[gdal] 03/12: Imported Upstream version 2.2.0~beta1+dfsg

Bas Couwenberg sebastic at debian.org
Fri Apr 14 15:12:28 UTC 2017


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch experimental-2.2
in repository gdal.

commit 91475de60a39245e1018b23c30e4b45eb86e4d76
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Apr 14 11:11:34 2017 +0200

    Imported Upstream version 2.2.0~beta1+dfsg
---
 Doxyfile                                           |   912 +-
 DoxygenLayout.xml                                  |   204 +
 GDALmake.opt.in                                    |    63 +-
 GNUmakefile                                        |    20 +-
 HOWTO-RELEASE                                      |    73 +-
 MIGRATION_GUIDE.TXT                                |    40 +-
 NEWS                                               |  1863 +--
 PROVENANCE.TXT                                     |   165 +-
 VERSION                                            |     2 +-
 Vagrantfile                                        |    57 +-
 aclocal.m4                                         |     7 +-
 alg/GNUmakefile                                    |    22 +-
 alg/contour.cpp                                    |   576 +-
 alg/delaunay.c                                     |    32 +-
 alg/gdal_alg.h                                     |    71 +-
 alg/gdal_alg_priv.h                                |    62 +-
 alg/gdal_crs.c                                     |    19 +-
 alg/gdal_nrgcrs.c                                  |    40 +-
 alg/gdal_octave.cpp                                |   254 +-
 alg/gdal_rpc.cpp                                   |  1303 +-
 alg/gdal_simplesurf.cpp                            |   367 +-
 alg/gdal_simplesurf.h                              |    26 +-
 alg/gdal_tps.cpp                                   |   145 +-
 alg/gdalapplyverticalshiftgrid.cpp                 |   744 ++
 alg/gdalchecksum.cpp                               |    90 +-
 alg/gdalcutline.cpp                                |   253 +-
 alg/gdaldither.cpp                                 |   461 +-
 alg/gdalgeoloc.cpp                                 |   881 +-
 alg/gdalgrid.cpp                                   |  1910 ++-
 alg/gdalgrid.h                                     |     5 +-
 alg/gdalgrid_priv.h                                |    38 +-
 alg/gdalgridavx.cpp                                |     3 +-
 alg/gdalgridsse.cpp                                |     4 +-
 alg/gdalmatching.cpp                               |   112 +-
 alg/gdalmediancut.cpp                              |  1014 +-
 alg/gdalpansharpen.cpp                             |   859 +-
 alg/gdalpansharpen.h                               |    12 +-
 alg/gdalproximity.cpp                              |   215 +-
 alg/gdalrasterize.cpp                              |   588 +-
 alg/gdalrasterpolygonenumerator.cpp                |    34 +-
 alg/gdalsievefilter.cpp                            |   164 +-
 alg/gdalsimplewarp.cpp                             |   341 +-
 alg/gdaltransformer.cpp                            |  1954 +--
 alg/gdaltransformgeolocs.cpp                       |    52 +-
 alg/gdalwarper.cpp                                 |  1025 +-
 alg/gdalwarper.h                                   |   124 +-
 alg/gdalwarpkernel.cpp                             |  3926 +++---
 alg/gdalwarpkernel_opencl.c                        |  2574 ----
 alg/gdalwarpkernel_opencl.cpp                      |  2689 ++++
 alg/gdalwarpkernel_opencl.h                        |     4 +-
 alg/gdalwarpoperation.cpp                          |  1141 +-
 alg/gvgcpfit.h                                     |    12 +-
 alg/{libqhull => internal_libqhull}/COPYING.txt    |     0
 alg/{libqhull => internal_libqhull}/README.txt     |     0
 alg/{libqhull => internal_libqhull}/geom.c         |     0
 alg/{libqhull => internal_libqhull}/geom.h         |     0
 alg/internal_libqhull/geom2.c                      |  2084 ++++
 alg/internal_libqhull/global.c                     |  2126 ++++
 alg/internal_libqhull/io.c                         |  4060 +++++++
 alg/{libqhull => internal_libqhull}/io.h           |     0
 alg/{libqhull => internal_libqhull}/libqhull.c     |     0
 alg/{libqhull => internal_libqhull}/libqhull.h     |     0
 alg/{libqhull => internal_libqhull}/mem.c          |     0
 alg/{libqhull => internal_libqhull}/mem.h          |     0
 alg/{libqhull => internal_libqhull}/merge.c        |     0
 alg/{libqhull => internal_libqhull}/merge.h        |     0
 alg/internal_libqhull/poly.c                       |  1202 ++
 alg/{libqhull => internal_libqhull}/poly.h         |     0
 alg/internal_libqhull/poly2.c                      |  3157 +++++
 alg/{libqhull => internal_libqhull}/qhull_a.h      |     0
 alg/{libqhull => internal_libqhull}/qset.c         |     0
 alg/{libqhull => internal_libqhull}/qset.h         |     0
 alg/{libqhull => internal_libqhull}/random.c       |     0
 alg/{libqhull => internal_libqhull}/random.h       |     0
 alg/internal_libqhull/rboxlib.c                    |   793 ++
 alg/{libqhull => internal_libqhull}/stat.c         |     0
 alg/{libqhull => internal_libqhull}/stat.h         |     0
 alg/{libqhull => internal_libqhull}/user.c         |     0
 alg/{libqhull => internal_libqhull}/user.h         |     0
 alg/{libqhull => internal_libqhull}/usermem.c      |     0
 alg/{libqhull => internal_libqhull}/userprintf.c   |     0
 .../userprintf_rbox.c                              |     0
 alg/internal_qhull_headers.h                       |    31 +-
 alg/libqhull/geom2.c                               |  2083 ----
 alg/libqhull/global.c                              |  2126 ----
 alg/libqhull/io.c                                  |  4060 -------
 alg/libqhull/poly.c                                |  1202 --
 alg/libqhull/poly2.c                               |  3156 -----
 alg/libqhull/rboxlib.c                             |   793 --
 alg/llrasterize.cpp                                |   391 +-
 alg/makefile.vc                                    |    11 +-
 alg/polygonize.cpp                                 |   382 +-
 alg/rasterfill.cpp                                 |   368 +-
 alg/thinplatespline.cpp                            |   706 +-
 alg/thinplatespline.h                              |    80 +-
 apps/GNUmakefile                                   |    10 +-
 apps/commonutils.cpp                               |   277 +-
 apps/commonutils.h                                 |     6 +-
 apps/dumpoverviews.cpp                             |    85 +-
 apps/gdal2ogr.c                                    |     3 +-
 apps/gdal_contour.cpp                              |    38 +-
 apps/gdal_grid_bin.cpp                             |     3 +-
 apps/gdal_grid_lib.cpp                             |    39 +-
 apps/gdal_rasterize_bin.cpp                        |    93 +-
 apps/gdal_rasterize_lib.cpp                        |   112 +-
 apps/gdal_translate_bin.cpp                        |    46 +-
 apps/gdal_translate_lib.cpp                        |   180 +-
 apps/gdal_utilities.dox                            |   622 +-
 apps/gdal_utils.h                                  |    13 +-
 apps/gdal_utils_priv.h                             |     6 +-
 apps/gdaladdo.cpp                                  |     6 +-
 apps/gdalasyncread.cpp                             |    30 +-
 apps/gdalbuildvrt_bin.cpp                          |     4 +-
 apps/gdalbuildvrt_lib.cpp                          |    99 +-
 apps/gdaldem_bin.cpp                               |    51 +-
 apps/gdaldem_lib.cpp                               |  3120 +++--
 apps/gdalenhance.cpp                               |    23 +-
 apps/gdalflattenmask.c                             |     8 +-
 apps/gdalinfo_bin.cpp                              |     6 +-
 apps/gdalinfo_lib.cpp                              |   847 +-
 apps/gdallocationinfo.cpp                          |     8 +-
 apps/gdalmanage.cpp                                |     3 +-
 apps/gdalserver.c                                  |     9 +-
 apps/gdalsrsinfo.cpp                               |    10 +-
 apps/gdaltindex.c                                  |   654 -
 apps/gdaltindex.cpp                                |   705 ++
 apps/gdaltorture.cpp                               |     4 +-
 apps/gdaltransform.cpp                             |     6 +-
 apps/gdalwarp_bin.cpp                              |    69 +-
 apps/gdalwarp_lib.cpp                              |   797 +-
 apps/gdalwarpsimple.c                              |    11 +-
 apps/gnm_utilities.dox                             |     6 +-
 apps/gnmanalyse.cpp                                |     9 +-
 apps/gnmmanage.cpp                                 |    35 +-
 apps/makefile.vc                                   |   134 +-
 apps/multireadtest.cpp                             |     8 +-
 apps/nearblack_bin.cpp                             |     5 +-
 apps/nearblack_lib.cpp                             |    31 +-
 apps/ogr2ogr_bin.cpp                               |    64 +-
 apps/ogr2ogr_lib.cpp                               |  1235 +-
 apps/ogr_utilities.dox                             |   195 +-
 apps/ogrdissolve.cpp                               |    43 +-
 apps/ogrinfo.cpp                                   |    99 +-
 apps/ogrlineref.cpp                                |    19 +-
 apps/ogrtindex.cpp                                 |   610 +-
 apps/test_ogrsf.cpp                                |   258 +-
 apps/testepsg.cpp                                  |    33 +-
 apps/testreprojmulti.cpp                           |     3 +-
 bridge/Makefile                                    |    11 -
 bridge/bridge_test.cpp                             |   373 -
 bridge/gbgetsymbol.cpp                             |   126 -
 bridge/gdalbridge.cpp                              |   520 -
 bridge/gdalbridge.h                                |   721 --
 ci/travis/android/before_install.sh                |     7 +
 ci/travis/android/install.sh                       |    13 +
 ci/travis/android/script.sh                        |     5 +
 ci/travis/big_endian/before_install.sh             |     6 +
 ci/travis/big_endian/install.sh                    |    14 +
 ci/travis/big_endian/script.sh                     |     5 +
 ci/travis/gcc48_stdcpp11/before_install.sh         |    66 +
 ci/travis/gcc48_stdcpp11/install.sh                |    32 +
 ci/travis/gcc48_stdcpp11/script.sh                 |    50 +
 .../gcc52_stdcpp14_sanitize/before_install.sh      |    62 +
 ci/travis/gcc52_stdcpp14_sanitize/install.sh       |    46 +
 ci/travis/gcc52_stdcpp14_sanitize/script.sh        |    55 +
 ci/travis/mingw/before_install.sh                  |     8 +
 ci/travis/mingw/install.sh                         |    34 +
 ci/travis/mingw/script.sh                          |    16 +
 ci/travis/mingw_w64/before_install.sh              |    14 +
 ci/travis/mingw_w64/install.sh                     |    36 +
 ci/travis/mingw_w64/script.sh                      |    17 +
 ci/travis/osx/before_install.sh                    |     8 +
 ci/travis/osx/install.sh                           |    43 +
 ci/travis/osx/script.sh                            |    13 +
 ci/travis/precise_32bit/before_install.sh          |    26 +
 ci/travis/precise_32bit/install.sh                 |    14 +
 ci/travis/precise_32bit/script.sh                  |    12 +
 ci/travis/precise_clang/before_install.sh          |    60 +
 ci/travis/precise_clang/install.sh                 |    39 +
 ci/travis/precise_clang/script.sh                  |    58 +
 ci/travis/python3/before_install.sh                |    54 +
 ci/travis/python3/install.sh                       |    32 +
 ci/travis/python3/script.sh                        |    49 +
 ci/travis/trusty_clang/before_install.sh           |    65 +
 ci/travis/trusty_clang/install.sh                  |    41 +
 ci/travis/trusty_clang/script.sh                   |    47 +
 ci/travis/ubuntu_1604/before_install.sh            |    42 +
 ci/travis/ubuntu_1604/install.sh                   |    23 +
 ci/travis/ubuntu_1604/script.sh                    |    17 +
 configure                                          |  2961 ++++-
 configure.ac                                       |  5510 +++++++++
 configure.in                                       |  5156 --------
 data/compdcs.csv                                   |     3 +
 data/coordinate_axis.csv                           |    12 +
 data/datum_shift.csv                               |  1312 +-
 data/default.rsc                                   |   Bin 0 -> 463632 bytes
 data/ellipsoid.csv                                 |     3 +-
 data/gcs.csv                                       |    22 +-
 data/gdal_datum.csv                                |  1029 +-
 data/gdalvrt.xsd                                   |    10 +-
 data/geoccs.csv                                    |    19 +-
 data/gml_registry.xml                              |    59 +
 data/gmlasconf.xml                                 |   169 +
 data/gmlasconf.xsd                                 |  1041 ++
 data/jpfgdgml_AdmArea.gfs                          |    59 +
 data/jpfgdgml_AdmBdry.gfs                          |    49 +
 data/jpfgdgml_AdmPt.gfs                            |    59 +
 data/jpfgdgml_BldA.gfs                             |    54 +
 data/jpfgdgml_BldL.gfs                             |    54 +
 data/jpfgdgml_Cntr.gfs                             |    54 +
 data/jpfgdgml_CommBdry.gfs                         |    49 +
 data/jpfgdgml_CommPt.gfs                           |    59 +
 data/jpfgdgml_Cstline.gfs                          |    54 +
 data/jpfgdgml_ElevPt.gfs                           |    54 +
 data/jpfgdgml_GCP.gfs                              |    94 +
 data/jpfgdgml_LeveeEdge.gfs                        |    49 +
 data/jpfgdgml_RailCL.gfs                           |    54 +
 data/jpfgdgml_RdASL.gfs                            |    44 +
 data/jpfgdgml_RdArea.gfs                           |    54 +
 data/jpfgdgml_RdCompt.gfs                          |    59 +
 data/jpfgdgml_RdEdg.gfs                            |    59 +
 data/jpfgdgml_RdMgtBdry.gfs                        |    49 +
 data/jpfgdgml_RdSgmtA.gfs                          |    59 +
 data/jpfgdgml_RvrMgtBdry.gfs                       |    49 +
 data/jpfgdgml_SBAPt.gfs                            |    49 +
 data/jpfgdgml_SBArea.gfs                           |    54 +
 data/jpfgdgml_SBBdry.gfs                           |    44 +
 data/jpfgdgml_WA.gfs                               |    54 +
 data/jpfgdgml_WL.gfs                               |    54 +
 data/jpfgdgml_WStrA.gfs                            |    54 +
 data/jpfgdgml_WStrL.gfs                            |    54 +
 data/nitf_spec.xml                                 |   100 +-
 data/ogrvrt.xsd                                    |    16 +-
 data/osmconf.ini                                   |     4 +-
 data/pcs.csv                                       |  9495 ++++++++-------
 data/pcs.override.csv                              |     8 +-
 data/plscenesconf.json                             |   296 +
 data/prime_meridian.csv                            |     2 +-
 data/projop_wparm.csv                              |    50 +-
 data/s57attributes.csv                             |   296 +-
 data/s57attributes_aml.csv                         |   440 -
 data/s57attributes_iw.csv                          |   236 -
 data/s57objectclasses.csv                          |   115 +-
 data/s57objectclasses_aml.csv                      |   305 -
 data/s57objectclasses_iw.csv                       |   217 -
 data/unit_of_measure.csv                           |     9 +-
 data/vertcs.csv                                    |    12 +-
 doc/api.dox                                        |    32 +-
 doc/br/Doxyfile                                    |  2274 ++--
 doc/br/gdal_building_br.dox                        |    18 +-
 doc/br/gdal_datamodel_br.dox                       |   620 +-
 doc/br/gdal_tutorial_br.dox                        |  1234 +-
 doc/br/index_br.dox                                |   304 +-
 doc/credits.dox                                    |    68 +-
 doc/download.dox                                   |     4 +-
 doc/examples.dox                                   |    13 +-
 doc/gdal_datamodel.dox                             |   188 +-
 doc/gdal_drivertut.dox                             |   781 +-
 doc/gdal_tutorial.dox                              |   142 +-
 doc/grid_tutorial.dox                              |    16 +-
 doc/images/OSGeo_project.png                       |   Bin 0 -> 2916 bytes
 doc/images/foss4g2017.png                          |   Bin 0 -> 16177 bytes
 doc/index.dox                                      |    82 +-
 doc/ru/Doxyfile                                    |  2274 ++--
 doc/ru/gdal_datamodel_ru.dox                       |   108 +-
 doc/ru/gdal_tutorial_ru.dox                        |    88 +-
 doc/ru/index_ru.dox                                |    10 +-
 doc/sponsorship.dox                                |    52 +-
 doc/vb6_tutorial.dox                               |   528 -
 doc/warptut.dox                                    |   152 +-
 frmts/aaigrid/aaigriddataset.cpp                   |   932 +-
 frmts/aaigrid/aaigriddataset.h                     |   169 +
 frmts/adrg/adrgdataset.cpp                         |   649 +-
 frmts/adrg/srpdataset.cpp                          |   359 +-
 frmts/aigrid/aigccitt.c                            |    30 +-
 frmts/aigrid/aigdataset.cpp                        |    66 +-
 frmts/aigrid/aigopen.c                             |     4 +-
 frmts/aigrid/aigrid.h                              |     2 +-
 frmts/aigrid/aigrid_format.html                    |     4 +-
 frmts/aigrid/aitest.c                              |     8 +-
 frmts/aigrid/gridlib.c                             |    10 +-
 frmts/airsar/airsardataset.cpp                     |    15 +-
 frmts/arg/GNUmakefile                              |     2 +-
 frmts/arg/argdataset.cpp                           |    57 +-
 frmts/blx/blx.c                                    |    42 +-
 frmts/blx/blxdataset.cpp                           |    49 +-
 frmts/bmp/bmpdataset.cpp                           |   108 +-
 frmts/bmp/frmt_bmp.html                            |     3 +-
 frmts/bpg/bpgdataset.cpp                           |    37 +-
 frmts/bsb/GNUmakefile                              |     2 +-
 frmts/bsb/README.dist                              |     6 +-
 frmts/bsb/bsb2raw.c                                |     4 +-
 frmts/bsb/bsb_read.c                               |     4 +-
 frmts/bsb/bsb_read.h                               |     9 +-
 frmts/bsb/bsbdataset.cpp                           |   133 +-
 frmts/cals/calsdataset.cpp                         |   215 +-
 frmts/ceos/ceosdataset.cpp                         |    34 +-
 frmts/ceos/ceosopen.c                              |     6 +-
 frmts/ceos/ceosopen.h                              |    43 +-
 frmts/ceos/ceostest.c                              |     2 +-
 frmts/ceos2/ceos.c                                 |    24 +-
 frmts/ceos2/ceos.h                                 |    19 +-
 frmts/ceos2/ceosrecipe.c                           |    10 +-
 frmts/ceos2/ceossar.c                              |     6 +-
 frmts/ceos2/link.c                                 |     4 +-
 frmts/ceos2/sar_ceosdataset.cpp                    |    99 +-
 frmts/coasp/GNUmakefile                            |     2 +-
 frmts/coasp/coasp_dataset.cpp                      |   489 +-
 frmts/cosar/cosar_dataset.cpp                      |    27 +-
 frmts/ctg/ctgdataset.cpp                           |    25 +-
 frmts/dds/ddsdataset.cpp                           |    17 +-
 frmts/derived/GNUmakefile                          |    11 +
 frmts/derived/deriveddataset.cpp                   |   223 +
 frmts/derived/derivedlist.c                        |    52 +
 frmts/derived/derivedlist.h                        |    48 +
 frmts/derived/frmt_derived.html                    |   236 +
 frmts/derived/makefile.vc                          |    13 +
 frmts/dimap/GNUmakefile                            |     4 +-
 frmts/dimap/dimapdataset.cpp                       |   931 +-
 frmts/dimap/makefile.vc                            |     2 +
 frmts/dods/GNUmakefile                             |     4 +-
 frmts/dods/dodsdataset2.cpp                        |   245 +-
 frmts/dods/libdap_headers.h                        |    67 +
 frmts/dted/dted_api.c                              |     5 +-
 frmts/dted/dted_api.h                              |     2 +-
 frmts/dted/dted_create.c                           |   151 +-
 frmts/dted/dted_ptstream.c                         |     8 +-
 frmts/dted/dted_test.c                             |     2 +-
 frmts/dted/dteddataset.cpp                         |    83 +-
 frmts/e00grid/e00compr.h                           |     5 +-
 frmts/e00grid/e00griddataset.cpp                   |    32 +-
 frmts/e00grid/e00read.c                            |     2 +-
 frmts/ecw/ecwasyncreader.cpp                       |   890 +-
 frmts/ecw/ecwcreatecopy.cpp                        |    89 +-
 frmts/ecw/ecwdataset.cpp                           |    95 +-
 frmts/ecw/ecwsdk_headers.h                         |     1 -
 frmts/ecw/frmt_ecw.html                            |    17 +-
 frmts/ecw/frmt_jp2ecw.html                         |    26 +
 frmts/ecw/gdal_ecw.h                               |    88 +-
 frmts/ecw/jp2userbox.cpp                           |     6 +-
 frmts/ecw/lookup.py                                |    14 +-
 frmts/elas/elasdataset.cpp                         |   118 +-
 frmts/envisat/EnvisatFile.c                        |    12 +-
 frmts/envisat/EnvisatFile.h                        |     2 +-
 frmts/envisat/adsrange.cpp                         |    11 +-
 frmts/envisat/adsrange.hpp                         |   116 +-
 frmts/envisat/dumpgeo.c                            |     2 +-
 frmts/envisat/envisat_dump.c                       |     2 +-
 frmts/envisat/envisatdataset.cpp                   |    92 +-
 frmts/envisat/records.c                            |     6 +-
 frmts/envisat/records.h                            |     4 +-
 frmts/envisat/timedelta.hpp                        |   154 +-
 frmts/envisat/unwrapgcps.cpp                       |    27 +-
 frmts/epsilon/epsilondataset.cpp                   |    87 +-
 frmts/ers/ersdataset.cpp                           |   121 +-
 frmts/ers/ershdrnode.cpp                           |     6 +-
 frmts/ers/ershdrnode.h                             |     2 +-
 frmts/fit/fit.cpp                                  |    12 +-
 frmts/fit/fit.h                                    |    75 +-
 frmts/fit/fitdataset.cpp                           |   164 +-
 frmts/fit/gstEndian.h                              |    38 +-
 frmts/fit/gstTypes.h                               |    14 +-
 frmts/fits/GNUmakefile                             |     2 +-
 frmts/fits/fitsdataset.cpp                         |   241 +-
 frmts/formats_list.html                            |    58 +-
 frmts/frmt_various.html                            |    52 +-
 frmts/gdalallregister.cpp                          |    26 +-
 frmts/georaster/frmt_georaster.html                |     2 +-
 frmts/georaster/georaster_dataset.cpp              |    48 +-
 frmts/georaster/georaster_priv.h                   |    92 +-
 frmts/georaster/georaster_rasterband.cpp           |     3 +-
 frmts/georaster/georaster_wrapper.cpp              |    74 +-
 frmts/georaster/makefile.vc                        |    11 +-
 frmts/georaster/oci_wrapper.cpp                    |    21 +-
 frmts/georaster/oci_wrapper.h                      |     3 +-
 frmts/gff/gff_dataset.cpp                          |    65 +-
 frmts/gif/biggifdataset.cpp                        |    21 +-
 frmts/gif/gifabstractdataset.cpp                   |    34 +-
 frmts/gif/gifabstractdataset.h                     |    27 +-
 frmts/gif/gifdataset.cpp                           |   316 +-
 frmts/gif/giflib/dgif_lib.c                        |     8 +-
 frmts/gif/giflib/egif_lib.c                        |     9 +-
 frmts/gif/giflib/gif_hash.h                        |    30 +-
 frmts/gif/giflib/gifalloc.c                        |     3 +-
 frmts/grass/grass57dataset.cpp                     |   462 +-
 frmts/grass/grassdataset.cpp                       |    64 +-
 frmts/grass/pkg/README                             |    18 +-
 frmts/grass/pkg/aclocal.m4                         |    16 +-
 frmts/grass/pkg/configure.in                       |     2 +-
 frmts/grib/GNUmakefile                             |    13 +-
 frmts/grib/degrib18/degrib/clock.c                 |    32 +-
 frmts/grib/degrib18/degrib/clock.h                 |     5 +-
 frmts/grib/degrib18/degrib/datasource.h            |    12 +-
 frmts/grib/degrib18/degrib/degrib1.cpp             |    29 +-
 frmts/grib/degrib18/degrib/degrib1.h               |     1 -
 frmts/grib/degrib18/degrib/degrib2.cpp             |    14 +-
 frmts/grib/degrib18/degrib/engribapi.c             |     8 +-
 frmts/grib/degrib18/degrib/engribapi.h             |     1 -
 frmts/grib/degrib18/degrib/filedatasource.cpp      |     2 +-
 frmts/grib/degrib18/degrib/filedatasource.h        |    22 +-
 frmts/grib/degrib18/degrib/grib2api.c              |    20 +-
 frmts/grib/degrib18/degrib/inventory.cpp           |   105 +-
 frmts/grib/degrib18/degrib/inventory.h             |     3 +-
 frmts/grib/degrib18/degrib/memorydatasource.cpp    |     4 +-
 frmts/grib/degrib18/degrib/memorydatasource.h      |    29 +-
 frmts/grib/degrib18/degrib/meta.h                  |    75 +-
 frmts/grib/degrib18/degrib/metaname.cpp            |  1663 ++-
 frmts/grib/degrib18/degrib/metaname.h              |     8 +-
 frmts/grib/degrib18/degrib/metaparse.cpp           |   159 +-
 frmts/grib/degrib18/degrib/metaprint.cpp           |     8 +-
 frmts/grib/degrib18/degrib/myassert.h              |     1 -
 frmts/grib/degrib18/degrib/myerror.c               |     2 +-
 frmts/grib/degrib18/degrib/myutil.c                |    71 +-
 frmts/grib/degrib18/degrib/myutil.h                |     8 +-
 frmts/grib/degrib18/degrib/scan.c                  |     2 +-
 frmts/grib/degrib18/degrib/tdlpack.cpp             |    36 +-
 frmts/grib/degrib18/degrib/tdlpack.h               |     1 -
 frmts/grib/degrib18/degrib/type.h                  |     7 +-
 frmts/grib/degrib18/degrib/weather.c               |     8 +-
 frmts/grib/degrib18/g2clib-1.0.4/README            |    20 +-
 frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c       |     6 +-
 frmts/grib/degrib18/g2clib-1.0.4/compack.c         |    42 +-
 frmts/grib/degrib18/g2clib-1.0.4/comunpack.c       |    41 +-
 frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp  |   125 +-
 frmts/grib/degrib18/g2clib-1.0.4/dec_png.c         |    52 +-
 frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c    |    30 +-
 frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h    |    14 +-
 frmts/grib/degrib18/g2clib-1.0.4/enc_jpeg2000.c    |    20 +-
 frmts/grib/degrib18/g2clib-1.0.4/enc_png.c         |    11 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c     |    32 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c      |    26 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c     |    20 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_create.c       |    18 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_free.c         |     6 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c       |    56 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c      |    18 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_info.c         |    26 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c         |    16 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack1.c      |    12 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack2.c      |     8 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c      |    24 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c      |    16 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack5.c      |    10 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack6.c      |    12 +-
 frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c      |    12 +-
 frmts/grib/degrib18/g2clib-1.0.4/gbits.c           |     2 +-
 frmts/grib/degrib18/g2clib-1.0.4/getdim.c          |     8 +-
 frmts/grib/degrib18/g2clib-1.0.4/getpoly.c         |     8 +-
 frmts/grib/degrib18/g2clib-1.0.4/grib2.h           |    21 +-
 frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc        |   136 +-
 frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c   |    18 +-
 frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h   |    15 +-
 frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c         |    24 +-
 frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c       |     8 +-
 frmts/grib/degrib18/g2clib-1.0.4/makefile.vc       |     4 -
 frmts/grib/degrib18/g2clib-1.0.4/misspack.c        |    40 +-
 frmts/grib/degrib18/g2clib-1.0.4/mkieee.c          |    16 +-
 frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c         |    30 +-
 frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c    |    23 +-
 frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h    |    18 +-
 frmts/grib/degrib18/g2clib-1.0.4/pngpack.c         |    26 +-
 frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c       |    34 +-
 frmts/grib/degrib18/g2clib-1.0.4/rdieee.c          |    16 +-
 frmts/grib/degrib18/g2clib-1.0.4/reduce.c          |     9 +-
 frmts/grib/degrib18/g2clib-1.0.4/seekgb.c          |     2 +-
 frmts/grib/degrib18/g2clib-1.0.4/simpack.c         |    36 +-
 frmts/grib/degrib18/g2clib-1.0.4/simunpack.c       |     6 +-
 frmts/grib/degrib18/g2clib-1.0.4/specpack.c        |    10 +-
 frmts/grib/degrib18/g2clib-1.0.4/specunpack.c      |    16 +-
 frmts/grib/gribdataset.cpp                         |   670 +-
 frmts/grib/gribdataset.h                           |   184 +
 frmts/grib/makefile.vc                             |     7 +-
 frmts/gsg/gs7bgdataset.cpp                         |    31 +-
 frmts/gsg/gsagdataset.cpp                          |  1404 ++-
 frmts/gsg/gsbgdataset.cpp                          |   741 +-
 frmts/gta/gtadataset.cpp                           |    76 +-
 frmts/gtiff/GNUmakefile                            |     6 +-
 frmts/gtiff/frmt_gtiff.html                        |   120 +-
 frmts/gtiff/geotiff.cpp                            | 12152 +++++++++++--------
 frmts/gtiff/gt_citation.cpp                        |   530 +-
 frmts/gtiff/gt_citation.h                          |    38 +-
 frmts/gtiff/gt_jpeg_copy.cpp                       |   551 +-
 frmts/gtiff/gt_jpeg_copy.h                         |    24 +-
 frmts/gtiff/gt_overview.cpp                        |   509 +-
 frmts/gtiff/gt_overview.h                          |    30 +-
 frmts/gtiff/gt_wkt_srs.cpp                         |   692 +-
 frmts/gtiff/gt_wkt_srs.h                           |     6 +-
 frmts/gtiff/gtiff.h                                |    21 +-
 frmts/gtiff/libgeotiff/epsg_datum.inc              |     2 +-
 frmts/gtiff/libgeotiff/epsg_units.inc              |     2 +-
 frmts/gtiff/libgeotiff/geo_ctrans.inc              |     6 +-
 frmts/gtiff/libgeotiff/geo_extra.c                 |     2 +-
 frmts/gtiff/libgeotiff/geo_get.c                   |     4 +-
 frmts/gtiff/libgeotiff/geo_new.c                   |     2 +-
 frmts/gtiff/libgeotiff/geo_normalize.c             |     2 +-
 frmts/gtiff/libgeotiff/geo_print.c                 |    21 +-
 frmts/gtiff/libgeotiff/geo_set.c                   |    26 +-
 frmts/gtiff/libgeotiff/geo_simpletags.c            |     1 +
 frmts/gtiff/libgeotiff/geo_trans.c                 |     2 +-
 frmts/gtiff/libgeotiff/geokeys.inc                 |     2 +-
 frmts/gtiff/libgeotiff/geotiff.h                   |     2 +-
 frmts/gtiff/libgeotiff/geotiff_proj4.c             |     2 +-
 frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h   |     3 +
 frmts/gtiff/libtiff/makefile.vc                    |     8 +-
 frmts/gtiff/libtiff/tif_aux.c                      |    19 +-
 frmts/gtiff/libtiff/tif_color.c                    |     8 +-
 frmts/gtiff/libtiff/tif_compress.c                 |     4 +-
 frmts/gtiff/libtiff/tif_dir.c                      |    74 +-
 frmts/gtiff/libtiff/tif_dirinfo.c                  |     4 +-
 frmts/gtiff/libtiff/tif_dirread.c                  |    59 +-
 frmts/gtiff/libtiff/tif_dirwrite.c                 |   129 +-
 frmts/gtiff/libtiff/tif_fax3.c                     |   122 +-
 frmts/gtiff/libtiff/tif_fax3.h                     |     6 +-
 frmts/gtiff/libtiff/tif_getimage.c                 |   192 +-
 frmts/gtiff/libtiff/tif_jpeg.c                     |    29 +-
 frmts/gtiff/libtiff/tif_luv.c                      |    74 +-
 frmts/gtiff/libtiff/tif_lzma.c                     |     2 +-
 frmts/gtiff/libtiff/tif_lzw.c                      |    57 +-
 frmts/gtiff/libtiff/tif_next.c                     |     8 +-
 frmts/gtiff/libtiff/tif_ojpeg.c                    |    54 +-
 frmts/gtiff/libtiff/tif_open.c                     |     6 +-
 frmts/gtiff/libtiff/tif_packbits.c                 |    16 +-
 frmts/gtiff/libtiff/tif_pixarlog.c                 |    89 +-
 frmts/gtiff/libtiff/tif_predict.c                  |   185 +-
 frmts/gtiff/libtiff/tif_predict.h                  |     8 +-
 frmts/gtiff/libtiff/tif_print.c                    |    10 +-
 frmts/gtiff/libtiff/tif_read.c                     |    78 +-
 frmts/gtiff/libtiff/tif_strip.c                    |     2 +-
 frmts/gtiff/libtiff/tif_swab.c                     |     8 +-
 frmts/gtiff/libtiff/tif_thunder.c                  |     5 +-
 frmts/gtiff/libtiff/tif_vsi.c                      |    13 +-
 frmts/gtiff/libtiff/tif_write.c                    |    79 +-
 frmts/gtiff/libtiff/tif_zip.c                      |     2 +-
 frmts/gtiff/libtiff/tiffio.h                       |     5 +-
 frmts/gtiff/libtiff/tiffiop.h                      |     6 +-
 frmts/gtiff/libtiff/tiffvers.h                     |     4 +-
 frmts/gtiff/tif_float.c                            |     2 +-
 frmts/gtiff/tifvsi.cpp                             |   170 +-
 frmts/gtiff/tifvsi.h                               |    10 +-
 frmts/gxf/Doxyfile                                 |    60 +-
 frmts/gxf/GNUmakefile                              |     2 +-
 frmts/gxf/README                                   |    20 +-
 frmts/gxf/gxf.dox                                  |    24 +-
 frmts/gxf/gxf_ogcwkt.c                             |     6 +-
 frmts/gxf/gxf_proj4.c                              |     8 +-
 frmts/gxf/gxfdataset.cpp                           |   159 +-
 frmts/gxf/gxfopen.c                                |    10 +-
 frmts/gxf/gxfopen.h                                |    72 +-
 frmts/hdf4/hdf-eos/GDapi.c                         |     4 +-
 frmts/hdf4/hdf-eos/HDFEOSVersion.h                 |     6 +-
 frmts/hdf4/hdf-eos/SWapi.c                         |    29 +-
 frmts/hdf4/hdf-eos/makefile.vc                     |     2 +-
 frmts/hdf4/hdf4dataset.cpp                         |   255 +-
 frmts/hdf4/hdf4dataset.h                           |    37 +-
 frmts/hdf4/hdf4imagedataset.cpp                    |  1106 +-
 frmts/hdf4/makefile.vc                             |     4 +-
 frmts/hdf5/GNUmakefile                             |     2 +-
 frmts/hdf5/bagdataset.cpp                          |   659 +-
 frmts/hdf5/gh5_convenience.cpp                     |   193 +-
 frmts/hdf5/gh5_convenience.h                       |    12 +-
 frmts/hdf5/hdf5dataset.cpp                         |  1122 +-
 frmts/hdf5/hdf5dataset.h                           |    98 +-
 frmts/hdf5/hdf5imagedataset.cpp                    |   845 +-
 frmts/hdf5/iso19115_srs.cpp                        |   117 +-
 frmts/hdf5/iso19115_srs.h                          |    43 +
 frmts/hf2/hf2dataset.cpp                           |    75 +-
 frmts/hfa/GNUmakefile                              |    21 +-
 frmts/hfa/TODO_Projections.txt                     |     6 +-
 frmts/hfa/frmt_hfa.html                            |    10 +-
 frmts/hfa/hfa.h                                    |   127 +-
 frmts/hfa/hfa_overviews.cpp                        |    94 +-
 frmts/hfa/hfa_p.h                                  |   332 +-
 frmts/hfa/hfaband.cpp                              |  1674 ++-
 frmts/hfa/hfacompress.cpp                          |   434 +-
 frmts/hfa/hfadataset.cpp                           |  4724 ++++---
 frmts/hfa/hfadataset.h                             |   312 +
 frmts/hfa/hfadictionary.cpp                        |   121 +-
 frmts/hfa/hfaentry.cpp                             |   580 +-
 frmts/hfa/hfafield.cpp                             |  1251 +-
 frmts/hfa/hfaopen.cpp                              |  3424 +++---
 frmts/hfa/hfatest.cpp                              |    55 +-
 frmts/hfa/hfatype.cpp                              |   304 +-
 frmts/idrisi/GNUmakefile                           |     2 +-
 frmts/idrisi/IdrisiDataset.cpp                     |   566 +-
 frmts/idrisi/rdc.txt                               |    10 +-
 frmts/idrisi/rst.txt                               |    16 +-
 frmts/ilwis/ilwiscoordinatesystem.cpp              |   511 +-
 frmts/ilwis/ilwisdataset.cpp                       |   488 +-
 frmts/ilwis/ilwisdataset.h                         |    72 +-
 frmts/ingr/IngrTypes.cpp                           |    23 +-
 frmts/ingr/IngrTypes.h                             |    25 +-
 frmts/ingr/IntergraphBand.cpp                      |   172 +-
 frmts/ingr/IntergraphBand.h                        |    58 +-
 frmts/ingr/IntergraphDataset.cpp                   |    19 +-
 frmts/ingr/IntergraphDataset.h                     |    10 +-
 frmts/ingr/JpegHelper.cpp                          |     3 +-
 frmts/ingr/JpegHelper.h                            |     2 +-
 frmts/iris/irisdataset.cpp                         |   981 +-
 frmts/iso8211/8211createfromxml.cpp                |   209 +-
 frmts/iso8211/8211dump.cpp                         |    21 +-
 frmts/iso8211/8211view.cpp                         |    41 +-
 frmts/iso8211/Doxyfile                             |    60 +-
 frmts/iso8211/ddffield.cpp                         |    59 +-
 frmts/iso8211/ddffielddefn.cpp                     |   171 +-
 frmts/iso8211/ddfmodule.cpp                        |    71 +-
 frmts/iso8211/ddfrecord.cpp                        |   262 +-
 frmts/iso8211/ddfsubfielddefn.cpp                  |   123 +-
 frmts/iso8211/ddfutils.cpp                         |    29 +-
 frmts/iso8211/intro.dox                            |    68 +-
 frmts/iso8211/iso8211.h                            |    16 +-
 frmts/iso8211/makefile.vc                          |    14 +-
 frmts/iso8211/mkcatalog.cpp                        |    34 +-
 frmts/iso8211/timetest.cpp                         |    45 +-
 frmts/jaxapalsar/jaxapalsardataset.cpp             |   128 +-
 frmts/jdem/jdemdataset.cpp                         |   218 +-
 frmts/jp2kak/GNUmakefile                           |     2 +-
 frmts/jp2kak/frmt_jp2kak.html                      |    57 +-
 frmts/jp2kak/jp2kak_headers.h                      |     4 +-
 frmts/jp2kak/jp2kakdataset.cpp                     |  1974 ++-
 frmts/jp2kak/jp2kakdataset.h                       |   226 +
 frmts/jp2kak/subfile_source.h                      |    75 +-
 frmts/jp2kak/vsil_target.h                         |    15 +-
 frmts/jp2lura/GNUmakefile                          |    22 +
 frmts/jp2lura/frmt_jp2lura.html                    |   291 +
 frmts/jp2lura/jp2luracallbacks.cpp                 |   502 +
 frmts/jp2lura/jp2luracallbacks.h                   |   127 +
 frmts/jp2lura/jp2luradataset.cpp                   |  2689 ++++
 frmts/jp2lura/jp2luradataset.h                     |    92 +
 frmts/jp2lura/jp2lurarasterband.cpp                |   420 +
 frmts/jp2lura/jp2lurarasterband.h                  |    64 +
 frmts/jp2lura/makefile.vc                          |    32 +
 frmts/jpeg/GNUmakefile                             |     4 +-
 frmts/jpeg/jpgdataset.cpp                          |  2311 ++--
 frmts/jpeg/jpgdataset.h                            |   379 +
 frmts/jpeg/libjpeg/jcmarker.c                      |     3 +
 frmts/jpeg/libjpeg/jcmaster.c                      |     1 +
 frmts/jpeg/libjpeg/jdcoefct.c                      |     4 +-
 frmts/jpeg/libjpeg/jdphuff.c                       |     6 +-
 frmts/jpeg/libjpeg/jmemmgr.c                       |     1 +
 frmts/jpeg/vsidataio.cpp                           |   593 +-
 frmts/jpeg2000/frmt_jpeg2000.html                  |    26 +
 frmts/jpeg2000/jpeg2000_vsil_io.cpp                |   580 +-
 frmts/jpeg2000/jpeg2000_vsil_io.h                  |    74 +-
 frmts/jpeg2000/jpeg2000dataset.cpp                 |   161 +-
 frmts/jpegls/frmt_jpegls.html                      |     4 +-
 frmts/jpegls/jpegls_header.h                       |    41 +
 frmts/jpegls/jpeglsdataset.cpp                     |   142 +-
 frmts/jpipkak/GNUmakefile                          |     4 +-
 frmts/jpipkak/jpipkakdataset.cpp                   |   103 +-
 frmts/jpipkak/jpipkakdataset.h                     |    40 +-
 frmts/kea/keaband.cpp                              |    13 +-
 frmts/kea/keaband.h                                |    45 +-
 frmts/kea/keacopy.cpp                              |    14 +-
 frmts/kea/keadataset.cpp                           |    16 +-
 frmts/kea/keadataset.h                             |    32 +-
 frmts/kea/keadriver.cpp                            |     3 +-
 frmts/kea/keamaskband.cpp                          |     3 +-
 frmts/kea/keamaskband.h                            |     7 +-
 frmts/kea/keaoverview.cpp                          |     8 +-
 frmts/kea/keaoverview.h                            |    10 +-
 frmts/kea/kearat.cpp                               |    46 +-
 frmts/kea/kearat.h                                 |    50 +-
 frmts/kea/libkea_headers.h                         |     1 -
 frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp   |   466 +-
 frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h     |    38 +-
 frmts/l1b/l1bdataset.cpp                           |   230 +-
 frmts/leveller/levellerdataset.cpp                 |  1228 +-
 frmts/makefile.vc                                  |    12 +-
 frmts/map/mapdataset.cpp                           |    44 +-
 frmts/mbtiles/GNUmakefile                          |     2 +-
 frmts/mbtiles/frmt_mbtiles.html                    |     2 +-
 frmts/mbtiles/makefile.vc                          |     8 +-
 frmts/mbtiles/mbtilesdataset.cpp                   |   189 +-
 frmts/mem/memdataset.cpp                           |   420 +-
 frmts/mem/memdataset.h                             |    88 +-
 frmts/mrf/GNUmakefile                              |    10 +-
 frmts/mrf/JPEG_band.cpp                            |    66 +-
 frmts/mrf/JPNG_band.cpp                            |    52 +-
 frmts/mrf/LERC_band.cpp                            |   416 +-
 frmts/mrf/PNG_band.cpp                             |    32 +-
 frmts/mrf/Raw_band.cpp                             |     3 +-
 frmts/mrf/Tif_band.cpp                             |    65 +-
 frmts/mrf/libLERC/BitMask.cpp                      |    81 +-
 frmts/mrf/libLERC/BitMask.h                        |    12 +-
 frmts/mrf/libLERC/BitMask2.h                       |     2 +-
 frmts/mrf/libLERC/BitStuffer.cpp                   |    12 +-
 frmts/mrf/libLERC/BitStuffer.h                     |    10 +-
 frmts/mrf/libLERC/BitStuffer2.cpp                  |     7 +-
 frmts/mrf/libLERC/BitStuffer2.h                    |    28 +-
 frmts/mrf/libLERC/CntZImage.cpp                    |    87 +-
 frmts/mrf/libLERC/CntZImage.h                      |    30 +-
 frmts/mrf/libLERC/Defines.h                        |     7 +-
 frmts/mrf/libLERC/Huffman.cpp                      |   104 +-
 frmts/mrf/libLERC/Huffman.h                        |    16 +-
 frmts/mrf/libLERC/Image.h                          |     7 +-
 frmts/mrf/libLERC/Lerc2.cpp                        |     8 +-
 frmts/mrf/libLERC/Lerc2.h                          |    40 +-
 frmts/mrf/libLERC/RLE.cpp                          |     9 +-
 frmts/mrf/libLERC/RLE.h                            |     8 +-
 frmts/mrf/libLERC/TImage.hpp                       |     6 +-
 frmts/mrf/makefile.vc                              |    14 +-
 frmts/mrf/marfa.h                                  |   134 +-
 frmts/mrf/marfa_dataset.cpp                        |  1640 +--
 frmts/mrf/mrf_band.cpp                             |   708 +-
 frmts/mrf/mrf_overview.cpp                         |   416 +-
 frmts/mrf/mrf_util.cpp                             |   319 +-
 frmts/mrsid/frmt_jp2mrsid.html                     |    24 +
 frmts/mrsid/mrsiddataset.cpp                       |   141 +-
 frmts/mrsid/mrsidstream.cpp                        |     3 +-
 frmts/mrsid_lidar/gdal_MG4Lidar.cpp                |    43 +-
 frmts/msg/GNUmakefile                              |    28 +-
 frmts/msg/PublicDecompWT_all.cpp                   |     1 +
 frmts/msg/PublicDecompWT_headers.h                 |     6 +
 frmts/msg/msgcommand.cpp                           |    47 +-
 frmts/msg/msgcommand.h                             |     8 +-
 frmts/msg/msgdataset.cpp                           |   157 +-
 frmts/msg/msgdataset.h                             |    20 +-
 frmts/msg/prologue.cpp                             |    28 +-
 frmts/msg/prologue.h                               |    15 +-
 frmts/msg/reflectancecalculator.cpp                |    35 +-
 frmts/msg/reflectancecalculator.h                  |    26 +-
 frmts/msg/xritheaderparser.cpp                     |    18 +-
 frmts/msg/xritheaderparser.h                       |    20 +-
 frmts/msgn/GNUmakefile                             |     2 +-
 frmts/msgn/msg_basic_types.cpp                     |    18 +-
 frmts/msgn/msg_basic_types.h                       |     4 +-
 frmts/msgn/msg_reader_core.cpp                     |    38 +-
 frmts/msgn/msg_reader_core.h                       |    50 +-
 frmts/msgn/msgndataset.cpp                         |    84 +-
 frmts/netcdf/GNUmakefile                           |     4 +-
 frmts/netcdf/gmtdataset.cpp                        |   101 +-
 frmts/netcdf/netcdfdataset.cpp                     | 10007 +++++++--------
 frmts/netcdf/netcdfdataset.h                       |   118 +-
 frmts/netcdf/netcdflayer.cpp                       |  2165 ++--
 frmts/netcdf/netcdfwriterconfig.cpp                |    86 +-
 frmts/ngsgeoid/ngsgeoiddataset.cpp                 |    23 +-
 frmts/nitf/ecrgtocdataset.cpp                      |   149 +-
 frmts/nitf/frmt_nitf.html                          |    24 +-
 frmts/nitf/mgrs.c                                  |    14 +-
 frmts/nitf/mgrs.h                                  |    20 +-
 frmts/nitf/nitf_gcprpc.cpp                         |    12 +-
 frmts/nitf/nitfaridpcm.cpp                         |    12 +-
 frmts/nitf/nitfbilevel.cpp                         |    13 +-
 frmts/nitf/nitfdataset.cpp                         |   310 +-
 frmts/nitf/nitfdataset.h                           |   117 +-
 frmts/nitf/nitfdes.c                               |     8 +-
 frmts/nitf/nitfdump.c                              |     8 +-
 frmts/nitf/nitffile.c                              |    36 +-
 frmts/nitf/nitfimage.c                             |   424 +-
 frmts/nitf/nitflib.h                               |    58 +-
 frmts/nitf/nitfrasterband.cpp                      |    71 +-
 frmts/nitf/nitfwritejpeg.cpp                       |     3 +-
 frmts/nitf/rpftocdataset.cpp                       |   166 +-
 frmts/nitf/rpftocfile.cpp                          |    18 +-
 frmts/nitf/rpftoclib.h                             |     2 +-
 frmts/northwood/frmt_nwtgrd.html                   |    49 +
 frmts/northwood/grcdataset.cpp                     |    45 +-
 frmts/northwood/grddataset.cpp                     |  1021 +-
 frmts/northwood/northwood.cpp                      |    84 +-
 frmts/northwood/northwood.h                        |    14 +-
 frmts/o/README.TXT                                 |     2 +-
 frmts/ogdi/ogdidataset.cpp                         |   183 +-
 frmts/openjpeg/frmt_jp2openjpeg.html               |    69 +-
 frmts/openjpeg/openjpegdataset.cpp                 |   289 +-
 frmts/ozi/makefile.vc                              |     6 +-
 frmts/ozi/ozidataset.cpp                           |    36 +-
 frmts/pcidsk/GNUmakefile                           |     2 +-
 frmts/pcidsk/gdal_edb.cpp                          |    27 +-
 frmts/pcidsk/notes.txt                             |    12 +-
 frmts/pcidsk/ogrpcidsklayer.cpp                    |    39 +-
 frmts/pcidsk/pcidskdataset2.cpp                    |    49 +-
 frmts/pcidsk/pcidskdataset2.h                      |    94 +-
 frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h |     8 +-
 frmts/pcidsk/sdk/channel/cexternalchannel.cpp      |     2 +-
 frmts/pcidsk/sdk/channel/cexternalchannel.h        |    12 +-
 frmts/pcidsk/sdk/channel/cpcidskchannel.h          |    50 +-
 .../pcidsk/sdk/channel/cpixelinterleavedchannel.h  |     4 +-
 frmts/pcidsk/sdk/channel/ctiledchannel.cpp         |    32 +-
 frmts/pcidsk/sdk/channel/ctiledchannel.h           |    16 +-
 frmts/pcidsk/sdk/core/clinksegment.h               |     2 +-
 frmts/pcidsk/sdk/core/cpcidskfile.cpp              |    59 +-
 frmts/pcidsk/sdk/core/cpcidskfile.h                |    48 +-
 frmts/pcidsk/sdk/core/edb_pcidsk.cpp               |    22 +-
 frmts/pcidsk/sdk/core/libjpeg_io.cpp               |    30 +-
 frmts/pcidsk/sdk/core/metadataset.h                |     2 +-
 frmts/pcidsk/sdk/core/metadataset_p.cpp            |     2 +-
 frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp          |     4 +-
 frmts/pcidsk/sdk/core/pcidsk_utils.cpp             |    18 +-
 frmts/pcidsk/sdk/core/pcidskcreate.cpp             |   514 +-
 frmts/pcidsk/sdk/core/pcidskexception.cpp          |    32 +-
 frmts/pcidsk/sdk/core/sysvirtualfile.cpp           |    26 +-
 frmts/pcidsk/sdk/core/sysvirtualfile.h             |     2 +-
 frmts/pcidsk/sdk/pcidsk_array.h                    |    14 +-
 frmts/pcidsk/sdk/pcidsk_buffer.h                   |     2 +-
 frmts/pcidsk/sdk/pcidsk_config.h                   |     8 +-
 frmts/pcidsk/sdk/pcidsk_edb.h                      |     4 +-
 frmts/pcidsk/sdk/pcidsk_exception.h                |     2 +-
 frmts/pcidsk/sdk/pcidsk_georef.h                   |     2 +-
 frmts/pcidsk/sdk/pcidsk_interfaces.h               |     2 +-
 frmts/pcidsk/sdk/pcidsk_pct.h                      |     6 +-
 frmts/pcidsk/sdk/pcidsk_segment.h                  |     2 +-
 frmts/pcidsk/sdk/pcidsk_shape.h                    |     6 +-
 frmts/pcidsk/sdk/pcidsk_tex.h                      |     2 +-
 frmts/pcidsk/sdk/pcidsk_vectorsegment.h            |     6 +-
 frmts/pcidsk/sdk/port/io_stdio.cpp                 |    16 +-
 frmts/pcidsk/sdk/port/io_win32.cpp                 |    21 +-
 frmts/pcidsk/sdk/port/pthread_mutex.cpp            |     4 +-
 frmts/pcidsk/sdk/port/win32_mutex.cpp              |     4 +-
 frmts/pcidsk/sdk/segment/cpcidsk_array.cpp         |     2 +-
 frmts/pcidsk/sdk/segment/cpcidsk_array.h           |    14 +-
 frmts/pcidsk/sdk/segment/cpcidsk_tex.h             |     4 +-
 frmts/pcidsk/sdk/segment/cpcidskads40model.h       |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp        |    13 +-
 frmts/pcidsk/sdk/segment/cpcidskapmodel.h          |    18 +-
 frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h    |     8 +-
 frmts/pcidsk/sdk/segment/cpcidskbitmap.h           |    64 +-
 .../pcidsk/sdk/segment/cpcidskephemerissegment.cpp |   220 +-
 frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp    |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h      |     8 +-
 frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp         |   144 +-
 frmts/pcidsk/sdk/segment/cpcidskgeoref.h           |    12 +-
 frmts/pcidsk/sdk/segment/cpcidskpct.h              |     4 +-
 frmts/pcidsk/sdk/segment/cpcidskpolymodel.h        |    26 +-
 frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h         |    48 +-
 frmts/pcidsk/sdk/segment/cpcidsksegment.h          |    38 +-
 frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp    |    60 +-
 frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h      |     6 +-
 frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp  |     2 +-
 frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h    |    48 +-
 .../cpcidskvectorsegment_consistencycheck.cpp      |    13 +-
 frmts/pcidsk/sdk/segment/metadatasegment.h         |     2 +-
 frmts/pcidsk/sdk/segment/metadatasegment_p.cpp     |     6 +-
 frmts/pcidsk/sdk/segment/orbitstructures.h         |   148 +-
 frmts/pcidsk/sdk/segment/sysblockmap.cpp           |     4 +-
 frmts/pcidsk/sdk/segment/sysblockmap.h             |     4 +-
 frmts/pcidsk/vsi_pcidsk_io.cpp                     |    25 +-
 frmts/pcraster/doxygen.cfg                         |   948 +-
 frmts/pcraster/libcsf/getattr.c                    |     2 +-
 frmts/pcraster/libcsf/kernlcsf.c                   |     8 +-
 frmts/pcraster/libcsf/mperror.c                    |     2 +-
 frmts/pcraster/libcsf/rextend.c                    |     2 +-
 frmts/pcraster/pcrasterdataset.cpp                 |    31 +-
 frmts/pcraster/pcrasterdataset.h                   |    18 +-
 frmts/pcraster/pcrastermisc.cpp                    |     3 +-
 frmts/pcraster/pcrasterrasterband.cpp              |    15 +-
 frmts/pcraster/pcrasterrasterband.h                |    18 +-
 frmts/pcraster/pcrasterutil.cpp                    |    15 +-
 frmts/pcraster/pcrasterutil.h                      |     8 +-
 frmts/pdf/GNUmakefile                              |     7 +
 frmts/pdf/frmt_pdf.html                            |    19 +-
 frmts/pdf/gdal_pdf.h                               |    77 +-
 frmts/pdf/ogrpdflayer.cpp                          |    27 +-
 frmts/pdf/pdfcreatecopy.cpp                        |   344 +-
 frmts/pdf/pdfcreatecopy.h                          |    22 +-
 frmts/pdf/pdfdataset.cpp                           |   572 +-
 frmts/pdf/pdfio.cpp                                |    82 +-
 frmts/pdf/pdfio.h                                  |    36 +-
 frmts/pdf/pdfobject.cpp                            |   108 +-
 frmts/pdf/pdfobject.h                              |   111 +-
 frmts/pdf/pdfreadvectors.cpp                       |    33 +-
 frmts/pdf/pdfwritabledataset.cpp                   |    44 +-
 frmts/pds/GNUmakefile                              |     4 +-
 frmts/pds/frmt_isis3.html                          |   235 +-
 frmts/pds/frmt_pds.html                            |    49 +-
 frmts/pds/isis2dataset.cpp                         |    31 +-
 frmts/pds/isis3dataset.cpp                         |  4770 +++++++-
 frmts/pds/makefile.vc                              |     2 +-
 frmts/pds/nasakeywordhandler.cpp                   |   263 +-
 frmts/pds/nasakeywordhandler.h                     |    63 +-
 frmts/pds/pdsdataset.cpp                           |    73 +-
 frmts/pds/vicardataset.cpp                         |    49 +-
 frmts/pds/vicarkeywordhandler.cpp                  |    31 +-
 frmts/plmosaic/GNUmakefile                         |     2 +-
 frmts/plmosaic/plmosaicdataset.cpp                 |   116 +-
 frmts/png/GNUmakefile                              |     4 +-
 frmts/png/libpng/README                            |    34 +-
 frmts/png/libpng/makefile.vc                       |    12 +-
 frmts/png/libpng/pngerror.c                        |     2 +-
 frmts/png/makefile.vc                              |    11 +-
 frmts/png/pngdataset.cpp                           |   466 +-
 frmts/postgisraster/GNUmakefile                    |     5 +-
 frmts/postgisraster/postgisraster.h                |   121 +-
 frmts/postgisraster/postgisrasterdataset.cpp       |   243 +-
 frmts/postgisraster/postgisrasterdriver.cpp        |    12 +-
 frmts/postgisraster/postgisrasterrasterband.cpp    |    45 +-
 frmts/postgisraster/postgisrastertiledataset.cpp   |    19 +-
 .../postgisraster/postgisrastertilerasterband.cpp  |    24 +-
 frmts/postgisraster/postgisrastertools.cpp         |    11 +-
 frmts/postgisraster/readme                         |     2 +-
 frmts/prf/GNUmakefile                              |    10 +
 frmts/prf/frmt_prf.html                            |    55 +
 frmts/prf/makefile.vc                              |    13 +
 frmts/prf/phprfdataset.cpp                         |   665 +
 frmts/r/rcreatecopy.cpp                            |   202 +-
 frmts/r/rdataset.cpp                               |   375 +-
 frmts/r/rdataset.h                                 |   104 +
 frmts/rasdaman/rasdamandataset.cpp                 |    69 +-
 frmts/rasterlite/rasterlitecreatecopy.cpp          |  1470 +--
 frmts/rasterlite/rasterlitedataset.cpp             |  2927 ++---
 frmts/rasterlite/rasterlitedataset.h               |   316 +-
 frmts/rasterlite/rasterliteoverviews.cpp           |  1602 ++-
 frmts/raw/GNUmakefile                              |     2 +-
 frmts/raw/ace2dataset.cpp                          |    52 +-
 frmts/raw/atlsci_spheroid.cpp                      |    88 +-
 frmts/raw/atlsci_spheroid.h                        |    32 +-
 frmts/raw/btdataset.cpp                            |   144 +-
 frmts/raw/cpgdataset.cpp                           |   136 +-
 frmts/raw/ctable2dataset.cpp                       |    16 +-
 frmts/raw/dipxdataset.cpp                          |    12 +-
 frmts/raw/doq1dataset.cpp                          |    15 +-
 frmts/raw/doq2dataset.cpp                          |    10 +-
 frmts/raw/ehdrdataset.cpp                          |  1400 +--
 frmts/raw/ehdrdataset.h                            |   169 +
 frmts/raw/eirdataset.cpp                           |    17 +-
 frmts/raw/envidataset.cpp                          |  2009 ++-
 frmts/raw/envidataset.h                            |   153 +
 frmts/raw/fastdataset.cpp                          |    35 +-
 frmts/raw/fujibasdataset.cpp                       |    13 +-
 frmts/raw/genbindataset.cpp                        |    17 +-
 frmts/raw/gscdataset.cpp                           |     5 +-
 frmts/raw/gtxdataset.cpp                           |    25 +-
 frmts/raw/hkvdataset.cpp                           |    39 +-
 frmts/raw/idadataset.cpp                           |   315 +-
 frmts/raw/iscedataset.cpp                          |   385 +-
 frmts/raw/krodataset.cpp                           |    62 +-
 frmts/raw/landataset.cpp                           |   200 +-
 frmts/raw/lcpdataset.cpp                           |   574 +-
 frmts/raw/loslasdataset.cpp                        |    14 +-
 frmts/raw/makefile.vc                              |     3 +-
 frmts/raw/mffdataset.cpp                           |   483 +-
 frmts/raw/ndfdataset.cpp                           |    15 +-
 frmts/raw/ntv2dataset.cpp                          |   208 +-
 frmts/raw/pauxdataset.cpp                          |   295 +-
 frmts/raw/pnmdataset.cpp                           |    97 +-
 frmts/raw/rawdataset.cpp                           |   885 +-
 frmts/raw/rawdataset.h                             |    50 +-
 frmts/raw/roipacdataset.cpp                        |   299 +-
 frmts/raw/rrasterdataset.cpp                       |   557 +
 frmts/raw/snodasdataset.cpp                        |   169 +-
 frmts/rik/makefile.vc                              |     6 +-
 frmts/rik/rikdataset.cpp                           |    69 +-
 frmts/rmf/frmt_rmf.html                            |     2 +-
 frmts/rmf/rmfdataset.cpp                           |   638 +-
 frmts/rmf/rmfdataset.h                             |    50 +-
 frmts/rmf/rmfdem.cpp                               |   155 +-
 frmts/rmf/rmflzw.cpp                               |   106 +-
 frmts/rs2/rs2dataset.cpp                           |   118 +-
 frmts/safe/frmt_safe.html                          |    12 +-
 frmts/safe/safedataset.cpp                         |   127 +-
 frmts/saga/sagadataset.cpp                         |   183 +-
 frmts/sde/GNUmakefile                              |    26 +-
 frmts/sde/gdal_sde.h                               |     7 -
 frmts/sde/sdedataset.cpp                           |    32 +-
 frmts/sde/sdedataset.h                             |    14 +-
 frmts/sde/sdeerror.cpp                             |     8 +-
 frmts/sde/sdeerror.h                               |     1 -
 frmts/sde/sderasterband.cpp                        |    48 +-
 frmts/sde/sderasterband.h                          |    32 +-
 frmts/sdts/Doxyfile                                |    60 +-
 frmts/sdts/sdts2shp.cpp                            |   135 +-
 frmts/sdts/sdts_al.h                               |    26 +-
 frmts/sdts/sdts_main.dox                           |    42 +-
 frmts/sdts/sdts_tut.dox                            |    72 +-
 frmts/sdts/sdtsattrreader.cpp                      |     9 +-
 frmts/sdts/sdtscatd.cpp                            |     7 +-
 frmts/sdts/sdtsdataset.cpp                         |    33 +-
 frmts/sdts/sdtsindexedreader.cpp                   |     8 +-
 frmts/sdts/sdtsiref.cpp                            |     8 +-
 frmts/sdts/sdtslib.cpp                             |    21 +-
 frmts/sdts/sdtslinereader.cpp                      |    21 +-
 frmts/sdts/sdtspointreader.cpp                     |     8 +-
 frmts/sdts/sdtspolygonreader.cpp                   |    11 +-
 frmts/sdts/sdtsrasterreader.cpp                    |    17 +-
 frmts/sdts/sdtstransfer.cpp                        |    10 +-
 frmts/sdts/sdtsxref.cpp                            |     3 +-
 frmts/sentinel2/frmt_sentinel2.html                |     2 +-
 frmts/sentinel2/sentinel2dataset.cpp               |   116 +-
 frmts/sgi/sgidataset.cpp                           |    58 +-
 frmts/srtmhgt/srtmhgtdataset.cpp                   |   157 +-
 frmts/terragen/terragendataset.cpp                 |   523 +-
 frmts/til/tildataset.cpp                           |    15 +-
 frmts/tsx/tsxdataset.cpp                           |    31 +-
 frmts/usgsdem/CDED.notes                           |    26 +-
 frmts/usgsdem/usgsdem_create.cpp                   |    48 +-
 frmts/usgsdem/usgsdemdataset.cpp                   |    55 +-
 frmts/vrt/GNUmakefile                              |    21 +-
 frmts/vrt/gdal_vrt.h                               |    34 +-
 frmts/vrt/makefile.vc                              |     4 +-
 frmts/vrt/pixelfunctions.cpp                       |   939 ++
 frmts/vrt/vrt_tutorial.dox                         |   505 +-
 frmts/vrt/vrtdataset.cpp                           |   358 +-
 frmts/vrt/vrtdataset.h                             |   481 +-
 frmts/vrt/vrtderivedrasterband.cpp                 |  1885 ++-
 frmts/vrt/vrtdriver.cpp                            |    62 +-
 frmts/vrt/vrtfilters.cpp                           |   179 +-
 frmts/vrt/vrtpansharpened.cpp                      |    74 +-
 frmts/vrt/vrtrasterband.cpp                        |    70 +-
 frmts/vrt/vrtrawrasterband.cpp                     |   157 +-
 frmts/vrt/vrtsourcedrasterband.cpp                 |   807 +-
 frmts/vrt/vrtsources.cpp                           |  1387 ++-
 frmts/vrt/vrtwarped.cpp                            |   530 +-
 frmts/wcs/GNUmakefile                              |     2 +-
 frmts/wcs/httpdriver.cpp                           |    14 +-
 frmts/wcs/wcsdataset.cpp                           |   146 +-
 frmts/webp/webpdataset.cpp                         |    20 +-
 frmts/wms/GNUmakefile                              |     7 +-
 frmts/wms/frmt_wms_arcgis_mapserver_tms.xml        |     2 +-
 frmts/wms/frmt_wms_arcgis_terrain_tms_lerc.xml     |    21 +
 frmts/wms/gdalhttp.cpp                             |   183 +-
 frmts/wms/gdalhttp.h                               |    49 +-
 frmts/wms/gdalwmscache.cpp                         |    43 +-
 frmts/wms/gdalwmsdataset.cpp                       |   476 +-
 frmts/wms/gdalwmsrasterband.cpp                    |  1798 +--
 frmts/wms/makefile.vc                              |     2 +-
 frmts/wms/md5.cpp                                  |    13 +-
 frmts/wms/md5.h                                    |     5 +
 frmts/wms/minidriver.cpp                           |   132 +-
 frmts/wms/minidriver_arcgis_server.cpp             |   282 +-
 frmts/wms/minidriver_arcgis_server.h               |    52 +-
 frmts/wms/minidriver_iip.cpp                       |    48 +-
 frmts/wms/minidriver_iip.h                         |    21 +-
 frmts/wms/minidriver_mrf.cpp                       |   323 +
 frmts/wms/minidriver_mrf.h                         |   117 +
 frmts/wms/minidriver_tiled_wms.cpp                 |   689 +-
 frmts/wms/minidriver_tiled_wms.h                   |    20 +-
 frmts/wms/minidriver_tileservice.cpp               |    68 +-
 frmts/wms/minidriver_tileservice.h                 |    23 +-
 frmts/wms/minidriver_tms.cpp                       |    60 +-
 frmts/wms/minidriver_tms.h                         |    24 +-
 frmts/wms/minidriver_virtualearth.cpp              |    83 +-
 frmts/wms/minidriver_virtualearth.h                |    22 +-
 frmts/wms/minidriver_wms.cpp                       |   127 +-
 frmts/wms/minidriver_wms.h                         |    45 +-
 frmts/wms/minidriver_worldwind.cpp                 |    66 +-
 frmts/wms/minidriver_worldwind.h                   |    24 +-
 frmts/wms/wmsdriver.cpp                            |   136 +-
 frmts/wms/wmsdriver.h                              |   301 +-
 frmts/wms/wmsmetadataset.cpp                       |    30 +-
 frmts/wms/wmsmetadataset.h                         |     8 +-
 frmts/wms/wmsutils.cpp                             |    75 +-
 frmts/wmts/frmt_wmts.html                          |    14 +-
 frmts/wmts/wmtsdataset.cpp                         |   448 +-
 frmts/xpm/xpmdataset.cpp                           |    31 +-
 frmts/xyz/xyzdataset.cpp                           |    79 +-
 frmts/zlib/README                                  |     6 +-
 frmts/zlib/deflate.c                               |     4 +-
 frmts/zlib/inflate.c                               |     2 +-
 frmts/zlib/trees.c                                 |    18 +-
 frmts/zlib/zlib.h                                  |     2 +-
 frmts/zlib/zutil.c                                 |     5 +-
 frmts/zmap/zmapdataset.cpp                         |    15 +-
 gcore/GNUmakefile                                  |     7 +-
 gcore/Version.rc                                   |     6 +-
 gcore/gdal.h                                       |   153 +-
 gcore/gdal_avx2_emulation.hpp                      |   240 +
 gcore/gdal_frmts.h                                 |     6 +-
 gcore/gdal_mdreader.cpp                            |    37 +-
 gcore/gdal_mdreader.h                              |     8 +-
 gcore/gdal_misc.cpp                                |   822 +-
 gcore/gdal_pam.h                                   |   115 +-
 gcore/gdal_priv.h                                  |   369 +-
 gcore/gdal_priv_templates.hpp                      |   234 +-
 gcore/gdal_proxy.h                                 |   211 +-
 gcore/gdal_rat.cpp                                 |   148 +-
 gcore/gdal_rat.h                                   |    55 +-
 gcore/gdal_version.h                               |    11 +-
 gcore/gdalabstractbandblockcache.cpp               |    23 +-
 gcore/gdalallvalidmaskband.cpp                     |    11 +-
 gcore/gdalarraybandblockcache.cpp                  |    38 +-
 gcore/gdalclientserver.cpp                         |   312 +-
 gcore/gdalcolortable.cpp                           |    89 +-
 gcore/gdaldataset.cpp                              |  3822 +++---
 gcore/gdaldefaultasync.cpp                         |   114 +-
 gcore/gdaldefaultoverviews.cpp                     |   433 +-
 gcore/gdaldllmain.cpp                              |    27 +-
 gcore/gdaldriver.cpp                               |   635 +-
 gcore/gdaldrivermanager.cpp                        |   210 +-
 gcore/gdalexif.cpp                                 |    45 +-
 gcore/gdalexif.h                                   |   231 +-
 gcore/gdalgeorefpamdataset.cpp                     |   245 +-
 gcore/gdalgeorefpamdataset.h                       |    42 +-
 gcore/gdalgmlcoverage.cpp                          |    15 +-
 gcore/gdalhashsetbandblockcache.cpp                |    88 +-
 gcore/gdaljp2abstractdataset.cpp                   |   425 +-
 gcore/gdaljp2abstractdataset.h                     |    19 +-
 gcore/gdaljp2box.cpp                               |    82 +-
 gcore/gdaljp2metadata.cpp                          |   743 +-
 gcore/gdaljp2metadata.h                            |    20 +-
 gcore/gdaljp2metadatagenerator.cpp                 |   630 +-
 gcore/gdaljp2metadatagenerator.h                   |     3 +-
 gcore/gdaljp2structure.cpp                         |    55 +-
 gcore/gdalmajorobject.cpp                          |    77 +-
 gcore/gdalmultidomainmetadata.cpp                  |    95 +-
 gcore/gdalnodatamaskband.cpp                       |   145 +-
 gcore/gdalnodatavaluesmaskband.cpp                 |   180 +-
 gcore/gdalopeninfo.cpp                             |    41 +-
 gcore/gdaloverviewdataset.cpp                      |   162 +-
 gcore/gdalpamdataset.cpp                           |   110 +-
 gcore/gdalpamproxydb.cpp                           |    23 +-
 gcore/gdalpamrasterband.cpp                        |   558 +-
 gcore/gdalproxydataset.cpp                         |   163 +-
 gcore/gdalproxypool.cpp                            |    66 +-
 gcore/gdalrasterband.cpp                           |  2921 ++++-
 gcore/gdalrasterblock.cpp                          |   369 +-
 gcore/gdalrescaledalphaband.cpp                    |    87 +-
 gcore/gdalsse_priv.h                               |    29 +-
 gcore/gdalvirtualmem.cpp                           |   898 +-
 gcore/makefile.vc                                  |     6 +-
 gcore/mdreader/reader_alos.cpp                     |    20 +-
 gcore/mdreader/reader_alos.h                       |    10 +-
 gcore/mdreader/reader_digital_globe.cpp            |    34 +-
 gcore/mdreader/reader_digital_globe.h              |     8 +-
 gcore/mdreader/reader_eros.cpp                     |    17 +-
 gcore/mdreader/reader_eros.h                       |    10 +-
 gcore/mdreader/reader_geo_eye.cpp                  |    18 +-
 gcore/mdreader/reader_geo_eye.h                    |    10 +-
 gcore/mdreader/reader_kompsat.cpp                  |    32 +-
 gcore/mdreader/reader_kompsat.h                    |    10 +-
 gcore/mdreader/reader_landsat.cpp                  |    15 +-
 gcore/mdreader/reader_landsat.h                    |     8 +-
 gcore/mdreader/reader_orb_view.cpp                 |    24 +-
 gcore/mdreader/reader_orb_view.h                   |     8 +-
 gcore/mdreader/reader_pleiades.cpp                 |    39 +-
 gcore/mdreader/reader_pleiades.h                   |    16 +-
 gcore/mdreader/reader_rapid_eye.cpp                |    13 +-
 gcore/mdreader/reader_rapid_eye.h                  |     8 +-
 gcore/mdreader/reader_rdk1.cpp                     |    21 +-
 gcore/mdreader/reader_rdk1.h                       |    12 +-
 gcore/mdreader/reader_spot.cpp                     |    17 +-
 gcore/mdreader/reader_spot.h                       |     6 +-
 gcore/overview.cpp                                 |  2940 +++--
 gcore/rasterio.cpp                                 |  2704 +++--
 gcore/rasterio_ssse3.cpp                           |   129 +
 gcore/statistics.txt                               |   549 +
 generate_vcxproj.bat                               |   490 +
 gnm/GNUmakefile                                    |    12 +-
 gnm/gnm.h                                          |   191 +-
 gnm/gnm_api.h                                      |     5 +-
 gnm/gnm_frmts/db/gnmdb.h                           |    24 +-
 gnm/gnm_frmts/db/gnmdbdriver.cpp                   |     4 +-
 gnm/gnm_frmts/db/gnmdbnetwork.cpp                  |    10 +-
 gnm/gnm_frmts/file/gnmfile.h                       |    32 +-
 gnm/gnm_frmts/file/gnmfiledriver.cpp               |     7 +-
 gnm/gnm_frmts/file/gnmfilenetwork.cpp              |    17 +-
 gnm/gnm_frmts/gnm_frmts.h                          |     2 +-
 gnm/gnm_frmts/gnmregisterall.cpp                   |     3 +-
 gnm/gnm_frmts/o/README.TXT                         |     2 +-
 gnm/gnm_priv.h                                     |    11 +-
 gnm/gnm_tut.dox                                    |    44 +-
 gnm/gnmgenericnetwork.cpp                          |    18 +-
 gnm/gnmgraph.cpp                                   |    17 +-
 gnm/gnmgraph.h                                     |    53 +-
 gnm/gnmlayer.cpp                                   |    20 +-
 gnm/gnmnetwork.cpp                                 |    12 +-
 gnm/gnmresultlayer.cpp                             |     6 +-
 gnm/gnmrule.cpp                                    |    35 +-
 gnm/makefile.vc                                    |     8 +-
 install-sh                                         |    16 +-
 m4/acinclude.m4                                    |     6 +-
 m4/ax_cxx_compile_stdcxx.m4                        |   562 +
 m4/ax_cxx_compile_stdcxx_11.m4                     |    39 +
 m4/ax_lib_libkml.m4                                |    37 +-
 m4/ax_lib_xerces.m4                                |    23 +-
 m4/geos.m4                                         |    12 +-
 m4/sfcgal.m4                                       |   150 +
 makefile.vc                                        |    82 +-
 makegdal_gen.bat                                   |   369 -
 man/man1/gdal-config.1                             |     5 +-
 man/man1/gdal2tiles.1                              |     5 +-
 man/man1/gdal_calc.1                               |    34 +-
 man/man1/gdal_contour.1                            |     7 +-
 man/man1/gdal_edit.1                               |    21 +-
 man/man1/gdal_fillnodata.1                         |     5 +-
 man/man1/gdal_grid.1                               |    15 +-
 man/man1/gdal_merge.1                              |     7 +-
 man/man1/gdal_pansharpen.1                         |     7 +-
 man/man1/gdal_polygonize.1                         |     9 +-
 man/man1/gdal_proximity.1                          |     9 +-
 man/man1/gdal_rasterize.1                          |    16 +-
 man/man1/gdal_retile.1                             |    12 +-
 man/man1/gdal_sieve.1                              |     7 +-
 man/man1/gdal_translate.1                          |    11 +-
 man/man1/gdal_utilities.1                          |    34 +-
 man/man1/gdaladdo.1                                |     5 +-
 man/man1/gdalbuildvrt.1                            |    11 +-
 man/man1/gdalcompare.1                             |     5 +-
 man/man1/gdaldem.1                                 |    31 +-
 man/man1/gdalinfo.1                                |     7 +-
 man/man1/gdallocationinfo.1                        |     4 +-
 man/man1/gdalmanage.1                              |     5 +-
 man/man1/gdalmove.1                                |     5 +-
 man/man1/gdalsrsinfo.1                             |     7 +-
 man/man1/gdaltindex.1                              |     5 +-
 man/man1/gdaltransform.1                           |    11 +-
 man/man1/gdalwarp.1                                |    60 +-
 man/man1/gnm_utilities.1                           |     2 +-
 man/man1/gnmanalyse.1                              |     2 +-
 man/man1/gnmmanage.1                               |     2 +-
 man/man1/nearblack.1                               |     7 +-
 man/man1/ogr2ogr.1                                 |    23 +-
 man/man1/ogr_utilities.1                           |     4 +-
 man/man1/ogrinfo.1                                 |    15 +-
 man/man1/ogrlineref.1                              |     5 +-
 man/man1/ogrmerge.1                                |   146 +
 man/man1/ogrtindex.1                               |    25 +-
 man/man1/pct2rgb.1                                 |     5 +-
 man/man1/rgb2pct.1                                 |     7 +-
 mkgdaldist.sh                                      |    31 +-
 mktestdist.sh                                      |     4 +-
 nmake.opt                                          |   112 +-
 ogr/Doxyfile                                       |  1006 +-
 ogr/GNUmakefile                                    |    12 +-
 ogr/file.lst                                       |     6 +-
 ogr/generate_encoding_table.c                      |     5 +-
 ogr/gml2ogrgeometry.cpp                            |  2408 ++--
 ogr/makefile.vc                                    |    22 +-
 ogr/ogr2gmlgeometry.cpp                            |   981 +-
 ogr/ogr_api.cpp                                    |   845 +-
 ogr/ogr_api.h                                      |    67 +-
 ogr/ogr_apitut.dox                                 |   140 +-
 ogr/ogr_arch.dox                                   |    82 +-
 ogr/ogr_capi_test.c                                |     2 +-
 ogr/ogr_core.h                                     |   419 +-
 ogr/ogr_drivertut.dox                              |   224 +-
 ogr/ogr_expat.cpp                                  |    83 +-
 ogr/ogr_expat.h                                    |     2 +-
 ogr/ogr_feature.h                                  |   162 +-
 ogr/ogr_feature_style.html                         |    14 +-
 ogr/ogr_featurestyle.h                             |    59 +-
 ogr/ogr_fromepsg.cpp                               |   487 +-
 ogr/ogr_geocoding.cpp                              |   527 +-
 ogr/ogr_geocoding.h                                |     3 +-
 ogr/ogr_geometry.h                                 |  1285 +-
 ogr/ogr_geos.h                                     |     2 +-
 ogr/ogr_json_header.h                              |    38 +
 ogr/ogr_libs.h                                     |    62 +
 ogr/ogr_opt.cpp                                    |    54 +-
 ogr/ogr_p.h                                        |     6 +-
 ogr/ogr_sfcgal.h                                   |    36 +
 ogr/ogr_spatialref.h                               |    38 +-
 ogr/ogr_sql.dox                                    |   205 +-
 ogr/ogr_sql_sqlite.dox                             |    28 +-
 ogr/ogr_srs_api.h                                  |   201 +-
 ogr/ogr_srs_dict.cpp                               |    41 +-
 ogr/ogr_srs_erm.cpp                                |    82 +-
 ogr/ogr_srs_esri.cpp                               |  1661 ++-
 ogr/ogr_srs_esri_names.h                           |     6 +-
 ogr/ogr_srs_ozi.cpp                                |   324 +-
 ogr/ogr_srs_panorama.cpp                           |   251 +-
 ogr/ogr_srs_pci.cpp                                |   483 +-
 ogr/ogr_srs_proj4.cpp                              |  2063 ++--
 ogr/ogr_srs_usgs.cpp                               |   345 +-
 ogr/ogr_srs_validate.cpp                           |   451 +-
 ogr/ogr_srs_xml.cpp                                |   334 +-
 ogr/ogr_srsnode.cpp                                |   178 +-
 ogr/ogr_xerces.cpp                                 |   185 +
 ogr/ogr_xerces.h                                   |    62 +
 ogr/ogr_xerces_headers.h                           |    42 +
 ogr/ograpispy.cpp                                  |   424 +-
 ogr/ograpispy.h                                    |     3 +-
 ogr/ograssemblepolygon.cpp                         |   209 +-
 ogr/ogrcircularstring.cpp                          |   483 +-
 ogr/ogrcompoundcurve.cpp                           |   223 +-
 ogr/ogrct.cpp                                      |   485 +-
 ogr/ogrcurve.cpp                                   |   114 +-
 ogr/ogrcurvecollection.cpp                         |   258 +-
 ogr/ogrcurvepolygon.cpp                            |   253 +-
 ogr/ogrfeature.cpp                                 |  2751 +++--
 ogr/ogrfeaturedefn.cpp                             |   209 +-
 ogr/ogrfeaturequery.cpp                            |   478 +-
 ogr/ogrfeaturestyle.cpp                            |  1552 +--
 ogr/ogrfielddefn.cpp                               |   232 +-
 ogr/ogrgeomediageometry.cpp                        |   195 +-
 ogr/ogrgeometry.cpp                                |  2447 ++--
 ogr/ogrgeometrycollection.cpp                      |   420 +-
 ogr/ogrgeometryfactory.cpp                         |  3132 +++--
 ogr/ogrgeomfielddefn.cpp                           |    88 +-
 ogr/ogrlinearring.cpp                              |   278 +-
 ogr/ogrlinestring.cpp                              |   873 +-
 ogr/ogrmulticurve.cpp                              |    72 +-
 ogr/ogrmultilinestring.cpp                         |    51 +-
 ogr/ogrmultipoint.cpp                              |   212 +-
 ogr/ogrmultipolygon.cpp                            |   107 +-
 ogr/ogrmultisurface.cpp                            |   110 +-
 ogr/ogrpgeogeometry.cpp                            |  2242 +++-
 ogr/ogrpgeogeometry.h                              |    27 +-
 ogr/ogrpoint.cpp                                   |   262 +-
 ogr/ogrpolygon.cpp                                 |   286 +-
 ogr/ogrpolyhedralsurface.cpp                       |  1076 ++
 ogr/ogrsf_frmts/GNUmakefile                        |     4 +-
 ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h        |    49 +-
 .../aeronavfaa/ograeronavfaadatasource.cpp         |    69 +-
 ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp |     5 +-
 ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp  |    96 +-
 ogr/ogrsf_frmts/amigocloud/GNUmakefile             |     2 +-
 ogr/ogrsf_frmts/amigocloud/drv_amigocloud.html     |    16 +-
 ogr/ogrsf_frmts/amigocloud/makefile.vc             |     2 +-
 ogr/ogrsf_frmts/amigocloud/ogr_amigocloud.h        |   126 +-
 .../amigocloud/ogramigoclouddatasource.cpp         |    83 +-
 ogr/ogrsf_frmts/amigocloud/ogramigoclouddriver.cpp |    14 +-
 ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp  |    53 +-
 .../amigocloud/ogramigocloudresultlayer.cpp        |     3 +-
 .../amigocloud/ogramigocloudtablelayer.cpp         |   102 +-
 ogr/ogrsf_frmts/arcgen/ogr_arcgen.h                |    25 +-
 ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp     |    15 +-
 ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp         |     7 +-
 ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp          |    17 +-
 ogr/ogrsf_frmts/arcobjects/GNUmakefile             |    32 +-
 ogr/ogrsf_frmts/arcobjects/aodatasource.cpp        |   437 +-
 ogr/ogrsf_frmts/arcobjects/aodriver.cpp            |   445 +-
 ogr/ogrsf_frmts/arcobjects/aolayer.cpp             |  1201 +-
 ogr/ogrsf_frmts/arcobjects/aoutils.cpp             |   927 +-
 ogr/ogrsf_frmts/arcobjects/aoutils.h               |    74 +-
 ogr/ogrsf_frmts/arcobjects/ogr_ao.h                |   398 +-
 ogr/ogrsf_frmts/avc/GNUmakefile                    |     4 +-
 ogr/ogrsf_frmts/avc/HISTORY.TXT                    |    68 +-
 ogr/ogrsf_frmts/avc/avc.h                          |    23 +-
 ogr/ogrsf_frmts/avc/avc_bin.c                      |    14 +-
 ogr/ogrsf_frmts/avc/avc_binwr.c                    |     8 +-
 ogr/ogrsf_frmts/avc/avc_e00gen.c                   |     6 +-
 ogr/ogrsf_frmts/avc/avc_e00parse.c                 |     4 +-
 ogr/ogrsf_frmts/avc/avc_e00read.c                  |     2 +-
 ogr/ogrsf_frmts/avc/avc_e00write.c                 |     2 +-
 ogr/ogrsf_frmts/avc/avc_mbyte.c                    |    10 +-
 ogr/ogrsf_frmts/avc/avc_mbyte.h                    |     3 +-
 ogr/ogrsf_frmts/avc/avc_misc.c                     |     4 +-
 ogr/ogrsf_frmts/avc/avc_rawbin.c                   |     2 +-
 ogr/ogrsf_frmts/avc/ogr_avc.h                      |    91 +-
 ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp        |     3 +-
 ogr/ogrsf_frmts/avc/ogravcbindriver.cpp            |     3 +-
 ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp             |    67 +-
 ogr/ogrsf_frmts/avc/ogravcdatasource.cpp           |     3 +-
 ogr/ogrsf_frmts/avc/ogravce00datasource.cpp        |    16 +-
 ogr/ogrsf_frmts/avc/ogravce00driver.cpp            |     3 +-
 ogr/ogrsf_frmts/avc/ogravce00layer.cpp             |    87 +-
 ogr/ogrsf_frmts/avc/ogravclayer.cpp                |    41 +-
 ogr/ogrsf_frmts/bna/ogr_bna.h                      |    41 +-
 ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp           |    45 +-
 ogr/ogrsf_frmts/bna/ogrbnadriver.cpp               |     3 +-
 ogr/ogrsf_frmts/bna/ogrbnalayer.cpp                |    70 +-
 ogr/ogrsf_frmts/bna/ogrbnaparser.cpp               |    49 +-
 ogr/ogrsf_frmts/bna/ogrbnaparser.h                 |     3 +-
 ogr/ogrsf_frmts/cad/GNUmakefile                    |    20 +
 ogr/ogrsf_frmts/cad/drv_cad.html                   |    49 +
 ogr/ogrsf_frmts/cad/gdalcaddataset.cpp             |   478 +
 ogr/ogrsf_frmts/cad/libopencad/GNUmakefile         |    31 +
 ogr/ogrsf_frmts/cad/libopencad/cadclasses.cpp      |   103 +
 ogr/ogrsf_frmts/cad/libopencad/cadclasses.h        |    71 +
 ogr/ogrsf_frmts/cad/libopencad/cadcolors.cpp       |   296 +
 ogr/ogrsf_frmts/cad/libopencad/cadcolors.h         |    46 +
 ogr/ogrsf_frmts/cad/libopencad/caddictionary.cpp   |   111 +
 ogr/ogrsf_frmts/cad/libopencad/caddictionary.h     |    86 +
 ogr/ogrsf_frmts/cad/libopencad/cadfile.cpp         |   121 +
 ogr/ogrsf_frmts/cad/libopencad/cadfile.h           |   148 +
 ogr/ogrsf_frmts/cad/libopencad/cadfileio.cpp       |    59 +
 ogr/ogrsf_frmts/cad/libopencad/cadfileio.h         |    79 +
 ogr/ogrsf_frmts/cad/libopencad/cadfilestreamio.cpp |   115 +
 ogr/ogrsf_frmts/cad/libopencad/cadfilestreamio.h   |    57 +
 ogr/ogrsf_frmts/cad/libopencad/cadgeometry.cpp     |  1263 ++
 ogr/ogrsf_frmts/cad/libopencad/cadgeometry.h       |   683 ++
 ogr/ogrsf_frmts/cad/libopencad/cadheader.cpp       |   525 +
 ogr/ogrsf_frmts/cad/libopencad/cadheader.h         |   709 ++
 ogr/ogrsf_frmts/cad/libopencad/cadlayer.cpp        |   333 +
 ogr/ogrsf_frmts/cad/libopencad/cadlayer.h          |   114 +
 ogr/ogrsf_frmts/cad/libopencad/cadobjects.cpp      |   918 ++
 ogr/ogrsf_frmts/cad/libopencad/cadobjects.h        |  1349 ++
 ogr/ogrsf_frmts/cad/libopencad/cadtables.cpp       |   172 +
 ogr/ogrsf_frmts/cad/libopencad/cadtables.h         |    86 +
 ogr/ogrsf_frmts/cad/libopencad/dwg/GNUmakefile     |    19 +
 ogr/ogrsf_frmts/cad/libopencad/dwg/io.cpp          |   899 ++
 ogr/ogrsf_frmts/cad/libopencad/dwg/io.h            |   145 +
 ogr/ogrsf_frmts/cad/libopencad/dwg/makefile.vc     |    18 +
 ogr/ogrsf_frmts/cad/libopencad/dwg/r2000.cpp       |  3653 ++++++
 ogr/ogrsf_frmts/cad/libopencad/dwg/r2000.h         |   237 +
 ogr/ogrsf_frmts/cad/libopencad/makefile.vc         |    34 +
 ogr/ogrsf_frmts/cad/libopencad/opencad.cpp         |   202 +
 ogr/ogrsf_frmts/cad/libopencad/opencad.h           |    93 +
 ogr/ogrsf_frmts/cad/libopencad/opencad_api.h       |    84 +
 ogr/ogrsf_frmts/cad/makefile.vc                    |    21 +
 ogr/ogrsf_frmts/cad/ogr_cad.h                      |   106 +
 ogr/ogrsf_frmts/cad/ogrcaddriver.cpp               |   213 +
 ogr/ogrsf_frmts/cad/ogrcadlayer.cpp                |   761 ++
 ogr/ogrsf_frmts/cad/vsilfileio.cpp                 |   123 +
 ogr/ogrsf_frmts/cad/vsilfileio.h                   |    56 +
 ogr/ogrsf_frmts/carto/GNUmakefile                  |     2 +-
 ogr/ogrsf_frmts/carto/drv_cartodb.html             |    13 +
 ogr/ogrsf_frmts/carto/makefile.vc                  |     2 +-
 ogr/ogrsf_frmts/carto/ogr_carto.h                  |   139 +-
 ogr/ogrsf_frmts/carto/ogrcartodatasource.cpp       |    92 +-
 ogr/ogrsf_frmts/carto/ogrcartodriver.cpp           |     8 +-
 ogr/ogrsf_frmts/carto/ogrcartolayer.cpp            |    50 +-
 ogr/ogrsf_frmts/carto/ogrcartoresultlayer.cpp      |     4 +-
 ogr/ogrsf_frmts/carto/ogrcartotablelayer.cpp       |   185 +-
 ogr/ogrsf_frmts/cloudant/ogr_cloudant.h            |    39 +-
 ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp |    47 +-
 ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp     |    83 +-
 ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp |    92 +-
 ogr/ogrsf_frmts/couchdb/ogr_couchdb.h              |   180 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp   |   196 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp       |    91 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp        |   104 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp    |    35 +-
 ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp   |   415 +-
 ogr/ogrsf_frmts/csv/drv_csv.html                   |     5 +
 ogr/ogrsf_frmts/csv/ogr_csv.h                      |   106 +-
 ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp           |   164 +-
 ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp               |    26 +-
 ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp                |   491 +-
 ogr/ogrsf_frmts/csw/ogrcswdataset.cpp              |    86 +-
 ogr/ogrsf_frmts/db2/GNUmakefile                    |    20 +-
 ogr/ogrsf_frmts/db2/drv_db2_raster.html            |     4 +-
 ogr/ogrsf_frmts/db2/gdaldb2rasterband.cpp          |    80 +-
 ogr/ogrsf_frmts/db2/ogr_db2.h                      |   196 +-
 ogr/ogrsf_frmts/db2/ogrdb2cli.cpp                  |    19 +-
 ogr/ogrsf_frmts/db2/ogrdb2datasource.cpp           |   106 +-
 ogr/ogrsf_frmts/db2/ogrdb2datasourcemd.cpp         |    46 +-
 ogr/ogrsf_frmts/db2/ogrdb2driver.cpp               |     4 +-
 ogr/ogrsf_frmts/db2/ogrdb2geometryvalidator.cpp    |     8 +-
 ogr/ogrsf_frmts/db2/ogrdb2layer.cpp                |    19 +-
 ogr/ogrsf_frmts/db2/ogrdb2selectlayer.cpp          |     4 +-
 ogr/ogrsf_frmts/db2/ogrdb2tablelayer.cpp           |    62 +-
 ogr/ogrsf_frmts/dgn/Doxyfile                       |    60 +-
 ogr/ogrsf_frmts/dgn/GNUmakefile                    |     2 +-
 ogr/ogrsf_frmts/dgn/dgndump.c                      |   250 -
 ogr/ogrsf_frmts/dgn/dgndump.cpp                    |   253 +
 ogr/ogrsf_frmts/dgn/dgnfloat.cpp                   |    22 +-
 ogr/ogrsf_frmts/dgn/dgnhelp.cpp                    |   163 +-
 ogr/ogrsf_frmts/dgn/dgnlib.h                       |    33 +-
 ogr/ogrsf_frmts/dgn/dgnlibp.h                      |    16 +-
 ogr/ogrsf_frmts/dgn/dgnopen.cpp                    |    59 +-
 ogr/ogrsf_frmts/dgn/dgnread.cpp                    |   484 +-
 ogr/ogrsf_frmts/dgn/dgnstroke.cpp                  |   103 +-
 ogr/ogrsf_frmts/dgn/dgnwrite.cpp                   |   510 +-
 ogr/ogrsf_frmts/dgn/dgnwritetest.c                 |   229 -
 ogr/ogrsf_frmts/dgn/dgnwritetest.cpp               |   225 +
 ogr/ogrsf_frmts/dgn/dist/README                    |    68 +-
 ogr/ogrsf_frmts/dgn/drv_dgn.html                   |     5 +-
 ogr/ogrsf_frmts/dgn/ogr_dgn.h                      |    39 +-
 ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp           |    19 +-
 ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp               |     3 +-
 ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp                |    72 +-
 ogr/ogrsf_frmts/dods/GNUmakefile                   |     2 +-
 ogr/ogrsf_frmts/dods/libdap_headers.h              |    72 +
 ogr/ogrsf_frmts/dods/ogr_dods.h                    |   111 +-
 ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp         |    23 +-
 ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp             |    12 +-
 ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp          |    45 +-
 ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp               |    60 +-
 ogr/ogrsf_frmts/dods/ogrdodslayer.cpp              |    30 +-
 ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp      |   109 +-
 ogr/ogrsf_frmts/dwg/GNUmakefile                    |    52 +-
 ogr/ogrsf_frmts/dwg/createdgnv8testfile.cpp        |   826 ++
 ogr/ogrsf_frmts/dwg/createdgnv8testfile_headers.h  |    76 +
 ogr/ogrsf_frmts/dwg/dgnv8_headers.h                |    79 +
 ogr/ogrsf_frmts/dwg/drv_dgnv8.html                 |   179 +
 ogr/ogrsf_frmts/dwg/dwg_headers.h                  |    90 +
 ogr/ogrsf_frmts/dwg/makefile.vc                    |    42 +-
 ogr/ogrsf_frmts/dwg/ogr_dgnv8.h                    |   171 +
 ogr/ogrsf_frmts/dwg/ogr_dwg.h                      |    70 +-
 ogr/ogrsf_frmts/dwg/ogrdgnv8datasource.cpp         |   626 +
 ogr/ogrsf_frmts/dwg/ogrdgnv8driver.cpp             |   205 +
 ogr/ogrsf_frmts/dwg/ogrdgnv8layer.cpp              |  2281 ++++
 ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp            |     7 +-
 ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp           |    19 +-
 ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp               |    11 +-
 ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp          |    10 +-
 ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp           |    40 +-
 ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp               |    70 +-
 ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp                |    79 +-
 ogr/ogrsf_frmts/dwg/ogrteigha.cpp                  |   147 +
 ogr/ogrsf_frmts/dwg/ogrteigha.h                    |    40 +
 ogr/ogrsf_frmts/dxf/intronurbs.cpp                 |   301 +-
 ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp       |     9 +-
 ogr/ogrsf_frmts/dxf/ogr_autocad_services.h         |     2 +-
 ogr/ogrsf_frmts/dxf/ogr_dxf.h                      |    91 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp            |    66 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp           |    82 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp               |   145 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp     |    58 +-
 ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h       |    46 +-
 ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp          |    10 +-
 ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp    |     8 +-
 ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp           |    38 +-
 ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp               |    23 +-
 ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp                |   494 +-
 ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp               |     6 +-
 ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp             |   176 +-
 ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp          |   142 +-
 ogr/ogrsf_frmts/edigeo/drv_edigeo.html             |     2 +-
 ogr/ogrsf_frmts/edigeo/ogr_edigeo.h                |    34 +-
 ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp     |   199 +-
 ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp         |     4 +-
 ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp          |    28 +-
 ogr/ogrsf_frmts/elastic/GNUmakefile                |     2 +-
 ogr/ogrsf_frmts/elastic/drv_elasticsearch.html     |    83 +-
 ogr/ogrsf_frmts/elastic/ogr_elastic.h              |   126 +-
 ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp   |   388 +-
 ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp       |     9 +-
 ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp        |  1282 +-
 ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp         |  1517 ++-
 ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp             |  1700 +--
 ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp              |  7654 ++++++------
 ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp        |   330 +-
 ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp              |  1207 +-
 ogr/ogrsf_frmts/filegdb/FGdbUtils.h                |   176 +-
 ogr/ogrsf_frmts/filegdb/GNUmakefile                |     2 +-
 ogr/ogrsf_frmts/filegdb/drv_filegdb.html           |     8 +-
 ogr/ogrsf_frmts/filegdb/filegdbsdk_headers.h       |     5 +
 ogr/ogrsf_frmts/filegdb/ogr_fgdb.h                 |   810 +-
 ogr/ogrsf_frmts/fme/fme2ogr.h                      |    57 +-
 ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp              |     3 +-
 ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp           |    14 +-
 ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp           |     7 +-
 ogr/ogrsf_frmts/fme/ogrfmedriver.cpp               |     3 +-
 ogr/ogrsf_frmts/fme/ogrfmelayer.cpp                |     6 +-
 ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp          |     3 +-
 ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp              |     5 +-
 ogr/ogrsf_frmts/generic/GNUmakefile                |    12 +-
 ogr/ogrsf_frmts/generic/makefile.vc                |    17 +-
 ogr/ogrsf_frmts/generic/ogr_attrind.cpp            |    26 +-
 ogr/ogrsf_frmts/generic/ogr_gensql.cpp             |   746 +-
 ogr/ogrsf_frmts/generic/ogr_gensql.h               |    53 +-
 ogr/ogrsf_frmts/generic/ogr_miattrind.cpp          |   134 +-
 ogr/ogrsf_frmts/generic/ogrdatasource.cpp          |    10 +-
 ogr/ogrsf_frmts/generic/ogreditablelayer.cpp       |    75 +-
 ogr/ogrsf_frmts/generic/ogreditablelayer.h         |    64 +-
 ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp |   109 +-
 ogr/ogrsf_frmts/generic/ogremulatedtransaction.h   |     3 +-
 ogr/ogrsf_frmts/generic/ogrlayer.cpp               |   197 +-
 ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp      |    16 +-
 ogr/ogrsf_frmts/generic/ogrlayerdecorator.h        |    86 +-
 ogr/ogrsf_frmts/generic/ogrlayerpool.cpp           |    46 +-
 ogr/ogrsf_frmts/generic/ogrlayerpool.h             |    78 +-
 ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp   |    31 +-
 ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h     |    48 +-
 ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp        |    22 +-
 ogr/ogrsf_frmts/generic/ogrmutexedlayer.h          |    84 +-
 ogr/ogrsf_frmts/generic/ogrregisterall.cpp         |    16 +-
 ogr/ogrsf_frmts/generic/ogrsfdriver.cpp            |    12 +-
 ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp   |    12 +-
 ogr/ogrsf_frmts/generic/ogrunionlayer.cpp          |   105 +-
 ogr/ogrsf_frmts/generic/ogrunionlayer.h            |    46 +-
 ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp         |    77 +-
 ogr/ogrsf_frmts/generic/ogrwarpedlayer.h           |    34 +-
 ogr/ogrsf_frmts/geoconcept/geoconcept.c            |   170 +-
 ogr/ogrsf_frmts/geoconcept/geoconcept.h            |     3 +-
 ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c   |    21 +-
 ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h   |     3 +-
 .../geoconcept/ogrgeoconceptdatasource.cpp         |    15 +-
 .../geoconcept/ogrgeoconceptdatasource.h           |    12 +-
 ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp |     4 +-
 ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h   |    12 +-
 ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp  |    42 +-
 ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h    |    26 +-
 ogr/ogrsf_frmts/geojson/drv_geojson.html           |    48 +-
 ogr/ogrsf_frmts/geojson/libjson/json_object.h      |     1 +
 ogr/ogrsf_frmts/geojson/libjson/printbuf.c         |     4 +-
 ogr/ogrsf_frmts/geojson/ogr_geojson.h              |    73 +-
 ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp      |   384 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp   |   403 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp       |   196 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp        |    71 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp       |   683 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h         |    73 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp        |    96 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h          |    11 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp   |   213 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp       |   854 +-
 ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h         |    65 +-
 ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp      |   238 +-
 ogr/ogrsf_frmts/geomedia/ogr_geomedia.h            |    74 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp |    52 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp     |     7 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp      |    49 +-
 .../geomedia/ogrgeomediaselectlayer.cpp            |     8 +-
 ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp |    23 +-
 ogr/ogrsf_frmts/georss/ogr_georss.h                |    59 +-
 ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp     |    47 +-
 ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp         |     3 +-
 ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp          |   482 +-
 ogr/ogrsf_frmts/gft/drv_gft.html                   |     2 +-
 ogr/ogrsf_frmts/gft/ogr_gft.h                      |   102 +-
 ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp           |    60 +-
 ogr/ogrsf_frmts/gft/ogrgftdriver.cpp               |     4 +-
 ogr/ogrsf_frmts/gft/ogrgftlayer.cpp                |    63 +-
 ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp          |    31 +-
 ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp           |   133 +-
 ogr/ogrsf_frmts/gml/GNUmakefile                    |     2 +-
 ogr/ogrsf_frmts/gml/drv_gml.html                   |    35 +-
 ogr/ogrsf_frmts/gml/gfstemplate.cpp                |   133 +-
 ogr/ogrsf_frmts/gml/gmlfeature.cpp                 |   140 +-
 ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp            |   574 +-
 ogr/ogrsf_frmts/gml/gmlhandler.cpp                 |   505 +-
 ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp            |   104 +-
 ogr/ogrsf_frmts/gml/gmlreader.cpp                  |   670 +-
 ogr/ogrsf_frmts/gml/gmlreader.h                    |    18 +-
 ogr/ogrsf_frmts/gml/gmlreaderp.h                   |   148 +-
 ogr/ogrsf_frmts/gml/gmlreadstate.cpp               |    39 +-
 ogr/ogrsf_frmts/gml/gmlregistry.cpp                |    80 +-
 ogr/ogrsf_frmts/gml/gmlregistry.h                  |    15 +-
 ogr/ogrsf_frmts/gml/gmlutils.cpp                   |   266 +-
 ogr/ogrsf_frmts/gml/gmlutils.h                     |    11 +-
 ogr/ogrsf_frmts/gml/hugefileresolver.cpp           |  1637 +--
 ogr/ogrsf_frmts/gml/makefile.vc                    |     2 +-
 ogr/ogrsf_frmts/gml/ogr_gml.h                      |    47 +-
 ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp           |  2255 ++--
 ogr/ogrsf_frmts/gml/ogrgmldriver.cpp               |    24 +-
 ogr/ogrsf_frmts/gml/ogrgmllayer.cpp                |   822 +-
 ogr/ogrsf_frmts/gml/parsexsd.cpp                   |   553 +-
 ogr/ogrsf_frmts/gml/resolvexlinks.cpp              |   480 +-
 ogr/ogrsf_frmts/gml/trstring.cpp                   |   236 -
 ogr/ogrsf_frmts/gmlas/GNUmakefile                  |    17 +
 ogr/ogrsf_frmts/gmlas/drv_gmlas.html               |   351 +
 .../gmlas/drv_gmlas_mapping_examples.html          |   325 +
 .../gmlas/drv_gmlas_metadata_layers.html           |   171 +
 ogr/ogrsf_frmts/gmlas/makefile.vc                  |    18 +
 ogr/ogrsf_frmts/gmlas/ogr_gmlas.h                  |  1555 +++
 ogr/ogrsf_frmts/gmlas/ogr_gmlas_consts.h           |   313 +
 ogr/ogrsf_frmts/gmlas/ogrgmlasconf.cpp             |   674 +
 ogr/ogrsf_frmts/gmlas/ogrgmlasdatasource.cpp       |  1409 +++
 ogr/ogrsf_frmts/gmlas/ogrgmlasdriver.cpp           |   194 +
 ogr/ogrsf_frmts/gmlas/ogrgmlasfeatureclass.cpp     |   199 +
 ogr/ogrsf_frmts/gmlas/ogrgmlaslayer.cpp            |   992 ++
 ogr/ogrsf_frmts/gmlas/ogrgmlasreader.cpp           |  3198 +++++
 ogr/ogrsf_frmts/gmlas/ogrgmlasschemaanalyzer.cpp   |  3584 ++++++
 ogr/ogrsf_frmts/gmlas/ogrgmlaswriter.cpp           |  3161 +++++
 ogr/ogrsf_frmts/gmlas/ogrgmlasxlinkresolver.cpp    |   312 +
 ogr/ogrsf_frmts/gmlas/ogrgmlasxpatchmatcher.cpp    |   236 +
 ogr/ogrsf_frmts/gmlas/ogrgmlasxsdcache.cpp         |   250 +
 ogr/ogrsf_frmts/gmlas/xercesc_headers.h            |    72 +
 ogr/ogrsf_frmts/gmt/ogr_gmt.h                      |    53 +-
 ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp           |     5 +-
 ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp               |     4 +-
 ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp                |    82 +-
 ogr/ogrsf_frmts/gpkg/GNUmakefile                   |     4 +
 ogr/ogrsf_frmts/gpkg/drv_geopackage.html           |    86 +-
 ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html    |    72 +-
 ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp  |  1328 +-
 ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h           |    54 +-
 ogr/ogrsf_frmts/gpkg/ogr_geopackage.h              |   311 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp   |  2049 +++-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp       |   157 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp        |   193 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp  |    28 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp   |  1646 ++-
 ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp      |   374 +-
 ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h        |    41 +-
 ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h            |   205 +-
 ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp |   811 +-
 ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp     |   421 +-
 .../gpsbabel/ogrgpsbabelwritedatasource.cpp        |   498 +-
 ogr/ogrsf_frmts/gpx/ogr_gpx.h                      |    27 +-
 ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp           |    14 +-
 ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp               |     3 +-
 ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp                |   121 +-
 ogr/ogrsf_frmts/grass/ogrgrass.h                   |   137 +-
 ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp       |    75 +-
 ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp           |    33 +-
 ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp            |   886 +-
 ogr/ogrsf_frmts/gtm/gtm.cpp                        |    64 +-
 ogr/ogrsf_frmts/gtm/gtm.h                          |     8 +-
 ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp              |     9 +-
 ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp           |    21 +-
 ogr/ogrsf_frmts/gtm/ogr_gtm.h                      |    56 +-
 ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp           |    47 +-
 ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp               |     5 +-
 ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp                |    12 +-
 ogr/ogrsf_frmts/htf/ogr_htf.h                      |    54 +-
 ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp           |     6 +-
 ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp               |     4 +-
 ogr/ogrsf_frmts/htf/ogrhtflayer.cpp                |    43 +-
 ogr/ogrsf_frmts/idb/drv_idb.html                   |     2 +-
 ogr/ogrsf_frmts/idb/ogr_idb.h                      |    74 +-
 ogr/ogrsf_frmts/idb/ogridbdatasource.cpp           |     4 +-
 ogr/ogrsf_frmts/idb/ogridbdriver.cpp               |     3 +-
 ogr/ogrsf_frmts/idb/ogridblayer.cpp                |    24 +-
 ogr/ogrsf_frmts/idb/ogridbselectlayer.cpp          |     3 +-
 ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp           |    14 +-
 ogr/ogrsf_frmts/idrisi/generate_test_files.c       |     2 +-
 ogr/ogrsf_frmts/idrisi/ogr_idrisi.h                |    54 +-
 ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp     |     5 +-
 ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp         |     5 +-
 ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp          |   139 +-
 ogr/ogrsf_frmts/ili/GNUmakefile                    |     2 +-
 ogr/ogrsf_frmts/ili/ili1reader.cpp                 |    12 +-
 ogr/ogrsf_frmts/ili/ili1reader.h                   |     2 +-
 ogr/ogrsf_frmts/ili/ili1readerp.h                  |    18 +-
 ogr/ogrsf_frmts/ili/ili2handler.cpp                |    31 +-
 ogr/ogrsf_frmts/ili/ili2reader.cpp                 |    95 +-
 ogr/ogrsf_frmts/ili/ili2reader.h                   |     3 +-
 ogr/ogrsf_frmts/ili/ili2readerp.h                  |    38 +-
 ogr/ogrsf_frmts/ili/imdreader.cpp                  |    32 +-
 ogr/ogrsf_frmts/ili/imdreader.h                    |     9 +-
 ogr/ogrsf_frmts/ili/makefile.vc                    |     2 +-
 ogr/ogrsf_frmts/ili/ogr_ili1.h                     |    34 +-
 ogr/ogrsf_frmts/ili/ogr_ili2.h                     |    32 +-
 ogr/ogrsf_frmts/ili/ogrili1datasource.cpp          |     3 +-
 ogr/ogrsf_frmts/ili/ogrili1driver.cpp              |     3 +-
 ogr/ogrsf_frmts/ili/ogrili1layer.cpp               |    30 +-
 ogr/ogrsf_frmts/ili/ogrili2datasource.cpp          |    19 +-
 ogr/ogrsf_frmts/ili/ogrili2driver.cpp              |    15 +-
 ogr/ogrsf_frmts/ili/ogrili2layer.cpp               |    17 +-
 ogr/ogrsf_frmts/ingres/ogr_ingres.h                |    99 +-
 ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp     |   213 +-
 ogr/ogrsf_frmts/ingres/ogringresdriver.cpp         |    19 +-
 ogr/ogrsf_frmts/ingres/ogringreslayer.cpp          |    88 +-
 ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp    |     4 +-
 ogr/ogrsf_frmts/ingres/ogringresstatement.cpp      |    79 +-
 ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp     |   260 +-
 ogr/ogrsf_frmts/jml/ogr_jml.h                      |    32 +-
 ogr/ogrsf_frmts/jml/ogrjmldataset.cpp              |     3 +-
 ogr/ogrsf_frmts/jml/ogrjmllayer.cpp                |    47 +-
 ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp          |    36 +-
 ogr/ogrsf_frmts/kml/drv_kml.html                   |     3 +
 ogr/ogrsf_frmts/kml/kml.cpp                        |    62 +-
 ogr/ogrsf_frmts/kml/kml.h                          |    88 +-
 ogr/ogrsf_frmts/kml/kmlnode.cpp                    |    36 +-
 ogr/ogrsf_frmts/kml/kmlnode.h                      |     3 +-
 ogr/ogrsf_frmts/kml/kmlutility.h                   |    11 +-
 ogr/ogrsf_frmts/kml/kmlvector.cpp                  |     4 +-
 ogr/ogrsf_frmts/kml/kmlvector.h                    |    14 +-
 ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp            |    15 +-
 ogr/ogrsf_frmts/kml/ogr_kml.h                      |    54 +-
 ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp           |   128 +-
 ogr/ogrsf_frmts/kml/ogrkmldriver.cpp               |    17 +-
 ogr/ogrsf_frmts/kml/ogrkmllayer.cpp                |   332 +-
 ogr/ogrsf_frmts/libkml/GNUmakefile                 |     1 -
 ogr/ogrsf_frmts/libkml/drv_libkml.html             |     4 +-
 ogr/ogrsf_frmts/libkml/ogr_libkml.h                |   371 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp     |  1842 ++-
 ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp         |    86 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp        |   781 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h          |    24 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp   |   366 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h     |    10 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp          |  1814 +--
 ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h            |    40 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp       |   868 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h         |    37 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp          |   881 +-
 ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp          |  1414 ++-
 ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h            |    71 +-
 ogr/ogrsf_frmts/makefile.vc                        |    24 +-
 ogr/ogrsf_frmts/mdb/drv_mdb.html                   |     8 +-
 ogr/ogrsf_frmts/mdb/ogr_mdb.h                      |    38 +-
 ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp           |     5 +-
 ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp               |     5 +-
 ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp             |   106 +-
 ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp                |    43 +-
 ogr/ogrsf_frmts/mem/ogr_mem.h                      |    78 +-
 ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp           |    19 +-
 ogr/ogrsf_frmts/mem/ogrmemdriver.cpp               |     7 +-
 ogr/ogrsf_frmts/mem/ogrmemlayer.cpp                |   183 +-
 ogr/ogrsf_frmts/mitab/HISTORY.TXT                  |   216 +-
 ogr/ogrsf_frmts/mitab/README.TXT                   |    54 +-
 ogr/ogrsf_frmts/mitab/TODO.TXT                     |     8 +-
 ogr/ogrsf_frmts/mitab/mitab.h                      |   659 +-
 ogr/ogrsf_frmts/mitab/mitab_bounds.cpp             |   254 +-
 ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp           |   363 +-
 ogr/ogrsf_frmts/mitab/mitab_datfile.cpp            |  1200 +-
 ogr/ogrsf_frmts/mitab/mitab_feature.cpp            |  2167 ++--
 ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp        |   660 +-
 ogr/ogrsf_frmts/mitab/mitab_geometry.cpp           |   181 +-
 ogr/ogrsf_frmts/mitab/mitab_geometry.h             |    11 +-
 ogr/ogrsf_frmts/mitab/mitab_idfile.cpp             |   176 +-
 ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp       |   189 +-
 ogr/ogrsf_frmts/mitab/mitab_indfile.cpp            |   168 +-
 ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp      |   164 +-
 ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp            |   462 +-
 ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp     |   232 +-
 ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp      |   324 +-
 ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp     |   205 +-
 ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp       |    76 +-
 ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp        |   240 +-
 ogr/ogrsf_frmts/mitab/mitab_miffile.cpp            |   406 +-
 ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp     |   345 +-
 ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp         |   135 +-
 ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h           |    61 +-
 ogr/ogrsf_frmts/mitab/mitab_priv.h                 |   323 +-
 ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp        |   184 +-
 ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp         |   302 +-
 ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp            |   354 +-
 ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp        |   108 +-
 ogr/ogrsf_frmts/mitab/mitab_tabview.cpp            |   271 +-
 ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp            |   144 +-
 ogr/ogrsf_frmts/mitab/mitab_utils.cpp              |   440 +-
 ogr/ogrsf_frmts/mitab/mitab_utils.h                |    36 +-
 ogr/ogrsf_frmts/mongodb/drv_mongodb.html           |     6 +-
 ogr/ogrsf_frmts/mongodb/ogrmongodbdriver.cpp       |   179 +-
 ogr/ogrsf_frmts/mssqlspatial/GNUmakefile           |    24 +-
 ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html |     4 +-
 ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h    |   155 +-
 .../mssqlspatial/ogrmssqlgeometryparser.cpp        |     4 +-
 .../mssqlspatial/ogrmssqlgeometryvalidator.cpp     |   985 +-
 .../mssqlspatial/ogrmssqlgeometrywriter.cpp        |    16 +-
 .../mssqlspatial/ogrmssqlspatialdatasource.cpp     |    81 +-
 .../mssqlspatial/ogrmssqlspatialdriver.cpp         |   332 +-
 .../mssqlspatial/ogrmssqlspatiallayer.cpp          |  1273 +-
 .../mssqlspatial/ogrmssqlspatialselectlayer.cpp    |   509 +-
 .../mssqlspatial/ogrmssqlspatialtablelayer.cpp     |   191 +-
 ogr/ogrsf_frmts/mysql/ogr_mysql.h                  |    89 +-
 ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp       |   121 +-
 ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp           |     5 +-
 ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp            |    64 +-
 ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp      |    64 +-
 ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp       |   229 +-
 ogr/ogrsf_frmts/nas/nashandler.cpp                 |   171 +-
 ogr/ogrsf_frmts/nas/nasreader.cpp                  |    97 +-
 ogr/ogrsf_frmts/nas/nasreaderp.h                   |    68 +-
 ogr/ogrsf_frmts/nas/ogr_nas.h                      |    38 +-
 ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp           |     7 +-
 ogr/ogrsf_frmts/nas/ogrnasdriver.cpp               |    16 +-
 ogr/ogrsf_frmts/nas/ogrnaslayer.cpp                |    56 +-
 ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp        |     4 +-
 ogr/ogrsf_frmts/ntf/README.txt                     |    70 +-
 ogr/ogrsf_frmts/ntf/ntf.h                          |    80 +-
 ogr/ogrsf_frmts/ntf/ntf_codelist.cpp               |    28 +-
 ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp              |   103 +-
 ogr/ogrsf_frmts/ntf/ntf_generic.cpp                |   111 +-
 ogr/ogrsf_frmts/ntf/ntf_raster.cpp                 |    72 +-
 ogr/ogrsf_frmts/ntf/ntfdump.cpp                    |    22 +-
 ogr/ogrsf_frmts/ntf/ntffilereader.cpp              |   301 +-
 ogr/ogrsf_frmts/ntf/ntfrecord.cpp                  |    47 +-
 ogr/ogrsf_frmts/ntf/ntfstroke.cpp                  |    91 +-
 ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp           |    78 +-
 ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp               |    10 +-
 ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp    |    21 +-
 ogr/ogrsf_frmts/ntf/ogrntflayer.cpp                |    37 +-
 ogr/ogrsf_frmts/null/ogrnulldriver.cpp             |    61 +-
 ogr/ogrsf_frmts/o/README.TXT                       |     2 +-
 ogr/ogrsf_frmts/oci/GNUmakefile                    |     2 +-
 ogr/ogrsf_frmts/oci/drv_oci.html                   |    23 +-
 ogr/ogrsf_frmts/oci/fastload.cpp                   |    10 +-
 ogr/ogrsf_frmts/oci/oci_utils.cpp                  |     4 +-
 ogr/ogrsf_frmts/oci/ocitest.cpp                    |     4 +-
 ogr/ogrsf_frmts/oci/ogr_oci.h                      |   107 +-
 ogr/ogrsf_frmts/oci/ogrocidatasource.cpp           |    35 +-
 ogr/ogrsf_frmts/oci/ogrocidriver.cpp               |     4 +-
 ogr/ogrsf_frmts/oci/ogrocilayer.cpp                |    10 +-
 ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp          |    18 +-
 ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp          |     3 +-
 ogr/ogrsf_frmts/oci/ogrocisession.cpp              |    23 +-
 ogr/ogrsf_frmts/oci/ogrocistatement.cpp            |     3 +-
 ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp            |     3 +-
 ogr/ogrsf_frmts/oci/ogrocistroke.cpp               |     3 +-
 ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp           |    27 +-
 ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp        |     4 +-
 ogr/ogrsf_frmts/odbc/ogr_odbc.h                    |    80 +-
 ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp         |    64 +-
 ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp             |    12 +-
 ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp              |    42 +-
 ogr/ogrsf_frmts/odbc/ogrodbcselectlayer.cpp        |     8 +-
 ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp         |    36 +-
 ogr/ogrsf_frmts/ods/ods_formula.cpp                |     3 +-
 ogr/ogrsf_frmts/ods/ods_formula.h                  |    53 +-
 ogr/ogrsf_frmts/ods/ods_formula_node.cpp           |   268 +-
 ogr/ogrsf_frmts/ods/ods_formula_parser.cpp         |     4 -
 ogr/ogrsf_frmts/ods/ods_formula_parser.y           |     3 +-
 ogr/ogrsf_frmts/ods/ogr_ods.h                      |    66 +-
 ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp           |   249 +-
 ogr/ogrsf_frmts/ods/ogrodsdriver.cpp               |     4 +-
 ogr/ogrsf_frmts/ods/testparser.cpp                 |     1 -
 ogr/ogrsf_frmts/ogdi/drv_ogdi.html                 |    12 +
 ogr/ogrsf_frmts/ogdi/ogrogdi.h                     |    40 +-
 ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp         |   276 +-
 ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp             |    30 +-
 ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp              |   138 +-
 ogr/ogrsf_frmts/ogr_attrind.h                      |     5 +-
 ogr/ogrsf_frmts/ogr_formats.html                   |    23 +-
 ogr/ogrsf_frmts/ogrsf_frmts.dox                    |   752 +-
 ogr/ogrsf_frmts/ogrsf_frmts.h                      |    37 +-
 ogr/ogrsf_frmts/openair/ogr_openair.h              |    37 +-
 ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp   |     6 +-
 ogr/ogrsf_frmts/openair/ogropenairdriver.cpp       |     4 +-
 ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp   |    15 +-
 ogr/ogrsf_frmts/openair/ogropenairlayer.cpp        |    65 +-
 ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html   |    13 +-
 ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp       |   190 +-
 ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp       |   492 +-
 ogr/ogrsf_frmts/openfilegdb/filegdbtable.h         |    13 +-
 ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h      |    49 +-
 .../openfilegdb/ogropenfilegdbdatasource.cpp       |   108 +-
 .../openfilegdb/ogropenfilegdbdriver.cpp           |    17 +-
 .../openfilegdb/ogropenfilegdblayer.cpp            |   268 +-
 ogr/ogrsf_frmts/osm/drv_osm.html                   |    27 +-
 ogr/ogrsf_frmts/osm/ogr_osm.h                      |    70 +-
 ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp           |   833 +-
 ogr/ogrsf_frmts/osm/ogrosmdriver.cpp               |     8 +-
 ogr/ogrsf_frmts/osm/ogrosmlayer.cpp                |   201 +-
 ogr/ogrsf_frmts/osm/osm_parser.cpp                 |   966 +-
 ogr/ogrsf_frmts/pds/ogr_pds.h                      |    35 +-
 ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp           |    44 +-
 ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp               |     5 +-
 ogr/ogrsf_frmts/pds/ogrpdslayer.cpp                |    84 +-
 ogr/ogrsf_frmts/pg/drv_pg.html                     |    12 +-
 ogr/ogrsf_frmts/pg/ogr_pg.h                        |   150 +-
 ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp             |   269 +-
 ogr/ogrsf_frmts/pg/ogrpgdriver.cpp                 |    12 +-
 ogr/ogrsf_frmts/pg/ogrpglayer.cpp                  |   354 +-
 ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp            |    45 +-
 ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp             |   316 +-
 ogr/ogrsf_frmts/pg/ogrpgutility.cpp                |    20 +-
 ogr/ogrsf_frmts/pg/ogrpgutility.h                  |     2 +-
 ogr/ogrsf_frmts/pgdump/ogr_pgdump.h                |   445 +-
 ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp     |  1380 ++-
 ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp         |   277 +-
 ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp          |  3671 +++---
 ogr/ogrsf_frmts/pgeo/ogr_pgeo.h                    |    76 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp         |    12 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp             |     8 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp              |    45 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp        |    12 +-
 ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp         |    20 +-
 ogr/ogrsf_frmts/plscenes/GNUmakefile               |     3 +-
 ogr/ogrsf_frmts/plscenes/drv_plscenes.html         |   508 +-
 ogr/ogrsf_frmts/plscenes/drv_plscenes_data_v1.html |   199 +
 ogr/ogrsf_frmts/plscenes/drv_plscenes_v0.html      |   202 +
 ogr/ogrsf_frmts/plscenes/drv_plscenes_v1.html      |   469 +
 ogr/ogrsf_frmts/plscenes/makefile.vc               |     4 +-
 ogr/ogrsf_frmts/plscenes/ogr_plscenes.h            |   213 +-
 ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp    |    83 +-
 .../plscenes/ogrplscenesdatav1dataset.cpp          |   812 ++
 .../plscenes/ogrplscenesdatav1layer.cpp            |  1319 ++
 ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp     |    22 +-
 ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp      |   125 +-
 ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp  |   111 +-
 ogr/ogrsf_frmts/plscenes/ogrplscenesv1layer.cpp    |   156 +-
 ogr/ogrsf_frmts/rec/ll_recio.cpp                   |    27 +-
 ogr/ogrsf_frmts/rec/ogr_rec.h                      |    20 +-
 ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp           |     3 +-
 ogr/ogrsf_frmts/rec/ogrrecdriver.cpp               |     4 +-
 ogr/ogrsf_frmts/rec/ogrreclayer.cpp                |     6 +-
 ogr/ogrsf_frmts/s57/ddfrecordindex.cpp             |     9 +-
 ogr/ogrsf_frmts/s57/ogr_s57.h                      |    30 +-
 ogr/ogrsf_frmts/s57/ogrs57datasource.cpp           |    31 +-
 ogr/ogrsf_frmts/s57/ogrs57driver.cpp               |     5 +-
 ogr/ogrsf_frmts/s57/ogrs57layer.cpp                |     7 +-
 ogr/ogrsf_frmts/s57/s57.h                          |    68 +-
 ogr/ogrsf_frmts/s57/s57classregistrar.cpp          |   103 +-
 ogr/ogrsf_frmts/s57/s57dump.cpp                    |     8 +-
 ogr/ogrsf_frmts/s57/s57featuredefns.cpp            |     7 +-
 ogr/ogrsf_frmts/s57/s57filecollector.cpp           |     4 +-
 ogr/ogrsf_frmts/s57/s57reader.cpp                  |   281 +-
 ogr/ogrsf_frmts/s57/s57tables.h                    |     2 +-
 ogr/ogrsf_frmts/s57/s57writer.cpp                  |   227 +-
 ogr/ogrsf_frmts/sde/ogr_sde.h                      |    55 +-
 ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp           |    41 +-
 ogr/ogrsf_frmts/sde/ogrsdedriver.cpp               |     3 +-
 ogr/ogrsf_frmts/sde/ogrsdelayer.cpp                |    48 +-
 ogr/ogrsf_frmts/sdts/GNUmakefile                   |     2 +-
 ogr/ogrsf_frmts/sdts/ogr_sdts.h                    |    25 +-
 ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp         |    43 +-
 ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp             |     3 +-
 ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp              |   132 +-
 ogr/ogrsf_frmts/segukooa/ogr_segukooa.h            |    40 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp |    19 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp     |     4 +-
 ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp      |   176 +-
 ogr/ogrsf_frmts/segy/ogr_segy.h                    |    48 +-
 ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp         |   101 +-
 ogr/ogrsf_frmts/segy/ogrsegydriver.cpp             |    90 +-
 ogr/ogrsf_frmts/segy/ogrsegylayer.cpp              |   783 +-
 ogr/ogrsf_frmts/selafin/GNUmakefile                |     2 +-
 ogr/ogrsf_frmts/selafin/io_selafin.cpp             |   103 +-
 ogr/ogrsf_frmts/selafin/io_selafin.h               |   622 +-
 ogr/ogrsf_frmts/selafin/ogr_selafin.h              |    60 +-
 ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp   |   117 +-
 ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp       |    13 +-
 ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp        |   127 +-
 ogr/ogrsf_frmts/shape/{LICENSE.LGPL => COPYING}    |     0
 ogr/ogrsf_frmts/shape/dbfopen.c                    |   292 +-
 ogr/ogrsf_frmts/shape/drv_shapefile.html           |    27 +-
 ogr/ogrsf_frmts/shape/ogrshape.h                   |   196 +-
 ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp       |   520 +-
 ogr/ogrsf_frmts/shape/ogrshapedriver.cpp           |   102 +-
 ogr/ogrsf_frmts/shape/ogrshapelayer.cpp            |  1226 +-
 ogr/ogrsf_frmts/shape/sbnsearch.c                  |    25 +-
 ogr/ogrsf_frmts/shape/shape2ogr.cpp                |  1262 +-
 ogr/ogrsf_frmts/shape/shapefil.h                   |   314 +-
 ogr/ogrsf_frmts/shape/shp_vsi.c                    |     7 +-
 ogr/ogrsf_frmts/shape/shpopen.c                    |   190 +-
 ogr/ogrsf_frmts/shape/shptree.c                    |     7 +-
 ogr/ogrsf_frmts/sosi/GNUmakefile                   |     2 +-
 ogr/ogrsf_frmts/sosi/fyba_melding.cpp              |   135 +-
 ogr/ogrsf_frmts/sosi/ogr_sosi.h                    |    33 +-
 ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp         |    66 +-
 ogr/ogrsf_frmts/sosi/ogrsosidatatypes.cpp          |     9 +-
 ogr/ogrsf_frmts/sosi/ogrsosidatatypes.h            |  3960 +++---
 ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp             |     3 +-
 ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp              |    34 +-
 ogr/ogrsf_frmts/sosi/tools/README                  |     2 +-
 ogr/ogrsf_frmts/sosi/tools/groupelements.xslt      |     4 +-
 ogr/ogrsf_frmts/sqlite/GNUmakefile                 |     7 +-
 ogr/ogrsf_frmts/sqlite/drv_sqlite.html             |    24 +-
 ogr/ogrsf_frmts/sqlite/frmt_rasterlite2.html       |   137 +
 ogr/ogrsf_frmts/sqlite/makefile.vc                 |     3 +-
 ogr/ogrsf_frmts/sqlite/ogr_sqlite.h                |   364 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h             |     2 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c      |    25 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp     |  1098 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp         |   112 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp     |   138 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h       |     4 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp          |   736 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp         |    46 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp    |    80 +-
 .../sqlite/ogrsqlitesinglefeaturelayer.cpp         |    29 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp   |   121 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp     |  1104 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteutility.cpp        |   332 +
 ogr/ogrsf_frmts/sqlite/ogrsqliteutility.h          |    70 +
 ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp            |    19 +-
 ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp      |   115 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp     |   264 +-
 ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h       |     6 +-
 ogr/ogrsf_frmts/sqlite/rasterlite2.cpp             |  2464 ++++
 ogr/ogrsf_frmts/sqlite/rasterlite2_header.h        |    49 +
 ogr/ogrsf_frmts/sua/ogr_sua.h                      |    29 +-
 ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp           |    16 +-
 ogr/ogrsf_frmts/sua/ogrsuadriver.cpp               |     4 +-
 ogr/ogrsf_frmts/sua/ogrsualayer.cpp                |   130 +-
 ogr/ogrsf_frmts/svg/ogr_svg.h                      |    37 +-
 ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp           |    17 +-
 ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp               |     6 +-
 ogr/ogrsf_frmts/svg/ogrsvglayer.cpp                |   142 +-
 ogr/ogrsf_frmts/sxf/ogr_sxf.h                      |    60 +-
 ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp           |   397 +-
 ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp               |    14 +-
 ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp                |   234 +-
 ogr/ogrsf_frmts/sxf/org_sxf_defs.h                 |     5 +-
 ogr/ogrsf_frmts/tiger/GNUmakefile                  |     8 -
 ogr/ogrsf_frmts/tiger/ogr_tiger.h                  |   114 +-
 ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp       |    85 +-
 ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp           |    14 +-
 ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp            |    28 +-
 ogr/ogrsf_frmts/tiger/tigeraltname.cpp             |    21 +-
 ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp       |     6 +-
 ogr/ogrsf_frmts/tiger/tigercompletechain.cpp       |   111 +-
 ogr/ogrsf_frmts/tiger/tigerentitynames.cpp         |     6 +-
 ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp          |     5 +-
 ogr/ogrsf_frmts/tiger/tigerfilebase.cpp            |   124 +-
 ogr/ogrsf_frmts/tiger/tigeridhistory.cpp           |     5 +-
 ogr/ogrsf_frmts/tiger/tigerinfo.cpp                |   235 -
 ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp         |     6 +-
 ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp           |     5 +-
 ogr/ogrsf_frmts/tiger/tigeroverunder.cpp           |     7 +-
 ogr/ogrsf_frmts/tiger/tigerpip.cpp                 |     6 +-
 ogr/ogrsf_frmts/tiger/tigerpoint.cpp               |    19 +-
 ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp       |     6 +-
 ogr/ogrsf_frmts/tiger/tigerpolygon.cpp             |    45 +-
 ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp  |    11 +-
 ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp     |     5 +-
 ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp     |     5 +-
 ogr/ogrsf_frmts/tiger/tigertlidrange.cpp           |     6 +-
 ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp          |     6 +-
 ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp            |     5 +-
 ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp            |     7 +-
 ogr/ogrsf_frmts/vdv/ogr_vdv.h                      |    50 +-
 ogr/ogrsf_frmts/vdv/ogrvdvdatasource.cpp           |    65 +-
 ogr/ogrsf_frmts/vfk/drv_vfk.html                   |    67 +-
 ogr/ogrsf_frmts/vfk/ogr_vfk.h                      |    27 +-
 ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp           |    95 +-
 ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp               |    36 +-
 ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp                |    49 +-
 ogr/ogrsf_frmts/vfk/vfkdatablock.cpp               |   178 +-
 ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp         |   817 +-
 ogr/ogrsf_frmts/vfk/vfkfeature.cpp                 |   361 +-
 ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp           |    80 +-
 ogr/ogrsf_frmts/vfk/vfkproperty.cpp                |    88 +-
 ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp            |    56 +-
 ogr/ogrsf_frmts/vfk/vfkreader.cpp                  |   147 +-
 ogr/ogrsf_frmts/vfk/vfkreader.h                    |    83 +-
 ogr/ogrsf_frmts/vfk/vfkreaderp.h                   |    63 +-
 ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp            |   495 +-
 ogr/ogrsf_frmts/vrt/ogr_vrt.h                      |   187 +-
 ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp           |   121 +-
 ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp               |     5 +-
 ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp                |   314 +-
 ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h    |    24 +-
 ogr/ogrsf_frmts/walk/ogrwalk.h                     |    72 +-
 ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp         |    20 +-
 ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp             |     3 +-
 ogr/ogrsf_frmts/walk/ogrwalklayer.cpp              |    47 +-
 ogr/ogrsf_frmts/walk/ogrwalkselectlayer.cpp        |     9 +-
 ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp         |    27 +-
 ogr/ogrsf_frmts/walk/ogrwalktool.cpp               |   158 +-
 ogr/ogrsf_frmts/wasp/ogrwasp.h                     |    47 +-
 ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp         |    19 +-
 ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp             |     2 +
 ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp              |   102 +-
 ogr/ogrsf_frmts/wfs/drv_wfs.html                   |    15 +-
 ogr/ogrsf_frmts/wfs/ogr_wfs.h                      |   229 +-
 ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp           |   556 +-
 ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp               |     4 +-
 ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp               |   202 +-
 ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp            |   105 +-
 ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp                |   468 +-
 ogr/ogrsf_frmts/xls/ogr_xls.h                      |    43 +-
 ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp           |    21 +-
 ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp               |     4 +-
 ogr/ogrsf_frmts/xls/ogrxlslayer.cpp                |    67 +-
 ogr/ogrsf_frmts/xlsx/ogr_xlsx.h                    |   104 +-
 ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp         |   409 +-
 ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp             |    17 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane.h                |    41 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp   |   429 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h     |    56 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp   |    74 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h     |    15 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp   |    33 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h     |    11 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp    |   108 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h      |     3 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp   |   146 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h     |    20 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp       |   148 +-
 ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h         |    29 +-
 ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp     |    33 +-
 ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp         |     7 +-
 ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp          |   106 +-
 ogr/ogrsf_frmts/xplane/test_geo_utils.cpp          |    19 +-
 ogr/ogrspatialreference.cpp                        |   513 +-
 ogr/ogrsurface.cpp                                 |    13 +-
 ogr/ogrtriangle.cpp                                |   277 +
 ogr/ogrtriangulatedsurface.cpp                     |   276 +
 ogr/ogrutils.cpp                                   |  1020 +-
 ogr/osr_cs_wkt.c                                   |     8 +-
 ogr/osr_cs_wkt.h                                   |     6 +-
 ogr/osr_cs_wkt_parser.h                            |     2 -
 ogr/osr_tutorial.dox                               |   122 +-
 ogr/swq.cpp                                        |   484 +-
 ogr/swq.h                                          |    46 +-
 ogr/swq_expr_node.cpp                              |   147 +-
 ogr/swq_op_general.cpp                             |   384 +-
 ogr/swq_op_registrar.cpp                           |    35 +-
 ogr/swq_parser.cpp                                 |   917 +-
 ogr/swq_parser.hpp                                 |    20 +-
 ogr/swq_parser.y                                   |   138 +-
 ogr/swq_select.cpp                                 |   276 +-
 port/GNUmakefile                                   |     5 +-
 port/cpl_atomic_ops.cpp                            |    43 +-
 port/cpl_atomic_ops.h                              |     9 +-
 port/cpl_aws.cpp                                   |   361 +-
 port/cpl_aws.h                                     |    16 +-
 port/cpl_base64.cpp                                |   139 +-
 port/cpl_config.h.in                               |    16 +
 port/cpl_config.h.vc                               |     2 +-
 port/cpl_config_extras.h                           |     4 +-
 port/cpl_conv.cpp                                  |  1304 +-
 port/cpl_conv.h                                    |    44 +-
 port/cpl_cpu_features.cpp                          |   214 +
 port/cpl_cpu_features.h                            |    73 +
 port/cpl_csv.cpp                                   |   140 +-
 port/cpl_csv.h                                     |     4 +-
 port/cpl_error.cpp                                 |   198 +-
 port/cpl_error.h                                   |    49 +-
 port/cpl_findfile.cpp                              |    68 +-
 port/cpl_getexecpath.cpp                           |    22 +-
 port/cpl_google_cloud.cpp                          |   180 +
 port/cpl_google_cloud.h                            |    70 +
 port/cpl_google_oauth2.cpp                         |   122 +-
 port/cpl_hash_set.cpp                              |   219 +-
 port/cpl_hash_set.h                                |     7 +-
 port/cpl_http.cpp                                  |   538 +-
 port/cpl_http.h                                    |    11 +-
 port/cpl_list.cpp                                  |    69 +-
 port/cpl_list.h                                    |     9 +-
 port/cpl_minixml.cpp                               |   538 +-
 port/cpl_minixml.h                                 |    18 +-
 port/cpl_minizip_ioapi.cpp                         |    51 +-
 port/cpl_minizip_ioapi.h                           |     9 +-
 port/cpl_minizip_unzip.cpp                         |   165 +-
 port/cpl_minizip_unzip.h                           |    19 +-
 port/cpl_minizip_zip.cpp                           |   154 +-
 port/cpl_minizip_zip.h                             |    12 +-
 port/cpl_multiproc.cpp                             |   703 +-
 port/cpl_multiproc.h                               |    20 +-
 port/cpl_odbc.cpp                                  |   479 +-
 port/cpl_odbc.h                                    |    48 +-
 port/cpl_path.cpp                                  |   234 +-
 port/cpl_port.h                                    |   388 +-
 port/cpl_progress.cpp                              |    20 +-
 port/cpl_progress.h                                |     2 +-
 port/cpl_quad_tree.cpp                             |   371 +-
 port/cpl_quad_tree.h                               |    12 +-
 port/cpl_recode.cpp                                |    79 +-
 port/cpl_recode_iconv.cpp                          |    88 +-
 port/cpl_recode_stub.cpp                           |   965 +-
 port/cpl_sha1.cpp                                  |   253 +
 port/cpl_sha1.h                                    |    53 +
 port/cpl_sha256.cpp                                |   264 +-
 port/cpl_sha256.h                                  |     6 +-
 port/cpl_spawn.cpp                                 |   479 +-
 port/cpl_string.cpp                                |   795 +-
 port/cpl_string.h                                  |   209 +-
 port/cpl_strtod.cpp                                |    94 +-
 port/cpl_time.cpp                                  |    99 +-
 port/cpl_time.h                                    |     2 +-
 port/cpl_virtualmem.cpp                            |   629 +-
 port/cpl_virtualmem.h                              |     7 +-
 port/cpl_vsi.h                                     |    83 +-
 port/cpl_vsi_error.cpp                             |   133 +-
 port/cpl_vsi_error.h                               |     9 +-
 port/cpl_vsi_mem.cpp                               |   329 +-
 port/cpl_vsi_virtual.h                             |    45 +-
 port/cpl_vsil.cpp                                  |   505 +-
 port/cpl_vsil_abstract_archive.cpp                 |   613 +-
 port/cpl_vsil_buffered_reader.cpp                  |   271 +-
 port/cpl_vsil_cache.cpp                            |   171 +-
 port/cpl_vsil_crypt.cpp                            |  1002 +-
 port/cpl_vsil_curl.cpp                             |  2876 +++--
 port/cpl_vsil_curl_priv.h                          |    28 +-
 port/cpl_vsil_curl_streaming.cpp                   |  1113 +-
 port/cpl_vsil_gzip.cpp                             |  1447 ++-
 port/cpl_vsil_simple.cpp                           |     7 +-
 port/cpl_vsil_sparsefile.cpp                       |   165 +-
 port/cpl_vsil_stdin.cpp                            |   144 +-
 port/cpl_vsil_stdout.cpp                           |   108 +-
 port/cpl_vsil_subfile.cpp                          |   178 +-
 port/cpl_vsil_tar.cpp                              |   131 +-
 port/cpl_vsil_unix_stdio_64.cpp                    |   292 +-
 port/cpl_vsil_win32.cpp                            |   196 +-
 port/cpl_vsisimple.cpp                             |   598 +-
 port/cpl_worker_thread_pool.cpp                    |   120 +-
 port/cpl_worker_thread_pool.h                      |     8 +-
 port/cpl_xml_validate.cpp                          |   803 +-
 port/cplgetsymbol.cpp                              |    43 +-
 port/cplkeywordparser.cpp                          |    64 +-
 port/cplkeywordparser.h                            |     6 +-
 port/cplstring.cpp                                 |   137 +-
 port/cplstringlist.cpp                             |    59 +-
 port/makefile.vc                                   |    19 +-
 port/vsipreload.cpp                                |   499 +-
 port/xmlreformat.cpp                               |    23 +-
 scripts/clang-format                               |    67 +
 scripts/completionFinder.py                        |    39 +-
 scripts/cppcheck.sh                                |   489 +
 scripts/detect_printf.sh                           |    26 +
 scripts/detect_self_assignment.py                  |    26 +
 scripts/detect_self_assignment.sh                  |    17 +
 scripts/detect_tabulations.sh                      |    15 +
 scripts/fix_container_dot_size_zero.py             |   157 +
 scripts/fix_container_dot_size_zero.sh             |     3 +
 scripts/fix_typos.sh                               |    13 +-
 scripts/gdal-bash-completion.sh                    |    31 +-
 scripts/typos_whitelist.txt                        |    30 +-
 scripts/vagrant/gdal.sh                            |     4 +-
 scripts/vagrant/libkml.sh                          |     2 +-
 scripts/vagrant/openjpeg.sh                        |     4 +-
 scripts/vagrant/sfcgal.sh                          |    15 +
 scripts/vagrant/swig-1.3.40.sh                     |     4 +-
 swig/SWIGmake.base                                 |    10 +-
 swig/csharp/apps/GDALAdjustContrast.cs             |    20 +-
 swig/csharp/apps/GDALColorTable.cs                 |    22 +-
 swig/csharp/apps/GDALCreateCopy.cs                 |    34 +-
 swig/csharp/apps/GDALInfo.cs                       |    36 +-
 swig/csharp/apps/GDALMemDataset.cs                 |    12 +-
 swig/csharp/apps/GDALOverviews.cs                  |    36 +-
 swig/csharp/apps/GDALRead.cs                       |    80 +-
 swig/csharp/apps/GDALReadDirect.cs                 |    82 +-
 swig/csharp/apps/GDALWrite.cs                      |    32 +-
 swig/csharp/apps/OGRGEOS.cs                        |     8 +-
 swig/csharp/apps/OGRLayerAlg.cs                    |    30 +-
 swig/csharp/apps/OSRTransform.cs                   |     4 +-
 swig/csharp/apps/ReadXML.cs                        |    14 +-
 swig/csharp/apps/VSIMem.cs                         |    12 +-
 swig/csharp/apps/WKT2WKB.cs                        |    18 +-
 swig/csharp/apps/createdata.cs                     |    42 +-
 swig/csharp/apps/ogrinfo.cs                        |    40 +-
 swig/csharp/const/GdalConst.cs                     |     3 +
 swig/csharp/const/GdalConstPINVOKE.cs              |     9 +
 swig/csharp/const/gdalconst_wrap.c                 |    30 +
 swig/csharp/gdal/Gdal.cs                           |    14 +
 swig/csharp/gdal/GdalPINVOKE.cs                    |     6 +
 swig/csharp/gdal/gdal_wrap.cpp                     |   131 +
 swig/csharp/ogr/Feature.cs                         |    34 +
 swig/csharp/ogr/Geometry.cs                        |     6 +
 swig/csharp/ogr/Ogr.cs                             |     2 +
 swig/csharp/ogr/OgrPINVOKE.cs                      |    27 +
 swig/csharp/ogr/OsrPINVOKE.cs                      |     3 +
 swig/csharp/ogr/SpatialReference.cs                |     6 +
 swig/csharp/ogr/ogr_wrap.cpp                       |   340 +
 swig/csharp/ogr/osr_wrap.cpp                       |    39 +
 swig/csharp/ogr/wkbGeometryType.cs                 |     4 +
 swig/csharp/osr/OsrPINVOKE.cs                      |     3 +
 swig/csharp/osr/SpatialReference.cs                |     6 +
 swig/csharp/osr/osr_wrap.cpp                       |    39 +
 swig/include/Band.i                                |    29 +-
 swig/include/ColorTable.i                          |     2 +-
 swig/include/Dataset.i                             |    47 +-
 swig/include/Driver.i                              |     2 +-
 swig/include/MajorObject.i                         |     2 +-
 swig/include/Operations.i                          |    30 +-
 swig/include/README.typemaps                       |    12 +-
 swig/include/RasterAttributeTable.i                |     2 +-
 swig/include/Transform.i                           |     2 +-
 swig/include/XMLNode.i                             |     2 +-
 swig/include/cpl.i                                 |    50 +-
 swig/include/cpl_exceptions.i                      |     2 +-
 swig/include/csharp/gdal_csharp.i                  |     2 +-
 swig/include/csharp/gdal_csharp_extend.i           |     2 +-
 swig/include/csharp/gnm_csharp.i                   |    14 +
 swig/include/csharp/ogr_csharp.i                   |     2 +-
 swig/include/csharp/ogr_csharp_extend.i            |     2 +-
 swig/include/csharp/osr_csharp.i                   |     2 +-
 swig/include/csharp/swig_csharp_extensions.i       |     2 +-
 swig/include/csharp/typemaps_csharp.i              |     2 +-
 swig/include/gdal.i                                |    28 +-
 swig/include/gdal_array.i                          |   129 +-
 swig/include/gdal_typemaps.i                       |     2 +-
 swig/include/gdalconst.i                           |    14 +-
 swig/include/gnm.i                                 |    71 +-
 swig/include/java/gdal_java.i                      |     5 +-
 swig/include/java/gdalconst_java.i                 |     2 +-
 swig/include/java/gnm_java.i                       |   130 +
 swig/include/java/ogr_java.i                       |     2 +-
 swig/include/java/ogr_java_extend.i                |     2 +-
 swig/include/java/osr_java.i                       |     2 +-
 swig/include/java/typemaps_java.i                  |     4 +-
 swig/include/ogr.i                                 |   270 +-
 swig/include/ogr_error_map.i                       |     2 +-
 swig/include/osr.i                                 |    16 +-
 swig/include/perl/band.i                           |   422 +
 swig/include/perl/confess.i                        |     2 +
 swig/include/perl/destroy.i                        |     2 +-
 swig/include/perl/gdal_perl.i                      |   819 +-
 swig/include/perl/gnm_perl.i                       |    30 +
 swig/include/perl/init.i                           |    48 +
 swig/include/perl/ogr_perl.i                       |   661 +-
 swig/include/perl/osr_perl.i                       |    18 +-
 swig/include/perl/typemaps_perl.i                  |    46 +-
 swig/include/php/gdal_php.i                        |     2 +-
 swig/include/php/gnm_php.i                         |    13 +
 swig/include/php/ogr_php.i                         |     2 +-
 swig/include/php/typemaps_php.i                    |     2 +-
 swig/include/python/callback.i                     |     9 +-
 swig/include/python/docs/doxy2swig.py              |    10 +-
 swig/include/python/docs/ogr_geometry_docs.i       |     6 +-
 swig/include/python/docs/ogr_layer_docs.i          |     5 +-
 swig/include/python/gdal_python.i                  |    88 +-
 swig/include/python/gnm_python.i                   |    39 +
 swig/include/python/ogr_python.i                   |    11 +-
 swig/include/python/osr_python.i                   |     2 +-
 swig/include/python/typemaps_python.i              |   133 +-
 swig/include/ruby/gdal_ruby.i                      |     2 +-
 swig/include/ruby/gnm_ruby.i                       |    28 +
 swig/include/ruby/ogr_ruby.i                       |     2 +-
 swig/include/ruby/typemaps_ruby.i                  |     2 +-
 swig/java/GNUmakefile                              |    12 +-
 swig/java/add_javadoc.c                            |    26 +-
 swig/java/apps/GDALContour.java                    |    26 +-
 swig/java/apps/GDALGrid.java                       |  1846 +--
 swig/java/apps/GDALOverviews.java                  |    18 +-
 swig/java/apps/GDALProximity.java                  |     6 +-
 swig/java/apps/GDALTestIO.java                     |   406 +-
 swig/java/apps/GDALtest.java                       |    62 +-
 swig/java/apps/OGRFeature.java                     |   272 +-
 swig/java/apps/OGRTestGC.java                      |   206 +-
 swig/java/apps/OSRTransform.java                   |     6 +-
 swig/java/apps/ReadXML.java                        |     6 +-
 swig/java/apps/WKT2WKB.java                        |     8 +-
 swig/java/apps/gdalinfo.java                       |     8 +-
 swig/java/apps/ogr2ogr.java                        |    42 +-
 swig/java/apps/ogrinfo.java                        |     2 +-
 swig/java/apps/ogrtindex.java                      |  1158 +-
 swig/java/javadoc.java                             |  1564 +--
 swig/makefile.vc                                   |     5 +-
 swig/perl/Changes-in-the-API-in-2.0                |     2 +-
 swig/perl/Doxyfile                                 |     8 +-
 swig/perl/GNUmakefile                              |     2 +
 swig/perl/MANIFEST                                 |    41 -
 swig/perl/Makefile.PL                              |   445 +-
 swig/perl/README                                   |    68 +-
 swig/perl/cv.dox                                   |    10 +-
 swig/perl/gdal_wrap.cpp                            |  1959 ++-
 swig/perl/gdalconst_wrap.c                         |    15 +
 swig/perl/gnm_wrap.cpp                             |  1848 +--
 swig/perl/index.dox                                |    52 +-
 swig/perl/lib/Geo/GDAL.dox                         |   339 +-
 swig/perl/lib/Geo/GDAL.pm                          |   853 +-
 swig/perl/lib/Geo/GDAL/Const.pm                    |     3 +
 swig/perl/lib/Geo/GNM.dox                          |     6 +-
 swig/perl/lib/Geo/GNM.pm                           |    40 +-
 swig/perl/lib/Geo/OGR.dox                          |   133 +-
 swig/perl/lib/Geo/OGR.pm                           |   685 +-
 swig/perl/lib/Geo/OSR.dox                          |     9 +-
 swig/perl/lib/Geo/OSR.pm                           |    19 +-
 swig/perl/ogr_wrap.cpp                             |  7739 +++---------
 swig/perl/osr_wrap.cpp                             |   180 +-
 swig/perl/parse-for-doxygen.pl                     |     9 +-
 swig/perl/pdl.dox                                  |    98 +-
 swig/perl/rv.dox                                   |     4 +-
 swig/perl/t/00-measures-00.t                       |     6 +-
 swig/perl/t/00-measures-03.t                       |    27 +-
 swig/perl/t/00-measures-04.t                       |    10 +-
 swig/perl/t/00.t                                   |    28 +-
 swig/perl/t/01.t                                   |     4 +-
 swig/perl/t/alg.t                                  |    61 +-
 swig/perl/t/band.t                                 |   105 +
 swig/perl/t/dataset.t                              |    32 +
 swig/perl/t/extent.t                               |    83 +
 swig/perl/t/feature.t                              |   121 +-
 swig/perl/t/geotransform.t                         |    53 +
 swig/perl/t/osr.t                                  |     6 +-
 swig/perl/t/pdl.t                                  |    32 +
 swig/perl/t/utf8.t                                 |     2 +-
 swig/perl/t/util.t                                 |    44 -
 swig/perl/tips.dox                                 |    75 +
 swig/perl/transform.dox                            |     4 +-
 swig/php/GNUmakefile                               |     2 +-
 swig/php/gdal.php                                  |     8 +-
 swig/php/gdalconst.php                             |     8 +-
 swig/php/ogr.php                                   |     8 +-
 swig/php/osr.php                                   |     8 +-
 swig/php/php_gdal.h                                |     8 +-
 swig/php/php_gdalconst.h                           |     8 +-
 swig/php/php_ogr.h                                 |     8 +-
 swig/php/php_osr.h                                 |     8 +-
 swig/python/GNUmakefile                            |    14 +-
 swig/python/README.txt                             |     2 +-
 swig/python/extensions/gdal_array_wrap.cpp         |   456 +-
 swig/python/extensions/gdal_wrap.cpp               |  4172 +++++--
 swig/python/extensions/gdalconst_wrap.c            |  2422 +++-
 swig/python/extensions/gnm_wrap.cpp                |  1794 ++-
 swig/python/extensions/ogr_wrap.cpp                |  5351 ++++++--
 swig/python/extensions/osr_wrap.cpp                |  3384 +++++-
 swig/python/fallback_build.bat                     |     8 +-
 swig/python/osgeo/gdal.py                          |  1378 ++-
 swig/python/osgeo/gdal_array.py                    |   174 +-
 swig/python/osgeo/gdalconst.py                     |   342 +-
 swig/python/osgeo/gnm.py                           |   190 +-
 swig/python/osgeo/ogr.py                           |  1069 +-
 swig/python/osgeo/osr.py                           |   619 +-
 swig/python/python3.2.patch                        |    88 -
 swig/python/samples/README                         |    12 +-
 swig/python/samples/ogr2vrt.py                     |     7 +-
 .../samples/validate_cloud_optimized_geotiff.py    |   194 +
 swig/python/samples/validate_gpkg.py               |  1554 +++
 swig/python/samples/validate_jp2.py                |    15 +-
 swig/python/scripts/gdal2tiles.py                  |  1006 +-
 swig/python/scripts/gdal2xyz.py                    |     2 +-
 swig/python/scripts/gdal_calc.dox                  |    46 +-
 swig/python/scripts/gdal_calc.py                   |   164 +-
 swig/python/scripts/gdal_edit.dox                  |    43 +-
 swig/python/scripts/gdal_edit.py                   |    23 +-
 swig/python/scripts/gdal_fillnodata.dox            |    23 +-
 swig/python/scripts/gdal_polygonize.dox            |    34 +-
 swig/python/scripts/gdal_polygonize.py             |    20 +-
 swig/python/scripts/gdal_proximity.dox             |    19 +-
 swig/python/scripts/gdal_retile.py                 |    99 +-
 swig/python/scripts/gdal_sieve.dox                 |    35 +-
 swig/python/scripts/gdalcompare.dox                |    17 +-
 swig/python/scripts/gdalmove.dox                   |    23 +-
 swig/python/scripts/ogrmerge.dox                   |   169 +
 swig/python/scripts/ogrmerge.py                    |   542 +
 swig/python/setup.cfg                              |     8 +-
 swig/python/setup.py                               |    14 +-
 vb6/GDAL.bas                                       |   187 -
 vb6/GDALColorTable.cls                             |   173 -
 vb6/GDALCore.bas                                   |   506 -
 vb6/GDALDataset.cls                                |   231 -
 vb6/GDALDriver.cls                                 |   157 -
 vb6/GDALRasterBand.cls                             |   241 -
 vb6/OGRCoordinateTransformation.cls                |   176 -
 vb6/OGRSpatialReference.cls                        |   246 -
 vb6/README.TXT                                     |    67 -
 vb6/makefile.vc                                    |    15 -
 vb6/test/GDALVB6Test.vbp                           |    46 -
 vb6/test/GDALVB6Test.vbw                           |    10 -
 vb6/test/Module1.bas                               |     9 -
 vb6/test/VB6Test.frm                               |   435 -
 vb6/vb6_support.cpp                                |   341 -
 2473 files changed, 335631 insertions(+), 220495 deletions(-)

diff --git a/Doxyfile b/Doxyfile
index fde9392..74f9be5 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -14,157 +14,157 @@
 # Project related configuration options
 #---------------------------------------------------------------------------
 
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
 # by quotes) that should identify the project.
 
 PROJECT_NAME           = GDAL
 
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
-# This could be handy for archiving the generated documentation or 
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 
+PROJECT_NUMBER         =
 
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
 # where doxygen was started. If left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = 
+OUTPUT_DIRECTORY       =
 
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
-# documentation generated by doxygen is written. Doxygen will use this 
-# information to generate all constant output in the proper language. 
-# The default language is English, other supported languages are: 
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
-# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
-# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
-# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
 # Swedish, and Ukrainian.
 
 OUTPUT_LANGUAGE        = English
 
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
-# include brief member descriptions after the members that are listed in 
-# the file and class documentation (similar to JavaDoc). 
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
 # Set to NO to disable this.
 
 BRIEF_MEMBER_DESC      = YES
 
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
-# the brief description of a member or function before the detailed description. 
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
 # brief descriptions will be completely suppressed.
 
 REPEAT_BRIEF           = YES
 
-# This tag implements a quasi-intelligent brief description abbreviator 
-# that is used to form the text in various listings. Each string 
-# in this list, if found as the leading text of the brief description, will be 
-# stripped from the text and the result after processing the whole list, is 
-# used as the annotated text. Otherwise, the brief description is used as-is. 
-# If left blank, the following values are used ("$name" is automatically 
-# replaced with the name of the entity): "The $name class" "The $name widget" 
-# "The $name file" "is" "provides" "specifies" "contains" 
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
 # "represents" "a" "an" "the"
 
-ABBREVIATE_BRIEF       = 
+ABBREVIATE_BRIEF       =
 
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
-# Doxygen will generate a detailed section even if there is only a brief 
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
 # description.
 
 ALWAYS_DETAILED_SEC    = NO
 
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
-# inherited members of a class in the documentation of that class as if those 
-# members were ordinary class members. Constructors, destructors and assignment 
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
 # operators of the base classes will not be shown.
 
 INLINE_INHERITED_MEMB  = NO
 
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
-# path before files name in the file list and in the header files. If set 
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
 # to NO the shortest path that makes the file name unique will be used.
 
 FULL_PATH_NAMES        = NO
 
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
-# the path mentioned in the documentation of a class, which tells 
-# the reader which header file to include in order to use a class. 
-# If left blank only the name of the header file containing the class 
-# definition is used. Otherwise one should specify the include paths that 
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
 # are normally passed to the compiler using the -I flag.
 
-STRIP_FROM_INC_PATH    = 
+STRIP_FROM_INC_PATH    =
 
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
-# (but less readable) file names. This can be useful is your file systems 
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
 # doesn't support long names like on DOS, Mac, or CD-ROM.
 
 SHORT_NAMES            = NO
 
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
-# will interpret the first line (until the first dot) of a JavaDoc-style 
-# comment as the brief description. If set to NO, the JavaDoc 
-# comments will behave just like the Qt-style comments (thus requiring an 
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
 # explicit @brief command for a brief description.
 
 JAVADOC_AUTOBRIEF      = YES
 
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
-# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
-# comments) as a brief description. This used to be the default behaviour. 
-# The new default is to treat a multi-line C++ comment block as a detailed 
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
 # description. Set this tag to YES if you prefer the old behaviour instead.
 
 MULTILINE_CPP_IS_BRIEF = NO
 
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
-# member inherits the documentation from any documented member that it 
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
 # re-implements.
 
 INHERIT_DOCS           = YES
 
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
 # all members of a group must be documented explicitly.
 
 DISTRIBUTE_GROUP_DOC   = NO
 
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
 # Doxygen uses this value to replace tabs by spaces in code fragments.
 
 TAB_SIZE               = 8
 
-# This tag can be used to specify a number of aliases that acts 
-# as commands in the documentation. An alias has the form "name=value". 
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
-# put the command \sideeffect (or @sideeffect) in the documentation, which 
-# will result in a user-defined paragraph with heading "Side Effects:". 
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
 # You can put \n's in the value part of an alias to insert newlines.
 
-ALIASES                = 
+ALIASES                =
 
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
-# sources only. Doxygen will then generate output that is more tailored for C. 
-# For instance, some of the names that are used will be different. The list 
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
 # of all members will be omitted, etc.
 
 OPTIMIZE_OUTPUT_FOR_C  = NO
 
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
-# only. Doxygen will then generate output that is more tailored for Java. 
-# For instance, namespaces will be presented as packages, qualified scopes 
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
 # will look different, etc.
 
 OPTIMIZE_OUTPUT_JAVA   = NO
 
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
-# the same type (for instance a group of public functions) to be put as a 
-# subgroup of that type (e.g. under the Public Functions section). Set it to 
-# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
 # the \nosubgrouping command.
 
 SUBGROUPING            = YES
@@ -173,155 +173,155 @@ SUBGROUPING            = YES
 # Build related configuration options
 #---------------------------------------------------------------------------
 
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
-# documentation are documented, even if no documentation was available. 
-# Private class members and static file members will be hidden unless 
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
 # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
 
 EXTRACT_ALL            = NO
 
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
 # will be included in the documentation.
 
 EXTRACT_PRIVATE        = NO
 
-# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
 # will be included in the documentation.
 
 EXTRACT_STATIC         = NO
 
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
-# defined locally in source files will be included in the documentation. 
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
 # If set to NO only classes defined in header files are included.
 
 EXTRACT_LOCAL_CLASSES  = NO
 
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
-# undocumented members of documented classes, files or namespaces. 
-# If set to NO (the default) these members will be included in the 
-# various overviews, but no documentation section is generated. 
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
 # This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_MEMBERS     = NO
 
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
-# undocumented classes that are normally visible in the class hierarchy. 
-# If set to NO (the default) these classes will be included in the various 
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
 # overviews. This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_CLASSES     = NO
 
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
-# friend (class|struct|union) declarations. 
-# If set to NO (the default) these declarations will be included in the 
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
 # documentation.
 
 HIDE_FRIEND_COMPOUNDS  = NO
 
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
-# documentation blocks found inside the body of a function. 
-# If set to NO (the default) these blocks will be appended to the 
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
 # function's detailed documentation block.
 
 HIDE_IN_BODY_DOCS      = NO
 
-# The INTERNAL_DOCS tag determines if documentation 
-# that is typed after a \internal command is included. If the tag is set 
-# to NO (the default) then the documentation will be excluded. 
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
 # Set it to YES to include the internal documentation.
 
 INTERNAL_DOCS          = NO
 
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
-# file names in lower-case letters. If set to YES upper-case letters are also 
-# allowed. This is useful if you have classes or files whose names only differ 
-# in case and if your file system supports case sensitive file names. Windows 
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
 # and Mac users are advised to set this option to NO.
 
 CASE_SENSE_NAMES       = YES
 
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
-# will show members with their full class and namespace scopes in the 
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
 # documentation. If set to YES the scope will be hidden.
 
 HIDE_SCOPE_NAMES       = NO
 
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
-# will put a list of the files that are included by a file in the documentation 
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
 # of that file.
 
 SHOW_INCLUDE_FILES     = YES
 
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
 # is inserted in the documentation for inline members.
 
 INLINE_INFO            = YES
 
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
-# will sort the (detailed) documentation of file and class members 
-# alphabetically by member name. If set to NO the members will appear in 
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
 # declaration order.
 
 SORT_MEMBER_DOCS       = YES
 
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
-# brief documentation of file, namespace and class members alphabetically 
-# by member name. If set to NO (the default) the members will appear in 
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
 # declaration order.
 
 SORT_BRIEF_DOCS        = NO
 
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
-# sorted by fully-qualified names, including namespaces. If set to 
-# NO (the default), the class list will be sorted only by class name, 
-# not including the namespace part. 
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
 # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the 
+# Note: This option applies only to the class list, not to the
 # alphabetical list.
 
 SORT_BY_SCOPE_NAME     = NO
 
-# The GENERATE_TODOLIST tag can be used to enable (YES) or 
-# disable (NO) the todo list. This list is created by putting \todo 
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
 # commands in the documentation.
 
 GENERATE_TODOLIST      = YES
 
-# The GENERATE_TESTLIST tag can be used to enable (YES) or 
-# disable (NO) the test list. This list is created by putting \test 
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
 # commands in the documentation.
 
 GENERATE_TESTLIST      = YES
 
-# The GENERATE_BUGLIST tag can be used to enable (YES) or 
-# disable (NO) the bug list. This list is created by putting \bug 
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
 # commands in the documentation.
 
 GENERATE_BUGLIST       = YES
 
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
-# disable (NO) the deprecated list. This list is created by putting 
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
 # \deprecated commands in the documentation.
 
 GENERATE_DEPRECATEDLIST= YES
 
-# The ENABLED_SECTIONS tag can be used to enable conditional 
+# The ENABLED_SECTIONS tag can be used to enable conditional
 # documentation sections, marked by \if sectionname ... \endif.
 
-ENABLED_SECTIONS       = 
+ENABLED_SECTIONS       =
 
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
-# the initial value of a variable or define consists of for it to appear in 
-# the documentation. If the initializer consists of more lines than specified 
-# here it will be hidden. Use a value of 0 to hide initializers completely. 
-# The appearance of the initializer of individual variables and defines in the 
-# documentation can be controlled using \showinitializer or \hideinitializer 
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
 # command in the documentation regardless of this setting.
 
 MAX_INITIALIZER_LINES  = 30
 
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
-# at the bottom of the documentation of classes and structs. If set to YES the 
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
 # list will mention the files that were used to generate the documentation.
 
 SHOW_USED_FILES        = YES
@@ -330,52 +330,52 @@ SHOW_USED_FILES        = YES
 # configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
 
-# The QUIET tag can be used to turn on/off the messages that are generated 
+# The QUIET tag can be used to turn on/off the messages that are generated
 # by doxygen. Possible values are YES and NO. If left blank NO is used.
 
 QUIET                  = NO
 
-# The WARNINGS tag can be used to turn on/off the warning messages that are 
-# generated by doxygen. Possible values are YES and NO. If left blank 
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
 # NO is used.
 
 WARNINGS               = YES
 
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
 # automatically be disabled.
 
 WARN_IF_UNDOCUMENTED   = YES
 
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
-# potential errors in the documentation, such as not documenting some 
-# parameters in a documented function, or documenting parameters that 
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
 # don't exist or using markup commands wrongly.
 
 WARN_IF_DOC_ERROR      = YES
 
-# The WARN_FORMAT tag determines the format of the warning messages that 
-# doxygen can produce. The string should contain the $file, $line, and $text 
-# tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text. Optionally the format may contain 
-# $version, which will be replaced by the version of the file (if it could 
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
 # be obtained via FILE_VERSION_FILTER)
 
 WARN_FORMAT            = "$file:$line: $text"
 
-# The WARN_LOGFILE tag can be used to specify a file to which warning 
-# and error messages should be written. If left blank the output is written 
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
 # to stderr.
 
-WARN_LOGFILE           = 
+WARN_LOGFILE           =
 
 #---------------------------------------------------------------------------
 # configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag can be used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
 INPUT                  = port \
@@ -384,20 +384,20 @@ INPUT                  = port \
                          alg \
                          frmts/vrt \
                          doc \
-			 apps \
+                         apps \
                          ogr \
                          ogr/ogrsf_frmts \
                          ogr/ogrsf_frmts/generic \
                          ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp \
                          ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp \
-			 swig/python/scripts \
-			 gnm 
-
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank the following patterns are tested: 
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+                         swig/python/scripts \
+                         gnm
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
 # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
 
 FILE_PATTERNS          = *.h \
@@ -405,70 +405,70 @@ FILE_PATTERNS          = *.h \
                          *.c \
                          *.dox
 
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
-# should be searched for input files as well. Possible values are YES and NO. 
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
 # If left blank NO is used.
 
 RECURSIVE              = NO
 
-# The EXCLUDE tag can be used to specify files and/or directories that should 
-# excluded from the INPUT source files. This way you can easily exclude a 
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
 # subdirectory from a directory tree whose root is specified with the INPUT tag.
 
-EXCLUDE                = 
+EXCLUDE                =
 
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
-# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
 # from the input.
 
 EXCLUDE_SYMLINKS       = NO
 
-# If the value of the INPUT tag contains directories, you can use the 
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
 # certain files from those directories.
 
-EXCLUDE_PATTERNS       = 
+EXCLUDE_PATTERNS       =
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
 # the \include command).
 
 EXAMPLE_PATH           = apps \
                          frmts \
-                         frmts/jdem 
+                         frmts/jdem
 
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
 # blank all files are included.
 
-EXAMPLE_PATTERNS       = 
+EXAMPLE_PATTERNS       =
 
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
-# searched for input files to be used with the \include or \dontinclude 
-# commands irrespective of the value of the RECURSIVE tag. 
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
 # Possible values are YES and NO. If left blank NO is used.
 
 EXAMPLE_RECURSIVE      = NO
 
-# The IMAGE_PATH tag can be used to specify one or more files or 
-# directories that contain image that are included in the documentation (see 
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
 # the \image command).
 
-IMAGE_PATH             = 
+IMAGE_PATH             = doc/grid
 
-# The INPUT_FILTER tag can be used to specify a program that doxygen should 
-# invoke to filter for each input file. Doxygen will invoke the filter program 
-# by executing (via popen()) the command <filter> <input-file>, where <filter> 
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
-# input file. Doxygen will then use the output that the filter program writes 
-# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
 # ignored.
 
-INPUT_FILTER           = 
+INPUT_FILTER           =
 
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
-# INPUT_FILTER) will be used to filter the input files when producing source 
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
 # files to browse (i.e. when SOURCE_BROWSER is set to YES).
 
 FILTER_SOURCE_FILES    = NO
@@ -477,47 +477,47 @@ FILTER_SOURCE_FILES    = NO
 # configuration options related to source browsing
 #---------------------------------------------------------------------------
 
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-# Note: To get rid of all source code in the generated output, make sure also 
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
 # VERBATIM_HEADERS is set to NO.
 
 SOURCE_BROWSER         = NO
 
-# Setting the INLINE_SOURCES tag to YES will include the body 
+# Setting the INLINE_SOURCES tag to YES will include the body
 # of functions and classes directly in the documentation.
 
 INLINE_SOURCES         = NO
 
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
-# doxygen to hide any special comment blocks from generated source code 
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
 # fragments. Normal C and C++ comments will always remain visible.
 
 STRIP_CODE_COMMENTS    = YES
 
-# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
-# then for each documented function all documented 
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
 # functions referencing it will be listed.
 
 REFERENCED_BY_RELATION = NO
 
-# If the REFERENCES_RELATION tag is set to YES (the default) 
-# then for each documented function all documented entities 
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
 # called/used by that function will be listed.
 
 REFERENCES_RELATION    = NO
 
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
-# link to the source code.  Otherwise they will link to the documentation. 
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentation.
 #
 # http://trac.osgeo.org/gdal/ticket/2723
 
-REFERENCES_LINK_SOURCE = NO 
+REFERENCES_LINK_SOURCE = NO
 
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
-# will generate a verbatim copy of the header file for each class for 
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
 # which an include is specified. Set to NO to disable this.
 
 VERBATIM_HEADERS       = YES
@@ -526,133 +526,136 @@ VERBATIM_HEADERS       = YES
 # configuration options related to the alphabetical class index
 #---------------------------------------------------------------------------
 
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
-# of all compounds will be generated. Enable this if the project 
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
 # contains a lot of classes, structs, unions or interfaces.
 
 ALPHABETICAL_INDEX     = NO
 
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
 # in which this list will be split (can be a number in the range [1..20])
 
 COLS_IN_ALPHA_INDEX    = 5
 
-# In case all classes in a project start with a common prefix, all 
-# classes will be put under the same header in the alphabetical index. 
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
 # should be ignored while generating the index headers.
 
-IGNORE_PREFIX          = 
+IGNORE_PREFIX          =
 
 #---------------------------------------------------------------------------
 # configuration options related to the HTML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
 # generate HTML output.
 
 GENERATE_HTML          = YES
 
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `html' will be used as the default path.
 
-HTML_OUTPUT            = 
+HTML_OUTPUT            =
 
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
 # doxygen will generate files with .html extension.
 
 HTML_FILE_EXTENSION    = .html
 
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard header.
 
-HTML_HEADER            = 
+HTML_HEADER            =
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard footer.
 
 HTML_FOOTER            = doc/gdal_footer.html
 
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
-# style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet. Note that doxygen will try to copy 
-# the style sheet file to the HTML output directory, so don't put your own 
+# Custom layout (see http://www.stack.nl/~dimitri/doxygen/manual/customize.html)
+LAYOUT_FILE 	       = DoxygenLayout.xml
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
 # stylesheet in the HTML output directory as well, or it will be erased!
 
-HTML_STYLESHEET        = 
+HTML_STYLESHEET        =
 
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
 # NO a bullet list will be used.
 
-HTML_ALIGN_MEMBERS     = YES
+# HTML_ALIGN_MEMBERS     = YES
 
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
-# will be generated that can be used as input for tools like the 
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
 # of the generated HTML documentation.
 
 GENERATE_HTMLHELP      = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
-# be used to specify the file name of the resulting .chm file. You 
-# can add a path in front of the file if the result should not be 
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
 # written to the html output directory.
 
-CHM_FILE               = 
+CHM_FILE               =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
-# be used to specify the location (absolute path including file name) of 
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
 # the HTML help compiler on the generated index.hhp.
 
-HHC_LOCATION           = 
+HHC_LOCATION           =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
-# controls if a separate .chi index file is generated (YES) or that 
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
 # it should be included in the master .chm file (NO).
 
 GENERATE_CHI           = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
-# controls whether a binary table of contents is generated (YES) or a 
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
 # normal table of contents (NO) in the .chm file.
 
 BINARY_TOC             = NO
 
-# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
 # to the contents of the HTML help documentation and to the tree view.
 
 TOC_EXPAND             = NO
 
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
 # the value YES disables it.
 
 DISABLE_INDEX          = NO
 
-# This tag can be used to set the number of enum values (range [1..20]) 
+# This tag can be used to set the number of enum values (range [1..20])
 # that doxygen will group on one line in the generated HTML documentation.
 
 ENUM_VALUES_PER_LINE   = 4
 
 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that 
-# is generated for HTML Help). For this to work a browser that supports 
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
 # probably better off using the HTML help feature.
 
 GENERATE_TREEVIEW      = NO
 
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
-# used to set the initial width (in pixels) of the frame in which the tree 
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
 # is shown.
 
 TREEVIEW_WIDTH         = 250
@@ -661,74 +664,74 @@ TREEVIEW_WIDTH         = 250
 # configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
 # generate Latex output.
 
 GENERATE_LATEX         = NO
 
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `latex' will be used as the default path.
 
-LATEX_OUTPUT           = 
+LATEX_OUTPUT           =
 
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
 # invoked. If left blank `latex' will be used as the default command name.
 
 LATEX_CMD_NAME         = latex
 
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
-# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
 # default command name.
 
 MAKEINDEX_CMD_NAME     = makeindex
 
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
-# LaTeX documents. This may be useful for small projects and may help to 
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
 # save some trees in general.
 
 COMPACT_LATEX          = NO
 
-# The PAPER_TYPE tag can be used to set the paper type that is used 
-# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
 # executive. If left blank a4wide will be used.
 
 PAPER_TYPE             = a4wide
 
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
 # packages that should be included in the LaTeX output.
 
-EXTRA_PACKAGES         = 
+EXTRA_PACKAGES         =
 
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
-# the generated latex document. The header should contain everything until 
-# the first chapter. If it is left blank doxygen will generate a 
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
 # standard header. Notice: only use this tag if you know what you are doing!
 
-LATEX_HEADER           = 
+LATEX_HEADER           =
 
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
-# contain links (just like the HTML output) instead of page references 
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
 # This makes the output suitable for online browsing using a pdf viewer.
 
 PDF_HYPERLINKS         = NO
 
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
-# plain latex in the generated Makefile. Set this option to YES to get a 
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
 # higher quality PDF documentation.
 
 USE_PDFLATEX           = NO
 
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
-# command to the generated LaTeX files. This will instruct LaTeX to keep 
-# running if errors occur, instead of asking the user for help. 
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
 # This option is also used when generating formulas in HTML.
 
 LATEX_BATCHMODE        = NO
 
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
-# include the index chapters (such as File Index, Compound Index, etc.) 
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
 # in the output.
 
 LATEX_HIDE_INDICES     = NO
@@ -737,68 +740,68 @@ LATEX_HIDE_INDICES     = NO
 # configuration options related to the RTF output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
-# The RTF output is optimized for Word 97 and may not look very pretty with 
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
 # other RTF readers or editors.
 
 GENERATE_RTF           = NO
 
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `rtf' will be used as the default path.
 
 RTF_OUTPUT             = rtf
 
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
-# RTF documents. This may be useful for small projects and may help to 
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
 # save some trees in general.
 
 COMPACT_RTF            = NO
 
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
-# will contain hyperlink fields. The RTF file will 
-# contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using WORD or other 
-# programs which support those fields. 
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
 # Note: wordpad (write) and others do not support links.
 
 RTF_HYPERLINKS         = NO
 
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
-# config file, i.e. a series of assignments. You only have to provide 
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
 # replacements, missing definitions are set to their default value.
 
-RTF_STYLESHEET_FILE    = 
+RTF_STYLESHEET_FILE    =
 
-# Set optional variables used in the generation of an rtf document. 
+# Set optional variables used in the generation of an rtf document.
 # Syntax is similar to doxygen's config file.
 
-RTF_EXTENSIONS_FILE    = 
+RTF_EXTENSIONS_FILE    =
 
 #---------------------------------------------------------------------------
 # configuration options related to the man page output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
 # generate man pages
 
 GENERATE_MAN           = NO
 
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `man' will be used as the default path.
 
 MAN_OUTPUT             = man
 
-# The MAN_EXTENSION tag determines the extension that is added to 
+# The MAN_EXTENSION tag determines the extension that is added to
 # the generated man pages (default is the subroutine's section .3)
 
 MAN_EXTENSION          = .1
 
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
-# then it will generate one additional man file for each entity 
-# documented in the real man page(s). These additional files 
-# only source the real man page, but without them the man command 
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
 # would be unable to find the correct page. The default is NO.
 
 MAN_LINKS              = NO
@@ -807,33 +810,33 @@ MAN_LINKS              = NO
 # configuration options related to the XML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_XML tag is set to YES Doxygen will 
-# generate an XML file that captures the structure of 
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
 # the code including all documentation.
 
 GENERATE_XML           = NO
 
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `xml' will be used as the default path.
 
 XML_OUTPUT             = xml
 
-# The XML_SCHEMA tag can be used to specify an XML schema, 
-# which can be used by a validating XML parser to check the 
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
 # syntax of the XML files.
 
-XML_SCHEMA             = 
+XML_SCHEMA             =
 
-# The XML_DTD tag can be used to specify an XML DTD, 
-# which can be used by a validating XML parser to check the 
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
 # syntax of the XML files.
 
-XML_DTD                = 
+XML_DTD                =
 
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
-# dump the program listings (including syntax highlighting 
-# and cross-referencing information) to the XML output. Note that 
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
 # enabling this will significantly increase the size of the XML output.
 
 XML_PROGRAMLISTING     = YES
@@ -842,10 +845,10 @@ XML_PROGRAMLISTING     = YES
 # configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
-# generate an AutoGen Definitions (see autogen.sf.net) file 
-# that captures the structure of the code including all 
-# documentation. Note that this feature is still experimental 
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
 # and incomplete at the moment.
 
 GENERATE_AUTOGEN_DEF   = NO
@@ -854,82 +857,82 @@ GENERATE_AUTOGEN_DEF   = NO
 # configuration options related to the Perl module output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
-# generate a Perl module file that captures the structure of 
-# the code including all documentation. Note that this 
-# feature is still experimental and incomplete at the 
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
 # moment.
 
 GENERATE_PERLMOD       = NO
 
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
 # to generate PDF and DVI output from the Perl module output.
 
 PERLMOD_LATEX          = NO
 
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
-# nicely formatted so it can be parsed by a human reader.  This is useful 
-# if you want to understand what is going on.  On the other hand, if this 
-# tag is set to NO the size of the Perl module output will be much smaller 
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
 # and Perl will parse it just the same.
 
 PERLMOD_PRETTY         = YES
 
-# The names of the make variables in the generated doxyrules.make file 
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
-# This is useful so different doxyrules.make files included by the same 
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
 # Makefile don't overwrite each other's variables.
 
-PERLMOD_MAKEVAR_PREFIX = 
+PERLMOD_MAKEVAR_PREFIX =
 
 #---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
+# Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
-# evaluate all C-preprocessor directives found in the sources and include 
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
 # files.
 
 ENABLE_PREPROCESSING   = YES
 
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
-# names in the source code. If set to NO (the default) only conditional 
-# compilation will be performed. Macro expansion can be done in a controlled 
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
 # way by setting EXPAND_ONLY_PREDEF to YES.
 
 MACRO_EXPANSION        = YES
 
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
-# then the macro expansion is limited to the macros specified with the 
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
 # PREDEFINED and EXPAND_AS_PREDEFINED tags.
 
 EXPAND_ONLY_PREDEF     = YES
 
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
 # in the INCLUDE_PATH (see below) will be search if a #include is found.
 
 SEARCH_INCLUDES        = YES
 
-# The INCLUDE_PATH tag can be used to specify one or more directories that 
-# contain include files that are not input files but should be processed by 
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
 # the preprocessor.
 
-INCLUDE_PATH           = 
+INCLUDE_PATH           =
 
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
-# patterns (like *.h and *.hpp) to filter out the header-files in the 
-# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
 # be used.
 
-INCLUDE_FILE_PATTERNS  = 
+INCLUDE_FILE_PATTERNS  =
 
-# The PREDEFINED tag can be used to specify one or more macro names that 
-# are defined before the preprocessor is started (similar to the -D option of 
-# gcc). The argument of the tag is a list of macros of the form: name 
-# or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed. To prevent a macro definition from being 
-# undefined via #undef or recursively expanded use the := operator 
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
 # instead of the = operator.
 
 PREDEFINED             = HAVE_DLFCN_H \
@@ -941,190 +944,197 @@ PREDEFINED             = HAVE_DLFCN_H \
                          DOXYGEN_SKIP \
                          HAVE_CURL \
                          CPL_UNUSED= \
-                         UNUSED_IF_NO_GEOS=
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
-# this tag can be used to specify a list of macro names that should be expanded. 
-# The macro definition that is found in the sources will be used. 
+                         UNUSED_IF_NO_GEOS= \
+                         UNUSED_IF_NO_SFCGAL= \
+                         UNUSED_PARAMETER= \
+                         isinf \
+                         HAVE_LIBXML2 \
+                         HAVE_RECENT_LIBXML2 \
+                         HAVE_LONG_LONG=1 \
+                         HAVE_SC_PHYS_PAGES=1
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
 # Use the PREDEFINED tag if you want to use a different macro definition.
 
-EXPAND_AS_DEFINED      = CPL_PRINT_FUNC_FORMAT
+EXPAND_AS_DEFINED      = CPL_PRINT_FUNC_FORMAT CPL_FORMAT_STRING
 
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
-# doxygen's preprocessor will remove all function-like macros that are alone 
-# on a line, have an all uppercase name, and do not end with a semicolon. Such 
-# function macros are typically used for boiler-plate code, and will confuse 
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
 # the parser if not removed.
 
 SKIP_FUNCTION_MACROS   = YES
 
 #---------------------------------------------------------------------------
-# Configuration::additions related to external references   
+# Configuration::additions related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES option can be used to specify one or more tagfiles. 
-# Optionally an initial location of the external documentation 
-# can be added for each tagfile. The format of a tag file without 
-# this location is as follows: 
-#   TAGFILES = file1 file2 ... 
-# Adding location for the tag files is done as follows: 
-#   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool 
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
 # does not have to be run to correct the links.
 # Note that each tag file must have a unique name
 # (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen 
+# If a tag file is not located in the directory in which doxygen
 # is run, you must also specify the path to the tagfile here.
 
-TAGFILES               = 
+TAGFILES               =
 
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
 # a tag file that is based on the input files it reads.
 
-GENERATE_TAGFILE       = 
+GENERATE_TAGFILE       =
 
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
-# in the class index. If set to NO only the inherited external classes 
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
 # will be listed.
 
 ALLEXTERNALS           = NO
 
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
-# in the modules index. If set to NO, only the current project's groups will 
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
 # be listed.
 
 EXTERNAL_GROUPS        = YES
 
-# The PERL_PATH should be the absolute path and name of the perl script 
+# The PERL_PATH should be the absolute path and name of the perl script
 # interpreter (i.e. the result of `which perl').
 
 PERL_PATH              = /usr/local/bin/perl
 
 #---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
+# Configuration options related to the dot tool
 #---------------------------------------------------------------------------
 
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
-# or super classes. Setting the tag to NO turns the diagrams off. Note that 
-# this option is superseded by the HAVE_DOT option below. This is only a 
-# fallback. It is recommended to install and use dot, since it yields more 
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
 # powerful graphs.
 
 CLASS_DIAGRAMS         = YES
 
-# If set to YES, the inheritance and collaboration graphs will hide 
-# inheritance and usage relations if the target is undocumented 
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
 # or is not a class.
 
 HIDE_UNDOC_RELATIONS   = YES
 
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
-# available from the path. This tool is part of Graphviz, a graph visualization 
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
 # have no effect if this option is set to NO (the default)
 
 HAVE_DOT               = NO
 
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect inheritance relations. Setting this tag to YES will force the 
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
 # the CLASS_DIAGRAMS tag to NO.
 
 CLASS_GRAPH            = YES
 
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect implementation dependencies (inheritance, containment, and 
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
 # class references variables) of the class with other documented classes.
 
 COLLABORATION_GRAPH    = YES
 
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
-# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
 # Language.
 
 UML_LOOK               = NO
 
-# If set to YES, the inheritance and collaboration graphs will show the 
+# If set to YES, the inheritance and collaboration graphs will show the
 # relations between templates and their instances.
 
 TEMPLATE_RELATIONS     = NO
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
-# tags are set to YES then doxygen will generate a graph for each documented 
-# file showing the direct and indirect include dependencies of the file with 
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
 # other documented files.
 
 INCLUDE_GRAPH          = YES
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
-# documented header file showing the documented files that directly or 
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
 # indirectly include this file.
 
 INCLUDED_BY_GRAPH      = YES
 
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
-# generate a call dependency graph for every global function or class method. 
-# Note that enabling this option will significantly increase the time of a run. 
-# So in most cases it will be better to enable call graphs for selected 
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
 # functions only using the \callgraph command.
 
 CALL_GRAPH             = NO
 
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
 # will graphical hierarchy of all classes instead of a textual one.
 
 GRAPHICAL_HIERARCHY    = YES
 
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
 # generated by dot. Possible values are png, jpg, or gif
 # If left blank png will be used.
 
 DOT_IMAGE_FORMAT       = png
 
-# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
 # found. If left blank, it is assumed the dot tool can be found in the path.
 
-DOT_PATH               = 
+DOT_PATH               =
 
-# The DOTFILE_DIRS tag can be used to specify one or more directories that 
-# contain dot files that are included in the documentation (see the 
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
 # \dotfile command).
 
-DOTFILE_DIRS           = 
+DOTFILE_DIRS           =
 
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
-# graphs generated by dot. A depth value of 3 means that only nodes reachable 
-# from the root by following a path via at most 3 edges will be shown. Nodes 
-# that lay further from the root node will be omitted. Note that setting this 
-# option to 1 or 2 may greatly reduce the computation time needed for large 
-# code bases. Also note that a graph may be further truncated if the graph's 
-# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
-# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
 # the graph is not depth-constrained.
 
 MAX_DOT_GRAPH_DEPTH    = 0
 
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
-# generate a legend page explaining the meaning of the various boxes and 
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
 # arrows in the dot generated graphs.
 
 GENERATE_LEGEND        = YES
 
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
-# remove the intermediate dot files that are used to generate 
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
 # the various graphs.
 
 DOT_CLEANUP            = YES
 
 #---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
+# Configuration::additions related to the search engine
 #---------------------------------------------------------------------------
 
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# The SEARCHENGINE tag specifies whether or not a search engine should be
 # used. If set to NO the values of all tags below this one will be ignored.
 
 SEARCHENGINE           = NO
diff --git a/DoxygenLayout.xml b/DoxygenLayout.xml
new file mode 100644
index 0000000..44e0833
--- /dev/null
+++ b/DoxygenLayout.xml
@@ -0,0 +1,204 @@
+<doxygenlayout version="1.0">
+  <!-- Generated by doxygen 1.8.12 -->
+  <!-- Navigation index tabs for HTML output -->
+  <!-- see "Changing the layout of pages" at http://www.stack.nl/~dimitri/doxygen/manual/customize.html -->
+  <navindex>
+    <tab type="mainpage" visible="yes" title=""/>
+    <tab type="pages" visible="yes" title="" intro=""/>
+    <tab type="modules" visible="yes" title="" intro=""/>
+    <tab type="namespaces" visible="yes" title="">
+      <tab type="namespacelist" visible="yes" title="" intro=""/>
+      <tab type="namespacemembers" visible="yes" title="" intro=""/>
+    </tab>
+    <tab type="classes" visible="yes" title="">
+      <tab type="classlist" visible="yes" title="" intro=""/>
+      <tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/> 
+      <tab type="hierarchy" visible="yes" title="" intro=""/>
+      <tab type="classmembers" visible="yes" title="" intro=""/>
+    </tab>
+    <tab type="files" visible="yes" title="">
+      <tab type="filelist" visible="yes" title="" intro=""/>
+      <tab type="globals" visible="yes" title="" intro=""/>
+    </tab>
+    <tab type="examples" visible="yes" title="" intro=""/>  
+    
+    <!-- beginning GDAL customization -->
+    <tab type="usergroup" title="Download">
+      <tab type="user" url="http://trac.osgeo.org/gdal/wiki/DownloadSource" title="Source"/>
+      <tab type="user" url="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries" title="Binaries"/>
+    </tab>
+    <tab type="user" url="http://trac.osgeo.org/gdal/report/1?sort=ticket&asc=0" title="Issue Tracker"/>
+    <!-- end GDAL customization -->
+    
+  </navindex>    
+
+  <!-- Layout definition for a class page -->
+  <class>
+    <briefdescription visible="yes"/>
+    <includes visible="$SHOW_INCLUDE_FILES"/>
+    <inheritancegraph visible="$CLASS_GRAPH"/>
+    <collaborationgraph visible="$COLLABORATION_GRAPH"/>
+    <memberdecl>
+      <nestedclasses visible="yes" title=""/>
+      <publictypes title=""/>
+      <services title=""/>
+      <interfaces title=""/>
+      <publicslots title=""/>
+      <signals title=""/>
+      <publicmethods title=""/>
+      <publicstaticmethods title=""/>
+      <publicattributes title=""/>
+      <publicstaticattributes title=""/>
+      <protectedtypes title=""/>
+      <protectedslots title=""/>
+      <protectedmethods title=""/>
+      <protectedstaticmethods title=""/>
+      <protectedattributes title=""/>
+      <protectedstaticattributes title=""/>
+      <packagetypes title=""/>
+      <packagemethods title=""/>
+      <packagestaticmethods title=""/>
+      <packageattributes title=""/>
+      <packagestaticattributes title=""/>
+      <properties title=""/>
+      <events title=""/>
+      <privatetypes title=""/>
+      <privateslots title=""/>
+      <privatemethods title=""/>
+      <privatestaticmethods title=""/>
+      <privateattributes title=""/>
+      <privatestaticattributes title=""/>
+      <friends title=""/>
+      <related title="" subtitle=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+    <memberdef>
+      <inlineclasses title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <services title=""/>
+      <interfaces title=""/>
+      <constructors title=""/>
+      <functions title=""/>
+      <related title=""/>
+      <variables title=""/>
+      <properties title=""/>
+      <events title=""/>
+    </memberdef>
+    <allmemberslink visible="yes"/>
+    <usedfiles visible="$SHOW_USED_FILES"/>
+    <authorsection visible="yes"/>
+  </class>
+
+  <!-- Layout definition for a namespace page -->
+  <namespace>
+    <briefdescription visible="yes"/>
+    <memberdecl>
+      <nestednamespaces visible="yes" title=""/>
+      <constantgroups visible="yes" title=""/>
+      <classes visible="yes" title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+    <memberdef>
+      <inlineclasses title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+    </memberdef>
+    <authorsection visible="yes"/>
+  </namespace>
+
+  <!-- Layout definition for a file page -->
+  <file>
+    <briefdescription visible="yes"/>
+    <includes visible="$SHOW_INCLUDE_FILES"/>
+    <includegraph visible="$INCLUDE_GRAPH"/>
+    <includedbygraph visible="$INCLUDED_BY_GRAPH"/>
+    <sourcelink visible="yes"/>
+    <memberdecl>
+      <classes visible="yes" title=""/>
+      <namespaces visible="yes" title=""/>
+      <constantgroups visible="yes" title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+    <memberdef>
+      <inlineclasses title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <functions title=""/>
+      <variables title=""/>
+    </memberdef>
+    <authorsection/>
+  </file>
+
+  <!-- Layout definition for a group page -->
+  <group>
+    <briefdescription visible="yes"/>
+    <groupgraph visible="$GROUP_GRAPHS"/>
+    <memberdecl>
+      <nestedgroups visible="yes" title=""/>
+      <dirs visible="yes" title=""/>
+      <files visible="yes" title=""/>
+      <namespaces visible="yes" title=""/>
+      <classes visible="yes" title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <enumvalues title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <signals title=""/>
+      <publicslots title=""/>
+      <protectedslots title=""/>
+      <privateslots title=""/>
+      <events title=""/>
+      <properties title=""/>
+      <friends title=""/>
+      <membergroups visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+    <memberdef>
+      <pagedocs/>
+      <inlineclasses title=""/>
+      <defines title=""/>
+      <typedefs title=""/>
+      <enums title=""/>
+      <enumvalues title=""/>
+      <functions title=""/>
+      <variables title=""/>
+      <signals title=""/>
+      <publicslots title=""/>
+      <protectedslots title=""/>
+      <privateslots title=""/>
+      <events title=""/>
+      <properties title=""/>
+      <friends title=""/>
+    </memberdef>
+    <authorsection visible="yes"/>
+  </group>
+
+  <!-- Layout definition for a directory page -->
+  <directory>
+    <briefdescription visible="yes"/>
+    <directorygraph visible="yes"/>
+    <memberdecl>
+      <dirs visible="yes"/>
+      <files visible="yes"/>
+    </memberdecl>
+    <detaileddescription title=""/>
+  </directory>
+</doxygenlayout>
diff --git a/GDALmake.opt.in b/GDALmake.opt.in
index 3d104c5..46a10a8 100644
--- a/GDALmake.opt.in
+++ b/GDALmake.opt.in
@@ -39,9 +39,8 @@ LIBS	=	$(SDE_LIB) @LIBS@ $(KAK_LIBS) $(DWG_LIBS) $(CURL_LIB) \
 		$(OPENCL_LIB) $(JVM_LIB) $(LIBICONV) $(FGDB_LIB) $(LIBXML2_LIB) $(MONGODB_LIB)
 
 SSEFLAGS = @SSEFLAGS@
-HAVE_SSE_AT_COMPILE_TIME = @HAVE_SSE_AT_COMPILE_TIME@
+SSSE3FLAGS = @SSSE3FLAGS@
 AVXFLAGS = @AVXFLAGS@
-HAVE_AVX_AT_COMPILE_TIME = @HAVE_AVX_AT_COMPILE_TIME@
 
 PYTHON = @PYTHON@
 PY_HAVE_SETUPTOOLS=@PY_HAVE_SETUPTOOLS@
@@ -73,7 +72,7 @@ CFLAGS		= @CFLAGS@ @C_WFLAGS@ $(USER_DEFS)
 CXXFLAGS	= @CXXFLAGS@ @CXX_WFLAGS@ $(USER_DEFS)
 CFLAGS_NOFTRAPV          = @CFLAGS_NOFTRAPV@ @C_WFLAGS@ $(USER_DEFS)
 CXXFLAGS_NOFTRAPV        = @CXXFLAGS_NOFTRAPV@ @CXX_WFLAGS@ $(USER_DEFS)
-CFLAGS_NO_LTO_IF_AVX_NONDEFAULT             = @CFLAGS_NO_LTO_IF_AVX_NONDEFAULT@ @C_WFLAGS@ $(USER_DEFS)
+CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT           = @CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT@ @CXX_WFLAGS@ $(USER_DEFS)
 CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT           = @CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT@ @CXX_WFLAGS@ $(USER_DEFS)
 
 NO_UNUSED_PARAMETER_FLAG = @NO_UNUSED_PARAMETER_FLAG@
@@ -120,9 +119,9 @@ GDAL_INCLUDE	=	-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore \
 
 # libtool targets and help variables
 LIBGDAL	:=		libgdal.la
-LIBGDAL_CURRENT	:=	21
-LIBGDAL_REVISION	:=	3
-LIBGDAL_AGE	:=	1
+LIBGDAL_CURRENT	:=	22
+LIBGDAL_REVISION	:=	0
+LIBGDAL_AGE	:=	2
 
 # native build targets and variables
 GDAL_VER	=	@GDAL_VER@
@@ -135,6 +134,7 @@ GDAL_VERSION_REV   =    @GDAL_VERSION_REV@
 GDAL_LIB	= 	$(GDAL_ROOT)/libgdal.a
 GDAL_SLIB	=	$(GDAL_ROOT)/libgdal.$(SO_EXT)
 GDAL_SLIB_LINK	=	-L$(GDAL_ROOT) -lgdal
+#GDAL_SLIB_SONAME = -Wl,-soname,libgdal.$(SO_EXT). at GDAL_VERSION_MAJOR@
 
 # Mac OS X Framework definition
 MACOSX_FRAMEWORK = @MACOSX_FRAMEWORK@
@@ -215,6 +215,8 @@ SPATIALITE_INC = @SPATIALITE_INC@
 SPATIALITE_AMALGAMATION = @SPATIALITE_AMALGAMATION@
 SPATIALITE_412_OR_LATER = @SPATIALITE_412_OR_LATER@
 HAVE_PCRE = @HAVE_PCRE@
+HAVE_RASTERLITE2 = @HAVE_RASTERLITE2@
+RASTERLITE2_CFLAGS = @RASTERLITE2_CFLAGS@
 
 #
 # JPEG2000 via Kakadu Support.
@@ -261,6 +263,11 @@ ECW_FLAGS	= @ECW_FLAGS@
 ECW_INCLUDE 	= @ECW_INCLUDE@
 ECW_LIBS	= @ECW_LIBS@
 
+#
+# JP2Lura Related
+#
+JP2LURA_INCLUDE 	= @JP2LURA_INCLUDE@
+
 # Xerces C++ XML Parser for GML and ILI
 #
 HAVE_XERCES	= @HAVE_XERCES@
@@ -294,9 +301,15 @@ OCI_INCLUDE	= @OCI_INCLUDE@
 HAVE_GEOS       =       @HAVE_GEOS@
 GEOS_CFLAGS     =       @GEOS_CFLAGS@
 
+# SFCGAL Support
+
+HAVE_SFCGAL       =       @HAVE_SFCGAL@
+SFCGAL_CFLAGS     =       @SFCGAL_CFLAGS@
+
 # QHull Support
 
 QHULL_SETTING   =       @QHULL_SETTING@
+QHULL_INCLUDE_SUBDIR_IS_LIBQHULL   =       @QHULL_INCLUDE_SUBDIR_IS_LIBQHULL@
 
 # GRASS Support
 
@@ -381,30 +394,9 @@ LIBXML2_INC = @LIBXML2_INC@
 LIBXML2_LIB = @LIBXML2_LIB@
 
 #
-# DWGdirect Library
-#
-DWGDIRECT =	@DWGDIRECT@
-DWG_PLT = @DWG_PLT@
-
-ifneq ($(DWGDIRECT),)
-DWG_LIBDIR =	$(DWGDIRECT)/lib/$(DWG_PLT)
-DWG_LIBS = $(DWG_LIBDIR)/DD_$(DWG_PLT)_ModelerGeometry.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_AcisRenderer.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Br.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_AcisBuilder.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Db.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Gs.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_SpatialIndex.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Gi.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Ge.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Root.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_FT.a \
-	$(DWG_LIBDIR)/DD_$(DWG_PLT)_Alloc.a
-HAVE_DWGDIRECT = yes
-else
-DWG_LIBS =
-HAVE_DWGDIRECT = no
-endif
+# CAD Support
+#
+HAVE_CAD	=	@CXX11_SUPPORT@
 
 #
 # Informix DataBlade support
@@ -508,6 +500,12 @@ PDFIUM_PLUGIN_LIB = @PDFIUM_PLUGIN_LIB@
 #CHARLS_LIB = -L/path/to/charls_lib -lCharLS
 
 #
+# Teigha stuff
+#
+HAVE_TEIGHA = @HAVE_TEIGHA@
+TEIGHA_DIR = @TEIGHA_DIR@
+
+#
 # PROJ.4 stuff
 #
 PROJ_STATIC	=	@PROJ_STATIC@
@@ -519,8 +517,6 @@ PROJ_INCLUDE	=	@PROJ_INCLUDE@
 PAM_SETTING     =       @PAM_SETTING@
 
 GDAL_LIBS	:= $(GDAL_LIB) $(OCI_LIB) $(GDAL_LIBS)
-# TODO: Remove -DOGR_ENABLED.
-CPPFLAGS	:= -DOGR_ENABLED $(CPPFLAGS)
 
 ifeq ($(GNM_ENABLED),yes)
 CPPFLAGS	:= -DGNM_ENABLED $(CPPFLAGS)
@@ -562,7 +558,8 @@ GDAL_FORMATS += nitf bmp airsar rs2 ilwis rmf leveller sgi srtmhgt
 GDAL_FORMATS += idrisi gsg ingr ers jaxapalsar dimap gff cosar pds adrg
 GDAL_FORMATS += coasp tsx terragen blx msgn til r northwood saga xyz hf2
 GDAL_FORMATS += kmlsuperoverlay ctg e00grid zmap ngsgeoid iris map cals
-GDAL_FORMATS += safe sentinel2
+GDAL_FORMATS += safe sentinel2 derived
+GDAL_FORMATS += prf
 GDAL_FORMATS += @OPT_GDAL_FORMATS@
 
 ifneq ($(PCIDSK_SETTING),no)
diff --git a/GNUmakefile b/GNUmakefile
index ec7d232..5635edf 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -1,4 +1,3 @@
-
 include GDALmake.opt
 
 GDAL_OBJ	=	$(GDAL_ROOT)/frmts/o/*.o \
@@ -53,7 +52,7 @@ $(GDAL_SLIB):	$(GDAL_OBJ) $(GDAL_LIB)
 		-o $(GDAL_SLIB)
 
 $(LIBGDAL):	$(GDAL_OBJ:.o=.lo)
-	$(LD) $(LDFLAGS) $(LIBS) -o $@ $(GDAL_OBJ:.o=.lo) \
+	$(LD) $(LDFLAGS) $(LIBS) -o $@ $(sort $(wildcard $(GDAL_OBJ:.o=.lo))) \
 	    -rpath $(INST_LIB) \
 	    -no-undefined \
 	    -version-info $(LIBGDAL_CURRENT):$(LIBGDAL_REVISION):$(LIBGDAL_AGE)
@@ -149,13 +148,20 @@ docs:
 	(cd doc/ru ; doxygen ; cp html/*.* ../../html/. )
 	(cd doc/br ; doxygen ; cp html/*.* ../../html/. )
 # Generate HTML docs
-	doxygen Doxyfile
+# Current DoxygenLayout.xml works only with Doxygen >= 1.8
+	@if [ `doxygen --version | awk -F . '{print $$1}'` -eq "1" ] && [ `doxygen --version | awk -F . '{print $$2}'` -lt "8" ]; then \
+	  echo "Using deprecated doxygen version. Removing custom layout"; \
+	  (cat Doxyfile; echo "LAYOUT_FILE=/dev/null") | doxygen -; \
+	else \
+	  doxygen Doxyfile; \
+	fi
 	cp data/gdalicon.png html
 	cp doc/images/*.* html
 	cp doc/grid/*.png html
 	cp frmts/*.html frmts/*/frmt_*.html html
 	cp frmts/openjpeg/*.xml html
 	cp frmts/wms/frmt_*.xml html
+	cp ogr/ogrsf_frmts/*/frmt_*.html html
 	cp ogr/ogrsf_frmts/*/drv_*.html html
 	cp ogr/ogrsf_frmts/ogr_formats.html html
 	cp ogr/ogr_feature_style.html html
@@ -166,7 +172,7 @@ docs:
 
 man:
 # Generate man pages
-	(cat Doxyfile ; echo "ENABLED_SECTIONS=man"; echo "INPUT=apps swig/python/scripts"; echo "FILE_PATTERNS=*.cpp *.dox"; echo "GENERATE_HTML=NO"; echo "GENERATE_MAN=YES") | doxygen -
+	(cat Doxyfile ; echo "ENABLED_SECTIONS=man"; echo "INPUT=apps swig/python/scripts"; echo "FILE_PATTERNS=*.cpp *.dox"; echo "GENERATE_HTML=NO"; echo "GENERATE_MAN=YES" ; echo "LAYOUT_FILE=/dev/null") | doxygen -
 # Remove "Directory reference" file. Not sure if there's a better way of doing it.
 	 @find man -name '_home_*_gdal_apps_.1' -exec rm {} \;
 
@@ -267,11 +273,9 @@ install-lib:
 	$(INSTALL_DIR) $(DESTDIR)$(INST_LIB)
 	$(INSTALL_LIB) $(GDAL_LIB) $(DESTDIR)$(INST_LIB)
 
-endif # HAVE_LD_SHARED=no 
-
-
-endif # HAVE_LIBTOOL=no 
+endif # HAVE_LD_SHARED=no
 
+endif # HAVE_LIBTOOL=no
 
 gdal.pc:	gdal.pc.in GDALmake.opt ./GNUmakefile VERSION
 	rm -f gdal.pc
diff --git a/HOWTO-RELEASE b/HOWTO-RELEASE
index 95f6c8f..bf02d2f 100644
--- a/HOWTO-RELEASE
+++ b/HOWTO-RELEASE
@@ -6,16 +6,16 @@ Prerequisites:
 
 1) Check that the release is ready to go as far as ABI (binary compatibility)
    is concerned. This can be checked by comparing the installed headers of the
-   candidate release with the installed headers of the previous release 
+   candidate release with the installed headers of the previous release
    (diff -ur $(OLD_INSTALL_DIR)/include $(NEW_INSTALL_DIR)/include). The API
    is defined as all functions and classes exported by the CPL_DLL keyword.
 
   - For major and minor releases, there must be no function signature change
     for the C API. Only new functions are allowed.
 
-  - For major releases, the allowed changes in C++ API should (or must?) be 
-    such that user calling C++ code can still compile against new headers 
-    without modification (existing methods can become virtual, default 
+  - For major releases, the allowed changes in C++ API should (or must?) be
+    such that user calling C++ code can still compile against new headers
+    without modification (existing methods can become virtual, default
     arguments can be added, new methods or members can be added)
 
   - For minor releases (1.6.1 versus 1.6.0), the C++ ABI stability must be
@@ -41,8 +41,9 @@ Process :
       must also be edited before if new utilities/scripts are added/removed.
 
 2) Update the release date, and number information in gcore/gdal_version.h.
+   Note: the format of GDAL_RELEASE_DATE should be YYYYMMDD.
 
-3) Update the VERSION file. 
+3) Update the VERSION file.
 
 3.1) Update ./swig/python/setup.py version information.
      And the version of libgdal in ./swig/python/README.txt
@@ -55,8 +56,8 @@ Perl module maintainer to make a CPAN release.
 3.3) For major releases update the VERSION macro in nmake.opt (for 1.6, 1.7etc)
 
 4) Update LIBGDAL_CURRENT/REVISION/AGE macros in GDALmake.opt.in.
-   - For a release with no interface changes just bump REVISION. 
-   - Adding interfaces, bump CURRENT/AGE, set REVISION to 0. 
+   - For a release with no interface changes just bump REVISION.
+   - Adding interfaces, bump CURRENT/AGE, set REVISION to 0.
    - Deleting interfaces / compatibility issues - bump CURRENT, others to zero.
 
 5) Prepare release overview in the NEWS file.  The Trac revision log for
@@ -66,17 +67,17 @@ Perl module maintainer to make a CPAN release.
 
   - commit new version to NEWS file.
 
-6) Update the GDAL http://trac.osgeo.org/gdal/wiki/DownloadSource topic to 
-   refer to the latest available source. 
+6) Update the GDAL http://trac.osgeo.org/gdal/wiki/DownloadSource topic to
+   refer to the latest available source.
    Update http://trac.osgeo.org/gdal/wiki (Releases section)
    Update http://trac.osgeo.org/gdal/wiki/NewsAndStatus
 
-7) If this is a major release, prepare a branch. 
+7) If this is a major release, prepare a branch.
 
    svn copy https://svn.osgeo.org/gdal/trunk \
             https://svn.osgeo.org/gdal/branches/1.5
 
-8) Tag the release set in SVN: 
+8) Tag the release set in SVN:
 
    svn copy https://svn.osgeo.org/gdal/branches/1.4 \
             https://svn.osgeo.org/gdal/tags/1.4.1
@@ -92,9 +93,9 @@ Perl module maintainer to make a CPAN release.
 10) Create a snapshot of the documentation.
 
  i.e. On www.gdal.org:
- % cd /osgeo/gdal
+ % cd /var/www/gdal
  % ./gdal-web-refresh.sh
- % zip -r gdal180doc.zip gdal-web/*.* gdal-web/ogr gdal-web/java 
+ % zip -r ~/gdal210doc.zip gdal-web/*.* gdal-web/java gdal-web/python
 
 11) Create a snapshot of autotest suite:
 
@@ -103,7 +104,7 @@ Perl module maintainer to make a CPAN release.
   zip -r gdalautotest-1.6.0.zip gdalautotest-1.6.0
 
 11.5) If changes have been made in the frmts/grass or ogr/ogrsf_frmts/grass dir,
-      generate an up-to-date gdal-grass snapshot (let's not forget do it for GDAL 1.7.0 !):
+      generate an up-to-date gdal-grass snapshot:
 
   % cd frmts/grass
   % make dist
@@ -114,22 +115,26 @@ Perl module maintainer to make a CPAN release.
   % ln -sf X.Y.Z CURRENT
 
 13) Announce release to :
-    - major release: gdal-dev at lists.osgeo.org, gdal-announce at lists.osgeo.org, news_item at osgeo.org. 
+    - major release: gdal-dev at lists.osgeo.org, gdal-announce at lists.osgeo.org, news_item at osgeo.org.
     - bugfix release: gdal-dev at lists.osgeo.org, gdal-announce at lists.osgeo.org
 
+Note: gdal-announce@ is moderated. Make sure that your email address is approved
+('mod' tick disabled in https://lists.osgeo.org/mailman/admin/gdal-announce/members),
+or your message manually approved, with an administrator of the list.
+
 14) Update the freecode.com (previously freshmeat) entry for GDAL.
 
 15) Update the freegis.org entry for GDAL.
 
 16) Update doc/index.dox to advertize the new release and link to the release notes
 
-17) Create a News page in Trac for the release (like 
+17) Create a News page in Trac for the release (like
 http://trac.osgeo.org/gdal/wiki/Release/1.7.0-News) and reference it from
-http://trac.osgeo.org/gdal/ (Releases) and 
+http://trac.osgeo.org/gdal/ (Releases) and
 http://trac.osgeo.org/gdal/wiki/NewsAndStatus .
 
 18) Add pointers to the source releases at:
-  
+
   http://trac.osgeo.org/gdal/wiki/DownloadSource
 
 19) Update Trac to mark this release milestone as "Completed", and create
@@ -169,22 +174,22 @@ d) For real :
 
 a) cd swig/java
 
-b) Make any updates to java.opt that might be required for the platform. For 
+b) Make any updates to java.opt that might be required for the platform. For
    example osx and windows users will have to change JAVA_INCLUDE to contain
-   include/darwin and include/win32 respectively. 
+   include/darwin and include/win32 respectively.
 
 c) Build the bindings:
 
      make
 
 22) Build maven artifacts. NOTE: This step only works on Linux and OSX since it
-    requires a shell script to build javadocs. 
+    requires a shell script to build javadocs.
 
     A quick one-liner for this step is:
 
       ant maven_sign -Dgpg.key=... -Dgpg.pass=...
 
-    This will build and sign the artifacts with a single command. Read on for 
+    This will build and sign the artifacts with a single command. Read on for
     more details.
 
 a)  Build the maven artifacts:
@@ -194,13 +199,13 @@ a)  Build the maven artifacts:
     Upon success maven artifacts should be located in the build/maven directory.
 
 b)  Sign maven artifacts with GPG. This step is required in order to deploy the
-    maven artifacts to the central Maven repository. Before this step can 
+    maven artifacts to the central Maven repository. Before this step can
     proceed you must set up a signing key as described here:
 
       http://central.sonatype.org/pages/working-with-pgp-signatures.html
 
     Each developer can use their own signing key although it is usually best to
-    avoid constantly using a different key for releases as users will need to 
+    avoid constantly using a different key for releases as users will need to
     import the public key in order to verify the artifacts.
 
     Here are a quick set of steps to generate a signing key key.
@@ -212,7 +217,7 @@ b)  Sign maven artifacts with GPG. This step is required in order to deploy the
     See the above link for more details.
 
     Once a key is set up run the "maven_sign" ant target. The target takes two
-    parameters specified as system properties: 
+    parameters specified as system properties:
 
     1. gpg.key - The identifier for the signing key
     2. gpg.pass - The passphrase for the signing key (optional)
@@ -224,14 +229,14 @@ b)  Sign maven artifacts with GPG. This step is required in order to deploy the
     that contains all the maven artifacts with signatures. This file is what
     will be uploaded to maven central. See the next step.
 
-23) Deploy maven artifacts to Maven central. 
+23) Deploy maven artifacts to Maven central.
 
     NOTE: Before you can deploy to maven central you must set up an account
     in Sonatype JIRA. That can be done here:
 
         https://issues.sonatype.org/secure/Signup!default.jspa
 
-    Once you have an account set up you must be associated with the gdal 
+    Once you have an account set up you must be associated with the gdal
     project. Create a ticket here asking to be associated with the project:
 
         https://issues.sonatype.org/browse/OSSRH
@@ -251,22 +256,22 @@ b) Once log in select "Staging Upload" on the left hand side.
 c) Select "Artifact Bundle" under "Upload Mode" and then choose the "bundle.jar"
    created in the previous Step 22. Finally "Upload Bundle" to start the upload.
 
-d) When the upload has been completed you will be notified that a staging 
+d) When the upload has been completed you will be notified that a staging
    repository has been created. Note the name of the repository. It should look
    something like "orggdal-100x".
 
 e) From the left hand menu navigate to "Staging Repositories". In the search
    box look for the staging repository name you noted from the previous section.
-   Or just search for "gdal". It should be obvious which repository is the 
+   Or just search for "gdal". It should be obvious which repository is the
    current one.
 
-f) Select the staging repository. If all is well You should see the option to 
-   "Release" (Located as a button near the top of the page). If not it means 
+f) Select the staging repository. If all is well You should see the option to
+   "Release" (Located as a button near the top of the page). If not it means
    there was an issue with the bundle. Consult the "Activity" tab at the bottom
-   of the page to find out why. 
+   of the page to find out why.
 
 e) Click the "Release" button and that is it! The release should be available in
-   Maven Central shortly. You can verify this by going to search.maven.org and 
-   searching for "gdal". 
+   Maven Central shortly. You can verify this by going to search.maven.org and
+   searching for "gdal".
 
 
diff --git a/MIGRATION_GUIDE.TXT b/MIGRATION_GUIDE.TXT
index fd1bc89..a2711d2 100644
--- a/MIGRATION_GUIDE.TXT
+++ b/MIGRATION_GUIDE.TXT
@@ -1,3 +1,15 @@
+MIGRATION GUIDE FROM GDAL 2.1 to GDAL 2.2
+-----------------------------------------
+
+A) RFC 64: Triangle, Polyhedral surface and TIN
+
+Link: https://trac.osgeo.org/gdal/wiki/rfc64_triangle_polyhedralsurface_tin
+
+Vector drivers can now return geometries of type wkbPolyhedralSurface, wkbTIN
+and wkbTriangle; and their Z, M and ZM variants (as well as for the type of
+geometry fields). Client code, as well as out-of-tree drivers that support
+writing geometries, must be ready to deal with them.
+
 MIGRATION GUIDE FROM GDAL 2.0 to GDAL 2.1
 ------------------------------------------
 
@@ -15,6 +27,24 @@ OGR core and drivers for now).
 Previously the ESRI Shapefile driver read XYM data as XYZ. Now it is read
 as XYM.
 
+B) RFC 67: Null values in OGR
+
+Link: https://trac.osgeo.org/gdal/wiki/rfc67_nullfieldvalues
+
+Previously, the "unset" state of a field was used both for a unset state
+(ie no information for the field of the feature) or the NULL state of the
+field. Now there is OGR_F_IsFieldSet() / OGRFeature::IsFieldSet() for the
+unset state, and a new OGR_F_IsFieldNull() / OGRFeature::IsFieldNull() for the
+new NULL state. Code that used OGR_F_IsFieldSet() / OGRFeature::IsFieldSet()
+should also test the NULL state, otherwise empty strings or 0 numeric values
+will be returned. A convenient way of migrating is to replace the use of
+OGR_F_IsFieldSet() / OGRFeature::IsFieldSet() by OGR_F_IsFieldSetAndNotNull() /
+OGRFeature::IsFieldSetAndNotNull() if there is no need to distinguish both
+states.
+On the writing side, a few drivers will now distinguish between the unset
+and null state, namely GeoJSON, CouchDB, Cloudant, MongoDB, ElasticSearch and
+GML.
+
 MIGRATION GUIDE FROM GDAL 1.11 to GDAL 2.0
 ------------------------------------------
 
@@ -135,7 +165,7 @@ Behaviour changes:
     it would have been interpreted as WHERE "a_column_name" = 'a_value" if
     a_column_name was indeed a column name.
 
-F) RFC 53: OGR not-null constraints and default values 
+F) RFC 53: OGR not-null constraints and default values
 
 Link: http://trac.osgeo.org/gdal/wiki/rfc53_ogr_notnull_default
 
@@ -168,7 +198,7 @@ Behaviour changes:
     * Drivers will now return OGRERR_NON_EXISTING_FEATURE when calling SetFeature()
       or DeleteFeature() with a feature id that does not exist.
 
-I) RFC 56: 
+I) RFC 56:
 
 Link: https://trac.osgeo.org/gdal/wiki/rfc56_millisecond_precision
 
@@ -179,16 +209,16 @@ API/ABI changes:
     The "GByte Second" field is now a "float Second".
 
   * OGRFeature::SetField( int i, int nYear, int nMonth, int nDay,
-                          int nHour=0, int nMinute=0, float fSecond=0.f, 
+                          int nHour=0, int nMinute=0, float fSecond=0.f,
                           int nTZFlag = 0 )
     and the variant that take a const char* as first argument now accept a
     floating-point number for seconds.
 
 API additions :
 
-    * OGRFeature::GetFieldAsDateTime( int i, 
+    * OGRFeature::GetFieldAsDateTime( int i,
                                      int *pnYear, int *pnMonth, int *pnDay,
-                                     int *pnHour, int *pnMinute, float *pfSecond, 
+                                     int *pnHour, int *pnMinute, float *pfSecond,
                                      int *pnTZFlag );
 
     * OGR_F_GetFieldAsDateTimeEx() and OGR_F_SetFieldDateTimeEx() are added.
diff --git a/NEWS b/NEWS
index 48e49fe..2ccc892 100644
--- a/NEWS
+++ b/NEWS
@@ -1,416 +1,845 @@
-= GDAL/OGR 2.1.3 Release Notes = 
+GDAL/OGR 2.2.0 Release Notes =
 
-The 2.1.3 release is a bug fix release.
+== In a nutshell... ==
 
-== Build ==
+ * New GDAL/raster drivers:
+   - DERIVED driver: read-support. Expose subdatasets in a a new metadata domain, called DERIVED_SUBDATASETS
+   - JP2Lura driver: read/create support for JPEG-2000 images using Luratech JP2 Library
+   - PRF: add read-only support for PHOTOMOD PRF file format driver (github #173)
+   - RRASTER driver: read-support .grd/.gri files handled by the R 'raster' package (#6249)
+ * New OGR/vector drivers:
+    - CAD driver: read support for DWG R2000 files (GSoC 2016 project)
+    - DGNv8 driver: read-write support for DGN 8.0 format (using Teigha ODA libraries)
+    - GMLAS driver: read-write support. XML/GML driver driven by Application Schemas.
+ * New utility script: ogrmerge.py to merge several vector datasets into a single one
+ * New /vsigs/ and /vsigs_streaming/ virtual file systems to read Google Cloud Storage non-public files
+ * Significantly improved drivers:
+  - NWT_GRD: write support (#6533)
+  - FileGDB/OpenFileGDB: add support to read curve geometries (#5890)
+  - VRT derived band: add the capability to define pixel functions in Python
+  - Add read support for RasterLite2 coverages in SQLite driver
+  - GPKG: implement tiled gridded elevation data extension
+  - ISIS3: add write support and improve read support
+ * RFC 63: Add GDALRasterBand::GetDataCoverageStatus() and implement it in GTiff and VRT drivers
+        https://trac.osgeo.org/gdal/wiki/rfc63_sparse_datasets_improvements
+ * RFC 64: Triangle, Polyhedral surface and TIN
+        https://trac.osgeo.org/gdal/wiki/rfc64_triangle_polyhedralsurface_tin
+ * RFC 66: OGR random layer read/write capabilities
+        https://trac.osgeo.org/gdal/wiki/rfc66_randomlayerreadwrite
+ * RFC 67: add null field state for OGR features, in addition to unset fields
+        https://trac.osgeo.org/gdal/wiki/rfc67_nullfieldvalues
+ * Upgrade to EPSG database v9.0 (#6772)
+ * Python bindings: Global Interpreter Lock (GIL) released before entering GDAL native code (for all, in GDAL module and a few ones in ogr like ogr.Open())
+ * Continued major efforts on sanitization of code base
+ * Remove bridge and vb6 bindings (#6640)
+ * GNM built by default
+
+== Installed files ==
+
+ * Removed: data/s57attributes_aml.csv data/s57attributes_iw.csv data/s57objectclasses_aml.csv data/s57objectclasses_iw.csv
+ * Added plscenesconf.json, gmlasconf.xsd
 
-* Windows: include plugins in clean, oci: also clean dll
-* windows: makegdal_gen.bat: update script to generate most recent Visual C++ project files (#6635)
+== Backward compatibility issues ==
 
-== Port ==
+See MIGRATION_GUIDE.TXT
 
-* CPLHTTPFetch(): add a CAINFO option to set the path to the CA bundle file. As a fallback also honour the CURL_CA_BUNDLE and SSL_CERT_FILE environment variables used by the curl binary, which makes this setting also available for /vsicurl/, /vsicurl_streaming/, /vsis3/ and /vsis3_streaming/ file systems (#6732)
-* Fix GetDiskFreeSpace() on 32bit Linux to avoid 32bit overflow when free disk space is above 4 GB (#6750)
+== GDAL/OGR 2.2.0 - General Changes ==
 
-== GDAL algorithms ==
+Build(Unix):
+ * improve detection of packaged libfyba (SOSI) --with-sosi, as in Ubuntu 16.04 (#6488)
+ * Sort files in static library to make the build reproducible (#6520)
+ * fix libqhull include path when it is /usr/local/include/libqhull (#6522)
+ * FileGDB: compilation fix on Linux in C++11 mode
+ * configure: make pdfium detection not fail if there are just warnings. And make configure fail if --with-pdfium was required but failed (#6653)
+ * Make ./configure --with-xerces fail if not found
+ * Don't install script documentation in INST_BIN (github #157)
+ * configure: autodetect webp without requiring explicit --with-webp
+ * configure: use pkg-config for HDF5 detection so that works out of the box on recent Ubuntu
+ * autodetect JDK 8 on Ubuntu
+ * MDB: allow libjvm.so to be dlopen'd with --with-jvm-lib=dlopen (Unix only, github #177)
+ * configure: delete temporary directories on the mac
+ * configure: make sure --with-macosx-framework is correctly defined
+ * configure: error out if --with-ld-shared is specified (#6769)
+ * configure: remove bashism.
+ * configure: fix --without-mrf (#6811)
+ * configure: take into account CXXFLAGS and LDFLAGS in a few more cases (cryptopp, podofo, libdap)
+ * Vagrant: all lxc and Hyper-V provider support; use vagrant-cachier for package caching
+ * configure: update DWG support to work with Teigha libraries
 
-* Warper: avoid undefined behaviour when doing floating point to int conversion, that may trigger exception with some compilers (LLVM 8) (#6753)
-* OpenCL wrapper: do not use CL_MEM_COPY_HOST_PTR flag as it is forbidden by the opencl spec for clGetSupportedImageFormats() use case. Fix for NVidia use case (#6624)
-* OpenCL wrapper: fix wrapping of Float32 data type with NVIDIA OpenCL (#6669)
+Build(Windows):
+ * Try to avoid confusiong between libqhull io.h and mingw own io.h (#6590)
+ * update script to generate most recent Visual C++ project files (#6635)
+ * fix broken and missing dependencies in makefile.vc
+ * add a way to use an external zlib (github #171)
+ * Rename makegdal_gen.bat to generate_vcxproj.bat
+ * generate_vcxproj.bat: Set correct value of PlatformToolset property based on specified Visual C++ version. Add NMAKE command line parameters: MSVC_VER based on specified Visual C++ version, DEBUG=1 WITH_PDB=1 to Debug build configuration.
+ * generate_vcxproj.bat: generate project for autotest/cpp (Ticket #6815)
+* Add WIN64=1 to NMAKE command line options.
+ * Add HDF4_INCLUDE option (#6805)
+ * Add MSVC compiler option /MP to build with parallel processes.
+ * Add ZLIB_LIB missing from EXTERNAL_LIBS
+ 
+Build(all):
+ * make Xerces 3.1 the minimal version
+ * drop support for PostgreSQL client library older than 7.4, or non security maintained releases older than 8.1.4, 8.0.8, 7.4.13, 7.3.15
 
-== Utilities ==
+== GDAL 2.2.0 - Overview of Changes ==
 
-* gdalinfo -json: fix order of points in wgs84Extent.coordinates (github #166)
-* gdal_rasterize: fix segfaults when rasterizing into an ungeoreferenced raster, or when doing 'gdal_rasterize my.shp my.tif' with a non existing my.tif (#6738)
-* gdal_calc.py: fix usage message
+Port:
+ * Export VSICreateCachedFile() as CPL_DLL so as to enable building JP2KAK as a plugin
+ * Added possibility to find GDAL_DATA path using INST_DATA definition without execution GDALAllRegister if GDAL_DATA placed in version named directory on Linux (#6543)
+ * Unix filesystem: make error message about failed open to report the filename (#6545)
+ * File finder: Remove hardcoded find location (/usr/local/share/gdal) (#6543)
+ * Win32 filesystem handler: make Truncate() turn on sparse files when doing file extension
+ * Add VSIFGetRangeStatusL() and VSISupportsSparseFiles()
+ * GDAL_NO_HARDCODED_FIND compilation option (#6543,#6531) to block file open calls (for sandboxed systems)
+ * Add VSIMallocAligned(), VSIMallocAlignedAuto() and VSIFreeAligned() APIs
+ * /vsizip / /vsitar: support alternate syntax /vsitar/{/path/to/the/archive}/path/inside/the/tar/file so as not to be dependent on file extension and enable chaining
+ * Optimize opening of /vsitar/my.tar.gz/my_single_file
+ * /vsizip/ : support creating non-ASCII filenames inside a ZIP (#6631)
+ * VSI Unix file system: fix behaviour in a+ mode that made MRF caching not work on Mac and other BSD systems
+ * Fix deadlock at CPLWorkerThreadPool destruction (#6646)
+ * Windows: honour GDAL_FILENAME_IS_UTF8 setting to call LoadLibraryW() (#6650)
+ * CPLFormFilename(): always use / path separator for /vsimem, even on Windows
+ * /vsimem/: add trick to limit the file size, so as to be able to test how drivers handle write errors
+ * /vsimem/: fix potential crash when closing -different- handles pointing to the same file from different threads (#6683)
+ * CPLHTTPFetch(): add MAX_FILE_SIZE option
+ * CPLHTTPFetch(): add a CAINFO option to set the path to the CA bundle file. As a fallback also honour the CURL_CA_BUNDLE and SSL_CERT_FILE environment variables used by the curl binary, which makes this setting also available for /vsicurl/, /vsicurl_streaming/, /vsis3/ and /vsis3_streaming/ file systems (#6732)
+ * CPLHTTPFetch(): don't disable peer certificate verification when doing https (#6734)
+ * CPLHTTPFetch(): cleanly deal with multiple headers passed with HEADERS and separated with newlines
+ * CPLHTTPFetch(): add a CONNECTTIMEOUT option
+ * CPLHTTPFetch(): add a GDAL_HTTP_HEADER_FILE / HEADER_FILE option.
+ * CPLHTTPSetOptions(): make redirection of POST requests to still be POST requests after redirection (#6849)
+ * /vsicurl/: take CPL_VSIL_CURL_ALLOWED_EXTENSIONS into account even if GDAL_DISABLE_READDIR_ON_OPEN is defined (#6681)
+ * /vsicurl/: get modification time if available from GET or HEAD results
+ * /vsis3/: add a AWS_REQUEST_PAYER=requester configuration option (github #186)
+ * CPLParseXMLString(): do not reset error state
+ * Windows: fix GetFreeDiskSpace()
+ * Fix GetDiskFreeSpace() on 32bit Linux to avoid 32bit overflow when free disk space is above 4 GB (#6750)
+ * Fix CPLPrintUIntBig() to really print a unsigned value and not a signed one
+ * Add CPL_HAS_GINT64, GINT64_MIN/MAX, GUINT64_MAX macros (#6747)
+ * Add CPLGetConfigOptions(), CPLSetConfigOptions(), CPLGetThreadLocalConfigOptions() and CPLSetThreadLocalConfigOptions() to help improving compatibility between osgeo.gdal python bindings and rasterio (related to https://github.com/mapbox/rasterio/pull/969)
+ * MiniXML serializer: fix potential buffer overflow.
 
-== GDAL drivers ==
+Core:
+ * Proxy dataset: add consistency checks in (the unlikely) case the proxy and underlying dataset/bands would not share compatible characteristics
+ * GDALPamDataset::TryLoadXML(): do not reset error context when parsing .aux.xml
+ * PAM/VRT: only take into account <Entry> elements when deserializing a <ColorTable>
+ * GDALCopyWords(): add fast copy path when src data type == dst data type == Int16 or UInt16
+ * GetVirtualMemAuto(): allow USE_DEFAULT_IMPLEMENTATION=NO to prevent the default implementation from being used
+ * Nodata comparison: fix test when nodata is FLT_MIN or DBL_MIN (#6578)
+ * GetHistogram() / ComputeRasterMinMax() / ComputeStatistics(): better deal with precision issues of nodata comparison on Float32 data type
+ * Fast implementation of GDALRasterBand::ComputeStatistics() for GDT_Byte and GDT_UInt16 (including use of SSE2/AVX2)
+ * Driver manage: If INST_DATA is not requested, do not check the GDAL_DATA variable.
+ * Make sure that GDALSetCacheMax() initialize the raster block mutex (#6611)
+ * External overview: fix incorrect overview building when generating from greater overview factors to lower ones, in compressed and single-band case (#6617)
+ * Speed-up SSE2 implementation of GDALCopy4Words from float to byte/uint16/int16
+ * Add SSE2 and SSSE3 implementations of GDALCopyWords from Byte with 2,3 or 4 byte stride to packed byte
+ * GDALCopyWords(): SSE2-accelerated Byte->Int32 and Byte->Float32 packed conversions
+ * Fix GDALRasterBand::IRasterIO() on a VRT dataset that has resampled sources, on requests such as nXSize == nBufXSize but nXSize != dfXSize
+ * GDALRasterBand::IRasterIO(): add small epsilon to floating-point srcX and srcY to avoid some numeric precision issues when rounding.
+ * Add GDALRasterBand::GetActualBlockSize() (#1233)
+ * Fix potential deadlock in multithreaded writing scenarios (#6661)
+ * Fix thread-unsafe behaviour when using GetLockedBlock()/MarkDirty()/DropLock() lower level interfaces (#6665)
+ * Fix multi-threading issues in read/write scenarios (#6684)
+ * Resampled RasterIO(): so as to get consistent results, use band datatype as intermediate type if it is different from the buffer type
+ * Add GDALIdentifyDriverEx() function (github #152)
+ * GDALOpenInfo: add a papszAllowedDrivers member and fill it in GDALOpenEx()
+ * GDALDefaultOverviews::BuildOverviews(): improve progress report
+ * Average and mode overview/rasterio resampling: correct source pixel computation due to numerical precision issues when downsampling by an integral factor, and also in oversampling use cases (github #156)
+ * Overview building: add experimental GDAL_OVR_PROPAGATE_NODATA config option that can be set to YES so that a nodata value in source samples will cause the target pixel to be zeroed. Only implemented for AVERAGE resampling right now
+ * GDALValidateOptions(): fix check of min/max values
+ * GMLJP2 v2: update to 2.0.1 corigendum and add capability to set gml:RectifiedGrid/gmlcov:rangeType content. Set SRSNAME_FORMAT=OGC_URL by default when converting to GML. Add gml:boundedBy in gmljp2:GMLJP2RectifiedGridCoverage
+ * GMLJP2 v2: ensure KML root node id unicity when converting annotations on the fly. When generating GML features, make sure that PREFIX and TARGET_NAMESPACE are unique when specifying several documents.
 
-ADRG driver:
-* handle north and south polar zones (ZNA 9 and 18) (#6783)
+Algorithms:
+ * RPC transformer: speed-up DEM extraction by requesting and caching a larger buffer, instead of doing many queries of just a few pixels that can be costly with VRT for example
+ * GDALDeserializeRPCTransformer(): for consistency, use the same default value as in GDALCreateRPCTransformer() if <PixErrThreshold> is missing (so use 0.1 instead of 0.25 as before)
+ * TPS solver: when Armadillo fails sometimes, fallback to old method
+ * GDALCreateGenImgProjTransformer2(): add SRC_APPROX_ERROR_IN_SRS_UNIT, SRC_APPROX_ERROR_IN_PIXEL, DST_APPROX_ERROR_IN_SRS_UNIT, DST_APPROX_ERROR_IN_PIXEL, REPROJECTION_APPROX_ERROR_IN_SRC_SRS_UNIT and REPROJECTION_APPROX_ERROR_IN_DST_SRS_UNIT transformer options, so as to be able to have approximate sub-transformers
+ * Fix GDAL_CG_Create() to call GDALContourGenerator::Init() (#6491)
+ * GDALContourGenerate(): handle the case where the nodata value is NaN (#6519)
+ * GDALGridCreate(): fix hang in multi-threaded case when pfnProgress is NULL or GDALDummyProgress (#6552)
+ * GDAL contour: fix incorrect oriented contour lines in some rare cases (#6563)
+ * Warper: multiple performance improvements for cubic interpolation and uint16 data type
+ * Warper: add SRC_ALPHA_MAX and DST_ALPHA_MAX warp options to control the maximum value of the alpha channel. Set now to 65535 for UInt16 (and 32767 for Int16), or to 2^NBITS-1. 255 used for other cases as before
+ * Warper: avoid undefined behaviour when doing floating point to int conversion, that may trigger exception with some compilers (LLVM 8) (#6753)
+ * OpenCL warper: update cubicConvolution to use same formula as CPU case (#6664)
+ * OpenCL warper: fix compliance to the spec. Fix issues with NVidia opencl (#6624, #6669)
+ * OpenCL warper: use GPU based over CPU based implementation when possible, use non-Intel OpenCL implementation when possible. Add BLACKLISTED_OPENCL_VENDOR and PREFERRED_OPENCL_VENDOR to customize choice of implementation
 
-DODS driver:
-* fix crash on URL that are not DODS servers (#6718)
+Utilities:
+ * gdalinfo -json: fix order of points in wgs84Extent.coordinates (github #166)
+ * gdalwarp: do not densify cutlines by default when CUTLINE_BLEND_DIST is used (#6507)
+ * gdalwarp: when -to RPC_DEM is specified, make -et default to 0 as documented (#6608)
+ * gdalwarp: improve detection of source alpha band and auto-setting of target alpha band. Automatically set PHOTOMETRIC=RGB on target GeoTIFF when input colors are RGB
+ * gdalwarp: add a -nosrcalpha option to wrap the alpha band as a regular band and not as the alpha band
+ * gdalwarp: avoid cutline densification when no transform at all is involved (related to #6648)
+ * gdalwarp: fix failure with cutline on a layer of touching polygons (#6694)
+ * gdalwarp: allow to set UNIFIED_SRC_NODATA=NO to override the default that set it to YES
+ * gdalwarp: fix -to SRC_METHOD=NO_GEOTRANSFORM -to DST_METHOD=NO_GEOTRANSFORM mode (#6721)
+ * gdalwarp: add support for shifting the values of input DEM when source and/or target SRS references a proj.4 vertical datum shift grid
+ * gdal_translate: when using -projwin with default nearest neighbour resampling, align on integer source pixels (#6610)
+ * gdal_translate & gdalwarp: lower the default value of GDAL_MAX_DATASET_POOL_SIZE to 100 on MacOSX (#6604)
+ * gdal_translate: avoid useless directory scanning on GeoTIFF files
+ * gdal_translate: make "-a_nodata inf -ot Float32" work without warning
+ * gdal_translate: set nodata value on vrtsource on scale / unscale / expand cases (github #199)
+ * GDALTranslate(): make it possible to create a anonymous target VRT from a (anonymous) memory source
+ * gdaldem: speed-up computations for src type = Byte/Int16/UInt16 and particularly for hillshade
+ * gdaldem hillshade: add a -multidirectional option
+ * GDALDEMProcessing() API: fix -alt support (#6847)
+ * gdal_polygonize.py: explicitly set output layer geometry type to be polygon (#6530)
+ * gdal_polygonize.py: add support for -b mask[,band_number] option to polygonize a mask band
+ * gdal_rasterize: make sure -3d, -burn and -a are exclusive
+ * gdal_rasterize: fix segfaults when rasterizing into an ungeoreferenced raster, or when doing 'gdal_rasterize my.shp my.tif' with a non existing my.tif (#6738)
+ * gdal_rasterize: fix crash when rasterizing empty polygon (#6844)
+ * gdal_grid: add a smoothing parameter to invdistnn algorithm (github #196)
+ * gdal_retile.py: add a -overlap switch
+ * gdal2tiles.py: do not crash on empty tiles generation (#6057)
+ * gdal2tiles.py: handle requested tile at too low zoom to get any data (#6795)
+ * gdal2tiles: fix handling of UTF-8 filenames (#6794)
+ * gdal2xyz: use %d formatting for Int32/UInt32 data types (#6644)
+ * gdal_edit.py: add -scale and -offset switches (#6833)
+ * gdaltindex: emit warning in -src_srs_format WKT when WKT is too large
+ * gdalbuildvrt: add a -oo switch to specify dataset open options
 
-HDF4 driver:
-* include hdf4compat.h in hdf4dataset.cpp
+Python samples:
+ * add validate_cloud_optimized_geotiff.py
+ * add validate_gpkg.py
 
-GRASS driver:
-* frmts/grass/pkg/configure: add support for GRASS 7.2 (#6785)
-* frmts/grass/pkg/Makefile.in: do not clone datum tables and drivers (#2953)
+Multi-driver:
+ * Add GEOREF_SOURCES open option / GDAL_GEOREF_SOURCES config. option to all JPEG2000 drivers and GTiff to control which sources of georeferencing can be used and their respective priority
 
-GTiff driver:
-* fix creating an image with the Create() interface with BLOCKYSIZE > image height (#6743)
-* don't check free disk space when outputting to /vsistdout/ (#6768)
+AIGRID driver:
+ * fix 2.1.0 regression when reading statistics (.sta) file with only 3 values, and fix <2.1 behaviour to read them in LSB order (#6633)
+ 
+AAIGRID driver:
+ * autodetect Float64 when the nodata value is not representable in the Float32 range
 
-Idrisi/RST driver:
-* on creation: use geotransform of source dataset even if it doesn't have a SRS (#6727)
+ADRG driver:
+ * handle north and south polar zones (ZNA 9 and 18) (#6783)
 
-netCDF driver:
-* fix erroneous detection of a non-longitude X axis as a longitude axis that caused a shift of 360m on the georeferencing (#6759)
+ASRP driver:
+ * fix georeferencing of polar arc zone images (#6560)
 
-OpenJPEG driver:
-* for single-line organized images, such as found in some GRIB2 JPEG2000 images, use a Wx1 block size to avoid huge performance issues (#6719)
+BMP driver:
 
-PCIDSK driver:
-* handle Exceptions returned from destructor and check access rights in setters (github #183)
+BPG driver:
+* declare GDALRegister_BPG as C exported for building as a plugin (#6693)
 
-RMF driver:
-* fix reading nodata for non-double data type (github #174)
+BLX driver:
 
-Sentinel2 driver:
-* add support for new "Safe Compact" encoding of L1C products (#6745)
+DIMAP driver:
+ * DIMAP: for DIMAP 2, read RPC from RPC_xxxxx.XML file (#6539)
+ * DIMAP/Pleiades metadata reader: take into tiling to properly shift RPC (#6293)
+ * add support for tiled DIMAP 2 datasets (#6293)
 
-VRT driver:
-* Fix linking error on VRTComplexSource::RasterIOInternal<float>() (#6748)
+DODS driver:
+ * fix crash on URL that are not DODS servers (#6718)
 
-== OGR core ==
+ECRG driver:
 
-* GML geometry parsing: avoid 'Cannot add a compound curve inside a compound curve' error (#6777)
-* Avoid assertion when stroking degenerated arcs (#6778)
-* Coordinate transformation: prevent unnecessary coordinate transformations (github #184)
+ECW driver:
+ * Add option ECW_ALWAYS_UPWARD=TRUE/FALSE  to work around issues with "Downward" oriented images (#6516).
 
-== OGR drivers == 
+ENVI driver:
+ * on closing, pad image file with trailing nul bytes if needed (#6662)
+ * add read/write support for rotated geotransform (#1778)
 
-AmigoCloud driver:
-* add option to receive an AmigoCloud API key in the connection string, fix page size (github #137)
+GeoRaster driver:
+ * fix report of rotation (#6593)
 
-GeoJSON driver:
-* fix segfaults on writing on NULL geometry with -lco WRITE_BBOX=YES (#6698)
-* support multilinestring from esriGeometryPolyline (#6773)
+GIF driver:
+
+GMT driver:
 
 GPKG driver:
-* don't show Spatialite vgpkg_ virtual tables (#6707)
+ * implement tiled gridded elevation data extension
+ * add VERSION creation option
+ * check if transaction COMMIT is successful (#6667)
+ * fix crash on overview building on big overview factor (#6668)
+ * fix crash when opening an empty raster with USE_TILE_EXTENT=YES
+ * fix gpkg_zoom_other registration
 
-ILI1 driver:
-* make polygon reconstruction in Surface layers robust to curves not in natural order (#6728)
+GTiff driver:
+ * support SPARSE_OK=YES in CreateCopy() mode (and in update mode with the SPARSE_OK=YES open option), by actively detecting blocks filled with 0/nodata about to be written
+ * When writing missing blocks (ie non SPARSE case), use the nodata value when defined. Otherwise fallback to 0 as before.
+ * in FillEmptyTiles() (ie in the TIFF non-sparse mode), avoid writing zeroes to file so as to speed up file creation when filesystem supports ... sparse files
+ * add write support for half-precision floating point (Float32 with NBITS=16)
+ * handle storing (and reading) band color interpretation in GDAL internal metadata when it doesn't match the capabilities of the TIFF format, such as B,G,R ordering (#6651)
+ * Fix RasterIO() reported when downsampling a RGBA JPEG compressed TIFF file (#6943)
+ * Switch search order in GTIFGetOGISDefn() - Look for gdal_datum.csv before datum.csv (#6531)
+ * optimize IWriteBlock() to avoid reloading tile/strip from disk in multiband contig/pixel-interleave layouts when all blocks are dirty
+ * fix race between empty block filling logic and background compression threads when using Create() interface and NUM_THREADS creation option (#6582)
+ * use VSIFTruncateL() to do file extension
+ * optimize reading and writing of 1-bit rasters
+ * fix detection of blocks larger than 2GB on opening on 32-bit builds
+ * fix saving and loading band description (#6592)
+ * avoid reading external metadata file that could be related to the target filename when using Create() or CreateCopy() (#6594)
+ * do not generate erroneous ExtraSamples tag when translating from a RGB UInt16, without explicit PHOTOMETRIC=RGB (#6647)
+ * do not set a PCSCitationGeoKey = 'LUnits = ...' as the PROJCS citation on reading
+ * fix creating an image with the Create() interface with BLOCKYSIZE > image height (#6743)
+ * fix so that GDAL_DISABLE_READDIR_ON_OPEN = NO / EMPTY_DIR is properly honoured and doesn't cause a useless directory listing
+ * make setting GCPs when geotransform is already set work (with warning about unsetting the geotransform), and vice-versa) (#6751)
+ * correctly detect error return of TIFFReadRGBATile() and TIFFReadRGBAStrip()
+ * in the YCBCR RGBA interface case, only expose RGB bands, as the alpha is always 255
+ * don't check free disk space when outputting to /vsistdout/ (#6768)
+ * make GetUnitType() use VERT_CS unit as a fallback (#6675)
+ * in COPY_SRC_OVERVIEWS=YES mode, set nodata value on overview bands
+ * read GCPs in ESRI <GeodataXform> .aux.xml
+ * explicitly write YCbCrSubsampling tag, so as to avoid (latest version of) libtiff to try reading the first strip to guess it. Helps performance for cloud optimized geotiffs
+ * Internal libtiff. Resync with CVS (post 4.0.7)
+ * Internal libtiff: fix 1.11 regression that prevents from reading one-strip files that have no StripByteCounts tag (#6490)
 
-MSSQL driver:
-* build optional mssql plugin with SQL Native Client support for MSSQL Bulk Copy
+GRASS driver:
+ * plugin configure: add support for GRASS 7.2 (#6785)
+ * plugin makefile: do not clone datum tables and drivers (#2953)
+ * use Rast_get_window/Rast_set_window for GRASS 7 (#6853)
+ 
+GRIB driver:
+ * Add (minimalistic) support for template 4.15 needed to read Wide Area Forecast System (WAFS) products (#5768)
+ * **Partial** resynchronization with degrib-2.0.3, mostly to get updated tables (related to #5768)
+ * adds MRMS grib2 decoder table (http://www.nssl.noaa.gov/projects/mrms/operational/tables.php) (github #160)
+ * enable PNG decoding on Unix (#5661, github #160)
+ * remove explicitly JPEG2000 decompression through Jasper and use generic GDAL code so that other drivers can be triggered
+ * fix a few crashes on malformed files
 
-NAS driver:
-* fix crash with enabled debugging
+GTX driver:
+ * add a SHIFT_ORIGIN_IN_MINUS_180_PLUS_180 open option
 
-SDE driver:
-* rename driver to OGR_SDE, and rename ICreateLayerFromRegInfo() as CreateLayerFromRegInfo() (#6714)
+HDF4 driver:
+ * Fixed erroneous type casting in HDF4Dataset::AnyTypeToDouble() that breaks reading georeferencing and other metadata
 
-Shape driver:
-* when rewriting the geometry of the last record in the .shp, do it at the file offset it previously used (#6787)
+HDF5 driver:
+ * correct number of GCPs to avoid dummy trailing (0,0)->(0,0,0) and remove +180 offset applied to GCP longitude. Add instead a heuristics to determine if the product is crossing the antimeridian, and a HDF5_SHIFT_GCPX_BY_180 config option to be able to override the heuristics (#6666)
 
-SQLite driver:
-* Spatialite: do not report some BLOB columns as geometry columns of tables/views (when found before the geometry column(s)) (#6695, #6659)
-* fix update of features with multiple geometry columns (#6696)
-* Spatialite: avoid spatial views to cause layers 'layer_name(geometry_name)' to be publicly listed (#6740)
-* SQLite/GPKG: add explicit error message when trying to open a read-only WAL-enabled database, and make sure when closing a WAL-enabled database opened in read-only mode to reopen it in read-write mode so that the -wal and -shm files are removed (#6776)
+HF2 driver:
 
-WFS driver:
-* fix potential nullptr dereference on dataset without layer (github #179)
+HFA driver:
+ * fix reading and writing of TOWGS84 parameters (github #132)
+ * export overview type from HFA files to GDAL metadata as OVERVIEWS_ALGORITHM (github #135)
+ * make .ige initialization use VSIFTruncateL() to be faster on Windows
+ * add support for TMSO and HOM Variant A projections (#6615)
+ * Add elevation units read from HFA files metadata (github #169)
+ * set binning type properly according to layerType being thematic or not (#6854)
 
-XLSX driver:
-* fix GDAL 2.1.2 regression regarding reading XLSX files whose sheet filenames are internally stored as 'absolute' (#6733)
-
-== Perl bindings ==
-* fix setting the geometry of a MultiLineString and MultiPolygon (#6786)
-
-== Python bindings ==
-* add outputType option to gdal.Rasterize() (#6710)
-* fix gdal.DEMProcessingOptions(zeroForFlat=True) (#6775)
-* swig/python/setup.py: fix build issues when CXX is defined in the environment (#6765)
-
-= GDAL/OGR 2.1.2 Release Notes = 
-
-The 2.1.2 release is a bug fix release.
-
-== Port ==
-* Fix deadlock at CPLWorkerThreadPool destruction (#6646)
-* CPLGetSymbol() on Windows: honour GDAL_FILENAME_IS_UTF8 setting to call
-  LoadLibraryW() (#6650)
-* /vsicurl/: take CPL_VSIL_CURL_ALLOWED_EXTENSIONS into account even if
-  GDAL_DISABLE_READDIR_ON_OPEN is defined (#6681)
-* Fix regression in PLScenes V1 raster random access. Add a CPL_VSIL_CURL_ALLOWED_FILENAME config option to solve that (fixes #6691)
-* /vsimem/: fix potential crash when closing -different- handles pointing to the same file from different threads (fixes #6683)
-
-== GDAL Core ==
-* Nodata comparison: fix test when nodata is FLT_MIN or DBL_MIN (#6578)
-* External overview: fix incorrect overview building when generating from greater
-  overview factors to lower ones, in compressed and single-band case (#6617)
-* Make sure that GDALSetCacheMax() initialize the raster block mutex (#6611)
-* Fix potential deadlock in multithreaded writing scenarios (#6661)
-* Make multi-threaded reading/writing when using GetLockedBlock()/MarkDirty()/
-  DropLock() lower level interfaces (#6665)
-* Fix multi-threading issues in read/write scenarios (fixes #6684)
-
-== Utilities ==
-* gdal_translate & gdalwarp: lower the default value of GDAL_MAX_DATASET_POOL_SIZE
-  to 100 on MacOSX (#6604)
-* gdalwarp: when -to RPC_DEM is specified, make -et default to 0 as documented (#6608)
-* gdalwarp: fix failure with cutline on a layer of touching polygons (#6694)
-* gdal_translate: when using -projwin with default nearest neighbour resampling,
-  align on integer source pixels (#6610)
-* gdal2xyz: use %d formatting for Int32/UInt32 data types (#6644)
-
-== GDAL drivers ==
+Idrisi driver:
+ * use geotransform of source dataset even if it doesn't have a SRS (#6727)
 
-AIGRID driver:
-* fix 2.1.0 regression when reading statistics (.sta) file with only 3 values,
-  and fix <2.1 behaviour to read them in LSB order (#6633)
+ILWIS driver:
+ * avoid IniFile::Load() to set the bChanged flag, so as to avoid a rewrite of files when just opening datasets
 
-ENVI driver:
-* on closing, pad image file with trailing nul bytes if needed (#6662)
+INGR driver:
 
-GeoRaster driver:
-* fix for geotransform matrix with rotation terms (#6593)
+ISCE driver:
+ * fix computation of line offset for multi-band BIP files, and warn if detecting a wrong file produced by GDAL 2.1.0 (#6556)
+ * fix misbehaviour on big endian hosts
+ * add support for reading and writing georeferencing (#6630, #6634)
+ * make parsing of properties case insensitive (#6637)
 
-GPKG driver:
-* check if transaction COMMIT is successful (#6667)
-* fix crash on overview building on big overview factor (#6668)
+ISIS3 driver:
+ * add write support
+ * add mask band support on read
+ * get label in json:ISIS3 metadata domain
+ 
+JPEGLS driver:
 
-GTiff driver:
-* fix saving and loading band description (#6592)
-* avoid reading external metadata file that could be related to the target
-  filename when using Create() or CreateCopy() (#6594)
-* do not generate erroneous ExtraSamples tag when translating from a RGB UInt16,
-  without explicit PHOTOMETRIC=RGB (#6647)
+JP2ECW driver:
+ * fix crash when translating a Float64 raster (at least with SDK 3.3)
 
-HDF4 driver:
-* Fixed erroneous type casting in HDF4Dataset::AnyTypeToDouble() breaking reading
-  georeference data and some other metadata from HDF4-EOS datasets (#6618)
+JP2KAK driver:
+ * add support for Kakadu v7.8
+ * catch exceptions in jp2_out.write_header()
 
-HDF5 driver:
-* correct number of GCPs to avoid dummy trailing (0,0)->(0,0,0) and remove +180
-  offset applied to GCP longitude. Add instead a heuristics to determine if the
-  product is crossing the antimeridian, and a HDF5_SHIFT_GCPX_BY_180 config option
-  to be able to override the heuristics (#6666)
+JP2OpenJPEG driver:
+ * add a USE_TILE_AS_BLOCK=YES open option that can help with whole image conversion
+ * prevent endless looping in openjpeg in case of short write
+ * for single-line organized images, such as found in some GRIB2 JPEG2000 images, use a Wx1 block size to avoid huge performance issues (#6719)
+  * ignore warnings related to empty tag-trees.
 
-ISCE driver:
-* make parsing of properties case insensitive (#6637)
+JPEG driver:
 
-netCDF driver:
-* fix crash on datasets with 1D variable with 0 record (#6645)
+JPIPKAK driver:
+ * fix random crashes JPIP in multi-tread environment (#6809)
 
-RMF driver:
-* fix wrong counter decrement that caused compressed RMF to be incorrectly
-  decompressed (https://github.com/OSGeo/gdal/pull/153)
-* fix load/store inversion of cm and dm units in MTW files (https://github.com/OSGeo/gdal/pull/162)
+KEA driver:
+ * Add support for Get/SetLinearBinning (#6855)
 
-ROI_PAC driver:
-* fix computation of line offset for multi-band BIP files, and warn if detecting
-  a wrong file produced by GDAL >= 2.0.0 (#6591)
+KMLSuperOverlay driver:
+ * recognize simple document made of GroundOverlay (#6712)
+ * Add FORMAT=AUTO option. Uses PNG for semi-transparent areas, else JPG. (#4745)
 
-SRTMHGT driver:
-* accept filenames like NXXEYYY.SRTMGL1.hgt (#6614)
+LAN driver:
+ * remove wrong byte-swapping for big-endian hosts
 
-VRT driver:
-* make CheckCompatibleForDatasetIO() return FALSE on VRTDerivedRasterBands (#6599)
-* fix performance issue when nodata set at band level and non-nearest resampling used (#6628)
-* VRTComplexSource: do temp computations on double to avoid precision issues
-  when band data type is Int32/UInt32/CInt32/Float64/CFloat64 (#6642)
-
-== OGR utilities ==
-* GDALVectorTranslate(): imply update mode if access mode not explicitly
-  specified and hDstDS != NULL (#6612)
-
-== OGR drivers == 
-
-Multi driver fix:
-* GPKG/SQLite/PG/FileGDB/MEM: properly set/reset field subtype with AlterFieldDefn() (fixes #6689)
-
-Carto driver:
-* rebranded from CartoDB to Carto. "CartoDB" is still a valid alias to Carto
-
-GPKG:
-* update schema to reflect CURRENT_TIMESTAMP -> 'now' changes (https://github.com/OSGeo/gdal/pull/155)
-* do not emit error when running ExecuteSQL() with a spatial filter on an empty
-  layer (#6639)
-* list (non spatial) layers not registered in gpkg_contents (#6679)
-* robustified layer deletion and renaming (#6679)
-* implementation of DeleteField, AlterFieldDefn and ReorderFields (#6679)
-* GetExtent() to save computed extent in gpkg_contents if empty (#6679)
-* add 'RECOMPUTE EXTENT ON' special SQL (#6679)
-* update last modified date on tiles update (#6679) 
-* check identifier unicity on layer creation (#6679)
-* add possibility to disable foreign key check by setting
-  OGR_GPKG_FOREIGN_KEY_CHECK=NO config option (#6679)
-* add HasSpatialIndex(tblname,geomcolname) SQL function (#6679)
+LCP driver:
 
-GML driver:
-* remove hack for CityGML regarding forcing srsDimension to 3 if not specified.
-  Instead add a GML_SRS_DIMENSION_IF_MISSING config option that can be set to
-  3 if needed (#6597)
-* consider srsName with URL like 'http://www.opengis.net/def/crs/EPSG/0/' as
-  following EPSG axis order. Add SWAP_COORDINATES=YES/NO/AUTO (and
-  GML_SWAP_COORDINATES configuration option) to override all auto guessing (#6678)
+Leveller driver:
 
-ILI1 driver:
-* fix crash in OGRILI1Layer::JoinSurfaceLayer() when the multicurve of the feature of the poSurfaceLineLayer layer is empty (fixes #6688)
+MAP driver:
+ * change logic to detect image file when its path is not absolute
 
-MSSQLSpatial driver:
-* Fix select layer to recognize geometry column with sqlncli (#6641)
+MBTiles driver:
+ * on opening if detecting 3 bands, expose 4 bands since there might be transparent border tiles (#6836)
 
-NAS driver:
-* Fix to handle that 'anlass' is optional
+MEM driver:
+ * disable R/W mutex for tiny performance increase in resampled RasterIO
+ * add support for overviews
+ * add support for mask bands
 
-OCI driver:
-* 3 new options: MULTI_LOAD, MULTI_LOAD_COUNT, FIRST_ID (#6606)
+MRF driver:
+ * bug fix in PNG and JPEG codecs
+ * Fixing a problem with setting NoData for MRFs generated with Create
+ * fix plugin building (#6498)
+ * rename CS variable so as to avoid build failure on Solaris 11 (#6559)
+ * Allow MRF to write the data file directly to an S3 bucket.
+ * Allow relative paths when MRF is open via the metadata string.
+ * Add support for spacing (unused space) between tiles. Defaults to none.
+ * Read a single LERC block as an MRF file.
 
-OSM driver:
-* fix issue garbage content when laundering tag name with column (https://github.com/OSGeo/gdal/pull/161)
+MSG driver:
+ * fix incorrect georeference calculation for msg datasets (github #129)
 
-PG driver:
-* fix errors caused by missing geometry_columns/spatial_ref_sys tables in non
-  PostGIS databases, that prevent reading more than 500 features (http://hub.qgis.org/issues/10904)
+NetCDF driver:
+ * add support for reading SRS from srid attribute when it exists and has content like urn:ogc:def:crs:EPSG::XXXX (#6613)
+ * fix crash on datasets with 1D variable with 0 record (#6645)
+ * fix erroneous detection of a non-longitude X axis as a longitude axis that caused a shift of 360m on the georeferencing (#6759)
+ * read/write US_survey_foot unit for linear units of projection
+ * apply 'add_offset' and 'scale_factor' on x and y variables when present, such as in files produced by NOAA from the new GOES-16 (GOES-R) satellite (github #200)
 
-PLScenes driver:
-* add HTTP retry logic (#6655)
-* V0 API: workaround limitations on filtering on image_statistics.image_quality (#6657)
+NGSGEOID driver:
 
-S57 driver:
-* fix GDAL 2.1.1 regression where open options are ignored if OGR_S57_OPTIONS
-  config option is not defined (#6609)
+NITF driver:
+ * implement creation of RPC00B TRE for RPC metadata in CreateCopy() mode
+ * add support for reading&writing _rpc.txt files
+ * nitf_spec.xml: Add support for MTIRPB TRE in NITF image segment. Also makes minor change to BLOCKA to include default values (github #127)
+ * nitf_spec.xml: add IMASDA and IMRFCA TREs
+ * GetFileList(): Small optimization to avoid useless file probing.
 
-Shapefile driver:
-* change REPACK implementation on Windows to be robust to remaining file
-  descriptors opened on the .shp/.shx/.dbf (#6672)
+Northwoord driver:
 
-SQLite driver:
-* do not emit error when running ExecuteSQL() with a spatial filter on an
-  empty layer (#6639)
-* Spatialite: avoid crash when creating layer with geom_type = wkbCurve (#6660)
-* don't touch nSoftTransactionLevel in DoTransactionCommand() in case of error,
-  since it can cause later CPLAssert() to trigger (#6667)
+NTv2 driver:
 
-XLSX driver:
-* only list worksheets (and no charts) as layers (#6680)
+NWT_GRD:
+ * detect short writes
 
-= GDAL/OGR 2.1.1 Release Notes = 
+PCIDSK driver:
+ * handle Exceptions returned from destructor and check access rights in setters (github #183)
 
-The 2.1.1 release is a bug fix release.
+PDF driver:
+ * implement loading/saving of metadata from/into PAM (#6600)
+ * implement reading from/writing to PAM for geotransform and projection (#6603)
+ * prevent crashes on dataset reopening in case of short write
 
-== Build ==
- * Unix: Fix compilation in std=c++11 mode with Ubuntu 16.04 (#6490)
- * Unix: fix libqhull include path when it is /usr/local/include/libqhull (#6522)
- * Fix build failure on Solaris 11 on MRF driver (#6559)
+PDS driver:
 
-== Port ==
- * Export VSICreateCachedFile() as CPL_DLL so as to enable building JP2KAK as a plugin (https://github.com/OSGeo/gdal/pull/126)
- * Unix filesystem: make error message about failed open to report the filename (#6545)
- * Fix VSIErrorV() buffer reallocation (#6545)
+PLScenes driver:
+ * add a METADATA open option
 
-== GDAL algorithms ==
- * Fix GDAL_CG_Create() to call GDALContourGenerator::Init() (#6491)
- * GDALContourGenerate(): handle the case where the nodata value is NaN (#6519)
- * GDALGridCreate(): fix hang in multi-threaded case when pfnProgress is NULL or GDALDummyProgress (#6552)
- * GDAL contour: fix incorrect oriented contour lines in some rare cases (#6563)
+PNG driver:
 
-== GDAL Core ==
- * DIMAP/Pleiades metadata reader: take into tiling to properly shift RPC (#6293)
+PostgisRaster driver:
+ * fix potential crash when one tile has a lower number of bands than the max of the table (#6267)
 
-== Utilities ==
- * gdal_polygonize.py: explicitly set output layer geometry type to be polygon (#6530)
- * gdalwarp: do not densify cutlines by default when CUTLINE_BLEND_DIST is used (#6507)
+R driver:
+ * fix out-of-memory (oom) with corrupt R file
+ 
+Raw drivers:
+ * prevent crashes on dataset closing in case of short write
 
-== GDAL drivers ==
+RIK driver:
 
-ASRP driver:
- * fix georeferencing of polar arc zone images (#6560)
+RMF driver:
+ * fix wrong counter decrement that caused compressed RMF to be incorrectly decompressed (github #153)
+ * fix load/store inversion of cm and dm units in MTW files (github #162)
+ * fix reading nodata for non-double data type (github #174)
 
-ECW driver:
- * Add configuration option ECW_ALWAYS_UPWARD=TRUE/FALSE  to work around issues with "Downward" oriented images (#6516)
+ROIPAC driver:
+ * add support for reading/writing .flg files (#6504)
+ * fix computation of line offset for multi-band BIP files, and warn if detecting a wrong file produced by GDAL >= 2.0.0 (#6591)
+ * fix for big endian hosts
 
-GTiff driver:
- * fix RasterIO() reported when downsampling a RGBA JPEG compressed TIFF file (#6943)
- * fix suboptimal behaviour before regarding flushing of working buffer (#6580)
- * fix race between empty block filling logic and background compression threads when using Create() interface and NUM_THREADS creation option (#6582)
- * Internal libtiff: fix 1.11 regression that prevents from reading one-strip files that have no StripByteCounts tag (#6490)
+RS2 driver:
+ * add support for reading RPC from product.xml
 
-ISCE driver:
- * fix computation of line offset for multi-band BIP files, and warn if detecting a wrong file produced by GDAL 2.1.0 (#6556)
+SAFE driver:
+ * fix handling of SLC Products by providing access to measurements as subdatasets (#6514)
 
-JP2KAK driver:
- * add support for Kakadu v7.8 (https://github.com/OSGeo/gdal/pull/138)
+Sentinel2 driver:
+ * add support for new "Safe Compact" encoding of L1C products (fixes #6745)
 
-MRF driver:
- * Fix plugin building (#6498)
- * Fix crashes on MRF using JPEG or PNG crashes due to dandling pointer (#6554)
- * Fix crashes when NoData is set after create (#6555)
+SQLite driver:
+ * Add read support for RasterLite2 coverages in SQLite driver
 
-PostgisRaster driver:
- * fix potential crash when one tile has a lower number of bands than the max of the table (fixes #6267)
+SRTMHGT driver:
+ * open directly .hgt.zip files
+ * accept filenames like NXXEYYY.SRTMGL1.hgt (#6614)
+ * handle files for latitude >= 50 (#6840)
 
-SAFE driver:
- * fix handling of SLC Products by providing access to measurements as subdatasets (#6514)
+VICAR driver:
 
 VRT driver:
-  * avoid useless floating point values in SrcRect / DstRect (#6568)
-  * VRT warp: fix issue with partial blocks at the right/bottom and dest nodata values that are different per band (#6581)
+ * add default pixel functions: real, imag, complex, mod, phase, conj, etc... for complex data types (github #141)
+ * avoid useless floating point values in SrcRect / DstRect (#6568)
+ * avoid buffer initialization in RasterIO() when possible (replace ancient and likely broken concept of bEqualAreas)
+ * make CheckCompatibleForDatasetIO() return FALSE on VRTDerivedRasterBands (#6599)
+ * VRT warp: fix issue with partial blocks at the right/bottom and dest nodata values that are different per band (#6581)
+ * fix performance issue when nodata set at band level and non-nearest resampling used (#6628)
+ * VRTComplexSource: do temp computations on double to avoid precision issues when band data type is Int32/UInt32/CInt32/Float64/CFloat64 (#6642)
+ * VRT derived band: add the capability to define pixel functions in Python
+ * CreateCopy(): detect short writes
+ * Fix linking error on VRTComplexSource::RasterIOInternal<float>() (#6748)
+ * avoid recursion in xml:VRT metadata (#6767)
+ * prevent 'Destination buffer too small' error when calling GetMetadata('xml:VRT') on a in-memory VRT copied from a VRT
+ * fix 2.1 regression that can cause crash in VRTSimpleSource::GetFileList() (#6802)
 
-== OGR core ==
- * Fix assertion in OGRGeometryFactory::GetCurveParmeters() on degnerated CIRCULARSTRING (#6553)
+WMS driver:
+ * Added support for open options to WMS minidrivers
+ * Refactored the multi-http code to make it possible to do range requests.
+ * Added a minidriver_mrf, which reads from remote MRFs using range requests.
+ * Made the minidriver_arcgis work with an ImageService, not only MapService.
+ * Added static cache of server response.
+ * Allow tiledWMS to work in off-line mode by including the server response in the .wms file itself.
+ * honour GDAL_HTTP_USERAGENT config option when it is set and <UserAgent> is missing (#6825)
+ * WMS/WMTS: better deal with tiles with different band count (grayscale, gray+alpha, palette, rgb, rgba) (github #208)
+ * Make HTTPS options apply to tWMS minidriver init, better HTTP error reporting
+
+WMTS driver:
+ * do not take into account WGS84BoundingBox/BoundingBox that would be the result of the densified reprojection of the bbox of the most precise tile matrix
+ * add TILEMATRIX / ZOOM_LEVEL open options
+ * accept tiles of small dimensions (github #210)
+
+XYZ driver:
+
+== OGR 2.2.0 - Overview of Changes ==
+
+Core:
+ * Layer algebra: Add KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO option to Intersection, Union and Identity.
+Default is yes, but it is set to no unless result layer is of geom type unknown.
+If set to no, result features which would have lower dim geoms are skipped
+if operating on two layers with same geom dim.
  * Fix crash/corrupted values when running importFromWkb() on POLYGON M/POLYGON ZM geometries (#6562)
+ * Add OGR_WKT_PRECISION config option that defaults to 15 to select the number of decimals when outputting to WKT
+ * Make OGRFeature::SetField(string) accept JSon serialized arrays for the String/Integer/Integer64/RealList types; add reciprocal OGRFeature::GetFieldAsSerializedJSon() for those types
+ * OGRGeometryFactory::transformWithOptions(): better deal with reprojection from polar projection to WGS84, and projections crossing the antimeridian to WGS84, by splitting geometries prior to reprojection (#6705)
+ * LinearRing transformTo(): force last point to be identical to first one in case it is not.
+ * GML geometry parsing: avoid 'Cannot add a compound curve inside a compound curve' error (#6777)
+ * OGR SQL: fix IN filtering on MapInfo indexed columns (#6798)
+ * OGR SQL: add support for LIMIT and OFFSET keywords
+ * OGR SQL: add comparisons on date / datetime (#6810)
+ * OGR SQL: increase efficiency of DISTINCT operator
+ * OGREnvelope: change initialization to fix issue when getting MULTIPOINT(0 0,1 1) envelope (#6841)
 
-== OGRSpatialReference == 
+OGRSpatialReference:
+ * Upgrade to EPSG database v8.9
+ * OGRCT: upgrade LIBNAME of mingw and cygwin to libproj-9.dll and cygproj-9.dll to be uptodate with proj 4.9.X (recommended method is using ./configure --with-static-proj4 instead) (#6501)
  * importFromESRI(): fix import of multi line MERCATOR SRS (#6523)
  * morphToESRI(): correctly compute standard_parallel_1 of Mercator(2SP) projection from scale factor of Mercator(1SP) (#6456, #4861)
+ * exportToProj4(): recognize explicit OSR_USE_ETMERC=NO to avoid using etmerc with proj >= 4.9.3
+ * importFromProj4(): do not set a AUTHORITY node for strings like '+init=epsg:XXXX +some_param=val'
+ * importFromProj4(): be robust with missing proj.4 epsg dictionary when importing '+init=epsg:xxxx +other_parm=value'
+ * AutoIdentifyEPSG(): add identification of EPSG:3995 (Arctic Polar Stereographic on WGS84) and EPSG:3031 (Antarctic Polar Stereographic on WGS84)
+ * OGRCoordinateTransformation: avoid potential bugs in proj.4 on NaN input
+ * importFromEPSG(): take into account DX,DY,DZ,RX,RY,RZ,DS columns in pcs.csv to add per-PCS TOWGS84 overrides (geotiff #52)
+ * Coordinate transformation: prevent unnecessary coordinate transformations (github #184, #185) 
 
-== OGR utilities ==
- * ogr2ogr: keep -append and -overwrite when -update follows (backport trunk r34341)
- * ogr2ogr: do not return error on ogr2ogr --utility_version (backport of trunk r34340)
+Utilities:
+ * ogr2ogr: do not return error on ogr2ogr --utility_version
+ * ogr2ogr: keep -append and -overwrite when -update follows
  * ogr2ogr: fix heuristics to detect likely absence of '-f' (#6561)
+ * ogr2ogr: do not emit a warning when updating/overwriting a destination dataset that is not a Shapefile and if -f is not specified (#6561)
+ * ogr2ogr: make overwriting of lots of PG tables less prone to PostgreSQL 'out of shared memory' errors, by committing transactions after each table recreation
+ * ogr2ogr: prevent 'ogr2ogr same.shp same.shp' (#1465)
+ * ogr2ogr: add a -limit option to limit the number of features read per layer
+ * GDALVectorTranslate(): imply update mode if access mode not explicitly specified and hDstDS != NULL (#6612)
+ * ogrlineref: Fix crash if no new layer name provided
+ * ogrtindex: add -src_srs_name, -src_srs_format and -t_srs option to allow indexing files that have different projections
+
+Multidriver:
+ * PGeo/FileGDB/OpenFileGDB: OGRCreateFromShapeBin(): do not error out on empty lines/polygons
+ * GPKG/SQLite/PG/FileGDB/MEM: properly set/reset field subtype with AlterFieldDefn() (#6689)
+ * DXF, GeoJSON, GML, KML, LIBKML, ODS, Shape, XLSX: report operating system error if file creation fails (#2253)
 
-== OGR drivers == 
+AmigoCloud driver:
+ * add option to receive an AmigoCloud API key in the connection string, fix page size (github #137)
 
-CartoDB driver:
+Carto:
+ * renamed from CartoDB
  * fix CartoDB'fication() by removing manual creation of the_geom_webmercator mercator, and also attach created sequence to table.cartodb_id (#6565)
 
+CSV driver:
+ * add read/write support for String/Integer/Integer64/RealList types as serialized JSon arrays
+
+DGN driver:
+ * avoid crash with -ftrapv on 250K_NF44NE_Area_V7.dgn (relates to #6806)
+ * use coordinate delta encoding from the attribute records array (6806)
+
+DXF driver:
+ * sanitize layer name on export to avoid forbidden characters
+ * reader: convert GeometryCollection to MultiPoint, MultiLineString or MultiPolygon when possible (QGIS #10485)
+ * add font of TEXT and MTEXT to OGR style string (https://github.com/OSGeo/gdal/pull/198)
+
+DWG driver:
+ * compilation fixes with Teigha 4.2.2
+
+ElasticSearch driver:
+ * add support for ElasticSearch 5.0 and fix 2.X support (#6724)
+ * implement translation from SQL to E.S. query language
+
+FileGDB driver:
+ * add support to read curve geometries (#5890)
+ * support opening '.' directory
+
 GeoJSON driver:
+ * writer: add a RFC7946=YES creation option (#6705)
+ * read and write 'name' and 'description' members at FeatureCollection level
  * fix field type detection when first value of a field is null (#6517)
- * ESRI Json reader: do not set field width of 2147483647 (#6529)
  * fix wrong behaviour when there's a 'id' at Feature level and 'id' or 'ID' field in properties (#6538)
  * in case top level id is a negative integer, put the value in a 'id' attribute (#6538)
+ * ESRI Json reader: support multilinestring from esriGeometryPolyline
+ * ESRI Json reader: do not set field width of 2147483647 (#6529)
+ * Add CPL_json_object_object_get() and use it, to avoid deprecation warnings on json_object_object_get()
+ * TopoJSON reader: sanitize invalid polygons (such as found in the 'TopoJSON' layer of http://bl.ocks.org/mbostock/raw/4090846/us.json)
+ * writer: fix segfaults on NULL geometry with -lco WRITE_BBOX=YES (#6698)
+ * Add support of TopoJSON without 'transform' element (github #192)
+ * don't set SRS if 'crs' set to null (github #206)
+
+GML driver:
+ * remove hack for CityGML regarding forcing srsDimension to 3 if not specified. Instead add a GML_SRS_DIMENSION_IF_MISSING config option that can be set to 3 if needed (#6597)
+ * consider srsName with URL like 'http://www.opengis.net/def/crs/EPSG/0/' as following EPSG axis order. Add SWAP_COORDINATES=YES/NO/AUTO (and GML_SWAP_COORDINATES configuration option) to override all auto guessing (#6678)
+ * add a SRSNAME_FORMAT=SHORT/OGC_URN/OGC_URL dataset creation option
+ * OGR_G_ExportToGMLEx(): add a COORD_SWAP option
+ * Writer: make ogr:FeatureCollection be a substitutionGroup of AbstractFeature for GML 3.2 output, so as to be compatible of GMLJP2 v2
+ * GML and NAS: improve error reporting (mention feature id and gml_id) when parsing fails because of geometry decoding error
+ * GML and NAS: add GML_SKIP_CORRUPTED_FEATURES and NAS_SKIP_CORRUPTED_FEATURES configuration options to avoid stopping reading a layer because of a corrupted geometry
+ * Add support for Japanese GML FGD v4.1 format (github #204)
+
+GPKG driver:
+ * list all tables/views by default (useful for non spatial tables not registered as aspatial). Add ASPATIAL_VARIANT layer creation option to select the way how to create a non-spatial table as aspatial.
+ * Create non-spatial tables by default conforming to GPKG v1.2 'attributes'
+ * use OGR_CURRENT_DATE config option if defined as the value of the 'last_change' of column of 'gpkg_contents' so as to be able to have binary identical output
+ * update last_change column when content of raster or vector tables has changed
+ * do not emit error when running ExecuteSQL() with a spatial filter on an empty layer (#6639)
+ * update schema to reflect CURRENT_TIMESTAMP -> 'now' changes (github #155)
+ * better table and column quoting.
+ * Robustify layer deletion (make it accessible through DROP TABLE xxx and DELLAYER:xxx syntax) and renaming
+ * implement DeleteField(), AlterFieldDefn(), ReorderFields()
+ * make GetExtent() save extent if not already cached
+ * add special SQL 'RECOMPUTE EXTENT ON layer_name' to force recomputation of extent
+ * check identifier unicity on layer creation
+ * add possibility to disable foreign key check by setting OGR_GPKG_FOREIGN_KEY_CHECK=NO config option
+ * add HasSpatialIndex(tblname,geomcolname) SQL function
+ * don't show Spatialite vgpkg_ virtual tables (#6707)
+ * SQLite/GPKG: add explicit error message when trying to open a read-only WAL-enabled database (#6776)
+ * SQLite/GPKG: make sure when closing a WAL-enabled database opened in read-only mode to reopen it in read-write mode so that the -wal and -shm files are removed (#6776)
+ * make GetFeature() works on non conformant tables that have no integer primary key field (#6799), and be robust to non standard column types
+ * remove triggers related to metadata tables that cause issues and have been removed by latest revisions of the spec.
+ * declare feature id column of features tables and tile pyramid user data tables as NOT NULL (#6807)
+ * add a gpkg_ogr_contents table to store feature count.
+ * speed-up GetFeatureCount() with only a spatial filter set
+ * improve column recognition for SQL result layer
+ * add/override ST_Transform() and SridFromAuthCRS() from Spatialite to make them work with gpkg_spatial_ref_sys
+ * add ImportFromEPSG()
+ * make ST_Min/MaxX/Y(), ST_SRID(), ST_GeometryType() and ST_IsEmpty() work with Spatialite geometries
+ * improve performance of spatial index creation and use on multi-gigabyte databases
+ * better support of spatial views, by adding a special behaviour if a column is named OGC_FID
+ * avoid potential denial of services by adding LIMIT clauses
+ * slightly more efficient implementation of GetExtent() if extent in gpkg_contents is empty
+ * create a dummy 'ogr_empty_table' features table in case we have no 'features' or 'tiles' table, so as to be conformant with Req 17 of the GeoPackage specification
+ * add DEFAULT '' to metadata column of gpkg_metadata table
+ * accept opening a .gpkg without vector content and without gpkg_geometry_columns table in vector mode if we also open in update mode; remove capability of opening a .gpkg without vector content but with gpkg_geometry_columns table in vector mode if we only open in read-only mode; fix creation of a vector layer in a database if it initially lacks a gpkg_geometry_columns table
+ * fix appending a raster to a vector database without pre-existing raster support tables
+ * add minimalistic support for definition_12_063 column in gpkg_spatial_ref_sys, so that insertion of new SRS doesn't fail
+ * use GEOMETRYCOLLECTION instead of GEOMCOLLECTION for SQL and gpkg_geometry_columns.geometry_type_name
+ * do not warn if gpkg_metadata extension declared
+
+GPX driver:
+
+ILI driver:
+ * ILI1: fix crash in JoinSurfaceLayer() when the multicurve of the feature of the poSurfaceLineLayer layer is empty (#6688)
+ * ILI1: make polygon reconstruction in Surface layers robust to curves not in natural order (#6728)
+ * ILI2: assign FID to features (#6839)
+ * ILI2: fix crashing bug in Create() if model file not specified
+
+JML driver:
+
+KML driver:
+ * add a DOCUMENT_ID datasource creation option to set the id of the root <Document> node
 
 LIBKML driver:
  * fix crash when reading <gx:TimeStamp> or <gx:TimeSpan> elements (#6518)
+ * add a DOCUMENT_ID datasource creation option to set the id of the root <Document> node
+ * emit style related errors as warnings to make datasets openable by SWIG bindings (#6850)
+
+Memory driver:
 
 MITAB driver:
  * limit (width, precision) of numeric fields on creation to (20,16) for compatibility with MapInfo (#6392)
-
+ * add support for oblique stereographic (#6598)
+ * Adds the authority code for Irish national grid (Ireland_1965) (github #149)
+ * fix spelling for Euref_89 and add EPSG code (#6816)
+ 
 MSSQLSpatial driver:
- * Fix MSSQL bulk insert with table names containing spaces (#6527)
+ * Fix bulk insert with table names containing spaces (#6527)
+ * Build optional mssql plugin with SQL Native Client support for MSSQL Bulk Copy
+ * Fix MSSQL select layer to recognize geometry column with sqlncli (#6641)
 
+MySQL driver:
+ * fix spatial filtering on recent mysql by adding a SRID in the rectangle geometry
+ * do not force NOT NULL constraint on geometry field if no spatial index is used
+ 
 NAS driver:
- * support multiple 'anlass' in updates (cherry picked from r34461)
+ * support multiple 'anlass' in updates
+
+NTF driver:
+
+NWT_GRD:
+ * add write support (#6533)
+
+OCI driver:
+ * Add options for faster feature loading (#6606)
+ * add WORKSPACE open option
+ * correctly handle OFTInteger64 case in loader layer (bug found by cppcheck multiCondition)
+
+ODBC driver:
+
+ODS driver:
+ * fix FID filtering (#6788)
+
+OGDI driver:
+ * make GetNextRawFeature() report an error when it is not end of layer
+ * better error reporting when the layer list cannot be established
+ * catch non-fatal OGDI errors emitted by OGDI 3.2.0 if OGDI_STOP_ON_ERROR environment variable is set to NO, and emit them as CPLError()s
+ * display OGDI error message if opening fails
 
 OpenFileGDB driver:
- * transcode UTF-16 strings found in column names, alias, etc... to UTF-8 (instead of using only their ASCII byte) (#6544)
  * do not error out on geometries that have a declared M array but that is missing (#6528)
+ * add support to read curve geometries (#5890)
+ * transcode UTF-16 strings found in column names, alias, etc... to UTF-8 (instead of using only their ASCII byte) (#6544)
  * do not emit an error on a empty table whose declaration has M settings (#6564)
+ * support opening '.' directory
+ * improve detection of some form of TINs from MULTIPATCH, and for MultiPatch layers, try to select a better geometry type for those layers (#5888)
+ * fix bug when field description offset is beyond 4GB (#6830)
+
+OSM driver:
+ * fix 'too many tags in relation' error when parsing .osm files
+ * allow key=value entries in closed_ways_are_polygons= configuration (#6476)
+ * allow OSM_SQLITE_CACHE config option to be greater than 2047
 
 PG driver:
  * fix insertion of binary/bytea content in non-copy mode (#6566)
+ * fix errors caused by missing geometry_columns/spatial_ref_sys tables in non PostGIS databases, that prevent reading more than 500 features (QGIS #10904)
 
-ROI_PAC driver:
- * add support for reading/writing .flg files (#6504)
+PGDump driver:
+
+PLScenes driver:
+ * add HTTP retry logic (#6655)
+ * V0 API: workaround limitations on filtering on image_statistics.image_quality (#6657)
+ * add support for Data V1 API
 
 S57 driver:
- * Fix ogr2ogr -S57 (#6549)
+ * Fix ogr2ogr -f S57 (#6549)
+ * fix crashes if the s57objectclasses.csv resource file contains invalid lines
+ * remove data/s57attributes_aml.csv data/s57attributes_iw.csv data/s57objectclasses_aml.csv data/s57objectclasses_iw.csv and move their content into main s57attributes.csv and s57objectclasses.csv files (#6673)
+ * Update s57 attributes and object classes according to s-57 reference (github #202)
+
+SDE driver:
+ * rename driver to OGR_SDE. Fix build (#6714)
+
+SEGY driver:
+ * Accept SEGY files with ASCII headers that have nul terminated strings (#6674)
+
+Shapefile driver:
+ * auto-repack by default at dataset closing and FlushCache()/SyncToDisk() time. Controlled by AUTO_REPACK open and layer creation options (that default to YES)
+ * generate .dbf end-of-file 0x1A character by default. Add DBF_EOF_CHAR layer creation options / open options to control that behaviour
+ * writing: use strerrno() for better error messages (QGIS #13468)
+ * change REPACK implementation on Windows to be robust to remaining file descriptors openend on the .shp/.shx/.dbf (#6672, QGIS #15570)
+ * Fix issue in DBFCloneEmpty() one a one field DBF not yet written to disk
+ * add call to AutoIdentifyEPSG() when reading a .prj
+ * support reading .dbf with substantial padding after last field definition.
+ * when rewriting the geometry of the last record in the .shp, do it at the file offset it previously used (#6787)
+
+SOSI driver:
+ * make registration of driver work again (2.1.0 regression) (#6500)
+ * update to latest version of https://github.com/kartverket/gdal. Make SOSI driver support more geometry types (including curved geometries) plus provides some improvements on attribute-type mapping. Fix some memory errors/leaks. Disable by default non working creation code (#6503)
+
+SQLite/Spatialite driver:
+ * do not emit error when running ExecuteSQL() with a spatial filter on an empty layer (#6639)
+ * add read/write support for String/Integer/Integer64/RealList types as serialized JSon arrays
+ * Spatiliate: avoid crash when creating layer with geom_type = wkbCurve (fixes #6660)
+ * Spatiliate: do not report some BLOB columns as geometry columns of tables/views (when found before the geometry column(s)) (#6695, #6659)
+ * fix update of features with multiple geometry columns (#6696)
+ * speed-up dataset closing when creating a database with many spatial layers
+ * Spatialite: avoid spatial views to cause layers 'layer_name(geometry_name)' to be publicly listed (#6740)
+ * Spatialite: speed-up creation of database with INIT_WITH_EPSG=NO that is slow without transaction (not sure why as the table is empty...)
+ * use AUTOINCREMENT for feature id column
+ * allow OGR_SQLITE_CACHE to be set to > 2047 (MB) without overflowing
+ * SQLite/GPKG: use SQLITE_OPEN_NOMUTEX flag to open databases.
+ * GPKG/SQLite: fix ExecuteSQL() to work with a statement with 2 SELECT and ORDER BY clause (#6832)
+ * SQLite/GPKG: change default page_size to 4096 bytes.
+ * Update layer statistics for Spatialite 4 DB (#6838)
+ * Remove traces of support of SQLite < 3.6.0
+
+SXF driver:
 
 VFK driver:
- * recreate DB automatically when it's outdated (#6511)
+ * allow reading multiple VFK files into single DB support amendment VFK files
+ * recreate DB in the case that it's outdated (VFK DB created by previous versions of GDAL)
+ * allow reading DB as valid datasource (#6509)
+ * new tables in backend SQLite database (geometry_columns/spatial_ref_sys) to enable reading DB datasource by SQLite driver
+ * new configuration option OGR_VFK_DB_READ to enable reading backend database by VFK driver
 
 VRT driver:
  * add support for 'm' attribute in PointFromColumns mode (#6505)
 
-SOSI driver:
- * make registration of driver work again (2.1 regression) (#6500)
- * Update to latest version of ​https://github.com/kartverket/gdal. Make SOSI driver support more geometry types (including curved geometries) plus provides some improvements on attribute-type mapping. Fix some memory errors/leaks. Disable by default non working creation code (#6503)
-
 WFS driver:
  * invalidate underlying layer when SetIgnoredFields() is called (QGIS #15112)
  * don't crash on empty <Keyword/> declaration (#6586)
+ * fix potential nullptr dereference on dataset without layer (github #179)
+
+XLSX driver:
+ * only list worksheets (and no charts) as layers (#6680)
 
-== Perl bindings ==
- * Fix GetGeomFieldIndex()
- * Fix Dataset.Warp (#6521)
+XPlane driver:
+
+== SWIG Language Bindings ==
+
+All bindings:
+ * map osr.GetTargetLinearUnits() (#6627)
+ * allow wkbCurve/wkbSurface as valid values for the geom type of GeomFieldDefn object
+ * map GDALIdentifyDriverEx()
+
+Java bindings:
+ * Fix SWIG Java bindings for GNM (#6434)
+ * Fix crash on GetDefaultHistogram() if the C++ method returns an error (#6812)
+
+Perl bindings:
+ * return value always from GetGeomFieldIndex (#6506)
+ * the Warp method requires a list of datasets (#6521)
+ * when 'use bigint' is in effect, int var is a ref.
+ * Separate the module building in the CPAN distribution and in
+the GDAL source tree. The CPAN distribution will be 
+developed at https://github.com/ajolma
+ * Fix the Extension method in Driver per RFC 46
+ * The Inv method of GeoTransform did not return a new object. 
+Allow a single point in Apply method of GeoTransform.
+ * Test for existence of PDL and require it if available.
+ * allow decimation/replication in Piddle i/o.
+ * support resampling in ReadTile.
+ * Polygonize: Require explicit 8 for Connectedness to set 8-connectedness and allow 8CONNECTED as an option.
+ * use Safefree to free memory allocated in Perl (#6796)
+
+Python bindings:
+ * release the GIL before entering GDAL native code (for all, in GDAL module and a few ones in ogr like ogr.Open())
+ * add outputType option to gdal.Rasterize()
+ * fix build issues when CXX is defined in the environment
+ * gdal.VectorTranslate(): add spatSRS option
+ * when enabling ogr.UseExceptions(), use the GDAL error message in the exception text (if available), when the exception is linked to an error value in the OGRErr return code
+ * gdal.VectorTranslate(): accept a single string as value of the layers option (instead of iterating over each of its characters)
+ * Regenerate Python bindings with SWIG 3.0.8 to avoid issue with Python 3.5. Add backward compatibility in Band.ComputeStatistics() to accept 0/1 as input instead of the expected bool value (#6749)
+ * fix gdal.DEMProcessingOptions(zeroForFlat=True) (#6775)
+ * fix 'import osgeo.gdal_array' with python3 and SWIG 3.0.10 (#6801)
+ * allow gdal.FileFromMemBuffer() to use buffer > 2GB (#6828)
 
 = GDAL/OGR 2.1.0 Release Notes =
 
@@ -546,7 +975,7 @@ Port:
  * CPLRecodeStub(): add special case for CP437 -> UTF-8 when input is only printable ASCII
  * CPLHTTPFetch(): add LOW_SPEED_TIME and LOW_SPEED_LIMIT options
  * CPLGetValueType(): improve heuristics to avoid detecting some WKB strings as real numbers (#6128)
- * Add CPL_SHA256* and CPL_HMAC_SHA256 functions 
+ * Add CPL_SHA256* and CPL_HMAC_SHA256 functions
  * Make CPLVirtualMemFileMapNew() work on all systems having mmap(), and thus GeoTIFF GTIFF_VIRTUAL_MEM_IO optimization too
  * Add VSI_MALLOC_VERBOSE() and similar macros to output an error message in case of failed alloc
  * CPLParseXMLString(): limit depth of elements to 10000
@@ -578,7 +1007,7 @@ Core:
  * Add GDALAdjustValueToDataType() in C API, and use it in GDALTranslate() and GDALWarp()
  * GDALDefaultOverviews::CreateMaskBand(): fix logic error related to writing per-band mask
  * Block cache: fix excessive memory consumption when dealing with datasets with different block sizes (#6226)
- * EXIFExtractMetadata(): fix potential 1-byte write buffer stack overflow 
+ * EXIFExtractMetadata(): fix potential 1-byte write buffer stack overflow
  * MDReader: do no attempt reading side-car files on /vsisubfile/ (#6241)
  * GDALCheckBandCount(): allow by default a maximum number of bands to 65536
  * GDALOpenInfo: add StealSiblingFiles() and AreSiblingFilesLoaded() methods
@@ -657,7 +1086,7 @@ Utilities:
 
 Python samples:
  * gdalpythonserver.py: update to protocol 3
- 
+
 AAIGRID:
  * when writing with floating-point values, ensure at least one value has a decimal point to avoid issues with some readers (#6060)
 
@@ -1168,7 +1597,7 @@ Python bindings:
     - Cloudant: read/write driver for Cloudant service
     - CSW: read-only driver for OGC CSW (Catalog Service for the Web) protocol
     - JML: read/write driver for OpenJUMP .jml format
-    - PLScenes: read-only driver for Planet Labs Scenes API 
+    - PLScenes: read-only driver for Planet Labs Scenes API
     - Selaphin: read/write driver for the Selaphin/Seraphin format (#5442)
  * Significantly improved drivers: CSV, GPKG, GTiff, JP2OpenJPEG, MapInfo file, PG, SQLite
  * RFC 31: OGR 64bit Integer Fields and FIDs (trac.osgeo.org/gdal/wiki/rfc31_ogr_64)
@@ -1284,7 +1713,7 @@ Core:
  * Metadata: fix correct sorting of StringList / metadata (#5540, #5557)
  * Make GetMaskBand() work with GDT_UInt16 alpha bands (#5692)
  * Fix 32bit overflow in GDALRasterBand::IRasterIO() and  GDALDataset::BlockBasedRasterIO() (#5713)
- * RasterIO: small optimization in generic RasterIO() implementation to avoid loading partial tiles at right and/or bottom edges of the raster when they are going to be completely written 
+ * RasterIO: small optimization in generic RasterIO() implementation to avoid loading partial tiles at right and/or bottom edges of the raster when they are going to be completely written
  * Fix crash when calling GetTiledVirtualMem() on non-Linux platform (#5728)
  * Add GDAL_OF_INTERNAL flag to avoid dataset to be registered in the global list of open datasets
  * GDALDriver::CreateCopy(): accept _INTERNAL_DATASET=YES as creation option, so as to avoid the returned dataset to be registered in the global list of open datasets
@@ -1422,7 +1851,7 @@ GRASS driver:
  * GRASS 7.0.0 support (#5852)
 
 GRIB driver:
- * avoid divide by zero while setting geotransform on 1xn or nx1 grib file (#5532à
+ * avoid divide by zero while setting geotransform on 1xn or nx1 grib file (#5532)
  * allow writing PDS template numbers to all bands (#5144)
 
 GTiff driver:
@@ -2109,7 +2538,7 @@ Python bindings:
  * Significantly improved drivers: GML, LIBKML
  * RFC 40: enhanced RAT support (#5129)
  * RFC 41: multiple geometry fields support
- * RFC 42: OGR Layer laundered field lookup 
+ * RFC 42: OGR Layer laundered field lookup
  * RFC 43: add GDALMajorObject::GetMetadataDomainList() (#5275)
  * RFC 45: GDAL datasets and raster bands as virtual memory mapping
  * Upgrade to EPSG 8.2 database
@@ -2209,7 +2638,7 @@ Algorithms:
  * warper: fix cutline blending (#5343)
  * warper: Average/mode kernels: make them less sensitive to numerical precision issues (#5350)
  * warper: Average/mode kernels: avoid 'holes' when the source coordinates are in a reversed order from the target coordinates (#5433)
- * warper: provide prototypes and work around strict compiler requirements on some opencl platforms (#5400) 
+ * warper: provide prototypes and work around strict compiler requirements on some opencl platforms (#5400)
  * RPC: fix for computation of adfGTFromLL (#5395)
  * TPS: optimization for GCC x86_64 that make computation about twice faster with huge number of GCPs
  * TPS: when using Armadillo to solve the coefficients, use solve(A,B) instead of inv(A)xB to faster resolution
@@ -2650,7 +3079,7 @@ GPX driver:
 
 ILI driver:
  * add support for multiple geometry columns (RFC 41)
- * use IlisMeta model reader/writer instead of IOM 
+ * use IlisMeta model reader/writer instead of IOM
  * add layers for surface and area geometries
 
 KML driver:
@@ -2816,7 +3245,7 @@ Java bindings:
  * respect JAVA_HOME set via configure
 
 Perl bindings:
- * ColorTable method of ColorTable class was documented but ColorEntries was 
+ * ColorTable method of ColorTable class was documented but ColorEntries was
    implemented. Implemented but deprecated ColorEntries.
 
 Python bindings:
@@ -2951,7 +3380,7 @@ Utilities:
  * gdal_edit.py: promote it as an 'official' tool (#4963)
  * gdalwarp: add "-r average" and "-r mode" resampling methods (#5049)
  * gdalwarp: copy metadata and band information from first source dataset and detect for conflicting values, new options -nomd and -cvmd (#3898)
- * gdalwarp: optimization when (-tr and -te) or (-ts and -te) are specified (#4804) 
+ * gdalwarp: optimization when (-tr and -te) or (-ts and -te) are specified (#4804)
  * gdalwarp: assign color interpretation of source bands to target dataset, in the case of target VRT (#4462)
  * gdalwarp: add -setci option to set the color interpretation of the bands of the target dataset from the source dataset
  * gdal_translate: accept -srcwin or -projwin values that fall partially or completely outside the source raster extent. Introduce -epo and -eco options to error out in those situations.
@@ -3135,7 +3564,7 @@ JP2KAK driver:
 
 JP2OpenJPEG driver:
  * Require OpenJPEG 2.0.0 now
- * Use several decoding threads when processing multi-tiles IRasterIO() requests 
+ * Use several decoding threads when processing multi-tiles IRasterIO() requests
  * Add support for writing georeferencing
  * Read and write JP2 Res box and translate it from/to TIFFTAG_XRESOLUTION, TIFFTAG_YRESOLUTION and TIFFTAG_RESOLUTIONUNIT metadata items
  * Promote 1bit alpha band of a RGBA dataset to 8 bits to improve general user experience (can be turned off by setting JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT to NO)
@@ -3626,7 +4055,7 @@ CSharp bindings:
 
 Java bindings:
  * Fix compilation issue with SWIG 2.0.6 on Java bindings (#4669)
- * New test application: ogrtindex.java 
+ * New test application: ogrtindex.java
  * Fix values of gdalconst.DCAP_* and gdalconst.DMD_* constants (#4828)
  * Fix check for opaque colors in getIndexColorModel()
 
@@ -3638,7 +4067,7 @@ Perl bindings:
  * Default to first band in GetRasterBand.
  * New method Geo::OGR::Layer::DataSource
  * New method Geo::OGR::Layer::HasField
- * Geometry method accepts geometries in Perl structures 
+ * Geometry method accepts geometries in Perl structures
  * Fixed a bug in FeatureDefn::create which changed the fields.
  * New experimental methods ForFeatures and ForGeometries.
  * InsertFeature, Tuple and Row methods use the Tuple and Row methods from Feature.
@@ -3833,7 +4262,7 @@ AIG driver:
 BSB driver:
  * Parse the GD keyword in BSB_KNP to recognize European 1950 datum (#4247)
  * fix compilation issues with -DBSB_CREATE
- 
+
 CEOS2 driver:
  * avoid potential crash reading past end of string. (#4065)
 
@@ -3997,7 +4426,7 @@ Idrisi driver:
 
 INGR driver:
  * Set NBITS for 1 bit bands
- 
+
 ISIS2/ISIS3 driver:
  * Various improvements to PDS related drivers (#3944)
 
@@ -4046,16 +4475,16 @@ NetCDF driver:
  * Add simple progress indicator
  * Add support for netcdf-4, HDF4 and HDF5 (#4294 and #3166)
  * Add support for deflate compression
- * Add format support information and CreateOptionList to driver metadata 
+ * Add format support information and CreateOptionList to driver metadata
  * Add support for valid_range/valid_min/valid_max
  * Proper handling of signed/unsigned byte data
  * Add support for Create() function and significantly refactor code for export (#4221)
  * Improvements to CF projection support (see wiki:NetCDF_ProjectionTestingStatus)
- 
+
 NGSGEOID driver:
  * New for GDAL/OGR 1.9.0
  * Read NOAA NGS Geoid Height Grids
- 
+
 NITF driver:
  * Add a generic way of decoding TREs from a XML description file located in data/nitf_spec.xml
  * Add a new metadata domain xml:TRE to report as XML content the decoded TREs
@@ -4111,7 +4540,7 @@ PNM driver:
 
 PostgisRaster driver:
  * Speed of PostGIS Raster driver improved. (#3228, #3233)
- 
+
 Rasterlite driver:
  * Robustness against buggy databases
  * Enable QUALITY creation option for WEBP tiles
@@ -4224,7 +4653,7 @@ Core:
  * Add OGR_G_GetPoints()
  * Fix parsing of WKT geometries mixing 2D and 3D parts
  * OGR_Dr_CopyDataSource() and OGRSFDriver::CopyDataSource() : make sure that the driver is attached to the created datasource (#4350)
- * OGRFeature::SetFrom() supports more conversions between field types. 
+ * OGRFeature::SetFrom() supports more conversions between field types.
 
 OGRSpatialReference:
  * Update to EPSG 7.9 database
@@ -4330,7 +4759,7 @@ Geomedia driver:
 
 GeoRSS driver:
  * Parse RSS documents without <channel> element
- 
+
 GFT driver:
  * New for GDAL/OGR 1.9.0
  * Read/write driver for Google Fusion Tables
@@ -4425,7 +4854,7 @@ OCI driver:
 
 OGDI driver:
  * Fix GetFeature() that did not like switching between layers
-   
+
 PG driver:
  * Write geometries as EWKB by default to avoid precision loss (#4138)
  * Return the table columns in the order they are in the database (#4194)
@@ -4452,7 +4881,7 @@ PGDump driver:
  * Add NONE_AS_UNKNOWN, FID, EXTRACT_SCHEMA_FROM_LAYER_NAME layer creation options
  * Better escaping of column and table names
  * Create field of type OFTString and width > 0, as VARCHAR(width) (#4202)
- 
+
 PGeo driver:
  * Move CreateFromShapeBin() method to an upper level
  * Only try to open .mdb files that have the GDB_GeomColumns string
@@ -4473,11 +4902,11 @@ SDE driver:
 SEGUKOOA driver:
  * New for GDAL/OGR 1.9.0
  * Read files in SEG-P1 and UKOOA P1/90 formats
- 
+
 SEGY driver:
  * New for GDAL/OGR 1.9.0
  * Read files in SEG-Y format
- 
+
 Shapefile driver:
  * Encoding support for shapefile/dbf (#882)
  * Allow managing datasources with several hundreds of layers (#4306)
@@ -4565,7 +4994,7 @@ General :
  * Add Geometry.SimplifyPreserveTopology()
  * Extend SWIG Geometry.ExportToJson() to accept a list of options (#4108)
  * Add (OGR)DataSource.SyncToDisk()
- * Add SpatialReference.SetVertCS(), IsSameVertCS(), IsVertical(), SetCompount(), IsCompound()
+ * Add SpatialReference.SetVertCS(), IsSameVertCS(), IsVertical(), SetCompound(), IsCompound()
  * Add SpatialReference.SetIGH() (#4060)
  * RFC 35: Add OGRLayer.DeleteField(), ReorderField(), ReorderFields(), AlterFieldDefn()
  * Add gdal.VSIFTruncateL()
@@ -4828,7 +5257,7 @@ GeoRaster driver :
  * Fix interleaving cache error (#3723)
  * Fix compress vs nbits order error (#3763)
  * Fix writing interleaved jpeg #3805 and reading default blocksize #3806
- * Add create option blocking=(YES,NO,OPTIMUM) #3807, also fix #3812 
+ * Add create option blocking=(YES,NO,OPTIMUM) #3807, also fix #3812
 
 GRASS driver:
  * Update GDAL and OGR GRASS drivers to compile against GRASS 7.0SVN (#2953)
@@ -5022,7 +5451,7 @@ PCIDSK2 driver:
  * Support for reading/writing complex PCIDSK files through libpcidsk
  * Support worldfile if lacking internal georef (#3544)
  * Fix locking state at CPLThreadMutex creation (#3755)
- * Improved projection support. 
+ * Improved projection support.
 
 PDF driver:
  * New for GDAL/OGR 1.8.0
@@ -5306,7 +5735,7 @@ HTF driver:
 Ingres driver:
  * Implement support for spatial reference systems (atrofast, #3159)
  * Added support for GEOMETRYCOLLECTION as a generic geometry type, and
-   fleshed out the layer creation logic to support all geometry types. 
+   fleshed out the layer creation logic to support all geometry types.
 
 KML driver:
  * KML vertex output: avoid warning for coordinates just above 90 and 180
@@ -5522,7 +5951,7 @@ Build (All) :
  * Fix GML and ILI reading problems with Xerces 3.x (#3156)
  * Add 8/12bit JPEG-in-TIFF support
  * Fix trunk compilation against libdap 3.9.X (#3105)
- 
+
 Build (Windows) :
  * Check for CURL_LIB instead of CURL_DIR
  * ensure OGR_ENABLED gets defined if INCLUDE_OGR_FRMTS set (#2784)
@@ -5564,7 +5993,7 @@ Port :
  * odbc: Fixed the null terminators for columns of length (x*511)+1, where x>1. (#2727)
  * unix VSIF*L : reworked to avoid unnecessary seeks which can be expensive
  * added HTTPAUTH and USERPWD options for http fetch (#3091)
- 
+
 == GDAL 1.7.0 - Overview of Changes ==
 
 Algorithms:
@@ -5578,7 +6007,7 @@ Algorithms:
  * rasterize : Add ALL_TOUCHED rasterize option (#2840)
  * rasterize : Added 3D support for rasterizing points and lines. (#3202)
  * rasterize : correct case of vertical/horizontal lines on raster right/bottom edge (#3268)
- * Added GDALCreateGenImgProjTransformer3() function 
+ * Added GDALCreateGenImgProjTransformer3() function
  * warp: Reduce destination file size, especially when it has compression (#1688)
  * warp: Fix crash when reprojecting to irrelevant SRS (#3079)
  * warp: avoid using the destination nodata value for integer datatypes (#3142)
@@ -5592,7 +6021,7 @@ Algorithms:
               and a grid node, average distance between data points.
  * gdal_grid: Properly cast the poOptions parameter in data metrics computation functions. (#3207)
 
-Core : 
+Core :
  * Added mechanism to clear overviews if zero overviews requested. Implemented by GTiff and HFA drivers (#2915)
  * Support for overviews in subdatasets
  * Support for overviews in proxydb directory (#2432)
@@ -5613,7 +6042,7 @@ Core :
    and georeferencing information from OziExplorer .MAP files.
  * Added declarations for GDALLoadTabFile() and GDALReadTabFile()
  * Add missing case for CInt16 and CInt32 in GDALNoDataMaskBand and GDALNoDataValuesMaskBand
-  
+
 Utilities :
  * gdaldem: new for GDAL/OGR 1.7.0 (#2640)
  * gdalinfo:
@@ -5674,7 +6103,7 @@ Changes in various drivers :
 
 ADRG driver:
  * Support PSP != 100 (#3193)
- 
+
 AIG driver:
  * Differ opening of the RAT only when GetDefaultRat() is called.
    Will improve performances and make less likely the error message of #3031
@@ -5685,7 +6114,7 @@ AAIGRID driver:
 
 BAG driver :
  * New for GDAL/OGR 1.7.0
- 
+
 BLX driver:
  * Implement progress callback in CreateCopy() (#2830)
 
@@ -5693,13 +6122,13 @@ BMP driver:
  * Modify GetGeoTransform() to return geotransform based on the resolution
    information in the BMP header if nothing else is available (ESRI merge).
  * use pam functions properly for geotransform when not using world file
- 
+
 BSB driver:
  * Fix several issues with BSB files reading (#2782)
  * Handle properly more than 256 GCPs (#2777)
  * Add logic to chip GCPs around to avoid split over dateline problems (#2809)
- * Add logic to reproject GCPs into Mercator for mercator projected images. 
- 
+ * Add logic to reproject GCPs into Mercator for mercator projected images.
+
 DTED driver:
  * Re-enable DTED driver to recognize files not starting by a UHL record (#2951)
 
@@ -5715,7 +6144,7 @@ EHDR driver:
  * added support for SIGNEDBYTE pixels (#2717)
  * Restructure stats handling so pam capture works right when stx write fails
  * improve a bit .clr reading (#3253)
- 
+
 ENVI driver:
  * Move RPC info into the RPC domain (#3063)
  * Converted to using VSI Large File API (#3274)
@@ -5724,14 +6153,14 @@ ENVI driver:
 EPSILON driver:
  * New for GDAL/OGR 1.7.0
  * Mainly used coupled with Rasterlite
- 
+
 ERS driver:
  * Added PIXELTYPE support to report/create SIGNEDBYTE (#2902)
  * Give precedence to PAM SRS, and even check for .aux file.  (ESRI Merge)
 
 FAST driver:
  * Support 7 bands (#3307)
- 
+
 Fujibas driver:
  * Fix to work on big-endian hosts
 
@@ -5767,7 +6196,7 @@ GeoTIFF driver :
  * Internal libtiff (4.0.0beta5) and libgeotiff (1.3.0beta) upgraded
  * use the SetCitationToSRS call for the PCSCitationGeoKey in a similar fashion to the GTCitationGeoKey (#2933)
  * NBITS set for GTiffOddBits.  YCbCr JPEG added as a compression type.
-   generate MINISWHITE IMAGESTRUCTURE metadata item.  Set missing blocks 
+   generate MINISWHITE IMAGESTRUCTURE metadata item.  Set missing blocks
    to the nodata value if there is one.  (ESRI Merge)
  * Support GeoTIFF with only ProjectedCSTypeGeoKey defined (#3019)
  * External overviews: try to preserve the bit depth of the original image
@@ -5779,7 +6208,7 @@ GFF driver :
  * Add pam, and overview support.  Switch to VSI*L API to support virtualio (#3014)
 
 GIF driver :
- * Introduced a BIGGIF driver to handle GIF files without using the 
+ * Introduced a BIGGIF driver to handle GIF files without using the
    slurp into memory approach. (#2542)
  * CreateCopy() reports now progress
  * Replace internal libungif by giflib-4.1.6 (#1825)
@@ -5798,7 +6227,7 @@ GRIB driver:
 
 GS7BG driver:
   * Recognize version 2 datasets (#3123)
- 
+
 HDF4 driver :
  * Allow HDF4 subdataset name to include Windows letter drive (#2823)
 
@@ -5807,13 +6236,13 @@ HDF5 driver :
  * Block size recognition. (#2270)
  * Fix initial value for nGCPCount in HDF5ImageDataset (#2774)
  * Fixes to type classification, and to avoid listing subdatsets for unsupported pixel data types (#2941)
- * Mark PAM for not saving .aux.xml files at this level.  Directly open 
-   subdatasets in HDF5Dataset::Open() if there is only one subdataset. 
- 
+ * Mark PAM for not saving .aux.xml files at this level.  Directly open
+   subdatasets in HDF5Dataset::Open() if there is only one subdataset.
+
 HFA driver:
  * Support reading and evaluating 3rd order xforms (#2716)
  * Various improvements to SRS support, particularly to preserve PE
-   compatibility.  (#2755) 
+   compatibility.  (#2755)
  * Added HFAEntry::RemoveAndDestroy() method to remove nodes from tree (#2421)
  * Added support for deleting color tables (#2421)
  * Add a scaled progress monitor for HFADataset::IBuildOverviews()
@@ -5838,14 +6267,14 @@ JPEG driver:
  * Enable the JPEG driver to read and create 12bit JPEG images when JPEG12_ENABLED=yes
  * Internal libjpeg: additional changes to ensure operation with IPP enabled apps (#2606,#2845)
  * JPEG read optimizations : differ extraction of EXIF metadata and internal maskband
- 
+
 JPEG2000 (JasPer) Driver:
  * Allow proper reading of JP2 images where dimensions are not multiple of 256 (#2399)
  * Add a virtual I/O interface to able to read from/write to JPEG2000-NITF files
  * Do not deregister jas_image_clearfmts() to avoid failure when gdal_translat'ing from JP2 streams
  * Add proper reading of YCbCr images as RGB
  * fix decoding of bit depth for BPCC and PCLR boxes
- 
+
 JP2KAK (Kakadu) Driver :
  * Fix band selection from ycbcr to rgb converted images in DirectRasterIO (#2732)
  * Support jpc vsisubfile streams
@@ -5863,12 +6292,12 @@ JP2KAK (Kakadu) Driver :
 
 
 LAN driver:
- * Give preference to PAM coordinate system since built-in info is very 
+ * Give preference to PAM coordinate system since built-in info is very
   limited.  Fallback to PAM geotransform if internal missing. (ESRI Merge)
 
 LCP driver:
  * Add projection file support (#3255)
-  
+
 MEM driver:
  * Allow creating bands of more than 2GB each if size_t is large enough.
  * Added GetInternalHandle() implementation to fetch band memory buffer
@@ -5885,7 +6314,7 @@ NetCDF driver:
  * correct a problem with 5+ dimensional data access (#2583)
  * fix y flip detection in common case (#2654)
  * add support for subdataset names with Windows full path names, like NETCDF:D:\...
- 
+
 NITF driver:
  * Add support for reading & creating large (>4GB) NITF files.
  * Add support for NITF/JPEG2000 overviews (JP2KAK)
@@ -5893,7 +6322,7 @@ NITF driver:
  * Add support for creating a NITF file with many bands and big TRE content
  * Add support for creating several uncompressed images in a NITF file (#2989)
  * Add support for creating M3 (masked multi-block JPEG compressed) images
- * Add support for unpacking a wider variety of pixel depths. 
+ * Add support for unpacking a wider variety of pixel depths.
  * Add support for overriding IGEOLO with GEOLOB TRE precision georef (#3180)
  * Add support for for CFloat32 reading & writing (#2526)
  * Add support for reading and writing NITF file with large single block (#3263)
@@ -5906,7 +6335,7 @@ NITF driver:
 
 NWT_GRC / NWG_GRD drivers (Northwood/VerticalMapper) :
  * New for GDAL/OGR 1.7.0
- 
+
 OGDI driver:
  * improve finding of PROJ.4 include files for OGDI (#1242)
 
@@ -5914,10 +6343,10 @@ PCIDSK driver (old driver):
  * Added worldfile reading. Added PAM fallback for geotransform.
  * Added support for default overviews (i.e. .ovr or .rrd).  (ESRI Merge)
  * fail somewhat gracefully on compressed images
- 
+
 PCIDSK driver (new driver):
  * New for GDAL/OGR 1.7.0, using the PCIDSK SDK
- 
+
 PDS driver:
  * Transfer various keywords to metadata
  * Made keyword handler more in complaint with ODL (#2956)
@@ -5928,28 +6357,28 @@ PNG driver :
  * Upgrade internal libpng to 1.2.35
  * Only write a world file if the source datasource has a geotransform
  * Allow writing a nodata value of 0 as the transparent color value (#3208)
- 
+
 R driver:
  * New for GDAL/OGR 1.7.0
- 
+
 Rasterlite driver
  * New for GDAL/OGR 1.7.0
 
 RIK driver:
  * Improved error checking
- 
+
 SAGA GIS Binary driver:
  * New for GDAL/OGR 1.7.0
 
 SDE driver :
  * Fix exporting ArcSDE raster results in a displaced image (#2063)
- 
+
 SRP driver (ASRP/USRP):
  * New for GDAL/OGR 1.7.0
- 
+
 SRTM driver :
  * Set GDALMD_AOP_POINT metadataitem (#1884)
- 
+
 TIL driver (EarthWatch .TIL) driver:
  * New for GDAL/OGR 1.7.0
 
@@ -5963,7 +6392,7 @@ VRT driver :
 WCS driver:
  * do not try to parse HTML content, which is returned by some provider when the server doesn't exist
  * added HttpAuth and UserPwd options for authentication (#3091)
- 
+
 WKT Raster driver:
  * New for GDAL/OGR 1.7.0
 
@@ -5993,7 +6422,7 @@ Utilities:
     - Set SRS to tileindex when one is found in the tiles
   * ogr2vrt.py : new script that will create a VRT corresponding to a
     source datasource (sample script for the moment, not promoted officially)
- 
+
 Core :
  * Improved OGR feature style (#2875, #2808)
  * Considerable speed-up of ExportToWkt() for very large geometries
@@ -6036,11 +6465,11 @@ OGRSpatialReference :
    (also add ggrs87, carthage, hermannskogel, ire65); Fix ellipsoid parameters for modified airy (#3104)
  * OSRGetEllipsoidInfo() available for various OGR SRS modules
  * added support for OGC:CRS84 and similar srses from wms/wcs spec in SetFromUserInput (#3090)
- 
+
 BNA driver :
  * Fix output of BNA driver with polygons with inner ring (#2985)
  * Proper CRLF output on Windows (#3256)
- 
+
 CSV driver :
  * Add support for reading and writing CSV files with semicolon or tabulation
    as the field separator (#2925, #2136)
@@ -6049,7 +6478,7 @@ CSV driver :
 
 DXF driver :
  * New for GDAL/OGR 1.7.0
- 
+
 Geoconcept driver:
  * Fix 'private Class and SubClass headers are inverted' (#2919)
  * Fix error in writing 2.5D/3D export file (#2921)
@@ -6115,7 +6544,7 @@ OGDI driver :
 PGEO driver :
  * Recognize more ESRI shape type constants. (#2991, #3100)
  * implement GetFIDColumn() and GetGeometryColumn() methods (#2694)
- 
+
 PostgreSQL driver:
  * Add support for tables with 'geography' column type introduced in PostGIS 1.5 (#3216)
  * Extend support of schemas in PG driver with 2 new options in the connection string:
@@ -6128,16 +6557,16 @@ PostgreSQL driver:
    which can be very expensive if the layer has many fields
  * allow ST_AsBinary with non binary connections
  * added a configuration option PG_SKIP_VIEWS.
- 
+
 GeoRSS driver :
  * New for GDAL/OGR 1.7.0 (#2726)
 
 OCI driver:
  * support blob column binding
- 
+
 PCIDSK driver :
  * New for GDAL/OGR 1.7.0
- 
+
 Shape driver :
  * Handle duplicate field names in shapefile driver. (#3247)
  * Support for opening and handling .DBF files > 2 GB (#3011)
@@ -6145,11 +6574,11 @@ Shape driver :
  * Support for alternate date format (#2746)
  * Improve/fix TestCapability() on OGRShapeLayer
  * Refreshed shapelib from upstream
- 
+
 S57 driver :
  * Fix incorrect return value of GetFeatureCount() on S57 SOUNDG layer when SPLIT_MULTIPOINT=ON;
    also avoid warning on that layer when ADD_SOUNDG_DEPTH=OFF (#3163)
-  
+
 SQLite driver:
  * Add creation and write support in SpatiaLite-compatible databases
  * Add SPATIAL_INDEX creation option for SpatiaLite tables if linked against
@@ -6174,19 +6603,19 @@ VRT driver:
  * Add a 'reportSrcColumn' attribute to the 'GeometryField' to avoid reporting
    the x,y,wkt or wkb source fields in the VRT layer field definition
  * Forward TestCapability(), GetExtent(), SetNextByIndex() to source layer when possible
- 
+
 XPlane/Flightgear driver:
  * Improve handling of Bezier curves (#3030)
  * Support new file names used by XPlane 9.00 & later
  * Cut into 2 pieces airway segments that cross the antemeridian
- * Add new layer 'Stopway' that contains the shape of the stopway/blastpad/over-run of a runway 
+ * Add new layer 'Stopway' that contains the shape of the stopway/blastpad/over-run of a runway
  * Recognize code 16 and 17 for seaplane bases and heliports and add a new field to APT layer
 
 == SWIG Language Bindings ==
 
 General:
  * Recommended SWIG version is 1.3.39
- * Added API : 
+ * Added API :
     - GDAL :
         gdal.FilldoData(), gdal.FileFromMemBuffer(), gdal.Unlink()
         gdal.ApplyGeoTransform(), gdal.InvGeoTransform()
@@ -6205,7 +6634,7 @@ General:
  * NONNULL checks have been added to check various arguments of methods
  * add missing constants : DCAP_VIRTUALIO, color interpretations, OGR constants
 
-CSharp bindings : 
+CSharp bindings :
  * Add support for GetFieldAsStringList, GetFieldAsDoubleList and
    GetFieldAsIntegerList in the C# wrapper (#2839)
  * Support MSVC2008 builds with the csharp interface (#2862)
@@ -6227,14 +6656,14 @@ Python bindings :
    Transform.TransformPoints and CoordinateTransformation.TransformPoints
  * Extend python TransformPoints typemap to accept any sequence (#3020)
  * Make Geometry iterable (#1886)
- 
+
 Java bindings (general changes):
  * Maintained again. A lot of changes to get them into clean state.
  * RasterIO API : added API for standard Java arrays in addition to DirectByteBuffer
  * Javadoc available at http://gdal.org/java
-  
-= GDAL/OGR 1.6.0 = 
- 
+
+= GDAL/OGR 1.6.0 =
+
 == GDAL/OGR 1.6.0 - General Changes ==
 
 Build (Unix):
@@ -6361,7 +6790,7 @@ Utilities:
  * gdal2ogr: New for 1.6.0. to create an OGR datasource from the values of a GDAL dataset; May be useful to test gdal_grid and generate its input OGR file (Not compiled by default)
 
  * Fix crash in gdalenhance
- * Add -nln switch for gdal_contour 
+ * Add -nln switch for gdal_contour
  * gdalgrid: Fixed zero search radius handling in nearest neighbor interpolation method.
  * gdalgrid: Added support for data metrics (minimum, maximum and range) computation.
  * gdalgrid: Added spatial filter support applied on the OGR data source
@@ -6516,7 +6945,7 @@ GTiff driver:
  * Prevent crash on tiff_ovr_9 when JPEG-In-TIFF support is not built
  * In GTiffDataset::Create(), set TIFFTAG_JPEGCOLORMODE=JPEGCOLORMODE_RGB when creating a TIFF with COMPRESS=JPEG and PHOTOMETRIC=YCBCR; In Crystalize(), backup the value of TIFFTAG_JPEGCOLORMODE and set it again after writing the directory (#2645)
  * Handle more gracefully the case where we open or create a TIFF file with a compression method not built in libtiff (use of TIFFIsCODECConfigured)
- * Don't fail when TIFFTAG_JPEGCOLORMODE tag cannot be read 
+ * Don't fail when TIFFTAG_JPEGCOLORMODE tag cannot be read
  * IPP libjpeg compatibility changes (#2606)
  * ensure zip/jpeg quality is preserved in crystalize. (#2642)
  * support handling nodata via pam/aux mechanisms (#2505)
@@ -6528,7 +6957,7 @@ GTiff driver:
  * Added logic to pre-clear geotiff tags when updating a file (#2546)
  * Add ExtraSample tag in overviews too (#2572)
  * Fix handling of non-degree angular units (#601)
- 
+
 GXF driver:
  * Add GXFRasterBand::GetNoDataValue (fix #835)
  * Avoid crash on bogus GXF file
@@ -6604,7 +7033,7 @@ JPEG driver:
 
 LCP (FARSITE) driver:
  * New for 1.6.0
- 
+
 L1B driver:
  * Added support for NOAA-18(N) and METOP-2 datasets; tiny code refactoring.
  * L1B : add auto guess of data format when it is 2 spaces or empty string
@@ -6759,7 +7188,7 @@ XPM driver:
 
 == OGR 1.6.0 - Overview of Changes ==
 
-General: 
+General:
   * RFC 21: OGR SQL type cast and field name alias (#2171)
   * Added support for outline color in OGRStyleLabel (#2480)
   * Added support for symbol outline color in OGR Style Strings (#2509)
@@ -6787,11 +7216,11 @@ General:
   * Fixed OGR SQL to properly escape single quotes in string literals (Ticket #2220).
   * Prevent an OGR driver from being registered several times (#2544)
 
-Utilities: 
+Utilities:
  * Start on a dissolve utility based on ogr2ogr
  * Add --version and --licence options for OGR CLI utilities
 
-OGRSpatialReference: 
+OGRSpatialReference:
  * RFC 20: Axes methods
  * Upgrade to EPSG 6.17
  * Added support for "International Map of the World Polyconic" and "Wagner I-VII" projections.
@@ -6910,7 +7339,7 @@ OCI driver:
  * OCI: Filter out MDSYS.CS_SRS entries with NULL value of WKTEXT.
  * add compound and stroked-arc read support
 
-PG (Postgres/PostGIS) Driver: 
+PG (Postgres/PostGIS) Driver:
  * Add the ability to specify a list of tables to be treated as layers with the 'tables=' connection string option (#1699)
  * Add SPATIAL_INDEX creation option to create GIST index. Turned ON by default (#959)
  * Add support for listing and correctly fetching geometry type of inherited spatial tables (#2558)
@@ -6970,7 +7399,7 @@ VRT driver:
  * Add "shared" attribute on SrcDataSource to control sharing.  Default to OFF for SrcLayer layers, and ON for SrcSQL layers.  This endeavors to avoid conflicts of layer state. (#2229)
 
 XPlane/Flightgear driver:
- * New for 1.6.0 
+ * New for 1.6.0
 
 
 
@@ -6995,13 +7424,13 @@ SWIG General :
  * Added gdal.Polygonize()
  * expose GDALDestroyDriverManager() to improve leak detection
  * Added RasterizeLayer() and SieveFilter()
- * If we receive an odd array type in BandWriteArray(), cast the array to float64 which we do support (#2285). 
+ * If we receive an odd array type in BandWriteArray(), cast the array to float64 which we do support (#2285).
 
-SWIG C# related changes: 
+SWIG C# related changes:
  * Implement GDALProgressFunc callback for C# (fix for #2122)
  * Fixed that passing null as the options parameter of Driver.CreateCopy causes access violation (#2185).
  * Added GDALCreateCopy sample application
- * Support for signing the GDAL C# assemblies (#2186) 
+ * Support for signing the GDAL C# assemblies (#2186)
  * Added raster specific tests
  * Reworked the wrapper implementation
  * Added the bandMap parameter to the C# Dataset.ReadRaster and Dataset.WriteRaster API.
@@ -7014,7 +7443,7 @@ SWIG C# related changes:
  * Changed the behaviour to use OSR.SpatialReference and OSR.CoordinateTransformation instead of defining the same classes in the OGR namespace
  * Changed the scope from internal to public of the required functions
 
-SWIG Python related changes: 
+SWIG Python related changes:
  * Fix layer __getitem__ bug (#2187)
  * add some sugar to ogr.DataSource.DeleteLayer to be able to take in either an index or a layer name.  If you give it a name, it *will* loop through all of the layers on the datasource.  This might be expensive depending on the driver.
  * add date/time fetching support to the generic GetField implementation... note this is not real 'datetime' support yet
@@ -7043,19 +7472,19 @@ SWIG Perl
  * made needed links from parameters to typemaps to make Get- and SetDefaultHistogram methods work in Perl
  * support for mingw Windows builds
 
-SWIG Java: 
+SWIG Java:
  * removed colortable from java bindings for now (#2231)
 
-= GDAL/OGR 1.5.0 = 
+= GDAL/OGR 1.5.0 =
 
 == GDAL/OGR 1.5.0 - General Changes ==
 
 Build:
  * CFG environment variable now ignored.  Instead set CFLAGS and CXXFLAGS
    environment variables to desired compilation options, or use --enable-debug
-   for a debug build.  Default is "-g -O2" like most other packages. 
+   for a debug build.  Default is "-g -O2" like most other packages.
  * Added --with-hide-internal-symbols to restrict exported API from .so files
-   to be the GDAL public API (as marked with CPL_DLL). 
+   to be the GDAL public API (as marked with CPL_DLL).
 
 Other:
  * OGR and GDAL C APIs now generally check for NULL objects and recover
@@ -7064,16 +7493,16 @@ Other:
 
 == GDAL 1.5.0 - Overview of Changes ==
 
-Core: 
+Core:
  * Enable Persistent Auxiliary Metadata (.aux.xml) by default.
- * Support for "pam proxies" for files in read-only locations. 
+ * Support for "pam proxies" for files in read-only locations.
  * Create and !CreateCopy pre-Delete output existing dataset.
  * Added Identify() method on drivers (per RFC 11: Fast Format Identify)
  * Implement !GetFileList() on datasets (per RFC 12).
  * Implement Delete(), Rename(), Copy() based on !GetFileList() (per RFC 12).
  * vrtdataset.h, memdataset.h and rawdataset.h are now considered part of
-   the public GDAL API, and will be installed along with gdal.h, etc. 
- * Support nodata/validity masks per RFC 14: Band Masks. 
+   the public GDAL API, and will be installed along with gdal.h, etc.
+ * Support nodata/validity masks per RFC 14: Band Masks.
  * Plugin drivers test for ABI compatibility at load time.
  * Creation flags can now be validated (this is used by gdal_translate)
  * Default block cache size changed to 40MB from 10MB.
@@ -7081,7 +7510,7 @@ Core:
 Algorithms / Utilities:
  * gdal_grid: New utility to interpolate point data to a grid.
  * gdal2tiles.py is new for 1.5.0.
- * gdaltransform: stdin/stdout point transformer similar to PROJ.4 cs2cs. 
+ * gdaltransform: stdin/stdout point transformer similar to PROJ.4 cs2cs.
  * gdalwarp: Several fixes related to destination "nodata" handling and
    nodata mixing in resampling kernels.
  * gdalwarp: Added Lanczos Windows Sinc resampling.
@@ -7101,7 +7530,7 @@ COASP Driver:
  * New for 1.5.0
  * SAR format produced by DRDC CASP SAR Processor.
 
-GFF Driver: 
+GFF Driver:
  * New for 1.5.0
 
 GENBIN (Generic Binary) Driver:
@@ -7130,7 +7559,7 @@ ERS Driver:
 
 HTTP Driver:
  * New for 1.5.0.
- * Fetches file by http and then GDALOpen()s. 
+ * Fetches file by http and then GDALOpen()s.
 
 GSG Driver:
  * New for 1.5.0.
@@ -7144,20 +7573,20 @@ Spot DIMAP Driver:
  * New for 1.5.0.
 
 RPFTOC Driver:
- * New for 1.5.0. 
+ * New for 1.5.0.
 
 ADRG Driver:
  * New for 1.5.0.
 
 NITF Driver:
- * Added support for writing JPEG compressed (IC=C3). 
+ * Added support for writing JPEG compressed (IC=C3).
  * Added support for reading text segments and TREs as metadata.
- * Added support for 1bit images. 
+ * Added support for 1bit images.
  * Added support for GeoSDE TRE for georeferencing.
  * Support PAM for subdatasets.
  * Improved NSIF support.
  * Support C1 (FAX3) compression.
- * Improved CADRG support (#913, #1750, #1751, #1754) 
+ * Improved CADRG support (#913, #1750, #1751, #1754)
 
 ENVI Driver:
  * Many improvements, particularly to coordinate system handling and metadata.
@@ -7170,14 +7599,14 @@ GTIFF (GeoTIFF) Driver:
  * Upgraded to include libtiff 4.0 (alpha2) as the internal option.
  * Support AVERAGE_BIT2GRAYSCALE overviews.
  * Produce pixel interleaved files instead of band interleaved by default.
- * Support TIFF files with odd numbers of bits (1-8, 11, etc). 
+ * Support TIFF files with odd numbers of bits (1-8, 11, etc).
  * Add ZLEVEL creation option to specify level of compression for DEFLATE method
 
 GIF Driver:
  * Nodata/transparency support added.
 
-JPEG Driver: 
- * Support in-file masks. 
+JPEG Driver:
+ * Support in-file masks.
 
 AIGrid Driver:
  * Supports reading associated info table as a Raster Attribute Table.
@@ -7190,14 +7619,14 @@ HFA Driver:
  * Support PE_STRING coordinate system definitions.
  * Support nodata values (#1567)
 
-WCS Driver: 
+WCS Driver:
  * Support WCS 1.1.0
 
 DTED Driver:
  * Can now perform checksum verification.
  * Better datum detection.
- 
-HDF4 Driver: 
+
+HDF4 Driver:
  * Support PAM for subdatasets.
 
 Leveller Driver:
@@ -7213,15 +7642,15 @@ General:
  * Added PointOnSurface implementation for OGRPolygon.
  * Added C API interface to OGR Feature Style classes (RFC 18).
 
-Utilities: 
- * All moved to gdal/apps. 
+Utilities:
+ * All moved to gdal/apps.
 
-OGRSpatialReference: 
+OGRSpatialReference:
  * Supports URL SRS type.
- * Upgraded to EPSG 6.13. 
+ * Upgraded to EPSG 6.13.
  * Operating much better in odd numeric locales.
 
-BNA Driver: 
+BNA Driver:
  * New for 1.5.0.
 
 GPX Driver:
@@ -7234,7 +7663,7 @@ GMT ASCII Driver:
  * New for 1.5.0.
 
 KML Driver:
- * Preliminary read support added. 
+ * Preliminary read support added.
 
 DXF / DWG Driver:
  * Removed due to licensing issues with some of the source code.  Still
@@ -7247,7 +7676,7 @@ PG (Postgres/PostGIS) Driver:
 
 Shapefile Driver:
  * Do not keep .shx open in read only mode (better file handle management).
- * Use GEOS to classify rings into polygons with holes and multipolygons if it is available. 
+ * Use GEOS to classify rings into polygons with holes and multipolygons if it is available.
  * Support dbf files larger than 2GB.
 
 MySQL Driver:
@@ -7277,11 +7706,11 @@ SWIG C# related changes:
  * C# namespace names and module names follows the .NET framework naming guidelines
  * Changed the names of the Windows builds for a better match with the GNU/Linux/OSX builds
  * The gdalconst assembly is now deprecated
- * GDAL C# libtool build support 
+ * GDAL C# libtool build support
  * !CreateFromWkb support
- * Dataset.!ReadRaster, Dataset.!WriteRaster support 
+ * Dataset.!ReadRaster, Dataset.!WriteRaster support
  * Added support for Dataset.!BuildOverviews
- * More examples added 
+ * More examples added
 
 SWIG Python related changes:
  * Progress function callback support added.  You can use a Python function, or the standard GDALTermProgress variant
@@ -7303,19 +7732,19 @@ SWIG Java:
 
 GDAL/OGR 1.4.0 - General Changes
 --------------------------------
- 
 
-Perl Bindings: 
+
+Perl Bindings:
  - Added doxygen based documentation.
 
-NG Python Bindings: 
+NG Python Bindings:
  - Implemented numpy support.
 
-CSharp Bindings: 
+CSharp Bindings:
  - Now mostly operational.
 
 WinCE Porting:
- - CPL 
+ - CPL
  - base OGR, OSR and mitab and shape drivers.
  - GDAL, including GeoTIFF, DTED, AAIGrid drivers
  - Added test suite (gdalautotest/cpp)
@@ -7359,25 +7788,25 @@ HDF4 Driver:
  - External raw raster bands supported.
 
 PCIDSK (.pix) Driver:
- - Support METER/FEET as LOCAL_CS. 
+ - Support METER/FEET as LOCAL_CS.
  - Fix serious byte swapping error on creation.
 
-BMP Driver: 
+BMP Driver:
  - Various fixes, including 16bit combinations, and non-intel byte swapping.
 
 GeoTIFF Driver:
  - Fixed in place update for LZW and Deflated compressed images.
 
 JP2KAK (JPEG2000) Driver:
- - Added support for reading and writing gmljp2 headers. 
- - Read xml boxes as metadata. 
- - Accelerate YCbCr handling. 
+ - Added support for reading and writing gmljp2 headers.
+ - Read xml boxes as metadata.
+ - Accelerate YCbCr handling.
 
-JP2MrSID (JPEG2000) Driver: 
- - Added support for reading gmljp2 headers. 
+JP2MrSID (JPEG2000) Driver:
+ - Added support for reading gmljp2 headers.
 
 EHDR (ESRI BIL) Driver:
- - Support 1-7 bit data. 
+ - Support 1-7 bit data.
  - Added statistics support.
 
 
@@ -7385,30 +7814,30 @@ OGR 1.4.0 - Overview of Changes
 -------------------------------
 
 OGR SQL:
- - RFC 6: Added support for SQL/attribute filter access to geometry, and 
-   style strings. 
+ - RFC 6: Added support for SQL/attribute filter access to geometry, and
+   style strings.
 
-OGRSpatialReference: 
- - Support for OGC SRS URNs. 
+OGRSpatialReference:
+ - Support for OGC SRS URNs.
  - Support for +wktext/EXTENSION stuff for preserving PROJ.4 string in WKT.
  - Added Two Point Equidistant projection.
  - Added Krovak projection.
  - Updated support files to EPSG 6.11.
 
-OGRCoordinateTransformation: 
+OGRCoordinateTransformation:
  - Support source and destination longitude wrapping control.
 
-OGRFeatureStyle: 
- - Various extensions and improvements. 
+OGRFeatureStyle:
+ - Various extensions and improvements.
 
-INFORMIX Driver: 
+INFORMIX Driver:
  - New
 
-KML Driver: 
+KML Driver:
  - New (write only)
 
 E00 Driver:
- - New (read only) 
+ - New (read only)
  - Polygon (PAL) likely not working properly.
 
 Postgres/PostGIS Driver:
@@ -7416,17 +7845,17 @@ Postgres/PostGIS Driver:
  - Fixed serious bug with writing SRSes.
  - Added schema support.
 
-GML Driver: 
- - Strip namespaces off field names. 
+GML Driver:
+ - Strip namespaces off field names.
  - Handle very large geometries gracefully.
 
-ODBC Driver: 
+ODBC Driver:
  - Added support for spatial_ref_sys table.
 
-SDE Driver: 
+SDE Driver:
  - Added logic to speed things up while actually detecting layer geometry types
 
-PGeo Driver: 
+PGeo Driver:
  - Added support for MDB Tools ODBC driver on linux/unix.
 
 VRT Driver:
@@ -7441,64 +7870,64 @@ GDAL/OGR 1.3.2 - General Changes
 WinCE Porting:
  - Support for MS WinCE new for this release.
 
-Java SWIG Bindings: 
+Java SWIG Bindings:
  - Preliminary support implemented.
 
 
 GDAL 1.3.2 - Overview of Changes
 --------------------------------
 
-Locale: 
+Locale:
  - Force numeric locale to "C" at a few strategic points.
 
 Idrisi Driver:
- - New for 1.3.2. 
- - Includes reading and writing. 
+ - New for 1.3.2.
+ - Includes reading and writing.
  - Limited coordinate system support.
 
-DIPEx Driver: 
+DIPEx Driver:
  - New for GDAL 1.3.2 (related to ELAS format).
 
 Leveller Driver:
- - New for GDAL 1.3.2. 
+ - New for GDAL 1.3.2.
 
 NetCDF Driver:
  - Improved autoidentification of x, y dimensions.
  - Improved CF support.
 
 JPEG2000 (JasPer) Driver:
- - Use GDALJP2Metadata to support various kinds of georeferencing. 
+ - Use GDALJP2Metadata to support various kinds of georeferencing.
 
 JPEG2000 (JP2KAK) Driver:
  - Support writing tiles outputs so that very large images can be written.
 
 GeoTIFF Driver:
  - Report error when attempting to create >4GB uncompressed file.
- - Updated to latest libtiff, now supports "old jpeg" fairly well. 
- - Improved support for subsampled YCbCr images. 
+ - Updated to latest libtiff, now supports "old jpeg" fairly well.
+ - Improved support for subsampled YCbCr images.
 
 Imagine (HFA) Driver:
- - Support reading affine polynomial transforms as geotransform. 
+ - Support reading affine polynomial transforms as geotransform.
  - Support overviews of different type than base band.
  - Support reading RDO style "nodata" indicator.
 
 PCI Aux Driver:
- - Support projections requiring parameters. 
+ - Support projections requiring parameters.
 
 MrSID Driver;
  - Fixed problem with writing files other than 1 or 3 bands.
- - Support ESDK 6.x. 
+ - Support ESDK 6.x.
 
 BMP Driver:
  - Added support for 32bit images with bitfields compression.
 
 DODS Driver:
- - Upgraded to support libdap 3.6.x. 
+ - Upgraded to support libdap 3.6.x.
  - Upgraded to support [-x][-y] to flip image.
 
 gdal_rasterize Utility:
- - New for GDAL 1.3.2. 
- - Rasterize OGR polygons into a raster. 
+ - New for GDAL 1.3.2.
+ - Rasterize OGR polygons into a raster.
 
 
 
@@ -7506,15 +7935,15 @@ OGR 1.3.2 - Overview of Changes
 -------------------------------
 
 OGRFeature:
- - Added support for OFTDate, OFTTime and OFTDateTime field types. 
+ - Added support for OFTDate, OFTTime and OFTDateTime field types.
  - Also applied to a few drivers (shapefile, mysql, postgres)
 
 OGRLayer:
  - GetFIDColumn() and GetGeometryColumn() added.
 
 Generic OGR SQL:
- - Proper support for spatial and attribute filters installed on 
-   OGR SQL resultsets. 
+ - Proper support for spatial and attribute filters installed on
+   OGR SQL resultsets.
 
 OGRSpatialReference:
  - Upgraded data files to EPSG 6.9
@@ -7526,15 +7955,15 @@ PostGIS Driver:
  - Added COPY support for accelerated loading.
 
 MySQL Driver:
- - Added read and write support for Spatial types. 
+ - Added read and write support for Spatial types.
  - Support spatial_ref_sys and geometry_columns tables.
  - Various other improvements (dates, smallint, tinyint, etc)
  - More robust auto-detection of column types for layers
    created from SQL statements
-   
+
 ArcSDE Driver:
- - New for 1.3.2. 
- - Read-only support for all geometry types. 
+ - New for 1.3.2.
+ - Read-only support for all geometry types.
  - Supports coordinate systems.
  - Requires SDE C API from ESRI.
 
@@ -7544,7 +7973,7 @@ Shapefile Driver:
  - Implement DeleteFeature()
 
 S-57 Driver:
- - Added support for Arcs. 
+ - Added support for Arcs.
  - Added special DSID_DSSI feature class to capture header info.
 
 DGN Driver:
@@ -7562,48 +7991,48 @@ GDAL 1.3.1 - Overview of Changes
 --------------------------------
 
 Next Generation SWIG Wrappers (GDAL and OGR):
- - Python, Perl and Ruby bindings considered to be ready to use. 
+ - Python, Perl and Ruby bindings considered to be ready to use.
  - C#, Java, PHP are at best initial prototypes.
- - Added configure options for most NG options. 
+ - Added configure options for most NG options.
 
-PCRaster Driver: 
+PCRaster Driver:
  - libcsf is now included as part of GDAL.
- - PCRaster enabled by default on win32. 
+ - PCRaster enabled by default on win32.
  - --with-pcraster=internal option now supported on unix (but not yet default)
 
 VSI Virtualization:
  - The "large file API" (VSI*L) has been re-engineered to allow installing
-   additional file handlers at runtime.  
- - Added "in memory" VSI handler so that now any driver using VSI*L 
-   functions for data access can operate on in-memory files. 
+   additional file handlers at runtime.
+ - Added "in memory" VSI handler so that now any driver using VSI*L
+   functions for data access can operate on in-memory files.
  - PNG, JPEG and GeoTIFF drivers upgraded to work with in-memory support.
 
 Raster Attribute Tables:
- - Implemented new Raster Attribute Tables support.  See the 
-   GDALRasterAttributeTable class for more information. 
+ - Implemented new Raster Attribute Tables support.  See the
+   GDALRasterAttributeTable class for more information.
 
 Erdas Imagine Overviews:
- - Erdas Imagine driver upgraded to support building internal overviews. 
+ - Erdas Imagine driver upgraded to support building internal overviews.
  - Generic overview handler updated to support overviews in Erdas Imagine
    format for any file format.  Set USE_RRD config option to YES to enable.
 
 gdalwarp:
  - Added proper support for "unified source nodata", so the -srcnodata
-   switch works well. 
+   switch works well.
 
-RIK Driver: 
+RIK Driver:
  - New Swedish format driver implemented by Daniel Wallner.
 
 JPEG Driver:
- - Substantial improvements to EXIF support.  
+ - Substantial improvements to EXIF support.
 
 MrSID Driver:
- - Updated with proper JPEG2000 support as JP2MRSID driver, including 
+ - Updated with proper JPEG2000 support as JP2MRSID driver, including
    encoding with ESDK.
  - Updated to support MrSID Version 5.x SDKs.
 
 PNG Driver:
- - Fixed serious bugs with 16bit file support. 
+ - Fixed serious bugs with 16bit file support.
  - Added NODATA_VALUES to identify RGB sets that indicate a nodata pixel.
 
 
@@ -7611,20 +8040,20 @@ OGR 1.3.1 - Overview of Changes
 -------------------------------
 
 Reference Counting:
- - OGRSpatialReference and OGRFeatureDefn now honour reference counting 
+ - OGRSpatialReference and OGRFeatureDefn now honour reference counting
    semantics.
  - Note that, especially for the OGRFeatureDefn, it is now critical that
    all drivers be careful with reference counting.  Any OGR drivers not in
    the core distribution will likely crash if not updated.
 
 ESRI Personal Geodatabase Driver:
- - New driver implemented for ESRI Personal Geodatabase (.mdb) files. 
- - Uses ODBC, enabled by default on win32. 
+ - New driver implemented for ESRI Personal Geodatabase (.mdb) files.
+ - Uses ODBC, enabled by default on win32.
 
 ODBC Driver:
- - Updated to support binary fields. 
- - Updated to support WKB geometry fields. 
- - Updated to support DSN-less connections. 
+ - Updated to support binary fields.
+ - Updated to support WKB geometry fields.
+ - Updated to support DSN-less connections.
 
 S57 Driver:
  - Added support for Inland Waterways, and Additional Military Layers profiles
@@ -7637,33 +8066,33 @@ GDAL 1.3.0 - Overview of Changes
 
 Multithreading:
  - Lots of work done to implement support for multiple threads reading
-   from distinct GDALDataset objects at the same time. 
+   from distinct GDALDataset objects at the same time.
 
 GDALRasterBand / Persistent Auxiliary Metadata (PAM):
- - Support for preserving a variety of metadata in a supporting XML file. 
+ - Support for preserving a variety of metadata in a supporting XML file.
  - GDALRasterBand now supports "remembering" histograms, and has a concept
-   of the default histogram. 
+   of the default histogram.
  - GDALRasterBand now supports remembering image statistics.
- - Disabled by default (set GDAL_PAM_ENABLED=YES to turn on). 
+ - Disabled by default (set GDAL_PAM_ENABLED=YES to turn on).
  - Supported by *most* drivers with some caveats.
 
-GDALCopyWords(): 
- - This function is a low level work horse for copying and converting pixel 
+GDALCopyWords():
+ - This function is a low level work horse for copying and converting pixel
    data in GDAL.  It has been substantially optimized by Steve Soule (Vexcel).
 
 Next Generation Bindings:
- - Kevin Ruland and Howard Butler are working on reworked support for 
+ - Kevin Ruland and Howard Butler are working on reworked support for
    SWIG to generate Python, PHP, Java, C# and other language bindings for GDAL
-   and OGR. 
+   and OGR.
 
-VB6 Bindings: 
+VB6 Bindings:
  - Now substantially complete, see VB6 directory.
 
-HDF5 Driver: 
- - New HDF5 driver implemented by Denis Nadeau. 
+HDF5 Driver:
+ - New HDF5 driver implemented by Denis Nadeau.
 
-RMF Driver: 
- - New driver for Raster Matrix Format by Andrey Kislev. 
+RMF Driver:
+ - New driver for Raster Matrix Format by Andrey Kislev.
 
 MSGN (Meteosat Second Generation Native) Driver:
  - New driver implemented by Frans van der Bergh.
@@ -7671,13 +8100,13 @@ MSGN (Meteosat Second Generation Native) Driver:
 VRT Driver:
  - Fixed whopper of a memory leak in warped raster case.
 
-NetCDF Driver: 
+NetCDF Driver:
  - Preliminary CF conventions support by Denis Nadeau.
 
 NITF Driver:
  - NITF files between 2 and 4 GB in size can now be read and written.
 
-JPEG Driver: 
+JPEG Driver:
  - Added support for reading EXIF as metadata by Denis Nadeau.
 
 DODS Driver:
@@ -7685,28 +8114,28 @@ DODS Driver:
 
 JP2ECW (JPEG2000 ECW SDK) Driver:
  - Implemented support for new GML-in-JPEG2000 specification.
- - Implemented support for old MSI "worldfile" box. 
+ - Implemented support for old MSI "worldfile" box.
 
 JP2KAK (JPEG2000 Kakadu) Driver:
  - Implemented support for new GML-in-JPEG2000 specification.
- - Implemented support for old MSI "worldfile" box. 
+ - Implemented support for old MSI "worldfile" box.
 
-PCIDSK Driver: 
+PCIDSK Driver:
  - tiled files now supported for reading.
  - overviews now supported for reading.
 
 HFA (Imagine) Driver:
- - Supports creating internal overviews in very large files. 
- - Support reading class names. 
- - Support creating compressed files. 
+ - Supports creating internal overviews in very large files.
+ - Support reading class names.
+ - Support creating compressed files.
 
 GeoTIFF Driver:
- - Support reading files with odd bit depths (i.e. 3, 12, etc). 
+ - Support reading files with odd bit depths (i.e. 3, 12, etc).
  - Support 16/24bit floating point TIFFs (per Technote 3) (Andrey).
  - Support 12bit jpeg compressed imagery using libjpeg "MK1" library.
 
 HDF4 Driver:
- - Added support for ASTER Level 1A, 1B and 2 products (Andrey). 
+ - Added support for ASTER Level 1A, 1B and 2 products (Andrey).
 
 
 OGR 1.3.0 - Overview of Changes
@@ -7714,21 +8143,21 @@ OGR 1.3.0 - Overview of Changes
 
 OGRGeometry:
  - WKT (and GML) encoding now attempts to preserve pretty much full double
-   precision. 
+   precision.
  - geometries are now "coordinate dimension preserving" rather than dynamically
    figuring out dimension depending on whether Z is set.  So a geometry can
-   now be 3D even if all z values are zero.  
+   now be 3D even if all z values are zero.
  - Fixed up proper EMPTY geometry support per standard.
 
-GRASS Driver:  
- - New driver for GRASS 6 vector data written by Radim Blazek. 
+GRASS Driver:
+ - New driver for GRASS 6 vector data written by Radim Blazek.
 
-Interlis Driver: 
+Interlis Driver:
  - New driver for Swiss Interlis format from Permin Kalberer (SourcePole).
 
 Shape Driver:
  - Fixed logic for degenerate polygons (Baumann Konstantin).
- 
+
 PostgreSQL/PostGIS Driver:
  - Implemented fast GetExtent() method (Oleg Semykin).
  - Implemented layer type from geometry_columns (Oleg Semykin).
@@ -7738,24 +8167,24 @@ PostgreSQL/PostGIS Driver:
  - Added PostGIS "binary cursor" mode for faster geometry access.
 
 VRT Driver:
- - Pass through attribute queries to underlying driver. 
+ - Pass through attribute queries to underlying driver.
  - Pass through spatial queries as attribute filters on the underlying layer.
 
 S57 Driver:
- - Added concept of supporting different profiles. 
- - Added prototype AML profile support. 
+ - Added concept of supporting different profiles.
+ - Added prototype AML profile support.
 
 MySQL Driver:
- - Fixed for FID recognition (eg. mediumint). 
+ - Fixed for FID recognition (eg. mediumint).
 
-GML Driver: 
+GML Driver:
  - Various fixes for generated GML correctness (Tom Kralidis).
 
 TIGER/Line Driver:
  - Added Tiger 2004 support.
 
 Oracle Driver:
- - Use VARCHAR2 for fixed size string fields. 
+ - Use VARCHAR2 for fixed size string fields.
  - Use OCI_FID config variable when creating layers, and reading select results
 
 
@@ -7766,70 +8195,70 @@ Oracle Driver:
 GDAL 1.2.6 - Overview of Changes
 --------------------------------
 
-gdal_translate: 
- - Added -sds switch to copy all subdatasets. 
+gdal_translate:
+ - Added -sds switch to copy all subdatasets.
 
-gdalwarp: 
- - Added Thin Plate Spline support (-tps switch). 
+gdalwarp:
+ - Added Thin Plate Spline support (-tps switch).
 
 GDALRasterBand:
  - Now uses two level block cache allowing efficient access to files
-   with a very large number of tiles. 
+   with a very large number of tiles.
  - Added support for YCbCr color space for raster band color interpretations.
- - Added AdviseRead() method - currently only used by ECW driver and OGDI 
-   drivers. 
+ - Added AdviseRead() method - currently only used by ECW driver and OGDI
+   drivers.
 
 ILWIS Driver:
- - New driver for the raster format of the ILWIS software. 
+ - New driver for the raster format of the ILWIS software.
 
 ECW Driver:
  - Updated to use ECW SDK 3.1 (older ECW SDK no longer supported!)
 
 ECWJP2 Driver:
  - Added JPEG2000 support driver based on ECW/JPEG2000 SDK with a variety
-   of features. 
+   of features.
 
-NITF Driver: 
- - Added support for reading *and* writing JPEG2000 compressed NITF files 
-   using the ECW/JPEG2000 SDK. 
- - Added ICHIPB support. 
+NITF Driver:
+ - Added support for reading *and* writing JPEG2000 compressed NITF files
+   using the ECW/JPEG2000 SDK.
+ - Added ICHIPB support.
 
 HDF Driver:
- - Add support for georeferencing from some additional metadata formats. 
- - Fixed bug with multi-band HDF-EOS datasets. 
+ - Add support for georeferencing from some additional metadata formats.
+ - Fixed bug with multi-band HDF-EOS datasets.
 
 MrSID Driver:
- - Driver can now be built as a plugin on win32. 
- - Split out MrSID 3.x SDK support - not readily buildable now. 
- - Implemented accelerated IO cases for MrSID 4.x SDK. 
+ - Driver can now be built as a plugin on win32.
+ - Split out MrSID 3.x SDK support - not readily buildable now.
+ - Implemented accelerated IO cases for MrSID 4.x SDK.
  - Support for writing MrSID files added (improved?)
 
-Imagine Driver: 
- - Fixed bug reading some large multiband Imagine files. 
- - Added support for writing compressed files. 
+Imagine Driver:
+ - Fixed bug reading some large multiband Imagine files.
+ - Added support for writing compressed files.
 
 Win32 Builds:
  - Added versioning information to GDAL DLL.
 
 L1B Driver:
- - Only return a reduced grid of control points. 
+ - Only return a reduced grid of control points.
 
 IDA (WinDisp4) Driver:
- - New read/write driver for the Image Display and Analysis raster format 
-   used by WinDisp 4. 
+ - New read/write driver for the Image Display and Analysis raster format
+   used by WinDisp 4.
 
 NDF (NLAPS) Driver:
- - Added NDF/NLAPS read driver for version 1 and 2. 
+ - Added NDF/NLAPS read driver for version 1 and 2.
 
-MSG Driver: 
+MSG Driver:
  - Added support for the Metosat Second Generation raw file format.
 
 GTiff Driver:
- - Added support for offset/scale being saved and loaded (special metadata). 
+ - Added support for offset/scale being saved and loaded (special metadata).
  - Added Cylindrical Equal Area.
  - Added PROFILE creation option to limit extra tags.
 
-PNG Driver: 
+PNG Driver:
  - Updated internal code for libpng to libpng 1.2.8.
 
 
@@ -7837,33 +8266,33 @@ OGR 1.2.6 - Overview of Changes
 -------------------------------
 
 OGRSFDriverRegistrar:
- - Added support for autoloading plugin drivers from ogr_<driver>.so. 
+ - Added support for autoloading plugin drivers from ogr_<driver>.so.
 
 ogr.py:
  - Geometry, and Feature now take care of their own reference counting and
    will delete themselves when unreferenced.  Care must still be taken to
-   unreference all features before destroying the corresponding 
+   unreference all features before destroying the corresponding
    layer/datasource.
- - ogr.Feature fields can now be fetched and set directly as attributes. 
- - Geometry constructor can now take various formats (wkt, gml, and wkb). 
- - Added docstrings. 
- - Added better __str__ methods on several objects. 
- - Various other improvements. 
+ - ogr.Feature fields can now be fetched and set directly as attributes.
+ - Geometry constructor can now take various formats (wkt, gml, and wkb).
+ - Added docstrings.
+ - Added better __str__ methods on several objects.
+ - Various other improvements.
 
 OGRLayer:
  - Re-wrote generic spatial search support to be faster in case of rectangular
-   filters. 
- - Intersects() method now really uses GEOS.  This also affects all OGR 
-   layer spatial filtering (with non-rectangular filters). 
- - Added SetNextByIndex() method on OGRLayer.  
+   filters.
+ - Intersects() method now really uses GEOS.  This also affects all OGR
+   layer spatial filtering (with non-rectangular filters).
+ - Added SetNextByIndex() method on OGRLayer.
 
 OGRSpatialReference:
  - Automatically generate +towgs84 from EPSG tables when translating to
-   PROJ.4 if available and TOWGS84 not specified in source WKT. 
+   PROJ.4 if available and TOWGS84 not specified in source WKT.
  - Updated GML CRS translation to follow OGC 05-011 more closely.  Still
-   incomplete but operational for some projections. 
- - Added support for FIPSZONE State Plane processing for old ESRI .prjs. 
- - Added Goode Homolosine support. 
+   incomplete but operational for some projections.
+ - Added support for FIPSZONE State Plane processing for old ESRI .prjs.
+ - Added Goode Homolosine support.
  - Added GEOS (Geostationary Satellite) support.
 
 OCI (Oracle) Driver:
@@ -7871,14 +8300,14 @@ OCI (Oracle) Driver:
    hold the geometry.
 
 PostGIS Driver:
- - Fixed some problems with truncation for integer and float list fields. 
+ - Fixed some problems with truncation for integer and float list fields.
 
-Shapefile Driver: 
- - Added support for MapServer style spatial index (.qix). 
+Shapefile Driver:
+ - Added support for MapServer style spatial index (.qix).
 
-GML Driver: 
- - Improved support for 3L0 (GML 3 - Level 0 profile) reading and writing. 
-   On read we can now use the .xsd instead of needing to build a .gfs file. 
+GML Driver:
+ - Improved support for 3L0 (GML 3 - Level 0 profile) reading and writing.
+   On read we can now use the .xsd instead of needing to build a .gfs file.
 
 
 ===============================================================================
@@ -7887,13 +8316,13 @@ GDAL 1.2.5 - Overview of Changes
 --------------------------------
 
 gdalwarp Utility:
- - Added "proper" source and destination alpha support. 
+ - Added "proper" source and destination alpha support.
 
-PCRaster Driver: 
+PCRaster Driver:
  - added write support, now consider ready for regular use.
 
 MrSID Driver:
- - Initial support for writing to MrSID with encoding SDK. 
+ - Initial support for writing to MrSID with encoding SDK.
 
 GeoTIFF Driver:
  - Updated internal copy of libtiff to fix overview building ... really!
@@ -7904,18 +8333,18 @@ OGR 1.2.5 - Overview of Changes
 -------------------------------
 
 OGRSpatialReference:
- - Added Bonne projection. 
+ - Added Bonne projection.
 
 Docs:
- - Added OGR C++ API Tutorial (reading and writing). 
+ - Added OGR C++ API Tutorial (reading and writing).
 
 PostGIS Driver:
  - Implemented SetFeature() and DeleteFeature() methods for in-place updates.
 
 Oracle (OCI) Driver:
- - Fixed support for writing into Oracle 10g. 
- - Fixed serious memory leak of geometries. 
- - Fixed bug with 3D multipolygons. 
+ - Fixed support for writing into Oracle 10g.
+ - Fixed serious memory leak of geometries.
+ - Fixed bug with 3D multipolygons.
  - Added support for selecting tables in the datasource name.
 
 ===============================================================================
@@ -7923,33 +8352,33 @@ Oracle (OCI) Driver:
 GDAL 1.2.4 - Overview of Changes
 --------------------------------
 
-gdalwarp: 
-  - Fixed some issues with only partially transformable regions. 
+gdalwarp:
+  - Fixed some issues with only partially transformable regions.
   - Added Alpha mask generation support (-dstalpha switch).
 
 HFA/Imagine Driver:
   - bug fix in histogram handling.
-  - improved support for large colormaps. 
+  - improved support for large colormaps.
 
 Envi Driver:
   - Capture category names and colormaps when reading.
 
 SAR CEOS Driver:
-  - Added support for PALSAR/ALOS Polarimetric Datasets. 
+  - Added support for PALSAR/ALOS Polarimetric Datasets.
 
 RadarSat 2 Driver:
-  - New.  Reads RadarSat 2 Polarimetric datasets with a "product.xml" and 
-    imagery in TIFF files. 
+  - New.  Reads RadarSat 2 Polarimetric datasets with a "product.xml" and
+    imagery in TIFF files.
 
 OGDI Driver:
   - Important bug fix for downsampled access.
 
 GeoTIFF Driver:
   - Lots of libtiff upgrades, including some quite serious bug fixes.
-  - Added better support for 16bit colormaps. 
+  - Added better support for 16bit colormaps.
   - Write projection information even if we don't have a geotransform or GCPs.
   - Improved alpha support.
-  - Generate graceful error message for BigTIFF files. 
+  - Generate graceful error message for BigTIFF files.
 
 DODS Driver:
   - Almost completely reimplemented.   Uses chunk-by-chunk access.  Supports
@@ -7960,28 +8389,28 @@ NetCDF Driver:
     NetCDF driver (Radim).
 
 JP2KAK Driver:
-  - Added alpha support, including greyscale+alpha. 
+  - Added alpha support, including greyscale+alpha.
 
 AirSAR Driver:
-  - New, reads AirSAR Polarimetric Radar format. 
+  - New, reads AirSAR Polarimetric Radar format.
 
 
 
 OGR 1.2.4 - Overview of Changes
 -------------------------------
 
-epsg_tr.py: 
+epsg_tr.py:
   - Added escaping rules when generating PostGIS output.
 
 tigerpoly.py:
-  - Discard dangles and degenerate rings. 
+  - Discard dangles and degenerate rings.
 
 VRT Driver:
-  - Fixed serious error in handling cleanup of VRT datasources, was often 
+  - Fixed serious error in handling cleanup of VRT datasources, was often
    causing a crash.
 
 SQLLite Driver:
-  - Fixed substantial memory leaks. 
+  - Fixed substantial memory leaks.
 
 MySQL Driver:
   - New readonly non-spatial MySQL driver implemented.
@@ -7990,7 +8419,7 @@ MITAB Driver:
   - Updated from upstream, several fixes.
 
 TIGER/Line Driver:
-  - Fixed serious bug with handling "full" records at end of .RT2 file. 
+  - Fixed serious bug with handling "full" records at end of .RT2 file.
 
 OCI/Oracle Driver:
   - Added OCI_FID environment support to control FID selection.
@@ -8004,7 +8433,7 @@ GDAL 1.2.3 - Overview of Changes
 --------------------------------
 
 GeoTIFF Driver:
-    - Fixed many missing compression codecs when built with the internal 
+    - Fixed many missing compression codecs when built with the internal
       libtiff.
     - Modified driver metadata to only list available compression types.
 
@@ -8015,7 +8444,7 @@ GRASS Driver:
     - Fixed support for building with grass57.
 
 MrSID Driver:
-    - Fixed support for MrSID Encoding SDK. 
+    - Fixed support for MrSID Encoding SDK.
 
 NITF Driver:
     - Fixed serious bug with non-square output files.
@@ -8026,42 +8455,42 @@ OGR 1.2.3 - Overview of Changes
 
 OGRSpatialReference:
     - Corrected memory leaks - OSRCleanup() cleans up temporary tables.
-    - Fixed build problem with ogrct.cpp on Solaris. 
+    - Fixed build problem with ogrct.cpp on Solaris.
 
 TIGER Driver:
     - Improved generality of support for GDT files.
 
 OGRGeometry:
-    - Added getArea() method for rings, polygons and multipolygons. 
+    - Added getArea() method for rings, polygons and multipolygons.
 
  =============================================================================
 
 GDAL 1.2.2 - Overview of Changes
 --------------------------------
 
-GRASS Driver: 
+GRASS Driver:
     - Add Radim's version of the driver submitted by Radim.  This version
-      uses GRASS 5.7 libraries directly instead of using libgrass. 
+      uses GRASS 5.7 libraries directly instead of using libgrass.
 
 DODS Driver:
     - Added support for spatial_ref, FlipX and FlipY .das info.
 
 CPG Driver:
-    - added new driver for Convair Polarimetric format. 
+    - added new driver for Convair Polarimetric format.
 
 HDF Driver:
-    - Significant bugs fixed. 
+    - Significant bugs fixed.
 
 USGS DEM Driver:
     - Support writing UTM projected files.
 
 PNG Driver:
-    - Upgraded to libpng 1.2.6. 
+    - Upgraded to libpng 1.2.6.
 
 MrSID Driver:
-    - Substantial performance improvements. 
-    - Support for DSDK 4.x 
-    - Support JPEG2000 files via MrSID SDK. 
+    - Substantial performance improvements.
+    - Support for DSDK 4.x
+    - Support JPEG2000 files via MrSID SDK.
 
 NITF Driver:
     - Support JPEG2000 compressed files (with Kakadu support)
@@ -8070,17 +8499,17 @@ ESRI BIL:
     - Support .clr color files.
 
 VRT Driver:
-    - Added support for describing raw files with VRTRawRasterBand. 
+    - Added support for describing raw files with VRTRawRasterBand.
     - Added support for virtual warped files with VRTWarpedRasterBand.
 
 GeoTIFF Driver:
-    - Fix support for 16bit image color tables. 
+    - Fix support for 16bit image color tables.
     - Write ExtraSamples tag for files with more samples than expected
-      in photometric interpretation. 
-    - External overviews now built for read-only files. 
+      in photometric interpretation.
+    - External overviews now built for read-only files.
 
 Erdas Imagine Driver:
-    - Fixed support for compressed floating point layers. 
+    - Fixed support for compressed floating point layers.
     - Various other fixes for compatible with newer Imagine versions.
     - improved metadata handling.
 
@@ -8101,14 +8530,14 @@ S-57 Driver:
     - Substantial performance improvements.
 
 ODBC Driver:
-    - Arbitrary length field values now supported. 
+    - Arbitrary length field values now supported.
 
 GEOS:
     - Integration a series of methods utilizing GEOS when available.  Note
       that Intersect() is still just an envelope comparison.
 
 OGRSpatialReference:
-    - Fixed Swiss Oblique Mercator support. 
+    - Fixed Swiss Oblique Mercator support.
 
  =============================================================================
 
@@ -8122,7 +8551,7 @@ HDF4 Driver:
     - Added some degree of HDF-EOS support.  HDFEOS layer now part of GDAL.
 
 DODS Driver:
-    - Substantial fixes, support for flipped datasets.  
+    - Substantial fixes, support for flipped datasets.
 
 HFA (Erdas Imagine) Driver:
     - Fixed bug with files between 2 and 4GB.
@@ -8143,7 +8572,7 @@ MrSID Driver:
     - Support added for DSDK 4.0.x.
 
 ECW Driver:
-    - Added preliminary support for using 3.0 SDK for JPEG2000 support. 
+    - Added preliminary support for using 3.0 SDK for JPEG2000 support.
     - Fix oversampling assertion problem.
 
 ArcInfo Binary Grids:
@@ -8157,7 +8586,7 @@ OGRSpatialReference:
     - Various fixes related to prime meridians.
 
 PostgreSQL/PostGIS Driver:
-    - Added layer name laundering. 
+    - Added layer name laundering.
     - Launder names on by default.
     - Clean stale entries in geometry_columns table when creating a layer.
     - Support treating names views as layers.
@@ -8166,7 +8595,7 @@ PostgreSQL/PostGIS Driver:
 S57 Driver:
     - Fixed serious bugs with support for auto-applying update files.
     - Improvements to S57 writing support.
-  
+
  =============================================================================
 
 GDAL 1.2.0 - Overview of Changes
@@ -8174,7 +8603,7 @@ GDAL 1.2.0 - Overview of Changes
 
 Configuration:
     - Libtool used by default with Unix style builds.  Use --without-libtool
-      to avoid this. 
+      to avoid this.
     - PROJ.4 can now be linked statically using --with-static-proj4.
     - Added --without-bsb option for those averse to legal risk.
 
@@ -8184,113 +8613,113 @@ DODS/OPeNDAP Driver:
 PCIDSK Driver:
     - PCIDSK read/write raster driver implemented (Andrey).
 
-Erdas Imagine / HFA Driver: 
+Erdas Imagine / HFA Driver:
     - Support recent Imagine versions (data dictionary changes).
     - Better logic to search for .rrd file locally.
     - Support creating files in the 2GB to 4GB size range.
 
-GIF Driver: 
-    - Updated to libungif 4.1.0. 
+GIF Driver:
+    - Updated to libungif 4.1.0.
     - Various hacks to try and identify transparent colors better.
 
-BMP Driver: 
+BMP Driver:
     - Handle 32bit BMPs properly.
 
 HDF4 Driver:
-    - Added proper support for multi-sample GR datasets. 
+    - Added proper support for multi-sample GR datasets.
     - Various fixes and improvements for specific product types.
 
-GeoTIFF Driver: 
+GeoTIFF Driver:
     - Added PHOTOMETRIC option to control photometric interp of new files.
 
-JPEG2000/Kakadu Driver: 
-    - Support reading/creating lossless 16bit files. 
+JPEG2000/Kakadu Driver:
+    - Support reading/creating lossless 16bit files.
     - Updated to support Kakadu 4.1 library.
 
-NITF Driver: 
-    - Implement support for IGEOLO="U" (MGRS/UTM) coordinates. 
+NITF Driver:
+    - Implement support for IGEOLO="U" (MGRS/UTM) coordinates.
     - Added overview (as external GeoTIFF file) support.
 
-MrSID Driver: 
-    - Support DSDK 4.2.x. 
+MrSID Driver:
+    - Support DSDK 4.2.x.
 
 PNG Driver:
-    - Support required byte swapping of 16bit PNG data. 
+    - Support required byte swapping of 16bit PNG data.
 
 FAST Driver:
-    - lots of fixes, supports more datums and ellipsoids. 
+    - lots of fixes, supports more datums and ellipsoids.
 
-NetCDF Driver: 
-    - New driver implemented for netCDF support. 
-    - Pretty much tied to form of netCDF used in GMT for now. 
+NetCDF Driver:
+    - New driver implemented for netCDF support.
+    - Pretty much tied to form of netCDF used in GMT for now.
 
-VTerrain .bt Driver: 
+VTerrain .bt Driver:
     - New driver for VTerrain .bt elevation format.
 
 ECW Driver:
-    - support supersampled reads efficiently. 
+    - support supersampled reads efficiently.
     - special case for dataset level RasterIO() implemented for much better
-      performance in some applications. 
+      performance in some applications.
 
 ESRI BIL (EHdr) Driver:
     - Support world files.
 
-VRT Driver: 
-    - Implement filtering support. 
+VRT Driver:
+    - Implement filtering support.
 
-GIO (Arc/Info Binary Grid via avgridio.dll): 
-   - Driver disabled ... to undependable. 
+GIO (Arc/Info Binary Grid via avgridio.dll):
+   - Driver disabled ... to undependable.
 
 
 Python:
-    - Preliminary support for numarray in addition to numpy (Numeric). 
+    - Preliminary support for numarray in addition to numpy (Numeric).
 
 Contouring:
-    - New gdal_contour utility program implementing contour generation.  
-    - Underlying algorithm in gdal/alg.  
+    - New gdal_contour utility program implementing contour generation.
+    - Underlying algorithm in gdal/alg.
 
 Warping:
     - Improved support in GDALSuggestedWarpOutput() for "world" sized
-      files that are only partially transformable. 
-    - Bicubic resampler improved. 
+      files that are only partially transformable.
+    - Bicubic resampler improved.
     - What was gdalwarptest is now gdalwarp, and the old gdalwarp is now
       gdalwarpsimple.  The sophisticated warper is now the default.
 
-Man Pages: 
+Man Pages:
     - Man pages for GDAL utilities now being maintained and installed (Silke).
 
- 
+
 
 OGR 1.2.0 - Overview of Changes
 -------------------------------
 
 OGRSpatialReference:
    - Added methods for converting to/from GCTP representation.
-   - Added HOM 2 points on centerline variant. 
+   - Added HOM 2 points on centerline variant.
 
 DODS (OPeNDAP) Driver:
    - Preliminary implementation.
 
-TIGER/Line Driver: 
-   - Added support for GDT ASCII TIGER-like format. 
-   - Support TIGER/Line 2003 format. 
+TIGER/Line Driver:
+   - Added support for GDT ASCII TIGER-like format.
+   - Support TIGER/Line 2003 format.
 
 S-57 Driver:
-   - Preliminary export support implemented. 
+   - Preliminary export support implemented.
    - Support capture of FFPT (feature to feature) linkages.
    - Support capture of TOPI from VRPT.
-   - Support capture of primitives as additional layers. 
+   - Support capture of primitives as additional layers.
 
 Shapefile Driver:
-   - gdal/frmts/shapelib removed from GDAL source tree, now just a 
-     copy of required shapelib files are kept in gdal/ogr/ogrsf_frmts/shape. 
-   - Attempt identify polygons that are really multi-polygons and convert them 
+   - gdal/frmts/shapelib removed from GDAL source tree, now just a
+     copy of required shapelib files are kept in gdal/ogr/ogrsf_frmts/shape.
+   - Attempt identify polygons that are really multi-polygons and convert them
      into multi-polygons properly (Radim Blazek).
    - Create FID attribute in .dbf file if no attribute added by application.
 
 GML Driver:
-   - Lots of fixes and improvements for reading and writing. 
-   - Now writes a schema file by default. 
+   - Lots of fixes and improvements for reading and writing.
+   - Now writes a schema file by default.
    - Field types are set now when reading based on data found on first pass.
    - Added support for the various kinds of geometry collections.
 
@@ -8300,21 +8729,21 @@ DGN Driver:
 
 ODBC Driver:
    - New ODBC driver implemented.  Build by default on Windows, and buildable
-     on Unix (with unixodbc). 
+     on Unix (with unixodbc).
 
-VRT Driver: 
-   - New "virtual" OGR Datasource format implemented.  
-   - Configuration stored in XML control file. 
+VRT Driver:
+   - New "virtual" OGR Datasource format implemented.
+   - Configuration stored in XML control file.
 
 Oracle (OCI) Driver:
-   - support reading views. 
+   - support reading views.
 
 OGR Core:
    - Added support for WKT EMPTY geometry objects (like "MULTIPOINT(EMPTY)").
-   - Added DeleteFeature() method on OGRLayer class.  
+   - Added DeleteFeature() method on OGRLayer class.
 
-NTF Driver: 
-   - Support CHG_TYPE attribute for landline plus product. 
+NTF Driver:
+   - Support CHG_TYPE attribute for landline plus product.
 
 
 
@@ -8324,12 +8753,12 @@ GDAL 1.1.9 - Overview of Changes
 --------------------------------
 
  o MrSID Driver: New for 1.1.9, read-only, includes good coordinate system
-   support, and should be high performance. 
+   support, and should be high performance.
 
- o ECW Driver: Now reads coordinate system information (but doesn't write). 
+ o ECW Driver: Now reads coordinate system information (but doesn't write).
 
- o HDF Driver: Added support for Hyperion Level 1, Aster Level 1A/1B/2, MODIS 
-   Level 1B(earth-view)/2/3, SeaWIFS Level 3. 
+ o HDF Driver: Added support for Hyperion Level 1, Aster Level 1A/1B/2, MODIS
+   Level 1B(earth-view)/2/3, SeaWIFS Level 3.
 
  o L1B Driver: Now reads GCPs for georeferencing.
 
@@ -8338,10 +8767,10 @@ GDAL 1.1.9 - Overview of Changes
 
  o JP2KAK Driver: Can be used with Kakadu 4.0.2 now.  Compatibility fixes
    for internal geotiff to improve compatibility with Mapping Science tools.
-   Added palette support. 
+   Added palette support.
 
  o HFA (Imagine) Driver: Added read/write support for color table opacity.
-   Added write support for large (spill) files. 
+   Added write support for large (spill) files.
 
  o "core" directory renamed to "gcore" to avoid confusing configure script.
 
@@ -8349,44 +8778,44 @@ GDAL 1.1.9 - Overview of Changes
    data files (those in gdal/data directory).
 
  o Added GDALDataset::RasterIO() for more efficient reading of multiple bands
-   in one request (in some cases anyways). 
+   in one request (in some cases anyways).
 
  o High performance warp api considered to be complete now, and substantially
    optimized.
 
- o gdal_merge.py: supported multiple bands, copying PCT. 
+ o gdal_merge.py: supported multiple bands, copying PCT.
 
 
 OGR 1.1.9 - Overview of Changes
 -------------------------------
 
  o Oracle Spatial: New generic read/write, and implemented highly optimized
-   loading support. 
+   loading support.
 
  o Tiger driver: added support for TIGER/Line 2002 product.
 
  o GML driver:  now supports Xerces versions from 1.6 up to 2.3.  Lots of
-   bugs fixes and improvements.   GML Geometry now in OGR core. 
+   bugs fixes and improvements.   GML Geometry now in OGR core.
 
  o Improved support for translating to and from ESRI WKT, including a complete
-   mapping between EPSG related ESRI datum names and OGR's expected names. 
+   mapping between EPSG related ESRI datum names and OGR's expected names.
 
  o Improved support for alternate prime meridians in coordinate system code.
 
- o Shapefiles: Can write features with NULL geometry, 
+ o Shapefiles: Can write features with NULL geometry,
 
- o DGN: added 3d write support. 
+ o DGN: added 3d write support.
 
  o Implemented generic attribute indexing support (only used for shapefile
-   at this point).  Use in SQL where clauses and ExecuteSQL(). 
+   at this point).  Use in SQL where clauses and ExecuteSQL().
 
  o WKT MULTIPOINT in/out formatting fixed.
 
- o Added SynToDisk() method on OGRDataset and OGRLayer. 
+ o Added SynToDisk() method on OGRDataset and OGRLayer.
 
- o Implemented "Web Coordinate Transformation Service" (ogr/wcts). 
+ o Implemented "Web Coordinate Transformation Service" (ogr/wcts).
 
- o Implemented "in memory" format driver. 
+ o Implemented "in memory" format driver.
 
  o C API documented.
 
@@ -8400,38 +8829,38 @@ GDAL 1.1.8 - Overview of Changes
 
  o Implemented HDF 4 read/write support. This includes HDF EOS reading.
 
- o Implemented Windows BMP read/write support. 
+ o Implemented Windows BMP read/write support.
 
- o Implemented NITF read/write support. 
+ o Implemented NITF read/write support.
 
- o Implemented NOAA Polar Orbiter L1B format driver. 
+ o Implemented NOAA Polar Orbiter L1B format driver.
 
- o Implemented EOSAT FAST format driver. 
+ o Implemented EOSAT FAST format driver.
 
  o Implemented a JasPer based JPEG2000 driver (several limitations).
 
- o Implemented a Kakadu based JPEG2000/GeoJP2(tm) driver (full featured, but 
-   Kakadu is not open source). 
+ o Implemented a Kakadu based JPEG2000/GeoJP2(tm) driver (full featured, but
+   Kakadu is not open source).
 
  o Implemented new 'gdalwarp' application for projection and GCP based image
    warping.  See gdal/alg for underlying algorithms.  Currently gdalwarp only
    supports 8 bit images and holds the whole source image in memory.
 
- o Implemented write support for ESRI ASCII Grids. 
+ o Implemented write support for ESRI ASCII Grids.
 
  o Lots of improvements to GeoTIFF driver.  Metadata writing, update of
    georeferencing, and support for writing PCS codes based on AUTHORITY fields
-   in WKT.  
+   in WKT.
 
  o Implemented support for uncompressed 1bit data in Erdas Imagine files,
    as well as generic metadata.
 
  o Fixed 0xFF compression support in the Arc/Info Binary Grid (AIG) driver.
 
- o Lots of improvements to BSB drive, including preliminary uncompressed 
+ o Lots of improvements to BSB drive, including preliminary uncompressed
    output support, support for reading BSB 3.0 and GEO/NOS.
 
- o Lots of work on VRT format.  
+ o Lots of work on VRT format.
 
  o ECW: Fixed bug with reading a more than full resolution.
 
@@ -8441,13 +8870,13 @@ GDAL 1.1.8 - Overview of Changes
 
  o Added the --version and --formats options to many utility programs.
 
- o gdal_translate: 
+ o gdal_translate:
     - added -projwin flag to copy a window specified in projection coordinates.
     - added the -a_srs option to assign a user supplied SRS to output file.
     - translation with subsetting to any format now support (uses VRT inside).
 
- o Lots of metadata now attached to driver objects describing their 
-   capabilities. 
+ o Lots of metadata now attached to driver objects describing their
+   capabilities.
 
  o Implemented GDALDestroyDriverManager() to ensure full memory cleanup of
    GDAL related resources.
@@ -8464,12 +8893,12 @@ OGR 1.1.8 - Overview of Changes
  o Implemented support for writing 2D DGN files.   Added support for MSLINK
    and Text values available as attributes.
 
- o Implemented FMEObjects based read driver. 
+ o Implemented FMEObjects based read driver.
 
  o Implemented ExecuteSQL() method on OGRDataSource.  Generic code supports
-   fairly full featured SELECT statements. 
+   fairly full featured SELECT statements.
 
- o Various fixes to 3D shapefile support. 
+ o Various fixes to 3D shapefile support.
 
  o Fixes to binary representation for 2.5D geometries.  Fixed MULTIPOINT WKT
    geometry representation.
@@ -8488,7 +8917,7 @@ OGR 1.1.8 - Overview of Changes
  o Implemented support for Meridian 2 NTF files in NTF driver.  Better
    support for GENERIC_CPOLY geometries.
 
- o  Added support for [NOT] IN, [NOT] LIKE and IS [NOT] NULL predicates in 
+ o  Added support for [NOT] IN, [NOT] LIKE and IS [NOT] NULL predicates in
    WHERE clauses.
 
  o Implemented a C API for accessing OGR.
@@ -8513,7 +8942,7 @@ GDAL 1.1.7 - Overview of Changes
  o Upgraded TIFF/GeoTIFF support to CVS version ... includes new extension
    API and removes need for private libtiff include files entirely.
 
- o gdal_translate now has scaling option (-scale). 
+ o gdal_translate now has scaling option (-scale).
 
  o Added utility documentation.
 
@@ -8550,15 +8979,15 @@ GDAL 1.1.6 - Overview of Changes
 
  o Implemented BSB Format (Nautical Chart Format) read support.
 
- o Preliminary implementation of Virtual Datasets (gdal/frmts/vrt). 
+ o Preliminary implementation of Virtual Datasets (gdal/frmts/vrt).
 
- o Support for writing DTED files. 
+ o Support for writing DTED files.
 
  o Some raw formats (i.e. PAux, HKV) support files larger than 2GB.
 
  o Add the AddBand() method on GDALDataset.
 
- o PAux: Added color table read support. 
+ o PAux: Added color table read support.
 
  o Various fixes to OGDI driver.
 
@@ -8566,7 +8995,7 @@ GDAL 1.1.6 - Overview of Changes
    OGRSpatialReference, and OGRCoordinateTransformation functionality.
 
  o Improved CEOS support, notable for ESA LANDSAT files, D-PAF ERS-1 and
-   Telaviv ERS data. 
+   Telaviv ERS data.
 
  o geotiff: upgraded libtiff support to approximately libtiff 3.5.7.
 
@@ -8577,17 +9006,17 @@ GDAL 1.1.6 - Overview of Changes
 OGR 1.1.6 - Overview of Changes
 -------------------------------
 
- o Fixed OGDI driver so that gltp urls with drive letters work properly on 
+ o Fixed OGDI driver so that gltp urls with drive letters work properly on
    windows.
 
- o Many improvements to OLE DB provider during the process of making it 
+ o Many improvements to OLE DB provider during the process of making it
    compatible with the MapGuide (SDP) client.  These include implementing
    restrictions for schema rowsets, treating missing information like WKT
    coordinate systems as NULL fields, and setting ISLONG on geometry fields.
-   Also made thread safe. 
+   Also made thread safe.
 
  o DGN: Threat SHAPE elements as polygons.  Set style information for text.
-   Added 3D support for most elements. 
+   Added 3D support for most elements.
 
  o Fixed bugs in WKT format for some OGR geometry types (i.e. multipoint).
 
@@ -8596,17 +9025,17 @@ OGR 1.1.6 - Overview of Changes
  o NTF: Don't try to cache all the records from multiple files at once.
 
  o Added experimental XML SRS support ... not the final schema.  Added
-   supporting "minixml" support to CPL.			
+   supporting "minixml" support to CPL.
 
- o PostGIS: Upgraded to PostGIS 0.6.  Added "soft transaction" semantics.  
+ o PostGIS: Upgraded to PostGIS 0.6.  Added "soft transaction" semantics.
    Many create feature calls can now be part of one transaction.  Transactions
-   are now a general OGR concept although only implemented for PostGIS. 
+   are now a general OGR concept although only implemented for PostGIS.
 
  o Added transform() and transformTo() methods for reprojecting geometries and
    added user options for this in ogr2ogr.
 
  o Very preliminary GML read/write support.  Needs Xerces C++ XML parser for
-   read support. 
+   read support.
 
 ==============================================================================
 
diff --git a/PROVENANCE.TXT b/PROVENANCE.TXT
index ede380f..a11f7c5 100644
--- a/PROVENANCE.TXT
+++ b/PROVENANCE.TXT
@@ -1,18 +1,18 @@
 == Committers ==
-   
+
 Current:
 
-See COMMITERS file. 
+See COMMITERS file.
 
 Historical and Current:
 
  fwarmerdam & warmerda - Frank Warmerdam
- dron - Andrey Kiselev 
+ dron - Andrey Kiselev
  danmo & daniel & dmorissette - Daniel Morissette (MapGears)
  dnadeau & denad21 - Denis Nadeau
  kdejong & kor - Kor de Jong (geog.uu.nl / PCRaster)
  aubin - Mark Aubin - Keyhole
- svillene & stephane - Stephane Villeneuve 
+ svillene & stephane - Stephane Villeneuve
  kmelero - Ken Melero (SANZ)
  nemec - Philip Nemec (Keyhole)
  pka - Pirmin Kalberer (Sourcepole)
@@ -26,9 +26,9 @@ Historical and Current:
  gwalter - Gillian Walter (Atlantis)
  aamici & andrea - Alessandro Amici
  kintel - Marius Kintel - dgnlib only
- lichun - Lichun Wang at ITC. 
+ lichun - Lichun Wang at ITC.
  hobu - Howard Butler (Hobu Inc)
- bsimon - Benjamin Simon - pgchip 
+ bsimon - Benjamin Simon - pgchip
  kshih - Ken Shih
  hsaggu - Harbinder Saggu (Safe Software)
  ryan - Ryan Proulx (Safe Software)
@@ -40,12 +40,12 @@ Historical and Current:
  cees - Cees Wesseling (PCRaster)
  rblazek - Radim Blazek (GRASS)
  cfis - Charles Savage - swig/ruby
- mloskot - Mateusz Loskot 
+ mloskot - Mateusz Loskot
  dwallner - Daniel Wallner
  collinsb - Benjamin Collins (MITRE) - swig/java
  jimg - James Gallager (OPeNDAP)
  kruland - Kevin Ruland
- vgough - Valient Gough - 1999 - configure stuff. 
+ vgough - Valient Gough - 1999 - configure stuff.
  silke - Silke Reimer (Intevation)
  ilucena - Ivan Lucena (Oracle)
  shalasz - Steve Halasz (Debian)
@@ -54,14 +54,14 @@ Historical and Current:
  pvachon - Phil Vachon
  klokan - Petr Pridal
  condit - Chris Condit (SDSC)
- retsios - Bas Retsios (ITC) 
+ retsios - Bas Retsios (ITC)
  rouault - Even Rouault
  rayg - Ray Gardener (Daylon Graphics)
- kosta - Konstantin Baumann 
+ kosta - Konstantin Baumann
  aaime - Andrea Aime (Openplans)
  gaopeng - Gao Peng (ESRI)
  hannah - hHannah Valbonesi (Safe Software)
- mchapman - Martin Chapman 
+ mchapman - Martin Chapman
  dreamil - Swapnil Harjare (Indictrans)
 
 == Outstanding Issues ==
@@ -87,39 +87,35 @@ In gdal/data we have several coordinate system dictionary files derived in one f
 
 Note: all the following are build options, not required.
 
-* Oracle OCI for OCI OGR driver. 
+* Oracle OCI for OCI OGR driver.
 * ESRI SDE for SDE OGR Driver.
-* ECW SDK for ECW/JP2ECW GDAL driver (close to free now I think). 
-* Kakadu for JP2KAK GDAL driver. 
-* MrSID SDK for MrSID/JP2MrSID driver. 
+* ECW SDK for ECW/JP2ECW GDAL driver (close to free now I think).
+* Kakadu for JP2KAK GDAL driver.
+* MrSID SDK for MrSID/JP2MrSID driver.
 * DWGdirect library for DWG writing.
 
 == Code Reviewed ==
 
-=== gdal/port === 
+=== gdal/port ===
 
 * Various contributors including Daniel Morissette, Andrey Kiselev, Frank Warmerdam and Mateusz Loskot.
 * cpl_minizip* files come from the "minizip" distribution. Placed under a modified BSD Licence (see port/LICENCE_minizip). Added to gdal/LICENSE.TXT
 
 === gdal/gcore ===
 
-* Various contributed, but mostly FrankW. 
-* All copyright held by FrankW. 
-* Version.rc contributed without copyright notice by Martin Daly, clarification requested.  Martin explicitly agreed by email, notice applied, all ok. 
+* Various contributed, but mostly FrankW.
+* All copyright held by FrankW.
+* Version.rc contributed without copyright notice by Martin Daly, clarification requested.  Martin explicitly agreed by email, notice applied, all ok.
 
 === gdal/alg ===
 
 * contour.cpp: Joint copyright between FrankW and ACT.
-* gdal_crs.c: derived from old GRASS/UMichigan code also under MIT/X license, properly noted in headers. 
+* gdal_crs.c: derived from old GRASS/UMichigan code also under MIT/X license, properly noted in headers.
 * gdalmediancut.cpp: derived from libtiff tiffmedian.c utility under a GDAL compatible license.  Properly noted in headers.
-* gdalrasterize.cpp: Derived from OpenEV code.  Relicensed from LGPL to MIT/X by explicit grant from copyright holder (Frank Warmerdam).  
+* gdalrasterize.cpp: Derived from OpenEV code.  Relicensed from LGPL to MIT/X by explicit grant from copyright holder (Frank Warmerdam).
 * gvgcpfit.c: Believed to be derived from Numerical Recipes in C.  It has not been used for some time, but was still in the CVS repository.  I have now removed it.
-* llrasterize.c: Derived from GD which has compatible MIT/X license.  Properly noted in header. 
-* thinplatespline.cpp: Contributed by VIZRT Inc.,  Relicensed to MIT/X with their explicit permission as noted in the header. 
-
-=== gdal/bridge === 
-
-* All FrankW, no issues of note.  
+* llrasterize.c: Derived from GD which has compatible MIT/X license.  Properly noted in header.
+* thinplatespline.cpp: Contributed by VIZRT Inc.,  Relicensed to MIT/X with their explicit permission as noted in the header.
 
 === gdal/data ===
 
@@ -127,39 +123,38 @@ Note: all the following are build options, not required.
 * cubewerx_extra.wkt: derived from definitions distributed by Cubewerx, rights unclear. See http://trac.osgeo.org/gdal/ticket/2165
 * ecw_cs.wkt: Derived via much processing from ERMapper GDT definitions, rights unclear. See http://trac.osgeo.org/gdal/ticket/2162
 * esri_extra.wkt: Derived with some processing from projections definitions in ArcGIS, rights unclear. See http://trac.osgeo.org/gdal/ticket/2163
-* ellipsoid.csv, gcs.csv, gdal_datum.csv, pcs.csv, prime_meridian.csv, projop_wparm.csv, unit_of_measure.csv: Derived from EPSG.  Modifications to EPSG data violate the EPSG use agreement (if we are to still attribute it to EPSG) so I have segregated changes into override files (i.e. gcs.override.csv). 
-* seed_2d.dgn, seed_3d.dgn: Exact source of these files is unclear.  The files contain no substantial creative content since all but the header elements were stripped.  Judged to acceptable use. 
+* ellipsoid.csv, gcs.csv, gdal_datum.csv, pcs.csv, prime_meridian.csv, projop_wparm.csv, unit_of_measure.csv: Derived from EPSG.  Modifications to EPSG data violate the EPSG use agreement (if we are to still attribute it to EPSG) so I have segregated changes into override files (i.e. gcs.override.csv).
+* seed_2d.dgn, seed_3d.dgn: Exact source of these files is unclear.  The files contain no substantial creative content since all but the header elements were stripped.  Judged to acceptable use.
 * NTS-50kindex.csv: Provided by Matt Wilkie, derived from NRCan dataset, rights unclear.  See http://trac.osgeo.org/gdal/ticket/2164 (closed - this file isn't actually in the source tree - it is separately distributed as part of FWTools!)
 
+=== gdal/apps ===
 
-=== gdal/apps === 
-
-* gdal_contour.cpp: copyright held by ACT. 
+* gdal_contour.cpp: copyright held by ACT.
 * gdaltindex.cpp: copyright held by DM Solutions.
-* gdalwarp.cpp, gdalwarpsimple.cpp: copyright held by i-cubed. 
-* gdaldem.cpp: copyright held by Matthew Perry, Even Rouault, and Howard Butler  
+* gdalwarp.cpp, gdalwarpsimple.cpp: copyright held by i-cubed.
+* gdaldem.cpp: copyright held by Matthew Perry, Even Rouault, and Howard Butler
                Derived from code by Michael Shapiro, Olga Waupotitsch, Marjorie Larson, Jim Westervelt :
                U.S. Army CERL, 1993. GRASS 4.1 Reference Manual. U.S. Army Corps of Engineers,
-               Construction Engineering Research Laboratories, Champaign, Illinois, 1-425. 
+               Construction Engineering Research Laboratories, Champaign, Illinois, 1-425.
                Derived from modules of GRASS 4.1 (public domain), properly noted in the headers.
                See http://trac.osgeo.org/gdal/ticket/2975
 
-=== gdal/debian === 
+=== gdal/debian ===
 
-* copyright somewhat unclear, not actually part of software. 
+* copyright somewhat unclear, not actually part of software.
 
 === gdal/doc ===
 
 * no copyright messages in .dox files.
-* ERMapper logo used with permissions. 
-* "ru" subdirectory (Russian translations) by Andrey Kiselev. 
+* ERMapper logo used with permissions.
+* "ru" subdirectory (Russian translations) by Andrey Kiselev.
 
 === gdal/pymod ===
 
 * gdal_merge.py: copyright held by Atlantis, under LGPL. This is an acceptable license and it is just noted as an exception to the general MIT/X rule for GDAL but no further action required.
 * gdal2xyz.py: copyright me, under LGPL - relicensed MIT/X.
-* gdal_wrap.c: Generated with SWIG under very permissive license (noted in file). 
-* Scripts mostly by me, all ok. 
+* gdal_wrap.c: Generated with SWIG under very permissive license (noted in file).
+* Scripts mostly by me, all ok.
 
 === gdal/pymod/samples ===
 
@@ -167,22 +162,18 @@ Note: all the following are build options, not required.
 * histrep.py: corrected copyright message (Atlantis to FrankW), change license to MIT/X.
 * various contributors, all under proper and compatible copyright headers.
 
-=== gdal/vb6 ===
-
-* all written by FrankW, clean. 
-
 === gdal/ogr/ogrsf_rmts/generic ===
 
-* Some files here (and elsewhere in OGR) copyright Softmap Inc (but MIT/X). 
+* Some files here (and elsewhere in OGR) copyright Softmap Inc (but MIT/X).
 
 === gdal/ogr/ogrsf_frmts/avc ===
 
 * Some copyright Daniel Morissette, MIT/X.
-* Included copy of dbfopen.h from Shapelib.  We really ought to reference the one in ../shape. 
+* Included copy of dbfopen.h from Shapelib.  We really ought to reference the one in ../shape.
 
 === gdal/ogr/ogrsf_rmts/csv ===
 
-* drv_*.html not copyright. 
+* drv_*.html not copyright.
 
 === gdal/ogr/ogrsf_rmts/dgn ===
 
@@ -209,11 +200,11 @@ Note: all the following are build options, not required.
 
 === gdal/ogr/ogrsf_frmts/grass ===
 
-* copyright Radim Blazek, MIT/X. 
+* copyright Radim Blazek, MIT/X.
 
 === gdal/ogr/ogrsf_frmts/ili ===
 
-* ili level code copyright Pirmin Kalberer (Sourcepole), MIT/X. 
+* ili level code copyright Pirmin Kalberer (Sourcepole), MIT/X.
 * iom/ili2c.jar is ambiguous.  (#1812) (removed - ok)
 * iom source code is all LGPL (per iom/README.src.txt) but none of the source files have a copyright or license header.  Action: this file has been removed. (#1812)
 
@@ -223,14 +214,14 @@ Note: all the following are build options, not required.
 
 === gdal/ogr/ogrsf_frmts/mitab ===
 
-* Copyright Daniel Morissette, Stepane Villeneuve, Frank Warmerdam (MIT/X). 
+* Copyright Daniel Morissette, Stepane Villeneuve, Frank Warmerdam (MIT/X).
 * Some code derived from MapServer with credit in headers, no problem foreseen.
 * All clean.
 
 === gdal/ogr/ogrsf_frmts/mysql ===
 
-* FrankW, clean. 
-* Howard Butler is co-author of some modules (but copyright all FrankW). 
+* FrankW, clean.
+* Howard Butler is co-author of some modules (but copyright all FrankW).
 
 === gdal/ogr/ogrsf_frmts/ntf ===
 
@@ -275,9 +266,9 @@ Note: all the following are build options, not required.
 
 === gdal/ogr/ogrsf_frmts/shape ===
 
-* inline copy of Shapelib which is dual licensed MIT/X and LGPL. 
-* Note, Shapelib code was written while I was at PCI, but permission was given to release it as open source. 
-* Some (OGR) code is Copyright Softmap Inc, MIT/X. 
+* inline copy of Shapelib which is dual licensed MIT/X and LGPL.
+* Note, Shapelib code was written while I was at PCI, but permission was given to release it as open source.
+* Some (OGR) code is Copyright Softmap Inc, MIT/X.
 
 === gdal/ogr/ogrsf_frmts/sqlite ===
 
@@ -299,7 +290,7 @@ Note: all the following are build options, not required.
 
 * SpatialReferenceIdl.idl, GeometryIdl.idl, CoverageIdl.idl: From OGC spec package I believe.  (removed)
 * ogr_capi_test.c: no copyright message, written by Daniel Morissette. Added copyright.
-* oledbgis.h: No copyright message, mostly OGC spec constants. 
+* oledbgis.h: No copyright message, mostly OGC spec constants.
 * swq.h, swq.c: Has alternate form of MIT/X license.  On review this license is functionally equivalent to the general GDAL license.
 * Copyright holders include Frank Warmerdam, Daniel Morissette, Softmap Inc., Stephane Villeneuve., Andrey Kiselev, Information Interoperability Institute
 
@@ -320,11 +311,11 @@ Note: all the following are build options, not required.
 * atl_net/ICRRowsetImpl.h,IFRowsetImpl.h,CCRRowsetImpl.h,SFAccessorImpl.h: Modified form of code from ATLDB.H, properly credited in the header. Copyright claim is dubious.  (#1817)
 * atl_net/IColumnsRowsetImpl.h: Derived from code for article by Len Holgate, JetByte Limited.  It is not clear if the code is properly licensed, though it is attributed.  (#1817)
 * Similar issues to above in atl_vc6 directory.
-* Code Copyright Softmap, FrankW, 
-* Some files lack headers (mostly MS Visual Studio generated files). 
+* Code Copyright Softmap, FrankW,
+* Some files lack headers (mostly MS Visual Studio generated files).
 * Whole tree moved to /spike/sfcom_oledb to avoid problems by act of the PSC.
 
-=== gdal/ogr/sfcom_serv === 
+=== gdal/ogr/sfcom_serv ===
 
 * Obsolete code, all deleted from CVS.
 
@@ -334,7 +325,7 @@ Note: all the following are build options, not required.
 
 === gdal/frmts/aigrid ===
 
-* aigccitt.c: Derived from libtiff - MIT/X. 
+* aigccitt.c: Derived from libtiff - MIT/X.
 * FrankW, clean.
 
 === gdal/frmts/airsar ===
@@ -347,16 +338,16 @@ Note: all the following are build options, not required.
 
 === gdal/frmts/bsb ===
 
-* FrankW, Mike Higgins, clean. 
+* FrankW, Mike Higgins, clean.
 
-NOTE: This code is implemented on the basis of work by Mike Higgins.  The 
-BSB format is subject to US patent 5,727,090; however, that patent 
-apparently only covers *writing* BSB files, not reading them, so this code 
-should not be affected.  
+NOTE: This code is implemented on the basis of work by Mike Higgins.  The
+BSB format is subject to US patent 5,727,090; however, that patent
+apparently only covers *writing* BSB files, not reading them, so this code
+should not be affected.
 
 See [http://home.gdal.org/projects/bsb/ipi.html]
 
-=== gdal/frmts/ceos === 
+=== gdal/frmts/ceos ===
 
 * FrankW, clean.
 
@@ -368,11 +359,11 @@ See [http://home.gdal.org/projects/bsb/ipi.html]
 
 * OPeNDAP Inc/FrankW, clean.
 
-=== gdal/frmts/dted === 
+=== gdal/frmts/dted ===
 
 * FrankW, clean.
 
-=== gdal/frmts/ecw === 
+=== gdal/frmts/ecw ===
 
 * FrankW, clean.
 
@@ -404,30 +395,30 @@ See [http://home.gdal.org/projects/bsb/ipi.html]
 
 === gdal/frmts/gtiff ===
 
-* tif_float.c: Industrial Light and Magic - MIT/X style, but with a credit requirement. Added license notice in gdal/LICENSE.TXT, setup ticket #1819 to streamline it's use. 
-* tif_memio.c: FrankW, Mike Johnson and MancTec AB - MIT/X. 
-* Contains copy of libtiff, license terms explicit in source files. 
-* Contains copy of libgeotiff, license terms not made clear.  A review of libgeotiff's LICENSE file makes it clear code is public domain unless otherwise noted (which would be FrankW's MIT/X code) 
+* tif_float.c: Industrial Light and Magic - MIT/X style, but with a credit requirement. Added license notice in gdal/LICENSE.TXT, setup ticket #1819 to streamline it's use.
+* tif_memio.c: FrankW, Mike Johnson and MancTec AB - MIT/X.
+* Contains copy of libtiff, license terms explicit in source files.
+* Contains copy of libgeotiff, license terms not made clear.  A review of libgeotiff's LICENSE file makes it clear code is public domain unless otherwise noted (which would be FrankW's MIT/X code)
 
 === gdal/frmts/gxf ===
 
 * README states:
   Gilles Clement of Global Geomatics approved this support library
   for general OpenSource release six months after it was released
-  as part of OGDI.  This should be approximately September of 1999. 
+  as part of OGDI.  This should be approximately September of 1999.
 
-* Frank, clean. 
+* Frank, clean.
 
 === gdal/frmts/hdf4 ===
 
 * AndreyK, clean.
-* embedded copy of HDF-EOS library with these apparent terms:  
+* embedded copy of HDF-EOS library with these apparent terms:
 
  Copyright (C) 1996 Hughes and Applied Research Corporation
 
- Permission to use, modify, and distribute this software and its documentation 
- for any purpose without fee is hereby granted, provided that the above 
- copyright notice appear in all copies and that both that copyright notice and 
+ Permission to use, modify, and distribute this software and its documentation
+ for any purpose without fee is hereby granted, provided that the above
+ copyright notice appear in all copies and that both that copyright notice and
  this permission notice appear in supporting documentation.
 
 I have added this license to LICENSE.TXT to satisfy the credit requirement.
@@ -441,13 +432,13 @@ I have added this license to LICENSE.TXT to satisfy the credit requirement.
 === gdal/frmts/hdf ===
 
 * geoextra.c: Derived by public domain contribution to libgeotiff from PCI but the terms are not clear.  This is a libgeotiff issue.  There is no problem with the license - it just isn't well documented in the code file.
-* Mostly copyright Intergraph Corporation, clean. 
+* Mostly copyright Intergraph Corporation, clean.
 * hfacompress.cpp: Sam Gillingham, clean.
 
 === gdal/frmts/idrisi ===
 
 * Ivan Lucena (Clark University), clean.
-* READMEs for rdc and rst format don't have any copyright details. 
+* READMEs for rdc and rst format don't have any copyright details.
 
 === gdal/frmts/ilwis ===
 
@@ -523,7 +514,7 @@ I have added this license to LICENSE.TXT to satisfy the credit requirement.
 
 * Kor de Jong holds copyright.
 * Some missing headers (pcrasterdataset.h, pcrastermisc.cpp, pcrasterrasterband.cpp, pcrasterutil.cpp, pcrasterutil.h (#1822).
-* libcsf: license and copyright implicit in AUTHORS and COPYING documents. 
+* libcsf: license and copyright implicit in AUTHORS and COPYING documents.
 * libcsf COPYING indicates an MIT-like agreement but with more explicit requirements for notice in binaries.  Added to gdal/LICENSE.TXT
 
  Copyright (c) 1997-2003, Utrecht University
@@ -564,7 +555,7 @@ I have added this license to LICENSE.TXT to satisfy the credit requirement.
 === gdal/frmts/png ===
 
 * FrankW, clean.
-* includes copy of libpng. 
+* includes copy of libpng.
 * libpng has a roughly MIT-like license but with explicit indication that notice is only required in source distributions.   http://www.gdal.org/srctree/frmts/png/libpng/LICENSE
 
 === gdal/frmts/raw ===
@@ -590,7 +581,7 @@ I have added this license to LICENSE.TXT to satisfy the credit requirement.
 === gdal/frmts/sgi ===
 
 * FrankW, clean.
-* Original SGI code used with permission of Paul Bourke. 
+* Original SGI code used with permission of Paul Bourke.
 
 === gdal/frmts/usgsdem ===
 
@@ -607,18 +598,18 @@ I have added this license to LICENSE.TXT to satisfy the credit requirement.
 === gdal/frmts/zlib ===
 
 * Using external zlib library
-* README includes the license (same as libpng). 
+* README includes the license (same as libpng).
 
 === gdal ===
 
-* aclocal.m4 and configure.in have copyright/license headers. 
+* aclocal.m4 and configure.in have copyright/license headers.
 * Various readme's, Doxyfile, Makefiles, scripts without any licensing info.
 
 === gdal/swig/include ===
 * Kevin Ruland, HowardB, FrankW, TamasS, clean.
 
 === gdal/swig/include/csharp ===
-* Mostly written by TamasS, lacking copyright headers.  Emailing Tamas. 
+* Mostly written by TamasS, lacking copyright headers.  Emailing Tamas.
 
 === gdal/swig/include/java ===
 * Mostly written by BenC, AndreaA, lacking copyright headers.
diff --git a/VERSION b/VERSION
index ac2cdeb..ccbccc3 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.3
+2.2.0
diff --git a/Vagrantfile b/Vagrantfile
index 54abdd4..bdd3622 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -7,26 +7,56 @@ require 'socket'
 VAGRANTFILE_API_VERSION = "2"
 
 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
-
-  vm_ram = ENV['VAGRANT_VM_RAM'] || 1024
+  # specify memory size in MiB
+  vm_ram = ENV['VAGRANT_VM_RAM'] || 2048
   vm_cpu = ENV['VAGRANT_VM_CPU'] || 2
-
-  config.vm.box = "precise64"
+  vm_ram_bytes = vm_ram * 1024 * 1024
 
   config.vm.hostname = "gdal-vagrant"
-  config.vm.box_url = "http://files.vagrantup.com/precise64.box"
   config.vm.host_name = "gdal-vagrant"
 
-  config.vm.network :forwarded_port, guest: 80, host: 8080
+  # proxy configurations.
+  # these options are also specified by environment variables;
+  #   VAGRANT_HTTP_PROXY, VAGRANT_HTTPS_PROXY, VAGRANT_FTP_PROXY
+  #   VAGRANT_NO_PROXY, VAGRANT_SVN_PROXY, VAGRANT_GIT_PROXY
+  # if you want to set these on Vagrantfile, edit followings.
+  if Vagrant.has_plugin?("vagrant-proxyconf")
+    config.proxy.enabled   = false  # true|false
+    #config.proxy.http      = "http://192.168.0.2:3128"
+    #config.proxy.ftp       = "http://192.168.0.2:3128"
+    #config.proxy.https     = "DIRECT"
+    #config.proxy.no_proxy  = "localhost,127.0.0.1,.example.com"
+    #config.svn_proxy.http  = ""
+    #config.git_proxy.http  = ""
+  end
 
   config.vm.synced_folder "../autotest/", "/home/vagrant/autotest/"
 
-  config.vm.provider :virtualbox do |vb|
+  config.vm.provider :virtualbox do |vb,ovrd|
+     ovrd.vm.network :forwarded_port, guest: 80, host: 8080
+     ovrd.vm.box = "precise64"
+     ovrd.vm.box_url = "http://files.vagrantup.com/precise64.box"
      vb.customize ["modifyvm", :id, "--memory", vm_ram]
      vb.customize ["modifyvm", :id, "--cpus", vm_cpu]
      vb.customize ["modifyvm", :id, "--ioapic", "on"]
      vb.name = "gdal-vagrant"
-   end
+  end
+
+  config.vm.provider :lxc do |lxc,ovrd|
+    ovrd.vm.box = "fgrehm/precise64-lxc"
+    lxc.backingstore = 'dir'
+    lxc.customize 'cgroup.memory.limit_in_bytes', vm_ram_bytes
+    lxc.customize 'aa_allow_incomplete', 1
+    lxc.container_name = "gdal-vagrant"
+  end
+ 
+  config.vm.provider :hyperv do |hyperv,ovrd|
+    ovrd.vm.box = "hashicorp/precise64"
+    ovrd.ssh.username = "vagrant"
+    hyperv.cpus = vm_cpu
+    hyperv.memory = vm_ram
+    hyperv.vmname = "gdal-vagrant"
+  end
 
   ppaRepos = [
     "ppa:ubuntugis/ubuntugis-unstable", "ppa:marlam/gta"
@@ -58,6 +88,9 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
     "libpoppler-dev",
     "libspatialite-dev",
     "gpsbabel",
+    "libboost-all-dev",
+    "libgmp-dev",
+    "libmpfr-dev",
     "swig",
     "libhdf4-alt-dev",
     "libhdf5-serial-dev",
@@ -85,11 +118,8 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
     "mono-mcs"
   ];
 
-  unless File.exists?(".no_apt_cache")
-    cache_dir = "apt-cache/#{config.vm.box}"
-    FileUtils.mkdir_p(cache_dir) unless Dir.exists?(cache_dir)
-    puts "Using local apt cache, #{cache_dir}"
-    config.vm.synced_folder cache_dir, "/var/cache/apt/archives"
+  if Vagrant.has_plugin?("vagrant-cachier")
+    config.cache.scope = :box
   end
 
   if Dir.glob("#{File.dirname(__FILE__)}/.vagrant/machines/default/*/id").empty?
@@ -106,6 +136,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
 	  pkg_cmd << "apt-get install -q -y " + packageList.join(" ") << " ; "
 	  config.vm.provision :shell, :inline => pkg_cmd
     scripts = [
+      "sfcgal.sh",
       "swig-1.3.40.sh",
       "libkml.sh",
       "openjpeg.sh",
diff --git a/aclocal.m4 b/aclocal.m4
index d9e879d..43db101 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.15 -*- Autoconf -*-
 
-# Copyright (C) 1996-2013 Free Software Foundation, Inc.
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -15,6 +15,8 @@ m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun
 m4_include([m4/acinclude.m4])
 m4_include([m4/ax_cflags_warn_all.m4])
 m4_include([m4/ax_check_compile_flag.m4])
+m4_include([m4/ax_cxx_compile_stdcxx.m4])
+m4_include([m4/ax_cxx_compile_stdcxx_11.m4])
 m4_include([m4/ax_lib_expat.m4])
 m4_include([m4/ax_lib_libkml.m4])
 m4_include([m4/ax_lib_sqlite3.m4])
@@ -31,3 +33,4 @@ m4_include([m4/ltsugar.m4])
 m4_include([m4/ltversion.m4])
 m4_include([m4/lt~obsolete.m4])
 m4_include([m4/pkg.m4])
+m4_include([m4/sfcgal.m4])
diff --git a/alg/GNUmakefile b/alg/GNUmakefile
index 3121032..b0b15da 100644
--- a/alg/GNUmakefile
+++ b/alg/GNUmakefile
@@ -10,32 +10,28 @@ OBJ	=	gdalmediancut.o gdaldither.o gdal_crs.o gdaltransformer.o \
 		gdalsievefilter.o gdalwarpkernel_opencl.o polygonize.o \
 		contour.o gdaltransformgeolocs.o \
 		gdal_octave.o gdal_simplesurf.o gdalmatching.o delaunay.o \
-		gdalpansharpen.o
-
-ifeq ($(HAVE_AVX_AT_COMPILE_TIME),yes)
-CPPFLAGS 	:=	-DHAVE_AVX_AT_COMPILE_TIME $(CPPFLAGS)
-endif
-
-ifeq ($(HAVE_SSE_AT_COMPILE_TIME),yes)
-CPPFLAGS 	:=	-DHAVE_SSE_AT_COMPILE_TIME $(CPPFLAGS)
-endif
+		gdalpansharpen.o gdalapplyverticalshiftgrid.o
 
 ifeq ($(HAVE_GEOS),yes)
 CPPFLAGS 	:=	-DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
 endif
 
+ifeq ($(HAVE_SFCGAL),yes)
+CPPFLAGS 	:=	-DHAVE_SFCGAL=1 $(SFCGAL_CFLAGS) $(CPPFLAGS)
+endif
+
 ifeq ($(HAVE_ARMADILLO),yes)
 CPPFLAGS 	:=	-DHAVE_ARMADILLO $(CPPFLAGS)
 endif
 
 ifeq ($(QHULL_SETTING),external)
-CPPFLAGS 	:=	-DEXTERNAL_QHULL $(CPPFLAGS)
+CPPFLAGS 	:=	-DEXTERNAL_QHULL -DQHULL_INCLUDE_SUBDIR_IS_LIBQHULL=$(QHULL_INCLUDE_SUBDIR_IS_LIBQHULL) $(CPPFLAGS)
 endif
 ifeq ($(QHULL_SETTING),internal)
-CPPFLAGS 	:=	-DINTERNAL_QHULL -Ilibqhull $(CPPFLAGS)
+CPPFLAGS 	:=	-DINTERNAL_QHULL $(CPPFLAGS)
 endif
 
-CPPFLAGS	:=	$(CPPFLAGS) $(OPENCL_FLAGS)
+CPPFLAGS	:=	-I../frmts/vrt $(CPPFLAGS) $(OPENCL_FLAGS) $(PROJ_FLAGS) $(PROJ_INCLUDE)
 
 default:	$(OBJ:.o=.$(OBJ_EXT)) gdalgridavx.$(OBJ_EXT) gdalgridsse.$(OBJ_EXT)
 
@@ -50,7 +46,7 @@ gdalgridsse.$(OBJ_EXT):   gdalgridsse.cpp
 clean:
 	$(RM) *.o $(O_OBJ)
 
-docs:	
+docs:
 	(cd ..; $(MAKE) docs)
 
 install:
diff --git a/alg/contour.cpp b/alg/contour.cpp
index be777d3..8d85153 100644
--- a/alg/contour.cpp
+++ b/alg/contour.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: contour.cpp 34472 2016-06-30 10:51:45Z rouault $
  *
  * Project:  Contour Generation
  * Purpose:  Core algorithm implementation for contour line generation.
@@ -29,21 +28,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
+#include "cpl_port.h"
 #include "gdal_alg.h"
+
+#include <cmath>
+#include <cstring>
+
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
 
-CPL_CVSID("$Id: contour.cpp 34472 2016-06-30 10:51:45Z rouault $");
+CPL_CVSID("$Id: contour.cpp 36689 2016-12-04 22:33:33Z goatbar $");
 
 // The amount of a contour interval that pixels should be fudged by if they
 // match a contour level exactly.
 
-#define FUDGE_EXACT 0.001
+static const double FUDGE_EXACT = 0.001;
 
 // The amount of a pixel that line ends need to be within to be considered to
 // match for joining purposes.
 
-#define JOIN_DIST 0.0001
+static const double JOIN_DIST = 0.0001;
 
 /************************************************************************/
 /*                           GDALContourItem                            */
@@ -51,28 +63,28 @@ CPL_CVSID("$Id: contour.cpp 34472 2016-06-30 10:51:45Z rouault $");
 class GDALContourItem
 {
 public:
-    int    bRecentlyAccessed;
+    bool bRecentlyAccessed;
     double dfLevel;
 
-    int  nPoints;
-    int  nMaxPoints;
+    int nPoints;
+    int nMaxPoints;
     double *padfX;
     double *padfY;
 
-    int bLeftIsHigh;
+    bool bLeftIsHigh;
 
     double dfTailX;
 
-    GDALContourItem( double dfLevel );
+    explicit GDALContourItem( double dfLevel );
     ~GDALContourItem();
 
     int    AddSegment( double dfXStart, double dfYStart,
                        double dfXEnd, double dfYEnd, int bLeftHigh );
     void   MakeRoomFor( int );
     int    Merge( GDALContourItem * );
-    double DistanceSqr(double x0, double y0, double x1, double y1);
-    int    MergeCase( double ax0, double ay0, double ax1, double ay1,
-                      double bx0, double by0, double bx1, double by1);
+    static double DistanceSqr( double x0, double y0, double x1, double y1 );
+    static int MergeCase( double ax0, double ay0, double ax1, double ay1,
+                          double bx0, double by0, double bx1, double by1);
     void   PrepareEjection();
 };
 
@@ -88,11 +100,11 @@ class GDALContourLevel
     GDALContourItem **papoEntries;
 
 public:
-    GDALContourLevel( double );
+    explicit GDALContourLevel( double );
     ~GDALContourLevel();
 
-    double GetLevel() { return dfLevel; }
-    int    GetContourCount() { return nEntryCount; }
+    double GetLevel() const { return dfLevel; }
+    int    GetContourCount() const { return nEntryCount; }
     GDALContourItem *GetContour( int i) { return papoEntries[i]; }
     void   AdjustContour( int );
     void   RemoveContour( int );
@@ -116,19 +128,19 @@ class GDALContourGenerator
     int    nLevelCount;
     GDALContourLevel **papoLevels;
 
-    int     bNoDataActive;
-    double  dfNoDataValue;
-
-    int     bFixedLevels;
-    double  dfContourInterval;
-    double  dfContourOffset;
+    bool   bNoDataActive;
+    double dfNoDataValue;
 
+    bool   bFixedLevels;
+    double dfContourInterval;
+    double dfContourOffset;
 
     CPLErr AddSegment( double dfLevel,
                        double dfXStart, double dfYStart,
                        double dfXEnd, double dfYEnd, int bLeftHigh );
 
-    template<EMULATED_BOOL bNoDataIsNan> inline bool IsNoData(double dfVal) const;
+    template<EMULATED_BOOL bNoDataIsNan> inline bool
+        IsNoData( double dfVal ) const;
 
     template<EMULATED_BOOL bNoDataIsNan> CPLErr ProcessPixel( int iPixel );
     CPLErr ProcessRect( double, double, double,
@@ -136,9 +148,9 @@ class GDALContourGenerator
                         double, double, double,
                         double, double, double );
 
-    void   Intersect( double, double, double,
-                      double, double, double,
-                      double, double, int *, double *, double * );
+    static void Intersect( double, double, double,
+                           double, double, double,
+                           double, double, int *, double *, double * );
 
     GDALContourLevel *FindLevel( double dfLevel );
 
@@ -161,7 +173,6 @@ public:
     void                SetFixedLevels( int, double * );
     CPLErr              FeedLine( double *padfScanline );
     CPLErr              EjectContours( int bOnlyUnused = FALSE );
-
 };
 
 template<> inline bool GDALContourGenerator::IsNoData<true>(double dfVal) const
@@ -174,11 +185,11 @@ template<> inline bool GDALContourGenerator::IsNoData<false>(double dfVal) const
     return dfVal == dfNoDataValue;
 }
 
-
 /************************************************************************/
 /*                           GDAL_CG_Create()                           */
 /************************************************************************/
 
+/** Create contour generator */
 GDALContourGeneratorH
 GDAL_CG_Create( int nWidth, int nHeight, int bNoDataSet, double dfNoDataValue,
                 double dfContourInterval, double dfContourBase,
@@ -203,22 +214,24 @@ GDAL_CG_Create( int nWidth, int nHeight, int bNoDataSet, double dfNoDataValue,
 /*                          GDAL_CG_FeedLine()                          */
 /************************************************************************/
 
+/** Feed a line to the contour generator */
 CPLErr GDAL_CG_FeedLine( GDALContourGeneratorH hCG, double *padfScanline )
 
 {
     VALIDATE_POINTER1( hCG, "GDAL_CG_FeedLine", CE_Failure );
 
-    return ((GDALContourGenerator *) hCG)->FeedLine( padfScanline );
+    return static_cast<GDALContourGenerator *>(hCG)->FeedLine(padfScanline);
 }
 
 /************************************************************************/
 /*                          GDAL_CG_Destroy()                           */
 /************************************************************************/
 
+/** Destroy contour generator */
 void GDAL_CG_Destroy( GDALContourGeneratorH hCG )
 
 {
-    delete ((GDALContourGenerator *) hCG);
+    delete static_cast<GDALContourGenerator *>(hCG);
 }
 
 /************************************************************************/
@@ -233,29 +246,23 @@ void GDAL_CG_Destroy( GDALContourGeneratorH hCG )
 
 GDALContourGenerator::GDALContourGenerator( int nWidthIn, int nHeightIn,
                                             GDALContourWriter pfnWriterIn,
-                                            void *pWriterCBDataIn )
-{
-    nWidth = nWidthIn;
-    nHeight = nHeightIn;
-
-    padfLastLine = NULL;
-    padfThisLine = NULL;
-
-    pfnWriter = pfnWriterIn;
-    pWriterCBData = pWriterCBDataIn;
-
-    iLine = -1;
-
-    bNoDataActive = FALSE;
-    dfNoDataValue = -1000000.0;
-    dfContourInterval = 10.0;
-    dfContourOffset = 0.0;
-
-    nLevelMax = 0;
-    nLevelCount = 0;
-    papoLevels = NULL;
-    bFixedLevels = FALSE;
-}
+                                            void *pWriterCBDataIn ) :
+    nWidth(nWidthIn),
+    nHeight(nHeightIn),
+    iLine(-1),
+    padfLastLine(NULL),
+    padfThisLine(NULL),
+    nLevelMax(0),
+    nLevelCount(0),
+    papoLevels(NULL),
+    bNoDataActive(false),
+    dfNoDataValue(-1000000.0),
+    bFixedLevels(false),
+    dfContourInterval(10.0),
+    dfContourOffset(0.0),
+    pfnWriter(pfnWriterIn),
+    pWriterCBData(pWriterCBDataIn)
+{}
 
 /************************************************************************/
 /*                       ~GDALContourGenerator()                        */
@@ -264,9 +271,7 @@ GDALContourGenerator::GDALContourGenerator( int nWidthIn, int nHeightIn,
 GDALContourGenerator::~GDALContourGenerator()
 
 {
-    int i;
-
-    for( i = 0; i < nLevelCount; i++ )
+    for( int i = 0; i < nLevelCount; i++ )
         delete papoLevels[i];
     CPLFree( papoLevels );
 
@@ -280,8 +285,10 @@ GDALContourGenerator::~GDALContourGenerator()
 
 bool GDALContourGenerator::Init()
 {
-    padfLastLine = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nWidth);
-    padfThisLine = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nWidth);
+    padfLastLine =
+        static_cast<double *>(VSI_CALLOC_VERBOSE(sizeof(double), nWidth));
+    padfThisLine =
+        static_cast<double *>(VSI_CALLOC_VERBOSE(sizeof(double), nWidth));
     return padfLastLine != NULL && padfThisLine != NULL;
 }
 
@@ -293,7 +300,7 @@ void GDALContourGenerator::SetFixedLevels( int nFixedLevelCount,
                                            double *padfFixedLevels )
 
 {
-    bFixedLevels = TRUE;
+    bFixedLevels = true;
     for( int i = 0; i < nFixedLevelCount; i++ )
         FindLevel( padfFixedLevels[i] );
 }
@@ -305,7 +312,7 @@ void GDALContourGenerator::SetFixedLevels( int nFixedLevelCount,
 void GDALContourGenerator::SetNoData( double dfNewValue )
 
 {
-    bNoDataActive = TRUE;
+    bNoDataActive = true;
     dfNoDataValue = dfNewValue;
 }
 
@@ -313,33 +320,33 @@ void GDALContourGenerator::SetNoData( double dfNewValue )
 /*                            ProcessPixel()                            */
 /************************************************************************/
 
-template<EMULATED_BOOL bNoDataIsNan> CPLErr GDALContourGenerator::ProcessPixel( int iPixel )
+template<EMULATED_BOOL bNoDataIsNan> CPLErr
+GDALContourGenerator::ProcessPixel( int iPixel )
 
 {
-    double  dfUpLeft, dfUpRight, dfLoLeft, dfLoRight;
-    int     bSubdivide = FALSE;
+    bool bSubdivide = false;
 
 /* -------------------------------------------------------------------- */
 /*      Collect the four corner pixel values.  Value left or right      */
 /*      of the scanline are taken from the nearest pixel on the         */
 /*      scanline itself.                                                */
 /* -------------------------------------------------------------------- */
-    dfUpLeft = padfLastLine[MAX(0,iPixel-1)];
-    dfUpRight = padfLastLine[MIN(nWidth-1,iPixel)];
+    const double dfUpLeft = padfLastLine[std::max(0, iPixel-1)];
+    const double dfUpRight = padfLastLine[std::min(nWidth - 1, iPixel)];
 
-    dfLoLeft = padfThisLine[MAX(0,iPixel-1)];
-    dfLoRight = padfThisLine[MIN(nWidth-1,iPixel)];
+    const double dfLoLeft = padfThisLine[std::max(0, iPixel - 1)];
+    const double dfLoRight = padfThisLine[std::min(nWidth - 1, iPixel)];
 
 /* -------------------------------------------------------------------- */
 /*      Check if we have any nodata values.                             */
 /* -------------------------------------------------------------------- */
     if( bNoDataActive
-        && ( IsNoData<bNoDataIsNan>(dfUpLeft)
-            || IsNoData<bNoDataIsNan>(dfLoLeft)
-            || IsNoData<bNoDataIsNan>(dfLoRight)
-            || IsNoData<bNoDataIsNan>(dfUpRight) ) )
+        && (IsNoData<bNoDataIsNan>(dfUpLeft) ||
+            IsNoData<bNoDataIsNan>(dfLoLeft) ||
+            IsNoData<bNoDataIsNan>(dfLoRight) ||
+            IsNoData<bNoDataIsNan>(dfUpRight)) )
     {
-        bSubdivide = TRUE;
+        bSubdivide = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -360,7 +367,6 @@ template<EMULATED_BOOL bNoDataIsNan> CPLErr GDALContourGenerator::ProcessPixel(
 /* -------------------------------------------------------------------- */
     int nGoodCount = 0;
     double dfASum = 0.0;
-    double dfTop=0.0, dfRight=0.0, dfLeft=0.0, dfBottom=0.0;
 
     if( !IsNoData<bNoDataIsNan>(dfUpLeft) )
     {
@@ -389,7 +395,9 @@ template<EMULATED_BOOL bNoDataIsNan> CPLErr GDALContourGenerator::ProcessPixel(
     if( nGoodCount == 0 )
         return CE_None;
 
-    double dfCenter = dfASum / nGoodCount;
+    const double dfCenter = dfASum / nGoodCount;
+    double dfTop = 0.0;
+    double dfLeft = 0.0;
 
     if( !IsNoData<bNoDataIsNan>(dfUpLeft) )
     {
@@ -409,6 +417,9 @@ template<EMULATED_BOOL bNoDataIsNan> CPLErr GDALContourGenerator::ProcessPixel(
         dfLeft = dfLoLeft;
     }
 
+    double dfRight = 0.0;
+    double dfBottom = 0.0;
+
     if( !IsNoData<bNoDataIsNan>(dfLoRight) )
     {
         if( !IsNoData<bNoDataIsNan>(dfUpRight) )
@@ -423,7 +434,7 @@ template<EMULATED_BOOL bNoDataIsNan> CPLErr GDALContourGenerator::ProcessPixel(
     }
     else
     {
-        dfBottom = dfLoLeft;;
+        dfBottom = dfLoLeft;
         dfRight = dfUpRight;
     }
 
@@ -449,7 +460,8 @@ template<EMULATED_BOOL bNoDataIsNan> CPLErr GDALContourGenerator::ProcessPixel(
                             dfCenter, iPixel, iLine );
     }
 
-    if( !IsNoData<bNoDataIsNan>(dfLoRight) && iPixel < nWidth && iLine < nHeight )
+    if( !IsNoData<bNoDataIsNan>(dfLoRight) &&
+        iPixel < nWidth && iLine < nHeight )
     {
         eErr = ProcessRect( dfCenter, iPixel, iLine,
                             dfBottom, iPixel, iLine + 0.5,
@@ -482,30 +494,30 @@ CPLErr GDALContourGenerator::ProcessRect(
 /* -------------------------------------------------------------------- */
 /*      Identify the range of elevations over this rect.                */
 /* -------------------------------------------------------------------- */
-    int iStartLevel, iEndLevel;
-
-    double dfMin = MIN(MIN(dfUpLeft,dfUpRight),MIN(dfLoLeft,dfLoRight));
-    double dfMax = MAX(MAX(dfUpLeft,dfUpRight),MAX(dfLoLeft,dfLoRight));
+    int iStartLevel = 0;
+    int iEndLevel = 0;
 
+    const double dfMin =
+        std::min(std::min(dfUpLeft, dfUpRight), std::min(dfLoLeft, dfLoRight));
+    const double dfMax =
+        std::max(std::max(dfUpLeft, dfUpRight), std::max(dfLoLeft, dfLoRight));
 
 /* -------------------------------------------------------------------- */
 /*      Compute the set of levels to compute contours for.              */
 /* -------------------------------------------------------------------- */
 
-    /*
-    ** If we are using fixed levels, then find the min/max in the levels
-    ** table.
-    */
+    // If we are using fixed levels, then find the min/max in the levels table.
     if( bFixedLevels )
     {
-        int nStart=0, nEnd=nLevelCount-1, nMiddle;
+        int nStart = 0;
+        int nEnd = nLevelCount-1;
 
         iStartLevel = -1;
         while( nStart <= nEnd )
         {
-            nMiddle = (nEnd + nStart) / 2;
+            const int nMiddle = (nEnd + nStart) / 2;
 
-            double dfMiddleLevel = papoLevels[nMiddle]->GetLevel();
+            const double dfMiddleLevel = papoLevels[nMiddle]->GetLevel();
 
             if( dfMiddleLevel < dfMin )
                 nStart = nMiddle + 1;
@@ -532,16 +544,13 @@ CPLErr GDALContourGenerator::ProcessRect(
         CPLAssert( iStartLevel >= 0 && iStartLevel < nLevelCount );
         CPLAssert( iEndLevel >= 0 && iEndLevel < nLevelCount );
     }
-
-    /*
-    ** Otherwise figure out the start and end using the base and offset.
-    */
+    // Otherwise figure out the start and end using the base and offset.
     else
     {
-        iStartLevel = (int)
-            ceil((dfMin - dfContourOffset) / dfContourInterval);
-        iEndLevel = (int)
-            floor((dfMax - dfContourOffset) / dfContourInterval);
+        iStartLevel = static_cast<int>(
+            ceil((dfMin - dfContourOffset) / dfContourInterval));
+        iEndLevel = static_cast<int>(
+            floor((dfMax - dfContourOffset) / dfContourInterval));
     }
 
     if( iStartLevel > iEndLevel )
@@ -550,39 +559,31 @@ CPLErr GDALContourGenerator::ProcessRect(
 /* -------------------------------------------------------------------- */
 /*      Loop over them.                                                 */
 /* -------------------------------------------------------------------- */
-    int iLevel;
-
-    for( iLevel = iStartLevel; iLevel <= iEndLevel; iLevel++ )
+    for( int iLevel = iStartLevel; iLevel <= iEndLevel; iLevel++ )
     {
-        double dfLevel;
-
-        if( bFixedLevels )
-            dfLevel = papoLevels[iLevel]->GetLevel();
-        else
-            dfLevel = iLevel * dfContourInterval + dfContourOffset;
-
-        int  nPoints = 0;
-        double adfX[4], adfY[4];
-        CPLErr eErr = CE_None;
-
-        /* Logs how many points we have af left + bottom,
-        ** and left + bottom + right.
-        */
-        int nPoints1 = 0, nPoints2 = 0, nPoints3 = 0;
+        const double dfLevel =
+            bFixedLevels
+            ? papoLevels[iLevel]->GetLevel()
+            : iLevel * dfContourInterval + dfContourOffset;
 
+        int nPoints = 0;
+        double adfX[4] = {};
+        double adfY[4] = {};
 
+        // Logs how many points we have af left + bottom,
+        // and left + bottom + right.
         Intersect( dfUpLeft, dfUpLeftX, dfUpLeftY,
                    dfLoLeft, dfLoLeftX, dfLoLeftY,
                    dfLoRight, dfLevel, &nPoints, adfX, adfY );
-        nPoints1 = nPoints;
+        const int nPoints1 = nPoints;
         Intersect( dfLoLeft, dfLoLeftX, dfLoLeftY,
                    dfLoRight, dfLoRightX, dfLoRightY,
                    dfUpRight, dfLevel, &nPoints, adfX, adfY );
-        nPoints2 = nPoints;
+        const int nPoints2 = nPoints;
         Intersect( dfLoRight, dfLoRightX, dfLoRightY,
                    dfUpRight, dfUpRightX, dfUpRightY,
                    dfUpLeft, dfLevel, &nPoints, adfX, adfY );
-        nPoints3 = nPoints;
+        const int nPoints3 = nPoints;
         Intersect( dfUpRight, dfUpRightX, dfUpRightY,
                    dfUpLeft, dfUpLeftX, dfUpLeftY,
                    dfLoLeft, dfLevel, &nPoints, adfX, adfY );
@@ -590,45 +591,49 @@ CPLErr GDALContourGenerator::ProcessRect(
         if( nPoints == 1 || nPoints == 3 )
             CPLDebug( "CONTOUR", "Got nPoints = %d", nPoints );
 
+        CPLErr eErr = CE_None;
+
         if( nPoints >= 2 )
         {
-            if ( nPoints1 == 1 && nPoints2 == 2) // left + bottom
+            if( nPoints1 == 1 && nPoints2 == 2 ) // left + bottom
             {
                 eErr = AddSegment( dfLevel,
                                    adfX[0], adfY[0], adfX[1], adfY[1],
                                    dfUpRight > dfLoLeft );
             }
-            else if ( nPoints1 == 1 && nPoints3 == 2 ) // left + right
+            else if( nPoints1 == 1 && nPoints3 == 2 ) // left + right
             {
                 eErr = AddSegment( dfLevel,
                                    adfX[0], adfY[0], adfX[1], adfY[1],
                                    dfUpLeft > dfLoRight );
             }
-            else if ( nPoints1 == 1 && nPoints == 2 ) // left + top
-            { // Do not do vertical contours on the left, due to symmetry
-              if ( !(dfUpLeft == dfLevel && dfLoLeft == dfLevel) )
-                eErr = AddSegment( dfLevel,
-                                   adfX[0], adfY[0], adfX[1], adfY[1],
-                                   dfUpLeft > dfLoRight );
+            else if( nPoints1 == 1 && nPoints == 2 ) // left + top
+            {
+                // Do not do vertical contours on the left, due to symmetry.
+                if( !(dfUpLeft == dfLevel && dfLoLeft == dfLevel) )
+                    eErr = AddSegment( dfLevel,
+                                       adfX[0], adfY[0], adfX[1], adfY[1],
+                                       dfUpLeft > dfLoRight );
             }
-            else if(  nPoints2 == 1 && nPoints3 == 2) // bottom + right
+            else if( nPoints2 == 1 && nPoints3 == 2 ) // bottom + right
             {
                 eErr = AddSegment( dfLevel,
                                    adfX[0], adfY[0], adfX[1], adfY[1],
                                    dfUpLeft > dfLoRight );
             }
-            else if ( nPoints2 == 1 && nPoints == 2 ) // bottom + top
+            else if( nPoints2 == 1 && nPoints == 2 ) // bottom + top
             {
                 eErr = AddSegment( dfLevel,
                                    adfX[0], adfY[0], adfX[1], adfY[1],
                                    dfLoLeft > dfUpRight );
             }
-            else if ( nPoints3 == 1 && nPoints == 2 ) // right + top
-            { // Do not do horizontal contours on upside, due to symmetry
-              if ( !(dfUpRight == dfLevel && dfUpLeft == dfLevel) )
-                eErr = AddSegment( dfLevel,
-                                   adfX[0], adfY[0], adfX[1], adfY[1],
-                                   dfLoLeft > dfUpRight );
+            else if( nPoints3 == 1 && nPoints == 2 ) // right + top
+            {
+                // Do not do horizontal contours on upside, due to symmetry.
+                if( !(dfUpRight == dfLevel && dfUpLeft == dfLevel) )
+                    eErr = AddSegment( dfLevel,
+                                       adfX[0], adfY[0], adfX[1], adfY[1],
+                                       dfLoLeft > dfUpRight );
             }
             else
             {
@@ -642,8 +647,8 @@ CPLErr GDALContourGenerator::ProcessRect(
 
         if( nPoints == 4 )
         {
-          // Do not do horizontal contours on upside, due to symmetry
-          if ( !(dfUpRight == dfLevel && dfUpLeft == dfLevel) )
+          // Do not do horizontal contours on upside, due to symmetry.
+          if( !(dfUpRight == dfLevel && dfUpLeft == dfLevel) )
           {
 /* -------------------------------------------------------------------- */
 /*          If we get here, we know the first was left+bottom,          */
@@ -677,7 +682,7 @@ void GDALContourGenerator::Intersect( double dfVal1, double dfX1, double dfY1,
 {
     if( dfVal1 < dfLevel && dfVal2 >= dfLevel )
     {
-        double dfRatio = (dfLevel - dfVal1) / (dfVal2 - dfVal1);
+        const double dfRatio = (dfLevel - dfVal1) / (dfVal2 - dfVal1);
 
         padfX[*pnPoints] = dfX1 * (1.0 - dfRatio) + dfX2 * dfRatio;
         padfY[*pnPoints] = dfY1 * (1.0 - dfRatio) + dfY2 * dfRatio;
@@ -685,7 +690,7 @@ void GDALContourGenerator::Intersect( double dfVal1, double dfX1, double dfY1,
     }
     else if( dfVal1 > dfLevel && dfVal2 <= dfLevel )
     {
-        double dfRatio = (dfLevel - dfVal2) / (dfVal1 - dfVal2);
+        const double dfRatio = (dfLevel - dfVal2) / (dfVal1 - dfVal2);
 
         padfX[*pnPoints] = dfX2 * (1.0 - dfRatio) + dfX1 * dfRatio;
         padfY[*pnPoints] = dfY2 * (1.0 - dfRatio) + dfY1 * dfRatio;
@@ -710,8 +715,7 @@ CPLErr GDALContourGenerator::AddSegment( double dfLevel,
 
 {
     GDALContourLevel *poLevel = FindLevel( dfLevel );
-    GDALContourItem *poTarget;
-    int iTarget;
+    GDALContourItem *poTarget = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Check all active contours for any that this might attach        */
@@ -719,10 +723,10 @@ CPLErr GDALContourGenerator::AddSegment( double dfLevel,
 /*      of the correct level more efficiently.                          */
 /* -------------------------------------------------------------------- */
 
-    if( dfY1 < dfY2 )
-        iTarget = poLevel->FindContour( dfX1, dfY1 );
-    else
-        iTarget = poLevel->FindContour( dfX2, dfY2 );
+    const int iTarget =
+        dfY1 < dfY2
+        ? poLevel->FindContour(dfX1, dfY1)
+        : poLevel->FindContour(dfX2, dfY2);
 
     if( iTarget != -1 )
     {
@@ -778,17 +782,17 @@ CPLErr GDALContourGenerator::FeedLine( double *padfScanline )
 /* -------------------------------------------------------------------- */
 /*      Perturb any values that occur exactly on level boundaries.      */
 /* -------------------------------------------------------------------- */
-    int iPixel;
+    int iPixel = 0;  // Used after for.
 
-    for( iPixel = 0; iPixel < nWidth; iPixel++ )
+    for( ; iPixel < nWidth; iPixel++ )
     {
         if( bNoDataActive && padfThisLine[iPixel] == dfNoDataValue )
             continue;
 
-        double dfLevel = (padfThisLine[iPixel] - dfContourOffset)
-            / dfContourInterval;
+        const double dfLevel =
+            (padfThisLine[iPixel] - dfContourOffset) / dfContourInterval;
 
-        if( dfLevel - (int) dfLevel == 0.0 )
+        if( dfLevel - static_cast<int>(dfLevel) == 0.0 )
         {
             padfThisLine[iPixel] += dfContourInterval * FUDGE_EXACT;
         }
@@ -808,24 +812,24 @@ CPLErr GDALContourGenerator::FeedLine( double *padfScanline )
 /*      Clear the recently used flags on the contours so we can         */
 /*      check later which ones were touched for this scanline.          */
 /* -------------------------------------------------------------------- */
-    int iLevel, iContour;
-
-    for( iLevel = 0; iLevel < nLevelCount; iLevel++ )
+    for( int iLevel = 0; iLevel < nLevelCount; iLevel++ )
     {
         GDALContourLevel *poLevel = papoLevels[iLevel];
 
-        for( iContour = 0; iContour < poLevel->GetContourCount(); iContour++ )
-            poLevel->GetContour( iContour )->bRecentlyAccessed = FALSE;
+        for( int iContour = 0;
+             iContour < poLevel->GetContourCount();
+             iContour++ )
+            poLevel->GetContour( iContour )->bRecentlyAccessed = false;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Process each pixel.                                             */
 /* -------------------------------------------------------------------- */
     const bool bNoDataIsNan = CPL_TO_BOOL(CPLIsNan(dfNoDataValue));
-    for( iPixel = 0; iPixel < nWidth+1; iPixel++ )
+    for( iPixel = 0; iPixel < nWidth + 1; iPixel++ )
     {
-        CPLErr eErr = bNoDataIsNan ? ProcessPixel<true>( iPixel ) :
-                                     ProcessPixel<false>( iPixel );
+        const CPLErr eErr = bNoDataIsNan ? ProcessPixel<true>( iPixel ) :
+                                           ProcessPixel<false>( iPixel );
         if( eErr != CE_None )
             return eErr;
     }
@@ -839,8 +843,8 @@ CPLErr GDALContourGenerator::FeedLine( double *padfScanline )
 
     if( iLine == nHeight && eErr == CE_None )
         return FeedLine( NULL );
-    else
-        return eErr;
+
+    return eErr;
 }
 
 /************************************************************************/
@@ -850,22 +854,19 @@ CPLErr GDALContourGenerator::FeedLine( double *padfScanline )
 CPLErr GDALContourGenerator::EjectContours( int bOnlyUnused )
 
 {
-    int iLevel;
     CPLErr eErr = CE_None;
 
 /* -------------------------------------------------------------------- */
 /*      Process all contours of all levels that match our criteria      */
 /* -------------------------------------------------------------------- */
-    for( iLevel = 0; iLevel < nLevelCount && eErr == CE_None; iLevel++ )
+    for( int iLevel = 0; iLevel < nLevelCount && eErr == CE_None; iLevel++ )
     {
         GDALContourLevel *poLevel = papoLevels[iLevel];
-        int iContour;
 
-        for( iContour = 0;
+        for( int iContour = 0;
              iContour < poLevel->GetContourCount() && eErr == CE_None;
              /* increment in loop if we don't consume it. */ )
         {
-            int  iC2;
             GDALContourItem *poTarget = poLevel->GetContour( iContour );
 
             if( bOnlyUnused && poTarget->bRecentlyAccessed )
@@ -878,7 +879,8 @@ CPLErr GDALContourGenerator::EjectContours( int bOnlyUnused )
 
             // Try to find another contour we can merge with in this level.
 
-            for( iC2 = 0; iC2 < poLevel->GetContourCount(); iC2++ )
+            int iC2 = 0;  // Used after for.
+            for( ; iC2 < poLevel->GetContourCount(); iC2++ )
             {
                 GDALContourItem *poOther = poLevel->GetContour( iC2 );
 
@@ -914,16 +916,17 @@ CPLErr GDALContourGenerator::EjectContours( int bOnlyUnused )
 GDALContourLevel *GDALContourGenerator::FindLevel( double dfLevel )
 
 {
-    int nStart=0, nEnd=nLevelCount-1, nMiddle;
+    int nStart = 0;
+    int nEnd = nLevelCount - 1;
 
 /* -------------------------------------------------------------------- */
 /*      Binary search to find the requested level.                      */
 /* -------------------------------------------------------------------- */
     while( nStart <= nEnd )
     {
-        nMiddle = (nEnd + nStart) / 2;
+        const int nMiddle = (nEnd + nStart) / 2;
 
-        double dfMiddleLevel = papoLevels[nMiddle]->GetLevel();
+        const double dfMiddleLevel = papoLevels[nMiddle]->GetLevel();
 
         if( dfMiddleLevel < dfLevel )
             nStart = nMiddle + 1;
@@ -942,8 +945,8 @@ GDALContourLevel *GDALContourGenerator::FindLevel( double dfLevel )
     if( nLevelMax == nLevelCount )
     {
         nLevelMax = nLevelMax * 2 + 10;
-        papoLevels = (GDALContourLevel **)
-            CPLRealloc( papoLevels, sizeof(void*) * nLevelMax );
+        papoLevels = static_cast<GDALContourLevel **>(
+            CPLRealloc(papoLevels, sizeof(void*) * nLevelMax));
     }
 
     if( nLevelCount - nEnd - 1 > 0 )
@@ -965,14 +968,12 @@ GDALContourLevel *GDALContourGenerator::FindLevel( double dfLevel )
 /*                          GDALContourLevel()                          */
 /************************************************************************/
 
-GDALContourLevel::GDALContourLevel( double dfLevelIn )
-
-{
-    dfLevel = dfLevelIn;
-    nEntryMax = 0;
-    nEntryCount = 0;
-    papoEntries = NULL;
-}
+GDALContourLevel::GDALContourLevel( double dfLevelIn ) :
+    dfLevel(dfLevelIn),
+    nEntryMax(0),
+    nEntryCount(0),
+    papoEntries(NULL)
+{}
 
 /************************************************************************/
 /*                         ~GDALContourLevel()                          */
@@ -1040,13 +1041,14 @@ void GDALContourLevel::RemoveContour( int iTarget )
 int GDALContourLevel::FindContour( double dfX, double dfY )
 
 {
-    int nStart = 0, nEnd = nEntryCount-1, nMiddle;
+    int nStart = 0;
+    int nEnd = nEntryCount - 1;
 
     while( nEnd >= nStart )
     {
-        nMiddle = (nEnd + nStart) / 2;
+        int nMiddle = (nEnd + nStart) / 2;
 
-        double dfMiddleX = papoEntries[nMiddle]->dfTailX;
+        const double dfMiddleX = papoEntries[nMiddle]->dfTailX;
 
         if( dfMiddleX < dfX )
             nStart = nMiddle + 1;
@@ -1061,7 +1063,9 @@ int GDALContourLevel::FindContour( double dfX, double dfY )
             while( nMiddle < nEntryCount
                    && fabs(papoEntries[nMiddle]->dfTailX-dfX) < JOIN_DIST )
             {
-                if( fabs(papoEntries[nMiddle]->padfY[papoEntries[nMiddle]->nPoints-1] - dfY) < JOIN_DIST )
+                if( fabs(papoEntries[nMiddle]->
+                         padfY[papoEntries[nMiddle]->nPoints-1] - dfY) <
+                    JOIN_DIST )
                     return nMiddle;
                 nMiddle++;
             }
@@ -1086,13 +1090,14 @@ int GDALContourLevel::InsertContour( GDALContourItem *poNewContour )
 /* -------------------------------------------------------------------- */
 /*      Find where to insert by binary search.                          */
 /* -------------------------------------------------------------------- */
-    int nStart = 0, nEnd = nEntryCount-1, nMiddle;
+    int nStart = 0;
+    int nEnd = nEntryCount - 1;
 
     while( nEnd >= nStart )
     {
-        nMiddle = (nEnd + nStart) / 2;
+        const int nMiddle = (nEnd + nStart) / 2;
 
-        double dfMiddleX = papoEntries[nMiddle]->dfTailX;
+        const double dfMiddleX = papoEntries[nMiddle]->dfTailX;
 
         if( dfMiddleX < poNewContour->dfLevel )
             nStart = nMiddle + 1;
@@ -1111,8 +1116,8 @@ int GDALContourLevel::InsertContour( GDALContourItem *poNewContour )
     if( nEntryMax == nEntryCount )
     {
         nEntryMax = nEntryMax * 2 + 10;
-        papoEntries = (GDALContourItem **)
-            CPLRealloc( papoEntries, sizeof(void*) * nEntryMax );
+        papoEntries = static_cast<GDALContourItem **>(
+            CPLRealloc(papoEntries, sizeof(void*) * nEntryMax));
     }
 
 /* -------------------------------------------------------------------- */
@@ -1127,7 +1132,6 @@ int GDALContourLevel::InsertContour( GDALContourItem *poNewContour )
     return nEnd+1;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                           GDALContourItem                            */
@@ -1138,20 +1142,16 @@ int GDALContourLevel::InsertContour( GDALContourItem *poNewContour )
 /*                          GDALContourItem()                           */
 /************************************************************************/
 
-GDALContourItem::GDALContourItem( double dfLevelIn )
-
-{
-    dfLevel = dfLevelIn;
-    bRecentlyAccessed = FALSE;
-    nPoints = 0;
-    nMaxPoints = 0;
-    padfX = NULL;
-    padfY = NULL;
-
-    bLeftIsHigh = FALSE;
-
-    dfTailX = 0.0;
-}
+GDALContourItem::GDALContourItem( double dfLevelIn ) :
+    bRecentlyAccessed(false),
+    dfLevel(dfLevelIn),
+    nPoints(0),
+    nMaxPoints(0),
+    padfX(NULL),
+    padfY(NULL),
+    bLeftIsHigh(false),
+    dfTailX(0.0)
+{}
 
 /************************************************************************/
 /*                          ~GDALContourItem()                          */
@@ -1186,12 +1186,12 @@ int GDALContourItem::AddSegment( double dfXStart, double dfYStart,
         padfY[0] = dfYStart;
         padfX[1] = dfXEnd;
         padfY[1] = dfYEnd;
-        bRecentlyAccessed = TRUE;
+        bRecentlyAccessed = true;
 
         dfTailX = padfX[1];
 
-        // Here we know that the left of this vector is the high side
-        bLeftIsHigh = bLeftHigh;
+        // Here we know that the left of this vector is the high side.
+        bLeftIsHigh = CPL_TO_BOOL(bLeftHigh);
 
         return TRUE;
     }
@@ -1206,7 +1206,7 @@ int GDALContourItem::AddSegment( double dfXStart, double dfYStart,
         padfY[nPoints] = dfYEnd;
         nPoints++;
 
-        bRecentlyAccessed = TRUE;
+        bRecentlyAccessed = true;
 
         dfTailX = dfXEnd;
 
@@ -1219,83 +1219,80 @@ int GDALContourItem::AddSegment( double dfXStart, double dfYStart,
         padfY[nPoints] = dfYStart;
         nPoints++;
 
-        bRecentlyAccessed = TRUE;
+        bRecentlyAccessed = true;
 
         dfTailX = dfXStart;
 
         return TRUE;
     }
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
 /*                               DistanceSqr()                          */
 /************************************************************************/
 
-double GDALContourItem::DistanceSqr( 
-   double x0, double y0, double x1, double y1
-)
+double GDALContourItem::DistanceSqr(
+   double x0, double y0, double x1, double y1 )
 {
 // --------------------------------------------------------------------
 // Coumpute the square of the euclidian distance between
 // (x0;y0)-(x1;y1)
 // --------------------------------------------------------------------
-   double dx = x0 - x1;
-   double dy = y0 - y1;
+   const double dx = x0 - x1;
+   const double dy = y0 - y1;
 
-   return (dx*dx + dy*dy);
+   return dx * dx + dy * dy;
 }
 
 /************************************************************************/
 /*                               MergeCase()                            */
 /************************************************************************/
 
-int GDALContourItem::MergeCase( 
+int GDALContourItem::MergeCase(
    double ax0, double ay0, double ax1, double ay1,
    double bx0, double by0, double bx1, double by1
 )
 {
-    double dd;
-
 // --------------------------------------------------------------------
-// Try to find a match case between line ends
+// Try to find a match case between line ends.
 // Calculate all possible distances and choose the closest
-// if less than JOIN_DIST
+// if less than JOIN_DIST.
 // --------------------------------------------------------------------
 
-    // avoid sqrt()
-    const double jds = JOIN_DIST * JOIN_DIST;   
+    // Avoid sqrt().
+    const double jds = JOIN_DIST * JOIN_DIST;
 
-    // case 1 e-b
+    // Case 1 e-b.
     int cs = 1;
-    double dmin = DistanceSqr (ax1, ay1, bx0, by0);
+    double dmin = DistanceSqr( ax1, ay1, bx0, by0 );
 
-    // case 2 b-e
-    dd = DistanceSqr (ax0, ay0, bx1, by1);
-    if (dd < dmin)
+    // Case 2 b-e.
+    double dd = DistanceSqr( ax0, ay0, bx1, by1 );
+    if( dd < dmin )
     {
         dmin = dd;
         cs   = 2;
     }
 
-    // case 3 e-e
-    dd = DistanceSqr (ax1, ay1, bx1, by1);
-    if (dd < dmin)
+    // Case 3 e-e.
+    dd = DistanceSqr( ax1, ay1, bx1, by1 );
+    if( dd < dmin )
     {
         dmin = dd;
         cs   = 3;
     }
 
-    // case 4 b-b
+    // Case 4 b-b.
     dd = DistanceSqr (ax0, ay0, bx0, by0);
-    if (dd < dmin)
+    if( dd < dmin )
     {
         dmin = dd;
         cs   = 4;
     }
 
-    if (dmin > jds)
+    if( dmin > jds )
         cs = 0;
 
     return cs;
@@ -1308,9 +1305,6 @@ int GDALContourItem::MergeCase(
 int GDALContourItem::Merge( GDALContourItem *poOther )
 
 {
-    int rc = FALSE;
-    int i;
-
     if( poOther->dfLevel != dfLevel )
         return FALSE;
 
@@ -1318,19 +1312,20 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
 /*      Try to matching up with one of the ends, and insert.            */
 /* -------------------------------------------------------------------- */
 
-    int mc = MergeCase (
-        padfX[0],                           padfY[0], 
+    const int mc = MergeCase(
+        padfX[0],                           padfY[0],
         padfX[nPoints-1],                   padfY[nPoints-1],
-        poOther->padfX[0],                  poOther->padfY[0], 
+        poOther->padfX[0],                  poOther->padfY[0],
         poOther->padfX[poOther->nPoints-1], poOther->padfY[poOther->nPoints-1]
     );
 
-    switch (mc)
+    bool rc = false;
+    switch( mc )
     {
         case 0:
             break;
 
-        case 1:   // case 1 e-b
+        case 1:  // Case 1 e-b.
             MakeRoomFor( nPoints + poOther->nPoints - 1 );
 
             memcpy( padfX + nPoints, poOther->padfX + 1,
@@ -1339,14 +1334,14 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
                     sizeof(double) * (poOther->nPoints-1) );
             nPoints += poOther->nPoints - 1;
 
-            bRecentlyAccessed = TRUE;
+            bRecentlyAccessed = true;
 
             dfTailX = padfX[nPoints-1];
 
-            rc = TRUE;
+            rc = true;
             break;
 
-        case 2:   // case 2 b-e
+        case 2:  // Case 2 b-e.
             MakeRoomFor( nPoints + poOther->nPoints - 1 );
 
             memmove( padfX + poOther->nPoints - 1, padfX,
@@ -1359,17 +1354,17 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
                     sizeof(double) * (poOther->nPoints-1) );
             nPoints += poOther->nPoints - 1;
 
-            bRecentlyAccessed = TRUE;
+            bRecentlyAccessed = true;
 
             dfTailX = padfX[nPoints-1];
 
-            rc = TRUE;
+            rc = true;
             break;
 
-        case 3:   // case 3 e-e
+        case 3:  // Case 3 e-e
             MakeRoomFor( nPoints + poOther->nPoints - 1 );
 
-            for( i = 0; i < poOther->nPoints-1; i++ )
+            for( int i = 0; i < poOther->nPoints-1; i++ )
             {
                 padfX[i+nPoints] = poOther->padfX[poOther->nPoints-i-2];
                 padfY[i+nPoints] = poOther->padfY[poOther->nPoints-i-2];
@@ -1377,14 +1372,14 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
 
             nPoints += poOther->nPoints - 1;
 
-            bRecentlyAccessed = TRUE;
+            bRecentlyAccessed = true;
 
             dfTailX = padfX[nPoints-1];
 
-            rc = TRUE;
+            rc = true;
             break;
 
-        case 4:   // case 3 b-b
+        case 4:  // Case 3 b-b.
             MakeRoomFor( nPoints + poOther->nPoints - 1 );
 
             memmove( padfX + poOther->nPoints - 1, padfX,
@@ -1392,7 +1387,7 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
             memmove( padfY + poOther->nPoints - 1, padfY,
                     sizeof(double) * nPoints );
 
-            for( i = 0; i < poOther->nPoints-1; i++ )
+            for( int i = 0; i < poOther->nPoints-1; i++ )
             {
                 padfX[i] = poOther->padfX[poOther->nPoints - i - 1];
                 padfY[i] = poOther->padfY[poOther->nPoints - i - 1];
@@ -1400,15 +1395,15 @@ int GDALContourItem::Merge( GDALContourItem *poOther )
 
             nPoints += poOther->nPoints - 1;
 
-            bRecentlyAccessed = TRUE;
+            bRecentlyAccessed = true;
 
             dfTailX = padfX[nPoints-1];
 
-            rc = TRUE;
+            rc = true;
             break;
 
         default:
-            CPLAssert(FALSE);
+            CPLAssert(false);
             break;
     }
 
@@ -1425,8 +1420,10 @@ void GDALContourItem::MakeRoomFor( int nNewPoints )
     if( nNewPoints > nMaxPoints )
     {
         nMaxPoints = nNewPoints * 2 + 50;
-        padfX = (double *) CPLRealloc(padfX,sizeof(double) * nMaxPoints);
-        padfY = (double *) CPLRealloc(padfY,sizeof(double) * nMaxPoints);
+        padfX = static_cast<double *>(
+            CPLRealloc(padfX, sizeof(double) * nMaxPoints));
+        padfY = static_cast<double *>(
+            CPLRealloc(padfY, sizeof(double) * nMaxPoints));
     }
 }
 
@@ -1437,29 +1434,15 @@ void GDALContourItem::MakeRoomFor( int nNewPoints )
 void GDALContourItem::PrepareEjection()
 
 {
-    /* If left side is the high side, then reverse to get curve normal
-    ** pointing downwards
-    */
+    // If left side is the high side, then reverse to get curve normal
+    // pointing downwards.
     if( bLeftIsHigh )
     {
-        int i;
-
-        // Reverse the arrays
-        for( i = 0; i < nPoints / 2; i++ )
-        {
-            double dfTemp;
-            dfTemp = padfX[i];
-            padfX[i] = padfX[ nPoints - i - 1];
-            padfX[ nPoints - i - 1] = dfTemp;
-
-            dfTemp = padfY[i];
-            padfY[i] = padfY[ nPoints - i - 1];
-            padfY[ nPoints - i - 1] = dfTemp;
-        }
+        std::reverse(padfX, padfX + nPoints);
+        std::reverse(padfY, padfY + nPoints);
     }
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                   Additional C Callable Functions                    */
@@ -1475,12 +1458,11 @@ CPLErr OGRContourWriter( double dfLevel,
                          void *pInfo )
 
 {
-    OGRContourWriterInfo *poInfo = (OGRContourWriterInfo *) pInfo;
-    OGRFeatureH hFeat;
-    OGRGeometryH hGeom;
-    int iPoint;
+    OGRContourWriterInfo *poInfo = static_cast<OGRContourWriterInfo *>(pInfo);
 
-    hFeat = OGR_F_Create( OGR_L_GetLayerDefn( (OGRLayerH) poInfo->hLayer ) );
+    OGRFeatureH hFeat =
+        OGR_F_Create(
+            OGR_L_GetLayerDefn( static_cast<OGRLayerH>(poInfo->hLayer) ));
 
     if( poInfo->nIDField != -1 )
         OGR_F_SetFieldInteger( hFeat, poInfo->nIDField, poInfo->nNextID++ );
@@ -1488,9 +1470,9 @@ CPLErr OGRContourWriter( double dfLevel,
     if( poInfo->nElevField != -1 )
         OGR_F_SetFieldDouble( hFeat, poInfo->nElevField, dfLevel );
 
-    hGeom = OGR_G_CreateGeometry( wkbLineString );
+    OGRGeometryH hGeom = OGR_G_CreateGeometry( wkbLineString );
 
-    for( iPoint = nPoints-1; iPoint >= 0; iPoint-- )
+    for( int iPoint = nPoints - 1; iPoint >= 0; iPoint-- )
     {
         OGR_G_SetPoint( hGeom, iPoint,
                         poInfo->adfGeoTransform[0]
@@ -1504,13 +1486,13 @@ CPLErr OGRContourWriter( double dfLevel,
 
     OGR_F_SetGeometryDirectly( hFeat, hGeom );
 
-    OGRErr eErr = OGR_L_CreateFeature( (OGRLayerH) poInfo->hLayer, hFeat );
+    const OGRErr eErr =
+        OGR_L_CreateFeature(static_cast<OGRLayerH>(poInfo->hLayer), hFeat);
     OGR_F_Destroy( hFeat );
 
-    return (eErr == OGRERR_NONE) ? CE_None : CE_Failure;
+    return eErr == OGRERR_NONE ? CE_None : CE_Failure;
 }
 
-
 /************************************************************************/
 /*                        GDALContourGenerate()                         */
 /************************************************************************/
@@ -1554,7 +1536,6 @@ General Case:
      -- + -+-------------- + --
      12 |  10              | 1
 
-
 Saddle Point:
 
       5 |                  | 12
@@ -1673,9 +1654,7 @@ CPLErr GDALContourGenerate( GDALRasterBandH hBand,
 /* -------------------------------------------------------------------- */
 /*      Setup contour writer information.                               */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hSrcDS;
-
-    oCWI.hLayer = (OGRLayerH) hLayer;
+    oCWI.hLayer = static_cast<OGRLayerH>(hLayer);
 
     oCWI.nElevField = iElevField;
     oCWI.nIDField = iIDField;
@@ -1686,7 +1665,7 @@ CPLErr GDALContourGenerate( GDALRasterBandH hBand,
     oCWI.adfGeoTransform[3] = 0.0;
     oCWI.adfGeoTransform[4] = 0.0;
     oCWI.adfGeoTransform[5] = 1.0;
-    hSrcDS = GDALGetBandDataset( hBand );
+    GDALDatasetH hSrcDS = GDALGetBandDataset( hBand );
     if( hSrcDS != NULL )
         GDALGetGeoTransform( hSrcDS, oCWI.adfGeoTransform );
     oCWI.nNextID = 0;
@@ -1694,8 +1673,8 @@ CPLErr GDALContourGenerate( GDALRasterBandH hBand,
 /* -------------------------------------------------------------------- */
 /*      Setup contour generator.                                        */
 /* -------------------------------------------------------------------- */
-    int nXSize = GDALGetRasterBandXSize( hBand );
-    int nYSize = GDALGetRasterBandYSize( hBand );
+    const int nXSize = GDALGetRasterBandXSize( hBand );
+    const int nYSize = GDALGetRasterBandYSize( hBand );
 
     GDALContourGenerator oCG( nXSize, nYSize, OGRContourWriter, &oCWI );
     if( !oCG.Init() )
@@ -1714,25 +1693,24 @@ CPLErr GDALContourGenerate( GDALRasterBandH hBand,
 /* -------------------------------------------------------------------- */
 /*      Feed the data into the contour generator.                       */
 /* -------------------------------------------------------------------- */
-    int iLine;
-    double *padfScanline;
-    CPLErr eErr = CE_None;
-
-    padfScanline = (double *) VSI_MALLOC2_VERBOSE(sizeof(double), nXSize);
-    if (padfScanline == NULL)
+    double *padfScanline =
+        static_cast<double *>(VSI_MALLOC2_VERBOSE(sizeof(double), nXSize));
+    if( padfScanline == NULL )
     {
         return CE_Failure;
     }
 
-    for( iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
+    CPLErr eErr = CE_None;
+    for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
     {
         eErr = GDALRasterIO( hBand, GF_Read, 0, iLine, nXSize, 1,
                       padfScanline, nXSize, 1, GDT_Float64, 0, 0 );
         if( eErr == CE_None )
             eErr = oCG.FeedLine( padfScanline );
 
-        if( eErr == CE_None
-            && !pfnProgress( (iLine+1) / (double) nYSize, "", pProgressArg ) )
+        if( eErr == CE_None &&
+            !pfnProgress((iLine + 1) / static_cast<double>(nYSize),
+                         "", pProgressArg) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
             eErr = CE_Failure;
diff --git a/alg/delaunay.c b/alg/delaunay.c
index 1d6ba9e..e36f8ba 100644
--- a/alg/delaunay.c
+++ b/alg/delaunay.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: delaunay.c 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: delaunay.c 36493 2016-11-24 20:53:30Z rouault $
  *
  * Project:  GDAL algorithms
  * Purpose:  Delaunay triangulation
@@ -50,7 +50,7 @@
 #include <ctype.h>
 #include <math.h>
 
-CPL_CVSID("$Id: delaunay.c 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: delaunay.c 36493 2016-11-24 20:53:30Z rouault $");
 
 #if defined(INTERNAL_QHULL) || defined(EXTERNAL_QHULL)
 #define HAVE_INTERNAL_OR_EXTERNAL_QHULL 1
@@ -63,8 +63,16 @@ CPL_CVSID("$Id: delaunay.c 33715 2016-03-13 08:52:06Z goatbar $");
 
 #else /* INTERNAL_QHULL */
 
+#if !defined(QHULL_INCLUDE_SUBDIR_IS_LIBQHULL)
 #include "libqhull.h"
 #include "qset.h"
+#elif QHULL_INCLUDE_SUBDIR_IS_LIBQHULL
+#include "libqhull/libqhull.h"
+#include "libqhull/qset.h"
+#else
+#include "qhull/libqhull.h"
+#include "qhull/qset.h"
+#endif
 
 #endif /* INTERNAL_QHULL */
 
@@ -163,6 +171,14 @@ GDALTriangulation* GDALTriangulationCreateDelaunay(int nPoints,
     VSIFree(points);
     points = NULL;
 
+#if qh_QHpointer  /* see user.h */
+    if (qh_qh == NULL)
+    {
+        CPLReleaseMutex(hMutex);
+        return NULL;
+    }
+#endif
+
     /* Establish a map from QHull facet id to the index in our array of sequential facets */
     panMapQHFacetIdToFacetIdx = (int*)VSI_MALLOC2_VERBOSE(sizeof(int), qh facet_id);
     if( panMapQHFacetIdToFacetIdx == NULL )
@@ -326,6 +342,12 @@ int  GDALTriangulationComputeBarycentricCoefficients(GDALTriangulation* psDT,
 /*               GDALTriangulationComputeBarycentricCoordinates()       */
 /************************************************************************/
 
+#define BARYC_COORD_L1(psCoeffs, dfX, dfY) \
+        (psCoeffs->dfMul1X * ((dfX) - psCoeffs->dfCstX) + psCoeffs->dfMul1Y * ((dfY) - psCoeffs->dfCstY))
+#define BARYC_COORD_L2(psCoeffs, dfX, dfY) \
+        (psCoeffs->dfMul2X * ((dfX) - psCoeffs->dfCstX) + psCoeffs->dfMul2Y * ((dfY) - psCoeffs->dfCstY))
+#define BARYC_COORD_L3(l1, l2)  (1 - (l1) - (l2))
+
 /** Computes the barycentric coordinates of a point.
  *
  * @param psDT triangulation.
@@ -341,12 +363,6 @@ int  GDALTriangulationComputeBarycentricCoefficients(GDALTriangulation* psDT,
  * @since GDAL 2.1
  */
 
-#define BARYC_COORD_L1(psCoeffs, dfX, dfY) \
-        (psCoeffs->dfMul1X * ((dfX) - psCoeffs->dfCstX) + psCoeffs->dfMul1Y * ((dfY) - psCoeffs->dfCstY))
-#define BARYC_COORD_L2(psCoeffs, dfX, dfY) \
-        (psCoeffs->dfMul2X * ((dfX) - psCoeffs->dfCstX) + psCoeffs->dfMul2Y * ((dfY) - psCoeffs->dfCstY))
-#define BARYC_COORD_L3(l1, l2)  (1 - (l1) - (l2))
-
 int  GDALTriangulationComputeBarycentricCoordinates(const GDALTriangulation* psDT,
                                                     int nFacetIdx,
                                                     double dfX,
diff --git a/alg/gdal_alg.h b/alg/gdal_alg.h
index 0235012..65b1e5c 100644
--- a/alg/gdal_alg.h
+++ b/alg/gdal_alg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_alg.h 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: gdal_alg.h 37723 2017-03-16 17:07:53Z rouault $
  *
  * Project:  GDAL Image Processing Algorithms
  * Purpose:  Prototypes, and definitions for various GDAL based algorithms.
@@ -115,6 +115,7 @@ typedef int
                         int bDstToSrc, int nPointCount,
                         double *x, double *y, double *z, int *panSuccess );
 
+/*! @cond Doxygen_Suppress */
 #define GDAL_GTI2_SIGNATURE     "GTI2"
 
 typedef struct {
@@ -125,14 +126,16 @@ typedef struct {
     CPLXMLNode *(*pfnSerialize)( void * pTransformerArg );
     void* (*pfnCreateSimilar)( void* pTransformerArg, double dfSrcRatioX, double dfSrcRatioY );
 } GDALTransformerInfo;
+/*! @endcond */
 
+/*! @cond Doxygen_Suppress */
 void CPL_DLL GDALDestroyTransformer( void *pTransformerArg );
 int  CPL_DLL GDALUseTransformer( void *pTransformerArg,
                                  int bDstToSrc, int nPointCount,
                                  double *x, double *y, double *z,
                                  int *panSuccess );
 void* GDALCreateSimilarTransformer( void* psTransformerArg, double dfSrcRatioX, double dfSrcRatioY );
-
+/*! @endcond */
 
 /* High level transformer for going from image coordinates on one file
    to image coordinates on another, potentially doing reprojection,
@@ -194,7 +197,9 @@ int CPL_DLL GDALTPSTransform(
     void *pTransformArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess );
 
+/*! @cond Doxygen_Suppress */
 char CPL_DLL ** RPCInfoToMD( GDALRPCInfo *psRPCInfo );
+/*! @endcond */
 
 /* RPC based transformer ... src is pixel/line/elev, dst is long/lat/elev */
 
@@ -229,7 +234,6 @@ int  CPL_DLL GDALApproxTransform(
     void *pTransformArg, int bDstToSrc, int nPointCount,
     double *x, double *y, double *z, int *panSuccess );
 
-
 int CPL_DLL CPL_STDCALL
 GDALSimpleImageWarp( GDALDatasetH hSrcDS,
                      GDALDatasetH hDstDS,
@@ -255,11 +259,13 @@ GDALSuggestedWarpOutput2( GDALDatasetH hSrcDS,
                           double *padfExtents,
                           int nOptions );
 
+/*! @cond Doxygen_Suppress */
 CPLXMLNode CPL_DLL *
 GDALSerializeTransformer( GDALTransformerFunc pfnFunc, void *pTransformArg );
 CPLErr CPL_DLL GDALDeserializeTransformer( CPLXMLNode *psTree,
                                            GDALTransformerFunc *ppfnFunc,
                                            void **ppTransformArg );
+/*! @endcond */
 
 CPLErr CPL_DLL
 GDALTransformGeolocations( GDALRasterBandH hXBand,
@@ -275,9 +281,11 @@ GDALTransformGeolocations( GDALRasterBandH hXBand,
 /*      Contour Line Generation                                         */
 /* -------------------------------------------------------------------- */
 
+/** Contour writer callback type */
 typedef CPLErr (*GDALContourWriter)( double dfLevel, int nPoints,
                                      double *padfX, double *padfY, void * );
 
+/** Contour generator opaque type */
 typedef void *GDALContourGeneratorH;
 
 GDALContourGeneratorH CPL_DLL
@@ -289,6 +297,7 @@ CPLErr CPL_DLL GDAL_CG_FeedLine( GDALContourGeneratorH hCG,
                                  double *padfScanline );
 void CPL_DLL GDAL_CG_Destroy( GDALContourGeneratorH hCG );
 
+/*! @cond Doxygen_Suppress */
 typedef struct
 {
     void   *hLayer;
@@ -302,6 +311,7 @@ typedef struct
 
 CPLErr CPL_DLL
 OGRContourWriter( double, int, double *, double *, void *pInfo );
+/*! @endcond */
 
 CPLErr CPL_DLL
 GDALContourGenerate( GDALRasterBandH hBand,
@@ -347,7 +357,6 @@ GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
                         char **papszOptions, GDALProgressFunc pfnProgress,
                         void *pProgressArg );
 
-
 /************************************************************************/
 /*  Gridding interface.                                                 */
 /************************************************************************/
@@ -407,12 +416,15 @@ typedef struct
     double  dfNoDataValue;
 } GDALGridInverseDistanceToAPowerOptions;
 
+/** Inverse distance to a power, with nearest neighbour search, control options */
 typedef struct
 {
     /*! Weighting power. */
     double  dfPower;
     /*! The radius of search circle. */
     double  dfRadius;
+    /*! Smoothing parameter. */
+    double  dfSmoothing;
 
     /*! Maximum number of data points to use.
      *
@@ -504,7 +516,6 @@ typedef struct
     double  dfNoDataValue;
 } GDALGridLinearOptions;
 
-
 CPLErr CPL_DLL
 GDALGridCreate( GDALGridAlgorithm, const void *, GUInt32,
                 const double *, const double *, const double *,
@@ -512,6 +523,7 @@ GDALGridCreate( GDALGridAlgorithm, const void *, GUInt32,
                 GUInt32, GUInt32, GDALDataType, void *,
                 GDALProgressFunc, void *);
 
+/** Grid context opaque type */
 typedef struct GDALGridContext GDALGridContext;
 
 GDALGridContext CPL_DLL*
@@ -537,34 +549,38 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
 /*  Delaunay triangulation interface.                                   */
 /************************************************************************/
 
+/** Triangle fact */
 typedef struct
 {
-    int anVertexIdx[3];   /* index to the padfX/padfY arrays */
-    int anNeighborIdx[3]; /* index to GDALDelaunayTriangulation.pasFacets, or -1 */
+    int anVertexIdx[3];   /**< index to the padfX/padfY arrays */
+    int anNeighborIdx[3]; /**< index to GDALDelaunayTriangulation.pasFacets, or -1 */
                           /* anNeighborIdx[k] is the triangle to the opposite side */
                           /* of the opposite segment of anVertexIdx[k] */
 } GDALTriFacet;
 
-/* Conversion from cartesian (x,y) to barycentric (l1,l2,l3) with :
-   l1 = dfMul1X * (x - dfCxtX) + dfMul1Y * (y - dfCstY)
-   l2 = dfMul2X * (x - dfCxtX) + dfMul2Y * (y - dfCstY)
-   l3 = 1 - l1 - l2
-*/
+/** Triangle barycentric coefficients.
+ *
+ * Conversion from cartesian (x,y) to barycentric (l1,l2,l3) with :
+ *  l1 = dfMul1X * (x - dfCxtX) + dfMul1Y * (y - dfCstY)
+ *  l2 = dfMul2X * (x - dfCxtX) + dfMul2Y * (y - dfCstY)
+ *  l3 = 1 - l1 - l2
+ */
 typedef struct
 {
-    double      dfMul1X;
-    double      dfMul1Y;
-    double      dfMul2X;
-    double      dfMul2Y;
-    double      dfCstX;
-    double      dfCstY;
+    double      dfMul1X; /**< dfMul1X */
+    double      dfMul1Y; /**< dfMul1Y */
+    double      dfMul2X; /**< dfMul2X */
+    double      dfMul2Y; /**< dfMul2Y */
+    double      dfCstX;  /**< dfCstX */
+    double      dfCstY;  /**< dfCstY */
 } GDALTriBarycentricCoefficients;
 
+/** Triangulation structure */
 typedef struct
 {
-    int                             nFacets;
-    GDALTriFacet                   *pasFacets;     /* nFacets elements */
-    GDALTriBarycentricCoefficients *pasFacetCoefficients; /* nFacets elements */
+    int                             nFacets;       /**< number of facets */
+    GDALTriFacet                   *pasFacets;     /**< array of nFacets facets */
+    GDALTriBarycentricCoefficients *pasFacetCoefficients; /**< arra of nFacets barycentric coefficients */
 } GDALTriangulation;
 
 int CPL_DLL GDALHasTriangulation(void);
@@ -595,8 +611,21 @@ int CPL_DLL GDALTriangulationFindFacetDirected( const GDALTriangulation* psDT,
                                                 int* panOutputFacetIdx );
 void CPL_DLL GDALTriangulationFree(GDALTriangulation* psDT);
 
+/*! @cond Doxygen_Suppress */
 // GDAL internal use only
 void GDALTriangulationTerminate(void);
+/*! @endcond */
+
+GDALDatasetH CPL_DLL GDALOpenVerticalShiftGrid(
+                                        const char* pszProj4Geoidgrids,
+                                        int* pbError );
+
+GDALDatasetH CPL_DLL GDALApplyVerticalShiftGrid( GDALDatasetH hSrcDataset,
+                                         GDALDatasetH hGridDataset,
+                                         int bInverse,
+                                         double dfSrcUnitToMeter,
+                                         double dfDstUnitToMeter,
+                                         const char* const* papszOptions );
 
 CPL_C_END
 
diff --git a/alg/gdal_alg_priv.h b/alg/gdal_alg_priv.h
index 88b0d11..e597927 100644
--- a/alg/gdal_alg_priv.h
+++ b/alg/gdal_alg_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_alg_priv.h 33757 2016-03-20 20:22:33Z goatbar $
+ * $Id: gdal_alg_priv.h 36411 2016-11-21 22:03:48Z rouault $
  *
  * Project:  GDAL Image Processing Algorithms
  * Purpose:  Prototypes and definitions for various GDAL based algorithms:
@@ -32,6 +32,8 @@
 #ifndef GDAL_ALG_PRIV_H_INCLUDED
 #define GDAL_ALG_PRIV_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "gdal_alg.h"
 
 CPL_C_START
@@ -39,7 +41,7 @@ CPL_C_START
 /** Source of the burn value */
 typedef enum {
     /*! Use value from padfBurnValue */    GBV_UserBurnValue = 0,
-    /*! Use value from the Z coordinate */    GBV_Z = 1,
+    /*! Use value from the Z coordinate */ GBV_Z = 1,
     /*! Use value form the M value */    GBV_M = 2
 } GDALBurnValueSrc;
 
@@ -76,17 +78,17 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                        double *padfX, double *padfY, double *padfVariant,
                        llPointFunc pfnPointFunc, void *pCBData );
 
-void GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
+void GDALdllImageLineAllTouched( int nRasterXSize, int nRasterYSize,
+                                 int nPartCount, int *panPartSize,
+                                 double *padfX, double *padfY,
+                                 double *padfVariant,
+                                 llPointFunc pfnPointFunc, void *pCBData );
+
+void GDALdllImageFilledPolygon( int nRasterXSize, int nRasterYSize,
                                 int nPartCount, int *panPartSize,
                                 double *padfX, double *padfY,
                                 double *padfVariant,
-                                llPointFunc pfnPointFunc, void *pCBData );
-
-void GDALdllImageFilledPolygon(int nRasterXSize, int nRasterYSize,
-                               int nPartCount, int *panPartSize,
-                               double *padfX, double *padfY,
-                               double *padfVariant,
-                               llScanlineFunc pfnScanlineFunc, void *pCBData );
+                                llScanlineFunc pfnScanlineFunc, void *pCBData );
 
 CPL_C_END
 
@@ -114,7 +116,7 @@ public:  // these are intended to be readonly.
     int      nConnectedness;
 
 public:
-             GDALRasterPolygonEnumeratorT( int nConnectedness=4 );
+    explicit GDALRasterPolygonEnumeratorT( int nConnectedness=4 );
             ~GDALRasterPolygonEnumeratorT();
 
     void     ProcessLine( DataType *panLastLineVal, DataType *panThisLineVal,
@@ -153,21 +155,21 @@ void CPL_DLL * GDALCloneTransformer( void *pTransformerArg );
 /*      Color table related                                             */
 /************************************************************************/
 
-/* definitions exists for T = GUInt32 and T = GUIntBig */
+// Definitions exists for T = GUInt32 and T = GUIntBig.
 template<class T> int
 GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
-                           GDALRasterBandH hGreen,
-                           GDALRasterBandH hBlue,
-                           GByte* pabyRedBand,
-                           GByte* pabyGreenBand,
-                           GByte* pabyBlueBand,
-                           int (*pfnIncludePixel)(int,int,void*),
-                           int nColors,
-                           int nBits,
-                           T* panHistogram,
-                           GDALColorTableH hColorTable,
-                           GDALProgressFunc pfnProgress,
-                           void * pProgressArg );
+                                 GDALRasterBandH hGreen,
+                                 GDALRasterBandH hBlue,
+                                 GByte* pabyRedBand,
+                                 GByte* pabyGreenBand,
+                                 GByte* pabyBlueBand,
+                                 int (*pfnIncludePixel)(int,int,void*),
+                                 int nColors,
+                                 int nBits,
+                                 T* panHistogram,
+                                 GDALColorTableH hColorTable,
+                                 GDALProgressFunc pfnProgress,
+                                 void * pProgressArg );
 
 int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
                                GDALRasterBandH hGreen,
@@ -180,12 +182,12 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
                                GDALProgressFunc pfnProgress,
                                void * pProgressArg );
 
-#define PRIME_FOR_65536                                 98317
-
-/* See HashHistogram structure in gdalmediancut.cpp and ColorIndex structure in gdaldither.cpp */
-/* 6 * sizeof(int) should be the size of the largest of both structures */
-#define MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536         (6 * sizeof(int) * PRIME_FOR_65536)
+#define PRIME_FOR_65536 98317
 
+// See HashHistogram structure in gdalmediancut.cpp and ColorIndex structure in
+// gdaldither.cpp 6 * sizeof(int) should be the size of the largest of both
+// structures.
+#define MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 (6 * sizeof(int) * PRIME_FOR_65536)
 
 /************************************************************************/
 /*      Float comparison function.                                      */
@@ -206,4 +208,6 @@ struct FloatEqualityTest
     bool operator()(float a, float b) { return GDALFloatEquals(a,b) == TRUE; }
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* ndef GDAL_ALG_PRIV_H_INCLUDED */
diff --git a/alg/gdal_crs.c b/alg/gdal_crs.c
index a219adc..8d59727 100644
--- a/alg/gdal_crs.c
+++ b/alg/gdal_crs.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_crs.c 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: gdal_crs.c 36530 2016-11-27 18:04:36Z goatbar $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implementation of the GDALTransformer wrapper around CRS.C functions
@@ -58,7 +58,11 @@
 #include "cpl_string.h"
 #include "cpl_atomic_ops.h"
 
-CPL_CVSID("$Id: gdal_crs.c 33715 2016-03-13 08:52:06Z goatbar $");
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+CPL_CVSID("$Id: gdal_crs.c 36530 2016-11-27 18:04:36Z goatbar $");
 
 /* Hum, we cannot include gdal_priv.h from a .c file... */
 CPL_C_START
@@ -181,6 +185,8 @@ void *GDALCreateGCPTransformerEx( int nGCPCount, const GDAL_GCP *pasGCPList,
     int    nCRSresult;
     struct Control_Points sPoints;
 
+    memset( &sPoints, 0, sizeof(sPoints) );
+
     if( nReqOrder == 0 )
     {
         if( nGCPCount >= 10 )
@@ -300,6 +306,9 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
     return GDALCreateGCPTransformerEx(nGCPCount, pasGCPList, nReqOrder, bReversed, FALSE, -1, -1);
 }
 
+/** Create GCP based polynomial transformer, with a tolerance threshold to
+ * discard GCPs that transform badly.
+ */
 void *GDALCreateGCPRefineTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
                                 int nReqOrder, int bReversed, double dfTolerance, int nMinimumGcps)
 
@@ -450,7 +459,7 @@ CPLXMLNode *GDALSerializeGCPTransformer( void *pTransformArg )
     }
 
 /* -------------------------------------------------------------------- */
-/*	Attach GCP List. 						*/
+/*     Attach GCP List.                                                 */
 /* -------------------------------------------------------------------- */
     if( psInfo->nGCPCount > 0 )
     {
@@ -703,6 +712,8 @@ calccoef (struct Control_Points *cp, double E[], double N[], int order)
     int numactive;   /* NUMBER OF ACTIVE CONTROL POINTS */
     int status, i;
 
+    memset( &m, 0, sizeof(m) );
+
     /* CALCULATE THE NUMBER OF VALID CONTROL POINTS */
 
     for(i = numactive = 0 ; i < cp->count ; i++)
@@ -1082,6 +1093,8 @@ static int remove_outliers( GCPTransformInfo *psInfo )
     double dfTolerance;
     struct Control_Points sPoints;
 
+    memset( &sPoints, 0, sizeof(sPoints) );
+
     nGCPCount = psInfo->nGCPCount;
     nMinimumGcps = psInfo->nMinimumGcps;
     nReqOrder = psInfo->nOrder;
diff --git a/alg/gdal_nrgcrs.c b/alg/gdal_nrgcrs.c
index c6d5af0..25ada96 100644
--- a/alg/gdal_nrgcrs.c
+++ b/alg/gdal_nrgcrs.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_nrgcrs.c 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: gdal_nrgcrs.c 34519 2016-07-02 21:09:22Z goatbar $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implementation of the GDALTransformer wrapper around CRS.C functions
@@ -127,7 +127,7 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
 /*      Compute the forward and reverse polynomials.                    */
 /* -------------------------------------------------------------------- */
     if ( TwoDPolyFit( &rms_err, psInfo->adfFromGeoX, nReqOrder, nGCPCount,
-		      padfRasterX, padfGeoX, padfGeoY ) < 0 )
+                      padfRasterX, padfGeoX, padfGeoY ) < 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to compute polynomial equations of desired order\n"
@@ -135,7 +135,7 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
         goto CleanupAfterError;
     }
     if ( TwoDPolyFit( &rms_err, psInfo->adfFromGeoY, nReqOrder, nGCPCount,
-		      padfRasterY, padfGeoX, padfGeoY ) < 0 )
+                      padfRasterY, padfGeoX, padfGeoY ) < 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to compute polynomial equations of desired order\n"
@@ -143,7 +143,7 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
         goto CleanupAfterError;
     }
     if ( TwoDPolyFit( &rms_err, psInfo->adfToGeoX, nReqOrder, nGCPCount,
-		      padfGeoX, padfRasterX, padfRasterY ) < 0 )
+                      padfGeoX, padfRasterX, padfRasterY ) < 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to compute polynomial equations of desired order\n"
@@ -151,7 +151,7 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
         goto CleanupAfterError;
     }
     if ( TwoDPolyFit( &rms_err, psInfo->adfToGeoY, nReqOrder, nGCPCount,
-		      padfGeoY, padfRasterX, padfRasterY ) < 0 )
+                      padfGeoY, padfRasterX, padfRasterY ) < 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to compute polynomial equations of desired order\n"
@@ -163,19 +163,19 @@ void *GDALCreateGCPTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
 /*      Dump residuals.                                                 */
 /* -------------------------------------------------------------------- */
     CPLDebug( "GDALCreateGCPTransformer",
-	      "Number of GCPs %d, transformation order %d",
-	      nGCPCount, psInfo->nOrder );
+              "Number of GCPs %d, transformation order %d",
+              nGCPCount, psInfo->nOrder );
 
     for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
     {
-	double x = pasGCPList[iGCP].dfGCPX;
-	double y = pasGCPList[iGCP].dfGCPY;
-	double z = pasGCPList[iGCP].dfGCPZ;
-	int bSuccess;
-	GDALGCPTransform( psInfo, TRUE, 1, &x, &y, &z, &bSuccess );
-	CPLDebug( "GDALCreateGCPTransformer",
-		  "GCP %d. Residuals: X: %f, Y: %f", iGCP,
-		  pasGCPList[iGCP].dfGCPPixel - x, pasGCPList[iGCP].dfGCPLine - y );
+        double x = pasGCPList[iGCP].dfGCPX;
+        double y = pasGCPList[iGCP].dfGCPY;
+        double z = pasGCPList[iGCP].dfGCPZ;
+        int bSuccess;
+        GDALGCPTransform( psInfo, TRUE, 1, &x, &y, &z, &bSuccess );
+        CPLDebug( "GDALCreateGCPTransformer",
+                  "GCP %d. Residuals: X: %f, Y: %f", iGCP,
+                  pasGCPList[iGCP].dfGCPPixel - x, pasGCPList[iGCP].dfGCPLine - y );
     }
 
     return psInfo;
@@ -251,19 +251,19 @@ int GDALGCPTransform( void *pTransformArg, int bDstToSrc,
 
     for( i = 0; i < nPointCount; i++ )
     {
-	X = x[i];
-	Y = y[i];
+        X = x[i];
+        Y = y[i];
         if( bDstToSrc )
         {
             x[i] = TwoDPolyEval( psInfo->adfFromGeoX, psInfo->nOrder, X, Y );
-	    y[i] = TwoDPolyEval( psInfo->adfFromGeoY, psInfo->nOrder, X, Y );
+            y[i] = TwoDPolyEval( psInfo->adfFromGeoY, psInfo->nOrder, X, Y );
         }
         else
         {
             x[i] = TwoDPolyEval( psInfo->adfToGeoX, psInfo->nOrder, X, Y );
-	    y[i] = TwoDPolyEval( psInfo->adfToGeoY, psInfo->nOrder, X, Y );
+            y[i] = TwoDPolyEval( psInfo->adfToGeoY, psInfo->nOrder, X, Y );
         }
-	z[i] = 0;
+        z[i] = 0;
         panSuccess[i] = TRUE;
     }
 
diff --git a/alg/gdal_octave.cpp b/alg/gdal_octave.cpp
index 46bd1b1..90005e6 100644
--- a/alg/gdal_octave.cpp
+++ b/alg/gdal_octave.cpp
@@ -27,7 +27,7 @@
 
 #include "gdal_simplesurf.h"
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: gdal_octave.cpp 36960 2016-12-19 14:13:21Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -46,88 +46,102 @@ int GDALIntegralImage::GetHeight() { return nHeight; }
 
 int GDALIntegralImage::GetWidth() { return nWidth; }
 
-void GDALIntegralImage::Initialize(const double **padfImg, int nHeightIn, int nWidthIn)
+void GDALIntegralImage::Initialize( const double **padfImg,
+                                    int nHeightIn, int nWidthIn )
 {
-    //Memory allocation
+    if( pMatrix )
+    {
+        for( int i = 0; i < nHeight; i++ )
+            delete[] pMatrix[i];
+        delete[] pMatrix;
+    }
+
+    // Memory allocation.
     pMatrix = new double*[nHeightIn];
-    for (int i = 0; i < nHeightIn; i++)
+    for( int i = 0; i < nHeightIn; i++ )
         pMatrix[i] = new double[nWidthIn];
 
     nHeight = nHeightIn;
     nWidth = nWidthIn;
 
-    //Integral image calculation
-    for (int i = 0; i < nHeight; i++)
-        for (int j = 0; j < nWidth; j++)
+    // Integral image calculation.
+    for( int i = 0; i < nHeight; i++ )
+        for( int j = 0; j < nWidth; j++ )
         {
-            double val = padfImg[i][j];
-            double a = 0, b = 0, c = 0;
+            const double val = padfImg[i][j];
+            double a = 0.0;
+            double b = 0.0;
+            double c = 0.0;
 
-            if (i - 1 >= 0 && j - 1 >= 0)
+            if( i - 1 >= 0 && j - 1 >= 0 )
                 a = pMatrix[i - 1][j - 1];
-            if (j - 1 >= 0)
+            if( j - 1 >= 0 )
                 b = pMatrix[i][j - 1];
-            if (i - 1 >= 0)
+            if( i - 1 >= 0 )
                 c = pMatrix[i - 1][j];
 
-            //New value based on previous calculations
+            // New value based on previous calculations.
             pMatrix[i][j] = val - a + b + c;
         }
 }
 
 /*
- * Returns value of specified cell
+ * Returns value of specified cell.
  */
-double GDALIntegralImage::GetValue(int nRow, int nCol)
+double GDALIntegralImage::GetValue( int nRow, int nCol )
 {
-    if ((nRow >= 0 && nRow < nHeight) && (nCol >= 0 && nCol < nWidth))
-        return pMatrix[nRow][nCol];
-    else
+    if( !((nRow >= 0 && nRow < nHeight) && (nCol >= 0 && nCol < nWidth)) )
         return 0;
+
+    return pMatrix[nRow][nCol];
 }
 
-double GDALIntegralImage::GetRectangleSum(int nRow, int nCol, int nWidthIn, int nHeightIn)
+double GDALIntegralImage::GetRectangleSum( int nRow, int nCol,
+                                           int nWidthIn, int nHeightIn )
 {
-    double a = 0, b = 0, c = 0, d = 0;
+    // Left top point of rectangle is first.
+    const int w = nWidthIn - 1;
+    const int h = nHeightIn - 1;
 
-    //Left top point of rectangle is first
-    int w = nWidthIn - 1;
-    int h = nHeightIn - 1;
+    const int row = nRow;
+    const int col = nCol;
 
-    int row = nRow;
-    int col = nCol;
+    // Left top point.
+    const int lt_row = (row <= nHeight) ? (row - 1) : -1;
+    const int lt_col = (col <= nWidth) ? (col - 1) : -1;
+    // Right bottom point of the rectangle.
+    const int rb_row = (row + h < nHeight) ? (row + h) : (nHeight - 1);
+    const int rb_col = (col + w < nWidth) ? (col + w) : (nWidth - 1);
 
-    //Left top point
-    int lt_row = (row <= nHeight) ? (row - 1) : -1;
-    int lt_col = (col <= nWidth) ? (col - 1) : -1;
-    //Right bottom point of the rectangle
-    int rb_row = (row + h < nHeight) ? (row + h) : (nHeight - 1);
-    int rb_col = (col + w < nWidth) ? (col + w) : (nWidth - 1);
+    double a = 0.0;
+    double b = 0.0;
+    double c = 0.0;
+    double d = 0.0;
 
-    if (lt_row >= 0 && lt_col >= 0)
-        a = this->GetValue(lt_row, lt_col);
+    if( lt_row >= 0 && lt_col >= 0 )
+        a = GetValue(lt_row, lt_col);
 
-    if (lt_row >= 0 && rb_col >= 0)
-        b = this->GetValue(lt_row, rb_col);
+    if( lt_row >= 0 && rb_col >= 0 )
+        b = GetValue(lt_row, rb_col);
 
-    if (rb_row >= 0 && rb_col >= 0)
-        c = this->GetValue(rb_row, rb_col);
+    if( rb_row >= 0 && rb_col >= 0 )
+        c = GetValue(rb_row, rb_col);
 
-    if (rb_row >= 0 && lt_col >= 0)
-        d = this->GetValue(rb_row, lt_col);
+    if( rb_row >= 0 && lt_col >= 0 )
+        d = GetValue(rb_row, lt_col);
 
-    double res = a + c - b - d;
+    const double res = a + c - b - d;
 
-    return (res > 0) ? res : 0;
+    return res > 0 ? res : 0;
 }
 
-double GDALIntegralImage::HaarWavelet_X(int nRow, int nCol, int nSize)
+double GDALIntegralImage::HaarWavelet_X( int nRow, int nCol, int nSize )
 {
     return GetRectangleSum(nRow, nCol + nSize / 2, nSize / 2, nSize)
         - GetRectangleSum(nRow, nCol, nSize / 2, nSize);
 }
 
-double GDALIntegralImage::HaarWavelet_Y(int nRow, int nCol, int nSize)
+double GDALIntegralImage::HaarWavelet_Y( int nRow, int nCol, int nSize )
 {
     return GetRectangleSum(nRow + nSize / 2, nCol, nSize, nSize / 2)
         - GetRectangleSum(nRow, nCol, nSize, nSize / 2);
@@ -135,69 +149,70 @@ double GDALIntegralImage::HaarWavelet_Y(int nRow, int nCol, int nSize)
 
 GDALIntegralImage::~GDALIntegralImage()
 {
-    //Clean up memory
-    for (int i = 0; i < nHeight; i++)
+    // Clean up memory.
+    for( int i = 0; i < nHeight; i++ )
         delete[] pMatrix[i];
 
     delete[] pMatrix;
 }
 
-
-
 /************************************************************************/
 /* ==================================================================== */
 /*                           GDALOctaveLayer                            */
 /* ==================================================================== */
 /************************************************************************/
 
-GDALOctaveLayer::GDALOctaveLayer(int nOctave, int nInterval)
+GDALOctaveLayer::GDALOctaveLayer( int nOctave, int nInterval ) :
+    octaveNum(nOctave),
+    filterSize(3 * static_cast<int>(pow(2.0, nOctave)) * nInterval + 1),
+    radius((filterSize - 1) / 2),
+    scale(static_cast<int>(pow(2.0, nOctave))),
+    width(0),
+    height(0),
+    detHessians(NULL),
+    signs(NULL)
+{}
+
+void GDALOctaveLayer::ComputeLayer( GDALIntegralImage *poImg )
 {
-    this->octaveNum = nOctave;
-    this->filterSize = 3 * ((int)pow(2.0, nOctave) * nInterval + 1);
-    this->radius = (this->filterSize - 1) / 2;
-    this->scale = (int)pow(2.0, nOctave);
-    this->width = 0;
-    this->height = 0;
-
-    this->detHessians = NULL;
-    this->signs = NULL;
-}
-
-void GDALOctaveLayer::ComputeLayer(GDALIntegralImage *poImg)
-{
-    this->width = poImg->GetWidth();
-    this->height = poImg->GetHeight();
+    width = poImg->GetWidth();
+    height = poImg->GetHeight();
 
-    //Allocate memory for arrays
-    this->detHessians = new double*[this->height];
-    this->signs = new int*[this->height];
+    // Allocate memory for arrays.
+    detHessians = new double *[height];
+    signs = new int *[height];
 
-    for (int i = 0; i < this->height; i++)
+    for( int i = 0; i < height; i++ )
     {
-        this->detHessians[i] = new double[this->width];
-        this->signs[i] = new int[this->width];
+        detHessians[i] = new double[width];
+        signs[i] = new int[width];
     }
-    //End Allocate memory for arrays
 
-    //Values of Fast Hessian filters
-    double dxx, dyy, dxy;
-    // 1/3 of filter side
-    int lobe = filterSize / 3;
+    // Values of Fast Hessian filters.
+    double dxx = 0.0;
+    double dyy = 0.0;
+    double dxy = 0.0;
+    // 1/3 of filter side.
+    const int lobe = filterSize / 3;
 
-    //Length of the longer side of the lobe in dxx and dyy filters
-    int longPart = 2 * lobe - 1;
+    // Length of the longer side of the lobe in dxx and dyy filters.
+    const int longPart = 2 * lobe - 1;
 
-    int normalization = filterSize * filterSize;
+    const int normalization = filterSize * filterSize;
 
-    //Loop over image pixels
-    //Filter should remain into image borders
-    for (int r = radius; r <= height - radius; r++)
-        for (int c = radius; c <= width - radius; c++)
+    // Loop over image pixels.
+    // Filter should remain into image borders.
+    for( int r = radius; r <= height - radius; r++ )
+        for( int c = radius; c <= width - radius; c++ )
         {
-            dxx = poImg->GetRectangleSum(r - lobe + 1, c - radius, filterSize, longPart)
-                - 3 * poImg->GetRectangleSum(r - lobe + 1, c - (lobe - 1) / 2, lobe, longPart);
-            dyy = poImg->GetRectangleSum(r - radius, c - lobe - 1, longPart, filterSize)
-                - 3 * poImg->GetRectangleSum(r - lobe + 1, c - lobe + 1, longPart, lobe);
+            dxx = poImg->GetRectangleSum(r - lobe + 1, c - radius,
+                                         filterSize, longPart)
+                - 3 * poImg->GetRectangleSum(r - lobe + 1, c - (lobe - 1) / 2,
+                                             lobe, longPart);
+            dyy = poImg->GetRectangleSum(r - radius, c - lobe - 1,
+                                         longPart, filterSize)
+                - 3 * poImg->GetRectangleSum(r - lobe + 1, c - lobe + 1,
+                                             longPart, lobe);
             dxy = poImg->GetRectangleSum(r - lobe, c - lobe, lobe, lobe)
                 + poImg->GetRectangleSum(r + 1, c + 1, lobe, lobe)
                 - poImg->GetRectangleSum(r - lobe, c + 1, lobe, lobe)
@@ -207,7 +222,7 @@ void GDALOctaveLayer::ComputeLayer(GDALIntegralImage *poImg)
             dyy /= normalization;
             dxy /= normalization;
 
-            //Memorize Hessian values and their signs
+            // Memorize Hessian values and their signs.
             detHessians[r][c] = dxx * dyy - 0.9 * 0.9 * dxy * dxy;
             signs[r][c] = (dxx + dyy >= 0) ? 1 : -1;
         }
@@ -215,7 +230,7 @@ void GDALOctaveLayer::ComputeLayer(GDALIntegralImage *poImg)
 
 GDALOctaveLayer::~GDALOctaveLayer()
 {
-    for (int i = 0; i < height; i++)
+    for( int i = 0; i < height; i++ )
     {
         delete[] detHessians[i];
         delete[] signs[i];
@@ -231,55 +246,54 @@ GDALOctaveLayer::~GDALOctaveLayer()
 /* ==================================================================== */
 /************************************************************************/
 
-GDALOctaveMap::GDALOctaveMap(int nOctaveStart, int nOctaveEnd)
+GDALOctaveMap::GDALOctaveMap( int nOctaveStartIn, int nOctaveEndIn ) :
+    pMap(new GDALOctaveLayer**[nOctaveEndIn]),
+    octaveStart(nOctaveStartIn),
+    octaveEnd(nOctaveEndIn)
 {
-    this->octaveStart = nOctaveStart;
-    this->octaveEnd = nOctaveEnd;
-
-    pMap = new GDALOctaveLayer**[octaveEnd];
-
-    for (int i = 0; i < nOctaveEnd; i++)
-        pMap[i] = new GDALOctaveLayer*[INTERVALS];
+    for( int i = 0; i < octaveEnd; i++ )
+        pMap[i] = new GDALOctaveLayer *[INTERVALS];
 
-    for (int oct = octaveStart; oct <= octaveEnd; oct++)
-        for (int i = 1; i <= INTERVALS; i++)
+    for( int oct = octaveStart; oct <= octaveEnd; oct++ )
+        for( int i = 1; i <= INTERVALS; i++ )
             pMap[oct - 1][i - 1] = new GDALOctaveLayer(oct, i);
 }
 
-void GDALOctaveMap::ComputeMap(GDALIntegralImage *poImg)
+void GDALOctaveMap::ComputeMap( GDALIntegralImage *poImg )
 {
-    for (int oct = octaveStart; oct <= octaveEnd; oct++)
-        for (int i = 1; i <= INTERVALS; i++)
+    for( int oct = octaveStart; oct <= octaveEnd; oct++ )
+        for( int i = 1; i <= INTERVALS; i++ )
             pMap[oct - 1][i - 1]->ComputeLayer(poImg);
 }
 
-bool GDALOctaveMap::PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
-                                    GDALOctaveLayer *mid, GDALOctaveLayer *top, double threshold)
+bool GDALOctaveMap::PointIsExtremum( int row, int col, GDALOctaveLayer *bot,
+                                     GDALOctaveLayer *mid, GDALOctaveLayer *top,
+                                     double threshold )
 {
     // Check that point in middle layer has all neighbors.
-    if (row <= top->radius || col <= top->radius ||
-        row + top->radius >= top->height || col + top->radius >= top->width)
+    if( row <= top->radius || col <= top->radius ||
+        row + top->radius >= top->height || col + top->radius >= top->width )
         return false;
 
-    double curPoint = mid->detHessians[row][col];
+    const double curPoint = mid->detHessians[row][col];
 
     // Hessian should be higher than threshold.
-    if (curPoint < threshold)
+    if( curPoint < threshold )
         return false;
 
-    // Hessian should be higher than Hessians of all neighbors
-    for (int i = -1; i <= 1; i++)
-        for (int j = -1; j <= 1; j++)
+    // Hessian should be higher than Hessians of all neighbors.
+    for( int i = -1; i <= 1; i++ )
+        for( int j = -1; j <= 1; j++ )
         {
-            double topPoint = top->detHessians[row + i][col + j];
-            double midPoint = mid->detHessians[row + i][col + j];
-            double botPoint = bot->detHessians[row + i][col + j];
+            const double topPoint = top->detHessians[row + i][col + j];
+            const double midPoint = mid->detHessians[row + i][col + j];
+            const double botPoint = bot->detHessians[row + i][col + j];
 
-            if (topPoint >= curPoint || botPoint >= curPoint)
+            if( topPoint >= curPoint || botPoint >= curPoint )
                 return false;
 
-            if (i != 0 || j != 0)
-                if (midPoint >= curPoint)
+            if( i != 0 || j != 0 )
+                if( midPoint >= curPoint )
                     return false;
         }
 
@@ -288,13 +302,13 @@ bool GDALOctaveMap::PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
 
 GDALOctaveMap::~GDALOctaveMap()
 {
-    // Clean up Octave layers
-    for (int oct = octaveStart; oct <= octaveEnd; oct++)
-        for(int i = 0; i < INTERVALS; i++)
+    // Clean up Octave layers.
+    for( int oct = octaveStart; oct <= octaveEnd; oct++ )
+        for( int i = 0; i < INTERVALS; i++ )
             delete pMap[oct - 1][i];
 
-    //Clean up allocated memory
-    for (int oct = 0; oct < octaveEnd; oct++)
+    // Clean up allocated memory.
+    for( int oct = 0; oct < octaveEnd; oct++ )
         delete[] pMap[oct];
 
     delete[] pMap;
diff --git a/alg/gdal_rpc.cpp b/alg/gdal_rpc.cpp
index 43f00aa..395a683 100644
--- a/alg/gdal_rpc.cpp
+++ b/alg/gdal_rpc.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_rpc.cpp 34067 2016-04-23 17:56:51Z rouault $
  *
  * Project:  Image Warper
  * Purpose:  Implements a rational polynomial (RPC) based transformer.
@@ -28,18 +27,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
+#include "cpl_port.h"
 #include "gdal_alg.h"
-#include "ogr_spatialref.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_mdreader.h"
-
-#if (defined(__x86_64) || defined(_M_X64))
-#define USE_SSE2_OPTIM
-#include "gdalsse_priv.h"
+#include "gdal_priv.h"
+#if defined(__x86_64) || defined(_M_X64)
+#  define USE_SSE2_OPTIM
+#  include "gdalsse_priv.h"
 #endif
+#include "ogr_api.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
+
+// #define DEBUG_VERBOSE_EXTRACT_DEM
 
-CPL_CVSID("$Id: gdal_rpc.cpp 34067 2016-04-23 17:56:51Z rouault $");
+CPL_CVSID("$Id: gdal_rpc.cpp 37169 2017-01-18 13:58:09Z rouault $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg );
@@ -47,11 +64,12 @@ void *GDALDeserializeRPCTransformer( CPLXMLNode *psTree );
 CPL_C_END
 
 static const int MAX_ABS_VALUE_WARNINGS = 20;
+static const double DEFAULT_PIX_ERR_THRESHOLD = 0.1;
 
 /************************************************************************/
 /*                            RPCInfoToMD()                             */
 /*                                                                      */
-/*      Turn an RPCInfo structure back into it's metadata format.       */
+/*      Turn an RPCInfo structure back into its metadata format.        */
 /************************************************************************/
 
 char ** RPCInfoToMD( GDALRPCInfo *psRPCInfo )
@@ -59,7 +77,6 @@ char ** RPCInfoToMD( GDALRPCInfo *psRPCInfo )
 {
     char **papszMD = NULL;
     CPLString osField, osMultiField;
-    int i;
 
     osField.Printf( "%.15g", psRPCInfo->dfLINE_OFF );
     papszMD = CSLSetNameValue( papszMD, RPC_LINE_OFF, osField );
@@ -103,7 +120,7 @@ char ** RPCInfoToMD( GDALRPCInfo *psRPCInfo )
     osField.Printf( "%.15g", psRPCInfo->dfMAX_LAT );
     papszMD = CSLSetNameValue( papszMD, "MAX_LAT", osField );
 
-    for( i = 0; i < 20; i++ )
+    for( int i = 0; i < 20; i++ )
     {
         osField.Printf( "%.15g", psRPCInfo->adfLINE_NUM_COEFF[i] );
         if( i > 0 )
@@ -114,7 +131,7 @@ char ** RPCInfoToMD( GDALRPCInfo *psRPCInfo )
     }
     papszMD = CSLSetNameValue( papszMD, "LINE_NUM_COEFF", osMultiField );
 
-    for( i = 0; i < 20; i++ )
+    for( int i = 0; i < 20; i++ )
     {
         osField.Printf( "%.15g", psRPCInfo->adfLINE_DEN_COEFF[i] );
         if( i > 0 )
@@ -125,7 +142,7 @@ char ** RPCInfoToMD( GDALRPCInfo *psRPCInfo )
     }
     papszMD = CSLSetNameValue( papszMD, "LINE_DEN_COEFF", osMultiField );
 
-    for( i = 0; i < 20; i++ )
+    for( int i = 0; i < 20; i++ )
     {
         osField.Printf( "%.15g", psRPCInfo->adfSAMP_NUM_COEFF[i] );
         if( i > 0 )
@@ -136,7 +153,7 @@ char ** RPCInfoToMD( GDALRPCInfo *psRPCInfo )
     }
     papszMD = CSLSetNameValue( papszMD, "SAMP_NUM_COEFF", osMultiField );
 
-    for( i = 0; i < 20; i++ )
+    for( int i = 0; i < 20; i++ )
     {
         osField.Printf( "%.15g", psRPCInfo->adfSAMP_DEN_COEFF[i] );
         if( i > 0 )
@@ -183,7 +200,7 @@ static void RPCComputeTerms( double dfLong, double dfLat, double dfHeight,
 
 /************************************************************************/
 /* ==================================================================== */
-/*			     GDALRPCTransformer                         */
+/*                           GDALRPCTransformer                         */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -221,6 +238,16 @@ typedef struct {
 
     int         bHasTriedOpeningDS;
     GDALDataset *poDS;
+    double     *padfDEMBuffer;
+    int         nDEMExtractions;
+    int         nBufferMaxRadius;
+    int         nHitsInBuffer;
+    int         nBufferX;
+    int         nBufferY;
+    int         nBufferWidth;
+    int         nBufferHeight;
+    int         nLastQueriedX;
+    int         nLastQueriedY;
 
     OGRCoordinateTransformation *poCT;
 
@@ -231,7 +258,8 @@ typedef struct {
 
 #ifdef USE_SSE2_OPTIM
     double      adfDoubles[20 * 4 + 1];
-    double     *padfCoeffs; // LINE_NUM_COEFF, LINE_DEN_COEFF, SAMP_NUM_COEFF and then SAMP_DEN_COEFF
+     // LINE_NUM_COEFF, LINE_DEN_COEFF, SAMP_NUM_COEFF and then SAMP_DEN_COEFF.
+    double     *padfCoeffs;
 #endif
 
     bool        bRPCInverseVerbose;
@@ -249,19 +277,31 @@ static void RPCEvaluate4( const double *padfTerms,
                           double& dfSum3, double& dfSum4 )
 
 {
-    int i;
-    XMMReg2Double terms, coefs1, coefs2, coefs3, coefs4,
-                  sum1 = XMMReg2Double::Zero(),
-                  sum2 = XMMReg2Double::Zero(),
-                  sum3 = XMMReg2Double::Zero(),
-                  sum4 = XMMReg2Double::Zero();
-    for( i = 0; i < 20; i+=2 )
+    XMMReg2Double sum1 = XMMReg2Double::Zero();
+    XMMReg2Double sum2 = XMMReg2Double::Zero();
+    XMMReg2Double sum3 = XMMReg2Double::Zero();
+    XMMReg2Double sum4 = XMMReg2Double::Zero();
+    for( int i = 0; i < 20; i += 2 )
     {
-        terms = XMMReg2Double::Load2ValAligned(padfTerms + i);
-        coefs1 = XMMReg2Double::Load2ValAligned(padfCoefs + i);       // LINE_NUM_COEFF
-        coefs2 = XMMReg2Double::Load2ValAligned(padfCoefs + i + 20);  // LINE_DEN_COEFF
-        coefs3 = XMMReg2Double::Load2ValAligned(padfCoefs + i + 40);  // SAMP_NUM_COEFF
-        coefs4 = XMMReg2Double::Load2ValAligned(padfCoefs + i + 60);  // SAMP_DEN_COEFF
+        const XMMReg2Double terms =
+            XMMReg2Double::Load2ValAligned(padfTerms + i);
+
+        // LINE_NUM_COEFF.
+        const XMMReg2Double coefs1 =
+            XMMReg2Double::Load2ValAligned(padfCoefs + i);
+
+        // LINE_DEN_COEFF.
+        const XMMReg2Double coefs2 =
+            XMMReg2Double::Load2ValAligned(padfCoefs + i + 20);
+
+        // SAMP_NUM_COEFF.
+        const XMMReg2Double coefs3 =
+            XMMReg2Double::Load2ValAligned(padfCoefs + i + 40);
+
+        // SAMP_DEN_COEFF.
+        const XMMReg2Double coefs4 =
+            XMMReg2Double::Load2ValAligned(padfCoefs + i + 60);
+
         sum1 += terms * coefs1;
         sum2 += terms * coefs2;
         sum3 += terms * coefs3;
@@ -271,10 +311,10 @@ static void RPCEvaluate4( const double *padfTerms,
     sum2.AddLowAndHigh();
     sum3.AddLowAndHigh();
     sum4.AddLowAndHigh();
-    dfSum1 = (double)sum1;
-    dfSum2 = (double)sum2;
-    dfSum3 = (double)sum3;
-    dfSum4 = (double)sum4;
+    dfSum1 = static_cast<double>(sum1);
+    dfSum2 = static_cast<double>(sum2);
+    dfSum3 = static_cast<double>(sum3);
+    dfSum4 = static_cast<double>(sum4);
 }
 
 #else
@@ -282,10 +322,10 @@ static void RPCEvaluate4( const double *padfTerms,
 static double RPCEvaluate( const double *padfTerms, const double *padfCoefs )
 
 {
-    double dfSum1 = 0.0, dfSum2 = 0.0;
-    int i;
+    double dfSum1 = 0.0;
+    double dfSum2 = 0.0;
 
-    for( i = 0; i < 20; i+=2 )
+    for( int i = 0; i < 20; i += 2 )
     {
         dfSum1 += padfTerms[i] * padfCoefs[i];
         dfSum2 += padfTerms[i+1] * padfCoefs[i+1];
@@ -305,12 +345,12 @@ static void RPCTransformPoint( const GDALRPCTransformInfo *psRPCTransformInfo,
                                double *pdfPixel, double *pdfLine )
 
 {
-    double dfResultX, dfResultY;
-    double adfTermsWithMargin[20+1];
-    // Make sure padfTerms is aligned on a 16-byte boundary for SSE2 aligned loads
-    double* padfTerms = adfTermsWithMargin + (((size_t)adfTermsWithMargin) % 16) / 8;
+    double adfTermsWithMargin[20+1] = {};
+    // Make padfTerms aligned on 16-byte boundary for SSE2 aligned loads.
+    double* padfTerms =
+        adfTermsWithMargin + (((GUIntptr_t)adfTermsWithMargin) % 16) / 8;
 
-    // Avoid dateline issues
+    // Avoid dateline issues.
     double diffLong = dfLong - psRPCTransformInfo->sRPC.dfLONG_OFF;
     if( diffLong < -270 )
     {
@@ -324,13 +364,15 @@ static void RPCTransformPoint( const GDALRPCTransformInfo *psRPCTransformInfo,
     const double dfNormalizedLong =
       diffLong / psRPCTransformInfo->sRPC.dfLONG_SCALE;
     const double dfNormalizedLat =
-      (dfLat    - psRPCTransformInfo->sRPC.dfLAT_OFF) / psRPCTransformInfo->sRPC.dfLAT_SCALE;
+        (dfLat - psRPCTransformInfo->sRPC.dfLAT_OFF) /
+        psRPCTransformInfo->sRPC.dfLAT_SCALE;
     const double dfNormalizedHeight =
-      (dfHeight - psRPCTransformInfo->sRPC.dfHEIGHT_OFF) / psRPCTransformInfo->sRPC.dfHEIGHT_SCALE;
+        (dfHeight - psRPCTransformInfo->sRPC.dfHEIGHT_OFF) /
+        psRPCTransformInfo->sRPC.dfHEIGHT_SCALE;
 
     // The absolute values of the 3 above normalized values are supposed to be
     // below 1. Warn (as debug message) if it is not the case. We allow for some
-    // margin above 1 (1.5, somewhat arbitrary chosen) before warning
+    // margin above 1 (1.5, somewhat arbitrary chosen) before warning.
     static int nCountWarningsAboutAboveOneNormalizedValues = 0;
     if( nCountWarningsAboutAboveOneNormalizedValues < MAX_ABS_VALUE_WARNINGS )
     {
@@ -338,56 +380,71 @@ static void RPCTransformPoint( const GDALRPCTransformInfo *psRPCTransformInfo,
         if( fabs(dfNormalizedLong) > 1.5 )
         {
             bWarned = true;
-            CPLDebug("RPC", "Normalized %s for (lon,lat,height)=(%f,%f,%f) is %f, "
-                    "ie with an absolute value of > 1, which may cause numeric stability problems",
-                    "longitude", dfLong, dfLat, dfHeight, dfNormalizedLong);
+            CPLDebug(
+                "RPC", "Normalized %s for (lon,lat,height)=(%f,%f,%f) is %f, "
+                "i.e. with an absolute value of > 1, which may cause numeric "
+                "stability problems",
+                "longitude", dfLong, dfLat, dfHeight, dfNormalizedLong );
         }
         if( fabs(dfNormalizedLat) > 1.5 )
         {
             bWarned = true;
-            CPLDebug("RPC", "Normalized %s for (lon,lat,height)=(%f,%f,%f) is %f, "
-                    "ie with an absolute value of > 1, which may cause numeric stability problems",
-                    "latitude", dfLong, dfLat, dfHeight, dfNormalizedLat);
+            CPLDebug(
+                "RPC", "Normalized %s for (lon,lat,height)=(%f,%f,%f) is %f, "
+                "ie with an absolute value of > 1, which may cause numeric "
+                "stability problems",
+                "latitude", dfLong, dfLat, dfHeight, dfNormalizedLat );
         }
         if( fabs(dfNormalizedHeight) > 1.5 )
         {
             bWarned = true;
-            CPLDebug("RPC", "Normalized %s for (lon,lat,height)=(%f,%f,%f) is %f, "
-                    "ie with an absolute value of > 1, which may cause numeric stability problems",
-                    "height", dfLong, dfLat, dfHeight, dfNormalizedHeight);
+            CPLDebug(
+                "RPC", "Normalized %s for (lon,lat,height)=(%f,%f,%f) is %f, "
+                "i.e. with an absolute value of > 1, which may cause numeric "
+                "stability problems",
+                "height", dfLong, dfLat, dfHeight, dfNormalizedHeight);
         }
         if( bWarned )
         {
-            // Limit the number of warnings
-            nCountWarningsAboutAboveOneNormalizedValues ++;
-            if( nCountWarningsAboutAboveOneNormalizedValues == MAX_ABS_VALUE_WARNINGS )
+            // Limit the number of warnings.
+            nCountWarningsAboutAboveOneNormalizedValues++;
+            if( nCountWarningsAboutAboveOneNormalizedValues ==
+                MAX_ABS_VALUE_WARNINGS )
             {
                 CPLDebug("RPC", "No more such debug warnings will be emitted");
             }
         }
     }
 
-    RPCComputeTerms( dfNormalizedLong, dfNormalizedLat, dfNormalizedHeight, padfTerms );
+    RPCComputeTerms( dfNormalizedLong, dfNormalizedLat,
+                     dfNormalizedHeight, padfTerms );
 
 #ifdef USE_SSE2_OPTIM
-    double dfSampNum, dfSampDen, dfLineNum, dfLineDen;
+    double dfSampNum = 0.0;
+    double dfSampDen = 0.0;
+    double dfLineNum = 0.0;
+    double dfLineDen = 0.0;
     RPCEvaluate4( padfTerms,
                   psRPCTransformInfo->padfCoeffs,
                   dfLineNum, dfLineDen, dfSampNum, dfSampDen );
-    dfResultX = dfSampNum / dfSampDen;
-    dfResultY = dfLineNum / dfLineDen;
+    const double dfResultX = dfSampNum / dfSampDen;
+    const double dfResultY = dfLineNum / dfLineDen;
 #else
-    dfResultX = RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfSAMP_NUM_COEFF )
+    const double dfResultX =
+        RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfSAMP_NUM_COEFF )
         / RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfSAMP_DEN_COEFF );
 
-    dfResultY = RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfLINE_NUM_COEFF )
+    const double dfResultY =
+        RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfLINE_NUM_COEFF )
         / RPCEvaluate( padfTerms, psRPCTransformInfo->sRPC.adfLINE_DEN_COEFF );
 #endif
 
     // RPCs are using the center of upper left pixel = 0,0 convention
-    // convert to top left corner = 0,0 convention used in GDAL
-    *pdfPixel = dfResultX * psRPCTransformInfo->sRPC.dfSAMP_SCALE + psRPCTransformInfo->sRPC.dfSAMP_OFF + 0.5;
-    *pdfLine = dfResultY * psRPCTransformInfo->sRPC.dfLINE_SCALE + psRPCTransformInfo->sRPC.dfLINE_OFF + 0.5;
+    // convert to top left corner = 0,0 convention used in GDAL.
+    *pdfPixel = dfResultX * psRPCTransformInfo->sRPC.dfSAMP_SCALE
+        + psRPCTransformInfo->sRPC.dfSAMP_OFF + 0.5;
+    *pdfLine = dfResultY * psRPCTransformInfo->sRPC.dfLINE_SCALE
+        + psRPCTransformInfo->sRPC.dfLINE_OFF + 0.5;
 }
 
 /************************************************************************/
@@ -413,11 +470,13 @@ static const char* GDALSerializeRPCDEMResample(DEMResampleAlg eResampleAlg)
 /************************************************************************/
 
 static
-void* GDALCreateSimilarRPCTransformer( void *hTransformArg, double dfRatioX, double dfRatioY )
+void* GDALCreateSimilarRPCTransformer( void *hTransformArg,
+                                       double dfRatioX, double dfRatioY )
 {
     VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarRPCTransformer", NULL );
 
-    GDALRPCTransformInfo *psInfo = (GDALRPCTransformInfo *) hTransformArg;
+    GDALRPCTransformInfo *psInfo =
+        static_cast<GDALRPCTransformInfo *>(hTransformArg);
 
     GDALRPCInfo sRPC;
     memcpy(&sRPC, &(psInfo->sRPC), sizeof(GDALRPCInfo));
@@ -437,20 +496,25 @@ void* GDALCreateSimilarRPCTransformer( void *hTransformArg, double dfRatioX, dou
                                    CPLSPrintf("%.18g", psInfo->dfHeightScale));
     if( psInfo->pszDEMPath != NULL )
     {
-        papszOptions = CSLSetNameValue(papszOptions, "RPC_DEM", psInfo->pszDEMPath);
-        papszOptions = CSLSetNameValue(papszOptions, "RPC_DEMINTERPOLATION",
-                                       GDALSerializeRPCDEMResample(psInfo->eResampleAlg));
+        papszOptions =
+            CSLSetNameValue(papszOptions, "RPC_DEM", psInfo->pszDEMPath);
+        papszOptions =
+            CSLSetNameValue(papszOptions, "RPC_DEMINTERPOLATION",
+                            GDALSerializeRPCDEMResample(psInfo->eResampleAlg));
         if( psInfo->bHasDEMMissingValue )
-            papszOptions = CSLSetNameValue(papszOptions, "RPC_DEM_MISSING_VALUE",
-                                           CPLSPrintf("%.18g", psInfo->dfDEMMissingValue)) ;
-        papszOptions = CSLSetNameValue(papszOptions, "RPC_DEM_APPLY_VDATUM_SHIFT",
-                                           (psInfo->bApplyDEMVDatumShift) ? "TRUE" : "FALSE") ;
+            papszOptions =
+                CSLSetNameValue(papszOptions, "RPC_DEM_MISSING_VALUE",
+                                CPLSPrintf("%.18g", psInfo->dfDEMMissingValue));
+        papszOptions =
+            CSLSetNameValue(papszOptions, "RPC_DEM_APPLY_VDATUM_SHIFT",
+                            (psInfo->bApplyDEMVDatumShift) ? "TRUE" : "FALSE") ;
     }
     papszOptions = CSLSetNameValue(papszOptions, "RPC_MAX_ITERATIONS",
                                    CPLSPrintf("%d", psInfo->nMaxIterations));
 
-    GDALRPCTransformInfo* psNewInfo = (GDALRPCTransformInfo*) GDALCreateRPCTransformer( &sRPC,
-           psInfo->bReversed, psInfo->dfPixErrThreshold, papszOptions );
+    GDALRPCTransformInfo* psNewInfo =
+        static_cast<GDALRPCTransformInfo*>(GDALCreateRPCTransformer(
+            &sRPC, psInfo->bReversed, psInfo->dfPixErrThreshold, papszOptions));
     CSLDestroy(papszOptions);
 
     return psNewInfo;
@@ -461,41 +525,45 @@ void* GDALCreateSimilarRPCTransformer( void *hTransformArg, double dfRatioX, dou
 /************************************************************************/
 
 static
-int GDALRPCGetDEMHeight( const GDALRPCTransformInfo *psTransform,
-                         const double dfXIn, const double dfYIn, double* pdfDEMH );
+int GDALRPCGetDEMHeight( GDALRPCTransformInfo *psTransform,
+                         const double dfXIn, const double dfYIn,
+                         double* pdfDEMH );
 
-static bool GDALRPCGetHeightAtLongLat( const GDALRPCTransformInfo *psTransform,
+static bool GDALRPCGetHeightAtLongLat( GDALRPCTransformInfo *psTransform,
                                        const double dfXIn, const double dfYIn,
                                        double* pdfHeight,
-                                       double* pdfDEMPixel = NULL, double* pdfDEMLine = NULL)
+                                       double* pdfDEMPixel = NULL,
+                                       double* pdfDEMLine = NULL )
 {
     double dfVDatumShift = 0.0;
-    double dfDEMH = 0;
-    if(psTransform->poDS)
+    double dfDEMH = 0.0;
+    if( psTransform->poDS )
     {
-        double dfX, dfY;
+        double dfX = 0.0;
+        double dfY = 0.0;
         double dfXTemp = dfXIn;
         double dfYTemp = dfYIn;
-        //check if dem is not in WGS84 and transform points padfX[i], padfY[i]
-        if(psTransform->poCT)
+        // Check if dem is not in WGS84 and transform points padfX[i], padfY[i].
+        if( psTransform->poCT )
         {
-            double dfZ = 0;
-            if (!psTransform->poCT->Transform(1, &dfXTemp, &dfYTemp, &dfZ))
+            double dfZ = 0.0;
+            if( !psTransform->poCT->Transform(1, &dfXTemp, &dfYTemp, &dfZ) )
             {
                 return false;
             }
 
             // We must take the opposite since poCT transforms from
             // WGS84 to geoid. And we are going to do the reverse:
-            // take an elevation over the geoid and transforms it to WGS84
+            // take an elevation over the geoid and transforms it to WGS84.
             if( psTransform->bApplyDEMVDatumShift )
                 dfVDatumShift = -dfZ;
         }
 
         bool bRetried = false;
 retry:
-        GDALApplyGeoTransform( (double*)(psTransform->adfDEMReverseGeoTransform),
-                                dfXTemp, dfYTemp, &dfX, &dfY );
+        GDALApplyGeoTransform(
+            psTransform->adfDEMReverseGeoTransform,
+            dfXTemp, dfYTemp, &dfX, &dfY );
         if( pdfDEMPixel )
             *pdfDEMPixel = dfX;
         if( pdfDEMLine )
@@ -503,15 +571,20 @@ retry:
 
         if( !GDALRPCGetDEMHeight( psTransform, dfX, dfY, &dfDEMH) )
         {
-            // Try to handle the case where the DEM is in LL WGS84 and spans over [-180,180],
-            // (or very close to it ), presumably with much hole in the middle if using VRT,
-            // and the longitude goes beyond that interval
-            if( !bRetried && psTransform->poCT == NULL && (dfXIn >= 180 || dfXIn <= -180) )
+            // Try to handle the case where the DEM is in LL WGS84 and spans
+            // over [-180,180], (or very close to it ), presumably with much
+            // hole in the middle if using VRT, and the longitude goes beyond
+            // that interval.
+            if( !bRetried && psTransform->poCT == NULL &&
+                (dfXIn >= 180.0 || dfXIn <= -180.0) )
             {
-                int nRasterXSize = psTransform->poDS->GetRasterXSize();
-                double dfMinDEMLong = psTransform->adfDEMGeoTransform[0];
-                double dfMaxDEMLong = psTransform->adfDEMGeoTransform[0] + nRasterXSize * psTransform->adfDEMGeoTransform[1];
-                if( fabs( dfMinDEMLong - -180 ) < 0.1 && fabs( dfMaxDEMLong - 180 ) < 0.1 )
+                const int nRasterXSize = psTransform->poDS->GetRasterXSize();
+                const double dfMinDEMLong = psTransform->adfDEMGeoTransform[0];
+                const double dfMaxDEMLong =
+                    psTransform->adfDEMGeoTransform[0]
+                    + nRasterXSize * psTransform->adfDEMGeoTransform[1];
+                if( fabs( dfMinDEMLong - -180 ) < 0.1 &&
+                    fabs( dfMaxDEMLong - 180 ) < 0.1 )
                 {
                     if( dfXIn >= 180 )
                     {
@@ -535,9 +608,13 @@ retry:
                 return false;
             }
         }
+#ifdef DEBUG_VERBOSE_EXTRACT_DEM
+        CPLDebug("RPC_DEM", "X=%f, Y=%f -> Z=%f", dfX, dfY, dfDEMH);
+#endif
     }
 
-    *pdfHeight = dfVDatumShift + (psTransform->dfHeightOffset + dfDEMH * psTransform->dfHeightScale);
+    *pdfHeight = dfVDatumShift + (psTransform->dfHeightOffset +
+                                  dfDEMH * psTransform->dfHeightScale);
     return true;
 }
 
@@ -577,8 +654,10 @@ retry:
  * and the GeoTIFF RPC document http://geotiff.maptools.org/rpc_prop.html .
  *
  * <ul>
- * <li>ERR_BIAS: Error - Bias. The RMS bias error in meters per horizontal axis of all points in the image (-1.0 if unknown)
- * <li>ERR_RAND: Error - Random. RMS random error in meters per horizontal axis of each point in the image (-1.0 if unknown)
+ * <li>ERR_BIAS: Error - Bias. The RMS bias error in meters per horizontal axis
+ * of all points in the image (-1.0 if unknown)
+ * <li>ERR_RAND: Error - Random. RMS random error in meters per horizontal axis
+ * of each point in the image (-1.0 if unknown)
  * <li>LINE_OFF: Line Offset
  * <li>SAMP_OFF: Sample Offset
  * <li>LAT_OFF: Geodetic Latitude Offset
@@ -589,10 +668,16 @@ retry:
  * <li>LAT_SCALE: Geodetic Latitude Scale
  * <li>LONG_SCALE: Geodetic Longitude Scale
  * <li>HEIGHT_SCALE: Geodetic Height Scale
- * <li>LINE_NUM_COEFF (1-20): Line Numerator Coefficients. Twenty coefficients for the polynomial in the Numerator of the rn equation. (space separated)
- * <li>LINE_DEN_COEFF (1-20): Line Denominator Coefficients. Twenty coefficients for the polynomial in the Denominator of the rn equation. (space separated)
- * <li>SAMP_NUM_COEFF (1-20): Sample Numerator Coefficients. Twenty coefficients for the polynomial in the Numerator of the cn equation. (space separated)
- * <li>SAMP_DEN_COEFF (1-20): Sample Denominator Coefficients. Twenty coefficients for the polynomial in the Denominator of the cn equation. (space separated)
+
+ * <li>LINE_NUM_COEFF (1-20): Line Numerator Coefficients. Twenty coefficients
+ * for the polynomial in the Numerator of the rn equation. (space separated)
+ * <li>LINE_DEN_COEFF (1-20): Line Denominator Coefficients. Twenty coefficients
+ * for the polynomial in the Denominator of the rn equation. (space separated)
+ * <li>SAMP_NUM_COEFF (1-20): Sample Numerator Coefficients. Twenty coefficients
+ * for the polynomial in the Numerator of the cn equation. (space separated)
+ * <li>SAMP_DEN_COEFF (1-20): Sample Denominator Coefficients. Twenty
+ * coefficients for the polynomial in the Denominator of the cn equation. (space
+ * separated)
  * </ul>
  *
  * The transformer normally maps from pixel/line/height to long/lat/height space
@@ -607,13 +692,13 @@ retry:
  * will not avoid all error, but will cause the operation to run for the maximum
  * number of iterations.
  *
- * Starting with GDAL 2.1, debugging of the RPC inverse transformer can be done by setting the
- * RPC_INVERSE_VERBOSE configuration option to YES (in which case extra debug
- * information will be displayed in the "RPC" debug category, so requiring CPL_DEBUG
- * to be also set) and/or by setting RPC_INVERSE_LOG to a filename that will
- * contain the content of iterations (this last option only makes sense when
- * debugging point by point, since each time RPCInverseTransformPoint() is called,
- * the file is rewritten)
+ * Starting with GDAL 2.1, debugging of the RPC inverse transformer can be done
+ * by setting the RPC_INVERSE_VERBOSE configuration option to YES (in which case
+ * extra debug information will be displayed in the "RPC" debug category, so
+ * requiring CPL_DEBUG to be also set) and/or by setting RPC_INVERSE_LOG to a
+ * filename that will contain the content of iterations (this last option only
+ * makes sense when debugging point by point, since each time
+ * RPCInverseTransformPoint() is called, the file is rewritten).
  *
  * Additional options to the transformer can be supplied in papszOptions.
  *
@@ -626,7 +711,8 @@ retry:
  * an average height above sea level for ground in the target scene.
  *
  * <li> RPC_HEIGHT_SCALE: a factor used to multiply heights above ground.
- * Useful when elevation offsets of the DEM are not expressed in meters. (GDAL >= 1.8.0)
+ * Useful when elevation offsets of the DEM are not expressed in meters. (GDAL
+ * >= 1.8.0)
  *
  * <li> RPC_DEM: the name of a GDAL dataset (a DEM file typically) used to
  * extract elevation offsets from. In this situation the Z passed into the
@@ -641,11 +727,12 @@ retry:
  * cover the requested coordinate. When not specified, missing values will cause
  * a failed transform. (GDAL >= 1.11.2)
  *
- * <li> RPC_DEM_APPLY_VDATUM_SHIFT: whether the vertical component of a compound SRS
- * for the DEM should be used (when it is present). This is useful so as to be able to transform the
- * "raw" values from the DEM expressed with respect to a geoid to the heights with
- * respect to the WGS84 ellipsoid. When this is enabled, the GTIFF_REPORT_COMPD_CS configuration
- * option will be also set temporarily so as to get the vertical information from GeoTIFF
+ * <li> RPC_DEM_APPLY_VDATUM_SHIFT: whether the vertical component of a compound
+ * SRS for the DEM should be used (when it is present). This is useful so as to
+ * be able to transform the "raw" values from the DEM expressed with respect to
+ * a geoid to the heights with respect to the WGS84 ellipsoid. When this is
+ * enabled, the GTIFF_REPORT_COMPD_CS configuration option will be also set
+ * temporarily so as to get the vertical information from GeoTIFF
  * files. Defaults to TRUE. (GDAL >= 2.1.0)
  *
  * <li> RPC_PIXEL_ERROR_THRESHOLD: overrides the dfPixErrThreshold parameter, ie
@@ -653,9 +740,9 @@ retry:
  * iterative solution of pixel/line to lat/long computations (the other way
  * is always exact given the equations).  (GDAL >= 2.1.0)
  *
- * <li> RPC_MAX_ITERATIONS: maximum number of iterations allowed in the iterative
- * solution of pixel/line to lat/long computations. Default value is 10
- * in the absence of a DEM, or 20 if there is a DEM.  (GDAL >= 2.1.0)
+ * <li> RPC_MAX_ITERATIONS: maximum number of iterations allowed in the
+ * iterative solution of pixel/line to lat/long computations. Default value is
+ * 10 in the absence of a DEM, or 20 if there is a DEM.  (GDAL >= 2.1.0)
  *
  * </ul>
  *
@@ -668,8 +755,9 @@ retry:
  * iterative solution of pixel/line to lat/long computations (the other way
  * is always exact given the equations). Starting with GDAL 2.1, this may also
  * be set through the RPC_PIXEL_ERROR_THRESHOLD transformer option.
+ * If a negative or null value is provided, then this defaults to 0.1 pixel.
  *
- * @param papszOptions Other transformer options (i.e. RPC_HEIGHT=<z>).
+ * @param papszOptions Other transformer options (i.e. RPC_HEIGHT=z).
  *
  * @return transformer callback data (deallocate with GDALDestroyTransformer()).
  */
@@ -679,27 +767,28 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
                                 char **papszOptions )
 
 {
-    GDALRPCTransformInfo *psTransform;
-
 /* -------------------------------------------------------------------- */
 /*      Initialize core info.                                           */
 /* -------------------------------------------------------------------- */
-    psTransform = (GDALRPCTransformInfo *)
-        CPLCalloc(sizeof(GDALRPCTransformInfo),1);
+    GDALRPCTransformInfo *psTransform = static_cast<GDALRPCTransformInfo *>(
+        CPLCalloc(sizeof(GDALRPCTransformInfo), 1));
 
     memcpy( &(psTransform->sRPC), psRPCInfo, sizeof(GDALRPCInfo) );
     psTransform->bReversed = bReversed;
-    const char* pszPixErrThreshold = CSLFetchNameValue( papszOptions, "RPC_PIXEL_ERROR_THRESHOLD" );
+    const char* pszPixErrThreshold =
+        CSLFetchNameValue( papszOptions, "RPC_PIXEL_ERROR_THRESHOLD" );
     if( pszPixErrThreshold != NULL )
         psTransform->dfPixErrThreshold = CPLAtof(pszPixErrThreshold);
     else if( dfPixErrThreshold > 0 )
         psTransform->dfPixErrThreshold = dfPixErrThreshold;
     else
-        psTransform->dfPixErrThreshold = 0.1;
+        psTransform->dfPixErrThreshold = DEFAULT_PIX_ERR_THRESHOLD;
     psTransform->dfHeightOffset = 0.0;
     psTransform->dfHeightScale = 1.0;
 
-    memcpy( psTransform->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
+    memcpy( psTransform->sTI.abySignature,
+            GDAL_GTI2_SIGNATURE,
+            strlen(GDAL_GTI2_SIGNATURE) );
     psTransform->sTI.pszClassName = "GDALRPCTransformer";
     psTransform->sTI.pfnTransform = GDALRPCTransform;
     psTransform->sTI.pfnCleanup = GDALDestroyRPCTransformer;
@@ -707,12 +796,23 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
     psTransform->sTI.pfnCreateSimilar = GDALCreateSimilarRPCTransformer;
 
 #ifdef USE_SSE2_OPTIM
-    // Make sure padfCoeffs is aligned on a 16-byte boundary for SSE2 aligned loads
-    psTransform->padfCoeffs = psTransform->adfDoubles + (((size_t)psTransform->adfDoubles) % 16) / 8;
-    memcpy(psTransform->padfCoeffs, psRPCInfo->adfLINE_NUM_COEFF, 20 * sizeof(double));
-    memcpy(psTransform->padfCoeffs+20, psRPCInfo->adfLINE_DEN_COEFF, 20 * sizeof(double));
-    memcpy(psTransform->padfCoeffs+40, psRPCInfo->adfSAMP_NUM_COEFF, 20 * sizeof(double));
-    memcpy(psTransform->padfCoeffs+60, psRPCInfo->adfSAMP_DEN_COEFF, 20 * sizeof(double));
+    // Make sure padfCoeffs is aligned on a 16-byte boundary for SSE2 aligned
+    // loads.
+    psTransform->padfCoeffs =
+        psTransform->adfDoubles +
+        (((GUIntptr_t)psTransform->adfDoubles) % 16) / 8;
+    memcpy(psTransform->padfCoeffs,
+           psRPCInfo->adfLINE_NUM_COEFF,
+           20 * sizeof(double));
+    memcpy(psTransform->padfCoeffs+20,
+           psRPCInfo->adfLINE_DEN_COEFF,
+           20 * sizeof(double));
+    memcpy(psTransform->padfCoeffs+40,
+           psRPCInfo->adfSAMP_NUM_COEFF,
+           20 * sizeof(double));
+    memcpy(psTransform->padfCoeffs+60,
+           psRPCInfo->adfSAMP_DEN_COEFF,
+           20 * sizeof(double));
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -726,7 +826,8 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 /* -------------------------------------------------------------------- */
 /*                       The "height scale"                             */
 /* -------------------------------------------------------------------- */
-    const char *pszHeightScale = CSLFetchNameValue( papszOptions, "RPC_HEIGHT_SCALE" );
+    const char *pszHeightScale =
+        CSLFetchNameValue(papszOptions, "RPC_HEIGHT_SCALE");
     if( pszHeightScale != NULL )
         psTransform->dfHeightScale = CPLAtof(pszHeightScale);
 
@@ -740,23 +841,32 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 /* -------------------------------------------------------------------- */
 /*                      The DEM interpolation                           */
 /* -------------------------------------------------------------------- */
-    const char *pszDEMInterpolation = CSLFetchNameValueDef( papszOptions, "RPC_DEMINTERPOLATION", "bilinear" );
-    if(EQUAL(pszDEMInterpolation, "near" ))
+    const char *pszDEMInterpolation =
+        CSLFetchNameValueDef(papszOptions, "RPC_DEMINTERPOLATION", "bilinear");
+    if( EQUAL(pszDEMInterpolation, "near" ) )
+    {
         psTransform->eResampleAlg = DRA_NearestNeighbour;
-    else if(EQUAL(pszDEMInterpolation, "bilinear" ))
+    }
+    else if( EQUAL(pszDEMInterpolation, "bilinear" ) )
+    {
         psTransform->eResampleAlg = DRA_Bilinear;
-    else if(EQUAL(pszDEMInterpolation, "cubic" ))
+    }
+    else if( EQUAL(pszDEMInterpolation, "cubic") )
+    {
         psTransform->eResampleAlg = DRA_Cubic;
+    }
     else
     {
-        CPLDebug("RPC", "Unknown interpolation %s. Defaulting to bilinear", pszDEMInterpolation);
+        CPLDebug("RPC", "Unknown interpolation %s. Defaulting to bilinear",
+                 pszDEMInterpolation);
         psTransform->eResampleAlg = DRA_Bilinear;
     }
 
 /* -------------------------------------------------------------------- */
 /*                       The DEM missing value                          */
 /* -------------------------------------------------------------------- */
-    const char *pszDEMMissingValue = CSLFetchNameValue( papszOptions, "RPC_DEM_MISSING_VALUE" );
+    const char *pszDEMMissingValue =
+        CSLFetchNameValue(papszOptions, "RPC_DEM_MISSING_VALUE");
     if( pszDEMMissingValue != NULL )
     {
         psTransform->bHasDEMMissingValue = TRUE;
@@ -766,9 +876,8 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 /* -------------------------------------------------------------------- */
 /*      Whether to apply vdatum shift                                   */
 /* -------------------------------------------------------------------- */
-    psTransform->bApplyDEMVDatumShift = CSLFetchBoolean(
-        papszOptions, "RPC_DEM_APPLY_VDATUM_SHIFT", TRUE );
-
+    psTransform->bApplyDEMVDatumShift =
+        CPLFetchBool( papszOptions, "RPC_DEM_APPLY_VDATUM_SHIFT", true );
 
     psTransform->nMaxIterations = atoi( CSLFetchNameValueDef(
         papszOptions, "RPC_MAX_ITERATIONS", "0" ) );
@@ -776,7 +885,8 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 /* -------------------------------------------------------------------- */
 /*      Debug                                                           */
 /* -------------------------------------------------------------------- */
-    psTransform->bRPCInverseVerbose = CPLTestBool( CPLGetConfigOption("RPC_INVERSE_VERBOSE", "NO") );
+    psTransform->bRPCInverseVerbose =
+        CPLTestBool( CPLGetConfigOption("RPC_INVERSE_VERBOSE", "NO") );
     const char* pszRPCInverseLog = CPLGetConfigOption("RPC_INVERSE_LOG", NULL);
     if( pszRPCInverseLog != NULL )
         psTransform->pszRPCInverseLog = CPLStrdup(pszRPCInverseLog);
@@ -785,8 +895,11 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 /*      Establish a reference point for calcualating an affine          */
 /*      geotransform approximate transformation.                        */
 /* -------------------------------------------------------------------- */
-    double adfGTFromLL[6], dfRefPixel = -1.0, dfRefLine = -1.0;
-    double dfRefLong = 0.0, dfRefLat = 0.0;
+    double adfGTFromLL[6] = {};
+    double dfRefPixel = -1.0;
+    double dfRefLine = -1.0;
+    double dfRefLong = 0.0;
+    double dfRefLat = 0.0;
 
     if( psRPCInfo->dfMIN_LONG != -180 || psRPCInfo->dfMAX_LONG != 180 )
     {
@@ -795,9 +908,9 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 
         double dfX = dfRefLong;
         double dfY = dfRefLat;
-        double dfZ = 0;
-        int nSuccess;
-        // Try with DEM first
+        double dfZ = 0.0;
+        int nSuccess = 0;
+        // Try with DEM first.
         if( GDALRPCTransform( psTransform, !(psTransform->bReversed), 1,
                           &dfX, &dfY, &dfZ, &nSuccess) )
         {
@@ -821,9 +934,9 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 
         double dfX = dfRefLong;
         double dfY = dfRefLat;
-        double dfZ = 0;
-        int nSuccess;
-        // Try with DEM first
+        double dfZ = 0.0;
+        int nSuccess = 0;
+        // Try with DEM first.
         if( GDALRPCTransform( psTransform, !(psTransform->bReversed), 1,
                                &dfX, &dfY, &dfZ, &nSuccess) )
         {
@@ -838,20 +951,25 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
     }
 
     psTransform->dfRefZ = 0.0;
-    GDALRPCGetHeightAtLongLat(psTransform, dfRefLong, dfRefLat, &psTransform->dfRefZ);
+    GDALRPCGetHeightAtLongLat(psTransform, dfRefLong, dfRefLat,
+                              &psTransform->dfRefZ);
 
 /* -------------------------------------------------------------------- */
 /*      Transform nearby locations to establish affine direction        */
 /*      vectors.                                                        */
 /* -------------------------------------------------------------------- */
-    double dfRefPixelDelta, dfRefLineDelta, dfLLDelta = 0.0001;
+    double dfRefPixelDelta = 0.0;
+    double dfRefLineDelta = 0.0;
+    double dfLLDelta = 0.0001;
 
-    RPCTransformPoint( psTransform, dfRefLong+dfLLDelta, dfRefLat, psTransform->dfRefZ,
+    RPCTransformPoint( psTransform, dfRefLong+dfLLDelta, dfRefLat,
+                       psTransform->dfRefZ,
                        &dfRefPixelDelta, &dfRefLineDelta );
     adfGTFromLL[1] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
     adfGTFromLL[4] = (dfRefLineDelta - dfRefLine) / dfLLDelta;
 
-    RPCTransformPoint( psTransform, dfRefLong, dfRefLat+dfLLDelta, psTransform->dfRefZ,
+    RPCTransformPoint( psTransform, dfRefLong, dfRefLat+dfLLDelta,
+                       psTransform->dfRefZ,
                        &dfRefPixelDelta, &dfRefLineDelta );
     adfGTFromLL[2] = (dfRefPixelDelta - dfRefPixel) / dfLLDelta;
     adfGTFromLL[5] = (dfRefLineDelta - dfRefLine) / dfLLDelta;
@@ -861,7 +979,8 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
     adfGTFromLL[3] = dfRefLine
         - adfGTFromLL[4] * dfRefLong - adfGTFromLL[5] * dfRefLat;
 
-    if( !GDALInvGeoTransform( adfGTFromLL, psTransform->adfPLToLatLongGeoTransform) )
+    if( !GDALInvGeoTransform(adfGTFromLL,
+                             psTransform->adfPLToLatLongGeoTransform) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
         GDALDestroyRPCTransformer(psTransform);
@@ -874,20 +993,24 @@ void *GDALCreateRPCTransformer( GDALRPCInfo *psRPCInfo, int bReversed,
 /*                 GDALDestroyReprojectionTransformer()                 */
 /************************************************************************/
 
+/** Destroy RPC tranformer */
 void GDALDestroyRPCTransformer( void *pTransformAlg )
 
 {
     if( pTransformAlg == NULL )
         return;
 
-    GDALRPCTransformInfo *psTransform = (GDALRPCTransformInfo *) pTransformAlg;
+    GDALRPCTransformInfo *psTransform =
+        static_cast<GDALRPCTransformInfo *>(pTransformAlg);
 
     CPLFree( psTransform->pszDEMPath );
 
-    if(psTransform->poDS)
+    if( psTransform->poDS )
         GDALClose(psTransform->poDS);
-    if(psTransform->poCT)
-        OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)psTransform->poCT);
+    CPLFree(psTransform->padfDEMBuffer);
+    if( psTransform->poCT )
+        OCTDestroyCoordinateTransformation(
+            reinterpret_cast<OGRCoordinateTransformationH>(psTransform->poCT));
     CPLFree( psTransform->pszRPCInverseLog );
 
     CPLFree( pTransformAlg );
@@ -898,29 +1021,28 @@ void GDALDestroyRPCTransformer( void *pTransformAlg )
 /************************************************************************/
 
 static bool
-RPCInverseTransformPoint( const GDALRPCTransformInfo *psTransform,
+RPCInverseTransformPoint( GDALRPCTransformInfo *psTransform,
                           double dfPixel, double dfLine, double dfUserHeight,
                           double *pdfLong, double *pdfLat )
 
 {
     // Memo:
-    // Known to work with 40 iterations with DEM on all points (int coord and +0.5,+0.5 shift)
-    // of flock1.20160216_041050_0905.tif, especially on (0,0)
-
-    double dfResultX, dfResultY;
-    int    iIter;
+    // Known to work with 40 iterations with DEM on all points (int coord and
+    // +0.5,+0.5 shift) of flock1.20160216_041050_0905.tif, especially on (0,0).
 
 /* -------------------------------------------------------------------- */
 /*      Compute an initial approximation based on linear                */
 /*      interpolation from our reference point.                         */
 /* -------------------------------------------------------------------- */
-    dfResultX = psTransform->adfPLToLatLongGeoTransform[0]
-        + psTransform->adfPLToLatLongGeoTransform[1] * dfPixel
-        + psTransform->adfPLToLatLongGeoTransform[2] * dfLine;
+    double dfResultX =
+        psTransform->adfPLToLatLongGeoTransform[0] +
+        psTransform->adfPLToLatLongGeoTransform[1] * dfPixel +
+        psTransform->adfPLToLatLongGeoTransform[2] * dfLine;
 
-    dfResultY = psTransform->adfPLToLatLongGeoTransform[3]
-        + psTransform->adfPLToLatLongGeoTransform[4] * dfPixel
-        + psTransform->adfPLToLatLongGeoTransform[5] * dfLine;
+    double dfResultY =
+        psTransform->adfPLToLatLongGeoTransform[3] +
+        psTransform->adfPLToLatLongGeoTransform[4] * dfPixel +
+        psTransform->adfPLToLatLongGeoTransform[5] * dfLine;
 
     if( psTransform->bRPCInverseVerbose )
     {
@@ -930,7 +1052,9 @@ RPCInverseTransformPoint( const GDALRPCTransformInfo *psTransform,
     VSILFILE* fpLog = NULL;
     if( psTransform->pszRPCInverseLog )
     {
-        fpLog = VSIFOpenL( CPLResetExtension(psTransform->pszRPCInverseLog, "csvt"), "wb" );
+        fpLog =
+            VSIFOpenL( CPLResetExtension(psTransform->pszRPCInverseLog, "csvt"),
+                       "wb" );
         if( fpLog != NULL )
         {
             VSIFPrintfL( fpLog, "Integer,Real,Real,Real,String,Real,Real\n" );
@@ -938,40 +1062,51 @@ RPCInverseTransformPoint( const GDALRPCTransformInfo *psTransform,
         }
         fpLog = VSIFOpenL( psTransform->pszRPCInverseLog, "wb" );
         if( fpLog != NULL )
-            VSIFPrintfL( fpLog, "iter,long,lat,height,WKT,error_pixel_x,error_pixel_y\n" );
+            VSIFPrintfL(
+                fpLog,
+                "iter,long,lat,height,WKT,error_pixel_x,error_pixel_y\n" );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Now iterate, trying to find a closer LL location that will      */
 /*      back transform to the indicated pixel and line.                 */
 /* -------------------------------------------------------------------- */
-    double dfPixelDeltaX=0.0, dfPixelDeltaY=0.0;
-    double dfLastResultX = 0.0, dfLastResultY = 0.0;
-    double dfLastPixelDeltaX = 0.0, dfLastPixelDeltaY = 0.0;
+    double dfPixelDeltaX = 0.0;
+    double dfPixelDeltaY = 0.0;
+    double dfLastResultX = 0.0;
+    double dfLastResultY = 0.0;
+    double dfLastPixelDeltaX = 0.0;
+    double dfLastPixelDeltaY = 0.0;
     double dfDEMH = 0.0;
     bool bLastPixelDeltaValid = false;
-    const int nMaxIterations = (psTransform->nMaxIterations > 0) ? psTransform->nMaxIterations :
-                               (psTransform->poDS != NULL) ? 20 : 10;
+    const int nMaxIterations =
+        (psTransform->nMaxIterations > 0) ? psTransform->nMaxIterations :
+        (psTransform->poDS != NULL) ? 20 : 10;
     int nCountConsecutiveErrorBelow2 = 0;
 
-    for( iIter = 0; iIter < nMaxIterations; iIter++ )
+    int iIter = 0;  // Used after for.
+    for( ; iIter < nMaxIterations; iIter++ )
     {
-        double dfBackPixel, dfBackLine;
+        double dfBackPixel = 0.0;
+        double dfBackLine = 0.0;
 
-        // Update DEMH
-        dfDEMH = 0;
-        double dfDEMPixel = 0.0, dfDEMLine = 0.0;
+        // Update DEMH.
+        dfDEMH = 0.0;
+        double dfDEMPixel = 0.0;
+        double dfDEMLine = 0.0;
         if( !GDALRPCGetHeightAtLongLat(psTransform, dfResultX, dfResultY,
-                                        &dfDEMH, &dfDEMPixel, &dfDEMLine) )
+                                       &dfDEMH, &dfDEMPixel, &dfDEMLine) )
         {
             if( psTransform->poDS )
             {
-                CPLDebug("RPC", "DEM (pixel, line) = (%g, %g)", dfDEMPixel, dfDEMLine);
+                CPLDebug(
+                    "RPC", "DEM (pixel, line) = (%g, %g)",
+                    dfDEMPixel, dfDEMLine);
             }
 
             // The first time, the guess might be completely out of the
             // validity of the DEM, so pickup the "reference Z" as the
-            // first guess or the closest point of the DEM by snapping to it
+            // first guess or the closest point of the DEM by snapping to it.
             if( iIter == 0 )
             {
                 bool bUseRefZ = true;
@@ -985,26 +1120,30 @@ RPCInverseTransformPoint( const GDALRPCTransformInfo *psTransform,
                         dfDEMLine = psTransform->poDS->GetRasterYSize() - 0.5;
                     else if( dfDEMPixel < 0 )
                         dfDEMPixel = 0.5;
-                    if( GDALRPCGetDEMHeight( psTransform, dfDEMPixel, dfDEMLine, &dfDEMH) )
+                    if( GDALRPCGetDEMHeight( psTransform, dfDEMPixel,
+                                             dfDEMLine, &dfDEMH) )
                     {
                         bUseRefZ = false;
-                        CPLDebug("RPC", "Iteration %d for (pixel, line) = (%g, %g): "
-                                "No elevation value at %.15g %.15g. "
-                                "Using elevation %g at DEM (pixel, line) = (%g, %g) (snapping to boundaries) instead",
-                                iIter, dfPixel, dfLine,
-                                dfResultX, dfResultY,
-                                dfDEMH, dfDEMPixel, dfDEMLine );
+                        CPLDebug(
+                            "RPC", "Iteration %d for (pixel, line) = (%g, %g): "
+                            "No elevation value at %.15g %.15g. "
+                            "Using elevation %g at DEM (pixel, line) = "
+                            "(%g, %g) (snapping to boundaries) instead",
+                            iIter, dfPixel, dfLine,
+                            dfResultX, dfResultY,
+                            dfDEMH, dfDEMPixel, dfDEMLine );
                     }
                 }
                 if( bUseRefZ )
                 {
                     dfDEMH = psTransform->dfRefZ;
-                    CPLDebug("RPC", "Iteration %d for (pixel, line) = (%g, %g): "
-                            "No elevation value at %.15g %.15g. "
-                            "Using elevation %g of reference point instead",
-                            iIter, dfPixel, dfLine,
-                            dfResultX, dfResultY,
-                            dfDEMH);
+                    CPLDebug(
+                        "RPC", "Iteration %d for (pixel, line) = (%g, %g): "
+                        "No elevation value at %.15g %.15g. "
+                        "Using elevation %g of reference point instead",
+                        iIter, dfPixel, dfLine,
+                        dfResultX, dfResultY,
+                        dfDEMH);
                 }
             }
             else
@@ -1027,18 +1166,22 @@ RPCInverseTransformPoint( const GDALRPCTransformInfo *psTransform,
 
         if( psTransform->bRPCInverseVerbose )
         {
-            CPLDebug( "RPC", "Iter %d: dfPixelDeltaX=%.02f, dfPixelDeltaY=%.02f, long=%f, lat=%f, height=%f",
-                      iIter, dfPixelDeltaX, dfPixelDeltaY,
-                      dfResultX, dfResultY, dfUserHeight + dfDEMH);
+            CPLDebug(
+                "RPC", "Iter %d: dfPixelDeltaX=%.02f, dfPixelDeltaY=%.02f, "
+                "long=%f, lat=%f, height=%f",
+                iIter, dfPixelDeltaX, dfPixelDeltaY,
+                dfResultX, dfResultY, dfUserHeight + dfDEMH);
         }
         if( fpLog != NULL )
         {
-            VSIFPrintfL( fpLog, "%d,%.12f,%.12f,%f,\"POINT(%.12f %.12f)\",%f,%f\n",
-                         iIter, dfResultX, dfResultY, dfUserHeight + dfDEMH,
-                         dfResultX, dfResultY, dfPixelDeltaX, dfPixelDeltaY);
+            VSIFPrintfL(
+                fpLog, "%d,%.12f,%.12f,%f,\"POINT(%.12f %.12f)\",%f,%f\n",
+                iIter, dfResultX, dfResultY, dfUserHeight + dfDEMH,
+                dfResultX, dfResultY, dfPixelDeltaX, dfPixelDeltaY);
         }
 
-        double dfError = MAX(ABS(dfPixelDeltaX), ABS(dfPixelDeltaY));
+        const double dfError =
+            std::max(std::abs(dfPixelDeltaX), std::abs(dfPixelDeltaY));
         if( dfError < psTransform->dfPixErrThreshold )
         {
             iIter = -1;
@@ -1049,31 +1192,39 @@ RPCInverseTransformPoint( const GDALRPCTransformInfo *psTransform,
             break;
         }
         else if( psTransform->poDS != NULL &&
-                 bLastPixelDeltaValid && dfPixelDeltaX * dfLastPixelDeltaX < 0 &&
+                 bLastPixelDeltaValid &&
+                 dfPixelDeltaX * dfLastPixelDeltaX < 0 &&
                  dfPixelDeltaY * dfLastPixelDeltaY < 0 )
         {
-            // When there is a DEM, if the error changes sign, we might oscillate
-            // forever, so take a mean position as a new guess
+            // When there is a DEM, if the error changes sign, we might
+            // oscillate forever, so take a mean position as a new guess.
             if( psTransform->bRPCInverseVerbose )
             {
-                CPLDebug( "RPC", "Oscillation detected. Taking mean of 2 previous results as new guess" );
+                CPLDebug(
+                    "RPC", "Oscillation detected. "
+                    "Taking mean of 2 previous results as new guess" );
             }
-            dfResultX = ( fabs(dfPixelDeltaX) * dfLastResultX + fabs(dfLastPixelDeltaX) * dfResultX ) /
-                          (fabs(dfPixelDeltaX) + fabs(dfLastPixelDeltaX));
-            dfResultY = ( fabs(dfPixelDeltaY) * dfLastResultY + fabs(dfLastPixelDeltaY) * dfResultY ) /
-                          (fabs(dfPixelDeltaY) + fabs(dfLastPixelDeltaY));
+            dfResultX =
+                ( fabs(dfPixelDeltaX) * dfLastResultX +
+                  fabs(dfLastPixelDeltaX) * dfResultX ) /
+                (fabs(dfPixelDeltaX) + fabs(dfLastPixelDeltaX));
+            dfResultY =
+                ( fabs(dfPixelDeltaY) * dfLastResultY +
+                  fabs(dfLastPixelDeltaY) * dfResultY ) /
+                (fabs(dfPixelDeltaY) + fabs(dfLastPixelDeltaY));
             bLastPixelDeltaValid = false;
             nCountConsecutiveErrorBelow2 = 0;
             continue;
         }
 
         double dfBoostFactor = 1.0;
-        if( psTransform->poDS != NULL && nCountConsecutiveErrorBelow2 >= 5 && dfError < 2 )
+        if( psTransform->poDS != NULL &&
+            nCountConsecutiveErrorBelow2 >= 5 && dfError < 2 )
         {
           // When there is a DEM, if we remain below a given threshold (somewhat
           // arbitrarily set to 2 pixels) for some time, apply a "boost factor"
           // for the new guessed result, in the hope we will go out of the
-          // somewhat current stuck situation
+          // somewhat current stuck situation.
           dfBoostFactor = 10;
           if( psTransform->bRPCInverseVerbose )
           {
@@ -1081,17 +1232,21 @@ RPCInverseTransformPoint( const GDALRPCTransformInfo *psTransform,
           }
         }
 
-        if ( dfError < 2 )
-            nCountConsecutiveErrorBelow2 ++;
+        if( dfError < 2 )
+            nCountConsecutiveErrorBelow2++;
         else
             nCountConsecutiveErrorBelow2 = 0;
 
-        double dfNewResultX = dfResultX
-            - dfPixelDeltaX * psTransform->adfPLToLatLongGeoTransform[1] * dfBoostFactor
-            - dfPixelDeltaY * psTransform->adfPLToLatLongGeoTransform[2] * dfBoostFactor;
-        double dfNewResultY = dfResultY
-            - dfPixelDeltaX * psTransform->adfPLToLatLongGeoTransform[4] * dfBoostFactor
-            - dfPixelDeltaY * psTransform->adfPLToLatLongGeoTransform[5] * dfBoostFactor;
+        const double dfNewResultX = dfResultX
+            - ( dfPixelDeltaX * psTransform->adfPLToLatLongGeoTransform[1] *
+                dfBoostFactor )
+            - ( dfPixelDeltaY * psTransform->adfPLToLatLongGeoTransform[2] *
+                dfBoostFactor );
+        const double dfNewResultY = dfResultY
+            - ( dfPixelDeltaX * psTransform->adfPLToLatLongGeoTransform[4] *
+                dfBoostFactor )
+            - ( dfPixelDeltaY * psTransform->adfPLToLatLongGeoTransform[5] *
+                dfBoostFactor );
 
         dfLastResultX = dfResultX;
         dfLastResultY = dfResultY;
@@ -1118,24 +1273,142 @@ RPCInverseTransformPoint( const GDALRPCTransformInfo *psTransform,
     return true;
 }
 
-
 static
-double BiCubicKernel(double dfVal)
+double BiCubicKernel( double dfVal )
+{
+    if( dfVal > 2.0 )
+        return 0.0;
+
+    const double xm1 = dfVal - 1.0;
+    const double xp1 = dfVal + 1.0;
+    const double xp2 = dfVal + 2.0;
+
+    const double a = xp2 <= 0.0 ? 0.0 : xp2 * xp2 * xp2;
+    const double b = xp1 <= 0.0 ? 0.0 : xp1 * xp1 * xp1;
+    const double c = dfVal <= 0.0 ? 0.0 : dfVal * dfVal * dfVal;
+    const double d = xm1 <= 0.0 ? 0.0 : xm1 * xm1 * xm1;
+
+    return
+        0.16666666666666666667 * (a - (4.0 * b) + (6.0 * c) - (4.0 * d));
+}
+
+/************************************************************************/
+/*                        GDALRPCExtractDEMWindow()                     */
+/************************************************************************/
+
+static bool GDALRPCExtractDEMWindow( GDALRPCTransformInfo *psTransform,
+                                     int nX, int nY, int nWidth, int nHeight,
+                                     double* padfOut )
 {
-	if ( dfVal > 2.0 )
-		return 0.0;
+    psTransform->nDEMExtractions++;
+    if( psTransform->padfDEMBuffer == NULL )
+    {
+        // Should only happen in case of failed memory allocation.
+        return psTransform->poDS->GetRasterBand(1)->
+                                  RasterIO(GF_Read, nX, nY, nWidth, nHeight,
+                                           padfOut, nWidth, nHeight,
+                                           GDT_Float64, 0, 0,
+                                           NULL) == CE_None;
+    }
 
-	double a, b, c, d;
-	double xm1 = dfVal - 1.0;
-	double xp1 = dfVal + 1.0;
-	double xp2 = dfVal + 2.0;
+    // Instead of reading just nWidth * nHeight pixels (with those being <= 4),
+    // target a larger buffer since small extractions can be costly, particular
+    // with VRT.
+    if( !(nX >= psTransform->nBufferX &&
+          nX + nWidth <= psTransform->nBufferX + psTransform->nBufferWidth &&
+          nY >= psTransform->nBufferY &&
+          nY + nHeight <= psTransform->nBufferY + psTransform->nBufferHeight ) )
+    {
+#ifdef DEBUG_VERBOSE_EXTRACT_DEM
+        CPLDebug("RPC", "Current request: %d,%d-%dx%d",
+                  nX, nY, nWidth, nHeight);
+        CPLDebug("RPC", "Hits in last DEM buffer: %d (%d pixels)",
+                 psTransform->nHitsInBuffer,
+                 psTransform->nBufferWidth * psTransform->nBufferHeight);
+        CPLDebug("RPC", "Last DEM buffer: %d,%d-%dx%d",
+                 psTransform->nBufferX,
+                 psTransform->nBufferY,
+                 psTransform->nBufferWidth,
+                 psTransform->nBufferHeight);
+#endif
+        const int nRasterXSize = psTransform->poDS->GetRasterXSize();
+        const int nRasterYSize = psTransform->poDS->GetRasterYSize();
+        // If we have only queried a few points, no need to extract on a large
+        // window We will progressively extend the window up to its maximum size
+        // if we extract a significant number of points.
+        int nRadius = psTransform->nBufferMaxRadius;
+        if( psTransform->nDEMExtractions <
+            psTransform->nBufferMaxRadius * psTransform->nBufferMaxRadius )
+        {
+            nRadius = static_cast<int> (
+                  sqrt(static_cast<double>(psTransform->nDEMExtractions)) );
+            CPLAssert( nRadius <= psTransform->nBufferMaxRadius );
+        }
+        // Check if there's some overlap between consecutive requests to decide
+        // if we must have a buffer around the interest window.
+        const int nDiffX = nX - psTransform->nLastQueriedX;
+        const int nDiffY = nY - psTransform->nLastQueriedY;
+        if( psTransform->nLastQueriedX >= 0 &&
+            (nDiffX > nRadius || -nDiffX > nRadius ||
+             nDiffY > nRadius || -nDiffY > nRadius) )
+        {
+            nRadius = 0;
+        }
+        psTransform->nBufferX = nX - nRadius;
+        if( psTransform->nBufferX < 0 )
+            psTransform->nBufferX = 0;
+        psTransform->nBufferY = nY - nRadius;
+        if( psTransform->nBufferY < 0 )
+            psTransform->nBufferY = 0;
+        psTransform->nBufferWidth = nWidth + 2 * nRadius;
+        if( psTransform->nBufferX + psTransform->nBufferWidth > nRasterXSize )
+            psTransform->nBufferWidth = nRasterXSize - psTransform->nBufferX;
+        psTransform->nBufferHeight = nHeight + 2 * nRadius;
+        if( psTransform->nBufferY + psTransform->nBufferHeight > nRasterYSize )
+            psTransform->nBufferHeight = nRasterYSize - psTransform->nBufferY;
+#ifdef DEBUG_VERBOSE_EXTRACT_DEM
+        CPLDebug("RPC", "New DEM buffer: %d,%d-%dx%d",
+                 psTransform->nBufferX,
+                 psTransform->nBufferY,
+                 psTransform->nBufferWidth,
+                 psTransform->nBufferHeight);
+#endif
+        CPLErr eErr = psTransform->poDS->GetRasterBand(1)->RasterIO(GF_Read,
+                        psTransform->nBufferX, psTransform->nBufferY,
+                        psTransform->nBufferWidth, psTransform->nBufferHeight,
+                        psTransform->padfDEMBuffer,
+                        psTransform->nBufferWidth, psTransform->nBufferHeight,
+                        GDT_Float64, 0, 0, NULL);
+        if( eErr != CE_None )
+        {
+            psTransform->nBufferX = -1;
+            psTransform->nBufferY = -1;
+            psTransform->nBufferWidth = -1;
+            psTransform->nBufferHeight = -1;
+            return false;
+        }
+#ifdef DEBUG_VERBOSE_EXTRACT_DEM
+         psTransform->nHitsInBuffer = 1;
+#endif
+    }
+    else
+    {
+#ifdef DEBUG_VERBOSE
+        psTransform->nHitsInBuffer++;
+#endif
+    }
+    psTransform->nLastQueriedX = nX;
+    psTransform->nLastQueriedY = nY;
 
-	a = ( xp2 <= 0.0 ) ? 0.0 : xp2 * xp2 * xp2;
-	b = ( xp1 <= 0.0 ) ? 0.0 : xp1 * xp1 * xp1;
-	c = ( dfVal   <= 0.0 ) ? 0.0 : dfVal * dfVal * dfVal;
-	d = ( xm1 <= 0.0 ) ? 0.0 : xm1 * xm1 * xm1;
+    for( int i=0; i<nHeight; i++)
+    {
+        memcpy( padfOut + i * nWidth,
+                psTransform->padfDEMBuffer + (nY - psTransform->nBufferY + i) *
+                    psTransform->nBufferWidth + nX - psTransform->nBufferX,
+                nWidth * sizeof(double) );
+    }
 
-	return ( 0.16666666666666666667 * ( a - ( 4.0 * b ) + ( 6.0 * c ) - ( 4.0 * d ) ) );
+    return true;
 }
 
 /************************************************************************/
@@ -1143,58 +1416,61 @@ double BiCubicKernel(double dfVal)
 /************************************************************************/
 
 static
-int GDALRPCGetDEMHeight( const GDALRPCTransformInfo *psTransform,
-                         const double dfXIn, const double dfYIn, double* pdfDEMH )
+int GDALRPCGetDEMHeight( GDALRPCTransformInfo *psTransform,
+                         const double dfXIn, const double dfYIn,
+                         double* pdfDEMH )
 {
-    int nRasterXSize = psTransform->poDS->GetRasterXSize();
-    int nRasterYSize = psTransform->poDS->GetRasterYSize();
+    const int nRasterXSize = psTransform->poDS->GetRasterXSize();
+    const int nRasterYSize = psTransform->poDS->GetRasterYSize();
     int bGotNoDataValue = FALSE;
-    double dfNoDataValue = psTransform->poDS->GetRasterBand(1)->GetNoDataValue( &bGotNoDataValue );
-    int bands[1] = {1};
+    const double dfNoDataValue =
+        psTransform->poDS->GetRasterBand(1)->GetNoDataValue( &bGotNoDataValue );
 
-    if(psTransform->eResampleAlg == DRA_Cubic)
+    if( psTransform->eResampleAlg == DRA_Cubic )
     {
-        // convert from upper left corner of pixel coordinates to center of pixel coordinates:
-        double dfX = dfXIn - 0.5;
-        double dfY = dfYIn - 0.5;
-        int dX = int(dfX);
-        int dY = int(dfY);
-        double dfDeltaX = dfX - dX;
-        double dfDeltaY = dfY - dY;
-
-        int dXNew = dX - 1;
-        int dYNew = dY - 1;
-        if (!(dXNew >= 0 && dYNew >= 0 && dXNew + 4 <= nRasterXSize && dYNew + 4 <= nRasterYSize))
+        // Convert from upper left corner of pixel coordinates to center of
+        // pixel coordinates:
+        const double dfX = dfXIn - 0.5;
+        const double dfY = dfYIn - 0.5;
+        const int dX = int(dfX);
+        const int dY = int(dfY);
+        const double dfDeltaX = dfX - dX;
+        const double dfDeltaY = dfY - dY;
+
+        const int dXNew = dX - 1;
+        const int dYNew = dY - 1;
+        if( !(dXNew >= 0 && dYNew >= 0 &&
+              dXNew + 4 <= nRasterXSize && dYNew + 4 <= nRasterYSize) )
         {
             goto bilinear_fallback;
         }
-        //cubic interpolation
-        double adfElevData[16] = {0};
-        CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dXNew, dYNew, 4, 4,
-                                                    &adfElevData, 4, 4,
-                                                    GDT_Float64, 1, bands, 0, 0, 0,
-                                                    NULL);
-        if(eErr != CE_None)
+        // Cubic interpolation.
+        double adfElevData[16] = { 0.0 };
+        if( !GDALRPCExtractDEMWindow( psTransform, dXNew, dYNew,
+                                      4, 4, adfElevData ) )
         {
             return FALSE;
         }
 
-        double dfSumH(0), dfSumWeight(0);
-        for ( int k_i = 0; k_i < 4; k_i++ )
+        double dfSumH = 0.0;
+        double dfSumWeight = 0.0;
+        for( int k_i = 0; k_i < 4; k_i++ )
         {
-            // Loop across the X axis
-            for ( int k_j = 0; k_j < 4; k_j++ )
+            // Loop across the X axis.
+            for( int k_j = 0; k_j < 4; k_j++ )
             {
                 // Calculate the weight for the specified pixel according
                 // to the bicubic b-spline kernel we're using for
-                // interpolation
-                int dKernIndX = k_j - 1;
-                int dKernIndY = k_i - 1;
-                double dfPixelWeight = BiCubicKernel(dKernIndX - dfDeltaX) * BiCubicKernel(dKernIndY - dfDeltaY);
+                // interpolation.
+                const int dKernIndX = k_j - 1;
+                const int dKernIndY = k_i - 1;
+                const double dfPixelWeight =
+                    BiCubicKernel(dKernIndX - dfDeltaX) *
+                    BiCubicKernel(dKernIndY - dfDeltaY);
 
                 // Create a sum of all values
-                // adjusted for the pixel's calculated weight
-                double dfElev = adfElevData[k_j + k_i * 4];
+                // adjusted for the pixel's calculated weight.
+                const double dfElev = adfElevData[k_j + k_i * 4];
                 if( bGotNoDataValue && ARE_REAL_EQUAL(dfNoDataValue, dfElev) )
                     continue;
 
@@ -1211,51 +1487,53 @@ int GDALRPCGetDEMHeight( const GDALRPCTransformInfo *psTransform,
 
         return TRUE;
     }
-    else if(psTransform->eResampleAlg == DRA_Bilinear)
+    else if( psTransform->eResampleAlg == DRA_Bilinear )
     {
 bilinear_fallback:
-        // convert from upper left corner of pixel coordinates to center of pixel coordinates:
-        double dfX = dfXIn - 0.5;
-        double dfY = dfYIn - 0.5;
-        int dX = int(dfX);
-        int dY = int(dfY);
-        double dfDeltaX = dfX - dX;
-        double dfDeltaY = dfY - dY;
-
-        if (!(dX >= 0 && dY >= 0 && dX + 2 <= nRasterXSize && dY + 2 <= nRasterYSize))
+        // Convert from upper left corner of pixel coordinates to center of
+        // pixel coordinates:
+        const double dfX = dfXIn - 0.5;
+        const double dfY = dfYIn - 0.5;
+        const int dX = static_cast<int>(dfX);
+        const int dY = static_cast<int>(dfY);
+        const double dfDeltaX = dfX - dX;
+        const double dfDeltaY = dfY - dY;
+
+        if( !(dX >= 0 && dY >= 0 &&
+              dX + 2 <= nRasterXSize && dY + 2 <= nRasterYSize) )
         {
             goto near_fallback;
         }
-        //bilinear interpolation
-        double adfElevData[4] = {0,0,0,0};
-        CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 2, 2,
-                                                    &adfElevData, 2, 2,
-                                                    GDT_Float64, 1, bands, 0, 0, 0,
-                                                  NULL);
-        if(eErr != CE_None)
+
+        // Bilinear interpolation.
+        double adfElevData[4] = { 0.0, 0.0, 0.0, 0.0 };
+        if( !GDALRPCExtractDEMWindow( psTransform, dX, dY, 2, 2, adfElevData ) )
         {
             return FALSE;
         }
+
         if( bGotNoDataValue )
         {
-            // TODO: we could perhaps use a valid sample if there's one
-            int bFoundNoDataElev = FALSE;
-            for(int k_i=0;k_i<4;k_i++)
+            // TODO: We could perhaps use a valid sample if there's one.
+            bool bFoundNoDataElev = false;
+            for( int k_i = 0; k_i < 4; k_i++ )
             {
                 if( ARE_REAL_EQUAL(dfNoDataValue, adfElevData[k_i]) )
-                    bFoundNoDataElev = TRUE;
+                    bFoundNoDataElev = true;
             }
             if( bFoundNoDataElev )
             {
                 return FALSE;
             }
         }
-        double dfDeltaX1 = 1.0 - dfDeltaX;
-        double dfDeltaY1 = 1.0 - dfDeltaY;
+        const double dfDeltaX1 = 1.0 - dfDeltaX;
+        const double dfDeltaY1 = 1.0 - dfDeltaY;
 
-        double dfXZ1 = adfElevData[0] * dfDeltaX1 + adfElevData[1] * dfDeltaX;
-        double dfXZ2 = adfElevData[2] * dfDeltaX1 + adfElevData[3] * dfDeltaX;
-        double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
+        const double dfXZ1 =
+            adfElevData[0] * dfDeltaX1 + adfElevData[1] * dfDeltaX;
+        const double dfXZ2 =
+            adfElevData[2] * dfDeltaX1 + adfElevData[3] * dfDeltaX;
+        const double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
 
         *pdfDEMH = dfYZ;
 
@@ -1264,18 +1542,14 @@ bilinear_fallback:
     else
     {
 near_fallback:
-        int dX = (int) (dfXIn);
-        int dY = (int) (dfYIn);
-        if (!(dX >= 0 && dY >= 0 && dX < nRasterXSize && dY < nRasterYSize))
+        const int dX = static_cast<int>(dfXIn);
+        const int dY = static_cast<int>(dfYIn);
+        if( !(dX >= 0 && dY >= 0 && dX < nRasterXSize && dY < nRasterYSize) )
         {
             return FALSE;
         }
-        double dfDEMH(0);
-        CPLErr eErr = psTransform->poDS->RasterIO(GF_Read, dX, dY, 1, 1,
-                                                    &dfDEMH, 1, 1,
-                                                    GDT_Float64, 1, bands, 0, 0, 0,
-                                                    NULL);
-        if(eErr != CE_None ||
+        double dfDEMH = 0.0;
+        if( !GDALRPCExtractDEMWindow( psTransform, dX, dY, 1, 1, &dfDEMH ) ||
             (bGotNoDataValue && ARE_REAL_EQUAL(dfNoDataValue, dfDEMH)) )
         {
             return FALSE;
@@ -1291,76 +1565,82 @@ near_fallback:
 /*                    GDALRPCTransformWholeLineWithDEM()                */
 /************************************************************************/
 
-static int GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTransform,
-                                             int nPointCount,
-                                             double *padfX, double *padfY, double *padfZ,
-                                             int *panSuccess,
-                                             int nXLeft, int nXWidth,
-                                             int nYTop, int nYHeight )
+static int
+GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTransform,
+                                  int nPointCount,
+                                  double *padfX, double *padfY, double *padfZ,
+                                  int *panSuccess,
+                                  int nXLeft, int nXWidth,
+                                  int nYTop, int nYHeight )
 {
-    int i;
-
-    double* padfDEMBuffer = (double*) VSI_MALLOC2_VERBOSE(sizeof(double), nXWidth * nYHeight);
+    double* padfDEMBuffer = static_cast<double *>(
+        VSI_MALLOC2_VERBOSE(sizeof(double), nXWidth * nYHeight));
     if( padfDEMBuffer == NULL )
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
             panSuccess[i] = FALSE;
         return FALSE;
     }
     CPLErr eErr = psTransform->poDS->GetRasterBand(1)->
-            RasterIO(GF_Read, nXLeft, nYTop, nXWidth, nYHeight,
-                        padfDEMBuffer, nXWidth, nYHeight,
-                        GDT_Float64, 0, 0, NULL);
+        RasterIO(GF_Read, nXLeft, nYTop, nXWidth, nYHeight,
+                 padfDEMBuffer, nXWidth, nYHeight,
+                 GDT_Float64, 0, 0, NULL);
     if( eErr != CE_None )
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
             panSuccess[i] = FALSE;
         VSIFree(padfDEMBuffer);
         return FALSE;
     }
 
-
     int bGotNoDataValue = FALSE;
-    double dfNoDataValue = 0;
-    dfNoDataValue = psTransform->poDS->GetRasterBand(1)->GetNoDataValue( &bGotNoDataValue );
+    const double dfNoDataValue =
+        psTransform->poDS->GetRasterBand(1)->GetNoDataValue( &bGotNoDataValue );
 
-    // dfY in pixel center convention
-    double dfY = psTransform->adfDEMReverseGeoTransform[3] +
-                        padfY[0] * psTransform->adfDEMReverseGeoTransform[5] - 0.5;
-    int nY = int(dfY);
-    double dfDeltaY = dfY - nY;
+    // dfY in pixel center convention.
+    const double dfY =
+        psTransform->adfDEMReverseGeoTransform[3] +
+        padfY[0] * psTransform->adfDEMReverseGeoTransform[5] - 0.5;
+    const int nY = static_cast<int>(dfY);
+    const double dfDeltaY = dfY - nY;
 
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
-        double dfDEMH(0);
+        double dfDEMH = 0.0;
 
-        if(psTransform->eResampleAlg == DRA_Cubic)
+        if( psTransform->eResampleAlg == DRA_Cubic )
         {
-            // dfX in pixel center convention
-            double dfX = psTransform->adfDEMReverseGeoTransform[0] +
-                            padfX[i] * psTransform->adfDEMReverseGeoTransform[1] - 0.5;
-            int nX = int(dfX);
-            double dfDeltaX = dfX - nX;
-
-            int nXNew = nX - 1;
-
-            double dfSumH(0), dfSumWeight(0);
-            for ( int k_i = 0; k_i < 4; k_i++ )
+            // dfX in pixel center convention.
+            const double dfX =
+                psTransform->adfDEMReverseGeoTransform[0] +
+                padfX[i] * psTransform->adfDEMReverseGeoTransform[1] - 0.5;
+            const int nX = static_cast<int>(dfX);
+            const double dfDeltaX = dfX - nX;
+
+            const int nXNew = nX - 1;
+
+            double dfSumH = 0.0;
+            double dfSumWeight = 0.0;
+            for( int k_i = 0; k_i < 4; k_i++ )
             {
-                // Loop across the X axis
-                for ( int k_j = 0; k_j < 4; k_j++ )
+                // Loop across the X axis.
+                for( int k_j = 0; k_j < 4; k_j++ )
                 {
                     // Calculate the weight for the specified pixel according
                     // to the bicubic b-spline kernel we're using for
-                    // interpolation
-                    int dKernIndX = k_j - 1;
-                    int dKernIndY = k_i - 1;
-                    double dfPixelWeight = BiCubicKernel(dKernIndX - dfDeltaX) * BiCubicKernel(dKernIndY - dfDeltaY);
+                    // interpolation.
+                    const int dKernIndX = k_j - 1;
+                    const int dKernIndY = k_i - 1;
+                    const double dfPixelWeight =
+                        BiCubicKernel(dKernIndX - dfDeltaX) *
+                        BiCubicKernel(dKernIndY - dfDeltaY);
 
                     // Create a sum of all values
-                    // adjusted for the pixel's calculated weight
-                    double dfElev = padfDEMBuffer[k_i * nXWidth + nXNew - nXLeft + k_j];
-                    if( bGotNoDataValue && ARE_REAL_EQUAL(dfNoDataValue, dfElev) )
+                    // adjusted for the pixel's calculated weight.
+                    const double dfElev =
+                        padfDEMBuffer[k_i * nXWidth + nXNew - nXLeft + k_j];
+                    if( bGotNoDataValue &&
+                        ARE_REAL_EQUAL(dfNoDataValue, dfElev) )
                         continue;
 
                     dfSumH += dfElev * dfPixelWeight;
@@ -1380,31 +1660,38 @@ static int GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTrans
             else
                 dfDEMH = dfSumH / dfSumWeight;
         }
-        else if(psTransform->eResampleAlg == DRA_Bilinear)
+        else if( psTransform->eResampleAlg == DRA_Bilinear )
         {
-            // dfX in pixel center convention
-            double dfX = psTransform->adfDEMReverseGeoTransform[0] +
-                            padfX[i] * psTransform->adfDEMReverseGeoTransform[1] - 0.5;
-            int nX = int(dfX);
-            double dfDeltaX = dfX - nX;
-
-            //bilinear interpolation
-            double adfElevData[4];
-            memcpy(adfElevData, padfDEMBuffer + nX - nXLeft, 2 * sizeof(double));
-            memcpy(adfElevData + 2, padfDEMBuffer + nXWidth + nX - nXLeft, 2 * sizeof(double));
+            // dfX in pixel center convention.
+            const double dfX =
+                psTransform->adfDEMReverseGeoTransform[0] +
+                padfX[i] * psTransform->adfDEMReverseGeoTransform[1] - 0.5;
+            const int nX = static_cast<int>(dfX);
+            const double dfDeltaX = dfX - nX;
+
+            // Bilinear interpolation.
+            double adfElevData[4] = {};
+            memcpy(adfElevData,
+                   padfDEMBuffer + nX - nXLeft,
+                   2 * sizeof(double));
+            memcpy(adfElevData + 2,
+                   padfDEMBuffer + nXWidth + nX - nXLeft,
+                   2 * sizeof(double));
 
             int bFoundNoDataElev = FALSE;
             if( bGotNoDataValue )
             {
                 int k_valid_sample = -1;
-                for(int k_i=0;k_i<4;k_i++)
+                for( int k_i = 0; k_i < 4; k_i++ )
                 {
                     if( ARE_REAL_EQUAL(dfNoDataValue, adfElevData[k_i]) )
                     {
                         bFoundNoDataElev = TRUE;
                     }
                     else if( k_valid_sample < 0 )
+                    {
                         k_valid_sample = k_i;
+                    }
                 }
                 if( bFoundNoDataElev )
                 {
@@ -1437,19 +1724,22 @@ static int GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTrans
                     }
                 }
             }
-            double dfDeltaX1 = 1.0 - dfDeltaX;
-            double dfDeltaY1 = 1.0 - dfDeltaY;
-
-            double dfXZ1 = adfElevData[0] * dfDeltaX1 + adfElevData[1] * dfDeltaX;
-            double dfXZ2 = adfElevData[2] * dfDeltaX1 + adfElevData[3] * dfDeltaX;
-            double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
+            const double dfDeltaX1 = 1.0 - dfDeltaX;
+            const double dfDeltaY1 = 1.0 - dfDeltaY;
+
+            const double dfXZ1 =
+                adfElevData[0] * dfDeltaX1 + adfElevData[1] * dfDeltaX;
+            const double dfXZ2 =
+                adfElevData[2] * dfDeltaX1 + adfElevData[3] * dfDeltaX;
+            const double dfYZ = dfXZ1 * dfDeltaY1 + dfXZ2 * dfDeltaY;
             dfDEMH = dfYZ;
         }
         else
         {
-            double dfX = psTransform->adfDEMReverseGeoTransform[0] +
-                            padfX[i] * psTransform->adfDEMReverseGeoTransform[1];
-            int nX = int(dfX);
+            const double dfX =
+                psTransform->adfDEMReverseGeoTransform[0] +
+                padfX[i] * psTransform->adfDEMReverseGeoTransform[1];
+            const int nX = int(dfX);
 
             dfDEMH = padfDEMBuffer[nX - nXLeft];
             if( bGotNoDataValue && ARE_REAL_EQUAL(dfNoDataValue, dfDEMH) )
@@ -1481,6 +1771,7 @@ static int GDALRPCTransformWholeLineWithDEM( const GDALRPCTransformInfo *psTrans
 /*                          GDALRPCTransform()                          */
 /************************************************************************/
 
+/** RPC transform */
 int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                       int nPointCount,
                       double *padfX, double *padfY, double *padfZ,
@@ -1489,8 +1780,8 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
 {
     VALIDATE_POINTER1( pTransformArg, "GDALRPCTransform", 0 );
 
-    GDALRPCTransformInfo *psTransform = (GDALRPCTransformInfo *) pTransformArg;
-    int i;
+    GDALRPCTransformInfo *psTransform =
+        static_cast<GDALRPCTransformInfo *>(pTransformArg);
 
     if( psTransform->bReversed )
         bDstToSrc = !bDstToSrc;
@@ -1498,10 +1789,10 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
 /* -------------------------------------------------------------------- */
 /*      Lazy opening of the optional DEM file.                          */
 /* -------------------------------------------------------------------- */
-    if(psTransform->pszDEMPath != NULL &&
-       psTransform->bHasTriedOpeningDS == FALSE)
+    if( psTransform->pszDEMPath != NULL &&
+        psTransform->bHasTriedOpeningDS == FALSE )
     {
-        int bIsValid = FALSE;
+        bool bIsValid = false;
         psTransform->bHasTriedOpeningDS = TRUE;
         CPLString osPrevValueConfigOption;
         if( psTransform->bApplyDEMVDatumShift )
@@ -1510,12 +1801,27 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                 = CPLGetThreadLocalConfigOption("GTIFF_REPORT_COMPD_CS", "");
             CPLSetThreadLocalConfigOption("GTIFF_REPORT_COMPD_CS", "YES");
         }
-        psTransform->poDS = (GDALDataset *)
-                                GDALOpen( psTransform->pszDEMPath, GA_ReadOnly );
-        if(psTransform->poDS != NULL && psTransform->poDS->GetRasterCount() >= 1)
+        psTransform->poDS = reinterpret_cast<GDALDataset *>(
+            GDALOpen(psTransform->pszDEMPath, GA_ReadOnly));
+        if( psTransform->poDS != NULL &&
+            psTransform->poDS->GetRasterCount() >= 1 )
         {
+            psTransform->nBufferMaxRadius =
+                atoi(CPLGetConfigOption("GDAL_RPC_DEM_BUFFER_MAX_RADIUS", "2"));
+            psTransform->nHitsInBuffer = 0;
+            const int nMaxWindowSize = 4;
+            psTransform->padfDEMBuffer = static_cast<double*>(VSIMalloc(
+                (nMaxWindowSize + 2 * psTransform->nBufferMaxRadius) *
+                (nMaxWindowSize + 2 * psTransform->nBufferMaxRadius) *
+                sizeof(double) ));
+            psTransform->nBufferX = -1;
+            psTransform->nBufferY = -1;
+            psTransform->nBufferWidth = -1;
+            psTransform->nBufferHeight = -1;
+            psTransform->nLastQueriedX = -1;
+            psTransform->nLastQueriedY = -1;
             const char* pszSpatialRef = psTransform->poDS->GetProjectionRef();
-            if (pszSpatialRef != NULL && pszSpatialRef[0] != '\0')
+            if( pszSpatialRef != NULL && pszSpatialRef[0] != '\0' )
             {
                 OGRSpatialReference* poWGSSpaRef =
                         new OGRSpatialReference(SRS_WKT_WGS84);
@@ -1525,24 +1831,30 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                 if( !psTransform->bApplyDEMVDatumShift )
                     poDSSpaRef->StripVertical();
 
-                if(!poWGSSpaRef->IsSame(poDSSpaRef))
-                    psTransform->poCT =OGRCreateCoordinateTransformation(
-                                                    poWGSSpaRef, poDSSpaRef );
+                if( !poWGSSpaRef->IsSame(poDSSpaRef) )
+                    psTransform->poCT =
+                        OGRCreateCoordinateTransformation(poWGSSpaRef,
+                                                          poDSSpaRef);
 
                 if( psTransform->poCT != NULL && !poDSSpaRef->IsCompound() )
                 {
                     // Empiric attempt to guess if the coordinate transformation
-                    // to WGS84 is a no-op. For example for NED13 datasets in NAD83
-                    double adfX[] = { -179, 179, 179, -179, 0, 0 };
-                    double adfY[] = { 89, 89, -89, -89, 0, 0 };
-                    double adfZ[] = { 0, 0, 0, 0, 0, 0 };
-
-                    // Also test with a "reference point" from the RPC values
-                    double dfRefLong, dfRefLat;
-                    if( psTransform->sRPC.dfMIN_LONG != -180 || psTransform->sRPC.dfMAX_LONG != 180 )
+                    // to WGS84 is a no-op. For example for NED13 datasets in
+                    // NAD83.
+                    double adfX[] = { -179.0, 179.0, 179.0, -179.0, 0.0, 0.0 };
+                    double adfY[] = { 89.0, 89.0, -89.0, -89.0, 0.0, 0.0 };
+                    double adfZ[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+
+                    // Also test with a "reference point" from the RPC values.
+                    double dfRefLong = 0.0;
+                    double dfRefLat = 0.0;
+                    if( psTransform->sRPC.dfMIN_LONG != -180 ||
+                        psTransform->sRPC.dfMAX_LONG != 180 )
                     {
-                        dfRefLong = (psTransform->sRPC.dfMIN_LONG + psTransform->sRPC.dfMAX_LONG) * 0.5;
-                        dfRefLat  = (psTransform->sRPC.dfMIN_LAT  + psTransform->sRPC.dfMAX_LAT ) * 0.5;
+                        dfRefLong = (psTransform->sRPC.dfMIN_LONG +
+                                     psTransform->sRPC.dfMAX_LONG) * 0.5;
+                        dfRefLat  = (psTransform->sRPC.dfMIN_LAT +
+                                     psTransform->sRPC.dfMAX_LAT ) * 0.5;
                     }
                     else
                     {
@@ -1554,14 +1866,22 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
 
                     if( psTransform->poCT->Transform(
                                                 6, adfX, adfY, adfZ) &&
-                        fabs(adfX[0] - -179) < 1e-12 && fabs(adfY[0] -  89) < 1e-12 &&
-                        fabs(adfX[1] -  179) < 1e-12 && fabs(adfY[1] -  89) < 1e-12 &&
-                        fabs(adfX[2] -  179) < 1e-12 && fabs(adfY[2] - -89) < 1e-12 &&
-                        fabs(adfX[3] - -179) < 1e-12 && fabs(adfY[3] - -89) < 1e-12 &&
-                        fabs(adfX[4] -    0) < 1e-12 && fabs(adfY[4] -   0) < 1e-12 &&
-                        fabs(adfX[5] - dfRefLong) < 1e-12 && fabs(adfY[5] - dfRefLat) < 1e-12 )
+                        fabs(adfX[0] - -179.0) < 1.0e-12 &&
+                        fabs(adfY[0] -   89.0) < 1.0e-12 &&
+                        fabs(adfX[1] -  179.0) < 1.0e-12 &&
+                        fabs(adfY[1] -   89.0) < 1.0e-12 &&
+                        fabs(adfX[2] -  179.0) < 1.0e-12 &&
+                        fabs(adfY[2] -  -89.0) < 1.0e-12 &&
+                        fabs(adfX[3] - -179.0) < 1.0e-12 &&
+                        fabs(adfY[3] -  -89.0) < 1.0e-12 &&
+                        fabs(adfX[4] -    0.0) < 1.0e-12 &&
+                        fabs(adfY[4] -    0.0) < 1.0e-12 &&
+                        fabs(adfX[5] - dfRefLong) < 1.0e-12 &&
+                        fabs(adfY[5] - dfRefLat) < 1.0e-12 )
                     {
-                        CPLDebug("RPC", "Short-circuiting coordinate transformation from DEM SRS to WGS 84 due to apparent nop");
+                        CPLDebug("RPC",
+                                 "Short-circuiting coordinate transformation "
+                                 "from DEM SRS to WGS 84 due to apparent nop");
                         delete psTransform->poCT;
                         psTransform->poCT = NULL;
                     }
@@ -1571,22 +1891,24 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
                 delete poDSSpaRef;
             }
 
-            if (psTransform->poDS->GetGeoTransform(
+            if( psTransform->poDS->GetGeoTransform(
                                 psTransform->adfDEMGeoTransform) == CE_None &&
                 GDALInvGeoTransform( psTransform->adfDEMGeoTransform,
-                                     psTransform->adfDEMReverseGeoTransform ))
+                                     psTransform->adfDEMReverseGeoTransform ) )
             {
-                bIsValid = TRUE;
+                bIsValid = true;
             }
         }
 
         if( psTransform->bApplyDEMVDatumShift )
         {
-            CPLSetThreadLocalConfigOption("GTIFF_REPORT_COMPD_CS",
-                osPrevValueConfigOption.size() ? osPrevValueConfigOption.c_str() : NULL);
+            CPLSetThreadLocalConfigOption(
+                "GTIFF_REPORT_COMPD_CS",
+                osPrevValueConfigOption.size()
+                ? osPrevValueConfigOption.c_str() : NULL);
         }
 
-        if (!bIsValid && psTransform->poDS != NULL)
+        if( !bIsValid && psTransform->poDS != NULL )
         {
             GDALClose(psTransform->poDS);
             psTransform->poDS = NULL;
@@ -1599,12 +1921,12 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
 /* -------------------------------------------------------------------- */
     if( bDstToSrc )
     {
-        /* Optimization to avoid doing too many picking in DEM in the particular */
-        /* case where each point to transform is on a single line of the DEM */
-        /* To make it simple and fast we check that all input latitudes are */
-        /* identical, that the DEM is in WGS84 geodetic and that it has no rotation. */
-        /* Such case is for example triggered when doing gdalwarp with a target SRS */
-        /* of EPSG:4326 or EPSG:3857 */
+        // Optimization to avoid doing too many picking in DEM in the particular
+        // case where each point to transform is on a single line of the DEM.
+        // To make it simple and fast we check that all input latitudes are
+        // identical, that the DEM is in WGS84 geodetic and that it has no
+        // rotation.  Such case is for example triggered when doing gdalwarp
+        // with a target SRS of EPSG:4326 or EPSG:3857.
         if( nPointCount >= 10 && psTransform->poDS != NULL &&
             psTransform->poCT == NULL && padfY[0] == padfY[nPointCount-1] &&
             padfY[0] == padfY[nPointCount/ 2] &&
@@ -1613,13 +1935,14 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
             psTransform->adfDEMReverseGeoTransform[4] == 0.0 &&
             CPLTestBool(CPLGetConfigOption("GDAL_RPC_DEM_OPTIM", "YES")) )
         {
-            int bUseOptimized = TRUE;
-            double dfMinX = padfX[0], dfMaxX = padfX[0];
-            for(i = 1; i < nPointCount; i++)
+            bool bUseOptimized = true;
+            double dfMinX = padfX[0];
+            double dfMaxX = padfX[0];
+            for( int i = 1; i < nPointCount; i++ )
             {
                 if( padfY[i] != padfY[0] )
                 {
-                    bUseOptimized = FALSE;
+                    bUseOptimized = false;
                     break;
                 }
                 if( padfX[i] < dfMinX ) dfMinX = padfX[i];
@@ -1627,60 +1950,68 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
             }
             if( bUseOptimized )
             {
-                double dfX1, dfY1, dfX2, dfY2;
+                double dfX1 = 0.0;
+                double dfY1 = 0.0;
+                double dfX2 = 0.0;
+                double dfY2 = 0.0;
                 GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
                                     dfMinX, padfY[0], &dfX1, &dfY1 );
                 GDALApplyGeoTransform( psTransform->adfDEMReverseGeoTransform,
                                     dfMaxX, padfY[0], &dfX2, &dfY2 );
 
-                // convert to center of pixel convention for reading the image data
+                // Convert to center of pixel convention for reading the image
+                // data.
                 if( psTransform->eResampleAlg != DRA_NearestNeighbour )
                 {
                     dfX1 -= 0.5;
                     dfY1 -= 0.5;
                     dfX2 -= 0.5;
-                    dfY2 -= 0.5;
+                    // dfY2 -= 0.5;
                 }
-                int nXLeft = int(floor(dfX1));
-                int nXRight = int(floor(dfX2));
+                int nXLeft = static_cast<int>(floor(dfX1));
+                int nXRight = static_cast<int>(floor(dfX2));
                 int nXWidth = nXRight - nXLeft + 1;
-                int nYTop = int(floor(dfY1));
+                int nYTop = static_cast<int>(floor(dfY1));
                 int nYHeight;
                 if( psTransform->eResampleAlg == DRA_Cubic )
                 {
-                    nXLeft --;
+                    nXLeft--;
                     nXWidth += 3;
-                    nYTop --;
+                    nYTop--;
                     nYHeight = 4;
                 }
                 else if( psTransform->eResampleAlg == DRA_Bilinear )
                 {
-                    nXWidth ++;
+                    nXWidth++;
                     nYHeight = 2;
                 }
                 else
                 {
                     nYHeight = 1;
                 }
-                if( nXLeft >= 0 && nXLeft + nXWidth <= psTransform->poDS->GetRasterXSize() &&
-                    nYTop >= 0 && nYTop + nYHeight <= psTransform->poDS->GetRasterYSize() )
+                if( nXLeft >= 0 &&
+                    nXLeft + nXWidth <= psTransform->poDS->GetRasterXSize() &&
+                    nYTop >= 0 &&
+                    nYTop + nYHeight <= psTransform->poDS->GetRasterYSize() )
                 {
-                    static int bOnce = FALSE;
+                    static bool bOnce = false;
                     if( !bOnce )
                     {
-                        bOnce = TRUE;
-                        CPLDebug("RPC", "Using GDALRPCTransformWholeLineWithDEM");
+                        bOnce = true;
+                        CPLDebug("RPC",
+                                 "Using GDALRPCTransformWholeLineWithDEM");
                     }
-                    return GDALRPCTransformWholeLineWithDEM( psTransform, nPointCount,
-                                                             padfX, padfY, padfZ,
-                                                             panSuccess,
-                                                             nXLeft, nXWidth,
-                                                             nYTop, nYHeight );
+                    return GDALRPCTransformWholeLineWithDEM(psTransform,
+                                                            nPointCount,
+                                                            padfX, padfY, padfZ,
+                                                            panSuccess,
+                                                            nXLeft, nXWidth,
+                                                            nYTop, nYHeight);
                 }
             }
         }
 
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             double dfHeight = 0.0;
             if( !GDALRPCGetHeightAtLongLat( psTransform, padfX[i], padfY[i],
@@ -1704,9 +2035,10 @@ int GDALRPCTransform( void *pTransformArg, int bDstToSrc,
 /*      function uses an iterative method from an initial linear        */
 /*      approximation.                                                  */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
-        double dfResultX, dfResultY;
+        double dfResultX = 0.0;
+        double dfResultY = 0.0;
 
         if( !RPCInverseTransformPoint( psTransform, padfX[i], padfY[i],
                     padfZ[i],
@@ -1734,11 +2066,10 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
 {
     VALIDATE_POINTER1( pTransformArg, "GDALSerializeRPCTransformer", NULL );
 
-    CPLXMLNode *psTree;
     GDALRPCTransformInfo *psInfo =
         (GDALRPCTransformInfo *)(pTransformArg);
 
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "RPCTransformer" );
+    CPLXMLNode *psTree = CPLCreateXMLNode(NULL, CXT_Element, "RPCTransformer");
 
 /* -------------------------------------------------------------------- */
 /*      Serialize bReversed.                                            */
@@ -1757,7 +2088,7 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
 /*      Serialize Height Scale.                                         */
 /* -------------------------------------------------------------------- */
-    if (psInfo->dfHeightScale != 1.0)
+    if( psInfo->dfHeightScale != 1.0 )
         CPLCreateXMLElementAndValue(
             psTree, "HeightScale",
             CPLString().Printf( "%.15g", psInfo->dfHeightScale ) );
@@ -1765,7 +2096,7 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
 /*      Serialize DEM path.                                             */
 /* -------------------------------------------------------------------- */
-    if (psInfo->pszDEMPath != NULL)
+    if( psInfo->pszDEMPath != NULL )
     {
         CPLCreateXMLElementAndValue(
             psTree, "DEMPath",
@@ -1775,16 +2106,19 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
 /*      Serialize DEM interpolation                                     */
 /* -------------------------------------------------------------------- */
         CPLCreateXMLElementAndValue(
-            psTree, "DEMInterpolation", GDALSerializeRPCDEMResample(psInfo->eResampleAlg) );
+            psTree, "DEMInterpolation",
+            GDALSerializeRPCDEMResample(psInfo->eResampleAlg) );
 
         if( psInfo->bHasDEMMissingValue )
         {
             CPLCreateXMLElementAndValue(
-                psTree, "DEMMissingValue", CPLSPrintf("%.18g", psInfo->dfDEMMissingValue) );
+                psTree, "DEMMissingValue",
+                CPLSPrintf("%.18g", psInfo->dfDEMMissingValue) );
         }
 
         CPLCreateXMLElementAndValue(
-                psTree, "DEMApplyVDatumShift", ( psInfo->bApplyDEMVDatumShift ) ? "true" : "false" );
+                psTree, "DEMApplyVDatumShift",
+                psInfo->bApplyDEMVDatumShift ? "true" : "false" );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1803,13 +2137,11 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
 
     for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
     {
-        const char *pszRawValue;
-        char *pszKey;
-        CPLXMLNode *psMDI;
+        char *pszKey = NULL;
 
-        pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
+        const char *pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
 
-        psMDI = CPLCreateXMLNode( psMD, CXT_Element, "MDI" );
+        CPLXMLNode *psMDI = CPLCreateXMLNode( psMD, CXT_Element, "MDI" );
         CPLSetXMLValue( psMDI, "#key", pszKey );
         CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
 
@@ -1828,27 +2160,24 @@ CPLXMLNode *GDALSerializeRPCTransformer( void *pTransformArg )
 void *GDALDeserializeRPCTransformer( CPLXMLNode *psTree )
 
 {
-    void *pResult;
     char **papszOptions = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Collect metadata.                                               */
 /* -------------------------------------------------------------------- */
-    char **papszMD = NULL;
-    CPLXMLNode *psMDI, *psMetadata;
-    GDALRPCInfo sRPC;
-
-    psMetadata = CPLGetXMLNode( psTree, "Metadata" );
+    CPLXMLNode *psMetadata = CPLGetXMLNode( psTree, "Metadata" );
 
     if( psMetadata == NULL
         || psMetadata->eType != CXT_Element
-        || !EQUAL(psMetadata->pszValue,"Metadata") )
+        || !EQUAL(psMetadata->pszValue, "Metadata") )
         return NULL;
 
-    for( psMDI = psMetadata->psChild; psMDI != NULL;
+    char **papszMD = NULL;
+    for( CPLXMLNode *psMDI = psMetadata->psChild;
+         psMDI != NULL;
          psMDI = psMDI->psNext )
     {
-        if( !EQUAL(psMDI->pszValue,"MDI")
+        if( !EQUAL(psMDI->pszValue, "MDI")
             || psMDI->eType != CXT_Element
             || psMDI->psChild == NULL
             || psMDI->psChild->psNext == NULL
@@ -1862,6 +2191,7 @@ void *GDALDeserializeRPCTransformer( CPLXMLNode *psTree )
                              psMDI->psChild->psNext->pszValue );
     }
 
+    GDALRPCInfo sRPC;
     if( !GDALExtractRPCInfo( papszMD, &sRPC ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1875,43 +2205,46 @@ void *GDALDeserializeRPCTransformer( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
 /*      Get other flags.                                                */
 /* -------------------------------------------------------------------- */
-    double dfPixErrThreshold;
-    int bReversed;
-
-    bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));
+    const int bReversed = atoi(CPLGetXMLValue(psTree, "Reversed", "0"));
 
-    dfPixErrThreshold =
-        CPLAtof(CPLGetXMLValue(psTree,"PixErrThreshold","0.25"));
+    const double dfPixErrThreshold =
+        CPLAtof(CPLGetXMLValue(psTree, "PixErrThreshold",
+                               CPLSPrintf( "%f", DEFAULT_PIX_ERR_THRESHOLD )));
 
-    papszOptions = CSLSetNameValue( papszOptions, "RPC_HEIGHT",
-                                    CPLGetXMLValue(psTree,"HeightOffset","0"));
-    papszOptions = CSLSetNameValue( papszOptions, "RPC_HEIGHT_SCALE",
-                                    CPLGetXMLValue(psTree,"HeightScale","1"));
-    const char* pszDEMPath = CPLGetXMLValue(psTree,"DEMPath",NULL);
-    if (pszDEMPath != NULL)
+    papszOptions = CSLSetNameValue(papszOptions,  "RPC_HEIGHT",
+                                   CPLGetXMLValue(psTree, "HeightOffset", "0"));
+    papszOptions = CSLSetNameValue(papszOptions, "RPC_HEIGHT_SCALE",
+                                   CPLGetXMLValue(psTree, "HeightScale", "1"));
+    const char* pszDEMPath = CPLGetXMLValue(psTree, "DEMPath", NULL);
+    if( pszDEMPath != NULL )
         papszOptions = CSLSetNameValue( papszOptions, "RPC_DEM",
                                         pszDEMPath);
 
-    const char* pszDEMInterpolation = CPLGetXMLValue(psTree,"DEMInterpolation", "bilinear");
-    if (pszDEMInterpolation != NULL)
+    const char* pszDEMInterpolation =
+        CPLGetXMLValue(psTree, "DEMInterpolation", "bilinear");
+    if( pszDEMInterpolation != NULL )
         papszOptions = CSLSetNameValue( papszOptions, "RPC_DEMINTERPOLATION",
                                         pszDEMInterpolation);
 
-    const char* pszDEMMissingValue = CPLGetXMLValue(psTree,"DEMMissingValue", NULL);
-    if (pszDEMMissingValue != NULL)
+    const char* pszDEMMissingValue =
+        CPLGetXMLValue(psTree, "DEMMissingValue", NULL);
+    if( pszDEMMissingValue != NULL )
         papszOptions = CSLSetNameValue( papszOptions, "RPC_DEM_MISSING_VALUE",
                                         pszDEMMissingValue);
 
-    const char* pszDEMApplyVDatumShift = CPLGetXMLValue(psTree,"DEMApplyVDatumShift", NULL);
-    if (pszDEMApplyVDatumShift != NULL)
-        papszOptions = CSLSetNameValue( papszOptions, "RPC_DEM_APPLY_VDATUM_SHIFT",
-                                        pszDEMApplyVDatumShift);
+    const char* pszDEMApplyVDatumShift =
+        CPLGetXMLValue(psTree, "DEMApplyVDatumShift", NULL);
+    if( pszDEMApplyVDatumShift != NULL )
+        papszOptions = CSLSetNameValue(papszOptions,
+                                       "RPC_DEM_APPLY_VDATUM_SHIFT",
+                                       pszDEMApplyVDatumShift);
 
 /* -------------------------------------------------------------------- */
 /*      Generate transformation.                                        */
 /* -------------------------------------------------------------------- */
-    pResult = GDALCreateRPCTransformer( &sRPC, bReversed, dfPixErrThreshold,
-                                        papszOptions );
+    void *pResult =
+        GDALCreateRPCTransformer( &sRPC, bReversed, dfPixErrThreshold,
+                                  papszOptions );
 
     CSLDestroy( papszOptions );
 
diff --git a/alg/gdal_simplesurf.cpp b/alg/gdal_simplesurf.cpp
index c871b75..b44b3ff 100644
--- a/alg/gdal_simplesurf.cpp
+++ b/alg/gdal_simplesurf.cpp
@@ -27,7 +27,9 @@
 
 #include "gdal_simplesurf.h"
 
-CPL_CVSID("$Id");
+#include <algorithm>
+
+CPL_CVSID("$Id: gdal_simplesurf.cpp 36714 2016-12-06 04:34:21Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -35,82 +37,77 @@ CPL_CVSID("$Id");
 /* ==================================================================== */
 /************************************************************************/
 
-GDALFeaturePoint::GDALFeaturePoint()
+GDALFeaturePoint::GDALFeaturePoint() :
+    nX(-1),
+    nY(-1),
+    nScale(-1),
+    nRadius(-1),
+    nSign(-1),
+    padfDescriptor(new double[DESC_SIZE])
+{}
+
+GDALFeaturePoint::GDALFeaturePoint( const GDALFeaturePoint& fp ) :
+    nX(fp.nX),
+    nY(fp.nY),
+    nScale(fp.nScale),
+    nRadius(fp.nRadius),
+    nSign(fp.nSign),
+    padfDescriptor(new double[DESC_SIZE])
 {
-    nX =      -1;
-    nY =      -1;
-    nScale =  -1;
-    nRadius = -1;
-    nSign =   -1;
-
-    padfDescriptor = new double[DESC_SIZE];
+    for( int i = 0; i < DESC_SIZE; i++ )
+        padfDescriptor[i] = fp.padfDescriptor[i];
 }
 
-GDALFeaturePoint::GDALFeaturePoint(const GDALFeaturePoint& fp)
+GDALFeaturePoint::GDALFeaturePoint( int nXIn, int nYIn,
+                                    int nScaleIn, int nRadiusIn, int nSignIn ) :
+    nX(nXIn),
+    nY(nYIn),
+    nScale(nScaleIn),
+    nRadius(nRadiusIn),
+    nSign(nSignIn),
+    padfDescriptor(new double[DESC_SIZE])
+{}
+
+GDALFeaturePoint& GDALFeaturePoint::operator=( const GDALFeaturePoint& point )
 {
-    nX = fp.nX;
-    nY = fp.nY;
-    nScale = fp.nScale;
-    nRadius = fp.nRadius;
-    nSign = fp.nSign;
+    if( this == &point )
+        return *this;
 
-    padfDescriptor = new double[DESC_SIZE];
-    for (int i = 0; i < DESC_SIZE; i++)
-        padfDescriptor[i] = fp.padfDescriptor[i];
-}
+    nX = point.nX;
+    nY = point.nY;
+    nScale = point.nScale;
+    nRadius = point.nRadius;
+    nSign = point.nSign;
 
-GDALFeaturePoint::GDALFeaturePoint(int nXIn, int nYIn,
-                                   int nScaleIn, int nRadiusIn, int nSignIn)
-{
-    nX = nXIn;
-    nY = nYIn;
-    nScale = nScaleIn;
-    nRadius = nRadiusIn;
-    nSign = nSignIn;
+    // Free memory.
+    delete[] padfDescriptor;
 
+    // Copy descriptor values.
     padfDescriptor = new double[DESC_SIZE];
-}
-
-GDALFeaturePoint& GDALFeaturePoint::operator=(const GDALFeaturePoint& point)
-{
-    if (this != &point)
-    {
-        nX = point.nX;
-        nY = point.nY;
-        nScale = point.nScale;
-        nRadius = point.nRadius;
-        nSign = point.nSign;
-
-        //Free memory
-        delete[] padfDescriptor;
-
-        //Copy descriptor values
-        padfDescriptor = new double[DESC_SIZE];
-        for (int i = 0; i < DESC_SIZE; i++)
-            padfDescriptor[i] = point.padfDescriptor[i];
-    }
+    for( int i = 0; i < DESC_SIZE; i++ )
+        padfDescriptor[i] = point.padfDescriptor[i];
 
     return *this;
 }
 
-int  GDALFeaturePoint::GetX() { return nX; }
-void GDALFeaturePoint::SetX(int nXIn) { nX = nXIn; }
+int  GDALFeaturePoint::GetX() const { return nX; }
+void GDALFeaturePoint::SetX( int nXIn ) { nX = nXIn; }
 
-int  GDALFeaturePoint::GetY() { return nY; }
-void GDALFeaturePoint::SetY(int nYIn) { nY = nYIn; }
+int  GDALFeaturePoint::GetY() const { return nY; }
+void GDALFeaturePoint::SetY( int nYIn ) { nY = nYIn; }
 
-int  GDALFeaturePoint::GetScale() { return nScale; }
-void GDALFeaturePoint::SetScale(int nScaleIn) { nScale = nScaleIn; }
+int  GDALFeaturePoint::GetScale() const { return nScale; }
+void GDALFeaturePoint::SetScale( int nScaleIn ) { nScale = nScaleIn; }
 
-int  GDALFeaturePoint::GetRadius() { return nRadius; }
-void GDALFeaturePoint::SetRadius(int nRadiusIn) { nRadius = nRadiusIn; }
+int  GDALFeaturePoint::GetRadius() const { return nRadius; }
+void GDALFeaturePoint::SetRadius( int nRadiusIn ) { nRadius = nRadiusIn; }
 
-int  GDALFeaturePoint::GetSign() { return nSign; }
-void GDALFeaturePoint::SetSign(int nSignIn) { nSign = nSignIn; }
+int  GDALFeaturePoint::GetSign() const { return nSign; }
+void GDALFeaturePoint::SetSign( int nSignIn ) { nSign = nSignIn; }
 
 double& GDALFeaturePoint::operator [] (int nIndex)
 {
-    if (nIndex < 0 || nIndex >= DESC_SIZE)
+    if( nIndex < 0 || nIndex >= DESC_SIZE )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Descriptor index is out of range");
@@ -129,46 +126,45 @@ GDALFeaturePoint::~GDALFeaturePoint() {
 /* ==================================================================== */
 /************************************************************************/
 
-GDALSimpleSURF::GDALSimpleSURF(int nOctaveStart, int nOctaveEnd)
-{
-    this->octaveStart = nOctaveStart;
-    this->octaveEnd = nOctaveEnd;
+GDALSimpleSURF::GDALSimpleSURF( int nOctaveStartIn, int nOctaveEndIn ) :
+    octaveStart(nOctaveStartIn),
+    octaveEnd(nOctaveEndIn),
+    // Initialize Octave map with custom range.
+    poOctMap(new GDALOctaveMap(nOctaveStartIn, nOctaveEndIn))
 
-    // Initialize Octave map with custom range
-    poOctMap = new GDALOctaveMap(octaveStart, octaveEnd);
-}
+{}
 
 CPLErr GDALSimpleSURF::ConvertRGBToLuminosity(
     GDALRasterBand *red, GDALRasterBand *green, GDALRasterBand *blue,
-    int nXSize, int nYSize, double **padfImg, int nHeight, int nWidth)
+    int nXSize, int nYSize, double **padfImg, int nHeight, int nWidth )
 {
-    const double forRed = 0.21;
-    const double forGreen = 0.72;
-    const double forBlue = 0.07;
-
-    if (red == NULL || green == NULL || blue == NULL)
+    if( red == NULL || green == NULL || blue == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Raster bands are not specified");
         return CE_Failure;
     }
 
-    if (nXSize > red->GetXSize() || nYSize > red->GetYSize())
+    if( nXSize > red->GetXSize() || nYSize > red->GetYSize() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Red band has less size than has been requested");
         return CE_Failure;
     }
 
-    if (padfImg == NULL)
+    if( padfImg == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Buffer isn't specified");
         return CE_Failure;
     }
 
-    GDALDataType eRedType = red->GetRasterDataType();
-    GDALDataType eGreenType = green->GetRasterDataType();
-    GDALDataType eBlueType = blue->GetRasterDataType();
+    const double forRed = 0.21;
+    const double forGreen = 0.72;
+    const double forBlue = 0.07;
+
+    const GDALDataType eRedType = red->GetRasterDataType();
+    const GDALDataType eGreenType = green->GetRasterDataType();
+    const GDALDataType eBlueType = blue->GetRasterDataType();
 
     const int dataRedSize = GDALGetDataTypeSizeBytes(eRedType);
     const int dataGreenSize = GDALGetDataTypeSizeBytes(eGreenType);
@@ -178,25 +174,28 @@ CPLErr GDALSimpleSURF::ConvertRGBToLuminosity(
     void *paGreenLayer = CPLMalloc(dataGreenSize * nWidth * nHeight);
     void *paBlueLayer = CPLMalloc(dataBlueSize * nWidth * nHeight);
 
-    CPLErr eErr;
-    eErr = red->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paRedLayer, nWidth, nHeight, eRedType, 0, 0, NULL);
+    CPLErr eErr = red->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paRedLayer,
+                                nWidth, nHeight, eRedType, 0, 0, NULL);
     if( eErr == CE_None )
-        eErr = green->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paGreenLayer, nWidth, nHeight, eGreenType, 0, 0, NULL);
+        eErr = green->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paGreenLayer,
+                               nWidth, nHeight, eGreenType, 0, 0, NULL);
     if( eErr == CE_None )
-        eErr = blue->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paBlueLayer, nWidth, nHeight, eBlueType, 0, 0, NULL);
+        eErr = blue->RasterIO(GF_Read, 0, 0, nXSize, nYSize, paBlueLayer,
+                              nWidth, nHeight, eBlueType, 0, 0, NULL);
 
     double maxValue = 255.0;
-    for (int row = 0; row < nHeight && eErr == CE_None; row++)
-        for (int col = 0; col < nWidth; col++)
+    for( int row = 0; row < nHeight && eErr == CE_None; row++ )
+        for( int col = 0; col < nWidth; col++ )
         {
-            // Get RGB values
-            double dfRedVal = SRCVAL(paRedLayer, eRedType,
-                                     nWidth * row + col * dataRedSize);
-            double dfGreenVal = SRCVAL(paGreenLayer, eGreenType,
-                                       nWidth * row + col * dataGreenSize);
-            double dfBlueVal = SRCVAL(paBlueLayer, eBlueType,
-                                      nWidth * row + col * dataBlueSize);
-            // Compute luminosity value
+            // Get RGB values.
+            const double dfRedVal = SRCVAL(paRedLayer, eRedType,
+                                           nWidth * row + col * dataRedSize);
+            const double dfGreenVal =
+                SRCVAL(paGreenLayer, eGreenType,
+                       nWidth * row + col * dataGreenSize);
+            const double dfBlueVal = SRCVAL(paBlueLayer, eBlueType,
+                                            nWidth * row + col * dataBlueSize);
+            // Compute luminosity value.
             padfImg[row][col] = (
                 dfRedVal * forRed +
                 dfGreenVal * forGreen +
@@ -211,29 +210,30 @@ CPLErr GDALSimpleSURF::ConvertRGBToLuminosity(
 }
 
 std::vector<GDALFeaturePoint>*
-GDALSimpleSURF::ExtractFeaturePoints(GDALIntegralImage *poImg,
-                                     double dfThreshold)
+GDALSimpleSURF::ExtractFeaturePoints( GDALIntegralImage *poImg,
+                                      double dfThreshold )
 {
     std::vector<GDALFeaturePoint>* poCollection =
         new std::vector<GDALFeaturePoint>();
 
-    //Calc Hessian values for layers
+    // Calc Hessian values for layers.
     poOctMap->ComputeMap(poImg);
 
     // Search for extremum points.
-    for (int oct = octaveStart; oct <= octaveEnd; oct++)
+    for( int oct = octaveStart; oct <= octaveEnd; oct++ )
     {
-        for (int k = 0; k < GDALOctaveMap::INTERVALS - 2; k++)
+        for( int k = 0; k < GDALOctaveMap::INTERVALS - 2; k++ )
         {
             GDALOctaveLayer *bot = poOctMap->pMap[oct - 1][k];
             GDALOctaveLayer *mid = poOctMap->pMap[oct - 1][k + 1];
             GDALOctaveLayer *top = poOctMap->pMap[oct - 1][k + 2];
 
-            for (int i = 0; i < mid->height; i++)
+            for( int i = 0; i < mid->height; i++ )
             {
-                for (int j = 0; j < mid->width; j++)
+                for( int j = 0; j < mid->width; j++ )
                 {
-                    if (poOctMap->PointIsExtremum(i, j, bot, mid, top, dfThreshold))
+                    if( poOctMap->PointIsExtremum(i, j, bot, mid, top,
+                                                  dfThreshold) )
                     {
                         GDALFeaturePoint oFP(j, i, mid->scale,
                                              mid->radius, mid->signs[i][j]);
@@ -248,79 +248,81 @@ GDALSimpleSURF::ExtractFeaturePoints(GDALIntegralImage *poImg,
     return poCollection;
 }
 
-
 double GDALSimpleSURF::GetEuclideanDistance(
     GDALFeaturePoint &firstPoint, GDALFeaturePoint &secondPoint)
 {
-    double sum = 0;
+    double sum = 0.0;
 
-    for (int i = 0; i < GDALFeaturePoint::DESC_SIZE; i++)
-        sum += (firstPoint[i] - secondPoint[i]) * (firstPoint[i] - secondPoint[i]);
+    for( int i = 0; i < GDALFeaturePoint::DESC_SIZE; i++ )
+        sum += (firstPoint[i] - secondPoint[i]) *
+               (firstPoint[i] - secondPoint[i]);
 
     return sqrt(sum);
 }
 
 void GDALSimpleSURF::NormalizeDistances(std::list<MatchedPointPairInfo> *poList)
 {
-    double max = 0;
+    double max = 0.0;
 
     std::list<MatchedPointPairInfo>::iterator i;
-    for (i = poList->begin(); i != poList->end(); i++)
-        if ((*i).euclideanDist > max)
+    for( i = poList->begin(); i != poList->end(); ++i )
+        if( (*i).euclideanDist > max )
             max = (*i).euclideanDist;
 
-    if (max != 0)
+    if( max != 0.0 )
     {
-        for (i = poList->begin(); i != poList->end(); i++)
+        for( i = poList->begin(); i != poList->end(); ++i )
             (*i).euclideanDist /= max;
     }
 }
 
 void GDALSimpleSURF::SetDescriptor(
-    GDALFeaturePoint *poPoint, GDALIntegralImage *poImg)
+    GDALFeaturePoint *poPoint, GDALIntegralImage *poImg )
 {
-    // Affects to the descriptor area
+    // Affects to the descriptor area.
     const int haarScale = 20;
 
-    // Side of the Haar wavelet
-    int haarFilterSize = 2 * poPoint->GetScale();
+    // Side of the Haar wavelet.
+    const int haarFilterSize = 2 * poPoint->GetScale();
 
-    // Length of the side of the descriptor area
-    int descSide = haarScale * poPoint->GetScale();
+    // Length of the side of the descriptor area.
+    const int descSide = haarScale * poPoint->GetScale();
 
-    // Side of the quadrant in 4x4 grid
-    int quadStep = descSide / 4;
+    // Side of the quadrant in 4x4 grid.
+    const int quadStep = descSide / 4;
 
-    // Side of the sub-quadrant in 5x5 regular grid of quadrant
-    int subQuadStep = quadStep / 5;
+    // Side of the sub-quadrant in 5x5 regular grid of quadrant.
+    const int subQuadStep = quadStep / 5;
 
-    int leftTop_row = poPoint->GetY() - (descSide / 2);
-    int leftTop_col = poPoint->GetX() - (descSide / 2);
+    const int leftTop_row = poPoint->GetY() - (descSide / 2);
+    const int leftTop_col = poPoint->GetX() - (descSide / 2);
 
     int count = 0;
 
-    for (int r = leftTop_row; r < leftTop_row + descSide; r += quadStep)
-        for (int c = leftTop_col; c < leftTop_col + descSide; c += quadStep)
+    for( int r = leftTop_row; r < leftTop_row + descSide; r += quadStep )
+        for( int c = leftTop_col; c < leftTop_col + descSide; c += quadStep )
         {
             double dx = 0;
             double dy = 0;
             double abs_dx = 0;
             double abs_dy = 0;
 
-            for (int sub_r = r; sub_r < r + quadStep; sub_r += subQuadStep)
-                for (int sub_c = c; sub_c < c + quadStep; sub_c += subQuadStep)
+            for( int sub_r = r; sub_r < r + quadStep; sub_r += subQuadStep )
+                for( int sub_c = c; sub_c < c + quadStep; sub_c += subQuadStep )
                 {
-                    // Approximate center of sub quadrant
-                    int cntr_r = sub_r + subQuadStep / 2;
-                    int cntr_c = sub_c + subQuadStep / 2;
+                    // Approximate center of sub quadrant.
+                    const int cntr_r = sub_r + subQuadStep / 2;
+                    const int cntr_c = sub_c + subQuadStep / 2;
 
-                    // Left top point for Haar wavelet computation
-                    int cur_r = cntr_r - haarFilterSize / 2;
-                    int cur_c = cntr_c - haarFilterSize / 2;
+                    // Left top point for Haar wavelet computation.
+                    const int cur_r = cntr_r - haarFilterSize / 2;
+                    const int cur_c = cntr_c - haarFilterSize / 2;
 
-                    // Gradients
-                    double cur_dx = poImg->HaarWavelet_X(cur_r, cur_c, haarFilterSize);
-                    double cur_dy = poImg->HaarWavelet_Y(cur_r, cur_c, haarFilterSize);
+                    // Gradients.
+                    const double cur_dx =
+                        poImg->HaarWavelet_X(cur_r, cur_c, haarFilterSize);
+                    const double cur_dy =
+                        poImg->HaarWavelet_Y(cur_r, cur_c, haarFilterSize);
 
                     dx += cur_dx;
                     dy += cur_dy;
@@ -328,7 +330,7 @@ void GDALSimpleSURF::SetDescriptor(
                     abs_dy += fabs(cur_dy);
                 }
 
-            // Fills point's descriptor
+            // Fills point's descriptor.
             (*poPoint)[count++] = dx;
             (*poPoint)[count++] = dy;
             (*poPoint)[count++] = abs_dx;
@@ -336,12 +338,15 @@ void GDALSimpleSURF::SetDescriptor(
         }
 }
 
+// TODO(schwehr): What does "value is 0,1." mean?  Is that 0 to 1 or 0.1?
+// TODO(schwehr): 0,001?
+
 /**
  * Find corresponding points (equal points in two collections).
  *
- * @param poMatched Resulting collection for matched points
- * @param poFirstCollection Points on the first image
- * @param poSecondCollection Points on the second image
+ * @param poMatchPairs Resulting collection for matched points
+ * @param poFirstCollect Points on the first image
+ * @param poSecondCollect Points on the second image
  * @param dfThreshold Value from 0 to 1. Threshold affects to number of
  * matched points. If threshold is higher, amount of corresponding
  * points is larger, and vice versa
@@ -349,10 +354,10 @@ void GDALSimpleSURF::SetDescriptor(
  * @note Typical threshold's value is 0,1. BUT it's a very approximate guide.
  * It can be 0,001 or even 1. This threshold provides direct adjustment
  * of point matching.
- * NOTICE that if threshold is lower, matches are more robust and correct, but number of
- * matched points is smaller. Therefore if algorithm performs many false
- * detections and produces bad results, reduce threshold.
- * Otherwise, if algorithm finds nothing, increase threshold.
+ * NOTICE that if threshold is lower, matches are more robust and correct, but
+ * number of matched points is smaller. Therefore if algorithm performs many
+ * false detections and produces bad results, reduce threshold.  Otherwise, if
+ * algorithm finds nothing, increase threshold.
  *
  * @return CE_None or CE_Failure if error occurs.
  */
@@ -361,19 +366,19 @@ CPLErr GDALSimpleSURF::MatchFeaturePoints(
     std::vector<GDALFeaturePoint*> *poMatchPairs,
     std::vector<GDALFeaturePoint> *poFirstCollect,
     std::vector<GDALFeaturePoint> *poSecondCollect,
-    double dfThreshold)
+    double dfThreshold )
 {
 /* -------------------------------------------------------------------- */
 /*      Validate parameters.                                            */
 /* -------------------------------------------------------------------- */
-    if (poMatchPairs == NULL)
+    if( poMatchPairs == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Matched points collection isn't specified" );
         return CE_Failure;
     }
 
-    if (poFirstCollect == NULL || poSecondCollect == NULL)
+    if( poFirstCollect == NULL || poSecondCollect == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Feature point collections are not specified");
@@ -383,99 +388,94 @@ CPLErr GDALSimpleSURF::MatchFeaturePoints(
 /* ==================================================================== */
 /*      Matching algorithm.                                             */
 /* ==================================================================== */
-    // Affects to false matching pruning
+    // Affects to false matching pruning.
     const double ratioThreshold = 0.8;
 
     int len_1 = static_cast<int>(poFirstCollect->size());
     int len_2 = static_cast<int>(poSecondCollect->size());
 
-    int minLength = (len_1 < len_2) ? len_1 : len_2;
+    const int minLength = std::min(len_1, len_2);
 
-    // Temporary pointers. Used to swap collections
+    // Temporary pointers. Used to swap collections.
     std::vector<GDALFeaturePoint> *p_1;
     std::vector<GDALFeaturePoint> *p_2;
 
     bool isSwap = false;
 
-    // Assign p_1 - collection with minimal number of points
-    if (minLength == len_2)
+    // Assign p_1 - collection with minimal number of points.
+    if( minLength == len_2 )
     {
         p_1 = poSecondCollect;
         p_2 = poFirstCollect;
 
-        int tmp = 0;
-        tmp = len_1;
-        len_1 = len_2;
-        len_2 = tmp;
+        std::swap(len_1, len_2);
         isSwap = true;
     }
     else
     {
-        // Assignment 'as is'
+        // Assignment 'as is'.
         p_1 = poFirstCollect;
         p_2 = poSecondCollect;
         isSwap = false;
     }
 
-    // Stores matched point indexes and
-    // their euclidean distances
+    // Stores matched point indexes and their euclidean distances.
     std::list<MatchedPointPairInfo> *poPairInfoList =
         new std::list<MatchedPointPairInfo>();
 
-    // Flags that points in the 2nd collection are matched or not
+    // Flags that points in the 2nd collection are matched or not.
     bool *alreadyMatched = new bool[len_2];
-    for (int i = 0; i < len_2; i++)
+    for( int i = 0; i < len_2; i++ )
         alreadyMatched[i] = false;
 
-    for (int i = 0; i < len_1; i++)
+    for( int i = 0; i < len_1; i++ )
     {
-        // Distance to the nearest point
+        // Distance to the nearest point.
         double bestDist = -1;
-        // Index of the nearest point in p_2 collection
+        // Index of the nearest point in p_2 collection.
         int bestIndex = -1;
 
-        // Distance to the 2nd nearest point
+        // Distance to the 2nd nearest point.
         double bestDist_2 = -1;
 
-        // Find the nearest and 2nd nearest points
-        for (int j = 0; j < len_2; j++)
-            if (!alreadyMatched[j])
-                if (p_1->at(i).GetSign() ==
-                    p_2->at(j).GetSign())
+        // Find the nearest and 2nd nearest points.
+        for( int j = 0; j < len_2; j++ )
+            if( !alreadyMatched[j] )
+                if( p_1->at(i).GetSign() == p_2->at(j).GetSign() )
                 {
-                    // Get distance between two feature points
+                    // Get distance between two feature points.
                     double curDist = GetEuclideanDistance(
                         p_1->at(i), p_2->at(j));
 
-                    if (bestDist == -1)
+                    if( bestDist == -1 )
                     {
                         bestDist = curDist;
                         bestIndex = j;
                     }
                     else
                     {
-                        if (curDist < bestDist)
+                        if( curDist < bestDist )
                         {
                             bestDist = curDist;
                             bestIndex = j;
                         }
                     }
 
-                    // Findes the 2nd nearest point
-                    if (bestDist_2 < 0)
+                    // Findes the 2nd nearest point.
+                    if( bestDist_2 < 0 )
                         bestDist_2 = curDist;
                     else
-                        if (curDist > bestDist && curDist < bestDist_2)
+                        if( curDist > bestDist && curDist < bestDist_2 )
                             bestDist_2 = curDist;
                 }
 /* -------------------------------------------------------------------- */
-/*	    False matching pruning.                                         */
+/*      False matching pruning.                                         */
 /* If ratio bestDist to bestDist_2 greater than 0.8 =>                  */
-/* 		consider as false detection.                                    */
+/*     consider as false detection.                                     */
 /* Otherwise, add points as matched pair.                               */
 /*----------------------------------------------------------------------*/
-        if (bestDist_2 > 0 && bestDist >= 0)
-            if (bestDist / bestDist_2 < ratioThreshold)
+        if( bestDist_2 > 0 && bestDist >= 0 )
+            if( bestDist / bestDist_2 < ratioThreshold )
             {
                 MatchedPointPairInfo info(i, bestIndex, bestDist);
                 poPairInfoList->push_back(info);
@@ -483,7 +483,6 @@ CPLErr GDALSimpleSURF::MatchFeaturePoints(
             }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Pruning based on the provided threshold                         */
 /* -------------------------------------------------------------------- */
@@ -491,15 +490,15 @@ CPLErr GDALSimpleSURF::MatchFeaturePoints(
     NormalizeDistances(poPairInfoList);
 
     std::list<MatchedPointPairInfo>::const_iterator iter;
-    for (iter = poPairInfoList->begin(); iter != poPairInfoList->end(); iter++)
+    for( iter = poPairInfoList->begin(); iter != poPairInfoList->end(); ++iter )
     {
-        if ((*iter).euclideanDist <= dfThreshold)
+        if( (*iter).euclideanDist <= dfThreshold )
         {
-            int i_1 = (*iter).ind_1;
-            int i_2 = (*iter).ind_2;
+            const int i_1 = (*iter).ind_1;
+            const int i_2 = (*iter).ind_2;
 
-            // Add copies into MatchedCollection
-            if(!isSwap)
+            // Add copies into MatchedCollection.
+            if( !isSwap )
             {
                 poMatchPairs->push_back( &(p_1->at(i_1)) );
                 poMatchPairs->push_back( &(p_2->at(i_2)) );
@@ -512,7 +511,7 @@ CPLErr GDALSimpleSURF::MatchFeaturePoints(
         }
     }
 
-    // Clean up
+    // Clean up.
     delete[] alreadyMatched;
     delete poPairInfoList;
 
diff --git a/alg/gdal_simplesurf.h b/alg/gdal_simplesurf.h
index ca262dc..cc48bdf 100644
--- a/alg/gdal_simplesurf.h
+++ b/alg/gdal_simplesurf.h
@@ -1,4 +1,5 @@
 /******************************************************************************
+ * $Id: gdal_simplesurf.h 36666 2016-12-04 04:32:31Z goatbar $
  * Project:  GDAL
  * Purpose:  Correlator
  * Author:   Andrew Migal, migal.drew at gmail.com
@@ -76,6 +77,7 @@ public:
     GDALFeaturePoint(int nX, int nY, int nScale, int nRadius, int nSign);
     virtual ~GDALFeaturePoint();
 
+    /** Assignment operator */
     GDALFeaturePoint& operator=(const GDALFeaturePoint& point);
 
     /**
@@ -89,7 +91,7 @@ public:
      */
     double& operator[](int nIndex);
 
-    // Descriptor length
+    /** Descriptor length */
     static const int DESC_SIZE = 64;
 
     /**
@@ -97,7 +99,7 @@ public:
      *
      * @return X-coordinate in pixels
      */
-    int GetX();
+    int GetX() const;
 
     /**
      * Set X coordinate of point
@@ -111,7 +113,7 @@ public:
      *
      * @return Y-coordinate in pixels.
      */
-    int  GetY();
+    int GetY() const;
 
     /**
      * Set Y coordinate of point.
@@ -125,7 +127,7 @@ public:
      *
      * @return Scale for this point.
      */
-    int  GetScale();
+    int GetScale() const ;
 
     /**
      * Set scale of point.
@@ -139,7 +141,7 @@ public:
      *
      * @return Radius for this point.
      */
-    int  GetRadius();
+    int  GetRadius() const;
 
     /**
      * Set radius of point.
@@ -153,7 +155,7 @@ public:
      *
      * @return Sign for this point.
      */
-    int  GetSign();
+    int GetSign() const;
 
     /**
      * Set sign of point.
@@ -340,6 +342,8 @@ public:
  */
 class GDALOctaveMap
 {
+    CPL_DISALLOW_COPY_ASSIGN( GDALOctaveMap )
+
 public:
     /**
      * Create octave space. Octave numbers are start with one. (1, 2, 3, 4, ... )
@@ -375,7 +379,7 @@ public:
      *
      * @return TRUE if candidate was evaluated as feature point or FALSE otherwise.
      */
-    bool PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
+    static bool PointIsExtremum(int row, int col, GDALOctaveLayer *bot,
                          GDALOctaveLayer *mid, GDALOctaveLayer *top, double threshold);
 
     /**
@@ -432,6 +436,8 @@ private:
         double euclideanDist;
     };
 
+    CPL_DISALLOW_COPY_ASSIGN( GDALSimpleSURF )
+
 public:
     /**
      * Prepare class according to specified parameters. Octave numbers affects
@@ -501,7 +507,7 @@ public:
      * Find corresponding points (equal points in two collections).
      *
      * @param poMatchPairs Resulting collection for matched points
-     * @param poSecondCollect Points on the first image
+     * @param poFirstCollect Points on the first image
      * @param poSecondCollect Points on the second image
      * @param dfThreshold Value from 0 to 1. Threshold affects to number of
      * matched points. If threshold is lower, amount of corresponding
@@ -541,8 +547,7 @@ private:
      * @param poPoint Feature point instance
      * @param poImg image where feature point was found
      */
-    void SetDescriptor(GDALFeaturePoint *poPoint, GDALIntegralImage *poImg);
-
+    static void SetDescriptor(GDALFeaturePoint *poPoint, GDALIntegralImage *poImg);
 
 private:
     int octaveStart;
@@ -550,5 +555,4 @@ private:
     GDALOctaveMap *poOctMap;
 };
 
-
 #endif /* GDALSIMPLESURF_H_ */
diff --git a/alg/gdal_tps.cpp b/alg/gdal_tps.cpp
index 6bf229c..ead9844 100644
--- a/alg/gdal_tps.cpp
+++ b/alg/gdal_tps.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_tps.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Thin Plate Spline transformer (GDAL wrapper portion)
@@ -28,17 +27,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "thinplatespline.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <map>
+#include <utility>
+
+#include "cpl_atomic_ops.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "gdal.h"
 #include "gdal_alg.h"
 #include "gdal_alg_priv.h"
 #include "gdal_priv.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "cpl_atomic_ops.h"
-#include "cpl_multiproc.h"
-#include <map>
 
-CPL_CVSID("$Id: gdal_tps.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: gdal_tps.cpp 36667 2016-12-04 05:25:23Z goatbar $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg );
@@ -51,10 +59,10 @@ typedef struct
 
     VizGeorefSpline2D   *poForward;
     VizGeorefSpline2D   *poReverse;
-    int                  bForwardSolved;
-    int                  bReverseSolved;
+    bool                 bForwardSolved;
+    bool                 bReverseSolved;
 
-    int       bReversed;
+    bool      bReversed;
 
     int       nGCPCount;
     GDAL_GCP *pasGCPList;
@@ -68,29 +76,31 @@ typedef struct
 /************************************************************************/
 
 static
-void* GDALCreateSimilarTPSTransformer( void *hTransformArg, double dfRatioX, double dfRatioY )
+void* GDALCreateSimilarTPSTransformer( void *hTransformArg,
+                                       double dfRatioX, double dfRatioY )
 {
     VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarTPSTransformer", NULL );
 
-    TPSTransformInfo *psInfo = (TPSTransformInfo *) hTransformArg;
+    TPSTransformInfo *psInfo = static_cast<TPSTransformInfo *>(hTransformArg);
 
     if( dfRatioX == 1.0 && dfRatioY == 1.0 )
     {
-        /* We can just use a ref count, since using the source transformation */
-        /* is thread-safe */
+        // We can just use a ref count, since using the source transformation
+        // is thread-safe.
         CPLAtomicInc(&(psInfo->nRefCount));
     }
     else
     {
         GDAL_GCP *pasGCPList = GDALDuplicateGCPs( psInfo->nGCPCount,
                                                   psInfo->pasGCPList );
-        for(int i=0;i<psInfo->nGCPCount;i++)
+        for( int i = 0; i < psInfo->nGCPCount; i++ )
         {
             pasGCPList[i].dfGCPPixel /= dfRatioX;
             pasGCPList[i].dfGCPLine /= dfRatioY;
         }
-        psInfo = (TPSTransformInfo *) GDALCreateTPSTransformer( psInfo->nGCPCount, pasGCPList,
-                                           psInfo->bReversed );
+        psInfo = static_cast<TPSTransformInfo *>(
+            GDALCreateTPSTransformer( psInfo->nGCPCount, pasGCPList,
+                                      psInfo->bReversed ));
         GDALDeinitGCPs( psInfo->nGCPCount, pasGCPList );
         CPLFree( pasGCPList );
     }
@@ -137,9 +147,9 @@ void *GDALCreateTPSTransformer( int nGCPCount, const GDAL_GCP *pasGCPList,
     return GDALCreateTPSTransformerInt(nGCPCount, pasGCPList, bReversed, NULL);
 }
 
-static void GDALTPSComputeForwardInThread(void* pData)
+static void GDALTPSComputeForwardInThread( void *pData )
 {
-    TPSTransformInfo *psInfo = (TPSTransformInfo *)pData;
+    TPSTransformInfo *psInfo = static_cast<TPSTransformInfo *>(pData);
     psInfo->bForwardSolved = psInfo->poForward->solve() != 0;
 }
 
@@ -147,22 +157,22 @@ void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
                                    int bReversed, char** papszOptions )
 
 {
-    TPSTransformInfo *psInfo;
-    int    iGCP;
-
 /* -------------------------------------------------------------------- */
 /*      Allocate transform info.                                        */
 /* -------------------------------------------------------------------- */
-    psInfo = (TPSTransformInfo *) CPLCalloc(sizeof(TPSTransformInfo),1);
+    TPSTransformInfo *psInfo = static_cast<TPSTransformInfo *>(
+        CPLCalloc(sizeof(TPSTransformInfo), 1));
 
     psInfo->pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPList );
     psInfo->nGCPCount = nGCPCount;
 
-    psInfo->bReversed = bReversed;
+    psInfo->bReversed = CPL_TO_BOOL(bReversed);
     psInfo->poForward = new VizGeorefSpline2D( 2 );
     psInfo->poReverse = new VizGeorefSpline2D( 2 );
 
-    memcpy( psInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
+    memcpy( psInfo->sTI.abySignature,
+            GDAL_GTI2_SIGNATURE,
+            strlen(GDAL_GTI2_SIGNATURE) );
     psInfo->sTI.pszClassName = "GDALTPSTransformer";
     psInfo->sTI.pfnTransform = GDALTPSTransform;
     psInfo->sTI.pfnCleanup = GDALDestroyTPSTransformer;
@@ -174,17 +184,17 @@ void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
 /* -------------------------------------------------------------------- */
     std::map< std::pair<double, double>, int > oMapPixelLineToIdx;
     std::map< std::pair<double, double>, int > oMapXYToIdx;
-    for( iGCP = 0; iGCP < nGCPCount; iGCP++ )
+    for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
     {
-        double    afPL[2], afXY[2];
-
-        afPL[0] = pasGCPList[iGCP].dfGCPPixel;
-        afPL[1] = pasGCPList[iGCP].dfGCPLine;
-        afXY[0] = pasGCPList[iGCP].dfGCPX;
-        afXY[1] = pasGCPList[iGCP].dfGCPY;
-
-        std::map< std::pair<double, double>, int >::iterator oIter;
-        oIter = oMapPixelLineToIdx.find( std::pair<double,double>(afPL[0], afPL[1]) );
+        const double afPL[2] = {
+            pasGCPList[iGCP].dfGCPPixel,
+            pasGCPList[iGCP].dfGCPLine };
+        const double afXY[2] =
+            { pasGCPList[iGCP].dfGCPX, pasGCPList[iGCP].dfGCPY };
+
+        std::map< std::pair<double, double>, int >::iterator oIter(
+            oMapPixelLineToIdx.find(std::pair<double, double>(afPL[0],
+                                                              afPL[1])));
         if( oIter != oMapPixelLineToIdx.end() )
         {
             if( afXY[0] == pasGCPList[oIter->second].dfGCPX &&
@@ -195,31 +205,36 @@ void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
             else
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
-                         "GCP %d and %d have same (pixel,line)=(%f,%f) but different (X,Y): (%f,%f) vs (%f,%f)",
+                         "GCP %d and %d have same (pixel,line)=(%f,%f), "
+                         "but different (X,Y): (%f,%f) vs (%f,%f)",
                          iGCP + 1, oIter->second,
                          afPL[0], afPL[1],
                          afXY[0], afXY[1],
-                         pasGCPList[oIter->second].dfGCPX, pasGCPList[oIter->second].dfGCPY);
+                         pasGCPList[oIter->second].dfGCPX,
+                         pasGCPList[oIter->second].dfGCPY);
             }
         }
         else
         {
-            oMapPixelLineToIdx[ std::pair<double,double>(afPL[0], afPL[1]) ] = iGCP;
+            oMapPixelLineToIdx[std::pair<double, double>(afPL[0], afPL[1])] =
+                iGCP;
         }
 
-        oIter = oMapXYToIdx.find( std::pair<double,double>(afXY[0], afXY[1]) );
+        oIter = oMapXYToIdx.find(std::pair<double, double>(afXY[0], afXY[1]));
         if( oIter != oMapXYToIdx.end() )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
-                        "GCP %d and %d have same (x,y)=(%f,%f) but different (pixel,line): (%f,%f) vs (%f,%f)",
-                        iGCP + 1, oIter->second,
-                        afXY[0], afXY[1],
-                        afPL[0], afPL[1],
-                        pasGCPList[oIter->second].dfGCPPixel, pasGCPList[oIter->second].dfGCPLine);
+                     "GCP %d and %d have same (x,y)=(%f,%f), "
+                     "but different (pixel,line): (%f,%f) vs (%f,%f)",
+                     iGCP + 1, oIter->second,
+                     afXY[0], afXY[1],
+                     afPL[0], afPL[1],
+                     pasGCPList[oIter->second].dfGCPPixel,
+                     pasGCPList[oIter->second].dfGCPLine);
         }
         else
         {
-            oMapXYToIdx[ std::pair<double,double>(afXY[0], afXY[1]) ] = iGCP;
+            oMapXYToIdx[std::pair<double, double>(afXY[0], afXY[1])] = iGCP;
         }
 
         bool bOK = true;
@@ -245,10 +260,11 @@ void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
     int nThreads = 1;
     if( nGCPCount > 100 )
     {
-        const char* pszWarpThreads = CSLFetchNameValue(papszOptions, "NUM_THREADS");
-        if (pszWarpThreads == NULL)
+        const char* pszWarpThreads =
+            CSLFetchNameValue(papszOptions, "NUM_THREADS");
+        if( pszWarpThreads == NULL )
             pszWarpThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "1");
-        if (EQUAL(pszWarpThreads, "ALL_CPUS"))
+        if( EQUAL(pszWarpThreads, "ALL_CPUS") )
             nThreads = CPLGetNumCPUs();
         else
             nThreads = atoi(pszWarpThreads);
@@ -256,8 +272,9 @@ void *GDALCreateTPSTransformerInt( int nGCPCount, const GDAL_GCP *pasGCPList,
 
     if( nThreads > 1 )
     {
-        /* Compute direct and reverse transforms in parallel */
-        CPLJoinableThread* hThread = CPLCreateJoinableThread(GDALTPSComputeForwardInThread, psInfo);
+        // Compute direct and reverse transforms in parallel.
+        CPLJoinableThread* hThread =
+            CPLCreateJoinableThread(GDALTPSComputeForwardInThread, psInfo);
         psInfo->bReverseSolved = psInfo->poReverse->solve() != 0;
         if( hThread != NULL )
             CPLJoinThread(hThread);
@@ -299,7 +316,7 @@ void GDALDestroyTPSTransformer( void *pTransformArg )
     if( pTransformArg == NULL )
         return;
 
-    TPSTransformInfo *psInfo = (TPSTransformInfo *) pTransformArg;
+    TPSTransformInfo *psInfo = static_cast<TPSTransformInfo *>(pTransformArg);
 
     if( CPLAtomicDec(&(psInfo->nRefCount)) == 0 )
     {
@@ -346,12 +363,11 @@ int GDALTPSTransform( void *pTransformArg, int bDstToSrc,
 {
     VALIDATE_POINTER1( pTransformArg, "GDALTPSTransform", 0 );
 
-    int    i;
-    TPSTransformInfo *psInfo = (TPSTransformInfo *) pTransformArg;
+    TPSTransformInfo *psInfo = static_cast<TPSTransformInfo *>(pTransformArg);
 
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
-        double xy_out[2];
+        double xy_out[2] = { 0.0, 0.0 };
 
         if( bDstToSrc )
         {
@@ -380,20 +396,19 @@ CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg )
 {
     VALIDATE_POINTER1( pTransformArg, "GDALSerializeTPSTransformer", NULL );
 
-    CPLXMLNode *psTree;
     TPSTransformInfo *psInfo = static_cast<TPSTransformInfo *>(pTransformArg);
 
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "TPSTransformer" );
+    CPLXMLNode *psTree = CPLCreateXMLNode(NULL, CXT_Element, "TPSTransformer");
 
 /* -------------------------------------------------------------------- */
 /*      Serialize bReversed.                                            */
 /* -------------------------------------------------------------------- */
     CPLCreateXMLElementAndValue(
         psTree, "Reversed",
-        CPLString().Printf( "%d", psInfo->bReversed ) );
+        CPLString().Printf( "%d", static_cast<int>(psInfo->bReversed) ) );
 
 /* -------------------------------------------------------------------- */
-/*	Attach GCP List. 						*/
+/*      Attach GCP List.                                                */
 /* -------------------------------------------------------------------- */
     if( psInfo->nGCPCount > 0 )
     {
@@ -413,15 +428,12 @@ CPLXMLNode *GDALSerializeTPSTransformer( void *pTransformArg )
 void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree )
 
 {
-    GDAL_GCP *pasGCPList = NULL;
-    int nGCPCount = 0;
-    void *pResult;
-    int bReversed;
-
     /* -------------------------------------------------------------------- */
     /*      Check for GCPs.                                                 */
     /* -------------------------------------------------------------------- */
     CPLXMLNode *psGCPList = CPLGetXMLNode( psTree, "GCPList" );
+    GDAL_GCP *pasGCPList = NULL;
+    int nGCPCount = 0;
 
     if( psGCPList != NULL )
     {
@@ -434,12 +446,13 @@ void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
 /*      Get other flags.                                                */
 /* -------------------------------------------------------------------- */
-    bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));
+    const int bReversed = atoi(CPLGetXMLValue(psTree, "Reversed", "0"));
 
 /* -------------------------------------------------------------------- */
 /*      Generate transformation.                                        */
 /* -------------------------------------------------------------------- */
-    pResult = GDALCreateTPSTransformer( nGCPCount, pasGCPList, bReversed );
+    void *pResult =
+        GDALCreateTPSTransformer( nGCPCount, pasGCPList, bReversed );
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup GCP copy.                                               */
diff --git a/alg/gdalapplyverticalshiftgrid.cpp b/alg/gdalapplyverticalshiftgrid.cpp
new file mode 100644
index 0000000..95d3cf4
--- /dev/null
+++ b/alg/gdalapplyverticalshiftgrid.cpp
@@ -0,0 +1,744 @@
+/******************************************************************************
+ *
+ * Project:  GDAL algorithms
+ * Purpose:  Apply vertical shift grid
+ * Author:   Even Rouault, even.rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "gdal_priv.h"
+#include "gdal_utils.h"
+#include "gdalwarper.h"
+#include "vrtdataset.h"
+#include "ogr_spatialref.h"
+
+#ifdef PROJ_STATIC
+#include "proj_api.h"
+#endif
+
+#include <limits>
+
+CPL_CVSID("$Id: gdalapplyverticalshiftgrid.cpp 37987 2017-04-14 07:42:50Z rouault $");
+
+/************************************************************************/
+/*                        GDALApplyVSGDataset                           */
+/************************************************************************/
+
+class GDALApplyVSGDataset: public GDALDataset
+{
+        friend class GDALApplyVSGRasterBand;
+
+        GDALDataset* m_poSrcDataset;
+        GDALDataset* m_poReprojectedGrid;
+        bool         m_bInverse;
+        double       m_dfSrcUnitToMeter;
+        double       m_dfDstUnitToMeter;
+
+    public:
+        GDALApplyVSGDataset( GDALDataset* poSrcDataset,
+                             GDALDataset* poReprojectedGrid,
+                             GDALDataType eDT,
+                             bool bInverse,
+                             double dfSrcUnitToMeter,
+                             double dfDstUnitToMeter,
+                             int nBlockSize );
+        virtual ~GDALApplyVSGDataset();
+
+        virtual int        CloseDependentDatasets() override;
+
+        virtual CPLErr GetGeoTransform(double* padfGeoTransform) override;
+        virtual const char* GetProjectionRef() override;
+
+        bool    IsInitOK();
+};
+
+/************************************************************************/
+/*                       GDALApplyVSGRasterBand                         */
+/************************************************************************/
+
+class GDALApplyVSGRasterBand: public GDALRasterBand
+{
+        friend class GDALApplyVSGDataset;
+
+        float       *m_pafSrcData;
+        float       *m_pafGridData;
+
+    public:
+        GDALApplyVSGRasterBand( GDALDataType eDT,
+                                int nBlockSize );
+        virtual ~GDALApplyVSGRasterBand();
+
+        virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff,
+                                   void * pData ) override;
+        virtual double GetNoDataValue( int* pbSuccess ) override;
+};
+
+/************************************************************************/
+/*                        GDALApplyVSGDataset()                         */
+/************************************************************************/
+
+GDALApplyVSGDataset::GDALApplyVSGDataset( GDALDataset* poSrcDataset,
+                                          GDALDataset* poReprojectedGrid,
+                                          GDALDataType eDT,
+                                          bool bInverse,
+                                          double dfSrcUnitToMeter,
+                                          double dfDstUnitToMeter,
+                                          int nBlockSize ) :
+    m_poSrcDataset(poSrcDataset),
+    m_poReprojectedGrid(poReprojectedGrid),
+    m_bInverse(bInverse),
+    m_dfSrcUnitToMeter(dfSrcUnitToMeter),
+    m_dfDstUnitToMeter(dfDstUnitToMeter)
+{
+    m_poSrcDataset->Reference();
+    m_poReprojectedGrid->Reference();
+
+    nRasterXSize = poSrcDataset->GetRasterXSize();
+    nRasterYSize = poSrcDataset->GetRasterYSize();
+    SetBand( 1, new GDALApplyVSGRasterBand( eDT, nBlockSize ) );
+}
+
+/************************************************************************/
+/*                       ~GDALApplyVSGDataset()                         */
+/************************************************************************/
+
+GDALApplyVSGDataset::~GDALApplyVSGDataset()
+{
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                     CloseDependentDatasets()                         */
+/************************************************************************/
+
+int GDALApplyVSGDataset::CloseDependentDatasets()
+{
+    bool bRet = false;
+    if( m_poSrcDataset != NULL )
+    {
+        if( m_poSrcDataset->ReleaseRef() )
+        {
+            bRet = true;
+        }
+        m_poSrcDataset = NULL;
+    }
+    if( m_poReprojectedGrid != NULL )
+    {
+        if( m_poReprojectedGrid->ReleaseRef() )
+        {
+            bRet = true;
+        }
+        m_poReprojectedGrid = NULL;
+    }
+    return bRet;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr GDALApplyVSGDataset::GetGeoTransform(double* padfGeoTransform)
+{
+    return m_poSrcDataset->GetGeoTransform(padfGeoTransform);
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char* GDALApplyVSGDataset::GetProjectionRef()
+{
+    return m_poSrcDataset->GetProjectionRef();
+}
+
+/************************************************************************/
+/*                             IsInitOK()                               */
+/************************************************************************/
+
+bool GDALApplyVSGDataset::IsInitOK()
+{
+    GDALApplyVSGRasterBand* poBand =
+        reinterpret_cast<GDALApplyVSGRasterBand*>(GetRasterBand(1));
+    return poBand->m_pafSrcData != NULL && poBand->m_pafGridData != NULL;
+}
+
+/************************************************************************/
+/*                       GDALApplyVSGRasterBand()                       */
+/************************************************************************/
+
+GDALApplyVSGRasterBand::GDALApplyVSGRasterBand( GDALDataType eDT,
+                                                int nBlockSize )
+{
+    eDataType = eDT;
+    nBlockXSize = nBlockSize;
+    nBlockYSize = nBlockSize;
+    m_pafSrcData = static_cast<float*>(
+        VSI_MALLOC3_VERBOSE(nBlockXSize, nBlockYSize, sizeof(float)));
+    m_pafGridData = static_cast<float*>(
+        VSI_MALLOC3_VERBOSE(nBlockXSize, nBlockYSize, sizeof(float)));
+}
+
+/************************************************************************/
+/*                      ~GDALApplyVSGRasterBand()                       */
+/************************************************************************/
+
+GDALApplyVSGRasterBand::~GDALApplyVSGRasterBand()
+{
+    VSIFree(m_pafSrcData);
+    VSIFree(m_pafGridData);
+}
+
+/************************************************************************/
+/*                           GetNoDataValue()                           */
+/************************************************************************/
+
+double GDALApplyVSGRasterBand::GetNoDataValue( int* pbSuccess )
+{
+    GDALApplyVSGDataset* poGDS = reinterpret_cast<GDALApplyVSGDataset*>(poDS);
+    return poGDS->m_poSrcDataset->GetRasterBand(1)->GetNoDataValue(pbSuccess);
+}
+
+/************************************************************************/
+/*                              IReadBlock()                            */
+/************************************************************************/
+
+CPLErr GDALApplyVSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                           void * pData )
+{
+    GDALApplyVSGDataset* poGDS = reinterpret_cast<GDALApplyVSGDataset*>(poDS);
+
+    const int nXOff = nBlockXOff * nBlockXSize;
+    const int nReqXSize = ( nXOff > nRasterXSize - nBlockXSize ) ?
+                                    nRasterXSize - nXOff : nBlockXSize;
+    const int nYOff = nBlockYOff * nBlockYSize;
+    const int nReqYSize = ( nYOff > nRasterYSize - nBlockYSize ) ?
+                                    nRasterYSize - nYOff : nBlockYSize;
+
+    CPLErr eErr =
+        poGDS->m_poSrcDataset->GetRasterBand(1)->RasterIO(GF_Read,
+                                                    nXOff, nYOff,
+                                                    nReqXSize, nReqYSize,
+                                                    m_pafSrcData,
+                                                    nReqXSize, nReqYSize,
+                                                    GDT_Float32,
+                                                    sizeof(float),
+                                                    nBlockXSize * sizeof(float),
+                                                    NULL);
+    if( eErr == CE_None )
+        eErr =  poGDS->m_poReprojectedGrid->GetRasterBand(1)->RasterIO(GF_Read,
+                                                    nXOff, nYOff,
+                                                    nReqXSize, nReqYSize,
+                                                    m_pafGridData,
+                                                    nReqXSize, nReqYSize,
+                                                    GDT_Float32,
+                                                    sizeof(float),
+                                                    nBlockXSize * sizeof(float),
+                                                    NULL);
+    if( eErr == CE_None )
+    {
+        const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
+        int bHasNoData = FALSE;
+        float fNoDataValue = static_cast<float>(GetNoDataValue(&bHasNoData));
+        for( int iY = 0; iY < nReqYSize; iY++ )
+        {
+            for( int iX = 0; iX < nReqXSize; iX ++ )
+            {
+                const float fSrcVal = m_pafSrcData[iY * nBlockXSize + iX];
+                const float fGridVal = m_pafGridData[iY * nBlockXSize + iX];
+                if( bHasNoData && fSrcVal == fNoDataValue )
+                {
+                }
+                else if( CPLIsInf(fGridVal) )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Missing vertical grid value at source (%d,%d)",
+                             nXOff + iX, nYOff + iY);
+                    return CE_Failure;
+                }
+                else if( poGDS->m_bInverse )
+                {
+                    m_pafSrcData[iY * nBlockXSize + iX] = static_cast<float>(
+                        (fSrcVal * poGDS->m_dfSrcUnitToMeter - fGridVal) / 
+                                                poGDS->m_dfDstUnitToMeter);
+                }
+                else
+                {
+                    m_pafSrcData[iY * nBlockXSize + iX] = static_cast<float>(
+                        (fSrcVal * poGDS->m_dfSrcUnitToMeter + fGridVal) / 
+                                                poGDS->m_dfDstUnitToMeter);
+                }
+            }
+            GDALCopyWords( m_pafSrcData + iY * nBlockXSize,
+                                GDT_Float32, sizeof(float),
+                           static_cast<GByte*>(pData) + iY * nBlockXSize *
+                                nDTSize, eDataType, nDTSize,
+                           nReqXSize );
+        }
+    }
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                      GDALApplyVerticalShiftGrid()                    */
+/************************************************************************/
+
+/** Apply a vertical shift grid to a source (DEM typically) dataset.
+ * 
+ * hGridDataset will typically use WGS84 as horizontal datum (but this is
+ * not a requirement) and its values are the values to add to go from geoid
+ * elevations to WGS84 ellipsoidal heights.
+ * 
+ * hGridDataset will be on-the-fly reprojected and resampled to the projection
+ * and resolution of hSrcDataset, using bilinear resampling by default.
+ * 
+ * Both hSrcDataset and hGridDataset must be single band datasets, and have
+ * a valid geotransform and projection.
+ *
+ * On success, a reference will be taken on hSrcDataset and hGridDataset.
+ * Reference counting semantics on the source and grid datasets should be
+ * honoured. That is, don't just GDALClose() it, unless it was opened with
+ * GDALOpenShared(), but rather use GDALReleaseDataset() if wanting to
+ * immediately release the reference(s) and make the returned dataset the
+ * owner of them.
+ *
+ * Valid use cases:
+ * 
+ * \code
+ * hSrcDataset = GDALOpen(...)
+ * hGridDataset = GDALOpen(...)
+ * hDstDataset = GDALApplyVerticalShiftGrid(hSrcDataset, hGridDataset, ...)
+ * GDALReleaseDataset(hSrcDataset);
+ * GDALReleaseDataset(hGridDataset);
+ * if( hDstDataset )
+ * {
+ *     // Do things with hDstDataset 
+ *     GDALClose(hDstDataset) // will close hSrcDataset and hGridDataset
+ * }
+ * \endcode
+
+ *
+ * @param hSrcDataset source (DEM) dataset. Must not be NULL.
+ * @param hGridDataset vertical grid shift dataset. Must not be NULL.
+ * @param bInverse if set to FALSE, hGridDataset values will be added to
+ *                 hSrcDataset. If set to TRUE, they will be subtracted.
+ * @param dfSrcUnitToMeter the factor to convert values from hSrcDataset to
+ *                         meters (1.0 if source values are in meter).
+ * @param dfDstUnitToMeter the factor to convert shifted values from meter
+ *                          (1.0 if output values must be in meter).
+ * @param papszOptions list of options, or NULL. Supported options are:
+ * <ul>
+ * <li>RESAMPLING=NEAREST/BILINEAR/CUBIC. Defaults to BILINEAR.</li>
+ * <li>MAX_ERROR=val. Maximum error measured in input pixels that is allowed in
+ * approximating the transformation (0.0 for exact calculations). Defaults
+ * to 0.125</li>
+ * <li>DATATYPE=Byte/UInt16/Int16/Float32/Float64. Output data type. If not
+ * specified will be the same as the one of hSrcDataset.
+ * <li>ERROR_ON_MISSING_VERT_SHIFT=YES/NO. Whether a missing/nodata value in
+ * hGridDataset should cause I/O requests to fail. Default is NO (in which case
+ * 0 will be used)
+ * <li>SRC_SRS=srs_def. Override projection on hSrcDataset;
+ * </ul>
+ *
+ * @return a new dataset corresponding to hSrcDataset adjusted with
+ * hGridDataset, or NULL. If not NULL, it must be closed with GDALClose().
+ *
+ * @since GDAL 2.2
+ */
+GDALDatasetH GDALApplyVerticalShiftGrid( GDALDatasetH hSrcDataset,
+                                         GDALDatasetH hGridDataset,
+                                         int bInverse,
+                                         double dfSrcUnitToMeter,
+                                         double dfDstUnitToMeter,
+                                         const char* const* papszOptions )
+{
+    VALIDATE_POINTER1( hSrcDataset, "GDALApplyVerticalShiftGrid", NULL );
+    VALIDATE_POINTER1( hGridDataset, "GDALApplyVerticalShiftGrid", NULL );
+
+    double adfSrcGT[6];
+    if( GDALGetGeoTransform(hSrcDataset, adfSrcGT) != CE_None )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Source dataset has no geotransform.");
+        return NULL;
+    }
+    const char* pszSrcProjection = CSLFetchNameValueDef(papszOptions,
+                                            "SRC_SRS",
+                                            GDALGetProjectionRef(hSrcDataset));
+    if( pszSrcProjection == NULL || pszSrcProjection[0] == '\0' )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Source dataset has no projection.");
+        return NULL;
+    }
+    if(  GDALGetRasterCount(hSrcDataset) != 1 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only single band source dataset is supported.");
+        return NULL;
+    }
+
+    double adfGridGT[6];
+    if( GDALGetGeoTransform(hGridDataset, adfGridGT) != CE_None )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Grid dataset has no geotransform.");
+        return NULL;
+    }
+    const char* pszGridProjection = GDALGetProjectionRef(hGridDataset);
+    if( pszGridProjection == NULL || pszGridProjection[0] == '\0' )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Grid dataset has no projection.");
+        return NULL;
+    }
+    if(  GDALGetRasterCount(hGridDataset) != 1 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only single band grid dataset is supported.");
+        return NULL;
+    }
+
+    GDALDataType eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDataset,1));
+    const char* pszDataType = CSLFetchNameValue(papszOptions, "DATATYPE");
+    if( pszDataType )
+        eDT = GDALGetDataTypeByName(pszDataType);
+    if( eDT == GDT_Unknown )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Invalid DATATYPE=%s", pszDataType);
+        return NULL;
+    }
+
+    const int nSrcXSize = GDALGetRasterXSize(hSrcDataset);
+    const int nSrcYSize = GDALGetRasterYSize(hSrcDataset);
+
+    OGRSpatialReference oSRS;
+    CPLString osSrcProjection(pszSrcProjection);
+    oSRS.SetFromUserInput(osSrcProjection);
+    if( oSRS.IsCompound() )
+    {
+        OGR_SRSNode* poNode = oSRS.GetRoot()->GetChild(1);
+        if( poNode != NULL )
+        {
+            char* pszWKT = NULL;
+            poNode->exportToWkt(&pszWKT);
+            osSrcProjection = pszWKT;
+            CPLFree(pszWKT);
+        }
+    }
+
+    void* hTransform = GDALCreateGenImgProjTransformer3( pszGridProjection,
+                                                         adfGridGT,
+                                                         osSrcProjection,
+                                                         adfSrcGT );
+    if( hTransform == NULL )
+        return NULL;
+    GDALWarpOptions* psWO = GDALCreateWarpOptions();
+    psWO->hSrcDS = hGridDataset;
+    psWO->eResampleAlg = GRA_Bilinear;
+    const char* pszResampling = CSLFetchNameValue(papszOptions, "RESAMPLING");
+    if( pszResampling )
+    {
+        if( EQUAL(pszResampling, "NEAREST") )
+            psWO->eResampleAlg = GRA_NearestNeighbour;
+        else if( EQUAL(pszResampling, "BILINEAR") )
+            psWO->eResampleAlg = GRA_Bilinear;
+        else if( EQUAL(pszResampling, "CUBIC") )
+            psWO->eResampleAlg = GRA_Cubic;
+    }
+    psWO->eWorkingDataType = GDT_Float32;
+    int bHasNoData = FALSE;
+    const double dfSrcNoData = GDALGetRasterNoDataValue(
+        GDALGetRasterBand(hGridDataset, 1), &bHasNoData );
+    if( bHasNoData )
+    {
+        psWO->padfSrcNoDataReal =
+                static_cast<double*>(CPLMalloc(sizeof(double)));
+        psWO->padfSrcNoDataReal[0] = dfSrcNoData;
+        psWO->padfSrcNoDataImag =
+                static_cast<double*>(CPLMalloc(sizeof(double)));
+        psWO->padfSrcNoDataImag[0] = 0.0;
+    }
+
+    psWO->padfDstNoDataReal = static_cast<double*>(CPLMalloc(sizeof(double)));
+    const bool bErrorOnMissingShift = CPLFetchBool( papszOptions,
+                                              "ERROR_ON_MISSING_VERT_SHIFT",
+                                              false );
+    psWO->padfDstNoDataReal[0] = 
+        (bErrorOnMissingShift) ? -std::numeric_limits<float>::infinity() : 0.0;
+    psWO->padfDstNoDataImag = static_cast<double*>(CPLMalloc(sizeof(double)));
+    psWO->padfDstNoDataImag[0] = 0.0;
+    psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
+                                                 "INIT_DEST",
+                                                 "NO_DATA");
+
+    psWO->pfnTransformer = GDALGenImgProjTransform;
+    psWO->pTransformerArg = hTransform;
+    const double dfMaxError = CPLAtof(CSLFetchNameValueDef(papszOptions,
+                                                           "MAX_ERROR",
+                                                           "0.125"));
+    if( dfMaxError > 0.0 )
+    {
+        psWO->pTransformerArg =
+            GDALCreateApproxTransformer( psWO->pfnTransformer,
+                                         psWO->pTransformerArg,
+                                         dfMaxError );
+        psWO->pfnTransformer = GDALApproxTransform;
+        GDALApproxTransformerOwnsSubtransformer(psWO->pTransformerArg, TRUE);
+    }
+    psWO->nBandCount = 1;
+    psWO->panSrcBands = static_cast<int *>(CPLMalloc(sizeof(int)));
+    psWO->panSrcBands[0] = 1;
+    psWO->panDstBands = static_cast<int *>(CPLMalloc(sizeof(int)));
+    psWO->panDstBands[0] = 1;
+
+    VRTWarpedDataset* poReprojectedGrid =
+                new VRTWarpedDataset(nSrcXSize, nSrcYSize);
+    // This takes a reference on hGridDataset
+    CPLErr eErr = poReprojectedGrid->Initialize(psWO);
+    CPLAssert(eErr == CE_None);
+    CPL_IGNORE_RET_VAL(eErr);
+    GDALDestroyWarpOptions(psWO);
+    poReprojectedGrid->SetGeoTransform(adfSrcGT);
+    poReprojectedGrid->AddBand(GDT_Float32, NULL);
+
+    GDALApplyVSGDataset* poOutDS = new GDALApplyVSGDataset(
+        reinterpret_cast<GDALDataset*>(hSrcDataset),
+        poReprojectedGrid,
+        eDT,
+        CPL_TO_BOOL(bInverse),
+        dfSrcUnitToMeter,
+        dfDstUnitToMeter,
+        // Undocumented option. For testing only
+        atoi(CSLFetchNameValueDef(papszOptions, "BLOCKSIZE", "256")) );
+
+    poReprojectedGrid->ReleaseRef();
+
+    if( !poOutDS->IsInitOK() )
+    {
+        delete poOutDS;
+        return NULL;
+    }
+    poOutDS->SetDescription( GDALGetDescription( hSrcDataset ) );
+    return reinterpret_cast<GDALDatasetH>(poOutDS);
+}
+
+/************************************************************************/
+/*                          my_proj4_logger()                           */
+/************************************************************************/
+
+#if defined(PROJ_STATIC) && PJ_VERSION <= 493
+static void my_proj4_logger(void * user_data, int /*level*/, const char * msg)
+{
+    CPLString* posMsg = static_cast<CPLString*>(user_data);
+    *posMsg += msg;
+}
+#endif
+
+/************************************************************************/
+/*                           GetProj4Filename()                         */
+/************************************************************************/
+
+static CPLString GetProj4Filename(const char* pszFilename)
+{
+    CPLString osFilename;
+
+    /* or fixed path: /name, ./name or ../name */
+    if ( !CPLIsFilenameRelative(pszFilename) || *pszFilename == '.' )
+    {
+        return pszFilename;
+    }
+
+#if defined(PROJ_STATIC) && PJ_VERSION > 493
+    osFilename.resize(2048);
+    projCtx ctx = pj_ctx_alloc();
+    if( pj_find_file(ctx, pszFilename, &osFilename[0], osFilename.size()) )
+    {
+        osFilename.resize( strlen(osFilename) );
+    }
+    else
+    {
+        osFilename.clear();
+    }
+    pj_ctx_free(ctx);
+#else
+    // Transpose some of the proj.4 pj_open_lib() logic...
+
+    /* check if ~/name */
+    char* pszSysname;
+    if (*pszFilename == '~' &&
+        (pszFilename[1] == '/' || pszFilename[1] == '\\') )
+    {
+        if ((pszSysname = getenv("HOME")) != NULL)
+        {
+            osFilename = CPLFormFilename(pszSysname, pszFilename + 1, NULL);
+        }
+        return osFilename;
+    }
+
+    /* or is environment PROJ_LIB defined */
+    else if ((pszSysname = getenv("PROJ_LIB")) != NULL)
+    {
+        osFilename = CPLFormFilename(pszSysname, pszFilename, NULL);
+        VSIStatBufL sStat;
+        if( VSIStatL(osFilename, &sStat) == 0 )
+            return osFilename;
+        osFilename.clear();
+    }
+
+
+#if defined(PROJ_STATIC) && PJ_VERSION >= 490
+    // Super messy. proj.4 up to 4.9.3 had no public API to return the full
+    // path to a resource file, so we rely on the fact that it emits a log
+    // message with it...
+    // Basically this is needed in the case where the file is in the
+    // resource installation directory of proj.4, which we have no way to
+    // know otherwise.
+    CPLString osMsg;
+    projCtx ctx = pj_ctx_alloc();
+    pj_ctx_set_app_data(ctx, &osMsg);
+    pj_ctx_set_debug(ctx, PJ_LOG_DEBUG_MAJOR);
+    pj_ctx_set_logger(ctx, my_proj4_logger);
+    PAFile f = pj_open_lib(ctx, pszFilename, "rb");
+    if( f )
+    {
+        pj_ctx_fclose(ctx, f);
+        size_t nPos = osMsg.find("fopen(");
+        if( nPos != std::string::npos )
+        {
+            osFilename = osMsg.substr(nPos + strlen("fopen("));
+            nPos = osFilename.find(")");
+            if( nPos != std::string::npos )
+                osFilename = osFilename.substr(0, nPos);
+        }
+    }
+    pj_ctx_free(ctx);
+#endif
+#endif
+    return osFilename;
+}
+
+
+/************************************************************************/
+/*                       GDALOpenVerticalShiftGrid()                    */
+/************************************************************************/
+
+/** Load proj.4 geoidgrids as GDAL dataset
+ *
+ * @param pszProj4Geoidgrids Value of proj.4 geoidgrids parameter.
+ * @param pbError If not NULL, the pointed value will be set to TRUE if an
+ *                error occurred.
+ *
+ * @return a dataset. If not NULL, it must be closed with GDALClose().
+ *
+ * @since GDAL 2.2
+ */
+GDALDatasetH GDALOpenVerticalShiftGrid( const char* pszProj4Geoidgrids,
+                                        int* pbError )
+{
+    char** papszGrids = CSLTokenizeString2( pszProj4Geoidgrids, ",", 0);
+    const int nGridCount = CSLCount(papszGrids);
+    if( nGridCount == 1 )
+    {
+        CSLDestroy(papszGrids);
+
+        bool bMissingOk = false;
+        if( *pszProj4Geoidgrids == '@' )
+        {
+            pszProj4Geoidgrids ++;
+            bMissingOk = true;
+        }
+        const CPLString osFilename(GetProj4Filename(pszProj4Geoidgrids));
+        const char* const papszOpenOptions[] =
+            { "@SHIFT_ORIGIN_IN_MINUS_180_PLUS_180=YES", NULL };
+        GDALDatasetH hDS = GDALOpenEx(osFilename, 0, NULL, papszOpenOptions, NULL);
+        if( hDS == NULL )
+        {
+            CPLDebug("GDAL", "Cannot find file corresponding to %s",
+                     pszProj4Geoidgrids);
+        }
+        if( pbError )
+            *pbError = (!bMissingOk && hDS == NULL);
+        return hDS;
+    }
+
+    CPLStringList aosFilenames;
+    for( int i = nGridCount - 1; i >= 0; i-- )
+    {
+        const char* pszName = papszGrids[i];
+        bool bMissingOk = false;
+        if( *pszName == '@' )
+        {
+            pszName ++;
+            bMissingOk = true;
+        }
+        const CPLString osFilename(GetProj4Filename(pszName));
+        VSIStatBufL sStat;
+        if( osFilename.empty() || VSIStatL(osFilename, &sStat) != 0 )
+        {
+            CPLDebug("GDAL", "Cannot find file corresponding to %s",
+                     pszName);
+            if( !bMissingOk )
+            {
+                if( pbError )
+                    *pbError = true;
+                CSLDestroy(papszGrids);
+                return NULL;
+            }
+        }
+        else
+        {
+            aosFilenames.AddString(osFilename);
+        }
+    }
+
+    CSLDestroy(papszGrids);
+
+    if( aosFilenames.empty() )
+    {
+        if( pbError )
+            *pbError = false;
+        return NULL;
+    }
+
+    char** papszArgv = NULL;
+    papszArgv = CSLAddString(papszArgv, "-resolution");
+    papszArgv = CSLAddString(papszArgv, "highest");
+    papszArgv = CSLAddString(papszArgv, "-vrtnodata");
+    papszArgv = CSLAddString(papszArgv, "-inf");
+    papszArgv = CSLAddString(papszArgv, "-oo");
+    papszArgv = CSLAddString(papszArgv, "@SHIFT_ORIGIN_IN_MINUS_180_PLUS_180=YES");
+    GDALBuildVRTOptions* psOptions = GDALBuildVRTOptionsNew(papszArgv, NULL);
+    CSLDestroy(papszArgv);
+    GDALDatasetH hDS =
+        GDALBuildVRT( "", aosFilenames.size(), NULL, aosFilenames.List(),
+                     psOptions, NULL );
+    GDALBuildVRTOptionsFree( psOptions );
+    if( pbError )
+        *pbError = hDS != NULL;
+    return hDS;
+}
diff --git a/alg/gdalchecksum.cpp b/alg/gdalchecksum.cpp
index 979be30..ec70c7a 100644
--- a/alg/gdalchecksum.cpp
+++ b/alg/gdalchecksum.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalchecksum.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Compute simple checksum for a region of image data.
@@ -28,10 +27,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_alg.h"
+
+#include <cmath>
+#include <cstddef>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+
 
-CPL_CVSID("$Id: gdalchecksum.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: gdalchecksum.cpp 36591 2016-12-01 04:25:22Z goatbar $");
 
 /************************************************************************/
 /*                         GDALChecksumImage()                          */
@@ -64,48 +72,51 @@ GDALChecksumImage( GDALRasterBandH hBand,
     const static int anPrimes[11] =
         { 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43 };
 
-    int  iLine, i, nChecksum = 0, iPrime = 0, nCount;
-    GDALDataType eDataType = GDALGetRasterDataType( hBand );
-    int  bComplex = GDALDataTypeIsComplex( eDataType );
+    int nChecksum = 0;
+    int iPrime = 0;
+    const GDALDataType eDataType = GDALGetRasterDataType(hBand);
+    const bool bComplex = CPL_TO_BOOL(GDALDataTypeIsComplex(eDataType));
 
-    if (eDataType == GDT_Float32 || eDataType == GDT_Float64 ||
-        eDataType == GDT_CFloat32 || eDataType == GDT_CFloat64)
+    if( eDataType == GDT_Float32 || eDataType == GDT_Float64 ||
+        eDataType == GDT_CFloat32 || eDataType == GDT_CFloat64 )
     {
-        double* padfLineData;
-        GDALDataType eDstDataType = (bComplex) ? GDT_CFloat64 : GDT_Float64;
+        const GDALDataType eDstDataType = bComplex ? GDT_CFloat64 : GDT_Float64;
 
-        padfLineData = (double *) VSI_MALLOC2_VERBOSE(nXSize, sizeof(double) * 2);
-        if (padfLineData == NULL)
+        double* padfLineData = static_cast<double *>(
+            VSI_MALLOC2_VERBOSE(nXSize, sizeof(double) * 2));
+        if( padfLineData == NULL )
         {
             return 0;
         }
 
-        for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
+        for( int iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
         {
-            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,
-                              padfLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None)
+            if( GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,
+                              padfLineData, nXSize, 1,
+                              eDstDataType, 0, 0 ) != CE_None )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                        "Checksum value couldn't be computed due to I/O read error.\n");
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Checksum value couldn't be computed due to "
+                         "I/O read error.");
                 break;
             }
-            nCount = (bComplex) ? nXSize * 2 : nXSize;
+            const int nCount = bComplex ? nXSize * 2 : nXSize;
 
-            for( i = 0; i < nCount; i++ )
+            for( int i = 0; i < nCount; i++ )
             {
                 double dfVal = padfLineData[i];
                 int nVal;
-                if (CPLIsNan(dfVal) || CPLIsInf(dfVal))
+                if( CPLIsNan(dfVal) || CPLIsInf(dfVal) )
                 {
-                    /* Most compilers seem to cast NaN or Inf to 0x80000000. */
-                    /* but VC7 is an exception. So we force the result */
-                    /* of such a cast */
+                    // Most compilers seem to cast NaN or Inf to 0x80000000.
+                    // but VC7 is an exception. So we force the result
+                    // of such a cast.
                     nVal = 0x80000000;
                 }
                 else
                 {
-                    /* Standard behaviour of GDALCopyWords when converting */
-                    /* from floating point to Int32 */
+                    // Standard behaviour of GDALCopyWords when converting
+                    // from floating point to Int32.
                     dfVal += 0.5;
 
                     if( dfVal < -2147483647.0 )
@@ -113,10 +124,10 @@ GDALChecksumImage( GDALRasterBandH hBand,
                     else if( dfVal > 2147483647 )
                         nVal = 2147483647;
                     else
-                        nVal = (GInt32) floor(dfVal);
+                        nVal = static_cast<GInt32>(floor(dfVal));
                 }
 
-                nChecksum += (nVal % anPrimes[iPrime++]);
+                nChecksum += nVal % anPrimes[iPrime++];
                 if( iPrime > 10 )
                     iPrime = 0;
 
@@ -128,30 +139,31 @@ GDALChecksumImage( GDALRasterBandH hBand,
     }
     else
     {
-        int  *panLineData;
-        GDALDataType eDstDataType = (bComplex) ? GDT_CInt32 : GDT_Int32;
+        const GDALDataType eDstDataType = bComplex ? GDT_CInt32 : GDT_Int32;
 
-        panLineData = (GInt32 *) VSI_MALLOC2_VERBOSE(nXSize, sizeof(GInt32) * 2);
-        if (panLineData == NULL)
+        int *panLineData = static_cast<GInt32 *>(
+            VSI_MALLOC2_VERBOSE(nXSize, sizeof(GInt32) * 2));
+        if( panLineData == NULL )
         {
             return 0;
         }
 
-        for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
+        for( int iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
         {
-            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,
-                            panLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None)
+            if( GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,
+                              panLineData, nXSize, 1, eDstDataType,
+                              0, 0 ) != CE_None )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Checksum value could not be computed due to I/O "
-                          "read error.\n");
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Checksum value could not be computed due to I/O "
+                         "read error.");
                 break;
             }
-            nCount = (bComplex) ? nXSize * 2 : nXSize;
+            const int nCount = bComplex ? nXSize * 2 : nXSize;
 
-            for( i = 0; i < nCount; i++ )
+            for( int i = 0; i < nCount; i++ )
             {
-                nChecksum += (panLineData[i] % anPrimes[iPrime++]);
+                nChecksum += panLineData[i] % anPrimes[iPrime++];
                 if( iPrime > 10 )
                     iPrime = 0;
 
diff --git a/alg/gdalcutline.cpp b/alg/gdalcutline.cpp
index 8036290..c5834a8 100644
--- a/alg/gdalcutline.cpp
+++ b/alg/gdalcutline.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalcutline.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implement cutline/blend mask generator.
@@ -28,49 +27,58 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdalwarper.h"
+
+#include <cmath>
+#include <cstdio>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "gdal.h"
 #include "gdal_alg.h"
 #include "ogr_api.h"
-#include "ogr_geos.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
-#include "cpl_string.h"
+#include "ogr_geos.h"
 
-CPL_CVSID("$Id: gdalcutline.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: gdalcutline.cpp 36668 2016-12-04 05:29:14Z goatbar $");
 
 /************************************************************************/
 /*                         BlendMaskGenerator()                         */
 /************************************************************************/
 
-static CPLErr
-BlendMaskGenerator(
 #ifndef HAVE_GEOS
-                    CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
-                    CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
-                    CPL_UNUSED GByte *pabyPolyMask,
-                    CPL_UNUSED float *pafValidityMask,
-                    CPL_UNUSED OGRGeometryH hPolygon,
-                    CPL_UNUSED double dfBlendDist
+
+static CPLErr
+BlendMaskGenerator( int /* nXOff */, int /* nYOff */,
+                    int /* nXSize */, int /* nYSize */,
+                    GByte * /* pabyPolyMask */,
+                    float * /* pafValidityMask */,
+                    OGRGeometryH /* hPolygon */,
+                    double /* dfBlendDist */ )
+{
+    CPLError(CE_Failure, CPLE_AppDefined,
+             "Blend distance support not available without the GEOS library.");
+    return CE_Failure;
+}
 #else
-                    int nXOff, int nYOff, int nXSize, int nYSize,
+static CPLErr
+BlendMaskGenerator( int nXOff, int nYOff, int nXSize, int nYSize,
                     GByte *pabyPolyMask, float *pafValidityMask,
-                    OGRGeometryH hPolygon, double dfBlendDist
-#endif
-)
+                    OGRGeometryH hPolygon, double dfBlendDist )
 {
-#ifndef HAVE_GEOS
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "Blend distance support not available without the GEOS library.");
-    return CE_Failure;
-
-#else /* HAVE_GEOS */
 
 /* -------------------------------------------------------------------- */
 /*      Convert the polygon into a collection of lines so that we       */
 /*      measure distance from the edge even on the inside.              */
 /* -------------------------------------------------------------------- */
-    OGRGeometry *poLines
-        = OGRGeometryFactory::forceToMultiLineString(
-            ((OGRGeometry *) hPolygon)->clone() );
+    OGRGeometry *poLines =
+        OGRGeometryFactory::forceToMultiLineString(
+            reinterpret_cast<OGRGeometry *>(hPolygon)->clone() );
 
 /* -------------------------------------------------------------------- */
 /*      Prepare a clipping polygon a bit bigger than the area of        */
@@ -80,29 +88,27 @@ BlendMaskGenerator(
     CPLString osClipRectWKT;
 
     osClipRectWKT.Printf( "POLYGON((%g %g,%g %g,%g %g,%g %g,%g %g))",
-                          nXOff - (dfBlendDist+1),
-                          nYOff - (dfBlendDist+1),
-                          nXOff + nXSize + (dfBlendDist+1),
-                          nYOff - (dfBlendDist+1),
-                          nXOff + nXSize + (dfBlendDist+1),
-                          nYOff + nYSize + (dfBlendDist+1),
-                          nXOff - (dfBlendDist+1),
-                          nYOff + nYSize + (dfBlendDist+1),
-                          nXOff - (dfBlendDist+1),
-                          nYOff - (dfBlendDist+1) );
+                          nXOff - (dfBlendDist + 1),
+                          nYOff - (dfBlendDist + 1),
+                          nXOff + nXSize + (dfBlendDist + 1),
+                          nYOff - (dfBlendDist + 1),
+                          nXOff + nXSize + (dfBlendDist + 1),
+                          nYOff + nYSize + (dfBlendDist + 1),
+                          nXOff - (dfBlendDist + 1),
+                          nYOff + nYSize + (dfBlendDist + 1),
+                          nXOff - (dfBlendDist + 1),
+                          nYOff - (dfBlendDist + 1) );
 
     OGRPolygon *poClipRect = NULL;
-    char *pszWKT = (char *) osClipRectWKT.c_str();
+    char *pszWKT = const_cast<char *>(osClipRectWKT.c_str());
 
     OGRGeometryFactory::createFromWkt( &pszWKT, NULL,
                                        (OGRGeometry**) (&poClipRect) );
 
     if( poClipRect )
     {
-
-        // If it does not intersect the polym zero the mask and return.
-
-        if ( ! ((OGRGeometry *) hPolygon)->Intersects( poClipRect ) )
+        // If it does not intersect the polym, zero the mask and return.
+        if( !reinterpret_cast<OGRGeometry *>(hPolygon)->Intersects(poClipRect) )
         {
             memset( pafValidityMask, 0, sizeof(float) * nXSize * nYSize );
 
@@ -112,9 +118,8 @@ BlendMaskGenerator(
             return CE_None;
         }
 
-        // If it does not intersect the line at all just return.
-
-        else if ( ! ((OGRGeometry *) poLines)->Intersects( poClipRect ) )
+        // If it does not intersect the line at all, just return.
+        else if( !static_cast<OGRGeometry *>(poLines)->Intersects(poClipRect) )
         {
             delete poLines;
             delete poClipRect;
@@ -122,8 +127,7 @@ BlendMaskGenerator(
             return CE_None;
         }
 
-        OGRGeometry *poClippedLines =
-            poLines->Intersection( poClipRect );
+        OGRGeometry *poClippedLines = poLines->Intersection(poClipRect);
         delete poLines;
         poLines = poClippedLines;
         delete poClipRect;
@@ -134,43 +138,43 @@ BlendMaskGenerator(
 /*      envelope to accelerate later distance operations.               */
 /* -------------------------------------------------------------------- */
     OGREnvelope sEnvelope;
-    int iXMin, iYMin, iXMax, iYMax;
     GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
-    GEOSGeom poGEOSPoly;
-
-    poGEOSPoly = poLines->exportToGEOS(hGEOSCtxt);
+    GEOSGeom poGEOSPoly = poLines->exportToGEOS(hGEOSCtxt);
     OGR_G_GetEnvelope( hPolygon, &sEnvelope );
 
     delete poLines;
 
-    /***** this check was already done in the calling *****/
-    /***** function and should never be true          *****/
-
-    /*if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize
-        || sEnvelope.MaxY + dfBlendDist < nYOff
-        || sEnvelope.MinX - dfBlendDist > nXOff+nXSize
-        || sEnvelope.MaxX + dfBlendDist < nXOff )
-        return CE_None;
-    */
-
-
-    iXMin = MAX(0,(int) floor(sEnvelope.MinX - dfBlendDist - nXOff));
-    iXMax = MIN(nXSize, (int) ceil(sEnvelope.MaxX + dfBlendDist - nXOff));
-    iYMin = MAX(0,(int) floor(sEnvelope.MinY - dfBlendDist - nYOff));
-    iYMax = MIN(nYSize, (int) ceil(sEnvelope.MaxY + dfBlendDist - nYOff));
+    // This check was already done in the calling
+    // function and should never be true.
+
+    // if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize
+    //     || sEnvelope.MaxY + dfBlendDist < nYOff
+    //     || sEnvelope.MinX - dfBlendDist > nXOff+nXSize
+    //     || sEnvelope.MaxX + dfBlendDist < nXOff )
+    //     return CE_None;
+
+    const int iXMin =
+        std::max(0,
+                 static_cast<int>(floor(sEnvelope.MinX - dfBlendDist - nXOff)));
+    const int iXMax =
+        std::min(nXSize,
+                 static_cast<int>(ceil(sEnvelope.MaxX + dfBlendDist - nXOff)));
+    const int iYMin =
+        std::max(0,
+                 static_cast<int>(floor(sEnvelope.MinY - dfBlendDist - nYOff)));
+    const int iYMax =
+        std::min(nYSize,
+                 static_cast<int>(ceil(sEnvelope.MaxY + dfBlendDist - nYOff)));
 
 /* -------------------------------------------------------------------- */
 /*      Loop over potential area within blend line distance,            */
 /*      processing each pixel.                                          */
 /* -------------------------------------------------------------------- */
-    int iY, iX;
-    double dfLastDist;
-
-    for( iY = 0; iY < nYSize; iY++ )
+    for( int iY = 0; iY < nYSize; iY++ )
     {
-        dfLastDist = 0.0;
+        double dfLastDist = 0.0;
 
-        for( iX = 0; iX < nXSize; iX++ )
+        for( int iX = 0; iX < nXSize; iX++ )
         {
             if( iX < iXMin || iX >= iXMax
                 || iY < iYMin || iY > iYMax
@@ -183,13 +187,12 @@ BlendMaskGenerator(
                 continue;
             }
 
-            double dfDist, dfRatio;
             CPLString osPointWKT;
-            GEOSGeom poGEOSPoint;
-
             osPointWKT.Printf( "POINT(%d.5 %d.5)", iX + nXOff, iY + nYOff );
-            poGEOSPoint = GEOSGeomFromWKT_r( hGEOSCtxt, osPointWKT );
 
+            GEOSGeom poGEOSPoint = GEOSGeomFromWKT_r( hGEOSCtxt, osPointWKT );
+
+            double dfDist = 0.0;
             GEOSDistance_r( hGEOSCtxt, poGEOSPoly, poGEOSPoint, &dfDist );
             GEOSGeom_destroy_r( hGEOSCtxt, poGEOSPoint );
 
@@ -203,18 +206,12 @@ BlendMaskGenerator(
                 continue;
             }
 
-            if( pabyPolyMask[iX + iY * nXSize] == 0 )
-            {
-                /* outside */
-                dfRatio = 0.5 - (dfDist / dfBlendDist) * 0.5;
-            }
-            else
-            {
-                /* inside */
-                dfRatio = 0.5 + (dfDist / dfBlendDist) * 0.5;
-            }
+            const double dfRatio =
+                pabyPolyMask[iX + iY * nXSize] == 0
+                ? 0.5 - (dfDist / dfBlendDist) * 0.5   // Outside.
+                : 0.5 + (dfDist / dfBlendDist) * 0.5;  // Inside.
 
-            pafValidityMask[iX + iY * nXSize] *= (float)dfRatio;
+            pafValidityMask[iX + iY * nXSize] *= static_cast<float>(dfRatio);
         }
     }
 
@@ -226,8 +223,8 @@ BlendMaskGenerator(
 
     return CE_None;
 
-#endif /* HAVE_GEOS */
 }
+#endif  // HAVE_GEOS
 
 /************************************************************************/
 /*                         CutlineTransformer()                         */
@@ -241,12 +238,11 @@ static int CutlineTransformer( void *pTransformArg,
                                int nPointCount,
                                double *x,
                                double *y,
-                               CPL_UNUSED double *z,
-                               CPL_UNUSED int *panSuccess )
+                               double * /* z */,
+                               int * /* panSuccess */ )
 {
-    int nXOff = ((int *) pTransformArg)[0];
-    int nYOff = ((int *) pTransformArg)[1];
-    int i;
+    int nXOff = static_cast<int *>(pTransformArg)[0];
+    int nYOff = static_cast<int *>(pTransformArg)[1];
 
     if( bDstToSrc )
     {
@@ -254,7 +250,7 @@ static int CutlineTransformer( void *pTransformArg,
         nYOff *= -1;
     }
 
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
         x[i] -= nXOff;
         y[i] -= nYOff;
@@ -263,7 +259,6 @@ static int CutlineTransformer( void *pTransformArg,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                       GDALWarpCutlineMasker()                        */
 /*                                                                      */
@@ -273,18 +268,13 @@ static int CutlineTransformer( void *pTransformArg,
 
 CPLErr
 GDALWarpCutlineMasker( void *pMaskFuncArg,
-                       CPL_UNUSED int nBandCount,
-                       CPL_UNUSED GDALDataType eType,
+                       int /* nBandCount */,
+                       GDALDataType /* eType */,
                        int nXOff, int nYOff, int nXSize, int nYSize,
                        GByte ** /*ppImageData */,
                        int bMaskIsFloat, void *pValidityMask )
 
 {
-    GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
-    float *pafMask = (float *) pValidityMask;
-    CPLErr eErr;
-    GDALDriverH hMemDriver;
-
     if( nXSize < 1 || nYSize < 1 )
         return CE_None;
 
@@ -293,38 +283,43 @@ GDALWarpCutlineMasker( void *pMaskFuncArg,
 /* -------------------------------------------------------------------- */
     if( !bMaskIsFloat )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
+    GDALWarpOptions *psWO = static_cast<GDALWarpOptions *>(pMaskFuncArg);
+
     if( psWO == NULL || psWO->hCutline == NULL )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
-    hMemDriver = GDALGetDriverByName("MEM");
-    if (hMemDriver == NULL)
+    GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
+    if( hMemDriver == NULL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "GDALWarpCutlineMasker needs MEM driver");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "GDALWarpCutlineMasker needs MEM driver");
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Check the polygon.                                              */
 /* -------------------------------------------------------------------- */
-    OGRGeometryH hPolygon = (OGRGeometryH) psWO->hCutline;
-    OGREnvelope  sEnvelope;
+    OGRGeometryH hPolygon = static_cast<OGRGeometryH>(psWO->hCutline);
 
     if( wkbFlatten(OGR_G_GetGeometryType(hPolygon)) != wkbPolygon
         && wkbFlatten(OGR_G_GetGeometryType(hPolygon)) != wkbMultiPolygon )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
+    OGREnvelope sEnvelope;
     OGR_G_GetEnvelope( hPolygon, &sEnvelope );
 
+    float *pafMask = static_cast<float *>(pValidityMask);
+
     if( sEnvelope.MaxX + psWO->dfCutlineBlendDist < nXOff
         || sEnvelope.MinX - psWO->dfCutlineBlendDist > nXOff + nXSize
         || sEnvelope.MaxY + psWO->dfCutlineBlendDist < nYOff
@@ -341,22 +336,23 @@ GDALWarpCutlineMasker( void *pMaskFuncArg,
 /*      Create a byte buffer into which we can burn the                 */
 /*      mask polygon and wrap it up as a memory dataset.                */
 /* -------------------------------------------------------------------- */
-    GByte *pabyPolyMask = (GByte *) CPLCalloc( nXSize, nYSize );
-    GDALDatasetH hMemDS;
-    double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
+    GByte *pabyPolyMask = static_cast<GByte *>(CPLCalloc(nXSize, nYSize));
 
-    char szDataPointer[100];
-    char *apszOptions[] = { szDataPointer, NULL };
+    char szDataPointer[100] = {};
 
-    memset( szDataPointer, 0, sizeof(szDataPointer) );
+    // cppcheck-suppress redundantCopy
     snprintf( szDataPointer, sizeof(szDataPointer), "DATAPOINTER=" );
-    CPLPrintPointer( szDataPointer+strlen(szDataPointer),
-                     pabyPolyMask,
-                     static_cast<int>(sizeof(szDataPointer) - strlen(szDataPointer)) );
+    CPLPrintPointer(
+        szDataPointer+strlen(szDataPointer),
+        pabyPolyMask,
+        static_cast<int>(sizeof(szDataPointer) - strlen(szDataPointer)) );
 
-    hMemDS = GDALCreate( hMemDriver, "warp_temp",
-                         nXSize, nYSize, 0, GDT_Byte, NULL );
+    GDALDatasetH hMemDS = GDALCreate( hMemDriver, "warp_temp",
+                                      nXSize, nYSize, 0, GDT_Byte, NULL );
+    char *apszOptions[] = { szDataPointer, NULL };
     GDALAddBand( hMemDS, GDT_Byte, apszOptions );
+
+    double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
     GDALSetGeoTransform( hMemDS, adfGeoTransform );
 
 /* -------------------------------------------------------------------- */
@@ -364,17 +360,15 @@ GDALWarpCutlineMasker( void *pMaskFuncArg,
 /* -------------------------------------------------------------------- */
     int nTargetBand = 1;
     double dfBurnValue = 255.0;
-    int    anXYOff[2];
-    char   **papszRasterizeOptions = NULL;
+    char **papszRasterizeOptions = NULL;
 
-    if( CSLFetchBoolean( psWO->papszWarpOptions, "CUTLINE_ALL_TOUCHED", FALSE ))
+    if( CPLFetchBool( psWO->papszWarpOptions, "CUTLINE_ALL_TOUCHED", false ))
         papszRasterizeOptions =
             CSLSetNameValue( papszRasterizeOptions, "ALL_TOUCHED", "TRUE" );
 
-    anXYOff[0] = nXOff;
-    anXYOff[1] = nYOff;
+    int anXYOff[2] = { nXOff, nYOff };
 
-    eErr =
+    CPLErr eErr =
         GDALRasterizeGeometries( hMemDS, 1, &nTargetBand,
                                  1, &hPolygon,
                                  CutlineTransformer, anXYOff,
@@ -392,18 +386,17 @@ GDALWarpCutlineMasker( void *pMaskFuncArg,
 /* -------------------------------------------------------------------- */
     if( psWO->dfCutlineBlendDist == 0.0 )
     {
-        int i;
-
-        for( i = nXSize * nYSize - 1; i >= 0; i-- )
+        for( int i = nXSize * nYSize - 1; i >= 0; i-- )
         {
             if( pabyPolyMask[i] == 0 )
-                ((float *) pValidityMask)[i] = 0.0;
+                static_cast<float *>(pValidityMask)[i] = 0.0;
         }
     }
     else
     {
         eErr = BlendMaskGenerator( nXOff, nYOff, nXSize, nYSize,
-                                   pabyPolyMask, (float *) pValidityMask,
+                                   pabyPolyMask,
+                                   static_cast<float *>(pValidityMask),
                                    hPolygon, psWO->dfCutlineBlendDist );
     }
 
diff --git a/alg/gdaldither.cpp b/alg/gdaldither.cpp
index b613fd0..154cfd8 100644
--- a/alg/gdaldither.cpp
+++ b/alg/gdaldither.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaldither.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  CIETMap Phase 2
  * Purpose:  Convert RGB (24bit) to a pseudo-colored approximation using
@@ -44,14 +43,24 @@
  *  seen the 3/8-3/8-1/4 distribution described as "our" algorithm before,
  *  but I have no idea who the credit really belongs to.
  *  --
- *					    Lou Steinberg
- *
+ *                                          Lou Steinberg
  */
 
-#include "gdal_priv.h"
+#include "cpl_port.h"
 #include "gdal_alg.h"
 #include "gdal_alg_priv.h"
 
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+
 #if defined(__x86_64) || defined(_M_X64)
 #define USE_SSE2
 #endif
@@ -60,26 +69,32 @@
 
 #include <emmintrin.h>
 #define CAST_PCT(x) ((GByte*)x)
-#define ALIGN_INT_ARRAY_ON_16_BYTE(x) ( (((GPtrDiff_t)(x) % 16) != 0 ) ? (int*)((GByte*)(x) + 16 - ((GPtrDiff_t)(x) % 16)) : (x) )
-
+#define ALIGN_INT_ARRAY_ON_16_BYTE(x) \
+    ( (((GUIntptr_t)(x) % 16) != 0 ) \
+      ? (int*)((GByte*)(x) + 16 - ((GUIntptr_t)(x) % 16)) \
+      : (x) )
 #else
-
 #define CAST_PCT(x) x
-
 #endif
 
-#define MAKE_COLOR_CODE(r,g,b) ((r)|((g)<<8)|((b)<<16))
+CPL_CVSID("$Id: gdaldither.cpp 36715 2016-12-06 04:34:41Z goatbar $");
 
-CPL_CVSID("$Id: gdaldither.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+static int MAKE_COLOR_CODE( int r, int g, int b )
+{
+  return r | (g << 8) | (b << 16);
+}
 
 static void FindNearestColor( int nColors, int *panPCT, GByte *pabyColorMap,
                               int nCLevels );
 static int FindNearestColor( int nColors, int *panPCT,
                              int nRedValue, int nGreenValue, int nBlueValue );
 
-/* Structure for a hashmap from a color code to a color index of the color table */
-/* NOTE: if changing the size of this structure, edit */
-/* MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 in gdal_alg_priv.h and take into account HashHistogram in gdalmediancut.cpp */
+// Structure for a hashmap from a color code to a color index of the
+// color table.
+
+// NOTE: if changing the size of this structure, edit
+// MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 in gdal_alg_priv.h and take
+// into account HashHistogram in gdalmediancut.cpp.
 typedef struct
 {
     GUInt32 nColorCode;
@@ -133,20 +148,22 @@ GDALDitherRGB2PCT( GDALRasterBandH hRed,
 
 {
     return GDALDitherRGB2PCTInternal( hRed, hGreen, hBlue, hTarget,
-                                hColorTable, 5, NULL, TRUE,
-                                pfnProgress, pProgressArg );
+                                      hColorTable, 5, NULL, TRUE,
+                                      pfnProgress, pProgressArg );
 }
 
-int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
-                         GDALRasterBandH hGreen,
-                         GDALRasterBandH hBlue,
-                         GDALRasterBandH hTarget,
-                         GDALColorTableH hColorTable,
-                         int nBits,
-                         GInt16* pasDynamicColorMap, /* NULL or at least 256 * 256 * 256 * sizeof(GInt16) bytes */
-                         int bDither,
-                         GDALProgressFunc pfnProgress,
-                         void * pProgressArg )
+int GDALDitherRGB2PCTInternal(
+    GDALRasterBandH hRed,
+    GDALRasterBandH hGreen,
+    GDALRasterBandH hBlue,
+    GDALRasterBandH hTarget,
+    GDALColorTableH hColorTable,
+    int nBits,
+    // NULL or at least 256 * 256 * 256 * sizeof(GInt16) bytes.
+    GInt16* pasDynamicColorMap,
+    int bDither,
+    GDALProgressFunc pfnProgress,
+    void* pProgressArg )
 {
     VALIDATE_POINTER1( hRed, "GDALDitherRGB2PCT", CE_Failure );
     VALIDATE_POINTER1( hGreen, "GDALDitherRGB2PCT", CE_Failure );
@@ -154,14 +171,11 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
     VALIDATE_POINTER1( hTarget, "GDALDitherRGB2PCT", CE_Failure );
     VALIDATE_POINTER1( hColorTable, "GDALDitherRGB2PCT", CE_Failure );
 
-    int		nXSize, nYSize;
-    CPLErr err = CE_None;
-
 /* -------------------------------------------------------------------- */
 /*      Validate parameters.                                            */
 /* -------------------------------------------------------------------- */
-    nXSize = GDALGetRasterBandXSize( hRed );
-    nYSize = GDALGetRasterBandYSize( hRed );
+    const int nXSize = GDALGetRasterBandXSize( hRed );
+    const int nYSize = GDALGetRasterBandYSize( hRed );
 
     if( GDALGetRasterBandXSize( hGreen ) != nXSize
         || GDALGetRasterBandYSize( hGreen ) != nYSize
@@ -169,7 +183,7 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
         || GDALGetRasterBandYSize( hBlue ) != nYSize )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "Green or blue band doesn't match size of red band.\n" );
+                  "Green or blue band doesn't match size of red band." );
 
         return CE_Failure;
     }
@@ -179,7 +193,7 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALDitherRGB2PCT(): "
-                  "Target band doesn't match size of source bands.\n" );
+                  "Target band doesn't match size of source bands." );
 
         return CE_Failure;
     }
@@ -190,28 +204,28 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 /* -------------------------------------------------------------------- */
 /*      Setup more direct colormap.                                     */
 /* -------------------------------------------------------------------- */
-    int		nColors, iColor;
+    int iColor;
 #ifdef USE_SSE2
-    int anPCTUnaligned[256+4]; /* 4 for alignment on 16-byte boundary */
+    int anPCTUnaligned[256+4];  // 4 for alignment on 16-byte boundary.
     int* anPCT = ALIGN_INT_ARRAY_ON_16_BYTE(anPCTUnaligned);
 #else
-    int anPCT[256*4];
+    int anPCT[256*4] = {};
 #endif
-    nColors = GDALGetColorEntryCount( hColorTable );
+    const int nColors = GDALGetColorEntryCount( hColorTable );
 
-    if (nColors == 0 )
+    if( nColors == 0 )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALDitherRGB2PCT(): "
-                  "Color table must not be empty.\n" );
+                  "Color table must not be empty." );
 
         return CE_Failure;
     }
-    else if (nColors > 256)
+    else if( nColors > 256 )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
                   "GDALDitherRGB2PCT(): "
-                  "Color table cannot have more than 256 entries.\n" );
+                  "Color table cannot have more than 256 entries." );
 
         return CE_Failure;
     }
@@ -219,7 +233,7 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
     iColor = 0;
     do
     {
-        GDALColorEntry	sEntry;
+        GDALColorEntry sEntry;
 
         GDALGetColorEntryAsRGB( hColorTable, iColor, &sEntry );
         CAST_PCT(anPCT)[4*iColor+0] = static_cast<GByte>(sEntry.c1);
@@ -227,15 +241,18 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
         CAST_PCT(anPCT)[4*iColor+2] = static_cast<GByte>(sEntry.c3);
         CAST_PCT(anPCT)[4*iColor+3] = 0;
 
-        iColor ++;
+        iColor++;
     } while( iColor < nColors );
 
 #ifdef USE_SSE2
-    /* Pad to multiple of 8 colors */
-    int nColorsMod8 = nColors % 8;
+    // Pad to multiple of 8 colors.
+    const int nColorsMod8 = nColors % 8;
     if( nColorsMod8 )
     {
-        for( iColor = 0; iColor < 8 - nColorsMod8; iColor ++)
+        // Make it obvious to Coverity that we won't overflow the array
+        // with the nColors + iColor < 256 condition.
+        for( iColor = 0; iColor < 8 - nColorsMod8 &&
+                         nColors + iColor < 256; iColor ++)
         {
             anPCT[nColors+iColor] = anPCT[nColors-1];
         }
@@ -245,42 +262,52 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 /* -------------------------------------------------------------------- */
 /*      Setup various variables.                                        */
 /* -------------------------------------------------------------------- */
-    GByte   *pabyRed, *pabyGreen, *pabyBlue, *pabyIndex;
-    GByte   *pabyColorMap = NULL;
-    int     *panError;
     int nCLevels = 1 << nBits;
     ColorIndex* psColorIndexMap = NULL;
 
-    pabyRed = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
-    pabyGreen = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
-    pabyBlue = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+    GByte *pabyRed = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize));
+    GByte *pabyGreen = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize));
+    GByte *pabyBlue = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize));
 
-    pabyIndex = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+    GByte *pabyIndex = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize));
 
-    panError = (int *) VSI_CALLOC_VERBOSE(sizeof(int),(nXSize+2) * 3);
+    int *panError = static_cast<int *>(
+        VSI_CALLOC_VERBOSE(sizeof(int), (nXSize + 2) * 3));
 
-    if (pabyRed == NULL ||
+    if( pabyRed == NULL ||
         pabyGreen == NULL ||
         pabyBlue == NULL ||
         pabyIndex == NULL ||
-        panError == NULL)
+        panError == NULL )
     {
-        err = CE_Failure;
-        goto end_and_cleanup;
+        CPLFree( pabyRed );
+        CPLFree( pabyGreen );
+        CPLFree( pabyBlue );
+        CPLFree( pabyIndex );
+        CPLFree( panError );
+
+        return  CE_Failure;
     }
 
+    GByte *pabyColorMap = NULL;
     if( pasDynamicColorMap == NULL )
     {
 /* -------------------------------------------------------------------- */
 /*      Build a 24bit to 8 bit color mapping.                           */
 /* -------------------------------------------------------------------- */
 
-        pabyColorMap = (GByte *) VSI_MALLOC_VERBOSE(nCLevels * nCLevels * nCLevels
-                                        * sizeof(GByte));
+        pabyColorMap = static_cast<GByte *>(
+            VSI_MALLOC_VERBOSE(nCLevels * nCLevels * nCLevels * sizeof(GByte)));
         if( pabyColorMap == NULL )
         {
-            err = CE_Failure;
-            goto end_and_cleanup;
+            CPLFree( pabyRed );
+            CPLFree( pabyGreen );
+            CPLFree( pabyBlue );
+            CPLFree( pabyIndex );
+            CPLFree( panError );
+            CPLFree( pabyColorMap );
+
+            return CE_Failure;
         }
 
         FindNearestColor( nColors, anPCT, pabyColorMap, nCLevels);
@@ -288,11 +315,11 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
     else
     {
         pabyColorMap = NULL;
-        if( nBits == 8 && (GIntBig)nXSize * nYSize <= 65536 )
+        if( nBits == 8 && static_cast<GIntBig>(nXSize) * nYSize <= 65536 )
         {
-            /* If the image is small enough, then the number of colors */
-            /* will be limited and using a hashmap, rather than a full table */
-            /* will be more efficient */
+            // If the image is small enough, then the number of colors
+            // will be limited and using a hashmap, rather than a full table
+            // will be more efficient.
             psColorIndexMap = (ColorIndex*)pasDynamicColorMap;
             memset(psColorIndexMap, 0xFF, sizeof(ColorIndex) * PRIME_FOR_65536);
         }
@@ -305,76 +332,95 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 /* ==================================================================== */
 /*      Loop over all scanlines of data to process.                     */
 /* ==================================================================== */
-    int		iScanline;
+    CPLErr err = CE_None;
 
-    for( iScanline = 0; iScanline < nYSize; iScanline++ )
+    for( int iScanline = 0; iScanline < nYSize; iScanline++ )
     {
-        int	nLastRedError, nLastGreenError, nLastBlueError, i;
-
 /* -------------------------------------------------------------------- */
 /*      Report progress                                                 */
 /* -------------------------------------------------------------------- */
-        if( !pfnProgress( iScanline / (double) nYSize, NULL, pProgressArg ) )
+        if( !pfnProgress( iScanline / static_cast<double>(nYSize),
+                          NULL, pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" );
-            err = CE_Failure;
-            goto end_and_cleanup;
+            CPLFree( pabyRed );
+            CPLFree( pabyGreen );
+            CPLFree( pabyBlue );
+            CPLFree( pabyIndex );
+            CPLFree( panError );
+            CPLFree( pabyColorMap );
+
+            return CE_Failure;
         }
 
 /* -------------------------------------------------------------------- */
 /*      Read source data.                                               */
 /* -------------------------------------------------------------------- */
-        err = GDALRasterIO( hRed, GF_Read, 0, iScanline, nXSize, 1,
-                      pabyRed, nXSize, 1, GDT_Byte, 0, 0 );
-        if( err == CE_None )
-            err = GDALRasterIO( hGreen, GF_Read, 0, iScanline, nXSize, 1,
+        CPLErr err1 =
+            GDALRasterIO( hRed, GF_Read, 0, iScanline, nXSize, 1,
+                          pabyRed, nXSize, 1, GDT_Byte, 0, 0 );
+        if( err1 == CE_None )
+            err1 = GDALRasterIO( hGreen, GF_Read, 0, iScanline, nXSize, 1,
                       pabyGreen, nXSize, 1, GDT_Byte, 0, 0 );
-        if( err == CE_None )
-            err = GDALRasterIO( hBlue, GF_Read, 0, iScanline, nXSize, 1,
+        if( err1 == CE_None )
+            err1 = GDALRasterIO( hBlue, GF_Read, 0, iScanline, nXSize, 1,
                       pabyBlue, nXSize, 1, GDT_Byte, 0, 0 );
-        if( err != CE_None )
-            goto end_and_cleanup;
+        if( err1 != CE_None )
+        {
+            CPLFree( pabyRed );
+            CPLFree( pabyGreen );
+            CPLFree( pabyBlue );
+            CPLFree( pabyIndex );
+            CPLFree( panError );
+            CPLFree( pabyColorMap );
+
+            return err1;
+        }
 
 /* -------------------------------------------------------------------- */
-/*	Apply the error from the previous line to this one.		*/
+/*      Apply the error from the previous line to this one.             */
 /* -------------------------------------------------------------------- */
         if( bDither )
         {
-          for( i = 0; i < nXSize; i++ )
+          for( int i = 0; i < nXSize; i++ )
           {
-            pabyRed[i] = (GByte)
-                MAX(0,MIN(255,(pabyRed[i]   + panError[i*3+0+3])));
-            pabyGreen[i] = (GByte)
-                MAX(0,MIN(255,(pabyGreen[i] + panError[i*3+1+3])));
-            pabyBlue[i] =  (GByte)
-                MAX(0,MIN(255,(pabyBlue[i]  + panError[i*3+2+3])));
+              pabyRed[i] = static_cast<GByte>(
+                  std::max(0, std::min(255, (pabyRed[i] + panError[i*3+0+3]))));
+              pabyGreen[i] = static_cast<GByte>(
+                  std::max(0,
+                           std::min(255, (pabyGreen[i] + panError[i*3+1+3]))));
+              pabyBlue[i] = static_cast<GByte>(
+                  std::max(0, std::min(255,
+                                       (pabyBlue[i] + panError[i*3+2+3]))));
           }
 
           memset( panError, 0, sizeof(int) * (nXSize+2) * 3 );
         }
 
 /* -------------------------------------------------------------------- */
-/*	Figure out the nearest color to the RGB value.			*/
+/*      Figure out the nearest color to the RGB value.                  */
 /* -------------------------------------------------------------------- */
-        nLastRedError = 0;
-        nLastGreenError = 0;
-        nLastBlueError = 0;
+        int nLastRedError = 0;
+        int nLastGreenError = 0;
+        int nLastBlueError = 0;
 
-        for( i = 0; i < nXSize; i++ )
+        for( int i = 0; i < nXSize; i++ )
         {
-            int		iIndex, nError, nSixth;
-            int		nRedValue, nGreenValue, nBlueValue;
-
-            nRedValue =   MAX(0,MIN(255, pabyRed[i]   + nLastRedError));
-            nGreenValue = MAX(0,MIN(255, pabyGreen[i] + nLastGreenError));
-            nBlueValue =  MAX(0,MIN(255, pabyBlue[i]  + nLastBlueError));
-
+            const int nRedValue =
+                std::max(0, std::min(255, pabyRed[i] + nLastRedError));
+            const int nGreenValue =
+                std::max(0, std::min(255, pabyGreen[i] + nLastGreenError));
+            const int nBlueValue =
+                std::max(0, std::min(255, pabyBlue[i] + nLastBlueError));
+
+            int iIndex = 0;
+            int nError = 0;
+            int nSixth = 0;
             if( psColorIndexMap )
             {
-                GUInt32 nColorCode = MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
+                const GUInt32 nColorCode =
+                    MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
                 GUInt32 nIdx = nColorCode % PRIME_FOR_65536;
-                //int nCollisions = 0;
-                //static int nMaxCollisions = 0;
                 while( true )
                 {
                     if( psColorIndexMap[nIdx].nColorCode == nColorCode )
@@ -382,12 +428,13 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
                         iIndex = psColorIndexMap[nIdx].nIndex;
                         break;
                     }
-                    if( (int)psColorIndexMap[nIdx].nColorCode < 0 )
+                    if( static_cast<int>(psColorIndexMap[nIdx].nColorCode) < 0 )
                     {
                         psColorIndexMap[nIdx].nColorCode = nColorCode;
-                        iIndex = FindNearestColor( nColors, anPCT,
-                                                   nRedValue, nGreenValue, nBlueValue );
-                        psColorIndexMap[nIdx].nIndex = (GByte) iIndex;
+                        iIndex = FindNearestColor(
+                            nColors, anPCT, nRedValue, nGreenValue, nBlueValue);
+                        psColorIndexMap[nIdx].nIndex =
+                            static_cast<GByte>(iIndex);
                         break;
                     }
                     if( psColorIndexMap[nIdx].nColorCode2 == nColorCode )
@@ -395,12 +442,14 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
                         iIndex = psColorIndexMap[nIdx].nIndex2;
                         break;
                     }
-                    if( (int)psColorIndexMap[nIdx].nColorCode2 < 0 )
+                    if( static_cast<int>(psColorIndexMap[nIdx].nColorCode2) <
+                        0 )
                     {
                         psColorIndexMap[nIdx].nColorCode2 = nColorCode;
-                        iIndex = FindNearestColor( nColors, anPCT,
-                                                   nRedValue, nGreenValue, nBlueValue );
-                        psColorIndexMap[nIdx].nIndex2 = (GByte) iIndex;
+                        iIndex = FindNearestColor(
+                            nColors, anPCT, nRedValue, nGreenValue, nBlueValue);
+                        psColorIndexMap[nIdx].nIndex2 =
+                            static_cast<GByte>(iIndex);
                         break;
                     }
                     if( psColorIndexMap[nIdx].nColorCode3 == nColorCode )
@@ -408,71 +457,77 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
                         iIndex = psColorIndexMap[nIdx].nIndex3;
                         break;
                     }
-                    if( (int)psColorIndexMap[nIdx].nColorCode3 < 0 )
+                    if( static_cast<int>(psColorIndexMap[nIdx].nColorCode3) <
+                        0 )
                     {
                         psColorIndexMap[nIdx].nColorCode3 = nColorCode;
                         iIndex = FindNearestColor( nColors, anPCT,
-                                                   nRedValue, nGreenValue, nBlueValue );
-                        psColorIndexMap[nIdx].nIndex3 = (GByte) iIndex;
+                                                   nRedValue, nGreenValue,
+                                                   nBlueValue );
+                        psColorIndexMap[nIdx].nIndex3 =
+                            static_cast<GByte>(iIndex);
                         break;
                     }
 
                     do
                     {
-                        //nCollisions ++;
                         nIdx+=257;
                         if( nIdx >= PRIME_FOR_65536 )
                             nIdx -= PRIME_FOR_65536;
                     }
-                    while( (int)psColorIndexMap[nIdx].nColorCode >= 0 &&
-                            psColorIndexMap[nIdx].nColorCode != nColorCode &&
-                            (int)psColorIndexMap[nIdx].nColorCode2 >= 0 &&
-                            psColorIndexMap[nIdx].nColorCode2 != nColorCode&&
-                            (int)psColorIndexMap[nIdx].nColorCode3 >= 0 &&
-                            psColorIndexMap[nIdx].nColorCode3 != nColorCode );
-                    /*if( nCollisions > nMaxCollisions )
-                    {
-                        nMaxCollisions = nCollisions;
-                        printf("nCollisions = %d for R=%d,G=%d,B=%d\n",
-                                nCollisions, nRedValue, nGreenValue, nBlueValue);
-                    }*/
+                    while( static_cast<int>(psColorIndexMap[nIdx].nColorCode)
+                           >= 0 &&
+                           psColorIndexMap[nIdx].nColorCode != nColorCode &&
+                           static_cast<int>(psColorIndexMap[nIdx].nColorCode2)
+                           >= 0 &&
+                           psColorIndexMap[nIdx].nColorCode2 != nColorCode&&
+                           static_cast<int>(psColorIndexMap[nIdx].nColorCode3)
+                           >= 0 &&
+                           psColorIndexMap[nIdx].nColorCode3 != nColorCode );
                 }
             }
             else if( pasDynamicColorMap == NULL )
             {
-                int iRed   = nRedValue *   nCLevels   / 256;
-                int iGreen = nGreenValue * nCLevels / 256;
-                int iBlue  = nBlueValue *  nCLevels  / 256;
+                const int iRed   = nRedValue *   nCLevels / 256;
+                const int iGreen = nGreenValue * nCLevels / 256;
+                const int iBlue  = nBlueValue *  nCLevels / 256;
 
                 iIndex = pabyColorMap[iRed + iGreen * nCLevels
-                                    + iBlue * nCLevels * nCLevels];
+                                      + iBlue * nCLevels * nCLevels];
             }
             else
             {
-                GUInt32 nColorCode = MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
+                const GUInt32 nColorCode =
+                    MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
                 GInt16* psIndex = &pasDynamicColorMap[nColorCode];
                 if( *psIndex < 0 )
-                    iIndex = *psIndex = static_cast<GInt16>(FindNearestColor( nColors, anPCT,
-                                                          nRedValue,
-                                                          nGreenValue,
-                                                          nBlueValue ));
+                {
+                    *psIndex = static_cast<GInt16>(
+                        FindNearestColor( nColors, anPCT,
+                                          nRedValue,
+                                          nGreenValue,
+                                          nBlueValue ));
+                    iIndex = *psIndex;
+                }
                 else
+                {
                     iIndex = *psIndex;
+                }
             }
 
-            pabyIndex[i] = (GByte) iIndex;
+            pabyIndex[i] = static_cast<GByte>(iIndex);
             if( !bDither )
                 continue;
 
 /* -------------------------------------------------------------------- */
 /*      Compute Red error, and carry it on to the next error line.      */
 /* -------------------------------------------------------------------- */
-            nError = nRedValue - CAST_PCT(anPCT)[4*iIndex+0];
+            nError = nRedValue - CAST_PCT(anPCT)[4 * iIndex + 0];
             nSixth = nError / 6;
 
-            panError[i*3    ] += nSixth;
-            panError[i*3+6  ] = nSixth;
-            panError[i*3+3  ] += nError - 5 * nSixth;
+            panError[i * 3    ] += nSixth;
+            panError[i * 3 + 6] = nSixth;
+            panError[i * 3 + 3] += nError - 5 * nSixth;
 
             nLastRedError = 2 * nSixth;
 
@@ -482,9 +537,9 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
             nError = nGreenValue - CAST_PCT(anPCT)[4*iIndex+1];
             nSixth = nError / 6;
 
-            panError[i*3  +1] += nSixth;
-            panError[i*3+6+1] = nSixth;
-            panError[i*3+3+1] += nError - 5 * nSixth;
+            panError[i * 3 + 1] += nSixth;
+            panError[i * 3 + 6 + 1] = nSixth;
+            panError[i * 3 + 3 + 1] += nError - 5 * nSixth;
 
             nLastGreenError = 2 * nSixth;
 
@@ -494,9 +549,9 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
             nError = nBlueValue - CAST_PCT(anPCT)[4*iIndex+2];
             nSixth = nError / 6;
 
-            panError[i*3  +2] += nSixth;
-            panError[i*3+6+2] = nSixth;
-            panError[i*3+3+2] += nError - 5 * nSixth;
+            panError[i * 3 + 2] += nSixth;
+            panError[i * 3 + 6 + 2] = nSixth;
+            panError[i * 3 + 3 + 2] += nError - 5 * nSixth;
 
             nLastBlueError = 2 * nSixth;
         }
@@ -515,7 +570,6 @@ int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed,
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-end_and_cleanup:
     CPLFree( pabyRed );
     CPLFree( pabyGreen );
     CPLFree( pabyBlue );
@@ -531,35 +585,39 @@ static int FindNearestColor( int nColors, int *panPCT,
 
 {
 #ifdef USE_SSE2
-    int     iColor;
+    int nBestDist = 768;
+    int nBestIndex = 0;
 
-    int nBestDist = 768, nBestIndex = 0;
-
-    int     anDistanceUnaligned[16+4]; /* 4 for alignment on 16-byte boundary */
+    int anDistanceUnaligned[16+4] = {};  // 4 for alignment on 16-byte boundary.
     int* anDistance = ALIGN_INT_ARRAY_ON_16_BYTE(anDistanceUnaligned);
 
     const __m128i ff = _mm_set1_epi32(0xFFFFFFFF);
     const __m128i mask_low = _mm_srli_epi64(ff, 32);
     const __m128i mask_high = _mm_slli_epi64(ff, 32);
 
-    unsigned int nColorVal = MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
+    const unsigned int nColorVal =
+        MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
     const __m128i thisColor = _mm_set1_epi32(nColorVal);
     const __m128i thisColor_low = _mm_srli_epi64(thisColor, 32);
     const __m128i thisColor_high = _mm_slli_epi64(thisColor, 32);
 
-    for( iColor = 0; iColor < nColors; iColor+=8 )
+    for( int iColor = 0; iColor < nColors; iColor+=8 )
     {
-        __m128i pctColor = _mm_load_si128((__m128i*)&panPCT[iColor]);
-        __m128i pctColor2 = _mm_load_si128((__m128i*)&panPCT[iColor+4]);
-
-        _mm_store_si128((__m128i*)anDistance,
-                        _mm_sad_epu8(_mm_and_si128(pctColor,mask_low),thisColor_low));
-        _mm_store_si128((__m128i*)(anDistance+4),
-                        _mm_sad_epu8(_mm_and_si128(pctColor,mask_high),thisColor_high));
-        _mm_store_si128((__m128i*)(anDistance+8),
-                        _mm_sad_epu8(_mm_and_si128(pctColor2,mask_low),thisColor_low));
-        _mm_store_si128((__m128i*)(anDistance+12),
-                        _mm_sad_epu8(_mm_and_si128(pctColor2,mask_high),thisColor_high));
+        const __m128i pctColor = _mm_load_si128((__m128i*)&panPCT[iColor]);
+        const __m128i pctColor2 = _mm_load_si128((__m128i*)&panPCT[iColor+4]);
+
+        _mm_store_si128(
+            (__m128i*)anDistance,
+            _mm_sad_epu8(_mm_and_si128(pctColor, mask_low), thisColor_low));
+        _mm_store_si128(
+            (__m128i*)(anDistance+4),
+            _mm_sad_epu8(_mm_and_si128(pctColor, mask_high), thisColor_high));
+        _mm_store_si128(
+            (__m128i*)(anDistance+8),
+            _mm_sad_epu8(_mm_and_si128(pctColor2, mask_low), thisColor_low));
+        _mm_store_si128(
+            (__m128i*)(anDistance+12),
+            _mm_sad_epu8(_mm_and_si128(pctColor2, mask_high), thisColor_high));
 
         if( anDistance[0] < nBestDist )
         {
@@ -568,53 +626,51 @@ static int FindNearestColor( int nColors, int *panPCT,
         }
         if( anDistance[4] < nBestDist )
         {
-            nBestIndex = iColor+1;
+            nBestIndex = iColor + 1;
             nBestDist = anDistance[4];
         }
         if( anDistance[2] < nBestDist )
         {
-            nBestIndex = iColor+2;
+            nBestIndex = iColor + 2;
             nBestDist = anDistance[2];
         }
         if( anDistance[6] < nBestDist )
         {
-            nBestIndex = iColor+3;
+            nBestIndex = iColor + 3;
             nBestDist = anDistance[6];
         }
-        if( anDistance[8+0] < nBestDist )
+        if( anDistance[8 + 0] < nBestDist )
         {
-            nBestIndex = iColor+4;
-            nBestDist = anDistance[8+0];
+            nBestIndex = iColor + 4;
+            nBestDist = anDistance[8 + 0];
         }
-        if( anDistance[8+4] < nBestDist )
+        if( anDistance[8 + 4] < nBestDist )
         {
-            nBestIndex = iColor+4+1;
-            nBestDist = anDistance[8+4];
+            nBestIndex = iColor + 4 + 1;
+            nBestDist = anDistance[8 + 4];
         }
-        if( anDistance[8+2] < nBestDist )
+        if( anDistance[8 + 2] < nBestDist )
         {
-            nBestIndex = iColor+4+2;
-            nBestDist = anDistance[8+2];
+            nBestIndex = iColor + 4 + 2;
+            nBestDist = anDistance[8 + 2];
         }
-        if( anDistance[8+6] < nBestDist )
+        if( anDistance[8 + 6] < nBestDist )
         {
-            nBestIndex = iColor+4+3;
-            nBestDist = anDistance[8+6];
+            nBestIndex = iColor + 4 + 3;
+            nBestDist = anDistance[8  +  6];
         }
     }
     return nBestIndex;
 #else
-    int     iColor;
-
-    int nBestDist = 768, nBestIndex = 0;
+    int nBestDist = 768;
+    int nBestIndex = 0;
 
-    for( iColor = 0; iColor < nColors; iColor++ )
+    for( int iColor = 0; iColor < nColors; iColor++ )
     {
-        int     nThisDist;
-
-        nThisDist = ABS(nRedValue   - panPCT[4*iColor+0])
-                  + ABS(nGreenValue - panPCT[4*iColor+1])
-                  + ABS(nBlueValue  - panPCT[4*iColor+2]);
+        const int nThisDist =
+            std::abs(nRedValue - panPCT[4*iColor + 0]) +
+            std::abs(nGreenValue - panPCT[4*iColor + 1]) +
+            std::abs(nBlueValue - panPCT[4*iColor + 2]);
 
         if( nThisDist < nBestDist )
         {
@@ -626,7 +682,6 @@ static int FindNearestColor( int nColors, int *panPCT,
 #endif
 }
 
-
 /************************************************************************/
 /*                          FindNearestColor()                          */
 /*                                                                      */
@@ -637,27 +692,25 @@ static void FindNearestColor( int nColors, int *panPCT, GByte *pabyColorMap,
                               int nCLevels )
 
 {
-    int     iBlue, iGreen, iRed;
-
 /* -------------------------------------------------------------------- */
-/*  Loop over all the cells in the high density cube.       */
+/*  Loop over all the cells in the high density cube.                   */
 /* -------------------------------------------------------------------- */
-    for( iBlue = 0; iBlue < nCLevels; iBlue++ )
+    for( int iBlue = 0; iBlue < nCLevels; iBlue++ )
     {
-        for( iGreen = 0; iGreen < nCLevels; iGreen++ )
+        for( int iGreen = 0; iGreen < nCLevels; iGreen++ )
         {
-            for( iRed = 0; iRed < nCLevels; iRed++ )
+            for( int iRed = 0; iRed < nCLevels; iRed++ )
             {
-                int     nRedValue, nGreenValue, nBlueValue;
-
-                nRedValue   = (iRed * 255) / (nCLevels-1);
-                nGreenValue = (iGreen * 255) / (nCLevels-1);
-                nBlueValue  = (iBlue * 255) / (nCLevels-1);
+                const int nRedValue   = (iRed * 255) / (nCLevels - 1);
+                const int nGreenValue = (iGreen * 255) / (nCLevels - 1);
+                const int nBlueValue  = (iBlue * 255) / (nCLevels - 1);
 
-                int nBestIndex = FindNearestColor( nColors, panPCT,
-                                        nRedValue, nGreenValue, nBlueValue );
+                const int nBestIndex =
+                    FindNearestColor( nColors, panPCT,
+                                      nRedValue, nGreenValue, nBlueValue );
                 pabyColorMap[iRed + iGreen*nCLevels
-                                    + iBlue*nCLevels*nCLevels] = (GByte)nBestIndex;
+                             + iBlue*nCLevels*nCLevels] =
+                    static_cast<GByte>(nBestIndex);
             }
         }
     }
diff --git a/alg/gdalgeoloc.cpp b/alg/gdalgeoloc.cpp
index 2945e93..4660277 100644
--- a/alg/gdalgeoloc.cpp
+++ b/alg/gdalgeoloc.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalgeoloc.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements Geolocation array based transformer.
@@ -28,17 +27,25 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
+#include "cpl_port.h"
 #include "gdal_alg.h"
 
-#ifdef SHAPE_DEBUG
-#include "/u/pkg/shapelib/shapefil.h"
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
 
-SHPHandle hSHP = NULL;
-DBFHandle hDBF = NULL;
-#endif
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalgeoloc.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: gdalgeoloc.cpp 36716 2016-12-06 04:45:35Z goatbar $");
 
 CPL_C_START
 CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg );
@@ -47,27 +54,24 @@ CPL_C_END
 
 /************************************************************************/
 /* ==================================================================== */
-/*			   GDALGeoLocTransformer                        */
+/*                         GDALGeoLocTransformer                        */
 /* ==================================================================== */
 /************************************************************************/
 
 typedef struct {
-
     GDALTransformerInfo sTI;
 
-    int         bReversed;
+    bool        bReversed;
 
     // Map from target georef coordinates back to geolocation array
     // pixel line coordinates.  Built only if needed.
-
     int         nBackMapWidth;
     int         nBackMapHeight;
-    double      adfBackMapGeoTransform[6]; // maps georef to pixel/line.
+    double      adfBackMapGeoTransform[6];  // Maps georef to pixel/line.
     float       *pafBackMapX;
     float       *pafBackMapY;
 
-    // geolocation bands.
-
+    // Geolocation bands.
     GDALDatasetH     hDS_X;
     GDALRasterBandH  hBand_X;
     GDALDatasetH     hDS_Y;
@@ -82,7 +86,7 @@ typedef struct {
     int              bHasNoData;
     double           dfNoDataX;
 
-    // geolocation <-> base image mapping.
+    // Geolocation <-> base image mapping.
     double           dfPIXEL_OFFSET;
     double           dfPIXEL_STEP;
     double           dfLINE_OFFSET;
@@ -96,80 +100,80 @@ typedef struct {
 /*                         GeoLocLoadFullData()                         */
 /************************************************************************/
 
-static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
+static bool GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
 
 {
-    int nXSize, nYSize;
-
-    int nXSize_XBand = GDALGetRasterXSize( psTransform->hDS_X );
-    int nYSize_XBand = GDALGetRasterYSize( psTransform->hDS_X );
-    int nXSize_YBand = GDALGetRasterXSize( psTransform->hDS_Y );
-    int nYSize_YBand = GDALGetRasterYSize( psTransform->hDS_Y );
-    if (nYSize_XBand == 1 && nYSize_YBand == 1)
+    const int nXSize_XBand = GDALGetRasterXSize( psTransform->hDS_X );
+    const int nYSize_XBand = GDALGetRasterYSize( psTransform->hDS_X );
+    const int nXSize_YBand = GDALGetRasterXSize( psTransform->hDS_Y );
+    const int nYSize_YBand = GDALGetRasterYSize( psTransform->hDS_Y );
+
+    const int nXSize = nXSize_XBand;
+    // TODO(schwehr): This could use an explanation.
+    int nYSize = 0;
+    if( nYSize_XBand == 1 && nYSize_YBand == 1 )
     {
-        nXSize = nXSize_XBand;
         nYSize = nXSize_YBand;
     }
     else
     {
-        nXSize = nXSize_XBand;
         nYSize = nYSize_XBand;
     }
 
     psTransform->nGeoLocXSize = nXSize;
     psTransform->nGeoLocYSize = nYSize;
 
-    psTransform->padfGeoLocY = (double *)
-        VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize);
-    psTransform->padfGeoLocX = (double *)
-        VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize);
+    psTransform->padfGeoLocY = static_cast<double *>(
+        VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize));
+    psTransform->padfGeoLocX = static_cast<double *>(
+        VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize));
 
     if( psTransform->padfGeoLocX == NULL ||
         psTransform->padfGeoLocY == NULL )
     {
-        return FALSE;
+        return false;
     }
 
-    if (nYSize_XBand == 1 && nYSize_YBand == 1)
+    if( nYSize_XBand == 1 && nYSize_YBand == 1 )
     {
-        /* Case of regular grid */
-        /* The XBAND contains the x coordinates for all lines */
-        /* The YBAND contains the y coordinates for all columns */
-
-        double* padfTempX = (double*)VSI_MALLOC2_VERBOSE(nXSize, sizeof(double));
-        double* padfTempY = (double*)VSI_MALLOC2_VERBOSE(nYSize, sizeof(double));
-        if (padfTempX == NULL || padfTempY == NULL)
+        // Case of regular grid.
+        // The XBAND contains the x coordinates for all lines.
+        // The YBAND contains the y coordinates for all columns.
+
+        double* padfTempX = static_cast<double *>(
+            VSI_MALLOC2_VERBOSE(nXSize, sizeof(double)));
+        double* padfTempY = static_cast<double *>(
+            VSI_MALLOC2_VERBOSE(nYSize, sizeof(double)));
+        if( padfTempX == NULL || padfTempY == NULL )
         {
             CPLFree(padfTempX);
             CPLFree(padfTempY);
-            return FALSE;
+            return false;
         }
 
-        CPLErr eErr = CE_None;
+        CPLErr eErr =
+            GDALRasterIO( psTransform->hBand_X, GF_Read,
+                          0, 0, nXSize, 1,
+                          padfTempX, nXSize, 1,
+                          GDT_Float64, 0, 0 );
 
-        eErr = GDALRasterIO( psTransform->hBand_X, GF_Read,
-                             0, 0, nXSize, 1,
-                             padfTempX, nXSize, 1,
-                             GDT_Float64, 0, 0 );
-
-        int i,j;
-        for(j=0;j<nYSize;j++)
+        for( int j = 0; j < nYSize; j++ )
         {
             memcpy( psTransform->padfGeoLocX + j * nXSize,
                     padfTempX,
                     nXSize * sizeof(double) );
         }
 
-        if (eErr == CE_None)
+        if( eErr == CE_None )
         {
             eErr = GDALRasterIO( psTransform->hBand_Y, GF_Read,
-                                0, 0, nYSize, 1,
-                                padfTempY, nYSize, 1,
-                                GDT_Float64, 0, 0 );
+                                 0, 0, nYSize, 1,
+                                 padfTempY, nYSize, 1,
+                                 GDT_Float64, 0, 0 );
 
-            for(j=0;j<nYSize;j++)
+            for( int j = 0; j < nYSize; j++ )
             {
-                for(i=0;i<nXSize;i++)
+                for( int i = 0; i < nXSize; i++ )
                 {
                     psTransform->padfGeoLocY[j * nXSize + i] = padfTempY[j];
                 }
@@ -179,62 +183,68 @@ static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )
         CPLFree(padfTempX);
         CPLFree(padfTempY);
 
-        if (eErr != CE_None)
-            return FALSE;
+        if( eErr != CE_None )
+            return false;
     }
     else
     {
         if( GDALRasterIO( psTransform->hBand_X, GF_Read,
-                        0, 0, nXSize, nYSize,
-                        psTransform->padfGeoLocX, nXSize, nYSize,
-                        GDT_Float64, 0, 0 ) != CE_None
+                          0, 0, nXSize, nYSize,
+                          psTransform->padfGeoLocX, nXSize, nYSize,
+                          GDT_Float64, 0, 0 ) != CE_None
             || GDALRasterIO( psTransform->hBand_Y, GF_Read,
-                            0, 0, nXSize, nYSize,
-                            psTransform->padfGeoLocY, nXSize, nYSize,
-                            GDT_Float64, 0, 0 ) != CE_None )
-            return FALSE;
+                             0, 0, nXSize, nYSize,
+                             psTransform->padfGeoLocY, nXSize, nYSize,
+                             GDT_Float64, 0, 0 ) != CE_None )
+            return false;
     }
 
-    psTransform->dfNoDataX = GDALGetRasterNoDataValue( psTransform->hBand_X,
-                                                       &(psTransform->bHasNoData) );
+    psTransform->dfNoDataX =
+        GDALGetRasterNoDataValue( psTransform->hBand_X,
+                                  &(psTransform->bHasNoData) );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                       GeoLocGenerateBackMap()                        */
 /************************************************************************/
 
-static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
+static bool GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 
 {
-    int nXSize = psTransform->nGeoLocXSize;
-    int nYSize = psTransform->nGeoLocYSize;
-    int nMaxIter = 3;
+    const int nXSize = psTransform->nGeoLocXSize;
+    const int nYSize = psTransform->nGeoLocYSize;
+    const int nMaxIter = 3;
 
 /* -------------------------------------------------------------------- */
 /*      Scan forward map for lat/long extents.                          */
 /* -------------------------------------------------------------------- */
-    double dfMinX=0, dfMaxX=0, dfMinY=0, dfMaxY=0;
-    int i, bInit = FALSE;
+    double dfMinX = 0.0;
+    double dfMaxX = 0.0;
+    double dfMinY = 0.0;
+    double dfMaxY = 0.0;
+    bool bInit = false;
 
-    for( i = nXSize * nYSize - 1; i >= 0; i-- )
+    for( int i = nXSize * nYSize - 1; i >= 0; i-- )
     {
         if( !psTransform->bHasNoData ||
             psTransform->padfGeoLocX[i] != psTransform->dfNoDataX )
         {
             if( bInit )
             {
-                dfMinX = MIN(dfMinX,psTransform->padfGeoLocX[i]);
-                dfMaxX = MAX(dfMaxX,psTransform->padfGeoLocX[i]);
-                dfMinY = MIN(dfMinY,psTransform->padfGeoLocY[i]);
-                dfMaxY = MAX(dfMaxY,psTransform->padfGeoLocY[i]);
+                dfMinX = std::min(dfMinX, psTransform->padfGeoLocX[i]);
+                dfMaxX = std::max(dfMaxX, psTransform->padfGeoLocX[i]);
+                dfMinY = std::min(dfMinY, psTransform->padfGeoLocY[i]);
+                dfMaxY = std::max(dfMaxY, psTransform->padfGeoLocY[i]);
             }
             else
             {
-                bInit = TRUE;
-                dfMinX = dfMaxX = psTransform->padfGeoLocX[i];
-                dfMinY = dfMaxY = psTransform->padfGeoLocY[i];
+                bInit = true;
+                dfMinX = psTransform->padfGeoLocX[i];
+                dfMaxX = psTransform->padfGeoLocX[i];
+                dfMinY = psTransform->padfGeoLocY[i];
+                dfMaxY = psTransform->padfGeoLocY[i];
             }
         }
     }
@@ -245,25 +255,24 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 /*      establish how much dead space there is in the backmap, so it    */
 /*      is approximate.                                                 */
 /* -------------------------------------------------------------------- */
-    double dfTargetPixels = (nXSize * nYSize * 1.3);
-    double dfPixelSize = sqrt((dfMaxX - dfMinX) * (dfMaxY - dfMinY)
+    const double dfTargetPixels = (nXSize * nYSize * 1.3);
+    const double dfPixelSize = sqrt((dfMaxX - dfMinX) * (dfMaxY - dfMinY)
                               / dfTargetPixels);
-    int nBMXSize, nBMYSize;
 
-    nBMYSize = psTransform->nBackMapHeight =
-        (int) ((dfMaxY - dfMinY) / dfPixelSize + 1);
-    nBMXSize= psTransform->nBackMapWidth =
-        (int) ((dfMaxX - dfMinX) / dfPixelSize + 1);
+    const int nBMYSize = psTransform->nBackMapHeight =
+        static_cast<int>((dfMaxY - dfMinY) / dfPixelSize + 1);
+    const int nBMXSize = psTransform->nBackMapWidth =
+        static_cast<int>((dfMaxX - dfMinX) / dfPixelSize + 1);
 
-    if (nBMXSize > INT_MAX / nBMYSize)
+    if( nBMXSize > INT_MAX / nBMYSize )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Int overflow : %d x %d",
                  nBMXSize, nBMYSize);
-        return FALSE;
+        return false;
     }
 
-    dfMinX -= dfPixelSize/2.0;
-    dfMaxY += dfPixelSize/2.0;
+    dfMinX -= dfPixelSize / 2.0;
+    dfMaxY += dfPixelSize / 2.0;
 
     psTransform->adfBackMapGeoTransform[0] = dfMinX;
     psTransform->adfBackMapGeoTransform[1] = dfPixelSize;
@@ -275,25 +284,23 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 /* -------------------------------------------------------------------- */
 /*      Allocate backmap, and initialize to nodata value (-1.0).        */
 /* -------------------------------------------------------------------- */
-    GByte  *pabyValidFlag;
+    GByte *pabyValidFlag = static_cast<GByte *>(
+        VSI_CALLOC_VERBOSE(nBMXSize, nBMYSize));
 
-    pabyValidFlag = (GByte *)
-        VSI_CALLOC_VERBOSE(nBMXSize, nBMYSize);
-
-    psTransform->pafBackMapX = (float *)
-        VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float));
-    psTransform->pafBackMapY = (float *)
-        VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float));
+    psTransform->pafBackMapX = static_cast<float *>(
+        VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float)));
+    psTransform->pafBackMapY = static_cast<float *>(
+        VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float)));
 
     if( pabyValidFlag == NULL ||
         psTransform->pafBackMapX == NULL ||
         psTransform->pafBackMapY == NULL )
     {
         CPLFree( pabyValidFlag );
-        return FALSE;
+        return false;
     }
 
-    for( i = nBMXSize * nBMYSize - 1; i >= 0; i-- )
+    for( int i = nBMXSize * nBMYSize - 1; i >= 0; i-- )
     {
         psTransform->pafBackMapX[i] = -1.0;
         psTransform->pafBackMapY[i] = -1.0;
@@ -305,33 +312,37 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 /*      Initialize to the nMaxIter+1 value so we can spot genuinely     */
 /*      valid pixels in the hole-filling loop.                          */
 /* -------------------------------------------------------------------- */
-    int iBMX, iBMY;
-    int iX, iY;
 
-    for( iY = 0; iY < nYSize; iY++ )
+    for( int iY = 0; iY < nYSize; iY++ )
     {
-        for( iX = 0; iX < nXSize; iX++ )
+        for( int iX = 0; iX < nXSize; iX++ )
         {
             if( psTransform->bHasNoData &&
                 psTransform->padfGeoLocX[iX + iY * nXSize]
                 == psTransform->dfNoDataX )
                 continue;
 
-            i = iX + iY * nXSize;
+            const int i = iX + iY * nXSize;
 
-            iBMX = (int) ((psTransform->padfGeoLocX[i] - dfMinX) / dfPixelSize);
-            iBMY = (int) ((dfMaxY - psTransform->padfGeoLocY[i]) / dfPixelSize);
+            const int iBMX = static_cast<int>(
+                (psTransform->padfGeoLocX[i] - dfMinX) / dfPixelSize);
+            const int iBMY = static_cast<int>(
+                (dfMaxY - psTransform->padfGeoLocY[i]) / dfPixelSize);
 
             if( iBMX < 0 || iBMY < 0 || iBMX >= nBMXSize || iBMY >= nBMYSize )
                 continue;
 
             psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] =
-                (float)(iX * psTransform->dfPIXEL_STEP + psTransform->dfPIXEL_OFFSET);
+                static_cast<float>(
+                    iX * psTransform->dfPIXEL_STEP +
+                    psTransform->dfPIXEL_OFFSET);
             psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] =
-                (float)(iY * psTransform->dfLINE_STEP + psTransform->dfLINE_OFFSET);
-
-            pabyValidFlag[iBMX + iBMY * nBMXSize] = (GByte) (nMaxIter+1);
+                static_cast<float>(
+                    iY * psTransform->dfLINE_STEP +
+                    psTransform->dfLINE_OFFSET);
 
+            pabyValidFlag[iBMX + iBMY * nBMXSize] =
+                static_cast<GByte>(nMaxIter+1);
         }
     }
 
@@ -339,17 +350,14 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
 /*      Now, loop over the backmap trying to fill in holes with         */
 /*      nearby values.                                                  */
 /* -------------------------------------------------------------------- */
-    int iIter;
-    int nNumValid;
-
-    for( iIter = 0; iIter < nMaxIter; iIter++ )
+    for( int iIter = 0; iIter < nMaxIter; iIter++ )
     {
-        nNumValid = 0;
-        for( iBMY = 0; iBMY < nBMYSize; iBMY++ )
+        int nNumValid = 0;
+        for( int iBMY = 0; iBMY < nBMYSize; iBMY++ )
         {
-            for( iBMX = 0; iBMX < nBMXSize; iBMX++ )
+            for( int iBMX = 0; iBMX < nBMXSize; iBMX++ )
             {
-                // if this point is already set, ignore it.
+                // If this point is already set, ignore it.
                 if( pabyValidFlag[iBMX + iBMY*nBMXSize] )
                 {
                     nNumValid++;
@@ -357,10 +365,11 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
                 }
 
                 int nCount = 0;
-                double dfXSum = 0.0, dfYSum = 0.0;
-                int nMarkedAsGood = nMaxIter - iIter;
+                double dfXSum = 0.0;
+                double dfYSum = 0.0;
+                const int nMarkedAsGood = nMaxIter - iIter;
 
-                // left?
+                // Left?
                 if( iBMX > 0 &&
                     pabyValidFlag[iBMX-1+iBMY*nBMXSize] > nMarkedAsGood )
                 {
@@ -368,7 +377,7 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
                     dfYSum += psTransform->pafBackMapY[iBMX-1+iBMY*nBMXSize];
                     nCount++;
                 }
-                // right?
+                // Right?
                 if( iBMX + 1 < nBMXSize &&
                     pabyValidFlag[iBMX+1+iBMY*nBMXSize] > nMarkedAsGood )
                 {
@@ -376,7 +385,7 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
                     dfYSum += psTransform->pafBackMapY[iBMX+1+iBMY*nBMXSize];
                     nCount++;
                 }
-                // top?
+                // Top?
                 if( iBMY > 0 &&
                     pabyValidFlag[iBMX+(iBMY-1)*nBMXSize] > nMarkedAsGood )
                 {
@@ -384,7 +393,7 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
                     dfYSum += psTransform->pafBackMapY[iBMX+(iBMY-1)*nBMXSize];
                     nCount++;
                 }
-                // bottom?
+                // Bottom?
                 if( iBMY + 1 < nBMYSize &&
                     pabyValidFlag[iBMX+(iBMY+1)*nBMXSize] > nMarkedAsGood )
                 {
@@ -392,323 +401,83 @@ static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )
                     dfYSum += psTransform->pafBackMapY[iBMX+(iBMY+1)*nBMXSize];
                     nCount++;
                 }
-                // top-left?
+                // Top-left?
                 if( iBMX > 0 && iBMY > 0 &&
                     pabyValidFlag[iBMX-1+(iBMY-1)*nBMXSize] > nMarkedAsGood )
                 {
-                    dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY-1)*nBMXSize];
-                    dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY-1)*nBMXSize];
+                    dfXSum +=
+                        psTransform->pafBackMapX[iBMX-1+(iBMY-1)*nBMXSize];
+                    dfYSum +=
+                        psTransform->pafBackMapY[iBMX-1+(iBMY-1)*nBMXSize];
                     nCount++;
                 }
-                // top-right?
+                // Top-right?
                 if( iBMX + 1 < nBMXSize && iBMY > 0 &&
                     pabyValidFlag[iBMX+1+(iBMY-1)*nBMXSize] > nMarkedAsGood )
                 {
-                    dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY-1)*nBMXSize];
-                    dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY-1)*nBMXSize];
+                    dfXSum +=
+                        psTransform->pafBackMapX[iBMX+1+(iBMY-1)*nBMXSize];
+                    dfYSum +=
+                        psTransform->pafBackMapY[iBMX+1+(iBMY-1)*nBMXSize];
                     nCount++;
                 }
-                // bottom-left?
+                // Bottom-left?
                 if( iBMX > 0 && iBMY + 1 < nBMYSize &&
                     pabyValidFlag[iBMX-1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
                 {
-                    dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY+1)*nBMXSize];
-                    dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY+1)*nBMXSize];
+                    dfXSum +=
+                        psTransform->pafBackMapX[iBMX-1+(iBMY+1)*nBMXSize];
+                    dfYSum +=
+                        psTransform->pafBackMapY[iBMX-1+(iBMY+1)*nBMXSize];
                     nCount++;
                 }
-                // bottom-right?
+                // Bottom-right?
                 if( iBMX + 1 < nBMXSize && iBMY + 1 < nBMYSize &&
                     pabyValidFlag[iBMX+1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
                 {
-                    dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY+1)*nBMXSize];
-                    dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY+1)*nBMXSize];
+                    dfXSum +=
+                        psTransform->pafBackMapX[iBMX+1+(iBMY+1)*nBMXSize];
+                    dfYSum +=
+                        psTransform->pafBackMapY[iBMX+1+(iBMY+1)*nBMXSize];
                     nCount++;
                 }
 
                 if( nCount > 0 )
                 {
-                    psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = (float)(dfXSum/nCount);
-                    psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = (float)(dfYSum/nCount);
-                    // genuinely valid points will have value iMaxIter+1
+                    psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] =
+                        static_cast<float>(dfXSum/nCount);
+                    psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] =
+                        static_cast<float>(dfYSum/nCount);
+                    // Genuinely valid points will have value iMaxIter + 1.
                     // On each iteration mark newly valid points with a
                     // descending value so that it will not be used on the
                     // current iteration only on subsequent ones.
-                    pabyValidFlag[iBMX+iBMY*nBMXSize] = (GByte) (nMaxIter - iIter);
+                    pabyValidFlag[iBMX+iBMY*nBMXSize] =
+                        static_cast<GByte>(nMaxIter - iIter);
                 }
             }
         }
-        if (nNumValid == nBMXSize * nBMYSize)
+        if( nNumValid == nBMXSize * nBMYSize )
             break;
     }
 
-#ifdef notdef
-    GDALDatasetH hBMDS = GDALCreate( GDALGetDriverByName( "GTiff" ),
-                                     "backmap.tif", nBMXSize, nBMYSize, 2,
-                                     GDT_Float32, NULL );
-    GDALSetGeoTransform( hBMDS, psTransform->adfBackMapGeoTransform );
-    GDALRasterIO( GDALGetRasterBand(hBMDS,1), GF_Write,
-                  0, 0, nBMXSize, nBMYSize,
-                  psTransform->pafBackMapX, nBMXSize, nBMYSize,
-                  GDT_Float32, 0, 0 );
-    GDALRasterIO( GDALGetRasterBand(hBMDS,2), GF_Write,
-                  0, 0, nBMXSize, nBMYSize,
-                  psTransform->pafBackMapY, nBMXSize, nBMYSize,
-                  GDT_Float32, 0, 0 );
-    GDALClose( hBMDS );
-#endif
-
     CPLFree( pabyValidFlag );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
-/*                         FindGeoLocPosition()                         */
-/************************************************************************/
-
-#ifdef notdef
-
-/*
-This searching approach has been abandoned because it is too sensitive
-to discontinuities in the data.  Left in case it might be revived in
-the future.
- */
-
-static int FindGeoLocPosition( GDALGeoLocTransformInfo *psTransform,
-                               double dfGeoX, double dfGeoY,
-                               int nStartX, int nStartY,
-                               double *pdfFoundX, double *pdfFoundY )
-
-{
-    double adfPathX[5000], adfPathY[5000];
-
-    if( psTransform->padfGeoLocX == NULL )
-        return FALSE;
-
-    int nXSize = psTransform->nGeoLocXSize;
-    int nYSize = psTransform->nGeoLocYSize;
-    int nStepCount = 0;
-
-    // Start in center if we don't have any provided info.
-    if( nStartX < 0 || nStartY < 0
-        || nStartX >= nXSize || nStartY >= nYSize )
-    {
-        nStartX = nXSize / 2;
-        nStartY = nYSize / 2;
-    }
-
-    nStartX = MIN(nStartX,nXSize-2);
-    nStartY = MIN(nStartY,nYSize-2);
-
-    int iX = nStartX, iY = nStartY;
-    int iLastX = -1, iLastY = -1;
-    int iSecondLastX = -1, iSecondLastY = -1;
-
-    while( nStepCount < MAX(nXSize,nYSize) )
-    {
-        int iXNext = -1, iYNext = -1;
-        double dfDeltaXRight, dfDeltaYRight, dfDeltaXDown, dfDeltaYDown;
-
-        double *padfThisX = psTransform->padfGeoLocX + iX + iY * nXSize;
-        double *padfThisY = psTransform->padfGeoLocY + iX + iY * nXSize;
-
-        double dfDeltaX = dfGeoX - *padfThisX;
-        double dfDeltaY = dfGeoY - *padfThisY;
-
-        if( iX == nXSize-1 )
-        {
-            dfDeltaXRight = *(padfThisX) - *(padfThisX-1);
-            dfDeltaYRight = *(padfThisY) - *(padfThisY-1);
-        }
-        else
-        {
-            dfDeltaXRight = *(padfThisX+1) - *padfThisX;
-            dfDeltaYRight = *(padfThisY+1) - *padfThisY;
-        }
-
-        if( iY == nYSize - 1 )
-        {
-            dfDeltaXDown = *(padfThisX) - *(padfThisX-nXSize);
-            dfDeltaYDown = *(padfThisY) - *(padfThisY-nXSize);
-        }
-        else
-        {
-            dfDeltaXDown = *(padfThisX+nXSize) - *padfThisX;
-            dfDeltaYDown = *(padfThisY+nXSize) - *padfThisY;
-        }
-
-        double dfRightProjection =
-            (dfDeltaXRight * dfDeltaX + dfDeltaYRight * dfDeltaY)
-            / (dfDeltaXRight*dfDeltaXRight + dfDeltaYRight*dfDeltaYRight);
-
-        double dfDownProjection =
-            (dfDeltaXDown * dfDeltaX + dfDeltaYDown * dfDeltaY)
-            / (dfDeltaXDown*dfDeltaXDown + dfDeltaYDown*dfDeltaYDown);
-
-        // Are we in our target cell?
-        if( dfRightProjection >= 0.0 && dfRightProjection < 1.0
-            && dfDownProjection >= 0.0 && dfDownProjection < 1.0 )
-        {
-            *pdfFoundX = iX + dfRightProjection;
-            *pdfFoundY = iY + dfDownProjection;
-
-            return TRUE;
-        }
-
-        if( ABS(dfRightProjection) > ABS(dfDownProjection) )
-        {
-            // Do we want to move right?
-            if( dfRightProjection > 1.0 && iX < nXSize-1 )
-            {
-                iXNext = iX + MAX(1,(int)(dfRightProjection - nStepCount)/2);
-                iYNext = iY;
-            }
-
-            // Do we want to move left?
-            else if( dfRightProjection < 0.0 && iX > 0 )
-            {
-                iXNext = iX - MAX(1,(int)(ABS(dfRightProjection) - nStepCount)/2);
-                iYNext = iY;
-            }
-
-            // Do we want to move down.
-            else if( dfDownProjection > 1.0 && iY < nYSize-1 )
-            {
-                iXNext = iX;
-                iYNext = iY + MAX(1,(int)(dfDownProjection - nStepCount)/2);
-            }
-
-            // Do we want to move up?
-            else if( dfDownProjection < 0.0 && iY > 0 )
-            {
-                iXNext = iX;
-                iYNext = iY - MAX(1,(int)(ABS(dfDownProjection) - nStepCount)/2);
-            }
-
-            // We aren't there, and we have no where to go
-            else
-            {
-                return FALSE;
-            }
-        }
-        else
-        {
-            // Do we want to move down.
-            if( dfDownProjection > 1.0 && iY < nYSize-1 )
-            {
-                iXNext = iX;
-                iYNext = iY + MAX(1,(int)(dfDownProjection - nStepCount)/2);
-            }
-
-            // Do we want to move up?
-            else if( dfDownProjection < 0.0 && iY > 0 )
-            {
-                iXNext = iX;
-                iYNext = iY - MAX(1,(int)(ABS(dfDownProjection) - nStepCount)/2);
-            }
-
-            // Do we want to move right?
-            else if( dfRightProjection > 1.0 && iX < nXSize-1 )
-            {
-                iXNext = iX + MAX(1,(int)(dfRightProjection - nStepCount)/2);
-                iYNext = iY;
-            }
-
-            // Do we want to move left?
-            else if( dfRightProjection < 0.0 && iX > 0 )
-            {
-                iXNext = iX - MAX(1,(int)(ABS(dfRightProjection) - nStepCount)/2);
-                iYNext = iY;
-            }
-
-            // We aren't there, and we have no where to go
-            else
-            {
-                return FALSE;
-            }
-        }
-                adfPathX[nStepCount] = iX;
-        adfPathY[nStepCount] = iY;
-
-        nStepCount++;
-        iX = MAX(0,MIN(iXNext,nXSize-1));
-        iY = MAX(0,MIN(iYNext,nYSize-1));
-
-        if( iX == iSecondLastX && iY == iSecondLastY )
-        {
-            // Are we *near* our target cell?
-            if( dfRightProjection >= -1.0 && dfRightProjection < 2.0
-                && dfDownProjection >= -1.0 && dfDownProjection < 2.0 )
-            {
-                *pdfFoundX = iX + dfRightProjection;
-                *pdfFoundY = iY + dfDownProjection;
-
-                return TRUE;
-            }
-
-#ifdef SHAPE_DEBUG
-            if( hSHP != NULL )
-            {
-                SHPObject *hObj;
-
-                hObj = SHPCreateSimpleObject( SHPT_ARC, nStepCount,
-                                              adfPathX, adfPathY, NULL );
-                SHPWriteObject( hSHP, -1, hObj );
-                SHPDestroyObject( hObj );
-
-                int iShape = DBFGetRecordCount( hDBF );
-                DBFWriteDoubleAttribute( hDBF, iShape, 0, dfGeoX );
-                DBFWriteDoubleAttribute( hDBF, iShape, 1, dfGeoY );
-            }
-#endif
-            //CPLDebug( "GeoL", "Looping at step (%d) on search for %g,%g.",
-            //          nStepCount, dfGeoX, dfGeoY );
-            return FALSE;
-        }
-
-        iSecondLastX = iLastX;
-        iSecondLastY = iLastY;
-
-        iLastX = iX;
-        iLastY = iY;
-
-    }
-
-    //CPLDebug( "GeoL", "Exceeded step count max (%d) on search for %g,%g.",
-    //          MAX(nXSize,nYSize),
-    //          dfGeoX, dfGeoY );
-
-#ifdef SHAPE_DEBUG
-    if( hSHP != NULL )
-    {
-        SHPObject *hObj;
-
-        hObj = SHPCreateSimpleObject( SHPT_ARC, nStepCount,
-                                      adfPathX, adfPathY, NULL );
-        SHPWriteObject( hSHP, -1, hObj );
-        SHPDestroyObject( hObj );
-
-        int iShape = DBFGetRecordCount( hDBF );
-        DBFWriteDoubleAttribute( hDBF, iShape, 0, dfGeoX );
-        DBFWriteDoubleAttribute( hDBF, iShape, 1, dfGeoY );
-    }
-#endif
-
-    return FALSE;
-}
-#endif /* def notdef */
-
-
-/************************************************************************/
 /*                       GDALGeoLocRescale()                            */
 /************************************************************************/
 
-static void GDALGeoLocRescale(char**& papszMD, const char* pszItem,
-                                  double dfRatio, double dfDefaultVal)
+static void GDALGeoLocRescale( char**& papszMD, const char* pszItem,
+                               double dfRatio, double dfDefaultVal )
 {
-    double dfVal = CPLAtofM(CSLFetchNameValueDef(papszMD, pszItem,
-                                            CPLSPrintf("%.18g", dfDefaultVal)));
-    dfVal *= dfRatio;
+    const double dfVal =
+        dfRatio *
+        CPLAtofM(CSLFetchNameValueDef(papszMD, pszItem,
+                                      CPLSPrintf("%.18g", dfDefaultVal)));
+
     papszMD = CSLSetNameValue(papszMD, pszItem, CPLSPrintf("%.18g", dfVal));
 }
 
@@ -717,11 +486,14 @@ static void GDALGeoLocRescale(char**& papszMD, const char* pszItem,
 /************************************************************************/
 
 static
-void* GDALCreateSimilarGeoLocTransformer( void *hTransformArg, double dfRatioX, double dfRatioY )
+void* GDALCreateSimilarGeoLocTransformer( void *hTransformArg,
+                                          double dfRatioX, double dfRatioY )
 {
-    VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarGeoLocTransformer", NULL );
+    VALIDATE_POINTER1(hTransformArg, "GDALCreateSimilarGeoLocTransformer",
+                      NULL);
 
-    GDALGeoLocTransformInfo *psInfo = (GDALGeoLocTransformInfo *) hTransformArg;
+    GDALGeoLocTransformInfo *psInfo =
+        static_cast<GDALGeoLocTransformInfo *>(hTransformArg);
 
     char** papszGeolocationInfo = CSLDuplicate(psInfo->papszGeolocationInfo);
 
@@ -729,12 +501,15 @@ void* GDALCreateSimilarGeoLocTransformer( void *hTransformArg, double dfRatioX,
     {
         GDALGeoLocRescale(papszGeolocationInfo, "PIXEL_OFFSET", dfRatioX, 0.0);
         GDALGeoLocRescale(papszGeolocationInfo, "LINE_OFFSET", dfRatioY, 0.0);
-        GDALGeoLocRescale(papszGeolocationInfo, "PIXEL_STEP", 1.0 / dfRatioX, 1.0);
-        GDALGeoLocRescale(papszGeolocationInfo, "LINE_STEP", 1.0 / dfRatioY, 1.0);
+        GDALGeoLocRescale(
+            papszGeolocationInfo, "PIXEL_STEP", 1.0 / dfRatioX, 1.0);
+        GDALGeoLocRescale(papszGeolocationInfo,
+            "LINE_STEP", 1.0 / dfRatioY, 1.0);
     }
 
-    psInfo = (GDALGeoLocTransformInfo*) GDALCreateGeoLocTransformer(
-        NULL, papszGeolocationInfo, psInfo->bReversed );
+    psInfo = static_cast<GDALGeoLocTransformInfo*>(
+        GDALCreateGeoLocTransformer(
+            NULL, papszGeolocationInfo, psInfo->bReversed));
 
     CSLDestroy(papszGeolocationInfo);
 
@@ -745,34 +520,37 @@ void* GDALCreateSimilarGeoLocTransformer( void *hTransformArg, double dfRatioX,
 /*                    GDALCreateGeoLocTransformer()                     */
 /************************************************************************/
 
+/** Create GeoLocation transformer */
 void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
                                    char **papszGeolocationInfo,
                                    int bReversed )
 
 {
-    GDALGeoLocTransformInfo *psTransform;
-
-    if( CSLFetchNameValue(papszGeolocationInfo,"PIXEL_OFFSET") == NULL
-        || CSLFetchNameValue(papszGeolocationInfo,"LINE_OFFSET") == NULL
-        || CSLFetchNameValue(papszGeolocationInfo,"PIXEL_STEP") == NULL
-        || CSLFetchNameValue(papszGeolocationInfo,"LINE_STEP") == NULL
-        || CSLFetchNameValue(papszGeolocationInfo,"X_BAND") == NULL
-        || CSLFetchNameValue(papszGeolocationInfo,"Y_BAND") == NULL )
+    if( CSLFetchNameValue(papszGeolocationInfo, "PIXEL_OFFSET") == NULL
+        || CSLFetchNameValue(papszGeolocationInfo, "LINE_OFFSET") == NULL
+        || CSLFetchNameValue(papszGeolocationInfo, "PIXEL_STEP") == NULL
+        || CSLFetchNameValue(papszGeolocationInfo, "LINE_STEP") == NULL
+        || CSLFetchNameValue(papszGeolocationInfo, "X_BAND") == NULL
+        || CSLFetchNameValue(papszGeolocationInfo, "Y_BAND") == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Missing some geolocation fields in GDALCreateGeoLocTransformer()" );
+                  "Missing some geolocation fields in "
+                  "GDALCreateGeoLocTransformer()" );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Initialize core info.                                           */
 /* -------------------------------------------------------------------- */
-    psTransform = (GDALGeoLocTransformInfo *)
-        CPLCalloc(sizeof(GDALGeoLocTransformInfo),1);
+    GDALGeoLocTransformInfo *psTransform =
+        static_cast<GDALGeoLocTransformInfo *>(
+            CPLCalloc(sizeof(GDALGeoLocTransformInfo), 1));
 
-    psTransform->bReversed = bReversed;
+    psTransform->bReversed = CPL_TO_BOOL(bReversed);
 
-    memcpy( psTransform->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
+    memcpy( psTransform->sTI.abySignature,
+            GDAL_GTI2_SIGNATURE,
+            strlen(GDAL_GTI2_SIGNATURE) );
     psTransform->sTI.pszClassName = "GDALGeoLocTransformer";
     psTransform->sTI.pfnTransform = GDALGeoLocTransform;
     psTransform->sTI.pfnCleanup = GDALDestroyGeoLocTransformer;
@@ -784,14 +562,14 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
 /* -------------------------------------------------------------------- */
 /*      Pull geolocation info from the options/metadata.                */
 /* -------------------------------------------------------------------- */
-    psTransform->dfPIXEL_OFFSET = CPLAtof(CSLFetchNameValue( papszGeolocationInfo,
-                                                          "PIXEL_OFFSET" ));
-    psTransform->dfLINE_OFFSET = CPLAtof(CSLFetchNameValue( papszGeolocationInfo,
-                                                         "LINE_OFFSET" ));
-    psTransform->dfPIXEL_STEP = CPLAtof(CSLFetchNameValue( papszGeolocationInfo,
-                                                        "PIXEL_STEP" ));
-    psTransform->dfLINE_STEP = CPLAtof(CSLFetchNameValue( papszGeolocationInfo,
-                                                       "LINE_STEP" ));
+    psTransform->dfPIXEL_OFFSET =
+        CPLAtof(CSLFetchNameValue( papszGeolocationInfo, "PIXEL_OFFSET" ));
+    psTransform->dfLINE_OFFSET =
+        CPLAtof(CSLFetchNameValue( papszGeolocationInfo, "LINE_OFFSET" ));
+    psTransform->dfPIXEL_STEP =
+        CPLAtof(CSLFetchNameValue( papszGeolocationInfo, "PIXEL_STEP" ));
+    psTransform->dfLINE_STEP =
+        CPLAtof(CSLFetchNameValue( papszGeolocationInfo, "LINE_STEP" ));
 
 /* -------------------------------------------------------------------- */
 /*      Establish access to geolocation dataset(s).                     */
@@ -833,8 +611,8 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
         }
     }
 
-    if (psTransform->hDS_X == NULL ||
-        psTransform->hDS_Y == NULL)
+    if( psTransform->hDS_X == NULL ||
+        psTransform->hDS_Y == NULL )
     {
         GDALDestroyGeoLocTransformer( psTransform );
         return NULL;
@@ -843,16 +621,16 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
 /* -------------------------------------------------------------------- */
 /*      Get the band handles.                                           */
 /* -------------------------------------------------------------------- */
-    int nBand;
+    const int nXBand =
+        std::max(1, atoi(CSLFetchNameValue( papszGeolocationInfo, "X_BAND" )));
+    psTransform->hBand_X = GDALGetRasterBand( psTransform->hDS_X, nXBand );
 
-    nBand = MAX(1,atoi(CSLFetchNameValue( papszGeolocationInfo, "X_BAND" )));
-    psTransform->hBand_X = GDALGetRasterBand( psTransform->hDS_X, nBand );
+    const int nYBand =
+        std::max(1, atoi(CSLFetchNameValue( papszGeolocationInfo, "Y_BAND" )));
+    psTransform->hBand_Y = GDALGetRasterBand( psTransform->hDS_Y, nYBand );
 
-    nBand = MAX(1,atoi(CSLFetchNameValue( papszGeolocationInfo, "Y_BAND" )));
-    psTransform->hBand_Y = GDALGetRasterBand( psTransform->hDS_Y, nBand );
-
-    if (psTransform->hBand_X == NULL ||
-        psTransform->hBand_Y == NULL)
+    if( psTransform->hBand_X == NULL ||
+        psTransform->hBand_Y == NULL )
     {
         GDALDestroyGeoLocTransformer( psTransform );
         return NULL;
@@ -861,21 +639,21 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
 /* -------------------------------------------------------------------- */
 /*     Check that X and Y bands have the same dimensions                */
 /* -------------------------------------------------------------------- */
-    int nXSize_XBand = GDALGetRasterXSize( psTransform->hDS_X );
-    int nYSize_XBand = GDALGetRasterYSize( psTransform->hDS_X );
-    int nXSize_YBand = GDALGetRasterXSize( psTransform->hDS_Y );
-    int nYSize_YBand = GDALGetRasterYSize( psTransform->hDS_Y );
-    if (nYSize_XBand == 1 || nYSize_YBand == 1)
+    const int nXSize_XBand = GDALGetRasterXSize( psTransform->hDS_X );
+    const int nYSize_XBand = GDALGetRasterYSize( psTransform->hDS_X );
+    const int nXSize_YBand = GDALGetRasterXSize( psTransform->hDS_Y );
+    const int nYSize_YBand = GDALGetRasterYSize( psTransform->hDS_Y );
+    if( nYSize_XBand == 1 || nYSize_YBand == 1 )
     {
-        if (nYSize_XBand != 1 || nYSize_YBand != 1)
+        if( nYSize_XBand != 1 || nYSize_YBand != 1 )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                 "X_BAND and Y_BAND should have both nYSize == 1");
+                     "X_BAND and Y_BAND should have both nYSize == 1");
             GDALDestroyGeoLocTransformer( psTransform );
             return NULL;
         }
     }
-    else if (nXSize_XBand != nXSize_YBand ||
+    else if( nXSize_XBand != nXSize_YBand ||
              nYSize_XBand != nYSize_YBand )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -884,7 +662,7 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
         return NULL;
     }
 
-    if (nXSize_XBand > INT_MAX / nYSize_XBand)
+    if( nXSize_XBand > INT_MAX / nYSize_XBand )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Int overflow : %d x %d",
                  nXSize_XBand, nYSize_XBand);
@@ -909,6 +687,7 @@ void *GDALCreateGeoLocTransformer( GDALDatasetH hBaseDS,
 /*                    GDALDestroyGeoLocTransformer()                    */
 /************************************************************************/
 
+/** Destroy GeoLocation transformer */
 void GDALDestroyGeoLocTransformer( void *pTransformAlg )
 
 {
@@ -916,7 +695,7 @@ void GDALDestroyGeoLocTransformer( void *pTransformAlg )
         return;
 
     GDALGeoLocTransformInfo *psTransform =
-        (GDALGeoLocTransformInfo *) pTransformAlg;
+        static_cast<GDALGeoLocTransformInfo *>(pTransformAlg);
 
     CPLFree( psTransform->pafBackMapX );
     CPLFree( psTransform->pafBackMapY );
@@ -939,6 +718,7 @@ void GDALDestroyGeoLocTransformer( void *pTransformAlg )
 /*                        GDALGeoLocTransform()                         */
 /************************************************************************/
 
+/** Use GeoLocation transformer */
 int GDALGeoLocTransform( void *pTransformArg,
                          int bDstToSrc,
                          int nPointCount,
@@ -947,7 +727,7 @@ int GDALGeoLocTransform( void *pTransformArg,
                          int *panSuccess )
 {
     GDALGeoLocTransformInfo *psTransform =
-        (GDALGeoLocTransformInfo *) pTransformArg;
+        static_cast<GDALGeoLocTransformInfo *>(pTransformArg);
 
     if( psTransform->bReversed )
         bDstToSrc = !bDstToSrc;
@@ -957,9 +737,9 @@ int GDALGeoLocTransform( void *pTransformArg,
 /* -------------------------------------------------------------------- */
     if( !bDstToSrc )
     {
-        int i, nXSize = psTransform->nGeoLocXSize;
+        const int nXSize = psTransform->nGeoLocXSize;
 
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
             {
@@ -967,17 +747,17 @@ int GDALGeoLocTransform( void *pTransformArg,
                 continue;
             }
 
-            double dfGeoLocPixel = (padfX[i] - psTransform->dfPIXEL_OFFSET)
+            const double dfGeoLocPixel =
+                (padfX[i] - psTransform->dfPIXEL_OFFSET)
                 / psTransform->dfPIXEL_STEP;
-            double dfGeoLocLine = (padfY[i] - psTransform->dfLINE_OFFSET)
+            const double dfGeoLocLine =
+                (padfY[i] - psTransform->dfLINE_OFFSET)
                 / psTransform->dfLINE_STEP;
 
-            int iX, iY;
-
-            iX = MAX(0,(int) dfGeoLocPixel);
-            iX = MIN(iX,psTransform->nGeoLocXSize-1);
-            iY = MAX(0,(int) dfGeoLocLine);
-            iY = MIN(iY,psTransform->nGeoLocYSize-1);
+            int iX = std::max(0, static_cast<int>(dfGeoLocPixel));
+            iX = std::min(iX, psTransform->nGeoLocXSize-1);
+            int iY = std::max(0, static_cast<int>(dfGeoLocLine));
+            iY = std::min(iY, psTransform->nGeoLocYSize-1);
 
             double *padfGLX = psTransform->padfGeoLocX + iX + iY * nXSize;
             double *padfGLY = psTransform->padfGeoLocY + iX + iY * nXSize;
@@ -1001,19 +781,29 @@ int GDALGeoLocTransform( void *pTransformArg,
                      padfGLX[nXSize] != psTransform->dfNoDataX &&
                      padfGLX[nXSize + 1] != psTransform->dfNoDataX) ))
             {
-                padfX[i] = (1 - (dfGeoLocLine -iY)) * (padfGLX[0] + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0]))
-                           + (dfGeoLocLine -iY) * (padfGLX[nXSize] + (dfGeoLocPixel-iX) * (padfGLX[nXSize+1] - padfGLX[nXSize]));
-                padfY[i] = (1 - (dfGeoLocLine -iY)) * (padfGLY[0] + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0]))
-                           + (dfGeoLocLine -iY) * (padfGLY[nXSize] + (dfGeoLocPixel-iX) * (padfGLY[nXSize+1] - padfGLY[nXSize]));
+                padfX[i] =
+                    (1 - (dfGeoLocLine -iY))
+                    * (padfGLX[0] +
+                       (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0]))
+                    + (dfGeoLocLine -iY)
+                    * (padfGLX[nXSize] + (dfGeoLocPixel-iX) *
+                       (padfGLX[nXSize+1] - padfGLX[nXSize]));
+                padfY[i] =
+                    (1 - (dfGeoLocLine -iY))
+                    * (padfGLY[0] +
+                       (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0]))
+                    + (dfGeoLocLine -iY)
+                    * (padfGLY[nXSize] + (dfGeoLocPixel-iX) *
+                       (padfGLY[nXSize+1] - padfGLY[nXSize]));
             }
             else if( iX + 1 < psTransform->nGeoLocXSize &&
                      (!psTransform->bHasNoData ||
                         padfGLX[1] != psTransform->dfNoDataX) )
             {
-                padfX[i] = padfGLX[0]
-                    + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0]);
-                padfY[i] = padfGLY[0]
-                    + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0]);
+                padfX[i] =
+                    padfGLX[0] + (dfGeoLocPixel-iX) * (padfGLX[1] - padfGLX[0]);
+                padfY[i] =
+                    padfGLY[0] + (dfGeoLocPixel-iX) * (padfGLY[1] - padfGLY[0]);
             }
             else if( iY + 1 < psTransform->nGeoLocYSize &&
                      (!psTransform->bHasNoData ||
@@ -1039,9 +829,7 @@ int GDALGeoLocTransform( void *pTransformArg,
 /* -------------------------------------------------------------------- */
     else
     {
-        int i;
-
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
             {
@@ -1049,18 +837,17 @@ int GDALGeoLocTransform( void *pTransformArg,
                 continue;
             }
 
-            double dfBMX, dfBMY;
-            int iBMX, iBMY;
-
-            dfBMX = ((padfX[i] - psTransform->adfBackMapGeoTransform[0])
-                          / psTransform->adfBackMapGeoTransform[1]);
-            dfBMY = ((padfY[i] - psTransform->adfBackMapGeoTransform[3])
-                          / psTransform->adfBackMapGeoTransform[5]);
+            const double dfBMX =
+                ((padfX[i] - psTransform->adfBackMapGeoTransform[0])
+                 / psTransform->adfBackMapGeoTransform[1]);
+            const double dfBMY =
+                ((padfY[i] - psTransform->adfBackMapGeoTransform[3])
+                 / psTransform->adfBackMapGeoTransform[5]);
 
-            iBMX = (int) dfBMX;
-            iBMY = (int) dfBMY;
+            const int iBMX = static_cast<int>(dfBMX);
+            const int iBMY = static_cast<int>(dfBMY);
 
-            int iBM = iBMX + iBMY * psTransform->nBackMapWidth;
+            const int iBM = iBMX + iBMY * psTransform->nBackMapWidth;
 
             if( iBMX < 0 || iBMY < 0
                 || iBMX >= psTransform->nBackMapWidth
@@ -1081,12 +868,20 @@ int GDALGeoLocTransform( void *pTransformArg,
                 pafBMX[1] >=0 && pafBMX[psTransform->nBackMapWidth] >= 0 &&
                 pafBMX[psTransform->nBackMapWidth+1] >= 0)
             {
-                padfX[i] = (1-(dfBMY - iBMY)) * (pafBMX[0] + (dfBMX - iBMX) * (pafBMX[1] - pafBMX[0])) +
-                           (dfBMY - iBMY) * (pafBMX[psTransform->nBackMapWidth] +
-                                (dfBMX - iBMX) * (pafBMX[psTransform->nBackMapWidth+1] - pafBMX[psTransform->nBackMapWidth]));
-                padfY[i] = (1-(dfBMY - iBMY)) * (pafBMY[0] + (dfBMX - iBMX) * (pafBMY[1] - pafBMY[0])) +
-                           (dfBMY - iBMY) * (pafBMY[psTransform->nBackMapWidth] +
-                                (dfBMX - iBMX) * (pafBMY[psTransform->nBackMapWidth+1] - pafBMY[psTransform->nBackMapWidth]));
+                padfX[i] =
+                    (1-(dfBMY - iBMY))
+                    * (pafBMX[0] + (dfBMX - iBMX) * (pafBMX[1] - pafBMX[0]))
+                    + (dfBMY - iBMY)
+                    * (pafBMX[psTransform->nBackMapWidth] +
+                       (dfBMX - iBMX) * (pafBMX[psTransform->nBackMapWidth+1] -
+                                         pafBMX[psTransform->nBackMapWidth]));
+                padfY[i] =
+                    (1-(dfBMY - iBMY))
+                    * (pafBMY[0] + (dfBMX - iBMX) * (pafBMY[1] - pafBMY[0]))
+                    + (dfBMY - iBMY)
+                    * (pafBMY[psTransform->nBackMapWidth] +
+                       (dfBMX - iBMX) * (pafBMY[psTransform->nBackMapWidth+1] -
+                                         pafBMY[psTransform->nBackMapWidth]));
             }
             else if( iBMX + 1 < psTransform->nBackMapWidth &&
                      pafBMX[1] >=0)
@@ -1099,10 +894,14 @@ int GDALGeoLocTransform( void *pTransformArg,
             else if( iBMY + 1 < psTransform->nBackMapHeight &&
                      pafBMX[psTransform->nBackMapWidth] >= 0 )
             {
-                padfX[i] = pafBMX[0] +
-                            (dfBMY - iBMY) * (pafBMX[psTransform->nBackMapWidth] - pafBMX[0]);
-                padfY[i] = pafBMY[0] +
-                            (dfBMY - iBMY) * (pafBMY[psTransform->nBackMapWidth] - pafBMY[0]);
+                padfX[i] =
+                    pafBMX[0] +
+                    (dfBMY - iBMY) * (pafBMX[psTransform->nBackMapWidth] -
+                                      pafBMX[0]);
+                padfY[i] =
+                    pafBMY[0] +
+                    (dfBMY - iBMY) * (pafBMY[psTransform->nBackMapWidth] -
+                                      pafBMY[0]);
             }
             else
             {
@@ -1113,64 +912,6 @@ int GDALGeoLocTransform( void *pTransformArg,
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      geox/geoy to pixel/line using search algorithm.                 */
-/* -------------------------------------------------------------------- */
-#ifdef notdef
-    else
-    {
-        int i;
-        int nStartX = -1, nStartY = -1;
-
-#ifdef SHAPE_DEBUG
-        hSHP = SHPCreate( "tracks.shp", SHPT_ARC );
-        hDBF = DBFCreate( "tracks.dbf" );
-        DBFAddField( hDBF, "GEOX", FTDouble, 10, 4 );
-        DBFAddField( hDBF, "GEOY", FTDouble, 10, 4 );
-#endif
-        for( i = 0; i < nPointCount; i++ )
-        {
-            double dfGeoLocX, dfGeoLocY;
-
-            if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
-            {
-                panSuccess[i] = FALSE;
-                continue;
-            }
-
-            if( !FindGeoLocPosition( psTransform, padfX[i], padfY[i],
-                                     -1, -1, &dfGeoLocX, &dfGeoLocY ) )
-            {
-                padfX[i] = HUGE_VAL;
-                padfY[i] = HUGE_VAL;
-
-                panSuccess[i] = FALSE;
-                continue;
-            }
-            nStartX = (int) dfGeoLocX;
-            nStartY = (int) dfGeoLocY;
-
-            padfX[i] = dfGeoLocX * psTransform->dfPIXEL_STEP
-                + psTransform->dfPIXEL_OFFSET;
-            padfY[i] = dfGeoLocY * psTransform->dfLINE_STEP
-                + psTransform->dfLINE_OFFSET;
-
-            panSuccess[i] = TRUE;
-        }
-
-#ifdef SHAPE_DEBUG
-        if( hSHP != NULL )
-        {
-            DBFClose( hDBF );
-            hDBF = NULL;
-
-            SHPClose( hSHP );
-            hSHP = NULL;
-        }
-#endif
-    }
-#endif
-
     return TRUE;
 }
 
@@ -1183,35 +924,31 @@ CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg )
 {
     VALIDATE_POINTER1( pTransformArg, "GDALSerializeGeoLocTransformer", NULL );
 
-    CPLXMLNode *psTree;
     GDALGeoLocTransformInfo *psInfo =
-        (GDALGeoLocTransformInfo *)(pTransformArg);
+        static_cast<GDALGeoLocTransformInfo *>(pTransformArg);
 
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "GeoLocTransformer" );
+    CPLXMLNode *psTree =
+        CPLCreateXMLNode( NULL, CXT_Element, "GeoLocTransformer" );
 
 /* -------------------------------------------------------------------- */
 /*      Serialize bReversed.                                            */
 /* -------------------------------------------------------------------- */
     CPLCreateXMLElementAndValue(
         psTree, "Reversed",
-        CPLString().Printf( "%d", psInfo->bReversed ) );
+        CPLString().Printf( "%d", static_cast<int>(psInfo->bReversed) ) );
 
 /* -------------------------------------------------------------------- */
 /*      geoloc metadata.                                                */
 /* -------------------------------------------------------------------- */
     char **papszMD = psInfo->papszGeolocationInfo;
-    CPLXMLNode *psMD= CPLCreateXMLNode( psTree, CXT_Element,
-                                        "Metadata" );
+    CPLXMLNode *psMD= CPLCreateXMLNode( psTree, CXT_Element, "Metadata" );
 
     for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
     {
-        const char *pszRawValue;
-        char *pszKey;
-        CPLXMLNode *psMDI;
-
-        pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
+        char *pszKey = NULL;
+        const char *pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
 
-        psMDI = CPLCreateXMLNode( psMD, CXT_Element, "MDI" );
+        CPLXMLNode *psMDI = CPLCreateXMLNode( psMD, CXT_Element, "MDI" );
         CPLSetXMLValue( psMDI, "#key", pszKey );
         CPLCreateXMLNode( psMDI, CXT_Text, pszRawValue );
 
@@ -1228,25 +965,23 @@ CPLXMLNode *GDALSerializeGeoLocTransformer( void *pTransformArg )
 void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree )
 
 {
-    void *pResult;
-    int bReversed;
-    char **papszMD = NULL;
-    CPLXMLNode *psMDI, *psMetadata;
-
 /* -------------------------------------------------------------------- */
 /*      Collect metadata.                                               */
 /* -------------------------------------------------------------------- */
-    psMetadata = CPLGetXMLNode( psTree, "Metadata" );
+    CPLXMLNode *psMetadata = CPLGetXMLNode( psTree, "Metadata" );
 
     if( psMetadata == NULL ||
         psMetadata->eType != CXT_Element
-        || !EQUAL(psMetadata->pszValue,"Metadata") )
+        || !EQUAL(psMetadata->pszValue, "Metadata") )
         return NULL;
 
-    for( psMDI = psMetadata->psChild; psMDI != NULL;
+    char **papszMD = NULL;
+
+    for( CPLXMLNode *psMDI = psMetadata->psChild;
+         psMDI != NULL;
          psMDI = psMDI->psNext )
     {
-        if( !EQUAL(psMDI->pszValue,"MDI")
+        if( !EQUAL(psMDI->pszValue, "MDI")
             || psMDI->eType != CXT_Element
             || psMDI->psChild == NULL
             || psMDI->psChild->psNext == NULL
@@ -1263,12 +998,12 @@ void *GDALDeserializeGeoLocTransformer( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
 /*      Get other flags.                                                */
 /* -------------------------------------------------------------------- */
-    bReversed = atoi(CPLGetXMLValue(psTree,"Reversed","0"));
+    const int bReversed = atoi(CPLGetXMLValue(psTree, "Reversed", "0"));
 
 /* -------------------------------------------------------------------- */
 /*      Generate transformation.                                        */
 /* -------------------------------------------------------------------- */
-    pResult = GDALCreateGeoLocTransformer( NULL, papszMD, bReversed );
+    void *pResult = GDALCreateGeoLocTransformer( NULL, papszMD, bReversed );
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup GCP copy.                                               */
diff --git a/alg/gdalgrid.cpp b/alg/gdalgrid.cpp
index 920ffbf..7df5869 100644
--- a/alg/gdalgrid.cpp
+++ b/alg/gdalgrid.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalgrid.cpp 34393 2016-06-22 21:21:29Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Implementation of GDAL scattered data gridder.
@@ -28,19 +27,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi.h"
-#include "cpl_string.h"
+#include "cpl_port.h"
 #include "gdalgrid.h"
-#include <float.h>
-#include <limits.h>
-#include <map>
-#include "cpl_worker_thread_pool.h"
 #include "gdalgrid_priv.h"
+
+#include <cfloat>
+#include <climits>
+#include <cmath>
 #include <cstdlib>
+#include <cstring>
+
+#include <map>
+#include <utility>
+
+#include "cpl_conv.h"
+#include "cpl_cpu_features.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_progress.h"
+#include "cpl_quad_tree.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "cpl_worker_thread_pool.h"
+#include "gdal.h"
 
-CPL_CVSID("$Id: gdalgrid.cpp 34393 2016-06-22 21:21:29Z rouault $");
+CPL_CVSID("$Id: gdalgrid.cpp 37481 2017-02-27 12:42:13Z rouault $");
 
-#define TO_RADIANS (M_PI / 180.0)
+static const double TO_RADIANS = M_PI / 180.0;
 
 #ifndef DBL_MAX
 # ifdef __DBL_MAX__
@@ -54,18 +67,18 @@ CPL_CVSID("$Id: gdalgrid.cpp 34393 2016-06-22 21:21:29Z rouault $");
 /*                        GDALGridGetPointBounds()                      */
 /************************************************************************/
 
-static void GDALGridGetPointBounds(const void* hFeature, CPLRectObj* pBounds)
+static void GDALGridGetPointBounds( const void* hFeature, CPLRectObj* pBounds )
 {
-    GDALGridPoint* psPoint = (GDALGridPoint*) hFeature;
+    const GDALGridPoint* psPoint = static_cast<const GDALGridPoint*>(hFeature);
     GDALGridXYArrays* psXYArrays = psPoint->psXYArrays;
-    int i = psPoint->i;
-    double dfX = psXYArrays->padfX[i];
-    double dfY = psXYArrays->padfY[i];
+    const int i = psPoint->i;
+    const double dfX = psXYArrays->padfX[i];
+    const double dfY = psXYArrays->padfY[i];
     pBounds->minx = dfX;
     pBounds->miny = dfY;
     pBounds->maxx = dfX;
     pBounds->maxy = dfY;
-};
+}
 
 /************************************************************************/
 /*                   GDALGridInverseDistanceToAPower()                  */
@@ -102,7 +115,7 @@ static void GDALGridGetPointBounds(const void* hFeature, CPLRectObj* pBounds)
  *      w=\frac{1}{r^p}
  *  \f]
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridInverseDistanceToAPowerOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
@@ -112,100 +125,89 @@ static void GDALGridGetPointBounds(const void* hFeature, CPLRectObj* pBounds)
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
- * @param hExtraParamsIn extra parameters.
+ * @param hExtraParamsIn extra parameters (unused)
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr
-GDALGridInverseDistanceToAPower( const void *poOptions, GUInt32 nPoints,
+GDALGridInverseDistanceToAPower( const void *poOptionsIn, GUInt32 nPoints,
                                  const double *padfX, const double *padfY,
                                  const double *padfZ,
                                  double dfXPoint, double dfYPoint,
                                  double *pdfValue,
-                                 CPL_UNUSED void* hExtraParamsIn )
+                                 CPL_UNUSED void* hExtraParamsIn)
 {
     // TODO: For optimization purposes pre-computed parameters should be moved
     // out of this routine to the calling function.
 
-    // Pre-compute search ellipse parameters
-    double      dfRadius1 =
-        ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfRadius1;
-    double      dfRadius2 =
-        ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfRadius2;
-    double  dfR12;
+    const GDALGridInverseDistanceToAPowerOptions * const poOptions =
+        static_cast<const GDALGridInverseDistanceToAPowerOptions *>(
+            poOptionsIn);
 
-    dfRadius1 *= dfRadius1;
-    dfRadius2 *= dfRadius2;
-    dfR12 = dfRadius1 * dfRadius2;
+    // Pre-compute search ellipse parameters.
+    const double dfRadius1 = poOptions->dfRadius1 * poOptions->dfRadius1;
+    const double dfRadius2 = poOptions->dfRadius2 * poOptions->dfRadius2;
+    const double dfR12 = dfRadius1 * dfRadius2;
 
     // Compute coefficients for coordinate system rotation.
-    double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
-    const double dfAngle = TO_RADIANS
-        * ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfAngle;
-    const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
-    if ( bRotated )
-    {
-        dfCoeff1 = cos(dfAngle);
-        dfCoeff2 = sin(dfAngle);
-    }
-
-    const double    dfPowerDiv2 =
-        ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfPower / 2;
-    const double    dfSmoothing =
-        ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfSmoothing;
-    const GUInt32   nMaxPoints =
-        ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->nMaxPoints;
-    double  dfNominator = 0.0, dfDenominator = 0.0;
-    GUInt32 i, n = 0;
+    const double dfAngle = TO_RADIANS * poOptions->dfAngle;
+    const bool bRotated = dfAngle != 0.0;
+    const double dfCoeff1 = bRotated ? cos(dfAngle) : 0.0;
+    const double dfCoeff2 = bRotated ? sin(dfAngle) : 0.0;
+
+    const double dfPowerDiv2 = poOptions->dfPower / 2;
+    const double dfSmoothing = poOptions->dfSmoothing;
+    const GUInt32 nMaxPoints = poOptions->nMaxPoints;
+    double dfNominator = 0.0;
+    double dfDenominator = 0.0;
+    GUInt32 n = 0;
 
-    for ( i = 0; i < nPoints; i++ )
+    for( GUInt32 i = 0; i < nPoints; i++ )
     {
-        double  dfRX = padfX[i] - dfXPoint;
-        double  dfRY = padfY[i] - dfYPoint;
+        double dfRX = padfX[i] - dfXPoint;
+        double dfRY = padfY[i] - dfYPoint;
         const double dfR2 =
             dfRX * dfRX + dfRY * dfRY + dfSmoothing * dfSmoothing;
 
-        if ( bRotated )
+        if( bRotated )
         {
-            double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
-            double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
+            const double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
+            const double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
 
             dfRX = dfRXRotated;
             dfRY = dfRYRotated;
         }
 
         // Is this point located inside the search ellipse?
-        if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
+        if( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
         {
             // If the test point is close to the grid node, use the point
             // value directly as a node value to avoid singularity.
-            if ( dfR2 < 0.0000000000001 )
+            if( dfR2 < 0.0000000000001 )
             {
-                (*pdfValue) = padfZ[i];
+                *pdfValue = padfZ[i];
                 return CE_None;
             }
-            else
-            {
-                const double dfW = pow( dfR2, dfPowerDiv2 );
-                double dfInvW = 1.0 / dfW;
-                dfNominator += dfInvW * padfZ[i];
-                dfDenominator += dfInvW;
-                n++;
-                if ( nMaxPoints > 0 && n > nMaxPoints )
-                    break;
-            }
+
+            const double dfW = pow( dfR2, dfPowerDiv2 );
+            const double dfInvW = 1.0 / dfW;
+            dfNominator += dfInvW * padfZ[i];
+            dfDenominator += dfInvW;
+            n++;
+            if( nMaxPoints > 0 && n > nMaxPoints )
+                break;
         }
     }
 
-    if ( n < ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->nMinPoints
-         || dfDenominator == 0.0 )
+    if( n < poOptions->nMinPoints || dfDenominator == 0.0 )
     {
-        (*pdfValue) =
-            ((GDALGridInverseDistanceToAPowerOptions*)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
-        (*pdfValue) = dfNominator / dfDenominator;
+    {
+        *pdfValue = dfNominator / dfDenominator;
+    }
 
     return CE_None;
 }
@@ -235,7 +237,7 @@ GDALGridInverseDistanceToAPower( const void *poOptions, GUInt32 nPoints,
  *  <ul>
  *      <li> \f$Z_i\f$ is a known value at point \f$i\f$,
  *      <li> \f$r_i\f$ is an Euclidean distance from the grid node
- *           to point \f$i\f$,
+ *           to point \f$i\f$ (with an optional smoothing parameter \f$s\f$),
  *      <li> \f$p\f$ is a weighting power,
  *      <li> \f$n\f$ is a total number of points in search ellipse.
  *  </ul>
@@ -246,7 +248,7 @@ GDALGridInverseDistanceToAPower( const void *poOptions, GUInt32 nPoints,
  *      w=\frac{1}{r^p}
  *  \f]
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridInverseDistanceToAPowerNearestNeighborOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
@@ -262,22 +264,27 @@ GDALGridInverseDistanceToAPower( const void *poOptions, GUInt32 nPoints,
  */
 
 CPLErr
-GDALGridInverseDistanceToAPowerNearestNeighbor( const void *poOptions, GUInt32 nPoints,
-                                 const double *padfX, const double *padfY,
-                                 const double *padfZ,
-                                 double dfXPoint, double dfYPoint,
-                                 double *pdfValue,
-                                 void* hExtraParamsIn )
+GDALGridInverseDistanceToAPowerNearestNeighbor(
+    const void *poOptionsIn, GUInt32 nPoints,
+    const double *padfX, const double *padfY,
+    const double *padfZ,
+    double dfXPoint, double dfYPoint,
+    double *pdfValue,
+    void* hExtraParamsIn )
 {
-    double dfRadius =
-        ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)poOptions)->dfRadius;
-
-    const GUInt32 nMaxPoints =
-        ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)poOptions)->nMaxPoints;
-    double dfNominator = 0.0, dfDenominator = 0.0;
-    GUInt32 n = 0;
-
-    GDALGridExtraParameters* psExtraParams = (GDALGridExtraParameters*) hExtraParamsIn;
+    const
+    GDALGridInverseDistanceToAPowerNearestNeighborOptions *const poOptions =
+      static_cast<
+          const GDALGridInverseDistanceToAPowerNearestNeighborOptions *>(
+          poOptionsIn);
+    const double dfRadius = poOptions->dfRadius;
+    const double dfSmoothing = poOptions->dfSmoothing;
+    const double dfSmoothing2 = dfSmoothing * dfSmoothing;
+
+    const GUInt32 nMaxPoints = poOptions->nMaxPoints;
+
+    GDALGridExtraParameters* psExtraParams =
+        static_cast<GDALGridExtraParameters *>(hExtraParamsIn);
     CPLQuadTree* phQuadTree = psExtraParams->hQuadTree;
 
     const double dfRPower2 = psExtraParams->dfRadiusPower2PreComp;
@@ -286,35 +293,39 @@ GDALGridInverseDistanceToAPowerNearestNeighbor( const void *poOptions, GUInt32 n
     const double dfPowerDiv2 = psExtraParams->dfPowerDiv2PreComp;
 
     std::multimap<double, double> oMapDistanceToZValues;
-    if (phQuadTree != NULL)
+    if( phQuadTree != NULL )
     {
+        const double dfSearchRadius = dfRadius;
         CPLRectObj sAoi;
-        double dfSearchRadius = dfRadius;
         sAoi.minx = dfXPoint - dfSearchRadius;
         sAoi.miny = dfYPoint - dfSearchRadius;
         sAoi.maxx = dfXPoint + dfSearchRadius;
         sAoi.maxy = dfYPoint + dfSearchRadius;
         int nFeatureCount = 0;
-        GDALGridPoint** papsPoints = (GDALGridPoint**)
-                CPLQuadTreeSearch(phQuadTree, &sAoi, &nFeatureCount);
-        if (nFeatureCount != 0)
+        GDALGridPoint** papsPoints = reinterpret_cast<GDALGridPoint **>(
+                CPLQuadTreeSearch(phQuadTree, &sAoi, &nFeatureCount) );
+        if( nFeatureCount != 0 )
         {
-            for(int k = 0; k < nFeatureCount; k++)
+            for( int k = 0; k < nFeatureCount; k++ )
             {
-                int i = papsPoints[k]->i;
-                double  dfRX = padfX[i] - dfXPoint;
-                double  dfRY = padfY[i] - dfYPoint;
+                const int i = papsPoints[k]->i;
+                const double dfRX = padfX[i] - dfXPoint;
+                const double dfRY = padfY[i] - dfYPoint;
 
                 const double dfR2 = dfRX * dfRX + dfRY * dfRY;
-                if (dfR2 < 0.0000000000001)
+                // real distance + smoothing
+                const double dfRsmoothed2 = dfR2 + dfSmoothing2;
+                if( dfRsmoothed2 < 0.0000000000001 )
                 {
-                    (*pdfValue) = padfZ[i];
+                    *pdfValue = padfZ[i];
                     CPLFree(papsPoints);
                     return CE_None;
                 }
-                if(dfR2 <= dfRPower2)
+                // is point within real distance?
+                if( dfR2 <= dfRPower2 )
                 {
-                    oMapDistanceToZValues.insert(std::make_pair(dfR2, padfZ[i]));
+                    oMapDistanceToZValues.insert(
+                        std::make_pair(dfRsmoothed2, padfZ[i]) );
                 }
             }
         }
@@ -322,61 +333,62 @@ GDALGridInverseDistanceToAPowerNearestNeighbor( const void *poOptions, GUInt32 n
     }
     else
     {
-        for (GUInt32 i = 0; i < nPoints; i++)
+        for( GUInt32 i = 0; i < nPoints; i++ )
         {
-            double dfRX = padfX[i] - dfXPoint;
-            double dfRY = padfY[i] - dfYPoint;
-            const double dfR2 =    dfRX * dfRX + dfRY * dfRY;
+            const double dfRX = padfX[i] - dfXPoint;
+            const double dfRY = padfY[i] - dfYPoint;
+            const double dfR2 = dfRX * dfRX + dfRY * dfRY;
+            const double dfRsmoothed2 = dfR2 + dfSmoothing2;
 
             // Is this point located inside the search circle?
-            if (dfRPower2 * dfRX * dfRX + dfRPower2 * dfRY * dfRY <= dfRPower4)
+            if( dfRPower2 * dfRX * dfRX + dfRPower2 * dfRY * dfRY <= dfRPower4 )
             {
                 // If the test point is close to the grid node, use the point
                 // value directly as a node value to avoid singularity.
-                if (dfR2 < 0.0000000000001)
+                if( dfRsmoothed2 < 0.0000000000001 )
                 {
-                    (*pdfValue) = padfZ[i];
+                    *pdfValue = padfZ[i];
                     return CE_None;
                 }
-                else
-                {
-                    oMapDistanceToZValues.insert(std::make_pair(dfR2, padfZ[i]));
-                }
+
+                oMapDistanceToZValues.insert(std::make_pair(dfRsmoothed2, padfZ[i]) );
             }
         }
     }
 
-    /**
-     * Examine all "neighbors" within the radius (sorted by distance via the multimap), and use the
-     * closest n points based on distance until the max is reached.
-     */
-    for(std::multimap<double, double>::iterator oMapDistanceToZValuesIter = oMapDistanceToZValues.begin();
-        oMapDistanceToZValuesIter != oMapDistanceToZValues.end();
-        ++oMapDistanceToZValuesIter)
+    double dfNominator = 0.0;
+    double dfDenominator = 0.0;
+    GUInt32 n = 0;
+
+    // Examine all "neighbors" within the radius (sorted by distance via the
+    // multimap), and use the closest n points based on distance until the max
+    // is reached.
+    for( std::multimap<double, double>::iterator oMapDistanceToZValuesIter =
+             oMapDistanceToZValues.begin();
+         oMapDistanceToZValuesIter != oMapDistanceToZValues.end();
+         ++oMapDistanceToZValuesIter)
     {
-        double dfR2 = (*oMapDistanceToZValuesIter).first;
-        double dfZ = (*oMapDistanceToZValuesIter).second;
+        const double dfR2 = oMapDistanceToZValuesIter->first;
+        const double dfZ = oMapDistanceToZValuesIter->second;
 
         const double dfW = pow(dfR2, dfPowerDiv2);
-        double dfInvW = 1.0 / dfW;
+        const double dfInvW = 1.0 / dfW;
         dfNominator += dfInvW * dfZ;
         dfDenominator += dfInvW;
         n++;
-        if (nMaxPoints > 0 && n >= nMaxPoints)
+        if( nMaxPoints > 0 && n >= nMaxPoints )
         {
             break;
         }
     }
 
-    if (n < ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)poOptions)->nMinPoints
-         || dfDenominator == 0.0 )
+    if( n < poOptions->nMinPoints || dfDenominator == 0.0 )
     {
-        (*pdfValue) =
-            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions*)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
     {
-        (*pdfValue) = dfNominator / dfDenominator;
+        *pdfValue = dfNominator / dfDenominator;
     }
 
     return CE_None;
@@ -398,99 +410,95 @@ GDALGridInverseDistanceToAPowerNearestNeighbor( const void *poOptions, GUInt32 n
  */
 
 CPLErr
-GDALGridInverseDistanceToAPowerNoSearch( const void *poOptions, GUInt32 nPoints,
-                                         const double *padfX, const double *padfY,
-                                         const double *padfZ,
-                                         double dfXPoint, double dfYPoint,
-                                         double *pdfValue,
-                                         CPL_UNUSED void* hExtraParamsIn )
+GDALGridInverseDistanceToAPowerNoSearch(
+    const void *poOptionsIn, GUInt32 nPoints,
+    const double *padfX, const double *padfY, const double *padfZ,
+    double dfXPoint, double dfYPoint,
+    double *pdfValue,
+    void * /* hExtraParamsIn */)
 {
-    const double    dfPowerDiv2 =
-        ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfPower / 2;
-    const double    dfSmoothing =
-        ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfSmoothing;
-    const double    dfSmoothing2 = dfSmoothing * dfSmoothing;
-    double  dfNominator = 0.0, dfDenominator = 0.0;
-    GUInt32 i = 0;
-    int bPower2 = (dfPowerDiv2 == 1.0);
-
+    const GDALGridInverseDistanceToAPowerOptions  * const poOptions =
+        static_cast<const GDALGridInverseDistanceToAPowerOptions *>(
+            poOptionsIn);
+    const double dfPowerDiv2 = poOptions->dfPower / 2.0;
+    const double dfSmoothing = poOptions->dfSmoothing;
+    const double dfSmoothing2 = dfSmoothing * dfSmoothing;
+    double dfNominator = 0.0;
+    double dfDenominator = 0.0;
+    const bool bPower2 = dfPowerDiv2 == 1.0;
+
+    GUInt32 i = 0;  // Used after if.
     if( bPower2 )
     {
         if( dfSmoothing2 > 0 )
         {
-            for ( i = 0; i < nPoints; i++ )
+            for( i = 0; i < nPoints; i++ )
             {
                 const double dfRX = padfX[i] - dfXPoint;
                 const double dfRY = padfY[i] - dfYPoint;
-                const double dfR2 =
-                    dfRX * dfRX + dfRY * dfRY + dfSmoothing2;
+                const double dfR2 = dfRX * dfRX + dfRY * dfRY + dfSmoothing2;
 
-                double dfInvR2 = 1.0 / dfR2;
+                const double dfInvR2 = 1.0 / dfR2;
                 dfNominator += dfInvR2 * padfZ[i];
                 dfDenominator += dfInvR2;
             }
         }
         else
         {
-            for ( i = 0; i < nPoints; i++ )
+            for( i = 0; i < nPoints; i++ )
             {
                 const double dfRX = padfX[i] - dfXPoint;
                 const double dfRY = padfY[i] - dfYPoint;
-                const double dfR2 =
-                    dfRX * dfRX + dfRY * dfRY;
+                const double dfR2 = dfRX * dfRX + dfRY * dfRY;
 
                 // If the test point is close to the grid node, use the point
                 // value directly as a node value to avoid singularity.
-                if ( dfR2 < 0.0000000000001 )
+                if( dfR2 < 0.0000000000001 )
                 {
                     break;
                 }
-                else
-                {
-                    double dfInvR2 = 1.0 / dfR2;
-                    dfNominator += dfInvR2 * padfZ[i];
-                    dfDenominator += dfInvR2;
-                }
+
+                const double dfInvR2 = 1.0 / dfR2;
+                dfNominator += dfInvR2 * padfZ[i];
+                dfDenominator += dfInvR2;
             }
         }
     }
     else
     {
-        for ( i = 0; i < nPoints; i++ )
+        for( i = 0; i < nPoints; i++ )
         {
             const double dfRX = padfX[i] - dfXPoint;
             const double dfRY = padfY[i] - dfYPoint;
-            const double dfR2 =
-                dfRX * dfRX + dfRY * dfRY + dfSmoothing2;
+            const double dfR2 = dfRX * dfRX + dfRY * dfRY + dfSmoothing2;
 
             // If the test point is close to the grid node, use the point
             // value directly as a node value to avoid singularity.
-            if ( dfR2 < 0.0000000000001 )
+            if( dfR2 < 0.0000000000001 )
             {
                 break;
             }
-            else
-            {
-                const double dfW = pow( dfR2, dfPowerDiv2 );
-                double dfInvW = 1.0 / dfW;
-                dfNominator += dfInvW * padfZ[i];
-                dfDenominator += dfInvW;
-            }
+
+            const double dfW = pow( dfR2, dfPowerDiv2 );
+            const double dfInvW = 1.0 / dfW;
+            dfNominator += dfInvW * padfZ[i];
+            dfDenominator += dfInvW;
         }
     }
 
     if( i != nPoints )
     {
-        (*pdfValue) = padfZ[i];
+        *pdfValue = padfZ[i];
     }
     else
-    if ( dfDenominator == 0.0 )
+    if( dfDenominator == 0.0 )
     {
-        (*pdfValue) =
-            ((GDALGridInverseDistanceToAPowerOptions*)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
-        (*pdfValue) = dfNominator / dfDenominator;
+    {
+        *pdfValue = dfNominator / dfDenominator;
+    }
 
     return CE_None;
 }
@@ -522,7 +530,7 @@ GDALGridInverseDistanceToAPowerNoSearch( const void *poOptions, GUInt32 nPoints,
  *      <li> \f$n\f$ is a total number of points in search ellipse.
  *  </ul>
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridMovingAverageOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
@@ -532,75 +540,69 @@ GDALGridInverseDistanceToAPowerNoSearch( const void *poOptions, GUInt32 nPoints,
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
+ * @param hExtraParamsIn extra parameters (unused)
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr
-GDALGridMovingAverage( const void *poOptions, GUInt32 nPoints,
+GDALGridMovingAverage( const void *poOptionsIn, GUInt32 nPoints,
                        const double *padfX, const double *padfY,
                        const double *padfZ,
                        double dfXPoint, double dfYPoint, double *pdfValue,
-                       CPL_UNUSED void* hExtraParamsIn )
+                       CPL_UNUSED void * hExtraParamsIn )
 {
     // TODO: For optimization purposes pre-computed parameters should be moved
     // out of this routine to the calling function.
 
-    // Pre-compute search ellipse parameters
-    double  dfRadius1 = ((GDALGridMovingAverageOptions *)poOptions)->dfRadius1;
-    double  dfRadius2 = ((GDALGridMovingAverageOptions *)poOptions)->dfRadius2;
-    double  dfR12;
-
-    dfRadius1 *= dfRadius1;
-    dfRadius2 *= dfRadius2;
-    dfR12 = dfRadius1 * dfRadius2;
+    const GDALGridMovingAverageOptions * const poOptions =
+        static_cast<const GDALGridMovingAverageOptions *>(poOptionsIn);
+    // Pre-compute search ellipse parameters.
+    const double dfRadius1 = poOptions->dfRadius1 * poOptions->dfRadius1;
+    const double dfRadius2 = poOptions->dfRadius2 * poOptions->dfRadius2;
+    const double dfR12 = dfRadius1 * dfRadius2;
 
     // Compute coefficients for coordinate system rotation.
-    double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
-    const double    dfAngle =
-        TO_RADIANS * ((GDALGridMovingAverageOptions *)poOptions)->dfAngle;
-    const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
-    if ( bRotated )
-    {
-        dfCoeff1 = cos(dfAngle);
-        dfCoeff2 = sin(dfAngle);
-    }
+    const double dfAngle = TO_RADIANS * poOptions->dfAngle;
+    const bool bRotated = dfAngle != 0.0;
+
+    const double dfCoeff1 = bRotated ? cos(dfAngle) : 0.0;
+    const double dfCoeff2 = bRotated ? sin(dfAngle) : 0.0;
+
+    double dfAccumulator = 0.0;
 
-    double  dfAccumulator = 0.0;
-    GUInt32 i = 0, n = 0;
+    GUInt32 n = 0;  // Used after for.
 
-    while ( i < nPoints )
+    for( GUInt32 i = 0; i < nPoints; i++ )
     {
-        double  dfRX = padfX[i] - dfXPoint;
-        double  dfRY = padfY[i] - dfYPoint;
+        double dfRX = padfX[i] - dfXPoint;
+        double dfRY = padfY[i] - dfYPoint;
 
-        if ( bRotated )
+        if( bRotated )
         {
-            double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
-            double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
+            const double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
+            const double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
 
             dfRX = dfRXRotated;
             dfRY = dfRYRotated;
         }
 
         // Is this point located inside the search ellipse?
-        if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
+        if( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
         {
             dfAccumulator += padfZ[i];
             n++;
         }
-
-        i++;
     }
 
-    if ( n < ((GDALGridMovingAverageOptions *)poOptions)->nMinPoints
-         || n == 0 )
+    if( n < poOptions->nMinPoints || n == 0 )
     {
-        (*pdfValue) =
-            ((GDALGridMovingAverageOptions *)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
-        (*pdfValue) = dfAccumulator / n;
+    {
+        *pdfValue = dfAccumulator / n;
+    }
 
     return CE_None;
 }
@@ -617,7 +619,7 @@ GDALGridMovingAverage( const void *poOptions, GUInt32 nPoints,
  * and returns it as a result. If there are no points found, the specified
  * NODATA value will be returned.
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridNearestNeighborOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
@@ -627,12 +629,13 @@ GDALGridMovingAverage( const void *poOptions, GUInt32 nPoints,
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
+ * @param hExtraParamsIn extra parameters.
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr
-GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
+GDALGridNearestNeighbor( const void *poOptionsIn, GUInt32 nPoints,
                          const double *padfX, const double *padfY,
                          const double *padfZ,
                          double dfXPoint, double dfYPoint, double *pdfValue,
@@ -641,64 +644,55 @@ GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
     // TODO: For optimization purposes pre-computed parameters should be moved
     // out of this routine to the calling function.
 
-    // Pre-compute search ellipse parameters
-    double  dfRadius1 =
-        ((GDALGridNearestNeighborOptions *)poOptions)->dfRadius1;
-    double  dfRadius2 =
-        ((GDALGridNearestNeighborOptions *)poOptions)->dfRadius2;
-    double  dfR12;
-    GDALGridExtraParameters* psExtraParams = (GDALGridExtraParameters*) hExtraParamsIn;
+    const GDALGridNearestNeighborOptions * const poOptions =
+        static_cast<const GDALGridNearestNeighborOptions *>(poOptionsIn);
+    // Pre-compute search ellipse parameters.
+    const double dfRadius1 = poOptions->dfRadius1 * poOptions->dfRadius1;
+    const double dfRadius2 = poOptions->dfRadius2 * poOptions->dfRadius2;
+    double dfR12 = dfRadius1 * dfRadius2;
+    GDALGridExtraParameters* psExtraParams =
+        static_cast<GDALGridExtraParameters *>(hExtraParamsIn);
     CPLQuadTree* hQuadTree = psExtraParams->hQuadTree;
 
-    dfRadius1 *= dfRadius1;
-    dfRadius2 *= dfRadius2;
-    dfR12 = dfRadius1 * dfRadius2;
-
     // Compute coefficients for coordinate system rotation.
-    double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
-    const double    dfAngle =
-        TO_RADIANS * ((GDALGridNearestNeighborOptions *)poOptions)->dfAngle;
-    const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
-    if ( bRotated )
-    {
-        dfCoeff1 = cos(dfAngle);
-        dfCoeff2 = sin(dfAngle);
-    }
+    const double dfAngle = TO_RADIANS * poOptions->dfAngle;
+    const bool bRotated = dfAngle != 0.0;
+    const double dfCoeff1 = bRotated ? cos(dfAngle) : 0.0;
+    const double dfCoeff2 = bRotated ? sin(dfAngle) : 0.0;
 
     // If the nearest point will not be found, its value remains as NODATA.
-    double      dfNearestValue =
-        ((GDALGridNearestNeighborOptions *)poOptions)->dfNoDataValue;
+    double dfNearestValue = poOptions->dfNoDataValue;
     // Nearest distance will be initialized with the distance to the first
     // point in array.
-    double      dfNearestR = DBL_MAX;
+    double dfNearestR = DBL_MAX;
     GUInt32 i = 0;
 
     double dfSearchRadius = psExtraParams->dfInitialSearchRadius;
     if( hQuadTree != NULL && dfRadius1 == dfRadius2 && dfSearchRadius > 0 )
     {
-        CPLRectObj sAoi;
         if( dfRadius1 > 0 )
-            dfSearchRadius = ((GDALGridNearestNeighborOptions *)poOptions)->dfRadius1;
-        while(dfSearchRadius > 0)
+            dfSearchRadius = poOptions->dfRadius1;
+        CPLRectObj sAoi;
+        while( dfSearchRadius > 0 )
         {
             sAoi.minx = dfXPoint - dfSearchRadius;
             sAoi.miny = dfYPoint - dfSearchRadius;
             sAoi.maxx = dfXPoint + dfSearchRadius;
             sAoi.maxy = dfYPoint + dfSearchRadius;
             int nFeatureCount = 0;
-            GDALGridPoint** papsPoints = (GDALGridPoint**)
-                    CPLQuadTreeSearch(hQuadTree, &sAoi, &nFeatureCount);
+            GDALGridPoint** papsPoints = reinterpret_cast<GDALGridPoint **>(
+                    CPLQuadTreeSearch(hQuadTree, &sAoi, &nFeatureCount) );
             if( nFeatureCount != 0 )
             {
                 if( dfRadius1 > 0 )
                     dfNearestR = dfRadius1;
-                for(int k=0; k<nFeatureCount; k++)
+                for( int k = 0; k < nFeatureCount; k++)
                 {
-                    int idx = papsPoints[k]->i;
-                    double  dfRX = padfX[idx] - dfXPoint;
-                    double  dfRY = padfY[idx] - dfYPoint;
+                    const int idx = papsPoints[k]->i;
+                    const double dfRX = padfX[idx] - dfXPoint;
+                    const double dfRY = padfY[idx] - dfYPoint;
 
-                    const double    dfR2 = dfRX * dfRX + dfRY * dfRY;
+                    const double dfR2 = dfRX * dfRX + dfRY * dfRY;
                     if( dfR2 <= dfNearestR )
                     {
                         dfNearestR = dfR2;
@@ -709,37 +703,39 @@ GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
                 CPLFree(papsPoints);
                 break;
             }
-            else
-            {
-                CPLFree(papsPoints);
-                if( dfRadius1 > 0 )
-                    break;
-                dfSearchRadius *= 2;
-                //CPLDebug("GDAL_GRID", "Increasing search radius to %.16g", dfSearchRadius);
-            }
+
+            CPLFree(papsPoints);
+            if( dfRadius1 > 0 )
+                break;
+            dfSearchRadius *= 2;
+#if DEBUG_VERBOSE
+            CPLDebug(
+                "GDAL_GRID", "Increasing search radius to %.16g",
+                dfSearchRadius);
+#endif
         }
     }
     else
     {
-        while ( i < nPoints )
+        while( i < nPoints )
         {
-            double  dfRX = padfX[i] - dfXPoint;
-            double  dfRY = padfY[i] - dfYPoint;
+            double dfRX = padfX[i] - dfXPoint;
+            double dfRY = padfY[i] - dfYPoint;
 
-            if ( bRotated )
+            if( bRotated )
             {
-                double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
-                double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
+                const double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
+                const double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
 
                 dfRX = dfRXRotated;
                 dfRY = dfRYRotated;
             }
 
             // Is this point located inside the search ellipse?
-            if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
+            if( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
             {
-                const double    dfR2 = dfRX * dfRX + dfRY * dfRY;
-                if ( dfR2 <= dfNearestR )
+                const double dfR2 = dfRX * dfRX + dfRY * dfRY;
+                if( dfR2 <= dfNearestR )
                 {
                     dfNearestR = dfR2;
                     dfNearestValue = padfZ[i];
@@ -750,7 +746,7 @@ GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
         }
     }
 
-    (*pdfValue) = dfNearestValue;
+    *pdfValue = dfNearestValue;
 
     return CE_None;
 }
@@ -776,7 +772,7 @@ GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
  *      <li> \f$n\f$ is a total number of points in search ellipse.
  *  </ul>
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
@@ -786,83 +782,79 @@ GDALGridNearestNeighbor( const void *poOptions, GUInt32 nPoints,
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
+ * @param hExtraParamsIn unused.
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr
-GDALGridDataMetricMinimum( const void *poOptions, GUInt32 nPoints,
+GDALGridDataMetricMinimum( const void *poOptionsIn, GUInt32 nPoints,
                            const double *padfX, const double *padfY,
                            const double *padfZ,
                            double dfXPoint, double dfYPoint, double *pdfValue,
-                           CPL_UNUSED void* hExtraParamsIn )
+                           CPL_UNUSED void * hExtraParamsIn )
 {
     // TODO: For optimization purposes pre-computed parameters should be moved
     // out of this routine to the calling function.
 
-    // Pre-compute search ellipse parameters
-    double  dfRadius1 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
-    double  dfRadius2 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
-    double  dfR12;
+    const GDALGridDataMetricsOptions *const poOptions =
+        static_cast<const GDALGridDataMetricsOptions *>(poOptionsIn);
 
-    dfRadius1 *= dfRadius1;
-    dfRadius2 *= dfRadius2;
-    dfR12 = dfRadius1 * dfRadius2;
+    // Pre-compute search ellipse parameters.
+    const double dfRadius1 = poOptions->dfRadius1 * poOptions->dfRadius1;
+    const double dfRadius2 = poOptions->dfRadius2 * poOptions->dfRadius2;
+    const double dfR12 = dfRadius1 * dfRadius2;
 
     // Compute coefficients for coordinate system rotation.
-    double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
-    const double dfAngle =
-        TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
-    const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
-    if ( bRotated )
-    {
-        dfCoeff1 = cos(dfAngle);
-        dfCoeff2 = sin(dfAngle);
-    }
+    const double dfAngle = TO_RADIANS * poOptions->dfAngle;
+    const bool bRotated = dfAngle != 0.0;
+    const double dfCoeff1 = bRotated ? cos(dfAngle) : 0.0;
+    const double dfCoeff2 = bRotated ? sin(dfAngle) : 0.0;
 
-    double      dfMinimumValue=0.0;
-    GUInt32     i = 0, n = 0;
+    double dfMinimumValue=0.0;
+    GUInt32 i = 0;
+    GUInt32 n = 0;
 
-    while ( i < nPoints )
+    while( i < nPoints )
     {
-        double  dfRX = padfX[i] - dfXPoint;
-        double  dfRY = padfY[i] - dfYPoint;
+        double dfRX = padfX[i] - dfXPoint;
+        double dfRY = padfY[i] - dfYPoint;
 
-        if ( bRotated )
+        if( bRotated )
         {
-            double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
-            double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
+            const double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
+            const double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
 
             dfRX = dfRXRotated;
             dfRY = dfRYRotated;
         }
 
         // Is this point located inside the search ellipse?
-        if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
+        if( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
         {
-            if ( n )
+            if( n > 0 )
             {
-                if ( dfMinimumValue > padfZ[i] )
+                if( dfMinimumValue > padfZ[i] )
                     dfMinimumValue = padfZ[i];
             }
             else
+            {
                 dfMinimumValue = padfZ[i];
+            }
             n++;
         }
 
         i++;
     }
 
-    if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
-         || n == 0 )
+    if( n < poOptions->nMinPoints || n == 0 )
     {
-        (*pdfValue) =
-            ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
-        (*pdfValue) = dfMinimumValue;
+    {
+        *pdfValue = dfMinimumValue;
+    }
 
     return CE_None;
 }
@@ -888,7 +880,7 @@ GDALGridDataMetricMinimum( const void *poOptions, GUInt32 nPoints,
  *      <li> \f$n\f$ is a total number of points in search ellipse.
  *  </ul>
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
@@ -898,12 +890,13 @@ GDALGridDataMetricMinimum( const void *poOptions, GUInt32 nPoints,
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
+ * @param hExtraParamsIn extra parameters (unused)
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr
-GDALGridDataMetricMaximum( const void *poOptions, GUInt32 nPoints,
+GDALGridDataMetricMaximum( const void *poOptionsIn, GUInt32 nPoints,
                            const double *padfX, const double *padfY,
                            const double *padfZ,
                            double dfXPoint, double dfYPoint, double *pdfValue,
@@ -912,69 +905,65 @@ GDALGridDataMetricMaximum( const void *poOptions, GUInt32 nPoints,
     // TODO: For optimization purposes pre-computed parameters should be moved
     // out of this routine to the calling function.
 
-    // Pre-compute search ellipse parameters
-    double  dfRadius1 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
-    double  dfRadius2 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
-    double  dfR12;
+    const GDALGridDataMetricsOptions *const poOptions =
+        static_cast<const GDALGridDataMetricsOptions *>(poOptionsIn);
 
-    dfRadius1 *= dfRadius1;
-    dfRadius2 *= dfRadius2;
-    dfR12 = dfRadius1 * dfRadius2;
+    // Pre-compute search ellipse parameters.
+    const double dfRadius1 = poOptions->dfRadius1 * poOptions->dfRadius1;
+    const double dfRadius2 = poOptions->dfRadius2 * poOptions->dfRadius2;
+    const double dfR12 = dfRadius1 * dfRadius2;
 
     // Compute coefficients for coordinate system rotation.
-    double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
-    const double    dfAngle =
-        TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
-    const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
-    if ( bRotated )
-    {
-        dfCoeff1 = cos(dfAngle);
-        dfCoeff2 = sin(dfAngle);
-    }
+    const double dfAngle = TO_RADIANS * poOptions->dfAngle;
+    const bool bRotated = dfAngle != 0.0;
+    const double dfCoeff1 = bRotated ? cos(dfAngle) : 0.0;
+    const double dfCoeff2 = bRotated ? sin(dfAngle) : 0.0;
 
-    double      dfMaximumValue=0.0;
-    GUInt32     i = 0, n = 0;
+    double dfMaximumValue=0.0;
+    GUInt32 i = 0;
+    GUInt32 n = 0;
 
-    while ( i < nPoints )
+    while( i < nPoints )
     {
-        double  dfRX = padfX[i] - dfXPoint;
-        double  dfRY = padfY[i] - dfYPoint;
+        double dfRX = padfX[i] - dfXPoint;
+        double dfRY = padfY[i] - dfYPoint;
 
-        if ( bRotated )
+        if( bRotated )
         {
-            double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
-            double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
+            const double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
+            const double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
 
             dfRX = dfRXRotated;
             dfRY = dfRYRotated;
         }
 
         // Is this point located inside the search ellipse?
-        if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
+        if( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
         {
-            if ( n )
+            if( n )
             {
-                if ( dfMaximumValue < padfZ[i] )
+                if( dfMaximumValue < padfZ[i] )
                     dfMaximumValue = padfZ[i];
             }
             else
+            {
                 dfMaximumValue = padfZ[i];
+            }
             n++;
         }
 
         i++;
     }
 
-    if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
+    if( n < poOptions->nMinPoints
          || n == 0 )
     {
-        (*pdfValue) =
-            ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
-        (*pdfValue) = dfMaximumValue;
+    {
+        *pdfValue = dfMaximumValue;
+    }
 
     return CE_None;
 }
@@ -1001,7 +990,7 @@ GDALGridDataMetricMaximum( const void *poOptions, GUInt32 nPoints,
  *      <li> \f$n\f$ is a total number of points in search ellipse.
  *  </ul>
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
@@ -1011,85 +1000,82 @@ GDALGridDataMetricMaximum( const void *poOptions, GUInt32 nPoints,
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
+ * @param hExtraParamsIn extra parameters (unused)
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr
-GDALGridDataMetricRange( const void *poOptions, GUInt32 nPoints,
+GDALGridDataMetricRange( const void *poOptionsIn, GUInt32 nPoints,
                          const double *padfX, const double *padfY,
                          const double *padfZ,
                          double dfXPoint, double dfYPoint, double *pdfValue,
-                         CPL_UNUSED void* hExtraParamsIn )
+                         CPL_UNUSED void * hExtraParamsIn )
 {
     // TODO: For optimization purposes pre-computed parameters should be moved
     // out of this routine to the calling function.
 
-    // Pre-compute search ellipse parameters
-    double  dfRadius1 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
-    double  dfRadius2 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
-    double  dfR12;
-
-    dfRadius1 *= dfRadius1;
-    dfRadius2 *= dfRadius2;
-    dfR12 = dfRadius1 * dfRadius2;
+    const GDALGridDataMetricsOptions *const poOptions =
+        static_cast<const GDALGridDataMetricsOptions *>(poOptionsIn);
+    // Pre-compute search ellipse parameters.
+    const double dfRadius1 = poOptions->dfRadius1 * poOptions->dfRadius1;
+    const double dfRadius2 = poOptions->dfRadius2 * poOptions->dfRadius2;
+    const double dfR12 = dfRadius1 * dfRadius2;
 
     // Compute coefficients for coordinate system rotation.
-    double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
-    const double    dfAngle =
-        TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
-    const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
-    if ( bRotated )
-    {
-        dfCoeff1 = cos(dfAngle);
-        dfCoeff2 = sin(dfAngle);
-    }
+    const double dfAngle = TO_RADIANS * poOptions->dfAngle;
+    const bool bRotated = dfAngle != 0.0;
+    const double dfCoeff1 = bRotated ? cos(dfAngle) : 0.0;
+    const double dfCoeff2 = bRotated ? sin(dfAngle) : 0.0;
 
-    double      dfMaximumValue=0.0, dfMinimumValue=0.0;
-    GUInt32     i = 0, n = 0;
+    double dfMaximumValue = 0.0;
+    double dfMinimumValue = 0.0;
+    GUInt32 i = 0;
+    GUInt32 n = 0;
 
-    while ( i < nPoints )
+    while( i < nPoints )
     {
-        double  dfRX = padfX[i] - dfXPoint;
-        double  dfRY = padfY[i] - dfYPoint;
+        double dfRX = padfX[i] - dfXPoint;
+        double dfRY = padfY[i] - dfYPoint;
 
-        if ( bRotated )
+        if( bRotated )
         {
-            double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
-            double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
+            const double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
+            const double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
 
             dfRX = dfRXRotated;
             dfRY = dfRYRotated;
         }
 
         // Is this point located inside the search ellipse?
-        if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
+        if( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
         {
-            if ( n )
+            if( n > 0 )
             {
-                if ( dfMinimumValue > padfZ[i] )
+                if( dfMinimumValue > padfZ[i] )
                     dfMinimumValue = padfZ[i];
-                if ( dfMaximumValue < padfZ[i] )
+                if( dfMaximumValue < padfZ[i] )
                     dfMaximumValue = padfZ[i];
             }
             else
-                dfMinimumValue = dfMaximumValue = padfZ[i];
+            {
+                dfMinimumValue = padfZ[i];
+                dfMaximumValue = padfZ[i];
+            }
             n++;
         }
 
         i++;
     }
 
-    if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
-         || n == 0 )
+    if( n < poOptions->nMinPoints || n == 0 )
     {
-        (*pdfValue) =
-            ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
-        (*pdfValue) = dfMaximumValue - dfMinimumValue;
+    {
+        *pdfValue = dfMaximumValue - dfMinimumValue;
+    }
 
     return CE_None;
 }
@@ -1113,7 +1099,7 @@ GDALGridDataMetricRange( const void *poOptions, GUInt32 nPoints,
  *      <li> \f$n\f$ is a total number of points in search ellipse.
  *  </ul>
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
@@ -1123,72 +1109,69 @@ GDALGridDataMetricRange( const void *poOptions, GUInt32 nPoints,
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
+ * @param hExtraParamsIn extra parameters (unused)
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr
-GDALGridDataMetricCount( const void *poOptions, GUInt32 nPoints,
+GDALGridDataMetricCount( const void *poOptionsIn, GUInt32 nPoints,
                          const double *padfX, const double *padfY,
-                         CPL_UNUSED const double *padfZ,
+                         CPL_UNUSED const double * padfZ,
                          double dfXPoint, double dfYPoint, double *pdfValue,
-                         CPL_UNUSED void* hExtraParamsIn )
+                         CPL_UNUSED void * hExtraParamsIn )
 {
     // TODO: For optimization purposes pre-computed parameters should be moved
     // out of this routine to the calling function.
 
-    // Pre-compute search ellipse parameters
-    double  dfRadius1 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
-    double  dfRadius2 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
-    double  dfR12;
+    const GDALGridDataMetricsOptions *const poOptions =
+        static_cast<const GDALGridDataMetricsOptions *>(poOptionsIn);
 
-    dfRadius1 *= dfRadius1;
-    dfRadius2 *= dfRadius2;
-    dfR12 = dfRadius1 * dfRadius2;
+    // Pre-compute search ellipse parameters.
+    const double dfRadius1 = poOptions->dfRadius1 * poOptions->dfRadius1;
+    const double dfRadius2 = poOptions->dfRadius2 * poOptions->dfRadius2;
+    const double dfR12 = dfRadius1 * dfRadius2;
 
     // Compute coefficients for coordinate system rotation.
-    double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
-    const double    dfAngle =
-        TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
-    const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
-    if ( bRotated )
-    {
-        dfCoeff1 = cos(dfAngle);
-        dfCoeff2 = sin(dfAngle);
-    }
+    const double    dfAngle = TO_RADIANS * poOptions->dfAngle;
+    const bool bRotated = dfAngle != 0.0;
+    const double dfCoeff1 = bRotated ? cos(dfAngle) : 0.0;
+    const double dfCoeff2 = bRotated ? sin(dfAngle) : 0.0;
 
-    GUInt32     i = 0, n = 0;
+    GUInt32 i = 0;
+    GUInt32 n = 0;
 
-    while ( i < nPoints )
+    while( i < nPoints )
     {
-        double  dfRX = padfX[i] - dfXPoint;
-        double  dfRY = padfY[i] - dfYPoint;
+        double dfRX = padfX[i] - dfXPoint;
+        double dfRY = padfY[i] - dfYPoint;
 
-        if ( bRotated )
+        if( bRotated )
         {
-            double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
-            double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
+            const double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
+            const double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
 
             dfRX = dfRXRotated;
             dfRY = dfRYRotated;
         }
 
         // Is this point located inside the search ellipse?
-        if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
+        if( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
+        {
             n++;
+        }
 
         i++;
     }
 
-    if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints )
+    if( n < poOptions->nMinPoints )
     {
-        (*pdfValue) =
-            ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
-        (*pdfValue) = (double)n;
+    {
+        *pdfValue = static_cast<double>(n);
+    }
 
     return CE_None;
 }
@@ -1216,72 +1199,66 @@ GDALGridDataMetricCount( const void *poOptions, GUInt32 nPoints,
  *      <li> \f$n\f$ is a total number of points in search ellipse.
  *  </ul>
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
  * @param padfY Input array of Y coordinates.
- * @param padfZ Input array of Z values.
+ * @param padfZ Input array of Z values (unused)
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
+ * @param hExtraParamsIn extra parameters (unused)
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr
-GDALGridDataMetricAverageDistance( const void *poOptions, GUInt32 nPoints,
+GDALGridDataMetricAverageDistance( const void *poOptionsIn, GUInt32 nPoints,
                                    const double *padfX, const double *padfY,
-                                   CPL_UNUSED const double *padfZ,
+                                   CPL_UNUSED const double * padfZ,
                                    double dfXPoint, double dfYPoint,
                                    double *pdfValue,
-                                   CPL_UNUSED void* hExtraParamsIn )
+                                   CPL_UNUSED void * hExtraParamsIn )
 {
     // TODO: For optimization purposes pre-computed parameters should be moved
     // out of this routine to the calling function.
 
-    // Pre-compute search ellipse parameters
-    double  dfRadius1 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
-    double  dfRadius2 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
-    double  dfR12;
+    const GDALGridDataMetricsOptions *const poOptions =
+        static_cast<const GDALGridDataMetricsOptions *>(poOptionsIn);
 
-    dfRadius1 *= dfRadius1;
-    dfRadius2 *= dfRadius2;
-    dfR12 = dfRadius1 * dfRadius2;
+    // Pre-compute search ellipse parameters.
+    const double dfRadius1 = poOptions->dfRadius1 * poOptions->dfRadius1;
+    const double dfRadius2 = poOptions->dfRadius2 * poOptions->dfRadius2;
+    const double dfR12 = dfRadius1 * dfRadius2;
 
     // Compute coefficients for coordinate system rotation.
-    double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
-    const double    dfAngle =
-        TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
-    const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
-    if ( bRotated )
-    {
-        dfCoeff1 = cos(dfAngle);
-        dfCoeff2 = sin(dfAngle);
-    }
+    const double dfAngle = TO_RADIANS * poOptions->dfAngle;
+    const bool bRotated = dfAngle != 0.0;
+    const double dfCoeff1 = bRotated ? cos(dfAngle) : 0.0;
+    const double dfCoeff2 = bRotated ? sin(dfAngle) : 0.0;
 
-    double      dfAccumulator = 0.0;
-    GUInt32     i = 0, n = 0;
+    double dfAccumulator = 0.0;
+    GUInt32 i = 0;
+    GUInt32 n = 0;
 
-    while ( i < nPoints )
+    while( i < nPoints )
     {
-        double  dfRX = padfX[i] - dfXPoint;
-        double  dfRY = padfY[i] - dfYPoint;
+        double dfRX = padfX[i] - dfXPoint;
+        double dfRY = padfY[i] - dfYPoint;
 
-        if ( bRotated )
+        if( bRotated )
         {
-            double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
-            double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
+            const double dfRXRotated = dfRX * dfCoeff1 + dfRY * dfCoeff2;
+            const double dfRYRotated = dfRY * dfCoeff1 - dfRX * dfCoeff2;
 
             dfRX = dfRXRotated;
             dfRY = dfRYRotated;
         }
 
         // Is this point located inside the search ellipse?
-        if ( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
+        if( dfRadius2 * dfRX * dfRX + dfRadius1 * dfRY * dfRY <= dfR12 )
         {
             dfAccumulator += sqrt( dfRX * dfRX + dfRY * dfRY );
             n++;
@@ -1290,14 +1267,14 @@ GDALGridDataMetricAverageDistance( const void *poOptions, GUInt32 nPoints,
         i++;
     }
 
-    if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
-         || n == 0 )
+    if( n < poOptions->nMinPoints || n == 0 )
     {
-        (*pdfValue) =
-            ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
-        (*pdfValue) = dfAccumulator / n;
+    {
+        *pdfValue = dfAccumulator / n;
+    }
 
     return CE_None;
 }
@@ -1327,93 +1304,87 @@ GDALGridDataMetricAverageDistance( const void *poOptions, GUInt32 nPoints,
  *      <li> \f$n\f$ is a total number of points in search ellipse.
  *  </ul>
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridDataMetricsOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
  * @param padfY Input array of Y coordinates.
- * @param padfZ Input array of Z values.
+ * @param padfZ Input array of Z values (unused)
  * @param dfXPoint X coordinate of the point to compute.
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
+ * @param hExtraParamsIn extra parameters (unused)
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
 CPLErr
-GDALGridDataMetricAverageDistancePts( const void *poOptions, GUInt32 nPoints,
+GDALGridDataMetricAverageDistancePts( const void *poOptionsIn, GUInt32 nPoints,
                                       const double *padfX, const double *padfY,
-                                      CPL_UNUSED const double *padfZ,
+                                      CPL_UNUSED const double * padfZ,
                                       double dfXPoint, double dfYPoint,
                                       double *pdfValue,
-                                      CPL_UNUSED void* hExtraParamsIn )
+                                      CPL_UNUSED void * hExtraParamsIn )
 {
     // TODO: For optimization purposes pre-computed parameters should be moved
     // out of this routine to the calling function.
 
-    // Pre-compute search ellipse parameters
-    double  dfRadius1 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius1;
-    double  dfRadius2 =
-        ((GDALGridDataMetricsOptions *)poOptions)->dfRadius2;
-    double  dfR12;
-
-    dfRadius1 *= dfRadius1;
-    dfRadius2 *= dfRadius2;
-    dfR12 = dfRadius1 * dfRadius2;
+    const GDALGridDataMetricsOptions *const poOptions =
+        static_cast<const GDALGridDataMetricsOptions *>(poOptionsIn);
+    // Pre-compute search ellipse parameters.
+    const double dfRadius1 = poOptions->dfRadius1 * poOptions->dfRadius1;
+    const double dfRadius2 = poOptions->dfRadius2 * poOptions->dfRadius2;
+    const double dfR12 = dfRadius1 * dfRadius2;
 
     // Compute coefficients for coordinate system rotation.
-    double      dfCoeff1 = 0.0, dfCoeff2 = 0.0;
-    const double    dfAngle =
-        TO_RADIANS * ((GDALGridDataMetricsOptions *)poOptions)->dfAngle;
-    const bool  bRotated = ( dfAngle == 0.0 ) ? false : true;
-    if ( bRotated )
-    {
-        dfCoeff1 = cos(dfAngle);
-        dfCoeff2 = sin(dfAngle);
-    }
+    const double dfAngle = TO_RADIANS * poOptions->dfAngle;
+    const bool bRotated = dfAngle != 0.0;
+    const double dfCoeff1 = bRotated ? cos(dfAngle) : 0.0;
+    const double dfCoeff2 = bRotated ? sin(dfAngle) : 0.0;
 
-    double      dfAccumulator = 0.0;
-    GUInt32     i = 0, n = 0;
+    double dfAccumulator = 0.0;
+    GUInt32 i = 0;
+    GUInt32 n = 0;
 
-    // Search for the first point within the search ellipse
-    while ( i < nPoints - 1 )
+    // Search for the first point within the search ellipse.
+    while( i < nPoints - 1 )
     {
-        double  dfRX1 = padfX[i] - dfXPoint;
-        double  dfRY1 = padfY[i] - dfYPoint;
+        double dfRX1 = padfX[i] - dfXPoint;
+        double dfRY1 = padfY[i] - dfYPoint;
 
-        if ( bRotated )
+        if( bRotated )
         {
-            double dfRXRotated = dfRX1 * dfCoeff1 + dfRY1 * dfCoeff2;
-            double dfRYRotated = dfRY1 * dfCoeff1 - dfRX1 * dfCoeff2;
+            const double dfRXRotated = dfRX1 * dfCoeff1 + dfRY1 * dfCoeff2;
+            const double dfRYRotated = dfRY1 * dfCoeff1 - dfRX1 * dfCoeff2;
 
             dfRX1 = dfRXRotated;
             dfRY1 = dfRYRotated;
         }
 
         // Is this point located inside the search ellipse?
-        if ( dfRadius2 * dfRX1 * dfRX1 + dfRadius1 * dfRY1 * dfRY1 <= dfR12 )
+        if( dfRadius2 * dfRX1 * dfRX1 + dfRadius1 * dfRY1 * dfRY1 <= dfR12 )
         {
-            GUInt32 j;
-
             // Search all the remaining points within the ellipse and compute
-            // distances between them and the first point
-            for ( j = i + 1; j < nPoints; j++ )
+            // distances between them and the first point.
+            for( GUInt32 j = i + 1; j < nPoints; j++ )
             {
-                double  dfRX2 = padfX[j] - dfXPoint;
-                double  dfRY2 = padfY[j] - dfYPoint;
+                double dfRX2 = padfX[j] - dfXPoint;
+                double dfRY2 = padfY[j] - dfYPoint;
 
-                if ( bRotated )
+                if( bRotated )
                 {
-                    double dfRXRotated = dfRX2 * dfCoeff1 + dfRY2 * dfCoeff2;
-                    double dfRYRotated = dfRY2 * dfCoeff1 - dfRX2 * dfCoeff2;
+                    const double dfRXRotated =
+                        dfRX2 * dfCoeff1 + dfRY2 * dfCoeff2;
+                    const double dfRYRotated =
+                        dfRY2 * dfCoeff1 - dfRX2 * dfCoeff2;
 
                     dfRX2 = dfRXRotated;
                     dfRY2 = dfRYRotated;
                 }
 
-                if ( dfRadius2 * dfRX2 * dfRX2 + dfRadius1 * dfRY2 * dfRY2 <= dfR12 )
+                if( dfRadius2 * dfRX2 * dfRX2 + dfRadius1 * dfRY2 * dfRY2
+                    <= dfR12 )
                 {
                     const double dfRX = padfX[j] - padfX[i];
                     const double dfRY = padfY[j] - padfY[i];
@@ -1427,14 +1398,14 @@ GDALGridDataMetricAverageDistancePts( const void *poOptions, GUInt32 nPoints,
         i++;
     }
 
-    if ( n < ((GDALGridDataMetricsOptions *)poOptions)->nMinPoints
-         || n == 0 )
+    if( n < poOptions->nMinPoints || n == 0 )
     {
-        (*pdfValue) =
-            ((GDALGridDataMetricsOptions *)poOptions)->dfNoDataValue;
+        *pdfValue = poOptions->dfNoDataValue;
     }
     else
-        (*pdfValue) = dfAccumulator / n;
+    {
+        *pdfValue = dfAccumulator / n;
+    }
 
     return CE_None;
 }
@@ -1452,7 +1423,7 @@ GDALGridDataMetricAverageDistancePts( const void *poOptions, GUInt32 nPoints,
  * If the point is not in any triangle, depending on the radius, the
  * algorithm will use the value of the nearest point or the nodata value.
  *
- * @param poOptions Algorithm parameters. This should point to
+ * @param poOptionsIn Algorithm parameters. This should point to
  * GDALGridLinearOptions object.
  * @param nPoints Number of elements in input arrays.
  * @param padfX Input array of X coordinates.
@@ -1462,6 +1433,7 @@ GDALGridDataMetricAverageDistancePts( const void *poOptions, GUInt32 nPoints,
  * @param dfYPoint Y coordinate of the point to compute.
  * @param pdfValue Pointer to variable where the computed grid node value
  * will be returned.
+ * @param hExtraParams extra parameters
  *
  * @return CE_None on success or CE_Failure if something goes wrong.
  *
@@ -1469,74 +1441,67 @@ GDALGridDataMetricAverageDistancePts( const void *poOptions, GUInt32 nPoints,
  */
 
 CPLErr
-GDALGridLinear( const void *poOptions, CPL_UNUSED GUInt32 nPoints,
+GDALGridLinear( const void *poOptionsIn, GUInt32 nPoints,
                 const double *padfX, const double *padfY,
                 const double *padfZ,
                 double dfXPoint, double dfYPoint, double *pdfValue,
-                void* hExtraParams )
+                void *hExtraParams )
 {
-    GDALGridExtraParameters* psExtraParams = (GDALGridExtraParameters*) hExtraParams;
+    GDALGridExtraParameters* psExtraParams =
+        static_cast<GDALGridExtraParameters *>(hExtraParams);
     GDALTriangulation* psTriangulation = psExtraParams->psTriangulation;
 
     int nOutputFacetIdx = -1;
-    int bRet = GDALTriangulationFindFacetDirected( psTriangulation,
-                                                   psExtraParams->nInitialFacetIdx,
-                                                   dfXPoint, dfYPoint,
-                                                   &nOutputFacetIdx );
+    const bool bRet = CPL_TO_BOOL( GDALTriangulationFindFacetDirected(
+        psTriangulation, psExtraParams->nInitialFacetIdx,
+        dfXPoint, dfYPoint, &nOutputFacetIdx ) );
+
     CPLAssert(nOutputFacetIdx >= 0);
-    // Reuse output facet idx as next initial index since we proceed line by line
+    // Reuse output facet idx as next initial index since we proceed line by
+    // line.
     psExtraParams->nInitialFacetIdx = nOutputFacetIdx;
 
     if( bRet )
     {
-        double lambda1, lambda2, lambda3;
+        double lambda1 = 0.0;
+        double lambda2 = 0.0;
+        double lambda3 = 0.0;
         GDALTriangulationComputeBarycentricCoordinates(
                                                 psTriangulation,
                                                 nOutputFacetIdx,
                                                 dfXPoint, dfYPoint,
                                                 &lambda1, &lambda2, &lambda3);
-        int i1 = psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[0];
-        int i2 = psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[1];
-        int i3 = psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[2];
-        *pdfValue = lambda1 * padfZ[i1] + lambda2 * padfZ[i2] + lambda3 * padfZ[i3];
+        const int i1 =
+            psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[0];
+        const int i2 =
+            psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[1];
+        const int i3 =
+            psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[2];
+        *pdfValue =
+            lambda1 * padfZ[i1] +
+            lambda2 * padfZ[i2] +
+            lambda3 * padfZ[i3];
     }
     else
     {
-        double dfRadius = ((GDALGridLinearOptions*)poOptions)->dfRadius;
-        if( dfRadius == 0 )
-            *pdfValue = ((GDALGridLinearOptions*)poOptions)->dfNoDataValue;
+        const GDALGridLinearOptions *const poOptions =
+            static_cast<const GDALGridLinearOptions *>(poOptionsIn);
+        const double dfRadius = poOptions->dfRadius;
+        if( dfRadius == 0.0 )
+        {
+            *pdfValue = poOptions->dfNoDataValue;
+        }
         else
         {
             GDALGridNearestNeighborOptions sNeighbourOptions;
-            sNeighbourOptions.dfRadius1 = dfRadius < 0 ? 0 : dfRadius;
-            sNeighbourOptions.dfRadius2 = dfRadius < 0 ? 0 : dfRadius;
-            sNeighbourOptions.dfAngle = 0;
-            sNeighbourOptions.dfNoDataValue = ((GDALGridLinearOptions*)poOptions)->dfNoDataValue;
-            return GDALGridNearestNeighbor(&sNeighbourOptions, nPoints,
-                                        padfX, padfY, padfZ,
-                                        dfXPoint, dfYPoint, pdfValue,
-                                        hExtraParams);
-#if 0
-            // Disabled since the nearest point is not necessarily the nearest
-            // vertex of the "nearest" triangle
-            int iBestIdx;
-            double dfBestDist;
-            for(int i=0;i<3;i++)
-            {
-                int idx = psTriangulation->pasFacets[nOutputFacetIdx].anVertexIdx[i];
-                double dfDist = (padfX[idx] - dfXPoint) * (padfX[idx] - dfXPoint) +
-                                (padfY[idx] - dfYPoint) * (padfY[idx] - dfYPoint);
-                if( i == 0 || dfDist < dfBestDist )
-                {
-                    iBestIdx = idx;
-                    dfBestDist = dfDist;
-                }
-            }
-            if( dfRadius < 0 || dfBestDist <= dfRadius * dfRadius )
-                *pdfValue = padfZ[iBestIdx];
-            else
-                *pdfValue = ((GDALGridLinearOptions*)poOptions)->dfNoDataValue;
-#endif
+            sNeighbourOptions.dfRadius1 = dfRadius < 0.0 ? 0.0 : dfRadius;
+            sNeighbourOptions.dfRadius2 = dfRadius < 0.0 ? 0.0 : dfRadius;
+            sNeighbourOptions.dfAngle = 0.0;
+            sNeighbourOptions.dfNoDataValue = poOptions->dfNoDataValue;
+            return GDALGridNearestNeighbor( &sNeighbourOptions, nPoints,
+                                            padfX, padfY, padfZ,
+                                            dfXPoint, dfYPoint, pdfValue,
+                                            hExtraParams );
         }
     }
 
@@ -1584,13 +1549,13 @@ struct _GDALGridJob
 /*                   GDALGridProgressMultiThread()                      */
 /************************************************************************/
 
-/* Return TRUE if the computation must be interrupted */
-static int GDALGridProgressMultiThread(GDALGridJob* psJob)
+// Return TRUE if the computation must be interrupted.
+static int GDALGridProgressMultiThread( GDALGridJob* psJob )
 {
     CPLAcquireMutex(psJob->hCondMutex, 1.0);
-    (*(psJob->pnCounter)) ++;
+    ++(*psJob->pnCounter);
     CPLCondSignal(psJob->hCond);
-    int bStop = *(psJob->pbStop);
+    const int bStop = *psJob->pbStop;
     CPLReleaseMutex(psJob->hCondMutex);
 
     return bStop;
@@ -1600,15 +1565,15 @@ static int GDALGridProgressMultiThread(GDALGridJob* psJob)
 /*                      GDALGridProgressMonoThread()                    */
 /************************************************************************/
 
-/* Return TRUE if the computation must be interrupted */
-static int GDALGridProgressMonoThread(GDALGridJob* psJob)
+// Return TRUE if the computation must be interrupted.
+static int GDALGridProgressMonoThread( GDALGridJob* psJob )
 {
-    int nCounter = ++(*(psJob->pnCounter));
-    if( !psJob->pfnRealProgress( (nCounter / (double) psJob->nYSize),
+    const int nCounter = ++(*psJob->pnCounter);
+    if( !psJob->pfnRealProgress( nCounter / static_cast<double>(psJob->nYSize),
                                  "", psJob->pRealProgressArg ) )
     {
         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-        *(psJob->pbStop) = TRUE;
+        *psJob->pbStop = TRUE;
         return TRUE;
     }
     return FALSE;
@@ -1618,69 +1583,70 @@ static int GDALGridProgressMonoThread(GDALGridJob* psJob)
 /*                         GDALGridJobProcess()                         */
 /************************************************************************/
 
-static void GDALGridJobProcess(void* user_data)
+static void GDALGridJobProcess( void* user_data )
 {
-    GDALGridJob* psJob = (GDALGridJob*)user_data;
-    GUInt32 nXPoint, nYPoint;
+    GDALGridJob* const psJob = static_cast<GDALGridJob *>(user_data);
+    int (*pfnProgress)(GDALGridJob* psJob) = psJob->pfnProgress;
+    const GUInt32 nXSize = psJob->nXSize;
+
+    /* -------------------------------------------------------------------- */
+    /*  Allocate a buffer of scanline size, fill it with gridded values     */
+    /*  and use GDALCopyWords() to copy values into output data array with  */
+    /*  appropriate data type conversion.                                   */
+    /* -------------------------------------------------------------------- */
+    double *padfValues =
+        static_cast<double *>(VSI_MALLOC2_VERBOSE( sizeof(double), nXSize ));
+    if( padfValues == NULL )
+    {
+        *(psJob->pbStop) = TRUE;
+        if( pfnProgress != NULL )
+            pfnProgress(psJob);  // To notify the main thread.
+        return;
+    }
 
     const GUInt32 nYStart = psJob->nYStart;
     const GUInt32 nYStep = psJob->nYStep;
     GByte *pabyData = psJob->pabyData;
 
-    const GUInt32 nXSize = psJob->nXSize;
     const GUInt32 nYSize = psJob->nYSize;
     const double dfXMin = psJob->dfXMin;
     const double dfYMin = psJob->dfYMin;
     const double dfDeltaX = psJob->dfDeltaX;
     const double dfDeltaY = psJob->dfDeltaY;
-    GUInt32 nPoints = psJob->nPoints;
+    const GUInt32 nPoints = psJob->nPoints;
     const double* padfX = psJob->padfX;
     const double* padfY = psJob->padfY;
     const double* padfZ = psJob->padfZ;
     const void *poOptions = psJob->poOptions;
-    GDALGridFunction  pfnGDALGridMethod = psJob->pfnGDALGridMethod;
+    GDALGridFunction pfnGDALGridMethod = psJob->pfnGDALGridMethod;
     // Have a local copy of sExtraParameters since we want to modify
-    // nInitialFacetIdx
-    GDALGridExtraParameters sExtraParameters = *(psJob->psExtraParameters);
-    GDALDataType eType = psJob->eType;
-    int (*pfnProgress)(GDALGridJob* psJob) = psJob->pfnProgress;
-
-    int         nDataTypeSize = GDALGetDataTypeSizeBytes(eType);
-    int         nLineSpace = nXSize * nDataTypeSize;
+    // nInitialFacetIdx.
+    GDALGridExtraParameters sExtraParameters = *psJob->psExtraParameters;
+    const GDALDataType eType = psJob->eType;
 
-    /* -------------------------------------------------------------------- */
-    /*  Allocate a buffer of scanline size, fill it with gridded values     */
-    /*  and use GDALCopyWords() to copy values into output data array with  */
-    /*  appropriate data type conversion.                                   */
-    /* -------------------------------------------------------------------- */
-    double      *padfValues = (double *)VSI_MALLOC2_VERBOSE( sizeof(double), nXSize );
-    if( padfValues == NULL )
-    {
-        *(psJob->pbStop) = TRUE;
-        if( pfnProgress != NULL )
-            pfnProgress(psJob); /* to notify the main thread */
-        return;
-    }
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eType);
+    const int nLineSpace = nXSize * nDataTypeSize;
 
-    for ( nYPoint = nYStart; nYPoint < nYSize; nYPoint += nYStep )
+    for( GUInt32 nYPoint = nYStart; nYPoint < nYSize; nYPoint += nYStep )
     {
-        const double    dfYPoint = dfYMin + ( nYPoint + 0.5 ) * dfDeltaY;
+        const double dfYPoint = dfYMin + ( nYPoint + 0.5 ) * dfDeltaY;
 
-        for ( nXPoint = 0; nXPoint < nXSize; nXPoint++ )
+        for( GUInt32 nXPoint = 0; nXPoint < nXSize; nXPoint++ )
         {
-            const double    dfXPoint = dfXMin + ( nXPoint + 0.5 ) * dfDeltaX;
+            const double dfXPoint = dfXMin + ( nXPoint + 0.5 ) * dfDeltaX;
 
-            if ( (*pfnGDALGridMethod)( poOptions, nPoints, padfX, padfY, padfZ,
-                                       dfXPoint, dfYPoint,
-                                       padfValues + nXPoint, &sExtraParameters ) != CE_None )
+            if( (*pfnGDALGridMethod)(poOptions, nPoints, padfX, padfY, padfZ,
+                                     dfXPoint, dfYPoint,
+                                     padfValues + nXPoint,
+                                     &sExtraParameters) != CE_None )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Gridding failed at X position %lu, Y position %lu",
-                          (long unsigned int)nXPoint,
-                          (long unsigned int)nYPoint );
-                *(psJob->pbStop) = TRUE;
+                          static_cast<long unsigned int>(nXPoint),
+                          static_cast<long unsigned int>(nYPoint) );
+                *psJob->pbStop = TRUE;
                 if( pfnProgress != NULL )
-                    pfnProgress(psJob); /* to notify the main thread */
+                    pfnProgress(psJob);  // To notify the main thread.
                 break;
             }
         }
@@ -1689,7 +1655,7 @@ static void GDALGridJobProcess(void* user_data)
                        pabyData + nYPoint * nLineSpace, eType, nDataTypeSize,
                        nXSize );
 
-        if( *(psJob->pbStop) || (pfnProgress != NULL && pfnProgress(psJob)) )
+        if( *psJob->pbStop || (pfnProgress != NULL && pfnProgress(psJob)) )
             break;
     }
 
@@ -1714,16 +1680,12 @@ struct GDALGridContext
     double*             padfX;
     double*             padfY;
     double*             padfZ;
-    int                 bFreePadfXYZArrays;
-
-    void               *pabyX;
-    void               *pabyY;
-    void               *pabyZ;
+    bool                bFreePadfXYZArrays;
 
     CPLWorkerThreadPool *poWorkerThreadPool;
 };
 
-static void GDALGridContextCreateQuadTree(GDALGridContext* psContext);
+static void GDALGridContextCreateQuadTree( GDALGridContext* psContext );
 
 /**
  * Creates a context to do regular gridding from the scattered data.
@@ -1755,12 +1717,13 @@ static void GDALGridContextCreateQuadTree(GDALGridContext* psContext);
  * @param padfX Input array of X coordinates.
  * @param padfY Input array of Y coordinates.
  * @param padfZ Input array of Z values.
- * @param bCallerWillKeepPointArraysAlive Whether the provided padfX, padfY, padfZ
- *        arrays will still be "alive" during the calls to GDALGridContextProcess().
- *        Setting to TRUE prevent them from being duplicated in the context.
- *        If unsure, set to FALSE.
+ * @param bCallerWillKeepPointArraysAlive Whether the provided padfX, padfY,
+ *        padfZ arrays will still be "alive" during the calls to
+ *        GDALGridContextProcess().  Setting to TRUE prevent them from being
+ *        duplicated in the context.  If unsure, set to FALSE.
  *
- * @return the context (to be freed with GDALGridContextFree()) or NULL in case or error
+ * @return the context (to be freed with GDALGridContextFree()) or NULL in case
+ *         or error.
  *
  * @since GDAL 2.1
  */
@@ -1768,210 +1731,239 @@ static void GDALGridContextCreateQuadTree(GDALGridContext* psContext);
 GDALGridContext*
 GDALGridContextCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
                        GUInt32 nPoints,
-                       const double *padfX, const double *padfY, const double *padfZ,
+                       const double *padfX, const double *padfY,
+                       const double *padfZ,
                        int bCallerWillKeepPointArraysAlive )
 {
-    GDALGridFunction    pfnGDALGridMethod = NULL;
     CPLAssert( poOptions );
     CPLAssert( padfX );
     CPLAssert( padfY );
     CPLAssert( padfZ );
-    int bCreateQuadTree = FALSE;
+    bool bCreateQuadTree = false;
 
-    /* Potentially unaligned pointers */
-    void* pabyX = NULL;
-    void* pabyY = NULL;
-    void* pabyZ = NULL;
-
-    /* Starting address aligned on 16-byte boundary */
+    // Starting address aligned on 32-byte boundary for AVX.
     float* pafXAligned = NULL;
     float* pafYAligned = NULL;
     float* pafZAligned = NULL;
 
     void *poOptionsNew = NULL;
 
-    switch ( eAlgorithm )
+    GDALGridFunction pfnGDALGridMethod = NULL;
+
+    switch( eAlgorithm )
     {
         case GGA_InverseDistanceToAPower:
-            poOptionsNew = CPLMalloc(sizeof(GDALGridInverseDistanceToAPowerOptions));
-            memcpy(poOptionsNew, poOptions, sizeof(GDALGridInverseDistanceToAPowerOptions));
-
-            if ( ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->
-                 dfRadius1 == 0.0 &&
-                 ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->
-                 dfRadius2 == 0.0 )
+        {
+            poOptionsNew =
+                CPLMalloc(sizeof(GDALGridInverseDistanceToAPowerOptions));
+            memcpy(poOptionsNew, poOptions,
+                   sizeof(GDALGridInverseDistanceToAPowerOptions));
+
+            const GDALGridInverseDistanceToAPowerOptions * const poPower =
+                static_cast<const GDALGridInverseDistanceToAPowerOptions *>(
+                    poOptions);
+            if( poPower->dfRadius1 == 0.0 && poPower->dfRadius2 == 0.0 )
             {
-                const double    dfPower =
-                    ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfPower;
-                const double    dfSmoothing =
-                    ((GDALGridInverseDistanceToAPowerOptions *)poOptions)->dfSmoothing;
+                const double dfPower = poPower->dfPower;
+                const double dfSmoothing = poPower->dfSmoothing;
 
                 pfnGDALGridMethod = GDALGridInverseDistanceToAPowerNoSearch;
                 if( dfPower == 2.0 && dfSmoothing == 0.0 )
                 {
 #ifdef HAVE_AVX_AT_COMPILE_TIME
 
-#define ALIGN32(x)  (((char*)(x)) + ((32 - (((size_t)(x)) % 32)) % 32))
-
-                    if( CPLTestBool(CPLGetConfigOption("GDAL_USE_AVX", "YES")) &&
+                    if( CPLTestBool(
+                            CPLGetConfigOption("GDAL_USE_AVX", "YES")) &&
                         CPLHaveRuntimeAVX() )
                     {
-                        pabyX = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 31);
-                        pabyY = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 31);
-                        pabyZ = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 31);
-                        if( pabyX != NULL && pabyY != NULL && pabyZ != NULL)
+                        pafXAligned = static_cast<float *>(
+                            VSI_MALLOC_ALIGNED_AUTO_VERBOSE(
+                                sizeof(float) * nPoints) );
+                        pafYAligned = static_cast<float *>(
+                            VSI_MALLOC_ALIGNED_AUTO_VERBOSE(
+                                sizeof(float) * nPoints) );
+                        pafZAligned = static_cast<float *>(
+                            VSI_MALLOC_ALIGNED_AUTO_VERBOSE(
+                                sizeof(float) * nPoints) );
+                        if( pafXAligned != NULL && pafYAligned != NULL &&
+                            pafZAligned != NULL )
                         {
-                            CPLDebug("GDAL_GRID", "Using AVX optimized version");
-                            pafXAligned = (float*) ALIGN32(pabyX);
-                            pafYAligned = (float*) ALIGN32(pabyY);
-                            pafZAligned = (float*) ALIGN32(pabyZ);
-                            pfnGDALGridMethod = GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX;
-                            GUInt32 i;
-                            for(i=0;i<nPoints;i++)
+                            CPLDebug("GDAL_GRID",
+                                     "Using AVX optimized version");
+                            pfnGDALGridMethod =
+                                GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX;
+                            for( GUInt32 i = 0; i < nPoints; i++ )
                             {
-                                pafXAligned[i] = (float) padfX[i];
-                                pafYAligned[i] = (float) padfY[i];
-                                pafZAligned[i] = (float) padfZ[i];
+                                pafXAligned[i] = static_cast<float>(padfX[i]);
+                                pafYAligned[i] = static_cast<float>(padfY[i]);
+                                pafZAligned[i] = static_cast<float>(padfZ[i]);
                             }
                         }
                         else
                         {
-                            VSIFree(pabyX);
-                            VSIFree(pabyY);
-                            VSIFree(pabyZ);
-                            pabyX = pabyY = pabyZ = NULL;
+                            VSIFree(pafXAligned);
+                            VSIFree(pafYAligned);
+                            VSIFree(pafZAligned);
+                            pafXAligned = NULL;
+                            pafYAligned = NULL;
+                            pafZAligned = NULL;
                         }
                     }
 #endif
 
 #ifdef HAVE_SSE_AT_COMPILE_TIME
 
-#define ALIGN16(x)  (((char*)(x)) + ((16 - (((size_t)(x)) % 16)) % 16))
-
                     if( pafXAligned == NULL &&
-                        CPLTestBool(CPLGetConfigOption("GDAL_USE_SSE", "YES")) &&
+                        CPLTestBool(
+                            CPLGetConfigOption("GDAL_USE_SSE", "YES")) &&
                         CPLHaveRuntimeSSE() )
                     {
-                        pabyX = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 15);
-                        pabyY = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 15);
-                        pabyZ = (float*)VSI_MALLOC_VERBOSE(sizeof(float) * nPoints + 15);
-                        if( pabyX != NULL && pabyY != NULL && pabyZ != NULL)
+                        pafXAligned = static_cast<float *>(
+                            VSI_MALLOC_ALIGNED_AUTO_VERBOSE(
+                                sizeof(float) * nPoints) );
+                        pafYAligned = static_cast<float *>(
+                            VSI_MALLOC_ALIGNED_AUTO_VERBOSE(
+                                sizeof(float) * nPoints) );
+                        pafZAligned = static_cast<float *>(
+                            VSI_MALLOC_ALIGNED_AUTO_VERBOSE(
+                                sizeof(float) * nPoints) );
+                        if( pafXAligned != NULL && pafYAligned != NULL &&
+                            pafZAligned != NULL )
                         {
-                            CPLDebug("GDAL_GRID", "Using SSE optimized version");
-                            pafXAligned = (float*) ALIGN16(pabyX);
-                            pafYAligned = (float*) ALIGN16(pabyY);
-                            pafZAligned = (float*) ALIGN16(pabyZ);
-                            pfnGDALGridMethod = GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE;
-                            GUInt32 i;
-                            for(i=0;i<nPoints;i++)
+                            CPLDebug("GDAL_GRID",
+                                     "Using SSE optimized version");
+                            pfnGDALGridMethod =
+                                GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE;
+                            for( GUInt32 i = 0; i < nPoints; i++ )
                             {
-                                pafXAligned[i] = (float) padfX[i];
-                                pafYAligned[i] = (float) padfY[i];
-                                pafZAligned[i] = (float) padfZ[i];
+                                pafXAligned[i] = static_cast<float>(padfX[i]);
+                                pafYAligned[i] = static_cast<float>(padfY[i]);
+                                pafZAligned[i] = static_cast<float>(padfZ[i]);
                             }
                         }
                         else
                         {
-                            VSIFree(pabyX);
-                            VSIFree(pabyY);
-                            VSIFree(pabyZ);
-                            pabyX = pabyY = pabyZ = NULL;
+                            VSIFree(pafXAligned);
+                            VSIFree(pafYAligned);
+                            VSIFree(pafZAligned);
+                            pafXAligned = NULL;
+                            pafYAligned = NULL;
+                            pafZAligned = NULL;
                         }
                     }
 #endif // HAVE_SSE_AT_COMPILE_TIME
                 }
             }
             else
+            {
                 pfnGDALGridMethod = GDALGridInverseDistanceToAPower;
+            }
             break;
-
+        }
         case GGA_InverseDistanceToAPowerNearestNeighbor:
-            poOptionsNew = CPLMalloc(sizeof(GDALGridInverseDistanceToAPowerNearestNeighborOptions));
-            memcpy(poOptionsNew, poOptions, sizeof(GDALGridInverseDistanceToAPowerNearestNeighborOptions));
+        {
+            poOptionsNew = CPLMalloc(
+                sizeof(GDALGridInverseDistanceToAPowerNearestNeighborOptions));
+            memcpy(poOptionsNew, poOptions,
+                   sizeof(
+                       GDALGridInverseDistanceToAPowerNearestNeighborOptions));
 
             pfnGDALGridMethod = GDALGridInverseDistanceToAPowerNearestNeighbor;
             bCreateQuadTree = TRUE;
             break;
-
+        }
         case GGA_MovingAverage:
+        {
             poOptionsNew = CPLMalloc(sizeof(GDALGridMovingAverageOptions));
-            memcpy(poOptionsNew, poOptions, sizeof(GDALGridMovingAverageOptions));
+            memcpy(poOptionsNew,
+                   poOptions,
+                   sizeof(GDALGridMovingAverageOptions));
 
             pfnGDALGridMethod = GDALGridMovingAverage;
             break;
-
+        }
         case GGA_NearestNeighbor:
+        {
             poOptionsNew = CPLMalloc(sizeof(GDALGridNearestNeighborOptions));
-            memcpy(poOptionsNew, poOptions, sizeof(GDALGridNearestNeighborOptions));
+            memcpy(poOptionsNew, poOptions,
+                   sizeof(GDALGridNearestNeighborOptions));
 
             pfnGDALGridMethod = GDALGridNearestNeighbor;
             bCreateQuadTree = (nPoints > 100 &&
                 (((GDALGridNearestNeighborOptions *)poOptions)->dfRadius1 ==
                 ((GDALGridNearestNeighborOptions *)poOptions)->dfRadius2));
             break;
-
+        }
         case GGA_MetricMinimum:
+        {
             poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
             memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
 
             pfnGDALGridMethod = GDALGridDataMetricMinimum;
             break;
-
+        }
         case GGA_MetricMaximum:
+        {
             poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
             memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
 
             pfnGDALGridMethod = GDALGridDataMetricMaximum;
             break;
-
+        }
         case GGA_MetricRange:
+        {
             poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
             memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
 
             pfnGDALGridMethod = GDALGridDataMetricRange;
             break;
-
+        }
         case GGA_MetricCount:
+        {
             poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
             memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
 
             pfnGDALGridMethod = GDALGridDataMetricCount;
             break;
-
+        }
         case GGA_MetricAverageDistance:
+        {
             poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
             memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
 
             pfnGDALGridMethod = GDALGridDataMetricAverageDistance;
             break;
-
+        }
         case GGA_MetricAverageDistancePts:
+        {
             poOptionsNew = CPLMalloc(sizeof(GDALGridDataMetricsOptions));
             memcpy(poOptionsNew, poOptions, sizeof(GDALGridDataMetricsOptions));
 
             pfnGDALGridMethod = GDALGridDataMetricAverageDistancePts;
             break;
-
+        }
         case GGA_Linear:
+        {
             poOptionsNew = CPLMalloc(sizeof(GDALGridLinearOptions));
             memcpy(poOptionsNew, poOptions, sizeof(GDALGridLinearOptions));
 
             pfnGDALGridMethod = GDALGridLinear;
             break;
-
+        }
         default:
             CPLError( CE_Failure, CPLE_IllegalArg,
                       "GDAL does not support gridding method %d", eAlgorithm );
             return NULL;
     }
 
-    if( pafXAligned != NULL )
-        bCallerWillKeepPointArraysAlive = TRUE;
-    if( !bCallerWillKeepPointArraysAlive )
+    if( pafXAligned == NULL && !bCallerWillKeepPointArraysAlive )
     {
-        double* padfXNew = (double*)VSI_MALLOC2_VERBOSE(nPoints, sizeof(double));
-        double* padfYNew = (double*)VSI_MALLOC2_VERBOSE(nPoints, sizeof(double));
-        double* padfZNew = (double*)VSI_MALLOC2_VERBOSE(nPoints, sizeof(double));
+        double* padfXNew =
+            static_cast<double *>(VSI_MALLOC2_VERBOSE(nPoints, sizeof(double)));
+        double* padfYNew =
+            static_cast<double *>(VSI_MALLOC2_VERBOSE(nPoints, sizeof(double)));
+        double* padfZNew =
+            static_cast<double *>(VSI_MALLOC2_VERBOSE(nPoints, sizeof(double)));
         if( padfXNew == NULL || padfYNew == NULL || padfZNew == NULL )
         {
             VSIFree(padfXNew);
@@ -1987,7 +1979,8 @@ GDALGridContextCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
         padfY = padfYNew;
         padfZ = padfZNew;
     }
-    GDALGridContext* psContext = (GDALGridContext*)CPLCalloc(1, sizeof(GDALGridContext));
+    GDALGridContext* psContext =
+        static_cast<GDALGridContext *>(CPLCalloc(1, sizeof(GDALGridContext)));
     psContext->eAlgorithm = eAlgorithm;
     psContext->poOptions = poOptionsNew;
     psContext->pfnGDALGridMethod = pfnGDALGridMethod;
@@ -1996,19 +1989,17 @@ GDALGridContextCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
     psContext->sXYArrays.padfX = padfX;
     psContext->sXYArrays.padfY = padfY;
     psContext->sExtraParameters.hQuadTree = NULL;
-    psContext->sExtraParameters.dfInitialSearchRadius = 0;
+    psContext->sExtraParameters.dfInitialSearchRadius = 0.0;
     psContext->sExtraParameters.pafX = pafXAligned;
     psContext->sExtraParameters.pafY = pafYAligned;
     psContext->sExtraParameters.pafZ = pafZAligned;
     psContext->sExtraParameters.psTriangulation = NULL;
     psContext->sExtraParameters.nInitialFacetIdx = 0;
-    psContext->padfX = pafXAligned ? NULL : (double*)padfX;
-    psContext->padfY = pafXAligned ? NULL : (double*)padfY;
-    psContext->padfZ = pafXAligned ? NULL : (double*)padfZ;
-    psContext->bFreePadfXYZArrays = !bCallerWillKeepPointArraysAlive;
-    psContext->pabyX = pabyX;
-    psContext->pabyY = pabyY;
-    psContext->pabyZ = pabyZ;
+    psContext->padfX = pafXAligned ? NULL : const_cast<double *>(padfX);
+    psContext->padfY = pafXAligned ? NULL : const_cast<double *>(padfY);
+    psContext->padfZ = pafXAligned ? NULL : const_cast<double *>(padfZ);
+    psContext->bFreePadfXYZArrays =
+        pafXAligned ? false : !bCallerWillKeepPointArraysAlive;
 
 /* -------------------------------------------------------------------- */
 /*  Create quadtree if requested and possible.                          */
@@ -2050,12 +2041,12 @@ GDALGridContextCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
 /*  Start thread pool.                                                  */
 /* -------------------------------------------------------------------- */
     const char* pszThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
-    int nThreads;
-    if (EQUAL(pszThreads, "ALL_CPUS"))
+    int nThreads = 0;
+    if( EQUAL(pszThreads, "ALL_CPUS") )
         nThreads = CPLGetNumCPUs();
     else
         nThreads = atoi(pszThreads);
-    if (nThreads > 128)
+    if( nThreads > 128 )
         nThreads = 128;
     if( nThreads > 1 )
     {
@@ -2080,25 +2071,23 @@ GDALGridContextCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
 /*                      GDALGridContextCreateQuadTree()                 */
 /************************************************************************/
 
-void GDALGridContextCreateQuadTree(GDALGridContext* psContext)
+void GDALGridContextCreateQuadTree( GDALGridContext* psContext )
 {
-    GUInt32 nPoints = psContext->nPoints;
-    psContext->pasGridPoints = (GDALGridPoint*)
-            VSI_MALLOC2_VERBOSE(nPoints, sizeof(GDALGridPoint));
+    const GUInt32 nPoints = psContext->nPoints;
+    psContext->pasGridPoints = static_cast<GDALGridPoint *>(
+            VSI_MALLOC2_VERBOSE(nPoints, sizeof(GDALGridPoint)) );
     if( psContext->pasGridPoints != NULL )
     {
-        const double* padfX = psContext->padfX;
-        const double* padfY = psContext->padfY;
+        const double * const padfX = psContext->padfX;
+        const double * const padfY = psContext->padfY;
 
+        // Determine point extents.
         CPLRectObj sRect;
-        GUInt32 i;
-
-        /* Determine point extents */
         sRect.minx = padfX[0];
         sRect.miny = padfY[0];
         sRect.maxx = padfX[0];
         sRect.maxy = padfY[0];
-        for(i = 1; i < nPoints; i++)
+        for( GUInt32 i = 1; i < nPoints; i++ )
         {
             if( padfX[i] < sRect.minx ) sRect.minx = padfX[i];
             if( padfY[i] < sRect.miny ) sRect.miny = padfY[i];
@@ -2106,16 +2095,16 @@ void GDALGridContextCreateQuadTree(GDALGridContext* psContext)
             if( padfY[i] > sRect.maxy ) sRect.maxy = padfY[i];
         }
 
-        /* Initial value for search radius is the typical dimension of a */
-        /* "pixel" of the point array (assuming rather uniform distribution) */
+        // Initial value for search radius is the typical dimension of a
+        // "pixel" of the point array (assuming rather uniform distribution).
         psContext->sExtraParameters.dfInitialSearchRadius =
-                                sqrt((sRect.maxx - sRect.minx) *
-                                        (sRect.maxy - sRect.miny) / nPoints);
+            sqrt((sRect.maxx - sRect.minx) *
+                 (sRect.maxy - sRect.miny) / nPoints);
 
         psContext->sExtraParameters.hQuadTree =
-                    CPLQuadTreeCreate(&sRect, GDALGridGetPointBounds );
+            CPLQuadTreeCreate(&sRect, GDALGridGetPointBounds );
 
-        for(i = 0; i < nPoints; i++)
+        for( GUInt32 i = 0; i < nPoints; i++ )
         {
             psContext->pasGridPoints[i].psXYArrays = &(psContext->sXYArrays);
             psContext->pasGridPoints[i].i = i;
@@ -2136,7 +2125,7 @@ void GDALGridContextCreateQuadTree(GDALGridContext* psContext)
  *
  * @since GDAL 2.1
  */
-void GDALGridContextFree(GDALGridContext* psContext)
+void GDALGridContextFree( GDALGridContext* psContext )
 {
     if( psContext )
     {
@@ -2150,11 +2139,11 @@ void GDALGridContextFree(GDALGridContext* psContext)
             CPLFree(psContext->padfY);
             CPLFree(psContext->padfZ);
         }
-        CPLFree(psContext->pabyX);
-        CPLFree(psContext->pabyY);
-        CPLFree(psContext->pabyZ);
+        VSIFreeAligned(psContext->sExtraParameters.pafX);
+        VSIFreeAligned(psContext->sExtraParameters.pafY);
+        VSIFreeAligned(psContext->sExtraParameters.pafZ);
         if( psContext->sExtraParameters.psTriangulation )
-            GDALTriangulationFree( psContext->sExtraParameters.psTriangulation );
+            GDALTriangulationFree(psContext->sExtraParameters.psTriangulation);
         delete psContext->poWorkerThreadPool;
         CPLFree(psContext);
     }
@@ -2190,73 +2179,82 @@ void GDALGridContextFree(GDALGridContext* psContext)
  * @since GDAL 2.1
  */
 
-CPLErr GDALGridContextProcess(GDALGridContext* psContext,
-                              double dfXMin, double dfXMax, double dfYMin, double dfYMax,
-                              GUInt32 nXSize, GUInt32 nYSize, GDALDataType eType, void *pData,
-                              GDALProgressFunc pfnProgress, void *pProgressArg )
+CPLErr GDALGridContextProcess(
+    GDALGridContext* psContext,
+    double dfXMin, double dfXMax, double dfYMin, double dfYMax,
+    GUInt32 nXSize, GUInt32 nYSize, GDALDataType eType, void *pData,
+    GDALProgressFunc pfnProgress, void *pProgressArg )
 {
     CPLAssert( psContext );
     CPLAssert( pData );
 
-    if ( nXSize == 0 || nYSize == 0 )
+    if( nXSize == 0 || nYSize == 0 )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
                   "Output raster dimensions should have non-zero size." );
         return CE_Failure;
     }
 
-    const double    dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
-    const double    dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
+    const double dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
+    const double dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
 
     // For linear, check if we will need to fallback to nearest neighbour
-    // by sampling along the edges (if all points on edges are within triangles,
-    // then interior points will also be!)
+    // by sampling along the edges.  If all points on edges are within
+    // triangles, then interior points will also be.
     if( psContext->eAlgorithm == GGA_Linear &&
         psContext->sExtraParameters.hQuadTree == NULL )
     {
-        int bNeedNearest = FALSE;
-        int nStartLeft = 0, nStartRight = 0;
-        const double    dfXPointMin = dfXMin + ( 0 + 0.5 ) * dfDeltaX;
-        const double    dfXPointMax = dfXMin + ( nXSize - 1 + 0.5 ) * dfDeltaX;
-        for ( GUInt32 nYPoint = 0; !bNeedNearest && nYPoint < nYSize; nYPoint ++ )
+        bool bNeedNearest = false;
+        int nStartLeft = 0;
+        int nStartRight = 0;
+        const double dfXPointMin = dfXMin + ( 0 + 0.5 ) * dfDeltaX;
+        const double dfXPointMax = dfXMin + ( nXSize - 1 + 0.5 ) * dfDeltaX;
+        for( GUInt32 nYPoint = 0; !bNeedNearest && nYPoint < nYSize; nYPoint++ )
         {
-            const double    dfYPoint = dfYMin + ( nYPoint + 0.5 ) * dfDeltaY;
+            const double dfYPoint = dfYMin + ( nYPoint + 0.5 ) * dfDeltaY;
 
-            if( !GDALTriangulationFindFacetDirected( psContext->sExtraParameters.psTriangulation,
-                                                     nStartLeft,
-                                                     dfXPointMin, dfYPoint,
-                                                     &nStartLeft) )
+            if( !GDALTriangulationFindFacetDirected(
+                psContext->sExtraParameters.psTriangulation,
+                nStartLeft,
+                dfXPointMin, dfYPoint,
+                &nStartLeft) )
             {
-                bNeedNearest = TRUE;
+                bNeedNearest = true;
             }
-            if( !GDALTriangulationFindFacetDirected( psContext->sExtraParameters.psTriangulation,
-                                                     nStartRight,
-                                                     dfXPointMax, dfYPoint,
-                                                     &nStartRight) )
+            if( !GDALTriangulationFindFacetDirected(
+                psContext->sExtraParameters.psTriangulation,
+                nStartRight,
+                dfXPointMax, dfYPoint,
+                &nStartRight) )
             {
-                bNeedNearest = TRUE;
+                bNeedNearest = true;
             }
         }
-        int nStartTop = 0, nStartBottom = 0;
-        const double    dfYPointMin = dfYMin + ( 0 + 0.5 ) * dfDeltaY;
-        const double    dfYPointMax = dfYMin + ( nYSize - 1 + 0.5 ) * dfDeltaY;
-        for ( GUInt32 nXPoint = 1; !bNeedNearest && nXPoint + 1 < nXSize; nXPoint ++ )
+        int nStartTop = 0;
+        int nStartBottom = 0;
+        const double dfYPointMin = dfYMin + ( 0 + 0.5 ) * dfDeltaY;
+        const double dfYPointMax = dfYMin + ( nYSize - 1 + 0.5 ) * dfDeltaY;
+        for( GUInt32 nXPoint = 1;
+             !bNeedNearest && nXPoint + 1 < nXSize;
+             nXPoint++ )
         {
-            const double    dfXPoint = dfXMin + ( nXPoint + 0.5 ) * dfDeltaX;
+            const double dfXPoint = dfXMin + ( nXPoint + 0.5 ) * dfDeltaX;
 
-            if( !GDALTriangulationFindFacetDirected( psContext->sExtraParameters.psTriangulation,
-                                                     nStartTop,
-                                                     dfXPoint, dfYPointMin,
-                                                     &nStartTop) )
+            if( !GDALTriangulationFindFacetDirected(
+                psContext->sExtraParameters.psTriangulation,
+                nStartTop,
+                dfXPoint, dfYPointMin,
+                &nStartTop) )
             {
-                bNeedNearest = TRUE;
+                bNeedNearest = true;
             }
-            if( !GDALTriangulationFindFacetDirected( psContext->sExtraParameters.psTriangulation,
-                                                     nStartBottom,
-                                                     dfXPoint, dfYPointMax,
-                                                     &nStartBottom) )
+            if( !GDALTriangulationFindFacetDirected(
+                psContext->sExtraParameters.psTriangulation,
+                nStartBottom,
+                dfXPoint, dfYPointMax,
+                &nStartBottom) )
             {
-                bNeedNearest = TRUE;
+                bNeedNearest = true;
             }
         }
         if( bNeedNearest )
@@ -2270,7 +2268,7 @@ CPLErr GDALGridContextProcess(GDALGridContext* psContext,
     volatile int bStop = FALSE;
     GDALGridJob sJob;
     sJob.nYStart = 0;
-    sJob.pabyData = (GByte*) pData;
+    sJob.pabyData = static_cast<GByte *>(pData);
     sJob.nYStep = 1;
     sJob.nXSize = nXSize;
     sJob.nYSize = nYSize;
@@ -2296,16 +2294,19 @@ CPLErr GDALGridContextProcess(GDALGridContext* psContext,
 
     if( psContext->poWorkerThreadPool == NULL )
     {
-        if( sJob.pfnRealProgress != NULL && sJob.pfnRealProgress != GDALDummyProgress )
+        if( sJob.pfnRealProgress != NULL &&
+            sJob.pfnRealProgress != GDALDummyProgress )
+        {
             sJob.pfnProgress = GDALGridProgressMonoThread;
+        }
 
         GDALGridJobProcess(&sJob);
     }
     else
     {
         int nThreads  = psContext->poWorkerThreadPool->GetThreadCount();
-        GDALGridJob* pasJobs = (GDALGridJob*) CPLMalloc(sizeof(GDALGridJob) * nThreads);
-        int i;
+        GDALGridJob* pasJobs = static_cast<GDALGridJob *>(
+            CPLMalloc(sizeof(GDALGridJob) * nThreads) );
 
         sJob.nYStep = nThreads;
         sJob.hCondMutex = CPLCreateMutex(); /* and  implicitly take the mutex */
@@ -2315,18 +2316,18 @@ CPLErr GDALGridContextProcess(GDALGridContext* psContext,
 /* -------------------------------------------------------------------- */
 /*      Start threads.                                                  */
 /* -------------------------------------------------------------------- */
-        for(i = 0; i < nThreads && !bStop; i++)
+        for( int i = 0; i < nThreads && !bStop; i++ )
         {
             memcpy(&pasJobs[i], &sJob, sizeof(GDALGridJob));
             pasJobs[i].nYStart = i;
             psContext->poWorkerThreadPool->SubmitJob( GDALGridJobProcess,
-                                                      (void*) &pasJobs[i] );
+                                                      &pasJobs[i] );
         }
 
 /* -------------------------------------------------------------------- */
 /*      Report progress.                                                */
 /* -------------------------------------------------------------------- */
-        while(nCounter < (int)nYSize && !bStop)
+        while( nCounter < static_cast<int>(nYSize) && !bStop )
         {
             CPLCondWait(sJob.hCond, sJob.hCondMutex);
 
@@ -2334,7 +2335,8 @@ CPLErr GDALGridContextProcess(GDALGridContext* psContext,
             CPLReleaseMutex(sJob.hCondMutex);
 
             if( pfnProgress != NULL &&
-                !pfnProgress( nLocalCounter / (double) nYSize, "", pProgressArg ) )
+                !pfnProgress( nLocalCounter / static_cast<double>(nYSize),
+                              "", pProgressArg ) )
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
                 bStop = TRUE;
@@ -2343,8 +2345,8 @@ CPLErr GDALGridContextProcess(GDALGridContext* psContext,
             CPLAcquireMutex(sJob.hCondMutex, 1.0);
         }
 
-        /* Release mutex before joining threads, otherwise they will dead-lock */
-        /* forever in GDALGridProgressMultiThread() */
+        // Release mutex before joining threads, otherwise they will dead-lock
+        // forever in GDALGridProgressMultiThread().
         CPLReleaseMutex(sJob.hCondMutex);
 
 /* -------------------------------------------------------------------- */
@@ -2423,11 +2425,11 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
                 GUInt32 nXSize, GUInt32 nYSize, GDALDataType eType, void *pData,
                 GDALProgressFunc pfnProgress, void *pProgressArg )
 {
+    GDALGridContext* psContext = GDALGridContextCreate(eAlgorithm, poOptions,
+                                                       nPoints,
+                                                       padfX, padfY, padfZ,
+                                                       TRUE);
     CPLErr eErr = CE_Failure;
-    GDALGridContext* psContext = GDALGridContextCreate( eAlgorithm,poOptions,
-                                                        nPoints,
-                                                        padfX, padfY, padfZ,
-                                                        TRUE );
     if( psContext )
     {
         eErr = GDALGridContextProcess( psContext,
@@ -2442,12 +2444,11 @@ GDALGridCreate( GDALGridAlgorithm eAlgorithm, const void *poOptions,
 
 /************************************************************************/
 /*                      ParseAlgorithmAndOptions()                      */
-/*                                                                      */
-/*      Translates mnemonic gridding algorithm names into               */
-/*      GDALGridAlgorithm code, parse control parameters and assign     */
-/*      defaults.                                                       */
 /************************************************************************/
 
+/** Translates mnemonic gridding algorithm names into GDALGridAlgorithm code,
+ * parse control parameters and assign defaults.
+ */
 CPLErr ParseAlgorithmAndOptions( const char *pszAlgorithm,
                                  GDALGridAlgorithm *peAlgorithm,
                                  void **ppOptions )
@@ -2460,38 +2461,61 @@ CPLErr ParseAlgorithmAndOptions( const char *pszAlgorithm,
 
     char **papszParms = CSLTokenizeString2( pszAlgorithm, ":", FALSE );
 
-    if ( CSLCount(papszParms) < 1 )
+    if( CSLCount(papszParms) < 1 )
     {
         CSLDestroy( papszParms );
         return CE_Failure;
     }
 
-    if ( EQUAL(papszParms[0], szAlgNameInvDist) )
+    if( EQUAL(papszParms[0], szAlgNameInvDist) )
+    {
         *peAlgorithm = GGA_InverseDistanceToAPower;
-    else if ( EQUAL(papszParms[0], szAlgNameInvDistNearestNeighbor) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameInvDistNearestNeighbor) )
+    {
         *peAlgorithm = GGA_InverseDistanceToAPowerNearestNeighbor;
-    else if ( EQUAL(papszParms[0], szAlgNameAverage) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameAverage) )
+    {
         *peAlgorithm = GGA_MovingAverage;
-    else if ( EQUAL(papszParms[0], szAlgNameNearest) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameNearest) )
+    {
         *peAlgorithm = GGA_NearestNeighbor;
-    else if ( EQUAL(papszParms[0], szAlgNameMinimum) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameMinimum) )
+    {
         *peAlgorithm = GGA_MetricMinimum;
-    else if ( EQUAL(papszParms[0], szAlgNameMaximum) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameMaximum) )
+    {
         *peAlgorithm = GGA_MetricMaximum;
-    else if ( EQUAL(papszParms[0], szAlgNameRange) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameRange) )
+    {
         *peAlgorithm = GGA_MetricRange;
-    else if ( EQUAL(papszParms[0], szAlgNameCount) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameCount) )
+    {
         *peAlgorithm = GGA_MetricCount;
-    else if ( EQUAL(papszParms[0], szAlgNameAverageDistance) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameAverageDistance) )
+    {
         *peAlgorithm = GGA_MetricAverageDistance;
-    else if ( EQUAL(papszParms[0], szAlgNameAverageDistancePts) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameAverageDistancePts) )
+    {
         *peAlgorithm = GGA_MetricAverageDistancePts;
-    else if ( EQUAL(papszParms[0], szAlgNameLinear) )
+    }
+    else if( EQUAL(papszParms[0], szAlgNameLinear) )
+    {
         *peAlgorithm = GGA_Linear;
+    }
     else
     {
-        fprintf( stderr, "Unsupported gridding method \"%s\".\n",
-                 papszParms[0] );
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "Unsupported gridding method \"%s\"",
+                  papszParms[0] );
         CSLDestroy( papszParms );
         return CE_Failure;
     }
@@ -2499,318 +2523,174 @@ CPLErr ParseAlgorithmAndOptions( const char *pszAlgorithm,
 /* -------------------------------------------------------------------- */
 /*      Parse algorithm parameters and assign defaults.                 */
 /* -------------------------------------------------------------------- */
-    const char  *pszValue;
-
-    switch ( *peAlgorithm )
+    switch( *peAlgorithm )
     {
         case GGA_InverseDistanceToAPower:
         default:
+        {
             *ppOptions =
                 CPLMalloc( sizeof(GDALGridInverseDistanceToAPowerOptions) );
 
-            pszValue = CSLFetchNameValue( papszParms, "power" );
-            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
-                dfPower = (pszValue) ? CPLAtofM(pszValue) : 2.0;
+            GDALGridInverseDistanceToAPowerOptions * const poPowerOpts =
+                static_cast<GDALGridInverseDistanceToAPowerOptions *>(
+                    *ppOptions);
+
+            const char *pszValue = CSLFetchNameValue( papszParms, "power" );
+            poPowerOpts->dfPower = pszValue ? CPLAtofM(pszValue) : 2.0;
 
             pszValue = CSLFetchNameValue( papszParms, "smoothing" );
-            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
-                dfSmoothing = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poPowerOpts->dfSmoothing = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "radius1" );
-            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
-                dfRadius1 = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poPowerOpts->dfRadius1 = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "radius2" );
-            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
-                dfRadius2 = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poPowerOpts->dfRadius2 = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "angle" );
-            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
-                dfAngle = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poPowerOpts->dfAngle = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "max_points" );
-            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
-                nMaxPoints = (GUInt32) ((pszValue) ? CPLAtofM(pszValue) : 0);
+            poPowerOpts->nMaxPoints = static_cast<GUInt32>(
+                pszValue ? CPLAtofM(pszValue) : 0);
 
             pszValue = CSLFetchNameValue( papszParms, "min_points" );
-            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
-                nMinPoints = (GUInt32) ((pszValue) ? CPLAtofM(pszValue) : 0);
+            poPowerOpts->nMinPoints = static_cast<GUInt32>(
+                pszValue ? CPLAtofM(pszValue) : 0);
 
             pszValue = CSLFetchNameValue( papszParms, "nodata" );
-            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
-                dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
-            break;
+            poPowerOpts->dfNoDataValue = pszValue ? CPLAtofM(pszValue) : 0.0;
 
+            break;
+        }
         case GGA_InverseDistanceToAPowerNearestNeighbor:
+        {
             *ppOptions =
-                CPLMalloc( sizeof(GDALGridInverseDistanceToAPowerNearestNeighborOptions) );
+                CPLMalloc( sizeof(
+                    GDALGridInverseDistanceToAPowerNearestNeighborOptions) );
+
+            GDALGridInverseDistanceToAPowerNearestNeighborOptions * const
+                poPowerOpts =
+                    static_cast<
+                    GDALGridInverseDistanceToAPowerNearestNeighborOptions *>(
+                        *ppOptions);
 
-            pszValue = CSLFetchNameValue( papszParms, "power" );
-            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
-                dfPower = (pszValue) ? CPLAtofM(pszValue) : 2.0;
+            const char *pszValue = CSLFetchNameValue( papszParms, "power" );
+            poPowerOpts->dfPower = pszValue ? CPLAtofM(pszValue) : 2.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "smoothing" );
+            poPowerOpts->dfSmoothing = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "radius" );
-            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
-                dfRadius = (pszValue) ? CPLAtofM(pszValue) : 1.0;
+            poPowerOpts->dfRadius = pszValue ? CPLAtofM(pszValue) : 1.0;
 
             pszValue = CSLFetchNameValue( papszParms, "max_points" );
-            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
-                nMaxPoints = (GUInt32) ((pszValue) ? CPLAtofM(pszValue) : 12);
+            poPowerOpts->nMaxPoints = static_cast<GUInt32>(
+                pszValue ? CPLAtofM(pszValue) : 12);
 
             pszValue = CSLFetchNameValue( papszParms, "min_points" );
-            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
-                nMinPoints = (GUInt32) ((pszValue) ? CPLAtofM(pszValue) : 0);
+            poPowerOpts->nMinPoints = static_cast<GUInt32>(
+                pszValue ? CPLAtofM(pszValue) : 0);
 
             pszValue = CSLFetchNameValue( papszParms, "nodata" );
-            ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)*ppOptions)->
-                dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
-            break;
+            poPowerOpts->dfNoDataValue = pszValue ? CPLAtofM(pszValue) : 0.0;
 
+            break;
+        }
         case GGA_MovingAverage:
+        {
             *ppOptions =
                 CPLMalloc( sizeof(GDALGridMovingAverageOptions) );
 
-            pszValue = CSLFetchNameValue( papszParms, "radius1" );
-            ((GDALGridMovingAverageOptions *)*ppOptions)->
-                dfRadius1 = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            GDALGridMovingAverageOptions * const poAverageOpts =
+                static_cast<GDALGridMovingAverageOptions *>(*ppOptions);
+
+            const char *pszValue = CSLFetchNameValue( papszParms, "radius1" );
+            poAverageOpts->dfRadius1 = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "radius2" );
-            ((GDALGridMovingAverageOptions *)*ppOptions)->
-                dfRadius2 = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poAverageOpts->dfRadius2 = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "angle" );
-            ((GDALGridMovingAverageOptions *)*ppOptions)->
-                dfAngle = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poAverageOpts->dfAngle = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "min_points" );
-            ((GDALGridMovingAverageOptions *)*ppOptions)->
-                nMinPoints = (GUInt32) ((pszValue) ? CPLAtofM(pszValue) : 0);
+            poAverageOpts->nMinPoints = static_cast<GUInt32>(
+                pszValue ? CPLAtofM(pszValue) : 0);
 
             pszValue = CSLFetchNameValue( papszParms, "nodata" );
-            ((GDALGridMovingAverageOptions *)*ppOptions)->
-                dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
-            break;
+            poAverageOpts->dfNoDataValue = pszValue ? CPLAtofM(pszValue) : 0.0;
 
+            break;
+        }
         case GGA_NearestNeighbor:
+        {
             *ppOptions =
                 CPLMalloc( sizeof(GDALGridNearestNeighborOptions) );
 
-            pszValue = CSLFetchNameValue( papszParms, "radius1" );
-            ((GDALGridNearestNeighborOptions *)*ppOptions)->
-                dfRadius1 = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            GDALGridNearestNeighborOptions * const poNeighborOpts =
+                static_cast<GDALGridNearestNeighborOptions *>(*ppOptions);
+
+            const char *pszValue = CSLFetchNameValue( papszParms, "radius1" );
+            poNeighborOpts->dfRadius1 = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "radius2" );
-            ((GDALGridNearestNeighborOptions *)*ppOptions)->
-                dfRadius2 = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poNeighborOpts->dfRadius2 = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "angle" );
-            ((GDALGridNearestNeighborOptions *)*ppOptions)->
-                dfAngle = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poNeighborOpts->dfAngle = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "nodata" );
-            ((GDALGridNearestNeighborOptions *)*ppOptions)->
-                dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poNeighborOpts->dfNoDataValue = pszValue ? CPLAtofM(pszValue) : 0.0;
             break;
-
+        }
         case GGA_MetricMinimum:
         case GGA_MetricMaximum:
         case GGA_MetricRange:
         case GGA_MetricCount:
         case GGA_MetricAverageDistance:
         case GGA_MetricAverageDistancePts:
+        {
             *ppOptions =
                 CPLMalloc( sizeof(GDALGridDataMetricsOptions) );
 
-            pszValue = CSLFetchNameValue( papszParms, "radius1" );
-            ((GDALGridDataMetricsOptions *)*ppOptions)->
-                dfRadius1 = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            GDALGridDataMetricsOptions * const poMetricsOptions =
+                static_cast<GDALGridDataMetricsOptions *>(*ppOptions);
+
+            const char *pszValue = CSLFetchNameValue( papszParms, "radius1" );
+            poMetricsOptions->dfRadius1 = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "radius2" );
-            ((GDALGridDataMetricsOptions *)*ppOptions)->
-                dfRadius2 = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poMetricsOptions->dfRadius2 = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "angle" );
-            ((GDALGridDataMetricsOptions *)*ppOptions)->
-                dfAngle = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poMetricsOptions->dfAngle = pszValue ? CPLAtofM(pszValue) : 0.0;
 
             pszValue = CSLFetchNameValue( papszParms, "min_points" );
-            ((GDALGridDataMetricsOptions *)*ppOptions)->
-                nMinPoints = (pszValue) ? atoi(pszValue) : 0;
+            poMetricsOptions->nMinPoints = pszValue ? atoi(pszValue) : 0;
 
             pszValue = CSLFetchNameValue( papszParms, "nodata" );
-            ((GDALGridDataMetricsOptions *)*ppOptions)->
-                dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poMetricsOptions->dfNoDataValue =
+                pszValue ? CPLAtofM(pszValue) : 0.0;
             break;
-
+        }
         case GGA_Linear:
+        {
             *ppOptions =
                 CPLMalloc( sizeof(GDALGridLinearOptions) );
 
-            pszValue = CSLFetchNameValue( papszParms, "radius" );
-            ((GDALGridLinearOptions *)*ppOptions)->
-                dfRadius = (pszValue) ? CPLAtofM(pszValue) : -1.0;
+            GDALGridLinearOptions * const poLinearOpts =
+                static_cast<GDALGridLinearOptions *>(*ppOptions);
+
+            const char *pszValue = CSLFetchNameValue( papszParms, "radius" );
+            poLinearOpts->dfRadius = pszValue ? CPLAtofM(pszValue) : -1.0;
 
             pszValue = CSLFetchNameValue( papszParms, "nodata" );
-            ((GDALGridLinearOptions *)*ppOptions)->
-                dfNoDataValue = (pszValue) ? CPLAtofM(pszValue) : 0.0;
+            poLinearOpts->dfNoDataValue = pszValue ? CPLAtofM(pszValue) : 0.0;
             break;
-   }
+         }
+    }
 
     CSLDestroy( papszParms );
     return CE_None;
 }
-
-#ifdef HAVE_SSE_AT_COMPILE_TIME
-
-/************************************************************************/
-/*                          CPLHaveRuntimeSSE()                         */
-/************************************************************************/
-
-#define CPUID_SSE_EDX_BIT     25
-
-#if (defined(_M_X64) || defined(__x86_64))
-
-int CPLHaveRuntimeSSE()
-{
-    return TRUE;
-}
-
-#elif defined(__GNUC__) && defined(__i386__)
-
-int CPLHaveRuntimeSSE()
-{
-    int cpuinfo[4] = {0,0,0,0};
-    GCC_CPUID(1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
-    return (cpuinfo[3] & (1 << CPUID_SSE_EDX_BIT)) != 0;
-}
-
-#elif defined(_MSC_VER) && defined(_M_IX86)
-
-#if _MSC_VER <= 1310
-static void inline __cpuid(int cpuinfo[4], int level)
-{
-    __asm
-    {
-        push   ebx
-        push   esi
-
-        mov    esi,cpuinfo
-        mov    eax,level
-        cpuid
-        mov    dword ptr [esi], eax
-        mov    dword ptr [esi+4],ebx
-        mov    dword ptr [esi+8],ecx
-        mov    dword ptr [esi+0Ch],edx
-
-        pop    esi
-        pop    ebx
-    }
-}
-#else
-#include <intrin.h>
-#endif
-
-int CPLHaveRuntimeSSE()
-{
-    int cpuinfo[4] = {0,0,0,0};
-    __cpuid(cpuinfo, 1);
-    return (cpuinfo[3] & (1 << CPUID_SSE_EDX_BIT)) != 0;
-}
-
-#else
-
-int CPLHaveRuntimeSSE()
-{
-    return FALSE;
-}
-#endif
-
-#endif // HAVE_SSE_AT_COMPILE_TIME
-
-#ifdef HAVE_AVX_AT_COMPILE_TIME
-
-/************************************************************************/
-/*                          CPLHaveRuntimeAVX()                         */
-/************************************************************************/
-
-#define CPUID_OSXSAVE_ECX_BIT   27
-#define CPUID_AVX_ECX_BIT       28
-
-#define BIT_XMM_STATE           (1 << 1)
-#define BIT_YMM_STATE           (2 << 1)
-
-#if defined(__GNUC__) && (defined(__i386__) ||defined(__x86_64))
-
-int CPLHaveRuntimeAVX()
-{
-    int cpuinfo[4] = {0,0,0,0};
-    GCC_CPUID(1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
-
-    /* Check OSXSAVE feature */
-    if( (cpuinfo[2] & (1 << CPUID_OSXSAVE_ECX_BIT)) == 0 )
-    {
-        return FALSE;
-    }
-
-    /* Check AVX feature */
-    if( (cpuinfo[2] & (1 << CPUID_AVX_ECX_BIT)) == 0 )
-    {
-        return FALSE;
-    }
-
-    /* Issue XGETBV and check the XMM and YMM state bit */
-    unsigned int nXCRLow;
-    unsigned int nXCRHigh;
-    __asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0));
-    if( (nXCRLow & ( BIT_XMM_STATE | BIT_YMM_STATE )) !=
-                   ( BIT_XMM_STATE | BIT_YMM_STATE ) )
-    {
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) && (defined(_M_IX86) || defined(_M_X64))
-// _xgetbv available only in Visual Studio 2010 SP1 or later
-
-#include <intrin.h>
-
-int CPLHaveRuntimeAVX()
-{
-    int cpuinfo[4] = {0,0,0,0};
-    __cpuid(cpuinfo, 1);
-
-    /* Check OSXSAVE feature */
-    if( (cpuinfo[2] & (1 << CPUID_OSXSAVE_ECX_BIT)) == 0 )
-    {
-        return FALSE;
-    }
-
-    /* Check AVX feature */
-    if( (cpuinfo[2] & (1 << CPUID_AVX_ECX_BIT)) == 0 )
-    {
-        return FALSE;
-    }
-
-    /* Issue XGETBV and check the XMM and YMM state bit */
-    unsigned __int64 xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
-    if( (xcrFeatureMask & ( BIT_XMM_STATE | BIT_YMM_STATE )) !=
-                          ( BIT_XMM_STATE | BIT_YMM_STATE ) )
-    {
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-#else
-
-int CPLHaveRuntimeAVX()
-{
-    return FALSE;
-}
-
-#endif
-
-#endif //  HAVE_AVX_AT_COMPILE_TIME
diff --git a/alg/gdalgrid.h b/alg/gdalgrid.h
index f111130..7c6c598 100644
--- a/alg/gdalgrid.h
+++ b/alg/gdalgrid.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgrid.h 29541 2015-07-20 14:03:42Z rouault $
+ * $Id: gdalgrid.h 34931 2016-08-05 17:13:05Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Prototypes, and definitions for of GDAL scattered data gridder.
@@ -57,11 +57,14 @@ static const char szAlgNameLinear[] = "linear";
 
 CPL_C_START
 
+/*! @cond Doxygen_Suppress */
 typedef CPLErr (*GDALGridFunction)( const void *, GUInt32,
                                     const double *, const double *,
                                     const double *,
                                     double, double, double *,
                                     void* );
+/*! @endcond */
+
 CPLErr
 GDALGridInverseDistanceToAPower( const void *, GUInt32,
                                  const double *, const double *,
diff --git a/alg/gdalgrid_priv.h b/alg/gdalgrid_priv.h
index 9fe4e13..fddc470 100644
--- a/alg/gdalgrid_priv.h
+++ b/alg/gdalgrid_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgrid_priv.h 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: gdalgrid_priv.h 35087 2016-08-13 21:20:46Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Prototypes, and definitions for of GDAL scattered data gridder.
@@ -27,9 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef GDALGRID_PRIV_H
+#define GDALGRID_PRIV_H
+
 #include "cpl_error.h"
 #include "cpl_quad_tree.h"
 
+//! @cond Doxygen_Suppress
+
 typedef struct
 {
     const double* padfX;
@@ -46,9 +51,9 @@ typedef struct
 {
     CPLQuadTree* hQuadTree;
     double       dfInitialSearchRadius;
-    const float *pafX;
-    const float *pafY;
-    const float *pafZ;
+    float *pafX; // Aligned to be usable with AVX
+    float *pafY;
+    float *pafZ;
     GDALTriangulation* psTriangulation;
     int                nInitialFacetIdx;
     /*! Weighting power divided by 2 (pre-computation). */
@@ -60,8 +65,6 @@ typedef struct
 } GDALGridExtraParameters;
 
 #ifdef HAVE_SSE_AT_COMPILE_TIME
-int CPLHaveRuntimeSSE();
-
 CPLErr
 GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE(
                                         const void *poOptions,
@@ -75,8 +78,6 @@ GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE(
 #endif
 
 #ifdef HAVE_AVX_AT_COMPILE_TIME
-int CPLHaveRuntimeAVX();
-
 CPLErr GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
                                         const void *poOptions,
                                         GUInt32 nPoints,
@@ -87,20 +88,7 @@ CPLErr GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX(
                                         double *pdfValue,
                                         void* hExtraParamsIn );
 #endif
-#if defined(__GNUC__)
-#if defined(__x86_64)
-#define GCC_CPUID(level, a, b, c, d)            \
-  __asm__ ("xchgq %%rbx, %q1\n"                 \
-           "cpuid\n"                            \
-           "xchgq %%rbx, %q1"                   \
-       : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
-       : "0" (level))
-#else
-#define GCC_CPUID(level, a, b, c, d)            \
-  __asm__ ("xchgl %%ebx, %1\n"                  \
-           "cpuid\n"                            \
-           "xchgl %%ebx, %1"                    \
-       : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
-       : "0" (level))
-#endif
-#endif
+
+//! @endcond
+
+#endif // GDALGRID_PRIV_H
diff --git a/alg/gdalgridavx.cpp b/alg/gdalgridavx.cpp
index 0e50831..a330a46 100644
--- a/alg/gdalgridavx.cpp
+++ b/alg/gdalgridavx.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalgridavx.cpp 31631 2015-11-18 17:55:29Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Implementation of GDAL scattered data gridder.
@@ -33,7 +32,7 @@
 #ifdef HAVE_AVX_AT_COMPILE_TIME
 #include <immintrin.h>
 
-CPL_CVSID("$Id: gdalgridavx.cpp 31631 2015-11-18 17:55:29Z rouault $");
+CPL_CVSID("$Id: gdalgridavx.cpp 34562 2016-07-06 06:09:41Z goatbar $");
 
 /************************************************************************/
 /*         GDALGridInverseDistanceToAPower2NoSmoothingNoSearchAVX()     */
diff --git a/alg/gdalgridsse.cpp b/alg/gdalgridsse.cpp
index d6cf9f3..b69090a 100644
--- a/alg/gdalgridsse.cpp
+++ b/alg/gdalgridsse.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalgridsse.cpp 29913 2015-08-29 21:16:44Z rouault $
  *
  * Project:  GDAL Gridding API.
  * Purpose:  Implementation of GDAL scattered data gridder.
@@ -33,7 +32,7 @@
 #ifdef HAVE_SSE_AT_COMPILE_TIME
 #include <xmmintrin.h>
 
-CPL_CVSID("$Id: gdalgridsse.cpp 29913 2015-08-29 21:16:44Z rouault $");
+CPL_CVSID("$Id: gdalgridsse.cpp 35882 2016-10-24 04:10:14Z goatbar $");
 
 /************************************************************************/
 /*         GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE()     */
@@ -174,5 +173,4 @@ GDALGridInverseDistanceToAPower2NoSmoothingNoSearchSSE(
     return CE_None;
 }
 
-
 #endif /* HAVE_SSE_AT_COMPILE_TIME */
diff --git a/alg/gdalmatching.cpp b/alg/gdalmatching.cpp
index 41ad625..a2715d4 100644
--- a/alg/gdalmatching.cpp
+++ b/alg/gdalmatching.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL
  * Purpose:  GDAL Wrapper for image matching via correlation algorithm.
@@ -31,7 +30,11 @@
 #include "gdal_alg.h"
 #include "gdal_simplesurf.h"
 
-CPL_CVSID("$Id");
+//! @cond Doxygen_Suppress
+CPL_CVSID("$Id: gdalmatching.cpp 36718 2016-12-06 04:46:30Z goatbar $");
+//! @endcond
+
+// TODO(schwehr): What?  This below: "0,001"
 
 /**
  * @file
@@ -42,42 +45,48 @@ CPL_CVSID("$Id");
  * Provides capability for detection feature points
  * and finding equal points on different images.
  * As original, this realization is scale invariant, but sensitive to rotation.
- * Images should have similar rotation angles (maximum difference is up to 10-15 degrees),
- * otherwise algorithm produces incorrect and very unstable results.
+ * Images should have similar rotation angles (maximum difference is up to 10-15
+ * degrees), otherwise algorithm produces incorrect and very unstable results.
  */
 
 /**
- * Detect feature points on provided image. Please carefully read documentation below.
+ * Detect feature points on provided image. Please carefully read documentation
+ * below.
  *
  * @param poDataset Image on which feature points will be detected
- * @param panBands Array of 3 raster bands numbers, for Red, Green, Blue bands (in that order)
+ * @param panBands Array of 3 raster bands numbers, for Red, Green, Blue bands
+ * (in that order)
  * @param nOctaveStart Number of bottom octave. Octave numbers starts from one.
  * This value directly and strongly affects to amount of recognized points
- * @param nOctaveEnd Number of top octave. Should be equal or greater than octaveStart
- * @param dfThreshold Value from 0 to 1. Threshold for feature point recognition.
- * Number of detected points is larger if threshold is lower
+ * @param nOctaveEnd Number of top octave. Should be equal or greater than
+ * octaveStart
+ * @param dfThreshold Value from 0 to 1. Threshold for feature point
+ * recognition.  Number of detected points is larger if threshold is lower
  *
  * @see GDALFeaturePoint, GDALSimpleSURF class for details.
  *
  * @note Every octave finds points in specific size. For small images
  * use small octave numbers, for high resolution - large.
  * For 1024x1024 images it's normal to use any octave numbers from range 1-6.
- * (for example, octave start - 1, octave end - 3, or octave start - 2, octave end - 2.)
+ * (for example, octave start - 1, octave end - 3, or octave start - 2, octave
+ * end - 2.)
  * For larger images, try 1-10 range or even higher.
- * Pay attention that number of detected point decreases quickly per octave
- * for particular image. Algorithm finds more points in case of small octave number.
+ * Pay attention that number of detected point decreases quickly per octave for
+ * particular image. Algorithm finds more points in case of small octave number.
  * If method detects nothing, reduce octave start value.
- * In addition, if many feature points are required (the largest possible amount),
- * use the lowest octave start value (1) and wide octave range.
+ * In addition, if many feature points are required (the largest possible
+ * amount), use the lowest octave start value (1) and wide octave range.
  *
  * @note Typical threshold's value is 0,001. It's pretty good for all images.
- * But this value depends on image's nature and may be various in each particular case.
+ * But this value depends on image's nature and may be various in each
+ * particular case.
  * For example, value can be 0,002 or 0,005.
  * Notice that number of detected points is larger if threshold is lower.
- * But with high threshold feature points will be better - "stronger", more "unique" and distinctive.
+ * But with high threshold feature points will be better - "stronger", more
+ * "unique" and distinctive.
  *
- * Feel free to experiment with parameters, because character, robustness and number of points
- * entirely depend on provided range of octaves and threshold.
+ * Feel free to experiment with parameters, because character, robustness and
+ * number of points entirely depend on provided range of octaves and threshold.
  *
  * NOTICE that every octave requires time to compute. Use a little range
  * or only one octave, if execution time is significant.
@@ -86,31 +95,31 @@ CPL_CVSID("$Id");
  */
 
 static std::vector<GDALFeaturePoint> *
-GatherFeaturePoints(GDALDataset* poDataset, int* panBands,
-                    int nOctaveStart, int nOctaveEnd, double dfThreshold)
+GatherFeaturePoints( GDALDataset* poDataset, int* panBands,
+                     int nOctaveStart, int nOctaveEnd, double dfThreshold )
 {
-    if (poDataset == NULL)
+    if( poDataset == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "GDALDataset isn't specified");
         return NULL;
     }
 
-    if (panBands == NULL)
+    if( panBands == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Raster bands are not specified");
         return NULL;
     }
 
-    if (nOctaveStart <= 0 || nOctaveEnd < 0 ||
-        nOctaveStart > nOctaveEnd)
+    if( nOctaveStart <= 0 || nOctaveEnd < 0 ||
+        nOctaveStart > nOctaveEnd )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Octave numbers are invalid");
         return NULL;
     }
 
-    if (dfThreshold < 0)
+    if( dfThreshold < 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Threshold have to be greater than zero");
@@ -124,45 +133,45 @@ GatherFeaturePoints(GDALDataset* poDataset, int* panBands,
     const int nWidth = poRstRedBand->GetXSize();
     const int nHeight = poRstRedBand->GetYSize();
 
-    if (nWidth == 0 || nHeight == 0)
+    if( nWidth == 0 || nHeight == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Must have non-zero width and height.");
         return NULL;
     }
 
-    // Allocate memory for grayscale image
+    // Allocate memory for grayscale image.
     double **padfImg = new double*[nHeight];
-    for (int i = 0; ;)
+    for( int i = 0; ; )
     {
         padfImg[i] = new double[nWidth];
-        for (int j = 0; j < nWidth; ++j)
+        for( int j = 0; j < nWidth; ++j )
           padfImg[i][j] = 0.0;
         ++i;
         if( i == nHeight )
             break;
     }
 
-    // Create grayscale image
+    // Create grayscale image.
     GDALSimpleSURF::ConvertRGBToLuminosity(
         poRstRedBand, poRstGreenBand, poRstBlueBand, nWidth, nHeight,
         padfImg, nHeight, nWidth);
 
-    // Prepare integral image
+    // Prepare integral image.
     GDALIntegralImage *poImg = new GDALIntegralImage();
     poImg->Initialize((const double**)padfImg, nHeight, nWidth);
 
-    // Get feature points
+    // Get feature points.
     GDALSimpleSURF *poSurf = new GDALSimpleSURF(nOctaveStart, nOctaveEnd);
 
     std::vector<GDALFeaturePoint> *poCollection =
         poSurf->ExtractFeaturePoints(poImg, dfThreshold);
 
-    // Clean up
+    // Clean up.
     delete poImg;
     delete poSurf;
 
-    for (int i = 0; i < nHeight; ++i)
+    for( int i = 0; i < nHeight; ++i )
         delete[] padfImg[i];
 
     delete[] padfImg;
@@ -174,6 +183,7 @@ GatherFeaturePoints(GDALDataset* poDataset, int* panBands,
 /*                     GDALComputeMatchingPoints()                      */
 /************************************************************************/
 
+/** GDALComputeMatchingPoints. TODO document */
 GDAL_GCP CPL_DLL *
 GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
                            GDALDatasetH hSecondImage,
@@ -187,14 +197,13 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
 /* -------------------------------------------------------------------- */
     int nOctaveStart, nOctaveEnd;
     double dfSURFThreshold;
-    double dfMatchingThreshold = 0.015;
 
     nOctaveStart =atoi(CSLFetchNameValueDef(papszOptions, "OCTAVE_START", "2"));
     nOctaveEnd = atoi(CSLFetchNameValueDef(papszOptions, "OCTAVE_END", "2"));
 
     dfSURFThreshold = CPLAtof(
         CSLFetchNameValueDef(papszOptions, "SURF_THRESHOLD", "0.001"));
-    dfMatchingThreshold = CPLAtof(
+    const double dfMatchingThreshold = CPLAtof(
         CSLFetchNameValueDef(papszOptions, "MATCHING_THRESHOLD", "0.015"));
 
 /* -------------------------------------------------------------------- */
@@ -202,41 +211,33 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
 /*      limited to using RGB input so if we have one band only treat    */
 /*      it as red=green=blue=band 1.  Disallow non eightbit imagery.    */
 /* -------------------------------------------------------------------- */
-    int anBandMap1[3], anBandMap2[3];
-
+    int anBandMap1[3] = { 1, 1, 1 };
     if( GDALGetRasterCount(hFirstImage) >= 3 )
     {
-        anBandMap1[0] = 1;
         anBandMap1[1] = 2;
         anBandMap1[2] = 3;
     }
-    else
-    {
-        anBandMap1[0] = anBandMap1[1] = anBandMap1[2] = 1;
-    }
 
+    int anBandMap2[3] = { 1, 1, 1 };
     if( GDALGetRasterCount(hSecondImage) >= 3 )
     {
-        anBandMap2[0] = 1;
         anBandMap2[1] = 2;
         anBandMap2[2] = 3;
     }
-    else
-    {
-        anBandMap2[0] = anBandMap2[1] = anBandMap2[2] = 1;
-    }
 
 /* -------------------------------------------------------------------- */
 /*      Collect reference points on each image.                         */
 /* -------------------------------------------------------------------- */
     std::vector<GDALFeaturePoint> *poFPCollection1 =
-        GatherFeaturePoints((GDALDataset *) hFirstImage, anBandMap1,
+        GatherFeaturePoints(reinterpret_cast<GDALDataset *>(hFirstImage),
+                            anBandMap1,
                             nOctaveStart, nOctaveEnd, dfSURFThreshold);
     if( poFPCollection1 == NULL )
         return NULL;
 
     std::vector<GDALFeaturePoint> *poFPCollection2 =
-        GatherFeaturePoints((GDALDataset *) hSecondImage, anBandMap2,
+        GatherFeaturePoints(reinterpret_cast<GDALDataset *>(hSecondImage),
+                            anBandMap2,
                             nOctaveStart, nOctaveEnd,
                             dfSURFThreshold);
 
@@ -266,11 +267,12 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
 /*      Translate these into GCPs - but with the output coordinate      */
 /*      system being pixel/line on the second image.                    */
 /* -------------------------------------------------------------------- */
-    GDAL_GCP *pasGCPList = (GDAL_GCP*) CPLCalloc(*pnGCPCount, sizeof(GDAL_GCP));
+    GDAL_GCP *pasGCPList =
+        static_cast<GDAL_GCP*>(CPLCalloc(*pnGCPCount, sizeof(GDAL_GCP)));
 
     GDALInitGCPs(*pnGCPCount, pasGCPList);
 
-    for (int i=0; i < *pnGCPCount; i++)
+    for( int i=0; i < *pnGCPCount; i++ )
     {
         GDALFeaturePoint *poPoint1 = oMatchPairs[i*2  ];
         GDALFeaturePoint *poPoint2 = oMatchPairs[i*2+1];
@@ -292,15 +294,15 @@ GDALComputeMatchingPoints( GDALDatasetH hFirstImage,
 /*      output image.                                                   */
 /* -------------------------------------------------------------------- */
     const bool bGeorefOutput =
-        CPLTestBool(CSLFetchNameValueDef(papszOptions,"OUTPUT_GEOREF","NO"));
+        CPLTestBool(CSLFetchNameValueDef(papszOptions, "OUTPUT_GEOREF", "NO"));
 
     if( bGeorefOutput )
     {
-        double adfGeoTransform[6];
+        double adfGeoTransform[6] = {};
 
         GDALGetGeoTransform( hSecondImage, adfGeoTransform );
 
-        for (int i=0; i < *pnGCPCount; i++)
+        for( int i=0; i < *pnGCPCount; i++ )
         {
             GDALApplyGeoTransform(adfGeoTransform,
                                   pasGCPList[i].dfGCPX,
diff --git a/alg/gdalmediancut.cpp b/alg/gdalmediancut.cpp
index b37a3c2..944a0e6 100644
--- a/alg/gdalmediancut.cpp
+++ b/alg/gdalmediancut.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalmediancut.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  CIETMap Phase 2
  * Purpose:  Use median cut algorithm to generate an near-optimal PCT for a
@@ -37,19 +36,39 @@
  *
  */
 
-#include "gdal_priv.h"
+#include "cpl_port.h"
 #include "gdal_alg.h"
 #include "gdal_alg_priv.h"
+
+#include <climits>
+#include <cstring>
+
+#include <algorithm>
 #include <limits>
 
-CPL_CVSID("$Id: gdalmediancut.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+
+CPL_CVSID("$Id: gdalmediancut.cpp 36822 2016-12-12 11:18:45Z rouault $");
 
-#define HISTOGRAM(h,n,r,g,b) h[((r)*(n)+(g))*(n)+(b)]
+template<typename T> static T* HISTOGRAM( T *h, int n, int r, int g, int b )
+{
+    const int index = (r * n + g) * n + b;
+    return &h[index];
+}
 
-#define MAKE_COLOR_CODE(r,g,b) ((r)+(g)*256+(b)*256*256)
+static int MAKE_COLOR_CODE( int r, int g, int b )
+{
+    return r + g * 256 + b * 256 * 256;
+}
 
-/* NOTE: if changing the size of this structure, edit */
-/* MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 in gdal_alg_priv.h and take into account ColorIndex in gdaldither.cpp */
+// NOTE: If changing the size of this structure, edit
+// MEDIAN_CUT_AND_DITHER_BUFFER_SIZE_65536 in gdal_alg_priv.h and take into
+// account ColorIndex in gdaldither.cpp.
 typedef struct
 {
     GUInt32 nColorCode;
@@ -60,29 +79,29 @@ typedef struct
     int     nCount3;
 } HashHistogram;
 
-typedef	struct colorbox {
-	struct	colorbox *next, *prev;
-	int	rmin, rmax;
-	int	gmin, gmax;
-	int	bmin, bmax;
-	GUIntBig	total;
+typedef struct colorbox {
+    struct colorbox *next, *prev;
+    int rmin, rmax;
+    int gmin, gmax;
+    int bmin, bmax;
+    GUIntBig total;
 } Colorbox;
 
 template<class T>
-static void splitbox(Colorbox* ptr, const T* histogram,
-                     const HashHistogram* psHashHistogram,
-                     int nCLevels,
-                     Colorbox **pfreeboxes, Colorbox **pusedboxes,
-                     GByte* pabyRedBand,
-                     GByte* pabyGreenBand,
-                     GByte* pabyBlueBand, T nPixels);
+static void splitbox( Colorbox* ptr, const T* histogram,
+                      const HashHistogram* psHashHistogram,
+                      int nCLevels,
+                      Colorbox **pfreeboxes, Colorbox **pusedboxes,
+                      GByte* pabyRedBand,
+                      GByte* pabyGreenBand,
+                      GByte* pabyBlueBand, T nPixels );
 
 template<class T>
-static void shrinkbox(Colorbox* box,
-                      const T* histogram,
-                      int nCLevels);
+static void shrinkbox( Colorbox* box,
+                       const T* histogram,
+                       int nCLevels );
 
-static Colorbox* largest_box(Colorbox *usedboxes);
+static Colorbox* largest_box( Colorbox *usedboxes );
 
 /************************************************************************/
 /*                      GDALComputeMedianCutPCT()                       */
@@ -128,7 +147,7 @@ extern "C" int CPL_STDCALL
 GDALComputeMedianCutPCT( GDALRasterBandH hRed,
                          GDALRasterBandH hGreen,
                          GDALRasterBandH hBlue,
-                         int (*pfnIncludePixel)(int,int,void*),
+                         int (*pfnIncludePixel)(int, int, void*),
                          int nColors,
                          GDALColorTableH hColorTable,
                          GDALProgressFunc pfnProgress,
@@ -136,42 +155,44 @@ GDALComputeMedianCutPCT( GDALRasterBandH hRed,
 
 {
     VALIDATE_POINTER1( hRed, "GDALComputeMedianCutPCT", CE_Failure );
-    int nXSize = GDALGetRasterBandXSize( hRed );
-    int nYSize = GDALGetRasterBandYSize( hRed );
+    const int nXSize = GDALGetRasterBandXSize( hRed );
+    const int nYSize = GDALGetRasterBandYSize( hRed );
     if( nYSize == 0 )
         return CE_Failure;
-    if( (GUInt32)nXSize < UINT_MAX / (GUInt32)nYSize )
+    if( static_cast<GUInt32>(nXSize) < UINT_MAX / static_cast<GUInt32>(nYSize) )
     {
         return GDALComputeMedianCutPCTInternal(hRed, hGreen, hBlue,
-                                        NULL, NULL, NULL,
-                                        pfnIncludePixel, nColors,
-                                        5,
-                                        (GUInt32*)NULL,
-                                        hColorTable,
-                                        pfnProgress, pProgressArg);
+                                               NULL, NULL, NULL,
+                                               pfnIncludePixel, nColors,
+                                               5,
+                                               static_cast<GUInt32 *>(NULL),
+                                               hColorTable,
+                                               pfnProgress, pProgressArg);
     }
     else
     {
+#ifdef CPL_HAS_GINT64
         return GDALComputeMedianCutPCTInternal(hRed, hGreen, hBlue,
-                                        NULL, NULL, NULL,
-                                        pfnIncludePixel, nColors,
-                                        5,
-                                        (GUIntBig*)NULL,
-                                        hColorTable,
-                                        pfnProgress, pProgressArg);
+                                               NULL, NULL, NULL,
+                                               pfnIncludePixel, nColors,
+                                               5,
+                                               static_cast<GUIntBig * >(NULL),
+                                               hColorTable,
+                                               pfnProgress, pProgressArg);
+#else
+        return CE_Failure;
+#endif
     }
 }
 
-/*static int nMaxCollisions = 0;*/
-
-static inline int FindColorCount(const HashHistogram* psHashHistogram,
-                                 GUInt32 nColorCode)
+static inline int FindColorCount( const HashHistogram* psHashHistogram,
+                                  GUInt32 nColorCode )
 {
+
     GUInt32 nIdx = nColorCode % PRIME_FOR_65536;
-    /*int nCollisions = 0; */
     while( true )
     {
-        if( (int)psHashHistogram[nIdx].nColorCode < 0 )
+        if( static_cast<int>(psHashHistogram[nIdx].nColorCode) < 0 )
         {
             return 0;
         }
@@ -179,7 +200,7 @@ static inline int FindColorCount(const HashHistogram* psHashHistogram,
         {
             return psHashHistogram[nIdx].nCount;
         }
-        if( (int)psHashHistogram[nIdx].nColorCode2 < 0 )
+        if( static_cast<int>(psHashHistogram[nIdx].nColorCode2) < 0 )
         {
             return 0;
         }
@@ -187,7 +208,7 @@ static inline int FindColorCount(const HashHistogram* psHashHistogram,
         {
             return psHashHistogram[nIdx].nCount2;
         }
-        if( (int)psHashHistogram[nIdx].nColorCode3 < 0 )
+        if( static_cast<int>(psHashHistogram[nIdx].nColorCode3) < 0 )
         {
             return 0;
         }
@@ -198,38 +219,30 @@ static inline int FindColorCount(const HashHistogram* psHashHistogram,
 
         do
         {
-            /*nCollisions ++;*/
-            nIdx+=257;
+            nIdx += 257;
             if( nIdx >= PRIME_FOR_65536 )
                 nIdx -= PRIME_FOR_65536;
         }
-        while( (int)psHashHistogram[nIdx].nColorCode >= 0 &&
-                psHashHistogram[nIdx].nColorCode != nColorCode &&
-                (int)psHashHistogram[nIdx].nColorCode2 >= 0 &&
-                psHashHistogram[nIdx].nColorCode2 != nColorCode&&
-                (int)psHashHistogram[nIdx].nColorCode3 >= 0 &&
-                psHashHistogram[nIdx].nColorCode3 != nColorCode );
-        /*if( nCollisions > nMaxCollisions )
-        {
-            nMaxCollisions = nCollisions;
-            printf("median cut: nCollisions = %d for R=%d,G=%d,B=%d\n",
-                    nCollisions, nColorCode&0xFF, (nColorCode>>8)&0xFF, (nColorCode>>16)&0xFF);
-        }*/
+        while( static_cast<int>(psHashHistogram[nIdx].nColorCode) >= 0 &&
+               psHashHistogram[nIdx].nColorCode != nColorCode &&
+               static_cast<int>(psHashHistogram[nIdx].nColorCode2) >= 0 &&
+               psHashHistogram[nIdx].nColorCode2 != nColorCode&&
+               static_cast<int>(psHashHistogram[nIdx].nColorCode3) >= 0 &&
+               psHashHistogram[nIdx].nColorCode3 != nColorCode );
     }
 }
 
-static inline int* FindAndInsertColorCount(HashHistogram* psHashHistogram,
-                           GUInt32 nColorCode)
+static inline int*
+FindAndInsertColorCount( HashHistogram* psHashHistogram, GUInt32 nColorCode )
 {
     GUInt32 nIdx = nColorCode % PRIME_FOR_65536;
-    /*int nCollisions = 0;*/
     while( true )
     {
         if( psHashHistogram[nIdx].nColorCode == nColorCode )
         {
             return &(psHashHistogram[nIdx].nCount);
         }
-        if( (int)psHashHistogram[nIdx].nColorCode < 0 )
+        if( static_cast<int>(psHashHistogram[nIdx].nColorCode) < 0 )
         {
             psHashHistogram[nIdx].nColorCode = nColorCode;
             psHashHistogram[nIdx].nCount = 0;
@@ -239,7 +252,7 @@ static inline int* FindAndInsertColorCount(HashHistogram* psHashHistogram,
         {
             return &(psHashHistogram[nIdx].nCount2);
         }
-        if( (int)psHashHistogram[nIdx].nColorCode2 < 0 )
+        if( static_cast<int>(psHashHistogram[nIdx].nColorCode2) < 0 )
         {
             psHashHistogram[nIdx].nColorCode2 = nColorCode;
             psHashHistogram[nIdx].nCount2 = 0;
@@ -249,7 +262,7 @@ static inline int* FindAndInsertColorCount(HashHistogram* psHashHistogram,
         {
             return &(psHashHistogram[nIdx].nCount3);
         }
-        if( (int)psHashHistogram[nIdx].nColorCode3 < 0 )
+        if( static_cast<int>(psHashHistogram[nIdx].nColorCode3) < 0 )
         {
             psHashHistogram[nIdx].nColorCode3 = nColorCode;
             psHashHistogram[nIdx].nCount3 = 0;
@@ -258,87 +271,82 @@ static inline int* FindAndInsertColorCount(HashHistogram* psHashHistogram,
 
         do
         {
-            /*nCollisions ++;*/
             nIdx+=257;
             if( nIdx >= PRIME_FOR_65536 )
                 nIdx -= PRIME_FOR_65536;
         }
-        while( (int)psHashHistogram[nIdx].nColorCode >= 0 &&
-                psHashHistogram[nIdx].nColorCode != nColorCode &&
-                (int)psHashHistogram[nIdx].nColorCode2 >= 0 &&
-                psHashHistogram[nIdx].nColorCode2 != nColorCode&&
-                (int)psHashHistogram[nIdx].nColorCode3 >= 0 &&
-                psHashHistogram[nIdx].nColorCode3 != nColorCode );
-        /*if( nCollisions > nMaxCollisions )
-        {
-            nMaxCollisions = nCollisions;
-            printf("median cut: nCollisions = %d for R=%d,G=%d,B=%d\n",
-                    nCollisions, nColorCode&0xFF, (nColorCode>>8)&0xFF, (nColorCode>>16)&0xFF);
-        }*/
+        while( static_cast<int>(psHashHistogram[nIdx].nColorCode) >= 0 &&
+               psHashHistogram[nIdx].nColorCode != nColorCode &&
+               static_cast<int>(psHashHistogram[nIdx].nColorCode2) >= 0 &&
+               psHashHistogram[nIdx].nColorCode2 != nColorCode&&
+               static_cast<int>(psHashHistogram[nIdx].nColorCode3) >= 0 &&
+               psHashHistogram[nIdx].nColorCode3 != nColorCode );
     }
 }
 
 template<class T> int
-GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
-                           GDALRasterBandH hGreen,
-                           GDALRasterBandH hBlue,
-                           GByte* pabyRedBand,
-                           GByte* pabyGreenBand,
-                           GByte* pabyBlueBand,
-                           int (*pfnIncludePixel)(int,int,void*),
-                           int nColors,
-                           int nBits,
-                           T* panHistogram, /* NULL, or at least of size (1<<nBits)^3 * sizeof(T) bytes */
-                           GDALColorTableH hColorTable,
-                           GDALProgressFunc pfnProgress,
-                           void * pProgressArg )
+GDALComputeMedianCutPCTInternal(
+    GDALRasterBandH hRed,
+    GDALRasterBandH hGreen,
+    GDALRasterBandH hBlue,
+    GByte* pabyRedBand,
+    GByte* pabyGreenBand,
+    GByte* pabyBlueBand,
+    int (*pfnIncludePixel)(int, int, void*),
+    int nColors,
+    int nBits,
+    T* panHistogram,  // NULL, or >= size (1<<nBits)^3 * sizeof(T) bytes.
+    GDALColorTableH hColorTable,
+    GDALProgressFunc pfnProgress,
+    void * pProgressArg )
 
 {
     VALIDATE_POINTER1( hRed, "GDALComputeMedianCutPCT", CE_Failure );
     VALIDATE_POINTER1( hGreen, "GDALComputeMedianCutPCT", CE_Failure );
     VALIDATE_POINTER1( hBlue, "GDALComputeMedianCutPCT", CE_Failure );
 
-    int		nXSize, nYSize;
     CPLErr err = CE_None;
 
 /* -------------------------------------------------------------------- */
 /*      Validate parameters.                                            */
 /* -------------------------------------------------------------------- */
-    nXSize = GDALGetRasterBandXSize( hRed );
-    nYSize = GDALGetRasterBandYSize( hRed );
+    const int nXSize = GDALGetRasterBandXSize( hRed );
+    const int nYSize = GDALGetRasterBandYSize( hRed );
 
     if( GDALGetRasterBandXSize( hGreen ) != nXSize
         || GDALGetRasterBandYSize( hGreen ) != nYSize
         || GDALGetRasterBandXSize( hBlue ) != nXSize
         || GDALGetRasterBandYSize( hBlue ) != nYSize )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
-                  "Green or blue band doesn't match size of red band.\n" );
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "Green or blue band doesn't match size of red band.");
 
         return CE_Failure;
     }
 
     if( pfnIncludePixel != NULL )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALComputeMedianCutPCT() doesn't currently support "
-                  " pfnIncludePixel function." );
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "GDALComputeMedianCutPCT() doesn't currently support "
+                 "pfnIncludePixel function.");
 
         return CE_Failure;
     }
 
-    if ( nColors <= 0 )
+    if( nColors <= 0 )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALComputeMedianCutPCT() : nColors must be strictly greater than 1." );
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "GDALComputeMedianCutPCT(): "
+                 "nColors must be strictly greater than 1.");
 
         return CE_Failure;
     }
 
-    if ( nColors > 256 )
+    if( nColors > 256 )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALComputeMedianCutPCT() : nColors must be lesser than or equal to 256." );
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "GDALComputeMedianCutPCT(): "
+                 "nColors must be lesser than or equal to 256.");
 
         return CE_Failure;
     }
@@ -349,40 +357,38 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
 /* ==================================================================== */
 /*      STEP 1: create empty boxes.                                     */
 /* ==================================================================== */
-    int	     i;
-    Colorbox *box_list, *ptr;
-    T* histogram;
-    Colorbox *freeboxes;
-    Colorbox *usedboxes;
-    int nCLevels = 1 << nBits;
-    int nColorShift = 8 - nBits;
-    int nColorCounter = 0;
-    GByte anRed[256], anGreen[256], anBlue[256];
-    T nPixels = 0;
-    HashHistogram* psHashHistogram = NULL;
-
-    if( (GUInt32)nXSize > std::numeric_limits<T>::max() / (GUInt32)nYSize )
+    if( static_cast<GUInt32>(nXSize) >
+        std::numeric_limits<T>::max() / static_cast<GUInt32>(nYSize) )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
-                 "GDALComputeMedianCutPCTInternal() not called with large enough type");
+                 "GDALComputeMedianCutPCTInternal() not called "
+                 "with large enough type");
     }
 
+    T nPixels = 0;
     if( nBits == 8 && pabyRedBand != NULL && pabyGreenBand != NULL &&
-        pabyBlueBand != NULL && (GUInt32)nXSize <= std::numeric_limits<T>::max() / (GUInt32)nYSize )
+        pabyBlueBand != NULL &&
+        static_cast<GUInt32>(nXSize) <=
+        std::numeric_limits<T>::max() / static_cast<GUInt32>(nYSize) )
     {
-        nPixels = (T)nXSize * (T)nYSize;
+      nPixels = static_cast<T>(nXSize) * static_cast<T>(nYSize);
     }
 
+    const int nCLevels = 1 << nBits;
+    T* histogram = NULL;
+    HashHistogram* psHashHistogram = NULL;
     if( panHistogram )
     {
-        if( nBits == 8 && (GUIntBig)nXSize * nYSize <= 65536 )
+        if( nBits == 8 && static_cast<GUIntBig>(nXSize) * nYSize <= 65536 )
         {
-            /* If the image is small enough, then the number of colors */
-            /* will be limited and using a hashmap, rather than a full table */
-            /* will be more efficient */
+            // If the image is small enough, then the number of colors
+            // will be limited and using a hashmap, rather than a full table
+            // will be more efficient.
             histogram = NULL;
             psHashHistogram = (HashHistogram*)panHistogram;
-            memset(psHashHistogram, 0xFF, sizeof(HashHistogram) * PRIME_FOR_65536);
+            memset(psHashHistogram,
+                   0xFF,
+                   sizeof(HashHistogram) * PRIME_FOR_65536);
         }
         else
         {
@@ -392,17 +398,20 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
     }
     else
     {
-        histogram = (T*) VSI_CALLOC_VERBOSE(nCLevels*nCLevels*nCLevels,sizeof(T));
+        histogram = static_cast<T*>(
+            VSI_CALLOC_VERBOSE(nCLevels * nCLevels * nCLevels, sizeof(T)));
         if( histogram == NULL )
         {
             return CE_Failure;
         }
     }
-    usedboxes = NULL;
-    box_list = freeboxes = (Colorbox *)CPLMalloc(nColors*sizeof (Colorbox));
+    Colorbox *box_list =
+        static_cast<Colorbox *>(CPLMalloc(nColors*sizeof (Colorbox)));
+    Colorbox *freeboxes = box_list;
     freeboxes[0].next = &freeboxes[1];
     freeboxes[0].prev = NULL;
-    for (i = 1; i < nColors-1; ++i) {
+    for( int i = 1; i < nColors-1; ++i )
+    {
         freeboxes[i].next = &freeboxes[i+1];
         freeboxes[i].prev = &freeboxes[i-1];
     }
@@ -412,43 +421,54 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
 /* ==================================================================== */
 /*      Build histogram.                                                */
 /* ==================================================================== */
-    GByte	*pabyRedLine, *pabyGreenLine, *pabyBlueLine;
-    int		iLine, iPixel;
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the box datastructures.                              */
 /* -------------------------------------------------------------------- */
-    ptr = freeboxes;
+    Colorbox *ptr = freeboxes;
     freeboxes = ptr->next;
-    if (freeboxes)
+    if( freeboxes )
         freeboxes->prev = NULL;
+    Colorbox *usedboxes = NULL;  // TODO(schwehr): What?
     ptr->next = usedboxes;
     usedboxes = ptr;
-    if (ptr->next)
+    if( ptr->next )
         ptr->next->prev = ptr;
 
-    ptr->rmin = ptr->gmin = ptr->bmin = 999;
-    ptr->rmax = ptr->gmax = ptr->bmax = -1;
-    ptr->total = (GUIntBig)nXSize * (GUIntBig)nYSize;
+    ptr->rmin = 999;
+    ptr->gmin = 999;
+    ptr->bmin = 999;
+    ptr->rmax = -1;
+    ptr->gmax = -1;
+    ptr->bmax = -1;
+    ptr->total = static_cast<GUIntBig>(nXSize) * static_cast<GUIntBig>(nYSize);
 
 /* -------------------------------------------------------------------- */
 /*      Collect histogram.                                              */
 /* -------------------------------------------------------------------- */
-    pabyRedLine = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
-    pabyGreenLine = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
-    pabyBlueLine = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
 
-    if (pabyRedLine == NULL ||
+    // TODO(schwehr): Move these closer to usage after removing gotos.
+    const int nColorShift = 8 - nBits;
+    int nColorCounter = 0;
+    GByte anRed[256] = {};
+    GByte anGreen[256] = {};
+    GByte anBlue[256] = {};
+
+    GByte *pabyRedLine = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize));
+    GByte *pabyGreenLine = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize));
+    GByte *pabyBlueLine = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize));
+
+    if( pabyRedLine == NULL ||
         pabyGreenLine == NULL ||
-        pabyBlueLine == NULL)
+        pabyBlueLine == NULL )
     {
         err = CE_Failure;
         goto end_and_cleanup;
     }
 
-    for( iLine = 0; iLine < nYSize; iLine++ )
+    for( int iLine = 0; iLine < nYSize; iLine++ )
     {
-        if( !pfnProgress( iLine / (double) nYSize,
+        if( !pfnProgress( iLine / static_cast<double>(nYSize),
                           "Generating Histogram", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" );
@@ -467,20 +487,18 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
         if( err != CE_None )
             goto end_and_cleanup;
 
-        for( iPixel = 0; iPixel < nXSize; iPixel++ )
+        for( int iPixel = 0; iPixel < nXSize; iPixel++ )
         {
-            int	nRed, nGreen, nBlue;
+            const int nRed = pabyRedLine[iPixel] >> nColorShift;
+            const int nGreen = pabyGreenLine[iPixel] >> nColorShift;
+            const int nBlue = pabyBlueLine[iPixel] >> nColorShift;
 
-            nRed = pabyRedLine[iPixel] >> nColorShift;
-            nGreen = pabyGreenLine[iPixel] >> nColorShift;
-            nBlue = pabyBlueLine[iPixel] >> nColorShift;
-
-            ptr->rmin = MIN(ptr->rmin, nRed);
-            ptr->gmin = MIN(ptr->gmin, nGreen);
-            ptr->bmin = MIN(ptr->bmin, nBlue);
-            ptr->rmax = MAX(ptr->rmax, nRed);
-            ptr->gmax = MAX(ptr->gmax, nGreen);
-            ptr->bmax = MAX(ptr->bmax, nBlue);
+            ptr->rmin = std::min(ptr->rmin, nRed);
+            ptr->gmin = std::min(ptr->gmin, nGreen);
+            ptr->bmin = std::min(ptr->bmin, nBlue);
+            ptr->rmax = std::max(ptr->rmax, nRed);
+            ptr->gmax = std::max(ptr->gmax, nGreen);
+            ptr->bmax = std::max(ptr->bmax, nBlue);
 
             bool bFirstOccurrence;
             if( psHashHistogram )
@@ -488,13 +506,14 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
                 int* pnColor = FindAndInsertColorCount(psHashHistogram,
                                          MAKE_COLOR_CODE(nRed, nGreen, nBlue));
                 bFirstOccurrence = ( *pnColor == 0 );
-                (*pnColor) ++;
+                (*pnColor)++;
             }
             else
             {
-                T* pnColor = &HISTOGRAM(histogram, nCLevels, nRed, nGreen, nBlue);
+                T* pnColor =
+                    HISTOGRAM(histogram, nCLevels, nRed, nGreen, nBlue);
                 bFirstOccurrence = ( *pnColor == 0 );
-                (*pnColor) ++;
+                (*pnColor)++;
             }
             if( bFirstOccurrence)
             {
@@ -518,14 +537,18 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
 
     if( nColorShift == 0 && nColorCounter <= nColors )
     {
-        //CPLDebug("MEDIAN_CUT", "%d colors found <= %d", nColorCounter, nColors);
-        for(int iColor = 0;iColor<nColorCounter;iColor++)
+#if DEBUG_VERBOSE
+        CPLDebug("MEDIAN_CUT", "%d colors found <= %d", nColorCounter, nColors);
+#endif
+        for( int iColor = 0; iColor < nColorCounter; iColor++ )
         {
-            GDALColorEntry  sEntry;
-            sEntry.c1 = (GByte) anRed[iColor];
-            sEntry.c2 = (GByte) anGreen[iColor];
-            sEntry.c3 = (GByte) anBlue[iColor];
-            sEntry.c4 = 255;
+            const GDALColorEntry sEntry =
+            {
+                static_cast<GByte>(anRed[iColor]),
+                static_cast<GByte>(anGreen[iColor]),
+                static_cast<GByte>(anBlue[iColor]),
+                255
+            };
             GDALSetColorEntry( hColorTable, iColor, &sEntry );
         }
         goto end_and_cleanup;
@@ -535,10 +558,12 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
 /*      STEP 3: continually subdivide boxes until no more free          */
 /*      boxes remain or until all colors assigned.                      */
 /* ==================================================================== */
-    while (freeboxes != NULL) {
+    while( freeboxes != NULL )
+    {
         ptr = largest_box(usedboxes);
-        if (ptr != NULL)
-            splitbox(ptr, histogram, psHashHistogram, nCLevels, &freeboxes, &usedboxes,
+        if( ptr != NULL )
+            splitbox(ptr, histogram, psHashHistogram, nCLevels,
+                     &freeboxes, &usedboxes,
                      pabyRedBand, pabyGreenBand, pabyBlueBand, nPixels);
         else
             freeboxes = NULL;
@@ -547,14 +572,15 @@ GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
 /* ==================================================================== */
 /*      STEP 4: assign colors to all boxes                              */
 /* ==================================================================== */
-    for (i = 0, ptr = usedboxes; ptr != NULL; ++i, ptr = ptr->next)
+    ptr = usedboxes;
+    for( int i = 0; ptr != NULL; ++i, ptr = ptr->next )
     {
-        GDALColorEntry	sEntry;
-
-        sEntry.c1 = (GByte) (((ptr->rmin + ptr->rmax) << nColorShift) / 2);
-        sEntry.c2 = (GByte) (((ptr->gmin + ptr->gmax) << nColorShift) / 2);
-        sEntry.c3 = (GByte) (((ptr->bmin + ptr->bmax) << nColorShift) / 2);
-        sEntry.c4 = 255;
+        const GDALColorEntry sEntry = {
+            static_cast<GByte>(((ptr->rmin + ptr->rmax) << nColorShift) / 2),
+            static_cast<GByte>(((ptr->gmin + ptr->gmax) << nColorShift) / 2),
+            static_cast<GByte>(((ptr->bmin + ptr->bmax) << nColorShift) / 2),
+            255
+        };
         GDALSetColorEntry( hColorTable, i, &sEntry );
     }
 
@@ -563,9 +589,10 @@ end_and_cleanup:
     CPLFree( pabyGreenLine );
     CPLFree( pabyBlueLine );
 
-    /* We're done with the boxes now */
+    // We're done with the boxes now.
     CPLFree(box_list);
-    freeboxes = usedboxes = NULL;
+    freeboxes = NULL;
+    usedboxes = NULL;
 
     if( panHistogram == NULL )
         CPLFree( histogram );
@@ -578,34 +605,37 @@ end_and_cleanup:
 /************************************************************************/
 
 static Colorbox *
-largest_box(Colorbox *usedboxes)
+largest_box( Colorbox *usedboxes )
 {
     Colorbox *b = NULL;
 
-    for (Colorbox* p = usedboxes; p != NULL; p = p->next)
+    for( Colorbox* p = usedboxes; p != NULL; p = p->next )
     {
-        if ((p->rmax > p->rmin || p->gmax > p->gmin ||
-             p->bmax > p->bmin) && (b == NULL || p->total > b->total))
+        if( (p->rmax > p->rmin || p->gmax > p->gmin ||
+             p->bmax > p->bmin) && (b == NULL || p->total > b->total) )
         {
             b = p;
         }
     }
-    return (b);
+    return b;
 }
 
-static void shrinkboxFromBand(Colorbox* ptr,
-                              const GByte* pabyRedBand,
-                              const GByte* pabyGreenBand,
-                              const GByte* pabyBlueBand, GUIntBig nPixels)
+static void shrinkboxFromBand( Colorbox* ptr,
+                               const GByte* pabyRedBand,
+                               const GByte* pabyGreenBand,
+                               const GByte* pabyBlueBand, GUIntBig nPixels )
 {
-    int rmin_new = 255, rmax_new = 0,
-        gmin_new = 255, gmax_new = 0,
-        bmin_new = 255, bmax_new = 0;
-    for(GUIntBig i=0;i<nPixels;i++)
+    int rmin_new = 255;
+    int rmax_new = 0;
+    int gmin_new = 255;
+    int gmax_new = 0;
+    int bmin_new = 255;
+    int bmax_new = 0;
+    for( GUIntBig i = 0; i < nPixels; i++ )
     {
-        int iR = pabyRedBand[i];
-        int iG = pabyGreenBand[i];
-        int iB = pabyBlueBand[i];
+        const int iR = pabyRedBand[i];
+        const int iG = pabyGreenBand[i];
+        const int iB = pabyBlueBand[i];
         if( iR >= ptr->rmin && iR <= ptr->rmax &&
             iG >= ptr->gmin && iG <= ptr->gmax &&
             iB >= ptr->bmin && iB <= ptr->bmax )
@@ -619,9 +649,12 @@ static void shrinkboxFromBand(Colorbox* ptr,
         }
     }
 
-    CPLAssert(rmin_new >= ptr->rmin && rmin_new <= rmax_new && rmax_new <= ptr->rmax);
-    CPLAssert(gmin_new >= ptr->gmin && gmin_new <= gmax_new && gmax_new <= ptr->gmax);
-    CPLAssert(bmin_new >= ptr->bmin && bmin_new <= bmax_new && bmax_new <= ptr->bmax);
+    CPLAssert(rmin_new >= ptr->rmin && rmin_new <= rmax_new &&
+              rmax_new <= ptr->rmax);
+    CPLAssert(gmin_new >= ptr->gmin && gmin_new <= gmax_new &&
+              gmax_new <= ptr->gmax);
+    CPLAssert(bmin_new >= ptr->bmin && bmin_new <= bmax_new &&
+              bmax_new <= ptr->bmax);
     ptr->rmin = rmin_new;
     ptr->rmax = rmax_new;
     ptr->gmin = gmin_new;
@@ -630,21 +663,20 @@ static void shrinkboxFromBand(Colorbox* ptr,
     ptr->bmax = bmax_new;
 }
 
-static void shrinkboxFromHashHistogram(Colorbox* box,
-                                       const HashHistogram* psHashHistogram)
+static void shrinkboxFromHashHistogram( Colorbox* box,
+                                        const HashHistogram* psHashHistogram )
 {
-    int ir, ig, ib;
-    //int count_iter;
-
-    if (box->rmax > box->rmin) {
-        //count_iter = 0;
-        for (ir = box->rmin; ir <= box->rmax; ++ir) {
-            for (ig = box->gmin; ig <= box->gmax; ++ig) {
-                for (ib = box->bmin; ib <= box->bmax; ++ib) {
-                    //count_iter ++;
-                    if (FindColorCount(psHashHistogram,
-                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0) {
-                        //if( count_iter > 65536 ) printf("iter rmin=%d\n", count_iter);
+    if( box->rmax > box->rmin )
+    {
+        for( int ir = box->rmin; ir <= box->rmax; ++ir )
+        {
+            for( int ig = box->gmin; ig <= box->gmax; ++ig )
+            {
+                for( int ib = box->bmin; ib <= box->bmax; ++ib )
+                {
+                    if( FindColorCount(psHashHistogram,
+                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0 )
+                    {
                         box->rmin = ir;
                         goto have_rmin;
                     }
@@ -653,16 +685,17 @@ static void shrinkboxFromHashHistogram(Colorbox* box,
         }
     }
     have_rmin:
-    if (box->rmax > box->rmin) {
-        //count_iter = 0;
-        for (ir = box->rmax; ir >= box->rmin; --ir) {
-            for (ig = box->gmin; ig <= box->gmax; ++ig) {
-                ib = box->bmin;
-                for (; ib <= box->bmax; ++ib) {
-                    //count_iter ++;
-                    if (FindColorCount(psHashHistogram,
-                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0) {
-                        //if( count_iter > 65536 ) printf("iter rmax=%d\n", count_iter);
+    if( box->rmax > box->rmin )
+    {
+        for( int ir = box->rmax; ir >= box->rmin; --ir )
+        {
+            for( int ig = box->gmin; ig <= box->gmax; ++ig )
+            {
+                for( int ib = box->bmin; ib <= box->bmax; ++ib )
+                {
+                    if( FindColorCount(psHashHistogram,
+                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0 )
+                    {
                         box->rmax = ir;
                         goto have_rmax;
                     }
@@ -672,15 +705,17 @@ static void shrinkboxFromHashHistogram(Colorbox* box,
     }
 
     have_rmax:
-    if (box->gmax > box->gmin) {
-        //count_iter = 0;
-        for (ig = box->gmin; ig <= box->gmax; ++ig) {
-            for (ir = box->rmin; ir <= box->rmax; ++ir) {
-                for (ib = box->bmin; ib <= box->bmax; ++ib) {
-                    //count_iter ++;
-                    if (FindColorCount(psHashHistogram,
-                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0) {
-                        //if( count_iter > 65536 ) printf("iter gmin=%d\n", count_iter);
+    if( box->gmax > box->gmin )
+    {
+        for( int ig = box->gmin; ig <= box->gmax; ++ig )
+        {
+            for( int ir = box->rmin; ir <= box->rmax; ++ir )
+            {
+                for( int ib = box->bmin; ib <= box->bmax; ++ib )
+                {
+                    if( FindColorCount(psHashHistogram,
+                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0 )
+                    {
                         box->gmin = ig;
                         goto have_gmin;
                     }
@@ -690,16 +725,18 @@ static void shrinkboxFromHashHistogram(Colorbox* box,
     }
 
     have_gmin:
-    if (box->gmax > box->gmin) {
-        //count_iter = 0;
-        for (ig = box->gmax; ig >= box->gmin; --ig) {
-            for (ir = box->rmin; ir <= box->rmax; ++ir) {
-                ib = box->bmin;
-                for (; ib <= box->bmax; ++ib) {
-                    //count_iter ++;
-                    if (FindColorCount(psHashHistogram,
-                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0) {
-                        //if( count_iter > 65536 ) printf("iter gmax=%d\n", count_iter);
+    if( box->gmax > box->gmin )
+    {
+        for( int ig = box->gmax; ig >= box->gmin; --ig)
+        {
+            for( int ir = box->rmin; ir <= box->rmax; ++ir )
+            {
+                int ib = box->bmin;
+                for( ; ib <= box->bmax; ++ib )
+                {
+                    if( FindColorCount(psHashHistogram,
+                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0 )
+                    {
                         box->gmax = ig;
                         goto have_gmax;
                     }
@@ -709,15 +746,17 @@ static void shrinkboxFromHashHistogram(Colorbox* box,
     }
 
     have_gmax:
-    if (box->bmax > box->bmin) {
-        //count_iter = 0;
-        for (ib = box->bmin; ib <= box->bmax; ++ib) {
-            for (ir = box->rmin; ir <= box->rmax; ++ir) {
-                for (ig = box->gmin; ig <= box->gmax; ++ig) {
-                    //count_iter ++;
-                    if (FindColorCount(psHashHistogram,
-                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0) {
-                        //if( count_iter > 65536 ) printf("iter bmin=%d\n", count_iter);
+    if( box->bmax > box->bmin )
+    {
+        for( int ib = box->bmin; ib <= box->bmax; ++ib )
+        {
+            for( int ir = box->rmin; ir <= box->rmax; ++ir )
+            {
+                for( int ig = box->gmin; ig <= box->gmax; ++ig )
+                {
+                    if( FindColorCount(psHashHistogram,
+                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0 )
+                    {
                         box->bmin = ib;
                         goto have_bmin;
                     }
@@ -727,16 +766,17 @@ static void shrinkboxFromHashHistogram(Colorbox* box,
     }
 
     have_bmin:
-    if (box->bmax > box->bmin) {
-        //count_iter = 0;
-        for (ib = box->bmax; ib >= box->bmin; --ib) {
-            for (ir = box->rmin; ir <= box->rmax; ++ir) {
-                ig = box->gmin;
-                for (; ig <= box->gmax; ++ig) {
-                    //count_iter ++;
-                    if (FindColorCount(psHashHistogram,
-                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0) {
-                        //if( count_iter > 65536 ) printf("iter bmax=%d\n", count_iter);
+    if( box->bmax > box->bmin )
+    {
+        for( int ib = box->bmax; ib >= box->bmin; --ib )
+        {
+            for( int ir = box->rmin; ir <= box->rmax; ++ir )
+            {
+                for( int ig = box->gmin; ig <= box->gmax; ++ig )
+                {
+                    if( FindColorCount(psHashHistogram,
+                                       MAKE_COLOR_CODE(ir, ig, ib)) != 0 )
+                    {
                         box->bmax = ib;
                         goto have_bmax;
                     }
@@ -761,45 +801,41 @@ splitbox(Colorbox* ptr, const T* histogram,
          GByte* pabyGreenBand,
          GByte* pabyBlueBand, T nPixels)
 {
-    T		hist2[256];
-    int		first=0, last=0;
-    Colorbox	*new_cb;
-    const T	*iptr;
-    T *histp;
-    int	i, j;
-    int	ir,ig,ib;
-    T sum, sum1, sum2;
+    T hist2[256] = {};
+    int first = 0;
+    int last = 0;
     enum { RED, GREEN, BLUE } axis;
 
-    /*
-     * See which axis is the largest, do a histogram along that
-     * axis.  Split at median point.  Contract both new boxes to
-     * fit points and return
-     */
-    i = ptr->rmax - ptr->rmin;
-    if (i >= ptr->gmax - ptr->gmin  && i >= ptr->bmax - ptr->bmin)
-        axis = RED;
-    else if (ptr->gmax - ptr->gmin >= ptr->bmax - ptr->bmin)
-        axis = GREEN;
-    else
-        axis = BLUE;
-    /* get histogram along longest axis */
-    GUInt32 nIters = (ptr->rmax - ptr->rmin + 1) * (ptr->gmax - ptr->gmin + 1) *
-                 (ptr->bmax - ptr->bmin + 1);
-    //printf("nIters = %d\n", nIters);
-    switch (axis) {
+    // See which axis is the largest, do a histogram along that axis.  Split at
+    // median point.  Contract both new boxes to fit points and return.
+    {
+        int i = ptr->rmax - ptr->rmin;
+        if( i >= ptr->gmax - ptr->gmin  && i >= ptr->bmax - ptr->bmin )
+            axis = RED;
+        else if( ptr->gmax - ptr->gmin >= ptr->bmax - ptr->bmin )
+            axis = GREEN;
+        else
+            axis = BLUE;
+    }
+    // Get histogram along longest axis.
+    const GUInt32 nIters =
+        (ptr->rmax - ptr->rmin + 1) *
+        (ptr->gmax - ptr->gmin + 1) *
+        (ptr->bmax - ptr->bmin + 1);
+
+    switch( axis )
+    {
       case RED:
       {
         if( nPixels != 0 && nIters > nPixels )
         {
-            memset(hist2, 0, sizeof(hist2));
-            const int           rmin = ptr->rmin,
-                                rmax = ptr->rmax,
-                                gmin = ptr->gmin,
-                                gmax = ptr->gmax,
-                                bmin = ptr->bmin,
-                                bmax = ptr->bmax;
-            for(T iPixel=0;iPixel<nPixels;iPixel++)
+            const int rmin = ptr->rmin;
+            const int rmax = ptr->rmax;
+            const int gmin = ptr->gmin;
+            const int gmax = ptr->gmax;
+            const int bmin = ptr->bmin;
+            const int bmax = ptr->bmax;
+            for( T iPixel = 0; iPixel < nPixels; iPixel++ )
             {
                 int iR = pabyRedBand[iPixel];
                 int iG = pabyGreenBand[iPixel];
@@ -808,20 +844,22 @@ splitbox(Colorbox* ptr, const T* histogram,
                     iG >= gmin && iG <= gmax &&
                     iB >= bmin && iB <= bmax )
                 {
-                    hist2[iR] ++;
+                    hist2[iR]++;
                 }
             }
         }
         else if( psHashHistogram )
         {
-            histp = &hist2[ptr->rmin];
-            for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
+            T *histp = &hist2[ptr->rmin];
+            for( int ir = ptr->rmin; ir <= ptr->rmax; ++ir )
+            {
                 *histp = 0;
-                for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
-                    for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
+                for( int ig = ptr->gmin; ig <= ptr->gmax; ++ig )
+                {
+                    for( int ib = ptr->bmin; ib <= ptr->bmax; ++ib )
                     {
                         *histp += FindColorCount(psHashHistogram,
-                                       MAKE_COLOR_CODE(ir, ig, ib));
+                                                 MAKE_COLOR_CODE(ir, ig, ib));
                     }
                 }
                 histp++;
@@ -829,12 +867,15 @@ splitbox(Colorbox* ptr, const T* histogram,
         }
         else
         {
-            histp = &hist2[ptr->rmin];
-            for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
+            T *histp = &hist2[ptr->rmin];
+            for( int ir = ptr->rmin; ir <= ptr->rmax; ++ir )
+            {
                 *histp = 0;
-                for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
-                    iptr = &HISTOGRAM(histogram,nCLevels,ir,ig,ptr->bmin);
-                    for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
+                for( int ig = ptr->gmin; ig <= ptr->gmax; ++ig )
+                {
+                    const T *iptr =
+                        HISTOGRAM(histogram, nCLevels, ir, ig, ptr->bmin);
+                    for( int ib = ptr->bmin; ib <= ptr->bmax; ++ib )
                         *histp += *iptr++;
                 }
                 histp++;
@@ -848,36 +889,37 @@ splitbox(Colorbox* ptr, const T* histogram,
       {
         if( nPixels != 0 && nIters > nPixels )
         {
-            memset(hist2, 0, sizeof(hist2));
-            const int           rmin = ptr->rmin,
-                                rmax = ptr->rmax,
-                                gmin = ptr->gmin,
-                                gmax = ptr->gmax,
-                                bmin = ptr->bmin,
-                                bmax = ptr->bmax;
-            for(T iPixel=0;iPixel<nPixels;iPixel++)
+            const int rmin = ptr->rmin;
+            const int rmax = ptr->rmax;
+            const int gmin = ptr->gmin;
+            const int gmax = ptr->gmax;
+            const int bmin = ptr->bmin;
+            const int bmax = ptr->bmax;
+            for( T iPixel = 0; iPixel < nPixels; iPixel++ )
             {
-                int iR = pabyRedBand[iPixel];
-                int iG = pabyGreenBand[iPixel];
-                int iB = pabyBlueBand[iPixel];
+                const int iR = pabyRedBand[iPixel];
+                const int iG = pabyGreenBand[iPixel];
+                const int iB = pabyBlueBand[iPixel];
                 if( iR >= rmin && iR <= rmax &&
                     iG >= gmin && iG <= gmax &&
                     iB >= bmin && iB <= bmax )
                 {
-                    hist2[iG] ++;
+                    hist2[iG]++;
                 }
             }
         }
         else if( psHashHistogram )
         {
-            histp = &hist2[ptr->gmin];
-            for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
+            T *histp = &hist2[ptr->gmin];
+            for( int ig = ptr->gmin; ig <= ptr->gmax; ++ig )
+            {
                 *histp = 0;
-                for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
-                    for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
+                for( int ir = ptr->rmin; ir <= ptr->rmax; ++ir )
+                {
+                    for( int ib = ptr->bmin; ib <= ptr->bmax; ++ib )
                     {
                         *histp += FindColorCount(psHashHistogram,
-                                       MAKE_COLOR_CODE(ir, ig, ib));
+                                                 MAKE_COLOR_CODE(ir, ig, ib));
                     }
                 }
                 histp++;
@@ -885,12 +927,15 @@ splitbox(Colorbox* ptr, const T* histogram,
         }
         else
         {
-            histp = &hist2[ptr->gmin];
-            for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
+            T *histp = &hist2[ptr->gmin];
+            for( int ig = ptr->gmin; ig <= ptr->gmax; ++ig )
+            {
                 *histp = 0;
-                for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
-                    iptr = &HISTOGRAM(histogram,nCLevels,ir,ig,ptr->bmin);
-                    for (ib = ptr->bmin; ib <= ptr->bmax; ++ib)
+                for( int ir = ptr->rmin; ir <= ptr->rmax; ++ir )
+                {
+                    const T *iptr =
+                        HISTOGRAM(histogram, nCLevels, ir, ig, ptr->bmin);
+                    for( int ib = ptr->bmin; ib <= ptr->bmax; ++ib )
                         *histp += *iptr++;
                 }
                 histp++;
@@ -904,35 +949,37 @@ splitbox(Colorbox* ptr, const T* histogram,
       {
         if( nPixels != 0 && nIters > nPixels )
         {
-            memset(hist2, 0, sizeof(hist2));
-            const int           rmin = ptr->rmin,
-                                rmax = ptr->rmax,
-                                gmin = ptr->gmin,
-                                gmax = ptr->gmax,
-                                bmin = ptr->bmin,
-                                bmax = ptr->bmax;
-            for(T iPixel=0;iPixel<nPixels;iPixel++)
+            const int rmin = ptr->rmin;
+            const int rmax = ptr->rmax;
+            const int gmin = ptr->gmin;
+            const int gmax = ptr->gmax;
+            const int bmin = ptr->bmin;
+            const int bmax = ptr->bmax;
+            for( T iPixel = 0; iPixel < nPixels; iPixel++ )
             {
-                int iR = pabyRedBand[iPixel];
-                int iG = pabyGreenBand[iPixel];
-                int iB = pabyBlueBand[iPixel];
+                const int iR = pabyRedBand[iPixel];
+                const int iG = pabyGreenBand[iPixel];
+                const int iB = pabyBlueBand[iPixel];
                 if( iR >= rmin && iR <= rmax &&
                     iG >= gmin && iG <= gmax &&
                     iB >= bmin && iB <= bmax )
                 {
-                    hist2[iB] ++;
+                    hist2[iB]++;
                 }
             }
         }
         else if( psHashHistogram )
         {
-            histp = &hist2[ptr->bmin];
-            for (ib = ptr->bmin; ib <= ptr->bmax; ++ib) {
+            T *histp = &hist2[ptr->bmin];
+            for( int ib = ptr->bmin; ib <= ptr->bmax; ++ib )
+            {
                 *histp = 0;
-                for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
-                    for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
+                for( int ir = ptr->rmin; ir <= ptr->rmax; ++ir )
+                {
+                    for( int ig = ptr->gmin; ig <= ptr->gmax; ++ig )
+                    {
                         *histp += FindColorCount(psHashHistogram,
-                                       MAKE_COLOR_CODE(ir, ig, ib));
+                                                 MAKE_COLOR_CODE(ir, ig, ib));
                     }
                 }
                 histp++;
@@ -940,12 +987,16 @@ splitbox(Colorbox* ptr, const T* histogram,
         }
         else
         {
-            histp = &hist2[ptr->bmin];
-            for (ib = ptr->bmin; ib <= ptr->bmax; ++ib) {
+            T *histp = &hist2[ptr->bmin];
+            for( int ib = ptr->bmin; ib <= ptr->bmax; ++ib )
+            {
                 *histp = 0;
-                for (ir = ptr->rmin; ir <= ptr->rmax; ++ir) {
-                    iptr = &HISTOGRAM(histogram,nCLevels,ir,ptr->gmin,ib);
-                    for (ig = ptr->gmin; ig <= ptr->gmax; ++ig) {
+                for( int ir = ptr->rmin; ir <= ptr->rmax; ++ir )
+                {
+                    const T *iptr =
+                        HISTOGRAM(histogram, nCLevels, ir, ptr->gmin, ib);
+                    for( int ig = ptr->gmin; ig <= ptr->gmax; ++ig )
+                    {
                         *histp += *iptr;
                         iptr += nCLevels;
                     }
@@ -958,58 +1009,68 @@ splitbox(Colorbox* ptr, const T* histogram,
         break;
       }
     }
-    /* find median point */
-    sum2 = static_cast<T>(ptr->total / 2);
-    histp = &hist2[first];
-    sum = 0;
-    for (i = first; i <= last && (sum += *histp++) < sum2; ++i)
-        ;
-    if (i == first)
+    // Find median point.
+    T *histp = &hist2[first];
+    int i = first;  // TODO(schwehr): Rename i.
+    {
+        T sum = 0;
+        T sum2 = static_cast<T>(ptr->total / 2);
+        for( ; i <= last && (sum += *histp++) < sum2; ++i )
+            {}
+    }
+    if( i == first )
         i++;
 
-    /* Create new box, re-allocate points */
-    new_cb = *pfreeboxes;
+    // Create new box, re-allocate points.
+    Colorbox *new_cb = *pfreeboxes;
     *pfreeboxes = new_cb->next;
-    if (*pfreeboxes)
+    if( *pfreeboxes )
         (*pfreeboxes)->prev = NULL;
-    if (*pusedboxes)
+    if( *pusedboxes )
         (*pusedboxes)->prev = new_cb;
     new_cb->next = *pusedboxes;
     *pusedboxes = new_cb;
 
     histp = &hist2[first];
-    for (sum1 = 0, j = first; j < i; j++)
-        sum1 += *histp++;
-    for (sum2 = 0, j = i; j <= last; j++)
-        sum2 += *histp++;
-    new_cb->total = sum1;
-    ptr->total = sum2;
-
+    {
+        T sum1 = 0;
+        for( int j = first; j < i; j++ )
+            sum1 += *histp++;
+        T sum2 = 0;
+        for( int j = i; j <= last; j++ )
+            sum2 += *histp++;
+        new_cb->total = sum1;
+        ptr->total = sum2;
+    }
     new_cb->rmin = ptr->rmin;
     new_cb->rmax = ptr->rmax;
     new_cb->gmin = ptr->gmin;
     new_cb->gmax = ptr->gmax;
     new_cb->bmin = ptr->bmin;
     new_cb->bmax = ptr->bmax;
-    switch (axis) {
+    switch( axis )
+    {
       case RED:
-        new_cb->rmax = i-1;
+        new_cb->rmax = i - 1;
         ptr->rmin = i;
         break;
       case GREEN:
-        new_cb->gmax = i-1;
+        new_cb->gmax = i - 1;
         ptr->gmin = i;
         break;
       case BLUE:
-        new_cb->bmax = i-1;
+        new_cb->bmax = i - 1;
         ptr->bmin = i;
         break;
     }
+
     if( nPixels != 0 &&
-        (T)(new_cb->rmax - new_cb->rmin + 1) * (T)(new_cb->gmax - new_cb->gmin + 1) *
-        (T)(new_cb->bmax - new_cb->bmin + 1) > nPixels )
+        static_cast<T>(new_cb->rmax - new_cb->rmin + 1) *
+        static_cast<T>(new_cb->gmax - new_cb->gmin + 1) *
+        static_cast<T>(new_cb->bmax - new_cb->bmin + 1) > nPixels )
     {
-        shrinkboxFromBand(new_cb, pabyRedBand, pabyGreenBand, pabyBlueBand, nPixels);
+        shrinkboxFromBand(new_cb, pabyRedBand, pabyGreenBand, pabyBlueBand,
+                          nPixels);
     }
     else if( psHashHistogram != NULL )
     {
@@ -1019,11 +1080,14 @@ splitbox(Colorbox* ptr, const T* histogram,
     {
         shrinkbox(new_cb, histogram, nCLevels);
     }
+
     if( nPixels != 0 &&
-        (T)(ptr->rmax - ptr->rmin + 1) * (T)(ptr->gmax - ptr->gmin + 1) *
-        (T)(ptr->bmax - ptr->bmin + 1) > nPixels )
+        static_cast<T>(ptr->rmax - ptr->rmin + 1) *
+        static_cast<T>(ptr->gmax - ptr->gmin + 1) *
+        static_cast<T>(ptr->bmax - ptr->bmin + 1) > nPixels )
     {
-        shrinkboxFromBand(ptr, pabyRedBand, pabyGreenBand, pabyBlueBand, nPixels);
+        shrinkboxFromBand(ptr, pabyRedBand, pabyGreenBand, pabyBlueBand,
+                          nPixels);
     }
     else if( psHashHistogram != NULL )
     {
@@ -1039,21 +1103,20 @@ splitbox(Colorbox* ptr, const T* histogram,
 /*                             shrinkbox()                              */
 /************************************************************************/
 template<class T> static void
-shrinkbox(Colorbox* box, const T* histogram, int nCLevels)
+shrinkbox( Colorbox* box, const T* histogram, int nCLevels )
 {
-    const T *histp;
-    int ir, ig, ib;
-    //int count_iter;
-
-    if (box->rmax > box->rmin) {
-        //count_iter = 0;
-        for (ir = box->rmin; ir <= box->rmax; ++ir) {
-            for (ig = box->gmin; ig <= box->gmax; ++ig) {
-                histp = &HISTOGRAM(histogram, nCLevels, ir, ig, box->bmin);
-                for (ib = box->bmin; ib <= box->bmax; ++ib) {
-                    //count_iter ++;
-                    if (*histp++ != 0) {
-                        //if( count_iter > 65536 ) printf("iter rmin=%d\n", count_iter);
+    if( box->rmax > box->rmin )
+    {
+        for( int ir = box->rmin; ir <= box->rmax; ++ir )
+        {
+            for( int ig = box->gmin; ig <= box->gmax; ++ig )
+            {
+                const T *histp =
+                    HISTOGRAM(histogram, nCLevels, ir, ig, box->bmin);
+                for( int ib = box->bmin; ib <= box->bmax; ++ib )
+                {
+                    if( *histp++ != 0 )
+                    {
                         box->rmin = ir;
                         goto have_rmin;
                     }
@@ -1062,16 +1125,18 @@ shrinkbox(Colorbox* box, const T* histogram, int nCLevels)
         }
     }
     have_rmin:
-    if (box->rmax > box->rmin) {
-        //count_iter = 0;
-        for (ir = box->rmax; ir >= box->rmin; --ir) {
-            for (ig = box->gmin; ig <= box->gmax; ++ig) {
-                histp = &HISTOGRAM(histogram, nCLevels, ir, ig, box->bmin);
-                ib = box->bmin;
-                for (; ib <= box->bmax; ++ib) {
-                    //count_iter ++;
-                    if (*histp++ != 0) {
-                        //if( count_iter > 65536 ) printf("iter rmax=%d\n", count_iter);
+    if( box->rmax > box->rmin )
+    {
+        for( int ir = box->rmax; ir >= box->rmin; --ir )
+        {
+            for( int ig = box->gmin; ig <= box->gmax; ++ig )
+            {
+                const T *histp =
+                    HISTOGRAM(histogram, nCLevels, ir, ig, box->bmin);
+                for( int ib = box->bmin; ib <= box->bmax; ++ib )
+                {
+                    if( *histp++ != 0 )
+                    {
                         box->rmax = ir;
                         goto have_rmax;
                     }
@@ -1081,15 +1146,18 @@ shrinkbox(Colorbox* box, const T* histogram, int nCLevels)
     }
 
     have_rmax:
-    if (box->gmax > box->gmin) {
-        //count_iter = 0;
-        for (ig = box->gmin; ig <= box->gmax; ++ig) {
-            for (ir = box->rmin; ir <= box->rmax; ++ir) {
-                histp = &HISTOGRAM(histogram, nCLevels, ir, ig, box->bmin);
-                for (ib = box->bmin; ib <= box->bmax; ++ib) {
-                    //count_iter ++;
-                    if (*histp++ != 0) {
-                        //if( count_iter > 65536 ) printf("iter gmin=%d\n", count_iter);
+    if( box->gmax > box->gmin )
+    {
+        for( int ig = box->gmin; ig <= box->gmax; ++ig )
+        {
+            for( int ir = box->rmin; ir <= box->rmax; ++ir )
+            {
+                const T *histp =
+                    HISTOGRAM(histogram, nCLevels, ir, ig, box->bmin);
+                for( int ib = box->bmin; ib <= box->bmax; ++ib )
+                {
+                    if( *histp++ != 0 )
+                    {
                         box->gmin = ig;
                         goto have_gmin;
                     }
@@ -1099,16 +1167,18 @@ shrinkbox(Colorbox* box, const T* histogram, int nCLevels)
     }
 
     have_gmin:
-    if (box->gmax > box->gmin) {
-        //count_iter = 0;
-        for (ig = box->gmax; ig >= box->gmin; --ig) {
-            for (ir = box->rmin; ir <= box->rmax; ++ir) {
-                histp = &HISTOGRAM(histogram, nCLevels, ir, ig, box->bmin);
-                ib = box->bmin;
-                for (; ib <= box->bmax; ++ib) {
-                    //count_iter ++;
-                    if (*histp++ != 0) {
-                        //if( count_iter > 65536 ) printf("iter gmax=%d\n", count_iter);
+    if( box->gmax > box->gmin )
+    {
+        for( int ig = box->gmax; ig >= box->gmin; --ig )
+        {
+            for( int ir = box->rmin; ir <= box->rmax; ++ir )
+            {
+                const T *histp =
+                    HISTOGRAM(histogram, nCLevels, ir, ig, box->bmin);
+                for( int ib = box->bmin; ib <= box->bmax; ++ib )
+                {
+                    if( *histp++ != 0 )
+                    {
                         box->gmax = ig;
                         goto have_gmax;
                     }
@@ -1118,15 +1188,18 @@ shrinkbox(Colorbox* box, const T* histogram, int nCLevels)
     }
 
     have_gmax:
-    if (box->bmax > box->bmin) {
-        //count_iter = 0;
-        for (ib = box->bmin; ib <= box->bmax; ++ib) {
-            for (ir = box->rmin; ir <= box->rmax; ++ir) {
-                histp = &HISTOGRAM(histogram, nCLevels, ir, box->gmin, ib);
-                for (ig = box->gmin; ig <= box->gmax; ++ig) {
-                    //count_iter ++;
-                    if (*histp != 0) {
-                        //if( count_iter > 65536 ) printf("iter bmin=%d\n", count_iter);
+    if( box->bmax > box->bmin )
+    {
+        for( int ib = box->bmin; ib <= box->bmax; ++ib )
+        {
+            for( int ir = box->rmin; ir <= box->rmax; ++ir )
+            {
+                const T *histp =
+                    HISTOGRAM(histogram, nCLevels, ir, box->gmin, ib);
+                for( int ig = box->gmin; ig <= box->gmax; ++ig )
+                {
+                    if( *histp != 0 )
+                    {
                         box->bmin = ib;
                         goto have_bmin;
                     }
@@ -1137,16 +1210,18 @@ shrinkbox(Colorbox* box, const T* histogram, int nCLevels)
     }
 
     have_bmin:
-    if (box->bmax > box->bmin) {
-        //count_iter = 0;
-        for (ib = box->bmax; ib >= box->bmin; --ib) {
-            for (ir = box->rmin; ir <= box->rmax; ++ir) {
-                histp = &HISTOGRAM(histogram, nCLevels, ir, box->gmin, ib);
-                ig = box->gmin;
-                for (; ig <= box->gmax; ++ig) {
-                    //count_iter ++;
-                    if (*histp != 0) {
-                        //if( count_iter > 65536 ) printf("iter bmax=%d\n", count_iter);
+    if( box->bmax > box->bmin )
+    {
+        for( int ib = box->bmax; ib >= box->bmin; --ib )
+        {
+            for( int ir = box->rmin; ir <= box->rmax; ++ir )
+            {
+                const T *histp =
+                    HISTOGRAM(histogram, nCLevels, ir, box->gmin, ib);
+                for( int ig = box->gmin; ig <= box->gmax; ++ig )
+                {
+                    if( *histp != 0 )
+                    {
                         box->bmax = ib;
                         goto have_bmax;
                     }
@@ -1160,32 +1235,35 @@ shrinkbox(Colorbox* box, const T* histogram, int nCLevels)
     ;
 }
 
-/* Explicitly instantiate template functions */
+// Explicitly instantiate template functions.
 template int
-GDALComputeMedianCutPCTInternal<GUInt32>( GDALRasterBandH hRed,
-                           GDALRasterBandH hGreen,
-                           GDALRasterBandH hBlue,
-                           GByte* pabyRedBand,
-                           GByte* pabyGreenBand,
-                           GByte* pabyBlueBand,
-                           int (*pfnIncludePixel)(int,int,void*),
-                           int nColors,
-                           int nBits,
-                           GUInt32* panHistogram,
-                           GDALColorTableH hColorTable,
-                           GDALProgressFunc pfnProgress,
-                           void * pProgressArg );
+GDALComputeMedianCutPCTInternal<GUInt32>(
+    GDALRasterBandH hRed,
+    GDALRasterBandH hGreen,
+    GDALRasterBandH hBlue,
+    GByte* pabyRedBand,
+    GByte* pabyGreenBand,
+    GByte* pabyBlueBand,
+    int (*pfnIncludePixel)(int, int, void*),
+    int nColors,
+    int nBits,
+    GUInt32* panHistogram,
+    GDALColorTableH hColorTable,
+    GDALProgressFunc pfnProgress,
+    void * pProgressArg );
+
 template int
-GDALComputeMedianCutPCTInternal<GUIntBig>( GDALRasterBandH hRed,
-                           GDALRasterBandH hGreen,
-                           GDALRasterBandH hBlue,
-                           GByte* pabyRedBand,
-                           GByte* pabyGreenBand,
-                           GByte* pabyBlueBand,
-                           int (*pfnIncludePixel)(int,int,void*),
-                           int nColors,
-                           int nBits,
-                           GUIntBig* panHistogram,
-                           GDALColorTableH hColorTable,
-                           GDALProgressFunc pfnProgress,
-                           void * pProgressArg );
+GDALComputeMedianCutPCTInternal<GUIntBig>(
+    GDALRasterBandH hRed,
+    GDALRasterBandH hGreen,
+    GDALRasterBandH hBlue,
+    GByte* pabyRedBand,
+    GByte* pabyGreenBand,
+    GByte* pabyBlueBand,
+    int (*pfnIncludePixel)(int, int, void*),
+    int nColors,
+    int nBits,
+    GUIntBig* panHistogram,
+    GDALColorTableH hColorTable,
+    GDALProgressFunc pfnProgress,
+    void * pProgressArg );
diff --git a/alg/gdalpansharpen.cpp b/alg/gdalpansharpen.cpp
index 2fc6a33..9550173 100644
--- a/alg/gdalpansharpen.cpp
+++ b/alg/gdalpansharpen.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalpansharpen.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Pansharpening module
  * Purpose:  Implementation of pansharpening.
@@ -28,18 +27,30 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdalpansharpen.h"
-#include "gdal_priv.h"
+
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <limits>
+#include <new>
+
 #include "cpl_conv.h"
-#include "gdal_priv_templates.hpp"
-#include "../frmts/vrt/vrtdataset.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_vsi.h"
 #include "../frmts/mem/memdataset.h"
-#include <new>
+#include "../frmts/vrt/vrtdataset.h"
+#include "gdal_priv.h"
+#include "gdal_priv_templates.hpp"
+// #include "gdalsse_priv.h"
 
-// Limit types to practical use cases
+// Limit types to practical use cases.
 #define LIMIT_TYPES 1
 
-CPL_CVSID("$Id: gdalpansharpen.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: gdalpansharpen.cpp 36763 2016-12-09 22:10:55Z rouault $");
 
 /************************************************************************/
 /*                     GDALCreatePansharpenOptions()                    */
@@ -55,8 +66,8 @@ CPL_CVSID("$Id: gdalpansharpen.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
 GDALPansharpenOptions * GDALCreatePansharpenOptions()
 {
-    GDALPansharpenOptions* psOptions =
-            (GDALPansharpenOptions*)CPLCalloc(1, sizeof(GDALPansharpenOptions));
+    GDALPansharpenOptions* psOptions = static_cast<GDALPansharpenOptions *>(
+        CPLCalloc(1, sizeof(GDALPansharpenOptions)));
     psOptions->ePansharpenAlg = GDAL_PSH_WEIGHTED_BROVEY;
     psOptions->eResampleAlg = GRIORA_Cubic;
     return psOptions;
@@ -108,8 +119,8 @@ GDALPansharpenOptions* GDALClonePansharpenOptions(
     psNewOptions->nWeightCount = psOptions->nWeightCount;
     if( psOptions->padfWeights )
     {
-        psNewOptions->padfWeights =
-            (double*)CPLMalloc(sizeof(double) * psOptions->nWeightCount);
+        psNewOptions->padfWeights = static_cast<double *>(
+            CPLMalloc(sizeof(double) * psOptions->nWeightCount));
         memcpy(psNewOptions->padfWeights,
                psOptions->padfWeights,
                sizeof(double) * psOptions->nWeightCount);
@@ -118,8 +129,9 @@ GDALPansharpenOptions* GDALClonePansharpenOptions(
     psNewOptions->nInputSpectralBands = psOptions->nInputSpectralBands;
     if( psOptions->pahInputSpectralBands )
     {
-        psNewOptions->pahInputSpectralBands =
-            (GDALRasterBandH*)CPLMalloc(sizeof(GDALRasterBandH) * psOptions->nInputSpectralBands);
+        psNewOptions->pahInputSpectralBands = static_cast<GDALRasterBandH *>(
+            CPLMalloc(sizeof(GDALRasterBandH) *
+                      psOptions->nInputSpectralBands));
         memcpy(psNewOptions->pahInputSpectralBands,
                psOptions->pahInputSpectralBands,
                sizeof(GDALRasterBandH) * psOptions->nInputSpectralBands);
@@ -127,8 +139,8 @@ GDALPansharpenOptions* GDALClonePansharpenOptions(
     psNewOptions->nOutPansharpenedBands = psOptions->nOutPansharpenedBands;
     if( psOptions->panOutPansharpenedBands )
     {
-        psNewOptions->panOutPansharpenedBands =
-            (int*)CPLMalloc(sizeof(int) * psOptions->nOutPansharpenedBands);
+        psNewOptions->panOutPansharpenedBands =  static_cast<int *>(
+            CPLMalloc(sizeof(int) * psOptions->nOutPansharpenedBands));
         memcpy(psNewOptions->panOutPansharpenedBands,
                psOptions->panOutPansharpenedBands,
                sizeof(int) * psOptions->nOutPansharpenedBands);
@@ -149,13 +161,12 @@ GDALPansharpenOptions* GDALClonePansharpenOptions(
  *
  * The object is ready to be used after Initialize() has been called.
  */
-GDALPansharpenOperation::GDALPansharpenOperation()
-{
-    psOptions = NULL;
-    bPositiveWeights = TRUE;
-    poThreadPool = NULL;
-    nKernelRadius = 0;
-}
+GDALPansharpenOperation::GDALPansharpenOperation() :
+    psOptions(NULL),
+    bPositiveWeights(TRUE),
+    poThreadPool(NULL),
+    nKernelRadius(0)
+{}
 
 /************************************************************************/
 /*                       ~GDALPansharpenOperation()                     */
@@ -167,7 +178,7 @@ GDALPansharpenOperation::GDALPansharpenOperation()
 GDALPansharpenOperation::~GDALPansharpenOperation()
 {
     GDALDestroyPansharpenOptions(psOptions);
-    for(size_t i=0;i<aVDS.size();i++)
+    for( size_t i = 0; i < aVDS.size(); i++ )
         delete aVDS[i];
     delete poThreadPool;
 }
@@ -182,7 +193,8 @@ GDALPansharpenOperation::~GDALPansharpenOperation()
  *
  * @return CE_None in case of success, CE_Failure in case of failure.
  */
-CPLErr GDALPansharpenOperation::Initialize(const GDALPansharpenOptions* psOptionsIn)
+CPLErr
+GDALPansharpenOperation::Initialize( const GDALPansharpenOptions* psOptionsIn )
 {
     if( psOptionsIn->hPanchroBand == NULL )
     {
@@ -191,28 +203,31 @@ CPLErr GDALPansharpenOperation::Initialize(const GDALPansharpenOptions* psOption
     }
     if( psOptionsIn->nInputSpectralBands <= 0 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "No input spectral bands defined");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "No input spectral bands defined");
         return CE_Failure;
     }
     if( psOptionsIn->padfWeights == NULL ||
         psOptionsIn->nWeightCount != psOptionsIn->nInputSpectralBands )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "No weights defined, or not the same number as input spectral bands");
+                 "No weights defined, or not the same number as input "
+                 "spectral bands");
         return CE_Failure;
     }
     GDALRasterBandH hRefBand = psOptionsIn->pahInputSpectralBands[0];
     int bSameDataset = psOptionsIn->nInputSpectralBands > 1;
     if( bSameDataset )
         anInputBands.push_back(GDALGetBandNumber(hRefBand));
-    for(int i=1;i<psOptionsIn->nInputSpectralBands;i++)
+    for( int i = 1; i < psOptionsIn->nInputSpectralBands; i++ )
     {
         GDALRasterBandH hBand = psOptionsIn->pahInputSpectralBands[i];
         if( GDALGetRasterBandXSize(hBand) != GDALGetRasterBandXSize(hRefBand) ||
             GDALGetRasterBandYSize(hBand) != GDALGetRasterBandYSize(hRefBand) )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Dimensions of input spectral band %d different from first spectral band",
+                     "Dimensions of input spectral band %d different from "
+                     "first spectral band",
                      i);
             return CE_Failure;
         }
@@ -232,12 +247,14 @@ CPLErr GDALPansharpenOperation::Initialize(const GDALPansharpenOptions* psOption
     }
     if( psOptionsIn->nOutPansharpenedBands == 0 )
     {
-        CPLError(CE_Warning, CPLE_AppDefined, "No output pansharpened band defined");
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "No output pansharpened band defined");
     }
-    for(int i=0;i<psOptionsIn->nOutPansharpenedBands;i++)
+    for( int i = 0; i < psOptionsIn->nOutPansharpenedBands; i++ )
     {
         if( psOptionsIn->panOutPansharpenedBands[i] < 0 ||
-            psOptionsIn->panOutPansharpenedBands[i] >= psOptionsIn->nInputSpectralBands )
+            psOptionsIn->panOutPansharpenedBands[i] >=
+            psOptionsIn->nInputSpectralBands )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Invalid value panOutPansharpenedBands[%d] = %d",
@@ -246,7 +263,8 @@ CPLErr GDALPansharpenOperation::Initialize(const GDALPansharpenOptions* psOption
         }
     }
 
-    GDALRasterBand* poPanchroBand = (GDALRasterBand*)psOptionsIn->hPanchroBand;
+    GDALRasterBand* poPanchroBand = reinterpret_cast<GDALRasterBand*>(
+                                                    psOptionsIn->hPanchroBand);
     GDALDataType eWorkDataType = poPanchroBand->GetRasterDataType();
     if( psOptionsIn->nBitDepth )
     {
@@ -275,8 +293,8 @@ CPLErr GDALPansharpenOperation::Initialize(const GDALPansharpenOptions* psOption
         psOptions->nBitDepth = 0;
     }
 
-    // Detect negative weights
-    for(int i=0;i<psOptions->nInputSpectralBands; i++)
+    // Detect negative weights.
+    for( int i = 0; i<psOptions->nInputSpectralBands; i++ )
     {
         if( psOptions->padfWeights[i] < 0.0 )
         {
@@ -285,65 +303,76 @@ CPLErr GDALPansharpenOperation::Initialize(const GDALPansharpenOptions* psOption
         }
     }
 
-    for(int i=0;i<psOptions->nInputSpectralBands; i++)
+    for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
     {
-        aMSBands.push_back((GDALRasterBand*)psOptions->pahInputSpectralBands[i]);
+        aMSBands.push_back( reinterpret_cast<GDALRasterBand*>(
+                                        psOptions->pahInputSpectralBands[i]) );
     }
 
     if( psOptions->bHasNoData )
     {
-        int bNeedToWrapInVRT = FALSE;
-        for(int i=0;i<psOptions->nInputSpectralBands; i++)
+        bool bNeedToWrapInVRT = false;
+        for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
         {
-            GDALRasterBand* poBand = (GDALRasterBand*)psOptions->pahInputSpectralBands[i];
-            int bHasNoData;
+            GDALRasterBand* poBand = reinterpret_cast<GDALRasterBand*>(
+                                        psOptions->pahInputSpectralBands[i]);
+            int bHasNoData = FALSE;
             double dfNoData = poBand->GetNoDataValue(&bHasNoData);
             if( !bHasNoData || dfNoData != psOptions->dfNoData )
-                bNeedToWrapInVRT = TRUE;
+                bNeedToWrapInVRT = true;
         }
 
         if( bNeedToWrapInVRT )
         {
-            // Wrap spectral bands in a VRT if they don't have the nodata value
+            // Wrap spectral bands in a VRT if they don't have the nodata value.
             VRTDataset* poVDS = NULL;
-            for(int i=0;i<psOptions->nInputSpectralBands; i++)
+            for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
             {
                 GDALRasterBand* poSrcBand = aMSBands[i];
-                if( anInputBands.size() == 0 || i == 0 )
+                if( anInputBands.empty() || i == 0 )
                 {
                     poVDS = new VRTDataset(poSrcBand->GetXSize(), poSrcBand->GetYSize());
                     aVDS.push_back(poVDS);
                 }
-                if( anInputBands.size() )
+                if( !anInputBands.empty() )
                     anInputBands[i] = i + 1;
                 poVDS->AddBand(poSrcBand->GetRasterDataType(), NULL);
-                VRTSourcedRasterBand* poVRTBand = (VRTSourcedRasterBand*) poVDS->GetRasterBand(i+1);
+                VRTSourcedRasterBand* poVRTBand =
+                    dynamic_cast<VRTSourcedRasterBand*>(
+                        poVDS->GetRasterBand(i + 1));
+                if( poVRTBand == NULL )
+                    return CE_Failure;
                 aMSBands[i] = poVRTBand;
                 poVRTBand->SetNoDataValue(psOptions->dfNoData);
-                const char* pszNBITS = poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+                const char* pszNBITS =
+                    poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
                 if( pszNBITS )
-                    poVRTBand->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
+                    poVRTBand->SetMetadataItem("NBITS", pszNBITS,
+                                               "IMAGE_STRUCTURE");
 
                 VRTSimpleSource* poSimpleSource = new VRTSimpleSource();
-                poVRTBand->ConfigureSource( poSimpleSource,
-                                            poSrcBand,
-                                            FALSE,
-                                            0, 0,
-                                            poSrcBand->GetXSize(), poSrcBand->GetYSize(),
-                                            0, 0,
-                                            poSrcBand->GetXSize(), poSrcBand->GetYSize() );
+                poVRTBand->ConfigureSource(poSimpleSource,
+                                           poSrcBand,
+                                           FALSE,
+                                           0, 0,
+                                           poSrcBand->GetXSize(),
+                                           poSrcBand->GetYSize(),
+                                           0, 0,
+                                           poSrcBand->GetXSize(),
+                                           poSrcBand->GetYSize());
                 poVRTBand->AddSource( poSimpleSource );
             }
         }
     }
 
-    // Setup thread pool
+    // Setup thread pool.
     int nThreads = psOptions->nThreads;
     if( nThreads == -1 )
         nThreads = CPLGetNumCPUs();
     else if( nThreads == 0 )
     {
-        const char* pszNumThreads = CPLGetConfigOption("GDAL_NUM_THREADS", NULL);
+        const char* pszNumThreads =
+            CPLGetConfigOption("GDAL_NUM_THREADS", NULL);
         if( pszNumThreads )
         {
             if( EQUAL(pszNumThreads, "ALL_CPUS") )
@@ -400,18 +429,18 @@ template<class WorkDataType, class OutDataType>
 
     if( !(std::numeric_limits<WorkDataType>::is_integer) )
         validValue = (WorkDataType)(noData + 1e-5);
-    else if (noData == std::numeric_limits<WorkDataType>::min())
+    else if( noData == std::numeric_limits<WorkDataType>::min() )
         validValue = std::numeric_limits<WorkDataType>::min() + 1;
     else
         validValue = noData - 1;
 
-    for(int j=0;j<nValues;j++)
+    for( int j = 0; j < nValues; j++ )
     {
-        double dfFactor;
-        double dfPseudoPanchro = 0;
-        for(int i=0;i<psOptions->nInputSpectralBands;i++)
+        double dfPseudoPanchro = 0.0;
+        for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
         {
-            WorkDataType nSpectralVal = pUpsampledSpectralBuffer[i * nBandValues + j];
+            WorkDataType nSpectralVal =
+                pUpsampledSpectralBuffer[i * nBandValues + j];
             if( nSpectralVal == noData )
             {
                 dfPseudoPanchro = 0.0;
@@ -419,18 +448,20 @@ template<class WorkDataType, class OutDataType>
             }
             dfPseudoPanchro += psOptions->padfWeights[i] * nSpectralVal;
         }
-        if( dfPseudoPanchro && pPanBuffer[j] != noData )
+        if( dfPseudoPanchro != 0.0 && pPanBuffer[j] != noData )
         {
-            dfFactor = pPanBuffer[j] / dfPseudoPanchro;
-            for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+            const double dfFactor = pPanBuffer[j] / dfPseudoPanchro;
+            for( int i = 0; i < psOptions->nOutPansharpenedBands; i++ )
             {
                 WorkDataType nRawValue =
-                    pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j];
+                    pUpsampledSpectralBuffer[
+                        psOptions->panOutPansharpenedBands[i] * nBandValues +
+                        j];
                 WorkDataType nPansharpenedValue;
                 GDALCopyWord(nRawValue * dfFactor, nPansharpenedValue);
-                if( nMaxValue && nPansharpenedValue > nMaxValue )
+                if( nMaxValue != 0 && nPansharpenedValue > nMaxValue )
                     nPansharpenedValue = nMaxValue;
-                // We don't want a valid value to be mapped to NoData
+                // We don't want a valid value to be mapped to NoData.
                 if( nPansharpenedValue == noData )
                     nPansharpenedValue = validValue;
                 GDALCopyWord(nPansharpenedValue, pDataBuf[i * nBandValues + j]);
@@ -438,7 +469,7 @@ template<class WorkDataType, class OutDataType>
         }
         else
         {
-            for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+            for( int i = 0; i < psOptions->nOutPansharpenedBands; i++ )
             {
                 GDALCopyWord(noData, pDataBuf[i * nBandValues + j]);
             }
@@ -451,40 +482,40 @@ template<class WorkDataType, class OutDataType>
 /************************************************************************/
 
 template<class WorkDataType, class OutDataType, int bHasBitDepth>
-                    void GDALPansharpenOperation::WeightedBrovey3(
-                                                     const WorkDataType* pPanBuffer,
-                                                     const WorkDataType* pUpsampledSpectralBuffer,
-                                                     OutDataType* pDataBuf,
-                                                     int nValues,
-                                                     int nBandValues,
-                                                     WorkDataType nMaxValue) const
+void GDALPansharpenOperation::WeightedBrovey3(
+    const WorkDataType* pPanBuffer,
+    const WorkDataType* pUpsampledSpectralBuffer,
+    OutDataType* pDataBuf,
+    int nValues,
+    int nBandValues,
+    WorkDataType nMaxValue) const
 {
     if( psOptions->bHasNoData )
     {
-        WeightedBroveyWithNoData<WorkDataType,OutDataType>
+        WeightedBroveyWithNoData<WorkDataType, OutDataType>
                                 (pPanBuffer, pUpsampledSpectralBuffer,
                                  pDataBuf, nValues, nBandValues, nMaxValue);
         return;
     }
 
-    for(int j=0;j<nValues;j++)
+    for( int j = 0; j < nValues; j++ )
     {
-        double dfFactor;
-        //if( pPanBuffer[j] == 0 )
-        //    dfFactor = 1.0;
-        //else
+        double dfFactor = 0.0;
+        // if( pPanBuffer[j] == 0 )
+        //     dfFactor = 1.0;
+        // else
         {
-            double dfPseudoPanchro = 0;
-            for(int i=0;i<psOptions->nInputSpectralBands;i++)
+            double dfPseudoPanchro = 0.0;
+            for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
                 dfPseudoPanchro += psOptions->padfWeights[i] *
                                 pUpsampledSpectralBuffer[i * nBandValues + j];
-            if( dfPseudoPanchro )
+            if( dfPseudoPanchro != 0.0 )
                 dfFactor = pPanBuffer[j] / dfPseudoPanchro;
             else
                 dfFactor = 0.0;
         }
 
-        for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+        for( int i = 0; i < psOptions->nOutPansharpenedBands; i++ )
         {
             WorkDataType nRawValue =
                 pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j];
@@ -521,10 +552,11 @@ int GDALPansharpenOperation::WeightedBroveyPositiveWeightsInternal(
 
     const XMMReg4Double zero = XMMReg4Double::Zero();
     double dfMaxValue = nMaxValue;
-    const XMMReg4Double maxValue = XMMReg4Double::Load1ValHighAndLow(&dfMaxValue);
+    const XMMReg4Double maxValue =
+        XMMReg4Double::Load1ValHighAndLow(&dfMaxValue);
 
-    int j;
-    for(j=0;j<nValues-3;j+=4)
+    int j = 0;  // Used after for.
+    for( ; j < nValues - 3; j += 4 )
     {
         XMMReg4Double pseudoPanchro = zero;
 
@@ -539,7 +571,7 @@ int GDALPansharpenOperation::WeightedBroveyPositiveWeightsInternal(
             XMMReg4Double::NotEquals(pseudoPanchro, zero),
             XMMReg4Double::Load4Val(pPanBuffer + j) / pseudoPanchro );
 
-        for(int i=0;i<NOUTPUT;i++)
+        for( int i = 0; i < NOUTPUT; i++ )
         {
             XMMReg4Double rawValue = XMMReg4Double::Load4Val(pUpsampledSpectralBuffer + i * nBandValues + j);
             XMMReg4Double tmp = XMMReg4Double::Min(rawValue * factor, maxValue);
@@ -553,24 +585,27 @@ int GDALPansharpenOperation::WeightedBroveyPositiveWeightsInternal(
 
 template<int NINPUT, int NOUTPUT>
 int GDALPansharpenOperation::WeightedBroveyPositiveWeightsInternal(
-                                                     const GUInt16* pPanBuffer,
-                                                     const GUInt16* pUpsampledSpectralBuffer,
-                                                     GUInt16* pDataBuf,
-                                                     int nValues,
-                                                     int nBandValues,
-                                                     GUInt16 nMaxValue) const
+    const GUInt16* pPanBuffer,
+    const GUInt16* pUpsampledSpectralBuffer,
+    GUInt16* pDataBuf,
+    int nValues,
+    int nBandValues,
+    GUInt16 nMaxValue) const
 {
+    // cppcheck-suppress knownConditionTrueFalse
     CPLAssert( NINPUT == 3 || NINPUT == 4 );
     const double dfw0 = psOptions->padfWeights[0];
     const double dfw1 = psOptions->padfWeights[1];
     const double dfw2 = psOptions->padfWeights[2];
+    // cppcheck-suppress knownConditionTrueFalse
     const double dfw3 = (NINPUT == 3) ? 0 : psOptions->padfWeights[3];
-    int j;
-    for(j=0;j<nValues-1;j+=2)
+    int j = 0;  // Used after for.
+    for( ; j < nValues-1; j += 2 )
     {
-        double dfFactor, dfFactor2;
-        double dfPseudoPanchro = 0;
-        double dfPseudoPanchro2 = 0;
+        double dfFactor = 0.0;
+        double dfFactor2 = 0.0;
+        double dfPseudoPanchro = 0.0;
+        double dfPseudoPanchro2 = 0.0;
 
         dfPseudoPanchro += dfw0 *
                         pUpsampledSpectralBuffer[j];
@@ -595,16 +630,16 @@ int GDALPansharpenOperation::WeightedBroveyPositiveWeightsInternal(
                             pUpsampledSpectralBuffer[3 * nBandValues + j + 1];
         }
 
-        if( dfPseudoPanchro )
+        if( dfPseudoPanchro != 0.0 )
             dfFactor = pPanBuffer[j] / dfPseudoPanchro;
         else
             dfFactor = 0.0;
-        if( dfPseudoPanchro2 )
+        if( dfPseudoPanchro2 != 0.0 )
             dfFactor2 = pPanBuffer[j+1] / dfPseudoPanchro2;
         else
             dfFactor2 = 0.0;
 
-        for(int i=0;i<NOUTPUT;i++)
+        for( int i = 0; i < NOUTPUT; i++ )
         {
             GUInt16 nRawValue =
                 pUpsampledSpectralBuffer[i * nBandValues + j];
@@ -628,16 +663,16 @@ int GDALPansharpenOperation::WeightedBroveyPositiveWeightsInternal(
 #endif
 
 void GDALPansharpenOperation::WeightedBroveyPositiveWeights(
-                                                     const GUInt16* pPanBuffer,
-                                                     const GUInt16* pUpsampledSpectralBuffer,
-                                                     GUInt16* pDataBuf,
-                                                     int nValues,
-                                                     int nBandValues,
-                                                     GUInt16 nMaxValue) const
+    const GUInt16* pPanBuffer,
+    const GUInt16* pUpsampledSpectralBuffer,
+    GUInt16* pDataBuf,
+    int nValues,
+    int nBandValues,
+    GUInt16 nMaxValue) const
 {
     if( psOptions->bHasNoData )
     {
-        WeightedBroveyWithNoData<GUInt16,GUInt16>
+        WeightedBroveyWithNoData<GUInt16, GUInt16>
                                 (pPanBuffer, pUpsampledSpectralBuffer,
                                  pDataBuf, nValues, nBandValues, nMaxValue);
         return;
@@ -652,8 +687,9 @@ void GDALPansharpenOperation::WeightedBroveyPositiveWeights(
         psOptions->panOutPansharpenedBands[1] == 1 &&
         psOptions->panOutPansharpenedBands[2] == 2 )
     {
-        j = WeightedBroveyPositiveWeightsInternal<3,3>(
-            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+        j = WeightedBroveyPositiveWeightsInternal<3, 3>(
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues,
+            nBandValues, nMaxValue);
     }
     else if( psOptions->nInputSpectralBands == 4 &&
         psOptions->nOutPansharpenedBands == 4 &&
@@ -662,8 +698,9 @@ void GDALPansharpenOperation::WeightedBroveyPositiveWeights(
         psOptions->panOutPansharpenedBands[2] == 2 &&
         psOptions->panOutPansharpenedBands[3] == 3 )
     {
-        j = WeightedBroveyPositiveWeightsInternal<4,4>(
-            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+        j = WeightedBroveyPositiveWeightsInternal<4, 4>(
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues,
+            nBandValues, nMaxValue);
     }
     else if( psOptions->nInputSpectralBands == 4 &&
         psOptions->nOutPansharpenedBands == 3 &&
@@ -671,68 +708,75 @@ void GDALPansharpenOperation::WeightedBroveyPositiveWeights(
         psOptions->panOutPansharpenedBands[1] == 1 &&
         psOptions->panOutPansharpenedBands[2] == 2 )
     {
-        j = WeightedBroveyPositiveWeightsInternal<4,3>(
-            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+        j = WeightedBroveyPositiveWeightsInternal<4, 3>(
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues,
+            nBandValues, nMaxValue);
     }
     else
     {
-        for(j=0;j<nValues-1;j+=2)
+        for( j = 0; j < nValues - 1; j += 2 )
         {
-            double dfFactor, dfFactor2;
-            double dfPseudoPanchro = 0;
-            double dfPseudoPanchro2 = 0;
-            for(int i=0;i<psOptions->nInputSpectralBands;i++)
+            double dfFactor = 0.0;
+            double dfFactor2 = 0.0;
+            double dfPseudoPanchro = 0.0;
+            double dfPseudoPanchro2 = 0.0;
+            for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
             {
-                dfPseudoPanchro += psOptions->padfWeights[i] *
-                                pUpsampledSpectralBuffer[i * nBandValues + j];
-                dfPseudoPanchro2 += psOptions->padfWeights[i] *
-                                pUpsampledSpectralBuffer[i * nBandValues + j + 1];
+                dfPseudoPanchro +=
+                    psOptions->padfWeights[i] *
+                    pUpsampledSpectralBuffer[i * nBandValues + j];
+                dfPseudoPanchro2 +=
+                    psOptions->padfWeights[i] *
+                    pUpsampledSpectralBuffer[i * nBandValues + j + 1];
             }
-            if( dfPseudoPanchro )
+            if( dfPseudoPanchro != 0.0 )
                 dfFactor = pPanBuffer[j] / dfPseudoPanchro;
             else
                 dfFactor = 0.0;
-            if( dfPseudoPanchro2 )
+            if( dfPseudoPanchro2 != 0.0 )
                 dfFactor2 = pPanBuffer[j+1] / dfPseudoPanchro2;
             else
                 dfFactor2 = 0.0;
 
-            for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+            for( int i = 0; i < psOptions->nOutPansharpenedBands; i++ )
             {
-                GUInt16 nRawValue =
+                const GUInt16 nRawValue =
                     pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j];
-                double dfTmp = nRawValue * dfFactor;
+                const double dfTmp = nRawValue * dfFactor;
                 if( dfTmp > nMaxValue )
                     pDataBuf[i * nBandValues + j] = nMaxValue;
                 else
-                    pDataBuf[i * nBandValues + j] = (GUInt16)(dfTmp + 0.5);
+                    pDataBuf[i * nBandValues + j] =
+                        static_cast<GUInt16>(dfTmp + 0.5);
 
-                GUInt16 nRawValue2 =
+                const GUInt16 nRawValue2 =
                     pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j + 1];
-                double dfTmp2 = nRawValue2 * dfFactor2;
+                const double dfTmp2 = nRawValue2 * dfFactor2;
                 if( dfTmp2 > nMaxValue )
                     pDataBuf[i * nBandValues + j + 1] = nMaxValue;
                 else
-                    pDataBuf[i * nBandValues + j + 1] = (GUInt16)(dfTmp2 + 0.5);
+                    pDataBuf[i * nBandValues + j + 1] =
+                        static_cast<GUInt16>(dfTmp2 + 0.5);
             }
         }
     }
     for( ;j<nValues ;j++)
     {
-        double dfFactor;
-        double dfPseudoPanchro = 0;
-        for(int i=0;i<psOptions->nInputSpectralBands;i++)
+        double dfFactor = 0.0;
+        double dfPseudoPanchro = 0.0;
+        for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
             dfPseudoPanchro += psOptions->padfWeights[i] *
                             pUpsampledSpectralBuffer[i * nBandValues + j];
-        if( dfPseudoPanchro )
+        if( dfPseudoPanchro != 0.0 )
             dfFactor = pPanBuffer[j] / dfPseudoPanchro;
         else
             dfFactor = 0.0;
 
-        for(int i=0;i<psOptions->nOutPansharpenedBands;i++)
+        for( int i = 0; i < psOptions->nOutPansharpenedBands; i++ )
         {
             GUInt16 nRawValue =
-                pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] * nBandValues + j];
+                pUpsampledSpectralBuffer[psOptions->panOutPansharpenedBands[i] *
+                                         nBandValues + j];
             double dfTmp = nRawValue * dfFactor;
             if( dfTmp > nMaxValue )
                 pDataBuf[i * nBandValues + j] = nMaxValue;
@@ -742,100 +786,114 @@ void GDALPansharpenOperation::WeightedBroveyPositiveWeights(
     }
 }
 
-template<class WorkDataType, class OutDataType> void GDALPansharpenOperation::WeightedBrovey(
-                                                     const WorkDataType* pPanBuffer,
-                                                     const WorkDataType* pUpsampledSpectralBuffer,
-                                                     OutDataType* pDataBuf,
-                                                     int nValues,
-                                                     int nBandValues,
-                                                     WorkDataType nMaxValue) const
+template<class WorkDataType, class OutDataType> void
+GDALPansharpenOperation::WeightedBrovey(
+    const WorkDataType* pPanBuffer,
+    const WorkDataType* pUpsampledSpectralBuffer,
+    OutDataType* pDataBuf,
+    int nValues,
+    int nBandValues,
+    WorkDataType nMaxValue ) const
 {
     if( nMaxValue == 0 )
         WeightedBrovey3<WorkDataType, OutDataType, FALSE>(
-            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, 0);
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues,
+            nBandValues, 0);
     else
     {
         WeightedBrovey3<WorkDataType, OutDataType, TRUE>(
-            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues,
+            nBandValues, nMaxValue);
     }
 }
 
 template<>
-void GDALPansharpenOperation::WeightedBrovey<GUInt16,GUInt16>(
-                                                     const GUInt16* pPanBuffer,
-                                                     const GUInt16* pUpsampledSpectralBuffer,
-                                                     GUInt16* pDataBuf,
-                                                     int nValues,
-                                                     int nBandValues,
-                                                     GUInt16 nMaxValue) const
+void GDALPansharpenOperation::WeightedBrovey<GUInt16, GUInt16>(
+    const GUInt16* pPanBuffer,
+    const GUInt16* pUpsampledSpectralBuffer,
+    GUInt16* pDataBuf,
+    int nValues,
+    int nBandValues,
+    GUInt16 nMaxValue ) const
 {
     if( bPositiveWeights )
     {
         WeightedBroveyPositiveWeights(
-                pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+                pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues,
+                nBandValues, nMaxValue);
     }
     else if( nMaxValue == 0 )
     {
         WeightedBrovey3<GUInt16, GUInt16, FALSE>(
-                pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, 0);
+                pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues,
+                nBandValues, 0);
     }
     else
     {
         WeightedBrovey3<GUInt16, GUInt16, TRUE>(
-            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues, nBandValues, nMaxValue);
+            pPanBuffer, pUpsampledSpectralBuffer, pDataBuf, nValues,
+            nBandValues, nMaxValue);
     }
 }
 
 template<class WorkDataType> CPLErr GDALPansharpenOperation::WeightedBrovey(
-                                                     const WorkDataType* pPanBuffer,
-                                                     const WorkDataType* pUpsampledSpectralBuffer,
-                                                     void *pDataBuf,
-                                                     GDALDataType eBufDataType,
-                                                     int nValues,
-                                                     int nBandValues,
-                                                     WorkDataType nMaxValue) const
+    const WorkDataType* pPanBuffer,
+    const WorkDataType* pUpsampledSpectralBuffer,
+    void *pDataBuf,
+    GDALDataType eBufDataType,
+    int nValues,
+    int nBandValues,
+    WorkDataType nMaxValue ) const
 {
     switch( eBufDataType )
     {
         case GDT_Byte:
             WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GByte*)pDataBuf, nValues, nBandValues, nMaxValue);
+                           static_cast<GByte *>(pDataBuf),
+                           nValues, nBandValues, nMaxValue);
             break;
 
         case GDT_UInt16:
             WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GUInt16*)pDataBuf, nValues, nBandValues, nMaxValue);
+                           static_cast<GUInt16 *>(pDataBuf),
+                           nValues, nBandValues, nMaxValue);
             break;
 
 #ifndef LIMIT_TYPES
         case GDT_Int16:
             WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GInt16*)pDataBuf, nValues, nBandValues, nMaxValue);
+                           static_cast<GInt16 *>(pDataBuf),
+                           nValues, nBandValues, nMaxValue);
             break;
 
         case GDT_UInt32:
             WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GUInt32*)pDataBuf, nValues, nBandValues, nMaxValue);
+                           static_cast<GUInt32 *>(pDataBuf),
+                           nValues, nBandValues, nMaxValue);
             break;
 
         case GDT_Int32:
             WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GInt32*)pDataBuf, nValues, nBandValues, nMaxValue);
+                           static_cast<GInt32 *>(pDataBuf),
+                           nValues, nBandValues, nMaxValue);
             break;
 
         case GDT_Float32:
             WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
-                           (float*)pDataBuf, nValues, nBandValues, nMaxValue);
+                           static_cast<float *>(pDataBuf),
+                           nValues, nBandValues, nMaxValue);
             break;
 #endif
 
         case GDT_Float64:
             WeightedBrovey(pPanBuffer, pUpsampledSpectralBuffer,
-                           (double*)pDataBuf, nValues, nBandValues, nMaxValue);
+                           static_cast<double *>(pDataBuf),
+                           nValues, nBandValues, nMaxValue);
             break;
 
         default:
-            CPLError(CE_Failure, CPLE_NotSupported, "eBufDataType not supported");
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "eBufDataType not supported");
             return CE_Failure;
             break;
     }
@@ -844,53 +902,61 @@ template<class WorkDataType> CPLErr GDALPansharpenOperation::WeightedBrovey(
 }
 
 template<class WorkDataType> CPLErr GDALPansharpenOperation::WeightedBrovey(
-                                                     const WorkDataType* pPanBuffer,
-                                                     const WorkDataType* pUpsampledSpectralBuffer,
-                                                     void *pDataBuf,
-                                                     GDALDataType eBufDataType,
-                                                     int nValues, int nBandValues) const
+    const WorkDataType* pPanBuffer,
+    const WorkDataType* pUpsampledSpectralBuffer,
+    void *pDataBuf,
+    GDALDataType eBufDataType,
+    int nValues, int nBandValues ) const
 {
     switch( eBufDataType )
     {
         case GDT_Byte:
-            WeightedBrovey3<WorkDataType, GByte, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GByte*)pDataBuf, nValues, nBandValues, 0);
+            WeightedBrovey3<WorkDataType, GByte, FALSE>(
+                pPanBuffer, pUpsampledSpectralBuffer,
+                static_cast<GByte *>(pDataBuf), nValues, nBandValues, 0);
             break;
 
         case GDT_UInt16:
-            WeightedBrovey3<WorkDataType, GUInt16, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GUInt16*)pDataBuf, nValues, nBandValues, 0);
+            WeightedBrovey3<WorkDataType, GUInt16, FALSE>(
+                pPanBuffer, pUpsampledSpectralBuffer,
+                static_cast<GUInt16 *>(pDataBuf), nValues, nBandValues, 0);
             break;
 
 #ifndef LIMIT_TYPES
         case GDT_Int16:
-            WeightedBrovey3<WorkDataType, GInt16, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GInt16*)pDataBuf, nValues, nBandValues, 0);
+            WeightedBrovey3<WorkDataType, GInt16, FALSE>(
+                pPanBuffer, pUpsampledSpectralBuffer,
+                static_cast<GInt16 *>(pDataBuf), nValues, nBandValues, 0);
             break;
 
         case GDT_UInt32:
-            WeightedBrovey3<WorkDataType, GUInt32, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GUInt32*)pDataBuf, nValues, nBandValues, 0);
+            WeightedBrovey3<WorkDataType, GUInt32, FALSE>(
+                pPanBuffer, pUpsampledSpectralBuffer,
+                static_cast<GUInt32 *>(pDataBuf), nValues, nBandValues, 0);
             break;
 
         case GDT_Int32:
-            WeightedBrovey3<WorkDataType, GInt32, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
-                           (GInt32*)pDataBuf, nValues, nBandValues, 0);
+            WeightedBrovey3<WorkDataType, GInt32, FALSE>(
+                pPanBuffer, pUpsampledSpectralBuffer,
+                static_cast<GInt32 *>(pDataBuf), nValues, nBandValues, 0);
             break;
 
         case GDT_Float32:
-            WeightedBrovey3<WorkDataType, float, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
-                           (float*)pDataBuf, nValues, nBandValues, 0);
+            WeightedBrovey3<WorkDataType, float, FALSE>(
+                pPanBuffer, pUpsampledSpectralBuffer,
+                static_cast<float *>(pDataBuf), nValues, nBandValues, 0);
             break;
 #endif
 
         case GDT_Float64:
-            WeightedBrovey3<WorkDataType, double, FALSE>(pPanBuffer, pUpsampledSpectralBuffer,
-                           (double*)pDataBuf, nValues, nBandValues, 0);
+            WeightedBrovey3<WorkDataType, double, FALSE>(
+                pPanBuffer, pUpsampledSpectralBuffer,
+                static_cast<double *>(pDataBuf), nValues, nBandValues, 0);
             break;
 
         default:
-            CPLError(CE_Failure, CPLE_NotSupported, "eBufDataType not supported");
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "eBufDataType not supported");
             return CE_Failure;
             break;
     }
@@ -903,9 +969,9 @@ template<class WorkDataType> CPLErr GDALPansharpenOperation::WeightedBrovey(
 /************************************************************************/
 
 template< class T >
-static void ClampValues(T* panBuffer, int nValues, T nMaxVal)
+static void ClampValues( T* panBuffer, int nValues, T nMaxVal )
 {
-    for(int i=0;i<nValues;i++)
+    for( int i = 0; i < nValues; i++ )
     {
         if( panBuffer[i] > nMaxVal )
             panBuffer[i] = nMaxVal;
@@ -940,25 +1006,28 @@ static void ClampValues(T* panBuffer, int nValues, T nMaxVal)
  *
  * @since GDAL 2.1
  */
-CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
-                                              int nXSize, int nYSize,
-                                              void *pDataBuf,
-                                              GDALDataType eBufDataType)
+CPLErr GDALPansharpenOperation::ProcessRegion( int nXOff, int nYOff,
+                                               int nXSize, int nYSize,
+                                               void *pDataBuf,
+                                               GDALDataType eBufDataType )
 {
     if( psOptions == NULL )
         return CE_Failure;
 
-    // TODO: avoid allocating buffers each time
-    GDALRasterBand* poPanchroBand = (GDALRasterBand*)psOptions->hPanchroBand;
+    // TODO: Avoid allocating buffers each time.
+    GDALRasterBand* poPanchroBand = reinterpret_cast<GDALRasterBand*>(
+                                                    psOptions->hPanchroBand);
     GDALDataType eWorkDataType = poPanchroBand->GetRasterDataType();
 #ifdef LIMIT_TYPES
     if( eWorkDataType != GDT_Byte && eWorkDataType != GDT_UInt16 )
         eWorkDataType = GDT_Float64;
 #endif
     const int nDataTypeSize = GDALGetDataTypeSizeBytes(eWorkDataType);
-    GByte* pUpsampledSpectralBuffer = (GByte*)VSI_MALLOC3_VERBOSE(nXSize, nYSize,
-        psOptions->nInputSpectralBands * nDataTypeSize);
-    GByte* pPanBuffer = (GByte*)VSI_MALLOC3_VERBOSE(nXSize, nYSize, nDataTypeSize);
+    GByte* pUpsampledSpectralBuffer = static_cast<GByte *>(
+        VSI_MALLOC3_VERBOSE(nXSize, nYSize,
+                            psOptions->nInputSpectralBands * nDataTypeSize));
+    GByte* pPanBuffer = static_cast<GByte *>(
+        VSI_MALLOC3_VERBOSE(nXSize, nYSize, nDataTypeSize));
     if( pUpsampledSpectralBuffer == NULL || pPanBuffer == NULL )
     {
         VSIFree(pUpsampledSpectralBuffer);
@@ -990,8 +1059,12 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
     const GDALRIOResampleAlg eResampleAlg = psOptions->eResampleAlg;
     sExtraArg.eResampleAlg = eResampleAlg;
     sExtraArg.bFloatingPointWindowValidity = TRUE;
-    double dfRatioX = (double)poPanchroBand->GetXSize() / aMSBands[0]->GetXSize();
-    double dfRatioY = (double)poPanchroBand->GetYSize() / aMSBands[0]->GetYSize();
+    double dfRatioX =
+        static_cast<double>(poPanchroBand->GetXSize()) /
+        aMSBands[0]->GetXSize();
+    double dfRatioY =
+        static_cast<double>(poPanchroBand->GetYSize()) /
+        aMSBands[0]->GetYSize();
     sExtraArg.dfXOff = (nXOff + psOptions->dfMSShiftX) / dfRatioX;
     sExtraArg.dfYOff = (nYOff + psOptions->dfMSShiftY) / dfRatioY;
     sExtraArg.dfXSize = nXSize / dfRatioX;
@@ -1000,10 +1073,10 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
         sExtraArg.dfXOff = aMSBands[0]->GetXSize() - sExtraArg.dfXSize;
     if( sExtraArg.dfYOff + sExtraArg.dfYSize > aMSBands[0]->GetYSize() )
         sExtraArg.dfYOff = aMSBands[0]->GetYSize() - sExtraArg.dfYSize;
-    int nSpectralXOff = (int)(sExtraArg.dfXOff);
-    int nSpectralYOff = (int)(sExtraArg.dfYOff);
-    int nSpectralXSize = (int)(0.49999 + sExtraArg.dfXSize);
-    int nSpectralYSize = (int)(0.49999 + sExtraArg.dfYSize);
+    int nSpectralXOff = static_cast<int>(sExtraArg.dfXOff);
+    int nSpectralYOff = static_cast<int>(sExtraArg.dfYOff);
+    int nSpectralXSize = static_cast<int>(0.49999 + sExtraArg.dfXSize);
+    int nSpectralYSize = static_cast<int>(0.49999 + sExtraArg.dfYSize);
     if( nSpectralXSize == 0 )
         nSpectralXSize = 1;
     if( nSpectralYSize == 0 )
@@ -1014,7 +1087,8 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
     if( nSpectralXSize < nXSize && nSpectralYSize < nYSize &&
         eResampleAlg != GRIORA_NearestNeighbour && nYSize > 1 )
     {
-        // Take some margin to take into account the radius of the resampling kernel
+        // Take some margin to take into account the radius of the
+        // resampling kernel.
         int nXOffExtract = nSpectralXOff - nKernelRadius;
         int nYOffExtract = nSpectralYOff - nKernelRadius;
         int nXSizeExtract = nSpectralXSize + 1 + 2 * nKernelRadius;
@@ -1034,8 +1108,10 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
         if( nYOffExtract + nYSizeExtract > aMSBands[0]->GetYSize() )
             nYSizeExtract = aMSBands[0]->GetYSize() - nYOffExtract;
 
-        GByte* pSpectralBuffer = (GByte*)VSI_MALLOC3_VERBOSE(nXSizeExtract, nYSizeExtract,
-                            psOptions->nInputSpectralBands * nDataTypeSize);
+        GByte* pSpectralBuffer = static_cast<GByte *>(
+            VSI_MALLOC3_VERBOSE(
+                nXSizeExtract, nYSizeExtract,
+                psOptions->nInputSpectralBands * nDataTypeSize));
         if( pSpectralBuffer == NULL )
         {
             VSIFree(pUpsampledSpectralBuffer);
@@ -1043,28 +1119,34 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
             return CE_Failure;
         }
 
-        if( anInputBands.size() )
+        if( !anInputBands.empty() )
         {
-            // Use dataset RasterIO when possible
-            eErr = aMSBands[0]->GetDataset()->RasterIO(GF_Read,
-                        nXOffExtract, nYOffExtract,
-                        nXSizeExtract, nYSizeExtract,
-                        pSpectralBuffer,
-                        nXSizeExtract, nYSizeExtract,
-                        eWorkDataType,
-                        (int)anInputBands.size(), &anInputBands[0],
-                        0, 0, 0, NULL);
+            // Use dataset RasterIO when possible.
+            eErr = aMSBands[0]->GetDataset()->RasterIO(
+                GF_Read,
+                nXOffExtract, nYOffExtract,
+                nXSizeExtract, nYSizeExtract,
+                pSpectralBuffer,
+                nXSizeExtract, nYSizeExtract,
+                eWorkDataType,
+                static_cast<int>(anInputBands.size()), &anInputBands[0],
+                0, 0, 0, NULL);
         }
         else
         {
-            for(int i=0; eErr == CE_None && i < psOptions->nInputSpectralBands; i++)
+            for( int i = 0;
+                 eErr == CE_None && i < psOptions->nInputSpectralBands;
+                 i++ )
             {
-                eErr = aMSBands[i]->RasterIO(GF_Read,
-                        nXOffExtract, nYOffExtract,
-                        nXSizeExtract, nYSizeExtract,
-                        pSpectralBuffer + (size_t)i * nXSizeExtract * nYSizeExtract * nDataTypeSize,
-                        nXSizeExtract, nYSizeExtract,
-                        eWorkDataType, 0, 0, NULL);
+                eErr = aMSBands[i]->RasterIO(
+                    GF_Read,
+                    nXOffExtract, nYOffExtract,
+                    nXSizeExtract, nYSizeExtract,
+                    pSpectralBuffer +
+                    static_cast<size_t>(i) *
+                    nXSizeExtract * nYSizeExtract * nDataTypeSize,
+                    nXSizeExtract, nYSizeExtract,
+                    eWorkDataType, 0, 0, NULL);
             }
         }
         if( eErr != CE_None )
@@ -1075,15 +1157,18 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
             return CE_Failure;
         }
 
-        /* Create a MEM dataset that wraps the input buffer */
+        // Create a MEM dataset that wraps the input buffer.
         GDALDataset* poMEMDS = MEMDataset::Create("", nXSizeExtract, nYSizeExtract, 0,
                                                   eWorkDataType, NULL);
 
-        char* apszOptions[4];
-        char szBuffer0[64], szBuffer1[64], szBuffer2[64];
-
-        snprintf(szBuffer1, sizeof(szBuffer1), "PIXELOFFSET=" CPL_FRMT_GIB, (GIntBig)nDataTypeSize);
-        snprintf(szBuffer2, sizeof(szBuffer2), "LINEOFFSET=" CPL_FRMT_GIB, (GIntBig)nDataTypeSize * nXSizeExtract);
+        char szBuffer0[64] = {};
+        char szBuffer1[64] = {};
+        char szBuffer2[64] = {};
+        snprintf(szBuffer1, sizeof(szBuffer1), "PIXELOFFSET=" CPL_FRMT_GIB,
+                 static_cast<GIntBig>(nDataTypeSize));
+        snprintf(szBuffer2, sizeof(szBuffer2), "LINEOFFSET=" CPL_FRMT_GIB,
+                 static_cast<GIntBig>(nDataTypeSize) * nXSizeExtract);
+        char* apszOptions[4] = {};
         apszOptions[0] = szBuffer0;
         apszOptions[1] = szBuffer1;
         apszOptions[2] = szBuffer2;
@@ -1091,21 +1176,28 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
 
         for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
         {
-            char szBuffer[64];
-            int nRet = CPLPrintPointer(szBuffer,
-                       pSpectralBuffer + (size_t)i * nDataTypeSize * nXSizeExtract * nYSizeExtract, sizeof(szBuffer));
+            char szBuffer[64] = {};
+            int nRet = CPLPrintPointer(
+                szBuffer,
+                pSpectralBuffer +
+                static_cast<size_t>(i) * nDataTypeSize * nXSizeExtract *
+                nYSizeExtract,
+                sizeof(szBuffer));
             szBuffer[nRet] = 0;
 
             snprintf(szBuffer0, sizeof(szBuffer0), "DATAPOINTER=%s", szBuffer);
 
             poMEMDS->AddBand(eWorkDataType, apszOptions);
 
-            const char* pszNBITS = aMSBands[i]->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+            const char* pszNBITS =
+                aMSBands[i]->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
             if( pszNBITS )
-                poMEMDS->GetRasterBand(i+1)->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
+                poMEMDS->GetRasterBand(i+1)->SetMetadataItem("NBITS", pszNBITS,
+                                                             "IMAGE_STRUCTURE");
 
             if( psOptions->bHasNoData )
-                poMEMDS->GetRasterBand(i+1)->SetNoDataValue(psOptions->dfNoData);
+                poMEMDS->GetRasterBand(i+1)
+                    ->SetNoDataValue(psOptions->dfNoData);
         }
 
         if( nTasks <= 1 )
@@ -1126,16 +1218,16 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
         }
         else
         {
-            // We are abusing the contract of the GDAL API by using the MEMDataset
-            // from several threads. In this case, this is safe. In case that would
-            // no longer be the case we could create as many MEMDataset as threads
-            // pointing to the same buffer.
+            // We are abusing the contract of the GDAL API by using the
+            // MEMDataset from several threads. In this case, this is safe. In
+            // case, that would no longer be the case we could create as many
+            // MEMDataset as threads pointing to the same buffer.
 
-            // To avoid races in threads, we query now the mask flags
-            // so that implicit mask bands are created now
+            // To avoid races in threads, we query now the mask flags,
+            // so that implicit mask bands are created now.
             if( eResampleAlg != GRIORA_NearestNeighbour )
             {
-                for(int i=0;i<poMEMDS->GetRasterCount();i++)
+                for( int i = 0; i < poMEMDS->GetRasterCount(); i++ )
                 {
                     poMEMDS->GetRasterBand(i+1)->GetMaskFlags();
                 }
@@ -1153,32 +1245,52 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
 #endif
                 for( int i=0;i<nTasks;i++)
                 {
-                    size_t iStartLine = ((size_t)i * nYSize) / nTasks;
-                    size_t iNextStartLine = ((size_t)(i+1) * nYSize) / nTasks;
+                    const size_t iStartLine =
+                        (static_cast<size_t>(i) * nYSize) / nTasks;
+                    const size_t iNextStartLine =
+                        (static_cast<size_t>(i+1) * nYSize) / nTasks;
                     pasJobs[i].poMEMDS = poMEMDS;
                     pasJobs[i].eResampleAlg = eResampleAlg;
                     pasJobs[i].dfXOff = sExtraArg.dfXOff - nXOffExtract;
-                    pasJobs[i].dfYOff = (nYOff + psOptions->dfMSShiftY + iStartLine) / dfRatioY - nYOffExtract;
+                    pasJobs[i].dfYOff =
+                        (nYOff + psOptions->dfMSShiftY + iStartLine) /
+                        dfRatioY - nYOffExtract;
                     pasJobs[i].dfXSize = sExtraArg.dfXSize;
-                    pasJobs[i].dfYSize = (iNextStartLine - iStartLine) / dfRatioY;
-                    if( pasJobs[i].dfXOff + pasJobs[i].dfXSize > aMSBands[0]->GetXSize() )
-                        pasJobs[i].dfXOff = aMSBands[0]->GetXSize() - pasJobs[i].dfXSize;
-                    if( pasJobs[i].dfYOff + pasJobs[i].dfYSize > aMSBands[0]->GetYSize() )
-                        pasJobs[i].dfYOff = aMSBands[0]->GetYSize() - pasJobs[i].dfYSize;
-                    pasJobs[i].nXOff = (int)pasJobs[i].dfXOff;
-                    pasJobs[i].nYOff = (int)pasJobs[i].dfYOff;
-                    pasJobs[i].nXSize = (int)(0.4999 + pasJobs[i].dfXSize);
-                    pasJobs[i].nYSize = (int)(0.4999 + pasJobs[i].dfYSize);
+                    pasJobs[i].dfYSize =
+                        (iNextStartLine - iStartLine) / dfRatioY;
+                    if( pasJobs[i].dfXOff + pasJobs[i].dfXSize >
+                        aMSBands[0]->GetXSize() )
+                    {
+                        pasJobs[i].dfXOff =
+                            aMSBands[0]->GetXSize() - pasJobs[i].dfXSize;
+                    }
+                    if( pasJobs[i].dfYOff + pasJobs[i].dfYSize >
+                        aMSBands[0]->GetYSize() )
+                    {
+                        pasJobs[i].dfYOff =
+                            aMSBands[0]->GetYSize() - pasJobs[i].dfYSize;
+                    }
+                    pasJobs[i].nXOff = static_cast<int>(pasJobs[i].dfXOff);
+                    pasJobs[i].nYOff = static_cast<int>(pasJobs[i].dfYOff);
+                    pasJobs[i].nXSize =
+                        static_cast<int>(0.4999 + pasJobs[i].dfXSize);
+                    pasJobs[i].nYSize =
+                        static_cast<int>(0.4999 + pasJobs[i].dfYSize);
                     if( pasJobs[i].nXSize == 0 )
                         pasJobs[i].nXSize = 1;
                     if( pasJobs[i].nYSize == 0 )
                         pasJobs[i].nYSize = 1;
-                    pasJobs[i].pBuffer = pUpsampledSpectralBuffer + (size_t)iStartLine * nXSize * nDataTypeSize;
+                    pasJobs[i].pBuffer =
+                        pUpsampledSpectralBuffer +
+                        static_cast<size_t>(iStartLine) *
+                        nXSize * nDataTypeSize;
                     pasJobs[i].eDT = eWorkDataType;
                     pasJobs[i].nBufXSize = nXSize;
-                    pasJobs[i].nBufYSize = (int)(iNextStartLine - iStartLine);
+                    pasJobs[i].nBufYSize =
+                        static_cast<int>(iNextStartLine - iStartLine);
                     pasJobs[i].nBandCount = psOptions->nInputSpectralBands;
-                    pasJobs[i].nBandSpace = (GSpacing)nXSize * nYSize * nDataTypeSize;
+                    pasJobs[i].nBandSpace =
+                        static_cast<GSpacing>(nXSize) * nYSize * nDataTypeSize;
 #ifdef DEBUG_TIMING
                     pasJobs[i].ptv = &tv;
 #endif
@@ -1187,7 +1299,8 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
 #ifdef DEBUG_TIMING
                 gettimeofday(&tv, NULL);
 #endif
-                poThreadPool->SubmitJobs(PansharpenResampleJobThreadFunc, ahJobData);
+                poThreadPool->SubmitJobs(PansharpenResampleJobThreadFunc,
+                                         ahJobData);
                 poThreadPool->WaitCompletion();
             }
         }
@@ -1198,28 +1311,33 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
     }
     else
     {
-        if( anInputBands.size() )
+        if( !anInputBands.empty() )
         {
-            // Use dataset RasterIO when possible
-            eErr = aMSBands[0]->GetDataset()->RasterIO(GF_Read,
-                        nSpectralXOff, nSpectralYOff,
-                        nSpectralXSize, nSpectralYSize,
-                        pUpsampledSpectralBuffer,
-                        nXSize, nYSize,
-                        eWorkDataType,
-                        (int)anInputBands.size(), &anInputBands[0],
-                        0, 0, 0, &sExtraArg);
+            // Use dataset RasterIO when possible.
+            eErr = aMSBands[0]->GetDataset()->RasterIO(
+                GF_Read,
+                nSpectralXOff, nSpectralYOff,
+                nSpectralXSize, nSpectralYSize,
+                pUpsampledSpectralBuffer,
+                nXSize, nYSize,
+                eWorkDataType,
+                static_cast<int>(anInputBands.size()), &anInputBands[0],
+                0, 0, 0, &sExtraArg);
         }
         else
         {
-            for(int i=0; eErr == CE_None && i < psOptions->nInputSpectralBands; i++)
+            for( int i = 0;
+                 eErr == CE_None && i < psOptions->nInputSpectralBands;
+                 i++ )
             {
-                eErr = aMSBands[i]->RasterIO(GF_Read,
-                        nSpectralXOff, nSpectralYOff,
-                        nSpectralXSize, nSpectralYSize,
-                        pUpsampledSpectralBuffer + (size_t)i * nXSize * nYSize * nDataTypeSize,
-                        nXSize, nYSize,
-                        eWorkDataType, 0, 0, &sExtraArg);
+                eErr = aMSBands[i]->RasterIO(
+                    GF_Read,
+                    nSpectralXOff, nSpectralYOff,
+                    nSpectralXSize, nSpectralYSize,
+                    pUpsampledSpectralBuffer +
+                    static_cast<size_t>(i) * nXSize * nYSize * nDataTypeSize,
+                    nXSize, nYSize,
+                    eWorkDataType, 0, 0, &sExtraArg);
             }
         }
         if( eErr != CE_None )
@@ -1237,11 +1355,12 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
                       eResampleAlg == GRIORA_CubicSpline ||
                       eResampleAlg == GRIORA_Lanczos) )
     {
-        for(int i=0;i < psOptions->nInputSpectralBands; i++)
+        for( int i = 0; i < psOptions->nInputSpectralBands; i++ )
         {
             GDALRasterBand* poBand = aMSBands[i];
             int nBandBitDepth = 0;
-            const char* pszNBITS = poBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+            const char* pszNBITS =
+                poBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
             if( pszNBITS )
                 nBandBitDepth = atoi(pszNBITS);
             if( nBandBitDepth < nBitDepth )
@@ -1261,9 +1380,10 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
 #ifndef LIMIT_TYPES
                 else if( eWorkDataType == GDT_UInt32 )
                 {
-                    ClampValues(((GUInt32*)pUpsampledSpectralBuffer) + i * nXSize * nYSize,
-                               nXSize*nYSize,
-                               (GUInt32)((1 << nBitDepth)-1));
+                    ClampValues(((GUInt32*)pUpsampledSpectralBuffer) +
+                                i * nXSize * nYSize,
+                                nXSize*nYSize,
+                                (GUInt32)((1 << nBitDepth)-1));
                 }
 #endif
             }
@@ -1282,8 +1402,10 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
     if( eBufDataType == GDT_CFloat64 )
 #endif
     {
-        padfTempBuffer = (double*)VSI_MALLOC3_VERBOSE(nXSize, nYSize,
-                    psOptions->nOutPansharpenedBands * sizeof(double));
+        padfTempBuffer = static_cast<double * >(
+            VSI_MALLOC3_VERBOSE(
+                nXSize, nYSize,
+                psOptions->nOutPansharpenedBands * sizeof(double)));
         if( padfTempBuffer == NULL )
         {
             VSIFree(pUpsampledSpectralBuffer);
@@ -1307,18 +1429,24 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
 #endif
             for( int i=0;i<nTasks;i++)
             {
-                size_t iStartLine = ((size_t)i * nYSize) / nTasks;
-                size_t iNextStartLine = ((size_t)(i+1) * nYSize) / nTasks;
+                const size_t iStartLine =
+                    (static_cast<size_t>(i) * nYSize) / nTasks;
+                const size_t iNextStartLine =
+                    (static_cast<size_t>(i + 1) * nYSize) / nTasks;
                 pasJobs[i].poPansharpenOperation = this;
                 pasJobs[i].eWorkDataType = eWorkDataType;
                 pasJobs[i].eBufDataType = eBufDataType;
-                pasJobs[i].pPanBuffer = pPanBuffer + iStartLine *  nXSize * nDataTypeSize;
-                pasJobs[i].pUpsampledSpectralBuffer = pUpsampledSpectralBuffer + iStartLine * nXSize * nDataTypeSize;
+                pasJobs[i].pPanBuffer =
+                    pPanBuffer + iStartLine *  nXSize * nDataTypeSize;
+                pasJobs[i].pUpsampledSpectralBuffer =
+                    pUpsampledSpectralBuffer +
+                    iStartLine * nXSize * nDataTypeSize;
                 pasJobs[i].pDataBuf =
                     static_cast<GByte*>(pDataBuf) +
                     iStartLine * nXSize *
                     GDALGetDataTypeSizeBytes(eBufDataType);
-                pasJobs[i].nValues = (int)(iNextStartLine - iStartLine) * nXSize;
+                pasJobs[i].nValues =
+                    static_cast<int>(iNextStartLine - iStartLine) * nXSize;
                 pasJobs[i].nBandValues = nXSize * nYSize;
                 pasJobs[i].nMaxValue = nMaxValue;
 #ifdef DEBUG_TIMING
@@ -1370,7 +1498,7 @@ CPLErr GDALPansharpenOperation::ProcessRegion(int nXOff, int nYOff,
 /*                   PansharpenResampleJobThreadFunc()                  */
 /************************************************************************/
 
-//static int acc=0;
+// static int acc=0;
 
 void GDALPansharpenOperation::PansharpenResampleJobThreadFunc(void* pUserData)
 {
@@ -1379,8 +1507,12 @@ void GDALPansharpenOperation::PansharpenResampleJobThreadFunc(void* pUserData)
 #ifdef DEBUG_TIMING
     struct timeval tv;
     gettimeofday(&tv, NULL);
-    GIntBig launch_time = (GIntBig)psJob->ptv->tv_sec * 1000000 + (GIntBig)psJob->ptv->tv_usec;
-    GIntBig start_job = (GIntBig)tv.tv_sec * 1000000 + (GIntBig)tv.tv_usec;
+    const GIntBig launch_time =
+        static_cast<GIntBig>(psJob->ptv->tv_sec) * 1000000 +
+        static_cast<GIntBig>(psJob->ptv->tv_usec);
+    const GIntBig start_job =
+        static_cast<GIntBig>(tv.tv_sec) * 1000000 +
+        static_cast<GIntBig>(tv.tv_usec);
 #endif
 
 #if 0
@@ -1414,9 +1546,12 @@ void GDALPansharpenOperation::PansharpenResampleJobThreadFunc(void* pUserData)
 #ifdef DEBUG_TIMING
     struct timeval tv_end;
     gettimeofday(&tv_end, NULL);
-    GIntBig end = (GIntBig)tv_end.tv_sec * 1000000 + (GIntBig)tv_end.tv_usec;
+    const GIntBig end =
+        static_cast<GIntBig>(tv_end.tv_sec) * 1000000 +
+        static_cast<GIntBig>(tv_end.tv_usec);
     if( start_job - launch_time > 500 )
-        printf("Resample: Delay before start=" CPL_FRMT_GIB ", completion time=" CPL_FRMT_GIB "\n",
+        /*ok*/printf("Resample: Delay before start=" CPL_FRMT_GIB
+               ", completion time=" CPL_FRMT_GIB "\n",
                start_job - launch_time, end - start_job);
 #endif
 }
@@ -1432,31 +1567,39 @@ void GDALPansharpenOperation::PansharpenJobThreadFunc(void* pUserData)
 #ifdef DEBUG_TIMING
     struct timeval tv;
     gettimeofday(&tv, NULL);
-    GIntBig launch_time = (GIntBig)psJob->ptv->tv_sec * 1000000 + (GIntBig)psJob->ptv->tv_usec;
-    GIntBig start_job = (GIntBig)tv.tv_sec * 1000000 + (GIntBig)tv.tv_usec;
+    const GIntBig launch_time =
+        static_cast<GIntBig>(psJob->ptv->tv_sec) * 1000000 +
+        static_cast<GIntBig>(psJob->ptv->tv_usec);
+    const GIntBig start_job =
+        static_cast<GIntBig>(tv.tv_sec) * 1000000 +
+        static_cast<GIntBig>(tv.tv_usec);
 #endif
 
 #if 0
-    for(int i=0;i<1000000;i++)
+    for( int i = 0; i < 1000000; i++ )
         acc += i * i;
     psJob->eErr = CE_None;
 #else
-    psJob->eErr = psJob->poPansharpenOperation->PansharpenChunk(psJob->eWorkDataType,
-                                  psJob->eBufDataType,
-                                  psJob->pPanBuffer,
-                                  psJob->pUpsampledSpectralBuffer,
-                                  psJob->pDataBuf,
-                                  psJob->nValues,
-                                  psJob->nBandValues,
-                                  psJob->nMaxValue);
+    psJob->eErr = psJob->poPansharpenOperation->PansharpenChunk(
+        psJob->eWorkDataType,
+        psJob->eBufDataType,
+        psJob->pPanBuffer,
+        psJob->pUpsampledSpectralBuffer,
+        psJob->pDataBuf,
+        psJob->nValues,
+        psJob->nBandValues,
+        psJob->nMaxValue);
 #endif
 
 #ifdef DEBUG_TIMING
     struct timeval tv_end;
     gettimeofday(&tv_end, NULL);
-    GIntBig end = (GIntBig)tv_end.tv_sec * 1000000 + (GIntBig)tv_end.tv_usec;
+    const GIntBig end =
+        static_cast<GIntBig>(tv_end.tv_sec) * 1000000 +
+        static_cast<GIntBig>(tv_end.tv_usec);
     if( start_job - launch_time > 500 )
-        printf("Pansharpen: Delay before start=" CPL_FRMT_GIB ", completion time=" CPL_FRMT_GIB "\n",
+        /*ok*/printf("Pansharpen: Delay before start=" CPL_FRMT_GIB
+               ", completion time=" CPL_FRMT_GIB "\n",
                start_job - launch_time, end - start_job);
 #endif
 }
@@ -1465,67 +1608,68 @@ void GDALPansharpenOperation::PansharpenJobThreadFunc(void* pUserData)
 /*                           PansharpenChunk()                          */
 /************************************************************************/
 
-CPLErr GDALPansharpenOperation::PansharpenChunk( GDALDataType eWorkDataType,
-                                                 GDALDataType eBufDataType,
-                                                 const void* pPanBuffer,
-                                                 const void* pUpsampledSpectralBuffer,
-                                                 void* pDataBuf,
-                                                 int nValues,
-                                                 int nBandValues,
-                                                 GUInt32 nMaxValue) const
+CPLErr
+GDALPansharpenOperation::PansharpenChunk( GDALDataType eWorkDataType,
+                                          GDALDataType eBufDataType,
+                                          const void* pPanBuffer,
+                                          const void* pUpsampledSpectralBuffer,
+                                          void* pDataBuf,
+                                          int nValues,
+                                          int nBandValues,
+                                          GUInt32 nMaxValue) const
 {
-    CPLErr eErr;
+    CPLErr eErr = CE_None;
 
     switch( eWorkDataType )
     {
         case GDT_Byte:
-            eErr = WeightedBrovey ((GByte*)pPanBuffer,
-                                   (GByte*)pUpsampledSpectralBuffer,
-                                   pDataBuf, eBufDataType,
-                                   nValues, nBandValues, (GByte)nMaxValue);
+            eErr = WeightedBrovey((GByte*)pPanBuffer,
+                                  (GByte*)pUpsampledSpectralBuffer,
+                                  pDataBuf, eBufDataType,
+                                  nValues, nBandValues, (GByte)nMaxValue);
             break;
 
         case GDT_UInt16:
-            eErr = WeightedBrovey ((GUInt16*)pPanBuffer,
-                                   (GUInt16*)pUpsampledSpectralBuffer,
-                                   pDataBuf, eBufDataType,
-                                   nValues, nBandValues, (GUInt16)nMaxValue);
+            eErr = WeightedBrovey((GUInt16*)pPanBuffer,
+                                  (GUInt16*)pUpsampledSpectralBuffer,
+                                  pDataBuf, eBufDataType,
+                                  nValues, nBandValues, (GUInt16)nMaxValue);
             break;
 
 #ifndef LIMIT_TYPES
         case GDT_Int16:
-            eErr = WeightedBrovey ((GInt16*)pPanBuffer,
-                                   (GInt16*)pUpsampledSpectralBuffer,
-                                   pDataBuf, eBufDataType,
-                                   nValues, nBandValues);
+            eErr = WeightedBrovey((GInt16*)pPanBuffer,
+                                  (GInt16*)pUpsampledSpectralBuffer,
+                                  pDataBuf, eBufDataType,
+                                  nValues, nBandValues);
             break;
 
         case GDT_UInt32:
-            eErr = WeightedBrovey ((GUInt32*)pPanBuffer,
-                                   (GUInt32*)pUpsampledSpectralBuffer,
-                                   pDataBuf, eBufDataType,
-                                   nValues, nBandValues, nMaxValue);
+            eErr = WeightedBrovey((GUInt32*)pPanBuffer,
+                                  (GUInt32*)pUpsampledSpectralBuffer,
+                                  pDataBuf, eBufDataType,
+                                  nValues, nBandValues, nMaxValue);
             break;
 
         case GDT_Int32:
-            eErr = WeightedBrovey ((GInt32*)pPanBuffer,
-                                   (GInt32*)pUpsampledSpectralBuffer,
-                                   pDataBuf, eBufDataType,
-                                   nValues, nBandValues);
+            eErr = WeightedBrovey((GInt32*)pPanBuffer,
+                                  (GInt32*)pUpsampledSpectralBuffer,
+                                  pDataBuf, eBufDataType,
+                                  nValues, nBandValues);
             break;
 
         case GDT_Float32:
-            eErr = WeightedBrovey ((float*)pPanBuffer,
-                                   (float*)pUpsampledSpectralBuffer,
-                                   pDataBuf, eBufDataType,
-                                   nValues, nBandValues);
+            eErr = WeightedBrovey((float*)pPanBuffer,
+                                  (float*)pUpsampledSpectralBuffer,
+                                  pDataBuf, eBufDataType,
+                                  nValues, nBandValues);
             break;
 #endif
         case GDT_Float64:
-            eErr = WeightedBrovey ((double*)pPanBuffer,
-                                   (double*)pUpsampledSpectralBuffer,
-                                   pDataBuf, eBufDataType,
-                                   nValues, nBandValues);
+            eErr = WeightedBrovey((double*)pPanBuffer,
+                                  (double*)pUpsampledSpectralBuffer,
+                                  pDataBuf, eBufDataType,
+                                  nValues, nBandValues);
             break;
 
         default:
@@ -1538,11 +1682,13 @@ CPLErr GDALPansharpenOperation::PansharpenChunk( GDALDataType eWorkDataType,
     return eErr;
 }
 
-
 /************************************************************************/
 /*                             GetOptions()                             */
 /************************************************************************/
 
+/** Return options.
+ * @return options.
+ */
 GDALPansharpenOptions* GDALPansharpenOperation::GetOptions()
 {
     return psOptions;
@@ -1564,7 +1710,7 @@ GDALPansharpenOptions* GDALPansharpenOperation::GetOptions()
  */
 
 GDALPansharpenOperationH GDALCreatePansharpenOperation(
-                                    const GDALPansharpenOptions* psOptions )
+    const GDALPansharpenOptions* psOptions )
 {
     GDALPansharpenOperation* psOperation = new GDALPansharpenOperation();
     if( psOperation->Initialize(psOptions) == CE_None )
@@ -1586,7 +1732,7 @@ GDALPansharpenOperationH GDALCreatePansharpenOperation(
 
 void GDALDestroyPansharpenOperation( GDALPansharpenOperationH hOperation )
 {
-    delete (GDALPansharpenOperation*)hOperation;
+    delete reinterpret_cast<GDALPansharpenOperation*>(hOperation);
 }
 
 /************************************************************************/
@@ -1624,7 +1770,8 @@ CPLErr GDALPansharpenProcessRegion( GDALPansharpenOperationH hOperation,
                                     void *pDataBuf,
                                     GDALDataType eBufDataType)
 {
-    return ((GDALPansharpenOperation*)hOperation)->ProcessRegion(nXOff, nYOff,
+    return reinterpret_cast<GDALPansharpenOperation*>(hOperation)->
+                                          ProcessRegion(nXOff, nYOff,
                                                         nXSize, nYSize,
                                                         pDataBuf, eBufDataType);
 }
diff --git a/alg/gdalpansharpen.h b/alg/gdalpansharpen.h
index 97f60db..9c5857a 100644
--- a/alg/gdalpansharpen.h
+++ b/alg/gdalpansharpen.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalpansharpen.h 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: gdalpansharpen.h 36427 2016-11-22 12:56:01Z rouault $
  *
  * Project:  GDAL Pansharpening module
  * Purpose:  Prototypes, and definitions for pansharpening related work.
@@ -100,12 +100,14 @@ typedef struct
       * unless the GDAL_NUM_THREADS configuration option is set to an integer or ALL_CPUS. */
     int                  nThreads;
 
+    /** Shift in pixels of multispectral bands w.r.t panchromatic band, in X direction */
     double               dfMSShiftX;
+
+    /** Shift in pixels of multispectral bands w.r.t panchromatic band, in Y direction */
     double               dfMSShiftY;
 
 } GDALPansharpenOptions;
 
-
 GDALPansharpenOptions CPL_DLL * GDALCreatePansharpenOptions(void);
 void CPL_DLL GDALDestroyPansharpenOptions( GDALPansharpenOptions * );
 GDALPansharpenOptions CPL_DLL * GDALClonePansharpenOptions(
@@ -136,6 +138,7 @@ CPL_C_END
 
 class GDALPansharpenOperation;
 
+//! @cond Doxygen_Suppress
 typedef struct
 {
     GDALPansharpenOperation* poPansharpenOperation;
@@ -178,6 +181,7 @@ typedef struct
     struct timeval* ptv;
 #endif
 } GDALPansharpenResampleJob;
+//! @endcond
 
 /** Pansharpening operation class.
  */
@@ -208,6 +212,8 @@ class GDALPansharpenOperation
                                                      int nValues,
                                                      int nBandValues,
                                                      WorkDataType nMaxValue) const;
+
+        // cppcheck-suppress functionStatic
         template<class WorkDataType, class OutDataType> void WeightedBrovey(
                                                      const WorkDataType* pPanBuffer,
                                                      const WorkDataType* pUpsampledSpectralBuffer,
@@ -223,6 +229,8 @@ class GDALPansharpenOperation
                                                      int nValues,
                                                      int nBandValues,
                                                      WorkDataType nMaxValue) const;
+
+        // cppcheck-suppress functionStatic
         template<class WorkDataType> CPLErr WeightedBrovey(
                                                      const WorkDataType* pPanBuffer,
                                                      const WorkDataType* pUpsampledSpectralBuffer,
diff --git a/alg/gdalproximity.cpp b/alg/gdalproximity.cpp
index 1fc490e..3d7e085 100644
--- a/alg/gdalproximity.cpp
+++ b/alg/gdalproximity.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalproximity.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Compute each pixel's proximity to a set of target pixels.
@@ -28,11 +27,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_alg.h"
+
+#include <cmath>
+#include <cstdlib>
+
+#include <algorithm>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 
-CPL_CVSID("$Id: gdalproximity.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: gdalproximity.cpp 36721 2016-12-06 05:02:46Z goatbar $");
 
 static CPLErr
 ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
@@ -98,7 +108,6 @@ If this option is set, all pixels within the MAXDIST threadhold are
 set to this fixed value instead of to a proximity distance.
 */
 
-
 CPLErr CPL_STDCALL
 GDALComputeProximity( GDALRasterBandH hSrcBand,
                       GDALRasterBandH hProximityBand,
@@ -107,11 +116,6 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
                       void * pProgressArg )
 
 {
-    int nXSize, nYSize, i, bFixedBufVal = FALSE;
-    const char *pszOpt;
-    double dfMaxDist;
-    double dfFixedBufVal = 0.0;
-
     VALIDATE_POINTER1( hSrcBand, "GDALComputeProximity", CE_Failure );
     VALIDATE_POINTER1( hProximityBand, "GDALComputeProximity", CE_Failure );
 
@@ -122,29 +126,31 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /*      Are we using pixels or georeferenced coordinates for distances? */
 /* -------------------------------------------------------------------- */
     double dfDistMult = 1.0;
-    pszOpt = CSLFetchNameValue( papszOptions, "DISTUNITS" );
+    const char *pszOpt = CSLFetchNameValue( papszOptions, "DISTUNITS" );
     if( pszOpt )
     {
-        if( EQUAL(pszOpt,"GEO") )
+        if( EQUAL(pszOpt, "GEO") )
         {
             GDALDatasetH hSrcDS = GDALGetBandDataset( hSrcBand );
             if( hSrcDS )
             {
-                double adfGeoTransform[6];
+                double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
 
                 GDALGetGeoTransform( hSrcDS, adfGeoTransform );
-                if( ABS(adfGeoTransform[1]) != ABS(adfGeoTransform[5]) )
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "Pixels not square, distances will be inaccurate." );
-                dfDistMult = ABS(adfGeoTransform[1]);
+                if( std::abs(adfGeoTransform[1]) !=
+                    std::abs(adfGeoTransform[5]) )
+                    CPLError(
+                        CE_Warning, CPLE_AppDefined,
+                        "Pixels not square, distances will be inaccurate." );
+                dfDistMult = std::abs(adfGeoTransform[1]);
             }
         }
-        else if( !EQUAL(pszOpt,"PIXEL") )
+        else if( !EQUAL(pszOpt, "PIXEL") )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unrecognized DISTUNITS value '%s', "
-                      "should be GEO or PIXEL.",
-                      pszOpt );
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Unrecognized DISTUNITS value '%s', should be GEO or PIXEL.",
+                pszOpt );
             return CE_Failure;
         }
     }
@@ -153,18 +159,17 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /*      What is our maxdist value?                                      */
 /* -------------------------------------------------------------------- */
     pszOpt = CSLFetchNameValue( papszOptions, "MAXDIST" );
-    if( pszOpt )
-        dfMaxDist = CPLAtof(pszOpt) / dfDistMult;
-    else
-        dfMaxDist = GDALGetRasterBandXSize(hSrcBand) + GDALGetRasterBandYSize(hSrcBand);
+    const double dfMaxDist = pszOpt ?
+        CPLAtof(pszOpt) / dfDistMult :
+        GDALGetRasterBandXSize(hSrcBand) + GDALGetRasterBandYSize(hSrcBand);
 
     CPLDebug( "GDAL", "MAXDIST=%g, DISTMULT=%g", dfMaxDist, dfDistMult );
 
 /* -------------------------------------------------------------------- */
 /*      Verify the source and destination are compatible.               */
 /* -------------------------------------------------------------------- */
-    nXSize = GDALGetRasterBandXSize( hSrcBand );
-    nYSize = GDALGetRasterBandYSize( hSrcBand );
+    const int nXSize = GDALGetRasterBandXSize( hSrcBand );
+    const int nYSize = GDALGetRasterBandYSize( hSrcBand );
     if( nXSize != GDALGetRasterBandXSize( hProximityBand )
         || nYSize != GDALGetRasterBandYSize( hProximityBand ))
     {
@@ -178,7 +183,7 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
     double dfSrcNoDataValue = 0.0;
     double *pdfSrcNoData = NULL;
-    if( CSLFetchBoolean( papszOptions, "USE_INPUT_NODATA", FALSE ) )
+    if( CPLFetchBool( papszOptions, "USE_INPUT_NODATA", false ) )
     {
         int bSrcHasNoData = 0;
         dfSrcNoDataValue = GDALGetRasterNoDataValue( hSrcBand, &bSrcHasNoData );
@@ -189,15 +194,18 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
 /*      Get output NODATA value.                                        */
 /* -------------------------------------------------------------------- */
-    float fNoDataValue;
+    float fNoDataValue = 0.0f;
     pszOpt = CSLFetchNameValue( papszOptions, "NODATA" );
     if( pszOpt != NULL )
-        fNoDataValue = (float) CPLAtof(pszOpt);
+    {
+        fNoDataValue = static_cast<float>(CPLAtof(pszOpt));
+    }
     else
     {
-        int bSuccess;
+        int bSuccess = FALSE;
 
-        fNoDataValue = (float) GDALGetRasterNoDataValue( hProximityBand, &bSuccess );
+        fNoDataValue = static_cast<float>(
+            GDALGetRasterNoDataValue( hProximityBand, &bSuccess ) );
         if( !bSuccess )
             fNoDataValue = 65535.0;
     }
@@ -205,30 +213,32 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
 /*      Is there a fixed value we wish to force the buffer area to?     */
 /* -------------------------------------------------------------------- */
+    double dfFixedBufVal = 0.0;
+    bool bFixedBufVal = false;
     pszOpt = CSLFetchNameValue( papszOptions, "FIXED_BUF_VAL" );
     if( pszOpt )
     {
         dfFixedBufVal = CPLAtof(pszOpt);
-        bFixedBufVal = TRUE;
+        bFixedBufVal = true;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Get the target value(s).                                        */
 /* -------------------------------------------------------------------- */
     int *panTargetValues = NULL;
-    int  nTargetValues = 0;
+    int nTargetValues = 0;
 
     pszOpt = CSLFetchNameValue( papszOptions, "VALUES" );
     if( pszOpt != NULL )
     {
-        char **papszValuesTokens;
-
-        papszValuesTokens = CSLTokenizeStringComplex( pszOpt, ",", FALSE,FALSE);
+        char **papszValuesTokens =
+            CSLTokenizeStringComplex( pszOpt, ",", FALSE, FALSE);
 
         nTargetValues = CSLCount(papszValuesTokens);
-        panTargetValues = (int *) CPLCalloc(sizeof(int),nTargetValues);
+        panTargetValues = static_cast<int *>(
+            CPLCalloc(sizeof(int), nTargetValues) );
 
-        for( i = 0; i < nTargetValues; i++ )
+        for( int i = 0; i < nTargetValues; i++ )
             panTargetValues[i] = atoi(papszValuesTokens[i]);
         CSLDestroy( papszValuesTokens );
     }
@@ -250,22 +260,24 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
     GDALRasterBandH hWorkProximityBand = hProximityBand;
     GDALDatasetH hWorkProximityDS = NULL;
-    GDALDataType eProxType = GDALGetRasterDataType( hProximityBand );
-    int   *panNearX = NULL, *panNearY = NULL;
+    const GDALDataType eProxType = GDALGetRasterDataType(hProximityBand);
+    CPLErr eErr = CE_None;
+
+    // TODO(schwehr): Localize after removing gotos.
     float *pafProximity = NULL;
+    int *panNearX = NULL;
+    int *panNearY = NULL;
     GInt32 *panSrcScanline = NULL;
-    int iLine;
-    CPLErr eErr = CE_None;
 
     if( eProxType == GDT_Byte
         || eProxType == GDT_UInt16
         || eProxType == GDT_UInt32 )
     {
         GDALDriverH hDriver = GDALGetDriverByName("GTiff");
-        if (hDriver == NULL)
+        if( hDriver == NULL )
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "GDALComputeProximity needs GTiff driver");
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "GDALComputeProximity needs GTiff driver" );
             eErr = CE_Failure;
             goto end;
         }
@@ -273,7 +285,7 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
         hWorkProximityDS =
             GDALCreate( hDriver, osTmpFile,
                         nXSize, nYSize, 1, GDT_Float32, NULL );
-        if (hWorkProximityDS == NULL)
+        if( hWorkProximityDS == NULL )
         {
             eErr = CE_Failure;
             goto end;
@@ -285,12 +297,16 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /*      Allocate buffer for two scanlines of distances as floats        */
 /*      (the current and last line).                                    */
 /* -------------------------------------------------------------------- */
-    pafProximity = (float *) VSI_MALLOC2_VERBOSE(sizeof(float), nXSize);
-    panNearX = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nXSize);
-    panNearY = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nXSize);
-    panSrcScanline = (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
+    pafProximity =
+        static_cast<float *>(VSI_MALLOC2_VERBOSE(sizeof(float), nXSize));
+    panNearX =
+        static_cast<int *>(VSI_MALLOC2_VERBOSE(sizeof(int), nXSize));
+    panNearY =
+        static_cast<int *>(VSI_MALLOC2_VERBOSE(sizeof(int), nXSize));
+    panSrcScanline =
+        static_cast<GInt32 *>(VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize));
 
-    if( pafProximity== NULL
+    if( pafProximity == NULL
         || panNearX == NULL
         || panNearY == NULL
         || panSrcScanline == NULL)
@@ -303,10 +319,13 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /*      Loop from top to bottom of the image.                           */
 /* -------------------------------------------------------------------- */
 
-    for( i = 0; i < nXSize; i++ )
-        panNearX[i] = panNearY[i] = -1;
+    for( int i = 0; i < nXSize; i++ )
+    {
+        panNearX[i] = -1;
+        panNearY[i] = -1;
+    }
 
-    for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
+    for( int iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
     {
         // Read for target values.
         eErr = GDALRasterIO( hSrcBand, GF_Read, 0, iLine, nXSize, 1,
@@ -314,15 +333,15 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
         if( eErr != CE_None )
             break;
 
-        for( i = 0; i < nXSize; i++ )
+        for( int i = 0; i < nXSize; i++ )
             pafProximity[i] = -1.0;
 
-        // Left to right
+        // Left to right.
         ProcessProximityLine( panSrcScanline, panNearX, panNearY,
                               TRUE, iLine, nXSize, dfMaxDist, pafProximity,
                               pdfSrcNoData, nTargetValues, panTargetValues );
 
-        // Right to Left
+        // Right to Left.
         ProcessProximityLine( panSrcScanline, panNearX, panNearY,
                               FALSE, iLine, nXSize, dfMaxDist, pafProximity,
                               pdfSrcNoData, nTargetValues, panTargetValues );
@@ -335,7 +354,7 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
         if( eErr != CE_None )
             break;
 
-        if( !pfnProgress( 0.5 * (iLine+1) / (double) nYSize,
+        if( !pfnProgress( 0.5 * (iLine+1) / static_cast<double>(nYSize),
                           "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -346,12 +365,15 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
 /*      Loop from bottom to top of the image.                           */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nXSize; i++ )
-        panNearX[i] = panNearY[i] = -1;
+    for( int i = 0; i < nXSize; i++ )
+    {
+        panNearX[i] = -1;
+        panNearY[i] = -1;
+    }
 
-    for( iLine = nYSize-1; eErr == CE_None && iLine >= 0; iLine-- )
+    for( int iLine = nYSize-1; eErr == CE_None && iLine >= 0; iLine-- )
     {
-        // Read first pass proximity
+        // Read first pass proximity.
         eErr =
             GDALRasterIO( hWorkProximityBand, GF_Read, 0, iLine, nXSize, 1,
                           pafProximity, nXSize, 1, GDT_Float32, 0, 0 );
@@ -366,27 +388,28 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
         if( eErr != CE_None )
             break;
 
-        // Right to left
+        // Right to left.
         ProcessProximityLine( panSrcScanline, panNearX, panNearY,
                               FALSE, iLine, nXSize, dfMaxDist, pafProximity,
                               pdfSrcNoData, nTargetValues, panTargetValues );
 
-        // Left to right
+        // Left to right.
         ProcessProximityLine( panSrcScanline, panNearX, panNearY,
                               TRUE, iLine, nXSize, dfMaxDist, pafProximity,
                               pdfSrcNoData, nTargetValues, panTargetValues );
 
         // Final post processing of distances.
-        for( i = 0; i < nXSize; i++ )
+        for( int i = 0; i < nXSize; i++ )
         {
             if( pafProximity[i] < 0.0 )
                 pafProximity[i] = fNoDataValue;
             else if( pafProximity[i] > 0.0 )
             {
                 if( bFixedBufVal )
-                    pafProximity[i] = (float) dfFixedBufVal;
+                    pafProximity[i] = static_cast<float>( dfFixedBufVal );
                 else
-                    pafProximity[i] = (float)(pafProximity[i] * dfDistMult);
+                    pafProximity[i] =
+                        static_cast<float>(pafProximity[i] * dfDistMult);
             }
         }
 
@@ -398,7 +421,8 @@ GDALComputeProximity( GDALRasterBandH hSrcBand,
         if( eErr != CE_None )
             break;
 
-        if( !pfnProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize,
+        if( !pfnProgress( 0.5 +
+                          0.5 * (nYSize-iLine) / static_cast<double>( nYSize ),
                           "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -414,7 +438,7 @@ end:
     CPLFree( panNearY );
     CPLFree( panSrcScanline );
     CPLFree( pafProximity );
-    CPLFree(panTargetValues);
+    CPLFree( panTargetValues );
 
     if( hWorkProximityDS != NULL )
     {
@@ -437,35 +461,24 @@ ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
                       int nTargetValues, int *panTargetValues )
 
 {
-    int iStart, iEnd, iStep, iPixel;
+    const int iStart = bForward ? 0 : nXSize - 1;
+    const int iEnd = bForward ? nXSize : -1;
+    const int iStep = bForward ? 1 : -1;
 
-    if( bForward )
+    for( int iPixel = iStart; iPixel != iEnd; iPixel += iStep )
     {
-        iStart = 0;
-        iEnd = nXSize;
-        iStep = 1;
-    }
-    else
-    {
-        iStart = nXSize-1;
-        iEnd = -1;
-        iStep = -1;
-    }
-
-    for( iPixel = iStart; iPixel != iEnd; iPixel += iStep )
-    {
-        int bIsTarget = FALSE;
+        bool bIsTarget = false;
 
 /* -------------------------------------------------------------------- */
 /*      Is the current pixel a target pixel?                            */
 /* -------------------------------------------------------------------- */
         if( nTargetValues == 0 )
-            bIsTarget = (panSrcScanline[iPixel] != 0);
+        {
+            bIsTarget = panSrcScanline[iPixel] != 0;
+        }
         else
         {
-            int i;
-
-            for( i = 0; i < nTargetValues; i++ )
+            for( int i = 0; i < nTargetValues; i++ )
             {
                 if( panSrcScanline[iPixel] == panTargetValues[i] )
                     bIsTarget = TRUE;
@@ -484,13 +497,15 @@ ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
 /*      Are we near(er) to the closest target to the above (below)      */
 /*      pixel?                                                          */
 /* -------------------------------------------------------------------- */
-        float fNearDistSq = (float) (MAX(dfMaxDist,nXSize) * MAX(dfMaxDist,nXSize) * 2);
-        float fDistSq;
+        float fNearDistSq =
+            static_cast<float>(
+                std::max(dfMaxDist, static_cast<double>(nXSize)) *
+                std::max(dfMaxDist, static_cast<double>(nXSize)) * 2.0);
 
         if( panNearX[iPixel] != -1 )
         {
-            fDistSq = (float)
-                ((panNearX[iPixel] - iPixel) * (panNearX[iPixel] - iPixel)
+            const float fDistSq = static_cast<float>(
+                (panNearX[iPixel] - iPixel) * (panNearX[iPixel] - iPixel)
                  + (panNearY[iPixel] - iLine) * (panNearY[iPixel] - iLine));
 
             if( fDistSq < fNearDistSq )
@@ -508,12 +523,12 @@ ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
 /*      Are we near(er) to the closest target to the left (right)       */
 /*      pixel?                                                          */
 /* -------------------------------------------------------------------- */
-        int iLast = iPixel-iStep;
+        const int iLast = iPixel - iStep;
 
         if( iPixel != iStart && panNearX[iLast] != -1 )
         {
-            fDistSq = (float)
-                ((panNearX[iLast] - iPixel) * (panNearX[iLast] - iPixel)
+            const float fDistSq = static_cast<float>(
+                (panNearX[iLast] - iPixel) * (panNearX[iLast] - iPixel)
                  + (panNearY[iLast] - iLine) * (panNearY[iLast] - iLine));
 
             if( fDistSq < fNearDistSq )
@@ -528,12 +543,12 @@ ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
 /*      Are we near(er) to the closest target to the topright           */
 /*      (bottom left) pixel?                                            */
 /* -------------------------------------------------------------------- */
-        int iTR = iPixel+iStep;
+        const int iTR = iPixel + iStep;
 
         if( iTR != iEnd && panNearX[iTR] != -1 )
         {
-            fDistSq = (float)
-                ((panNearX[iTR] - iPixel) * (panNearX[iTR] - iPixel)
+            const float fDistSq = static_cast<float>(
+                (panNearX[iTR] - iPixel) * (panNearX[iTR] - iPixel)
                  + (panNearY[iTR] - iLine) * (panNearY[iTR] - iLine));
 
             if( fDistSq < fNearDistSq )
@@ -553,7 +568,7 @@ ProcessProximityLine( GInt32 *panSrcScanline, int *panNearX, int *panNearY,
             && fNearDistSq <= dfMaxDist * dfMaxDist
             && (pafProximity[iPixel] < 0
                 || fNearDistSq < pafProximity[iPixel] * pafProximity[iPixel]) )
-            pafProximity[iPixel] = sqrt(fNearDistSq);
+            pafProximity[iPixel] = static_cast<float>(sqrt(fNearDistSq));
     }
 
     return CE_None;
diff --git a/alg/gdalrasterize.cpp b/alg/gdalrasterize.cpp
index 38507ef..182a76c 100644
--- a/alg/gdalrasterize.cpp
+++ b/alg/gdalrasterize.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalrasterize.cpp 36584 2016-11-30 17:46:24Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Vector rasterization.
@@ -28,17 +27,32 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <vector>
-
+#include "cpl_port.h"
 #include "gdal_alg.h"
 #include "gdal_alg_priv.h"
+
+#include <climits>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_priv.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
 #include "ogr_geometry.h"
 #include "ogr_spatialref.h"
-
 #include "ogrsf_frmts.h"
 
+CPL_CVSID("$Id: gdalrasterize.cpp 37849 2017-03-27 06:37:09Z rouault $");
+
 /************************************************************************/
 /*                           gvBurnScanline()                           */
 /************************************************************************/
@@ -47,17 +61,17 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
                      double dfVariant )
 
 {
-    GDALRasterizeInfo *psInfo = (GDALRasterizeInfo *) pCBData;
-    int iBand;
-
     if( nXStart > nXEnd )
         return;
 
+    GDALRasterizeInfo *psInfo = static_cast<GDALRasterizeInfo *>(pCBData);
+
     CPLAssert( nY >= 0 && nY < psInfo->nYSize );
     CPLAssert( nXStart <= nXEnd );
     CPLAssert( nXStart < psInfo->nXSize );
     CPLAssert( nXEnd >= 0 );
 
+
     if( nXStart < 0 )
         nXStart = 0;
     if( nXEnd >= psInfo->nXSize )
@@ -65,20 +79,20 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
 
     if( psInfo->eType == GDT_Byte )
     {
-        for( iBand = 0; iBand < psInfo->nBands; iBand++ )
+        for( int iBand = 0; iBand < psInfo->nBands; iBand++ )
         {
-            unsigned char *pabyInsert;
             unsigned char nBurnValue = (unsigned char)
                 ( psInfo->padfBurnValue[iBand] +
                   ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
                              0 : dfVariant ) );
 
-            pabyInsert = psInfo->pabyChunkBuf
+            unsigned char *pabyInsert =
+                psInfo->pabyChunkBuf
                 + iBand * psInfo->nXSize * psInfo->nYSize
                 + nY * psInfo->nXSize + nXStart;
 
             if( psInfo->eMergeAlg == GRMA_Add ) {
-                int	nPixels = nXEnd - nXStart + 1;
+                int nPixels = nXEnd - nXStart + 1;
                 while( nPixels-- > 0 )
                     *(pabyInsert++) += nBurnValue;
             } else {
@@ -88,16 +102,16 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
     }
     else if( psInfo->eType == GDT_Float64 )
     {
-        for( iBand = 0; iBand < psInfo->nBands; iBand++ )
+        for( int iBand = 0; iBand < psInfo->nBands; iBand++ )
         {
-            int	nPixels = nXEnd - nXStart + 1;
-            double   *padfInsert;
-            double   dfBurnValue =
+            int nPixels = nXEnd - nXStart + 1;
+            const double dfBurnValue =
                 ( psInfo->padfBurnValue[iBand] +
                   ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
                              0 : dfVariant ) );
 
-            padfInsert = ((double *) psInfo->pabyChunkBuf)
+            double *padfInsert =
+                ((double *) psInfo->pabyChunkBuf)
                 + iBand * psInfo->nXSize * psInfo->nYSize
                 + nY * psInfo->nXSize + nXStart;
 
@@ -111,7 +125,7 @@ void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
         }
     }
     else {
-        CPLAssert(0);
+        CPLAssert(false);
     }
 }
 
@@ -122,15 +136,14 @@ static
 void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
 
 {
-    GDALRasterizeInfo *psInfo = (GDALRasterizeInfo *) pCBData;
-    int iBand;
+    GDALRasterizeInfo *psInfo = static_cast<GDALRasterizeInfo *>(pCBData);
 
     CPLAssert( nY >= 0 && nY < psInfo->nYSize );
     CPLAssert( nX >= 0 && nX < psInfo->nXSize );
 
     if( psInfo->eType == GDT_Byte )
     {
-        for( iBand = 0; iBand < psInfo->nBands; iBand++ )
+        for( int iBand = 0; iBand < psInfo->nBands; iBand++ )
         {
             unsigned char *pbyInsert = psInfo->pabyChunkBuf
                                       + iBand * psInfo->nXSize * psInfo->nYSize
@@ -149,9 +162,9 @@ void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
     }
     else if( psInfo->eType == GDT_Float64 )
     {
-        for( iBand = 0; iBand < psInfo->nBands; iBand++ )
+        for( int iBand = 0; iBand < psInfo->nBands; iBand++ )
         {
-            double   *pdfInsert = ((double *) psInfo->pabyChunkBuf)
+            double *pdfInsert = (double *) psInfo->pabyChunkBuf
                                 + iBand * psInfo->nXSize * psInfo->nYSize
                                 + nY * psInfo->nXSize + nX;
 
@@ -167,7 +180,7 @@ void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
         }
     }
     else {
-        CPLAssert(0);
+        CPLAssert(false);
     }
 }
 
@@ -182,16 +195,16 @@ static void GDALCollectRingsFromGeometry(
     std::vector<int> &aPartSize, GDALBurnValueSrc eBurnValueSrc)
 
 {
-    if( poShape == NULL )
+    if( poShape == NULL || poShape->IsEmpty() )
         return;
 
-    OGRwkbGeometryType eFlatType = wkbFlatten(poShape->getGeometryType());
-    int i;
+    const OGRwkbGeometryType eFlatType = wkbFlatten(poShape->getGeometryType());
 
-    if ( eFlatType == wkbPoint )
+    if( eFlatType == wkbPoint )
     {
-        OGRPoint    *poPoint = (OGRPoint *) poShape;
-        size_t nNewCount = aPointX.size() + 1;
+        OGRPoint *poPoint = dynamic_cast<OGRPoint *>(poShape);
+        CPLAssert(poPoint != NULL);
+        const size_t nNewCount = aPointX.size() + 1;
 
         aPointX.reserve( nNewCount );
         aPointY.reserve( nNewCount );
@@ -200,29 +213,30 @@ static void GDALCollectRingsFromGeometry(
         aPartSize.push_back( 1 );
         if( eBurnValueSrc != GBV_UserBurnValue )
         {
-            /*switch( eBurnValueSrc )
-            {
-            case GBV_Z:*/
-                aPointVariant.reserve( nNewCount );
-                aPointVariant.push_back( poPoint->getZ() );
-                /*break;
-            case GBV_M:
-                aPointVariant.reserve( nNewCount );
-                aPointVariant.push_back( poPoint->getM() );
-            }*/
+            // TODO(schwehr): Why not have the option for M r18164?
+            // switch( eBurnValueSrc )
+            // {
+            // case GBV_Z:*/
+            aPointVariant.reserve( nNewCount );
+            aPointVariant.push_back( poPoint->getZ() );
+            // break;
+            // case GBV_M:
+            //    aPointVariant.reserve( nNewCount );
+            //    aPointVariant.push_back( poPoint->getM() );
         }
     }
-    else if ( eFlatType == wkbLineString )
+    else if( eFlatType == wkbLineString )
     {
-        OGRLineString   *poLine = (OGRLineString *) poShape;
-        int nCount = poLine->getNumPoints();
-        size_t nNewCount = aPointX.size() + static_cast<size_t>(nCount);
+        OGRLineString *poLine = dynamic_cast<OGRLineString *>(poShape);
+        CPLAssert(poLine != NULL);
+        const int nCount = poLine->getNumPoints();
+        const size_t nNewCount = aPointX.size() + static_cast<size_t>(nCount);
 
         aPointX.reserve( nNewCount );
         aPointY.reserve( nNewCount );
         if( eBurnValueSrc != GBV_UserBurnValue )
             aPointVariant.reserve( nNewCount );
-        for ( i = nCount - 1; i >= 0; i-- )
+        for( int i = nCount - 1; i >= 0; i-- )
         {
             aPointX.push_back( poLine->getX(i) );
             aPointY.push_back( poLine->getY(i) );
@@ -240,17 +254,19 @@ static void GDALCollectRingsFromGeometry(
         }
         aPartSize.push_back( nCount );
     }
-    else if ( EQUAL(poShape->getGeometryName(),"LINEARRING") )
+    else if( EQUAL(poShape->getGeometryName(), "LINEARRING") )
     {
-        OGRLinearRing *poRing = (OGRLinearRing *) poShape;
-        int nCount = poRing->getNumPoints();
-        size_t nNewCount = aPointX.size() + static_cast<size_t>(nCount);
+        OGRLinearRing *poRing = dynamic_cast<OGRLinearRing *>(poShape);
+        CPLAssert(poRing != NULL);
+        const int nCount = poRing->getNumPoints();
+        const size_t nNewCount = aPointX.size() + static_cast<size_t>(nCount);
 
         aPointX.reserve( nNewCount );
         aPointY.reserve( nNewCount );
         if( eBurnValueSrc != GBV_UserBurnValue )
             aPointVariant.reserve( nNewCount );
-        for ( i = nCount - 1; i >= 0; i-- )
+        int i = nCount - 1;  // Used after for.
+        for( ; i >= 0; i-- )
         {
             aPointX.push_back( poRing->getX(i) );
             aPointY.push_back( poRing->getY(i) );
@@ -270,26 +286,27 @@ static void GDALCollectRingsFromGeometry(
     }
     else if( eFlatType == wkbPolygon )
     {
-        OGRPolygon *poPolygon = (OGRPolygon *) poShape;
+        OGRPolygon *poPolygon = dynamic_cast<OGRPolygon *>(poShape);
+        CPLAssert(poPolygon != NULL);
 
         GDALCollectRingsFromGeometry( poPolygon->getExteriorRing(),
                                       aPointX, aPointY, aPointVariant,
                                       aPartSize, eBurnValueSrc );
 
-        for( i = 0; i < poPolygon->getNumInteriorRings(); i++ )
+        for( int i = 0; i < poPolygon->getNumInteriorRings(); i++ )
             GDALCollectRingsFromGeometry( poPolygon->getInteriorRing(i),
                                           aPointX, aPointY, aPointVariant,
                                           aPartSize, eBurnValueSrc );
     }
-
     else if( eFlatType == wkbMultiPoint
              || eFlatType == wkbMultiLineString
              || eFlatType == wkbMultiPolygon
              || eFlatType == wkbGeometryCollection )
     {
-        OGRGeometryCollection *poGC = (OGRGeometryCollection *) poShape;
+        OGRGeometryCollection *poGC = dynamic_cast<OGRGeometryCollection *>(poShape);
+        CPLAssert(poGC != NULL);
 
-        for( i = 0; i < poGC->getNumGeometries(); i++ )
+        for( int i = 0; i < poGC->getNumGeometries(); i++ )
             GDALCollectRingsFromGeometry( poGC->getGeometryRef(i),
                                           aPointX, aPointY, aPointVariant,
                                           aPartSize, eBurnValueSrc );
@@ -314,11 +331,10 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
                         void *pTransformArg )
 
 {
-    GDALRasterizeInfo sInfo;
-
-    if (poShape == NULL)
+    if( poShape == NULL || poShape->IsEmpty() )
         return;
 
+    GDALRasterizeInfo sInfo;
     sInfo.nXSize = nXSize;
     sInfo.nYSize = nYSize;
     sInfo.nBands = nBands;
@@ -345,9 +361,10 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
 /* -------------------------------------------------------------------- */
     if( pfnTransformer != NULL )
     {
-        int *panSuccess = (int *) CPLCalloc(sizeof(int),aPointX.size());
+        int *panSuccess =
+            static_cast<int *>(CPLCalloc(sizeof(int), aPointX.size()));
 
-        // TODO: we need to add all appropriate error checking at some point.
+        // TODO: We need to add all appropriate error checking at some point.
         pfnTransformer( pTransformArg, FALSE, static_cast<int>(aPointX.size()),
                         &(aPointX[0]), &(aPointY[0]), NULL, panSuccess );
         CPLFree( panSuccess );
@@ -356,9 +373,7 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
 /* -------------------------------------------------------------------- */
 /*      Shift to account for the buffer offset of this buffer.          */
 /* -------------------------------------------------------------------- */
-    unsigned int i;
-
-    for( i = 0; i < aPointY.size(); i++ )
+    for( unsigned int i = 0; i < aPointY.size(); i++ )
         aPointY[i] -= nYOff;
 
 /* -------------------------------------------------------------------- */
@@ -369,11 +384,11 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
 
     // TODO - mloskot: Check if vectors are empty, otherwise it may
     // lead to undefined behavior by returning non-referencable pointer.
-    // if (!aPointX.empty())
-    //    /* fill polygon */
+    // if( !aPointX.empty() )
+    //    // Fill polygon.
     // else
-    //    /* How to report this problem? */
-    switch ( wkbFlatten(poShape->getGeometryType()) )
+    //    // How to report this problem?
+    switch( wkbFlatten(poShape->getGeometryType()) )
     {
       case wkbPoint:
       case wkbMultiPoint:
@@ -389,14 +404,16 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
       {
           if( bAllTouched )
               GDALdllImageLineAllTouched( sInfo.nXSize, nYSize,
-                                          static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                                          static_cast<int>(aPartSize.size()),
+                                          &(aPartSize[0]),
                                           &(aPointX[0]), &(aPointY[0]),
                                           (eBurnValueSrc == GBV_UserBurnValue)?
                                           NULL : &(aPointVariant[0]),
                                           gvBurnPoint, &sInfo );
           else
               GDALdllImageLine( sInfo.nXSize, nYSize,
-                                static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                                static_cast<int>(aPartSize.size()),
+                                &(aPartSize[0]),
                                 &(aPointX[0]), &(aPointY[0]),
                                 (eBurnValueSrc == GBV_UserBurnValue)?
                                 NULL : &(aPointVariant[0]),
@@ -406,41 +423,44 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
 
       default:
       {
-          GDALdllImageFilledPolygon( sInfo.nXSize, nYSize,
-                                     static_cast<int>(aPartSize.size()), &(aPartSize[0]),
-                                     &(aPointX[0]), &(aPointY[0]),
-                                     (eBurnValueSrc == GBV_UserBurnValue)?
-                                     NULL : &(aPointVariant[0]),
-                                     gvBurnScanline, &sInfo );
+          GDALdllImageFilledPolygon(
+              sInfo.nXSize, nYSize,
+              static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+              &(aPointX[0]), &(aPointY[0]),
+              (eBurnValueSrc == GBV_UserBurnValue)?
+              NULL : &(aPointVariant[0]),
+              gvBurnScanline, &sInfo );
           if( bAllTouched )
           {
-              /* Reverting the variants to the first value because the
-                 polygon is filled using the variant from the first point of
-                 the first segment. Should be removed when the code to full
-                 polygons more appropriately is added. */
-              if(eBurnValueSrc == GBV_UserBurnValue)
+              // Reverting the variants to the first value because the
+              // polygon is filled using the variant from the first point of
+              // the first segment. Should be removed when the code to full
+              // polygons more appropriately is added.
+              if( eBurnValueSrc == GBV_UserBurnValue )
               {
-                  GDALdllImageLineAllTouched( sInfo.nXSize, nYSize,
-                                              static_cast<int>(aPartSize.size()), &(aPartSize[0]),
-                                              &(aPointX[0]), &(aPointY[0]),
-                                              NULL,
-                                              gvBurnPoint, &sInfo );
+                  GDALdllImageLineAllTouched(
+                      sInfo.nXSize, nYSize,
+                      static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                      &(aPointX[0]), &(aPointY[0]),
+                      NULL,
+                      gvBurnPoint, &sInfo );
               }
               else
               {
-                  unsigned int n;
-                  for ( i = 0, n = 0; i < static_cast<unsigned int>(aPartSize.size()); i++ )
+                  for( unsigned int i = 0, n = 0;
+                       i < static_cast<unsigned int>(aPartSize.size());
+                       i++ )
                   {
-                      int j;
-                      for ( j = 0; j < aPartSize[i]; j++ )
+                      for( int j = 0; j < aPartSize[i]; j++ )
                           aPointVariant[n++] = aPointVariant[0];
                   }
 
-                  GDALdllImageLineAllTouched( sInfo.nXSize, nYSize,
-                                              static_cast<int>(aPartSize.size()), &(aPartSize[0]),
-                                              &(aPointX[0]), &(aPointY[0]),
-                                              &(aPointVariant[0]),
-                                              gvBurnPoint, &sInfo );
+                  GDALdllImageLineAllTouched(
+                      sInfo.nXSize, nYSize,
+                      static_cast<int>(aPartSize.size()), &(aPartSize[0]),
+                      &(aPointX[0]), &(aPointY[0]),
+                      &(aPointVariant[0]),
+                      gvBurnPoint, &sInfo );
               }
           }
       }
@@ -455,21 +475,23 @@ gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
 /*      points.                                                         */
 /************************************************************************/
 
-static CPLErr GDALRasterizeOptions(char **papszOptions,
-                                   int *pbAllTouched,
-                                   GDALBurnValueSrc *peBurnValueSource,
-                                   GDALRasterMergeAlg *peMergeAlg)
+static CPLErr GDALRasterizeOptions( char **papszOptions,
+                                    int *pbAllTouched,
+                                    GDALBurnValueSrc *peBurnValueSource,
+                                    GDALRasterMergeAlg *peMergeAlg )
 {
-    *pbAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
+    *pbAllTouched = CPLFetchBool( papszOptions, "ALL_TOUCHED", false );
 
     const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
     *peBurnValueSource = GBV_UserBurnValue;
     if( pszOpt )
     {
-        if( EQUAL(pszOpt,"Z"))
+        if( EQUAL(pszOpt, "Z"))
+        {
             *peBurnValueSource = GBV_Z;
-        /*else if( EQUAL(pszOpt,"M"))
-            eBurnValueSource = GBV_M;*/
+        }
+        // else if( EQUAL(pszOpt, "M"))
+        //     eBurnValueSource = GBV_M;
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -486,10 +508,14 @@ static CPLErr GDALRasterizeOptions(char **papszOptions,
     pszOpt = CSLFetchNameValue( papszOptions, "MERGE_ALG" );
     if( pszOpt )
     {
-        if( EQUAL(pszOpt,"ADD"))
+        if( EQUAL(pszOpt, "ADD"))
+        {
             *peMergeAlg = GRMA_Add;
-        else if( EQUAL(pszOpt,"REPLACE"))
+        }
+        else if( EQUAL(pszOpt, "REPLACE"))
+        {
             *peMergeAlg = GRMA_Replace;
+        }
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -538,17 +564,19 @@ static CPLErr GDALRasterizeOptions(char **papszOptions,
  * @param padfGeomBurnValue the array of values to burn into the raster.
  * There should be nBandCount values for each geometry.
  * @param papszOptions special options controlling rasterization
- * <dl>
- * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched
+ * <ul>
+ * <li>"ALL_TOUCHED": May be set to TRUE to set all pixels touched
  * by the line or polygons, not just those whose center is within the polygon
- * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</dd>
- * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use the Z values of the
+ * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</li>
+ * <li>"BURN_VALUE_FROM": May be set to "Z" to use the Z values of the
  * geometries. dfBurnValue is added to this before burning.
  * Defaults to GDALBurnValueSrc.GBV_UserBurnValue in which case just the
  * dfBurnValue is burned. This is implemented only for points and lines for
- * now. The M value may be supported in the future.</dd>
- * <dt>"MERGE_ALG":</dt> <dd>May be REPLACE (the default) or ADD.  REPLACE results in overwriting of value, while ADD adds the new value to the existing raster, suitable for heatmaps for instance.</dd>
- * </dl>
+ * now. The M value may be supported in the future.</li>
+ * <li>"MERGE_ALG": May be REPLACE (the default) or ADD.  REPLACE results in
+ * overwriting of value, while ADD adds the new value to the existing raster,
+ * suitable for heatmaps for instance.</li>
+ * </ul>
  * @param pfnProgress the progress function to report completion.
  * @param pProgressArg callback data for progress function.
  *
@@ -568,15 +596,11 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
 {
     VALIDATE_POINTER1( hDS, "GDALRasterizeGeometries", CE_Failure);
 
-    GDALDataType   eType;
-    int            nYChunkSize, nScanlineBytes;
-    unsigned char *pabyChunkBuf;
-    int            iY;
-    GDALDataset *poDS = (GDALDataset *) hDS;
-
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
+    GDALDataset *poDS = reinterpret_cast<GDALDataset *>(hDS);
+
 /* -------------------------------------------------------------------- */
 /*      Do some rudimentary arg checking.                               */
 /* -------------------------------------------------------------------- */
@@ -586,19 +610,20 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
         return CE_None;
     }
 
-    // prototype band.
+    // Prototype band.
     GDALRasterBand *poBand = poDS->GetRasterBand( panBandList[0] );
-    if (poBand == NULL)
+    if( poBand == NULL )
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
 /*      Options                                                         */
 /* -------------------------------------------------------------------- */
-    int bAllTouched;
-    GDALBurnValueSrc eBurnValueSource;
-    GDALRasterMergeAlg eMergeAlg;
+    int bAllTouched = FALSE;
+    GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
+    GDALRasterMergeAlg eMergeAlg = GRMA_Replace;
     if( GDALRasterizeOptions(papszOptions, &bAllTouched,
-                             &eBurnValueSource, &eMergeAlg) == CE_Failure) {
+                             &eBurnValueSource, &eMergeAlg) == CE_Failure )
+    {
         return CE_Failure;
     }
 
@@ -610,14 +635,14 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
 /*      We really just need to apply an affine transform, but for       */
 /*      simplicity we use the more general GenImgProjTransformer.       */
 /* -------------------------------------------------------------------- */
-    int bNeedToFreeTransformer = FALSE;
+    bool bNeedToFreeTransformer = false;
 
     if( pfnTransformer == NULL )
     {
-        bNeedToFreeTransformer = TRUE;
+        bNeedToFreeTransformer = true;
 
         char** papszTransformerOptions = NULL;
-        double adfGeoTransform[6] = { 0 };
+        double adfGeoTransform[6] = { 0.0 };
         if( poDS->GetGeoTransform( adfGeoTransform ) != CE_None &&
             poDS->GetGCPCount() == 0 &&
             poDS->GetMetadata("RPC") == NULL )
@@ -626,7 +651,7 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
                 papszTransformerOptions, "DST_METHOD", "NO_GEOTRANSFORM");
         }
 
-        pTransformArg = 
+        pTransformArg =
             GDALCreateGenImgProjTransformer2( NULL, hDS,
                                                 papszTransformerOptions );
         CSLDestroy( papszTransformerOptions );
@@ -643,15 +668,14 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
 /*      size the less times we need to make a pass through all the      */
 /*      shapes.                                                         */
 /* -------------------------------------------------------------------- */
-    if( poBand->GetRasterDataType() == GDT_Byte )
-        eType = GDT_Byte;
-    else
-        eType = GDT_Float64;
+    const GDALDataType eType =
+        poBand->GetRasterDataType() == GDT_Byte ? GDT_Byte : GDT_Float64;
 
-    nScanlineBytes = nBandCount * poDS->GetRasterXSize()
-        * GDALGetDataTypeSizeBytes(eType);
+    const int nScanlineBytes =
+        nBandCount * poDS->GetRasterXSize() * GDALGetDataTypeSizeBytes(eType);
 
-    const char  *pszYChunkSize = CSLFetchNameValue(papszOptions, "CHUNKYSIZE");
+    int nYChunkSize = 0;
+    const char *pszYChunkSize = CSLFetchNameValue(papszOptions, "CHUNKYSIZE");
     if( pszYChunkSize == NULL || ((nYChunkSize = atoi(pszYChunkSize))) == 0)
     {
         nYChunkSize = 10000000 / nScanlineBytes;
@@ -661,48 +685,50 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
         nYChunkSize = poDS->GetRasterYSize();
 
     CPLDebug( "GDAL", "Rasterizer operating on %d swaths of %d scanlines.",
-              (poDS->GetRasterYSize()+nYChunkSize-1) / nYChunkSize,
+              (poDS->GetRasterYSize() + nYChunkSize - 1) / nYChunkSize,
               nYChunkSize );
 
-    pabyChunkBuf = (unsigned char *) VSI_MALLOC2_VERBOSE(nYChunkSize, nScanlineBytes);
+    unsigned char *pabyChunkBuf = static_cast<unsigned char *>(
+        VSI_MALLOC2_VERBOSE(nYChunkSize, nScanlineBytes));
     if( pabyChunkBuf == NULL )
     {
+        if( bNeedToFreeTransformer )
+            GDALDestroyTransformer( pTransformArg );
         return CE_Failure;
     }
 
 /* ==================================================================== */
 /*      Loop over image in designated chunks.                           */
 /* ==================================================================== */
-    CPLErr  eErr = CE_None;
+    CPLErr eErr = CE_None;
 
     pfnProgress( 0.0, NULL, pProgressArg );
 
-    for( iY = 0;
+    for( int iY = 0;
          iY < poDS->GetRasterYSize() && eErr == CE_None;
          iY += nYChunkSize )
     {
-        int	nThisYChunkSize;
-        int     iShape;
-
-        nThisYChunkSize = nYChunkSize;
+        int nThisYChunkSize = nYChunkSize;
         if( nThisYChunkSize + iY > poDS->GetRasterYSize() )
             nThisYChunkSize = poDS->GetRasterYSize() - iY;
 
         eErr =
             poDS->RasterIO(GF_Read,
                            0, iY, poDS->GetRasterXSize(), nThisYChunkSize,
-                           pabyChunkBuf,poDS->GetRasterXSize(),nThisYChunkSize,
+                           pabyChunkBuf,
+                           poDS->GetRasterXSize(), nThisYChunkSize,
                            eType, nBandCount, panBandList,
-                           0, 0, 0, NULL );
+                           0, 0, 0, NULL);
         if( eErr != CE_None )
             break;
 
-        for( iShape = 0; iShape < nGeomCount; iShape++ )
+        for( int iShape = 0; iShape < nGeomCount; iShape++ )
         {
             gv_rasterize_one_shape( pabyChunkBuf, iY,
                                     poDS->GetRasterXSize(), nThisYChunkSize,
                                     nBandCount, eType, bAllTouched,
-                                    (OGRGeometry *) pahGeometries[iShape],
+                                    reinterpret_cast<OGRGeometry *>(
+                                                        pahGeometries[iShape]),
                                     padfGeomBurnValue + iShape*nBandCount,
                                     eBurnValueSource, eMergeAlg,
                                     pfnTransformer, pTransformArg );
@@ -715,7 +741,8 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
                             poDS->GetRasterXSize(), nThisYChunkSize,
                             eType, nBandCount, panBandList, 0, 0, 0, NULL);
 
-        if( !pfnProgress((iY+nThisYChunkSize)/((double)poDS->GetRasterYSize()),
+        if( !pfnProgress((iY + nThisYChunkSize) /
+                         static_cast<double>(poDS->GetRasterYSize()),
                          "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -767,28 +794,30 @@ CPLErr GDALRasterizeGeometries( GDALDatasetH hDS,
  * @param padfLayerBurnValues the array of values to burn into the raster.
  * There should be nBandCount values for each layer.
  * @param papszOptions special options controlling rasterization:
- * <dl>
- * <dt>"ATTRIBUTE":</dt> <dd>Identifies an attribute field on the features to be
+ * <ul>
+ * <li>"ATTRIBUTE": Identifies an attribute field on the features to be
  * used for a burn in value. The value will be burned into all output
  * bands. If specified, padfLayerBurnValues will not be used and can be a NULL
- * pointer.</dd>
- * <dt>"CHUNKYSIZE":</dt> <dd>The height in lines of the chunk to operate on.
+ * pointer.</li>
+ * <li>"CHUNKYSIZE": The height in lines of the chunk to operate on.
  * The larger the chunk size the less times we need to make a pass through all
  * the shapes. If it is not set or set to zero the default chunk size will be
  * used. Default size will be estimated based on the GDAL cache buffer size
  * using formula: cache_size_bytes/scanline_size_bytes, so the chunk will
- * not exceed the cache.</dd>
- * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched
+ * not exceed the cache.</li>
+ * <li>"ALL_TOUCHED": May be set to TRUE to set all pixels touched
  * by the line or polygons, not just those whose center is within the polygon
- * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</dd>
- * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use the Z values of the
+ * or that are selected by brezenhams line algorithm.  Defaults to FALSE.
+ * <li>"BURN_VALUE_FROM": May be set to "Z" to use the Z values of the</li>
  * geometries. The value from padfLayerBurnValues or the attribute field value
  * is added to this before burning. In default case dfBurnValue is burned as it
  * is. This is implemented properly only for points and lines for now. Polygons
  * will be burned using the Z value from the first point. The M value may be
- * supported in the future.</dd>
- * <dt>"MERGE_ALG":</dt> <dd>May be REPLACE (the default) or ADD.  REPLACE results in overwriting of value, while ADD adds the new value to the existing raster, suitable for heatmaps for instance.</dd>
- * </dl>
+ * supported in the future.</li>
+ * <li>"MERGE_ALG": May be REPLACE (the default) or ADD.  REPLACE results in
+ * overwriting of value, while ADD adds the new value to the existing raster,
+ * suitable for heatmaps for instance.</li>
+ * </ul>
  * @param pfnProgress the progress function to report completion.
  * @param pProgressArg callback data for progress function.
  *
@@ -808,10 +837,6 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 {
     VALIDATE_POINTER1( hDS, "GDALRasterizeLayers", CE_Failure);
 
-    GDALDataType   eType;
-    unsigned char *pabyChunkBuf;
-    GDALDataset *poDS = (GDALDataset *) hDS;
-
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
@@ -821,19 +846,22 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
     if( nBandCount == 0 || nLayerCount == 0 )
         return CE_None;
 
-    // prototype band.
+    GDALDataset *poDS = reinterpret_cast<GDALDataset *>(hDS);
+
+    // Prototype band.
     GDALRasterBand *poBand = poDS->GetRasterBand( panBandList[0] );
-    if (poBand == NULL)
+    if( poBand == NULL )
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
 /*      Options                                                         */
 /* -------------------------------------------------------------------- */
-    int bAllTouched;
-    GDALBurnValueSrc eBurnValueSource;
-    GDALRasterMergeAlg eMergeAlg;
+    int bAllTouched = FALSE;
+    GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
+    GDALRasterMergeAlg eMergeAlg = GRMA_Replace;;
     if( GDALRasterizeOptions(papszOptions, &bAllTouched,
-                             &eBurnValueSource, &eMergeAlg) == CE_Failure) {
+                             &eBurnValueSource, &eMergeAlg) == CE_Failure )
+    {
         return CE_Failure;
     }
 
@@ -842,27 +870,24 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 /*      size the less times we need to make a pass through all the      */
 /*      shapes.                                                         */
 /* -------------------------------------------------------------------- */
-    int         nYChunkSize, nScanlineBytes;
     const char  *pszYChunkSize =
         CSLFetchNameValue( papszOptions, "CHUNKYSIZE" );
 
-    if( poBand->GetRasterDataType() == GDT_Byte )
-        eType = GDT_Byte;
-    else
-        eType = GDT_Float64;
+    const GDALDataType eType =
+        poBand->GetRasterDataType() == GDT_Byte ? GDT_Byte : GDT_Float64;
 
-    nScanlineBytes = nBandCount * poDS->GetRasterXSize()
+    const int nScanlineBytes =
+        nBandCount * poDS->GetRasterXSize()
         * GDALGetDataTypeSizeBytes(eType);
 
-    if ( pszYChunkSize && ((nYChunkSize = atoi(pszYChunkSize))) != 0 )
-        ;
-    else
+    int nYChunkSize = 0;
+    if( !(pszYChunkSize && ((nYChunkSize = atoi(pszYChunkSize))) != 0) )
     {
-        GIntBig nYChunkSize64 = GDALGetCacheMax64() / nScanlineBytes;
-        if (nYChunkSize64 > INT_MAX)
+        const GIntBig nYChunkSize64 = GDALGetCacheMax64() / nScanlineBytes;
+        if( nYChunkSize64 > INT_MAX )
             nYChunkSize = INT_MAX;
         else
-            nYChunkSize = (int)nYChunkSize64;
+          nYChunkSize = static_cast<int>(nYChunkSize64);
     }
 
     if( nYChunkSize < 1 )
@@ -871,9 +896,10 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
         nYChunkSize = poDS->GetRasterYSize();
 
     CPLDebug( "GDAL", "Rasterizer operating on %d swaths of %d scanlines.",
-              (poDS->GetRasterYSize()+nYChunkSize-1) / nYChunkSize,
+              (poDS->GetRasterYSize() + nYChunkSize - 1) / nYChunkSize,
               nYChunkSize );
-    pabyChunkBuf = (unsigned char *) VSI_MALLOC2_VERBOSE(nYChunkSize, nScanlineBytes);
+    unsigned char *pabyChunkBuf = static_cast<unsigned char *>(
+        VSI_MALLOC2_VERBOSE(nYChunkSize, nScanlineBytes));
     if( pabyChunkBuf == NULL )
     {
         return CE_Failure;
@@ -883,12 +909,12 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 /*      Read the image once for all layers if user requested to render  */
 /*      the whole raster in single chunk.                               */
 /* -------------------------------------------------------------------- */
-    if ( nYChunkSize == poDS->GetRasterYSize() )
+    if( nYChunkSize == poDS->GetRasterYSize() )
     {
-        if ( poDS->RasterIO( GF_Read, 0, 0, poDS->GetRasterXSize(),
-                             nYChunkSize, pabyChunkBuf,
-                             poDS->GetRasterXSize(), nYChunkSize,
-                             eType, nBandCount, panBandList, 0, 0, 0, NULL )
+        if( poDS->RasterIO( GF_Read, 0, 0, poDS->GetRasterXSize(),
+                            nYChunkSize, pabyChunkBuf,
+                            poDS->GetRasterXSize(), nYChunkSize,
+                            eType, nBandCount, panBandList, 0, 0, 0, NULL )
              != CE_None )
         {
             CPLFree( pabyChunkBuf );
@@ -900,23 +926,19 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 /*      Read the specified layers transforming and rasterizing          */
 /*      geometries.                                                     */
 /* ==================================================================== */
-    CPLErr      eErr = CE_None;
-    int         iLayer;
-    const char  *pszBurnAttribute =
-        CSLFetchNameValue( papszOptions, "ATTRIBUTE" );
+    CPLErr eErr = CE_None;
+    const char *pszBurnAttribute = CSLFetchNameValue(papszOptions, "ATTRIBUTE");
 
     pfnProgress( 0.0, NULL, pProgressArg );
 
-    for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayerCount; iLayer++ )
     {
-        int         iBurnField = -1;
-        double      *padfBurnValues = NULL;
-        OGRLayer    *poLayer = (OGRLayer *) pahLayers[iLayer];
+        OGRLayer *poLayer = reinterpret_cast<OGRLayer *>(pahLayers[iLayer]);
 
-        if ( !poLayer )
+        if( !poLayer )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Layer element number %d is NULL, skipping.\n", iLayer );
+                      "Layer element number %d is NULL, skipping.", iLayer );
             continue;
         }
 
@@ -925,53 +947,61 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 /*      Do not force the feature count, so if driver doesn't know       */
 /*      exact number of features, go down the normal way.               */
 /* -------------------------------------------------------------------- */
-        if ( poLayer->GetFeatureCount(FALSE) == 0 )
+        if( poLayer->GetFeatureCount(FALSE) == 0 )
             continue;
 
-        if ( pszBurnAttribute )
+        int iBurnField = -1;
+        double *padfBurnValues = NULL;
+
+        if( pszBurnAttribute )
         {
             iBurnField =
                 poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute );
-            if ( iBurnField == -1 )
+            if( iBurnField == -1 )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                          "Failed to find field %s on layer %s, skipping.\n",
+                          "Failed to find field %s on layer %s, skipping.",
                           pszBurnAttribute,
                           poLayer->GetLayerDefn()->GetName() );
                 continue;
             }
         }
         else
+        {
             padfBurnValues = padfLayerBurnValues + iLayer * nBandCount;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      If we have no transformer, create the one from input file       */
 /*      projection. Note that each layer can be georefernced            */
 /*      separately.                                                     */
 /* -------------------------------------------------------------------- */
-        int bNeedToFreeTransformer = FALSE;
+        bool bNeedToFreeTransformer = false;
 
         if( pfnTransformer == NULL )
         {
-            char    *pszProjection = NULL;
-            bNeedToFreeTransformer = TRUE;
+            char *pszProjection = NULL;
+            bNeedToFreeTransformer = true;
 
             OGRSpatialReference *poSRS = poLayer->GetSpatialRef();
-            if ( !poSRS )
+            if( !poSRS )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Failed to fetch spatial reference on layer %s "
-                          "to build transformer, assuming matching coordinate systems.\n",
+                          "to build transformer, assuming matching coordinate "
+                          "systems.",
                           poLayer->GetLayerDefn()->GetName() );
             }
             else
+            {
                 poSRS->exportToWkt( &pszProjection );
+            }
 
             char** papszTransformerOptions = NULL;
             if( pszProjection != NULL )
                 papszTransformerOptions = CSLSetNameValue(
                         papszTransformerOptions, "SRC_SRS", pszProjection );
-            double adfGeoTransform[6] = { 0 };
+            double adfGeoTransform[6] = {};
             if( poDS->GetGeoTransform( adfGeoTransform ) != CE_None &&
                 poDS->GetGCPCount() == 0 &&
                 poDS->GetMetadata("RPC") == NULL )
@@ -980,7 +1010,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
                     papszTransformerOptions, "DST_METHOD", "NO_GEOTRANSFORM");
             }
 
-            pTransformArg = 
+            pTransformArg =
                 GDALCreateGenImgProjTransformer2( NULL, hDS,
                                                   papszTransformerOptions );
             pfnTransformer = GDALGenImgProjTransform;
@@ -994,53 +1024,49 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
             }
         }
 
-        OGRFeature *poFeat;
-
         poLayer->ResetReading();
 
 /* -------------------------------------------------------------------- */
 /*      Loop over image in designated chunks.                           */
 /* -------------------------------------------------------------------- */
 
-        double *padfAttrValues = (double *) VSI_MALLOC_VERBOSE(sizeof(double) * nBandCount);
+        double *padfAttrValues = static_cast<double *>(
+            VSI_MALLOC_VERBOSE(sizeof(double) * nBandCount));
         if( padfAttrValues == NULL )
             eErr = CE_Failure;
 
-        int     iY;
-        for( iY = 0;
+        for( int iY = 0;
              iY < poDS->GetRasterYSize() && eErr == CE_None;
              iY += nYChunkSize )
         {
-            int	nThisYChunkSize;
-
-            nThisYChunkSize = nYChunkSize;
+            int nThisYChunkSize = nYChunkSize;
             if( nThisYChunkSize + iY > poDS->GetRasterYSize() )
                 nThisYChunkSize = poDS->GetRasterYSize() - iY;
 
-            // Only re-read image if not a single chunk is being rendered
-            if ( nYChunkSize < poDS->GetRasterYSize() )
+            // Only re-read image if not a single chunk is being rendered.
+            if( nYChunkSize < poDS->GetRasterYSize() )
             {
                 eErr =
                     poDS->RasterIO( GF_Read, 0, iY,
                                     poDS->GetRasterXSize(), nThisYChunkSize,
                                     pabyChunkBuf,
                                     poDS->GetRasterXSize(), nThisYChunkSize,
-                                    eType, nBandCount, panBandList, 0, 0, 0, NULL );
+                                    eType, nBandCount, panBandList,
+                                    0, 0, 0, NULL );
                 if( eErr != CE_None )
                     break;
             }
 
+            OGRFeature *poFeat = NULL;
             while( (poFeat = poLayer->GetNextFeature()) != NULL )
             {
                 OGRGeometry *poGeom = poFeat->GetGeometryRef();
 
-                if ( pszBurnAttribute )
+                if( pszBurnAttribute )
                 {
-                    int         iBand;
-                    double      dfAttrValue;
-
-                    dfAttrValue = poFeat->GetFieldAsDouble( iBurnField );
-                    for (iBand = 0 ; iBand < nBandCount ; iBand++)
+                    const double dfAttrValue =
+                        poFeat->GetFieldAsDouble( iBurnField );
+                    for( int iBand = 0 ; iBand < nBandCount ; iBand++)
                         padfAttrValues[iBand] = dfAttrValue;
 
                     padfBurnValues = padfAttrValues;
@@ -1057,20 +1083,22 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
                 delete poFeat;
             }
 
-            // Only write image if not a single chunk is being rendered
-            if ( nYChunkSize < poDS->GetRasterYSize() )
+            // Only write image if not a single chunk is being rendered.
+            if( nYChunkSize < poDS->GetRasterYSize() )
             {
                 eErr =
                     poDS->RasterIO( GF_Write, 0, iY,
                                     poDS->GetRasterXSize(), nThisYChunkSize,
                                     pabyChunkBuf,
                                     poDS->GetRasterXSize(), nThisYChunkSize,
-                                    eType, nBandCount, panBandList, 0, 0, 0, NULL );
+                                    eType, nBandCount, panBandList,
+                                    0, 0, 0, NULL );
             }
 
             poLayer->ResetReading();
 
-            if( !pfnProgress((iY+nThisYChunkSize)/((double)poDS->GetRasterYSize()),
+            if( !pfnProgress((iY + nThisYChunkSize) /
+                             static_cast<double>(poDS->GetRasterYSize()),
                              "", pProgressArg) )
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -1080,7 +1108,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 
         VSIFree( padfAttrValues );
 
-        if ( bNeedToFreeTransformer )
+        if( bNeedToFreeTransformer )
         {
             GDALDestroyTransformer( pTransformArg );
             pTransformArg = NULL;
@@ -1092,7 +1120,7 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
 /*      Write out the image once for all layers if user requested       */
 /*      to render the whole raster in single chunk.                     */
 /* -------------------------------------------------------------------- */
-    if ( eErr == CE_None && nYChunkSize == poDS->GetRasterYSize() )
+    if( eErr == CE_None && nYChunkSize == poDS->GetRasterYSize() )
     {
         eErr = poDS->RasterIO( GF_Write, 0, 0,
                                 poDS->GetRasterXSize(), nYChunkSize,
@@ -1163,25 +1191,24 @@ CPLErr GDALRasterizeLayers( GDALDatasetH hDS,
  * @param dfBurnValue the value to burn into the raster.
  *
  * @param papszOptions special options controlling rasterization:
- * <dl>
- * <dt>"ATTRIBUTE":</dt> <dd>Identifies an attribute field on the features to be
+ * <ul>
+ * <li>"ATTRIBUTE": Identifies an attribute field on the features to be
  * used for a burn in value. The value will be burned into all output
  * bands. If specified, padfLayerBurnValues will not be used and can be a NULL
- * pointer.</dd>
- * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched
+ * pointer.</li>
+ * <li>"ALL_TOUCHED": May be set to TRUE to set all pixels touched
  * by the line or polygons, not just those whose center is within the polygon
- * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</dd>
- * </dl>
- * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use
+ * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</li>
+ * <li>"BURN_VALUE_FROM": May be set to "Z" to use
  * the Z values of the geometries. dfBurnValue or the attribute field value is
  * added to this before burning. In default case dfBurnValue is burned as it
  * is. This is implemented properly only for points and lines for now. Polygons
  * will be burned using the Z value from the first point. The M value may
- * be supported in the future.</dd>
- * <dt>"MERGE_ALG":</dt> <dd>May be REPLACE (the default) or ADD.  REPLACE
+ * be supported in the future.</li>
+ * <li>"MERGE_ALG": May be REPLACE (the default) or ADD.  REPLACE
  * results in overwriting of value, while ADD adds the new value to the
- * existing raster, suitable for heatmaps for instance.</dd>
- * </dl>
+ * existing raster, suitable for heatmaps for instance.</li>
+ * </ul>
  *
  * @param pfnProgress the progress function to report completion.
  *
@@ -1214,8 +1241,8 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
     }
     if( nPixelSpace != GDALGetDataTypeSizeBytes( eBufType ) )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                "GDALRasterizeLayersBuf(): unsupported value of nPixelSpace" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "GDALRasterizeLayersBuf(): unsupported value of nPixelSpace");
         return CE_Failure;
     }
 
@@ -1225,8 +1252,8 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
     }
     if( nLineSpace != nPixelSpace * nBufXSize )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                "GDALRasterizeLayersBuf(): unsupported value of nLineSpace" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "GDALRasterizeLayersBuf(): unsupported value of nLineSpace");
         return CE_Failure;
     }
 
@@ -1242,11 +1269,12 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
 /* -------------------------------------------------------------------- */
 /*      Options                                                         */
 /* -------------------------------------------------------------------- */
-    int bAllTouched;
-    GDALBurnValueSrc eBurnValueSource;
-    GDALRasterMergeAlg eMergeAlg;
+    int bAllTouched = FALSE;
+    GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
+    GDALRasterMergeAlg eMergeAlg = GRMA_Replace;
     if( GDALRasterizeOptions(papszOptions, &bAllTouched,
-                             &eBurnValueSource, &eMergeAlg) == CE_Failure) {
+                             &eBurnValueSource, &eMergeAlg) == CE_Failure )
+    {
         return CE_Failure;
     }
 
@@ -1254,22 +1282,20 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
 /*      Read the specified layers transforming and rasterizing          */
 /*      geometries.                                                     */
 /* ==================================================================== */
-    CPLErr      eErr = CE_None;
-    int         iLayer;
+    CPLErr eErr = CE_None;
     const char  *pszBurnAttribute =
         CSLFetchNameValue( papszOptions, "ATTRIBUTE" );
 
     pfnProgress( 0.0, NULL, pProgressArg );
 
-    for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayerCount; iLayer++ )
     {
-        int         iBurnField = -1;
-        OGRLayer    *poLayer = (OGRLayer *) pahLayers[iLayer];
+        OGRLayer *poLayer = reinterpret_cast<OGRLayer *>(pahLayers[iLayer]);
 
-        if ( !poLayer )
+        if( !poLayer )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Layer element number %d is NULL, skipping.\n", iLayer );
+                      "Layer element number %d is NULL, skipping.", iLayer );
             continue;
         }
 
@@ -1278,17 +1304,18 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
 /*      Do not force the feature count, so if driver doesn't know       */
 /*      exact number of features, go down the normal way.               */
 /* -------------------------------------------------------------------- */
-        if ( poLayer->GetFeatureCount(FALSE) == 0 )
+        if( poLayer->GetFeatureCount(FALSE) == 0 )
             continue;
 
-        if ( pszBurnAttribute )
+        int iBurnField = -1;
+        if( pszBurnAttribute )
         {
             iBurnField =
                 poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute );
-            if ( iBurnField == -1 )
+            if( iBurnField == -1 )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                          "Failed to find field %s on layer %s, skipping.\n",
+                          "Failed to find field %s on layer %s, skipping.",
                           pszBurnAttribute,
                           poLayer->GetLayerDefn()->GetName() );
                 continue;
@@ -1300,23 +1327,26 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
 /*      projection. Note that each layer can be georefernced            */
 /*      separately.                                                     */
 /* -------------------------------------------------------------------- */
-        int bNeedToFreeTransformer = FALSE;
+        bool bNeedToFreeTransformer = false;
 
         if( pfnTransformer == NULL )
         {
-            char    *pszProjection = NULL;
-            bNeedToFreeTransformer = TRUE;
+            char *pszProjection = NULL;
+            bNeedToFreeTransformer = true;
 
             OGRSpatialReference *poSRS = poLayer->GetSpatialRef();
-            if ( !poSRS )
+            if( !poSRS )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Failed to fetch spatial reference on layer %s "
-                          "to build transformer, assuming matching coordinate systems.\n",
+                          "to build transformer, assuming matching coordinate "
+                          "systems.",
                           poLayer->GetLayerDefn()->GetName() );
             }
             else
+            {
                 poSRS->exportToWkt( &pszProjection );
+            }
 
             pTransformArg =
                 GDALCreateGenImgProjTransformer3( pszProjection, NULL,
@@ -1327,24 +1357,26 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
             CPLFree( pszProjection );
         }
 
-        OGRFeature *poFeat;
-
         poLayer->ResetReading();
 
-        while( (poFeat = poLayer->GetNextFeature()) != NULL )
         {
-            OGRGeometry *poGeom = poFeat->GetGeometryRef();
+            OGRFeature *poFeat = NULL;
+            while( (poFeat = poLayer->GetNextFeature()) != NULL )
+            {
+                OGRGeometry *poGeom = poFeat->GetGeometryRef();
 
-            if ( pszBurnAttribute )
-                dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
+                if( pszBurnAttribute )
+                    dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
 
-            gv_rasterize_one_shape( (unsigned char *) pData, 0,
-                                    nBufXSize, nBufYSize,
-                                    1, eBufType, bAllTouched, poGeom,
-                                    &dfBurnValue, eBurnValueSource, eMergeAlg,
-                                    pfnTransformer, pTransformArg );
+                gv_rasterize_one_shape( static_cast<unsigned char *>(pData), 0,
+                                        nBufXSize, nBufYSize,
+                                        1, eBufType, bAllTouched, poGeom,
+                                        &dfBurnValue, eBurnValueSource,
+                                        eMergeAlg,
+                                        pfnTransformer, pTransformArg );
 
-            delete poFeat;
+                delete poFeat;
+            }
         }
 
         poLayer->ResetReading();
@@ -1355,7 +1387,7 @@ CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
             eErr = CE_Failure;
         }
 
-        if ( bNeedToFreeTransformer )
+        if( bNeedToFreeTransformer )
         {
             GDALDestroyTransformer( pTransformArg );
             pTransformArg = NULL;
diff --git a/alg/gdalrasterpolygonenumerator.cpp b/alg/gdalrasterpolygonenumerator.cpp
index 60727fa..570002b 100644
--- a/alg/gdalrasterpolygonenumerator.cpp
+++ b/alg/gdalrasterpolygonenumerator.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalrasterpolygonenumerator.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Raster Polygon Enumerator
@@ -28,11 +27,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_alg_priv.h"
+
+#include <cstddef>
+
 #include "cpl_conv.h"
-#include <vector>
+#include "cpl_error.h"
 
-CPL_CVSID("$Id: gdalrasterpolygonenumerator.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+CPL_CVSID("$Id: gdalrasterpolygonenumerator.cpp 36698 2016-12-05 04:25:21Z goatbar $");
+
+/*! @cond Doxygen_Suppress */
 
 /************************************************************************/
 /*                    GDALRasterPolygonEnumeratorT()                    */
@@ -90,12 +95,12 @@ template<class DataType, class EqualityTest>
 void GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::MergePolygon( int nSrcId, int nDstIdInit )
 
 {
-    // Figure out the final dest id
+    // Figure out the final dest id.
     int nDstIdFinal = nDstIdInit;
     while( panPolyIdMap[nDstIdFinal] != nDstIdFinal )
         nDstIdFinal = panPolyIdMap[nDstIdFinal];
 
-    // Map the whole intermediate chain to it
+    // Map the whole intermediate chain to it.
     int nDstIdCur = nDstIdInit;
     while( panPolyIdMap[nDstIdCur] != nDstIdCur )
     {
@@ -104,7 +109,7 @@ void GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::MergePolygon( int nSrc
         nDstIdCur = nNextDstId;
     }
 
-    // And map the whole source chain to it too (can be done in one pass)
+    // And map the whole source chain to it too (can be done in one pass).
     while( panPolyIdMap[nSrcId] != nSrcId )
     {
         int nNextSrcId = panPolyIdMap[nSrcId];
@@ -122,16 +127,19 @@ void GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::MergePolygon( int nSrc
 /************************************************************************/
 
 template<class DataType, class EqualityTest>
-int GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::NewPolygon( DataType nValue )
+int GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::NewPolygon(
+    DataType nValue )
 
 {
-    int nPolyId = nNextPolygonId;
+    const int nPolyId = nNextPolygonId;
 
     if( nNextPolygonId >= nPolyAlloc )
     {
         nPolyAlloc = nPolyAlloc * 2 + 20;
-        panPolyIdMap = (GInt32 *) CPLRealloc(panPolyIdMap,nPolyAlloc*sizeof(GInt32));
-        panPolyValue = (DataType *) CPLRealloc(panPolyValue,nPolyAlloc*sizeof(DataType));
+        panPolyIdMap = static_cast<GInt32 *>(
+            CPLRealloc(panPolyIdMap,nPolyAlloc*sizeof(GInt32)));
+        panPolyValue = static_cast<DataType *>(
+            CPLRealloc(panPolyValue,nPolyAlloc*sizeof(DataType)));
     }
 
     nNextPolygonId++;
@@ -159,14 +167,14 @@ void GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::CompleteMerges()
 
     for( iPoly = 0; iPoly < nNextPolygonId; iPoly++ )
     {
-        // Figure out the final id
+        // Figure out the final id.
         int nId = panPolyIdMap[iPoly];
         while( nId != panPolyIdMap[nId] )
         {
             nId = panPolyIdMap[nId];
         }
 
-        // Then map the whole intermediate chain to it
+        // Then map the whole intermediate chain to it.
         int nIdCur = panPolyIdMap[iPoly];
         panPolyIdMap[iPoly] = nId;
         while( nIdCur != panPolyIdMap[nIdCur] )
@@ -290,3 +298,5 @@ void GDALRasterPolygonEnumeratorT<DataType,EqualityTest>::ProcessLine(
 template class GDALRasterPolygonEnumeratorT<GInt32, IntEqualityTest>;
 
 template class GDALRasterPolygonEnumeratorT<float, FloatEqualityTest>;
+
+/*! @endcond */
diff --git a/alg/gdalsievefilter.cpp b/alg/gdalsievefilter.cpp
index ae1bff1..7b1b6cf 100644
--- a/alg/gdalsievefilter.cpp
+++ b/alg/gdalsievefilter.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalsievefilter.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Raster to Polygon Converter
@@ -28,12 +27,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_alg_priv.h"
-#include "cpl_conv.h"
-#include <vector>
+#include "cpl_port.h"
+#include "gdal_alg.h"
+
+#include <cstring>
+
+#include <algorithm>
 #include <set>
+#include <vector>
+#include <utility>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_alg_priv.h"
 
-CPL_CVSID("$Id: gdalsievefilter.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: gdalsievefilter.cpp 36722 2016-12-06 10:55:21Z rouault $");
 
 #define MY_MAX_INT 2147483647
 
@@ -64,18 +75,17 @@ CPL_CVSID("$Id: gdalsievefilter.cpp 33715 2016-03-13 08:52:06Z goatbar $");
 /************************************************************************/
 
 static CPLErr
-GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine, int iY, int nXSize,
+GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine,
+                 int iY, int nXSize,
                  GInt32 *panImageLine )
 
 {
-    CPLErr eErr;
-
-    eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
-                         pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
+    const CPLErr eErr =
+        GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
+                      pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
     if( eErr == CE_None )
     {
-        int i;
-        for( i = 0; i < nXSize; i++ )
+        for( int i = 0; i < nXSize; i++ )
         {
             if( pabyMaskLine[i] == 0 )
                 panImageLine[i] = GP_NODATA_MARKER;
@@ -91,11 +101,11 @@ GPMaskImageData( GDALRasterBandH hMaskBand, GByte *pabyMaskLine, int iY, int nXS
 /*                          CompareNeighbour()                          */
 /*                                                                      */
 /*      Compare two neighbouring polygons, and update eaches            */
-/*      "biggest neighbour" if the other is larger than it's current    */
+/*      "biggest neighbour" if the other is larger than its current     */
 /*      largest neighbour.                                              */
 /*                                                                      */
 /*      Note that this should end up with each polygon knowing the      */
-/*      id of it's largest neighbour.  No attempt is made to            */
+/*      id of its largest neighbour.  No attempt is made to             */
 /*      restrict things to small polygons that we will be merging,      */
 /*      nor to exclude assigning "biggest neighbours" that are still    */
 /*      smaller than our sieve threshold.                               */
@@ -108,22 +118,22 @@ static inline void CompareNeighbour( int nPolyId1, int nPolyId2,
                                      std::vector<int> &anBigNeighbour )
 
 {
-    // nodata polygon do not need neighbours, and cannot be neighbours
+    // Nodata polygon do not need neighbours, and cannot be neighbours
     // to valid polygons.
     if( nPolyId1 < 0 || nPolyId2 < 0 )
         return;
 
-    // make sure we are working with the final merged polygon ids.
+    // Make sure we are working with the final merged polygon ids.
     nPolyId1 = panPolyIdMap[nPolyId1];
     nPolyId2 = panPolyIdMap[nPolyId2];
 
     if( nPolyId1 == nPolyId2 )
         return;
 
-    // nodata polygon do not need neighbours, and cannot be neighbours
+    // Nodata polygon do not need neighbours, and cannot be neighbours
     // to valid polygons.
-    // should no longer happen with r28826 optimization
-    //if( panPolyValue[nPolyId1] == GP_NODATA_MARKER
+    // Should no longer happen with r28826 optimization.
+    // if( panPolyValue[nPolyId1] == GP_NODATA_MARKER
     //    || panPolyValue[nPolyId2] == GP_NODATA_MARKER )
     //    return;
 
@@ -177,8 +187,8 @@ static inline void CompareNeighbour( int nPolyId1, int nPolyId2,
  * @param nConnectedness either 4 indicating that diagonal pixels are not
  * considered directly adjacent for polygon membership purposes or 8
  * indicating they are.
- * @param papszOptions algorithm options in name=value list form.  None currently
- * supported.
+ * @param papszOptions algorithm options in name=value list form.  None
+ * currently supported.
  * @param pfnProgress callback for reporting algorithm progress matching the
  * GDALProgressFunc() semantics.  May be NULL.
  * @param pProgressArg callback argument passed to pfnProgress.
@@ -203,19 +213,26 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /* -------------------------------------------------------------------- */
 /*      Allocate working buffers.                                       */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr = CE_None;
     int nXSize = GDALGetRasterBandXSize( hSrcBand );
     int nYSize = GDALGetRasterBandYSize( hSrcBand );
-    GInt32 *panLastLineVal = (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
-    GInt32 *panThisLineVal = (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
-    GInt32 *panLastLineId =  (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
-    GInt32 *panThisLineId =  (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
-    GInt32 *panThisLineWriteVal = (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize);
-    GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSI_MALLOC_VERBOSE(nXSize) : NULL;
-    if (panLastLineVal == NULL || panThisLineVal == NULL ||
+    GInt32 *panLastLineVal = static_cast<GInt32 *>(
+        VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize));
+    GInt32 *panThisLineVal = static_cast<GInt32 *>(
+        VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize));
+    GInt32 *panLastLineId = static_cast<GInt32 *>(
+        VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize));
+    GInt32 *panThisLineId = static_cast<GInt32 *>(
+        VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize));
+    GInt32 *panThisLineWriteVal = static_cast<GInt32 *>(
+        VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize));
+    GByte *pabyMaskLine =
+        hMaskBand != NULL
+        ? static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize))
+        : NULL;
+    if( panLastLineVal == NULL || panThisLineVal == NULL ||
         panLastLineId == NULL || panThisLineId == NULL ||
         panThisLineWriteVal == NULL ||
-        (hMaskBand != NULL && pabyMaskLine == NULL))
+        (hMaskBand != NULL && pabyMaskLine == NULL) )
     {
         CPLFree( panThisLineId );
         CPLFree( panLastLineId );
@@ -231,11 +248,11 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /*      polygon id map so we will know in advance what polygons are     */
 /*      what on the second pass.                                        */
 /* -------------------------------------------------------------------- */
-    int iY, iX, iPoly;
     GDALRasterPolygonEnumerator oFirstEnum( nConnectedness );
     std::vector<int> anPolySizes;
 
-    for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
+    CPLErr eErr = CE_None;
+    for( int iY = 0; eErr == CE_None && iY < nYSize; iY++ )
     {
         eErr = GDALRasterIO(
             hSrcBand,
@@ -243,7 +260,8 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
             panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
 
         if( eErr == CE_None && hMaskBand != NULL )
-            eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
+            eErr = GPMaskImageData(hMaskBand, pabyMaskLine, iY, nXSize,
+                                   panThisLineVal);
 
         if( iY == 0 )
             oFirstEnum.ProcessLine(
@@ -257,12 +275,12 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /* -------------------------------------------------------------------- */
 /*      Accumulate polygon sizes.                                       */
 /* -------------------------------------------------------------------- */
-        if( oFirstEnum.nNextPolygonId > (int) anPolySizes.size() )
+        if( oFirstEnum.nNextPolygonId > static_cast<int>(anPolySizes.size()) )
             anPolySizes.resize( oFirstEnum.nNextPolygonId );
 
-        for( iX = 0; iX < nXSize; iX++ )
+        for( int iX = 0; iX < nXSize; iX++ )
         {
-            iPoly = panThisLineId[iX];
+            const int iPoly = panThisLineId[iX];
 
             if( iPoly >= 0 && anPolySizes[iPoly] < MY_MAX_INT )
                 anPolySizes[iPoly] += 1;
@@ -271,19 +289,14 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /* -------------------------------------------------------------------- */
 /*      swap this/last lines.                                           */
 /* -------------------------------------------------------------------- */
-        GInt32 *panTmp = panLastLineVal;
-        panLastLineVal = panThisLineVal;
-        panThisLineVal = panTmp;
-
-        panTmp = panThisLineId;
-        panThisLineId = panLastLineId;
-        panLastLineId = panTmp;
+        std::swap(panLastLineVal, panThisLineVal);
+        std::swap(panLastLineId, panThisLineId);
 
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
         if( eErr == CE_None
-            && !pfnProgress( 0.25 * ((iY+1) / (double) nYSize),
+            && !pfnProgress( 0.25 * ((iY+1) / static_cast<double>(nYSize)),
                              "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -302,7 +315,8 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /*      Push the sizes of merged polygon fragments into the             */
 /*      merged polygon id's count.                                      */
 /* -------------------------------------------------------------------- */
-    for( iPoly = 0; iPoly < oFirstEnum.nNextPolygonId; iPoly++ )
+    for( int iPoly = 0; oFirstEnum.panPolyIdMap != NULL && // for Coverity
+                        iPoly < oFirstEnum.nNextPolygonId; iPoly++ )
     {
         if( oFirstEnum.panPolyIdMap[iPoly] != iPoly )
         {
@@ -313,7 +327,8 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
             if( nSize > MY_MAX_INT )
                 nSize = MY_MAX_INT;
 
-            anPolySizes[oFirstEnum.panPolyIdMap[iPoly]] = (int)nSize;
+            anPolySizes[oFirstEnum.panPolyIdMap[iPoly]] =
+                static_cast<int>(nSize);
             anPolySizes[iPoly] = 0;
         }
     }
@@ -327,14 +342,14 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
     std::vector<int> anBigNeighbour;
     anBigNeighbour.resize( anPolySizes.size() );
 
-    for( iPoly = 0; iPoly < (int) anPolySizes.size(); iPoly++ )
+    for( int iPoly = 0; iPoly < static_cast<int>(anPolySizes.size()); iPoly++ )
         anBigNeighbour[iPoly] = -1;
 
 /* ==================================================================== */
 /*      Second pass ... identify the largest neighbour for each         */
 /*      polygon.                                                        */
 /* ==================================================================== */
-    for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
+    for( int iY = 0; eErr == CE_None && iY < nYSize; iY++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Read the image data.                                            */
@@ -343,7 +358,8 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
                              panThisLineVal, nXSize, 1, GDT_Int32, 0, 0 );
 
         if( eErr == CE_None && hMaskBand != NULL )
-            eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
+            eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
+                                    panThisLineVal );
 
         if( eErr != CE_None )
             continue;
@@ -365,7 +381,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /*      Check our neighbours, and update our biggest neighbour map      */
 /*      as appropriate.                                                 */
 /* -------------------------------------------------------------------- */
-        for( iX = 0; iX < nXSize; iX++ )
+        for( int iX = 0; iX < nXSize; iX++ )
         {
             if( iY > 0 )
             {
@@ -405,20 +421,15 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /*      Swap pixel value, and polygon id lines to be ready for the      */
 /*      next line.                                                      */
 /* -------------------------------------------------------------------- */
-        GInt32 *panTmp = panLastLineVal;
-        panLastLineVal = panThisLineVal;
-        panThisLineVal = panTmp;
-
-        panTmp = panThisLineId;
-        panThisLineId = panLastLineId;
-        panLastLineId = panTmp;
+        std::swap(panLastLineVal, panThisLineVal);
+        std::swap(panLastLineId, panThisLineId);
 
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
-        if( eErr == CE_None
-            && !pfnProgress( 0.25 + 0.25 * ((iY+1) / (double) nYSize),
-                             "", pProgressArg ) )
+        if( eErr == CE_None &&
+            !pfnProgress(0.25 + 0.25 * ((iY + 1) / static_cast<double>(nYSize)),
+                         "", pProgressArg) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
             eErr = CE_Failure;
@@ -434,7 +445,9 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
     int nIsolatedSmall = 0;
     int nSieveTargets = 0;
 
-    for( iPoly = 0; iPoly < (int) anPolySizes.size(); iPoly++ )
+    for( int iPoly = 0; oFirstEnum.panPolyIdMap != NULL && // for Coverity
+                        oFirstEnum.panPolyValue != NULL && // for Coverity
+                        iPoly < static_cast<int>(anPolySizes.size()); iPoly++ )
     {
         if( oFirstEnum.panPolyIdMap[iPoly] != iPoly )
             continue;
@@ -462,10 +475,10 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
         std::set<int> oSetVisitedPoly;
         oSetVisitedPoly.insert(iPoly);
 
-        // Walk through our neighbours until we find a polygon large enough
+        // Walk through our neighbours until we find a polygon large enough.
         int iFinalId = iPoly;
         bool bFoundBigEnoughPoly = false;
-        while(true)
+        while( true )
         {
             iFinalId = anBigNeighbour[iFinalId];
             if( iFinalId < 0 )
@@ -479,7 +492,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
                 bFoundBigEnoughPoly = true;
                 break;
             }
-            // Check that we don't cycle on an already visited polygon
+            // Check that we don't cycle on an already visited polygon.
             if( oSetVisitedPoly.find(iFinalId) != oSetVisitedPoly.end() )
                 break;
             oSetVisitedPoly.insert(iFinalId);
@@ -492,7 +505,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
             continue;
         }
 
-        // Map the whole intermediate chain to it
+        // Map the whole intermediate chain to it.
         int iPolyCur = iPoly;
         while( anBigNeighbour[iPolyCur] != iFinalId )
         {
@@ -513,7 +526,8 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /* ==================================================================== */
     oSecondEnum.Clear();
 
-    for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
+    for( int iY = 0; oFirstEnum.panPolyIdMap != NULL && // for Coverity
+                     eErr == CE_None && iY < nYSize; iY++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Read the image data.                                            */
@@ -524,7 +538,8 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
         memcpy( panThisLineWriteVal, panThisLineVal, 4 * nXSize );
 
         if( eErr == CE_None && hMaskBand != NULL )
-            eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
+            eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
+                                    panThisLineVal );
 
         if( eErr != CE_None )
             continue;
@@ -546,7 +561,7 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /*      Reprocess the actual pixel values according to the polygon      */
 /*      merging, and write out this line of image data.                 */
 /* -------------------------------------------------------------------- */
-        for( iX = 0; iX < nXSize; iX++ )
+        for( int iX = 0; iX < nXSize; iX++ )
         {
             int iThisPoly = panThisLineId[iX];
             if( iThisPoly >= 0 )
@@ -572,20 +587,15 @@ GDALSieveFilter( GDALRasterBandH hSrcBand, GDALRasterBandH hMaskBand,
 /*      Swap pixel value, and polygon id lines to be ready for the      */
 /*      next line.                                                      */
 /* -------------------------------------------------------------------- */
-        GInt32 *panTmp = panLastLineVal;
-        panLastLineVal = panThisLineVal;
-        panThisLineVal = panTmp;
-
-        panTmp = panThisLineId;
-        panThisLineId = panLastLineId;
-        panLastLineId = panTmp;
+        std::swap(panLastLineVal, panThisLineVal);
+        std::swap(panLastLineId, panThisLineId);
 
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
         if( eErr == CE_None
-            && !pfnProgress( 0.5 + 0.5 * ((iY+1) / (double) nYSize),
-                             "", pProgressArg ) )
+            && !pfnProgress(0.5 + 0.5 * ((iY+1) / static_cast<double>(nYSize)),
+                            "", pProgressArg) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
             eErr = CE_Failure;
diff --git a/alg/gdalsimplewarp.cpp b/alg/gdalsimplewarp.cpp
index 0d27f95..0930035 100644
--- a/alg/gdalsimplewarp.cpp
+++ b/alg/gdalsimplewarp.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalsimplewarp.cpp 33676 2016-03-07 21:38:34Z goatbar $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Simple (source in memory) warp algorithm.
@@ -27,16 +26,164 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h"
+#include "cpl_port.h"
 #include "gdal_alg.h"
+
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalsimplewarp.cpp 33676 2016-03-07 21:38:34Z goatbar $");
+CPL_CVSID("$Id: gdalsimplewarp.cpp 36703 2016-12-05 14:56:04Z goatbar $");
+
+/************************************************************************/
+/*                      GDALSimpleWarpRemapping()                       */
+/*                                                                      */
+/*      This function implements any raster remapping requested in      */
+/*      the options list.  The remappings are applied to the source     */
+/*      data before warping.  Two kinds are support ... REMAP           */
+/*      commands which remap selected pixel values for any band and     */
+/*      REMAP_MULTI which only remap pixels matching the input in       */
+/*      all bands at once (i.e. to remap an RGB value to another).       */
+/************************************************************************/
 
 static void
 GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
                          int nSrcXSize, int nSrcYSize,
-                         char **papszWarpOptions );
+                         char **papszWarpOptions )
+
+{
+
+/* ==================================================================== */
+/*      Process any and all single value REMAP commands.                */
+/* ==================================================================== */
+    char **papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions,
+                                                    "REMAP" );
+
+    for( int iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
+    {
+
+/* -------------------------------------------------------------------- */
+/*      What are the pixel values to map from and to?                   */
+/* -------------------------------------------------------------------- */
+        char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
+
+        if( CSLCount(papszTokens) != 2 )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Ill formed REMAP `%s' ignored in "
+                     "GDALSimpleWarpRemapping()",
+                     papszRemaps[iRemap] );
+            CSLDestroy( papszTokens );
+            continue;
+        }
+
+        const int nFromValue = atoi(papszTokens[0]);
+        const int nToValue = atoi(papszTokens[1]);
+
+        CSLDestroy( papszTokens );
+
+/* -------------------------------------------------------------------- */
+/*      Pass over each band searching for matches.                      */
+/* -------------------------------------------------------------------- */
+        for( int iBand = 0; iBand < nBandCount; iBand++ )
+        {
+            GByte *pabyData = papabySrcData[iBand];
+            int nPixelCount = nSrcXSize * nSrcYSize;
+
+            while( nPixelCount != 0 )
+            {
+                if( *pabyData == nFromValue )
+                    *pabyData = static_cast<GByte>( nToValue );
+
+                pabyData++;
+                nPixelCount--;
+            }
+        }
+    }
+
+    CSLDestroy( papszRemaps );
+
+/* ==================================================================== */
+/*      Process any and all REMAP_MULTI commands.                       */
+/* ==================================================================== */
+    papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions,
+                                             "REMAP_MULTI" );
+
+    for( int iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
+    {
+/* -------------------------------------------------------------------- */
+/*      What are the pixel values to map from and to?                   */
+/* -------------------------------------------------------------------- */
+        char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
+
+        if( CSLCount(papszTokens) % 2 == 1
+            || CSLCount(papszTokens) == 0
+            || CSLCount(papszTokens) > nBandCount * 2 )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Ill formed REMAP_MULTI `%s' ignored in "
+                     "GDALSimpleWarpRemapping()",
+                     papszRemaps[iRemap]);
+            CSLDestroy( papszTokens );
+            continue;
+        }
+
+        const int nMapBandCount = CSLCount(papszTokens) / 2;
+
+        int *panFromValue = static_cast<int *>(
+            CPLMalloc(sizeof(int) * nMapBandCount ) );
+        int *panToValue = static_cast<int *>(
+            CPLMalloc(sizeof(int) * nMapBandCount ) );
+
+        for( int iBand = 0; iBand < nMapBandCount; iBand++ )
+        {
+            panFromValue[iBand] = atoi(papszTokens[iBand]);
+            panToValue[iBand] = atoi(papszTokens[iBand+nMapBandCount]);
+        }
+
+        CSLDestroy( papszTokens );
+
+/* -------------------------------------------------------------------- */
+/*      Search for matching values to replace.                          */
+/* -------------------------------------------------------------------- */
+        const int nPixelCount = nSrcXSize * nSrcYSize;
+
+        for( int iPixel = 0; iPixel < nPixelCount; iPixel++ )
+        {
+            if( papabySrcData[0][iPixel] != panFromValue[0] )
+                continue;
+
+            bool bMatch = true;
+
+            for( int iBand = 1; iBand < nMapBandCount; iBand++ )
+            {
+                if( papabySrcData[iBand][iPixel] != panFromValue[iBand] )
+                    bMatch = false;
+            }
+
+            if( !bMatch )
+                continue;
+
+            for( int iBand = 0; iBand < nMapBandCount; iBand++ )
+                papabySrcData[iBand][iPixel] =
+                    static_cast<GByte>( panToValue[iBand] );
+        }
+
+        CPLFree( panFromValue );
+        CPLFree( panToValue );
+    }
+
+    CSLDestroy( papszRemaps );
+}
 
 /************************************************************************/
 /*                        GDALSimpleImageWarp()                         */
@@ -94,17 +241,17 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     if( nBandCount == 0 )
     {
         nBandCount = GDALGetRasterCount( hSrcDS );
-        if (nBandCount == 0)
+        if( nBandCount == 0 )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "No raster band in source dataset");
             return FALSE;
         }
 
-        panBandList = (int *) CPLCalloc(sizeof(int),nBandCount);
+        panBandList = static_cast<int *>(CPLCalloc(sizeof(int), nBandCount));
 
         for( int iBand = 0; iBand < nBandCount; iBand++ )
-            panBandList[iBand] = iBand+1;
+            panBandList[iBand] = iBand + 1;
 
         const int nResult =
             GDALSimpleImageWarp( hSrcDS, hDstDS, nBandCount, panBandList,
@@ -140,24 +287,26 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         if( papabySrcData[iBand] == NULL )
         {
             CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "GDALSimpleImageWarp out of memory.\n" );
+                      "GDALSimpleImageWarp out of memory." );
             ok = false;
             break;
         }
 
-        if( GDALRasterIO( GDALGetRasterBand(hSrcDS,panBandList[iBand]), GF_Read,
-                      0, 0, nSrcXSize, nSrcYSize,
-                      papabySrcData[iBand], nSrcXSize, nSrcYSize, GDT_Byte,
-                      0, 0 ) != CE_None )
+        if( GDALRasterIO(
+                GDALGetRasterBand(hSrcDS,panBandList[iBand]), GF_Read,
+                0, 0, nSrcXSize, nSrcYSize,
+                papabySrcData[iBand], nSrcXSize, nSrcYSize, GDT_Byte,
+                0, 0 ) != CE_None )
         {
-            CPLError( CE_Failure, CPLE_FileIO, "GDALSimpleImageWarp "
-                      "GDALRasterIO failure %s ",
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "GDALSimpleImageWarp GDALRasterIO failure %s",
                       CPLGetLastErrorMsg() );
             ok = false;
             break;
         }
     }
-    if( !ok ) {
+    if( !ok )
+    {
         for( int i=0; i <= nBandCount; i++ )
         {
             VSIFree(papabySrcData[i]);
@@ -219,7 +368,7 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
                 panBandInit[iBand] = 0;
             else
                 panBandInit[iBand] =
-                    atoi(papszTokens[MIN(iBand,nTokenCount-1)]);
+                    atoi(papszTokens[std::min(iBand, nTokenCount- 1)]);
         }
 
         CSLDestroy(papszTokens);
@@ -236,17 +385,20 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         {
             if( panBandInit[iBand] == -1 )
             {
-                if( GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Read,
-                              0, iDstY, nDstXSize, 1,
-                              papabyDstLine[iBand], nDstXSize, 1, GDT_Byte,
-                              0, 0 ) != CE_None )
+                if( GDALRasterIO(
+                        GDALGetRasterBand(hDstDS,iBand + 1), GF_Read,
+                        0, iDstY, nDstXSize, 1,
+                        papabyDstLine[iBand], nDstXSize, 1, GDT_Byte,
+                        0, 0 ) != CE_None )
                 {
                     bError = TRUE;
                     break;
                 }
             }
             else
+            {
                 memset( papabyDstLine[iBand], panBandInit[iBand], nDstXSize );
+            }
         }
 
         // Set point to transform.
@@ -289,9 +441,11 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         // Write scanline to disk.
         for( int iBand = 0; iBand < nBandCount; iBand++ )
         {
-            if( GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Write,
-                          0, iDstY, nDstXSize, 1,
-                          papabyDstLine[iBand], nDstXSize, 1, GDT_Byte, 0, 0 ) != CE_None )
+            if( GDALRasterIO(
+                    GDALGetRasterBand(hDstDS,iBand+1), GF_Write,
+                    0, iDstY, nDstXSize, 1,
+                    papabyDstLine[iBand], nDstXSize,
+                    1, GDT_Byte, 0, 0 ) != CE_None )
             {
                 bError = TRUE;
                 break;
@@ -300,7 +454,7 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 
         if( pfnProgress != NULL )
         {
-            if( !pfnProgress( (iDstY+1) / (double) nDstYSize,
+            if( !pfnProgress( (iDstY + 1) / static_cast<double>(nDstYSize),
                               "", pProgressArg ) )
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -329,142 +483,3 @@ GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 
     return !bError;
 }
-
-/************************************************************************/
-/*                      GDALSimpleWarpRemapping()                       */
-/*                                                                      */
-/*      This function implements any raster remapping requested in      */
-/*      the options list.  The remappings are applied to the source     */
-/*      data before warping.  Two kinds are support ... REMAP           */
-/*      commands which remap selected pixel values for any band and     */
-/*      REMAP_MULTI which only remap pixels matching the input in       */
-/*      all bands at once (i.e. to remap an RGB value to another).       */
-/************************************************************************/
-
-static void
-GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData,
-                         int nSrcXSize, int nSrcYSize,
-                         char **papszWarpOptions )
-
-{
-
-/* ==================================================================== */
-/*      Process any and all single value REMAP commands.                */
-/* ==================================================================== */
-    char **papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions,
-                                                    "REMAP" );
-
-    for( int iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
-    {
-
-/* -------------------------------------------------------------------- */
-/*      What are the pixel values to map from and to?                   */
-/* -------------------------------------------------------------------- */
-        char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
-
-        if( CSLCount(papszTokens) != 2 )
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Ill formed REMAP `%s' ignored in GDALSimpleWarpRemapping()",
-                      papszRemaps[iRemap] );
-            CSLDestroy( papszTokens );
-            continue;
-        }
-
-        const int nFromValue = atoi(papszTokens[0]);
-        const int nToValue = atoi(papszTokens[1]);
-
-        CSLDestroy( papszTokens );
-
-/* -------------------------------------------------------------------- */
-/*      Pass over each band searching for matches.                      */
-/* -------------------------------------------------------------------- */
-        for( int iBand = 0; iBand < nBandCount; iBand++ )
-        {
-            GByte *pabyData = papabySrcData[iBand];
-            int nPixelCount = nSrcXSize * nSrcYSize;
-
-            while( nPixelCount != 0 )
-            {
-                if( *pabyData == nFromValue )
-                    *pabyData = static_cast<GByte>( nToValue );
-
-                pabyData++;
-                nPixelCount--;
-            }
-        }
-    }
-
-    CSLDestroy( papszRemaps );
-
-/* ==================================================================== */
-/*      Process any and all REMAP_MULTI commands.                       */
-/* ==================================================================== */
-    papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions,
-                                             "REMAP_MULTI" );
-
-    for( int iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
-    {
-/* -------------------------------------------------------------------- */
-/*      What are the pixel values to map from and to?                   */
-/* -------------------------------------------------------------------- */
-        char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
-
-        if( CSLCount(papszTokens) % 2 == 1
-            || CSLCount(papszTokens) == 0
-            || CSLCount(papszTokens) > nBandCount * 2 )
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Ill formed REMAP_MULTI `%s' ignored in GDALSimpleWarpRemapping()",
-                      papszRemaps[iRemap] );
-            CSLDestroy( papszTokens );
-            continue;
-        }
-
-        const int nMapBandCount = CSLCount(papszTokens) / 2;
-
-        int *panFromValue = static_cast<int *>(
-            CPLMalloc(sizeof(int) * nMapBandCount ) );
-        int *panToValue = static_cast<int *>(
-            CPLMalloc(sizeof(int) * nMapBandCount ) );
-
-        for( int iBand = 0; iBand < nMapBandCount; iBand++ )
-        {
-            panFromValue[iBand] = atoi(papszTokens[iBand]);
-            panToValue[iBand] = atoi(papszTokens[iBand+nMapBandCount]);
-        }
-
-        CSLDestroy( papszTokens );
-
-/* -------------------------------------------------------------------- */
-/*      Search for matching values to replace.                          */
-/* -------------------------------------------------------------------- */
-        const int nPixelCount = nSrcXSize * nSrcYSize;
-
-        for( int iPixel = 0; iPixel < nPixelCount; iPixel++ )
-        {
-            if( papabySrcData[0][iPixel] != panFromValue[0] )
-                continue;
-
-            bool bMatch = true;
-
-            for( int iBand = 1; iBand < nMapBandCount; iBand++ )
-            {
-                if( papabySrcData[iBand][iPixel] != panFromValue[iBand] )
-                    bMatch = false;
-            }
-
-            if( !bMatch )
-                continue;
-
-            for( int iBand = 0; iBand < nMapBandCount; iBand++ )
-                papabySrcData[iBand][iPixel] =
-                    static_cast<GByte>( panToValue[iBand] );
-        }
-
-        CPLFree( panFromValue );
-        CPLFree( panToValue );
-    }
-
-    CSLDestroy( papszRemaps );
-}
diff --git a/alg/gdaltransformer.cpp b/alg/gdaltransformer.cpp
index d534c3f..cca2f1d 100644
--- a/alg/gdaltransformer.cpp
+++ b/alg/gdaltransformer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaltransformer.cpp 36584 2016-11-30 17:46:24Z rouault $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Implementation of one or more GDALTrasformerFunc types, including
@@ -30,15 +29,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
+#define DO_NOT_USE_DEBUG_BOOL  // See TODO for bGCPUseOK.
+
+#include "cpl_port.h"
 #include "gdal_alg.h"
-#include "ogr_spatialref.h"
-#include "cpl_string.h"
 #include "gdal_alg_priv.h"
+
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_list.h"
+#include "cpl_minixml.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
+
+
+CPL_CVSID("$Id: gdaltransformer.cpp 37723 2017-03-16 17:07:53Z rouault $");
 
-CPL_CVSID("$Id: gdaltransformer.cpp 36584 2016-11-30 17:46:24Z rouault $");
 CPL_C_START
 void *GDALDeserializeGCPTransformer( CPLXMLNode *psTree );
 void *GDALDeserializeTPSTransformer( CPLXMLNode *psTree );
@@ -54,6 +74,12 @@ static void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree );
 
 static void GDALRefreshGenImgProjTransformer(void* hTransformArg);
 
+static void *
+GDALCreateApproxTransformer2( GDALTransformerFunc pfnRawTransformer,
+                              void *pRawTransformerArg,
+                              double dfMaxErrorForward,
+                              double dfMaxErrorReverse );
+
 /************************************************************************/
 /*                          GDALTransformFunc                           */
 /*                                                                      */
@@ -147,7 +173,6 @@ points may have failed) or FALSE if the overall transformation fails.
  * @return CE_None if successful or CE_Failure otherwise.
  */
 
-
 CPLErr CPL_STDCALL
 GDALSuggestedWarpOutput( GDALDatasetH hSrcDS,
                          GDALTransformerFunc pfnTransformer,
@@ -158,138 +183,126 @@ GDALSuggestedWarpOutput( GDALDatasetH hSrcDS,
 {
     VALIDATE_POINTER1( hSrcDS, "GDALSuggestedWarpOutput", CE_Failure );
 
-    double adfExtent[4] = { 0 };
+    double adfExtent[4] = {};
 
     return GDALSuggestedWarpOutput2( hSrcDS, pfnTransformer, pTransformArg,
                                      padfGeoTransformOut, pnPixels, pnLines,
                                      adfExtent, 0 );
 }
 
-
 static int GDALSuggestedWarpOutput2_MustAdjustForRightBorder(
     GDALTransformerFunc pfnTransformer, void *pTransformArg,
     double* padfExtent,
     CPL_UNUSED int nPixels,
     int nLines,
-    double dfPixelSizeX, double dfPixelSizeY)
+    double dfPixelSizeX, double dfPixelSizeY )
 {
-    int nSamplePoints;
-    double dfRatio;
-    int bErr;
-    int nBadCount;
-    int    abSuccess[21] = { 0 };
-    double adfX[21] = { 0 };
-    double adfY[21] = { 0 };
-    double adfZ[21] = { 0 };
-
-    //double dfMinXOut = padfExtent[0];
-    //double dfMinYOut = padfExtent[1];
-    double dfMaxXOut = padfExtent[2];
-    double dfMaxYOut = padfExtent[3];
-
-    // Take 20 steps
-    nSamplePoints = 0;
-    for( dfRatio = 0.0; dfRatio <= 1.01; dfRatio += 0.05 )
+    double adfX[21] = {};
+    double adfY[21] = {};
+
+    const double dfMaxXOut = padfExtent[2];
+    const double dfMaxYOut = padfExtent[3];
+
+    // Take 20 steps.
+    int nSamplePoints = 0;
+    for( double dfRatio = 0.0; dfRatio <= 1.01; dfRatio += 0.05 )
     {
         // Ensure we end exactly at the end.
         if( dfRatio > 0.99 )
             dfRatio = 1.0;
 
-        // Along right
-        adfX[nSamplePoints]   = dfMaxXOut;
-        adfY[nSamplePoints]   = dfMaxYOut - dfPixelSizeY * dfRatio * nLines;
-        adfZ[nSamplePoints++] = 0.0;
+        // Along right.
+        adfX[nSamplePoints] = dfMaxXOut;
+        adfY[nSamplePoints] = dfMaxYOut - dfPixelSizeY * dfRatio * nLines;
+        nSamplePoints++;
     }
+    double adfZ[21] = {};
+
+    int abSuccess[21] = {};
 
-    bErr = FALSE;
+    bool bErr = false;
     if( !pfnTransformer( pTransformArg, TRUE, nSamplePoints,
-                             adfX, adfY, adfZ, abSuccess ) )
+                         adfX, adfY, adfZ, abSuccess ) )
     {
-        bErr = TRUE;
+        bErr = true;
     }
 
     if( !bErr && !pfnTransformer( pTransformArg, FALSE, nSamplePoints,
-                             adfX, adfY, adfZ, abSuccess ) )
+                                  adfX, adfY, adfZ, abSuccess ) )
     {
-        bErr = TRUE;
+        bErr = true;
     }
 
     nSamplePoints = 0;
-    nBadCount = 0;
-    for( dfRatio = 0.0; !bErr && dfRatio <= 1.01; dfRatio += 0.05 )
+    int nBadCount = 0;
+    for( double dfRatio = 0.0; !bErr && dfRatio <= 1.01; dfRatio += 0.05 )
     {
-        double expected_x = dfMaxXOut;
-        double expected_y = dfMaxYOut - dfPixelSizeY * dfRatio * nLines;
-        if (fabs(adfX[nSamplePoints] -  expected_x) > dfPixelSizeX ||
-            fabs(adfY[nSamplePoints] -  expected_y) > dfPixelSizeY)
-            nBadCount ++;
-        nSamplePoints ++;
+        const double expected_x = dfMaxXOut;
+        const double expected_y = dfMaxYOut - dfPixelSizeY * dfRatio * nLines;
+        if( fabs(adfX[nSamplePoints] -  expected_x) > dfPixelSizeX ||
+            fabs(adfY[nSamplePoints] -  expected_y) > dfPixelSizeY )
+            nBadCount++;
+        nSamplePoints++;
     }
 
-    return (nBadCount == nSamplePoints);
+    return nBadCount == nSamplePoints;
 }
 
-
 static int GDALSuggestedWarpOutput2_MustAdjustForBottomBorder(
      GDALTransformerFunc pfnTransformer, void *pTransformArg,
      double* padfExtent, int nPixels,
      CPL_UNUSED int nLines,
      double dfPixelSizeX, double dfPixelSizeY)
 {
-    int nSamplePoints;
-    double dfRatio;
-    int bErr;
-    int nBadCount;
-    int    abSuccess[21] = { 0 };
-    double adfX[21] = { 0 };
-    double adfY[21] = { 0 };
-    double adfZ[21] = { 0 };
-
-    double dfMinXOut = padfExtent[0];
-    double dfMinYOut = padfExtent[1];
-    //double dfMaxXOut = padfExtent[2];
-    //double dfMaxYOut = padfExtent[3];
-
-    // Take 20 steps
-    nSamplePoints = 0;
-    for( dfRatio = 0.0; dfRatio <= 1.01; dfRatio += 0.05 )
+    double adfX[21] = {};
+    double adfY[21] = {};
+
+    const double dfMinXOut = padfExtent[0];
+    const double dfMinYOut = padfExtent[1];
+
+    // Take 20 steps.
+    int nSamplePoints = 0;
+    for( double dfRatio = 0.0; dfRatio <= 1.01; dfRatio += 0.05 )
     {
         // Ensure we end exactly at the end.
         if( dfRatio > 0.99 )
             dfRatio = 1.0;
 
-        // Along right
-        adfX[nSamplePoints]   = dfMinXOut + dfPixelSizeX * dfRatio * nPixels;
-        adfY[nSamplePoints]   = dfMinYOut;
-        adfZ[nSamplePoints++] = 0.0;
+        // Along right.
+        adfX[nSamplePoints] = dfMinXOut + dfPixelSizeX * dfRatio * nPixels;
+        adfY[nSamplePoints] = dfMinYOut;
+        nSamplePoints++;
     }
+    double adfZ[21] = {};
+
+    int abSuccess[21] = {};
 
-    bErr = FALSE;
+    bool bErr = false;
     if( !pfnTransformer( pTransformArg, TRUE, nSamplePoints,
                              adfX, adfY, adfZ, abSuccess ) )
     {
-        bErr = TRUE;
+        bErr = true;
     }
 
     if( !bErr && !pfnTransformer( pTransformArg, FALSE, nSamplePoints,
                              adfX, adfY, adfZ, abSuccess ) )
     {
-        bErr = TRUE;
+        bErr = true;
     }
 
     nSamplePoints = 0;
-    nBadCount = 0;
-    for( dfRatio = 0.0; !bErr && dfRatio <= 1.01; dfRatio += 0.05 )
+    int nBadCount = 0;
+    for( double dfRatio = 0.0; !bErr && dfRatio <= 1.01; dfRatio += 0.05 )
     {
-        double expected_x = dfMinXOut + dfPixelSizeX * dfRatio * nPixels;
-        double expected_y = dfMinYOut;
-        if (fabs(adfX[nSamplePoints] -  expected_x) > dfPixelSizeX ||
-            fabs(adfY[nSamplePoints] -  expected_y) > dfPixelSizeY)
-            nBadCount ++;
-        nSamplePoints ++;
+        const double expected_x = dfMinXOut + dfPixelSizeX * dfRatio * nPixels;
+        const double expected_y = dfMinYOut;
+        if( fabs(adfX[nSamplePoints] -  expected_x) > dfPixelSizeX ||
+            fabs(adfY[nSamplePoints] -  expected_y) > dfPixelSizeY )
+            nBadCount++;
+        nSamplePoints++;
     }
 
-    return (nBadCount == nSamplePoints);
+    return nBadCount == nSamplePoints;
 }
 
 /************************************************************************/
@@ -330,7 +343,8 @@ static int GDALSuggestedWarpOutput2_MustAdjustForBottomBorder(
  * geotransform is returned.
  * @param pnPixels int in which the suggest pixel width of output is returned.
  * @param pnLines int in which the suggest pixel height of output is returned.
- * @param padfExtent Four entry array to return extents as (xmin, ymin, xmax, ymax).
+ * @param padfExtent Four entry array to return extents as (xmin, ymin, xmax,
+ * ymax).
  * @param nOptions Options, currently always zero.
  *
  * @return CE_None if successful or CE_Failure otherwise.
@@ -350,92 +364,105 @@ GDALSuggestedWarpOutput2( GDALDatasetH hSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Setup sample points all around the edge of the input raster.    */
 /* -------------------------------------------------------------------- */
-    int    nSamplePoints = 0;
-    int    nInXSize = GDALGetRasterXSize( hSrcDS );
-    int    nInYSize = GDALGetRasterYSize( hSrcDS );
-
-    if (pfnTransformer == GDALGenImgProjTransform)
+    if( pfnTransformer == GDALGenImgProjTransform ||
+        pfnTransformer == GDALApproxTransform )
     {
-        /* In case CHECK_WITH_INVERT_PROJ has been modified */
+        // In case CHECK_WITH_INVERT_PROJ has been modified.
         GDALRefreshGenImgProjTransformer(pTransformArg);
     }
 
-#define N_PIXELSTEP 50
-    int nSteps = (int) (double(MIN(nInYSize, nInXSize)) / N_PIXELSTEP + .5);
-    if (nSteps < 20)
-        nSteps = 20;
-    nSteps = MIN(nSteps,100);
+    const int nInXSize = GDALGetRasterXSize( hSrcDS );
+    const int nInYSize = GDALGetRasterYSize( hSrcDS );
 
-retry:
+    const int N_PIXELSTEP = 50;
+    int nSteps = static_cast<int>(
+        static_cast<double>(std::min(nInYSize, nInXSize)) / N_PIXELSTEP + 0.5);
+    if( nSteps < 20 )
+        nSteps = 20;
+    nSteps = std::min(nSteps, 100);
+
+    // TODO(rouault): How is this goto retry supposed to work?  Added in r20537.
+    // Does redoing the same malloc multiple times work?  If it is needed, can
+    // it be converted to a tigher while loop around the MALLOC3s and free?  Is
+    // the point to try with the full requested steps.  Then, if there is not
+    // enough memory, back off and try with just 20 steps?
+ retry:
     int nSampleMax = (nSteps + 1)*(nSteps + 1);
     int *pabSuccess = NULL;
-    double *padfX, *padfY, *padfZ;
-    double *padfXRevert, *padfYRevert, *padfZRevert;
 
     double dfRatio = 0.0;
-    double dfStep = 1. / nSteps;
-
-    pabSuccess = (int *) VSI_MALLOC3_VERBOSE(sizeof(int), nSteps + 1, nSteps + 1);
-    padfX = (double *) VSI_MALLOC3_VERBOSE(sizeof(double) * 3, nSteps + 1, nSteps + 1);
-    padfXRevert = (double *) VSI_MALLOC3_VERBOSE(sizeof(double) * 3, nSteps + 1, nSteps + 1);
-    if (pabSuccess == NULL || padfX == NULL || padfXRevert == NULL)
+    double dfStep = 1.0 / nSteps;
+    double *padfX = NULL;
+    double *padfY = NULL;
+    double *padfZ = NULL;
+    double *padfXRevert = NULL;
+    double *padfYRevert = NULL;
+    double *padfZRevert = NULL;
+
+    pabSuccess = static_cast<int *>(
+        VSI_MALLOC3_VERBOSE(sizeof(int), nSteps + 1, nSteps + 1));
+    padfX = static_cast<double *>(
+        VSI_MALLOC3_VERBOSE(sizeof(double) * 3, nSteps + 1, nSteps + 1));
+    padfXRevert = static_cast<double *>(
+        VSI_MALLOC3_VERBOSE(sizeof(double) * 3, nSteps + 1, nSteps + 1));
+    if( pabSuccess == NULL || padfX == NULL || padfXRevert == NULL )
     {
         CPLFree( padfX );
         CPLFree( padfXRevert );
         CPLFree( pabSuccess );
-        if (nSteps > 20)
+        if( nSteps > 20 )
         {
             nSteps = 20;
             goto retry;
         }
         return CE_Failure;
     }
+
     padfY = padfX + nSampleMax;
     padfZ = padfX + nSampleMax * 2;
     padfYRevert = padfXRevert + nSampleMax;
     padfZRevert = padfXRevert + nSampleMax * 2;
 
-    // Take N_STEPS steps
-    int iStep;
-    for( iStep = 0; iStep <= nSteps; iStep ++ )
+    // Take N_STEPS steps.
+    for( int iStep = 0; iStep <= nSteps; iStep++ )
     {
         dfRatio = (iStep == nSteps) ? 1.0 : iStep * dfStep;
 
-        // Along top
-        padfX[iStep]   = dfRatio * nInXSize;
-        padfY[iStep]   = 0.0;
+        // Along top.
+        padfX[iStep] = dfRatio * nInXSize;
+        padfY[iStep] = 0.0;
         padfZ[iStep] = 0.0;
 
-        // Along bottom
-        padfX[nSteps + 1 + iStep]   = dfRatio * nInXSize;
-        padfY[nSteps + 1 + iStep]   = nInYSize;
+        // Along bottom.
+        padfX[nSteps + 1 + iStep] = dfRatio * nInXSize;
+        padfY[nSteps + 1 + iStep] = nInYSize;
         padfZ[nSteps + 1 + iStep] = 0.0;
 
-        // Along left
-        padfX[2 * (nSteps + 1) + iStep]   = 0.0;
+        // Along left.
+        padfX[2 * (nSteps + 1) + iStep] = 0.0;
         padfY[2 * (nSteps + 1) + iStep] = dfRatio * nInYSize;
         padfZ[2 * (nSteps + 1) + iStep] = 0.0;
 
-        // Along right
-        padfX[3 * (nSteps + 1) + iStep]   = nInXSize;
+        // Along right.
+        padfX[3 * (nSteps + 1) + iStep] = nInXSize;
         padfY[3 * (nSteps + 1) + iStep] = dfRatio * nInYSize;
         padfZ[3 * (nSteps + 1) + iStep] = 0.0;
     }
 
-    nSamplePoints = 4 * (nSteps + 1);
+    int nSamplePoints = 4 * (nSteps + 1);
 
     memset( pabSuccess, 1, sizeof(int) * nSampleMax );
 
 /* -------------------------------------------------------------------- */
 /*      Transform them to the output coordinate system.                 */
 /* -------------------------------------------------------------------- */
-    int    nFailedCount = 0, i;
+    int nFailedCount = 0;
 
     if( !pfnTransformer( pTransformArg, FALSE, nSamplePoints,
                          padfX, padfY, padfZ, pabSuccess ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "GDALSuggestedWarpOutput() failed because the passed\n"
+                  "GDALSuggestedWarpOutput() failed because the passed "
                   "transformer failed." );
         CPLFree( padfX );
         CPLFree( padfXRevert );
@@ -443,7 +470,7 @@ retry:
         return CE_Failure;
     }
 
-    for( i = 0; i < nSamplePoints; i++ )
+    for( int i = 0; i < nSamplePoints; i++ )
     {
         if( !pabSuccess[i] )
             nFailedCount++;
@@ -453,19 +480,19 @@ retry:
 /*      Check if the computed target coordinates are revertable.        */
 /*      If not, try the detailed grid sampling.                         */
 /* -------------------------------------------------------------------- */
-    if (nFailedCount == 0 )
+    if( nFailedCount == 0 )
     {
         memcpy(padfXRevert, padfX, nSamplePoints * sizeof(double));
         memcpy(padfYRevert, padfY, nSamplePoints * sizeof(double));
         memcpy(padfZRevert, padfZ, nSamplePoints * sizeof(double));
-        if( !pfnTransformer( pTransformArg, TRUE, nSamplePoints,
-                             padfXRevert, padfYRevert, padfZRevert, pabSuccess ) )
+        if( !pfnTransformer(pTransformArg, TRUE, nSamplePoints,
+                            padfXRevert, padfYRevert, padfZRevert, pabSuccess) )
         {
             nFailedCount = 1;
         }
         else
         {
-            for( i = 0; nFailedCount == 0 && i < nSamplePoints; i++ )
+            for( int i = 0; nFailedCount == 0 && i < nSamplePoints; i++ )
             {
                 if( !pabSuccess[i] )
                 {
@@ -474,23 +501,22 @@ retry:
                 }
 
                 dfRatio = (i % (nSteps + 1)) * dfStep;
-                if (dfRatio>0.99)
+                if( dfRatio > 0.99 )
                     dfRatio = 1.0;
 
-                double dfExpectedX, dfExpectedY;
-                if (i < nSteps + 1)
+                double dfExpectedX = 0.0;
+                double dfExpectedY = 0.0;
+                if( i < nSteps + 1 )
                 {
-                    dfExpectedX   = dfRatio * nInXSize;
-                    dfExpectedY   = 0.0;
+                    dfExpectedX = dfRatio * nInXSize;
                 }
-                else if (i < 2 * (nSteps + 1))
+                else if( i < 2 * (nSteps + 1) )
                 {
-                    dfExpectedX   = dfRatio * nInXSize;
-                    dfExpectedY   = nInYSize;
+                    dfExpectedX = dfRatio * nInXSize;
+                    dfExpectedY = nInYSize;
                 }
-                else if (i < 3 * (nSteps + 1))
+                else if( i < 3 * (nSteps + 1) )
                 {
-                    dfExpectedX   = 0.0;
                     dfExpectedY   = dfRatio * nInYSize;
                 }
                 else
@@ -499,16 +525,21 @@ retry:
                     dfExpectedY   = dfRatio * nInYSize;
                 }
 
-                if (fabs(padfXRevert[i] - dfExpectedX) > nInXSize / static_cast<double>(nSteps) ||
-                    fabs(padfYRevert[i] - dfExpectedY) > nInYSize / static_cast<double>(nSteps))
-                    nFailedCount ++;
+                if( fabs(padfXRevert[i] - dfExpectedX) > nInXSize /
+                    static_cast<double>(nSteps) ||
+                    fabs(padfYRevert[i] - dfExpectedY) > nInYSize /
+                    static_cast<double>(nSteps) )
+                    nFailedCount++;
             }
             if( nFailedCount != 0 )
-                CPLDebug("WARP", "At least one point failed after revert transform");
+                CPLDebug("WARP",
+                         "At least one point failed after revert transform");
         }
     }
     else
+    {
         CPLDebug("WARP", "At least one point failed after direct transform");
+    }
 
 /* -------------------------------------------------------------------- */
 /*      If any of the edge points failed to transform, we need to       */
@@ -517,23 +548,23 @@ retry:
 /* -------------------------------------------------------------------- */
     if( nFailedCount > 0 )
     {
-        int iStep2;
-        double dfRatio2;
         nSamplePoints = 0;
 
-        // Take N_STEPS steps
-        for( iStep = 0; iStep <= nSteps; iStep ++ )
+        // Take N_STEPS steps.
+        for( int iStep = 0; iStep <= nSteps; iStep++ )
         {
             dfRatio = (iStep == nSteps) ? 1.0 : iStep * dfStep;
 
-            for( iStep2 = 0; iStep2 <= nSteps; iStep2 ++ )
+            for( int iStep2 = 0; iStep2 <= nSteps; iStep2++ )
             {
-                dfRatio2 = (iStep2 == nSteps) ? 1.0 : iStep2 * dfStep;
-
-                // From top to bottom, from left to right
-                padfX[nSamplePoints]   = dfRatio2 * nInXSize;
-                padfY[nSamplePoints]   = dfRatio * nInYSize;
-                padfZ[nSamplePoints++] = 0.0;
+                const double dfRatio2 =
+                    iStep2 == nSteps ? 1.0 : iStep2 * dfStep;
+
+                // From top to bottom, from left to right.
+                padfX[nSamplePoints] = dfRatio2 * nInXSize;
+                padfY[nSamplePoints] = dfRatio * nInYSize;
+                padfZ[nSamplePoints] = 0.0;
+                nSamplePoints++;
             }
         }
 
@@ -542,9 +573,9 @@ retry:
         if( !pfnTransformer( pTransformArg, FALSE, nSamplePoints,
                              padfX, padfY, padfZ, pabSuccess ) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "GDALSuggestedWarpOutput() failed because the passed\n"
-                      "transformer failed." );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "GDALSuggestedWarpOutput() failed because the passed"
+                     "transformer failed.");
 
             CPLFree( padfX );
             CPLFree( padfXRevert );
@@ -557,13 +588,17 @@ retry:
 /* -------------------------------------------------------------------- */
 /*      Collect the bounds, ignoring any failed points.                 */
 /* -------------------------------------------------------------------- */
-    double dfMinXOut=0, dfMinYOut=0, dfMaxXOut=0, dfMaxYOut=0;
-    int    bGotInitialPoint = FALSE;
+    double dfMinXOut = 0.0;
+    double dfMinYOut = 0.0;
+    double dfMaxXOut = 0.0;
+    double dfMaxYOut = 0.0;
+    bool bGotInitialPoint = false;
 
     nFailedCount = 0;
-    for( i = 0; i < nSamplePoints; i++ )
+    for( int i = 0; i < nSamplePoints; i++ )
     {
-        int x_i, y_i;
+        int x_i = 0;
+        int y_i = 0;
 
         if( nSamplePoints == nSampleMax )
         {
@@ -581,13 +616,15 @@ retry:
                 x_i = y_i = 0;
         }
 
-        if (x_i > 0 && (pabSuccess[i-1] || pabSuccess[i]))
+        if( x_i > 0 && (pabSuccess[i-1] || pabSuccess[i]) )
         {
             double x_out_before = padfX[i-1];
             double x_out_after = padfX[i];
             int nIter = 0;
-            double x_in_before = (double)(x_i - 1) * nInXSize / nSteps;
-            double x_in_after = (double)x_i * nInXSize / nSteps;
+            double x_in_before =
+                static_cast<double>(x_i - 1) * nInXSize / nSteps;
+            double x_in_after =
+                static_cast<double>(x_i) * nInXSize / nSteps;
             int valid_before = pabSuccess[i-1];
             int valid_after = pabSuccess[i];
 
@@ -595,61 +632,61 @@ retry:
             // coordinates change sign. This may be a false positive when the
             // target tx is around 0 Dichotomic search to reduce the interval
             // to near the discontinuity and get a better out extent.
-            while ( (!valid_before || !valid_after ||
-                     x_out_before * x_out_after < 0) && nIter < 16 )
+            while( (!valid_before || !valid_after ||
+                    x_out_before * x_out_after < 0.0) && nIter < 16 )
             {
-                double x = (x_in_before + x_in_after) / 2;
-                double y = (double)y_i * nInYSize / nSteps;
-                double z= 0;
-                //fprintf(stderr, "[%d] (%f, %f) -> ", nIter, x, y);
+                double x = (x_in_before + x_in_after) / 2.0;
+                double y = static_cast<double>(y_i) * nInYSize / nSteps;
+                double z = 0.0;
                 int bSuccess = TRUE;
                 if( !pfnTransformer( pTransformArg, FALSE, 1,
                                      &x, &y, &z, &bSuccess ) || !bSuccess )
                 {
-                    //fprintf(stderr, "invalid\n");
-                    if (!valid_before)
+                    if( !valid_before )
                     {
-                        x_in_before = (x_in_before + x_in_after) / 2;
+                        x_in_before = (x_in_before + x_in_after) / 2.0;
                     }
-                    else if (!valid_after)
+                    else if( !valid_after )
                     {
-                        x_in_after = (x_in_before + x_in_after) / 2;
+                        x_in_after = (x_in_before + x_in_after) / 2.0;
                     }
                     else
+                    {
                         break;
+                    }
                 }
                 else
                 {
-                    //fprintf(stderr, "(%f, %f)\n", x, y);
-
                     if( !bGotInitialPoint )
                     {
-                        bGotInitialPoint = TRUE;
-                        dfMinXOut = dfMaxXOut = x;
-                        dfMinYOut = dfMaxYOut = y;
+                        bGotInitialPoint = true;
+                        dfMinXOut = x;
+                        dfMaxXOut = x;
+                        dfMinYOut = y;
+                        dfMaxYOut = y;
                     }
                     else
                     {
-                        dfMinXOut = MIN(dfMinXOut,x);
-                        dfMinYOut = MIN(dfMinYOut,y);
-                        dfMaxXOut = MAX(dfMaxXOut,x);
-                        dfMaxYOut = MAX(dfMaxYOut,y);
+                        dfMinXOut = std::min(dfMinXOut, x);
+                        dfMinYOut = std::min(dfMinYOut, y);
+                        dfMaxXOut = std::max(dfMaxXOut, x);
+                        dfMaxYOut = std::max(dfMaxYOut, y);
                     }
 
-                    if (!valid_before || x_out_before * x < 0)
+                    if( !valid_before || x_out_before * x < 0 )
                     {
                         valid_after = TRUE;
-                        x_in_after = (x_in_before + x_in_after) / 2;
+                        x_in_after = (x_in_before + x_in_after) / 2.0;
                         x_out_after = x;
                     }
                     else
                     {
                         valid_before = TRUE;
                         x_out_before = x;
-                        x_in_before = (x_in_before + x_in_after) / 2;
+                        x_in_before = (x_in_before + x_in_after) / 2.0;
                     }
                 }
-                nIter ++;
+                nIter++;
             }
         }
 
@@ -661,25 +698,27 @@ retry:
 
         if( !bGotInitialPoint )
         {
-            bGotInitialPoint = TRUE;
-            dfMinXOut = dfMaxXOut = padfX[i];
-            dfMinYOut = dfMaxYOut = padfY[i];
+            bGotInitialPoint = true;
+            dfMinXOut = padfX[i];
+            dfMaxXOut = padfX[i];
+            dfMinYOut = padfY[i];
+            dfMaxYOut = padfY[i];
         }
         else
         {
-            dfMinXOut = MIN(dfMinXOut, padfX[i]);
-            dfMinYOut = MIN(dfMinYOut, padfY[i]);
-            dfMaxXOut = MAX(dfMaxXOut, padfX[i]);
-            dfMaxYOut = MAX(dfMaxYOut, padfY[i]);
+            dfMinXOut = std::min(dfMinXOut, padfX[i]);
+            dfMinYOut = std::min(dfMinYOut, padfY[i]);
+            dfMaxXOut = std::max(dfMaxXOut, padfX[i]);
+            dfMaxYOut = std::max(dfMaxYOut, padfY[i]);
         }
     }
 
     if( nFailedCount > nSamplePoints - 10 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Too many points (%d out of %d) failed to transform,\n"
-                  "unable to compute output bounds.",
-                  nFailedCount, nSamplePoints );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Too many points (%d out of %d) failed to transform, "
+                 "unable to compute output bounds.",
+                 nFailedCount, nSamplePoints);
 
         CPLFree( padfX );
         CPLFree( padfXRevert );
@@ -689,9 +728,10 @@ retry:
     }
 
     if( nFailedCount > 0 )
-        CPLDebug( "GDAL",
-                  "GDALSuggestedWarpOutput(): %d out of %d points failed to transform.",
-                  nFailedCount, nSamplePoints );
+        CPLDebug("GDAL",
+                 "GDALSuggestedWarpOutput(): %d out of %d points failed to "
+                 "transform.",
+                 nFailedCount, nSamplePoints);
 
 /* -------------------------------------------------------------------- */
 /*      Compute the distance in "georeferenced" units from the top      */
@@ -700,14 +740,16 @@ retry:
 /*      compute an approximate pixel size in the output                 */
 /*      georeferenced coordinates.                                      */
 /* -------------------------------------------------------------------- */
-    double dfDiagonalDist, dfDeltaX = 0.0, dfDeltaY = 0.0;
+    double dfDiagonalDist = 0.0;
+    double dfDeltaX = 0.0;
+    double dfDeltaY = 0.0;
 
     if( pabSuccess[0] && pabSuccess[nSamplePoints - 1] )
     {
         dfDeltaX = padfX[nSamplePoints-1] - padfX[0];
         dfDeltaY = padfY[nSamplePoints-1] - padfY[0];
         // In some cases this can result in 0 values. See #5980
-        // so fallback to safer method in that case
+        // Fallback to safer method in that case.
     }
     if( dfDeltaX == 0.0 || dfDeltaY == 0.0 )
     {
@@ -720,13 +762,13 @@ retry:
 /* -------------------------------------------------------------------- */
 /*      Compute a pixel size from this.                                 */
 /* -------------------------------------------------------------------- */
-    double dfPixelSize;
-
-    dfPixelSize = dfDiagonalDist
-        / sqrt(((double)nInXSize)*nInXSize + ((double)nInYSize)*nInYSize);
+    const double dfPixelSize =
+        dfDiagonalDist /
+        sqrt(static_cast<double>(nInXSize) * nInXSize +
+             static_cast<double>(nInYSize) * nInYSize);
 
-    double dfPixels = (dfMaxXOut - dfMinXOut) / dfPixelSize;
-    double dfLines =  (dfMaxYOut - dfMinYOut) / dfPixelSize;
+    const double dfPixels = (dfMaxXOut - dfMinXOut) / dfPixelSize;
+    const double dfLines = (dfMaxYOut - dfMinYOut) / dfPixelSize;
 
     if( dfPixels > INT_MAX - 1 || dfLines > INT_MAX - 1 )
     {
@@ -741,35 +783,33 @@ retry:
         return CE_Failure;
     }
 
-    *pnPixels = (int) (dfPixels + 0.5);
-    *pnLines = (int) (dfLines + 0.5);
+    *pnPixels = static_cast<int>(dfPixels + 0.5);
+    *pnLines = static_cast<int>(dfLines + 0.5);
 
     double dfPixelSizeX = dfPixelSize;
     double dfPixelSizeY = dfPixelSize;
 
-    double adfExtent[4];
-    const double adfRatioArray[] = { 0, 0.001, 0.01, 0.1, 1 };
-    size_t nRetry;
-
-#define N_ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
+    double adfExtent[4] = {};
+    const double adfRatioArray[] = { 0.000, 0.001, 0.010, 0.100, 1.000 };
+    size_t nRetry = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Check that the right border is not completely out of source     */
 /*      image. If so, adjust the x pixel size a bit in the hope it will */
 /*      fit.                                                            */
 /* -------------------------------------------------------------------- */
-    for( nRetry = 0; nRetry < N_ELEMENTS(adfRatioArray); nRetry ++ )
+    for( nRetry = 0; nRetry < CPL_ARRAYSIZE(adfRatioArray); nRetry++ )
     {
-        double dfTryPixelSizeX =
+        const double dfTryPixelSizeX =
             dfPixelSizeX - dfPixelSizeX * adfRatioArray[nRetry] / *pnPixels;
         adfExtent[0] = dfMinXOut;
         adfExtent[1] = dfMaxYOut - (*pnLines) * dfPixelSizeY;
         adfExtent[2] = dfMinXOut + (*pnPixels) * dfTryPixelSizeX;
         adfExtent[3] = dfMaxYOut;
-        if (!GDALSuggestedWarpOutput2_MustAdjustForRightBorder(
+        if( !GDALSuggestedWarpOutput2_MustAdjustForRightBorder(
                                             pfnTransformer, pTransformArg,
                                             adfExtent, *pnPixels,  *pnLines,
-                                            dfTryPixelSizeX, dfPixelSizeY))
+                                            dfTryPixelSizeX, dfPixelSizeY) )
         {
             dfPixelSizeX = dfTryPixelSizeX;
             break;
@@ -781,25 +821,24 @@ retry:
 /*      image. If so, adjust the y pixel size a bit in the hope it will */
 /*      fit.                                                            */
 /* -------------------------------------------------------------------- */
-    for( nRetry = 0; nRetry < N_ELEMENTS(adfRatioArray); nRetry ++ )
+    for( nRetry = 0; nRetry < CPL_ARRAYSIZE(adfRatioArray); nRetry++ )
     {
-        double dfTryPixelSizeY =
+        const double dfTryPixelSizeY =
             dfPixelSizeY - dfPixelSizeY * adfRatioArray[nRetry] / *pnLines;
         adfExtent[0] = dfMinXOut;
         adfExtent[1] = dfMaxYOut - (*pnLines) * dfTryPixelSizeY;
         adfExtent[2] = dfMinXOut + (*pnPixels) * dfPixelSizeX;
         adfExtent[3] = dfMaxYOut;
-        if (!GDALSuggestedWarpOutput2_MustAdjustForBottomBorder(
+        if( !GDALSuggestedWarpOutput2_MustAdjustForBottomBorder(
                                             pfnTransformer, pTransformArg,
                                             adfExtent, *pnPixels,  *pnLines,
-                                            dfPixelSizeX, dfTryPixelSizeY))
+                                            dfPixelSizeX, dfTryPixelSizeY) )
         {
             dfPixelSizeY = dfTryPixelSizeY;
             break;
         }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Recompute some bounds so that all return values are consistent  */
 /* -------------------------------------------------------------------- */
@@ -833,7 +872,7 @@ retry:
 
 /************************************************************************/
 /* ==================================================================== */
-/*			 GDALGenImgProjTransformer                      */
+/*                       GDALGenImgProjTransformer                      */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -844,19 +883,17 @@ typedef struct {
     double   adfSrcGeoTransform[6];
     double   adfSrcInvGeoTransform[6];
 
-    void     *pSrcGCPTransformArg;
-    void     *pSrcRPCTransformArg;
-    void     *pSrcTPSTransformArg;
-    void     *pSrcGeoLocTransformArg;
+    void     *pSrcTransformArg;
+    GDALTransformerFunc pSrcTransformer;
 
     void     *pReprojectArg;
+    GDALTransformerFunc pReproject;
 
     double   adfDstGeoTransform[6];
     double   adfDstInvGeoTransform[6];
 
-    void     *pDstGCPTransformArg;
-    void     *pDstRPCTransformArg;
-    void     *pDstTPSTransformArg;
+    void     *pDstTransformArg;
+    GDALTransformerFunc pDstTransformer;
 
 } GDALGenImgProjTransformInfo;
 
@@ -864,37 +901,38 @@ typedef struct {
 /*                GDALCreateSimilarGenImgProjTransformer()              */
 /************************************************************************/
 
-static void* GDALCreateSimilarGenImgProjTransformer( void *hTransformArg, double dfRatioX, double dfRatioY )
+static void *
+GDALCreateSimilarGenImgProjTransformer( void *hTransformArg,
+                                        double dfRatioX, double dfRatioY )
 {
-    VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarGenImgProjTransformer", NULL );
+    VALIDATE_POINTER1( hTransformArg,
+                       "GDALCreateSimilarGenImgProjTransformer", NULL );
 
     GDALGenImgProjTransformInfo *psInfo =
-        (GDALGenImgProjTransformInfo *) hTransformArg;
+        static_cast<GDALGenImgProjTransformInfo *>(hTransformArg);
 
-    GDALGenImgProjTransformInfo *psClonedInfo =  (GDALGenImgProjTransformInfo *)
-        CPLMalloc(sizeof(GDALGenImgProjTransformInfo));
+    GDALGenImgProjTransformInfo *psClonedInfo =
+        static_cast<GDALGenImgProjTransformInfo *>(
+            CPLMalloc(sizeof(GDALGenImgProjTransformInfo)));
 
     memcpy(psClonedInfo, psInfo, sizeof(GDALGenImgProjTransformInfo));
 
-    if( psClonedInfo->pSrcGCPTransformArg )
-        psClonedInfo->pSrcGCPTransformArg = GDALCreateSimilarTransformer( psInfo->pSrcGCPTransformArg, dfRatioX, dfRatioY );
-    else if( psClonedInfo->pSrcRPCTransformArg )
-        psClonedInfo->pSrcRPCTransformArg = GDALCreateSimilarTransformer( psInfo->pSrcRPCTransformArg, dfRatioX, dfRatioY );
-    else if( psClonedInfo->pSrcTPSTransformArg )
-        psClonedInfo->pSrcTPSTransformArg = GDALCreateSimilarTransformer( psInfo->pSrcTPSTransformArg, dfRatioX, dfRatioY );
-    else if( psClonedInfo->pSrcGeoLocTransformArg )
-        psClonedInfo->pSrcGeoLocTransformArg = GDALCreateSimilarTransformer( psInfo->pSrcGeoLocTransformArg, dfRatioX, dfRatioY );
+    if( psClonedInfo->pSrcTransformArg )
+        psClonedInfo->pSrcTransformArg =
+            GDALCreateSimilarTransformer( psInfo->pSrcTransformArg,
+                                          dfRatioX, dfRatioY );
     else if( dfRatioX != 1.0 || dfRatioY != 1.0 )
     {
-        if( psClonedInfo->adfSrcGeoTransform[2] == 0.0 && psClonedInfo->adfSrcGeoTransform[4] == 0.0 )
+        if( psClonedInfo->adfSrcGeoTransform[2] == 0.0 &&
+            psClonedInfo->adfSrcGeoTransform[4] == 0.0 )
         {
             psClonedInfo->adfSrcGeoTransform[1] *= dfRatioX;
             psClonedInfo->adfSrcGeoTransform[5] *= dfRatioY;
         }
         else
         {
-            /* If the x and y ratios are not equal, then we cannot really */
-            /* compute a geotransform */
+            // If the x and y ratios are not equal, then we cannot really
+            // compute a geotransform.
             psClonedInfo->adfSrcGeoTransform[1] *= dfRatioX;
             psClonedInfo->adfSrcGeoTransform[2] *= dfRatioX;
             psClonedInfo->adfSrcGeoTransform[4] *= dfRatioX;
@@ -910,15 +948,12 @@ static void* GDALCreateSimilarGenImgProjTransformer( void *hTransformArg, double
     }
 
     if( psClonedInfo->pReprojectArg )
-        psClonedInfo->pReprojectArg = GDALCloneTransformer( psInfo->pReprojectArg );
-
-    if( psClonedInfo->pDstGCPTransformArg )
-        psClonedInfo->pDstGCPTransformArg = GDALCloneTransformer( psInfo->pDstGCPTransformArg );
-    else if( psClonedInfo->pDstRPCTransformArg )
-        psClonedInfo->pDstRPCTransformArg = GDALCloneTransformer( psInfo->pDstRPCTransformArg );
-    else if( psClonedInfo->pDstTPSTransformArg )
-        psClonedInfo->pDstTPSTransformArg = GDALCloneTransformer( psInfo->pDstTPSTransformArg );
+        psClonedInfo->pReprojectArg =
+            GDALCloneTransformer( psInfo->pReprojectArg );
 
+    if( psClonedInfo->pDstTransformArg )
+        psClonedInfo->pDstTransformArg =
+            GDALCloneTransformer( psInfo->pDstTransformArg );
 
     return psClonedInfo;
 }
@@ -979,7 +1014,6 @@ GDALCreateGenImgProjTransformer( GDALDatasetH hSrcDS, const char *pszSrcWKT,
                                  int nOrder )
 {
     char **papszOptions = NULL;
-    void *pRet;
 
     if( pszSrcWKT != NULL )
         papszOptions = CSLSetNameValue( papszOptions, "SRC_SRS", pszSrcWKT );
@@ -989,16 +1023,15 @@ GDALCreateGenImgProjTransformer( GDALDatasetH hSrcDS, const char *pszSrcWKT,
         papszOptions = CSLSetNameValue( papszOptions, "GCPS_OK", "FALSE" );
     if( nOrder != 0 )
         papszOptions = CSLSetNameValue( papszOptions, "MAX_GCP_ORDER",
-                                        CPLString().Printf("%d",nOrder) );
+                                        CPLString().Printf("%d", nOrder) );
 
-    pRet = GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszOptions );
+    void *pRet =
+        GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszOptions );
     CSLDestroy( papszOptions );
 
     return pRet;
 }
 
-
-
 /************************************************************************/
 /*                          InsertCenterLong()                          */
 /*                                                                      */
@@ -1012,14 +1045,14 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
     if( !STARTS_WITH_CI(osWKT.c_str(), "GEOGCS[") )
         return osWKT;
 
-    if( strstr(osWKT,"EXTENSION[\"CENTER_LONG") != NULL )
+    if( strstr(osWKT, "EXTENSION[\"CENTER_LONG") != NULL )
         return osWKT;
 
 /* -------------------------------------------------------------------- */
 /*      For now we only do this if we have a geotransform since         */
 /*      other forms require a bunch of extra work.                      */
 /* -------------------------------------------------------------------- */
-    double   adfGeoTransform[6];
+    double adfGeoTransform[6] = {};
 
     if( GDALGetGeoTransform( hDS, adfGeoTransform ) != CE_None )
         return osWKT;
@@ -1027,25 +1060,24 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
 /* -------------------------------------------------------------------- */
 /*      Compute min/max longitude based on testing the four corners.    */
 /* -------------------------------------------------------------------- */
-    double dfMinLong, dfMaxLong;
-    int nXSize = GDALGetRasterXSize( hDS );
-    int nYSize = GDALGetRasterYSize( hDS );
+    const int nXSize = GDALGetRasterXSize( hDS );
+    const int nYSize = GDALGetRasterYSize( hDS );
 
-    dfMinLong =
-        MIN(MIN(adfGeoTransform[0] + 0 * adfGeoTransform[1]
+    const double dfMinLong =
+        std::min(std::min(adfGeoTransform[0] + 0 * adfGeoTransform[1]
                 + 0 * adfGeoTransform[2],
                 adfGeoTransform[0] + nXSize * adfGeoTransform[1]
                 + 0 * adfGeoTransform[2]),
-            MIN(adfGeoTransform[0] + 0 * adfGeoTransform[1]
+            std::min(adfGeoTransform[0] + 0 * adfGeoTransform[1]
                 + nYSize * adfGeoTransform[2],
                 adfGeoTransform[0] + nXSize * adfGeoTransform[1]
                 + nYSize * adfGeoTransform[2]));
-    dfMaxLong =
-        MAX(MAX(adfGeoTransform[0] + 0 * adfGeoTransform[1]
+    const double dfMaxLong =
+        std::max(std::max(adfGeoTransform[0] + 0 * adfGeoTransform[1]
                 + 0 * adfGeoTransform[2],
                 adfGeoTransform[0] + nXSize * adfGeoTransform[1]
                 + 0 * adfGeoTransform[2]),
-            MAX(adfGeoTransform[0] + 0 * adfGeoTransform[1]
+            std::max(adfGeoTransform[0] + 0 * adfGeoTransform[1]
                 + nYSize * adfGeoTransform[2],
                 adfGeoTransform[0] + nXSize * adfGeoTransform[1]
                 + nYSize * adfGeoTransform[2]));
@@ -1057,12 +1089,10 @@ static CPLString InsertCenterLong( GDALDatasetH hDS, CPLString osWKT )
 /*      Insert center long.                                             */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oSRS( osWKT );
-    double dfCenterLong = (dfMaxLong + dfMinLong) / 2.0;
-    OGR_SRSNode *poExt;
-
-    poExt  = new OGR_SRSNode( "EXTENSION" );
+    const double dfCenterLong = (dfMaxLong + dfMinLong) / 2.0;
+    OGR_SRSNode *poExt = new OGR_SRSNode( "EXTENSION" );
     poExt->AddChild( new OGR_SRSNode( "CENTER_LONG" ) );
-    poExt->AddChild( new OGR_SRSNode( CPLString().Printf("%g",dfCenterLong) ));
+    poExt->AddChild( new OGR_SRSNode( CPLString().Printf("%g", dfCenterLong) ));
 
     oSRS.GetRoot()->AddChild( poExt->Clone() );
     delete poExt;
@@ -1088,10 +1118,13 @@ static GDALGenImgProjTransformInfo* GDALCreateGenImgProjTransformerInternal()
 /* -------------------------------------------------------------------- */
 /*      Initialize the transform info.                                  */
 /* -------------------------------------------------------------------- */
-    GDALGenImgProjTransformInfo* psInfo = (GDALGenImgProjTransformInfo *)
-        CPLCalloc(sizeof(GDALGenImgProjTransformInfo),1);
+    GDALGenImgProjTransformInfo* psInfo =
+        static_cast<GDALGenImgProjTransformInfo *>(
+            CPLCalloc(sizeof(GDALGenImgProjTransformInfo), 1));
 
-    memcpy( psInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
+    memcpy( psInfo->sTI.abySignature,
+            GDAL_GTI2_SIGNATURE,
+            strlen(GDAL_GTI2_SIGNATURE) );
     psInfo->sTI.pszClassName = "GDALGenImgProjTransformer";
     psInfo->sTI.pfnTransform = GDALGenImgProjTransform;
     psInfo->sTI.pfnCleanup = GDALDestroyGenImgProjTransformer;
@@ -1133,32 +1166,69 @@ static GDALGenImgProjTransformInfo* GDALCreateGenImgProjTransformerInternal()
  * GDALGCPTransform().  This stage is skipped if hDstDS is NULL when the
  * transformation is created.
  *
- * Supported Options:
+ * Supported Options (specified with the -to switch of gdalwarp for example):
  * <ul>
  * <li> SRC_SRS: WKT SRS to be used as an override for hSrcDS.
  * <li> DST_SRS: WKT SRS to be used as an override for hDstDS.
  * <li> GCPS_OK: If false, GCPs will not be used, default is TRUE.
- * <li> REFINE_MINIMUM_GCPS: The minimum amount of GCPs that should be available after the refinement.
- * <li> REFINE_TOLERANCE: The tolerance that specifies when a GCP will be eliminated.
+ * <li> REFINE_MINIMUM_GCPS: The minimum amount of GCPs that should be available
+ * after the refinement.
+ * <li> REFINE_TOLERANCE: The tolerance that specifies when a GCP will be
+ * eliminated.
  * <li> MAX_GCP_ORDER: the maximum order to use for GCP derived polynomials if
  * possible.  The default is to autoselect based on the number of GCPs.
  * A value of -1 triggers use of Thin Plate Spline instead of polynomials.
  * <li> SRC_METHOD: may have a value which is one of GEOTRANSFORM,
  * GCP_POLYNOMIAL, GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation
  * method to be considered on the source dataset. Will be used for pixel/line
- * to georef transformation on the source dataset.
+ * to georef transformation on the source dataset. NO_GEOTRANSFORM can be
+ * used to specify the identity geotransform (ungeoreference image)
  * <li> DST_METHOD: may have a value which is one of GEOTRANSFORM,
  * GCP_POLYNOMIAL, GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation
  * method to be considered on the target dataset.  Will be used for pixel/line
- * to georef transformation on the destination dataset.
+ * to georef transformation on the destination dataset. NO_GEOTRANSFORM can be
+ * used to specify the identity geotransform (ungeoreference image)
  * <li> RPC_HEIGHT: A fixed height to be used with RPC calculations.
  * <li> RPC_DEM: The name of a DEM file to be used with RPC calculations.
  * <li> Other RPC related options. See GDALCreateRPCTransformer()
  * <li> INSERT_CENTER_LONG: May be set to FALSE to disable setting up a
  * CENTER_LONG value on the coordinate system to rewrap things around the
  * center of the image.
+ * <li> SRC_APPROX_ERROR_IN_SRS_UNIT=err_threshold_in_SRS_units. (GDAL >= 2.2) Use an
+ * approximate transformer for the source transformer. Must be defined together
+ * with SRC_APPROX_ERROR_IN_PIXEL to be taken into account.
+ * <li> SRC_APPROX_ERROR_IN_PIXEL=err_threshold_in_pixel. (GDAL >= 2.2) Use an
+ * approximate transformer for the source transformer.. Must be defined together
+ * with SRC_APPROX_ERROR_IN_SRS_UNIT to be taken into account.
+ * <li> DST_APPROX_ERROR_IN_SRS_UNIT=err_threshold_in_SRS_units. (GDAL >= 2.2) Use an
+ * approximate transformer for the destination transformer. Must be defined together
+ * with DST_APPROX_ERROR_IN_PIXEL to be taken into account.
+ * <li> DST_APPROX_ERROR_IN_PIXEL=err_threshold_in_pixel. (GDAL >= 2.2) Use an
+ * approximate transformer for the destination transformer. Must be defined together
+ * with DST_APPROX_ERROR_IN_SRS_UNIT to be taken into account.
+ * <li> REPROJECTION_APPROX_ERROR_IN_SRC_SRS_UNIT=err_threshold_in_src_SRS_units.
+ * (GDAL >= 2.2) Use an approximate transformer for the coordinate reprojection.
+ * Must be used together with REPROJECTION_APPROX_ERROR_IN_DST_SRS_UNIT to be taken
+ * into account.
+ * <li> REPROJECTION_APPROX_ERROR_IN_DST_SRS_UNIT=err_threshold_in_dst_SRS_units.
+ * (GDAL >= 2.2) Use an approximate transformer for the coordinate reprojection.
+ * Must be used together with REPROJECTION_APPROX_ERROR_IN_SRC_SRS_UNIT to be taken
+ * into account.
  * </ul>
  *
+ * The use case for the *_APPROX_ERROR_* options is when defining an approximate
+ * transformer on top of the GenImgProjTransformer globally is not practical.
+ * Such a use case is when the source dataset has RPC with a RPC DEM. In such
+ * case we don't want to use the approximate transformer on the RPC transformation,
+ * as the RPC DEM generally involves non-linearities that the approximate
+ * transformer will not detect. In such case, we must a non-approximated
+ * GenImgProjTransformer, but it might be worthwile to use approximate sub-
+ * transformers, for example on coordinate reprojection. For example if
+ * warping from a source dataset with RPC to a destination dataset with
+ * a UTM projection, since the inverse UTM transformation is rather costly.
+ * In which case, one can use the REPROJECTION_APPROX_ERROR_IN_SRC_SRS_UNIT and
+ * REPROJECTION_APPROX_ERROR_IN_DST_SRS_UNIT options.
+ *
  * @param hSrcDS source dataset, or NULL.
  * @param hDstDS destination dataset (or NULL).
  * @param papszOptions NULL-terminated list of string options (or NULL).
@@ -1172,49 +1242,39 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
                                   char **papszOptions )
 
 {
-    GDALGenImgProjTransformInfo *psInfo;
-    char **papszMD;
+    char **papszMD = NULL;
     GDALRPCInfo sRPCInfo;
     const char *pszMethod = CSLFetchNameValue( papszOptions, "SRC_METHOD" );
     if( pszMethod == NULL )
         pszMethod = CSLFetchNameValue( papszOptions, "METHOD" );
-    const char *pszValue;
-    int nOrder = 0, bGCPUseOK = TRUE, nMinimumGcps = -1, bRefine = FALSE;
-    double dfTolerance = 0.0;
     const char *pszSrcWKT = CSLFetchNameValue( papszOptions, "SRC_SRS" );
     const char *pszDstWKT = CSLFetchNameValue( papszOptions, "DST_SRS" );
 
-    pszValue = CSLFetchNameValue( papszOptions, "MAX_GCP_ORDER" );
-    if( pszValue )
-        nOrder = atoi(pszValue);
+    const char *pszValue = CSLFetchNameValue( papszOptions, "MAX_GCP_ORDER" );
+    const int nOrder = pszValue ? atoi(pszValue) : 0;
 
     pszValue = CSLFetchNameValue( papszOptions, "GCPS_OK" );
-    if( pszValue )
-        bGCPUseOK = CPLTestBool(pszValue);
+    // TODO(schwehr): Why does this upset DEBUG_BOOL?
+    const bool bGCPUseOK = pszValue ? CPLTestBool(pszValue) : true;
 
     pszValue = CSLFetchNameValue( papszOptions, "REFINE_MINIMUM_GCPS" );
-    if( pszValue )
-    {
-        if( atoi(pszValue) != -1)
-            nMinimumGcps = atoi(pszValue);
-    }
+    const int nMinimumGcps =  pszValue ? atoi(pszValue) : -1;
 
     pszValue = CSLFetchNameValue( papszOptions, "REFINE_TOLERANCE" );
-    if( pszValue )
-    {
-        dfTolerance = CPLAtof(pszValue);
-        bRefine = TRUE;
-    }
+    const bool bRefine = pszValue != NULL;
+    const double dfTolerance = pszValue ? CPLAtof(pszValue) : 0.0;
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the transform info.                                  */
 /* -------------------------------------------------------------------- */
-    psInfo = GDALCreateGenImgProjTransformerInternal();
+    GDALGenImgProjTransformInfo *psInfo =
+        GDALCreateGenImgProjTransformerInternal();
 
 /* -------------------------------------------------------------------- */
 /*      Get forward and inverse geotransform for the source image.      */
 /* -------------------------------------------------------------------- */
-    if( hSrcDS == NULL || (pszMethod != NULL && EQUAL(pszMethod,"NO_GEOTRANSFORM")) )
+    if( hSrcDS == NULL ||
+        (pszMethod != NULL && EQUAL(pszMethod, "NO_GEOTRANSFORM")) )
     {
         psInfo->adfSrcGeoTransform[0] = 0.0;
         psInfo->adfSrcGeoTransform[1] = 1.0;
@@ -1225,8 +1285,7 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         memcpy( psInfo->adfSrcInvGeoTransform, psInfo->adfSrcGeoTransform,
                 sizeof(double) * 6 );
     }
-
-    else if( (pszMethod == NULL || EQUAL(pszMethod,"GEOTRANSFORM"))
+    else if( (pszMethod == NULL || EQUAL(pszMethod, "GEOTRANSFORM"))
              && GDALGetGeoTransform( hSrcDS, psInfo->adfSrcGeoTransform )
              == CE_None
              && (psInfo->adfSrcGeoTransform[0] != 0.0
@@ -1234,7 +1293,7 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
                  || psInfo->adfSrcGeoTransform[2] != 0.0
                  || psInfo->adfSrcGeoTransform[3] != 0.0
                  || psInfo->adfSrcGeoTransform[4] != 0.0
-                 || ABS(psInfo->adfSrcGeoTransform[5]) != 1.0) )
+                 || std::abs(psInfo->adfSrcGeoTransform[5]) != 1.0) )
     {
         if( !GDALInvGeoTransform( psInfo->adfSrcGeoTransform,
                                   psInfo->adfSrcInvGeoTransform ) )
@@ -1246,31 +1305,32 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         if( pszSrcWKT == NULL )
             pszSrcWKT = GDALGetProjectionRef( hSrcDS );
     }
-
     else if( bGCPUseOK
-             && (pszMethod == NULL || EQUAL(pszMethod,"GCP_POLYNOMIAL") )
+             && (pszMethod == NULL || EQUAL(pszMethod, "GCP_POLYNOMIAL") )
              && GDALGetGCPCount( hSrcDS ) > 0 && nOrder >= 0 )
     {
-        if(bRefine)
+        if( bRefine )
         {
-                psInfo->pSrcGCPTransformArg =
-                    GDALCreateGCPRefineTransformer( GDALGetGCPCount( hSrcDS ),
-                                                    GDALGetGCPs( hSrcDS ), nOrder,
-                                                    FALSE, dfTolerance, nMinimumGcps );
+                psInfo->pSrcTransformArg =
+                    GDALCreateGCPRefineTransformer(
+                        GDALGetGCPCount( hSrcDS ),
+                        GDALGetGCPs( hSrcDS ), nOrder,
+                        FALSE, dfTolerance, nMinimumGcps );
         }
         else
         {
-            psInfo->pSrcGCPTransformArg =
+            psInfo->pSrcTransformArg =
                 GDALCreateGCPTransformer( GDALGetGCPCount( hSrcDS ),
                                           GDALGetGCPs( hSrcDS ), nOrder,
                                           FALSE );
         }
 
-        if( psInfo->pSrcGCPTransformArg == NULL )
+        if( psInfo->pSrcTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
             return NULL;
         }
+        psInfo->pSrcTransformer = GDALGCPTransform;
 
         if( pszSrcWKT == NULL )
             pszSrcWKT = GDALGetGCPProjection( hSrcDS );
@@ -1279,58 +1339,61 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     else if( bGCPUseOK
              && GDALGetGCPCount( hSrcDS ) > 0
              && nOrder <= 0
-             && (pszMethod == NULL || EQUAL(pszMethod,"GCP_TPS")) )
+             && (pszMethod == NULL || EQUAL(pszMethod, "GCP_TPS")) )
     {
-        psInfo->pSrcTPSTransformArg =
+        psInfo->pSrcTransformArg =
             GDALCreateTPSTransformerInt( GDALGetGCPCount( hSrcDS ),
                                          GDALGetGCPs( hSrcDS ), FALSE,
                                          papszOptions);
-        if( psInfo->pSrcTPSTransformArg == NULL )
+        if( psInfo->pSrcTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
             return NULL;
         }
+        psInfo->pSrcTransformer = GDALTPSTransform;
 
         if( pszSrcWKT == NULL )
             pszSrcWKT = GDALGetGCPProjection( hSrcDS );
     }
 
-    else if( (pszMethod == NULL || EQUAL(pszMethod,"RPC"))
+    else if( (pszMethod == NULL || EQUAL(pszMethod, "RPC"))
              && (papszMD = GDALGetMetadata( hSrcDS, "RPC" )) != NULL
              && GDALExtractRPCInfo( papszMD, &sRPCInfo ) )
     {
-        psInfo->pSrcRPCTransformArg =
+        psInfo->pSrcTransformArg =
             GDALCreateRPCTransformer( &sRPCInfo, FALSE, 0, papszOptions );
-        if( psInfo->pSrcRPCTransformArg == NULL )
+        if( psInfo->pSrcTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
             return NULL;
         }
+        psInfo->pSrcTransformer = GDALRPCTransform;
         if( pszSrcWKT == NULL )
             pszSrcWKT = SRS_WKT_WGS84;
     }
 
-    else if( (pszMethod == NULL || EQUAL(pszMethod,"GEOLOC_ARRAY"))
+    else if( (pszMethod == NULL || EQUAL(pszMethod, "GEOLOC_ARRAY"))
              && (papszMD = GDALGetMetadata( hSrcDS, "GEOLOCATION" )) != NULL )
     {
-        psInfo->pSrcGeoLocTransformArg =
+        psInfo->pSrcTransformArg =
             GDALCreateGeoLocTransformer( hSrcDS, papszMD, FALSE );
 
-        if( psInfo->pSrcGeoLocTransformArg == NULL )
+        if( psInfo->pSrcTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
             return NULL;
         }
+        psInfo->pSrcTransformer = GDALGeoLocTransform;
         if( pszSrcWKT == NULL )
             pszSrcWKT = CSLFetchNameValue( papszMD, "SRS" );
     }
 
     else if( pszMethod != NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to compute a %s based transformation between pixel/line\n"
-                  "and georeferenced coordinates for %s.\n",
-                  pszMethod, GDALGetDescription( hSrcDS ) );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to compute a %s based transformation between "
+                 "pixel/line and georeferenced coordinates for %s.",
+                 pszMethod, GDALGetDescription(hSrcDS));
 
         GDALDestroyGenImgProjTransformer( psInfo );
         return NULL;
@@ -1338,25 +1401,54 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "The transformation is already \"north up\" or\n"
-                  "a transformation between pixel/line and georeferenced\n"
-                  "coordinates cannot be computed for %s.\n"
-                  "There is no affine transformation and no GCPs.\n"
-                  "Specify transformation option SRC_METHOD=NO_GEOTRANSFORM to bypass this check.",
-                  GDALGetDescription( hSrcDS ) );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The transformation is already \"north up\" or "
+                 "a transformation between pixel/line and georeferenced "
+                 "coordinates cannot be computed for %s. "
+                 "There is no affine transformation and no GCPs. "
+                 "Specify transformation option SRC_METHOD=NO_GEOTRANSFORM to "
+                 "bypass this check.",
+                 GDALGetDescription(hSrcDS));
 
         GDALDestroyGenImgProjTransformer( psInfo );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
+/*      Handle optional source approximation transformer.               */
+/* -------------------------------------------------------------------- */
+    if( psInfo->pSrcTransformer )
+    {
+        const char* pszSrcApproxErrorFwd = CSLFetchNameValue( papszOptions,
+                                                "SRC_APPROX_ERROR_IN_SRS_UNIT" );
+        const char* pszSrcApproxErrorReverse = CSLFetchNameValue( papszOptions,
+                                                "SRC_APPROX_ERROR_IN_PIXEL" );
+        if( pszSrcApproxErrorFwd &&pszSrcApproxErrorReverse  )
+        {
+            void* pArg = GDALCreateApproxTransformer2( psInfo->pSrcTransformer,
+                                            psInfo->pSrcTransformArg,
+                                            CPLAtof(pszSrcApproxErrorFwd),
+                                            CPLAtof(pszSrcApproxErrorReverse) );
+            if( pArg == NULL )
+            {
+                GDALDestroyGenImgProjTransformer( psInfo );
+                return NULL;
+            }
+            psInfo->pSrcTransformArg = pArg;
+            psInfo->pSrcTransformer = GDALApproxTransform;
+            GDALApproxTransformerOwnsSubtransformer(psInfo->pSrcTransformArg,
+                                                    TRUE);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Get forward and inverse geotransform for destination image.     */
 /*      If we have no destination use a unit transform.                 */
 /* -------------------------------------------------------------------- */
     const char *pszDstMethod = CSLFetchNameValue( papszOptions, "DST_METHOD" );
 
-    if( !hDstDS || (pszDstMethod != NULL && EQUAL(pszDstMethod,"NO_GEOTRANSFORM"))  )
+    if( !hDstDS || (pszDstMethod != NULL &&
+                    EQUAL(pszDstMethod, "NO_GEOTRANSFORM"))  )
     {
         psInfo->adfDstGeoTransform[0] = 0.0;
         psInfo->adfDstGeoTransform[1] = 1.0;
@@ -1367,7 +1459,7 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         memcpy( psInfo->adfDstInvGeoTransform, psInfo->adfDstGeoTransform,
                 sizeof(double) * 6 );
     }
-    else if( (pszDstMethod == NULL || EQUAL(pszDstMethod,"GEOTRANSFORM"))
+    else if( (pszDstMethod == NULL || EQUAL(pszDstMethod, "GEOTRANSFORM"))
         && GDALGetGeoTransform( hDstDS, psInfo->adfDstGeoTransform ) == CE_None)
     {
         if( pszDstWKT == NULL )
@@ -1382,12 +1474,12 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         }
     }
     else if( bGCPUseOK
-             && (pszDstMethod == NULL || EQUAL(pszDstMethod,"GCP_POLYNOMIAL") )
+             && (pszDstMethod == NULL || EQUAL(pszDstMethod, "GCP_POLYNOMIAL") )
              && GDALGetGCPCount( hDstDS ) > 0 && nOrder >= 0 )
     {
-        if(bRefine)
+        if( bRefine )
         {
-            psInfo->pDstGCPTransformArg =
+            psInfo->pDstTransformArg =
                 GDALCreateGCPRefineTransformer( GDALGetGCPCount( hDstDS ),
                                                 GDALGetGCPs( hDstDS ), nOrder,
                                                 FALSE, dfTolerance,
@@ -1395,17 +1487,18 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
         }
         else
         {
-            psInfo->pDstGCPTransformArg =
+            psInfo->pDstTransformArg =
                 GDALCreateGCPTransformer( GDALGetGCPCount( hDstDS ),
                                           GDALGetGCPs( hDstDS ), nOrder,
                                           FALSE );
         }
 
-        if( psInfo->pDstGCPTransformArg == NULL )
+        if( psInfo->pDstTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
             return NULL;
         }
+        psInfo->pDstTransformer = GDALGCPTransform;
 
         if( pszDstWKT == NULL )
             pszDstWKT = GDALGetGCPProjection( hDstDS );
@@ -1413,69 +1506,157 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
     else if( bGCPUseOK
              && GDALGetGCPCount( hDstDS ) > 0
              && nOrder <= 0
-             && (pszDstMethod == NULL || EQUAL(pszDstMethod,"GCP_TPS")) )
+             && (pszDstMethod == NULL || EQUAL(pszDstMethod, "GCP_TPS")) )
     {
-        psInfo->pDstTPSTransformArg =
+        psInfo->pDstTransformArg =
             GDALCreateTPSTransformerInt( GDALGetGCPCount( hDstDS ),
                                          GDALGetGCPs( hDstDS ), FALSE,
                                          papszOptions );
-        if( psInfo->pDstTPSTransformArg == NULL )
+        if( psInfo->pDstTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
             return NULL;
         }
+        psInfo->pDstTransformer = GDALTPSTransform;
 
         if( pszDstWKT == NULL )
             pszDstWKT = GDALGetGCPProjection( hDstDS );
     }
-    else if( (pszDstMethod == NULL || EQUAL(pszDstMethod,"RPC"))
+    else if( (pszDstMethod == NULL || EQUAL(pszDstMethod, "RPC"))
              && (papszMD = GDALGetMetadata( hDstDS, "RPC" )) != NULL
              && GDALExtractRPCInfo( papszMD, &sRPCInfo ) )
     {
-        psInfo->pDstRPCTransformArg =
+        psInfo->pDstTransformArg =
             GDALCreateRPCTransformer( &sRPCInfo, FALSE, 0, papszOptions );
-        if( psInfo->pDstRPCTransformArg == NULL )
+        if( psInfo->pDstTransformArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
             return NULL;
         }
+        psInfo->pDstTransformer = GDALRPCTransform;
         if( pszDstWKT == NULL )
             pszDstWKT = SRS_WKT_WGS84;
     }
 
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to compute a transformation between pixel/line\n"
-                  "and georeferenced coordinates for %s.\n"
-                  "There is no affine transformation and no GCPs.\n"
-                  "Specify transformation option DST_METHOD=NO_GEOTRANSFORM "
-                  "to bypass this check.",
-                  GDALGetDescription( hDstDS ) );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to compute a transformation between pixel/line "
+                 "and georeferenced coordinates for %s. "
+                 "There is no affine transformation and no GCPs. "
+                 "Specify transformation option DST_METHOD=NO_GEOTRANSFORM "
+                 "to bypass this check.",
+                 GDALGetDescription(hDstDS));
 
         GDALDestroyGenImgProjTransformer( psInfo );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
+/*      Handle optional source approximation transformer.               */
+/* -------------------------------------------------------------------- */
+    if( psInfo->pDstTransformer )
+    {
+        const char* pszDstApproxErrorFwd = CSLFetchNameValue( papszOptions,
+                                                "DST_APPROX_ERROR_IN_PIXEL" );
+        const char* pszDstApproxErrorReverse = CSLFetchNameValue( papszOptions,
+                                                "DST_APPROX_ERROR_IN_SRS_UNIT" );
+        if( pszDstApproxErrorFwd &&pszDstApproxErrorReverse  )
+        {
+            void* pArg = GDALCreateApproxTransformer2( psInfo->pDstTransformer,
+                                            psInfo->pDstTransformArg,
+                                            CPLAtof(pszDstApproxErrorFwd),
+                                            CPLAtof(pszDstApproxErrorReverse) );
+            if( pArg == NULL )
+            {
+                GDALDestroyGenImgProjTransformer( psInfo );
+                return NULL;
+            }
+            psInfo->pDstTransformArg = pArg;
+            psInfo->pDstTransformer = GDALApproxTransform;
+            GDALApproxTransformerOwnsSubtransformer(psInfo->pDstTransformArg,
+                                                    TRUE);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Setup reprojection.                                             */
 /* -------------------------------------------------------------------- */
-    if( pszSrcWKT != NULL && strlen(pszSrcWKT) > 0
-        && pszDstWKT != NULL && strlen(pszDstWKT) > 0
-        && !EQUAL(pszSrcWKT,pszDstWKT) )
+    CPLString osSrcWKT = pszSrcWKT ? pszSrcWKT : "";
+    CPLString osDstWKT = pszDstWKT ? pszDstWKT : "";
+
+    if( !osSrcWKT.empty() && !osDstWKT.empty() && !EQUAL(osSrcWKT, osDstWKT) )
+    {
+        if( CPLFetchBool( papszOptions, "STRIP_VERT_CS", false ) )
+        {
+            OGRSpatialReference oSRS;
+            oSRS.SetFromUserInput(osSrcWKT);
+            if( oSRS.IsCompound() )
+            {
+                OGR_SRSNode* poNode = oSRS.GetRoot()->GetChild(1);
+                if( poNode != NULL )
+                {
+                    char* pszWKT = NULL;
+                    poNode->exportToWkt(&pszWKT);
+                    osSrcWKT = pszWKT;
+                    CPLFree(pszWKT);
+                }
+            }
+
+            oSRS.SetFromUserInput(osDstWKT);
+            if( oSRS.IsCompound() )
+            {
+                OGR_SRSNode* poNode = oSRS.GetRoot()->GetChild(1);
+                if( poNode != NULL )
+                {
+                    char* pszWKT = NULL;
+                    poNode->exportToWkt(&pszWKT);
+                    osDstWKT = pszWKT;
+                    CPLFree(pszWKT);
+                }
+            }
+        }
+    }
+
+    if( !osSrcWKT.empty() && !osDstWKT.empty() && !EQUAL(osSrcWKT, osDstWKT) )
     {
-        CPLString osSrcWKT = pszSrcWKT;
-        if (hSrcDS
-            && CSLFetchBoolean( papszOptions, "INSERT_CENTER_LONG", TRUE ) )
+        if( hSrcDS
+            && CPLFetchBool( papszOptions, "INSERT_CENTER_LONG", true ) )
             osSrcWKT = InsertCenterLong( hSrcDS, osSrcWKT );
 
+
         psInfo->pReprojectArg =
-            GDALCreateReprojectionTransformer( osSrcWKT.c_str(), pszDstWKT );
+            GDALCreateReprojectionTransformer( osSrcWKT, osDstWKT );
         if( psInfo->pReprojectArg == NULL )
         {
             GDALDestroyGenImgProjTransformer( psInfo );
             return NULL;
         }
+        psInfo->pReproject = GDALReprojectionTransform;
+
+/* -------------------------------------------------------------------- */
+/*      Handle optional reprojection approximation transformer.         */
+/* -------------------------------------------------------------------- */
+        const char* psApproxErrorFwd = CSLFetchNameValue( papszOptions,
+                                    "REPROJECTION_APPROX_ERROR_IN_DST_SRS_UNIT" );
+        const char* psApproxErrorReverse = CSLFetchNameValue( papszOptions,
+                                    "REPROJECTION_APPROX_ERROR_IN_SRC_SRS_UNIT" );
+        if( psApproxErrorFwd && psApproxErrorReverse )
+        {
+            void* pArg = GDALCreateApproxTransformer2( psInfo->pReproject,
+                                                psInfo->pReprojectArg,
+                                                CPLAtof(psApproxErrorFwd),
+                                                CPLAtof(psApproxErrorReverse) );
+            if( pArg == NULL )
+            {
+                GDALDestroyGenImgProjTransformer( psInfo );
+                return NULL;
+            }
+            psInfo->pReprojectArg = pArg;
+            psInfo->pReproject = GDALApproxTransform;
+            GDALApproxTransformerOwnsSubtransformer(psInfo->pReprojectArg,
+                                                    TRUE);
+        }
     }
 
     return psInfo;
@@ -1485,16 +1666,20 @@ GDALCreateGenImgProjTransformer2( GDALDatasetH hSrcDS, GDALDatasetH hDstDS,
 /*                  GDALRefreshGenImgProjTransformer()                  */
 /************************************************************************/
 
-void GDALRefreshGenImgProjTransformer(void* hTransformArg)
+void GDALRefreshGenImgProjTransformer( void* hTransformArg )
 {
     GDALGenImgProjTransformInfo *psInfo =
         static_cast<GDALGenImgProjTransformInfo *>( hTransformArg );
 
-    if (psInfo->pReprojectArg)
+    if( psInfo->pReprojectArg )
     {
-        CPLXMLNode* psXML = GDALSerializeReprojectionTransformer(psInfo->pReprojectArg);
-        GDALDestroyReprojectionTransformer(psInfo->pReprojectArg);
-        psInfo->pReprojectArg = GDALDeserializeReprojectionTransformer(psXML);
+        CPLXMLNode* psXML =
+            GDALSerializeTransformer(psInfo->pReproject,
+                                     psInfo->pReprojectArg);
+        GDALDestroyTransformer(psInfo->pReprojectArg);
+        GDALDeserializeTransformer(psXML,
+                                   &psInfo->pReproject,
+                                   &psInfo->pReprojectArg);
         CPLDestroyXMLNode(psXML);
     }
 }
@@ -1547,12 +1732,12 @@ GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
                                   const double *padfDstGeoTransform )
 
 {
-    GDALGenImgProjTransformInfo *psInfo;
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the transform info.                                  */
 /* -------------------------------------------------------------------- */
-    psInfo = GDALCreateGenImgProjTransformerInternal();
+    GDALGenImgProjTransformInfo *psInfo =
+        GDALCreateGenImgProjTransformerInternal();
 
 /* -------------------------------------------------------------------- */
 /*      Get forward and inverse geotransform for the source image.      */
@@ -1595,6 +1780,7 @@ GDALCreateGenImgProjTransformer3( const char *pszSrcWKT,
             GDALDestroyGenImgProjTransformer( psInfo );
             return NULL;
         }
+        psInfo->pReproject = GDALReprojectionTransform;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1652,7 +1838,8 @@ void GDALSetGenImgProjTransformerDstGeoTransform(
     void *hTransformArg, const double *padfGeoTransform )
 
 {
-    VALIDATE_POINTER0( hTransformArg, "GDALSetGenImgProjTransformerDstGeoTransform" );
+    VALIDATE_POINTER0( hTransformArg,
+                       "GDALSetGenImgProjTransformerDstGeoTransform" );
 
     GDALGenImgProjTransformInfo *psInfo =
         static_cast<GDALGenImgProjTransformInfo *>( hTransformArg );
@@ -1685,31 +1872,16 @@ void GDALDestroyGenImgProjTransformer( void *hTransformArg )
         return;
 
     GDALGenImgProjTransformInfo *psInfo =
-        (GDALGenImgProjTransformInfo *) hTransformArg;
-
-    if( psInfo->pSrcGCPTransformArg != NULL )
-        GDALDestroyGCPTransformer( psInfo->pSrcGCPTransformArg );
-
-    if( psInfo->pSrcTPSTransformArg != NULL )
-        GDALDestroyTPSTransformer( psInfo->pSrcTPSTransformArg );
-
-    if( psInfo->pSrcRPCTransformArg != NULL )
-        GDALDestroyRPCTransformer( psInfo->pSrcRPCTransformArg );
-
-    if( psInfo->pSrcGeoLocTransformArg != NULL )
-        GDALDestroyGeoLocTransformer( psInfo->pSrcGeoLocTransformArg );
+        static_cast<GDALGenImgProjTransformInfo *>(hTransformArg);
 
-    if( psInfo->pDstGCPTransformArg != NULL )
-        GDALDestroyGCPTransformer( psInfo->pDstGCPTransformArg );
+    if( psInfo->pSrcTransformArg != NULL )
+        GDALDestroyTransformer( psInfo->pSrcTransformArg );
 
-    if( psInfo->pDstRPCTransformArg != NULL )
-        GDALDestroyRPCTransformer( psInfo->pDstRPCTransformArg );
-
-    if( psInfo->pDstTPSTransformArg != NULL )
-        GDALDestroyTPSTransformer( psInfo->pDstTPSTransformArg );
+    if( psInfo->pDstTransformArg != NULL )
+        GDALDestroyTransformer( psInfo->pDstTransformArg );
 
     if( psInfo->pReprojectArg != NULL )
-        GDALDestroyReprojectionTransformer( psInfo->pReprojectArg );
+        GDALDestroyTransformer( psInfo->pReprojectArg );
 
     CPLFree( psInfo );
 }
@@ -1731,26 +1903,23 @@ void GDALDestroyGenImgProjTransformer( void *hTransformArg )
 int countGDALGenImgProjTransform = 0;
 #endif
 
-int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
+int GDALGenImgProjTransform( void *pTransformArgIn, int bDstToSrc,
                              int nPointCount,
                              double *padfX, double *padfY, double *padfZ,
                              int *panSuccess )
 {
     GDALGenImgProjTransformInfo *psInfo =
-        (GDALGenImgProjTransformInfo *) pTransformArg;
-    int   i;
+        (GDALGenImgProjTransformInfo *) pTransformArgIn;
     double *padfGeoTransform;
-    void *pGCPTransformArg;
-    void *pRPCTransformArg;
-    void *pTPSTransformArg;
-    void *pGeoLocTransformArg;
+    GDALTransformerFunc pTransformer;
+    void *pTransformArg;
 
 #ifdef DEBUG_APPROX_TRANSFORMER
     CPLAssert(nPointCount > 0);
     countGDALGenImgProjTransform += nPointCount;
 #endif
 
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
         panSuccess[i] = ( padfX[i] != HUGE_VAL && padfY[i] != HUGE_VAL );
     }
@@ -1762,64 +1931,37 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
     if( bDstToSrc )
     {
         padfGeoTransform = psInfo->adfDstGeoTransform;
-        pGCPTransformArg = psInfo->pDstGCPTransformArg;
-        pRPCTransformArg = psInfo->pDstRPCTransformArg;
-        pTPSTransformArg = psInfo->pDstTPSTransformArg;
-        pGeoLocTransformArg = NULL;
+        pTransformArg = psInfo->pDstTransformArg;
+        pTransformer = psInfo->pDstTransformer;
     }
     else
     {
         padfGeoTransform = psInfo->adfSrcGeoTransform;
-        pGCPTransformArg = psInfo->pSrcGCPTransformArg;
-        pRPCTransformArg = psInfo->pSrcRPCTransformArg;
-        pTPSTransformArg = psInfo->pSrcTPSTransformArg;
-        pGeoLocTransformArg = psInfo->pSrcGeoLocTransformArg;
+        pTransformArg = psInfo->pSrcTransformArg;
+        pTransformer = psInfo->pSrcTransformer;
     }
 
-    if( pGCPTransformArg != NULL )
-    {
-        if( !GDALGCPTransform( pGCPTransformArg, FALSE,
-                               nPointCount, padfX, padfY, padfZ,
-                               panSuccess ) )
-            return FALSE;
-    }
-    else if( pTPSTransformArg != NULL )
-    {
-        if( !GDALTPSTransform( pTPSTransformArg, FALSE,
-                               nPointCount, padfX, padfY, padfZ,
-                               panSuccess ) )
-            return FALSE;
-    }
-    else if( pRPCTransformArg != NULL )
-    {
-        if( !GDALRPCTransform( pRPCTransformArg, FALSE,
-                               nPointCount, padfX, padfY, padfZ,
-                               panSuccess ) )
-            return FALSE;
-    }
-    else if( pGeoLocTransformArg != NULL )
+    if( pTransformArg != NULL )
     {
-        if( !GDALGeoLocTransform( pGeoLocTransformArg, FALSE,
-                                  nPointCount, padfX, padfY, padfZ,
-                                  panSuccess ) )
+        if( !pTransformer( pTransformArg, FALSE,
+                           nPointCount, padfX, padfY, padfZ,
+                           panSuccess ) )
             return FALSE;
     }
     else
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
-            double dfNewX, dfNewY;
-
             if( padfX[i] == HUGE_VAL || padfY[i] == HUGE_VAL )
             {
                 panSuccess[i] = FALSE;
                 continue;
             }
 
-            dfNewX = padfGeoTransform[0]
+            const double dfNewX = padfGeoTransform[0]
                 + padfX[i] * padfGeoTransform[1]
                 + padfY[i] * padfGeoTransform[2];
-            dfNewY = padfGeoTransform[3]
+            const double dfNewY = padfGeoTransform[3]
                 + padfX[i] * padfGeoTransform[4]
                 + padfY[i] * padfGeoTransform[5];
 
@@ -1833,9 +1975,9 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
 /* -------------------------------------------------------------------- */
     if( psInfo->pReprojectArg )
     {
-        if( !GDALReprojectionTransform( psInfo->pReprojectArg, bDstToSrc,
-                                        nPointCount, padfX, padfY, padfZ,
-                                        panSuccess ) )
+        if( !psInfo->pReproject( psInfo->pReprojectArg, bDstToSrc,
+                                 nPointCount, padfX, padfY, padfZ,
+                                 panSuccess ) )
             return FALSE;
     }
 
@@ -1845,61 +1987,35 @@ int GDALGenImgProjTransform( void *pTransformArg, int bDstToSrc,
     if( bDstToSrc )
     {
         padfGeoTransform = psInfo->adfSrcInvGeoTransform;
-        pGCPTransformArg = psInfo->pSrcGCPTransformArg;
-        pRPCTransformArg = psInfo->pSrcRPCTransformArg;
-        pTPSTransformArg = psInfo->pSrcTPSTransformArg;
-        pGeoLocTransformArg = psInfo->pSrcGeoLocTransformArg;
+        pTransformArg = psInfo->pSrcTransformArg;
+        pTransformer = psInfo->pSrcTransformer;
     }
     else
     {
         padfGeoTransform = psInfo->adfDstInvGeoTransform;
-        pGCPTransformArg = psInfo->pDstGCPTransformArg;
-        pRPCTransformArg = psInfo->pDstRPCTransformArg;
-        pTPSTransformArg = psInfo->pDstTPSTransformArg;
-        pGeoLocTransformArg = NULL;
+        pTransformArg = psInfo->pDstTransformArg;
+        pTransformer = psInfo->pDstTransformer;
     }
 
-    if( pGCPTransformArg != NULL )
-    {
-        if( !GDALGCPTransform( pGCPTransformArg, TRUE,
-                               nPointCount, padfX, padfY, padfZ,
-                               panSuccess ) )
-            return FALSE;
-    }
-    else if( pTPSTransformArg != NULL )
-    {
-        if( !GDALTPSTransform( pTPSTransformArg, TRUE,
-                               nPointCount, padfX, padfY, padfZ,
-                               panSuccess ) )
-            return FALSE;
-    }
-    else if( pRPCTransformArg != NULL )
-    {
-        if( !GDALRPCTransform( pRPCTransformArg, TRUE,
-                               nPointCount, padfX, padfY, padfZ,
-                               panSuccess ) )
-            return FALSE;
-    }
-    else if( pGeoLocTransformArg != NULL )
+
+    if( pTransformArg != NULL )
     {
-        if( !GDALGeoLocTransform( pGeoLocTransformArg, TRUE,
-                                  nPointCount, padfX, padfY, padfZ,
-                                  panSuccess ) )
+        if( !pTransformer( pTransformArg, TRUE,
+                           nPointCount, padfX, padfY, padfZ,
+                           panSuccess ) )
             return FALSE;
     }
     else
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
-            double dfNewX, dfNewY;
-
             if( !panSuccess[i] )
                 continue;
 
-            dfNewX = padfGeoTransform[0]
+            const double dfNewX = padfGeoTransform[0]
                 + padfX[i] * padfGeoTransform[1]
                 + padfY[i] * padfGeoTransform[2];
-            dfNewY = padfGeoTransform[3]
+            const double dfNewY = padfGeoTransform[3]
                 + padfX[i] * padfGeoTransform[4]
                 + padfY[i] * padfGeoTransform[5];
 
@@ -1919,69 +2035,30 @@ static CPLXMLNode *
 GDALSerializeGenImgProjTransformer( void *pTransformArg )
 
 {
-    char szWork[200];
-    CPLXMLNode *psTree;
     GDALGenImgProjTransformInfo *psInfo =
-        (GDALGenImgProjTransformInfo *) pTransformArg;
-
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "GenImgProjTransformer" );
+        static_cast<GDALGenImgProjTransformInfo *>(pTransformArg);
 
-/* -------------------------------------------------------------------- */
-/*      Handle GCP transformation.                                      */
-/* -------------------------------------------------------------------- */
-    if( psInfo->pSrcGCPTransformArg != NULL )
-    {
+    CPLXMLNode *psTree =
+        CPLCreateXMLNode( NULL, CXT_Element, "GenImgProjTransformer" );
 
-        CPLXMLNode *psTransformerContainer =
-            CPLCreateXMLNode( psTree, CXT_Element, "SrcGCPTransformer" );
-
-        CPLXMLNode *psTransformer
-            = GDALSerializeTransformer( GDALGCPTransform,
-                                        psInfo->pSrcGCPTransformArg);
-        if( psTransformer != NULL )
-            CPLAddXMLChild( psTransformerContainer, psTransformer );
-    }
+    char szWork[200] = {};
 
 /* -------------------------------------------------------------------- */
-/*      Handle TPS transformation.                                      */
+/*      Handle source transformation.                                   */
 /* -------------------------------------------------------------------- */
-    else if( psInfo->pSrcTPSTransformArg != NULL )
+    if( psInfo->pSrcTransformArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer
-            = CPLCreateXMLNode( psTree, CXT_Element, "SrcTPSTransformer" );
-
-        CPLXMLNode *psTransformer
-            = GDALSerializeTransformer( NULL, psInfo->pSrcTPSTransformArg);
+        CPLXMLNode *psTransformer =
+            GDALSerializeTransformer( psInfo->pSrcTransformer,
+                                      psInfo->pSrcTransformArg);
         if( psTransformer != NULL )
-            CPLAddXMLChild( psTransformerContainer, psTransformer );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Handle GeoLoc transformation.                                   */
-/* -------------------------------------------------------------------- */
-    else if( psInfo->pSrcGeoLocTransformArg != NULL )
-    {
-        CPLXMLNode *psTransformerContainer
-            = CPLCreateXMLNode( psTree, CXT_Element, "SrcGeoLocTransformer" );
-
-        CPLXMLNode *psTransformer
-            = GDALSerializeTransformer( NULL, psInfo->pSrcGeoLocTransformArg);
-        if( psTransformer != NULL )
-            CPLAddXMLChild( psTransformerContainer, psTransformer );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Handle RPC transformation.                                      */
-/* -------------------------------------------------------------------- */
-    else if( psInfo->pSrcRPCTransformArg != NULL )
-    {
-        CPLXMLNode *psTransformerContainer
-            = CPLCreateXMLNode( psTree, CXT_Element, "SrcRPCTransformer" );
+        {
+            CPLXMLNode *psTransformerContainer =
+                CPLCreateXMLNode( psTree, CXT_Element,
+                              CPLSPrintf("Src%s", psTransformer->pszValue) );
 
-        CPLXMLNode *psTransformer
-            = GDALSerializeTransformer( NULL, psInfo->pSrcRPCTransformArg);
-        if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1989,66 +2066,44 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     else
     {
-        CPLsnprintf( szWork, sizeof(szWork), "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
-                 psInfo->adfSrcGeoTransform[0],
-                 psInfo->adfSrcGeoTransform[1],
-                 psInfo->adfSrcGeoTransform[2],
-                 psInfo->adfSrcGeoTransform[3],
-                 psInfo->adfSrcGeoTransform[4],
-                 psInfo->adfSrcGeoTransform[5] );
+        CPLsnprintf( szWork, sizeof(szWork),
+                     "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+                     psInfo->adfSrcGeoTransform[0],
+                     psInfo->adfSrcGeoTransform[1],
+                     psInfo->adfSrcGeoTransform[2],
+                     psInfo->adfSrcGeoTransform[3],
+                     psInfo->adfSrcGeoTransform[4],
+                     psInfo->adfSrcGeoTransform[5] );
         CPLCreateXMLElementAndValue( psTree, "SrcGeoTransform", szWork );
 
-        CPLsnprintf( szWork, sizeof(szWork), "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
-                 psInfo->adfSrcInvGeoTransform[0],
-                 psInfo->adfSrcInvGeoTransform[1],
-                 psInfo->adfSrcInvGeoTransform[2],
-                 psInfo->adfSrcInvGeoTransform[3],
-                 psInfo->adfSrcInvGeoTransform[4],
-                 psInfo->adfSrcInvGeoTransform[5] );
+        CPLsnprintf( szWork, sizeof(szWork),
+                     "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+                     psInfo->adfSrcInvGeoTransform[0],
+                     psInfo->adfSrcInvGeoTransform[1],
+                     psInfo->adfSrcInvGeoTransform[2],
+                     psInfo->adfSrcInvGeoTransform[3],
+                     psInfo->adfSrcInvGeoTransform[4],
+                     psInfo->adfSrcInvGeoTransform[5] );
         CPLCreateXMLElementAndValue( psTree, "SrcInvGeoTransform", szWork );
     }
 
-/* -------------------------------------------------------------------- */
-/*      Handle Dest GCP transformation.                                 */
-/* -------------------------------------------------------------------- */
-    if( psInfo->pDstGCPTransformArg != NULL )
-    {
-        CPLXMLNode *psTransformerContainer
-            = CPLCreateXMLNode( psTree, CXT_Element, "DstGCPTransformer" );
-
-        CPLXMLNode *psTransformer
-            = GDALSerializeTransformer( GDALGCPTransform,
-                                        psInfo->pDstGCPTransformArg);
-        if( psTransformer != NULL )
-            CPLAddXMLChild( psTransformerContainer, psTransformer );
-    }
 
 /* -------------------------------------------------------------------- */
-/*      Handle Dest TPS transformation.                                 */
+/*      Handle dest transformation.                                     */
 /* -------------------------------------------------------------------- */
-    else if( psInfo->pDstTPSTransformArg != NULL )
+    if( psInfo->pDstTransformArg != NULL )
     {
-        CPLXMLNode *psTransformerContainer
-            = CPLCreateXMLNode( psTree, CXT_Element, "DstTPSTransformer" );
-
-        CPLXMLNode *psTransformer
-            = GDALSerializeTransformer( NULL, psInfo->pDstTPSTransformArg);
+        CPLXMLNode *psTransformer =
+            GDALSerializeTransformer( psInfo->pDstTransformer,
+                                      psInfo->pDstTransformArg);
         if( psTransformer != NULL )
-            CPLAddXMLChild( psTransformerContainer, psTransformer );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Handle Dest RPC transformation.                                 */
-/* -------------------------------------------------------------------- */
-    else if( psInfo->pDstRPCTransformArg != NULL )
-    {
-        CPLXMLNode *psTransformerContainer
-            = CPLCreateXMLNode( psTree, CXT_Element, "DstRPCTransformer" );
+        {
+            CPLXMLNode *psTransformerContainer =
+                CPLCreateXMLNode( psTree, CXT_Element,
+                              CPLSPrintf("Dst%s", psTransformer->pszValue) );
 
-        CPLXMLNode *psTransformer
-            = GDALSerializeTransformer( NULL, psInfo->pDstRPCTransformArg);
-        if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -2056,22 +2111,24 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
     else
     {
-        CPLsnprintf( szWork, sizeof(szWork), "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
-                 psInfo->adfDstGeoTransform[0],
-                 psInfo->adfDstGeoTransform[1],
-                 psInfo->adfDstGeoTransform[2],
-                 psInfo->adfDstGeoTransform[3],
-                 psInfo->adfDstGeoTransform[4],
-                 psInfo->adfDstGeoTransform[5] );
+        CPLsnprintf( szWork, sizeof(szWork),
+                     "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+                     psInfo->adfDstGeoTransform[0],
+                     psInfo->adfDstGeoTransform[1],
+                     psInfo->adfDstGeoTransform[2],
+                     psInfo->adfDstGeoTransform[3],
+                     psInfo->adfDstGeoTransform[4],
+                     psInfo->adfDstGeoTransform[5] );
         CPLCreateXMLElementAndValue( psTree, "DstGeoTransform", szWork );
 
-        CPLsnprintf( szWork, sizeof(szWork), "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
-                 psInfo->adfDstInvGeoTransform[0],
-                 psInfo->adfDstInvGeoTransform[1],
-                 psInfo->adfDstInvGeoTransform[2],
-                 psInfo->adfDstInvGeoTransform[3],
-                 psInfo->adfDstInvGeoTransform[4],
-                 psInfo->adfDstInvGeoTransform[5] );
+        CPLsnprintf( szWork, sizeof(szWork),
+                     "%.18g,%.18g,%.18g,%.18g,%.18g,%.18g",
+                     psInfo->adfDstInvGeoTransform[0],
+                     psInfo->adfDstInvGeoTransform[1],
+                     psInfo->adfDstInvGeoTransform[2],
+                     psInfo->adfDstInvGeoTransform[3],
+                     psInfo->adfDstInvGeoTransform[4],
+                     psInfo->adfDstInvGeoTransform[5] );
         CPLCreateXMLElementAndValue( psTree, "DstInvGeoTransform", szWork );
     }
 
@@ -2085,8 +2142,8 @@ GDALSerializeGenImgProjTransformer( void *pTransformArg )
             = CPLCreateXMLNode( psTree, CXT_Element, "ReprojectTransformer" );
 
         CPLXMLNode *psTransformer
-            = GDALSerializeTransformer( GDALReprojectionTransform,
-                                                  psInfo->pReprojectArg );
+            = GDALSerializeTransformer( psInfo->pReproject,
+                                        psInfo->pReprojectArg );
         if( psTransformer != NULL )
             CPLAddXMLChild( psTransformerContainer, psTransformer );
     }
@@ -2117,95 +2174,54 @@ static void GDALDeserializeGeoTransform(const char* pszGT,
 void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
 
 {
-    CPLXMLNode *psSubtree;
-
 /* -------------------------------------------------------------------- */
 /*      Initialize the transform info.                                  */
 /* -------------------------------------------------------------------- */
-    GDALGenImgProjTransformInfo *psInfo
-        = GDALCreateGenImgProjTransformerInternal();
+    GDALGenImgProjTransformInfo *psInfo =
+        GDALCreateGenImgProjTransformerInternal();
 
 /* -------------------------------------------------------------------- */
 /*      SrcGeotransform                                                 */
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psTree, "SrcGeoTransform" ) != NULL )
     {
-        GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "SrcGeoTransform", "" ),
-                                     psInfo->adfSrcGeoTransform );
+        GDALDeserializeGeoTransform(
+            CPLGetXMLValue( psTree, "SrcGeoTransform", "" ),
+            psInfo->adfSrcGeoTransform );
 
         if( CPLGetXMLNode( psTree, "SrcInvGeoTransform" ) != NULL )
         {
-            GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "SrcInvGeoTransform", "" ),
-                                     psInfo->adfSrcInvGeoTransform );
+            GDALDeserializeGeoTransform(
+                CPLGetXMLValue( psTree, "SrcInvGeoTransform", "" ),
+                psInfo->adfSrcInvGeoTransform );
         }
         else
         {
             if( !GDALInvGeoTransform( psInfo->adfSrcGeoTransform,
                                       psInfo->adfSrcInvGeoTransform ) )
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot invert geotransform");
             }
         }
     }
 
 /* -------------------------------------------------------------------- */
-/*      Src GCP Transform                                               */
-/* -------------------------------------------------------------------- */
-    psSubtree = CPLGetXMLNode( psTree, "SrcGCPTransformer" );
-    if( psSubtree != NULL && psSubtree->psChild != NULL )
-    {
-        psInfo->pSrcGCPTransformArg =
-            GDALDeserializeGCPTransformer( psSubtree->psChild );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Src TPS Transform                                               */
+/*      Src Transform                                                   */
 /* -------------------------------------------------------------------- */
-    psSubtree = CPLGetXMLNode( psTree, "SrcTPSTransformer" );
-    if( psSubtree != NULL && psSubtree->psChild != NULL )
-    {
-        psInfo->pSrcTPSTransformArg =
-            GDALDeserializeTPSTransformer( psSubtree->psChild );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Src GeoLoc Transform                                            */
-/* -------------------------------------------------------------------- */
-    psSubtree = CPLGetXMLNode( psTree, "SrcGeoLocTransformer" );
-    if( psSubtree != NULL && psSubtree->psChild != NULL )
-    {
-        psInfo->pSrcGeoLocTransformArg =
-            GDALDeserializeGeoLocTransformer( psSubtree->psChild );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Src RPC Transform                                               */
-/* -------------------------------------------------------------------- */
-    psSubtree = CPLGetXMLNode( psTree, "SrcRPCTransformer" );
-    if( psSubtree != NULL && psSubtree->psChild != NULL )
-    {
-        psInfo->pSrcRPCTransformArg =
-            GDALDeserializeRPCTransformer( psSubtree->psChild );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Dst TPS Transform                                               */
-/* -------------------------------------------------------------------- */
-    psSubtree = CPLGetXMLNode( psTree, "DstTPSTransformer" );
-    if( psSubtree != NULL && psSubtree->psChild != NULL )
-    {
-        psInfo->pDstTPSTransformArg =
-            GDALDeserializeTPSTransformer( psSubtree->psChild );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Dst RPC Transform                                               */
-/* -------------------------------------------------------------------- */
-    psSubtree = CPLGetXMLNode( psTree, "DstRPCTransformer" );
-    if( psSubtree != NULL && psSubtree->psChild != NULL )
+    else
     {
-        psInfo->pDstRPCTransformArg =
-            GDALDeserializeRPCTransformer( psSubtree->psChild );
+        for( CPLXMLNode* psIter = psTree->psChild; psIter != NULL;
+                                                   psIter = psIter->psNext )
+        {
+            if( psIter->eType == CXT_Element &&
+                STARTS_WITH_CI(psIter->pszValue, "Src") )
+            {
+                GDALDeserializeTransformer( psIter->psChild,
+                                            &psInfo->pSrcTransformer,
+                                            &psInfo->pSrcTransformArg );
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -2213,20 +2229,42 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psTree, "DstGeoTransform" ) != NULL )
     {
-        GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "DstGeoTransform", "" ),
-                                     psInfo->adfDstGeoTransform );
+        GDALDeserializeGeoTransform(
+            CPLGetXMLValue( psTree, "DstGeoTransform", "" ),
+            psInfo->adfDstGeoTransform);
 
         if( CPLGetXMLNode( psTree, "DstInvGeoTransform" ) != NULL )
         {
-            GDALDeserializeGeoTransform( CPLGetXMLValue( psTree, "DstInvGeoTransform", "" ),
-                                        psInfo->adfDstInvGeoTransform );
+            GDALDeserializeGeoTransform(
+                CPLGetXMLValue( psTree, "DstInvGeoTransform", "" ),
+                psInfo->adfDstInvGeoTransform);
         }
         else
         {
             if( !GDALInvGeoTransform( psInfo->adfDstGeoTransform,
                                       psInfo->adfDstInvGeoTransform ) )
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot invert geotransform");
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Dst Transform                                                   */
+/* -------------------------------------------------------------------- */
+    else
+    {
+        for( CPLXMLNode* psIter = psTree->psChild; psIter != NULL;
+                                                   psIter = psIter->psNext )
+        {
+            if( psIter->eType == CXT_Element &&
+                STARTS_WITH_CI(psIter->pszValue, "Dst") )
+            {
+                GDALDeserializeTransformer( psIter->psChild,
+                                            &psInfo->pDstTransformer,
+                                            &psInfo->pDstTransformArg );
+                break;
             }
         }
     }
@@ -2234,11 +2272,12 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
 /*      Reproject transformer                                           */
 /* -------------------------------------------------------------------- */
-    psSubtree = CPLGetXMLNode( psTree, "ReprojectTransformer" );
+    CPLXMLNode* psSubtree = CPLGetXMLNode( psTree, "ReprojectTransformer" );
     if( psSubtree != NULL && psSubtree->psChild != NULL )
     {
-        psInfo->pReprojectArg =
-            GDALDeserializeReprojectionTransformer( psSubtree->psChild );
+        GDALDeserializeTransformer( psSubtree->psChild,
+                                    &psInfo->pReproject,
+                                    &psInfo->pReprojectArg );
     }
 
     return psInfo;
@@ -2246,7 +2285,7 @@ void *GDALDeserializeGenImgProjTransformer( CPLXMLNode *psTree )
 
 /************************************************************************/
 /* ==================================================================== */
-/*			 GDALReprojectionTransformer                    */
+/*                       GDALReprojectionTransformer                    */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -2284,12 +2323,10 @@ void *GDALCreateReprojectionTransformer( const char *pszSrcWKT,
                                          const char *pszDstWKT )
 
 {
-    OGRSpatialReference oSrcSRS, oDstSRS;
-    OGRCoordinateTransformation *poForwardTransform;
-
 /* -------------------------------------------------------------------- */
 /*      Ingest the SRS definitions.                                     */
 /* -------------------------------------------------------------------- */
+    OGRSpatialReference oSrcSRS;
     if( oSrcSRS.importFromWkt( (char **) &pszSrcWKT ) != OGRERR_NONE )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -2297,6 +2334,8 @@ void *GDALCreateReprojectionTransformer( const char *pszSrcWKT,
                   pszSrcWKT );
         return NULL;
     }
+
+    OGRSpatialReference oDstSRS;
     if( oDstSRS.importFromWkt( (char **) &pszDstWKT ) != OGRERR_NONE )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -2308,7 +2347,8 @@ void *GDALCreateReprojectionTransformer( const char *pszSrcWKT,
 /* -------------------------------------------------------------------- */
 /*      Build the forward coordinate transformation.                    */
 /* -------------------------------------------------------------------- */
-    poForwardTransform = OGRCreateCoordinateTransformation(&oSrcSRS,&oDstSRS);
+    OGRCoordinateTransformation *poForwardTransform =
+        OGRCreateCoordinateTransformation(&oSrcSRS, &oDstSRS);
 
     if( poForwardTransform == NULL )
         // OGRCreateCoordinateTransformation() will report errors on its own.
@@ -2319,16 +2359,17 @@ void *GDALCreateReprojectionTransformer( const char *pszSrcWKT,
 /*      build reverse transform.  We assume that if the forward         */
 /*      transform can be created, then so can the reverse one.          */
 /* -------------------------------------------------------------------- */
-    GDALReprojectionTransformInfo *psInfo;
-
-    psInfo = (GDALReprojectionTransformInfo *)
-        CPLCalloc(sizeof(GDALReprojectionTransformInfo),1);
+    GDALReprojectionTransformInfo *psInfo =
+        static_cast<GDALReprojectionTransformInfo *>(
+            CPLCalloc(sizeof(GDALReprojectionTransformInfo), 1));
 
     psInfo->poForwardTransform = poForwardTransform;
     psInfo->poReverseTransform =
-        OGRCreateCoordinateTransformation(&oDstSRS,&oSrcSRS);
+        OGRCreateCoordinateTransformation(&oDstSRS, &oSrcSRS);
 
-    memcpy( psInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
+    memcpy( psInfo->sTI.abySignature,
+            GDAL_GTI2_SIGNATURE,
+            strlen(GDAL_GTI2_SIGNATURE) );
     psInfo->sTI.pszClassName = "GDALReprojectionTransformer";
     psInfo->sTI.pfnTransform = GDALReprojectionTransform;
     psInfo->sTI.pfnCleanup = GDALDestroyReprojectionTransformer;
@@ -2471,9 +2512,9 @@ GDALDeserializeReprojectionTransformer( CPLXMLNode *psTree )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "ReprojectionTransformer definition missing either\n"
-                  "SourceSRS or TargetSRS definition." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "ReprojectionTransformer definition missing either "
+                 "SourceSRS or TargetSRS definition.");
     }
 
     CPLFree( pszSourceWKT );
@@ -2493,33 +2534,37 @@ typedef struct
     GDALTransformerInfo sTI;
 
     GDALTransformerFunc pfnBaseTransformer;
-    void             *pBaseCBData;
-    double	      dfMaxError;
+    void *pBaseCBData;
+    double dfMaxErrorForward;
+    double dfMaxErrorReverse;
 
-    int               bOwnSubtransformer;
+    int bOwnSubtransformer;
 } ApproxTransformInfo;
 
 /************************************************************************/
 /*                  GDALCreateSimilarApproxTransformer()                */
 /************************************************************************/
 
-static
-void* GDALCreateSimilarApproxTransformer( void *hTransformArg, double dfSrcRatioX, double dfSrcRatioY )
+static void *
+GDALCreateSimilarApproxTransformer( void *hTransformArg,
+                                    double dfSrcRatioX, double dfSrcRatioY )
 {
-    VALIDATE_POINTER1( hTransformArg, "GDALCreateSimilarApproxTransformer", NULL );
+    VALIDATE_POINTER1( hTransformArg,
+                       "GDALCreateSimilarApproxTransformer", NULL );
 
     ApproxTransformInfo *psInfo =
-        (ApproxTransformInfo *) hTransformArg;
+      static_cast<ApproxTransformInfo *>(hTransformArg);
 
-    ApproxTransformInfo *psClonedInfo =  (ApproxTransformInfo *)
-        CPLMalloc(sizeof(ApproxTransformInfo));
+    ApproxTransformInfo *psClonedInfo = static_cast<ApproxTransformInfo *>(
+        CPLMalloc(sizeof(ApproxTransformInfo)));
 
     memcpy(psClonedInfo, psInfo, sizeof(ApproxTransformInfo));
     if( psClonedInfo->pBaseCBData )
     {
-        psClonedInfo->pBaseCBData = GDALCreateSimilarTransformer( psInfo->pBaseCBData,
-                                                                  dfSrcRatioX,
-                                                                  dfSrcRatioY );
+        psClonedInfo->pBaseCBData =
+            GDALCreateSimilarTransformer( psInfo->pBaseCBData,
+                                          dfSrcRatioX,
+                                          dfSrcRatioY );
         if( psClonedInfo->pBaseCBData == NULL )
         {
             CPLFree(psClonedInfo);
@@ -2547,20 +2592,28 @@ GDALSerializeApproxTransformer( void *pTransformArg )
 /* -------------------------------------------------------------------- */
 /*      Attach max error.                                               */
 /* -------------------------------------------------------------------- */
-    CPLCreateXMLElementAndValue( psTree, "MaxError",
-                                 CPLString().Printf("%g",psInfo->dfMaxError) );
+    if( psInfo->dfMaxErrorForward == psInfo->dfMaxErrorReverse )
+    {
+        CPLCreateXMLElementAndValue( psTree, "MaxError",
+                        CPLString().Printf("%g", psInfo->dfMaxErrorForward) );
+    }
+    else
+    {
+        CPLCreateXMLElementAndValue( psTree, "MaxErrorForward",
+                        CPLString().Printf("%g", psInfo->dfMaxErrorForward) );
+        CPLCreateXMLElementAndValue( psTree, "MaxErrorReverse",
+                        CPLString().Printf("%g", psInfo->dfMaxErrorReverse) );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Capture underlying transformer.                                 */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psTransformerContainer;
-    CPLXMLNode *psTransformer;
-
-    psTransformerContainer =
+    CPLXMLNode *psTransformerContainer =
         CPLCreateXMLNode( psTree, CXT_Element, "BaseTransformer" );
 
-    psTransformer = GDALSerializeTransformer( psInfo->pfnBaseTransformer,
-                                              psInfo->pBaseCBData );
+    CPLXMLNode *psTransformer =
+        GDALSerializeTransformer( psInfo->pfnBaseTransformer,
+                                  psInfo->pBaseCBData );
     if( psTransformer != NULL )
         CPLAddXMLChild( psTransformerContainer, psTransformer );
 
@@ -2613,15 +2666,31 @@ void *GDALCreateApproxTransformer( GDALTransformerFunc pfnBaseTransformer,
                                    void *pBaseTransformArg, double dfMaxError)
 
 {
-    ApproxTransformInfo	*psATInfo;
+    return GDALCreateApproxTransformer2(pfnBaseTransformer,
+                                        pBaseTransformArg,
+                                        dfMaxError,
+                                        dfMaxError);
+}
+
+
+static
+void *GDALCreateApproxTransformer2( GDALTransformerFunc pfnBaseTransformer,
+                                    void *pBaseTransformArg,
+                                    double dfMaxErrorForward,
+                                    double dfMaxErrorReverse)
 
-    psATInfo = (ApproxTransformInfo*) CPLMalloc(sizeof(ApproxTransformInfo));
+{
+    ApproxTransformInfo *psATInfo = static_cast<ApproxTransformInfo *>(
+        CPLMalloc(sizeof(ApproxTransformInfo)));
     psATInfo->pfnBaseTransformer = pfnBaseTransformer;
     psATInfo->pBaseCBData = pBaseTransformArg;
-    psATInfo->dfMaxError = dfMaxError;
+    psATInfo->dfMaxErrorForward = dfMaxErrorForward;
+    psATInfo->dfMaxErrorReverse = dfMaxErrorReverse;
     psATInfo->bOwnSubtransformer = FALSE;
 
-    memcpy( psATInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
+    memcpy(psATInfo->sTI.abySignature,
+           GDAL_GTI2_SIGNATURE,
+           strlen(GDAL_GTI2_SIGNATURE));
     psATInfo->sTI.pszClassName = "GDALApproxTransformer";
     psATInfo->sTI.pfnTransform = GDALApproxTransform;
     psATInfo->sTI.pfnCleanup = GDALDestroyApproxTransformer;
@@ -2635,10 +2704,11 @@ void *GDALCreateApproxTransformer( GDALTransformerFunc pfnBaseTransformer,
 /*              GDALApproxTransformerOwnsSubtransformer()               */
 /************************************************************************/
 
+/** Set bOwnSubtransformer flag */
 void GDALApproxTransformerOwnsSubtransformer( void *pCBData, int bOwnFlag )
 
 {
-    ApproxTransformInfo	*psATInfo = (ApproxTransformInfo *) pCBData;
+    ApproxTransformInfo *psATInfo = static_cast<ApproxTransformInfo *>(pCBData);
 
     psATInfo->bOwnSubtransformer = bOwnFlag;
 }
@@ -2662,7 +2732,7 @@ void GDALDestroyApproxTransformer( void * pCBData )
     if( pCBData == NULL)
         return;
 
-    ApproxTransformInfo	*psATInfo = (ApproxTransformInfo *) pCBData;
+    ApproxTransformInfo *psATInfo = static_cast<ApproxTransformInfo *>(pCBData);
 
     if( psATInfo->bOwnSubtransformer )
         GDALDestroyTransformer( psATInfo->pBaseCBData );
@@ -2674,31 +2744,26 @@ void GDALDestroyApproxTransformer( void * pCBData )
 /*                      GDALApproxTransformInternal()                   */
 /************************************************************************/
 
-static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoints,
-                                        double *x, double *y, double *z, int *panSuccess,
-                                        const double xSMETransformed[3], /* SME = Start, Middle, End */
+static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc,
+                                        int nPoints,
+                                        double *x, double *y, double *z,
+                                        int *panSuccess,
+                                        // SME = Start, Middle, End.
+                                        const double xSMETransformed[3],
                                         const double ySMETransformed[3],
-                                        const double zSMETransformed[3])
+                                        const double zSMETransformed[3] )
 {
-    ApproxTransformInfo *psATInfo = (ApproxTransformInfo *) pCBData;
-    double dfDeltaX, dfDeltaY, dfError, dfDist, dfDeltaZ;
-    int nMiddle, i, bSuccess;
+    ApproxTransformInfo *psATInfo = static_cast<ApproxTransformInfo *>(pCBData);
+    int bSuccess = FALSE;  // TODO(schwehr): Split into each case.
 
-    nMiddle = (nPoints-1)/2;
+    const int nMiddle = (nPoints - 1) / 2;
 
 #ifdef notdef_sanify_check
     {
-        double x2[3], y2[3], z2[3];
-        int anSuccess2[3];
-        x2[0] = x[0];
-        y2[0] = y[0];
-        z2[0] = z[0];
-        x2[1] = x[nMiddle];
-        y2[1] = y[nMiddle];
-        z2[1] = z[nMiddle];
-        x2[2] = x[nPoints-1];
-        y2[2] = y[nPoints-1];
-        z2[2] = z[nPoints-1];
+        double x2[3] = { x[0], x[nMiddle], x[nPoints-1] };
+        double y2[3] = { y[0], y[nMiddle], y[nPoints-1] };
+        double z2[3] = { z[0], z[nMiddle], z[nPoints-1] };
+        int anSuccess2[3] = {};
 
         bSuccess =
             psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 3,
@@ -2720,11 +2785,11 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
 #endif
 
 #ifdef DEBUG_APPROX_TRANSFORMER
-    fprintf(stderr, "start (%.3f,%.3f) -> (%.3f,%.3f)\n",
+    fprintf(stderr, "start (%.3f,%.3f) -> (%.3f,%.3f)\n",/*ok*/
             x[0], y[0], xSMETransformed[0], ySMETransformed[0]);
-    fprintf(stderr, "middle (%.3f,%.3f) -> (%.3f,%.3f)\n",
+    fprintf(stderr, "middle (%.3f,%.3f) -> (%.3f,%.3f)\n",/*ok*/
             x[nMiddle], y[nMiddle], xSMETransformed[1], ySMETransformed[1]);
-    fprintf(stderr, "end (%.3f,%.3f) -> (%.3f,%.3f)\n",
+    fprintf(stderr, "end (%.3f,%.3f) -> (%.3f,%.3f)\n",/*ok*/
             x[nPoints-1], y[nPoints-1], xSMETransformed[2], ySMETransformed[2]);
 #endif
 
@@ -2732,78 +2797,105 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
 /*      Is the error at the middle acceptable relative to an            */
 /*      interpolation of the middle position?                           */
 /* -------------------------------------------------------------------- */
-    dfDeltaX = (xSMETransformed[2] - xSMETransformed[0]) / (x[nPoints-1] - x[0]);
-    dfDeltaY = (ySMETransformed[2] - ySMETransformed[0]) / (x[nPoints-1] - x[0]);
-    dfDeltaZ = (zSMETransformed[2] - zSMETransformed[0]) / (x[nPoints-1] - x[0]);
+    const double dfDeltaX =
+        (xSMETransformed[2] - xSMETransformed[0]) / (x[nPoints-1] - x[0]);
+    const double dfDeltaY =
+        (ySMETransformed[2] - ySMETransformed[0]) / (x[nPoints-1] - x[0]);
+    const double dfDeltaZ =
+        (zSMETransformed[2] - zSMETransformed[0]) / (x[nPoints-1] - x[0]);
 
-    dfError = fabs((xSMETransformed[0] + dfDeltaX * (x[nMiddle] - x[0])) - xSMETransformed[1])
-            + fabs((ySMETransformed[0] + dfDeltaY * (x[nMiddle] - x[0])) - ySMETransformed[1]);
+    const double dfError =
+        fabs((xSMETransformed[0] + dfDeltaX * (x[nMiddle] - x[0])) -
+             xSMETransformed[1]) +
+        fabs((ySMETransformed[0] + dfDeltaY * (x[nMiddle] - x[0])) -
+             ySMETransformed[1]);
 
-    if( dfError > psATInfo->dfMaxError )
+    const double dfMaxError = (bDstToSrc) ? psATInfo->dfMaxErrorReverse :
+                                            psATInfo->dfMaxErrorForward;
+    if( dfError > dfMaxError )
     {
-#ifdef notdef
+#if DEBUG_VERBOSE
         CPLDebug( "GDAL", "ApproxTransformer - "
                   "error %g over threshold %g, subdivide %d points.",
-                  dfError, psATInfo->dfMaxError, nPoints );
+                  dfError, dfMaxError, nPoints );
 #endif
 
-        double xMiddle[3], yMiddle[3], zMiddle[3];
-        int  anSuccess2[3];
-        xMiddle[0] = x[ (nMiddle - 1) / 2 ];
-        yMiddle[0] = y[ (nMiddle - 1) / 2 ];
-        zMiddle[0] = z[ (nMiddle - 1) / 2 ];
-        xMiddle[1] = x[ nMiddle - 1 ];
-        yMiddle[1] = y[ nMiddle - 1 ];
-        zMiddle[1] = z[ nMiddle - 1 ];
-        xMiddle[2] = x[ nMiddle + (nPoints - nMiddle - 1) / 2 ];
-        yMiddle[2] = y[ nMiddle + (nPoints - nMiddle - 1) / 2 ];
-        zMiddle[2] = z[ nMiddle + (nPoints - nMiddle - 1) / 2 ];
-
-        int bUseBaseTransformForHalf1 = ( nMiddle <= 5 ||
-                                y[0] != y[nMiddle-1] ||
-                                y[0] != y[(nMiddle - 1) / 2] ||
-                                x[0] == x[nMiddle-1] ||
-                                x[0] == x[(nMiddle - 1) / 2]  );
-        int bUseBaseTransformForHalf2 = ( nPoints - nMiddle <= 5 ||
-                                 y[nMiddle] != y[nPoints-1] ||
-                                 y[nMiddle] != y[nMiddle + (nPoints - nMiddle - 1) / 2] ||
-                                 x[nMiddle] == x[nPoints-1] ||
-                                 x[nMiddle] == x[nMiddle + (nPoints - nMiddle - 1) / 2] );
-
+        double xMiddle[3] = {
+            x[(nMiddle - 1) / 2],
+            x[nMiddle - 1],
+            x[nMiddle + (nPoints - nMiddle - 1) / 2]
+        };
+        double yMiddle[3] = {
+            y[(nMiddle - 1) / 2],
+            y[nMiddle - 1],
+            y[nMiddle + (nPoints - nMiddle - 1) / 2]
+        };
+        double zMiddle[3] = {
+            z[(nMiddle - 1) / 2],
+            z[nMiddle - 1 ],
+            z[nMiddle + (nPoints - nMiddle - 1) / 2]
+        };
+
+        const bool bUseBaseTransformForHalf1 =
+            nMiddle <= 5 ||
+            y[0] != y[nMiddle-1] ||
+            y[0] != y[(nMiddle - 1) / 2] ||
+            x[0] == x[nMiddle-1] ||
+            x[0] == x[(nMiddle - 1) / 2];
+        const bool bUseBaseTransformForHalf2 =
+            nPoints - nMiddle <= 5 ||
+            y[nMiddle] != y[nPoints-1] ||
+            y[nMiddle] != y[nMiddle + (nPoints - nMiddle - 1) / 2] ||
+            x[nMiddle] == x[nPoints-1] ||
+            x[nMiddle] == x[nMiddle + (nPoints - nMiddle - 1) / 2];
+
+        int anSuccess2[3] = {};
         if( !bUseBaseTransformForHalf1 && !bUseBaseTransformForHalf2 )
             bSuccess =
-                psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 3,
-                                             xMiddle, yMiddle, zMiddle, anSuccess2 );
+                psATInfo->pfnBaseTransformer(psATInfo->pBaseCBData,
+                                             bDstToSrc, 3,
+                                             xMiddle, yMiddle, zMiddle,
+                                             anSuccess2 );
         else if( !bUseBaseTransformForHalf1 )
         {
             bSuccess =
-                psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 2,
-                                             xMiddle, yMiddle, zMiddle, anSuccess2 );
+                psATInfo->pfnBaseTransformer(psATInfo->pBaseCBData,
+                                             bDstToSrc, 2,
+                                             xMiddle, yMiddle, zMiddle,
+                                             anSuccess2 );
             anSuccess2[2] = TRUE;
         }
         else if( !bUseBaseTransformForHalf2 )
         {
             bSuccess =
-                psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc, 1,
-                                              xMiddle + 2, yMiddle + 2, zMiddle + 2,
-                                              anSuccess2 + 2 );
+                psATInfo->pfnBaseTransformer(psATInfo->pBaseCBData,
+                                             bDstToSrc, 1,
+                                             xMiddle + 2,
+                                             yMiddle + 2,
+                                             zMiddle + 2,
+                                             anSuccess2 + 2 );
             anSuccess2[0] = TRUE;
             anSuccess2[1] = TRUE;
         }
         else
+        {
             bSuccess = FALSE;
+        }
+
         if( !bSuccess || !anSuccess2[0] || !anSuccess2[1] || !anSuccess2[2] )
         {
-            bSuccess = psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc,
-                                                     nMiddle - 1,
-                                                     x + 1, y + 1, z + 1,
-                                                     panSuccess + 1 );
-            bSuccess &= psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc,
-                                                      nPoints - nMiddle - 2,
-                                                      x + nMiddle + 1,
-                                                      y + nMiddle + 1,
-                                                      z + nMiddle + 1,
-                                                      panSuccess + nMiddle + 1 );
+            bSuccess = psATInfo->pfnBaseTransformer(psATInfo->pBaseCBData,
+                                                    bDstToSrc,
+                                                    nMiddle - 1,
+                                                    x + 1, y + 1, z + 1,
+                                                    panSuccess + 1);
+            bSuccess &= psATInfo->pfnBaseTransformer(psATInfo->pBaseCBData,
+                                                     bDstToSrc,
+                                                     nPoints - nMiddle - 2,
+                                                     x + nMiddle + 1,
+                                                     y + nMiddle + 1,
+                                                     z + nMiddle + 1,
+                                                     panSuccess + nMiddle + 1);
 
             x[0] = xSMETransformed[0];
             y[0] = ySMETransformed[0];
@@ -2820,7 +2912,9 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
             return bSuccess;
         }
 
-        double x2[3], y2[3], z2[3];
+        double x2[3] = {};
+        double y2[3] = {};
+        double z2[3] = {};
         if( !bUseBaseTransformForHalf1 )
         {
             x2[0] = xSMETransformed[0];
@@ -2837,13 +2931,14 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
                 GDALApproxTransformInternal( psATInfo, bDstToSrc, nMiddle,
                                             x, y, z, panSuccess,
                                             x2, y2, z2);
-
         }
         else
         {
-            bSuccess = psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc,
-                                                     nMiddle - 1, x + 1, y + 1, z + 1,
-                                                     panSuccess + 1 );
+            bSuccess = psATInfo->pfnBaseTransformer(psATInfo->pBaseCBData,
+                                                    bDstToSrc,
+                                                    nMiddle - 1,
+                                                    x + 1, y + 1, z + 1,
+                                                    panSuccess + 1 );
             x[0] = xSMETransformed[0];
             y[0] = ySMETransformed[0];
             z[0] = zSMETransformed[0];
@@ -2866,17 +2961,21 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
             z2[2] = zSMETransformed[2];
 
             bSuccess =
-                GDALApproxTransformInternal( psATInfo, bDstToSrc, nPoints - nMiddle,
+                GDALApproxTransformInternal(psATInfo, bDstToSrc,
+                                            nPoints - nMiddle,
                                             x+nMiddle, y+nMiddle, z+nMiddle,
                                             panSuccess+nMiddle,
                                             x2, y2, z2);
         }
         else
         {
-            bSuccess = psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc,
-                                                     nPoints - nMiddle - 2,
-                                                     x+nMiddle + 1, y+nMiddle+1, z+nMiddle+1,
-                                                     panSuccess+nMiddle+1 );
+            bSuccess = psATInfo->pfnBaseTransformer(psATInfo->pBaseCBData,
+                                                    bDstToSrc,
+                                                    nPoints - nMiddle - 2,
+                                                    x + nMiddle + 1,
+                                                    y + nMiddle + 1,
+                                                    z + nMiddle + 1,
+                                                    panSuccess+nMiddle+1 );
 
             x[nMiddle] = xSMETransformed[1];
             y[nMiddle] = ySMETransformed[1];
@@ -2903,24 +3002,27 @@ static int GDALApproxTransformInternal( void *pCBData, int bDstToSrc, int nPoint
 /*      NOTE: the above comment is not true: gdalwarp uses approximator */
 /*      also to compute the source pixel of each target pixel.          */
 /* -------------------------------------------------------------------- */
-    for( i = nPoints-1; i >= 0; i-- )
+    for( int i = nPoints-1; i >= 0; i-- )
     {
 #ifdef check_error
-        double xtemp = x[i], ytemp = y[i], ztemp = z[i];
-        double x_ori = xtemp, y_ori = ytemp;
-        int btemp;
+        double xtemp = x[i];
+        double ytemp = y[i];
+        double ztemp = z[i];
+        double x_ori = xtemp;
+        double y_ori = ytemp;
+        int btemp = FALSE;
         psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc,
                                       1, &xtemp, &ytemp, &ztemp, &btemp);
 #endif
-        dfDist = (x[i] - x[0]);
+        const double dfDist = (x[i] - x[0]);
         x[i] = xSMETransformed[0] + dfDeltaX * dfDist;
         y[i] = ySMETransformed[0] + dfDeltaY * dfDist;
         z[i] = zSMETransformed[0] + dfDeltaZ * dfDist;
 #ifdef check_error
-        dfError = fabs(x[i] - xtemp) + fabs(y[i] - ytemp);
-        if( dfError > 4 /*10 * psATInfo->dfMaxError*/ )
+        const double dfError2 = fabs(x[i] - xtemp) + fabs(y[i] - ytemp);
+        if( dfError2 > 4 /*10 * dfMaxError*/ )
         {
-            printf("Error = %f on (%f, %f)\n", dfError,  x_ori, y_ori);
+            /*ok*/printf("Error = %f on (%f, %f)\n", dfError2,  x_ori, y_ori);
         }
 #endif
         panSuccess[i] = TRUE;
@@ -2946,11 +3048,14 @@ int GDALApproxTransform( void *pCBData, int bDstToSrc, int nPoints,
                          double *x, double *y, double *z, int *panSuccess )
 
 {
-    ApproxTransformInfo *psATInfo = (ApproxTransformInfo *) pCBData;
-    double x2[3], y2[3], z2[3];
-    int anSuccess2[3], bSuccess;
+    ApproxTransformInfo *psATInfo = static_cast<ApproxTransformInfo *>(pCBData);
+    double x2[3] = {};
+    double y2[3] = {};
+    double z2[3] = {};
+    int anSuccess2[3] = {};
+    int bSuccess;
 
-    int nMiddle = (nPoints-1)/2;
+    const int nMiddle = (nPoints - 1) / 2;
 
 /* -------------------------------------------------------------------- */
 /*      Bail if our preconditions are not met, or if error is not       */
@@ -2959,7 +3064,8 @@ int GDALApproxTransform( void *pCBData, int bDstToSrc, int nPoints,
     int bRet = FALSE;
     if( y[0] != y[nPoints-1] || y[0] != y[nMiddle]
         || x[0] == x[nPoints-1] || x[0] == x[nMiddle]
-        || psATInfo->dfMaxError == 0.0 || nPoints <= 5 )
+        || (psATInfo->dfMaxErrorForward == 0.0 &&
+            psATInfo->dfMaxErrorReverse == 0.0) || nPoints <= 5 )
     {
         bRet = psATInfo->pfnBaseTransformer( psATInfo->pBaseCBData, bDstToSrc,
                                              nPoints, x, y, z, panSuccess );
@@ -2997,8 +3103,9 @@ int GDALApproxTransform( void *pCBData, int bDstToSrc, int nPoints,
 
 end:
 #ifdef DEBUG_APPROX_TRANSFORMER
-    for(int i=0;i<nPoints;i++ )
-        fprintf(stderr, "[%d] (%.10f,%.10f) %d\n", i, x[i], y[i], panSuccess[i]);
+    for( int i = 0; i < nPoints; i++ )
+        fprintf(stderr, "[%d] (%.10f,%.10f) %d\n",/*ok*/
+                i, x[i], y[i], panSuccess[i]);
 #endif
 
     return bRet;
@@ -3012,7 +3119,27 @@ static void *
 GDALDeserializeApproxTransformer( CPLXMLNode *psTree )
 
 {
-    double dfMaxError = CPLAtof(CPLGetXMLValue( psTree, "MaxError",  "0.25" ));
+    double dfMaxErrorForward = 0.25;
+    double dfMaxErrorReverse = 0.25;
+    const char* pszMaxError = CPLGetXMLValue( psTree, "MaxError", NULL);
+    if( pszMaxError != NULL )
+    {
+        dfMaxErrorForward = CPLAtof(pszMaxError);
+        dfMaxErrorReverse = dfMaxErrorForward;
+    }
+    const char* pszMaxErrorForward =
+                    CPLGetXMLValue( psTree, "MaxErrorForward", NULL);
+    if( pszMaxErrorForward != NULL )
+    {
+        dfMaxErrorForward = CPLAtof(pszMaxErrorForward);
+    }
+    const char* pszMaxErrorReverse =
+                    CPLGetXMLValue( psTree, "MaxErrorReverse", NULL);
+    if( pszMaxErrorForward != NULL )
+    {
+        dfMaxErrorReverse = CPLAtof(pszMaxErrorReverse);
+    }
+
     GDALTransformerFunc pfnBaseTransform = NULL;
     void *pBaseCBData = NULL;
 
@@ -3031,15 +3158,14 @@ GDALDeserializeApproxTransformer( CPLXMLNode *psTree )
                   "Cannot get base transform for approx transformer." );
         return NULL;
     }
-    else
-    {
-        void *pApproxCBData = GDALCreateApproxTransformer( pfnBaseTransform,
-                                                           pBaseCBData,
-                                                           dfMaxError );
-        GDALApproxTransformerOwnsSubtransformer( pApproxCBData, TRUE );
 
-        return pApproxCBData;
-    }
+    void *pApproxCBData = GDALCreateApproxTransformer2( pfnBaseTransform,
+                                                        pBaseCBData,
+                                                        dfMaxErrorForward,
+                                                        dfMaxErrorReverse );
+    GDALApproxTransformerOwnsSubtransformer( pApproxCBData, TRUE );
+
+    return pApproxCBData;
 }
 
 /************************************************************************/
@@ -3049,8 +3175,8 @@ GDALDeserializeApproxTransformer( CPLXMLNode *psTree )
 /**
  * Apply GeoTransform to x/y coordinate.
  *
- * Applies the following computation, converting a (pixel,line) coordinate
- * into a georeferenced (geo_x,geo_y) location.
+ * Applies the following computation, converting a (pixel, line) coordinate
+ * into a georeferenced (geo_x, geo_y) location.
  *
  *  *pdfGeoX = padfGeoTransform[0] + dfPixel * padfGeoTransform[1]
  *                                 + dfLine  * padfGeoTransform[2];
@@ -3060,8 +3186,10 @@ GDALDeserializeApproxTransformer( CPLXMLNode *psTree )
  * @param padfGeoTransform Six coefficient GeoTransform to apply.
  * @param dfPixel Input pixel position.
  * @param dfLine Input line position.
- * @param pdfGeoX output location where geo_x (easting/longitude) location is placed.
- * @param pdfGeoY output location where geo_y (northing/latitude) location is placed.
+ * @param pdfGeoX output location where geo_x (easting/longitude)
+ * location is placed.
+ * @param pdfGeoY output location where geo_y (northing/latitude)
+ * location is placed.
  */
 
 void CPL_STDCALL GDALApplyGeoTransform( double *padfGeoTransform,
@@ -3093,8 +3221,8 @@ void CPL_STDCALL GDALApplyGeoTransform( double *padfGeoTransform,
 int CPL_STDCALL GDALInvGeoTransform( double *gt_in, double *gt_out )
 
 {
-    /* Special case - no rotation - to avoid computing determinate */
-    /* and potential precision issues. */
+    // Special case - no rotation - to avoid computing determinate
+    // and potential precision issues.
     if( gt_in[2] == 0.0 && gt_in[4] == 0.0 &&
         gt_in[1] != 0.0 && gt_in[5] != 0.0 )
     {
@@ -3113,9 +3241,9 @@ int CPL_STDCALL GDALInvGeoTransform( double *gt_in, double *gt_out )
         return 1;
     }
 
-    /* we assume a 3rd row that is [1 0 0] */
+    // Assume a 3rd row that is [1 0 0].
 
-    /* Compute determinate */
+    // Compute determinate.
 
     const double det = gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4];
 
@@ -3124,7 +3252,7 @@ int CPL_STDCALL GDALInvGeoTransform( double *gt_in, double *gt_out )
 
     const double inv_det = 1.0 / det;
 
-    /* compute adjoint, and divide by determinate */
+    // Compute adjoint, and divide by determinate.
 
     gt_out[1] =  gt_in[5] * inv_det;
     gt_out[4] = -gt_in[4] * inv_det;
@@ -3142,30 +3270,31 @@ int CPL_STDCALL GDALInvGeoTransform( double *gt_in, double *gt_out )
 /*                      GDALSerializeTransformer()                      */
 /************************************************************************/
 
-CPLXMLNode *GDALSerializeTransformer( CPL_UNUSED GDALTransformerFunc pfnFunc,
+CPLXMLNode *GDALSerializeTransformer( GDALTransformerFunc /* pfnFunc */,
                                       void *pTransformArg )
 {
     VALIDATE_POINTER1( pTransformArg, "GDALSerializeTransformer", NULL );
 
-    GDALTransformerInfo *psInfo = static_cast<GDALTransformerInfo *>(pTransformArg);
+    GDALTransformerInfo *psInfo =
+        static_cast<GDALTransformerInfo *>(pTransformArg);
 
     if( psInfo == NULL ||
-        memcmp(psInfo->abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE)) != 0 )
+        memcmp(psInfo->abySignature,
+               GDAL_GTI2_SIGNATURE,
+               strlen(GDAL_GTI2_SIGNATURE)) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to serialize non-GTI2 transformer." );
         return NULL;
     }
-    else if ( psInfo->pfnSerialize == NULL )
+    else if( psInfo->pfnSerialize == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "No serialization function available for this transformer." );
         return NULL;
     }
-    else
-    {
-        return psInfo->pfnSerialize( pTransformArg );
-    }
+
+    return psInfo->pfnSerialize( pTransformArg );
 }
 
 /************************************************************************/
@@ -3182,12 +3311,15 @@ typedef struct
     GDALTransformDeserializeFunc pfnDeserializeFunc;
 } TransformDeserializerInfo;
 
-void* GDALRegisterTransformDeserializer(const char* pszTransformName,
-                                       GDALTransformerFunc pfnTransformerFunc,
-                                       GDALTransformDeserializeFunc pfnDeserializeFunc)
+void *
+GDALRegisterTransformDeserializer(
+    const char* pszTransformName,
+    GDALTransformerFunc pfnTransformerFunc,
+    GDALTransformDeserializeFunc pfnDeserializeFunc )
 {
     TransformDeserializerInfo* psInfo =
-        (TransformDeserializerInfo*)CPLMalloc(sizeof(TransformDeserializerInfo));
+        static_cast<TransformDeserializerInfo *>(
+            CPLMalloc(sizeof(TransformDeserializerInfo)));
     psInfo->pszTransformName = CPLStrdup(pszTransformName);
     psInfo->pfnTransformerFunc = pfnTransformerFunc;
     psInfo->pfnDeserializeFunc = pfnDeserializeFunc;
@@ -3202,20 +3334,20 @@ void* GDALRegisterTransformDeserializer(const char* pszTransformName,
 /*                GDALUnregisterTransformDeserializer()                 */
 /************************************************************************/
 
-void GDALUnregisterTransformDeserializer(void* pData)
+void GDALUnregisterTransformDeserializer( void* pData )
 {
     CPLMutexHolderD(&hDeserializerMutex);
     CPLList* psList = psListDeserializer;
     CPLList* psLast = NULL;
-    while(psList)
+    while( psList )
     {
-        if (psList->pData == pData)
+        if( psList->pData == pData )
         {
             TransformDeserializerInfo* psInfo =
-                    (TransformDeserializerInfo*)pData;
+                static_cast<TransformDeserializerInfo *>(pData);
             CPLFree(psInfo->pszTransformName);
             CPLFree(pData);
-            if (psLast)
+            if( psLast )
                 psLast->psNext = psList->psNext;
             else
                 psListDeserializer = NULL;
@@ -3257,37 +3389,37 @@ CPLErr GDALDeserializeTransformer( CPLXMLNode *psTree,
     if( psTree == NULL || psTree->eType != CXT_Element )
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Malformed element in GDALDeserializeTransformer" );
-    else if( EQUAL(psTree->pszValue,"GenImgProjTransformer") )
+    else if( EQUAL(psTree->pszValue, "GenImgProjTransformer") )
     {
         *ppfnFunc = GDALGenImgProjTransform;
         *ppTransformArg = GDALDeserializeGenImgProjTransformer( psTree );
     }
-    else if( EQUAL(psTree->pszValue,"ReprojectionTransformer") )
+    else if( EQUAL(psTree->pszValue, "ReprojectionTransformer") )
     {
         *ppfnFunc = GDALReprojectionTransform;
         *ppTransformArg = GDALDeserializeReprojectionTransformer( psTree );
     }
-    else if( EQUAL(psTree->pszValue,"GCPTransformer") )
+    else if( EQUAL(psTree->pszValue, "GCPTransformer") )
     {
         *ppfnFunc = GDALGCPTransform;
         *ppTransformArg = GDALDeserializeGCPTransformer( psTree );
     }
-    else if( EQUAL(psTree->pszValue,"TPSTransformer") )
+    else if( EQUAL(psTree->pszValue, "TPSTransformer") )
     {
         *ppfnFunc = GDALTPSTransform;
         *ppTransformArg = GDALDeserializeTPSTransformer( psTree );
     }
-    else if( EQUAL(psTree->pszValue,"GeoLocTransformer") )
+    else if( EQUAL(psTree->pszValue, "GeoLocTransformer") )
     {
         *ppfnFunc = GDALGeoLocTransform;
         *ppTransformArg = GDALDeserializeGeoLocTransformer( psTree );
     }
-    else if( EQUAL(psTree->pszValue,"RPCTransformer") )
+    else if( EQUAL(psTree->pszValue, "RPCTransformer") )
     {
         *ppfnFunc = GDALRPCTransform;
         *ppTransformArg = GDALDeserializeRPCTransformer( psTree );
     }
-    else if( EQUAL(psTree->pszValue,"ApproxTransformer") )
+    else if( EQUAL(psTree->pszValue, "ApproxTransformer") )
     {
         *ppfnFunc = GDALApproxTransform;
         *ppTransformArg = GDALDeserializeApproxTransformer( psTree );
@@ -3298,11 +3430,11 @@ CPLErr GDALDeserializeTransformer( CPLXMLNode *psTree,
         {
             CPLMutexHolderD(&hDeserializerMutex);
             CPLList* psList = psListDeserializer;
-            while(psList)
+            while( psList )
             {
                 TransformDeserializerInfo* psInfo =
                             (TransformDeserializerInfo*)psList->pData;
-                if (strcmp(psInfo->pszTransformName, psTree->pszValue) == 0)
+                if( strcmp(psInfo->pszTransformName, psTree->pszValue) == 0 )
                 {
                     *ppfnFunc = psInfo->pfnTransformerFunc;
                     pfnDeserializeFunc = psInfo->pfnDeserializeFunc;
@@ -3312,7 +3444,7 @@ CPLErr GDALDeserializeTransformer( CPLXMLNode *psTree,
             }
         }
 
-        if (pfnDeserializeFunc != NULL)
+        if( pfnDeserializeFunc != NULL )
         {
             *ppTransformArg = pfnDeserializeFunc( psTree );
         }
@@ -3337,16 +3469,19 @@ void GDALDestroyTransformer( void *pTransformArg )
     if( pTransformArg == NULL )
         return;
 
-    GDALTransformerInfo *psInfo = (GDALTransformerInfo *) pTransformArg;
+    GDALTransformerInfo *psInfo =
+        static_cast<GDALTransformerInfo *>(pTransformArg);
 
-    if( memcmp(psInfo->abySignature,GDAL_GTI2_SIGNATURE,
-        strlen(GDAL_GTI2_SIGNATURE)) != 0 )
+    if( memcmp(psInfo->abySignature,
+               GDAL_GTI2_SIGNATURE,
+               strlen(GDAL_GTI2_SIGNATURE)) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to destroy non-GTI2 transformer." );
+        return;
     }
-    else
-        psInfo->pfnCleanup( pTransformArg );
+
+    psInfo->pfnCleanup( pTransformArg );
 }
 
 /************************************************************************/
@@ -3358,18 +3493,21 @@ int GDALUseTransformer( void *pTransformArg,
                         double *x, double *y, double *z,
                         int *panSuccess )
 {
-    GDALTransformerInfo *psInfo = (GDALTransformerInfo *) pTransformArg;
+    GDALTransformerInfo *psInfo =
+        static_cast<GDALTransformerInfo *>(pTransformArg);
 
     if( psInfo == NULL ||
-        memcmp(psInfo->abySignature,GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE)) != 0 )
+        memcmp(psInfo->abySignature,
+               GDAL_GTI2_SIGNATURE,
+               strlen(GDAL_GTI2_SIGNATURE)) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to use non-GTI2 transformer." );
         return FALSE;
     }
-    else
-        return psInfo->pfnTransform( pTransformArg, bDstToSrc, nPointCount,
-                                     x, y, z, panSuccess );
+
+    return psInfo->pfnTransform(pTransformArg, bDstToSrc, nPointCount,
+                                x, y, z, panSuccess);
 }
 
 /************************************************************************/
@@ -3380,10 +3518,13 @@ void *GDALCloneTransformer( void *pTransformArg )
 {
     VALIDATE_POINTER1( pTransformArg, "GDALCloneTransformer", NULL );
 
-    GDALTransformerInfo *psInfo = static_cast<GDALTransformerInfo *>(pTransformArg);
+    GDALTransformerInfo *psInfo =
+        static_cast<GDALTransformerInfo *>(pTransformArg);
 
     if( psInfo == NULL ||
-        memcmp(psInfo->abySignature,GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE)) != 0 )
+        memcmp(psInfo->abySignature,
+               GDAL_GTI2_SIGNATURE,
+               strlen(GDAL_GTI2_SIGNATURE)) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to clone non-GTI2 transformer." );
@@ -3395,88 +3536,119 @@ void *GDALCloneTransformer( void *pTransformArg )
         return psInfo->pfnCreateSimilar(psInfo, 1.0, 1.0);
     }
 
-    if ( psInfo->pfnSerialize == NULL )
+    if( psInfo->pfnSerialize == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "No serialization function available for this transformer." );
         return NULL;
     }
-    else
+
+    CPLXMLNode* pSerialized = psInfo->pfnSerialize( pTransformArg );
+    if( pSerialized == NULL )
+        return NULL;
+    GDALTransformerFunc pfnTransformer = NULL;
+    void *pClonedTransformArg = NULL;
+    if( GDALDeserializeTransformer( pSerialized, &pfnTransformer,
+                                    &pClonedTransformArg ) !=
+        CE_None )
     {
-        CPLXMLNode* pSerialized = psInfo->pfnSerialize( pTransformArg );
-        if( pSerialized == NULL )
-            return NULL;
-        GDALTransformerFunc pfnTransformer = NULL;
-        void *pClonedTransformArg = NULL;
-        if( GDALDeserializeTransformer( pSerialized, &pfnTransformer, &pClonedTransformArg ) !=
-            CE_None )
-        {
-            CPLDestroyXMLNode(pSerialized);
-            CPLFree(pClonedTransformArg);
-            return NULL;
-        }
         CPLDestroyXMLNode(pSerialized);
-        return pClonedTransformArg;
+        CPLFree(pClonedTransformArg);
+        return NULL;
     }
+
+    CPLDestroyXMLNode(pSerialized);
+    return pClonedTransformArg;
 }
 
 /************************************************************************/
 /*                   GDALCreateSimilarTransformer()                     */
 /************************************************************************/
 
-void* GDALCreateSimilarTransformer( void* pTransformArg, double dfRatioX, double dfRatioY )
+void* GDALCreateSimilarTransformer( void* pTransformArg,
+                                    double dfRatioX, double dfRatioY )
 {
     VALIDATE_POINTER1( pTransformArg, "GDALCreateSimilarTransformer", NULL );
 
-    GDALTransformerInfo *psInfo = static_cast<GDALTransformerInfo *>(pTransformArg);
+    GDALTransformerInfo *psInfo =
+        static_cast<GDALTransformerInfo *>(pTransformArg);
 
     if( psInfo == NULL ||
-        memcmp(psInfo->abySignature,GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE)) != 0 )
+        memcmp(psInfo->abySignature,
+               GDAL_GTI2_SIGNATURE,
+               strlen(GDAL_GTI2_SIGNATURE)) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to call CreateSimilar on a non-GTI2 transformer." );
         return NULL;
     }
 
-    if( psInfo->pfnCreateSimilar != NULL )
+    if( psInfo->pfnCreateSimilar == NULL )
     {
-        return psInfo->pfnCreateSimilar(psInfo, dfRatioX, dfRatioY);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "No CreateSimilar function available for this transformer.");
+        return NULL;
     }
 
-    CPLError( CE_Failure, CPLE_AppDefined,
-                  "No CreateSimilar function available for this transformer." );
-    return NULL;
+    return psInfo->pfnCreateSimilar(psInfo, dfRatioX, dfRatioY);
 }
 
 /************************************************************************/
 /*                 GDALSetTransformerDstGeoTransform()                  */
 /************************************************************************/
 
-void GDALSetTransformerDstGeoTransform(void *pTransformArg,
-                                       const double *padfGeoTransform )
+/**
+ * Set ApproxTransformer or GenImgProj output geotransform.
+ *
+ * This is a layer above GDALSetGenImgProjTransformerDstGeoTransform() that
+ * checks that the passed hTransformArg is compatible.
+ *
+ * Normally the "destination geotransform", or transformation between
+ * georeferenced output coordinates and pixel/line coordinates on the
+ * destination file is extracted from the destination file by
+ * GDALCreateGenImgProjTransformer() and stored in the GenImgProj private
+ * info.  However, sometimes it is inconvenient to have an output file
+ * handle with appropriate geotransform information when creating the
+ * transformation.  For these cases, this function can be used to apply
+ * the destination geotransform.
+ *
+ * @param pTransformArg the handle to update.
+ * @param padfGeoTransform the destination geotransform to apply (six doubles).
+ */
+
+void GDALSetTransformerDstGeoTransform( void *pTransformArg,
+                                        const double *padfGeoTransform )
 {
     VALIDATE_POINTER0( pTransformArg, "GDALSetTransformerDstGeoTransform" );
 
-    GDALTransformerInfo *psInfo = static_cast<GDALTransformerInfo *>(pTransformArg);
+    GDALTransformerInfo *psInfo =
+        static_cast<GDALTransformerInfo *>(pTransformArg);
 
     if( psInfo == NULL ||
-        memcmp(psInfo->abySignature,GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE)) != 0 )
+        memcmp(psInfo->abySignature,
+               GDAL_GTI2_SIGNATURE,
+               strlen(GDAL_GTI2_SIGNATURE)) != 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to call GDALSetTransformerDstGeoTransform on a non-GTI2 transformer." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Attempt to call GDALSetTransformerDstGeoTransform on "
+                 "a non-GTI2 transformer.");
         return;
     }
 
     if( EQUAL(psInfo->pszClassName, "GDALApproxTransformer") )
     {
-        ApproxTransformInfo   *psATInfo = (ApproxTransformInfo*)pTransformArg;
-        psInfo = (GDALTransformerInfo *)psATInfo->pBaseCBData;
+        ApproxTransformInfo *psATInfo =
+            static_cast<ApproxTransformInfo *>(pTransformArg);
+        psInfo = static_cast<GDALTransformerInfo *>(psATInfo->pBaseCBData);
 
         if( psInfo == NULL ||
-            memcmp(psInfo->abySignature,GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE)) != 0 )
+            memcmp(psInfo->abySignature,
+                   GDAL_GTI2_SIGNATURE,
+                   strlen(GDAL_GTI2_SIGNATURE)) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to call GDALSetTransformerDstGeoTransform on a non-GTI2 transformer." );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Attempt to call GDALSetTransformerDstGeoTransform on "
+                     "a non-GTI2 transformer.");
             return;
         }
     }
diff --git a/alg/gdaltransformgeolocs.cpp b/alg/gdaltransformgeolocs.cpp
index 9294f81..d486282 100644
--- a/alg/gdaltransformgeolocs.cpp
+++ b/alg/gdaltransformgeolocs.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL
  * Purpose:  Algorithm to apply a transformer to geolocation style bands.
@@ -27,11 +26,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_alg.h"
+
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "gdal.h"
 #include "gdal_alg_priv.h"
 #include "gdal_priv.h"
-#include "cpl_conv.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: gdaltransformgeolocs.cpp 36532 2016-11-27 23:13:25Z goatbar $");
 
 /************************************************************************/
 /*                     GDALTransformGeolocations()                      */
@@ -77,11 +84,11 @@ GDALTransformGeolocations( GDALRasterBandH hXBand,
 /* -------------------------------------------------------------------- */
 /*      Ensure the bands are matching in size.                          */
 /* -------------------------------------------------------------------- */
-    GDALRasterBand *poXBand = (GDALRasterBand *) hXBand;
-    GDALRasterBand *poYBand = (GDALRasterBand *) hYBand;
-    GDALRasterBand *poZBand = (GDALRasterBand *) hZBand;
-    int nXSize = poXBand->GetXSize();
-    int nYSize = poXBand->GetYSize();
+    GDALRasterBand *poXBand = reinterpret_cast<GDALRasterBand *>(hXBand);
+    GDALRasterBand *poYBand = reinterpret_cast<GDALRasterBand *>(hYBand);
+    GDALRasterBand *poZBand = reinterpret_cast<GDALRasterBand *>(hZBand);
+    const int nXSize = poXBand->GetXSize();
+    const int nYSize = poXBand->GetYSize();
 
     if( nXSize != poYBand->GetXSize()
         || nYSize != poYBand->GetYSize()
@@ -96,24 +103,25 @@ GDALTransformGeolocations( GDALRasterBandH hXBand,
 /* -------------------------------------------------------------------- */
 /*      Allocate a buffer large enough to hold one whole row.           */
 /* -------------------------------------------------------------------- */
-    double *padfX = (double*) CPLMalloc(sizeof(double) * nXSize);
-    double *padfY = (double*) CPLMalloc(sizeof(double) * nXSize);
-    double *padfZ = (double*) CPLMalloc(sizeof(double) * nXSize);
-    int    *panSuccess = (int*) CPLMalloc(sizeof(int) * nXSize);
-    int iLine;
+    double *padfX = static_cast<double *>(CPLMalloc(sizeof(double) * nXSize));
+    double *padfY = static_cast<double *>(CPLMalloc(sizeof(double) * nXSize));
+    double *padfZ = static_cast<double *>(CPLMalloc(sizeof(double) * nXSize));
+    int *panSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nXSize));
     CPLErr eErr = CE_None;
 
     pfnProgress( 0.0, "", pProgressArg );
-    for( iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
+    for( int iLine = 0; eErr == CE_None && iLine < nYSize; iLine++ )
     {
         eErr = poXBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
                                   padfX, nXSize, 1, GDT_Float64, 0, 0, NULL );
         if( eErr == CE_None )
             eErr = poYBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
-                                      padfY, nXSize, 1, GDT_Float64, 0, 0, NULL );
+                                      padfY, nXSize, 1, GDT_Float64,
+                                      0, 0, NULL );
         if( eErr == CE_None && poZBand != NULL )
             eErr = poZBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
-                                      padfZ, nXSize, 1, GDT_Float64, 0, 0, NULL );
+                                      padfZ, nXSize, 1, GDT_Float64,
+                                      0, 0, NULL );
         else
             memset( padfZ, 0, sizeof(double) * nXSize);
 
@@ -125,16 +133,20 @@ GDALTransformGeolocations( GDALRasterBandH hXBand,
 
         if( eErr == CE_None )
             eErr = poXBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
-                                      padfX, nXSize, 1, GDT_Float64, 0, 0, NULL );
+                                      padfX, nXSize, 1, GDT_Float64,
+                                      0, 0, NULL );
         if( eErr == CE_None )
             eErr = poYBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
-                                      padfY, nXSize, 1, GDT_Float64, 0, 0, NULL );
+                                      padfY, nXSize, 1, GDT_Float64,
+                                      0, 0, NULL );
         if( eErr == CE_None && poZBand != NULL )
             eErr = poZBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
-                                      padfZ, nXSize, 1, GDT_Float64, 0, 0, NULL );
+                                      padfZ, nXSize, 1, GDT_Float64,
+                                      0, 0, NULL );
 
         if( eErr == CE_None )
-            pfnProgress( (iLine+1) / (double) nYSize, "", pProgressArg );
+            pfnProgress( (iLine+1) /
+                         static_cast<double>(nYSize), "", pProgressArg );
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/alg/gdalwarper.cpp b/alg/gdalwarper.cpp
index 6a9206e..46ce3d8 100644
--- a/alg/gdalwarper.cpp
+++ b/alg/gdalwarper.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalwarper.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of high level convenience APIs for warper.
@@ -28,13 +27,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdalwarper.h"
-#include "cpl_string.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <limits>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
-#include "ogr_api.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_priv.h"
+#include "ogr_api.h"
+#include "ogr_core.h"
+
+#if (defined(__x86_64) || defined(_M_X64))
+#include <emmintrin.h>
+#endif
 
-CPL_CVSID("$Id: gdalwarper.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: gdalwarper.cpp 36857 2016-12-14 20:14:32Z goatbar $");
 
 /************************************************************************/
 /*                         GDALReprojectImage()                         */
@@ -86,14 +103,10 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
                     GDALWarpOptions *psOptions )
 
 {
-    GDALWarpOptions *psWOptions;
-
 /* -------------------------------------------------------------------- */
 /*      Setup a reprojection based transformer.                         */
 /* -------------------------------------------------------------------- */
-    void *hTransformArg;
-
-    hTransformArg =
+    void *hTransformArg =
         GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT,
                                          TRUE, 1000.0, 0 );
 
@@ -104,10 +117,10 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 /*      Create a copy of the user provided options, or a defaulted      */
 /*      options structure.                                              */
 /* -------------------------------------------------------------------- */
-    if( psOptions == NULL )
-        psWOptions = GDALCreateWarpOptions();
-    else
-        psWOptions = GDALCloneWarpOptions( psOptions );
+    GDALWarpOptions *psWOptions =
+        psOptions == NULL
+        ? GDALCreateWarpOptions()
+        : GDALCloneWarpOptions( psOptions );
 
     psWOptions->eResampleAlg = eResampleAlg;
 
@@ -131,22 +144,20 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 /* -------------------------------------------------------------------- */
 /*      Set file and band mapping.                                      */
 /* -------------------------------------------------------------------- */
-    int  iBand;
-
     psWOptions->hSrcDS = hSrcDS;
     psWOptions->hDstDS = hDstDS;
 
     if( psWOptions->nBandCount == 0 )
     {
-        psWOptions->nBandCount = MIN(GDALGetRasterCount(hSrcDS),
+        psWOptions->nBandCount = std::min(GDALGetRasterCount(hSrcDS),
                                      GDALGetRasterCount(hDstDS));
 
-        psWOptions->panSrcBands = (int *)
-            CPLMalloc(sizeof(int) * psWOptions->nBandCount);
-        psWOptions->panDstBands = (int *)
-            CPLMalloc(sizeof(int) * psWOptions->nBandCount);
+        psWOptions->panSrcBands = static_cast<int *>(
+            CPLMalloc(sizeof(int) * psWOptions->nBandCount));
+        psWOptions->panDstBands = static_cast<int *>(
+            CPLMalloc(sizeof(int) * psWOptions->nBandCount));
 
-        for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
+        for( int iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
         {
             psWOptions->panSrcBands[iBand] = iBand+1;
             psWOptions->panDstBands[iBand] = iBand+1;
@@ -157,30 +168,27 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 /*      Set source nodata values if the source dataset seems to have    */
 /*      any. Same for target nodata values                              */
 /* -------------------------------------------------------------------- */
-    for( iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
+    for( int iBand = 0; iBand < psWOptions->nBandCount; iBand++ )
     {
         GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, iBand+1 );
-        int             bGotNoData = FALSE;
-        double          dfNoDataValue;
 
         if (GDALGetRasterColorInterpretation(hBand) == GCI_AlphaBand)
         {
             psWOptions->nSrcAlphaBand = iBand + 1;
         }
 
-        dfNoDataValue = GDALGetRasterNoDataValue( hBand, &bGotNoData );
+        int bGotNoData = FALSE;
+        double dfNoDataValue = GDALGetRasterNoDataValue( hBand, &bGotNoData );
         if( bGotNoData )
         {
             if( psWOptions->padfSrcNoDataReal == NULL )
             {
-                int  ii;
-
-                psWOptions->padfSrcNoDataReal = (double *)
-                    CPLMalloc(sizeof(double) * psWOptions->nBandCount);
-                psWOptions->padfSrcNoDataImag = (double *)
-                    CPLMalloc(sizeof(double) * psWOptions->nBandCount);
+                psWOptions->padfSrcNoDataReal = static_cast<double *>(
+                    CPLMalloc(sizeof(double) * psWOptions->nBandCount));
+                psWOptions->padfSrcNoDataImag = static_cast<double *>(
+                    CPLMalloc(sizeof(double) * psWOptions->nBandCount));
 
-                for( ii = 0; ii < psWOptions->nBandCount; ii++ )
+                for( int ii = 0; ii < psWOptions->nBandCount; ii++ )
                 {
                     psWOptions->padfSrcNoDataReal[ii] = -1.1e20;
                     psWOptions->padfSrcNoDataImag[ii] = 0.0;
@@ -190,7 +198,7 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
             psWOptions->padfSrcNoDataReal[iBand] = dfNoDataValue;
         }
 
-        // Deal with target band
+        // Deal with target band.
         hBand = GDALGetRasterBand( hDstDS, iBand+1 );
         if (hBand && GDALGetRasterColorInterpretation(hBand) == GCI_AlphaBand)
         {
@@ -202,14 +210,12 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
         {
             if( psWOptions->padfDstNoDataReal == NULL )
             {
-                int  ii;
+                psWOptions->padfDstNoDataReal = static_cast<double *>(
+                    CPLMalloc(sizeof(double) * psWOptions->nBandCount));
+                psWOptions->padfDstNoDataImag = static_cast<double *>(
+                    CPLMalloc(sizeof(double) * psWOptions->nBandCount));
 
-                psWOptions->padfDstNoDataReal = (double *)
-                    CPLMalloc(sizeof(double) * psWOptions->nBandCount);
-                psWOptions->padfDstNoDataImag = (double *)
-                    CPLMalloc(sizeof(double) * psWOptions->nBandCount);
-
-                for( ii = 0; ii < psWOptions->nBandCount; ii++ )
+                for( int ii = 0; ii < psWOptions->nBandCount; ii++ )
                 {
                     psWOptions->padfDstNoDataReal[ii] = -1.1e20;
                     psWOptions->padfDstNoDataImag[ii] = 0.0;
@@ -232,10 +238,8 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 /* -------------------------------------------------------------------- */
 /*      Create a warp options based on the options.                     */
 /* -------------------------------------------------------------------- */
-    GDALWarpOperation  oWarper;
-    CPLErr eErr;
-
-    eErr = oWarper.Initialize( psWOptions );
+    GDALWarpOperation oWarper;
+    CPLErr eErr = oWarper.Initialize( psWOptions );
 
     if( eErr == CE_None )
         eErr = oWarper.ChunkAndWarpImage( 0, 0,
@@ -261,6 +265,7 @@ GDALReprojectImage( GDALDatasetH hSrcDS, const char *pszSrcWKT,
 /*      This is a "quicky" reprojection API.                            */
 /************************************************************************/
 
+/** Reproject an image and create the target reprojected image */
 CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
     GDALDatasetH hSrcDS, const char *pszSrcWKT,
     const char *pszDstFilename, const char *pszDstWKT,
@@ -296,9 +301,7 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
 /*      Create a transformation object from the source to               */
 /*      destination coordinate system.                                  */
 /* -------------------------------------------------------------------- */
-    void *hTransformArg;
-
-    hTransformArg =
+    void *hTransformArg =
         GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT,
                                          TRUE, 1000.0, 0 );
 
@@ -308,8 +311,9 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
 /* -------------------------------------------------------------------- */
 /*      Get approximate output definition.                              */
 /* -------------------------------------------------------------------- */
-    double adfDstGeoTransform[6];
-    int    nPixels, nLines;
+    double adfDstGeoTransform[6] = {};
+    int nPixels = 0;
+    int nLines = 0;
 
     if( GDALSuggestedWarpOutput( hSrcDS,
                                  GDALGenImgProjTransform, hTransformArg,
@@ -322,12 +326,11 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hDstDS;
-
-    hDstDS = GDALCreate( hDstDriver, pszDstFilename, nPixels, nLines,
-                         GDALGetRasterCount(hSrcDS),
-                         GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1)),
-                         papszCreateOptions );
+    GDALDatasetH hDstDS =
+        GDALCreate( hDstDriver, pszDstFilename, nPixels, nLines,
+                    GDALGetRasterCount(hSrcDS),
+                    GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1)),
+                    papszCreateOptions );
 
     if( hDstDS == NULL )
         return CE_Failure;
@@ -341,9 +344,7 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
 /* -------------------------------------------------------------------- */
 /*      Perform the reprojection.                                       */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr ;
-
-    eErr =
+    CPLErr eErr =
         GDALReprojectImage( hSrcDS, pszSrcWKT, hDstDS, pszDstWKT,
                             eResampleAlg, dfWarpMemoryLimit, dfMaxError,
                             pfnProgress, pProgressArg, psOptions );
@@ -354,6 +355,40 @@ CPLErr CPL_STDCALL GDALCreateAndReprojectImage(
 }
 
 /************************************************************************/
+/*                       GDALWarpNoDataMaskerT()                        */
+/************************************************************************/
+
+template<class T> static CPLErr GDALWarpNoDataMaskerT( const double *padfNoData,
+                                                       size_t nPixels,
+                                                       const T *pData ,
+                                                       GUInt32 *panValidityMask,
+                                                       int* pbOutAllValid )
+{
+    // Nothing to do if value is out of range.
+    if( padfNoData[0] < std::numeric_limits<T>::min() ||
+        padfNoData[0] > std::numeric_limits<T>::max() + 0.000001
+        || padfNoData[1] != 0.0 )
+    {
+        *pbOutAllValid = TRUE;
+        return CE_None;
+    }
+
+    const int nNoData = static_cast<int>(floor(padfNoData[0] + 0.000001));
+    int bAllValid = TRUE;
+    for( size_t iOffset = 0; iOffset < nPixels; ++iOffset )
+    {
+        if( pData[iOffset] == nNoData )
+        {
+            bAllValid = FALSE;
+            panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
+        }
+    }
+    *pbOutAllValid = bAllValid;
+
+    return CE_None;
+}
+
+/************************************************************************/
 /*                        GDALWarpNoDataMasker()                        */
 /*                                                                      */
 /*      GDALMaskFunc for establishing a validity mask for a source      */
@@ -364,112 +399,53 @@ CPLErr
 GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
                       int /* nXOff */, int /* nYOff */, int nXSize, int nYSize,
                       GByte **ppImageData,
-                      int bMaskIsFloat, void *pValidityMask, int* pbOutAllValid )
+                      int bMaskIsFloat, void *pValidityMask,
+                      int* pbOutAllValid )
 
 {
-    double *padfNoData = (double *) pMaskFuncArg;
-    GUInt32 *panValidityMask = (GUInt32 *) pValidityMask;
+    const double *padfNoData = static_cast<double*>(pMaskFuncArg);
+    GUInt32 *panValidityMask = static_cast<GUInt32 *>(pValidityMask);
+    const size_t nPixels = static_cast<size_t>(nXSize) * nYSize;
 
     *pbOutAllValid = FALSE;
 
     if( nBandCount != 1 || bMaskIsFloat )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Invalid nBandCount or bMaskIsFloat argument in SourceNoDataMask" );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Invalid nBandCount or bMaskIsFloat argument in SourceNoDataMask");
         return CE_Failure;
     }
 
     switch( eType )
     {
       case GDT_Byte:
-      {
-          int nNoData = (int) padfNoData[0];
-          GByte *pabyData = (GByte *) *ppImageData;
-          int iOffset;
-
-          // nothing to do if value is out of range.
-          if( padfNoData[0] < 0.0 || padfNoData[0] > 255.000001
-              || padfNoData[1] != 0.0 )
-          {
-              *pbOutAllValid = TRUE;
-              return CE_None;
-          }
-
-          int bAllValid = TRUE;
-          for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
-          {
-              if( pabyData[iOffset] == nNoData )
-              {
-                  bAllValid = FALSE;
-                  panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
-              }
-          }
-          *pbOutAllValid = bAllValid;
-      }
-      break;
+          return
+              GDALWarpNoDataMaskerT(
+                  padfNoData, nPixels,
+                  *ppImageData,  // Already a GByte *.
+                  panValidityMask, pbOutAllValid );
 
       case GDT_Int16:
-      {
-          int nNoData = (int) padfNoData[0];
-          GInt16 *panData = (GInt16 *) *ppImageData;
-          int iOffset;
-
-          // nothing to do if value is out of range.
-          if( padfNoData[0] < -32768 || padfNoData[0] > 32767
-              || padfNoData[1] != 0.0 )
-          {
-              *pbOutAllValid = TRUE;
-              return CE_None;
-          }
-
-          int bAllValid = TRUE;
-          for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
-          {
-              if( panData[iOffset] == nNoData )
-              {
-                  bAllValid = FALSE;
-                  panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
-              }
-          }
-          *pbOutAllValid = bAllValid;
-      }
-      break;
+          return
+              GDALWarpNoDataMaskerT(
+                   padfNoData, nPixels,
+                   reinterpret_cast<GInt16*>(*ppImageData),
+                   panValidityMask, pbOutAllValid );
 
       case GDT_UInt16:
-      {
-          int nNoData = (int) padfNoData[0];
-          GUInt16 *panData = (GUInt16 *) *ppImageData;
-          int iOffset;
-
-          // nothing to do if value is out of range.
-          if( padfNoData[0] < 0 || padfNoData[0] > 65535
-              || padfNoData[1] != 0.0 )
-          {
-              *pbOutAllValid = TRUE;
-              return CE_None;
-          }
-
-          int bAllValid = TRUE;
-          for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
-          {
-              if( panData[iOffset] == nNoData )
-              {
-                  bAllValid = FALSE;
-                  panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
-              }
-          }
-          *pbOutAllValid = bAllValid;
-      }
-      break;
+          return GDALWarpNoDataMaskerT(
+                      padfNoData, nPixels,
+                      reinterpret_cast<GUInt16*>(*ppImageData),
+                      panValidityMask, pbOutAllValid );
 
       case GDT_Float32:
       {
-          float fNoData = (float) padfNoData[0];
-          float *pafData = (float *) *ppImageData;
-          int iOffset;
-          int bIsNoDataNan = CPLIsNan(fNoData);
+          const float fNoData = static_cast<float>(padfNoData[0]);
+          const float *pafData = reinterpret_cast<float *>(*ppImageData);
+          const bool bIsNoDataNan = CPL_TO_BOOL(CPLIsNan(fNoData));
 
-          // nothing to do if value is out of range.
+          // Nothing to do if value is out of range.
           if( padfNoData[1] != 0.0 )
           {
               *pbOutAllValid = TRUE;
@@ -477,10 +453,11 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           }
 
           int bAllValid = TRUE;
-          for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
+          for( size_t iOffset = 0; iOffset < nPixels; ++iOffset )
           {
               float fVal = pafData[iOffset];
-              if( (bIsNoDataNan && CPLIsNan(fVal)) || (!bIsNoDataNan && ARE_REAL_EQUAL(fVal, fNoData)) )
+              if( (bIsNoDataNan && CPLIsNan(fVal)) ||
+                  (!bIsNoDataNan && ARE_REAL_EQUAL(fVal, fNoData)) )
               {
                   bAllValid = FALSE;
                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
@@ -492,12 +469,12 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
 
       case GDT_Float64:
       {
-          double dfNoData = padfNoData[0];
-          double *padfData = (double *) *ppImageData;
-          int iOffset;
-          int bIsNoDataNan = CPLIsNan(dfNoData);
+          const double dfNoData = padfNoData[0];
+          const double *padfData =
+              reinterpret_cast<double *>(*ppImageData);
+          const bool bIsNoDataNan = CPL_TO_BOOL(CPLIsNan(dfNoData));
 
-          // nothing to do if value is out of range.
+          // Nothing to do if value is out of range.
           if( padfNoData[1] != 0.0 )
           {
               *pbOutAllValid = TRUE;
@@ -505,10 +482,11 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
           }
 
           int bAllValid = TRUE;
-          for( iOffset = nXSize*nYSize-1; iOffset >= 0; iOffset-- )
+          for( size_t iOffset = 0; iOffset < nPixels; ++iOffset )
           {
               double dfVal = padfData[iOffset];
-              if( (bIsNoDataNan && CPLIsNan(dfVal)) || (!bIsNoDataNan && ARE_REAL_EQUAL(dfVal, dfNoData)) )
+              if( (bIsNoDataNan && CPLIsNan(dfVal)) ||
+                  (!bIsNoDataNan && ARE_REAL_EQUAL(dfVal, dfNoData)) )
               {
                   bAllValid = FALSE;
                   panValidityMask[iOffset>>5] &= ~(0x01 << (iOffset & 0x1f));
@@ -520,36 +498,38 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
 
       default:
       {
-          double  *padfWrk;
-          int     iLine, iPixel;
           const int nWordSize = GDALGetDataTypeSizeBytes(eType);
 
-          int bIsNoDataRealNan = CPLIsNan(padfNoData[0]);
-          int bIsNoDataImagNan = CPLIsNan(padfNoData[1]);
+          const bool bIsNoDataRealNan = CPL_TO_BOOL(CPLIsNan(padfNoData[0]));
+          const bool bIsNoDataImagNan = CPL_TO_BOOL(CPLIsNan(padfNoData[1]));
 
-          padfWrk = (double *) CPLMalloc(nXSize * sizeof(double) * 2);
+          double *padfWrk = static_cast<double *>(
+              CPLMalloc(nXSize * sizeof(double) * 2));
           int bAllValid = TRUE;
-          for( iLine = 0; iLine < nYSize; iLine++ )
+          for( int iLine = 0; iLine < nYSize; iLine++ )
           {
-              GDALCopyWords( ((GByte *) *ppImageData)+nWordSize*iLine*nXSize,
+              GDALCopyWords( (*ppImageData)+nWordSize*iLine*nXSize,
                              eType, nWordSize,
                              padfWrk, GDT_CFloat64, 16, nXSize );
 
-              for( iPixel = 0; iPixel < nXSize; iPixel++ )
+              for( int iPixel = 0; iPixel < nXSize; ++iPixel )
               {
                   if( ((bIsNoDataRealNan && CPLIsNan(padfWrk[iPixel*2])) ||
-                       (!bIsNoDataRealNan && ARE_REAL_EQUAL(padfWrk[iPixel*2], padfNoData[0])))
+                       (!bIsNoDataRealNan &&
+                         ARE_REAL_EQUAL(padfWrk[iPixel*2], padfNoData[0])))
                       && ((bIsNoDataImagNan && CPLIsNan(padfWrk[iPixel*2+1])) ||
-                          (!bIsNoDataImagNan && ARE_REAL_EQUAL(padfWrk[iPixel*2+1], padfNoData[1]))) )
+                          (!bIsNoDataImagNan &&
+                           ARE_REAL_EQUAL(padfWrk[iPixel*2+1],
+                                          padfNoData[1]))) )
                   {
-                      int iOffset = iPixel + iLine * nXSize;
+                      size_t iOffset =
+                          iPixel + static_cast<size_t>(iLine) * nXSize;
 
                       bAllValid = FALSE;
                       panValidityMask[iOffset>>5] &=
                           ~(0x01 << (iOffset & 0x1f));
                   }
               }
-
           }
           *pbOutAllValid = bAllValid;
 
@@ -571,60 +551,195 @@ GDALWarpNoDataMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
 
 CPLErr
 GDALWarpSrcAlphaMasker( void *pMaskFuncArg,
-                        CPL_UNUSED int nBandCount,
-                        CPL_UNUSED GDALDataType eType,
+                        int /* nBandCount */,
+                        GDALDataType /* eType */,
                         int nXOff, int nYOff, int nXSize, int nYSize,
                         GByte ** /*ppImageData */,
                         int bMaskIsFloat, void *pValidityMask,
                         int* pbOutAllOpaque )
 
 {
-    GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
-    float *pafMask = (float *) pValidityMask;
+    GDALWarpOptions *psWO = static_cast<GDALWarpOptions *>(pMaskFuncArg);
+    float *pafMask = static_cast<float *>(pValidityMask);
     *pbOutAllOpaque = FALSE;
+    const size_t nPixels = static_cast<size_t>(nXSize) * nYSize;
 
 /* -------------------------------------------------------------------- */
 /*      Do some minimal checking.                                       */
 /* -------------------------------------------------------------------- */
     if( !bMaskIsFloat )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
     if( psWO == NULL || psWO->nSrcAlphaBand < 1 )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Read the alpha band.                                            */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
     GDALRasterBandH hAlphaBand = GDALGetRasterBand( psWO->hSrcDS,
                                                     psWO->nSrcAlphaBand );
     if (hAlphaBand == NULL)
         return CE_Failure;
 
-    eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
-                         pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
+    // Rescale.
+    const float inv_alpha_max = static_cast<float>(1.0 / CPLAtof(
+      CSLFetchNameValueDef( psWO->papszWarpOptions, "SRC_ALPHA_MAX", "255" )));
+    bool bOutAllOpaque = true;
 
-    if( eErr != CE_None )
-        return eErr;
+    size_t iPixel = 0;
+    CPLErr eErr;
 
-/* -------------------------------------------------------------------- */
-/*      Rescale from 0-255 to 0.0-1.0.                                  */
-/* -------------------------------------------------------------------- */
-    int bOutAllOpaque = TRUE;
-    for( int iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
-    {                                    //  (1/255)
-        pafMask[iPixel] = (float)( pafMask[iPixel] * 0.00392157 );
-        if( pafMask[iPixel] >= 1.0F )
-            pafMask[iPixel] = 1.0F;
-        else
-            bOutAllOpaque = FALSE;
+
+#if (defined(__x86_64) || defined(_M_X64))
+    GDALDataType eDT = GDALGetRasterDataType(hAlphaBand);
+    // Make sure that pafMask is at least 8-byte aligned, which should
+    // normally be always the case if being a ptr returned by malloc().
+    if( (eDT == GDT_Byte || eDT == GDT_UInt16) && CPL_IS_ALIGNED(pafMask, 8) )
+    {
+        // Read data.
+        eErr = GDALRasterIOEx( hAlphaBand, GF_Read,
+                               nXOff, nYOff, nXSize, nYSize,
+                               pafMask, nXSize, nYSize, eDT,
+                               static_cast<GSpacing>(sizeof(int)),
+                               static_cast<GSpacing>(sizeof(int)) * nXSize,
+                               NULL );
+
+        if( eErr != CE_None )
+            return eErr;
+
+        // Make sure we have the correct alignment before doing SSE
+        // On Linux x86_64, the alignment should be always correct due
+        // the alignment of malloc() being 16 byte.
+        const GUInt32 mask = (eDT == GDT_Byte) ? 0xff : 0xffff;
+        if( !CPL_IS_ALIGNED(pafMask, 16) )
+        {
+            pafMask[iPixel] = (((GUInt32*)pafMask)[iPixel] & mask) *
+                                                    inv_alpha_max;
+            if( pafMask[iPixel] >= 1.0f )
+                pafMask[iPixel] = 1.0f;
+            else
+                bOutAllOpaque = false;
+            iPixel ++;
+        }
+        CPLAssert( CPL_IS_ALIGNED(pafMask + iPixel, 16) );
+        const __m128 xmm_inverse_alpha_max = _mm_load1_ps(&inv_alpha_max);
+        const float one_single = 1.0f;
+        const __m128 xmm_one = _mm_load1_ps(&one_single);
+        const __m128i xmm_i_mask = _mm_set1_epi32 (mask);
+        __m128 xmmMaskNonOpaque0 = _mm_setzero_ps();
+        __m128 xmmMaskNonOpaque1 = _mm_setzero_ps();
+        __m128 xmmMaskNonOpaque2 = _mm_setzero_ps();
+        for( ; iPixel + 6*4-1 < nPixels; iPixel+=6*4 )
+        {
+            __m128 xmm_mask0 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 0) )) );
+            __m128 xmm_mask1 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 1) )) );
+            __m128 xmm_mask2 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 2) )) );
+            __m128 xmm_mask3 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 3) )) );
+            __m128 xmm_mask4 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 4) )) );
+            __m128 xmm_mask5 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 5) )) );
+            xmm_mask0 = _mm_mul_ps(xmm_mask0, xmm_inverse_alpha_max);
+            xmm_mask1 = _mm_mul_ps(xmm_mask1, xmm_inverse_alpha_max);
+            xmm_mask2 = _mm_mul_ps(xmm_mask2, xmm_inverse_alpha_max);
+            xmm_mask3 = _mm_mul_ps(xmm_mask3, xmm_inverse_alpha_max);
+            xmm_mask4 = _mm_mul_ps(xmm_mask4, xmm_inverse_alpha_max);
+            xmm_mask5 = _mm_mul_ps(xmm_mask5, xmm_inverse_alpha_max);
+            xmmMaskNonOpaque0 =
+                _mm_or_ps(xmmMaskNonOpaque0, _mm_cmplt_ps(xmm_mask0, xmm_one));
+            xmmMaskNonOpaque1 =
+                _mm_or_ps(xmmMaskNonOpaque1, _mm_cmplt_ps(xmm_mask1, xmm_one));
+            xmmMaskNonOpaque2 =
+                _mm_or_ps(xmmMaskNonOpaque2, _mm_cmplt_ps(xmm_mask2, xmm_one));
+            xmmMaskNonOpaque0 =
+                _mm_or_ps(xmmMaskNonOpaque0, _mm_cmplt_ps(xmm_mask3, xmm_one));
+            xmmMaskNonOpaque1 =
+                _mm_or_ps(xmmMaskNonOpaque1, _mm_cmplt_ps(xmm_mask4, xmm_one));
+            xmmMaskNonOpaque2 =
+                _mm_or_ps(xmmMaskNonOpaque2, _mm_cmplt_ps(xmm_mask5, xmm_one));
+            xmm_mask0 = _mm_min_ps(xmm_mask0, xmm_one);
+            xmm_mask1 = _mm_min_ps(xmm_mask1, xmm_one);
+            xmm_mask2 = _mm_min_ps(xmm_mask2, xmm_one);
+            xmm_mask3 = _mm_min_ps(xmm_mask3, xmm_one);
+            xmm_mask4 = _mm_min_ps(xmm_mask4, xmm_one);
+            xmm_mask5 = _mm_min_ps(xmm_mask5, xmm_one);
+            _mm_store_ps(pafMask + iPixel + 4 * 0, xmm_mask0);
+            _mm_store_ps(pafMask + iPixel + 4 * 1, xmm_mask1);
+            _mm_store_ps(pafMask + iPixel + 4 * 2, xmm_mask2);
+            _mm_store_ps(pafMask + iPixel + 4 * 3, xmm_mask3);
+            _mm_store_ps(pafMask + iPixel + 4 * 4, xmm_mask4);
+            _mm_store_ps(pafMask + iPixel + 4 * 5, xmm_mask5);
+        }
+        if( _mm_movemask_ps(_mm_or_ps(_mm_or_ps(
+                  xmmMaskNonOpaque0, xmmMaskNonOpaque1), xmmMaskNonOpaque2))  )
+        {
+            bOutAllOpaque = false;
+        }
+        for(; iPixel < nPixels; iPixel++ )
+        {
+            pafMask[iPixel] = (((GUInt32*)pafMask)[iPixel] & mask) *
+                                                      inv_alpha_max;
+            if( pafMask[iPixel] >= 1.0f )
+                pafMask[iPixel] = 1.0f;
+            else
+                bOutAllOpaque = false;
+        }
     }
+    else
+#endif
+    {
+        // Read data.
+        eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
+                             pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
+
+        if( eErr != CE_None )
+            return eErr;
+
+        // TODO(rouault): Is loop unrolling by hand (r34564) actually helpful?
+        for( ; iPixel + 3 < nPixels; iPixel += 4 )
+        {
+            pafMask[iPixel] = pafMask[iPixel] * inv_alpha_max;
+            if( pafMask[iPixel] >= 1.0f )
+                pafMask[iPixel] = 1.0f;
+            else
+                bOutAllOpaque = false;
+            pafMask[iPixel+1] = pafMask[iPixel+1] * inv_alpha_max;
+            if( pafMask[iPixel+1] >= 1.0f )
+                pafMask[iPixel+1] = 1.0f;
+            else
+                bOutAllOpaque = false;
+            pafMask[iPixel+2] = pafMask[iPixel+2] * inv_alpha_max;
+            if( pafMask[iPixel+2] >= 1.0f )
+                pafMask[iPixel+2] = 1.0f;
+            else
+                bOutAllOpaque = false;
+            pafMask[iPixel+3] = pafMask[iPixel+3] * inv_alpha_max;
+            if( pafMask[iPixel+3] >= 1.0f )
+                pafMask[iPixel+3] = 1.0f;
+            else
+                bOutAllOpaque = false;
+        }
+
+        for( ; iPixel < nPixels; iPixel++ )
+        {
+            pafMask[iPixel] = pafMask[iPixel] * inv_alpha_max;
+            if( pafMask[iPixel] >= 1.0f )
+                pafMask[iPixel] = 1.0f;
+            else
+                bOutAllOpaque = false;
+        }
+    }
+
     *pbOutAllOpaque = bOutAllOpaque;
 
     return CE_None;
@@ -639,37 +754,36 @@ GDALWarpSrcAlphaMasker( void *pMaskFuncArg,
 
 CPLErr
 GDALWarpSrcMaskMasker( void *pMaskFuncArg,
-                       CPL_UNUSED int nBandCount,
-                       CPL_UNUSED GDALDataType eType,
+                       int /* nBandCount */,
+                       GDALDataType /* eType */,
                        int nXOff, int nYOff, int nXSize, int nYSize,
                        GByte ** /*ppImageData */,
                        int bMaskIsFloat, void *pValidityMask )
 
 {
-    GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
-    GUInt32  *panMask = (GUInt32 *) pValidityMask;
+    GDALWarpOptions *psWO = static_cast<GDALWarpOptions *>(pMaskFuncArg);
+    GUInt32  *panMask = static_cast<GUInt32 *>(pValidityMask);
 
 /* -------------------------------------------------------------------- */
 /*      Do some minimal checking.                                       */
 /* -------------------------------------------------------------------- */
     if( bMaskIsFloat )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
     if( psWO == NULL )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Allocate a temporary buffer to read mask byte data into.        */
 /* -------------------------------------------------------------------- */
-    GByte *pabySrcMask;
-
-    pabySrcMask = (GByte *) VSI_MALLOC2_VERBOSE(nXSize,nYSize);
+    GByte *pabySrcMask = static_cast<GByte *>(
+        VSI_MALLOC2_VERBOSE(nXSize,nYSize));
     if( pabySrcMask == NULL )
     {
         return CE_Failure;
@@ -678,25 +792,24 @@ GDALWarpSrcMaskMasker( void *pMaskFuncArg,
 /* -------------------------------------------------------------------- */
 /*      Fetch our mask band.                                            */
 /* -------------------------------------------------------------------- */
-    GDALRasterBandH hSrcBand, hMaskBand = NULL;
-
-    hSrcBand = GDALGetRasterBand( psWO->hSrcDS, psWO->panSrcBands[0] );
+    GDALRasterBandH hMaskBand = NULL;
+    GDALRasterBandH hSrcBand =
+        GDALGetRasterBand( psWO->hSrcDS, psWO->panSrcBands[0] );
     if( hSrcBand != NULL )
         hMaskBand = GDALGetMaskBand( hSrcBand );
 
     if( hMaskBand == NULL )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Read the mask band.                                             */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
-
-    eErr = GDALRasterIO( hMaskBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
-                         pabySrcMask, nXSize, nYSize, GDT_Byte, 0, 0 );
+    CPLErr eErr =
+        GDALRasterIO( hMaskBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
+                      pabySrcMask, nXSize, nYSize, GDT_Byte, 0, 0 );
 
     if( eErr != CE_None )
     {
@@ -707,7 +820,8 @@ GDALWarpSrcMaskMasker( void *pMaskFuncArg,
 /* -------------------------------------------------------------------- */
 /*      Pack into 1 bit per pixel for validity.                         */
 /* -------------------------------------------------------------------- */
-    for( int iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
+    const size_t nPixels = static_cast<size_t>(nXSize) * nYSize;
+    for( size_t iPixel = 0; iPixel < nPixels; iPixel++ )
     {
         if( pabySrcMask[iPixel] == 0 )
             panMask[iPixel>>5] &= ~(0x01 << (iPixel & 0x1f));
@@ -729,64 +843,159 @@ GDALWarpSrcMaskMasker( void *pMaskFuncArg,
 
 CPLErr
 GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
-                        CPL_UNUSED GDALDataType eType,
+                        CPL_UNUSED GDALDataType /* eType */,
                         int nXOff, int nYOff, int nXSize, int nYSize,
                         GByte ** /*ppImageData */,
                         int bMaskIsFloat, void *pValidityMask )
 {
-    GDALWarpOptions *psWO = (GDALWarpOptions *) pMaskFuncArg;
-    float *pafMask = (float *) pValidityMask;
-    int iPixel;
-    CPLErr eErr;
-
 /* -------------------------------------------------------------------- */
 /*      Do some minimal checking.                                       */
 /* -------------------------------------------------------------------- */
     if( !bMaskIsFloat )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
+    GDALWarpOptions *psWO = static_cast<GDALWarpOptions *>(pMaskFuncArg);
     if( psWO == NULL || psWO->nDstAlphaBand < 1 )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
 
+    float *pafMask = static_cast<float *>(pValidityMask);
+    const size_t nPixels = static_cast<size_t>(nXSize) * nYSize;
+
     GDALRasterBandH hAlphaBand =
         GDALGetRasterBand( psWO->hDstDS, psWO->nDstAlphaBand );
     if (hAlphaBand == NULL)
         return CE_Failure;
 
+    size_t iPixel = 0;
+
 /* -------------------------------------------------------------------- */
-/*      Read alpha case.						*/
+/*      Read alpha case.                                                */
 /* -------------------------------------------------------------------- */
     if( nBandCount >= 0 )
     {
         const char *pszInitDest =
             CSLFetchNameValue( psWO->papszWarpOptions, "INIT_DEST" );
 
-        // Special logic for destinations being initialized on the fly.
+        // Special logic for destinations being initialized on-the-fly.
         if( pszInitDest != NULL )
         {
-            for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
-                pafMask[iPixel] = 0.0;
+            memset( pafMask, 0, nPixels * sizeof(float) );
             return CE_None;
         }
 
-        // Read data.
-        eErr = GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
-                             pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
+        // Rescale.
+        const float inv_alpha_max =  static_cast<float>(1.0 / CPLAtof(
+            CSLFetchNameValueDef( psWO->papszWarpOptions, "DST_ALPHA_MAX",
+                                  "255" ) ));
+
+#if (defined(__x86_64) || defined(_M_X64))
+        const GDALDataType eDT = GDALGetRasterDataType(hAlphaBand);
+        // Make sure that pafMask is at least 8-byte aligned, which should
+        // normally be always the case if being a ptr returned by malloc().
+        if( (eDT == GDT_Byte || eDT == GDT_UInt16) &&
+            CPL_IS_ALIGNED(pafMask, 8) )
+        {
+            // Read data.
+            const CPLErr eErr =
+                GDALRasterIOEx( hAlphaBand, GF_Read,
+                                nXOff, nYOff, nXSize, nYSize,
+                                pafMask, nXSize, nYSize, eDT,
+                                static_cast<GSpacing>(sizeof(int)),
+                                static_cast<GSpacing>(sizeof(int)) * nXSize,
+                                NULL );
+
+            if( eErr != CE_None )
+                return eErr;
+
+            // Make sure we have the correct alignment before doing SSE
+            // On Linux x86_64, the alignment should be always correct due
+            // the alignment of malloc() being 16 byte.
+            const GUInt32 mask = (eDT == GDT_Byte) ? 0xff : 0xffff;
+            if( !CPL_IS_ALIGNED(pafMask, 16) )
+            {
+                pafMask[iPixel] = (((GUInt32*)pafMask)[iPixel] & mask) *
+                                                          inv_alpha_max;
+                pafMask[iPixel] = std::min( 1.0f, pafMask[iPixel] );
+                iPixel ++;
+            }
+            CPLAssert( CPL_IS_ALIGNED(pafMask + iPixel, 16) );
+            const __m128 xmm_inverse_alpha_max =
+                                        _mm_load1_ps(&inv_alpha_max);
+            const float one_single = 1.0f;
+            const __m128 xmm_one = _mm_load1_ps(&one_single);
+            const __m128i xmm_i_mask = _mm_set1_epi32 (mask);
+            for( ; iPixel + 31 < nPixels; iPixel+=32 )
+            {
+                __m128 xmm_mask0 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 0) )) );
+                __m128 xmm_mask1 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 1) )) );
+                __m128 xmm_mask2 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 2) )) );
+                __m128 xmm_mask3 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 3) )) );
+                __m128 xmm_mask4 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 4) )) );
+                __m128 xmm_mask5 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 5) )) );
+                __m128 xmm_mask6 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 6) )) );
+                __m128 xmm_mask7 = _mm_cvtepi32_ps( _mm_and_si128(xmm_i_mask,
+                    _mm_load_si128( (__m128i *)(pafMask + iPixel + 4 * 7) )) );
+                xmm_mask0 = _mm_mul_ps(xmm_mask0, xmm_inverse_alpha_max);
+                xmm_mask1 = _mm_mul_ps(xmm_mask1, xmm_inverse_alpha_max);
+                xmm_mask2 = _mm_mul_ps(xmm_mask2, xmm_inverse_alpha_max);
+                xmm_mask3 = _mm_mul_ps(xmm_mask3, xmm_inverse_alpha_max);
+                xmm_mask4 = _mm_mul_ps(xmm_mask4, xmm_inverse_alpha_max);
+                xmm_mask5 = _mm_mul_ps(xmm_mask5, xmm_inverse_alpha_max);
+                xmm_mask6 = _mm_mul_ps(xmm_mask6, xmm_inverse_alpha_max);
+                xmm_mask7 = _mm_mul_ps(xmm_mask7, xmm_inverse_alpha_max);
+                xmm_mask0 = _mm_min_ps(xmm_mask0, xmm_one);
+                xmm_mask1 = _mm_min_ps(xmm_mask1, xmm_one);
+                xmm_mask2 = _mm_min_ps(xmm_mask2, xmm_one);
+                xmm_mask3 = _mm_min_ps(xmm_mask3, xmm_one);
+                xmm_mask4 = _mm_min_ps(xmm_mask4, xmm_one);
+                xmm_mask5 = _mm_min_ps(xmm_mask5, xmm_one);
+                xmm_mask6 = _mm_min_ps(xmm_mask6, xmm_one);
+                xmm_mask7 = _mm_min_ps(xmm_mask7, xmm_one);
+                _mm_store_ps(pafMask + iPixel + 4 * 0, xmm_mask0);
+                _mm_store_ps(pafMask + iPixel + 4 * 1, xmm_mask1);
+                _mm_store_ps(pafMask + iPixel + 4 * 2, xmm_mask2);
+                _mm_store_ps(pafMask + iPixel + 4 * 3, xmm_mask3);
+                _mm_store_ps(pafMask + iPixel + 4 * 4, xmm_mask4);
+                _mm_store_ps(pafMask + iPixel + 4 * 5, xmm_mask5);
+                _mm_store_ps(pafMask + iPixel + 4 * 6, xmm_mask6);
+                _mm_store_ps(pafMask + iPixel + 4 * 7, xmm_mask7);
+            }
+            for(; iPixel < nPixels; iPixel++ )
+            {
+                pafMask[iPixel] = (((GUInt32*)pafMask)[iPixel] & mask) *
+                                                        inv_alpha_max;
+                pafMask[iPixel] = std::min( 1.0f, pafMask[iPixel] );
+            }
+        }
+        else
+#endif
+        {
+            // Read data.
+            const CPLErr eErr =
+                GDALRasterIO( hAlphaBand, GF_Read, nXOff, nYOff, nXSize, nYSize,
+                              pafMask, nXSize, nYSize, GDT_Float32, 0, 0 );
 
-        if( eErr != CE_None )
-            return eErr;
+            if( eErr != CE_None )
+                return eErr;
 
-        // rescale.
-        for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
-        {
-            pafMask[iPixel] = (float) (pafMask[iPixel] * 0.00392157);
-            pafMask[iPixel] = MIN( 1.0F, pafMask[iPixel] );
+            for(; iPixel < nPixels; iPixel++ )
+            {
+                pafMask[iPixel] = pafMask[iPixel] * inv_alpha_max;
+                pafMask[iPixel] = std::min(1.0f, pafMask[iPixel]);
+            }
         }
 
         return CE_None;
@@ -797,25 +1006,107 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
 /* -------------------------------------------------------------------- */
     else
     {
-        for( iPixel = nXSize * nYSize - 1; iPixel >= 0; iPixel-- )
-            pafMask[iPixel] = (float)(int) ( pafMask[iPixel] * 255.1 );
-
-        // Write data.
-
-        /* The VRT warper will pass destination sizes that may exceed */
-        /* the size of the raster for the partial blocks at the right */
-        /* and bottom of the band. So let's adjust the size */
-        int nDstXSize = nXSize;
-        if (nXOff + nXSize > GDALGetRasterBandXSize(hAlphaBand))
-            nDstXSize = GDALGetRasterBandXSize(hAlphaBand) - nXOff;
-        int nDstYSize = nYSize;
-        if (nYOff + nYSize > GDALGetRasterBandYSize(hAlphaBand))
-            nDstYSize = GDALGetRasterBandYSize(hAlphaBand) - nYOff;
-
-        eErr = GDALRasterIO( hAlphaBand, GF_Write,
-                             nXOff, nYOff, nDstXSize, nDstYSize,
-                             pafMask, nDstXSize, nDstYSize, GDT_Float32,
-                             0, (int)sizeof(float) * nXSize );
+        GDALDataType eDT = GDALGetRasterDataType(hAlphaBand);
+        const float cst_alpha_max = static_cast<float>(CPLAtof(
+            CSLFetchNameValueDef( psWO->papszWarpOptions, "DST_ALPHA_MAX",
+                                  "255" ) )) +
+            (( eDT == GDT_Byte || eDT == GDT_Int16 || eDT == GDT_UInt16 ||
+               eDT == GDT_Int32 || eDT == GDT_UInt32 ) ?
+                0.1f : 0.0f);
+
+        CPLErr eErr = CE_None;
+
+#if (defined(__x86_64) || defined(_M_X64))
+        // Make sure that pafMask is at least 8-byte aligned, which should
+        // normally be always the case if being a ptr returned by malloc()
+        if( (eDT == GDT_Byte || eDT == GDT_Int16 || eDT == GDT_UInt16) &&
+            CPL_IS_ALIGNED(pafMask, 8) )
+        {
+            // Make sure we have the correct alignment before doing SSE
+            // On Linux x86_64, the alignment should be always correct due
+            // the alignment of malloc() being 16 byte
+            if( !CPL_IS_ALIGNED(pafMask, 16) )
+            {
+                ((int*)pafMask)[iPixel] =
+                    static_cast<int>(pafMask[iPixel] * cst_alpha_max);
+                iPixel++;
+            }
+            CPLAssert( CPL_IS_ALIGNED(pafMask + iPixel, 16) );
+            const __m128 xmm_alpha_max = _mm_load1_ps(&cst_alpha_max);
+            for( ; iPixel + 31 < nPixels; iPixel += 32 )
+            {
+                __m128 xmm_mask0 = _mm_load_ps(pafMask + iPixel + 4 * 0);
+                __m128 xmm_mask1 = _mm_load_ps(pafMask + iPixel + 4 * 1);
+                __m128 xmm_mask2 = _mm_load_ps(pafMask + iPixel + 4 * 2);
+                __m128 xmm_mask3 = _mm_load_ps(pafMask + iPixel + 4 * 3);
+                __m128 xmm_mask4 = _mm_load_ps(pafMask + iPixel + 4 * 4);
+                __m128 xmm_mask5 = _mm_load_ps(pafMask + iPixel + 4 * 5);
+                __m128 xmm_mask6 = _mm_load_ps(pafMask + iPixel + 4 * 6);
+                __m128 xmm_mask7 = _mm_load_ps(pafMask + iPixel + 4 * 7);
+                xmm_mask0 = _mm_mul_ps(xmm_mask0, xmm_alpha_max);
+                xmm_mask1 = _mm_mul_ps(xmm_mask1, xmm_alpha_max);
+                xmm_mask2 = _mm_mul_ps(xmm_mask2, xmm_alpha_max);
+                xmm_mask3 = _mm_mul_ps(xmm_mask3, xmm_alpha_max);
+                xmm_mask4 = _mm_mul_ps(xmm_mask4, xmm_alpha_max);
+                xmm_mask5 = _mm_mul_ps(xmm_mask5, xmm_alpha_max);
+                xmm_mask6 = _mm_mul_ps(xmm_mask6, xmm_alpha_max);
+                xmm_mask7 = _mm_mul_ps(xmm_mask7, xmm_alpha_max);
+                 // Truncate to int.
+                _mm_store_si128((__m128i*)(pafMask + iPixel + 4 * 0),
+                                _mm_cvttps_epi32(xmm_mask0));
+                _mm_store_si128((__m128i*)(pafMask + iPixel + 4 * 1),
+                                _mm_cvttps_epi32(xmm_mask1));
+                _mm_store_si128((__m128i*)(pafMask + iPixel + 4 * 2),
+                                _mm_cvttps_epi32(xmm_mask2));
+                _mm_store_si128((__m128i*)(pafMask + iPixel + 4 * 3),
+                                _mm_cvttps_epi32(xmm_mask3));
+                _mm_store_si128((__m128i*)(pafMask + iPixel + 4 * 4),
+                                _mm_cvttps_epi32(xmm_mask4));
+                _mm_store_si128((__m128i*)(pafMask + iPixel + 4 * 5),
+                                _mm_cvttps_epi32(xmm_mask5));
+                _mm_store_si128((__m128i*)(pafMask + iPixel + 4 * 6),
+                                _mm_cvttps_epi32(xmm_mask6));
+                _mm_store_si128((__m128i*)(pafMask + iPixel + 4 * 7),
+                                _mm_cvttps_epi32(xmm_mask7));
+            }
+            for( ; iPixel < nPixels; iPixel++ )
+                ((int*)pafMask)[iPixel] =
+                  static_cast<int>(pafMask[iPixel] * cst_alpha_max);
+
+            // Write data.
+            // Assumes little endianness here.
+            eErr = GDALRasterIOEx( hAlphaBand, GF_Write,
+                                   nXOff, nYOff, nXSize, nYSize,
+                                   pafMask, nXSize, nYSize, eDT,
+                                   static_cast<GSpacing>(sizeof(int)),
+                                   static_cast<GSpacing>(sizeof(int)) * nXSize,
+                                   NULL );
+        }
+        else
+#endif
+        {
+            for( ; iPixel + 3 < nPixels; iPixel+=4 )
+            {
+                pafMask[iPixel+0] = static_cast<float>(
+                    static_cast<int>( pafMask[iPixel+0] * cst_alpha_max ));
+                pafMask[iPixel+1] = static_cast<float>(
+                    static_cast<int>( pafMask[iPixel+1] * cst_alpha_max ));
+                pafMask[iPixel+2] = static_cast<float>(
+                    static_cast<int>( pafMask[iPixel+2] * cst_alpha_max ));
+                pafMask[iPixel+3] = static_cast<float>(
+                    static_cast<int>( pafMask[iPixel+3] * cst_alpha_max ));
+            }
+            for( ; iPixel < nPixels; iPixel++ )
+                pafMask[iPixel] = static_cast<float>(
+                    static_cast<int>(pafMask[iPixel] * cst_alpha_max ));
+
+            // Write data.
+
+            eErr = GDALRasterIO( hAlphaBand, GF_Write,
+                                nXOff, nYOff, nXSize, nYSize,
+                                pafMask, nXSize, nYSize, GDT_Float32,
+                                0, 0 );
+        }
         return eErr;
     }
 }
@@ -834,94 +1125,70 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
  * CSLSetNameValue().
  *
  * The following values are currently supported:
- *
- *  - INIT_DEST=[value] or INIT_DEST=NO_DATA: This option forces the
+ * <ul>
+ * <li>INIT_DEST=[value] or INIT_DEST=NO_DATA: This option forces the
  * destination image to be initialized to the indicated value (for all bands)
  * or indicates that it should be initialized to the NO_DATA value in
  * padfDstNoDataReal/padfDstNoDataImag.  If this value isn't set the
- * destination image will be read and overlaid.
+ * destination image will be read and overlaid.</li>
  *
- * - WRITE_FLUSH=YES/NO: This option forces a flush to disk of data after
+ * <li>WRITE_FLUSH=YES/NO: This option forces a flush to disk of data after
  * each chunk is processed.  In some cases this helps ensure a serial
  * writing of the output data otherwise a block of data may be written to disk
  * each time a block of data is read for the input buffer resulting in a lot
  * of extra seeking around the disk, and reduced IO throughput.  The default
- * at this time is NO.
+ * at this time is NO.</li>
  *
- * - SKIP_NOSOURCE=YES/NO: Skip all processing for chunks for which there
+ * <li>SKIP_NOSOURCE=YES/NO: Skip all processing for chunks for which there
  * is no corresponding input data.  This will disable initializing the
  * destination (INIT_DEST) and all other processing, and so should be used
- * careful.  Mostly useful to short circuit a lot of extra work in mosaicing
- * situations.
+ * carefully.  Mostly useful to short circuit a lot of extra work in mosaicing
+ * situations.</li>
  *
- * - UNIFIED_SRC_NODATA=YES/[NO]: By default nodata masking values considered
+ * <li>UNIFIED_SRC_NODATA=YES/NO: By default nodata masking values considered
  * independently for each band.  However, sometimes it is desired to treat all
  * bands as nodata if and only if, all bands match the corresponding nodata
- * values.  To get this behavior set this option to YES.
+ * values. To get this behavior set this option to YES.
+ * Note: UNIFIED_SRC_NODATA=YES is set by default, when called from gdalwarp /
+ * GDALWarp()</li>
  *
- * Normally when computing the source raster data to
- * load to generate a particular output area, the warper samples transforms
- * 21 points along each edge of the destination region back onto the source
- * file, and uses this to compute a bounding window on the source image that
- * is sufficient.  Depending on the transformation in effect, the source
- * window may be a bit too small, or even missing large areas.  Problem
- * situations are those where the transformation is very non-linear or
- * "inside out".  Examples are transforming from WGS84 to Polar Steregraphic
- * for areas around the pole, or transformations where some of the image is
- * untransformable.  The following options provide some additional control
- * to deal with errors in computing the source window:
- *
- * - SAMPLE_GRID=YES/NO: Setting this option to YES will force the sampling to
- * include internal points as well as edge points which can be important if
- * the transformation is esoteric inside out, or if large sections of the
- * destination image are not transformable into the source coordinate system.
- *
- * - SAMPLE_STEPS: Modifies the density of the sampling grid.  The default
- * number of steps is 21.   Increasing this can increase the computational
- * cost, but improves the accuracy with which the source region is computed.
- *
- * - SOURCE_EXTRA: This is a number of extra pixels added around the source
- * window for a given request, and by default it is 1 to take care of rounding
- * error.  Setting this larger will increase the amount of data that needs to
- * be read, but can avoid missing source data.
- *
- * - CUTLINE: This may contain the WKT geometry for a cutline.  It will
+ * <li>CUTLINE: This may contain the WKT geometry for a cutline.  It will
  * be converted into a geometry by GDALWarpOperation::Initialize() and assigned
  * to the GDALWarpOptions hCutline field. The coordinates must be expressed
  * in source pixel/line coordinates. Note: this is different from the assumptions
- * made for the -cutline option of the gdalwarp utility !
+ * made for the -cutline option of the gdalwarp utility !</li>
  *
- * - CUTLINE_BLEND_DIST: This may be set with a distance in pixels which
- * will be assigned to the dfCutlineBlendDist field in the GDALWarpOptions.
+ * <li>CUTLINE_BLEND_DIST: This may be set with a distance in pixels which
+ * will be assigned to the dfCutlineBlendDist field in the GDALWarpOptions.</li>
  *
- * - CUTLINE_ALL_TOUCHED: This defaults to FALSE, but may be set to TRUE
+ * <li>CUTLINE_ALL_TOUCHED: This defaults to FALSE, but may be set to TRUE
  * to enable ALL_TOUCHEd mode when rasterizing cutline polygons.  This is
  * useful to ensure that that all pixels overlapping the cutline polygon
  * will be selected, not just those whose center point falls within the
- * polygon.
+ * polygon.</li>
  *
- * - OPTIMIZE_SIZE: This defaults to FALSE, but may be set to TRUE
+ * <li>OPTIMIZE_SIZE: This defaults to FALSE, but may be set to TRUE
  * typically when writing to a compressed dataset (GeoTIFF with
  * COMPRESSED creation option set for example) for achieving a smaller
  * file size. This is achieved by writing at once data aligned on full
  * blocks of the target dataset, which avoids partial writes of
  * compressed blocks and lost space when they are rewritten at the end
  * of the file. However sticking to target block size may cause major
- * processing slowdown for some particular reprojections.
+ * processing slowdown for some particular reprojections.</li>
  *
- * - NUM_THREADS: (GDAL >= 1.10) Can be set to a numeric value or ALL_CPUS to
+ * <li>NUM_THREADS: (GDAL >= 1.10) Can be set to a numeric value or ALL_CPUS to
  * set the number of threads to use to parallelize the computation part of the
- * warping. If not set, computation will be done in a single thread.
+ * warping. If not set, computation will be done in a single thread.</li>
  *
- * - STREAMABLE_OUTPUT: (GDAL >= 2.0) This defaults to FALSE, but may
+ * <li>STREAMABLE_OUTPUT: (GDAL >= 2.0) This defaults to FALSE, but may
  * be set to TRUE typically when writing to a streamed file. The
  * gdalwarp utility automatically sets this option when writing to
  * /vsistdout/ or a named pipe (on Unix).  This option has performance
  * impacts for some reprojections.  Note: band interleaved output is
  * not currently supported by the warping algorithm in a streamable
- * compatible way.
+ * compatible way.</li>
  *
- * - SRC_COORD_PRECISION: (GDAL >= 2.0). Advanced setting. This
+ * <li>SRC_COORD_PRECISION: (GDAL >= 2.0). Advanced setting. This
  * defaults to 0, to indicate that no rounding of computing source
  * image coordinates corresponding to the target image must be
  * done. If greater than 0 (and typically below 1), this value,
@@ -933,19 +1200,63 @@ GDALWarpDstAlphaMasker( void *pMaskFuncArg, int nBandCount,
  * error threshold. The higher the SRC_COORD_PRECISION/error_threshold
  * ratio, the higher the performance will be, since exact
  * reprojections must statistically be done with a frequency of
- * 4*error_threshold/SRC_COORD_PRECISION.
+ * 4*error_threshold/SRC_COORD_PRECISION.</li>
+ *
+ * <li>SRC_ALPHA_MAX: (GDAL >= 2.2). Maximum value for the alpha band of the
+ * source dataset. If the value is not set and the alpha band has a NBITS
+ * metadata item, it is used to set SRC_ALPHA_MAX = 2^NBITS-1. Otherwise, if the
+ * value is not set and the alpha band is of type UInt16 (resp Int16), 65535
+ * (resp 32767) is used. Otherwise, 255 is used.</li>
+ *
+ * <li>DST_ALPHA_MAX: (GDAL >= 2.2). Maximum value for the alpha band of the
+ * destination dataset. If the value is not set and the alpha band has a NBITS
+ * metadata item, it is used to set DST_ALPHA_MAX = 2^NBITS-1. Otherwise, if the
+ * value is not set and the alpha band is of type UInt16 (resp Int16), 65535
+ * (resp 32767) is used. Otherwise, 255 is used.</li>
+ * </ul>
+ *
+ * Normally when computing the source raster data to
+ * load to generate a particular output area, the warper samples transforms
+ * 21 points along each edge of the destination region back onto the source
+ * file, and uses this to compute a bounding window on the source image that
+ * is sufficient.  Depending on the transformation in effect, the source
+ * window may be a bit too small, or even missing large areas.  Problem
+ * situations are those where the transformation is very non-linear or
+ * "inside out".  Examples are transforming from WGS84 to Polar Steregraphic
+ * for areas around the pole, or transformations where some of the image is
+ * untransformable.  The following options provide some additional control
+ * to deal with errors in computing the source window:
+ * <ul>
+ *
+ * <li>SAMPLE_GRID=YES/NO: Setting this option to YES will force the sampling to
+ * include internal points as well as edge points which can be important if
+ * the transformation is esoteric inside out, or if large sections of the
+ * destination image are not transformable into the source coordinate system.</li>
+ *
+ * <li>SAMPLE_STEPS: Modifies the density of the sampling grid.  The default
+ * number of steps is 21.   Increasing this can increase the computational
+ * cost, but improves the accuracy with which the source region is computed.</li>
+ *
+ * <li>SOURCE_EXTRA: This is a number of extra pixels added around the source
+ * window for a given request, and by default it is 1 to take care of rounding
+ * error.  Setting this larger will increase the amount of data that needs to
+ * be read, but can avoid missing source data.</li>
+ * </ul>
  */
 
 /************************************************************************/
 /*                       GDALCreateWarpOptions()                        */
 /************************************************************************/
 
+/** Create a warp options structure.
+ *
+ * Must be deallocated with GDALDestroyWarpOptions()
+ */
 GDALWarpOptions * CPL_STDCALL GDALCreateWarpOptions()
 
 {
-    GDALWarpOptions *psOptions;
-
-    psOptions = (GDALWarpOptions *) CPLCalloc(sizeof(GDALWarpOptions),1);
+    GDALWarpOptions *psOptions = static_cast<GDALWarpOptions *>(
+        CPLCalloc(sizeof(GDALWarpOptions), 1));
 
     psOptions->nBandCount = 0;
     psOptions->eResampleAlg = GRA_NearestNeighbour;
@@ -959,6 +1270,7 @@ GDALWarpOptions * CPL_STDCALL GDALCreateWarpOptions()
 /*                       GDALDestroyWarpOptions()                       */
 /************************************************************************/
 
+/** Destroy a warp options structure. */
 void CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions *psOptions )
 
 {
@@ -981,21 +1293,24 @@ void CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions *psOptions )
     CPLFree( psOptions );
 }
 
-
-#define COPY_MEM(target,type,count)					\
-   do { if( (psSrcOptions->target) != NULL && (count) != 0 ) 		\
-   { 									\
+#define COPY_MEM(target,type,count)                                     \
+   do { if( (psSrcOptions->target) != NULL && (count) != 0 )            \
+   {                                                                    \
        (psDstOptions->target) = (type *) CPLMalloc(sizeof(type)*(count)); \
-       memcpy( (psDstOptions->target), (psSrcOptions->target),		\
- 	       sizeof(type) * (count) ); 	        			\
+       memcpy( (psDstOptions->target), (psSrcOptions->target),          \
+               sizeof(type) * (count) );                                \
    } \
    else \
-       (psDstOptions->target) = NULL; } while(0)
+       (psDstOptions->target) = NULL; } while( false )
 
 /************************************************************************/
 /*                        GDALCloneWarpOptions()                        */
 /************************************************************************/
 
+/** Clone a warp options structure.
+ *
+ * Must be deallocated with GDALDestroyWarpOptions()
+ */
 GDALWarpOptions * CPL_STDCALL
 GDALCloneWarpOptions( const GDALWarpOptions *psSrcOptions )
 
@@ -1034,12 +1349,11 @@ CPLXMLNode * CPL_STDCALL
 GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 
 {
-    CPLXMLNode *psTree;
-
 /* -------------------------------------------------------------------- */
 /*      Create root.                                                    */
 /* -------------------------------------------------------------------- */
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "GDALWarpOptions" );
+    CPLXMLNode *psTree =
+        CPLCreateXMLNode( NULL, CXT_Element, "GDALWarpOptions" );
 
 /* -------------------------------------------------------------------- */
 /*      WarpMemoryLimit                                                 */
@@ -1051,7 +1365,7 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 /* -------------------------------------------------------------------- */
 /*      ResampleAlg                                                     */
 /* -------------------------------------------------------------------- */
-    const char *pszAlgName;
+    const char *pszAlgName = NULL;
 
     if( psWO->eResampleAlg == GRA_NearestNeighbour )
         pszAlgName = "NearestNeighbour";
@@ -1086,7 +1400,6 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 /* -------------------------------------------------------------------- */
 /*      Working Data Type                                               */
 /* -------------------------------------------------------------------- */
-
     CPLCreateXMLElementAndValue(
         psTree, "WorkingDataType",
         GDALGetDataTypeName( psWO->eWorkingDataType ) );
@@ -1094,17 +1407,15 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 /* -------------------------------------------------------------------- */
 /*      Name/value warp options.                                        */
 /* -------------------------------------------------------------------- */
-    int iWO;
-
-    for( iWO = 0; psWO->papszWarpOptions != NULL
+    for( int iWO = 0; psWO->papszWarpOptions != NULL
              && psWO->papszWarpOptions[iWO] != NULL; iWO++ )
     {
         char *pszName = NULL;
         const char *pszValue =
             CPLParseNameValue( psWO->papszWarpOptions[iWO], &pszName );
 
-        /* EXTRA_ELTS is an internal detail that we will recover */
-        /* no need to serialize it */
+        // EXTRA_ELTS is an internal detail that we will recover
+        // no need to serialize it.
         if( !EQUAL(pszName, "EXTRA_ELTS") )
         {
             CPLXMLNode *psOption =
@@ -1128,7 +1439,8 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
             psTree, "SourceDataset",
             GDALGetDescription( psWO->hSrcDS ) );
 
-        char** papszOpenOptions = ((GDALDataset*)psWO->hSrcDS)->GetOpenOptions();
+        char** papszOpenOptions =
+            (static_cast<GDALDataset*>(psWO->hSrcDS))->GetOpenOptions();
         GDALSerializeOpenOptionsToXML(psTree, papszOpenOptions);
     }
 
@@ -1144,13 +1456,10 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 /* -------------------------------------------------------------------- */
     if( psWO->pfnTransformer != NULL )
     {
-        CPLXMLNode *psTransformerContainer;
-        CPLXMLNode *psTransformerTree;
-
-        psTransformerContainer =
+        CPLXMLNode *psTransformerContainer =
             CPLCreateXMLNode( psTree, CXT_Element, "Transformer" );
 
-        psTransformerTree =
+        CPLXMLNode *psTransformerTree =
             GDALSerializeTransformer( psWO->pfnTransformer,
                                       psWO->pTransformerArg );
 
@@ -1162,12 +1471,11 @@ GDALSerializeWarpOptions( const GDALWarpOptions *psWO )
 /*      Band count and lists.                                           */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psBandList = NULL;
-    int i;
 
     if( psWO->nBandCount != 0 )
         psBandList = CPLCreateXMLNode( psTree, CXT_Element, "BandList" );
 
-    for( i = 0; i < psWO->nBandCount; i++ )
+    for( int i = 0; i < psWO->nBandCount; i++ )
     {
         CPLXMLNode *psBand;
 
@@ -1270,7 +1578,7 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 /*      Verify this is the right kind of object.                        */
 /* -------------------------------------------------------------------- */
     if( psTree == NULL || psTree->eType != CXT_Element
-        || !EQUAL(psTree->pszValue,"GDALWarpOptions") )
+        || !EQUAL(psTree->pszValue, "GDALWarpOptions") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Wrong node, unable to deserialize GDALWarpOptions." );
@@ -1286,7 +1594,7 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 /*      Warp memory limit.                                              */
 /* -------------------------------------------------------------------- */
     psWO->dfWarpMemoryLimit =
-        CPLAtof(CPLGetXMLValue(psTree,"WarpMemoryLimit","0.0"));
+        CPLAtof(CPLGetXMLValue(psTree,"WarpMemoryLimit", "0.0"));
 
 /* -------------------------------------------------------------------- */
 /*      resample algorithm                                              */
@@ -1296,29 +1604,29 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 
     if( EQUAL(pszValue,"NearestNeighbour") )
         psWO->eResampleAlg = GRA_NearestNeighbour;
-    else if( EQUAL(pszValue,"Bilinear") )
+    else if( EQUAL(pszValue, "Bilinear") )
         psWO->eResampleAlg = GRA_Bilinear;
-    else if( EQUAL(pszValue,"Cubic") )
+    else if( EQUAL(pszValue, "Cubic") )
         psWO->eResampleAlg = GRA_Cubic;
-    else if( EQUAL(pszValue,"CubicSpline") )
+    else if( EQUAL(pszValue, "CubicSpline") )
         psWO->eResampleAlg = GRA_CubicSpline;
-    else if( EQUAL(pszValue,"Lanczos") )
+    else if( EQUAL(pszValue, "Lanczos") )
         psWO->eResampleAlg = GRA_Lanczos;
-    else if( EQUAL(pszValue,"Average") )
+    else if( EQUAL(pszValue, "Average") )
         psWO->eResampleAlg = GRA_Average;
-    else if( EQUAL(pszValue,"Mode") )
+    else if( EQUAL(pszValue, "Mode") )
         psWO->eResampleAlg = GRA_Mode;
-    else if( EQUAL(pszValue,"Maximum") )
+    else if( EQUAL(pszValue, "Maximum") )
         psWO->eResampleAlg = GRA_Max;
-    else if( EQUAL(pszValue,"Minimum") )
+    else if( EQUAL(pszValue, "Minimum") )
         psWO->eResampleAlg = GRA_Min;
-    else if( EQUAL(pszValue,"Median") )
+    else if( EQUAL(pszValue, "Median") )
         psWO->eResampleAlg = GRA_Med;
-    else if( EQUAL(pszValue,"Quartile1") )
+    else if( EQUAL(pszValue, "Quartile1") )
         psWO->eResampleAlg = GRA_Q1;
-    else if( EQUAL(pszValue,"Quartile3") )
+    else if( EQUAL(pszValue, "Quartile3") )
         psWO->eResampleAlg = GRA_Q3;
-    else if( EQUAL(pszValue,"Default") )
+    else if( EQUAL(pszValue, "Default") )
         /* leave as is */;
     else
     {
@@ -1337,12 +1645,12 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 /* -------------------------------------------------------------------- */
 /*      Name/value warp options.                                        */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psItem;
-
-    for( psItem = psTree->psChild; psItem != NULL; psItem = psItem->psNext )
+    for( CPLXMLNode *psItem = psTree->psChild;
+         psItem != NULL;
+         psItem = psItem->psNext )
     {
         if( psItem->eType == CXT_Element
-            && EQUAL(psItem->pszValue,"Option") )
+            && EQUAL(psItem->pszValue, "Option") )
         {
             const char *pszName = CPLGetXMLValue(psItem, "Name", NULL );
             pszValue = CPLGetXMLValue(psItem, "", NULL );
@@ -1365,15 +1673,16 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
     {
         char** papszOpenOptions = GDALDeserializeOpenOptionsFromXML(psTree);
         psWO->hSrcDS = GDALOpenEx(
-                    pszValue, GDAL_OF_SHARED | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL,
-                    (const char* const* )papszOpenOptions, NULL );
+            pszValue, GDAL_OF_SHARED | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR,
+            NULL,
+            (const char* const* )papszOpenOptions, NULL );
         CSLDestroy(papszOpenOptions);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Destination Dataset.                                            */
 /* -------------------------------------------------------------------- */
-    pszValue = CPLGetXMLValue(psTree,"DestinationDataset",NULL);
+    pszValue = CPLGetXMLValue(psTree, "DestinationDataset",NULL);
 
     if( pszValue != NULL )
         psWO->hDstDS = GDALOpenShared( pszValue, GA_Update );
@@ -1382,14 +1691,10 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 /*      First, count band mappings so we can establish the bandcount.   */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psBandTree = CPLGetXMLNode( psTree, "BandList" );
-    CPLXMLNode *psBand = NULL;
 
     psWO->nBandCount = 0;
 
-    if (psBandTree)
-        psBand = psBandTree->psChild;
-    else
-        psBand = NULL;
+    CPLXMLNode *psBand = psBandTree ? psBandTree->psChild : NULL;
 
     for( ; psBand != NULL; psBand = psBand->psNext )
     {
@@ -1405,10 +1710,7 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 /* ==================================================================== */
     int iBand = 0;
 
-    if (psBandTree)
-        psBand = psBandTree->psChild;
-    else
-        psBand = NULL;
+    psBand = psBandTree ? psBandTree->psChild : NULL;
 
     for( ; psBand != NULL; psBand = psBand->psNext )
     {
@@ -1420,11 +1722,12 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
 /*      Source band                                                     */
 /* -------------------------------------------------------------------- */
         if( psWO->panSrcBands == NULL )
-            psWO->panSrcBands = (int *)CPLMalloc(sizeof(int)*psWO->nBandCount);
+          psWO->panSrcBands = static_cast<int *>(
+              CPLMalloc(sizeof(int)*psWO->nBandCount));
 
         pszValue = CPLGetXMLValue(psBand,"src",NULL);
         if( pszValue == NULL )
-            psWO->panSrcBands[iBand] = iBand+1;
+            psWO->panSrcBands[iBand] = iBand + 1;
         else
             psWO->panSrcBands[iBand] = atoi(pszValue);
 
@@ -1435,8 +1738,8 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
         if( pszValue != NULL )
         {
             if( psWO->panDstBands == NULL )
-                psWO->panDstBands =
-                    (int *) CPLMalloc(sizeof(int)*psWO->nBandCount);
+                psWO->panDstBands = static_cast<int *>(
+                    CPLMalloc(sizeof(int)*psWO->nBandCount));
 
             psWO->panDstBands[iBand] = atoi(pszValue);
         }
@@ -1481,8 +1784,8 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
         if( pszValue != NULL )
         {
             if( psWO->padfDstNoDataImag == NULL )
-                psWO->padfDstNoDataImag =
-                    (double *) CPLCalloc(sizeof(double),psWO->nBandCount);
+              psWO->padfDstNoDataImag = static_cast<double *>(
+                  CPLCalloc(sizeof(double),psWO->nBandCount));
 
             psWO->padfDstNoDataImag[iBand] = CPLAtof(pszValue);
         }
@@ -1546,6 +1849,6 @@ GDALWarpOptions * CPL_STDCALL GDALDeserializeWarpOptions( CPLXMLNode *psTree )
         GDALDestroyWarpOptions( psWO );
         return NULL;
     }
-    else
-        return psWO;
+
+    return psWO;
 }
diff --git a/alg/gdalwarper.h b/alg/gdalwarper.h
index 9cf35ef..550f03b 100644
--- a/alg/gdalwarper.h
+++ b/alg/gdalwarper.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarper.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: gdalwarper.h 37035 2016-12-29 16:08:53Z goatbar $
  *
  * Project:  GDAL High Performance Warper
  * Purpose:  Prototypes, and definitions for warping related work.
@@ -55,7 +55,7 @@ typedef enum {
   /*! Lanczos windowed sinc interpolation (6x6 kernel) */ GRA_Lanczos=4,
   /*! Average (computes the average of all non-NODATA contributing pixels) */ GRA_Average=5,
   /*! Mode (selects the value which appears most often of all the sampled points) */ GRA_Mode=6,
-  // GRA_Gauss=7 reserved.
+  /*  GRA_Gauss=7 reserved. */
   /*! Max (selects maximum of all non-NODATA contributing pixels) */ GRA_Max=8,
   /*! Min (selects minimum of all non-NODATA contributing pixels) */ GRA_Min=9,
   /*! Med (selects median of all non-NODATA contributing pixels) */ GRA_Med=10,
@@ -73,6 +73,7 @@ typedef enum {
     /*! Quantile */ GWKAOM_Quant=6
 } GWKAverageOrModeAlg;
 
+/*! @cond Doxygen_Suppress */
 typedef int
 (*GDALMaskFunc)( void *pMaskFuncArg,
                  int nBandCount, GDALDataType eType,
@@ -109,6 +110,7 @@ GDALWarpCutlineMasker( void *pMaskFuncArg, int nBandCount, GDALDataType eType,
                        int nXOff, int nYOff, int nXSize, int nYSize,
                        GByte ** /* ppImageData */,
                        int bMaskIsFloat, void *pValidityMask );
+/*! @endcond */
 
 /************************************************************************/
 /*                           GDALWarpOptions                            */
@@ -130,7 +132,7 @@ typedef struct {
     GDALDataType        eWorkingDataType;
 
     /*! Source image dataset. */
-    GDALDatasetH	hSrcDS;
+    GDALDatasetH        hSrcDS;
 
     /*! Destination image dataset - may be NULL if only using GDALWarpOperation::WarpRegionToBuffer(). */
     GDALDatasetH        hDstDS;
@@ -175,25 +177,39 @@ typedef struct {
     /*! Handle to image transformer setup structure */
     void                *pTransformerArg;
 
+    /** Unused. Must be NULL */
     GDALMaskFunc       *papfnSrcPerBandValidityMaskFunc;
+    /** Unused. Must be NULL */
     void              **papSrcPerBandValidityMaskFuncArg;
 
+    /** Unused. Must be NULL */
     GDALMaskFunc        pfnSrcValidityMaskFunc;
+    /** Unused. Must be NULL */
     void               *pSrcValidityMaskFuncArg;
 
+    /** Unused. Must be NULL */
     GDALMaskFunc        pfnSrcDensityMaskFunc;
+    /** Unused. Must be NULL */
     void               *pSrcDensityMaskFuncArg;
 
+    /** Unused. Must be NULL */
     GDALMaskFunc        pfnDstDensityMaskFunc;
+    /** Unused. Must be NULL */
     void               *pDstDensityMaskFuncArg;
 
+    /** Unused. Must be NULL */
     GDALMaskFunc        pfnDstValidityMaskFunc;
+    /** Unused. Must be NULL */
     void               *pDstValidityMaskFuncArg;
 
+    /** Unused. Must be NULL */
     CPLErr              (*pfnPreWarpChunkProcessor)( void *pKern, void *pArg );
+    /** Unused. Must be NULL */
     void               *pPreWarpProcessorArg;
 
+    /** Unused. Must be NULL */
     CPLErr              (*pfnPostWarpChunkProcessor)( void *pKern, void *pArg);
+    /** Unused. Must be NULL */
     void               *pPostWarpProcessorArg;
 
     /*! Optional OGRPolygonH for a masking cutline. */
@@ -209,10 +225,12 @@ void CPL_DLL CPL_STDCALL GDALDestroyWarpOptions( GDALWarpOptions * );
 GDALWarpOptions CPL_DLL * CPL_STDCALL
 GDALCloneWarpOptions( const GDALWarpOptions * );
 
+/*! @cond Doxygen_Suppress */
 CPLXMLNode CPL_DLL * CPL_STDCALL
       GDALSerializeWarpOptions( const GDALWarpOptions * );
 GDALWarpOptions CPL_DLL * CPL_STDCALL
       GDALDeserializeWarpOptions( CPLXMLNode * );
+/*! @endcond */
 
 /************************************************************************/
 /*                         GDALReprojectImage()                         */
@@ -261,72 +279,112 @@ CPL_C_END
 /************************************************************************/
 /*                            GDALWarpKernel                            */
 /*                                                                      */
-/*      This class represents the lowest level of abstraction.  It      */
-/*      is holds the imagery for one "chunk" of a warp, and the         */
-/*      pre-prepared masks.  All IO is done before and after it's       */
-/*      operation.  This class is not normally used by the              */
-/*      application.                                                    */
-/************************************************************************/
 
-// This is the number of dummy pixels that must be reserved in source arrays
-// in order to satisfy assumptions made in GWKResample(), and more specifically
-// by GWKGetPixelRow() that always read a even number of pixels. So if we are
-// in the situation to read the last pixel of the source array, we need 1 extra
-// dummy pixel to avoid reading out of bounds.
+/** This is the number of dummy pixels that must be reserved in source arrays
+ * in order to satisfy assumptions made in GWKResample(), and more specifically
+ * by GWKGetPixelRow() that always read a even number of pixels. So if we are
+ * in the situation to read the last pixel of the source array, we need 1 extra
+ * dummy pixel to avoid reading out of bounds. */
 #define WARP_EXTRA_ELTS    1
 
+/** This class represents the lowest level of abstraction of warping.
+ *
+ * It holds the imagery for one "chunk" of a warp, and the
+ * pre-prepared masks.  All IO is done before and after its
+ * operation.  This class is not normally used by the
+ * application.
+ */
 class CPL_DLL GDALWarpKernel
 {
 public:
+    /** Warp options */
     char              **papszWarpOptions;
 
-    GDALResampleAlg	eResample;
+    /** Resample algorithm */
+    GDALResampleAlg     eResample;
+    /** Working data type */
     GDALDataType        eWorkingDataType;
+    /** Number of input and output bands (excluding alpha bands) */
     int                 nBands;
 
+    /** Width of the source image */
     int                 nSrcXSize;
+    /** Height of the source image */
     int                 nSrcYSize;
-    int                 nSrcXExtraSize; /* extra pixels (included in nSrcXSize) reserved for filter window. Should be ignored in scale computation */
-    int                 nSrcYExtraSize; /* extra pixels (included in nSrcYSize) reserved for filter window. Should be ignored in scale computation */
-    GByte               **papabySrcImage; /* each subarray must have WARP_EXTRA_ELTS at the end */
-
-    GUInt32           **papanBandSrcValid; /* each subarray must have WARP_EXTRA_ELTS at the end */
-    GUInt32            *panUnifiedSrcValid; /* must have WARP_EXTRA_ELTS at the end */
-    float              *pafUnifiedSrcDensity; /* must have WARP_EXTRA_ELTS at the end */
-
+    /** Extra pixels (included in nSrcXSize) reserved for filter window. Should be ignored in scale computation */
+    int                 nSrcXExtraSize;
+    /** Extra pixels (included in nSrcYSize) reserved for filter window. Should be ignored in scale computation */
+    int                 nSrcYExtraSize;
+    /** Array of nBands source images of size nSrcXSize * nSrcYSize. Each subarray must have WARP_EXTRA_ELTS at the end */
+    GByte               **papabySrcImage;
+
+    /** Array of nBands validity mask of size (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) / 8 */
+    GUInt32           **papanBandSrcValid;
+    /** Unified validity mask of size (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) / 8 */
+    GUInt32            *panUnifiedSrcValid;
+    /** Unified source density of size nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS */
+    float              *pafUnifiedSrcDensity;
+
+    /** Width of the destination image */
     int                 nDstXSize;
+    /** Height of the destination image */
     int                 nDstYSize;
+    /** Array of nBands destination images of size nDstXSize * nDstYSize */
     GByte             **papabyDstImage;
+    /** Validify mask of size (nDstXSize * nDstYSize) / 8 */
     GUInt32            *panDstValid;
+    /** Destination density of size nDstXSize * nDstYSize */
     float              *pafDstDensity;
 
-    double              dfXScale;   // Resampling scale, i.e.
-    double              dfYScale;   // nDstSize/nSrcSize.
-    double              dfXFilter;  // Size of filter kernel.
+    /** X resampling scale, i.e. nDstXSize / nSrcXSize */
+    double              dfXScale;
+    /** Y resampling scale, i.e. nDstYSize / nSrcYSize */
+    double              dfYScale;
+    /** X size of filter kernel */
+    double              dfXFilter;
+    /** Y size of filter kernel */
     double              dfYFilter;
-    int                 nXRadius;   // Size of window to filter.
+    /** X size of window to filter */
+    int                 nXRadius;
+    /** Y size of window to filter */
     int                 nYRadius;
-    int                 nFiltInitX; // Filtering offset
+    /** X filtering offset */
+    int                 nFiltInitX;
+    /** Y filtering offset */
     int                 nFiltInitY;
 
+    /** X offset of the source buffer regarding the top-left corner of the image */
     int                 nSrcXOff;
+    /** Y offset of the source buffer regarding the top-left corner of the image */
     int                 nSrcYOff;
 
+    /** X offset of the destination buffer regarding the top-left corner of the image */
     int                 nDstXOff;
+    /** Y offset of the destination buffer regarding the top-left corner of the image */
     int                 nDstYOff;
 
+    /** Pixel transformation function */
     GDALTransformerFunc pfnTransformer;
+    /** User data provided to pfnTransformer */
     void                *pTransformerArg;
 
+    /** Progress function */
     GDALProgressFunc    pfnProgress;
+    /** User data provided to pfnProgress */
     void                *pProgress;
 
+    /** Base/offset value for progress computation */
     double              dfProgressBase;
+    /** Scale value for progress computation */
     double              dfProgressScale;
 
+    /** Array of nBands value for destination nodata */
     double              *padfDstNoDataReal;
 
+/*! @cond Doxygen_Suppress */
+    /** Per-thread data. Internally set */
     void                *psThreadData;
+/*! @endcond */
 
                        GDALWarpKernel();
     virtual           ~GDALWarpKernel();
@@ -335,10 +393,12 @@ public:
     CPLErr              PerformWarp();
 };
 
+/*! @cond Doxygen_Suppress */
 void* GWKThreadsCreate(char** papszWarpOptions,
                        GDALTransformerFunc pfnTransformer,
                        void* pTransformerArg);
 void GWKThreadsEnd(void* psThreadDataIn);
+/*! @endcond */
 
 /************************************************************************/
 /*                         GDALWarpOperation()                          */
@@ -350,7 +410,9 @@ void GWKThreadsEnd(void* psThreadDataIn);
 /*      masks.  Actual resampling is done by the GDALWarpKernel.        */
 /************************************************************************/
 
+/*! @cond Doxygen_Suppress */
 typedef struct _GDALWarpChunk GDALWarpChunk;
+/*! @endcond */
 
 class CPL_DLL GDALWarpOperation {
 private:
@@ -366,7 +428,7 @@ private:
                                          int *pnSrcXExtraSize, int *pnSrcYExtraSize,
                                          double* pdfSrcFillRatio );
 
-    CPLErr          CreateKernelMask( GDALWarpKernel *, int iBand,
+    static CPLErr          CreateKernelMask( GDALWarpKernel *, int iBand,
                                       const char *pszType );
 
     CPLMutex        *hIOMutex;
@@ -430,6 +492,7 @@ public:
 
 CPL_C_START
 
+/** Opaque type representing a GDALWarpOperation object */
 typedef void * GDALWarpOperationH;
 
 GDALWarpOperationH CPL_DLL GDALCreateWarpOperation(const GDALWarpOptions* );
@@ -446,13 +509,16 @@ CPLErr CPL_DLL GDALWarpRegionToBuffer( GDALWarpOperationH, int, int, int, int,
 /*      Warping kernel functions                                        */
 /************************************************************************/
 
+/*! @cond Doxygen_Suppress */
 int GWKGetFilterRadius(GDALResampleAlg eResampleAlg);
 
 typedef double (*FilterFuncType)(double dfX);
 FilterFuncType GWKGetFilterFunc(GDALResampleAlg eResampleAlg);
 
+// TODO(schwehr): Can padfVals be a const pointer?
 typedef double (*FilterFunc4ValuesType)(double* padfVals);
 FilterFunc4ValuesType GWKGetFilterFunc4Values(GDALResampleAlg eResampleAlg);
+/*! @endcond */
 
 CPL_C_END
 
diff --git a/alg/gdalwarpkernel.cpp b/alg/gdalwarpkernel.cpp
index e9aa218..1e1d121 100644
--- a/alg/gdalwarpkernel.cpp
+++ b/alg/gdalwarpkernel.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalwarpkernel.cpp 36995 2016-12-22 11:36:36Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel class.  Implements the actual
@@ -30,38 +29,70 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <vector>
-#include <algorithm>
-#include <cmath>
-#include <cfloat>
+#include "cpl_port.h"
 #include "gdalwarper.h"
-#include "gdal_alg_priv.h"
-#include "cpl_string.h"
-#include "gdalwarpkernel_opencl.h"
-#include "cpl_atomic_ops.h"
-#include "cpl_worker_thread_pool.h"
+
+#include <cfloat>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
 #include <limits>
 #include <new>
+#include <vector>
+
+#include "cpl_atomic_ops.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "cpl_worker_thread_pool.h"
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "gdal_alg_priv.h"
+#include "gdalwarpkernel_opencl.h"
+
+// We restrict to 64bit processors because they are guaranteed to have SSE2.
+// Could possibly be used too on 32bit, but we would need to check at runtime.
+#if defined(__x86_64) || defined(_M_X64)
+#include <gdalsse_priv.h>
 
-CPL_CVSID("$Id: gdalwarpkernel.cpp 36995 2016-12-22 11:36:36Z rouault $");
+#if __SSE4_1__
+#include <smmintrin.h>
+#endif
+
+#if __SSE3__
+#include <pmmintrin.h>
+#endif
+
+#endif
+
+CPL_CVSID("$Id: gdalwarpkernel.cpp 37976 2017-04-13 12:34:40Z rouault $");
 
-//#define INSTANTIATE_FLOAT64_SSE2_IMPL
+static const double BAND_DENSITY_THRESHOLD = 0.0000000001;
+static const float SRC_DENSITY_THRESHOLD =  0.000000001f;
+
+// #define INSTANTIATE_FLOAT64_SSE2_IMPL
 
 static const int anGWKFilterRadius[] =
 {
-    0,      // Nearest neighbour
-    1,      // Bilinear
-    2,      // Cubic Convolution (Catmull-Rom)
-    2,      // Cubic B-Spline
-    3,      // Lanczos windowed sinc
-    0,      // Average
-    0,      // Mode
-    0,      // Reserved GRA_Gauss=7
-    0,      // Max
-    0,      // Min
-    0,      // Med
-    0,      // Q1
-    0,      // Q3
+    0,  // Nearest neighbour
+    1,  // Bilinear
+    2,  // Cubic Convolution (Catmull-Rom)
+    2,  // Cubic B-Spline
+    3,  // Lanczos windowed sinc
+    0,  // Average
+    0,  // Mode
+    0,  // Reserved GRA_Gauss=7
+    0,  // Max
+    0,  // Min
+    0,  // Med
+    0,  // Q1
+    0,  // Q3
 };
 
 static double GWKBilinear(double dfX);
@@ -76,16 +107,17 @@ static const FilterFuncType apfGWKFilter[] =
     GWKCubic,        // Cubic Convolution (Catmull-Rom)
     GWKBSpline,      // Cubic B-Spline
     GWKLanczosSinc,  // Lanczos windowed sinc
-    NULL,            // Average
-    NULL,            // Mode
-    NULL,      // Reserved GRA_Gauss=7
-    NULL,      // Max
-    NULL,      // Min
-    NULL,      // Med
-    NULL,      // Q1
-    NULL,      // Q3
+    NULL,  // Average
+    NULL,  // Mode
+    NULL,  // Reserved GRA_Gauss=7
+    NULL,  // Max
+    NULL,  // Min
+    NULL,  // Med
+    NULL,  // Q1
+    NULL,  // Q3
 };
 
+// TODO(schwehr): Can we make these functions have a const * const arg?
 static double GWKBilinear4Values(double* padfVals);
 static double GWKCubic4Values(double* padfVals);
 static double GWKBSpline4Values(double* padfVals);
@@ -93,19 +125,19 @@ static double GWKLanczosSinc4Values(double* padfVals);
 
 static const FilterFunc4ValuesType apfGWKFilter4Values[] =
 {
-    NULL,            // Nearest neighbour
+    NULL,  // Nearest neighbour
     GWKBilinear4Values,     // Bilinear
     GWKCubic4Values,        // Cubic Convolution (Catmull-Rom)
     GWKBSpline4Values,      // Cubic B-Spline
     GWKLanczosSinc4Values,  // Lanczos windowed sinc
-    NULL,            // Average
-    NULL,            // Mode
-    NULL,      // Reserved GRA_Gauss=7
-    NULL,      // Max
-    NULL,      // Min
-    NULL,      // Med
-    NULL,      // Q1
-    NULL,      // Q3
+    NULL,  // Average
+    NULL,  // Mode
+    NULL,  // Reserved GRA_Gauss=7
+    NULL,  // Max
+    NULL,  // Min
+    NULL,  // Med
+    NULL,  // Q1
+    NULL,  // Q3
 };
 
 int GWKGetFilterRadius(GDALResampleAlg eResampleAlg)
@@ -128,6 +160,7 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel * );
 #endif
 
 static CPLErr GWKGeneralCase( GDALWarpKernel * );
+static CPLErr GWKRealCase( GDALWarpKernel *poWK );
 static CPLErr GWKNearestNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK );
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK );
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK );
@@ -171,7 +204,7 @@ struct _GWKJobStruct
     int           (*pfnProgress)(GWKJobStruct* psJob);
     void           *pTransformerArg;
 
-    // Just used during thread initialization phase
+    // Just used during thread initialization phase.
     GDALTransformerFunc pfnTransformerInit;
     void           *pTransformerArgInit;
 } ;
@@ -180,11 +213,11 @@ struct _GWKJobStruct
 /*                        GWKProgressThread()                           */
 /************************************************************************/
 
-/* Return TRUE if the computation must be interrupted */
-static int GWKProgressThread(GWKJobStruct* psJob)
+// Return TRUE if the computation must be interrupted.
+static int GWKProgressThread( GWKJobStruct* psJob )
 {
     CPLAcquireMutex(psJob->hCondMutex, 1.0);
-    (*(psJob->pnCounter)) ++;
+    (*(psJob->pnCounter))++;
     CPLCondSignal(psJob->hCond);
     int bStop = *(psJob->pbStop);
     CPLReleaseMutex(psJob->hCondMutex);
@@ -196,13 +229,13 @@ static int GWKProgressThread(GWKJobStruct* psJob)
 /*                      GWKProgressMonoThread()                         */
 /************************************************************************/
 
-/* Return TRUE if the computation must be interrupted */
-static int GWKProgressMonoThread(GWKJobStruct* psJob)
+// Return TRUE if the computation must be interrupted.
+static int GWKProgressMonoThread( GWKJobStruct* psJob )
 {
     GDALWarpKernel *poWK = psJob->poWK;
     int nCounter = ++(*(psJob->pnCounter));
     if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
-                            (nCounter / (double) psJob->iYMax),
+                            (nCounter / static_cast<double>(psJob->iYMax)),
                             "", poWK->pProgress ) )
     {
         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -246,12 +279,16 @@ static void GWKThreadInitTransformer(void* pData)
 {
     GWKJobStruct* psJob = (GWKJobStruct*)pData;
     if( psJob->pTransformerArg == NULL )
-        psJob->pTransformerArg = GDALCloneTransformer(psJob->pTransformerArgInit);
+        psJob->pTransformerArg =
+            GDALCloneTransformer(psJob->pTransformerArgInit);
     if( psJob->pTransformerArg != NULL )
     {
-        // In case of lazy opening (for example RPCDEM), do a dummy transformation
-        // to be sure that the DEM is really opened with the context of this thread.
-        double dfX = 0.5, dfY = 0.5, dfZ = 0.0;
+        // In case of lazy opening (for example RPCDEM), do a dummy
+        // transformation to be sure that the DEM is really opened with the
+        // context of this thread.
+        double dfX = 0.5;
+        double dfY = 0.5;
+        double dfZ = 0.0;
         int bSuccess = FALSE;
         CPLPushErrorHandler(CPLQuietErrorHandler);
         psJob->pfnTransformerInit(psJob->pTransformerArg, TRUE, 1,
@@ -272,23 +309,27 @@ typedef struct
     CPLMutex* hCondMutex;
 } GWKThreadData;
 
-void* GWKThreadsCreate(char** papszWarpOptions,
-                       GDALTransformerFunc pfnTransformer, void* pTransformerArg)
+void* GWKThreadsCreate( char** papszWarpOptions,
+                        GDALTransformerFunc pfnTransformer,
+                        void* pTransformerArg )
 {
-    int nThreads;
-    const char* pszWarpThreads = CSLFetchNameValue(papszWarpOptions, "NUM_THREADS");
-    if (pszWarpThreads == NULL)
+    const char* pszWarpThreads =
+        CSLFetchNameValue(papszWarpOptions, "NUM_THREADS");
+    if( pszWarpThreads == NULL )
         pszWarpThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "1");
-    if (EQUAL(pszWarpThreads, "ALL_CPUS"))
+
+    int nThreads = 0;
+    if( EQUAL(pszWarpThreads, "ALL_CPUS") )
         nThreads = CPLGetNumCPUs();
     else
         nThreads = atoi(pszWarpThreads);
     if( nThreads <= 1 )
         nThreads = 0;
-    if (nThreads > 128)
+    if( nThreads > 128 )
         nThreads = 128;
 
-    GWKThreadData* psThreadData = (GWKThreadData*)VSI_CALLOC_VERBOSE(1,sizeof(GWKThreadData));
+    GWKThreadData* psThreadData = static_cast<GWKThreadData *>(
+        VSI_CALLOC_VERBOSE(1, sizeof(GWKThreadData)));
     if( psThreadData == NULL )
         return NULL;
 
@@ -300,12 +341,11 @@ void* GWKThreadsCreate(char** papszWarpOptions,
 /* -------------------------------------------------------------------- */
 /*      Duplicate pTransformerArg per thread.                           */
 /* -------------------------------------------------------------------- */
-        int i;
-        int bTransformerCloningSuccess = TRUE;
+        bool bTransformerCloningSuccess = true;
 
         psThreadData->hCond = hCond;
-        psThreadData->pasThreadJob =
-                (GWKJobStruct*)VSI_CALLOC_VERBOSE(sizeof(GWKJobStruct), nThreads);
+        psThreadData->pasThreadJob = static_cast<GWKJobStruct *>(
+            VSI_CALLOC_VERBOSE(sizeof(GWKJobStruct), nThreads));
         if( psThreadData->pasThreadJob == NULL )
         {
             GWKThreadsEnd(psThreadData);
@@ -321,7 +361,7 @@ void* GWKThreadsCreate(char** papszWarpOptions,
         CPLReleaseMutex(psThreadData->hCondMutex);
 
         std::vector<void*> apInitData;
-        for(i=0;i<nThreads;i++)
+        for( int i = 0; i < nThreads; i++ )
         {
             psThreadData->pasThreadJob[i].hCond = psThreadData->hCond;
             psThreadData->pasThreadJob[i].hCondMutex = psThreadData->hCondMutex;
@@ -344,22 +384,23 @@ void* GWKThreadsCreate(char** papszWarpOptions,
             return NULL;
         }
 
-        for(i=1;i<nThreads;i++)
+        for( int i = 1; i < nThreads; i++ )
         {
             if( psThreadData->pasThreadJob[i].pTransformerArg == NULL )
             {
                 CPLDebug("WARP", "Cannot deserialize transformer");
-                bTransformerCloningSuccess = FALSE;
+                bTransformerCloningSuccess = false;
                 break;
             }
         }
 
-        if (!bTransformerCloningSuccess)
+        if( !bTransformerCloningSuccess )
         {
-            for(i=1;i<nThreads;i++)
+            for( int i = 1; i < nThreads; i++ )
             {
                 if( psThreadData->pasThreadJob[i].pTransformerArg )
-                    GDALDestroyTransformer(psThreadData->pasThreadJob[i].pTransformerArg);
+                    GDALDestroyTransformer(psThreadData->
+                                           pasThreadJob[i].pTransformerArg);
             }
             CPLFree(psThreadData->pasThreadJob);
             psThreadData->pasThreadJob = NULL;
@@ -378,18 +419,20 @@ void* GWKThreadsCreate(char** papszWarpOptions,
 /*                             GWKThreadsEnd()                          */
 /************************************************************************/
 
-void GWKThreadsEnd(void* psThreadDataIn)
+void GWKThreadsEnd( void* psThreadDataIn )
 {
-    GWKThreadData* psThreadData = (GWKThreadData*)psThreadDataIn;
-    if( psThreadData == NULL )
+    if( psThreadDataIn == NULL )
         return;
+
+    GWKThreadData* psThreadData = static_cast<GWKThreadData *>(psThreadDataIn);
     if( psThreadData->poThreadPool )
     {
-        int nThreads = psThreadData->poThreadPool->GetThreadCount();
-        for(int i=1;i<nThreads;i++)
+        const int nThreads = psThreadData->poThreadPool->GetThreadCount();
+        for( int i = 1; i < nThreads; i++ )
         {
             if( psThreadData->pasThreadJob[i].pTransformerArg )
-                GDALDestroyTransformer(psThreadData->pasThreadJob[i].pTransformerArg);
+                GDALDestroyTransformer(psThreadData->
+                                       pasThreadJob[i].pTransformerArg);
         }
         delete psThreadData->poThreadPool;
     }
@@ -410,15 +453,15 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
                       void (*pfnFunc) (void *pUserData) )
 
 {
-    int nDstYSize = poWK->nDstYSize;
+    const int nDstYSize = poWK->nDstYSize;
 
-    CPLDebug( "GDAL", "GDALWarpKernel()::%s()\n"
-              "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
-              pszFuncName,
-              poWK->nSrcXOff, poWK->nSrcYOff,
-              poWK->nSrcXSize, poWK->nSrcYSize,
-              poWK->nDstXOff, poWK->nDstYOff,
-              poWK->nDstXSize, poWK->nDstYSize );
+    CPLDebug("GDAL", "GDALWarpKernel()::%s() "
+             "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
+             pszFuncName,
+             poWK->nSrcXOff, poWK->nSrcYOff,
+             poWK->nSrcXSize, poWK->nSrcYSize,
+             poWK->nDstXOff, poWK->nDstYOff,
+             poWK->nDstXSize, poWK->nDstYSize);
 
     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
     {
@@ -426,15 +469,15 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
         return CE_Failure;
     }
 
-    GWKThreadData* psThreadData = (GWKThreadData*)poWK->psThreadData;
+    GWKThreadData* psThreadData =
+        static_cast<GWKThreadData*>(poWK->psThreadData);
     if( psThreadData == NULL || psThreadData->poThreadPool == NULL )
     {
         return GWKGenericMonoThread(poWK, pfnFunc);
     }
 
-    int nThreads = psThreadData->poThreadPool->GetThreadCount();
-    if (nThreads >= nDstYSize / 2)
-        nThreads = nDstYSize / 2;
+    const int nThreads =
+        std::min(psThreadData->poThreadPool->GetThreadCount(), nDstYSize / 2);
 
     CPLDebug("WARP", "Using %d threads", nThreads);
 
@@ -446,12 +489,15 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 /* -------------------------------------------------------------------- */
 /*      Submit jobs                                                     */
 /* -------------------------------------------------------------------- */
-    for(int i=0;i<nThreads;i++)
+    for( int i = 0; i < nThreads; i++ )
     {
         psThreadData->pasThreadJob[i].poWK = poWK;
         psThreadData->pasThreadJob[i].pnCounter = &nCounter;
-        psThreadData->pasThreadJob[i].iYMin = (int)(((GIntBig)i) * nDstYSize / nThreads);
-        psThreadData->pasThreadJob[i].iYMax = (int)(((GIntBig)(i + 1)) * nDstYSize / nThreads);
+        psThreadData->pasThreadJob[i].iYMin =
+            static_cast<int>((static_cast<GIntBig>(i)) * nDstYSize / nThreads);
+        psThreadData->pasThreadJob[i].iYMax =
+            static_cast<int>((static_cast<GIntBig>(i + 1)) *
+                             nDstYSize / nThreads);
         psThreadData->pasThreadJob[i].pbStop = &bStop;
         if( poWK->pfnProgress != GDALDummyProgress )
             psThreadData->pasThreadJob[i].pfnProgress = GWKProgressThread;
@@ -466,13 +512,14 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
 /* -------------------------------------------------------------------- */
     if( poWK->pfnProgress != GDALDummyProgress )
     {
-        while(nCounter < nDstYSize)
+        while( nCounter < nDstYSize )
         {
             CPLCondWait(psThreadData->hCond, psThreadData->hCondMutex);
 
-            if( !poWK->pfnProgress( poWK->dfProgressBase + poWK->dfProgressScale *
-                                    (nCounter / (double) nDstYSize),
-                                    "", poWK->pProgress ) )
+            if( !poWK->pfnProgress(
+                    poWK->dfProgressBase + poWK->dfProgressScale *
+                    (nCounter / static_cast<double>(nDstYSize)),
+                    "", poWK->pProgress ) )
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
                 bStop = TRUE;
@@ -634,15 +681,15 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  * block of image data in left to right, then bottom to top order.  The actual
  * type of the image data is determined by GDALWarpKernel::eWorkingDataType.
  *
- * To access the pixel value for the (x=3,y=4) pixel (zero based) of
+ * To access the pixel value for the (x=3, y=4) pixel (zero based) of
  * the second band with eWorkingDataType set to GDT_Float32 use code like
  * this:
  *
  * \code
  *   float dfPixelValue;
- *   int   nBand = 1;  // band indexes are zero based.
- *   int   nPixel = 3; // zero based
- *   int   nLine = 4;  // zero based
+ *   int   nBand = 1;  // Band indexes are zero based.
+ *   int   nPixel = 3; // Zero based.
+ *   int   nLine = 4;  // Zero based.
  *
  *   assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
  *   assert( nLine >= 0 && nLine < poKern->nSrcYSize );
@@ -669,9 +716,9 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  *
  * \code
  *   int   bIsValid = TRUE;
- *   int   nBand = 1;  // band indexes are zero based.
- *   int   nPixel = 3; // zero based
- *   int   nLine = 4;  // zero based
+ *   int   nBand = 1;  // Band indexes are zero based.
+ *   int   nPixel = 3; // Zero based.
+ *   int   nLine = 4;  // Zero based.
  *
  *   assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
  *   assert( nLine >= 0 && nLine < poKern->nSrcYSize );
@@ -720,8 +767,8 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  *
  * \code
  *   float fDensity = 1.0;
- *   int   nPixel = 3; // zero based
- *   int   nLine = 4;  // zero based
+ *   int nPixel = 3;  // Zero based.
+ *   int nLine = 4;   // Zero based.
  *
  *   assert( nPixel >= 0 && nPixel < poKern->nSrcXSize );
  *   assert( nLine >= 0 && nLine < poKern->nSrcYSize );
@@ -757,15 +804,15 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  * block of image data in left to right, then bottom to top order.  The actual
  * type of the image data is determined by GDALWarpKernel::eWorkingDataType.
  *
- * To access the pixel value for the (x=3,y=4) pixel (zero based) of
+ * To access the pixel value for the (x=3, y=4) pixel (zero based) of
  * the second band with eWorkingDataType set to GDT_Float32 use code like
  * this:
  *
  * \code
  *   float dfPixelValue;
- *   int   nBand = 1;  // band indexes are zero based.
- *   int   nPixel = 3; // zero based
- *   int   nLine = 4;  // zero based
+ *   int   nBand = 1;  // Band indexes are zero based.
+ *   int   nPixel = 3; // Zero based.
+ *   int   nLine = 4;  // Zero based.
  *
  *   assert( nPixel >= 0 && nPixel < poKern->nDstXSize );
  *   assert( nLine >= 0 && nLine < poKern->nDstYSize );
@@ -803,8 +850,8 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  *
  * \code
  *   float fDensity = 1.0;
- *   int   nPixel = 3; // zero based
- *   int   nLine = 4;  // zero based
+ *   int   nPixel = 3; // Zero based.
+ *   int   nLine = 4;  // Zero based.
  *
  *   assert( nPixel >= 0 && nPixel < poKern->nDstXSize );
  *   assert( nLine >= 0 && nLine < poKern->nDstYSize );
@@ -910,61 +957,55 @@ static CPLErr GWKRun( GDALWarpKernel *poWK,
  * This field may be NULL if not required for the pfnProgress being used.
  */
 
-
 /************************************************************************/
 /*                           GDALWarpKernel()                           */
 /************************************************************************/
 
-GDALWarpKernel::GDALWarpKernel()
-
-{
-    eResample = GRA_NearestNeighbour;
-    eWorkingDataType = GDT_Unknown;
-    nBands = 0;
-    nDstXOff = 0;
-    nDstYOff = 0;
-    nDstXSize = 0;
-    nDstYSize = 0;
-    nSrcXOff = 0;
-    nSrcYOff = 0;
-    nSrcXSize = 0;
-    nSrcYSize = 0;
-    nSrcXExtraSize = 0;
-    nSrcYExtraSize = 0;
-    dfXScale = 1.0;
-    dfYScale = 1.0;
-    dfXFilter = 0.0;
-    dfYFilter = 0.0;
-    nXRadius = 0;
-    nYRadius = 0;
-    nFiltInitX = 0;
-    nFiltInitY = 0;
-    pafDstDensity = NULL;
-    pafUnifiedSrcDensity = NULL;
-    panDstValid = NULL;
-    panUnifiedSrcValid = NULL;
-    papabyDstImage = NULL;
-    papabySrcImage = NULL;
-    papanBandSrcValid = NULL;
-    pfnProgress = GDALDummyProgress;
-    pProgress = NULL;
-    dfProgressBase = 0.0;
-    dfProgressScale = 1.0;
-    pfnTransformer = NULL;
-    pTransformerArg = NULL;
-    papszWarpOptions = NULL;
-    padfDstNoDataReal = NULL;
-    psThreadData = NULL;
-}
+GDALWarpKernel::GDALWarpKernel() :
+    papszWarpOptions(NULL),
+    eResample(GRA_NearestNeighbour),
+    eWorkingDataType(GDT_Unknown),
+    nBands(0),
+    nSrcXSize(0),
+    nSrcYSize(0),
+    nSrcXExtraSize(0),
+    nSrcYExtraSize(0),
+    papabySrcImage(NULL),
+    papanBandSrcValid(NULL),
+    panUnifiedSrcValid(NULL),
+    pafUnifiedSrcDensity(NULL),
+    nDstXSize(0),
+    nDstYSize(0),
+    papabyDstImage(NULL),
+    panDstValid(NULL),
+    pafDstDensity(NULL),
+    dfXScale(1.0),
+    dfYScale(1.0),
+    dfXFilter(0.0),
+    dfYFilter(0.0),
+    nXRadius(0),
+    nYRadius(0),
+    nFiltInitX(0),
+    nFiltInitY(0),
+    nSrcXOff(0),
+    nSrcYOff(0),
+    nDstXOff(0),
+    nDstYOff(0),
+    pfnTransformer(NULL),
+    pTransformerArg(NULL),
+    pfnProgress(GDALDummyProgress),
+    pProgress(NULL),
+    dfProgressBase(0.0),
+    dfProgressScale(1.0),
+    padfDstNoDataReal(NULL),
+    psThreadData(NULL)
+{}
 
 /************************************************************************/
 /*                          ~GDALWarpKernel()                           */
 /************************************************************************/
 
-GDALWarpKernel::~GDALWarpKernel()
-
-{
-}
+GDALWarpKernel::~GDALWarpKernel() {}
 
 /************************************************************************/
 /*                            PerformWarp()                             */
@@ -981,16 +1022,16 @@ GDALWarpKernel::~GDALWarpKernel()
 CPLErr GDALWarpKernel::PerformWarp()
 
 {
-    CPLErr eErr;
+    const CPLErr eErr = Validate();
 
-    if( (eErr = Validate()) != CE_None )
+    if( eErr != CE_None )
         return eErr;
 
-    // See #2445 and #3079
-    if (nSrcXSize <= 0 || nSrcYSize <= 0)
+    // See #2445 and #3079.
+    if( nSrcXSize <= 0 || nSrcYSize <= 0 )
     {
-        if ( !pfnProgress( dfProgressBase + dfProgressScale,
-                           "", pProgress ) )
+        if( !pfnProgress( dfProgressBase + dfProgressScale,
+                          "", pProgress ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
             return CE_Failure;
@@ -1002,87 +1043,110 @@ CPLErr GDALWarpKernel::PerformWarp()
 /*      Pre-calculate resampling scales and window sizes for filtering. */
 /* -------------------------------------------------------------------- */
 
-    dfXScale = (double)nDstXSize / (nSrcXSize - nSrcXExtraSize);
-    dfYScale = (double)nDstYSize / (nSrcYSize - nSrcYExtraSize);
+    dfXScale = static_cast<double>(nDstXSize) / (nSrcXSize - nSrcXExtraSize);
+    dfYScale = static_cast<double>(nDstYSize) / (nSrcYSize - nSrcYExtraSize);
     if( nSrcXSize >= nDstXSize && nSrcXSize <= nDstXSize + nSrcXExtraSize )
-        dfXScale = 1;
+        dfXScale = 1.0;
     if( nSrcYSize >= nDstYSize && nSrcYSize <= nDstYSize + nSrcYExtraSize )
-        dfYScale = 1;
-    if( dfXScale < 1 )
+        dfYScale = 1.0;
+    if( dfXScale < 1.0 )
     {
-        double dfXReciprocalScale =  1. / dfXScale;
-        int nXReciprocalScale = (int)(dfXReciprocalScale + 0.5);
+        double dfXReciprocalScale =  1.0 / dfXScale;
+        const int nXReciprocalScale =
+            static_cast<int>(dfXReciprocalScale + 0.5);
         if( fabs(dfXReciprocalScale-nXReciprocalScale) < 0.05 )
             dfXScale = 1.0 / nXReciprocalScale;
     }
-    if( dfYScale < 1 )
+    if( dfYScale < 1.0 )
     {
-        double dfYReciprocalScale =  1. / dfYScale;
-        int nYReciprocalScale = (int)(dfYReciprocalScale + 0.5);
+        double dfYReciprocalScale =  1.0 / dfYScale;
+        const int nYReciprocalScale =
+            static_cast<int>(dfYReciprocalScale + 0.5);
         if( fabs(dfYReciprocalScale-nYReciprocalScale) < 0.05 )
             dfYScale = 1.0 / nYReciprocalScale;
     }
-    /*CPLDebug("WARP", "dfXScale = %f, dfYScale = %f", dfXScale, dfYScale);*/
 
-    int bUse4SamplesFormula = (dfXScale >= 0.95 && dfYScale >= 0.95);
+    // XSCALE and YSCALE undocumented for now. Can help in some cases
+    // Best would probably a per-pixel scale computation.
+    const char* pszXScale = CSLFetchNameValue(papszWarpOptions, "XSCALE");
+    if( pszXScale != NULL )
+        dfXScale = CPLAtof(pszXScale);
+    const char* pszYScale = CSLFetchNameValue(papszWarpOptions, "YSCALE");
+    if( pszYScale != NULL )
+        dfYScale = CPLAtof(pszYScale);
+
+#if DEBUG_VERBOSE
+    CPLDebug("WARP", "dfXScale = %f, dfYScale = %f", dfXScale, dfYScale);
+#endif
+
+    const int bUse4SamplesFormula = dfXScale >= 0.95 && dfYScale >= 0.95;
 
     // Safety check for callers that would use GDALWarpKernel without using
     // GDALWarpOperation.
     if( (eResample == GRA_CubicSpline || eResample == GRA_Lanczos ||
-         ((eResample == GRA_Cubic || eResample == GRA_Bilinear) && !bUse4SamplesFormula)) &&
-         atoi(CSLFetchNameValueDef(papszWarpOptions, "EXTRA_ELTS", "0") ) != WARP_EXTRA_ELTS )
+         ((eResample == GRA_Cubic || eResample == GRA_Bilinear) &&
+          !bUse4SamplesFormula)) &&
+        atoi(CSLFetchNameValueDef(papszWarpOptions,
+                                  "EXTRA_ELTS", "0") ) != WARP_EXTRA_ELTS )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Source arrays must have WARP_EXTRA_ELTS extra elements at their end. "
-                  "See GDALWarpKernel class definition. If this condition is fulfilled, "
-                  "define a EXTRA_ELTS=%d warp options", WARP_EXTRA_ELTS);
+                  "Source arrays must have WARP_EXTRA_ELTS extra elements at "
+                  "their end. "
+                  "See GDALWarpKernel class definition. If this condition is "
+                  "fulfilled, define a EXTRA_ELTS=%d warp options",
+                  WARP_EXTRA_ELTS);
         return CE_Failure;
     }
 
     dfXFilter = anGWKFilterRadius[eResample];
     dfYFilter = anGWKFilterRadius[eResample];
 
-    nXRadius = ( dfXScale < 1.0 ) ?
-        (int)ceil( dfXFilter / dfXScale ) :(int)dfXFilter;
-    nYRadius = ( dfYScale < 1.0 ) ?
-        (int)ceil( dfYFilter / dfYScale ) : (int)dfYFilter;
+    nXRadius =
+        dfXScale < 1.0
+        ? static_cast<int>(ceil(dfXFilter / dfXScale))
+        : static_cast<int>(dfXFilter);
+    nYRadius =
+        dfYScale < 1.0
+        ? static_cast<int>(ceil(dfYFilter / dfYScale))
+        : static_cast<int>(dfYFilter);
 
-    // Filter window offset depends on the parity of the kernel radius
+    // Filter window offset depends on the parity of the kernel radius.
     nFiltInitX = ((anGWKFilterRadius[eResample] + 1) % 2) - nXRadius;
     nFiltInitY = ((anGWKFilterRadius[eResample] + 1) % 2) - nYRadius;
 
 /* -------------------------------------------------------------------- */
 /*      Set up resampling functions.                                    */
 /* -------------------------------------------------------------------- */
-    if( CSLFetchBoolean( papszWarpOptions, "USE_GENERAL_CASE", FALSE ) )
+    if( CPLFetchBool( papszWarpOptions, "USE_GENERAL_CASE", false ) )
         return GWKGeneralCase( this );
 
 #if defined(HAVE_OPENCL)
-    if((eWorkingDataType == GDT_Byte
-        || eWorkingDataType == GDT_CInt16
-        || eWorkingDataType == GDT_UInt16
-        || eWorkingDataType == GDT_Int16
-        || eWorkingDataType == GDT_CFloat32
-        || eWorkingDataType == GDT_Float32) &&
-       (eResample == GRA_Bilinear
-        || eResample == GRA_Cubic
-        || eResample == GRA_CubicSpline
-        || eResample == GRA_Lanczos) &&
-        CSLFetchBoolean( papszWarpOptions, "USE_OPENCL", TRUE ))
+    if( (eWorkingDataType == GDT_Byte
+         || eWorkingDataType == GDT_CInt16
+         || eWorkingDataType == GDT_UInt16
+         || eWorkingDataType == GDT_Int16
+         || eWorkingDataType == GDT_CFloat32
+         || eWorkingDataType == GDT_Float32) &&
+        (eResample == GRA_Bilinear
+         || eResample == GRA_Cubic
+         || eResample == GRA_CubicSpline
+         || eResample == GRA_Lanczos) &&
+        CPLFetchBool( papszWarpOptions, "USE_OPENCL", true ) )
     {
-        CPLErr eResult = GWKOpenCLCase( this );
+        const CPLErr eResult = GWKOpenCLCase( this );
 
         // CE_Warning tells us a suitable OpenCL environment was not available
         // so we fall through to other CPU based methods.
         if( eResult != CE_Warning )
             return eResult;
     }
-#endif /* defined HAVE_OPENCL */
+#endif  // defined HAVE_OPENCL
 
-    int bNoMasksOrDstDensityOnly = (papanBandSrcValid == NULL
+    const bool bNoMasksOrDstDensityOnly =
+        papanBandSrcValid == NULL
         && panUnifiedSrcValid == NULL
         && pafUnifiedSrcDensity == NULL
-        && panDstValid == NULL );
+        && panDstValid == NULL;
 
     if( eWorkingDataType == GDT_Byte
         && eResample == GRA_NearestNeighbour
@@ -1199,6 +1263,9 @@ CPLErr GDALWarpKernel::PerformWarp()
     if( eResample == GRA_Q3 )
         return GWKAverageOrMode( this );
 
+    if( !GDALDataTypeIsComplex(eWorkingDataType) )
+        return GWKRealCase( this );
+
     return GWKGeneralCase( this );
 }
 
@@ -1222,11 +1289,12 @@ CPLErr GDALWarpKernel::PerformWarp()
 CPLErr GDALWarpKernel::Validate()
 
 {
-    if ( (size_t)eResample >=
-         (sizeof(anGWKFilterRadius) / sizeof(anGWKFilterRadius[0])) )
+    if( static_cast<size_t>(eResample) >=
+        (sizeof(anGWKFilterRadius) / sizeof(anGWKFilterRadius[0])) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unsupported resampling method %d.", (int) eResample );
+                  "Unsupported resampling method %d.",
+                  static_cast<int>(eResample) );
         return CE_Failure;
     }
 
@@ -1294,9 +1362,9 @@ template<> double GWKRoundValueT<double>(double dfValue)
 template<class T>
 static CPL_INLINE T GWKClampValueT(double dfValue)
 {
-    if (dfValue < std::numeric_limits<T>::min())
+    if( dfValue < std::numeric_limits<T>::min() )
         return std::numeric_limits<T>::min();
-    else if (dfValue > std::numeric_limits<T>::max())
+    else if( dfValue > std::numeric_limits<T>::max() )
         return std::numeric_limits<T>::max();
     else
         return GWKRoundValueT<T>(dfValue);
@@ -1319,11 +1387,11 @@ template<> double GWKClampValueT<double>(double dfValue)
 /************************************************************************/
 
 template<class T>
-static int GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand,
-                         int iDstOffset, double dfDensity,
-                         T value)
+static bool GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand,
+                                   int iDstOffset, double dfDensity,
+                                   T value)
 {
-    T *pDst = (T*)(poWK->papabyDstImage[iBand]);
+    T *pDst = reinterpret_cast<T*>(poWK->papabyDstImage[iBand]);
 
 /* -------------------------------------------------------------------- */
 /*      If the source density is less than 100% we need to fetch the    */
@@ -1336,10 +1404,10 @@ static int GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand,
 /* -------------------------------------------------------------------- */
     if( dfDensity < 0.9999 )
     {
-        double dfDstReal, dfDstDensity = 1.0;
-
         if( dfDensity < 0.0001 )
-            return TRUE;
+            return true;
+
+        double dfDstDensity = 1.0;
 
         if( poWK->pafDstDensity != NULL )
             dfDstDensity = poWK->pafDstDensity[iDstOffset];
@@ -1350,14 +1418,15 @@ static int GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand,
 
         // It seems like we also ought to be testing panDstValid[] here!
 
-        dfDstReal = pDst[iDstOffset];
+        const double dfDstReal = pDst[iDstOffset];
 
-        // the destination density is really only relative to the portion
+        // The destination density is really only relative to the portion
         // not occluded by the overlay.
-        double dfDstInfluence = (1.0 - dfDensity) * dfDstDensity;
+        const double dfDstInfluence = (1.0 - dfDensity) * dfDstDensity;
 
-        double dfReal = (value * dfDensity + dfDstReal * dfDstInfluence)
-                            / (dfDensity + dfDstInfluence);
+        const double dfReal =
+            (value * dfDensity + dfDstReal * dfDstInfluence)
+            / (dfDensity + dfDstInfluence);
 
 /* -------------------------------------------------------------------- */
 /*      Actually apply the destination value.                           */
@@ -1368,27 +1437,30 @@ static int GWKSetPixelValueRealT( GDALWarpKernel *poWK, int iBand,
         pDst[iDstOffset] = GWKClampValueT<T>(dfReal);
     }
     else
+    {
         pDst[iDstOffset] = value;
+    }
 
-    if (poWK->padfDstNoDataReal != NULL &&
-        poWK->padfDstNoDataReal[iBand] == (double)pDst[iDstOffset])
+    if( poWK->padfDstNoDataReal != NULL &&
+        poWK->padfDstNoDataReal[iBand] ==
+        static_cast<double>(pDst[iDstOffset]) )
     {
-        if (pDst[iDstOffset] == std::numeric_limits<T>::min())
+        if( pDst[iDstOffset] == std::numeric_limits<T>::min() )
             pDst[iDstOffset] = std::numeric_limits<T>::min() + 1;
         else
-            pDst[iDstOffset] --;
+            pDst[iDstOffset]--;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                          GWKSetPixelValue()                          */
 /************************************************************************/
 
-static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
-                             int iDstOffset, double dfDensity,
-                             double dfReal, double dfImag )
+static bool GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
+                              int iDstOffset, double dfDensity,
+                              double dfReal, double dfImag )
 
 {
     GByte *pabyDst = poWK->papabyDstImage[iBand];
@@ -1404,11 +1476,10 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
 /* -------------------------------------------------------------------- */
     if( dfDensity < 0.9999 )
     {
-        double dfDstReal, dfDstImag, dfDstDensity = 1.0;
-
         if( dfDensity < 0.0001 )
-            return TRUE;
+            return true;
 
+        double dfDstDensity = 1.0;
         if( poWK->pafDstDensity != NULL )
             dfDstDensity = poWK->pafDstDensity[iDstOffset];
         else if( poWK->panDstValid != NULL
@@ -1416,8 +1487,11 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
                        & (0x01 << (iDstOffset & 0x1f))) ) )
             dfDstDensity = 0.0;
 
+        double dfDstReal = 0.0;
+        double dfDstImag = 0.0;
         // It seems like we also ought to be testing panDstValid[] here!
 
+        // TODO(schwehr): Factor out this repreated type of set.
         switch( poWK->eWorkingDataType )
         {
           case GDT_Byte:
@@ -1476,19 +1550,21 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
             break;
 
           default:
-            CPLAssert( FALSE );
+            CPLAssert( false );
             dfDstDensity = 0.0;
-            return FALSE;
+            return false;
         }
 
-        // the destination density is really only relative to the portion
+        // The destination density is really only relative to the portion
         // not occluded by the overlay.
-        double dfDstInfluence = (1.0 - dfDensity) * dfDstDensity;
+        const double dfDstInfluence = (1.0 - dfDensity) * dfDstDensity;
 
-        dfReal = (dfReal * dfDensity + dfDstReal * dfDstInfluence)
+        dfReal =
+            (dfReal * dfDensity + dfDstReal * dfDstInfluence)
             / (dfDensity + dfDstInfluence);
 
-        dfImag = (dfImag * dfDensity + dfDstImag * dfDstInfluence)
+        dfImag =
+            (dfImag * dfDensity + dfDstImag * dfDstInfluence)
             / (dfDensity + dfDstInfluence);
     }
 
@@ -1499,44 +1575,52 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
 /*      if by chance it is equal to the computed pixel value.           */
 /* -------------------------------------------------------------------- */
 
-#define CLAMP(type,minval,maxval) \
+// TODO(schwehr): Can we make this a template?
+#define CLAMP(type) \
     do { \
-    if (dfReal < minval) ((type *) pabyDst)[iDstOffset] = (type)minval; \
-    else if (dfReal > maxval) ((type *) pabyDst)[iDstOffset] = (type)maxval; \
-    else ((type *) pabyDst)[iDstOffset] = (minval < 0) ? (type)floor(dfReal + 0.5) : (type)(dfReal + 0.5);  \
-    if (poWK->padfDstNoDataReal != NULL && \
-        poWK->padfDstNoDataReal[iBand] == (double)((type *) pabyDst)[iDstOffset]) \
+    type* _pDst = reinterpret_cast<type*>(pabyDst); \
+    if( dfReal < static_cast<double>(std::numeric_limits<type>::min()) ) \
+        _pDst[iDstOffset] = static_cast<type>(std::numeric_limits<type>::min()); \
+    else if( dfReal > static_cast<double>(std::numeric_limits<type>::max()) ) \
+        _pDst[iDstOffset] = static_cast<type>(std::numeric_limits<type>::max()); \
+    else \
+        _pDst[iDstOffset] = \
+            (std::numeric_limits<type>::is_signed) ? \
+                static_cast<type>(floor(dfReal + 0.5)) : \
+                static_cast<type>(dfReal + 0.5);  \
+    if( poWK->padfDstNoDataReal != NULL && \
+        poWK->padfDstNoDataReal[iBand] == static_cast<double>(_pDst[iDstOffset]) ) \
     { \
-        if (((type *) pabyDst)[iDstOffset] == minval)  \
-            ((type *) pabyDst)[iDstOffset] = (type)(minval + 1); \
+        if( _pDst[iDstOffset] == static_cast<type>(std::numeric_limits<type>::min()) )  \
+            _pDst[iDstOffset] = static_cast<type>(std::numeric_limits<type>::min() + 1); \
         else \
-            ((type *) pabyDst)[iDstOffset] --; \
-    } } while(0)
+            _pDst[iDstOffset]--; \
+    } } while( false )
 
     switch( poWK->eWorkingDataType )
     {
       case GDT_Byte:
-        CLAMP(GByte, 0.0, 255.0);
+        CLAMP(GByte);
         break;
 
       case GDT_Int16:
-        CLAMP(GInt16, -32768.0, 32767.0);
+        CLAMP(GInt16);
         break;
 
       case GDT_UInt16:
-        CLAMP(GUInt16, 0.0, 65535.0);
+        CLAMP(GUInt16);
         break;
 
       case GDT_UInt32:
-        CLAMP(GUInt32, 0.0, 4294967295.0);
+        CLAMP(GUInt32);
         break;
 
       case GDT_Int32:
-        CLAMP(GInt32, -2147483648.0, 2147483647.0);
+        CLAMP(GInt32);
         break;
 
       case GDT_Float32:
-        ((float *) pabyDst)[iDstOffset] = (float) dfReal;
+        ((float *) pabyDst)[iDstOffset] = static_cast<float>(dfReal);
         break;
 
       case GDT_Float64:
@@ -1544,34 +1628,40 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
         break;
 
       case GDT_CInt16:
-        if( dfReal < -32768 )
-            ((GInt16 *) pabyDst)[iDstOffset*2] = -32768;
-        else if( dfReal > 32767 )
-            ((GInt16 *) pabyDst)[iDstOffset*2] = 32767;
+      {
+        typedef GInt16 T;
+        if( dfReal < static_cast<double>(std::numeric_limits<T>::min()) )
+            ((T *) pabyDst)[iDstOffset*2] = std::numeric_limits<T>::min();
+        else if( dfReal > static_cast<double>(std::numeric_limits<T>::max()) )
+            ((T *) pabyDst)[iDstOffset*2] = std::numeric_limits<T>::max();
         else
-            ((GInt16 *) pabyDst)[iDstOffset*2] = (GInt16) floor(dfReal+0.5);
-        if( dfImag < -32768 )
-            ((GInt16 *) pabyDst)[iDstOffset*2+1] = -32768;
-        else if( dfImag > 32767 )
-            ((GInt16 *) pabyDst)[iDstOffset*2+1] = 32767;
+            ((T *) pabyDst)[iDstOffset*2] = static_cast<T>(floor(dfReal+0.5));
+        if( dfImag < static_cast<double>(std::numeric_limits<T>::min()) )
+            ((T *) pabyDst)[iDstOffset*2+1] =  std::numeric_limits<T>::min();
+        else if( dfImag > static_cast<double>(std::numeric_limits<T>::max()) )
+            ((T *) pabyDst)[iDstOffset*2+1] = std::numeric_limits<T>::max();
         else
-            ((GInt16 *) pabyDst)[iDstOffset*2+1] = (GInt16) floor(dfImag+0.5);
+            ((T *) pabyDst)[iDstOffset*2+1] = static_cast<T>(floor(dfImag+0.5));
         break;
+      }
 
       case GDT_CInt32:
-        if( dfReal < -2147483648.0 )
-            ((GInt32 *) pabyDst)[iDstOffset*2] = (GInt32) -2147483648.0;
-        else if( dfReal > 2147483647.0 )
-            ((GInt32 *) pabyDst)[iDstOffset*2] = (GInt32) 2147483647.0;
+      {
+        typedef GInt32 T;
+        if( dfReal < static_cast<double>(std::numeric_limits<T>::min()) )
+            ((T *) pabyDst)[iDstOffset*2] = std::numeric_limits<T>::min();
+        else if( dfReal > static_cast<double>(std::numeric_limits<T>::max()) )
+            ((T *) pabyDst)[iDstOffset*2] = std::numeric_limits<T>::max();
         else
-            ((GInt32 *) pabyDst)[iDstOffset*2] = (GInt32) floor(dfReal+0.5);
-        if( dfImag < -2147483648.0 )
-            ((GInt32 *) pabyDst)[iDstOffset*2+1] = (GInt32) -2147483648.0;
-        else if( dfImag > 2147483647.0 )
-            ((GInt32 *) pabyDst)[iDstOffset*2+1] = (GInt32) 2147483647.0;
+            ((T *) pabyDst)[iDstOffset*2] = static_cast<T>(floor(dfReal+0.5));
+        if( dfImag < static_cast<double>(std::numeric_limits<T>::min()) )
+            ((T *) pabyDst)[iDstOffset*2+1] = std::numeric_limits<T>::min();
+        else if( dfImag > static_cast<double>(std::numeric_limits<T>::max()) )
+            ((T *) pabyDst)[iDstOffset*2+1] = std::numeric_limits<T>::max();
         else
-            ((GInt32 *) pabyDst)[iDstOffset*2+1] = (GInt32) floor(dfImag+0.5);
+            ((T *) pabyDst)[iDstOffset*2+1] = static_cast<T>(floor(dfImag+0.5));
         break;
+      }
 
       case GDT_CFloat32:
         ((float *) pabyDst)[iDstOffset*2] = (float) dfReal;
@@ -1584,10 +1674,136 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
         break;
 
       default:
-        return FALSE;
+        return false;
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                       GWKSetPixelValueReal()                         */
+/************************************************************************/
+
+static bool GWKSetPixelValueReal( GDALWarpKernel *poWK, int iBand,
+                                  int iDstOffset, double dfDensity,
+                                  double dfReal )
+
+{
+    GByte *pabyDst = poWK->papabyDstImage[iBand];
+
+/* -------------------------------------------------------------------- */
+/*      If the source density is less than 100% we need to fetch the    */
+/*      existing destination value, and mix it with the source to       */
+/*      get the new "to apply" value.  Also compute composite           */
+/*      density.                                                        */
+/*                                                                      */
+/*      We avoid mixing if density is very near one or risk mixing      */
+/*      in very extreme nodata values and causing odd results (#1610)   */
+/* -------------------------------------------------------------------- */
+    if( dfDensity < 0.9999 )
+    {
+        if( dfDensity < 0.0001 )
+            return true;
+
+        double dfDstReal = 0.0;
+        double dfDstDensity = 1.0;
+
+        if( poWK->pafDstDensity != NULL )
+            dfDstDensity = poWK->pafDstDensity[iDstOffset];
+        else if( poWK->panDstValid != NULL
+                 && !((poWK->panDstValid[iDstOffset>>5]
+                       & (0x01 << (iDstOffset & 0x1f))) ) )
+            dfDstDensity = 0.0;
+
+        // It seems like we also ought to be testing panDstValid[] here!
+
+        switch( poWK->eWorkingDataType )
+        {
+          case GDT_Byte:
+            dfDstReal = pabyDst[iDstOffset];
+            break;
+
+          case GDT_Int16:
+            dfDstReal = ((GInt16 *) pabyDst)[iDstOffset];
+            break;
+
+          case GDT_UInt16:
+            dfDstReal = ((GUInt16 *) pabyDst)[iDstOffset];
+            break;
+
+          case GDT_Int32:
+            dfDstReal = ((GInt32 *) pabyDst)[iDstOffset];
+            break;
+
+          case GDT_UInt32:
+            dfDstReal = ((GUInt32 *) pabyDst)[iDstOffset];
+            break;
+
+          case GDT_Float32:
+            dfDstReal = ((float *) pabyDst)[iDstOffset];
+            break;
+
+          case GDT_Float64:
+            dfDstReal = ((double *) pabyDst)[iDstOffset];
+            break;
+
+          default:
+            CPLAssert( false );
+            dfDstDensity = 0.0;
+            return false;
+        }
+
+        // The destination density is really only relative to the portion
+        // not occluded by the overlay.
+        const double dfDstInfluence = (1.0 - dfDensity) * dfDstDensity;
+
+        dfReal =
+            (dfReal * dfDensity + dfDstReal * dfDstInfluence)
+            / (dfDensity + dfDstInfluence);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Actually apply the destination value.                           */
+/*                                                                      */
+/*      Avoid using the destination nodata value for integer datatypes  */
+/*      if by chance it is equal to the computed pixel value.           */
+/* -------------------------------------------------------------------- */
+
+    switch( poWK->eWorkingDataType )
+    {
+      case GDT_Byte:
+        CLAMP(GByte);
+        break;
+
+      case GDT_Int16:
+        CLAMP(GInt16);
+        break;
+
+      case GDT_UInt16:
+        CLAMP(GUInt16);
+        break;
+
+      case GDT_UInt32:
+        CLAMP(GUInt32);
+        break;
+
+      case GDT_Int32:
+        CLAMP(GInt32);
+        break;
+
+      case GDT_Float32:
+        ((float *) pabyDst)[iDstOffset] = static_cast<float>(dfReal);
+        break;
+
+      case GDT_Float64:
+        ((double *) pabyDst)[iDstOffset] = dfReal;
+        break;
+
+      default:
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1596,9 +1812,9 @@ static int GWKSetPixelValue( GDALWarpKernel *poWK, int iBand,
 
 /* It is assumed that panUnifiedSrcValid has been checked before */
 
-static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand,
-                             int iSrcOffset, double *pdfDensity,
-                             double *pdfReal, double *pdfImag )
+static bool GWKGetPixelValue( GDALWarpKernel *poWK, int iBand,
+                              int iSrcOffset, double *pdfDensity,
+                              double *pdfReal, double *pdfImag )
 
 {
     GByte *pabySrc = poWK->papabySrcImage[iBand];
@@ -1609,9 +1825,10 @@ static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand,
               & (0x01 << (iSrcOffset & 0x1f)))) )
     {
         *pdfDensity = 0.0;
-        return FALSE;
+        return false;
     }
 
+    // TODO(schwehr): Fix casting.
     switch( poWK->eWorkingDataType )
     {
       case GDT_Byte:
@@ -1671,7 +1888,70 @@ static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand,
 
       default:
         *pdfDensity = 0.0;
-        return FALSE;
+        return false;
+    }
+
+    if( poWK->pafUnifiedSrcDensity != NULL )
+        *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
+    else
+        *pdfDensity = 1.0;
+
+    return *pdfDensity != 0.0;
+}
+
+/************************************************************************/
+/*                       GWKGetPixelValueReal()                         */
+/************************************************************************/
+
+static bool GWKGetPixelValueReal( GDALWarpKernel *poWK, int iBand,
+                                  int iSrcOffset, double *pdfDensity,
+                                  double *pdfReal )
+
+{
+    GByte *pabySrc = poWK->papabySrcImage[iBand];
+
+    if( poWK->papanBandSrcValid != NULL
+        && poWK->papanBandSrcValid[iBand] != NULL
+        && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
+              & (0x01 << (iSrcOffset & 0x1f)))) )
+    {
+        *pdfDensity = 0.0;
+        return false;
+    }
+
+    switch( poWK->eWorkingDataType )
+    {
+      case GDT_Byte:
+        *pdfReal = pabySrc[iSrcOffset];
+        break;
+
+      case GDT_Int16:
+        *pdfReal = ((GInt16 *) pabySrc)[iSrcOffset];
+        break;
+
+      case GDT_UInt16:
+        *pdfReal = ((GUInt16 *) pabySrc)[iSrcOffset];
+        break;
+
+      case GDT_Int32:
+        *pdfReal = ((GInt32 *) pabySrc)[iSrcOffset];
+        break;
+
+      case GDT_UInt32:
+        *pdfReal = ((GUInt32 *) pabySrc)[iSrcOffset];
+        break;
+
+      case GDT_Float32:
+        *pdfReal = ((float *) pabySrc)[iSrcOffset];
+        break;
+
+      case GDT_Float64:
+        *pdfReal = ((double *) pabySrc)[iSrcOffset];
+        break;
+
+      default:
+        CPLAssert(false);
+        return false;
     }
 
     if( poWK->pafUnifiedSrcDensity != NULL )
@@ -1689,84 +1969,84 @@ static int GWKGetPixelValue( GDALWarpKernel *poWK, int iBand,
 /* It is assumed that adfImag[] is set to 0 by caller code for non-complex */
 /* data-types. */
 
-static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
-                           int iSrcOffset, int nHalfSrcLen,
-                           double* padfDensity,
-                           double adfReal[],
-                           double* padfImag )
+static bool GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
+                            int iSrcOffset, int nHalfSrcLen,
+                            double* padfDensity,
+                            double adfReal[],
+                            double* padfImag )
 {
-    // We know that nSrcLen is even, so we can *always* unroll loops 2x
-    int     nSrcLen = nHalfSrcLen * 2;
-    int     bHasValid = FALSE;
-    int     i;
+    // We know that nSrcLen is even, so we can *always* unroll loops 2x.
+    const int nSrcLen = nHalfSrcLen * 2;
+    bool bHasValid = false;
 
     if( padfDensity != NULL )
     {
-        // Init the density
-        for ( i = 0; i < nSrcLen; i += 2 )
+        // Init the density.
+        for( int i = 0; i < nSrcLen; i += 2 )
         {
             padfDensity[i] = 1.0;
             padfDensity[i+1] = 1.0;
         }
 
-        if ( poWK->panUnifiedSrcValid != NULL )
+        if( poWK->panUnifiedSrcValid != NULL )
         {
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
-                if(poWK->panUnifiedSrcValid[(iSrcOffset+i)>>5]
-                & (0x01 << ((iSrcOffset+i) & 0x1f)))
-                    bHasValid = TRUE;
+                if( poWK->panUnifiedSrcValid[(iSrcOffset+i)>>5]
+                    & (0x01 << ((iSrcOffset+i) & 0x1f)) )
+                    bHasValid = true;
                 else
                     padfDensity[i] = 0.0;
 
-                if(poWK->panUnifiedSrcValid[(iSrcOffset+i+1)>>5]
-                & (0x01 << ((iSrcOffset+i+1) & 0x1f)))
-                    bHasValid = TRUE;
+                if( poWK->panUnifiedSrcValid[(iSrcOffset+i+1)>>5]
+                    & (0x01 << ((iSrcOffset+i+1) & 0x1f)) )
+                    bHasValid = true;
                 else
                     padfDensity[i+1] = 0.0;
             }
 
-            // Reset or fail as needed
-            if ( bHasValid )
-                bHasValid = FALSE;
+            // Reset or fail as needed.
+            if( bHasValid )
+                bHasValid = false;
             else
-                return FALSE;
+                return false;
         }
 
-        if ( poWK->papanBandSrcValid != NULL
-            && poWK->papanBandSrcValid[iBand] != NULL)
+        if( poWK->papanBandSrcValid != NULL
+            && poWK->papanBandSrcValid[iBand] != NULL )
         {
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
-                if(poWK->papanBandSrcValid[iBand][(iSrcOffset+i)>>5]
-                & (0x01 << ((iSrcOffset+i) & 0x1f)))
-                    bHasValid = TRUE;
+                if( poWK->papanBandSrcValid[iBand][(iSrcOffset+i)>>5]
+                    & (0x01 << ((iSrcOffset+i) & 0x1f)) )
+                    bHasValid = true;
                 else
                     padfDensity[i] = 0.0;
 
-                if(poWK->papanBandSrcValid[iBand][(iSrcOffset+i+1)>>5]
-                & (0x01 << ((iSrcOffset+i+1) & 0x1f)))
-                    bHasValid = TRUE;
+                if( poWK->papanBandSrcValid[iBand][(iSrcOffset+i+1)>>5]
+                    & (0x01 << ((iSrcOffset+i+1) & 0x1f)) )
+                    bHasValid = true;
                 else
                     padfDensity[i+1] = 0.0;
             }
 
-            // Reset or fail as needed
-            if ( bHasValid )
-                bHasValid = FALSE;
+            // Reset or fail as needed.
+            if( bHasValid )
+                bHasValid = false;
             else
-                return FALSE;
+                return false;
         }
     }
 
-    // Fetch data
+    // TODO(schwehr): Fix casting.
+    // Fetch data.
     switch( poWK->eWorkingDataType )
     {
         case GDT_Byte:
         {
             GByte* pSrc = (GByte*) poWK->papabySrcImage[iBand];
             pSrc += iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[i];
                 adfReal[i+1] = pSrc[i+1];
@@ -1778,7 +2058,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
         {
             GInt16* pSrc = (GInt16*) poWK->papabySrcImage[iBand];
             pSrc += iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[i];
                 adfReal[i+1] = pSrc[i+1];
@@ -1790,7 +2070,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
          {
             GUInt16* pSrc = (GUInt16*) poWK->papabySrcImage[iBand];
             pSrc += iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[i];
                 adfReal[i+1] = pSrc[i+1];
@@ -1802,7 +2082,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
         {
             GInt32* pSrc = (GInt32*) poWK->papabySrcImage[iBand];
             pSrc += iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[i];
                 adfReal[i+1] = pSrc[i+1];
@@ -1814,7 +2094,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
         {
             GUInt32* pSrc = (GUInt32*) poWK->papabySrcImage[iBand];
             pSrc += iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[i];
                 adfReal[i+1] = pSrc[i+1];
@@ -1826,7 +2106,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
         {
             float* pSrc = (float*) poWK->papabySrcImage[iBand];
             pSrc += iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[i];
                 adfReal[i+1] = pSrc[i+1];
@@ -1838,7 +2118,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
        {
             double* pSrc = (double*) poWK->papabySrcImage[iBand];
             pSrc += iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[i];
                 adfReal[i+1] = pSrc[i+1];
@@ -1850,7 +2130,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
         {
             GInt16* pSrc = (GInt16*) poWK->papabySrcImage[iBand];
             pSrc += 2 * iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[2*i];
                 padfImag[i] = pSrc[2*i+1];
@@ -1865,7 +2145,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
         {
             GInt32* pSrc = (GInt32*) poWK->papabySrcImage[iBand];
             pSrc += 2 * iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[2*i];
                 padfImag[i] = pSrc[2*i+1];
@@ -1880,7 +2160,7 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
         {
             float* pSrc = (float*) poWK->papabySrcImage[iBand];
             pSrc += 2 * iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[2*i];
                 padfImag[i] = pSrc[2*i+1];
@@ -1891,12 +2171,11 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
             break;
         }
 
-
         case GDT_CFloat64:
         {
             double* pSrc = (double*) poWK->papabySrcImage[iBand];
             pSrc += 2 * iSrcOffset;
-            for ( i = 0; i < nSrcLen; i += 2 )
+            for( int i = 0; i < nSrcLen; i += 2 )
             {
                 adfReal[i] = pSrc[2*i];
                 padfImag[i] = pSrc[2*i+1];
@@ -1908,46 +2187,46 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
         }
 
         default:
-            CPLAssert(FALSE);
+            CPLAssert(false);
             if( padfDensity )
                 memset( padfDensity, 0, nSrcLen * sizeof(double) );
-            return FALSE;
+            return false;
     }
 
     if( padfDensity == NULL )
-        return TRUE;
+        return true;
 
     if( poWK->pafUnifiedSrcDensity == NULL )
     {
-        for ( i = 0; i < nSrcLen; i += 2 )
+        for( int i = 0; i < nSrcLen; i += 2 )
         {
-            // Take into account earlier calcs
-            if(padfDensity[i] > 0.000000001)
+            // Take into account earlier calcs.
+            if( padfDensity[i] > SRC_DENSITY_THRESHOLD )
             {
                 padfDensity[i] = 1.0;
-                bHasValid = TRUE;
+                bHasValid = true;
             }
 
-            if(padfDensity[i+1] > 0.000000001)
+            if( padfDensity[i+1] > SRC_DENSITY_THRESHOLD )
             {
                 padfDensity[i+1] = 1.0;
-                bHasValid = TRUE;
+                bHasValid = true;
             }
         }
     }
     else
     {
-        for ( i = 0; i < nSrcLen; i += 2 )
+        for( int i = 0; i < nSrcLen; i += 2 )
         {
-            if(padfDensity[i] > 0.000000001)
+            if( padfDensity[i] > SRC_DENSITY_THRESHOLD )
                 padfDensity[i] = poWK->pafUnifiedSrcDensity[iSrcOffset+i];
-            if(padfDensity[i] > 0.000000001)
-                bHasValid = TRUE;
+            if( padfDensity[i] > SRC_DENSITY_THRESHOLD )
+                bHasValid = true;
 
-            if(padfDensity[i+1] > 0.000000001)
+            if( padfDensity[i+1] > SRC_DENSITY_THRESHOLD )
                 padfDensity[i+1] = poWK->pafUnifiedSrcDensity[iSrcOffset+i+1];
-            if(padfDensity[i+1] > 0.000000001)
-                bHasValid = TRUE;
+            if( padfDensity[i+1] > SRC_DENSITY_THRESHOLD )
+                bHasValid = true;
         }
     }
 
@@ -1959,28 +2238,28 @@ static int GWKGetPixelRow( GDALWarpKernel *poWK, int iBand,
 /************************************************************************/
 
 template<class T>
-static int GWKGetPixelT( GDALWarpKernel *poWK, int iBand,
-                         int iSrcOffset, double *pdfDensity,
-                         T *pValue )
+static bool GWKGetPixelT( GDALWarpKernel *poWK, int iBand,
+                          int iSrcOffset, double *pdfDensity,
+                          T *pValue )
 
 {
-    T *pSrc = (T *)poWK->papabySrcImage[iBand];
-
-    if ( ( poWK->panUnifiedSrcValid != NULL
-           && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
-                 & (0x01 << (iSrcOffset & 0x1f))) ) )
-         || ( poWK->papanBandSrcValid != NULL
-              && poWK->papanBandSrcValid[iBand] != NULL
-              && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
-                    & (0x01 << (iSrcOffset & 0x1f)))) ) )
+    T *pSrc = reinterpret_cast<T *>(poWK->papabySrcImage[iBand]);
+
+    if( ( poWK->panUnifiedSrcValid != NULL
+          && !((poWK->panUnifiedSrcValid[iSrcOffset>>5]
+                & (0x01 << (iSrcOffset & 0x1f))) ) )
+        || ( poWK->papanBandSrcValid != NULL
+             && poWK->papanBandSrcValid[iBand] != NULL
+             && !((poWK->papanBandSrcValid[iBand][iSrcOffset>>5]
+                   & (0x01 << (iSrcOffset & 0x1f)))) ) )
     {
         *pdfDensity = 0.0;
-        return FALSE;
+        return false;
     }
 
     *pValue = pSrc[iSrcOffset];
 
-    if ( poWK->pafUnifiedSrcDensity == NULL )
+    if( poWK->pafUnifiedSrcDensity == NULL )
         *pdfDensity = 1.0;
     else
         *pdfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
@@ -1993,67 +2272,70 @@ static int GWKGetPixelT( GDALWarpKernel *poWK, int iBand,
 /*     Set of bilinear interpolators                                    */
 /************************************************************************/
 
-static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
+static bool GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
                                 double dfSrcX, double dfSrcY,
                                 double *pdfDensity,
                                 double *pdfReal, double *pdfImag )
 
 {
-    // Save as local variables to avoid following pointers
-    int     nSrcXSize = poWK->nSrcXSize;
-    int     nSrcYSize = poWK->nSrcYSize;
-
-    int     iSrcX = (int) floor(dfSrcX - 0.5);
-    int     iSrcY = (int) floor(dfSrcY - 0.5);
-    int     iSrcOffset;
-    double  dfRatioX = 1.5 - (dfSrcX - iSrcX);
-    double  dfRatioY = 1.5 - (dfSrcY - iSrcY);
-    double  adfDensity[2], adfReal[2], adfImag[2] = {0, 0};
-    double  dfAccumulatorReal = 0.0, dfAccumulatorImag = 0.0;
-    double  dfAccumulatorDensity = 0.0;
-    double  dfAccumulatorDivisor = 0.0;
-    int     bShifted = FALSE;
-
-    if (iSrcX == -1)
+    // Save as local variables to avoid following pointers.
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
+
+    int iSrcX = static_cast<int>(floor(dfSrcX - 0.5));
+    int iSrcY = static_cast<int>(floor(dfSrcY - 0.5));
+    double dfRatioX = 1.5 - (dfSrcX - iSrcX);
+    double dfRatioY = 1.5 - (dfSrcY - iSrcY);
+    bool bShifted = false;
+
+    if( iSrcX == -1 )
     {
         iSrcX = 0;
         dfRatioX = 1;
     }
-    if (iSrcY == -1)
+    if( iSrcY == -1 )
     {
         iSrcY = 0;
         dfRatioY = 1;
     }
-    iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+    int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
 
-    // Shift so we don't overrun the array
+    // Shift so we don't overrun the array.
     if( nSrcXSize * nSrcYSize == iSrcOffset + 1
         || nSrcXSize * nSrcYSize == iSrcOffset + nSrcXSize + 1 )
     {
-        bShifted = TRUE;
+        bShifted = true;
         --iSrcOffset;
     }
 
-    // Get pixel row
-    if ( iSrcY >= 0 && iSrcY < nSrcYSize
-         && iSrcOffset >= 0 && iSrcOffset < nSrcXSize * nSrcYSize
-         && GWKGetPixelRow( poWK, iBand, iSrcOffset, 1,
-                            adfDensity, adfReal, adfImag ) )
+    double adfDensity[2] = { 0.0, 0.0 };
+    double adfReal[2] = { 0.0, 0.0 };
+    double adfImag[2] = { 0.0, 0.0 };
+    double dfAccumulatorReal = 0.0;
+    double dfAccumulatorImag = 0.0;
+    double dfAccumulatorDensity = 0.0;
+    double dfAccumulatorDivisor = 0.0;
+
+    // Get pixel row.
+    if( iSrcY >= 0 && iSrcY < nSrcYSize
+        && iSrcOffset >= 0 && iSrcOffset < nSrcXSize * nSrcYSize
+        && GWKGetPixelRow( poWK, iBand, iSrcOffset, 1,
+                           adfDensity, adfReal, adfImag ) )
     {
         double dfMult1 = dfRatioX * dfRatioY;
         double dfMult2 = (1.0-dfRatioX) * dfRatioY;
 
-        // Shifting corrected
-        if ( bShifted )
+        // Shifting corrected.
+        if( bShifted )
         {
             adfReal[0] = adfReal[1];
             adfImag[0] = adfImag[1];
             adfDensity[0] = adfDensity[1];
         }
 
-        // Upper Left Pixel
-        if ( iSrcX >= 0 && iSrcX < nSrcXSize
-             && adfDensity[0] > 0.000000001 )
+        // Upper Left Pixel.
+        if( iSrcX >= 0 && iSrcX < nSrcXSize
+            && adfDensity[0] > SRC_DENSITY_THRESHOLD )
         {
             dfAccumulatorDivisor += dfMult1;
 
@@ -2062,9 +2344,9 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
             dfAccumulatorDensity += adfDensity[0] * dfMult1;
         }
 
-        // Upper Right Pixel
-        if ( iSrcX+1 >= 0 && iSrcX+1 < nSrcXSize
-             && adfDensity[1] > 0.000000001 )
+        // Upper Right Pixel.
+        if( iSrcX+1 >= 0 && iSrcX+1 < nSrcXSize
+            && adfDensity[1] > SRC_DENSITY_THRESHOLD )
         {
             dfAccumulatorDivisor += dfMult2;
 
@@ -2074,11 +2356,11 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
         }
     }
 
-    // Get pixel row
-    if ( iSrcY+1 >= 0 && iSrcY+1 < nSrcYSize
-         && iSrcOffset+nSrcXSize >= 0
-         && iSrcOffset+nSrcXSize < nSrcXSize * nSrcYSize
-         && GWKGetPixelRow( poWK, iBand, iSrcOffset+nSrcXSize, 1,
+    // Get pixel row.
+    if( iSrcY+1 >= 0 && iSrcY+1 < nSrcYSize
+        && iSrcOffset+nSrcXSize >= 0
+        && iSrcOffset+nSrcXSize < nSrcXSize * nSrcYSize
+        && GWKGetPixelRow( poWK, iBand, iSrcOffset+nSrcXSize, 1,
                            adfDensity, adfReal, adfImag ) )
     {
         double dfMult1 = dfRatioX * (1.0-dfRatioY);
@@ -2094,7 +2376,7 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
 
         // Lower Left Pixel
         if ( iSrcX >= 0 && iSrcX < nSrcXSize
-             && adfDensity[0] > 0.000000001 )
+             && adfDensity[0] > SRC_DENSITY_THRESHOLD )
         {
             dfAccumulatorDivisor += dfMult1;
 
@@ -2103,9 +2385,9 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
             dfAccumulatorDensity += adfDensity[0] * dfMult1;
         }
 
-        // Lower Right Pixel
-        if ( iSrcX+1 >= 0 && iSrcX+1 < nSrcXSize
-             && adfDensity[1] > 0.000000001 )
+        // Lower Right Pixel.
+        if( iSrcX+1 >= 0 && iSrcX+1 < nSrcXSize
+            && adfDensity[1] > SRC_DENSITY_THRESHOLD )
         {
             dfAccumulatorDivisor += dfMult2;
 
@@ -2118,61 +2400,67 @@ static int GWKBilinearResample4Sample( GDALWarpKernel *poWK, int iBand,
 /* -------------------------------------------------------------------- */
 /*      Return result.                                                  */
 /* -------------------------------------------------------------------- */
-    if ( dfAccumulatorDivisor == 1.0 )
+    if( dfAccumulatorDivisor == 1.0 )
     {
         *pdfReal = dfAccumulatorReal;
         *pdfImag = dfAccumulatorImag;
         *pdfDensity = dfAccumulatorDensity;
-        return TRUE;
+        return false;
     }
-    else if ( dfAccumulatorDivisor < 0.00001 )
+    else if( dfAccumulatorDivisor < 0.00001 )
     {
         *pdfReal = 0.0;
         *pdfImag = 0.0;
         *pdfDensity = 0.0;
-        return FALSE;
+        return false;
     }
     else
     {
         *pdfReal = dfAccumulatorReal / dfAccumulatorDivisor;
         *pdfImag = dfAccumulatorImag / dfAccumulatorDivisor;
         *pdfDensity = dfAccumulatorDensity / dfAccumulatorDivisor;
-        return TRUE;
+        return true;
     }
 }
 
 template<class T>
-static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
+static bool GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
                                         double dfSrcX, double dfSrcY,
                                         T *pValue )
 
 {
-    double dfMult;
-    double  dfAccumulator = 0.0;
-    double  dfAccumulatorDivisor = 0.0;
 
-    int     iSrcX = (int) floor(dfSrcX - 0.5);
-    int     iSrcY = (int) floor(dfSrcY - 0.5);
-    int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
-    double  dfRatioX = 1.5 - (dfSrcX - iSrcX);
-    double  dfRatioY = 1.5 - (dfSrcY - iSrcY);
+    const int iSrcX = static_cast<int>(floor(dfSrcX - 0.5));
+    const int iSrcY = static_cast<int>(floor(dfSrcY - 0.5));
+    const int iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
+    const double dfRatioX = 1.5 - (dfSrcX - iSrcX);
+    const double dfRatioY = 1.5 - (dfSrcY - iSrcY);
+
+    T* pSrc = reinterpret_cast<T *>(poWK->papabySrcImage[iBand]);
 
-    T* pSrc = (T *)poWK->papabySrcImage[iBand];
 
     if( iSrcX >= 0 && iSrcX+1 < poWK->nSrcXSize
         && iSrcY >= 0 && iSrcY+1 < poWK->nSrcYSize )
     {
-        dfAccumulator = ((double)pSrc[iSrcOffset] * dfRatioX +
-                         (double)pSrc[iSrcOffset+1] * (1.0-dfRatioX)) * dfRatioY +
-                        ((double)pSrc[iSrcOffset+poWK->nSrcXSize] * dfRatioX +
-                         (double)pSrc[iSrcOffset+1+poWK->nSrcXSize] * (1.0-dfRatioX)) * (1.0-dfRatioY);
+        // TODO(schwehr): Should be able to remove these casts.
+        const double dfAccumulator =
+            (static_cast<double>(pSrc[iSrcOffset]) * dfRatioX +
+             static_cast<double>(pSrc[iSrcOffset+1]) * (1.0 - dfRatioX)) *
+            dfRatioY +
+            (static_cast<double>(pSrc[iSrcOffset+poWK->nSrcXSize]) * dfRatioX +
+             static_cast<double>(pSrc[iSrcOffset+1+poWK->nSrcXSize]) *
+             (1.0 - dfRatioX)) * (1.0-dfRatioY);
 
         *pValue = GWKRoundValueT<T>(dfAccumulator);
 
-        return TRUE;
+        return true;
     }
 
-    // Upper Left Pixel
+    double dfMult = 0.0;
+    double dfAccumulatorDivisor = 0.0;
+    double dfAccumulator = 0.0;
+
+    // Upper Left Pixel.
     if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
         && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
     {
@@ -2180,51 +2468,51 @@ static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
 
         dfAccumulatorDivisor += dfMult;
 
-        dfAccumulator += (double)pSrc[iSrcOffset] * dfMult;
+        dfAccumulator += pSrc[iSrcOffset] * dfMult;
     }
 
-    // Upper Right Pixel
+    // Upper Right Pixel.
     if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
         && iSrcY >= 0 && iSrcY < poWK->nSrcYSize )
     {
-        dfMult = (1.0-dfRatioX) * dfRatioY;
+        dfMult = (1.0 - dfRatioX) * dfRatioY;
 
         dfAccumulatorDivisor += dfMult;
 
-        dfAccumulator += (double)pSrc[iSrcOffset+1] * dfMult;
+        dfAccumulator += pSrc[iSrcOffset+1] * dfMult;
     }
 
-    // Lower Right Pixel
+    // Lower Right Pixel.
     if( iSrcX+1 >= 0 && iSrcX+1 < poWK->nSrcXSize
         && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
     {
-        dfMult = (1.0-dfRatioX) * (1.0-dfRatioY);
+        dfMult = (1.0 - dfRatioX) * (1.0 - dfRatioY);
 
         dfAccumulatorDivisor += dfMult;
 
-        dfAccumulator += (double)pSrc[iSrcOffset+1+poWK->nSrcXSize] * dfMult;
+        dfAccumulator += pSrc[iSrcOffset+1+poWK->nSrcXSize] * dfMult;
     }
 
-    // Lower Left Pixel
+    // Lower Left Pixel.
     if( iSrcX >= 0 && iSrcX < poWK->nSrcXSize
         && iSrcY+1 >= 0 && iSrcY+1 < poWK->nSrcYSize )
     {
-        dfMult = dfRatioX * (1.0-dfRatioY);
+        dfMult = dfRatioX * (1.0 - dfRatioY);
 
         dfAccumulatorDivisor += dfMult;
 
-        dfAccumulator += (double)pSrc[iSrcOffset+poWK->nSrcXSize] * dfMult;
+        dfAccumulator += pSrc[iSrcOffset+poWK->nSrcXSize] * dfMult;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Return result.                                                  */
 /* -------------------------------------------------------------------- */
-    double      dfValue;
+    double dfValue = 0.0;
 
     if( dfAccumulatorDivisor < 0.00001 )
     {
         *pValue = 0;
-        return FALSE;
+        return false;
     }
     else if( dfAccumulatorDivisor == 1.0 )
     {
@@ -2237,7 +2525,7 @@ static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
 
     *pValue = GWKRoundValueT<T>(dfValue);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -2245,60 +2533,112 @@ static int GWKBilinearResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
 /*     Set of bicubic interpolators using cubic convolution.            */
 /************************************************************************/
 
-/* http://verona.fi-p.unam.mx/boris/practicas/CubConvInterp.pdf Formula 18
-or http://en.wikipedia.org/wiki/Cubic_Hermite_spline : CINTx(p_1,p0,p1,p2)
-or http://en.wikipedia.org/wiki/Bicubic_interpolation: matrix notation */
+// http://verona.fi-p.unam.mx/boris/practicas/CubConvInterp.pdf Formula 18
+// or http://en.wikipedia.org/wiki/Cubic_Hermite_spline : CINTx(p_1,p0,p1,p2)
+// http://en.wikipedia.org/wiki/Bicubic_interpolation: matrix notation
 
+// TODO(schwehr): Use an inline function.
 #define CubicConvolution(distance1,distance2,distance3,f0,f1,f2,f3) \
      (             f1                                               \
       + 0.5 * (distance1*(f2 - f0)                                  \
              + distance2*(2.0*f0 - 5.0*f1 + 4.0*f2 - f3)            \
              + distance3*(3.0*(f1 - f2) + f3 - f0)))
 
-static int GWKCubicResample4Sample( GDALWarpKernel *poWK, int iBand,
-                             double dfSrcX, double dfSrcY,
-                             double *pdfDensity,
-                             double *pdfReal, double *pdfImag )
+/************************************************************************/
+/*                       GWKCubicComputeWeights()                       */
+/************************************************************************/
+
+// adfCoeffs[2] = 1.0 - (adfCoeffs[0] + adfCoeffs[1] - adfCoeffs[3]);
+
+// TODO(schwehr): Use an inline function.
+#define GWKCubicComputeWeights(dfX_, adfCoeffs) \
+{ \
+    const double dfX = dfX_; \
+    const double dfHalfX = 0.5 * dfX; \
+    const double dfThreeX = 3.0 * dfX; \
+    const double dfHalfX2 = dfHalfX * dfX; \
+ \
+    adfCoeffs[0] = dfHalfX * (-1 + dfX * (2 - dfX)); \
+    adfCoeffs[1] = 1 + dfHalfX2 * (-5 + dfThreeX); \
+    adfCoeffs[2] = dfHalfX * (1 + dfX * (4 - dfThreeX)); \
+    adfCoeffs[3] = dfHalfX2 * (-1 + dfX); \
+}
+
+// TODO(schwehr): Use an inline function.
+#define CONVOL4(v1, v2) ((v1)[0] * (v2)[0] + (v1)[1] * (v2)[1] + \
+                         (v1)[2] * (v2)[2] + (v1)[3] * (v2)[3])
+
+#if 0
+// Optimal (in theory...) for max 2 convolutions: 14 multiplications
+// instead of 17.
+// TODO(schwehr): Use an inline function.
+#define GWKCubicComputeWeights_Optim2MAX(dfX_, adfCoeffs, dfHalfX) \
+{ \
+    const double dfX = dfX_; \
+    dfHalfX = 0.5 * dfX; \
+    const double dfThreeX = 3.0 * dfX; \
+    const double dfXMinus1 = dfX - 1; \
+ \
+    adfCoeffs[0] = -1 + dfX * (2 - dfX); \
+    adfCoeffs[1] = dfX * (-5 + dfThreeX); \
+    /*adfCoeffs[2] = 1 + dfX * (4 - dfThreeX);*/ \
+    adfCoeffs[2] = -dfXMinus1 - adfCoeffs[1]; \
+    /*adfCoeffs[3] = dfX * (-1 + dfX); */ \
+    adfCoeffs[3] = dfXMinus1 - adfCoeffs[0]; \
+}
+
+// TODO(schwehr): Use an inline function.
+#define CONVOL4_Optim2MAX(adfCoeffs, v, dfHalfX) \
+      ((v)[1] + (dfHalfX) * (\
+          (adfCoeffs)[0] * (v)[0] + (adfCoeffs)[1] * (v)[1] + \
+          (adfCoeffs)[2] * (v)[2] + (adfCoeffs)[3] * (v)[3]))
+#endif
+
+static bool GWKCubicResample4Sample( GDALWarpKernel *poWK, int iBand,
+                                     double dfSrcX, double dfSrcY,
+                                     double *pdfDensity,
+                                     double *pdfReal, double *pdfImag )
 
 {
-    int     iSrcX = (int) (dfSrcX - 0.5);
-    int     iSrcY = (int) (dfSrcY - 0.5);
-    int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
-    double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
-    double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
-    double  dfDeltaX2 = dfDeltaX * dfDeltaX;
-    double  dfDeltaY2 = dfDeltaY * dfDeltaY;
-    double  dfDeltaX3 = dfDeltaX2 * dfDeltaX;
-    double  dfDeltaY3 = dfDeltaY2 * dfDeltaY;
-    double  adfValueDens[4], adfValueReal[4], adfValueImag[4];
-    double  adfDensity[4], adfReal[4], adfImag[4] = {0, 0, 0, 0};
-    int     i;
-
-    // Get the bilinear interpolation at the image borders
-    if ( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
-         || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
+    const int iSrcX = static_cast<int>(dfSrcX - 0.5);
+    const int iSrcY = static_cast<int>(dfSrcY - 0.5);
+    const int  iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
+    const double dfDeltaX = dfSrcX - 0.5 - iSrcX;
+    const double dfDeltaY = dfSrcY - 0.5 - iSrcY;
+    double adfDensity[4] = {};
+    double adfReal[4] = {};
+    double adfImag[4] = {};
+    int i;
+
+    // Get the bilinear interpolation at the image borders.
+    if( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
+        || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
         return GWKBilinearResample4Sample( poWK, iBand, dfSrcX, dfSrcY,
-                                    pdfDensity, pdfReal, pdfImag );
+                                           pdfDensity, pdfReal, pdfImag );
+
+    double adfValueDens[4] = {};
+    double adfValueReal[4] = {};
+    double adfValueImag[4] = {};
+
+    double adfCoeffsX[4] = {};
+    GWKCubicComputeWeights(dfDeltaX, adfCoeffsX);
 
-    for ( i = -1; i < 3; i++ )
+    for( i = -1; i < 3; i++ )
     {
-        if ( !GWKGetPixelRow(poWK, iBand, iSrcOffset + i * poWK->nSrcXSize - 1,
-                             2, adfDensity, adfReal, adfImag)
-             || adfDensity[0] < 0.000000001
-             || adfDensity[1] < 0.000000001
-             || adfDensity[2] < 0.000000001
-             || adfDensity[3] < 0.000000001 )
+        if( !GWKGetPixelRow(poWK, iBand, iSrcOffset + i * poWK->nSrcXSize - 1,
+                            2, adfDensity, adfReal, adfImag)
+            || adfDensity[0] < SRC_DENSITY_THRESHOLD
+            || adfDensity[1] < SRC_DENSITY_THRESHOLD
+            || adfDensity[2] < SRC_DENSITY_THRESHOLD
+            || adfDensity[3] < SRC_DENSITY_THRESHOLD )
         {
             return GWKBilinearResample4Sample( poWK, iBand, dfSrcX, dfSrcY,
                                        pdfDensity, pdfReal, pdfImag );
         }
 
-        adfValueDens[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
-            adfDensity[0], adfDensity[1], adfDensity[2], adfDensity[3]);
-        adfValueReal[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
-            adfReal[0], adfReal[1], adfReal[2], adfReal[3]);
-        adfValueImag[i + 1] = CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
-            adfImag[0], adfImag[1], adfImag[2], adfImag[3]);
+        adfValueDens[i + 1] = CONVOL4(adfCoeffsX, adfDensity);
+        adfValueReal[i + 1] = CONVOL4(adfCoeffsX, adfReal);
+        adfValueImag[i + 1] = CONVOL4(adfCoeffsX, adfImag);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2307,64 +2647,342 @@ static int GWKCubicResample4Sample( GDALWarpKernel *poWK, int iBand,
 /*      should do "weight adjustment" of our results similarly to       */
 /*      what is done for the cubic spline and lanc. interpolators.      */
 /* -------------------------------------------------------------------- */
-    *pdfDensity = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
-                                   adfValueDens[0], adfValueDens[1],
-                                   adfValueDens[2], adfValueDens[3]);
-    *pdfReal = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
-                                   adfValueReal[0], adfValueReal[1],
-                                   adfValueReal[2], adfValueReal[3]);
-    *pdfImag = CubicConvolution(dfDeltaY, dfDeltaY2, dfDeltaY3,
-                                   adfValueImag[0], adfValueImag[1],
-                                   adfValueImag[2], adfValueImag[3]);
-
-    return TRUE;
-}
 
-template<class T>
-static int GWKCubicResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
-                                     double dfSrcX, double dfSrcY,
-                                     T *pValue )
+    double adfCoeffsY[4] = {};
+    GWKCubicComputeWeights(dfDeltaY, adfCoeffsY);
 
+    *pdfDensity = CONVOL4(adfCoeffsY, adfValueDens);
+    *pdfReal    = CONVOL4(adfCoeffsY, adfValueReal);
+    *pdfImag    = CONVOL4(adfCoeffsY, adfValueImag);
+
+    return true;
+}
+
+// We do not define USE_SSE_CUBIC_IMPL since in practice, it gives zero
+// perf benefit.
+
+#if defined(USE_SSE_CUBIC_IMPL) && (defined(__x86_64) || defined(_M_X64))
+
+/************************************************************************/
+/*                           XMMLoad4Values()                           */
+/*                                                                      */
+/*  Load 4 packed byte or uint16, cast them to float and put them in a  */
+/*  m128 register.                                                      */
+/************************************************************************/
+
+static CPL_INLINE __m128 XMMLoad4Values(const GByte* ptr)
+{
+#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
+    unsigned int i;
+    memcpy(&i, ptr, 4);
+    __m128i xmm_i = _mm_cvtsi32_si128(s);
+#else
+    __m128i xmm_i = _mm_cvtsi32_si128(*(unsigned int*)(ptr));
+#endif
+    // Zero extend 4 packed unsigned 8-bit integers in a to packed
+    // 32-bit integers.
+#if __SSE4_1__
+    xmm_i = _mm_cvtepu8_epi32(xmm_i);
+#else
+    xmm_i = _mm_unpacklo_epi8(xmm_i, _mm_setzero_si128());
+    xmm_i = _mm_unpacklo_epi16(xmm_i, _mm_setzero_si128());
+#endif
+    return _mm_cvtepi32_ps(xmm_i);
+}
+
+static CPL_INLINE __m128 XMMLoad4Values(const GUInt16* ptr)
+{
+#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
+    GUInt64 i;
+    memcpy(&i, ptr, 8);
+    __m128i xmm_i =  _mm_cvtsi64_si128(s);
+#else
+    __m128i xmm_i =  _mm_cvtsi64_si128(*(GUInt64*)(ptr));
+#endif
+    // Zero extend 4 packed unsigned 16-bit integers in a to packed
+    // 32-bit integers.
+#if __SSE4_1__
+    xmm_i = _mm_cvtepu16_epi32(xmm_i);
+#else
+    xmm_i = _mm_unpacklo_epi16(xmm_i, _mm_setzero_si128());
+#endif
+    return _mm_cvtepi32_ps(xmm_i);
+}
+
+/************************************************************************/
+/*                           XMMHorizontalAdd()                         */
+/*                                                                      */
+/*  Return the sum of the 4 floating points of the register.            */
+/************************************************************************/
+
+#if __SSE3__
+static CPL_INLINE float XMMHorizontalAdd(__m128 v)
+{
+    __m128 shuf = _mm_movehdup_ps(v);        // (v3   , v3   , v1   , v1)
+    __m128 sums = _mm_add_ps(v, shuf);       // (v3+v3, v3+v2, v1+v1, v1+v0)
+    shuf        = _mm_movehl_ps(shuf, sums); // (v3   , v3   , v3+v3, v3+v2)
+    sums        = _mm_add_ss(sums, shuf);    // (v1+v0)+(v3+v2)
+    return        _mm_cvtss_f32(sums);
+}
+#else
+static CPL_INLINE float XMMHorizontalAdd(__m128 v)
+{
+    __m128 shuf = _mm_movehl_ps(v, v);           // (v3   , v2   , v3   , v2)
+    __m128 sums = _mm_add_ps(v, shuf);           // (v3+v3, v2+v2, v3+v1, v2+v0)
+    shuf        = _mm_shuffle_ps(sums, sums, 1); // (v2+v0, v2+v0, v2+v0, v3+v1)
+    sums        = _mm_add_ss(sums, shuf);        // (v2+v0)+(v3+v1)
+    return _mm_cvtss_f32(sums);
+}
+#endif
+
+#endif // defined(USE_SSE_CUBIC_IMPL) && (defined(__x86_64) || defined(_M_X64))
+
+/************************************************************************/
+/*            GWKCubicResampleSrcMaskIsDensity4SampleRealT()            */
+/************************************************************************/
+
+// Note: if USE_SSE_CUBIC_IMPL, only instantiate that for Byte and UInt16,
+// because there are a few assumptions above those types.
+
+template<class T>
+static CPL_INLINE bool GWKCubicResampleSrcMaskIsDensity4SampleRealT(
+    GDALWarpKernel *poWK, int iBand,
+    double dfSrcX, double dfSrcY,
+    double *pdfDensity,
+    double *pdfReal )
 {
-    int     iSrcX = (int) (dfSrcX - 0.5);
-    int     iSrcY = (int) (dfSrcY - 0.5);
-    int     iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
-    double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
-    double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
-    double  dfDeltaX2 = dfDeltaX * dfDeltaX;
-    double  dfDeltaY2 = dfDeltaY * dfDeltaY;
-    double  dfDeltaX3 = dfDeltaX2 * dfDeltaX;
-    double  dfDeltaY3 = dfDeltaY2 * dfDeltaY;
-    double  adfValue[4];
-    int     i;
-
-    // Get the bilinear interpolation at the image borders
-    if ( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
-         || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
+    const int iSrcX = static_cast<int>(dfSrcX - 0.5);
+    const int iSrcY = static_cast<int>(dfSrcY - 0.5);
+    const int iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
+
+    // Get the bilinear interpolation at the image borders.
+    if( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
+        || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
+    {
+        double adfImagIgnored[4] = {};
+        return GWKBilinearResample4Sample(poWK, iBand, dfSrcX, dfSrcY,
+                                          pdfDensity, pdfReal, adfImagIgnored);
+    }
+
+#if defined(USE_SSE_CUBIC_IMPL) && (defined(__x86_64) || defined(_M_X64))
+    const float fDeltaX = static_cast<float>(dfSrcX) - 0.5f - iSrcX;
+    const float fDeltaY = static_cast<float>(dfSrcY) - 0.5f - iSrcY;
+
+    // TODO(schwehr): Explain the magic numbers.
+    float  afTemp[4 + 4 + 4 + 1];
+    float* pafAligned =
+        reinterpret_cast<float*>(afTemp + ((size_t)afTemp & 0xf));
+    float* pafCoeffs = pafAligned;
+    float* pafDensity = pafAligned + 4;
+    float* pafValue = pafAligned + 8;
+
+    const float fHalfDeltaX = 0.5f * fDeltaX;
+    const float fThreeDeltaX = 3.0f * fDeltaX;
+    const float fHalfDeltaX2 = fHalfDeltaX * fDeltaX;
+
+    pafCoeffs[0] = fHalfDeltaX * (-1 + fDeltaX * (2 - fDeltaX));
+    pafCoeffs[1] = 1 + fHalfDeltaX2 * (-5 + fThreeDeltaX);
+    pafCoeffs[2] = fHalfDeltaX * (1 + fDeltaX * (4 - fThreeDeltaX));
+    pafCoeffs[3] = fHalfDeltaX2 * (-1 + fDeltaX);
+    __m128 xmmCoeffs = _mm_load_ps(pafCoeffs);
+    const __m128 xmmThreshold = _mm_load1_ps(&SRC_DENSITY_THRESHOLD);
+
+    __m128 xmmMaskLowDensity = _mm_setzero_ps();
+    for( int i = -1, iOffset = iSrcOffset - poWK->nSrcXSize - 1;
+         i < 3; i++, iOffset += poWK->nSrcXSize )
+    {
+        const __m128 xmmDensity = _mm_loadu_ps(
+                                    poWK->pafUnifiedSrcDensity + iOffset);
+        xmmMaskLowDensity = _mm_or_ps(xmmMaskLowDensity,
+                                      _mm_cmplt_ps(xmmDensity, xmmThreshold));
+        pafDensity[i + 1] = XMMHorizontalAdd(_mm_mul_ps(xmmCoeffs, xmmDensity));
+
+        const __m128 xmmValues = XMMLoad4Values(
+                              ((T*) poWK->papabySrcImage[iBand]) + iOffset);
+        pafValue[i + 1] = XMMHorizontalAdd(_mm_mul_ps(xmmCoeffs, xmmValues));
+    }
+    if( _mm_movemask_ps(xmmMaskLowDensity) )
+    {
+        double adfImagIgnored[4] = {};
+        return GWKBilinearResample4Sample( poWK, iBand, dfSrcX, dfSrcY,
+                                  pdfDensity, pdfReal, adfImagIgnored );
+    }
+
+    const float fHalfDeltaY = 0.5f * fDeltaY;
+    const float fThreeDeltaY = 3.0f * fDeltaY;
+    const float fHalfDeltaY2 = fHalfDeltaY * fDeltaY;
+
+    pafCoeffs[0] = fHalfDeltaY * (-1 + fDeltaY * (2 - fDeltaY));
+    pafCoeffs[1] = 1 + fHalfDeltaY2 * (-5 + fThreeDeltaY);
+    pafCoeffs[2] = fHalfDeltaY * (1 + fDeltaY * (4 - fThreeDeltaY));
+    pafCoeffs[3] = fHalfDeltaY2 * (-1 + fDeltaY);
+
+    xmmCoeffs = _mm_load_ps(pafCoeffs);
+
+    const __m128 xmmDensity = _mm_load_ps(pafDensity);
+    const __m128 xmmValue = _mm_load_ps(pafValue);
+    *pdfDensity = XMMHorizontalAdd(_mm_mul_ps(xmmCoeffs, xmmDensity));
+    *pdfReal = XMMHorizontalAdd(_mm_mul_ps(xmmCoeffs, xmmValue));
+
+    // We did all above computations on float32 whereas the general case is
+    // float64. Not sure if one is fundamentally more correct than the other
+    // one, but we want our optimization to give the same result as the
+    // general case as much as possible, so if the resulting value is
+    // close to some_int_value + 0.5, redo the computation with the general
+    // case.
+    // Note: If other types than Byte or UInt16, will need changes.
+    if( fabs(*pdfReal - static_cast<int>(*pdfReal) - 0.5) > .007 )
+        return true;
+
+#endif // defined(USE_SSE_CUBIC_IMPL) && (defined(__x86_64) || defined(_M_X64))
+
+    const double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
+    const double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
+
+    double adfValueDens[4] = {};
+    double adfValueReal[4] = {};
+
+    double adfCoeffsX[4] = {};
+    GWKCubicComputeWeights(dfDeltaX, adfCoeffsX);
+
+    double adfCoeffsY[4] = {};
+    GWKCubicComputeWeights(dfDeltaY, adfCoeffsY);
+
+    for( int i = -1; i < 3; i++ )
+    {
+        const int iOffset = iSrcOffset+i*poWK->nSrcXSize - 1;
+#if !(defined(USE_SSE_CUBIC_IMPL) && (defined(__x86_64) || defined(_M_X64)))
+        if( poWK->pafUnifiedSrcDensity[iOffset + 0] < SRC_DENSITY_THRESHOLD ||
+            poWK->pafUnifiedSrcDensity[iOffset + 1] < SRC_DENSITY_THRESHOLD ||
+            poWK->pafUnifiedSrcDensity[iOffset + 2] < SRC_DENSITY_THRESHOLD ||
+            poWK->pafUnifiedSrcDensity[iOffset + 3] < SRC_DENSITY_THRESHOLD )
+        {
+            double adfImagIgnored[4] = {};
+            return GWKBilinearResample4Sample( poWK, iBand, dfSrcX, dfSrcY,
+                                      pdfDensity, pdfReal, adfImagIgnored );
+        }
+#endif
+
+        adfValueDens[i + 1] = CONVOL4(
+            adfCoeffsX,
+            poWK->pafUnifiedSrcDensity + iOffset);
+
+        adfValueReal[i + 1] = CONVOL4(
+            adfCoeffsX,
+            reinterpret_cast<T*>(poWK->papabySrcImage[iBand]) + iOffset);
+    }
+
+    *pdfDensity = CONVOL4(adfCoeffsY, adfValueDens);
+    *pdfReal    = CONVOL4(adfCoeffsY, adfValueReal);
+
+    return true;
+}
+
+/************************************************************************/
+/*              GWKCubicResampleSrcMaskIsDensity4SampleReal()             */
+/*     Bi-cubic when source has and only has pafUnifiedSrcDensity.      */
+/************************************************************************/
+
+static bool GWKCubicResampleSrcMaskIsDensity4SampleReal(
+                             GDALWarpKernel *poWK, int iBand,
+                             double dfSrcX, double dfSrcY,
+                             double *pdfDensity,
+                             double *pdfReal )
+
+{
+    const int iSrcX = static_cast<int>(dfSrcX - 0.5);
+    const int iSrcY = static_cast<int>(dfSrcY - 0.5);
+    const int iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
+    const double dfDeltaX = dfSrcX - 0.5 - iSrcX;
+    const double dfDeltaY = dfSrcY - 0.5 - iSrcY;
+
+    // Get the bilinear interpolation at the image borders.
+    if( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
+        || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
+    {
+        double adfImagIgnored[4] = {};
+        return GWKBilinearResample4Sample(poWK, iBand, dfSrcX, dfSrcY,
+                                          pdfDensity, pdfReal, adfImagIgnored);
+    }
+
+    double adfCoeffsX[4] = {};
+    GWKCubicComputeWeights(dfDeltaX, adfCoeffsX);
+
+    double adfCoeffsY[4] = {};
+    GWKCubicComputeWeights(dfDeltaY, adfCoeffsY);
+
+    double adfValueDens[4] = {};
+    double adfValueReal[4] = {};
+    double adfDensity[4] = {};
+    double adfReal[4] = {};
+    double adfImagIgnored[4] = {};
+
+    for( int i = -1; i < 3; i++ )
+    {
+        if( !GWKGetPixelRow(poWK, iBand, iSrcOffset + i * poWK->nSrcXSize - 1,
+                            2, adfDensity, adfReal, adfImagIgnored)
+            || adfDensity[0] < SRC_DENSITY_THRESHOLD
+            || adfDensity[1] < SRC_DENSITY_THRESHOLD
+            || adfDensity[2] < SRC_DENSITY_THRESHOLD
+            || adfDensity[3] < SRC_DENSITY_THRESHOLD )
+        {
+            return GWKBilinearResample4Sample( poWK, iBand, dfSrcX, dfSrcY,
+                                      pdfDensity, pdfReal, adfImagIgnored );
+        }
+
+        adfValueDens[i + 1] = CONVOL4(adfCoeffsX, adfDensity);
+        adfValueReal[i + 1] = CONVOL4(adfCoeffsX, adfReal);
+    }
+
+    *pdfDensity = CONVOL4(adfCoeffsY, adfValueDens);
+    *pdfReal    = CONVOL4(adfCoeffsY, adfValueReal);
+
+    return true;
+}
+
+template<class T>
+static bool GWKCubicResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
+                                     double dfSrcX, double dfSrcY,
+                                     T *pValue )
+
+{
+    const int iSrcX = static_cast<int>(dfSrcX - 0.5);
+    const int iSrcY = static_cast<int>(dfSrcY - 0.5);
+    const int iSrcOffset = iSrcX + iSrcY * poWK->nSrcXSize;
+    const double dfDeltaX = dfSrcX - 0.5 - iSrcX;
+    const double dfDeltaY = dfSrcY - 0.5 - iSrcY;
+    const double dfDeltaY2 = dfDeltaY * dfDeltaY;
+    const double dfDeltaY3 = dfDeltaY2 * dfDeltaY;
+
+    // Get the bilinear interpolation at the image borders.
+    if( iSrcX - 1 < 0 || iSrcX + 2 >= poWK->nSrcXSize
+        || iSrcY - 1 < 0 || iSrcY + 2 >= poWK->nSrcYSize )
         return GWKBilinearResampleNoMasks4SampleT ( poWK, iBand, dfSrcX, dfSrcY,
                                              pValue );
 
-    for ( i = -1; i < 3; i++ )
+    double adfCoeffs[4] = {};
+    GWKCubicComputeWeights(dfDeltaX, adfCoeffs);
+
+    double adfValue[4] = {};
+
+    for( int i = -1; i < 3; i++ )
     {
-        int     iOffset = iSrcOffset + i * poWK->nSrcXSize;
+        const int iOffset = iSrcOffset + i * poWK->nSrcXSize - 1;
 
-        adfValue[i + 1] =CubicConvolution(dfDeltaX, dfDeltaX2, dfDeltaX3,
-                (double)((T *)poWK->papabySrcImage[iBand])[iOffset - 1],
-                (double)((T *)poWK->papabySrcImage[iBand])[iOffset],
-                (double)((T *)poWK->papabySrcImage[iBand])[iOffset + 1],
-                (double)((T *)poWK->papabySrcImage[iBand])[iOffset + 2]);
+        adfValue[i + 1] = CONVOL4(
+            adfCoeffs,
+            reinterpret_cast<T*>(poWK->papabySrcImage[iBand]) + iOffset);
     }
 
-    double dfValue = CubicConvolution(
+    const double dfValue = CubicConvolution(
         dfDeltaY, dfDeltaY2, dfDeltaY3,
         adfValue[0], adfValue[1], adfValue[2], adfValue[3]);
 
     *pValue = GWKClampValueT<T>(dfValue);
 
-    return TRUE;
+    return true;
 }
 
-
 /************************************************************************/
 /*                          GWKLanczosSinc()                            */
 /************************************************************************/
@@ -2382,12 +3000,7 @@ static int GWKCubicResampleNoMasks4SampleT( GDALWarpKernel *poWK, int iBand,
 
 static double GWKLanczosSinc( double dfX )
 {
-    /*if( fabs(dfX) > 3.0 )
-    {
-        printf("%f\n", dfX);
-        return 0;
-    }*/
-    if ( dfX == 0.0 )
+    if( dfX == 0.0 )
         return 1.0;
 
     const double dfPIX = M_PI * dfX;
@@ -2398,10 +3011,12 @@ static double GWKLanczosSinc( double dfX )
 
 static double GWKLanczosSinc4Values( double* padfValues )
 {
-    for(int i=0;i<4;i++)
+    for( int i = 0; i < 4; i++ )
     {
-        if ( padfValues[i] == 0.0 )
+        if( padfValues[i] == 0.0 )
+        {
             padfValues[i] = 1.0;
+        }
         else
         {
             const double dfPIX = M_PI * padfValues[i];
@@ -2417,7 +3032,7 @@ static double GWKLanczosSinc4Values( double* padfValues )
 /*                           GWKBilinear()                              */
 /************************************************************************/
 
-static double GWKBilinear(double dfX)
+static double GWKBilinear( double dfX )
 {
     double dfAbsX = fabs(dfX);
     if( dfAbsX <= 1.0 )
@@ -2455,12 +3070,12 @@ static double GWKBilinear4Values( double* padfValues )
 /*                            GWKCubic()                                */
 /************************************************************************/
 
-static double GWKCubic(double dfX)
+static double GWKCubic( double dfX )
 {
-    /* http://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm */
-    /* W(x) formula with a = -0.5 (cubic hermite spline ) */
-    /* or http://www.cs.utexas.edu/users/fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf */
-    /* k(x) (formula 8) with (B,C)=(0,0.5) the Catmull-Rom spline */
+    // http://en.wikipedia.org/wiki/Bicubic_interpolation#Bicubic_convolution_algorithm
+    // W(x) formula with a = -0.5 (cubic hermite spline )
+    // or http://www.cs.utexas.edu/users/fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf
+    // k(x) (formula 8) with (B,C)=(0,0.5) the Catmull-Rom spline
     double dfAbsX = fabs(dfX);
     if( dfAbsX <= 1.0 )
     {
@@ -2478,39 +3093,38 @@ static double GWKCubic(double dfX)
 
 static double GWKCubic4Values( double* padfValues )
 {
-    double dfAbsX_0 = fabs(padfValues[0]);
-    double dfX2_0 = padfValues[0] * padfValues[0];
-    double dfAbsX_1 = fabs(padfValues[1]);
-    double dfX2_1 = padfValues[1] * padfValues[1];
-    double dfAbsX_2 = fabs(padfValues[2]);
-    double dfX2_2 = padfValues[2] * padfValues[2];
-    double dfAbsX_3 = fabs(padfValues[3]);
-    double dfX2_3 = padfValues[3] * padfValues[3];
-    double dfVal0, dfVal1, dfVal2, dfVal3;
+    const double dfAbsX_0 = fabs(padfValues[0]);
+    const double dfAbsX_1 = fabs(padfValues[1]);
+    const double dfAbsX_2 = fabs(padfValues[2]);
+    const double dfAbsX_3 = fabs(padfValues[3]);
+    const double dfX2_0 = padfValues[0] * padfValues[0];
+    const double dfX2_1 = padfValues[1] * padfValues[1];
+    const double dfX2_2 = padfValues[2] * padfValues[2];
+    const double dfX2_3 = padfValues[3] * padfValues[3];
+
+    double dfVal0 = 0.0;
     if( dfAbsX_0 <= 1.0 )
-        dfVal0 = dfX2_0 * (1.5 * dfAbsX_0 - 2.5) + 1;
+        dfVal0 = dfX2_0 * (1.5 * dfAbsX_0 - 2.5) + 1.0;
     else if( dfAbsX_0 <= 2.0 )
-        dfVal0 = dfX2_0 * (-0.5 * dfAbsX_0 + 2.5) - 4 * dfAbsX_0 + 2;
-    else
-        dfVal0 = 0.0;
+        dfVal0 = dfX2_0 * (-0.5 * dfAbsX_0 + 2.5) - 4.0 * dfAbsX_0 + 2.0;
+
+    double dfVal1 = 0.0;
     if( dfAbsX_1 <= 1.0 )
-        dfVal1 = dfX2_1 * (1.5 * dfAbsX_1 - 2.5) + 1;
+        dfVal1 = dfX2_1 * (1.5 * dfAbsX_1 - 2.5) + 1.0;
     else if( dfAbsX_1 <= 2.0 )
-        dfVal1 = dfX2_1 * (-0.5 * dfAbsX_1 + 2.5) - 4 * dfAbsX_1 + 2;
-    else
-        dfVal1 = 0.0;
+        dfVal1 = dfX2_1 * (-0.5 * dfAbsX_1 + 2.5) - 4.0 * dfAbsX_1 + 2.0;
+
+    double dfVal2 = 0.0;
     if( dfAbsX_2 <= 1.0 )
-        dfVal2 = dfX2_2 * (1.5 * dfAbsX_2 - 2.5) + 1;
+        dfVal2 = dfX2_2 * (1.5 * dfAbsX_2 - 2.5) + 1.0;
     else if( dfAbsX_2 <= 2.0 )
-        dfVal2 = dfX2_2 * (-0.5 * dfAbsX_2 + 2.5) - 4 * dfAbsX_2 + 2;
-    else
-        dfVal2 = 0.0;
+        dfVal2 = dfX2_2 * (-0.5 * dfAbsX_2 + 2.5) - 4.0 * dfAbsX_2 + 2.0;
+
+    double dfVal3 = 0.0;
     if( dfAbsX_3 <= 1.0 )
-        dfVal3 = dfX2_3 * (1.5 * dfAbsX_3 - 2.5) + 1;
+        dfVal3 = dfX2_3 * (1.5 * dfAbsX_3 - 2.5) + 1.0;
     else if( dfAbsX_3 <= 2.0 )
-        dfVal3 = dfX2_3 * (-0.5 * dfAbsX_3 + 2.5) - 4 * dfAbsX_3 + 2;
-    else
-        dfVal3 = 0.0;
+        dfVal3 = dfX2_3 * (-0.5 * dfAbsX_3 + 2.5) - 4.0 * dfAbsX_3 + 2.0;
 
     padfValues[0] = dfVal0;
     padfValues[1] = dfVal1;
@@ -2523,47 +3137,52 @@ static double GWKCubic4Values( double* padfValues )
 /*                           GWKBSpline()                               */
 /************************************************************************/
 
-/* http://www.cs.utexas.edu/users/fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf with (B,C)=(1,0) */
-/* 1/6 * ( 3 * |x|^3 -  6 * |x|^2 + 4) |x| < 1
-   1/6 * ( -|x|^3 + 6 |x|^2  - 12|x| + 8) |x| > 1
-*/
+// http://www.cs.utexas.edu/users/fussell/courses/cs384g/lectures/mitchell/Mitchell.pdf
+// with (B,C)=(1,0)
+// 1/6 * ( 3 * |x|^3 -  6 * |x|^2 + 4) |x| < 1
+// 1/6 * ( -|x|^3 + 6 |x|^2  - 12|x| + 8) |x| > 1
+
 static double GWKBSpline( double x )
 {
-    double xp2 = x + 2.0;
-    double xp1 = x + 1.0;
-    double xm1 = x - 1.0;
+    const double xp2 = x + 2.0;
+    const double xp1 = x + 1.0;
+    const double xm1 = x - 1.0;
 
     // This will most likely be used, so we'll compute it ahead of time to
-    // avoid stalling the processor
-    double xp2c = xp2 * xp2 * xp2;
-
-    // Note that the test is computed only if it is needed
-    return (((xp2 > 0.0)?((xp1 > 0.0)?((x > 0.0)?((xm1 > 0.0)?
-                                                  -4.0 * xm1*xm1*xm1:0.0) +
-                                       6.0 * x*x*x:0.0) +
-                          -4.0 * xp1*xp1*xp1:0.0) +
-             xp2c:0.0) ) /* * 0.166666666666666666666 */;
+    // avoid stalling the processor.
+    const double xp2c = xp2 * xp2 * xp2;
+
+    // Note that the test is computed only if it is needed.
+    // TODO(schwehr): Make this easier to follow.
+    return
+        xp2 > 0.0
+        ? ((xp1 > 0.0)?((x > 0.0)?((xm1 > 0.0)?
+                                   -4.0 * xm1*xm1*xm1:0.0) +
+                        6.0 * x*x*x:0.0) +
+           -4.0 * xp1*xp1*xp1:0.0) + xp2c
+        : 0.0;  // * 0.166666666666666666666
 }
 
 static double GWKBSpline4Values( double* padfValues )
 {
-    for(int i=0;i<4;i++)
+    for( int i = 0; i < 4; i++ )
     {
-        double x = padfValues[i];
-        double xp2 = x + 2.0;
-        double xp1 = x + 1.0;
-        double xm1 = x - 1.0;
+        const double x = padfValues[i];
+        const double xp2 = x + 2.0;
+        const double xp1 = x + 1.0;
+        const double xm1 = x - 1.0;
 
         // This will most likely be used, so we'll compute it ahead of time to
-        // avoid stalling the processor
-        double xp2c = xp2 * xp2 * xp2;
+        // avoid stalling the processor.
+        const double xp2c = xp2 * xp2 * xp2;
 
-        // Note that the test is computed only if it is needed
-        padfValues[i] = (((xp2 > 0.0)?((xp1 > 0.0)?((x > 0.0)?((xm1 > 0.0)?
+        // Note that the test is computed only if it is needed.
+        // TODO(schwehr): Make this easier to follow.
+        padfValues[i] = (xp2 > 0.0)?((xp1 > 0.0)?((x > 0.0)?((xm1 > 0.0)?
                                                     -4.0 * xm1*xm1*xm1:0.0) +
                                         6.0 * x*x*x:0.0) +
                             -4.0 * xp1*xp1*xp1:0.0) +
-                xp2c:0.0) ) /* * 0.166666666666666666666 */;
+                xp2c:0.0;  // * 0.166666666666666666666
     }
     return padfValues[0] + padfValues[1] + padfValues[2] + padfValues[3];
 }
@@ -2573,28 +3192,27 @@ static double GWKBSpline4Values( double* padfValues )
 
 typedef struct _GWKResampleWrkStruct GWKResampleWrkStruct;
 
-typedef int (*pfnGWKResampleType) ( GDALWarpKernel *poWK, int iBand,
-                                    double dfSrcX, double dfSrcY,
-                                    double *pdfDensity,
-                                    double *pdfReal, double *pdfImag,
-                                    GWKResampleWrkStruct* psWrkStruct );
-
+typedef bool (*pfnGWKResampleType) ( GDALWarpKernel *poWK, int iBand,
+                                     double dfSrcX, double dfSrcY,
+                                     double *pdfDensity,
+                                     double *pdfReal, double *pdfImag,
+                                     GWKResampleWrkStruct* psWrkStruct );
 
 struct _GWKResampleWrkStruct
 {
     pfnGWKResampleType pfnGWKResample;
 
-    // Space for saved X weights
+    // Space for saved X weights.
     double  *padfWeightsX;
-    char    *panCalcX;
+    bool    *pabCalcX;
 
-    double  *padfWeightsY; // only used by GWKResampleOptimizedLanczos
-    int      iLastSrcX; // only used by GWKResampleOptimizedLanczos
-    int      iLastSrcY; // only used by GWKResampleOptimizedLanczos
-    double   dfLastDeltaX; // only used by GWKResampleOptimizedLanczos
-    double   dfLastDeltaY; // only used by GWKResampleOptimizedLanczos
+    double  *padfWeightsY; // Only used by GWKResampleOptimizedLanczos.
+    int      iLastSrcX; // Only used by GWKResampleOptimizedLanczos.
+    int      iLastSrcY; // Only used by GWKResampleOptimizedLanczos.
+    double   dfLastDeltaX; // Only used by GWKResampleOptimizedLanczos.
+    double   dfLastDeltaY; // Only used by GWKResampleOptimizedLanczos.
 
-    // Space for saving a row of pixels
+    // Space for saving a row of pixels.
     double  *padfRowDensity;
     double  *padfRowReal;
     double  *padfRowImag;
@@ -2604,13 +3222,13 @@ struct _GWKResampleWrkStruct
 /*                    GWKResampleCreateWrkStruct()                      */
 /************************************************************************/
 
-static int GWKResample( GDALWarpKernel *poWK, int iBand,
+static bool GWKResample( GDALWarpKernel *poWK, int iBand,
                         double dfSrcX, double dfSrcY,
                         double *pdfDensity,
                         double *pdfReal, double *pdfImag,
                         GWKResampleWrkStruct* psWrkStruct );
 
-static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
+static bool GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
                                         double dfSrcX, double dfSrcY,
                                         double *pdfDensity,
                                         double *pdfReal, double *pdfImag,
@@ -2618,23 +3236,26 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
 
 static GWKResampleWrkStruct* GWKResampleCreateWrkStruct(GDALWarpKernel *poWK)
 {
-    int     nXDist = ( poWK->nXRadius + 1 ) * 2;
-    int     nYDist = ( poWK->nYRadius + 1 ) * 2;
+    const int nXDist = ( poWK->nXRadius + 1 ) * 2;
+    const int nYDist = ( poWK->nYRadius + 1 ) * 2;
 
-    GWKResampleWrkStruct* psWrkStruct =
-            (GWKResampleWrkStruct*)CPLMalloc(sizeof(GWKResampleWrkStruct));
+    GWKResampleWrkStruct* psWrkStruct = static_cast<GWKResampleWrkStruct *>(
+        CPLMalloc(sizeof(GWKResampleWrkStruct)));
 
-    // Alloc space for saved X weights
-    psWrkStruct->padfWeightsX = (double *)CPLCalloc( nXDist, sizeof(double) );
-    psWrkStruct->panCalcX = (char *)CPLMalloc( nXDist * sizeof(char) );
+    // Alloc space for saved X weights.
+    psWrkStruct->padfWeightsX =
+        static_cast<double *>(CPLCalloc( nXDist, sizeof(double)));
+    psWrkStruct->pabCalcX =
+        static_cast<bool *>(CPLMalloc(nXDist * sizeof(bool)));
 
-    psWrkStruct->padfWeightsY = (double *)CPLCalloc( nYDist, sizeof(double) );
+    psWrkStruct->padfWeightsY =
+        static_cast<double *>(CPLCalloc(nYDist, sizeof(double)));
     psWrkStruct->iLastSrcX = -10;
     psWrkStruct->iLastSrcY = -10;
     psWrkStruct->dfLastDeltaX = -10;
     psWrkStruct->dfLastDeltaY = -10;
 
-    // Alloc space for saving a row of pixels
+    // Alloc space for saving a row of pixels.
     if( poWK->pafUnifiedSrcDensity == NULL &&
         poWK->panUnifiedSrcValid == NULL &&
         poWK->papanBandSrcValid == NULL )
@@ -2643,10 +3264,13 @@ static GWKResampleWrkStruct* GWKResampleCreateWrkStruct(GDALWarpKernel *poWK)
     }
     else
     {
-        psWrkStruct->padfRowDensity = (double *)CPLCalloc( nXDist, sizeof(double) );
+        psWrkStruct->padfRowDensity =
+            static_cast<double *>(CPLCalloc(nXDist, sizeof(double)));
     }
-    psWrkStruct->padfRowReal = (double *)CPLCalloc( nXDist, sizeof(double) );
-    psWrkStruct->padfRowImag = (double *)CPLCalloc( nXDist, sizeof(double) );
+    psWrkStruct->padfRowReal =
+        static_cast<double *>(CPLCalloc(nXDist, sizeof(double)));
+    psWrkStruct->padfRowImag =
+        static_cast<double *>(CPLCalloc(nXDist, sizeof(double)));
 
     if( poWK->eResample == GRA_Lanczos )
     {
@@ -2655,13 +3279,14 @@ static GWKResampleWrkStruct* GWKResampleCreateWrkStruct(GDALWarpKernel *poWK)
         const double dfXScale = poWK->dfXScale;
         if( dfXScale < 1.0 )
         {
-            int iMin = poWK->nFiltInitX, iMax = poWK->nXRadius;
+            int iMin = poWK->nFiltInitX;
+            int iMax = poWK->nXRadius;
             while( iMin * dfXScale < -3.0 )
-                iMin ++;
+                iMin++;
             while( iMax * dfXScale > 3.0 )
-                iMax --;
+                iMax--;
 
-            for(int i = iMin; i <= iMax; ++i)
+            for( int i = iMin; i <= iMax; ++i )
             {
                 psWrkStruct->padfWeightsX[i-poWK->nFiltInitX] =
                     GWKLanczosSinc(i * dfXScale);
@@ -2671,13 +3296,14 @@ static GWKResampleWrkStruct* GWKResampleCreateWrkStruct(GDALWarpKernel *poWK)
         const double dfYScale = poWK->dfYScale;
         if( dfYScale < 1.0 )
         {
-            int jMin = poWK->nFiltInitY, jMax = poWK->nYRadius;
+            int jMin = poWK->nFiltInitY;
+            int jMax = poWK->nYRadius;
             while( jMin * dfYScale < -3.0 )
-                jMin ++;
+                jMin++;
             while( jMax * dfYScale > 3.0 )
-                jMax --;
+                jMax--;
 
-            for(int j = jMin; j <= jMax; ++j)
+            for( int j = jMin; j <= jMax; ++j )
             {
                 psWrkStruct->padfWeightsY[j-poWK->nFiltInitY] =
                     GWKLanczosSinc(j * dfYScale);
@@ -2698,7 +3324,7 @@ static void GWKResampleDeleteWrkStruct(GWKResampleWrkStruct* psWrkStruct)
 {
     CPLFree( psWrkStruct->padfWeightsX );
     CPLFree( psWrkStruct->padfWeightsY );
-    CPLFree( psWrkStruct->panCalcX );
+    CPLFree( psWrkStruct->pabCalcX );
     CPLFree( psWrkStruct->padfRowDensity );
     CPLFree( psWrkStruct->padfRowReal );
     CPLFree( psWrkStruct->padfRowImag );
@@ -2709,56 +3335,58 @@ static void GWKResampleDeleteWrkStruct(GWKResampleWrkStruct* psWrkStruct)
 /*                           GWKResample()                              */
 /************************************************************************/
 
-static int GWKResample( GDALWarpKernel *poWK, int iBand,
+static bool GWKResample( GDALWarpKernel *poWK, int iBand,
                         double dfSrcX, double dfSrcY,
                         double *pdfDensity,
                         double *pdfReal, double *pdfImag,
                         GWKResampleWrkStruct* psWrkStruct )
 
 {
-    // Save as local variables to avoid following pointers in loops
-    const int     nSrcXSize = poWK->nSrcXSize;
-    const int     nSrcYSize = poWK->nSrcYSize;
-
-    double  dfAccumulatorReal = 0.0, dfAccumulatorImag = 0.0;
-    double  dfAccumulatorDensity = 0.0;
-    double  dfAccumulatorWeight = 0.0;
-    const int     iSrcX = (int) floor( dfSrcX - 0.5 );
-    const int     iSrcY = (int) floor( dfSrcY - 0.5 );
-    const int     iSrcOffset = iSrcX + iSrcY * nSrcXSize;
-    const double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
-    const double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
-
-    const double  dfXScale = poWK->dfXScale, dfYScale = poWK->dfYScale;
-
-    int     i, j;
-    const int     nXDist = ( poWK->nXRadius + 1 ) * 2;
-
-    // Space for saved X weights
-    double  *padfWeightsX = psWrkStruct->padfWeightsX;
-    char    *panCalcX = psWrkStruct->panCalcX;
-
-    // Space for saving a row of pixels
-    double  *padfRowDensity = psWrkStruct->padfRowDensity;
-    double  *padfRowReal = psWrkStruct->padfRowReal;
-    double  *padfRowImag = psWrkStruct->padfRowImag;
+    // Save as local variables to avoid following pointers in loops.
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
+
+    double dfAccumulatorReal = 0.0;
+    double dfAccumulatorImag = 0.0;
+    double dfAccumulatorDensity = 0.0;
+    double dfAccumulatorWeight = 0.0;
+    const int iSrcX = static_cast<int>(floor(dfSrcX - 0.5));
+    const int iSrcY = static_cast<int>(floor(dfSrcY - 0.5));
+    const int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+    const double dfDeltaX = dfSrcX - 0.5 - iSrcX;
+    const double dfDeltaY = dfSrcY - 0.5 - iSrcY;
+
+    const double dfXScale = poWK->dfXScale;
+    const double dfYScale = poWK->dfYScale;
+
+    const int nXDist = ( poWK->nXRadius + 1 ) * 2;
+
+    // Space for saved X weights.
+    double *padfWeightsX = psWrkStruct->padfWeightsX;
+    bool *pabCalcX = psWrkStruct->pabCalcX;
+
+    // Space for saving a row of pixels.
+    double *padfRowDensity = psWrkStruct->padfRowDensity;
+    double *padfRowReal = psWrkStruct->padfRowReal;
+    double *padfRowImag = psWrkStruct->padfRowImag;
 
     // Mark as needing calculation (don't calculate the weights yet,
-    // because a mask may render it unnecessary)
-    memset( panCalcX, FALSE, nXDist * sizeof(char) );
+    // because a mask may render it unnecessary).
+    memset( pabCalcX, false, nXDist * sizeof(bool) );
 
     FilterFuncType pfnGetWeight = apfGWKFilter[poWK->eResample];
     CPLAssert(pfnGetWeight);
 
-    // Skip sampling over edge of image
-    j = poWK->nFiltInitY;
+    // Skip sampling over edge of image.
+    int j = poWK->nFiltInitY;
     int jMax= poWK->nYRadius;
     if( iSrcY + j < 0 )
         j = -iSrcY;
     if( iSrcY + jMax >= nSrcYSize )
         jMax = nSrcYSize - iSrcY - 1;
 
-    int iMin = poWK->nFiltInitX, iMax = poWK->nXRadius;
+    int iMin = poWK->nFiltInitX;
+    int iMax = poWK->nXRadius;
     if( iSrcX + iMin < 0 )
         iMin = -iSrcX;
     if( iSrcX + iMax >= nSrcXSize )
@@ -2769,57 +3397,54 @@ static int GWKResample( GDALWarpKernel *poWK, int iBand,
 
     int iRowOffset = iSrcOffset + (j - 1) * nSrcXSize + iMin;
 
-    // Loop over pixel rows in the kernel
-    for ( ; j <= jMax; ++j )
+    // Loop over pixel rows in the kernel.
+    for( ; j <= jMax; ++j )
     {
-        double  dfWeight1;
-
         iRowOffset += nSrcXSize;
 
-        // Get pixel values
-        // We can potentially read extra elements after the "normal" end of the source arrays,
-        // but the contract of papabySrcImage[iBand], papanBandSrcValid[iBand],
-        // panUnifiedSrcValid and pafUnifiedSrcDensity is to have WARP_EXTRA_ELTS
-        // reserved at their end.
-        if ( !GWKGetPixelRow( poWK, iBand, iRowOffset, (iMax-iMin+2)/2,
-                              padfRowDensity, padfRowReal, padfRowImag ) )
+        // Get pixel values.
+        // We can potentially read extra elements after the "normal" end of the
+        // source arrays, but the contract of papabySrcImage[iBand],
+        // papanBandSrcValid[iBand], panUnifiedSrcValid and pafUnifiedSrcDensity
+        // is to have WARP_EXTRA_ELTS reserved at their end.
+        if( !GWKGetPixelRow( poWK, iBand, iRowOffset, (iMax-iMin+2)/2,
+                             padfRowDensity, padfRowReal, padfRowImag ) )
             continue;
 
-         // Calculate the Y weight
-        dfWeight1 = ( bYScaleBelow1 ) ?
+        // Calculate the Y weight.
+        double dfWeight1 = ( bYScaleBelow1 ) ?
                 pfnGetWeight((j - dfDeltaY) * dfYScale):
                 pfnGetWeight(j - dfDeltaY);
 
-
-        // Iterate over pixels in row
+        // Iterate over pixels in row.
         double dfAccumulatorRealLocal = 0.0;
         double dfAccumulatorImagLocal = 0.0;
         double dfAccumulatorDensityLocal = 0.0;
         double dfAccumulatorWeightLocal = 0.0;
 
-        for (i = iMin; i <= iMax; ++i )
+        for( int i = iMin; i <= iMax; ++i )
         {
-            double dfWeight2;
-
-            // Skip sampling if pixel has zero density
-            if ( padfRowDensity != NULL &&
-                 padfRowDensity[i-iMin] < 0.000000001 )
+            // Skip sampling if pixel has zero density.
+            if( padfRowDensity != NULL &&
+                padfRowDensity[i-iMin] < SRC_DENSITY_THRESHOLD )
                 continue;
 
-            // Make or use a cached set of weights for this row
-            if ( panCalcX[i-iMin] )
+            double dfWeight2 = 0.0;
+
+            // Make or use a cached set of weights for this row.
+            if( pabCalcX[i-iMin] )
             {
-                // Use saved weight value instead of recomputing it
+                // Use saved weight value instead of recomputing it.
                 dfWeight2 = padfWeightsX[i-iMin];
             }
             else
             {
-                // Calculate & save the X weight
+                // Calculate & save the X weight.
                 padfWeightsX[i-iMin] = dfWeight2 = ( bXScaleBelow1 ) ?
                         pfnGetWeight((i - dfDeltaX) * dfXScale):
                         pfnGetWeight(i - dfDeltaX);
 
-                panCalcX[i-iMin] = TRUE;
+                pabCalcX[i-iMin] = true;
             }
 
             // Accumulate!
@@ -2836,15 +3461,15 @@ static int GWKResample( GDALWarpKernel *poWK, int iBand,
         dfAccumulatorWeight += dfAccumulatorWeightLocal * dfWeight1;
     }
 
-    if ( dfAccumulatorWeight < 0.000001 ||
-         (padfRowDensity != NULL && dfAccumulatorDensity < 0.000001) )
+    if( dfAccumulatorWeight < 0.000001 ||
+        (padfRowDensity != NULL && dfAccumulatorDensity < 0.000001) )
     {
         *pdfDensity = 0.0;
-        return FALSE;
+        return false;
     }
 
-    // Calculate the output taking into account weighting
-    if ( dfAccumulatorWeight < 0.99999 || dfAccumulatorWeight > 1.00001 )
+    // Calculate the output taking into account weighting.
+    if( dfAccumulatorWeight < 0.99999 || dfAccumulatorWeight > 1.00001 )
     {
         *pdfReal = dfAccumulatorReal / dfAccumulatorWeight;
         *pdfImag = dfAccumulatorImag / dfAccumulatorWeight;
@@ -2863,52 +3488,56 @@ static int GWKResample( GDALWarpKernel *poWK, int iBand,
             *pdfDensity = 1.0;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                      GWKResampleOptimizedLanczos()                   */
 /************************************************************************/
 
-static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
+static bool GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
                         double dfSrcX, double dfSrcY,
                         double *pdfDensity,
                         double *pdfReal, double *pdfImag,
                         GWKResampleWrkStruct* psWrkStruct )
 
 {
-    // Save as local variables to avoid following pointers in loops
-    const int     nSrcXSize = poWK->nSrcXSize;
-    const int     nSrcYSize = poWK->nSrcYSize;
-
-    double  dfAccumulatorReal = 0.0, dfAccumulatorImag = 0.0;
-    double  dfAccumulatorDensity = 0.0;
-    double  dfAccumulatorWeight = 0.0;
+    // Save as local variables to avoid following pointers in loops.
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
+
+    double dfAccumulatorReal = 0.0;
+    double dfAccumulatorImag = 0.0;
+    double dfAccumulatorDensity = 0.0;
+    double dfAccumulatorWeight = 0.0;
     const int     iSrcX = (int) floor( dfSrcX - 0.5 );
     const int     iSrcY = (int) floor( dfSrcY - 0.5 );
     const int     iSrcOffset = iSrcX + iSrcY * nSrcXSize;
     const double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
     const double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
 
-    const double  dfXScale = poWK->dfXScale, dfYScale = poWK->dfYScale;
+    const double dfXScale = poWK->dfXScale;
+    const double dfYScale = poWK->dfYScale;
 
-    // Space for saved X weights
-    double  *padfWeightsX = psWrkStruct->padfWeightsX;
-    double  *padfWeightsY = psWrkStruct->padfWeightsY;
+    // Space for saved X weights.
+    double *padfWeightsX = psWrkStruct->padfWeightsX;
+    double *padfWeightsY = psWrkStruct->padfWeightsY;
 
-    // Space for saving a row of pixels
-    double  *padfRowDensity = psWrkStruct->padfRowDensity;
-    double  *padfRowReal = psWrkStruct->padfRowReal;
-    double  *padfRowImag = psWrkStruct->padfRowImag;
+    // Space for saving a row of pixels.
+    double *padfRowDensity = psWrkStruct->padfRowDensity;
+    double *padfRowReal = psWrkStruct->padfRowReal;
+    double *padfRowImag = psWrkStruct->padfRowImag;
 
-    // Skip sampling over edge of image
-    int jMin = poWK->nFiltInitY, jMax= poWK->nYRadius;
+    // Skip sampling over edge of image.
+    int jMin = poWK->nFiltInitY;
+    int jMax = poWK->nYRadius;
     if( iSrcY + jMin < 0 )
         jMin = -iSrcY;
     if( iSrcY + jMax >= nSrcYSize )
         jMax = nSrcYSize - iSrcY - 1;
 
-    int iMin = poWK->nFiltInitX, iMax = poWK->nXRadius;
+    int iMin = poWK->nFiltInitX;
+    int iMax = poWK->nXRadius;
     if( iSrcX + iMin < 0 )
         iMin = -iSrcX;
     if( iSrcX + iMax >= nSrcXSize )
@@ -2917,60 +3546,68 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
     if( dfXScale < 1.0 )
     {
         while( iMin * dfXScale < -3.0 )
-            iMin ++;
+            iMin++;
         while( iMax * dfXScale > 3.0 )
-            iMax --;
-        // padfWeightsX computed in GWKResampleCreateWrkStruct
+            iMax--;
+        // padfWeightsX computed in GWKResampleCreateWrkStruct.
     }
     else
     {
         while( iMin - dfDeltaX < -3.0 )
-            iMin ++;
+            iMin++;
         while( iMax - dfDeltaX > 3.0 )
-            iMax --;
+            iMax--;
 
         if( iSrcX != psWrkStruct->iLastSrcX ||
             dfDeltaX != psWrkStruct->dfLastDeltaX )
         {
-            // Optimisation of GWKLanczosSinc(i - dfDeltaX) based on the following
-            // trigonometric formulas.
-
-    //sin(M_PI * (dfBase + k)) = sin(M_PI * dfBase) * cos(M_PI * k) + cos(M_PI * dfBase) * sin(M_PI * k)
-    //sin(M_PI * (dfBase + k)) = dfSinPIBase * cos(M_PI * k) + dfCosPIBase * sin(M_PI * k)
-    //sin(M_PI * (dfBase + k)) = dfSinPIBase * cos(M_PI * k)
-    //sin(M_PI * (dfBase + k)) = dfSinPIBase * (((k % 2) == 0) ? 1 : -1)
-
-    //sin(M_PI / dfR * (dfBase + k)) = sin(M_PI / dfR * dfBase) * cos(M_PI / dfR * k) + cos(M_PI / dfR * dfBase) * sin(M_PI / dfR * k)
-    //sin(M_PI / dfR * (dfBase + k)) = dfSinPIBaseOverR * cos(M_PI / dfR * k) + dfCosPIBaseOverR * sin(M_PI / dfR * k)
-
-            double dfSinPIDeltaXOver3 = sin((-M_PI / 3) * dfDeltaX);
-            double dfSin2PIDeltaXOver3 = dfSinPIDeltaXOver3 * dfSinPIDeltaXOver3;
-            /* ok to use sqrt(1-sin^2) since M_PI / 3 * dfDeltaX < PI/2 */
-            double dfCosPIDeltaXOver3 = sqrt(1 - dfSin2PIDeltaXOver3);
-            double dfSinPIDeltaX = (3-4*dfSin2PIDeltaXOver3)*dfSinPIDeltaXOver3;
+            // Optimisation of GWKLanczosSinc(i - dfDeltaX) based on the
+            // following trigonometric formulas.
+
+// TODO(schwehr): Move this somewhere where it can be rendered at LaTeX.
+// sin(M_PI * (dfBase + k)) = sin(M_PI * dfBase) * cos(M_PI * k) + cos(M_PI * dfBase) * sin(M_PI * k)
+// sin(M_PI * (dfBase + k)) = dfSinPIBase * cos(M_PI * k) + dfCosPIBase * sin(M_PI * k)
+// sin(M_PI * (dfBase + k)) = dfSinPIBase * cos(M_PI * k)
+// sin(M_PI * (dfBase + k)) = dfSinPIBase * (((k % 2) == 0) ? 1 : -1)
+
+// sin(M_PI / dfR * (dfBase + k)) = sin(M_PI / dfR * dfBase) * cos(M_PI / dfR * k) + cos(M_PI / dfR * dfBase) * sin(M_PI / dfR * k)
+// sin(M_PI / dfR * (dfBase + k)) = dfSinPIBaseOverR * cos(M_PI / dfR * k) + dfCosPIBaseOverR * sin(M_PI / dfR * k)
+
+            const double dfSinPIDeltaXOver3 = sin((-M_PI / 3.0) * dfDeltaX);
+            const double dfSin2PIDeltaXOver3 =
+                dfSinPIDeltaXOver3 * dfSinPIDeltaXOver3;
+            // Ok to use sqrt(1-sin^2) since M_PI / 3 * dfDeltaX < PI/2.
+            const double dfCosPIDeltaXOver3 = sqrt(1.0 - dfSin2PIDeltaXOver3);
+            const double dfSinPIDeltaX =
+                (3.0 - 4 * dfSin2PIDeltaXOver3) * dfSinPIDeltaXOver3;
             const double dfInvPI2Over3 = 3.0 / (M_PI * M_PI);
-            double dfInvPI2Over3xSinPIDeltaX = dfInvPI2Over3 * dfSinPIDeltaX;
-            double dfInvPI2Over3xSinPIDeltaXxm0d5SinPIDeltaXOver3 =
+            const double dfInvPI2Over3xSinPIDeltaX =
+                dfInvPI2Over3 * dfSinPIDeltaX;
+            const double dfInvPI2Over3xSinPIDeltaXxm0d5SinPIDeltaXOver3 =
                 -0.5 * dfInvPI2Over3xSinPIDeltaX * dfSinPIDeltaXOver3;
             const double dfSinPIOver3 = 0.8660254037844386;
-            double dfInvPI2Over3xSinPIDeltaXxSinPIOver3xCosPIDeltaXOver3 =
+            const double dfInvPI2Over3xSinPIDeltaXxSinPIOver3xCosPIDeltaXOver3 =
                 dfSinPIOver3 * dfInvPI2Over3xSinPIDeltaX * dfCosPIDeltaXOver3;
-            double padfCst[] = {
+            const double padfCst[] = {
                 dfInvPI2Over3xSinPIDeltaX * dfSinPIDeltaXOver3,
                 dfInvPI2Over3xSinPIDeltaXxm0d5SinPIDeltaXOver3 -
                         dfInvPI2Over3xSinPIDeltaXxSinPIOver3xCosPIDeltaXOver3,
                 dfInvPI2Over3xSinPIDeltaXxm0d5SinPIDeltaXOver3 +
                         dfInvPI2Over3xSinPIDeltaXxSinPIOver3xCosPIDeltaXOver3 };
 
-            for (int i = iMin; i <= iMax; ++i )
+            for( int i = iMin; i <= iMax; ++i )
             {
                 const double dfX = i - dfDeltaX;
-                if (dfX == 0.0)
+                if( dfX == 0.0 )
                     padfWeightsX[i-poWK->nFiltInitX] = 1.0;
                 else
                     padfWeightsX[i-poWK->nFiltInitX] =
                                             padfCst[(i + 3) % 3] / (dfX * dfX);
-                //CPLAssert(fabs(padfWeightsX[i-poWK->nFiltInitX] - GWKLanczosSinc(dfX, 3.0)) < 1e-10);
+#if DEBUG_VERBOSE
+                // TODO(schwehr): AlmostEqual.
+                CPLAssert(fabs(padfWeightsX[i-poWK->nFiltInitX] -
+                               GWKLanczosSinc(dfX, 3.0)) < 1e-10);
+#endif
             }
 
             psWrkStruct->iLastSrcX = iSrcX;
@@ -2981,49 +3618,56 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
     if( dfYScale < 1.0 )
     {
         while( jMin * dfYScale < -3.0 )
-            jMin ++;
+            jMin++;
         while( jMax * dfYScale > 3.0 )
-            jMax --;
-        // padfWeightsY computed in GWKResampleCreateWrkStruct
+            jMax--;
+        // padfWeightsY computed in GWKResampleCreateWrkStruct.
     }
     else
     {
         while( jMin - dfDeltaY < -3.0 )
-            jMin ++;
+            jMin++;
         while( jMax - dfDeltaY > 3.0 )
-            jMax --;
+            jMax--;
 
         if( iSrcY != psWrkStruct->iLastSrcY ||
             dfDeltaY != psWrkStruct->dfLastDeltaY )
         {
-            double dfSinPIDeltaYOver3 = sin((-M_PI / 3) * dfDeltaY);
-            double dfSin2PIDeltaYOver3 = dfSinPIDeltaYOver3 * dfSinPIDeltaYOver3;
-            /* ok to use sqrt(1-sin^2) since M_PI / 3 * dfDeltaY < PI/2 */
-            double dfCosPIDeltaYOver3 = sqrt(1 - dfSin2PIDeltaYOver3);
-            double dfSinPIDeltaY = (3-4*dfSin2PIDeltaYOver3)*dfSinPIDeltaYOver3;
+            const double dfSinPIDeltaYOver3 = sin((-M_PI / 3.0) * dfDeltaY);
+            const double dfSin2PIDeltaYOver3 =
+                dfSinPIDeltaYOver3 * dfSinPIDeltaYOver3;
+            // Ok to use sqrt(1-sin^2) since M_PI / 3 * dfDeltaY < PI/2.
+            const double dfCosPIDeltaYOver3 = sqrt(1.0 - dfSin2PIDeltaYOver3);
+            const double dfSinPIDeltaY =
+                (3.0 - 4.0 * dfSin2PIDeltaYOver3) * dfSinPIDeltaYOver3;
             const double dfInvPI2Over3 = 3.0 / (M_PI * M_PI);
-            double dfInvPI2Over3xSinPIDeltaY = dfInvPI2Over3 * dfSinPIDeltaY;
-            double dfInvPI2Over3xSinPIDeltaYxm0d5SinPIDeltaYOver3 =
+            const double dfInvPI2Over3xSinPIDeltaY =
+                dfInvPI2Over3 * dfSinPIDeltaY;
+            const double dfInvPI2Over3xSinPIDeltaYxm0d5SinPIDeltaYOver3 =
                 -0.5 * dfInvPI2Over3xSinPIDeltaY * dfSinPIDeltaYOver3;
             const double dfSinPIOver3 = 0.8660254037844386;
-            double dfInvPI2Over3xSinPIDeltaYxSinPIOver3xCosPIDeltaYOver3 =
+            const double dfInvPI2Over3xSinPIDeltaYxSinPIOver3xCosPIDeltaYOver3 =
                 dfSinPIOver3 * dfInvPI2Over3xSinPIDeltaY * dfCosPIDeltaYOver3;
-            double padfCst[] = {
+            const double padfCst[] = {
                 dfInvPI2Over3xSinPIDeltaY * dfSinPIDeltaYOver3,
                 dfInvPI2Over3xSinPIDeltaYxm0d5SinPIDeltaYOver3 -
                         dfInvPI2Over3xSinPIDeltaYxSinPIOver3xCosPIDeltaYOver3,
                 dfInvPI2Over3xSinPIDeltaYxm0d5SinPIDeltaYOver3 +
                         dfInvPI2Over3xSinPIDeltaYxSinPIOver3xCosPIDeltaYOver3 };
 
-            for ( int j = jMin; j <= jMax; ++j )
+            for( int j = jMin; j <= jMax; ++j )
             {
                 const double dfY = j - dfDeltaY;
-                if (dfY == 0.0)
+                if( dfY == 0.0 )
                     padfWeightsY[j-poWK->nFiltInitY] = 1.0;
                 else
                     padfWeightsY[j-poWK->nFiltInitY] =
                                             padfCst[(j + 3) % 3] / (dfY * dfY);
-                //CPLAssert(fabs(padfWeightsY[j-poWK->nFiltInitY] - GWKLanczosSinc(dfY, 3.0)) < 1e-10);
+#if DEBUG_VERBOSE
+                // TODO(schwehr): AlmostEqual.
+                CPLAssert(fabs(padfWeightsY[j-poWK->nFiltInitY] -
+                               GWKLanczosSinc(dfY, 3.0)) < 1e-10);
+#endif
             }
 
             psWrkStruct->iLastSrcY = iSrcY;
@@ -3038,12 +3682,12 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
     if( padfRowDensity == NULL )
     {
         double dfRowAccWeight = 0.0;
-        for (int i = iMin; i <= iMax; ++i )
+        for( int i = iMin; i <= iMax; ++i )
         {
             dfRowAccWeight += padfWeightsX[i-poWK->nFiltInitX];
         }
         double dfColAccWeight = 0.0;
-        for ( int j = jMin; j <= jMax; ++j )
+        for( int j = jMin; j <= jMax; ++j )
         {
             dfColAccWeight += padfWeightsY[j-poWK->nFiltInitY];
         }
@@ -3052,37 +3696,34 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
 
     const bool bIsNonComplex = !GDALDataTypeIsComplex(poWK->eWorkingDataType);
 
-    // Loop over pixel rows in the kernel
-    for ( int j = jMin; j <= jMax; ++j )
+    // Loop over pixel rows in the kernel.
+    for( int j = jMin; j <= jMax; ++j )
     {
-        double  dfWeight1;
-
         iRowOffset += nSrcXSize;
 
-        // Get pixel values
-        // We can potentially read extra elements after the "normal" end of the source arrays,
-        // but the contract of papabySrcImage[iBand], papanBandSrcValid[iBand],
-        // panUnifiedSrcValid and pafUnifiedSrcDensity is to have WARP_EXTRA_ELTS
-        // reserved at their end.
-        if ( !GWKGetPixelRow( poWK, iBand, iRowOffset, (iMax-iMin+2)/2,
-                              padfRowDensity, padfRowReal, padfRowImag ) )
+        // Get pixel values.
+        // We can potentially read extra elements after the "normal" end of the
+        // source arrays, but the contract of papabySrcImage[iBand],
+        // papanBandSrcValid[iBand], panUnifiedSrcValid and pafUnifiedSrcDensity
+        // is to have WARP_EXTRA_ELTS reserved at their end.
+        if( !GWKGetPixelRow( poWK, iBand, iRowOffset, (iMax-iMin+2)/2,
+                             padfRowDensity, padfRowReal, padfRowImag ) )
             continue;
 
-        dfWeight1 = padfWeightsY[j-poWK->nFiltInitY];
+        const double dfWeight1 = padfWeightsY[j-poWK->nFiltInitY];
 
-        // Iterate over pixels in row
-        if ( padfRowDensity != NULL )
+        // Iterate over pixels in row.
+        if( padfRowDensity != NULL )
         {
-            for (int i = iMin; i <= iMax; ++i )
+            for( int i = iMin; i <= iMax; ++i )
             {
-                double dfWeight2;
-
-                // Skip sampling if pixel has zero density
-                if ( padfRowDensity[i - iMin] < 0.000000001 )
+                // Skip sampling if pixel has zero density.
+                if( padfRowDensity[i - iMin] < SRC_DENSITY_THRESHOLD )
                     continue;
 
-                //  Use a cached set of weights for this row
-                dfWeight2 = dfWeight1 * padfWeightsX[i- poWK->nFiltInitX];
+                //  Use a cached set of weights for this row.
+                const double dfWeight2 =
+                    dfWeight1 * padfWeightsX[i- poWK->nFiltInitX];
 
                 // Accumulate!
                 dfAccumulatorReal += padfRowReal[i - iMin] * dfWeight2;
@@ -3094,9 +3735,9 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
         else if( bIsNonComplex )
         {
             double dfRowAccReal = 0.0;
-            for (int i = iMin; i <= iMax; ++i )
+            for( int i = iMin; i <= iMax; ++i )
             {
-                double dfWeight2 = padfWeightsX[i- poWK->nFiltInitX];
+                const double dfWeight2 = padfWeightsX[i- poWK->nFiltInitX];
 
                 // Accumulate!
                 dfRowAccReal += padfRowReal[i - iMin] * dfWeight2;
@@ -3108,9 +3749,9 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
         {
             double dfRowAccReal = 0.0;
             double dfRowAccImag = 0.0;
-            for (int i = iMin; i <= iMax; ++i )
+            for( int i = iMin; i <= iMax; ++i )
             {
-                double dfWeight2 = padfWeightsX[i- poWK->nFiltInitX];
+                const double dfWeight2 = padfWeightsX[i- poWK->nFiltInitX];
 
                 // Accumulate!
                 dfRowAccReal += padfRowReal[i - iMin] * dfWeight2;
@@ -3122,15 +3763,15 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
         }
     }
 
-    if ( dfAccumulatorWeight < 0.000001 ||
+    if( dfAccumulatorWeight < 0.000001 ||
          (padfRowDensity != NULL && dfAccumulatorDensity < 0.000001) )
     {
         *pdfDensity = 0.0;
-        return FALSE;
+        return false;
     }
 
-    // Calculate the output taking into account weighting
-    if ( dfAccumulatorWeight < 0.99999 || dfAccumulatorWeight > 1.00001 )
+    // Calculate the output taking into account weighting.
+    if( dfAccumulatorWeight < 0.99999 || dfAccumulatorWeight > 1.00001 )
     {
         const double dfInvAcc = 1.0 / dfAccumulatorWeight;
         *pdfReal = dfAccumulatorReal * dfInvAcc;
@@ -3150,7 +3791,7 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
             *pdfDensity = 1.0;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -3158,43 +3799,42 @@ static int GWKResampleOptimizedLanczos( GDALWarpKernel *poWK, int iBand,
 /************************************************************************/
 
 template <class T>
-static int GWKResampleNoMasksT( GDALWarpKernel *poWK, int iBand,
+static bool GWKResampleNoMasksT( GDALWarpKernel *poWK, int iBand,
                                 double dfSrcX, double dfSrcY,
                                 T *pValue, double *padfWeight )
 
 {
-    // Commonly used; save locally
-    int     nSrcXSize = poWK->nSrcXSize;
-    int     nSrcYSize = poWK->nSrcYSize;
+    // Commonly used; save locally.
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
 
-    double  dfAccumulator = 0.0;
-    int     iSrcX = (int) floor( dfSrcX - 0.5 );
-    int     iSrcY = (int) floor( dfSrcY - 0.5 );
-    int     iSrcOffset = iSrcX + iSrcY * nSrcXSize;
-    double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
-    double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
+    const int iSrcX = static_cast<int>(floor(dfSrcX - 0.5));
+    const int iSrcY = static_cast<int>(floor(dfSrcY - 0.5));
+    const int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
 
-    double  dfXScale = poWK->dfXScale;
-    double  dfYScale = poWK->dfYScale;
-    int     nXRadius = poWK->nXRadius;
-    int     nYRadius = poWK->nYRadius;
+    const int nXRadius = poWK->nXRadius;
+    const int nYRadius = poWK->nYRadius;
 
-    T*  pSrcBand = (T*) poWK->papabySrcImage[iBand];
+    // Politely refuse to process invalid coordinates or obscenely small image.
+    if( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize
+        || nXRadius > nSrcXSize || nYRadius > nSrcYSize )
+        return GWKBilinearResampleNoMasks4SampleT(poWK, iBand, dfSrcX, dfSrcY,
+                                                  pValue);
 
-    // Politely refusing to process invalid coordinates or obscenely small image
-    if ( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize
-         || nXRadius > nSrcXSize || nYRadius > nSrcYSize )
-        return GWKBilinearResampleNoMasks4SampleT( poWK, iBand, dfSrcX, dfSrcY, pValue);
+    T* pSrcBand = reinterpret_cast<T*>(poWK->papabySrcImage[iBand]);
+    const double dfDeltaX = dfSrcX - 0.5 - iSrcX;
+    const double dfDeltaY = dfSrcY - 0.5 - iSrcY;
 
-    FilterFuncType pfnGetWeight = apfGWKFilter[poWK->eResample];
+    const FilterFuncType pfnGetWeight = apfGWKFilter[poWK->eResample];
     CPLAssert(pfnGetWeight);
-    FilterFunc4ValuesType pfnGetWeight4Values = apfGWKFilter4Values[poWK->eResample];
+    const FilterFunc4ValuesType pfnGetWeight4Values =
+        apfGWKFilter4Values[poWK->eResample];
     CPLAssert(pfnGetWeight4Values);
 
-    if( dfXScale > 1.0 ) dfXScale = 1.0;
-    if( dfYScale > 1.0 ) dfYScale = 1.0;
+    const double dfXScale = std::min(poWK->dfXScale, 1.0);
+    const double dfYScale = std::min(poWK->dfYScale, 1.0);
 
-    // Loop over all rows in the kernel
+    // Loop over all rows in the kernel.
     double dfAccumulatorWeightHorizontal = 0.0;
     double dfAccumulatorWeightVertical = 0.0;
 
@@ -3204,8 +3844,9 @@ static int GWKResampleNoMasksT( GDALWarpKernel *poWK, int iBand,
     int iMax = nXRadius;
     if( iSrcX + iMax >= nSrcXSize-1 )
         iMax = nSrcXSize-1 - iSrcX;
-    int i, iC;
-    for(iC = 0, i = iMin; i+2 < iMax; i+=4, iC+=4 )
+    int i = iMin;  // Used after for.
+    int iC = 0;  // Used after for.
+    for( ; i+2 < iMax; i += 4, iC += 4 )
     {
         padfWeight[iC] = (i - dfDeltaX) * dfXScale;
         padfWeight[iC+1] = padfWeight[iC] + dfXScale;
@@ -3213,9 +3854,9 @@ static int GWKResampleNoMasksT( GDALWarpKernel *poWK, int iBand,
         padfWeight[iC+3] = padfWeight[iC+2] + dfXScale;
         dfAccumulatorWeightHorizontal += pfnGetWeight4Values(padfWeight+iC);
     }
-    for(; i <= iMax; ++i, ++iC )
+    for( ; i <= iMax; ++i, ++iC )
     {
-        double dfWeight = pfnGetWeight((i - dfDeltaX) * dfXScale);
+        const double dfWeight = pfnGetWeight((i - dfDeltaX) * dfXScale);
         padfWeight[iC] = dfWeight;
         dfAccumulatorWeightHorizontal += dfWeight;
     }
@@ -3227,98 +3868,99 @@ static int GWKResampleNoMasksT( GDALWarpKernel *poWK, int iBand,
     if( iSrcY + jMax >= nSrcYSize-1 )
         jMax = nSrcYSize-1 - iSrcY;
 
-    for ( ; j <= jMax; ++j )
+    double dfAccumulator = 0.0;
+
+    for( ; j <= jMax; ++j )
     {
-        int     iSampJ = iSrcOffset + j * nSrcXSize;
+        const int iSampJ = iSrcOffset + j * nSrcXSize;
 
-        // Loop over all pixels in the row
-        double dfAccumulatorLocal = 0.0, dfAccumulatorLocal2 = 0.0;
+        // Loop over all pixels in the row.
+        double dfAccumulatorLocal = 0.0;
+        double dfAccumulatorLocal2 = 0.0;
         iC = 0;
         i = iMin;
-        /* Process by chunk of 4 cols */
-        for(; i+2 < iMax; i+=4, iC+=4 )
+        // Process by chunk of 4 cols.
+        for( ; i+2 < iMax; i += 4, iC += 4 )
         {
-            // Retrieve the pixel & accumulate
-            dfAccumulatorLocal += (double)pSrcBand[i+iSampJ] * padfWeight[iC];
-            dfAccumulatorLocal += (double)pSrcBand[i+1+iSampJ] * padfWeight[iC+1];
-            dfAccumulatorLocal2 += (double)pSrcBand[i+2+iSampJ] * padfWeight[iC+2];
-            dfAccumulatorLocal2 += (double)pSrcBand[i+3+iSampJ] * padfWeight[iC+3];
+            // Retrieve the pixel & accumulate.
+            dfAccumulatorLocal += pSrcBand[i+iSampJ] * padfWeight[iC];
+            dfAccumulatorLocal += pSrcBand[i+1+iSampJ] * padfWeight[iC+1];
+            dfAccumulatorLocal2 += pSrcBand[i+2+iSampJ] * padfWeight[iC+2];
+            dfAccumulatorLocal2 += pSrcBand[i+3+iSampJ] * padfWeight[iC+3];
         }
         dfAccumulatorLocal += dfAccumulatorLocal2;
         if( i < iMax )
         {
-            dfAccumulatorLocal += (double)pSrcBand[i+iSampJ] * padfWeight[iC];
-            dfAccumulatorLocal += (double)pSrcBand[i+1+iSampJ] * padfWeight[iC+1];
-            i+=2;
-            iC+=2;
+            dfAccumulatorLocal += pSrcBand[i+iSampJ] * padfWeight[iC];
+            dfAccumulatorLocal += pSrcBand[i+1+iSampJ] * padfWeight[iC+1];
+            i += 2;
+            iC += 2;
         }
         if( i == iMax )
         {
-            dfAccumulatorLocal += (double)pSrcBand[i+iSampJ] * padfWeight[iC];
+            dfAccumulatorLocal += pSrcBand[i+iSampJ] * padfWeight[iC];
         }
 
-        // Calculate the Y weight
-        double  dfWeight = pfnGetWeight((j - dfDeltaY) * dfYScale);
+        // Calculate the Y weight.
+        const double dfWeight = pfnGetWeight((j - dfDeltaY) * dfYScale);
         dfAccumulator += dfWeight * dfAccumulatorLocal;
         dfAccumulatorWeightVertical += dfWeight;
     }
 
-    double dfAccumulatorWeight = dfAccumulatorWeightHorizontal * dfAccumulatorWeightVertical;
+    const double dfAccumulatorWeight =
+        dfAccumulatorWeightHorizontal * dfAccumulatorWeightVertical;
 
     *pValue = GWKClampValueT<T>(dfAccumulator / dfAccumulatorWeight);
 
-    return TRUE;
+    return true;
 }
 
 /* We restrict to 64bit processors because they are guaranteed to have SSE2 */
 /* Could possibly be used too on 32bit, but we would need to check at runtime */
 #if defined(__x86_64) || defined(_M_X64)
 
-#include <gdalsse_priv.h>
-
 /************************************************************************/
 /*                    GWKResampleNoMasks_SSE2_T()                       */
 /************************************************************************/
 
 template<class T>
-static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
+static bool GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
                                       double dfSrcX, double dfSrcY,
                                       T *pValue, double *padfWeight )
 {
-    // Commonly used; save locally
-    int     nSrcXSize = poWK->nSrcXSize;
-    int     nSrcYSize = poWK->nSrcYSize;
+    // Commonly used; save locally.
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
 
-    double  dfAccumulator = 0.0;
-    int     iSrcX = (int) floor( dfSrcX - 0.5 );
-    int     iSrcY = (int) floor( dfSrcY - 0.5 );
-    int     iSrcOffset = iSrcX + iSrcY * nSrcXSize;
-    double  dfDeltaX = dfSrcX - 0.5 - iSrcX;
-    double  dfDeltaY = dfSrcY - 0.5 - iSrcY;
+    const int iSrcX = static_cast<int>(floor(dfSrcX - 0.5));
+    const int iSrcY = static_cast<int>(floor(dfSrcY - 0.5));
+    const int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
+    const int nXRadius = poWK->nXRadius;
+    const int nYRadius = poWK->nYRadius;
 
-    double  dfXScale = poWK->dfXScale;
-    double  dfYScale = poWK->dfYScale;
-    int     nXRadius = poWK->nXRadius;
-    int     nYRadius = poWK->nYRadius;
+    // Politely refuse to process invalid coordinates or obscenely small image.
+    if( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize ||
+        nXRadius > nSrcXSize || nYRadius > nSrcYSize )
+        return GWKBilinearResampleNoMasks4SampleT(poWK, iBand, dfSrcX, dfSrcY,
+                                                  pValue);
 
-    const T*  pSrcBand = (const T*) poWK->papabySrcImage[iBand];
+    const T* pSrcBand = reinterpret_cast<const T*>(poWK->papabySrcImage[iBand]);
 
-    // Politely refusing to process invalid coordinates or obscenely small image
-    if ( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize
-         || nXRadius > nSrcXSize || nYRadius > nSrcYSize )
-        return GWKBilinearResampleNoMasks4SampleT( poWK, iBand, dfSrcX, dfSrcY, pValue);
-
-    FilterFuncType pfnGetWeight = apfGWKFilter[poWK->eResample];
+    const FilterFuncType pfnGetWeight = apfGWKFilter[poWK->eResample];
     CPLAssert(pfnGetWeight);
-    FilterFunc4ValuesType pfnGetWeight4Values = apfGWKFilter4Values[poWK->eResample];
+    const FilterFunc4ValuesType pfnGetWeight4Values =
+        apfGWKFilter4Values[poWK->eResample];
     CPLAssert(pfnGetWeight4Values);
 
-    if( dfXScale > 1.0 ) dfXScale = 1.0;
-    if( dfYScale > 1.0 ) dfYScale = 1.0;
+    const double dfDeltaX = dfSrcX - 0.5 - iSrcX;
+    const double dfDeltaY = dfSrcY - 0.5 - iSrcY;
+    const double dfXScale = std::min(poWK->dfXScale, 1.0);
+    const double dfYScale = std::min(poWK->dfYScale, 1.0);
 
-    // Loop over all rows in the kernel
+    // Loop over all rows in the kernel.
     double dfAccumulatorWeightHorizontal = 0.0;
     double dfAccumulatorWeightVertical = 0.0;
+    double dfAccumulator = 0.0;
 
     int iMin = 1 - nXRadius;
     if( iSrcX + iMin < 0 )
@@ -3327,7 +3969,7 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
     if( iSrcX + iMax >= nSrcXSize-1 )
         iMax = nSrcXSize-1 - iSrcX;
     int i, iC;
-    for(iC = 0, i = iMin; i+2 < iMax; i+=4, iC+=4 )
+    for( iC = 0, i = iMin; i+2 < iMax; i+=4, iC+=4 )
     {
         padfWeight[iC] = (i - dfDeltaX) * dfXScale;
         padfWeight[iC+1] = padfWeight[iC] + dfXScale;
@@ -3335,7 +3977,7 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
         padfWeight[iC+3] = padfWeight[iC+2] + dfXScale;
         dfAccumulatorWeightHorizontal += pfnGetWeight4Values(padfWeight+iC);
     }
-    for(; i <= iMax; ++i, ++iC )
+    for( ; i <= iMax; ++i, ++iC )
     {
         double dfWeight = pfnGetWeight((i - dfDeltaX) * dfXScale);
         padfWeight[iC] = dfWeight;
@@ -3349,28 +3991,33 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
     if( iSrcY + jMax >= nSrcYSize-1 )
         jMax = nSrcYSize-1 - iSrcY;
 
-    /* Process by chunk of 4 rows */
-    for ( ; j+2 < jMax; j+=4 )
+    // Process by chunk of 4 rows.
+    for( ; j+2 < jMax; j+=4 )
     {
         int     iSampJ = iSrcOffset + j * nSrcXSize;
 
-        // Loop over all pixels in the row
+        // Loop over all pixels in the row.
         iC = 0;
         i = iMin;
-        /* Process by chunk of 4 cols */
+        // Process by chunk of 4 cols.
         XMMReg4Double v_acc_1 = XMMReg4Double::Zero();
         XMMReg4Double v_acc_2 = XMMReg4Double::Zero();
         XMMReg4Double v_acc_3 = XMMReg4Double::Zero();
         XMMReg4Double v_acc_4 = XMMReg4Double::Zero();
-        for(; i+2 < iMax; i+=4, iC+=4 )
+        for( ; i+2 < iMax; i+=4, iC+=4 )
         {
-            // Retrieve the pixel & accumulate
-            XMMReg4Double v_pixels_1 = XMMReg4Double::Load4Val(pSrcBand+i+iSampJ);
-            XMMReg4Double v_pixels_2 = XMMReg4Double::Load4Val(pSrcBand+i+iSampJ+nSrcXSize);
-            XMMReg4Double v_pixels_3 = XMMReg4Double::Load4Val(pSrcBand+i+iSampJ+2*nSrcXSize);
-            XMMReg4Double v_pixels_4 = XMMReg4Double::Load4Val(pSrcBand+i+iSampJ+3*nSrcXSize);
-
-            XMMReg4Double v_padfWeight = XMMReg4Double::Load4Val(padfWeight + iC);
+            // Retrieve the pixel & accumulate.
+            XMMReg4Double v_pixels_1 =
+                XMMReg4Double::Load4Val(pSrcBand+i+iSampJ);
+            XMMReg4Double v_pixels_2 =
+                XMMReg4Double::Load4Val(pSrcBand+i+iSampJ+nSrcXSize);
+            XMMReg4Double v_pixels_3 =
+                XMMReg4Double::Load4Val(pSrcBand+i+iSampJ+2*nSrcXSize);
+            XMMReg4Double v_pixels_4 =
+                XMMReg4Double::Load4Val(pSrcBand+i+iSampJ+3*nSrcXSize);
+
+            XMMReg4Double v_padfWeight =
+                XMMReg4Double::Load4Val(padfWeight + iC);
 
             v_acc_1 += v_pixels_1 * v_padfWeight;
             v_acc_2 += v_pixels_2 * v_padfWeight;
@@ -3380,12 +4027,17 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
 
         if( i < iMax )
         {
-            XMMReg2Double v_pixels_1 = XMMReg2Double::Load2Val(pSrcBand+i+iSampJ);
-            XMMReg2Double v_pixels_2 = XMMReg2Double::Load2Val(pSrcBand+i+iSampJ+nSrcXSize);
-            XMMReg2Double v_pixels_3 = XMMReg2Double::Load2Val(pSrcBand+i+iSampJ+2*nSrcXSize);
-            XMMReg2Double v_pixels_4 = XMMReg2Double::Load2Val(pSrcBand+i+iSampJ+3*nSrcXSize);
-
-            XMMReg2Double v_padfWeight = XMMReg2Double::Load2Val(padfWeight + iC);
+            XMMReg2Double v_pixels_1 =
+                XMMReg2Double::Load2Val(pSrcBand+i+iSampJ);
+            XMMReg2Double v_pixels_2 =
+                XMMReg2Double::Load2Val(pSrcBand+i+iSampJ+nSrcXSize);
+            XMMReg2Double v_pixels_3 =
+                XMMReg2Double::Load2Val(pSrcBand+i+iSampJ+2*nSrcXSize);
+            XMMReg2Double v_pixels_4 =
+                XMMReg2Double::Load2Val(pSrcBand+i+iSampJ+3*nSrcXSize);
+
+            XMMReg2Double v_padfWeight =
+                XMMReg2Double::Load2Val(padfWeight + iC);
 
             v_acc_1.GetLow() += v_pixels_1 * v_padfWeight;
             v_acc_2.GetLow() += v_pixels_2 * v_padfWeight;
@@ -3401,57 +4053,66 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
         v_acc_3.AddLowAndHigh();
         v_acc_4.AddLowAndHigh();
 
-        double dfAccumulatorLocal_1 = (double)v_acc_1.GetLow(),
-               dfAccumulatorLocal_2 = (double)v_acc_2.GetLow(),
-               dfAccumulatorLocal_3 = (double)v_acc_3.GetLow(),
-               dfAccumulatorLocal_4 = (double)v_acc_4.GetLow();
+        double dfAccumulatorLocal_1 = static_cast<double>(v_acc_1.GetLow());
+        double dfAccumulatorLocal_2 = static_cast<double>(v_acc_2.GetLow());
+        double dfAccumulatorLocal_3 = static_cast<double>(v_acc_3.GetLow());
+        double dfAccumulatorLocal_4 = static_cast<double>(v_acc_4.GetLow());
 
         if( i == iMax )
         {
-            dfAccumulatorLocal_1 += (double)pSrcBand[i+iSampJ] * padfWeight[iC];
-            dfAccumulatorLocal_2 += (double)pSrcBand[i+iSampJ + nSrcXSize] * padfWeight[iC];
-            dfAccumulatorLocal_3 += (double)pSrcBand[i+iSampJ + 2 * nSrcXSize] * padfWeight[iC];
-            dfAccumulatorLocal_4 += (double)pSrcBand[i+iSampJ + 3 * nSrcXSize] * padfWeight[iC];
+            dfAccumulatorLocal_1 +=
+                static_cast<double>(pSrcBand[i+iSampJ]) * padfWeight[iC];
+            dfAccumulatorLocal_2 +=
+                static_cast<double>(pSrcBand[i+iSampJ + nSrcXSize]) *
+                padfWeight[iC];
+            dfAccumulatorLocal_3 +=
+                static_cast<double>(pSrcBand[i+iSampJ + 2 * nSrcXSize]) *
+                padfWeight[iC];
+            dfAccumulatorLocal_4 +=
+                static_cast<double>(pSrcBand[i+iSampJ + 3 * nSrcXSize]) *
+                padfWeight[iC];
         }
 
-        // Calculate the Y weight
-        double adfWeight[4];
-        adfWeight[0] = (j - dfDeltaY) * dfYScale;
-        adfWeight[1] = adfWeight[0] + dfYScale;
-        adfWeight[2] = adfWeight[1] + dfYScale;
-        adfWeight[3] = adfWeight[2] + dfYScale;
+        // Calculate the Y weight.
+        const double dfWeight0 = (j - dfDeltaY) * dfYScale;
+        const double dfWeight1 = dfWeight0 + dfYScale;
+        const double dfWeight2 = dfWeight1 + dfYScale;
+        const double dfWeight3 = dfWeight2 + dfYScale;
+        double adfWeight[4] = { dfWeight0, dfWeight1, dfWeight2, dfWeight3 };
+
         dfAccumulatorWeightVertical += pfnGetWeight4Values(adfWeight);
         dfAccumulator += adfWeight[0] * dfAccumulatorLocal_1;
         dfAccumulator += adfWeight[1] * dfAccumulatorLocal_2;
         dfAccumulator += adfWeight[2] * dfAccumulatorLocal_3;
         dfAccumulator += adfWeight[3] * dfAccumulatorLocal_4;
     }
-    for ( ; j <= jMax; ++j )
+    for( ; j <= jMax; ++j )
     {
-        int     iSampJ = iSrcOffset + j * nSrcXSize;
+        int iSampJ = iSrcOffset + j * nSrcXSize;
 
-        // Loop over all pixels in the row
+        // Loop over all pixels in the row.
         iC = 0;
         i = iMin;
-        /* Process by chunk of 4 cols */
+        // Process by chunk of 4 cols.
         XMMReg4Double v_acc = XMMReg4Double::Zero();
-        for(; i+2 < iMax; i+=4, iC+=4 )
+        for( ; i+2 < iMax; i+=4, iC+=4 )
         {
-            // Retrieve the pixel & accumulate
+            // Retrieve the pixel & accumulate.
             XMMReg4Double v_pixels= XMMReg4Double::Load4Val(pSrcBand+i+iSampJ);
-            XMMReg4Double v_padfWeight = XMMReg4Double::Load4Val(padfWeight + iC);
+            XMMReg4Double v_padfWeight =
+                XMMReg4Double::Load4Val(padfWeight + iC);
 
             v_acc += v_pixels * v_padfWeight;
         }
 
         v_acc.AddLowAndHigh();
 
-        double dfAccumulatorLocal = (double)v_acc.GetLow();
+        double dfAccumulatorLocal = static_cast<double>(v_acc.GetLow());
 
         if( i < iMax )
         {
-            dfAccumulatorLocal += (double)pSrcBand[i+iSampJ] * padfWeight[iC];
-            dfAccumulatorLocal += (double)pSrcBand[i+1+iSampJ] * padfWeight[iC+1];
+            dfAccumulatorLocal += pSrcBand[i+iSampJ] * padfWeight[iC];
+            dfAccumulatorLocal += pSrcBand[i+1+iSampJ] * padfWeight[iC+1];
             i+=2;
             iC+=2;
         }
@@ -3460,17 +4121,18 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
             dfAccumulatorLocal += (double)pSrcBand[i+iSampJ] * padfWeight[iC];
         }
 
-        // Calculate the Y weight
-        double  dfWeight = pfnGetWeight((j - dfDeltaY) * dfYScale);
+        // Calculate the Y weight.
+        double dfWeight = pfnGetWeight((j - dfDeltaY) * dfYScale);
         dfAccumulator += dfWeight * dfAccumulatorLocal;
         dfAccumulatorWeightVertical += dfWeight;
     }
 
-    double dfAccumulatorWeight = dfAccumulatorWeightHorizontal * dfAccumulatorWeightVertical;
+    const double dfAccumulatorWeight =
+        dfAccumulatorWeightHorizontal * dfAccumulatorWeightVertical;
 
     *pValue = GWKClampValueT<T>(dfAccumulator / dfAccumulatorWeight);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -3478,11 +4140,12 @@ static int GWKResampleNoMasks_SSE2_T( GDALWarpKernel *poWK, int iBand,
 /************************************************************************/
 
 template<>
-int GWKResampleNoMasksT<GByte>( GDALWarpKernel *poWK, int iBand,
-                                double dfSrcX, double dfSrcY,
-                                GByte *pValue, double *padfWeight )
+bool GWKResampleNoMasksT<GByte>( GDALWarpKernel *poWK, int iBand,
+                                 double dfSrcX, double dfSrcY,
+                                 GByte *pValue, double *padfWeight )
 {
-    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY, pValue, padfWeight);
+    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY,
+                                     pValue, padfWeight);
 }
 
 /************************************************************************/
@@ -3490,11 +4153,12 @@ int GWKResampleNoMasksT<GByte>( GDALWarpKernel *poWK, int iBand,
 /************************************************************************/
 
 template<>
-int GWKResampleNoMasksT<GInt16>( GDALWarpKernel *poWK, int iBand,
-                                 double dfSrcX, double dfSrcY,
-                                 GInt16 *pValue, double *padfWeight )
+bool GWKResampleNoMasksT<GInt16>( GDALWarpKernel *poWK, int iBand,
+                                  double dfSrcX, double dfSrcY,
+                                  GInt16 *pValue, double *padfWeight )
 {
-    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY, pValue, padfWeight);
+    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY,
+                                     pValue, padfWeight);
 }
 
 /************************************************************************/
@@ -3502,11 +4166,12 @@ int GWKResampleNoMasksT<GInt16>( GDALWarpKernel *poWK, int iBand,
 /************************************************************************/
 
 template<>
-int GWKResampleNoMasksT<GUInt16>( GDALWarpKernel *poWK, int iBand,
-                                  double dfSrcX, double dfSrcY,
-                                  GUInt16 *pValue, double *padfWeight )
+bool GWKResampleNoMasksT<GUInt16>( GDALWarpKernel *poWK, int iBand,
+                                   double dfSrcX, double dfSrcY,
+                                   GUInt16 *pValue, double *padfWeight )
 {
-    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY, pValue, padfWeight);
+    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY,
+                                     pValue, padfWeight);
 }
 
 /************************************************************************/
@@ -3514,11 +4179,12 @@ int GWKResampleNoMasksT<GUInt16>( GDALWarpKernel *poWK, int iBand,
 /************************************************************************/
 
 template<>
-int GWKResampleNoMasksT<float>( GDALWarpKernel *poWK, int iBand,
+bool GWKResampleNoMasksT<float>( GDALWarpKernel *poWK, int iBand,
                                  double dfSrcX, double dfSrcY,
                                  float *pValue, double *padfWeight )
 {
-    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY, pValue, padfWeight);
+    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY,
+                                     pValue, padfWeight);
 }
 
 #ifdef INSTANTIATE_FLOAT64_SSE2_IMPL
@@ -3528,11 +4194,12 @@ int GWKResampleNoMasksT<float>( GDALWarpKernel *poWK, int iBand,
 /************************************************************************/
 
 template<>
-int GWKResampleNoMasksT<double>( GDALWarpKernel *poWK, int iBand,
-                                 double dfSrcX, double dfSrcY,
-                                 double *pValue, double *padfWeight )
+bool GWKResampleNoMasksT<double>( GDALWarpKernel *poWK, int iBand,
+                                  double dfSrcX, double dfSrcY,
+                                  double *pValue, double *padfWeight )
 {
-    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY, pValue, padfWeight);
+    return GWKResampleNoMasks_SSE2_T(poWK, iBand, dfSrcX, dfSrcY,
+                                     pValue, padfWeight);
 }
 
 #endif /* INSTANTIATE_FLOAT64_SSE2_IMPL */
@@ -3543,34 +4210,40 @@ int GWKResampleNoMasksT<double>( GDALWarpKernel *poWK, int iBand,
 /*                     GWKRoundSourceCoordinates()                      */
 /************************************************************************/
 
-static void GWKRoundSourceCoordinates(int nDstXSize,
-                                      double* padfX,
-                                      double* padfY,
-                                      double* padfZ,
-                                      int* pabSuccess,
-                                      double dfSrcCoordPrecision,
-                                      double dfErrorThreshold,
-                                      GDALTransformerFunc pfnTransformer,
-                                      void* pTransformerArg,
-                                      double dfDstXOff,
-                                      double dfDstY)
+static void GWKRoundSourceCoordinates( int nDstXSize,
+                                       double* padfX,
+                                       double* padfY,
+                                       double* padfZ,
+                                       int* pabSuccess,
+                                       double dfSrcCoordPrecision,
+                                       double dfErrorThreshold,
+                                       GDALTransformerFunc pfnTransformer,
+                                       void* pTransformerArg,
+                                       double dfDstXOff,
+                                       double dfDstY )
 {
     double dfPct = 0.8;
     if( dfErrorThreshold > 0 && dfSrcCoordPrecision / dfErrorThreshold >= 10.0 )
     {
         dfPct = 1.0 - 2 * 1.0 / (dfSrcCoordPrecision / dfErrorThreshold);
     }
-    double dfExactTransformThreshold = 0.5 * dfPct * dfSrcCoordPrecision;
+    const double dfExactTransformThreshold = 0.5 * dfPct * dfSrcCoordPrecision;
 
     for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
     {
-        double dfXBefore = padfX[iDstX], dfYBefore = padfY[iDstX];
-        padfX[iDstX] = floor(padfX[iDstX] / dfSrcCoordPrecision + 0.5) * dfSrcCoordPrecision;
-        padfY[iDstX] = floor(padfY[iDstX] / dfSrcCoordPrecision + 0.5) * dfSrcCoordPrecision;
-
-        /* If we are in an uncertainty zone, go to non approximated transformation */
-        /* Due to the 80% of half-precision threshold, dfSrcCoordPrecision must */
-        /* be at least 10 times greater than the approximation error */
+        const double dfXBefore = padfX[iDstX];
+        const double dfYBefore = padfY[iDstX];
+        padfX[iDstX] =
+            floor(padfX[iDstX] / dfSrcCoordPrecision + 0.5) *
+            dfSrcCoordPrecision;
+        padfY[iDstX] =
+            floor(padfY[iDstX] / dfSrcCoordPrecision + 0.5) *
+            dfSrcCoordPrecision;
+
+        // If we are in an uncertainty zone, go to non-approximated
+        // transformation.
+        // Due to the 80% of half-precision threshold, dfSrcCoordPrecision must
+        // be at least 10 times greater than the approximation error.
         if( fabs(dfXBefore - padfX[iDstX]) > dfExactTransformThreshold ||
             fabs(dfYBefore - padfY[iDstX]) > dfExactTransformThreshold )
         {
@@ -3580,8 +4253,12 @@ static void GWKRoundSourceCoordinates(int nDstXSize,
             pfnTransformer( pTransformerArg, TRUE, 1,
                             padfX + iDstX, padfY + iDstX,
                             padfZ + iDstX, pabSuccess + iDstX );
-            padfX[iDstX] = floor(padfX[iDstX] / dfSrcCoordPrecision + 0.5) * dfSrcCoordPrecision;
-            padfY[iDstX] = floor(padfY[iDstX] / dfSrcCoordPrecision + 0.5) * dfSrcCoordPrecision;
+            padfX[iDstX] =
+                floor(padfX[iDstX] / dfSrcCoordPrecision + 0.5) *
+                dfSrcCoordPrecision;
+            padfY[iDstX] =
+                floor(padfY[iDstX] / dfSrcCoordPrecision + 0.5) *
+                dfSrcCoordPrecision;
         }
     }
 }
@@ -3599,19 +4276,18 @@ static void GWKRoundSourceCoordinates(int nDstXSize,
 #if defined(HAVE_OPENCL)
 static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
 {
-    int iDstY, iBand;
-    int nDstXSize = poWK->nDstXSize, nDstYSize = poWK->nDstYSize;
-    int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
-    int nDstXOff  = poWK->nDstXOff , nDstYOff  = poWK->nDstYOff;
-    int nSrcXOff  = poWK->nSrcXOff , nSrcYOff  = poWK->nSrcYOff;
-    CPLErr eErr = CE_None;
-    struct oclWarper *warper;
-    cl_channel_type imageFormat;
-    int useImag = FALSE;
-    OCLResampAlg resampAlg;
-    cl_int err;
+    const int nDstXSize = poWK->nDstXSize;
+    const int nDstYSize = poWK->nDstYSize;
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
+    const int nDstXOff = poWK->nDstXOff;
+    const int nDstYOff = poWK->nDstYOff;
+    const int nSrcXOff = poWK->nSrcXOff;
+    const int nSrcYOff = poWK->nSrcYOff;
+    bool bUseImag = false;
 
-    switch ( poWK->eWorkingDataType )
+    cl_channel_type imageFormat;
+    switch( poWK->eWorkingDataType )
     {
       case GDT_Byte:
         imageFormat = CL_UNORM_INT8;
@@ -3620,24 +4296,27 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
         imageFormat = CL_UNORM_INT16;
         break;
       case GDT_CInt16:
-        useImag = TRUE;
+        bUseImag = true;
+        CPL_FALLTHROUGH
       case GDT_Int16:
         imageFormat = CL_SNORM_INT16;
         break;
       case GDT_CFloat32:
-        useImag = TRUE;
+        bUseImag = true;
+        CPL_FALLTHROUGH
       case GDT_Float32:
         imageFormat = CL_FLOAT;
         break;
       default:
-        // We don't support higher precision formats
-        CPLDebug( "OpenCL",
-                  "Unsupported resampling OpenCL data type %d.",
-                  (int) poWK->eWorkingDataType );
+        // No support for higher precision formats.
+        CPLDebug("OpenCL",
+                 "Unsupported resampling OpenCL data type %d.",
+                 static_cast<int>(poWK->eWorkingDataType));
         return CE_Warning;
     }
 
-    switch (poWK->eResample)
+    OCLResampAlg resampAlg;
+    switch( poWK->eResample )
     {
       case GRA_Bilinear:
         resampAlg = OCL_Bilinear;
@@ -3652,76 +4331,97 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
         resampAlg = OCL_Lanczos;
         break;
       default:
-        // We don't support higher precision formats
-        CPLDebug( "OpenCL",
-                  "Unsupported resampling OpenCL resampling alg %d.",
-                  (int) poWK->eResample );
+        // No support for higher precision formats.
+        CPLDebug("OpenCL",
+                 "Unsupported resampling OpenCL resampling alg %d.",
+                 static_cast<int>(poWK->eResample));
         return CE_Warning;
     }
 
+    struct oclWarper *warper = NULL;
+    cl_int err;
+    CPLErr eErr = CE_None;
+
+    // TODO(schwehr): Fix indenting.
+  try
+  {
+
     // Using a factor of 2 or 4 seems to have much less rounding error
     // than 3 on the GPU.
     // Then the rounding error can cause strange artifacts under the
     // right conditions.
-    warper = GDALWarpKernelOpenCL_createEnv(nSrcXSize, nSrcYSize,
-                                            nDstXSize, nDstYSize,
-                                            imageFormat, poWK->nBands, 4,
-                                            useImag, poWK->papanBandSrcValid != NULL,
-                                            poWK->pafDstDensity,
-                                            poWK->padfDstNoDataReal,
-                                            resampAlg, &err );
-
-    if(err != CL_SUCCESS || warper == NULL)
+    warper =
+        GDALWarpKernelOpenCL_createEnv(nSrcXSize, nSrcYSize,
+                                       nDstXSize, nDstYSize,
+                                       imageFormat, poWK->nBands, 4,
+                                       bUseImag,
+                                       poWK->papanBandSrcValid != NULL,
+                                       poWK->pafDstDensity,
+                                       poWK->padfDstNoDataReal,
+                                       resampAlg, &err);
+
+    if( err != CL_SUCCESS || warper == NULL )
     {
         eErr = CE_Warning;
-        if (warper != NULL)
-            goto free_warper;
+        if( warper != NULL )
+            throw eErr;
         return eErr;
     }
 
-    CPLDebug( "GDAL", "GDALWarpKernel()::GWKOpenCLCase()\n"
-              "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
-              nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
-              nDstXOff, nDstYOff, nDstXSize, nDstYSize );
+    CPLDebug("GDAL", "GDALWarpKernel()::GWKOpenCLCase() "
+             "Src=%d,%d,%dx%d Dst=%d,%d,%dx%d",
+             nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
+             nDstXOff, nDstYOff, nDstXSize, nDstYSize);
 
     if( !poWK->pfnProgress( poWK->dfProgressBase, "", poWK->pProgress ) )
     {
         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
         eErr = CE_Failure;
-        goto free_warper;
+        throw eErr;
     }
 
     /* ==================================================================== */
     /*      Loop over bands.                                                */
     /* ==================================================================== */
-    for( iBand = 0; iBand < poWK->nBands; iBand++ ) {
-        if( poWK->papanBandSrcValid != NULL && poWK->papanBandSrcValid[iBand] != NULL) {
-            GDALWarpKernelOpenCL_setSrcValid(warper, (int *)poWK->papanBandSrcValid[iBand], iBand);
-            if(err != CL_SUCCESS)
+    for( int iBand = 0; iBand < poWK->nBands; iBand++ )
+    {
+        if( poWK->papanBandSrcValid != NULL &&
+            poWK->papanBandSrcValid[iBand] != NULL)
+        {
+            GDALWarpKernelOpenCL_setSrcValid(
+                warper, (int *)poWK->papanBandSrcValid[iBand], iBand);
+            if( err != CL_SUCCESS )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
+                          "OpenCL routines reported failure (%d) on line %d.",
+                          static_cast<int>(err), __LINE__ );
                 eErr = CE_Failure;
-                goto free_warper;
+                throw eErr;
             }
         }
 
-        err = GDALWarpKernelOpenCL_setSrcImg(warper, poWK->papabySrcImage[iBand], iBand);
-        if(err != CL_SUCCESS)
+        err = GDALWarpKernelOpenCL_setSrcImg(warper,
+                                             poWK->papabySrcImage[iBand],
+                                             iBand);
+        if( err != CL_SUCCESS )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "OpenCL routines reported failure (%d) on line %d.",
+                     static_cast<int>(err), __LINE__);
             eErr = CE_Failure;
-            goto free_warper;
+            throw eErr;
         }
 
-        err = GDALWarpKernelOpenCL_setDstImg(warper, poWK->papabyDstImage[iBand], iBand);
-        if(err != CL_SUCCESS)
+        err = GDALWarpKernelOpenCL_setDstImg(warper,
+                                             poWK->papabyDstImage[iBand],
+                                             iBand);
+        if( err != CL_SUCCESS )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "OpenCL routines reported failure (%d) on line %d.",
+                     static_cast<int>(err), __LINE__);
             eErr = CE_Failure;
-            goto free_warper;
+            throw eErr;
         }
     }
 
@@ -3729,36 +4429,38 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
     /*      Allocate x,y,z coordinate arrays for transformation ... one     */
     /*      scanlines worth of positions.                                   */
     /* -------------------------------------------------------------------- */
-    double *padfX, *padfY, *padfZ;
-    int    *pabSuccess;
-    double dfSrcCoordPrecision;
-    double dfErrorThreshold;
-
-    padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
-    dfSrcCoordPrecision = CPLAtof(
-        CSLFetchNameValueDef(poWK->papszWarpOptions, "SRC_COORD_PRECISION", "0"));
-    dfErrorThreshold = CPLAtof(
+
+    // For x, 2 *, because we cache the precomputed values at the end.
+    double *padfX =
+        static_cast<double *>(CPLMalloc(2 * sizeof(double) * nDstXSize));
+    double * padfY =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfZ =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    int *pabSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nDstXSize));
+    const double dfSrcCoordPrecision = CPLAtof(
+        CSLFetchNameValueDef(poWK->papszWarpOptions,
+                             "SRC_COORD_PRECISION", "0"));
+    const double dfErrorThreshold = CPLAtof(
         CSLFetchNameValueDef(poWK->papszWarpOptions, "ERROR_THRESHOLD", "0"));
 
+    // Precompute values.
+    for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        padfX[nDstXSize + iDstX] = iDstX + 0.5 + poWK->nDstXOff;
+
     /* ==================================================================== */
     /*      Loop over output lines.                                         */
     /* ==================================================================== */
-    for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; ++iDstY )
+    for( int iDstY = 0; iDstY < nDstYSize && eErr == CE_None; ++iDstY )
     {
-        int iDstX;
-
         /* ---------------------------------------------------------------- */
         /*      Setup points to transform to source image space.            */
         /* ---------------------------------------------------------------- */
-        for( iDstX = 0; iDstX < nDstXSize; ++iDstX )
-        {
-            padfX[iDstX] = iDstX + 0.5 + nDstXOff;
-            padfY[iDstX] = iDstY + 0.5 + nDstYOff;
-            padfZ[iDstX] = 0.0;
-        }
+        memcpy( padfX, padfX + nDstXSize, sizeof(double) * nDstXSize );
+        const double dfYConst = iDstY + 0.5 + poWK->nDstYOff;
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+            padfY[iDstX] = dfYConst;
+        memset( padfZ, 0, sizeof(double) * nDstXSize );
 
         /* ---------------------------------------------------------------- */
         /*      Transform the points from destination pixel/line coordinates*/
@@ -3768,7 +4470,8 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
                               padfX, padfY, padfZ, pabSuccess );
         if( dfSrcCoordPrecision > 0.0 )
         {
-            GWKRoundSourceCoordinates(nDstXSize, padfX, padfY, padfZ, pabSuccess,
+            GWKRoundSourceCoordinates(nDstXSize, padfX, padfY, padfZ,
+                                      pabSuccess,
                                       dfSrcCoordPrecision,
                                       dfErrorThreshold,
                                       poWK->pfnTransformer,
@@ -3780,32 +4483,36 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
         err = GDALWarpKernelOpenCL_setCoordRow(warper, padfX, padfY,
                                                nSrcXOff, nSrcYOff,
                                                pabSuccess, iDstY);
-        if(err != CL_SUCCESS)
+        if( err != CL_SUCCESS )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
-            return CE_Failure;
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "OpenCL routines reported failure (%d) on line %d.",
+                     static_cast<int>(err), __LINE__);
+            eErr = CE_Failure;
+            break;
         }
 
-        //Update the valid & density masks because we don't do so in the kernel
-        for( iDstX = 0; iDstX < nDstXSize && eErr == CE_None; iDstX++ )
+        // Update the valid & density masks because we don't do so in the
+        // kernel.
+        for( int iDstX = 0; iDstX < nDstXSize && eErr == CE_None; iDstX++ )
         {
-            double dfX = padfX[iDstX];
-            double dfY = padfY[iDstX];
-            int iDstOffset = iDstX + iDstY * nDstXSize;
+            const double dfX = padfX[iDstX];
+            const double dfY = padfY[iDstX];
+            const int iDstOffset = iDstX + iDstY * nDstXSize;
 
-            //See GWKGeneralCase() for appropriate commenting
+            // See GWKGeneralCase() for appropriate commenting.
             if( !pabSuccess[iDstX] || dfX < nSrcXOff || dfY < nSrcYOff )
                 continue;
 
             int iSrcX = ((int) dfX) - nSrcXOff;
             int iSrcY = ((int) dfY) - nSrcYOff;
 
-            if( iSrcX < 0 || iSrcX >= nSrcXSize || iSrcY < 0 || iSrcY >= nSrcYSize )
+            if( iSrcX < 0 || iSrcX >= nSrcXSize ||
+                iSrcY < 0 || iSrcY >= nSrcYSize )
                 continue;
 
             int iSrcOffset = iSrcX + iSrcY * nSrcXSize;
-            double  dfDensity = 1.0;
+            double dfDensity = 1.0;
 
             if( poWK->pafUnifiedSrcDensity != NULL
                 && iSrcX >= 0 && iSrcY >= 0
@@ -3814,7 +4521,8 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
 
             GWKOverlayDensity( poWK, iDstOffset, dfDensity );
 
-            //Because this is on the bit-wise level, it can't be done well in OpenCL
+            // Because this is on the bit-wise level, it can't be done well in
+            // OpenCL.
             if( poWK->panDstValid != NULL )
                 poWK->panDstValid[iDstOffset>>5] |= 0x01 << (iDstOffset & 0x1f);
         }
@@ -3825,6 +4533,9 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
     CPLFree( padfZ );
     CPLFree( pabSuccess );
 
+    if( eErr != CE_None )
+        throw eErr;
+
     err = GDALWarpKernelOpenCL_runResamp(warper,
                                          poWK->pafUnifiedSrcDensity,
                                          poWK->panUnifiedSrcValid,
@@ -3835,37 +4546,41 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
                                          poWK->nXRadius, poWK->nYRadius,
                                          poWK->nFiltInitX, poWK->nFiltInitY);
 
-    if(err != CL_SUCCESS)
+    if( err != CL_SUCCESS )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "OpenCL routines reported failure (%d) on line %d.",
+                 static_cast<int>(err), __LINE__);
         eErr = CE_Failure;
-        goto free_warper;
+        throw eErr;
     }
 
     /* ==================================================================== */
     /*      Loop over output lines.                                         */
     /* ==================================================================== */
-    for( iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
+    for( int iDstY = 0; iDstY < nDstYSize && eErr == CE_None; iDstY++ )
     {
-        for( iBand = 0; iBand < poWK->nBands; iBand++ )
+        for( int iBand = 0; iBand < poWK->nBands; iBand++ )
         {
-            int iDstX;
-            void *rowReal, *rowImag;
+            void *rowReal = NULL;
+            void *rowImag = NULL;
             GByte *pabyDst = poWK->papabyDstImage[iBand];
 
-            err = GDALWarpKernelOpenCL_getRow(warper, &rowReal, &rowImag, iDstY, iBand);
-            if(err != CL_SUCCESS)
+            err = GDALWarpKernelOpenCL_getRow(warper, &rowReal, &rowImag,
+                                              iDstY, iBand);
+            if( err != CL_SUCCESS )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
+                          "OpenCL routines reported failure (%d) on line %d.",
+                          static_cast<int>(err), __LINE__ );
                 eErr = CE_Failure;
-                goto free_warper;
+                throw eErr;
             }
 
-            //Copy the data from the warper to GDAL's memory
-            switch ( poWK->eWorkingDataType )
+            // Copy the data from the warper to GDAL's memory.
+            switch( poWK->eWorkingDataType )
             {
+              // TODO(schwehr): Fix casting.
               case GDT_Byte:
                 memcpy((void **)&(((GByte *)pabyDst)[iDstY*nDstXSize]),
                        rowReal, sizeof(GByte)*nDstXSize);
@@ -3885,7 +4600,8 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
               case GDT_CInt16:
               {
                   GInt16 *pabyDstI16 = &(((GInt16 *)pabyDst)[iDstY*nDstXSize]);
-                  for (iDstX = 0; iDstX < nDstXSize; iDstX++) {
+                  for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+                  {
                       pabyDstI16[iDstX*2  ] = ((GInt16 *)rowReal)[iDstX];
                       pabyDstI16[iDstX*2+1] = ((GInt16 *)rowImag)[iDstX];
                   }
@@ -3894,26 +4610,33 @@ static CPLErr GWKOpenCLCase( GDALWarpKernel *poWK )
               case GDT_CFloat32:
               {
                   float *pabyDstF32 = &(((float *)pabyDst)[iDstY*nDstXSize]);
-                  for (iDstX = 0; iDstX < nDstXSize; iDstX++) {
+                  for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+                  {
                       pabyDstF32[iDstX*2  ] = ((float *)rowReal)[iDstX];
                       pabyDstF32[iDstX*2+1] = ((float *)rowImag)[iDstX];
                   }
               }
               break;
               default:
-                // We don't support higher precision formats
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Unsupported resampling OpenCL data type %d.", (int) poWK->eWorkingDataType );
+                // No support for higher precision formats.
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Unsupported resampling OpenCL data type %d.",
+                         static_cast<int>(poWK->eWorkingDataType) );
                 eErr = CE_Failure;
-                goto free_warper;
+                throw eErr;
             }
         }
     }
-free_warper:
-    if((err = GDALWarpKernelOpenCL_deleteEnv(warper)) != CL_SUCCESS)
+  }
+  catch( const CPLErr& )
+  {
+  }
+
+    if( (err = GDALWarpKernelOpenCL_deleteEnv(warper)) != CL_SUCCESS )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "OpenCL routines reported failure (%d) on line %d.", (int) err, __LINE__ );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "OpenCL routines reported failure (%d) on line %d.",
+                 static_cast<int>(err), __LINE__ );
         return CE_Failure;
     }
 
@@ -3924,17 +4647,18 @@ free_warper:
 /************************************************************************/
 /*                     GWKCheckAndComputeSrcOffsets()                   */
 /************************************************************************/
-static CPL_INLINE int GWKCheckAndComputeSrcOffsets(const int* _pabSuccess,
-                                         int _iDstX,
-                                         const double* _padfX,
-                                         const double* _padfY,
-                                         const GDALWarpKernel* _poWK,
-                                         int _nSrcXSize,
-                                         int _nSrcYSize,
-                                         int& iSrcOffset)
+static CPL_INLINE bool GWKCheckAndComputeSrcOffsets(
+    const int* _pabSuccess,
+    int _iDstX,
+    const double* _padfX,
+    const double* _padfY,
+    const GDALWarpKernel* _poWK,
+    int _nSrcXSize,
+    int _nSrcYSize,
+    int& iSrcOffset)
 {
     if( !_pabSuccess[_iDstX] )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Figure out what pixel we want in our source raster, and skip    */
@@ -3945,7 +4669,7 @@ static CPL_INLINE int GWKCheckAndComputeSrcOffsets(const int* _pabSuccess,
     /* -0.5 will be 0 when cast to an int. */
     if( _padfX[_iDstX] < _poWK->nSrcXOff
         || _padfY[_iDstX] < _poWK->nSrcYOff )
-        return FALSE;
+        return false;
 
     // Check for potential overflow when casting from float to int, (if
     // operating outside natural projection area, padfX/Y can be a very huge
@@ -3958,10 +4682,10 @@ static CPL_INLINE int GWKCheckAndComputeSrcOffsets(const int* _pabSuccess,
         return false;
     }
 
-    int iSrcX, iSrcY;
-
-    iSrcX = static_cast<int>(_padfX[_iDstX] + 1e-10) - _poWK->nSrcXOff;
-    iSrcY = static_cast<int>(_padfY[_iDstX] + 1e-10) - _poWK->nSrcYOff;
+    const int iSrcX =
+        static_cast<int>(_padfX[_iDstX] + 1.0e-10) - _poWK->nSrcXOff;
+    const int iSrcY =
+        static_cast<int>(_padfY[_iDstX] + 1.0e-10) - _poWK->nSrcYOff;
 
     // Those checks should normally be OK given the previous ones.
     CPLAssert( iSrcX >= 0 );
@@ -3971,7 +4695,7 @@ static CPL_INLINE int GWKCheckAndComputeSrcOffsets(const int* _pabSuccess,
 
     iSrcOffset = iSrcX + iSrcY * _nSrcXSize;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -3982,65 +4706,62 @@ static CPL_INLINE int GWKCheckAndComputeSrcOffsets(const int* _pabSuccess,
 /*      efficiency.                                                     */
 /************************************************************************/
 
-static void GWKGeneralCaseThread(void* pData);
-
-static CPLErr GWKGeneralCase( GDALWarpKernel *poWK )
-{
-    return GWKRun( poWK, "GWKGeneralCase", GWKGeneralCaseThread );
-}
-
 static void GWKGeneralCaseThread( void* pData)
 
 {
-    GWKJobStruct* psJob = (GWKJobStruct*) pData;
+    GWKJobStruct* psJob = reinterpret_cast<GWKJobStruct *>(pData);
     GDALWarpKernel *poWK = psJob->poWK;
-    int iYMin = psJob->iYMin;
-    int iYMax = psJob->iYMax;
+    const int iYMin = psJob->iYMin;
+    const int iYMax = psJob->iYMax;
 
-    int iDstY;
     int nDstXSize = poWK->nDstXSize;
-    int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
+    int nSrcXSize = poWK->nSrcXSize;
+    int nSrcYSize = poWK->nSrcYSize;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate x,y,z coordinate arrays for transformation ... one     */
 /*      scanlines worth of positions.                                   */
 /* -------------------------------------------------------------------- */
-    double *padfX, *padfY, *padfZ;
-    int    *pabSuccess;
-
-    padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
-
-    int bUse4SamplesFormula = (poWK->dfXScale >= 0.95 && poWK->dfYScale >= 0.95);
+    // For x, 2 *, because we cache the precomputed values at the end.
+    double *padfX =
+        static_cast<double *>(CPLMalloc(2 * sizeof(double) * nDstXSize));
+    double *padfY =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfZ =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    int *pabSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nDstXSize));
+
+    const bool bUse4SamplesFormula =
+        poWK->dfXScale >= 0.95 && poWK->dfYScale >= 0.95;
 
     GWKResampleWrkStruct* psWrkStruct = NULL;
-    if (poWK->eResample != GRA_NearestNeighbour)
+    if( poWK->eResample != GRA_NearestNeighbour )
     {
         psWrkStruct = GWKResampleCreateWrkStruct(poWK);
     }
-    double dfSrcCoordPrecision = CPLAtof(
-        CSLFetchNameValueDef(poWK->papszWarpOptions, "SRC_COORD_PRECISION", "0"));
-    double dfErrorThreshold = CPLAtof(
+    const double dfSrcCoordPrecision = CPLAtof(
+        CSLFetchNameValueDef(poWK->papszWarpOptions,
+                             "SRC_COORD_PRECISION", "0"));
+    const double dfErrorThreshold = CPLAtof(
         CSLFetchNameValueDef(poWK->papszWarpOptions, "ERROR_THRESHOLD", "0"));
 
+    // Precompute values.
+    for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        padfX[nDstXSize + iDstX] = iDstX + 0.5 + poWK->nDstXOff;
+
 /* ==================================================================== */
 /*      Loop over output lines.                                         */
 /* ==================================================================== */
-    for( iDstY = iYMin; iDstY < iYMax; iDstY++ )
+    for( int iDstY = iYMin; iDstY < iYMax; iDstY++ )
     {
-        int iDstX;
-
 /* -------------------------------------------------------------------- */
 /*      Setup points to transform to source image space.                */
 /* -------------------------------------------------------------------- */
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
-        {
-            padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
-            padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
-            padfZ[iDstX] = 0.0;
-        }
+        memcpy( padfX, padfX + nDstXSize, sizeof(double) * nDstXSize );
+        const double dfY = iDstY + 0.5 + poWK->nDstYOff;
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+            padfY[iDstX] = dfY;
+        memset( padfZ, 0, sizeof(double) * nDstXSize );
 
 /* -------------------------------------------------------------------- */
 /*      Transform the points from destination pixel/line coordinates    */
@@ -4050,7 +4771,8 @@ static void GWKGeneralCaseThread( void* pData)
                               padfX, padfY, padfZ, pabSuccess );
         if( dfSrcCoordPrecision > 0.0 )
         {
-            GWKRoundSourceCoordinates(nDstXSize, padfX, padfY, padfZ, pabSuccess,
+            GWKRoundSourceCoordinates(nDstXSize, padfX, padfY, padfZ,
+                                      pabSuccess,
                                       dfSrcCoordPrecision,
                                       dfErrorThreshold,
                                       poWK->pfnTransformer,
@@ -4062,11 +4784,9 @@ static void GWKGeneralCaseThread( void* pData)
 /* ==================================================================== */
 /*      Loop over pixels in output scanline.                            */
 /* ==================================================================== */
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
-            int iDstOffset;
-
-            int iSrcOffset;
+            int iSrcOffset = 0;
             if( !GWKCheckAndComputeSrcOffsets(pabSuccess, iDstX, padfX, padfY,
                                     poWK, nSrcXSize, nSrcYSize, iSrcOffset) )
                 continue;
@@ -4076,12 +4796,12 @@ static void GWKGeneralCaseThread( void* pData)
 /*      destination.  This currently ignores the multi-pixel input      */
 /*      of bilinear and cubic resamples.                                */
 /* -------------------------------------------------------------------- */
-            double  dfDensity = 1.0;
+            double dfDensity = 1.0;
 
             if( poWK->pafUnifiedSrcDensity != NULL )
             {
                 dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
-                if( dfDensity < 0.00001 )
+                if( dfDensity < SRC_DENSITY_THRESHOLD )
                     continue;
             }
 
@@ -4093,11 +4813,10 @@ static void GWKGeneralCaseThread( void* pData)
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
 /* ==================================================================== */
-            int iBand;
-            int bHasFoundDensity = FALSE;
+            bool bHasFoundDensity = false;
 
-            iDstOffset = iDstX + iDstY * nDstXSize;
-            for( iBand = 0; iBand < poWK->nBands; iBand++ )
+            const int iDstOffset = iDstX + iDstY * nDstXSize;
+            for( int iBand = 0; iBand < poWK->nBands; iBand++ )
             {
                 double dfBandDensity = 0.0;
                 double dfValueReal = 0.0;
@@ -4106,16 +4825,18 @@ static void GWKGeneralCaseThread( void* pData)
 /* -------------------------------------------------------------------- */
 /*      Collect the source value.                                       */
 /* -------------------------------------------------------------------- */
-                if ( poWK->eResample == GRA_NearestNeighbour ||
-                     nSrcXSize == 1 || nSrcYSize == 1)
+                if( poWK->eResample == GRA_NearestNeighbour ||
+                    nSrcXSize == 1 || nSrcYSize == 1 )
                 {
                     // FALSE is returned if dfBandDensity == 0, which is
-                    // checked below
-                    CPL_IGNORE_RET_VAL(GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                      &dfBandDensity, &dfValueReal, &dfValueImag ));
+                    // checked below.
+                    CPL_IGNORE_RET_VAL(
+                        GWKGetPixelValue( poWK, iBand, iSrcOffset,
+                                          &dfBandDensity,
+                                          &dfValueReal, &dfValueImag ));
                 }
-                else if ( poWK->eResample == GRA_Bilinear &&
-                          bUse4SamplesFormula )
+                else if( poWK->eResample == GRA_Bilinear &&
+                         bUse4SamplesFormula )
                 {
                     GWKBilinearResample4Sample( poWK, iBand,
                                          padfX[iDstX]-poWK->nSrcXOff,
@@ -4123,8 +4844,8 @@ static void GWKGeneralCaseThread( void* pData)
                                          &dfBandDensity,
                                          &dfValueReal, &dfValueImag );
                 }
-                else if ( poWK->eResample == GRA_Cubic &&
-                          bUse4SamplesFormula )
+                else if( poWK->eResample == GRA_Cubic &&
+                         bUse4SamplesFormula )
                 {
                     GWKCubicResample4Sample( poWK, iBand,
                                         padfX[iDstX]-poWK->nSrcXOff,
@@ -4134,7 +4855,8 @@ static void GWKGeneralCaseThread( void* pData)
                 }
                 else
 #ifdef DEBUG
-                if( psWrkStruct != NULL ) /* only useful for clang static analyzer */
+                // Only useful for clang static analyzer.
+                if( psWrkStruct != NULL )
 #endif
                 {
                     psWrkStruct->pfnGWKResample( poWK, iBand,
@@ -4144,12 +4866,11 @@ static void GWKGeneralCaseThread( void* pData)
                                  &dfValueReal, &dfValueImag, psWrkStruct );
                 }
 
-
                 // If we didn't find any valid inputs skip to next band.
-                if ( dfBandDensity < 0.0000000001 )
+                if( dfBandDensity < BAND_DENSITY_THRESHOLD )
                     continue;
 
-                bHasFoundDensity = TRUE;
+                bHasFoundDensity = true;
 
 /* -------------------------------------------------------------------- */
 /*      We have a computed value from the source.  Now apply it to      */
@@ -4158,10 +4879,9 @@ static void GWKGeneralCaseThread( void* pData)
                 GWKSetPixelValue( poWK, iBand, iDstOffset,
                                   dfBandDensity,
                                   dfValueReal, dfValueImag );
-
             }
 
-            if (!bHasFoundDensity)
+            if( !bHasFoundDensity )
               continue;
 
 /* -------------------------------------------------------------------- */
@@ -4174,13 +4894,12 @@ static void GWKGeneralCaseThread( void* pData)
                 poWK->panDstValid[iDstOffset>>5] |=
                     0x01 << (iDstOffset & 0x1f);
             }
-
         } /* Next iDstX */
 
 /* -------------------------------------------------------------------- */
 /*      Report progress to the user, and optionally cancel out.         */
 /* -------------------------------------------------------------------- */
-        if (psJob->pfnProgress && psJob->pfnProgress(psJob))
+        if( psJob->pfnProgress && psJob->pfnProgress(psJob) )
             break;
     }
 
@@ -4191,63 +4910,333 @@ static void GWKGeneralCaseThread( void* pData)
     CPLFree( padfY );
     CPLFree( padfZ );
     CPLFree( pabSuccess );
-    if (psWrkStruct)
+    if( psWrkStruct )
         GWKResampleDeleteWrkStruct(psWrkStruct);
 }
 
+static CPLErr GWKGeneralCase( GDALWarpKernel *poWK )
+{
+    return GWKRun( poWK, "GWKGeneralCase", GWKGeneralCaseThread );
+}
+
 /************************************************************************/
-/*                GWKResampleNoMasksOrDstDensityOnlyThreadInternal()           */
+/*                            GWKRealCase()                             */
+/*                                                                      */
+/*      General case for non-complex data types.                        */
 /************************************************************************/
 
-template<class T,GDALResampleAlg eResample, int bUse4SamplesFormula>
-static void GWKResampleNoMasksOrDstDensityOnlyThreadInternal( void* pData )
+static void GWKRealCaseThread( void* pData)
 
 {
-    GWKJobStruct* psJob = (GWKJobStruct*) pData;
+    GWKJobStruct* psJob = static_cast<GWKJobStruct*>(pData);
     GDALWarpKernel *poWK = psJob->poWK;
-    int iYMin = psJob->iYMin;
-    int iYMax = psJob->iYMax;
+    const int iYMin = psJob->iYMin;
+    const int iYMax = psJob->iYMax;
 
-    int iDstY;
-    int nDstXSize = poWK->nDstXSize;
-    int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
+    const int nDstXSize = poWK->nDstXSize;
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate x,y,z coordinate arrays for transformation ... one     */
 /*      scanlines worth of positions.                                   */
 /* -------------------------------------------------------------------- */
-    double *padfX, *padfY, *padfZ;
-    int    *pabSuccess;
-
-    padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
-
-    int     nXRadius = poWK->nXRadius;
-    double  *padfWeight = (double *)CPLCalloc( 1 + nXRadius * 2, sizeof(double) );
-    double dfSrcCoordPrecision = CPLAtof(
-        CSLFetchNameValueDef(poWK->papszWarpOptions, "SRC_COORD_PRECISION", "0"));
-    double dfErrorThreshold = CPLAtof(
+
+    // For x, 2 *, because we cache the precomputed values at the end.
+    double *padfX =
+        static_cast<double *>(CPLMalloc(2 * sizeof(double) * nDstXSize));
+    double *padfY =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfZ =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    int *pabSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nDstXSize));
+
+    const bool bUse4SamplesFormula =
+        poWK->dfXScale >= 0.95 && poWK->dfYScale >= 0.95;
+
+    GWKResampleWrkStruct* psWrkStruct = NULL;
+    if( poWK->eResample != GRA_NearestNeighbour )
+    {
+        psWrkStruct = GWKResampleCreateWrkStruct(poWK);
+    }
+    const double dfSrcCoordPrecision = CPLAtof(
+        CSLFetchNameValueDef(poWK->papszWarpOptions,
+                             "SRC_COORD_PRECISION", "0"));
+    const double dfErrorThreshold = CPLAtof(
         CSLFetchNameValueDef(poWK->papszWarpOptions, "ERROR_THRESHOLD", "0"));
 
+    const bool bSrcMaskIsDensity =
+        poWK->panUnifiedSrcValid == NULL &&
+        poWK->papanBandSrcValid == NULL &&
+        poWK->pafUnifiedSrcDensity != NULL;
+
+    // Precompute values.
+    for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        padfX[nDstXSize + iDstX] = iDstX + 0.5 + poWK->nDstXOff;
+
 /* ==================================================================== */
 /*      Loop over output lines.                                         */
 /* ==================================================================== */
-    for( iDstY = iYMin; iDstY < iYMax; iDstY++ )
+    for( int iDstY = iYMin; iDstY < iYMax; iDstY++ )
     {
-        int iDstX;
-
 /* -------------------------------------------------------------------- */
 /*      Setup points to transform to source image space.                */
 /* -------------------------------------------------------------------- */
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        memcpy( padfX, padfX + nDstXSize, sizeof(double) * nDstXSize );
+        const double dfY = iDstY + 0.5 + poWK->nDstYOff;
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+            padfY[iDstX] = dfY;
+        memset( padfZ, 0, sizeof(double) * nDstXSize );
+
+/* -------------------------------------------------------------------- */
+/*      Transform the points from destination pixel/line coordinates    */
+/*      to source pixel/line coordinates.                               */
+/* -------------------------------------------------------------------- */
+        poWK->pfnTransformer( psJob->pTransformerArg, TRUE, nDstXSize,
+                              padfX, padfY, padfZ, pabSuccess );
+        if( dfSrcCoordPrecision > 0.0 )
         {
-            padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
-            padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
-            padfZ[iDstX] = 0.0;
+            GWKRoundSourceCoordinates(nDstXSize, padfX, padfY, padfZ,
+                                      pabSuccess,
+                                      dfSrcCoordPrecision,
+                                      dfErrorThreshold,
+                                      poWK->pfnTransformer,
+                                      psJob->pTransformerArg,
+                                      0.5 + poWK->nDstXOff,
+                                      iDstY + 0.5 + poWK->nDstYOff);
         }
 
+/* ==================================================================== */
+/*      Loop over pixels in output scanline.                            */
+/* ==================================================================== */
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        {
+            int iSrcOffset = 0;
+            if( !GWKCheckAndComputeSrcOffsets(pabSuccess, iDstX, padfX, padfY,
+                                    poWK, nSrcXSize, nSrcYSize, iSrcOffset) )
+                continue;
+
+/* -------------------------------------------------------------------- */
+/*      Do not try to apply transparent/invalid source pixels to the    */
+/*      destination.  This currently ignores the multi-pixel input      */
+/*      of bilinear and cubic resamples.                                */
+/* -------------------------------------------------------------------- */
+            double dfDensity = 1.0;
+
+            if( poWK->pafUnifiedSrcDensity != NULL )
+            {
+                dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
+                if( dfDensity < SRC_DENSITY_THRESHOLD )
+                    continue;
+            }
+
+            if( poWK->panUnifiedSrcValid != NULL
+                && !(poWK->panUnifiedSrcValid[iSrcOffset>>5]
+                     & (0x01 << (iSrcOffset & 0x1f))) )
+                continue;
+
+/* ==================================================================== */
+/*      Loop processing each band.                                      */
+/* ==================================================================== */
+            bool bHasFoundDensity = false;
+
+            const int iDstOffset = iDstX + iDstY * nDstXSize;
+            for( int iBand = 0; iBand < poWK->nBands; iBand++ )
+            {
+                double dfBandDensity = 0.0;
+                double dfValueReal = 0.0;
+
+/* -------------------------------------------------------------------- */
+/*      Collect the source value.                                       */
+/* -------------------------------------------------------------------- */
+                if( poWK->eResample == GRA_NearestNeighbour ||
+                    nSrcXSize == 1 || nSrcYSize == 1 )
+                {
+                    // FALSE is returned if dfBandDensity == 0, which is
+                    // checked below.
+                    CPL_IGNORE_RET_VAL(
+                        GWKGetPixelValueReal( poWK, iBand, iSrcOffset,
+                                              &dfBandDensity, &dfValueReal ));
+                }
+                else if( poWK->eResample == GRA_Bilinear &&
+                         bUse4SamplesFormula )
+                {
+                    double dfValueImagIgnored = 0.0;
+                    GWKBilinearResample4Sample( poWK, iBand,
+                                         padfX[iDstX]-poWK->nSrcXOff,
+                                         padfY[iDstX]-poWK->nSrcYOff,
+                                         &dfBandDensity,
+                                         &dfValueReal, &dfValueImagIgnored );
+                }
+                else if( poWK->eResample == GRA_Cubic &&
+                         bUse4SamplesFormula )
+                {
+                    if( bSrcMaskIsDensity )
+                    {
+                        if( poWK->eWorkingDataType == GDT_Byte )
+                        {
+                            GWKCubicResampleSrcMaskIsDensity4SampleRealT<GByte>(
+                                                poWK, iBand,
+                                                padfX[iDstX]-poWK->nSrcXOff,
+                                                padfY[iDstX]-poWK->nSrcYOff,
+                                                &dfBandDensity,
+                                                &dfValueReal );
+                        }
+                        else if( poWK->eWorkingDataType == GDT_UInt16 )
+                        {
+                            GWKCubicResampleSrcMaskIsDensity4SampleRealT<GUInt16>(
+                                                poWK, iBand,
+                                                padfX[iDstX]-poWK->nSrcXOff,
+                                                padfY[iDstX]-poWK->nSrcYOff,
+                                                &dfBandDensity,
+                                                &dfValueReal );
+                        }
+                        else
+                        {
+                            GWKCubicResampleSrcMaskIsDensity4SampleReal( poWK, iBand,
+                                    padfX[iDstX]-poWK->nSrcXOff,
+                                    padfY[iDstX]-poWK->nSrcYOff,
+                                    &dfBandDensity,
+                                    &dfValueReal );
+                        }
+                    }
+                    else
+                    {
+                        double dfValueImagIgnored = 0.0;
+                        GWKCubicResample4Sample( poWK, iBand,
+                                            padfX[iDstX]-poWK->nSrcXOff,
+                                            padfY[iDstX]-poWK->nSrcYOff,
+                                            &dfBandDensity,
+                                            &dfValueReal,
+                                            &dfValueImagIgnored);
+                    }
+                }
+                else
+#ifdef DEBUG
+                // Only useful for clang static analyzer.
+                if( psWrkStruct != NULL )
+#endif
+                {
+                    double dfValueImagIgnored = 0.0;
+                    psWrkStruct->pfnGWKResample(
+                        poWK, iBand,
+                        padfX[iDstX]-poWK->nSrcXOff,
+                        padfY[iDstX]-poWK->nSrcYOff,
+                        &dfBandDensity,
+                        &dfValueReal, &dfValueImagIgnored, psWrkStruct);
+                }
+
+                // If we didn't find any valid inputs skip to next band.
+                if( dfBandDensity < BAND_DENSITY_THRESHOLD )
+                    continue;
+
+                bHasFoundDensity = true;
+
+/* -------------------------------------------------------------------- */
+/*      We have a computed value from the source.  Now apply it to      */
+/*      the destination pixel.                                          */
+/* -------------------------------------------------------------------- */
+                GWKSetPixelValueReal(poWK, iBand, iDstOffset,
+                                     dfBandDensity,
+                                     dfValueReal);
+            }
+
+            if( !bHasFoundDensity )
+              continue;
+
+/* -------------------------------------------------------------------- */
+/*      Update destination density/validity masks.                      */
+/* -------------------------------------------------------------------- */
+            GWKOverlayDensity( poWK, iDstOffset, dfDensity );
+
+            if( poWK->panDstValid != NULL )
+            {
+                poWK->panDstValid[iDstOffset>>5] |=
+                    0x01 << (iDstOffset & 0x1f);
+            }
+        }  // Next iDstX.
+
+/* -------------------------------------------------------------------- */
+/*      Report progress to the user, and optionally cancel out.         */
+/* -------------------------------------------------------------------- */
+        if( psJob->pfnProgress && psJob->pfnProgress(psJob) )
+            break;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup and return.                                             */
+/* -------------------------------------------------------------------- */
+    CPLFree( padfX );
+    CPLFree( padfY );
+    CPLFree( padfZ );
+    CPLFree( pabSuccess );
+    if( psWrkStruct )
+        GWKResampleDeleteWrkStruct(psWrkStruct);
+}
+
+static CPLErr GWKRealCase( GDALWarpKernel *poWK )
+{
+    return GWKRun( poWK, "GWKRealCase", GWKRealCaseThread );
+}
+
+/************************************************************************/
+/*                GWKResampleNoMasksOrDstDensityOnlyThreadInternal()    */
+/************************************************************************/
+
+template<class T, GDALResampleAlg eResample, int bUse4SamplesFormula>
+static void GWKResampleNoMasksOrDstDensityOnlyThreadInternal( void* pData )
+
+{
+    GWKJobStruct* psJob = static_cast<GWKJobStruct *>(pData);
+    GDALWarpKernel *poWK = psJob->poWK;
+    const int iYMin = psJob->iYMin;
+    const int iYMax = psJob->iYMax;
+
+    const int nDstXSize = poWK->nDstXSize;
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
+
+/* -------------------------------------------------------------------- */
+/*      Allocate x,y,z coordinate arrays for transformation ... one     */
+/*      scanlines worth of positions.                                   */
+/* -------------------------------------------------------------------- */
+
+    // For x, 2 *, because we cache the precomputed values at the end.
+    double *padfX =
+        static_cast<double *>(CPLMalloc(2 * sizeof(double) * nDstXSize));
+    double *padfY =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfZ =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    int *pabSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nDstXSize));
+
+    const int nXRadius = poWK->nXRadius;
+    double  *padfWeight =
+      static_cast<double *>(CPLCalloc(1 + nXRadius * 2, sizeof(double)));
+    const double dfSrcCoordPrecision = CPLAtof(
+        CSLFetchNameValueDef(poWK->papszWarpOptions,
+                             "SRC_COORD_PRECISION", "0"));
+    const double dfErrorThreshold = CPLAtof(
+        CSLFetchNameValueDef(poWK->papszWarpOptions, "ERROR_THRESHOLD", "0"));
+
+    // Precompute values.
+    for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        padfX[nDstXSize + iDstX] = iDstX + 0.5 + poWK->nDstXOff;
+
+/* ==================================================================== */
+/*      Loop over output lines.                                         */
+/* ==================================================================== */
+    for( int iDstY = iYMin; iDstY < iYMax; iDstY++ )
+    {
+/* -------------------------------------------------------------------- */
+/*      Setup points to transform to source image space.                */
+/* -------------------------------------------------------------------- */
+        memcpy( padfX, padfX + nDstXSize, sizeof(double) * nDstXSize );
+        const double dfY = iDstY + 0.5 + poWK->nDstYOff;
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+            padfY[iDstX] = dfY;
+        memset( padfZ, 0, sizeof(double) * nDstXSize );
+
 /* -------------------------------------------------------------------- */
 /*      Transform the points from destination pixel/line coordinates    */
 /*      to source pixel/line coordinates.                               */
@@ -4268,27 +5257,26 @@ static void GWKResampleNoMasksOrDstDensityOnlyThreadInternal( void* pData )
 /* ==================================================================== */
 /*      Loop over pixels in output scanline.                            */
 /* ==================================================================== */
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
-            int iSrcOffset;
+            int iSrcOffset = 0;
             if( !GWKCheckAndComputeSrcOffsets(pabSuccess, iDstX, padfX, padfY,
-                                        poWK, nSrcXSize, nSrcYSize, iSrcOffset) )
+                                              poWK, nSrcXSize, nSrcYSize,
+                                              iSrcOffset) )
                 continue;
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
 /* ==================================================================== */
-            int iBand;
-            int iDstOffset;
-
-            iDstOffset = iDstX + iDstY * nDstXSize;
+            const int iDstOffset = iDstX + iDstY * nDstXSize;
 
-            for( iBand = 0; iBand < poWK->nBands; iBand++ )
+            for( int iBand = 0; iBand < poWK->nBands; iBand++ )
             {
                 T value = 0;
                 if( eResample == GRA_NearestNeighbour )
                 {
-                    value = ((T *)poWK->papabySrcImage[iBand])[iSrcOffset];
+                    value = reinterpret_cast<T *>(
+                        poWK->papabySrcImage[iBand])[iSrcOffset];
                 }
                 else if( bUse4SamplesFormula )
                 {
@@ -4304,12 +5292,15 @@ static void GWKResampleNoMasksOrDstDensityOnlyThreadInternal( void* pData )
                                               &value );
                 }
                 else
+                {
                     GWKResampleNoMasksT( poWK, iBand,
                                     padfX[iDstX]-poWK->nSrcXOff,
                                     padfY[iDstX]-poWK->nSrcYOff,
                                     &value,
                                     padfWeight);
-                ((T *)poWK->papabyDstImage[iBand])[iDstOffset] = value;
+                }
+                reinterpret_cast<T *>(poWK->papabyDstImage[iBand])[iDstOffset] =
+                    value;
             }
 
             if( poWK->pafDstDensity )
@@ -4319,7 +5310,7 @@ static void GWKResampleNoMasksOrDstDensityOnlyThreadInternal( void* pData )
 /* -------------------------------------------------------------------- */
 /*      Report progress to the user, and optionally cancel out.         */
 /* -------------------------------------------------------------------- */
-        if (psJob->pfnProgress && psJob->pfnProgress(psJob))
+        if( psJob->pfnProgress && psJob->pfnProgress(psJob) )
             break;
     }
 
@@ -4333,63 +5324,74 @@ static void GWKResampleNoMasksOrDstDensityOnlyThreadInternal( void* pData )
     CPLFree( padfWeight );
 }
 
-template<class T,GDALResampleAlg eResample>
+template<class T, GDALResampleAlg eResample>
 static void GWKResampleNoMasksOrDstDensityOnlyThread( void* pData )
 {
-    GWKResampleNoMasksOrDstDensityOnlyThreadInternal<T,eResample,FALSE>(pData);
+    GWKResampleNoMasksOrDstDensityOnlyThreadInternal<T, eResample,
+                                                     FALSE>(pData);
 }
 
-template<class T,GDALResampleAlg eResample>
+template<class T, GDALResampleAlg eResample>
 static void GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread( void* pData )
 
 {
-    GWKJobStruct* psJob = (GWKJobStruct*) pData;
+    GWKJobStruct* psJob = static_cast<GWKJobStruct *>(pData);
     GDALWarpKernel *poWK = psJob->poWK;
     CPLAssert(eResample == GRA_Bilinear || eResample == GRA_Cubic);
-    int bUse4SamplesFormula = (poWK->dfXScale >= 0.95 && poWK->dfYScale >= 0.95);
+    const bool bUse4SamplesFormula =
+        poWK->dfXScale >= 0.95 && poWK->dfYScale >= 0.95;
     if( bUse4SamplesFormula )
-        GWKResampleNoMasksOrDstDensityOnlyThreadInternal<T,eResample,TRUE>(pData);
+        GWKResampleNoMasksOrDstDensityOnlyThreadInternal<T, eResample,
+                                                         TRUE>(pData);
     else
-        GWKResampleNoMasksOrDstDensityOnlyThreadInternal<T,eResample,FALSE>(pData);
+        GWKResampleNoMasksOrDstDensityOnlyThreadInternal<T, eResample,
+                                                         FALSE>(pData);
 }
 
 static CPLErr GWKNearestNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKNearestNoMasksOrDstDensityOnlyByte",
-                   GWKResampleNoMasksOrDstDensityOnlyThread<GByte,GRA_NearestNeighbour> );
+    return GWKRun(
+        poWK, "GWKNearestNoMasksOrDstDensityOnlyByte",
+        GWKResampleNoMasksOrDstDensityOnlyThread<GByte, GRA_NearestNeighbour>);
 }
 
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKBilinearNoMasksOrDstDensityOnlyByte",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GByte,GRA_Bilinear> );
+    return GWKRun(
+        poWK, "GWKBilinearNoMasksOrDstDensityOnlyByte",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GByte,
+                                                           GRA_Bilinear>);
 }
 
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKCubicNoMasksOrDstDensityOnlyByte",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GByte,GRA_Cubic> );
+    return GWKRun(
+        poWK, "GWKCubicNoMasksOrDstDensityOnlyByte",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GByte, GRA_Cubic>);
 }
 
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyFloat( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKCubicNoMasksOrDstDensityOnlyFloat",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<float,GRA_Cubic> );
+    return GWKRun(
+        poWK, "GWKCubicNoMasksOrDstDensityOnlyFloat",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<float, GRA_Cubic>);
 }
 
 #ifdef INSTANTIATE_FLOAT64_SSE2_IMPL
 
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyDouble( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKCubicNoMasksOrDstDensityOnlyDouble",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<double,GRA_Cubic> );
+    return GWKRun(
+        poWK, "GWKCubicNoMasksOrDstDensityOnlyDouble",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<double, GRA_Cubic>);
 }
 #endif
 
 static CPLErr GWKCubicSplineNoMasksOrDstDensityOnlyByte( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKCubicSplineNoMasksOrDstDensityOnlyByte",
-                   GWKResampleNoMasksOrDstDensityOnlyThread<GByte,GRA_CubicSpline> );
+    return GWKRun(
+        poWK, "GWKCubicSplineNoMasksOrDstDensityOnlyByte",
+        GWKResampleNoMasksOrDstDensityOnlyThread<GByte, GRA_CubicSpline>);
 }
 
 /************************************************************************/
@@ -4404,48 +5406,53 @@ template<class T>
 static void GWKNearestThread( void* pData )
 
 {
-    GWKJobStruct* psJob = (GWKJobStruct*) pData;
+    GWKJobStruct* psJob = static_cast<GWKJobStruct *>(pData);
     GDALWarpKernel *poWK = psJob->poWK;
-    int iYMin = psJob->iYMin;
-    int iYMax = psJob->iYMax;
+    const int iYMin = psJob->iYMin;
+    const int iYMax = psJob->iYMax;
 
-    int iDstY;
-    int nDstXSize = poWK->nDstXSize;
-    int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
+    const int nDstXSize = poWK->nDstXSize;
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate x,y,z coordinate arrays for transformation ... one     */
 /*      scanlines worth of positions.                                   */
 /* -------------------------------------------------------------------- */
-    double *padfX, *padfY, *padfZ;
-    int    *pabSuccess;
 
-    padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
-
-    double dfSrcCoordPrecision = CPLAtof(
-        CSLFetchNameValueDef(poWK->papszWarpOptions, "SRC_COORD_PRECISION", "0"));
-    double dfErrorThreshold = CPLAtof(
+    // For x, 2 *, because we cache the precomputed values at the end.
+    double *padfX =
+        static_cast<double *>(CPLMalloc(2 * sizeof(double) * nDstXSize));
+    double *padfY =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfZ =
+       static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    int *pabSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nDstXSize));
+
+    const double dfSrcCoordPrecision = CPLAtof(
+        CSLFetchNameValueDef(poWK->papszWarpOptions,
+                             "SRC_COORD_PRECISION", "0"));
+    const double dfErrorThreshold = CPLAtof(
         CSLFetchNameValueDef(poWK->papszWarpOptions, "ERROR_THRESHOLD", "0"));
 
+    // Precompute values.
+    for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        padfX[nDstXSize + iDstX] = iDstX + 0.5 + poWK->nDstXOff;
+
 /* ==================================================================== */
 /*      Loop over output lines.                                         */
 /* ==================================================================== */
-    for( iDstY = iYMin; iDstY < iYMax; iDstY++ )
+    for( int iDstY = iYMin; iDstY < iYMax; iDstY++ )
     {
-        int iDstX;
 
 /* -------------------------------------------------------------------- */
 /*      Setup points to transform to source image space.                */
 /* -------------------------------------------------------------------- */
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
-        {
-            padfX[iDstX] = iDstX + 0.5 + poWK->nDstXOff;
-            padfY[iDstX] = iDstY + 0.5 + poWK->nDstYOff;
-            padfZ[iDstX] = 0.0;
-        }
+        memcpy( padfX, padfX + nDstXSize, sizeof(double) * nDstXSize );
+        const double dfY = iDstY + 0.5 + poWK->nDstYOff;
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
+            padfY[iDstX] = dfY;
+        memset( padfZ, 0, sizeof(double) * nDstXSize );
 
 /* -------------------------------------------------------------------- */
 /*      Transform the points from destination pixel/line coordinates    */
@@ -4455,7 +5462,8 @@ static void GWKNearestThread( void* pData )
                               padfX, padfY, padfZ, pabSuccess );
         if( dfSrcCoordPrecision > 0.0 )
         {
-            GWKRoundSourceCoordinates(nDstXSize, padfX, padfY, padfZ, pabSuccess,
+            GWKRoundSourceCoordinates(nDstXSize, padfX, padfY, padfZ,
+                                      pabSuccess,
                                       dfSrcCoordPrecision,
                                       dfErrorThreshold,
                                       poWK->pfnTransformer,
@@ -4466,11 +5474,9 @@ static void GWKNearestThread( void* pData )
 /* ==================================================================== */
 /*      Loop over pixels in output scanline.                            */
 /* ==================================================================== */
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
-            int iDstOffset;
-
-            int iSrcOffset;
+            int iSrcOffset = 0;
             if( !GWKCheckAndComputeSrcOffsets(pabSuccess, iDstX, padfX, padfY,
                                     poWK, nSrcXSize, nSrcYSize, iSrcOffset) )
                 continue;
@@ -4486,46 +5492,49 @@ static void GWKNearestThread( void* pData )
 /* -------------------------------------------------------------------- */
 /*      Do not try to apply transparent source pixels to the destination.*/
 /* -------------------------------------------------------------------- */
-            double  dfDensity = 1.0;
+            double dfDensity = 1.0;
 
             if( poWK->pafUnifiedSrcDensity != NULL )
             {
                 dfDensity = poWK->pafUnifiedSrcDensity[iSrcOffset];
-                if( dfDensity < 0.00001 )
+                if( dfDensity < SRC_DENSITY_THRESHOLD )
                     continue;
             }
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
 /* ==================================================================== */
-            int iBand;
 
-            iDstOffset = iDstX + iDstY * nDstXSize;
+            const int iDstOffset = iDstX + iDstY * nDstXSize;
 
-            for( iBand = 0; iBand < poWK->nBands; iBand++ )
+            for( int iBand = 0; iBand < poWK->nBands; iBand++ )
             {
-                T   value = 0;
+                T value = 0;
                 double dfBandDensity = 0.0;
 
 /* -------------------------------------------------------------------- */
 /*      Collect the source value.                                       */
 /* -------------------------------------------------------------------- */
-                if ( GWKGetPixelT(poWK, iBand, iSrcOffset, &dfBandDensity, &value) )
+                if( GWKGetPixelT(poWK, iBand, iSrcOffset,
+                                 &dfBandDensity, &value) )
                 {
                     if( dfBandDensity < 1.0 )
                     {
                         if( dfBandDensity == 0.0 )
-                            /* do nothing */;
+                        {
+                            // Do nothing.
+                        }
                         else
                         {
-                            /* let the general code take care of mixing */
+                            // Let the general code take care of mixing.
                             GWKSetPixelValueRealT( poWK, iBand, iDstOffset,
                                           dfBandDensity, value );
                         }
                     }
                     else
                     {
-                        ((T *)poWK->papabyDstImage[iBand])[iDstOffset] = value;
+                        reinterpret_cast<T *>(
+                            poWK->papabyDstImage[iBand])[iDstOffset] = value;
                     }
                 }
             }
@@ -4545,7 +5554,7 @@ static void GWKNearestThread( void* pData )
 /* -------------------------------------------------------------------- */
 /*      Report progress to the user, and optionally cancel out.         */
 /* -------------------------------------------------------------------- */
-        if (psJob->pfnProgress && psJob->pfnProgress(psJob))
+        if( psJob->pfnProgress && psJob->pfnProgress(psJob) )
             break;
     }
 
@@ -4565,78 +5574,92 @@ static CPLErr GWKNearestByte( GDALWarpKernel *poWK )
 
 static CPLErr GWKNearestNoMasksOrDstDensityOnlyShort( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKNearestNoMasksOrDstDensityOnlyShort",
-                   GWKResampleNoMasksOrDstDensityOnlyThread<GInt16,GRA_NearestNeighbour> );
+    return GWKRun(
+        poWK, "GWKNearestNoMasksOrDstDensityOnlyShort",
+        GWKResampleNoMasksOrDstDensityOnlyThread<GInt16, GRA_NearestNeighbour>);
 }
 
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyShort( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKBilinearNoMasksOrDstDensityOnlyShort",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GInt16,GRA_Bilinear> );
+    return GWKRun(
+        poWK, "GWKBilinearNoMasksOrDstDensityOnlyShort",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GInt16,
+                                                           GRA_Bilinear>);
 }
 
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyUShort( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKBilinearNoMasksOrDstDensityOnlyUShort",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GUInt16,GRA_Bilinear> );
+    return GWKRun(
+        poWK, "GWKBilinearNoMasksOrDstDensityOnlyUShort",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GUInt16,
+                                                           GRA_Bilinear>);
 }
 
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyFloat( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKBilinearNoMasksOrDstDensityOnlyFloat",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<float,GRA_Bilinear> );
+    return GWKRun(
+        poWK, "GWKBilinearNoMasksOrDstDensityOnlyFloat",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<float,
+                                                           GRA_Bilinear>);
 }
 
 #ifdef INSTANTIATE_FLOAT64_SSE2_IMPL
 
 static CPLErr GWKBilinearNoMasksOrDstDensityOnlyDouble( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKBilinearNoMasksOrDstDensityOnlyDouble",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<double,GRA_Bilinear> );
+    return GWKRun(
+        poWK, "GWKBilinearNoMasksOrDstDensityOnlyDouble",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<double,
+                                                           GRA_Bilinear>);
 }
 #endif
 
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyShort( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKCubicNoMasksOrDstDensityOnlyShort",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GInt16,GRA_Cubic> );
+    return GWKRun(
+        poWK, "GWKCubicNoMasksOrDstDensityOnlyShort",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GInt16, GRA_Cubic>);
 }
 
 static CPLErr GWKCubicNoMasksOrDstDensityOnlyUShort( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKCubicNoMasksOrDstDensityOnlyUShort",
-                   GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GUInt16,GRA_Cubic> );
+    return GWKRun(
+        poWK, "GWKCubicNoMasksOrDstDensityOnlyUShort",
+        GWKResampleNoMasksOrDstDensityOnlyHas4SampleThread<GUInt16, GRA_Cubic>);
 }
 
 static CPLErr GWKCubicSplineNoMasksOrDstDensityOnlyShort( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKCubicSplineNoMasksOrDstDensityOnlyShort",
-                   GWKResampleNoMasksOrDstDensityOnlyThread<GInt16,GRA_CubicSpline> );
+    return GWKRun(
+        poWK, "GWKCubicSplineNoMasksOrDstDensityOnlyShort",
+        GWKResampleNoMasksOrDstDensityOnlyThread<GInt16, GRA_CubicSpline>);
 }
 
-static CPLErr GWKCubicSplineNoMasksOrDstDensityOnlyUShort( GDALWarpKernel *poWK )
+static CPLErr GWKCubicSplineNoMasksOrDstDensityOnlyUShort(
+    GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKCubicSplineNoMasksOrDstDensityOnlyUShort",
-                   GWKResampleNoMasksOrDstDensityOnlyThread<GUInt16,GRA_CubicSpline> );
+    return GWKRun(
+        poWK, "GWKCubicSplineNoMasksOrDstDensityOnlyUShort",
+        GWKResampleNoMasksOrDstDensityOnlyThread<GUInt16, GRA_CubicSpline>);
 }
 
 static CPLErr GWKNearestShort( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKNearestShort", GWKNearestThread<GInt16> );
+    return GWKRun(poWK, "GWKNearestShort", GWKNearestThread<GInt16>);
 }
 
 static CPLErr GWKNearestNoMasksOrDstDensityOnlyFloat( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKNearestNoMasksOrDstDensityOnlyFloat",
-                   GWKResampleNoMasksOrDstDensityOnlyThread<float,GRA_NearestNeighbour> );
+    return GWKRun(
+        poWK, "GWKNearestNoMasksOrDstDensityOnlyFloat",
+        GWKResampleNoMasksOrDstDensityOnlyThread<float, GRA_NearestNeighbour>);
 }
 
 static CPLErr GWKNearestFloat( GDALWarpKernel *poWK )
 {
-    return GWKRun( poWK, "GWKNearestFloat", GWKNearestThread<float> );
+    return GWKRun(poWK, "GWKNearestFloat", GWKNearestThread<float>);
 }
 
-
 /************************************************************************/
 /*                           GWKAverageOrMode()                         */
 /*                                                                      */
@@ -4649,65 +5672,67 @@ static CPLErr GWKAverageOrMode( GDALWarpKernel *poWK )
     return GWKRun( poWK, "GWKAverageOrMode", GWKAverageOrModeThread );
 }
 
-// overall logic based on GWKGeneralCaseThread()
+// Overall logic based on GWKGeneralCaseThread().
 static void GWKAverageOrModeThread( void* pData)
 {
-    GWKJobStruct* psJob = (GWKJobStruct*) pData;
+    GWKJobStruct* psJob = static_cast<GWKJobStruct *>(pData);
     GDALWarpKernel *poWK = psJob->poWK;
-    int iYMin = psJob->iYMin;
-    int iYMax = psJob->iYMax;
+    const int iYMin = psJob->iYMin;
+    const int iYMax = psJob->iYMax;
 
-    int iDstY, iDstX, iSrcX, iSrcY, iDstOffset;
-    int nDstXSize = poWK->nDstXSize;
-    int nSrcXSize = poWK->nSrcXSize, nSrcYSize = poWK->nSrcYSize;
+    const int nDstXSize = poWK->nDstXSize;
+    const int nSrcXSize = poWK->nSrcXSize;
+    const int nSrcYSize = poWK->nSrcYSize;
 
 /* -------------------------------------------------------------------- */
 /*      Find out which algorithm to use (small optim.)                  */
 /* -------------------------------------------------------------------- */
     int nAlgo = 0;
 
-    // these vars only used with nAlgo == 3
+    // These vars only used with nAlgo == 3.
     int *panVals = NULL;
-    int nBins = 0, nBinsOffset = 0;
+    int nBins = 0;
+    int nBinsOffset = 0;
 
-    // only used with nAlgo = 2
-    float*   pafVals = NULL;
-    int*     panSums = NULL;
+    // Only used with nAlgo = 2.
+    float* pafVals = NULL;
+    int* panSums = NULL;
 
-    // only used with nAlgo = 6
+    // Only used with nAlgo = 6.
     float quant = 0.5;
 
-    if ( poWK->eResample == GRA_Average )
+    if( poWK->eResample == GRA_Average )
     {
         nAlgo = GWKAOM_Average;
     }
     else if( poWK->eResample == GRA_Mode )
     {
-        // TODO check color table count > 256
-        if ( poWK->eWorkingDataType == GDT_Byte ||
-             poWK->eWorkingDataType == GDT_UInt16 ||
-             poWK->eWorkingDataType == GDT_Int16 )
+        // TODO check color table count > 256.
+        if( poWK->eWorkingDataType == GDT_Byte ||
+            poWK->eWorkingDataType == GDT_UInt16 ||
+            poWK->eWorkingDataType == GDT_Int16 )
         {
             nAlgo = GWKAOM_Imode;
 
-            /* In the case of a paletted or non-paletted byte band, */
-            /* input values are between 0 and 255 */
-            if ( poWK->eWorkingDataType == GDT_Byte )
+            // In the case of a paletted or non-paletted byte band,
+            // Input values are between 0 and 255.
+            if( poWK->eWorkingDataType == GDT_Byte )
             {
                 nBins = 256;
             }
-            /* In the case of Int16, input values are between -32768 and 32767 */
-            else if ( poWK->eWorkingDataType == GDT_Int16 )
+            // In the case of Int16, input values are between -32768 and 32767.
+            else if( poWK->eWorkingDataType == GDT_Int16 )
             {
                 nBins = 65536;
                 nBinsOffset = 32768;
             }
-            /* In the case of UInt16, input values are between 0 and 65537 */
-            else if ( poWK->eWorkingDataType == GDT_UInt16 )
+            // In the case of UInt16, input values are between 0 and 65537.
+            else if( poWK->eWorkingDataType == GDT_UInt16 )
             {
                 nBins = 65536;
             }
-            panVals = (int*) VSI_MALLOC_VERBOSE(nBins * sizeof(int));
+            panVals =
+                static_cast<int *>(VSI_MALLOC_VERBOSE(nBins * sizeof(int)));
             if( panVals == NULL )
                 return;
         }
@@ -4715,10 +5740,12 @@ static void GWKAverageOrModeThread( void* pData)
         {
             nAlgo = GWKAOM_Fmode;
 
-            if ( nSrcXSize > 0 && nSrcYSize > 0 )
+            if( nSrcXSize > 0 && nSrcYSize > 0 )
             {
-                pafVals = (float*) VSI_MALLOC3_VERBOSE(nSrcXSize, nSrcYSize, sizeof(float));
-                panSums = (int*) VSI_MALLOC3_VERBOSE(nSrcXSize, nSrcYSize, sizeof(int));
+                pafVals = static_cast<float *>(
+                    VSI_MALLOC3_VERBOSE(nSrcXSize, nSrcYSize, sizeof(float)));
+                panSums = static_cast<int *>(
+                    VSI_MALLOC3_VERBOSE(nSrcXSize, nSrcYSize, sizeof(int)));
                 if( pafVals == NULL || panSums == NULL )
                 {
                     VSIFree(pafVals);
@@ -4753,44 +5780,52 @@ static void GWKAverageOrModeThread( void* pData)
     }
     else
     {
-        // other resample algorithms not permitted here
-        CPLDebug( "GDAL", "GDALWarpKernel():GWKAverageOrModeThread() ERROR, illegal resample" );
+        // Other resample algorithms not permitted here.
+        CPLDebug("GDAL",
+                 "GDALWarpKernel():GWKAverageOrModeThread() ERROR, "
+                 "illegal resample" );
         return;
     }
-    CPLDebug( "GDAL", "GDALWarpKernel():GWKAverageOrModeThread() using algo %d", nAlgo );
+
+    CPLDebug("GDAL",
+             "GDALWarpKernel():GWKAverageOrModeThread() using algo %d", nAlgo);
 
 /* -------------------------------------------------------------------- */
 /*      Allocate x,y,z coordinate arrays for transformation ... two     */
 /*      scanlines worth of positions.                                   */
 /* -------------------------------------------------------------------- */
-    double *padfX, *padfY, *padfZ;
-    double *padfX2, *padfY2, *padfZ2;
-    int    *pabSuccess, *pabSuccess2;
-
-    padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfX2 = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfY2 = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    padfZ2 = (double *) CPLMalloc(sizeof(double) * nDstXSize);
-    pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
-    pabSuccess2 = (int *) CPLMalloc(sizeof(int) * nDstXSize);
-
-    double dfSrcCoordPrecision = CPLAtof(
-        CSLFetchNameValueDef(poWK->papszWarpOptions, "SRC_COORD_PRECISION", "0"));
-    double dfErrorThreshold = CPLAtof(
+
+    double *padfX =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfY =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfZ =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfX2 =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfY2 =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    double *padfZ2 =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nDstXSize));
+    int *pabSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nDstXSize));
+    int *pabSuccess2 = static_cast<int *>(CPLMalloc(sizeof(int) * nDstXSize));
+
+    const double dfSrcCoordPrecision = CPLAtof(
+        CSLFetchNameValueDef(poWK->papszWarpOptions,
+                             "SRC_COORD_PRECISION", "0"));
+    const double dfErrorThreshold = CPLAtof(
         CSLFetchNameValueDef(poWK->papszWarpOptions, "ERROR_THRESHOLD", "0"));
 
 /* ==================================================================== */
 /*      Loop over output lines.                                         */
 /* ==================================================================== */
-    for( iDstY = iYMin; iDstY < iYMax; iDstY++ )
+    for( int iDstY = iYMin; iDstY < iYMax; iDstY++ )
     {
 
 /* -------------------------------------------------------------------- */
 /*      Setup points to transform to source image space.                */
 /* -------------------------------------------------------------------- */
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
             padfX[iDstX] = iDstX + poWK->nDstXOff;
             padfY[iDstX] = iDstY + poWK->nDstYOff;
@@ -4811,14 +5846,16 @@ static void GWKAverageOrModeThread( void* pData)
 
         if( dfSrcCoordPrecision > 0.0 )
         {
-            GWKRoundSourceCoordinates(nDstXSize, padfX, padfY, padfZ, pabSuccess,
+            GWKRoundSourceCoordinates(nDstXSize, padfX, padfY, padfZ,
+                                      pabSuccess,
                                       dfSrcCoordPrecision,
                                       dfErrorThreshold,
                                       poWK->pfnTransformer,
                                       psJob->pTransformerArg,
                                       poWK->nDstXOff,
                                       iDstY + poWK->nDstYOff);
-            GWKRoundSourceCoordinates(nDstXSize, padfX2, padfY2, padfZ2, pabSuccess2,
+            GWKRoundSourceCoordinates(nDstXSize, padfX2, padfY2, padfZ2,
+                                      pabSuccess2,
                                       dfSrcCoordPrecision,
                                       dfErrorThreshold,
                                       poWK->pfnTransformer,
@@ -4830,15 +5867,15 @@ static void GWKAverageOrModeThread( void* pData)
 /* ==================================================================== */
 /*      Loop over pixels in output scanline.                            */
 /* ==================================================================== */
-        for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
+        for( int iDstX = 0; iDstX < nDstXSize; iDstX++ )
         {
             int iSrcOffset = 0;
-            double  dfDensity = 1.0;
-            int bHasFoundDensity = FALSE;
+            double dfDensity = 1.0;
+            bool bHasFoundDensity = false;
 
             if( !pabSuccess[iDstX] || !pabSuccess2[iDstX] )
                 continue;
-            iDstOffset = iDstX + iDstY * nDstXSize;
+            const int iDstOffset = iDstX + iDstY * nDstXSize;
 
 /* ==================================================================== */
 /*      Loop processing each band.                                      */
@@ -4848,7 +5885,6 @@ static void GWKAverageOrModeThread( void* pData)
             {
                 double dfBandDensity = 0.0;
                 double dfValueReal = 0.0;
-                double dfValueImag = 0.0;
                 double dfValueRealTmp = 0.0;
                 double dfValueImagTmp = 0.0;
 
@@ -4856,46 +5892,71 @@ static void GWKAverageOrModeThread( void* pData)
 /*      Collect the source value.                                       */
 /* -------------------------------------------------------------------- */
 
-                double dfTotal = 0;
-                int    nCount = 0;  // count of pixels used to compute average/mode
-                int    nCount2 = 0; // count of all pixels sampled, including nodata
-                int iSrcXMin, iSrcXMax,iSrcYMin,iSrcYMax;
-
-                // compute corners in source crs
-                iSrcXMin = MAX( ((int) floor((padfX[iDstX] + 1e-10))) - poWK->nSrcXOff, 0 );
-                iSrcXMax = MIN( ((int) ceil((padfX2[iDstX] - 1e-10))) - poWK->nSrcXOff, nSrcXSize );
-                iSrcYMin = MAX( ((int) floor((padfY[iDstX] + 1e-10))) - poWK->nSrcYOff, 0 );
-                iSrcYMax = MIN( ((int) ceil((padfY2[iDstX] - 1e-10))) - poWK->nSrcYOff, nSrcYSize );
-
-                // The transformation might not have preserved ordering of coordinates
-                // so do the necessary swapping (#5433)
-                // NOTE: this is really an approximative fix. To do something more precise
-                // we would for example need to compute the transformation of coordinates
-                // in the [iDstX,iDstY]x[iDstX+1,iDstY+1] square back to source coordinates,
-                // and take the bounding box of the got source coordinates.
+                double dfTotal = 0.0;
+                // Count of pixels used to compute average/mode.
+                int nCount = 0;
+                // Count of all pixels sampled, including nodata.
+                int nCount2 = 0;
+
+                // Compute corners in source crs.
+                int iSrcXMin =
+                    std::max(static_cast<int>(floor(padfX[iDstX] + 1e-10)) -
+                             poWK->nSrcXOff, 0);
+                int iSrcXMax =
+                    std::min(static_cast<int>(ceil(padfX2[iDstX] - 1e-10)) -
+                             poWK->nSrcXOff, nSrcXSize);
+                int iSrcYMin =
+                    std::max(static_cast<int>(floor(padfY[iDstX] + 1e-10)) -
+                             poWK->nSrcYOff, 0);
+                int iSrcYMax =
+                    std::min(static_cast<int>(ceil(padfY2[iDstX] - 1e-10)) -
+                             poWK->nSrcYOff, nSrcYSize);
+
+                // The transformation might not have preserved ordering of
+                // coordinates so do the necessary swapping (#5433).
+                // NOTE: this is really an approximative fix. To do something
+                // more precise we would for example need to compute the
+                // transformation of coordinates in the
+                // [iDstX,iDstY]x[iDstX+1,iDstY+1] square back to source
+                // coordinates, and take the bounding box of the got source
+                // coordinates.
                 if( iSrcXMax < iSrcXMin )
                 {
-                    iSrcXMin = MAX( ((int) floor((padfX2[iDstX] + 1e-10))) - poWK->nSrcXOff, 0 );
-                    iSrcXMax = MIN( ((int) ceil((padfX[iDstX] - 1e-10))) - poWK->nSrcXOff, nSrcXSize );
+                    iSrcXMin = std::max(
+                         static_cast<int>(floor((padfX2[iDstX] + 1.0e-10))) -
+                         poWK->nSrcXOff,
+                         0);
+                    iSrcXMax = std::min(
+                         static_cast<int>(ceil((padfX[iDstX] - 1.0e-10))) -
+                         poWK->nSrcXOff,
+                         nSrcXSize);
                 }
                 if( iSrcYMax < iSrcYMin )
                 {
-                    iSrcYMin = MAX( ((int) floor((padfY2[iDstX] + 1e-10))) - poWK->nSrcYOff, 0 );
-                    iSrcYMax = MIN( ((int) ceil((padfY[iDstX] - 1e-10))) - poWK->nSrcYOff, nSrcYSize );
+                    iSrcYMin = std::max(
+                        static_cast<int>(floor((padfY2[iDstX] + 1e-10))) -
+                        poWK->nSrcYOff,
+                        0);
+                    iSrcYMax = std::min(
+                        static_cast<int>(ceil((padfY[iDstX] - 1e-10))) -
+                        poWK->nSrcYOff,
+                        nSrcYSize);
                 }
                 if( iSrcXMin == iSrcXMax && iSrcXMax < nSrcXSize )
-                    iSrcXMax ++;
+                    iSrcXMax++;
                 if( iSrcYMin == iSrcYMax && iSrcYMax < nSrcYSize )
-                    iSrcYMax ++;
+                    iSrcYMax++;
 
-                // loop over source lines and pixels - 3 possible algorithms
+                // Loop over source lines and pixels - 3 possible algorithms.
 
-                if ( nAlgo == GWKAOM_Average ) // poWK->eResample == GRA_Average
+                // poWK->eResample == GRA_Average.
+                if( nAlgo == GWKAOM_Average )
                 {
-                    // this code adapted from GDALDownsampleChunk32R_AverageT() in gcore/overview.cpp
-                    for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
+                    // This code adapted from GDALDownsampleChunk32R_AverageT()
+                    // in gcore/overview.cpp.
+                    for( int iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                     {
-                        for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
+                        for( int iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
                         {
                             iSrcOffset = iSrcX + iSrcY * nSrcXSize;
 
@@ -4907,8 +5968,11 @@ static void GWKAverageOrModeThread( void* pData)
                             }
 
                             nCount2++;
-                            if ( GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                                   &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 )
+                            if( GWKGetPixelValue(
+                                    poWK, iBand, iSrcOffset,
+                                    &dfBandDensity, &dfValueRealTmp,
+                                    &dfValueImagTmp ) &&
+                                dfBandDensity > BAND_DENSITY_THRESHOLD )
                             {
                                 nCount++;
                                 dfTotal += dfValueRealTmp;
@@ -4916,30 +5980,33 @@ static void GWKAverageOrModeThread( void* pData)
                         }
                     }
 
-                    if ( nCount > 0 )
+                    if( nCount > 0 )
                     {
                         dfValueReal = dfTotal / nCount;
                         dfBandDensity = 1;
-                        bHasFoundDensity = TRUE;
+                        bHasFoundDensity = true;
                     }
-
-                } // GRA_Average
-
-                else if ( nAlgo == GWKAOM_Imode || nAlgo == GWKAOM_Fmode ) // poWK->eResample == GRA_Mode
+                }  // GRA_Average.
+                else if( nAlgo == GWKAOM_Imode || nAlgo == GWKAOM_Fmode )
+                // poWK->eResample == GRA_Mode
                 {
-                    // this code adapted from GDALDownsampleChunk32R_Mode() in gcore/overview.cpp
-
-                    if ( nAlgo == GWKAOM_Fmode ) // int32 or float
+                    // This code adapted from GDALDownsampleChunk32R_Mode() in
+                    // gcore/overview.cpp.
+                    if( nAlgo == GWKAOM_Fmode ) // int32 or float.
                     {
-                        /* I'm not sure how much sense it makes to run a
-                           majority filter on floating point data, but here it
-                           is for the sake of compatibility. It won't look
-                           right on RGB images by the nature of the filter. */
-                        int iMaxInd = 0, iMaxVal = -1, i = 0;
-
-                        for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
+                        // Does it make sense it makes to run a
+                        // majority filter on floating point data? But, here it
+                        // is for the sake of compatibility. It won't look
+                        // right on RGB images by the nature of the filter.
+                        int iMaxInd = 0;
+                        int iMaxVal = -1;
+                        int i = 0;
+
+                        for( int iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                         {
-                            for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
+                            for( int iSrcX = iSrcXMin;
+                                 iSrcX < iSrcXMax;
+                                 iSrcX++ )
                             {
                                 iSrcOffset = iSrcX + iSrcY * nSrcXSize;
 
@@ -4949,14 +6016,18 @@ static void GWKAverageOrModeThread( void* pData)
                                     continue;
 
                                 nCount2++;
-                                if ( GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                                       &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 )
+                                if( GWKGetPixelValue(
+                                        poWK, iBand, iSrcOffset,
+                                        &dfBandDensity, &dfValueRealTmp,
+                                        &dfValueImagTmp ) &&
+                                    dfBandDensity > BAND_DENSITY_THRESHOLD )
                                 {
                                     nCount++;
 
-                                    float fVal = (float)dfValueRealTmp;
+                                    const float fVal =
+                                        static_cast<float>(dfValueRealTmp);
 
-                                    //Check array for existing entry
+                                    // Check array for existing entry.
                                     for( i = 0; i < iMaxInd; ++i )
                                         if( pafVals[i] == fVal
                                             && ++panSums[i] > panSums[iMaxVal] )
@@ -4965,7 +6036,7 @@ static void GWKAverageOrModeThread( void* pData)
                                             break;
                                         }
 
-                                    //Add to arr if entry not already there
+                                    // Add to arr if entry not already there.
                                     if( i == iMaxInd )
                                     {
                                         pafVals[iMaxInd] = fVal;
@@ -4984,19 +6055,21 @@ static void GWKAverageOrModeThread( void* pData)
                         {
                             dfValueReal = pafVals[iMaxVal];
                             dfBandDensity = 1;
-                            bHasFoundDensity = TRUE;
+                            bHasFoundDensity = true;
                         }
                     }
-
-                    else // byte or int16
+                    else // byte or int16.
                     {
-                        int nMaxVal = 0, iMaxInd = -1;
+                        int nMaxVal = 0;
+                        int iMaxInd = -1;
 
                         memset(panVals, 0, nBins*sizeof(int));
 
-                        for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
+                        for( int iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                         {
-                            for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
+                            for( int iSrcX = iSrcXMin;
+                                 iSrcX < iSrcXMax;
+                                 iSrcX++ )
                             {
                                 iSrcOffset = iSrcX + iSrcY * nSrcXSize;
 
@@ -5006,16 +6079,20 @@ static void GWKAverageOrModeThread( void* pData)
                                     continue;
 
                                 nCount2++;
-                                if ( GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                                       &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 )
+                                if( GWKGetPixelValue(
+                                        poWK, iBand, iSrcOffset,
+                                        &dfBandDensity, &dfValueRealTmp,
+                                        &dfValueImagTmp ) &&
+                                    dfBandDensity > BAND_DENSITY_THRESHOLD )
                                 {
                                     nCount++;
 
-                                    int nVal = (int) dfValueRealTmp;
-                                    if ( ++panVals[nVal+nBinsOffset] > nMaxVal)
+                                    const int nVal =
+                                        static_cast<int>(dfValueRealTmp);
+                                    if( ++panVals[nVal+nBinsOffset] > nMaxVal )
                                     {
-                                        //Sum the density
-                                        //Is it the most common value so far?
+                                        // Sum the density.
+                                        // Is it the most common value so far?
                                         iMaxInd = nVal;
                                         nMaxVal = panVals[nVal+nBinsOffset];
                                     }
@@ -5027,18 +6104,18 @@ static void GWKAverageOrModeThread( void* pData)
                         {
                             dfValueReal = (float)iMaxInd;
                             dfBandDensity = 1;
-                            bHasFoundDensity = TRUE;
+                            bHasFoundDensity = true;
                         }
                     }
-
-                } // GRA_Mode
-                else if ( nAlgo == GWKAOM_Max ) // poWK->eResample == GRA_Max
+                }  // GRA_Mode.
+                else if( nAlgo == GWKAOM_Max )
+                // poWK->eResample == GRA_Max.
                 {
                     dfTotal = -DBL_MAX;
-                    // this code adapted from nAlgo 1 method, GRA_Average
-                    for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
+                    // This code adapted from nAlgo 1 method, GRA_Average.
+                    for( int iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                     {
-                        for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
+                        for( int iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
                         {
                             iSrcOffset = iSrcX + iSrcY * nSrcXSize;
 
@@ -5049,12 +6126,15 @@ static void GWKAverageOrModeThread( void* pData)
                                 continue;
                             }
 
-                            // Returns pixel value if it is not no data
-                            if ( GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                                   &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 )
+                            // Returns pixel value if it is not no data.
+                            if( GWKGetPixelValue(
+                                    poWK, iBand, iSrcOffset,
+                                    &dfBandDensity, &dfValueRealTmp,
+                                    &dfValueImagTmp ) &&
+                                dfBandDensity > BAND_DENSITY_THRESHOLD )
                             {
                                 nCount++;
-                                if (dfTotal < dfValueRealTmp)
+                                if( dfTotal < dfValueRealTmp )
                                 {
                                     dfTotal = dfValueRealTmp;
                                 }
@@ -5062,21 +6142,21 @@ static void GWKAverageOrModeThread( void* pData)
                         }
                     }
 
-                    if ( nCount > 0 )
+                    if( nCount > 0 )
                     {
                         dfValueReal = dfTotal;
                         dfBandDensity = 1;
-                        bHasFoundDensity = TRUE;
+                        bHasFoundDensity = true;
                     }
-
-                } // GRA_Max
-                else if ( nAlgo == GWKAOM_Min ) // poWK->eResample == GRA_Min
+                }  // GRA_Max.
+                else if( nAlgo == GWKAOM_Min )
+                // poWK->eResample == GRA_Min.
                 {
                     dfTotal = DBL_MAX;
-                    // this code adapted from nAlgo 1 method, GRA_Average
-                    for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
+                    // This code adapted from nAlgo 1 method, GRA_Average.
+                    for( int iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                     {
-                        for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
+                        for( int iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
                         {
                             iSrcOffset = iSrcX + iSrcY * nSrcXSize;
 
@@ -5087,12 +6167,15 @@ static void GWKAverageOrModeThread( void* pData)
                                 continue;
                             }
 
-                            // Returns pixel value if it is not no data
-                            if ( GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                                   &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 )
+                            // Returns pixel value if it is not no data.
+                            if( GWKGetPixelValue(
+                                    poWK, iBand, iSrcOffset,
+                                    &dfBandDensity, &dfValueRealTmp,
+                                    &dfValueImagTmp ) &&
+                                dfBandDensity > BAND_DENSITY_THRESHOLD )
                             {
                                 nCount++;
-                                if (dfTotal > dfValueRealTmp)
+                                if( dfTotal > dfValueRealTmp )
                                 {
                                     dfTotal = dfValueRealTmp;
                                 }
@@ -5100,22 +6183,22 @@ static void GWKAverageOrModeThread( void* pData)
                         }
                     }
 
-                    if ( nCount > 0 )
+                    if( nCount > 0 )
                     {
                         dfValueReal = dfTotal;
                         dfBandDensity = 1;
-                        bHasFoundDensity = TRUE;
+                        bHasFoundDensity = true;
                     }
-
-                } // GRA_Min
-                else if ( nAlgo == GWKAOM_Quant ) // poWK->eResample == GRA_Med | GRA_Q1 | GRA_Q3
+                }  // GRA_Min.
+                else if( nAlgo == GWKAOM_Quant )
+                // poWK->eResample == GRA_Med | GRA_Q1 | GRA_Q3.
                 {
                     std::vector<double> dfValuesTmp;
 
-                    // this code adapted from nAlgo 1 method, GRA_Average
-                    for( iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
+                    // This code adapted from nAlgo 1 method, GRA_Average.
+                    for( int iSrcY = iSrcYMin; iSrcY < iSrcYMax; iSrcY++ )
                     {
-                        for( iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
+                        for( int iSrcX = iSrcXMin; iSrcX < iSrcXMax; iSrcX++ )
                         {
                             iSrcOffset = iSrcX + iSrcY * nSrcXSize;
 
@@ -5126,9 +6209,12 @@ static void GWKAverageOrModeThread( void* pData)
                                 continue;
                             }
 
-                            // Returns pixel value if it is not no data
-                            if ( GWKGetPixelValue( poWK, iBand, iSrcOffset,
-                                                   &dfBandDensity, &dfValueRealTmp, &dfValueImagTmp ) && dfBandDensity > 0.0000000001 )
+                            // Returns pixel value if it is not no data.
+                            if( GWKGetPixelValue(
+                                    poWK, iBand, iSrcOffset,
+                                    &dfBandDensity, &dfValueRealTmp,
+                                    &dfValueImagTmp ) &&
+                                dfBandDensity > BAND_DENSITY_THRESHOLD )
                             {
                                 nCount++;
                                 dfValuesTmp.push_back(dfValueRealTmp);
@@ -5136,37 +6222,40 @@ static void GWKAverageOrModeThread( void* pData)
                         }
                     }
 
-                    if ( nCount > 0 )
+                    if( nCount > 0 )
                     {
                         std::sort(dfValuesTmp.begin(), dfValuesTmp.end());
-                        int quantIdx = static_cast<int>(std::ceil(quant * dfValuesTmp.size() - 1));
+                        int quantIdx = static_cast<int>(
+                            std::ceil(quant * dfValuesTmp.size() - 1));
                         dfValueReal = dfValuesTmp[quantIdx];
 
                         dfBandDensity = 1;
-                        bHasFoundDensity = TRUE;
+                        bHasFoundDensity = true;
                         dfValuesTmp.clear();
                     }
-
-                } // Quantile
+                }  // Quantile.
 
 /* -------------------------------------------------------------------- */
 /*      We have a computed value from the source.  Now apply it to      */
 /*      the destination pixel.                                          */
 /* -------------------------------------------------------------------- */
-                if ( bHasFoundDensity )
+                if( bHasFoundDensity )
                 {
-                    // TODO should we compute dfBandDensity in fct of nCount/nCount2 ,
-                    // or use as a threshold to set the dest value?
+                    // TODO: Should we compute dfBandDensity in fct of
+                    // nCount/nCount2, or use as a threshold to set the dest
+                    // value?
                     // dfBandDensity = (float) nCount / nCount2;
-                    // if ( (float) nCount / nCount2 > 0.1 )
-                    // or fix gdalwarp crop_to_cutline to crop partially overlapping pixels
+                    // if( (float) nCount / nCount2 > 0.1 )
+                    // or fix gdalwarp crop_to_cutline to crop partially
+                    // overlapping pixels.
+                    double dfValueImag = 0.0;
                     GWKSetPixelValue( poWK, iBand, iDstOffset,
                                       dfBandDensity,
                                       dfValueReal, dfValueImag );
                 }
             }
 
-            if (!bHasFoundDensity)
+            if( !bHasFoundDensity )
                 continue;
 
 /* -------------------------------------------------------------------- */
@@ -5179,13 +6268,12 @@ static void GWKAverageOrModeThread( void* pData)
                 poWK->panDstValid[iDstOffset>>5] |=
                     0x01 << (iDstOffset & 0x1f);
             }
-
         } /* Next iDstX */
 
 /* -------------------------------------------------------------------- */
 /*      Report progress to the user, and optionally cancel out.         */
 /* -------------------------------------------------------------------- */
-        if (psJob->pfnProgress && psJob->pfnProgress(psJob))
+        if( psJob->pfnProgress && psJob->pfnProgress(psJob) )
             break;
     }
 
diff --git a/alg/gdalwarpkernel_opencl.c b/alg/gdalwarpkernel_opencl.c
deleted file mode 100644
index c444578..0000000
--- a/alg/gdalwarpkernel_opencl.c
+++ /dev/null
@@ -1,2574 +0,0 @@
-/******************************************************************************
- * $Id: gdalwarpkernel_opencl.c 36105 2016-11-04 22:15:51Z rouault $
- *
- * Project:  OpenCL Image Reprojector
- * Purpose:  Implementation of the GDALWarpKernel reprojector in OpenCL.
- * Author:   Seth Price, seth at pricepages.org
- *
- ******************************************************************************
- * Copyright (c) 2010, Seth Price <seth at pricepages.org>
- * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#if defined(HAVE_OPENCL)
-
-/* The following line may be uncommented for increased debugging traces and profiling */
-/* #define DEBUG_OPENCL 1 */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <limits.h>
-#include <float.h>
-#include "cpl_string.h"
-#include "gdalwarpkernel_opencl.h"
-
-CPL_CVSID("$Id: gdalwarpkernel_opencl.c 36105 2016-11-04 22:15:51Z rouault $");
-
-#define handleErr(err) if((err) != CL_SUCCESS) { \
-    CPLError(CE_Failure, CPLE_AppDefined, "Error at file %s line %d: %s", __FILE__, __LINE__, getCLErrorString(err)); \
-    return err; \
-}
-
-#define handleErrRetNULL(err) if((err) != CL_SUCCESS) { \
-    (*clErr) = err; \
-    CPLError(CE_Failure, CPLE_AppDefined, "Error at file %s line %d: %s", __FILE__, __LINE__, getCLErrorString(err)); \
-    return NULL; \
-}
-
-#define handleErrGoto(err, goto_label) if((err) != CL_SUCCESS) { \
-    (*clErr) = err; \
-    CPLError(CE_Failure, CPLE_AppDefined, "Error at file %s line %d: %s", __FILE__, __LINE__, getCLErrorString(err)); \
-    goto goto_label; \
-}
-
-#define freeCLMem(clMem, fallBackMem)  do { \
-    if ((clMem) != NULL) { \
-        handleErr(err = clReleaseMemObject(clMem)); \
-        clMem = NULL; \
-        fallBackMem = NULL; \
-    } else if ((fallBackMem) != NULL) { \
-        CPLFree(fallBackMem); \
-        fallBackMem = NULL; \
-    } \
-} while(0)
-
-static const char* getCLErrorString(cl_int err)
-{
-    switch (err)
-    {
-        case CL_SUCCESS:
-            return("CL_SUCCESS");
-            break;
-        case CL_DEVICE_NOT_FOUND:
-            return("CL_DEVICE_NOT_FOUND");
-            break;
-        case CL_DEVICE_NOT_AVAILABLE:
-            return("CL_DEVICE_NOT_AVAILABLE");
-            break;
-        case CL_COMPILER_NOT_AVAILABLE:
-            return("CL_COMPILER_NOT_AVAILABLE");
-            break;
-        case CL_MEM_OBJECT_ALLOCATION_FAILURE:
-            return("CL_MEM_OBJECT_ALLOCATION_FAILURE");
-            break;
-        case CL_OUT_OF_RESOURCES:
-            return("CL_OUT_OF_RESOURCES");
-            break;
-        case CL_OUT_OF_HOST_MEMORY:
-            return("CL_OUT_OF_HOST_MEMORY");
-            break;
-        case CL_PROFILING_INFO_NOT_AVAILABLE:
-            return("CL_PROFILING_INFO_NOT_AVAILABLE");
-            break;
-        case CL_MEM_COPY_OVERLAP:
-            return("CL_MEM_COPY_OVERLAP");
-            break;
-        case CL_IMAGE_FORMAT_MISMATCH:
-            return("CL_IMAGE_FORMAT_MISMATCH");
-            break;
-        case CL_IMAGE_FORMAT_NOT_SUPPORTED:
-            return("CL_IMAGE_FORMAT_NOT_SUPPORTED");
-            break;
-        case CL_BUILD_PROGRAM_FAILURE:
-            return("CL_BUILD_PROGRAM_FAILURE");
-            break;
-        case CL_MAP_FAILURE:
-            return("CL_MAP_FAILURE");
-            break;
-        case CL_INVALID_VALUE:
-            return("CL_INVALID_VALUE");
-            break;
-        case CL_INVALID_DEVICE_TYPE:
-            return("CL_INVALID_DEVICE_TYPE");
-            break;
-        case CL_INVALID_PLATFORM:
-            return("CL_INVALID_PLATFORM");
-            break;
-        case CL_INVALID_DEVICE:
-            return("CL_INVALID_DEVICE");
-            break;
-        case CL_INVALID_CONTEXT:
-            return("CL_INVALID_CONTEXT");
-            break;
-        case CL_INVALID_QUEUE_PROPERTIES:
-            return("CL_INVALID_QUEUE_PROPERTIES");
-            break;
-        case CL_INVALID_COMMAND_QUEUE:
-            return("CL_INVALID_COMMAND_QUEUE");
-            break;
-        case CL_INVALID_HOST_PTR:
-            return("CL_INVALID_HOST_PTR");
-            break;
-        case CL_INVALID_MEM_OBJECT:
-            return("CL_INVALID_MEM_OBJECT");
-            break;
-        case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
-            return("CL_INVALID_IMAGE_FORMAT_DESCRIPTOR");
-            break;
-        case CL_INVALID_IMAGE_SIZE:
-            return("CL_INVALID_IMAGE_SIZE");
-            break;
-        case CL_INVALID_SAMPLER:
-            return("CL_INVALID_SAMPLER");
-            break;
-        case CL_INVALID_BINARY:
-            return("CL_INVALID_BINARY");
-            break;
-        case CL_INVALID_BUILD_OPTIONS:
-            return("CL_INVALID_BUILD_OPTIONS");
-            break;
-        case CL_INVALID_PROGRAM:
-            return("CL_INVALID_PROGRAM");
-            break;
-        case CL_INVALID_PROGRAM_EXECUTABLE:
-            return("CL_INVALID_PROGRAM_EXECUTABLE");
-            break;
-        case CL_INVALID_KERNEL_NAME:
-            return("CL_INVALID_KERNEL_NAME");
-            break;
-        case CL_INVALID_KERNEL_DEFINITION:
-            return("CL_INVALID_KERNEL_DEFINITION");
-            break;
-        case CL_INVALID_KERNEL:
-            return("CL_INVALID_KERNEL");
-            break;
-        case CL_INVALID_ARG_INDEX:
-            return("CL_INVALID_ARG_INDEX");
-            break;
-        case CL_INVALID_ARG_VALUE:
-            return("CL_INVALID_ARG_VALUE");
-            break;
-        case CL_INVALID_ARG_SIZE:
-            return("CL_INVALID_ARG_SIZE");
-            break;
-        case CL_INVALID_KERNEL_ARGS:
-            return("CL_INVALID_KERNEL_ARGS");
-            break;
-        case CL_INVALID_WORK_DIMENSION:
-            return("CL_INVALID_WORK_DIMENSION");
-            break;
-        case CL_INVALID_WORK_GROUP_SIZE:
-            return("CL_INVALID_WORK_GROUP_SIZE");
-            break;
-        case CL_INVALID_WORK_ITEM_SIZE:
-            return("CL_INVALID_WORK_ITEM_SIZE");
-            break;
-        case CL_INVALID_GLOBAL_OFFSET:
-            return("CL_INVALID_GLOBAL_OFFSET");
-            break;
-        case CL_INVALID_EVENT_WAIT_LIST:
-            return("CL_INVALID_EVENT_WAIT_LIST");
-            break;
-        case CL_INVALID_EVENT:
-            return("CL_INVALID_EVENT");
-            break;
-        case CL_INVALID_OPERATION:
-            return("CL_INVALID_OPERATION");
-            break;
-        case CL_INVALID_GL_OBJECT:
-            return("CL_INVALID_GL_OBJECT");
-            break;
-        case CL_INVALID_BUFFER_SIZE:
-            return("CL_INVALID_BUFFER_SIZE");
-            break;
-        case CL_INVALID_MIP_LEVEL:
-            return("CL_INVALID_MIP_LEVEL");
-            break;
-        case CL_INVALID_GLOBAL_WORK_SIZE:
-            return("CL_INVALID_GLOBAL_WORK_SIZE");
-            break;
-    }
-
-    return "unknown_error";
-}
-
-static const char* getCLDataTypeString( cl_channel_type dataType )
-{
-    switch( dataType )
-    {
-        case CL_SNORM_INT8: return "CL_SNORM_INT8";
-        case CL_SNORM_INT16: return "CL_SNORM_INT16";
-        case CL_UNORM_INT8: return "CL_UNORM_INT8";
-        case CL_UNORM_INT16: return "CL_UNORM_INT16";
-#if 0
-        case CL_UNORM_SHORT_565: return "CL_UNORM_SHORT_565";
-        case CL_UNORM_SHORT_555: return "CL_UNORM_SHORT_555";
-        case CL_UNORM_INT_101010: return "CL_UNORM_INT_101010";
-        case CL_SIGNED_INT8: return "CL_SIGNED_INT8";
-        case CL_SIGNED_INT16: return "CL_SIGNED_INT16";
-        case CL_SIGNED_INT32: return "CL_SIGNED_INT32";
-        case CL_UNSIGNED_INT8: return "CL_UNSIGNED_INT8";
-        case CL_UNSIGNED_INT16: return "CL_UNSIGNED_INT16";
-        case CL_UNSIGNED_INT32: return "CL_UNSIGNED_INT32";
-        case CL_HALF_FLOAT: return "CL_HALF_FLOAT";
-#endif
-        case CL_FLOAT: return "CL_FLOAT";
-        default: return "unknown";
-    }
-}
-
-/*
- Finds an appropriate OpenCL device. If the user specifies a preference, the
- code for it should be here (but not currently supported). For debugging, it's
- always easier to use CL_DEVICE_TYPE_CPU because then printf() can be called
- from the kernel. If debugging is on, we can print the name and stats about the
- device we're using.
- */
-cl_device_id get_device(OCLVendor *peVendor)
-{
-    cl_int err = 0;
-    cl_device_id device = NULL;
-    size_t returned_size = 0;
-    cl_char vendor_name[1024] = {0};
-    cl_char device_name[1024] = {0};
-
-    cl_platform_id platforms[10];
-    cl_uint num_platforms;
-
-    err = clGetPlatformIDs( 10, platforms, &num_platforms );
-    if( err != CL_SUCCESS || num_platforms == 0 )
-        return NULL;
-
-    // Find the GPU CL device, this is what we really want
-    // If there is no GPU device is CL capable, fall back to CPU
-    err = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_GPU, 1, &device, NULL);
-    if (err != CL_SUCCESS)
-    {
-        // Find the CPU CL device, as a fallback
-        err = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_CPU, 1, &device, NULL);
-        if( err != CL_SUCCESS || device == 0 )
-            return NULL;
-    }
-
-    // Get some information about the returned device
-    err = clGetDeviceInfo(device, CL_DEVICE_VENDOR, sizeof(vendor_name),
-                          vendor_name, &returned_size);
-    err |= clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_name),
-                           device_name, &returned_size);
-    assert(err == CL_SUCCESS);
-    CPLDebug( "OpenCL", "Connected to %s %s.", vendor_name, device_name);
-
-    if (STARTS_WITH((const char*)vendor_name, "Advanced Micro Devices"))
-        *peVendor = VENDOR_AMD;
-    else if (STARTS_WITH((const char*)vendor_name, "Intel(R) Corporation"))
-        *peVendor = VENDOR_INTEL;
-    else
-        *peVendor = VENDOR_OTHER;
-
-    return device;
-}
-
-/*
- Given that not all OpenCL devices support the same image formats, we need to
- make do with what we have. This leads to wasted space, but as OpenCL matures
- I hope it'll get better.
- */
-cl_int set_supported_formats(struct oclWarper *warper,
-                             cl_channel_order minOrderSize,
-                             cl_channel_order *chosenOrder,
-                             unsigned int *chosenSize,
-                             cl_channel_type dataType )
-{
-    cl_image_format *fmtBuf = (cl_image_format *)calloc(256, sizeof(cl_image_format));
-    cl_uint numRet;
-    int i;
-    int extraSpace = 9999;
-    cl_int err;
-    int bFound = FALSE;
-
-    //Find what we *can* handle
-    handleErr(err = clGetSupportedImageFormats(warper->context,
-                                               CL_MEM_READ_ONLY,
-                                               CL_MEM_OBJECT_IMAGE2D,
-                                               256, fmtBuf, &numRet));
-    for (i = 0; i < numRet; ++i) {
-        int thisOrderSize = 0;
-        switch (fmtBuf[i].image_channel_order)
-        {
-            //Only support formats which use the channels in order (x,y,z,w)
-          case CL_R:
-          case CL_INTENSITY:
-          case CL_LUMINANCE:
-            thisOrderSize = 1;
-            break;
-          case CL_RG:
-            thisOrderSize = 2;
-            break;
-          case CL_RGB:
-            thisOrderSize = 3;
-            break;
-          case CL_RGBA:
-            thisOrderSize = 4;
-            break;
-        }
-
-        //Choose an order with the least wasted space
-        if (fmtBuf[i].image_channel_data_type == dataType &&
-            minOrderSize <= thisOrderSize &&
-            extraSpace > thisOrderSize - minOrderSize ) {
-
-            //Set the vector size, order, & remember wasted space
-            (*chosenSize) = thisOrderSize;
-            (*chosenOrder) = fmtBuf[i].image_channel_order;
-            extraSpace = thisOrderSize - minOrderSize;
-            bFound = TRUE;
-        }
-    }
-
-    free(fmtBuf);
-
-    if( !bFound )
-    {
-        CPLDebug("OpenCL",
-                 "Cannot find supported format for dataType = %s and minOrderSize = %d",
-                 getCLDataTypeString(dataType), (int)minOrderSize);
-    }
-    return (bFound) ? CL_SUCCESS : CL_INVALID_OPERATION;
-}
-
-/*
- Allocate some pinned memory that we can use as an intermediate buffer. We're
- using the pinned memory to assemble the data before transferring it to the
- device. The reason we're using pinned RAM is because the transfer speed from
- host RAM to device RAM is faster than non-pinned. The disadvantage is that
- pinned RAM is a scarce OS resource. I'm making the assumption that the user
- has as much pinned host RAM available as total device RAM because device RAM
- tends to be similarly scarce. However, if the pinned memory fails we fall back
- to using a regular memory allocation.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int alloc_pinned_mem(struct oclWarper *warper, int imgNum, size_t dataSz,
-                        void **wrkPtr, cl_mem *wrkCL)
-{
-	cl_int err = CL_SUCCESS;
-    wrkCL[imgNum] = clCreateBuffer(warper->context,
-                                   CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR,
-                                   dataSz, NULL, &err);
-
-    if (err == CL_SUCCESS) {
-        wrkPtr[imgNum] = (void *)clEnqueueMapBuffer(warper->queue, wrkCL[imgNum],
-                                                    CL_FALSE, CL_MAP_WRITE,
-                                                    0, dataSz, 0, NULL, NULL, &err);
-        handleErr(err);
-    } else {
-        wrkCL[imgNum] = NULL;
-#ifdef DEBUG_OPENCL
-        CPLDebug("OpenCL", "Using fallback non-pinned memory!");
-#endif
-        //Fallback to regular allocation
-        wrkPtr[imgNum] = (void *)VSI_MALLOC_VERBOSE(dataSz);
-
-        if (wrkPtr[imgNum] == NULL)
-            handleErr(err = CL_OUT_OF_HOST_MEMORY);
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Allocates the working host memory for all bands of the image in the warper
- structure. This includes both the source image buffers and the destination
- buffers. This memory is located on the host, so we can assemble the image.
- Reasons for buffering it like this include reading each row from disk and
- de-interleaving bands and parts of bands. Then they can be copied to the device
- as a single operation fit for use as an OpenCL memory object.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int alloc_working_arr(struct oclWarper *warper,
-                         size_t ptrSz, size_t dataSz, size_t *fmtSz)
-{
-	cl_int err = CL_SUCCESS;
-    int i, b;
-    size_t srcDataSz1, dstDataSz1, srcDataSz4, dstDataSz4;
-    const int numBands = warper->numBands;
-
-    //Find the best channel order for this format
-    err = set_supported_formats(warper, 1,
-                                &(warper->imgChOrder1), &(warper->imgChSize1),
-                                warper->imageFormat);
-    handleErr(err);
-    if(warper->useVec) {
-        err = set_supported_formats(warper, 4,
-                                    &(warper->imgChOrder4), &(warper->imgChSize4),
-                                    warper->imageFormat);
-        handleErr(err);
-    }
-
-    //Alloc space for pointers to the main image data
-    warper->realWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
-    warper->dstRealWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
-    if (warper->realWork.v == NULL || warper->dstRealWork.v == NULL)
-        handleErr(err = CL_OUT_OF_HOST_MEMORY);
-
-    if (warper->imagWorkCL != NULL) {
-        //Alloc space for pointers to the extra channel, if it exists
-        warper->imagWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
-        warper->dstImagWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
-        if (warper->imagWork.v == NULL || warper->dstImagWork.v == NULL)
-            handleErr(err = CL_OUT_OF_HOST_MEMORY);
-    } else {
-        warper->imagWork.v = NULL;
-        warper->dstImagWork.v = NULL;
-    }
-
-    //Calc the sizes we need
-    srcDataSz1 = dataSz * warper->srcWidth * warper->srcHeight * warper->imgChSize1;
-    dstDataSz1 = dataSz * warper->dstWidth * warper->dstHeight;
-    srcDataSz4 = dataSz * warper->srcWidth * warper->srcHeight * warper->imgChSize4;
-    dstDataSz4 = dataSz * warper->dstWidth * warper->dstHeight * 4;
-
-    //Allocate pinned memory for each band's image
-    for (b = 0, i = 0; b < numBands && i < warper->numImages; ++i) {
-        if(warper->useVec && b < numBands - numBands % 4) {
-            handleErr(err = alloc_pinned_mem(warper, i, srcDataSz4,
-                                             warper->realWork.v,
-                                             warper->realWorkCL));
-
-            handleErr(err = alloc_pinned_mem(warper, i, dstDataSz4,
-                                             warper->dstRealWork.v,
-                                             warper->dstRealWorkCL));
-            b += 4;
-        } else {
-            handleErr(err = alloc_pinned_mem(warper, i, srcDataSz1,
-                                             warper->realWork.v,
-                                             warper->realWorkCL));
-
-            handleErr(err = alloc_pinned_mem(warper, i, dstDataSz1,
-                                             warper->dstRealWork.v,
-                                             warper->dstRealWorkCL));
-            ++b;
-        }
-    }
-
-    if (warper->imagWorkCL != NULL) {
-        //Allocate pinned memory for each band's extra channel, if exists
-        for (b = 0, i = 0; b < numBands && i < warper->numImages; ++i) {
-            if(warper->useVec && b < numBands - numBands % 4) {
-                handleErr(err = alloc_pinned_mem(warper, i, srcDataSz4,
-                                                 warper->imagWork.v,
-                                                 warper->imagWorkCL));
-
-                handleErr(err = alloc_pinned_mem(warper, i, dstDataSz4,
-                                                 warper->dstImagWork.v,
-                                                 warper->dstImagWorkCL));
-                b += 4;
-            } else {
-                handleErr(err = alloc_pinned_mem(warper, i, srcDataSz1,
-                                                 warper->imagWork.v,
-                                                 warper->imagWorkCL));
-
-                handleErr(err = alloc_pinned_mem(warper, i, dstDataSz1,
-                                                 warper->dstImagWork.v,
-                                                 warper->dstImagWorkCL));
-                ++b;
-            }
-        }
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Assemble and create the kernel. For optimization, portability, and
- implementation limitation reasons, the program is actually assembled from
- several strings, then compiled with as many invariants as possible defined by
- the preprocessor. There is also quite a bit of error-catching code in here
- because the kernel is where many bugs show up.
-
- Returns CL_SUCCESS on success and other CL_* errors in the error buffer when
- something goes wrong.
- */
-cl_kernel get_kernel(struct oclWarper *warper, char useVec,
-                     double dfXScale, double dfYScale, double dfXFilter, double dfYFilter,
-                     int nXRadius, int nYRadius, int nFiltInitX, int nFiltInitY,
-                     cl_int *clErr )
-{
-	cl_program program;
-    cl_kernel kernel;
-	cl_int err = CL_SUCCESS;
-    char *buffer = (char *)CPLCalloc(128000, sizeof(char));
-#define PROGBUF_SIZE 128000
-    char *progBuf = (char *)CPLCalloc(PROGBUF_SIZE, sizeof(char));
-    float dstMinVal, dstMaxVal;
-
-    const char *outType;
-    const char *dUseVec = "";
-    const char *dVecf = "float";
-    const char *kernGenFuncs =
-// ********************* General Funcs ********************
-"void clampToDst(float fReal,\n"
-                "__global outType *dstPtr,\n"
-                "unsigned int iDstOffset,\n"
-                "__constant float *fDstNoDataReal,\n"
-                "int bandNum);\n"
-"void setPixel(__global outType *dstReal,\n"
-                "__global outType *dstImag,\n"
-                "__global float *dstDensity,\n"
-                "__global int *nDstValid,\n"
-                "__constant float *fDstNoDataReal,\n"
-                "const int bandNum,\n"
-                "vecf fDensity, vecf fReal, vecf fImag);\n"
-"int getPixel(__read_only image2d_t srcReal,\n"
-                "__read_only image2d_t srcImag,\n"
-                "__global float *fUnifiedSrcDensity,\n"
-                "__global int *nUnifiedSrcValid,\n"
-                "__constant char *useBandSrcValid,\n"
-                "__global int *nBandSrcValid,\n"
-                "const int2 iSrc,\n"
-                "int bandNum,\n"
-                "vecf *fDensity, vecf *fReal, vecf *fImag);\n"
-"int isValid(__global float *fUnifiedSrcDensity,\n"
-                "__global int *nUnifiedSrcValid,\n"
-                "float2 fSrcCoords );\n"
-"float2 getSrcCoords(__read_only image2d_t srcCoords);\n"
-
-"#ifdef USE_CLAMP_TO_DST_FLOAT\n"
-"void clampToDst(float fReal,\n"
-                "__global outType *dstPtr,\n"
-                "unsigned int iDstOffset,\n"
-                "__constant float *fDstNoDataReal,\n"
-                "int bandNum)\n"
-"{\n"
-    "dstPtr[iDstOffset] = fReal;\n"
-"}\n"
-"#else\n"
-"void clampToDst(float fReal,\n"
-                "__global outType *dstPtr,\n"
-                "unsigned int iDstOffset,\n"
-                "__constant float *fDstNoDataReal,\n"
-                "int bandNum)\n"
-"{\n"
-	"fReal *= dstMaxVal;\n"
-
-    "if (fReal < dstMinVal)\n"
-        "dstPtr[iDstOffset] = (outType)dstMinVal;\n"
-    "else if (fReal > dstMaxVal)\n"
-        "dstPtr[iDstOffset] = (outType)dstMaxVal;\n"
-    "else\n"
-        "dstPtr[iDstOffset] = (dstMinVal < 0) ? (outType)floor(fReal + 0.5f) : (outType)(fReal + 0.5f);\n"
-
-    "if (useDstNoDataReal && bandNum >= 0 &&\n"
-        "fDstNoDataReal[bandNum] == dstPtr[iDstOffset])\n"
-    "{\n"
-        "if (dstPtr[iDstOffset] == dstMinVal)\n"
-            "dstPtr[iDstOffset] = dstMinVal + 1;\n"
-        "else\n"
-            "dstPtr[iDstOffset] = dstPtr[iDstOffset] - 1;\n"
-    "}\n"
-"}\n"
-"#endif\n"
-
-"void setPixel(__global outType *dstReal,\n"
-              "__global outType *dstImag,\n"
-              "__global float *dstDensity,\n"
-              "__global int *nDstValid,\n"
-              "__constant float *fDstNoDataReal,\n"
-              "const int bandNum,\n"
-              "vecf fDensity, vecf fReal, vecf fImag)\n"
-"{\n"
-    "unsigned int iDstOffset = get_global_id(1)*iDstWidth + get_global_id(0);\n"
-
-"#ifdef USE_VEC\n"
-    "if (fDensity.x < 0.00001f && fDensity.y < 0.00001f &&\n"
-        "fDensity.z < 0.00001f && fDensity.w < 0.00001f ) {\n"
-
-        "fReal = 0.0f;\n"
-        "fImag = 0.0f;\n"
-
-    "} else if (fDensity.x < 0.9999f || fDensity.y < 0.9999f ||\n"
-               "fDensity.z < 0.9999f || fDensity.w < 0.9999f ) {\n"
-        "vecf fDstReal, fDstImag;\n"
-        "float fDstDensity;\n"
-
-        "fDstReal.x = dstReal[iDstOffset];\n"
-        "fDstReal.y = dstReal[iDstOffset+iDstHeight*iDstWidth];\n"
-        "fDstReal.z = dstReal[iDstOffset+iDstHeight*iDstWidth*2];\n"
-        "fDstReal.w = dstReal[iDstOffset+iDstHeight*iDstWidth*3];\n"
-        "if (useImag) {\n"
-            "fDstImag.x = dstImag[iDstOffset];\n"
-            "fDstImag.y = dstImag[iDstOffset+iDstHeight*iDstWidth];\n"
-            "fDstImag.z = dstImag[iDstOffset+iDstHeight*iDstWidth*2];\n"
-            "fDstImag.w = dstImag[iDstOffset+iDstHeight*iDstWidth*3];\n"
-        "}\n"
-"#else\n"
-    "if (fDensity < 0.00001f) {\n"
-
-        "fReal = 0.0f;\n"
-        "fImag = 0.0f;\n"
-
-    "} else if (fDensity < 0.9999f) {\n"
-        "vecf fDstReal, fDstImag;\n"
-        "float fDstDensity;\n"
-
-        "fDstReal = dstReal[iDstOffset];\n"
-        "if (useImag)\n"
-            "fDstImag = dstImag[iDstOffset];\n"
-"#endif\n"
-
-        "if (useDstDensity)\n"
-            "fDstDensity = dstDensity[iDstOffset];\n"
-        "else if (useDstValid &&\n"
-                 "!((nDstValid[iDstOffset>>5] & (0x01 << (iDstOffset & 0x1f))) ))\n"
-            "fDstDensity = 0.0f;\n"
-        "else\n"
-            "fDstDensity = 1.0f;\n"
-
-        "vecf fDstInfluence = (1.0f - fDensity) * fDstDensity;\n"
-
-        // Density should be checked for <= 0.0 & handled by the calling function
-        "fReal = (fReal * fDensity + fDstReal * fDstInfluence) / (fDensity + fDstInfluence);\n"
-        "if (useImag)\n"
-            "fImag = (fImag * fDensity + fDstImag * fDstInfluence) / (fDensity + fDstInfluence);\n"
-    "}\n"
-
-"#ifdef USE_VEC\n"
-    "clampToDst(fReal.x, dstReal, iDstOffset, fDstNoDataReal, bandNum);\n"
-    "clampToDst(fReal.y, dstReal, iDstOffset+iDstHeight*iDstWidth, fDstNoDataReal, bandNum);\n"
-    "clampToDst(fReal.z, dstReal, iDstOffset+iDstHeight*iDstWidth*2, fDstNoDataReal, bandNum);\n"
-    "clampToDst(fReal.w, dstReal, iDstOffset+iDstHeight*iDstWidth*3, fDstNoDataReal, bandNum);\n"
-    "if (useImag) {\n"
-        "clampToDst(fImag.x, dstImag, iDstOffset, fDstNoDataReal, -1);\n"
-        "clampToDst(fImag.y, dstImag, iDstOffset+iDstHeight*iDstWidth, fDstNoDataReal, -1);\n"
-        "clampToDst(fImag.z, dstImag, iDstOffset+iDstHeight*iDstWidth*2, fDstNoDataReal, -1);\n"
-        "clampToDst(fImag.w, dstImag, iDstOffset+iDstHeight*iDstWidth*3, fDstNoDataReal, -1);\n"
-    "}\n"
-"#else\n"
-    "clampToDst(fReal, dstReal, iDstOffset, fDstNoDataReal, bandNum);\n"
-    "if (useImag)\n"
-        "clampToDst(fImag, dstImag, iDstOffset, fDstNoDataReal, -1);\n"
-"#endif\n"
-"}\n"
-
-"int getPixel(__read_only image2d_t srcReal,\n"
-             "__read_only image2d_t srcImag,\n"
-             "__global float *fUnifiedSrcDensity,\n"
-             "__global int *nUnifiedSrcValid,\n"
-             "__constant char *useBandSrcValid,\n"
-             "__global int *nBandSrcValid,\n"
-             "const int2 iSrc,\n"
-             "int bandNum,\n"
-             "vecf *fDensity, vecf *fReal, vecf *fImag)\n"
-"{\n"
-    "int iSrcOffset = 0, iBandValidLen = 0, iSrcOffsetMask = 0;\n"
-    "int bHasValid = FALSE;\n"
-
-    // Clamp the src offset values if needed
-    "if(useUnifiedSrcDensity | useUnifiedSrcValid | useUseBandSrcValid){\n"
-        "int iSrcX = iSrc.x;\n"
-        "int iSrcY = iSrc.y;\n"
-
-        // Needed because the offset isn't clamped in OpenCL hardware
-        "if(iSrcX < 0)\n"
-            "iSrcX = 0;\n"
-        "else if(iSrcX >= iSrcWidth)\n"
-            "iSrcX = iSrcWidth - 1;\n"
-
-        "if(iSrcY < 0)\n"
-            "iSrcY = 0;\n"
-        "else if(iSrcY >= iSrcHeight)\n"
-            "iSrcY = iSrcHeight - 1;\n"
-
-        "iSrcOffset = iSrcY*iSrcWidth + iSrcX;\n"
-        "iBandValidLen = 1 + ((iSrcWidth*iSrcHeight)>>5);\n"
-        "iSrcOffsetMask = (0x01 << (iSrcOffset & 0x1f));\n"
-    "}\n"
-
-    "if (useUnifiedSrcValid &&\n"
-        "!((nUnifiedSrcValid[iSrcOffset>>5] & iSrcOffsetMask) ) )\n"
-        "return FALSE;\n"
-
-"#ifdef USE_VEC\n"
-    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum] ||\n"
-        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*bandNum    ] & iSrcOffsetMask)) )\n"
-        "bHasValid = TRUE;\n"
-
-    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum+1] ||\n"
-        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*(1+bandNum)] & iSrcOffsetMask)) )\n"
-        "bHasValid = TRUE;\n"
-
-    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum+2] ||\n"
-        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*(2+bandNum)] & iSrcOffsetMask)) )\n"
-        "bHasValid = TRUE;\n"
-
-    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum+3] ||\n"
-        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*(3+bandNum)] & iSrcOffsetMask)) )\n"
-        "bHasValid = TRUE;\n"
-"#else\n"
-    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum] ||\n"
-        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*bandNum    ] & iSrcOffsetMask)) )\n"
-        "bHasValid = TRUE;\n"
-"#endif\n"
-
-    "if (!bHasValid)\n"
-        "return FALSE;\n"
-
-    "const sampler_t samp =  CLK_NORMALIZED_COORDS_FALSE |\n"
-                            "CLK_ADDRESS_CLAMP_TO_EDGE |\n"
-                            "CLK_FILTER_NEAREST;\n"
-
-"#ifdef USE_VEC\n"
-    "(*fReal) = read_imagef(srcReal, samp, iSrc);\n"
-    "if (useImag)\n"
-        "(*fImag) = read_imagef(srcImag, samp, iSrc);\n"
-"#else\n"
-    "(*fReal) = read_imagef(srcReal, samp, iSrc).x;\n"
-    "if (useImag)\n"
-        "(*fImag) = read_imagef(srcImag, samp, iSrc).x;\n"
-"#endif\n"
-
-    "if (useUnifiedSrcDensity) {\n"
-        "(*fDensity) = fUnifiedSrcDensity[iSrcOffset];\n"
-    "} else {\n"
-        "(*fDensity) = 1.0f;\n"
-        "return TRUE;\n"
-    "}\n"
-
-"#ifdef USE_VEC\n"
-    "return  (*fDensity).x > 0.0000001f || (*fDensity).y > 0.0000001f ||\n"
-            "(*fDensity).z > 0.0000001f || (*fDensity).w > 0.0000001f;\n"
-"#else\n"
-    "return (*fDensity) > 0.0000001f;\n"
-"#endif\n"
-"}\n"
-
-"int isValid(__global float *fUnifiedSrcDensity,\n"
-            "__global int *nUnifiedSrcValid,\n"
-            "float2 fSrcCoords )\n"
-"{\n"
-    "if (fSrcCoords.x < 0.0f || fSrcCoords.y < 0.0f)\n"
-        "return FALSE;\n"
-
-    "int iSrcX = (int) (fSrcCoords.x - 0.5f);\n"
-    "int iSrcY = (int) (fSrcCoords.y - 0.5f);\n"
-
-    "if( iSrcX < 0 || iSrcX >= iSrcWidth || iSrcY < 0 || iSrcY >= iSrcHeight )\n"
-        "return FALSE;\n"
-
-    "int iSrcOffset = iSrcX + iSrcY * iSrcWidth;\n"
-
-    "if (useUnifiedSrcDensity && fUnifiedSrcDensity[iSrcOffset] < 0.00001f)\n"
-        "return FALSE;\n"
-
-    "if (useUnifiedSrcValid &&\n"
-        "!(nUnifiedSrcValid[iSrcOffset>>5] & (0x01 << (iSrcOffset & 0x1f))) )\n"
-        "return FALSE;\n"
-
-    "return TRUE;\n"
-"}\n"
-
-"float2 getSrcCoords(__read_only image2d_t srcCoords)\n"
-"{\n"
-    // Find an appropriate place to sample the coordinates so we're still
-    // accurate after linear interpolation.
-    "int nDstX = get_global_id(0);\n"
-    "int nDstY = get_global_id(1);\n"
-    "float2  fDst = (float2)((0.5f * (float)iCoordMult + nDstX) /\n"
-                                "(float)((ceil((iDstWidth  - 1) / (float)iCoordMult) + 1) * iCoordMult), \n"
-                            "(0.5f * (float)iCoordMult + nDstY) /\n"
-                                "(float)((ceil((iDstHeight - 1) / (float)iCoordMult) + 1) * iCoordMult));\n"
-
-    // Check & return when the thread group overruns the image size
-    "if (nDstX >= iDstWidth || nDstY >= iDstHeight)\n"
-        "return (float2)(-99.0f, -99.0f);\n"
-
-    "const sampler_t samp =  CLK_NORMALIZED_COORDS_TRUE |\n"
-                            "CLK_ADDRESS_CLAMP_TO_EDGE |\n"
-                            "CLK_FILTER_LINEAR;\n"
-
-    "float4  fSrcCoords = read_imagef(srcCoords,samp,fDst);\n"
-
-    "return (float2)(fSrcCoords.x, fSrcCoords.y);\n"
-"}\n";
-
-    const char *kernBilinear =
-// ************************ Bilinear ************************
-"__kernel void resamp(__read_only image2d_t srcCoords,\n"
-                    "__read_only image2d_t srcReal,\n"
-                    "__read_only image2d_t srcImag,\n"
-                    "__global float *fUnifiedSrcDensity,\n"
-                    "__global int *nUnifiedSrcValid,\n"
-                    "__constant char *useBandSrcValid,\n"
-                    "__global int *nBandSrcValid,\n"
-                    "__global outType *dstReal,\n"
-                    "__global outType *dstImag,\n"
-                    "__constant float *fDstNoDataReal,\n"
-                    "__global float *dstDensity,\n"
-                    "__global int *nDstValid,\n"
-                    "const int bandNum)\n"
-"{\n"
-    "float2  fSrc = getSrcCoords(srcCoords);\n"
-    "if (!isValid(fUnifiedSrcDensity, nUnifiedSrcValid, fSrc))\n"
-        "return;\n"
-
-    "int     iSrcX = (int) floor(fSrc.x - 0.5f);\n"
-    "int     iSrcY = (int) floor(fSrc.y - 0.5f);\n"
-    "float   fRatioX = 1.5f - (fSrc.x - iSrcX);\n"
-    "float   fRatioY = 1.5f - (fSrc.y - iSrcY);\n"
-    "vecf    fReal, fImag, fDens;\n"
-    "vecf    fAccumulatorReal = 0.0f, fAccumulatorImag = 0.0f;\n"
-    "vecf    fAccumulatorDensity = 0.0f;\n"
-    "float   fAccumulatorDivisor = 0.0f;\n"
-
-    "if ( iSrcY >= 0 && iSrcY < iSrcHeight ) {\n"
-        "float fMult1 = fRatioX * fRatioY;\n"
-        "float fMult2 = (1.0f-fRatioX) * fRatioY;\n"
-
-		// Upper Left Pixel
-		"if ( iSrcX >= 0 && iSrcX < iSrcWidth\n"
-			 "&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-						"useBandSrcValid, nBandSrcValid, (int2)(iSrcX, iSrcY),\n"
-						"bandNum, &fDens, &fReal, &fImag))\n"
-		"{\n"
-			"fAccumulatorDivisor += fMult1;\n"
-			"fAccumulatorReal += fReal * fMult1;\n"
-			"fAccumulatorImag += fImag * fMult1;\n"
-			"fAccumulatorDensity += fDens * fMult1;\n"
-		"}\n"
-
-		// Upper Right Pixel
-		"if ( iSrcX+1 >= 0 && iSrcX+1 < iSrcWidth\n"
-			"&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-						"useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY),\n"
-						"bandNum, &fDens, &fReal, &fImag))\n"
-		"{\n"
-			"fAccumulatorDivisor += fMult2;\n"
-			"fAccumulatorReal += fReal * fMult2;\n"
-			"fAccumulatorImag += fImag * fMult2;\n"
-			"fAccumulatorDensity += fDens * fMult2;\n"
-		"}\n"
-    "}\n"
-
-    "if ( iSrcY+1 >= 0 && iSrcY+1 < iSrcHeight ) {\n"
-        "float fMult1 = fRatioX * (1.0f-fRatioY);\n"
-        "float fMult2 = (1.0f-fRatioX) * (1.0f-fRatioY);\n"
-
-        // Lower Left Pixel
-		"if ( iSrcX >= 0 && iSrcX < iSrcWidth\n"
-			"&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-						"useBandSrcValid, nBandSrcValid, (int2)(iSrcX, iSrcY+1),\n"
-						"bandNum, &fDens, &fReal, &fImag))\n"
-		"{\n"
-			"fAccumulatorDivisor += fMult1;\n"
-			"fAccumulatorReal += fReal * fMult1;\n"
-			"fAccumulatorImag += fImag * fMult1;\n"
-			"fAccumulatorDensity += fDens * fMult1;\n"
-		"}\n"
-
-		// Lower Right Pixel
-		"if ( iSrcX+1 >= 0 && iSrcX+1 < iSrcWidth\n"
-			"&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-						"useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY+1),\n"
-						"bandNum, &fDens, &fReal, &fImag))\n"
-		"{\n"
-			"fAccumulatorDivisor += fMult2;\n"
-			"fAccumulatorReal += fReal * fMult2;\n"
-			"fAccumulatorImag += fImag * fMult2;\n"
-			"fAccumulatorDensity += fDens * fMult2;\n"
-		"}\n"
-    "}\n"
-
-    // Compute and save final pixel
-    "if ( fAccumulatorDivisor < 0.00001f ) {\n"
-        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
-                "0.0f, 0.0f, 0.0f );\n"
-    "} else if ( fAccumulatorDivisor < 0.99999f || fAccumulatorDivisor > 1.00001f ) {\n"
-        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
-                "fAccumulatorDensity / fAccumulatorDivisor,\n"
-                "fAccumulatorReal / fAccumulatorDivisor,\n"
-"#if useImag != 0\n"
-                "fAccumulatorImag / fAccumulatorDivisor );\n"
-"#else\n"
-                "0.0f );\n"
-"#endif\n"
-    "} else {\n"
-        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
-                "fAccumulatorDensity, fAccumulatorReal, fAccumulatorImag );\n"
-    "}\n"
-"}\n";
-
-    const char *kernCubic =
-// ************************ Cubic ************************
-"vecf cubicConvolution(float dist1, float dist2, float dist3,\n"
-                        "vecf f0, vecf f1, vecf f2, vecf f3);\n"
-
-"vecf cubicConvolution(float dist1, float dist2, float dist3,\n"
-                       "vecf f0, vecf f1, vecf f2, vecf f3)\n"
-"{\n"
-    "return   (  -f0 +    f1  - f2 + f3) * dist3\n"
-           "+ (2.0f*(f0 - f1) + f2 - f3) * dist2\n"
-           "+ (  -f0          + f2     ) * dist1\n"
-           "+             f1;\n"
-"}\n"
-
-// ************************ Cubic ************************
-"__kernel void resamp(__read_only image2d_t srcCoords,\n"
-                     "__read_only image2d_t srcReal,\n"
-                     "__read_only image2d_t srcImag,\n"
-                     "__global float *fUnifiedSrcDensity,\n"
-                     "__global int *nUnifiedSrcValid,\n"
-                     "__constant char *useBandSrcValid,\n"
-                     "__global int *nBandSrcValid,\n"
-                     "__global outType *dstReal,\n"
-                     "__global outType *dstImag,\n"
-                     "__constant float *fDstNoDataReal,\n"
-                     "__global float *dstDensity,\n"
-                     "__global int *nDstValid,\n"
-                     "const int bandNum)\n"
-"{\n"
-    "int i;\n"
-    "float2  fSrc = getSrcCoords(srcCoords);\n"
-
-    "if (!isValid(fUnifiedSrcDensity, nUnifiedSrcValid, fSrc))\n"
-        "return;\n"
-
-    "int     iSrcX = (int) floor( fSrc.x - 0.5f );\n"
-    "int     iSrcY = (int) floor( fSrc.y - 0.5f );\n"
-    "float   fDeltaX = fSrc.x - 0.5f - (float)iSrcX;\n"
-    "float   fDeltaY = fSrc.y - 0.5f - (float)iSrcY;\n"
-    "float   fDeltaX2 = fDeltaX * fDeltaX;\n"
-    "float   fDeltaY2 = fDeltaY * fDeltaY;\n"
-    "float   fDeltaX3 = fDeltaX2 * fDeltaX;\n"
-    "float   fDeltaY3 = fDeltaY2 * fDeltaY;\n"
-    "vecf    afReal[4], afDens[4];\n"
-"#if useImag != 0\n"
-    "vecf    afImag[4];\n"
-"#else\n"
-    "vecf    fImag = 0.0f;\n"
-"#endif\n"
-
-    // Loop over rows
-    "for (i = -1; i < 3; ++i)\n"
-    "{\n"
-        "vecf    fReal1 = 0.0f, fReal2 = 0.0f, fReal3 = 0.0f, fReal4 = 0.0f;\n"
-        "vecf    fDens1 = 0.0f, fDens2 = 0.0f, fDens3 = 0.0f, fDens4 = 0.0f;\n"
-        "int hasPx;\n"
-"#if useImag != 0\n"
-        "vecf    fImag1 = 0.0f, fImag2 = 0.0f, fImag3 = 0.0f, fImag4 = 0.0f;\n"
-
-        //Get all the pixels for this row
-        "hasPx  = getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-                        "useBandSrcValid, nBandSrcValid, (int2)(iSrcX-1, iSrcY+i),\n"
-                        "bandNum, &fDens1, &fReal1, &fImag1);\n"
-
-        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-                        "useBandSrcValid, nBandSrcValid, (int2)(iSrcX  , iSrcY+i),\n"
-                        "bandNum, &fDens2, &fReal2, &fImag2);\n"
-
-        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-                        "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY+i),\n"
-                        "bandNum, &fDens3, &fReal3, &fImag3);\n"
-
-        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-                        "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+2, iSrcY+i),\n"
-                        "bandNum, &fDens4, &fReal4, &fImag4);\n"
-"#else\n"
-        //Get all the pixels for this row
-        "hasPx  = getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX-1, iSrcY+i),\n"
-                "bandNum, &fDens1, &fReal1, &fImag);\n"
-
-        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX  , iSrcY+i),\n"
-                "bandNum, &fDens2, &fReal2, &fImag);\n"
-
-        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY+i),\n"
-                "bandNum, &fDens3, &fReal3, &fImag);\n"
-
-        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
-                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+2, iSrcY+i),\n"
-                "bandNum, &fDens4, &fReal4, &fImag);\n"
-"#endif\n"
-
-        // Shortcut if no px
-        "if (!hasPx) {\n"
-            "afDens[i+1] = 0.0f;\n"
-            "afReal[i+1] = 0.0f;\n"
-"#if useImag != 0\n"
-            "afImag[i+1] = 0.0f;\n"
-"#endif\n"
-            "continue;\n"
-        "}\n"
-
-        // Process this row
-        "afDens[i+1] = cubicConvolution(fDeltaX, fDeltaX2, fDeltaX3, fDens1, fDens2, fDens3, fDens4);\n"
-        "afReal[i+1] = cubicConvolution(fDeltaX, fDeltaX2, fDeltaX3, fReal1, fReal2, fReal3, fReal4);\n"
-"#if useImag != 0\n"
-        "afImag[i+1] = cubicConvolution(fDeltaX, fDeltaX2, fDeltaX3, fImag1, fImag2, fImag3, fImag4);\n"
-"#endif\n"
-    "}\n"
-
-    // Compute and save final pixel
-    "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
-             "cubicConvolution(fDeltaY, fDeltaY2, fDeltaY3, afDens[0], afDens[1], afDens[2], afDens[3]),\n"
-             "cubicConvolution(fDeltaY, fDeltaY2, fDeltaY3, afReal[0], afReal[1], afReal[2], afReal[3]),\n"
-"#if useImag != 0\n"
-             "cubicConvolution(fDeltaY, fDeltaY2, fDeltaY3, afImag[0], afImag[1], afImag[2], afImag[3]) );\n"
-"#else\n"
-             "fImag );\n"
-"#endif\n"
-"}\n";
-
-    const char *kernResampler =
-// ************************ LanczosSinc ************************
-
-"float lanczosSinc( float fX, float fR );\n"
-"float bSpline( float x );\n"
-
-"float lanczosSinc( float fX, float fR )\n"
-"{\n"
-    "if ( fX > fR || fX < -fR)\n"
-        "return 0.0f;\n"
-    "if ( fX == 0.0f )\n"
-        "return 1.0f;\n"
-
-    "float fPIX = PI * fX;\n"
-    "return ( sin(fPIX) / fPIX ) * ( sin(fPIX / fR) * fR / fPIX );\n"
-"}\n"
-
-// ************************ Bicubic Spline ************************
-
-"float bSpline( float x )\n"
-"{\n"
-    "float xp2 = x + 2.0f;\n"
-    "float xp1 = x + 1.0f;\n"
-    "float xm1 = x - 1.0f;\n"
-    "float xp2c = xp2 * xp2 * xp2;\n"
-
-    "return (((xp2 > 0.0f)?((xp1 > 0.0f)?((x > 0.0f)?((xm1 > 0.0f)?\n"
-                                                     "-4.0f * xm1*xm1*xm1:0.0f) +\n"
-                                         "6.0f * x*x*x:0.0f) +\n"
-                           "-4.0f * xp1*xp1*xp1:0.0f) +\n"
-             "xp2c:0.0f) ) * 0.166666666666666666666f;\n"
-"}\n"
-
-// ************************ General Resampler ************************
-
-"__kernel void resamp(__read_only image2d_t srcCoords,\n"
-                     "__read_only image2d_t srcReal,\n"
-                     "__read_only image2d_t srcImag,\n"
-                     "__global float *fUnifiedSrcDensity,\n"
-                     "__global int *nUnifiedSrcValid,\n"
-                     "__constant char *useBandSrcValid,\n"
-                     "__global int *nBandSrcValid,\n"
-                     "__global outType *dstReal,\n"
-                     "__global outType *dstImag,\n"
-                     "__constant float *fDstNoDataReal,\n"
-                     "__global float *dstDensity,\n"
-                     "__global int *nDstValid,\n"
-                     "const int bandNum)\n"
-"{\n"
-    "float2  fSrc = getSrcCoords(srcCoords);\n"
-
-    "if (!isValid(fUnifiedSrcDensity, nUnifiedSrcValid, fSrc))\n"
-        "return;\n"
-
-    "int     iSrcX = floor( fSrc.x - 0.5f );\n"
-    "int     iSrcY = floor( fSrc.y - 0.5f );\n"
-    "float   fDeltaX = fSrc.x - 0.5f - (float)iSrcX;\n"
-    "float   fDeltaY = fSrc.y - 0.5f - (float)iSrcY;\n"
-
-    "vecf  fAccumulatorReal = 0.0f, fAccumulatorImag = 0.0f;\n"
-    "vecf  fAccumulatorDensity = 0.0f;\n"
-    "float fAccumulatorWeight = 0.0f;\n"
-    "int   i, j;\n"
-
-    // Loop over pixel rows in the kernel
-    "for ( j = nFiltInitY; j <= nYRadius; ++j )\n"
-    "{\n"
-        "float   fWeight1;\n"
-        "int2 iSrc = (int2)(0, iSrcY + j);\n"
-
-        // Skip sampling over edge of image
-        "if ( iSrc.y < 0 || iSrc.y >= iSrcHeight )\n"
-            "continue;\n"
-
-        // Select the resampling algorithm
-        "if ( doCubicSpline )\n"
-            // Calculate the Y weight
-            "fWeight1 = ( fYScale < 1.0f ) ?\n"
-                "bSpline(((float)j) * fYScale) * fYScale :\n"
-                "bSpline(((float)j) - fDeltaY);\n"
-        "else\n"
-            "fWeight1 = ( fYScale < 1.0f ) ?\n"
-                "lanczosSinc(j * fYScale, fYFilter) * fYScale :\n"
-                "lanczosSinc(j - fDeltaY, fYFilter);\n"
-
-        // Iterate over pixels in row
-        "for ( i = nFiltInitX; i <= nXRadius; ++i )\n"
-        "{\n"
-            "float fWeight2;\n"
-            "vecf fDensity = 0.0f, fReal, fImag;\n"
-            "iSrc.x = iSrcX + i;\n"
-
-            // Skip sampling at edge of image
-            // Skip sampling when invalid pixel
-            "if ( iSrc.x < 0 || iSrc.x >= iSrcWidth || \n"
-                  "!getPixel(srcReal, srcImag, fUnifiedSrcDensity,\n"
-                            "nUnifiedSrcValid, useBandSrcValid, nBandSrcValid,\n"
-                            "iSrc, bandNum, &fDensity, &fReal, &fImag) )\n"
-                "continue;\n"
-
-            // Choose among possible algorithms
-            "if ( doCubicSpline )\n"
-                // Calculate & save the X weight
-                "fWeight2 = fWeight1 * ((fXScale < 1.0f ) ?\n"
-                    "bSpline((float)i * fXScale) * fXScale :\n"
-                    "bSpline(fDeltaX - (float)i));\n"
-            "else\n"
-                // Calculate & save the X weight
-                "fWeight2 = fWeight1 * ((fXScale < 1.0f ) ?\n"
-                    "lanczosSinc(i * fXScale, fXFilter) * fXScale :\n"
-                    "lanczosSinc(i - fDeltaX, fXFilter));\n"
-
-            // Accumulate!
-            "fAccumulatorReal += fReal * fWeight2;\n"
-            "fAccumulatorImag += fImag * fWeight2;\n"
-            "fAccumulatorDensity += fDensity * fWeight2;\n"
-            "fAccumulatorWeight += fWeight2;\n"
-        "}\n"
-    "}\n"
-
-    "if ( fAccumulatorWeight < 0.000001f ) {\n"
-        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
-                 "0.0f, 0.0f, 0.0f);\n"
-    "} else if ( fAccumulatorWeight < 0.99999f || fAccumulatorWeight > 1.00001f ) {\n"
-        // Calculate the output taking into account weighting
-        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
-                 "fAccumulatorDensity / fAccumulatorWeight,\n"
-                 "fAccumulatorReal / fAccumulatorWeight,\n"
-"#if useImag != 0\n"
-                 "fAccumulatorImag / fAccumulatorWeight );\n"
-"#else\n"
-                 "0.0f );\n"
-"#endif\n"
-    "} else {\n"
-        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
-                 "fAccumulatorDensity, fAccumulatorReal, fAccumulatorImag);\n"
-    "}\n"
-"}\n";
-
-    //Defines based on image format
-    switch (warper->imageFormat) {
-        case CL_FLOAT:
-            dstMinVal = -FLT_MAX;
-            dstMaxVal = FLT_MAX;
-            outType = "float";
-            break;
-        case CL_SNORM_INT8:
-            dstMinVal = -128.0;
-            dstMaxVal = 127.0;
-            outType = "char";
-            break;
-        case CL_UNORM_INT8:
-            dstMinVal = 0.0;
-            dstMaxVal = 255.0;
-            outType = "uchar";
-            break;
-        case CL_SNORM_INT16:
-            dstMinVal = -32768.0;
-            dstMaxVal = 32767.0;
-            outType = "short";
-            break;
-        case CL_UNORM_INT16:
-            dstMinVal = 0.0;
-            dstMaxVal = 65535.0;
-            outType = "ushort";
-            break;
-    }
-
-    //Use vector format?
-    if (useVec) {
-        dUseVec = "-D USE_VEC";
-        dVecf = "float4";
-    }
-
-    //Assemble the kernel from parts. The compiler is unable to handle multiple
-    //kernels in one string with more than a few __constant modifiers each.
-    if (warper->resampAlg == OCL_Bilinear)
-        snprintf(progBuf, PROGBUF_SIZE, "%s\n%s", kernGenFuncs, kernBilinear);
-    else if (warper->resampAlg == OCL_Cubic)
-        snprintf(progBuf, PROGBUF_SIZE, "%s\n%s", kernGenFuncs, kernCubic);
-    else
-        snprintf(progBuf, PROGBUF_SIZE, "%s\n%s", kernGenFuncs, kernResampler);
-
-    //Actually make the program from assembled source
-    program = clCreateProgramWithSource(warper->context, 1, (const char**)&progBuf,
-                                        NULL, &err);
-    handleErrGoto(err, error_final);
-
-    //Assemble the compiler arg string for speed. All invariants should be defined here.
-    sprintf(buffer, "-cl-fast-relaxed-math -Werror -D FALSE=0 -D TRUE=1 "
-            "%s"
-            "-D iSrcWidth=%d -D iSrcHeight=%d -D iDstWidth=%d -D iDstHeight=%d "
-            "-D useUnifiedSrcDensity=%d -D useUnifiedSrcValid=%d "
-            "-D useDstDensity=%d -D useDstValid=%d -D useImag=%d "
-            "-D fXScale=%015.15lff -D fYScale=%015.15lff -D fXFilter=%015.15lff -D fYFilter=%015.15lff "
-            "-D nXRadius=%d -D nYRadius=%d -D nFiltInitX=%d -D nFiltInitY=%d "
-            "-D PI=%015.15lff -D outType=%s -D dstMinVal=%015.15lff -D dstMaxVal=%015.15lff "
-            "-D useDstNoDataReal=%d -D vecf=%s %s -D doCubicSpline=%d "
-            "-D useUseBandSrcValid=%d -D iCoordMult=%d ",
-            (warper->imageFormat == CL_FLOAT) ? "-D USE_CLAMP_TO_DST_FLOAT=1 " : "",
-            warper->srcWidth, warper->srcHeight, warper->dstWidth, warper->dstHeight,
-            warper->useUnifiedSrcDensity, warper->useUnifiedSrcValid,
-            warper->useDstDensity, warper->useDstValid, warper->imagWorkCL != NULL,
-            dfXScale, dfYScale, dfXFilter, dfYFilter,
-            nXRadius, nYRadius, nFiltInitX, nFiltInitY,
-            M_PI, outType, dstMinVal, dstMaxVal, warper->fDstNoDataRealCL != NULL,
-            dVecf, dUseVec, warper->resampAlg == OCL_CubicSpline,
-            warper->nBandSrcValidCL != NULL, warper->coordMult);
-
-    (*clErr) = err = clBuildProgram(program, 1, &(warper->dev), buffer, NULL, NULL);
-
-    //Detailed debugging info
-    if (err != CL_SUCCESS)
-    {
-        const char* pszStatus = "unknown_status";
-        err = clGetProgramBuildInfo(program, warper->dev, CL_PROGRAM_BUILD_LOG,
-                                    128000*sizeof(char), buffer, NULL);
-        handleErrGoto(err, error_free_program);
-
-        CPLError(CE_Failure, CPLE_AppDefined, "Error: Failed to build program executable!\nBuild Log:\n%s", buffer);
-
-        err = clGetProgramBuildInfo(program, warper->dev, CL_PROGRAM_BUILD_STATUS,
-                                    128000*sizeof(char), buffer, NULL);
-        handleErrGoto(err, error_free_program);
-
-        if(buffer[0] == CL_BUILD_NONE)
-            pszStatus = "CL_BUILD_NONE";
-        else if(buffer[0] == CL_BUILD_ERROR)
-            pszStatus = "CL_BUILD_ERROR";
-        else if(buffer[0] == CL_BUILD_SUCCESS)
-            pszStatus = "CL_BUILD_SUCCESS";
-        else if(buffer[0] == CL_BUILD_IN_PROGRESS)
-            pszStatus = "CL_BUILD_IN_PROGRESS";
-
-        CPLDebug("OpenCL", "Build Status: %s\nProgram Source:\n%s", pszStatus, progBuf);
-        goto error_free_program;
-    }
-
-    kernel = clCreateKernel(program, "resamp", &err);
-    handleErrGoto(err, error_free_program);
-
-    err = clReleaseProgram(program);
-    handleErrGoto(err, error_final);
-
-    CPLFree(buffer);
-    CPLFree(progBuf);
-    return kernel;
-
-error_free_program:
-    err = clReleaseProgram(program);
-
-error_final:
-    CPLFree(buffer);
-    CPLFree(progBuf);
-    return NULL;
-}
-
-/*
- Alloc & copy the coordinate data from host working memory to the device. The
- working memory should be a pinned, linear, array of floats. This allows us to
- allocate and copy all data in one step. The pointer to the device memory is
- saved and set as the appropriate argument number.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int set_coord_data (struct oclWarper *warper, cl_mem *xy)
-{
-    cl_int err = CL_SUCCESS;
-    cl_image_format imgFmt;
-
-    //Copy coord data to the device
-    imgFmt.image_channel_order = warper->xyChOrder;
-    imgFmt.image_channel_data_type = CL_FLOAT;
-    (*xy) = clCreateImage2D(warper->context,
-                            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imgFmt,
-                            (size_t) warper->xyWidth,
-                            (size_t) warper->xyHeight,
-                            (size_t) sizeof(float) * warper->xyChSize * warper->xyWidth,
-                            warper->xyWork, &err);
-    handleErr(err);
-
-    //Free the source memory, now that it's copied we don't need it
-    freeCLMem(warper->xyWorkCL, warper->xyWork);
-
-    //Set up argument
-    if (warper->kern1 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern1, 0, sizeof(cl_mem), xy));
-    }
-    if (warper->kern4 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern4, 0, sizeof(cl_mem), xy));
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Sets the unified density & valid data structures. These are optional structures
- from GDAL, and as such if they are NULL a small placeholder memory segment is
- defined. This is because the spec is unclear on if a NULL value can be passed
- as a kernel argument in place of memory. If it's not NULL, the data is copied
- from the working memory to the device memory. After that, we check if we are
- using the per-band validity mask, and set that as appropriate. At the end, the
- CL mem is passed as the kernel arguments.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int set_unified_data(struct oclWarper *warper,
-                        cl_mem *unifiedSrcDensityCL, cl_mem *unifiedSrcValidCL,
-                        float *unifiedSrcDensity, unsigned int *unifiedSrcValid,
-                        cl_mem *useBandSrcValidCL, cl_mem *nBandSrcValidCL)
-{
-    cl_int err = CL_SUCCESS;
-    size_t sz = warper->srcWidth * warper->srcHeight;
-    int useValid = warper->nBandSrcValidCL != NULL;
-    //32 bits in the mask
-    int validSz = sizeof(int) * ((31 + sz) >> 5);
-
-    //Copy unifiedSrcDensity if it exists
-    if (unifiedSrcDensity == NULL) {
-        //Alloc dummy device RAM
-        (*unifiedSrcDensityCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
-        handleErr(err);
-    } else {
-        //Alloc & copy all density data
-        (*unifiedSrcDensityCL) = clCreateBuffer(warper->context,
-                                                CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
-                                                sizeof(float) * sz, unifiedSrcDensity, &err);
-        handleErr(err);
-    }
-
-    //Copy unifiedSrcValid if it exists
-    if (unifiedSrcValid == NULL) {
-        //Alloc dummy device RAM
-        (*unifiedSrcValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
-        handleErr(err);
-    } else {
-        //Alloc & copy all validity data
-        (*unifiedSrcValidCL) = clCreateBuffer(warper->context,
-                                              CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
-                                              validSz, unifiedSrcValid, &err);
-        handleErr(err);
-    }
-
-    // Set the band validity usage
-    if(useValid) {
-        (*useBandSrcValidCL) = clCreateBuffer(warper->context,
-                                              CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
-                                              sizeof(char) * warper->numBands,
-                                              warper->useBandSrcValid, &err);
-        handleErr(err);
-    } else {
-        //Make a fake image so we don't have a NULL pointer
-        (*useBandSrcValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
-        handleErr(err);
-    }
-
-    //Do a more thorough check for validity
-    if (useValid) {
-        int i;
-        useValid = FALSE;
-        for (i = 0; i < warper->numBands; ++i)
-            if (warper->useBandSrcValid[i])
-                useValid = TRUE;
-    }
-
-    //And the validity mask if needed
-    if (useValid) {
-        (*nBandSrcValidCL) = clCreateBuffer(warper->context,
-                                            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
-                                            warper->numBands * validSz,
-                                            warper->nBandSrcValid, &err);
-        handleErr(err);
-    } else {
-        //Make a fake image so we don't have a NULL pointer
-        (*nBandSrcValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
-        handleErr(err);
-    }
-
-    //Set up arguments
-    if (warper->kern1 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern1, 3, sizeof(cl_mem), unifiedSrcDensityCL));
-        handleErr(err = clSetKernelArg(warper->kern1, 4, sizeof(cl_mem), unifiedSrcValidCL));
-        handleErr(err = clSetKernelArg(warper->kern1, 5, sizeof(cl_mem), useBandSrcValidCL));
-        handleErr(err = clSetKernelArg(warper->kern1, 6, sizeof(cl_mem), nBandSrcValidCL));
-    }
-    if (warper->kern4 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern4, 3, sizeof(cl_mem), unifiedSrcDensityCL));
-        handleErr(err = clSetKernelArg(warper->kern4, 4, sizeof(cl_mem), unifiedSrcValidCL));
-        handleErr(err = clSetKernelArg(warper->kern4, 5, sizeof(cl_mem), useBandSrcValidCL));
-        handleErr(err = clSetKernelArg(warper->kern4, 6, sizeof(cl_mem), nBandSrcValidCL));
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Here we set the per-band raster data. First priority is the real raster data,
- of course. Then, if applicable, we set the additional image channel. Once this
- data is copied to the device, it can be freed on the host, so that is done
- here. Finally the appropriate kernel arguments are set.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int set_src_rast_data (struct oclWarper *warper, int iNum, size_t sz,
-                          cl_channel_order chOrder, cl_mem *srcReal, cl_mem *srcImag)
-{
-    cl_image_format imgFmt;
-    cl_int err = CL_SUCCESS;
-    int useImagWork = warper->imagWork.v != NULL && warper->imagWork.v[iNum] != NULL;
-
-    //Set up image vars
-    imgFmt.image_channel_order = chOrder;
-    imgFmt.image_channel_data_type = warper->imageFormat;
-
-    //Create & copy the source image
-    (*srcReal) = clCreateImage2D(warper->context,
-                                 CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imgFmt,
-                                 (size_t) warper->srcWidth, (size_t) warper->srcHeight,
-                                 sz * warper->srcWidth, warper->realWork.v[iNum], &err);
-    handleErr(err);
-
-    //And the source image parts if needed
-    if (useImagWork) {
-        (*srcImag) = clCreateImage2D(warper->context,
-                                     CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imgFmt,
-                                     (size_t) warper->srcWidth, (size_t) warper->srcHeight,
-                                     sz * warper->srcWidth, warper->imagWork.v[iNum], &err);
-        handleErr(err);
-    } else {
-        //Make a fake image so we don't have a NULL pointer
-
-        char dummyImageData[16];
-        (*srcImag) = clCreateImage2D(warper->context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imgFmt,
-                                    1, 1, sz, dummyImageData, &err);
-
-        handleErr(err);
-    }
-
-    //Free the source memory, now that it's copied we don't need it
-    freeCLMem(warper->realWorkCL[iNum], warper->realWork.v[iNum]);
-    if (warper->imagWork.v != NULL) {
-        freeCLMem(warper->imagWorkCL[iNum], warper->imagWork.v[iNum]);
-    }
-
-    //Set up per-band arguments
-    if (warper->kern1 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern1, 1, sizeof(cl_mem), srcReal));
-        handleErr(err = clSetKernelArg(warper->kern1, 2, sizeof(cl_mem), srcImag));
-    }
-    if (warper->kern4 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern4, 1, sizeof(cl_mem), srcReal));
-        handleErr(err = clSetKernelArg(warper->kern4, 2, sizeof(cl_mem), srcImag));
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Set the destination data for the raster. Although it's the output, it still
- is copied to the device because some blending is done there. First the real
- data is allocated and copied, then the imag data is allocated and copied if
- needed. They are then set as the appropriate arguments to the kernel.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int set_dst_rast_data(struct oclWarper *warper, int iImg, size_t sz,
-                         cl_mem *dstReal, cl_mem *dstImag)
-{
-    cl_int err = CL_SUCCESS;
-    sz *= warper->dstWidth * warper->dstHeight;
-
-    //Copy the dst real data
-    (*dstReal) = clCreateBuffer(warper->context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
-                                sz, warper->dstRealWork.v[iImg], &err);
-    handleErr(err);
-
-    //Copy the dst imag data if exists
-    if (warper->dstImagWork.v != NULL && warper->dstImagWork.v[iImg] != NULL) {
-        (*dstImag) = clCreateBuffer(warper->context,
-                                    CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
-                                    sz, warper->dstImagWork.v[iImg], &err);
-        handleErr(err);
-    } else {
-        (*dstImag) = clCreateBuffer(warper->context, CL_MEM_READ_WRITE, 1, NULL, &err);
-        handleErr(err);
-    }
-
-    //Set up per-band arguments
-    if (warper->kern1 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern1, 7, sizeof(cl_mem), dstReal));
-        handleErr(err = clSetKernelArg(warper->kern1, 8, sizeof(cl_mem), dstImag));
-    }
-    if (warper->kern4 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern4, 7, sizeof(cl_mem), dstReal));
-        handleErr(err = clSetKernelArg(warper->kern4, 8, sizeof(cl_mem), dstImag));
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Read the final raster data back from the graphics card to working memory. This
- copies both the real memory and the imag memory if appropriate.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int get_dst_rast_data(struct oclWarper *warper, int iImg, size_t wordSz,
-                         cl_mem dstReal, cl_mem dstImag)
-{
-    cl_int err = CL_SUCCESS;
-    size_t sz = warper->dstWidth * warper->dstHeight * wordSz;
-
-    //Copy from dev into working memory
-    handleErr(err = clEnqueueReadBuffer(warper->queue, dstReal,
-                                        CL_FALSE, 0, sz, warper->dstRealWork.v[iImg],
-                                        0, NULL, NULL));
-
-    //If we are expecting the imag channel, then copy it back also
-    if (warper->dstImagWork.v != NULL && warper->dstImagWork.v[iImg] != NULL) {
-        handleErr(err = clEnqueueReadBuffer(warper->queue, dstImag,
-                                            CL_FALSE, 0, sz, warper->dstImagWork.v[iImg],
-                                            0, NULL, NULL));
-    }
-
-    //The copy requests were non-blocking, so we'll need to make sure they finish.
-    handleErr(err = clFinish(warper->queue));
-
-    return CL_SUCCESS;
-}
-
-/*
- Set the destination image density & validity mask on the device. This is used
- to blend the final output image with the existing buffer. This handles the
- unified structures that apply to all bands. After the buffers are created and
- copied, they are set as kernel arguments.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int set_dst_data(struct oclWarper *warper,
-                    cl_mem *dstDensityCL, cl_mem *dstValidCL, cl_mem *dstNoDataRealCL,
-                    float *dstDensity, unsigned int *dstValid, float *dstNoDataReal)
-{
-    cl_int err = CL_SUCCESS;
-    size_t sz = warper->dstWidth * warper->dstHeight;
-
-    //Copy the no-data value(s)
-    if (dstNoDataReal == NULL) {
-        (*dstNoDataRealCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
-        handleErr(err);
-    } else {
-        (*dstNoDataRealCL) = clCreateBuffer(warper->context,
-                                         CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
-                                         sizeof(float) * warper->numBands, dstNoDataReal, &err);
-        handleErr(err);
-    }
-
-    //Copy unifiedSrcDensity if it exists
-    if (dstDensity == NULL) {
-        (*dstDensityCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
-        handleErr(err);
-    } else {
-        (*dstDensityCL) = clCreateBuffer(warper->context,
-                                         CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
-                                         sizeof(float) * sz, dstDensity, &err);
-        handleErr(err);
-    }
-
-    //Copy unifiedSrcValid if it exists
-    if (dstValid == NULL) {
-        (*dstValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
-        handleErr(err);
-    } else {
-        (*dstValidCL) = clCreateBuffer(warper->context,
-                                       CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
-                                       sizeof(int) * ((31 + sz) >> 5), dstValid, &err);
-        handleErr(err);
-    }
-
-    //Set up arguments
-    if (warper->kern1 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern1,  9, sizeof(cl_mem), dstNoDataRealCL));
-        handleErr(err = clSetKernelArg(warper->kern1, 10, sizeof(cl_mem), dstDensityCL));
-        handleErr(err = clSetKernelArg(warper->kern1, 11, sizeof(cl_mem), dstValidCL));
-    }
-    if (warper->kern4 != NULL) {
-        handleErr(err = clSetKernelArg(warper->kern4,  9, sizeof(cl_mem), dstNoDataRealCL));
-        handleErr(err = clSetKernelArg(warper->kern4, 10, sizeof(cl_mem), dstDensityCL));
-        handleErr(err = clSetKernelArg(warper->kern4, 11, sizeof(cl_mem), dstValidCL));
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Go ahead and execute the kernel. This handles some housekeeping stuff like the
- run dimensions. When running in debug mode, it times the kernel call and prints
- the execution time.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int execute_kern(struct oclWarper *warper, cl_kernel kern, size_t loc_size)
-{
-    cl_int err = CL_SUCCESS;
-    cl_event ev;
-    size_t ceil_runs[2];
-    size_t group_size[2];
-#ifdef DEBUG_OPENCL
-    size_t start_time = 0;
-    size_t end_time;
-    char *vecTxt = "";
-#endif
-
-    // Use a likely X-dimension which is a power of 2
-    if (loc_size >= 512)
-        group_size[0] = 32;
-    else if (loc_size >= 64)
-        group_size[0] = 16;
-    else if (loc_size > 8)
-        group_size[0] = 8;
-    else
-        group_size[0] = 1;
-
-    if (group_size[0] > loc_size)
-        group_size[1] = group_size[0]/loc_size;
-    else
-        group_size[1] = 1;
-
-    //Round up num_runs to find the dim of the block of pixels we'll be processing
-    if(warper->dstWidth % group_size[0])
-        ceil_runs[0] = warper->dstWidth + group_size[0] - warper->dstWidth % group_size[0];
-    else
-        ceil_runs[0] = warper->dstWidth;
-
-    if(warper->dstHeight % group_size[1])
-        ceil_runs[1] = warper->dstHeight + group_size[1] - warper->dstHeight % group_size[1];
-    else
-        ceil_runs[1] = warper->dstHeight;
-
-#ifdef DEBUG_OPENCL
-    handleErr(err = clSetCommandQueueProperty(warper->queue, CL_QUEUE_PROFILING_ENABLE, CL_TRUE, NULL));
-#endif
-
-    // Run the calculation by enqueuing it and forcing the
-    // command queue to complete the task
-    handleErr(err = clEnqueueNDRangeKernel(warper->queue, kern, 2, NULL,
-                                           ceil_runs, group_size, 0, NULL, &ev));
-    handleErr(err = clFinish(warper->queue));
-
-#ifdef DEBUG_OPENCL
-    handleErr(err = clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_START,
-                                            sizeof(size_t), &start_time, NULL));
-    handleErr(err = clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_END,
-                                            sizeof(size_t), &end_time, NULL));
-    assert(end_time != 0);
-    assert(start_time != 0);
-    handleErr(err = clReleaseEvent(ev));
-    if (kern == warper->kern4)
-        vecTxt = "(vec)";
-
-    CPLDebug("OpenCL", "Kernel Time: %6s %10lu", vecTxt, (long int)((end_time-start_time)/100000));
-#endif
-    return CL_SUCCESS;
-}
-
-/*
- Copy data from a raw source to the warper's working memory. If the imag
- channel is expected, then the data will be de-interlaced into component blocks
- of memory.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int set_img_data(struct oclWarper *warper, void *srcImgData,
-                    unsigned int width, unsigned int height, int isSrc,
-                    unsigned int bandNum, void **dstRealImgs, void **dstImagImgs)
-{
-    unsigned int imgChSize = warper->imgChSize1;
-    unsigned int iSrcY, i;
-    unsigned int vecOff = 0;
-    unsigned int imgNum = bandNum;
-    void *dstReal = NULL;
-    void *dstImag = NULL;
-
-    // Handle vector if needed
-    if (warper->useVec && bandNum < warper->numBands - warper->numBands % 4) {
-        imgChSize = warper->imgChSize4;
-        vecOff = bandNum % 4;
-        imgNum = bandNum / 4;
-    } else if(warper->useVec) {
-        imgNum = bandNum / 4 + bandNum % 4;
-    }
-
-    // Set the images as needed
-    dstReal = dstRealImgs[imgNum];
-    if(dstImagImgs == NULL)
-        dstImag = NULL;
-    else
-        dstImag = dstImagImgs[imgNum];
-
-    // Set stuff for dst imgs
-    if (!isSrc) {
-        vecOff *= height * width;
-        imgChSize = 1;
-    }
-
-    // Copy values as needed
-    if (warper->imagWorkCL == NULL && !(warper->useVec && isSrc)) {
-        //Set memory size & location depending on the data type
-        //This is the ideal code path for speed
-        switch (warper->imageFormat) {
-            case CL_UNORM_INT8:
-            {
-                unsigned char *realDst = &(((unsigned char *)dstReal)[vecOff]);
-                memcpy(realDst, srcImgData, width*height*sizeof(unsigned char));
-                break;
-            }
-            case CL_SNORM_INT8:
-            {
-                char *realDst = &(((char *)dstReal)[vecOff]);
-                memcpy(realDst, srcImgData, width*height*sizeof(char));
-                break;
-            }
-            case CL_UNORM_INT16:
-            {
-                unsigned short *realDst = &(((unsigned short *)dstReal)[vecOff]);
-                memcpy(realDst, srcImgData, width*height*sizeof(unsigned short));
-                break;
-            }
-            case CL_SNORM_INT16:
-            {
-                short *realDst = &(((short *)dstReal)[vecOff]);
-                memcpy(realDst, srcImgData, width*height*sizeof(short));
-                break;
-            }
-            case CL_FLOAT:
-            {
-                float *realDst = &(((float *)dstReal)[vecOff]);
-                memcpy(realDst, srcImgData, width*height*sizeof(float));
-                break;
-            }
-        }
-    } else if (warper->imagWorkCL == NULL) {
-        //We need to space the values due to OpenCL implementation reasons
-        for( iSrcY = 0; iSrcY < height; iSrcY++ )
-        {
-            int pxOff = width*iSrcY;
-            int imgOff = imgChSize*pxOff + vecOff;
-            //Copy & deinterleave interleaved data
-            switch (warper->imageFormat) {
-                case CL_UNORM_INT8:
-                {
-                    unsigned char *realDst = &(((unsigned char *)dstReal)[imgOff]);
-                    unsigned char *dataSrc = &(((unsigned char *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i)
-                        realDst[imgChSize*i] = dataSrc[i];
-                }
-                    break;
-                case CL_SNORM_INT8:
-                {
-                    char *realDst = &(((char *)dstReal)[imgOff]);
-                    char *dataSrc = &(((char *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i)
-                        realDst[imgChSize*i] = dataSrc[i];
-                }
-                    break;
-                case CL_UNORM_INT16:
-                {
-                    unsigned short *realDst = &(((unsigned short *)dstReal)[imgOff]);
-                    unsigned short *dataSrc = &(((unsigned short *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i)
-                        realDst[imgChSize*i] = dataSrc[i];
-                }
-                    break;
-                case CL_SNORM_INT16:
-                {
-                    short *realDst = &(((short *)dstReal)[imgOff]);
-                    short *dataSrc = &(((short *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i)
-                        realDst[imgChSize*i] = dataSrc[i];
-                }
-                    break;
-                case CL_FLOAT:
-                {
-                    float *realDst = &(((float *)dstReal)[imgOff]);
-                    float *dataSrc = &(((float *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i)
-                        realDst[imgChSize*i] = dataSrc[i];
-                }
-                    break;
-            }
-        }
-    } else {
-        //Copy, deinterleave, & space interleaved data
-        for( iSrcY = 0; iSrcY < height; iSrcY++ )
-        {
-            int pxOff = width*iSrcY;
-            int imgOff = imgChSize*pxOff + vecOff;
-            //Copy & deinterleave interleaved data
-            switch (warper->imageFormat) {
-                case CL_FLOAT:
-                {
-                    float *realDst = &(((float *)dstReal)[imgOff]);
-                    float *imagDst = &(((float *)dstImag)[imgOff]);
-                    float *dataSrc = &(((float *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i) {
-                        realDst[imgChSize*i] = dataSrc[i*2  ];
-                        imagDst[imgChSize*i] = dataSrc[i*2+1];
-                    }
-                }
-                    break;
-                case CL_SNORM_INT8:
-                {
-                    char *realDst = &(((char *)dstReal)[imgOff]);
-                    char *imagDst = &(((char *)dstImag)[imgOff]);
-                    char *dataSrc = &(((char *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i) {
-                        realDst[imgChSize*i] = dataSrc[i*2  ];
-                        imagDst[imgChSize*i] = dataSrc[i*2+1];
-                    }
-                }
-                    break;
-                case CL_UNORM_INT8:
-                {
-                    unsigned char *realDst = &(((unsigned char *)dstReal)[imgOff]);
-                    unsigned char *imagDst = &(((unsigned char *)dstImag)[imgOff]);
-                    unsigned char *dataSrc = &(((unsigned char *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i) {
-                        realDst[imgChSize*i] = dataSrc[i*2  ];
-                        imagDst[imgChSize*i] = dataSrc[i*2+1];
-                    }
-                }
-                    break;
-                case CL_SNORM_INT16:
-                {
-                    short *realDst = &(((short *)dstReal)[imgOff]);
-                    short *imagDst = &(((short *)dstImag)[imgOff]);
-                    short *dataSrc = &(((short *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i) {
-                        realDst[imgChSize*i] = dataSrc[i*2  ];
-                        imagDst[imgChSize*i] = dataSrc[i*2+1];
-                    }
-                }
-                    break;
-                case CL_UNORM_INT16:
-                {
-                    unsigned short *realDst = &(((unsigned short *)dstReal)[imgOff]);
-                    unsigned short *imagDst = &(((unsigned short *)dstImag)[imgOff]);
-                    unsigned short *dataSrc = &(((unsigned short *)srcImgData)[pxOff]);
-                    for (i = 0; i < width; ++i) {
-                        realDst[imgChSize*i] = dataSrc[i*2  ];
-                        imagDst[imgChSize*i] = dataSrc[i*2+1];
-                    }
-                }
-                    break;
-            }
-        }
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Creates the struct which inits & contains the OpenCL context & environment.
- Inits wired(?) space to buffer the image in host RAM. Chooses the OpenCL
- device, perhaps the user can choose it later? This would also choose the
- appropriate OpenCL image format (R, RG, RGBA, or multiples thereof). Space
- for metadata can be allocated as required, though.
-
- Supported image formats are:
- CL_FLOAT, CL_SNORM_INT8, CL_UNORM_INT8, CL_SNORM_INT16, CL_UNORM_INT16
- 32-bit int formats won't keep precision when converted to floats internally
- and doubles are generally not supported on the GPU image formats.
- */
-struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
-                                                 int dstWidth, int dstHeight,
-                                                 cl_channel_type imageFormat,
-                                                 int numBands, int coordMult,
-                                                 int useImag, int useBandSrcValid,
-                                                 float *fDstDensity,
-                                                 double *dfDstNoDataReal,
-                                                 OCLResampAlg resampAlg, cl_int *clErr)
-{
-    struct oclWarper *warper;
-    int i;
-    size_t maxWidth = 0, maxHeight = 0;
-    cl_int err = CL_SUCCESS;
-    size_t fmtSize, sz;
-    cl_device_id device;
-    cl_bool bool_flag;
-    OCLVendor eCLVendor = VENDOR_OTHER;
-
-    // Do we have a suitable OpenCL device?
-    device = get_device(&eCLVendor);
-    if( device == NULL )
-        return NULL;
-
-    err = clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT,
-                          sizeof(cl_bool), &bool_flag, &sz);
-    if( err != CL_SUCCESS || !bool_flag )
-    {
-        CPLDebug( "OpenCL", "No image support on selected device." );
-        return NULL;
-    }
-
-    // Set up warper environment.
-    warper = (struct oclWarper *)CPLCalloc(1, sizeof(struct oclWarper));
-
-    warper->eCLVendor = eCLVendor;
-
-    //Init passed vars
-    warper->srcWidth = srcWidth;
-    warper->srcHeight = srcHeight;
-    warper->dstWidth = dstWidth;
-    warper->dstHeight = dstHeight;
-
-    warper->coordMult = coordMult;
-    warper->numBands = numBands;
-    warper->imageFormat = imageFormat;
-    warper->resampAlg = resampAlg;
-
-    warper->useUnifiedSrcDensity = FALSE;
-    warper->useUnifiedSrcValid = FALSE;
-    warper->useDstDensity = FALSE;
-    warper->useDstValid = FALSE;
-
-    warper->imagWorkCL = NULL;
-    warper->dstImagWorkCL = NULL;
-    warper->useBandSrcValidCL = NULL;
-    warper->useBandSrcValid = NULL;
-    warper->nBandSrcValidCL = NULL;
-    warper->nBandSrcValid = NULL;
-    warper->fDstNoDataRealCL = NULL;
-    warper->fDstNoDataReal = NULL;
-    warper->kern1 = NULL;
-    warper->kern4 = NULL;
-
-    warper->dev = device;
-
-    warper->context = clCreateContext(0, 1, &(warper->dev), NULL, NULL, &err);
-    handleErrGoto(err, error_label);
-    warper->queue = clCreateCommandQueue(warper->context, warper->dev, 0, &err);
-    handleErrGoto(err, error_label);
-
-    //Ensure that we hand handle imagery of these dimensions
-    err = clGetDeviceInfo(warper->dev, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &maxWidth, &sz);
-    handleErrGoto(err, error_label);
-    err = clGetDeviceInfo(warper->dev, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &maxHeight, &sz);
-    handleErrGoto(err, error_label);
-    if (maxWidth < srcWidth || maxHeight < srcHeight) {
-        err = CL_INVALID_IMAGE_SIZE;
-        handleErrGoto(err, error_label);
-    }
-
-    // Split bands into sets of four when possible
-    // Cubic runs slower as vector, so don't use it (probably register pressure)
-    // Feel free to do more testing and come up with more precise case statements
-    if(numBands < 4 || resampAlg == OCL_Cubic) {
-        warper->numImages = numBands;
-        warper->useVec = FALSE;
-    } else {
-        warper->numImages = numBands/4 + numBands % 4;
-        warper->useVec = TRUE;
-    }
-
-    //Make the pointer space for the real images
-    warper->realWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
-    warper->dstRealWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
-
-    //Make space for the per-channel Imag data (if exists)
-    if (useImag) {
-        warper->imagWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
-        warper->dstImagWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
-    }
-
-    //Make space for the per-band BandSrcValid data (if exists)
-    if (useBandSrcValid) {
-        //32 bits in the mask
-        size_t sz = warper->numBands * ((31 + warper->srcWidth * warper->srcHeight) >> 5);
-
-        //Allocate some space for the validity of the validity mask
-        err = alloc_pinned_mem(warper, 0, warper->numBands*sizeof(char),
-                               (void **)&(warper->useBandSrcValid),
-                               &(warper->useBandSrcValidCL));
-        handleErrGoto(err, error_label);
-
-        for (i = 0; i < warper->numBands; ++i)
-            warper->useBandSrcValid[i] = FALSE;
-
-        // Allocate one array for all the band validity masks.
-        // Remember that the masks don't use much memory (they're bitwise).
-        err = alloc_pinned_mem(warper, 0, sz * sizeof(int),
-                               (void **)&(warper->nBandSrcValid),
-                               &(warper->nBandSrcValidCL));
-        handleErrGoto(err, error_label);
-    }
-
-    //Make space for the per-band
-    if (dfDstNoDataReal != NULL) {
-        alloc_pinned_mem(warper, 0, warper->numBands,
-                         (void **)&(warper->fDstNoDataReal), &(warper->fDstNoDataRealCL));
-
-        //Copy over values
-        for (i = 0; i < warper->numBands; ++i)
-            warper->fDstNoDataReal[i] = dfDstNoDataReal[i];
-    }
-
-    //Alloc working host image memory
-    //We'll be copying into these buffers soon
-    switch (imageFormat) {
-      case CL_FLOAT:
-        err = alloc_working_arr(warper, sizeof(float *), sizeof(float), &fmtSize);
-        break;
-      case CL_SNORM_INT8:
-        err = alloc_working_arr(warper, sizeof(char *), sizeof(char), &fmtSize);
-        break;
-      case CL_UNORM_INT8:
-        err = alloc_working_arr(warper, sizeof(unsigned char *), sizeof(unsigned char), &fmtSize);
-        break;
-      case CL_SNORM_INT16:
-        err = alloc_working_arr(warper, sizeof(short *), sizeof(short), &fmtSize);
-        break;
-      case CL_UNORM_INT16:
-        err = alloc_working_arr(warper, sizeof(unsigned short *), sizeof(unsigned short), &fmtSize);
-        break;
-    }
-    handleErrGoto(err, error_label);
-
-    // Find a good & compatible image channel order for the Lat/Long array.
-    err = set_supported_formats(warper, 2,
-                                &(warper->xyChOrder), &(warper->xyChSize),
-                                CL_FLOAT);
-    handleErrGoto(err, error_label);
-
-    //Set coordinate image dimensions
-    warper->xyWidth  = ceil(((float)warper->dstWidth  + (float)warper->coordMult-1)/(float)warper->coordMult);
-    warper->xyHeight = ceil(((float)warper->dstHeight + (float)warper->coordMult-1)/(float)warper->coordMult);
-
-    //Alloc coord memory
-    sz = sizeof(float) * warper->xyChSize * warper->xyWidth * warper->xyHeight;
-    err = alloc_pinned_mem(warper, 0, sz, (void **)&(warper->xyWork),
-                           &(warper->xyWorkCL));
-    handleErrGoto(err, error_label);
-
-    //Ensure everything is finished allocating, copying, & mapping
-    err = clFinish(warper->queue);
-    handleErrGoto(err, error_label);
-
-    (*clErr) = CL_SUCCESS;
-    return warper;
-
-error_label:
-    GDALWarpKernelOpenCL_deleteEnv(warper);
-    return NULL;
-}
-
-/*
- Copy the validity mask for an image band to the warper.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int GDALWarpKernelOpenCL_setSrcValid(struct oclWarper *warper,
-                                        int *bandSrcValid, int bandNum)
-{
-    //32 bits in the mask
-    int stride = (31 + warper->srcWidth * warper->srcHeight) >> 5;
-
-    //Copy bandSrcValid
-    assert(warper->nBandSrcValid != NULL);
-    memcpy(&(warper->nBandSrcValid[bandNum*stride]), bandSrcValid, sizeof(int) * stride);
-    warper->useBandSrcValid[bandNum] = TRUE;
-
-    return CL_SUCCESS;
-}
-
-/*
- Sets the source image real & imag into the host memory so that it is
- permuted (ex. RGBA) for better graphics card access.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int GDALWarpKernelOpenCL_setSrcImg(struct oclWarper *warper, void *imgData,
-                                      int bandNum)
-{
-    void **imagWorkPtr = NULL;
-
-    if (warper->imagWorkCL != NULL)
-        imagWorkPtr = warper->imagWork.v;
-
-    return set_img_data(warper, imgData, warper->srcWidth, warper->srcHeight,
-                        TRUE, bandNum, warper->realWork.v, imagWorkPtr);
-}
-
-/*
- Sets the destination image real & imag into the host memory so that it is
- permuted (ex. RGBA) for better graphics card access.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int GDALWarpKernelOpenCL_setDstImg(struct oclWarper *warper, void *imgData,
-                                      int bandNum)
-{
-    void **dstImagWorkPtr = NULL;
-
-    if (warper->dstImagWorkCL != NULL)
-        dstImagWorkPtr = warper->dstImagWork.v;
-
-    return set_img_data(warper, imgData, warper->dstWidth, warper->dstHeight,
-                        FALSE, bandNum, warper->dstRealWork.v, dstImagWorkPtr);
-}
-
-/*
- Inputs the source coordinates for a row of the destination pixels. Invalid
- coordinates are set as -99.0, which should be out of the image bounds. Sets
- the coordinates as ready to be used in OpenCL image memory: interleaved and
- minus the offset. By using image memory, we can use a smaller texture for
- coordinates and use OpenCL's built-in interpolation to save memory.
-
- What it does: generates a smaller matrix of X/Y coordinate transformation
- values from an original matrix. When bilinearly sampled in the GPU hardware,
- the generated values are as close as possible to the original matrix.
-
- Complication: matrices have arbitrary dimensions and the sub-sampling factor
- is an arbitrary integer greater than zero. Getting the edge cases right is
- difficult.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int GDALWarpKernelOpenCL_setCoordRow(struct oclWarper *warper,
-                                        double *rowSrcX, double *rowSrcY,
-                                        double srcXOff, double srcYOff,
-                                        int *success, int rowNum)
-{
-    int coordMult = warper->coordMult;
-    int width = warper->dstWidth;
-    int height = warper->dstHeight;
-    int xyWidth = warper->xyWidth;
-    int i;
-    int xyChSize = warper->xyChSize;
-    float *xyPtr, *xyPrevPtr = NULL;
-    int lastRow = rowNum == height - 1;
-    double dstHeightMod = 1.0, dstWidthMod = 1.0;
-
-    //Return if we're at an off row
-    if(!lastRow && rowNum % coordMult != 0)
-        return CL_SUCCESS;
-
-    //Standard row, adjusted for the skipped rows
-    xyPtr = &(warper->xyWork[xyWidth * xyChSize * rowNum / coordMult]);
-
-    //Find our row
-    if(lastRow){
-        //Setup for the final row
-        xyPtr     = &(warper->xyWork[xyWidth * xyChSize * (warper->xyHeight - 1)]);
-        xyPrevPtr = &(warper->xyWork[xyWidth * xyChSize * (warper->xyHeight - 2)]);
-
-        if((height-1) % coordMult)
-            dstHeightMod = (double)coordMult / (double)((height-1) % coordMult);
-    }
-
-    //Copy selected coordinates
-    for (i = 0; i < width; i += coordMult) {
-        if (success[i]) {
-            xyPtr[0] = rowSrcX[i] - srcXOff;
-            xyPtr[1] = rowSrcY[i] - srcYOff;
-
-            if(lastRow) {
-                //Adjust bottom row so interpolator returns correct value
-                xyPtr[0] = dstHeightMod * (xyPtr[0] - xyPrevPtr[0]) + xyPrevPtr[0];
-                xyPtr[1] = dstHeightMod * (xyPtr[1] - xyPrevPtr[1]) + xyPrevPtr[1];
-            }
-        } else {
-            xyPtr[0] = -99.0f;
-            xyPtr[1] = -99.0f;
-        }
-
-        xyPtr += xyChSize;
-        xyPrevPtr += xyChSize;
-    }
-
-    //Copy remaining coordinate
-    if((width-1) % coordMult){
-        dstWidthMod = (double)coordMult / (double)((width-1) % coordMult);
-        xyPtr -= xyChSize;
-        xyPrevPtr -= xyChSize;
-    } else {
-        xyPtr -= xyChSize*2;
-        xyPrevPtr -= xyChSize*2;
-    }
-
-    if(lastRow) {
-        double origX = rowSrcX[width-1] - srcXOff;
-        double origY = rowSrcY[width-1] - srcYOff;
-        double a = 1.0, b = 1.0;
-
-        // Calculate the needed x/y values using an equation from the OpenCL Spec
-        // section 8.2, solving for Ti1j1
-        if((width -1) % coordMult)
-            a = ((width -1) % coordMult)/(double)coordMult;
-
-        if((height-1) % coordMult)
-            b = ((height-1) % coordMult)/(double)coordMult;
-
-        xyPtr[xyChSize  ] = (((1.0 - a) * (1.0 - b) * xyPrevPtr[0]
-                              + a * (1.0 - b) * xyPrevPtr[xyChSize]
-                              + (1.0 - a) * b * xyPtr[0]) - origX)/(-a * b);
-
-        xyPtr[xyChSize+1] = (((1.0 - a) * (1.0 - b) * xyPrevPtr[1]
-                              + a * (1.0 - b) * xyPrevPtr[xyChSize+1]
-                              + (1.0 - a) * b * xyPtr[1]) - origY)/(-a * b);
-    } else {
-        //Adjust last coordinate so interpolator returns correct value
-        xyPtr[xyChSize  ] = dstWidthMod * (rowSrcX[width-1] - srcXOff - xyPtr[0]) + xyPtr[0];
-        xyPtr[xyChSize+1] = dstWidthMod * (rowSrcY[width-1] - srcYOff - xyPtr[1]) + xyPtr[1];
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Copies all data to the device RAM, frees the host RAM, runs the
- appropriate resampling kernel, mallocs output space, & copies the data
- back from the device RAM for each band. Also check to make sure that
- setRow*() was called the appropriate number of times to init all image
- data.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
-                                      float *unifiedSrcDensity,
-                                      unsigned int *unifiedSrcValid,
-                                      float *dstDensity,
-                                      unsigned int *dstValid,
-                                      double dfXScale, double dfYScale,
-                                      double dfXFilter, double dfYFilter,
-                                      int nXRadius, int nYRadius,
-                                      int nFiltInitX, int nFiltInitY)
-{
-    int i, nextBandNum = 0, chSize = 1;
-	cl_int err = CL_SUCCESS;
-    cl_mem xy, unifiedSrcDensityCL, unifiedSrcValidCL;
-    cl_mem dstDensityCL, dstValidCL, dstNoDataRealCL;
-    cl_mem useBandSrcValidCL, nBandSrcValidCL;
-	size_t groupSize, wordSize;
-    cl_kernel kern = NULL;
-    cl_channel_order chOrder;
-
-    warper->useUnifiedSrcDensity = unifiedSrcDensity != NULL;
-    warper->useUnifiedSrcValid = unifiedSrcValid != NULL;
-
-    //Check the word size
-    switch (warper->imageFormat) {
-        case CL_FLOAT:
-            wordSize = sizeof(float);
-            break;
-        case CL_SNORM_INT8:
-            wordSize = sizeof(char);
-            break;
-        case CL_UNORM_INT8:
-            wordSize = sizeof(unsigned char);
-            break;
-        case CL_SNORM_INT16:
-            wordSize = sizeof(short);
-            break;
-        case CL_UNORM_INT16:
-            wordSize = sizeof(unsigned short);
-            break;
-    }
-
-    //Compile the kernel; the invariants are being compiled into the code
-    if (!warper->useVec || warper->numBands % 4) {
-        warper->kern1 = get_kernel(warper, FALSE,
-                                   dfXScale, dfYScale, dfXFilter, dfYFilter,
-                                   nXRadius, nYRadius, nFiltInitX, nFiltInitY, &err);
-        handleErr(err);
-    }
-    if (warper->useVec){
-        warper->kern4 = get_kernel(warper, TRUE,
-                                   dfXScale, dfYScale, dfXFilter, dfYFilter,
-                                   nXRadius, nYRadius, nFiltInitX, nFiltInitY, &err);
-        handleErr(err);
-    }
-
-    //Copy coord data to the device
-    handleErr(err = set_coord_data(warper, &xy));
-
-    //Copy unified density & valid data
-    handleErr(err = set_unified_data(warper, &unifiedSrcDensityCL, &unifiedSrcValidCL,
-                                     unifiedSrcDensity, unifiedSrcValid,
-                                     &useBandSrcValidCL, &nBandSrcValidCL));
-
-    //Copy output density & valid data
-    handleErr(set_dst_data(warper, &dstDensityCL, &dstValidCL, &dstNoDataRealCL,
-                           dstDensity, dstValid, warper->fDstNoDataReal));
-
-    //What's the recommended group size?
-    if (warper->useVec) {
-        // Start with the vector kernel
-        handleErr(clGetKernelWorkGroupInfo(warper->kern4, warper->dev,
-                                           CL_KERNEL_WORK_GROUP_SIZE,
-                                           sizeof(size_t), &groupSize, NULL));
-        kern = warper->kern4;
-        chSize = warper->imgChSize4;
-        chOrder = warper->imgChOrder4;
-    } else {
-        // We're only using the float kernel
-        handleErr(clGetKernelWorkGroupInfo(warper->kern1, warper->dev,
-                                           CL_KERNEL_WORK_GROUP_SIZE,
-                                           sizeof(size_t), &groupSize, NULL));
-        kern = warper->kern1;
-        chSize = warper->imgChSize1;
-        chOrder = warper->imgChOrder1;
-    }
-
-    //Loop over each image
-    for (i = 0; i < warper->numImages; ++i)
-    {
-        cl_mem srcImag, srcReal;
-        cl_mem dstReal, dstImag;
-        int bandNum = nextBandNum;
-
-        //Switch kernels if needed
-        if (warper->useVec && nextBandNum < warper->numBands - warper->numBands % 4) {
-            nextBandNum += 4;
-        } else {
-            if (kern == warper->kern4) {
-                handleErr(clGetKernelWorkGroupInfo(warper->kern1, warper->dev,
-                                                   CL_KERNEL_WORK_GROUP_SIZE,
-                                                   sizeof(size_t), &groupSize, NULL));
-                kern = warper->kern1;
-                chSize = warper->imgChSize1;
-                chOrder = warper->imgChOrder1;
-            }
-            ++nextBandNum;
-        }
-
-        //Create & copy the source image
-        handleErr(err = set_src_rast_data(warper, i, chSize*wordSize, chOrder,
-                                          &srcReal, &srcImag));
-
-        //Create & copy the output image
-        if (kern == warper->kern1) {
-            handleErr(err = set_dst_rast_data(warper, i, wordSize, &dstReal, &dstImag));
-        } else {
-            handleErr(err = set_dst_rast_data(warper, i, wordSize*4, &dstReal, &dstImag));
-        }
-
-        //Set the bandNum
-        handleErr(err = clSetKernelArg(kern, 12, sizeof(int), &bandNum));
-
-        //Run the kernel
-        handleErr(err = execute_kern(warper, kern, groupSize));
-
-        //Free loop CL mem
-        handleErr(err = clReleaseMemObject(srcReal));
-        handleErr(err = clReleaseMemObject(srcImag));
-
-        //Copy the back output results
-        if (kern == warper->kern1) {
-            handleErr(err = get_dst_rast_data(warper, i, wordSize, dstReal, dstImag));
-        } else {
-            handleErr(err = get_dst_rast_data(warper, i, wordSize*4, dstReal, dstImag));
-        }
-
-        //Free remaining CL mem
-        handleErr(err = clReleaseMemObject(dstReal));
-        handleErr(err = clReleaseMemObject(dstImag));
-    }
-
-    //Free remaining CL mem
-    handleErr(err = clReleaseMemObject(xy));
-    handleErr(err = clReleaseMemObject(unifiedSrcDensityCL));
-    handleErr(err = clReleaseMemObject(unifiedSrcValidCL));
-    handleErr(err = clReleaseMemObject(useBandSrcValidCL));
-    handleErr(err = clReleaseMemObject(nBandSrcValidCL));
-    handleErr(err = clReleaseMemObject(dstDensityCL));
-    handleErr(err = clReleaseMemObject(dstValidCL));
-    handleErr(err = clReleaseMemObject(dstNoDataRealCL));
-
-    return CL_SUCCESS;
-}
-
-/*
- Sets pointers to the floating point data in the warper. The pointers
- are internal to the warper structure, so don't free() them. If the imag
- channel is in use, it will receive a pointer. Otherwise it'll be set to NULL.
- These are pointers to floating point data, so the caller will need to
- manipulate the output as appropriate before saving the data.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int GDALWarpKernelOpenCL_getRow(struct oclWarper *warper,
-                                   void **rowReal, void **rowImag,
-                                   int rowNum, int bandNum)
-{
-    int memOff = rowNum * warper->dstWidth;
-    int imgNum = bandNum;
-
-    if (warper->useVec && bandNum < warper->numBands - warper->numBands % 4) {
-        memOff += warper->dstWidth * warper->dstHeight * (bandNum % 4);
-        imgNum = bandNum / 4;
-    } else if(warper->useVec) {
-        imgNum = bandNum / 4 + bandNum % 4;
-    }
-
-    //Return pointers into the warper's data
-    switch (warper->imageFormat) {
-        case CL_FLOAT:
-            (*rowReal) = &(warper->dstRealWork.f[imgNum][memOff]);
-            break;
-        case CL_SNORM_INT8:
-            (*rowReal) = &(warper->dstRealWork.c[imgNum][memOff]);
-            break;
-        case CL_UNORM_INT8:
-            (*rowReal) = &(warper->dstRealWork.uc[imgNum][memOff]);
-            break;
-        case CL_SNORM_INT16:
-            (*rowReal) = &(warper->dstRealWork.s[imgNum][memOff]);
-            break;
-        case CL_UNORM_INT16:
-            (*rowReal) = &(warper->dstRealWork.us[imgNum][memOff]);
-            break;
-    }
-
-    if (warper->dstImagWorkCL == NULL) {
-        (*rowImag) = NULL;
-    } else {
-        switch (warper->imageFormat) {
-            case CL_FLOAT:
-                (*rowImag) = &(warper->dstImagWork.f[imgNum][memOff]);
-                break;
-            case CL_SNORM_INT8:
-                (*rowImag) = &(warper->dstImagWork.c[imgNum][memOff]);
-                break;
-            case CL_UNORM_INT8:
-                (*rowImag) = &(warper->dstImagWork.uc[imgNum][memOff]);
-                break;
-            case CL_SNORM_INT16:
-                (*rowImag) = &(warper->dstImagWork.s[imgNum][memOff]);
-                break;
-            case CL_UNORM_INT16:
-                (*rowImag) = &(warper->dstImagWork.us[imgNum][memOff]);
-                break;
-        }
-    }
-
-    return CL_SUCCESS;
-}
-
-/*
- Free the OpenCL warper environment. It should check everything for NULL, so
- be sure to mark free()ed pointers as NULL or it'll be double free()ed.
-
- Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
- */
-cl_int GDALWarpKernelOpenCL_deleteEnv(struct oclWarper *warper)
-{
-    int i;
-	cl_int err = CL_SUCCESS;
-
-    for (i = 0; i < warper->numImages; ++i) {
-        // Run free!!
-        void* dummy = NULL;
-        if( warper->realWork.v )
-            freeCLMem(warper->realWorkCL[i], warper->realWork.v[i]);
-        else
-            freeCLMem(warper->realWorkCL[i], dummy);
-        if( warper->realWork.v )
-            freeCLMem(warper->dstRealWorkCL[i], warper->dstRealWork.v[i]);
-        else
-            freeCLMem(warper->dstRealWorkCL[i], dummy);
-
-        //(As applicable)
-        if(warper->imagWorkCL != NULL && warper->imagWork.v != NULL && warper->imagWork.v[i] != NULL) {
-            freeCLMem(warper->imagWorkCL[i], warper->imagWork.v[i]);
-        }
-        if(warper->dstImagWorkCL != NULL && warper->dstImagWork.v != NULL && warper->dstImagWork.v[i] != NULL) {
-            freeCLMem(warper->dstImagWorkCL[i], warper->dstImagWork.v[i]);
-        }
-    }
-
-    //Free cl_mem
-    freeCLMem(warper->useBandSrcValidCL, warper->useBandSrcValid);
-    freeCLMem(warper->nBandSrcValidCL, warper->nBandSrcValid);
-    freeCLMem(warper->xyWorkCL, warper->xyWork);
-    freeCLMem(warper->fDstNoDataRealCL, warper->fDstNoDataReal);
-
-    //Free pointers to cl_mem*
-    if (warper->realWorkCL != NULL)
-        CPLFree(warper->realWorkCL);
-    if (warper->dstRealWorkCL != NULL)
-        CPLFree(warper->dstRealWorkCL);
-
-    if (warper->imagWorkCL != NULL)
-        CPLFree(warper->imagWorkCL);
-    if (warper->dstImagWorkCL != NULL)
-        CPLFree(warper->dstImagWorkCL);
-
-    if (warper->realWork.v != NULL)
-        CPLFree(warper->realWork.v);
-    if (warper->dstRealWork.v != NULL)
-        CPLFree(warper->dstRealWork.v);
-
-    if (warper->imagWork.v != NULL)
-        CPLFree(warper->imagWork.v);
-    if (warper->dstImagWork.v != NULL)
-        CPLFree(warper->dstImagWork.v);
-
-    //Free OpenCL structures
-    if (warper->kern1 != NULL)
-        clReleaseKernel(warper->kern1);
-    if (warper->kern4 != NULL)
-        clReleaseKernel(warper->kern4);
-    if (warper->queue != NULL)
-        clReleaseCommandQueue(warper->queue);
-    if (warper->context != NULL)
-        clReleaseContext(warper->context);
-
-    CPLFree(warper);
-
-    return CL_SUCCESS;
-}
-
-#endif /* defined(HAVE_OPENCL) */
diff --git a/alg/gdalwarpkernel_opencl.cpp b/alg/gdalwarpkernel_opencl.cpp
new file mode 100644
index 0000000..935dfde
--- /dev/null
+++ b/alg/gdalwarpkernel_opencl.cpp
@@ -0,0 +1,2689 @@
+/******************************************************************************
+ * $Id: gdalwarpkernel_opencl.cpp 36763 2016-12-09 22:10:55Z rouault $
+ *
+ * Project:  OpenCL Image Reprojector
+ * Purpose:  Implementation of the GDALWarpKernel reprojector in OpenCL.
+ * Author:   Seth Price, seth at pricepages.org
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Seth Price <seth at pricepages.org>
+ * Copyright (c) 2010-2012, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#if defined(HAVE_OPENCL)
+
+/* The following line may be uncommented for increased debugging traces and profiling */
+/* #define DEBUG_OPENCL 1 */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <float.h>
+#include "cpl_string.h"
+#include "gdalwarpkernel_opencl.h"
+
+CPL_CVSID("$Id: gdalwarpkernel_opencl.cpp 36763 2016-12-09 22:10:55Z rouault $");
+
+#define handleErr(err) if((err) != CL_SUCCESS) { \
+    CPLError(CE_Failure, CPLE_AppDefined, "Error at file %s line %d: %s", __FILE__, __LINE__, getCLErrorString(err)); \
+    return err; \
+}
+
+#define handleErrRetNULL(err) if((err) != CL_SUCCESS) { \
+    (*clErr) = err; \
+    CPLError(CE_Failure, CPLE_AppDefined, "Error at file %s line %d: %s", __FILE__, __LINE__, getCLErrorString(err)); \
+    return NULL; \
+}
+
+#define handleErrGoto(err, goto_label) if((err) != CL_SUCCESS) { \
+    (*clErr) = err; \
+    CPLError(CE_Failure, CPLE_AppDefined, "Error at file %s line %d: %s", __FILE__, __LINE__, getCLErrorString(err)); \
+    goto goto_label; \
+}
+
+#define freeCLMem(clMem, fallBackMem)  do { \
+    if ((clMem) != NULL) { \
+        handleErr(err = clReleaseMemObject(clMem)); \
+        clMem = NULL; \
+        fallBackMem = NULL; \
+    } else if ((fallBackMem) != NULL) { \
+        CPLFree(fallBackMem); \
+        fallBackMem = NULL; \
+    } \
+} while( false )
+
+static const char* getCLErrorString(cl_int err)
+{
+    switch (err)
+    {
+        case CL_SUCCESS:
+            return("CL_SUCCESS");
+            break;
+        case CL_DEVICE_NOT_FOUND:
+            return("CL_DEVICE_NOT_FOUND");
+            break;
+        case CL_DEVICE_NOT_AVAILABLE:
+            return("CL_DEVICE_NOT_AVAILABLE");
+            break;
+        case CL_COMPILER_NOT_AVAILABLE:
+            return("CL_COMPILER_NOT_AVAILABLE");
+            break;
+        case CL_MEM_OBJECT_ALLOCATION_FAILURE:
+            return("CL_MEM_OBJECT_ALLOCATION_FAILURE");
+            break;
+        case CL_OUT_OF_RESOURCES:
+            return("CL_OUT_OF_RESOURCES");
+            break;
+        case CL_OUT_OF_HOST_MEMORY:
+            return("CL_OUT_OF_HOST_MEMORY");
+            break;
+        case CL_PROFILING_INFO_NOT_AVAILABLE:
+            return("CL_PROFILING_INFO_NOT_AVAILABLE");
+            break;
+        case CL_MEM_COPY_OVERLAP:
+            return("CL_MEM_COPY_OVERLAP");
+            break;
+        case CL_IMAGE_FORMAT_MISMATCH:
+            return("CL_IMAGE_FORMAT_MISMATCH");
+            break;
+        case CL_IMAGE_FORMAT_NOT_SUPPORTED:
+            return("CL_IMAGE_FORMAT_NOT_SUPPORTED");
+            break;
+        case CL_BUILD_PROGRAM_FAILURE:
+            return("CL_BUILD_PROGRAM_FAILURE");
+            break;
+        case CL_MAP_FAILURE:
+            return("CL_MAP_FAILURE");
+            break;
+        case CL_INVALID_VALUE:
+            return("CL_INVALID_VALUE");
+            break;
+        case CL_INVALID_DEVICE_TYPE:
+            return("CL_INVALID_DEVICE_TYPE");
+            break;
+        case CL_INVALID_PLATFORM:
+            return("CL_INVALID_PLATFORM");
+            break;
+        case CL_INVALID_DEVICE:
+            return("CL_INVALID_DEVICE");
+            break;
+        case CL_INVALID_CONTEXT:
+            return("CL_INVALID_CONTEXT");
+            break;
+        case CL_INVALID_QUEUE_PROPERTIES:
+            return("CL_INVALID_QUEUE_PROPERTIES");
+            break;
+        case CL_INVALID_COMMAND_QUEUE:
+            return("CL_INVALID_COMMAND_QUEUE");
+            break;
+        case CL_INVALID_HOST_PTR:
+            return("CL_INVALID_HOST_PTR");
+            break;
+        case CL_INVALID_MEM_OBJECT:
+            return("CL_INVALID_MEM_OBJECT");
+            break;
+        case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
+            return("CL_INVALID_IMAGE_FORMAT_DESCRIPTOR");
+            break;
+        case CL_INVALID_IMAGE_SIZE:
+            return("CL_INVALID_IMAGE_SIZE");
+            break;
+        case CL_INVALID_SAMPLER:
+            return("CL_INVALID_SAMPLER");
+            break;
+        case CL_INVALID_BINARY:
+            return("CL_INVALID_BINARY");
+            break;
+        case CL_INVALID_BUILD_OPTIONS:
+            return("CL_INVALID_BUILD_OPTIONS");
+            break;
+        case CL_INVALID_PROGRAM:
+            return("CL_INVALID_PROGRAM");
+            break;
+        case CL_INVALID_PROGRAM_EXECUTABLE:
+            return("CL_INVALID_PROGRAM_EXECUTABLE");
+            break;
+        case CL_INVALID_KERNEL_NAME:
+            return("CL_INVALID_KERNEL_NAME");
+            break;
+        case CL_INVALID_KERNEL_DEFINITION:
+            return("CL_INVALID_KERNEL_DEFINITION");
+            break;
+        case CL_INVALID_KERNEL:
+            return("CL_INVALID_KERNEL");
+            break;
+        case CL_INVALID_ARG_INDEX:
+            return("CL_INVALID_ARG_INDEX");
+            break;
+        case CL_INVALID_ARG_VALUE:
+            return("CL_INVALID_ARG_VALUE");
+            break;
+        case CL_INVALID_ARG_SIZE:
+            return("CL_INVALID_ARG_SIZE");
+            break;
+        case CL_INVALID_KERNEL_ARGS:
+            return("CL_INVALID_KERNEL_ARGS");
+            break;
+        case CL_INVALID_WORK_DIMENSION:
+            return("CL_INVALID_WORK_DIMENSION");
+            break;
+        case CL_INVALID_WORK_GROUP_SIZE:
+            return("CL_INVALID_WORK_GROUP_SIZE");
+            break;
+        case CL_INVALID_WORK_ITEM_SIZE:
+            return("CL_INVALID_WORK_ITEM_SIZE");
+            break;
+        case CL_INVALID_GLOBAL_OFFSET:
+            return("CL_INVALID_GLOBAL_OFFSET");
+            break;
+        case CL_INVALID_EVENT_WAIT_LIST:
+            return("CL_INVALID_EVENT_WAIT_LIST");
+            break;
+        case CL_INVALID_EVENT:
+            return("CL_INVALID_EVENT");
+            break;
+        case CL_INVALID_OPERATION:
+            return("CL_INVALID_OPERATION");
+            break;
+        case CL_INVALID_GL_OBJECT:
+            return("CL_INVALID_GL_OBJECT");
+            break;
+        case CL_INVALID_BUFFER_SIZE:
+            return("CL_INVALID_BUFFER_SIZE");
+            break;
+        case CL_INVALID_MIP_LEVEL:
+            return("CL_INVALID_MIP_LEVEL");
+            break;
+        case CL_INVALID_GLOBAL_WORK_SIZE:
+            return("CL_INVALID_GLOBAL_WORK_SIZE");
+            break;
+    }
+
+    return "unknown_error";
+}
+
+static const char* getCLDataTypeString( cl_channel_type dataType )
+{
+    switch( dataType )
+    {
+        case CL_SNORM_INT8: return "CL_SNORM_INT8";
+        case CL_SNORM_INT16: return "CL_SNORM_INT16";
+        case CL_UNORM_INT8: return "CL_UNORM_INT8";
+        case CL_UNORM_INT16: return "CL_UNORM_INT16";
+#if 0
+        case CL_UNORM_SHORT_565: return "CL_UNORM_SHORT_565";
+        case CL_UNORM_SHORT_555: return "CL_UNORM_SHORT_555";
+        case CL_UNORM_INT_101010: return "CL_UNORM_INT_101010";
+        case CL_SIGNED_INT8: return "CL_SIGNED_INT8";
+        case CL_SIGNED_INT16: return "CL_SIGNED_INT16";
+        case CL_SIGNED_INT32: return "CL_SIGNED_INT32";
+        case CL_UNSIGNED_INT8: return "CL_UNSIGNED_INT8";
+        case CL_UNSIGNED_INT16: return "CL_UNSIGNED_INT16";
+        case CL_UNSIGNED_INT32: return "CL_UNSIGNED_INT32";
+        case CL_HALF_FLOAT: return "CL_HALF_FLOAT";
+#endif
+        case CL_FLOAT: return "CL_FLOAT";
+        default: return "unknown";
+    }
+}
+
+/*
+ Finds an appropriate OpenCL device. For debugging, it's
+ always easier to use CL_DEVICE_TYPE_CPU because then */ /*ok*/ /*printf() can be called
+ from the kernel. If debugging is on, we can print the name and stats about the
+ device we're using.
+ */
+static cl_device_id get_device(OCLVendor *peVendor)
+{
+    cl_int err = 0;
+    size_t returned_size = 0;
+    cl_char vendor_name[1024] = {0};
+    cl_char device_name[1024] = {0};
+
+    cl_platform_id platforms[10];
+    cl_uint num_platforms;
+    cl_uint i;
+    cl_device_id preferred_device_id = NULL;
+    int preferred_is_gpu = FALSE;
+
+    static bool gbBuggyOpenCL = false;
+    if( gbBuggyOpenCL )
+        return NULL;
+    try
+    {
+        err = clGetPlatformIDs( 10, platforms, &num_platforms );
+        if( err != CL_SUCCESS || num_platforms == 0 )
+            return NULL;
+    }
+    catch( ... )
+    {
+        gbBuggyOpenCL = true;   
+        CPLDebug("OpenCL", "clGetPlatformIDs() threw a C++ exception");
+        // This should normally not happen. But that does happen with
+        // intel-opencl 0r2.0-54426 when run under xvfb-run 
+        return NULL;
+    }
+    
+    bool bUseOpenCLCPU = CPLTestBool( CPLGetConfigOption("OPENCL_USE_CPU", "FALSE") );
+
+    // In case we have several implementations, pick up the non Intel one by
+    // default, unless the PREFERRED_OPENCL_VENDOR config option is specified.
+    for( i=0; i<num_platforms;i++)
+    {
+        cl_device_id device = NULL;
+        const char* pszBlacklistedVendor;
+        const char* pszPreferredVendor;
+        int is_gpu;
+
+        // Find the GPU CL device, this is what we really want
+        // If there is no GPU device is CL capable, fall back to CPU
+        if( bUseOpenCLCPU )
+            err = CL_DEVICE_NOT_FOUND;
+        else
+            err = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_GPU, 1,
+                                 &device, NULL);
+        is_gpu = (err == CL_SUCCESS);
+        if (err != CL_SUCCESS)
+        {
+            // Find the CPU CL device, as a fallback
+            err = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_CPU, 1,
+                                 &device, NULL);
+            if( err != CL_SUCCESS || device == 0 )
+                continue;
+        }
+
+        // Get some information about the returned device
+        err = clGetDeviceInfo(device, CL_DEVICE_VENDOR, sizeof(vendor_name),
+                            vendor_name, &returned_size);
+        err |= clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_name),
+                            device_name, &returned_size);
+        assert(err == CL_SUCCESS);
+
+        if( num_platforms > 1 )
+            CPLDebug( "OpenCL", "Found vendor='%s' / device='%s' (%s implementation).",
+                      vendor_name, device_name, (is_gpu) ? "GPU" : "CPU");
+        
+        pszBlacklistedVendor = CPLGetConfigOption("BLACKLISTED_OPENCL_VENDOR", NULL);
+        if( pszBlacklistedVendor &&
+            EQUAL( (const char*)vendor_name, pszBlacklistedVendor ) ) 
+        {
+            CPLDebug("OpenCL", "Blacklisted vendor='%s' / device='%s' implementation skipped",
+                     vendor_name, device_name);
+            continue;
+        }
+            
+        if( preferred_device_id == NULL || (is_gpu && !preferred_is_gpu) )
+        {
+            preferred_device_id = device;
+            preferred_is_gpu = is_gpu;
+        }
+            
+        pszPreferredVendor = CPLGetConfigOption("PREFERRED_OPENCL_VENDOR", NULL);
+        if( pszPreferredVendor )
+        {
+            if( EQUAL( (const char*)vendor_name, pszPreferredVendor ) )
+            {
+                preferred_device_id = device;
+                preferred_is_gpu = is_gpu;
+                break;
+            }
+        }
+        else if( is_gpu && !STARTS_WITH((const char*)vendor_name, "Intel") )
+        {
+            preferred_device_id = device;
+            preferred_is_gpu = is_gpu;
+            break;
+        }
+    }
+    if( preferred_device_id == NULL )
+    {
+        CPLDebug("OpenCL", "No implementation found");
+        return NULL;
+    }
+    
+    err = clGetDeviceInfo(preferred_device_id, CL_DEVICE_VENDOR, sizeof(vendor_name),
+                            vendor_name, &returned_size);
+    err |= clGetDeviceInfo(preferred_device_id, CL_DEVICE_NAME, sizeof(device_name),
+                            device_name, &returned_size);
+    CPLDebug( "OpenCL", "Connected to vendor='%s' / device='%s' (%s implementation).",
+              vendor_name, device_name, (preferred_is_gpu) ? "GPU" : "CPU");
+
+    if (STARTS_WITH((const char*)vendor_name, "Advanced Micro Devices"))
+        *peVendor = VENDOR_AMD;
+    else if (STARTS_WITH((const char*)vendor_name, "Intel"))
+        *peVendor = VENDOR_INTEL;
+    else
+        *peVendor = VENDOR_OTHER;
+
+    return preferred_device_id;
+}
+
+/*
+ Given that not all OpenCL devices support the same image formats, we need to
+ make do with what we have. This leads to wasted space, but as OpenCL matures
+ I hope it'll get better.
+ */
+static cl_int set_supported_formats(struct oclWarper *warper,
+                             cl_channel_order minOrderSize,
+                             cl_channel_order *chosenOrder,
+                             unsigned int *chosenSize,
+                             cl_channel_type dataType )
+{
+    cl_image_format *fmtBuf = (cl_image_format *)calloc(256, sizeof(cl_image_format));
+    cl_uint numRet;
+    cl_uint i;
+    cl_uint extraSpace = 9999;
+    cl_int err;
+    int bFound = FALSE;
+
+    //Find what we *can* handle
+    handleErr(err = clGetSupportedImageFormats(warper->context,
+                                               CL_MEM_READ_ONLY,
+                                               CL_MEM_OBJECT_IMAGE2D,
+                                               256, fmtBuf, &numRet));
+    for (i = 0; i < numRet; ++i) {
+        cl_channel_order thisOrderSize = 0;
+        switch (fmtBuf[i].image_channel_order)
+        {
+            //Only support formats which use the channels in order (x,y,z,w)
+          case CL_R:
+          case CL_INTENSITY:
+          case CL_LUMINANCE:
+            thisOrderSize = 1;
+            break;
+          case CL_RG:
+            thisOrderSize = 2;
+            break;
+          case CL_RGB:
+            thisOrderSize = 3;
+            break;
+          case CL_RGBA:
+            thisOrderSize = 4;
+            break;
+        }
+
+        //Choose an order with the least wasted space
+        if (fmtBuf[i].image_channel_data_type == dataType &&
+            minOrderSize <= thisOrderSize &&
+            extraSpace > thisOrderSize - minOrderSize ) {
+
+            //Set the vector size, order, & remember wasted space
+            (*chosenSize) = thisOrderSize;
+            (*chosenOrder) = fmtBuf[i].image_channel_order;
+            extraSpace = thisOrderSize - minOrderSize;
+            bFound = TRUE;
+        }
+    }
+
+    free(fmtBuf);
+
+    if( !bFound )
+    {
+        CPLDebug("OpenCL",
+                 "Cannot find supported format for dataType = %s and minOrderSize = %d",
+                 getCLDataTypeString(dataType), (int)minOrderSize);
+    }
+    return (bFound) ? CL_SUCCESS : CL_INVALID_OPERATION;
+}
+
+/*
+ Allocate some pinned memory that we can use as an intermediate buffer. We're
+ using the pinned memory to assemble the data before transferring it to the
+ device. The reason we're using pinned RAM is because the transfer speed from
+ host RAM to device RAM is faster than non-pinned. The disadvantage is that
+ pinned RAM is a scarce OS resource. I'm making the assumption that the user
+ has as much pinned host RAM available as total device RAM because device RAM
+ tends to be similarly scarce. However, if the pinned memory fails we fall back
+ to using a regular memory allocation.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int alloc_pinned_mem(struct oclWarper *warper, int imgNum, size_t dataSz,
+                        void **wrkPtr, cl_mem *wrkCL)
+{
+    cl_int err = CL_SUCCESS;
+    wrkCL[imgNum] = clCreateBuffer(warper->context,
+                                   CL_MEM_READ_ONLY | CL_MEM_ALLOC_HOST_PTR,
+                                   dataSz, NULL, &err);
+
+    if (err == CL_SUCCESS) {
+        wrkPtr[imgNum] = (void *)clEnqueueMapBuffer(warper->queue, wrkCL[imgNum],
+                                                    CL_FALSE, CL_MAP_WRITE,
+                                                    0, dataSz, 0, NULL, NULL, &err);
+        handleErr(err);
+    } else {
+        wrkCL[imgNum] = NULL;
+#ifdef DEBUG_OPENCL
+        CPLDebug("OpenCL", "Using fallback non-pinned memory!");
+#endif
+        //Fallback to regular allocation
+        wrkPtr[imgNum] = (void *)VSI_MALLOC_VERBOSE(dataSz);
+
+        if (wrkPtr[imgNum] == NULL)
+            handleErr(err = CL_OUT_OF_HOST_MEMORY);
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Allocates the working host memory for all bands of the image in the warper
+ structure. This includes both the source image buffers and the destination
+ buffers. This memory is located on the host, so we can assemble the image.
+ Reasons for buffering it like this include reading each row from disk and
+ de-interleaving bands and parts of bands. Then they can be copied to the device
+ as a single operation fit for use as an OpenCL memory object.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int alloc_working_arr(struct oclWarper *warper,
+                         size_t ptrSz, size_t dataSz, CPL_UNUSED size_t *fmtSz)
+{
+    cl_int err = CL_SUCCESS;
+    int i, b;
+    size_t srcDataSz1, dstDataSz1, srcDataSz4, dstDataSz4;
+    const int numBands = warper->numBands;
+
+    //Find the best channel order for this format
+    err = set_supported_formats(warper, 1,
+                                &(warper->imgChOrder1), &(warper->imgChSize1),
+                                warper->imageFormat);
+    handleErr(err);
+    if(warper->useVec) {
+        err = set_supported_formats(warper, 4,
+                                    &(warper->imgChOrder4), &(warper->imgChSize4),
+                                    warper->imageFormat);
+        handleErr(err);
+    }
+
+    //Alloc space for pointers to the main image data
+    warper->realWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
+    warper->dstRealWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
+    if (warper->realWork.v == NULL || warper->dstRealWork.v == NULL)
+        handleErr(err = CL_OUT_OF_HOST_MEMORY);
+
+    if (warper->imagWorkCL != NULL) {
+        //Alloc space for pointers to the extra channel, if it exists
+        warper->imagWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
+        warper->dstImagWork.v = (void **)VSI_CALLOC_VERBOSE(ptrSz, warper->numImages);
+        if (warper->imagWork.v == NULL || warper->dstImagWork.v == NULL)
+            handleErr(err = CL_OUT_OF_HOST_MEMORY);
+    } else {
+        warper->imagWork.v = NULL;
+        warper->dstImagWork.v = NULL;
+    }
+
+    //Calc the sizes we need
+    srcDataSz1 = dataSz * warper->srcWidth * warper->srcHeight * warper->imgChSize1;
+    dstDataSz1 = dataSz * warper->dstWidth * warper->dstHeight;
+    srcDataSz4 = dataSz * warper->srcWidth * warper->srcHeight * warper->imgChSize4;
+    dstDataSz4 = dataSz * warper->dstWidth * warper->dstHeight * 4;
+
+    //Allocate pinned memory for each band's image
+    for (b = 0, i = 0; b < numBands && i < warper->numImages; ++i) {
+        if(warper->useVec && b < numBands - numBands % 4) {
+            handleErr(err = alloc_pinned_mem(warper, i, srcDataSz4,
+                                             warper->realWork.v,
+                                             warper->realWorkCL));
+
+            handleErr(err = alloc_pinned_mem(warper, i, dstDataSz4,
+                                             warper->dstRealWork.v,
+                                             warper->dstRealWorkCL));
+            b += 4;
+        } else {
+            handleErr(err = alloc_pinned_mem(warper, i, srcDataSz1,
+                                             warper->realWork.v,
+                                             warper->realWorkCL));
+
+            handleErr(err = alloc_pinned_mem(warper, i, dstDataSz1,
+                                             warper->dstRealWork.v,
+                                             warper->dstRealWorkCL));
+            ++b;
+        }
+    }
+
+    if (warper->imagWorkCL != NULL) {
+        //Allocate pinned memory for each band's extra channel, if exists
+        for (b = 0, i = 0; b < numBands && i < warper->numImages; ++i) {
+            if(warper->useVec && b < numBands - numBands % 4) {
+                handleErr(err = alloc_pinned_mem(warper, i, srcDataSz4,
+                                                 warper->imagWork.v,
+                                                 warper->imagWorkCL));
+
+                handleErr(err = alloc_pinned_mem(warper, i, dstDataSz4,
+                                                 warper->dstImagWork.v,
+                                                 warper->dstImagWorkCL));
+                b += 4;
+            } else {
+                handleErr(err = alloc_pinned_mem(warper, i, srcDataSz1,
+                                                 warper->imagWork.v,
+                                                 warper->imagWorkCL));
+
+                handleErr(err = alloc_pinned_mem(warper, i, dstDataSz1,
+                                                 warper->dstImagWork.v,
+                                                 warper->dstImagWorkCL));
+                ++b;
+            }
+        }
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Assemble and create the kernel. For optimization, portability, and
+ implementation limitation reasons, the program is actually assembled from
+ several strings, then compiled with as many invariants as possible defined by
+ the preprocessor. There is also quite a bit of error-catching code in here
+ because the kernel is where many bugs show up.
+
+ Returns CL_SUCCESS on success and other CL_* errors in the error buffer when
+ something goes wrong.
+ */
+static
+cl_kernel get_kernel(struct oclWarper *warper, char useVec,
+                     double dfXScale, double dfYScale, double dfXFilter, double dfYFilter,
+                     int nXRadius, int nYRadius, int nFiltInitX, int nFiltInitY,
+                     cl_int *clErr )
+{
+    cl_program program;
+    cl_kernel kernel;
+    cl_int err = CL_SUCCESS;
+#define PROGBUF_SIZE 128000
+    char *buffer = (char *)CPLCalloc(PROGBUF_SIZE, sizeof(char));
+    char *progBuf = (char *)CPLCalloc(PROGBUF_SIZE, sizeof(char));
+    float dstMinVal = 0.f, dstMaxVal = 0.0;
+
+    const char *outType;
+    const char *dUseVec = "";
+    const char *dVecf = "float";
+    const char *kernGenFuncs =
+// ********************* General Funcs ********************
+"void clampToDst(float fReal,\n"
+                "__global outType *dstPtr,\n"
+                "unsigned int iDstOffset,\n"
+                "__constant float *fDstNoDataReal,\n"
+                "int bandNum);\n"
+"void setPixel(__global outType *dstReal,\n"
+                "__global outType *dstImag,\n"
+                "__global float *dstDensity,\n"
+                "__global int *nDstValid,\n"
+                "__constant float *fDstNoDataReal,\n"
+                "const int bandNum,\n"
+                "vecf fDensity, vecf fReal, vecf fImag);\n"
+"int getPixel(__read_only image2d_t srcReal,\n"
+                "__read_only image2d_t srcImag,\n"
+                "__global float *fUnifiedSrcDensity,\n"
+                "__global int *nUnifiedSrcValid,\n"
+                "__constant char *useBandSrcValid,\n"
+                "__global int *nBandSrcValid,\n"
+                "const int2 iSrc,\n"
+                "int bandNum,\n"
+                "vecf *fDensity, vecf *fReal, vecf *fImag);\n"
+"int isValid(__global float *fUnifiedSrcDensity,\n"
+                "__global int *nUnifiedSrcValid,\n"
+                "float2 fSrcCoords );\n"
+"float2 getSrcCoords(__read_only image2d_t srcCoords);\n"
+
+"#ifdef USE_CLAMP_TO_DST_FLOAT\n"
+"void clampToDst(float fReal,\n"
+                "__global outType *dstPtr,\n"
+                "unsigned int iDstOffset,\n"
+                "__constant float *fDstNoDataReal,\n"
+                "int bandNum)\n"
+"{\n"
+    "dstPtr[iDstOffset] = fReal;\n"
+"}\n"
+"#else\n"
+"void clampToDst(float fReal,\n"
+                "__global outType *dstPtr,\n"
+                "unsigned int iDstOffset,\n"
+                "__constant float *fDstNoDataReal,\n"
+                "int bandNum)\n"
+"{\n"
+    "fReal *= dstMaxVal;\n"
+
+    "if (fReal < dstMinVal)\n"
+        "dstPtr[iDstOffset] = (outType)dstMinVal;\n"
+    "else if (fReal > dstMaxVal)\n"
+        "dstPtr[iDstOffset] = (outType)dstMaxVal;\n"
+    "else\n"
+        "dstPtr[iDstOffset] = (dstMinVal < 0) ? (outType)floor(fReal + 0.5f) : (outType)(fReal + 0.5f);\n"
+
+    "if (useDstNoDataReal && bandNum >= 0 &&\n"
+        "fDstNoDataReal[bandNum] == dstPtr[iDstOffset])\n"
+    "{\n"
+        "if (dstPtr[iDstOffset] == dstMinVal)\n"
+            "dstPtr[iDstOffset] = dstMinVal + 1;\n"
+        "else\n"
+            "dstPtr[iDstOffset] = dstPtr[iDstOffset] - 1;\n"
+    "}\n"
+"}\n"
+"#endif\n"
+
+"void setPixel(__global outType *dstReal,\n"
+              "__global outType *dstImag,\n"
+              "__global float *dstDensity,\n"
+              "__global int *nDstValid,\n"
+              "__constant float *fDstNoDataReal,\n"
+              "const int bandNum,\n"
+              "vecf fDensity, vecf fReal, vecf fImag)\n"
+"{\n"
+    "unsigned int iDstOffset = get_global_id(1)*iDstWidth + get_global_id(0);\n"
+
+"#ifdef USE_VEC\n"
+    "if (fDensity.x < 0.00001f && fDensity.y < 0.00001f &&\n"
+        "fDensity.z < 0.00001f && fDensity.w < 0.00001f ) {\n"
+
+        "fReal = 0.0f;\n"
+        "fImag = 0.0f;\n"
+
+    "} else if (fDensity.x < 0.9999f || fDensity.y < 0.9999f ||\n"
+               "fDensity.z < 0.9999f || fDensity.w < 0.9999f ) {\n"
+        "vecf fDstReal, fDstImag;\n"
+        "float fDstDensity;\n"
+
+        "fDstReal.x = dstReal[iDstOffset];\n"
+        "fDstReal.y = dstReal[iDstOffset+iDstHeight*iDstWidth];\n"
+        "fDstReal.z = dstReal[iDstOffset+iDstHeight*iDstWidth*2];\n"
+        "fDstReal.w = dstReal[iDstOffset+iDstHeight*iDstWidth*3];\n"
+        "if (useImag) {\n"
+            "fDstImag.x = dstImag[iDstOffset];\n"
+            "fDstImag.y = dstImag[iDstOffset+iDstHeight*iDstWidth];\n"
+            "fDstImag.z = dstImag[iDstOffset+iDstHeight*iDstWidth*2];\n"
+            "fDstImag.w = dstImag[iDstOffset+iDstHeight*iDstWidth*3];\n"
+        "}\n"
+"#else\n"
+    "if (fDensity < 0.00001f) {\n"
+
+        "fReal = 0.0f;\n"
+        "fImag = 0.0f;\n"
+
+    "} else if (fDensity < 0.9999f) {\n"
+        "vecf fDstReal, fDstImag;\n"
+        "float fDstDensity;\n"
+
+        "fDstReal = dstReal[iDstOffset];\n"
+        "if (useImag)\n"
+            "fDstImag = dstImag[iDstOffset];\n"
+"#endif\n"
+
+        "if (useDstDensity)\n"
+            "fDstDensity = dstDensity[iDstOffset];\n"
+        "else if (useDstValid &&\n"
+                 "!((nDstValid[iDstOffset>>5] & (0x01 << (iDstOffset & 0x1f))) ))\n"
+            "fDstDensity = 0.0f;\n"
+        "else\n"
+            "fDstDensity = 1.0f;\n"
+
+        "vecf fDstInfluence = (1.0f - fDensity) * fDstDensity;\n"
+
+        // Density should be checked for <= 0.0 & handled by the calling function
+        "fReal = (fReal * fDensity + fDstReal * fDstInfluence) / (fDensity + fDstInfluence);\n"
+        "if (useImag)\n"
+            "fImag = (fImag * fDensity + fDstImag * fDstInfluence) / (fDensity + fDstInfluence);\n"
+    "}\n"
+
+"#ifdef USE_VEC\n"
+    "clampToDst(fReal.x, dstReal, iDstOffset, fDstNoDataReal, bandNum);\n"
+    "clampToDst(fReal.y, dstReal, iDstOffset+iDstHeight*iDstWidth, fDstNoDataReal, bandNum);\n"
+    "clampToDst(fReal.z, dstReal, iDstOffset+iDstHeight*iDstWidth*2, fDstNoDataReal, bandNum);\n"
+    "clampToDst(fReal.w, dstReal, iDstOffset+iDstHeight*iDstWidth*3, fDstNoDataReal, bandNum);\n"
+    "if (useImag) {\n"
+        "clampToDst(fImag.x, dstImag, iDstOffset, fDstNoDataReal, -1);\n"
+        "clampToDst(fImag.y, dstImag, iDstOffset+iDstHeight*iDstWidth, fDstNoDataReal, -1);\n"
+        "clampToDst(fImag.z, dstImag, iDstOffset+iDstHeight*iDstWidth*2, fDstNoDataReal, -1);\n"
+        "clampToDst(fImag.w, dstImag, iDstOffset+iDstHeight*iDstWidth*3, fDstNoDataReal, -1);\n"
+    "}\n"
+"#else\n"
+    "clampToDst(fReal, dstReal, iDstOffset, fDstNoDataReal, bandNum);\n"
+    "if (useImag)\n"
+        "clampToDst(fImag, dstImag, iDstOffset, fDstNoDataReal, -1);\n"
+"#endif\n"
+"}\n"
+
+"int getPixel(__read_only image2d_t srcReal,\n"
+             "__read_only image2d_t srcImag,\n"
+             "__global float *fUnifiedSrcDensity,\n"
+             "__global int *nUnifiedSrcValid,\n"
+             "__constant char *useBandSrcValid,\n"
+             "__global int *nBandSrcValid,\n"
+             "const int2 iSrc,\n"
+             "int bandNum,\n"
+             "vecf *fDensity, vecf *fReal, vecf *fImag)\n"
+"{\n"
+    "int iSrcOffset = 0, iBandValidLen = 0, iSrcOffsetMask = 0;\n"
+    "int bHasValid = FALSE;\n"
+
+    // Clamp the src offset values if needed
+    "if(useUnifiedSrcDensity | useUnifiedSrcValid | useUseBandSrcValid){\n"
+        "int iSrcX = iSrc.x;\n"
+        "int iSrcY = iSrc.y;\n"
+
+        // Needed because the offset isn't clamped in OpenCL hardware
+        "if(iSrcX < 0)\n"
+            "iSrcX = 0;\n"
+        "else if(iSrcX >= iSrcWidth)\n"
+            "iSrcX = iSrcWidth - 1;\n"
+
+        "if(iSrcY < 0)\n"
+            "iSrcY = 0;\n"
+        "else if(iSrcY >= iSrcHeight)\n"
+            "iSrcY = iSrcHeight - 1;\n"
+
+        "iSrcOffset = iSrcY*iSrcWidth + iSrcX;\n"
+        "iBandValidLen = 1 + ((iSrcWidth*iSrcHeight)>>5);\n"
+        "iSrcOffsetMask = (0x01 << (iSrcOffset & 0x1f));\n"
+    "}\n"
+
+    "if (useUnifiedSrcValid &&\n"
+        "!((nUnifiedSrcValid[iSrcOffset>>5] & iSrcOffsetMask) ) )\n"
+        "return FALSE;\n"
+
+"#ifdef USE_VEC\n"
+    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum] ||\n"
+        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*bandNum    ] & iSrcOffsetMask)) )\n"
+        "bHasValid = TRUE;\n"
+
+    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum+1] ||\n"
+        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*(1+bandNum)] & iSrcOffsetMask)) )\n"
+        "bHasValid = TRUE;\n"
+
+    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum+2] ||\n"
+        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*(2+bandNum)] & iSrcOffsetMask)) )\n"
+        "bHasValid = TRUE;\n"
+
+    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum+3] ||\n"
+        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*(3+bandNum)] & iSrcOffsetMask)) )\n"
+        "bHasValid = TRUE;\n"
+"#else\n"
+    "if (!useUseBandSrcValid || !useBandSrcValid[bandNum] ||\n"
+        "((nBandSrcValid[(iSrcOffset>>5)+iBandValidLen*bandNum    ] & iSrcOffsetMask)) )\n"
+        "bHasValid = TRUE;\n"
+"#endif\n"
+
+    "if (!bHasValid)\n"
+        "return FALSE;\n"
+
+    "const sampler_t samp =  CLK_NORMALIZED_COORDS_FALSE |\n"
+                            "CLK_ADDRESS_CLAMP_TO_EDGE |\n"
+                            "CLK_FILTER_NEAREST;\n"
+
+"#ifdef USE_VEC\n"
+    "(*fReal) = read_imagef(srcReal, samp, iSrc);\n"
+    "if (useImag)\n"
+        "(*fImag) = read_imagef(srcImag, samp, iSrc);\n"
+"#else\n"
+    "(*fReal) = read_imagef(srcReal, samp, iSrc).x;\n"
+    "if (useImag)\n"
+        "(*fImag) = read_imagef(srcImag, samp, iSrc).x;\n"
+"#endif\n"
+
+    "if (useUnifiedSrcDensity) {\n"
+        "(*fDensity) = fUnifiedSrcDensity[iSrcOffset];\n"
+    "} else {\n"
+        "(*fDensity) = 1.0f;\n"
+        "return TRUE;\n"
+    "}\n"
+
+"#ifdef USE_VEC\n"
+    "return  (*fDensity).x > 0.0000001f || (*fDensity).y > 0.0000001f ||\n"
+            "(*fDensity).z > 0.0000001f || (*fDensity).w > 0.0000001f;\n"
+"#else\n"
+    "return (*fDensity) > 0.0000001f;\n"
+"#endif\n"
+"}\n"
+
+"int isValid(__global float *fUnifiedSrcDensity,\n"
+            "__global int *nUnifiedSrcValid,\n"
+            "float2 fSrcCoords )\n"
+"{\n"
+    "if (fSrcCoords.x < 0.0f || fSrcCoords.y < 0.0f)\n"
+        "return FALSE;\n"
+
+    "int iSrcX = (int) (fSrcCoords.x - 0.5f);\n"
+    "int iSrcY = (int) (fSrcCoords.y - 0.5f);\n"
+
+    "if( iSrcX < 0 || iSrcX >= iSrcWidth || iSrcY < 0 || iSrcY >= iSrcHeight )\n"
+        "return FALSE;\n"
+
+    "int iSrcOffset = iSrcX + iSrcY * iSrcWidth;\n"
+
+    "if (useUnifiedSrcDensity && fUnifiedSrcDensity[iSrcOffset] < 0.00001f)\n"
+        "return FALSE;\n"
+
+    "if (useUnifiedSrcValid &&\n"
+        "!(nUnifiedSrcValid[iSrcOffset>>5] & (0x01 << (iSrcOffset & 0x1f))) )\n"
+        "return FALSE;\n"
+
+    "return TRUE;\n"
+"}\n"
+
+"float2 getSrcCoords(__read_only image2d_t srcCoords)\n"
+"{\n"
+    // Find an appropriate place to sample the coordinates so we're still
+    // accurate after linear interpolation.
+    "int nDstX = get_global_id(0);\n"
+    "int nDstY = get_global_id(1);\n"
+    "float2  fDst = (float2)((0.5f * (float)iCoordMult + nDstX) /\n"
+                                "(float)((ceil((iDstWidth  - 1) / (float)iCoordMult) + 1) * iCoordMult), \n"
+                            "(0.5f * (float)iCoordMult + nDstY) /\n"
+                                "(float)((ceil((iDstHeight - 1) / (float)iCoordMult) + 1) * iCoordMult));\n"
+
+    // Check & return when the thread group overruns the image size
+    "if (nDstX >= iDstWidth || nDstY >= iDstHeight)\n"
+        "return (float2)(-99.0f, -99.0f);\n"
+
+    "const sampler_t samp =  CLK_NORMALIZED_COORDS_TRUE |\n"
+                            "CLK_ADDRESS_CLAMP_TO_EDGE |\n"
+                            "CLK_FILTER_LINEAR;\n"
+
+    "float4  fSrcCoords = read_imagef(srcCoords,samp,fDst);\n"
+
+    "return (float2)(fSrcCoords.x, fSrcCoords.y);\n"
+"}\n";
+
+    const char *kernBilinear =
+// ************************ Bilinear ************************
+"__kernel void resamp(__read_only image2d_t srcCoords,\n"
+                    "__read_only image2d_t srcReal,\n"
+                    "__read_only image2d_t srcImag,\n"
+                    "__global float *fUnifiedSrcDensity,\n"
+                    "__global int *nUnifiedSrcValid,\n"
+                    "__constant char *useBandSrcValid,\n"
+                    "__global int *nBandSrcValid,\n"
+                    "__global outType *dstReal,\n"
+                    "__global outType *dstImag,\n"
+                    "__constant float *fDstNoDataReal,\n"
+                    "__global float *dstDensity,\n"
+                    "__global int *nDstValid,\n"
+                    "const int bandNum)\n"
+"{\n"
+    "float2  fSrc = getSrcCoords(srcCoords);\n"
+    "if (!isValid(fUnifiedSrcDensity, nUnifiedSrcValid, fSrc))\n"
+        "return;\n"
+
+    "int     iSrcX = (int) floor(fSrc.x - 0.5f);\n"
+    "int     iSrcY = (int) floor(fSrc.y - 0.5f);\n"
+    "float   fRatioX = 1.5f - (fSrc.x - iSrcX);\n"
+    "float   fRatioY = 1.5f - (fSrc.y - iSrcY);\n"
+    "vecf    fReal, fImag, fDens;\n"
+    "vecf    fAccumulatorReal = 0.0f, fAccumulatorImag = 0.0f;\n"
+    "vecf    fAccumulatorDensity = 0.0f;\n"
+    "float   fAccumulatorDivisor = 0.0f;\n"
+
+    "if ( iSrcY >= 0 && iSrcY < iSrcHeight ) {\n"
+        "float fMult1 = fRatioX * fRatioY;\n"
+        "float fMult2 = (1.0f-fRatioX) * fRatioY;\n"
+
+                // Upper Left Pixel
+                "if ( iSrcX >= 0 && iSrcX < iSrcWidth\n"
+                         "&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                                                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX, iSrcY),\n"
+                                                "bandNum, &fDens, &fReal, &fImag))\n"
+                "{\n"
+                        "fAccumulatorDivisor += fMult1;\n"
+                        "fAccumulatorReal += fReal * fMult1;\n"
+                        "fAccumulatorImag += fImag * fMult1;\n"
+                        "fAccumulatorDensity += fDens * fMult1;\n"
+                "}\n"
+
+                // Upper Right Pixel
+                "if ( iSrcX+1 >= 0 && iSrcX+1 < iSrcWidth\n"
+                        "&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                                                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY),\n"
+                                                "bandNum, &fDens, &fReal, &fImag))\n"
+                "{\n"
+                        "fAccumulatorDivisor += fMult2;\n"
+                        "fAccumulatorReal += fReal * fMult2;\n"
+                        "fAccumulatorImag += fImag * fMult2;\n"
+                        "fAccumulatorDensity += fDens * fMult2;\n"
+                "}\n"
+    "}\n"
+
+    "if ( iSrcY+1 >= 0 && iSrcY+1 < iSrcHeight ) {\n"
+        "float fMult1 = fRatioX * (1.0f-fRatioY);\n"
+        "float fMult2 = (1.0f-fRatioX) * (1.0f-fRatioY);\n"
+
+        // Lower Left Pixel
+                "if ( iSrcX >= 0 && iSrcX < iSrcWidth\n"
+                        "&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                                                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX, iSrcY+1),\n"
+                                                "bandNum, &fDens, &fReal, &fImag))\n"
+                "{\n"
+                        "fAccumulatorDivisor += fMult1;\n"
+                        "fAccumulatorReal += fReal * fMult1;\n"
+                        "fAccumulatorImag += fImag * fMult1;\n"
+                        "fAccumulatorDensity += fDens * fMult1;\n"
+                "}\n"
+
+                // Lower Right Pixel
+                "if ( iSrcX+1 >= 0 && iSrcX+1 < iSrcWidth\n"
+                        "&& getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                                                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY+1),\n"
+                                                "bandNum, &fDens, &fReal, &fImag))\n"
+                "{\n"
+                        "fAccumulatorDivisor += fMult2;\n"
+                        "fAccumulatorReal += fReal * fMult2;\n"
+                        "fAccumulatorImag += fImag * fMult2;\n"
+                        "fAccumulatorDensity += fDens * fMult2;\n"
+                "}\n"
+    "}\n"
+
+    // Compute and save final pixel
+    "if ( fAccumulatorDivisor < 0.00001f ) {\n"
+        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
+                "0.0f, 0.0f, 0.0f );\n"
+    "} else if ( fAccumulatorDivisor < 0.99999f || fAccumulatorDivisor > 1.00001f ) {\n"
+        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
+                "fAccumulatorDensity / fAccumulatorDivisor,\n"
+                "fAccumulatorReal / fAccumulatorDivisor,\n"
+"#if useImag != 0\n"
+                "fAccumulatorImag / fAccumulatorDivisor );\n"
+"#else\n"
+                "0.0f );\n"
+"#endif\n"
+    "} else {\n"
+        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
+                "fAccumulatorDensity, fAccumulatorReal, fAccumulatorImag );\n"
+    "}\n"
+"}\n";
+
+    const char *kernCubic =
+// ************************ Cubic ************************
+"vecf cubicConvolution(float dist1, float dist2, float dist3,\n"
+                        "vecf f0, vecf f1, vecf f2, vecf f3);\n"
+
+"vecf cubicConvolution(float dist1, float dist2, float dist3,\n"
+                       "vecf f0, vecf f1, vecf f2, vecf f3)\n"
+"{\n"
+   "return (  f1\n"
+       "+ 0.5f * (dist1*(f2 - f0)\n"
+               "+ dist2*(2.0f*f0 - 5.0f*f1 + 4.0f*f2 - f3)\n"
+               "+ dist3*(3.0f*(f1 - f2) + f3 - f0)));\n"
+"}\n"
+
+// ************************ Cubic ************************
+"__kernel void resamp(__read_only image2d_t srcCoords,\n"
+                     "__read_only image2d_t srcReal,\n"
+                     "__read_only image2d_t srcImag,\n"
+                     "__global float *fUnifiedSrcDensity,\n"
+                     "__global int *nUnifiedSrcValid,\n"
+                     "__constant char *useBandSrcValid,\n"
+                     "__global int *nBandSrcValid,\n"
+                     "__global outType *dstReal,\n"
+                     "__global outType *dstImag,\n"
+                     "__constant float *fDstNoDataReal,\n"
+                     "__global float *dstDensity,\n"
+                     "__global int *nDstValid,\n"
+                     "const int bandNum)\n"
+"{\n"
+    "int i;\n"
+    "float2  fSrc = getSrcCoords(srcCoords);\n"
+
+    "if (!isValid(fUnifiedSrcDensity, nUnifiedSrcValid, fSrc))\n"
+        "return;\n"
+
+    "int     iSrcX = (int) floor( fSrc.x - 0.5f );\n"
+    "int     iSrcY = (int) floor( fSrc.y - 0.5f );\n"
+    "float   fDeltaX = fSrc.x - 0.5f - (float)iSrcX;\n"
+    "float   fDeltaY = fSrc.y - 0.5f - (float)iSrcY;\n"
+    "float   fDeltaX2 = fDeltaX * fDeltaX;\n"
+    "float   fDeltaY2 = fDeltaY * fDeltaY;\n"
+    "float   fDeltaX3 = fDeltaX2 * fDeltaX;\n"
+    "float   fDeltaY3 = fDeltaY2 * fDeltaY;\n"
+    "vecf    afReal[4], afDens[4];\n"
+"#if useImag != 0\n"
+    "vecf    afImag[4];\n"
+"#else\n"
+    "vecf    fImag = 0.0f;\n"
+"#endif\n"
+
+    // Loop over rows
+    "for (i = -1; i < 3; ++i)\n"
+    "{\n"
+        "vecf    fReal1 = 0.0f, fReal2 = 0.0f, fReal3 = 0.0f, fReal4 = 0.0f;\n"
+        "vecf    fDens1 = 0.0f, fDens2 = 0.0f, fDens3 = 0.0f, fDens4 = 0.0f;\n"
+        "int hasPx;\n"
+"#if useImag != 0\n"
+        "vecf    fImag1 = 0.0f, fImag2 = 0.0f, fImag3 = 0.0f, fImag4 = 0.0f;\n"
+
+        //Get all the pixels for this row
+        "hasPx  = getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                        "useBandSrcValid, nBandSrcValid, (int2)(iSrcX-1, iSrcY+i),\n"
+                        "bandNum, &fDens1, &fReal1, &fImag1);\n"
+
+        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                        "useBandSrcValid, nBandSrcValid, (int2)(iSrcX  , iSrcY+i),\n"
+                        "bandNum, &fDens2, &fReal2, &fImag2);\n"
+
+        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                        "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY+i),\n"
+                        "bandNum, &fDens3, &fReal3, &fImag3);\n"
+
+        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                        "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+2, iSrcY+i),\n"
+                        "bandNum, &fDens4, &fReal4, &fImag4);\n"
+"#else\n"
+        //Get all the pixels for this row
+        "hasPx  = getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX-1, iSrcY+i),\n"
+                "bandNum, &fDens1, &fReal1, &fImag);\n"
+
+        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX  , iSrcY+i),\n"
+                "bandNum, &fDens2, &fReal2, &fImag);\n"
+
+        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+1, iSrcY+i),\n"
+                "bandNum, &fDens3, &fReal3, &fImag);\n"
+
+        "hasPx |= getPixel(srcReal, srcImag, fUnifiedSrcDensity, nUnifiedSrcValid,\n"
+                "useBandSrcValid, nBandSrcValid, (int2)(iSrcX+2, iSrcY+i),\n"
+                "bandNum, &fDens4, &fReal4, &fImag);\n"
+"#endif\n"
+
+        // Shortcut if no px
+        "if (!hasPx) {\n"
+            "afDens[i+1] = 0.0f;\n"
+            "afReal[i+1] = 0.0f;\n"
+"#if useImag != 0\n"
+            "afImag[i+1] = 0.0f;\n"
+"#endif\n"
+            "continue;\n"
+        "}\n"
+
+        // Process this row
+        "afDens[i+1] = cubicConvolution(fDeltaX, fDeltaX2, fDeltaX3, fDens1, fDens2, fDens3, fDens4);\n"
+        "afReal[i+1] = cubicConvolution(fDeltaX, fDeltaX2, fDeltaX3, fReal1, fReal2, fReal3, fReal4);\n"
+"#if useImag != 0\n"
+        "afImag[i+1] = cubicConvolution(fDeltaX, fDeltaX2, fDeltaX3, fImag1, fImag2, fImag3, fImag4);\n"
+"#endif\n"
+    "}\n"
+
+    // Compute and save final pixel
+    "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
+             "cubicConvolution(fDeltaY, fDeltaY2, fDeltaY3, afDens[0], afDens[1], afDens[2], afDens[3]),\n"
+             "cubicConvolution(fDeltaY, fDeltaY2, fDeltaY3, afReal[0], afReal[1], afReal[2], afReal[3]),\n"
+"#if useImag != 0\n"
+             "cubicConvolution(fDeltaY, fDeltaY2, fDeltaY3, afImag[0], afImag[1], afImag[2], afImag[3]) );\n"
+"#else\n"
+             "fImag );\n"
+"#endif\n"
+"}\n";
+
+    const char *kernResampler =
+// ************************ LanczosSinc ************************
+
+"float lanczosSinc( float fX, float fR );\n"
+"float bSpline( float x );\n"
+
+"float lanczosSinc( float fX, float fR )\n"
+"{\n"
+    "if ( fX > fR || fX < -fR)\n"
+        "return 0.0f;\n"
+    "if ( fX == 0.0f )\n"
+        "return 1.0f;\n"
+
+    "float fPIX = PI * fX;\n"
+    "return ( sin(fPIX) / fPIX ) * ( sin(fPIX / fR) * fR / fPIX );\n"
+"}\n"
+
+// ************************ Bicubic Spline ************************
+
+"float bSpline( float x )\n"
+"{\n"
+    "float xp2 = x + 2.0f;\n"
+    "float xp1 = x + 1.0f;\n"
+    "float xm1 = x - 1.0f;\n"
+    "float xp2c = xp2 * xp2 * xp2;\n"
+
+    "return (((xp2 > 0.0f)?((xp1 > 0.0f)?((x > 0.0f)?((xm1 > 0.0f)?\n"
+                                                     "-4.0f * xm1*xm1*xm1:0.0f) +\n"
+                                         "6.0f * x*x*x:0.0f) +\n"
+                           "-4.0f * xp1*xp1*xp1:0.0f) +\n"
+             "xp2c:0.0f) ) * 0.166666666666666666666f;\n"
+"}\n"
+
+// ************************ General Resampler ************************
+
+"__kernel void resamp(__read_only image2d_t srcCoords,\n"
+                     "__read_only image2d_t srcReal,\n"
+                     "__read_only image2d_t srcImag,\n"
+                     "__global float *fUnifiedSrcDensity,\n"
+                     "__global int *nUnifiedSrcValid,\n"
+                     "__constant char *useBandSrcValid,\n"
+                     "__global int *nBandSrcValid,\n"
+                     "__global outType *dstReal,\n"
+                     "__global outType *dstImag,\n"
+                     "__constant float *fDstNoDataReal,\n"
+                     "__global float *dstDensity,\n"
+                     "__global int *nDstValid,\n"
+                     "const int bandNum)\n"
+"{\n"
+    "float2  fSrc = getSrcCoords(srcCoords);\n"
+
+    "if (!isValid(fUnifiedSrcDensity, nUnifiedSrcValid, fSrc))\n"
+        "return;\n"
+
+    "int     iSrcX = floor( fSrc.x - 0.5f );\n"
+    "int     iSrcY = floor( fSrc.y - 0.5f );\n"
+    "float   fDeltaX = fSrc.x - 0.5f - (float)iSrcX;\n"
+    "float   fDeltaY = fSrc.y - 0.5f - (float)iSrcY;\n"
+
+    "vecf  fAccumulatorReal = 0.0f, fAccumulatorImag = 0.0f;\n"
+    "vecf  fAccumulatorDensity = 0.0f;\n"
+    "float fAccumulatorWeight = 0.0f;\n"
+    "int   i, j;\n"
+
+    // Loop over pixel rows in the kernel
+    "for ( j = nFiltInitY; j <= nYRadius; ++j )\n"
+    "{\n"
+        "float   fWeight1;\n"
+        "int2 iSrc = (int2)(0, iSrcY + j);\n"
+
+        // Skip sampling over edge of image
+        "if ( iSrc.y < 0 || iSrc.y >= iSrcHeight )\n"
+            "continue;\n"
+
+        // Select the resampling algorithm
+        "if ( doCubicSpline )\n"
+            // Calculate the Y weight
+            "fWeight1 = ( fYScale < 1.0f ) ?\n"
+                "bSpline(((float)j) * fYScale) * fYScale :\n"
+                "bSpline(((float)j) - fDeltaY);\n"
+        "else\n"
+            "fWeight1 = ( fYScale < 1.0f ) ?\n"
+                "lanczosSinc(j * fYScale, fYFilter) * fYScale :\n"
+                "lanczosSinc(j - fDeltaY, fYFilter);\n"
+
+        // Iterate over pixels in row
+        "for ( i = nFiltInitX; i <= nXRadius; ++i )\n"
+        "{\n"
+            "float fWeight2;\n"
+            "vecf fDensity = 0.0f, fReal, fImag;\n"
+            "iSrc.x = iSrcX + i;\n"
+
+            // Skip sampling at edge of image
+            // Skip sampling when invalid pixel
+            "if ( iSrc.x < 0 || iSrc.x >= iSrcWidth || \n"
+                  "!getPixel(srcReal, srcImag, fUnifiedSrcDensity,\n"
+                            "nUnifiedSrcValid, useBandSrcValid, nBandSrcValid,\n"
+                            "iSrc, bandNum, &fDensity, &fReal, &fImag) )\n"
+                "continue;\n"
+
+            // Choose among possible algorithms
+            "if ( doCubicSpline )\n"
+                // Calculate & save the X weight
+                "fWeight2 = fWeight1 * ((fXScale < 1.0f ) ?\n"
+                    "bSpline((float)i * fXScale) * fXScale :\n"
+                    "bSpline(fDeltaX - (float)i));\n"
+            "else\n"
+                // Calculate & save the X weight
+                "fWeight2 = fWeight1 * ((fXScale < 1.0f ) ?\n"
+                    "lanczosSinc(i * fXScale, fXFilter) * fXScale :\n"
+                    "lanczosSinc(i - fDeltaX, fXFilter));\n"
+
+            // Accumulate!
+            "fAccumulatorReal += fReal * fWeight2;\n"
+            "fAccumulatorImag += fImag * fWeight2;\n"
+            "fAccumulatorDensity += fDensity * fWeight2;\n"
+            "fAccumulatorWeight += fWeight2;\n"
+        "}\n"
+    "}\n"
+
+    "if ( fAccumulatorWeight < 0.000001f ) {\n"
+        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
+                 "0.0f, 0.0f, 0.0f);\n"
+    "} else if ( fAccumulatorWeight < 0.99999f || fAccumulatorWeight > 1.00001f ) {\n"
+        // Calculate the output taking into account weighting
+        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
+                 "fAccumulatorDensity / fAccumulatorWeight,\n"
+                 "fAccumulatorReal / fAccumulatorWeight,\n"
+"#if useImag != 0\n"
+                 "fAccumulatorImag / fAccumulatorWeight );\n"
+"#else\n"
+                 "0.0f );\n"
+"#endif\n"
+    "} else {\n"
+        "setPixel(dstReal, dstImag, dstDensity, nDstValid, fDstNoDataReal, bandNum,\n"
+                 "fAccumulatorDensity, fAccumulatorReal, fAccumulatorImag);\n"
+    "}\n"
+"}\n";
+
+    //Defines based on image format
+    switch (warper->imageFormat) {
+        case CL_FLOAT:
+            dstMinVal = -FLT_MAX;
+            dstMaxVal = FLT_MAX;
+            outType = "float";
+            break;
+        case CL_SNORM_INT8:
+            dstMinVal = -128.0;
+            dstMaxVal = 127.0;
+            outType = "char";
+            break;
+        case CL_UNORM_INT8:
+            dstMinVal = 0.0;
+            dstMaxVal = 255.0;
+            outType = "uchar";
+            break;
+        case CL_SNORM_INT16:
+            dstMinVal = -32768.0;
+            dstMaxVal = 32767.0;
+            outType = "short";
+            break;
+        case CL_UNORM_INT16:
+            dstMinVal = 0.0;
+            dstMaxVal = 65535.0;
+            outType = "ushort";
+            break;
+    }
+
+    //Use vector format?
+    if (useVec) {
+        dUseVec = "-D USE_VEC";
+        dVecf = "float4";
+    }
+
+    //Assemble the kernel from parts. The compiler is unable to handle multiple
+    //kernels in one string with more than a few __constant modifiers each.
+    if (warper->resampAlg == OCL_Bilinear)
+        snprintf(progBuf, PROGBUF_SIZE, "%s\n%s", kernGenFuncs, kernBilinear);
+    else if (warper->resampAlg == OCL_Cubic)
+        snprintf(progBuf, PROGBUF_SIZE, "%s\n%s", kernGenFuncs, kernCubic);
+    else
+        snprintf(progBuf, PROGBUF_SIZE, "%s\n%s", kernGenFuncs, kernResampler);
+
+    //Actually make the program from assembled source
+    program = clCreateProgramWithSource(warper->context, 1, (const char**)&progBuf,
+                                        NULL, &err);
+    handleErrGoto(err, error_final);
+
+    //Assemble the compiler arg string for speed. All invariants should be defined here.
+    snprintf(buffer, PROGBUF_SIZE,
+             "-cl-fast-relaxed-math -Werror -D FALSE=0 -D TRUE=1 "
+            "%s"
+            "-D iSrcWidth=%d -D iSrcHeight=%d -D iDstWidth=%d -D iDstHeight=%d "
+            "-D useUnifiedSrcDensity=%d -D useUnifiedSrcValid=%d "
+            "-D useDstDensity=%d -D useDstValid=%d -D useImag=%d "
+            "-D fXScale=%015.15lff -D fYScale=%015.15lff -D fXFilter=%015.15lff -D fYFilter=%015.15lff "
+            "-D nXRadius=%d -D nYRadius=%d -D nFiltInitX=%d -D nFiltInitY=%d "
+            "-D PI=%015.15lff -D outType=%s -D dstMinVal=%015.15lff -D dstMaxVal=%015.15lff "
+            "-D useDstNoDataReal=%d -D vecf=%s %s -D doCubicSpline=%d "
+            "-D useUseBandSrcValid=%d -D iCoordMult=%d ",
+            (warper->imageFormat == CL_FLOAT) ? "-D USE_CLAMP_TO_DST_FLOAT=1 " : "",
+            warper->srcWidth, warper->srcHeight, warper->dstWidth, warper->dstHeight,
+            warper->useUnifiedSrcDensity, warper->useUnifiedSrcValid,
+            warper->useDstDensity, warper->useDstValid, warper->imagWorkCL != NULL,
+            dfXScale, dfYScale, dfXFilter, dfYFilter,
+            nXRadius, nYRadius, nFiltInitX, nFiltInitY,
+            M_PI, outType, dstMinVal, dstMaxVal, warper->fDstNoDataRealCL != NULL,
+            dVecf, dUseVec, warper->resampAlg == OCL_CubicSpline,
+            warper->nBandSrcValidCL != NULL, warper->coordMult);
+
+    (*clErr) = err = clBuildProgram(program, 1, &(warper->dev), buffer, NULL, NULL);
+
+    //Detailed debugging info
+    if (err != CL_SUCCESS)
+    {
+        const char* pszStatus = "unknown_status";
+        err = clGetProgramBuildInfo(program, warper->dev, CL_PROGRAM_BUILD_LOG,
+                                    128000*sizeof(char), buffer, NULL);
+        handleErrGoto(err, error_free_program);
+
+        CPLError(CE_Failure, CPLE_AppDefined, "Error: Failed to build program executable!\nBuild Log:\n%s", buffer);
+
+        err = clGetProgramBuildInfo(program, warper->dev, CL_PROGRAM_BUILD_STATUS,
+                                    128000*sizeof(char), buffer, NULL);
+        handleErrGoto(err, error_free_program);
+
+        if(buffer[0] == CL_BUILD_NONE)
+            pszStatus = "CL_BUILD_NONE";
+        else if(buffer[0] == CL_BUILD_ERROR)
+            pszStatus = "CL_BUILD_ERROR";
+        else if(buffer[0] == CL_BUILD_SUCCESS)
+            pszStatus = "CL_BUILD_SUCCESS";
+        else if(buffer[0] == CL_BUILD_IN_PROGRESS)
+            pszStatus = "CL_BUILD_IN_PROGRESS";
+
+        CPLDebug("OpenCL", "Build Status: %s\nProgram Source:\n%s", pszStatus, progBuf);
+        goto error_free_program;
+    }
+
+    kernel = clCreateKernel(program, "resamp", &err);
+    handleErrGoto(err, error_free_program);
+
+    err = clReleaseProgram(program);
+    handleErrGoto(err, error_final);
+
+    CPLFree(buffer);
+    CPLFree(progBuf);
+    return kernel;
+
+error_free_program:
+    err = clReleaseProgram(program);
+
+error_final:
+    CPLFree(buffer);
+    CPLFree(progBuf);
+    return NULL;
+}
+
+/*
+ Alloc & copy the coordinate data from host working memory to the device. The
+ working memory should be a pinned, linear, array of floats. This allows us to
+ allocate and copy all data in one step. The pointer to the device memory is
+ saved and set as the appropriate argument number.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int set_coord_data (struct oclWarper *warper, cl_mem *xy)
+{
+    cl_int err = CL_SUCCESS;
+    cl_image_format imgFmt;
+
+    //Copy coord data to the device
+    imgFmt.image_channel_order = warper->xyChOrder;
+    imgFmt.image_channel_data_type = CL_FLOAT;
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+    (*xy) = clCreateImage2D(warper->context,
+                            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imgFmt,
+                            (size_t) warper->xyWidth,
+                            (size_t) warper->xyHeight,
+                            (size_t) sizeof(float) * warper->xyChSize * warper->xyWidth,
+                            warper->xyWork, &err);
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+    handleErr(err);
+
+    //Free the source memory, now that it's copied we don't need it
+    freeCLMem(warper->xyWorkCL, warper->xyWork);
+
+    //Set up argument
+    if (warper->kern1 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern1, 0, sizeof(cl_mem), xy));
+    }
+    if (warper->kern4 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern4, 0, sizeof(cl_mem), xy));
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Sets the unified density & valid data structures. These are optional structures
+ from GDAL, and as such if they are NULL a small placeholder memory segment is
+ defined. This is because the spec is unclear on if a NULL value can be passed
+ as a kernel argument in place of memory. If it's not NULL, the data is copied
+ from the working memory to the device memory. After that, we check if we are
+ using the per-band validity mask, and set that as appropriate. At the end, the
+ CL mem is passed as the kernel arguments.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int set_unified_data(struct oclWarper *warper,
+                        cl_mem *unifiedSrcDensityCL, cl_mem *unifiedSrcValidCL,
+                        float *unifiedSrcDensity, unsigned int *unifiedSrcValid,
+                        cl_mem *useBandSrcValidCL, cl_mem *nBandSrcValidCL)
+{
+    cl_int err = CL_SUCCESS;
+    size_t sz = warper->srcWidth * warper->srcHeight;
+    int useValid = warper->nBandSrcValidCL != NULL;
+    //32 bits in the mask
+    int validSz = (int)(sizeof(int) * ((31 + sz) >> 5));
+
+    //Copy unifiedSrcDensity if it exists
+    if (unifiedSrcDensity == NULL) {
+        //Alloc dummy device RAM
+        (*unifiedSrcDensityCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
+        handleErr(err);
+    } else {
+        //Alloc & copy all density data
+        (*unifiedSrcDensityCL) = clCreateBuffer(warper->context,
+                                                CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+                                                sizeof(float) * sz, unifiedSrcDensity, &err);
+        handleErr(err);
+    }
+
+    //Copy unifiedSrcValid if it exists
+    if (unifiedSrcValid == NULL) {
+        //Alloc dummy device RAM
+        (*unifiedSrcValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
+        handleErr(err);
+    } else {
+        //Alloc & copy all validity data
+        (*unifiedSrcValidCL) = clCreateBuffer(warper->context,
+                                              CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+                                              validSz, unifiedSrcValid, &err);
+        handleErr(err);
+    }
+
+    // Set the band validity usage
+    if(useValid) {
+        (*useBandSrcValidCL) = clCreateBuffer(warper->context,
+                                              CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+                                              sizeof(char) * warper->numBands,
+                                              warper->useBandSrcValid, &err);
+        handleErr(err);
+    } else {
+        //Make a fake image so we don't have a NULL pointer
+        (*useBandSrcValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
+        handleErr(err);
+    }
+
+    //Do a more thorough check for validity
+    if (useValid) {
+        int i;
+        useValid = FALSE;
+        for (i = 0; i < warper->numBands; ++i)
+            if (warper->useBandSrcValid[i])
+                useValid = TRUE;
+    }
+
+    //And the validity mask if needed
+    if (useValid) {
+        (*nBandSrcValidCL) = clCreateBuffer(warper->context,
+                                            CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+                                            warper->numBands * validSz,
+                                            warper->nBandSrcValid, &err);
+        handleErr(err);
+    } else {
+        //Make a fake image so we don't have a NULL pointer
+        (*nBandSrcValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
+        handleErr(err);
+    }
+
+    //Set up arguments
+    if (warper->kern1 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern1, 3, sizeof(cl_mem), unifiedSrcDensityCL));
+        handleErr(err = clSetKernelArg(warper->kern1, 4, sizeof(cl_mem), unifiedSrcValidCL));
+        handleErr(err = clSetKernelArg(warper->kern1, 5, sizeof(cl_mem), useBandSrcValidCL));
+        handleErr(err = clSetKernelArg(warper->kern1, 6, sizeof(cl_mem), nBandSrcValidCL));
+    }
+    if (warper->kern4 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern4, 3, sizeof(cl_mem), unifiedSrcDensityCL));
+        handleErr(err = clSetKernelArg(warper->kern4, 4, sizeof(cl_mem), unifiedSrcValidCL));
+        handleErr(err = clSetKernelArg(warper->kern4, 5, sizeof(cl_mem), useBandSrcValidCL));
+        handleErr(err = clSetKernelArg(warper->kern4, 6, sizeof(cl_mem), nBandSrcValidCL));
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Here we set the per-band raster data. First priority is the real raster data,
+ of course. Then, if applicable, we set the additional image channel. Once this
+ data is copied to the device, it can be freed on the host, so that is done
+ here. Finally the appropriate kernel arguments are set.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int set_src_rast_data (struct oclWarper *warper, int iNum, size_t sz,
+                          cl_channel_order chOrder, cl_mem *srcReal, cl_mem *srcImag)
+{
+    cl_image_format imgFmt;
+    cl_int err = CL_SUCCESS;
+    int useImagWork = warper->imagWork.v != NULL && warper->imagWork.v[iNum] != NULL;
+
+    //Set up image vars
+    imgFmt.image_channel_order = chOrder;
+    imgFmt.image_channel_data_type = warper->imageFormat;
+
+    //Create & copy the source image
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+    (*srcReal) = clCreateImage2D(warper->context,
+                                 CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imgFmt,
+                                 (size_t) warper->srcWidth, (size_t) warper->srcHeight,
+                                 sz * warper->srcWidth, warper->realWork.v[iNum], &err);
+    handleErr(err);
+
+    //And the source image parts if needed
+    if (useImagWork) {
+        (*srcImag) = clCreateImage2D(warper->context,
+                                     CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imgFmt,
+                                     (size_t) warper->srcWidth, (size_t) warper->srcHeight,
+                                     sz * warper->srcWidth, warper->imagWork.v[iNum], &err);
+        handleErr(err);
+    } else {
+        //Make a fake image so we don't have a NULL pointer
+
+        char dummyImageData[16];
+        (*srcImag) = clCreateImage2D(warper->context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &imgFmt,
+                                    1, 1, sz, dummyImageData, &err);
+
+        handleErr(err);
+    }
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+    //Free the source memory, now that it's copied we don't need it
+    freeCLMem(warper->realWorkCL[iNum], warper->realWork.v[iNum]);
+    if (warper->imagWork.v != NULL) {
+        freeCLMem(warper->imagWorkCL[iNum], warper->imagWork.v[iNum]);
+    }
+
+    //Set up per-band arguments
+    if (warper->kern1 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern1, 1, sizeof(cl_mem), srcReal));
+        handleErr(err = clSetKernelArg(warper->kern1, 2, sizeof(cl_mem), srcImag));
+    }
+    if (warper->kern4 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern4, 1, sizeof(cl_mem), srcReal));
+        handleErr(err = clSetKernelArg(warper->kern4, 2, sizeof(cl_mem), srcImag));
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Set the destination data for the raster. Although it's the output, it still
+ is copied to the device because some blending is done there. First the real
+ data is allocated and copied, then the imag data is allocated and copied if
+ needed. They are then set as the appropriate arguments to the kernel.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int set_dst_rast_data(struct oclWarper *warper, int iImg, size_t sz,
+                         cl_mem *dstReal, cl_mem *dstImag)
+{
+    cl_int err = CL_SUCCESS;
+    sz *= warper->dstWidth * warper->dstHeight;
+
+    //Copy the dst real data
+    (*dstReal) = clCreateBuffer(warper->context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
+                                sz, warper->dstRealWork.v[iImg], &err);
+    handleErr(err);
+
+    //Copy the dst imag data if exists
+    if (warper->dstImagWork.v != NULL && warper->dstImagWork.v[iImg] != NULL) {
+        (*dstImag) = clCreateBuffer(warper->context,
+                                    CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR,
+                                    sz, warper->dstImagWork.v[iImg], &err);
+        handleErr(err);
+    } else {
+        (*dstImag) = clCreateBuffer(warper->context, CL_MEM_READ_WRITE, 1, NULL, &err);
+        handleErr(err);
+    }
+
+    //Set up per-band arguments
+    if (warper->kern1 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern1, 7, sizeof(cl_mem), dstReal));
+        handleErr(err = clSetKernelArg(warper->kern1, 8, sizeof(cl_mem), dstImag));
+    }
+    if (warper->kern4 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern4, 7, sizeof(cl_mem), dstReal));
+        handleErr(err = clSetKernelArg(warper->kern4, 8, sizeof(cl_mem), dstImag));
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Read the final raster data back from the graphics card to working memory. This
+ copies both the real memory and the imag memory if appropriate.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int get_dst_rast_data(struct oclWarper *warper, int iImg, size_t wordSz,
+                         cl_mem dstReal, cl_mem dstImag)
+{
+    cl_int err = CL_SUCCESS;
+    size_t sz = warper->dstWidth * warper->dstHeight * wordSz;
+
+    //Copy from dev into working memory
+    handleErr(err = clEnqueueReadBuffer(warper->queue, dstReal,
+                                        CL_FALSE, 0, sz, warper->dstRealWork.v[iImg],
+                                        0, NULL, NULL));
+
+    //If we are expecting the imag channel, then copy it back also
+    if (warper->dstImagWork.v != NULL && warper->dstImagWork.v[iImg] != NULL) {
+        handleErr(err = clEnqueueReadBuffer(warper->queue, dstImag,
+                                            CL_FALSE, 0, sz, warper->dstImagWork.v[iImg],
+                                            0, NULL, NULL));
+    }
+
+    //The copy requests were non-blocking, so we'll need to make sure they finish.
+    handleErr(err = clFinish(warper->queue));
+
+    return CL_SUCCESS;
+}
+
+/*
+ Set the destination image density & validity mask on the device. This is used
+ to blend the final output image with the existing buffer. This handles the
+ unified structures that apply to all bands. After the buffers are created and
+ copied, they are set as kernel arguments.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int set_dst_data(struct oclWarper *warper,
+                    cl_mem *dstDensityCL, cl_mem *dstValidCL, cl_mem *dstNoDataRealCL,
+                    float *dstDensity, unsigned int *dstValid, float *dstNoDataReal)
+{
+    cl_int err = CL_SUCCESS;
+    size_t sz = warper->dstWidth * warper->dstHeight;
+
+    //Copy the no-data value(s)
+    if (dstNoDataReal == NULL) {
+        (*dstNoDataRealCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
+        handleErr(err);
+    } else {
+        (*dstNoDataRealCL) = clCreateBuffer(warper->context,
+                                         CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+                                         sizeof(float) * warper->numBands, dstNoDataReal, &err);
+        handleErr(err);
+    }
+
+    //Copy unifiedSrcDensity if it exists
+    if (dstDensity == NULL) {
+        (*dstDensityCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
+        handleErr(err);
+    } else {
+        (*dstDensityCL) = clCreateBuffer(warper->context,
+                                         CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+                                         sizeof(float) * sz, dstDensity, &err);
+        handleErr(err);
+    }
+
+    //Copy unifiedSrcValid if it exists
+    if (dstValid == NULL) {
+        (*dstValidCL) = clCreateBuffer(warper->context, CL_MEM_READ_ONLY, 1, NULL, &err);
+        handleErr(err);
+    } else {
+        (*dstValidCL) = clCreateBuffer(warper->context,
+                                       CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
+                                       sizeof(int) * ((31 + sz) >> 5), dstValid, &err);
+        handleErr(err);
+    }
+
+    //Set up arguments
+    if (warper->kern1 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern1,  9, sizeof(cl_mem), dstNoDataRealCL));
+        handleErr(err = clSetKernelArg(warper->kern1, 10, sizeof(cl_mem), dstDensityCL));
+        handleErr(err = clSetKernelArg(warper->kern1, 11, sizeof(cl_mem), dstValidCL));
+    }
+    if (warper->kern4 != NULL) {
+        handleErr(err = clSetKernelArg(warper->kern4,  9, sizeof(cl_mem), dstNoDataRealCL));
+        handleErr(err = clSetKernelArg(warper->kern4, 10, sizeof(cl_mem), dstDensityCL));
+        handleErr(err = clSetKernelArg(warper->kern4, 11, sizeof(cl_mem), dstValidCL));
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Go ahead and execute the kernel. This handles some housekeeping stuff like the
+ run dimensions. When running in debug mode, it times the kernel call and prints
+ the execution time.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int execute_kern(struct oclWarper *warper, cl_kernel kern, size_t loc_size)
+{
+    cl_int err = CL_SUCCESS;
+    cl_event ev;
+    size_t ceil_runs[2];
+    size_t group_size[2];
+#ifdef DEBUG_OPENCL
+    size_t start_time = 0;
+    size_t end_time;
+    char *vecTxt = "";
+#endif
+
+    // Use a likely X-dimension which is a power of 2
+    if (loc_size >= 512)
+        group_size[0] = 32;
+    else if (loc_size >= 64)
+        group_size[0] = 16;
+    else if (loc_size > 8)
+        group_size[0] = 8;
+    else
+        group_size[0] = 1;
+
+    if (group_size[0] > loc_size)
+        group_size[1] = group_size[0]/loc_size;
+    else
+        group_size[1] = 1;
+
+    //Round up num_runs to find the dim of the block of pixels we'll be processing
+    if(warper->dstWidth % group_size[0])
+        ceil_runs[0] = warper->dstWidth + group_size[0] - warper->dstWidth % group_size[0];
+    else
+        ceil_runs[0] = warper->dstWidth;
+
+    if(warper->dstHeight % group_size[1])
+        ceil_runs[1] = warper->dstHeight + group_size[1] - warper->dstHeight % group_size[1];
+    else
+        ceil_runs[1] = warper->dstHeight;
+
+#ifdef DEBUG_OPENCL
+    handleErr(err = clSetCommandQueueProperty(warper->queue, CL_QUEUE_PROFILING_ENABLE, CL_TRUE, NULL));
+#endif
+
+    // Run the calculation by enqueuing it and forcing the
+    // command queue to complete the task
+    handleErr(err = clEnqueueNDRangeKernel(warper->queue, kern, 2, NULL,
+                                           ceil_runs, group_size, 0, NULL, &ev));
+    handleErr(err = clFinish(warper->queue));
+
+#ifdef DEBUG_OPENCL
+    handleErr(err = clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_START,
+                                            sizeof(size_t), &start_time, NULL));
+    handleErr(err = clGetEventProfilingInfo(ev, CL_PROFILING_COMMAND_END,
+                                            sizeof(size_t), &end_time, NULL));
+    assert(end_time != 0);
+    assert(start_time != 0);
+    handleErr(err = clReleaseEvent(ev));
+    if (kern == warper->kern4)
+        vecTxt = "(vec)";
+
+    CPLDebug("OpenCL", "Kernel Time: %6s %10lu", vecTxt, (long int)((end_time-start_time)/100000));
+#endif
+    return CL_SUCCESS;
+}
+
+/*
+ Copy data from a raw source to the warper's working memory. If the imag
+ channel is expected, then the data will be de-interlaced into component blocks
+ of memory.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+static
+cl_int set_img_data(struct oclWarper *warper, void *srcImgData,
+                    unsigned int width, unsigned int height, int isSrc,
+                    unsigned int bandNum, void **dstRealImgs, void **dstImagImgs)
+{
+    unsigned int imgChSize = warper->imgChSize1;
+    unsigned int iSrcY, i;
+    unsigned int vecOff = 0;
+    unsigned int imgNum = bandNum;
+    void *dstReal = NULL;
+    void *dstImag = NULL;
+
+    // Handle vector if needed
+    if (warper->useVec && (int)bandNum < warper->numBands - warper->numBands % 4) {
+        imgChSize = warper->imgChSize4;
+        vecOff = bandNum % 4;
+        imgNum = bandNum / 4;
+    } else if(warper->useVec) {
+        imgNum = bandNum / 4 + bandNum % 4;
+    }
+
+    // Set the images as needed
+    dstReal = dstRealImgs[imgNum];
+    if(dstImagImgs == NULL)
+        dstImag = NULL;
+    else
+        dstImag = dstImagImgs[imgNum];
+
+    // Set stuff for dst imgs
+    if (!isSrc) {
+        vecOff *= height * width;
+        imgChSize = 1;
+    }
+
+    // Copy values as needed
+    if (warper->imagWorkCL == NULL && !(warper->useVec && isSrc)) {
+        //Set memory size & location depending on the data type
+        //This is the ideal code path for speed
+        switch (warper->imageFormat) {
+            case CL_UNORM_INT8:
+            {
+                unsigned char *realDst = &(((unsigned char *)dstReal)[vecOff]);
+                memcpy(realDst, srcImgData, width*height*sizeof(unsigned char));
+                break;
+            }
+            case CL_SNORM_INT8:
+            {
+                char *realDst = &(((char *)dstReal)[vecOff]);
+                memcpy(realDst, srcImgData, width*height*sizeof(char));
+                break;
+            }
+            case CL_UNORM_INT16:
+            {
+                unsigned short *realDst = &(((unsigned short *)dstReal)[vecOff]);
+                memcpy(realDst, srcImgData, width*height*sizeof(unsigned short));
+                break;
+            }
+            case CL_SNORM_INT16:
+            {
+                short *realDst = &(((short *)dstReal)[vecOff]);
+                memcpy(realDst, srcImgData, width*height*sizeof(short));
+                break;
+            }
+            case CL_FLOAT:
+            {
+                float *realDst = &(((float *)dstReal)[vecOff]);
+                memcpy(realDst, srcImgData, width*height*sizeof(float));
+                break;
+            }
+        }
+    } else if (warper->imagWorkCL == NULL) {
+        //We need to space the values due to OpenCL implementation reasons
+        for( iSrcY = 0; iSrcY < height; iSrcY++ )
+        {
+            int pxOff = width*iSrcY;
+            int imgOff = imgChSize*pxOff + vecOff;
+            //Copy & deinterleave interleaved data
+            switch (warper->imageFormat) {
+                case CL_UNORM_INT8:
+                {
+                    unsigned char *realDst = &(((unsigned char *)dstReal)[imgOff]);
+                    unsigned char *dataSrc = &(((unsigned char *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i)
+                        realDst[imgChSize*i] = dataSrc[i];
+                }
+                    break;
+                case CL_SNORM_INT8:
+                {
+                    char *realDst = &(((char *)dstReal)[imgOff]);
+                    char *dataSrc = &(((char *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i)
+                        realDst[imgChSize*i] = dataSrc[i];
+                }
+                    break;
+                case CL_UNORM_INT16:
+                {
+                    unsigned short *realDst = &(((unsigned short *)dstReal)[imgOff]);
+                    unsigned short *dataSrc = &(((unsigned short *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i)
+                        realDst[imgChSize*i] = dataSrc[i];
+                }
+                    break;
+                case CL_SNORM_INT16:
+                {
+                    short *realDst = &(((short *)dstReal)[imgOff]);
+                    short *dataSrc = &(((short *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i)
+                        realDst[imgChSize*i] = dataSrc[i];
+                }
+                    break;
+                case CL_FLOAT:
+                {
+                    float *realDst = &(((float *)dstReal)[imgOff]);
+                    float *dataSrc = &(((float *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i)
+                        realDst[imgChSize*i] = dataSrc[i];
+                }
+                    break;
+            }
+        }
+    } else {
+        //Copy, deinterleave, & space interleaved data
+        for( iSrcY = 0; iSrcY < height; iSrcY++ )
+        {
+            int pxOff = width*iSrcY;
+            int imgOff = imgChSize*pxOff + vecOff;
+            //Copy & deinterleave interleaved data
+            switch (warper->imageFormat) {
+                case CL_FLOAT:
+                {
+                    float *realDst = &(((float *)dstReal)[imgOff]);
+                    float *imagDst = &(((float *)dstImag)[imgOff]);
+                    float *dataSrc = &(((float *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i) {
+                        realDst[imgChSize*i] = dataSrc[i*2  ];
+                        imagDst[imgChSize*i] = dataSrc[i*2+1];
+                    }
+                }
+                    break;
+                case CL_SNORM_INT8:
+                {
+                    char *realDst = &(((char *)dstReal)[imgOff]);
+                    char *imagDst = &(((char *)dstImag)[imgOff]);
+                    char *dataSrc = &(((char *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i) {
+                        realDst[imgChSize*i] = dataSrc[i*2  ];
+                        imagDst[imgChSize*i] = dataSrc[i*2+1];
+                    }
+                }
+                    break;
+                case CL_UNORM_INT8:
+                {
+                    unsigned char *realDst = &(((unsigned char *)dstReal)[imgOff]);
+                    unsigned char *imagDst = &(((unsigned char *)dstImag)[imgOff]);
+                    unsigned char *dataSrc = &(((unsigned char *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i) {
+                        realDst[imgChSize*i] = dataSrc[i*2  ];
+                        imagDst[imgChSize*i] = dataSrc[i*2+1];
+                    }
+                }
+                    break;
+                case CL_SNORM_INT16:
+                {
+                    short *realDst = &(((short *)dstReal)[imgOff]);
+                    short *imagDst = &(((short *)dstImag)[imgOff]);
+                    short *dataSrc = &(((short *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i) {
+                        realDst[imgChSize*i] = dataSrc[i*2  ];
+                        imagDst[imgChSize*i] = dataSrc[i*2+1];
+                    }
+                }
+                    break;
+                case CL_UNORM_INT16:
+                {
+                    unsigned short *realDst = &(((unsigned short *)dstReal)[imgOff]);
+                    unsigned short *imagDst = &(((unsigned short *)dstImag)[imgOff]);
+                    unsigned short *dataSrc = &(((unsigned short *)srcImgData)[pxOff]);
+                    for (i = 0; i < width; ++i) {
+                        realDst[imgChSize*i] = dataSrc[i*2  ];
+                        imagDst[imgChSize*i] = dataSrc[i*2+1];
+                    }
+                }
+                    break;
+            }
+        }
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Creates the struct which inits & contains the OpenCL context & environment.
+ Inits wired(?) space to buffer the image in host RAM. Chooses the OpenCL
+ device, perhaps the user can choose it later? This would also choose the
+ appropriate OpenCL image format (R, RG, RGBA, or multiples thereof). Space
+ for metadata can be allocated as required, though.
+
+ Supported image formats are:
+ CL_FLOAT, CL_SNORM_INT8, CL_UNORM_INT8, CL_SNORM_INT16, CL_UNORM_INT16
+ 32-bit int formats won't keep precision when converted to floats internally
+ and doubles are generally not supported on the GPU image formats.
+ */
+struct oclWarper* GDALWarpKernelOpenCL_createEnv(int srcWidth, int srcHeight,
+                                                 int dstWidth, int dstHeight,
+                                                 cl_channel_type imageFormat,
+                                                 int numBands, int coordMult,
+                                                 int useImag, int useBandSrcValid,
+                                                 CPL_UNUSED float *fDstDensity,
+                                                 double *dfDstNoDataReal,
+                                                 OCLResampAlg resampAlg, cl_int *clErr)
+{
+    struct oclWarper *warper;
+    int i;
+    size_t maxWidth = 0, maxHeight = 0;
+    cl_int err = CL_SUCCESS;
+    size_t fmtSize, sz;
+    cl_device_id device;
+    cl_bool bool_flag;
+    OCLVendor eCLVendor = VENDOR_OTHER;
+
+    // Do we have a suitable OpenCL device?
+    device = get_device(&eCLVendor);
+    if( device == NULL )
+        return NULL;
+
+    err = clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT,
+                          sizeof(cl_bool), &bool_flag, &sz);
+    if( err != CL_SUCCESS || !bool_flag )
+    {
+        CPLDebug( "OpenCL", "No image support on selected device." );
+        return NULL;
+    }
+
+    // Set up warper environment.
+    warper = (struct oclWarper *)CPLCalloc(1, sizeof(struct oclWarper));
+
+    warper->eCLVendor = eCLVendor;
+
+    //Init passed vars
+    warper->srcWidth = srcWidth;
+    warper->srcHeight = srcHeight;
+    warper->dstWidth = dstWidth;
+    warper->dstHeight = dstHeight;
+
+    warper->coordMult = coordMult;
+    warper->numBands = numBands;
+    warper->imageFormat = imageFormat;
+    warper->resampAlg = resampAlg;
+
+    warper->useUnifiedSrcDensity = FALSE;
+    warper->useUnifiedSrcValid = FALSE;
+    warper->useDstDensity = FALSE;
+    warper->useDstValid = FALSE;
+
+    warper->imagWorkCL = NULL;
+    warper->dstImagWorkCL = NULL;
+    warper->useBandSrcValidCL = NULL;
+    warper->useBandSrcValid = NULL;
+    warper->nBandSrcValidCL = NULL;
+    warper->nBandSrcValid = NULL;
+    warper->fDstNoDataRealCL = NULL;
+    warper->fDstNoDataReal = NULL;
+    warper->kern1 = NULL;
+    warper->kern4 = NULL;
+
+    warper->dev = device;
+
+    warper->context = clCreateContext(0, 1, &(warper->dev), NULL, NULL, &err);
+    handleErrGoto(err, error_label);
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+    warper->queue = clCreateCommandQueue(warper->context, warper->dev, 0, &err);
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+    handleErrGoto(err, error_label);
+
+    //Ensure that we hand handle imagery of these dimensions
+    err = clGetDeviceInfo(warper->dev, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &maxWidth, &sz);
+    handleErrGoto(err, error_label);
+    err = clGetDeviceInfo(warper->dev, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &maxHeight, &sz);
+    handleErrGoto(err, error_label);
+    if (maxWidth < (size_t)srcWidth || maxHeight < (size_t)srcHeight) {
+        err = CL_INVALID_IMAGE_SIZE;
+        handleErrGoto(err, error_label);
+    }
+
+    // Split bands into sets of four when possible
+    // Cubic runs slower as vector, so don't use it (probably register pressure)
+    // Feel free to do more testing and come up with more precise case statements
+    if(numBands < 4 || resampAlg == OCL_Cubic) {
+        warper->numImages = numBands;
+        warper->useVec = FALSE;
+    } else {
+        warper->numImages = numBands/4 + numBands % 4;
+        warper->useVec = TRUE;
+    }
+
+    //Make the pointer space for the real images
+    warper->realWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
+    warper->dstRealWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
+
+    //Make space for the per-channel Imag data (if exists)
+    if (useImag) {
+        warper->imagWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
+        warper->dstImagWorkCL = (cl_mem *)CPLCalloc(sizeof(cl_mem), warper->numImages);
+    }
+
+    //Make space for the per-band BandSrcValid data (if exists)
+    if (useBandSrcValid) {
+        //32 bits in the mask
+        sz = warper->numBands * ((31 + warper->srcWidth * warper->srcHeight) >> 5);
+
+        //Allocate some space for the validity of the validity mask
+        err = alloc_pinned_mem(warper, 0, warper->numBands*sizeof(char),
+                               (void **)&(warper->useBandSrcValid),
+                               &(warper->useBandSrcValidCL));
+        handleErrGoto(err, error_label);
+
+        for (i = 0; i < warper->numBands; ++i)
+            warper->useBandSrcValid[i] = FALSE;
+
+        // Allocate one array for all the band validity masks.
+        // Remember that the masks don't use much memory (they're bitwise).
+        err = alloc_pinned_mem(warper, 0, sz * sizeof(int),
+                               (void **)&(warper->nBandSrcValid),
+                               &(warper->nBandSrcValidCL));
+        handleErrGoto(err, error_label);
+    }
+
+    //Make space for the per-band
+    if (dfDstNoDataReal != NULL) {
+        alloc_pinned_mem(warper, 0, warper->numBands,
+                         (void **)&(warper->fDstNoDataReal), &(warper->fDstNoDataRealCL));
+
+        //Copy over values
+        for (i = 0; i < warper->numBands; ++i)
+            warper->fDstNoDataReal[i] = (float) dfDstNoDataReal[i];
+    }
+
+    //Alloc working host image memory
+    //We'll be copying into these buffers soon
+    switch (imageFormat) {
+      case CL_FLOAT:
+        err = alloc_working_arr(warper, sizeof(float *), sizeof(float), &fmtSize);
+        break;
+      case CL_SNORM_INT8:
+        err = alloc_working_arr(warper, sizeof(char *), sizeof(char), &fmtSize);
+        break;
+      case CL_UNORM_INT8:
+        err = alloc_working_arr(warper, sizeof(unsigned char *), sizeof(unsigned char), &fmtSize);
+        break;
+      case CL_SNORM_INT16:
+        err = alloc_working_arr(warper, sizeof(short *), sizeof(short), &fmtSize);
+        break;
+      case CL_UNORM_INT16:
+        err = alloc_working_arr(warper, sizeof(unsigned short *), sizeof(unsigned short), &fmtSize);
+        break;
+    }
+    handleErrGoto(err, error_label);
+
+    // Find a good & compatible image channel order for the Lat/Long array.
+    err = set_supported_formats(warper, 2,
+                                &(warper->xyChOrder), &(warper->xyChSize),
+                                CL_FLOAT);
+    handleErrGoto(err, error_label);
+
+    //Set coordinate image dimensions
+    warper->xyWidth  = (int)ceil(((float)warper->dstWidth  + (float)warper->coordMult-1)/(float)warper->coordMult);
+    warper->xyHeight = (int)ceil(((float)warper->dstHeight + (float)warper->coordMult-1)/(float)warper->coordMult);
+
+    //Alloc coord memory
+    sz = sizeof(float) * warper->xyChSize * warper->xyWidth * warper->xyHeight;
+    err = alloc_pinned_mem(warper, 0, sz, (void **)&(warper->xyWork),
+                           &(warper->xyWorkCL));
+    handleErrGoto(err, error_label);
+
+    //Ensure everything is finished allocating, copying, & mapping
+    err = clFinish(warper->queue);
+    handleErrGoto(err, error_label);
+
+    (*clErr) = CL_SUCCESS;
+    return warper;
+
+error_label:
+    GDALWarpKernelOpenCL_deleteEnv(warper);
+    return NULL;
+}
+
+/*
+ Copy the validity mask for an image band to the warper.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+cl_int GDALWarpKernelOpenCL_setSrcValid(struct oclWarper *warper,
+                                        int *bandSrcValid, int bandNum)
+{
+    //32 bits in the mask
+    int stride = (31 + warper->srcWidth * warper->srcHeight) >> 5;
+
+    //Copy bandSrcValid
+    assert(warper->nBandSrcValid != NULL);
+    memcpy(&(warper->nBandSrcValid[bandNum*stride]), bandSrcValid, sizeof(int) * stride);
+    warper->useBandSrcValid[bandNum] = TRUE;
+
+    return CL_SUCCESS;
+}
+
+/*
+ Sets the source image real & imag into the host memory so that it is
+ permuted (ex. RGBA) for better graphics card access.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+cl_int GDALWarpKernelOpenCL_setSrcImg(struct oclWarper *warper, void *imgData,
+                                      int bandNum)
+{
+    void **imagWorkPtr = NULL;
+
+    if (warper->imagWorkCL != NULL)
+        imagWorkPtr = warper->imagWork.v;
+
+    return set_img_data(warper, imgData, warper->srcWidth, warper->srcHeight,
+                        TRUE, bandNum, warper->realWork.v, imagWorkPtr);
+}
+
+/*
+ Sets the destination image real & imag into the host memory so that it is
+ permuted (ex. RGBA) for better graphics card access.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+cl_int GDALWarpKernelOpenCL_setDstImg(struct oclWarper *warper, void *imgData,
+                                      int bandNum)
+{
+    void **dstImagWorkPtr = NULL;
+
+    if (warper->dstImagWorkCL != NULL)
+        dstImagWorkPtr = warper->dstImagWork.v;
+
+    return set_img_data(warper, imgData, warper->dstWidth, warper->dstHeight,
+                        FALSE, bandNum, warper->dstRealWork.v, dstImagWorkPtr);
+}
+
+/*
+ Inputs the source coordinates for a row of the destination pixels. Invalid
+ coordinates are set as -99.0, which should be out of the image bounds. Sets
+ the coordinates as ready to be used in OpenCL image memory: interleaved and
+ minus the offset. By using image memory, we can use a smaller texture for
+ coordinates and use OpenCL's built-in interpolation to save memory.
+
+ What it does: generates a smaller matrix of X/Y coordinate transformation
+ values from an original matrix. When bilinearly sampled in the GPU hardware,
+ the generated values are as close as possible to the original matrix.
+
+ Complication: matrices have arbitrary dimensions and the sub-sampling factor
+ is an arbitrary integer greater than zero. Getting the edge cases right is
+ difficult.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+cl_int GDALWarpKernelOpenCL_setCoordRow(struct oclWarper *warper,
+                                        double *rowSrcX, double *rowSrcY,
+                                        double srcXOff, double srcYOff,
+                                        int *success, int rowNum)
+{
+    int coordMult = warper->coordMult;
+    int width = warper->dstWidth;
+    int height = warper->dstHeight;
+    int xyWidth = warper->xyWidth;
+    int i;
+    int xyChSize = warper->xyChSize;
+    float *xyPtr, *xyPrevPtr = NULL;
+    int lastRow = rowNum == height - 1;
+    double dstHeightMod = 1.0, dstWidthMod = 1.0;
+
+    //Return if we're at an off row
+    if(!lastRow && rowNum % coordMult != 0)
+        return CL_SUCCESS;
+
+    //Standard row, adjusted for the skipped rows
+    xyPtr = &(warper->xyWork[xyWidth * xyChSize * rowNum / coordMult]);
+
+    //Find our row
+    if(lastRow){
+        //Setup for the final row
+        xyPtr     = &(warper->xyWork[xyWidth * xyChSize * (warper->xyHeight - 1)]);
+        xyPrevPtr = &(warper->xyWork[xyWidth * xyChSize * (warper->xyHeight - 2)]);
+
+        if((height-1) % coordMult)
+            dstHeightMod = (double)coordMult / (double)((height-1) % coordMult);
+    }
+
+    //Copy selected coordinates
+    for (i = 0; i < width; i += coordMult) {
+        if (success[i]) {
+            xyPtr[0] = (float) (rowSrcX[i] - srcXOff);
+            xyPtr[1] = (float) (rowSrcY[i] - srcYOff);
+
+            if(lastRow) {
+                //Adjust bottom row so interpolator returns correct value
+                xyPtr[0] = (float) (dstHeightMod * (xyPtr[0] - xyPrevPtr[0]) + xyPrevPtr[0]);
+                xyPtr[1] = (float) (dstHeightMod * (xyPtr[1] - xyPrevPtr[1]) + xyPrevPtr[1]);
+            }
+        } else {
+            xyPtr[0] = -99.0f;
+            xyPtr[1] = -99.0f;
+        }
+
+        xyPtr += xyChSize;
+        xyPrevPtr += xyChSize;
+    }
+
+    //Copy remaining coordinate
+    if((width-1) % coordMult){
+        dstWidthMod = (double)coordMult / (double)((width-1) % coordMult);
+        xyPtr -= xyChSize;
+        xyPrevPtr -= xyChSize;
+    } else {
+        xyPtr -= xyChSize*2;
+        xyPrevPtr -= xyChSize*2;
+    }
+
+    if(lastRow) {
+        double origX = rowSrcX[width-1] - srcXOff;
+        double origY = rowSrcY[width-1] - srcYOff;
+        double a = 1.0, b = 1.0;
+
+        // Calculate the needed x/y values using an equation from the OpenCL Spec
+        // section 8.2, solving for Ti1j1
+        if((width -1) % coordMult)
+            a = ((width -1) % coordMult)/(double)coordMult;
+
+        if((height-1) % coordMult)
+            b = ((height-1) % coordMult)/(double)coordMult;
+
+        xyPtr[xyChSize  ] = (float) ((((1.0 - a) * (1.0 - b) * xyPrevPtr[0]
+                              + a * (1.0 - b) * xyPrevPtr[xyChSize]
+                              + (1.0 - a) * b * xyPtr[0]) - origX)/(-a * b));
+
+        xyPtr[xyChSize+1] = (float) ((((1.0 - a) * (1.0 - b) * xyPrevPtr[1]
+                              + a * (1.0 - b) * xyPrevPtr[xyChSize+1]
+                              + (1.0 - a) * b * xyPtr[1]) - origY)/(-a * b));
+    } else {
+        //Adjust last coordinate so interpolator returns correct value
+        xyPtr[xyChSize  ] = (float) (dstWidthMod * (rowSrcX[width-1] - srcXOff - xyPtr[0]) + xyPtr[0]);
+        xyPtr[xyChSize+1] = (float) (dstWidthMod * (rowSrcY[width-1] - srcYOff - xyPtr[1]) + xyPtr[1]);
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Copies all data to the device RAM, frees the host RAM, runs the
+ appropriate resampling kernel, mallocs output space, & copies the data
+ back from the device RAM for each band. Also check to make sure that
+ setRow*() was called the appropriate number of times to init all image
+ data.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+cl_int GDALWarpKernelOpenCL_runResamp(struct oclWarper *warper,
+                                      float *unifiedSrcDensity,
+                                      unsigned int *unifiedSrcValid,
+                                      float *dstDensity,
+                                      unsigned int *dstValid,
+                                      double dfXScale, double dfYScale,
+                                      double dfXFilter, double dfYFilter,
+                                      int nXRadius, int nYRadius,
+                                      int nFiltInitX, int nFiltInitY)
+{
+    int i, nextBandNum = 0, chSize = 1;
+    cl_int err = CL_SUCCESS;
+    cl_mem xy, unifiedSrcDensityCL, unifiedSrcValidCL;
+    cl_mem dstDensityCL, dstValidCL, dstNoDataRealCL;
+    cl_mem useBandSrcValidCL, nBandSrcValidCL;
+    size_t groupSize, wordSize = 0;
+    cl_kernel kern = NULL;
+    cl_channel_order chOrder;
+
+    warper->useUnifiedSrcDensity = unifiedSrcDensity != NULL;
+    warper->useUnifiedSrcValid = unifiedSrcValid != NULL;
+
+    //Check the word size
+    switch (warper->imageFormat) {
+        case CL_FLOAT:
+            wordSize = sizeof(float);
+            break;
+        case CL_SNORM_INT8:
+            wordSize = sizeof(char);
+            break;
+        case CL_UNORM_INT8:
+            wordSize = sizeof(unsigned char);
+            break;
+        case CL_SNORM_INT16:
+            wordSize = sizeof(short);
+            break;
+        case CL_UNORM_INT16:
+            wordSize = sizeof(unsigned short);
+            break;
+    }
+
+    //Compile the kernel; the invariants are being compiled into the code
+    if (!warper->useVec || warper->numBands % 4) {
+        warper->kern1 = get_kernel(warper, FALSE,
+                                   dfXScale, dfYScale, dfXFilter, dfYFilter,
+                                   nXRadius, nYRadius, nFiltInitX, nFiltInitY, &err);
+        handleErr(err);
+    }
+    if (warper->useVec){
+        warper->kern4 = get_kernel(warper, TRUE,
+                                   dfXScale, dfYScale, dfXFilter, dfYFilter,
+                                   nXRadius, nYRadius, nFiltInitX, nFiltInitY, &err);
+        handleErr(err);
+    }
+
+    //Copy coord data to the device
+    handleErr(err = set_coord_data(warper, &xy));
+
+    //Copy unified density & valid data
+    handleErr(err = set_unified_data(warper, &unifiedSrcDensityCL, &unifiedSrcValidCL,
+                                     unifiedSrcDensity, unifiedSrcValid,
+                                     &useBandSrcValidCL, &nBandSrcValidCL));
+
+    //Copy output density & valid data
+    handleErr(set_dst_data(warper, &dstDensityCL, &dstValidCL, &dstNoDataRealCL,
+                           dstDensity, dstValid, warper->fDstNoDataReal));
+
+    //What's the recommended group size?
+    if (warper->useVec) {
+        // Start with the vector kernel
+        handleErr(clGetKernelWorkGroupInfo(warper->kern4, warper->dev,
+                                           CL_KERNEL_WORK_GROUP_SIZE,
+                                           sizeof(size_t), &groupSize, NULL));
+        kern = warper->kern4;
+        chSize = warper->imgChSize4;
+        chOrder = warper->imgChOrder4;
+    } else {
+        // We're only using the float kernel
+        handleErr(clGetKernelWorkGroupInfo(warper->kern1, warper->dev,
+                                           CL_KERNEL_WORK_GROUP_SIZE,
+                                           sizeof(size_t), &groupSize, NULL));
+        kern = warper->kern1;
+        chSize = warper->imgChSize1;
+        chOrder = warper->imgChOrder1;
+    }
+
+    //Loop over each image
+    for (i = 0; i < warper->numImages; ++i)
+    {
+        cl_mem srcImag, srcReal;
+        cl_mem dstReal, dstImag;
+        int bandNum = nextBandNum;
+
+        //Switch kernels if needed
+        if (warper->useVec && nextBandNum < warper->numBands - warper->numBands % 4) {
+            nextBandNum += 4;
+        } else {
+            if (kern == warper->kern4) {
+                handleErr(clGetKernelWorkGroupInfo(warper->kern1, warper->dev,
+                                                   CL_KERNEL_WORK_GROUP_SIZE,
+                                                   sizeof(size_t), &groupSize, NULL));
+                kern = warper->kern1;
+                chSize = warper->imgChSize1;
+                chOrder = warper->imgChOrder1;
+            }
+            ++nextBandNum;
+        }
+
+        //Create & copy the source image
+        handleErr(err = set_src_rast_data(warper, i, chSize*wordSize, chOrder,
+                                          &srcReal, &srcImag));
+
+        //Create & copy the output image
+        if (kern == warper->kern1) {
+            handleErr(err = set_dst_rast_data(warper, i, wordSize, &dstReal, &dstImag));
+        } else {
+            handleErr(err = set_dst_rast_data(warper, i, wordSize*4, &dstReal, &dstImag));
+        }
+
+        //Set the bandNum
+        handleErr(err = clSetKernelArg(kern, 12, sizeof(int), &bandNum));
+
+        //Run the kernel
+        handleErr(err = execute_kern(warper, kern, groupSize));
+
+        //Free loop CL mem
+        handleErr(err = clReleaseMemObject(srcReal));
+        handleErr(err = clReleaseMemObject(srcImag));
+
+        //Copy the back output results
+        if (kern == warper->kern1) {
+            handleErr(err = get_dst_rast_data(warper, i, wordSize, dstReal, dstImag));
+        } else {
+            handleErr(err = get_dst_rast_data(warper, i, wordSize*4, dstReal, dstImag));
+        }
+
+        //Free remaining CL mem
+        handleErr(err = clReleaseMemObject(dstReal));
+        handleErr(err = clReleaseMemObject(dstImag));
+    }
+
+    //Free remaining CL mem
+    handleErr(err = clReleaseMemObject(xy));
+    handleErr(err = clReleaseMemObject(unifiedSrcDensityCL));
+    handleErr(err = clReleaseMemObject(unifiedSrcValidCL));
+    handleErr(err = clReleaseMemObject(useBandSrcValidCL));
+    handleErr(err = clReleaseMemObject(nBandSrcValidCL));
+    handleErr(err = clReleaseMemObject(dstDensityCL));
+    handleErr(err = clReleaseMemObject(dstValidCL));
+    handleErr(err = clReleaseMemObject(dstNoDataRealCL));
+
+    return CL_SUCCESS;
+}
+
+/*
+ Sets pointers to the floating point data in the warper. The pointers
+ are internal to the warper structure, so don't free() them. If the imag
+ channel is in use, it will receive a pointer. Otherwise it'll be set to NULL.
+ These are pointers to floating point data, so the caller will need to
+ manipulate the output as appropriate before saving the data.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+cl_int GDALWarpKernelOpenCL_getRow(struct oclWarper *warper,
+                                   void **rowReal, void **rowImag,
+                                   int rowNum, int bandNum)
+{
+    int memOff = rowNum * warper->dstWidth;
+    int imgNum = bandNum;
+
+    if (warper->useVec && bandNum < warper->numBands - warper->numBands % 4) {
+        memOff += warper->dstWidth * warper->dstHeight * (bandNum % 4);
+        imgNum = bandNum / 4;
+    } else if(warper->useVec) {
+        imgNum = bandNum / 4 + bandNum % 4;
+    }
+
+    //Return pointers into the warper's data
+    switch (warper->imageFormat) {
+        case CL_FLOAT:
+            (*rowReal) = &(warper->dstRealWork.f[imgNum][memOff]);
+            break;
+        case CL_SNORM_INT8:
+            (*rowReal) = &(warper->dstRealWork.c[imgNum][memOff]);
+            break;
+        case CL_UNORM_INT8:
+            (*rowReal) = &(warper->dstRealWork.uc[imgNum][memOff]);
+            break;
+        case CL_SNORM_INT16:
+            (*rowReal) = &(warper->dstRealWork.s[imgNum][memOff]);
+            break;
+        case CL_UNORM_INT16:
+            (*rowReal) = &(warper->dstRealWork.us[imgNum][memOff]);
+            break;
+    }
+
+    if (warper->dstImagWorkCL == NULL) {
+        (*rowImag) = NULL;
+    } else {
+        switch (warper->imageFormat) {
+            case CL_FLOAT:
+                (*rowImag) = &(warper->dstImagWork.f[imgNum][memOff]);
+                break;
+            case CL_SNORM_INT8:
+                (*rowImag) = &(warper->dstImagWork.c[imgNum][memOff]);
+                break;
+            case CL_UNORM_INT8:
+                (*rowImag) = &(warper->dstImagWork.uc[imgNum][memOff]);
+                break;
+            case CL_SNORM_INT16:
+                (*rowImag) = &(warper->dstImagWork.s[imgNum][memOff]);
+                break;
+            case CL_UNORM_INT16:
+                (*rowImag) = &(warper->dstImagWork.us[imgNum][memOff]);
+                break;
+        }
+    }
+
+    return CL_SUCCESS;
+}
+
+/*
+ Free the OpenCL warper environment. It should check everything for NULL, so
+ be sure to mark free()ed pointers as NULL or it'll be double free()ed.
+
+ Returns CL_SUCCESS on success and other CL_* errors when something goes wrong.
+ */
+cl_int GDALWarpKernelOpenCL_deleteEnv(struct oclWarper *warper)
+{
+    int i;
+    cl_int err = CL_SUCCESS;
+
+    for (i = 0; i < warper->numImages; ++i) {
+        // Run free!!
+        void* dummy = NULL;
+        if( warper->realWork.v )
+            freeCLMem(warper->realWorkCL[i], warper->realWork.v[i]);
+        else
+            freeCLMem(warper->realWorkCL[i], dummy);
+        if( warper->realWork.v )
+            freeCLMem(warper->dstRealWorkCL[i], warper->dstRealWork.v[i]);
+        else
+            freeCLMem(warper->dstRealWorkCL[i], dummy);
+
+        //(As applicable)
+        if(warper->imagWorkCL != NULL && warper->imagWork.v != NULL && warper->imagWork.v[i] != NULL) {
+            freeCLMem(warper->imagWorkCL[i], warper->imagWork.v[i]);
+        }
+        if(warper->dstImagWorkCL != NULL && warper->dstImagWork.v != NULL && warper->dstImagWork.v[i] != NULL) {
+            freeCLMem(warper->dstImagWorkCL[i], warper->dstImagWork.v[i]);
+        }
+    }
+
+    //Free cl_mem
+    freeCLMem(warper->useBandSrcValidCL, warper->useBandSrcValid);
+    freeCLMem(warper->nBandSrcValidCL, warper->nBandSrcValid);
+    freeCLMem(warper->xyWorkCL, warper->xyWork);
+    freeCLMem(warper->fDstNoDataRealCL, warper->fDstNoDataReal);
+
+    //Free pointers to cl_mem*
+    if (warper->realWorkCL != NULL)
+        CPLFree(warper->realWorkCL);
+    if (warper->dstRealWorkCL != NULL)
+        CPLFree(warper->dstRealWorkCL);
+
+    if (warper->imagWorkCL != NULL)
+        CPLFree(warper->imagWorkCL);
+    if (warper->dstImagWorkCL != NULL)
+        CPLFree(warper->dstImagWorkCL);
+
+    if (warper->realWork.v != NULL)
+        CPLFree(warper->realWork.v);
+    if (warper->dstRealWork.v != NULL)
+        CPLFree(warper->dstRealWork.v);
+
+    if (warper->imagWork.v != NULL)
+        CPLFree(warper->imagWork.v);
+    if (warper->dstImagWork.v != NULL)
+        CPLFree(warper->dstImagWork.v);
+
+    //Free OpenCL structures
+    if (warper->kern1 != NULL)
+        clReleaseKernel(warper->kern1);
+    if (warper->kern4 != NULL)
+        clReleaseKernel(warper->kern4);
+    if (warper->queue != NULL)
+        clReleaseCommandQueue(warper->queue);
+    if (warper->context != NULL)
+        clReleaseContext(warper->context);
+
+    CPLFree(warper);
+
+    return CL_SUCCESS;
+}
+
+#endif /* defined(HAVE_OPENCL) */
diff --git a/alg/gdalwarpkernel_opencl.h b/alg/gdalwarpkernel_opencl.h
index 003b0c1..0f04517 100644
--- a/alg/gdalwarpkernel_opencl.h
+++ b/alg/gdalwarpkernel_opencl.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalwarpkernel_opencl.h 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: gdalwarpkernel_opencl.h 34485 2016-06-30 22:42:39Z goatbar $
  *
  * Project:  OpenCL Image Reprojector
  * Purpose:  Implementation of the GDALWarpKernel reprojector in OpenCL.
@@ -127,7 +127,7 @@ struct oclWarper {
     cl_channel_order imgChOrder1;
     unsigned int imgChSize4;
     cl_channel_order imgChOrder4;
-	char    useVec;
+    char    useVec;
 
     cl_mem useBandSrcValidCL;
     char *useBandSrcValid;
diff --git a/alg/gdalwarpoperation.cpp b/alg/gdalwarpoperation.cpp
index bfc4f0a..cc9fd64 100644
--- a/alg/gdalwarpoperation.cpp
+++ b/alg/gdalwarpoperation.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalwarpoperation.cpp 33918 2016-04-08 14:02:35Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Implementation of the GDALWarpOperation class.
@@ -28,12 +27,29 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdalwarper.h"
-#include "cpl_string.h"
+
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+
+#include "cpl_config.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
 
-CPL_CVSID("$Id: gdalwarpoperation.cpp 33918 2016-04-08 14:02:35Z rouault $");
+CPL_CVSID("$Id: gdalwarpoperation.cpp 37002 2016-12-22 23:15:16Z goatbar $");
 
 struct _GDALWarpChunk {
     int dx, dy, dsx, dsy;
@@ -118,22 +134,17 @@ GDALWarpKernel.
 /*                         GDALWarpOperation()                          */
 /************************************************************************/
 
-GDALWarpOperation::GDALWarpOperation()
-
-{
-    psOptions = NULL;
-
-    hIOMutex = NULL;
-    hWarpMutex = NULL;
-
-    nChunkListCount = 0;
-    nChunkListMax = 0;
-    pasChunkList = NULL;
-
-    bReportTimings = FALSE;
-    nLastTimeReported = 0;
-    psThreadData = NULL;
-}
+GDALWarpOperation::GDALWarpOperation() :
+    psOptions(NULL),
+    hIOMutex(NULL),
+    hWarpMutex(NULL),
+    nChunkListCount(0),
+    nChunkListMax(0),
+    pasChunkList(NULL),
+    bReportTimings(FALSE),
+    nLastTimeReported(0),
+    psThreadData(NULL)
+{}
 
 /************************************************************************/
 /*                         ~GDALWarpOperation()                         */
@@ -159,6 +170,7 @@ GDALWarpOperation::~GDALWarpOperation()
 /*                             GetOptions()                             */
 /************************************************************************/
 
+/** Return warp options */
 const GDALWarpOptions *GDALWarpOperation::GetOptions()
 
 {
@@ -189,16 +201,16 @@ int GDALWarpOperation::ValidateOptions()
     if( psOptions == NULL )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  no options currently initialized." );
+                  "GDALWarpOptions.Validate(): "
+                  "no options currently initialized." );
         return FALSE;
     }
 
     if( psOptions->dfWarpMemoryLimit < 100000.0 )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  dfWarpMemoryLimit=%g is unreasonably small.",
+                  "GDALWarpOptions.Validate(): "
+                  "dfWarpMemoryLimit=%g is unreasonably small.",
                   psOptions->dfWarpMemoryLimit );
         return FALSE;
     }
@@ -217,18 +229,18 @@ int GDALWarpOperation::ValidateOptions()
         && psOptions->eResampleAlg != GRA_Q3)
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  eResampleArg=%d is not a supported value.",
+                  "GDALWarpOptions.Validate(): "
+                  "eResampleArg=%d is not a supported value.",
                   psOptions->eResampleAlg );
         return FALSE;
     }
 
-    if( (int) psOptions->eWorkingDataType < 1
-        || (int) psOptions->eWorkingDataType >= GDT_TypeCount )
+    if( static_cast<int>(psOptions->eWorkingDataType) < 1 ||
+        static_cast<int>(psOptions->eWorkingDataType) >= GDT_TypeCount )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  eWorkingDataType=%d is not a supported value.",
+                  "GDALWarpOptions.Validate(): "
+                  "eWorkingDataType=%d is not a supported value.",
                   psOptions->eWorkingDataType );
         return FALSE;
     }
@@ -236,32 +248,32 @@ int GDALWarpOperation::ValidateOptions()
     if( psOptions->hSrcDS == NULL )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  hSrcDS is not set." );
+                  "GDALWarpOptions.Validate(): "
+                  "hSrcDS is not set." );
         return FALSE;
     }
 
     if( psOptions->nBandCount == 0 )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  nBandCount=0, no bands configured!" );
+                  "GDALWarpOptions.Validate(): "
+                  "nBandCount=0, no bands configured!" );
         return FALSE;
     }
 
     if( psOptions->panSrcBands == NULL )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  panSrcBands is NULL." );
+                  "GDALWarpOptions.Validate(): "
+                  "panSrcBands is NULL." );
         return FALSE;
     }
 
     if( psOptions->hDstDS != NULL && psOptions->panDstBands == NULL )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  panDstBands is NULL." );
+                  "GDALWarpOptions.Validate(): "
+                  "panDstBands is NULL." );
         return FALSE;
     }
 
@@ -303,8 +315,8 @@ int GDALWarpOperation::ValidateOptions()
     if( psOptions->nBandCount == 0 )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  nBandCount=0, no bands configured!" );
+                  "GDALWarpOptions.Validate(): "
+                  "nBandCount=0, no bands configured!" );
         return FALSE;
     }
 
@@ -312,24 +324,24 @@ int GDALWarpOperation::ValidateOptions()
         && psOptions->padfSrcNoDataImag == NULL )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  padfSrcNoDataReal set, but padfSrcNoDataImag not set." );
+                  "GDALWarpOptions.Validate(): "
+                  "padfSrcNoDataReal set, but padfSrcNoDataImag not set." );
         return FALSE;
     }
 
     if( psOptions->pfnProgress == NULL )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  pfnProgress is NULL." );
+                  "GDALWarpOptions.Validate(): "
+                  "pfnProgress is NULL." );
         return FALSE;
     }
 
     if( psOptions->pfnTransformer == NULL )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-                  "GDALWarpOptions.Validate()\n"
-                  "  pfnTransformer is NULL." );
+                  "GDALWarpOptions.Validate(): "
+                  "pfnTransformer is NULL." );
         return FALSE;
     }
 
@@ -340,16 +352,16 @@ int GDALWarpOperation::ValidateOptions()
                                     "SAMPLE_STEPS" )) < 2 )
         {
             CPLError( CE_Failure, CPLE_IllegalArg,
-                      "GDALWarpOptions.Validate()\n"
-                      "  SAMPLE_STEPS warp option has illegal value." );
+                      "GDALWarpOptions.Validate(): "
+                      "SAMPLE_STEPS warp option has illegal value." );
             return FALSE;
         }
     }
 
     if( psOptions->nSrcAlphaBand > 0)
     {
-        if ( psOptions->hSrcDS == NULL ||
-             psOptions->nSrcAlphaBand > GDALGetRasterCount(psOptions->hSrcDS) )
+        if( psOptions->hSrcDS == NULL ||
+            psOptions->nSrcAlphaBand > GDALGetRasterCount(psOptions->hSrcDS) )
         {
             CPLError( CE_Failure, CPLE_IllegalArg,
                       "nSrcAlphaBand = %d ... out of range for dataset.",
@@ -360,8 +372,8 @@ int GDALWarpOperation::ValidateOptions()
 
     if( psOptions->nDstAlphaBand > 0)
     {
-        if ( psOptions->hDstDS == NULL ||
-             psOptions->nDstAlphaBand > GDALGetRasterCount(psOptions->hDstDS) )
+        if( psOptions->hDstDS == NULL ||
+            psOptions->nDstAlphaBand > GDALGetRasterCount(psOptions->hDstDS) )
         {
             CPLError( CE_Failure, CPLE_IllegalArg,
                       "nDstAlphaBand = %d ... out of range for dataset.",
@@ -374,8 +386,8 @@ int GDALWarpOperation::ValidateOptions()
         && psOptions->pfnSrcDensityMaskFunc != NULL )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-               "GDALWarpOptions.Validate()\n"
-               "  pfnSrcDensityMaskFunc provided as well as a SrcAlphaBand." );
+                  "GDALWarpOptions.Validate(): "
+                  "pfnSrcDensityMaskFunc provided as well as a SrcAlphaBand." );
         return FALSE;
     }
 
@@ -383,8 +395,8 @@ int GDALWarpOperation::ValidateOptions()
         && psOptions->pfnDstDensityMaskFunc != NULL )
     {
         CPLError( CE_Failure, CPLE_IllegalArg,
-               "GDALWarpOptions.Validate()\n"
-               "  pfnDstDensityMaskFunc provided as well as a DstAlphaBand." );
+                  "GDALWarpOptions.Validate(): "
+                  "pfnDstDensityMaskFunc provided as well as a DstAlphaBand." );
         return FALSE;
     }
 
@@ -392,6 +404,37 @@ int GDALWarpOperation::ValidateOptions()
 }
 
 /************************************************************************/
+/*                            SetAlphaMax()                             */
+/************************************************************************/
+
+static void SetAlphaMax( GDALWarpOptions* psOptions,
+                         GDALRasterBandH hBand,
+                         const char* pszKey )
+{
+    const char* pszNBits =
+        GDALGetMetadataItem(hBand, "NBITS", "IMAGE_STRUCTURE");
+    const char *pszAlphaMax = NULL;
+    if( pszNBits )
+    {
+        pszAlphaMax = CPLSPrintf("%u", (1U << atoi(pszNBits)) - 1U);
+    }
+    else if( GDALGetRasterDataType( hBand ) == GDT_Int16 )
+    {
+        pszAlphaMax = "32767";
+    }
+    else if( GDALGetRasterDataType( hBand ) == GDT_UInt16 )
+    {
+        pszAlphaMax = "65535";
+    }
+
+    if( pszAlphaMax != NULL )
+        psOptions->papszWarpOptions = CSLSetNameValue(
+            psOptions->papszWarpOptions, pszKey, pszAlphaMax);
+    else
+        CPLDebug("WARP", "SetAlphaMax: AlphaMax not set.");
+}
+
+/************************************************************************/
 /*                             Initialize()                             */
 /************************************************************************/
 
@@ -417,8 +460,6 @@ int GDALWarpOperation::ValidateOptions()
 CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
 
 {
-    CPLErr eErr = CE_None;
-
 /* -------------------------------------------------------------------- */
 /*      Copy the passed in options.                                     */
 /* -------------------------------------------------------------------- */
@@ -438,16 +479,14 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
         && GDALGetRasterCount( psOptions->hSrcDS )
         == GDALGetRasterCount( psOptions->hDstDS ) )
     {
-        int  i;
-
         psOptions->nBandCount = GDALGetRasterCount( psOptions->hSrcDS );
 
-        psOptions->panSrcBands = (int *)
-            CPLMalloc(sizeof(int) * psOptions->nBandCount );
-        psOptions->panDstBands = (int *)
-            CPLMalloc(sizeof(int) * psOptions->nBandCount );
+        psOptions->panSrcBands = static_cast<int *>(
+            CPLMalloc(sizeof(int) * psOptions->nBandCount));
+        psOptions->panDstBands = static_cast<int *>(
+            CPLMalloc(sizeof(int) * psOptions->nBandCount));
 
-        for( i = 0; i < psOptions->nBandCount; i++ )
+        for( int i = 0; i < psOptions->nBandCount; i++ )
         {
             psOptions->panSrcBands[i] = i+1;
             psOptions->panDstBands[i] = i+1;
@@ -467,10 +506,9 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
         && psOptions->hDstDS != NULL
         && psOptions->nBandCount >= 1 )
     {
-        int iBand;
         psOptions->eWorkingDataType = GDT_Byte;
 
-        for( iBand = 0; iBand < psOptions->nBandCount; iBand++ )
+        for( int iBand = 0; iBand < psOptions->nBandCount; iBand++ )
         {
             GDALRasterBandH hDstBand = GDALGetRasterBand(
                 psOptions->hDstDS, psOptions->panDstBands[iBand] );
@@ -485,38 +523,38 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
             if( hSrcBand != NULL
                 && psOptions->padfSrcNoDataReal != NULL )
             {
-                int bMergeSource = FALSE;
+                bool bMergeSource = false;
 
                 if( psOptions->padfSrcNoDataImag != NULL
                     && psOptions->padfSrcNoDataImag[iBand] != 0.0
                     && !GDALDataTypeIsComplex( psOptions->eWorkingDataType ) )
-                    bMergeSource = TRUE;
+                    bMergeSource = true;
                 else if( psOptions->padfSrcNoDataReal[iBand] < 0.0
                          && (psOptions->eWorkingDataType == GDT_Byte
                              || psOptions->eWorkingDataType == GDT_UInt16
                              || psOptions->eWorkingDataType == GDT_UInt32) )
-                    bMergeSource = TRUE;
+                    bMergeSource = true;
                 else if( psOptions->padfSrcNoDataReal[iBand] < -32768.0
                          && psOptions->eWorkingDataType == GDT_Int16 )
-                    bMergeSource = TRUE;
+                    bMergeSource = true;
                 else if( psOptions->padfSrcNoDataReal[iBand] < -2147483648.0
                          && psOptions->eWorkingDataType == GDT_Int32 )
-                    bMergeSource = TRUE;
+                    bMergeSource = true;
                 else if( psOptions->padfSrcNoDataReal[iBand] > 256
                          && psOptions->eWorkingDataType == GDT_Byte )
-                    bMergeSource = TRUE;
+                    bMergeSource = true;
                 else if( psOptions->padfSrcNoDataReal[iBand] > 32767
                          && psOptions->eWorkingDataType == GDT_Int16 )
-                    bMergeSource = TRUE;
+                    bMergeSource = true;
                 else if( psOptions->padfSrcNoDataReal[iBand] > 65535
                          && psOptions->eWorkingDataType == GDT_UInt16 )
-                    bMergeSource = TRUE;
+                    bMergeSource = true;
                 else if( psOptions->padfSrcNoDataReal[iBand] > 2147483648.0
                          && psOptions->eWorkingDataType == GDT_Int32 )
-                    bMergeSource = TRUE;
+                    bMergeSource = true;
                 else if( psOptions->padfSrcNoDataReal[iBand] > 4294967295.0
                          && psOptions->eWorkingDataType == GDT_UInt32 )
-                    bMergeSource = TRUE;
+                    bMergeSource = true;
 
                 if( bMergeSource )
                     psOptions->eWorkingDataType =
@@ -541,8 +579,8 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
 /* -------------------------------------------------------------------- */
 /*      Are we doing timings?                                           */
 /* -------------------------------------------------------------------- */
-    bReportTimings = CSLFetchBoolean( psOptions->papszWarpOptions,
-                                      "REPORT_TIMINGS", FALSE );
+    bReportTimings = CPLFetchBool( psOptions->papszWarpOptions,
+                                   "REPORT_TIMINGS", false );
 
 /* -------------------------------------------------------------------- */
 /*      Support creating cutline from text warpoption.                  */
@@ -550,6 +588,7 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
     const char *pszCutlineWKT =
         CSLFetchNameValue( psOptions->papszWarpOptions, "CUTLINE" );
 
+    CPLErr eErr = CE_None;
     if( pszCutlineWKT )
     {
         if( OGR_G_CreateFromWkt( (char **) &pszCutlineWKT, NULL,
@@ -570,13 +609,43 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Set SRC_ALPHA_MAX if not provided.                              */
+/* -------------------------------------------------------------------- */
+    if( psOptions->hSrcDS != NULL &&
+        psOptions->nSrcAlphaBand > 0 &&
+        psOptions->nSrcAlphaBand <= GDALGetRasterCount(psOptions->hSrcDS) &&
+        CSLFetchNameValue( psOptions->papszWarpOptions,
+                           "SRC_ALPHA_MAX" ) == NULL )
+    {
+        GDALRasterBandH hSrcAlphaBand = GDALGetRasterBand(
+                          psOptions->hSrcDS, psOptions->nSrcAlphaBand);
+        SetAlphaMax( psOptions, hSrcAlphaBand, "SRC_ALPHA_MAX" );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Set DST_ALPHA_MAX if not provided.                              */
+/* -------------------------------------------------------------------- */
+    if( psOptions->hDstDS != NULL &&
+        psOptions->nDstAlphaBand > 0 &&
+        psOptions->nDstAlphaBand <= GDALGetRasterCount(psOptions->hDstDS) &&
+        CSLFetchNameValue( psOptions->papszWarpOptions,
+                           "DST_ALPHA_MAX" ) == NULL )
+    {
+        GDALRasterBandH hDstAlphaBand = GDALGetRasterBand(
+            psOptions->hDstDS, psOptions->nDstAlphaBand);
+        SetAlphaMax( psOptions, hDstAlphaBand, "DST_ALPHA_MAX" );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      If the options don't validate, then wipe them.                  */
 /* -------------------------------------------------------------------- */
     if( !ValidateOptions() )
         eErr = CE_Failure;
 
     if( eErr != CE_None )
+    {
         WipeOptions();
+    }
     else
     {
         psThreadData = GWKThreadsCreate(psOptions->papszWarpOptions,
@@ -600,16 +669,14 @@ CPLErr GDALWarpOperation::Initialize( const GDALWarpOptions *psNewOptions )
 GDALWarpOperationH GDALCreateWarpOperation(
     const GDALWarpOptions *psNewOptions )
 {
-    GDALWarpOperation *poOperation;
-
-    poOperation = new GDALWarpOperation;
-    if ( poOperation->Initialize( psNewOptions ) != CE_None )
+    GDALWarpOperation *poOperation = new GDALWarpOperation;
+    if( poOperation->Initialize( psNewOptions ) != CE_None )
     {
         delete poOperation;
         return NULL;
     }
 
-    return (GDALWarpOperationH)poOperation;
+    return reinterpret_cast<GDALWarpOperationH>(poOperation);
 }
 
 /************************************************************************/
@@ -622,7 +689,7 @@ GDALWarpOperationH GDALCreateWarpOperation(
 
 void GDALDestroyWarpOperation( GDALWarpOperationH hOperation )
 {
-    if ( hOperation )
+    if( hOperation )
         delete static_cast<GDALWarpOperation *>(hOperation);
 }
 
@@ -632,15 +699,15 @@ void GDALDestroyWarpOperation( GDALWarpOperationH hOperation )
 
 static int OrderWarpChunk(const void* _a, const void *_b)
 {
-    const GDALWarpChunk* a = (const GDALWarpChunk* )_a;
-    const GDALWarpChunk* b = (const GDALWarpChunk* )_b;
-    if (a->dy < b->dy)
+    const GDALWarpChunk* a = static_cast<const GDALWarpChunk *>(_a);
+    const GDALWarpChunk* b = static_cast<const GDALWarpChunk *>(_b);
+    if( a->dy < b->dy )
         return -1;
-    else if (a->dy > b->dy)
+    else if( a->dy > b->dy )
         return 1;
-    else if (a->dx < b->dx)
+    else if( a->dx < b->dx )
         return -1;
-    else if (a->dx > b->dx)
+    else if( a->dx > b->dx )
         return 1;
     else
         return 0;
@@ -679,20 +746,24 @@ CPLErr GDALWarpOperation::ChunkAndWarpImage(
     WipeChunkList();
     CollectChunkList( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
 
-    /* Sort chucks from top to bottom, and for equal y, from left to right */
+    // Sort chucks from top to bottom, and for equal y, from left to right.
+    // TODO(schwehr): Use std::sort.
     if( pasChunkList )
-        qsort(pasChunkList, nChunkListCount, sizeof(GDALWarpChunk), OrderWarpChunk);
+        qsort(pasChunkList, nChunkListCount, sizeof(GDALWarpChunk),
+              OrderWarpChunk);
 
 /* -------------------------------------------------------------------- */
 /*      Total up output pixels to process.                              */
 /* -------------------------------------------------------------------- */
-    int iChunk;
-    double dfTotalPixels = 0;
+    double dfTotalPixels = 0.0;
 
-    for( iChunk = 0; pasChunkList != NULL && iChunk < nChunkListCount; iChunk++ )
+    for( int iChunk = 0;
+         pasChunkList != NULL && iChunk < nChunkListCount;
+         iChunk++ )
     {
         GDALWarpChunk *pasThisChunk = pasChunkList + iChunk;
-        double dfChunkPixels = pasThisChunk->dsx * (double) pasThisChunk->dsy;
+        const double dfChunkPixels =
+          pasThisChunk->dsx * static_cast<double>(pasThisChunk->dsy);
 
         dfTotalPixels += dfChunkPixels;
     }
@@ -703,21 +774,24 @@ CPLErr GDALWarpOperation::ChunkAndWarpImage(
 /* -------------------------------------------------------------------- */
     double dfPixelsProcessed=0.0;
 
-    for( iChunk = 0; pasChunkList != NULL && iChunk < nChunkListCount; iChunk++ )
+    for( int iChunk = 0;
+         pasChunkList != NULL && iChunk < nChunkListCount;
+         iChunk++ )
     {
         GDALWarpChunk *pasThisChunk = pasChunkList + iChunk;
-        double dfChunkPixels = pasThisChunk->dsx * (double) pasThisChunk->dsy;
-        CPLErr eErr;
+        const double dfChunkPixels =
+            pasThisChunk->dsx * static_cast<double>(pasThisChunk->dsy);
 
-        double dfProgressBase = dfPixelsProcessed / dfTotalPixels;
-        double dfProgressScale = dfChunkPixels / dfTotalPixels;
+        const double dfProgressBase = dfPixelsProcessed / dfTotalPixels;
+        const double dfProgressScale = dfChunkPixels / dfTotalPixels;
 
-        eErr = WarpRegion( pasThisChunk->dx, pasThisChunk->dy,
-                           pasThisChunk->dsx, pasThisChunk->dsy,
-                           pasThisChunk->sx, pasThisChunk->sy,
-                           pasThisChunk->ssx, pasThisChunk->ssy,
-                           pasThisChunk->sExtraSx, pasThisChunk->sExtraSy,
-                           dfProgressBase, dfProgressScale);
+        CPLErr eErr =
+            WarpRegion(pasThisChunk->dx, pasThisChunk->dy,
+                       pasThisChunk->dsx, pasThisChunk->dsy,
+                       pasThisChunk->sx, pasThisChunk->sy,
+                       pasThisChunk->ssx, pasThisChunk->ssy,
+                       pasThisChunk->sExtraSx, pasThisChunk->sExtraSy,
+                       dfProgressBase, dfProgressScale);
 
         if( eErr != CE_None )
             return eErr;
@@ -745,7 +819,7 @@ CPLErr GDALChunkAndWarpImage( GDALWarpOperationH hOperation,
 {
     VALIDATE_POINTER1( hOperation, "GDALChunkAndWarpImage", CE_Failure );
 
-    return ( (GDALWarpOperation *)hOperation )->
+    return reinterpret_cast<GDALWarpOperation *>(hOperation) ->
         ChunkAndWarpImage( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
 }
 
@@ -768,7 +842,6 @@ typedef struct
     CPLCond           *hCond;
 } ChunkThreadData;
 
-
 static void ChunkThreadMain( void *pThreadData )
 
 {
@@ -787,7 +860,7 @@ static void ChunkThreadMain( void *pThreadData )
     }
     else
     {
-        if (psData->hCond != NULL)
+        if( psData->hCond != NULL )
         {
             CPLAcquireMutex( psData->hCondMutex, 1.0 );
             psData->bIOMutexTaken = TRUE;
@@ -800,7 +873,8 @@ static void ChunkThreadMain( void *pThreadData )
                                     pasChunkInfo->dsx, pasChunkInfo->dsy,
                                     pasChunkInfo->sx, pasChunkInfo->sy,
                                     pasChunkInfo->ssx, pasChunkInfo->ssy,
-                                    pasChunkInfo->sExtraSx, pasChunkInfo->sExtraSy,
+                                    pasChunkInfo->sExtraSx,
+                                    pasChunkInfo->sExtraSy,
                                     psData->dfProgressBase,
                                     psData->dfProgressScale);
 
@@ -855,28 +929,30 @@ CPLErr GDALWarpOperation::ChunkAndWarpMulti(
     WipeChunkList();
     CollectChunkList( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
 
-    /* Sort chucks from top to bottom, and for equal y, from left to right */
+    // Sort chucks from top to bottom, and for equal y, from left to right.
+    // TODO(schwehr): Use std::sort.
     if( pasChunkList )
-        qsort(pasChunkList, nChunkListCount, sizeof(GDALWarpChunk), OrderWarpChunk);
+        qsort(pasChunkList, nChunkListCount, sizeof(GDALWarpChunk),
+              OrderWarpChunk);
 
 /* -------------------------------------------------------------------- */
 /*      Process them one at a time, updating the progress               */
 /*      information for each region.                                    */
 /* -------------------------------------------------------------------- */
-    ChunkThreadData volatile asThreadData[2];
+    ChunkThreadData volatile asThreadData[2] = {};
     memset((void*)&asThreadData, 0, sizeof(asThreadData));
     asThreadData[0].poOperation = this;
     asThreadData[0].hIOMutex = hIOMutex;
     asThreadData[1].poOperation = this;
     asThreadData[1].hIOMutex = hIOMutex;
 
-    int iChunk;
-    double dfPixelsProcessed=0.0, dfTotalPixels = nDstXSize*(double)nDstYSize;
+    double dfPixelsProcessed = 0.0;
+    double dfTotalPixels = nDstXSize*(double)nDstYSize;
 
     CPLErr eErr = CE_None;
-    for( iChunk = 0; iChunk < nChunkListCount+1; iChunk++ )
+    for( int iChunk = 0; iChunk < nChunkListCount+1; iChunk++ )
     {
-        int    iThread = iChunk % 2;
+        int iThread = iChunk % 2;
 
 /* -------------------------------------------------------------------- */
 /*      Launch thread for this chunk.                                   */
@@ -884,16 +960,19 @@ CPLErr GDALWarpOperation::ChunkAndWarpMulti(
         if( pasChunkList != NULL && iChunk < nChunkListCount )
         {
             GDALWarpChunk *pasThisChunk = pasChunkList + iChunk;
-            double dfChunkPixels = pasThisChunk->dsx * (double) pasThisChunk->dsy;
+            const double dfChunkPixels =
+                pasThisChunk->dsx * static_cast<double>(pasThisChunk->dsy);
 
-            asThreadData[iThread].dfProgressBase = dfPixelsProcessed / dfTotalPixels;
-            asThreadData[iThread].dfProgressScale = dfChunkPixels / dfTotalPixels;
+            asThreadData[iThread].dfProgressBase =
+                dfPixelsProcessed / dfTotalPixels;
+            asThreadData[iThread].dfProgressScale =
+                dfChunkPixels / dfTotalPixels;
 
             dfPixelsProcessed += dfChunkPixels;
 
             asThreadData[iThread].pasChunkInfo = pasThisChunk;
 
-            if ( iChunk == 0 )
+            if( iChunk == 0 )
             {
                 asThreadData[iThread].hCond = hCond;
                 asThreadData[iThread].hCondMutex = hCondMutex;
@@ -906,22 +985,25 @@ CPLErr GDALWarpOperation::ChunkAndWarpMulti(
             asThreadData[iThread].bIOMutexTaken = FALSE;
 
             CPLDebug( "GDAL", "Start chunk %d.", iChunk );
-            asThreadData[iThread].hThreadHandle =
-                CPLCreateJoinableThread( ChunkThreadMain, (void*) &asThreadData[iThread] );
+            asThreadData[iThread].hThreadHandle = CPLCreateJoinableThread(
+                ChunkThreadMain,
+                const_cast<ChunkThreadData *>(&asThreadData[iThread]));
             if( asThreadData[iThread].hThreadHandle == NULL )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "CPLCreateJoinableThread() failed in ChunkAndWarpMulti()" );
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "CPLCreateJoinableThread() failed in ChunkAndWarpMulti()");
                 eErr = CE_Failure;
                 break;
             }
 
-            /* Wait that the first thread has acquired the IO mutex before proceeding. */
-            /* (This will ensure that the first thread will run before the second one). */
+            // Wait that the first thread has acquired the IO mutex before
+            // proceeding.  This will ensure that the first thread will run
+            // before the second one.
             if( iChunk == 0 )
             {
                 CPLAcquireMutex(hCondMutex, 1.0);
-                while (asThreadData[iThread].bIOMutexTaken == FALSE)
+                while( asThreadData[iThread].bIOMutexTaken == FALSE )
                     CPLCondWait(hCond, hCondMutex);
                 CPLReleaseMutex(hCondMutex);
             }
@@ -934,7 +1016,7 @@ CPLErr GDALWarpOperation::ChunkAndWarpMulti(
         {
             iThread = (iChunk-1) % 2;
 
-            /* Wait for thread to finish. */
+            // Wait for thread to finish.
             CPLJoinThread(asThreadData[iThread].hThreadHandle);
             asThreadData[iThread].hThreadHandle = NULL;
 
@@ -950,10 +1032,9 @@ CPLErr GDALWarpOperation::ChunkAndWarpMulti(
     /* -------------------------------------------------------------------- */
     /*      Wait for all threads to complete.                               */
     /* -------------------------------------------------------------------- */
-    int iThread;
-    for(iThread = 0; iThread < 2; iThread ++)
+    for( int iThread = 0; iThread < 2; iThread++ )
     {
-        if (asThreadData[iThread].hThreadHandle)
+        if( asThreadData[iThread].hThreadHandle )
             CPLJoinThread(asThreadData[iThread].hThreadHandle);
     }
 
@@ -978,7 +1059,7 @@ CPLErr GDALChunkAndWarpMulti( GDALWarpOperationH hOperation,
 {
     VALIDATE_POINTER1( hOperation, "GDALChunkAndWarpMulti", CE_Failure );
 
-    return ( (GDALWarpOperation *)hOperation )->
+    return reinterpret_cast<GDALWarpOperation *>(hOperation)->
         ChunkAndWarpMulti( nDstXOff, nDstYOff, nDstXSize, nDstYSize );
 }
 
@@ -1007,20 +1088,24 @@ CPLErr GDALWarpOperation::CollectChunkList(
 /*      Compute the bounds of the input area corresponding to the       */
 /*      output area.                                                    */
 /* -------------------------------------------------------------------- */
-    int nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize;
-    int nSrcXExtraSize, nSrcYExtraSize;
-    double dfSrcFillRatio;
-    CPLErr eErr;
-
-    eErr = ComputeSourceWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                                &nSrcXOff, &nSrcYOff, &nSrcXSize, &nSrcYSize,
-                                &nSrcXExtraSize, &nSrcYExtraSize, &dfSrcFillRatio );
+    int nSrcXOff = 0;
+    int nSrcYOff = 0;
+    int nSrcXSize = 0;
+    int nSrcYSize = 0;
+    int nSrcXExtraSize = 0;
+    int nSrcYExtraSize = 0;
+    double dfSrcFillRatio = 0.0;
+    CPLErr eErr =
+        ComputeSourceWindow(nDstXOff, nDstYOff, nDstXSize, nDstYSize,
+                            &nSrcXOff, &nSrcYOff, &nSrcXSize, &nSrcYSize,
+                            &nSrcXExtraSize, &nSrcYExtraSize, &dfSrcFillRatio);
 
     if( eErr != CE_None )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Unable to compute source region for output window %d,%d,%d,%d, skipping.",
-                  nDstXOff, nDstYOff, nDstXSize, nDstYSize );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Unable to compute source region for "
+                 "output window %d,%d,%d,%d, skipping.",
+                 nDstXOff, nDstYOff, nDstXSize, nDstYSize);
         return eErr;
     }
 
@@ -1029,21 +1114,19 @@ CPLErr GDALWarpOperation::CollectChunkList(
 /*      appropriate.                                                    */
 /* -------------------------------------------------------------------- */
     if( (nSrcXSize == 0 || nSrcYSize == 0)
-        && CSLFetchBoolean( psOptions->papszWarpOptions, "SKIP_NOSOURCE",0 ))
+        && CPLFetchBool( psOptions->papszWarpOptions, "SKIP_NOSOURCE", false ))
         return CE_None;
 
 /* -------------------------------------------------------------------- */
 /*      Based on the types of masks in use, how many bits will each     */
 /*      source pixel cost us?                                           */
 /* -------------------------------------------------------------------- */
-    int nSrcPixelCostInBits;
-
-    nSrcPixelCostInBits =
+    int nSrcPixelCostInBits =
         GDALGetDataTypeSize( psOptions->eWorkingDataType )
         * psOptions->nBandCount;
 
     if( psOptions->pfnSrcDensityMaskFunc != NULL )
-        nSrcPixelCostInBits += 32; /* ?? float mask */
+        nSrcPixelCostInBits += 32;  // Float mask?
 
     GDALRasterBandH hSrcBand = NULL;
     if( psOptions->nBandCount > 0 )
@@ -1051,23 +1134,22 @@ CPLErr GDALWarpOperation::CollectChunkList(
                                      psOptions->panSrcBands[0]);
 
     if( psOptions->nSrcAlphaBand > 0 || psOptions->hCutline != NULL )
-        nSrcPixelCostInBits += 32; /* UnifiedSrcDensity float mask */
-    else if (hSrcBand != NULL && (GDALGetMaskFlags(hSrcBand) & GMF_PER_DATASET))
-        nSrcPixelCostInBits += 1; /* UnifiedSrcValid bit mask */
+        nSrcPixelCostInBits += 32;  // UnifiedSrcDensity float mask.
+    else if( hSrcBand != NULL &&
+             (GDALGetMaskFlags(hSrcBand) & GMF_PER_DATASET) )
+        nSrcPixelCostInBits += 1;  // UnifiedSrcValid bit mask.
 
     if( psOptions->papfnSrcPerBandValidityMaskFunc != NULL
         || psOptions->padfSrcNoDataReal != NULL )
-        nSrcPixelCostInBits += psOptions->nBandCount; /* bit/band mask */
+        nSrcPixelCostInBits += psOptions->nBandCount;  // Bit/band mask.
 
     if( psOptions->pfnSrcValidityMaskFunc != NULL )
-        nSrcPixelCostInBits += 1; /* bit mask */
+        nSrcPixelCostInBits += 1;  // Bit mask.
 
 /* -------------------------------------------------------------------- */
 /*      What about the cost for the destination.                        */
 /* -------------------------------------------------------------------- */
-    int nDstPixelCostInBits;
-
-    nDstPixelCostInBits =
+    int nDstPixelCostInBits =
         GDALGetDataTypeSize( psOptions->eWorkingDataType )
         * psOptions->nBandCount;
 
@@ -1079,21 +1161,20 @@ CPLErr GDALWarpOperation::CollectChunkList(
         nDstPixelCostInBits += psOptions->nBandCount;
 
     if( psOptions->nDstAlphaBand > 0 )
-        nDstPixelCostInBits += 32; /* DstDensity float mask */
+        nDstPixelCostInBits += 32;  // DstDensity float mask.
 
 /* -------------------------------------------------------------------- */
 /*      Does the cost of the current rectangle exceed our memory        */
 /*      limit? If so, split the destination along the longest           */
 /*      dimension and recurse.                                          */
 /* -------------------------------------------------------------------- */
-    double dfTotalMemoryUse;
-
-    dfTotalMemoryUse =
-        (((double) nSrcPixelCostInBits) * nSrcXSize * nSrcYSize
-         + ((double) nDstPixelCostInBits) * nDstXSize * nDstYSize) / 8.0;
+    double dfTotalMemoryUse =
+      (static_cast<double>(nSrcPixelCostInBits) * nSrcXSize * nSrcYSize +
+       static_cast<double>(nDstPixelCostInBits) * nDstXSize * nDstYSize) / 8.0;
 
-    int nBlockXSize = 1, nBlockYSize = 1;
-    if (psOptions->hDstDS)
+    int nBlockXSize = 1;
+    int nBlockYSize = 1;
+    if( psOptions->hDstDS )
     {
         GDALGetBlockSize(GDALGetRasterBand(psOptions->hDstDS, 1),
                          &nBlockXSize, &nBlockYSize);
@@ -1105,35 +1186,46 @@ CPLErr GDALWarpOperation::CollectChunkList(
     // only if there's at least some source pixel intersecting. The
     // SRC_FILL_RATIO_HEURISTICS warping option is undocumented and only here
     // in case the heuristics would cause issues.
-    /*CPLDebug("WARP", "dst=(%d,%d,%d,%d) src=(%d,%d,%d,%d) srcfillratio=%.18g",
+#if DEBUG_VERBOSE
+    CPLDebug("WARP",
+             "dst=(%d,%d,%d,%d) src=(%d,%d,%d,%d) srcfillratio=%.18g",
              nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-             nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize, dfSrcFillRatio);*/
-    if( (dfTotalMemoryUse > psOptions->dfWarpMemoryLimit && (nDstXSize > 2 || nDstYSize > 2)) ||
-        (dfSrcFillRatio > 0 && dfSrcFillRatio < 0.5 && (nDstXSize > 100 || nDstYSize > 100) &&
-         CSLFetchBoolean( psOptions->papszWarpOptions, "SRC_FILL_RATIO_HEURISTICS", TRUE )) )
+             nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize, dfSrcFillRatio);
+#endif
+    if( (dfTotalMemoryUse > psOptions->dfWarpMemoryLimit &&
+         (nDstXSize > 2 || nDstYSize > 2)) ||
+        (dfSrcFillRatio > 0 && dfSrcFillRatio < 0.5 &&
+         (nDstXSize > 100 || nDstYSize > 100) &&
+         CPLFetchBool( psOptions->papszWarpOptions, "SRC_FILL_RATIO_HEURISTICS",
+                       true )) )
     {
-        CPLErr eErr2 = CE_None;
-
         int bStreamableOutput =
-                CSLFetchBoolean( psOptions->papszWarpOptions, "STREAMABLE_OUTPUT", FALSE );
-        int bOptimizeSize = !bStreamableOutput &&
-                CSLFetchBoolean( psOptions->papszWarpOptions, "OPTIMIZE_SIZE", FALSE );
-
-        /* If the region width is greater than the region height, */
-        /* cut in half in the width. When we want to optimize the size */
-        /* of a compressed output dataset, do this only if each half part */
-        /* is at least as wide as the block width */
-        int bHasDivided = FALSE;
+            CPLFetchBool( psOptions->papszWarpOptions, "STREAMABLE_OUTPUT",
+                          false );
+        const bool bOptimizeSize =
+            !bStreamableOutput &&
+            CPLFetchBool( psOptions->papszWarpOptions, "OPTIMIZE_SIZE", false );
+
+        // If the region width is greater than the region height,
+        // cut in half in the width. When we want to optimize the size
+        // of a compressed output dataset, do this only if each half part
+        // is at least as wide as the block width.
+        bool bHasDivided = false;
+        CPLErr eErr2 = CE_None;
         if( nDstXSize > nDstYSize &&
             ((!bOptimizeSize && !bStreamableOutput) ||
-             (bOptimizeSize && (nDstXSize / 2 >= nBlockXSize || nDstYSize == 1)) ||
-             (bStreamableOutput && nDstXSize / 2 >= nBlockXSize && nDstYSize == nBlockYSize)) )
+             (bOptimizeSize &&
+              (nDstXSize / 2 >= nBlockXSize || nDstYSize == 1)) ||
+             (bStreamableOutput &&
+              nDstXSize / 2 >= nBlockXSize &&
+              nDstYSize == nBlockYSize)) )
         {
-            bHasDivided = TRUE;
+            bHasDivided = true;
             int nChunk1 = nDstXSize / 2;
 
-            /* In the optimize size case, try to stick on target block boundaries */
-            if ((bOptimizeSize || bStreamableOutput) && nChunk1 > nBlockXSize)
+            // In the optimize size case, try to stick on target block
+            // boundaries.
+            if( (bOptimizeSize || bStreamableOutput) && nChunk1 > nBlockXSize )
                 nChunk1 = (nChunk1 / nBlockXSize) * nBlockXSize;
 
             int nChunk2 = nDstXSize - nChunk1;
@@ -1146,14 +1238,15 @@ CPLErr GDALWarpOperation::CollectChunkList(
         }
         else if( !(bStreamableOutput && nDstYSize / 2 < nBlockYSize) )
         {
-            bHasDivided = TRUE;
+            bHasDivided = true;
             int nChunk1 = nDstYSize / 2;
 
-            /* In the optimize size case, try to stick on target block boundaries */
-            if ((bOptimizeSize || bStreamableOutput) && nChunk1 > nBlockYSize)
+            // In the optimize size case, try to stick on target block
+            // boundaries.
+            if( (bOptimizeSize || bStreamableOutput) && nChunk1 > nBlockYSize )
                 nChunk1 = (nChunk1 / nBlockYSize) * nBlockYSize;
 
-            int nChunk2 = nDstYSize - nChunk1;
+            const int nChunk2 = nDstYSize - nChunk1;
 
             eErr = CollectChunkList( nDstXOff, nDstYOff,
                                      nDstXSize, nChunk1 );
@@ -1177,8 +1270,8 @@ CPLErr GDALWarpOperation::CollectChunkList(
     if( nChunkListCount == nChunkListMax )
     {
         nChunkListMax = nChunkListMax * 2 + 1;
-        pasChunkList = (GDALWarpChunk *)
-            CPLRealloc(pasChunkList,sizeof(GDALWarpChunk)*nChunkListMax );
+        pasChunkList = static_cast<GDALWarpChunk *>(
+            CPLRealloc(pasChunkList, sizeof(GDALWarpChunk) * nChunkListMax));
     }
 
     pasChunkList[nChunkListCount].dx = nDstXOff;
@@ -1197,19 +1290,11 @@ CPLErr GDALWarpOperation::CollectChunkList(
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                             WarpRegion()                             */
 /************************************************************************/
 
 /**
- * \fn CPLErr GDALWarpOperation::WarpRegion(int nDstXOff, int nDstYOff,
-                                            int nDstXSize, int nDstYSize,
-                                            int nSrcXOff=0, int nSrcYOff=0,
-                                            int nSrcXSize=0, int nSrcYSize=0,
-                                            double dfProgressBase = 0,
-                                            double dfProgressScale = 1);
- *
  * This method requests the indicated region of the output file be generated.
  *
  * Note that WarpRegion() will produce the requested area in one low level warp
@@ -1243,7 +1328,7 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
                                       int nSrcXOff, int nSrcYOff,
                                       int nSrcXSize, int nSrcYSize,
                                       double dfProgressBase,
-                                      double dfProgressScale)
+                                      double dfProgressScale )
 {
     return WarpRegion(nDstXOff, nDstYOff,
                       nDstXSize, nDstYSize,
@@ -1253,6 +1338,39 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
                       dfProgressBase, dfProgressScale);
 }
 
+/**
+ * This method requests the indicated region of the output file be generated.
+ *
+ * Note that WarpRegion() will produce the requested area in one low level warp
+ * operation without verifying that this does not exceed the stated memory
+ * limits for the warp operation.  Applications should take care not to call
+ * WarpRegion() on too large a region!  This function
+ * is normally called by ChunkAndWarpImage(), the normal entry point for
+ * applications.  Use it instead if staying within memory constraints is
+ * desired.
+ *
+ * Progress is reported from dfProgressBase to dfProgressBase + dfProgressScale
+ * for the indicated region.
+ *
+ * @param nDstXOff X offset to window of destination data to be produced.
+ * @param nDstYOff Y offset to window of destination data to be produced.
+ * @param nDstXSize Width of output window on destination file to be produced.
+ * @param nDstYSize Height of output window on destination file to be produced.
+ * @param nSrcXOff source window X offset (computed if window all zero)
+ * @param nSrcYOff source window Y offset (computed if window all zero)
+ * @param nSrcXSize source window X size (computed if window all zero)
+ * @param nSrcYSize source window Y size (computed if window all zero)
+ * @param nSrcXExtraSize Extra pixels (included in nSrcXSize) reserved
+ * for filter window. Should be ignored in scale computation
+ * @param nSrcYExtraSize Extra pixels (included in nSrcYSize) reserved
+ * for filter window. Should be ignored in scale computation
+ * @param dfProgressBase minimum progress value reported
+ * @param dfProgressScale value such as dfProgressBase + dfProgressScale is the
+ *                        maximum progress value reported
+ *
+ * @return CE_None on success or CE_Failure if an error occurs.
+ */
+
 CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
                                       int nDstXSize, int nDstYSize,
                                       int nSrcXOff, int nSrcYOff,
@@ -1262,20 +1380,16 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
                                       double dfProgressScale)
 
 {
-    CPLErr eErr;
-    int   iBand;
-
     ReportTiming( NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Allocate the output buffer.                                     */
 /* -------------------------------------------------------------------- */
-    void *pDstBuffer;
     const int nWordSize = GDALGetDataTypeSizeBytes(psOptions->eWorkingDataType);
-    int  nBandSize = nWordSize * nDstXSize * nDstYSize;
+    const int nBandSize = nWordSize * nDstXSize * nDstYSize;
 
-    if (nDstXSize > INT_MAX / nDstYSize ||
-        nDstXSize * nDstYSize > INT_MAX / (nWordSize * psOptions->nBandCount))
+    if( nDstXSize > INT_MAX / nDstYSize ||
+        nDstXSize * nDstYSize > INT_MAX / (nWordSize * psOptions->nBandCount) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Integer overflow : nDstXSize=%d, nDstYSize=%d",
@@ -1283,7 +1397,7 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
         return CE_Failure;
     }
 
-    pDstBuffer = VSI_MALLOC_VERBOSE( nBandSize * psOptions->nBandCount );
+    void *pDstBuffer = VSI_MALLOC_VERBOSE( nBandSize * psOptions->nBandCount );
     if( pDstBuffer == NULL )
     {
         return CE_Failure;
@@ -1305,15 +1419,15 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
     {
         char **papszInitValues =
             CSLTokenizeStringComplex( pszInitDest, ",", FALSE, FALSE );
-        int nInitCount = CSLCount(papszInitValues);
+        const int nInitCount = CSLCount(papszInitValues);
 
-        for( iBand = 0; iBand < psOptions->nBandCount; iBand++ )
+        for( int iBand = 0; iBand < psOptions->nBandCount; iBand++ )
         {
-            double adfInitRealImag[2];
-            GByte *pBandData;
-            const char *pszBandInit = papszInitValues[MIN(iBand,nInitCount-1)];
+            double adfInitRealImag[2] = { 0.0, 0.0 };
+            const char *pszBandInit =
+                papszInitValues[std::min(iBand, nInitCount - 1)];
 
-            if( EQUAL(pszBandInit,"NO_DATA")
+            if( EQUAL(pszBandInit, "NO_DATA")
                 && psOptions->padfDstNoDataReal != NULL )
             {
                 adfInitRealImag[0] = psOptions->padfDstNoDataReal[iBand];
@@ -1325,27 +1439,35 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
                                     adfInitRealImag + 0, adfInitRealImag + 1);
             }
 
-            pBandData = ((GByte *) pDstBuffer) + iBand * nBandSize;
+            GByte *pBandData =
+                static_cast<GByte *>(pDstBuffer) + iBand * nBandSize;
 
             if( psOptions->eWorkingDataType == GDT_Byte )
                 memset( pBandData,
-                        MAX(0,MIN(255,(int)adfInitRealImag[0])),
+                        std::max(
+                            0, std::min(255,
+                                        static_cast<int>(adfInitRealImag[0]))),
                         nBandSize);
-            else if( !CPLIsNan(adfInitRealImag[0]) && adfInitRealImag[0] == 0.0 &&
-                     !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
+            else if( !CPLIsNan(adfInitRealImag[0]) &&
+                     adfInitRealImag[0] == 0.0 &&
+                     !CPLIsNan(adfInitRealImag[1]) &&
+                     adfInitRealImag[1] == 0.0 )
             {
                 memset( pBandData, 0, nBandSize );
             }
-            else if( !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
+            else if( !CPLIsNan(adfInitRealImag[1]) &&
+                     adfInitRealImag[1] == 0.0 )
             {
                 GDALCopyWords( &adfInitRealImag, GDT_Float64, 0,
-                               pBandData,psOptions->eWorkingDataType,nWordSize,
+                               pBandData, psOptions->eWorkingDataType,
+                               nWordSize,
                                nDstXSize * nDstYSize );
             }
             else
             {
                 GDALCopyWords( &adfInitRealImag, GDT_CFloat64, 0,
-                               pBandData,psOptions->eWorkingDataType,nWordSize,
+                               pBandData, psOptions->eWorkingDataType,
+                               nWordSize,
                                nDstXSize * nDstYSize );
             }
         }
@@ -1357,15 +1479,32 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
 /*      If we aren't doing fixed initialization of the output buffer    */
 /*      then read it from disk so we can overlay on existing imagery.   */
 /* -------------------------------------------------------------------- */
+    GDALDataset* poDstDS = reinterpret_cast<GDALDataset*>(psOptions->hDstDS);
     if( pszInitDest == NULL )
     {
-        eErr = GDALDatasetRasterIO( psOptions->hDstDS, GF_Read,
-                                    nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                                    pDstBuffer, nDstXSize, nDstYSize,
-                                    psOptions->eWorkingDataType,
-                                    psOptions->nBandCount,
-                                    psOptions->panDstBands,
-                                    0, 0, 0 );
+        CPLErr eErr = CE_None;
+        if( psOptions->nBandCount == 1 )
+        {
+            // Particular case to simplify the stack a bit.
+            // TODO(rouault): Need an explanation of what and why r34502 helps.
+            eErr = poDstDS->GetRasterBand(psOptions->panDstBands[0])->RasterIO(
+                GF_Read,
+                nDstXOff, nDstYOff, nDstXSize, nDstYSize,
+                pDstBuffer, nDstXSize, nDstYSize,
+                psOptions->eWorkingDataType,
+                0, 0, NULL);
+        }
+        else
+        {
+            eErr = poDstDS->RasterIO(
+                GF_Read,
+                nDstXOff, nDstYOff, nDstXSize, nDstYSize,
+                pDstBuffer, nDstXSize, nDstYSize,
+                psOptions->eWorkingDataType,
+                psOptions->nBandCount,
+                psOptions->panDstBands,
+                0, 0, 0, NULL);
+        }
 
         if( eErr != CE_None )
         {
@@ -1379,33 +1518,48 @@ CPLErr GDALWarpOperation::WarpRegion( int nDstXOff, int nDstYOff,
 /* -------------------------------------------------------------------- */
 /*      Perform the warp.                                               */
 /* -------------------------------------------------------------------- */
-    eErr = WarpRegionToBuffer( nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                               pDstBuffer, psOptions->eWorkingDataType,
-                               nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
-                               nSrcXExtraSize, nSrcYExtraSize,
-                               dfProgressBase, dfProgressScale);
+    CPLErr eErr =
+        WarpRegionToBuffer(nDstXOff, nDstYOff, nDstXSize, nDstYSize,
+                           pDstBuffer, psOptions->eWorkingDataType,
+                           nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
+                           nSrcXExtraSize, nSrcYExtraSize,
+                           dfProgressBase, dfProgressScale);
 
 /* -------------------------------------------------------------------- */
 /*      Write the output data back to disk if all went well.            */
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None )
     {
-        eErr = GDALDatasetRasterIO( psOptions->hDstDS, GF_Write,
+        if( psOptions->nBandCount == 1 )
+        {
+            // Particular case to simplify the stack a bit.
+            eErr = poDstDS->GetRasterBand(psOptions->panDstBands[0])->RasterIO(
+                  GF_Write,
+                  nDstXOff, nDstYOff, nDstXSize, nDstYSize,
+                  pDstBuffer, nDstXSize, nDstYSize,
+                  psOptions->eWorkingDataType,
+                  0, 0, NULL );
+        }
+        else
+        {
+            eErr = poDstDS->RasterIO( GF_Write,
                                     nDstXOff, nDstYOff, nDstXSize, nDstYSize,
                                     pDstBuffer, nDstXSize, nDstYSize,
                                     psOptions->eWorkingDataType,
                                     psOptions->nBandCount,
                                     psOptions->panDstBands,
-                                    0, 0, 0 );
+                                    0, 0, 0, NULL );
+        }
+
         if( eErr == CE_None &&
-            CSLFetchBoolean( psOptions->papszWarpOptions, "WRITE_FLUSH",
-                             FALSE ) )
+            CPLFetchBool( psOptions->papszWarpOptions, "WRITE_FLUSH", false ) )
         {
-            CPLErr eOldErr = CPLGetLastErrorType();
-            CPLString osLastErrMsg = CPLGetLastErrorMsg();
+            const CPLErr eOldErr = CPLGetLastErrorType();
+            const CPLString osLastErrMsg = CPLGetLastErrorMsg();
             GDALFlushCache( psOptions->hDstDS );
-            CPLErr eNewErr = CPLGetLastErrorType();
-            if (eNewErr != eOldErr || osLastErrMsg.compare(CPLGetLastErrorMsg()) != 0)
+            const CPLErr eNewErr = CPLGetLastErrorType();
+            if( eNewErr != eOldErr ||
+                osLastErrMsg.compare(CPLGetLastErrorMsg()) != 0 )
                 eErr = CE_Failure;
         }
         ReportTiming( "Output buffer write" );
@@ -1436,7 +1590,7 @@ CPLErr GDALWarpRegion( GDALWarpOperationH hOperation,
 {
     VALIDATE_POINTER1( hOperation, "GDALWarpRegion", CE_Failure );
 
-    return ( (GDALWarpOperation *)hOperation )->
+    return reinterpret_cast<GDALWarpOperation *>(hOperation)->
         WarpRegion( nDstXOff, nDstYOff, nDstXSize, nDstYSize,
                     nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize);
 }
@@ -1446,16 +1600,6 @@ CPLErr GDALWarpRegion( GDALWarpOperationH hOperation,
 /************************************************************************/
 
 /**
- * \fn CPLErr GDALWarpOperation::WarpRegionToBuffer(
-                                  int nDstXOff, int nDstYOff,
-                                  int nDstXSize, int nDstYSize,
-                                  void *pDataBuf,
-                                  GDALDataType eBufDataType,
-                                  int nSrcXOff=0, int nSrcYOff=0,
-                                  int nSrcXSize=0, int nSrcYSize=0,
-                                  double dfProgressBase = 0,
-                                  double dfProgressScale = 1 );
- *
  * This method requests that a particular window of the output dataset
  * be warped and the result put into the provided data buffer.  The output
  * dataset doesn't even really have to exist to use this method as long as
@@ -1495,19 +1639,50 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
                               dfProgressBase, dfProgressScale);
 }
 
+/**
+ * This method requests that a particular window of the output dataset
+ * be warped and the result put into the provided data buffer.  The output
+ * dataset doesn't even really have to exist to use this method as long as
+ * the transformation function in the GDALWarpOptions is setup to map to
+ * a virtual pixel/line space.
+ *
+ * This method will do the whole region in one chunk, so be wary of the
+ * amount of memory that might be used.
+ *
+ * @param nDstXOff X offset to window of destination data to be produced.
+ * @param nDstYOff Y offset to window of destination data to be produced.
+ * @param nDstXSize Width of output window on destination file to be produced.
+ * @param nDstYSize Height of output window on destination file to be produced.
+ * @param pDataBuf the data buffer to place result in, of type eBufDataType.
+ * @param eBufDataType the type of the output data buffer.  For now this
+ * must match GDALWarpOptions::eWorkingDataType.
+ * @param nSrcXOff source window X offset (computed if window all zero)
+ * @param nSrcYOff source window Y offset (computed if window all zero)
+ * @param nSrcXSize source window X size (computed if window all zero)
+ * @param nSrcYSize source window Y size (computed if window all zero)
+ * @param nSrcXExtraSize Extra pixels (included in nSrcXSize) reserved
+ * for filter window. Should be ignored in scale computation
+ * @param nSrcYExtraSize Extra pixels (included in nSrcYSize) reserved
+ * for filter window. Should be ignored in scale computation
+ * @param dfProgressBase minimum progress value reported
+ * @param dfProgressScale value such as dfProgressBase + dfProgressScale is the
+ *                        maximum progress value reported
+ *
+ * @return CE_None on success or CE_Failure if an error occurs.
+ */
+
 CPLErr GDALWarpOperation::WarpRegionToBuffer(
     int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize,
-    void *pDataBuf, GDALDataType eBufDataType,
+    void *pDataBuf,
+    // Only in a CPLAssert.
+    CPL_UNUSED GDALDataType eBufDataType,
     int nSrcXOff, int nSrcYOff, int nSrcXSize, int nSrcYSize,
     int nSrcXExtraSize, int nSrcYExtraSize,
     double dfProgressBase, double dfProgressScale)
 
 {
-    CPLErr eErr = CE_None;
-    int    i;
     const int nWordSize = GDALGetDataTypeSizeBytes(psOptions->eWorkingDataType);
 
-    (void) eBufDataType;
     CPLAssert( eBufDataType == psOptions->eWorkingDataType );
 
 /* -------------------------------------------------------------------- */
@@ -1515,10 +1690,11 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /* -------------------------------------------------------------------- */
     if( nSrcXSize == 0 && nSrcYSize == 0 )
     {
-        eErr = ComputeSourceWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-                                    &nSrcXOff, &nSrcYOff,
-                                    &nSrcXSize, &nSrcYSize,
-                                    &nSrcXExtraSize, &nSrcYExtraSize, NULL );
+        const CPLErr eErr =
+            ComputeSourceWindow( nDstXOff, nDstYOff, nDstXSize, nDstYSize,
+                                 &nSrcXOff, &nSrcYOff,
+                                 &nSrcXSize, &nSrcYSize,
+                                 &nSrcXExtraSize, &nSrcYExtraSize, NULL );
         if( eErr != CE_None )
             return eErr;
     }
@@ -1526,7 +1702,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /* -------------------------------------------------------------------- */
 /*      Prepare a WarpKernel object to match this operation.            */
 /* -------------------------------------------------------------------- */
-    GDALWarpKernel   oWK;
+    GDALWarpKernel oWK;
 
     oWK.eResample = psOptions->eResampleAlg;
     oWK.nBands = psOptions->nBandCount;
@@ -1558,9 +1734,10 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     oWK.nSrcXExtraSize = nSrcXExtraSize;
     oWK.nSrcYExtraSize = nSrcYExtraSize;
 
-    if (nSrcXSize != 0 && nSrcYSize != 0 &&
+    if( nSrcXSize != 0 && nSrcYSize != 0 &&
         (nSrcXSize > INT_MAX / nSrcYSize ||
-         nSrcXSize * nSrcYSize > INT_MAX / (nWordSize * psOptions->nBandCount) - WARP_EXTRA_ELTS))
+         nSrcXSize * nSrcYSize >
+         INT_MAX / (nWordSize * psOptions->nBandCount) - WARP_EXTRA_ELTS) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Integer overflow : nSrcXSize=%d, nSrcYSize=%d",
@@ -1568,28 +1745,47 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
         return CE_Failure;
     }
 
-    oWK.papabySrcImage = (GByte **)
-        CPLCalloc(sizeof(GByte*),psOptions->nBandCount);
-    oWK.papabySrcImage[0] = (GByte *)
-        VSI_MALLOC_VERBOSE( nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) * psOptions->nBandCount );
+    oWK.papabySrcImage = static_cast<GByte **>(
+        CPLCalloc(sizeof(GByte*), psOptions->nBandCount));
+    oWK.papabySrcImage[0] = static_cast<GByte *>(
+        VSI_MALLOC_VERBOSE(nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS)
+                           * psOptions->nBandCount));
 
-    if( nSrcXSize != 0 && nSrcYSize != 0 && oWK.papabySrcImage[0] == NULL )
-    {
-        eErr = CE_Failure;
-    }
+    CPLErr eErr =
+        nSrcXSize != 0 && nSrcYSize != 0 && oWK.papabySrcImage[0] == NULL
+        ? CE_Failure
+        : CE_None;
 
-    for( i = 0; i < psOptions->nBandCount && eErr == CE_None; i++ )
+
+    for( int i = 0; i < psOptions->nBandCount && eErr == CE_None; i++ )
         oWK.papabySrcImage[i] = ((GByte *) oWK.papabySrcImage[0])
             + nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) * i;
 
     if( eErr == CE_None && nSrcXSize > 0 && nSrcYSize > 0 )
-        eErr =
-            GDALDatasetRasterIO( psOptions->hSrcDS, GF_Read,
-                                 nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
-                                 oWK.papabySrcImage[0], nSrcXSize, nSrcYSize,
-                                 psOptions->eWorkingDataType,
-                                 psOptions->nBandCount, psOptions->panSrcBands,
-                                 0, 0, nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS) );
+    {
+        GDALDataset* poSrcDS =
+            reinterpret_cast<GDALDataset*>(psOptions->hSrcDS);
+        if( psOptions->nBandCount == 1 )
+        {
+            // Particular case to simplify the stack a bit.
+            eErr = poSrcDS->GetRasterBand(psOptions->panDstBands[0])->RasterIO(
+                                  GF_Read,
+                                  nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
+                                  oWK.papabySrcImage[0], nSrcXSize, nSrcYSize,
+                                  psOptions->eWorkingDataType,
+                                  0, 0, NULL );
+        }
+        else
+        {
+            eErr = poSrcDS->RasterIO( GF_Read,
+                  nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize,
+                  oWK.papabySrcImage[0], nSrcXSize, nSrcYSize,
+                  psOptions->eWorkingDataType,
+                  psOptions->nBandCount, psOptions->panSrcBands,
+                  0, 0, nWordSize * (nSrcXSize * nSrcYSize + WARP_EXTRA_ELTS),
+                  NULL );
+        }
+    }
 
     ReportTiming( "Input buffer read" );
 
@@ -1601,13 +1797,14 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     oWK.nDstXSize = nDstXSize;
     oWK.nDstYSize = nDstYSize;
 
-    oWK.papabyDstImage = (GByte **)
-        CPLCalloc(sizeof(GByte*),psOptions->nBandCount);
+    oWK.papabyDstImage = reinterpret_cast<GByte **>(
+        CPLCalloc(sizeof(GByte*), psOptions->nBandCount));
 
-    for( i = 0; i < psOptions->nBandCount && eErr == CE_None; i++ )
+    int i1 = 0;  // Used after for.
+    for( ; i1 < psOptions->nBandCount && eErr == CE_None; i1++ )
     {
-        oWK.papabyDstImage[i] = ((GByte *) pDataBuf)
-            + i * nDstXSize * nDstYSize * nWordSize;
+        oWK.papabyDstImage[i1] = static_cast<GByte *>(pDataBuf)
+            + i1 * nDstXSize * nDstYSize * nWordSize;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1615,7 +1812,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /*      validity and density masks here.                                */
 /* -------------------------------------------------------------------- */
 
-    /* TODO */
+    // TODO
 
 /* -------------------------------------------------------------------- */
 /*      Generate a source density mask if we have a source alpha band   */
@@ -1641,7 +1838,11 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
                                         &bOutAllOpaque );
             if( bOutAllOpaque )
             {
-                //CPLDebug("WARP", "No need for a source density mask as all values are opaque");
+#if DEBUG_VERBOSE
+                CPLDebug("WARP",
+                         "No need for a source density mask as all values "
+                         "are opaque");
+#endif
                 CPLFree(oWK.pafUnifiedSrcDensity);
                 oWK.pafUnifiedSrcDensity = NULL;
             }
@@ -1660,7 +1861,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 
             if( eErr == CE_None )
             {
-                for( int j = oWK.nSrcXSize * oWK.nSrcYSize - 1; j >= 0; j-- )
+                for( int j = 0; j < oWK.nSrcXSize * oWK.nSrcYSize; j++ )
                     oWK.pafUnifiedSrcDensity[j] = 1.0;
             }
         }
@@ -1684,7 +1885,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     {
         CPLAssert( oWK.pafDstDensity == NULL );
 
-        eErr = CreateKernelMask( &oWK, i, "DstDensity" );
+        eErr = CreateKernelMask( &oWK, i1, "DstDensity" );
 
         if( eErr == CE_None )
             eErr =
@@ -1705,16 +1906,18 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     {
         CPLAssert( oWK.papanBandSrcValid == NULL );
 
-        int bAllBandsAllValid = TRUE;
-        for( i = 0; i < psOptions->nBandCount && eErr == CE_None; i++ )
+        bool bAllBandsAllValid = true;
+        int i2 = 0;  // Used after for.
+        for( ; i2 < psOptions->nBandCount && eErr == CE_None; i2++ )
         {
-            eErr = CreateKernelMask( &oWK, i, "BandSrcValid" );
+            eErr = CreateKernelMask( &oWK, i2, "BandSrcValid" );
             if( eErr == CE_None )
             {
-                double adfNoData[2];
-
-                adfNoData[0] = psOptions->padfSrcNoDataReal[i];
-                adfNoData[1] = psOptions->padfSrcNoDataImag[i];
+                double adfNoData[2] =
+                {
+                    psOptions->padfSrcNoDataReal[i2],
+                    psOptions->padfSrcNoDataImag[i2]
+                };
 
                 int bAllValid = FALSE;
                 eErr =
@@ -1722,21 +1925,25 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
                                           psOptions->eWorkingDataType,
                                           oWK.nSrcXOff, oWK.nSrcYOff,
                                           oWK.nSrcXSize, oWK.nSrcYSize,
-                                          &(oWK.papabySrcImage[i]),
-                                          FALSE, oWK.papanBandSrcValid[i],
+                                          &(oWK.papabySrcImage[i2]),
+                                          FALSE, oWK.papanBandSrcValid[i2],
                                           &bAllValid );
                 if( !bAllValid )
-                    bAllBandsAllValid = FALSE;
+                    bAllBandsAllValid = false;
             }
         }
 
-        /* Optimization: if all pixels in all bands are valid, */
-        /* we don't need a mask */
+        // Optimization: if all pixels in all bands are valid,
+        // we don't need a mask.
         if( bAllBandsAllValid )
         {
-            //CPLDebug("WARP", "No need for a source nodata mask as all values are valid");
-            for( i = 0; i < oWK.nBands; i++ )
-                CPLFree( oWK.papanBandSrcValid[i] );
+#if DEBUG_VERBOSE
+            CPLDebug(
+                "WARP",
+                "No need for a source nodata mask as all values are valid");
+#endif
+            for( int k = 0; k < oWK.nBands; k++ )
+                CPLFree( oWK.papanBandSrcValid[k] );
             CPLFree( oWK.papanBandSrcValid );
             oWK.papanBandSrcValid = NULL;
         }
@@ -1748,26 +1955,25 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /*      respective nodata values.                                       */
 /* -------------------------------------------------------------------- */
         if( oWK.papanBandSrcValid != NULL &&
-            CSLFetchBoolean( psOptions->papszWarpOptions, "UNIFIED_SRC_NODATA",
-                             FALSE )
+            CPLFetchBool( psOptions->papszWarpOptions, "UNIFIED_SRC_NODATA",
+                          false )
             && eErr == CE_None )
         {
-            int nBytesInMask = (oWK.nSrcXSize * oWK.nSrcYSize + 31) / 8;
-            int iWord;
+            const int nBytesInMask = (oWK.nSrcXSize * oWK.nSrcYSize + 31) / 8;
 
-            eErr = CreateKernelMask( &oWK, i, "UnifiedSrcValid" );
+            eErr = CreateKernelMask( &oWK, i2, "UnifiedSrcValid" );
 
             if( eErr == CE_None )
             {
                 memset( oWK.panUnifiedSrcValid, 0, nBytesInMask );
 
-                for( i = 0; i < psOptions->nBandCount; i++ )
+                for( int k = 0; k < psOptions->nBandCount; k++ )
                 {
-                    for( iWord = nBytesInMask/4 - 1; iWord >= 0; iWord-- )
+                    for( int iWord = nBytesInMask/4 - 1; iWord >= 0; iWord-- )
                         oWK.panUnifiedSrcValid[iWord] |=
-                            oWK.papanBandSrcValid[i][iWord];
-                    CPLFree( oWK.papanBandSrcValid[i] );
-                    oWK.papanBandSrcValid[i] = NULL;
+                            oWK.papanBandSrcValid[k][iWord];
+                    CPLFree( oWK.papanBandSrcValid[k] );
+                    oWK.papanBandSrcValid[k] = NULL;
                 }
 
                 CPLFree( oWK.papanBandSrcValid );
@@ -1777,19 +1983,23 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     }
 
 /* -------------------------------------------------------------------- */
-/*      Generate a source validity mask if we have a source mask for     */
+/*      Generate a source validity mask if we have a source mask for    */
 /*      the whole input dataset (and didn't already treat it as         */
 /*      alpha band).                                                    */
 /* -------------------------------------------------------------------- */
-    GDALRasterBandH hSrcBand = NULL;
-    if( psOptions->nBandCount > 0 )
-        hSrcBand = GDALGetRasterBand(psOptions->hSrcDS,
-                                     psOptions->panSrcBands[0]);
+    GDALRasterBandH hSrcBand =
+        psOptions->nBandCount < 1
+        ? NULL
+        : GDALGetRasterBand(psOptions->hSrcDS, psOptions->panSrcBands[0]);
 
     if( eErr == CE_None
         && oWK.pafUnifiedSrcDensity == NULL
-        && (GDALGetMaskFlags(hSrcBand) & GMF_PER_DATASET) &&
-        nSrcXSize > 0 && nSrcYSize > 0 )
+        && oWK.panUnifiedSrcValid == NULL
+        && psOptions->nSrcAlphaBand <= 0
+        && (GDALGetMaskFlags(hSrcBand) & GMF_PER_DATASET)
+        // Need to double check for -nosrcalpha case.
+        && !(GDALGetMaskFlags(hSrcBand) & GMF_ALPHA)
+        && nSrcXSize > 0 && nSrcYSize > 0 )
 
     {
         eErr = CreateKernelMask( &oWK, 0, "UnifiedSrcValid" );
@@ -1818,27 +2028,25 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
     {
         CPLAssert( oWK.panDstValid == NULL );
 
-        GUInt32 *panBandMask = NULL;
-        int     nMaskWords = (oWK.nDstXSize * oWK.nDstYSize + 31)/32;
+        const int nMaskWords = (oWK.nDstXSize * oWK.nDstYSize + 31)/32;
 
         eErr = CreateKernelMask( &oWK, 0, "DstValid" );
-        if( eErr == CE_None )
-        {
-            panBandMask = (GUInt32 *) CPLMalloc(nMaskWords*4);
-        }
+        GUInt32 *panBandMask =
+            eErr == CE_None
+            ? static_cast<GUInt32 *>(CPLMalloc(nMaskWords * 4))
+            : NULL;
 
         if( eErr == CE_None && panBandMask != NULL )
         {
-            int iBand, iWord;
-
-            for( iBand = 0; iBand < psOptions->nBandCount; iBand++ )
+            for( int iBand = 0; iBand < psOptions->nBandCount; iBand++ )
             {
-                double adfNoData[2];
-
                 memset( panBandMask, 0xff, nMaskWords * 4 );
 
-                adfNoData[0] = psOptions->padfDstNoDataReal[iBand];
-                adfNoData[1] = psOptions->padfDstNoDataImag[iBand];
+                double adfNoData[2] =
+                {
+                    psOptions->padfDstNoDataReal[iBand],
+                    psOptions->padfDstNoDataImag[iBand]
+                };
 
                 int bAllValid = FALSE;
                 eErr =
@@ -1850,17 +2058,21 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
                                           FALSE, panBandMask,
                                           &bAllValid );
 
-                /* Optimization: if there's a single band and all pixels are */
-                /* valid then we don't need a mask */
+                // Optimization: if there's a single band and all pixels are
+                // valid then we don't need a mask.
                 if( bAllValid && psOptions->nBandCount == 1 )
                 {
-                    //CPLDebug("WARP", "No need for a destination nodata mask as all values are valid");
+#if DEBUG_VERBOSE
+                    CPLDebug("WARP",
+                             "No need for a destination nodata mask as "
+                             "all values are valid");
+#endif
                     CPLFree(oWK.panDstValid);
                     oWK.panDstValid = NULL;
                     break;
                 }
 
-                for( iWord = nMaskWords - 1; iWord >= 0; iWord-- )
+                for( int iWord = nMaskWords - 1; iWord >= 0; iWord-- )
                     oWK.panDstValid[iWord] |= panBandMask[iWord];
             }
             CPLFree( panBandMask );
@@ -1886,7 +2098,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None && psOptions->pfnPreWarpChunkProcessor != NULL )
         eErr = psOptions->pfnPreWarpChunkProcessor(
-            (void *) &oWK, psOptions->pPreWarpProcessorArg );
+            &oWK, psOptions->pPreWarpProcessorArg );
 
 /* -------------------------------------------------------------------- */
 /*      Perform the warp.                                               */
@@ -1902,7 +2114,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None && psOptions->pfnPostWarpChunkProcessor != NULL )
         eErr = psOptions->pfnPostWarpChunkProcessor(
-            (void *) &oWK, psOptions->pPostWarpProcessorArg );
+            &oWK, psOptions->pPostWarpProcessorArg );
 
 /* -------------------------------------------------------------------- */
 /*      Release Warp Mutex, and acquire io mutex.                       */
@@ -1942,7 +2154,7 @@ CPLErr GDALWarpOperation::WarpRegionToBuffer(
 
     if( oWK.papanBandSrcValid != NULL )
     {
-        for( i = 0; i < oWK.nBands; i++ )
+        for( int i = 0; i < oWK.nBands; i++ )
             CPLFree( oWK.papanBandSrcValid[i] );
         CPLFree( oWK.papanBandSrcValid );
     }
@@ -1970,7 +2182,7 @@ CPLErr GDALWarpRegionToBuffer( GDALWarpOperationH hOperation,
 {
     VALIDATE_POINTER1( hOperation, "GDALWarpRegionToBuffer", CE_Failure );
 
-    return ( (GDALWarpOperation *)hOperation )->
+    return reinterpret_cast<GDALWarpOperation *>(hOperation )->
         WarpRegionToBuffer( nDstXOff, nDstYOff, nDstXSize, nDstYSize,
                             pDataBuf, eBufDataType,
                             nSrcXOff, nSrcYOff, nSrcXSize, nSrcYSize );
@@ -1989,65 +2201,72 @@ CPLErr GDALWarpOperation::CreateKernelMask( GDALWarpKernel *poKernel,
                                             int iBand, const char *pszType )
 
 {
-    void **ppMask;
-    int  nXSize, nYSize, nBitsPerPixel, nDefault;
+    void **ppMask = NULL;
+    int nXSize = 0;
+    int nYSize = 0;
+    int nBitsPerPixel = 0;
+    int nDefault = 0;
     int  nExtraElts = 0;
+    bool bDoMemset = true;
 
 /* -------------------------------------------------------------------- */
 /*      Get particulars of mask to be updated.                          */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszType,"BandSrcValid") )
+    if( EQUAL(pszType, "BandSrcValid") )
     {
         if( poKernel->papanBandSrcValid == NULL )
-            poKernel->papanBandSrcValid = (GUInt32 **)
-                CPLCalloc( sizeof(void*),poKernel->nBands);
+            poKernel->papanBandSrcValid = static_cast<GUInt32 **>(
+                CPLCalloc(sizeof(void*), poKernel->nBands));
 
-        ppMask = (void **) &(poKernel->papanBandSrcValid[iBand]);
+        ppMask =
+            reinterpret_cast<void **>(&(poKernel->papanBandSrcValid[iBand]));
         nExtraElts = WARP_EXTRA_ELTS;
         nXSize = poKernel->nSrcXSize;
         nYSize = poKernel->nSrcYSize;
         nBitsPerPixel = 1;
         nDefault = 0xff;
     }
-    else if( EQUAL(pszType,"UnifiedSrcValid") )
+    else if( EQUAL(pszType, "UnifiedSrcValid") )
     {
-        ppMask = (void **) &(poKernel->panUnifiedSrcValid);
+        ppMask = reinterpret_cast<void **>(&(poKernel->panUnifiedSrcValid));
         nExtraElts = WARP_EXTRA_ELTS;
         nXSize = poKernel->nSrcXSize;
         nYSize = poKernel->nSrcYSize;
         nBitsPerPixel = 1;
         nDefault = 0xff;
     }
-    else if( EQUAL(pszType,"UnifiedSrcDensity") )
+    else if( EQUAL(pszType, "UnifiedSrcDensity") )
     {
-        ppMask = (void **) &(poKernel->pafUnifiedSrcDensity);
+        ppMask = reinterpret_cast<void **>(&(poKernel->pafUnifiedSrcDensity));
         nExtraElts = WARP_EXTRA_ELTS;
         nXSize = poKernel->nSrcXSize;
         nYSize = poKernel->nSrcYSize;
         nBitsPerPixel = 32;
         nDefault = 0;
+        bDoMemset = false;
     }
-    else if( EQUAL(pszType,"DstValid") )
+    else if( EQUAL(pszType, "DstValid") )
     {
-        ppMask = (void **) &(poKernel->panDstValid);
+        ppMask = reinterpret_cast<void **>(&(poKernel->panDstValid));
         nXSize = poKernel->nDstXSize;
         nYSize = poKernel->nDstYSize;
         nBitsPerPixel = 1;
         nDefault = 0;
     }
-    else if( EQUAL(pszType,"DstDensity") )
+    else if( EQUAL(pszType, "DstDensity") )
     {
-        ppMask = (void **) &(poKernel->pafDstDensity);
+        ppMask = reinterpret_cast<void **>(&(poKernel->pafDstDensity));
         nXSize = poKernel->nDstXSize;
         nYSize = poKernel->nDstYSize;
         nBitsPerPixel = 32;
         nDefault = 0;
+        bDoMemset = false;
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Internal error in CreateKernelMask(%s).",
-                  pszType );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal error in CreateKernelMask(%s).",
+                 pszType);
         return CE_Failure;
     }
 
@@ -2056,19 +2275,19 @@ CPLErr GDALWarpOperation::CreateKernelMask( GDALWarpKernel *poKernel,
 /* -------------------------------------------------------------------- */
     if( *ppMask == NULL )
     {
-        GIntBig nBytes;
-
-        if( nBitsPerPixel == 32 )
-            nBytes = (static_cast<GIntBig>(nXSize) * nYSize + nExtraElts) * 4;
-        else
-            nBytes = (static_cast<GIntBig>(nXSize) * nYSize + nExtraElts + 31) / 8;
+        const GIntBig nBytes =
+          nBitsPerPixel == 32
+          ? (static_cast<GIntBig>(nXSize) * nYSize + nExtraElts) * 4
+          : (static_cast<GIntBig>(nXSize) * nYSize + nExtraElts + 31) / 8;
 
         const size_t nByteSize_t = static_cast<size_t>(nBytes);
 #if SIZEOF_VOIDP != 8
         if( static_cast<GIntBig>(nByteSize_t) != nBytes )
         {
-            CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate " CPL_FRMT_GIB " bytes",
-                      nBytes );
+            CPLError(
+                CE_Failure, CPLE_OutOfMemory,
+                "Cannot allocate " CPL_FRMT_GIB " bytes",
+                nBytes );
             return CE_Failure;
         }
 #endif
@@ -2080,24 +2299,24 @@ CPLErr GDALWarpOperation::CreateKernelMask( GDALWarpKernel *poKernel,
             return CE_Failure;
         }
 
-        memset( *ppMask, nDefault, nByteSize_t );
+        if( bDoMemset )
+            memset( *ppMask, nDefault, nByteSize_t );
     }
 
     return CE_None;
 }
 
-
-
 /************************************************************************/
 /*                        ComputeSourceWindow()                         */
 /************************************************************************/
 
-CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
-                                              int nDstXSize, int nDstYSize,
-                                              int *pnSrcXOff, int *pnSrcYOff,
-                                              int *pnSrcXSize, int *pnSrcYSize,
-                                              int *pnSrcXExtraSize, int *pnSrcYExtraSize,
-                                              double *pdfSrcFillRatio)
+CPLErr GDALWarpOperation::ComputeSourceWindow(
+    int nDstXOff, int nDstYOff,
+    int nDstXSize, int nDstYSize,
+    int *pnSrcXOff, int *pnSrcYOff,
+    int *pnSrcXSize, int *pnSrcYSize,
+    int *pnSrcXExtraSize, int *pnSrcYExtraSize,
+    double *pdfSrcFillRatio )
 
 {
 /* -------------------------------------------------------------------- */
@@ -2107,12 +2326,14 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
 /*      polar stereographic around the pole.   Also figure out the      */
 /*      sampling rate.                                                  */
 /* -------------------------------------------------------------------- */
-    double dfStepSize;
-    int nSampleMax, nStepCount = 21, bUseGrid;
+    int nSampleMax = 0;
+    int nStepCount = 21;
     int *pabSuccess = NULL;
-    double *padfX, *padfY, *padfZ;
-    int    nSamplePoints;
-    double dfRatio;
+    double *padfX = NULL;
+    double *padfY = NULL;
+    double *padfZ = NULL;
+    int nSamplePoints = 0;
+    double dfRatio = 0.0;
 
     if( CSLFetchNameValue( psOptions->papszWarpOptions,
                            "SAMPLE_STEPS" ) != NULL )
@@ -2120,19 +2341,19 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
         nStepCount =
             atoi(CSLFetchNameValue( psOptions->papszWarpOptions,
                                     "SAMPLE_STEPS" ));
-        nStepCount = MAX(2,nStepCount);
+        nStepCount = std::max(2, nStepCount);
     }
 
-    dfStepSize = 1.0 / (nStepCount-1);
+    const double dfStepSize = 1.0 / (nStepCount - 1);
 
-    bUseGrid = CSLFetchBoolean( psOptions->papszWarpOptions,
-                                "SAMPLE_GRID", FALSE );
+    bool bUseGrid =
+        CPLFetchBool(psOptions->papszWarpOptions, "SAMPLE_GRID", false);
 
   TryAgainWithGrid:
     nSamplePoints = 0;
     if( bUseGrid )
     {
-        if (nStepCount > INT_MAX / nStepCount)
+        if( nStepCount > INT_MAX / nStepCount )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Too many steps : %d", nStepCount);
@@ -2142,7 +2363,7 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
     }
     else
     {
-        if (nStepCount > INT_MAX / 4)
+        if( nStepCount > INT_MAX / 4 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Too many steps : %d", nStepCount);
@@ -2151,9 +2372,11 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
         nSampleMax = nStepCount * 4;
     }
 
-    pabSuccess = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nSampleMax);
-    padfX = (double *) VSI_MALLOC2_VERBOSE(sizeof(double) * 3, nSampleMax);
-    if (pabSuccess == NULL || padfX == NULL)
+    pabSuccess =
+        static_cast<int *>(VSI_MALLOC2_VERBOSE(sizeof(int), nSampleMax));
+    padfX = static_cast<double *>(VSI_MALLOC2_VERBOSE(sizeof(double) * 3,
+                                                      nSampleMax));
+    if( pabSuccess == NULL || padfX == NULL )
     {
         CPLFree( padfX );
         CPLFree( pabSuccess );
@@ -2167,9 +2390,7 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
 /* -------------------------------------------------------------------- */
     if( bUseGrid )
     {
-        double dfRatioY;
-
-        for( dfRatioY = 0.0;
+        for( double dfRatioY = 0.0;
              dfRatioY <= 1.0 + dfStepSize*0.5;
              dfRatioY += dfStepSize )
         {
@@ -2188,7 +2409,9 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
  /* -------------------------------------------------------------------- */
     else
     {
-        for( dfRatio = 0.0; dfRatio <= 1.0 + dfStepSize*0.5; dfRatio += dfStepSize )
+        for( dfRatio = 0.0;
+             dfRatio <= 1.0 + dfStepSize*0.5;
+             dfRatio += dfStepSize )
         {
             // Along top
             padfX[nSamplePoints]   = dfRatio * nDstXSize + nDstXOff;
@@ -2225,7 +2448,7 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
         CPLFree( pabSuccess );
 
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "GDALWarperOperation::ComputeSourceWindow() failed because\n"
+                  "GDALWarperOperation::ComputeSourceWindow() failed because "
                   "the pfnTransformer failed." );
         return CE_Failure;
     }
@@ -2233,11 +2456,14 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
 /* -------------------------------------------------------------------- */
 /*      Collect the bounds, ignoring any failed points.                 */
 /* -------------------------------------------------------------------- */
-    double dfMinXOut=0.0, dfMinYOut=0.0, dfMaxXOut=0.0, dfMaxYOut=0.0;
-    int    bGotInitialPoint = FALSE;
-    int    nFailedCount = 0, i;
+    double dfMinXOut = 0.0;
+    double dfMinYOut = 0.0;
+    double dfMaxXOut = 0.0;
+    double dfMaxYOut = 0.0;
+    bool bGotInitialPoint = false;
+    int nFailedCount = 0;
 
-    for( i = 0; i < nSamplePoints; i++ )
+    for( int i = 0; i < nSamplePoints; i++ )
     {
         if( !pabSuccess[i] )
         {
@@ -2247,16 +2473,18 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
 
         if( !bGotInitialPoint )
         {
-            bGotInitialPoint = TRUE;
-            dfMinXOut = dfMaxXOut = padfX[i];
-            dfMinYOut = dfMaxYOut = padfY[i];
+            bGotInitialPoint = true;
+            dfMinXOut = padfX[i];
+            dfMaxXOut = padfX[i];
+            dfMinYOut = padfY[i];
+            dfMaxYOut = padfY[i];
         }
         else
         {
-            dfMinXOut = MIN(dfMinXOut,padfX[i]);
-            dfMinYOut = MIN(dfMinYOut,padfY[i]);
-            dfMaxXOut = MAX(dfMaxXOut,padfX[i]);
-            dfMaxYOut = MAX(dfMaxYOut,padfY[i]);
+            dfMinXOut = std::min(dfMinXOut, padfX[i]);
+            dfMinYOut = std::min(dfMinYOut, padfY[i]);
+            dfMaxXOut = std::max(dfMaxXOut, padfX[i]);
+            dfMaxYOut = std::max(dfMaxYOut, padfY[i]);
         }
     }
 
@@ -2270,7 +2498,7 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
 /* -------------------------------------------------------------------- */
     if( !bUseGrid && nFailedCount > 0 )
     {
-        bUseGrid = TRUE;
+        bUseGrid = true;
         goto TryAgainWithGrid;
     }
 
@@ -2281,7 +2509,7 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
     if( nFailedCount > nSamplePoints - 5 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Too many points (%d out of %d) failed to transform,\n"
+                  "Too many points (%d out of %d) failed to transform, "
                   "unable to compute output bounds.",
                   nFailedCount, nSamplePoints );
         return CE_Failure;
@@ -2289,7 +2517,8 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
 
     if( nFailedCount > 0 )
         CPLDebug( "GDAL",
-                  "GDALWarpOperation::ComputeSourceWindow() %d out of %d points failed to transform.",
+                  "GDALWarpOperation::ComputeSourceWindow() %d out of %d "
+                  "points failed to transform.",
                   nFailedCount, nSamplePoints );
 
 /* -------------------------------------------------------------------- */
@@ -2312,7 +2541,7 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
         if( pnSrcYExtraSize )
             *pnSrcYExtraSize = 0;
         if( pdfSrcFillRatio )
-            *pdfSrcFillRatio = 0;
+            *pdfSrcFillRatio = 0.0;
         return CE_None;
     }
 
@@ -2325,14 +2554,16 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
 /* -------------------------------------------------------------------- */
     int nResWinSize = GWKGetFilterRadius(psOptions->eResampleAlg);
 
-    /* Take scaling into account */
-    double dfXScale = (double)nDstXSize / (dfMaxXOut - dfMinXOut);
-    double dfYScale = (double)nDstYSize / (dfMaxYOut - dfMinYOut);
-    int nXRadius = ( dfXScale < 1.0 ) ?
-        (int)ceil( nResWinSize / dfXScale ) :nResWinSize;
-    int nYRadius = ( dfYScale < 1.0 ) ?
-        (int)ceil( nResWinSize / dfYScale ) : nResWinSize;
-    nResWinSize = MAX(nXRadius, nYRadius);
+    // Take scaling into account.
+    const double dfXScale =
+        static_cast<double>(nDstXSize) / (dfMaxXOut - dfMinXOut);
+    const double dfYScale =
+        static_cast<double>(nDstYSize) / (dfMaxYOut - dfMinYOut);
+    const int nXRadius = dfXScale < 1.0 ?
+        static_cast<int>(ceil( nResWinSize / dfXScale )) : nResWinSize;
+    const int nYRadius = dfYScale < 1.0 ?
+        static_cast<int>(ceil( nResWinSize / dfYScale )) : nResWinSize;
+    nResWinSize = std::max(nXRadius, nYRadius);
 
 /* -------------------------------------------------------------------- */
 /*      Allow addition of extra sample pixels to source window to       */
@@ -2347,19 +2578,24 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
             CSLFetchNameValue( psOptions->papszWarpOptions, "SOURCE_EXTRA" ));
     }
     else if( nFailedCount > 0 )
+    {
         nResWinSize += 10;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      return bounds.                                                  */
 /* -------------------------------------------------------------------- */
-    /*CPLDebug("WARP", "dst=(%d,%d,%d,%d) raw src=(minx=%.8g,miny=%.8g,maxx=%.8g,maxy=%.8g)",
-             nDstXOff, nDstYOff, nDstXSize, nDstYSize,
-             dfMinXOut, dfMinYOut, dfMaxXOut, dfMaxYOut);
-    */
-    *pnSrcXOff = MAX(0,(int) floor( dfMinXOut ) );
-    *pnSrcYOff = MAX(0,(int) floor( dfMinYOut ) );
-    *pnSrcXOff = MIN(*pnSrcXOff,nRasterXSize);
-    *pnSrcYOff = MIN(*pnSrcYOff,nRasterYSize);
+#if DEBUG_VERBOSE
+    CPLDebug(
+        "WARP",
+        "dst=(%d,%d,%d,%d) raw src=(minx=%.8g,miny=%.8g,maxx=%.8g,maxy=%.8g)",
+        nDstXOff, nDstYOff, nDstXSize, nDstYSize,
+        dfMinXOut, dfMinYOut, dfMaxXOut, dfMaxYOut);
+#endif
+    *pnSrcXOff = std::max(0, static_cast<int>(floor(dfMinXOut)));
+    *pnSrcYOff = std::max(0, static_cast<int>(floor(dfMinYOut)));
+    *pnSrcXOff = std::min(*pnSrcXOff, nRasterXSize);
+    *pnSrcYOff = std::min(*pnSrcYOff, nRasterYSize);
 
     double dfCeilMaxXOut = ceil(dfMaxXOut);
     if( dfCeilMaxXOut > INT_MAX )
@@ -2368,24 +2604,26 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
     if( dfCeilMaxYOut > INT_MAX )
         dfCeilMaxYOut = INT_MAX;
 
-    int nSrcXSizeRaw = MIN( nRasterXSize - *pnSrcXOff,
-                       ((int) dfCeilMaxXOut) - *pnSrcXOff );
-    int nSrcYSizeRaw = MIN( nRasterYSize - *pnSrcYOff,
-                       ((int) dfCeilMaxYOut) - *pnSrcYOff );
-    nSrcXSizeRaw = MAX(0,nSrcXSizeRaw);
-    nSrcYSizeRaw = MAX(0,nSrcYSizeRaw);
-
-    *pnSrcXOff = MAX(0,(int) floor( dfMinXOut ) - nResWinSize );
-    *pnSrcYOff = MAX(0,(int) floor( dfMinYOut ) - nResWinSize );
-    *pnSrcXOff = MIN(*pnSrcXOff,nRasterXSize);
-    *pnSrcYOff = MIN(*pnSrcYOff,nRasterYSize);
-
-    *pnSrcXSize = MIN( nRasterXSize - *pnSrcXOff,
-                       ((int) dfCeilMaxXOut) - *pnSrcXOff + nResWinSize );
-    *pnSrcYSize = MIN( nRasterYSize - *pnSrcYOff,
-                       ((int) dfCeilMaxYOut) - *pnSrcYOff + nResWinSize );
-    *pnSrcXSize = MAX(0,*pnSrcXSize);
-    *pnSrcYSize = MAX(0,*pnSrcYSize);
+    int nSrcXSizeRaw = std::min(nRasterXSize - *pnSrcXOff,
+                                static_cast<int>(dfCeilMaxXOut) - *pnSrcXOff);
+    int nSrcYSizeRaw = std::min(nRasterYSize - *pnSrcYOff,
+                                static_cast<int>(dfCeilMaxYOut) - *pnSrcYOff);
+    nSrcXSizeRaw = std::max(0, nSrcXSizeRaw);
+    nSrcYSizeRaw = std::max(0, nSrcYSizeRaw);
+
+    *pnSrcXOff = std::max(0, static_cast<int>(floor(dfMinXOut)) - nResWinSize);
+    *pnSrcYOff = std::max(0, static_cast<int>(floor(dfMinYOut)) - nResWinSize);
+    *pnSrcXOff = std::min(*pnSrcXOff, nRasterXSize);
+    *pnSrcYOff = std::min(*pnSrcYOff, nRasterYSize);
+
+    *pnSrcXSize =
+        std::min(nRasterXSize - *pnSrcXOff,
+                 static_cast<int>(dfCeilMaxXOut) - *pnSrcXOff + nResWinSize);
+    *pnSrcYSize =
+        std::min(nRasterYSize - *pnSrcYOff,
+                 static_cast<int>(dfCeilMaxYOut) - *pnSrcYOff + nResWinSize);
+    *pnSrcXSize = std::max(0, *pnSrcXSize);
+    *pnSrcYSize = std::max(0, *pnSrcYSize);
 
     if( pnSrcXExtraSize )
         *pnSrcXExtraSize = *pnSrcXSize - nSrcXSizeRaw;
@@ -2393,10 +2631,13 @@ CPLErr GDALWarpOperation::ComputeSourceWindow(int nDstXOff, int nDstYOff,
         *pnSrcYExtraSize = *pnSrcYSize - nSrcYSizeRaw;
 
     // Computed the ratio of the clamped source raster window size over
-    // the unclamped source raster window size
+    // the unclamped source raster window size.
     if( pdfSrcFillRatio )
-        *pdfSrcFillRatio = *pnSrcXSize * *pnSrcYSize / MAX(1.0,
-        (dfMaxXOut - dfMinXOut + 2 * nResWinSize) * (dfMaxYOut - dfMinYOut + 2 * nResWinSize));
+        *pdfSrcFillRatio =
+            *pnSrcXSize * *pnSrcYSize /
+            std::max(1.0,
+                     (dfMaxXOut - dfMinXOut + 2 * nResWinSize) *
+                     (dfMaxYOut - dfMinYOut + 2 * nResWinSize));
 
     return CE_None;
 }
@@ -2411,12 +2652,12 @@ void GDALWarpOperation::ReportTiming( const char * pszMessage )
     if( !bReportTimings )
         return;
 
-    unsigned long nNewTime = VSITime(NULL);
+    const unsigned long nNewTime = VSITime(NULL);
 
     if( pszMessage != NULL )
     {
         CPLDebug( "WARP_TIMING", "%s: %lds",
-                  pszMessage, (long)(nNewTime - nLastTimeReported) );
+                  pszMessage, static_cast<long>(nNewTime - nLastTimeReported) );
     }
 
     nLastTimeReported = nNewTime;
diff --git a/alg/gvgcpfit.h b/alg/gvgcpfit.h
index 4496c59..9bdb15d 100644
--- a/alg/gvgcpfit.h
+++ b/alg/gvgcpfit.h
@@ -1,3 +1,5 @@
+/* $Id: gvgcpfit.h 35882 2016-10-24 04:10:14Z goatbar $ */
+
 #ifndef GVGCPFIT_H_INCLUDED
 #define GVGCPFIT_H_INCLUDED
 
@@ -11,7 +13,6 @@
 #define SUCCESS 0
 #define ABORT -1
 
-
 /*------------------------ Start of file CURVEFIT.H -----------------------*/
 
 /*
@@ -24,7 +25,6 @@
 ******************************************************************************
 */
 
-
 #ifndef CURVEFIT_H
 #define CURVEFIT_H
 
@@ -41,15 +41,10 @@ EXTERNAL void svdvar(double **v, int ma, double w[], double **cvm);
 
 EXTERNAL int svdcmp(double **a, int m, int n, double *w, double **v);
 
-
 #endif
 
-
 /*-------------------------- End of file CURVEFIT.H -----------------------*/
 
-
-
-
 /*----------------------------- FILE polyfit.h ----------------------------*/
 #ifndef POLYFIT_H
 #define POLYFIT_H
@@ -84,11 +79,8 @@ EXTERNAL int ThreeDPolyFit( double *rms_err, double *coeffs_array,
 
 EXTERNAL double ThreeDPolyEval( double *coeff, int order, double x, double y, double z );
 
-
-
 #endif /* POLYFIT_H */
 
-
 /*---------------------- End of FILE polyfit.h ----------------------------*/
 
 #endif /* ndef _GVGCPFIT_INCLUDED */
diff --git a/alg/libqhull/COPYING.txt b/alg/internal_libqhull/COPYING.txt
similarity index 100%
rename from alg/libqhull/COPYING.txt
rename to alg/internal_libqhull/COPYING.txt
diff --git a/alg/libqhull/README.txt b/alg/internal_libqhull/README.txt
similarity index 100%
rename from alg/libqhull/README.txt
rename to alg/internal_libqhull/README.txt
diff --git a/alg/libqhull/geom.c b/alg/internal_libqhull/geom.c
similarity index 100%
rename from alg/libqhull/geom.c
rename to alg/internal_libqhull/geom.c
diff --git a/alg/libqhull/geom.h b/alg/internal_libqhull/geom.h
similarity index 100%
rename from alg/libqhull/geom.h
rename to alg/internal_libqhull/geom.h
diff --git a/alg/internal_libqhull/geom2.c b/alg/internal_libqhull/geom2.c
new file mode 100644
index 0000000..34cafef
--- /dev/null
+++ b/alg/internal_libqhull/geom2.c
@@ -0,0 +1,2084 @@
+/*<html><pre>  -<a                             href="qh-geom.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+
+   geom2.c
+   infrequently used geometric routines of qhull
+
+   see qh-geom.htm and geom.h
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/geom2.c#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+
+   frequently used code goes into geom.c
+*/
+
+#include "qhull_a.h"
+
+/*================== functions in alphabetic order ============*/
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="copypoints">-</a>
+
+  qh_copypoints( points, numpoints, dimension)
+    return qh_malloc'd copy of points
+*/
+coordT *qh_copypoints(coordT *points, int numpoints, int dimension) {
+  int size;
+  coordT *newpoints;
+
+  size= numpoints * dimension * (int)sizeof(coordT);
+  if (!(newpoints=(coordT*)qh_malloc((size_t)size))) {
+    qh_fprintf(qh ferr, 6004, "qhull error: insufficient memory to copy %d points\n",
+        numpoints);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  /* newpoints cannot be NULL since above qh_errexit didn't return */
+  /* coverity[var_deref_model] */
+  memcpy((char *)newpoints, (char *)points, (size_t)size);
+  return newpoints;
+} /* copypoints */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="crossproduct">-</a>
+
+  qh_crossproduct( dim, vecA, vecB, vecC )
+    crossproduct of 2 dim vectors
+    C= A x B
+
+  notes:
+    from Glasner, Graphics Gems I, p. 639
+    only defined for dim==3
+*/
+void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
+
+  if (dim == 3) {
+    vecC[0]=   det2_(vecA[1], vecA[2],
+                     vecB[1], vecB[2]);
+    vecC[1]= - det2_(vecA[0], vecA[2],
+                     vecB[0], vecB[2]);
+    vecC[2]=   det2_(vecA[0], vecA[1],
+                     vecB[0], vecB[1]);
+  }
+} /* vcross */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="determinant">-</a>
+
+  qh_determinant( rows, dim, nearzero )
+    compute signed determinant of a square matrix
+    uses qh.NEARzero to test for degenerate matrices
+
+  returns:
+    determinant
+    overwrites rows and the matrix
+    if dim == 2 or 3
+      nearzero iff determinant < qh NEARzero[dim-1]
+      (!quite correct, not critical)
+    if dim >= 4
+      nearzero iff diagonal[k] < qh NEARzero[k]
+*/
+realT qh_determinant(realT **rows, int dim, boolT *nearzero) {
+  realT det=0;
+  int i;
+  boolT sign= False;
+
+  *nearzero= False;
+  if (dim < 2) {
+    qh_fprintf(qh ferr, 6005, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }else if (dim == 2) {
+    det= det2_(rows[0][0], rows[0][1],
+                 rows[1][0], rows[1][1]);
+    if (fabs_(det) < qh NEARzero[1])  /* not really correct, what should this be? */
+      *nearzero= True;
+  }else if (dim == 3) {
+    det= det3_(rows[0][0], rows[0][1], rows[0][2],
+                 rows[1][0], rows[1][1], rows[1][2],
+                 rows[2][0], rows[2][1], rows[2][2]);
+    if (fabs_(det) < qh NEARzero[2])  /* not really correct, what should this be? */
+      *nearzero= True;
+  }else {
+    qh_gausselim(rows, dim, dim, &sign, nearzero);  /* if nearzero, diagonal still ok*/
+    det= 1.0;
+    for (i=dim; i--; )
+      det *= (rows[i])[i];
+    if (sign)
+      det= -det;
+  }
+  return det;
+} /* determinant */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="detjoggle">-</a>
+
+  qh_detjoggle( points, numpoints, dimension )
+    determine default max joggle for point array
+      as qh_distround * qh_JOGGLEdefault
+
+  returns:
+    initial value for JOGGLEmax from points and REALepsilon
+
+  notes:
+    computes DISTround since qh_maxmin not called yet
+    if qh SCALElast, last dimension will be scaled later to MAXwidth
+
+    loop duplicated from qh_maxmin
+*/
+realT qh_detjoggle(pointT *points, int numpoints, int dimension) {
+  realT abscoord, distround, joggle, maxcoord, mincoord;
+  pointT *point, *pointtemp;
+  realT maxabs= -REALmax;
+  realT sumabs= 0;
+  realT maxwidth= 0;
+  int k;
+
+  for (k=0; k < dimension; k++) {
+    if (qh SCALElast && k == dimension-1)
+      abscoord= maxwidth;
+    else if (qh DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
+      abscoord= 2 * maxabs * maxabs;  /* may be low by qh hull_dim/2 */
+    else {
+      maxcoord= -REALmax;
+      mincoord= REALmax;
+      FORALLpoint_(points, numpoints) {
+        maximize_(maxcoord, point[k]);
+        minimize_(mincoord, point[k]);
+      }
+      maximize_(maxwidth, maxcoord-mincoord);
+      abscoord= fmax_(maxcoord, -mincoord);
+    }
+    sumabs += abscoord;
+    maximize_(maxabs, abscoord);
+  } /* for k */
+  distround= qh_distround(qh hull_dim, maxabs, sumabs);
+  joggle= distround * qh_JOGGLEdefault;
+  maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
+  trace2((qh ferr, 2001, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
+  return joggle;
+} /* detjoggle */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="detroundoff">-</a>
+
+  qh_detroundoff()
+    determine maximum roundoff errors from
+      REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord,
+      qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
+
+    accounts for qh.SETroundoff, qh.RANDOMdist, qh MERGEexact
+      qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
+      qh.postmerge_centrum, qh.MINoutside,
+      qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
+
+  returns:
+    sets qh.DISTround, etc. (see below)
+    appends precision constants to qh.qhull_options
+
+  see:
+    qh_maxmin() for qh.NEARzero
+
+  design:
+    determine qh.DISTround for distance computations
+    determine minimum denominators for qh_divzero
+    determine qh.ANGLEround for angle computations
+    adjust qh.premerge_cos,... for roundoff error
+    determine qh.ONEmerge for maximum error due to a single merge
+    determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
+      qh.MINoutside, qh.WIDEfacet
+    initialize qh.max_vertex and qh.minvertex
+*/
+void qh_detroundoff(void) {
+
+  qh_option("_max-width", NULL, &qh MAXwidth);
+  if (!qh SETroundoff) {
+    qh DISTround= qh_distround(qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
+    if (qh RANDOMdist)
+      qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
+    qh_option("Error-roundoff", NULL, &qh DISTround);
+  }
+  qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
+  qh MINdenom_1_2= sqrt(qh MINdenom_1 * qh hull_dim) ;  /* if will be normalized */
+  qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
+                                              /* for inner product */
+  qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
+  if (qh RANDOMdist)
+    qh ANGLEround += qh RANDOMfactor;
+  if (qh premerge_cos < REALmax/2) {
+    qh premerge_cos -= qh ANGLEround;
+    if (qh RANDOMdist)
+      qh_option("Angle-premerge-with-random", NULL, &qh premerge_cos);
+  }
+  if (qh postmerge_cos < REALmax/2) {
+    qh postmerge_cos -= qh ANGLEround;
+    if (qh RANDOMdist)
+      qh_option("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
+  }
+  qh premerge_centrum += 2 * qh DISTround;    /*2 for centrum and distplane()*/
+  qh postmerge_centrum += 2 * qh DISTround;
+  if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
+    qh_option("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
+  if (qh RANDOMdist && qh POSTmerge)
+    qh_option("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
+  { /* compute ONEmerge, max vertex offset for merging simplicial facets */
+    realT maxangle= 1.0, maxrho;
+
+    minimize_(maxangle, qh premerge_cos);
+    minimize_(maxangle, qh postmerge_cos);
+    /* max diameter * sin theta + DISTround for vertex to its hyperplane */
+    qh ONEmerge= sqrt((realT)qh hull_dim) * qh MAXwidth *
+      sqrt(1.0 - maxangle * maxangle) + qh DISTround;
+    maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
+    maximize_(qh ONEmerge, maxrho);
+    maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
+    maximize_(qh ONEmerge, maxrho);
+    if (qh MERGING)
+      qh_option("_one-merge", NULL, &qh ONEmerge);
+  }
+  qh NEARinside= qh ONEmerge * qh_RATIOnearinside; /* only used if qh KEEPnearinside */
+  if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
+    realT maxdist;             /* adjust qh.NEARinside for joggle */
+    qh KEEPnearinside= True;
+    maxdist= sqrt((realT)qh hull_dim) * qh JOGGLEmax + qh DISTround;
+    maxdist= 2*maxdist;        /* vertex and coplanar point can joggle in opposite directions */
+    maximize_(qh NEARinside, maxdist);  /* must agree with qh_nearcoplanar() */
+  }
+  if (qh KEEPnearinside)
+    qh_option("_near-inside", NULL, &qh NEARinside);
+  if (qh JOGGLEmax < qh DISTround) {
+    qh_fprintf(qh ferr, 6006, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
+         qh JOGGLEmax, qh DISTround);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh MINvisible > REALmax/2) {
+    if (!qh MERGING)
+      qh MINvisible= qh DISTround;
+    else if (qh hull_dim <= 3)
+      qh MINvisible= qh premerge_centrum;
+    else
+      qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
+    if (qh APPROXhull && qh MINvisible > qh MINoutside)
+      qh MINvisible= qh MINoutside;
+    qh_option("Visible-distance", NULL, &qh MINvisible);
+  }
+  if (qh MAXcoplanar > REALmax/2) {
+    qh MAXcoplanar= qh MINvisible;
+    qh_option("U-coplanar-distance", NULL, &qh MAXcoplanar);
+  }
+  if (!qh APPROXhull) {             /* user may specify qh MINoutside */
+    qh MINoutside= 2 * qh MINvisible;
+    if (qh premerge_cos < REALmax/2)
+      maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
+    qh_option("Width-outside", NULL, &qh MINoutside);
+  }
+  qh WIDEfacet= qh MINoutside;
+  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar);
+  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible);
+  qh_option("_wide-facet", NULL, &qh WIDEfacet);
+  if (qh MINvisible > qh MINoutside + 3 * REALepsilon
+  && !qh BESToutside && !qh FORCEoutput)
+    qh_fprintf(qh ferr, 7001, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g.  Flipped facets are likely.\n",
+             qh MINvisible, qh MINoutside);
+  qh max_vertex= qh DISTround;
+  qh min_vertex= -qh DISTround;
+  /* numeric constants reported in printsummary */
+} /* detroundoff */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="detsimplex">-</a>
+
+  qh_detsimplex( apex, points, dim, nearzero )
+    compute determinant of a simplex with point apex and base points
+
+  returns:
+     signed determinant and nearzero from qh_determinant
+
+  notes:
+     uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
+
+  design:
+    construct qm_matrix by subtracting apex from points
+    compute determinate
+*/
+realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
+  pointT *coorda, *coordp, *gmcoord, *point, **pointp;
+  coordT **rows;
+  int k,  i=0;
+  realT det;
+
+  zinc_(Zdetsimplex);
+  gmcoord= qh gm_matrix;
+  rows= qh gm_row;
+  FOREACHpoint_(points) {
+    if (i == dim)
+      break;
+    rows[i++]= gmcoord;
+    coordp= point;
+    coorda= apex;
+    for (k=dim; k--; )
+      *(gmcoord++)= *coordp++ - *coorda++;
+  }
+  if (i < dim) {
+    qh_fprintf(qh ferr, 6007, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n",
+               i, dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  det= qh_determinant(rows, dim, nearzero);
+  trace2((qh ferr, 2002, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
+          det, qh_pointid(apex), dim, *nearzero));
+  return det;
+} /* detsimplex */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="distnorm">-</a>
+
+  qh_distnorm( dim, point, normal, offset )
+    return distance from point to hyperplane at normal/offset
+
+  returns:
+    dist
+
+  notes:
+    dist > 0 if point is outside of hyperplane
+
+  see:
+    qh_distplane in geom.c
+*/
+realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp) {
+  coordT *normalp= normal, *coordp= point;
+  realT dist;
+  int k;
+
+  dist= *offsetp;
+  for (k=dim; k--; )
+    dist += *(coordp++) * *(normalp++);
+  return dist;
+} /* distnorm */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="distround">-</a>
+
+  qh_distround(dimension, maxabs, maxsumabs )
+    compute maximum round-off error for a distance computation
+      to a normalized hyperplane
+    maxabs is the maximum absolute value of a coordinate
+    maxsumabs is the maximum possible sum of absolute coordinate values
+
+  returns:
+    max dist round for REALepsilon
+
+  notes:
+    calculate roundoff error according to
+    Lemma 3.2-1 of Golub and van Loan "Matrix Computation"
+    use sqrt(dim) since one vector is normalized
+      or use maxsumabs since one vector is < 1
+*/
+realT qh_distround(int dimension, realT maxabs, realT maxsumabs) {
+  realT maxdistsum, maxround;
+
+  maxdistsum= sqrt((realT)dimension) * maxabs;
+  minimize_( maxdistsum, maxsumabs);
+  maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
+              /* adds maxabs for offset */
+  trace4((qh ferr, 4008, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
+                 maxround, maxabs, maxsumabs, maxdistsum));
+  return maxround;
+} /* distround */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="divzero">-</a>
+
+  qh_divzero( numer, denom, mindenom1, zerodiv )
+    divide by a number that's nearly zero
+    mindenom1= minimum denominator for dividing into 1.0
+
+  returns:
+    quotient
+    sets zerodiv and returns 0.0 if it would overflow
+
+  design:
+    if numer is nearly zero and abs(numer) < abs(denom)
+      return numer/denom
+    else if numer is nearly zero
+      return 0 and zerodiv
+    else if denom/numer non-zero
+      return numer/denom
+    else
+      return 0 and zerodiv
+*/
+realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
+  realT temp, numerx, denomx;
+
+
+  if (numer < mindenom1 && numer > -mindenom1) {
+    numerx= fabs_(numer);
+    denomx= fabs_(denom);
+    if (numerx < denomx) {
+      *zerodiv= False;
+      return numer/denom;
+    }else {
+      *zerodiv= True;
+      return 0.0;
+    }
+  }
+  temp= denom/numer;
+  if (temp > mindenom1 || temp < -mindenom1) {
+    *zerodiv= False;
+    return numer/denom;
+  }else {
+    *zerodiv= True;
+    return 0.0;
+  }
+} /* divzero */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="facetarea">-</a>
+
+  qh_facetarea( facet )
+    return area for a facet
+
+  notes:
+    if non-simplicial,
+      uses centrum to triangulate facet and sums the projected areas.
+    if (qh DELAUNAY),
+      computes projected area instead for last coordinate
+    assumes facet->normal exists
+    projecting tricoplanar facets to the hyperplane does not appear to make a difference
+
+  design:
+    if simplicial
+      compute area
+    else
+      for each ridge
+        compute area from centrum to ridge
+    negate area if upper Delaunay facet
+*/
+realT qh_facetarea(facetT *facet) {
+  vertexT *apex;
+  pointT *centrum;
+  realT area= 0.0;
+  ridgeT *ridge, **ridgep;
+
+  if (facet->simplicial) {
+    apex= SETfirstt_(facet->vertices, vertexT);
+    area= qh_facetarea_simplex(qh hull_dim, apex->point, facet->vertices,
+                    apex, facet->toporient, facet->normal, &facet->offset);
+  }else {
+    if (qh CENTERtype == qh_AScentrum)
+      centrum= facet->center;
+    else
+      centrum= qh_getcentrum(facet);
+    FOREACHridge_(facet->ridges)
+      area += qh_facetarea_simplex(qh hull_dim, centrum, ridge->vertices,
+                 NULL, (boolT)(ridge->top == facet),  facet->normal, &facet->offset);
+    if (qh CENTERtype != qh_AScentrum)
+      qh_memfree(centrum, qh normal_size);
+  }
+  if (facet->upperdelaunay && qh DELAUNAY)
+    area= -area;  /* the normal should be [0,...,1] */
+  trace4((qh ferr, 4009, "qh_facetarea: f%d area %2.2g\n", facet->id, area));
+  return area;
+} /* facetarea */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="facetarea_simplex">-</a>
+
+  qh_facetarea_simplex( dim, apex, vertices, notvertex, toporient, normal, offset )
+    return area for a simplex defined by
+      an apex, a base of vertices, an orientation, and a unit normal
+    if simplicial or tricoplanar facet,
+      notvertex is defined and it is skipped in vertices
+
+  returns:
+    computes area of simplex projected to plane [normal,offset]
+    returns 0 if vertex too far below plane (qh WIDEfacet)
+      vertex can't be apex of tricoplanar facet
+
+  notes:
+    if (qh DELAUNAY),
+      computes projected area instead for last coordinate
+    uses qh gm_matrix/gm_row and qh hull_dim
+    helper function for qh_facetarea
+
+  design:
+    if Notvertex
+      translate simplex to apex
+    else
+      project simplex to normal/offset
+      translate simplex to apex
+    if Delaunay
+      set last row/column to 0 with -1 on diagonal
+    else
+      set last row to Normal
+    compute determinate
+    scale and flip sign for area
+*/
+realT qh_facetarea_simplex(int dim, coordT *apex, setT *vertices,
+        vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset) {
+  pointT *coorda, *coordp, *gmcoord;
+  coordT **rows, *normalp;
+  int k,  i=0;
+  realT area, dist;
+  vertexT *vertex, **vertexp;
+  boolT nearzero;
+
+  gmcoord= qh gm_matrix;
+  rows= qh gm_row;
+  FOREACHvertex_(vertices) {
+    if (vertex == notvertex)
+      continue;
+    rows[i++]= gmcoord;
+    coorda= apex;
+    coordp= vertex->point;
+    normalp= normal;
+    if (notvertex) {
+      for (k=dim; k--; )
+        *(gmcoord++)= *coordp++ - *coorda++;
+    }else {
+      dist= *offset;
+      for (k=dim; k--; )
+        dist += *coordp++ * *normalp++;
+      if (dist < -qh WIDEfacet) {
+        zinc_(Znoarea);
+        return 0.0;
+      }
+      coordp= vertex->point;
+      normalp= normal;
+      for (k=dim; k--; )
+        *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
+    }
+  }
+  if (i != dim-1) {
+    qh_fprintf(qh ferr, 6008, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n",
+               i, dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  rows[i]= gmcoord;
+  if (qh DELAUNAY) {
+    for (i=0; i < dim-1; i++)
+      rows[i][dim-1]= 0.0;
+    for (k=dim; k--; )
+      *(gmcoord++)= 0.0;
+    rows[dim-1][dim-1]= -1.0;
+  }else {
+    normalp= normal;
+    for (k=dim; k--; )
+      *(gmcoord++)= *normalp++;
+  }
+  zinc_(Zdetsimplex);
+  area= qh_determinant(rows, dim, &nearzero);
+  if (toporient)
+    area= -area;
+  area *= qh AREAfactor;
+  trace4((qh ferr, 4010, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
+          area, qh_pointid(apex), toporient, nearzero));
+  return area;
+} /* facetarea_simplex */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="facetcenter">-</a>
+
+  qh_facetcenter( vertices )
+    return Voronoi center (Voronoi vertex) for a facet's vertices
+
+  returns:
+    return temporary point equal to the center
+
+  see:
+    qh_voronoi_center()
+*/
+pointT *qh_facetcenter(setT *vertices) {
+  setT *points= qh_settemp(qh_setsize(vertices));
+  vertexT *vertex, **vertexp;
+  pointT *center;
+
+  FOREACHvertex_(vertices)
+    qh_setappend(&points, vertex->point);
+  center= qh_voronoi_center(qh hull_dim-1, points);
+  qh_settempfree(&points);
+  return center;
+} /* facetcenter */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="findgooddist">-</a>
+
+  qh_findgooddist( point, facetA, dist, facetlist )
+    find best good facet visible for point from facetA
+    assumes facetA is visible from point
+
+  returns:
+    best facet, i.e., good facet that is furthest from point
+      distance to best facet
+      NULL if none
+
+    moves good, visible facets (and some other visible facets)
+      to end of qh facet_list
+
+  notes:
+    uses qh visit_id
+
+  design:
+    initialize bestfacet if facetA is good
+    move facetA to end of facetlist
+    for each facet on facetlist
+      for each unvisited neighbor of facet
+        move visible neighbors to end of facetlist
+        update best good neighbor
+        if no good neighbors, update best facet
+*/
+facetT *qh_findgooddist(pointT *point, facetT *facetA, realT *distp,
+               facetT **facetlist) {
+  realT bestdist= -REALmax, dist;
+  facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
+  boolT goodseen= False;
+
+  if (facetA->good) {
+    zzinc_(Zcheckpart);  /* calls from check_bestdist occur after print stats */
+    qh_distplane(point, facetA, &bestdist);
+    bestfacet= facetA;
+    goodseen= True;
+  }
+  qh_removefacet(facetA);
+  qh_appendfacet(facetA);
+  *facetlist= facetA;
+  facetA->visitid= ++qh visit_id;
+  FORALLfacet_(*facetlist) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == qh visit_id)
+        continue;
+      neighbor->visitid= qh visit_id;
+      if (goodseen && !neighbor->good)
+        continue;
+      zzinc_(Zcheckpart);
+      qh_distplane(point, neighbor, &dist);
+      if (dist > 0) {
+        qh_removefacet(neighbor);
+        qh_appendfacet(neighbor);
+        if (neighbor->good) {
+          goodseen= True;
+          if (dist > bestdist) {
+            bestdist= dist;
+            bestfacet= neighbor;
+          }
+        }
+      }
+    }
+  }
+  if (bestfacet) {
+    *distp= bestdist;
+    trace2((qh ferr, 2003, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
+      qh_pointid(point), bestdist, bestfacet->id));
+    return bestfacet;
+  }
+  trace4((qh ferr, 4011, "qh_findgooddist: no good facet for p%d above f%d\n",
+      qh_pointid(point), facetA->id));
+  return NULL;
+}  /* findgooddist */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="getarea">-</a>
+
+  qh_getarea( facetlist )
+    set area of all facets in facetlist
+    collect statistics
+    nop if hasAreaVolume
+
+  returns:
+    sets qh totarea/totvol to total area and volume of convex hull
+    for Delaunay triangulation, computes projected area of the lower or upper hull
+      ignores upper hull if qh ATinfinity
+
+  notes:
+    could compute outer volume by expanding facet area by rays from interior
+    the following attempt at perpendicular projection underestimated badly:
+      qh.totoutvol += (-dist + facet->maxoutside + qh DISTround)
+                            * area/ qh hull_dim;
+  design:
+    for each facet on facetlist
+      compute facet->area
+      update qh.totarea and qh.totvol
+*/
+void qh_getarea(facetT *facetlist) {
+  realT area;
+  realT dist;
+  facetT *facet;
+
+  if (qh hasAreaVolume)
+    return;
+  if (qh REPORTfreq)
+    qh_fprintf(qh ferr, 8020, "computing area of each facet and volume of the convex hull\n");
+  else
+    trace1((qh ferr, 1001, "qh_getarea: computing volume and area for each facet\n"));
+  qh totarea= qh totvol= 0.0;
+  FORALLfacet_(facetlist) {
+    if (!facet->normal)
+      continue;
+    if (facet->upperdelaunay && qh ATinfinity)
+      continue;
+    if (!facet->isarea) {
+      facet->f.area= qh_facetarea(facet);
+      facet->isarea= True;
+    }
+    area= facet->f.area;
+    if (qh DELAUNAY) {
+      if (facet->upperdelaunay == qh UPPERdelaunay)
+        qh totarea += area;
+    }else {
+      qh totarea += area;
+      qh_distplane(qh interior_point, facet, &dist);
+      qh totvol += -dist * area/ qh hull_dim;
+    }
+    if (qh PRINTstatistics) {
+      wadd_(Wareatot, area);
+      wmax_(Wareamax, area);
+      wmin_(Wareamin, area);
+    }
+  }
+  qh hasAreaVolume= True;
+} /* getarea */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="gram_schmidt">-</a>
+
+  qh_gram_schmidt( dim, row )
+    implements Gram-Schmidt orthogonalization by rows
+
+  returns:
+    false if zero norm
+    overwrites rows[dim][dim]
+
+  notes:
+    see Golub & van Loan Algorithm 6.2-2
+    overflow due to small divisors not handled
+
+  design:
+    for each row
+      compute norm for row
+      if non-zero, normalize row
+      for each remaining rowA
+        compute inner product of row and rowA
+        reduce rowA by row * inner product
+*/
+boolT qh_gram_schmidt(int dim, realT **row) {
+  realT *rowi, *rowj, norm;
+  int i, j, k;
+
+  for (i=0; i < dim; i++) {
+    rowi= row[i];
+    for (norm= 0.0, k= dim; k--; rowi++)
+      norm += *rowi * *rowi;
+    norm= sqrt(norm);
+    wmin_(Wmindenom, norm);
+    if (norm == 0.0)  /* either 0 or overflow due to sqrt */
+      return False;
+    for (k=dim; k--; )
+      *(--rowi) /= norm;
+    for (j=i+1; j < dim; j++) {
+      rowj= row[j];
+      for (norm= 0.0, k=dim; k--; )
+        norm += *rowi++ * *rowj++;
+      for (k=dim; k--; )
+        *(--rowj) -= *(--rowi) * norm;
+    }
+  }
+  return True;
+} /* gram_schmidt */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="inthresholds">-</a>
+
+  qh_inthresholds( normal, angle )
+    return True if normal within qh.lower_/upper_threshold
+
+  returns:
+    estimate of angle by summing of threshold diffs
+      angle may be NULL
+      smaller "angle" is better
+
+  notes:
+    invalid if qh.SPLITthresholds
+
+  see:
+    qh.lower_threshold in qh_initbuild()
+    qh_initthresholds()
+
+  design:
+    for each dimension
+      test threshold
+*/
+boolT qh_inthresholds(coordT *normal, realT *angle) {
+  boolT within= True;
+  int k;
+  realT threshold;
+
+  if (angle)
+    *angle= 0.0;
+  for (k=0; k < qh hull_dim; k++) {
+    threshold= qh lower_threshold[k];
+    if (threshold > -REALmax/2) {
+      if (normal[k] < threshold)
+        within= False;
+      if (angle) {
+        threshold -= normal[k];
+        *angle += fabs_(threshold);
+      }
+    }
+    if (qh upper_threshold[k] < REALmax/2) {
+      threshold= qh upper_threshold[k];
+      if (normal[k] > threshold)
+        within= False;
+      if (angle) {
+        threshold -= normal[k];
+        *angle += fabs_(threshold);
+      }
+    }
+  }
+  return within;
+} /* inthresholds */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="joggleinput">-</a>
+
+  qh_joggleinput()
+    randomly joggle input to Qhull by qh.JOGGLEmax
+    initial input is qh.first_point/qh.num_points of qh.hull_dim
+      repeated calls use qh.input_points/qh.num_points
+
+  returns:
+    joggles points at qh.first_point/qh.num_points
+    copies data to qh.input_points/qh.input_malloc if first time
+    determines qh.JOGGLEmax if it was zero
+    if qh.DELAUNAY
+      computes the Delaunay projection of the joggled points
+
+  notes:
+    if qh.DELAUNAY, unnecessarily joggles the last coordinate
+    the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
+
+  design:
+    if qh.DELAUNAY
+      set qh.SCALElast for reduced precision errors
+    if first call
+      initialize qh.input_points to the original input points
+      if qh.JOGGLEmax == 0
+        determine default qh.JOGGLEmax
+    else
+      increase qh.JOGGLEmax according to qh.build_cnt
+    joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
+    if qh.DELAUNAY
+      sets the Delaunay projection
+*/
+void qh_joggleinput(void) {
+  int i, seed, size;
+  coordT *coordp, *inputp;
+  realT randr, randa, randb;
+
+  if (!qh input_points) { /* first call */
+    qh input_points= qh first_point;
+    qh input_malloc= qh POINTSmalloc;
+    size= qh num_points * qh hull_dim * sizeof(coordT);
+    if (!(qh first_point=(coordT*)qh_malloc((size_t)size))) {
+      qh_fprintf(qh ferr, 6009, "qhull error: insufficient memory to joggle %d points\n",
+          qh num_points);
+      qh_errexit(qh_ERRmem, NULL, NULL);
+    }
+    qh POINTSmalloc= True;
+    if (qh JOGGLEmax == 0.0) {
+      qh JOGGLEmax= qh_detjoggle(qh input_points, qh num_points, qh hull_dim);
+      qh_option("QJoggle", NULL, &qh JOGGLEmax);
+    }
+  }else {                 /* repeated call */
+    if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
+      if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
+        realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
+        if (qh JOGGLEmax < maxjoggle) {
+          qh JOGGLEmax *= qh_JOGGLEincrease;
+          minimize_(qh JOGGLEmax, maxjoggle);
+        }
+      }
+    }
+    qh_option("QJoggle", NULL, &qh JOGGLEmax);
+  }
+  if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
+      qh_fprintf(qh ferr, 6010, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input.  If possible, recompile Qhull with higher-precision reals.\n",
+                qh JOGGLEmax);
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  /* for some reason, using qh ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
+  seed= qh_RANDOMint;
+  qh_option("_joggle-seed", &seed, NULL);
+  trace0((qh ferr, 6, "qh_joggleinput: joggle input by %2.2g with seed %d\n",
+    qh JOGGLEmax, seed));
+  inputp= qh input_points;
+  coordp= qh first_point;
+  randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
+  randb= -qh JOGGLEmax;
+  size= qh num_points * qh hull_dim;
+  for (i=size; i--; ) {
+    randr= qh_RANDOMint;
+    *(coordp++)= *(inputp++) + (randr * randa + randb);
+  }
+  if (qh DELAUNAY) {
+    qh last_low= qh last_high= qh last_newhigh= REALmax;
+    qh_setdelaunay(qh hull_dim, qh num_points, qh first_point);
+  }
+} /* joggleinput */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxabsval">-</a>
+
+  qh_maxabsval( normal, dim )
+    return pointer to maximum absolute value of a dim vector
+    returns NULL if dim=0
+*/
+realT *qh_maxabsval(realT *normal, int dim) {
+  realT maxval= -REALmax;
+  realT *maxp= NULL, *colp, absval;
+  int k;
+
+  for (k=dim, colp= normal; k--; colp++) {
+    absval= fabs_(*colp);
+    if (absval > maxval) {
+      maxval= absval;
+      maxp= colp;
+    }
+  }
+  return maxp;
+} /* maxabsval */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxmin">-</a>
+
+  qh_maxmin( points, numpoints, dimension )
+    return max/min points for each dimension
+    determine max and min coordinates
+
+  returns:
+    returns a temporary set of max and min points
+      may include duplicate points. Does not include qh.GOODpoint
+    sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
+         qh.MAXlastcoord, qh.MINlastcoord
+    initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
+
+  notes:
+    loop duplicated in qh_detjoggle()
+
+  design:
+    initialize global precision variables
+    checks definition of REAL...
+    for each dimension
+      for each point
+        collect maximum and minimum point
+      collect maximum of maximums and minimum of minimums
+      determine qh.NEARzero for Gaussian Elimination
+*/
+setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
+  int k;
+  realT maxcoord, temp;
+  pointT *minimum, *maximum, *point, *pointtemp;
+  setT *set;
+
+  qh max_outside= 0.0;
+  qh MAXabs_coord= 0.0;
+  qh MAXwidth= -REALmax;
+  qh MAXsumcoord= 0.0;
+  qh min_vertex= 0.0;
+  qh WAScoplanar= False;
+  if (qh ZEROcentrum)
+    qh ZEROall_ok= True;
+  if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
+  && REALmax > 0.0 && -REALmax < 0.0)
+    ; /* all ok */
+  else {
+    qh_fprintf(qh ferr, 6011, "qhull error: floating point constants in user.h are wrong\n\
+REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
+             REALepsilon, REALmin, REALmax, -REALmax);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  set= qh_settemp(2*dimension);
+  for (k=0; k < dimension; k++) {
+    if (points == qh GOODpointp)
+      minimum= maximum= points + dimension;
+    else
+      minimum= maximum= points;
+    FORALLpoint_(points, numpoints) {
+      if (point == qh GOODpointp)
+        continue;
+      if (maximum[k] < point[k])
+        maximum= point;
+      else if (minimum[k] > point[k])
+        minimum= point;
+    }
+    if (k == dimension-1) {
+      qh MINlastcoord= minimum[k];
+      qh MAXlastcoord= maximum[k];
+    }
+    if (qh SCALElast && k == dimension-1)
+      maxcoord= qh MAXwidth;
+    else {
+      maxcoord= fmax_(maximum[k], -minimum[k]);
+      if (qh GOODpointp) {
+        temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
+        maximize_(maxcoord, temp);
+      }
+      temp= maximum[k] - minimum[k];
+      maximize_(qh MAXwidth, temp);
+    }
+    maximize_(qh MAXabs_coord, maxcoord);
+    qh MAXsumcoord += maxcoord;
+    qh_setappend(&set, maximum);
+    qh_setappend(&set, minimum);
+    /* calculation of qh NEARzero is based on error formula 4.4-13 of
+       Golub & van Loan, authors say n^3 can be ignored and 10 be used in
+       place of rho */
+    qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
+  }
+  if (qh IStracing >=1)
+    qh_printpoints(qh ferr, "qh_maxmin: found the max and min points(by dim):", set);
+  return(set);
+} /* maxmin */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxouter">-</a>
+
+  qh_maxouter()
+    return maximum distance from facet to outer plane
+    normally this is qh.max_outside+qh.DISTround
+    does not include qh.JOGGLEmax
+
+  see:
+    qh_outerinner()
+
+  notes:
+    need to add another qh.DISTround if testing actual point with computation
+
+  for joggle:
+    qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
+    need to use Wnewvertexmax since could have a coplanar point for a high
+      facet that is replaced by a low facet
+    need to add qh.JOGGLEmax if testing input points
+*/
+realT qh_maxouter(void) {
+  realT dist;
+
+  dist= fmax_(qh max_outside, qh DISTround);
+  dist += qh DISTround;
+  trace4((qh ferr, 4012, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
+  return dist;
+} /* maxouter */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="maxsimplex">-</a>
+
+  qh_maxsimplex( dim, maxpoints, points, numpoints, simplex )
+    determines maximum simplex for a set of points
+    starts from points already in simplex
+    skips qh.GOODpointp (assumes that it isn't in maxpoints)
+
+  returns:
+    simplex with dim+1 points
+
+  notes:
+    assumes at least pointsneeded points in points
+    maximizes determinate for x,y,z,w, etc.
+    uses maxpoints as long as determinate is clearly non-zero
+
+  design:
+    initialize simplex with at least two points
+      (find points with max or min x coordinate)
+    for each remaining dimension
+      add point that maximizes the determinate
+        (use points from maxpoints first)
+*/
+void qh_maxsimplex(int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
+  pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
+  boolT nearzero, maxnearzero= False;
+  int k, sizinit;
+  realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
+
+  sizinit= qh_setsize(*simplex);
+  if (sizinit < 2) {
+    if (qh_setsize(maxpoints) >= 2) {
+      FOREACHpoint_(maxpoints) {
+        if (maxcoord < point[0]) {
+          maxcoord= point[0];
+          maxx= point;
+        }
+        if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+        }
+      }
+    }else {
+      FORALLpoint_(points, numpoints) {
+        if (point == qh GOODpointp)
+          continue;
+        if (maxcoord < point[0]) {
+          maxcoord= point[0];
+          maxx= point;
+        }
+        if (mincoord > point[0]) {
+          mincoord= point[0];
+          minx= point;
+        }
+      }
+    }
+    qh_setunique(simplex, minx);
+    if (qh_setsize(*simplex) < 2)
+      qh_setunique(simplex, maxx);
+    sizinit= qh_setsize(*simplex);
+    if (sizinit < 2) {
+      qh_precision("input has same x coordinate");
+      if (zzval_(Zsetplane) > qh hull_dim+1) {
+        qh_fprintf(qh ferr, 6012, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
+                 qh_setsize(maxpoints)+numpoints);
+        qh_errexit(qh_ERRprec, NULL, NULL);
+      }else {
+        qh_fprintf(qh ferr, 6013, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+    }
+  }
+  for (k=sizinit; k < dim+1; k++) {
+    maxpoint= NULL;
+    maxdet= -REALmax;
+    FOREACHpoint_(maxpoints) {
+      if (!qh_setin(*simplex, point)) {
+        det= qh_detsimplex(point, *simplex, k, &nearzero);
+        if ((det= fabs_(det)) > maxdet) {
+          maxdet= det;
+          maxpoint= point;
+          maxnearzero= nearzero;
+        }
+      }
+    }
+    if (!maxpoint || maxnearzero) {
+      zinc_(Zsearchpoints);
+      if (!maxpoint) {
+        trace0((qh ferr, 7, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
+      }else {
+        trace0((qh ferr, 8, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
+                k+1, qh_pointid(maxpoint), maxdet));
+      }
+      FORALLpoint_(points, numpoints) {
+        if (point == qh GOODpointp)
+          continue;
+        if (!qh_setin(*simplex, point)) {
+          det= qh_detsimplex(point, *simplex, k, &nearzero);
+          if ((det= fabs_(det)) > maxdet) {
+            maxdet= det;
+            maxpoint= point;
+            maxnearzero= nearzero;
+          }
+        }
+      }
+    } /* !maxpoint */
+    if (!maxpoint) {
+      qh_fprintf(qh ferr, 6014, "qhull internal error (qh_maxsimplex): not enough points available\n");
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+    qh_setappend(simplex, maxpoint);
+    trace1((qh ferr, 1002, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
+            qh_pointid(maxpoint), k+1, maxdet));
+  } /* k */
+} /* maxsimplex */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="minabsval">-</a>
+
+  qh_minabsval( normal, dim )
+    return minimum absolute value of a dim vector
+*/
+realT qh_minabsval(realT *normal, int dim) {
+  realT minval= 0;
+  realT maxval= 0;
+  realT *colp;
+  int k;
+
+  for (k=dim, colp=normal; k--; colp++) {
+    maximize_(maxval, *colp);
+    minimize_(minval, *colp);
+  }
+  return fmax_(maxval, -minval);
+} /* minabsval */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="mindiff">-</a>
+
+  qh_mindif ( vecA, vecB, dim )
+    return index of min abs. difference of two vectors
+*/
+int qh_mindiff(realT *vecA, realT *vecB, int dim) {
+  realT mindiff= REALmax, diff;
+  realT *vecAp= vecA, *vecBp= vecB;
+  int k, mink= 0;
+
+  for (k=0; k < dim; k++) {
+    diff= *vecAp++ - *vecBp++;
+    diff= fabs_(diff);
+    if (diff < mindiff) {
+      mindiff= diff;
+      mink= k;
+    }
+  }
+  return mink;
+} /* mindiff */
+
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="orientoutside">-</a>
+
+  qh_orientoutside( facet  )
+    make facet outside oriented via qh.interior_point
+
+  returns:
+    True if facet reversed orientation.
+*/
+boolT qh_orientoutside(facetT *facet) {
+  int k;
+  realT dist;
+
+  qh_distplane(qh interior_point, facet, &dist);
+  if (dist > 0) {
+    for (k=qh hull_dim; k--; )
+      facet->normal[k]= -facet->normal[k];
+    facet->offset= -facet->offset;
+    return True;
+  }
+  return False;
+} /* orientoutside */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="outerinner">-</a>
+
+  qh_outerinner( facet, outerplane, innerplane  )
+    if facet and qh.maxoutdone (i.e., qh_check_maxout)
+      returns outer and inner plane for facet
+    else
+      returns maximum outer and inner plane
+    accounts for qh.JOGGLEmax
+
+  see:
+    qh_maxouter(), qh_check_bestdist(), qh_check_points()
+
+  notes:
+    outerplaner or innerplane may be NULL
+    facet is const
+    Does not error (QhullFacet)
+
+    includes qh.DISTround for actual points
+    adds another qh.DISTround if testing with floating point arithmetic
+*/
+void qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane) {
+  realT dist, mindist;
+  vertexT *vertex, **vertexp;
+
+  if (outerplane) {
+    if (!qh_MAXoutside || !facet || !qh maxoutdone) {
+      *outerplane= qh_maxouter();       /* includes qh.DISTround */
+    }else { /* qh_MAXoutside ... */
+#if qh_MAXoutside
+      *outerplane= facet->maxoutside + qh DISTround;
+#endif
+
+    }
+    if (qh JOGGLEmax < REALmax/2)
+      *outerplane += qh JOGGLEmax * sqrt((realT)qh hull_dim);
+  }
+  if (innerplane) {
+    if (facet) {
+      mindist= REALmax;
+      FOREACHvertex_(facet->vertices) {
+        zinc_(Zdistio);
+        qh_distplane(vertex->point, facet, &dist);
+        minimize_(mindist, dist);
+      }
+      *innerplane= mindist - qh DISTround;
+    }else
+      *innerplane= qh min_vertex - qh DISTround;
+    if (qh JOGGLEmax < REALmax/2)
+      *innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
+  }
+} /* outerinner */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="pointdist">-</a>
+
+  qh_pointdist( point1, point2, dim )
+    return distance between two points
+
+  notes:
+    returns distance squared if 'dim' is negative
+*/
+coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
+  coordT dist, diff;
+  int k;
+
+  dist= 0.0;
+  k= (dim > 0 ? dim : -dim);
+  for (; k; k--) {
+    diff= *point1++ - *point2++;
+    dist += diff * diff;
+  }
+  if (dim > 0)
+    return(sqrt(dist));
+  return dist;
+} /* pointdist */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="printmatrix">-</a>
+
+  qh_printmatrix( fp, string, rows, numrow, numcol )
+    print matrix to fp given by row vectors
+    print string as header
+
+  notes:
+    print a vector by qh_printmatrix(fp, "", &vect, 1, len)
+*/
+void qh_printmatrix(FILE *fp, const char *string, realT **rows, int numrow, int numcol) {
+  realT *rowp;
+  realT r; /*bug fix*/
+  int i,k;
+
+  qh_fprintf(fp, 9001, "%s\n", string);
+  for (i=0; i < numrow; i++) {
+    rowp= rows[i];
+    for (k=0; k < numcol; k++) {
+      r= *rowp++;
+      qh_fprintf(fp, 9002, "%6.3g ", r);
+    }
+    qh_fprintf(fp, 9003, "\n");
+  }
+} /* printmatrix */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="printpoints">-</a>
+
+  qh_printpoints( fp, string, points )
+    print pointids to fp for a set of points
+    if string, prints string and 'p' point ids
+*/
+void qh_printpoints(FILE *fp, const char *string, setT *points) {
+  pointT *point, **pointp;
+
+  if (string) {
+    qh_fprintf(fp, 9004, "%s", string);
+    FOREACHpoint_(points)
+      qh_fprintf(fp, 9005, " p%d", qh_pointid(point));
+    qh_fprintf(fp, 9006, "\n");
+  }else {
+    FOREACHpoint_(points)
+      qh_fprintf(fp, 9007, " %d", qh_pointid(point));
+    qh_fprintf(fp, 9008, "\n");
+  }
+} /* printpoints */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="projectinput">-</a>
+
+  qh_projectinput()
+    project input points using qh.lower_bound/upper_bound and qh DELAUNAY
+    if qh.lower_bound[k]=qh.upper_bound[k]= 0,
+      removes dimension k
+    if halfspace intersection
+      removes dimension k from qh.feasible_point
+    input points in qh first_point, num_points, input_dim
+
+  returns:
+    new point array in qh first_point of qh hull_dim coordinates
+    sets qh POINTSmalloc
+    if qh DELAUNAY
+      projects points to paraboloid
+      lowbound/highbound is also projected
+    if qh ATinfinity
+      adds point "at-infinity"
+    if qh POINTSmalloc
+      frees old point array
+
+  notes:
+    checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
+
+
+  design:
+    sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
+    determines newdim and newnum for qh hull_dim and qh num_points
+    projects points to newpoints
+    projects qh.lower_bound to itself
+    projects qh.upper_bound to itself
+    if qh DELAUNAY
+      if qh ATINFINITY
+        projects points to paraboloid
+        computes "infinity" point as vertex average and 10% above all points
+      else
+        uses qh_setdelaunay to project points to paraboloid
+*/
+void qh_projectinput(void) {
+  int k,i;
+  int newdim= qh input_dim, newnum= qh num_points;
+  signed char *project;
+  int size= (qh input_dim+1)*sizeof(*project);
+  pointT *newpoints, *coord, *infinity;
+  realT paraboloid, maxboloid= 0;
+
+  project= (signed char*)qh_memalloc(size);
+  memset((char*)project, 0, (size_t)size);
+  for (k=0; k < qh input_dim; k++) {   /* skip Delaunay bound */
+    if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
+      project[k]= -1;
+      newdim--;
+    }
+  }
+  if (qh DELAUNAY) {
+    project[k]= 1;
+    newdim++;
+    if (qh ATinfinity)
+      newnum++;
+  }
+  if (newdim != qh hull_dim) {
+    qh_fprintf(qh ferr, 6015, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (!(newpoints=(coordT*)qh_malloc(newnum*newdim*sizeof(coordT)))){
+    qh_fprintf(qh ferr, 6016, "qhull error: insufficient memory to project %d points\n",
+           qh num_points);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  qh_projectpoints(project, qh input_dim+1, qh first_point,
+                    qh num_points, qh input_dim, newpoints, newdim);
+  trace1((qh ferr, 1003, "qh_projectinput: updating lower and upper_bound\n"));
+  qh_projectpoints(project, qh input_dim+1, qh lower_bound,
+                    1, qh input_dim+1, qh lower_bound, newdim+1);
+  qh_projectpoints(project, qh input_dim+1, qh upper_bound,
+                    1, qh input_dim+1, qh upper_bound, newdim+1);
+  if (qh HALFspace) {
+    if (!qh feasible_point) {
+      qh_fprintf(qh ferr, 6017, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+    qh_projectpoints(project, qh input_dim, qh feasible_point,
+                      1, qh input_dim, qh feasible_point, newdim);
+  }
+  qh_memfree(project, (qh input_dim+1)*sizeof(*project));
+  if (qh POINTSmalloc)
+    qh_free(qh first_point);
+  qh first_point= newpoints;
+  qh POINTSmalloc= True;
+  if (qh DELAUNAY && qh ATinfinity) {
+    coord= qh first_point;
+    infinity= qh first_point + qh hull_dim * qh num_points;
+    for (k=qh hull_dim-1; k--; )
+      infinity[k]= 0.0;
+    for (i=qh num_points; i--; ) {
+      paraboloid= 0.0;
+      for (k=0; k < qh hull_dim-1; k++) {
+        paraboloid += *coord * *coord;
+        infinity[k] += *coord;
+        coord++;
+      }
+      *(coord++)= paraboloid;
+      maximize_(maxboloid, paraboloid);
+    }
+    /* coord == infinity */
+    for (k=qh hull_dim-1; k--; )
+      *(coord++) /= qh num_points;
+    *(coord++)= maxboloid * 1.1;
+    qh num_points++;
+    trace0((qh ferr, 9, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
+  }else if (qh DELAUNAY)  /* !qh ATinfinity */
+    qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
+} /* projectinput */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="projectpoints">-</a>
+
+  qh_projectpoints( project, n, points, numpoints, dim, newpoints, newdim )
+    project points/numpoints/dim to newpoints/newdim
+    if project[k] == -1
+      delete dimension k
+    if project[k] == 1
+      add dimension k by duplicating previous column
+    n is size of project
+
+  notes:
+    newpoints may be points if only adding dimension at end
+
+  design:
+    check that 'project' and 'newdim' agree
+    for each dimension
+      if project == -1
+        skip dimension
+      else
+        determine start of column in newpoints
+        determine start of column in points
+          if project == +1, duplicate previous column
+        copy dimension (column) from points to newpoints
+*/
+void qh_projectpoints(signed char *project, int n, realT *points,
+        int numpoints, int dim, realT *newpoints, int newdim) {
+  int testdim= dim, oldk=0, newk=0, i,j=0,k;
+  realT *newp, *oldp;
+
+  for (k=0; k < n; k++)
+    testdim += project[k];
+  if (testdim != newdim) {
+    qh_fprintf(qh ferr, 6018, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
+      newdim, testdim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  for (j=0; j<n; j++) {
+    if (project[j] == -1)
+      oldk++;
+    else {
+      newp= newpoints+newk++;
+      if (project[j] == +1) {
+        if (oldk >= dim)
+          continue;
+        oldp= points+oldk;
+      }else
+        oldp= points+oldk++;
+      for (i=numpoints; i--; ) {
+        *newp= *oldp;
+        newp += newdim;
+        oldp += dim;
+      }
+    }
+    if (oldk >= dim)
+      break;
+  }
+  trace1((qh ferr, 1004, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
+    numpoints, dim, newdim));
+} /* projectpoints */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="rotateinput">-</a>
+
+  qh_rotateinput( rows )
+    rotate input using row matrix
+    input points given by qh first_point, num_points, hull_dim
+    assumes rows[dim] is a scratch buffer
+    if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    rotated input
+    sets qh POINTSmalloc
+
+  design:
+    see qh_rotatepoints
+*/
+void qh_rotateinput(realT **rows) {
+
+  if (!qh POINTSmalloc) {
+    qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
+    qh POINTSmalloc= True;
+  }
+  qh_rotatepoints(qh first_point, qh num_points, qh hull_dim, rows);
+}  /* rotateinput */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="rotatepoints">-</a>
+
+  qh_rotatepoints( points, numpoints, dim, row )
+    rotate numpoints points by a d-dim row matrix
+    assumes rows[dim] is a scratch buffer
+
+  returns:
+    rotated points in place
+
+  design:
+    for each point
+      for each coordinate
+        use row[dim] to compute partial inner product
+      for each coordinate
+        rotate by partial inner product
+*/
+void qh_rotatepoints(realT *points, int numpoints, int dim, realT **row) {
+  realT *point, *rowi, *coord= NULL, sum, *newval;
+  int i,j,k;
+
+  if (qh IStracing >= 1)
+    qh_printmatrix(qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
+  for (point= points, j= numpoints; j--; point += dim) {
+    newval= row[dim];
+    for (i=0; i < dim; i++) {
+      rowi= row[i];
+      coord= point;
+      for (sum= 0.0, k= dim; k--; )
+        sum += *rowi++ * *coord++;
+      *(newval++)= sum;
+    }
+    for (k=dim; k--; )
+      *(--coord)= *(--newval);
+  }
+} /* rotatepoints */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="scaleinput">-</a>
+
+  qh_scaleinput()
+    scale input points using qh low_bound/high_bound
+    input points given by qh first_point, num_points, hull_dim
+    if qh POINTSmalloc, overwrites input points, else mallocs a new array
+
+  returns:
+    scales coordinates of points to low_bound[k], high_bound[k]
+    sets qh POINTSmalloc
+
+  design:
+    see qh_scalepoints
+*/
+void qh_scaleinput(void) {
+
+  if (!qh POINTSmalloc) {
+    qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
+    qh POINTSmalloc= True;
+  }
+  qh_scalepoints(qh first_point, qh num_points, qh hull_dim,
+       qh lower_bound, qh upper_bound);
+}  /* scaleinput */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="scalelast">-</a>
+
+  qh_scalelast( points, numpoints, dim, low, high, newhigh )
+    scale last coordinate to [0,m] for Delaunay triangulations
+    input points given by points, numpoints, dim
+
+  returns:
+    changes scale of last coordinate from [low, high] to [0, newhigh]
+    overwrites last coordinate of each point
+    saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
+
+  notes:
+    when called by qh_setdelaunay, low/high may not match actual data
+
+  design:
+    compute scale and shift factors
+    apply to last coordinate of each point
+*/
+void qh_scalelast(coordT *points, int numpoints, int dim, coordT low,
+                   coordT high, coordT newhigh) {
+  realT scale, shift;
+  coordT *coord;
+  int i;
+  boolT nearzero= False;
+
+  trace4((qh ferr, 4013, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
+    low, high, newhigh));
+  qh last_low= low;
+  qh last_high= high;
+  qh last_newhigh= newhigh;
+  scale= qh_divzero(newhigh, high - low,
+                  qh MINdenom_1, &nearzero);
+  if (nearzero) {
+    if (qh DELAUNAY)
+      qh_fprintf(qh ferr, 6019, "qhull input error: can not scale last coordinate.  Input is cocircular\n   or cospherical.   Use option 'Qz' to add a point at infinity.\n");
+    else
+      qh_fprintf(qh ferr, 6020, "qhull input error: can not scale last coordinate.  New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
+                newhigh, low, high, high-low);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  shift= - low * newhigh / (high-low);
+  coord= points + dim - 1;
+  for (i=numpoints; i--; coord += dim)
+    *coord= *coord * scale + shift;
+} /* scalelast */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="scalepoints">-</a>
+
+  qh_scalepoints( points, numpoints, dim, newlows, newhighs )
+    scale points to new lowbound and highbound
+    retains old bound when newlow= -REALmax or newhigh= +REALmax
+
+  returns:
+    scaled points
+    overwrites old points
+
+  design:
+    for each coordinate
+      compute current low and high bound
+      compute scale and shift factors
+      scale all points
+      enforce new low and high bound for all points
+*/
+void qh_scalepoints(pointT *points, int numpoints, int dim,
+        realT *newlows, realT *newhighs) {
+  int i,k;
+  realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
+  boolT nearzero= False;
+
+  for (k=0; k < dim; k++) {
+    newhigh= newhighs[k];
+    newlow= newlows[k];
+    if (newhigh > REALmax/2 && newlow < -REALmax/2)
+      continue;
+    low= REALmax;
+    high= -REALmax;
+    for (i=numpoints, coord=points+k; i--; coord += dim) {
+      minimize_(low, *coord);
+      maximize_(high, *coord);
+    }
+    if (newhigh > REALmax/2)
+      newhigh= high;
+    if (newlow < -REALmax/2)
+      newlow= low;
+    if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
+      qh_fprintf(qh ferr, 6021, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
+               k, k, newhigh, newlow);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    scale= qh_divzero(newhigh - newlow, high - low,
+                  qh MINdenom_1, &nearzero);
+    if (nearzero) {
+      qh_fprintf(qh ferr, 6022, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
+              k, newlow, newhigh, low, high);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    shift= (newlow * high - low * newhigh)/(high-low);
+    coord= points+k;
+    for (i=numpoints; i--; coord += dim)
+      *coord= *coord * scale + shift;
+    coord= points+k;
+    if (newlow < newhigh) {
+      mincoord= newlow;
+      maxcoord= newhigh;
+    }else {
+      mincoord= newhigh;
+      maxcoord= newlow;
+    }
+    for (i=numpoints; i--; coord += dim) {
+      minimize_(*coord, maxcoord);  /* because of roundoff error */
+      maximize_(*coord, mincoord);
+    }
+    trace0((qh ferr, 10, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
+      k, low, high, newlow, newhigh, numpoints, scale, shift));
+  }
+} /* scalepoints */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="setdelaunay">-</a>
+
+  qh_setdelaunay( dim, count, points )
+    project count points to dim-d paraboloid for Delaunay triangulation
+
+    dim is one more than the dimension of the input set
+    assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
+
+    points is a dim*count realT array.  The first dim-1 coordinates
+    are the coordinates of the first input point.  array[dim] is
+    the first coordinate of the second input point.  array[2*dim] is
+    the first coordinate of the third input point.
+
+    if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
+      calls qh_scalelast to scale the last coordinate the same as the other points
+
+  returns:
+    for each point
+      sets point[dim-1] to sum of squares of coordinates
+    scale points to 'Qbb' if needed
+
+  notes:
+    to project one point, use
+      qh_setdelaunay(qh hull_dim, 1, point)
+
+    Do not use options 'Qbk', 'QBk', or 'QbB' since they scale
+    the coordinates after the original projection.
+
+*/
+void qh_setdelaunay(int dim, int count, pointT *points) {
+  int i, k;
+  coordT *coordp, coord;
+  realT paraboloid;
+
+  trace0((qh ferr, 11, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
+  coordp= points;
+  for (i=0; i < count; i++) {
+    coord= *coordp++;
+    paraboloid= coord*coord;
+    for (k=dim-2; k--; ) {
+      coord= *coordp++;
+      paraboloid += coord*coord;
+    }
+    *coordp++ = paraboloid;
+  }
+  if (qh last_low < REALmax/2)
+    qh_scalelast(points, count, dim, qh last_low, qh last_high, qh last_newhigh);
+} /* setdelaunay */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethalfspace">-</a>
+
+  qh_sethalfspace( dim, coords, nextp, normal, offset, feasible )
+    set point to dual of halfspace relative to feasible point
+    halfspace is normal coefficients and offset.
+
+  returns:
+    false if feasible point is outside of hull (error message already reported)
+    overwrites coordinates for point at dim coords
+    nextp= next point (coords)
+
+  design:
+    compute distance from feasible point to halfspace
+    divide each normal coefficient by -dist
+*/
+boolT qh_sethalfspace(int dim, coordT *coords, coordT **nextp,
+         coordT *normal, coordT *offset, coordT *feasible) {
+  coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
+  realT dist;
+  realT r; /*bug fix*/
+  int k;
+  boolT zerodiv;
+
+  dist= *offset;
+  for (k=dim; k--; )
+    dist += *(normp++) * *(feasiblep++);
+  if (dist > 0)
+    goto LABELerroroutside;
+  normp= normal;
+  if (dist < -qh MINdenom) {
+    for (k=dim; k--; )
+      *(coordp++)= *(normp++) / -dist;
+  }else {
+    for (k=dim; k--; ) {
+      *(coordp++)= qh_divzero(*(normp++), -dist, qh MINdenom_1, &zerodiv);
+      if (zerodiv)
+        goto LABELerroroutside;
+    }
+  }
+  *nextp= coordp;
+  if (qh IStracing >= 4) {
+    qh_fprintf(qh ferr, 8021, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
+    for (k=dim, coordp=coords; k--; ) {
+      r= *coordp++;
+      qh_fprintf(qh ferr, 8022, " %6.2g", r);
+    }
+    qh_fprintf(qh ferr, 8023, "\n");
+  }
+  return True;
+LABELerroroutside:
+  feasiblep= feasible;
+  normp= normal;
+  qh_fprintf(qh ferr, 6023, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
+  for (k=dim; k--; )
+    qh_fprintf(qh ferr, 8024, qh_REAL_1, r=*(feasiblep++));
+  qh_fprintf(qh ferr, 8025, "\n     halfspace: ");
+  for (k=dim; k--; )
+    qh_fprintf(qh ferr, 8026, qh_REAL_1, r=*(normp++));
+  qh_fprintf(qh ferr, 8027, "\n     at offset: ");
+  qh_fprintf(qh ferr, 8028, qh_REAL_1, *offset);
+  qh_fprintf(qh ferr, 8029, " and distance: ");
+  qh_fprintf(qh ferr, 8030, qh_REAL_1, dist);
+  qh_fprintf(qh ferr, 8031, "\n");
+  return False;
+} /* sethalfspace */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sethalfspace_all">-</a>
+
+  qh_sethalfspace_all( dim, count, halfspaces, feasible )
+    generate dual for halfspace intersection with feasible point
+    array of count halfspaces
+      each halfspace is normal coefficients followed by offset
+      the origin is inside the halfspace if the offset is negative
+
+  returns:
+    malloc'd array of count X dim-1 points
+
+  notes:
+    call before qh_init_B or qh_initqhull_globals
+    unused/untested code: please email bradb at shore.net if this works ok for you
+    If using option 'Fp', also set qh feasible_point. It is a malloc'd array
+      that is freed by qh_freebuffers.
+
+  design:
+    see qh_sethalfspace
+*/
+coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible) {
+  int i, newdim;
+  pointT *newpoints;
+  coordT *coordp, *normalp, *offsetp;
+
+  trace0((qh ferr, 12, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
+  newdim= dim - 1;
+  if (!(newpoints=(coordT*)qh_malloc(count*newdim*sizeof(coordT)))){
+    qh_fprintf(qh ferr, 6024, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
+          count);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coordp= newpoints;
+  normalp= halfspaces;
+  for (i=0; i < count; i++) {
+    offsetp= normalp + newdim;
+    if (!qh_sethalfspace(newdim, coordp, &coordp, normalp, offsetp, feasible)) {
+      qh_fprintf(qh ferr, 8032, "The halfspace was at index %d\n", i);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    normalp= offsetp + 1;
+  }
+  return newpoints;
+} /* sethalfspace_all */
+
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="sharpnewfacets">-</a>
+
+  qh_sharpnewfacets()
+
+  returns:
+    true if could be an acute angle (facets in different quadrants)
+
+  notes:
+    for qh_findbest
+
+  design:
+    for all facets on qh.newfacet_list
+      if two facets are in different quadrants
+        set issharp
+*/
+boolT qh_sharpnewfacets() {
+  facetT *facet;
+  boolT issharp = False;
+  int *quadrant, k;
+
+  quadrant= (int*)qh_memalloc(qh hull_dim * sizeof(int));
+  FORALLfacet_(qh newfacet_list) {
+    if (facet == qh newfacet_list) {
+      for (k=qh hull_dim; k--; )
+        quadrant[ k]= (facet->normal[ k] > 0);
+    }else {
+      for (k=qh hull_dim; k--; ) {
+        if (quadrant[ k] != (facet->normal[ k] > 0)) {
+          issharp= True;
+          break;
+        }
+      }
+    }
+    if (issharp)
+      break;
+  }
+  qh_memfree( quadrant, qh hull_dim * sizeof(int));
+  trace3((qh ferr, 3001, "qh_sharpnewfacets: %d\n", issharp));
+  return issharp;
+} /* sharpnewfacets */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="voronoi_center">-</a>
+
+  qh_voronoi_center( dim, points )
+    return Voronoi center for a set of points
+    dim is the original dimension of the points
+    gh.gm_matrix/qh.gm_row are scratch buffers
+
+  returns:
+    center as a temporary point
+    if non-simplicial,
+      returns center for max simplex of points
+
+  notes:
+    from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
+
+  design:
+    if non-simplicial
+      determine max simplex for points
+    translate point0 of simplex to origin
+    compute sum of squares of diagonal
+    compute determinate
+    compute Voronoi center (see Bowyer & Woodwark)
+*/
+pointT *qh_voronoi_center(int dim, setT *points) {
+  pointT *point, **pointp, *point0;
+  pointT *center= (pointT*)qh_memalloc(qh center_size);
+  setT *simplex;
+  int i, j, k, size= qh_setsize(points);
+  coordT *gmcoord;
+  realT *diffp, sum2, *sum2row, *sum2p, det, factor;
+  boolT nearzero, infinite;
+
+  if (size == dim+1)
+    simplex= points;
+  else if (size < dim+1) {
+    qh_fprintf(qh ferr, 6025, "qhull internal error (qh_voronoi_center):\n  need at least %d points to construct a Voronoi center\n",
+             dim+1);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+    simplex= points;  /* never executed -- avoids warning */
+  }else {
+    simplex= qh_settemp(dim+1);
+    qh_maxsimplex(dim, points, NULL, 0, &simplex);
+  }
+  point0= SETfirstt_(simplex, pointT);
+  gmcoord= qh gm_matrix;
+  for (k=0; k < dim; k++) {
+    qh gm_row[k]= gmcoord;
+    FOREACHpoint_(simplex) {
+      if (point != point0)
+        *(gmcoord++)= point[k] - point0[k];
+    }
+  }
+  sum2row= gmcoord;
+  for (i=0; i < dim; i++) {
+    sum2= 0.0;
+    for (k=0; k < dim; k++) {
+      diffp= qh gm_row[k] + i;
+      sum2 += *diffp * *diffp;
+    }
+    *(gmcoord++)= sum2;
+  }
+  det= qh_determinant(qh gm_row, dim, &nearzero);
+  factor= qh_divzero(0.5, det, qh MINdenom, &infinite);
+  if (infinite) {
+    for (k=dim; k--; )
+      center[k]= qh_INFINITE;
+    if (qh IStracing)
+      qh_printpoints(qh ferr, "qh_voronoi_center: at infinity for ", simplex);
+  }else {
+    for (i=0; i < dim; i++) {
+      gmcoord= qh gm_matrix;
+      sum2p= sum2row;
+      for (k=0; k < dim; k++) {
+        qh gm_row[k]= gmcoord;
+        if (k == i) {
+          for (j=dim; j--; )
+            *(gmcoord++)= *sum2p++;
+        }else {
+          FOREACHpoint_(simplex) {
+            if (point != point0)
+              *(gmcoord++)= point[k] - point0[k];
+          }
+        }
+      }
+      center[i]= qh_determinant(qh gm_row, dim, &nearzero)*factor + point0[i];
+    }
+#ifndef qh_NOtrace
+    if (qh IStracing >= 3) {
+      qh_fprintf(qh ferr, 8033, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
+      qh_printmatrix(qh ferr, "center:", &center, 1, dim);
+      if (qh IStracing >= 5) {
+        qh_printpoints(qh ferr, "points", simplex);
+        FOREACHpoint_(simplex)
+          qh_fprintf(qh ferr, 8034, "p%d dist %.2g, ", qh_pointid(point),
+                   qh_pointdist(point, center, dim));
+        qh_fprintf(qh ferr, 8035, "\n");
+      }
+    }
+#endif
+  }
+  if (simplex != points)
+    qh_settempfree(&simplex);
+  return center;
+} /* voronoi_center */
+
diff --git a/alg/internal_libqhull/global.c b/alg/internal_libqhull/global.c
new file mode 100644
index 0000000..e46add2
--- /dev/null
+++ b/alg/internal_libqhull/global.c
@@ -0,0 +1,2126 @@
+
+/*<html><pre>  -<a                             href="qh-globa.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   global.c
+   initializes all the globals of the qhull application
+
+   see README
+
+   see libqhull.h for qh.globals and function prototypes
+
+   see qhull_a.h for internal functions
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/global.c#15 $$Change: 1490 $
+   $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
+ */
+
+#include "qhull_a.h"
+
+/*========= qh definition -- globals defined in libqhull.h =======================*/
+
+int qhull_inuse= 0; /* not used */
+
+#if qh_QHpointer
+qhT *qh_qh= NULL;       /* pointer to all global variables */
+#else
+qhT qh_qh;              /* all global variables.
+                           Add "= {0}" if this causes a compiler error.
+                           Also qh_qhstat in stat.c and qhmem in mem.c.  */
+#endif
+
+/*-<a                             href  ="qh-globa.htm#TOC"
+  >--------------------------------</a><a name="qh_version">-</a>
+
+  qh_version
+    version string by year and date
+
+    the revision increases on code changes only
+
+  notes:
+    change date:    Changes.txt, Announce.txt, index.htm, README.txt,
+                    qhull-news.html, Eudora signatures, CMakeLists.txt
+    change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt
+    change year:    Copying.txt
+    check download size
+    recompile user_eg.c, rbox.c, libqhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c, testqset.c
+*/
+
+const char *qh_version = "2012.1 2012/02/18";
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="appendprint">-</a>
+
+  qh_appendprint( printFormat )
+    append printFormat to qh.PRINTout unless already defined
+*/
+void qh_appendprint(qh_PRINT format) {
+  int i;
+
+  for (i=0; i < qh_PRINTEND; i++) {
+    if (qh PRINTout[i] == format && format != qh_PRINTqhull)
+      break;
+    if (!qh PRINTout[i]) {
+      qh PRINTout[i]= format;
+      break;
+    }
+  }
+} /* appendprint */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="checkflags">-</a>
+
+  qh_checkflags( commandStr, hiddenFlags )
+    errors if commandStr contains hiddenFlags
+    hiddenFlags starts and ends with a space and is space deliminated (checked)
+
+  notes:
+    ignores first word (e.g., "qconvex i")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+  see:
+    qh_initflags() initializes Qhull according to commandStr
+*/
+void qh_checkflags(char *command, char *hiddenflags) {
+  char *s= command, *t, *chkerr; /* qh_skipfilename is non-const */
+  char key, opt, prevopt;
+  char chkkey[]= "   ";
+  char chkopt[]=  "    ";
+  char chkopt2[]= "     ";
+  boolT waserr= False;
+
+  if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
+    qh_fprintf(qh ferr, 6026, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (strpbrk(hiddenflags, ",\n\r\t")) {
+    qh_fprintf(qh ferr, 6027, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    key = *s++;
+    chkerr = NULL;
+    if (key == 'T' && (*s == 'I' || *s == 'O')) {  /* TI or TO 'file name' */
+      s= qh_skipfilename(++s);
+      continue;
+    }
+    chkkey[1]= key;
+    if (strstr(hiddenflags, chkkey)) {
+      chkerr= chkkey;
+    }else if (isupper(key)) {
+      opt= ' ';
+      prevopt= ' ';
+      chkopt[1]= key;
+      chkopt2[1]= key;
+      while (!chkerr && *s && !isspace(*s)) {
+        opt= *s++;
+        if (isalpha(opt)) {
+          chkopt[2]= opt;
+          if (strstr(hiddenflags, chkopt))
+            chkerr= chkopt;
+          if (prevopt != ' ') {
+            chkopt2[2]= prevopt;
+            chkopt2[3]= opt;
+            if (strstr(hiddenflags, chkopt2))
+              chkerr= chkopt2;
+          }
+        }else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
+              && (prevopt == ' ' || islower(prevopt))) {
+            chkopt[2]= opt;
+            if (strstr(hiddenflags, chkopt))
+              chkerr= chkopt;
+        }else {
+          qh_strtod(s-1, &t);
+          if (s < t)
+            s= t;
+        }
+        prevopt= opt;
+      }
+    }
+    if (chkerr) {
+      *chkerr= '\'';
+      chkerr[strlen(chkerr)-1]=  '\'';
+      qh_fprintf(qh ferr, 6029, "qhull error: option %s is not used with this program.\n             It may be used with qhull.\n", chkerr);
+      waserr= True;
+    }
+  }
+  if (waserr)
+    qh_errexit(qh_ERRinput, NULL, NULL);
+} /* checkflags */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="qh_clear_outputflags">-</a>
+
+  qh_clear_outputflags()
+    Clear output flags for QhullPoints
+*/
+void qh_clear_outputflags(void) {
+  int i,k;
+
+  qh ANNOTATEoutput= False;
+  qh DOintersections= False;
+  qh DROPdim= -1;
+  qh FORCEoutput= False;
+  qh GETarea= False;
+  qh GOODpoint= 0;
+  qh GOODpointp= NULL;
+  qh GOODthreshold= False;
+  qh GOODvertex= 0;
+  qh GOODvertexp= NULL;
+  qh IStracing= 0;
+  qh KEEParea= False;
+  qh KEEPmerge= False;
+  qh KEEPminArea= REALmax;
+  qh PRINTcentrums= False;
+  qh PRINTcoplanar= False;
+  qh PRINTdots= False;
+  qh PRINTgood= False;
+  qh PRINTinner= False;
+  qh PRINTneighbors= False;
+  qh PRINTnoplanes= False;
+  qh PRINToptions1st= False;
+  qh PRINTouter= False;
+  qh PRINTprecision= True;
+  qh PRINTridges= False;
+  qh PRINTspheres= False;
+  qh PRINTstatistics= False;
+  qh PRINTsummary= False;
+  qh PRINTtransparent= False;
+  qh SPLITthresholds= False;
+  qh TRACElevel= 0;
+  qh TRInormals= False;
+  qh USEstdout= False;
+  qh VERIFYoutput= False;
+  for (k=qh input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
+    qh lower_threshold[k]= -REALmax;
+    qh upper_threshold[k]= REALmax;
+    qh lower_bound[k]= -REALmax;
+    qh upper_bound[k]= REALmax;
+  }
+
+  for (i=0; i < qh_PRINTEND; i++) {
+    qh PRINTout[i]= qh_PRINTnone;
+  }
+
+  if (!qh qhull_commandsiz2)
+      qh qhull_commandsiz2= (int)strlen(qh qhull_command); /* WARN64 */
+  else {
+      qh qhull_command[qh qhull_commandsiz2]= '\0';
+  }
+  if (!qh qhull_optionsiz2)
+    qh qhull_optionsiz2= (int)strlen(qh qhull_options);  /* WARN64 */
+  else {
+    qh qhull_options[qh qhull_optionsiz2]= '\0';
+    qh qhull_optionlen= qh_OPTIONline;  /* start a new line */
+  }
+} /* clear_outputflags */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="clock">-</a>
+
+  qh_clock()
+    return user CPU time in 100ths (qh_SECtick)
+    only defined for qh_CLOCKtype == 2
+
+  notes:
+    use first value to determine time 0
+    from Stevens '92 8.15
+*/
+unsigned long qh_clock(void) {
+
+#if (qh_CLOCKtype == 2)
+  struct tms time;
+  static long clktck;  /* initialized first call */
+  double ratio, cpu;
+  unsigned long ticks;
+
+  if (!clktck) {
+    if ((clktck= sysconf(_SC_CLK_TCK)) < 0) {
+      qh_fprintf(qh ferr, 6030, "qhull internal error (qh_clock): sysconf() failed.  Use qh_CLOCKtype 1 in user.h\n");
+      qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+  }
+  if (times(&time) == -1) {
+    qh_fprintf(qh ferr, 6031, "qhull internal error (qh_clock): times() failed.  Use qh_CLOCKtype 1 in user.h\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  ratio= qh_SECticks / (double)clktck;
+  ticks= time.tms_utime * ratio;
+  return ticks;
+#else
+  qh_fprintf(qh ferr, 6032, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
+  qh_errexit(qh_ERRqhull, NULL, NULL); /* never returns */
+  return 0;
+#endif
+} /* clock */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="freebuffers">-</a>
+
+  qh_freebuffers()
+    free up global memory buffers
+
+  notes:
+    must match qh_initbuffers()
+*/
+void qh_freebuffers(void) {
+
+  trace5((qh ferr, 5001, "qh_freebuffers: freeing up global memory buffers\n"));
+  /* allocated by qh_initqhull_buffers */
+  qh_memfree(qh NEARzero, qh hull_dim * sizeof(realT));
+  qh_memfree(qh lower_threshold, (qh input_dim+1) * sizeof(realT));
+  qh_memfree(qh upper_threshold, (qh input_dim+1) * sizeof(realT));
+  qh_memfree(qh lower_bound, (qh input_dim+1) * sizeof(realT));
+  qh_memfree(qh upper_bound, (qh input_dim+1) * sizeof(realT));
+  qh_memfree(qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
+  qh_memfree(qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
+  qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
+  qh lower_bound= qh upper_bound= NULL;
+  qh gm_matrix= NULL;
+  qh gm_row= NULL;
+  qh_setfree(&qh other_points);
+  qh_setfree(&qh del_vertices);
+  qh_setfree(&qh coplanarfacetset);
+  if (qh line)                /* allocated by qh_readinput, freed if no error */
+    qh_free(qh line);
+  if (qh half_space)
+    qh_free(qh half_space);
+  if (qh temp_malloc)
+    qh_free(qh temp_malloc);
+  if (qh feasible_point)      /* allocated by qh_readfeasible */
+    qh_free(qh feasible_point);
+  if (qh feasible_string)     /* allocated by qh_initflags */
+    qh_free(qh feasible_string);
+  qh line= qh feasible_string= NULL;
+  qh half_space= qh feasible_point= qh temp_malloc= NULL;
+  /* usually allocated by qh_readinput */
+  if (qh first_point && qh POINTSmalloc) {
+    qh_free(qh first_point);
+    qh first_point= NULL;
+  }
+  if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
+    qh_free(qh input_points);
+    qh input_points= NULL;
+  }
+  trace5((qh ferr, 5002, "qh_freebuffers: finished\n"));
+} /* freebuffers */
+
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="freebuild">-</a>
+
+  qh_freebuild( allmem )
+    free global memory used by qh_initbuild and qh_buildhull
+    if !allmem,
+      does not free short memory (e.g., facetT, freed by qh_memfreeshort)
+
+  design:
+    free centrums
+    free each vertex
+    mark unattached ridges
+    for each facet
+      free ridges
+      free outside set, coplanar set, neighbor set, ridge set, vertex set
+      free facet
+    free hash table
+    free interior point
+    free merge set
+    free temporary sets
+*/
+void qh_freebuild(boolT allmem) {
+  facetT *facet;
+  vertexT *vertex;
+  ridgeT *ridge, **ridgep;
+  mergeT *merge, **mergep;
+
+  trace1((qh ferr, 1005, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
+  if (qh del_vertices)
+    qh_settruncate(qh del_vertices, 0);
+  if (allmem) {
+    while ((vertex= qh vertex_list)) {
+      if (vertex->next)
+        qh_delvertex(vertex);
+      else {
+        qh_memfree(vertex, (int)sizeof(vertexT));
+        qh newvertex_list= qh vertex_list= NULL;
+      }
+    }
+  }else if (qh VERTEXneighbors) {
+    FORALLvertices
+      qh_setfreelong(&(vertex->neighbors));
+  }
+  qh VERTEXneighbors= False;
+  qh GOODclosest= NULL;
+  if (allmem) {
+    FORALLfacets {
+      FOREACHridge_(facet->ridges)
+        ridge->seen= False;
+    }
+    FORALLfacets {
+      if (facet->visible) {
+        FOREACHridge_(facet->ridges) {
+          if (!otherfacet_(ridge, facet)->visible)
+            ridge->seen= True;  /* an unattached ridge */
+        }
+      }
+    }
+    while ((facet= qh facet_list)) {
+      FOREACHridge_(facet->ridges) {
+        if (ridge->seen) {
+          qh_setfree(&(ridge->vertices));
+          qh_memfree(ridge, (int)sizeof(ridgeT));
+        }else
+          ridge->seen= True;
+      }
+      qh_setfree(&(facet->outsideset));
+      qh_setfree(&(facet->coplanarset));
+      qh_setfree(&(facet->neighbors));
+      qh_setfree(&(facet->ridges));
+      qh_setfree(&(facet->vertices));
+      if (facet->next)
+        qh_delfacet(facet);
+      else {
+        qh_memfree(facet, (int)sizeof(facetT));
+        qh visible_list= qh newfacet_list= qh facet_list= NULL;
+      }
+    }
+  }else {
+    FORALLfacets {
+      qh_setfreelong(&(facet->outsideset));
+      qh_setfreelong(&(facet->coplanarset));
+      if (!facet->simplicial) {
+        qh_setfreelong(&(facet->neighbors));
+        qh_setfreelong(&(facet->ridges));
+        qh_setfreelong(&(facet->vertices));
+      }
+    }
+  }
+  qh_setfree(&(qh hash_table));
+  qh_memfree(qh interior_point, qh normal_size);
+  qh interior_point= NULL;
+  FOREACHmerge_(qh facet_mergeset)  /* usually empty */
+    qh_memfree(merge, (int)sizeof(mergeT));
+  qh facet_mergeset= NULL;  /* temp set */
+  qh degen_mergeset= NULL;  /* temp set */
+  qh_settempfree_all();
+} /* freebuild */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="freeqhull">-</a>
+
+  qh_freeqhull( allmem )
+    see qh_freeqhull2
+    if qh_QHpointer, frees qh_qh
+*/
+void qh_freeqhull(boolT allmem) {
+    qh_freeqhull2(allmem);
+#if qh_QHpointer
+    qh_free(qh_qh);
+    qh_qh= NULL;
+#endif
+}
+
+/*-<a                             href="qh-globa.htm#TOC"
+>-------------------------------</a><a name="freeqhull2">-</a>
+
+qh_freeqhull2( allmem )
+  free global memory
+  if !allmem,
+    does not free short memory (freed by qh_memfreeshort)
+
+notes:
+  sets qh.NOerrexit in case caller forgets to
+
+see:
+  see qh_initqhull_start2()
+
+design:
+  free global and temporary memory from qh_initbuild and qh_buildhull
+  free buffers
+  free statistics
+*/
+void qh_freeqhull2(boolT allmem) {
+
+  trace1((qh ferr, 1006, "qh_freeqhull2: free global memory\n"));
+  qh NOerrexit= True;  /* no more setjmp since called at exit and ~QhullQh */
+  qh_freebuild(allmem);
+  qh_freebuffers();
+  qh_freestatistics();
+#if qh_QHpointer
+  memset((char *)qh_qh, 0, sizeof(qhT));
+  /* qh_qh freed by caller, qh_freeqhull() */
+#else
+  memset((char *)&qh_qh, 0, sizeof(qhT));
+#endif
+  qh NOerrexit= True;
+} /* freeqhull2 */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="init_A">-</a>
+
+  qh_init_A( infile, outfile, errfile, argc, argv )
+    initialize memory and stdio files
+    convert input options to option string (qh.qhull_command)
+
+  notes:
+    infile may be NULL if qh_readpoints() is not called
+
+    errfile should always be defined.  It is used for reporting
+    errors.  outfile is used for output and format options.
+
+    argc/argv may be 0/NULL
+
+    called before error handling initialized
+    qh_errexit() may not be used
+*/
+void qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
+  qh_meminit(errfile);
+  qh_initqhull_start(infile, outfile, errfile);
+  qh_init_qhull_command(argc, argv);
+} /* init_A */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="init_B">-</a>
+
+  qh_init_B( points, numpoints, dim, ismalloc )
+    initialize globals for points array
+
+    points has numpoints dim-dimensional points
+      points[0] is the first coordinate of the first point
+      points[1] is the second coordinate of the first point
+      points[dim] is the first coordinate of the second point
+
+    ismalloc=True
+      Qhull will call qh_free(points) on exit or input transformation
+    ismalloc=False
+      Qhull will allocate a new point array if needed for input transformation
+
+    qh.qhull_command
+      is the option string.
+      It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
+
+  returns:
+    if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
+      projects the input to a new point array
+
+        if qh.DELAUNAY,
+          qh.hull_dim is increased by one
+        if qh.ATinfinity,
+          qh_projectinput adds point-at-infinity for Delaunay tri.
+
+    if qh.SCALEinput
+      changes the upper and lower bounds of the input, see qh_scaleinput()
+
+    if qh.ROTATEinput
+      rotates the input by a random rotation, see qh_rotateinput()
+      if qh.DELAUNAY
+        rotates about the last coordinate
+
+  notes:
+    called after points are defined
+    qh_errexit() may be used
+*/
+void qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc) {
+  qh_initqhull_globals(points, numpoints, dim, ismalloc);
+  if (qhmem.LASTsize == 0)
+    qh_initqhull_mem();
+  /* mem.c and qset.c are initialized */
+  qh_initqhull_buffers();
+  qh_initthresholds(qh qhull_command);
+  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
+    qh_projectinput();
+  if (qh SCALEinput)
+    qh_scaleinput();
+  if (qh ROTATErandom >= 0) {
+    qh_randommatrix(qh gm_matrix, qh hull_dim, qh gm_row);
+    if (qh DELAUNAY) {
+      int k, lastk= qh hull_dim-1;
+      for (k=0; k < lastk; k++) {
+        qh gm_row[k][lastk]= 0.0;
+        qh gm_row[lastk][k]= 0.0;
+      }
+      qh gm_row[lastk][lastk]= 1.0;
+    }
+    qh_gram_schmidt(qh hull_dim, qh gm_row);
+    qh_rotateinput(qh gm_row);
+  }
+} /* init_B */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="init_qhull_command">-</a>
+
+  qh_init_qhull_command( argc, argv )
+    build qh.qhull_command from argc/argv
+
+  returns:
+    a space-delimited string of options (just as typed)
+
+  notes:
+    makes option string easy to input and output
+
+    argc/argv may be 0/NULL
+*/
+void qh_init_qhull_command(int argc, char *argv[]) {
+
+  if (!qh_argv_to_command(argc, argv, qh qhull_command, (int)sizeof(qh qhull_command))){
+    /* Assumes qh.ferr is defined. */
+    qh_fprintf(qh ferr, 6033, "qhull input error: more than %d characters in command line\n",
+          (int)sizeof(qh qhull_command));
+    qh_exit(qh_ERRinput);  /* error reported, can not use qh_errexit */
+  }
+} /* init_qhull_command */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initflags">-</a>
+
+  qh_initflags( commandStr )
+    set flags and initialized constants from commandStr
+
+  returns:
+    sets qh.qhull_command to command if needed
+
+  notes:
+    ignores first word (e.g., "qhull d")
+    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
+
+  see:
+    qh_initthresholds() continues processing of 'Pdn' and 'PDn'
+    'prompt' in unix.c for documentation
+
+  design:
+    for each space-delimited option group
+      if top-level option
+        check syntax
+        append appropriate option to option string
+        set appropriate global variable or append printFormat to print options
+      else
+        for each sub-option
+          check syntax
+          append appropriate option to option string
+          set appropriate global variable or append printFormat to print options
+*/
+void qh_initflags(char *command) {
+  int k, i, lastproject;
+  char *s= command, *t, *prev_s, *start, key;
+  boolT isgeom= False, wasproject;
+  realT r;
+
+  if (command <= &qh qhull_command[0] || command > &qh qhull_command[0] + sizeof(qh qhull_command)) {
+    if (command != &qh qhull_command[0]) {
+      *qh qhull_command= '\0';
+      strncat(qh qhull_command, command, sizeof(qh qhull_command)-strlen(qh qhull_command)-1);
+    }
+    while (*s && !isspace(*s))  /* skip program name */
+      s++;
+  }
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    prev_s= s;
+    switch (*s++) {
+    case 'd':
+      qh_option("delaunay", NULL, NULL);
+      qh DELAUNAY= True;
+      break;
+    case 'f':
+      qh_option("facets", NULL, NULL);
+      qh_appendprint(qh_PRINTfacets);
+      break;
+    case 'i':
+      qh_option("incidence", NULL, NULL);
+      qh_appendprint(qh_PRINTincidences);
+      break;
+    case 'm':
+      qh_option("mathematica", NULL, NULL);
+      qh_appendprint(qh_PRINTmathematica);
+      break;
+    case 'n':
+      qh_option("normals", NULL, NULL);
+      qh_appendprint(qh_PRINTnormals);
+      break;
+    case 'o':
+      qh_option("offFile", NULL, NULL);
+      qh_appendprint(qh_PRINToff);
+      break;
+    case 'p':
+      qh_option("points", NULL, NULL);
+      qh_appendprint(qh_PRINTpoints);
+      break;
+    case 's':
+      qh_option("summary", NULL, NULL);
+      qh PRINTsummary= True;
+      break;
+    case 'v':
+      qh_option("voronoi", NULL, NULL);
+      qh VORONOI= True;
+      qh DELAUNAY= True;
+      break;
+    case 'A':
+      if (!isdigit(*s) && *s != '.' && *s != '-')
+        qh_fprintf(qh ferr, 7002, "qhull warning: no maximum cosine angle given for option 'An'.  Ignored.\n");
+      else {
+        if (*s == '-') {
+          qh premerge_cos= -qh_strtod(s, &s);
+          qh_option("Angle-premerge-", NULL, &qh premerge_cos);
+          qh PREmerge= True;
+        }else {
+          qh postmerge_cos= qh_strtod(s, &s);
+          qh_option("Angle-postmerge", NULL, &qh postmerge_cos);
+          qh POSTmerge= True;
+        }
+        qh MERGING= True;
+      }
+      break;
+    case 'C':
+      if (!isdigit(*s) && *s != '.' && *s != '-')
+        qh_fprintf(qh ferr, 7003, "qhull warning: no centrum radius given for option 'Cn'.  Ignored.\n");
+      else {
+        if (*s == '-') {
+          qh premerge_centrum= -qh_strtod(s, &s);
+          qh_option("Centrum-premerge-", NULL, &qh premerge_centrum);
+          qh PREmerge= True;
+        }else {
+          qh postmerge_centrum= qh_strtod(s, &s);
+          qh_option("Centrum-postmerge", NULL, &qh postmerge_centrum);
+          qh POSTmerge= True;
+        }
+        qh MERGING= True;
+      }
+      break;
+    case 'E':
+      if (*s == '-')
+        qh_fprintf(qh ferr, 7004, "qhull warning: negative maximum roundoff given for option 'An'.  Ignored.\n");
+      else if (!isdigit(*s))
+        qh_fprintf(qh ferr, 7005, "qhull warning: no maximum roundoff given for option 'En'.  Ignored.\n");
+      else {
+        qh DISTround= qh_strtod(s, &s);
+        qh_option("Distance-roundoff", NULL, &qh DISTround);
+        qh SETroundoff= True;
+      }
+      break;
+    case 'H':
+      start= s;
+      qh HALFspace= True;
+      qh_strtod(s, &t);
+      while (t > s)  {
+        if (*t && !isspace(*t)) {
+          if (*t == ',')
+            t++;
+          else
+            qh_fprintf(qh ferr, 7006, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
+        }
+        s= t;
+        qh_strtod(s, &t);
+      }
+      if (start < t) {
+        if (!(qh feasible_string= (char*)calloc((size_t)(t-start+1), (size_t)1))) {
+          qh_fprintf(qh ferr, 6034, "qhull error: insufficient memory for 'Hn,n,n'\n");
+          qh_errexit(qh_ERRmem, NULL, NULL);
+        }
+        strncpy(qh feasible_string, start, (size_t)(t-start));
+        qh_option("Halfspace-about", NULL, NULL);
+        qh_option(qh feasible_string, NULL, NULL);
+      }else
+        qh_option("Halfspace", NULL, NULL);
+      break;
+    case 'R':
+      if (!isdigit(*s))
+        qh_fprintf(qh ferr, 7007, "qhull warning: missing random perturbation for option 'Rn'.  Ignored\n");
+      else {
+        qh RANDOMfactor= qh_strtod(s, &s);
+        qh_option("Random_perturb", NULL, &qh RANDOMfactor);
+        qh RANDOMdist= True;
+      }
+      break;
+    case 'V':
+      if (!isdigit(*s) && *s != '-')
+        qh_fprintf(qh ferr, 7008, "qhull warning: missing visible distance for option 'Vn'.  Ignored\n");
+      else {
+        qh MINvisible= qh_strtod(s, &s);
+        qh_option("Visible", NULL, &qh MINvisible);
+      }
+      break;
+    case 'U':
+      if (!isdigit(*s) && *s != '-')
+        qh_fprintf(qh ferr, 7009, "qhull warning: missing coplanar distance for option 'Un'.  Ignored\n");
+      else {
+        qh MAXcoplanar= qh_strtod(s, &s);
+        qh_option("U-coplanar", NULL, &qh MAXcoplanar);
+      }
+      break;
+    case 'W':
+      if (*s == '-')
+        qh_fprintf(qh ferr, 7010, "qhull warning: negative outside width for option 'Wn'.  Ignored.\n");
+      else if (!isdigit(*s))
+        qh_fprintf(qh ferr, 7011, "qhull warning: missing outside width for option 'Wn'.  Ignored\n");
+      else {
+        qh MINoutside= qh_strtod(s, &s);
+        qh_option("W-outside", NULL, &qh MINoutside);
+        qh APPROXhull= True;
+      }
+      break;
+    /************  sub menus ***************/
+    case 'F':
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'a':
+          qh_option("Farea", NULL, NULL);
+          qh_appendprint(qh_PRINTarea);
+          qh GETarea= True;
+          break;
+        case 'A':
+          qh_option("FArea-total", NULL, NULL);
+          qh GETarea= True;
+          break;
+        case 'c':
+          qh_option("Fcoplanars", NULL, NULL);
+          qh_appendprint(qh_PRINTcoplanars);
+          break;
+        case 'C':
+          qh_option("FCentrums", NULL, NULL);
+          qh_appendprint(qh_PRINTcentrums);
+          break;
+        case 'd':
+          qh_option("Fd-cdd-in", NULL, NULL);
+          qh CDDinput= True;
+          break;
+        case 'D':
+          qh_option("FD-cdd-out", NULL, NULL);
+          qh CDDoutput= True;
+          break;
+        case 'F':
+          qh_option("FFacets-xridge", NULL, NULL);
+          qh_appendprint(qh_PRINTfacets_xridge);
+          break;
+        case 'i':
+          qh_option("Finner", NULL, NULL);
+          qh_appendprint(qh_PRINTinner);
+          break;
+        case 'I':
+          qh_option("FIDs", NULL, NULL);
+          qh_appendprint(qh_PRINTids);
+          break;
+        case 'm':
+          qh_option("Fmerges", NULL, NULL);
+          qh_appendprint(qh_PRINTmerges);
+          break;
+        case 'M':
+          qh_option("FMaple", NULL, NULL);
+          qh_appendprint(qh_PRINTmaple);
+          break;
+        case 'n':
+          qh_option("Fneighbors", NULL, NULL);
+          qh_appendprint(qh_PRINTneighbors);
+          break;
+        case 'N':
+          qh_option("FNeighbors-vertex", NULL, NULL);
+          qh_appendprint(qh_PRINTvneighbors);
+          break;
+        case 'o':
+          qh_option("Fouter", NULL, NULL);
+          qh_appendprint(qh_PRINTouter);
+          break;
+        case 'O':
+          if (qh PRINToptions1st) {
+            qh_option("FOptions", NULL, NULL);
+            qh_appendprint(qh_PRINToptions);
+          }else
+            qh PRINToptions1st= True;
+          break;
+        case 'p':
+          qh_option("Fpoint-intersect", NULL, NULL);
+          qh_appendprint(qh_PRINTpointintersect);
+          break;
+        case 'P':
+          qh_option("FPoint-nearest", NULL, NULL);
+          qh_appendprint(qh_PRINTpointnearest);
+          break;
+        case 'Q':
+          qh_option("FQhull", NULL, NULL);
+          qh_appendprint(qh_PRINTqhull);
+          break;
+        case 's':
+          qh_option("Fsummary", NULL, NULL);
+          qh_appendprint(qh_PRINTsummary);
+          break;
+        case 'S':
+          qh_option("FSize", NULL, NULL);
+          qh_appendprint(qh_PRINTsize);
+          qh GETarea= True;
+          break;
+        case 't':
+          qh_option("Ftriangles", NULL, NULL);
+          qh_appendprint(qh_PRINTtriangles);
+          break;
+        case 'v':
+          /* option set in qh_initqhull_globals */
+          qh_appendprint(qh_PRINTvertices);
+          break;
+        case 'V':
+          qh_option("FVertex-average", NULL, NULL);
+          qh_appendprint(qh_PRINTaverage);
+          break;
+        case 'x':
+          qh_option("Fxtremes", NULL, NULL);
+          qh_appendprint(qh_PRINTextremes);
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7012, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'G':
+      isgeom= True;
+      qh_appendprint(qh_PRINTgeom);
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'a':
+          qh_option("Gall-points", NULL, NULL);
+          qh PRINTdots= True;
+          break;
+        case 'c':
+          qh_option("Gcentrums", NULL, NULL);
+          qh PRINTcentrums= True;
+          break;
+        case 'h':
+          qh_option("Gintersections", NULL, NULL);
+          qh DOintersections= True;
+          break;
+        case 'i':
+          qh_option("Ginner", NULL, NULL);
+          qh PRINTinner= True;
+          break;
+        case 'n':
+          qh_option("Gno-planes", NULL, NULL);
+          qh PRINTnoplanes= True;
+          break;
+        case 'o':
+          qh_option("Gouter", NULL, NULL);
+          qh PRINTouter= True;
+          break;
+        case 'p':
+          qh_option("Gpoints", NULL, NULL);
+          qh PRINTcoplanar= True;
+          break;
+        case 'r':
+          qh_option("Gridges", NULL, NULL);
+          qh PRINTridges= True;
+          break;
+        case 't':
+          qh_option("Gtransparent", NULL, NULL);
+          qh PRINTtransparent= True;
+          break;
+        case 'v':
+          qh_option("Gvertices", NULL, NULL);
+          qh PRINTspheres= True;
+          break;
+        case 'D':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6035, "qhull input error: missing dimension for option 'GDn'\n");
+          else {
+            if (qh DROPdim >= 0)
+              qh_fprintf(qh ferr, 7013, "qhull warning: can only drop one dimension.  Previous 'GD%d' ignored\n",
+                   qh DROPdim);
+            qh DROPdim= qh_strtol(s, &s);
+            qh_option("GDrop-dim", &qh DROPdim, NULL);
+          }
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7014, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'P':
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'd': case 'D':  /* see qh_initthresholds() */
+          key= s[-1];
+          i= qh_strtol(s, &s);
+          r= 0;
+          if (*s == ':') {
+            s++;
+            r= qh_strtod(s, &s);
+          }
+          if (key == 'd')
+            qh_option("Pdrop-facets-dim-less", &i, &r);
+          else
+            qh_option("PDrop-facets-dim-more", &i, &r);
+          break;
+        case 'g':
+          qh_option("Pgood-facets", NULL, NULL);
+          qh PRINTgood= True;
+          break;
+        case 'G':
+          qh_option("PGood-facet-neighbors", NULL, NULL);
+          qh PRINTneighbors= True;
+          break;
+        case 'o':
+          qh_option("Poutput-forced", NULL, NULL);
+          qh FORCEoutput= True;
+          break;
+        case 'p':
+          qh_option("Pprecision-ignore", NULL, NULL);
+          qh PRINTprecision= False;
+          break;
+        case 'A':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6036, "qhull input error: missing facet count for keep area option 'PAn'\n");
+          else {
+            qh KEEParea= qh_strtol(s, &s);
+            qh_option("PArea-keep", &qh KEEParea, NULL);
+            qh GETarea= True;
+          }
+          break;
+        case 'F':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6037, "qhull input error: missing facet area for option 'PFn'\n");
+          else {
+            qh KEEPminArea= qh_strtod(s, &s);
+            qh_option("PFacet-area-keep", NULL, &qh KEEPminArea);
+            qh GETarea= True;
+          }
+          break;
+        case 'M':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6038, "qhull input error: missing merge count for option 'PMn'\n");
+          else {
+            qh KEEPmerge= qh_strtol(s, &s);
+            qh_option("PMerge-keep", &qh KEEPmerge, NULL);
+          }
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7015, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'Q':
+      lastproject= -1;
+      while (*s && !isspace(*s)) {
+        switch (*s++) {
+        case 'b': case 'B':  /* handled by qh_initthresholds */
+          key= s[-1];
+          if (key == 'b' && *s == 'B') {
+            s++;
+            r= qh_DEFAULTbox;
+            qh SCALEinput= True;
+            qh_option("QbBound-unit-box", NULL, &r);
+            break;
+          }
+          if (key == 'b' && *s == 'b') {
+            s++;
+            qh SCALElast= True;
+            qh_option("Qbbound-last", NULL, NULL);
+            break;
+          }
+          k= qh_strtol(s, &s);
+          r= 0.0;
+          wasproject= False;
+          if (*s == ':') {
+            s++;
+            if ((r= qh_strtod(s, &s)) == 0.0) {
+              t= s;            /* need true dimension for memory allocation */
+              while (*t && !isspace(*t)) {
+                if (toupper(*t++) == 'B'
+                 && k == qh_strtol(t, &t)
+                 && *t++ == ':'
+                 && qh_strtod(t, &t) == 0.0) {
+                  qh PROJECTinput++;
+                  trace2((qh ferr, 2004, "qh_initflags: project dimension %d\n", k));
+                  qh_option("Qb-project-dim", &k, NULL);
+                  wasproject= True;
+                  lastproject= k;
+                  break;
+                }
+              }
+            }
+          }
+          if (!wasproject) {
+            if (lastproject == k && r == 0.0)
+              lastproject= -1;  /* doesn't catch all possible sequences */
+            else if (key == 'b') {
+              qh SCALEinput= True;
+              if (r == 0.0)
+                r= -qh_DEFAULTbox;
+              qh_option("Qbound-dim-low", &k, &r);
+            }else {
+              qh SCALEinput= True;
+              if (r == 0.0)
+                r= qh_DEFAULTbox;
+              qh_option("QBound-dim-high", &k, &r);
+            }
+          }
+          break;
+        case 'c':
+          qh_option("Qcoplanar-keep", NULL, NULL);
+          qh KEEPcoplanar= True;
+          break;
+        case 'f':
+          qh_option("Qfurthest-outside", NULL, NULL);
+          qh BESToutside= True;
+          break;
+        case 'g':
+          qh_option("Qgood-facets-only", NULL, NULL);
+          qh ONLYgood= True;
+          break;
+        case 'i':
+          qh_option("Qinterior-keep", NULL, NULL);
+          qh KEEPinside= True;
+          break;
+        case 'm':
+          qh_option("Qmax-outside-only", NULL, NULL);
+          qh ONLYmax= True;
+          break;
+        case 'r':
+          qh_option("Qrandom-outside", NULL, NULL);
+          qh RANDOMoutside= True;
+          break;
+        case 's':
+          qh_option("Qsearch-initial-simplex", NULL, NULL);
+          qh ALLpoints= True;
+          break;
+        case 't':
+          qh_option("Qtriangulate", NULL, NULL);
+          qh TRIangulate= True;
+          break;
+        case 'T':
+          qh_option("QTestPoints", NULL, NULL);
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 6039, "qhull input error: missing number of test points for option 'QTn'\n");
+          else {
+            qh TESTpoints= qh_strtol(s, &s);
+            qh_option("QTestPoints", &qh TESTpoints, NULL);
+          }
+          break;
+        case 'u':
+          qh_option("QupperDelaunay", NULL, NULL);
+          qh UPPERdelaunay= True;
+          break;
+        case 'v':
+          qh_option("Qvertex-neighbors-convex", NULL, NULL);
+          qh TESTvneighbors= True;
+          break;
+        case 'x':
+          qh_option("Qxact-merge", NULL, NULL);
+          qh MERGEexact= True;
+          break;
+        case 'z':
+          qh_option("Qz-infinity-point", NULL, NULL);
+          qh ATinfinity= True;
+          break;
+        case '0':
+          qh_option("Q0-no-premerge", NULL, NULL);
+          qh NOpremerge= True;
+          break;
+        case '1':
+          if (!isdigit(*s)) {
+            qh_option("Q1-no-angle-sort", NULL, NULL);
+            qh ANGLEmerge= False;
+            break;
+          }
+          switch (*s++) {
+          case '0':
+            qh_option("Q10-no-narrow", NULL, NULL);
+            qh NOnarrow= True;
+            break;
+          case '1':
+            qh_option("Q11-trinormals Qtriangulate", NULL, NULL);
+            qh TRInormals= True;
+            qh TRIangulate= True;
+            break;
+          default:
+            s--;
+            qh_fprintf(qh ferr, 7016, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
+            while (*++s && !isspace(*s));
+            break;
+          }
+          break;
+        case '2':
+          qh_option("Q2-no-merge-independent", NULL, NULL);
+          qh MERGEindependent= False;
+          goto LABELcheckdigit;
+          break; /* no warnings */
+        case '3':
+          qh_option("Q3-no-merge-vertices", NULL, NULL);
+          qh MERGEvertices= False;
+        LABELcheckdigit:
+          if (isdigit(*s))
+            qh_fprintf(qh ferr, 7017, "qhull warning: can not follow '1', '2', or '3' with a digit.  '%c' skipped.\n",
+                     *s++);
+          break;
+        case '4':
+          qh_option("Q4-avoid-old-into-new", NULL, NULL);
+          qh AVOIDold= True;
+          break;
+        case '5':
+          qh_option("Q5-no-check-outer", NULL, NULL);
+          qh SKIPcheckmax= True;
+          break;
+        case '6':
+          qh_option("Q6-no-concave-merge", NULL, NULL);
+          qh SKIPconvex= True;
+          break;
+        case '7':
+          qh_option("Q7-no-breadth-first", NULL, NULL);
+          qh VIRTUALmemory= True;
+          break;
+        case '8':
+          qh_option("Q8-no-near-inside", NULL, NULL);
+          qh NOnearinside= True;
+          break;
+        case '9':
+          qh_option("Q9-pick-furthest", NULL, NULL);
+          qh PICKfurthest= True;
+          break;
+        case 'G':
+          i= qh_strtol(s, &t);
+          if (qh GOODpoint)
+            qh_fprintf(qh ferr, 7018, "qhull warning: good point already defined for option 'QGn'.  Ignored\n");
+          else if (s == t)
+            qh_fprintf(qh ferr, 7019, "qhull warning: missing good point id for option 'QGn'.  Ignored\n");
+          else if (i < 0 || *s == '-') {
+            qh GOODpoint= i-1;
+            qh_option("QGood-if-dont-see-point", &i, NULL);
+          }else {
+            qh GOODpoint= i+1;
+            qh_option("QGood-if-see-point", &i, NULL);
+          }
+          s= t;
+          break;
+        case 'J':
+          if (!isdigit(*s) && *s != '-')
+            qh JOGGLEmax= 0.0;
+          else {
+            qh JOGGLEmax= (realT) qh_strtod(s, &s);
+            qh_option("QJoggle", NULL, &qh JOGGLEmax);
+          }
+          break;
+        case 'R':
+          if (!isdigit(*s) && *s != '-')
+            qh_fprintf(qh ferr, 7020, "qhull warning: missing random seed for option 'QRn'.  Ignored\n");
+          else {
+            qh ROTATErandom= i= qh_strtol(s, &s);
+            if (i > 0)
+              qh_option("QRotate-id", &i, NULL );
+            else if (i < -1)
+              qh_option("QRandom-seed", &i, NULL );
+          }
+          break;
+        case 'V':
+          i= qh_strtol(s, &t);
+          if (qh GOODvertex)
+            qh_fprintf(qh ferr, 7021, "qhull warning: good vertex already defined for option 'QVn'.  Ignored\n");
+          else if (s == t)
+            qh_fprintf(qh ferr, 7022, "qhull warning: no good point id given for option 'QVn'.  Ignored\n");
+          else if (i < 0) {
+            qh GOODvertex= i - 1;
+            qh_option("QV-good-facets-not-point", &i, NULL);
+          }else {
+            qh_option("QV-good-facets-point", &i, NULL);
+            qh GOODvertex= i + 1;
+          }
+          s= t;
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7023, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    case 'T':
+      while (*s && !isspace(*s)) {
+        if (isdigit(*s) || *s == '-')
+          qh IStracing= qh_strtol(s, &s);
+        else switch (*s++) {
+        case 'a':
+          qh_option("Tannotate-output", NULL, NULL);
+          qh ANNOTATEoutput= True;
+          break;
+        case 'c':
+          qh_option("Tcheck-frequently", NULL, NULL);
+          qh CHECKfrequently= True;
+          break;
+        case 's':
+          qh_option("Tstatistics", NULL, NULL);
+          qh PRINTstatistics= True;
+          break;
+        case 'v':
+          qh_option("Tverify", NULL, NULL);
+          qh VERIFYoutput= True;
+          break;
+        case 'z':
+          if (qh ferr == qh_FILEstderr) {
+            /* The C++ interface captures the output in qh_fprint_qhull() */
+            qh_option("Tz-stdout", NULL, NULL);
+            qh USEstdout= True;
+          }else if (!qh fout)
+            qh_fprintf(qh ferr, 7024, "qhull warning: output file undefined(stdout).  Option 'Tz' ignored.\n");
+          else {
+            qh_option("Tz-stdout", NULL, NULL);
+            qh USEstdout= True;
+            qh ferr= qh fout;
+            qhmem.ferr= qh fout;
+          }
+          break;
+        case 'C':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7025, "qhull warning: missing point id for cone for trace option 'TCn'.  Ignored\n");
+          else {
+            i= qh_strtol(s, &s);
+            qh_option("TCone-stop", &i, NULL);
+            qh STOPcone= i + 1;
+          }
+          break;
+        case 'F':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7026, "qhull warning: missing frequency count for trace option 'TFn'.  Ignored\n");
+          else {
+            qh REPORTfreq= qh_strtol(s, &s);
+            qh_option("TFacet-log", &qh REPORTfreq, NULL);
+            qh REPORTfreq2= qh REPORTfreq/2;  /* for tracemerging() */
+          }
+          break;
+        case 'I':
+          if (!isspace(*s))
+            qh_fprintf(qh ferr, 7027, "qhull warning: missing space between 'TI' and filename, %s\n", s);
+          while (isspace(*s))
+            s++;
+          t= qh_skipfilename(s);
+          {
+            char filename[qh_FILENAMElen];
+
+            qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s));   /* WARN64 */
+            s= t;
+            if (!freopen(filename, "r", stdin)) {
+              qh_fprintf(qh ferr, 6041, "qhull error: could not open file \"%s\".", filename);
+              qh_errexit(qh_ERRinput, NULL, NULL);
+            }else {
+              qh_option("TInput-file", NULL, NULL);
+              qh_option(filename, NULL, NULL);
+            }
+          }
+          break;
+        case 'O':
+            if (!isspace(*s))
+                qh_fprintf(qh ferr, 7028, "qhull warning: missing space between 'TO' and filename, %s\n", s);
+            while (isspace(*s))
+                s++;
+            t= qh_skipfilename(s);
+            {
+              char filename[qh_FILENAMElen];
+
+              qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s));  /* WARN64 */
+              s= t;
+              if (!freopen(filename, "w", stdout)) {
+                qh_fprintf(qh ferr, 6044, "qhull error: could not open file \"%s\".", filename);
+                qh_errexit(qh_ERRinput, NULL, NULL);
+              }else {
+                qh_option("TOutput-file", NULL, NULL);
+              qh_option(filename, NULL, NULL);
+            }
+          }
+          break;
+        case 'P':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7029, "qhull warning: missing point id for trace option 'TPn'.  Ignored\n");
+          else {
+            qh TRACEpoint= qh_strtol(s, &s);
+            qh_option("Trace-point", &qh TRACEpoint, NULL);
+          }
+          break;
+        case 'M':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7030, "qhull warning: missing merge id for trace option 'TMn'.  Ignored\n");
+          else {
+            qh TRACEmerge= qh_strtol(s, &s);
+            qh_option("Trace-merge", &qh TRACEmerge, NULL);
+          }
+          break;
+        case 'R':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7031, "qhull warning: missing rerun count for trace option 'TRn'.  Ignored\n");
+          else {
+            qh RERUN= qh_strtol(s, &s);
+            qh_option("TRerun", &qh RERUN, NULL);
+          }
+          break;
+        case 'V':
+          i= qh_strtol(s, &t);
+          if (s == t)
+            qh_fprintf(qh ferr, 7032, "qhull warning: missing furthest point id for trace option 'TVn'.  Ignored\n");
+          else if (i < 0) {
+            qh STOPpoint= i - 1;
+            qh_option("TV-stop-before-point", &i, NULL);
+          }else {
+            qh STOPpoint= i + 1;
+            qh_option("TV-stop-after-point", &i, NULL);
+          }
+          s= t;
+          break;
+        case 'W':
+          if (!isdigit(*s))
+            qh_fprintf(qh ferr, 7033, "qhull warning: missing max width for trace option 'TWn'.  Ignored\n");
+          else {
+            qh TRACEdist= (realT) qh_strtod(s, &s);
+            qh_option("TWide-trace", NULL, &qh TRACEdist);
+          }
+          break;
+        default:
+          s--;
+          qh_fprintf(qh ferr, 7034, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
+          while (*++s && !isspace(*s));
+          break;
+        }
+      }
+      break;
+    default:
+      qh_fprintf(qh ferr, 7035, "qhull warning: unknown flag %c(%x)\n", (int)s[-1],
+               (int)s[-1]);
+      break;
+    }
+    if (s-1 == prev_s && *s && !isspace(*s)) {
+      qh_fprintf(qh ferr, 7036, "qhull warning: missing space after flag %c(%x); reserved for menu. Skipped.\n",
+               (int)*prev_s, (int)*prev_s);
+      while (*s && !isspace(*s))
+        s++;
+    }
+  }
+  if (qh STOPcone && qh JOGGLEmax < REALmax/2)
+    qh_fprintf(qh ferr, 7078, "qhull warning: 'TCn' (stopCone) ignored when used with 'QJn' (joggle)\n");
+  if (isgeom && !qh FORCEoutput && qh PRINTout[1])
+    qh_fprintf(qh ferr, 7037, "qhull warning: additional output formats are not compatible with Geomview\n");
+  /* set derived values in qh_initqhull_globals */
+} /* initflags */
+
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_buffers">-</a>
+
+  qh_initqhull_buffers()
+    initialize global memory buffers
+
+  notes:
+    must match qh_freebuffers()
+*/
+void qh_initqhull_buffers(void) {
+  int k;
+
+  qh TEMPsize= (qhmem.LASTsize - sizeof(setT))/SETelemsize;
+  if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
+    qh TEMPsize= 8;  /* e.g., if qh_NOmem */
+  qh other_points= qh_setnew(qh TEMPsize);
+  qh del_vertices= qh_setnew(qh TEMPsize);
+  qh coplanarfacetset= qh_setnew(qh TEMPsize);
+  qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
+  qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
+  for (k=qh input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
+    qh lower_threshold[k]= -REALmax;
+    qh upper_threshold[k]= REALmax;
+    qh lower_bound[k]= -REALmax;
+    qh upper_bound[k]= REALmax;
+  }
+  qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
+  qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
+} /* initqhull_buffers */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_globals">-</a>
+
+  qh_initqhull_globals( points, numpoints, dim, ismalloc )
+    initialize globals
+    if ismalloc
+      points were malloc'd and qhull should free at end
+
+  returns:
+    sets qh.first_point, num_points, input_dim, hull_dim and others
+    seeds random number generator (seed=1 if tracing)
+    modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
+    adjust user flags as needed
+    also checks DIM3 dependencies and constants
+
+  notes:
+    do not use qh_point() since an input transformation may move them elsewhere
+
+  see:
+    qh_initqhull_start() sets default values for non-zero globals
+
+  design:
+    initialize points array from input arguments
+    test for qh.ZEROcentrum
+      (i.e., use opposite vertex instead of centrum for convexity testing)
+    initialize qh.CENTERtype, qh.normal_size,
+      qh.center_size, qh.TRACEpoint/level,
+    initialize and test random numbers
+    qh_initqhull_outputflags() -- adjust and test output flags
+*/
+void qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc) {
+  int seed, pointsneeded, extra= 0, i, randi, k;
+  realT randr;
+  realT factorial;
+
+  time_t timedata = 0;
+
+  trace0((qh ferr, 13, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
+      qh qhull_command));
+  qh POINTSmalloc= ismalloc;
+  qh first_point= points;
+  qh num_points= numpoints;
+  qh hull_dim= qh input_dim= dim;
+  if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
+    qh MERGING= True;
+    if (qh hull_dim <= 4) {
+      qh PREmerge= True;
+      qh_option("_pre-merge", NULL, NULL);
+    }else {
+      qh MERGEexact= True;
+      qh_option("Qxact_merge", NULL, NULL);
+    }
+  }else if (qh MERGEexact)
+    qh MERGING= True;
+  if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
+#ifdef qh_NOmerge
+    qh JOGGLEmax= 0.0;
+#endif
+  }
+  if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
+    qh_fprintf(qh ferr, 7038, "qhull warning: joggle('QJ') always produces simplicial output.  Triangulated output('Qt') does nothing.\n");
+  if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
+    qh SCALElast= True;
+    qh_option("Qbbound-last-qj", NULL, NULL);
+  }
+  if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
+  && qh premerge_centrum == 0) {
+    qh ZEROcentrum= True;
+    qh ZEROall_ok= True;
+    qh_option("_zero-centrum", NULL, NULL);
+  }
+  if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
+    qh_fprintf(qh ferr, 7039, "qhull warning: real epsilon, %2.2g, is probably too large for joggle('QJn')\nRecompile with double precision reals(see user.h).\n",
+          REALepsilon);
+#ifdef qh_NOmerge
+  if (qh MERGING) {
+    qh_fprintf(qh ferr, 6045, "qhull input error: merging not installed(qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+#endif
+  if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
+    qh KEEPinside= True;
+    qh_option("Qinterior-keep", NULL, NULL);
+  }
+  if (qh DELAUNAY && qh HALFspace) {
+    qh_fprintf(qh ferr, 6046, "qhull input error: can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
+    qh_fprintf(qh ferr, 6047, "qhull input error: use upper-Delaunay('Qu') or infinity-point('Qz') with Delaunay('d') or Voronoi('v')\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh UPPERdelaunay && qh ATinfinity) {
+    qh_fprintf(qh ferr, 6048, "qhull input error: can not use infinity-point('Qz') with upper-Delaunay('Qu')\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
+    qh_fprintf(qh ferr, 7040, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
+  qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
+  qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar)
+                          && !qh NOnearinside);
+  if (qh MERGING)
+    qh CENTERtype= qh_AScentrum;
+  else if (qh VORONOI)
+    qh CENTERtype= qh_ASvoronoi;
+  if (qh TESTvneighbors && !qh MERGING) {
+    qh_fprintf(qh ferr, 6049, "qhull input error: test vertex neighbors('Qv') needs a merge option\n");
+    qh_errexit(qh_ERRinput, NULL ,NULL);
+  }
+  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
+    qh hull_dim -= qh PROJECTinput;
+    if (qh DELAUNAY) {
+      qh hull_dim++;
+      if (qh ATinfinity)
+        extra= 1;
+    }
+  }
+  if (qh hull_dim <= 1) {
+    qh_fprintf(qh ferr, 6050, "qhull error: dimension %d must be > 1\n", qh hull_dim);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  for (k=2, factorial=1.0; k < qh hull_dim; k++)
+    factorial *= k;
+  qh AREAfactor= 1.0 / factorial;
+  trace2((qh ferr, 2005, "qh_initqhull_globals: initialize globals.  dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
+        dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
+  qh normal_size= qh hull_dim * sizeof(coordT);
+  qh center_size= qh normal_size - sizeof(coordT);
+  pointsneeded= qh hull_dim+1;
+  if (qh hull_dim > qh_DIMmergeVertex) {
+    qh MERGEvertices= False;
+    qh_option("Q3-no-merge-vertices-dim-high", NULL, NULL);
+  }
+  if (qh GOODpoint)
+    pointsneeded++;
+#ifdef qh_NOtrace
+  if (qh IStracing) {
+    qh_fprintf(qh ferr, 6051, "qhull input error: tracing is not installed(qh_NOtrace in user.h)");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+#endif
+  if (qh RERUN > 1) {
+    qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
+    if (qh IStracing != -1)
+      qh IStracing= 0;
+  }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
+    qh TRACElevel= (qh IStracing? qh IStracing : 3);
+    qh IStracing= 0;
+  }
+  if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
+    seed= (int)time(&timedata);
+    if (qh ROTATErandom  == -1) {
+      seed= -seed;
+      qh_option("QRandom-seed", &seed, NULL );
+    }else
+      qh_option("QRotate-random", &seed, NULL);
+    qh ROTATErandom= seed;
+  }
+  seed= qh ROTATErandom;
+  if (seed == INT_MIN)    /* default value */
+    seed= 1;
+  else if (seed < 0)
+    seed= -seed;
+  qh_RANDOMseed_(seed);
+  randr= 0.0;
+  for (i=1000; i--; ) {
+    randi= qh_RANDOMint;
+    randr += randi;
+    if (randi > qh_RANDOMmax) {
+      qh_fprintf(qh ferr, 8036, "\
+qhull configuration error (qh_RANDOMmax in user.h):\n\
+   random integer %d > qh_RANDOMmax(%.8g)\n",
+               randi, qh_RANDOMmax);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+  }
+  qh_RANDOMseed_(seed);
+  randr = randr/1000;
+  if (randr < qh_RANDOMmax * 0.1
+  || randr > qh_RANDOMmax * 0.9)
+    qh_fprintf(qh ferr, 8037, "\
+qhull configuration warning (qh_RANDOMmax in user.h):\n\
+   average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
+   Is qh_RANDOMmax (%.2g) wrong?\n",
+             randr, qh_RANDOMmax * 0.5, qh_RANDOMmax);
+  qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
+  qh RANDOMb= 1.0 - qh RANDOMfactor;
+  if (qh_HASHfactor < 1.1) {
+    qh_fprintf(qh ferr, 6052, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1.  Qhull uses linear hash probing\n",
+      qh_HASHfactor);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (numpoints+extra < pointsneeded) {
+    qh_fprintf(qh ferr, 6214, "qhull input error: not enough points(%d) to construct initial simplex (need %d)\n",
+            numpoints, pointsneeded);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  qh_initqhull_outputflags();
+} /* initqhull_globals */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_mem">-</a>
+
+  qh_initqhull_mem(  )
+    initialize mem.c for qhull
+    qh.hull_dim and qh.normal_size determine some of the allocation sizes
+    if qh.MERGING,
+      includes ridgeT
+    calls qh_user_memsizes() to add up to 10 additional sizes for quick allocation
+      (see numsizes below)
+
+  returns:
+    mem.c already for qh_memalloc/qh_memfree (errors if called beforehand)
+
+  notes:
+    qh_produceoutput() prints memsizes
+
+*/
+void qh_initqhull_mem(void) {
+  int numsizes;
+  int i;
+
+  numsizes= 8+10;
+  qh_meminitbuffers(qh IStracing, qh_MEMalign, numsizes,
+                     qh_MEMbufsize,qh_MEMinitbuf);
+  qh_memsize((int)sizeof(vertexT));
+  if (qh MERGING) {
+    qh_memsize((int)sizeof(ridgeT));
+    qh_memsize((int)sizeof(mergeT));
+  }
+  qh_memsize((int)sizeof(facetT));
+  i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;  /* ridge.vertices */
+  qh_memsize(i);
+  qh_memsize(qh normal_size);        /* normal */
+  i += SETelemsize;                 /* facet.vertices, .ridges, .neighbors */
+  qh_memsize(i);
+  qh_user_memsizes();
+  qh_memsetup();
+} /* initqhull_mem */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_outputflags">-</a>
+
+  qh_initqhull_outputflags
+    initialize flags concerned with output
+
+  returns:
+    adjust user flags as needed
+
+  see:
+    qh_clear_outputflags() resets the flags
+
+  design:
+    test for qh.PRINTgood (i.e., only print 'good' facets)
+    check for conflicting print output options
+*/
+void qh_initqhull_outputflags(void) {
+  boolT printgeom= False, printmath= False, printcoplanar= False;
+  int i;
+
+  trace3((qh ferr, 3024, "qh_initqhull_outputflags: %s\n", qh qhull_command));
+  if (!(qh PRINTgood || qh PRINTneighbors)) {
+    if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
+        || (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
+      qh PRINTgood= True;
+      qh_option("Pgood", NULL, NULL);
+    }
+  }
+  if (qh PRINTtransparent) {
+    if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
+      qh_fprintf(qh ferr, 6215, "qhull input error: transparent Delaunay('Gt') needs 3-d Delaunay('d') w/o 'GDn'\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    qh DROPdim = 3;
+    qh PRINTridges = True;
+  }
+  for (i=qh_PRINTEND; i--; ) {
+    if (qh PRINTout[i] == qh_PRINTgeom)
+      printgeom= True;
+    else if (qh PRINTout[i] == qh_PRINTmathematica || qh PRINTout[i] == qh_PRINTmaple)
+      printmath= True;
+    else if (qh PRINTout[i] == qh_PRINTcoplanars)
+      printcoplanar= True;
+    else if (qh PRINTout[i] == qh_PRINTpointnearest)
+      printcoplanar= True;
+    else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
+      qh_fprintf(qh ferr, 6053, "qhull input error: option 'Fp' is only used for \nhalfspace intersection('Hn,n,n').\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
+      qh_fprintf(qh ferr, 6054, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
+      qh_fprintf(qh ferr, 6055, "qhull input error: option 'FC' is not available for Voronoi vertices('v')\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }else if (qh PRINTout[i] == qh_PRINTvertices) {
+      if (qh VORONOI)
+        qh_option("Fvoronoi", NULL, NULL);
+      else
+        qh_option("Fvertices", NULL, NULL);
+    }
+  }
+  if (printcoplanar && qh DELAUNAY && qh JOGGLEmax < REALmax/2) {
+    if (qh PRINTprecision)
+      qh_fprintf(qh ferr, 7041, "qhull input warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
+  }
+  if (printmath && (qh hull_dim > 3 || qh VORONOI)) {
+    qh_fprintf(qh ferr, 6056, "qhull input error: Mathematica and Maple output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (printgeom) {
+    if (qh hull_dim > 4) {
+      qh_fprintf(qh ferr, 6057, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
+     + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
+      qh_fprintf(qh ferr, 6058, "qhull input error: no output specified for Geomview\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
+      qh_fprintf(qh ferr, 6059, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    /* can not warn about furthest-site Geomview output: no lower_threshold */
+    if (qh hull_dim == 4 && qh DROPdim == -1 &&
+        (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
+      qh_fprintf(qh ferr, 7042, "qhull input warning: coplanars, vertices, and centrums output not\n\
+available for 4-d output(ignored).  Could use 'GDn' instead.\n");
+      qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
+    }
+  }
+  if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
+    if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar) {
+      if (qh QHULLfinished) {
+        qh_fprintf(qh ferr, 7072, "qhull output warning: ignoring coplanar points, option 'Qc' was not set for the first run of qhull.\n");
+      }else {
+        qh KEEPcoplanar = True;
+        qh_option("Qcoplanar", NULL, NULL);
+      }
+    }
+  }
+  qh PRINTdim= qh hull_dim;
+  if (qh DROPdim >=0) {    /* after Geomview checks */
+    if (qh DROPdim < qh hull_dim) {
+      qh PRINTdim--;
+      if (!printgeom || qh hull_dim < 3)
+        qh_fprintf(qh ferr, 7043, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
+    }else
+      qh DROPdim= -1;
+  }else if (qh VORONOI) {
+    qh DROPdim= qh hull_dim-1;
+    qh PRINTdim= qh hull_dim-1;
+  }
+} /* qh_initqhull_outputflags */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_start">-</a>
+
+  qh_initqhull_start( infile, outfile, errfile )
+    allocate memory if needed and call qh_initqhull_start2()
+*/
+void qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile) {
+
+#if qh_QHpointer
+  if (qh_qh) {
+    qh_fprintf(errfile, 6205, "qhull error (qh_initqhull_start): qh_qh already defined.  Call qh_save_qhull() first\n");
+    qh_exit(qh_ERRqhull);  /* no error handler */
+  }
+  if (!(qh_qh= (qhT *)qh_malloc(sizeof(qhT)))) {
+    qh_fprintf(errfile, 6060, "qhull error (qh_initqhull_start): insufficient memory\n");
+    qh_exit(qh_ERRmem);  /* no error handler */
+  }
+#endif
+  qh_initstatistics();
+  qh_initqhull_start2(infile, outfile, errfile);
+} /* initqhull_start */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initqhull_start2">-</a>
+
+  qh_initqhull_start2( infile, outfile, errfile )
+    start initialization of qhull
+    initialize statistics, stdio, default values for global variables
+    assumes qh_qh is defined
+  notes:
+    report errors elsewhere, error handling and g_qhull_output [Qhull.cpp, QhullQh()] not in initialized
+  see:
+    qh_maxmin() determines the precision constants
+    qh_freeqhull2()
+*/
+void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile) {
+  time_t timedata = 0;
+  int seed;
+
+  qh_CPUclock; /* start the clock(for qh_clock).  One-shot. */
+#if qh_QHpointer
+  memset((char *)qh_qh, 0, sizeof(qhT));   /* every field is 0, FALSE, NULL */
+#else
+  memset((char *)&qh_qh, 0, sizeof(qhT));
+#endif
+  qh ANGLEmerge= True;
+  qh DROPdim= -1;
+  qh ferr= errfile;
+  qh fin= infile;
+  qh fout= outfile;
+  qh furthest_id= -1;
+  qh JOGGLEmax= REALmax;
+  qh KEEPminArea = REALmax;
+  qh last_low= REALmax;
+  qh last_high= REALmax;
+  qh last_newhigh= REALmax;
+  qh max_outside= 0.0;
+  qh max_vertex= 0.0;
+  qh MAXabs_coord= 0.0;
+  qh MAXsumcoord= 0.0;
+  qh MAXwidth= -REALmax;
+  qh MERGEindependent= True;
+  qh MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
+  qh MINoutside= 0.0;
+  qh MINvisible= REALmax;
+  qh MAXcoplanar= REALmax;
+  qh outside_err= REALmax;
+  qh premerge_centrum= 0.0;
+  qh premerge_cos= REALmax;
+  qh PRINTprecision= True;
+  qh PRINTradius= 0.0;
+  qh postmerge_cos= REALmax;
+  qh postmerge_centrum= 0.0;
+  qh ROTATErandom= INT_MIN;
+  qh MERGEvertices= True;
+  qh totarea= 0.0;
+  qh totvol= 0.0;
+  qh TRACEdist= REALmax;
+  qh TRACEpoint= -1; /* recompile or use 'TPn' */
+  qh tracefacet_id= UINT_MAX;  /* recompile to trace a facet */
+  qh tracevertex_id= UINT_MAX; /* recompile to trace a vertex */
+  seed= (int)time(&timedata);
+  qh_RANDOMseed_(seed);
+  qh run_id= qh_RANDOMint+1; /* disallow 0 [UsingLibQhull::NOqhRunId] */
+  qh_option("run-id", &qh run_id, NULL);
+  strcat(qh qhull, "qhull");
+} /* initqhull_start2 */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="initthresholds">-</a>
+
+  qh_initthresholds( commandString )
+    set thresholds for printing and scaling from commandString
+
+  returns:
+    sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
+
+  see:
+    qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
+    qh_inthresholds()
+
+  design:
+    for each 'Pdn' or 'PDn' option
+      check syntax
+      set qh.lower_threshold or qh.upper_threshold
+    set qh.GOODthreshold if an unbounded threshold is used
+    set qh.SPLITthreshold if a bounded threshold is used
+*/
+void qh_initthresholds(char *command) {
+  realT value;
+  int idx, maxdim, k;
+  char *s= command; /* non-const due to strtol */
+  char key;
+
+  maxdim= qh input_dim;
+  if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
+    maxdim++;
+  while (*s) {
+    if (*s == '-')
+      s++;
+    if (*s == 'P') {
+      s++;
+      while (*s && !isspace(key= *s++)) {
+        if (key == 'd' || key == 'D') {
+          if (!isdigit(*s)) {
+            qh_fprintf(qh ferr, 7044, "qhull warning: no dimension given for Print option '%c' at: %s.  Ignored\n",
+                    key, s-1);
+            continue;
+          }
+          idx= qh_strtol(s, &s);
+          if (idx >= qh hull_dim) {
+            qh_fprintf(qh ferr, 7045, "qhull warning: dimension %d for Print option '%c' is >= %d.  Ignored\n",
+                idx, key, qh hull_dim);
+            continue;
+          }
+          if (*s == ':') {
+            s++;
+            value= qh_strtod(s, &s);
+            if (fabs((double)value) > 1.0) {
+              qh_fprintf(qh ferr, 7046, "qhull warning: value %2.4g for Print option %c is > +1 or < -1.  Ignored\n",
+                      value, key);
+              continue;
+            }
+          }else
+            value= 0.0;
+          if (key == 'd')
+            qh lower_threshold[idx]= value;
+          else
+            qh upper_threshold[idx]= value;
+        }
+      }
+    }else if (*s == 'Q') {
+      s++;
+      while (*s && !isspace(key= *s++)) {
+        if (key == 'b' && *s == 'B') {
+          s++;
+          for (k=maxdim; k--; ) {
+            qh lower_bound[k]= -qh_DEFAULTbox;
+            qh upper_bound[k]= qh_DEFAULTbox;
+          }
+        }else if (key == 'b' && *s == 'b')
+          s++;
+        else if (key == 'b' || key == 'B') {
+          if (!isdigit(*s)) {
+            qh_fprintf(qh ferr, 7047, "qhull warning: no dimension given for Qhull option %c.  Ignored\n",
+                    key);
+            continue;
+          }
+          idx= qh_strtol(s, &s);
+          if (idx >= maxdim) {
+            qh_fprintf(qh ferr, 7048, "qhull warning: dimension %d for Qhull option %c is >= %d.  Ignored\n",
+                idx, key, maxdim);
+            continue;
+          }
+          if (*s == ':') {
+            s++;
+            value= qh_strtod(s, &s);
+          }else if (key == 'b')
+            value= -qh_DEFAULTbox;
+          else
+            value= qh_DEFAULTbox;
+          if (key == 'b')
+            qh lower_bound[idx]= value;
+          else
+            qh upper_bound[idx]= value;
+        }
+      }
+    }else {
+      while (*s && !isspace(*s))
+        s++;
+    }
+    while (isspace(*s))
+      s++;
+  }
+  for (k=qh hull_dim; k--; ) {
+    if (qh lower_threshold[k] > -REALmax/2) {
+      qh GOODthreshold= True;
+      if (qh upper_threshold[k] < REALmax/2) {
+        qh SPLITthresholds= True;
+        qh GOODthreshold= False;
+        break;
+      }
+    }else if (qh upper_threshold[k] < REALmax/2)
+      qh GOODthreshold= True;
+  }
+} /* initthresholds */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="option">-</a>
+
+  qh_option( option, intVal, realVal )
+    add an option description to qh.qhull_options
+
+  notes:
+    NOerrors -- qh_option can not call qh_errexit() [qh_initqhull_start2]
+    will be printed with statistics ('Ts') and errors
+    strlen(option) < 40
+*/
+void qh_option(const char *option, int *i, realT *r) {
+  char buf[200];
+  int len, maxlen;
+
+  sprintf(buf, "  %s", option);
+  if (i)
+    sprintf(buf+strlen(buf), " %d", *i);
+  if (r)
+    sprintf(buf+strlen(buf), " %2.2g", *r);
+  len= (int)strlen(buf);  /* WARN64 */
+  qh qhull_optionlen += len;
+  maxlen= sizeof(qh qhull_options) - len -1;
+  maximize_(maxlen, 0);
+  if (qh qhull_optionlen >= qh_OPTIONline && maxlen > 0) {
+    qh qhull_optionlen= len;
+    strncat(qh qhull_options, "\n", (size_t)(maxlen--));
+  }
+  strncat(qh qhull_options, buf, (size_t)maxlen);
+} /* option */
+
+#if qh_QHpointer
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="restore_qhull">-</a>
+
+  qh_restore_qhull( oldqh )
+    restores a previously saved qhull
+    also restores qh_qhstat and qhmem.tempstack
+    Sets *oldqh to NULL
+  notes:
+    errors if current qhull hasn't been saved or freed
+    uses qhmem for error reporting
+
+  NOTE 1998/5/11:
+    Freeing memory after qh_save_qhull and qh_restore_qhull
+    is complicated.  The procedures will be redesigned.
+
+  see:
+    qh_save_qhull(), UsingLibQhull
+*/
+void qh_restore_qhull(qhT **oldqh) {
+
+  if (*oldqh && strcmp((*oldqh)->qhull, "qhull")) {
+    qh_fprintf(qhmem.ferr, 6061, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
+                  *oldqh);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (qh_qh) {
+    qh_fprintf(qhmem.ferr, 6062, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (!*oldqh || !(*oldqh)->old_qhstat) {
+    qh_fprintf(qhmem.ferr, 6063, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
+                  *oldqh);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  qh_qh= *oldqh;
+  *oldqh= NULL;
+  qh_qhstat= qh old_qhstat;
+  qhmem.tempstack= qh old_tempstack;
+  qh old_qhstat= 0;
+  qh old_tempstack= 0;
+  trace1((qh ferr, 1007, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
+} /* restore_qhull */
+
+/*-<a                             href="qh-globa.htm#TOC"
+  >-------------------------------</a><a name="save_qhull">-</a>
+
+  qh_save_qhull(  )
+    saves qhull for a later qh_restore_qhull
+    also saves qh_qhstat and qhmem.tempstack
+
+  returns:
+    qh_qh=NULL
+
+  notes:
+    need to initialize qhull or call qh_restore_qhull before continuing
+
+  NOTE 1998/5/11:
+    Freeing memory after qh_save_qhull and qh_restore_qhull
+    is complicated.  The procedures will be redesigned.
+
+  see:
+    qh_restore_qhull()
+*/
+qhT *qh_save_qhull(void) {
+  qhT *oldqh;
+
+  trace1((qhmem.ferr, 1045, "qh_save_qhull: save qhull %p\n", qh_qh));
+  if (!qh_qh) {
+    qh_fprintf(qhmem.ferr, 6064, "qhull internal error (qh_save_qhull): qhull not initialized\n");
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  qh old_qhstat= qh_qhstat;
+  qh_qhstat= NULL;
+  qh old_tempstack= qhmem.tempstack;
+  qhmem.tempstack= NULL;
+  oldqh= qh_qh;
+  qh_qh= NULL;
+  return oldqh;
+} /* save_qhull */
+
+#endif
diff --git a/alg/internal_libqhull/io.c b/alg/internal_libqhull/io.c
new file mode 100644
index 0000000..3207f84
--- /dev/null
+++ b/alg/internal_libqhull/io.c
@@ -0,0 +1,4060 @@
+/*<html><pre>  -<a                             href="qh-io.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   io.c
+   Input/Output routines of qhull application
+
+   see qh-io.htm and io.h
+
+   see user.c for qh_errprint and qh_printfacetlist
+
+   unix.c calls qh_readpoints and qh_produce_output
+
+   unix.c and user.c are the only callers of io.c functions
+   This allows the user to avoid loading io.o from qhull.a
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/io.c#3 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#include "qhull_a.h"
+
+/*========= -functions in alphabetical order after qh_produce_output()  =====*/
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="produce_output">-</a>
+
+  qh_produce_output()
+  qh_produce_output2()
+    prints out the result of qhull in desired format
+    qh_produce_output2() does not call qh_prepare_output()
+    if qh.GETarea
+      computes and prints area and volume
+    qh.PRINTout[] is an array of output formats
+
+  notes:
+    prints output in qh.PRINTout order
+*/
+void qh_produce_output(void) {
+    int tempsize= qh_setsize(qhmem.tempstack);
+
+    qh_prepare_output();
+    qh_produce_output2();
+    if (qh_setsize(qhmem.tempstack) != tempsize) {
+        qh_fprintf(qh ferr, 6206, "qhull internal error (qh_produce_output): temporary sets not empty(%d)\n",
+            qh_setsize(qhmem.tempstack));
+        qh_errexit(qh_ERRqhull, NULL, NULL);
+    }
+} /* produce_output */
+
+
+void qh_produce_output2(void) {
+  int i, tempsize= qh_setsize(qhmem.tempstack), d_1;
+
+  if (qh PRINTsummary)
+    qh_printsummary(qh ferr);
+  else if (qh PRINTout[0] == qh_PRINTnone)
+    qh_printsummary(qh fout);
+  for (i=0; i < qh_PRINTEND; i++)
+    qh_printfacets(qh fout, qh PRINTout[i], qh facet_list, NULL, !qh_ALL);
+  qh_allstatistics();
+  if (qh PRINTprecision && !qh MERGING && (qh JOGGLEmax > REALmax/2 || qh RERUN))
+    qh_printstats(qh ferr, qhstat precision, NULL);
+  if (qh VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0))
+    qh_printstats(qh ferr, qhstat vridges, NULL);
+  if (qh PRINTstatistics) {
+    qh_printstatistics(qh ferr, "");
+    qh_memstatistics(qh ferr);
+    d_1= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;
+    qh_fprintf(qh ferr, 8040, "\
+    size in bytes: merge %d ridge %d vertex %d facet %d\n\
+         normal %d ridge vertices %d facet vertices or neighbors %d\n",
+            (int)sizeof(mergeT), (int)sizeof(ridgeT),
+            (int)sizeof(vertexT), (int)sizeof(facetT),
+            qh normal_size, d_1, d_1 + SETelemsize);
+  }
+  if (qh_setsize(qhmem.tempstack) != tempsize) {
+    qh_fprintf(qh ferr, 6065, "qhull internal error (qh_produce_output2): temporary sets not empty(%d)\n",
+             qh_setsize(qhmem.tempstack));
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+} /* produce_output2 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="dfacet">-</a>
+
+  dfacet( id )
+    print facet by id, for debugging
+
+*/
+void dfacet(unsigned id) {
+  facetT *facet;
+
+  FORALLfacets {
+    if (facet->id == id) {
+      qh_printfacet(qh fout, facet);
+      break;
+    }
+  }
+} /* dfacet */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="dvertex">-</a>
+
+  dvertex( id )
+    print vertex by id, for debugging
+*/
+void dvertex(unsigned id) {
+  vertexT *vertex;
+
+  FORALLvertices {
+    if (vertex->id == id) {
+      qh_printvertex(qh fout, vertex);
+      break;
+    }
+  }
+} /* dvertex */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="compare_vertexpoint">-</a>
+
+  qh_compare_vertexpoint( p1, p2 )
+    used by qsort() to order vertices by point id
+*/
+int qh_compare_vertexpoint(const void *p1, const void *p2) {
+  const vertexT *a= *((vertexT *const*)p1), *b= *((vertexT *const*)p2);
+
+  return((qh_pointid(a->point) > qh_pointid(b->point)?1:-1));
+} /* compare_vertexpoint */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="compare_facetarea">-</a>
+
+  qh_compare_facetarea( p1, p2 )
+    used by qsort() to order facets by area
+*/
+int qh_compare_facetarea(const void *p1, const void *p2) {
+  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
+
+  if (!a->isarea)
+    return -1;
+  if (!b->isarea)
+    return 1;
+  if (a->f.area > b->f.area)
+    return 1;
+  else if (a->f.area == b->f.area)
+    return 0;
+  return -1;
+} /* compare_facetarea */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="compare_facetmerge">-</a>
+
+  qh_compare_facetmerge( p1, p2 )
+    used by qsort() to order facets by number of merges
+*/
+int qh_compare_facetmerge(const void *p1, const void *p2) {
+  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
+
+  return(a->nummerge - b->nummerge);
+} /* compare_facetvisit */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="compare_facetvisit">-</a>
+
+  qh_compare_facetvisit( p1, p2 )
+    used by qsort() to order facets by visit id or id
+*/
+int qh_compare_facetvisit(const void *p1, const void *p2) {
+  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
+  int i,j;
+
+  if (!(i= a->visitid))
+    i= 0 - a->id; /* do not convert to int, sign distinguishes id from visitid */
+  if (!(j= b->visitid))
+    j= 0 - b->id;
+  return(i - j);
+} /* compare_facetvisit */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="copyfilename">-</a>
+
+  qh_copyfilename( dest, size, source, length )
+    copy filename identified by qh_skipfilename()
+
+  notes:
+    see qh_skipfilename() for syntax
+*/
+void qh_copyfilename(char *filename, int size, const char* source, int length) {
+  char c= *source;
+
+  if (length > size + 1) {
+      qh_fprintf(qh ferr, 6040, "qhull error: filename is more than %d characters, %s\n",  size-1, source);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  strncpy(filename, source, length);
+  filename[length]= '\0';
+  if (c == '\'' || c == '"') {
+    char *s= filename + 1;
+    char *t= filename;
+    while (*s) {
+      if (*s == c) {
+          if (s[-1] == '\\')
+              t[-1]= c;
+      }else
+          *t++= *s;
+      s++;
+    }
+    *t= '\0';
+  }
+} /* copyfilename */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="countfacets">-</a>
+
+  qh_countfacets( facetlist, facets, printall,
+          numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars  )
+    count good facets for printing and set visitid
+    if allfacets, ignores qh_skipfacet()
+
+  notes:
+    qh_printsummary and qh_countfacets must match counts
+
+  returns:
+    numfacets, numsimplicial, total neighbors, numridges, coplanars
+    each facet with ->visitid indicating 1-relative position
+      ->visitid==0 indicates not good
+
+  notes
+    numfacets >= numsimplicial
+    if qh.NEWfacets,
+      does not count visible facets (matches qh_printafacet)
+
+  design:
+    for all facets on facetlist and in facets set
+      unless facet is skipped or visible (i.e., will be deleted)
+        mark facet->visitid
+        update counts
+*/
+void qh_countfacets(facetT *facetlist, setT *facets, boolT printall,
+    int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
+  facetT *facet, **facetp;
+  int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
+
+  FORALLfacet_(facetlist) {
+    if ((facet->visible && qh NEWfacets)
+    || (!printall && qh_skipfacet(facet)))
+      facet->visitid= 0;
+    else {
+      facet->visitid= ++numfacets;
+      totneighbors += qh_setsize(facet->neighbors);
+      if (facet->simplicial) {
+        numsimplicial++;
+        if (facet->keepcentrum && facet->tricoplanar)
+          numtricoplanars++;
+      }else
+        numridges += qh_setsize(facet->ridges);
+      if (facet->coplanarset)
+        numcoplanars += qh_setsize(facet->coplanarset);
+    }
+  }
+
+  FOREACHfacet_(facets) {
+    if ((facet->visible && qh NEWfacets)
+    || (!printall && qh_skipfacet(facet)))
+      facet->visitid= 0;
+    else {
+      facet->visitid= ++numfacets;
+      totneighbors += qh_setsize(facet->neighbors);
+      if (facet->simplicial){
+        numsimplicial++;
+        if (facet->keepcentrum && facet->tricoplanar)
+          numtricoplanars++;
+      }else
+        numridges += qh_setsize(facet->ridges);
+      if (facet->coplanarset)
+        numcoplanars += qh_setsize(facet->coplanarset);
+    }
+  }
+  qh visit_id += numfacets+1;
+  *numfacetsp= numfacets;
+  *numsimplicialp= numsimplicial;
+  *totneighborsp= totneighbors;
+  *numridgesp= numridges;
+  *numcoplanarsp= numcoplanars;
+  *numtricoplanarsp= numtricoplanars;
+} /* countfacets */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="detvnorm">-</a>
+
+  qh_detvnorm( vertex, vertexA, centers, offset )
+    compute separating plane of the Voronoi diagram for a pair of input sites
+    centers= set of facets (i.e., Voronoi vertices)
+      facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
+
+  assumes:
+    qh_ASvoronoi and qh_vertexneighbors() already set
+
+  returns:
+    norm
+      a pointer into qh.gm_matrix to qh.hull_dim-1 reals
+      copy the data before reusing qh.gm_matrix
+    offset
+      if 'QVn'
+        sign adjusted so that qh.GOODvertexp is inside
+      else
+        sign adjusted so that vertex is inside
+
+    qh.gm_matrix= simplex of points from centers relative to first center
+
+  notes:
+    in io.c so that code for 'v Tv' can be removed by removing io.c
+    returns pointer into qh.gm_matrix to avoid tracking of temporary memory
+
+  design:
+    determine midpoint of input sites
+    build points as the set of Voronoi vertices
+    select a simplex from points (if necessary)
+      include midpoint if the Voronoi region is unbounded
+    relocate the first vertex of the simplex to the origin
+    compute the normalized hyperplane through the simplex
+    orient the hyperplane toward 'QVn' or 'vertex'
+    if 'Tv' or 'Ts'
+      if bounded
+        test that hyperplane is the perpendicular bisector of the input sites
+      test that Voronoi vertices not in the simplex are still on the hyperplane
+    free up temporary memory
+*/
+pointT *qh_detvnorm(vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
+  facetT *facet, **facetp;
+  int  i, k, pointid, pointidA, point_i, point_n;
+  setT *simplex= NULL;
+  pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
+  coordT *coord, *gmcoord, *normalp;
+  setT *points= qh_settemp(qh TEMPsize);
+  boolT nearzero= False;
+  boolT unbounded= False;
+  int numcenters= 0;
+  int dim= qh hull_dim - 1;
+  realT dist, offset, angle, zero= 0.0;
+
+  midpoint= qh gm_matrix + qh hull_dim * qh hull_dim;  /* last row */
+  for (k=0; k < dim; k++)
+    midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
+  FOREACHfacet_(centers) {
+    numcenters++;
+    if (!facet->visitid)
+      unbounded= True;
+    else {
+      if (!facet->center)
+        facet->center= qh_facetcenter(facet->vertices);
+      qh_setappend(&points, facet->center);
+    }
+  }
+  if (numcenters > dim) {
+    simplex= qh_settemp(qh TEMPsize);
+    qh_setappend(&simplex, vertex->point);
+    if (unbounded)
+      qh_setappend(&simplex, midpoint);
+    qh_maxsimplex(dim, points, NULL, 0, &simplex);
+    qh_setdelnth(simplex, 0);
+  }else if (numcenters == dim) {
+    if (unbounded)
+      qh_setappend(&points, midpoint);
+    simplex= points;
+  }else {
+    qh_fprintf(qh ferr, 6216, "qhull internal error (qh_detvnorm): too few points(%d) to compute separating plane\n", numcenters);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  i= 0;
+  gmcoord= qh gm_matrix;
+  point0= SETfirstt_(simplex, pointT);
+  FOREACHpoint_(simplex) {
+    if (qh IStracing >= 4)
+      qh_printmatrix(qh ferr, "qh_detvnorm: Voronoi vertex or midpoint",
+                              &point, 1, dim);
+    if (point != point0) {
+      qh gm_row[i++]= gmcoord;
+      coord= point0;
+      for (k=dim; k--; )
+        *(gmcoord++)= *point++ - *coord++;
+    }
+  }
+  qh gm_row[i]= gmcoord;  /* does not overlap midpoint, may be used later for qh_areasimplex */
+  normal= gmcoord;
+  qh_sethyperplane_gauss(dim, qh gm_row, point0, True,
+                normal, &offset, &nearzero);
+  if (qh GOODvertexp == vertexA->point)
+    inpoint= vertexA->point;
+  else
+    inpoint= vertex->point;
+  zinc_(Zdistio);
+  dist= qh_distnorm(dim, inpoint, normal, &offset);
+  if (dist > 0) {
+    offset= -offset;
+    normalp= normal;
+    for (k=dim; k--; ) {
+      *normalp= -(*normalp);
+      normalp++;
+    }
+  }
+  if (qh VERIFYoutput || qh PRINTstatistics) {
+    pointid= qh_pointid(vertex->point);
+    pointidA= qh_pointid(vertexA->point);
+    if (!unbounded) {
+      zinc_(Zdiststat);
+      dist= qh_distnorm(dim, midpoint, normal, &offset);
+      if (dist < 0)
+        dist= -dist;
+      zzinc_(Zridgemid);
+      wwmax_(Wridgemidmax, dist);
+      wwadd_(Wridgemid, dist);
+      trace4((qh ferr, 4014, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
+                 pointid, pointidA, dist));
+      for (k=0; k < dim; k++)
+        midpoint[k]= vertexA->point[k] - vertex->point[k];  /* overwrites midpoint! */
+      qh_normalize(midpoint, dim, False);
+      angle= qh_distnorm(dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
+      if (angle < 0.0)
+        angle= angle + 1.0;
+      else
+        angle= angle - 1.0;
+      if (angle < 0.0)
+        angle -= angle;
+      trace4((qh ferr, 4015, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
+                 pointid, pointidA, angle, nearzero));
+      if (nearzero) {
+        zzinc_(Zridge0);
+        wwmax_(Wridge0max, angle);
+        wwadd_(Wridge0, angle);
+      }else {
+        zzinc_(Zridgeok)
+        wwmax_(Wridgeokmax, angle);
+        wwadd_(Wridgeok, angle);
+      }
+    }
+    if (simplex != points) {
+      FOREACHpoint_i_(points) {
+        if (!qh_setin(simplex, point)) {
+          facet= SETelemt_(centers, point_i, facetT);
+          zinc_(Zdiststat);
+          dist= qh_distnorm(dim, point, normal, &offset);
+          if (dist < 0)
+            dist= -dist;
+          zzinc_(Zridge);
+          wwmax_(Wridgemax, dist);
+          wwadd_(Wridge, dist);
+          trace4((qh ferr, 4016, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
+                             pointid, pointidA, facet->visitid, dist));
+        }
+      }
+    }
+  }
+  *offsetp= offset;
+  if (simplex != points)
+    qh_settempfree(&simplex);
+  qh_settempfree(&points);
+  return normal;
+} /* detvnorm */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="detvridge">-</a>
+
+  qh_detvridge( vertexA )
+    determine Voronoi ridge from 'seen' neighbors of vertexA
+    include one vertex-at-infinite if an !neighbor->visitid
+
+  returns:
+    temporary set of centers (facets, i.e., Voronoi vertices)
+    sorted by center id
+*/
+setT *qh_detvridge(vertexT *vertex) {
+  setT *centers= qh_settemp(qh TEMPsize);
+  setT *tricenters= qh_settemp(qh TEMPsize);
+  facetT *neighbor, **neighborp;
+  boolT firstinf= True;
+
+  FOREACHneighbor_(vertex) {
+    if (neighbor->seen) {
+      if (neighbor->visitid) {
+        if (!neighbor->tricoplanar || qh_setunique(&tricenters, neighbor->center))
+          qh_setappend(&centers, neighbor);
+      }else if (firstinf) {
+        firstinf= False;
+        qh_setappend(&centers, neighbor);
+      }
+    }
+  }
+  qsort(SETaddr_(centers, facetT), (size_t)qh_setsize(centers),
+             sizeof(facetT *), qh_compare_facetvisit);
+  qh_settempfree(&tricenters);
+  return centers;
+} /* detvridge */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="detvridge3">-</a>
+
+  qh_detvridge3( atvertex, vertex )
+    determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
+    include one vertex-at-infinite for !neighbor->visitid
+    assumes all facet->seen2= True
+
+  returns:
+    temporary set of centers (facets, i.e., Voronoi vertices)
+    listed in adjacency order (!oriented)
+    all facet->seen2= True
+
+  design:
+    mark all neighbors of atvertex
+    for each adjacent neighbor of both atvertex and vertex
+      if neighbor selected
+        add neighbor to set of Voronoi vertices
+*/
+setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex) {
+  setT *centers= qh_settemp(qh TEMPsize);
+  setT *tricenters= qh_settemp(qh TEMPsize);
+  facetT *neighbor, **neighborp, *facet= NULL;
+  boolT firstinf= True;
+
+  FOREACHneighbor_(atvertex)
+    neighbor->seen2= False;
+  FOREACHneighbor_(vertex) {
+    if (!neighbor->seen2) {
+      facet= neighbor;
+      break;
+    }
+  }
+  while (facet) {
+    facet->seen2= True;
+    if (neighbor->seen) {
+      if (facet->visitid) {
+        if (!facet->tricoplanar || qh_setunique(&tricenters, facet->center))
+          qh_setappend(&centers, facet);
+      }else if (firstinf) {
+        firstinf= False;
+        qh_setappend(&centers, facet);
+      }
+    }
+    FOREACHneighbor_(facet) {
+      if (!neighbor->seen2) {
+        if (qh_setin(vertex->neighbors, neighbor))
+          break;
+        else
+          neighbor->seen2= True;
+      }
+    }
+    facet= neighbor;
+  }
+  if (qh CHECKfrequently) {
+    FOREACHneighbor_(vertex) {
+      if (!neighbor->seen2) {
+          qh_fprintf(qh ferr, 6217, "qhull internal error (qh_detvridge3): neighbors of vertex p%d are not connected at facet %d\n",
+                 qh_pointid(vertex->point), neighbor->id);
+        qh_errexit(qh_ERRqhull, neighbor, NULL);
+      }
+    }
+  }
+  FOREACHneighbor_(atvertex)
+    neighbor->seen2= True;
+  qh_settempfree(&tricenters);
+  return centers;
+} /* detvridge3 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="eachvoronoi">-</a>
+
+  qh_eachvoronoi( fp, printvridge, vertex, visitall, innerouter, inorder )
+    if visitall,
+      visit all Voronoi ridges for vertex (i.e., an input site)
+    else
+      visit all unvisited Voronoi ridges for vertex
+      all vertex->seen= False if unvisited
+    assumes
+      all facet->seen= False
+      all facet->seen2= True (for qh_detvridge3)
+      all facet->visitid == 0 if vertex_at_infinity
+                         == index of Voronoi vertex
+                         >= qh.num_facets if ignored
+    innerouter:
+      qh_RIDGEall--  both inner (bounded) and outer(unbounded) ridges
+      qh_RIDGEinner- only inner
+      qh_RIDGEouter- only outer
+
+    if inorder
+      orders vertices for 3-d Voronoi diagrams
+
+  returns:
+    number of visited ridges (does not include previously visited ridges)
+
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers)
+        fp== any pointer (assumes FILE*)
+        vertex,vertexA= pair of input sites that define a Voronoi ridge
+        centers= set of facets (i.e., Voronoi vertices)
+                 ->visitid == index or 0 if vertex_at_infinity
+                 ordered for 3-d Voronoi diagram
+  notes:
+    uses qh.vertex_visit
+
+  see:
+    qh_eachvoronoi_all()
+
+  design:
+    mark selected neighbors of atvertex
+    for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
+      for each unvisited vertex
+        if atvertex and vertex share more than d-1 neighbors
+          bump totalcount
+          if printvridge defined
+            build the set of shared neighbors (i.e., Voronoi vertices)
+            call printvridge
+*/
+int qh_eachvoronoi(FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
+  boolT unbounded;
+  int count;
+  facetT *neighbor, **neighborp, *neighborA, **neighborAp;
+  setT *centers;
+  setT *tricenters= qh_settemp(qh TEMPsize);
+
+  vertexT *vertex, **vertexp;
+  boolT firstinf;
+  unsigned int numfacets= (unsigned int)qh num_facets;
+  int totridges= 0;
+
+  qh vertex_visit++;
+  atvertex->seen= True;
+  if (visitall) {
+    FORALLvertices
+      vertex->seen= False;
+  }
+  FOREACHneighbor_(atvertex) {
+    if (neighbor->visitid < numfacets)
+      neighbor->seen= True;
+  }
+  FOREACHneighbor_(atvertex) {
+    if (neighbor->seen) {
+      FOREACHvertex_(neighbor->vertices) {
+        if (vertex->visitid != qh vertex_visit && !vertex->seen) {
+          vertex->visitid= qh vertex_visit;
+          count= 0;
+          firstinf= True;
+          qh_settruncate(tricenters, 0);
+          FOREACHneighborA_(vertex) {
+            if (neighborA->seen) {
+              if (neighborA->visitid) {
+                if (!neighborA->tricoplanar || qh_setunique(&tricenters, neighborA->center))
+                  count++;
+              }else if (firstinf) {
+                count++;
+                firstinf= False;
+              }
+            }
+          }
+          if (count >= qh hull_dim - 1) {  /* e.g., 3 for 3-d Voronoi */
+            if (firstinf) {
+              if (innerouter == qh_RIDGEouter)
+                continue;
+              unbounded= False;
+            }else {
+              if (innerouter == qh_RIDGEinner)
+                continue;
+              unbounded= True;
+            }
+            totridges++;
+            trace4((qh ferr, 4017, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
+                  count, qh_pointid(atvertex->point), qh_pointid(vertex->point)));
+            if (printvridge && fp) {
+              if (inorder && qh hull_dim == 3+1) /* 3-d Voronoi diagram */
+                centers= qh_detvridge3 (atvertex, vertex);
+              else
+                centers= qh_detvridge(vertex);
+              (*printvridge) (fp, atvertex, vertex, centers, unbounded);
+              qh_settempfree(&centers);
+            }
+          }
+        }
+      }
+    }
+  }
+  FOREACHneighbor_(atvertex)
+    neighbor->seen= False;
+  qh_settempfree(&tricenters);
+  return totridges;
+} /* eachvoronoi */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="eachvoronoi_all">-</a>
+
+  qh_eachvoronoi_all( fp, printvridge, isUpper, innerouter, inorder )
+    visit all Voronoi ridges
+
+    innerouter:
+      see qh_eachvoronoi()
+
+    if inorder
+      orders vertices for 3-d Voronoi diagrams
+
+  returns
+    total number of ridges
+
+    if isUpper == facet->upperdelaunay  (i.e., a Vornoi vertex)
+      facet->visitid= Voronoi vertex index(same as 'o' format)
+    else
+      facet->visitid= 0
+
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers)
+      [see qh_eachvoronoi]
+
+  notes:
+    Not used for qhull.exe
+    same effect as qh_printvdiagram but ridges not sorted by point id
+*/
+int qh_eachvoronoi_all(FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder) {
+  facetT *facet;
+  vertexT *vertex;
+  int numcenters= 1;  /* vertex 0 is vertex-at-infinity */
+  int totridges= 0;
+
+  qh_clearcenters(qh_ASvoronoi);
+  qh_vertexneighbors();
+  maximize_(qh visit_id, (unsigned) qh num_facets);
+  FORALLfacets {
+    facet->visitid= 0;
+    facet->seen= False;
+    facet->seen2= True;
+  }
+  FORALLfacets {
+    if (facet->upperdelaunay == isUpper)
+      facet->visitid= numcenters++;
+  }
+  FORALLvertices
+    vertex->seen= False;
+  FORALLvertices {
+    if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
+      continue;
+    totridges += qh_eachvoronoi(fp, printvridge, vertex,
+                   !qh_ALL, innerouter, inorder);
+  }
+  return totridges;
+} /* eachvoronoi_all */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="facet2point">-</a>
+
+  qh_facet2point( facet, point0, point1, mindist )
+    return two projected temporary vertices for a 2-d facet
+    may be non-simplicial
+
+  returns:
+    point0 and point1 oriented and projected to the facet
+    returns mindist (maximum distance below plane)
+*/
+void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
+  vertexT *vertex0, *vertex1;
+  realT dist;
+
+  if (facet->toporient ^ qh_ORIENTclock) {
+    vertex0= SETfirstt_(facet->vertices, vertexT);
+    vertex1= SETsecondt_(facet->vertices, vertexT);
+  }else {
+    vertex1= SETfirstt_(facet->vertices, vertexT);
+    vertex0= SETsecondt_(facet->vertices, vertexT);
+  }
+  zadd_(Zdistio, 2);
+  qh_distplane(vertex0->point, facet, &dist);
+  *mindist= dist;
+  *point0= qh_projectpoint(vertex0->point, facet, dist);
+  qh_distplane(vertex1->point, facet, &dist);
+  minimize_(*mindist, dist);
+  *point1= qh_projectpoint(vertex1->point, facet, dist);
+} /* facet2point */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="facetvertices">-</a>
+
+  qh_facetvertices( facetlist, facets, allfacets )
+    returns temporary set of vertices in a set and/or list of facets
+    if allfacets, ignores qh_skipfacet()
+
+  returns:
+    vertices with qh.vertex_visit
+
+  notes:
+    optimized for allfacets of facet_list
+
+  design:
+    if allfacets of facet_list
+      create vertex set from vertex_list
+    else
+      for each selected facet in facets or facetlist
+        append unvisited vertices to vertex set
+*/
+setT *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets) {
+  setT *vertices;
+  facetT *facet, **facetp;
+  vertexT *vertex, **vertexp;
+
+  qh vertex_visit++;
+  if (facetlist == qh facet_list && allfacets && !facets) {
+    vertices= qh_settemp(qh num_vertices);
+    FORALLvertices {
+      vertex->visitid= qh vertex_visit;
+      qh_setappend(&vertices, vertex);
+    }
+  }else {
+    vertices= qh_settemp(qh TEMPsize);
+    FORALLfacet_(facetlist) {
+      if (!allfacets && qh_skipfacet(facet))
+        continue;
+      FOREACHvertex_(facet->vertices) {
+        if (vertex->visitid != qh vertex_visit) {
+          vertex->visitid= qh vertex_visit;
+          qh_setappend(&vertices, vertex);
+        }
+      }
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (!allfacets && qh_skipfacet(facet))
+      continue;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        vertex->visitid= qh vertex_visit;
+        qh_setappend(&vertices, vertex);
+      }
+    }
+  }
+  return vertices;
+} /* facetvertices */
+
+/*-<a                             href="qh-geom.htm#TOC"
+  >-------------------------------</a><a name="geomplanes">-</a>
+
+  qh_geomplanes( facet, outerplane, innerplane )
+    return outer and inner planes for Geomview
+    qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
+
+  notes:
+    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+*/
+void qh_geomplanes(facetT *facet, realT *outerplane, realT *innerplane) {
+  realT radius;
+
+  if (qh MERGING || qh JOGGLEmax < REALmax/2) {
+    qh_outerinner(facet, outerplane, innerplane);
+    radius= qh PRINTradius;
+    if (qh JOGGLEmax < REALmax/2)
+      radius -= qh JOGGLEmax * sqrt((realT)qh hull_dim);  /* already accounted for in qh_outerinner() */
+    *outerplane += radius;
+    *innerplane -= radius;
+    if (qh PRINTcoplanar || qh PRINTspheres) {
+      *outerplane += qh MAXabs_coord * qh_GEOMepsilon;
+      *innerplane -= qh MAXabs_coord * qh_GEOMepsilon;
+    }
+  }else
+    *innerplane= *outerplane= 0;
+} /* geomplanes */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="markkeep">-</a>
+
+  qh_markkeep( facetlist )
+    mark good facets that meet qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
+    ignores visible facets (!part of convex hull)
+
+  returns:
+    may clear facet->good
+    recomputes qh.num_good
+
+  design:
+    get set of good facets
+    if qh.KEEParea
+      sort facets by area
+      clear facet->good for all but n largest facets
+    if qh.KEEPmerge
+      sort facets by merge count
+      clear facet->good for all but n most merged facets
+    if qh.KEEPminarea
+      clear facet->good if area too small
+    update qh.num_good
+*/
+void qh_markkeep(facetT *facetlist) {
+  facetT *facet, **facetp;
+  setT *facets= qh_settemp(qh num_facets);
+  int size, count;
+
+  trace2((qh ferr, 2006, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
+          qh KEEParea, qh KEEPmerge, qh KEEPminArea));
+  FORALLfacet_(facetlist) {
+    if (!facet->visible && facet->good)
+      qh_setappend(&facets, facet);
+  }
+  size= qh_setsize(facets);
+  if (qh KEEParea) {
+    qsort(SETaddr_(facets, facetT), (size_t)size,
+             sizeof(facetT *), qh_compare_facetarea);
+    if ((count= size - qh KEEParea) > 0) {
+      FOREACHfacet_(facets) {
+        facet->good= False;
+        if (--count == 0)
+          break;
+      }
+    }
+  }
+  if (qh KEEPmerge) {
+    qsort(SETaddr_(facets, facetT), (size_t)size,
+             sizeof(facetT *), qh_compare_facetmerge);
+    if ((count= size - qh KEEPmerge) > 0) {
+      FOREACHfacet_(facets) {
+        facet->good= False;
+        if (--count == 0)
+          break;
+      }
+    }
+  }
+  if (qh KEEPminArea < REALmax/2) {
+    FOREACHfacet_(facets) {
+      if (!facet->isarea || facet->f.area < qh KEEPminArea)
+        facet->good= False;
+    }
+  }
+  qh_settempfree(&facets);
+  count= 0;
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      count++;
+  }
+  qh num_good= count;
+} /* markkeep */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="markvoronoi">-</a>
+
+  qh_markvoronoi( facetlist, facets, printall, isLower, numcenters )
+    mark voronoi vertices for printing by site pairs
+
+  returns:
+    temporary set of vertices indexed by pointid
+    isLower set if printing lower hull (i.e., at least one facet is lower hull)
+    numcenters= total number of Voronoi vertices
+    bumps qh.printoutnum for vertex-at-infinity
+    clears all facet->seen and sets facet->seen2
+
+    if selected
+      facet->visitid= Voronoi vertex id
+    else if upper hull (or 'Qu' and lower hull)
+      facet->visitid= 0
+    else
+      facet->visitid >= qh num_facets
+
+  notes:
+    ignores qh.ATinfinity, if defined
+*/
+setT *qh_markvoronoi(facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp) {
+  int numcenters=0;
+  facetT *facet, **facetp;
+  setT *vertices;
+  boolT isLower= False;
+
+  qh printoutnum++;
+  qh_clearcenters(qh_ASvoronoi);  /* in case, qh_printvdiagram2 called by user */
+  qh_vertexneighbors();
+  vertices= qh_pointvertex();
+  if (qh ATinfinity)
+    SETelem_(vertices, qh num_points-1)= NULL;
+  qh visit_id++;
+  maximize_(qh visit_id, (unsigned) qh num_facets);
+  FORALLfacet_(facetlist) {
+    if (printall || !qh_skipfacet(facet)) {
+      if (!facet->upperdelaunay) {
+        isLower= True;
+        break;
+      }
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (printall || !qh_skipfacet(facet)) {
+      if (!facet->upperdelaunay) {
+        isLower= True;
+        break;
+      }
+    }
+  }
+  FORALLfacets {
+    if (facet->normal && (facet->upperdelaunay == isLower))
+      facet->visitid= 0;  /* facetlist or facets may overwrite */
+    else
+      facet->visitid= qh visit_id;
+    facet->seen= False;
+    facet->seen2= True;
+  }
+  numcenters++;  /* qh_INFINITE */
+  FORALLfacet_(facetlist) {
+    if (printall || !qh_skipfacet(facet))
+      facet->visitid= numcenters++;
+  }
+  FOREACHfacet_(facets) {
+    if (printall || !qh_skipfacet(facet))
+      facet->visitid= numcenters++;
+  }
+  *isLowerp= isLower;
+  *numcentersp= numcenters;
+  trace2((qh ferr, 2007, "qh_markvoronoi: isLower %d numcenters %d\n", isLower, numcenters));
+  return vertices;
+} /* markvoronoi */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="order_vertexneighbors">-</a>
+
+  qh_order_vertexneighbors( vertex )
+    order facet neighbors of a 2-d or 3-d vertex by adjacency
+
+  notes:
+    does not orient the neighbors
+
+  design:
+    initialize a new neighbor set with the first facet in vertex->neighbors
+    while vertex->neighbors non-empty
+      select next neighbor in the previous facet's neighbor set
+    set vertex->neighbors to the new neighbor set
+*/
+void qh_order_vertexneighbors(vertexT *vertex) {
+  setT *newset;
+  facetT *facet, *neighbor, **neighborp;
+
+  trace4((qh ferr, 4018, "qh_order_vertexneighbors: order neighbors of v%d for 3-d\n", vertex->id));
+  newset= qh_settemp(qh_setsize(vertex->neighbors));
+  facet= (facetT*)qh_setdellast(vertex->neighbors);
+  qh_setappend(&newset, facet);
+  while (qh_setsize(vertex->neighbors)) {
+    FOREACHneighbor_(vertex) {
+      if (qh_setin(facet->neighbors, neighbor)) {
+        qh_setdel(vertex->neighbors, neighbor);
+        qh_setappend(&newset, neighbor);
+        facet= neighbor;
+        break;
+      }
+    }
+    if (!neighbor) {
+      qh_fprintf(qh ferr, 6066, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
+        vertex->id, facet->id);
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+  }
+  qh_setfree(&vertex->neighbors);
+  qh_settemppop();
+  vertex->neighbors= newset;
+} /* order_vertexneighbors */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="prepare_output">-</a>
+
+  qh_prepare_output( )
+    prepare for qh_produce_output2() according to
+      qh.KEEPminArea, KEEParea, KEEPmerge, GOODvertex, GOODthreshold, GOODpoint, ONLYgood, SPLITthresholds
+    does not reset facet->good
+
+  notes
+    except for PRINTstatistics, no-op if previously called with same options
+*/
+void qh_prepare_output(void) {
+  if (qh VORONOI) {
+    qh_clearcenters (qh_ASvoronoi);
+    qh_vertexneighbors();
+  }
+  if (qh TRIangulate && !qh hasTriangulation) {
+    qh_triangulate();
+    if (qh VERIFYoutput && !qh CHECKfrequently)
+      qh_checkpolygon (qh facet_list);
+  }
+  qh_findgood_all (qh facet_list);
+  if (qh GETarea)
+    qh_getarea(qh facet_list);
+  if (qh KEEParea || qh KEEPmerge || qh KEEPminArea < REALmax/2)
+    qh_markkeep (qh facet_list);
+  if (qh PRINTstatistics)
+    qh_collectstatistics();
+}
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printafacet">-</a>
+
+  qh_printafacet( fp, format, facet, printall )
+    print facet to fp in given output format (see qh.PRINTout)
+
+  returns:
+    nop if !printall and qh_skipfacet()
+    nop if visible facet and NEWfacets and format != PRINTfacets
+    must match qh_countfacets
+
+  notes
+    preserves qh.visit_id
+    facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
+
+  see
+    qh_printbegin() and qh_printend()
+
+  design:
+    test for printing facet
+    call appropriate routine for format
+    or output results directly
+*/
+void qh_printafacet(FILE *fp, qh_PRINT format, facetT *facet, boolT printall) {
+  realT color[4], offset, dist, outerplane, innerplane;
+  boolT zerodiv;
+  coordT *point, *normp, *coordp, **pointp, *feasiblep;
+  int k;
+  vertexT *vertex, **vertexp;
+  facetT *neighbor, **neighborp;
+
+  if (!printall && qh_skipfacet(facet))
+    return;
+  if (facet->visible && qh NEWfacets && format != qh_PRINTfacets)
+    return;
+  qh printoutnum++;
+  switch (format) {
+  case qh_PRINTarea:
+    if (facet->isarea) {
+      qh_fprintf(fp, 9009, qh_REAL_1, facet->f.area);
+      qh_fprintf(fp, 9010, "\n");
+    }else
+      qh_fprintf(fp, 9011, "0\n");
+    break;
+  case qh_PRINTcoplanars:
+    qh_fprintf(fp, 9012, "%d", qh_setsize(facet->coplanarset));
+    FOREACHpoint_(facet->coplanarset)
+      qh_fprintf(fp, 9013, " %d", qh_pointid(point));
+    qh_fprintf(fp, 9014, "\n");
+    break;
+  case qh_PRINTcentrums:
+    qh_printcenter(fp, format, NULL, facet);
+    break;
+  case qh_PRINTfacets:
+    qh_printfacet(fp, facet);
+    break;
+  case qh_PRINTfacets_xridge:
+    qh_printfacetheader(fp, facet);
+    break;
+  case qh_PRINTgeom:  /* either 2 , 3, or 4-d by qh_printbegin */
+    if (!facet->normal)
+      break;
+    for (k=qh hull_dim; k--; ) {
+      color[k]= (facet->normal[k]+1.0)/2.0;
+      maximize_(color[k], -1.0);
+      minimize_(color[k], +1.0);
+    }
+    qh_projectdim3 (color, color);
+    if (qh PRINTdim != qh hull_dim)
+      qh_normalize2 (color, 3, True, NULL, NULL);
+    if (qh hull_dim <= 2)
+      qh_printfacet2geom(fp, facet, color);
+    else if (qh hull_dim == 3) {
+      if (facet->simplicial)
+        qh_printfacet3geom_simplicial(fp, facet, color);
+      else
+        qh_printfacet3geom_nonsimplicial(fp, facet, color);
+    }else {
+      if (facet->simplicial)
+        qh_printfacet4geom_simplicial(fp, facet, color);
+      else
+        qh_printfacet4geom_nonsimplicial(fp, facet, color);
+    }
+    break;
+  case qh_PRINTids:
+    qh_fprintf(fp, 9015, "%d\n", facet->id);
+    break;
+  case qh_PRINTincidences:
+  case qh_PRINToff:
+  case qh_PRINTtriangles:
+    if (qh hull_dim == 3 && format != qh_PRINTtriangles)
+      qh_printfacet3vertex(fp, facet, format);
+    else if (facet->simplicial || qh hull_dim == 2 || format == qh_PRINToff)
+      qh_printfacetNvertex_simplicial(fp, facet, format);
+    else
+      qh_printfacetNvertex_nonsimplicial(fp, facet, qh printoutvar++, format);
+    break;
+  case qh_PRINTinner:
+    qh_outerinner(facet, NULL, &innerplane);
+    offset= facet->offset - innerplane;
+    goto LABELprintnorm;
+    break; /* prevent warning */
+  case qh_PRINTmerges:
+    qh_fprintf(fp, 9016, "%d\n", facet->nummerge);
+    break;
+  case qh_PRINTnormals:
+    offset= facet->offset;
+    goto LABELprintnorm;
+    break; /* prevent warning */
+  case qh_PRINTouter:
+    qh_outerinner(facet, &outerplane, NULL);
+    offset= facet->offset - outerplane;
+  LABELprintnorm:
+    if (!facet->normal) {
+      qh_fprintf(fp, 9017, "no normal for facet f%d\n", facet->id);
+      break;
+    }
+    if (qh CDDoutput) {
+      qh_fprintf(fp, 9018, qh_REAL_1, -offset);
+      for (k=0; k < qh hull_dim; k++)
+        qh_fprintf(fp, 9019, qh_REAL_1, -facet->normal[k]);
+    }else {
+      for (k=0; k < qh hull_dim; k++)
+        qh_fprintf(fp, 9020, qh_REAL_1, facet->normal[k]);
+      qh_fprintf(fp, 9021, qh_REAL_1, offset);
+    }
+    qh_fprintf(fp, 9022, "\n");
+    break;
+  case qh_PRINTmathematica:  /* either 2 or 3-d by qh_printbegin */
+  case qh_PRINTmaple:
+    if (qh hull_dim == 2)
+      qh_printfacet2math(fp, facet, format, qh printoutvar++);
+    else
+      qh_printfacet3math(fp, facet, format, qh printoutvar++);
+    break;
+  case qh_PRINTneighbors:
+    qh_fprintf(fp, 9023, "%d", qh_setsize(facet->neighbors));
+    FOREACHneighbor_(facet)
+      qh_fprintf(fp, 9024, " %d",
+               neighbor->visitid ? neighbor->visitid - 1: 0 - neighbor->id);
+    qh_fprintf(fp, 9025, "\n");
+    break;
+  case qh_PRINTpointintersect:
+    if (!qh feasible_point) {
+      qh_fprintf(qh ferr, 6067, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n");
+      qh_errexit( qh_ERRinput, NULL, NULL);
+    }
+    if (facet->offset > 0)
+      goto LABELprintinfinite;
+    point= coordp= (coordT*)qh_memalloc(qh normal_size);
+    normp= facet->normal;
+    feasiblep= qh feasible_point;
+    if (facet->offset < -qh MINdenom) {
+      for (k=qh hull_dim; k--; )
+        *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
+    }else {
+      for (k=qh hull_dim; k--; ) {
+        *(coordp++)= qh_divzero(*(normp++), facet->offset, qh MINdenom_1,
+                                 &zerodiv) + *(feasiblep++);
+        if (zerodiv) {
+          qh_memfree(point, qh normal_size);
+          goto LABELprintinfinite;
+        }
+      }
+    }
+    qh_printpoint(fp, NULL, point);
+    qh_memfree(point, qh normal_size);
+    break;
+  LABELprintinfinite:
+    for (k=qh hull_dim; k--; )
+      qh_fprintf(fp, 9026, qh_REAL_1, qh_INFINITE);
+    qh_fprintf(fp, 9027, "\n");
+    break;
+  case qh_PRINTpointnearest:
+    FOREACHpoint_(facet->coplanarset) {
+      int id, id2;
+      vertex= qh_nearvertex(facet, point, &dist);
+      id= qh_pointid(vertex->point);
+      id2= qh_pointid(point);
+      qh_fprintf(fp, 9028, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
+    }
+    break;
+  case qh_PRINTpoints:  /* VORONOI only by qh_printbegin */
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9029, "1 ");
+    qh_printcenter(fp, format, NULL, facet);
+    break;
+  case qh_PRINTvertices:
+    qh_fprintf(fp, 9030, "%d", qh_setsize(facet->vertices));
+    FOREACHvertex_(facet->vertices)
+      qh_fprintf(fp, 9031, " %d", qh_pointid(vertex->point));
+    qh_fprintf(fp, 9032, "\n");
+    break;
+  default:
+    break;
+  }
+} /* printafacet */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printbegin">-</a>
+
+  qh_printbegin(  )
+    prints header for all output formats
+
+  returns:
+    checks for valid format
+
+  notes:
+    uses qh.visit_id for 3/4off
+    changes qh.interior_point if printing centrums
+    qh_countfacets clears facet->visitid for non-good facets
+
+  see
+    qh_printend() and qh_printafacet()
+
+  design:
+    count facets and related statistics
+    print header for format
+*/
+void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+  int i, num;
+  facetT *facet, **facetp;
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+  pointT *point, **pointp, *pointtemp;
+
+  qh printoutnum= 0;
+  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+  switch (format) {
+  case qh_PRINTnone:
+    break;
+  case qh_PRINTarea:
+    qh_fprintf(fp, 9033, "%d\n", numfacets);
+    break;
+  case qh_PRINTcoplanars:
+    qh_fprintf(fp, 9034, "%d\n", numfacets);
+    break;
+  case qh_PRINTcentrums:
+    if (qh CENTERtype == qh_ASnone)
+      qh_clearcenters(qh_AScentrum);
+    qh_fprintf(fp, 9035, "%d\n%d\n", qh hull_dim, numfacets);
+    break;
+  case qh_PRINTfacets:
+  case qh_PRINTfacets_xridge:
+    if (facetlist)
+      qh_printvertexlist(fp, "Vertices and facets:\n", facetlist, facets, printall);
+    break;
+  case qh_PRINTgeom:
+    if (qh hull_dim > 4)  /* qh_initqhull_globals also checks */
+      goto LABELnoformat;
+    if (qh VORONOI && qh hull_dim > 3)  /* PRINTdim == DROPdim == hull_dim-1 */
+      goto LABELnoformat;
+    if (qh hull_dim == 2 && (qh PRINTridges || qh DOintersections))
+      qh_fprintf(qh ferr, 7049, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
+    if (qh hull_dim == 4 && (qh PRINTinner || qh PRINTouter ||
+                             (qh PRINTdim == 4 && qh PRINTcentrums)))
+      qh_fprintf(qh ferr, 7050, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
+    if (qh PRINTdim == 4 && (qh PRINTspheres))
+      qh_fprintf(qh ferr, 7051, "qhull warning: output for vertices not implemented in 4-d\n");
+    if (qh PRINTdim == 4 && qh DOintersections && qh PRINTnoplanes)
+      qh_fprintf(qh ferr, 7052, "qhull warning: 'Gnh' generates no output in 4-d\n");
+    if (qh PRINTdim == 2) {
+      qh_fprintf(fp, 9036, "{appearance {linewidth 3} LIST # %s | %s\n",
+              qh rbox_command, qh qhull_command);
+    }else if (qh PRINTdim == 3) {
+      qh_fprintf(fp, 9037, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
+              qh rbox_command, qh qhull_command);
+    }else if (qh PRINTdim == 4) {
+      qh visit_id++;
+      num= 0;
+      FORALLfacet_(facetlist)    /* get number of ridges to be printed */
+        qh_printend4geom(NULL, facet, &num, printall);
+      FOREACHfacet_(facets)
+        qh_printend4geom(NULL, facet, &num, printall);
+      qh ridgeoutnum= num;
+      qh printoutvar= 0;  /* counts number of ridges in output */
+      qh_fprintf(fp, 9038, "LIST # %s | %s\n", qh rbox_command, qh qhull_command);
+    }
+
+    if (qh PRINTdots) {
+      qh printoutnum++;
+      num= qh num_points + qh_setsize(qh other_points);
+      if (qh DELAUNAY && qh ATinfinity)
+        num--;
+      if (qh PRINTdim == 4)
+        qh_fprintf(fp, 9039, "4VECT %d %d 1\n", num, num);
+      else
+        qh_fprintf(fp, 9040, "VECT %d %d 1\n", num, num);
+
+      for (i=num; i--; ) {
+        if (i % 20 == 0)
+          qh_fprintf(fp, 9041, "\n");
+        qh_fprintf(fp, 9042, "1 ");
+      }
+      qh_fprintf(fp, 9043, "# 1 point per line\n1 ");
+      for (i=num-1; i--; ) { /* num at least 3 for D2 */
+        if (i % 20 == 0)
+          qh_fprintf(fp, 9044, "\n");
+        qh_fprintf(fp, 9045, "0 ");
+      }
+      qh_fprintf(fp, 9046, "# 1 color for all\n");
+      FORALLpoints {
+        if (!qh DELAUNAY || !qh ATinfinity || qh_pointid(point) != qh num_points-1) {
+          if (qh PRINTdim == 4)
+            qh_printpoint(fp, NULL, point);
+            else
+              qh_printpoint3 (fp, point);
+        }
+      }
+      FOREACHpoint_(qh other_points) {
+        if (qh PRINTdim == 4)
+          qh_printpoint(fp, NULL, point);
+        else
+          qh_printpoint3 (fp, point);
+      }
+      qh_fprintf(fp, 9047, "0 1 1 1  # color of points\n");
+    }
+
+    if (qh PRINTdim == 4  && !qh PRINTnoplanes)
+      /* 4dview loads up multiple 4OFF objects slowly */
+      qh_fprintf(fp, 9048, "4OFF %d %d 1\n", 3*qh ridgeoutnum, qh ridgeoutnum);
+    qh PRINTcradius= 2 * qh DISTround;  /* include test DISTround */
+    if (qh PREmerge) {
+      maximize_(qh PRINTcradius, qh premerge_centrum + qh DISTround);
+    }else if (qh POSTmerge)
+      maximize_(qh PRINTcradius, qh postmerge_centrum + qh DISTround);
+    qh PRINTradius= qh PRINTcradius;
+    if (qh PRINTspheres + qh PRINTcoplanar)
+      maximize_(qh PRINTradius, qh MAXabs_coord * qh_MINradius);
+    if (qh premerge_cos < REALmax/2) {
+      maximize_(qh PRINTradius, (1- qh premerge_cos) * qh MAXabs_coord);
+    }else if (!qh PREmerge && qh POSTmerge && qh postmerge_cos < REALmax/2) {
+      maximize_(qh PRINTradius, (1- qh postmerge_cos) * qh MAXabs_coord);
+    }
+    maximize_(qh PRINTradius, qh MINvisible);
+    if (qh JOGGLEmax < REALmax/2)
+      qh PRINTradius += qh JOGGLEmax * sqrt((realT)qh hull_dim);
+    if (qh PRINTdim != 4 &&
+        (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
+      vertices= qh_facetvertices(facetlist, facets, printall);
+      if (qh PRINTspheres && qh PRINTdim <= 3)
+        qh_printspheres(fp, vertices, qh PRINTradius);
+      if (qh PRINTcoplanar || qh PRINTcentrums) {
+        qh firstcentrum= True;
+        if (qh PRINTcoplanar&& !qh PRINTspheres) {
+          FOREACHvertex_(vertices)
+            qh_printpointvect2 (fp, vertex->point, NULL, qh interior_point, qh PRINTradius);
+        }
+        FORALLfacet_(facetlist) {
+          if (!printall && qh_skipfacet(facet))
+            continue;
+          if (!facet->normal)
+            continue;
+          if (qh PRINTcentrums && qh PRINTdim <= 3)
+            qh_printcentrum(fp, facet, qh PRINTcradius);
+          if (!qh PRINTcoplanar)
+            continue;
+          FOREACHpoint_(facet->coplanarset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+          FOREACHpoint_(facet->outsideset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+        }
+        FOREACHfacet_(facets) {
+          if (!printall && qh_skipfacet(facet))
+            continue;
+          if (!facet->normal)
+            continue;
+          if (qh PRINTcentrums && qh PRINTdim <= 3)
+            qh_printcentrum(fp, facet, qh PRINTcradius);
+          if (!qh PRINTcoplanar)
+            continue;
+          FOREACHpoint_(facet->coplanarset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+          FOREACHpoint_(facet->outsideset)
+            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
+        }
+      }
+      qh_settempfree(&vertices);
+    }
+    qh visit_id++; /* for printing hyperplane intersections */
+    break;
+  case qh_PRINTids:
+    qh_fprintf(fp, 9049, "%d\n", numfacets);
+    break;
+  case qh_PRINTincidences:
+    if (qh VORONOI && qh PRINTprecision)
+      qh_fprintf(qh ferr, 7053, "qhull warning: writing Delaunay.  Use 'p' or 'o' for Voronoi centers\n");
+    qh printoutvar= qh vertex_id;  /* centrum id for non-simplicial facets */
+    if (qh hull_dim <= 3)
+      qh_fprintf(fp, 9050, "%d\n", numfacets);
+    else
+      qh_fprintf(fp, 9051, "%d\n", numsimplicial+numridges);
+    break;
+  case qh_PRINTinner:
+  case qh_PRINTnormals:
+  case qh_PRINTouter:
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9052, "%s | %s\nbegin\n    %d %d real\n", qh rbox_command,
+            qh qhull_command, numfacets, qh hull_dim+1);
+    else
+      qh_fprintf(fp, 9053, "%d\n%d\n", qh hull_dim+1, numfacets);
+    break;
+  case qh_PRINTmathematica:
+  case qh_PRINTmaple:
+    if (qh hull_dim > 3)  /* qh_initbuffers also checks */
+      goto LABELnoformat;
+    if (qh VORONOI)
+      qh_fprintf(qh ferr, 7054, "qhull warning: output is the Delaunay triangulation\n");
+    if (format == qh_PRINTmaple) {
+      if (qh hull_dim == 2)
+        qh_fprintf(fp, 9054, "PLOT(CURVES(\n");
+      else
+        qh_fprintf(fp, 9055, "PLOT3D(POLYGONS(\n");
+    }else
+      qh_fprintf(fp, 9056, "{\n");
+    qh printoutvar= 0;   /* counts number of facets for notfirst */
+    break;
+  case qh_PRINTmerges:
+    qh_fprintf(fp, 9057, "%d\n", numfacets);
+    break;
+  case qh_PRINTpointintersect:
+    qh_fprintf(fp, 9058, "%d\n%d\n", qh hull_dim, numfacets);
+    break;
+  case qh_PRINTneighbors:
+    qh_fprintf(fp, 9059, "%d\n", numfacets);
+    break;
+  case qh_PRINToff:
+  case qh_PRINTtriangles:
+    if (qh VORONOI)
+      goto LABELnoformat;
+    num = qh hull_dim;
+    if (format == qh_PRINToff || qh hull_dim == 2)
+      qh_fprintf(fp, 9060, "%d\n%d %d %d\n", num,
+        qh num_points+qh_setsize(qh other_points), numfacets, totneighbors/2);
+    else { /* qh_PRINTtriangles */
+      qh printoutvar= qh num_points+qh_setsize(qh other_points); /* first centrum */
+      if (qh DELAUNAY)
+        num--;  /* drop last dimension */
+      qh_fprintf(fp, 9061, "%d\n%d %d %d\n", num, qh printoutvar
+        + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
+    }
+    FORALLpoints
+      qh_printpointid(qh fout, NULL, num, point, -1);
+    FOREACHpoint_(qh other_points)
+      qh_printpointid(qh fout, NULL, num, point, -1);
+    if (format == qh_PRINTtriangles && qh hull_dim > 2) {
+      FORALLfacets {
+        if (!facet->simplicial && facet->visitid)
+          qh_printcenter(qh fout, format, NULL, facet);
+      }
+    }
+    break;
+  case qh_PRINTpointnearest:
+    qh_fprintf(fp, 9062, "%d\n", numcoplanars);
+    break;
+  case qh_PRINTpoints:
+    if (!qh VORONOI)
+      goto LABELnoformat;
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9063, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
+           qh qhull_command, numfacets, qh hull_dim);
+    else
+      qh_fprintf(fp, 9064, "%d\n%d\n", qh hull_dim-1, numfacets);
+    break;
+  case qh_PRINTvertices:
+    qh_fprintf(fp, 9065, "%d\n", numfacets);
+    break;
+  case qh_PRINTsummary:
+  default:
+  LABELnoformat:
+    qh_fprintf(qh ferr, 6068, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
+         qh hull_dim);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+} /* printbegin */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printcenter">-</a>
+
+  qh_printcenter( fp, string, facet )
+    print facet->center as centrum or Voronoi center
+    string may be NULL.  Don't include '%' codes.
+    nop if qh CENTERtype neither CENTERvoronoi nor CENTERcentrum
+    if upper envelope of Delaunay triangulation and point at-infinity
+      prints qh_INFINITE instead;
+
+  notes:
+    defines facet->center if needed
+    if format=PRINTgeom, adds a 0 if would otherwise be 2-d
+    Same as QhullFacet::printCenter
+*/
+void qh_printcenter(FILE *fp, qh_PRINT format, const char *string, facetT *facet) {
+  int k, num;
+
+  if (qh CENTERtype != qh_ASvoronoi && qh CENTERtype != qh_AScentrum)
+    return;
+  if (string)
+    qh_fprintf(fp, 9066, string);
+  if (qh CENTERtype == qh_ASvoronoi) {
+    num= qh hull_dim-1;
+    if (!facet->normal || !facet->upperdelaunay || !qh ATinfinity) {
+      if (!facet->center)
+        facet->center= qh_facetcenter(facet->vertices);
+      for (k=0; k < num; k++)
+        qh_fprintf(fp, 9067, qh_REAL_1, facet->center[k]);
+    }else {
+      for (k=0; k < num; k++)
+        qh_fprintf(fp, 9068, qh_REAL_1, qh_INFINITE);
+    }
+  }else /* qh CENTERtype == qh_AScentrum */ {
+    num= qh hull_dim;
+    if (format == qh_PRINTtriangles && qh DELAUNAY)
+      num--;
+    if (!facet->center)
+      facet->center= qh_getcentrum(facet);
+    for (k=0; k < num; k++)
+      qh_fprintf(fp, 9069, qh_REAL_1, facet->center[k]);
+  }
+  if (format == qh_PRINTgeom && num == 2)
+    qh_fprintf(fp, 9070, " 0\n");
+  else
+    qh_fprintf(fp, 9071, "\n");
+} /* printcenter */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printcentrum">-</a>
+
+  qh_printcentrum( fp, facet, radius )
+    print centrum for a facet in OOGL format
+    radius defines size of centrum
+    2-d or 3-d only
+
+  returns:
+    defines facet->center if needed
+*/
+void qh_printcentrum(FILE *fp, facetT *facet, realT radius) {
+  pointT *centrum, *projpt;
+  boolT tempcentrum= False;
+  realT xaxis[4], yaxis[4], normal[4], dist;
+  realT green[3]={0, 1, 0};
+  vertexT *apex;
+  int k;
+
+  if (qh CENTERtype == qh_AScentrum) {
+    if (!facet->center)
+      facet->center= qh_getcentrum(facet);
+    centrum= facet->center;
+  }else {
+    centrum= qh_getcentrum(facet);
+    tempcentrum= True;
+  }
+  qh_fprintf(fp, 9072, "{appearance {-normal -edge normscale 0} ");
+  if (qh firstcentrum) {
+    qh firstcentrum= False;
+    qh_fprintf(fp, 9073, "{INST geom { define centrum CQUAD  # f%d\n\
+-0.3 -0.3 0.0001     0 0 1 1\n\
+ 0.3 -0.3 0.0001     0 0 1 1\n\
+ 0.3  0.3 0.0001     0 0 1 1\n\
+-0.3  0.3 0.0001     0 0 1 1 } transform { \n", facet->id);
+  }else
+    qh_fprintf(fp, 9074, "{INST geom { : centrum } transform { # f%d\n", facet->id);
+  apex= SETfirstt_(facet->vertices, vertexT);
+  qh_distplane(apex->point, facet, &dist);
+  projpt= qh_projectpoint(apex->point, facet, dist);
+  for (k=qh hull_dim; k--; ) {
+    xaxis[k]= projpt[k] - centrum[k];
+    normal[k]= facet->normal[k];
+  }
+  if (qh hull_dim == 2) {
+    xaxis[2]= 0;
+    normal[2]= 0;
+  }else if (qh hull_dim == 4) {
+    qh_projectdim3 (xaxis, xaxis);
+    qh_projectdim3 (normal, normal);
+    qh_normalize2 (normal, qh PRINTdim, True, NULL, NULL);
+  }
+  qh_crossproduct(3, xaxis, normal, yaxis);
+  qh_fprintf(fp, 9075, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
+  qh_fprintf(fp, 9076, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
+  qh_fprintf(fp, 9077, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
+  qh_printpoint3 (fp, centrum);
+  qh_fprintf(fp, 9078, "1 }}}\n");
+  qh_memfree(projpt, qh normal_size);
+  qh_printpointvect(fp, centrum, facet->normal, NULL, radius, green);
+  if (tempcentrum)
+    qh_memfree(centrum, qh normal_size);
+} /* printcentrum */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printend">-</a>
+
+  qh_printend( fp, format )
+    prints trailer for all output formats
+
+  see:
+    qh_printbegin() and qh_printafacet()
+
+*/
+void qh_printend(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int num;
+  facetT *facet, **facetp;
+
+  if (!qh printoutnum)
+    qh_fprintf(qh ferr, 7055, "qhull warning: no facets printed\n");
+  switch (format) {
+  case qh_PRINTgeom:
+    if (qh hull_dim == 4 && qh DROPdim < 0  && !qh PRINTnoplanes) {
+      qh visit_id++;
+      num= 0;
+      FORALLfacet_(facetlist)
+        qh_printend4geom(fp, facet,&num, printall);
+      FOREACHfacet_(facets)
+        qh_printend4geom(fp, facet, &num, printall);
+      if (num != qh ridgeoutnum || qh printoutvar != qh ridgeoutnum) {
+        qh_fprintf(qh ferr, 6069, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh ridgeoutnum, qh printoutvar, num);
+        qh_errexit(qh_ERRqhull, NULL, NULL);
+      }
+    }else
+      qh_fprintf(fp, 9079, "}\n");
+    break;
+  case qh_PRINTinner:
+  case qh_PRINTnormals:
+  case qh_PRINTouter:
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9080, "end\n");
+    break;
+  case qh_PRINTmaple:
+    qh_fprintf(fp, 9081, "));\n");
+    break;
+  case qh_PRINTmathematica:
+    qh_fprintf(fp, 9082, "}\n");
+    break;
+  case qh_PRINTpoints:
+    if (qh CDDoutput)
+      qh_fprintf(fp, 9083, "end\n");
+    break;
+  default:
+    break;
+  }
+} /* printend */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printend4geom">-</a>
+
+  qh_printend4geom( fp, facet, numridges, printall )
+    helper function for qh_printbegin/printend
+
+  returns:
+    number of printed ridges
+
+  notes:
+    just counts printed ridges if fp=NULL
+    uses facet->visitid
+    must agree with qh_printfacet4geom...
+
+  design:
+    computes color for facet from its normal
+    prints each ridge of facet
+*/
+void qh_printend4geom(FILE *fp, facetT *facet, int *nump, boolT printall) {
+  realT color[3] = { 0.0 };
+  int i, num= *nump;
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+
+  if (!printall && qh_skipfacet(facet))
+    return;
+  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+    return;
+  if (!facet->normal)
+    return;
+  if (fp) {
+    for (i=0; i < 3; i++) {
+      color[i]= (facet->normal[i]+1.0)/2.0;
+      maximize_(color[i], -1.0);
+      minimize_(color[i], +1.0);
+    }
+  }
+  facet->visitid= qh visit_id;
+  if (facet->simplicial) {
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+        if (fp)
+          qh_fprintf(fp, 9084, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
+                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+                 facet->id, neighbor->id);
+        num++;
+      }
+    }
+  }else {
+    FOREACHridge_(facet->ridges) {
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->visitid != qh visit_id) {
+        if (fp)
+          qh_fprintf(fp, 9085, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
+                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
+                 ridge->id, facet->id, neighbor->id);
+        num++;
+      }
+    }
+  }
+  *nump= num;
+} /* printend4geom */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printextremes">-</a>
+
+  qh_printextremes( fp, facetlist, facets, printall )
+    print extreme points for convex hulls or halfspace intersections
+
+  notes:
+    #points, followed by ids, one per line
+
+    sorted by id
+    same order as qh_printpoints_out if no coplanar/interior points
+*/
+void qh_printextremes(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices, *points;
+  pointT *point;
+  vertexT *vertex, **vertexp;
+  int id;
+  int numpoints=0, point_i, point_n;
+  int allpoints= qh num_points + qh_setsize(qh other_points);
+
+  points= qh_settemp(allpoints);
+  qh_setzero(points, 0, allpoints);
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  FOREACHvertex_(vertices) {
+    id= qh_pointid(vertex->point);
+    if (id >= 0) {
+      SETelem_(points, id)= vertex->point;
+      numpoints++;
+    }
+  }
+  qh_settempfree(&vertices);
+  qh_fprintf(fp, 9086, "%d\n", numpoints);
+  FOREACHpoint_i_(points) {
+    if (point)
+      qh_fprintf(fp, 9087, "%d\n", point_i);
+  }
+  qh_settempfree(&points);
+} /* printextremes */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printextremes_2d">-</a>
+
+  qh_printextremes_2d( fp, facetlist, facets, printall )
+    prints point ids for facets in qh_ORIENTclock order
+
+  notes:
+    #points, followed by ids, one per line
+    if facetlist/facets are disjoint than the output includes skips
+    errors if facets form a loop
+    does not print coplanar points
+*/
+void qh_printextremes_2d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
+  setT *vertices;
+  facetT *facet, *startfacet, *nextfacet;
+  vertexT *vertexA, *vertexB;
+
+  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh visit_id */
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  qh_fprintf(fp, 9088, "%d\n", qh_setsize(vertices));
+  qh_settempfree(&vertices);
+  if (!numfacets)
+    return;
+  facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
+  qh vertex_visit++;
+  qh visit_id++;
+  do {
+    if (facet->toporient ^ qh_ORIENTclock) {
+      vertexA= SETfirstt_(facet->vertices, vertexT);
+      vertexB= SETsecondt_(facet->vertices, vertexT);
+      nextfacet= SETfirstt_(facet->neighbors, facetT);
+    }else {
+      vertexA= SETsecondt_(facet->vertices, vertexT);
+      vertexB= SETfirstt_(facet->vertices, vertexT);
+      nextfacet= SETsecondt_(facet->neighbors, facetT);
+    }
+    if (facet->visitid == qh visit_id) {
+      qh_fprintf(qh ferr, 6218, "Qhull internal error (qh_printextremes_2d): loop in facet list.  facet %d nextfacet %d\n",
+                 facet->id, nextfacet->id);
+      qh_errexit2 (qh_ERRqhull, facet, nextfacet);
+    }
+    if (facet->visitid) {
+      if (vertexA->visitid != qh vertex_visit) {
+        vertexA->visitid= qh vertex_visit;
+        qh_fprintf(fp, 9089, "%d\n", qh_pointid(vertexA->point));
+      }
+      if (vertexB->visitid != qh vertex_visit) {
+        vertexB->visitid= qh vertex_visit;
+        qh_fprintf(fp, 9090, "%d\n", qh_pointid(vertexB->point));
+      }
+    }
+    facet->visitid= qh visit_id;
+    facet= nextfacet;
+  }while (facet && facet != startfacet);
+} /* printextremes_2d */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printextremes_d">-</a>
+
+  qh_printextremes_d( fp, facetlist, facets, printall )
+    print extreme points of input sites for Delaunay triangulations
+
+  notes:
+    #points, followed by ids, one per line
+
+    unordered
+*/
+void qh_printextremes_d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices;
+  vertexT *vertex, **vertexp;
+  boolT upperseen, lowerseen;
+  facetT *neighbor, **neighborp;
+  int numpoints=0;
+
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  qh_vertexneighbors();
+  FOREACHvertex_(vertices) {
+    upperseen= lowerseen= False;
+    FOREACHneighbor_(vertex) {
+      if (neighbor->upperdelaunay)
+        upperseen= True;
+      else
+        lowerseen= True;
+    }
+    if (upperseen && lowerseen) {
+      vertex->seen= True;
+      numpoints++;
+    }else
+      vertex->seen= False;
+  }
+  qh_fprintf(fp, 9091, "%d\n", numpoints);
+  FOREACHvertex_(vertices) {
+    if (vertex->seen)
+      qh_fprintf(fp, 9092, "%d\n", qh_pointid(vertex->point));
+  }
+  qh_settempfree(&vertices);
+} /* printextremes_d */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet">-</a>
+
+  qh_printfacet( fp, facet )
+    prints all fields of a facet to fp
+
+  notes:
+    ridges printed in neighbor order
+*/
+void qh_printfacet(FILE *fp, facetT *facet) {
+
+  qh_printfacetheader(fp, facet);
+  if (facet->ridges)
+    qh_printfacetridges(fp, facet);
+} /* printfacet */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet2geom">-</a>
+
+  qh_printfacet2geom( fp, facet, color )
+    print facet as part of a 2-d VECT for Geomview
+
+    notes:
+      assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+      mindist is calculated within io.c.  maxoutside is calculated elsewhere,
+      so a DISTround error may have occurred.
+*/
+void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) {
+  pointT *point0, *point1;
+  realT mindist, innerplane, outerplane;
+  int k;
+
+  qh_facet2point(facet, &point0, &point1, &mindist);
+  qh_geomplanes(facet, &outerplane, &innerplane);
+  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+    qh_printfacet2geom_points(fp, point0, point1, facet, outerplane, color);
+  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet2geom_points(fp, point0, point1, facet, innerplane, color);
+  }
+  qh_memfree(point1, qh normal_size);
+  qh_memfree(point0, qh normal_size);
+} /* printfacet2geom */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet2geom_points">-</a>
+
+  qh_printfacet2geom_points( fp, point1, point2, facet, offset, color )
+    prints a 2-d facet as a VECT with 2 points at some offset.
+    The points are on the facet's plane.
+*/
+void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
+                               facetT *facet, realT offset, realT color[3]) {
+  pointT *p1= point1, *p2= point2;
+
+  qh_fprintf(fp, 9093, "VECT 1 2 1 2 1 # f%d\n", facet->id);
+  if (offset != 0.0) {
+    p1= qh_projectpoint(p1, facet, -offset);
+    p2= qh_projectpoint(p2, facet, -offset);
+  }
+  qh_fprintf(fp, 9094, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
+           p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
+  if (offset != 0.0) {
+    qh_memfree(p1, qh normal_size);
+    qh_memfree(p2, qh normal_size);
+  }
+  qh_fprintf(fp, 9095, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printfacet2geom_points */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet2math">-</a>
+
+  qh_printfacet2math( fp, facet, format, notfirst )
+    print 2-d Maple or Mathematica output for a facet
+    may be non-simplicial
+
+  notes:
+    use %16.8f since Mathematica 2.2 does not handle exponential format
+    see qh_printfacet3math
+*/
+void qh_printfacet2math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
+  pointT *point0, *point1;
+  realT mindist;
+  const char *pointfmt;
+
+  qh_facet2point(facet, &point0, &point1, &mindist);
+  if (notfirst)
+    qh_fprintf(fp, 9096, ",");
+  if (format == qh_PRINTmaple)
+    pointfmt= "[[%16.8f, %16.8f], [%16.8f, %16.8f]]\n";
+  else
+    pointfmt= "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n";
+  qh_fprintf(fp, 9097, pointfmt, point0[0], point0[1], point1[0], point1[1]);
+  qh_memfree(point1, qh normal_size);
+  qh_memfree(point0, qh normal_size);
+} /* printfacet2math */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3geom_nonsimplicial">-</a>
+
+  qh_printfacet3geom_nonsimplicial( fp, facet, color )
+    print Geomview OFF for a 3-d nonsimplicial facet.
+    if DOintersections, prints ridges to unvisited neighbors(qh visit_id)
+
+  notes
+    uses facet->visitid for intersections and ridges
+*/
+void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
+  ridgeT *ridge, **ridgep;
+  setT *projectedpoints, *vertices;
+  vertexT *vertex, **vertexp, *vertexA, *vertexB;
+  pointT *projpt, *point, **pointp;
+  facetT *neighbor;
+  realT dist, outerplane, innerplane;
+  int cntvertices, k;
+  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+
+  qh_geomplanes(facet, &outerplane, &innerplane);
+  vertices= qh_facet3vertex(facet); /* oriented */
+  cntvertices= qh_setsize(vertices);
+  projectedpoints= qh_settemp(cntvertices);
+  FOREACHvertex_(vertices) {
+    zinc_(Zdistio);
+    qh_distplane(vertex->point, facet, &dist);
+    projpt= qh_projectpoint(vertex->point, facet, dist);
+    qh_setappend(&projectedpoints, projpt);
+  }
+  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+    qh_printfacet3geom_points(fp, projectedpoints, facet, outerplane, color);
+  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet3geom_points(fp, projectedpoints, facet, innerplane, color);
+  }
+  FOREACHpoint_(projectedpoints)
+    qh_memfree(point, qh normal_size);
+  qh_settempfree(&projectedpoints);
+  qh_settempfree(&vertices);
+  if ((qh DOintersections || qh PRINTridges)
+  && (!facet->visible || !qh NEWfacets)) {
+    facet->visitid= qh visit_id;
+    FOREACHridge_(facet->ridges) {
+      neighbor= otherfacet_(ridge, facet);
+      if (neighbor->visitid != qh visit_id) {
+        if (qh DOintersections)
+          qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, black);
+        if (qh PRINTridges) {
+          vertexA= SETfirstt_(ridge->vertices, vertexT);
+          vertexB= SETsecondt_(ridge->vertices, vertexT);
+          qh_printline3geom(fp, vertexA->point, vertexB->point, green);
+        }
+      }
+    }
+  }
+} /* printfacet3geom_nonsimplicial */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3geom_points">-</a>
+
+  qh_printfacet3geom_points( fp, points, facet, offset )
+    prints a 3-d facet as OFF Geomview object.
+    offset is relative to the facet's hyperplane
+    Facet is determined as a list of points
+*/
+void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
+  int k, n= qh_setsize(points), i;
+  pointT *point, **pointp;
+  setT *printpoints;
+
+  qh_fprintf(fp, 9098, "{ OFF %d 1 1 # f%d\n", n, facet->id);
+  if (offset != 0.0) {
+    printpoints= qh_settemp(n);
+    FOREACHpoint_(points)
+      qh_setappend(&printpoints, qh_projectpoint(point, facet, -offset));
+  }else
+    printpoints= points;
+  FOREACHpoint_(printpoints) {
+    for (k=0; k < qh hull_dim; k++) {
+      if (k == qh DROPdim)
+        qh_fprintf(fp, 9099, "0 ");
+      else
+        qh_fprintf(fp, 9100, "%8.4g ", point[k]);
+    }
+    if (printpoints != points)
+      qh_memfree(point, qh normal_size);
+    qh_fprintf(fp, 9101, "\n");
+  }
+  if (printpoints != points)
+    qh_settempfree(&printpoints);
+  qh_fprintf(fp, 9102, "%d ", n);
+  for (i=0; i < n; i++)
+    qh_fprintf(fp, 9103, "%d ", i);
+  qh_fprintf(fp, 9104, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
+} /* printfacet3geom_points */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3geom_simplicial">-</a>
+
+  qh_printfacet3geom_simplicial(  )
+    print Geomview OFF for a 3-d simplicial facet.
+
+  notes:
+    may flip color
+    uses facet->visitid for intersections and ridges
+
+    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
+    innerplane may be off by qh DISTround.  Maxoutside is calculated elsewhere
+    so a DISTround error may have occurred.
+*/
+void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
+  setT *points, *vertices;
+  vertexT *vertex, **vertexp, *vertexA, *vertexB;
+  facetT *neighbor, **neighborp;
+  realT outerplane, innerplane;
+  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
+  int k;
+
+  qh_geomplanes(facet, &outerplane, &innerplane);
+  vertices= qh_facet3vertex(facet);
+  points= qh_settemp(qh TEMPsize);
+  FOREACHvertex_(vertices)
+    qh_setappend(&points, vertex->point);
+  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
+    qh_printfacet3geom_points(fp, points, facet, outerplane, color);
+  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
+              outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
+    for (k=3; k--; )
+      color[k]= 1.0 - color[k];
+    qh_printfacet3geom_points(fp, points, facet, innerplane, color);
+  }
+  qh_settempfree(&points);
+  qh_settempfree(&vertices);
+  if ((qh DOintersections || qh PRINTridges)
+  && (!facet->visible || !qh NEWfacets)) {
+    facet->visitid= qh visit_id;
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid != qh visit_id) {
+        vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
+                          SETindex_(facet->neighbors, neighbor), 0);
+        if (qh DOintersections)
+           qh_printhyperplaneintersection(fp, facet, neighbor, vertices, black);
+        if (qh PRINTridges) {
+          vertexA= SETfirstt_(vertices, vertexT);
+          vertexB= SETsecondt_(vertices, vertexT);
+          qh_printline3geom(fp, vertexA->point, vertexB->point, green);
+        }
+        qh_setfree(&vertices);
+      }
+    }
+  }
+} /* printfacet3geom_simplicial */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3math">-</a>
+
+  qh_printfacet3math( fp, facet, notfirst )
+    print 3-d Maple or Mathematica output for a facet
+
+  notes:
+    may be non-simplicial
+    use %16.8f since Mathematica 2.2 does not handle exponential format
+    see qh_printfacet2math
+*/
+void qh_printfacet3math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
+  vertexT *vertex, **vertexp;
+  setT *points, *vertices;
+  pointT *point, **pointp;
+  boolT firstpoint= True;
+  realT dist;
+  const char *pointfmt, *endfmt;
+
+  if (notfirst)
+    qh_fprintf(fp, 9105, ",\n");
+  vertices= qh_facet3vertex(facet);
+  points= qh_settemp(qh_setsize(vertices));
+  FOREACHvertex_(vertices) {
+    zinc_(Zdistio);
+    qh_distplane(vertex->point, facet, &dist);
+    point= qh_projectpoint(vertex->point, facet, dist);
+    qh_setappend(&points, point);
+  }
+  if (format == qh_PRINTmaple) {
+    qh_fprintf(fp, 9106, "[");
+    pointfmt= "[%16.8f, %16.8f, %16.8f]";
+    endfmt= "]";
+  }else {
+    qh_fprintf(fp, 9107, "Polygon[{");
+    pointfmt= "{%16.8f, %16.8f, %16.8f}";
+    endfmt= "}]";
+  }
+  FOREACHpoint_(points) {
+    if (firstpoint)
+      firstpoint= False;
+    else
+      qh_fprintf(fp, 9108, ",\n");
+    qh_fprintf(fp, 9109, pointfmt, point[0], point[1], point[2]);
+  }
+  FOREACHpoint_(points)
+    qh_memfree(point, qh normal_size);
+  qh_settempfree(&points);
+  qh_settempfree(&vertices);
+  qh_fprintf(fp, 9110, endfmt);
+} /* printfacet3math */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet3vertex">-</a>
+
+  qh_printfacet3vertex( fp, facet, format )
+    print vertices in a 3-d facet as point ids
+
+  notes:
+    prints number of vertices first if format == qh_PRINToff
+    the facet may be non-simplicial
+*/
+void qh_printfacet3vertex(FILE *fp, facetT *facet, qh_PRINT format) {
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+
+  vertices= qh_facet3vertex(facet);
+  if (format == qh_PRINToff)
+    qh_fprintf(fp, 9111, "%d ", qh_setsize(vertices));
+  FOREACHvertex_(vertices)
+    qh_fprintf(fp, 9112, "%d ", qh_pointid(vertex->point));
+  qh_fprintf(fp, 9113, "\n");
+  qh_settempfree(&vertices);
+} /* printfacet3vertex */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet4geom_nonsimplicial">-</a>
+
+  qh_printfacet4geom_nonsimplicial(  )
+    print Geomview 4OFF file for a 4d nonsimplicial facet
+    prints all ridges to unvisited neighbors (qh.visit_id)
+    if qh.DROPdim
+      prints in OFF format
+
+  notes:
+    must agree with printend4geom()
+*/
+void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
+  facetT *neighbor;
+  ridgeT *ridge, **ridgep;
+  vertexT *vertex, **vertexp;
+  pointT *point;
+  int k;
+  realT dist;
+
+  facet->visitid= qh visit_id;
+  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+    return;
+  FOREACHridge_(facet->ridges) {
+    neighbor= otherfacet_(ridge, facet);
+    if (neighbor->visitid == qh visit_id)
+      continue;
+    if (qh PRINTtransparent && !neighbor->good)
+      continue;
+    if (qh DOintersections)
+      qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, color);
+    else {
+      if (qh DROPdim >= 0)
+        qh_fprintf(fp, 9114, "OFF 3 1 1 # f%d\n", facet->id);
+      else {
+        qh printoutvar++;
+        qh_fprintf(fp, 9115, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
+      }
+      FOREACHvertex_(ridge->vertices) {
+        zinc_(Zdistio);
+        qh_distplane(vertex->point,facet, &dist);
+        point=qh_projectpoint(vertex->point,facet, dist);
+        for (k=0; k < qh hull_dim; k++) {
+          if (k != qh DROPdim)
+            qh_fprintf(fp, 9116, "%8.4g ", point[k]);
+        }
+        qh_fprintf(fp, 9117, "\n");
+        qh_memfree(point, qh normal_size);
+      }
+      if (qh DROPdim >= 0)
+        qh_fprintf(fp, 9118, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+    }
+  }
+} /* printfacet4geom_nonsimplicial */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacet4geom_simplicial">-</a>
+
+  qh_printfacet4geom_simplicial( fp, facet, color )
+    print Geomview 4OFF file for a 4d simplicial facet
+    prints triangles for unvisited neighbors (qh.visit_id)
+
+  notes:
+    must agree with printend4geom()
+*/
+void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
+  setT *vertices;
+  facetT *neighbor, **neighborp;
+  vertexT *vertex, **vertexp;
+  int k;
+
+  facet->visitid= qh visit_id;
+  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
+    return;
+  FOREACHneighbor_(facet) {
+    if (neighbor->visitid == qh visit_id)
+      continue;
+    if (qh PRINTtransparent && !neighbor->good)
+      continue;
+    vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
+                          SETindex_(facet->neighbors, neighbor), 0);
+    if (qh DOintersections)
+      qh_printhyperplaneintersection(fp, facet, neighbor, vertices, color);
+    else {
+      if (qh DROPdim >= 0)
+        qh_fprintf(fp, 9119, "OFF 3 1 1 # ridge between f%d f%d\n",
+                facet->id, neighbor->id);
+      else {
+        qh printoutvar++;
+        qh_fprintf(fp, 9120, "# ridge between f%d f%d\n", facet->id, neighbor->id);
+      }
+      FOREACHvertex_(vertices) {
+        for (k=0; k < qh hull_dim; k++) {
+          if (k != qh DROPdim)
+            qh_fprintf(fp, 9121, "%8.4g ", vertex->point[k]);
+        }
+        qh_fprintf(fp, 9122, "\n");
+      }
+      if (qh DROPdim >= 0)
+        qh_fprintf(fp, 9123, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
+    }
+    qh_setfree(&vertices);
+  }
+} /* printfacet4geom_simplicial */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacetNvertex_nonsimplicial">-</a>
+
+  qh_printfacetNvertex_nonsimplicial( fp, facet, id, format )
+    print vertices for an N-d non-simplicial facet
+    triangulates each ridge to the id
+*/
+void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, qh_PRINT format) {
+  vertexT *vertex, **vertexp;
+  ridgeT *ridge, **ridgep;
+
+  if (facet->visible && qh NEWfacets)
+    return;
+  FOREACHridge_(facet->ridges) {
+    if (format == qh_PRINTtriangles)
+      qh_fprintf(fp, 9124, "%d ", qh hull_dim);
+    qh_fprintf(fp, 9125, "%d ", id);
+    if ((ridge->top == facet) ^ qh_ORIENTclock) {
+      FOREACHvertex_(ridge->vertices)
+        qh_fprintf(fp, 9126, "%d ", qh_pointid(vertex->point));
+    }else {
+      FOREACHvertexreverse12_(ridge->vertices)
+        qh_fprintf(fp, 9127, "%d ", qh_pointid(vertex->point));
+    }
+    qh_fprintf(fp, 9128, "\n");
+  }
+} /* printfacetNvertex_nonsimplicial */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacetNvertex_simplicial">-</a>
+
+  qh_printfacetNvertex_simplicial( fp, facet, format )
+    print vertices for an N-d simplicial facet
+    prints vertices for non-simplicial facets
+      2-d facets (orientation preserved by qh_mergefacet2d)
+      PRINToff ('o') for 4-d and higher
+*/
+void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, qh_PRINT format) {
+  vertexT *vertex, **vertexp;
+
+  if (format == qh_PRINToff || format == qh_PRINTtriangles)
+    qh_fprintf(fp, 9129, "%d ", qh_setsize(facet->vertices));
+  if ((facet->toporient ^ qh_ORIENTclock)
+  || (qh hull_dim > 2 && !facet->simplicial)) {
+    FOREACHvertex_(facet->vertices)
+      qh_fprintf(fp, 9130, "%d ", qh_pointid(vertex->point));
+  }else {
+    FOREACHvertexreverse12_(facet->vertices)
+      qh_fprintf(fp, 9131, "%d ", qh_pointid(vertex->point));
+  }
+  qh_fprintf(fp, 9132, "\n");
+} /* printfacetNvertex_simplicial */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacetheader">-</a>
+
+  qh_printfacetheader( fp, facet )
+    prints header fields of a facet to fp
+
+  notes:
+    for 'f' output and debugging
+    Same as QhullFacet::printHeader()
+*/
+void qh_printfacetheader(FILE *fp, facetT *facet) {
+  pointT *point, **pointp, *furthest;
+  facetT *neighbor, **neighborp;
+  realT dist;
+
+  if (facet == qh_MERGEridge) {
+    qh_fprintf(fp, 9133, " MERGEridge\n");
+    return;
+  }else if (facet == qh_DUPLICATEridge) {
+    qh_fprintf(fp, 9134, " DUPLICATEridge\n");
+    return;
+  }else if (!facet) {
+    qh_fprintf(fp, 9135, " NULLfacet\n");
+    return;
+  }
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  qh_fprintf(fp, 9136, "- f%d\n", facet->id);
+  qh_fprintf(fp, 9137, "    - flags:");
+  if (facet->toporient)
+    qh_fprintf(fp, 9138, " top");
+  else
+    qh_fprintf(fp, 9139, " bottom");
+  if (facet->simplicial)
+    qh_fprintf(fp, 9140, " simplicial");
+  if (facet->tricoplanar)
+    qh_fprintf(fp, 9141, " tricoplanar");
+  if (facet->upperdelaunay)
+    qh_fprintf(fp, 9142, " upperDelaunay");
+  if (facet->visible)
+    qh_fprintf(fp, 9143, " visible");
+  if (facet->newfacet)
+    qh_fprintf(fp, 9144, " new");
+  if (facet->tested)
+    qh_fprintf(fp, 9145, " tested");
+  if (!facet->good)
+    qh_fprintf(fp, 9146, " notG");
+  if (facet->seen)
+    qh_fprintf(fp, 9147, " seen");
+  if (facet->coplanar)
+    qh_fprintf(fp, 9148, " coplanar");
+  if (facet->mergehorizon)
+    qh_fprintf(fp, 9149, " mergehorizon");
+  if (facet->keepcentrum)
+    qh_fprintf(fp, 9150, " keepcentrum");
+  if (facet->dupridge)
+    qh_fprintf(fp, 9151, " dupridge");
+  if (facet->mergeridge && !facet->mergeridge2)
+    qh_fprintf(fp, 9152, " mergeridge1");
+  if (facet->mergeridge2)
+    qh_fprintf(fp, 9153, " mergeridge2");
+  if (facet->newmerge)
+    qh_fprintf(fp, 9154, " newmerge");
+  if (facet->flipped)
+    qh_fprintf(fp, 9155, " flipped");
+  if (facet->notfurthest)
+    qh_fprintf(fp, 9156, " notfurthest");
+  if (facet->degenerate)
+    qh_fprintf(fp, 9157, " degenerate");
+  if (facet->redundant)
+    qh_fprintf(fp, 9158, " redundant");
+  qh_fprintf(fp, 9159, "\n");
+  if (facet->isarea)
+    qh_fprintf(fp, 9160, "    - area: %2.2g\n", facet->f.area);
+  else if (qh NEWfacets && facet->visible && facet->f.replace)
+    qh_fprintf(fp, 9161, "    - replacement: f%d\n", facet->f.replace->id);
+  else if (facet->newfacet) {
+    if (facet->f.samecycle && facet->f.samecycle != facet)
+      qh_fprintf(fp, 9162, "    - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
+  }else if (facet->tricoplanar /* !isarea */) {
+    if (facet->f.triowner)
+      qh_fprintf(fp, 9163, "    - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
+  }else if (facet->f.newcycle)
+    qh_fprintf(fp, 9164, "    - was horizon to f%d\n", facet->f.newcycle->id);
+  if (facet->nummerge)
+    qh_fprintf(fp, 9165, "    - merges: %d\n", facet->nummerge);
+  qh_printpointid(fp, "    - normal: ", qh hull_dim, facet->normal, -1);
+  qh_fprintf(fp, 9166, "    - offset: %10.7g\n", facet->offset);
+  if (qh CENTERtype == qh_ASvoronoi || facet->center)
+    qh_printcenter(fp, qh_PRINTfacets, "    - center: ", facet);
+#if qh_MAXoutside
+  if (facet->maxoutside > qh DISTround)
+    qh_fprintf(fp, 9167, "    - maxoutside: %10.7g\n", facet->maxoutside);
+#endif
+  if (!SETempty_(facet->outsideset)) {
+    furthest= (pointT*)qh_setlast(facet->outsideset);
+    if (qh_setsize(facet->outsideset) < 6) {
+      qh_fprintf(fp, 9168, "    - outside set(furthest p%d):\n", qh_pointid(furthest));
+      FOREACHpoint_(facet->outsideset)
+        qh_printpoint(fp, "     ", point);
+    }else if (qh_setsize(facet->outsideset) < 21) {
+      qh_printpoints(fp, "    - outside set:", facet->outsideset);
+    }else {
+      qh_fprintf(fp, 9169, "    - outside set:  %d points.", qh_setsize(facet->outsideset));
+      qh_printpoint(fp, "  Furthest", furthest);
+    }
+#if !qh_COMPUTEfurthest
+    qh_fprintf(fp, 9170, "    - furthest distance= %2.2g\n", facet->furthestdist);
+#endif
+  }
+  if (!SETempty_(facet->coplanarset)) {
+    furthest= (pointT*)qh_setlast(facet->coplanarset);
+    if (qh_setsize(facet->coplanarset) < 6) {
+      qh_fprintf(fp, 9171, "    - coplanar set(furthest p%d):\n", qh_pointid(furthest));
+      FOREACHpoint_(facet->coplanarset)
+        qh_printpoint(fp, "     ", point);
+    }else if (qh_setsize(facet->coplanarset) < 21) {
+      qh_printpoints(fp, "    - coplanar set:", facet->coplanarset);
+    }else {
+      qh_fprintf(fp, 9172, "    - coplanar set:  %d points.", qh_setsize(facet->coplanarset));
+      qh_printpoint(fp, "  Furthest", furthest);
+    }
+    zinc_(Zdistio);
+    qh_distplane(furthest, facet, &dist);
+    qh_fprintf(fp, 9173, "      furthest distance= %2.2g\n", dist);
+  }
+  qh_printvertices(fp, "    - vertices:", facet->vertices);
+  qh_fprintf(fp, 9174, "    - neighboring facets:");
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge)
+      qh_fprintf(fp, 9175, " MERGE");
+    else if (neighbor == qh_DUPLICATEridge)
+      qh_fprintf(fp, 9176, " DUP");
+    else
+      qh_fprintf(fp, 9177, " f%d", neighbor->id);
+  }
+  qh_fprintf(fp, 9178, "\n");
+  qh RANDOMdist= qh old_randomdist;
+} /* printfacetheader */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacetridges">-</a>
+
+  qh_printfacetridges( fp, facet )
+    prints ridges of a facet to fp
+
+  notes:
+    ridges printed in neighbor order
+    assumes the ridges exist
+    for 'f' output
+    same as QhullFacet::printRidges
+*/
+void qh_printfacetridges(FILE *fp, facetT *facet) {
+  facetT *neighbor, **neighborp;
+  ridgeT *ridge, **ridgep;
+  int numridges= 0;
+
+
+  if (facet->visible && qh NEWfacets) {
+    qh_fprintf(fp, 9179, "    - ridges(ids may be garbage):");
+    FOREACHridge_(facet->ridges)
+      qh_fprintf(fp, 9180, " r%d", ridge->id);
+    qh_fprintf(fp, 9181, "\n");
+  }else {
+    qh_fprintf(fp, 9182, "    - ridges:\n");
+    FOREACHridge_(facet->ridges)
+      ridge->seen= False;
+    if (qh hull_dim == 3) {
+      ridge= SETfirstt_(facet->ridges, ridgeT);
+      while (ridge && !ridge->seen) {
+        ridge->seen= True;
+        qh_printridge(fp, ridge);
+        numridges++;
+        ridge= qh_nextridge3d(ridge, facet, NULL);
+        }
+    }else {
+      FOREACHneighbor_(facet) {
+        FOREACHridge_(facet->ridges) {
+          if (otherfacet_(ridge,facet) == neighbor) {
+            ridge->seen= True;
+            qh_printridge(fp, ridge);
+            numridges++;
+          }
+        }
+      }
+    }
+    if (numridges != qh_setsize(facet->ridges)) {
+      qh_fprintf(fp, 9183, "     - all ridges:");
+      FOREACHridge_(facet->ridges)
+        qh_fprintf(fp, 9184, " r%d", ridge->id);
+        qh_fprintf(fp, 9185, "\n");
+    }
+    FOREACHridge_(facet->ridges) {
+      if (!ridge->seen)
+        qh_printridge(fp, ridge);
+    }
+  }
+} /* printfacetridges */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printfacets">-</a>
+
+  qh_printfacets( fp, format, facetlist, facets, printall )
+    prints facetlist and/or facet set in output format
+
+  notes:
+    also used for specialized formats ('FO' and summary)
+    turns off 'Rn' option since want actual numbers
+*/
+void qh_printfacets(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
+  facetT *facet, **facetp;
+  setT *vertices;
+  coordT *center;
+  realT outerplane, innerplane;
+
+  qh old_randomdist= qh RANDOMdist;
+  qh RANDOMdist= False;
+  if (qh CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
+    qh_fprintf(qh ferr, 7056, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
+  if (format == qh_PRINTnone)
+    ; /* print nothing */
+  else if (format == qh_PRINTaverage) {
+    vertices= qh_facetvertices(facetlist, facets, printall);
+    center= qh_getcenter(vertices);
+    qh_fprintf(fp, 9186, "%d 1\n", qh hull_dim);
+    qh_printpointid(fp, NULL, qh hull_dim, center, -1);
+    qh_memfree(center, qh normal_size);
+    qh_settempfree(&vertices);
+  }else if (format == qh_PRINTextremes) {
+    if (qh DELAUNAY)
+      qh_printextremes_d(fp, facetlist, facets, printall);
+    else if (qh hull_dim == 2)
+      qh_printextremes_2d(fp, facetlist, facets, printall);
+    else
+      qh_printextremes(fp, facetlist, facets, printall);
+  }else if (format == qh_PRINToptions)
+    qh_fprintf(fp, 9187, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
+  else if (format == qh_PRINTpoints && !qh VORONOI)
+    qh_printpoints_out(fp, facetlist, facets, printall);
+  else if (format == qh_PRINTqhull)
+    qh_fprintf(fp, 9188, "%s | %s\n", qh rbox_command, qh qhull_command);
+  else if (format == qh_PRINTsize) {
+    qh_fprintf(fp, 9189, "0\n2 ");
+    qh_fprintf(fp, 9190, qh_REAL_1, qh totarea);
+    qh_fprintf(fp, 9191, qh_REAL_1, qh totvol);
+    qh_fprintf(fp, 9192, "\n");
+  }else if (format == qh_PRINTsummary) {
+    qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
+    vertices= qh_facetvertices(facetlist, facets, printall);
+    qh_fprintf(fp, 9193, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh hull_dim,
+                qh num_points + qh_setsize(qh other_points),
+                qh num_vertices, qh num_facets - qh num_visible,
+                qh_setsize(vertices), numfacets, numcoplanars,
+                numfacets - numsimplicial, zzval_(Zdelvertextot),
+                numtricoplanars);
+    qh_settempfree(&vertices);
+    qh_outerinner(NULL, &outerplane, &innerplane);
+    qh_fprintf(fp, 9194, qh_REAL_2n, outerplane, innerplane);
+  }else if (format == qh_PRINTvneighbors)
+    qh_printvneighbors(fp, facetlist, facets, printall);
+  else if (qh VORONOI && format == qh_PRINToff)
+    qh_printvoronoi(fp, format, facetlist, facets, printall);
+  else if (qh VORONOI && format == qh_PRINTgeom) {
+    qh_printbegin(fp, format, facetlist, facets, printall);
+    qh_printvoronoi(fp, format, facetlist, facets, printall);
+    qh_printend(fp, format, facetlist, facets, printall);
+  }else if (qh VORONOI
+  && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
+    qh_printvdiagram(fp, format, facetlist, facets, printall);
+  else {
+    qh_printbegin(fp, format, facetlist, facets, printall);
+    FORALLfacet_(facetlist)
+      qh_printafacet(fp, format, facet, printall);
+    FOREACHfacet_(facets)
+      qh_printafacet(fp, format, facet, printall);
+    qh_printend(fp, format, facetlist, facets, printall);
+  }
+  qh RANDOMdist= qh old_randomdist;
+} /* printfacets */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printhyperplaneintersection">-</a>
+
+  qh_printhyperplaneintersection( fp, facet1, facet2, vertices, color )
+    print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
+*/
+void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
+                   setT *vertices, realT color[3]) {
+  realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
+  vertexT *vertex, **vertexp;
+  int i, k;
+  boolT nearzero1, nearzero2;
+
+  costheta= qh_getangle(facet1->normal, facet2->normal);
+  denominator= 1 - costheta * costheta;
+  i= qh_setsize(vertices);
+  if (qh hull_dim == 3)
+    qh_fprintf(fp, 9195, "VECT 1 %d 1 %d 1 ", i, i);
+  else if (qh hull_dim == 4 && qh DROPdim >= 0)
+    qh_fprintf(fp, 9196, "OFF 3 1 1 ");
+  else
+    qh printoutvar++;
+  qh_fprintf(fp, 9197, "# intersect f%d f%d\n", facet1->id, facet2->id);
+  mindenom= 1 / (10.0 * qh MAXabs_coord);
+  FOREACHvertex_(vertices) {
+    zadd_(Zdistio, 2);
+    qh_distplane(vertex->point, facet1, &dist1);
+    qh_distplane(vertex->point, facet2, &dist2);
+    s= qh_divzero(-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
+    t= qh_divzero(-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
+    if (nearzero1 || nearzero2)
+      s= t= 0.0;
+    for (k=qh hull_dim; k--; )
+      p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
+    if (qh PRINTdim <= 3) {
+      qh_projectdim3 (p, p);
+      qh_fprintf(fp, 9198, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
+    }else
+      qh_fprintf(fp, 9199, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
+    if (nearzero1+nearzero2)
+      qh_fprintf(fp, 9200, "p%d(coplanar facets)\n", qh_pointid(vertex->point));
+    else
+      qh_fprintf(fp, 9201, "projected p%d\n", qh_pointid(vertex->point));
+  }
+  if (qh hull_dim == 3)
+    qh_fprintf(fp, 9202, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+  else if (qh hull_dim == 4 && qh DROPdim >= 0)
+    qh_fprintf(fp, 9203, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
+} /* printhyperplaneintersection */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printline3geom">-</a>
+
+  qh_printline3geom( fp, pointA, pointB, color )
+    prints a line as a VECT
+    prints 0's for qh.DROPdim
+
+  notes:
+    if pointA == pointB,
+      it's a 1 point VECT
+*/
+void qh_printline3geom(FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
+  int k;
+  realT pA[4], pB[4];
+
+  qh_projectdim3(pointA, pA);
+  qh_projectdim3(pointB, pB);
+  if ((fabs(pA[0] - pB[0]) > 1e-3) ||
+      (fabs(pA[1] - pB[1]) > 1e-3) ||
+      (fabs(pA[2] - pB[2]) > 1e-3)) {
+    qh_fprintf(fp, 9204, "VECT 1 2 1 2 1\n");
+    for (k=0; k < 3; k++)
+       qh_fprintf(fp, 9205, "%8.4g ", pB[k]);
+    qh_fprintf(fp, 9206, " # p%d\n", qh_pointid(pointB));
+  }else
+    qh_fprintf(fp, 9207, "VECT 1 1 1 1 1\n");
+  for (k=0; k < 3; k++)
+    qh_fprintf(fp, 9208, "%8.4g ", pA[k]);
+  qh_fprintf(fp, 9209, " # p%d\n", qh_pointid(pointA));
+  qh_fprintf(fp, 9210, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
+}
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printneighborhood">-</a>
+
+  qh_printneighborhood( fp, format, facetA, facetB, printall )
+    print neighborhood of one or two facets
+
+  notes:
+    calls qh_findgood_all()
+    bumps qh.visit_id
+*/
+void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall) {
+  facetT *neighbor, **neighborp, *facet;
+  setT *facets;
+
+  if (format == qh_PRINTnone)
+    return;
+  qh_findgood_all(qh facet_list);
+  if (facetA == facetB)
+    facetB= NULL;
+  facets= qh_settemp(2*(qh_setsize(facetA->neighbors)+1));
+  qh visit_id++;
+  for (facet= facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
+    if (facet->visitid != qh visit_id) {
+      facet->visitid= qh visit_id;
+      qh_setappend(&facets, facet);
+    }
+    FOREACHneighbor_(facet) {
+      if (neighbor->visitid == qh visit_id)
+        continue;
+      neighbor->visitid= qh visit_id;
+      if (printall || !qh_skipfacet(neighbor))
+        qh_setappend(&facets, neighbor);
+    }
+  }
+  qh_printfacets(fp, format, NULL, facets, printall);
+  qh_settempfree(&facets);
+} /* printneighborhood */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpoint">-</a>
+
+  qh_printpoint( fp, string, point )
+  qh_printpointid( fp, string, dim, point, id )
+    prints the coordinates of a point
+
+  returns:
+    if string is defined
+      prints 'string p%d' (skips p%d if id=-1)
+
+  notes:
+    nop if point is NULL
+    prints id unless it is undefined (-1)
+    Same as QhullPoint's printPoint
+*/
+void qh_printpoint(FILE *fp, const char *string, pointT *point) {
+  int id= qh_pointid( point);
+
+  qh_printpointid( fp, string, qh hull_dim, point, id);
+} /* printpoint */
+
+void qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int id) {
+  int k;
+  realT r; /*bug fix*/
+
+  if (!point)
+    return;
+  if (string) {
+    qh_fprintf(fp, 9211, "%s", string);
+   if (id != -1)
+      qh_fprintf(fp, 9212, " p%d: ", id);
+  }
+  for (k=dim; k--; ) {
+    r= *point++;
+    if (string)
+      qh_fprintf(fp, 9213, " %8.4g", r);
+    else
+      qh_fprintf(fp, 9214, qh_REAL_1, r);
+  }
+  qh_fprintf(fp, 9215, "\n");
+} /* printpointid */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpoint3">-</a>
+
+  qh_printpoint3( fp, point )
+    prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
+*/
+void qh_printpoint3 (FILE *fp, pointT *point) {
+  int k;
+  realT p[4];
+
+  qh_projectdim3 (point, p);
+  for (k=0; k < 3; k++)
+    qh_fprintf(fp, 9216, "%8.4g ", p[k]);
+  qh_fprintf(fp, 9217, " # p%d\n", qh_pointid(point));
+} /* printpoint3 */
+
+/*----------------------------------------
+-printpoints- print pointids for a set of points starting at index
+   see geom.c
+*/
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpoints_out">-</a>
+
+  qh_printpoints_out( fp, facetlist, facets, printall )
+    prints vertices, coplanar/inside points, for facets by their point coordinates
+    allows qh.CDDoutput
+
+  notes:
+    same format as qhull input
+    if no coplanar/interior points,
+      same order as qh_printextremes
+*/
+void qh_printpoints_out(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
+  int allpoints= qh num_points + qh_setsize(qh other_points);
+  int numpoints=0, point_i, point_n;
+  setT *vertices, *points;
+  facetT *facet, **facetp;
+  pointT *point, **pointp;
+  vertexT *vertex, **vertexp;
+  int id;
+
+  points= qh_settemp(allpoints);
+  qh_setzero(points, 0, allpoints);
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  FOREACHvertex_(vertices) {
+    id= qh_pointid(vertex->point);
+    if (id >= 0)
+      SETelem_(points, id)= vertex->point;
+  }
+  if (qh KEEPinside || qh KEEPcoplanar || qh KEEPnearinside) {
+    FORALLfacet_(facetlist) {
+      if (!printall && qh_skipfacet(facet))
+        continue;
+      FOREACHpoint_(facet->coplanarset) {
+        id= qh_pointid(point);
+        if (id >= 0)
+          SETelem_(points, id)= point;
+      }
+    }
+    FOREACHfacet_(facets) {
+      if (!printall && qh_skipfacet(facet))
+        continue;
+      FOREACHpoint_(facet->coplanarset) {
+        id= qh_pointid(point);
+        if (id >= 0)
+          SETelem_(points, id)= point;
+      }
+    }
+  }
+  qh_settempfree(&vertices);
+  FOREACHpoint_i_(points) {
+    if (point)
+      numpoints++;
+  }
+  if (qh CDDoutput)
+    qh_fprintf(fp, 9218, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
+             qh qhull_command, numpoints, qh hull_dim + 1);
+  else
+    qh_fprintf(fp, 9219, "%d\n%d\n", qh hull_dim, numpoints);
+  FOREACHpoint_i_(points) {
+    if (point) {
+      if (qh CDDoutput)
+        qh_fprintf(fp, 9220, "1 ");
+      qh_printpoint(fp, NULL, point);
+    }
+  }
+  if (qh CDDoutput)
+    qh_fprintf(fp, 9221, "end\n");
+  qh_settempfree(&points);
+} /* printpoints_out */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpointvect">-</a>
+
+  qh_printpointvect( fp, point, normal, center, radius, color )
+    prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
+*/
+void qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
+  realT diff[4] = { 0.0 }, pointA[4] = { 0.0 };
+  int k;
+
+  for (k=qh hull_dim; k--; ) {
+    if (center)
+      diff[k]= point[k]-center[k];
+    else if (normal)
+      diff[k]= normal[k];
+    else
+      diff[k]= 0;
+  }
+  if (center)
+    qh_normalize2 (diff, qh hull_dim, True, NULL, NULL);
+  for (k=qh hull_dim; k--; )
+    pointA[k]= point[k]+diff[k] * radius;
+  qh_printline3geom(fp, point, pointA, color);
+} /* printpointvect */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printpointvect2">-</a>
+
+  qh_printpointvect2( fp, point, normal, center, radius )
+    prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
+*/
+void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
+  realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
+
+  qh_printpointvect(fp, point, normal, center, radius, red);
+  qh_printpointvect(fp, point, normal, center, -radius, yellow);
+} /* printpointvect2 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printridge">-</a>
+
+  qh_printridge( fp, ridge )
+    prints the information in a ridge
+
+  notes:
+    for qh_printfacetridges()
+    same as operator<< [QhullRidge.cpp]
+*/
+void qh_printridge(FILE *fp, ridgeT *ridge) {
+
+  qh_fprintf(fp, 9222, "     - r%d", ridge->id);
+  if (ridge->tested)
+    qh_fprintf(fp, 9223, " tested");
+  if (ridge->nonconvex)
+    qh_fprintf(fp, 9224, " nonconvex");
+  qh_fprintf(fp, 9225, "\n");
+  qh_printvertices(fp, "           vertices:", ridge->vertices);
+  if (ridge->top && ridge->bottom)
+    qh_fprintf(fp, 9226, "           between f%d and f%d\n",
+            ridge->top->id, ridge->bottom->id);
+} /* printridge */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printspheres">-</a>
+
+  qh_printspheres( fp, vertices, radius )
+    prints 3-d vertices as OFF spheres
+
+  notes:
+    inflated octahedron from Stuart Levy earth/mksphere2
+*/
+void qh_printspheres(FILE *fp, setT *vertices, realT radius) {
+  vertexT *vertex, **vertexp;
+
+  qh printoutnum++;
+  qh_fprintf(fp, 9227, "{appearance {-edge -normal normscale 0} {\n\
+INST geom {define vsphere OFF\n\
+18 32 48\n\
+\n\
+0 0 1\n\
+1 0 0\n\
+0 1 0\n\
+-1 0 0\n\
+0 -1 0\n\
+0 0 -1\n\
+0.707107 0 0.707107\n\
+0 -0.707107 0.707107\n\
+0.707107 -0.707107 0\n\
+-0.707107 0 0.707107\n\
+-0.707107 -0.707107 0\n\
+0 0.707107 0.707107\n\
+-0.707107 0.707107 0\n\
+0.707107 0.707107 0\n\
+0.707107 0 -0.707107\n\
+0 0.707107 -0.707107\n\
+-0.707107 0 -0.707107\n\
+0 -0.707107 -0.707107\n\
+\n\
+3 0 6 11\n\
+3 0 7 6 \n\
+3 0 9 7 \n\
+3 0 11 9\n\
+3 1 6 8 \n\
+3 1 8 14\n\
+3 1 13 6\n\
+3 1 14 13\n\
+3 2 11 13\n\
+3 2 12 11\n\
+3 2 13 15\n\
+3 2 15 12\n\
+3 3 9 12\n\
+3 3 10 9\n\
+3 3 12 16\n\
+3 3 16 10\n\
+3 4 7 10\n\
+3 4 8 7\n\
+3 4 10 17\n\
+3 4 17 8\n\
+3 5 14 17\n\
+3 5 15 14\n\
+3 5 16 15\n\
+3 5 17 16\n\
+3 6 13 11\n\
+3 7 8 6\n\
+3 9 10 7\n\
+3 11 12 9\n\
+3 14 8 17\n\
+3 15 13 14\n\
+3 16 12 15\n\
+3 17 10 16\n} transforms { TLIST\n");
+  FOREACHvertex_(vertices) {
+    qh_fprintf(fp, 9228, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
+      radius, vertex->id, radius, radius);
+    qh_printpoint3 (fp, vertex->point);
+    qh_fprintf(fp, 9229, "1\n");
+  }
+  qh_fprintf(fp, 9230, "}}}\n");
+} /* printspheres */
+
+
+/*----------------------------------------------
+-printsummary-
+                see libqhull.c
+*/
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvdiagram">-</a>
+
+  qh_printvdiagram( fp, format, facetlist, facets, printall )
+    print voronoi diagram
+      # of pairs of input sites
+      #indices site1 site2 vertex1 ...
+
+    sites indexed by input point id
+      point 0 is the first input point
+    vertices indexed by 'o' and 'p' order
+      vertex 0 is the 'vertex-at-infinity'
+      vertex 1 is the first Voronoi vertex
+
+  see:
+    qh_printvoronoi()
+    qh_eachvoronoi_all()
+
+  notes:
+    if all facets are upperdelaunay,
+      prints upper hull (furthest-site Voronoi diagram)
+*/
+void qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  setT *vertices;
+  int totcount, numcenters;
+  boolT isLower;
+  qh_RIDGE innerouter= qh_RIDGEall;
+  printvridgeT printvridge= NULL;
+
+  if (format == qh_PRINTvertices) {
+    innerouter= qh_RIDGEall;
+    printvridge= qh_printvridge;
+  }else if (format == qh_PRINTinner) {
+    innerouter= qh_RIDGEinner;
+    printvridge= qh_printvnorm;
+  }else if (format == qh_PRINTouter) {
+    innerouter= qh_RIDGEouter;
+    printvridge= qh_printvnorm;
+  }else {
+    qh_fprintf(qh ferr, 6219, "Qhull internal error (qh_printvdiagram): unknown print format %d.\n", format);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
+  totcount= qh_printvdiagram2 (NULL, NULL, vertices, innerouter, False);
+  qh_fprintf(fp, 9231, "%d\n", totcount);
+  /*totcount=*/ qh_printvdiagram2 (fp, printvridge, vertices, innerouter, True /* inorder*/);
+  qh_settempfree(&vertices);
+#if 0  /* for testing qh_eachvoronoi_all */
+  qh_fprintf(fp, 9232, "\n");
+  totcount= qh_eachvoronoi_all(fp, printvridge, qh UPPERdelaunay, innerouter, True /* inorder*/);
+  qh_fprintf(fp, 9233, "%d\n", totcount);
+#endif
+} /* printvdiagram */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvdiagram2">-</a>
+
+  qh_printvdiagram2( fp, printvridge, vertices, innerouter, inorder )
+    visit all pairs of input sites (vertices) for selected Voronoi vertices
+    vertices may include NULLs
+
+  innerouter:
+    qh_RIDGEall   print inner ridges(bounded) and outer ridges(unbounded)
+    qh_RIDGEinner print only inner ridges
+    qh_RIDGEouter print only outer ridges
+
+  inorder:
+    print 3-d Voronoi vertices in order
+
+  assumes:
+    qh_markvoronoi marked facet->visitid for Voronoi vertices
+    all facet->seen= False
+    all facet->seen2= True
+
+  returns:
+    total number of Voronoi ridges
+    if printvridge,
+      calls printvridge( fp, vertex, vertexA, centers) for each ridge
+      [see qh_eachvoronoi()]
+
+  see:
+    qh_eachvoronoi_all()
+*/
+int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
+  int totcount= 0;
+  int vertex_i, vertex_n;
+  vertexT *vertex;
+
+  FORALLvertices
+    vertex->seen= False;
+  FOREACHvertex_i_(vertices) {
+    if (vertex) {
+      if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
+        continue;
+      totcount += qh_eachvoronoi(fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
+    }
+  }
+  return totcount;
+} /* printvdiagram2 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvertex">-</a>
+
+  qh_printvertex( fp, vertex )
+    prints the information in a vertex
+    Duplicated as operator<< [QhullVertex.cpp]
+*/
+void qh_printvertex(FILE *fp, vertexT *vertex) {
+  pointT *point;
+  int k, count= 0;
+  facetT *neighbor, **neighborp;
+  realT r; /*bug fix*/
+
+  if (!vertex) {
+    qh_fprintf(fp, 9234, "  NULLvertex\n");
+    return;
+  }
+  qh_fprintf(fp, 9235, "- p%d(v%d):", qh_pointid(vertex->point), vertex->id);
+  point= vertex->point;
+  if (point) {
+    for (k=qh hull_dim; k--; ) {
+      r= *point++;
+      qh_fprintf(fp, 9236, " %5.2g", r);
+    }
+  }
+  if (vertex->deleted)
+    qh_fprintf(fp, 9237, " deleted");
+  if (vertex->delridge)
+    qh_fprintf(fp, 9238, " ridgedeleted");
+  qh_fprintf(fp, 9239, "\n");
+  if (vertex->neighbors) {
+    qh_fprintf(fp, 9240, "  neighbors:");
+    FOREACHneighbor_(vertex) {
+      if (++count % 100 == 0)
+        qh_fprintf(fp, 9241, "\n     ");
+      qh_fprintf(fp, 9242, " f%d", neighbor->id);
+    }
+    qh_fprintf(fp, 9243, "\n");
+  }
+} /* printvertex */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvertexlist">-</a>
+
+  qh_printvertexlist( fp, string, facetlist, facets, printall )
+    prints vertices used by a facetlist or facet set
+    tests qh_skipfacet() if !printall
+*/
+void qh_printvertexlist(FILE *fp, const char* string, facetT *facetlist,
+                         setT *facets, boolT printall) {
+  vertexT *vertex, **vertexp;
+  setT *vertices;
+
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  qh_fprintf(fp, 9244, "%s", string);
+  FOREACHvertex_(vertices)
+    qh_printvertex(fp, vertex);
+  qh_settempfree(&vertices);
+} /* printvertexlist */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvertices">-</a>
+
+  qh_printvertices( fp, string, vertices )
+    prints vertices in a set
+    duplicated as printVertexSet [QhullVertex.cpp]
+*/
+void qh_printvertices(FILE *fp, const char* string, setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  qh_fprintf(fp, 9245, "%s", string);
+  FOREACHvertex_(vertices)
+    qh_fprintf(fp, 9246, " p%d(v%d)", qh_pointid(vertex->point), vertex->id);
+  qh_fprintf(fp, 9247, "\n");
+} /* printvertices */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvneighbors">-</a>
+
+  qh_printvneighbors( fp, facetlist, facets, printall )
+    print vertex neighbors of vertices in facetlist and facets ('FN')
+
+  notes:
+    qh_countfacets clears facet->visitid for non-printed facets
+
+  design:
+    collect facet count and related statistics
+    if necessary, build neighbor sets for each vertex
+    collect vertices in facetlist and facets
+    build a point array for point->vertex and point->coplanar facet
+    for each point
+      list vertex neighbors or coplanar facet
+*/
+void qh_printvneighbors(FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
+  int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
+  setT *vertices, *vertex_points, *coplanar_points;
+  int numpoints= qh num_points + qh_setsize(qh other_points);
+  vertexT *vertex, **vertexp;
+  int vertex_i, vertex_n;
+  facetT *facet, **facetp, *neighbor, **neighborp;
+  pointT *point, **pointp;
+
+  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
+      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);  /* sets facet->visitid */
+  qh_fprintf(fp, 9248, "%d\n", numpoints);
+  qh_vertexneighbors();
+  vertices= qh_facetvertices(facetlist, facets, printall);
+  vertex_points= qh_settemp(numpoints);
+  coplanar_points= qh_settemp(numpoints);
+  qh_setzero(vertex_points, 0, numpoints);
+  qh_setzero(coplanar_points, 0, numpoints);
+  FOREACHvertex_(vertices)
+    qh_point_add(vertex_points, vertex->point, vertex);
+  FORALLfacet_(facetlist) {
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add(coplanar_points, point, facet);
+  }
+  FOREACHfacet_(facets) {
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add(coplanar_points, point, facet);
+  }
+  FOREACHvertex_i_(vertex_points) {
+    if (vertex) {
+      numneighbors= qh_setsize(vertex->neighbors);
+      qh_fprintf(fp, 9249, "%d", numneighbors);
+      if (qh hull_dim == 3)
+        qh_order_vertexneighbors(vertex);
+      else if (qh hull_dim >= 4)
+        qsort(SETaddr_(vertex->neighbors, facetT), (size_t)numneighbors,
+             sizeof(facetT *), qh_compare_facetvisit);
+      FOREACHneighbor_(vertex)
+        qh_fprintf(fp, 9250, " %d",
+                 neighbor->visitid ? neighbor->visitid - 1 : 0 - neighbor->id);
+      qh_fprintf(fp, 9251, "\n");
+    }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
+      qh_fprintf(fp, 9252, "1 %d\n",
+                  facet->visitid ? facet->visitid - 1 : 0 - facet->id);
+    else
+      qh_fprintf(fp, 9253, "0\n");
+  }
+  qh_settempfree(&coplanar_points);
+  qh_settempfree(&vertex_points);
+  qh_settempfree(&vertices);
+} /* printvneighbors */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvoronoi">-</a>
+
+  qh_printvoronoi( fp, format, facetlist, facets, printall )
+    print voronoi diagram in 'o' or 'G' format
+    for 'o' format
+      prints voronoi centers for each facet and for infinity
+      for each vertex, lists ids of printed facets or infinity
+      assumes facetlist and facets are disjoint
+    for 'G' format
+      prints an OFF object
+      adds a 0 coordinate to center
+      prints infinity but does not list in vertices
+
+  see:
+    qh_printvdiagram()
+
+  notes:
+    if 'o',
+      prints a line for each point except "at-infinity"
+    if all facets are upperdelaunay,
+      reverses lower and upper hull
+*/
+void qh_printvoronoi(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
+  int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
+  facetT *facet, **facetp, *neighbor, **neighborp;
+  setT *vertices;
+  vertexT *vertex;
+  boolT isLower;
+  unsigned int numfacets= (unsigned int) qh num_facets;
+
+  vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
+  FOREACHvertex_i_(vertices) {
+    if (vertex) {
+      numvertices++;
+      numneighbors = numinf = 0;
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visitid == 0)
+          numinf= 1;
+        else if (neighbor->visitid < numfacets)
+          numneighbors++;
+      }
+      if (numinf && !numneighbors) {
+        SETelem_(vertices, vertex_i)= NULL;
+        numvertices--;
+      }
+    }
+  }
+  if (format == qh_PRINTgeom)
+    qh_fprintf(fp, 9254, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n",
+                numcenters, numvertices);
+  else
+    qh_fprintf(fp, 9255, "%d\n%d %d 1\n", qh hull_dim-1, numcenters, qh_setsize(vertices));
+  if (format == qh_PRINTgeom) {
+    for (k=qh hull_dim-1; k--; )
+      qh_fprintf(fp, 9256, qh_REAL_1, 0.0);
+    qh_fprintf(fp, 9257, " 0 # infinity not used\n");
+  }else {
+    for (k=qh hull_dim-1; k--; )
+      qh_fprintf(fp, 9258, qh_REAL_1, qh_INFINITE);
+    qh_fprintf(fp, 9259, "\n");
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->visitid && facet->visitid < numfacets) {
+      if (format == qh_PRINTgeom)
+        qh_fprintf(fp, 9260, "# %d f%d\n", vid++, facet->id);
+      qh_printcenter(fp, format, NULL, facet);
+    }
+  }
+  FOREACHfacet_(facets) {
+    if (facet->visitid && facet->visitid < numfacets) {
+      if (format == qh_PRINTgeom)
+        qh_fprintf(fp, 9261, "# %d f%d\n", vid++, facet->id);
+      qh_printcenter(fp, format, NULL, facet);
+    }
+  }
+  FOREACHvertex_i_(vertices) {
+    numneighbors= 0;
+    numinf=0;
+    if (vertex) {
+      if (qh hull_dim == 3)
+        qh_order_vertexneighbors(vertex);
+      else if (qh hull_dim >= 4)
+        qsort(SETaddr_(vertex->neighbors, facetT),
+             (size_t)qh_setsize(vertex->neighbors),
+             sizeof(facetT *), qh_compare_facetvisit);
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visitid == 0)
+          numinf= 1;
+        else if (neighbor->visitid < numfacets)
+          numneighbors++;
+      }
+    }
+    if (format == qh_PRINTgeom) {
+      if (vertex) {
+        qh_fprintf(fp, 9262, "%d", numneighbors);
+        FOREACHneighbor_(vertex) {
+          if (neighbor->visitid && neighbor->visitid < numfacets)
+            qh_fprintf(fp, 9263, " %d", neighbor->visitid);
+        }
+        qh_fprintf(fp, 9264, " # p%d(v%d)\n", vertex_i, vertex->id);
+      }else
+        qh_fprintf(fp, 9265, " # p%d is coplanar or isolated\n", vertex_i);
+    }else {
+      if (numinf)
+        numneighbors++;
+      qh_fprintf(fp, 9266, "%d", numneighbors);
+      if (vertex) {
+        FOREACHneighbor_(vertex) {
+          if (neighbor->visitid == 0) {
+            if (numinf) {
+              numinf= 0;
+              qh_fprintf(fp, 9267, " %d", neighbor->visitid);
+            }
+          }else if (neighbor->visitid < numfacets)
+            qh_fprintf(fp, 9268, " %d", neighbor->visitid);
+        }
+      }
+      qh_fprintf(fp, 9269, "\n");
+    }
+  }
+  if (format == qh_PRINTgeom)
+    qh_fprintf(fp, 9270, "}\n");
+  qh_settempfree(&vertices);
+} /* printvoronoi */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvnorm">-</a>
+
+  qh_printvnorm( fp, vertex, vertexA, centers, unbounded )
+    print one separating plane of the Voronoi diagram for a pair of input sites
+    unbounded==True if centers includes vertex-at-infinity
+
+  assumes:
+    qh_ASvoronoi and qh_vertexneighbors() already set
+
+  note:
+    parameter unbounded is UNUSED by this callback
+
+  see:
+    qh_printvdiagram()
+    qh_eachvoronoi()
+*/
+void qh_printvnorm(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+  pointT *normal;
+  realT offset;
+  int k;
+  QHULL_UNUSED(unbounded);
+
+  normal= qh_detvnorm(vertex, vertexA, centers, &offset);
+  qh_fprintf(fp, 9271, "%d %d %d ",
+      2+qh hull_dim, qh_pointid(vertex->point), qh_pointid(vertexA->point));
+  for (k=0; k< qh hull_dim-1; k++)
+    qh_fprintf(fp, 9272, qh_REAL_1, normal[k]);
+  qh_fprintf(fp, 9273, qh_REAL_1, offset);
+  qh_fprintf(fp, 9274, "\n");
+} /* printvnorm */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="printvridge">-</a>
+
+  qh_printvridge( fp, vertex, vertexA, centers, unbounded )
+    print one ridge of the Voronoi diagram for a pair of input sites
+    unbounded==True if centers includes vertex-at-infinity
+
+  see:
+    qh_printvdiagram()
+
+  notes:
+    the user may use a different function
+    parameter unbounded is UNUSED
+*/
+void qh_printvridge(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
+  facetT *facet, **facetp;
+  QHULL_UNUSED(unbounded);
+
+  qh_fprintf(fp, 9275, "%d %d %d", qh_setsize(centers)+2,
+       qh_pointid(vertex->point), qh_pointid(vertexA->point));
+  FOREACHfacet_(centers)
+    qh_fprintf(fp, 9276, " %d", facet->visitid);
+  qh_fprintf(fp, 9277, "\n");
+} /* printvridge */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="projectdim3">-</a>
+
+  qh_projectdim3( source, destination )
+    project 2-d 3-d or 4-d point to a 3-d point
+    uses qh.DROPdim and qh.hull_dim
+    source and destination may be the same
+
+  notes:
+    allocate 4 elements to destination just in case
+*/
+void qh_projectdim3 (pointT *source, pointT *destination) {
+  int i,k;
+
+  for (k=0, i=0; k < qh hull_dim; k++) {
+    if (qh hull_dim == 4) {
+      if (k != qh DROPdim)
+        destination[i++]= source[k];
+    }else if (k == qh DROPdim)
+      destination[i++]= 0;
+    else
+      destination[i++]= source[k];
+  }
+  while (i < 3)
+    destination[i++]= 0.0;
+} /* projectdim3 */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="readfeasible">-</a>
+
+  qh_readfeasible( dim, curline )
+    read feasible point from current line and qh.fin
+
+  returns:
+    number of lines read from qh.fin
+    sets qh.FEASIBLEpoint with malloc'd coordinates
+
+  notes:
+    checks for qh.HALFspace
+    assumes dim > 1
+
+  see:
+    qh_setfeasible
+*/
+int qh_readfeasible(int dim, const char *curline) {
+  boolT isfirst= True;
+  int linecount= 0, tokcount= 0;
+  const char *s;
+  char *t, firstline[qh_MAXfirst+1];
+  coordT *coords, value;
+
+  if (!qh HALFspace) {
+    qh_fprintf(qh ferr, 6070, "qhull input error: feasible point(dim 1 coords) is only valid for halfspace intersection\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (qh feasible_string)
+    qh_fprintf(qh ferr, 7057, "qhull input warning: feasible point(dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
+  if (!(qh feasible_point= (coordT*)qh_malloc(dim* sizeof(coordT)))) {
+    qh_fprintf(qh ferr, 6071, "qhull error: insufficient memory for feasible point\n");
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coords= qh feasible_point;
+  while ((s= (isfirst ?  curline : fgets(firstline, qh_MAXfirst, qh fin)))) {
+    if (isfirst)
+      isfirst= False;
+    else
+      linecount++;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      value= qh_strtod(s, &t);
+      if (s == t)
+        break;
+      s= t;
+      *(coords++)= value;
+      if (++tokcount == dim) {
+        while (isspace(*s))
+          s++;
+        qh_strtod(s, &t);
+        if (s != t) {
+          qh_fprintf(qh ferr, 6072, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
+               s);
+          qh_errexit(qh_ERRinput, NULL, NULL);
+        }
+        return linecount;
+      }
+    }
+  }
+  qh_fprintf(qh ferr, 6073, "qhull input error: only %d coordinates.  Could not read %d-d feasible point.\n",
+           tokcount, dim);
+  qh_errexit(qh_ERRinput, NULL, NULL);
+  return 0;
+} /* readfeasible */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="readpoints">-</a>
+
+  qh_readpoints( numpoints, dimension, ismalloc )
+    read points from qh.fin into qh.first_point, qh.num_points
+    qh.fin is lines of coordinates, one per vertex, first line number of points
+    if 'rbox D4',
+      gives message
+    if qh.ATinfinity,
+      adds point-at-infinity for Delaunay triangulations
+
+  returns:
+    number of points, array of point coordinates, dimension, ismalloc True
+    if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
+        and clears qh.PROJECTdelaunay
+    if qh.HALFspace, reads optional feasible point, reads halfspaces,
+        converts to dual.
+
+  for feasible point in "cdd format" in 3-d:
+    3 1
+    coordinates
+    comments
+    begin
+    n 4 real/integer
+    ...
+    end
+
+  notes:
+    dimension will change in qh_initqhull_globals if qh.PROJECTinput
+    uses malloc() since qh_mem not initialized
+    FIXUP QH11012: qh_readpoints needs rewriting, too long
+*/
+coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) {
+  coordT *points, *coords, *infinity= NULL;
+  realT paraboloid, maxboloid= -REALmax, value;
+  realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
+  char *s= 0, *t, firstline[qh_MAXfirst+1];
+  int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
+  int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
+  int tokcount= 0, linecount=0, maxcount, coordcount=0;
+  boolT islong, isfirst= True, wasbegin= False;
+  boolT isdelaunay= qh DELAUNAY && !qh PROJECTinput;
+
+  if (qh CDDinput) {
+    while ((s= fgets(firstline, qh_MAXfirst, qh fin))) {
+      linecount++;
+      if (qh HALFspace && linecount == 1 && isdigit(*s)) {
+        dimfeasible= qh_strtol(s, &s);
+        while (isspace(*s))
+          s++;
+        if (qh_strtol(s, &s) == 1)
+          linecount += qh_readfeasible(dimfeasible, s);
+        else
+          dimfeasible= 0;
+      }else if (!memcmp(firstline, "begin", (size_t)5) || !memcmp(firstline, "BEGIN", (size_t)5))
+        break;
+      else if (!*qh rbox_command)
+        strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
+    }
+    if (!s) {
+      qh_fprintf(qh ferr, 6074, "qhull input error: missing \"begin\" for cdd-formatted input\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+  }
+  while (!numinput && (s= fgets(firstline, qh_MAXfirst, qh fin))) {
+    linecount++;
+    if (!memcmp(s, "begin", (size_t)5) || !memcmp(s, "BEGIN", (size_t)5))
+      wasbegin= True;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      if (!*s)
+        break;
+      if (!isdigit(*s)) {
+        if (!*qh rbox_command) {
+          strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
+          firsttext= linecount;
+        }
+        break;
+      }
+      if (!diminput)
+        diminput= qh_strtol(s, &s);
+      else {
+        numinput= qh_strtol(s, &s);
+        if (numinput == 1 && diminput >= 2 && qh HALFspace && !qh CDDinput) {
+          linecount += qh_readfeasible(diminput, s); /* checks if ok */
+          dimfeasible= diminput;
+          diminput= numinput= 0;
+        }else
+          break;
+      }
+    }
+  }
+  if (!s) {
+    qh_fprintf(qh ferr, 6075, "qhull input error: short input file.  Did not find dimension and number of points\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (diminput > numinput) {
+    tempi= diminput;    /* exchange dim and n, e.g., for cdd input format */
+    diminput= numinput;
+    numinput= tempi;
+  }
+  if (diminput < 2) {
+    qh_fprintf(qh ferr, 6220,"qhull input error: dimension %d(first number) should be at least 2\n",
+            diminput);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (isdelaunay) {
+    qh PROJECTdelaunay= False;
+    if (qh CDDinput)
+      *dimension= diminput;
+    else
+      *dimension= diminput+1;
+    *numpoints= numinput;
+    if (qh ATinfinity)
+      (*numpoints)++;
+  }else if (qh HALFspace) {
+    *dimension= diminput - 1;
+    *numpoints= numinput;
+    if (diminput < 3) {
+      qh_fprintf(qh ferr, 6221,"qhull input error: dimension %d(first number, includes offset) should be at least 3 for halfspaces\n",
+            diminput);
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (dimfeasible) {
+      if (dimfeasible != *dimension) {
+        qh_fprintf(qh ferr, 6222,"qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
+          dimfeasible, diminput);
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+    }else
+      qh_setfeasible(*dimension);
+  }else {
+    if (qh CDDinput)
+      *dimension= diminput-1;
+    else
+      *dimension= diminput;
+    *numpoints= numinput;
+  }
+  qh normal_size= *dimension * sizeof(coordT); /* for tracing with qh_printpoint */
+  if (qh HALFspace) {
+    qh half_space= coordp= (coordT*)qh_malloc(qh normal_size + sizeof(coordT));
+    if (qh CDDinput) {
+      offsetp= qh half_space;
+      normalp= offsetp + 1;
+    }else {
+      normalp= qh half_space;
+      offsetp= normalp + *dimension;
+    }
+  }
+  qh maxline= diminput * (qh_REALdigits + 5);
+  maximize_(qh maxline, 500);
+  qh line= (char*)qh_malloc((qh maxline+1) * sizeof(char));
+  *ismalloc= True;  /* use malloc since memory not setup */
+  coords= points= qh temp_malloc=
+        (coordT*)qh_malloc((*numpoints)*(*dimension)*sizeof(coordT));
+  if (!coords || !qh line || (qh HALFspace && !qh half_space)) {
+    qh_fprintf(qh ferr, 6076, "qhull error: insufficient memory to read %d points\n",
+            numinput);
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  if (isdelaunay && qh ATinfinity) {
+    infinity= points + numinput * (*dimension);
+    for (k= (*dimension) - 1; k--; )
+      infinity[k]= 0.0;
+  }
+  maxcount= numinput * diminput;
+  paraboloid= 0.0;
+  while ((s= (isfirst ?  s : fgets(qh line, qh maxline, qh fin)))) {
+    if (!isfirst) {
+      linecount++;
+      if (*s == 'e' || *s == 'E') {
+        if (!memcmp(s, "end", (size_t)3) || !memcmp(s, "END", (size_t)3)) {
+          if (qh CDDinput )
+            break;
+          else if (wasbegin)
+            qh_fprintf(qh ferr, 7058, "qhull input warning: the input appears to be in cdd format.  If so, use 'Fd'\n");
+        }
+      }
+    }
+    islong= False;
+    while (*s) {
+      while (isspace(*s))
+        s++;
+      value= qh_strtod(s, &t);
+      if (s == t) {
+        if (!*qh rbox_command)
+         strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
+        if (*s && !firsttext)
+          firsttext= linecount;
+        if (!islong && !firstshort && coordcount)
+          firstshort= linecount;
+        break;
+      }
+      if (!firstpoint)
+        firstpoint= linecount;
+      s= t;
+      if (++tokcount > maxcount)
+        continue;
+      if (qh HALFspace) {
+        if (qh CDDinput)
+          *(coordp++)= -value; /* both coefficients and offset */
+        else
+          *(coordp++)= value;
+      }else {
+        *(coords++)= value;
+        if (qh CDDinput && !coordcount) {
+          if (value != 1.0) {
+            qh_fprintf(qh ferr, 6077, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
+                   linecount);
+            qh_errexit(qh_ERRinput, NULL, NULL);
+          }
+          coords--;
+        }else if (isdelaunay) {
+          paraboloid += value * value;
+          if (qh ATinfinity) {
+            if (qh CDDinput)
+              infinity[coordcount-1] += value;
+            else
+              infinity[coordcount] += value;
+          }
+        }
+      }
+      if (++coordcount == diminput) {
+        coordcount= 0;
+        if (isdelaunay) {
+          *(coords++)= paraboloid;
+          maximize_(maxboloid, paraboloid);
+          paraboloid= 0.0;
+        }else if (qh HALFspace) {
+          if (!qh_sethalfspace(*dimension, coords, &coords, normalp, offsetp, qh feasible_point)) {
+            qh_fprintf(qh ferr, 8048, "The halfspace was on line %d\n", linecount);
+            if (wasbegin)
+              qh_fprintf(qh ferr, 8049, "The input appears to be in cdd format.  If so, you should use option 'Fd'\n");
+            qh_errexit(qh_ERRinput, NULL, NULL);
+          }
+          coordp= qh half_space;
+        }
+        while (isspace(*s))
+          s++;
+        if (*s) {
+          islong= True;
+          if (!firstlong)
+            firstlong= linecount;
+        }
+      }
+    }
+    if (!islong && !firstshort && coordcount)
+      firstshort= linecount;
+    if (!isfirst && s - qh line >= qh maxline) {
+      qh_fprintf(qh ferr, 6078, "qhull input error: line %d contained more than %d characters\n",
+              linecount, (int) (s - qh line));   /* WARN64 */
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    isfirst= False;
+  }
+  if (tokcount != maxcount) {
+    newnum= fmin_(numinput, tokcount/diminput);
+    qh_fprintf(qh ferr, 7073,"\
+qhull warning: instead of %d %d-dimensional points, input contains\n\
+%d points and %d extra coordinates.  Line %d is the first\npoint",
+       numinput, diminput, tokcount/diminput, tokcount % diminput, firstpoint);
+    if (firsttext)
+      qh_fprintf(qh ferr, 8051, ", line %d is the first comment", firsttext);
+    if (firstshort)
+      qh_fprintf(qh ferr, 8052, ", line %d is the first short\nline", firstshort);
+    if (firstlong)
+      qh_fprintf(qh ferr, 8053, ", line %d is the first long line", firstlong);
+    qh_fprintf(qh ferr, 8054, ".  Continue with %d points.\n", newnum);
+    numinput= newnum;
+    if (isdelaunay && qh ATinfinity) {
+      for (k= tokcount % diminput; k--; )
+        infinity[k] -= *(--coords);
+      *numpoints= newnum+1;
+    }else {
+      coords -= tokcount % diminput;
+      *numpoints= newnum;
+    }
+  }
+  if (isdelaunay && qh ATinfinity) {
+    for (k= (*dimension) -1; k--; )
+      infinity[k] /= numinput;
+    if (coords == infinity)
+      coords += (*dimension) -1;
+    else {
+      for (k=0; k < (*dimension) -1; k++)
+        *(coords++)= infinity[k];
+    }
+    *(coords++)= maxboloid * 1.1;
+  }
+  if (qh rbox_command[0]) {
+    qh rbox_command[strlen(qh rbox_command)-1]= '\0';
+    if (!strcmp(qh rbox_command, "./rbox D4"))
+      qh_fprintf(qh ferr, 8055, "\n\
+This is the qhull test case.  If any errors or core dumps occur,\n\
+recompile qhull with 'make new'.  If errors still occur, there is\n\
+an incompatibility.  You should try a different compiler.  You can also\n\
+change the choices in user.h.  If you discover the source of the problem,\n\
+please send mail to qhull_bug at qhull.org.\n\
+\n\
+Type 'qhull' for a short list of options.\n");
+  }
+  qh_free(qh line);
+  qh line= NULL;
+  if (qh half_space) {
+    qh_free(qh half_space);
+    qh half_space= NULL;
+  }
+  qh temp_malloc= NULL;
+  trace1((qh ferr, 1008,"qh_readpoints: read in %d %d-dimensional points\n",
+          numinput, diminput));
+  return(points);
+} /* readpoints */
+
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="setfeasible">-</a>
+
+  qh_setfeasible( dim )
+    set qh.FEASIBLEpoint from qh.feasible_string in "n,n,n" or "n n n" format
+
+  notes:
+    "n,n,n" already checked by qh_initflags()
+    see qh_readfeasible()
+*/
+void qh_setfeasible(int dim) {
+  int tokcount= 0;
+  char *s;
+  coordT *coords, value;
+
+  if (!(s= qh feasible_string)) {
+    qh_fprintf(qh ferr, 6223, "\
+qhull input error: halfspace intersection needs a feasible point.\n\
+Either prepend the input with 1 point or use 'Hn,n,n'.  See manual.\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (!(qh feasible_point= (pointT*)qh_malloc(dim * sizeof(coordT)))) {
+    qh_fprintf(qh ferr, 6079, "qhull error: insufficient memory for 'Hn,n,n'\n");
+    qh_errexit(qh_ERRmem, NULL, NULL);
+  }
+  coords= qh feasible_point;
+  while (*s) {
+    value= qh_strtod(s, &s);
+    if (++tokcount > dim) {
+      qh_fprintf(qh ferr, 7059, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
+          qh feasible_string, dim);
+      break;
+    }
+    *(coords++)= value;
+    if (*s)
+      s++;
+  }
+  while (++tokcount <= dim)
+    *(coords++)= 0.0;
+} /* setfeasible */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="skipfacet">-</a>
+
+  qh_skipfacet( facet )
+    returns 'True' if this facet is not to be printed
+
+  notes:
+    based on the user provided slice thresholds and 'good' specifications
+*/
+boolT qh_skipfacet(facetT *facet) {
+  facetT *neighbor, **neighborp;
+
+  if (qh PRINTneighbors) {
+    if (facet->good)
+      return !qh PRINTgood;
+    FOREACHneighbor_(facet) {
+      if (neighbor->good)
+        return False;
+    }
+    return True;
+  }else if (qh PRINTgood)
+    return !facet->good;
+  else if (!facet->normal)
+    return True;
+  return(!qh_inthresholds(facet->normal, NULL));
+} /* skipfacet */
+
+/*-<a                             href="qh-io.htm#TOC"
+  >-------------------------------</a><a name="skipfilename">-</a>
+
+  qh_skipfilename( string )
+    returns pointer to character after filename
+
+  notes:
+    skips leading spaces
+    ends with spacing or eol
+    if starts with ' or " ends with the same, skipping \' or \"
+    For qhull, qh_argv_to_command() only uses double quotes
+*/
+char *qh_skipfilename(char *filename) {
+  char *s= filename;  /* non-const due to return */
+  char c;
+
+  while (*s && isspace(*s))
+    s++;
+  c= *s++;
+  if (c == '\0') {
+    qh_fprintf(qh ferr, 6204, "qhull input error: filename expected, none found.\n");
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  if (c == '\'' || c == '"') {
+    while (*s !=c || s[-1] == '\\') {
+      if (!*s) {
+        qh_fprintf(qh ferr, 6203, "qhull input error: missing quote after filename -- %s\n", filename);
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+      s++;
+    }
+    s++;
+  }
+  else while (*s && !isspace(*s))
+      s++;
+  return s;
+} /* skipfilename */
+
diff --git a/alg/libqhull/io.h b/alg/internal_libqhull/io.h
similarity index 100%
rename from alg/libqhull/io.h
rename to alg/internal_libqhull/io.h
diff --git a/alg/libqhull/libqhull.c b/alg/internal_libqhull/libqhull.c
similarity index 100%
rename from alg/libqhull/libqhull.c
rename to alg/internal_libqhull/libqhull.c
diff --git a/alg/libqhull/libqhull.h b/alg/internal_libqhull/libqhull.h
similarity index 100%
rename from alg/libqhull/libqhull.h
rename to alg/internal_libqhull/libqhull.h
diff --git a/alg/libqhull/mem.c b/alg/internal_libqhull/mem.c
similarity index 100%
rename from alg/libqhull/mem.c
rename to alg/internal_libqhull/mem.c
diff --git a/alg/libqhull/mem.h b/alg/internal_libqhull/mem.h
similarity index 100%
rename from alg/libqhull/mem.h
rename to alg/internal_libqhull/mem.h
diff --git a/alg/libqhull/merge.c b/alg/internal_libqhull/merge.c
similarity index 100%
rename from alg/libqhull/merge.c
rename to alg/internal_libqhull/merge.c
diff --git a/alg/libqhull/merge.h b/alg/internal_libqhull/merge.h
similarity index 100%
rename from alg/libqhull/merge.h
rename to alg/internal_libqhull/merge.h
diff --git a/alg/internal_libqhull/poly.c b/alg/internal_libqhull/poly.c
new file mode 100644
index 0000000..2ba1813
--- /dev/null
+++ b/alg/internal_libqhull/poly.c
@@ -0,0 +1,1202 @@
+/*<html><pre>  -<a                             href="qh-poly.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   poly.c
+   implements polygons and simplices
+
+   see qh-poly.htm, poly.h and libqhull.h
+
+   infrequent code is in poly2.c
+   (all but top 50 and their callers 12/3/95)
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/poly.c#5 $$Change: 1464 $
+   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
+*/
+
+#include "qhull_a.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="appendfacet">-</a>
+
+  qh_appendfacet( facet )
+    appends facet to end of qh.facet_list,
+
+  returns:
+    updates qh.newfacet_list, facet_next, facet_list
+    increments qh.numfacets
+
+  notes:
+    assumes qh.facet_list/facet_tail is defined (createsimplex)
+
+  see:
+    qh_removefacet()
+
+*/
+void qh_appendfacet(facetT *facet) {
+  facetT *tail= qh facet_tail;
+
+  if (tail == qh newfacet_list)
+    qh newfacet_list= facet;
+  if (tail == qh facet_next)
+    qh facet_next= facet;
+  facet->previous= tail->previous;
+  facet->next= tail;
+  if (tail->previous)
+    tail->previous->next= facet;
+  else
+    qh facet_list= facet;
+  tail->previous= facet;
+  qh num_facets++;
+  trace4((qh ferr, 4044, "qh_appendfacet: append f%d to facet_list\n", facet->id));
+} /* appendfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="appendvertex">-</a>
+
+  qh_appendvertex( vertex )
+    appends vertex to end of qh.vertex_list,
+
+  returns:
+    sets vertex->newlist
+    updates qh.vertex_list, newvertex_list
+    increments qh.num_vertices
+
+  notes:
+    assumes qh.vertex_list/vertex_tail is defined (createsimplex)
+
+*/
+void qh_appendvertex(vertexT *vertex) {
+  vertexT *tail= qh vertex_tail;
+
+  if (tail == qh newvertex_list)
+    qh newvertex_list= vertex;
+  vertex->newlist= True;
+  vertex->previous= tail->previous;
+  vertex->next= tail;
+  if (tail->previous)
+    tail->previous->next= vertex;
+  else
+    qh vertex_list= vertex;
+  tail->previous= vertex;
+  qh num_vertices++;
+  trace4((qh ferr, 4045, "qh_appendvertex: append v%d to vertex_list\n", vertex->id));
+} /* appendvertex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="attachnewfacets">-</a>
+
+  qh_attachnewfacets( )
+    attach horizon facets to new facets in qh.newfacet_list
+    newfacets have neighbor and ridge links to horizon but not vice versa
+    only needed for qh.ONLYgood
+
+  returns:
+    set qh.NEWfacets
+    horizon facets linked to new facets
+      ridges changed from visible facets to new facets
+      simplicial ridges deleted
+    qh.visible_list, no ridges valid
+    facet->f.replace is a newfacet (if any)
+
+  design:
+    delete interior ridges and neighbor sets by
+      for each visible, non-simplicial facet
+        for each ridge
+          if last visit or if neighbor is simplicial
+            if horizon neighbor
+              delete ridge for horizon's ridge set
+            delete ridge
+        erase neighbor set
+    attach horizon facets and new facets by
+      for all new facets
+        if corresponding horizon facet is simplicial
+          locate corresponding visible facet {may be more than one}
+          link visible facet to new facet
+          replace visible facet with new facet in horizon
+        else it's non-simplicial
+          for all visible neighbors of the horizon facet
+            link visible neighbor to new facet
+            delete visible neighbor from horizon facet
+          append new facet to horizon's neighbors
+          the first ridge of the new facet is the horizon ridge
+          link the new facet into the horizon ridge
+*/
+void qh_attachnewfacets(void ) {
+  facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
+  ridgeT *ridge, **ridgep;
+
+  qh NEWfacets= True;
+  trace3((qh ferr, 3012, "qh_attachnewfacets: delete interior ridges\n"));
+  qh visit_id++;
+  FORALLvisible_facets {
+    visible->visitid= qh visit_id;
+    if (visible->ridges) {
+      FOREACHridge_(visible->ridges) {
+        neighbor= otherfacet_(ridge, visible);
+        if (neighbor->visitid == qh visit_id
+            || (!neighbor->visible && neighbor->simplicial)) {
+          if (!neighbor->visible)  /* delete ridge for simplicial horizon */
+            qh_setdel(neighbor->ridges, ridge);
+          qh_setfree(&(ridge->vertices)); /* delete on 2nd visit */
+          qh_memfree(ridge, (int)sizeof(ridgeT));
+        }
+      }
+      SETfirst_(visible->ridges)= NULL;
+    }
+    SETfirst_(visible->neighbors)= NULL;
+  }
+  trace1((qh ferr, 1017, "qh_attachnewfacets: attach horizon facets to new facets\n"));
+  FORALLnew_facets {
+    horizon= SETfirstt_(newfacet->neighbors, facetT);
+    if (horizon->simplicial) {
+      visible= NULL;
+      FOREACHneighbor_(horizon) {   /* may have more than one horizon ridge */
+        if (neighbor->visible) {
+          if (visible) {
+            if (qh_setequal_skip(newfacet->vertices, 0, horizon->vertices,
+                                  SETindex_(horizon->neighbors, neighbor))) {
+              visible= neighbor;
+              break;
+            }
+          }else
+            visible= neighbor;
+        }
+      }
+      if (visible) {
+        visible->f.replace= newfacet;
+        qh_setreplace(horizon->neighbors, visible, newfacet);
+      }else {
+        qh_fprintf(qh ferr, 6102, "qhull internal error (qh_attachnewfacets): couldn't find visible facet for horizon f%d of newfacet f%d\n",
+                 horizon->id, newfacet->id);
+        qh_errexit2 (qh_ERRqhull, horizon, newfacet);
+      }
+    }else { /* non-simplicial, with a ridge for newfacet */
+      FOREACHneighbor_(horizon) {    /* may hold for many new facets */
+        if (neighbor->visible) {
+          neighbor->f.replace= newfacet;
+          qh_setdelnth(horizon->neighbors,
+                        SETindex_(horizon->neighbors, neighbor));
+          neighborp--; /* repeat */
+        }
+      }
+      qh_setappend(&horizon->neighbors, newfacet);
+      ridge= SETfirstt_(newfacet->ridges, ridgeT);
+      if (ridge->top == horizon)
+        ridge->bottom= newfacet;
+      else
+        ridge->top= newfacet;
+      }
+  } /* newfacets */
+  if (qh PRINTstatistics) {
+    FORALLvisible_facets {
+      if (!visible->f.replace)
+        zinc_(Zinsidevisible);
+    }
+  }
+} /* attachnewfacets */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkflipped">-</a>
+
+  qh_checkflipped( facet, dist, allerror )
+    checks facet orientation to interior point
+
+    if allerror set,
+      tests against qh.DISTround
+    else
+      tests against 0 since tested against DISTround before
+
+  returns:
+    False if it flipped orientation (sets facet->flipped)
+    distance if non-NULL
+*/
+boolT qh_checkflipped(facetT *facet, realT *distp, boolT allerror) {
+  realT dist;
+
+  if (facet->flipped && !distp)
+    return False;
+  zzinc_(Zdistcheck);
+  qh_distplane(qh interior_point, facet, &dist);
+  if (distp)
+    *distp= dist;
+  if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) {
+    facet->flipped= True;
+    zzinc_(Zflippedfacets);
+    trace0((qh ferr, 19, "qh_checkflipped: facet f%d is flipped, distance= %6.12g during p%d\n",
+              facet->id, dist, qh furthest_id));
+    qh_precision("flipped facet");
+    return False;
+  }
+  return True;
+} /* checkflipped */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="delfacet">-</a>
+
+  qh_delfacet( facet )
+    removes facet from facet_list and frees up its memory
+
+  notes:
+    assumes vertices and ridges already freed
+*/
+void qh_delfacet(facetT *facet) {
+  void **freelistp; /* used !qh_NOmem */
+
+  trace4((qh ferr, 4046, "qh_delfacet: delete f%d\n", facet->id));
+  if (facet == qh tracefacet)
+    qh tracefacet= NULL;
+  if (facet == qh GOODclosest)
+    qh GOODclosest= NULL;
+  qh_removefacet(facet);
+  if (!facet->tricoplanar || facet->keepcentrum) {
+    qh_memfree_(facet->normal, qh normal_size, freelistp);
+    if (qh CENTERtype == qh_ASvoronoi) {   /* uses macro calls */
+      qh_memfree_(facet->center, qh center_size, freelistp);
+    }else /* AScentrum */ {
+      qh_memfree_(facet->center, qh normal_size, freelistp);
+    }
+  }
+  qh_setfree(&(facet->neighbors));
+  if (facet->ridges)
+    qh_setfree(&(facet->ridges));
+  qh_setfree(&(facet->vertices));
+  if (facet->outsideset)
+    qh_setfree(&(facet->outsideset));
+  if (facet->coplanarset)
+    qh_setfree(&(facet->coplanarset));
+  qh_memfree_(facet, (int)sizeof(facetT), freelistp);
+} /* delfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="deletevisible">-</a>
+
+  qh_deletevisible()
+    delete visible facets and vertices
+
+  returns:
+    deletes each facet and removes from facetlist
+    at exit, qh.visible_list empty (== qh.newfacet_list)
+
+  notes:
+    ridges already deleted
+    horizon facets do not reference facets on qh.visible_list
+    new facets in qh.newfacet_list
+    uses   qh.visit_id;
+*/
+void qh_deletevisible(void /*qh visible_list*/) {
+  facetT *visible, *nextfacet;
+  vertexT *vertex, **vertexp;
+  int numvisible= 0, numdel= qh_setsize(qh del_vertices);
+
+  trace1((qh ferr, 1018, "qh_deletevisible: delete %d visible facets and %d vertices\n",
+         qh num_visible, numdel));
+  for (visible= qh visible_list; visible && visible->visible;
+                visible= nextfacet) { /* deleting current */
+    nextfacet= visible->next;
+    numvisible++;
+    qh_delfacet(visible);
+  }
+  if (numvisible != qh num_visible) {
+    qh_fprintf(qh ferr, 6103, "qhull internal error (qh_deletevisible): qh num_visible %d is not number of visible facets %d\n",
+             qh num_visible, numvisible);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  qh num_visible= 0;
+  zadd_(Zvisfacettot, numvisible);
+  zmax_(Zvisfacetmax, numvisible);
+  zzadd_(Zdelvertextot, numdel);
+  zmax_(Zdelvertexmax, numdel);
+  FOREACHvertex_(qh del_vertices)
+    qh_delvertex(vertex);
+  qh_settruncate(qh del_vertices, 0);
+} /* deletevisible */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="facetintersect">-</a>
+
+  qh_facetintersect( facetA, facetB, skipa, skipB, prepend )
+    return vertices for intersection of two simplicial facets
+    may include 1 prepended entry (if more, need to settemppush)
+
+  returns:
+    returns set of qh.hull_dim-1 + prepend vertices
+    returns skipped index for each test and checks for exactly one
+
+  notes:
+    does not need settemp since set in quick memory
+
+  see also:
+    qh_vertexintersect and qh_vertexintersect_new
+    use qh_setnew_delnthsorted to get nth ridge (no skip information)
+
+  design:
+    locate skipped vertex by scanning facet A's neighbors
+    locate skipped vertex by scanning facet B's neighbors
+    intersect the vertex sets
+*/
+setT *qh_facetintersect(facetT *facetA, facetT *facetB,
+                         int *skipA,int *skipB, int prepend) {
+  setT *intersect;
+  int dim= qh hull_dim, i, j;
+  facetT **neighborsA, **neighborsB;
+
+  neighborsA= SETaddr_(facetA->neighbors, facetT);
+  neighborsB= SETaddr_(facetB->neighbors, facetT);
+  i= j= 0;
+  if (facetB == *neighborsA++)
+    *skipA= 0;
+  else if (facetB == *neighborsA++)
+    *skipA= 1;
+  else if (facetB == *neighborsA++)
+    *skipA= 2;
+  else {
+    for (i=3; i < dim; i++) {
+      if (facetB == *neighborsA++) {
+        *skipA= i;
+        break;
+      }
+    }
+  }
+  if (facetA == *neighborsB++)
+    *skipB= 0;
+  else if (facetA == *neighborsB++)
+    *skipB= 1;
+  else if (facetA == *neighborsB++)
+    *skipB= 2;
+  else {
+    for (j=3; j < dim; j++) {
+      if (facetA == *neighborsB++) {
+        *skipB= j;
+        break;
+      }
+    }
+  }
+  if (i >= dim || j >= dim) {
+    qh_fprintf(qh ferr, 6104, "qhull internal error (qh_facetintersect): f%d or f%d not in others neighbors\n",
+            facetA->id, facetB->id);
+    qh_errexit2 (qh_ERRqhull, facetA, facetB);
+  }
+  intersect= qh_setnew_delnthsorted(facetA->vertices, qh hull_dim, *skipA, prepend);
+  trace4((qh ferr, 4047, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
+          facetA->id, *skipA, facetB->id, *skipB));
+  return(intersect);
+} /* facetintersect */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="gethash">-</a>
+
+  qh_gethash( hashsize, set, size, firstindex, skipelem )
+    return hashvalue for a set with firstindex and skipelem
+
+  notes:
+    returned hash is in [0,hashsize)
+    assumes at least firstindex+1 elements
+    assumes skipelem is NULL, in set, or part of hash
+
+    hashes memory addresses which may change over different runs of the same data
+    using sum for hash does badly in high d
+*/
+int qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem) {
+  void **elemp= SETelemaddr_(set, firstindex, void);
+  ptr_intT hash = 0, elem;
+  unsigned result;
+  int i;
+#ifdef _MSC_VER                   /* Microsoft Visual C++ -- warn about 64-bit issues */
+#pragma warning( push)            /* WARN64 -- ptr_intT holds a 64-bit pointer */
+#pragma warning( disable : 4311)  /* 'type cast': pointer truncation from 'void*' to 'ptr_intT' */
+#endif
+
+  switch (size-firstindex) {
+  case 1:
+    hash= (ptr_intT)(*elemp) - (ptr_intT) skipelem;
+    break;
+  case 2:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem;
+    break;
+  case 3:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      - (ptr_intT) skipelem;
+    break;
+  case 4:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] - (ptr_intT) skipelem;
+    break;
+  case 5:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem;
+    break;
+  case 6:
+    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
+      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
+      - (ptr_intT) skipelem;
+    break;
+  default:
+    hash= 0;
+    i= 3;
+    do {     /* this is about 10% in 10-d */
+      if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
+        hash ^= (elem << i) + (elem >> (32-i));
+        i += 3;
+        if (i >= 32)
+          i -= 32;
+      }
+    }while (*elemp);
+    break;
+  }
+  if (hashsize<0) {
+    qh_fprintf(qh ferr, 6202, "qhull internal error: negative hashsize %d passed to qh_gethash [poly.c]\n", hashsize);
+    qh_errexit2 (qh_ERRqhull, NULL, NULL);
+  }
+  result= (unsigned)(hash & 0xFFFFFFFFU);
+  result %= (unsigned)hashsize;
+  /* result= 0; for debugging */
+  return result;
+#ifdef _MSC_VER
+#pragma warning( pop)
+#endif
+} /* gethash */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenewfacet">-</a>
+
+  qh_makenewfacet( vertices, toporient, horizon )
+    creates a toporient? facet from vertices
+
+  returns:
+    returns newfacet
+      adds newfacet to qh.facet_list
+      newfacet->vertices= vertices
+      if horizon
+        newfacet->neighbor= horizon, but not vice versa
+    newvertex_list updated with vertices
+*/
+facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) {
+  facetT *newfacet;
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (!vertex->newlist) {
+      qh_removevertex(vertex);
+      qh_appendvertex(vertex);
+    }
+  }
+  newfacet= qh_newfacet();
+  newfacet->vertices= vertices;
+  newfacet->toporient= (unsigned char)toporient;
+  if (horizon)
+    qh_setappend(&(newfacet->neighbors), horizon);
+  qh_appendfacet(newfacet);
+  return(newfacet);
+} /* makenewfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenewplanes">-</a>
+
+  qh_makenewplanes()
+    make new hyperplanes for facets on qh.newfacet_list
+
+  returns:
+    all facets have hyperplanes or are marked for   merging
+    doesn't create hyperplane if horizon is coplanar (will merge)
+    updates qh.min_vertex if qh.JOGGLEmax
+
+  notes:
+    facet->f.samecycle is defined for facet->mergehorizon facets
+*/
+void qh_makenewplanes(void /* newfacet_list */) {
+  facetT *newfacet;
+
+  FORALLnew_facets {
+    if (!newfacet->mergehorizon)
+      qh_setfacetplane(newfacet);
+  }
+  if (qh JOGGLEmax < REALmax/2)
+    minimize_(qh min_vertex, -wwval_(Wnewvertexmax));
+} /* makenewplanes */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenew_nonsimplicial">-</a>
+
+  qh_makenew_nonsimplicial( visible, apex, numnew )
+    make new facets for ridges of a visible facet
+
+  returns:
+    first newfacet, bumps numnew as needed
+    attaches new facets if !qh.ONLYgood
+    marks ridge neighbors for simplicial visible
+    if (qh.ONLYgood)
+      ridges on newfacet, horizon, and visible
+    else
+      ridge and neighbors between newfacet and   horizon
+      visible facet's ridges are deleted
+
+  notes:
+    qh.visit_id if visible has already been processed
+    sets neighbor->seen for building f.samecycle
+      assumes all 'seen' flags initially false
+
+  design:
+    for each ridge of visible facet
+      get neighbor of visible facet
+      if neighbor was already processed
+        delete the ridge (will delete all visible facets later)
+      if neighbor is a horizon facet
+        create a new facet
+        if neighbor coplanar
+          adds newfacet to f.samecycle for later merging
+        else
+          updates neighbor's neighbor set
+          (checks for non-simplicial facet with multiple ridges to visible facet)
+        updates neighbor's ridge set
+        (checks for simplicial neighbor to non-simplicial visible facet)
+        (deletes ridge if neighbor is simplicial)
+
+*/
+#ifndef qh_NOmerge
+facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
+  void **freelistp; /* used !qh_NOmem */
+  ridgeT *ridge, **ridgep;
+  facetT *neighbor, *newfacet= NULL, *samecycle;
+  setT *vertices;
+  boolT toporient;
+  int ridgeid;
+
+  FOREACHridge_(visible->ridges) {
+    ridgeid= ridge->id;
+    neighbor= otherfacet_(ridge, visible);
+    if (neighbor->visible) {
+      if (!qh ONLYgood) {
+        if (neighbor->visitid == qh visit_id) {
+          qh_setfree(&(ridge->vertices));  /* delete on 2nd visit */
+          qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
+        }
+      }
+    }else {  /* neighbor is an horizon facet */
+      toporient= (ridge->top == visible);
+      vertices= qh_setnew(qh hull_dim); /* makes sure this is quick */
+      qh_setappend(&vertices, apex);
+      qh_setappend_set(&vertices, ridge->vertices);
+      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
+      (*numnew)++;
+      if (neighbor->coplanar) {
+        newfacet->mergehorizon= True;
+        if (!neighbor->seen) {
+          newfacet->f.samecycle= newfacet;
+          neighbor->f.newcycle= newfacet;
+        }else {
+          samecycle= neighbor->f.newcycle;
+          newfacet->f.samecycle= samecycle->f.samecycle;
+          samecycle->f.samecycle= newfacet;
+        }
+      }
+      if (qh ONLYgood) {
+        if (!neighbor->simplicial)
+          qh_setappend(&(newfacet->ridges), ridge);
+      }else {  /* qh_attachnewfacets */
+        if (neighbor->seen) {
+          if (neighbor->simplicial) {
+            qh_fprintf(qh ferr, 6105, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n",
+                   neighbor->id, visible->id);
+            qh_errexit2 (qh_ERRqhull, neighbor, visible);
+          }
+          qh_setappend(&(neighbor->neighbors), newfacet);
+        }else
+          qh_setreplace(neighbor->neighbors, visible, newfacet);
+        if (neighbor->simplicial) {
+          qh_setdel(neighbor->ridges, ridge);
+          qh_setfree(&(ridge->vertices));
+          qh_memfree(ridge, (int)sizeof(ridgeT));
+        }else {
+          qh_setappend(&(newfacet->ridges), ridge);
+          if (toporient)
+            ridge->top= newfacet;
+          else
+            ridge->bottom= newfacet;
+        }
+      trace4((qh ferr, 4048, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
+            newfacet->id, apex->id, ridgeid, neighbor->id));
+      }
+    }
+    neighbor->seen= True;
+  } /* for each ridge */
+  if (!qh ONLYgood)
+    SETfirst_(visible->ridges)= NULL;
+  return newfacet;
+} /* makenew_nonsimplicial */
+#else /* qh_NOmerge */
+facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
+  return NULL;
+}
+#endif /* qh_NOmerge */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenew_simplicial">-</a>
+
+  qh_makenew_simplicial( visible, apex, numnew )
+    make new facets for simplicial visible facet and apex
+
+  returns:
+    attaches new facets if (!qh.ONLYgood)
+      neighbors between newfacet and horizon
+
+  notes:
+    nop if neighbor->seen or neighbor->visible(see qh_makenew_nonsimplicial)
+
+  design:
+    locate neighboring horizon facet for visible facet
+    determine vertices and orientation
+    create new facet
+    if coplanar,
+      add new facet to f.samecycle
+    update horizon facet's neighbor list
+*/
+facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew) {
+  facetT *neighbor, **neighborp, *newfacet= NULL;
+  setT *vertices;
+  boolT flip, toporient;
+  int horizonskip=0, visibleskip=0;
+
+  FOREACHneighbor_(visible) {
+    if (!neighbor->seen && !neighbor->visible) {
+      vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1);
+      SETfirst_(vertices)= apex;
+      flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
+      if (neighbor->toporient)
+        toporient= horizonskip & 0x1;
+      else
+        toporient= (horizonskip & 0x1) ^ 0x1;
+      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
+      (*numnew)++;
+      if (neighbor->coplanar && (qh PREmerge || qh MERGEexact)) {
+#ifndef qh_NOmerge
+        newfacet->f.samecycle= newfacet;
+        newfacet->mergehorizon= True;
+#endif
+      }
+      if (!qh ONLYgood)
+        SETelem_(neighbor->neighbors, horizonskip)= newfacet;
+      trace4((qh ferr, 4049, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
+            newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
+              neighbor->toporient, visible->id, visibleskip, flip));
+    }
+  }
+  return newfacet;
+} /* makenew_simplicial */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="matchneighbor">-</a>
+
+  qh_matchneighbor( newfacet, newskip, hashsize, hashcount )
+    either match subridge of newfacet with neighbor or add to hash_table
+
+  returns:
+    duplicate ridges are unmatched and marked by qh_DUPLICATEridge
+
+  notes:
+    ridge is newfacet->vertices w/o newskip vertex
+    do not allocate memory (need to free hash_table cleanly)
+    uses linear hash chains
+
+  see also:
+    qh_matchduplicates
+
+  design:
+    for each possible matching facet in qh.hash_table
+      if vertices match
+        set ismatch, if facets have opposite orientation
+        if ismatch and matching facet doesn't have a match
+          match the facets by updating their neighbor sets
+        else
+          indicate a duplicate ridge
+          set facet hyperplane for later testing
+          add facet to hashtable
+          unless the other facet was already a duplicate ridge
+            mark both facets with a duplicate ridge
+            add other facet (if defined) to hash table
+*/
+void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcount) {
+  boolT newfound= False;   /* True, if new facet is already in hash chain */
+  boolT same, ismatch;
+  int hash, scan;
+  facetT *facet, *matchfacet;
+  int skip, matchskip;
+
+  hash= qh_gethash(hashsize, newfacet->vertices, qh hull_dim, 1,
+                     SETelem_(newfacet->vertices, newskip));
+  trace4((qh ferr, 4050, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
+          newfacet->id, newskip, hash, *hashcount));
+  zinc_(Zhashlookup);
+  for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
+       scan= (++scan >= hashsize ? 0 : scan)) {
+    if (facet == newfacet) {
+      newfound= True;
+      continue;
+    }
+    zinc_(Zhashtests);
+    if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+      if (SETelem_(newfacet->vertices, newskip) ==
+          SETelem_(facet->vertices, skip)) {
+        qh_precision("two facets with the same vertices");
+        qh_fprintf(qh ferr, 6106, "qhull precision error: Vertex sets are the same for f%d and f%d.  Can not force output.\n",
+          facet->id, newfacet->id);
+        qh_errexit2 (qh_ERRprec, facet, newfacet);
+      }
+      ismatch= (same == (boolT)((newfacet->toporient ^ facet->toporient)));
+      matchfacet= SETelemt_(facet->neighbors, skip, facetT);
+      if (ismatch && !matchfacet) {
+        SETelem_(facet->neighbors, skip)= newfacet;
+        SETelem_(newfacet->neighbors, newskip)= facet;
+        (*hashcount)--;
+        trace4((qh ferr, 4051, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
+           facet->id, skip, newfacet->id, newskip));
+        return;
+      }
+      if (!qh PREmerge && !qh MERGEexact) {
+        qh_precision("a ridge with more than two neighbors");
+        qh_fprintf(qh ferr, 6107, "qhull precision error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors.  Can not continue.\n",
+                 facet->id, newfacet->id, getid_(matchfacet));
+        qh_errexit2 (qh_ERRprec, facet, newfacet);
+      }
+      SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
+      newfacet->dupridge= True;
+      if (!newfacet->normal)
+        qh_setfacetplane(newfacet);
+      qh_addhash(newfacet, qh hash_table, hashsize, hash);
+      (*hashcount)++;
+      if (!facet->normal)
+        qh_setfacetplane(facet);
+      if (matchfacet != qh_DUPLICATEridge) {
+        SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
+        facet->dupridge= True;
+        if (!facet->normal)
+          qh_setfacetplane(facet);
+        if (matchfacet) {
+          matchskip= qh_setindex(matchfacet->neighbors, facet);
+          if( matchskip >= 0 )
+          {
+            SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge;
+          }
+          matchfacet->dupridge= True;
+          if (!matchfacet->normal)
+            qh_setfacetplane(matchfacet);
+          qh_addhash(matchfacet, qh hash_table, hashsize, hash);
+          *hashcount += 2;
+        }
+      }
+      trace4((qh ferr, 4052, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
+           newfacet->id, newskip, facet->id, skip,
+           (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)),
+           ismatch, hash));
+      return; /* end of duplicate ridge */
+    }
+  }
+  if (!newfound)
+    SETelem_(qh hash_table, scan)= newfacet;  /* same as qh_addhash */
+  (*hashcount)++;
+  trace4((qh ferr, 4053, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
+           newfacet->id, newskip, hash));
+} /* matchneighbor */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="matchnewfacets">-</a>
+
+  qh_matchnewfacets()
+    match newfacets in qh.newfacet_list to their newfacet neighbors
+
+  returns:
+    qh.newfacet_list with full neighbor sets
+      get vertices with nth neighbor by deleting nth vertex
+    if qh.PREmerge/MERGEexact or qh.FORCEoutput
+      sets facet->flippped if flipped normal (also prevents point partitioning)
+    if duplicate ridges and qh.PREmerge/MERGEexact
+      sets facet->dupridge
+      missing neighbor links identifies extra ridges to be merging (qh_MERGEridge)
+
+  notes:
+    newfacets already have neighbor[0] (horizon facet)
+    assumes qh.hash_table is NULL
+    vertex->neighbors has not been updated yet
+    do not allocate memory after qh.hash_table (need to free it cleanly)
+
+  design:
+    delete neighbor sets for all new facets
+    initialize a hash table
+    for all new facets
+      match facet with neighbors
+    if unmatched facets (due to duplicate ridges)
+      for each new facet with a duplicate ridge
+        match it with a facet
+    check for flipped facets
+*/
+void qh_matchnewfacets(void /* qh newfacet_list */) {
+  int numnew=0, hashcount=0, newskip;
+  facetT *newfacet, *neighbor;
+  int dim= qh hull_dim, hashsize, neighbor_i, neighbor_n;
+  setT *neighbors;
+#ifndef qh_NOtrace
+  int facet_i, facet_n, numfree= 0;
+  facetT *facet;
+#endif
+
+  trace1((qh ferr, 1019, "qh_matchnewfacets: match neighbors for new facets.\n"));
+  FORALLnew_facets {
+    numnew++;
+    {  /* inline qh_setzero(newfacet->neighbors, 1, qh hull_dim); */
+      neighbors= newfacet->neighbors;
+      neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
+      memset((char *)SETelemaddr_(neighbors, 1, void), 0, dim * SETelemsize);
+    }
+  }
+
+  qh_newhashtable(numnew*(qh hull_dim-1)); /* twice what is normally needed,
+                                     but every ridge could be DUPLICATEridge */
+  hashsize= qh_setsize(qh hash_table);
+  FORALLnew_facets {
+    for (newskip=1; newskip<qh hull_dim; newskip++) /* furthest/horizon already matched */
+    {
+      if( hashsize )
+        qh_matchneighbor(newfacet, newskip, hashsize, &hashcount);
+    }
+#if 0   /* use the following to trap hashcount errors */
+    {
+      int count= 0, k;
+      facetT *facet, *neighbor;
+
+      count= 0;
+      FORALLfacet_(qh newfacet_list) {  /* newfacet already in use */
+        for (k=1; k < qh hull_dim; k++) {
+          neighbor= SETelemt_(facet->neighbors, k, facetT);
+          if (!neighbor || neighbor == qh_DUPLICATEridge)
+            count++;
+        }
+        if (facet == newfacet)
+          break;
+      }
+      if (count != hashcount) {
+        qh_fprintf(qh ferr, 8088, "qh_matchnewfacets: after adding facet %d, hashcount %d != count %d\n",
+                 newfacet->id, hashcount, count);
+        qh_errexit(qh_ERRqhull, newfacet, NULL);
+      }
+    }
+#endif  /* end of trap code */
+  }
+  if (hashcount) {
+    FORALLnew_facets {
+      if (newfacet->dupridge) {
+        FOREACHneighbor_i_(newfacet) {
+          if (neighbor == qh_DUPLICATEridge) {
+            qh_matchduplicates(newfacet, neighbor_i, hashsize, &hashcount);
+                    /* this may report MERGEfacet */
+          }
+        }
+      }
+    }
+  }
+  if (hashcount) {
+    qh_fprintf(qh ferr, 6108, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
+        hashcount);
+    qh_printhashtable(qh ferr);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+#ifndef qh_NOtrace
+  if (qh IStracing >= 2) {
+    FOREACHfacet_i_(qh hash_table) {
+      if (!facet)
+        numfree++;
+    }
+    qh_fprintf(qh ferr, 8089, "qh_matchnewfacets: %d new facets, %d unused hash entries .  hashsize %d\n",
+             numnew, numfree, qh_setsize(qh hash_table));
+  }
+#endif /* !qh_NOtrace */
+  qh_setfree(&qh hash_table);
+  if (qh PREmerge || qh MERGEexact) {
+    if (qh IStracing >= 4)
+      qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
+    FORALLnew_facets {
+      if (newfacet->normal)
+        qh_checkflipped(newfacet, NULL, qh_ALL);
+    }
+  }else if (qh FORCEoutput)
+    qh_checkflipped_all(qh newfacet_list);  /* prints warnings for flipped */
+} /* matchnewfacets */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="matchvertices">-</a>
+
+  qh_matchvertices( firstindex, verticesA, skipA, verticesB, skipB, same )
+    tests whether vertices match with a single skip
+    starts match at firstindex since all new facets have a common vertex
+
+  returns:
+    true if matched vertices
+    skip index for each set
+    sets same iff vertices have the same orientation
+
+  notes:
+    assumes skipA is in A and both sets are the same size
+
+  design:
+    set up pointers
+    scan both sets checking for a match
+    test orientation
+*/
+boolT qh_matchvertices(int firstindex, setT *verticesA, int skipA,
+       setT *verticesB, int *skipB, boolT *same) {
+  vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
+
+  elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
+  elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
+  skipAp= SETelemaddr_(verticesA, skipA, vertexT);
+  do if (elemAp != skipAp) {
+    while (*elemAp != *elemBp++) {
+      if (skipBp)
+        return False;
+      skipBp= elemBp;  /* one extra like FOREACH */
+    }
+  }while (*(++elemAp));
+  if (!skipBp)
+    skipBp= ++elemBp;
+  *skipB= SETindex_(verticesB, skipB); /* i.e., skipBp - verticesB */
+  *same= !((skipA & 0x1) ^ (*skipB & 0x1)); /* result is 0 or 1 */
+  trace4((qh ferr, 4054, "qh_matchvertices: matched by skip %d(v%d) and skip %d(v%d) same? %d\n",
+          skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
+  return(True);
+} /* matchvertices */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="newfacet">-</a>
+
+  qh_newfacet()
+    return a new facet
+
+  returns:
+    all fields initialized or cleared   (NULL)
+    preallocates neighbors set
+*/
+facetT *qh_newfacet(void) {
+  facetT *facet;
+  void **freelistp; /* used !qh_NOmem */
+
+  qh_memalloc_((int)sizeof(facetT), freelistp, facet, facetT);
+  memset((char *)facet, (size_t)0, sizeof(facetT));
+  if (qh facet_id == qh tracefacet_id)
+    qh tracefacet= facet;
+  facet->id= qh facet_id++;
+  facet->neighbors= qh_setnew(qh hull_dim);
+#if !qh_COMPUTEfurthest
+  facet->furthestdist= 0.0;
+#endif
+#if qh_MAXoutside
+  if (qh FORCEoutput && qh APPROXhull)
+    facet->maxoutside= qh MINoutside;
+  else
+    facet->maxoutside= qh DISTround;
+#endif
+  facet->simplicial= True;
+  facet->good= True;
+  facet->newfacet= True;
+  trace4((qh ferr, 4055, "qh_newfacet: created facet f%d\n", facet->id));
+  return(facet);
+} /* newfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="newridge">-</a>
+
+  qh_newridge()
+    return a new ridge
+*/
+ridgeT *qh_newridge(void) {
+  ridgeT *ridge;
+  void **freelistp;   /* used !qh_NOmem */
+
+  qh_memalloc_((int)sizeof(ridgeT), freelistp, ridge, ridgeT);
+  memset((char *)ridge, (size_t)0, sizeof(ridgeT));
+  zinc_(Ztotridges);
+  if (qh ridge_id == 0xFFFFFF) {
+    qh_fprintf(qh ferr, 7074, "\
+qhull warning: more than %d ridges.  ID field overflows and two ridges\n\
+may have the same identifier.  Otherwise output ok.\n", 0xFFFFFF);
+  }
+  ridge->id= qh ridge_id++;
+  trace4((qh ferr, 4056, "qh_newridge: created ridge r%d\n", ridge->id));
+  return(ridge);
+} /* newridge */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="pointid">-</a>
+
+  qh_pointid(  )
+    return id for a point,
+    returns -3 if null, -2 if interior, or -1 if not known
+
+  alternative code:
+    unsigned long id;
+    id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
+
+  notes:
+    WARN64 -- id truncated to 32-bits, at most 2G points
+    NOerrors returned (QhullPoint::id)
+    if point not in point array
+      the code does a comparison of unrelated pointers.
+*/
+int qh_pointid(pointT *point) {
+  ptr_intT offset, id;
+
+  if (!point)
+    return -3;
+  else if (point == qh interior_point)
+    return -2;
+  else if (point >= qh first_point
+  && point < qh first_point + qh num_points * qh hull_dim) {
+    offset= (ptr_intT)(point - qh first_point);
+    id= offset / qh hull_dim;
+  }else if ((id= qh_setindex(qh other_points, point)) != -1)
+    id += qh num_points;
+  else
+    return -1;
+  return (int)id;
+} /* pointid */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="removefacet">-</a>
+
+  qh_removefacet( facet )
+    unlinks facet from qh.facet_list,
+
+  returns:
+    updates qh.facet_list .newfacet_list .facet_next visible_list
+    decrements qh.num_facets
+
+  see:
+    qh_appendfacet
+*/
+void qh_removefacet(facetT *facet) {
+  facetT *next= facet->next, *previous= facet->previous;
+
+  if (facet == qh newfacet_list)
+    qh newfacet_list= next;
+  if (facet == qh facet_next)
+    qh facet_next= next;
+  if (facet == qh visible_list)
+    qh visible_list= next;
+  if (previous) {
+    previous->next= next;
+    next->previous= previous;
+  }else {  /* 1st facet in qh facet_list */
+    qh facet_list= next;
+    qh facet_list->previous= NULL;
+  }
+  qh num_facets--;
+  trace4((qh ferr, 4057, "qh_removefacet: remove f%d from facet_list\n", facet->id));
+} /* removefacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="removevertex">-</a>
+
+  qh_removevertex( vertex )
+    unlinks vertex from qh.vertex_list,
+
+  returns:
+    updates qh.vertex_list .newvertex_list
+    decrements qh.num_vertices
+*/
+void qh_removevertex(vertexT *vertex) {
+  vertexT *next= vertex->next, *previous= vertex->previous;
+
+  if (vertex == qh newvertex_list)
+    qh newvertex_list= next;
+  if (previous) {
+    previous->next= next;
+    next->previous= previous;
+  }else {  /* 1st vertex in qh vertex_list */
+    qh vertex_list= vertex->next;
+    qh vertex_list->previous= NULL;
+  }
+  qh num_vertices--;
+  trace4((qh ferr, 4058, "qh_removevertex: remove v%d from vertex_list\n", vertex->id));
+} /* removevertex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="updatevertices">-</a>
+
+  qh_updatevertices()
+    update vertex neighbors and delete interior vertices
+
+  returns:
+    if qh.VERTEXneighbors, updates neighbors for each vertex
+      if qh.newvertex_list,
+         removes visible neighbors  from vertex neighbors
+      if qh.newfacet_list
+         adds new facets to vertex neighbors
+    if qh.visible_list
+       interior vertices added to qh.del_vertices for later partitioning
+
+  design:
+    if qh.VERTEXneighbors
+      deletes references to visible facets from vertex neighbors
+      appends new facets to the neighbor list for each vertex
+      checks all vertices of visible facets
+        removes visible facets from neighbor lists
+        marks unused vertices for deletion
+*/
+void qh_updatevertices(void /*qh newvertex_list, newfacet_list, visible_list*/) {
+  facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
+  vertexT *vertex, **vertexp;
+
+  trace3((qh ferr, 3013, "qh_updatevertices: delete interior vertices and update vertex->neighbors\n"));
+  if (qh VERTEXneighbors) {
+    FORALLvertex_(qh newvertex_list) {
+      FOREACHneighbor_(vertex) {
+        if (neighbor->visible)
+          SETref_(neighbor)= NULL;
+      }
+      qh_setcompact(vertex->neighbors);
+    }
+    FORALLnew_facets {
+      FOREACHvertex_(newfacet->vertices)
+        qh_setappend(&vertex->neighbors, newfacet);
+    }
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newlist && !vertex->deleted) {
+          FOREACHneighbor_(vertex) { /* this can happen under merging */
+            if (!neighbor->visible)
+              break;
+          }
+          if (neighbor)
+            qh_setdel(vertex->neighbors, visible);
+          else {
+            vertex->deleted= True;
+            qh_setappend(&qh del_vertices, vertex);
+            trace2((qh ferr, 2041, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
+                  qh_pointid(vertex->point), vertex->id, visible->id));
+          }
+        }
+      }
+    }
+  }else {  /* !VERTEXneighbors */
+    FORALLvisible_facets {
+      FOREACHvertex_(visible->vertices) {
+        if (!vertex->newlist && !vertex->deleted) {
+          vertex->deleted= True;
+          qh_setappend(&qh del_vertices, vertex);
+          trace2((qh ferr, 2042, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
+                  qh_pointid(vertex->point), vertex->id, visible->id));
+        }
+      }
+    }
+  }
+} /* updatevertices */
diff --git a/alg/libqhull/poly.h b/alg/internal_libqhull/poly.h
similarity index 100%
rename from alg/libqhull/poly.h
rename to alg/internal_libqhull/poly.h
diff --git a/alg/internal_libqhull/poly2.c b/alg/internal_libqhull/poly2.c
new file mode 100644
index 0000000..2d3ee25
--- /dev/null
+++ b/alg/internal_libqhull/poly2.c
@@ -0,0 +1,3157 @@
+/*<html><pre>  -<a                             href="qh-poly.htm"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   poly2.c
+   implements polygons and simplices
+
+   see qh-poly.htm, poly.h and libqhull.h
+
+   frequently used code is in poly.c
+
+   Copyright (c) 1993-2012 The Geometry Center.
+   $Id: //main/2011/qhull/src/libqhull/poly2.c#5 $$Change: 1490 $
+   $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
+*/
+
+#include "qhull_a.h"
+
+/*======== functions in alphabetical order ==========*/
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="addhash">-</a>
+
+  qh_addhash( newelem, hashtable, hashsize, hash )
+    add newelem to linear hash table at hash if not already there
+*/
+void qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash) {
+  int scan;
+  void *elem;
+
+  for (scan= (int)hash; (elem= SETelem_(hashtable, scan));
+       scan= (++scan >= hashsize ? 0 : scan)) {
+    if (elem == newelem)
+      break;
+  }
+  /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
+  if (!elem)
+    SETelem_(hashtable, scan)= newelem;
+} /* addhash */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_bestdist">-</a>
+
+  qh_check_bestdist()
+    check that all points are within max_outside of the nearest facet
+    if qh.ONLYgood,
+      ignores !good facets
+
+  see:
+    qh_check_maxout(), qh_outerinner()
+
+  notes:
+    only called from qh_check_points()
+      seldom used since qh.MERGING is almost always set
+    if notverified>0 at end of routine
+      some points were well inside the hull.  If the hull contains
+      a lens-shaped component, these points were not verified.  Use
+      options 'Qi Tv' to verify all points.  (Exhaustive check also verifies)
+
+  design:
+    determine facet for each point (if any)
+    for each point
+      start with the assigned facet or with the first facet
+      find the best facet for the point and check all coplanar facets
+      error if point is outside of facet
+*/
+void qh_check_bestdist(void) {
+  boolT waserror= False, unassigned;
+  facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
+  facetT *facetlist;
+  realT dist, maxoutside, maxdist= -REALmax;
+  pointT *point;
+  int numpart= 0, facet_i, facet_n, notgood= 0, notverified= 0;
+  setT *facets;
+
+  trace1((qh ferr, 1020, "qh_check_bestdist: check points below nearest facet.  Facet_list f%d\n",
+      qh facet_list->id));
+  maxoutside= qh_maxouter();
+  maxoutside += qh DISTround;
+  /* one more qh.DISTround for check computation */
+  trace1((qh ferr, 1021, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
+  facets= qh_pointfacet(/*qh facet_list*/);
+  if (!qh_QUICKhelp && qh PRINTprecision)
+    qh_fprintf(qh ferr, 8091, "\n\
+qhull output completed.  Verifying that %d points are\n\
+below %2.2g of the nearest %sfacet.\n",
+             qh_setsize(facets), maxoutside, (qh ONLYgood ?  "good " : ""));
+  FOREACHfacet_i_(facets) {  /* for each point with facet assignment */
+    if (facet)
+      unassigned= False;
+    else {
+      unassigned= True;
+      facet= qh facet_list;
+    }
+    point= qh_point(facet_i);
+    if (point == qh GOODpointp)
+      continue;
+    qh_distplane(point, facet, &dist);
+    numpart++;
+    bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, facet, qh_NOupper, &dist, &numpart);
+    /* occurs after statistics reported */
+    maximize_(maxdist, dist);
+    if (dist > maxoutside) {
+      if (qh ONLYgood && !bestfacet->good
+          && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
+               && dist > maxoutside))
+        notgood++;
+      else {
+        waserror= True;
+        qh_fprintf(qh ferr, 6109, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
+                facet_i, bestfacet->id, dist, maxoutside);
+        if (errfacet1 != bestfacet) {
+          errfacet2= errfacet1;
+          errfacet1= bestfacet;
+        }
+      }
+    }else if (unassigned && dist < -qh MAXcoplanar)
+      notverified++;
+  }
+  qh_settempfree(&facets);
+  if (notverified && !qh DELAUNAY && !qh_QUICKhelp && qh PRINTprecision)
+    qh_fprintf(qh ferr, 8092, "\n%d points were well inside the hull.  If the hull contains\n\
+a lens-shaped component, these points were not verified.  Use\n\
+options 'Qci Tv' to verify all points.\n", notverified);
+  if (maxdist > qh outside_err) {
+    qh_fprintf(qh ferr, 6110, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull.  The maximum value(qh.outside_err) is %6.2g\n",
+              maxdist, qh outside_err);
+    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+  }else if (waserror && qh outside_err > REALmax/2)
+    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+  /* else if waserror, the error was logged to qh.ferr but does not effect the output */
+  trace0((qh ferr, 20, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
+} /* check_bestdist */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_maxout">-</a>
+
+  qh_check_maxout()
+    updates qh.max_outside by checking all points against bestfacet
+    if qh.ONLYgood, ignores !good facets
+
+  returns:
+    updates facet->maxoutside via qh_findbesthorizon()
+    sets qh.maxoutdone
+    if printing qh.min_vertex (qh_outerinner),
+      it is updated to the current vertices
+    removes inside/coplanar points from coplanarset as needed
+
+  notes:
+    defines coplanar as min_vertex instead of MAXcoplanar
+    may not need to check near-inside points because of qh.MAXcoplanar
+      and qh.KEEPnearinside (before it was -DISTround)
+
+  see also:
+    qh_check_bestdist()
+
+  design:
+    if qh.min_vertex is needed
+      for all neighbors of all vertices
+        test distance from vertex to neighbor
+    determine facet for each point (if any)
+    for each point with an assigned facet
+      find the best facet for the point and check all coplanar facets
+        (updates outer planes)
+    remove near-inside points from coplanar sets
+*/
+#ifndef qh_NOmerge
+void qh_check_maxout(void) {
+  facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist;
+  realT dist, maxoutside, minvertex, old_maxoutside;
+  pointT *point;
+  int numpart= 0, facet_i, facet_n, notgood= 0;
+  setT *facets, *vertices;
+  vertexT *vertex;
+
+  trace1((qh ferr, 1022, "qh_check_maxout: check and update maxoutside for each facet.\n"));
+  maxoutside= minvertex= 0;
+  if (qh VERTEXneighbors
+  && (qh PRINTsummary || qh KEEPinside || qh KEEPcoplanar
+        || qh TRACElevel || qh PRINTstatistics
+        || qh PRINTout[0] == qh_PRINTsummary || qh PRINTout[0] == qh_PRINTnone)) {
+    trace1((qh ferr, 1023, "qh_check_maxout: determine actual maxoutside and minvertex\n"));
+    vertices= qh_pointvertex(/*qh facet_list*/);
+    FORALLvertices {
+      FOREACHneighbor_(vertex) {
+        zinc_(Zdistvertex);  /* distance also computed by main loop below */
+        qh_distplane(vertex->point, neighbor, &dist);
+        minimize_(minvertex, dist);
+        if (-dist > qh TRACEdist || dist > qh TRACEdist
+        || neighbor == qh tracefacet || vertex == qh tracevertex)
+          qh_fprintf(qh ferr, 8093, "qh_check_maxout: p%d(v%d) is %.2g from f%d\n",
+                    qh_pointid(vertex->point), vertex->id, dist, neighbor->id);
+      }
+    }
+    if (qh MERGING) {
+      wmin_(Wminvertex, qh min_vertex);
+    }
+    qh min_vertex= minvertex;
+    qh_settempfree(&vertices);
+  }
+  facets= qh_pointfacet(/*qh facet_list*/);
+  do {
+    old_maxoutside= fmax_(qh max_outside, maxoutside);
+    FOREACHfacet_i_(facets) {     /* for each point with facet assignment */
+      if (facet) {
+        point= qh_point(facet_i);
+        if (point == qh GOODpointp)
+          continue;
+        zzinc_(Ztotcheck);
+        qh_distplane(point, facet, &dist);
+        numpart++;
+        bestfacet= qh_findbesthorizon(qh_IScheckmax, point, facet, !qh_NOupper, &dist, &numpart);
+        if (bestfacet && dist > maxoutside) {
+          if (qh ONLYgood && !bestfacet->good
+          && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
+               && dist > maxoutside))
+            notgood++;
+          else
+            maxoutside= dist;
+        }
+        if (dist > qh TRACEdist || (bestfacet && bestfacet == qh tracefacet))
+          qh_fprintf(qh ferr, 8094, "qh_check_maxout: p%d is %.2g above f%d\n",
+                     qh_pointid(point), dist, bestfacet ? (int)bestfacet->id : -1);
+      }
+    }
+  }while
+    (maxoutside > 2*old_maxoutside);
+    /* if qh.maxoutside increases substantially, qh_SEARCHdist is not valid
+          e.g., RBOX 5000 s Z1 G1e-13 t1001200614 | qhull */
+  zzadd_(Zcheckpart, numpart);
+  qh_settempfree(&facets);
+  wval_(Wmaxout)= maxoutside - qh max_outside;
+  wmax_(Wmaxoutside, qh max_outside);
+  qh max_outside= maxoutside;
+  qh_nearcoplanar(/*qh.facet_list*/);
+  qh maxoutdone= True;
+  trace1((qh ferr, 1024, "qh_check_maxout: maxoutside %2.2g, min_vertex %2.2g, outside of not good %d\n",
+       maxoutside, qh min_vertex, notgood));
+} /* check_maxout */
+#else /* qh_NOmerge */
+void qh_check_maxout(void) {
+}
+#endif
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_output">-</a>
+
+  qh_check_output()
+    performs the checks at the end of qhull algorithm
+    Maybe called after voronoi output.  Will recompute otherwise centrums are Voronoi centers instead
+*/
+void qh_check_output(void) {
+  int i;
+
+  if (qh STOPcone)
+    return;
+  if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
+    qh_checkpolygon(qh facet_list);
+    qh_checkflipped_all(qh facet_list);
+    qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
+  }else if (!qh MERGING && qh_newstats(qhstat precision, &i)) {
+    qh_checkflipped_all(qh facet_list);
+    qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
+  }
+} /* check_output */
+
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_point">-</a>
+
+  qh_check_point( point, facet, maxoutside, maxdist, errfacet1, errfacet2 )
+    check that point is less than maxoutside from facet
+*/
+void qh_check_point(pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2) {
+  realT dist;
+
+  /* occurs after statistics reported */
+  qh_distplane(point, facet, &dist);
+  if (dist > *maxoutside) {
+    if (*errfacet1 != facet) {
+      *errfacet2= *errfacet1;
+      *errfacet1= facet;
+    }
+    qh_fprintf(qh ferr, 6111, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
+              qh_pointid(point), facet->id, dist, *maxoutside);
+  }
+  maximize_(*maxdist, dist);
+} /* qh_check_point */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="check_points">-</a>
+
+  qh_check_points()
+    checks that all points are inside all facets
+
+  notes:
+    if many points and qh_check_maxout not called (i.e., !qh.MERGING),
+       calls qh_findbesthorizon (seldom done).
+    ignores flipped facets
+    maxoutside includes 2 qh.DISTrounds
+      one qh.DISTround for the computed distances in qh_check_points
+    qh_printafacet and qh_printsummary needs only one qh.DISTround
+    the computation for qh.VERIFYdirect does not account for qh.other_points
+
+  design:
+    if many points
+      use qh_check_bestdist()
+    else
+      for all facets
+        for all points
+          check that point is inside facet
+*/
+void qh_check_points(void) {
+  facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
+  realT total, maxoutside, maxdist= -REALmax;
+  pointT *point, **pointp, *pointtemp;
+  boolT testouter;
+
+  maxoutside= qh_maxouter();
+  maxoutside += qh DISTround;
+  /* one more qh.DISTround for check computation */
+  trace1((qh ferr, 1025, "qh_check_points: check all points below %2.2g of all facet planes\n",
+          maxoutside));
+  if (qh num_good)   /* miss counts other_points and !good facets */
+     total= (float)qh num_good * (float)qh num_points;
+  else
+     total= (float)qh num_facets * (float)qh num_points;
+  if (total >= qh_VERIFYdirect && !qh maxoutdone) {
+    if (!qh_QUICKhelp && qh SKIPcheckmax && qh MERGING)
+      qh_fprintf(qh ferr, 7075, "qhull input warning: merging without checking outer planes('Q5' or 'Po').\n\
+Verify may report that a point is outside of a facet.\n");
+    qh_check_bestdist();
+  }else {
+    if (qh_MAXoutside && qh maxoutdone)
+      testouter= True;
+    else
+      testouter= False;
+    if (!qh_QUICKhelp) {
+      if (qh MERGEexact)
+        qh_fprintf(qh ferr, 7076, "qhull input warning: exact merge ('Qx').  Verify may report that a point\n\
+is outside of a facet.  See qh-optq.htm#Qx\n");
+      else if (qh SKIPcheckmax || qh NOnearinside)
+        qh_fprintf(qh ferr, 7077, "qhull input warning: no outer plane check ('Q5') or no processing of\n\
+near-inside points ('Q8').  Verify may report that a point is outside\n\
+of a facet.\n");
+    }
+    if (qh PRINTprecision) {
+      if (testouter)
+        qh_fprintf(qh ferr, 8098, "\n\
+Output completed.  Verifying that all points are below outer planes of\n\
+all %sfacets.  Will make %2.0f distance computations.\n",
+              (qh ONLYgood ?  "good " : ""), total);
+      else
+        qh_fprintf(qh ferr, 8099, "\n\
+Output completed.  Verifying that all points are below %2.2g of\n\
+all %sfacets.  Will make %2.0f distance computations.\n",
+              maxoutside, (qh ONLYgood ?  "good " : ""), total);
+    }
+    FORALLfacets {
+      if (!facet->good && qh ONLYgood)
+        continue;
+      if (facet->flipped)
+        continue;
+      if (!facet->normal) {
+        qh_fprintf(qh ferr, 7061, "qhull warning (qh_check_points): missing normal for facet f%d\n", facet->id);
+        continue;
+      }
+      if (testouter) {
+#if qh_MAXoutside
+        maxoutside= facet->maxoutside + 2* qh DISTround;
+        /* one DISTround to actual point and another to computed point */
+#endif
+      }
+      FORALLpoints {
+        if (point != qh GOODpointp)
+          qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
+      }
+      FOREACHpoint_(qh other_points) {
+        if (point != qh GOODpointp)
+          qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
+      }
+    }
+    if (maxdist > qh outside_err) {
+      qh_fprintf(qh ferr, 6112, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull.  The maximum value(qh.outside_err) is %6.2g\n",
+                maxdist, qh outside_err );
+      qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
+    }else if (errfacet1 && qh outside_err > REALmax/2)
+        qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
+    /* else if errfacet1, the error was logged to qh.ferr but does not effect the output */
+    trace0((qh ferr, 21, "qh_check_points: max distance outside %2.2g\n", maxdist));
+  }
+} /* check_points */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkconvex">-</a>
+
+  qh_checkconvex( facetlist, fault )
+    check that each ridge in facetlist is convex
+    fault = qh_DATAfault if reporting errors
+          = qh_ALGORITHMfault otherwise
+
+  returns:
+    counts Zconcaveridges and Zcoplanarridges
+    errors if concaveridge or if merging an coplanar ridge
+
+  note:
+    if not merging,
+      tests vertices for neighboring simplicial facets
+    else if ZEROcentrum,
+      tests vertices for neighboring simplicial   facets
+    else
+      tests centrums of neighboring facets
+
+  design:
+    for all facets
+      report flipped facets
+      if ZEROcentrum and simplicial neighbors
+        test vertices for neighboring simplicial facets
+      else
+        test centrum against all neighbors
+*/
+void qh_checkconvex(facetT *facetlist, int fault) {
+  facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
+  vertexT *vertex;
+  realT dist;
+  pointT *centrum;
+  boolT waserror= False, centrum_warning= False, tempcentrum= False, allsimplicial;
+  int neighbor_i;
+
+  trace1((qh ferr, 1026, "qh_checkconvex: check all ridges are convex\n"));
+  if (!qh RERUN) {
+    zzval_(Zconcaveridges)= 0;
+    zzval_(Zcoplanarridges)= 0;
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->flipped) {
+      qh_precision("flipped facet");
+      qh_fprintf(qh ferr, 6113, "qhull precision error: f%d is flipped(interior point is outside)\n",
+               facet->id);
+      errfacet1= facet;
+      waserror= True;
+      continue;
+    }
+    if (qh MERGING && (!qh ZEROcentrum || !facet->simplicial || facet->tricoplanar))
+      allsimplicial= False;
+    else {
+      allsimplicial= True;
+      neighbor_i= 0;
+      FOREACHneighbor_(facet) {
+        vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
+        if (!neighbor->simplicial || neighbor->tricoplanar) {
+          allsimplicial= False;
+          continue;
+        }
+        qh_distplane(vertex->point, neighbor, &dist);
+        if (dist > -qh DISTround) {
+          if (fault == qh_DATAfault) {
+            qh_precision("coplanar or concave ridge");
+            qh_fprintf(qh ferr, 6114, "qhull precision error: initial simplex is not convex. Distance=%.2g\n", dist);
+            qh_errexit(qh_ERRsingular, NULL, NULL);
+          }
+          if (dist > qh DISTround) {
+            zzinc_(Zconcaveridges);
+            qh_precision("concave ridge");
+            qh_fprintf(qh ferr, 6115, "qhull precision error: f%d is concave to f%d, since p%d(v%d) is %6.4g above\n",
+              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
+            errfacet1= facet;
+            errfacet2= neighbor;
+            waserror= True;
+          }else if (qh ZEROcentrum) {
+            if (dist > 0) {     /* qh_checkzero checks that dist < - qh DISTround */
+              zzinc_(Zcoplanarridges);
+              qh_precision("coplanar ridge");
+              qh_fprintf(qh ferr, 6116, "qhull precision error: f%d is clearly not convex to f%d, since p%d(v%d) is %6.4g above\n",
+                facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
+              errfacet1= facet;
+              errfacet2= neighbor;
+              waserror= True;
+            }
+          }else {
+            zzinc_(Zcoplanarridges);
+            qh_precision("coplanar ridge");
+            trace0((qh ferr, 22, "qhull precision error: f%d may be coplanar to f%d, since p%d(v%d) is within %6.4g during p%d\n",
+              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist, qh furthest_id));
+          }
+        }
+      }
+    }
+    if (!allsimplicial) {
+      if (qh CENTERtype == qh_AScentrum) {
+        if (!facet->center)
+          facet->center= qh_getcentrum(facet);
+        centrum= facet->center;
+      }else {
+        if (!centrum_warning && (!facet->simplicial || facet->tricoplanar)) {
+           centrum_warning= True;
+           qh_fprintf(qh ferr, 7062, "qhull warning: recomputing centrums for convexity test.  This may lead to false, precision errors.\n");
+        }
+        centrum= qh_getcentrum(facet);
+        tempcentrum= True;
+      }
+      FOREACHneighbor_(facet) {
+        if (qh ZEROcentrum && facet->simplicial && neighbor->simplicial)
+          continue;
+        if (facet->tricoplanar || neighbor->tricoplanar)
+          continue;
+        zzinc_(Zdistconvex);
+        qh_distplane(centrum, neighbor, &dist);
+        if (dist > qh DISTround) {
+          zzinc_(Zconcaveridges);
+          qh_precision("concave ridge");
+          qh_fprintf(qh ferr, 6117, "qhull precision error: f%d is concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
+            facet->id, neighbor->id, facet->id, dist, neighbor->id);
+          errfacet1= facet;
+          errfacet2= neighbor;
+          waserror= True;
+        }else if (dist >= 0.0) {   /* if arithmetic always rounds the same,
+                                     can test against centrum radius instead */
+          zzinc_(Zcoplanarridges);
+          qh_precision("coplanar ridge");
+          qh_fprintf(qh ferr, 6118, "qhull precision error: f%d is coplanar or concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
+            facet->id, neighbor->id, facet->id, dist, neighbor->id);
+          errfacet1= facet;
+          errfacet2= neighbor;
+          waserror= True;
+        }
+      }
+      if (tempcentrum)
+        qh_memfree(centrum, qh normal_size);
+    }
+  }
+  if (waserror && !qh FORCEoutput)
+    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
+} /* checkconvex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkfacet">-</a>
+
+  qh_checkfacet( facet, newmerge, waserror )
+    checks for consistency errors in facet
+    newmerge set if from merge.c
+
+  returns:
+    sets waserror if any error occurs
+
+  checks:
+    vertex ids are inverse sorted
+    unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
+    if non-simplicial, at least as many ridges as neighbors
+    neighbors are not duplicated
+    ridges are not duplicated
+    in 3-d, ridges=vertices
+    (qh.hull_dim-1) ridge vertices
+    neighbors are reciprocated
+    ridge neighbors are facet neighbors and a ridge for every neighbor
+    simplicial neighbors match facetintersect
+    vertex intersection matches vertices of common ridges
+    vertex neighbors and facet vertices agree
+    all ridges have distinct vertex sets
+
+  notes:
+    uses neighbor->seen
+
+  design:
+    check sets
+    check vertices
+    check sizes of neighbors and vertices
+    check for qh_MERGEridge and qh_DUPLICATEridge flags
+    check neighbor set
+    check ridge set
+    check ridges, neighbors, and vertices
+*/
+void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
+  facetT *neighbor, **neighborp, *errother=NULL;
+  ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
+  vertexT *vertex, **vertexp;
+  unsigned previousid= INT_MAX;
+  int numneighbors, numvertices, numridges=0, numRvertices=0;
+  boolT waserror= False;
+  int skipA, skipB, ridge_i, ridge_n, i;
+  setT *intersection;
+
+  if (facet->visible) {
+    qh_fprintf(qh ferr, 6119, "qhull internal error (qh_checkfacet): facet f%d is on the visible_list\n",
+      facet->id);
+    qh_errexit(qh_ERRqhull, facet, NULL);
+  }
+  if (!facet->normal) {
+    qh_fprintf(qh ferr, 6120, "qhull internal error (qh_checkfacet): facet f%d does not have  a normal\n",
+      facet->id);
+    waserror= True;
+  }
+  qh_setcheck(facet->vertices, "vertices for f", facet->id);
+  qh_setcheck(facet->ridges, "ridges for f", facet->id);
+  qh_setcheck(facet->outsideset, "outsideset for f", facet->id);
+  qh_setcheck(facet->coplanarset, "coplanarset for f", facet->id);
+  qh_setcheck(facet->neighbors, "neighbors for f", facet->id);
+  FOREACHvertex_(facet->vertices) {
+    if (vertex->deleted) {
+      qh_fprintf(qh ferr, 6121, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
+      qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
+      waserror= True;
+    }
+    if (vertex->id >= previousid) {
+      qh_fprintf(qh ferr, 6122, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
+      waserror= True;
+      break;
+    }
+    previousid= vertex->id;
+  }
+  numneighbors= qh_setsize(facet->neighbors);
+  numvertices= qh_setsize(facet->vertices);
+  numridges= qh_setsize(facet->ridges);
+  if (facet->simplicial) {
+    if (numvertices+numneighbors != 2*qh hull_dim
+    && !facet->degenerate && !facet->redundant) {
+      qh_fprintf(qh ferr, 6123, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n",
+                facet->id, numvertices, numneighbors);
+      qh_setprint(qh ferr, "", facet->neighbors);
+      waserror= True;
+    }
+  }else { /* non-simplicial */
+    if (!newmerge
+    &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
+    && !facet->degenerate && !facet->redundant) {
+      qh_fprintf(qh ferr, 6124, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
+         facet->id, numvertices, numneighbors);
+       waserror= True;
+    }
+    /* in 3-d, can get a vertex twice in an edge list, e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv TP624 TW1e-13 T4 */
+    if (numridges < numneighbors
+    ||(qh hull_dim == 3 && numvertices > numridges && !qh NEWfacets)
+    ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
+      if (!facet->degenerate && !facet->redundant) {
+        qh_fprintf(qh ferr, 6125, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or(3-d) > #vertices %d or(2-d) not all 2\n",
+            facet->id, numridges, numneighbors, numvertices);
+        waserror= True;
+      }
+    }
+  }
+  FOREACHneighbor_(facet) {
+    if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
+      qh_fprintf(qh ferr, 6126, "qhull internal error (qh_checkfacet): facet f%d still has a MERGE or DUP neighbor\n", facet->id);
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+    neighbor->seen= True;
+  }
+  FOREACHneighbor_(facet) {
+    if (!qh_setin(neighbor->neighbors, facet)) {
+      qh_fprintf(qh ferr, 6127, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
+              facet->id, neighbor->id, neighbor->id, facet->id);
+      errother= neighbor;
+      waserror= True;
+    }
+    if (!neighbor->seen) {
+      qh_fprintf(qh ferr, 6128, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
+              facet->id, neighbor->id);
+      errother= neighbor;
+      waserror= True;
+    }
+    neighbor->seen= False;
+  }
+  FOREACHridge_(facet->ridges) {
+    qh_setcheck(ridge->vertices, "vertices for r", ridge->id);
+    ridge->seen= False;
+  }
+  FOREACHridge_(facet->ridges) {
+    if (ridge->seen) {
+      qh_fprintf(qh ferr, 6129, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
+              facet->id, ridge->id);
+      errridge= ridge;
+      waserror= True;
+    }
+    ridge->seen= True;
+    numRvertices= qh_setsize(ridge->vertices);
+    if (numRvertices != qh hull_dim - 1) {
+      qh_fprintf(qh ferr, 6130, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n",
+                ridge->top->id, ridge->bottom->id, numRvertices);
+      errridge= ridge;
+      waserror= True;
+    }
+    neighbor= otherfacet_(ridge, facet);
+    neighbor->seen= True;
+    if (!qh_setin(facet->neighbors, neighbor)) {
+      qh_fprintf(qh ferr, 6131, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
+           facet->id, neighbor->id, ridge->id);
+      errridge= ridge;
+      waserror= True;
+    }
+  }
+  if (!facet->simplicial) {
+    FOREACHneighbor_(facet) {
+      if (!neighbor->seen) {
+        qh_fprintf(qh ferr, 6132, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
+              facet->id, neighbor->id);
+        errother= neighbor;
+        waserror= True;
+      }
+      intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
+      qh_settemppush(intersection);
+      FOREACHvertex_(facet->vertices) {
+        vertex->seen= False;
+        vertex->seen2= False;
+      }
+      FOREACHvertex_(intersection)
+        vertex->seen= True;
+      FOREACHridge_(facet->ridges) {
+        if (neighbor != otherfacet_(ridge, facet))
+            continue;
+        FOREACHvertex_(ridge->vertices) {
+          if (!vertex->seen) {
+            qh_fprintf(qh ferr, 6133, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
+                  vertex->id, ridge->id, facet->id, neighbor->id);
+            qh_errexit(qh_ERRqhull, facet, ridge);
+          }
+          vertex->seen2= True;
+        }
+      }
+      if (!newmerge) {
+        FOREACHvertex_(intersection) {
+          if (!vertex->seen2) {
+            if (qh IStracing >=3 || !qh MERGING) {
+              qh_fprintf(qh ferr, 6134, "qhull precision error (qh_checkfacet): vertex v%d in f%d intersect f%d but\n\
+ not in a ridge.  This is ok under merging.  Last point was p%d\n",
+                     vertex->id, facet->id, neighbor->id, qh furthest_id);
+              if (!qh FORCEoutput && !qh MERGING) {
+                qh_errprint("ERRONEOUS", facet, neighbor, NULL, vertex);
+                if (!qh MERGING)
+                  qh_errexit(qh_ERRqhull, NULL, NULL);
+              }
+            }
+          }
+        }
+      }
+      qh_settempfree(&intersection);
+    }
+  }else { /* simplicial */
+    FOREACHneighbor_(facet) {
+      if (neighbor->simplicial) {
+        skipA= SETindex_(facet->neighbors, neighbor);
+        skipB= qh_setindex(neighbor->neighbors, facet);
+        if (skipB >= 0 && !qh_setequal_skip(facet->vertices, skipA, neighbor->vertices, skipB)) {
+          qh_fprintf(qh ferr, 6135, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
+                   facet->id, skipA, neighbor->id, skipB);
+          errother= neighbor;
+          waserror= True;
+        }
+      }
+    }
+  }
+  if (qh hull_dim < 5 && (qh IStracing > 2 || qh CHECKfrequently)) {
+    FOREACHridge_i_(facet->ridges) {           /* expensive */
+      for (i=ridge_i+1; i < ridge_n; i++) {
+        ridge2= SETelemt_(facet->ridges, i, ridgeT);
+        if (qh_setequal(ridge->vertices, ridge2->vertices)) {
+          qh_fprintf(qh ferr, 6227, "Qhull internal error (qh_checkfacet): ridges r%d and r%d have the same vertices\n",
+                  ridge->id, ridge2->id);
+          errridge= ridge;
+          waserror= True;
+        }
+      }
+    }
+  }
+  if (waserror) {
+    qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
+    *waserrorp= True;
+  }
+} /* checkfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkflipped_all">-</a>
+
+  qh_checkflipped_all( facetlist )
+    checks orientation of facets in list against interior point
+*/
+void qh_checkflipped_all(facetT *facetlist) {
+  facetT *facet;
+  boolT waserror= False;
+  realT dist;
+
+  if (facetlist == qh facet_list)
+    zzval_(Zflippedfacets)= 0;
+  FORALLfacet_(facetlist) {
+    if (facet->normal && !qh_checkflipped(facet, &dist, !qh_ALL)) {
+      qh_fprintf(qh ferr, 6136, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
+              facet->id, dist);
+      if (!qh FORCEoutput) {
+        qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
+        waserror= True;
+      }
+    }
+  }
+  if (waserror) {
+    qh_fprintf(qh ferr, 8101, "\n\
+A flipped facet occurs when its distance to the interior point is\n\
+greater than %2.2g, the maximum roundoff error.\n", -qh DISTround);
+    qh_errexit(qh_ERRprec, NULL, NULL);
+  }
+} /* checkflipped_all */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkpolygon">-</a>
+
+  qh_checkpolygon( facetlist )
+    checks the correctness of the structure
+
+  notes:
+    call with either qh.facet_list or qh.newfacet_list
+    checks num_facets and num_vertices if qh.facet_list
+
+  design:
+    for each facet
+      checks facet and outside set
+    initializes vertexlist
+    for each facet
+      checks vertex set
+    if checking all facets(qh.facetlist)
+      check facet count
+      if qh.VERTEXneighbors
+        check vertex neighbors and count
+      check vertex count
+*/
+void qh_checkpolygon(facetT *facetlist) {
+  facetT *facet;
+  vertexT *vertex, **vertexp, *vertexlist;
+  int numfacets= 0, numvertices= 0, numridges= 0;
+  int totvneighbors= 0, totvertices= 0;
+  boolT waserror= False, nextseen= False, visibleseen= False;
+
+  trace1((qh ferr, 1027, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
+  if (facetlist != qh facet_list || qh ONLYgood)
+    nextseen= True;
+  FORALLfacet_(facetlist) {
+    if (facet == qh visible_list)
+      visibleseen= True;
+    if (!facet->visible) {
+      if (!nextseen) {
+        if (facet == qh facet_next)
+          nextseen= True;
+        else if (qh_setsize(facet->outsideset)) {
+          if (!qh NARROWhull
+#if !qh_COMPUTEfurthest
+               || facet->furthestdist >= qh MINoutside
+#endif
+                        ) {
+            qh_fprintf(qh ferr, 6137, "qhull internal error (qh_checkpolygon): f%d has outside points before qh facet_next\n",
+                     facet->id);
+            qh_errexit(qh_ERRqhull, facet, NULL);
+          }
+        }
+      }
+      numfacets++;
+      qh_checkfacet(facet, False, &waserror);
+    }
+  }
+  if (qh visible_list && !visibleseen && facetlist == qh facet_list) {
+    qh_fprintf(qh ferr, 6138, "qhull internal error (qh_checkpolygon): visible list f%d no longer on facet list\n", qh visible_list->id);
+    qh_printlists();
+    qh_errexit(qh_ERRqhull, qh visible_list, NULL);
+  }
+  if (facetlist == qh facet_list)
+    vertexlist= qh vertex_list;
+  else if (facetlist == qh newfacet_list)
+    vertexlist= qh newvertex_list;
+  else
+    vertexlist= NULL;
+  FORALLvertex_(vertexlist) {
+    vertex->seen= False;
+    vertex->visitid= 0;
+  }
+  FORALLfacet_(facetlist) {
+    if (facet->visible)
+      continue;
+    if (facet->simplicial)
+      numridges += qh hull_dim;
+    else
+      numridges += qh_setsize(facet->ridges);
+    FOREACHvertex_(facet->vertices) {
+      vertex->visitid++;
+      if (!vertex->seen) {
+        vertex->seen= True;
+        numvertices++;
+        if (qh_pointid(vertex->point) == -1) {
+          qh_fprintf(qh ferr, 6139, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
+                   vertex->point, vertex->id, qh first_point);
+          waserror= True;
+        }
+      }
+    }
+  }
+  qh vertex_visit += (unsigned int)numfacets;
+  if (facetlist == qh facet_list) {
+    if (numfacets != qh num_facets - qh num_visible) {
+      qh_fprintf(qh ferr, 6140, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d - %d visible facets\n",
+              numfacets, qh num_facets, qh num_visible);
+      waserror= True;
+    }
+    qh vertex_visit++;
+    if (qh VERTEXneighbors) {
+      FORALLvertices {
+        qh_setcheck(vertex->neighbors, "neighbors for v", vertex->id);
+        if (vertex->deleted)
+          continue;
+        totvneighbors += qh_setsize(vertex->neighbors);
+      }
+      FORALLfacet_(facetlist)
+        totvertices += qh_setsize(facet->vertices);
+      if (totvneighbors != totvertices) {
+        qh_fprintf(qh ferr, 6141, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent.  Totvneighbors %d, totvertices %d\n",
+                totvneighbors, totvertices);
+        waserror= True;
+      }
+    }
+    if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
+      qh_fprintf(qh ferr, 6142, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
+              numvertices, qh num_vertices - qh_setsize(qh del_vertices));
+      waserror= True;
+    }
+    if (qh hull_dim == 2 && numvertices != numfacets) {
+      qh_fprintf(qh ferr, 6143, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
+        numvertices, numfacets);
+      waserror= True;
+    }
+    if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
+      qh_fprintf(qh ferr, 7063, "qhull warning: #vertices %d + #facets %d - #edges %d != 2\n\
+        A vertex appears twice in a edge list.  May occur during merging.",
+        numvertices, numfacets, numridges/2);
+      /* occurs if lots of merging and a vertex ends up twice in an edge list.  e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv */
+    }
+  }
+  if (waserror)
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+} /* checkpolygon */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="checkvertex">-</a>
+
+  qh_checkvertex( vertex )
+    check vertex for consistency
+    checks vertex->neighbors
+
+  notes:
+    neighbors checked efficiently in checkpolygon
+*/
+void qh_checkvertex(vertexT *vertex) {
+  boolT waserror= False;
+  facetT *neighbor, **neighborp, *errfacet=NULL;
+
+  if (qh_pointid(vertex->point) == -1) {
+    qh_fprintf(qh ferr, 6144, "qhull internal error (qh_checkvertex): unknown point id %p\n", vertex->point);
+    waserror= True;
+  }
+  if (vertex->id >= qh vertex_id) {
+    qh_fprintf(qh ferr, 6145, "qhull internal error (qh_checkvertex): unknown vertex id %d\n", vertex->id);
+    waserror= True;
+  }
+  if (!waserror && !vertex->deleted) {
+    if (qh_setsize(vertex->neighbors)) {
+      FOREACHneighbor_(vertex) {
+        if (!qh_setin(neighbor->vertices, vertex)) {
+          qh_fprintf(qh ferr, 6146, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
+          errfacet= neighbor;
+          waserror= True;
+        }
+      }
+    }
+  }
+  if (waserror) {
+    qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
+    qh_errexit(qh_ERRqhull, errfacet, NULL);
+  }
+} /* checkvertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="clearcenters">-</a>
+
+  qh_clearcenters( type )
+    clear old data from facet->center
+
+  notes:
+    sets new centertype
+    nop if CENTERtype is the same
+*/
+void qh_clearcenters(qh_CENTER type) {
+  facetT *facet;
+
+  if (qh CENTERtype != type) {
+    FORALLfacets {
+      if (facet->tricoplanar && !facet->keepcentrum)
+          facet->center= NULL;
+      else if (qh CENTERtype == qh_ASvoronoi){
+        if (facet->center) {
+          qh_memfree(facet->center, qh center_size);
+          facet->center= NULL;
+        }
+      }else /* qh CENTERtype == qh_AScentrum */ {
+        if (facet->center) {
+          qh_memfree(facet->center, qh normal_size);
+          facet->center= NULL;
+        }
+      }
+    }
+    qh CENTERtype= type;
+  }
+  trace2((qh ferr, 2043, "qh_clearcenters: switched to center type %d\n", type));
+} /* clearcenters */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="createsimplex">-</a>
+
+  qh_createsimplex( vertices )
+    creates a simplex from a set of vertices
+
+  returns:
+    initializes qh.facet_list to the simplex
+    initializes qh.newfacet_list, .facet_tail
+    initializes qh.vertex_list, .newvertex_list, .vertex_tail
+
+  design:
+    initializes lists
+    for each vertex
+      create a new facet
+    for each new facet
+      create its neighbor set
+*/
+void qh_createsimplex(setT *vertices) {
+  facetT *facet= NULL, *newfacet;
+  boolT toporient= True;
+  int vertex_i, vertex_n, nth;
+  setT *newfacets= qh_settemp(qh hull_dim+1);
+  vertexT *vertex;
+
+  qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
+  qh num_facets= qh num_vertices= qh num_visible= 0;
+  qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
+  FOREACHvertex_i_(vertices) {
+    newfacet= qh_newfacet();
+    newfacet->vertices= qh_setnew_delnthsorted(vertices, vertex_n,
+                                                vertex_i, 0);
+    newfacet->toporient= (unsigned char)toporient;
+    qh_appendfacet(newfacet);
+    newfacet->newfacet= True;
+    qh_appendvertex(vertex);
+    qh_setappend(&newfacets, newfacet);
+    toporient ^= True;
+  }
+  FORALLnew_facets {
+    nth= 0;
+    FORALLfacet_(qh newfacet_list) {
+      if (facet != newfacet)
+        SETelem_(newfacet->neighbors, nth++)= facet;
+    }
+    qh_settruncate(newfacet->neighbors, qh hull_dim);
+  }
+  qh_settempfree(&newfacets);
+  trace1((qh ferr, 1028, "qh_createsimplex: created simplex\n"));
+} /* createsimplex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="delridge">-</a>
+
+  qh_delridge( ridge )
+    deletes ridge from data structures it belongs to
+    frees up its memory
+
+  notes:
+    in merge.c, caller sets vertex->delridge for each vertex
+    ridges also freed in qh_freeqhull
+*/
+void qh_delridge(ridgeT *ridge) {
+  void **freelistp; /* used !qh_NOmem */
+
+  qh_setdel(ridge->top->ridges, ridge);
+  qh_setdel(ridge->bottom->ridges, ridge);
+  qh_setfree(&(ridge->vertices));
+  qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
+} /* delridge */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="delvertex">-</a>
+
+  qh_delvertex( vertex )
+    deletes a vertex and frees its memory
+
+  notes:
+    assumes vertex->adjacencies have been updated if needed
+    unlinks from vertex_list
+*/
+void qh_delvertex(vertexT *vertex) {
+
+  if (vertex == qh tracevertex)
+    qh tracevertex= NULL;
+  qh_removevertex(vertex);
+  qh_setfree(&vertex->neighbors);
+  qh_memfree(vertex, (int)sizeof(vertexT));
+} /* delvertex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="facet3vertex">-</a>
+
+  qh_facet3vertex(  )
+    return temporary set of 3-d vertices in qh_ORIENTclock order
+
+  design:
+    if simplicial facet
+      build set from facet->vertices with facet->toporient
+    else
+      for each ridge in order
+        build set from ridge's vertices
+*/
+setT *qh_facet3vertex(facetT *facet) {
+  ridgeT *ridge, *firstridge;
+  vertexT *vertex;
+  int cntvertices, cntprojected=0;
+  setT *vertices;
+
+  cntvertices= qh_setsize(facet->vertices);
+  vertices= qh_settemp(cntvertices);
+  if (facet->simplicial) {
+    if (cntvertices != 3) {
+      qh_fprintf(qh ferr, 6147, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n",
+                  cntvertices, facet->id);
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+    qh_setappend(&vertices, SETfirst_(facet->vertices));
+    if (facet->toporient ^ qh_ORIENTclock)
+      qh_setappend(&vertices, SETsecond_(facet->vertices));
+    else
+      qh_setaddnth(&vertices, 0, SETsecond_(facet->vertices));
+    qh_setappend(&vertices, SETelem_(facet->vertices, 2));
+  }else {
+    ridge= firstridge= SETfirstt_(facet->ridges, ridgeT);   /* no infinite */
+    while ((ridge= qh_nextridge3d(ridge, facet, &vertex))) {
+      qh_setappend(&vertices, vertex);
+      if (++cntprojected > cntvertices || ridge == firstridge)
+        break;
+    }
+    if (!ridge || cntprojected != cntvertices) {
+      qh_fprintf(qh ferr, 6148, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up.  got at least %d\n",
+                  facet->id, cntprojected);
+      qh_errexit(qh_ERRqhull, facet, ridge);
+    }
+  }
+  return vertices;
+} /* facet3vertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findbestfacet">-</a>
+
+  qh_findbestfacet( point, bestoutside, bestdist, isoutside )
+    find facet that is furthest below a point
+
+    for Delaunay triangulations,
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+  returns:
+    if bestoutside is set (e.g., qh_ALL)
+      returns best facet that is not upperdelaunay
+      if Delaunay and inside, point is outside circumsphere of bestfacet
+    else
+      returns first facet below point
+      if point is inside, returns nearest, !upperdelaunay facet
+    distance to facet
+    isoutside set if outside of facet
+
+  notes:
+    For tricoplanar facets, this finds one of the tricoplanar facets closest
+    to the point.  For Delaunay triangulations, the point may be inside a
+    different tricoplanar facet. See <a href="../html/qh-code.htm#findfacet">locate a facet with qh_findbestfacet()</a>
+
+    If inside, qh_findbestfacet performs an exhaustive search
+       this may be too conservative.  Sometimes it is clearly required.
+
+    qh_findbestfacet is not used by qhull.
+    uses qh.visit_id and qh.coplanarset
+
+  see:
+    <a href="geom.c#findbest">qh_findbest</a>
+*/
+facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
+           realT *bestdist, boolT *isoutside) {
+  facetT *bestfacet= NULL;
+  int numpart, totpart= 0;
+
+  bestfacet= qh_findbest(point, qh facet_list,
+                            bestoutside, !qh_ISnewfacets, bestoutside /* qh_NOupper */,
+                            bestdist, isoutside, &totpart);
+  if (*bestdist < -qh DISTround) {
+    bestfacet= qh_findfacet_all(point, bestdist, isoutside, &numpart);
+    totpart += numpart;
+    if ((isoutside && bestoutside)
+    /* cppcheck-suppress nullPointerRedundantCheck */
+    || (!isoutside && bestfacet->upperdelaunay)) {
+      bestfacet= qh_findbest(point, bestfacet,
+                            bestoutside, False, bestoutside,
+                            bestdist, isoutside, &totpart);
+      totpart += numpart;
+    }
+  }
+  trace3((qh ferr, 3014, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
+          bestfacet->id, *bestdist, *isoutside, totpart));
+  return bestfacet;
+} /* findbestfacet */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findbestlower">-</a>
+
+  qh_findbestlower( facet, point, bestdist, numpart )
+    returns best non-upper, non-flipped neighbor of facet for point
+    if needed, searches vertex neighbors
+
+  returns:
+    returns bestdist and updates numpart
+
+  notes:
+    if Delaunay and inside, point is outside of circumsphere of bestfacet
+    called by qh_findbest() for points above an upperdelaunay facet
+
+*/
+facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart) {
+  facetT *neighbor, **neighborp, *bestfacet= NULL;
+  realT bestdist= -REALmax/2 /* avoid underflow */;
+  realT dist;
+  vertexT *vertex;
+
+  zinc_(Zbestlower);
+  FOREACHneighbor_(upperfacet) {
+    if (neighbor->upperdelaunay || neighbor->flipped)
+      continue;
+    (*numpart)++;
+    qh_distplane(point, neighbor, &dist);
+    if (dist > bestdist) {
+      bestfacet= neighbor;
+      bestdist= dist;
+    }
+  }
+  if (!bestfacet) {
+    zinc_(Zbestlowerv);
+    /* rarely called, numpart does not count nearvertex computations */
+    vertex= qh_nearvertex(upperfacet, point, &dist);
+    qh_vertexneighbors();
+    FOREACHneighbor_(vertex) {
+      if (neighbor->upperdelaunay || neighbor->flipped)
+        continue;
+      (*numpart)++;
+      qh_distplane(point, neighbor, &dist);
+      if (dist > bestdist) {
+        bestfacet= neighbor;
+        bestdist= dist;
+      }
+    }
+  }
+  if (!bestfacet) {
+    qh_fprintf(qh ferr, 6228, "\n\
+Qhull internal error (qh_findbestlower): all neighbors of facet %d are flipped or upper Delaunay.\n\
+Please report this error to qhull_bug at qhull.org with the input and all of the output.\n",
+       upperfacet->id);
+    qh_errexit(qh_ERRqhull, upperfacet, NULL);
+  }
+  *bestdistp= bestdist;
+  trace3((qh ferr, 3015, "qh_findbestlower: f%d dist %2.2g for f%d p%d\n",
+          bestfacet->id, bestdist, upperfacet->id, qh_pointid(point)));
+  return bestfacet;
+} /* findbestlower */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findfacet_all">-</a>
+
+  qh_findfacet_all( point, bestdist, isoutside, numpart )
+    exhaustive search for facet below a point
+
+    for Delaunay triangulations,
+      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
+      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
+
+  returns:
+    returns first facet below point
+    if point is inside,
+      returns nearest facet
+    distance to facet
+    isoutside if point is outside of the hull
+    number of distance tests
+
+  notes:
+    for library users, not used by Qhull
+*/
+facetT *qh_findfacet_all(pointT *point, realT *bestdist, boolT *isoutside,
+                          int *numpart) {
+  facetT *bestfacet= NULL, *facet;
+  realT dist;
+  int totpart= 0;
+
+  *bestdist= -REALmax;
+  *isoutside= False;
+  FORALLfacets {
+    if (facet->flipped || !facet->normal)
+      continue;
+    totpart++;
+    qh_distplane(point, facet, &dist);
+    if (dist > *bestdist) {
+      *bestdist= dist;
+      bestfacet= facet;
+      if (dist > qh MINoutside) {
+        *isoutside= True;
+        break;
+      }
+    }
+  }
+  *numpart= totpart;
+  trace3((qh ferr, 3016, "qh_findfacet_all: f%d dist %2.2g isoutside %d totpart %d\n",
+          getid_(bestfacet), *bestdist, *isoutside, totpart));
+  return bestfacet;
+} /* findfacet_all */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findgood">-</a>
+
+  qh_findgood( facetlist, goodhorizon )
+    identify good facets for qh.PRINTgood
+    if qh.GOODvertex>0
+      facet includes point as vertex
+      if !match, returns goodhorizon
+      inactive if qh.MERGING
+    if qh.GOODpoint
+      facet is visible or coplanar (>0) or not visible (<0)
+    if qh.GOODthreshold
+      facet->normal matches threshold
+    if !goodhorizon and !match,
+      selects facet with closest angle
+      sets GOODclosest
+
+  returns:
+    number of new, good facets found
+    determines facet->good
+    may update qh.GOODclosest
+
+  notes:
+    qh_findgood_all further reduces the good region
+
+  design:
+    count good facets
+    mark good facets for qh.GOODpoint
+    mark good facets for qh.GOODthreshold
+    if necessary
+      update qh.GOODclosest
+*/
+int qh_findgood(facetT *facetlist, int goodhorizon) {
+  facetT *facet, *bestfacet= NULL;
+  realT angle, bestangle= REALmax, dist;
+  int  numgood=0;
+
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      numgood++;
+  }
+  if (qh GOODvertex>0 && !qh MERGING) {
+    FORALLfacet_(facetlist) {
+      if (!qh_isvertex(qh GOODvertexp, facet->vertices)) {
+        facet->good= False;
+        numgood--;
+      }
+    }
+  }
+  if (qh GOODpoint && numgood) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && facet->normal) {
+        zinc_(Zdistgood);
+        qh_distplane(qh GOODpointp, facet, &dist);
+        if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
+          facet->good= False;
+          numgood--;
+        }
+      }
+    }
+  }
+  if (qh GOODthreshold && (numgood || goodhorizon || qh GOODclosest)) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && facet->normal) {
+        if (!qh_inthresholds(facet->normal, &angle)) {
+          facet->good= False;
+          numgood--;
+          if (angle < bestangle) {
+            bestangle= angle;
+            bestfacet= facet;
+          }
+        }
+      }
+    }
+    if (!numgood && (!goodhorizon || qh GOODclosest)) {
+      if (qh GOODclosest) {
+        if (qh GOODclosest->visible)
+          qh GOODclosest= NULL;
+        else {
+          qh_inthresholds(qh GOODclosest->normal, &angle);
+          if (angle < bestangle)
+            bestfacet= qh GOODclosest;
+        }
+      }
+      if (bestfacet && bestfacet != qh GOODclosest) {
+        if (qh GOODclosest)
+          qh GOODclosest->good= False;
+        qh GOODclosest= bestfacet;
+        bestfacet->good= True;
+        numgood++;
+        trace2((qh ferr, 2044, "qh_findgood: f%d is closest(%2.2g) to thresholds\n",
+           bestfacet->id, bestangle));
+        return numgood;
+      }
+    }else if (qh GOODclosest) { /* numgood > 0 */
+      qh GOODclosest->good= False;
+      qh GOODclosest= NULL;
+    }
+  }
+  zadd_(Zgoodfacet, numgood);
+  trace2((qh ferr, 2045, "qh_findgood: found %d good facets with %d good horizon\n",
+               numgood, goodhorizon));
+  if (!numgood && qh GOODvertex>0 && !qh MERGING)
+    return goodhorizon;
+  return numgood;
+} /* findgood */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="findgood_all">-</a>
+
+  qh_findgood_all( facetlist )
+    apply other constraints for good facets (used by qh.PRINTgood)
+    if qh.GOODvertex
+      facet includes (>0) or doesn't include (<0) point as vertex
+      if last good facet and ONLYgood, prints warning and continues
+    if qh.SPLITthresholds
+      facet->normal matches threshold, or if none, the closest one
+    calls qh_findgood
+    nop if good not used
+
+  returns:
+    clears facet->good if not good
+    sets qh.num_good
+
+  notes:
+    this is like qh_findgood but more restrictive
+
+  design:
+    uses qh_findgood to mark good facets
+    marks facets for qh.GOODvertex
+    marks facets for qh.SPLITthreholds
+*/
+void qh_findgood_all(facetT *facetlist) {
+  facetT *facet, *bestfacet=NULL;
+  realT angle, bestangle= REALmax;
+  int  numgood=0, startgood;
+
+  if (!qh GOODvertex && !qh GOODthreshold && !qh GOODpoint
+  && !qh SPLITthresholds)
+    return;
+  if (!qh ONLYgood)
+    qh_findgood(qh facet_list, 0);
+  FORALLfacet_(facetlist) {
+    if (facet->good)
+      numgood++;
+  }
+  if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
+    FORALLfacet_(facetlist) {
+      if (facet->good && ((qh GOODvertex > 0) ^ !!qh_isvertex(qh GOODvertexp, facet->vertices))) {
+        if (!--numgood) {
+          if (qh ONLYgood) {
+            qh_fprintf(qh ferr, 7064, "qhull warning: good vertex p%d does not match last good facet f%d.  Ignored.\n",
+               qh_pointid(qh GOODvertexp), facet->id);
+            return;
+          }else if (qh GOODvertex > 0)
+            qh_fprintf(qh ferr, 7065, "qhull warning: point p%d is not a vertex('QV%d').\n",
+                qh GOODvertex-1, qh GOODvertex-1);
+          else
+            qh_fprintf(qh ferr, 7066, "qhull warning: point p%d is a vertex for every facet('QV-%d').\n",
+                -qh GOODvertex - 1, -qh GOODvertex - 1);
+        }
+        facet->good= False;
+      }
+    }
+  }
+  startgood= numgood;
+  if (qh SPLITthresholds) {
+    FORALLfacet_(facetlist) {
+      if (facet->good) {
+        if (!qh_inthresholds(facet->normal, &angle)) {
+          facet->good= False;
+          numgood--;
+          if (angle < bestangle) {
+            bestangle= angle;
+            bestfacet= facet;
+          }
+        }
+      }
+    }
+    if (!numgood && bestfacet) {
+      bestfacet->good= True;
+      numgood++;
+      trace0((qh ferr, 23, "qh_findgood_all: f%d is closest(%2.2g) to thresholds\n",
+           bestfacet->id, bestangle));
+      return;
+    }
+  }
+  qh num_good= numgood;
+  trace0((qh ferr, 24, "qh_findgood_all: %d good facets remain out of %d facets\n",
+        numgood, startgood));
+} /* findgood_all */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="furthestnext">-</a>
+
+  qh_furthestnext()
+    set qh.facet_next to facet with furthest of all furthest points
+    searches all facets on qh.facet_list
+
+  notes:
+    this may help avoid precision problems
+*/
+void qh_furthestnext(void /* qh facet_list */) {
+  facetT *facet, *bestfacet= NULL;
+  realT dist, bestdist= -REALmax;
+
+  FORALLfacets {
+    if (facet->outsideset) {
+#if qh_COMPUTEfurthest
+      pointT *furthest;
+      furthest= (pointT*)qh_setlast(facet->outsideset);
+      zinc_(Zcomputefurthest);
+      qh_distplane(furthest, facet, &dist);
+#else
+      dist= facet->furthestdist;
+#endif
+      if (dist > bestdist) {
+        bestfacet= facet;
+        bestdist= dist;
+      }
+    }
+  }
+  if (bestfacet) {
+    qh_removefacet(bestfacet);
+    qh_prependfacet(bestfacet, &qh facet_next);
+    trace1((qh ferr, 1029, "qh_furthestnext: made f%d next facet(dist %.2g)\n",
+            bestfacet->id, bestdist));
+  }
+} /* furthestnext */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="furthestout">-</a>
+
+  qh_furthestout( facet )
+    make furthest outside point the last point of outsideset
+
+  returns:
+    updates facet->outsideset
+    clears facet->notfurthest
+    sets facet->furthestdist
+
+  design:
+    determine best point of outsideset
+    make it the last point of outsideset
+*/
+void qh_furthestout(facetT *facet) {
+  pointT *point, **pointp, *bestpoint= NULL;
+  realT dist, bestdist= -REALmax;
+
+  FOREACHpoint_(facet->outsideset) {
+    qh_distplane(point, facet, &dist);
+    zinc_(Zcomputefurthest);
+    if (dist > bestdist) {
+      bestpoint= point;
+      bestdist= dist;
+    }
+  }
+  if (bestpoint) {
+    qh_setdel(facet->outsideset, point);
+    qh_setappend(&facet->outsideset, point);
+#if !qh_COMPUTEfurthest
+    facet->furthestdist= bestdist;
+#endif
+  }
+  facet->notfurthest= False;
+  trace3((qh ferr, 3017, "qh_furthestout: p%d is furthest outside point of f%d\n",
+          qh_pointid(point), facet->id));
+} /* furthestout */
+
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="infiniteloop">-</a>
+
+  qh_infiniteloop( facet )
+    report infinite loop error due to facet
+*/
+void qh_infiniteloop(facetT *facet) {
+
+  qh_fprintf(qh ferr, 6149, "qhull internal error (qh_infiniteloop): potential infinite loop detected\n");
+  qh_errexit(qh_ERRqhull, facet, NULL);
+} /* qh_infiniteloop */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="initbuild">-</a>
+
+  qh_initbuild()
+    initialize hull and outside sets with point array
+    qh.FIRSTpoint/qh.NUMpoints is point array
+    if qh.GOODpoint
+      adds qh.GOODpoint to initial hull
+
+  returns:
+    qh_facetlist with initial hull
+    points partioned into outside sets, coplanar sets, or inside
+    initializes qh.GOODpointp, qh.GOODvertexp,
+
+  design:
+    initialize global variables used during qh_buildhull
+    determine precision constants and points with max/min coordinate values
+      if qh.SCALElast, scale last coordinate(for 'd')
+    build initial simplex
+    partition input points into facets of initial simplex
+    set up lists
+    if qh.ONLYgood
+      check consistency
+      add qh.GOODvertex if defined
+*/
+void qh_initbuild( void) {
+  setT *maxpoints, *vertices;
+  facetT *facet;
+  int i, numpart;
+  realT dist;
+  boolT isoutside;
+
+  qh furthest_id= -1;
+  qh lastreport= 0;
+  qh facet_id= qh vertex_id= qh ridge_id= 0;
+  qh visit_id= qh vertex_visit= 0;
+  qh maxoutdone= False;
+
+  if (qh GOODpoint > 0)
+    qh GOODpointp= qh_point(qh GOODpoint-1);
+  else if (qh GOODpoint < 0)
+    qh GOODpointp= qh_point(-qh GOODpoint-1);
+  if (qh GOODvertex > 0)
+    qh GOODvertexp= qh_point(qh GOODvertex-1);
+  else if (qh GOODvertex < 0)
+    qh GOODvertexp= qh_point(-qh GOODvertex-1);
+  if ((qh GOODpoint
+       && (qh GOODpointp < qh first_point  /* also catches !GOODpointp */
+           || qh GOODpointp > qh_point(qh num_points-1)))
+    || (qh GOODvertex
+        && (qh GOODvertexp < qh first_point  /* also catches !GOODvertexp */
+            || qh GOODvertexp > qh_point(qh num_points-1)))) {
+    qh_fprintf(qh ferr, 6150, "qhull input error: either QGn or QVn point is > p%d\n",
+             qh num_points-1);
+    qh_errexit(qh_ERRinput, NULL, NULL);
+  }
+  maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
+  if (qh SCALElast)
+    qh_scalelast(qh first_point, qh num_points, qh hull_dim,
+               qh MINlastcoord, qh MAXlastcoord, qh MAXwidth);
+  qh_detroundoff();
+  if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2
+                  && qh lower_threshold[qh hull_dim-1] < -REALmax/2) {
+    for (i=qh_PRINTEND; i--; ) {
+      if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0
+          && !qh GOODthreshold && !qh SPLITthresholds)
+        break;  /* in this case, don't set upper_threshold */
+    }
+    if (i < 0) {
+      if (qh UPPERdelaunay) { /* matches qh.upperdelaunay in qh_setfacetplane */
+        qh lower_threshold[qh hull_dim-1]= qh ANGLEround * qh_ZEROdelaunay;
+        qh GOODthreshold= True;
+      }else {
+        qh upper_threshold[qh hull_dim-1]= -qh ANGLEround * qh_ZEROdelaunay;
+        if (!qh GOODthreshold)
+          qh SPLITthresholds= True; /* build upper-convex hull even if Qg */
+          /* qh_initqhull_globals errors if Qg without Pdk/etc. */
+      }
+    }
+  }
+  vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points);
+  qh_initialhull(vertices);  /* initial qh facet_list */
+  qh_partitionall(vertices, qh first_point, qh num_points);
+  if (qh PRINToptions1st || qh TRACElevel || qh IStracing) {
+    if (qh TRACElevel || qh IStracing)
+      qh_fprintf(qh ferr, 8103, "\nTrace level %d for %s | %s\n",
+         qh IStracing ? qh IStracing : qh TRACElevel, qh rbox_command, qh qhull_command);
+    qh_fprintf(qh ferr, 8104, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
+  }
+  qh_resetlists(False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
+  qh facet_next= qh facet_list;
+  qh_furthestnext(/* qh facet_list */);
+  if (qh PREmerge) {
+    qh cos_max= qh premerge_cos;
+    qh centrum_radius= qh premerge_centrum;
+  }
+  if (qh ONLYgood) {
+    if (qh GOODvertex > 0 && qh MERGING) {
+      qh_fprintf(qh ferr, 6151, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (!(qh GOODthreshold || qh GOODpoint
+         || (!qh MERGEexact && !qh PREmerge && qh GOODvertexp))) {
+      qh_fprintf(qh ferr, 6152, "qhull input error: 'Qg' (ONLYgood) needs a good threshold('Pd0D0'), a\n\
+good point(QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
+      qh_errexit(qh_ERRinput, NULL, NULL);
+    }
+    if (qh GOODvertex > 0  && !qh MERGING  /* matches qh_partitionall */
+        && !qh_isvertex(qh GOODvertexp, vertices)) {
+      facet= qh_findbestnew(qh GOODvertexp, qh facet_list,
+                          &dist, !qh_ALL, &isoutside, &numpart);
+      zadd_(Zdistgood, numpart);
+      if (!isoutside) {
+        qh_fprintf(qh ferr, 6153, "qhull input error: point for QV%d is inside initial simplex.  It can not be made a vertex.\n",
+               qh_pointid(qh GOODvertexp));
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+      if (!qh_addpoint(qh GOODvertexp, facet, False)) {
+        qh_settempfree(&vertices);
+        qh_settempfree(&maxpoints);
+        return;
+      }
+    }
+    qh_findgood(qh facet_list, 0);
+  }
+  qh_settempfree(&vertices);
+  qh_settempfree(&maxpoints);
+  trace1((qh ferr, 1030, "qh_initbuild: initial hull created and points partitioned\n"));
+} /* initbuild */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="initialhull">-</a>
+
+  qh_initialhull( vertices )
+    constructs the initial hull as a DIM3 simplex of vertices
+
+  design:
+    creates a simplex (initializes lists)
+    determines orientation of simplex
+    sets hyperplanes for facets
+    doubles checks orientation (in case of axis-parallel facets with Gaussian elimination)
+    checks for flipped facets and qh.NARROWhull
+    checks the result
+*/
+void qh_initialhull(setT *vertices) {
+  facetT *facet, *firstfacet, *neighbor, **neighborp;
+  realT dist, angle, minangle= REALmax;
+#ifndef qh_NOtrace
+  int k;
+#endif
+
+  qh_createsimplex(vertices);  /* qh facet_list */
+  qh_resetlists(False, qh_RESETvisible);
+  qh facet_next= qh facet_list;      /* advance facet when processed */
+  qh interior_point= qh_getcenter(vertices);
+  firstfacet= qh facet_list;
+  qh_setfacetplane(firstfacet);
+  zinc_(Znumvisibility); /* needs to be in printsummary */
+  qh_distplane(qh interior_point, firstfacet, &dist);
+  if (dist > 0) {
+    FORALLfacets
+      facet->toporient ^= (unsigned char)True;
+  }
+  FORALLfacets
+    qh_setfacetplane(facet);
+  FORALLfacets {
+    if (!qh_checkflipped(facet, NULL, qh_ALL)) {/* due to axis-parallel facet */
+      trace1((qh ferr, 1031, "qh_initialhull: initial orientation incorrect.  Correct all facets\n"));
+      facet->flipped= False;
+      FORALLfacets {
+        facet->toporient ^= (unsigned char)True;
+        qh_orientoutside(facet);
+      }
+      break;
+    }
+  }
+  FORALLfacets {
+    if (!qh_checkflipped(facet, NULL, !qh_ALL)) {  /* can happen with 'R0.1' */
+      if (qh DELAUNAY && ! qh ATinfinity) {
+        if (qh UPPERdelaunay)
+          qh_fprintf(qh ferr, 6240, "Qhull input error: Can not compute the upper Delaunay triangulation or upper Voronoi diagram of cocircular/cospherical points.\n");
+        else
+          qh_fprintf(qh ferr, 6239, "Qhull input error: Use option 'Qz' for the Delaunay triangulation or Voronoi diagram of cocircular/cospherical points.  Option 'Qz' adds a point \"at infinity\" (above the corresponding paraboloid).\n");
+        qh_errexit(qh_ERRinput, NULL, NULL);
+      }
+      qh_precision("initial facet is coplanar with interior point");
+      qh_fprintf(qh ferr, 6154, "qhull precision error: initial facet %d is coplanar with the interior point\n",
+                   facet->id);
+      qh_errexit(qh_ERRsingular, facet, NULL);
+    }
+    FOREACHneighbor_(facet) {
+      angle= qh_getangle(facet->normal, neighbor->normal);
+      minimize_( minangle, angle);
+    }
+  }
+  if (minangle < qh_MAXnarrow && !qh NOnarrow) {
+    realT diff= 1.0 + minangle;
+
+    qh NARROWhull= True;
+    qh_option("_narrow-hull", NULL, &diff);
+    if (minangle < qh_WARNnarrow && !qh RERUN && qh PRINTprecision)
+      qh_printhelp_narrowhull(qh ferr, minangle);
+  }
+  zzval_(Zprocessed)= qh hull_dim+1;
+  qh_checkpolygon(qh facet_list);
+  qh_checkconvex(qh facet_list,   qh_DATAfault);
+#ifndef qh_NOtrace
+  if (qh IStracing >= 1) {
+    qh_fprintf(qh ferr, 8105, "qh_initialhull: simplex constructed, interior point:");
+    for (k=0; k < qh hull_dim; k++)
+      qh_fprintf(qh ferr, 8106, " %6.4g", qh interior_point[k]);
+    qh_fprintf(qh ferr, 8107, "\n");
+  }
+#endif
+} /* initialhull */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="initialvertices">-</a>
+
+  qh_initialvertices( dim, maxpoints, points, numpoints )
+    determines a non-singular set of initial vertices
+    maxpoints may include duplicate points
+
+  returns:
+    temporary set of dim+1 vertices in descending order by vertex id
+    if qh.RANDOMoutside && !qh.ALLpoints
+      picks random points
+    if dim >= qh_INITIALmax,
+      uses min/max x and max points with non-zero determinants
+
+  notes:
+    unless qh.ALLpoints,
+      uses maxpoints as long as determinate is non-zero
+*/
+setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
+  pointT *point, **pointp;
+  setT *vertices, *simplex, *tested;
+  realT randr;
+  int idx, point_i, point_n, k;
+  boolT nearzero= False;
+
+  vertices= qh_settemp(dim + 1);
+  simplex= qh_settemp(dim+1);
+  if (qh ALLpoints)
+    qh_maxsimplex(dim, NULL, points, numpoints, &simplex);
+  else if (qh RANDOMoutside) {
+    while (qh_setsize(simplex) != dim+1) {
+      randr= qh_RANDOMint;
+      randr= randr/(qh_RANDOMmax+1);
+      idx= (int)floor(qh num_points * randr);
+      while (qh_setin(simplex, qh_point(idx))) {
+            idx++; /* in case qh_RANDOMint always returns the same value */
+        idx= idx < qh num_points ? idx : 0;
+      }
+      qh_setappend(&simplex, qh_point(idx));
+    }
+  }else if (qh hull_dim >= qh_INITIALmax) {
+    tested= qh_settemp(dim+1);
+    qh_setappend(&simplex, SETfirst_(maxpoints));   /* max and min X coord */
+    qh_setappend(&simplex, SETsecond_(maxpoints));
+    qh_maxsimplex(fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
+    k= qh_setsize(simplex);
+    FOREACHpoint_i_(maxpoints) {
+      if (point_i & 0x1) {     /* first pick up max. coord. points */
+        if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
+          qh_detsimplex(point, simplex, k, &nearzero);
+          if (nearzero)
+            qh_setappend(&tested, point);
+          else {
+            qh_setappend(&simplex, point);
+            if (++k == dim)  /* use search for last point */
+              break;
+          }
+        }
+      }
+    }
+    while (k != dim && (point= (pointT*)qh_setdellast(maxpoints))) {
+      if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
+        qh_detsimplex(point, simplex, k, &nearzero);
+        if (nearzero)
+          qh_setappend(&tested, point);
+        else {
+          qh_setappend(&simplex, point);
+          k++;
+        }
+      }
+    }
+    idx= 0;
+    while (k != dim && (point= qh_point(idx++))) {
+      if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
+        qh_detsimplex(point, simplex, k, &nearzero);
+        if (!nearzero){
+          qh_setappend(&simplex, point);
+          k++;
+        }
+      }
+    }
+    qh_settempfree(&tested);
+    qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
+  }else
+    qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
+  FOREACHpoint_(simplex)
+    qh_setaddnth(&vertices, 0, qh_newvertex(point)); /* descending order */
+  qh_settempfree(&simplex);
+  return vertices;
+} /* initialvertices */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="isvertex">-</a>
+
+  qh_isvertex(  )
+    returns vertex if point is in vertex set, else returns NULL
+
+  notes:
+    for qh.GOODvertex
+*/
+vertexT *qh_isvertex(pointT *point, setT *vertices) {
+  vertexT *vertex, **vertexp;
+
+  FOREACHvertex_(vertices) {
+    if (vertex->point == point)
+      return vertex;
+  }
+  return NULL;
+} /* isvertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="makenewfacets">-</a>
+
+  qh_makenewfacets( point )
+    make new facets from point and qh.visible_list
+
+  returns:
+    qh.newfacet_list= list of new facets with hyperplanes and ->newfacet
+    qh.newvertex_list= list of vertices in new facets with ->newlist set
+
+    if (qh.ONLYgood)
+      newfacets reference horizon facets, but not vice versa
+      ridges reference non-simplicial horizon ridges, but not vice versa
+      does not change existing facets
+    else
+      sets qh.NEWfacets
+      new facets attached to horizon facets and ridges
+      for visible facets,
+        visible->r.replace is corresponding new facet
+
+  see also:
+    qh_makenewplanes() -- make hyperplanes for facets
+    qh_attachnewfacets() -- attachnewfacets if not done here(qh ONLYgood)
+    qh_matchnewfacets() -- match up neighbors
+    qh_updatevertices() -- update vertex neighbors and delvertices
+    qh_deletevisible() -- delete visible facets
+    qh_checkpolygon() --check the result
+    qh_triangulate() -- triangulate a non-simplicial facet
+
+  design:
+    for each visible facet
+      make new facets to its horizon facets
+      update its f.replace
+      clear its neighbor set
+*/
+vertexT *qh_makenewfacets(pointT *point /*visible_list*/) {
+  facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
+  vertexT *apex;
+  int numnew=0;
+
+  qh newfacet_list= qh facet_tail;
+  qh newvertex_list= qh vertex_tail;
+  apex= qh_newvertex(point);
+  qh_appendvertex(apex);
+  qh visit_id++;
+  if (!qh ONLYgood)
+    qh NEWfacets= True;
+  FORALLvisible_facets {
+    FOREACHneighbor_(visible)
+      neighbor->seen= False;
+    if (visible->ridges) {
+      visible->visitid= qh visit_id;
+      newfacet2= qh_makenew_nonsimplicial(visible, apex, &numnew);
+    }
+    if (visible->simplicial)
+      newfacet= qh_makenew_simplicial(visible, apex, &numnew);
+    if (!qh ONLYgood) {
+      if (newfacet2)  /* newfacet is null if all ridges defined */
+        newfacet= newfacet2;
+      if (newfacet)
+        visible->f.replace= newfacet;
+      else
+        zinc_(Zinsidevisible);
+      SETfirst_(visible->neighbors)= NULL;
+    }
+  }
+  trace1((qh ferr, 1032, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
+          numnew, qh_pointid(point)));
+  if (qh IStracing >= 4)
+    qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
+  return apex;
+} /* makenewfacets */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="matchduplicates">-</a>
+
+  qh_matchduplicates( atfacet, atskip, hashsize, hashcount )
+    match duplicate ridges in qh.hash_table for atfacet/atskip
+    duplicates marked with ->dupridge and qh_DUPLICATEridge
+
+  returns:
+    picks match with worst merge (min distance apart)
+    updates hashcount
+
+  see also:
+    qh_matchneighbor
+
+  notes:
+
+  design:
+    compute hash value for atfacet and atskip
+    repeat twice -- once to make best matches, once to match the rest
+      for each possible facet in qh.hash_table
+        if it is a matching facet and pass 2
+          make match
+          unless tricoplanar, mark match for merging (qh_MERGEridge)
+          [e.g., tricoplanar RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Qt]
+        if it is a matching facet and pass 1
+          test if this is a better match
+      if pass 1,
+        make best match (it will not be merged)
+*/
+#ifndef qh_NOmerge
+void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+  boolT same, ismatch;
+  int hash, scan;
+  facetT *facet, *newfacet, *maxmatch= NULL, *maxmatch2= NULL, *nextfacet;
+  int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch;
+  realT maxdist= -REALmax, mindist, dist2, low, high;
+
+  hash= qh_gethash(hashsize, atfacet->vertices, qh hull_dim, 1,
+                     SETelem_(atfacet->vertices, atskip));
+  trace2((qh ferr, 2046, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n",
+          atfacet->id, atskip, hash, *hashcount));
+  for (makematch= 0; makematch < 2; makematch++) {
+    qh visit_id++;
+    for (newfacet= atfacet, newskip= atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
+      zinc_(Zhashlookup);
+      nextfacet= NULL;
+      newfacet->visitid= qh visit_id;
+      for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
+           scan= (++scan >= hashsize ? 0 : scan)) {
+        if (!facet->dupridge || facet->visitid == qh visit_id)
+          continue;
+        zinc_(Zhashtests);
+        if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
+          ismatch= (same == (boolT)(newfacet->toporient ^ facet->toporient));
+          if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
+            if (!makematch) {
+              qh_fprintf(qh ferr, 6155, "qhull internal error (qh_matchduplicates): missing dupridge at f%d skip %d for new f%d skip %d hash %d\n",
+                     facet->id, skip, newfacet->id, newskip, hash);
+              qh_errexit2 (qh_ERRqhull, facet, newfacet);
+            }
+          }else if (ismatch && makematch) {
+            if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
+              SETelem_(facet->neighbors, skip)= newfacet;
+              if (newfacet->tricoplanar)
+                SETelem_(newfacet->neighbors, newskip)= facet;
+              else
+                SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
+              *hashcount -= 2; /* removed two unmatched facets */
+              trace4((qh ferr, 4059, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d merge\n",
+                    facet->id, skip, newfacet->id, newskip));
+            }
+          }else if (ismatch) {
+            mindist= qh_getdistance(facet, newfacet, &low, &high);
+            dist2= qh_getdistance(newfacet, facet, &low, &high);
+            minimize_(mindist, dist2);
+            if (mindist > maxdist) {
+              maxdist= mindist;
+              maxmatch= facet;
+              maxskip= skip;
+              maxmatch2= newfacet;
+              maxskip2= newskip;
+            }
+            trace3((qh ferr, 3018, "qh_matchduplicates: duplicate f%d skip %d new f%d skip %d at dist %2.2g, max is now f%d f%d\n",
+                    facet->id, skip, newfacet->id, newskip, mindist,
+                    maxmatch->id, maxmatch2->id));
+          }else { /* !ismatch */
+            nextfacet= facet;
+            nextskip= skip;
+          }
+        }
+        if (makematch && !facet
+        && SETelemt_(facet->neighbors, skip, facetT) == qh_DUPLICATEridge) {
+          qh_fprintf(qh ferr, 6156, "qhull internal error (qh_matchduplicates): no MERGEridge match for duplicate f%d skip %d at hash %d\n",
+                     newfacet->id, newskip, hash);
+          qh_errexit(qh_ERRqhull, newfacet, NULL);
+        }
+      }
+    } /* end of for each new facet at hash */
+    if (!makematch) {
+      if (!maxmatch) {
+        qh_fprintf(qh ferr, 6157, "qhull internal error (qh_matchduplicates): no maximum match at duplicate f%d skip %d at hash %d\n",
+                     atfacet->id, atskip, hash);
+        qh_errexit(qh_ERRqhull, atfacet, NULL);
+      }
+      /* maxmatch cannot be NULL since above qh_errexit didn't return */
+      /* coverity[var_deref_op] */
+      SETelem_(maxmatch->neighbors, maxskip)= maxmatch2;
+      SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
+      *hashcount -= 2; /* removed two unmatched facets */
+      zzinc_(Zmultiridge);
+      trace0((qh ferr, 25, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d keep\n",
+              maxmatch->id, maxskip, maxmatch2->id, maxskip2));
+      qh_precision("ridge with multiple neighbors");
+      if (qh IStracing >= 4)
+        qh_errprint("DUPLICATED/MATCH", maxmatch, maxmatch2, NULL, NULL);
+    }
+  }
+} /* matchduplicates */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="nearcoplanar">-</a>
+
+  qh_nearcoplanar()
+    for all facets, remove near-inside points from facet->coplanarset</li>
+    coplanar points defined by innerplane from qh_outerinner()
+
+  returns:
+    if qh KEEPcoplanar && !qh KEEPinside
+      facet->coplanarset only contains coplanar points
+    if qh.JOGGLEmax
+      drops inner plane by another qh.JOGGLEmax diagonal since a
+        vertex could shift out while a coplanar point shifts in
+
+  notes:
+    used for qh.PREmerge and qh.JOGGLEmax
+    must agree with computation of qh.NEARcoplanar in qh_detroundoff()
+  design:
+    if not keeping coplanar or inside points
+      free all coplanar sets
+    else if not keeping both coplanar and inside points
+      remove !coplanar or !inside points from coplanar sets
+*/
+void qh_nearcoplanar(void /* qh.facet_list */) {
+  facetT *facet;
+  pointT *point, **pointp;
+  int numpart;
+  realT dist, innerplane;
+
+  if (!qh KEEPcoplanar && !qh KEEPinside) {
+    FORALLfacets {
+      if (facet->coplanarset)
+        qh_setfree( &facet->coplanarset);
+    }
+  }else if (!qh KEEPcoplanar || !qh KEEPinside) {
+    qh_outerinner(NULL, NULL, &innerplane);
+    if (qh JOGGLEmax < REALmax/2)
+      innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
+    numpart= 0;
+    FORALLfacets {
+      if (facet->coplanarset) {
+        FOREACHpoint_(facet->coplanarset) {
+          numpart++;
+          qh_distplane(point, facet, &dist);
+          if (dist < innerplane) {
+            if (!qh KEEPinside)
+              SETref_(point)= NULL;
+          }else if (!qh KEEPcoplanar)
+            SETref_(point)= NULL;
+        }
+        qh_setcompact(facet->coplanarset);
+      }
+    }
+    zzadd_(Zcheckpart, numpart);
+  }
+} /* nearcoplanar */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="nearvertex">-</a>
+
+  qh_nearvertex( facet, point, bestdist )
+    return nearest vertex in facet to point
+
+  returns:
+    vertex and its distance
+
+  notes:
+    if qh.DELAUNAY
+      distance is measured in the input set
+    searches neighboring tricoplanar facets (requires vertexneighbors)
+      Slow implementation.  Recomputes vertex set for each point.
+    The vertex set could be stored in the qh.keepcentrum facet.
+*/
+vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp) {
+  realT bestdist= REALmax, dist;
+  vertexT *bestvertex= NULL, *vertex, **vertexp, *apex;
+  coordT *center;
+  facetT *neighbor, **neighborp;
+  setT *vertices;
+  int dim= qh hull_dim;
+
+  if (qh DELAUNAY)
+    dim--;
+  if (facet->tricoplanar) {
+    if (!qh VERTEXneighbors || !facet->center) {
+      qh_fprintf(qh ferr, 6158, "qhull internal error (qh_nearvertex): qh.VERTEXneighbors and facet->center required for tricoplanar facets\n");
+      qh_errexit(qh_ERRqhull, facet, NULL);
+    }
+    vertices= qh_settemp(qh TEMPsize);
+    apex= SETfirstt_(facet->vertices, vertexT);
+    center= facet->center;
+    FOREACHneighbor_(apex) {
+      if (neighbor->center == center) {
+        FOREACHvertex_(neighbor->vertices)
+          qh_setappend(&vertices, vertex);
+      }
+    }
+  }else
+    vertices= facet->vertices;
+  FOREACHvertex_(vertices) {
+    dist= qh_pointdist(vertex->point, point, -dim);
+    if (dist < bestdist) {
+      bestdist= dist;
+      bestvertex= vertex;
+    }
+  }
+  if (facet->tricoplanar)
+    qh_settempfree(&vertices);
+  *bestdistp= sqrt(bestdist);
+  trace3((qh ferr, 3019, "qh_nearvertex: v%d dist %2.2g for f%d p%d\n",
+        bestvertex ? bestvertex->id : -1, *bestdistp, facet->id, qh_pointid(point)));
+  return bestvertex;
+} /* nearvertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="newhashtable">-</a>
+
+  qh_newhashtable( newsize )
+    returns size of qh.hash_table of at least newsize slots
+
+  notes:
+    assumes qh.hash_table is NULL
+    qh_HASHfactor determines the number of extra slots
+    size is not divisible by 2, 3, or 5
+*/
+int qh_newhashtable(int newsize) {
+  int size;
+
+  size= ((newsize+1)*qh_HASHfactor) | 0x1;  /* odd number */
+  while (True) {
+    if (newsize<0 || size<0) {
+        qh_fprintf(qhmem.ferr, 6236, "qhull error (qh_newhashtable): negative request (%d) or size (%d).  Did int overflow due to high-D?\n", newsize, size); /* WARN64 */
+        qh_errexit(qhmem_ERRmem, NULL, NULL);
+    }
+    if ((size%3) && (size%5))
+      break;
+    size += 2;
+    /* loop terminates because there is an infinite number of primes */
+  }
+  qh hash_table= qh_setnew(size);
+  qh_setzero(qh hash_table, 0, size);
+  return size;
+} /* newhashtable */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="newvertex">-</a>
+
+  qh_newvertex( point )
+    returns a new vertex for point
+*/
+vertexT *qh_newvertex(pointT *point) {
+  vertexT *vertex;
+
+  zinc_(Ztotvertices);
+  vertex= (vertexT *)qh_memalloc((int)sizeof(vertexT));
+  memset((char *) vertex, (size_t)0, sizeof(vertexT));
+  if (qh vertex_id == 0xFFFFFF) {
+    qh_fprintf(qh ferr, 6159, "qhull error: more than %d vertices.  ID field overflows and two vertices\n\
+may have the same identifier.  Vertices will not be sorted correctly.\n", 0xFFFFFF);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }
+  if (qh vertex_id == qh tracevertex_id)
+    qh tracevertex= vertex;
+  vertex->id= qh vertex_id++;
+  vertex->point= point;
+  vertex->dim= (unsigned char)(qh hull_dim <= MAX_vdim ? qh hull_dim : 0);
+  trace4((qh ferr, 4060, "qh_newvertex: vertex p%d(v%d) created\n", qh_pointid(vertex->point),
+          vertex->id));
+  return(vertex);
+} /* newvertex */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="nextridge3d">-</a>
+
+  qh_nextridge3d( atridge, facet, vertex )
+    return next ridge and vertex for a 3d facet
+    returns NULL on error
+    [for QhullFacet::nextRidge3d] Does not call qh_errexit nor access qh_qh.
+
+  notes:
+    in qh_ORIENTclock order
+    this is a O(n^2) implementation to trace all ridges
+    be sure to stop on any 2nd visit
+    same as QhullRidge::nextRidge3d
+    does not use qh_qh or qh_errexit [QhullFacet.cpp]
+
+  design:
+    for each ridge
+      exit if it is the ridge after atridge
+*/
+ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
+  vertexT *atvertex, *vertex, *othervertex;
+  ridgeT *ridge, **ridgep;
+
+  if ((atridge->top == facet) ^ qh_ORIENTclock)
+    atvertex= SETsecondt_(atridge->vertices, vertexT);
+  else
+    atvertex= SETfirstt_(atridge->vertices, vertexT);
+  FOREACHridge_(facet->ridges) {
+    if (ridge == atridge)
+      continue;
+    if ((ridge->top == facet) ^ qh_ORIENTclock) {
+      othervertex= SETsecondt_(ridge->vertices, vertexT);
+      vertex= SETfirstt_(ridge->vertices, vertexT);
+    }else {
+      vertex= SETsecondt_(ridge->vertices, vertexT);
+      othervertex= SETfirstt_(ridge->vertices, vertexT);
+    }
+    if (vertex == atvertex) {
+      if (vertexp)
+        *vertexp= othervertex;
+      return ridge;
+    }
+  }
+  return NULL;
+} /* nextridge3d */
+#else /* qh_NOmerge */
+void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
+}
+ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
+
+  return NULL;
+}
+#endif /* qh_NOmerge */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="outcoplanar">-</a>
+
+  qh_outcoplanar()
+    move points from all facets' outsidesets to their coplanarsets
+
+  notes:
+    for post-processing under qh.NARROWhull
+
+  design:
+    for each facet
+      for each outside point for facet
+        partition point into coplanar set
+*/
+void qh_outcoplanar(void /* facet_list */) {
+  pointT *point, **pointp;
+  facetT *facet;
+  realT dist;
+
+  trace1((qh ferr, 1033, "qh_outcoplanar: move outsideset to coplanarset for qh NARROWhull\n"));
+  FORALLfacets {
+    FOREACHpoint_(facet->outsideset) {
+      qh num_outside--;
+      if (qh KEEPcoplanar || qh KEEPnearinside) {
+        qh_distplane(point, facet, &dist);
+        zinc_(Zpartition);
+        qh_partitioncoplanar(point, facet, &dist);
+      }
+    }
+    qh_setfree(&facet->outsideset);
+  }
+} /* outcoplanar */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="point">-</a>
+
+  qh_point( id )
+    return point for a point id, or NULL if unknown
+
+  alternative code:
+    return((pointT *)((unsigned   long)qh.first_point
+           + (unsigned long)((id)*qh.normal_size)));
+*/
+pointT *qh_point(int id) {
+
+  if (id < 0)
+    return NULL;
+  if (id < qh num_points)
+    return qh first_point + id * qh hull_dim;
+  id -= qh num_points;
+  if (id < qh_setsize(qh other_points))
+    return SETelemt_(qh other_points, id, pointT);
+  return NULL;
+} /* point */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="point_add">-</a>
+
+  qh_point_add( set, point, elem )
+    stores elem at set[point.id]
+
+  returns:
+    access function for qh_pointfacet and qh_pointvertex
+
+  notes:
+    checks point.id
+*/
+void qh_point_add(setT *set, pointT *point, void *elem) {
+  int id, size;
+
+  SETreturnsize_(set, size);
+  if ((id= qh_pointid(point)) < 0)
+    qh_fprintf(qh ferr, 7067, "qhull internal warning (point_add): unknown point %p id %d\n",
+      point, id);
+  else if (id >= size) {
+    qh_fprintf(qh ferr, 6160, "qhull internal error(point_add): point p%d is out of bounds(%d)\n",
+             id, size);
+    qh_errexit(qh_ERRqhull, NULL, NULL);
+  }else
+    SETelem_(set, id)= elem;
+} /* point_add */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="pointfacet">-</a>
+
+  qh_pointfacet()
+    return temporary set of facet for each point
+    the set is indexed by point id
+
+  notes:
+    vertices assigned to one of the facets
+    coplanarset assigned to the facet
+    outside set assigned to the facet
+    NULL if no facet for point (inside)
+      includes qh.GOODpointp
+
+  access:
+    FOREACHfacet_i_(facets) { ... }
+    SETelem_(facets, i)
+
+  design:
+    for each facet
+      add each vertex
+      add each coplanar point
+      add each outside point
+*/
+setT *qh_pointfacet(void /*qh facet_list*/) {
+  int numpoints= qh num_points + qh_setsize(qh other_points);
+  setT *facets;
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+  pointT *point, **pointp;
+
+  facets= qh_settemp(numpoints);
+  qh_setzero(facets, 0, numpoints);
+  qh vertex_visit++;
+  FORALLfacets {
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        vertex->visitid= qh vertex_visit;
+        qh_point_add(facets, vertex->point, facet);
+      }
+    }
+    FOREACHpoint_(facet->coplanarset)
+      qh_point_add(facets, point, facet);
+    FOREACHpoint_(facet->outsideset)
+      qh_point_add(facets, point, facet);
+  }
+  return facets;
+} /* pointfacet */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="pointvertex">-</a>
+
+  qh_pointvertex(  )
+    return temporary set of vertices indexed by point id
+    entry is NULL if no vertex for a point
+      this will include qh.GOODpointp
+
+  access:
+    FOREACHvertex_i_(vertices) { ... }
+    SETelem_(vertices, i)
+*/
+setT *qh_pointvertex(void /*qh facet_list*/) {
+  int numpoints= qh num_points + qh_setsize(qh other_points);
+  setT *vertices;
+  vertexT *vertex;
+
+  vertices= qh_settemp(numpoints);
+  qh_setzero(vertices, 0, numpoints);
+  FORALLvertices
+    qh_point_add(vertices, vertex->point, vertex);
+  return vertices;
+} /* pointvertex */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="prependfacet">-</a>
+
+  qh_prependfacet( facet, facetlist )
+    prepend facet to the start of a facetlist
+
+  returns:
+    increments qh.numfacets
+    updates facetlist, qh.facet_list, facet_next
+
+  notes:
+    be careful of prepending since it can lose a pointer.
+      e.g., can lose _next by deleting and then prepending before _next
+*/
+void qh_prependfacet(facetT *facet, facetT **facetlist) {
+  facetT *prevfacet, *list;
+
+
+  trace4((qh ferr, 4061, "qh_prependfacet: prepend f%d before f%d\n",
+          facet->id, getid_(*facetlist)));
+  if (!*facetlist)
+    (*facetlist)= qh facet_tail;
+  list= *facetlist;
+  prevfacet= list->previous;
+  facet->previous= prevfacet;
+  if (prevfacet)
+    prevfacet->next= facet;
+  list->previous= facet;
+  facet->next= *facetlist;
+  if (qh facet_list == list)  /* this may change *facetlist */
+    qh facet_list= facet;
+  if (qh facet_next == list)
+    qh facet_next= facet;
+  *facetlist= facet;
+  qh num_facets++;
+} /* prependfacet */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="printhashtable">-</a>
+
+  qh_printhashtable( fp )
+    print hash table to fp
+
+  notes:
+    not in I/O to avoid bringing io.c in
+
+  design:
+    for each hash entry
+      if defined
+        if unmatched or will merge (NULL, qh_MERGEridge, qh_DUPLICATEridge)
+          print entry and neighbors
+*/
+void qh_printhashtable(FILE *fp) {
+  facetT *facet, *neighbor;
+  int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
+  vertexT *vertex, **vertexp;
+
+  FOREACHfacet_i_(qh hash_table) {
+    if (facet) {
+      FOREACHneighbor_i_(facet) {
+        if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
+          break;
+      }
+      if (neighbor_i == neighbor_n)
+        continue;
+      qh_fprintf(fp, 9283, "hash %d f%d ", facet_i, facet->id);
+      FOREACHvertex_(facet->vertices)
+        qh_fprintf(fp, 9284, "v%d ", vertex->id);
+      qh_fprintf(fp, 9285, "\n neighbors:");
+      FOREACHneighbor_i_(facet) {
+        if (neighbor == qh_MERGEridge)
+          id= -3;
+        else if (neighbor == qh_DUPLICATEridge)
+          id= -2;
+        else
+          id= getid_(neighbor);
+        qh_fprintf(fp, 9286, " %d", id);
+      }
+      qh_fprintf(fp, 9287, "\n");
+    }
+  }
+} /* printhashtable */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="printlists">-</a>
+
+  qh_printlists( fp )
+    print out facet and vertex list for debugging (without 'f/v' tags)
+*/
+void qh_printlists(void) {
+  facetT *facet;
+  vertexT *vertex;
+  int count= 0;
+
+  qh_fprintf(qh ferr, 8108, "qh_printlists: facets:");
+  FORALLfacets {
+    if (++count % 100 == 0)
+      qh_fprintf(qh ferr, 8109, "\n     ");
+    qh_fprintf(qh ferr, 8110, " %d", facet->id);
+  }
+  qh_fprintf(qh ferr, 8111, "\n  new facets %d visible facets %d next facet for qh_addpoint %d\n  vertices(new %d):",
+     getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
+     getid_(qh newvertex_list));
+  count = 0;
+  FORALLvertices {
+    if (++count % 100 == 0)
+      qh_fprintf(qh ferr, 8112, "\n     ");
+    qh_fprintf(qh ferr, 8113, " %d", vertex->id);
+  }
+  qh_fprintf(qh ferr, 8114, "\n");
+} /* printlists */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="resetlists">-</a>
+
+  qh_resetlists( stats, qh_RESETvisible )
+    reset newvertex_list, newfacet_list, visible_list
+    if stats,
+      maintains statistics
+
+  returns:
+    visible_list is empty if qh_deletevisible was called
+*/
+void qh_resetlists(boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/) {
+  vertexT *vertex;
+  facetT *newfacet, *visible;
+  int totnew=0, totver=0;
+
+  if (stats) {
+    FORALLvertex_(qh newvertex_list)
+      totver++;
+    FORALLnew_facets
+      totnew++;
+    zadd_(Zvisvertextot, totver);
+    zmax_(Zvisvertexmax, totver);
+    zadd_(Znewfacettot, totnew);
+    zmax_(Znewfacetmax, totnew);
+  }
+  FORALLvertex_(qh newvertex_list)
+    vertex->newlist= False;
+  qh newvertex_list= NULL;
+  FORALLnew_facets
+    newfacet->newfacet= False;
+  qh newfacet_list= NULL;
+  if (resetVisible) {
+    FORALLvisible_facets {
+      visible->f.replace= NULL;
+      visible->visible= False;
+    }
+    qh num_visible= 0;
+  }
+  qh visible_list= NULL; /* may still have visible facets via qh_triangulate */
+  qh NEWfacets= False;
+} /* resetlists */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="setvoronoi_all">-</a>
+
+  qh_setvoronoi_all()
+    compute Voronoi centers for all facets
+    includes upperDelaunay facets if qh.UPPERdelaunay ('Qu')
+
+  returns:
+    facet->center is the Voronoi center
+
+  notes:
+    this is unused/untested code
+      please email bradb at shore.net if this works ok for you
+
+  use:
+    FORALLvertices {...} to locate the vertex for a point.
+    FOREACHneighbor_(vertex) {...} to visit the Voronoi centers for a Voronoi cell.
+*/
+void qh_setvoronoi_all(void) {
+  facetT *facet;
+
+  qh_clearcenters(qh_ASvoronoi);
+  qh_vertexneighbors();
+
+  FORALLfacets {
+    if (!facet->normal || !facet->upperdelaunay || qh UPPERdelaunay) {
+      if (!facet->center)
+        facet->center= qh_facetcenter(facet->vertices);
+    }
+  }
+} /* setvoronoi_all */
+
+#ifndef qh_NOmerge
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate">-</a>
+
+  qh_triangulate()
+    triangulate non-simplicial facets on qh.facet_list,
+    if qh VORONOI, sets Voronoi centers of non-simplicial facets
+    nop if hasTriangulation
+
+  returns:
+    all facets simplicial
+    each tricoplanar facet has ->f.triowner == owner of ->center,normal,etc.
+
+  notes:
+    call after qh_check_output since may switch to Voronoi centers
+    Output may overwrite ->f.triowner with ->f.area
+*/
+void qh_triangulate(void /*qh facet_list*/) {
+  facetT *facet, *nextfacet, *owner;
+  int onlygood= qh ONLYgood;
+  facetT *neighbor, *visible= NULL, *facet1, *facet2, *new_facet_list= NULL;
+  facetT *orig_neighbor= NULL, *otherfacet;
+  vertexT *new_vertex_list= NULL;
+  mergeT *merge;
+  mergeType mergetype;
+  int neighbor_i, neighbor_n;
+
+  if (qh hasTriangulation)
+      return;
+  trace1((qh ferr, 1034, "qh_triangulate: triangulate non-simplicial facets\n"));
+  if (qh hull_dim == 2)
+    return;
+  if (qh VORONOI) {  /* otherwise lose Voronoi centers [could rebuild vertex set from tricoplanar] */
+    qh_clearcenters(qh_ASvoronoi);
+    qh_vertexneighbors();
+  }
+  qh ONLYgood= False; /* for makenew_nonsimplicial */
+  qh visit_id++;
+  qh NEWfacets= True;
+  qh degen_mergeset= qh_settemp(qh TEMPsize);
+  qh newvertex_list= qh vertex_tail;
+  for (facet= qh facet_list; facet && facet->next; facet= nextfacet) { /* non-simplicial facets moved to end */
+    nextfacet= facet->next;
+    if (facet->visible || facet->simplicial)
+      continue;
+    /* triangulate all non-simplicial facets, otherwise merging does not work, e.g., RBOX c P-0.1 P+0.1 P+0.1 D3 | QHULL d Qt Tv */
+    if (!new_facet_list)
+      new_facet_list= facet;  /* will be moved to end */
+    qh_triangulate_facet(facet, &new_vertex_list);
+  }
+  trace2((qh ferr, 2047, "qh_triangulate: delete null facets from f%d -- apex same as second vertex\n", getid_(new_facet_list)));
+  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* null facets moved to end */
+    nextfacet= facet->next;
+    if (facet->visible)
+      continue;
+    if (facet->ridges) {
+      if (qh_setsize(facet->ridges) > 0) {
+        qh_fprintf(qh ferr, 6161, "qhull error (qh_triangulate): ridges still defined for f%d\n", facet->id);
+        qh_errexit(qh_ERRqhull, facet, NULL);
+      }
+      qh_setfree(&facet->ridges);
+    }
+    if (SETfirst_(facet->vertices) == SETsecond_(facet->vertices)) {
+      zinc_(Ztrinull);
+      qh_triangulate_null(facet);
+    }
+  }
+  trace2((qh ferr, 2048, "qh_triangulate: delete %d or more mirror facets -- same vertices and neighbors\n", qh_setsize(qh degen_mergeset)));
+  qh visible_list= qh facet_tail;
+  while ((merge= (mergeT*)qh_setdellast(qh degen_mergeset))) {
+    facet1= merge->facet1;
+    facet2= merge->facet2;
+    mergetype= merge->type;
+    qh_memfree(merge, (int)sizeof(mergeT));
+    if (mergetype == MRGmirror) {
+      zinc_(Ztrimirror);
+      qh_triangulate_mirror(facet1, facet2);
+    }
+  }
+  qh_settempfree(&qh degen_mergeset);
+  trace2((qh ferr, 2049, "qh_triangulate: update neighbor lists for vertices from v%d\n", getid_(new_vertex_list)));
+  qh newvertex_list= new_vertex_list;  /* all vertices of new facets */
+  qh visible_list= NULL;
+  qh_updatevertices(/*qh newvertex_list, empty newfacet_list and visible_list*/);
+  qh_resetlists(False, !qh_RESETvisible /*qh newvertex_list, empty newfacet_list and visible_list*/);
+
+  trace2((qh ferr, 2050, "qh_triangulate: identify degenerate tricoplanar facets from f%d\n", getid_(new_facet_list)));
+  trace2((qh ferr, 2051, "qh_triangulate: and replace facet->f.triowner with tricoplanar facets that own center, normal, etc.\n"));
+  FORALLfacet_(new_facet_list) {
+    if (facet->tricoplanar && !facet->visible) {
+      FOREACHneighbor_i_(facet) {
+        if (neighbor_i == 0) {  /* first iteration */
+          if (neighbor->tricoplanar)
+            orig_neighbor= neighbor->f.triowner;
+          else
+            orig_neighbor= neighbor;
+        }else {
+          if (neighbor->tricoplanar)
+            otherfacet= neighbor->f.triowner;
+          else
+            otherfacet= neighbor;
+          if (orig_neighbor == otherfacet) {
+            zinc_(Ztridegen);
+            facet->degenerate= True;
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  trace2((qh ferr, 2052, "qh_triangulate: delete visible facets -- non-simplicial, null, and mirrored facets\n"));
+  owner= NULL;
+  visible= NULL;
+  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* may delete facet */
+    nextfacet= facet->next;
+    if (facet->visible) {
+      if (facet->tricoplanar) { /* a null or mirrored facet */
+        qh_delfacet(facet);
+        qh num_visible--;
+      }else {  /* a non-simplicial facet followed by its tricoplanars */
+        if (visible && !owner) {
+          /*  RBOX 200 s D5 t1001471447 | QHULL Qt C-0.01 Qx Qc Tv Qt -- f4483 had 6 vertices/neighbors and 8 ridges */
+          trace2((qh ferr, 2053, "qh_triangulate: all tricoplanar facets degenerate for non-simplicial facet f%d\n",
+                       visible->id));
+          qh_delfacet(visible);
+          qh num_visible--;
+        }
+        visible= facet;
+        owner= NULL;
+      }
+    }else if (facet->tricoplanar) {
+      if (facet->f.triowner != visible) {
+        qh_fprintf(qh ferr, 6162, "qhull error (qh_triangulate): tricoplanar facet f%d not owned by its visible, non-simplicial facet f%d\n", facet->id, getid_(visible));
+        qh_errexit2 (qh_ERRqhull, facet, visible);
+      }
+      if (owner)
+        facet->f.triowner= owner;
+      else if (visible != NULL && !facet->degenerate) {
+        owner= facet;
+        nextfacet= visible->next; /* rescan tricoplanar facets with owner */
+        facet->keepcentrum= True;  /* one facet owns ->normal, etc. */
+        facet->coplanarset= visible->coplanarset;
+        facet->outsideset= visible->outsideset;
+        visible->coplanarset= NULL;
+        visible->outsideset= NULL;
+        if (!qh TRInormals) { /* center and normal copied to tricoplanar facets */
+          visible->center= NULL;
+          visible->normal= NULL;
+        }
+        qh_delfacet(visible);
+        qh num_visible--;
+      }
+    }
+  }
+  if (visible && !owner) {
+    trace2((qh ferr, 2054, "qh_triangulate: all tricoplanar facets degenerate for last non-simplicial facet f%d\n",
+                 visible->id));
+    qh_delfacet(visible);
+    qh num_visible--;
+  }
+  qh NEWfacets= False;
+  qh ONLYgood= onlygood; /* restore value */
+  if (qh CHECKfrequently)
+    qh_checkpolygon(qh facet_list);
+  qh hasTriangulation= True;
+} /* triangulate */
+
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate_facet">-</a>
+
+  qh_triangulate_facet(facetA)
+    triangulate a non-simplicial facet
+      if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center
+  returns:
+    qh.newfacet_list == simplicial facets
+      facet->tricoplanar set and ->keepcentrum false
+      facet->degenerate set if duplicated apex
+      facet->f.trivisible set to facetA
+      facet->center copied from facetA (created if qh_ASvoronoi)
+        qh_eachvoronoi, qh_detvridge, qh_detvridge3 assume centers copied
+      facet->normal,offset,maxoutside copied from facetA
+
+  notes:
+      qh_makenew_nonsimplicial uses neighbor->seen for the same
+
+  see also:
+      qh_addpoint() -- add a point
+      qh_makenewfacets() -- construct a cone of facets for a new vertex
+
+  design:
+      if qh_ASvoronoi,
+         compute Voronoi center (facet->center)
+      select first vertex (highest ID to preserve ID ordering of ->vertices)
+      triangulate from vertex to ridges
+      copy facet->center, normal, offset
+      update vertex neighbors
+*/
+void qh_triangulate_facet(facetT *facetA, vertexT **first_vertex) {
+  facetT *newfacet;
+  facetT *neighbor, **neighborp;
+  vertexT *apex;
+  int numnew=0;
+
+  trace3((qh ferr, 3020, "qh_triangulate_facet: triangulate facet f%d\n", facetA->id));
+
+  if (qh IStracing >= 4)
+    qh_printfacet(qh ferr, facetA);
+  FOREACHneighbor_(facetA) {
+    neighbor->seen= False;
+    neighbor->coplanar= False;
+  }
+  if (qh CENTERtype == qh_ASvoronoi && !facetA->center  /* matches upperdelaunay in qh_setfacetplane() */
+        && fabs_(facetA->normal[qh hull_dim -1]) >= qh ANGLEround * qh_ZEROdelaunay) {
+    facetA->center= qh_facetcenter(facetA->vertices);
+  }
+  qh_willdelete(facetA, NULL);
+  qh newfacet_list= qh facet_tail;
+  facetA->visitid= qh visit_id;
+  apex= SETfirstt_(facetA->vertices, vertexT);
+  qh_makenew_nonsimplicial(facetA, apex, &numnew);
+  SETfirst_(facetA->neighbors)= NULL;
+  FORALLnew_facets {
+    newfacet->tricoplanar= True;
+    newfacet->f.trivisible= facetA;
+    newfacet->degenerate= False;
+    newfacet->upperdelaunay= facetA->upperdelaunay;
+    newfacet->good= facetA->good;
+    if (qh TRInormals) {
+      newfacet->keepcentrum= True;
+      newfacet->normal= qh_copypoints(facetA->normal, 1, qh hull_dim);
+      if (qh CENTERtype == qh_AScentrum)
+        newfacet->center= qh_getcentrum(newfacet);
+      else
+        newfacet->center= qh_copypoints(facetA->center, 1, qh hull_dim);
+    }else {
+      newfacet->keepcentrum= False;
+      newfacet->normal= facetA->normal;
+      newfacet->center= facetA->center;
+    }
+    newfacet->offset= facetA->offset;
+#if qh_MAXoutside
+    newfacet->maxoutside= facetA->maxoutside;
+#endif
+  }
+  qh_matchnewfacets(/*qh newfacet_list*/);
+  zinc_(Ztricoplanar);
+  zadd_(Ztricoplanartot, numnew);
+  zmax_(Ztricoplanarmax, numnew);
+  qh visible_list= NULL;
+  if (!(*first_vertex))
+    (*first_vertex)= qh newvertex_list;
+  qh newvertex_list= NULL;
+  qh_updatevertices(/*qh newfacet_list, empty visible_list and newvertex_list*/);
+  qh_resetlists(False, !qh_RESETvisible /*qh newfacet_list, empty visible_list and newvertex_list*/);
+} /* triangulate_facet */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate_link">-</a>
+
+  qh_triangulate_link(oldfacetA, facetA, oldfacetB, facetB)
+    relink facetA to facetB via oldfacets
+  returns:
+    adds mirror facets to qh degen_mergeset (4-d and up only)
+  design:
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_link(facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB) {
+  int errmirror= False;
+
+  trace3((qh ferr, 3021, "qh_triangulate_link: relink old facets f%d and f%d between neighbors f%d and f%d\n",
+         oldfacetA->id, oldfacetB->id, facetA->id, facetB->id));
+  if (qh_setin(facetA->neighbors, facetB)) {
+    if (!qh_setin(facetB->neighbors, facetA))
+      errmirror= True;
+    else
+      qh_appendmergeset(facetA, facetB, MRGmirror, NULL);
+  }else if (qh_setin(facetB->neighbors, facetA))
+    errmirror= True;
+  if (errmirror) {
+    qh_fprintf(qh ferr, 6163, "qhull error (qh_triangulate_link): mirror facets f%d and f%d do not match for old facets f%d and f%d\n",
+       facetA->id, facetB->id, oldfacetA->id, oldfacetB->id);
+    qh_errexit2 (qh_ERRqhull, facetA, facetB);
+  }
+  qh_setreplace(facetB->neighbors, oldfacetB, facetA);
+  qh_setreplace(facetA->neighbors, oldfacetA, facetB);
+} /* triangulate_link */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate_mirror">-</a>
+
+  qh_triangulate_mirror(facetA, facetB)
+    delete mirrored facets from qh_triangulate_null() and qh_triangulate_mirror
+      a mirrored facet shares the same vertices of a logical ridge
+  design:
+    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_mirror(facetT *facetA, facetT *facetB) {
+  facetT *neighbor, *neighborB;
+  int neighbor_i, neighbor_n;
+
+  trace3((qh ferr, 3022, "qh_triangulate_mirror: delete mirrored facets f%d and f%d\n",
+         facetA->id, facetB->id));
+  FOREACHneighbor_i_(facetA) {
+    neighborB= SETelemt_(facetB->neighbors, neighbor_i, facetT);
+    if (neighbor == neighborB)
+      continue; /* occurs twice */
+    qh_triangulate_link(facetA, neighbor, facetB, neighborB);
+  }
+  qh_willdelete(facetA, NULL);
+  qh_willdelete(facetB, NULL);
+} /* triangulate_mirror */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="triangulate_null">-</a>
+
+  qh_triangulate_null(facetA)
+    remove null facetA from qh_triangulate_facet()
+      a null facet has vertex #1 (apex) == vertex #2
+  returns:
+    adds facetA to ->visible for deletion after qh_updatevertices
+    qh degen_mergeset contains mirror facets (4-d and up only)
+  design:
+    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
+    if they are already neighbors, the opposing neighbors become MRGmirror facets
+*/
+void qh_triangulate_null(facetT *facetA) {
+  facetT *neighbor, *otherfacet;
+
+  trace3((qh ferr, 3023, "qh_triangulate_null: delete null facet f%d\n", facetA->id));
+  neighbor= SETfirstt_(facetA->neighbors, facetT);
+  otherfacet= SETsecondt_(facetA->neighbors, facetT);
+  qh_triangulate_link(facetA, neighbor, facetA, otherfacet);
+  qh_willdelete(facetA, NULL);
+} /* triangulate_null */
+
+#else /* qh_NOmerge */
+void qh_triangulate(void) {
+}
+#endif /* qh_NOmerge */
+
+   /*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="vertexintersect">-</a>
+
+  qh_vertexintersect( vertexsetA, vertexsetB )
+    intersects two vertex sets (inverse id ordered)
+    vertexsetA is a temporary set at the top of qhmem.tempstack
+
+  returns:
+    replaces vertexsetA with the intersection
+
+  notes:
+    could overwrite vertexsetA if currently too slow
+*/
+void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
+  setT *intersection;
+
+  intersection= qh_vertexintersect_new(*vertexsetA, vertexsetB);
+  qh_settempfree(vertexsetA);
+  *vertexsetA= intersection;
+  qh_settemppush(intersection);
+} /* vertexintersect */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="vertexintersect_new">-</a>
+
+  qh_vertexintersect_new(  )
+    intersects two vertex sets (inverse id ordered)
+
+  returns:
+    a new set
+*/
+setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB) {
+  setT *intersection= qh_setnew(qh hull_dim - 1);
+  vertexT **vertexA= SETaddr_(vertexsetA, vertexT);
+  vertexT **vertexB= SETaddr_(vertexsetB, vertexT);
+
+  while (*vertexA && *vertexB) {
+    if (*vertexA  == *vertexB) {
+      qh_setappend(&intersection, *vertexA);
+      vertexA++; vertexB++;
+    }else {
+      if ((*vertexA)->id > (*vertexB)->id)
+        vertexA++;
+      else
+        vertexB++;
+    }
+  }
+  return intersection;
+} /* vertexintersect_new */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="vertexneighbors">-</a>
+
+  qh_vertexneighbors()
+    for each vertex in qh.facet_list,
+      determine its neighboring facets
+
+  returns:
+    sets qh.VERTEXneighbors
+      nop if qh.VERTEXneighbors already set
+      qh_addpoint() will maintain them
+
+  notes:
+    assumes all vertex->neighbors are NULL
+
+  design:
+    for each facet
+      for each vertex
+        append facet to vertex->neighbors
+*/
+void qh_vertexneighbors(void /*qh facet_list*/) {
+  facetT *facet;
+  vertexT *vertex, **vertexp;
+
+  if (qh VERTEXneighbors)
+    return;
+  trace1((qh ferr, 1035, "qh_vertexneighbors: determine neighboring facets for each vertex\n"));
+  qh vertex_visit++;
+  FORALLfacets {
+    if (facet->visible)
+      continue;
+    FOREACHvertex_(facet->vertices) {
+      if (vertex->visitid != qh vertex_visit) {
+        vertex->visitid= qh vertex_visit;
+        vertex->neighbors= qh_setnew(qh hull_dim);
+      }
+      qh_setappend(&vertex->neighbors, facet);
+    }
+  }
+  qh VERTEXneighbors= True;
+} /* vertexneighbors */
+
+/*-<a                             href="qh-poly.htm#TOC"
+  >-------------------------------</a><a name="vertexsubset">-</a>
+
+  qh_vertexsubset( vertexsetA, vertexsetB )
+    returns True if vertexsetA is a subset of vertexsetB
+    assumes vertexsets are sorted
+
+  note:
+    empty set is a subset of any other set
+*/
+boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
+  vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
+  vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
+
+  while (True) {
+    if (!*vertexA)
+      return True;
+    if (!*vertexB)
+      return False;
+    if ((*vertexA)->id > (*vertexB)->id)
+      return False;
+    if (*vertexA  == *vertexB)
+      vertexA++;
+    vertexB++;
+  }
+  return False; /* avoid warnings */
+} /* vertexsubset */
diff --git a/alg/libqhull/qhull_a.h b/alg/internal_libqhull/qhull_a.h
similarity index 100%
rename from alg/libqhull/qhull_a.h
rename to alg/internal_libqhull/qhull_a.h
diff --git a/alg/libqhull/qset.c b/alg/internal_libqhull/qset.c
similarity index 100%
rename from alg/libqhull/qset.c
rename to alg/internal_libqhull/qset.c
diff --git a/alg/libqhull/qset.h b/alg/internal_libqhull/qset.h
similarity index 100%
rename from alg/libqhull/qset.h
rename to alg/internal_libqhull/qset.h
diff --git a/alg/libqhull/random.c b/alg/internal_libqhull/random.c
similarity index 100%
rename from alg/libqhull/random.c
rename to alg/internal_libqhull/random.c
diff --git a/alg/libqhull/random.h b/alg/internal_libqhull/random.h
similarity index 100%
rename from alg/libqhull/random.h
rename to alg/internal_libqhull/random.h
diff --git a/alg/internal_libqhull/rboxlib.c b/alg/internal_libqhull/rboxlib.c
new file mode 100644
index 0000000..b29a4d3
--- /dev/null
+++ b/alg/internal_libqhull/rboxlib.c
@@ -0,0 +1,793 @@
+/*<html><pre>  -<a                             href="index.htm#TOC"
+  >-------------------------------</a><a name="TOP">-</a>
+
+   rboxlib.c
+     Generate input points
+
+   notes:
+     For documentation, see prompt[] of rbox.c
+     50 points generated for 'rbox D4'
+
+   WARNING:
+     incorrect range if qh_RANDOMmax is defined wrong (user.h)
+*/
+
+#include "random.h"
+#include "libqhull.h"
+
+#include <ctype.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER  /* Microsoft Visual C++ */
+#pragma warning( disable : 4706)  /* assignment within conditional expression. */
+#pragma warning( disable : 4996)  /* this function (strncat,sprintf,strcpy) or variable may be unsafe. */
+#endif
+
+#define MAXdim 200
+
+/* ------------------------------ prototypes ----------------*/
+int roundi( double a);
+void out1( double a);
+void out2n( double a, double b);
+void out3n( double a, double b, double c);
+
+void    qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
+void    qh_free(void *mem);
+void   *qh_malloc(size_t size);
+int     qh_rand( void);
+void    qh_srand( int seed);
+
+
+/* ------------------------------ globals -------------------*/
+
+/* No state is carried between rbox requests */
+typedef struct rboxT rboxT;
+struct rboxT {
+  FILE *fout;
+  FILE *ferr;
+  int isinteger;
+  double out_offset;
+  jmp_buf errexit;        /* exit label for rboxpoints, defined by setjmp(), called by qh_errexit_rbox() */
+};
+
+
+int rbox_inuse= 0;
+rboxT rbox;
+
+/*-<a                             href="qh-qhull.htm#TOC"
+  >-------------------------------</a><a name="rboxpoints">-</a>
+
+  qh_rboxpoints( fout, ferr, rbox_command )
+    Generate points to fout according to rbox options
+    Report errors on ferr
+
+  returns:
+    0 (qh_ERRnone) on success
+    1 (qh_ERRinput) on input error
+    4 (qh_ERRmem) on memory error
+    5 (qh_ERRqhull) on internal error
+
+  notes:
+    To avoid stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user.c)
+    Rbox is not multithreaded.
+
+  design:
+    Straight line code (consider defining a struct and functions):
+
+    Parse arguments into variables
+    Determine the number of points
+    Generate the points
+*/
+int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
+  int i,j,k;
+  int gendim;
+  int cubesize, diamondsize, seed=0, count, apex;
+  int dim=3 , numpoints= 0, totpoints, addpoints=0;
+  int issphere=0, isaxis=0,  iscdd= 0, islens= 0, isregular=0, iswidth=0, addcube=0;
+  int isgap=0, isspiral=0, NOcommand= 0, adddiamond=0;
+  int israndom=0, istime=0;
+  int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
+  double width=0.0, gap=0.0, radius= 0.0;
+  double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
+  double *simplex= NULL, *simplexp;
+  int nthroot, mult[MAXdim];
+  double norm, factor, randr, rangap, lensangle= 0, lensbase= 1;
+  double anglediff, angle, x, y, cube= 0.0, diamond= 0.0;
+  double box= qh_DEFAULTbox; /* scale all numbers before output */
+  double randmax= qh_RANDOMmax;
+  char command[200], seedbuf[200];
+  char *s= command, *t, *first_point= NULL;
+  time_t timedata = 0;
+  int exitcode;
+
+  if (rbox_inuse) {
+    qh_fprintf_rbox(rbox.ferr, 6188, "rbox error: rbox in use by another process.  Please lock calls to rbox.\n");
+    return qh_ERRqhull;
+  }
+  rbox_inuse= True;
+  rbox.ferr= ferr;
+  rbox.fout= fout;
+
+  exitcode= setjmp(rbox.errexit);
+  if (exitcode) {
+    /* same code for error exit and normal return */
+    if (simplex)
+        qh_free(simplex);
+    rbox_inuse= False;
+    return exitcode;
+  }
+
+  *command= '\0';
+  strncat(command, rbox_command, sizeof(command)-strlen(command)-1);
+
+  while (*s && !isspace(*s))  /* skip program name */
+    s++;
+  while (*s) {
+    while (*s && isspace(*s))
+      s++;
+    if (*s == '-')
+      s++;
+    if (!*s)
+      break;
+    if (isdigit(*s)) {
+      numpoints= qh_strtol(s, &s);
+      continue;
+    }
+    /* ============= read flags =============== */
+    switch (*s++) {
+    case 'c':
+      addcube= 1;
+      t= s;
+      while (isspace(*t))
+        t++;
+      if (*t == 'G')
+        cube= qh_strtod(++t, &s);
+      break;
+    case 'd':
+      adddiamond= 1;
+      t= s;
+      while (isspace(*t))
+        t++;
+      if (*t == 'G')
+        diamond= qh_strtod(++t, &s);
+      break;
+    case 'h':
+      iscdd= 1;
+      break;
+    case 'l':
+      isspiral= 1;
+      break;
+    case 'n':
+      NOcommand= 1;
+      break;
+    case 'r':
+      isregular= 1;
+      break;
+    case 's':
+      issphere= 1;
+      break;
+    case 't':
+      istime= 1;
+      if (isdigit(*s)) {
+        seed= qh_strtol(s, &s);
+        israndom= 0;
+      }else
+        israndom= 1;
+      break;
+    case 'x':
+      issimplex= 1;
+      break;
+    case 'y':
+      issimplex2= 1;
+      break;
+    case 'z':
+      rbox.isinteger= 1;
+      break;
+    case 'B':
+      box= qh_strtod(s, &s);
+      isbox= 1;
+      break;
+    case 'D':
+      dim= qh_strtol(s, &s);
+      if (dim < 1
+      || dim > MAXdim) {
+        qh_fprintf_rbox(rbox.ferr, 6189, "rbox error: dimension, D%d, out of bounds (>=%d or <=0)", dim, MAXdim);
+        qh_errexit_rbox(qh_ERRinput);
+      }
+      break;
+    case 'G':
+      if (isdigit(*s))
+        gap= qh_strtod(s, &s);
+      else
+        gap= 0.5;
+      isgap= 1;
+      break;
+    case 'L':
+      if (isdigit(*s))
+        radius= qh_strtod(s, &s);
+      else
+        radius= 10;
+      islens= 1;
+      break;
+    case 'M':
+      ismesh= 1;
+      if (*s)
+        meshn= qh_strtod(s, &s);
+      if (*s == ',') {
+        ++s;
+        meshm= qh_strtod(s, &s);
+      }else
+        meshm= 0.0;
+      if (*s == ',') {
+        ++s;
+        meshr= qh_strtod(s, &s);
+      }else
+        meshr= sqrt(meshn*meshn + meshm*meshm);
+      if (*s && !isspace(*s)) {
+        qh_fprintf_rbox(rbox.ferr, 7069, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
+        meshn= 3.0, meshm=4.0, meshr=5.0;
+      }
+      break;
+    case 'O':
+      rbox.out_offset= qh_strtod(s, &s);
+      break;
+    case 'P':
+      if (!first_point)
+        first_point= s-1;
+      addpoints++;
+      while (*s && !isspace(*s))   /* read points later */
+        s++;
+      break;
+    case 'W':
+      width= qh_strtod(s, &s);
+      iswidth= 1;
+      break;
+    case 'Z':
+      if (isdigit(*s))
+        radius= qh_strtod(s, &s);
+      else
+        radius= 1.0;
+      isaxis= 1;
+      break;
+    default:
+      qh_fprintf_rbox(rbox.ferr, 7070, "rbox error: unknown flag at %s.\nExecute 'rbox' without arguments for documentation.\n", s);
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    if (*s && !isspace(*s)) {
+      qh_fprintf_rbox(rbox.ferr, 7071, "rbox error: missing space between flags at %s.\n", s);
+      qh_errexit_rbox(qh_ERRinput);
+    }
+  }
+
+  /* ============= defaults, constants, and sizes =============== */
+  if (rbox.isinteger && !isbox)
+    box= qh_DEFAULTzbox;
+  if (addcube) {
+    cubesize= (int)floor(ldexp(1.0,dim)+0.5);
+    if (cube == 0.0)
+      cube= box;
+  }else
+    cubesize= 0;
+  if (adddiamond) {
+    diamondsize= 2*dim;
+    if (diamond == 0.0)
+      diamond= box;
+  }else
+    diamondsize= 0;
+  if (islens) {
+    if (isaxis) {
+        qh_fprintf_rbox(rbox.ferr, 6190, "rbox error: can not combine 'Ln' with 'Zn'\n");
+        qh_errexit_rbox(qh_ERRinput);
+    }
+    if (radius <= 1.0) {
+        qh_fprintf_rbox(rbox.ferr, 6191, "rbox error: lens radius %.2g should be greater than 1.0\n",
+               radius);
+        qh_errexit_rbox(qh_ERRinput);
+    }
+    lensangle= asin(1.0/radius);
+    lensbase= radius * cos(lensangle);
+  }
+
+  if (!numpoints) {
+    if (issimplex2)
+        ; /* ok */
+    else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
+        qh_fprintf_rbox(rbox.ferr, 6192, "rbox error: missing count\n");
+        qh_errexit_rbox(qh_ERRinput);
+    }else if (adddiamond + addcube + addpoints)
+        ; /* ok */
+    else {
+        numpoints= 50;  /* ./rbox D4 is the test case */
+        issphere= 1;
+    }
+  }
+  if ((issimplex + islens + isspiral + ismesh > 1)
+  || (issimplex + issphere + isspiral + ismesh > 1)) {
+    qh_fprintf_rbox(rbox.ferr, 6193, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
+    qh_errexit_rbox(qh_ERRinput);
+  }
+
+  /* ============= print header with total points =============== */
+  if (issimplex || ismesh)
+    totpoints= numpoints;
+  else if (issimplex2)
+    totpoints= numpoints+dim+1;
+  else if (isregular) {
+    totpoints= numpoints;
+    if (dim == 2) {
+        if (islens)
+          totpoints += numpoints - 2;
+    }else if (dim == 3) {
+        if (islens)
+          totpoints += 2 * numpoints;
+      else if (isgap)
+        totpoints += 1 + numpoints;
+      else
+        totpoints += 2;
+    }
+  }else
+    totpoints= numpoints + isaxis;
+  totpoints += cubesize + diamondsize + addpoints;
+
+  /* ============= seed randoms =============== */
+  if (istime == 0) {
+    for (s=command; *s; s++) {
+      if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
+        i= 'x';
+      else
+        i= *s;
+      seed= 11*seed + i;
+    }
+  }else if (israndom) {
+    seed= (int)time(&timedata);
+    sprintf(seedbuf, " t%d", seed);  /* appends an extra t, not worth removing */
+    strncat(command, seedbuf, sizeof(command)-strlen(command)-1);
+    t= strstr(command, " t ");
+    if (t)
+      strcpy(t+1, t+3); /* remove " t " */
+  } /* else, seed explicitly set to n */
+  qh_RANDOMseed_(seed);
+
+  /* ============= print header =============== */
+
+  if (iscdd)
+      qh_fprintf_rbox(rbox.fout, 9391, "%s\nbegin\n        %d %d %s\n",
+      NOcommand ? "" : command,
+      totpoints, dim+1,
+      rbox.isinteger ? "integer" : "real");
+  else if (NOcommand)
+      qh_fprintf_rbox(rbox.fout, 9392, "%d\n%d\n", dim, totpoints);
+  else
+      qh_fprintf_rbox(rbox.fout, 9393, "%d %s\n%d\n", dim, command, totpoints);
+
+  /* ============= explicit points =============== */
+  if ((s= first_point)) {
+    while (s && *s) { /* 'P' */
+      count= 0;
+      if (iscdd)
+        out1( 1.0);
+      while (*++s) {
+        out1( qh_strtod(s, &s));
+        count++;
+        if (isspace(*s) || !*s)
+          break;
+        if (*s != ',') {
+          qh_fprintf_rbox(rbox.ferr, 6194, "rbox error: missing comma after coordinate in %s\n\n", s);
+          qh_errexit_rbox(qh_ERRinput);
+        }
+      }
+      if (count < dim) {
+        for (k=dim-count; k--; )
+          out1( 0.0);
+      }else if (count > dim) {
+        qh_fprintf_rbox(rbox.ferr, 6195, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
+                  count, dim, s);
+        qh_errexit_rbox(qh_ERRinput);
+      }
+      qh_fprintf_rbox(rbox.fout, 9394, "\n");
+      while ((s= strchr(s, 'P'))) {
+        if (isspace(s[-1]))
+          break;
+      }
+    }
+  }
+
+  /* ============= simplex distribution =============== */
+  if (issimplex+issimplex2) {
+    if (!(simplex= (double*)qh_malloc( dim * (dim+1) * sizeof(double)))) {
+      qh_fprintf_rbox(rbox.ferr, 6196, "rbox error: insufficient memory for simplex\n");
+      qh_errexit_rbox(qh_ERRmem); /* qh_ERRmem */
+    }
+    simplexp= simplex;
+    if (isregular) {
+      for (i=0; i<dim; i++) {
+        for (k=0; k<dim; k++)
+          *(simplexp++)= i==k ? 1.0 : 0.0;
+      }
+      for (k=0; k<dim; k++)
+        *(simplexp++)= -1.0;
+    }else {
+      for (i=0; i<dim+1; i++) {
+        for (k=0; k<dim; k++) {
+          randr= qh_RANDOMint;
+          *(simplexp++)= 2.0 * randr/randmax - 1.0;
+        }
+      }
+    }
+    if (issimplex2) {
+        simplexp= simplex;
+      for (i=0; i<dim+1; i++) {
+        if (iscdd)
+          out1( 1.0);
+        for (k=0; k<dim; k++)
+          out1( *(simplexp++) * box);
+        qh_fprintf_rbox(rbox.fout, 9395, "\n");
+      }
+    }
+    for (j=0; j<numpoints; j++) {
+      if (iswidth)
+        apex= qh_RANDOMint % (dim+1);
+      else
+        apex= -1;
+      for (k=0; k<dim; k++)
+        coord[k]= 0.0;
+      norm= 0.0;
+      for (i=0; i<dim+1; i++) {
+        randr= qh_RANDOMint;
+        factor= randr/randmax;
+        if (i == apex)
+          factor *= width;
+        norm += factor;
+        for (k=0; k<dim; k++) {
+          simplexp= simplex + i*dim + k;
+          coord[k] += factor * (*simplexp);
+        }
+      }
+      for (k=0; k<dim; k++)
+        coord[k] /= norm;
+      if (iscdd)
+        out1( 1.0);
+      for (k=0; k < dim; k++)
+        out1( coord[k] * box);
+      qh_fprintf_rbox(rbox.fout, 9396, "\n");
+    }
+    isregular= 0; /* continue with isbox */
+    numpoints= 0;
+  }
+
+  /* ============= mesh distribution =============== */
+  if (ismesh) {
+    nthroot= (int)(pow((double)numpoints, 1.0/dim) + 0.99999);
+    for (k=dim; k--; )
+      mult[k]= 0;
+    for (i=0; i < numpoints; i++) {
+      for (k=0; k < dim; k++) {
+        if (k == 0)
+          out1( mult[0] * meshn + mult[1] * (-meshm));
+        else if (k == 1)
+          out1( mult[0] * meshm + mult[1] * meshn);
+        else
+          out1( mult[k] * meshr );
+      }
+      qh_fprintf_rbox(rbox.fout, 9397, "\n");
+      for (k=0; k < dim; k++) {
+        if (++mult[k] < nthroot)
+          break;
+        mult[k]= 0;
+      }
+    }
+  }
+  /* ============= regular points for 's' =============== */
+  else if (isregular && !islens) {
+    if (dim != 2 && dim != 3) {
+      qh_fprintf_rbox(rbox.ferr, 6197, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    if (!isaxis || radius == 0.0) {
+      isaxis= 1;
+      radius= 1.0;
+    }
+    if (dim == 3) {
+      if (iscdd)
+        out1( 1.0);
+      out3n( 0.0, 0.0, -box);
+      if (!isgap) {
+        if (iscdd)
+          out1( 1.0);
+        out3n( 0.0, 0.0, box);
+      }
+    }
+    angle= 0.0;
+    anglediff= 2.0 * M_PI/numpoints;
+    for (i=0; i < numpoints; i++) {
+      angle += anglediff;
+      x= radius * cos(angle);
+      y= radius * sin(angle);
+      if (dim == 2) {
+        if (iscdd)
+          out1( 1.0);
+        out2n( x*box, y*box);
+      }else {
+        norm= sqrt(1.0 + x*x + y*y);
+        if (iscdd)
+          out1( 1.0);
+        out3n( box*x/norm, box*y/norm, box/norm);
+        if (isgap) {
+          x *= 1-gap;
+          y *= 1-gap;
+          norm= sqrt(1.0 + x*x + y*y);
+          if (iscdd)
+            out1( 1.0);
+          out3n( box*x/norm, box*y/norm, box/norm);
+        }
+      }
+    }
+  }
+  /* ============= regular points for 'r Ln D2' =============== */
+  else if (isregular && islens && dim == 2) {
+    double cos_0;
+
+    angle= lensangle;
+    anglediff= 2 * lensangle/(numpoints - 1);
+    cos_0= cos(lensangle);
+    for (i=0; i < numpoints; i++, angle -= anglediff) {
+      x= radius * sin(angle);
+      y= radius * (cos(angle) - cos_0);
+      if (iscdd)
+        out1( 1.0);
+      out2n( x*box, y*box);
+      if (i != 0 && i != numpoints - 1) {
+        if (iscdd)
+          out1( 1.0);
+        out2n( x*box, -y*box);
+      }
+    }
+  }
+  /* ============= regular points for 'r Ln D3' =============== */
+  else if (isregular && islens && dim != 2) {
+    if (dim != 3) {
+      qh_fprintf_rbox(rbox.ferr, 6198, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    angle= 0.0;
+    anglediff= 2* M_PI/numpoints;
+    if (!isgap) {
+      isgap= 1;
+      gap= 0.5;
+    }
+    offset= sqrt(radius * radius - (1-gap)*(1-gap)) - lensbase;
+    for (i=0; i < numpoints; i++, angle += anglediff) {
+      x= cos(angle);
+      y= sin(angle);
+      if (iscdd)
+        out1( 1.0);
+      out3n( box*x, box*y, 0.0);
+      x *= 1-gap;
+      y *= 1-gap;
+      if (iscdd)
+        out1( 1.0);
+      out3n( box*x, box*y, box * offset);
+      if (iscdd)
+        out1( 1.0);
+      out3n( box*x, box*y, -box * offset);
+    }
+  }
+  /* ============= apex of 'Zn' distribution + gendim =============== */
+  else {
+    if (isaxis) {
+      gendim= dim-1;
+      if (iscdd)
+        out1( 1.0);
+      for (j=0; j < gendim; j++)
+        out1( 0.0);
+      out1( -box);
+      qh_fprintf_rbox(rbox.fout, 9398, "\n");
+    }else if (islens)
+      gendim= dim-1;
+    else
+      gendim= dim;
+    /* ============= generate random point in unit cube =============== */
+    for (i=0; i < numpoints; i++) {
+      norm= 0.0;
+      for (j=0; j < gendim; j++) {
+        randr= qh_RANDOMint;
+        coord[j]= 2.0 * randr/randmax - 1.0;
+        norm += coord[j] * coord[j];
+      }
+      norm= sqrt(norm);
+      /* ============= dim-1 point of 'Zn' distribution ========== */
+      if (isaxis) {
+        if (!isgap) {
+          isgap= 1;
+          gap= 1.0;
+        }
+        randr= qh_RANDOMint;
+        rangap= 1.0 - gap * randr/randmax;
+        factor= radius * rangap / norm;
+        for (j=0; j<gendim; j++)
+          coord[j]= factor * coord[j];
+      /* ============= dim-1 point of 'Ln s' distribution =========== */
+      }else if (islens && issphere) {
+        if (!isgap) {
+          isgap= 1;
+          gap= 1.0;
+        }
+        randr= qh_RANDOMint;
+        rangap= 1.0 - gap * randr/randmax;
+        factor= rangap / norm;
+        for (j=0; j<gendim; j++)
+          coord[j]= factor * coord[j];
+      /* ============= dim-1 point of 'Ln' distribution ========== */
+      }else if (islens && !issphere) {
+        if (!isgap) {
+          isgap= 1;
+          gap= 1.0;
+        }
+        j= qh_RANDOMint % gendim;
+        if (coord[j] < 0)
+          coord[j]= -1.0 - coord[j] * gap;
+        else
+          coord[j]= 1.0 - coord[j] * gap;
+      /* ============= point of 'l' distribution =============== */
+      }else if (isspiral) {
+        if (dim != 3) {
+          qh_fprintf_rbox(rbox.ferr, 6199, "rbox error: spiral distribution is available only in 3d\n\n");
+          longjmp(rbox.errexit,qh_ERRinput);
+        }
+        coord[0]= cos(2*M_PI*i/(numpoints - 1));
+        coord[1]= sin(2*M_PI*i/(numpoints - 1));
+        coord[2]= 2.0*(double)i/(double)(numpoints-1) - 1.0;
+      /* ============= point of 's' distribution =============== */
+      }else if (issphere) {
+        factor= 1.0/norm;
+        if (iswidth) {
+          randr= qh_RANDOMint;
+          factor *= 1.0 - width * randr/randmax;
+        }
+        for (j=0; j<dim; j++)
+          coord[j]= factor * coord[j];
+      }
+      /* ============= project 'Zn s' point in to sphere =============== */
+      if (isaxis && issphere) {
+        coord[dim-1]= 1.0;
+        norm= 1.0;
+        for (j=0; j<gendim; j++)
+          norm += coord[j] * coord[j];
+        norm= sqrt(norm);
+        for (j=0; j<dim; j++)
+          coord[j]= coord[j] / norm;
+        if (iswidth) {
+          randr= qh_RANDOMint;
+          coord[dim-1] *= 1 - width * randr/randmax;
+        }
+      /* ============= project 'Zn' point onto cube =============== */
+      }else if (isaxis && !issphere) {  /* not very interesting */
+        randr= qh_RANDOMint;
+        coord[dim-1]= 2.0 * randr/randmax - 1.0;
+      /* ============= project 'Ln' point out to sphere =============== */
+      }else if (islens) {
+        coord[dim-1]= lensbase;
+        for (j=0, norm= 0; j<dim; j++)
+          norm += coord[j] * coord[j];
+        norm= sqrt(norm);
+        for (j=0; j<dim; j++)
+          coord[j]= coord[j] * radius/ norm;
+        coord[dim-1] -= lensbase;
+        if (iswidth) {
+          randr= qh_RANDOMint;
+          coord[dim-1] *= 1 - width * randr/randmax;
+        }
+        if (qh_RANDOMint > randmax/2)
+          coord[dim-1]= -coord[dim-1];
+      /* ============= project 'Wn' point toward boundary =============== */
+      }else if (iswidth && !issphere) {
+        j= qh_RANDOMint % gendim;
+        if (coord[j] < 0)
+          coord[j]= -1.0 - coord[j] * width;
+        else
+          coord[j]= 1.0 - coord[j] * width;
+      }
+      /* ============= write point =============== */
+      if (iscdd)
+        out1( 1.0);
+      for (k=0; k < dim; k++)
+        out1( coord[k] * box);
+      qh_fprintf_rbox(rbox.fout, 9399, "\n");
+    }
+  }
+
+  /* ============= write cube vertices =============== */
+  if (addcube) {
+    for (j=0; j<cubesize; j++) {
+      if (iscdd)
+        out1( 1.0);
+      for (k=dim-1; k>=0; k--) {
+        if (j & ( 1 << k))
+          out1( cube);
+        else
+          out1( -cube);
+      }
+      qh_fprintf_rbox(rbox.fout, 9400, "\n");
+    }
+  }
+
+  /* ============= write diamond vertices =============== */
+  if (adddiamond) {
+    for (j=0; j<diamondsize; j++) {
+      if (iscdd)
+        out1( 1.0);
+      for (k=dim-1; k>=0; k--) {
+        if (j/2 != k)
+          out1( 0.0);
+        else if (j & 0x1)
+          out1( diamond);
+        else
+          out1( -diamond);
+      }
+      qh_fprintf_rbox(rbox.fout, 9401, "\n");
+    }
+  }
+
+  if (iscdd)
+    qh_fprintf_rbox(rbox.fout, 9402, "end\nhull\n");
+
+  /* same code for error exit and normal return */
+  if (simplex)
+    qh_free(simplex);
+  rbox_inuse= False;
+  return qh_ERRnone;
+} /* rboxpoints */
+
+/*------------------------------------------------
+outxxx - output functions
+*/
+int roundi( double a) {
+  if (a < 0.0) {
+    if (a - 0.5 < INT_MIN) {
+      qh_fprintf_rbox(rbox.ferr, 6200, "rbox input error: negative coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    return (int)(a - 0.5);
+  }else {
+    if (a + 0.5 > INT_MAX) {
+      qh_fprintf_rbox(rbox.ferr, 6201, "rbox input error: coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
+      qh_errexit_rbox(qh_ERRinput);
+    }
+    return (int)(a + 0.5);
+  }
+} /* roundi */
+
+void out1(double a) {
+
+  if (rbox.isinteger)
+    qh_fprintf_rbox(rbox.fout, 9403, "%d ", roundi( a+rbox.out_offset));
+  else
+    qh_fprintf_rbox(rbox.fout, 9404, qh_REAL_1, a+rbox.out_offset);
+} /* out1 */
+
+void out2n( double a, double b) {
+
+  if (rbox.isinteger)
+    qh_fprintf_rbox(rbox.fout, 9405, "%d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset));
+  else
+    qh_fprintf_rbox(rbox.fout, 9406, qh_REAL_2n, a+rbox.out_offset, b+rbox.out_offset);
+} /* out2n */
+
+void out3n( double a, double b, double c) {
+
+  if (rbox.isinteger)
+    qh_fprintf_rbox(rbox.fout, 9407, "%d %d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset), roundi(c+rbox.out_offset));
+  else
+    qh_fprintf_rbox(rbox.fout, 9408, qh_REAL_3n, a+rbox.out_offset, b+rbox.out_offset, c+rbox.out_offset);
+} /* out3n */
+
+void qh_errexit_rbox(int exitcode)
+{
+    longjmp(rbox.errexit, exitcode);
+} /* rbox_errexit */
diff --git a/alg/libqhull/stat.c b/alg/internal_libqhull/stat.c
similarity index 100%
rename from alg/libqhull/stat.c
rename to alg/internal_libqhull/stat.c
diff --git a/alg/libqhull/stat.h b/alg/internal_libqhull/stat.h
similarity index 100%
rename from alg/libqhull/stat.h
rename to alg/internal_libqhull/stat.h
diff --git a/alg/libqhull/user.c b/alg/internal_libqhull/user.c
similarity index 100%
rename from alg/libqhull/user.c
rename to alg/internal_libqhull/user.c
diff --git a/alg/libqhull/user.h b/alg/internal_libqhull/user.h
similarity index 100%
rename from alg/libqhull/user.h
rename to alg/internal_libqhull/user.h
diff --git a/alg/libqhull/usermem.c b/alg/internal_libqhull/usermem.c
similarity index 100%
rename from alg/libqhull/usermem.c
rename to alg/internal_libqhull/usermem.c
diff --git a/alg/libqhull/userprintf.c b/alg/internal_libqhull/userprintf.c
similarity index 100%
rename from alg/libqhull/userprintf.c
rename to alg/internal_libqhull/userprintf.c
diff --git a/alg/libqhull/userprintf_rbox.c b/alg/internal_libqhull/userprintf_rbox.c
similarity index 100%
rename from alg/libqhull/userprintf_rbox.c
rename to alg/internal_libqhull/userprintf_rbox.c
diff --git a/alg/internal_qhull_headers.h b/alg/internal_qhull_headers.h
index 61f2bf1..bcff124 100644
--- a/alg/internal_qhull_headers.h
+++ b/alg/internal_qhull_headers.h
@@ -1,4 +1,5 @@
 /******************************************************************************
+ * $Id: internal_qhull_headers.h 34641 2016-07-12 10:54:28Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Includes internal qhull headers
@@ -973,22 +974,22 @@ static gdal_realT qh_stddev();
 #pragma warning( disable : 4306 )  /* e.g 'type cast' : conversion from 'long' to 'facetT *' of greater size */
 #endif
 
-#include "libqhull.h"
-#include "libqhull.c"
-#include "poly.c"
-#include "poly2.c"
-#include "mem.c"
-#include "user.c"
-#include "global.c"
+#include "internal_libqhull/libqhull.h"
+#include "internal_libqhull/libqhull.c"
+#include "internal_libqhull/poly.c"
+#include "internal_libqhull/poly2.c"
+#include "internal_libqhull/mem.c"
+#include "internal_libqhull/user.c"
+#include "internal_libqhull/global.c"
 /*#include "userprintf.c"*/
-#include "random.c"
-#include "qset.c"
-#include "io.c"
-#include "usermem.c"
-#include "geom.c"
-#include "geom2.c"
-#include "stat.c"
-#include "merge.c"
+#include "internal_libqhull/random.c"
+#include "internal_libqhull/qset.c"
+#include "internal_libqhull/io.c"
+#include "internal_libqhull/usermem.c"
+#include "internal_libqhull/geom.c"
+#include "internal_libqhull/geom2.c"
+#include "internal_libqhull/stat.c"
+#include "internal_libqhull/merge.c"
 
 #ifdef _MSC_VER
 #pragma warning( pop )
diff --git a/alg/libqhull/geom2.c b/alg/libqhull/geom2.c
deleted file mode 100644
index e242fb3..0000000
--- a/alg/libqhull/geom2.c
+++ /dev/null
@@ -1,2083 +0,0 @@
-/*<html><pre>  -<a                             href="qh-geom.htm"
-  >-------------------------------</a><a name="TOP">-</a>
-
-
-   geom2.c
-   infrequently used geometric routines of qhull
-
-   see qh-geom.htm and geom.h
-
-   Copyright (c) 1993-2012 The Geometry Center.
-   $Id: //main/2011/qhull/src/libqhull/geom2.c#3 $$Change: 1464 $
-   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-
-   frequently used code goes into geom.c
-*/
-
-#include "qhull_a.h"
-
-/*================== functions in alphabetic order ============*/
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="copypoints">-</a>
-
-  qh_copypoints( points, numpoints, dimension)
-    return qh_malloc'd copy of points
-*/
-coordT *qh_copypoints(coordT *points, int numpoints, int dimension) {
-  int size;
-  coordT *newpoints;
-
-  size= numpoints * dimension * (int)sizeof(coordT);
-  if (!(newpoints=(coordT*)qh_malloc((size_t)size))) {
-    qh_fprintf(qh ferr, 6004, "qhull error: insufficient memory to copy %d points\n",
-        numpoints);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  /* newpoints cannot be NULL since above qh_errexit didn't return */
-  /* coverity[var_deref_model] */
-  memcpy((char *)newpoints, (char *)points, (size_t)size);
-  return newpoints;
-} /* copypoints */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="crossproduct">-</a>
-
-  qh_crossproduct( dim, vecA, vecB, vecC )
-    crossproduct of 2 dim vectors
-    C= A x B
-
-  notes:
-    from Glasner, Graphics Gems I, p. 639
-    only defined for dim==3
-*/
-void qh_crossproduct(int dim, realT vecA[3], realT vecB[3], realT vecC[3]){
-
-  if (dim == 3) {
-    vecC[0]=   det2_(vecA[1], vecA[2],
-                     vecB[1], vecB[2]);
-    vecC[1]= - det2_(vecA[0], vecA[2],
-                     vecB[0], vecB[2]);
-    vecC[2]=   det2_(vecA[0], vecA[1],
-                     vecB[0], vecB[1]);
-  }
-} /* vcross */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="determinant">-</a>
-
-  qh_determinant( rows, dim, nearzero )
-    compute signed determinant of a square matrix
-    uses qh.NEARzero to test for degenerate matrices
-
-  returns:
-    determinant
-    overwrites rows and the matrix
-    if dim == 2 or 3
-      nearzero iff determinant < qh NEARzero[dim-1]
-      (!quite correct, not critical)
-    if dim >= 4
-      nearzero iff diagonal[k] < qh NEARzero[k]
-*/
-realT qh_determinant(realT **rows, int dim, boolT *nearzero) {
-  realT det=0;
-  int i;
-  boolT sign= False;
-
-  *nearzero= False;
-  if (dim < 2) {
-    qh_fprintf(qh ferr, 6005, "qhull internal error (qh_determinate): only implemented for dimension >= 2\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }else if (dim == 2) {
-    det= det2_(rows[0][0], rows[0][1],
-                 rows[1][0], rows[1][1]);
-    if (fabs_(det) < qh NEARzero[1])  /* not really correct, what should this be? */
-      *nearzero= True;
-  }else if (dim == 3) {
-    det= det3_(rows[0][0], rows[0][1], rows[0][2],
-                 rows[1][0], rows[1][1], rows[1][2],
-                 rows[2][0], rows[2][1], rows[2][2]);
-    if (fabs_(det) < qh NEARzero[2])  /* not really correct, what should this be? */
-      *nearzero= True;
-  }else {
-    qh_gausselim(rows, dim, dim, &sign, nearzero);  /* if nearzero, diagonal still ok*/
-    det= 1.0;
-    for (i=dim; i--; )
-      det *= (rows[i])[i];
-    if (sign)
-      det= -det;
-  }
-  return det;
-} /* determinant */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="detjoggle">-</a>
-
-  qh_detjoggle( points, numpoints, dimension )
-    determine default max joggle for point array
-      as qh_distround * qh_JOGGLEdefault
-
-  returns:
-    initial value for JOGGLEmax from points and REALepsilon
-
-  notes:
-    computes DISTround since qh_maxmin not called yet
-    if qh SCALElast, last dimension will be scaled later to MAXwidth
-
-    loop duplicated from qh_maxmin
-*/
-realT qh_detjoggle(pointT *points, int numpoints, int dimension) {
-  realT abscoord, distround, joggle, maxcoord, mincoord;
-  pointT *point, *pointtemp;
-  realT maxabs= -REALmax;
-  realT sumabs= 0;
-  realT maxwidth= 0;
-  int k;
-
-  for (k=0; k < dimension; k++) {
-    if (qh SCALElast && k == dimension-1)
-      abscoord= maxwidth;
-    else if (qh DELAUNAY && k == dimension-1) /* will qh_setdelaunay() */
-      abscoord= 2 * maxabs * maxabs;  /* may be low by qh hull_dim/2 */
-    else {
-      maxcoord= -REALmax;
-      mincoord= REALmax;
-      FORALLpoint_(points, numpoints) {
-        maximize_(maxcoord, point[k]);
-        minimize_(mincoord, point[k]);
-      }
-      maximize_(maxwidth, maxcoord-mincoord);
-      abscoord= fmax_(maxcoord, -mincoord);
-    }
-    sumabs += abscoord;
-    maximize_(maxabs, abscoord);
-  } /* for k */
-  distround= qh_distround(qh hull_dim, maxabs, sumabs);
-  joggle= distround * qh_JOGGLEdefault;
-  maximize_(joggle, REALepsilon * qh_JOGGLEdefault);
-  trace2((qh ferr, 2001, "qh_detjoggle: joggle=%2.2g maxwidth=%2.2g\n", joggle, maxwidth));
-  return joggle;
-} /* detjoggle */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="detroundoff">-</a>
-
-  qh_detroundoff()
-    determine maximum roundoff errors from
-      REALepsilon, REALmax, REALmin, qh.hull_dim, qh.MAXabs_coord,
-      qh.MAXsumcoord, qh.MAXwidth, qh.MINdenom_1
-
-    accounts for qh.SETroundoff, qh.RANDOMdist, qh MERGEexact
-      qh.premerge_cos, qh.postmerge_cos, qh.premerge_centrum,
-      qh.postmerge_centrum, qh.MINoutside,
-      qh_RATIOnearinside, qh_COPLANARratio, qh_WIDEcoplanar
-
-  returns:
-    sets qh.DISTround, etc. (see below)
-    appends precision constants to qh.qhull_options
-
-  see:
-    qh_maxmin() for qh.NEARzero
-
-  design:
-    determine qh.DISTround for distance computations
-    determine minimum denominators for qh_divzero
-    determine qh.ANGLEround for angle computations
-    adjust qh.premerge_cos,... for roundoff error
-    determine qh.ONEmerge for maximum error due to a single merge
-    determine qh.NEARinside, qh.MAXcoplanar, qh.MINvisible,
-      qh.MINoutside, qh.WIDEfacet
-    initialize qh.max_vertex and qh.minvertex
-*/
-void qh_detroundoff(void) {
-
-  qh_option("_max-width", NULL, &qh MAXwidth);
-  if (!qh SETroundoff) {
-    qh DISTround= qh_distround(qh hull_dim, qh MAXabs_coord, qh MAXsumcoord);
-    if (qh RANDOMdist)
-      qh DISTround += qh RANDOMfactor * qh MAXabs_coord;
-    qh_option("Error-roundoff", NULL, &qh DISTround);
-  }
-  qh MINdenom= qh MINdenom_1 * qh MAXabs_coord;
-  qh MINdenom_1_2= sqrt(qh MINdenom_1 * qh hull_dim) ;  /* if will be normalized */
-  qh MINdenom_2= qh MINdenom_1_2 * qh MAXabs_coord;
-                                              /* for inner product */
-  qh ANGLEround= 1.01 * qh hull_dim * REALepsilon;
-  if (qh RANDOMdist)
-    qh ANGLEround += qh RANDOMfactor;
-  if (qh premerge_cos < REALmax/2) {
-    qh premerge_cos -= qh ANGLEround;
-    if (qh RANDOMdist)
-      qh_option("Angle-premerge-with-random", NULL, &qh premerge_cos);
-  }
-  if (qh postmerge_cos < REALmax/2) {
-    qh postmerge_cos -= qh ANGLEround;
-    if (qh RANDOMdist)
-      qh_option("Angle-postmerge-with-random", NULL, &qh postmerge_cos);
-  }
-  qh premerge_centrum += 2 * qh DISTround;    /*2 for centrum and distplane()*/
-  qh postmerge_centrum += 2 * qh DISTround;
-  if (qh RANDOMdist && (qh MERGEexact || qh PREmerge))
-    qh_option("Centrum-premerge-with-random", NULL, &qh premerge_centrum);
-  if (qh RANDOMdist && qh POSTmerge)
-    qh_option("Centrum-postmerge-with-random", NULL, &qh postmerge_centrum);
-  { /* compute ONEmerge, max vertex offset for merging simplicial facets */
-    realT maxangle= 1.0, maxrho;
-
-    minimize_(maxangle, qh premerge_cos);
-    minimize_(maxangle, qh postmerge_cos);
-    /* max diameter * sin theta + DISTround for vertex to its hyperplane */
-    qh ONEmerge= sqrt((realT)qh hull_dim) * qh MAXwidth *
-      sqrt(1.0 - maxangle * maxangle) + qh DISTround;
-    maxrho= qh hull_dim * qh premerge_centrum + qh DISTround;
-    maximize_(qh ONEmerge, maxrho);
-    maxrho= qh hull_dim * qh postmerge_centrum + qh DISTround;
-    maximize_(qh ONEmerge, maxrho);
-    if (qh MERGING)
-      qh_option("_one-merge", NULL, &qh ONEmerge);
-  }
-  qh NEARinside= qh ONEmerge * qh_RATIOnearinside; /* only used if qh KEEPnearinside */
-  if (qh JOGGLEmax < REALmax/2 && (qh KEEPcoplanar || qh KEEPinside)) {
-    realT maxdist;             /* adjust qh.NEARinside for joggle */
-    qh KEEPnearinside= True;
-    maxdist= sqrt((realT)qh hull_dim) * qh JOGGLEmax + qh DISTround;
-    maxdist= 2*maxdist;        /* vertex and coplanar point can joggle in opposite directions */
-    maximize_(qh NEARinside, maxdist);  /* must agree with qh_nearcoplanar() */
-  }
-  if (qh KEEPnearinside)
-    qh_option("_near-inside", NULL, &qh NEARinside);
-  if (qh JOGGLEmax < qh DISTround) {
-    qh_fprintf(qh ferr, 6006, "qhull error: the joggle for 'QJn', %.2g, is below roundoff for distance computations, %.2g\n",
-         qh JOGGLEmax, qh DISTround);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh MINvisible > REALmax/2) {
-    if (!qh MERGING)
-      qh MINvisible= qh DISTround;
-    else if (qh hull_dim <= 3)
-      qh MINvisible= qh premerge_centrum;
-    else
-      qh MINvisible= qh_COPLANARratio * qh premerge_centrum;
-    if (qh APPROXhull && qh MINvisible > qh MINoutside)
-      qh MINvisible= qh MINoutside;
-    qh_option("Visible-distance", NULL, &qh MINvisible);
-  }
-  if (qh MAXcoplanar > REALmax/2) {
-    qh MAXcoplanar= qh MINvisible;
-    qh_option("U-coplanar-distance", NULL, &qh MAXcoplanar);
-  }
-  if (!qh APPROXhull) {             /* user may specify qh MINoutside */
-    qh MINoutside= 2 * qh MINvisible;
-    if (qh premerge_cos < REALmax/2)
-      maximize_(qh MINoutside, (1- qh premerge_cos) * qh MAXabs_coord);
-    qh_option("Width-outside", NULL, &qh MINoutside);
-  }
-  qh WIDEfacet= qh MINoutside;
-  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MAXcoplanar);
-  maximize_(qh WIDEfacet, qh_WIDEcoplanar * qh MINvisible);
-  qh_option("_wide-facet", NULL, &qh WIDEfacet);
-  if (qh MINvisible > qh MINoutside + 3 * REALepsilon
-  && !qh BESToutside && !qh FORCEoutput)
-    qh_fprintf(qh ferr, 7001, "qhull input warning: minimum visibility V%.2g is greater than \nminimum outside W%.2g.  Flipped facets are likely.\n",
-             qh MINvisible, qh MINoutside);
-  qh max_vertex= qh DISTround;
-  qh min_vertex= -qh DISTround;
-  /* numeric constants reported in printsummary */
-} /* detroundoff */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="detsimplex">-</a>
-
-  qh_detsimplex( apex, points, dim, nearzero )
-    compute determinant of a simplex with point apex and base points
-
-  returns:
-     signed determinant and nearzero from qh_determinant
-
-  notes:
-     uses qh.gm_matrix/qh.gm_row (assumes they're big enough)
-
-  design:
-    construct qm_matrix by subtracting apex from points
-    compute determinate
-*/
-realT qh_detsimplex(pointT *apex, setT *points, int dim, boolT *nearzero) {
-  pointT *coorda, *coordp, *gmcoord, *point, **pointp;
-  coordT **rows;
-  int k,  i=0;
-  realT det;
-
-  zinc_(Zdetsimplex);
-  gmcoord= qh gm_matrix;
-  rows= qh gm_row;
-  FOREACHpoint_(points) {
-    if (i == dim)
-      break;
-    rows[i++]= gmcoord;
-    coordp= point;
-    coorda= apex;
-    for (k=dim; k--; )
-      *(gmcoord++)= *coordp++ - *coorda++;
-  }
-  if (i < dim) {
-    qh_fprintf(qh ferr, 6007, "qhull internal error (qh_detsimplex): #points %d < dimension %d\n",
-               i, dim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  det= qh_determinant(rows, dim, nearzero);
-  trace2((qh ferr, 2002, "qh_detsimplex: det=%2.2g for point p%d, dim %d, nearzero? %d\n",
-          det, qh_pointid(apex), dim, *nearzero));
-  return det;
-} /* detsimplex */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="distnorm">-</a>
-
-  qh_distnorm( dim, point, normal, offset )
-    return distance from point to hyperplane at normal/offset
-
-  returns:
-    dist
-
-  notes:
-    dist > 0 if point is outside of hyperplane
-
-  see:
-    qh_distplane in geom.c
-*/
-realT qh_distnorm(int dim, pointT *point, pointT *normal, realT *offsetp) {
-  coordT *normalp= normal, *coordp= point;
-  realT dist;
-  int k;
-
-  dist= *offsetp;
-  for (k=dim; k--; )
-    dist += *(coordp++) * *(normalp++);
-  return dist;
-} /* distnorm */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="distround">-</a>
-
-  qh_distround(dimension, maxabs, maxsumabs )
-    compute maximum round-off error for a distance computation
-      to a normalized hyperplane
-    maxabs is the maximum absolute value of a coordinate
-    maxsumabs is the maximum possible sum of absolute coordinate values
-
-  returns:
-    max dist round for REALepsilon
-
-  notes:
-    calculate roundoff error according to
-    Lemma 3.2-1 of Golub and van Loan "Matrix Computation"
-    use sqrt(dim) since one vector is normalized
-      or use maxsumabs since one vector is < 1
-*/
-realT qh_distround(int dimension, realT maxabs, realT maxsumabs) {
-  realT maxdistsum, maxround;
-
-  maxdistsum= sqrt((realT)dimension) * maxabs;
-  minimize_( maxdistsum, maxsumabs);
-  maxround= REALepsilon * (dimension * maxdistsum * 1.01 + maxabs);
-              /* adds maxabs for offset */
-  trace4((qh ferr, 4008, "qh_distround: %2.2g maxabs %2.2g maxsumabs %2.2g maxdistsum %2.2g\n",
-                 maxround, maxabs, maxsumabs, maxdistsum));
-  return maxround;
-} /* distround */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="divzero">-</a>
-
-  qh_divzero( numer, denom, mindenom1, zerodiv )
-    divide by a number that's nearly zero
-    mindenom1= minimum denominator for dividing into 1.0
-
-  returns:
-    quotient
-    sets zerodiv and returns 0.0 if it would overflow
-
-  design:
-    if numer is nearly zero and abs(numer) < abs(denom)
-      return numer/denom
-    else if numer is nearly zero
-      return 0 and zerodiv
-    else if denom/numer non-zero
-      return numer/denom
-    else
-      return 0 and zerodiv
-*/
-realT qh_divzero(realT numer, realT denom, realT mindenom1, boolT *zerodiv) {
-  realT temp, numerx, denomx;
-
-
-  if (numer < mindenom1 && numer > -mindenom1) {
-    numerx= fabs_(numer);
-    denomx= fabs_(denom);
-    if (numerx < denomx) {
-      *zerodiv= False;
-      return numer/denom;
-    }else {
-      *zerodiv= True;
-      return 0.0;
-    }
-  }
-  temp= denom/numer;
-  if (temp > mindenom1 || temp < -mindenom1) {
-    *zerodiv= False;
-    return numer/denom;
-  }else {
-    *zerodiv= True;
-    return 0.0;
-  }
-} /* divzero */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="facetarea">-</a>
-
-  qh_facetarea( facet )
-    return area for a facet
-
-  notes:
-    if non-simplicial,
-      uses centrum to triangulate facet and sums the projected areas.
-    if (qh DELAUNAY),
-      computes projected area instead for last coordinate
-    assumes facet->normal exists
-    projecting tricoplanar facets to the hyperplane does not appear to make a difference
-
-  design:
-    if simplicial
-      compute area
-    else
-      for each ridge
-        compute area from centrum to ridge
-    negate area if upper Delaunay facet
-*/
-realT qh_facetarea(facetT *facet) {
-  vertexT *apex;
-  pointT *centrum;
-  realT area= 0.0;
-  ridgeT *ridge, **ridgep;
-
-  if (facet->simplicial) {
-    apex= SETfirstt_(facet->vertices, vertexT);
-    area= qh_facetarea_simplex(qh hull_dim, apex->point, facet->vertices,
-                    apex, facet->toporient, facet->normal, &facet->offset);
-  }else {
-    if (qh CENTERtype == qh_AScentrum)
-      centrum= facet->center;
-    else
-      centrum= qh_getcentrum(facet);
-    FOREACHridge_(facet->ridges)
-      area += qh_facetarea_simplex(qh hull_dim, centrum, ridge->vertices,
-                 NULL, (boolT)(ridge->top == facet),  facet->normal, &facet->offset);
-    if (qh CENTERtype != qh_AScentrum)
-      qh_memfree(centrum, qh normal_size);
-  }
-  if (facet->upperdelaunay && qh DELAUNAY)
-    area= -area;  /* the normal should be [0,...,1] */
-  trace4((qh ferr, 4009, "qh_facetarea: f%d area %2.2g\n", facet->id, area));
-  return area;
-} /* facetarea */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="facetarea_simplex">-</a>
-
-  qh_facetarea_simplex( dim, apex, vertices, notvertex, toporient, normal, offset )
-    return area for a simplex defined by
-      an apex, a base of vertices, an orientation, and a unit normal
-    if simplicial or tricoplanar facet,
-      notvertex is defined and it is skipped in vertices
-
-  returns:
-    computes area of simplex projected to plane [normal,offset]
-    returns 0 if vertex too far below plane (qh WIDEfacet)
-      vertex can't be apex of tricoplanar facet
-
-  notes:
-    if (qh DELAUNAY),
-      computes projected area instead for last coordinate
-    uses qh gm_matrix/gm_row and qh hull_dim
-    helper function for qh_facetarea
-
-  design:
-    if Notvertex
-      translate simplex to apex
-    else
-      project simplex to normal/offset
-      translate simplex to apex
-    if Delaunay
-      set last row/column to 0 with -1 on diagonal
-    else
-      set last row to Normal
-    compute determinate
-    scale and flip sign for area
-*/
-realT qh_facetarea_simplex(int dim, coordT *apex, setT *vertices,
-        vertexT *notvertex,  boolT toporient, coordT *normal, realT *offset) {
-  pointT *coorda, *coordp, *gmcoord;
-  coordT **rows, *normalp;
-  int k,  i=0;
-  realT area, dist;
-  vertexT *vertex, **vertexp;
-  boolT nearzero;
-
-  gmcoord= qh gm_matrix;
-  rows= qh gm_row;
-  FOREACHvertex_(vertices) {
-    if (vertex == notvertex)
-      continue;
-    rows[i++]= gmcoord;
-    coorda= apex;
-    coordp= vertex->point;
-    normalp= normal;
-    if (notvertex) {
-      for (k=dim; k--; )
-        *(gmcoord++)= *coordp++ - *coorda++;
-    }else {
-      dist= *offset;
-      for (k=dim; k--; )
-        dist += *coordp++ * *normalp++;
-      if (dist < -qh WIDEfacet) {
-        zinc_(Znoarea);
-        return 0.0;
-      }
-      coordp= vertex->point;
-      normalp= normal;
-      for (k=dim; k--; )
-        *(gmcoord++)= (*coordp++ - dist * *normalp++) - *coorda++;
-    }
-  }
-  if (i != dim-1) {
-    qh_fprintf(qh ferr, 6008, "qhull internal error (qh_facetarea_simplex): #points %d != dim %d -1\n",
-               i, dim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  rows[i]= gmcoord;
-  if (qh DELAUNAY) {
-    for (i=0; i < dim-1; i++)
-      rows[i][dim-1]= 0.0;
-    for (k=dim; k--; )
-      *(gmcoord++)= 0.0;
-    rows[dim-1][dim-1]= -1.0;
-  }else {
-    normalp= normal;
-    for (k=dim; k--; )
-      *(gmcoord++)= *normalp++;
-  }
-  zinc_(Zdetsimplex);
-  area= qh_determinant(rows, dim, &nearzero);
-  if (toporient)
-    area= -area;
-  area *= qh AREAfactor;
-  trace4((qh ferr, 4010, "qh_facetarea_simplex: area=%2.2g for point p%d, toporient %d, nearzero? %d\n",
-          area, qh_pointid(apex), toporient, nearzero));
-  return area;
-} /* facetarea_simplex */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="facetcenter">-</a>
-
-  qh_facetcenter( vertices )
-    return Voronoi center (Voronoi vertex) for a facet's vertices
-
-  returns:
-    return temporary point equal to the center
-
-  see:
-    qh_voronoi_center()
-*/
-pointT *qh_facetcenter(setT *vertices) {
-  setT *points= qh_settemp(qh_setsize(vertices));
-  vertexT *vertex, **vertexp;
-  pointT *center;
-
-  FOREACHvertex_(vertices)
-    qh_setappend(&points, vertex->point);
-  center= qh_voronoi_center(qh hull_dim-1, points);
-  qh_settempfree(&points);
-  return center;
-} /* facetcenter */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="findgooddist">-</a>
-
-  qh_findgooddist( point, facetA, dist, facetlist )
-    find best good facet visible for point from facetA
-    assumes facetA is visible from point
-
-  returns:
-    best facet, i.e., good facet that is furthest from point
-      distance to best facet
-      NULL if none
-
-    moves good, visible facets (and some other visible facets)
-      to end of qh facet_list
-
-  notes:
-    uses qh visit_id
-
-  design:
-    initialize bestfacet if facetA is good
-    move facetA to end of facetlist
-    for each facet on facetlist
-      for each unvisited neighbor of facet
-        move visible neighbors to end of facetlist
-        update best good neighbor
-        if no good neighbors, update best facet
-*/
-facetT *qh_findgooddist(pointT *point, facetT *facetA, realT *distp,
-               facetT **facetlist) {
-  realT bestdist= -REALmax, dist;
-  facetT *neighbor, **neighborp, *bestfacet=NULL, *facet;
-  boolT goodseen= False;
-
-  if (facetA->good) {
-    zzinc_(Zcheckpart);  /* calls from check_bestdist occur after print stats */
-    qh_distplane(point, facetA, &bestdist);
-    bestfacet= facetA;
-    goodseen= True;
-  }
-  qh_removefacet(facetA);
-  qh_appendfacet(facetA);
-  *facetlist= facetA;
-  facetA->visitid= ++qh visit_id;
-  FORALLfacet_(*facetlist) {
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid == qh visit_id)
-        continue;
-      neighbor->visitid= qh visit_id;
-      if (goodseen && !neighbor->good)
-        continue;
-      zzinc_(Zcheckpart);
-      qh_distplane(point, neighbor, &dist);
-      if (dist > 0) {
-        qh_removefacet(neighbor);
-        qh_appendfacet(neighbor);
-        if (neighbor->good) {
-          goodseen= True;
-          if (dist > bestdist) {
-            bestdist= dist;
-            bestfacet= neighbor;
-          }
-        }
-      }
-    }
-  }
-  if (bestfacet) {
-    *distp= bestdist;
-    trace2((qh ferr, 2003, "qh_findgooddist: p%d is %2.2g above good facet f%d\n",
-      qh_pointid(point), bestdist, bestfacet->id));
-    return bestfacet;
-  }
-  trace4((qh ferr, 4011, "qh_findgooddist: no good facet for p%d above f%d\n",
-      qh_pointid(point), facetA->id));
-  return NULL;
-}  /* findgooddist */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="getarea">-</a>
-
-  qh_getarea( facetlist )
-    set area of all facets in facetlist
-    collect statistics
-    nop if hasAreaVolume
-
-  returns:
-    sets qh totarea/totvol to total area and volume of convex hull
-    for Delaunay triangulation, computes projected area of the lower or upper hull
-      ignores upper hull if qh ATinfinity
-
-  notes:
-    could compute outer volume by expanding facet area by rays from interior
-    the following attempt at perpendicular projection underestimated badly:
-      qh.totoutvol += (-dist + facet->maxoutside + qh DISTround)
-                            * area/ qh hull_dim;
-  design:
-    for each facet on facetlist
-      compute facet->area
-      update qh.totarea and qh.totvol
-*/
-void qh_getarea(facetT *facetlist) {
-  realT area;
-  realT dist;
-  facetT *facet;
-
-  if (qh hasAreaVolume)
-    return;
-  if (qh REPORTfreq)
-    qh_fprintf(qh ferr, 8020, "computing area of each facet and volume of the convex hull\n");
-  else
-    trace1((qh ferr, 1001, "qh_getarea: computing volume and area for each facet\n"));
-  qh totarea= qh totvol= 0.0;
-  FORALLfacet_(facetlist) {
-    if (!facet->normal)
-      continue;
-    if (facet->upperdelaunay && qh ATinfinity)
-      continue;
-    if (!facet->isarea) {
-      facet->f.area= qh_facetarea(facet);
-      facet->isarea= True;
-    }
-    area= facet->f.area;
-    if (qh DELAUNAY) {
-      if (facet->upperdelaunay == qh UPPERdelaunay)
-        qh totarea += area;
-    }else {
-      qh totarea += area;
-      qh_distplane(qh interior_point, facet, &dist);
-      qh totvol += -dist * area/ qh hull_dim;
-    }
-    if (qh PRINTstatistics) {
-      wadd_(Wareatot, area);
-      wmax_(Wareamax, area);
-      wmin_(Wareamin, area);
-    }
-  }
-  qh hasAreaVolume= True;
-} /* getarea */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="gram_schmidt">-</a>
-
-  qh_gram_schmidt( dim, row )
-    implements Gram-Schmidt orthogonalization by rows
-
-  returns:
-    false if zero norm
-    overwrites rows[dim][dim]
-
-  notes:
-    see Golub & van Loan Algorithm 6.2-2
-    overflow due to small divisors not handled
-
-  design:
-    for each row
-      compute norm for row
-      if non-zero, normalize row
-      for each remaining rowA
-        compute inner product of row and rowA
-        reduce rowA by row * inner product
-*/
-boolT qh_gram_schmidt(int dim, realT **row) {
-  realT *rowi, *rowj, norm;
-  int i, j, k;
-
-  for (i=0; i < dim; i++) {
-    rowi= row[i];
-    for (norm= 0.0, k= dim; k--; rowi++)
-      norm += *rowi * *rowi;
-    norm= sqrt(norm);
-    wmin_(Wmindenom, norm);
-    if (norm == 0.0)  /* either 0 or overflow due to sqrt */
-      return False;
-    for (k=dim; k--; )
-      *(--rowi) /= norm;
-    for (j=i+1; j < dim; j++) {
-      rowj= row[j];
-      for (norm= 0.0, k=dim; k--; )
-        norm += *rowi++ * *rowj++;
-      for (k=dim; k--; )
-        *(--rowj) -= *(--rowi) * norm;
-    }
-  }
-  return True;
-} /* gram_schmidt */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="inthresholds">-</a>
-
-  qh_inthresholds( normal, angle )
-    return True if normal within qh.lower_/upper_threshold
-
-  returns:
-    estimate of angle by summing of threshold diffs
-      angle may be NULL
-      smaller "angle" is better
-
-  notes:
-    invalid if qh.SPLITthresholds
-
-  see:
-    qh.lower_threshold in qh_initbuild()
-    qh_initthresholds()
-
-  design:
-    for each dimension
-      test threshold
-*/
-boolT qh_inthresholds(coordT *normal, realT *angle) {
-  boolT within= True;
-  int k;
-  realT threshold;
-
-  if (angle)
-    *angle= 0.0;
-  for (k=0; k < qh hull_dim; k++) {
-    threshold= qh lower_threshold[k];
-    if (threshold > -REALmax/2) {
-      if (normal[k] < threshold)
-        within= False;
-      if (angle) {
-        threshold -= normal[k];
-        *angle += fabs_(threshold);
-      }
-    }
-    if (qh upper_threshold[k] < REALmax/2) {
-      threshold= qh upper_threshold[k];
-      if (normal[k] > threshold)
-        within= False;
-      if (angle) {
-        threshold -= normal[k];
-        *angle += fabs_(threshold);
-      }
-    }
-  }
-  return within;
-} /* inthresholds */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="joggleinput">-</a>
-
-  qh_joggleinput()
-    randomly joggle input to Qhull by qh.JOGGLEmax
-    initial input is qh.first_point/qh.num_points of qh.hull_dim
-      repeated calls use qh.input_points/qh.num_points
-
-  returns:
-    joggles points at qh.first_point/qh.num_points
-    copies data to qh.input_points/qh.input_malloc if first time
-    determines qh.JOGGLEmax if it was zero
-    if qh.DELAUNAY
-      computes the Delaunay projection of the joggled points
-
-  notes:
-    if qh.DELAUNAY, unnecessarily joggles the last coordinate
-    the initial 'QJn' may be set larger than qh_JOGGLEmaxincrease
-
-  design:
-    if qh.DELAUNAY
-      set qh.SCALElast for reduced precision errors
-    if first call
-      initialize qh.input_points to the original input points
-      if qh.JOGGLEmax == 0
-        determine default qh.JOGGLEmax
-    else
-      increase qh.JOGGLEmax according to qh.build_cnt
-    joggle the input by adding a random number in [-qh.JOGGLEmax,qh.JOGGLEmax]
-    if qh.DELAUNAY
-      sets the Delaunay projection
-*/
-void qh_joggleinput(void) {
-  int i, seed, size;
-  coordT *coordp, *inputp;
-  realT randr, randa, randb;
-
-  if (!qh input_points) { /* first call */
-    qh input_points= qh first_point;
-    qh input_malloc= qh POINTSmalloc;
-    size= qh num_points * qh hull_dim * sizeof(coordT);
-    if (!(qh first_point=(coordT*)qh_malloc((size_t)size))) {
-      qh_fprintf(qh ferr, 6009, "qhull error: insufficient memory to joggle %d points\n",
-          qh num_points);
-      qh_errexit(qh_ERRmem, NULL, NULL);
-    }
-    qh POINTSmalloc= True;
-    if (qh JOGGLEmax == 0.0) {
-      qh JOGGLEmax= qh_detjoggle(qh input_points, qh num_points, qh hull_dim);
-      qh_option("QJoggle", NULL, &qh JOGGLEmax);
-    }
-  }else {                 /* repeated call */
-    if (!qh RERUN && qh build_cnt > qh_JOGGLEretry) {
-      if (((qh build_cnt-qh_JOGGLEretry-1) % qh_JOGGLEagain) == 0) {
-        realT maxjoggle= qh MAXwidth * qh_JOGGLEmaxincrease;
-        if (qh JOGGLEmax < maxjoggle) {
-          qh JOGGLEmax *= qh_JOGGLEincrease;
-          minimize_(qh JOGGLEmax, maxjoggle);
-        }
-      }
-    }
-    qh_option("QJoggle", NULL, &qh JOGGLEmax);
-  }
-  if (qh build_cnt > 1 && qh JOGGLEmax > fmax_(qh MAXwidth/4, 0.1)) {
-      qh_fprintf(qh ferr, 6010, "qhull error: the current joggle for 'QJn', %.2g, is too large for the width\nof the input.  If possible, recompile Qhull with higher-precision reals.\n",
-                qh JOGGLEmax);
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  /* for some reason, using qh ROTATErandom and qh_RANDOMseed does not repeat the run. Use 'TRn' instead */
-  seed= qh_RANDOMint;
-  qh_option("_joggle-seed", &seed, NULL);
-  trace0((qh ferr, 6, "qh_joggleinput: joggle input by %2.2g with seed %d\n",
-    qh JOGGLEmax, seed));
-  inputp= qh input_points;
-  coordp= qh first_point;
-  randa= 2.0 * qh JOGGLEmax/qh_RANDOMmax;
-  randb= -qh JOGGLEmax;
-  size= qh num_points * qh hull_dim;
-  for (i=size; i--; ) {
-    randr= qh_RANDOMint;
-    *(coordp++)= *(inputp++) + (randr * randa + randb);
-  }
-  if (qh DELAUNAY) {
-    qh last_low= qh last_high= qh last_newhigh= REALmax;
-    qh_setdelaunay(qh hull_dim, qh num_points, qh first_point);
-  }
-} /* joggleinput */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="maxabsval">-</a>
-
-  qh_maxabsval( normal, dim )
-    return pointer to maximum absolute value of a dim vector
-    returns NULL if dim=0
-*/
-realT *qh_maxabsval(realT *normal, int dim) {
-  realT maxval= -REALmax;
-  realT *maxp= NULL, *colp, absval;
-  int k;
-
-  for (k=dim, colp= normal; k--; colp++) {
-    absval= fabs_(*colp);
-    if (absval > maxval) {
-      maxval= absval;
-      maxp= colp;
-    }
-  }
-  return maxp;
-} /* maxabsval */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="maxmin">-</a>
-
-  qh_maxmin( points, numpoints, dimension )
-    return max/min points for each dimension
-    determine max and min coordinates
-
-  returns:
-    returns a temporary set of max and min points
-      may include duplicate points. Does not include qh.GOODpoint
-    sets qh.NEARzero, qh.MAXabs_coord, qh.MAXsumcoord, qh.MAXwidth
-         qh.MAXlastcoord, qh.MINlastcoord
-    initializes qh.max_outside, qh.min_vertex, qh.WAScoplanar, qh.ZEROall_ok
-
-  notes:
-    loop duplicated in qh_detjoggle()
-
-  design:
-    initialize global precision variables
-    checks definition of REAL...
-    for each dimension
-      for each point
-        collect maximum and minimum point
-      collect maximum of maximums and minimum of minimums
-      determine qh.NEARzero for Gaussian Elimination
-*/
-setT *qh_maxmin(pointT *points, int numpoints, int dimension) {
-  int k;
-  realT maxcoord, temp;
-  pointT *minimum, *maximum, *point, *pointtemp;
-  setT *set;
-
-  qh max_outside= 0.0;
-  qh MAXabs_coord= 0.0;
-  qh MAXwidth= -REALmax;
-  qh MAXsumcoord= 0.0;
-  qh min_vertex= 0.0;
-  qh WAScoplanar= False;
-  if (qh ZEROcentrum)
-    qh ZEROall_ok= True;
-  if (REALmin < REALepsilon && REALmin < REALmax && REALmin > -REALmax
-  && REALmax > 0.0 && -REALmax < 0.0)
-    ; /* all ok */
-  else {
-    qh_fprintf(qh ferr, 6011, "qhull error: floating point constants in user.h are wrong\n\
-REALepsilon %g REALmin %g REALmax %g -REALmax %g\n",
-             REALepsilon, REALmin, REALmax, -REALmax);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  set= qh_settemp(2*dimension);
-  for (k=0; k < dimension; k++) {
-    if (points == qh GOODpointp)
-      minimum= maximum= points + dimension;
-    else
-      minimum= maximum= points;
-    FORALLpoint_(points, numpoints) {
-      if (point == qh GOODpointp)
-        continue;
-      if (maximum[k] < point[k])
-        maximum= point;
-      else if (minimum[k] > point[k])
-        minimum= point;
-    }
-    if (k == dimension-1) {
-      qh MINlastcoord= minimum[k];
-      qh MAXlastcoord= maximum[k];
-    }
-    if (qh SCALElast && k == dimension-1)
-      maxcoord= qh MAXwidth;
-    else {
-      maxcoord= fmax_(maximum[k], -minimum[k]);
-      if (qh GOODpointp) {
-        temp= fmax_(qh GOODpointp[k], -qh GOODpointp[k]);
-        maximize_(maxcoord, temp);
-      }
-      temp= maximum[k] - minimum[k];
-      maximize_(qh MAXwidth, temp);
-    }
-    maximize_(qh MAXabs_coord, maxcoord);
-    qh MAXsumcoord += maxcoord;
-    qh_setappend(&set, maximum);
-    qh_setappend(&set, minimum);
-    /* calculation of qh NEARzero is based on error formula 4.4-13 of
-       Golub & van Loan, authors say n^3 can be ignored and 10 be used in
-       place of rho */
-    qh NEARzero[k]= 80 * qh MAXsumcoord * REALepsilon;
-  }
-  if (qh IStracing >=1)
-    qh_printpoints(qh ferr, "qh_maxmin: found the max and min points(by dim):", set);
-  return(set);
-} /* maxmin */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="maxouter">-</a>
-
-  qh_maxouter()
-    return maximum distance from facet to outer plane
-    normally this is qh.max_outside+qh.DISTround
-    does not include qh.JOGGLEmax
-
-  see:
-    qh_outerinner()
-
-  notes:
-    need to add another qh.DISTround if testing actual point with computation
-
-  for joggle:
-    qh_setfacetplane() updated qh.max_outer for Wnewvertexmax (max distance to vertex)
-    need to use Wnewvertexmax since could have a coplanar point for a high
-      facet that is replaced by a low facet
-    need to add qh.JOGGLEmax if testing input points
-*/
-realT qh_maxouter(void) {
-  realT dist;
-
-  dist= fmax_(qh max_outside, qh DISTround);
-  dist += qh DISTround;
-  trace4((qh ferr, 4012, "qh_maxouter: max distance from facet to outer plane is %2.2g max_outside is %2.2g\n", dist, qh max_outside));
-  return dist;
-} /* maxouter */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="maxsimplex">-</a>
-
-  qh_maxsimplex( dim, maxpoints, points, numpoints, simplex )
-    determines maximum simplex for a set of points
-    starts from points already in simplex
-    skips qh.GOODpointp (assumes that it isn't in maxpoints)
-
-  returns:
-    simplex with dim+1 points
-
-  notes:
-    assumes at least pointsneeded points in points
-    maximizes determinate for x,y,z,w, etc.
-    uses maxpoints as long as determinate is clearly non-zero
-
-  design:
-    initialize simplex with at least two points
-      (find points with max or min x coordinate)
-    for each remaining dimension
-      add point that maximizes the determinate
-        (use points from maxpoints first)
-*/
-void qh_maxsimplex(int dim, setT *maxpoints, pointT *points, int numpoints, setT **simplex) {
-  pointT *point, **pointp, *pointtemp, *maxpoint, *minx=NULL, *maxx=NULL;
-  boolT nearzero, maxnearzero= False;
-  int k, sizinit;
-  realT maxdet= -REALmax, det, mincoord= REALmax, maxcoord= -REALmax;
-
-  sizinit= qh_setsize(*simplex);
-  if (sizinit < 2) {
-    if (qh_setsize(maxpoints) >= 2) {
-      FOREACHpoint_(maxpoints) {
-        if (maxcoord < point[0]) {
-          maxcoord= point[0];
-          maxx= point;
-        }
-        if (mincoord > point[0]) {
-          mincoord= point[0];
-          minx= point;
-        }
-      }
-    }else {
-      FORALLpoint_(points, numpoints) {
-        if (point == qh GOODpointp)
-          continue;
-        if (maxcoord < point[0]) {
-          maxcoord= point[0];
-          maxx= point;
-        }
-        if (mincoord > point[0]) {
-          mincoord= point[0];
-          minx= point;
-        }
-      }
-    }
-    qh_setunique(simplex, minx);
-    if (qh_setsize(*simplex) < 2)
-      qh_setunique(simplex, maxx);
-    sizinit= qh_setsize(*simplex);
-    if (sizinit < 2) {
-      qh_precision("input has same x coordinate");
-      if (zzval_(Zsetplane) > qh hull_dim+1) {
-        qh_fprintf(qh ferr, 6012, "qhull precision error (qh_maxsimplex for voronoi_center):\n%d points with the same x coordinate.\n",
-                 qh_setsize(maxpoints)+numpoints);
-        qh_errexit(qh_ERRprec, NULL, NULL);
-      }else {
-        qh_fprintf(qh ferr, 6013, "qhull input error: input is less than %d-dimensional since it has the same x coordinate\n", qh hull_dim);
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-    }
-  }
-  for (k=sizinit; k < dim+1; k++) {
-    maxpoint= NULL;
-    maxdet= -REALmax;
-    FOREACHpoint_(maxpoints) {
-      if (!qh_setin(*simplex, point)) {
-        det= qh_detsimplex(point, *simplex, k, &nearzero);
-        if ((det= fabs_(det)) > maxdet) {
-          maxdet= det;
-          maxpoint= point;
-          maxnearzero= nearzero;
-        }
-      }
-    }
-    if (!maxpoint || maxnearzero) {
-      zinc_(Zsearchpoints);
-      if (!maxpoint) {
-        trace0((qh ferr, 7, "qh_maxsimplex: searching all points for %d-th initial vertex.\n", k+1));
-      }else {
-        trace0((qh ferr, 8, "qh_maxsimplex: searching all points for %d-th initial vertex, better than p%d det %2.2g\n",
-                k+1, qh_pointid(maxpoint), maxdet));
-      }
-      FORALLpoint_(points, numpoints) {
-        if (point == qh GOODpointp)
-          continue;
-        if (!qh_setin(*simplex, point)) {
-          det= qh_detsimplex(point, *simplex, k, &nearzero);
-          if ((det= fabs_(det)) > maxdet) {
-            maxdet= det;
-            maxpoint= point;
-            maxnearzero= nearzero;
-          }
-        }
-      }
-    } /* !maxpoint */
-    if (!maxpoint) {
-      qh_fprintf(qh ferr, 6014, "qhull internal error (qh_maxsimplex): not enough points available\n");
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-    qh_setappend(simplex, maxpoint);
-    trace1((qh ferr, 1002, "qh_maxsimplex: selected point p%d for %d`th initial vertex, det=%2.2g\n",
-            qh_pointid(maxpoint), k+1, maxdet));
-  } /* k */
-} /* maxsimplex */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="minabsval">-</a>
-
-  qh_minabsval( normal, dim )
-    return minimum absolute value of a dim vector
-*/
-realT qh_minabsval(realT *normal, int dim) {
-  realT minval= 0;
-  realT maxval= 0;
-  realT *colp;
-  int k;
-
-  for (k=dim, colp=normal; k--; colp++) {
-    maximize_(maxval, *colp);
-    minimize_(minval, *colp);
-  }
-  return fmax_(maxval, -minval);
-} /* minabsval */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="mindiff">-</a>
-
-  qh_mindif ( vecA, vecB, dim )
-    return index of min abs. difference of two vectors
-*/
-int qh_mindiff(realT *vecA, realT *vecB, int dim) {
-  realT mindiff= REALmax, diff;
-  realT *vecAp= vecA, *vecBp= vecB;
-  int k, mink= 0;
-
-  for (k=0; k < dim; k++) {
-    diff= *vecAp++ - *vecBp++;
-    diff= fabs_(diff);
-    if (diff < mindiff) {
-      mindiff= diff;
-      mink= k;
-    }
-  }
-  return mink;
-} /* mindiff */
-
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="orientoutside">-</a>
-
-  qh_orientoutside( facet  )
-    make facet outside oriented via qh.interior_point
-
-  returns:
-    True if facet reversed orientation.
-*/
-boolT qh_orientoutside(facetT *facet) {
-  int k;
-  realT dist;
-
-  qh_distplane(qh interior_point, facet, &dist);
-  if (dist > 0) {
-    for (k=qh hull_dim; k--; )
-      facet->normal[k]= -facet->normal[k];
-    facet->offset= -facet->offset;
-    return True;
-  }
-  return False;
-} /* orientoutside */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="outerinner">-</a>
-
-  qh_outerinner( facet, outerplane, innerplane  )
-    if facet and qh.maxoutdone (i.e., qh_check_maxout)
-      returns outer and inner plane for facet
-    else
-      returns maximum outer and inner plane
-    accounts for qh.JOGGLEmax
-
-  see:
-    qh_maxouter(), qh_check_bestdist(), qh_check_points()
-
-  notes:
-    outerplaner or innerplane may be NULL
-    facet is const
-    Does not error (QhullFacet)
-
-    includes qh.DISTround for actual points
-    adds another qh.DISTround if testing with floating point arithmetic
-*/
-void qh_outerinner(facetT *facet, realT *outerplane, realT *innerplane) {
-  realT dist, mindist;
-  vertexT *vertex, **vertexp;
-
-  if (outerplane) {
-    if (!qh_MAXoutside || !facet || !qh maxoutdone) {
-      *outerplane= qh_maxouter();       /* includes qh.DISTround */
-    }else { /* qh_MAXoutside ... */
-#if qh_MAXoutside
-      *outerplane= facet->maxoutside + qh DISTround;
-#endif
-
-    }
-    if (qh JOGGLEmax < REALmax/2)
-      *outerplane += qh JOGGLEmax * sqrt((realT)qh hull_dim);
-  }
-  if (innerplane) {
-    if (facet) {
-      mindist= REALmax;
-      FOREACHvertex_(facet->vertices) {
-        zinc_(Zdistio);
-        qh_distplane(vertex->point, facet, &dist);
-        minimize_(mindist, dist);
-      }
-      *innerplane= mindist - qh DISTround;
-    }else
-      *innerplane= qh min_vertex - qh DISTround;
-    if (qh JOGGLEmax < REALmax/2)
-      *innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
-  }
-} /* outerinner */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="pointdist">-</a>
-
-  qh_pointdist( point1, point2, dim )
-    return distance between two points
-
-  notes:
-    returns distance squared if 'dim' is negative
-*/
-coordT qh_pointdist(pointT *point1, pointT *point2, int dim) {
-  coordT dist, diff;
-  int k;
-
-  dist= 0.0;
-  for (k= (dim > 0 ? dim : -dim); k--; ) {
-    diff= *point1++ - *point2++;
-    dist += diff * diff;
-  }
-  if (dim > 0)
-    return(sqrt(dist));
-  return dist;
-} /* pointdist */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="printmatrix">-</a>
-
-  qh_printmatrix( fp, string, rows, numrow, numcol )
-    print matrix to fp given by row vectors
-    print string as header
-
-  notes:
-    print a vector by qh_printmatrix(fp, "", &vect, 1, len)
-*/
-void qh_printmatrix(FILE *fp, const char *string, realT **rows, int numrow, int numcol) {
-  realT *rowp;
-  realT r; /*bug fix*/
-  int i,k;
-
-  qh_fprintf(fp, 9001, "%s\n", string);
-  for (i=0; i < numrow; i++) {
-    rowp= rows[i];
-    for (k=0; k < numcol; k++) {
-      r= *rowp++;
-      qh_fprintf(fp, 9002, "%6.3g ", r);
-    }
-    qh_fprintf(fp, 9003, "\n");
-  }
-} /* printmatrix */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="printpoints">-</a>
-
-  qh_printpoints( fp, string, points )
-    print pointids to fp for a set of points
-    if string, prints string and 'p' point ids
-*/
-void qh_printpoints(FILE *fp, const char *string, setT *points) {
-  pointT *point, **pointp;
-
-  if (string) {
-    qh_fprintf(fp, 9004, "%s", string);
-    FOREACHpoint_(points)
-      qh_fprintf(fp, 9005, " p%d", qh_pointid(point));
-    qh_fprintf(fp, 9006, "\n");
-  }else {
-    FOREACHpoint_(points)
-      qh_fprintf(fp, 9007, " %d", qh_pointid(point));
-    qh_fprintf(fp, 9008, "\n");
-  }
-} /* printpoints */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="projectinput">-</a>
-
-  qh_projectinput()
-    project input points using qh.lower_bound/upper_bound and qh DELAUNAY
-    if qh.lower_bound[k]=qh.upper_bound[k]= 0,
-      removes dimension k
-    if halfspace intersection
-      removes dimension k from qh.feasible_point
-    input points in qh first_point, num_points, input_dim
-
-  returns:
-    new point array in qh first_point of qh hull_dim coordinates
-    sets qh POINTSmalloc
-    if qh DELAUNAY
-      projects points to paraboloid
-      lowbound/highbound is also projected
-    if qh ATinfinity
-      adds point "at-infinity"
-    if qh POINTSmalloc
-      frees old point array
-
-  notes:
-    checks that qh.hull_dim agrees with qh.input_dim, PROJECTinput, and DELAUNAY
-
-
-  design:
-    sets project[k] to -1 (delete), 0 (keep), 1 (add for Delaunay)
-    determines newdim and newnum for qh hull_dim and qh num_points
-    projects points to newpoints
-    projects qh.lower_bound to itself
-    projects qh.upper_bound to itself
-    if qh DELAUNAY
-      if qh ATINFINITY
-        projects points to paraboloid
-        computes "infinity" point as vertex average and 10% above all points
-      else
-        uses qh_setdelaunay to project points to paraboloid
-*/
-void qh_projectinput(void) {
-  int k,i;
-  int newdim= qh input_dim, newnum= qh num_points;
-  signed char *project;
-  int size= (qh input_dim+1)*sizeof(*project);
-  pointT *newpoints, *coord, *infinity;
-  realT paraboloid, maxboloid= 0;
-
-  project= (signed char*)qh_memalloc(size);
-  memset((char*)project, 0, (size_t)size);
-  for (k=0; k < qh input_dim; k++) {   /* skip Delaunay bound */
-    if (qh lower_bound[k] == 0 && qh upper_bound[k] == 0) {
-      project[k]= -1;
-      newdim--;
-    }
-  }
-  if (qh DELAUNAY) {
-    project[k]= 1;
-    newdim++;
-    if (qh ATinfinity)
-      newnum++;
-  }
-  if (newdim != qh hull_dim) {
-    qh_fprintf(qh ferr, 6015, "qhull internal error (qh_projectinput): dimension after projection %d != hull_dim %d\n", newdim, qh hull_dim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (!(newpoints=(coordT*)qh_malloc(newnum*newdim*sizeof(coordT)))){
-    qh_fprintf(qh ferr, 6016, "qhull error: insufficient memory to project %d points\n",
-           qh num_points);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  qh_projectpoints(project, qh input_dim+1, qh first_point,
-                    qh num_points, qh input_dim, newpoints, newdim);
-  trace1((qh ferr, 1003, "qh_projectinput: updating lower and upper_bound\n"));
-  qh_projectpoints(project, qh input_dim+1, qh lower_bound,
-                    1, qh input_dim+1, qh lower_bound, newdim+1);
-  qh_projectpoints(project, qh input_dim+1, qh upper_bound,
-                    1, qh input_dim+1, qh upper_bound, newdim+1);
-  if (qh HALFspace) {
-    if (!qh feasible_point) {
-      qh_fprintf(qh ferr, 6017, "qhull internal error (qh_projectinput): HALFspace defined without qh.feasible_point\n");
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-    qh_projectpoints(project, qh input_dim, qh feasible_point,
-                      1, qh input_dim, qh feasible_point, newdim);
-  }
-  qh_memfree(project, (qh input_dim+1)*sizeof(*project));
-  if (qh POINTSmalloc)
-    qh_free(qh first_point);
-  qh first_point= newpoints;
-  qh POINTSmalloc= True;
-  if (qh DELAUNAY && qh ATinfinity) {
-    coord= qh first_point;
-    infinity= qh first_point + qh hull_dim * qh num_points;
-    for (k=qh hull_dim-1; k--; )
-      infinity[k]= 0.0;
-    for (i=qh num_points; i--; ) {
-      paraboloid= 0.0;
-      for (k=0; k < qh hull_dim-1; k++) {
-        paraboloid += *coord * *coord;
-        infinity[k] += *coord;
-        coord++;
-      }
-      *(coord++)= paraboloid;
-      maximize_(maxboloid, paraboloid);
-    }
-    /* coord == infinity */
-    for (k=qh hull_dim-1; k--; )
-      *(coord++) /= qh num_points;
-    *(coord++)= maxboloid * 1.1;
-    qh num_points++;
-    trace0((qh ferr, 9, "qh_projectinput: projected points to paraboloid for Delaunay\n"));
-  }else if (qh DELAUNAY)  /* !qh ATinfinity */
-    qh_setdelaunay( qh hull_dim, qh num_points, qh first_point);
-} /* projectinput */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="projectpoints">-</a>
-
-  qh_projectpoints( project, n, points, numpoints, dim, newpoints, newdim )
-    project points/numpoints/dim to newpoints/newdim
-    if project[k] == -1
-      delete dimension k
-    if project[k] == 1
-      add dimension k by duplicating previous column
-    n is size of project
-
-  notes:
-    newpoints may be points if only adding dimension at end
-
-  design:
-    check that 'project' and 'newdim' agree
-    for each dimension
-      if project == -1
-        skip dimension
-      else
-        determine start of column in newpoints
-        determine start of column in points
-          if project == +1, duplicate previous column
-        copy dimension (column) from points to newpoints
-*/
-void qh_projectpoints(signed char *project, int n, realT *points,
-        int numpoints, int dim, realT *newpoints, int newdim) {
-  int testdim= dim, oldk=0, newk=0, i,j=0,k;
-  realT *newp, *oldp;
-
-  for (k=0; k < n; k++)
-    testdim += project[k];
-  if (testdim != newdim) {
-    qh_fprintf(qh ferr, 6018, "qhull internal error (qh_projectpoints): newdim %d should be %d after projection\n",
-      newdim, testdim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  for (j=0; j<n; j++) {
-    if (project[j] == -1)
-      oldk++;
-    else {
-      newp= newpoints+newk++;
-      if (project[j] == +1) {
-        if (oldk >= dim)
-          continue;
-        oldp= points+oldk;
-      }else
-        oldp= points+oldk++;
-      for (i=numpoints; i--; ) {
-        *newp= *oldp;
-        newp += newdim;
-        oldp += dim;
-      }
-    }
-    if (oldk >= dim)
-      break;
-  }
-  trace1((qh ferr, 1004, "qh_projectpoints: projected %d points from dim %d to dim %d\n",
-    numpoints, dim, newdim));
-} /* projectpoints */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="rotateinput">-</a>
-
-  qh_rotateinput( rows )
-    rotate input using row matrix
-    input points given by qh first_point, num_points, hull_dim
-    assumes rows[dim] is a scratch buffer
-    if qh POINTSmalloc, overwrites input points, else mallocs a new array
-
-  returns:
-    rotated input
-    sets qh POINTSmalloc
-
-  design:
-    see qh_rotatepoints
-*/
-void qh_rotateinput(realT **rows) {
-
-  if (!qh POINTSmalloc) {
-    qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
-    qh POINTSmalloc= True;
-  }
-  qh_rotatepoints(qh first_point, qh num_points, qh hull_dim, rows);
-}  /* rotateinput */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="rotatepoints">-</a>
-
-  qh_rotatepoints( points, numpoints, dim, row )
-    rotate numpoints points by a d-dim row matrix
-    assumes rows[dim] is a scratch buffer
-
-  returns:
-    rotated points in place
-
-  design:
-    for each point
-      for each coordinate
-        use row[dim] to compute partial inner product
-      for each coordinate
-        rotate by partial inner product
-*/
-void qh_rotatepoints(realT *points, int numpoints, int dim, realT **row) {
-  realT *point, *rowi, *coord= NULL, sum, *newval;
-  int i,j,k;
-
-  if (qh IStracing >= 1)
-    qh_printmatrix(qh ferr, "qh_rotatepoints: rotate points by", row, dim, dim);
-  for (point= points, j= numpoints; j--; point += dim) {
-    newval= row[dim];
-    for (i=0; i < dim; i++) {
-      rowi= row[i];
-      coord= point;
-      for (sum= 0.0, k= dim; k--; )
-        sum += *rowi++ * *coord++;
-      *(newval++)= sum;
-    }
-    for (k=dim; k--; )
-      *(--coord)= *(--newval);
-  }
-} /* rotatepoints */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="scaleinput">-</a>
-
-  qh_scaleinput()
-    scale input points using qh low_bound/high_bound
-    input points given by qh first_point, num_points, hull_dim
-    if qh POINTSmalloc, overwrites input points, else mallocs a new array
-
-  returns:
-    scales coordinates of points to low_bound[k], high_bound[k]
-    sets qh POINTSmalloc
-
-  design:
-    see qh_scalepoints
-*/
-void qh_scaleinput(void) {
-
-  if (!qh POINTSmalloc) {
-    qh first_point= qh_copypoints(qh first_point, qh num_points, qh hull_dim);
-    qh POINTSmalloc= True;
-  }
-  qh_scalepoints(qh first_point, qh num_points, qh hull_dim,
-       qh lower_bound, qh upper_bound);
-}  /* scaleinput */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="scalelast">-</a>
-
-  qh_scalelast( points, numpoints, dim, low, high, newhigh )
-    scale last coordinate to [0,m] for Delaunay triangulations
-    input points given by points, numpoints, dim
-
-  returns:
-    changes scale of last coordinate from [low, high] to [0, newhigh]
-    overwrites last coordinate of each point
-    saves low/high/newhigh in qh.last_low, etc. for qh_setdelaunay()
-
-  notes:
-    when called by qh_setdelaunay, low/high may not match actual data
-
-  design:
-    compute scale and shift factors
-    apply to last coordinate of each point
-*/
-void qh_scalelast(coordT *points, int numpoints, int dim, coordT low,
-                   coordT high, coordT newhigh) {
-  realT scale, shift;
-  coordT *coord;
-  int i;
-  boolT nearzero= False;
-
-  trace4((qh ferr, 4013, "qh_scalelast: scale last coordinate from [%2.2g, %2.2g] to [0,%2.2g]\n",
-    low, high, newhigh));
-  qh last_low= low;
-  qh last_high= high;
-  qh last_newhigh= newhigh;
-  scale= qh_divzero(newhigh, high - low,
-                  qh MINdenom_1, &nearzero);
-  if (nearzero) {
-    if (qh DELAUNAY)
-      qh_fprintf(qh ferr, 6019, "qhull input error: can not scale last coordinate.  Input is cocircular\n   or cospherical.   Use option 'Qz' to add a point at infinity.\n");
-    else
-      qh_fprintf(qh ferr, 6020, "qhull input error: can not scale last coordinate.  New bounds [0, %2.2g] are too wide for\nexisting bounds [%2.2g, %2.2g] (width %2.2g)\n",
-                newhigh, low, high, high-low);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  shift= - low * newhigh / (high-low);
-  coord= points + dim - 1;
-  for (i=numpoints; i--; coord += dim)
-    *coord= *coord * scale + shift;
-} /* scalelast */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="scalepoints">-</a>
-
-  qh_scalepoints( points, numpoints, dim, newlows, newhighs )
-    scale points to new lowbound and highbound
-    retains old bound when newlow= -REALmax or newhigh= +REALmax
-
-  returns:
-    scaled points
-    overwrites old points
-
-  design:
-    for each coordinate
-      compute current low and high bound
-      compute scale and shift factors
-      scale all points
-      enforce new low and high bound for all points
-*/
-void qh_scalepoints(pointT *points, int numpoints, int dim,
-        realT *newlows, realT *newhighs) {
-  int i,k;
-  realT shift, scale, *coord, low, high, newlow, newhigh, mincoord, maxcoord;
-  boolT nearzero= False;
-
-  for (k=0; k < dim; k++) {
-    newhigh= newhighs[k];
-    newlow= newlows[k];
-    if (newhigh > REALmax/2 && newlow < -REALmax/2)
-      continue;
-    low= REALmax;
-    high= -REALmax;
-    for (i=numpoints, coord=points+k; i--; coord += dim) {
-      minimize_(low, *coord);
-      maximize_(high, *coord);
-    }
-    if (newhigh > REALmax/2)
-      newhigh= high;
-    if (newlow < -REALmax/2)
-      newlow= low;
-    if (qh DELAUNAY && k == dim-1 && newhigh < newlow) {
-      qh_fprintf(qh ferr, 6021, "qhull input error: 'Qb%d' or 'QB%d' inverts paraboloid since high bound %.2g < low bound %.2g\n",
-               k, k, newhigh, newlow);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    scale= qh_divzero(newhigh - newlow, high - low,
-                  qh MINdenom_1, &nearzero);
-    if (nearzero) {
-      qh_fprintf(qh ferr, 6022, "qhull input error: %d'th dimension's new bounds [%2.2g, %2.2g] too wide for\nexisting bounds [%2.2g, %2.2g]\n",
-              k, newlow, newhigh, low, high);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    shift= (newlow * high - low * newhigh)/(high-low);
-    coord= points+k;
-    for (i=numpoints; i--; coord += dim)
-      *coord= *coord * scale + shift;
-    coord= points+k;
-    if (newlow < newhigh) {
-      mincoord= newlow;
-      maxcoord= newhigh;
-    }else {
-      mincoord= newhigh;
-      maxcoord= newlow;
-    }
-    for (i=numpoints; i--; coord += dim) {
-      minimize_(*coord, maxcoord);  /* because of roundoff error */
-      maximize_(*coord, mincoord);
-    }
-    trace0((qh ferr, 10, "qh_scalepoints: scaled %d'th coordinate [%2.2g, %2.2g] to [%.2g, %.2g] for %d points by %2.2g and shifted %2.2g\n",
-      k, low, high, newlow, newhigh, numpoints, scale, shift));
-  }
-} /* scalepoints */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="setdelaunay">-</a>
-
-  qh_setdelaunay( dim, count, points )
-    project count points to dim-d paraboloid for Delaunay triangulation
-
-    dim is one more than the dimension of the input set
-    assumes dim is at least 3 (i.e., at least a 2-d Delaunay triangulation)
-
-    points is a dim*count realT array.  The first dim-1 coordinates
-    are the coordinates of the first input point.  array[dim] is
-    the first coordinate of the second input point.  array[2*dim] is
-    the first coordinate of the third input point.
-
-    if qh.last_low defined (i.e., 'Qbb' called qh_scalelast)
-      calls qh_scalelast to scale the last coordinate the same as the other points
-
-  returns:
-    for each point
-      sets point[dim-1] to sum of squares of coordinates
-    scale points to 'Qbb' if needed
-
-  notes:
-    to project one point, use
-      qh_setdelaunay(qh hull_dim, 1, point)
-
-    Do not use options 'Qbk', 'QBk', or 'QbB' since they scale
-    the coordinates after the original projection.
-
-*/
-void qh_setdelaunay(int dim, int count, pointT *points) {
-  int i, k;
-  coordT *coordp, coord;
-  realT paraboloid;
-
-  trace0((qh ferr, 11, "qh_setdelaunay: project %d points to paraboloid for Delaunay triangulation\n", count));
-  coordp= points;
-  for (i=0; i < count; i++) {
-    coord= *coordp++;
-    paraboloid= coord*coord;
-    for (k=dim-2; k--; ) {
-      coord= *coordp++;
-      paraboloid += coord*coord;
-    }
-    *coordp++ = paraboloid;
-  }
-  if (qh last_low < REALmax/2)
-    qh_scalelast(points, count, dim, qh last_low, qh last_high, qh last_newhigh);
-} /* setdelaunay */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="sethalfspace">-</a>
-
-  qh_sethalfspace( dim, coords, nextp, normal, offset, feasible )
-    set point to dual of halfspace relative to feasible point
-    halfspace is normal coefficients and offset.
-
-  returns:
-    false if feasible point is outside of hull (error message already reported)
-    overwrites coordinates for point at dim coords
-    nextp= next point (coords)
-
-  design:
-    compute distance from feasible point to halfspace
-    divide each normal coefficient by -dist
-*/
-boolT qh_sethalfspace(int dim, coordT *coords, coordT **nextp,
-         coordT *normal, coordT *offset, coordT *feasible) {
-  coordT *normp= normal, *feasiblep= feasible, *coordp= coords;
-  realT dist;
-  realT r; /*bug fix*/
-  int k;
-  boolT zerodiv;
-
-  dist= *offset;
-  for (k=dim; k--; )
-    dist += *(normp++) * *(feasiblep++);
-  if (dist > 0)
-    goto LABELerroroutside;
-  normp= normal;
-  if (dist < -qh MINdenom) {
-    for (k=dim; k--; )
-      *(coordp++)= *(normp++) / -dist;
-  }else {
-    for (k=dim; k--; ) {
-      *(coordp++)= qh_divzero(*(normp++), -dist, qh MINdenom_1, &zerodiv);
-      if (zerodiv)
-        goto LABELerroroutside;
-    }
-  }
-  *nextp= coordp;
-  if (qh IStracing >= 4) {
-    qh_fprintf(qh ferr, 8021, "qh_sethalfspace: halfspace at offset %6.2g to point: ", *offset);
-    for (k=dim, coordp=coords; k--; ) {
-      r= *coordp++;
-      qh_fprintf(qh ferr, 8022, " %6.2g", r);
-    }
-    qh_fprintf(qh ferr, 8023, "\n");
-  }
-  return True;
-LABELerroroutside:
-  feasiblep= feasible;
-  normp= normal;
-  qh_fprintf(qh ferr, 6023, "qhull input error: feasible point is not clearly inside halfspace\nfeasible point: ");
-  for (k=dim; k--; )
-    qh_fprintf(qh ferr, 8024, qh_REAL_1, r=*(feasiblep++));
-  qh_fprintf(qh ferr, 8025, "\n     halfspace: ");
-  for (k=dim; k--; )
-    qh_fprintf(qh ferr, 8026, qh_REAL_1, r=*(normp++));
-  qh_fprintf(qh ferr, 8027, "\n     at offset: ");
-  qh_fprintf(qh ferr, 8028, qh_REAL_1, *offset);
-  qh_fprintf(qh ferr, 8029, " and distance: ");
-  qh_fprintf(qh ferr, 8030, qh_REAL_1, dist);
-  qh_fprintf(qh ferr, 8031, "\n");
-  return False;
-} /* sethalfspace */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="sethalfspace_all">-</a>
-
-  qh_sethalfspace_all( dim, count, halfspaces, feasible )
-    generate dual for halfspace intersection with feasible point
-    array of count halfspaces
-      each halfspace is normal coefficients followed by offset
-      the origin is inside the halfspace if the offset is negative
-
-  returns:
-    malloc'd array of count X dim-1 points
-
-  notes:
-    call before qh_init_B or qh_initqhull_globals
-    unused/untested code: please email bradb at shore.net if this works ok for you
-    If using option 'Fp', also set qh feasible_point. It is a malloc'd array
-      that is freed by qh_freebuffers.
-
-  design:
-    see qh_sethalfspace
-*/
-coordT *qh_sethalfspace_all(int dim, int count, coordT *halfspaces, pointT *feasible) {
-  int i, newdim;
-  pointT *newpoints;
-  coordT *coordp, *normalp, *offsetp;
-
-  trace0((qh ferr, 12, "qh_sethalfspace_all: compute dual for halfspace intersection\n"));
-  newdim= dim - 1;
-  if (!(newpoints=(coordT*)qh_malloc(count*newdim*sizeof(coordT)))){
-    qh_fprintf(qh ferr, 6024, "qhull error: insufficient memory to compute dual of %d halfspaces\n",
-          count);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  coordp= newpoints;
-  normalp= halfspaces;
-  for (i=0; i < count; i++) {
-    offsetp= normalp + newdim;
-    if (!qh_sethalfspace(newdim, coordp, &coordp, normalp, offsetp, feasible)) {
-      qh_fprintf(qh ferr, 8032, "The halfspace was at index %d\n", i);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    normalp= offsetp + 1;
-  }
-  return newpoints;
-} /* sethalfspace_all */
-
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="sharpnewfacets">-</a>
-
-  qh_sharpnewfacets()
-
-  returns:
-    true if could be an acute angle (facets in different quadrants)
-
-  notes:
-    for qh_findbest
-
-  design:
-    for all facets on qh.newfacet_list
-      if two facets are in different quadrants
-        set issharp
-*/
-boolT qh_sharpnewfacets() {
-  facetT *facet;
-  boolT issharp = False;
-  int *quadrant, k;
-
-  quadrant= (int*)qh_memalloc(qh hull_dim * sizeof(int));
-  FORALLfacet_(qh newfacet_list) {
-    if (facet == qh newfacet_list) {
-      for (k=qh hull_dim; k--; )
-        quadrant[ k]= (facet->normal[ k] > 0);
-    }else {
-      for (k=qh hull_dim; k--; ) {
-        if (quadrant[ k] != (facet->normal[ k] > 0)) {
-          issharp= True;
-          break;
-        }
-      }
-    }
-    if (issharp)
-      break;
-  }
-  qh_memfree( quadrant, qh hull_dim * sizeof(int));
-  trace3((qh ferr, 3001, "qh_sharpnewfacets: %d\n", issharp));
-  return issharp;
-} /* sharpnewfacets */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="voronoi_center">-</a>
-
-  qh_voronoi_center( dim, points )
-    return Voronoi center for a set of points
-    dim is the original dimension of the points
-    gh.gm_matrix/qh.gm_row are scratch buffers
-
-  returns:
-    center as a temporary point
-    if non-simplicial,
-      returns center for max simplex of points
-
-  notes:
-    from Bowyer & Woodwark, A Programmer's Geometry, 1983, p. 65
-
-  design:
-    if non-simplicial
-      determine max simplex for points
-    translate point0 of simplex to origin
-    compute sum of squares of diagonal
-    compute determinate
-    compute Voronoi center (see Bowyer & Woodwark)
-*/
-pointT *qh_voronoi_center(int dim, setT *points) {
-  pointT *point, **pointp, *point0;
-  pointT *center= (pointT*)qh_memalloc(qh center_size);
-  setT *simplex;
-  int i, j, k, size= qh_setsize(points);
-  coordT *gmcoord;
-  realT *diffp, sum2, *sum2row, *sum2p, det, factor;
-  boolT nearzero, infinite;
-
-  if (size == dim+1)
-    simplex= points;
-  else if (size < dim+1) {
-    qh_fprintf(qh ferr, 6025, "qhull internal error (qh_voronoi_center):\n  need at least %d points to construct a Voronoi center\n",
-             dim+1);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-    simplex= points;  /* never executed -- avoids warning */
-  }else {
-    simplex= qh_settemp(dim+1);
-    qh_maxsimplex(dim, points, NULL, 0, &simplex);
-  }
-  point0= SETfirstt_(simplex, pointT);
-  gmcoord= qh gm_matrix;
-  for (k=0; k < dim; k++) {
-    qh gm_row[k]= gmcoord;
-    FOREACHpoint_(simplex) {
-      if (point != point0)
-        *(gmcoord++)= point[k] - point0[k];
-    }
-  }
-  sum2row= gmcoord;
-  for (i=0; i < dim; i++) {
-    sum2= 0.0;
-    for (k=0; k < dim; k++) {
-      diffp= qh gm_row[k] + i;
-      sum2 += *diffp * *diffp;
-    }
-    *(gmcoord++)= sum2;
-  }
-  det= qh_determinant(qh gm_row, dim, &nearzero);
-  factor= qh_divzero(0.5, det, qh MINdenom, &infinite);
-  if (infinite) {
-    for (k=dim; k--; )
-      center[k]= qh_INFINITE;
-    if (qh IStracing)
-      qh_printpoints(qh ferr, "qh_voronoi_center: at infinity for ", simplex);
-  }else {
-    for (i=0; i < dim; i++) {
-      gmcoord= qh gm_matrix;
-      sum2p= sum2row;
-      for (k=0; k < dim; k++) {
-        qh gm_row[k]= gmcoord;
-        if (k == i) {
-          for (j=dim; j--; )
-            *(gmcoord++)= *sum2p++;
-        }else {
-          FOREACHpoint_(simplex) {
-            if (point != point0)
-              *(gmcoord++)= point[k] - point0[k];
-          }
-        }
-      }
-      center[i]= qh_determinant(qh gm_row, dim, &nearzero)*factor + point0[i];
-    }
-#ifndef qh_NOtrace
-    if (qh IStracing >= 3) {
-      qh_fprintf(qh ferr, 8033, "qh_voronoi_center: det %2.2g factor %2.2g ", det, factor);
-      qh_printmatrix(qh ferr, "center:", &center, 1, dim);
-      if (qh IStracing >= 5) {
-        qh_printpoints(qh ferr, "points", simplex);
-        FOREACHpoint_(simplex)
-          qh_fprintf(qh ferr, 8034, "p%d dist %.2g, ", qh_pointid(point),
-                   qh_pointdist(point, center, dim));
-        qh_fprintf(qh ferr, 8035, "\n");
-      }
-    }
-#endif
-  }
-  if (simplex != points)
-    qh_settempfree(&simplex);
-  return center;
-} /* voronoi_center */
-
diff --git a/alg/libqhull/global.c b/alg/libqhull/global.c
deleted file mode 100644
index 5ef7e02..0000000
--- a/alg/libqhull/global.c
+++ /dev/null
@@ -1,2126 +0,0 @@
-
-/*<html><pre>  -<a                             href="qh-globa.htm"
-  >-------------------------------</a><a name="TOP">-</a>
-
-   global.c
-   initializes all the globals of the qhull application
-
-   see README
-
-   see libqhull.h for qh.globals and function prototypes
-
-   see qhull_a.h for internal functions
-
-   Copyright (c) 1993-2012 The Geometry Center.
-   $Id: //main/2011/qhull/src/libqhull/global.c#15 $$Change: 1490 $
-   $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
- */
-
-#include "qhull_a.h"
-
-/*========= qh definition -- globals defined in libqhull.h =======================*/
-
-int qhull_inuse= 0; /* not used */
-
-#if qh_QHpointer
-qhT *qh_qh= NULL;       /* pointer to all global variables */
-#else
-qhT qh_qh;              /* all global variables.
-                           Add "= {0}" if this causes a compiler error.
-                           Also qh_qhstat in stat.c and qhmem in mem.c.  */
-#endif
-
-/*-<a                             href  ="qh-globa.htm#TOC"
-  >--------------------------------</a><a name="qh_version">-</a>
-
-  qh_version
-    version string by year and date
-
-    the revision increases on code changes only
-
-  notes:
-    change date:    Changes.txt, Announce.txt, index.htm, README.txt,
-                    qhull-news.html, Eudora signatures, CMakeLists.txt
-    change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt
-    change year:    Copying.txt
-    check download size
-    recompile user_eg.c, rbox.c, libqhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c, testqset.c
-*/
-
-const char *qh_version = "2012.1 2012/02/18";
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="appendprint">-</a>
-
-  qh_appendprint( printFormat )
-    append printFormat to qh.PRINTout unless already defined
-*/
-void qh_appendprint(qh_PRINT format) {
-  int i;
-
-  for (i=0; i < qh_PRINTEND; i++) {
-    if (qh PRINTout[i] == format && format != qh_PRINTqhull)
-      break;
-    if (!qh PRINTout[i]) {
-      qh PRINTout[i]= format;
-      break;
-    }
-  }
-} /* appendprint */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="checkflags">-</a>
-
-  qh_checkflags( commandStr, hiddenFlags )
-    errors if commandStr contains hiddenFlags
-    hiddenFlags starts and ends with a space and is space deliminated (checked)
-
-  notes:
-    ignores first word (e.g., "qconvex i")
-    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
-
-  see:
-    qh_initflags() initializes Qhull according to commandStr
-*/
-void qh_checkflags(char *command, char *hiddenflags) {
-  char *s= command, *t, *chkerr; /* qh_skipfilename is non-const */
-  char key, opt, prevopt;
-  char chkkey[]= "   ";
-  char chkopt[]=  "    ";
-  char chkopt2[]= "     ";
-  boolT waserr= False;
-
-  if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
-    qh_fprintf(qh ferr, 6026, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (strpbrk(hiddenflags, ",\n\r\t")) {
-    qh_fprintf(qh ferr, 6027, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  while (*s && !isspace(*s))  /* skip program name */
-    s++;
-  while (*s) {
-    while (*s && isspace(*s))
-      s++;
-    if (*s == '-')
-      s++;
-    if (!*s)
-      break;
-    key = *s++;
-    chkerr = NULL;
-    if (key == 'T' && (*s == 'I' || *s == 'O')) {  /* TI or TO 'file name' */
-      s= qh_skipfilename(++s);
-      continue;
-    }
-    chkkey[1]= key;
-    if (strstr(hiddenflags, chkkey)) {
-      chkerr= chkkey;
-    }else if (isupper(key)) {
-      opt= ' ';
-      prevopt= ' ';
-      chkopt[1]= key;
-      chkopt2[1]= key;
-      while (!chkerr && *s && !isspace(*s)) {
-        opt= *s++;
-        if (isalpha(opt)) {
-          chkopt[2]= opt;
-          if (strstr(hiddenflags, chkopt))
-            chkerr= chkopt;
-          if (prevopt != ' ') {
-            chkopt2[2]= prevopt;
-            chkopt2[3]= opt;
-            if (strstr(hiddenflags, chkopt2))
-              chkerr= chkopt2;
-          }
-        }else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
-              && (prevopt == ' ' || islower(prevopt))) {
-            chkopt[2]= opt;
-            if (strstr(hiddenflags, chkopt))
-              chkerr= chkopt;
-        }else {
-          qh_strtod(s-1, &t);
-          if (s < t)
-            s= t;
-        }
-        prevopt= opt;
-      }
-    }
-    if (chkerr) {
-      *chkerr= '\'';
-      chkerr[strlen(chkerr)-1]=  '\'';
-      qh_fprintf(qh ferr, 6029, "qhull error: option %s is not used with this program.\n             It may be used with qhull.\n", chkerr);
-      waserr= True;
-    }
-  }
-  if (waserr)
-    qh_errexit(qh_ERRinput, NULL, NULL);
-} /* checkflags */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="qh_clear_outputflags">-</a>
-
-  qh_clear_outputflags()
-    Clear output flags for QhullPoints
-*/
-void qh_clear_outputflags(void) {
-  int i,k;
-
-  qh ANNOTATEoutput= False;
-  qh DOintersections= False;
-  qh DROPdim= -1;
-  qh FORCEoutput= False;
-  qh GETarea= False;
-  qh GOODpoint= 0;
-  qh GOODpointp= NULL;
-  qh GOODthreshold= False;
-  qh GOODvertex= 0;
-  qh GOODvertexp= NULL;
-  qh IStracing= 0;
-  qh KEEParea= False;
-  qh KEEPmerge= False;
-  qh KEEPminArea= REALmax;
-  qh PRINTcentrums= False;
-  qh PRINTcoplanar= False;
-  qh PRINTdots= False;
-  qh PRINTgood= False;
-  qh PRINTinner= False;
-  qh PRINTneighbors= False;
-  qh PRINTnoplanes= False;
-  qh PRINToptions1st= False;
-  qh PRINTouter= False;
-  qh PRINTprecision= True;
-  qh PRINTridges= False;
-  qh PRINTspheres= False;
-  qh PRINTstatistics= False;
-  qh PRINTsummary= False;
-  qh PRINTtransparent= False;
-  qh SPLITthresholds= False;
-  qh TRACElevel= 0;
-  qh TRInormals= False;
-  qh USEstdout= False;
-  qh VERIFYoutput= False;
-  for (k=qh input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
-    qh lower_threshold[k]= -REALmax;
-    qh upper_threshold[k]= REALmax;
-    qh lower_bound[k]= -REALmax;
-    qh upper_bound[k]= REALmax;
-  }
-
-  for (i=0; i < qh_PRINTEND; i++) {
-    qh PRINTout[i]= qh_PRINTnone;
-  }
-
-  if (!qh qhull_commandsiz2)
-      qh qhull_commandsiz2= (int)strlen(qh qhull_command); /* WARN64 */
-  else {
-      qh qhull_command[qh qhull_commandsiz2]= '\0';
-  }
-  if (!qh qhull_optionsiz2)
-    qh qhull_optionsiz2= (int)strlen(qh qhull_options);  /* WARN64 */
-  else {
-    qh qhull_options[qh qhull_optionsiz2]= '\0';
-    qh qhull_optionlen= qh_OPTIONline;  /* start a new line */
-  }
-} /* clear_outputflags */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="clock">-</a>
-
-  qh_clock()
-    return user CPU time in 100ths (qh_SECtick)
-    only defined for qh_CLOCKtype == 2
-
-  notes:
-    use first value to determine time 0
-    from Stevens '92 8.15
-*/
-unsigned long qh_clock(void) {
-
-#if (qh_CLOCKtype == 2)
-  struct tms time;
-  static long clktck;  /* initialized first call */
-  double ratio, cpu;
-  unsigned long ticks;
-
-  if (!clktck) {
-    if ((clktck= sysconf(_SC_CLK_TCK)) < 0) {
-      qh_fprintf(qh ferr, 6030, "qhull internal error (qh_clock): sysconf() failed.  Use qh_CLOCKtype 1 in user.h\n");
-      qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-  }
-  if (times(&time) == -1) {
-    qh_fprintf(qh ferr, 6031, "qhull internal error (qh_clock): times() failed.  Use qh_CLOCKtype 1 in user.h\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  ratio= qh_SECticks / (double)clktck;
-  ticks= time.tms_utime * ratio;
-  return ticks;
-#else
-  qh_fprintf(qh ferr, 6032, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
-  qh_errexit(qh_ERRqhull, NULL, NULL); /* never returns */
-  return 0;
-#endif
-} /* clock */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="freebuffers">-</a>
-
-  qh_freebuffers()
-    free up global memory buffers
-
-  notes:
-    must match qh_initbuffers()
-*/
-void qh_freebuffers(void) {
-
-  trace5((qh ferr, 5001, "qh_freebuffers: freeing up global memory buffers\n"));
-  /* allocated by qh_initqhull_buffers */
-  qh_memfree(qh NEARzero, qh hull_dim * sizeof(realT));
-  qh_memfree(qh lower_threshold, (qh input_dim+1) * sizeof(realT));
-  qh_memfree(qh upper_threshold, (qh input_dim+1) * sizeof(realT));
-  qh_memfree(qh lower_bound, (qh input_dim+1) * sizeof(realT));
-  qh_memfree(qh upper_bound, (qh input_dim+1) * sizeof(realT));
-  qh_memfree(qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
-  qh_memfree(qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
-  qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
-  qh lower_bound= qh upper_bound= NULL;
-  qh gm_matrix= NULL;
-  qh gm_row= NULL;
-  qh_setfree(&qh other_points);
-  qh_setfree(&qh del_vertices);
-  qh_setfree(&qh coplanarfacetset);
-  if (qh line)                /* allocated by qh_readinput, freed if no error */
-    qh_free(qh line);
-  if (qh half_space)
-    qh_free(qh half_space);
-  if (qh temp_malloc)
-    qh_free(qh temp_malloc);
-  if (qh feasible_point)      /* allocated by qh_readfeasible */
-    qh_free(qh feasible_point);
-  if (qh feasible_string)     /* allocated by qh_initflags */
-    qh_free(qh feasible_string);
-  qh line= qh feasible_string= NULL;
-  qh half_space= qh feasible_point= qh temp_malloc= NULL;
-  /* usually allocated by qh_readinput */
-  if (qh first_point && qh POINTSmalloc) {
-    qh_free(qh first_point);
-    qh first_point= NULL;
-  }
-  if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
-    qh_free(qh input_points);
-    qh input_points= NULL;
-  }
-  trace5((qh ferr, 5002, "qh_freebuffers: finished\n"));
-} /* freebuffers */
-
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="freebuild">-</a>
-
-  qh_freebuild( allmem )
-    free global memory used by qh_initbuild and qh_buildhull
-    if !allmem,
-      does not free short memory (e.g., facetT, freed by qh_memfreeshort)
-
-  design:
-    free centrums
-    free each vertex
-    mark unattached ridges
-    for each facet
-      free ridges
-      free outside set, coplanar set, neighbor set, ridge set, vertex set
-      free facet
-    free hash table
-    free interior point
-    free merge set
-    free temporary sets
-*/
-void qh_freebuild(boolT allmem) {
-  facetT *facet;
-  vertexT *vertex;
-  ridgeT *ridge, **ridgep;
-  mergeT *merge, **mergep;
-
-  trace1((qh ferr, 1005, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
-  if (qh del_vertices)
-    qh_settruncate(qh del_vertices, 0);
-  if (allmem) {
-    while ((vertex= qh vertex_list)) {
-      if (vertex->next)
-        qh_delvertex(vertex);
-      else {
-        qh_memfree(vertex, (int)sizeof(vertexT));
-        qh newvertex_list= qh vertex_list= NULL;
-      }
-    }
-  }else if (qh VERTEXneighbors) {
-    FORALLvertices
-      qh_setfreelong(&(vertex->neighbors));
-  }
-  qh VERTEXneighbors= False;
-  qh GOODclosest= NULL;
-  if (allmem) {
-    FORALLfacets {
-      FOREACHridge_(facet->ridges)
-        ridge->seen= False;
-    }
-    FORALLfacets {
-      if (facet->visible) {
-        FOREACHridge_(facet->ridges) {
-          if (!otherfacet_(ridge, facet)->visible)
-            ridge->seen= True;  /* an unattached ridge */
-        }
-      }
-    }
-    while ((facet= qh facet_list)) {
-      FOREACHridge_(facet->ridges) {
-        if (ridge->seen) {
-          qh_setfree(&(ridge->vertices));
-          qh_memfree(ridge, (int)sizeof(ridgeT));
-        }else
-          ridge->seen= True;
-      }
-      qh_setfree(&(facet->outsideset));
-      qh_setfree(&(facet->coplanarset));
-      qh_setfree(&(facet->neighbors));
-      qh_setfree(&(facet->ridges));
-      qh_setfree(&(facet->vertices));
-      if (facet->next)
-        qh_delfacet(facet);
-      else {
-        qh_memfree(facet, (int)sizeof(facetT));
-        qh visible_list= qh newfacet_list= qh facet_list= NULL;
-      }
-    }
-  }else {
-    FORALLfacets {
-      qh_setfreelong(&(facet->outsideset));
-      qh_setfreelong(&(facet->coplanarset));
-      if (!facet->simplicial) {
-        qh_setfreelong(&(facet->neighbors));
-        qh_setfreelong(&(facet->ridges));
-        qh_setfreelong(&(facet->vertices));
-      }
-    }
-  }
-  qh_setfree(&(qh hash_table));
-  qh_memfree(qh interior_point, qh normal_size);
-  qh interior_point= NULL;
-  FOREACHmerge_(qh facet_mergeset)  /* usually empty */
-    qh_memfree(merge, (int)sizeof(mergeT));
-  qh facet_mergeset= NULL;  /* temp set */
-  qh degen_mergeset= NULL;  /* temp set */
-  qh_settempfree_all();
-} /* freebuild */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="freeqhull">-</a>
-
-  qh_freeqhull( allmem )
-    see qh_freeqhull2
-    if qh_QHpointer, frees qh_qh
-*/
-void qh_freeqhull(boolT allmem) {
-    qh_freeqhull2(allmem);
-#if qh_QHpointer
-    qh_free(qh_qh);
-    qh_qh= NULL;
-#endif
-}
-
-/*-<a                             href="qh-globa.htm#TOC"
->-------------------------------</a><a name="freeqhull2">-</a>
-
-qh_freeqhull2( allmem )
-  free global memory
-  if !allmem,
-    does not free short memory (freed by qh_memfreeshort)
-
-notes:
-  sets qh.NOerrexit in case caller forgets to
-
-see:
-  see qh_initqhull_start2()
-
-design:
-  free global and temporary memory from qh_initbuild and qh_buildhull
-  free buffers
-  free statistics
-*/
-void qh_freeqhull2(boolT allmem) {
-
-  trace1((qh ferr, 1006, "qh_freeqhull2: free global memory\n"));
-  qh NOerrexit= True;  /* no more setjmp since called at exit and ~QhullQh */
-  qh_freebuild(allmem);
-  qh_freebuffers();
-  qh_freestatistics();
-#if qh_QHpointer
-  memset((char *)qh_qh, 0, sizeof(qhT));
-  /* qh_qh freed by caller, qh_freeqhull() */
-#else
-  memset((char *)&qh_qh, 0, sizeof(qhT));
-#endif
-  qh NOerrexit= True;
-} /* freeqhull2 */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="init_A">-</a>
-
-  qh_init_A( infile, outfile, errfile, argc, argv )
-    initialize memory and stdio files
-    convert input options to option string (qh.qhull_command)
-
-  notes:
-    infile may be NULL if qh_readpoints() is not called
-
-    errfile should always be defined.  It is used for reporting
-    errors.  outfile is used for output and format options.
-
-    argc/argv may be 0/NULL
-
-    called before error handling initialized
-    qh_errexit() may not be used
-*/
-void qh_init_A(FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
-  qh_meminit(errfile);
-  qh_initqhull_start(infile, outfile, errfile);
-  qh_init_qhull_command(argc, argv);
-} /* init_A */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="init_B">-</a>
-
-  qh_init_B( points, numpoints, dim, ismalloc )
-    initialize globals for points array
-
-    points has numpoints dim-dimensional points
-      points[0] is the first coordinate of the first point
-      points[1] is the second coordinate of the first point
-      points[dim] is the first coordinate of the second point
-
-    ismalloc=True
-      Qhull will call qh_free(points) on exit or input transformation
-    ismalloc=False
-      Qhull will allocate a new point array if needed for input transformation
-
-    qh.qhull_command
-      is the option string.
-      It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
-
-  returns:
-    if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
-      projects the input to a new point array
-
-        if qh.DELAUNAY,
-          qh.hull_dim is increased by one
-        if qh.ATinfinity,
-          qh_projectinput adds point-at-infinity for Delaunay tri.
-
-    if qh.SCALEinput
-      changes the upper and lower bounds of the input, see qh_scaleinput()
-
-    if qh.ROTATEinput
-      rotates the input by a random rotation, see qh_rotateinput()
-      if qh.DELAUNAY
-        rotates about the last coordinate
-
-  notes:
-    called after points are defined
-    qh_errexit() may be used
-*/
-void qh_init_B(coordT *points, int numpoints, int dim, boolT ismalloc) {
-  qh_initqhull_globals(points, numpoints, dim, ismalloc);
-  if (qhmem.LASTsize == 0)
-    qh_initqhull_mem();
-  /* mem.c and qset.c are initialized */
-  qh_initqhull_buffers();
-  qh_initthresholds(qh qhull_command);
-  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
-    qh_projectinput();
-  if (qh SCALEinput)
-    qh_scaleinput();
-  if (qh ROTATErandom >= 0) {
-    qh_randommatrix(qh gm_matrix, qh hull_dim, qh gm_row);
-    if (qh DELAUNAY) {
-      int k, lastk= qh hull_dim-1;
-      for (k=0; k < lastk; k++) {
-        qh gm_row[k][lastk]= 0.0;
-        qh gm_row[lastk][k]= 0.0;
-      }
-      qh gm_row[lastk][lastk]= 1.0;
-    }
-    qh_gram_schmidt(qh hull_dim, qh gm_row);
-    qh_rotateinput(qh gm_row);
-  }
-} /* init_B */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="init_qhull_command">-</a>
-
-  qh_init_qhull_command( argc, argv )
-    build qh.qhull_command from argc/argv
-
-  returns:
-    a space-delimited string of options (just as typed)
-
-  notes:
-    makes option string easy to input and output
-
-    argc/argv may be 0/NULL
-*/
-void qh_init_qhull_command(int argc, char *argv[]) {
-
-  if (!qh_argv_to_command(argc, argv, qh qhull_command, (int)sizeof(qh qhull_command))){
-    /* Assumes qh.ferr is defined. */
-    qh_fprintf(qh ferr, 6033, "qhull input error: more than %d characters in command line\n",
-          (int)sizeof(qh qhull_command));
-    qh_exit(qh_ERRinput);  /* error reported, can not use qh_errexit */
-  }
-} /* init_qhull_command */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="initflags">-</a>
-
-  qh_initflags( commandStr )
-    set flags and initialized constants from commandStr
-
-  returns:
-    sets qh.qhull_command to command if needed
-
-  notes:
-    ignores first word (e.g., "qhull d")
-    use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
-
-  see:
-    qh_initthresholds() continues processing of 'Pdn' and 'PDn'
-    'prompt' in unix.c for documentation
-
-  design:
-    for each space-delimited option group
-      if top-level option
-        check syntax
-        append appropriate option to option string
-        set appropriate global variable or append printFormat to print options
-      else
-        for each sub-option
-          check syntax
-          append appropriate option to option string
-          set appropriate global variable or append printFormat to print options
-*/
-void qh_initflags(char *command) {
-  int k, i, lastproject;
-  char *s= command, *t, *prev_s, *start, key;
-  boolT isgeom= False, wasproject;
-  realT r;
-
-  if (command <= &qh qhull_command[0] || command > &qh qhull_command[0] + sizeof(qh qhull_command)) {
-    if (command != &qh qhull_command[0]) {
-      *qh qhull_command= '\0';
-      strncat(qh qhull_command, command, sizeof(qh qhull_command)-strlen(qh qhull_command)-1);
-    }
-    while (*s && !isspace(*s))  /* skip program name */
-      s++;
-  }
-  while (*s) {
-    while (*s && isspace(*s))
-      s++;
-    if (*s == '-')
-      s++;
-    if (!*s)
-      break;
-    prev_s= s;
-    switch (*s++) {
-    case 'd':
-      qh_option("delaunay", NULL, NULL);
-      qh DELAUNAY= True;
-      break;
-    case 'f':
-      qh_option("facets", NULL, NULL);
-      qh_appendprint(qh_PRINTfacets);
-      break;
-    case 'i':
-      qh_option("incidence", NULL, NULL);
-      qh_appendprint(qh_PRINTincidences);
-      break;
-    case 'm':
-      qh_option("mathematica", NULL, NULL);
-      qh_appendprint(qh_PRINTmathematica);
-      break;
-    case 'n':
-      qh_option("normals", NULL, NULL);
-      qh_appendprint(qh_PRINTnormals);
-      break;
-    case 'o':
-      qh_option("offFile", NULL, NULL);
-      qh_appendprint(qh_PRINToff);
-      break;
-    case 'p':
-      qh_option("points", NULL, NULL);
-      qh_appendprint(qh_PRINTpoints);
-      break;
-    case 's':
-      qh_option("summary", NULL, NULL);
-      qh PRINTsummary= True;
-      break;
-    case 'v':
-      qh_option("voronoi", NULL, NULL);
-      qh VORONOI= True;
-      qh DELAUNAY= True;
-      break;
-    case 'A':
-      if (!isdigit(*s) && *s != '.' && *s != '-')
-        qh_fprintf(qh ferr, 7002, "qhull warning: no maximum cosine angle given for option 'An'.  Ignored.\n");
-      else {
-        if (*s == '-') {
-          qh premerge_cos= -qh_strtod(s, &s);
-          qh_option("Angle-premerge-", NULL, &qh premerge_cos);
-          qh PREmerge= True;
-        }else {
-          qh postmerge_cos= qh_strtod(s, &s);
-          qh_option("Angle-postmerge", NULL, &qh postmerge_cos);
-          qh POSTmerge= True;
-        }
-        qh MERGING= True;
-      }
-      break;
-    case 'C':
-      if (!isdigit(*s) && *s != '.' && *s != '-')
-        qh_fprintf(qh ferr, 7003, "qhull warning: no centrum radius given for option 'Cn'.  Ignored.\n");
-      else {
-        if (*s == '-') {
-          qh premerge_centrum= -qh_strtod(s, &s);
-          qh_option("Centrum-premerge-", NULL, &qh premerge_centrum);
-          qh PREmerge= True;
-        }else {
-          qh postmerge_centrum= qh_strtod(s, &s);
-          qh_option("Centrum-postmerge", NULL, &qh postmerge_centrum);
-          qh POSTmerge= True;
-        }
-        qh MERGING= True;
-      }
-      break;
-    case 'E':
-      if (*s == '-')
-        qh_fprintf(qh ferr, 7004, "qhull warning: negative maximum roundoff given for option 'An'.  Ignored.\n");
-      else if (!isdigit(*s))
-        qh_fprintf(qh ferr, 7005, "qhull warning: no maximum roundoff given for option 'En'.  Ignored.\n");
-      else {
-        qh DISTround= qh_strtod(s, &s);
-        qh_option("Distance-roundoff", NULL, &qh DISTround);
-        qh SETroundoff= True;
-      }
-      break;
-    case 'H':
-      start= s;
-      qh HALFspace= True;
-      qh_strtod(s, &t);
-      while (t > s)  {
-        if (*t && !isspace(*t)) {
-          if (*t == ',')
-            t++;
-          else
-            qh_fprintf(qh ferr, 7006, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
-        }
-        s= t;
-        qh_strtod(s, &t);
-      }
-      if (start < t) {
-        if (!(qh feasible_string= (char*)calloc((size_t)(t-start+1), (size_t)1))) {
-          qh_fprintf(qh ferr, 6034, "qhull error: insufficient memory for 'Hn,n,n'\n");
-          qh_errexit(qh_ERRmem, NULL, NULL);
-        }
-        strncpy(qh feasible_string, start, (size_t)(t-start));
-        qh_option("Halfspace-about", NULL, NULL);
-        qh_option(qh feasible_string, NULL, NULL);
-      }else
-        qh_option("Halfspace", NULL, NULL);
-      break;
-    case 'R':
-      if (!isdigit(*s))
-        qh_fprintf(qh ferr, 7007, "qhull warning: missing random perturbation for option 'Rn'.  Ignored\n");
-      else {
-        qh RANDOMfactor= qh_strtod(s, &s);
-        qh_option("Random_perturb", NULL, &qh RANDOMfactor);
-        qh RANDOMdist= True;
-      }
-      break;
-    case 'V':
-      if (!isdigit(*s) && *s != '-')
-        qh_fprintf(qh ferr, 7008, "qhull warning: missing visible distance for option 'Vn'.  Ignored\n");
-      else {
-        qh MINvisible= qh_strtod(s, &s);
-        qh_option("Visible", NULL, &qh MINvisible);
-      }
-      break;
-    case 'U':
-      if (!isdigit(*s) && *s != '-')
-        qh_fprintf(qh ferr, 7009, "qhull warning: missing coplanar distance for option 'Un'.  Ignored\n");
-      else {
-        qh MAXcoplanar= qh_strtod(s, &s);
-        qh_option("U-coplanar", NULL, &qh MAXcoplanar);
-      }
-      break;
-    case 'W':
-      if (*s == '-')
-        qh_fprintf(qh ferr, 7010, "qhull warning: negative outside width for option 'Wn'.  Ignored.\n");
-      else if (!isdigit(*s))
-        qh_fprintf(qh ferr, 7011, "qhull warning: missing outside width for option 'Wn'.  Ignored\n");
-      else {
-        qh MINoutside= qh_strtod(s, &s);
-        qh_option("W-outside", NULL, &qh MINoutside);
-        qh APPROXhull= True;
-      }
-      break;
-    /************  sub menus ***************/
-    case 'F':
-      while (*s && !isspace(*s)) {
-        switch (*s++) {
-        case 'a':
-          qh_option("Farea", NULL, NULL);
-          qh_appendprint(qh_PRINTarea);
-          qh GETarea= True;
-          break;
-        case 'A':
-          qh_option("FArea-total", NULL, NULL);
-          qh GETarea= True;
-          break;
-        case 'c':
-          qh_option("Fcoplanars", NULL, NULL);
-          qh_appendprint(qh_PRINTcoplanars);
-          break;
-        case 'C':
-          qh_option("FCentrums", NULL, NULL);
-          qh_appendprint(qh_PRINTcentrums);
-          break;
-        case 'd':
-          qh_option("Fd-cdd-in", NULL, NULL);
-          qh CDDinput= True;
-          break;
-        case 'D':
-          qh_option("FD-cdd-out", NULL, NULL);
-          qh CDDoutput= True;
-          break;
-        case 'F':
-          qh_option("FFacets-xridge", NULL, NULL);
-          qh_appendprint(qh_PRINTfacets_xridge);
-          break;
-        case 'i':
-          qh_option("Finner", NULL, NULL);
-          qh_appendprint(qh_PRINTinner);
-          break;
-        case 'I':
-          qh_option("FIDs", NULL, NULL);
-          qh_appendprint(qh_PRINTids);
-          break;
-        case 'm':
-          qh_option("Fmerges", NULL, NULL);
-          qh_appendprint(qh_PRINTmerges);
-          break;
-        case 'M':
-          qh_option("FMaple", NULL, NULL);
-          qh_appendprint(qh_PRINTmaple);
-          break;
-        case 'n':
-          qh_option("Fneighbors", NULL, NULL);
-          qh_appendprint(qh_PRINTneighbors);
-          break;
-        case 'N':
-          qh_option("FNeighbors-vertex", NULL, NULL);
-          qh_appendprint(qh_PRINTvneighbors);
-          break;
-        case 'o':
-          qh_option("Fouter", NULL, NULL);
-          qh_appendprint(qh_PRINTouter);
-          break;
-        case 'O':
-          if (qh PRINToptions1st) {
-            qh_option("FOptions", NULL, NULL);
-            qh_appendprint(qh_PRINToptions);
-          }else
-            qh PRINToptions1st= True;
-          break;
-        case 'p':
-          qh_option("Fpoint-intersect", NULL, NULL);
-          qh_appendprint(qh_PRINTpointintersect);
-          break;
-        case 'P':
-          qh_option("FPoint-nearest", NULL, NULL);
-          qh_appendprint(qh_PRINTpointnearest);
-          break;
-        case 'Q':
-          qh_option("FQhull", NULL, NULL);
-          qh_appendprint(qh_PRINTqhull);
-          break;
-        case 's':
-          qh_option("Fsummary", NULL, NULL);
-          qh_appendprint(qh_PRINTsummary);
-          break;
-        case 'S':
-          qh_option("FSize", NULL, NULL);
-          qh_appendprint(qh_PRINTsize);
-          qh GETarea= True;
-          break;
-        case 't':
-          qh_option("Ftriangles", NULL, NULL);
-          qh_appendprint(qh_PRINTtriangles);
-          break;
-        case 'v':
-          /* option set in qh_initqhull_globals */
-          qh_appendprint(qh_PRINTvertices);
-          break;
-        case 'V':
-          qh_option("FVertex-average", NULL, NULL);
-          qh_appendprint(qh_PRINTaverage);
-          break;
-        case 'x':
-          qh_option("Fxtremes", NULL, NULL);
-          qh_appendprint(qh_PRINTextremes);
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7012, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    case 'G':
-      isgeom= True;
-      qh_appendprint(qh_PRINTgeom);
-      while (*s && !isspace(*s)) {
-        switch (*s++) {
-        case 'a':
-          qh_option("Gall-points", NULL, NULL);
-          qh PRINTdots= True;
-          break;
-        case 'c':
-          qh_option("Gcentrums", NULL, NULL);
-          qh PRINTcentrums= True;
-          break;
-        case 'h':
-          qh_option("Gintersections", NULL, NULL);
-          qh DOintersections= True;
-          break;
-        case 'i':
-          qh_option("Ginner", NULL, NULL);
-          qh PRINTinner= True;
-          break;
-        case 'n':
-          qh_option("Gno-planes", NULL, NULL);
-          qh PRINTnoplanes= True;
-          break;
-        case 'o':
-          qh_option("Gouter", NULL, NULL);
-          qh PRINTouter= True;
-          break;
-        case 'p':
-          qh_option("Gpoints", NULL, NULL);
-          qh PRINTcoplanar= True;
-          break;
-        case 'r':
-          qh_option("Gridges", NULL, NULL);
-          qh PRINTridges= True;
-          break;
-        case 't':
-          qh_option("Gtransparent", NULL, NULL);
-          qh PRINTtransparent= True;
-          break;
-        case 'v':
-          qh_option("Gvertices", NULL, NULL);
-          qh PRINTspheres= True;
-          break;
-        case 'D':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6035, "qhull input error: missing dimension for option 'GDn'\n");
-          else {
-            if (qh DROPdim >= 0)
-              qh_fprintf(qh ferr, 7013, "qhull warning: can only drop one dimension.  Previous 'GD%d' ignored\n",
-                   qh DROPdim);
-            qh DROPdim= qh_strtol(s, &s);
-            qh_option("GDrop-dim", &qh DROPdim, NULL);
-          }
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7014, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    case 'P':
-      while (*s && !isspace(*s)) {
-        switch (*s++) {
-        case 'd': case 'D':  /* see qh_initthresholds() */
-          key= s[-1];
-          i= qh_strtol(s, &s);
-          r= 0;
-          if (*s == ':') {
-            s++;
-            r= qh_strtod(s, &s);
-          }
-          if (key == 'd')
-            qh_option("Pdrop-facets-dim-less", &i, &r);
-          else
-            qh_option("PDrop-facets-dim-more", &i, &r);
-          break;
-        case 'g':
-          qh_option("Pgood-facets", NULL, NULL);
-          qh PRINTgood= True;
-          break;
-        case 'G':
-          qh_option("PGood-facet-neighbors", NULL, NULL);
-          qh PRINTneighbors= True;
-          break;
-        case 'o':
-          qh_option("Poutput-forced", NULL, NULL);
-          qh FORCEoutput= True;
-          break;
-        case 'p':
-          qh_option("Pprecision-ignore", NULL, NULL);
-          qh PRINTprecision= False;
-          break;
-        case 'A':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6036, "qhull input error: missing facet count for keep area option 'PAn'\n");
-          else {
-            qh KEEParea= qh_strtol(s, &s);
-            qh_option("PArea-keep", &qh KEEParea, NULL);
-            qh GETarea= True;
-          }
-          break;
-        case 'F':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6037, "qhull input error: missing facet area for option 'PFn'\n");
-          else {
-            qh KEEPminArea= qh_strtod(s, &s);
-            qh_option("PFacet-area-keep", NULL, &qh KEEPminArea);
-            qh GETarea= True;
-          }
-          break;
-        case 'M':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6038, "qhull input error: missing merge count for option 'PMn'\n");
-          else {
-            qh KEEPmerge= qh_strtol(s, &s);
-            qh_option("PMerge-keep", &qh KEEPmerge, NULL);
-          }
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7015, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    case 'Q':
-      lastproject= -1;
-      while (*s && !isspace(*s)) {
-        switch (*s++) {
-        case 'b': case 'B':  /* handled by qh_initthresholds */
-          key= s[-1];
-          if (key == 'b' && *s == 'B') {
-            s++;
-            r= qh_DEFAULTbox;
-            qh SCALEinput= True;
-            qh_option("QbBound-unit-box", NULL, &r);
-            break;
-          }
-          if (key == 'b' && *s == 'b') {
-            s++;
-            qh SCALElast= True;
-            qh_option("Qbbound-last", NULL, NULL);
-            break;
-          }
-          k= qh_strtol(s, &s);
-          r= 0.0;
-          wasproject= False;
-          if (*s == ':') {
-            s++;
-            if ((r= qh_strtod(s, &s)) == 0.0) {
-              t= s;            /* need true dimension for memory allocation */
-              while (*t && !isspace(*t)) {
-                if (toupper(*t++) == 'B'
-                 && k == qh_strtol(t, &t)
-                 && *t++ == ':'
-                 && qh_strtod(t, &t) == 0.0) {
-                  qh PROJECTinput++;
-                  trace2((qh ferr, 2004, "qh_initflags: project dimension %d\n", k));
-                  qh_option("Qb-project-dim", &k, NULL);
-                  wasproject= True;
-                  lastproject= k;
-                  break;
-                }
-              }
-            }
-          }
-          if (!wasproject) {
-            if (lastproject == k && r == 0.0)
-              lastproject= -1;  /* doesn't catch all possible sequences */
-            else if (key == 'b') {
-              qh SCALEinput= True;
-              if (r == 0.0)
-                r= -qh_DEFAULTbox;
-              qh_option("Qbound-dim-low", &k, &r);
-            }else {
-              qh SCALEinput= True;
-              if (r == 0.0)
-                r= qh_DEFAULTbox;
-              qh_option("QBound-dim-high", &k, &r);
-            }
-          }
-          break;
-        case 'c':
-          qh_option("Qcoplanar-keep", NULL, NULL);
-          qh KEEPcoplanar= True;
-          break;
-        case 'f':
-          qh_option("Qfurthest-outside", NULL, NULL);
-          qh BESToutside= True;
-          break;
-        case 'g':
-          qh_option("Qgood-facets-only", NULL, NULL);
-          qh ONLYgood= True;
-          break;
-        case 'i':
-          qh_option("Qinterior-keep", NULL, NULL);
-          qh KEEPinside= True;
-          break;
-        case 'm':
-          qh_option("Qmax-outside-only", NULL, NULL);
-          qh ONLYmax= True;
-          break;
-        case 'r':
-          qh_option("Qrandom-outside", NULL, NULL);
-          qh RANDOMoutside= True;
-          break;
-        case 's':
-          qh_option("Qsearch-initial-simplex", NULL, NULL);
-          qh ALLpoints= True;
-          break;
-        case 't':
-          qh_option("Qtriangulate", NULL, NULL);
-          qh TRIangulate= True;
-          break;
-        case 'T':
-          qh_option("QTestPoints", NULL, NULL);
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 6039, "qhull input error: missing number of test points for option 'QTn'\n");
-          else {
-            qh TESTpoints= qh_strtol(s, &s);
-            qh_option("QTestPoints", &qh TESTpoints, NULL);
-          }
-          break;
-        case 'u':
-          qh_option("QupperDelaunay", NULL, NULL);
-          qh UPPERdelaunay= True;
-          break;
-        case 'v':
-          qh_option("Qvertex-neighbors-convex", NULL, NULL);
-          qh TESTvneighbors= True;
-          break;
-        case 'x':
-          qh_option("Qxact-merge", NULL, NULL);
-          qh MERGEexact= True;
-          break;
-        case 'z':
-          qh_option("Qz-infinity-point", NULL, NULL);
-          qh ATinfinity= True;
-          break;
-        case '0':
-          qh_option("Q0-no-premerge", NULL, NULL);
-          qh NOpremerge= True;
-          break;
-        case '1':
-          if (!isdigit(*s)) {
-            qh_option("Q1-no-angle-sort", NULL, NULL);
-            qh ANGLEmerge= False;
-            break;
-          }
-          switch (*s++) {
-          case '0':
-            qh_option("Q10-no-narrow", NULL, NULL);
-            qh NOnarrow= True;
-            break;
-          case '1':
-            qh_option("Q11-trinormals Qtriangulate", NULL, NULL);
-            qh TRInormals= True;
-            qh TRIangulate= True;
-            break;
-          default:
-            s--;
-            qh_fprintf(qh ferr, 7016, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
-            while (*++s && !isspace(*s));
-            break;
-          }
-          break;
-        case '2':
-          qh_option("Q2-no-merge-independent", NULL, NULL);
-          qh MERGEindependent= False;
-          goto LABELcheckdigit;
-          break; /* no warnings */
-        case '3':
-          qh_option("Q3-no-merge-vertices", NULL, NULL);
-          qh MERGEvertices= False;
-        LABELcheckdigit:
-          if (isdigit(*s))
-            qh_fprintf(qh ferr, 7017, "qhull warning: can not follow '1', '2', or '3' with a digit.  '%c' skipped.\n",
-                     *s++);
-          break;
-        case '4':
-          qh_option("Q4-avoid-old-into-new", NULL, NULL);
-          qh AVOIDold= True;
-          break;
-        case '5':
-          qh_option("Q5-no-check-outer", NULL, NULL);
-          qh SKIPcheckmax= True;
-          break;
-        case '6':
-          qh_option("Q6-no-concave-merge", NULL, NULL);
-          qh SKIPconvex= True;
-          break;
-        case '7':
-          qh_option("Q7-no-breadth-first", NULL, NULL);
-          qh VIRTUALmemory= True;
-          break;
-        case '8':
-          qh_option("Q8-no-near-inside", NULL, NULL);
-          qh NOnearinside= True;
-          break;
-        case '9':
-          qh_option("Q9-pick-furthest", NULL, NULL);
-          qh PICKfurthest= True;
-          break;
-        case 'G':
-          i= qh_strtol(s, &t);
-          if (qh GOODpoint)
-            qh_fprintf(qh ferr, 7018, "qhull warning: good point already defined for option 'QGn'.  Ignored\n");
-          else if (s == t)
-            qh_fprintf(qh ferr, 7019, "qhull warning: missing good point id for option 'QGn'.  Ignored\n");
-          else if (i < 0 || *s == '-') {
-            qh GOODpoint= i-1;
-            qh_option("QGood-if-dont-see-point", &i, NULL);
-          }else {
-            qh GOODpoint= i+1;
-            qh_option("QGood-if-see-point", &i, NULL);
-          }
-          s= t;
-          break;
-        case 'J':
-          if (!isdigit(*s) && *s != '-')
-            qh JOGGLEmax= 0.0;
-          else {
-            qh JOGGLEmax= (realT) qh_strtod(s, &s);
-            qh_option("QJoggle", NULL, &qh JOGGLEmax);
-          }
-          break;
-        case 'R':
-          if (!isdigit(*s) && *s != '-')
-            qh_fprintf(qh ferr, 7020, "qhull warning: missing random seed for option 'QRn'.  Ignored\n");
-          else {
-            qh ROTATErandom= i= qh_strtol(s, &s);
-            if (i > 0)
-              qh_option("QRotate-id", &i, NULL );
-            else if (i < -1)
-              qh_option("QRandom-seed", &i, NULL );
-          }
-          break;
-        case 'V':
-          i= qh_strtol(s, &t);
-          if (qh GOODvertex)
-            qh_fprintf(qh ferr, 7021, "qhull warning: good vertex already defined for option 'QVn'.  Ignored\n");
-          else if (s == t)
-            qh_fprintf(qh ferr, 7022, "qhull warning: no good point id given for option 'QVn'.  Ignored\n");
-          else if (i < 0) {
-            qh GOODvertex= i - 1;
-            qh_option("QV-good-facets-not-point", &i, NULL);
-          }else {
-            qh_option("QV-good-facets-point", &i, NULL);
-            qh GOODvertex= i + 1;
-          }
-          s= t;
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7023, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    case 'T':
-      while (*s && !isspace(*s)) {
-        if (isdigit(*s) || *s == '-')
-          qh IStracing= qh_strtol(s, &s);
-        else switch (*s++) {
-        case 'a':
-          qh_option("Tannotate-output", NULL, NULL);
-          qh ANNOTATEoutput= True;
-          break;
-        case 'c':
-          qh_option("Tcheck-frequently", NULL, NULL);
-          qh CHECKfrequently= True;
-          break;
-        case 's':
-          qh_option("Tstatistics", NULL, NULL);
-          qh PRINTstatistics= True;
-          break;
-        case 'v':
-          qh_option("Tverify", NULL, NULL);
-          qh VERIFYoutput= True;
-          break;
-        case 'z':
-          if (qh ferr == qh_FILEstderr) {
-            /* The C++ interface captures the output in qh_fprint_qhull() */
-            qh_option("Tz-stdout", NULL, NULL);
-            qh USEstdout= True;
-          }else if (!qh fout)
-            qh_fprintf(qh ferr, 7024, "qhull warning: output file undefined(stdout).  Option 'Tz' ignored.\n");
-          else {
-            qh_option("Tz-stdout", NULL, NULL);
-            qh USEstdout= True;
-            qh ferr= qh fout;
-            qhmem.ferr= qh fout;
-          }
-          break;
-        case 'C':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7025, "qhull warning: missing point id for cone for trace option 'TCn'.  Ignored\n");
-          else {
-            i= qh_strtol(s, &s);
-            qh_option("TCone-stop", &i, NULL);
-            qh STOPcone= i + 1;
-          }
-          break;
-        case 'F':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7026, "qhull warning: missing frequency count for trace option 'TFn'.  Ignored\n");
-          else {
-            qh REPORTfreq= qh_strtol(s, &s);
-            qh_option("TFacet-log", &qh REPORTfreq, NULL);
-            qh REPORTfreq2= qh REPORTfreq/2;  /* for tracemerging() */
-          }
-          break;
-        case 'I':
-          if (!isspace(*s))
-            qh_fprintf(qh ferr, 7027, "qhull warning: missing space between 'TI' and filename, %s\n", s);
-          while (isspace(*s))
-            s++;
-          t= qh_skipfilename(s);
-          {
-            char filename[qh_FILENAMElen];
-
-            qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s));   /* WARN64 */
-            s= t;
-            if (!freopen(filename, "r", stdin)) {
-              qh_fprintf(qh ferr, 6041, "qhull error: could not open file \"%s\".", filename);
-              qh_errexit(qh_ERRinput, NULL, NULL);
-            }else {
-              qh_option("TInput-file", NULL, NULL);
-              qh_option(filename, NULL, NULL);
-            }
-          }
-          break;
-        case 'O':
-            if (!isspace(*s))
-                qh_fprintf(qh ferr, 7028, "qhull warning: missing space between 'TO' and filename, %s\n", s);
-            while (isspace(*s))
-                s++;
-            t= qh_skipfilename(s);
-            {
-              char filename[qh_FILENAMElen];
-
-              qh_copyfilename(filename, (int)sizeof(filename), s, (int)(t-s));  /* WARN64 */
-              s= t;
-              if (!freopen(filename, "w", stdout)) {
-                qh_fprintf(qh ferr, 6044, "qhull error: could not open file \"%s\".", filename);
-                qh_errexit(qh_ERRinput, NULL, NULL);
-              }else {
-                qh_option("TOutput-file", NULL, NULL);
-              qh_option(filename, NULL, NULL);
-            }
-          }
-          break;
-        case 'P':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7029, "qhull warning: missing point id for trace option 'TPn'.  Ignored\n");
-          else {
-            qh TRACEpoint= qh_strtol(s, &s);
-            qh_option("Trace-point", &qh TRACEpoint, NULL);
-          }
-          break;
-        case 'M':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7030, "qhull warning: missing merge id for trace option 'TMn'.  Ignored\n");
-          else {
-            qh TRACEmerge= qh_strtol(s, &s);
-            qh_option("Trace-merge", &qh TRACEmerge, NULL);
-          }
-          break;
-        case 'R':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7031, "qhull warning: missing rerun count for trace option 'TRn'.  Ignored\n");
-          else {
-            qh RERUN= qh_strtol(s, &s);
-            qh_option("TRerun", &qh RERUN, NULL);
-          }
-          break;
-        case 'V':
-          i= qh_strtol(s, &t);
-          if (s == t)
-            qh_fprintf(qh ferr, 7032, "qhull warning: missing furthest point id for trace option 'TVn'.  Ignored\n");
-          else if (i < 0) {
-            qh STOPpoint= i - 1;
-            qh_option("TV-stop-before-point", &i, NULL);
-          }else {
-            qh STOPpoint= i + 1;
-            qh_option("TV-stop-after-point", &i, NULL);
-          }
-          s= t;
-          break;
-        case 'W':
-          if (!isdigit(*s))
-            qh_fprintf(qh ferr, 7033, "qhull warning: missing max width for trace option 'TWn'.  Ignored\n");
-          else {
-            qh TRACEdist= (realT) qh_strtod(s, &s);
-            qh_option("TWide-trace", NULL, &qh TRACEdist);
-          }
-          break;
-        default:
-          s--;
-          qh_fprintf(qh ferr, 7034, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
-          while (*++s && !isspace(*s));
-          break;
-        }
-      }
-      break;
-    default:
-      qh_fprintf(qh ferr, 7035, "qhull warning: unknown flag %c(%x)\n", (int)s[-1],
-               (int)s[-1]);
-      break;
-    }
-    if (s-1 == prev_s && *s && !isspace(*s)) {
-      qh_fprintf(qh ferr, 7036, "qhull warning: missing space after flag %c(%x); reserved for menu. Skipped.\n",
-               (int)*prev_s, (int)*prev_s);
-      while (*s && !isspace(*s))
-        s++;
-    }
-  }
-  if (qh STOPcone && qh JOGGLEmax < REALmax/2)
-    qh_fprintf(qh ferr, 7078, "qhull warning: 'TCn' (stopCone) ignored when used with 'QJn' (joggle)\n");
-  if (isgeom && !qh FORCEoutput && qh PRINTout[1])
-    qh_fprintf(qh ferr, 7037, "qhull warning: additional output formats are not compatible with Geomview\n");
-  /* set derived values in qh_initqhull_globals */
-} /* initflags */
-
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="initqhull_buffers">-</a>
-
-  qh_initqhull_buffers()
-    initialize global memory buffers
-
-  notes:
-    must match qh_freebuffers()
-*/
-void qh_initqhull_buffers(void) {
-  int k;
-
-  qh TEMPsize= (qhmem.LASTsize - sizeof(setT))/SETelemsize;
-  if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
-    qh TEMPsize= 8;  /* e.g., if qh_NOmem */
-  qh other_points= qh_setnew(qh TEMPsize);
-  qh del_vertices= qh_setnew(qh TEMPsize);
-  qh coplanarfacetset= qh_setnew(qh TEMPsize);
-  qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
-  qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
-  for (k=qh input_dim+1; k--; ) {  /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
-    qh lower_threshold[k]= -REALmax;
-    qh upper_threshold[k]= REALmax;
-    qh lower_bound[k]= -REALmax;
-    qh upper_bound[k]= REALmax;
-  }
-  qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
-  qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
-} /* initqhull_buffers */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="initqhull_globals">-</a>
-
-  qh_initqhull_globals( points, numpoints, dim, ismalloc )
-    initialize globals
-    if ismalloc
-      points were malloc'd and qhull should free at end
-
-  returns:
-    sets qh.first_point, num_points, input_dim, hull_dim and others
-    seeds random number generator (seed=1 if tracing)
-    modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
-    adjust user flags as needed
-    also checks DIM3 dependencies and constants
-
-  notes:
-    do not use qh_point() since an input transformation may move them elsewhere
-
-  see:
-    qh_initqhull_start() sets default values for non-zero globals
-
-  design:
-    initialize points array from input arguments
-    test for qh.ZEROcentrum
-      (i.e., use opposite vertex instead of centrum for convexity testing)
-    initialize qh.CENTERtype, qh.normal_size,
-      qh.center_size, qh.TRACEpoint/level,
-    initialize and test random numbers
-    qh_initqhull_outputflags() -- adjust and test output flags
-*/
-void qh_initqhull_globals(coordT *points, int numpoints, int dim, boolT ismalloc) {
-  int seed, pointsneeded, extra= 0, i, randi, k;
-  realT randr;
-  realT factorial;
-
-  time_t timedata;
-
-  trace0((qh ferr, 13, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
-      qh qhull_command));
-  qh POINTSmalloc= ismalloc;
-  qh first_point= points;
-  qh num_points= numpoints;
-  qh hull_dim= qh input_dim= dim;
-  if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
-    qh MERGING= True;
-    if (qh hull_dim <= 4) {
-      qh PREmerge= True;
-      qh_option("_pre-merge", NULL, NULL);
-    }else {
-      qh MERGEexact= True;
-      qh_option("Qxact_merge", NULL, NULL);
-    }
-  }else if (qh MERGEexact)
-    qh MERGING= True;
-  if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
-#ifdef qh_NOmerge
-    qh JOGGLEmax= 0.0;
-#endif
-  }
-  if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
-    qh_fprintf(qh ferr, 7038, "qhull warning: joggle('QJ') always produces simplicial output.  Triangulated output('Qt') does nothing.\n");
-  if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
-    qh SCALElast= True;
-    qh_option("Qbbound-last-qj", NULL, NULL);
-  }
-  if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
-  && qh premerge_centrum == 0) {
-    qh ZEROcentrum= True;
-    qh ZEROall_ok= True;
-    qh_option("_zero-centrum", NULL, NULL);
-  }
-  if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
-    qh_fprintf(qh ferr, 7039, "qhull warning: real epsilon, %2.2g, is probably too large for joggle('QJn')\nRecompile with double precision reals(see user.h).\n",
-          REALepsilon);
-#ifdef qh_NOmerge
-  if (qh MERGING) {
-    qh_fprintf(qh ferr, 6045, "qhull input error: merging not installed(qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-#endif
-  if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
-    qh KEEPinside= True;
-    qh_option("Qinterior-keep", NULL, NULL);
-  }
-  if (qh DELAUNAY && qh HALFspace) {
-    qh_fprintf(qh ferr, 6046, "qhull input error: can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
-    qh_fprintf(qh ferr, 6047, "qhull input error: use upper-Delaunay('Qu') or infinity-point('Qz') with Delaunay('d') or Voronoi('v')\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh UPPERdelaunay && qh ATinfinity) {
-    qh_fprintf(qh ferr, 6048, "qhull input error: can not use infinity-point('Qz') with upper-Delaunay('Qu')\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
-    qh_fprintf(qh ferr, 7040, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
-  qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
-  qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar)
-                          && !qh NOnearinside);
-  if (qh MERGING)
-    qh CENTERtype= qh_AScentrum;
-  else if (qh VORONOI)
-    qh CENTERtype= qh_ASvoronoi;
-  if (qh TESTvneighbors && !qh MERGING) {
-    qh_fprintf(qh ferr, 6049, "qhull input error: test vertex neighbors('Qv') needs a merge option\n");
-    qh_errexit(qh_ERRinput, NULL ,NULL);
-  }
-  if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
-    qh hull_dim -= qh PROJECTinput;
-    if (qh DELAUNAY) {
-      qh hull_dim++;
-      if (qh ATinfinity)
-        extra= 1;
-    }
-  }
-  if (qh hull_dim <= 1) {
-    qh_fprintf(qh ferr, 6050, "qhull error: dimension %d must be > 1\n", qh hull_dim);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  for (k=2, factorial=1.0; k < qh hull_dim; k++)
-    factorial *= k;
-  qh AREAfactor= 1.0 / factorial;
-  trace2((qh ferr, 2005, "qh_initqhull_globals: initialize globals.  dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
-        dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
-  qh normal_size= qh hull_dim * sizeof(coordT);
-  qh center_size= qh normal_size - sizeof(coordT);
-  pointsneeded= qh hull_dim+1;
-  if (qh hull_dim > qh_DIMmergeVertex) {
-    qh MERGEvertices= False;
-    qh_option("Q3-no-merge-vertices-dim-high", NULL, NULL);
-  }
-  if (qh GOODpoint)
-    pointsneeded++;
-#ifdef qh_NOtrace
-  if (qh IStracing) {
-    qh_fprintf(qh ferr, 6051, "qhull input error: tracing is not installed(qh_NOtrace in user.h)");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-#endif
-  if (qh RERUN > 1) {
-    qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
-    if (qh IStracing != -1)
-      qh IStracing= 0;
-  }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
-    qh TRACElevel= (qh IStracing? qh IStracing : 3);
-    qh IStracing= 0;
-  }
-  if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
-    seed= (int)time(&timedata);
-    if (qh ROTATErandom  == -1) {
-      seed= -seed;
-      qh_option("QRandom-seed", &seed, NULL );
-    }else
-      qh_option("QRotate-random", &seed, NULL);
-    qh ROTATErandom= seed;
-  }
-  seed= qh ROTATErandom;
-  if (seed == INT_MIN)    /* default value */
-    seed= 1;
-  else if (seed < 0)
-    seed= -seed;
-  qh_RANDOMseed_(seed);
-  randr= 0.0;
-  for (i=1000; i--; ) {
-    randi= qh_RANDOMint;
-    randr += randi;
-    if (randi > qh_RANDOMmax) {
-      qh_fprintf(qh ferr, 8036, "\
-qhull configuration error (qh_RANDOMmax in user.h):\n\
-   random integer %d > qh_RANDOMmax(%.8g)\n",
-               randi, qh_RANDOMmax);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-  }
-  qh_RANDOMseed_(seed);
-  randr = randr/1000;
-  if (randr < qh_RANDOMmax * 0.1
-  || randr > qh_RANDOMmax * 0.9)
-    qh_fprintf(qh ferr, 8037, "\
-qhull configuration warning (qh_RANDOMmax in user.h):\n\
-   average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
-   Is qh_RANDOMmax (%.2g) wrong?\n",
-             randr, qh_RANDOMmax * 0.5, qh_RANDOMmax);
-  qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
-  qh RANDOMb= 1.0 - qh RANDOMfactor;
-  if (qh_HASHfactor < 1.1) {
-    qh_fprintf(qh ferr, 6052, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1.  Qhull uses linear hash probing\n",
-      qh_HASHfactor);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (numpoints+extra < pointsneeded) {
-    qh_fprintf(qh ferr, 6214, "qhull input error: not enough points(%d) to construct initial simplex (need %d)\n",
-            numpoints, pointsneeded);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  qh_initqhull_outputflags();
-} /* initqhull_globals */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="initqhull_mem">-</a>
-
-  qh_initqhull_mem(  )
-    initialize mem.c for qhull
-    qh.hull_dim and qh.normal_size determine some of the allocation sizes
-    if qh.MERGING,
-      includes ridgeT
-    calls qh_user_memsizes() to add up to 10 additional sizes for quick allocation
-      (see numsizes below)
-
-  returns:
-    mem.c already for qh_memalloc/qh_memfree (errors if called beforehand)
-
-  notes:
-    qh_produceoutput() prints memsizes
-
-*/
-void qh_initqhull_mem(void) {
-  int numsizes;
-  int i;
-
-  numsizes= 8+10;
-  qh_meminitbuffers(qh IStracing, qh_MEMalign, numsizes,
-                     qh_MEMbufsize,qh_MEMinitbuf);
-  qh_memsize((int)sizeof(vertexT));
-  if (qh MERGING) {
-    qh_memsize((int)sizeof(ridgeT));
-    qh_memsize((int)sizeof(mergeT));
-  }
-  qh_memsize((int)sizeof(facetT));
-  i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;  /* ridge.vertices */
-  qh_memsize(i);
-  qh_memsize(qh normal_size);        /* normal */
-  i += SETelemsize;                 /* facet.vertices, .ridges, .neighbors */
-  qh_memsize(i);
-  qh_user_memsizes();
-  qh_memsetup();
-} /* initqhull_mem */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="initqhull_outputflags">-</a>
-
-  qh_initqhull_outputflags
-    initialize flags concerned with output
-
-  returns:
-    adjust user flags as needed
-
-  see:
-    qh_clear_outputflags() resets the flags
-
-  design:
-    test for qh.PRINTgood (i.e., only print 'good' facets)
-    check for conflicting print output options
-*/
-void qh_initqhull_outputflags(void) {
-  boolT printgeom= False, printmath= False, printcoplanar= False;
-  int i;
-
-  trace3((qh ferr, 3024, "qh_initqhull_outputflags: %s\n", qh qhull_command));
-  if (!(qh PRINTgood || qh PRINTneighbors)) {
-    if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
-        || (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
-      qh PRINTgood= True;
-      qh_option("Pgood", NULL, NULL);
-    }
-  }
-  if (qh PRINTtransparent) {
-    if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
-      qh_fprintf(qh ferr, 6215, "qhull input error: transparent Delaunay('Gt') needs 3-d Delaunay('d') w/o 'GDn'\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    qh DROPdim = 3;
-    qh PRINTridges = True;
-  }
-  for (i=qh_PRINTEND; i--; ) {
-    if (qh PRINTout[i] == qh_PRINTgeom)
-      printgeom= True;
-    else if (qh PRINTout[i] == qh_PRINTmathematica || qh PRINTout[i] == qh_PRINTmaple)
-      printmath= True;
-    else if (qh PRINTout[i] == qh_PRINTcoplanars)
-      printcoplanar= True;
-    else if (qh PRINTout[i] == qh_PRINTpointnearest)
-      printcoplanar= True;
-    else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
-      qh_fprintf(qh ferr, 6053, "qhull input error: option 'Fp' is only used for \nhalfspace intersection('Hn,n,n').\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
-      qh_fprintf(qh ferr, 6054, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
-      qh_fprintf(qh ferr, 6055, "qhull input error: option 'FC' is not available for Voronoi vertices('v')\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }else if (qh PRINTout[i] == qh_PRINTvertices) {
-      if (qh VORONOI)
-        qh_option("Fvoronoi", NULL, NULL);
-      else
-        qh_option("Fvertices", NULL, NULL);
-    }
-  }
-  if (printcoplanar && qh DELAUNAY && qh JOGGLEmax < REALmax/2) {
-    if (qh PRINTprecision)
-      qh_fprintf(qh ferr, 7041, "qhull input warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
-  }
-  if (printmath && (qh hull_dim > 3 || qh VORONOI)) {
-    qh_fprintf(qh ferr, 6056, "qhull input error: Mathematica and Maple output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (printgeom) {
-    if (qh hull_dim > 4) {
-      qh_fprintf(qh ferr, 6057, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
-     + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
-      qh_fprintf(qh ferr, 6058, "qhull input error: no output specified for Geomview\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
-      qh_fprintf(qh ferr, 6059, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    /* can not warn about furthest-site Geomview output: no lower_threshold */
-    if (qh hull_dim == 4 && qh DROPdim == -1 &&
-        (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
-      qh_fprintf(qh ferr, 7042, "qhull input warning: coplanars, vertices, and centrums output not\n\
-available for 4-d output(ignored).  Could use 'GDn' instead.\n");
-      qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
-    }
-  }
-  if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
-    if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar) {
-      if (qh QHULLfinished) {
-        qh_fprintf(qh ferr, 7072, "qhull output warning: ignoring coplanar points, option 'Qc' was not set for the first run of qhull.\n");
-      }else {
-        qh KEEPcoplanar = True;
-        qh_option("Qcoplanar", NULL, NULL);
-      }
-    }
-  }
-  qh PRINTdim= qh hull_dim;
-  if (qh DROPdim >=0) {    /* after Geomview checks */
-    if (qh DROPdim < qh hull_dim) {
-      qh PRINTdim--;
-      if (!printgeom || qh hull_dim < 3)
-        qh_fprintf(qh ferr, 7043, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
-    }else
-      qh DROPdim= -1;
-  }else if (qh VORONOI) {
-    qh DROPdim= qh hull_dim-1;
-    qh PRINTdim= qh hull_dim-1;
-  }
-} /* qh_initqhull_outputflags */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="initqhull_start">-</a>
-
-  qh_initqhull_start( infile, outfile, errfile )
-    allocate memory if needed and call qh_initqhull_start2()
-*/
-void qh_initqhull_start(FILE *infile, FILE *outfile, FILE *errfile) {
-
-#if qh_QHpointer
-  if (qh_qh) {
-    qh_fprintf(errfile, 6205, "qhull error (qh_initqhull_start): qh_qh already defined.  Call qh_save_qhull() first\n");
-    qh_exit(qh_ERRqhull);  /* no error handler */
-  }
-  if (!(qh_qh= (qhT *)qh_malloc(sizeof(qhT)))) {
-    qh_fprintf(errfile, 6060, "qhull error (qh_initqhull_start): insufficient memory\n");
-    qh_exit(qh_ERRmem);  /* no error handler */
-  }
-#endif
-  qh_initstatistics();
-  qh_initqhull_start2(infile, outfile, errfile);
-} /* initqhull_start */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="initqhull_start2">-</a>
-
-  qh_initqhull_start2( infile, outfile, errfile )
-    start initialization of qhull
-    initialize statistics, stdio, default values for global variables
-    assumes qh_qh is defined
-  notes:
-    report errors elsewhere, error handling and g_qhull_output [Qhull.cpp, QhullQh()] not in initialized
-  see:
-    qh_maxmin() determines the precision constants
-    qh_freeqhull2()
-*/
-void qh_initqhull_start2(FILE *infile, FILE *outfile, FILE *errfile) {
-  time_t timedata;
-  int seed;
-
-  qh_CPUclock; /* start the clock(for qh_clock).  One-shot. */
-#if qh_QHpointer
-  memset((char *)qh_qh, 0, sizeof(qhT));   /* every field is 0, FALSE, NULL */
-#else
-  memset((char *)&qh_qh, 0, sizeof(qhT));
-#endif
-  qh ANGLEmerge= True;
-  qh DROPdim= -1;
-  qh ferr= errfile;
-  qh fin= infile;
-  qh fout= outfile;
-  qh furthest_id= -1;
-  qh JOGGLEmax= REALmax;
-  qh KEEPminArea = REALmax;
-  qh last_low= REALmax;
-  qh last_high= REALmax;
-  qh last_newhigh= REALmax;
-  qh max_outside= 0.0;
-  qh max_vertex= 0.0;
-  qh MAXabs_coord= 0.0;
-  qh MAXsumcoord= 0.0;
-  qh MAXwidth= -REALmax;
-  qh MERGEindependent= True;
-  qh MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
-  qh MINoutside= 0.0;
-  qh MINvisible= REALmax;
-  qh MAXcoplanar= REALmax;
-  qh outside_err= REALmax;
-  qh premerge_centrum= 0.0;
-  qh premerge_cos= REALmax;
-  qh PRINTprecision= True;
-  qh PRINTradius= 0.0;
-  qh postmerge_cos= REALmax;
-  qh postmerge_centrum= 0.0;
-  qh ROTATErandom= INT_MIN;
-  qh MERGEvertices= True;
-  qh totarea= 0.0;
-  qh totvol= 0.0;
-  qh TRACEdist= REALmax;
-  qh TRACEpoint= -1; /* recompile or use 'TPn' */
-  qh tracefacet_id= UINT_MAX;  /* recompile to trace a facet */
-  qh tracevertex_id= UINT_MAX; /* recompile to trace a vertex */
-  seed= (int)time(&timedata);
-  qh_RANDOMseed_(seed);
-  qh run_id= qh_RANDOMint+1; /* disallow 0 [UsingLibQhull::NOqhRunId] */
-  qh_option("run-id", &qh run_id, NULL);
-  strcat(qh qhull, "qhull");
-} /* initqhull_start2 */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="initthresholds">-</a>
-
-  qh_initthresholds( commandString )
-    set thresholds for printing and scaling from commandString
-
-  returns:
-    sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
-
-  see:
-    qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
-    qh_inthresholds()
-
-  design:
-    for each 'Pdn' or 'PDn' option
-      check syntax
-      set qh.lower_threshold or qh.upper_threshold
-    set qh.GOODthreshold if an unbounded threshold is used
-    set qh.SPLITthreshold if a bounded threshold is used
-*/
-void qh_initthresholds(char *command) {
-  realT value;
-  int idx, maxdim, k;
-  char *s= command; /* non-const due to strtol */
-  char key;
-
-  maxdim= qh input_dim;
-  if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
-    maxdim++;
-  while (*s) {
-    if (*s == '-')
-      s++;
-    if (*s == 'P') {
-      s++;
-      while (*s && !isspace(key= *s++)) {
-        if (key == 'd' || key == 'D') {
-          if (!isdigit(*s)) {
-            qh_fprintf(qh ferr, 7044, "qhull warning: no dimension given for Print option '%c' at: %s.  Ignored\n",
-                    key, s-1);
-            continue;
-          }
-          idx= qh_strtol(s, &s);
-          if (idx >= qh hull_dim) {
-            qh_fprintf(qh ferr, 7045, "qhull warning: dimension %d for Print option '%c' is >= %d.  Ignored\n",
-                idx, key, qh hull_dim);
-            continue;
-          }
-          if (*s == ':') {
-            s++;
-            value= qh_strtod(s, &s);
-            if (fabs((double)value) > 1.0) {
-              qh_fprintf(qh ferr, 7046, "qhull warning: value %2.4g for Print option %c is > +1 or < -1.  Ignored\n",
-                      value, key);
-              continue;
-            }
-          }else
-            value= 0.0;
-          if (key == 'd')
-            qh lower_threshold[idx]= value;
-          else
-            qh upper_threshold[idx]= value;
-        }
-      }
-    }else if (*s == 'Q') {
-      s++;
-      while (*s && !isspace(key= *s++)) {
-        if (key == 'b' && *s == 'B') {
-          s++;
-          for (k=maxdim; k--; ) {
-            qh lower_bound[k]= -qh_DEFAULTbox;
-            qh upper_bound[k]= qh_DEFAULTbox;
-          }
-        }else if (key == 'b' && *s == 'b')
-          s++;
-        else if (key == 'b' || key == 'B') {
-          if (!isdigit(*s)) {
-            qh_fprintf(qh ferr, 7047, "qhull warning: no dimension given for Qhull option %c.  Ignored\n",
-                    key);
-            continue;
-          }
-          idx= qh_strtol(s, &s);
-          if (idx >= maxdim) {
-            qh_fprintf(qh ferr, 7048, "qhull warning: dimension %d for Qhull option %c is >= %d.  Ignored\n",
-                idx, key, maxdim);
-            continue;
-          }
-          if (*s == ':') {
-            s++;
-            value= qh_strtod(s, &s);
-          }else if (key == 'b')
-            value= -qh_DEFAULTbox;
-          else
-            value= qh_DEFAULTbox;
-          if (key == 'b')
-            qh lower_bound[idx]= value;
-          else
-            qh upper_bound[idx]= value;
-        }
-      }
-    }else {
-      while (*s && !isspace(*s))
-        s++;
-    }
-    while (isspace(*s))
-      s++;
-  }
-  for (k=qh hull_dim; k--; ) {
-    if (qh lower_threshold[k] > -REALmax/2) {
-      qh GOODthreshold= True;
-      if (qh upper_threshold[k] < REALmax/2) {
-        qh SPLITthresholds= True;
-        qh GOODthreshold= False;
-        break;
-      }
-    }else if (qh upper_threshold[k] < REALmax/2)
-      qh GOODthreshold= True;
-  }
-} /* initthresholds */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="option">-</a>
-
-  qh_option( option, intVal, realVal )
-    add an option description to qh.qhull_options
-
-  notes:
-    NOerrors -- qh_option can not call qh_errexit() [qh_initqhull_start2]
-    will be printed with statistics ('Ts') and errors
-    strlen(option) < 40
-*/
-void qh_option(const char *option, int *i, realT *r) {
-  char buf[200];
-  int len, maxlen;
-
-  sprintf(buf, "  %s", option);
-  if (i)
-    sprintf(buf+strlen(buf), " %d", *i);
-  if (r)
-    sprintf(buf+strlen(buf), " %2.2g", *r);
-  len= (int)strlen(buf);  /* WARN64 */
-  qh qhull_optionlen += len;
-  maxlen= sizeof(qh qhull_options) - len -1;
-  maximize_(maxlen, 0);
-  if (qh qhull_optionlen >= qh_OPTIONline && maxlen > 0) {
-    qh qhull_optionlen= len;
-    strncat(qh qhull_options, "\n", (size_t)(maxlen--));
-  }
-  strncat(qh qhull_options, buf, (size_t)maxlen);
-} /* option */
-
-#if qh_QHpointer
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="restore_qhull">-</a>
-
-  qh_restore_qhull( oldqh )
-    restores a previously saved qhull
-    also restores qh_qhstat and qhmem.tempstack
-    Sets *oldqh to NULL
-  notes:
-    errors if current qhull hasn't been saved or freed
-    uses qhmem for error reporting
-
-  NOTE 1998/5/11:
-    Freeing memory after qh_save_qhull and qh_restore_qhull
-    is complicated.  The procedures will be redesigned.
-
-  see:
-    qh_save_qhull(), UsingLibQhull
-*/
-void qh_restore_qhull(qhT **oldqh) {
-
-  if (*oldqh && strcmp((*oldqh)->qhull, "qhull")) {
-    qh_fprintf(qhmem.ferr, 6061, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
-                  *oldqh);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (qh_qh) {
-    qh_fprintf(qhmem.ferr, 6062, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (!*oldqh || !(*oldqh)->old_qhstat) {
-    qh_fprintf(qhmem.ferr, 6063, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
-                  *oldqh);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  qh_qh= *oldqh;
-  *oldqh= NULL;
-  qh_qhstat= qh old_qhstat;
-  qhmem.tempstack= qh old_tempstack;
-  qh old_qhstat= 0;
-  qh old_tempstack= 0;
-  trace1((qh ferr, 1007, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
-} /* restore_qhull */
-
-/*-<a                             href="qh-globa.htm#TOC"
-  >-------------------------------</a><a name="save_qhull">-</a>
-
-  qh_save_qhull(  )
-    saves qhull for a later qh_restore_qhull
-    also saves qh_qhstat and qhmem.tempstack
-
-  returns:
-    qh_qh=NULL
-
-  notes:
-    need to initialize qhull or call qh_restore_qhull before continuing
-
-  NOTE 1998/5/11:
-    Freeing memory after qh_save_qhull and qh_restore_qhull
-    is complicated.  The procedures will be redesigned.
-
-  see:
-    qh_restore_qhull()
-*/
-qhT *qh_save_qhull(void) {
-  qhT *oldqh;
-
-  trace1((qhmem.ferr, 1045, "qh_save_qhull: save qhull %p\n", qh_qh));
-  if (!qh_qh) {
-    qh_fprintf(qhmem.ferr, 6064, "qhull internal error (qh_save_qhull): qhull not initialized\n");
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  qh old_qhstat= qh_qhstat;
-  qh_qhstat= NULL;
-  qh old_tempstack= qhmem.tempstack;
-  qhmem.tempstack= NULL;
-  oldqh= qh_qh;
-  qh_qh= NULL;
-  return oldqh;
-} /* save_qhull */
-
-#endif
diff --git a/alg/libqhull/io.c b/alg/libqhull/io.c
deleted file mode 100644
index 752ab73..0000000
--- a/alg/libqhull/io.c
+++ /dev/null
@@ -1,4060 +0,0 @@
-/*<html><pre>  -<a                             href="qh-io.htm"
-  >-------------------------------</a><a name="TOP">-</a>
-
-   io.c
-   Input/Output routines of qhull application
-
-   see qh-io.htm and io.h
-
-   see user.c for qh_errprint and qh_printfacetlist
-
-   unix.c calls qh_readpoints and qh_produce_output
-
-   unix.c and user.c are the only callers of io.c functions
-   This allows the user to avoid loading io.o from qhull.a
-
-   Copyright (c) 1993-2012 The Geometry Center.
-   $Id: //main/2011/qhull/src/libqhull/io.c#3 $$Change: 1464 $
-   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*========= -functions in alphabetical order after qh_produce_output()  =====*/
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="produce_output">-</a>
-
-  qh_produce_output()
-  qh_produce_output2()
-    prints out the result of qhull in desired format
-    qh_produce_output2() does not call qh_prepare_output()
-    if qh.GETarea
-      computes and prints area and volume
-    qh.PRINTout[] is an array of output formats
-
-  notes:
-    prints output in qh.PRINTout order
-*/
-void qh_produce_output(void) {
-    int tempsize= qh_setsize(qhmem.tempstack);
-
-    qh_prepare_output();
-    qh_produce_output2();
-    if (qh_setsize(qhmem.tempstack) != tempsize) {
-        qh_fprintf(qh ferr, 6206, "qhull internal error (qh_produce_output): temporary sets not empty(%d)\n",
-            qh_setsize(qhmem.tempstack));
-        qh_errexit(qh_ERRqhull, NULL, NULL);
-    }
-} /* produce_output */
-
-
-void qh_produce_output2(void) {
-  int i, tempsize= qh_setsize(qhmem.tempstack), d_1;
-
-  if (qh PRINTsummary)
-    qh_printsummary(qh ferr);
-  else if (qh PRINTout[0] == qh_PRINTnone)
-    qh_printsummary(qh fout);
-  for (i=0; i < qh_PRINTEND; i++)
-    qh_printfacets(qh fout, qh PRINTout[i], qh facet_list, NULL, !qh_ALL);
-  qh_allstatistics();
-  if (qh PRINTprecision && !qh MERGING && (qh JOGGLEmax > REALmax/2 || qh RERUN))
-    qh_printstats(qh ferr, qhstat precision, NULL);
-  if (qh VERIFYoutput && (zzval_(Zridge) > 0 || zzval_(Zridgemid) > 0))
-    qh_printstats(qh ferr, qhstat vridges, NULL);
-  if (qh PRINTstatistics) {
-    qh_printstatistics(qh ferr, "");
-    qh_memstatistics(qh ferr);
-    d_1= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;
-    qh_fprintf(qh ferr, 8040, "\
-    size in bytes: merge %d ridge %d vertex %d facet %d\n\
-         normal %d ridge vertices %d facet vertices or neighbors %d\n",
-            (int)sizeof(mergeT), (int)sizeof(ridgeT),
-            (int)sizeof(vertexT), (int)sizeof(facetT),
-            qh normal_size, d_1, d_1 + SETelemsize);
-  }
-  if (qh_setsize(qhmem.tempstack) != tempsize) {
-    qh_fprintf(qh ferr, 6065, "qhull internal error (qh_produce_output2): temporary sets not empty(%d)\n",
-             qh_setsize(qhmem.tempstack));
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-} /* produce_output2 */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="dfacet">-</a>
-
-  dfacet( id )
-    print facet by id, for debugging
-
-*/
-void dfacet(unsigned id) {
-  facetT *facet;
-
-  FORALLfacets {
-    if (facet->id == id) {
-      qh_printfacet(qh fout, facet);
-      break;
-    }
-  }
-} /* dfacet */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="dvertex">-</a>
-
-  dvertex( id )
-    print vertex by id, for debugging
-*/
-void dvertex(unsigned id) {
-  vertexT *vertex;
-
-  FORALLvertices {
-    if (vertex->id == id) {
-      qh_printvertex(qh fout, vertex);
-      break;
-    }
-  }
-} /* dvertex */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="compare_vertexpoint">-</a>
-
-  qh_compare_vertexpoint( p1, p2 )
-    used by qsort() to order vertices by point id
-*/
-int qh_compare_vertexpoint(const void *p1, const void *p2) {
-  const vertexT *a= *((vertexT *const*)p1), *b= *((vertexT *const*)p2);
-
-  return((qh_pointid(a->point) > qh_pointid(b->point)?1:-1));
-} /* compare_vertexpoint */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="compare_facetarea">-</a>
-
-  qh_compare_facetarea( p1, p2 )
-    used by qsort() to order facets by area
-*/
-int qh_compare_facetarea(const void *p1, const void *p2) {
-  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
-
-  if (!a->isarea)
-    return -1;
-  if (!b->isarea)
-    return 1;
-  if (a->f.area > b->f.area)
-    return 1;
-  else if (a->f.area == b->f.area)
-    return 0;
-  return -1;
-} /* compare_facetarea */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="compare_facetmerge">-</a>
-
-  qh_compare_facetmerge( p1, p2 )
-    used by qsort() to order facets by number of merges
-*/
-int qh_compare_facetmerge(const void *p1, const void *p2) {
-  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
-
-  return(a->nummerge - b->nummerge);
-} /* compare_facetvisit */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="compare_facetvisit">-</a>
-
-  qh_compare_facetvisit( p1, p2 )
-    used by qsort() to order facets by visit id or id
-*/
-int qh_compare_facetvisit(const void *p1, const void *p2) {
-  const facetT *a= *((facetT *const*)p1), *b= *((facetT *const*)p2);
-  int i,j;
-
-  if (!(i= a->visitid))
-    i= 0 - a->id; /* do not convert to int, sign distinguishes id from visitid */
-  if (!(j= b->visitid))
-    j= 0 - b->id;
-  return(i - j);
-} /* compare_facetvisit */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="copyfilename">-</a>
-
-  qh_copyfilename( dest, size, source, length )
-    copy filename identified by qh_skipfilename()
-
-  notes:
-    see qh_skipfilename() for syntax
-*/
-void qh_copyfilename(char *filename, int size, const char* source, int length) {
-  char c= *source;
-
-  if (length > size + 1) {
-      qh_fprintf(qh ferr, 6040, "qhull error: filename is more than %d characters, %s\n",  size-1, source);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  strncpy(filename, source, length);
-  filename[length]= '\0';
-  if (c == '\'' || c == '"') {
-    char *s= filename + 1;
-    char *t= filename;
-    while (*s) {
-      if (*s == c) {
-          if (s[-1] == '\\')
-              t[-1]= c;
-      }else
-          *t++= *s;
-      s++;
-    }
-    *t= '\0';
-  }
-} /* copyfilename */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="countfacets">-</a>
-
-  qh_countfacets( facetlist, facets, printall,
-          numfacets, numsimplicial, totneighbors, numridges, numcoplanar, numtricoplanars  )
-    count good facets for printing and set visitid
-    if allfacets, ignores qh_skipfacet()
-
-  notes:
-    qh_printsummary and qh_countfacets must match counts
-
-  returns:
-    numfacets, numsimplicial, total neighbors, numridges, coplanars
-    each facet with ->visitid indicating 1-relative position
-      ->visitid==0 indicates not good
-
-  notes
-    numfacets >= numsimplicial
-    if qh.NEWfacets,
-      does not count visible facets (matches qh_printafacet)
-
-  design:
-    for all facets on facetlist and in facets set
-      unless facet is skipped or visible (i.e., will be deleted)
-        mark facet->visitid
-        update counts
-*/
-void qh_countfacets(facetT *facetlist, setT *facets, boolT printall,
-    int *numfacetsp, int *numsimplicialp, int *totneighborsp, int *numridgesp, int *numcoplanarsp, int *numtricoplanarsp) {
-  facetT *facet, **facetp;
-  int numfacets= 0, numsimplicial= 0, numridges= 0, totneighbors= 0, numcoplanars= 0, numtricoplanars= 0;
-
-  FORALLfacet_(facetlist) {
-    if ((facet->visible && qh NEWfacets)
-    || (!printall && qh_skipfacet(facet)))
-      facet->visitid= 0;
-    else {
-      facet->visitid= ++numfacets;
-      totneighbors += qh_setsize(facet->neighbors);
-      if (facet->simplicial) {
-        numsimplicial++;
-        if (facet->keepcentrum && facet->tricoplanar)
-          numtricoplanars++;
-      }else
-        numridges += qh_setsize(facet->ridges);
-      if (facet->coplanarset)
-        numcoplanars += qh_setsize(facet->coplanarset);
-    }
-  }
-
-  FOREACHfacet_(facets) {
-    if ((facet->visible && qh NEWfacets)
-    || (!printall && qh_skipfacet(facet)))
-      facet->visitid= 0;
-    else {
-      facet->visitid= ++numfacets;
-      totneighbors += qh_setsize(facet->neighbors);
-      if (facet->simplicial){
-        numsimplicial++;
-        if (facet->keepcentrum && facet->tricoplanar)
-          numtricoplanars++;
-      }else
-        numridges += qh_setsize(facet->ridges);
-      if (facet->coplanarset)
-        numcoplanars += qh_setsize(facet->coplanarset);
-    }
-  }
-  qh visit_id += numfacets+1;
-  *numfacetsp= numfacets;
-  *numsimplicialp= numsimplicial;
-  *totneighborsp= totneighbors;
-  *numridgesp= numridges;
-  *numcoplanarsp= numcoplanars;
-  *numtricoplanarsp= numtricoplanars;
-} /* countfacets */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="detvnorm">-</a>
-
-  qh_detvnorm( vertex, vertexA, centers, offset )
-    compute separating plane of the Voronoi diagram for a pair of input sites
-    centers= set of facets (i.e., Voronoi vertices)
-      facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
-
-  assumes:
-    qh_ASvoronoi and qh_vertexneighbors() already set
-
-  returns:
-    norm
-      a pointer into qh.gm_matrix to qh.hull_dim-1 reals
-      copy the data before reusing qh.gm_matrix
-    offset
-      if 'QVn'
-        sign adjusted so that qh.GOODvertexp is inside
-      else
-        sign adjusted so that vertex is inside
-
-    qh.gm_matrix= simplex of points from centers relative to first center
-
-  notes:
-    in io.c so that code for 'v Tv' can be removed by removing io.c
-    returns pointer into qh.gm_matrix to avoid tracking of temporary memory
-
-  design:
-    determine midpoint of input sites
-    build points as the set of Voronoi vertices
-    select a simplex from points (if necessary)
-      include midpoint if the Voronoi region is unbounded
-    relocate the first vertex of the simplex to the origin
-    compute the normalized hyperplane through the simplex
-    orient the hyperplane toward 'QVn' or 'vertex'
-    if 'Tv' or 'Ts'
-      if bounded
-        test that hyperplane is the perpendicular bisector of the input sites
-      test that Voronoi vertices not in the simplex are still on the hyperplane
-    free up temporary memory
-*/
-pointT *qh_detvnorm(vertexT *vertex, vertexT *vertexA, setT *centers, realT *offsetp) {
-  facetT *facet, **facetp;
-  int  i, k, pointid, pointidA, point_i, point_n;
-  setT *simplex= NULL;
-  pointT *point, **pointp, *point0, *midpoint, *normal, *inpoint;
-  coordT *coord, *gmcoord, *normalp;
-  setT *points= qh_settemp(qh TEMPsize);
-  boolT nearzero= False;
-  boolT unbounded= False;
-  int numcenters= 0;
-  int dim= qh hull_dim - 1;
-  realT dist, offset, angle, zero= 0.0;
-
-  midpoint= qh gm_matrix + qh hull_dim * qh hull_dim;  /* last row */
-  for (k=0; k < dim; k++)
-    midpoint[k]= (vertex->point[k] + vertexA->point[k])/2;
-  FOREACHfacet_(centers) {
-    numcenters++;
-    if (!facet->visitid)
-      unbounded= True;
-    else {
-      if (!facet->center)
-        facet->center= qh_facetcenter(facet->vertices);
-      qh_setappend(&points, facet->center);
-    }
-  }
-  if (numcenters > dim) {
-    simplex= qh_settemp(qh TEMPsize);
-    qh_setappend(&simplex, vertex->point);
-    if (unbounded)
-      qh_setappend(&simplex, midpoint);
-    qh_maxsimplex(dim, points, NULL, 0, &simplex);
-    qh_setdelnth(simplex, 0);
-  }else if (numcenters == dim) {
-    if (unbounded)
-      qh_setappend(&points, midpoint);
-    simplex= points;
-  }else {
-    qh_fprintf(qh ferr, 6216, "qhull internal error (qh_detvnorm): too few points(%d) to compute separating plane\n", numcenters);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  i= 0;
-  gmcoord= qh gm_matrix;
-  point0= SETfirstt_(simplex, pointT);
-  FOREACHpoint_(simplex) {
-    if (qh IStracing >= 4)
-      qh_printmatrix(qh ferr, "qh_detvnorm: Voronoi vertex or midpoint",
-                              &point, 1, dim);
-    if (point != point0) {
-      qh gm_row[i++]= gmcoord;
-      coord= point0;
-      for (k=dim; k--; )
-        *(gmcoord++)= *point++ - *coord++;
-    }
-  }
-  qh gm_row[i]= gmcoord;  /* does not overlap midpoint, may be used later for qh_areasimplex */
-  normal= gmcoord;
-  qh_sethyperplane_gauss(dim, qh gm_row, point0, True,
-                normal, &offset, &nearzero);
-  if (qh GOODvertexp == vertexA->point)
-    inpoint= vertexA->point;
-  else
-    inpoint= vertex->point;
-  zinc_(Zdistio);
-  dist= qh_distnorm(dim, inpoint, normal, &offset);
-  if (dist > 0) {
-    offset= -offset;
-    normalp= normal;
-    for (k=dim; k--; ) {
-      *normalp= -(*normalp);
-      normalp++;
-    }
-  }
-  if (qh VERIFYoutput || qh PRINTstatistics) {
-    pointid= qh_pointid(vertex->point);
-    pointidA= qh_pointid(vertexA->point);
-    if (!unbounded) {
-      zinc_(Zdiststat);
-      dist= qh_distnorm(dim, midpoint, normal, &offset);
-      if (dist < 0)
-        dist= -dist;
-      zzinc_(Zridgemid);
-      wwmax_(Wridgemidmax, dist);
-      wwadd_(Wridgemid, dist);
-      trace4((qh ferr, 4014, "qh_detvnorm: points %d %d midpoint dist %2.2g\n",
-                 pointid, pointidA, dist));
-      for (k=0; k < dim; k++)
-        midpoint[k]= vertexA->point[k] - vertex->point[k];  /* overwrites midpoint! */
-      qh_normalize(midpoint, dim, False);
-      angle= qh_distnorm(dim, midpoint, normal, &zero); /* qh_detangle uses dim+1 */
-      if (angle < 0.0)
-        angle= angle + 1.0;
-      else
-        angle= angle - 1.0;
-      if (angle < 0.0)
-        angle -= angle;
-      trace4((qh ferr, 4015, "qh_detvnorm: points %d %d angle %2.2g nearzero %d\n",
-                 pointid, pointidA, angle, nearzero));
-      if (nearzero) {
-        zzinc_(Zridge0);
-        wwmax_(Wridge0max, angle);
-        wwadd_(Wridge0, angle);
-      }else {
-        zzinc_(Zridgeok)
-        wwmax_(Wridgeokmax, angle);
-        wwadd_(Wridgeok, angle);
-      }
-    }
-    if (simplex != points) {
-      FOREACHpoint_i_(points) {
-        if (!qh_setin(simplex, point)) {
-          facet= SETelemt_(centers, point_i, facetT);
-          zinc_(Zdiststat);
-          dist= qh_distnorm(dim, point, normal, &offset);
-          if (dist < 0)
-            dist= -dist;
-          zzinc_(Zridge);
-          wwmax_(Wridgemax, dist);
-          wwadd_(Wridge, dist);
-          trace4((qh ferr, 4016, "qh_detvnorm: points %d %d Voronoi vertex %d dist %2.2g\n",
-                             pointid, pointidA, facet->visitid, dist));
-        }
-      }
-    }
-  }
-  *offsetp= offset;
-  if (simplex != points)
-    qh_settempfree(&simplex);
-  qh_settempfree(&points);
-  return normal;
-} /* detvnorm */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="detvridge">-</a>
-
-  qh_detvridge( vertexA )
-    determine Voronoi ridge from 'seen' neighbors of vertexA
-    include one vertex-at-infinite if an !neighbor->visitid
-
-  returns:
-    temporary set of centers (facets, i.e., Voronoi vertices)
-    sorted by center id
-*/
-setT *qh_detvridge(vertexT *vertex) {
-  setT *centers= qh_settemp(qh TEMPsize);
-  setT *tricenters= qh_settemp(qh TEMPsize);
-  facetT *neighbor, **neighborp;
-  boolT firstinf= True;
-
-  FOREACHneighbor_(vertex) {
-    if (neighbor->seen) {
-      if (neighbor->visitid) {
-        if (!neighbor->tricoplanar || qh_setunique(&tricenters, neighbor->center))
-          qh_setappend(&centers, neighbor);
-      }else if (firstinf) {
-        firstinf= False;
-        qh_setappend(&centers, neighbor);
-      }
-    }
-  }
-  qsort(SETaddr_(centers, facetT), (size_t)qh_setsize(centers),
-             sizeof(facetT *), qh_compare_facetvisit);
-  qh_settempfree(&tricenters);
-  return centers;
-} /* detvridge */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="detvridge3">-</a>
-
-  qh_detvridge3( atvertex, vertex )
-    determine 3-d Voronoi ridge from 'seen' neighbors of atvertex and vertex
-    include one vertex-at-infinite for !neighbor->visitid
-    assumes all facet->seen2= True
-
-  returns:
-    temporary set of centers (facets, i.e., Voronoi vertices)
-    listed in adjacency order (!oriented)
-    all facet->seen2= True
-
-  design:
-    mark all neighbors of atvertex
-    for each adjacent neighbor of both atvertex and vertex
-      if neighbor selected
-        add neighbor to set of Voronoi vertices
-*/
-setT *qh_detvridge3 (vertexT *atvertex, vertexT *vertex) {
-  setT *centers= qh_settemp(qh TEMPsize);
-  setT *tricenters= qh_settemp(qh TEMPsize);
-  facetT *neighbor, **neighborp, *facet= NULL;
-  boolT firstinf= True;
-
-  FOREACHneighbor_(atvertex)
-    neighbor->seen2= False;
-  FOREACHneighbor_(vertex) {
-    if (!neighbor->seen2) {
-      facet= neighbor;
-      break;
-    }
-  }
-  while (facet) {
-    facet->seen2= True;
-    if (neighbor->seen) {
-      if (facet->visitid) {
-        if (!facet->tricoplanar || qh_setunique(&tricenters, facet->center))
-          qh_setappend(&centers, facet);
-      }else if (firstinf) {
-        firstinf= False;
-        qh_setappend(&centers, facet);
-      }
-    }
-    FOREACHneighbor_(facet) {
-      if (!neighbor->seen2) {
-        if (qh_setin(vertex->neighbors, neighbor))
-          break;
-        else
-          neighbor->seen2= True;
-      }
-    }
-    facet= neighbor;
-  }
-  if (qh CHECKfrequently) {
-    FOREACHneighbor_(vertex) {
-      if (!neighbor->seen2) {
-          qh_fprintf(qh ferr, 6217, "qhull internal error (qh_detvridge3): neighbors of vertex p%d are not connected at facet %d\n",
-                 qh_pointid(vertex->point), neighbor->id);
-        qh_errexit(qh_ERRqhull, neighbor, NULL);
-      }
-    }
-  }
-  FOREACHneighbor_(atvertex)
-    neighbor->seen2= True;
-  qh_settempfree(&tricenters);
-  return centers;
-} /* detvridge3 */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="eachvoronoi">-</a>
-
-  qh_eachvoronoi( fp, printvridge, vertex, visitall, innerouter, inorder )
-    if visitall,
-      visit all Voronoi ridges for vertex (i.e., an input site)
-    else
-      visit all unvisited Voronoi ridges for vertex
-      all vertex->seen= False if unvisited
-    assumes
-      all facet->seen= False
-      all facet->seen2= True (for qh_detvridge3)
-      all facet->visitid == 0 if vertex_at_infinity
-                         == index of Voronoi vertex
-                         >= qh.num_facets if ignored
-    innerouter:
-      qh_RIDGEall--  both inner (bounded) and outer(unbounded) ridges
-      qh_RIDGEinner- only inner
-      qh_RIDGEouter- only outer
-
-    if inorder
-      orders vertices for 3-d Voronoi diagrams
-
-  returns:
-    number of visited ridges (does not include previously visited ridges)
-
-    if printvridge,
-      calls printvridge( fp, vertex, vertexA, centers)
-        fp== any pointer (assumes FILE*)
-        vertex,vertexA= pair of input sites that define a Voronoi ridge
-        centers= set of facets (i.e., Voronoi vertices)
-                 ->visitid == index or 0 if vertex_at_infinity
-                 ordered for 3-d Voronoi diagram
-  notes:
-    uses qh.vertex_visit
-
-  see:
-    qh_eachvoronoi_all()
-
-  design:
-    mark selected neighbors of atvertex
-    for each selected neighbor (either Voronoi vertex or vertex-at-infinity)
-      for each unvisited vertex
-        if atvertex and vertex share more than d-1 neighbors
-          bump totalcount
-          if printvridge defined
-            build the set of shared neighbors (i.e., Voronoi vertices)
-            call printvridge
-*/
-int qh_eachvoronoi(FILE *fp, printvridgeT printvridge, vertexT *atvertex, boolT visitall, qh_RIDGE innerouter, boolT inorder) {
-  boolT unbounded;
-  int count;
-  facetT *neighbor, **neighborp, *neighborA, **neighborAp;
-  setT *centers;
-  setT *tricenters= qh_settemp(qh TEMPsize);
-
-  vertexT *vertex, **vertexp;
-  boolT firstinf;
-  unsigned int numfacets= (unsigned int)qh num_facets;
-  int totridges= 0;
-
-  qh vertex_visit++;
-  atvertex->seen= True;
-  if (visitall) {
-    FORALLvertices
-      vertex->seen= False;
-  }
-  FOREACHneighbor_(atvertex) {
-    if (neighbor->visitid < numfacets)
-      neighbor->seen= True;
-  }
-  FOREACHneighbor_(atvertex) {
-    if (neighbor->seen) {
-      FOREACHvertex_(neighbor->vertices) {
-        if (vertex->visitid != qh vertex_visit && !vertex->seen) {
-          vertex->visitid= qh vertex_visit;
-          count= 0;
-          firstinf= True;
-          qh_settruncate(tricenters, 0);
-          FOREACHneighborA_(vertex) {
-            if (neighborA->seen) {
-              if (neighborA->visitid) {
-                if (!neighborA->tricoplanar || qh_setunique(&tricenters, neighborA->center))
-                  count++;
-              }else if (firstinf) {
-                count++;
-                firstinf= False;
-              }
-            }
-          }
-          if (count >= qh hull_dim - 1) {  /* e.g., 3 for 3-d Voronoi */
-            if (firstinf) {
-              if (innerouter == qh_RIDGEouter)
-                continue;
-              unbounded= False;
-            }else {
-              if (innerouter == qh_RIDGEinner)
-                continue;
-              unbounded= True;
-            }
-            totridges++;
-            trace4((qh ferr, 4017, "qh_eachvoronoi: Voronoi ridge of %d vertices between sites %d and %d\n",
-                  count, qh_pointid(atvertex->point), qh_pointid(vertex->point)));
-            if (printvridge && fp) {
-              if (inorder && qh hull_dim == 3+1) /* 3-d Voronoi diagram */
-                centers= qh_detvridge3 (atvertex, vertex);
-              else
-                centers= qh_detvridge(vertex);
-              (*printvridge) (fp, atvertex, vertex, centers, unbounded);
-              qh_settempfree(&centers);
-            }
-          }
-        }
-      }
-    }
-  }
-  FOREACHneighbor_(atvertex)
-    neighbor->seen= False;
-  qh_settempfree(&tricenters);
-  return totridges;
-} /* eachvoronoi */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="eachvoronoi_all">-</a>
-
-  qh_eachvoronoi_all( fp, printvridge, isUpper, innerouter, inorder )
-    visit all Voronoi ridges
-
-    innerouter:
-      see qh_eachvoronoi()
-
-    if inorder
-      orders vertices for 3-d Voronoi diagrams
-
-  returns
-    total number of ridges
-
-    if isUpper == facet->upperdelaunay  (i.e., a Vornoi vertex)
-      facet->visitid= Voronoi vertex index(same as 'o' format)
-    else
-      facet->visitid= 0
-
-    if printvridge,
-      calls printvridge( fp, vertex, vertexA, centers)
-      [see qh_eachvoronoi]
-
-  notes:
-    Not used for qhull.exe
-    same effect as qh_printvdiagram but ridges not sorted by point id
-*/
-int qh_eachvoronoi_all(FILE *fp, printvridgeT printvridge, boolT isUpper, qh_RIDGE innerouter, boolT inorder) {
-  facetT *facet;
-  vertexT *vertex;
-  int numcenters= 1;  /* vertex 0 is vertex-at-infinity */
-  int totridges= 0;
-
-  qh_clearcenters(qh_ASvoronoi);
-  qh_vertexneighbors();
-  maximize_(qh visit_id, (unsigned) qh num_facets);
-  FORALLfacets {
-    facet->visitid= 0;
-    facet->seen= False;
-    facet->seen2= True;
-  }
-  FORALLfacets {
-    if (facet->upperdelaunay == isUpper)
-      facet->visitid= numcenters++;
-  }
-  FORALLvertices
-    vertex->seen= False;
-  FORALLvertices {
-    if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
-      continue;
-    totridges += qh_eachvoronoi(fp, printvridge, vertex,
-                   !qh_ALL, innerouter, inorder);
-  }
-  return totridges;
-} /* eachvoronoi_all */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="facet2point">-</a>
-
-  qh_facet2point( facet, point0, point1, mindist )
-    return two projected temporary vertices for a 2-d facet
-    may be non-simplicial
-
-  returns:
-    point0 and point1 oriented and projected to the facet
-    returns mindist (maximum distance below plane)
-*/
-void qh_facet2point(facetT *facet, pointT **point0, pointT **point1, realT *mindist) {
-  vertexT *vertex0, *vertex1;
-  realT dist;
-
-  if (facet->toporient ^ qh_ORIENTclock) {
-    vertex0= SETfirstt_(facet->vertices, vertexT);
-    vertex1= SETsecondt_(facet->vertices, vertexT);
-  }else {
-    vertex1= SETfirstt_(facet->vertices, vertexT);
-    vertex0= SETsecondt_(facet->vertices, vertexT);
-  }
-  zadd_(Zdistio, 2);
-  qh_distplane(vertex0->point, facet, &dist);
-  *mindist= dist;
-  *point0= qh_projectpoint(vertex0->point, facet, dist);
-  qh_distplane(vertex1->point, facet, &dist);
-  minimize_(*mindist, dist);
-  *point1= qh_projectpoint(vertex1->point, facet, dist);
-} /* facet2point */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="facetvertices">-</a>
-
-  qh_facetvertices( facetlist, facets, allfacets )
-    returns temporary set of vertices in a set and/or list of facets
-    if allfacets, ignores qh_skipfacet()
-
-  returns:
-    vertices with qh.vertex_visit
-
-  notes:
-    optimized for allfacets of facet_list
-
-  design:
-    if allfacets of facet_list
-      create vertex set from vertex_list
-    else
-      for each selected facet in facets or facetlist
-        append unvisited vertices to vertex set
-*/
-setT *qh_facetvertices(facetT *facetlist, setT *facets, boolT allfacets) {
-  setT *vertices;
-  facetT *facet, **facetp;
-  vertexT *vertex, **vertexp;
-
-  qh vertex_visit++;
-  if (facetlist == qh facet_list && allfacets && !facets) {
-    vertices= qh_settemp(qh num_vertices);
-    FORALLvertices {
-      vertex->visitid= qh vertex_visit;
-      qh_setappend(&vertices, vertex);
-    }
-  }else {
-    vertices= qh_settemp(qh TEMPsize);
-    FORALLfacet_(facetlist) {
-      if (!allfacets && qh_skipfacet(facet))
-        continue;
-      FOREACHvertex_(facet->vertices) {
-        if (vertex->visitid != qh vertex_visit) {
-          vertex->visitid= qh vertex_visit;
-          qh_setappend(&vertices, vertex);
-        }
-      }
-    }
-  }
-  FOREACHfacet_(facets) {
-    if (!allfacets && qh_skipfacet(facet))
-      continue;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        vertex->visitid= qh vertex_visit;
-        qh_setappend(&vertices, vertex);
-      }
-    }
-  }
-  return vertices;
-} /* facetvertices */
-
-/*-<a                             href="qh-geom.htm#TOC"
-  >-------------------------------</a><a name="geomplanes">-</a>
-
-  qh_geomplanes( facet, outerplane, innerplane )
-    return outer and inner planes for Geomview
-    qh.PRINTradius is size of vertices and points (includes qh.JOGGLEmax)
-
-  notes:
-    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-*/
-void qh_geomplanes(facetT *facet, realT *outerplane, realT *innerplane) {
-  realT radius;
-
-  if (qh MERGING || qh JOGGLEmax < REALmax/2) {
-    qh_outerinner(facet, outerplane, innerplane);
-    radius= qh PRINTradius;
-    if (qh JOGGLEmax < REALmax/2)
-      radius -= qh JOGGLEmax * sqrt((realT)qh hull_dim);  /* already accounted for in qh_outerinner() */
-    *outerplane += radius;
-    *innerplane -= radius;
-    if (qh PRINTcoplanar || qh PRINTspheres) {
-      *outerplane += qh MAXabs_coord * qh_GEOMepsilon;
-      *innerplane -= qh MAXabs_coord * qh_GEOMepsilon;
-    }
-  }else
-    *innerplane= *outerplane= 0;
-} /* geomplanes */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="markkeep">-</a>
-
-  qh_markkeep( facetlist )
-    mark good facets that meet qh.KEEParea, qh.KEEPmerge, and qh.KEEPminArea
-    ignores visible facets (!part of convex hull)
-
-  returns:
-    may clear facet->good
-    recomputes qh.num_good
-
-  design:
-    get set of good facets
-    if qh.KEEParea
-      sort facets by area
-      clear facet->good for all but n largest facets
-    if qh.KEEPmerge
-      sort facets by merge count
-      clear facet->good for all but n most merged facets
-    if qh.KEEPminarea
-      clear facet->good if area too small
-    update qh.num_good
-*/
-void qh_markkeep(facetT *facetlist) {
-  facetT *facet, **facetp;
-  setT *facets= qh_settemp(qh num_facets);
-  int size, count;
-
-  trace2((qh ferr, 2006, "qh_markkeep: only keep %d largest and/or %d most merged facets and/or min area %.2g\n",
-          qh KEEParea, qh KEEPmerge, qh KEEPminArea));
-  FORALLfacet_(facetlist) {
-    if (!facet->visible && facet->good)
-      qh_setappend(&facets, facet);
-  }
-  size= qh_setsize(facets);
-  if (qh KEEParea) {
-    qsort(SETaddr_(facets, facetT), (size_t)size,
-             sizeof(facetT *), qh_compare_facetarea);
-    if ((count= size - qh KEEParea) > 0) {
-      FOREACHfacet_(facets) {
-        facet->good= False;
-        if (--count == 0)
-          break;
-      }
-    }
-  }
-  if (qh KEEPmerge) {
-    qsort(SETaddr_(facets, facetT), (size_t)size,
-             sizeof(facetT *), qh_compare_facetmerge);
-    if ((count= size - qh KEEPmerge) > 0) {
-      FOREACHfacet_(facets) {
-        facet->good= False;
-        if (--count == 0)
-          break;
-      }
-    }
-  }
-  if (qh KEEPminArea < REALmax/2) {
-    FOREACHfacet_(facets) {
-      if (!facet->isarea || facet->f.area < qh KEEPminArea)
-        facet->good= False;
-    }
-  }
-  qh_settempfree(&facets);
-  count= 0;
-  FORALLfacet_(facetlist) {
-    if (facet->good)
-      count++;
-  }
-  qh num_good= count;
-} /* markkeep */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="markvoronoi">-</a>
-
-  qh_markvoronoi( facetlist, facets, printall, isLower, numcenters )
-    mark voronoi vertices for printing by site pairs
-
-  returns:
-    temporary set of vertices indexed by pointid
-    isLower set if printing lower hull (i.e., at least one facet is lower hull)
-    numcenters= total number of Voronoi vertices
-    bumps qh.printoutnum for vertex-at-infinity
-    clears all facet->seen and sets facet->seen2
-
-    if selected
-      facet->visitid= Voronoi vertex id
-    else if upper hull (or 'Qu' and lower hull)
-      facet->visitid= 0
-    else
-      facet->visitid >= qh num_facets
-
-  notes:
-    ignores qh.ATinfinity, if defined
-*/
-setT *qh_markvoronoi(facetT *facetlist, setT *facets, boolT printall, boolT *isLowerp, int *numcentersp) {
-  int numcenters=0;
-  facetT *facet, **facetp;
-  setT *vertices;
-  boolT isLower= False;
-
-  qh printoutnum++;
-  qh_clearcenters(qh_ASvoronoi);  /* in case, qh_printvdiagram2 called by user */
-  qh_vertexneighbors();
-  vertices= qh_pointvertex();
-  if (qh ATinfinity)
-    SETelem_(vertices, qh num_points-1)= NULL;
-  qh visit_id++;
-  maximize_(qh visit_id, (unsigned) qh num_facets);
-  FORALLfacet_(facetlist) {
-    if (printall || !qh_skipfacet(facet)) {
-      if (!facet->upperdelaunay) {
-        isLower= True;
-        break;
-      }
-    }
-  }
-  FOREACHfacet_(facets) {
-    if (printall || !qh_skipfacet(facet)) {
-      if (!facet->upperdelaunay) {
-        isLower= True;
-        break;
-      }
-    }
-  }
-  FORALLfacets {
-    if (facet->normal && (facet->upperdelaunay == isLower))
-      facet->visitid= 0;  /* facetlist or facets may overwrite */
-    else
-      facet->visitid= qh visit_id;
-    facet->seen= False;
-    facet->seen2= True;
-  }
-  numcenters++;  /* qh_INFINITE */
-  FORALLfacet_(facetlist) {
-    if (printall || !qh_skipfacet(facet))
-      facet->visitid= numcenters++;
-  }
-  FOREACHfacet_(facets) {
-    if (printall || !qh_skipfacet(facet))
-      facet->visitid= numcenters++;
-  }
-  *isLowerp= isLower;
-  *numcentersp= numcenters;
-  trace2((qh ferr, 2007, "qh_markvoronoi: isLower %d numcenters %d\n", isLower, numcenters));
-  return vertices;
-} /* markvoronoi */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="order_vertexneighbors">-</a>
-
-  qh_order_vertexneighbors( vertex )
-    order facet neighbors of a 2-d or 3-d vertex by adjacency
-
-  notes:
-    does not orient the neighbors
-
-  design:
-    initialize a new neighbor set with the first facet in vertex->neighbors
-    while vertex->neighbors non-empty
-      select next neighbor in the previous facet's neighbor set
-    set vertex->neighbors to the new neighbor set
-*/
-void qh_order_vertexneighbors(vertexT *vertex) {
-  setT *newset;
-  facetT *facet, *neighbor, **neighborp;
-
-  trace4((qh ferr, 4018, "qh_order_vertexneighbors: order neighbors of v%d for 3-d\n", vertex->id));
-  newset= qh_settemp(qh_setsize(vertex->neighbors));
-  facet= (facetT*)qh_setdellast(vertex->neighbors);
-  qh_setappend(&newset, facet);
-  while (qh_setsize(vertex->neighbors)) {
-    FOREACHneighbor_(vertex) {
-      if (qh_setin(facet->neighbors, neighbor)) {
-        qh_setdel(vertex->neighbors, neighbor);
-        qh_setappend(&newset, neighbor);
-        facet= neighbor;
-        break;
-      }
-    }
-    if (!neighbor) {
-      qh_fprintf(qh ferr, 6066, "qhull internal error (qh_order_vertexneighbors): no neighbor of v%d for f%d\n",
-        vertex->id, facet->id);
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-  }
-  qh_setfree(&vertex->neighbors);
-  qh_settemppop();
-  vertex->neighbors= newset;
-} /* order_vertexneighbors */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="prepare_output">-</a>
-
-  qh_prepare_output( )
-    prepare for qh_produce_output2() according to
-      qh.KEEPminArea, KEEParea, KEEPmerge, GOODvertex, GOODthreshold, GOODpoint, ONLYgood, SPLITthresholds
-    does not reset facet->good
-
-  notes
-    except for PRINTstatistics, no-op if previously called with same options
-*/
-void qh_prepare_output(void) {
-  if (qh VORONOI) {
-    qh_clearcenters (qh_ASvoronoi);
-    qh_vertexneighbors();
-  }
-  if (qh TRIangulate && !qh hasTriangulation) {
-    qh_triangulate();
-    if (qh VERIFYoutput && !qh CHECKfrequently)
-      qh_checkpolygon (qh facet_list);
-  }
-  qh_findgood_all (qh facet_list);
-  if (qh GETarea)
-    qh_getarea(qh facet_list);
-  if (qh KEEParea || qh KEEPmerge || qh KEEPminArea < REALmax/2)
-    qh_markkeep (qh facet_list);
-  if (qh PRINTstatistics)
-    qh_collectstatistics();
-}
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printafacet">-</a>
-
-  qh_printafacet( fp, format, facet, printall )
-    print facet to fp in given output format (see qh.PRINTout)
-
-  returns:
-    nop if !printall and qh_skipfacet()
-    nop if visible facet and NEWfacets and format != PRINTfacets
-    must match qh_countfacets
-
-  notes
-    preserves qh.visit_id
-    facet->normal may be null if PREmerge/MERGEexact and STOPcone before merge
-
-  see
-    qh_printbegin() and qh_printend()
-
-  design:
-    test for printing facet
-    call appropriate routine for format
-    or output results directly
-*/
-void qh_printafacet(FILE *fp, qh_PRINT format, facetT *facet, boolT printall) {
-  realT color[4], offset, dist, outerplane, innerplane;
-  boolT zerodiv;
-  coordT *point, *normp, *coordp, **pointp, *feasiblep;
-  int k;
-  vertexT *vertex, **vertexp;
-  facetT *neighbor, **neighborp;
-
-  if (!printall && qh_skipfacet(facet))
-    return;
-  if (facet->visible && qh NEWfacets && format != qh_PRINTfacets)
-    return;
-  qh printoutnum++;
-  switch (format) {
-  case qh_PRINTarea:
-    if (facet->isarea) {
-      qh_fprintf(fp, 9009, qh_REAL_1, facet->f.area);
-      qh_fprintf(fp, 9010, "\n");
-    }else
-      qh_fprintf(fp, 9011, "0\n");
-    break;
-  case qh_PRINTcoplanars:
-    qh_fprintf(fp, 9012, "%d", qh_setsize(facet->coplanarset));
-    FOREACHpoint_(facet->coplanarset)
-      qh_fprintf(fp, 9013, " %d", qh_pointid(point));
-    qh_fprintf(fp, 9014, "\n");
-    break;
-  case qh_PRINTcentrums:
-    qh_printcenter(fp, format, NULL, facet);
-    break;
-  case qh_PRINTfacets:
-    qh_printfacet(fp, facet);
-    break;
-  case qh_PRINTfacets_xridge:
-    qh_printfacetheader(fp, facet);
-    break;
-  case qh_PRINTgeom:  /* either 2 , 3, or 4-d by qh_printbegin */
-    if (!facet->normal)
-      break;
-    for (k=qh hull_dim; k--; ) {
-      color[k]= (facet->normal[k]+1.0)/2.0;
-      maximize_(color[k], -1.0);
-      minimize_(color[k], +1.0);
-    }
-    qh_projectdim3 (color, color);
-    if (qh PRINTdim != qh hull_dim)
-      qh_normalize2 (color, 3, True, NULL, NULL);
-    if (qh hull_dim <= 2)
-      qh_printfacet2geom(fp, facet, color);
-    else if (qh hull_dim == 3) {
-      if (facet->simplicial)
-        qh_printfacet3geom_simplicial(fp, facet, color);
-      else
-        qh_printfacet3geom_nonsimplicial(fp, facet, color);
-    }else {
-      if (facet->simplicial)
-        qh_printfacet4geom_simplicial(fp, facet, color);
-      else
-        qh_printfacet4geom_nonsimplicial(fp, facet, color);
-    }
-    break;
-  case qh_PRINTids:
-    qh_fprintf(fp, 9015, "%d\n", facet->id);
-    break;
-  case qh_PRINTincidences:
-  case qh_PRINToff:
-  case qh_PRINTtriangles:
-    if (qh hull_dim == 3 && format != qh_PRINTtriangles)
-      qh_printfacet3vertex(fp, facet, format);
-    else if (facet->simplicial || qh hull_dim == 2 || format == qh_PRINToff)
-      qh_printfacetNvertex_simplicial(fp, facet, format);
-    else
-      qh_printfacetNvertex_nonsimplicial(fp, facet, qh printoutvar++, format);
-    break;
-  case qh_PRINTinner:
-    qh_outerinner(facet, NULL, &innerplane);
-    offset= facet->offset - innerplane;
-    goto LABELprintnorm;
-    break; /* prevent warning */
-  case qh_PRINTmerges:
-    qh_fprintf(fp, 9016, "%d\n", facet->nummerge);
-    break;
-  case qh_PRINTnormals:
-    offset= facet->offset;
-    goto LABELprintnorm;
-    break; /* prevent warning */
-  case qh_PRINTouter:
-    qh_outerinner(facet, &outerplane, NULL);
-    offset= facet->offset - outerplane;
-  LABELprintnorm:
-    if (!facet->normal) {
-      qh_fprintf(fp, 9017, "no normal for facet f%d\n", facet->id);
-      break;
-    }
-    if (qh CDDoutput) {
-      qh_fprintf(fp, 9018, qh_REAL_1, -offset);
-      for (k=0; k < qh hull_dim; k++)
-        qh_fprintf(fp, 9019, qh_REAL_1, -facet->normal[k]);
-    }else {
-      for (k=0; k < qh hull_dim; k++)
-        qh_fprintf(fp, 9020, qh_REAL_1, facet->normal[k]);
-      qh_fprintf(fp, 9021, qh_REAL_1, offset);
-    }
-    qh_fprintf(fp, 9022, "\n");
-    break;
-  case qh_PRINTmathematica:  /* either 2 or 3-d by qh_printbegin */
-  case qh_PRINTmaple:
-    if (qh hull_dim == 2)
-      qh_printfacet2math(fp, facet, format, qh printoutvar++);
-    else
-      qh_printfacet3math(fp, facet, format, qh printoutvar++);
-    break;
-  case qh_PRINTneighbors:
-    qh_fprintf(fp, 9023, "%d", qh_setsize(facet->neighbors));
-    FOREACHneighbor_(facet)
-      qh_fprintf(fp, 9024, " %d",
-               neighbor->visitid ? neighbor->visitid - 1: 0 - neighbor->id);
-    qh_fprintf(fp, 9025, "\n");
-    break;
-  case qh_PRINTpointintersect:
-    if (!qh feasible_point) {
-      qh_fprintf(qh ferr, 6067, "qhull input error (qh_printafacet): option 'Fp' needs qh feasible_point\n");
-      qh_errexit( qh_ERRinput, NULL, NULL);
-    }
-    if (facet->offset > 0)
-      goto LABELprintinfinite;
-    point= coordp= (coordT*)qh_memalloc(qh normal_size);
-    normp= facet->normal;
-    feasiblep= qh feasible_point;
-    if (facet->offset < -qh MINdenom) {
-      for (k=qh hull_dim; k--; )
-        *(coordp++)= (*(normp++) / - facet->offset) + *(feasiblep++);
-    }else {
-      for (k=qh hull_dim; k--; ) {
-        *(coordp++)= qh_divzero(*(normp++), facet->offset, qh MINdenom_1,
-                                 &zerodiv) + *(feasiblep++);
-        if (zerodiv) {
-          qh_memfree(point, qh normal_size);
-          goto LABELprintinfinite;
-        }
-      }
-    }
-    qh_printpoint(fp, NULL, point);
-    qh_memfree(point, qh normal_size);
-    break;
-  LABELprintinfinite:
-    for (k=qh hull_dim; k--; )
-      qh_fprintf(fp, 9026, qh_REAL_1, qh_INFINITE);
-    qh_fprintf(fp, 9027, "\n");
-    break;
-  case qh_PRINTpointnearest:
-    FOREACHpoint_(facet->coplanarset) {
-      int id, id2;
-      vertex= qh_nearvertex(facet, point, &dist);
-      id= qh_pointid(vertex->point);
-      id2= qh_pointid(point);
-      qh_fprintf(fp, 9028, "%d %d %d " qh_REAL_1 "\n", id, id2, facet->id, dist);
-    }
-    break;
-  case qh_PRINTpoints:  /* VORONOI only by qh_printbegin */
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9029, "1 ");
-    qh_printcenter(fp, format, NULL, facet);
-    break;
-  case qh_PRINTvertices:
-    qh_fprintf(fp, 9030, "%d", qh_setsize(facet->vertices));
-    FOREACHvertex_(facet->vertices)
-      qh_fprintf(fp, 9031, " %d", qh_pointid(vertex->point));
-    qh_fprintf(fp, 9032, "\n");
-    break;
-  default:
-    break;
-  }
-} /* printafacet */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printbegin">-</a>
-
-  qh_printbegin(  )
-    prints header for all output formats
-
-  returns:
-    checks for valid format
-
-  notes:
-    uses qh.visit_id for 3/4off
-    changes qh.interior_point if printing centrums
-    qh_countfacets clears facet->visitid for non-good facets
-
-  see
-    qh_printend() and qh_printafacet()
-
-  design:
-    count facets and related statistics
-    print header for format
-*/
-void qh_printbegin(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
-  int i, num;
-  facetT *facet, **facetp;
-  vertexT *vertex, **vertexp;
-  setT *vertices;
-  pointT *point, **pointp, *pointtemp;
-
-  qh printoutnum= 0;
-  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
-  switch (format) {
-  case qh_PRINTnone:
-    break;
-  case qh_PRINTarea:
-    qh_fprintf(fp, 9033, "%d\n", numfacets);
-    break;
-  case qh_PRINTcoplanars:
-    qh_fprintf(fp, 9034, "%d\n", numfacets);
-    break;
-  case qh_PRINTcentrums:
-    if (qh CENTERtype == qh_ASnone)
-      qh_clearcenters(qh_AScentrum);
-    qh_fprintf(fp, 9035, "%d\n%d\n", qh hull_dim, numfacets);
-    break;
-  case qh_PRINTfacets:
-  case qh_PRINTfacets_xridge:
-    if (facetlist)
-      qh_printvertexlist(fp, "Vertices and facets:\n", facetlist, facets, printall);
-    break;
-  case qh_PRINTgeom:
-    if (qh hull_dim > 4)  /* qh_initqhull_globals also checks */
-      goto LABELnoformat;
-    if (qh VORONOI && qh hull_dim > 3)  /* PRINTdim == DROPdim == hull_dim-1 */
-      goto LABELnoformat;
-    if (qh hull_dim == 2 && (qh PRINTridges || qh DOintersections))
-      qh_fprintf(qh ferr, 7049, "qhull warning: output for ridges and intersections not implemented in 2-d\n");
-    if (qh hull_dim == 4 && (qh PRINTinner || qh PRINTouter ||
-                             (qh PRINTdim == 4 && qh PRINTcentrums)))
-      qh_fprintf(qh ferr, 7050, "qhull warning: output for outer/inner planes and centrums not implemented in 4-d\n");
-    if (qh PRINTdim == 4 && (qh PRINTspheres))
-      qh_fprintf(qh ferr, 7051, "qhull warning: output for vertices not implemented in 4-d\n");
-    if (qh PRINTdim == 4 && qh DOintersections && qh PRINTnoplanes)
-      qh_fprintf(qh ferr, 7052, "qhull warning: 'Gnh' generates no output in 4-d\n");
-    if (qh PRINTdim == 2) {
-      qh_fprintf(fp, 9036, "{appearance {linewidth 3} LIST # %s | %s\n",
-              qh rbox_command, qh qhull_command);
-    }else if (qh PRINTdim == 3) {
-      qh_fprintf(fp, 9037, "{appearance {+edge -evert linewidth 2} LIST # %s | %s\n",
-              qh rbox_command, qh qhull_command);
-    }else if (qh PRINTdim == 4) {
-      qh visit_id++;
-      num= 0;
-      FORALLfacet_(facetlist)    /* get number of ridges to be printed */
-        qh_printend4geom(NULL, facet, &num, printall);
-      FOREACHfacet_(facets)
-        qh_printend4geom(NULL, facet, &num, printall);
-      qh ridgeoutnum= num;
-      qh printoutvar= 0;  /* counts number of ridges in output */
-      qh_fprintf(fp, 9038, "LIST # %s | %s\n", qh rbox_command, qh qhull_command);
-    }
-
-    if (qh PRINTdots) {
-      qh printoutnum++;
-      num= qh num_points + qh_setsize(qh other_points);
-      if (qh DELAUNAY && qh ATinfinity)
-        num--;
-      if (qh PRINTdim == 4)
-        qh_fprintf(fp, 9039, "4VECT %d %d 1\n", num, num);
-      else
-        qh_fprintf(fp, 9040, "VECT %d %d 1\n", num, num);
-
-      for (i=num; i--; ) {
-        if (i % 20 == 0)
-          qh_fprintf(fp, 9041, "\n");
-        qh_fprintf(fp, 9042, "1 ");
-      }
-      qh_fprintf(fp, 9043, "# 1 point per line\n1 ");
-      for (i=num-1; i--; ) { /* num at least 3 for D2 */
-        if (i % 20 == 0)
-          qh_fprintf(fp, 9044, "\n");
-        qh_fprintf(fp, 9045, "0 ");
-      }
-      qh_fprintf(fp, 9046, "# 1 color for all\n");
-      FORALLpoints {
-        if (!qh DELAUNAY || !qh ATinfinity || qh_pointid(point) != qh num_points-1) {
-          if (qh PRINTdim == 4)
-            qh_printpoint(fp, NULL, point);
-            else
-              qh_printpoint3 (fp, point);
-        }
-      }
-      FOREACHpoint_(qh other_points) {
-        if (qh PRINTdim == 4)
-          qh_printpoint(fp, NULL, point);
-        else
-          qh_printpoint3 (fp, point);
-      }
-      qh_fprintf(fp, 9047, "0 1 1 1  # color of points\n");
-    }
-
-    if (qh PRINTdim == 4  && !qh PRINTnoplanes)
-      /* 4dview loads up multiple 4OFF objects slowly */
-      qh_fprintf(fp, 9048, "4OFF %d %d 1\n", 3*qh ridgeoutnum, qh ridgeoutnum);
-    qh PRINTcradius= 2 * qh DISTround;  /* include test DISTround */
-    if (qh PREmerge) {
-      maximize_(qh PRINTcradius, qh premerge_centrum + qh DISTround);
-    }else if (qh POSTmerge)
-      maximize_(qh PRINTcradius, qh postmerge_centrum + qh DISTround);
-    qh PRINTradius= qh PRINTcradius;
-    if (qh PRINTspheres + qh PRINTcoplanar)
-      maximize_(qh PRINTradius, qh MAXabs_coord * qh_MINradius);
-    if (qh premerge_cos < REALmax/2) {
-      maximize_(qh PRINTradius, (1- qh premerge_cos) * qh MAXabs_coord);
-    }else if (!qh PREmerge && qh POSTmerge && qh postmerge_cos < REALmax/2) {
-      maximize_(qh PRINTradius, (1- qh postmerge_cos) * qh MAXabs_coord);
-    }
-    maximize_(qh PRINTradius, qh MINvisible);
-    if (qh JOGGLEmax < REALmax/2)
-      qh PRINTradius += qh JOGGLEmax * sqrt((realT)qh hull_dim);
-    if (qh PRINTdim != 4 &&
-        (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
-      vertices= qh_facetvertices(facetlist, facets, printall);
-      if (qh PRINTspheres && qh PRINTdim <= 3)
-        qh_printspheres(fp, vertices, qh PRINTradius);
-      if (qh PRINTcoplanar || qh PRINTcentrums) {
-        qh firstcentrum= True;
-        if (qh PRINTcoplanar&& !qh PRINTspheres) {
-          FOREACHvertex_(vertices)
-            qh_printpointvect2 (fp, vertex->point, NULL, qh interior_point, qh PRINTradius);
-        }
-        FORALLfacet_(facetlist) {
-          if (!printall && qh_skipfacet(facet))
-            continue;
-          if (!facet->normal)
-            continue;
-          if (qh PRINTcentrums && qh PRINTdim <= 3)
-            qh_printcentrum(fp, facet, qh PRINTcradius);
-          if (!qh PRINTcoplanar)
-            continue;
-          FOREACHpoint_(facet->coplanarset)
-            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
-          FOREACHpoint_(facet->outsideset)
-            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
-        }
-        FOREACHfacet_(facets) {
-          if (!printall && qh_skipfacet(facet))
-            continue;
-          if (!facet->normal)
-            continue;
-          if (qh PRINTcentrums && qh PRINTdim <= 3)
-            qh_printcentrum(fp, facet, qh PRINTcradius);
-          if (!qh PRINTcoplanar)
-            continue;
-          FOREACHpoint_(facet->coplanarset)
-            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
-          FOREACHpoint_(facet->outsideset)
-            qh_printpointvect2 (fp, point, facet->normal, NULL, qh PRINTradius);
-        }
-      }
-      qh_settempfree(&vertices);
-    }
-    qh visit_id++; /* for printing hyperplane intersections */
-    break;
-  case qh_PRINTids:
-    qh_fprintf(fp, 9049, "%d\n", numfacets);
-    break;
-  case qh_PRINTincidences:
-    if (qh VORONOI && qh PRINTprecision)
-      qh_fprintf(qh ferr, 7053, "qhull warning: writing Delaunay.  Use 'p' or 'o' for Voronoi centers\n");
-    qh printoutvar= qh vertex_id;  /* centrum id for non-simplicial facets */
-    if (qh hull_dim <= 3)
-      qh_fprintf(fp, 9050, "%d\n", numfacets);
-    else
-      qh_fprintf(fp, 9051, "%d\n", numsimplicial+numridges);
-    break;
-  case qh_PRINTinner:
-  case qh_PRINTnormals:
-  case qh_PRINTouter:
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9052, "%s | %s\nbegin\n    %d %d real\n", qh rbox_command,
-            qh qhull_command, numfacets, qh hull_dim+1);
-    else
-      qh_fprintf(fp, 9053, "%d\n%d\n", qh hull_dim+1, numfacets);
-    break;
-  case qh_PRINTmathematica:
-  case qh_PRINTmaple:
-    if (qh hull_dim > 3)  /* qh_initbuffers also checks */
-      goto LABELnoformat;
-    if (qh VORONOI)
-      qh_fprintf(qh ferr, 7054, "qhull warning: output is the Delaunay triangulation\n");
-    if (format == qh_PRINTmaple) {
-      if (qh hull_dim == 2)
-        qh_fprintf(fp, 9054, "PLOT(CURVES(\n");
-      else
-        qh_fprintf(fp, 9055, "PLOT3D(POLYGONS(\n");
-    }else
-      qh_fprintf(fp, 9056, "{\n");
-    qh printoutvar= 0;   /* counts number of facets for notfirst */
-    break;
-  case qh_PRINTmerges:
-    qh_fprintf(fp, 9057, "%d\n", numfacets);
-    break;
-  case qh_PRINTpointintersect:
-    qh_fprintf(fp, 9058, "%d\n%d\n", qh hull_dim, numfacets);
-    break;
-  case qh_PRINTneighbors:
-    qh_fprintf(fp, 9059, "%d\n", numfacets);
-    break;
-  case qh_PRINToff:
-  case qh_PRINTtriangles:
-    if (qh VORONOI)
-      goto LABELnoformat;
-    num = qh hull_dim;
-    if (format == qh_PRINToff || qh hull_dim == 2)
-      qh_fprintf(fp, 9060, "%d\n%d %d %d\n", num,
-        qh num_points+qh_setsize(qh other_points), numfacets, totneighbors/2);
-    else { /* qh_PRINTtriangles */
-      qh printoutvar= qh num_points+qh_setsize(qh other_points); /* first centrum */
-      if (qh DELAUNAY)
-        num--;  /* drop last dimension */
-      qh_fprintf(fp, 9061, "%d\n%d %d %d\n", num, qh printoutvar
-        + numfacets - numsimplicial, numsimplicial + numridges, totneighbors/2);
-    }
-    FORALLpoints
-      qh_printpointid(qh fout, NULL, num, point, -1);
-    FOREACHpoint_(qh other_points)
-      qh_printpointid(qh fout, NULL, num, point, -1);
-    if (format == qh_PRINTtriangles && qh hull_dim > 2) {
-      FORALLfacets {
-        if (!facet->simplicial && facet->visitid)
-          qh_printcenter(qh fout, format, NULL, facet);
-      }
-    }
-    break;
-  case qh_PRINTpointnearest:
-    qh_fprintf(fp, 9062, "%d\n", numcoplanars);
-    break;
-  case qh_PRINTpoints:
-    if (!qh VORONOI)
-      goto LABELnoformat;
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9063, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
-           qh qhull_command, numfacets, qh hull_dim);
-    else
-      qh_fprintf(fp, 9064, "%d\n%d\n", qh hull_dim-1, numfacets);
-    break;
-  case qh_PRINTvertices:
-    qh_fprintf(fp, 9065, "%d\n", numfacets);
-    break;
-  case qh_PRINTsummary:
-  default:
-  LABELnoformat:
-    qh_fprintf(qh ferr, 6068, "qhull internal error (qh_printbegin): can not use this format for dimension %d\n",
-         qh hull_dim);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-} /* printbegin */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printcenter">-</a>
-
-  qh_printcenter( fp, string, facet )
-    print facet->center as centrum or Voronoi center
-    string may be NULL.  Don't include '%' codes.
-    nop if qh CENTERtype neither CENTERvoronoi nor CENTERcentrum
-    if upper envelope of Delaunay triangulation and point at-infinity
-      prints qh_INFINITE instead;
-
-  notes:
-    defines facet->center if needed
-    if format=PRINTgeom, adds a 0 if would otherwise be 2-d
-    Same as QhullFacet::printCenter
-*/
-void qh_printcenter(FILE *fp, qh_PRINT format, const char *string, facetT *facet) {
-  int k, num;
-
-  if (qh CENTERtype != qh_ASvoronoi && qh CENTERtype != qh_AScentrum)
-    return;
-  if (string)
-    qh_fprintf(fp, 9066, string);
-  if (qh CENTERtype == qh_ASvoronoi) {
-    num= qh hull_dim-1;
-    if (!facet->normal || !facet->upperdelaunay || !qh ATinfinity) {
-      if (!facet->center)
-        facet->center= qh_facetcenter(facet->vertices);
-      for (k=0; k < num; k++)
-        qh_fprintf(fp, 9067, qh_REAL_1, facet->center[k]);
-    }else {
-      for (k=0; k < num; k++)
-        qh_fprintf(fp, 9068, qh_REAL_1, qh_INFINITE);
-    }
-  }else /* qh CENTERtype == qh_AScentrum */ {
-    num= qh hull_dim;
-    if (format == qh_PRINTtriangles && qh DELAUNAY)
-      num--;
-    if (!facet->center)
-      facet->center= qh_getcentrum(facet);
-    for (k=0; k < num; k++)
-      qh_fprintf(fp, 9069, qh_REAL_1, facet->center[k]);
-  }
-  if (format == qh_PRINTgeom && num == 2)
-    qh_fprintf(fp, 9070, " 0\n");
-  else
-    qh_fprintf(fp, 9071, "\n");
-} /* printcenter */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printcentrum">-</a>
-
-  qh_printcentrum( fp, facet, radius )
-    print centrum for a facet in OOGL format
-    radius defines size of centrum
-    2-d or 3-d only
-
-  returns:
-    defines facet->center if needed
-*/
-void qh_printcentrum(FILE *fp, facetT *facet, realT radius) {
-  pointT *centrum, *projpt;
-  boolT tempcentrum= False;
-  realT xaxis[4], yaxis[4], normal[4], dist;
-  realT green[3]={0, 1, 0};
-  vertexT *apex;
-  int k;
-
-  if (qh CENTERtype == qh_AScentrum) {
-    if (!facet->center)
-      facet->center= qh_getcentrum(facet);
-    centrum= facet->center;
-  }else {
-    centrum= qh_getcentrum(facet);
-    tempcentrum= True;
-  }
-  qh_fprintf(fp, 9072, "{appearance {-normal -edge normscale 0} ");
-  if (qh firstcentrum) {
-    qh firstcentrum= False;
-    qh_fprintf(fp, 9073, "{INST geom { define centrum CQUAD  # f%d\n\
--0.3 -0.3 0.0001     0 0 1 1\n\
- 0.3 -0.3 0.0001     0 0 1 1\n\
- 0.3  0.3 0.0001     0 0 1 1\n\
--0.3  0.3 0.0001     0 0 1 1 } transform { \n", facet->id);
-  }else
-    qh_fprintf(fp, 9074, "{INST geom { : centrum } transform { # f%d\n", facet->id);
-  apex= SETfirstt_(facet->vertices, vertexT);
-  qh_distplane(apex->point, facet, &dist);
-  projpt= qh_projectpoint(apex->point, facet, dist);
-  for (k=qh hull_dim; k--; ) {
-    xaxis[k]= projpt[k] - centrum[k];
-    normal[k]= facet->normal[k];
-  }
-  if (qh hull_dim == 2) {
-    xaxis[2]= 0;
-    normal[2]= 0;
-  }else if (qh hull_dim == 4) {
-    qh_projectdim3 (xaxis, xaxis);
-    qh_projectdim3 (normal, normal);
-    qh_normalize2 (normal, qh PRINTdim, True, NULL, NULL);
-  }
-  qh_crossproduct(3, xaxis, normal, yaxis);
-  qh_fprintf(fp, 9075, "%8.4g %8.4g %8.4g 0\n", xaxis[0], xaxis[1], xaxis[2]);
-  qh_fprintf(fp, 9076, "%8.4g %8.4g %8.4g 0\n", yaxis[0], yaxis[1], yaxis[2]);
-  qh_fprintf(fp, 9077, "%8.4g %8.4g %8.4g 0\n", normal[0], normal[1], normal[2]);
-  qh_printpoint3 (fp, centrum);
-  qh_fprintf(fp, 9078, "1 }}}\n");
-  qh_memfree(projpt, qh normal_size);
-  qh_printpointvect(fp, centrum, facet->normal, NULL, radius, green);
-  if (tempcentrum)
-    qh_memfree(centrum, qh normal_size);
-} /* printcentrum */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printend">-</a>
-
-  qh_printend( fp, format )
-    prints trailer for all output formats
-
-  see:
-    qh_printbegin() and qh_printafacet()
-
-*/
-void qh_printend(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  int num;
-  facetT *facet, **facetp;
-
-  if (!qh printoutnum)
-    qh_fprintf(qh ferr, 7055, "qhull warning: no facets printed\n");
-  switch (format) {
-  case qh_PRINTgeom:
-    if (qh hull_dim == 4 && qh DROPdim < 0  && !qh PRINTnoplanes) {
-      qh visit_id++;
-      num= 0;
-      FORALLfacet_(facetlist)
-        qh_printend4geom(fp, facet,&num, printall);
-      FOREACHfacet_(facets)
-        qh_printend4geom(fp, facet, &num, printall);
-      if (num != qh ridgeoutnum || qh printoutvar != qh ridgeoutnum) {
-        qh_fprintf(qh ferr, 6069, "qhull internal error (qh_printend): number of ridges %d != number printed %d and at end %d\n", qh ridgeoutnum, qh printoutvar, num);
-        qh_errexit(qh_ERRqhull, NULL, NULL);
-      }
-    }else
-      qh_fprintf(fp, 9079, "}\n");
-    break;
-  case qh_PRINTinner:
-  case qh_PRINTnormals:
-  case qh_PRINTouter:
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9080, "end\n");
-    break;
-  case qh_PRINTmaple:
-    qh_fprintf(fp, 9081, "));\n");
-    break;
-  case qh_PRINTmathematica:
-    qh_fprintf(fp, 9082, "}\n");
-    break;
-  case qh_PRINTpoints:
-    if (qh CDDoutput)
-      qh_fprintf(fp, 9083, "end\n");
-    break;
-  default:
-    break;
-  }
-} /* printend */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printend4geom">-</a>
-
-  qh_printend4geom( fp, facet, numridges, printall )
-    helper function for qh_printbegin/printend
-
-  returns:
-    number of printed ridges
-
-  notes:
-    just counts printed ridges if fp=NULL
-    uses facet->visitid
-    must agree with qh_printfacet4geom...
-
-  design:
-    computes color for facet from its normal
-    prints each ridge of facet
-*/
-void qh_printend4geom(FILE *fp, facetT *facet, int *nump, boolT printall) {
-  realT color[3];
-  int i, num= *nump;
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-
-  if (!printall && qh_skipfacet(facet))
-    return;
-  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
-    return;
-  if (!facet->normal)
-    return;
-  if (fp) {
-    for (i=0; i < 3; i++) {
-      color[i]= (facet->normal[i]+1.0)/2.0;
-      maximize_(color[i], -1.0);
-      minimize_(color[i], +1.0);
-    }
-  }
-  facet->visitid= qh visit_id;
-  if (facet->simplicial) {
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-        if (fp)
-          qh_fprintf(fp, 9084, "3 %d %d %d %8.4g %8.4g %8.4g 1 # f%d f%d\n",
-                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
-                 facet->id, neighbor->id);
-        num++;
-      }
-    }
-  }else {
-    FOREACHridge_(facet->ridges) {
-      neighbor= otherfacet_(ridge, facet);
-      if (neighbor->visitid != qh visit_id) {
-        if (fp)
-          qh_fprintf(fp, 9085, "3 %d %d %d %8.4g %8.4g %8.4g 1 #r%d f%d f%d\n",
-                 3*num, 3*num+1, 3*num+2, color[0], color[1], color[2],
-                 ridge->id, facet->id, neighbor->id);
-        num++;
-      }
-    }
-  }
-  *nump= num;
-} /* printend4geom */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printextremes">-</a>
-
-  qh_printextremes( fp, facetlist, facets, printall )
-    print extreme points for convex hulls or halfspace intersections
-
-  notes:
-    #points, followed by ids, one per line
-
-    sorted by id
-    same order as qh_printpoints_out if no coplanar/interior points
-*/
-void qh_printextremes(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
-  setT *vertices, *points;
-  pointT *point;
-  vertexT *vertex, **vertexp;
-  int id;
-  int numpoints=0, point_i, point_n;
-  int allpoints= qh num_points + qh_setsize(qh other_points);
-
-  points= qh_settemp(allpoints);
-  qh_setzero(points, 0, allpoints);
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  FOREACHvertex_(vertices) {
-    id= qh_pointid(vertex->point);
-    if (id >= 0) {
-      SETelem_(points, id)= vertex->point;
-      numpoints++;
-    }
-  }
-  qh_settempfree(&vertices);
-  qh_fprintf(fp, 9086, "%d\n", numpoints);
-  FOREACHpoint_i_(points) {
-    if (point)
-      qh_fprintf(fp, 9087, "%d\n", point_i);
-  }
-  qh_settempfree(&points);
-} /* printextremes */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printextremes_2d">-</a>
-
-  qh_printextremes_2d( fp, facetlist, facets, printall )
-    prints point ids for facets in qh_ORIENTclock order
-
-  notes:
-    #points, followed by ids, one per line
-    if facetlist/facets are disjoint than the output includes skips
-    errors if facets form a loop
-    does not print coplanar points
-*/
-void qh_printextremes_2d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
-  int numfacets, numridges, totneighbors, numcoplanars, numsimplicial, numtricoplanars;
-  setT *vertices;
-  facetT *facet, *startfacet, *nextfacet;
-  vertexT *vertexA, *vertexB;
-
-  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars); /* marks qh visit_id */
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  qh_fprintf(fp, 9088, "%d\n", qh_setsize(vertices));
-  qh_settempfree(&vertices);
-  if (!numfacets)
-    return;
-  facet= startfacet= facetlist ? facetlist : SETfirstt_(facets, facetT);
-  qh vertex_visit++;
-  qh visit_id++;
-  do {
-    if (facet->toporient ^ qh_ORIENTclock) {
-      vertexA= SETfirstt_(facet->vertices, vertexT);
-      vertexB= SETsecondt_(facet->vertices, vertexT);
-      nextfacet= SETfirstt_(facet->neighbors, facetT);
-    }else {
-      vertexA= SETsecondt_(facet->vertices, vertexT);
-      vertexB= SETfirstt_(facet->vertices, vertexT);
-      nextfacet= SETsecondt_(facet->neighbors, facetT);
-    }
-    if (facet->visitid == qh visit_id) {
-      qh_fprintf(qh ferr, 6218, "Qhull internal error (qh_printextremes_2d): loop in facet list.  facet %d nextfacet %d\n",
-                 facet->id, nextfacet->id);
-      qh_errexit2 (qh_ERRqhull, facet, nextfacet);
-    }
-    if (facet->visitid) {
-      if (vertexA->visitid != qh vertex_visit) {
-        vertexA->visitid= qh vertex_visit;
-        qh_fprintf(fp, 9089, "%d\n", qh_pointid(vertexA->point));
-      }
-      if (vertexB->visitid != qh vertex_visit) {
-        vertexB->visitid= qh vertex_visit;
-        qh_fprintf(fp, 9090, "%d\n", qh_pointid(vertexB->point));
-      }
-    }
-    facet->visitid= qh visit_id;
-    facet= nextfacet;
-  }while (facet && facet != startfacet);
-} /* printextremes_2d */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printextremes_d">-</a>
-
-  qh_printextremes_d( fp, facetlist, facets, printall )
-    print extreme points of input sites for Delaunay triangulations
-
-  notes:
-    #points, followed by ids, one per line
-
-    unordered
-*/
-void qh_printextremes_d(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
-  setT *vertices;
-  vertexT *vertex, **vertexp;
-  boolT upperseen, lowerseen;
-  facetT *neighbor, **neighborp;
-  int numpoints=0;
-
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  qh_vertexneighbors();
-  FOREACHvertex_(vertices) {
-    upperseen= lowerseen= False;
-    FOREACHneighbor_(vertex) {
-      if (neighbor->upperdelaunay)
-        upperseen= True;
-      else
-        lowerseen= True;
-    }
-    if (upperseen && lowerseen) {
-      vertex->seen= True;
-      numpoints++;
-    }else
-      vertex->seen= False;
-  }
-  qh_fprintf(fp, 9091, "%d\n", numpoints);
-  FOREACHvertex_(vertices) {
-    if (vertex->seen)
-      qh_fprintf(fp, 9092, "%d\n", qh_pointid(vertex->point));
-  }
-  qh_settempfree(&vertices);
-} /* printextremes_d */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet">-</a>
-
-  qh_printfacet( fp, facet )
-    prints all fields of a facet to fp
-
-  notes:
-    ridges printed in neighbor order
-*/
-void qh_printfacet(FILE *fp, facetT *facet) {
-
-  qh_printfacetheader(fp, facet);
-  if (facet->ridges)
-    qh_printfacetridges(fp, facet);
-} /* printfacet */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet2geom">-</a>
-
-  qh_printfacet2geom( fp, facet, color )
-    print facet as part of a 2-d VECT for Geomview
-
-    notes:
-      assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-      mindist is calculated within io.c.  maxoutside is calculated elsewhere,
-      so a DISTround error may have occurred.
-*/
-void qh_printfacet2geom(FILE *fp, facetT *facet, realT color[3]) {
-  pointT *point0, *point1;
-  realT mindist, innerplane, outerplane;
-  int k;
-
-  qh_facet2point(facet, &point0, &point1, &mindist);
-  qh_geomplanes(facet, &outerplane, &innerplane);
-  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
-    qh_printfacet2geom_points(fp, point0, point1, facet, outerplane, color);
-  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
-                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
-    for (k=3; k--; )
-      color[k]= 1.0 - color[k];
-    qh_printfacet2geom_points(fp, point0, point1, facet, innerplane, color);
-  }
-  qh_memfree(point1, qh normal_size);
-  qh_memfree(point0, qh normal_size);
-} /* printfacet2geom */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet2geom_points">-</a>
-
-  qh_printfacet2geom_points( fp, point1, point2, facet, offset, color )
-    prints a 2-d facet as a VECT with 2 points at some offset.
-    The points are on the facet's plane.
-*/
-void qh_printfacet2geom_points(FILE *fp, pointT *point1, pointT *point2,
-                               facetT *facet, realT offset, realT color[3]) {
-  pointT *p1= point1, *p2= point2;
-
-  qh_fprintf(fp, 9093, "VECT 1 2 1 2 1 # f%d\n", facet->id);
-  if (offset != 0.0) {
-    p1= qh_projectpoint(p1, facet, -offset);
-    p2= qh_projectpoint(p2, facet, -offset);
-  }
-  qh_fprintf(fp, 9094, "%8.4g %8.4g %8.4g\n%8.4g %8.4g %8.4g\n",
-           p1[0], p1[1], 0.0, p2[0], p2[1], 0.0);
-  if (offset != 0.0) {
-    qh_memfree(p1, qh normal_size);
-    qh_memfree(p2, qh normal_size);
-  }
-  qh_fprintf(fp, 9095, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-} /* printfacet2geom_points */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet2math">-</a>
-
-  qh_printfacet2math( fp, facet, format, notfirst )
-    print 2-d Maple or Mathematica output for a facet
-    may be non-simplicial
-
-  notes:
-    use %16.8f since Mathematica 2.2 does not handle exponential format
-    see qh_printfacet3math
-*/
-void qh_printfacet2math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
-  pointT *point0, *point1;
-  realT mindist;
-  const char *pointfmt;
-
-  qh_facet2point(facet, &point0, &point1, &mindist);
-  if (notfirst)
-    qh_fprintf(fp, 9096, ",");
-  if (format == qh_PRINTmaple)
-    pointfmt= "[[%16.8f, %16.8f], [%16.8f, %16.8f]]\n";
-  else
-    pointfmt= "Line[{{%16.8f, %16.8f}, {%16.8f, %16.8f}}]\n";
-  qh_fprintf(fp, 9097, pointfmt, point0[0], point0[1], point1[0], point1[1]);
-  qh_memfree(point1, qh normal_size);
-  qh_memfree(point0, qh normal_size);
-} /* printfacet2math */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet3geom_nonsimplicial">-</a>
-
-  qh_printfacet3geom_nonsimplicial( fp, facet, color )
-    print Geomview OFF for a 3-d nonsimplicial facet.
-    if DOintersections, prints ridges to unvisited neighbors(qh visit_id)
-
-  notes
-    uses facet->visitid for intersections and ridges
-*/
-void qh_printfacet3geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
-  ridgeT *ridge, **ridgep;
-  setT *projectedpoints, *vertices;
-  vertexT *vertex, **vertexp, *vertexA, *vertexB;
-  pointT *projpt, *point, **pointp;
-  facetT *neighbor;
-  realT dist, outerplane, innerplane;
-  int cntvertices, k;
-  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
-
-  qh_geomplanes(facet, &outerplane, &innerplane);
-  vertices= qh_facet3vertex(facet); /* oriented */
-  cntvertices= qh_setsize(vertices);
-  projectedpoints= qh_settemp(cntvertices);
-  FOREACHvertex_(vertices) {
-    zinc_(Zdistio);
-    qh_distplane(vertex->point, facet, &dist);
-    projpt= qh_projectpoint(vertex->point, facet, dist);
-    qh_setappend(&projectedpoints, projpt);
-  }
-  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
-    qh_printfacet3geom_points(fp, projectedpoints, facet, outerplane, color);
-  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
-                outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
-    for (k=3; k--; )
-      color[k]= 1.0 - color[k];
-    qh_printfacet3geom_points(fp, projectedpoints, facet, innerplane, color);
-  }
-  FOREACHpoint_(projectedpoints)
-    qh_memfree(point, qh normal_size);
-  qh_settempfree(&projectedpoints);
-  qh_settempfree(&vertices);
-  if ((qh DOintersections || qh PRINTridges)
-  && (!facet->visible || !qh NEWfacets)) {
-    facet->visitid= qh visit_id;
-    FOREACHridge_(facet->ridges) {
-      neighbor= otherfacet_(ridge, facet);
-      if (neighbor->visitid != qh visit_id) {
-        if (qh DOintersections)
-          qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, black);
-        if (qh PRINTridges) {
-          vertexA= SETfirstt_(ridge->vertices, vertexT);
-          vertexB= SETsecondt_(ridge->vertices, vertexT);
-          qh_printline3geom(fp, vertexA->point, vertexB->point, green);
-        }
-      }
-    }
-  }
-} /* printfacet3geom_nonsimplicial */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet3geom_points">-</a>
-
-  qh_printfacet3geom_points( fp, points, facet, offset )
-    prints a 3-d facet as OFF Geomview object.
-    offset is relative to the facet's hyperplane
-    Facet is determined as a list of points
-*/
-void qh_printfacet3geom_points(FILE *fp, setT *points, facetT *facet, realT offset, realT color[3]) {
-  int k, n= qh_setsize(points), i;
-  pointT *point, **pointp;
-  setT *printpoints;
-
-  qh_fprintf(fp, 9098, "{ OFF %d 1 1 # f%d\n", n, facet->id);
-  if (offset != 0.0) {
-    printpoints= qh_settemp(n);
-    FOREACHpoint_(points)
-      qh_setappend(&printpoints, qh_projectpoint(point, facet, -offset));
-  }else
-    printpoints= points;
-  FOREACHpoint_(printpoints) {
-    for (k=0; k < qh hull_dim; k++) {
-      if (k == qh DROPdim)
-        qh_fprintf(fp, 9099, "0 ");
-      else
-        qh_fprintf(fp, 9100, "%8.4g ", point[k]);
-    }
-    if (printpoints != points)
-      qh_memfree(point, qh normal_size);
-    qh_fprintf(fp, 9101, "\n");
-  }
-  if (printpoints != points)
-    qh_settempfree(&printpoints);
-  qh_fprintf(fp, 9102, "%d ", n);
-  for (i=0; i < n; i++)
-    qh_fprintf(fp, 9103, "%d ", i);
-  qh_fprintf(fp, 9104, "%8.4g %8.4g %8.4g 1.0 }\n", color[0], color[1], color[2]);
-} /* printfacet3geom_points */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet3geom_simplicial">-</a>
-
-  qh_printfacet3geom_simplicial(  )
-    print Geomview OFF for a 3-d simplicial facet.
-
-  notes:
-    may flip color
-    uses facet->visitid for intersections and ridges
-
-    assume precise calculations in io.c with roundoff covered by qh_GEOMepsilon
-    innerplane may be off by qh DISTround.  Maxoutside is calculated elsewhere
-    so a DISTround error may have occurred.
-*/
-void qh_printfacet3geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
-  setT *points, *vertices;
-  vertexT *vertex, **vertexp, *vertexA, *vertexB;
-  facetT *neighbor, **neighborp;
-  realT outerplane, innerplane;
-  realT black[3]={0, 0, 0}, green[3]={0, 1, 0};
-  int k;
-
-  qh_geomplanes(facet, &outerplane, &innerplane);
-  vertices= qh_facet3vertex(facet);
-  points= qh_settemp(qh TEMPsize);
-  FOREACHvertex_(vertices)
-    qh_setappend(&points, vertex->point);
-  if (qh PRINTouter || (!qh PRINTnoplanes && !qh PRINTinner))
-    qh_printfacet3geom_points(fp, points, facet, outerplane, color);
-  if (qh PRINTinner || (!qh PRINTnoplanes && !qh PRINTouter &&
-              outerplane - innerplane > 2 * qh MAXabs_coord * qh_GEOMepsilon)) {
-    for (k=3; k--; )
-      color[k]= 1.0 - color[k];
-    qh_printfacet3geom_points(fp, points, facet, innerplane, color);
-  }
-  qh_settempfree(&points);
-  qh_settempfree(&vertices);
-  if ((qh DOintersections || qh PRINTridges)
-  && (!facet->visible || !qh NEWfacets)) {
-    facet->visitid= qh visit_id;
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid != qh visit_id) {
-        vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
-                          SETindex_(facet->neighbors, neighbor), 0);
-        if (qh DOintersections)
-           qh_printhyperplaneintersection(fp, facet, neighbor, vertices, black);
-        if (qh PRINTridges) {
-          vertexA= SETfirstt_(vertices, vertexT);
-          vertexB= SETsecondt_(vertices, vertexT);
-          qh_printline3geom(fp, vertexA->point, vertexB->point, green);
-        }
-        qh_setfree(&vertices);
-      }
-    }
-  }
-} /* printfacet3geom_simplicial */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet3math">-</a>
-
-  qh_printfacet3math( fp, facet, notfirst )
-    print 3-d Maple or Mathematica output for a facet
-
-  notes:
-    may be non-simplicial
-    use %16.8f since Mathematica 2.2 does not handle exponential format
-    see qh_printfacet2math
-*/
-void qh_printfacet3math(FILE *fp, facetT *facet, qh_PRINT format, int notfirst) {
-  vertexT *vertex, **vertexp;
-  setT *points, *vertices;
-  pointT *point, **pointp;
-  boolT firstpoint= True;
-  realT dist;
-  const char *pointfmt, *endfmt;
-
-  if (notfirst)
-    qh_fprintf(fp, 9105, ",\n");
-  vertices= qh_facet3vertex(facet);
-  points= qh_settemp(qh_setsize(vertices));
-  FOREACHvertex_(vertices) {
-    zinc_(Zdistio);
-    qh_distplane(vertex->point, facet, &dist);
-    point= qh_projectpoint(vertex->point, facet, dist);
-    qh_setappend(&points, point);
-  }
-  if (format == qh_PRINTmaple) {
-    qh_fprintf(fp, 9106, "[");
-    pointfmt= "[%16.8f, %16.8f, %16.8f]";
-    endfmt= "]";
-  }else {
-    qh_fprintf(fp, 9107, "Polygon[{");
-    pointfmt= "{%16.8f, %16.8f, %16.8f}";
-    endfmt= "}]";
-  }
-  FOREACHpoint_(points) {
-    if (firstpoint)
-      firstpoint= False;
-    else
-      qh_fprintf(fp, 9108, ",\n");
-    qh_fprintf(fp, 9109, pointfmt, point[0], point[1], point[2]);
-  }
-  FOREACHpoint_(points)
-    qh_memfree(point, qh normal_size);
-  qh_settempfree(&points);
-  qh_settempfree(&vertices);
-  qh_fprintf(fp, 9110, endfmt);
-} /* printfacet3math */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet3vertex">-</a>
-
-  qh_printfacet3vertex( fp, facet, format )
-    print vertices in a 3-d facet as point ids
-
-  notes:
-    prints number of vertices first if format == qh_PRINToff
-    the facet may be non-simplicial
-*/
-void qh_printfacet3vertex(FILE *fp, facetT *facet, qh_PRINT format) {
-  vertexT *vertex, **vertexp;
-  setT *vertices;
-
-  vertices= qh_facet3vertex(facet);
-  if (format == qh_PRINToff)
-    qh_fprintf(fp, 9111, "%d ", qh_setsize(vertices));
-  FOREACHvertex_(vertices)
-    qh_fprintf(fp, 9112, "%d ", qh_pointid(vertex->point));
-  qh_fprintf(fp, 9113, "\n");
-  qh_settempfree(&vertices);
-} /* printfacet3vertex */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet4geom_nonsimplicial">-</a>
-
-  qh_printfacet4geom_nonsimplicial(  )
-    print Geomview 4OFF file for a 4d nonsimplicial facet
-    prints all ridges to unvisited neighbors (qh.visit_id)
-    if qh.DROPdim
-      prints in OFF format
-
-  notes:
-    must agree with printend4geom()
-*/
-void qh_printfacet4geom_nonsimplicial(FILE *fp, facetT *facet, realT color[3]) {
-  facetT *neighbor;
-  ridgeT *ridge, **ridgep;
-  vertexT *vertex, **vertexp;
-  pointT *point;
-  int k;
-  realT dist;
-
-  facet->visitid= qh visit_id;
-  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
-    return;
-  FOREACHridge_(facet->ridges) {
-    neighbor= otherfacet_(ridge, facet);
-    if (neighbor->visitid == qh visit_id)
-      continue;
-    if (qh PRINTtransparent && !neighbor->good)
-      continue;
-    if (qh DOintersections)
-      qh_printhyperplaneintersection(fp, facet, neighbor, ridge->vertices, color);
-    else {
-      if (qh DROPdim >= 0)
-        qh_fprintf(fp, 9114, "OFF 3 1 1 # f%d\n", facet->id);
-      else {
-        qh printoutvar++;
-        qh_fprintf(fp, 9115, "# r%d between f%d f%d\n", ridge->id, facet->id, neighbor->id);
-      }
-      FOREACHvertex_(ridge->vertices) {
-        zinc_(Zdistio);
-        qh_distplane(vertex->point,facet, &dist);
-        point=qh_projectpoint(vertex->point,facet, dist);
-        for (k=0; k < qh hull_dim; k++) {
-          if (k != qh DROPdim)
-            qh_fprintf(fp, 9116, "%8.4g ", point[k]);
-        }
-        qh_fprintf(fp, 9117, "\n");
-        qh_memfree(point, qh normal_size);
-      }
-      if (qh DROPdim >= 0)
-        qh_fprintf(fp, 9118, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
-    }
-  }
-} /* printfacet4geom_nonsimplicial */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacet4geom_simplicial">-</a>
-
-  qh_printfacet4geom_simplicial( fp, facet, color )
-    print Geomview 4OFF file for a 4d simplicial facet
-    prints triangles for unvisited neighbors (qh.visit_id)
-
-  notes:
-    must agree with printend4geom()
-*/
-void qh_printfacet4geom_simplicial(FILE *fp, facetT *facet, realT color[3]) {
-  setT *vertices;
-  facetT *neighbor, **neighborp;
-  vertexT *vertex, **vertexp;
-  int k;
-
-  facet->visitid= qh visit_id;
-  if (qh PRINTnoplanes || (facet->visible && qh NEWfacets))
-    return;
-  FOREACHneighbor_(facet) {
-    if (neighbor->visitid == qh visit_id)
-      continue;
-    if (qh PRINTtransparent && !neighbor->good)
-      continue;
-    vertices= qh_setnew_delnthsorted(facet->vertices, qh hull_dim,
-                          SETindex_(facet->neighbors, neighbor), 0);
-    if (qh DOintersections)
-      qh_printhyperplaneintersection(fp, facet, neighbor, vertices, color);
-    else {
-      if (qh DROPdim >= 0)
-        qh_fprintf(fp, 9119, "OFF 3 1 1 # ridge between f%d f%d\n",
-                facet->id, neighbor->id);
-      else {
-        qh printoutvar++;
-        qh_fprintf(fp, 9120, "# ridge between f%d f%d\n", facet->id, neighbor->id);
-      }
-      FOREACHvertex_(vertices) {
-        for (k=0; k < qh hull_dim; k++) {
-          if (k != qh DROPdim)
-            qh_fprintf(fp, 9121, "%8.4g ", vertex->point[k]);
-        }
-        qh_fprintf(fp, 9122, "\n");
-      }
-      if (qh DROPdim >= 0)
-        qh_fprintf(fp, 9123, "3 0 1 2 %8.4g %8.4g %8.4g\n", color[0], color[1], color[2]);
-    }
-    qh_setfree(&vertices);
-  }
-} /* printfacet4geom_simplicial */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacetNvertex_nonsimplicial">-</a>
-
-  qh_printfacetNvertex_nonsimplicial( fp, facet, id, format )
-    print vertices for an N-d non-simplicial facet
-    triangulates each ridge to the id
-*/
-void qh_printfacetNvertex_nonsimplicial(FILE *fp, facetT *facet, int id, qh_PRINT format) {
-  vertexT *vertex, **vertexp;
-  ridgeT *ridge, **ridgep;
-
-  if (facet->visible && qh NEWfacets)
-    return;
-  FOREACHridge_(facet->ridges) {
-    if (format == qh_PRINTtriangles)
-      qh_fprintf(fp, 9124, "%d ", qh hull_dim);
-    qh_fprintf(fp, 9125, "%d ", id);
-    if ((ridge->top == facet) ^ qh_ORIENTclock) {
-      FOREACHvertex_(ridge->vertices)
-        qh_fprintf(fp, 9126, "%d ", qh_pointid(vertex->point));
-    }else {
-      FOREACHvertexreverse12_(ridge->vertices)
-        qh_fprintf(fp, 9127, "%d ", qh_pointid(vertex->point));
-    }
-    qh_fprintf(fp, 9128, "\n");
-  }
-} /* printfacetNvertex_nonsimplicial */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacetNvertex_simplicial">-</a>
-
-  qh_printfacetNvertex_simplicial( fp, facet, format )
-    print vertices for an N-d simplicial facet
-    prints vertices for non-simplicial facets
-      2-d facets (orientation preserved by qh_mergefacet2d)
-      PRINToff ('o') for 4-d and higher
-*/
-void qh_printfacetNvertex_simplicial(FILE *fp, facetT *facet, qh_PRINT format) {
-  vertexT *vertex, **vertexp;
-
-  if (format == qh_PRINToff || format == qh_PRINTtriangles)
-    qh_fprintf(fp, 9129, "%d ", qh_setsize(facet->vertices));
-  if ((facet->toporient ^ qh_ORIENTclock)
-  || (qh hull_dim > 2 && !facet->simplicial)) {
-    FOREACHvertex_(facet->vertices)
-      qh_fprintf(fp, 9130, "%d ", qh_pointid(vertex->point));
-  }else {
-    FOREACHvertexreverse12_(facet->vertices)
-      qh_fprintf(fp, 9131, "%d ", qh_pointid(vertex->point));
-  }
-  qh_fprintf(fp, 9132, "\n");
-} /* printfacetNvertex_simplicial */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacetheader">-</a>
-
-  qh_printfacetheader( fp, facet )
-    prints header fields of a facet to fp
-
-  notes:
-    for 'f' output and debugging
-    Same as QhullFacet::printHeader()
-*/
-void qh_printfacetheader(FILE *fp, facetT *facet) {
-  pointT *point, **pointp, *furthest;
-  facetT *neighbor, **neighborp;
-  realT dist;
-
-  if (facet == qh_MERGEridge) {
-    qh_fprintf(fp, 9133, " MERGEridge\n");
-    return;
-  }else if (facet == qh_DUPLICATEridge) {
-    qh_fprintf(fp, 9134, " DUPLICATEridge\n");
-    return;
-  }else if (!facet) {
-    qh_fprintf(fp, 9135, " NULLfacet\n");
-    return;
-  }
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  qh_fprintf(fp, 9136, "- f%d\n", facet->id);
-  qh_fprintf(fp, 9137, "    - flags:");
-  if (facet->toporient)
-    qh_fprintf(fp, 9138, " top");
-  else
-    qh_fprintf(fp, 9139, " bottom");
-  if (facet->simplicial)
-    qh_fprintf(fp, 9140, " simplicial");
-  if (facet->tricoplanar)
-    qh_fprintf(fp, 9141, " tricoplanar");
-  if (facet->upperdelaunay)
-    qh_fprintf(fp, 9142, " upperDelaunay");
-  if (facet->visible)
-    qh_fprintf(fp, 9143, " visible");
-  if (facet->newfacet)
-    qh_fprintf(fp, 9144, " new");
-  if (facet->tested)
-    qh_fprintf(fp, 9145, " tested");
-  if (!facet->good)
-    qh_fprintf(fp, 9146, " notG");
-  if (facet->seen)
-    qh_fprintf(fp, 9147, " seen");
-  if (facet->coplanar)
-    qh_fprintf(fp, 9148, " coplanar");
-  if (facet->mergehorizon)
-    qh_fprintf(fp, 9149, " mergehorizon");
-  if (facet->keepcentrum)
-    qh_fprintf(fp, 9150, " keepcentrum");
-  if (facet->dupridge)
-    qh_fprintf(fp, 9151, " dupridge");
-  if (facet->mergeridge && !facet->mergeridge2)
-    qh_fprintf(fp, 9152, " mergeridge1");
-  if (facet->mergeridge2)
-    qh_fprintf(fp, 9153, " mergeridge2");
-  if (facet->newmerge)
-    qh_fprintf(fp, 9154, " newmerge");
-  if (facet->flipped)
-    qh_fprintf(fp, 9155, " flipped");
-  if (facet->notfurthest)
-    qh_fprintf(fp, 9156, " notfurthest");
-  if (facet->degenerate)
-    qh_fprintf(fp, 9157, " degenerate");
-  if (facet->redundant)
-    qh_fprintf(fp, 9158, " redundant");
-  qh_fprintf(fp, 9159, "\n");
-  if (facet->isarea)
-    qh_fprintf(fp, 9160, "    - area: %2.2g\n", facet->f.area);
-  else if (qh NEWfacets && facet->visible && facet->f.replace)
-    qh_fprintf(fp, 9161, "    - replacement: f%d\n", facet->f.replace->id);
-  else if (facet->newfacet) {
-    if (facet->f.samecycle && facet->f.samecycle != facet)
-      qh_fprintf(fp, 9162, "    - shares same visible/horizon as f%d\n", facet->f.samecycle->id);
-  }else if (facet->tricoplanar /* !isarea */) {
-    if (facet->f.triowner)
-      qh_fprintf(fp, 9163, "    - owner of normal & centrum is facet f%d\n", facet->f.triowner->id);
-  }else if (facet->f.newcycle)
-    qh_fprintf(fp, 9164, "    - was horizon to f%d\n", facet->f.newcycle->id);
-  if (facet->nummerge)
-    qh_fprintf(fp, 9165, "    - merges: %d\n", facet->nummerge);
-  qh_printpointid(fp, "    - normal: ", qh hull_dim, facet->normal, -1);
-  qh_fprintf(fp, 9166, "    - offset: %10.7g\n", facet->offset);
-  if (qh CENTERtype == qh_ASvoronoi || facet->center)
-    qh_printcenter(fp, qh_PRINTfacets, "    - center: ", facet);
-#if qh_MAXoutside
-  if (facet->maxoutside > qh DISTround)
-    qh_fprintf(fp, 9167, "    - maxoutside: %10.7g\n", facet->maxoutside);
-#endif
-  if (!SETempty_(facet->outsideset)) {
-    furthest= (pointT*)qh_setlast(facet->outsideset);
-    if (qh_setsize(facet->outsideset) < 6) {
-      qh_fprintf(fp, 9168, "    - outside set(furthest p%d):\n", qh_pointid(furthest));
-      FOREACHpoint_(facet->outsideset)
-        qh_printpoint(fp, "     ", point);
-    }else if (qh_setsize(facet->outsideset) < 21) {
-      qh_printpoints(fp, "    - outside set:", facet->outsideset);
-    }else {
-      qh_fprintf(fp, 9169, "    - outside set:  %d points.", qh_setsize(facet->outsideset));
-      qh_printpoint(fp, "  Furthest", furthest);
-    }
-#if !qh_COMPUTEfurthest
-    qh_fprintf(fp, 9170, "    - furthest distance= %2.2g\n", facet->furthestdist);
-#endif
-  }
-  if (!SETempty_(facet->coplanarset)) {
-    furthest= (pointT*)qh_setlast(facet->coplanarset);
-    if (qh_setsize(facet->coplanarset) < 6) {
-      qh_fprintf(fp, 9171, "    - coplanar set(furthest p%d):\n", qh_pointid(furthest));
-      FOREACHpoint_(facet->coplanarset)
-        qh_printpoint(fp, "     ", point);
-    }else if (qh_setsize(facet->coplanarset) < 21) {
-      qh_printpoints(fp, "    - coplanar set:", facet->coplanarset);
-    }else {
-      qh_fprintf(fp, 9172, "    - coplanar set:  %d points.", qh_setsize(facet->coplanarset));
-      qh_printpoint(fp, "  Furthest", furthest);
-    }
-    zinc_(Zdistio);
-    qh_distplane(furthest, facet, &dist);
-    qh_fprintf(fp, 9173, "      furthest distance= %2.2g\n", dist);
-  }
-  qh_printvertices(fp, "    - vertices:", facet->vertices);
-  qh_fprintf(fp, 9174, "    - neighboring facets:");
-  FOREACHneighbor_(facet) {
-    if (neighbor == qh_MERGEridge)
-      qh_fprintf(fp, 9175, " MERGE");
-    else if (neighbor == qh_DUPLICATEridge)
-      qh_fprintf(fp, 9176, " DUP");
-    else
-      qh_fprintf(fp, 9177, " f%d", neighbor->id);
-  }
-  qh_fprintf(fp, 9178, "\n");
-  qh RANDOMdist= qh old_randomdist;
-} /* printfacetheader */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacetridges">-</a>
-
-  qh_printfacetridges( fp, facet )
-    prints ridges of a facet to fp
-
-  notes:
-    ridges printed in neighbor order
-    assumes the ridges exist
-    for 'f' output
-    same as QhullFacet::printRidges
-*/
-void qh_printfacetridges(FILE *fp, facetT *facet) {
-  facetT *neighbor, **neighborp;
-  ridgeT *ridge, **ridgep;
-  int numridges= 0;
-
-
-  if (facet->visible && qh NEWfacets) {
-    qh_fprintf(fp, 9179, "    - ridges(ids may be garbage):");
-    FOREACHridge_(facet->ridges)
-      qh_fprintf(fp, 9180, " r%d", ridge->id);
-    qh_fprintf(fp, 9181, "\n");
-  }else {
-    qh_fprintf(fp, 9182, "    - ridges:\n");
-    FOREACHridge_(facet->ridges)
-      ridge->seen= False;
-    if (qh hull_dim == 3) {
-      ridge= SETfirstt_(facet->ridges, ridgeT);
-      while (ridge && !ridge->seen) {
-        ridge->seen= True;
-        qh_printridge(fp, ridge);
-        numridges++;
-        ridge= qh_nextridge3d(ridge, facet, NULL);
-        }
-    }else {
-      FOREACHneighbor_(facet) {
-        FOREACHridge_(facet->ridges) {
-          if (otherfacet_(ridge,facet) == neighbor) {
-            ridge->seen= True;
-            qh_printridge(fp, ridge);
-            numridges++;
-          }
-        }
-      }
-    }
-    if (numridges != qh_setsize(facet->ridges)) {
-      qh_fprintf(fp, 9183, "     - all ridges:");
-      FOREACHridge_(facet->ridges)
-        qh_fprintf(fp, 9184, " r%d", ridge->id);
-        qh_fprintf(fp, 9185, "\n");
-    }
-    FOREACHridge_(facet->ridges) {
-      if (!ridge->seen)
-        qh_printridge(fp, ridge);
-    }
-  }
-} /* printfacetridges */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printfacets">-</a>
-
-  qh_printfacets( fp, format, facetlist, facets, printall )
-    prints facetlist and/or facet set in output format
-
-  notes:
-    also used for specialized formats ('FO' and summary)
-    turns off 'Rn' option since want actual numbers
-*/
-void qh_printfacets(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  int numfacets, numsimplicial, numridges, totneighbors, numcoplanars, numtricoplanars;
-  facetT *facet, **facetp;
-  setT *vertices;
-  coordT *center;
-  realT outerplane, innerplane;
-
-  qh old_randomdist= qh RANDOMdist;
-  qh RANDOMdist= False;
-  if (qh CDDoutput && (format == qh_PRINTcentrums || format == qh_PRINTpointintersect || format == qh_PRINToff))
-    qh_fprintf(qh ferr, 7056, "qhull warning: CDD format is not available for centrums, halfspace\nintersections, and OFF file format.\n");
-  if (format == qh_PRINTnone)
-    ; /* print nothing */
-  else if (format == qh_PRINTaverage) {
-    vertices= qh_facetvertices(facetlist, facets, printall);
-    center= qh_getcenter(vertices);
-    qh_fprintf(fp, 9186, "%d 1\n", qh hull_dim);
-    qh_printpointid(fp, NULL, qh hull_dim, center, -1);
-    qh_memfree(center, qh normal_size);
-    qh_settempfree(&vertices);
-  }else if (format == qh_PRINTextremes) {
-    if (qh DELAUNAY)
-      qh_printextremes_d(fp, facetlist, facets, printall);
-    else if (qh hull_dim == 2)
-      qh_printextremes_2d(fp, facetlist, facets, printall);
-    else
-      qh_printextremes(fp, facetlist, facets, printall);
-  }else if (format == qh_PRINToptions)
-    qh_fprintf(fp, 9187, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
-  else if (format == qh_PRINTpoints && !qh VORONOI)
-    qh_printpoints_out(fp, facetlist, facets, printall);
-  else if (format == qh_PRINTqhull)
-    qh_fprintf(fp, 9188, "%s | %s\n", qh rbox_command, qh qhull_command);
-  else if (format == qh_PRINTsize) {
-    qh_fprintf(fp, 9189, "0\n2 ");
-    qh_fprintf(fp, 9190, qh_REAL_1, qh totarea);
-    qh_fprintf(fp, 9191, qh_REAL_1, qh totvol);
-    qh_fprintf(fp, 9192, "\n");
-  }else if (format == qh_PRINTsummary) {
-    qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);
-    vertices= qh_facetvertices(facetlist, facets, printall);
-    qh_fprintf(fp, 9193, "10 %d %d %d %d %d %d %d %d %d %d\n2 ", qh hull_dim,
-                qh num_points + qh_setsize(qh other_points),
-                qh num_vertices, qh num_facets - qh num_visible,
-                qh_setsize(vertices), numfacets, numcoplanars,
-                numfacets - numsimplicial, zzval_(Zdelvertextot),
-                numtricoplanars);
-    qh_settempfree(&vertices);
-    qh_outerinner(NULL, &outerplane, &innerplane);
-    qh_fprintf(fp, 9194, qh_REAL_2n, outerplane, innerplane);
-  }else if (format == qh_PRINTvneighbors)
-    qh_printvneighbors(fp, facetlist, facets, printall);
-  else if (qh VORONOI && format == qh_PRINToff)
-    qh_printvoronoi(fp, format, facetlist, facets, printall);
-  else if (qh VORONOI && format == qh_PRINTgeom) {
-    qh_printbegin(fp, format, facetlist, facets, printall);
-    qh_printvoronoi(fp, format, facetlist, facets, printall);
-    qh_printend(fp, format, facetlist, facets, printall);
-  }else if (qh VORONOI
-  && (format == qh_PRINTvertices || format == qh_PRINTinner || format == qh_PRINTouter))
-    qh_printvdiagram(fp, format, facetlist, facets, printall);
-  else {
-    qh_printbegin(fp, format, facetlist, facets, printall);
-    FORALLfacet_(facetlist)
-      qh_printafacet(fp, format, facet, printall);
-    FOREACHfacet_(facets)
-      qh_printafacet(fp, format, facet, printall);
-    qh_printend(fp, format, facetlist, facets, printall);
-  }
-  qh RANDOMdist= qh old_randomdist;
-} /* printfacets */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printhyperplaneintersection">-</a>
-
-  qh_printhyperplaneintersection( fp, facet1, facet2, vertices, color )
-    print Geomview OFF or 4OFF for the intersection of two hyperplanes in 3-d or 4-d
-*/
-void qh_printhyperplaneintersection(FILE *fp, facetT *facet1, facetT *facet2,
-                   setT *vertices, realT color[3]) {
-  realT costheta, denominator, dist1, dist2, s, t, mindenom, p[4];
-  vertexT *vertex, **vertexp;
-  int i, k;
-  boolT nearzero1, nearzero2;
-
-  costheta= qh_getangle(facet1->normal, facet2->normal);
-  denominator= 1 - costheta * costheta;
-  i= qh_setsize(vertices);
-  if (qh hull_dim == 3)
-    qh_fprintf(fp, 9195, "VECT 1 %d 1 %d 1 ", i, i);
-  else if (qh hull_dim == 4 && qh DROPdim >= 0)
-    qh_fprintf(fp, 9196, "OFF 3 1 1 ");
-  else
-    qh printoutvar++;
-  qh_fprintf(fp, 9197, "# intersect f%d f%d\n", facet1->id, facet2->id);
-  mindenom= 1 / (10.0 * qh MAXabs_coord);
-  FOREACHvertex_(vertices) {
-    zadd_(Zdistio, 2);
-    qh_distplane(vertex->point, facet1, &dist1);
-    qh_distplane(vertex->point, facet2, &dist2);
-    s= qh_divzero(-dist1 + costheta * dist2, denominator,mindenom,&nearzero1);
-    t= qh_divzero(-dist2 + costheta * dist1, denominator,mindenom,&nearzero2);
-    if (nearzero1 || nearzero2)
-      s= t= 0.0;
-    for (k=qh hull_dim; k--; )
-      p[k]= vertex->point[k] + facet1->normal[k] * s + facet2->normal[k] * t;
-    if (qh PRINTdim <= 3) {
-      qh_projectdim3 (p, p);
-      qh_fprintf(fp, 9198, "%8.4g %8.4g %8.4g # ", p[0], p[1], p[2]);
-    }else
-      qh_fprintf(fp, 9199, "%8.4g %8.4g %8.4g %8.4g # ", p[0], p[1], p[2], p[3]);
-    if (nearzero1+nearzero2)
-      qh_fprintf(fp, 9200, "p%d(coplanar facets)\n", qh_pointid(vertex->point));
-    else
-      qh_fprintf(fp, 9201, "projected p%d\n", qh_pointid(vertex->point));
-  }
-  if (qh hull_dim == 3)
-    qh_fprintf(fp, 9202, "%8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-  else if (qh hull_dim == 4 && qh DROPdim >= 0)
-    qh_fprintf(fp, 9203, "3 0 1 2 %8.4g %8.4g %8.4g 1.0\n", color[0], color[1], color[2]);
-} /* printhyperplaneintersection */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printline3geom">-</a>
-
-  qh_printline3geom( fp, pointA, pointB, color )
-    prints a line as a VECT
-    prints 0's for qh.DROPdim
-
-  notes:
-    if pointA == pointB,
-      it's a 1 point VECT
-*/
-void qh_printline3geom(FILE *fp, pointT *pointA, pointT *pointB, realT color[3]) {
-  int k;
-  realT pA[4], pB[4];
-
-  qh_projectdim3(pointA, pA);
-  qh_projectdim3(pointB, pB);
-  if ((fabs(pA[0] - pB[0]) > 1e-3) ||
-      (fabs(pA[1] - pB[1]) > 1e-3) ||
-      (fabs(pA[2] - pB[2]) > 1e-3)) {
-    qh_fprintf(fp, 9204, "VECT 1 2 1 2 1\n");
-    for (k=0; k < 3; k++)
-       qh_fprintf(fp, 9205, "%8.4g ", pB[k]);
-    qh_fprintf(fp, 9206, " # p%d\n", qh_pointid(pointB));
-  }else
-    qh_fprintf(fp, 9207, "VECT 1 1 1 1 1\n");
-  for (k=0; k < 3; k++)
-    qh_fprintf(fp, 9208, "%8.4g ", pA[k]);
-  qh_fprintf(fp, 9209, " # p%d\n", qh_pointid(pointA));
-  qh_fprintf(fp, 9210, "%8.4g %8.4g %8.4g 1\n", color[0], color[1], color[2]);
-}
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printneighborhood">-</a>
-
-  qh_printneighborhood( fp, format, facetA, facetB, printall )
-    print neighborhood of one or two facets
-
-  notes:
-    calls qh_findgood_all()
-    bumps qh.visit_id
-*/
-void qh_printneighborhood(FILE *fp, qh_PRINT format, facetT *facetA, facetT *facetB, boolT printall) {
-  facetT *neighbor, **neighborp, *facet;
-  setT *facets;
-
-  if (format == qh_PRINTnone)
-    return;
-  qh_findgood_all(qh facet_list);
-  if (facetA == facetB)
-    facetB= NULL;
-  facets= qh_settemp(2*(qh_setsize(facetA->neighbors)+1));
-  qh visit_id++;
-  for (facet= facetA; facet; facet= ((facet == facetA) ? facetB : NULL)) {
-    if (facet->visitid != qh visit_id) {
-      facet->visitid= qh visit_id;
-      qh_setappend(&facets, facet);
-    }
-    FOREACHneighbor_(facet) {
-      if (neighbor->visitid == qh visit_id)
-        continue;
-      neighbor->visitid= qh visit_id;
-      if (printall || !qh_skipfacet(neighbor))
-        qh_setappend(&facets, neighbor);
-    }
-  }
-  qh_printfacets(fp, format, NULL, facets, printall);
-  qh_settempfree(&facets);
-} /* printneighborhood */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printpoint">-</a>
-
-  qh_printpoint( fp, string, point )
-  qh_printpointid( fp, string, dim, point, id )
-    prints the coordinates of a point
-
-  returns:
-    if string is defined
-      prints 'string p%d' (skips p%d if id=-1)
-
-  notes:
-    nop if point is NULL
-    prints id unless it is undefined (-1)
-    Same as QhullPoint's printPoint
-*/
-void qh_printpoint(FILE *fp, const char *string, pointT *point) {
-  int id= qh_pointid( point);
-
-  qh_printpointid( fp, string, qh hull_dim, point, id);
-} /* printpoint */
-
-void qh_printpointid(FILE *fp, const char *string, int dim, pointT *point, int id) {
-  int k;
-  realT r; /*bug fix*/
-
-  if (!point)
-    return;
-  if (string) {
-    qh_fprintf(fp, 9211, "%s", string);
-   if (id != -1)
-      qh_fprintf(fp, 9212, " p%d: ", id);
-  }
-  for (k=dim; k--; ) {
-    r= *point++;
-    if (string)
-      qh_fprintf(fp, 9213, " %8.4g", r);
-    else
-      qh_fprintf(fp, 9214, qh_REAL_1, r);
-  }
-  qh_fprintf(fp, 9215, "\n");
-} /* printpointid */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printpoint3">-</a>
-
-  qh_printpoint3( fp, point )
-    prints 2-d, 3-d, or 4-d point as Geomview 3-d coordinates
-*/
-void qh_printpoint3 (FILE *fp, pointT *point) {
-  int k;
-  realT p[4];
-
-  qh_projectdim3 (point, p);
-  for (k=0; k < 3; k++)
-    qh_fprintf(fp, 9216, "%8.4g ", p[k]);
-  qh_fprintf(fp, 9217, " # p%d\n", qh_pointid(point));
-} /* printpoint3 */
-
-/*----------------------------------------
--printpoints- print pointids for a set of points starting at index
-   see geom.c
-*/
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printpoints_out">-</a>
-
-  qh_printpoints_out( fp, facetlist, facets, printall )
-    prints vertices, coplanar/inside points, for facets by their point coordinates
-    allows qh.CDDoutput
-
-  notes:
-    same format as qhull input
-    if no coplanar/interior points,
-      same order as qh_printextremes
-*/
-void qh_printpoints_out(FILE *fp, facetT *facetlist, setT *facets, boolT printall) {
-  int allpoints= qh num_points + qh_setsize(qh other_points);
-  int numpoints=0, point_i, point_n;
-  setT *vertices, *points;
-  facetT *facet, **facetp;
-  pointT *point, **pointp;
-  vertexT *vertex, **vertexp;
-  int id;
-
-  points= qh_settemp(allpoints);
-  qh_setzero(points, 0, allpoints);
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  FOREACHvertex_(vertices) {
-    id= qh_pointid(vertex->point);
-    if (id >= 0)
-      SETelem_(points, id)= vertex->point;
-  }
-  if (qh KEEPinside || qh KEEPcoplanar || qh KEEPnearinside) {
-    FORALLfacet_(facetlist) {
-      if (!printall && qh_skipfacet(facet))
-        continue;
-      FOREACHpoint_(facet->coplanarset) {
-        id= qh_pointid(point);
-        if (id >= 0)
-          SETelem_(points, id)= point;
-      }
-    }
-    FOREACHfacet_(facets) {
-      if (!printall && qh_skipfacet(facet))
-        continue;
-      FOREACHpoint_(facet->coplanarset) {
-        id= qh_pointid(point);
-        if (id >= 0)
-          SETelem_(points, id)= point;
-      }
-    }
-  }
-  qh_settempfree(&vertices);
-  FOREACHpoint_i_(points) {
-    if (point)
-      numpoints++;
-  }
-  if (qh CDDoutput)
-    qh_fprintf(fp, 9218, "%s | %s\nbegin\n%d %d real\n", qh rbox_command,
-             qh qhull_command, numpoints, qh hull_dim + 1);
-  else
-    qh_fprintf(fp, 9219, "%d\n%d\n", qh hull_dim, numpoints);
-  FOREACHpoint_i_(points) {
-    if (point) {
-      if (qh CDDoutput)
-        qh_fprintf(fp, 9220, "1 ");
-      qh_printpoint(fp, NULL, point);
-    }
-  }
-  if (qh CDDoutput)
-    qh_fprintf(fp, 9221, "end\n");
-  qh_settempfree(&points);
-} /* printpoints_out */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printpointvect">-</a>
-
-  qh_printpointvect( fp, point, normal, center, radius, color )
-    prints a 2-d, 3-d, or 4-d point as 3-d VECT's relative to normal or to center point
-*/
-void qh_printpointvect(FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius, realT color[3]) {
-  realT diff[4], pointA[4];
-  int k;
-
-  for (k=qh hull_dim; k--; ) {
-    if (center)
-      diff[k]= point[k]-center[k];
-    else if (normal)
-      diff[k]= normal[k];
-    else
-      diff[k]= 0;
-  }
-  if (center)
-    qh_normalize2 (diff, qh hull_dim, True, NULL, NULL);
-  for (k=qh hull_dim; k--; )
-    pointA[k]= point[k]+diff[k] * radius;
-  qh_printline3geom(fp, point, pointA, color);
-} /* printpointvect */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printpointvect2">-</a>
-
-  qh_printpointvect2( fp, point, normal, center, radius )
-    prints a 2-d, 3-d, or 4-d point as 2 3-d VECT's for an imprecise point
-*/
-void qh_printpointvect2 (FILE *fp, pointT *point, coordT *normal, pointT *center, realT radius) {
-  realT red[3]={1, 0, 0}, yellow[3]={1, 1, 0};
-
-  qh_printpointvect(fp, point, normal, center, radius, red);
-  qh_printpointvect(fp, point, normal, center, -radius, yellow);
-} /* printpointvect2 */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printridge">-</a>
-
-  qh_printridge( fp, ridge )
-    prints the information in a ridge
-
-  notes:
-    for qh_printfacetridges()
-    same as operator<< [QhullRidge.cpp]
-*/
-void qh_printridge(FILE *fp, ridgeT *ridge) {
-
-  qh_fprintf(fp, 9222, "     - r%d", ridge->id);
-  if (ridge->tested)
-    qh_fprintf(fp, 9223, " tested");
-  if (ridge->nonconvex)
-    qh_fprintf(fp, 9224, " nonconvex");
-  qh_fprintf(fp, 9225, "\n");
-  qh_printvertices(fp, "           vertices:", ridge->vertices);
-  if (ridge->top && ridge->bottom)
-    qh_fprintf(fp, 9226, "           between f%d and f%d\n",
-            ridge->top->id, ridge->bottom->id);
-} /* printridge */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printspheres">-</a>
-
-  qh_printspheres( fp, vertices, radius )
-    prints 3-d vertices as OFF spheres
-
-  notes:
-    inflated octahedron from Stuart Levy earth/mksphere2
-*/
-void qh_printspheres(FILE *fp, setT *vertices, realT radius) {
-  vertexT *vertex, **vertexp;
-
-  qh printoutnum++;
-  qh_fprintf(fp, 9227, "{appearance {-edge -normal normscale 0} {\n\
-INST geom {define vsphere OFF\n\
-18 32 48\n\
-\n\
-0 0 1\n\
-1 0 0\n\
-0 1 0\n\
--1 0 0\n\
-0 -1 0\n\
-0 0 -1\n\
-0.707107 0 0.707107\n\
-0 -0.707107 0.707107\n\
-0.707107 -0.707107 0\n\
--0.707107 0 0.707107\n\
--0.707107 -0.707107 0\n\
-0 0.707107 0.707107\n\
--0.707107 0.707107 0\n\
-0.707107 0.707107 0\n\
-0.707107 0 -0.707107\n\
-0 0.707107 -0.707107\n\
--0.707107 0 -0.707107\n\
-0 -0.707107 -0.707107\n\
-\n\
-3 0 6 11\n\
-3 0 7 6 \n\
-3 0 9 7 \n\
-3 0 11 9\n\
-3 1 6 8 \n\
-3 1 8 14\n\
-3 1 13 6\n\
-3 1 14 13\n\
-3 2 11 13\n\
-3 2 12 11\n\
-3 2 13 15\n\
-3 2 15 12\n\
-3 3 9 12\n\
-3 3 10 9\n\
-3 3 12 16\n\
-3 3 16 10\n\
-3 4 7 10\n\
-3 4 8 7\n\
-3 4 10 17\n\
-3 4 17 8\n\
-3 5 14 17\n\
-3 5 15 14\n\
-3 5 16 15\n\
-3 5 17 16\n\
-3 6 13 11\n\
-3 7 8 6\n\
-3 9 10 7\n\
-3 11 12 9\n\
-3 14 8 17\n\
-3 15 13 14\n\
-3 16 12 15\n\
-3 17 10 16\n} transforms { TLIST\n");
-  FOREACHvertex_(vertices) {
-    qh_fprintf(fp, 9228, "%8.4g 0 0 0 # v%d\n 0 %8.4g 0 0\n0 0 %8.4g 0\n",
-      radius, vertex->id, radius, radius);
-    qh_printpoint3 (fp, vertex->point);
-    qh_fprintf(fp, 9229, "1\n");
-  }
-  qh_fprintf(fp, 9230, "}}}\n");
-} /* printspheres */
-
-
-/*----------------------------------------------
--printsummary-
-                see libqhull.c
-*/
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printvdiagram">-</a>
-
-  qh_printvdiagram( fp, format, facetlist, facets, printall )
-    print voronoi diagram
-      # of pairs of input sites
-      #indices site1 site2 vertex1 ...
-
-    sites indexed by input point id
-      point 0 is the first input point
-    vertices indexed by 'o' and 'p' order
-      vertex 0 is the 'vertex-at-infinity'
-      vertex 1 is the first Voronoi vertex
-
-  see:
-    qh_printvoronoi()
-    qh_eachvoronoi_all()
-
-  notes:
-    if all facets are upperdelaunay,
-      prints upper hull (furthest-site Voronoi diagram)
-*/
-void qh_printvdiagram(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  setT *vertices;
-  int totcount, numcenters;
-  boolT isLower;
-  qh_RIDGE innerouter= qh_RIDGEall;
-  printvridgeT printvridge= NULL;
-
-  if (format == qh_PRINTvertices) {
-    innerouter= qh_RIDGEall;
-    printvridge= qh_printvridge;
-  }else if (format == qh_PRINTinner) {
-    innerouter= qh_RIDGEinner;
-    printvridge= qh_printvnorm;
-  }else if (format == qh_PRINTouter) {
-    innerouter= qh_RIDGEouter;
-    printvridge= qh_printvnorm;
-  }else {
-    qh_fprintf(qh ferr, 6219, "Qhull internal error (qh_printvdiagram): unknown print format %d.\n", format);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
-  totcount= qh_printvdiagram2 (NULL, NULL, vertices, innerouter, False);
-  qh_fprintf(fp, 9231, "%d\n", totcount);
-  totcount= qh_printvdiagram2 (fp, printvridge, vertices, innerouter, True /* inorder*/);
-  qh_settempfree(&vertices);
-#if 0  /* for testing qh_eachvoronoi_all */
-  qh_fprintf(fp, 9232, "\n");
-  totcount= qh_eachvoronoi_all(fp, printvridge, qh UPPERdelaunay, innerouter, True /* inorder*/);
-  qh_fprintf(fp, 9233, "%d\n", totcount);
-#endif
-} /* printvdiagram */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printvdiagram2">-</a>
-
-  qh_printvdiagram2( fp, printvridge, vertices, innerouter, inorder )
-    visit all pairs of input sites (vertices) for selected Voronoi vertices
-    vertices may include NULLs
-
-  innerouter:
-    qh_RIDGEall   print inner ridges(bounded) and outer ridges(unbounded)
-    qh_RIDGEinner print only inner ridges
-    qh_RIDGEouter print only outer ridges
-
-  inorder:
-    print 3-d Voronoi vertices in order
-
-  assumes:
-    qh_markvoronoi marked facet->visitid for Voronoi vertices
-    all facet->seen= False
-    all facet->seen2= True
-
-  returns:
-    total number of Voronoi ridges
-    if printvridge,
-      calls printvridge( fp, vertex, vertexA, centers) for each ridge
-      [see qh_eachvoronoi()]
-
-  see:
-    qh_eachvoronoi_all()
-*/
-int qh_printvdiagram2 (FILE *fp, printvridgeT printvridge, setT *vertices, qh_RIDGE innerouter, boolT inorder) {
-  int totcount= 0;
-  int vertex_i, vertex_n;
-  vertexT *vertex;
-
-  FORALLvertices
-    vertex->seen= False;
-  FOREACHvertex_i_(vertices) {
-    if (vertex) {
-      if (qh GOODvertex > 0 && qh_pointid(vertex->point)+1 != qh GOODvertex)
-        continue;
-      totcount += qh_eachvoronoi(fp, printvridge, vertex, !qh_ALL, innerouter, inorder);
-    }
-  }
-  return totcount;
-} /* printvdiagram2 */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printvertex">-</a>
-
-  qh_printvertex( fp, vertex )
-    prints the information in a vertex
-    Duplicated as operator<< [QhullVertex.cpp]
-*/
-void qh_printvertex(FILE *fp, vertexT *vertex) {
-  pointT *point;
-  int k, count= 0;
-  facetT *neighbor, **neighborp;
-  realT r; /*bug fix*/
-
-  if (!vertex) {
-    qh_fprintf(fp, 9234, "  NULLvertex\n");
-    return;
-  }
-  qh_fprintf(fp, 9235, "- p%d(v%d):", qh_pointid(vertex->point), vertex->id);
-  point= vertex->point;
-  if (point) {
-    for (k=qh hull_dim; k--; ) {
-      r= *point++;
-      qh_fprintf(fp, 9236, " %5.2g", r);
-    }
-  }
-  if (vertex->deleted)
-    qh_fprintf(fp, 9237, " deleted");
-  if (vertex->delridge)
-    qh_fprintf(fp, 9238, " ridgedeleted");
-  qh_fprintf(fp, 9239, "\n");
-  if (vertex->neighbors) {
-    qh_fprintf(fp, 9240, "  neighbors:");
-    FOREACHneighbor_(vertex) {
-      if (++count % 100 == 0)
-        qh_fprintf(fp, 9241, "\n     ");
-      qh_fprintf(fp, 9242, " f%d", neighbor->id);
-    }
-    qh_fprintf(fp, 9243, "\n");
-  }
-} /* printvertex */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printvertexlist">-</a>
-
-  qh_printvertexlist( fp, string, facetlist, facets, printall )
-    prints vertices used by a facetlist or facet set
-    tests qh_skipfacet() if !printall
-*/
-void qh_printvertexlist(FILE *fp, const char* string, facetT *facetlist,
-                         setT *facets, boolT printall) {
-  vertexT *vertex, **vertexp;
-  setT *vertices;
-
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  qh_fprintf(fp, 9244, "%s", string);
-  FOREACHvertex_(vertices)
-    qh_printvertex(fp, vertex);
-  qh_settempfree(&vertices);
-} /* printvertexlist */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printvertices">-</a>
-
-  qh_printvertices( fp, string, vertices )
-    prints vertices in a set
-    duplicated as printVertexSet [QhullVertex.cpp]
-*/
-void qh_printvertices(FILE *fp, const char* string, setT *vertices) {
-  vertexT *vertex, **vertexp;
-
-  qh_fprintf(fp, 9245, "%s", string);
-  FOREACHvertex_(vertices)
-    qh_fprintf(fp, 9246, " p%d(v%d)", qh_pointid(vertex->point), vertex->id);
-  qh_fprintf(fp, 9247, "\n");
-} /* printvertices */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printvneighbors">-</a>
-
-  qh_printvneighbors( fp, facetlist, facets, printall )
-    print vertex neighbors of vertices in facetlist and facets ('FN')
-
-  notes:
-    qh_countfacets clears facet->visitid for non-printed facets
-
-  design:
-    collect facet count and related statistics
-    if necessary, build neighbor sets for each vertex
-    collect vertices in facetlist and facets
-    build a point array for point->vertex and point->coplanar facet
-    for each point
-      list vertex neighbors or coplanar facet
-*/
-void qh_printvneighbors(FILE *fp, facetT* facetlist, setT *facets, boolT printall) {
-  int numfacets, numsimplicial, numridges, totneighbors, numneighbors, numcoplanars, numtricoplanars;
-  setT *vertices, *vertex_points, *coplanar_points;
-  int numpoints= qh num_points + qh_setsize(qh other_points);
-  vertexT *vertex, **vertexp;
-  int vertex_i, vertex_n;
-  facetT *facet, **facetp, *neighbor, **neighborp;
-  pointT *point, **pointp;
-
-  qh_countfacets(facetlist, facets, printall, &numfacets, &numsimplicial,
-      &totneighbors, &numridges, &numcoplanars, &numtricoplanars);  /* sets facet->visitid */
-  qh_fprintf(fp, 9248, "%d\n", numpoints);
-  qh_vertexneighbors();
-  vertices= qh_facetvertices(facetlist, facets, printall);
-  vertex_points= qh_settemp(numpoints);
-  coplanar_points= qh_settemp(numpoints);
-  qh_setzero(vertex_points, 0, numpoints);
-  qh_setzero(coplanar_points, 0, numpoints);
-  FOREACHvertex_(vertices)
-    qh_point_add(vertex_points, vertex->point, vertex);
-  FORALLfacet_(facetlist) {
-    FOREACHpoint_(facet->coplanarset)
-      qh_point_add(coplanar_points, point, facet);
-  }
-  FOREACHfacet_(facets) {
-    FOREACHpoint_(facet->coplanarset)
-      qh_point_add(coplanar_points, point, facet);
-  }
-  FOREACHvertex_i_(vertex_points) {
-    if (vertex) {
-      numneighbors= qh_setsize(vertex->neighbors);
-      qh_fprintf(fp, 9249, "%d", numneighbors);
-      if (qh hull_dim == 3)
-        qh_order_vertexneighbors(vertex);
-      else if (qh hull_dim >= 4)
-        qsort(SETaddr_(vertex->neighbors, facetT), (size_t)numneighbors,
-             sizeof(facetT *), qh_compare_facetvisit);
-      FOREACHneighbor_(vertex)
-        qh_fprintf(fp, 9250, " %d",
-                 neighbor->visitid ? neighbor->visitid - 1 : 0 - neighbor->id);
-      qh_fprintf(fp, 9251, "\n");
-    }else if ((facet= SETelemt_(coplanar_points, vertex_i, facetT)))
-      qh_fprintf(fp, 9252, "1 %d\n",
-                  facet->visitid ? facet->visitid - 1 : 0 - facet->id);
-    else
-      qh_fprintf(fp, 9253, "0\n");
-  }
-  qh_settempfree(&coplanar_points);
-  qh_settempfree(&vertex_points);
-  qh_settempfree(&vertices);
-} /* printvneighbors */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printvoronoi">-</a>
-
-  qh_printvoronoi( fp, format, facetlist, facets, printall )
-    print voronoi diagram in 'o' or 'G' format
-    for 'o' format
-      prints voronoi centers for each facet and for infinity
-      for each vertex, lists ids of printed facets or infinity
-      assumes facetlist and facets are disjoint
-    for 'G' format
-      prints an OFF object
-      adds a 0 coordinate to center
-      prints infinity but does not list in vertices
-
-  see:
-    qh_printvdiagram()
-
-  notes:
-    if 'o',
-      prints a line for each point except "at-infinity"
-    if all facets are upperdelaunay,
-      reverses lower and upper hull
-*/
-void qh_printvoronoi(FILE *fp, qh_PRINT format, facetT *facetlist, setT *facets, boolT printall) {
-  int k, numcenters, numvertices= 0, numneighbors, numinf, vid=1, vertex_i, vertex_n;
-  facetT *facet, **facetp, *neighbor, **neighborp;
-  setT *vertices;
-  vertexT *vertex;
-  boolT isLower;
-  unsigned int numfacets= (unsigned int) qh num_facets;
-
-  vertices= qh_markvoronoi(facetlist, facets, printall, &isLower, &numcenters);
-  FOREACHvertex_i_(vertices) {
-    if (vertex) {
-      numvertices++;
-      numneighbors = numinf = 0;
-      FOREACHneighbor_(vertex) {
-        if (neighbor->visitid == 0)
-          numinf= 1;
-        else if (neighbor->visitid < numfacets)
-          numneighbors++;
-      }
-      if (numinf && !numneighbors) {
-        SETelem_(vertices, vertex_i)= NULL;
-        numvertices--;
-      }
-    }
-  }
-  if (format == qh_PRINTgeom)
-    qh_fprintf(fp, 9254, "{appearance {+edge -face} OFF %d %d 1 # Voronoi centers and cells\n",
-                numcenters, numvertices);
-  else
-    qh_fprintf(fp, 9255, "%d\n%d %d 1\n", qh hull_dim-1, numcenters, qh_setsize(vertices));
-  if (format == qh_PRINTgeom) {
-    for (k=qh hull_dim-1; k--; )
-      qh_fprintf(fp, 9256, qh_REAL_1, 0.0);
-    qh_fprintf(fp, 9257, " 0 # infinity not used\n");
-  }else {
-    for (k=qh hull_dim-1; k--; )
-      qh_fprintf(fp, 9258, qh_REAL_1, qh_INFINITE);
-    qh_fprintf(fp, 9259, "\n");
-  }
-  FORALLfacet_(facetlist) {
-    if (facet->visitid && facet->visitid < numfacets) {
-      if (format == qh_PRINTgeom)
-        qh_fprintf(fp, 9260, "# %d f%d\n", vid++, facet->id);
-      qh_printcenter(fp, format, NULL, facet);
-    }
-  }
-  FOREACHfacet_(facets) {
-    if (facet->visitid && facet->visitid < numfacets) {
-      if (format == qh_PRINTgeom)
-        qh_fprintf(fp, 9261, "# %d f%d\n", vid++, facet->id);
-      qh_printcenter(fp, format, NULL, facet);
-    }
-  }
-  FOREACHvertex_i_(vertices) {
-    numneighbors= 0;
-    numinf=0;
-    if (vertex) {
-      if (qh hull_dim == 3)
-        qh_order_vertexneighbors(vertex);
-      else if (qh hull_dim >= 4)
-        qsort(SETaddr_(vertex->neighbors, facetT),
-             (size_t)qh_setsize(vertex->neighbors),
-             sizeof(facetT *), qh_compare_facetvisit);
-      FOREACHneighbor_(vertex) {
-        if (neighbor->visitid == 0)
-          numinf= 1;
-        else if (neighbor->visitid < numfacets)
-          numneighbors++;
-      }
-    }
-    if (format == qh_PRINTgeom) {
-      if (vertex) {
-        qh_fprintf(fp, 9262, "%d", numneighbors);
-        FOREACHneighbor_(vertex) {
-          if (neighbor->visitid && neighbor->visitid < numfacets)
-            qh_fprintf(fp, 9263, " %d", neighbor->visitid);
-        }
-        qh_fprintf(fp, 9264, " # p%d(v%d)\n", vertex_i, vertex->id);
-      }else
-        qh_fprintf(fp, 9265, " # p%d is coplanar or isolated\n", vertex_i);
-    }else {
-      if (numinf)
-        numneighbors++;
-      qh_fprintf(fp, 9266, "%d", numneighbors);
-      if (vertex) {
-        FOREACHneighbor_(vertex) {
-          if (neighbor->visitid == 0) {
-            if (numinf) {
-              numinf= 0;
-              qh_fprintf(fp, 9267, " %d", neighbor->visitid);
-            }
-          }else if (neighbor->visitid < numfacets)
-            qh_fprintf(fp, 9268, " %d", neighbor->visitid);
-        }
-      }
-      qh_fprintf(fp, 9269, "\n");
-    }
-  }
-  if (format == qh_PRINTgeom)
-    qh_fprintf(fp, 9270, "}\n");
-  qh_settempfree(&vertices);
-} /* printvoronoi */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printvnorm">-</a>
-
-  qh_printvnorm( fp, vertex, vertexA, centers, unbounded )
-    print one separating plane of the Voronoi diagram for a pair of input sites
-    unbounded==True if centers includes vertex-at-infinity
-
-  assumes:
-    qh_ASvoronoi and qh_vertexneighbors() already set
-
-  note:
-    parameter unbounded is UNUSED by this callback
-
-  see:
-    qh_printvdiagram()
-    qh_eachvoronoi()
-*/
-void qh_printvnorm(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
-  pointT *normal;
-  realT offset;
-  int k;
-  QHULL_UNUSED(unbounded);
-
-  normal= qh_detvnorm(vertex, vertexA, centers, &offset);
-  qh_fprintf(fp, 9271, "%d %d %d ",
-      2+qh hull_dim, qh_pointid(vertex->point), qh_pointid(vertexA->point));
-  for (k=0; k< qh hull_dim-1; k++)
-    qh_fprintf(fp, 9272, qh_REAL_1, normal[k]);
-  qh_fprintf(fp, 9273, qh_REAL_1, offset);
-  qh_fprintf(fp, 9274, "\n");
-} /* printvnorm */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="printvridge">-</a>
-
-  qh_printvridge( fp, vertex, vertexA, centers, unbounded )
-    print one ridge of the Voronoi diagram for a pair of input sites
-    unbounded==True if centers includes vertex-at-infinity
-
-  see:
-    qh_printvdiagram()
-
-  notes:
-    the user may use a different function
-    parameter unbounded is UNUSED
-*/
-void qh_printvridge(FILE *fp, vertexT *vertex, vertexT *vertexA, setT *centers, boolT unbounded) {
-  facetT *facet, **facetp;
-  QHULL_UNUSED(unbounded);
-
-  qh_fprintf(fp, 9275, "%d %d %d", qh_setsize(centers)+2,
-       qh_pointid(vertex->point), qh_pointid(vertexA->point));
-  FOREACHfacet_(centers)
-    qh_fprintf(fp, 9276, " %d", facet->visitid);
-  qh_fprintf(fp, 9277, "\n");
-} /* printvridge */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="projectdim3">-</a>
-
-  qh_projectdim3( source, destination )
-    project 2-d 3-d or 4-d point to a 3-d point
-    uses qh.DROPdim and qh.hull_dim
-    source and destination may be the same
-
-  notes:
-    allocate 4 elements to destination just in case
-*/
-void qh_projectdim3 (pointT *source, pointT *destination) {
-  int i,k;
-
-  for (k=0, i=0; k < qh hull_dim; k++) {
-    if (qh hull_dim == 4) {
-      if (k != qh DROPdim)
-        destination[i++]= source[k];
-    }else if (k == qh DROPdim)
-      destination[i++]= 0;
-    else
-      destination[i++]= source[k];
-  }
-  while (i < 3)
-    destination[i++]= 0.0;
-} /* projectdim3 */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="readfeasible">-</a>
-
-  qh_readfeasible( dim, curline )
-    read feasible point from current line and qh.fin
-
-  returns:
-    number of lines read from qh.fin
-    sets qh.FEASIBLEpoint with malloc'd coordinates
-
-  notes:
-    checks for qh.HALFspace
-    assumes dim > 1
-
-  see:
-    qh_setfeasible
-*/
-int qh_readfeasible(int dim, const char *curline) {
-  boolT isfirst= True;
-  int linecount= 0, tokcount= 0;
-  const char *s;
-  char *t, firstline[qh_MAXfirst+1];
-  coordT *coords, value;
-
-  if (!qh HALFspace) {
-    qh_fprintf(qh ferr, 6070, "qhull input error: feasible point(dim 1 coords) is only valid for halfspace intersection\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (qh feasible_string)
-    qh_fprintf(qh ferr, 7057, "qhull input warning: feasible point(dim 1 coords) overrides 'Hn,n,n' feasible point for halfspace intersection\n");
-  if (!(qh feasible_point= (coordT*)qh_malloc(dim* sizeof(coordT)))) {
-    qh_fprintf(qh ferr, 6071, "qhull error: insufficient memory for feasible point\n");
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  coords= qh feasible_point;
-  while ((s= (isfirst ?  curline : fgets(firstline, qh_MAXfirst, qh fin)))) {
-    if (isfirst)
-      isfirst= False;
-    else
-      linecount++;
-    while (*s) {
-      while (isspace(*s))
-        s++;
-      value= qh_strtod(s, &t);
-      if (s == t)
-        break;
-      s= t;
-      *(coords++)= value;
-      if (++tokcount == dim) {
-        while (isspace(*s))
-          s++;
-        qh_strtod(s, &t);
-        if (s != t) {
-          qh_fprintf(qh ferr, 6072, "qhull input error: coordinates for feasible point do not finish out the line: %s\n",
-               s);
-          qh_errexit(qh_ERRinput, NULL, NULL);
-        }
-        return linecount;
-      }
-    }
-  }
-  qh_fprintf(qh ferr, 6073, "qhull input error: only %d coordinates.  Could not read %d-d feasible point.\n",
-           tokcount, dim);
-  qh_errexit(qh_ERRinput, NULL, NULL);
-  return 0;
-} /* readfeasible */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="readpoints">-</a>
-
-  qh_readpoints( numpoints, dimension, ismalloc )
-    read points from qh.fin into qh.first_point, qh.num_points
-    qh.fin is lines of coordinates, one per vertex, first line number of points
-    if 'rbox D4',
-      gives message
-    if qh.ATinfinity,
-      adds point-at-infinity for Delaunay triangulations
-
-  returns:
-    number of points, array of point coordinates, dimension, ismalloc True
-    if qh.DELAUNAY & !qh.PROJECTinput, projects points to paraboloid
-        and clears qh.PROJECTdelaunay
-    if qh.HALFspace, reads optional feasible point, reads halfspaces,
-        converts to dual.
-
-  for feasible point in "cdd format" in 3-d:
-    3 1
-    coordinates
-    comments
-    begin
-    n 4 real/integer
-    ...
-    end
-
-  notes:
-    dimension will change in qh_initqhull_globals if qh.PROJECTinput
-    uses malloc() since qh_mem not initialized
-    FIXUP QH11012: qh_readpoints needs rewriting, too long
-*/
-coordT *qh_readpoints(int *numpoints, int *dimension, boolT *ismalloc) {
-  coordT *points, *coords, *infinity= NULL;
-  realT paraboloid, maxboloid= -REALmax, value;
-  realT *coordp= NULL, *offsetp= NULL, *normalp= NULL;
-  char *s= 0, *t, firstline[qh_MAXfirst+1];
-  int diminput=0, numinput=0, dimfeasible= 0, newnum, k, tempi;
-  int firsttext=0, firstshort=0, firstlong=0, firstpoint=0;
-  int tokcount= 0, linecount=0, maxcount, coordcount=0;
-  boolT islong, isfirst= True, wasbegin= False;
-  boolT isdelaunay= qh DELAUNAY && !qh PROJECTinput;
-
-  if (qh CDDinput) {
-    while ((s= fgets(firstline, qh_MAXfirst, qh fin))) {
-      linecount++;
-      if (qh HALFspace && linecount == 1 && isdigit(*s)) {
-        dimfeasible= qh_strtol(s, &s);
-        while (isspace(*s))
-          s++;
-        if (qh_strtol(s, &s) == 1)
-          linecount += qh_readfeasible(dimfeasible, s);
-        else
-          dimfeasible= 0;
-      }else if (!memcmp(firstline, "begin", (size_t)5) || !memcmp(firstline, "BEGIN", (size_t)5))
-        break;
-      else if (!*qh rbox_command)
-        strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
-    }
-    if (!s) {
-      qh_fprintf(qh ferr, 6074, "qhull input error: missing \"begin\" for cdd-formatted input\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-  }
-  while (!numinput && (s= fgets(firstline, qh_MAXfirst, qh fin))) {
-    linecount++;
-    if (!memcmp(s, "begin", (size_t)5) || !memcmp(s, "BEGIN", (size_t)5))
-      wasbegin= True;
-    while (*s) {
-      while (isspace(*s))
-        s++;
-      if (!*s)
-        break;
-      if (!isdigit(*s)) {
-        if (!*qh rbox_command) {
-          strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
-          firsttext= linecount;
-        }
-        break;
-      }
-      if (!diminput)
-        diminput= qh_strtol(s, &s);
-      else {
-        numinput= qh_strtol(s, &s);
-        if (numinput == 1 && diminput >= 2 && qh HALFspace && !qh CDDinput) {
-          linecount += qh_readfeasible(diminput, s); /* checks if ok */
-          dimfeasible= diminput;
-          diminput= numinput= 0;
-        }else
-          break;
-      }
-    }
-  }
-  if (!s) {
-    qh_fprintf(qh ferr, 6075, "qhull input error: short input file.  Did not find dimension and number of points\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (diminput > numinput) {
-    tempi= diminput;    /* exchange dim and n, e.g., for cdd input format */
-    diminput= numinput;
-    numinput= tempi;
-  }
-  if (diminput < 2) {
-    qh_fprintf(qh ferr, 6220,"qhull input error: dimension %d(first number) should be at least 2\n",
-            diminput);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (isdelaunay) {
-    qh PROJECTdelaunay= False;
-    if (qh CDDinput)
-      *dimension= diminput;
-    else
-      *dimension= diminput+1;
-    *numpoints= numinput;
-    if (qh ATinfinity)
-      (*numpoints)++;
-  }else if (qh HALFspace) {
-    *dimension= diminput - 1;
-    *numpoints= numinput;
-    if (diminput < 3) {
-      qh_fprintf(qh ferr, 6221,"qhull input error: dimension %d(first number, includes offset) should be at least 3 for halfspaces\n",
-            diminput);
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (dimfeasible) {
-      if (dimfeasible != *dimension) {
-        qh_fprintf(qh ferr, 6222,"qhull input error: dimension %d of feasible point is not one less than dimension %d for halfspaces\n",
-          dimfeasible, diminput);
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-    }else
-      qh_setfeasible(*dimension);
-  }else {
-    if (qh CDDinput)
-      *dimension= diminput-1;
-    else
-      *dimension= diminput;
-    *numpoints= numinput;
-  }
-  qh normal_size= *dimension * sizeof(coordT); /* for tracing with qh_printpoint */
-  if (qh HALFspace) {
-    qh half_space= coordp= (coordT*)qh_malloc(qh normal_size + sizeof(coordT));
-    if (qh CDDinput) {
-      offsetp= qh half_space;
-      normalp= offsetp + 1;
-    }else {
-      normalp= qh half_space;
-      offsetp= normalp + *dimension;
-    }
-  }
-  qh maxline= diminput * (qh_REALdigits + 5);
-  maximize_(qh maxline, 500);
-  qh line= (char*)qh_malloc((qh maxline+1) * sizeof(char));
-  *ismalloc= True;  /* use malloc since memory not setup */
-  coords= points= qh temp_malloc=
-        (coordT*)qh_malloc((*numpoints)*(*dimension)*sizeof(coordT));
-  if (!coords || !qh line || (qh HALFspace && !qh half_space)) {
-    qh_fprintf(qh ferr, 6076, "qhull error: insufficient memory to read %d points\n",
-            numinput);
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  if (isdelaunay && qh ATinfinity) {
-    infinity= points + numinput * (*dimension);
-    for (k= (*dimension) - 1; k--; )
-      infinity[k]= 0.0;
-  }
-  maxcount= numinput * diminput;
-  paraboloid= 0.0;
-  while ((s= (isfirst ?  s : fgets(qh line, qh maxline, qh fin)))) {
-    if (!isfirst) {
-      linecount++;
-      if (*s == 'e' || *s == 'E') {
-        if (!memcmp(s, "end", (size_t)3) || !memcmp(s, "END", (size_t)3)) {
-          if (qh CDDinput )
-            break;
-          else if (wasbegin)
-            qh_fprintf(qh ferr, 7058, "qhull input warning: the input appears to be in cdd format.  If so, use 'Fd'\n");
-        }
-      }
-    }
-    islong= False;
-    while (*s) {
-      while (isspace(*s))
-        s++;
-      value= qh_strtod(s, &t);
-      if (s == t) {
-        if (!*qh rbox_command)
-         strncat(qh rbox_command, s, sizeof(qh rbox_command)-1);
-        if (*s && !firsttext)
-          firsttext= linecount;
-        if (!islong && !firstshort && coordcount)
-          firstshort= linecount;
-        break;
-      }
-      if (!firstpoint)
-        firstpoint= linecount;
-      s= t;
-      if (++tokcount > maxcount)
-        continue;
-      if (qh HALFspace) {
-        if (qh CDDinput)
-          *(coordp++)= -value; /* both coefficients and offset */
-        else
-          *(coordp++)= value;
-      }else {
-        *(coords++)= value;
-        if (qh CDDinput && !coordcount) {
-          if (value != 1.0) {
-            qh_fprintf(qh ferr, 6077, "qhull input error: for cdd format, point at line %d does not start with '1'\n",
-                   linecount);
-            qh_errexit(qh_ERRinput, NULL, NULL);
-          }
-          coords--;
-        }else if (isdelaunay) {
-          paraboloid += value * value;
-          if (qh ATinfinity) {
-            if (qh CDDinput)
-              infinity[coordcount-1] += value;
-            else
-              infinity[coordcount] += value;
-          }
-        }
-      }
-      if (++coordcount == diminput) {
-        coordcount= 0;
-        if (isdelaunay) {
-          *(coords++)= paraboloid;
-          maximize_(maxboloid, paraboloid);
-          paraboloid= 0.0;
-        }else if (qh HALFspace) {
-          if (!qh_sethalfspace(*dimension, coords, &coords, normalp, offsetp, qh feasible_point)) {
-            qh_fprintf(qh ferr, 8048, "The halfspace was on line %d\n", linecount);
-            if (wasbegin)
-              qh_fprintf(qh ferr, 8049, "The input appears to be in cdd format.  If so, you should use option 'Fd'\n");
-            qh_errexit(qh_ERRinput, NULL, NULL);
-          }
-          coordp= qh half_space;
-        }
-        while (isspace(*s))
-          s++;
-        if (*s) {
-          islong= True;
-          if (!firstlong)
-            firstlong= linecount;
-        }
-      }
-    }
-    if (!islong && !firstshort && coordcount)
-      firstshort= linecount;
-    if (!isfirst && s - qh line >= qh maxline) {
-      qh_fprintf(qh ferr, 6078, "qhull input error: line %d contained more than %d characters\n",
-              linecount, (int) (s - qh line));   /* WARN64 */
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    isfirst= False;
-  }
-  if (tokcount != maxcount) {
-    newnum= fmin_(numinput, tokcount/diminput);
-    qh_fprintf(qh ferr, 7073,"\
-qhull warning: instead of %d %d-dimensional points, input contains\n\
-%d points and %d extra coordinates.  Line %d is the first\npoint",
-       numinput, diminput, tokcount/diminput, tokcount % diminput, firstpoint);
-    if (firsttext)
-      qh_fprintf(qh ferr, 8051, ", line %d is the first comment", firsttext);
-    if (firstshort)
-      qh_fprintf(qh ferr, 8052, ", line %d is the first short\nline", firstshort);
-    if (firstlong)
-      qh_fprintf(qh ferr, 8053, ", line %d is the first long line", firstlong);
-    qh_fprintf(qh ferr, 8054, ".  Continue with %d points.\n", newnum);
-    numinput= newnum;
-    if (isdelaunay && qh ATinfinity) {
-      for (k= tokcount % diminput; k--; )
-        infinity[k] -= *(--coords);
-      *numpoints= newnum+1;
-    }else {
-      coords -= tokcount % diminput;
-      *numpoints= newnum;
-    }
-  }
-  if (isdelaunay && qh ATinfinity) {
-    for (k= (*dimension) -1; k--; )
-      infinity[k] /= numinput;
-    if (coords == infinity)
-      coords += (*dimension) -1;
-    else {
-      for (k=0; k < (*dimension) -1; k++)
-        *(coords++)= infinity[k];
-    }
-    *(coords++)= maxboloid * 1.1;
-  }
-  if (qh rbox_command[0]) {
-    qh rbox_command[strlen(qh rbox_command)-1]= '\0';
-    if (!strcmp(qh rbox_command, "./rbox D4"))
-      qh_fprintf(qh ferr, 8055, "\n\
-This is the qhull test case.  If any errors or core dumps occur,\n\
-recompile qhull with 'make new'.  If errors still occur, there is\n\
-an incompatibility.  You should try a different compiler.  You can also\n\
-change the choices in user.h.  If you discover the source of the problem,\n\
-please send mail to qhull_bug at qhull.org.\n\
-\n\
-Type 'qhull' for a short list of options.\n");
-  }
-  qh_free(qh line);
-  qh line= NULL;
-  if (qh half_space) {
-    qh_free(qh half_space);
-    qh half_space= NULL;
-  }
-  qh temp_malloc= NULL;
-  trace1((qh ferr, 1008,"qh_readpoints: read in %d %d-dimensional points\n",
-          numinput, diminput));
-  return(points);
-} /* readpoints */
-
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="setfeasible">-</a>
-
-  qh_setfeasible( dim )
-    set qh.FEASIBLEpoint from qh.feasible_string in "n,n,n" or "n n n" format
-
-  notes:
-    "n,n,n" already checked by qh_initflags()
-    see qh_readfeasible()
-*/
-void qh_setfeasible(int dim) {
-  int tokcount= 0;
-  char *s;
-  coordT *coords, value;
-
-  if (!(s= qh feasible_string)) {
-    qh_fprintf(qh ferr, 6223, "\
-qhull input error: halfspace intersection needs a feasible point.\n\
-Either prepend the input with 1 point or use 'Hn,n,n'.  See manual.\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (!(qh feasible_point= (pointT*)qh_malloc(dim * sizeof(coordT)))) {
-    qh_fprintf(qh ferr, 6079, "qhull error: insufficient memory for 'Hn,n,n'\n");
-    qh_errexit(qh_ERRmem, NULL, NULL);
-  }
-  coords= qh feasible_point;
-  while (*s) {
-    value= qh_strtod(s, &s);
-    if (++tokcount > dim) {
-      qh_fprintf(qh ferr, 7059, "qhull input warning: more coordinates for 'H%s' than dimension %d\n",
-          qh feasible_string, dim);
-      break;
-    }
-    *(coords++)= value;
-    if (*s)
-      s++;
-  }
-  while (++tokcount <= dim)
-    *(coords++)= 0.0;
-} /* setfeasible */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="skipfacet">-</a>
-
-  qh_skipfacet( facet )
-    returns 'True' if this facet is not to be printed
-
-  notes:
-    based on the user provided slice thresholds and 'good' specifications
-*/
-boolT qh_skipfacet(facetT *facet) {
-  facetT *neighbor, **neighborp;
-
-  if (qh PRINTneighbors) {
-    if (facet->good)
-      return !qh PRINTgood;
-    FOREACHneighbor_(facet) {
-      if (neighbor->good)
-        return False;
-    }
-    return True;
-  }else if (qh PRINTgood)
-    return !facet->good;
-  else if (!facet->normal)
-    return True;
-  return(!qh_inthresholds(facet->normal, NULL));
-} /* skipfacet */
-
-/*-<a                             href="qh-io.htm#TOC"
-  >-------------------------------</a><a name="skipfilename">-</a>
-
-  qh_skipfilename( string )
-    returns pointer to character after filename
-
-  notes:
-    skips leading spaces
-    ends with spacing or eol
-    if starts with ' or " ends with the same, skipping \' or \"
-    For qhull, qh_argv_to_command() only uses double quotes
-*/
-char *qh_skipfilename(char *filename) {
-  char *s= filename;  /* non-const due to return */
-  char c;
-
-  while (*s && isspace(*s))
-    s++;
-  c= *s++;
-  if (c == '\0') {
-    qh_fprintf(qh ferr, 6204, "qhull input error: filename expected, none found.\n");
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  if (c == '\'' || c == '"') {
-    while (*s !=c || s[-1] == '\\') {
-      if (!*s) {
-        qh_fprintf(qh ferr, 6203, "qhull input error: missing quote after filename -- %s\n", filename);
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-      s++;
-    }
-    s++;
-  }
-  else while (*s && !isspace(*s))
-      s++;
-  return s;
-} /* skipfilename */
-
diff --git a/alg/libqhull/poly.c b/alg/libqhull/poly.c
deleted file mode 100644
index 93f09a5..0000000
--- a/alg/libqhull/poly.c
+++ /dev/null
@@ -1,1202 +0,0 @@
-/*<html><pre>  -<a                             href="qh-poly.htm"
-  >-------------------------------</a><a name="TOP">-</a>
-
-   poly.c
-   implements polygons and simplices
-
-   see qh-poly.htm, poly.h and libqhull.h
-
-   infrequent code is in poly2.c
-   (all but top 50 and their callers 12/3/95)
-
-   Copyright (c) 1993-2012 The Geometry Center.
-   $Id: //main/2011/qhull/src/libqhull/poly.c#5 $$Change: 1464 $
-   $DateTime: 2012/01/25 22:58:41 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*======== functions in alphabetical order ==========*/
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="appendfacet">-</a>
-
-  qh_appendfacet( facet )
-    appends facet to end of qh.facet_list,
-
-  returns:
-    updates qh.newfacet_list, facet_next, facet_list
-    increments qh.numfacets
-
-  notes:
-    assumes qh.facet_list/facet_tail is defined (createsimplex)
-
-  see:
-    qh_removefacet()
-
-*/
-void qh_appendfacet(facetT *facet) {
-  facetT *tail= qh facet_tail;
-
-  if (tail == qh newfacet_list)
-    qh newfacet_list= facet;
-  if (tail == qh facet_next)
-    qh facet_next= facet;
-  facet->previous= tail->previous;
-  facet->next= tail;
-  if (tail->previous)
-    tail->previous->next= facet;
-  else
-    qh facet_list= facet;
-  tail->previous= facet;
-  qh num_facets++;
-  trace4((qh ferr, 4044, "qh_appendfacet: append f%d to facet_list\n", facet->id));
-} /* appendfacet */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="appendvertex">-</a>
-
-  qh_appendvertex( vertex )
-    appends vertex to end of qh.vertex_list,
-
-  returns:
-    sets vertex->newlist
-    updates qh.vertex_list, newvertex_list
-    increments qh.num_vertices
-
-  notes:
-    assumes qh.vertex_list/vertex_tail is defined (createsimplex)
-
-*/
-void qh_appendvertex(vertexT *vertex) {
-  vertexT *tail= qh vertex_tail;
-
-  if (tail == qh newvertex_list)
-    qh newvertex_list= vertex;
-  vertex->newlist= True;
-  vertex->previous= tail->previous;
-  vertex->next= tail;
-  if (tail->previous)
-    tail->previous->next= vertex;
-  else
-    qh vertex_list= vertex;
-  tail->previous= vertex;
-  qh num_vertices++;
-  trace4((qh ferr, 4045, "qh_appendvertex: append v%d to vertex_list\n", vertex->id));
-} /* appendvertex */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="attachnewfacets">-</a>
-
-  qh_attachnewfacets( )
-    attach horizon facets to new facets in qh.newfacet_list
-    newfacets have neighbor and ridge links to horizon but not vice versa
-    only needed for qh.ONLYgood
-
-  returns:
-    set qh.NEWfacets
-    horizon facets linked to new facets
-      ridges changed from visible facets to new facets
-      simplicial ridges deleted
-    qh.visible_list, no ridges valid
-    facet->f.replace is a newfacet (if any)
-
-  design:
-    delete interior ridges and neighbor sets by
-      for each visible, non-simplicial facet
-        for each ridge
-          if last visit or if neighbor is simplicial
-            if horizon neighbor
-              delete ridge for horizon's ridge set
-            delete ridge
-        erase neighbor set
-    attach horizon facets and new facets by
-      for all new facets
-        if corresponding horizon facet is simplicial
-          locate corresponding visible facet {may be more than one}
-          link visible facet to new facet
-          replace visible facet with new facet in horizon
-        else it's non-simplicial
-          for all visible neighbors of the horizon facet
-            link visible neighbor to new facet
-            delete visible neighbor from horizon facet
-          append new facet to horizon's neighbors
-          the first ridge of the new facet is the horizon ridge
-          link the new facet into the horizon ridge
-*/
-void qh_attachnewfacets(void ) {
-  facetT *newfacet= NULL, *neighbor, **neighborp, *horizon, *visible;
-  ridgeT *ridge, **ridgep;
-
-  qh NEWfacets= True;
-  trace3((qh ferr, 3012, "qh_attachnewfacets: delete interior ridges\n"));
-  qh visit_id++;
-  FORALLvisible_facets {
-    visible->visitid= qh visit_id;
-    if (visible->ridges) {
-      FOREACHridge_(visible->ridges) {
-        neighbor= otherfacet_(ridge, visible);
-        if (neighbor->visitid == qh visit_id
-            || (!neighbor->visible && neighbor->simplicial)) {
-          if (!neighbor->visible)  /* delete ridge for simplicial horizon */
-            qh_setdel(neighbor->ridges, ridge);
-          qh_setfree(&(ridge->vertices)); /* delete on 2nd visit */
-          qh_memfree(ridge, (int)sizeof(ridgeT));
-        }
-      }
-      SETfirst_(visible->ridges)= NULL;
-    }
-    SETfirst_(visible->neighbors)= NULL;
-  }
-  trace1((qh ferr, 1017, "qh_attachnewfacets: attach horizon facets to new facets\n"));
-  FORALLnew_facets {
-    horizon= SETfirstt_(newfacet->neighbors, facetT);
-    if (horizon->simplicial) {
-      visible= NULL;
-      FOREACHneighbor_(horizon) {   /* may have more than one horizon ridge */
-        if (neighbor->visible) {
-          if (visible) {
-            if (qh_setequal_skip(newfacet->vertices, 0, horizon->vertices,
-                                  SETindex_(horizon->neighbors, neighbor))) {
-              visible= neighbor;
-              break;
-            }
-          }else
-            visible= neighbor;
-        }
-      }
-      if (visible) {
-        visible->f.replace= newfacet;
-        qh_setreplace(horizon->neighbors, visible, newfacet);
-      }else {
-        qh_fprintf(qh ferr, 6102, "qhull internal error (qh_attachnewfacets): couldn't find visible facet for horizon f%d of newfacet f%d\n",
-                 horizon->id, newfacet->id);
-        qh_errexit2 (qh_ERRqhull, horizon, newfacet);
-      }
-    }else { /* non-simplicial, with a ridge for newfacet */
-      FOREACHneighbor_(horizon) {    /* may hold for many new facets */
-        if (neighbor->visible) {
-          neighbor->f.replace= newfacet;
-          qh_setdelnth(horizon->neighbors,
-                        SETindex_(horizon->neighbors, neighbor));
-          neighborp--; /* repeat */
-        }
-      }
-      qh_setappend(&horizon->neighbors, newfacet);
-      ridge= SETfirstt_(newfacet->ridges, ridgeT);
-      if (ridge->top == horizon)
-        ridge->bottom= newfacet;
-      else
-        ridge->top= newfacet;
-      }
-  } /* newfacets */
-  if (qh PRINTstatistics) {
-    FORALLvisible_facets {
-      if (!visible->f.replace)
-        zinc_(Zinsidevisible);
-    }
-  }
-} /* attachnewfacets */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="checkflipped">-</a>
-
-  qh_checkflipped( facet, dist, allerror )
-    checks facet orientation to interior point
-
-    if allerror set,
-      tests against qh.DISTround
-    else
-      tests against 0 since tested against DISTround before
-
-  returns:
-    False if it flipped orientation (sets facet->flipped)
-    distance if non-NULL
-*/
-boolT qh_checkflipped(facetT *facet, realT *distp, boolT allerror) {
-  realT dist;
-
-  if (facet->flipped && !distp)
-    return False;
-  zzinc_(Zdistcheck);
-  qh_distplane(qh interior_point, facet, &dist);
-  if (distp)
-    *distp= dist;
-  if ((allerror && dist > -qh DISTround)|| (!allerror && dist >= 0.0)) {
-    facet->flipped= True;
-    zzinc_(Zflippedfacets);
-    trace0((qh ferr, 19, "qh_checkflipped: facet f%d is flipped, distance= %6.12g during p%d\n",
-              facet->id, dist, qh furthest_id));
-    qh_precision("flipped facet");
-    return False;
-  }
-  return True;
-} /* checkflipped */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="delfacet">-</a>
-
-  qh_delfacet( facet )
-    removes facet from facet_list and frees up its memory
-
-  notes:
-    assumes vertices and ridges already freed
-*/
-void qh_delfacet(facetT *facet) {
-  void **freelistp; /* used !qh_NOmem */
-
-  trace4((qh ferr, 4046, "qh_delfacet: delete f%d\n", facet->id));
-  if (facet == qh tracefacet)
-    qh tracefacet= NULL;
-  if (facet == qh GOODclosest)
-    qh GOODclosest= NULL;
-  qh_removefacet(facet);
-  if (!facet->tricoplanar || facet->keepcentrum) {
-    qh_memfree_(facet->normal, qh normal_size, freelistp);
-    if (qh CENTERtype == qh_ASvoronoi) {   /* uses macro calls */
-      qh_memfree_(facet->center, qh center_size, freelistp);
-    }else /* AScentrum */ {
-      qh_memfree_(facet->center, qh normal_size, freelistp);
-    }
-  }
-  qh_setfree(&(facet->neighbors));
-  if (facet->ridges)
-    qh_setfree(&(facet->ridges));
-  qh_setfree(&(facet->vertices));
-  if (facet->outsideset)
-    qh_setfree(&(facet->outsideset));
-  if (facet->coplanarset)
-    qh_setfree(&(facet->coplanarset));
-  qh_memfree_(facet, (int)sizeof(facetT), freelistp);
-} /* delfacet */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="deletevisible">-</a>
-
-  qh_deletevisible()
-    delete visible facets and vertices
-
-  returns:
-    deletes each facet and removes from facetlist
-    at exit, qh.visible_list empty (== qh.newfacet_list)
-
-  notes:
-    ridges already deleted
-    horizon facets do not reference facets on qh.visible_list
-    new facets in qh.newfacet_list
-    uses   qh.visit_id;
-*/
-void qh_deletevisible(void /*qh visible_list*/) {
-  facetT *visible, *nextfacet;
-  vertexT *vertex, **vertexp;
-  int numvisible= 0, numdel= qh_setsize(qh del_vertices);
-
-  trace1((qh ferr, 1018, "qh_deletevisible: delete %d visible facets and %d vertices\n",
-         qh num_visible, numdel));
-  for (visible= qh visible_list; visible && visible->visible;
-                visible= nextfacet) { /* deleting current */
-    nextfacet= visible->next;
-    numvisible++;
-    qh_delfacet(visible);
-  }
-  if (numvisible != qh num_visible) {
-    qh_fprintf(qh ferr, 6103, "qhull internal error (qh_deletevisible): qh num_visible %d is not number of visible facets %d\n",
-             qh num_visible, numvisible);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  qh num_visible= 0;
-  zadd_(Zvisfacettot, numvisible);
-  zmax_(Zvisfacetmax, numvisible);
-  zzadd_(Zdelvertextot, numdel);
-  zmax_(Zdelvertexmax, numdel);
-  FOREACHvertex_(qh del_vertices)
-    qh_delvertex(vertex);
-  qh_settruncate(qh del_vertices, 0);
-} /* deletevisible */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="facetintersect">-</a>
-
-  qh_facetintersect( facetA, facetB, skipa, skipB, prepend )
-    return vertices for intersection of two simplicial facets
-    may include 1 prepended entry (if more, need to settemppush)
-
-  returns:
-    returns set of qh.hull_dim-1 + prepend vertices
-    returns skipped index for each test and checks for exactly one
-
-  notes:
-    does not need settemp since set in quick memory
-
-  see also:
-    qh_vertexintersect and qh_vertexintersect_new
-    use qh_setnew_delnthsorted to get nth ridge (no skip information)
-
-  design:
-    locate skipped vertex by scanning facet A's neighbors
-    locate skipped vertex by scanning facet B's neighbors
-    intersect the vertex sets
-*/
-setT *qh_facetintersect(facetT *facetA, facetT *facetB,
-                         int *skipA,int *skipB, int prepend) {
-  setT *intersect;
-  int dim= qh hull_dim, i, j;
-  facetT **neighborsA, **neighborsB;
-
-  neighborsA= SETaddr_(facetA->neighbors, facetT);
-  neighborsB= SETaddr_(facetB->neighbors, facetT);
-  i= j= 0;
-  if (facetB == *neighborsA++)
-    *skipA= 0;
-  else if (facetB == *neighborsA++)
-    *skipA= 1;
-  else if (facetB == *neighborsA++)
-    *skipA= 2;
-  else {
-    for (i=3; i < dim; i++) {
-      if (facetB == *neighborsA++) {
-        *skipA= i;
-        break;
-      }
-    }
-  }
-  if (facetA == *neighborsB++)
-    *skipB= 0;
-  else if (facetA == *neighborsB++)
-    *skipB= 1;
-  else if (facetA == *neighborsB++)
-    *skipB= 2;
-  else {
-    for (j=3; j < dim; j++) {
-      if (facetA == *neighborsB++) {
-        *skipB= j;
-        break;
-      }
-    }
-  }
-  if (i >= dim || j >= dim) {
-    qh_fprintf(qh ferr, 6104, "qhull internal error (qh_facetintersect): f%d or f%d not in others neighbors\n",
-            facetA->id, facetB->id);
-    qh_errexit2 (qh_ERRqhull, facetA, facetB);
-  }
-  intersect= qh_setnew_delnthsorted(facetA->vertices, qh hull_dim, *skipA, prepend);
-  trace4((qh ferr, 4047, "qh_facetintersect: f%d skip %d matches f%d skip %d\n",
-          facetA->id, *skipA, facetB->id, *skipB));
-  return(intersect);
-} /* facetintersect */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="gethash">-</a>
-
-  qh_gethash( hashsize, set, size, firstindex, skipelem )
-    return hashvalue for a set with firstindex and skipelem
-
-  notes:
-    returned hash is in [0,hashsize)
-    assumes at least firstindex+1 elements
-    assumes skipelem is NULL, in set, or part of hash
-
-    hashes memory addresses which may change over different runs of the same data
-    using sum for hash does badly in high d
-*/
-int qh_gethash(int hashsize, setT *set, int size, int firstindex, void *skipelem) {
-  void **elemp= SETelemaddr_(set, firstindex, void);
-  ptr_intT hash = 0, elem;
-  unsigned result;
-  int i;
-#ifdef _MSC_VER                   /* Microsoft Visual C++ -- warn about 64-bit issues */
-#pragma warning( push)            /* WARN64 -- ptr_intT holds a 64-bit pointer */
-#pragma warning( disable : 4311)  /* 'type cast': pointer truncation from 'void*' to 'ptr_intT' */
-#endif
-
-  switch (size-firstindex) {
-  case 1:
-    hash= (ptr_intT)(*elemp) - (ptr_intT) skipelem;
-    break;
-  case 2:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] - (ptr_intT) skipelem;
-    break;
-  case 3:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      - (ptr_intT) skipelem;
-    break;
-  case 4:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      + (ptr_intT)elemp[3] - (ptr_intT) skipelem;
-    break;
-  case 5:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4] - (ptr_intT) skipelem;
-    break;
-  case 6:
-    hash= (ptr_intT)(*elemp) + (ptr_intT)elemp[1] + (ptr_intT)elemp[2]
-      + (ptr_intT)elemp[3] + (ptr_intT)elemp[4]+ (ptr_intT)elemp[5]
-      - (ptr_intT) skipelem;
-    break;
-  default:
-    hash= 0;
-    i= 3;
-    do {     /* this is about 10% in 10-d */
-      if ((elem= (ptr_intT)*elemp++) != (ptr_intT)skipelem) {
-        hash ^= (elem << i) + (elem >> (32-i));
-        i += 3;
-        if (i >= 32)
-          i -= 32;
-      }
-    }while (*elemp);
-    break;
-  }
-  if (hashsize<0) {
-    qh_fprintf(qh ferr, 6202, "qhull internal error: negative hashsize %d passed to qh_gethash [poly.c]\n", hashsize);
-    qh_errexit2 (qh_ERRqhull, NULL, NULL);
-  }
-  result= (unsigned)(hash & 0xFFFFFFFFU);
-  result %= (unsigned)hashsize;
-  /* result= 0; for debugging */
-  return result;
-#ifdef _MSC_VER
-#pragma warning( pop)
-#endif
-} /* gethash */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="makenewfacet">-</a>
-
-  qh_makenewfacet( vertices, toporient, horizon )
-    creates a toporient? facet from vertices
-
-  returns:
-    returns newfacet
-      adds newfacet to qh.facet_list
-      newfacet->vertices= vertices
-      if horizon
-        newfacet->neighbor= horizon, but not vice versa
-    newvertex_list updated with vertices
-*/
-facetT *qh_makenewfacet(setT *vertices, boolT toporient,facetT *horizon) {
-  facetT *newfacet;
-  vertexT *vertex, **vertexp;
-
-  FOREACHvertex_(vertices) {
-    if (!vertex->newlist) {
-      qh_removevertex(vertex);
-      qh_appendvertex(vertex);
-    }
-  }
-  newfacet= qh_newfacet();
-  newfacet->vertices= vertices;
-  newfacet->toporient= (unsigned char)toporient;
-  if (horizon)
-    qh_setappend(&(newfacet->neighbors), horizon);
-  qh_appendfacet(newfacet);
-  return(newfacet);
-} /* makenewfacet */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="makenewplanes">-</a>
-
-  qh_makenewplanes()
-    make new hyperplanes for facets on qh.newfacet_list
-
-  returns:
-    all facets have hyperplanes or are marked for   merging
-    doesn't create hyperplane if horizon is coplanar (will merge)
-    updates qh.min_vertex if qh.JOGGLEmax
-
-  notes:
-    facet->f.samecycle is defined for facet->mergehorizon facets
-*/
-void qh_makenewplanes(void /* newfacet_list */) {
-  facetT *newfacet;
-
-  FORALLnew_facets {
-    if (!newfacet->mergehorizon)
-      qh_setfacetplane(newfacet);
-  }
-  if (qh JOGGLEmax < REALmax/2)
-    minimize_(qh min_vertex, -wwval_(Wnewvertexmax));
-} /* makenewplanes */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="makenew_nonsimplicial">-</a>
-
-  qh_makenew_nonsimplicial( visible, apex, numnew )
-    make new facets for ridges of a visible facet
-
-  returns:
-    first newfacet, bumps numnew as needed
-    attaches new facets if !qh.ONLYgood
-    marks ridge neighbors for simplicial visible
-    if (qh.ONLYgood)
-      ridges on newfacet, horizon, and visible
-    else
-      ridge and neighbors between newfacet and   horizon
-      visible facet's ridges are deleted
-
-  notes:
-    qh.visit_id if visible has already been processed
-    sets neighbor->seen for building f.samecycle
-      assumes all 'seen' flags initially false
-
-  design:
-    for each ridge of visible facet
-      get neighbor of visible facet
-      if neighbor was already processed
-        delete the ridge (will delete all visible facets later)
-      if neighbor is a horizon facet
-        create a new facet
-        if neighbor coplanar
-          adds newfacet to f.samecycle for later merging
-        else
-          updates neighbor's neighbor set
-          (checks for non-simplicial facet with multiple ridges to visible facet)
-        updates neighbor's ridge set
-        (checks for simplicial neighbor to non-simplicial visible facet)
-        (deletes ridge if neighbor is simplicial)
-
-*/
-#ifndef qh_NOmerge
-facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
-  void **freelistp; /* used !qh_NOmem */
-  ridgeT *ridge, **ridgep;
-  facetT *neighbor, *newfacet= NULL, *samecycle;
-  setT *vertices;
-  boolT toporient;
-  int ridgeid;
-
-  FOREACHridge_(visible->ridges) {
-    ridgeid= ridge->id;
-    neighbor= otherfacet_(ridge, visible);
-    if (neighbor->visible) {
-      if (!qh ONLYgood) {
-        if (neighbor->visitid == qh visit_id) {
-          qh_setfree(&(ridge->vertices));  /* delete on 2nd visit */
-          qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
-        }
-      }
-    }else {  /* neighbor is an horizon facet */
-      toporient= (ridge->top == visible);
-      vertices= qh_setnew(qh hull_dim); /* makes sure this is quick */
-      qh_setappend(&vertices, apex);
-      qh_setappend_set(&vertices, ridge->vertices);
-      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
-      (*numnew)++;
-      if (neighbor->coplanar) {
-        newfacet->mergehorizon= True;
-        if (!neighbor->seen) {
-          newfacet->f.samecycle= newfacet;
-          neighbor->f.newcycle= newfacet;
-        }else {
-          samecycle= neighbor->f.newcycle;
-          newfacet->f.samecycle= samecycle->f.samecycle;
-          samecycle->f.samecycle= newfacet;
-        }
-      }
-      if (qh ONLYgood) {
-        if (!neighbor->simplicial)
-          qh_setappend(&(newfacet->ridges), ridge);
-      }else {  /* qh_attachnewfacets */
-        if (neighbor->seen) {
-          if (neighbor->simplicial) {
-            qh_fprintf(qh ferr, 6105, "qhull internal error (qh_makenew_nonsimplicial): simplicial f%d sharing two ridges with f%d\n",
-                   neighbor->id, visible->id);
-            qh_errexit2 (qh_ERRqhull, neighbor, visible);
-          }
-          qh_setappend(&(neighbor->neighbors), newfacet);
-        }else
-          qh_setreplace(neighbor->neighbors, visible, newfacet);
-        if (neighbor->simplicial) {
-          qh_setdel(neighbor->ridges, ridge);
-          qh_setfree(&(ridge->vertices));
-          qh_memfree(ridge, (int)sizeof(ridgeT));
-        }else {
-          qh_setappend(&(newfacet->ridges), ridge);
-          if (toporient)
-            ridge->top= newfacet;
-          else
-            ridge->bottom= newfacet;
-        }
-      trace4((qh ferr, 4048, "qh_makenew_nonsimplicial: created facet f%d from v%d and r%d of horizon f%d\n",
-            newfacet->id, apex->id, ridgeid, neighbor->id));
-      }
-    }
-    neighbor->seen= True;
-  } /* for each ridge */
-  if (!qh ONLYgood)
-    SETfirst_(visible->ridges)= NULL;
-  return newfacet;
-} /* makenew_nonsimplicial */
-#else /* qh_NOmerge */
-facetT *qh_makenew_nonsimplicial(facetT *visible, vertexT *apex, int *numnew) {
-  return NULL;
-}
-#endif /* qh_NOmerge */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="makenew_simplicial">-</a>
-
-  qh_makenew_simplicial( visible, apex, numnew )
-    make new facets for simplicial visible facet and apex
-
-  returns:
-    attaches new facets if (!qh.ONLYgood)
-      neighbors between newfacet and horizon
-
-  notes:
-    nop if neighbor->seen or neighbor->visible(see qh_makenew_nonsimplicial)
-
-  design:
-    locate neighboring horizon facet for visible facet
-    determine vertices and orientation
-    create new facet
-    if coplanar,
-      add new facet to f.samecycle
-    update horizon facet's neighbor list
-*/
-facetT *qh_makenew_simplicial(facetT *visible, vertexT *apex, int *numnew) {
-  facetT *neighbor, **neighborp, *newfacet= NULL;
-  setT *vertices;
-  boolT flip, toporient;
-  int horizonskip=0, visibleskip;
-
-  FOREACHneighbor_(visible) {
-    if (!neighbor->seen && !neighbor->visible) {
-      vertices= qh_facetintersect(neighbor,visible, &horizonskip, &visibleskip, 1);
-      SETfirst_(vertices)= apex;
-      flip= ((horizonskip & 0x1) ^ (visibleskip & 0x1));
-      if (neighbor->toporient)
-        toporient= horizonskip & 0x1;
-      else
-        toporient= (horizonskip & 0x1) ^ 0x1;
-      newfacet= qh_makenewfacet(vertices, toporient, neighbor);
-      (*numnew)++;
-      if (neighbor->coplanar && (qh PREmerge || qh MERGEexact)) {
-#ifndef qh_NOmerge
-        newfacet->f.samecycle= newfacet;
-        newfacet->mergehorizon= True;
-#endif
-      }
-      if (!qh ONLYgood)
-        SETelem_(neighbor->neighbors, horizonskip)= newfacet;
-      trace4((qh ferr, 4049, "qh_makenew_simplicial: create facet f%d top %d from v%d and horizon f%d skip %d top %d and visible f%d skip %d, flip? %d\n",
-            newfacet->id, toporient, apex->id, neighbor->id, horizonskip,
-              neighbor->toporient, visible->id, visibleskip, flip));
-    }
-  }
-  return newfacet;
-} /* makenew_simplicial */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="matchneighbor">-</a>
-
-  qh_matchneighbor( newfacet, newskip, hashsize, hashcount )
-    either match subridge of newfacet with neighbor or add to hash_table
-
-  returns:
-    duplicate ridges are unmatched and marked by qh_DUPLICATEridge
-
-  notes:
-    ridge is newfacet->vertices w/o newskip vertex
-    do not allocate memory (need to free hash_table cleanly)
-    uses linear hash chains
-
-  see also:
-    qh_matchduplicates
-
-  design:
-    for each possible matching facet in qh.hash_table
-      if vertices match
-        set ismatch, if facets have opposite orientation
-        if ismatch and matching facet doesn't have a match
-          match the facets by updating their neighbor sets
-        else
-          indicate a duplicate ridge
-          set facet hyperplane for later testing
-          add facet to hashtable
-          unless the other facet was already a duplicate ridge
-            mark both facets with a duplicate ridge
-            add other facet (if defined) to hash table
-*/
-void qh_matchneighbor(facetT *newfacet, int newskip, int hashsize, int *hashcount) {
-  boolT newfound= False;   /* True, if new facet is already in hash chain */
-  boolT same, ismatch;
-  int hash, scan;
-  facetT *facet, *matchfacet;
-  int skip, matchskip;
-
-  hash= qh_gethash(hashsize, newfacet->vertices, qh hull_dim, 1,
-                     SETelem_(newfacet->vertices, newskip));
-  trace4((qh ferr, 4050, "qh_matchneighbor: newfacet f%d skip %d hash %d hashcount %d\n",
-          newfacet->id, newskip, hash, *hashcount));
-  zinc_(Zhashlookup);
-  for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
-       scan= (++scan >= hashsize ? 0 : scan)) {
-    if (facet == newfacet) {
-      newfound= True;
-      continue;
-    }
-    zinc_(Zhashtests);
-    if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
-      if (SETelem_(newfacet->vertices, newskip) ==
-          SETelem_(facet->vertices, skip)) {
-        qh_precision("two facets with the same vertices");
-        qh_fprintf(qh ferr, 6106, "qhull precision error: Vertex sets are the same for f%d and f%d.  Can not force output.\n",
-          facet->id, newfacet->id);
-        qh_errexit2 (qh_ERRprec, facet, newfacet);
-      }
-      ismatch= (same == (boolT)((newfacet->toporient ^ facet->toporient)));
-      matchfacet= SETelemt_(facet->neighbors, skip, facetT);
-      if (ismatch && !matchfacet) {
-        SETelem_(facet->neighbors, skip)= newfacet;
-        SETelem_(newfacet->neighbors, newskip)= facet;
-        (*hashcount)--;
-        trace4((qh ferr, 4051, "qh_matchneighbor: f%d skip %d matched with new f%d skip %d\n",
-           facet->id, skip, newfacet->id, newskip));
-        return;
-      }
-      if (!qh PREmerge && !qh MERGEexact) {
-        qh_precision("a ridge with more than two neighbors");
-        qh_fprintf(qh ferr, 6107, "qhull precision error: facets f%d, f%d and f%d meet at a ridge with more than 2 neighbors.  Can not continue.\n",
-                 facet->id, newfacet->id, getid_(matchfacet));
-        qh_errexit2 (qh_ERRprec, facet, newfacet);
-      }
-      SETelem_(newfacet->neighbors, newskip)= qh_DUPLICATEridge;
-      newfacet->dupridge= True;
-      if (!newfacet->normal)
-        qh_setfacetplane(newfacet);
-      qh_addhash(newfacet, qh hash_table, hashsize, hash);
-      (*hashcount)++;
-      if (!facet->normal)
-        qh_setfacetplane(facet);
-      if (matchfacet != qh_DUPLICATEridge) {
-        SETelem_(facet->neighbors, skip)= qh_DUPLICATEridge;
-        facet->dupridge= True;
-        if (!facet->normal)
-          qh_setfacetplane(facet);
-        if (matchfacet) {
-          matchskip= qh_setindex(matchfacet->neighbors, facet);
-          if( matchskip >= 0 )
-          {
-            SETelem_(matchfacet->neighbors, matchskip)= qh_DUPLICATEridge;
-          }
-          matchfacet->dupridge= True;
-          if (!matchfacet->normal)
-            qh_setfacetplane(matchfacet);
-          qh_addhash(matchfacet, qh hash_table, hashsize, hash);
-          *hashcount += 2;
-        }
-      }
-      trace4((qh ferr, 4052, "qh_matchneighbor: new f%d skip %d duplicates ridge for f%d skip %d matching f%d ismatch %d at hash %d\n",
-           newfacet->id, newskip, facet->id, skip,
-           (matchfacet == qh_DUPLICATEridge ? -2 : getid_(matchfacet)),
-           ismatch, hash));
-      return; /* end of duplicate ridge */
-    }
-  }
-  if (!newfound)
-    SETelem_(qh hash_table, scan)= newfacet;  /* same as qh_addhash */
-  (*hashcount)++;
-  trace4((qh ferr, 4053, "qh_matchneighbor: no match for f%d skip %d at hash %d\n",
-           newfacet->id, newskip, hash));
-} /* matchneighbor */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="matchnewfacets">-</a>
-
-  qh_matchnewfacets()
-    match newfacets in qh.newfacet_list to their newfacet neighbors
-
-  returns:
-    qh.newfacet_list with full neighbor sets
-      get vertices with nth neighbor by deleting nth vertex
-    if qh.PREmerge/MERGEexact or qh.FORCEoutput
-      sets facet->flippped if flipped normal (also prevents point partitioning)
-    if duplicate ridges and qh.PREmerge/MERGEexact
-      sets facet->dupridge
-      missing neighbor links identifies extra ridges to be merging (qh_MERGEridge)
-
-  notes:
-    newfacets already have neighbor[0] (horizon facet)
-    assumes qh.hash_table is NULL
-    vertex->neighbors has not been updated yet
-    do not allocate memory after qh.hash_table (need to free it cleanly)
-
-  design:
-    delete neighbor sets for all new facets
-    initialize a hash table
-    for all new facets
-      match facet with neighbors
-    if unmatched facets (due to duplicate ridges)
-      for each new facet with a duplicate ridge
-        match it with a facet
-    check for flipped facets
-*/
-void qh_matchnewfacets(void /* qh newfacet_list */) {
-  int numnew=0, hashcount=0, newskip;
-  facetT *newfacet, *neighbor;
-  int dim= qh hull_dim, hashsize, neighbor_i, neighbor_n;
-  setT *neighbors;
-#ifndef qh_NOtrace
-  int facet_i, facet_n, numfree= 0;
-  facetT *facet;
-#endif
-
-  trace1((qh ferr, 1019, "qh_matchnewfacets: match neighbors for new facets.\n"));
-  FORALLnew_facets {
-    numnew++;
-    {  /* inline qh_setzero(newfacet->neighbors, 1, qh hull_dim); */
-      neighbors= newfacet->neighbors;
-      neighbors->e[neighbors->maxsize].i= dim+1; /*may be overwritten*/
-      memset((char *)SETelemaddr_(neighbors, 1, void), 0, dim * SETelemsize);
-    }
-  }
-
-  qh_newhashtable(numnew*(qh hull_dim-1)); /* twice what is normally needed,
-                                     but every ridge could be DUPLICATEridge */
-  hashsize= qh_setsize(qh hash_table);
-  FORALLnew_facets {
-    for (newskip=1; newskip<qh hull_dim; newskip++) /* furthest/horizon already matched */
-    {
-      if( hashsize )
-        qh_matchneighbor(newfacet, newskip, hashsize, &hashcount);
-    }
-#if 0   /* use the following to trap hashcount errors */
-    {
-      int count= 0, k;
-      facetT *facet, *neighbor;
-
-      count= 0;
-      FORALLfacet_(qh newfacet_list) {  /* newfacet already in use */
-        for (k=1; k < qh hull_dim; k++) {
-          neighbor= SETelemt_(facet->neighbors, k, facetT);
-          if (!neighbor || neighbor == qh_DUPLICATEridge)
-            count++;
-        }
-        if (facet == newfacet)
-          break;
-      }
-      if (count != hashcount) {
-        qh_fprintf(qh ferr, 8088, "qh_matchnewfacets: after adding facet %d, hashcount %d != count %d\n",
-                 newfacet->id, hashcount, count);
-        qh_errexit(qh_ERRqhull, newfacet, NULL);
-      }
-    }
-#endif  /* end of trap code */
-  }
-  if (hashcount) {
-    FORALLnew_facets {
-      if (newfacet->dupridge) {
-        FOREACHneighbor_i_(newfacet) {
-          if (neighbor == qh_DUPLICATEridge) {
-            qh_matchduplicates(newfacet, neighbor_i, hashsize, &hashcount);
-                    /* this may report MERGEfacet */
-          }
-        }
-      }
-    }
-  }
-  if (hashcount) {
-    qh_fprintf(qh ferr, 6108, "qhull internal error (qh_matchnewfacets): %d neighbors did not match up\n",
-        hashcount);
-    qh_printhashtable(qh ferr);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-#ifndef qh_NOtrace
-  if (qh IStracing >= 2) {
-    FOREACHfacet_i_(qh hash_table) {
-      if (!facet)
-        numfree++;
-    }
-    qh_fprintf(qh ferr, 8089, "qh_matchnewfacets: %d new facets, %d unused hash entries .  hashsize %d\n",
-             numnew, numfree, qh_setsize(qh hash_table));
-  }
-#endif /* !qh_NOtrace */
-  qh_setfree(&qh hash_table);
-  if (qh PREmerge || qh MERGEexact) {
-    if (qh IStracing >= 4)
-      qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
-    FORALLnew_facets {
-      if (newfacet->normal)
-        qh_checkflipped(newfacet, NULL, qh_ALL);
-    }
-  }else if (qh FORCEoutput)
-    qh_checkflipped_all(qh newfacet_list);  /* prints warnings for flipped */
-} /* matchnewfacets */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="matchvertices">-</a>
-
-  qh_matchvertices( firstindex, verticesA, skipA, verticesB, skipB, same )
-    tests whether vertices match with a single skip
-    starts match at firstindex since all new facets have a common vertex
-
-  returns:
-    true if matched vertices
-    skip index for each set
-    sets same iff vertices have the same orientation
-
-  notes:
-    assumes skipA is in A and both sets are the same size
-
-  design:
-    set up pointers
-    scan both sets checking for a match
-    test orientation
-*/
-boolT qh_matchvertices(int firstindex, setT *verticesA, int skipA,
-       setT *verticesB, int *skipB, boolT *same) {
-  vertexT **elemAp, **elemBp, **skipBp=NULL, **skipAp;
-
-  elemAp= SETelemaddr_(verticesA, firstindex, vertexT);
-  elemBp= SETelemaddr_(verticesB, firstindex, vertexT);
-  skipAp= SETelemaddr_(verticesA, skipA, vertexT);
-  do if (elemAp != skipAp) {
-    while (*elemAp != *elemBp++) {
-      if (skipBp)
-        return False;
-      skipBp= elemBp;  /* one extra like FOREACH */
-    }
-  }while (*(++elemAp));
-  if (!skipBp)
-    skipBp= ++elemBp;
-  *skipB= SETindex_(verticesB, skipB); /* i.e., skipBp - verticesB */
-  *same= !((skipA & 0x1) ^ (*skipB & 0x1)); /* result is 0 or 1 */
-  trace4((qh ferr, 4054, "qh_matchvertices: matched by skip %d(v%d) and skip %d(v%d) same? %d\n",
-          skipA, (*skipAp)->id, *skipB, (*(skipBp-1))->id, *same));
-  return(True);
-} /* matchvertices */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="newfacet">-</a>
-
-  qh_newfacet()
-    return a new facet
-
-  returns:
-    all fields initialized or cleared   (NULL)
-    preallocates neighbors set
-*/
-facetT *qh_newfacet(void) {
-  facetT *facet;
-  void **freelistp; /* used !qh_NOmem */
-
-  qh_memalloc_((int)sizeof(facetT), freelistp, facet, facetT);
-  memset((char *)facet, (size_t)0, sizeof(facetT));
-  if (qh facet_id == qh tracefacet_id)
-    qh tracefacet= facet;
-  facet->id= qh facet_id++;
-  facet->neighbors= qh_setnew(qh hull_dim);
-#if !qh_COMPUTEfurthest
-  facet->furthestdist= 0.0;
-#endif
-#if qh_MAXoutside
-  if (qh FORCEoutput && qh APPROXhull)
-    facet->maxoutside= qh MINoutside;
-  else
-    facet->maxoutside= qh DISTround;
-#endif
-  facet->simplicial= True;
-  facet->good= True;
-  facet->newfacet= True;
-  trace4((qh ferr, 4055, "qh_newfacet: created facet f%d\n", facet->id));
-  return(facet);
-} /* newfacet */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="newridge">-</a>
-
-  qh_newridge()
-    return a new ridge
-*/
-ridgeT *qh_newridge(void) {
-  ridgeT *ridge;
-  void **freelistp;   /* used !qh_NOmem */
-
-  qh_memalloc_((int)sizeof(ridgeT), freelistp, ridge, ridgeT);
-  memset((char *)ridge, (size_t)0, sizeof(ridgeT));
-  zinc_(Ztotridges);
-  if (qh ridge_id == 0xFFFFFF) {
-    qh_fprintf(qh ferr, 7074, "\
-qhull warning: more than %d ridges.  ID field overflows and two ridges\n\
-may have the same identifier.  Otherwise output ok.\n", 0xFFFFFF);
-  }
-  ridge->id= qh ridge_id++;
-  trace4((qh ferr, 4056, "qh_newridge: created ridge r%d\n", ridge->id));
-  return(ridge);
-} /* newridge */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="pointid">-</a>
-
-  qh_pointid(  )
-    return id for a point,
-    returns -3 if null, -2 if interior, or -1 if not known
-
-  alternative code:
-    unsigned long id;
-    id= ((unsigned long)point - (unsigned long)qh.first_point)/qh.normal_size;
-
-  notes:
-    WARN64 -- id truncated to 32-bits, at most 2G points
-    NOerrors returned (QhullPoint::id)
-    if point not in point array
-      the code does a comparison of unrelated pointers.
-*/
-int qh_pointid(pointT *point) {
-  ptr_intT offset, id;
-
-  if (!point)
-    return -3;
-  else if (point == qh interior_point)
-    return -2;
-  else if (point >= qh first_point
-  && point < qh first_point + qh num_points * qh hull_dim) {
-    offset= (ptr_intT)(point - qh first_point);
-    id= offset / qh hull_dim;
-  }else if ((id= qh_setindex(qh other_points, point)) != -1)
-    id += qh num_points;
-  else
-    return -1;
-  return (int)id;
-} /* pointid */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="removefacet">-</a>
-
-  qh_removefacet( facet )
-    unlinks facet from qh.facet_list,
-
-  returns:
-    updates qh.facet_list .newfacet_list .facet_next visible_list
-    decrements qh.num_facets
-
-  see:
-    qh_appendfacet
-*/
-void qh_removefacet(facetT *facet) {
-  facetT *next= facet->next, *previous= facet->previous;
-
-  if (facet == qh newfacet_list)
-    qh newfacet_list= next;
-  if (facet == qh facet_next)
-    qh facet_next= next;
-  if (facet == qh visible_list)
-    qh visible_list= next;
-  if (previous) {
-    previous->next= next;
-    next->previous= previous;
-  }else {  /* 1st facet in qh facet_list */
-    qh facet_list= next;
-    qh facet_list->previous= NULL;
-  }
-  qh num_facets--;
-  trace4((qh ferr, 4057, "qh_removefacet: remove f%d from facet_list\n", facet->id));
-} /* removefacet */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="removevertex">-</a>
-
-  qh_removevertex( vertex )
-    unlinks vertex from qh.vertex_list,
-
-  returns:
-    updates qh.vertex_list .newvertex_list
-    decrements qh.num_vertices
-*/
-void qh_removevertex(vertexT *vertex) {
-  vertexT *next= vertex->next, *previous= vertex->previous;
-
-  if (vertex == qh newvertex_list)
-    qh newvertex_list= next;
-  if (previous) {
-    previous->next= next;
-    next->previous= previous;
-  }else {  /* 1st vertex in qh vertex_list */
-    qh vertex_list= vertex->next;
-    qh vertex_list->previous= NULL;
-  }
-  qh num_vertices--;
-  trace4((qh ferr, 4058, "qh_removevertex: remove v%d from vertex_list\n", vertex->id));
-} /* removevertex */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="updatevertices">-</a>
-
-  qh_updatevertices()
-    update vertex neighbors and delete interior vertices
-
-  returns:
-    if qh.VERTEXneighbors, updates neighbors for each vertex
-      if qh.newvertex_list,
-         removes visible neighbors  from vertex neighbors
-      if qh.newfacet_list
-         adds new facets to vertex neighbors
-    if qh.visible_list
-       interior vertices added to qh.del_vertices for later partitioning
-
-  design:
-    if qh.VERTEXneighbors
-      deletes references to visible facets from vertex neighbors
-      appends new facets to the neighbor list for each vertex
-      checks all vertices of visible facets
-        removes visible facets from neighbor lists
-        marks unused vertices for deletion
-*/
-void qh_updatevertices(void /*qh newvertex_list, newfacet_list, visible_list*/) {
-  facetT *newfacet= NULL, *neighbor, **neighborp, *visible;
-  vertexT *vertex, **vertexp;
-
-  trace3((qh ferr, 3013, "qh_updatevertices: delete interior vertices and update vertex->neighbors\n"));
-  if (qh VERTEXneighbors) {
-    FORALLvertex_(qh newvertex_list) {
-      FOREACHneighbor_(vertex) {
-        if (neighbor->visible)
-          SETref_(neighbor)= NULL;
-      }
-      qh_setcompact(vertex->neighbors);
-    }
-    FORALLnew_facets {
-      FOREACHvertex_(newfacet->vertices)
-        qh_setappend(&vertex->neighbors, newfacet);
-    }
-    FORALLvisible_facets {
-      FOREACHvertex_(visible->vertices) {
-        if (!vertex->newlist && !vertex->deleted) {
-          FOREACHneighbor_(vertex) { /* this can happen under merging */
-            if (!neighbor->visible)
-              break;
-          }
-          if (neighbor)
-            qh_setdel(vertex->neighbors, visible);
-          else {
-            vertex->deleted= True;
-            qh_setappend(&qh del_vertices, vertex);
-            trace2((qh ferr, 2041, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
-                  qh_pointid(vertex->point), vertex->id, visible->id));
-          }
-        }
-      }
-    }
-  }else {  /* !VERTEXneighbors */
-    FORALLvisible_facets {
-      FOREACHvertex_(visible->vertices) {
-        if (!vertex->newlist && !vertex->deleted) {
-          vertex->deleted= True;
-          qh_setappend(&qh del_vertices, vertex);
-          trace2((qh ferr, 2042, "qh_updatevertices: delete vertex p%d(v%d) in f%d\n",
-                  qh_pointid(vertex->point), vertex->id, visible->id));
-        }
-      }
-    }
-  }
-} /* updatevertices */
diff --git a/alg/libqhull/poly2.c b/alg/libqhull/poly2.c
deleted file mode 100644
index ff9c3bc..0000000
--- a/alg/libqhull/poly2.c
+++ /dev/null
@@ -1,3156 +0,0 @@
-/*<html><pre>  -<a                             href="qh-poly.htm"
-  >-------------------------------</a><a name="TOP">-</a>
-
-   poly2.c
-   implements polygons and simplices
-
-   see qh-poly.htm, poly.h and libqhull.h
-
-   frequently used code is in poly.c
-
-   Copyright (c) 1993-2012 The Geometry Center.
-   $Id: //main/2011/qhull/src/libqhull/poly2.c#5 $$Change: 1490 $
-   $DateTime: 2012/02/19 20:27:01 $$Author: bbarber $
-*/
-
-#include "qhull_a.h"
-
-/*======== functions in alphabetical order ==========*/
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="addhash">-</a>
-
-  qh_addhash( newelem, hashtable, hashsize, hash )
-    add newelem to linear hash table at hash if not already there
-*/
-void qh_addhash(void* newelem, setT *hashtable, int hashsize, int hash) {
-  int scan;
-  void *elem;
-
-  for (scan= (int)hash; (elem= SETelem_(hashtable, scan));
-       scan= (++scan >= hashsize ? 0 : scan)) {
-    if (elem == newelem)
-      break;
-  }
-  /* loop terminates because qh_HASHfactor >= 1.1 by qh_initbuffers */
-  if (!elem)
-    SETelem_(hashtable, scan)= newelem;
-} /* addhash */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="check_bestdist">-</a>
-
-  qh_check_bestdist()
-    check that all points are within max_outside of the nearest facet
-    if qh.ONLYgood,
-      ignores !good facets
-
-  see:
-    qh_check_maxout(), qh_outerinner()
-
-  notes:
-    only called from qh_check_points()
-      seldom used since qh.MERGING is almost always set
-    if notverified>0 at end of routine
-      some points were well inside the hull.  If the hull contains
-      a lens-shaped component, these points were not verified.  Use
-      options 'Qi Tv' to verify all points.  (Exhaustive check also verifies)
-
-  design:
-    determine facet for each point (if any)
-    for each point
-      start with the assigned facet or with the first facet
-      find the best facet for the point and check all coplanar facets
-      error if point is outside of facet
-*/
-void qh_check_bestdist(void) {
-  boolT waserror= False, unassigned;
-  facetT *facet, *bestfacet, *errfacet1= NULL, *errfacet2= NULL;
-  facetT *facetlist;
-  realT dist, maxoutside, maxdist= -REALmax;
-  pointT *point;
-  int numpart= 0, facet_i, facet_n, notgood= 0, notverified= 0;
-  setT *facets;
-
-  trace1((qh ferr, 1020, "qh_check_bestdist: check points below nearest facet.  Facet_list f%d\n",
-      qh facet_list->id));
-  maxoutside= qh_maxouter();
-  maxoutside += qh DISTround;
-  /* one more qh.DISTround for check computation */
-  trace1((qh ferr, 1021, "qh_check_bestdist: check that all points are within %2.2g of best facet\n", maxoutside));
-  facets= qh_pointfacet(/*qh facet_list*/);
-  if (!qh_QUICKhelp && qh PRINTprecision)
-    qh_fprintf(qh ferr, 8091, "\n\
-qhull output completed.  Verifying that %d points are\n\
-below %2.2g of the nearest %sfacet.\n",
-             qh_setsize(facets), maxoutside, (qh ONLYgood ?  "good " : ""));
-  FOREACHfacet_i_(facets) {  /* for each point with facet assignment */
-    if (facet)
-      unassigned= False;
-    else {
-      unassigned= True;
-      facet= qh facet_list;
-    }
-    point= qh_point(facet_i);
-    if (point == qh GOODpointp)
-      continue;
-    qh_distplane(point, facet, &dist);
-    numpart++;
-    bestfacet= qh_findbesthorizon(!qh_IScheckmax, point, facet, qh_NOupper, &dist, &numpart);
-    /* occurs after statistics reported */
-    maximize_(maxdist, dist);
-    if (dist > maxoutside) {
-      if (qh ONLYgood && !bestfacet->good
-          && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
-               && dist > maxoutside))
-        notgood++;
-      else {
-        waserror= True;
-        qh_fprintf(qh ferr, 6109, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
-                facet_i, bestfacet->id, dist, maxoutside);
-        if (errfacet1 != bestfacet) {
-          errfacet2= errfacet1;
-          errfacet1= bestfacet;
-        }
-      }
-    }else if (unassigned && dist < -qh MAXcoplanar)
-      notverified++;
-  }
-  qh_settempfree(&facets);
-  if (notverified && !qh DELAUNAY && !qh_QUICKhelp && qh PRINTprecision)
-    qh_fprintf(qh ferr, 8092, "\n%d points were well inside the hull.  If the hull contains\n\
-a lens-shaped component, these points were not verified.  Use\n\
-options 'Qci Tv' to verify all points.\n", notverified);
-  if (maxdist > qh outside_err) {
-    qh_fprintf(qh ferr, 6110, "qhull precision error (qh_check_bestdist): a coplanar point is %6.2g from convex hull.  The maximum value(qh.outside_err) is %6.2g\n",
-              maxdist, qh outside_err);
-    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
-  }else if (waserror && qh outside_err > REALmax/2)
-    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
-  /* else if waserror, the error was logged to qh.ferr but does not effect the output */
-  trace0((qh ferr, 20, "qh_check_bestdist: max distance outside %2.2g\n", maxdist));
-} /* check_bestdist */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="check_maxout">-</a>
-
-  qh_check_maxout()
-    updates qh.max_outside by checking all points against bestfacet
-    if qh.ONLYgood, ignores !good facets
-
-  returns:
-    updates facet->maxoutside via qh_findbesthorizon()
-    sets qh.maxoutdone
-    if printing qh.min_vertex (qh_outerinner),
-      it is updated to the current vertices
-    removes inside/coplanar points from coplanarset as needed
-
-  notes:
-    defines coplanar as min_vertex instead of MAXcoplanar
-    may not need to check near-inside points because of qh.MAXcoplanar
-      and qh.KEEPnearinside (before it was -DISTround)
-
-  see also:
-    qh_check_bestdist()
-
-  design:
-    if qh.min_vertex is needed
-      for all neighbors of all vertices
-        test distance from vertex to neighbor
-    determine facet for each point (if any)
-    for each point with an assigned facet
-      find the best facet for the point and check all coplanar facets
-        (updates outer planes)
-    remove near-inside points from coplanar sets
-*/
-#ifndef qh_NOmerge
-void qh_check_maxout(void) {
-  facetT *facet, *bestfacet, *neighbor, **neighborp, *facetlist;
-  realT dist, maxoutside, minvertex, old_maxoutside;
-  pointT *point;
-  int numpart= 0, facet_i, facet_n, notgood= 0;
-  setT *facets, *vertices;
-  vertexT *vertex;
-
-  trace1((qh ferr, 1022, "qh_check_maxout: check and update maxoutside for each facet.\n"));
-  maxoutside= minvertex= 0;
-  if (qh VERTEXneighbors
-  && (qh PRINTsummary || qh KEEPinside || qh KEEPcoplanar
-        || qh TRACElevel || qh PRINTstatistics
-        || qh PRINTout[0] == qh_PRINTsummary || qh PRINTout[0] == qh_PRINTnone)) {
-    trace1((qh ferr, 1023, "qh_check_maxout: determine actual maxoutside and minvertex\n"));
-    vertices= qh_pointvertex(/*qh facet_list*/);
-    FORALLvertices {
-      FOREACHneighbor_(vertex) {
-        zinc_(Zdistvertex);  /* distance also computed by main loop below */
-        qh_distplane(vertex->point, neighbor, &dist);
-        minimize_(minvertex, dist);
-        if (-dist > qh TRACEdist || dist > qh TRACEdist
-        || neighbor == qh tracefacet || vertex == qh tracevertex)
-          qh_fprintf(qh ferr, 8093, "qh_check_maxout: p%d(v%d) is %.2g from f%d\n",
-                    qh_pointid(vertex->point), vertex->id, dist, neighbor->id);
-      }
-    }
-    if (qh MERGING) {
-      wmin_(Wminvertex, qh min_vertex);
-    }
-    qh min_vertex= minvertex;
-    qh_settempfree(&vertices);
-  }
-  facets= qh_pointfacet(/*qh facet_list*/);
-  do {
-    old_maxoutside= fmax_(qh max_outside, maxoutside);
-    FOREACHfacet_i_(facets) {     /* for each point with facet assignment */
-      if (facet) {
-        point= qh_point(facet_i);
-        if (point == qh GOODpointp)
-          continue;
-        zzinc_(Ztotcheck);
-        qh_distplane(point, facet, &dist);
-        numpart++;
-        bestfacet= qh_findbesthorizon(qh_IScheckmax, point, facet, !qh_NOupper, &dist, &numpart);
-        if (bestfacet && dist > maxoutside) {
-          if (qh ONLYgood && !bestfacet->good
-          && !((bestfacet= qh_findgooddist(point, bestfacet, &dist, &facetlist))
-               && dist > maxoutside))
-            notgood++;
-          else
-            maxoutside= dist;
-        }
-        if (dist > qh TRACEdist || (bestfacet && bestfacet == qh tracefacet))
-          qh_fprintf(qh ferr, 8094, "qh_check_maxout: p%d is %.2g above f%d\n",
-                     qh_pointid(point), dist, bestfacet ? bestfacet->id : -1);
-      }
-    }
-  }while
-    (maxoutside > 2*old_maxoutside);
-    /* if qh.maxoutside increases substantially, qh_SEARCHdist is not valid
-          e.g., RBOX 5000 s Z1 G1e-13 t1001200614 | qhull */
-  zzadd_(Zcheckpart, numpart);
-  qh_settempfree(&facets);
-  wval_(Wmaxout)= maxoutside - qh max_outside;
-  wmax_(Wmaxoutside, qh max_outside);
-  qh max_outside= maxoutside;
-  qh_nearcoplanar(/*qh.facet_list*/);
-  qh maxoutdone= True;
-  trace1((qh ferr, 1024, "qh_check_maxout: maxoutside %2.2g, min_vertex %2.2g, outside of not good %d\n",
-       maxoutside, qh min_vertex, notgood));
-} /* check_maxout */
-#else /* qh_NOmerge */
-void qh_check_maxout(void) {
-}
-#endif
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="check_output">-</a>
-
-  qh_check_output()
-    performs the checks at the end of qhull algorithm
-    Maybe called after voronoi output.  Will recompute otherwise centrums are Voronoi centers instead
-*/
-void qh_check_output(void) {
-  int i;
-
-  if (qh STOPcone)
-    return;
-  if (qh VERIFYoutput | qh IStracing | qh CHECKfrequently) {
-    qh_checkpolygon(qh facet_list);
-    qh_checkflipped_all(qh facet_list);
-    qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
-  }else if (!qh MERGING && qh_newstats(qhstat precision, &i)) {
-    qh_checkflipped_all(qh facet_list);
-    qh_checkconvex(qh facet_list, qh_ALGORITHMfault);
-  }
-} /* check_output */
-
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="check_point">-</a>
-
-  qh_check_point( point, facet, maxoutside, maxdist, errfacet1, errfacet2 )
-    check that point is less than maxoutside from facet
-*/
-void qh_check_point(pointT *point, facetT *facet, realT *maxoutside, realT *maxdist, facetT **errfacet1, facetT **errfacet2) {
-  realT dist;
-
-  /* occurs after statistics reported */
-  qh_distplane(point, facet, &dist);
-  if (dist > *maxoutside) {
-    if (*errfacet1 != facet) {
-      *errfacet2= *errfacet1;
-      *errfacet1= facet;
-    }
-    qh_fprintf(qh ferr, 6111, "qhull precision error: point p%d is outside facet f%d, distance= %6.8g maxoutside= %6.8g\n",
-              qh_pointid(point), facet->id, dist, *maxoutside);
-  }
-  maximize_(*maxdist, dist);
-} /* qh_check_point */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="check_points">-</a>
-
-  qh_check_points()
-    checks that all points are inside all facets
-
-  notes:
-    if many points and qh_check_maxout not called (i.e., !qh.MERGING),
-       calls qh_findbesthorizon (seldom done).
-    ignores flipped facets
-    maxoutside includes 2 qh.DISTrounds
-      one qh.DISTround for the computed distances in qh_check_points
-    qh_printafacet and qh_printsummary needs only one qh.DISTround
-    the computation for qh.VERIFYdirect does not account for qh.other_points
-
-  design:
-    if many points
-      use qh_check_bestdist()
-    else
-      for all facets
-        for all points
-          check that point is inside facet
-*/
-void qh_check_points(void) {
-  facetT *facet, *errfacet1= NULL, *errfacet2= NULL;
-  realT total, maxoutside, maxdist= -REALmax;
-  pointT *point, **pointp, *pointtemp;
-  boolT testouter;
-
-  maxoutside= qh_maxouter();
-  maxoutside += qh DISTround;
-  /* one more qh.DISTround for check computation */
-  trace1((qh ferr, 1025, "qh_check_points: check all points below %2.2g of all facet planes\n",
-          maxoutside));
-  if (qh num_good)   /* miss counts other_points and !good facets */
-     total= (float)qh num_good * (float)qh num_points;
-  else
-     total= (float)qh num_facets * (float)qh num_points;
-  if (total >= qh_VERIFYdirect && !qh maxoutdone) {
-    if (!qh_QUICKhelp && qh SKIPcheckmax && qh MERGING)
-      qh_fprintf(qh ferr, 7075, "qhull input warning: merging without checking outer planes('Q5' or 'Po').\n\
-Verify may report that a point is outside of a facet.\n");
-    qh_check_bestdist();
-  }else {
-    if (qh_MAXoutside && qh maxoutdone)
-      testouter= True;
-    else
-      testouter= False;
-    if (!qh_QUICKhelp) {
-      if (qh MERGEexact)
-        qh_fprintf(qh ferr, 7076, "qhull input warning: exact merge ('Qx').  Verify may report that a point\n\
-is outside of a facet.  See qh-optq.htm#Qx\n");
-      else if (qh SKIPcheckmax || qh NOnearinside)
-        qh_fprintf(qh ferr, 7077, "qhull input warning: no outer plane check ('Q5') or no processing of\n\
-near-inside points ('Q8').  Verify may report that a point is outside\n\
-of a facet.\n");
-    }
-    if (qh PRINTprecision) {
-      if (testouter)
-        qh_fprintf(qh ferr, 8098, "\n\
-Output completed.  Verifying that all points are below outer planes of\n\
-all %sfacets.  Will make %2.0f distance computations.\n",
-              (qh ONLYgood ?  "good " : ""), total);
-      else
-        qh_fprintf(qh ferr, 8099, "\n\
-Output completed.  Verifying that all points are below %2.2g of\n\
-all %sfacets.  Will make %2.0f distance computations.\n",
-              maxoutside, (qh ONLYgood ?  "good " : ""), total);
-    }
-    FORALLfacets {
-      if (!facet->good && qh ONLYgood)
-        continue;
-      if (facet->flipped)
-        continue;
-      if (!facet->normal) {
-        qh_fprintf(qh ferr, 7061, "qhull warning (qh_check_points): missing normal for facet f%d\n", facet->id);
-        continue;
-      }
-      if (testouter) {
-#if qh_MAXoutside
-        maxoutside= facet->maxoutside + 2* qh DISTround;
-        /* one DISTround to actual point and another to computed point */
-#endif
-      }
-      FORALLpoints {
-        if (point != qh GOODpointp)
-          qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
-      }
-      FOREACHpoint_(qh other_points) {
-        if (point != qh GOODpointp)
-          qh_check_point(point, facet, &maxoutside, &maxdist, &errfacet1, &errfacet2);
-      }
-    }
-    if (maxdist > qh outside_err) {
-      qh_fprintf(qh ferr, 6112, "qhull precision error (qh_check_points): a coplanar point is %6.2g from convex hull.  The maximum value(qh.outside_err) is %6.2g\n",
-                maxdist, qh outside_err );
-      qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
-    }else if (errfacet1 && qh outside_err > REALmax/2)
-        qh_errexit2( qh_ERRprec, errfacet1, errfacet2 );
-    /* else if errfacet1, the error was logged to qh.ferr but does not effect the output */
-    trace0((qh ferr, 21, "qh_check_points: max distance outside %2.2g\n", maxdist));
-  }
-} /* check_points */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="checkconvex">-</a>
-
-  qh_checkconvex( facetlist, fault )
-    check that each ridge in facetlist is convex
-    fault = qh_DATAfault if reporting errors
-          = qh_ALGORITHMfault otherwise
-
-  returns:
-    counts Zconcaveridges and Zcoplanarridges
-    errors if concaveridge or if merging an coplanar ridge
-
-  note:
-    if not merging,
-      tests vertices for neighboring simplicial facets
-    else if ZEROcentrum,
-      tests vertices for neighboring simplicial   facets
-    else
-      tests centrums of neighboring facets
-
-  design:
-    for all facets
-      report flipped facets
-      if ZEROcentrum and simplicial neighbors
-        test vertices for neighboring simplicial facets
-      else
-        test centrum against all neighbors
-*/
-void qh_checkconvex(facetT *facetlist, int fault) {
-  facetT *facet, *neighbor, **neighborp, *errfacet1=NULL, *errfacet2=NULL;
-  vertexT *vertex;
-  realT dist;
-  pointT *centrum;
-  boolT waserror= False, centrum_warning= False, tempcentrum= False, allsimplicial;
-  int neighbor_i;
-
-  trace1((qh ferr, 1026, "qh_checkconvex: check all ridges are convex\n"));
-  if (!qh RERUN) {
-    zzval_(Zconcaveridges)= 0;
-    zzval_(Zcoplanarridges)= 0;
-  }
-  FORALLfacet_(facetlist) {
-    if (facet->flipped) {
-      qh_precision("flipped facet");
-      qh_fprintf(qh ferr, 6113, "qhull precision error: f%d is flipped(interior point is outside)\n",
-               facet->id);
-      errfacet1= facet;
-      waserror= True;
-      continue;
-    }
-    if (qh MERGING && (!qh ZEROcentrum || !facet->simplicial || facet->tricoplanar))
-      allsimplicial= False;
-    else {
-      allsimplicial= True;
-      neighbor_i= 0;
-      FOREACHneighbor_(facet) {
-        vertex= SETelemt_(facet->vertices, neighbor_i++, vertexT);
-        if (!neighbor->simplicial || neighbor->tricoplanar) {
-          allsimplicial= False;
-          continue;
-        }
-        qh_distplane(vertex->point, neighbor, &dist);
-        if (dist > -qh DISTround) {
-          if (fault == qh_DATAfault) {
-            qh_precision("coplanar or concave ridge");
-            qh_fprintf(qh ferr, 6114, "qhull precision error: initial simplex is not convex. Distance=%.2g\n", dist);
-            qh_errexit(qh_ERRsingular, NULL, NULL);
-          }
-          if (dist > qh DISTround) {
-            zzinc_(Zconcaveridges);
-            qh_precision("concave ridge");
-            qh_fprintf(qh ferr, 6115, "qhull precision error: f%d is concave to f%d, since p%d(v%d) is %6.4g above\n",
-              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
-            errfacet1= facet;
-            errfacet2= neighbor;
-            waserror= True;
-          }else if (qh ZEROcentrum) {
-            if (dist > 0) {     /* qh_checkzero checks that dist < - qh DISTround */
-              zzinc_(Zcoplanarridges);
-              qh_precision("coplanar ridge");
-              qh_fprintf(qh ferr, 6116, "qhull precision error: f%d is clearly not convex to f%d, since p%d(v%d) is %6.4g above\n",
-                facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist);
-              errfacet1= facet;
-              errfacet2= neighbor;
-              waserror= True;
-            }
-          }else {
-            zzinc_(Zcoplanarridges);
-            qh_precision("coplanar ridge");
-            trace0((qh ferr, 22, "qhull precision error: f%d may be coplanar to f%d, since p%d(v%d) is within %6.4g during p%d\n",
-              facet->id, neighbor->id, qh_pointid(vertex->point), vertex->id, dist, qh furthest_id));
-          }
-        }
-      }
-    }
-    if (!allsimplicial) {
-      if (qh CENTERtype == qh_AScentrum) {
-        if (!facet->center)
-          facet->center= qh_getcentrum(facet);
-        centrum= facet->center;
-      }else {
-        if (!centrum_warning && (!facet->simplicial || facet->tricoplanar)) {
-           centrum_warning= True;
-           qh_fprintf(qh ferr, 7062, "qhull warning: recomputing centrums for convexity test.  This may lead to false, precision errors.\n");
-        }
-        centrum= qh_getcentrum(facet);
-        tempcentrum= True;
-      }
-      FOREACHneighbor_(facet) {
-        if (qh ZEROcentrum && facet->simplicial && neighbor->simplicial)
-          continue;
-        if (facet->tricoplanar || neighbor->tricoplanar)
-          continue;
-        zzinc_(Zdistconvex);
-        qh_distplane(centrum, neighbor, &dist);
-        if (dist > qh DISTround) {
-          zzinc_(Zconcaveridges);
-          qh_precision("concave ridge");
-          qh_fprintf(qh ferr, 6117, "qhull precision error: f%d is concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
-            facet->id, neighbor->id, facet->id, dist, neighbor->id);
-          errfacet1= facet;
-          errfacet2= neighbor;
-          waserror= True;
-        }else if (dist >= 0.0) {   /* if arithmetic always rounds the same,
-                                     can test against centrum radius instead */
-          zzinc_(Zcoplanarridges);
-          qh_precision("coplanar ridge");
-          qh_fprintf(qh ferr, 6118, "qhull precision error: f%d is coplanar or concave to f%d.  Centrum of f%d is %6.4g above f%d\n",
-            facet->id, neighbor->id, facet->id, dist, neighbor->id);
-          errfacet1= facet;
-          errfacet2= neighbor;
-          waserror= True;
-        }
-      }
-      if (tempcentrum)
-        qh_memfree(centrum, qh normal_size);
-    }
-  }
-  if (waserror && !qh FORCEoutput)
-    qh_errexit2 (qh_ERRprec, errfacet1, errfacet2);
-} /* checkconvex */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="checkfacet">-</a>
-
-  qh_checkfacet( facet, newmerge, waserror )
-    checks for consistency errors in facet
-    newmerge set if from merge.c
-
-  returns:
-    sets waserror if any error occurs
-
-  checks:
-    vertex ids are inverse sorted
-    unless newmerge, at least hull_dim neighbors and vertices (exactly if simplicial)
-    if non-simplicial, at least as many ridges as neighbors
-    neighbors are not duplicated
-    ridges are not duplicated
-    in 3-d, ridges=verticies
-    (qh.hull_dim-1) ridge vertices
-    neighbors are reciprocated
-    ridge neighbors are facet neighbors and a ridge for every neighbor
-    simplicial neighbors match facetintersect
-    vertex intersection matches vertices of common ridges
-    vertex neighbors and facet vertices agree
-    all ridges have distinct vertex sets
-
-  notes:
-    uses neighbor->seen
-
-  design:
-    check sets
-    check vertices
-    check sizes of neighbors and vertices
-    check for qh_MERGEridge and qh_DUPLICATEridge flags
-    check neighbor set
-    check ridge set
-    check ridges, neighbors, and vertices
-*/
-void qh_checkfacet(facetT *facet, boolT newmerge, boolT *waserrorp) {
-  facetT *neighbor, **neighborp, *errother=NULL;
-  ridgeT *ridge, **ridgep, *errridge= NULL, *ridge2;
-  vertexT *vertex, **vertexp;
-  unsigned previousid= INT_MAX;
-  int numneighbors, numvertices, numridges=0, numRvertices=0;
-  boolT waserror= False;
-  int skipA, skipB, ridge_i, ridge_n, i;
-  setT *intersection;
-
-  if (facet->visible) {
-    qh_fprintf(qh ferr, 6119, "qhull internal error (qh_checkfacet): facet f%d is on the visible_list\n",
-      facet->id);
-    qh_errexit(qh_ERRqhull, facet, NULL);
-  }
-  if (!facet->normal) {
-    qh_fprintf(qh ferr, 6120, "qhull internal error (qh_checkfacet): facet f%d does not have  a normal\n",
-      facet->id);
-    waserror= True;
-  }
-  qh_setcheck(facet->vertices, "vertices for f", facet->id);
-  qh_setcheck(facet->ridges, "ridges for f", facet->id);
-  qh_setcheck(facet->outsideset, "outsideset for f", facet->id);
-  qh_setcheck(facet->coplanarset, "coplanarset for f", facet->id);
-  qh_setcheck(facet->neighbors, "neighbors for f", facet->id);
-  FOREACHvertex_(facet->vertices) {
-    if (vertex->deleted) {
-      qh_fprintf(qh ferr, 6121, "qhull internal error (qh_checkfacet): deleted vertex v%d in f%d\n", vertex->id, facet->id);
-      qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
-      waserror= True;
-    }
-    if (vertex->id >= previousid) {
-      qh_fprintf(qh ferr, 6122, "qhull internal error (qh_checkfacet): vertices of f%d are not in descending id order at v%d\n", facet->id, vertex->id);
-      waserror= True;
-      break;
-    }
-    previousid= vertex->id;
-  }
-  numneighbors= qh_setsize(facet->neighbors);
-  numvertices= qh_setsize(facet->vertices);
-  numridges= qh_setsize(facet->ridges);
-  if (facet->simplicial) {
-    if (numvertices+numneighbors != 2*qh hull_dim
-    && !facet->degenerate && !facet->redundant) {
-      qh_fprintf(qh ferr, 6123, "qhull internal error (qh_checkfacet): for simplicial facet f%d, #vertices %d + #neighbors %d != 2*qh hull_dim\n",
-                facet->id, numvertices, numneighbors);
-      qh_setprint(qh ferr, "", facet->neighbors);
-      waserror= True;
-    }
-  }else { /* non-simplicial */
-    if (!newmerge
-    &&(numvertices < qh hull_dim || numneighbors < qh hull_dim)
-    && !facet->degenerate && !facet->redundant) {
-      qh_fprintf(qh ferr, 6124, "qhull internal error (qh_checkfacet): for facet f%d, #vertices %d or #neighbors %d < qh hull_dim\n",
-         facet->id, numvertices, numneighbors);
-       waserror= True;
-    }
-    /* in 3-d, can get a vertex twice in an edge list, e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv TP624 TW1e-13 T4 */
-    if (numridges < numneighbors
-    ||(qh hull_dim == 3 && numvertices > numridges && !qh NEWfacets)
-    ||(qh hull_dim == 2 && numridges + numvertices + numneighbors != 6)) {
-      if (!facet->degenerate && !facet->redundant) {
-        qh_fprintf(qh ferr, 6125, "qhull internal error (qh_checkfacet): for facet f%d, #ridges %d < #neighbors %d or(3-d) > #vertices %d or(2-d) not all 2\n",
-            facet->id, numridges, numneighbors, numvertices);
-        waserror= True;
-      }
-    }
-  }
-  FOREACHneighbor_(facet) {
-    if (neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge) {
-      qh_fprintf(qh ferr, 6126, "qhull internal error (qh_checkfacet): facet f%d still has a MERGE or DUP neighbor\n", facet->id);
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-    neighbor->seen= True;
-  }
-  FOREACHneighbor_(facet) {
-    if (!qh_setin(neighbor->neighbors, facet)) {
-      qh_fprintf(qh ferr, 6127, "qhull internal error (qh_checkfacet): facet f%d has neighbor f%d, but f%d does not have neighbor f%d\n",
-              facet->id, neighbor->id, neighbor->id, facet->id);
-      errother= neighbor;
-      waserror= True;
-    }
-    if (!neighbor->seen) {
-      qh_fprintf(qh ferr, 6128, "qhull internal error (qh_checkfacet): facet f%d has a duplicate neighbor f%d\n",
-              facet->id, neighbor->id);
-      errother= neighbor;
-      waserror= True;
-    }
-    neighbor->seen= False;
-  }
-  FOREACHridge_(facet->ridges) {
-    qh_setcheck(ridge->vertices, "vertices for r", ridge->id);
-    ridge->seen= False;
-  }
-  FOREACHridge_(facet->ridges) {
-    if (ridge->seen) {
-      qh_fprintf(qh ferr, 6129, "qhull internal error (qh_checkfacet): facet f%d has a duplicate ridge r%d\n",
-              facet->id, ridge->id);
-      errridge= ridge;
-      waserror= True;
-    }
-    ridge->seen= True;
-    numRvertices= qh_setsize(ridge->vertices);
-    if (numRvertices != qh hull_dim - 1) {
-      qh_fprintf(qh ferr, 6130, "qhull internal error (qh_checkfacet): ridge between f%d and f%d has %d vertices\n",
-                ridge->top->id, ridge->bottom->id, numRvertices);
-      errridge= ridge;
-      waserror= True;
-    }
-    neighbor= otherfacet_(ridge, facet);
-    neighbor->seen= True;
-    if (!qh_setin(facet->neighbors, neighbor)) {
-      qh_fprintf(qh ferr, 6131, "qhull internal error (qh_checkfacet): for facet f%d, neighbor f%d of ridge r%d not in facet\n",
-           facet->id, neighbor->id, ridge->id);
-      errridge= ridge;
-      waserror= True;
-    }
-  }
-  if (!facet->simplicial) {
-    FOREACHneighbor_(facet) {
-      if (!neighbor->seen) {
-        qh_fprintf(qh ferr, 6132, "qhull internal error (qh_checkfacet): facet f%d does not have a ridge for neighbor f%d\n",
-              facet->id, neighbor->id);
-        errother= neighbor;
-        waserror= True;
-      }
-      intersection= qh_vertexintersect_new(facet->vertices, neighbor->vertices);
-      qh_settemppush(intersection);
-      FOREACHvertex_(facet->vertices) {
-        vertex->seen= False;
-        vertex->seen2= False;
-      }
-      FOREACHvertex_(intersection)
-        vertex->seen= True;
-      FOREACHridge_(facet->ridges) {
-        if (neighbor != otherfacet_(ridge, facet))
-            continue;
-        FOREACHvertex_(ridge->vertices) {
-          if (!vertex->seen) {
-            qh_fprintf(qh ferr, 6133, "qhull internal error (qh_checkfacet): vertex v%d in r%d not in f%d intersect f%d\n",
-                  vertex->id, ridge->id, facet->id, neighbor->id);
-            qh_errexit(qh_ERRqhull, facet, ridge);
-          }
-          vertex->seen2= True;
-        }
-      }
-      if (!newmerge) {
-        FOREACHvertex_(intersection) {
-          if (!vertex->seen2) {
-            if (qh IStracing >=3 || !qh MERGING) {
-              qh_fprintf(qh ferr, 6134, "qhull precision error (qh_checkfacet): vertex v%d in f%d intersect f%d but\n\
- not in a ridge.  This is ok under merging.  Last point was p%d\n",
-                     vertex->id, facet->id, neighbor->id, qh furthest_id);
-              if (!qh FORCEoutput && !qh MERGING) {
-                qh_errprint("ERRONEOUS", facet, neighbor, NULL, vertex);
-                if (!qh MERGING)
-                  qh_errexit(qh_ERRqhull, NULL, NULL);
-              }
-            }
-          }
-        }
-      }
-      qh_settempfree(&intersection);
-    }
-  }else { /* simplicial */
-    FOREACHneighbor_(facet) {
-      if (neighbor->simplicial) {
-        skipA= SETindex_(facet->neighbors, neighbor);
-        skipB= qh_setindex(neighbor->neighbors, facet);
-        if (skipB >= 0 && !qh_setequal_skip(facet->vertices, skipA, neighbor->vertices, skipB)) {
-          qh_fprintf(qh ferr, 6135, "qhull internal error (qh_checkfacet): facet f%d skip %d and neighbor f%d skip %d do not match \n",
-                   facet->id, skipA, neighbor->id, skipB);
-          errother= neighbor;
-          waserror= True;
-        }
-      }
-    }
-  }
-  if (qh hull_dim < 5 && (qh IStracing > 2 || qh CHECKfrequently)) {
-    FOREACHridge_i_(facet->ridges) {           /* expensive */
-      for (i=ridge_i+1; i < ridge_n; i++) {
-        ridge2= SETelemt_(facet->ridges, i, ridgeT);
-        if (qh_setequal(ridge->vertices, ridge2->vertices)) {
-          qh_fprintf(qh ferr, 6227, "Qhull internal error (qh_checkfacet): ridges r%d and r%d have the same vertices\n",
-                  ridge->id, ridge2->id);
-          errridge= ridge;
-          waserror= True;
-        }
-      }
-    }
-  }
-  if (waserror) {
-    qh_errprint("ERRONEOUS", facet, errother, errridge, NULL);
-    *waserrorp= True;
-  }
-} /* checkfacet */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="checkflipped_all">-</a>
-
-  qh_checkflipped_all( facetlist )
-    checks orientation of facets in list against interior point
-*/
-void qh_checkflipped_all(facetT *facetlist) {
-  facetT *facet;
-  boolT waserror= False;
-  realT dist;
-
-  if (facetlist == qh facet_list)
-    zzval_(Zflippedfacets)= 0;
-  FORALLfacet_(facetlist) {
-    if (facet->normal && !qh_checkflipped(facet, &dist, !qh_ALL)) {
-      qh_fprintf(qh ferr, 6136, "qhull precision error: facet f%d is flipped, distance= %6.12g\n",
-              facet->id, dist);
-      if (!qh FORCEoutput) {
-        qh_errprint("ERRONEOUS", facet, NULL, NULL, NULL);
-        waserror= True;
-      }
-    }
-  }
-  if (waserror) {
-    qh_fprintf(qh ferr, 8101, "\n\
-A flipped facet occurs when its distance to the interior point is\n\
-greater than %2.2g, the maximum roundoff error.\n", -qh DISTround);
-    qh_errexit(qh_ERRprec, NULL, NULL);
-  }
-} /* checkflipped_all */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="checkpolygon">-</a>
-
-  qh_checkpolygon( facetlist )
-    checks the correctness of the structure
-
-  notes:
-    call with either qh.facet_list or qh.newfacet_list
-    checks num_facets and num_vertices if qh.facet_list
-
-  design:
-    for each facet
-      checks facet and outside set
-    initializes vertexlist
-    for each facet
-      checks vertex set
-    if checking all facets(qh.facetlist)
-      check facet count
-      if qh.VERTEXneighbors
-        check vertex neighbors and count
-      check vertex count
-*/
-void qh_checkpolygon(facetT *facetlist) {
-  facetT *facet;
-  vertexT *vertex, **vertexp, *vertexlist;
-  int numfacets= 0, numvertices= 0, numridges= 0;
-  int totvneighbors= 0, totvertices= 0;
-  boolT waserror= False, nextseen= False, visibleseen= False;
-
-  trace1((qh ferr, 1027, "qh_checkpolygon: check all facets from f%d\n", facetlist->id));
-  if (facetlist != qh facet_list || qh ONLYgood)
-    nextseen= True;
-  FORALLfacet_(facetlist) {
-    if (facet == qh visible_list)
-      visibleseen= True;
-    if (!facet->visible) {
-      if (!nextseen) {
-        if (facet == qh facet_next)
-          nextseen= True;
-        else if (qh_setsize(facet->outsideset)) {
-          if (!qh NARROWhull
-#if !qh_COMPUTEfurthest
-               || facet->furthestdist >= qh MINoutside
-#endif
-                        ) {
-            qh_fprintf(qh ferr, 6137, "qhull internal error (qh_checkpolygon): f%d has outside points before qh facet_next\n",
-                     facet->id);
-            qh_errexit(qh_ERRqhull, facet, NULL);
-          }
-        }
-      }
-      numfacets++;
-      qh_checkfacet(facet, False, &waserror);
-    }
-  }
-  if (qh visible_list && !visibleseen && facetlist == qh facet_list) {
-    qh_fprintf(qh ferr, 6138, "qhull internal error (qh_checkpolygon): visible list f%d no longer on facet list\n", qh visible_list->id);
-    qh_printlists();
-    qh_errexit(qh_ERRqhull, qh visible_list, NULL);
-  }
-  if (facetlist == qh facet_list)
-    vertexlist= qh vertex_list;
-  else if (facetlist == qh newfacet_list)
-    vertexlist= qh newvertex_list;
-  else
-    vertexlist= NULL;
-  FORALLvertex_(vertexlist) {
-    vertex->seen= False;
-    vertex->visitid= 0;
-  }
-  FORALLfacet_(facetlist) {
-    if (facet->visible)
-      continue;
-    if (facet->simplicial)
-      numridges += qh hull_dim;
-    else
-      numridges += qh_setsize(facet->ridges);
-    FOREACHvertex_(facet->vertices) {
-      vertex->visitid++;
-      if (!vertex->seen) {
-        vertex->seen= True;
-        numvertices++;
-        if (qh_pointid(vertex->point) == -1) {
-          qh_fprintf(qh ferr, 6139, "qhull internal error (qh_checkpolygon): unknown point %p for vertex v%d first_point %p\n",
-                   vertex->point, vertex->id, qh first_point);
-          waserror= True;
-        }
-      }
-    }
-  }
-  qh vertex_visit += (unsigned int)numfacets;
-  if (facetlist == qh facet_list) {
-    if (numfacets != qh num_facets - qh num_visible) {
-      qh_fprintf(qh ferr, 6140, "qhull internal error (qh_checkpolygon): actual number of facets is %d, cumulative facet count is %d - %d visible facets\n",
-              numfacets, qh num_facets, qh num_visible);
-      waserror= True;
-    }
-    qh vertex_visit++;
-    if (qh VERTEXneighbors) {
-      FORALLvertices {
-        qh_setcheck(vertex->neighbors, "neighbors for v", vertex->id);
-        if (vertex->deleted)
-          continue;
-        totvneighbors += qh_setsize(vertex->neighbors);
-      }
-      FORALLfacet_(facetlist)
-        totvertices += qh_setsize(facet->vertices);
-      if (totvneighbors != totvertices) {
-        qh_fprintf(qh ferr, 6141, "qhull internal error (qh_checkpolygon): vertex neighbors inconsistent.  Totvneighbors %d, totvertices %d\n",
-                totvneighbors, totvertices);
-        waserror= True;
-      }
-    }
-    if (numvertices != qh num_vertices - qh_setsize(qh del_vertices)) {
-      qh_fprintf(qh ferr, 6142, "qhull internal error (qh_checkpolygon): actual number of vertices is %d, cumulative vertex count is %d\n",
-              numvertices, qh num_vertices - qh_setsize(qh del_vertices));
-      waserror= True;
-    }
-    if (qh hull_dim == 2 && numvertices != numfacets) {
-      qh_fprintf(qh ferr, 6143, "qhull internal error (qh_checkpolygon): #vertices %d != #facets %d\n",
-        numvertices, numfacets);
-      waserror= True;
-    }
-    if (qh hull_dim == 3 && numvertices + numfacets - numridges/2 != 2) {
-      qh_fprintf(qh ferr, 7063, "qhull warning: #vertices %d + #facets %d - #edges %d != 2\n\
-        A vertex appears twice in a edge list.  May occur during merging.",
-        numvertices, numfacets, numridges/2);
-      /* occurs if lots of merging and a vertex ends up twice in an edge list.  e.g., RBOX 1000 s W1e-13 t995849315 D2 | QHULL d Tc Tv */
-    }
-  }
-  if (waserror)
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-} /* checkpolygon */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="checkvertex">-</a>
-
-  qh_checkvertex( vertex )
-    check vertex for consistency
-    checks vertex->neighbors
-
-  notes:
-    neighbors checked efficiently in checkpolygon
-*/
-void qh_checkvertex(vertexT *vertex) {
-  boolT waserror= False;
-  facetT *neighbor, **neighborp, *errfacet=NULL;
-
-  if (qh_pointid(vertex->point) == -1) {
-    qh_fprintf(qh ferr, 6144, "qhull internal error (qh_checkvertex): unknown point id %p\n", vertex->point);
-    waserror= True;
-  }
-  if (vertex->id >= qh vertex_id) {
-    qh_fprintf(qh ferr, 6145, "qhull internal error (qh_checkvertex): unknown vertex id %d\n", vertex->id);
-    waserror= True;
-  }
-  if (!waserror && !vertex->deleted) {
-    if (qh_setsize(vertex->neighbors)) {
-      FOREACHneighbor_(vertex) {
-        if (!qh_setin(neighbor->vertices, vertex)) {
-          qh_fprintf(qh ferr, 6146, "qhull internal error (qh_checkvertex): neighbor f%d does not contain v%d\n", neighbor->id, vertex->id);
-          errfacet= neighbor;
-          waserror= True;
-        }
-      }
-    }
-  }
-  if (waserror) {
-    qh_errprint("ERRONEOUS", NULL, NULL, NULL, vertex);
-    qh_errexit(qh_ERRqhull, errfacet, NULL);
-  }
-} /* checkvertex */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="clearcenters">-</a>
-
-  qh_clearcenters( type )
-    clear old data from facet->center
-
-  notes:
-    sets new centertype
-    nop if CENTERtype is the same
-*/
-void qh_clearcenters(qh_CENTER type) {
-  facetT *facet;
-
-  if (qh CENTERtype != type) {
-    FORALLfacets {
-      if (facet->tricoplanar && !facet->keepcentrum)
-          facet->center= NULL;
-      else if (qh CENTERtype == qh_ASvoronoi){
-        if (facet->center) {
-          qh_memfree(facet->center, qh center_size);
-          facet->center= NULL;
-        }
-      }else /* qh CENTERtype == qh_AScentrum */ {
-        if (facet->center) {
-          qh_memfree(facet->center, qh normal_size);
-          facet->center= NULL;
-        }
-      }
-    }
-    qh CENTERtype= type;
-  }
-  trace2((qh ferr, 2043, "qh_clearcenters: switched to center type %d\n", type));
-} /* clearcenters */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="createsimplex">-</a>
-
-  qh_createsimplex( vertices )
-    creates a simplex from a set of vertices
-
-  returns:
-    initializes qh.facet_list to the simplex
-    initializes qh.newfacet_list, .facet_tail
-    initializes qh.vertex_list, .newvertex_list, .vertex_tail
-
-  design:
-    initializes lists
-    for each vertex
-      create a new facet
-    for each new facet
-      create its neighbor set
-*/
-void qh_createsimplex(setT *vertices) {
-  facetT *facet= NULL, *newfacet;
-  boolT toporient= True;
-  int vertex_i, vertex_n, nth;
-  setT *newfacets= qh_settemp(qh hull_dim+1);
-  vertexT *vertex;
-
-  qh facet_list= qh newfacet_list= qh facet_tail= qh_newfacet();
-  qh num_facets= qh num_vertices= qh num_visible= 0;
-  qh vertex_list= qh newvertex_list= qh vertex_tail= qh_newvertex(NULL);
-  FOREACHvertex_i_(vertices) {
-    newfacet= qh_newfacet();
-    newfacet->vertices= qh_setnew_delnthsorted(vertices, vertex_n,
-                                                vertex_i, 0);
-    newfacet->toporient= (unsigned char)toporient;
-    qh_appendfacet(newfacet);
-    newfacet->newfacet= True;
-    qh_appendvertex(vertex);
-    qh_setappend(&newfacets, newfacet);
-    toporient ^= True;
-  }
-  FORALLnew_facets {
-    nth= 0;
-    FORALLfacet_(qh newfacet_list) {
-      if (facet != newfacet)
-        SETelem_(newfacet->neighbors, nth++)= facet;
-    }
-    qh_settruncate(newfacet->neighbors, qh hull_dim);
-  }
-  qh_settempfree(&newfacets);
-  trace1((qh ferr, 1028, "qh_createsimplex: created simplex\n"));
-} /* createsimplex */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="delridge">-</a>
-
-  qh_delridge( ridge )
-    deletes ridge from data structures it belongs to
-    frees up its memory
-
-  notes:
-    in merge.c, caller sets vertex->delridge for each vertex
-    ridges also freed in qh_freeqhull
-*/
-void qh_delridge(ridgeT *ridge) {
-  void **freelistp; /* used !qh_NOmem */
-
-  qh_setdel(ridge->top->ridges, ridge);
-  qh_setdel(ridge->bottom->ridges, ridge);
-  qh_setfree(&(ridge->vertices));
-  qh_memfree_(ridge, (int)sizeof(ridgeT), freelistp);
-} /* delridge */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="delvertex">-</a>
-
-  qh_delvertex( vertex )
-    deletes a vertex and frees its memory
-
-  notes:
-    assumes vertex->adjacencies have been updated if needed
-    unlinks from vertex_list
-*/
-void qh_delvertex(vertexT *vertex) {
-
-  if (vertex == qh tracevertex)
-    qh tracevertex= NULL;
-  qh_removevertex(vertex);
-  qh_setfree(&vertex->neighbors);
-  qh_memfree(vertex, (int)sizeof(vertexT));
-} /* delvertex */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="facet3vertex">-</a>
-
-  qh_facet3vertex(  )
-    return temporary set of 3-d vertices in qh_ORIENTclock order
-
-  design:
-    if simplicial facet
-      build set from facet->vertices with facet->toporient
-    else
-      for each ridge in order
-        build set from ridge's vertices
-*/
-setT *qh_facet3vertex(facetT *facet) {
-  ridgeT *ridge, *firstridge;
-  vertexT *vertex;
-  int cntvertices, cntprojected=0;
-  setT *vertices;
-
-  cntvertices= qh_setsize(facet->vertices);
-  vertices= qh_settemp(cntvertices);
-  if (facet->simplicial) {
-    if (cntvertices != 3) {
-      qh_fprintf(qh ferr, 6147, "qhull internal error (qh_facet3vertex): only %d vertices for simplicial facet f%d\n",
-                  cntvertices, facet->id);
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-    qh_setappend(&vertices, SETfirst_(facet->vertices));
-    if (facet->toporient ^ qh_ORIENTclock)
-      qh_setappend(&vertices, SETsecond_(facet->vertices));
-    else
-      qh_setaddnth(&vertices, 0, SETsecond_(facet->vertices));
-    qh_setappend(&vertices, SETelem_(facet->vertices, 2));
-  }else {
-    ridge= firstridge= SETfirstt_(facet->ridges, ridgeT);   /* no infinite */
-    while ((ridge= qh_nextridge3d(ridge, facet, &vertex))) {
-      qh_setappend(&vertices, vertex);
-      if (++cntprojected > cntvertices || ridge == firstridge)
-        break;
-    }
-    if (!ridge || cntprojected != cntvertices) {
-      qh_fprintf(qh ferr, 6148, "qhull internal error (qh_facet3vertex): ridges for facet %d don't match up.  got at least %d\n",
-                  facet->id, cntprojected);
-      qh_errexit(qh_ERRqhull, facet, ridge);
-    }
-  }
-  return vertices;
-} /* facet3vertex */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="findbestfacet">-</a>
-
-  qh_findbestfacet( point, bestoutside, bestdist, isoutside )
-    find facet that is furthest below a point
-
-    for Delaunay triangulations,
-      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
-      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
-
-  returns:
-    if bestoutside is set (e.g., qh_ALL)
-      returns best facet that is not upperdelaunay
-      if Delaunay and inside, point is outside circumsphere of bestfacet
-    else
-      returns first facet below point
-      if point is inside, returns nearest, !upperdelaunay facet
-    distance to facet
-    isoutside set if outside of facet
-
-  notes:
-    For tricoplanar facets, this finds one of the tricoplanar facets closest
-    to the point.  For Delaunay triangulations, the point may be inside a
-    different tricoplanar facet. See <a href="../html/qh-code.htm#findfacet">locate a facet with qh_findbestfacet()</a>
-
-    If inside, qh_findbestfacet performs an exhaustive search
-       this may be too conservative.  Sometimes it is clearly required.
-
-    qh_findbestfacet is not used by qhull.
-    uses qh.visit_id and qh.coplanarset
-
-  see:
-    <a href="geom.c#findbest">qh_findbest</a>
-*/
-facetT *qh_findbestfacet(pointT *point, boolT bestoutside,
-           realT *bestdist, boolT *isoutside) {
-  facetT *bestfacet= NULL;
-  int numpart, totpart= 0;
-
-  bestfacet= qh_findbest(point, qh facet_list,
-                            bestoutside, !qh_ISnewfacets, bestoutside /* qh_NOupper */,
-                            bestdist, isoutside, &totpart);
-  if (*bestdist < -qh DISTround) {
-    bestfacet= qh_findfacet_all(point, bestdist, isoutside, &numpart);
-    totpart += numpart;
-    if ((isoutside && bestoutside)
-    || (!isoutside && bestfacet->upperdelaunay)) {
-      bestfacet= qh_findbest(point, bestfacet,
-                            bestoutside, False, bestoutside,
-                            bestdist, isoutside, &totpart);
-      totpart += numpart;
-    }
-  }
-  trace3((qh ferr, 3014, "qh_findbestfacet: f%d dist %2.2g isoutside %d totpart %d\n",
-          bestfacet->id, *bestdist, *isoutside, totpart));
-  return bestfacet;
-} /* findbestfacet */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="findbestlower">-</a>
-
-  qh_findbestlower( facet, point, bestdist, numpart )
-    returns best non-upper, non-flipped neighbor of facet for point
-    if needed, searches vertex neighbors
-
-  returns:
-    returns bestdist and updates numpart
-
-  notes:
-    if Delaunay and inside, point is outside of circumsphere of bestfacet
-    called by qh_findbest() for points above an upperdelaunay facet
-
-*/
-facetT *qh_findbestlower(facetT *upperfacet, pointT *point, realT *bestdistp, int *numpart) {
-  facetT *neighbor, **neighborp, *bestfacet= NULL;
-  realT bestdist= -REALmax/2 /* avoid underflow */;
-  realT dist;
-  vertexT *vertex;
-
-  zinc_(Zbestlower);
-  FOREACHneighbor_(upperfacet) {
-    if (neighbor->upperdelaunay || neighbor->flipped)
-      continue;
-    (*numpart)++;
-    qh_distplane(point, neighbor, &dist);
-    if (dist > bestdist) {
-      bestfacet= neighbor;
-      bestdist= dist;
-    }
-  }
-  if (!bestfacet) {
-    zinc_(Zbestlowerv);
-    /* rarely called, numpart does not count nearvertex computations */
-    vertex= qh_nearvertex(upperfacet, point, &dist);
-    qh_vertexneighbors();
-    FOREACHneighbor_(vertex) {
-      if (neighbor->upperdelaunay || neighbor->flipped)
-        continue;
-      (*numpart)++;
-      qh_distplane(point, neighbor, &dist);
-      if (dist > bestdist) {
-        bestfacet= neighbor;
-        bestdist= dist;
-      }
-    }
-  }
-  if (!bestfacet) {
-    qh_fprintf(qh ferr, 6228, "\n\
-Qhull internal error (qh_findbestlower): all neighbors of facet %d are flipped or upper Delaunay.\n\
-Please report this error to qhull_bug at qhull.org with the input and all of the output.\n",
-       upperfacet->id);
-    qh_errexit(qh_ERRqhull, upperfacet, NULL);
-  }
-  *bestdistp= bestdist;
-  trace3((qh ferr, 3015, "qh_findbestlower: f%d dist %2.2g for f%d p%d\n",
-          bestfacet->id, bestdist, upperfacet->id, qh_pointid(point)));
-  return bestfacet;
-} /* findbestlower */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="findfacet_all">-</a>
-
-  qh_findfacet_all( point, bestdist, isoutside, numpart )
-    exhaustive search for facet below a point
-
-    for Delaunay triangulations,
-      Use qh_setdelaunay() to lift point to paraboloid and scale by 'Qbb' if needed
-      Do not use options 'Qbk', 'QBk', or 'QbB' since they scale the coordinates.
-
-  returns:
-    returns first facet below point
-    if point is inside,
-      returns nearest facet
-    distance to facet
-    isoutside if point is outside of the hull
-    number of distance tests
-
-  notes:
-    for library users, not used by Qhull
-*/
-facetT *qh_findfacet_all(pointT *point, realT *bestdist, boolT *isoutside,
-                          int *numpart) {
-  facetT *bestfacet= NULL, *facet;
-  realT dist;
-  int totpart= 0;
-
-  *bestdist= -REALmax;
-  *isoutside= False;
-  FORALLfacets {
-    if (facet->flipped || !facet->normal)
-      continue;
-    totpart++;
-    qh_distplane(point, facet, &dist);
-    if (dist > *bestdist) {
-      *bestdist= dist;
-      bestfacet= facet;
-      if (dist > qh MINoutside) {
-        *isoutside= True;
-        break;
-      }
-    }
-  }
-  *numpart= totpart;
-  trace3((qh ferr, 3016, "qh_findfacet_all: f%d dist %2.2g isoutside %d totpart %d\n",
-          getid_(bestfacet), *bestdist, *isoutside, totpart));
-  return bestfacet;
-} /* findfacet_all */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="findgood">-</a>
-
-  qh_findgood( facetlist, goodhorizon )
-    identify good facets for qh.PRINTgood
-    if qh.GOODvertex>0
-      facet includes point as vertex
-      if !match, returns goodhorizon
-      inactive if qh.MERGING
-    if qh.GOODpoint
-      facet is visible or coplanar (>0) or not visible (<0)
-    if qh.GOODthreshold
-      facet->normal matches threshold
-    if !goodhorizon and !match,
-      selects facet with closest angle
-      sets GOODclosest
-
-  returns:
-    number of new, good facets found
-    determines facet->good
-    may update qh.GOODclosest
-
-  notes:
-    qh_findgood_all further reduces the good region
-
-  design:
-    count good facets
-    mark good facets for qh.GOODpoint
-    mark good facets for qh.GOODthreshold
-    if necessary
-      update qh.GOODclosest
-*/
-int qh_findgood(facetT *facetlist, int goodhorizon) {
-  facetT *facet, *bestfacet= NULL;
-  realT angle, bestangle= REALmax, dist;
-  int  numgood=0;
-
-  FORALLfacet_(facetlist) {
-    if (facet->good)
-      numgood++;
-  }
-  if (qh GOODvertex>0 && !qh MERGING) {
-    FORALLfacet_(facetlist) {
-      if (!qh_isvertex(qh GOODvertexp, facet->vertices)) {
-        facet->good= False;
-        numgood--;
-      }
-    }
-  }
-  if (qh GOODpoint && numgood) {
-    FORALLfacet_(facetlist) {
-      if (facet->good && facet->normal) {
-        zinc_(Zdistgood);
-        qh_distplane(qh GOODpointp, facet, &dist);
-        if ((qh GOODpoint > 0) ^ (dist > 0.0)) {
-          facet->good= False;
-          numgood--;
-        }
-      }
-    }
-  }
-  if (qh GOODthreshold && (numgood || goodhorizon || qh GOODclosest)) {
-    FORALLfacet_(facetlist) {
-      if (facet->good && facet->normal) {
-        if (!qh_inthresholds(facet->normal, &angle)) {
-          facet->good= False;
-          numgood--;
-          if (angle < bestangle) {
-            bestangle= angle;
-            bestfacet= facet;
-          }
-        }
-      }
-    }
-    if (!numgood && (!goodhorizon || qh GOODclosest)) {
-      if (qh GOODclosest) {
-        if (qh GOODclosest->visible)
-          qh GOODclosest= NULL;
-        else {
-          qh_inthresholds(qh GOODclosest->normal, &angle);
-          if (angle < bestangle)
-            bestfacet= qh GOODclosest;
-        }
-      }
-      if (bestfacet && bestfacet != qh GOODclosest) {
-        if (qh GOODclosest)
-          qh GOODclosest->good= False;
-        qh GOODclosest= bestfacet;
-        bestfacet->good= True;
-        numgood++;
-        trace2((qh ferr, 2044, "qh_findgood: f%d is closest(%2.2g) to thresholds\n",
-           bestfacet->id, bestangle));
-        return numgood;
-      }
-    }else if (qh GOODclosest) { /* numgood > 0 */
-      qh GOODclosest->good= False;
-      qh GOODclosest= NULL;
-    }
-  }
-  zadd_(Zgoodfacet, numgood);
-  trace2((qh ferr, 2045, "qh_findgood: found %d good facets with %d good horizon\n",
-               numgood, goodhorizon));
-  if (!numgood && qh GOODvertex>0 && !qh MERGING)
-    return goodhorizon;
-  return numgood;
-} /* findgood */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="findgood_all">-</a>
-
-  qh_findgood_all( facetlist )
-    apply other constraints for good facets (used by qh.PRINTgood)
-    if qh.GOODvertex
-      facet includes (>0) or doesn't include (<0) point as vertex
-      if last good facet and ONLYgood, prints warning and continues
-    if qh.SPLITthresholds
-      facet->normal matches threshold, or if none, the closest one
-    calls qh_findgood
-    nop if good not used
-
-  returns:
-    clears facet->good if not good
-    sets qh.num_good
-
-  notes:
-    this is like qh_findgood but more restrictive
-
-  design:
-    uses qh_findgood to mark good facets
-    marks facets for qh.GOODvertex
-    marks facets for qh.SPLITthreholds
-*/
-void qh_findgood_all(facetT *facetlist) {
-  facetT *facet, *bestfacet=NULL;
-  realT angle, bestangle= REALmax;
-  int  numgood=0, startgood;
-
-  if (!qh GOODvertex && !qh GOODthreshold && !qh GOODpoint
-  && !qh SPLITthresholds)
-    return;
-  if (!qh ONLYgood)
-    qh_findgood(qh facet_list, 0);
-  FORALLfacet_(facetlist) {
-    if (facet->good)
-      numgood++;
-  }
-  if (qh GOODvertex <0 || (qh GOODvertex > 0 && qh MERGING)) {
-    FORALLfacet_(facetlist) {
-      if (facet->good && ((qh GOODvertex > 0) ^ !!qh_isvertex(qh GOODvertexp, facet->vertices))) {
-        if (!--numgood) {
-          if (qh ONLYgood) {
-            qh_fprintf(qh ferr, 7064, "qhull warning: good vertex p%d does not match last good facet f%d.  Ignored.\n",
-               qh_pointid(qh GOODvertexp), facet->id);
-            return;
-          }else if (qh GOODvertex > 0)
-            qh_fprintf(qh ferr, 7065, "qhull warning: point p%d is not a vertex('QV%d').\n",
-                qh GOODvertex-1, qh GOODvertex-1);
-          else
-            qh_fprintf(qh ferr, 7066, "qhull warning: point p%d is a vertex for every facet('QV-%d').\n",
-                -qh GOODvertex - 1, -qh GOODvertex - 1);
-        }
-        facet->good= False;
-      }
-    }
-  }
-  startgood= numgood;
-  if (qh SPLITthresholds) {
-    FORALLfacet_(facetlist) {
-      if (facet->good) {
-        if (!qh_inthresholds(facet->normal, &angle)) {
-          facet->good= False;
-          numgood--;
-          if (angle < bestangle) {
-            bestangle= angle;
-            bestfacet= facet;
-          }
-        }
-      }
-    }
-    if (!numgood && bestfacet) {
-      bestfacet->good= True;
-      numgood++;
-      trace0((qh ferr, 23, "qh_findgood_all: f%d is closest(%2.2g) to thresholds\n",
-           bestfacet->id, bestangle));
-      return;
-    }
-  }
-  qh num_good= numgood;
-  trace0((qh ferr, 24, "qh_findgood_all: %d good facets remain out of %d facets\n",
-        numgood, startgood));
-} /* findgood_all */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="furthestnext">-</a>
-
-  qh_furthestnext()
-    set qh.facet_next to facet with furthest of all furthest points
-    searches all facets on qh.facet_list
-
-  notes:
-    this may help avoid precision problems
-*/
-void qh_furthestnext(void /* qh facet_list */) {
-  facetT *facet, *bestfacet= NULL;
-  realT dist, bestdist= -REALmax;
-
-  FORALLfacets {
-    if (facet->outsideset) {
-#if qh_COMPUTEfurthest
-      pointT *furthest;
-      furthest= (pointT*)qh_setlast(facet->outsideset);
-      zinc_(Zcomputefurthest);
-      qh_distplane(furthest, facet, &dist);
-#else
-      dist= facet->furthestdist;
-#endif
-      if (dist > bestdist) {
-        bestfacet= facet;
-        bestdist= dist;
-      }
-    }
-  }
-  if (bestfacet) {
-    qh_removefacet(bestfacet);
-    qh_prependfacet(bestfacet, &qh facet_next);
-    trace1((qh ferr, 1029, "qh_furthestnext: made f%d next facet(dist %.2g)\n",
-            bestfacet->id, bestdist));
-  }
-} /* furthestnext */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="furthestout">-</a>
-
-  qh_furthestout( facet )
-    make furthest outside point the last point of outsideset
-
-  returns:
-    updates facet->outsideset
-    clears facet->notfurthest
-    sets facet->furthestdist
-
-  design:
-    determine best point of outsideset
-    make it the last point of outsideset
-*/
-void qh_furthestout(facetT *facet) {
-  pointT *point, **pointp, *bestpoint= NULL;
-  realT dist, bestdist= -REALmax;
-
-  FOREACHpoint_(facet->outsideset) {
-    qh_distplane(point, facet, &dist);
-    zinc_(Zcomputefurthest);
-    if (dist > bestdist) {
-      bestpoint= point;
-      bestdist= dist;
-    }
-  }
-  if (bestpoint) {
-    qh_setdel(facet->outsideset, point);
-    qh_setappend(&facet->outsideset, point);
-#if !qh_COMPUTEfurthest
-    facet->furthestdist= bestdist;
-#endif
-  }
-  facet->notfurthest= False;
-  trace3((qh ferr, 3017, "qh_furthestout: p%d is furthest outside point of f%d\n",
-          qh_pointid(point), facet->id));
-} /* furthestout */
-
-
-/*-<a                             href="qh-qhull.htm#TOC"
-  >-------------------------------</a><a name="infiniteloop">-</a>
-
-  qh_infiniteloop( facet )
-    report infinite loop error due to facet
-*/
-void qh_infiniteloop(facetT *facet) {
-
-  qh_fprintf(qh ferr, 6149, "qhull internal error (qh_infiniteloop): potential infinite loop detected\n");
-  qh_errexit(qh_ERRqhull, facet, NULL);
-} /* qh_infiniteloop */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="initbuild">-</a>
-
-  qh_initbuild()
-    initialize hull and outside sets with point array
-    qh.FIRSTpoint/qh.NUMpoints is point array
-    if qh.GOODpoint
-      adds qh.GOODpoint to initial hull
-
-  returns:
-    qh_facetlist with initial hull
-    points partioned into outside sets, coplanar sets, or inside
-    initializes qh.GOODpointp, qh.GOODvertexp,
-
-  design:
-    initialize global variables used during qh_buildhull
-    determine precision constants and points with max/min coordinate values
-      if qh.SCALElast, scale last coordinate(for 'd')
-    build initial simplex
-    partition input points into facets of initial simplex
-    set up lists
-    if qh.ONLYgood
-      check consistency
-      add qh.GOODvertex if defined
-*/
-void qh_initbuild( void) {
-  setT *maxpoints, *vertices;
-  facetT *facet;
-  int i, numpart;
-  realT dist;
-  boolT isoutside;
-
-  qh furthest_id= -1;
-  qh lastreport= 0;
-  qh facet_id= qh vertex_id= qh ridge_id= 0;
-  qh visit_id= qh vertex_visit= 0;
-  qh maxoutdone= False;
-
-  if (qh GOODpoint > 0)
-    qh GOODpointp= qh_point(qh GOODpoint-1);
-  else if (qh GOODpoint < 0)
-    qh GOODpointp= qh_point(-qh GOODpoint-1);
-  if (qh GOODvertex > 0)
-    qh GOODvertexp= qh_point(qh GOODvertex-1);
-  else if (qh GOODvertex < 0)
-    qh GOODvertexp= qh_point(-qh GOODvertex-1);
-  if ((qh GOODpoint
-       && (qh GOODpointp < qh first_point  /* also catches !GOODpointp */
-           || qh GOODpointp > qh_point(qh num_points-1)))
-    || (qh GOODvertex
-        && (qh GOODvertexp < qh first_point  /* also catches !GOODvertexp */
-            || qh GOODvertexp > qh_point(qh num_points-1)))) {
-    qh_fprintf(qh ferr, 6150, "qhull input error: either QGn or QVn point is > p%d\n",
-             qh num_points-1);
-    qh_errexit(qh_ERRinput, NULL, NULL);
-  }
-  maxpoints= qh_maxmin(qh first_point, qh num_points, qh hull_dim);
-  if (qh SCALElast)
-    qh_scalelast(qh first_point, qh num_points, qh hull_dim,
-               qh MINlastcoord, qh MAXlastcoord, qh MAXwidth);
-  qh_detroundoff();
-  if (qh DELAUNAY && qh upper_threshold[qh hull_dim-1] > REALmax/2
-                  && qh lower_threshold[qh hull_dim-1] < -REALmax/2) {
-    for (i=qh_PRINTEND; i--; ) {
-      if (qh PRINTout[i] == qh_PRINTgeom && qh DROPdim < 0
-          && !qh GOODthreshold && !qh SPLITthresholds)
-        break;  /* in this case, don't set upper_threshold */
-    }
-    if (i < 0) {
-      if (qh UPPERdelaunay) { /* matches qh.upperdelaunay in qh_setfacetplane */
-        qh lower_threshold[qh hull_dim-1]= qh ANGLEround * qh_ZEROdelaunay;
-        qh GOODthreshold= True;
-      }else {
-        qh upper_threshold[qh hull_dim-1]= -qh ANGLEround * qh_ZEROdelaunay;
-        if (!qh GOODthreshold)
-          qh SPLITthresholds= True; /* build upper-convex hull even if Qg */
-          /* qh_initqhull_globals errors if Qg without Pdk/etc. */
-      }
-    }
-  }
-  vertices= qh_initialvertices(qh hull_dim, maxpoints, qh first_point, qh num_points);
-  qh_initialhull(vertices);  /* initial qh facet_list */
-  qh_partitionall(vertices, qh first_point, qh num_points);
-  if (qh PRINToptions1st || qh TRACElevel || qh IStracing) {
-    if (qh TRACElevel || qh IStracing)
-      qh_fprintf(qh ferr, 8103, "\nTrace level %d for %s | %s\n",
-         qh IStracing ? qh IStracing : qh TRACElevel, qh rbox_command, qh qhull_command);
-    qh_fprintf(qh ferr, 8104, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
-  }
-  qh_resetlists(False, qh_RESETvisible /*qh visible_list newvertex_list newfacet_list */);
-  qh facet_next= qh facet_list;
-  qh_furthestnext(/* qh facet_list */);
-  if (qh PREmerge) {
-    qh cos_max= qh premerge_cos;
-    qh centrum_radius= qh premerge_centrum;
-  }
-  if (qh ONLYgood) {
-    if (qh GOODvertex > 0 && qh MERGING) {
-      qh_fprintf(qh ferr, 6151, "qhull input error: 'Qg QVn' (only good vertex) does not work with merging.\nUse 'QJ' to joggle the input or 'Q0' to turn off merging.\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (!(qh GOODthreshold || qh GOODpoint
-         || (!qh MERGEexact && !qh PREmerge && qh GOODvertexp))) {
-      qh_fprintf(qh ferr, 6152, "qhull input error: 'Qg' (ONLYgood) needs a good threshold('Pd0D0'), a\n\
-good point(QGn or QG-n), or a good vertex with 'QJ' or 'Q0' (QVn).\n");
-      qh_errexit(qh_ERRinput, NULL, NULL);
-    }
-    if (qh GOODvertex > 0  && !qh MERGING  /* matches qh_partitionall */
-        && !qh_isvertex(qh GOODvertexp, vertices)) {
-      facet= qh_findbestnew(qh GOODvertexp, qh facet_list,
-                          &dist, !qh_ALL, &isoutside, &numpart);
-      zadd_(Zdistgood, numpart);
-      if (!isoutside) {
-        qh_fprintf(qh ferr, 6153, "qhull input error: point for QV%d is inside initial simplex.  It can not be made a vertex.\n",
-               qh_pointid(qh GOODvertexp));
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-      if (!qh_addpoint(qh GOODvertexp, facet, False)) {
-        qh_settempfree(&vertices);
-        qh_settempfree(&maxpoints);
-        return;
-      }
-    }
-    qh_findgood(qh facet_list, 0);
-  }
-  qh_settempfree(&vertices);
-  qh_settempfree(&maxpoints);
-  trace1((qh ferr, 1030, "qh_initbuild: initial hull created and points partitioned\n"));
-} /* initbuild */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="initialhull">-</a>
-
-  qh_initialhull( vertices )
-    constructs the initial hull as a DIM3 simplex of vertices
-
-  design:
-    creates a simplex (initializes lists)
-    determines orientation of simplex
-    sets hyperplanes for facets
-    doubles checks orientation (in case of axis-parallel facets with Gaussian elimination)
-    checks for flipped facets and qh.NARROWhull
-    checks the result
-*/
-void qh_initialhull(setT *vertices) {
-  facetT *facet, *firstfacet, *neighbor, **neighborp;
-  realT dist, angle, minangle= REALmax;
-#ifndef qh_NOtrace
-  int k;
-#endif
-
-  qh_createsimplex(vertices);  /* qh facet_list */
-  qh_resetlists(False, qh_RESETvisible);
-  qh facet_next= qh facet_list;      /* advance facet when processed */
-  qh interior_point= qh_getcenter(vertices);
-  firstfacet= qh facet_list;
-  qh_setfacetplane(firstfacet);
-  zinc_(Znumvisibility); /* needs to be in printsummary */
-  qh_distplane(qh interior_point, firstfacet, &dist);
-  if (dist > 0) {
-    FORALLfacets
-      facet->toporient ^= (unsigned char)True;
-  }
-  FORALLfacets
-    qh_setfacetplane(facet);
-  FORALLfacets {
-    if (!qh_checkflipped(facet, NULL, qh_ALL)) {/* due to axis-parallel facet */
-      trace1((qh ferr, 1031, "qh_initialhull: initial orientation incorrect.  Correct all facets\n"));
-      facet->flipped= False;
-      FORALLfacets {
-        facet->toporient ^= (unsigned char)True;
-        qh_orientoutside(facet);
-      }
-      break;
-    }
-  }
-  FORALLfacets {
-    if (!qh_checkflipped(facet, NULL, !qh_ALL)) {  /* can happen with 'R0.1' */
-      if (qh DELAUNAY && ! qh ATinfinity) {
-        if (qh UPPERdelaunay)
-          qh_fprintf(qh ferr, 6240, "Qhull input error: Can not compute the upper Delaunay triangulation or upper Voronoi diagram of cocircular/cospherical points.\n");
-        else
-          qh_fprintf(qh ferr, 6239, "Qhull input error: Use option 'Qz' for the Delaunay triangulation or Voronoi diagram of cocircular/cospherical points.  Option 'Qz' adds a point \"at infinity\" (above the corresponding paraboloid).\n");
-        qh_errexit(qh_ERRinput, NULL, NULL);
-      }
-      qh_precision("initial facet is coplanar with interior point");
-      qh_fprintf(qh ferr, 6154, "qhull precision error: initial facet %d is coplanar with the interior point\n",
-                   facet->id);
-      qh_errexit(qh_ERRsingular, facet, NULL);
-    }
-    FOREACHneighbor_(facet) {
-      angle= qh_getangle(facet->normal, neighbor->normal);
-      minimize_( minangle, angle);
-    }
-  }
-  if (minangle < qh_MAXnarrow && !qh NOnarrow) {
-    realT diff= 1.0 + minangle;
-
-    qh NARROWhull= True;
-    qh_option("_narrow-hull", NULL, &diff);
-    if (minangle < qh_WARNnarrow && !qh RERUN && qh PRINTprecision)
-      qh_printhelp_narrowhull(qh ferr, minangle);
-  }
-  zzval_(Zprocessed)= qh hull_dim+1;
-  qh_checkpolygon(qh facet_list);
-  qh_checkconvex(qh facet_list,   qh_DATAfault);
-#ifndef qh_NOtrace
-  if (qh IStracing >= 1) {
-    qh_fprintf(qh ferr, 8105, "qh_initialhull: simplex constructed, interior point:");
-    for (k=0; k < qh hull_dim; k++)
-      qh_fprintf(qh ferr, 8106, " %6.4g", qh interior_point[k]);
-    qh_fprintf(qh ferr, 8107, "\n");
-  }
-#endif
-} /* initialhull */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="initialvertices">-</a>
-
-  qh_initialvertices( dim, maxpoints, points, numpoints )
-    determines a non-singular set of initial vertices
-    maxpoints may include duplicate points
-
-  returns:
-    temporary set of dim+1 vertices in descending order by vertex id
-    if qh.RANDOMoutside && !qh.ALLpoints
-      picks random points
-    if dim >= qh_INITIALmax,
-      uses min/max x and max points with non-zero determinants
-
-  notes:
-    unless qh.ALLpoints,
-      uses maxpoints as long as determinate is non-zero
-*/
-setT *qh_initialvertices(int dim, setT *maxpoints, pointT *points, int numpoints) {
-  pointT *point, **pointp;
-  setT *vertices, *simplex, *tested;
-  realT randr;
-  int idx, point_i, point_n, k;
-  boolT nearzero= False;
-
-  vertices= qh_settemp(dim + 1);
-  simplex= qh_settemp(dim+1);
-  if (qh ALLpoints)
-    qh_maxsimplex(dim, NULL, points, numpoints, &simplex);
-  else if (qh RANDOMoutside) {
-    while (qh_setsize(simplex) != dim+1) {
-      randr= qh_RANDOMint;
-      randr= randr/(qh_RANDOMmax+1);
-      idx= (int)floor(qh num_points * randr);
-      while (qh_setin(simplex, qh_point(idx))) {
-            idx++; /* in case qh_RANDOMint always returns the same value */
-        idx= idx < qh num_points ? idx : 0;
-      }
-      qh_setappend(&simplex, qh_point(idx));
-    }
-  }else if (qh hull_dim >= qh_INITIALmax) {
-    tested= qh_settemp(dim+1);
-    qh_setappend(&simplex, SETfirst_(maxpoints));   /* max and min X coord */
-    qh_setappend(&simplex, SETsecond_(maxpoints));
-    qh_maxsimplex(fmin_(qh_INITIALsearch, dim), maxpoints, points, numpoints, &simplex);
-    k= qh_setsize(simplex);
-    FOREACHpoint_i_(maxpoints) {
-      if (point_i & 0x1) {     /* first pick up max. coord. points */
-        if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
-          qh_detsimplex(point, simplex, k, &nearzero);
-          if (nearzero)
-            qh_setappend(&tested, point);
-          else {
-            qh_setappend(&simplex, point);
-            if (++k == dim)  /* use search for last point */
-              break;
-          }
-        }
-      }
-    }
-    while (k != dim && (point= (pointT*)qh_setdellast(maxpoints))) {
-      if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
-        qh_detsimplex(point, simplex, k, &nearzero);
-        if (nearzero)
-          qh_setappend(&tested, point);
-        else {
-          qh_setappend(&simplex, point);
-          k++;
-        }
-      }
-    }
-    idx= 0;
-    while (k != dim && (point= qh_point(idx++))) {
-      if (!qh_setin(simplex, point) && !qh_setin(tested, point)){
-        qh_detsimplex(point, simplex, k, &nearzero);
-        if (!nearzero){
-          qh_setappend(&simplex, point);
-          k++;
-        }
-      }
-    }
-    qh_settempfree(&tested);
-    qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
-  }else
-    qh_maxsimplex(dim, maxpoints, points, numpoints, &simplex);
-  FOREACHpoint_(simplex)
-    qh_setaddnth(&vertices, 0, qh_newvertex(point)); /* descending order */
-  qh_settempfree(&simplex);
-  return vertices;
-} /* initialvertices */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="isvertex">-</a>
-
-  qh_isvertex(  )
-    returns vertex if point is in vertex set, else returns NULL
-
-  notes:
-    for qh.GOODvertex
-*/
-vertexT *qh_isvertex(pointT *point, setT *vertices) {
-  vertexT *vertex, **vertexp;
-
-  FOREACHvertex_(vertices) {
-    if (vertex->point == point)
-      return vertex;
-  }
-  return NULL;
-} /* isvertex */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="makenewfacets">-</a>
-
-  qh_makenewfacets( point )
-    make new facets from point and qh.visible_list
-
-  returns:
-    qh.newfacet_list= list of new facets with hyperplanes and ->newfacet
-    qh.newvertex_list= list of vertices in new facets with ->newlist set
-
-    if (qh.ONLYgood)
-      newfacets reference horizon facets, but not vice versa
-      ridges reference non-simplicial horizon ridges, but not vice versa
-      does not change existing facets
-    else
-      sets qh.NEWfacets
-      new facets attached to horizon facets and ridges
-      for visible facets,
-        visible->r.replace is corresponding new facet
-
-  see also:
-    qh_makenewplanes() -- make hyperplanes for facets
-    qh_attachnewfacets() -- attachnewfacets if not done here(qh ONLYgood)
-    qh_matchnewfacets() -- match up neighbors
-    qh_updatevertices() -- update vertex neighbors and delvertices
-    qh_deletevisible() -- delete visible facets
-    qh_checkpolygon() --check the result
-    qh_triangulate() -- triangulate a non-simplicial facet
-
-  design:
-    for each visible facet
-      make new facets to its horizon facets
-      update its f.replace
-      clear its neighbor set
-*/
-vertexT *qh_makenewfacets(pointT *point /*visible_list*/) {
-  facetT *visible, *newfacet= NULL, *newfacet2= NULL, *neighbor, **neighborp;
-  vertexT *apex;
-  int numnew=0;
-
-  qh newfacet_list= qh facet_tail;
-  qh newvertex_list= qh vertex_tail;
-  apex= qh_newvertex(point);
-  qh_appendvertex(apex);
-  qh visit_id++;
-  if (!qh ONLYgood)
-    qh NEWfacets= True;
-  FORALLvisible_facets {
-    FOREACHneighbor_(visible)
-      neighbor->seen= False;
-    if (visible->ridges) {
-      visible->visitid= qh visit_id;
-      newfacet2= qh_makenew_nonsimplicial(visible, apex, &numnew);
-    }
-    if (visible->simplicial)
-      newfacet= qh_makenew_simplicial(visible, apex, &numnew);
-    if (!qh ONLYgood) {
-      if (newfacet2)  /* newfacet is null if all ridges defined */
-        newfacet= newfacet2;
-      if (newfacet)
-        visible->f.replace= newfacet;
-      else
-        zinc_(Zinsidevisible);
-      SETfirst_(visible->neighbors)= NULL;
-    }
-  }
-  trace1((qh ferr, 1032, "qh_makenewfacets: created %d new facets from point p%d to horizon\n",
-          numnew, qh_pointid(point)));
-  if (qh IStracing >= 4)
-    qh_printfacetlist(qh newfacet_list, NULL, qh_ALL);
-  return apex;
-} /* makenewfacets */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="matchduplicates">-</a>
-
-  qh_matchduplicates( atfacet, atskip, hashsize, hashcount )
-    match duplicate ridges in qh.hash_table for atfacet/atskip
-    duplicates marked with ->dupridge and qh_DUPLICATEridge
-
-  returns:
-    picks match with worst merge (min distance apart)
-    updates hashcount
-
-  see also:
-    qh_matchneighbor
-
-  notes:
-
-  design:
-    compute hash value for atfacet and atskip
-    repeat twice -- once to make best matches, once to match the rest
-      for each possible facet in qh.hash_table
-        if it is a matching facet and pass 2
-          make match
-          unless tricoplanar, mark match for merging (qh_MERGEridge)
-          [e.g., tricoplanar RBOX s 1000 t993602376 | QHULL C-1e-3 d Qbb FA Qt]
-        if it is a matching facet and pass 1
-          test if this is a better match
-      if pass 1,
-        make best match (it will not be merged)
-*/
-#ifndef qh_NOmerge
-void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
-  boolT same, ismatch;
-  int hash, scan;
-  facetT *facet, *newfacet, *maxmatch= NULL, *maxmatch2= NULL, *nextfacet;
-  int skip, newskip, nextskip= 0, maxskip= 0, maxskip2= 0, makematch;
-  realT maxdist= -REALmax, mindist, dist2, low, high;
-
-  hash= qh_gethash(hashsize, atfacet->vertices, qh hull_dim, 1,
-                     SETelem_(atfacet->vertices, atskip));
-  trace2((qh ferr, 2046, "qh_matchduplicates: find duplicate matches for f%d skip %d hash %d hashcount %d\n",
-          atfacet->id, atskip, hash, *hashcount));
-  for (makematch= 0; makematch < 2; makematch++) {
-    qh visit_id++;
-    for (newfacet= atfacet, newskip= atskip; newfacet; newfacet= nextfacet, newskip= nextskip) {
-      zinc_(Zhashlookup);
-      nextfacet= NULL;
-      newfacet->visitid= qh visit_id;
-      for (scan= hash; (facet= SETelemt_(qh hash_table, scan, facetT));
-           scan= (++scan >= hashsize ? 0 : scan)) {
-        if (!facet->dupridge || facet->visitid == qh visit_id)
-          continue;
-        zinc_(Zhashtests);
-        if (qh_matchvertices(1, newfacet->vertices, newskip, facet->vertices, &skip, &same)) {
-          ismatch= (same == (boolT)(newfacet->toporient ^ facet->toporient));
-          if (SETelemt_(facet->neighbors, skip, facetT) != qh_DUPLICATEridge) {
-            if (!makematch) {
-              qh_fprintf(qh ferr, 6155, "qhull internal error (qh_matchduplicates): missing dupridge at f%d skip %d for new f%d skip %d hash %d\n",
-                     facet->id, skip, newfacet->id, newskip, hash);
-              qh_errexit2 (qh_ERRqhull, facet, newfacet);
-            }
-          }else if (ismatch && makematch) {
-            if (SETelemt_(newfacet->neighbors, newskip, facetT) == qh_DUPLICATEridge) {
-              SETelem_(facet->neighbors, skip)= newfacet;
-              if (newfacet->tricoplanar)
-                SETelem_(newfacet->neighbors, newskip)= facet;
-              else
-                SETelem_(newfacet->neighbors, newskip)= qh_MERGEridge;
-              *hashcount -= 2; /* removed two unmatched facets */
-              trace4((qh ferr, 4059, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d merge\n",
-                    facet->id, skip, newfacet->id, newskip));
-            }
-          }else if (ismatch) {
-            mindist= qh_getdistance(facet, newfacet, &low, &high);
-            dist2= qh_getdistance(newfacet, facet, &low, &high);
-            minimize_(mindist, dist2);
-            if (mindist > maxdist) {
-              maxdist= mindist;
-              maxmatch= facet;
-              maxskip= skip;
-              maxmatch2= newfacet;
-              maxskip2= newskip;
-            }
-            trace3((qh ferr, 3018, "qh_matchduplicates: duplicate f%d skip %d new f%d skip %d at dist %2.2g, max is now f%d f%d\n",
-                    facet->id, skip, newfacet->id, newskip, mindist,
-                    maxmatch->id, maxmatch2->id));
-          }else { /* !ismatch */
-            nextfacet= facet;
-            nextskip= skip;
-          }
-        }
-        if (makematch && !facet
-        && SETelemt_(facet->neighbors, skip, facetT) == qh_DUPLICATEridge) {
-          qh_fprintf(qh ferr, 6156, "qhull internal error (qh_matchduplicates): no MERGEridge match for duplicate f%d skip %d at hash %d\n",
-                     newfacet->id, newskip, hash);
-          qh_errexit(qh_ERRqhull, newfacet, NULL);
-        }
-      }
-    } /* end of for each new facet at hash */
-    if (!makematch) {
-      if (!maxmatch) {
-        qh_fprintf(qh ferr, 6157, "qhull internal error (qh_matchduplicates): no maximum match at duplicate f%d skip %d at hash %d\n",
-                     atfacet->id, atskip, hash);
-        qh_errexit(qh_ERRqhull, atfacet, NULL);
-      }
-      /* maxmatch cannot be NULL since above qh_errexit didn't return */
-      /* coverity[var_deref_op] */
-      SETelem_(maxmatch->neighbors, maxskip)= maxmatch2;
-      SETelem_(maxmatch2->neighbors, maxskip2)= maxmatch;
-      *hashcount -= 2; /* removed two unmatched facets */
-      zzinc_(Zmultiridge);
-      trace0((qh ferr, 25, "qh_matchduplicates: duplicate f%d skip %d matched with new f%d skip %d keep\n",
-              maxmatch->id, maxskip, maxmatch2->id, maxskip2));
-      qh_precision("ridge with multiple neighbors");
-      if (qh IStracing >= 4)
-        qh_errprint("DUPLICATED/MATCH", maxmatch, maxmatch2, NULL, NULL);
-    }
-  }
-} /* matchduplicates */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="nearcoplanar">-</a>
-
-  qh_nearcoplanar()
-    for all facets, remove near-inside points from facet->coplanarset</li>
-    coplanar points defined by innerplane from qh_outerinner()
-
-  returns:
-    if qh KEEPcoplanar && !qh KEEPinside
-      facet->coplanarset only contains coplanar points
-    if qh.JOGGLEmax
-      drops inner plane by another qh.JOGGLEmax diagonal since a
-        vertex could shift out while a coplanar point shifts in
-
-  notes:
-    used for qh.PREmerge and qh.JOGGLEmax
-    must agree with computation of qh.NEARcoplanar in qh_detroundoff()
-  design:
-    if not keeping coplanar or inside points
-      free all coplanar sets
-    else if not keeping both coplanar and inside points
-      remove !coplanar or !inside points from coplanar sets
-*/
-void qh_nearcoplanar(void /* qh.facet_list */) {
-  facetT *facet;
-  pointT *point, **pointp;
-  int numpart;
-  realT dist, innerplane;
-
-  if (!qh KEEPcoplanar && !qh KEEPinside) {
-    FORALLfacets {
-      if (facet->coplanarset)
-        qh_setfree( &facet->coplanarset);
-    }
-  }else if (!qh KEEPcoplanar || !qh KEEPinside) {
-    qh_outerinner(NULL, NULL, &innerplane);
-    if (qh JOGGLEmax < REALmax/2)
-      innerplane -= qh JOGGLEmax * sqrt((realT)qh hull_dim);
-    numpart= 0;
-    FORALLfacets {
-      if (facet->coplanarset) {
-        FOREACHpoint_(facet->coplanarset) {
-          numpart++;
-          qh_distplane(point, facet, &dist);
-          if (dist < innerplane) {
-            if (!qh KEEPinside)
-              SETref_(point)= NULL;
-          }else if (!qh KEEPcoplanar)
-            SETref_(point)= NULL;
-        }
-        qh_setcompact(facet->coplanarset);
-      }
-    }
-    zzadd_(Zcheckpart, numpart);
-  }
-} /* nearcoplanar */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="nearvertex">-</a>
-
-  qh_nearvertex( facet, point, bestdist )
-    return nearest vertex in facet to point
-
-  returns:
-    vertex and its distance
-
-  notes:
-    if qh.DELAUNAY
-      distance is measured in the input set
-    searches neighboring tricoplanar facets (requires vertexneighbors)
-      Slow implementation.  Recomputes vertex set for each point.
-    The vertex set could be stored in the qh.keepcentrum facet.
-*/
-vertexT *qh_nearvertex(facetT *facet, pointT *point, realT *bestdistp) {
-  realT bestdist= REALmax, dist;
-  vertexT *bestvertex= NULL, *vertex, **vertexp, *apex;
-  coordT *center;
-  facetT *neighbor, **neighborp;
-  setT *vertices;
-  int dim= qh hull_dim;
-
-  if (qh DELAUNAY)
-    dim--;
-  if (facet->tricoplanar) {
-    if (!qh VERTEXneighbors || !facet->center) {
-      qh_fprintf(qh ferr, 6158, "qhull internal error (qh_nearvertex): qh.VERTEXneighbors and facet->center required for tricoplanar facets\n");
-      qh_errexit(qh_ERRqhull, facet, NULL);
-    }
-    vertices= qh_settemp(qh TEMPsize);
-    apex= SETfirstt_(facet->vertices, vertexT);
-    center= facet->center;
-    FOREACHneighbor_(apex) {
-      if (neighbor->center == center) {
-        FOREACHvertex_(neighbor->vertices)
-          qh_setappend(&vertices, vertex);
-      }
-    }
-  }else
-    vertices= facet->vertices;
-  FOREACHvertex_(vertices) {
-    dist= qh_pointdist(vertex->point, point, -dim);
-    if (dist < bestdist) {
-      bestdist= dist;
-      bestvertex= vertex;
-    }
-  }
-  if (facet->tricoplanar)
-    qh_settempfree(&vertices);
-  *bestdistp= sqrt(bestdist);
-  trace3((qh ferr, 3019, "qh_nearvertex: v%d dist %2.2g for f%d p%d\n",
-        bestvertex ? bestvertex->id : -1, *bestdistp, facet->id, qh_pointid(point)));
-  return bestvertex;
-} /* nearvertex */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="newhashtable">-</a>
-
-  qh_newhashtable( newsize )
-    returns size of qh.hash_table of at least newsize slots
-
-  notes:
-    assumes qh.hash_table is NULL
-    qh_HASHfactor determines the number of extra slots
-    size is not divisible by 2, 3, or 5
-*/
-int qh_newhashtable(int newsize) {
-  int size;
-
-  size= ((newsize+1)*qh_HASHfactor) | 0x1;  /* odd number */
-  while (True) {
-    if (newsize<0 || size<0) {
-        qh_fprintf(qhmem.ferr, 6236, "qhull error (qh_newhashtable): negative request (%d) or size (%d).  Did int overflow due to high-D?\n", newsize, size); /* WARN64 */
-        qh_errexit(qhmem_ERRmem, NULL, NULL);
-    }
-    if ((size%3) && (size%5))
-      break;
-    size += 2;
-    /* loop terminates because there is an infinite number of primes */
-  }
-  qh hash_table= qh_setnew(size);
-  qh_setzero(qh hash_table, 0, size);
-  return size;
-} /* newhashtable */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="newvertex">-</a>
-
-  qh_newvertex( point )
-    returns a new vertex for point
-*/
-vertexT *qh_newvertex(pointT *point) {
-  vertexT *vertex;
-
-  zinc_(Ztotvertices);
-  vertex= (vertexT *)qh_memalloc((int)sizeof(vertexT));
-  memset((char *) vertex, (size_t)0, sizeof(vertexT));
-  if (qh vertex_id == 0xFFFFFF) {
-    qh_fprintf(qh ferr, 6159, "qhull error: more than %d vertices.  ID field overflows and two vertices\n\
-may have the same identifier.  Vertices will not be sorted correctly.\n", 0xFFFFFF);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }
-  if (qh vertex_id == qh tracevertex_id)
-    qh tracevertex= vertex;
-  vertex->id= qh vertex_id++;
-  vertex->point= point;
-  vertex->dim= (unsigned char)(qh hull_dim <= MAX_vdim ? qh hull_dim : 0);
-  trace4((qh ferr, 4060, "qh_newvertex: vertex p%d(v%d) created\n", qh_pointid(vertex->point),
-          vertex->id));
-  return(vertex);
-} /* newvertex */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="nextridge3d">-</a>
-
-  qh_nextridge3d( atridge, facet, vertex )
-    return next ridge and vertex for a 3d facet
-    returns NULL on error
-    [for QhullFacet::nextRidge3d] Does not call qh_errexit nor access qh_qh.
-
-  notes:
-    in qh_ORIENTclock order
-    this is a O(n^2) implementation to trace all ridges
-    be sure to stop on any 2nd visit
-    same as QhullRidge::nextRidge3d
-    does not use qh_qh or qh_errexit [QhullFacet.cpp]
-
-  design:
-    for each ridge
-      exit if it is the ridge after atridge
-*/
-ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
-  vertexT *atvertex, *vertex, *othervertex;
-  ridgeT *ridge, **ridgep;
-
-  if ((atridge->top == facet) ^ qh_ORIENTclock)
-    atvertex= SETsecondt_(atridge->vertices, vertexT);
-  else
-    atvertex= SETfirstt_(atridge->vertices, vertexT);
-  FOREACHridge_(facet->ridges) {
-    if (ridge == atridge)
-      continue;
-    if ((ridge->top == facet) ^ qh_ORIENTclock) {
-      othervertex= SETsecondt_(ridge->vertices, vertexT);
-      vertex= SETfirstt_(ridge->vertices, vertexT);
-    }else {
-      vertex= SETsecondt_(ridge->vertices, vertexT);
-      othervertex= SETfirstt_(ridge->vertices, vertexT);
-    }
-    if (vertex == atvertex) {
-      if (vertexp)
-        *vertexp= othervertex;
-      return ridge;
-    }
-  }
-  return NULL;
-} /* nextridge3d */
-#else /* qh_NOmerge */
-void qh_matchduplicates(facetT *atfacet, int atskip, int hashsize, int *hashcount) {
-}
-ridgeT *qh_nextridge3d(ridgeT *atridge, facetT *facet, vertexT **vertexp) {
-
-  return NULL;
-}
-#endif /* qh_NOmerge */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="outcoplanar">-</a>
-
-  qh_outcoplanar()
-    move points from all facets' outsidesets to their coplanarsets
-
-  notes:
-    for post-processing under qh.NARROWhull
-
-  design:
-    for each facet
-      for each outside point for facet
-        partition point into coplanar set
-*/
-void qh_outcoplanar(void /* facet_list */) {
-  pointT *point, **pointp;
-  facetT *facet;
-  realT dist;
-
-  trace1((qh ferr, 1033, "qh_outcoplanar: move outsideset to coplanarset for qh NARROWhull\n"));
-  FORALLfacets {
-    FOREACHpoint_(facet->outsideset) {
-      qh num_outside--;
-      if (qh KEEPcoplanar || qh KEEPnearinside) {
-        qh_distplane(point, facet, &dist);
-        zinc_(Zpartition);
-        qh_partitioncoplanar(point, facet, &dist);
-      }
-    }
-    qh_setfree(&facet->outsideset);
-  }
-} /* outcoplanar */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="point">-</a>
-
-  qh_point( id )
-    return point for a point id, or NULL if unknown
-
-  alternative code:
-    return((pointT *)((unsigned   long)qh.first_point
-           + (unsigned long)((id)*qh.normal_size)));
-*/
-pointT *qh_point(int id) {
-
-  if (id < 0)
-    return NULL;
-  if (id < qh num_points)
-    return qh first_point + id * qh hull_dim;
-  id -= qh num_points;
-  if (id < qh_setsize(qh other_points))
-    return SETelemt_(qh other_points, id, pointT);
-  return NULL;
-} /* point */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="point_add">-</a>
-
-  qh_point_add( set, point, elem )
-    stores elem at set[point.id]
-
-  returns:
-    access function for qh_pointfacet and qh_pointvertex
-
-  notes:
-    checks point.id
-*/
-void qh_point_add(setT *set, pointT *point, void *elem) {
-  int id, size;
-
-  SETreturnsize_(set, size);
-  if ((id= qh_pointid(point)) < 0)
-    qh_fprintf(qh ferr, 7067, "qhull internal warning (point_add): unknown point %p id %d\n",
-      point, id);
-  else if (id >= size) {
-    qh_fprintf(qh ferr, 6160, "qhull internal error(point_add): point p%d is out of bounds(%d)\n",
-             id, size);
-    qh_errexit(qh_ERRqhull, NULL, NULL);
-  }else
-    SETelem_(set, id)= elem;
-} /* point_add */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="pointfacet">-</a>
-
-  qh_pointfacet()
-    return temporary set of facet for each point
-    the set is indexed by point id
-
-  notes:
-    vertices assigned to one of the facets
-    coplanarset assigned to the facet
-    outside set assigned to the facet
-    NULL if no facet for point (inside)
-      includes qh.GOODpointp
-
-  access:
-    FOREACHfacet_i_(facets) { ... }
-    SETelem_(facets, i)
-
-  design:
-    for each facet
-      add each vertex
-      add each coplanar point
-      add each outside point
-*/
-setT *qh_pointfacet(void /*qh facet_list*/) {
-  int numpoints= qh num_points + qh_setsize(qh other_points);
-  setT *facets;
-  facetT *facet;
-  vertexT *vertex, **vertexp;
-  pointT *point, **pointp;
-
-  facets= qh_settemp(numpoints);
-  qh_setzero(facets, 0, numpoints);
-  qh vertex_visit++;
-  FORALLfacets {
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        vertex->visitid= qh vertex_visit;
-        qh_point_add(facets, vertex->point, facet);
-      }
-    }
-    FOREACHpoint_(facet->coplanarset)
-      qh_point_add(facets, point, facet);
-    FOREACHpoint_(facet->outsideset)
-      qh_point_add(facets, point, facet);
-  }
-  return facets;
-} /* pointfacet */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="pointvertex">-</a>
-
-  qh_pointvertex(  )
-    return temporary set of vertices indexed by point id
-    entry is NULL if no vertex for a point
-      this will include qh.GOODpointp
-
-  access:
-    FOREACHvertex_i_(vertices) { ... }
-    SETelem_(vertices, i)
-*/
-setT *qh_pointvertex(void /*qh facet_list*/) {
-  int numpoints= qh num_points + qh_setsize(qh other_points);
-  setT *vertices;
-  vertexT *vertex;
-
-  vertices= qh_settemp(numpoints);
-  qh_setzero(vertices, 0, numpoints);
-  FORALLvertices
-    qh_point_add(vertices, vertex->point, vertex);
-  return vertices;
-} /* pointvertex */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="prependfacet">-</a>
-
-  qh_prependfacet( facet, facetlist )
-    prepend facet to the start of a facetlist
-
-  returns:
-    increments qh.numfacets
-    updates facetlist, qh.facet_list, facet_next
-
-  notes:
-    be careful of prepending since it can lose a pointer.
-      e.g., can lose _next by deleting and then prepending before _next
-*/
-void qh_prependfacet(facetT *facet, facetT **facetlist) {
-  facetT *prevfacet, *list;
-
-
-  trace4((qh ferr, 4061, "qh_prependfacet: prepend f%d before f%d\n",
-          facet->id, getid_(*facetlist)));
-  if (!*facetlist)
-    (*facetlist)= qh facet_tail;
-  list= *facetlist;
-  prevfacet= list->previous;
-  facet->previous= prevfacet;
-  if (prevfacet)
-    prevfacet->next= facet;
-  list->previous= facet;
-  facet->next= *facetlist;
-  if (qh facet_list == list)  /* this may change *facetlist */
-    qh facet_list= facet;
-  if (qh facet_next == list)
-    qh facet_next= facet;
-  *facetlist= facet;
-  qh num_facets++;
-} /* prependfacet */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="printhashtable">-</a>
-
-  qh_printhashtable( fp )
-    print hash table to fp
-
-  notes:
-    not in I/O to avoid bringing io.c in
-
-  design:
-    for each hash entry
-      if defined
-        if unmatched or will merge (NULL, qh_MERGEridge, qh_DUPLICATEridge)
-          print entry and neighbors
-*/
-void qh_printhashtable(FILE *fp) {
-  facetT *facet, *neighbor;
-  int id, facet_i, facet_n, neighbor_i= 0, neighbor_n= 0;
-  vertexT *vertex, **vertexp;
-
-  FOREACHfacet_i_(qh hash_table) {
-    if (facet) {
-      FOREACHneighbor_i_(facet) {
-        if (!neighbor || neighbor == qh_MERGEridge || neighbor == qh_DUPLICATEridge)
-          break;
-      }
-      if (neighbor_i == neighbor_n)
-        continue;
-      qh_fprintf(fp, 9283, "hash %d f%d ", facet_i, facet->id);
-      FOREACHvertex_(facet->vertices)
-        qh_fprintf(fp, 9284, "v%d ", vertex->id);
-      qh_fprintf(fp, 9285, "\n neighbors:");
-      FOREACHneighbor_i_(facet) {
-        if (neighbor == qh_MERGEridge)
-          id= -3;
-        else if (neighbor == qh_DUPLICATEridge)
-          id= -2;
-        else
-          id= getid_(neighbor);
-        qh_fprintf(fp, 9286, " %d", id);
-      }
-      qh_fprintf(fp, 9287, "\n");
-    }
-  }
-} /* printhashtable */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="printlists">-</a>
-
-  qh_printlists( fp )
-    print out facet and vertex list for debugging (without 'f/v' tags)
-*/
-void qh_printlists(void) {
-  facetT *facet;
-  vertexT *vertex;
-  int count= 0;
-
-  qh_fprintf(qh ferr, 8108, "qh_printlists: facets:");
-  FORALLfacets {
-    if (++count % 100 == 0)
-      qh_fprintf(qh ferr, 8109, "\n     ");
-    qh_fprintf(qh ferr, 8110, " %d", facet->id);
-  }
-  qh_fprintf(qh ferr, 8111, "\n  new facets %d visible facets %d next facet for qh_addpoint %d\n  vertices(new %d):",
-     getid_(qh newfacet_list), getid_(qh visible_list), getid_(qh facet_next),
-     getid_(qh newvertex_list));
-  count = 0;
-  FORALLvertices {
-    if (++count % 100 == 0)
-      qh_fprintf(qh ferr, 8112, "\n     ");
-    qh_fprintf(qh ferr, 8113, " %d", vertex->id);
-  }
-  qh_fprintf(qh ferr, 8114, "\n");
-} /* printlists */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="resetlists">-</a>
-
-  qh_resetlists( stats, qh_RESETvisible )
-    reset newvertex_list, newfacet_list, visible_list
-    if stats,
-      maintains statistics
-
-  returns:
-    visible_list is empty if qh_deletevisible was called
-*/
-void qh_resetlists(boolT stats, boolT resetVisible /*qh newvertex_list newfacet_list visible_list*/) {
-  vertexT *vertex;
-  facetT *newfacet, *visible;
-  int totnew=0, totver=0;
-
-  if (stats) {
-    FORALLvertex_(qh newvertex_list)
-      totver++;
-    FORALLnew_facets
-      totnew++;
-    zadd_(Zvisvertextot, totver);
-    zmax_(Zvisvertexmax, totver);
-    zadd_(Znewfacettot, totnew);
-    zmax_(Znewfacetmax, totnew);
-  }
-  FORALLvertex_(qh newvertex_list)
-    vertex->newlist= False;
-  qh newvertex_list= NULL;
-  FORALLnew_facets
-    newfacet->newfacet= False;
-  qh newfacet_list= NULL;
-  if (resetVisible) {
-    FORALLvisible_facets {
-      visible->f.replace= NULL;
-      visible->visible= False;
-    }
-    qh num_visible= 0;
-  }
-  qh visible_list= NULL; /* may still have visible facets via qh_triangulate */
-  qh NEWfacets= False;
-} /* resetlists */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="setvoronoi_all">-</a>
-
-  qh_setvoronoi_all()
-    compute Voronoi centers for all facets
-    includes upperDelaunay facets if qh.UPPERdelaunay ('Qu')
-
-  returns:
-    facet->center is the Voronoi center
-
-  notes:
-    this is unused/untested code
-      please email bradb at shore.net if this works ok for you
-
-  use:
-    FORALLvertices {...} to locate the vertex for a point.
-    FOREACHneighbor_(vertex) {...} to visit the Voronoi centers for a Voronoi cell.
-*/
-void qh_setvoronoi_all(void) {
-  facetT *facet;
-
-  qh_clearcenters(qh_ASvoronoi);
-  qh_vertexneighbors();
-
-  FORALLfacets {
-    if (!facet->normal || !facet->upperdelaunay || qh UPPERdelaunay) {
-      if (!facet->center)
-        facet->center= qh_facetcenter(facet->vertices);
-    }
-  }
-} /* setvoronoi_all */
-
-#ifndef qh_NOmerge
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="triangulate">-</a>
-
-  qh_triangulate()
-    triangulate non-simplicial facets on qh.facet_list,
-    if qh VORONOI, sets Voronoi centers of non-simplicial facets
-    nop if hasTriangulation
-
-  returns:
-    all facets simplicial
-    each tricoplanar facet has ->f.triowner == owner of ->center,normal,etc.
-
-  notes:
-    call after qh_check_output since may switch to Voronoi centers
-    Output may overwrite ->f.triowner with ->f.area
-*/
-void qh_triangulate(void /*qh facet_list*/) {
-  facetT *facet, *nextfacet, *owner;
-  int onlygood= qh ONLYgood;
-  facetT *neighbor, *visible= NULL, *facet1, *facet2, *new_facet_list= NULL;
-  facetT *orig_neighbor= NULL, *otherfacet;
-  vertexT *new_vertex_list= NULL;
-  mergeT *merge;
-  mergeType mergetype;
-  int neighbor_i, neighbor_n;
-
-  if (qh hasTriangulation)
-      return;
-  trace1((qh ferr, 1034, "qh_triangulate: triangulate non-simplicial facets\n"));
-  if (qh hull_dim == 2)
-    return;
-  if (qh VORONOI) {  /* otherwise lose Voronoi centers [could rebuild vertex set from tricoplanar] */
-    qh_clearcenters(qh_ASvoronoi);
-    qh_vertexneighbors();
-  }
-  qh ONLYgood= False; /* for makenew_nonsimplicial */
-  qh visit_id++;
-  qh NEWfacets= True;
-  qh degen_mergeset= qh_settemp(qh TEMPsize);
-  qh newvertex_list= qh vertex_tail;
-  for (facet= qh facet_list; facet && facet->next; facet= nextfacet) { /* non-simplicial facets moved to end */
-    nextfacet= facet->next;
-    if (facet->visible || facet->simplicial)
-      continue;
-    /* triangulate all non-simplicial facets, otherwise merging does not work, e.g., RBOX c P-0.1 P+0.1 P+0.1 D3 | QHULL d Qt Tv */
-    if (!new_facet_list)
-      new_facet_list= facet;  /* will be moved to end */
-    qh_triangulate_facet(facet, &new_vertex_list);
-  }
-  trace2((qh ferr, 2047, "qh_triangulate: delete null facets from f%d -- apex same as second vertex\n", getid_(new_facet_list)));
-  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* null facets moved to end */
-    nextfacet= facet->next;
-    if (facet->visible)
-      continue;
-    if (facet->ridges) {
-      if (qh_setsize(facet->ridges) > 0) {
-        qh_fprintf(qh ferr, 6161, "qhull error (qh_triangulate): ridges still defined for f%d\n", facet->id);
-        qh_errexit(qh_ERRqhull, facet, NULL);
-      }
-      qh_setfree(&facet->ridges);
-    }
-    if (SETfirst_(facet->vertices) == SETsecond_(facet->vertices)) {
-      zinc_(Ztrinull);
-      qh_triangulate_null(facet);
-    }
-  }
-  trace2((qh ferr, 2048, "qh_triangulate: delete %d or more mirror facets -- same vertices and neighbors\n", qh_setsize(qh degen_mergeset)));
-  qh visible_list= qh facet_tail;
-  while ((merge= (mergeT*)qh_setdellast(qh degen_mergeset))) {
-    facet1= merge->facet1;
-    facet2= merge->facet2;
-    mergetype= merge->type;
-    qh_memfree(merge, (int)sizeof(mergeT));
-    if (mergetype == MRGmirror) {
-      zinc_(Ztrimirror);
-      qh_triangulate_mirror(facet1, facet2);
-    }
-  }
-  qh_settempfree(&qh degen_mergeset);
-  trace2((qh ferr, 2049, "qh_triangulate: update neighbor lists for vertices from v%d\n", getid_(new_vertex_list)));
-  qh newvertex_list= new_vertex_list;  /* all vertices of new facets */
-  qh visible_list= NULL;
-  qh_updatevertices(/*qh newvertex_list, empty newfacet_list and visible_list*/);
-  qh_resetlists(False, !qh_RESETvisible /*qh newvertex_list, empty newfacet_list and visible_list*/);
-
-  trace2((qh ferr, 2050, "qh_triangulate: identify degenerate tricoplanar facets from f%d\n", getid_(new_facet_list)));
-  trace2((qh ferr, 2051, "qh_triangulate: and replace facet->f.triowner with tricoplanar facets that own center, normal, etc.\n"));
-  FORALLfacet_(new_facet_list) {
-    if (facet->tricoplanar && !facet->visible) {
-      FOREACHneighbor_i_(facet) {
-        if (neighbor_i == 0) {  /* first iteration */
-          if (neighbor->tricoplanar)
-            orig_neighbor= neighbor->f.triowner;
-          else
-            orig_neighbor= neighbor;
-        }else {
-          if (neighbor->tricoplanar)
-            otherfacet= neighbor->f.triowner;
-          else
-            otherfacet= neighbor;
-          if (orig_neighbor == otherfacet) {
-            zinc_(Ztridegen);
-            facet->degenerate= True;
-            break;
-          }
-        }
-      }
-    }
-  }
-
-  trace2((qh ferr, 2052, "qh_triangulate: delete visible facets -- non-simplicial, null, and mirrored facets\n"));
-  owner= NULL;
-  visible= NULL;
-  for (facet= new_facet_list; facet && facet->next; facet= nextfacet) { /* may delete facet */
-    nextfacet= facet->next;
-    if (facet->visible) {
-      if (facet->tricoplanar) { /* a null or mirrored facet */
-        qh_delfacet(facet);
-        qh num_visible--;
-      }else {  /* a non-simplicial facet followed by its tricoplanars */
-        if (visible && !owner) {
-          /*  RBOX 200 s D5 t1001471447 | QHULL Qt C-0.01 Qx Qc Tv Qt -- f4483 had 6 vertices/neighbors and 8 ridges */
-          trace2((qh ferr, 2053, "qh_triangulate: all tricoplanar facets degenerate for non-simplicial facet f%d\n",
-                       visible->id));
-          qh_delfacet(visible);
-          qh num_visible--;
-        }
-        visible= facet;
-        owner= NULL;
-      }
-    }else if (facet->tricoplanar) {
-      if (facet->f.triowner != visible) {
-        qh_fprintf(qh ferr, 6162, "qhull error (qh_triangulate): tricoplanar facet f%d not owned by its visible, non-simplicial facet f%d\n", facet->id, getid_(visible));
-        qh_errexit2 (qh_ERRqhull, facet, visible);
-      }
-      if (owner)
-        facet->f.triowner= owner;
-      else if (visible != NULL && !facet->degenerate) {
-        owner= facet;
-        nextfacet= visible->next; /* rescan tricoplanar facets with owner */
-        facet->keepcentrum= True;  /* one facet owns ->normal, etc. */
-        facet->coplanarset= visible->coplanarset;
-        facet->outsideset= visible->outsideset;
-        visible->coplanarset= NULL;
-        visible->outsideset= NULL;
-        if (!qh TRInormals) { /* center and normal copied to tricoplanar facets */
-          visible->center= NULL;
-          visible->normal= NULL;
-        }
-        qh_delfacet(visible);
-        qh num_visible--;
-      }
-    }
-  }
-  if (visible && !owner) {
-    trace2((qh ferr, 2054, "qh_triangulate: all tricoplanar facets degenerate for last non-simplicial facet f%d\n",
-                 visible->id));
-    qh_delfacet(visible);
-    qh num_visible--;
-  }
-  qh NEWfacets= False;
-  qh ONLYgood= onlygood; /* restore value */
-  if (qh CHECKfrequently)
-    qh_checkpolygon(qh facet_list);
-  qh hasTriangulation= True;
-} /* triangulate */
-
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="triangulate_facet">-</a>
-
-  qh_triangulate_facet(facetA)
-    triangulate a non-simplicial facet
-      if qh.CENTERtype=qh_ASvoronoi, sets its Voronoi center
-  returns:
-    qh.newfacet_list == simplicial facets
-      facet->tricoplanar set and ->keepcentrum false
-      facet->degenerate set if duplicated apex
-      facet->f.trivisible set to facetA
-      facet->center copied from facetA (created if qh_ASvoronoi)
-        qh_eachvoronoi, qh_detvridge, qh_detvridge3 assume centers copied
-      facet->normal,offset,maxoutside copied from facetA
-
-  notes:
-      qh_makenew_nonsimplicial uses neighbor->seen for the same
-
-  see also:
-      qh_addpoint() -- add a point
-      qh_makenewfacets() -- construct a cone of facets for a new vertex
-
-  design:
-      if qh_ASvoronoi,
-         compute Voronoi center (facet->center)
-      select first vertex (highest ID to preserve ID ordering of ->vertices)
-      triangulate from vertex to ridges
-      copy facet->center, normal, offset
-      update vertex neighbors
-*/
-void qh_triangulate_facet(facetT *facetA, vertexT **first_vertex) {
-  facetT *newfacet;
-  facetT *neighbor, **neighborp;
-  vertexT *apex;
-  int numnew=0;
-
-  trace3((qh ferr, 3020, "qh_triangulate_facet: triangulate facet f%d\n", facetA->id));
-
-  if (qh IStracing >= 4)
-    qh_printfacet(qh ferr, facetA);
-  FOREACHneighbor_(facetA) {
-    neighbor->seen= False;
-    neighbor->coplanar= False;
-  }
-  if (qh CENTERtype == qh_ASvoronoi && !facetA->center  /* matches upperdelaunay in qh_setfacetplane() */
-        && fabs_(facetA->normal[qh hull_dim -1]) >= qh ANGLEround * qh_ZEROdelaunay) {
-    facetA->center= qh_facetcenter(facetA->vertices);
-  }
-  qh_willdelete(facetA, NULL);
-  qh newfacet_list= qh facet_tail;
-  facetA->visitid= qh visit_id;
-  apex= SETfirstt_(facetA->vertices, vertexT);
-  qh_makenew_nonsimplicial(facetA, apex, &numnew);
-  SETfirst_(facetA->neighbors)= NULL;
-  FORALLnew_facets {
-    newfacet->tricoplanar= True;
-    newfacet->f.trivisible= facetA;
-    newfacet->degenerate= False;
-    newfacet->upperdelaunay= facetA->upperdelaunay;
-    newfacet->good= facetA->good;
-    if (qh TRInormals) {
-      newfacet->keepcentrum= True;
-      newfacet->normal= qh_copypoints(facetA->normal, 1, qh hull_dim);
-      if (qh CENTERtype == qh_AScentrum)
-        newfacet->center= qh_getcentrum(newfacet);
-      else
-        newfacet->center= qh_copypoints(facetA->center, 1, qh hull_dim);
-    }else {
-      newfacet->keepcentrum= False;
-      newfacet->normal= facetA->normal;
-      newfacet->center= facetA->center;
-    }
-    newfacet->offset= facetA->offset;
-#if qh_MAXoutside
-    newfacet->maxoutside= facetA->maxoutside;
-#endif
-  }
-  qh_matchnewfacets(/*qh newfacet_list*/);
-  zinc_(Ztricoplanar);
-  zadd_(Ztricoplanartot, numnew);
-  zmax_(Ztricoplanarmax, numnew);
-  qh visible_list= NULL;
-  if (!(*first_vertex))
-    (*first_vertex)= qh newvertex_list;
-  qh newvertex_list= NULL;
-  qh_updatevertices(/*qh newfacet_list, empty visible_list and newvertex_list*/);
-  qh_resetlists(False, !qh_RESETvisible /*qh newfacet_list, empty visible_list and newvertex_list*/);
-} /* triangulate_facet */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="triangulate_link">-</a>
-
-  qh_triangulate_link(oldfacetA, facetA, oldfacetB, facetB)
-    relink facetA to facetB via oldfacets
-  returns:
-    adds mirror facets to qh degen_mergeset (4-d and up only)
-  design:
-    if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_link(facetT *oldfacetA, facetT *facetA, facetT *oldfacetB, facetT *facetB) {
-  int errmirror= False;
-
-  trace3((qh ferr, 3021, "qh_triangulate_link: relink old facets f%d and f%d between neighbors f%d and f%d\n",
-         oldfacetA->id, oldfacetB->id, facetA->id, facetB->id));
-  if (qh_setin(facetA->neighbors, facetB)) {
-    if (!qh_setin(facetB->neighbors, facetA))
-      errmirror= True;
-    else
-      qh_appendmergeset(facetA, facetB, MRGmirror, NULL);
-  }else if (qh_setin(facetB->neighbors, facetA))
-    errmirror= True;
-  if (errmirror) {
-    qh_fprintf(qh ferr, 6163, "qhull error (qh_triangulate_link): mirror facets f%d and f%d do not match for old facets f%d and f%d\n",
-       facetA->id, facetB->id, oldfacetA->id, oldfacetB->id);
-    qh_errexit2 (qh_ERRqhull, facetA, facetB);
-  }
-  qh_setreplace(facetB->neighbors, oldfacetB, facetA);
-  qh_setreplace(facetA->neighbors, oldfacetA, facetB);
-} /* triangulate_link */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="triangulate_mirror">-</a>
-
-  qh_triangulate_mirror(facetA, facetB)
-    delete mirrored facets from qh_triangulate_null() and qh_triangulate_mirror
-      a mirrored facet shares the same vertices of a logical ridge
-  design:
-    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
-    if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_mirror(facetT *facetA, facetT *facetB) {
-  facetT *neighbor, *neighborB;
-  int neighbor_i, neighbor_n;
-
-  trace3((qh ferr, 3022, "qh_triangulate_mirror: delete mirrored facets f%d and f%d\n",
-         facetA->id, facetB->id));
-  FOREACHneighbor_i_(facetA) {
-    neighborB= SETelemt_(facetB->neighbors, neighbor_i, facetT);
-    if (neighbor == neighborB)
-      continue; /* occurs twice */
-    qh_triangulate_link(facetA, neighbor, facetB, neighborB);
-  }
-  qh_willdelete(facetA, NULL);
-  qh_willdelete(facetB, NULL);
-} /* triangulate_mirror */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="triangulate_null">-</a>
-
-  qh_triangulate_null(facetA)
-    remove null facetA from qh_triangulate_facet()
-      a null facet has vertex #1 (apex) == vertex #2
-  returns:
-    adds facetA to ->visible for deletion after qh_updatevertices
-    qh degen_mergeset contains mirror facets (4-d and up only)
-  design:
-    since a null facet duplicates the first two vertices, the opposing neighbors absorb the null facet
-    if they are already neighbors, the opposing neighbors become MRGmirror facets
-*/
-void qh_triangulate_null(facetT *facetA) {
-  facetT *neighbor, *otherfacet;
-
-  trace3((qh ferr, 3023, "qh_triangulate_null: delete null facet f%d\n", facetA->id));
-  neighbor= SETfirstt_(facetA->neighbors, facetT);
-  otherfacet= SETsecondt_(facetA->neighbors, facetT);
-  qh_triangulate_link(facetA, neighbor, facetA, otherfacet);
-  qh_willdelete(facetA, NULL);
-} /* triangulate_null */
-
-#else /* qh_NOmerge */
-void qh_triangulate(void) {
-}
-#endif /* qh_NOmerge */
-
-   /*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="vertexintersect">-</a>
-
-  qh_vertexintersect( vertexsetA, vertexsetB )
-    intersects two vertex sets (inverse id ordered)
-    vertexsetA is a temporary set at the top of qhmem.tempstack
-
-  returns:
-    replaces vertexsetA with the intersection
-
-  notes:
-    could overwrite vertexsetA if currently too slow
-*/
-void qh_vertexintersect(setT **vertexsetA,setT *vertexsetB) {
-  setT *intersection;
-
-  intersection= qh_vertexintersect_new(*vertexsetA, vertexsetB);
-  qh_settempfree(vertexsetA);
-  *vertexsetA= intersection;
-  qh_settemppush(intersection);
-} /* vertexintersect */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="vertexintersect_new">-</a>
-
-  qh_vertexintersect_new(  )
-    intersects two vertex sets (inverse id ordered)
-
-  returns:
-    a new set
-*/
-setT *qh_vertexintersect_new(setT *vertexsetA,setT *vertexsetB) {
-  setT *intersection= qh_setnew(qh hull_dim - 1);
-  vertexT **vertexA= SETaddr_(vertexsetA, vertexT);
-  vertexT **vertexB= SETaddr_(vertexsetB, vertexT);
-
-  while (*vertexA && *vertexB) {
-    if (*vertexA  == *vertexB) {
-      qh_setappend(&intersection, *vertexA);
-      vertexA++; vertexB++;
-    }else {
-      if ((*vertexA)->id > (*vertexB)->id)
-        vertexA++;
-      else
-        vertexB++;
-    }
-  }
-  return intersection;
-} /* vertexintersect_new */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="vertexneighbors">-</a>
-
-  qh_vertexneighbors()
-    for each vertex in qh.facet_list,
-      determine its neighboring facets
-
-  returns:
-    sets qh.VERTEXneighbors
-      nop if qh.VERTEXneighbors already set
-      qh_addpoint() will maintain them
-
-  notes:
-    assumes all vertex->neighbors are NULL
-
-  design:
-    for each facet
-      for each vertex
-        append facet to vertex->neighbors
-*/
-void qh_vertexneighbors(void /*qh facet_list*/) {
-  facetT *facet;
-  vertexT *vertex, **vertexp;
-
-  if (qh VERTEXneighbors)
-    return;
-  trace1((qh ferr, 1035, "qh_vertexneighbors: determine neighboring facets for each vertex\n"));
-  qh vertex_visit++;
-  FORALLfacets {
-    if (facet->visible)
-      continue;
-    FOREACHvertex_(facet->vertices) {
-      if (vertex->visitid != qh vertex_visit) {
-        vertex->visitid= qh vertex_visit;
-        vertex->neighbors= qh_setnew(qh hull_dim);
-      }
-      qh_setappend(&vertex->neighbors, facet);
-    }
-  }
-  qh VERTEXneighbors= True;
-} /* vertexneighbors */
-
-/*-<a                             href="qh-poly.htm#TOC"
-  >-------------------------------</a><a name="vertexsubset">-</a>
-
-  qh_vertexsubset( vertexsetA, vertexsetB )
-    returns True if vertexsetA is a subset of vertexsetB
-    assumes vertexsets are sorted
-
-  note:
-    empty set is a subset of any other set
-*/
-boolT qh_vertexsubset(setT *vertexsetA, setT *vertexsetB) {
-  vertexT **vertexA= (vertexT **) SETaddr_(vertexsetA, vertexT);
-  vertexT **vertexB= (vertexT **) SETaddr_(vertexsetB, vertexT);
-
-  while (True) {
-    if (!*vertexA)
-      return True;
-    if (!*vertexB)
-      return False;
-    if ((*vertexA)->id > (*vertexB)->id)
-      return False;
-    if (*vertexA  == *vertexB)
-      vertexA++;
-    vertexB++;
-  }
-  return False; /* avoid warnings */
-} /* vertexsubset */
diff --git a/alg/libqhull/rboxlib.c b/alg/libqhull/rboxlib.c
deleted file mode 100644
index d877eba..0000000
--- a/alg/libqhull/rboxlib.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/*<html><pre>  -<a                             href="index.htm#TOC"
-  >-------------------------------</a><a name="TOP">-</a>
-
-   rboxlib.c
-     Generate input points
-
-   notes:
-     For documentation, see prompt[] of rbox.c
-     50 points generated for 'rbox D4'
-
-   WARNING:
-     incorrect range if qh_RANDOMmax is defined wrong (user.h)
-*/
-
-#include "random.h"
-#include "libqhull.h"
-
-#include <ctype.h>
-#include <limits.h>
-#include <math.h>
-#include <setjmp.h>
-#include <string.h>
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef _MSC_VER  /* Microsoft Visual C++ */
-#pragma warning( disable : 4706)  /* assignment within conditional expression. */
-#pragma warning( disable : 4996)  /* this function (strncat,sprintf,strcpy) or variable may be unsafe. */
-#endif
-
-#define MAXdim 200
-
-/* ------------------------------ prototypes ----------------*/
-int roundi( double a);
-void out1( double a);
-void out2n( double a, double b);
-void out3n( double a, double b, double c);
-
-void    qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
-void    qh_free(void *mem);
-void   *qh_malloc(size_t size);
-int     qh_rand( void);
-void    qh_srand( int seed);
-
-
-/* ------------------------------ globals -------------------*/
-
-/* No state is carried between rbox requests */
-typedef struct rboxT rboxT;
-struct rboxT {
-  FILE *fout;
-  FILE *ferr;
-  int isinteger;
-  double out_offset;
-  jmp_buf errexit;        /* exit label for rboxpoints, defined by setjmp(), called by qh_errexit_rbox() */
-};
-
-
-int rbox_inuse= 0;
-rboxT rbox;
-
-/*-<a                             href="qh-qhull.htm#TOC"
-  >-------------------------------</a><a name="rboxpoints">-</a>
-
-  qh_rboxpoints( fout, ferr, rbox_command )
-    Generate points to fout according to rbox options
-    Report errors on ferr
-
-  returns:
-    0 (qh_ERRnone) on success
-    1 (qh_ERRinput) on input error
-    4 (qh_ERRmem) on memory error
-    5 (qh_ERRqhull) on internal error
-
-  notes:
-    To avoid stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user.c)
-    Rbox is not multithreaded.
-
-  design:
-    Straight line code (consider defining a struct and functions):
-
-    Parse arguments into variables
-    Determine the number of points
-    Generate the points
-*/
-int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
-  int i,j,k;
-  int gendim;
-  int cubesize, diamondsize, seed=0, count, apex;
-  int dim=3 , numpoints= 0, totpoints, addpoints=0;
-  int issphere=0, isaxis=0,  iscdd= 0, islens= 0, isregular=0, iswidth=0, addcube=0;
-  int isgap=0, isspiral=0, NOcommand= 0, adddiamond=0;
-  int israndom=0, istime=0;
-  int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
-  double width=0.0, gap=0.0, radius= 0.0;
-  double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
-  double *simplex= NULL, *simplexp;
-  int nthroot, mult[MAXdim];
-  double norm, factor, randr, rangap, lensangle= 0, lensbase= 1;
-  double anglediff, angle, x, y, cube= 0.0, diamond= 0.0;
-  double box= qh_DEFAULTbox; /* scale all numbers before output */
-  double randmax= qh_RANDOMmax;
-  char command[200], seedbuf[200];
-  char *s= command, *t, *first_point= NULL;
-  time_t timedata;
-  int exitcode;
-
-  if (rbox_inuse) {
-    qh_fprintf_rbox(rbox.ferr, 6188, "rbox error: rbox in use by another process.  Please lock calls to rbox.\n");
-    return qh_ERRqhull;
-  }
-  rbox_inuse= True;
-  rbox.ferr= ferr;
-  rbox.fout= fout;
-
-  exitcode= setjmp(rbox.errexit);
-  if (exitcode) {
-    /* same code for error exit and normal return */
-    if (simplex)
-        qh_free(simplex);
-    rbox_inuse= False;
-    return exitcode;
-  }
-
-  *command= '\0';
-  strncat(command, rbox_command, sizeof(command)-strlen(command)-1);
-
-  while (*s && !isspace(*s))  /* skip program name */
-    s++;
-  while (*s) {
-    while (*s && isspace(*s))
-      s++;
-    if (*s == '-')
-      s++;
-    if (!*s)
-      break;
-    if (isdigit(*s)) {
-      numpoints= qh_strtol(s, &s);
-      continue;
-    }
-    /* ============= read flags =============== */
-    switch (*s++) {
-    case 'c':
-      addcube= 1;
-      t= s;
-      while (isspace(*t))
-        t++;
-      if (*t == 'G')
-        cube= qh_strtod(++t, &s);
-      break;
-    case 'd':
-      adddiamond= 1;
-      t= s;
-      while (isspace(*t))
-        t++;
-      if (*t == 'G')
-        diamond= qh_strtod(++t, &s);
-      break;
-    case 'h':
-      iscdd= 1;
-      break;
-    case 'l':
-      isspiral= 1;
-      break;
-    case 'n':
-      NOcommand= 1;
-      break;
-    case 'r':
-      isregular= 1;
-      break;
-    case 's':
-      issphere= 1;
-      break;
-    case 't':
-      istime= 1;
-      if (isdigit(*s)) {
-        seed= qh_strtol(s, &s);
-        israndom= 0;
-      }else
-        israndom= 1;
-      break;
-    case 'x':
-      issimplex= 1;
-      break;
-    case 'y':
-      issimplex2= 1;
-      break;
-    case 'z':
-      rbox.isinteger= 1;
-      break;
-    case 'B':
-      box= qh_strtod(s, &s);
-      isbox= 1;
-      break;
-    case 'D':
-      dim= qh_strtol(s, &s);
-      if (dim < 1
-      || dim > MAXdim) {
-        qh_fprintf_rbox(rbox.ferr, 6189, "rbox error: dimension, D%d, out of bounds (>=%d or <=0)", dim, MAXdim);
-        qh_errexit_rbox(qh_ERRinput);
-      }
-      break;
-    case 'G':
-      if (isdigit(*s))
-        gap= qh_strtod(s, &s);
-      else
-        gap= 0.5;
-      isgap= 1;
-      break;
-    case 'L':
-      if (isdigit(*s))
-        radius= qh_strtod(s, &s);
-      else
-        radius= 10;
-      islens= 1;
-      break;
-    case 'M':
-      ismesh= 1;
-      if (*s)
-        meshn= qh_strtod(s, &s);
-      if (*s == ',') {
-        ++s;
-        meshm= qh_strtod(s, &s);
-      }else
-        meshm= 0.0;
-      if (*s == ',') {
-        ++s;
-        meshr= qh_strtod(s, &s);
-      }else
-        meshr= sqrt(meshn*meshn + meshm*meshm);
-      if (*s && !isspace(*s)) {
-        qh_fprintf_rbox(rbox.ferr, 7069, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
-        meshn= 3.0, meshm=4.0, meshr=5.0;
-      }
-      break;
-    case 'O':
-      rbox.out_offset= qh_strtod(s, &s);
-      break;
-    case 'P':
-      if (!first_point)
-        first_point= s-1;
-      addpoints++;
-      while (*s && !isspace(*s))   /* read points later */
-        s++;
-      break;
-    case 'W':
-      width= qh_strtod(s, &s);
-      iswidth= 1;
-      break;
-    case 'Z':
-      if (isdigit(*s))
-        radius= qh_strtod(s, &s);
-      else
-        radius= 1.0;
-      isaxis= 1;
-      break;
-    default:
-      qh_fprintf_rbox(rbox.ferr, 7070, "rbox error: unknown flag at %s.\nExecute 'rbox' without arguments for documentation.\n", s);
-      qh_errexit_rbox(qh_ERRinput);
-    }
-    if (*s && !isspace(*s)) {
-      qh_fprintf_rbox(rbox.ferr, 7071, "rbox error: missing space between flags at %s.\n", s);
-      qh_errexit_rbox(qh_ERRinput);
-    }
-  }
-
-  /* ============= defaults, constants, and sizes =============== */
-  if (rbox.isinteger && !isbox)
-    box= qh_DEFAULTzbox;
-  if (addcube) {
-    cubesize= (int)floor(ldexp(1.0,dim)+0.5);
-    if (cube == 0.0)
-      cube= box;
-  }else
-    cubesize= 0;
-  if (adddiamond) {
-    diamondsize= 2*dim;
-    if (diamond == 0.0)
-      diamond= box;
-  }else
-    diamondsize= 0;
-  if (islens) {
-    if (isaxis) {
-        qh_fprintf_rbox(rbox.ferr, 6190, "rbox error: can not combine 'Ln' with 'Zn'\n");
-        qh_errexit_rbox(qh_ERRinput);
-    }
-    if (radius <= 1.0) {
-        qh_fprintf_rbox(rbox.ferr, 6191, "rbox error: lens radius %.2g should be greater than 1.0\n",
-               radius);
-        qh_errexit_rbox(qh_ERRinput);
-    }
-    lensangle= asin(1.0/radius);
-    lensbase= radius * cos(lensangle);
-  }
-
-  if (!numpoints) {
-    if (issimplex2)
-        ; /* ok */
-    else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
-        qh_fprintf_rbox(rbox.ferr, 6192, "rbox error: missing count\n");
-        qh_errexit_rbox(qh_ERRinput);
-    }else if (adddiamond + addcube + addpoints)
-        ; /* ok */
-    else {
-        numpoints= 50;  /* ./rbox D4 is the test case */
-        issphere= 1;
-    }
-  }
-  if ((issimplex + islens + isspiral + ismesh > 1)
-  || (issimplex + issphere + isspiral + ismesh > 1)) {
-    qh_fprintf_rbox(rbox.ferr, 6193, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
-    qh_errexit_rbox(qh_ERRinput);
-  }
-
-  /* ============= print header with total points =============== */
-  if (issimplex || ismesh)
-    totpoints= numpoints;
-  else if (issimplex2)
-    totpoints= numpoints+dim+1;
-  else if (isregular) {
-    totpoints= numpoints;
-    if (dim == 2) {
-        if (islens)
-          totpoints += numpoints - 2;
-    }else if (dim == 3) {
-        if (islens)
-          totpoints += 2 * numpoints;
-      else if (isgap)
-        totpoints += 1 + numpoints;
-      else
-        totpoints += 2;
-    }
-  }else
-    totpoints= numpoints + isaxis;
-  totpoints += cubesize + diamondsize + addpoints;
-
-  /* ============= seed randoms =============== */
-  if (istime == 0) {
-    for (s=command; *s; s++) {
-      if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
-        i= 'x';
-      else
-        i= *s;
-      seed= 11*seed + i;
-    }
-  }else if (israndom) {
-    seed= (int)time(&timedata);
-    sprintf(seedbuf, " t%d", seed);  /* appends an extra t, not worth removing */
-    strncat(command, seedbuf, sizeof(command)-strlen(command)-1);
-    t= strstr(command, " t ");
-    if (t)
-      strcpy(t+1, t+3); /* remove " t " */
-  } /* else, seed explicitly set to n */
-  qh_RANDOMseed_(seed);
-
-  /* ============= print header =============== */
-
-  if (iscdd)
-      qh_fprintf_rbox(rbox.fout, 9391, "%s\nbegin\n        %d %d %s\n",
-      NOcommand ? "" : command,
-      totpoints, dim+1,
-      rbox.isinteger ? "integer" : "real");
-  else if (NOcommand)
-      qh_fprintf_rbox(rbox.fout, 9392, "%d\n%d\n", dim, totpoints);
-  else
-      qh_fprintf_rbox(rbox.fout, 9393, "%d %s\n%d\n", dim, command, totpoints);
-
-  /* ============= explicit points =============== */
-  if ((s= first_point)) {
-    while (s && *s) { /* 'P' */
-      count= 0;
-      if (iscdd)
-        out1( 1.0);
-      while (*++s) {
-        out1( qh_strtod(s, &s));
-        count++;
-        if (isspace(*s) || !*s)
-          break;
-        if (*s != ',') {
-          qh_fprintf_rbox(rbox.ferr, 6194, "rbox error: missing comma after coordinate in %s\n\n", s);
-          qh_errexit_rbox(qh_ERRinput);
-        }
-      }
-      if (count < dim) {
-        for (k=dim-count; k--; )
-          out1( 0.0);
-      }else if (count > dim) {
-        qh_fprintf_rbox(rbox.ferr, 6195, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
-                  count, dim, s);
-        qh_errexit_rbox(qh_ERRinput);
-      }
-      qh_fprintf_rbox(rbox.fout, 9394, "\n");
-      while ((s= strchr(s, 'P'))) {
-        if (isspace(s[-1]))
-          break;
-      }
-    }
-  }
-
-  /* ============= simplex distribution =============== */
-  if (issimplex+issimplex2) {
-    if (!(simplex= (double*)qh_malloc( dim * (dim+1) * sizeof(double)))) {
-      qh_fprintf_rbox(rbox.ferr, 6196, "rbox error: insufficient memory for simplex\n");
-      qh_errexit_rbox(qh_ERRmem); /* qh_ERRmem */
-    }
-    simplexp= simplex;
-    if (isregular) {
-      for (i=0; i<dim; i++) {
-        for (k=0; k<dim; k++)
-          *(simplexp++)= i==k ? 1.0 : 0.0;
-      }
-      for (k=0; k<dim; k++)
-        *(simplexp++)= -1.0;
-    }else {
-      for (i=0; i<dim+1; i++) {
-        for (k=0; k<dim; k++) {
-          randr= qh_RANDOMint;
-          *(simplexp++)= 2.0 * randr/randmax - 1.0;
-        }
-      }
-    }
-    if (issimplex2) {
-        simplexp= simplex;
-      for (i=0; i<dim+1; i++) {
-        if (iscdd)
-          out1( 1.0);
-        for (k=0; k<dim; k++)
-          out1( *(simplexp++) * box);
-        qh_fprintf_rbox(rbox.fout, 9395, "\n");
-      }
-    }
-    for (j=0; j<numpoints; j++) {
-      if (iswidth)
-        apex= qh_RANDOMint % (dim+1);
-      else
-        apex= -1;
-      for (k=0; k<dim; k++)
-        coord[k]= 0.0;
-      norm= 0.0;
-      for (i=0; i<dim+1; i++) {
-        randr= qh_RANDOMint;
-        factor= randr/randmax;
-        if (i == apex)
-          factor *= width;
-        norm += factor;
-        for (k=0; k<dim; k++) {
-          simplexp= simplex + i*dim + k;
-          coord[k] += factor * (*simplexp);
-        }
-      }
-      for (k=0; k<dim; k++)
-        coord[k] /= norm;
-      if (iscdd)
-        out1( 1.0);
-      for (k=0; k < dim; k++)
-        out1( coord[k] * box);
-      qh_fprintf_rbox(rbox.fout, 9396, "\n");
-    }
-    isregular= 0; /* continue with isbox */
-    numpoints= 0;
-  }
-
-  /* ============= mesh distribution =============== */
-  if (ismesh) {
-    nthroot= (int)(pow((double)numpoints, 1.0/dim) + 0.99999);
-    for (k=dim; k--; )
-      mult[k]= 0;
-    for (i=0; i < numpoints; i++) {
-      for (k=0; k < dim; k++) {
-        if (k == 0)
-          out1( mult[0] * meshn + mult[1] * (-meshm));
-        else if (k == 1)
-          out1( mult[0] * meshm + mult[1] * meshn);
-        else
-          out1( mult[k] * meshr );
-      }
-      qh_fprintf_rbox(rbox.fout, 9397, "\n");
-      for (k=0; k < dim; k++) {
-        if (++mult[k] < nthroot)
-          break;
-        mult[k]= 0;
-      }
-    }
-  }
-  /* ============= regular points for 's' =============== */
-  else if (isregular && !islens) {
-    if (dim != 2 && dim != 3) {
-      qh_fprintf_rbox(rbox.ferr, 6197, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
-      qh_errexit_rbox(qh_ERRinput);
-    }
-    if (!isaxis || radius == 0.0) {
-      isaxis= 1;
-      radius= 1.0;
-    }
-    if (dim == 3) {
-      if (iscdd)
-        out1( 1.0);
-      out3n( 0.0, 0.0, -box);
-      if (!isgap) {
-        if (iscdd)
-          out1( 1.0);
-        out3n( 0.0, 0.0, box);
-      }
-    }
-    angle= 0.0;
-    anglediff= 2.0 * M_PI/numpoints;
-    for (i=0; i < numpoints; i++) {
-      angle += anglediff;
-      x= radius * cos(angle);
-      y= radius * sin(angle);
-      if (dim == 2) {
-        if (iscdd)
-          out1( 1.0);
-        out2n( x*box, y*box);
-      }else {
-        norm= sqrt(1.0 + x*x + y*y);
-        if (iscdd)
-          out1( 1.0);
-        out3n( box*x/norm, box*y/norm, box/norm);
-        if (isgap) {
-          x *= 1-gap;
-          y *= 1-gap;
-          norm= sqrt(1.0 + x*x + y*y);
-          if (iscdd)
-            out1( 1.0);
-          out3n( box*x/norm, box*y/norm, box/norm);
-        }
-      }
-    }
-  }
-  /* ============= regular points for 'r Ln D2' =============== */
-  else if (isregular && islens && dim == 2) {
-    double cos_0;
-
-    angle= lensangle;
-    anglediff= 2 * lensangle/(numpoints - 1);
-    cos_0= cos(lensangle);
-    for (i=0; i < numpoints; i++, angle -= anglediff) {
-      x= radius * sin(angle);
-      y= radius * (cos(angle) - cos_0);
-      if (iscdd)
-        out1( 1.0);
-      out2n( x*box, y*box);
-      if (i != 0 && i != numpoints - 1) {
-        if (iscdd)
-          out1( 1.0);
-        out2n( x*box, -y*box);
-      }
-    }
-  }
-  /* ============= regular points for 'r Ln D3' =============== */
-  else if (isregular && islens && dim != 2) {
-    if (dim != 3) {
-      qh_fprintf_rbox(rbox.ferr, 6198, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
-      qh_errexit_rbox(qh_ERRinput);
-    }
-    angle= 0.0;
-    anglediff= 2* M_PI/numpoints;
-    if (!isgap) {
-      isgap= 1;
-      gap= 0.5;
-    }
-    offset= sqrt(radius * radius - (1-gap)*(1-gap)) - lensbase;
-    for (i=0; i < numpoints; i++, angle += anglediff) {
-      x= cos(angle);
-      y= sin(angle);
-      if (iscdd)
-        out1( 1.0);
-      out3n( box*x, box*y, 0.0);
-      x *= 1-gap;
-      y *= 1-gap;
-      if (iscdd)
-        out1( 1.0);
-      out3n( box*x, box*y, box * offset);
-      if (iscdd)
-        out1( 1.0);
-      out3n( box*x, box*y, -box * offset);
-    }
-  }
-  /* ============= apex of 'Zn' distribution + gendim =============== */
-  else {
-    if (isaxis) {
-      gendim= dim-1;
-      if (iscdd)
-        out1( 1.0);
-      for (j=0; j < gendim; j++)
-        out1( 0.0);
-      out1( -box);
-      qh_fprintf_rbox(rbox.fout, 9398, "\n");
-    }else if (islens)
-      gendim= dim-1;
-    else
-      gendim= dim;
-    /* ============= generate random point in unit cube =============== */
-    for (i=0; i < numpoints; i++) {
-      norm= 0.0;
-      for (j=0; j < gendim; j++) {
-        randr= qh_RANDOMint;
-        coord[j]= 2.0 * randr/randmax - 1.0;
-        norm += coord[j] * coord[j];
-      }
-      norm= sqrt(norm);
-      /* ============= dim-1 point of 'Zn' distribution ========== */
-      if (isaxis) {
-        if (!isgap) {
-          isgap= 1;
-          gap= 1.0;
-        }
-        randr= qh_RANDOMint;
-        rangap= 1.0 - gap * randr/randmax;
-        factor= radius * rangap / norm;
-        for (j=0; j<gendim; j++)
-          coord[j]= factor * coord[j];
-      /* ============= dim-1 point of 'Ln s' distribution =========== */
-      }else if (islens && issphere) {
-        if (!isgap) {
-          isgap= 1;
-          gap= 1.0;
-        }
-        randr= qh_RANDOMint;
-        rangap= 1.0 - gap * randr/randmax;
-        factor= rangap / norm;
-        for (j=0; j<gendim; j++)
-          coord[j]= factor * coord[j];
-      /* ============= dim-1 point of 'Ln' distribution ========== */
-      }else if (islens && !issphere) {
-        if (!isgap) {
-          isgap= 1;
-          gap= 1.0;
-        }
-        j= qh_RANDOMint % gendim;
-        if (coord[j] < 0)
-          coord[j]= -1.0 - coord[j] * gap;
-        else
-          coord[j]= 1.0 - coord[j] * gap;
-      /* ============= point of 'l' distribution =============== */
-      }else if (isspiral) {
-        if (dim != 3) {
-          qh_fprintf_rbox(rbox.ferr, 6199, "rbox error: spiral distribution is available only in 3d\n\n");
-          longjmp(rbox.errexit,qh_ERRinput);
-        }
-        coord[0]= cos(2*M_PI*i/(numpoints - 1));
-        coord[1]= sin(2*M_PI*i/(numpoints - 1));
-        coord[2]= 2.0*(double)i/(double)(numpoints-1) - 1.0;
-      /* ============= point of 's' distribution =============== */
-      }else if (issphere) {
-        factor= 1.0/norm;
-        if (iswidth) {
-          randr= qh_RANDOMint;
-          factor *= 1.0 - width * randr/randmax;
-        }
-        for (j=0; j<dim; j++)
-          coord[j]= factor * coord[j];
-      }
-      /* ============= project 'Zn s' point in to sphere =============== */
-      if (isaxis && issphere) {
-        coord[dim-1]= 1.0;
-        norm= 1.0;
-        for (j=0; j<gendim; j++)
-          norm += coord[j] * coord[j];
-        norm= sqrt(norm);
-        for (j=0; j<dim; j++)
-          coord[j]= coord[j] / norm;
-        if (iswidth) {
-          randr= qh_RANDOMint;
-          coord[dim-1] *= 1 - width * randr/randmax;
-        }
-      /* ============= project 'Zn' point onto cube =============== */
-      }else if (isaxis && !issphere) {  /* not very interesting */
-        randr= qh_RANDOMint;
-        coord[dim-1]= 2.0 * randr/randmax - 1.0;
-      /* ============= project 'Ln' point out to sphere =============== */
-      }else if (islens) {
-        coord[dim-1]= lensbase;
-        for (j=0, norm= 0; j<dim; j++)
-          norm += coord[j] * coord[j];
-        norm= sqrt(norm);
-        for (j=0; j<dim; j++)
-          coord[j]= coord[j] * radius/ norm;
-        coord[dim-1] -= lensbase;
-        if (iswidth) {
-          randr= qh_RANDOMint;
-          coord[dim-1] *= 1 - width * randr/randmax;
-        }
-        if (qh_RANDOMint > randmax/2)
-          coord[dim-1]= -coord[dim-1];
-      /* ============= project 'Wn' point toward boundary =============== */
-      }else if (iswidth && !issphere) {
-        j= qh_RANDOMint % gendim;
-        if (coord[j] < 0)
-          coord[j]= -1.0 - coord[j] * width;
-        else
-          coord[j]= 1.0 - coord[j] * width;
-      }
-      /* ============= write point =============== */
-      if (iscdd)
-        out1( 1.0);
-      for (k=0; k < dim; k++)
-        out1( coord[k] * box);
-      qh_fprintf_rbox(rbox.fout, 9399, "\n");
-    }
-  }
-
-  /* ============= write cube vertices =============== */
-  if (addcube) {
-    for (j=0; j<cubesize; j++) {
-      if (iscdd)
-        out1( 1.0);
-      for (k=dim-1; k>=0; k--) {
-        if (j & ( 1 << k))
-          out1( cube);
-        else
-          out1( -cube);
-      }
-      qh_fprintf_rbox(rbox.fout, 9400, "\n");
-    }
-  }
-
-  /* ============= write diamond vertices =============== */
-  if (adddiamond) {
-    for (j=0; j<diamondsize; j++) {
-      if (iscdd)
-        out1( 1.0);
-      for (k=dim-1; k>=0; k--) {
-        if (j/2 != k)
-          out1( 0.0);
-        else if (j & 0x1)
-          out1( diamond);
-        else
-          out1( -diamond);
-      }
-      qh_fprintf_rbox(rbox.fout, 9401, "\n");
-    }
-  }
-
-  if (iscdd)
-    qh_fprintf_rbox(rbox.fout, 9402, "end\nhull\n");
-
-  /* same code for error exit and normal return */
-  if (simplex)
-    qh_free(simplex);
-  rbox_inuse= False;
-  return qh_ERRnone;
-} /* rboxpoints */
-
-/*------------------------------------------------
-outxxx - output functions
-*/
-int roundi( double a) {
-  if (a < 0.0) {
-    if (a - 0.5 < INT_MIN) {
-      qh_fprintf_rbox(rbox.ferr, 6200, "rbox input error: negative coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
-      qh_errexit_rbox(qh_ERRinput);
-    }
-    return (int)(a - 0.5);
-  }else {
-    if (a + 0.5 > INT_MAX) {
-      qh_fprintf_rbox(rbox.ferr, 6201, "rbox input error: coordinate %2.2g is too large.  Reduce 'Bn'\n", a);
-      qh_errexit_rbox(qh_ERRinput);
-    }
-    return (int)(a + 0.5);
-  }
-} /* roundi */
-
-void out1(double a) {
-
-  if (rbox.isinteger)
-    qh_fprintf_rbox(rbox.fout, 9403, "%d ", roundi( a+rbox.out_offset));
-  else
-    qh_fprintf_rbox(rbox.fout, 9404, qh_REAL_1, a+rbox.out_offset);
-} /* out1 */
-
-void out2n( double a, double b) {
-
-  if (rbox.isinteger)
-    qh_fprintf_rbox(rbox.fout, 9405, "%d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset));
-  else
-    qh_fprintf_rbox(rbox.fout, 9406, qh_REAL_2n, a+rbox.out_offset, b+rbox.out_offset);
-} /* out2n */
-
-void out3n( double a, double b, double c) {
-
-  if (rbox.isinteger)
-    qh_fprintf_rbox(rbox.fout, 9407, "%d %d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset), roundi(c+rbox.out_offset));
-  else
-    qh_fprintf_rbox(rbox.fout, 9408, qh_REAL_3n, a+rbox.out_offset, b+rbox.out_offset, c+rbox.out_offset);
-} /* out3n */
-
-void qh_errexit_rbox(int exitcode)
-{
-    longjmp(rbox.errexit, exitcode);
-} /* rbox_errexit */
diff --git a/alg/llrasterize.cpp b/alg/llrasterize.cpp
index 6109a49..893ef4e 100644
--- a/alg/llrasterize.cpp
+++ b/alg/llrasterize.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: llrasterize.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Vector polygon rasterization code.
@@ -28,19 +27,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_alg.h"
+#include "cpl_port.h"
 #include "gdal_alg_priv.h"
 
-static int llCompareInt(const void *a, const void *b)
-{
-	return (*(const int *)a) - (*(const int *)b);
-}
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+#include <utility>
+
+#include "gdal_alg.h"
+
+CPL_CVSID("$Id: llrasterize.cpp 36894 2016-12-15 22:57:29Z rouault $");
 
-static void llSwapDouble(double *a, double *b)
+static int llCompareInt(const void *a, const void *b)
 {
-	double temp = *a;
-	*a = *b;
-	*b = temp;
+    return (*(const int *)a) - (*(const int *)b);
 }
 
 /************************************************************************/
@@ -97,142 +100,149 @@ void GDALdllImageFilledPolygon(int nRasterXSize, int nRasterYSize,
 No known bug
 *************************************************************************/
 
-    int i;
-    int y;
-    int miny, maxy,minx,maxx;
-    double dminy, dmaxy;
-    double dx1, dy1;
-    double dx2, dy2;
-    double dy;
-    double intersect;
-
-    int ind1, ind2;
-    int ints, n, part;
-    int *polyInts;
-
-    int horizontal_x1, horizontal_x2;
-
-    if (!nPartCount) {
+    if( !nPartCount )
+    {
         return;
     }
 
-    n = 0;
-    for( part = 0; part < nPartCount; part++ )
+    int n = 0;
+    for( int part = 0; part < nPartCount; part++ )
         n += panPartSize[part];
 
-    // +1 to make clang static analyzer not warn about potential malloc(0)
-    polyInts = (int *) malloc(sizeof(int) * (n+1));
-
-    dminy = padfY[0];
-    dmaxy = padfY[0];
-    for (i=1; (i < n); i++) {
+    // +1 to make clang static analyzer not warn about potential malloc(0).
+    int *polyInts = static_cast<int *>(malloc(sizeof(int) * (n + 1)));
 
-        if (padfY[i] < dminy) {
+    double dminy = padfY[0];
+    double dmaxy = padfY[0];
+    for( int i = 1; i < n; i++ )
+    {
+        if( padfY[i] < dminy )
+        {
             dminy = padfY[i];
         }
-        if (padfY[i] > dmaxy) {
+        if( padfY[i] > dmaxy )
+        {
             dmaxy = padfY[i];
         }
     }
-    miny = (int) dminy;
-    maxy = (int) dmaxy;
+    int miny = static_cast<int>(dminy);
+    int maxy = static_cast<int>(dmaxy);
 
     if( miny < 0 )
         miny = 0;
     if( maxy >= nRasterYSize )
-        maxy = nRasterYSize-1;
+        maxy = nRasterYSize - 1;
 
-    minx = 0;
-    maxx = nRasterXSize - 1;
+    int minx = 0;
+    const int maxx = nRasterXSize - 1;
 
-    /* Fix in 1.3: count a vertex only once */
-    for (y=miny; y <= maxy; y++) {
-        int	partoffset = 0;
+    // Fix in 1.3: count a vertex only once.
+    for( int y = miny; y <= maxy; y++ )
+    {
+        int partoffset = 0;
 
-        dy = y +0.5; /* center height of line*/
+        const double dy = y + 0.5;  // Center height of line.
 
-        part = 0;
-        ints = 0;
+        int part = 0;
+        int ints = 0;
 
-        /*Initialize polyInts, otherwise it can sometimes causes a seg fault */
+        // Initialize polyInts, otherwise it can sometimes causes a seg fault.
         memset(polyInts, -1, sizeof(int) * n);
 
-        for (i=0; (i < n); i++) {
-
-            if( i == partoffset + panPartSize[part] ) {
+        for( int i = 0; i < n; i++ )
+        {
+            if( i == partoffset + panPartSize[part] )
+            {
                 partoffset += panPartSize[part];
                 part++;
             }
 
-            if( i == partoffset ) {
+            int ind1 = 0;
+            int ind2 = 0;
+            if( i == partoffset )
+            {
                 ind1 = partoffset + panPartSize[part] - 1;
                 ind2 = partoffset;
-            } else {
+            }
+            else
+            {
                 ind1 = i-1;
                 ind2 = i;
             }
 
-            dy1 = padfY[ind1];
-            dy2 = padfY[ind2];
+            double dy1 = padfY[ind1];
+            double dy2 = padfY[ind2];
 
             if( (dy1 < dy && dy2 < dy) || (dy1 > dy && dy2 > dy) )
                 continue;
 
-            if (dy1 < dy2) {
+            double dx1 = 0.0;
+            double dx2 = 0.0;
+            if( dy1 < dy2 )
+            {
                 dx1 = padfX[ind1];
                 dx2 = padfX[ind2];
-            } else if (dy1 > dy2) {
+            }
+            else if( dy1 > dy2 )
+            {
                 dy2 = padfY[ind1];
                 dy1 = padfY[ind2];
                 dx2 = padfX[ind1];
                 dx1 = padfX[ind2];
-            } else /* if (fabs(dy1-dy2)< 1.e-6) */
+            }
+            else // if( fabs(dy1-dy2) < 1.e-6 )
             {
 
-                /*AE: DO NOT skip bottom horizontal segments
-                  -Fill them separately-
-                  They are not taken into account twice.*/
-                if (padfX[ind1] > padfX[ind2])
+                // AE: DO NOT skip bottom horizontal segments
+                // -Fill them separately-
+                // They are not taken into account twice.
+                if( padfX[ind1] > padfX[ind2] )
                 {
-                    horizontal_x1 = (int) floor(padfX[ind2]+0.5);
-                    horizontal_x2 = (int) floor(padfX[ind1]+0.5);
+                    const int horizontal_x1 =
+                        static_cast<int>(floor(padfX[ind2] + 0.5));
+                    const int horizontal_x2 =
+                        static_cast<int>(floor(padfX[ind1] + 0.5));
 
-                    if  ( (horizontal_x1 >  maxx) ||  (horizontal_x2 <= minx) )
+                    if( (horizontal_x1 >  maxx) ||  (horizontal_x2 <= minx) )
                         continue;
 
-                    /*fill the horizontal segment (separately from the rest)*/
-                    pfnScanlineFunc( pCBData, y, horizontal_x1, horizontal_x2 - 1, (dfVariant == NULL)?0:dfVariant[0] );
+                    // Fill the horizontal segment (separately from the rest).
+                    pfnScanlineFunc( pCBData, y, horizontal_x1,
+                                     horizontal_x2 - 1,
+                                     (dfVariant == NULL)?0:dfVariant[0] );
                     continue;
                 }
-                else /*skip top horizontal segments (they are already filled in the regular loop)*/
+                else
+                {
+                    // Skip top horizontal segments (they are already filled in
+                    // the regular loop).
                     continue;
-
+                }
             }
 
-            if(( dy < dy2 ) && (dy >= dy1))
+            if( dy < dy2 && dy >= dy1 )
             {
+                const double intersect = (dy-dy1) * (dx2-dx1) / (dy2-dy1) + dx1;
 
-                intersect = (dy-dy1) * (dx2-dx1) / (dy2-dy1) + dx1;
-
-                polyInts[ints++] = (int) floor(intersect+0.5);
+                polyInts[ints++] = static_cast<int>(floor(intersect + 0.5));
             }
         }
 
-        /*
-         * It would be more efficient to do this inline, to avoid
-         * a function call for each comparison.
-         * NOTE - mloskot: make llCompareInt a functor and use std
-         * algorithm and it will be optimized and expanded
-         * automatically in compile-time, with modularity preserved.
-         */
+        // It would be more efficient to do this inline, to avoid
+        // a function call for each comparison.
+        // NOTE - mloskot: make llCompareInt a functor and use std
+        // algorithm and it will be optimized and expanded
+        // automatically in compile-time, with modularity preserved.
+        //
+        // TODO(schwehr): Use std::sort.
         qsort(polyInts, ints, sizeof(int), llCompareInt);
 
-
-        for (i=0; (i < (ints)); i+=2)
+        for( int i = 0; i < ints; i += 2 )
         {
             if( polyInts[i] <= maxx && polyInts[i+1] > minx )
             {
-                pfnScanlineFunc( pCBData, y, polyInts[i], polyInts[i+1] - 1, (dfVariant == NULL)?0:dfVariant[0] );
+                pfnScanlineFunc(pCBData, y, polyInts[i], polyInts[i+1] - 1,
+                                dfVariant == NULL ? 0 : dfVariant[0]);
             }
         }
     }
@@ -250,17 +260,15 @@ void GDALdllImagePoint( int nRasterXSize, int nRasterYSize,
                         double *padfX, double *padfY, double *padfVariant,
                         llPointFunc pfnPointFunc, void *pCBData )
 {
-    int i;
-
-    for ( i = 0; i < nPartCount; i++ )
+    for( int i = 0; i < nPartCount; i++ )
     {
-        int nX = (int)floor( padfX[i] );
-        int nY = (int)floor( padfY[i] );
-        double dfVariant = 0;
+        const int nX = static_cast<int>(floor( padfX[i] ));
+        const int nY = static_cast<int>(floor( padfY[i] ));
+        double dfVariant = 0.0;
         if( padfVariant != NULL )
             dfVariant = padfVariant[i];
 
-        if ( 0 <= nX && nX < nRasterXSize && 0 <= nY && nY < nRasterYSize )
+        if( 0 <= nX && nX < nRasterXSize && 0 <= nY && nY < nRasterYSize )
             pfnPointFunc( pCBData, nY, nX, dfVariant );
     }
 }
@@ -274,24 +282,21 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                        double *padfX, double *padfY, double *padfVariant,
                        llPointFunc pfnPointFunc, void *pCBData )
 {
-    int     i, n;
-
-    if ( !nPartCount )
+    if( !nPartCount )
         return;
 
-    for ( i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
+    for( int i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
     {
-        int j;
-
-        for ( j = 1; j < panPartSize[i]; j++ )
+        for( int j = 1; j < panPartSize[i]; j++ )
         {
-            int iX = (int)floor( padfX[n + j - 1] );
-            int iY = (int)floor( padfY[n + j - 1] );
+            int iX = static_cast<int>(floor( padfX[n + j - 1] ));
+            int iY = static_cast<int>(floor( padfY[n + j - 1] ));
 
-            const int iX1 = (int)floor( padfX[n + j] );
-            const int iY1 = (int)floor( padfY[n + j] );
+            const int iX1 = static_cast<int>(floor(padfX[n + j]));
+            const int iY1 = static_cast<int>(floor(padfY[n + j]));
 
-            double dfVariant = 0, dfVariant1 = 0;
+            double dfVariant = 0.0;
+            double dfVariant1 = 0.0;
             if( padfVariant != NULL &&
                 ((GDALRasterizeInfo *)pCBData)->eBurnValueSource !=
                     GBV_UserBurnValue )
@@ -300,39 +305,44 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                 dfVariant1 = padfVariant[n + j];
             }
 
-            int nDeltaX = ABS( iX1 - iX );
-            int nDeltaY = ABS( iY1 - iY );
+            int nDeltaX = std::abs(iX1 - iX);
+            int nDeltaY = std::abs(iY1 - iY);
 
             // Step direction depends on line direction.
             const int nXStep = ( iX > iX1 ) ? -1 : 1;
             const int nYStep = ( iY > iY1 ) ? -1 : 1;
 
             // Determine the line slope.
-            if ( nDeltaX >= nDeltaY )
+            if( nDeltaX >= nDeltaY )
             {
                 const int nXError = nDeltaY << 1;
                 const int nYError = nXError - (nDeltaX << 1);
                 int nError = nXError - nDeltaX;
-                /* == 0 makes clang -fcatch-undefined-behavior -ftrapv happy, but if */
-                /* it is == 0, dfDeltaVariant is not really used, so any value is OK */
-                double dfDeltaVariant = (nDeltaX == 0) ? 0 : (dfVariant1 - dfVariant) /
-                                                           (double)nDeltaX;
-
-                while ( nDeltaX-- >= 0 )
+                // == 0 makes clang -fcatch-undefined-behavior -ftrapv happy,
+                // but if it is == 0, dfDeltaVariant is not really used, so any
+                // value is okay.
+                const double dfDeltaVariant =
+                    nDeltaX == 0
+                    ? 0.0
+                    : (dfVariant1 - dfVariant) / static_cast<double>(nDeltaX);
+
+                while( nDeltaX-- >= 0 )
                 {
-                    if ( 0 <= iX && iX < nRasterXSize
-                         && 0 <= iY && iY < nRasterYSize )
+                    if( 0 <= iX && iX < nRasterXSize
+                        && 0 <= iY && iY < nRasterYSize )
                         pfnPointFunc( pCBData, iY, iX, dfVariant );
 
                     dfVariant += dfDeltaVariant;
                     iX += nXStep;
-                    if ( nError > 0 )
+                    if( nError > 0 )
                     {
                         iY += nYStep;
                         nError += nYError;
                     }
                     else
+                    {
                         nError += nXError;
+                    }
                 }
             }
             else
@@ -340,26 +350,31 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
                 const int nXError = nDeltaX << 1;
                 const int nYError = nXError - (nDeltaY << 1);
                 int nError = nXError - nDeltaY;
-                /* == 0 makes clang -fcatch-undefined-behavior -ftrapv happy, but if */
-                /* it is == 0, dfDeltaVariant is not really used, so any value is OK */
-                double dfDeltaVariant = (nDeltaY == 0) ? 0 : (dfVariant1 - dfVariant) /
-                                                           (double)nDeltaY;
-
-                while ( nDeltaY-- >= 0 )
+                // == 0 makes clang -fcatch-undefined-behavior -ftrapv happy,
+                // but if it is == 0, dfDeltaVariant is not really used, so any
+                // value is okay.
+                double dfDeltaVariant =
+                    nDeltaY == 0
+                    ? 0.0
+                    : (dfVariant1 - dfVariant) / static_cast<double>(nDeltaY);
+
+                while( nDeltaY-- >= 0 )
                 {
-                    if ( 0 <= iX && iX < nRasterXSize
-                         && 0 <= iY && iY < nRasterYSize )
+                    if( 0 <= iX && iX < nRasterXSize
+                        && 0 <= iY && iY < nRasterYSize )
                         pfnPointFunc( pCBData, iY, iX, dfVariant );
 
                     dfVariant += dfDeltaVariant;
                     iY += nYStep;
-                    if ( nError > 0 )
+                    if( nError > 0 )
                     {
                         iX += nXStep;
                         nError += nYError;
                     }
                     else
+                    {
                         nError += nXError;
+                    }
                 }
             }
         }
@@ -380,22 +395,18 @@ void GDALdllImageLine( int nRasterXSize, int nRasterYSize,
 /************************************************************************/
 
 void
-GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
-                           int nPartCount, int *panPartSize,
-                           double *padfX, double *padfY, double *padfVariant,
-                           llPointFunc pfnPointFunc, void *pCBData )
+GDALdllImageLineAllTouched( int nRasterXSize, int nRasterYSize,
+                            int nPartCount, int *panPartSize,
+                            double *padfX, double *padfY, double *padfVariant,
+                            llPointFunc pfnPointFunc, void *pCBData )
 
 {
-    int     i, n;
-
-    if ( !nPartCount )
+    if( !nPartCount )
         return;
 
-    for ( i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
+    for( int i = 0, n = 0; i < nPartCount; n += panPartSize[i++] )
     {
-        int j;
-
-        for ( j = 1; j < panPartSize[i]; j++ )
+        for( int j = 1; j < panPartSize[i]; j++ )
         {
             double dfX = padfX[n + j - 1];
             double dfY = padfY[n + j - 1];
@@ -403,7 +414,8 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
             double dfXEnd = padfX[n + j];
             double dfYEnd = padfY[n + j];
 
-            double dfVariant = 0, dfVariantEnd = 0;
+            double dfVariant = 0.0;
+            double dfVariantEnd = 0.0;
             if( padfVariant != NULL &&
                 ((GDALRasterizeInfo *)pCBData)->eBurnValueSource !=
                     GBV_UserBurnValue )
@@ -413,18 +425,18 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
             }
 
             // Skip segments that are off the target region.
-            if( (dfY < 0 && dfYEnd < 0)
+            if( (dfY < 0.0 && dfYEnd < 0.0)
                 || (dfY > nRasterYSize && dfYEnd > nRasterYSize)
-                || (dfX < 0 && dfXEnd < 0)
+                || (dfX < 0.0 && dfXEnd < 0.0)
                 || (dfX > nRasterXSize && dfXEnd > nRasterXSize) )
                 continue;
 
             // Swap if needed so we can proceed from left2right (X increasing)
             if( dfX > dfXEnd )
             {
-                llSwapDouble( &dfX, &dfXEnd );
-                llSwapDouble( &dfY, &dfYEnd );
-                llSwapDouble( &dfVariant, &dfVariantEnd );
+                std::swap(dfX, dfXEnd);
+                std::swap(dfY, dfYEnd );
+                std::swap(dfVariant, dfVariantEnd);
             }
 
             // Special case for vertical lines.
@@ -432,28 +444,29 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
             {
                 if( dfYEnd < dfY )
                 {
-                    llSwapDouble( &dfY, &dfYEnd );
-                    llSwapDouble( &dfVariant, &dfVariantEnd );
+                    std::swap(dfY, dfYEnd );
+                    std::swap(dfVariant, dfVariantEnd);
                 }
 
-                int iX = (int) floor(dfX);
-                int iY = (int) floor(dfY);
+                const int iX = static_cast<int>(floor(dfX));
+                int iY = static_cast<int>(floor(dfY));
                 int iYEnd = (int) floor(dfYEnd);
 
                 if( iX >= nRasterXSize )
                     continue;
 
-                double dfDeltaVariant = 0;
-                if(( dfYEnd - dfY ) > 0)
-                    dfDeltaVariant = ( dfVariantEnd - dfVariant )
-                                     / ( dfYEnd - dfY );//per unit change in iY
+                double dfDeltaVariant = 0.0;
+                if( dfYEnd - dfY > 0.0 )
+                    dfDeltaVariant =
+                        ( dfVariantEnd - dfVariant ) /
+                        ( dfYEnd - dfY );  // Per unit change in iY.
 
-                // Clip to the borders of the target region
+                // Clip to the borders of the target region.
                 if( iY < 0 )
                     iY = 0;
                 if( iYEnd >= nRasterYSize )
                     iYEnd = nRasterYSize - 1;
-                dfVariant += dfDeltaVariant * ( (double)iY - dfY );
+                dfVariant += dfDeltaVariant * (static_cast<double>(iY) - dfY);
 
                 if( padfVariant == NULL )
                     for( ; iY <= iYEnd; iY++ )
@@ -462,34 +475,35 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                     for( ; iY <= iYEnd; iY++, dfVariant +=  dfDeltaVariant )
                         pfnPointFunc( pCBData, iY, iX, dfVariant );
 
-                continue; // next segment
+                continue;  // Next segment.
             }
 
-            double dfDeltaVariant = ( dfVariantEnd - dfVariant )
-                                    / ( dfXEnd - dfX );//per unit change in iX
+            const double dfDeltaVariant =
+                ( dfVariantEnd - dfVariant ) /
+                ( dfXEnd - dfX );  // Per unit change in iX.
 
-            // special case for horizontal lines
+            // Special case for horizontal lines.
             if( floor(dfY) == floor(dfYEnd) )
             {
                 if( dfXEnd < dfX )
                 {
-                    llSwapDouble( &dfX, &dfXEnd );
-                    llSwapDouble( &dfVariant, &dfVariantEnd );
+                    std::swap(dfX, dfXEnd);
+                    std::swap(dfVariant, dfVariantEnd);
                 }
 
-                int iX = (int) floor(dfX);
-                int iY = (int) floor(dfY);
+                int iX = static_cast<int>(floor(dfX));
+                const int iY = static_cast<int>(floor(dfY));
                 int iXEnd = (int) floor(dfXEnd);
 
                 if( iY >= nRasterYSize )
                     continue;
 
-                // Clip to the borders of the target region
+                // Clip to the borders of the target region.
                 if( iX < 0 )
                     iX = 0;
                 if( iXEnd >= nRasterXSize )
                     iXEnd = nRasterXSize - 1;
-                dfVariant += dfDeltaVariant * ( (double)iX - dfX );
+                dfVariant += dfDeltaVariant * (static_cast<double>(iX) - dfX);
 
                 if( padfVariant == NULL )
                     for( ; iX <= iXEnd; iX++ )
@@ -498,63 +512,71 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                     for( ; iX <= iXEnd; iX++, dfVariant +=  dfDeltaVariant )
                         pfnPointFunc( pCBData, iY, iX, dfVariant );
 
-                continue; // next segment
+                continue;  // Next segment.
             }
 
 /* -------------------------------------------------------------------- */
 /*      General case - left to right sloped.                            */
 /* -------------------------------------------------------------------- */
-            double dfSlope = (dfYEnd - dfY) / (dfXEnd - dfX);
+            const double dfSlope = (dfYEnd - dfY) / (dfXEnd - dfX);
 
-            // clip segment in X
+            // Clip segment in X.
             if( dfXEnd > nRasterXSize )
             {
-                dfYEnd -= ( dfXEnd - (double)nRasterXSize ) * dfSlope;
+                dfYEnd -=
+                    (dfXEnd - static_cast<double>(nRasterXSize)) * dfSlope;
                 dfXEnd = nRasterXSize;
             }
-            if( dfX < 0 )
+            if( dfX < 0.0 )
             {
-                dfY += (0 - dfX) * dfSlope;
+                dfY += (0.0 - dfX) * dfSlope;
                 dfVariant += dfDeltaVariant * (0.0 - dfX);
                 dfX = 0.0;
             }
 
-            // clip segment in Y
-            double dfDiffX;
+            // Clip segment in Y.
+            double dfDiffX = 0.0;
             if( dfYEnd > dfY )
             {
-                if( dfY < 0 )
+                if( dfY < 0.0 )
                 {
-                    dfX += (dfDiffX = (0 - dfY) / dfSlope);
+                    dfDiffX = (0.0 - dfY) / dfSlope;
+                    dfX += dfDiffX;
                     dfVariant += dfDeltaVariant * dfDiffX;
                     dfY = 0.0;
                 }
                 if( dfYEnd >= nRasterYSize )
                 {
-                    dfXEnd += ( dfYEnd - (double)nRasterYSize ) / dfSlope;
-                    dfYEnd = nRasterXSize;
+                    dfXEnd +=
+                        (dfYEnd - static_cast<double>(nRasterYSize)) / dfSlope;
+                    // dfYEnd is no longer used afterwards, but for
+                    // consistency it should be:
+                    // dfYEnd = nRasterXSize;
                 }
             }
             else
             {
                 if( dfY >= nRasterYSize )
                 {
-                    dfX += (dfDiffX = ((double)nRasterYSize - dfY) / dfSlope);
+                  dfDiffX = (static_cast<double>(nRasterYSize) - dfY) / dfSlope;
+                    dfX += dfDiffX;
                     dfVariant += dfDeltaVariant * dfDiffX;
                     dfY = nRasterYSize;
                 }
-                if( dfYEnd < 0 )
+                if( dfYEnd < 0.0 )
                 {
                     dfXEnd -= ( dfYEnd - 0 ) / dfSlope;
-                    dfYEnd = 0;
+                    // dfYEnd is no longer used afterwards, but for
+                    // consistency it should be:
+                    // dfYEnd = 0.0;
                 }
             }
 
-            // step from pixel to pixel.
-            while( dfX >= 0 && dfX < dfXEnd )
+            // Step from pixel to pixel.
+            while( dfX >= 0.0 && dfX < dfXEnd )
             {
-                int iX = (int) floor(dfX);
-                int iY = (int) floor(dfY);
+                const int iX = static_cast<int>(floor(dfX));
+                const int iY = static_cast<int>(floor(dfY));
 
                 // Burn in the current point.
                 // We should be able to drop the Y check because we clipped
@@ -565,8 +587,8 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                 double dfStepX = floor(dfX+1.0) - dfX;
                 double dfStepY = dfStepX * dfSlope;
 
-                // step to right pixel without changing scanline?
-                if( (int) floor(dfY + dfStepY) == iY )
+                // Step to right pixel without changing scanline?
+                if( static_cast<int>(floor(dfY + dfStepY)) == iY )
                 {
                     dfX += dfStepX;
                     dfY += dfStepY;
@@ -594,8 +616,7 @@ GDALdllImageLineAllTouched(int nRasterXSize, int nRasterYSize,
                     dfY += dfStepY;
                     dfVariant += dfDeltaVariant * dfStepX;
                 }
-            } // next step along segment.
-
-        } // next segment
-    } // next part
+            }  // Next step along segment.
+        }  // Next segment.
+    }  // Next part.
 }
diff --git a/alg/makefile.vc b/alg/makefile.vc
index 1a240f8..8f82a1d 100644
--- a/alg/makefile.vc
+++ b/alg/makefile.vc
@@ -5,17 +5,13 @@
 
 GDAL_ROOT	=	..
 
-EXTRAFLAGS =	-I../ogr/ogrsf_frmts $(GEOS_CFLAGS)
+EXTRAFLAGS =	-I../frmts/vrt -I../ogr/ogrsf_frmts $(GEOS_CFLAGS) $(PROJ_FLAGS) $(PROJ_INCLUDE)
 
 !INCLUDE ..\nmake.opt
 
-!IFDEF INCLUDE_OGR_FRMTS
-EXTRAFLAGS = $(EXTRAFLAGS) -DOGR_ENABLED
-!ENDIF
-
 !IFDEF QHULL_SETTING
 !IF "$(QHULL_SETTING)" == "INTERNAL"
-EXTRAFLAGS = $(EXTRAFLAGS) -DINTERNAL_QHULL -Ilibqhull
+EXTRAFLAGS = $(EXTRAFLAGS) -DINTERNAL_QHULL
 !ELSE
 !IF "$(QHULL_SETTING)" == "EXTERNAL"
 EXTRAFLAGS = $(EXTRAFLAGS) -DEXTERNAL_QHULL $(QHULL_INC)
@@ -31,7 +27,8 @@ OBJ =	gdaldither.obj gdalmediancut.obj gdal_crs.obj gdaltransformer.obj \
 	gdalsievefilter.obj gdalrasterpolygonenumerator.obj polygonize.obj \
 	contour.obj \
 	gdal_octave.obj gdal_simplesurf.obj gdalmatching.obj \
-	gdaltransformgeolocs.obj delaunay.obj gdalpansharpen.obj
+	gdaltransformgeolocs.obj delaunay.obj gdalpansharpen.obj \
+	gdalapplyverticalshiftgrid.obj
 
 !IF "$(SSEFLAGS)" == "/DHAVE_SSE_AT_COMPILE_TIME"
 SSE_OBJ = gdalgridsse.obj
diff --git a/alg/polygonize.cpp b/alg/polygonize.cpp
index 500f40b..aa99210 100644
--- a/alg/polygonize.cpp
+++ b/alg/polygonize.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: polygonize.cpp 33757 2016-03-20 20:22:33Z goatbar $
  * Project:  GDAL
  * Purpose:  Raster to Polygon Converter
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -27,17 +26,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_alg.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <cstdlib>
+#include <string.h>
+
+#include <algorithm>
+#include <memory>
+#include <vector>
+
 #include "gdal_alg_priv.h"
+#include "gdal.h"
+#include "ogr_api.h"
+#include "ogr_core.h"
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
-#include <vector>
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: polygonize.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+CPL_CVSID("$Id: polygonize.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
 /*                               RPolygon                               */
-/*									*/
+/*                                                                      */
 /*      This is a helper class to hold polygons while they are being    */
 /*      formed in memory, and to provide services to coalesce a much    */
 /*      of edge sections into complete rings.                           */
@@ -46,15 +62,16 @@ CPL_CVSID("$Id: polygonize.cpp 33757 2016-03-20 20:22:33Z goatbar $");
 
 class RPolygon {
 public:
-    RPolygon(  double dfValue ) { dfPolyValue = dfValue; nLastLineUpdated = -1; }
+    explicit RPolygon( double dfValue )
+        { dfPolyValue = dfValue; nLastLineUpdated = -1; }
 
-    double              dfPolyValue;
+    double           dfPolyValue;
     int              nLastLineUpdated;
 
     std::vector< std::vector<int> > aanXY;
 
     void             AddSegment( int x1, int y1, int x2, int y2 );
-    void             Dump();
+    void             Dump() const;
     void             Coalesce();
     void             Merge( int iBaseString, int iSrcString, int iDirection );
 };
@@ -62,22 +79,19 @@ public:
 /************************************************************************/
 /*                                Dump()                                */
 /************************************************************************/
-void RPolygon::Dump()
+void RPolygon::Dump() const
 {
-    size_t iString;
-
-    printf( "RPolygon: Value=%g, LastLineUpdated=%d\n",
+    /*ok*/printf( "RPolygon: Value=%g, LastLineUpdated=%d\n",
             dfPolyValue, nLastLineUpdated );
 
-    for( iString = 0; iString < aanXY.size(); iString++ )
+    for( size_t iString = 0; iString < aanXY.size(); iString++ )
     {
-        std::vector<int> &anString = aanXY[iString];
-        size_t iVert;
+        const std::vector<int> &anString = aanXY[iString];
 
-        printf( "  String %d:\n", (int) iString );
-        for( iVert = 0; iVert < anString.size(); iVert += 2 )
+        /*ok*/printf( "  String %d:\n", (int) iString );
+        for( size_t iVert = 0; iVert < anString.size(); iVert += 2 )
         {
-            printf( "    (%d,%d)\n", anString[iVert], anString[iVert+1] );
+            /*ok*/printf( "    (%d,%d)\n", anString[iVert], anString[iVert+1] );
         }
     }
 }
@@ -89,16 +103,14 @@ void RPolygon::Dump()
 void RPolygon::Coalesce()
 
 {
-    size_t iBaseString;
-
 /* -------------------------------------------------------------------- */
 /*      Iterate over loops starting from the first, trying to merge     */
 /*      other segments into them.                                       */
 /* -------------------------------------------------------------------- */
-    for( iBaseString = 0; iBaseString < aanXY.size(); iBaseString++ )
+    for( size_t iBaseString = 0; iBaseString < aanXY.size(); iBaseString++ )
     {
         std::vector<int> &anBase = aanXY[iBaseString];
-        int bMergeHappened = TRUE;
+        bool bMergeHappened = true;
 
 /* -------------------------------------------------------------------- */
 /*      Keep trying to merge the following strings into our target      */
@@ -107,41 +119,41 @@ void RPolygon::Coalesce()
 /* -------------------------------------------------------------------- */
         while( bMergeHappened )
         {
-            size_t iString;
-
-            bMergeHappened = FALSE;
+            bMergeHappened = false;
 
 /* -------------------------------------------------------------------- */
 /*      Loop over the following strings, trying to find one we can      */
 /*      merge onto the end of our base string.                          */
 /* -------------------------------------------------------------------- */
-            for( iString = iBaseString+1;
+            for( size_t iString = iBaseString+1;
                  iString < aanXY.size();
                  iString++ )
             {
                 std::vector<int> &anString = aanXY[iString];
 
-                if( anBase[anBase.size()-2] == anString[0]
-                    && anBase[anBase.size()-1] == anString[1] )
+                if( anBase[anBase.size() - 2] == anString[0]
+                    && anBase.back() == anString[1] )
                 {
-                    Merge( static_cast<int>(iBaseString), static_cast<int>(iString), 1 );
-                    bMergeHappened = TRUE;
+                    Merge( static_cast<int>(iBaseString),
+                           static_cast<int>(iString), 1 );
+                    bMergeHappened = true;
                 }
-                else if( anBase[anBase.size()-2] == anString[anString.size()-2]
-                         && anBase[anBase.size()-1] == anString[anString.size()-1] )
+                else if( anBase[anBase.size() - 2] ==
+                             anString[anString.size() - 2] &&
+                         anBase.back() ==
+                             anString.back() )
                 {
-                    Merge( static_cast<int>(iBaseString), static_cast<int>(iString), -1 );
-                    bMergeHappened = TRUE;
+                    Merge( static_cast<int>(iBaseString),
+                           static_cast<int>(iString), -1 );
+                    bMergeHappened = true;
                 }
             }
         }
 
-        /* At this point our loop *should* be closed! */
-
+        // At this point our loop *should* be closed!
         CPLAssert( anBase[0] == anBase[anBase.size()-2]
-                   && anBase[1] == anBase[anBase.size()-1] );
+                   && anBase[1] == anBase.back() );
     }
-
 }
 
 /************************************************************************/
@@ -153,30 +165,29 @@ void RPolygon::Merge( int iBaseString, int iSrcString, int iDirection )
 {
     std::vector<int> &anBase = aanXY[iBaseString];
     std::vector<int> &anString = aanXY[iSrcString];
-    int iStart, iEnd, i;
+    int iStart = 1;
+    int iEnd = -1;
 
     if( iDirection == 1 )
     {
-        iStart = 1;
         iEnd = static_cast<int>(anString.size()) / 2;
     }
     else
     {
         iStart = static_cast<int>(anString.size()) / 2 - 2;
-        iEnd = -1;
     }
 
-    for( i = iStart; i != iEnd; i += iDirection )
+    for( int i = iStart; i != iEnd; i += iDirection )
     {
         anBase.push_back( anString[i*2+0] );
         anBase.push_back( anString[i*2+1] );
     }
 
-    if( iSrcString < ((int) aanXY.size())-1 )
+    if( iSrcString < static_cast<int>(aanXY.size()) - 1 )
         aanXY[iSrcString] = aanXY[aanXY.size()-1];
 
-    size_t nSize = aanXY.size();
-    aanXY.resize(nSize-1);
+    const size_t nSize = aanXY.size();
+    aanXY.resize(nSize - 1);
 }
 
 /************************************************************************/
@@ -186,46 +197,38 @@ void RPolygon::Merge( int iBaseString, int iSrcString, int iDirection )
 void RPolygon::AddSegment( int x1, int y1, int x2, int y2 )
 
 {
-    nLastLineUpdated = MAX(y1, y2);
+    nLastLineUpdated = std::max(y1, y2);
 
 /* -------------------------------------------------------------------- */
 /*      Is there an existing string ending with this?                   */
 /* -------------------------------------------------------------------- */
-    size_t iString;
-
-    for( iString = 0; iString < aanXY.size(); iString++ )
+    for( size_t iString = 0; iString < aanXY.size(); iString++ )
     {
         std::vector<int> &anString = aanXY[iString];
-        size_t nSSize = anString.size();
+        const size_t nSSize = anString.size();
 
         if( anString[nSSize-2] == x1
             && anString[nSSize-1] == y1 )
         {
-            int nTemp;
-
-            nTemp = x2;
-            x2 = x1;
-            x1 = nTemp;
-
-            nTemp = y2;
-            y2 = y1;
-            y1 = nTemp;
+            std::swap(x1, x2);
+            std::swap(y1, y2);
         }
 
-        if( anString[nSSize-2] == x2
-            && anString[nSSize-1] == y2 )
+        if( anString[nSSize - 2] == x2 &&
+            anString[nSSize - 1] == y2 )
         {
             // We are going to add a segment, but should we just extend
             // an existing segment already going in the right direction?
 
-            int nLastLen = MAX(ABS(anString[nSSize-4]-anString[nSSize-2]),
-                               ABS(anString[nSSize-3]-anString[nSSize-1]));
+            const int nLastLen =
+                std::max(std::abs(anString[nSSize - 4] - anString[nSSize - 2]),
+                         std::abs(anString[nSSize - 3] - anString[nSSize - 1]));
 
             if( nSSize >= 4
-                && (anString[nSSize-4] - anString[nSSize-2]
-                    == (anString[nSSize-2] - x1)*nLastLen)
-                && (anString[nSSize-3] - anString[nSSize-1]
-                    == (anString[nSSize-1] - y1)*nLastLen) )
+                && (anString[nSSize - 4] - anString[nSSize - 2]
+                    == (anString[nSSize - 2] - x1) * nLastLen)
+                && (anString[nSSize - 3] - anString[nSSize - 1]
+                    == (anString[nSSize - 1] - y1) * nLastLen) )
             {
                 anString.pop_back();
                 anString.pop_back();
@@ -240,7 +243,7 @@ void RPolygon::AddSegment( int x1, int y1, int x2, int y2 )
 /* -------------------------------------------------------------------- */
 /*      Create a new string.                                            */
 /* -------------------------------------------------------------------- */
-    size_t nSize = aanXY.size();
+    const size_t nSize = aanXY.size();
     aanXY.resize(nSize + 1);
     std::vector<int> &anString = aanXY[nSize];
 
@@ -273,18 +276,19 @@ static void AddEdges( GInt32 *panThisLineId, GInt32 *panLastLineId,
                       RPolygon **papoPoly, int iX, int iY )
 
 {
+    // TODO(schwehr): Simplify these three vars.
     int nThisId = panThisLineId[iX];
-    int nRightId = panThisLineId[iX+1];
-    int nPreviousId = panLastLineId[iX];
-    int iXReal = iX - 1;
-
     if( nThisId != -1 )
         nThisId = panPolyIdMap[nThisId];
+    int nRightId = panThisLineId[iX+1];
     if( nRightId != -1 )
         nRightId = panPolyIdMap[nRightId];
+    int nPreviousId = panLastLineId[iX];
     if( nPreviousId != -1 )
         nPreviousId = panPolyIdMap[nPreviousId];
 
+    const int iXReal = iX - 1;
+
     if( nThisId != nPreviousId )
     {
         if( nThisId != -1 )
@@ -332,9 +336,6 @@ EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
                     RPolygon *poRPoly, double *padfGeoTransform )
 
 {
-    OGRFeatureH hFeat;
-    OGRGeometryH hPolygon;
-
 /* -------------------------------------------------------------------- */
 /*      Turn bits of lines into coherent rings.                         */
 /* -------------------------------------------------------------------- */
@@ -343,31 +344,28 @@ EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
 /* -------------------------------------------------------------------- */
 /*      Create the polygon geometry.                                    */
 /* -------------------------------------------------------------------- */
-    size_t iString;
-
-    hPolygon = OGR_G_CreateGeometry( wkbPolygon );
+    OGRGeometryH hPolygon = OGR_G_CreateGeometry( wkbPolygon );
 
-    for( iString = 0; iString < poRPoly->aanXY.size(); iString++ )
+    for( size_t iString = 0; iString < poRPoly->aanXY.size(); iString++ )
     {
         std::vector<int> &anString = poRPoly->aanXY[iString];
         OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
 
-        int iVert;
-
-        // we go last to first to ensure the linestring is allocated to
+        // We go last to first to ensure the linestring is allocated to
         // the proper size on the first try.
-        for( iVert = static_cast<int>(anString.size())/2 - 1; iVert >= 0; iVert-- )
+        for( int iVert = static_cast<int>(anString.size()) / 2 - 1;
+             iVert >= 0;
+             iVert-- )
         {
-            double dfX, dfY;
-            int    nPixelX, nPixelY;
-
-            nPixelX = anString[iVert*2];
-            nPixelY = anString[iVert*2+1];
+            const int nPixelX = anString[iVert*2];
+            const int nPixelY = anString[iVert*2+1];
 
-            dfX = padfGeoTransform[0]
+            const double dfX =
+                padfGeoTransform[0]
                 + nPixelX * padfGeoTransform[1]
                 + nPixelY * padfGeoTransform[2];
-            dfY = padfGeoTransform[3]
+            const double dfY =
+                padfGeoTransform[3]
                 + nPixelX * padfGeoTransform[4]
                 + nPixelY * padfGeoTransform[5];
 
@@ -380,7 +378,7 @@ EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
 /* -------------------------------------------------------------------- */
 /*      Create the feature object.                                      */
 /* -------------------------------------------------------------------- */
-    hFeat = OGR_F_Create( OGR_L_GetLayerDefn( hOutLayer ) );
+    OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn( hOutLayer ) );
 
     OGR_F_SetGeometryDirectly( hFeat, hPolygon );
 
@@ -409,25 +407,24 @@ EmitPolygonToLayer( OGRLayerH hOutLayer, int iPixValField,
 
 template<class DataType>
 static CPLErr
-GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine, int iY, int nXSize,
+GPMaskImageData( GDALRasterBandH hMaskBand, GByte* pabyMaskLine,
+                 int iY, int nXSize,
                  DataType *panImageLine )
 
 {
-    CPLErr eErr;
+    const CPLErr eErr =
+        GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
+                      pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
+    if( eErr != CE_None )
+        return eErr;
 
-    eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
-                         pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
-    if( eErr == CE_None )
+    for( int i = 0; i < nXSize; i++ )
     {
-        int i;
-        for( i = 0; i < nXSize; i++ )
-        {
-            if( pabyMaskLine[i] == 0 )
-                panImageLine[i] = GP_NODATA_MARKER;
-        }
+        if( pabyMaskLine[i] == 0 )
+            panImageLine[i] = GP_NODATA_MARKER;
     }
 
-    return eErr;
+    return CE_None;
 }
 
 /************************************************************************/
@@ -451,33 +448,43 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
-    int nConnectedness = CSLFetchNameValue( papszOptions, "8CONNECTED" ) ? 8 : 4;
+    const int nConnectedness =
+        CSLFetchNameValue( papszOptions, "8CONNECTED" ) ? 8 : 4;
 
 /* -------------------------------------------------------------------- */
 /*      Confirm our output layer will support feature creation.         */
 /* -------------------------------------------------------------------- */
     if( !OGR_L_TestCapability( hOutLayer, OLCSequentialWrite ) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Output feature layer does not appear to support creation\n"
-                  "of features in GDALPolygonize()." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Output feature layer does not appear to support creation "
+                 "of features in GDALPolygonize().");
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Allocate working buffers.                                       */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr = CE_None;
-    int nXSize = GDALGetRasterBandXSize( hSrcBand );
-    int nYSize = GDALGetRasterBandYSize( hSrcBand );
-    DataType *panLastLineVal = (DataType *) VSI_MALLOC2_VERBOSE(sizeof(DataType),nXSize + 2);
-    DataType *panThisLineVal = (DataType *) VSI_MALLOC2_VERBOSE(sizeof(DataType),nXSize + 2);
-    GInt32 *panLastLineId =  (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32),nXSize + 2);
-    GInt32 *panThisLineId =  (GInt32 *) VSI_MALLOC2_VERBOSE(sizeof(GInt32),nXSize + 2);
-    GByte *pabyMaskLine = (hMaskBand != NULL) ? (GByte *) VSI_MALLOC_VERBOSE(nXSize) : NULL;
-    if (panLastLineVal == NULL || panThisLineVal == NULL ||
+    const int nXSize = GDALGetRasterBandXSize( hSrcBand );
+    const int nYSize = GDALGetRasterBandYSize( hSrcBand );
+
+    DataType *panLastLineVal = static_cast<DataType *>(
+        VSI_MALLOC2_VERBOSE(sizeof(DataType), nXSize + 2));
+    DataType *panThisLineVal = static_cast<DataType *>(
+        VSI_MALLOC2_VERBOSE(sizeof(DataType), nXSize + 2));
+    GInt32 *panLastLineId = static_cast<GInt32 *>(
+        VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize + 2));
+    GInt32 *panThisLineId = static_cast<GInt32 *>(
+        VSI_MALLOC2_VERBOSE(sizeof(GInt32), nXSize + 2));
+
+    GByte *pabyMaskLine =
+        hMaskBand != NULL
+        ? static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize))
+        : NULL;
+
+    if( panLastLineVal == NULL || panThisLineVal == NULL ||
         panLastLineId == NULL || panThisLineId == NULL ||
-        (hMaskBand != NULL && pabyMaskLine == NULL))
+        (hMaskBand != NULL && pabyMaskLine == NULL) )
     {
         CPLFree( panThisLineId );
         CPLFree( panLastLineId );
@@ -491,21 +498,37 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
 /*      Get the geotransform, if there is one, so we can convert the    */
 /*      vectors into georeferenced coordinates.                         */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hSrcDS = GDALGetBandDataset( hSrcBand );
     double adfGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
 
-    if( hSrcDS )
-        GDALGetGeoTransform( hSrcDS, adfGeoTransform );
+    const char* pszDatasetForGeoRef = CSLFetchNameValue(papszOptions,
+                                                        "DATASET_FOR_GEOREF");
+    if( pszDatasetForGeoRef )
+    {
+        GDALDatasetH hSrcDS = GDALOpen(pszDatasetForGeoRef, GA_ReadOnly);
+        if( hSrcDS )
+        {
+            GDALGetGeoTransform( hSrcDS, adfGeoTransform );
+            GDALClose(hSrcDS);
+        }
+    }
+    else
+    {
+        GDALDatasetH hSrcDS = GDALGetBandDataset( hSrcBand );
+        if( hSrcDS )
+            GDALGetGeoTransform( hSrcDS, adfGeoTransform );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      The first pass over the raster is only used to build up the     */
 /*      polygon id map so we will know in advance what polygons are     */
 /*      what on the second pass.                                        */
 /* -------------------------------------------------------------------- */
-    int iY;
-    GDALRasterPolygonEnumeratorT<DataType, EqualityTest> oFirstEnum(nConnectedness);
+    GDALRasterPolygonEnumeratorT<DataType,
+                                 EqualityTest> oFirstEnum(nConnectedness);
 
-    for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
+    CPLErr eErr = CE_None;
+
+    for( int iY = 0; eErr == CE_None && iY < nYSize; iY++ )
     {
         eErr = GDALRasterIO(
             hSrcBand,
@@ -513,7 +536,8 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
             panThisLineVal, nXSize, 1, eDT, 0, 0 );
 
         if( eErr == CE_None && hMaskBand != NULL )
-            eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
+            eErr = GPMaskImageData(hMaskBand, pabyMaskLine, iY, nXSize,
+                                   panThisLineVal);
 
         if( iY == 0 )
             oFirstEnum.ProcessLine(
@@ -524,20 +548,15 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
                 panLastLineId,  panThisLineId,
                 nXSize );
 
-        // swap lines
-        DataType *panTmpVal = panLastLineVal;
-        panLastLineVal = panThisLineVal;
-        panThisLineVal = panTmpVal;
-
-        GInt32* panTmp = panThisLineId;
-        panThisLineId = panLastLineId;
-        panLastLineId = panTmp;
+        // Swap lines.
+        std::swap(panLastLineVal, panThisLineVal);
+        std::swap(panLastLineId, panThisLineId);
 
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
         if( eErr == CE_None
-            && !pfnProgress( 0.10 * ((iY+1) / (double) nYSize),
+            && !pfnProgress( 0.10 * ((iY+1) / static_cast<double>(nYSize)),
                              "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -557,27 +576,26 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
 /*      previous line, and past the beginning and end of the            */
 /*      scanlines.                                                      */
 /* -------------------------------------------------------------------- */
-    int iX;
-
     panThisLineId[0] = -1;
     panThisLineId[nXSize+1] = -1;
 
-    for( iX = 0; iX < nXSize+2; iX++ )
+    for( int iX = 0; iX < nXSize+2; iX++ )
         panLastLineId[iX] = -1;
 
 /* -------------------------------------------------------------------- */
 /*      We will use a new enumerator for the second pass primarily      */
 /*      so we can preserve the first pass map.                          */
 /* -------------------------------------------------------------------- */
-    GDALRasterPolygonEnumeratorT<DataType, EqualityTest> oSecondEnum(nConnectedness);
-    RPolygon **papoPoly = (RPolygon **)
-        CPLCalloc(sizeof(RPolygon*),oFirstEnum.nNextPolygonId);
+    GDALRasterPolygonEnumeratorT<DataType,
+                                 EqualityTest> oSecondEnum(nConnectedness);
+    RPolygon **papoPoly = static_cast<RPolygon **>(
+        CPLCalloc(sizeof(RPolygon*), oFirstEnum.nNextPolygonId));
 
 /* ==================================================================== */
 /*      Second pass during which we will actually collect polygon       */
 /*      edges as geometries.                                            */
 /* ==================================================================== */
-    for( iY = 0; eErr == CE_None && iY < nYSize+1; iY++ )
+    for( int iY = 0; eErr == CE_None && iY < nYSize+1; iY++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Read the image data.                                            */
@@ -588,7 +606,8 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
                                  panThisLineVal, nXSize, 1, eDT, 0, 0 );
 
             if( eErr == CE_None && hMaskBand != NULL )
-                eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize, panThisLineVal );
+                eErr = GPMaskImageData( hMaskBand, pabyMaskLine, iY, nXSize,
+                                        panThisLineVal );
         }
 
         if( eErr != CE_None )
@@ -600,23 +619,27 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
         if( iY == nYSize )
         {
-            for( iX = 0; iX < nXSize+2; iX++ )
+            for( int iX = 0; iX < nXSize+2; iX++ )
                 panThisLineId[iX] = -1;
         }
         else if( iY == 0 )
+        {
             oSecondEnum.ProcessLine(
                 NULL, panThisLineVal, NULL, panThisLineId+1, nXSize );
+        }
         else
+        {
             oSecondEnum.ProcessLine(
                 panLastLineVal, panThisLineVal,
                 panLastLineId+1,  panThisLineId+1,
                 nXSize );
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Add polygon edges to our polygon list for the pixel             */
 /*      boundaries within and above this line.                          */
 /* -------------------------------------------------------------------- */
-        for( iX = 0; iX < nXSize+1; iX++ )
+        for( int iX = 0; iX < nXSize+1; iX++ )
         {
             AddEdges( panThisLineId, panLastLineId,
                       oFirstEnum.panPolyIdMap, oFirstEnum.panPolyValue,
@@ -630,7 +653,7 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
         if( iY % 8 == 7 )
         {
-            for( iX = 0;
+            for( int iX = 0;
                  eErr == CE_None && iX < oSecondEnum.nNextPolygonId;
                  iX++ )
             {
@@ -650,19 +673,15 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
 /*      Swap pixel value, and polygon id lines to be ready for the      */
 /*      next line.                                                      */
 /* -------------------------------------------------------------------- */
-        DataType *panTmpVal = panLastLineVal;
-        panLastLineVal = panThisLineVal;
-        panThisLineVal = panTmpVal;
-
-        GInt32* panTmp = panThisLineId;
-        panThisLineId = panLastLineId;
-        panLastLineId = panTmp;
+        std::swap(panLastLineVal, panThisLineVal);
+        std::swap(panLastLineId, panThisLineId);
 
 /* -------------------------------------------------------------------- */
 /*      Report progress, and support interrupts.                        */
 /* -------------------------------------------------------------------- */
         if( eErr == CE_None
-            && !pfnProgress( 0.10 + 0.90 * ((iY+1) / (double) nYSize),
+            && !pfnProgress( 0.10 + 0.90 * ((iY + 1) /
+                                            static_cast<double>(nYSize)),
                              "", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -673,13 +692,12 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
 /*      Make a cleanup pass for all unflushed polygons.                 */
 /* -------------------------------------------------------------------- */
-    for( iX = 0; eErr == CE_None && iX < oSecondEnum.nNextPolygonId; iX++ )
+    for( int iX = 0; eErr == CE_None && iX < oSecondEnum.nNextPolygonId; iX++ )
     {
         if( papoPoly[iX] )
         {
-            eErr =
-                EmitPolygonToLayer( hOutLayer, iPixValField,
-                                    papoPoly[iX], adfGeoTransform );
+            eErr = EmitPolygonToLayer( hOutLayer, iPixValField,
+                                       papoPoly[iX], adfGeoTransform );
 
             delete papoPoly[iX];
             papoPoly[iX] = NULL;
@@ -699,61 +717,54 @@ GDALPolygonizeT( GDALRasterBandH hSrcBand,
     return eErr;
 }
 
-
 /******************************************************************************/
 /*                          GDALFloatEquals()                                 */
 /* Code from:                                                                 */
 /* http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm  */
 /******************************************************************************/
-GBool GDALFloatEquals(float A, float B)
+GBool GDALFloatEquals( float A, float B )
 {
-    /**
-     * This function will allow maxUlps-1 floats between A and B.
-     */
+    // This function will allow maxUlps-1 floats between A and B.
     const int maxUlps = MAX_ULPS;
-    int aInt, bInt;
 
-    /**
-     * Make sure maxUlps is non-negative and small enough that the default NAN
-     * won't compare as equal to anything.
-     */
+    // Make sure maxUlps is non-negative and small enough that the default NAN
+    // won't compare as equal to anything.
 #if MAX_ULPS <= 0 || MAX_ULPS >= 4 * 1024 * 1024
 #error "Invalid MAX_ULPS"
 #endif
 
-    /**
-     * This assignation could violate strict aliasing. It causes a warning with
-     * gcc -O2. Use of memcpy preferred. Credits for Even Rouault. Further info
-     * at http://trac.osgeo.org/gdal/ticket/4005#comment:6
-     */
-    //int aInt = *(int*)&A;
+    // This assignation could violate strict aliasing. It causes a warning with
+    // gcc -O2. Use of memcpy preferred. Credits for Even Rouault. Further info
+    // at http://trac.osgeo.org/gdal/ticket/4005#comment:6
+    int aInt = 0;
     memcpy(&aInt, &A, 4);
 
-    /**
-     * Make aInt lexicographically ordered as a twos-complement int
-     */
-    if (aInt < 0)
+    // Make aInt lexicographically ordered as a twos-complement int.
+    if( aInt < 0 )
         aInt = 0x80000000 - aInt;
-    /**
-     * Make bInt lexicographically ordered as a twos-complement int
-     */
-    //int bInt = *(int*)&B;
+
+    // Make bInt lexicographically ordered as a twos-complement int.
+    int bInt = 0;
     memcpy(&bInt, &B, 4);
 
-    if (bInt < 0)
+    if( bInt < 0 )
         bInt = 0x80000000 - bInt;
 #ifdef COMPAT_WITH_ICC_CONVERSION_CHECK
-    int intDiff = abs((int) (((GUIntBig)((GIntBig)aInt - (GIntBig)bInt)) & 0xFFFFFFFFU) );
+    const int intDiff =
+        abs(static_cast<int>(static_cast<GUIntBig>(
+            static_cast<GIntBig>(aInt) - static_cast<GIntBig>(bInt))
+            & 0xFFFFFFFFU));
 #else
-    /* to make -ftrapv happy we compute the diff on larger type and cast down later */
-    int intDiff = abs((int)((GIntBig)aInt - (GIntBig)bInt));
+    // To make -ftrapv happy we compute the diff on larger type and
+    // cast down later.
+    const int intDiff = abs(static_cast<int>(
+        static_cast<GIntBig>(aInt) - static_cast<GIntBig>(bInt)));
 #endif
-    if (intDiff <= maxUlps)
+    if( intDiff <= maxUlps )
         return true;
     return false;
 }
 
-
 /************************************************************************/
 /*                           GDALPolygonize()                           */
 /************************************************************************/
@@ -831,7 +842,6 @@ GDALPolygonize( GDALRasterBandH hSrcBand,
                                                     GDT_Int32);
 }
 
-
 /************************************************************************/
 /*                           GDALFPolygonize()                           */
 /************************************************************************/
diff --git a/alg/rasterfill.cpp b/alg/rasterfill.cpp
index c657103..6c1dbc8 100644
--- a/alg/rasterfill.cpp
+++ b/alg/rasterfill.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rasterfill.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Interpolate in nodata areas.
@@ -29,11 +28,24 @@
  * DEALINGS IN THE SOFTWARE.
  ***************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_alg.h"
+
+#include <cmath>
+#include <cstring>
+
+#include <algorithm>
+#include <string>
+#include <utility>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 
-CPL_CVSID("$Id: rasterfill.cpp 33715 2016-03-13 08:52:06Z goatbar $");
+CPL_CVSID("$Id: rasterfill.cpp 36726 2016-12-06 19:01:12Z goatbar $");
 
 /************************************************************************/
 /*                           GDALFilterLine()                           */
@@ -50,9 +62,7 @@ GDALFilterLine( float *pafLastLine, float *pafThisLine, float *pafNextLine,
                 GByte *pabyThisFMask, int nXSize )
 
 {
-    int iX;
-
-    for( iX = 0; iX < nXSize; iX++ )
+    for( int iX = 0; iX < nXSize; iX++ )
     {
         if( !pabyThisFMask[iX] )
         {
@@ -65,7 +75,7 @@ GDALFilterLine( float *pafLastLine, float *pafThisLine, float *pafNextLine,
         double dfValSum = 0.0;
         double dfWeightSum = 0.0;
 
-        // Previous line
+        // Previous line.
         if( pafLastLine != NULL )
         {
             if( iX > 0 && pabyLastTMask[iX-1] )
@@ -85,7 +95,7 @@ GDALFilterLine( float *pafLastLine, float *pafThisLine, float *pafNextLine,
             }
         }
 
-        // Current Line
+        // Current Line.
         if( iX > 0 && pabyThisTMask[iX-1] )
         {
             dfValSum += pafThisLine[iX-1];
@@ -102,7 +112,7 @@ GDALFilterLine( float *pafLastLine, float *pafThisLine, float *pafNextLine,
             dfWeightSum += 1.0;
         }
 
-        // Next line
+        // Next line.
         if( pafNextLine != NULL )
         {
             if( iX > 0 && pabyNextTMask[iX-1] )
@@ -151,17 +161,8 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
                  void * pProgressArg )
 
 {
-    float *paf3PassLineBuf;
-    GByte *pabyTMaskBuf;
-    GByte *pabyFMaskBuf;
-    float *pafThisPass, *pafLastPass, *pafSLastPass;
-
-    int   nBufLines = nIterations + 2;
-    int   iPassCounter = 0;
-    int   nNewLine; // the line being loaded this time (zero based scanline)
     int   nXSize = GDALGetRasterBandXSize( hTargetBand );
     int   nYSize = GDALGetRasterBandYSize( hTargetBand );
-    CPLErr eErr = CE_None;
 
 /* -------------------------------------------------------------------- */
 /*      Report starting progress value.                                 */
@@ -175,20 +176,34 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
 /*      Allocate rotating buffers.                                      */
 /* -------------------------------------------------------------------- */
-    pabyTMaskBuf = (GByte *) VSI_MALLOC2_VERBOSE(nXSize, nBufLines);
-    pabyFMaskBuf = (GByte *) VSI_MALLOC2_VERBOSE(nXSize, nBufLines);
+    const int nBufLines = nIterations + 2;
 
-    paf3PassLineBuf = (float *) VSI_MALLOC3_VERBOSE(nXSize, nBufLines, 3 * sizeof(float));
-    if (pabyTMaskBuf == NULL || pabyFMaskBuf == NULL || paf3PassLineBuf == NULL)
+    GByte *pabyTMaskBuf =
+        static_cast<GByte *>(VSI_MALLOC2_VERBOSE(nXSize, nBufLines));
+    GByte *pabyFMaskBuf =
+        static_cast<GByte *>(VSI_MALLOC2_VERBOSE(nXSize, nBufLines));
+
+    float *paf3PassLineBuf = static_cast<float *>(
+        VSI_MALLOC3_VERBOSE(nXSize, nBufLines, 3 * sizeof(float)));
+    if( pabyTMaskBuf == NULL || pabyFMaskBuf == NULL ||
+        paf3PassLineBuf == NULL )
     {
-        eErr = CE_Failure;
-        goto end;
+        CPLFree( pabyTMaskBuf );
+        CPLFree( pabyFMaskBuf );
+        CPLFree( paf3PassLineBuf );
+
+        return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Process rotating buffers.                                       */
 /* -------------------------------------------------------------------- */
-    for( nNewLine = 0;
+
+    CPLErr eErr = CE_None;
+
+    int iPassCounter = 0;
+
+    for( int nNewLine = 0;  // Line being loaded (zero based scanline).
          eErr == CE_None && nNewLine < nYSize+nIterations;
          nNewLine++ )
     {
@@ -197,17 +212,17 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
         iPassCounter = (iPassCounter + 1) % 3;
 
-        pafSLastPass = paf3PassLineBuf
-            + ((iPassCounter+0)%3) * nXSize*nBufLines;
-        pafLastPass = paf3PassLineBuf
-            + ((iPassCounter+1)%3) * nXSize*nBufLines;
-        pafThisPass = paf3PassLineBuf
-            + ((iPassCounter+2)%3) * nXSize*nBufLines;
+        float * const pafSLastPass =
+            paf3PassLineBuf + ((iPassCounter + 0) % 3) * nXSize * nBufLines;
+        float * const pafLastPass =
+            paf3PassLineBuf + ((iPassCounter + 1) % 3) * nXSize * nBufLines;
+        float * const pafThisPass =
+            paf3PassLineBuf + ((iPassCounter + 2) % 3) * nXSize * nBufLines;
 
 /* -------------------------------------------------------------------- */
 /*      Where does the new line go in the rotating buffer?              */
 /* -------------------------------------------------------------------- */
-        int iBufOffset = nNewLine % nBufLines;
+        const int iBufOffset = nNewLine % nBufLines;
 
 /* -------------------------------------------------------------------- */
 /*      Read the new data line if it is't off the bottom of the         */
@@ -247,26 +262,22 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /*      Loop over the loaded data, applying the filter to all loaded    */
 /*      lines with neighbours.                                          */
 /* -------------------------------------------------------------------- */
-        int iFLine;
-
-        for( iFLine = nNewLine-1;
+        for( int iFLine = nNewLine-1;
              eErr == CE_None && iFLine >= nNewLine-nIterations;
              iFLine-- )
         {
-            int iLastOffset, iThisOffset, iNextOffset;
+            const int iLastOffset = (iFLine-1) % nBufLines;
+            const int iThisOffset = (iFLine  ) % nBufLines;
+            const int iNextOffset = (iFLine+1) % nBufLines;
 
-            iLastOffset = (iFLine-1) % nBufLines;
-            iThisOffset = (iFLine  ) % nBufLines;
-            iNextOffset = (iFLine+1) % nBufLines;
-
-            // default to preserving the old value.
+            // Default to preserving the old value.
             if( iFLine >= 0 )
                 memcpy( pafThisPass + iThisOffset * nXSize,
                         pafLastPass + iThisOffset * nXSize,
                         sizeof(float) * nXSize );
 
-            // currently this skips the first and last line.  Eventually
-            // we will enable these too.  TODO
+            // TODO: Enable first and last line.
+            // Skip the first and last line.
             if( iFLine < 1 || iFLine >= nYSize-1 )
             {
                 continue;
@@ -288,25 +299,26 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /*      Write out the top data line that will be rolling out of our     */
 /*      buffer.                                                         */
 /* -------------------------------------------------------------------- */
-        int iLineToSave = nNewLine - nIterations;
+        const int iLineToSave = nNewLine - nIterations;
 
         if( iLineToSave >= 0 && eErr == CE_None )
         {
-            iBufOffset = iLineToSave % nBufLines;
+            const int iBufOffset2 = iLineToSave % nBufLines;
 
             eErr =
                 GDALRasterIO( hTargetBand, GF_Write,
                               0, iLineToSave, nXSize, 1,
-                              pafThisPass + nXSize * iBufOffset, nXSize, 1,
+                              pafThisPass + nXSize * iBufOffset2, nXSize, 1,
                               GDT_Float32, 0, 0 );
         }
 
 /* -------------------------------------------------------------------- */
 /*      Report progress.                                                */
 /* -------------------------------------------------------------------- */
-        if( eErr == CE_None
-            && !pfnProgress( (nNewLine+1) / (double) (nYSize+nIterations),
-                             "Smoothing Filter...", pProgressArg ) )
+        if( eErr == CE_None &&
+            !pfnProgress(
+                (nNewLine + 1) / static_cast<double>(nYSize+nIterations),
+                "Smoothing Filter...", pProgressArg) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
             eErr = CE_Failure;
@@ -316,7 +328,6 @@ GDALMultiFilter( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-end:
     CPLFree( pabyTMaskBuf );
     CPLFree( pabyFMaskBuf );
     CPLFree( paf3PassLineBuf );
@@ -330,21 +341,23 @@ end:
 /*      macro for checking whether a point is nearer than the           */
 /*      existing closest point.                                         */
 /************************************************************************/
-#define QUAD_CHECK(quad_dist, quad_value, 				\
-target_x, target_y, origin_x, origin_y, target_value )			\
-									\
-if( quad_value != nNoDataVal ) 						\
-{									\
-    double dfDx = (double)target_x - (double)origin_x;			\
-    double dfDy = (double)target_y - (double)origin_y;			\
-    double dfDistSq = dfDx * dfDx + dfDy * dfDy;			\
-    									\
-    if( dfDistSq < quad_dist*quad_dist )				\
-    {									\
-	CPLAssert( dfDistSq > 0.0 );                                    \
-        quad_dist = sqrt(dfDistSq); 					\
-        quad_value = target_value;					\
-    }									\
+
+// TODO(schwehr): Convert to an inline function.
+#define QUAD_CHECK(quad_dist, quad_value,                               \
+target_x, target_y, origin_x, origin_y, target_value )                  \
+                                                                        \
+if( quad_value != nNoDataVal )                                          \
+{                                                                       \
+    double dfDx = (double)target_x - (double)origin_x;                  \
+    double dfDy = (double)target_y - (double)origin_y;                  \
+    double dfDistSq = dfDx * dfDx + dfDy * dfDy;                        \
+                                                                        \
+    if( dfDistSq < quad_dist*quad_dist )                                \
+    {                                                                   \
+        CPLAssert( dfDistSq > 0.0 );                                    \
+        quad_dist = sqrt(dfDistSq);                                     \
+        quad_value = target_value;                                      \
+    }                                                                   \
 }
 
 /************************************************************************/
@@ -370,7 +383,8 @@ if( quad_value != nNoDataVal ) 						\
  * point data - see the algorithms defined in gdal_grid.h for that case.
  *
  * @param hTargetBand the raster band to be modified in place.
- * @param hMaskBand a mask band indicating pixels to be interpolated (zero valued
+ * @param hMaskBand a mask band indicating pixels to be interpolated
+ * (zero valued).
  * @param dfMaxSearchDist the maximum number of pixels to search in all
  * directions to find values to interpolate from.
  * @param bDeprecatedOption unused argument, should be zero.
@@ -397,35 +411,29 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 {
     VALIDATE_POINTER1( hTargetBand, "GDALFillNodata", CE_Failure );
 
-    int nXSize = GDALGetRasterBandXSize( hTargetBand );
-    int nYSize = GDALGetRasterBandYSize( hTargetBand );
-    CPLErr eErr = CE_None;
-
-    // Special "x" pixel values identifying pixels as special.
-    GUInt32 nNoDataVal;
-    GDALDataType eType;
+    const int nXSize = GDALGetRasterBandXSize(hTargetBand);
+    const int nYSize = GDALGetRasterBandYSize(hTargetBand);
 
     if( dfMaxSearchDist == 0.0 )
-        dfMaxSearchDist = MAX(nXSize,nYSize) + 1;
+        dfMaxSearchDist = std::max(nXSize, nYSize) + 1;
 
-    int nMaxSearchDist = (int) floor(dfMaxSearchDist);
+    const int nMaxSearchDist = static_cast<int>(floor(dfMaxSearchDist));
+
+    // Special "x" pixel values identifying pixels as special.
+    GDALDataType eType = GDT_UInt16;
+    GUInt32 nNoDataVal = 65535;
 
     if( nXSize > 65533 || nYSize > 65533 )
     {
         eType = GDT_UInt32;
         nNoDataVal = 4000002;
     }
-    else
-    {
-        eType = GDT_UInt16;
-        nNoDataVal = 65535;
-    }
 
     if( hMaskBand == NULL )
         hMaskBand = GDALGetMaskBand( hTargetBand );
 
-    /* If there are smoothing iterations, reserve 10% of the progress for them */
-    double dfProgressRatio = (nSmoothingIterations > 0) ? 0.9 : 1.0;
+    // If there are smoothing iterations, reserve 10% of the progress for them.
+    const double dfProgressRatio = nSmoothingIterations > 0 ? 0.9 : 1.0;
 
 /* -------------------------------------------------------------------- */
 /*      Initialize progress counter.                                    */
@@ -444,16 +452,16 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
     CPLString osTmpFileDriver = CSLFetchNameValueDef(
             papszOptions, "TEMP_FILE_DRIVER", "GTiff");
-    GDALDriverH hDriver = GDALGetDriverByName((const char *) osTmpFileDriver);
+    GDALDriverH hDriver = GDALGetDriverByName(osTmpFileDriver.c_str());
 
-    if (hDriver == NULL)
+    if( hDriver == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Given driver is not registered");
         return CE_Failure;
     }
 
-    if (GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL) == NULL)
+    if( GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, NULL) == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Given driver is incapable of creating temp work files");
@@ -461,7 +469,8 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
     }
 
     char **papszWorkFileOptions = NULL;
-    if (osTmpFileDriver == "GTiff") {
+    if( osTmpFileDriver == "GTiff" )
+    {
         papszWorkFileOptions = CSLSetNameValue(
                 papszWorkFileOptions, "COMPRESS", "LZW");
         papszWorkFileOptions = CSLSetNameValue(
@@ -471,93 +480,95 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
 /*      Create a work file to hold the Y "last value" indices.          */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hYDS;
-    GDALRasterBandH hYBand;
-
-    CPLString osTmpFile = CPLGenerateTempFilename("");
-    CPLString osYTmpFile = osTmpFile + "fill_y_work.tif";
+    const CPLString osTmpFile = CPLGenerateTempFilename("");
+    const CPLString osYTmpFile = osTmpFile + "fill_y_work.tif";
 
-    hYDS = GDALCreate( hDriver, osYTmpFile, nXSize, nYSize, 1,
-                       eType, (char **) papszWorkFileOptions );
+    GDALDatasetH hYDS =
+        GDALCreate( hDriver, osYTmpFile, nXSize, nYSize, 1,
+                    eType, papszWorkFileOptions );
 
-    if ( hYDS == NULL )
+    if( hYDS == NULL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
             "Could not create Y index work file. Check driver capabilities.");
         return CE_Failure;
     }
 
-    hYBand = GDALGetRasterBand( hYDS, 1 );
+    GDALRasterBandH hYBand = GDALGetRasterBand( hYDS, 1 );
 
 /* -------------------------------------------------------------------- */
 /*      Create a work file to hold the pixel value associated with      */
 /*      the "last xy value" pixel.                                      */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hValDS;
-    GDALRasterBandH hValBand;
-    CPLString osValTmpFile = osTmpFile + "fill_val_work.tif";
+    const CPLString osValTmpFile = osTmpFile + "fill_val_work.tif";
 
-    hValDS = GDALCreate( hDriver, osValTmpFile, nXSize, nYSize, 1,
-                         GDALGetRasterDataType( hTargetBand ),
-                         (char **) papszWorkFileOptions );
+    GDALDatasetH hValDS =
+        GDALCreate( hDriver, osValTmpFile, nXSize, nYSize, 1,
+                    GDALGetRasterDataType( hTargetBand ),
+                    papszWorkFileOptions );
 
-    if ( hValDS == NULL )
+    if( hValDS == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
             "Could not create XY value work file. Check driver capabilities.");
         return CE_Failure;
     }
 
-    hValBand = GDALGetRasterBand( hValDS, 1 );
+    GDALRasterBandH hValBand = GDALGetRasterBand( hValDS, 1 );
 
 /* -------------------------------------------------------------------- */
 /*      Create a mask file to make it clear what pixels can be filtered */
 /*      on the filtering pass.                                          */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hFiltMaskDS;
-    GDALRasterBandH hFiltMaskBand;
-    CPLString osFiltMaskTmpFile = osTmpFile + "fill_filtmask_work.tif";
+    const CPLString osFiltMaskTmpFile = osTmpFile + "fill_filtmask_work.tif";
 
-    hFiltMaskDS =
+    GDALDatasetH hFiltMaskDS =
         GDALCreate( hDriver, osFiltMaskTmpFile, nXSize, nYSize, 1,
-                    GDT_Byte, (char **) papszWorkFileOptions );
+                    GDT_Byte, papszWorkFileOptions );
 
-    if ( hFiltMaskDS == NULL )
+    if( hFiltMaskDS == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
             "Could not create mask work file. Check driver capabilities.");
         return CE_Failure;
     }
 
-    hFiltMaskBand = GDALGetRasterBand( hFiltMaskDS, 1 );
+    GDALRasterBandH hFiltMaskBand = GDALGetRasterBand( hFiltMaskDS, 1 );
 
 /* -------------------------------------------------------------------- */
 /*      Allocate buffers for last scanline and this scanline.           */
 /* -------------------------------------------------------------------- */
-    GUInt32 *panLastY, *panThisY, *panTopDownY;
-    float   *pafLastValue, *pafThisValue, *pafScanline, *pafTopDownValue;
-    GByte   *pabyMask, *pabyFiltMask;
-    int     iX;
-    int     iY;
-
-    panLastY = (GUInt32 *) VSI_CALLOC_VERBOSE(nXSize,sizeof(GUInt32));
-    panThisY = (GUInt32 *) VSI_CALLOC_VERBOSE(nXSize,sizeof(GUInt32));
-    panTopDownY = (GUInt32 *) VSI_CALLOC_VERBOSE(nXSize,sizeof(GUInt32));
-    pafLastValue = (float *) VSI_CALLOC_VERBOSE(nXSize,sizeof(float));
-    pafThisValue = (float *) VSI_CALLOC_VERBOSE(nXSize,sizeof(float));
-    pafTopDownValue = (float *) VSI_CALLOC_VERBOSE(nXSize,sizeof(float));
-    pafScanline = (float *) VSI_CALLOC_VERBOSE(nXSize,sizeof(float));
-    pabyMask = (GByte *) VSI_CALLOC_VERBOSE(nXSize,1);
-    pabyFiltMask = (GByte *) VSI_CALLOC_VERBOSE(nXSize,1);
-    if (panLastY == NULL || panThisY == NULL || panTopDownY == NULL ||
-        pafLastValue == NULL || pafThisValue == NULL || pafTopDownValue == NULL ||
-        pafScanline == NULL || pabyMask == NULL || pabyFiltMask == NULL)
+
+    GUInt32 *panLastY =
+        static_cast<GUInt32 *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(GUInt32)));
+    GUInt32 *panThisY =
+        static_cast<GUInt32 *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(GUInt32)));
+    GUInt32 *panTopDownY =
+        static_cast<GUInt32 *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(GUInt32)));
+    float *pafLastValue =
+        static_cast<float *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(float)));
+    float *pafThisValue =
+        static_cast<float *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(float)));
+    float *pafTopDownValue =
+        static_cast<float *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(float)));
+    float *pafScanline =
+        static_cast<float *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(float)));
+    GByte *pabyMask = static_cast<GByte *>(VSI_CALLOC_VERBOSE(nXSize, 1));
+    GByte *pabyFiltMask = static_cast<GByte *>(VSI_CALLOC_VERBOSE(nXSize, 1));
+
+    CPLErr eErr = CE_None;
+
+    if( panLastY == NULL || panThisY == NULL || panTopDownY == NULL ||
+        pafLastValue == NULL || pafThisValue == NULL ||
+        pafTopDownValue == NULL ||
+        pafScanline == NULL || pabyMask == NULL || pabyFiltMask == NULL )
     {
         eErr = CE_Failure;
         goto end;
     }
 
-    for( iX = 0; iX < nXSize; iX++ )
+    for( int iX = 0; iX < nXSize; iX++ )
     {
         panLastY[iX] = nNoDataVal;
     }
@@ -568,7 +579,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /*      files.                                                          */
 /* ==================================================================== */
 
-    for( iY = 0; iY < nYSize && eErr == CE_None; iY++ )
+    for( int iY = 0; iY < nYSize && eErr == CE_None; iY++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Read data and mask for this line.                               */
@@ -591,7 +602,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /*      Figure out the most recent pixel for each column.               */
 /* -------------------------------------------------------------------- */
 
-        for( iX = 0; iX < nXSize; iX++ )
+        for( int iX = 0; iX < nXSize; iX++ )
         {
             if( pabyMask[iX] )
             {
@@ -625,22 +636,17 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
 /*      Flip this/last buffers.                                         */
 /* -------------------------------------------------------------------- */
-        {
-            float *pafTmp = pafThisValue;
-            pafThisValue = pafLastValue;
-            pafLastValue = pafTmp;
-
-            GUInt32 *panTmp = panThisY;
-            panThisY = panLastY;
-            panLastY = panTmp;
-        }
+        std::swap(pafThisValue, pafLastValue);
+        std::swap(panThisY, panLastY);
 
 /* -------------------------------------------------------------------- */
 /*      report progress.                                                */
 /* -------------------------------------------------------------------- */
-        if( eErr == CE_None
-            && !pfnProgress( dfProgressRatio * (0.5*(iY+1) / (double)nYSize),
-                             "Filling...", pProgressArg ) )
+        if( eErr == CE_None &&
+            !pfnProgress(
+                dfProgressRatio * (0.5*(iY+1) /
+                                   static_cast<double>(nYSize)),
+                "Filling...", pProgressArg ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
             eErr = CE_Failure;
@@ -652,7 +658,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /*      bottom to top and use it in combination with the top to         */
 /*      bottom search info to interpolate.                              */
 /* ==================================================================== */
-    for( iY = nYSize-1; iY >= 0 && eErr == CE_None; iY-- )
+    for( int iY = nYSize-1; iY >= 0 && eErr == CE_None; iY-- )
     {
         eErr =
             GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1,
@@ -672,7 +678,7 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /*      Figure out the most recent pixel for each column.               */
 /* -------------------------------------------------------------------- */
 
-        for( iX = 0; iX < nXSize; iX++ )
+        for( int iX = 0; iX < nXSize; iX++ )
         {
             if( pabyMask[iX] )
             {
@@ -711,9 +717,8 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /*      Attempt to interpolate any pixels that are nodata.              */
 /* -------------------------------------------------------------------- */
         memset( pabyFiltMask, 0, nXSize );
-        for( iX = 0; iX < nXSize; iX++ )
+        for( int iX = 0; iX < nXSize; iX++ )
         {
-            int iStep, iQuad;
             int nThisMaxSearchDist = nMaxSearchDist;
 
             // If this was a valid target - no change.
@@ -721,10 +726,10 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
                 continue;
 
             // Quadrants 0:topleft, 1:bottomleft, 2:topright, 3:bottomright
-            double adfQuadDist[4];
-            double adfQuadValue[4];
+            double adfQuadDist[4] = {};
+            double adfQuadValue[4] = {};
 
-            for( iQuad = 0; iQuad < 4; iQuad++ )
+            for( int iQuad = 0; iQuad < 4; iQuad++ )
             {
                 adfQuadDist[iQuad] = dfMaxSearchDist + 1.0;
                 adfQuadValue[iQuad] = 0.0;
@@ -732,50 +737,50 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 
             // Step left and right by one pixel searching for the closest
             // target value for each quadrant.
-            for( iStep = 0; iStep < nThisMaxSearchDist; iStep++ )
+            for( int iStep = 0; iStep < nThisMaxSearchDist; iStep++ )
             {
-                int iLeftX = MAX(0,iX - iStep);
-                int iRightX = MIN(nXSize-1,iX + iStep);
+                const int iLeftX = std::max(0, iX - iStep);
+                const int iRightX = std::min(nXSize - 1, iX + iStep);
 
-                // top left includes current line
-                QUAD_CHECK(adfQuadDist[0],adfQuadValue[0],
+                // Top left includes current line.
+                QUAD_CHECK(adfQuadDist[0], adfQuadValue[0],
                            iLeftX, panTopDownY[iLeftX], iX, iY,
                            pafTopDownValue[iLeftX] );
 
-                // bottom left
-                QUAD_CHECK(adfQuadDist[1],adfQuadValue[1],
+                // Bottom left.
+                QUAD_CHECK(adfQuadDist[1], adfQuadValue[1],
                            iLeftX, panLastY[iLeftX], iX, iY,
                            pafLastValue[iLeftX] );
 
-                // top right and bottom right do no include center pixel.
+                // Top right and bottom right do no include center pixel.
                 if( iStep == 0 )
                      continue;
 
-                // top right includes current line
-                QUAD_CHECK(adfQuadDist[2],adfQuadValue[2],
+                // Top right includes current line.
+                QUAD_CHECK(adfQuadDist[2], adfQuadValue[2],
                            iRightX, panTopDownY[iRightX], iX, iY,
                            pafTopDownValue[iRightX] );
 
-                // bottom right
-                QUAD_CHECK(adfQuadDist[3],adfQuadValue[3],
+                // Bottom right.
+                QUAD_CHECK(adfQuadDist[3], adfQuadValue[3],
                            iRightX, panLastY[iRightX], iX, iY,
                            pafLastValue[iRightX] );
 
-                // every four steps, recompute maximum distance.
+                // Every four steps, recompute maximum distance.
                 if( (iStep & 0x3) == 0 )
-                    nThisMaxSearchDist = (int) floor(
-                        MAX(MAX(adfQuadDist[0],adfQuadDist[1]),
-                            MAX(adfQuadDist[2],adfQuadDist[3])) );
+                    nThisMaxSearchDist = static_cast<int>(floor(
+                        std::max(std::max(adfQuadDist[0], adfQuadDist[1]),
+                                 std::max(adfQuadDist[2], adfQuadDist[3]))));
             }
 
             double dfWeightSum = 0.0;
             double dfValueSum = 0.0;
 
-            for( iQuad = 0; iQuad < 4; iQuad++ )
+            for( int iQuad = 0; iQuad < 4; iQuad++ )
             {
                 if( adfQuadDist[iQuad] <= dfMaxSearchDist )
                 {
-                    double dfWeight = 1.0 / adfQuadDist[iQuad];
+                    const double dfWeight = 1.0 / adfQuadDist[iQuad];
 
                     dfWeightSum += dfWeight;
                     dfValueSum += adfQuadValue[iQuad] * dfWeight;
@@ -786,9 +791,8 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
             {
                 pabyMask[iX] = 255;
                 pabyFiltMask[iX] = 255;
-                pafScanline[iX] = (float) (dfValueSum / dfWeightSum);
+                pafScanline[iX] = static_cast<float>(dfValueSum / dfWeightSum);
             }
-
         }
 
 /* -------------------------------------------------------------------- */
@@ -811,22 +815,17 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /* -------------------------------------------------------------------- */
 /*      Flip this/last buffers.                                         */
 /* -------------------------------------------------------------------- */
-        {
-            float *pafTmp = pafThisValue;
-            pafThisValue = pafLastValue;
-            pafLastValue = pafTmp;
-
-            GUInt32 *panTmp = panThisY;
-            panThisY = panLastY;
-            panLastY = panTmp;
-        }
+        std::swap(pafThisValue, pafLastValue);
+        std::swap(panThisY, panLastY);
 
 /* -------------------------------------------------------------------- */
 /*      report progress.                                                */
 /* -------------------------------------------------------------------- */
-        if( eErr == CE_None
-            && !pfnProgress( dfProgressRatio*(0.5+0.5*(nYSize-iY) / (double)nYSize),
-                             "Filling...", pProgressArg ) )
+        if( eErr == CE_None &&
+            !pfnProgress(
+                dfProgressRatio*(0.5+0.5*(nYSize-iY) /
+                                 static_cast<double>(nYSize)),
+                "Filling...", pProgressArg) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
             eErr = CE_Failure;
@@ -840,11 +839,10 @@ GDALFillNodata( GDALRasterBandH hTargetBand,
 /* ==================================================================== */
     if( eErr == CE_None && nSmoothingIterations > 0 )
     {
-        // force masks to be to flushed and recomputed.
+        // Force masks to be to flushed and recomputed.
         GDALFlushRasterCache( hMaskBand );
 
-        void *pScaledProgress;
-        pScaledProgress =
+        void *pScaledProgress =
             GDALCreateScaledProgress( dfProgressRatio, 1.0, pfnProgress, NULL );
 
         eErr = GDALMultiFilter( hTargetBand, hMaskBand, hFiltMaskBand,
diff --git a/alg/thinplatespline.cpp b/alg/thinplatespline.cpp
index eeedfe3..0004e57 100644
--- a/alg/thinplatespline.cpp
+++ b/alg/thinplatespline.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: thinplatespline.cpp 33715 2016-03-13 08:52:06Z goatbar $
  *
  * Project:  GDAL Warp API
  * Purpose:  Implemenentation of 2D Thin Plate Spline transformer.
@@ -31,12 +30,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+/*! @cond Doxygen_Suppress */
+
+#if defined(HAVE_ARMADILLO) && !defined(DO_NOT_USE_DEBUG_BOOL)
+#define DO_NOT_USE_DEBUG_BOOL
+#endif
+
+#include "cpl_port.h"
+#include "thinplatespline.h"
+
 #ifdef HAVE_ARMADILLO
-/* Include before #define A(r,c) because armadillo uses A in its include files */
+// Include before #define A(r,c) because armadillo uses A in its include files.
 #include "armadillo"
 #endif
 
-#include "thinplatespline.h"
+#include <climits>
+#ifndef DEBUG_BOOL  // TODO(schwehr): Why?
+#include <cmath>
+#endif
+#include <cstdio>
+#include <cstring>
+
+#include <algorithm>
+#include <utility>
+
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+
+CPL_CVSID("$Id: thinplatespline.cpp 37119 2017-01-12 12:22:02Z rouault $");
 
 //////////////////////////////////////////////////////////////////////////////
 //// vizGeorefSpline2D
@@ -45,42 +66,43 @@
 #define A(r,c) _AA[ _nof_eqs * (r) + (c) ]
 #define Ainv(r,c) _Ainv[ _nof_eqs * (r) + (c) ]
 
+// #define VIZ_GEOREF_SPLINE_DEBUG 0
 
-#define VIZ_GEOREF_SPLINE_DEBUG 0
-
-#ifndef HAVE_ARMADILLO
 static int matrixInvert( int N, double input[], double output[] );
-#endif
 
 bool VizGeorefSpline2D::grow_points()
 
 {
-    int new_max = _max_nof_points*2 + 2 + 3;
-    int i;
+    const int new_max = _max_nof_points * 2 + 2 + 3;
 
-    double *new_x = (double *) VSI_REALLOC_VERBOSE( x, sizeof(double) * new_max );
+    double *new_x = static_cast<double *>(
+        VSI_REALLOC_VERBOSE(x, sizeof(double) * new_max ));
     if( !new_x ) return false;
     x = new_x;
-    double *new_y = (double *) VSI_REALLOC_VERBOSE( y, sizeof(double) * new_max );
+    double *new_y = static_cast<double *>(
+        VSI_REALLOC_VERBOSE(y, sizeof(double) * new_max ));
     if( !new_y ) return false;
     y = new_y;
-    double *new_u = (double *) VSI_REALLOC_VERBOSE( u, sizeof(double) * new_max );
+    double *new_u = static_cast<double *>(
+        VSI_REALLOC_VERBOSE(u, sizeof(double) * new_max ));
     if( !new_u ) return false;
     u = new_u;
-    int *new_unused = (int *) VSI_REALLOC_VERBOSE( unused, sizeof(int) * new_max );
+    int *new_unused = static_cast<int *>(
+        VSI_REALLOC_VERBOSE(unused, sizeof(int) * new_max ));
     if( !new_unused ) return false;
     unused = new_unused;
-    int *new_index = (int *) VSI_REALLOC_VERBOSE( index, sizeof(int) * new_max );
+    int *new_index = static_cast<int *>(
+        VSI_REALLOC_VERBOSE(index, sizeof(int) * new_max));
     if( !new_index ) return false;
     index = new_index;
-    for( i = 0; i < _nof_vars; i++ )
+    for( int i = 0; i < _nof_vars; i++ )
     {
-        double* rhs_i_new = (double *)
-            VSI_REALLOC_VERBOSE( rhs[i], sizeof(double) * new_max );
+        double* rhs_i_new = static_cast<double *>(
+            VSI_REALLOC_VERBOSE(rhs[i], sizeof(double) * new_max));
         if( !rhs_i_new ) return false;
         rhs[i] = rhs_i_new;
-        double* coef_i_new = (double *)
-            VSI_REALLOC_VERBOSE( coef[i], sizeof(double) * new_max );
+        double* coef_i_new = static_cast<double *>(
+            VSI_REALLOC_VERBOSE(coef[i], sizeof(double) * new_max));
         if( !coef_i_new ) return false;
         coef[i] = coef_i_new;
         if( _max_nof_points == 0 )
@@ -94,7 +116,8 @@ bool VizGeorefSpline2D::grow_points()
     return true;
 }
 
-bool VizGeorefSpline2D::add_point( const double Px, const double Py, const double *Pvars )
+bool VizGeorefSpline2D::add_point( const double Px, const double Py,
+                                   const double *Pvars )
 {
     type = VIZ_GEOREF_SPLINE_POINT_WAS_ADDED;
     int i;
@@ -106,78 +129,80 @@ bool VizGeorefSpline2D::add_point( const double Px, const double Py, const doubl
     }
 
     i = _nof_points;
-    //A new point is added
+    // A new point is added.
     x[i] = Px;
     y[i] = Py;
-    for ( int j = 0; j < _nof_vars; j++ )
+    for( int j = 0; j < _nof_vars; j++ )
         rhs[j][i+3] = Pvars[j];
     _nof_points++;
     return true;
 }
 
 #if 0
-bool VizGeorefSpline2D::change_point(int index, double Px, double Py, double* Pvars)
+bool VizGeorefSpline2D::change_point( int index, double Px, double Py,
+                                      double* Pvars )
 {
-    if ( index < _nof_points )
+    if( index < _nof_points )
     {
         int i = index;
         x[i] = Px;
         y[i] = Py;
-        for ( int j = 0; j < _nof_vars; j++ )
+        for( int j = 0; j < _nof_vars; j++ )
             rhs[j][i+3] = Pvars[j];
     }
 
-    return( true );
+    return true;
 }
 
-bool VizGeorefSpline2D::get_xy(int index, double& outX, double& outY)
+bool VizGeorefSpline2D::get_xy( int index, double& outX, double& outY )
 {
-    bool ok;
-
-    if ( index < _nof_points )
+    if( index < _nof_points )
     {
         ok = true;
         outX = x[index];
         outY = y[index];
+        return true;
     }
-    else
-    {
-        ok = false;
-        outX = outY = 0.0f;
-    }
 
-    return(ok);
+    outX = 0.0;
+    outY = 0.0;
+
+    return false;
 }
 
-int VizGeorefSpline2D::delete_point(const double Px, const double Py )
+int VizGeorefSpline2D::delete_point( const double Px, const double Py )
 {
-    for ( int i = 0; i < _nof_points; i++ )
+    for( int i = 0; i < _nof_points; i++ )
     {
-        if ( ( fabs(Px - x[i]) <= _tx ) && ( fabs(Py - y[i]) <= _ty ) )
+        if( ( fabs(Px - x[i]) <= _tx ) && ( fabs(Py - y[i]) <= _ty ) )
         {
-            for ( int j = i; j < _nof_points - 1; j++ )
+            for( int j = i; j < _nof_points - 1; j++ )
             {
                 x[j] = x[j+1];
                 y[j] = y[j+1];
-                for ( int k = 0; k < _nof_vars; k++ )
+                for( int k = 0; k < _nof_vars; k++ )
                     rhs[k][j+3] = rhs[k][j+3+1];
             }
             _nof_points--;
             type = VIZ_GEOREF_SPLINE_POINT_WAS_DELETED;
-            return(1);
+            return 1;
         }
     }
-    return(0);
+    return 0;
 }
 #endif
 
-#define SQ(x) ((x)*(x))
+template<typename T> static inline T SQ( const T &x )
+{
+    return x * x;
+}
 
-static CPL_INLINE double VizGeorefSpline2DBase_func( const double x1, const double y1,
-                          const double x2, const double y2 )
+static inline double
+VizGeorefSpline2DBase_func( const double x1, const double y1,
+                            const double x2, const double y2 )
 {
-    double dist  = SQ( x2 - x1 )  + SQ( y2 - y1 );
-    return dist ? dist * log( dist ) : 0.0;
+    const double dist = SQ( x2 - x1 )  + SQ( y2 - y1 );
+    return dist != 0.0 ? dist * log( dist ) : 0.0;
 }
 
 #if defined(__GNUC__) && defined(__x86_64__)
@@ -277,20 +302,21 @@ typedef union
     long long li;
 } i64union;
 
-static const V2DF
-v2_ln2_div_2pow20 = {6.93147180559945286e-01 / 1048576, 6.93147180559945286e-01 / 1048576},
-v2_Lg1 = {6.666666666666735130e-01, 6.666666666666735130e-01},
-v2_Lg2 = {3.999999999940941908e-01, 3.999999999940941908e-01},
-v2_Lg3 = {2.857142874366239149e-01, 2.857142874366239149e-01},
-v2_Lg4 = {2.222219843214978396e-01, 2.222219843214978396e-01},
-v2_Lg5 = {1.818357216161805012e-01, 1.818357216161805012e-01},
-v2_Lg6 = {1.531383769920937332e-01, 1.531383769920937332e-01},
+static const V2DF v2_ln2_div_2pow20 =
+    { 6.93147180559945286e-01 / 1048576, 6.93147180559945286e-01 / 1048576 };
+static const V2DF v2_Lg1 = {6.666666666666735130e-01, 6.666666666666735130e-01};
+static const V2DF v2_Lg2 = {3.999999999940941908e-01, 3.999999999940941908e-01};
+static const V2DF v2_Lg3 = {2.857142874366239149e-01, 2.857142874366239149e-01};
+static const V2DF v2_Lg4 = {2.222219843214978396e-01, 2.222219843214978396e-01};
+static const V2DF v2_Lg5 = {1.818357216161805012e-01, 1.818357216161805012e-01};
+static const V2DF v2_Lg6 = {1.531383769920937332e-01, 1.531383769920937332e-01};
 /*v2_Lg7 = {1.479819860511658591e-01, 1.479819860511658591e-01}, */
-v2_one = { 1.0, 1.0 },
-v2_const1023_mul_2pow20 = { 1023.0 * 1048576, 1023.0 * 1048576};
+static const V2DF v2_one = { 1.0, 1.0 };
+static const V2DF v2_const1023_mul_2pow20 =
+    { 1023.0 * 1048576, 1023.0 * 1048576 };
 
-#define GET_HIGH_WORD(hx,x) memcpy(&hx,((char*)&x+4),4)
-#define SET_HIGH_WORD(x,hx) memcpy(((char*)&x+4),&hx,4)
+#define GET_HIGH_WORD(hx,x) memcpy(&hx, ((char*)&x+4),4)
+#define SET_HIGH_WORD(x,hx) memcpy(((char*)&x+4), &hx,4)
 
 #define MAKE_WIDE_CST(x) ((((long long)(x)) << 32) | (x))
 static const long long cst_expmask = MAKE_WIDE_CST(0xfff00000);
@@ -298,83 +324,103 @@ static const long long cst_0x95f64 = MAKE_WIDE_CST(0x00095f64);
 static const long long cst_0x100000 = MAKE_WIDE_CST(0x00100000);
 static const long long cst_0x3ff00000 = MAKE_WIDE_CST(0x3ff00000);
 
-/* Modified version of __ieee754_log(), less precise than log() but a bit */
-/* faster, and computing 4 log() at a time. Assumes that the values are > 0 */
+// Modified version of __ieee754_log(), less precise than log() but a bit
+// faster, and computing 4 log() at a time. Assumes that the values are > 0.
 static void FastApproxLog4Val(v2dfunion* x)
 {
-    V2DF f[2],s[2],z[2],R[2],w[2],t1[2],t2[2];
-    v2dfunion dk[2];
-    i64union k[2], hx[2], i[2];
+    i64union hx[2] = {};
+    i64union k[2] = {};
+    i64union i[2] = {};
+    GET_HIGH_WORD(hx[0].i[0], x[0].d[0]);
+    GET_HIGH_WORD(hx[0].i[1], x[0].d[1]);
 
-    GET_HIGH_WORD(hx[0].i[0],x[0].d[0]);
-    GET_HIGH_WORD(hx[0].i[1],x[0].d[1]);
-    /* coverity[uninit_use] */
+    // coverity[uninit_use]
     k[0].li = hx[0].li & cst_expmask;
     hx[0].li &= ~cst_expmask;
     i[0].li = (hx[0].li + cst_0x95f64) & cst_0x100000;
     hx[0].li |= i[0].li ^ cst_0x3ff00000;
-    SET_HIGH_WORD(x[0].d[0],hx[0].i[0]);     /* normalize x or x/2 */
-    SET_HIGH_WORD(x[0].d[1],hx[0].i[1]);     /* normalize x or x/2 */
+    SET_HIGH_WORD(x[0].d[0], hx[0].i[0]);  // Normalize x or x/2.
+    SET_HIGH_WORD(x[0].d[1], hx[0].i[1]);  // Normalize x or x/2.
     k[0].li += i[0].li;
-    dk[0].d[0] = (double)k[0].i[0];
-    dk[0].d[1] = (double)k[0].i[1];
 
-    GET_HIGH_WORD(hx[1].i[0],x[1].d[0]);
-    GET_HIGH_WORD(hx[1].i[1],x[1].d[1]);
+    v2dfunion dk[2] = {};
+    dk[0].d[0] = static_cast<double>(k[0].i[0]);
+    dk[0].d[1] = static_cast<double>(k[0].i[1]);
+
+    GET_HIGH_WORD(hx[1].i[0], x[1].d[0]);
+    GET_HIGH_WORD(hx[1].i[1], x[1].d[1]);
     k[1].li = hx[1].li & cst_expmask;
     hx[1].li &= ~cst_expmask;
     i[1].li = (hx[1].li + cst_0x95f64) & cst_0x100000;
     hx[1].li |= i[1].li ^ cst_0x3ff00000;
-    SET_HIGH_WORD(x[1].d[0],hx[1].i[0]);     /* normalize x or x/2 */
-    SET_HIGH_WORD(x[1].d[1],hx[1].i[1]);     /* normalize x or x/2 */
+    SET_HIGH_WORD(x[1].d[0], hx[1].i[0]);  // Normalize x or x/2.
+    SET_HIGH_WORD(x[1].d[1], hx[1].i[1]);  // Normalize x or x/2.
     k[1].li += i[1].li;
-    dk[1].d[0] = (double)k[1].i[0];
-    dk[1].d[1] = (double)k[1].i[1];
+    dk[1].d[0] = static_cast<double>(k[1].i[0]);
+    dk[1].d[1] = static_cast<double>(k[1].i[1]);
 
+    V2DF f[2] = {};
     f[0] = x[0].v2-v2_one;
+    V2DF s[2] = {};
     s[0] = f[0]/(x[0].v2+v2_one);
+    V2DF z[2] = {};
     z[0] = s[0]*s[0];
+    V2DF w[2] = {};
     w[0] = z[0]*z[0];
-    /* coverity[ptr_arith] */
+
+    V2DF t1[2] = {};
+    // coverity[ptr_arith]
     t1[0]= w[0]*(v2_Lg2+w[0]*(v2_Lg4+w[0]*v2_Lg6));
-    /* coverity[ptr_arith] */
+
+    V2DF t2[2] = {};
+    // coverity[ptr_arith]
     t2[0]= z[0]*(v2_Lg1+w[0]*(v2_Lg3+w[0]*(v2_Lg5/*+w[0]*v2_Lg7*/)));
+
+    V2DF R[2] = {};
     R[0] = t2[0]+t1[0];
-    x[0].v2 = ((dk[0].v2 - v2_const1023_mul_2pow20)*v2_ln2_div_2pow20-(s[0]*(f[0]-R[0])-f[0]));
+    x[0].v2 =
+        (dk[0].v2 - v2_const1023_mul_2pow20) * v2_ln2_div_2pow20 -
+        (s[0] * (f[0] - R[0]) - f[0]);
 
     f[1] = x[1].v2-v2_one;
     s[1] = f[1]/(x[1].v2+v2_one);
     z[1] = s[1]*s[1];
     w[1] = z[1]*z[1];
-    /* coverity[ptr_arith] */
+    // coverity[ptr_arith]
     t1[1]= w[1]*(v2_Lg2+w[1]*(v2_Lg4+w[1]*v2_Lg6));
-    /* coverity[ptr_arith] */
+    // coverity[ptr_arith]
     t2[1]= z[1]*(v2_Lg1+w[1]*(v2_Lg3+w[1]*(v2_Lg5/*+w[1]*v2_Lg7*/)));
     R[1] = t2[1]+t1[1];
-    x[1].v2 = ((dk[1].v2- v2_const1023_mul_2pow20)*v2_ln2_div_2pow20-(s[1]*(f[1]-R[1])-f[1]));
+    x[1].v2 =
+        (dk[1].v2 - v2_const1023_mul_2pow20) * v2_ln2_div_2pow20 -
+        (s[1] * (f[1] - R[1]) - f[1]);
 }
 
-static CPL_INLINE void VizGeorefSpline2DBase_func4( double* res,
-                                         const double* pxy,
-                                         const double* xr, const double* yr )
+static CPL_INLINE void VizGeorefSpline2DBase_func4(
+    double* res,
+    const double* pxy,
+    const double* xr, const double* yr )
 {
-    v2dfunion x1v, y1v, xv[2], yv[2], dist[2], resv[2];
+    v2dfunion xv[2] = {};
     xv[0].d[0] = xr[0];
     xv[0].d[1] = xr[1];
     xv[1].d[0] = xr[2];
     xv[1].d[1] = xr[3];
+    v2dfunion yv[2];
     yv[0].d[0] = yr[0];
     yv[0].d[1] = yr[1];
     yv[1].d[0] = yr[2];
     yv[1].d[1] = yr[3];
+    v2dfunion x1v;
     x1v.d[0] = pxy[0];
     x1v.d[1] = pxy[0];
+    v2dfunion y1v;
     y1v.d[0] = pxy[1];
     y1v.d[1] = pxy[1];
+    v2dfunion dist[2] = {};
     dist[0].v2 = SQ( xv[0].v2 - x1v.v2 ) + SQ( yv[0].v2 - y1v.v2 );
     dist[1].v2 = SQ( xv[1].v2 - x1v.v2 ) + SQ( yv[1].v2 - y1v.v2 );
-    resv[0] = dist[0];
-    resv[1] = dist[1];
+    v2dfunion resv[2] = { dist[0], dist[1] };
     FastApproxLog4Val(dist);
     resv[0].v2 *= dist[0].v2;
     resv[1].v2 *= dist[1].v2;
@@ -399,54 +445,55 @@ static void VizGeorefSpline2DBase_func4( double* res,
 }
 #endif // defined(USE_OPTIMIZED_VizGeorefSpline2DBase_func4)
 
-int VizGeorefSpline2D::solve(void)
+int VizGeorefSpline2D::solve()
 {
-    int r, c;
-    int p;
-
-    //	No points at all
-    if ( _nof_points < 1 )
+    // No points at all.
+    if( _nof_points < 1 )
     {
         type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
-        return(0);
+        return 0;
     }
 
-    // Only one point
-    if ( _nof_points == 1 )
+    // Only one point.
+    if( _nof_points == 1 )
     {
         type = VIZ_GEOREF_SPLINE_ONE_POINT;
-        return(1);
+        return 1;
     }
-    // Just 2 points - it is necessarily 1D case
-    if ( _nof_points == 2 )
+    // Just 2 points - it is necessarily 1D case.
+    if( _nof_points == 2 )
     {
         _dx = x[1] - x[0];
         _dy = y[1] - y[0];
-        double fact = 1.0 / ( _dx * _dx + _dy * _dy );
+        const double fact = 1.0 / ( _dx * _dx + _dy * _dy );
         _dx *= fact;
         _dy *= fact;
 
         type = VIZ_GEOREF_SPLINE_TWO_POINTS;
-        return(2);
+        return 2;
     }
 
     // More than 2 points - first we have to check if it is 1D or 2D case
 
-    double xmax = x[0], xmin = x[0], ymax = y[0], ymin = y[0];
-    double delx, dely;
-    double xx, yy;
-    double sumx = 0.0f, sumy= 0.0f, sumx2 = 0.0f, sumy2 = 0.0f, sumxy = 0.0f;
-    double SSxx, SSyy, SSxy;
-
-    for ( p = 0; p < _nof_points; p++ )
+    double xmax = x[0];
+    double xmin = x[0];
+    double ymax = y[0];
+    double ymin = y[0];
+    double sumx = 0.0;
+    double sumy = 0.0;
+    double sumx2 = 0.0;
+    double sumy2 = 0.0;
+    double sumxy = 0.0;
+
+    for( int p = 0; p < _nof_points; p++ )
     {
-        xx = x[p];
-        yy = y[p];
+        const double xx = x[p];
+        const double yy = y[p];
 
-        xmax = MAX( xmax, xx );
-        xmin = MIN( xmin, xx );
-        ymax = MAX( ymax, yy );
-        ymin = MIN( ymin, yy );
+        xmax = std::max(xmax, xx);
+        xmin = std::min(xmin, xx);
+        ymax = std::max(ymax, yy);
+        ymin = std::min(ymin, yy);
 
         sumx  += xx;
         sumx2 += xx * xx;
@@ -454,43 +501,41 @@ int VizGeorefSpline2D::solve(void)
         sumy2 += yy * yy;
         sumxy += xx * yy;
     }
-    delx = xmax - xmin;
-    dely = ymax - ymin;
+    const double delx = xmax - xmin;
+    const double dely = ymax - ymin;
 
-    SSxx = sumx2 - sumx * sumx / _nof_points;
-    SSyy = sumy2 - sumy * sumy / _nof_points;
-    SSxy = sumxy - sumx * sumy / _nof_points;
+    const double SSxx = sumx2 - sumx * sumx / _nof_points;
+    const double SSyy = sumy2 - sumy * sumy / _nof_points;
+    const double SSxy = sumxy - sumx * sumy / _nof_points;
 
-    if ( delx < 0.001 * dely || dely < 0.001 * delx ||
-         fabs ( SSxy * SSxy / ( SSxx * SSyy ) ) > 0.99 )
+    if( delx < 0.001 * dely || dely < 0.001 * delx ||
+        fabs ( SSxy * SSxy / ( SSxx * SSyy ) ) > 0.99 )
     {
-        int p1;
-
         type = VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL;
 
         _dx = _nof_points * sumx2 - sumx * sumx;
         _dy = _nof_points * sumy2 - sumy * sumy;
-        double fact = 1.0 / sqrt( _dx * _dx + _dy * _dy );
+        const double fact = 1.0 / sqrt( _dx * _dx + _dy * _dy );
         _dx *= fact;
         _dy *= fact;
 
-        for ( p = 0; p < _nof_points; p++ )
+        for( int p = 0; p < _nof_points; p++ )
         {
-            double dxp = x[p] - x[0];
-            double dyp = y[p] - y[0];
+            const double dxp = x[p] - x[0];
+            const double dyp = y[p] - y[0];
             u[p] = _dx * dxp + _dy * dyp;
             unused[p] = 1;
         }
 
-        for ( p = 0; p < _nof_points; p++ )
+        for( int p = 0; p < _nof_points; p++ )
         {
             int min_index = -1;
-            double min_u = 0;
-            for ( p1 = 0; p1 < _nof_points; p1++ )
+            double min_u = 0.0;
+            for( int p1 = 0; p1 < _nof_points; p1++ )
             {
-                if ( unused[p1] )
+                if( unused[p1] )
                 {
-                    if ( min_index < 0 || u[p1] < min_u )
+                    if( min_index < 0 || u[p1] < min_u )
                     {
                         min_index = p1;
                         min_u = u[p1];
@@ -501,22 +546,25 @@ int VizGeorefSpline2D::solve(void)
             unused[min_index] = 0;
         }
 
-        return(3);
+        return 3;
     }
 
     type = VIZ_GEOREF_SPLINE_FULL;
-    // Make the necessary memory allocations
+    // Make the necessary memory allocations.
 
     _nof_eqs = _nof_points + 3;
 
     if( _nof_eqs > INT_MAX / _nof_eqs )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Too many coefficients. Computation aborted.");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Too many coefficients. Computation aborted.");
         return 0;
     }
 
-    double* _AA = ( double * )VSI_CALLOC_VERBOSE( _nof_eqs * _nof_eqs, sizeof( double ) );
-    double* _Ainv = ( double * )VSI_CALLOC_VERBOSE( _nof_eqs * _nof_eqs, sizeof( double ) );
+    double* _AA = static_cast<double *>(
+        VSI_CALLOC_VERBOSE(_nof_eqs * _nof_eqs, sizeof(double)));
+    double* _Ainv = static_cast< double *>(
+        VSI_CALLOC_VERBOSE(_nof_eqs * _nof_eqs, sizeof(double)));
 
     if( _AA == NULL || _Ainv == NULL )
     {
@@ -525,199 +573,221 @@ int VizGeorefSpline2D::solve(void)
         return 0;
     }
 
-    // Calc the values of the matrix A
-    for ( r = 0; r < 3; r++ )
-        for ( c = 0; c < 3; c++ )
-            A(r,c) = 0.0;
+    // Calc the values of the matrix A.
+    for( int r = 0; r < 3; r++ )
+        for( int c = 0; c < 3; c++ )
+            A(r, c) = 0.0;
 
-    for ( c = 0; c < _nof_points; c++ )
+    for( int c = 0; c < _nof_points; c++ )
     {
-        A(0,c+3) = 1.0;
-        A(1,c+3) = x[c];
-        A(2,c+3) = y[c];
+        A(0, c+3) = 1.0;
+        A(1, c+3) = x[c];
+        A(2, c+3) = y[c];
 
-        A(c+3,0) = 1.0;
-        A(c+3,1) = x[c];
-        A(c+3,2) = y[c];
+        A(c+3, 0) = 1.0;
+        A(c+3, 1) = x[c];
+        A(c+3, 2) = y[c];
     }
 
-    for ( r = 0; r < _nof_points; r++ )
-        for ( c = r; c < _nof_points; c++ )
+    for( int r = 0; r < _nof_points; r++ )
+        for( int c = r; c < _nof_points; c++ )
         {
-            A(r+3,c+3) = VizGeorefSpline2DBase_func( x[r], y[r], x[c], y[c] );
-            if ( r != c )
-                A(c+3,r+3 ) = A(r+3,c+3);
+            A(r+3, c+3) = VizGeorefSpline2DBase_func( x[r], y[r], x[c], y[c] );
+            if( r != c )
+                A(c+3, r+3) = A(r+3, c+3);
         }
 
 #if VIZ_GEOREF_SPLINE_DEBUG
 
-    for ( r = 0; r < _nof_eqs; r++ )
+    for( r = 0; r < _nof_eqs; r++ )
     {
-        for ( c = 0; c < _nof_eqs; c++ )
-            fprintf(stderr, "%f", A(r,c));
-        fprintf(stderr, "\n");
+        for( c = 0; c < _nof_eqs; c++ )
+            fprintf(stderr, "%f", A(r, c));/*ok*/
+        fprintf(stderr, "\n");/*ok*/
     }
 
 #endif
 
-    int ret  = 4;
+    int ret = 4;
 #ifdef HAVE_ARMADILLO
     try
     {
-        arma::mat matA(_AA,_nof_eqs,_nof_eqs,false);
+        arma::mat matA(_AA, _nof_eqs, _nof_eqs,false);
         arma::mat matRHS(_nof_eqs, _nof_vars);
-        int row, col;
-        for(row = 0; row < _nof_eqs; row++)
-            for(col = 0; col < _nof_vars; col++)
+        for( int row = 0; row < _nof_eqs; row++ )
+            for( int col = 0; col < _nof_vars; col++ )
                 matRHS.at(row, col) = rhs[col][row];
         arma::mat matCoefs(_nof_vars, _nof_eqs);
 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
 #endif
+
+#if ARMA_VERSION_MAJOR > 6 || (ARMA_VERSION_MAJOR == 6 && ARMA_VERSION_MINOR >= 500 )
+        // Perhaps available in earlier versions, but didn't check
+        if( !arma::solve(matCoefs, matA, matRHS, arma::solve_opts::no_approx) )
+#else
         if( !arma::solve(matCoefs, matA, matRHS) )
+#endif
+
 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
 #pragma GCC diagnostic pop
 #endif
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "There is a problem inverting the interpolation matrix.");
             ret = 0;
         }
         else
         {
-            for(row = 0; row < _nof_eqs; row++)
-                for(col = 0; col < _nof_vars; col++)
+            for( int row = 0; row < _nof_eqs; row++ )
+                for( int col = 0; col < _nof_vars; col++ )
                     coef[col][row] = matCoefs.at(row, col);
         }
     }
     catch(...)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "There is a problem inverting the interpolation matrix.");
         ret = 0;
     }
-#else
-    int status = matrixInvert( _nof_eqs, _AA, _Ainv );
-
-    if ( !status )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "There is a problem inverting the interpolation matrix.");
-        ret = 0;
-    }
-    else
+    if( ret == 0 )
+#endif
     {
-        // calc the coefs
-        for ( int v = 0; v < _nof_vars; v++ )
-            for ( r = 0; r < _nof_eqs; r++ )
-            {
-                coef[v][r] = 0.0;
-                for ( c = 0; c < _nof_eqs; c++ )
-                    coef[v][r] += Ainv(r,c) * rhs[v][c];
-            }
+        const int status = matrixInvert( _nof_eqs, _AA, _Ainv );
+
+        if( !status )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "There is a problem inverting the interpolation matrix.");
+            ret = 0;
+        }
+        else
+        {
+            ret = 4;
+            // calc the coefs
+            for( int v = 0; v < _nof_vars; v++ )
+                for( int r = 0; r < _nof_eqs; r++ )
+                {
+                    coef[v][r] = 0.0;
+                    for( int c = 0; c < _nof_eqs; c++ )
+                        coef[v][r] += Ainv(r, c) * rhs[v][c];
+                }
+        }
     }
-#endif
 
     VSIFree(_AA);
     VSIFree(_Ainv);
 
-    return(ret);
+    return ret;
 }
 
-int VizGeorefSpline2D::get_point( const double Px, const double Py, double *vars )
+int VizGeorefSpline2D::get_point( const double Px, const double Py,
+                                  double *vars )
 {
-	int v, r;
-	double tmp, Pu;
-	double fact;
-	int leftP=0, rightP=0, found = 0;
-
-	switch ( type )
-	{
-	case VIZ_GEOREF_SPLINE_ZERO_POINTS :
-		for ( v = 0; v < _nof_vars; v++ )
-			vars[v] = 0.0;
-		break;
-	case VIZ_GEOREF_SPLINE_ONE_POINT :
-		for ( v = 0; v < _nof_vars; v++ )
-			vars[v] = rhs[v][3];
-		break;
-	case VIZ_GEOREF_SPLINE_TWO_POINTS :
-		fact = _dx * ( Px - x[0] ) + _dy * ( Py - y[0] );
-		for ( v = 0; v < _nof_vars; v++ )
-			vars[v] = ( 1 - fact ) * rhs[v][3] + fact * rhs[v][4];
-		break;
-	case VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL :
-		Pu = _dx * ( Px - x[0] ) + _dy * ( Py - y[0] );
-		if ( Pu <= u[index[0]] )
-		{
-			leftP = index[0];
-			rightP = index[1];
-		}
-		else if ( Pu >= u[index[_nof_points-1]] )
-		{
-			leftP = index[_nof_points-2];
-			rightP = index[_nof_points-1];
-		}
-		else
-		{
-			for ( r = 1; !found && r < _nof_points; r++ )
-			{
-				leftP = index[r-1];
-				rightP = index[r];
-				if ( Pu >= u[leftP] && Pu <= u[rightP] )
-					found = 1;
-			}
-		}
-
-		fact = ( Pu - u[leftP] ) / ( u[rightP] - u[leftP] );
-		for ( v = 0; v < _nof_vars; v++ )
-			vars[v] = ( 1.0 - fact ) * rhs[v][leftP+3] +
-			fact * rhs[v][rightP+3];
-		break;
-	case VIZ_GEOREF_SPLINE_FULL :
-    {
-        double Pxy[2] = { Px, Py };
-        for ( v = 0; v < _nof_vars; v++ )
+    switch( type )
+    {
+    case VIZ_GEOREF_SPLINE_ZERO_POINTS:
+    {
+        for( int v = 0; v < _nof_vars; v++ )
+            vars[v] = 0.0;
+        break;
+    }
+    case VIZ_GEOREF_SPLINE_ONE_POINT:
+    {
+        for( int v = 0; v < _nof_vars; v++ )
+            vars[v] = rhs[v][3];
+        break;
+    }
+    case VIZ_GEOREF_SPLINE_TWO_POINTS:
+    {
+        const double fact = _dx * ( Px - x[0] ) + _dy * ( Py - y[0] );
+        for( int v = 0; v < _nof_vars; v++ )
+            vars[v] = ( 1 - fact ) * rhs[v][3] + fact * rhs[v][4];
+        break;
+    }
+    case VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL:
+    {
+        int leftP = 0;
+        int rightP = 0;
+        const double Pu = _dx * ( Px - x[0] ) + _dy * ( Py - y[0] );
+        if( Pu <= u[index[0]] )
+        {
+            leftP = index[0];
+            rightP = index[1];
+        }
+        else if( Pu >= u[index[_nof_points-1]] )
+        {
+            leftP = index[_nof_points-2];
+            rightP = index[_nof_points-1];
+        }
+        else
+        {
+            for( int r = 1; r < _nof_points; r++ )
+            {
+                leftP = index[r-1];
+                rightP = index[r];
+                if( Pu >= u[leftP] && Pu <= u[rightP] )
+                    break;  // Found.
+            }
+        }
+
+        const double fact = ( Pu - u[leftP] ) / ( u[rightP] - u[leftP] );
+        for( int v = 0; v < _nof_vars; v++ )
+            vars[v] = ( 1.0 - fact ) * rhs[v][leftP+3] +
+                fact * rhs[v][rightP+3];
+        break;
+    }
+    case VIZ_GEOREF_SPLINE_FULL:
+    {
+        const double Pxy[2] = { Px, Py };
+        for( int v = 0; v < _nof_vars; v++ )
             vars[v] = coef[v][0] + coef[v][1] * Px + coef[v][2] * Py;
 
-        for ( r = 0; r < (_nof_points & (~3)); r+=4 )
+        int r = 0;  // Used after for.
+        for( ; r < (_nof_points & (~3)); r+=4 )
         {
-            double dfTmp[4];
+            double dfTmp[4] = {};
             VizGeorefSpline2DBase_func4( dfTmp, Pxy, &x[r], &y[r] );
-            for ( v= 0; v < _nof_vars; v++ )
+            for( int v = 0; v < _nof_vars; v++ )
                 vars[v] += coef[v][r+3] * dfTmp[0] +
                         coef[v][r+3+1] * dfTmp[1] +
                         coef[v][r+3+2] * dfTmp[2] +
                         coef[v][r+3+3] * dfTmp[3];
         }
-        for ( ; r < _nof_points; r++ )
+        for( ; r < _nof_points; r++ )
         {
-            tmp = VizGeorefSpline2DBase_func( Px, Py, x[r], y[r] );
-            for ( v= 0; v < _nof_vars; v++ )
+            const double tmp = VizGeorefSpline2DBase_func( Px, Py, x[r], y[r] );
+            for( int v= 0; v < _nof_vars; v++ )
                 vars[v] += coef[v][r+3] * tmp;
         }
         break;
     }
-	case VIZ_GEOREF_SPLINE_POINT_WAS_ADDED :
-		fprintf(stderr, " A point was added after the last solve\n");
-		fprintf(stderr, " NO interpolation - return values are zero\n");
-		for ( v = 0; v < _nof_vars; v++ )
-			vars[v] = 0.0;
-		return(0);
-		break;
-	case VIZ_GEOREF_SPLINE_POINT_WAS_DELETED :
-		fprintf(stderr, " A point was deleted after the last solve\n");
-		fprintf(stderr, " NO interpolation - return values are zero\n");
-		for ( v = 0; v < _nof_vars; v++ )
-			vars[v] = 0.0;
-		return(0);
-		break;
-	default :
-		return(0);
-		break;
-	}
-	return(1);
+    case VIZ_GEOREF_SPLINE_POINT_WAS_ADDED:
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "A point was added after the last solve."
+                 " NO interpolation - return values are zero");
+        for( int v = 0; v < _nof_vars; v++ )
+            vars[v] = 0.0;
+        return 0;
+        // break;  // TODO(schwehr): Remove this assuming no compiler needs it.
+    }
+    case VIZ_GEOREF_SPLINE_POINT_WAS_DELETED:
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "A point was deleted after the last solve."
+                 " NO interpolation - return values are zero");
+        for( int v = 0; v < _nof_vars; v++ )
+            vars[v] = 0.0;
+        return 0;
+        // break;  // TODO(schwehr): Remove this assuming no compiler needs it.
+    }
+    default:
+    {
+        return 0;
+        // break;  // TODO(schwehr): Remove this assuming no compiler needs it.
+    }
+    }
+    return 1;
 }
 
-#ifndef HAVE_ARMADILLO
 static int matrixInvert( int N, double input[], double output[] )
 {
     // Receives an array of dimension NxN as input.  This is passed as a one-
@@ -732,126 +802,122 @@ static int matrixInvert( int N, double input[], double output[] )
     // We need to have a temporary array of size N x 2N.  We'll refer to the
     // "left" and "right" halves of this array.
 
-    int row, col;
-
-#if 0
-    fprintf(stderr, "Matrix Inversion input matrix (N=%d)\n", N);
-    for ( row=0; row<N; row++ )
+#if DEBUG_VERBOSE
+    fprintf(stderr, "Matrix Inversion input matrix (N=%d)\n", N);/*ok*/
+    for( int row = 0; row < N; row++ )
     {
-        for ( col=0; col<N; col++ )
+        for( int col = 0; col < N; col++ )
         {
-            fprintf(stderr, "%5.2f ", input[row*N + col ]  );
+            fprintf(stderr, "%5.2f ", input[row*N + col]);/*ok*/
         }
-        fprintf(stderr, "\n");
+        fprintf(stderr, "\n");/*ok*/
     }
 #endif
 
-    int tempSize = 2 * N * N;
-    double* temp = (double*) new double[ tempSize ];
-    double ftemp;
-
-    if (temp == NULL) {
+    const int tempSize = 2 * N * N;
+    double* temp = new double[tempSize];
 
-        CPLError(CE_Failure, CPLE_AppDefined, "matrixInvert(): ERROR - memory allocation failed.");
+    if( temp == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "matrixInvert(): ERROR - memory allocation failed.");
         return false;
     }
 
     // First create a double-width matrix with the input array on the left
     // and the identity matrix on the right.
 
-    for ( row=0; row<N; row++ )
+    for( int row = 0; row < N; row++ )
     {
-        for ( col=0; col<N; col++ )
+        for( int col = 0; col<N; col++ )
         {
             // Our index into the temp array is X2 because it's twice as wide
             // as the input matrix.
 
-            temp[ 2*row*N + col ] = input[ row*N+col ];	// left = input matrix
-            temp[ 2*row*N + col + N ] = 0.0f;			// right = 0
+            temp[ 2*row*N + col ] = input[ row*N+col ];  // left = input matrix
+            temp[ 2*row*N + col + N ] = 0.0f;            // right = 0
         }
-        temp[ 2*row*N + row + N ] = 1.0f;		// 1 on the diagonal of RHS
+        temp[ 2*row*N + row + N ] = 1.0f;  // 1 on the diagonal of RHS
     }
 
     // Now perform row-oriented operations to convert the left hand side
     // of temp to the identity matrix.  The inverse of input will then be
     // on the right.
 
-    int max;
-    int k=0;
-    for (k = 0; k < N; k++)
+    int max = 0;
+    int k = 0;
+    for( k = 0; k < N; k++ )
     {
-        if (k+1 < N)	// if not on the last row
+        if( k + 1 < N )  // If not on the last row.
         {
             max = k;
-            for (row = k+1; row < N; row++) // find the maximum element
+            for( int row = k + 1; row < N; row++ )  // Find the maximum element.
             {
-                if (fabs( temp[row*2*N + k] ) > fabs( temp[max*2*N + k] ))
+                if( fabs( temp[row*2*N + k] ) > fabs( temp[max*2*N + k] ) )
                 {
                     max = row;
                 }
             }
 
-            if (max != k)	// swap all the elements in the two rows
+            if( max != k )  // Swap all the elements in the two rows.
             {
-                for (col=k; col<2*N; col++)
+                for( int col = k; col < 2 * N; col++ )
                 {
-                    ftemp = temp[k*2*N + col];
-                    temp[k*2*N + col] = temp[max*2*N + col];
-                    temp[max*2*N + col] = ftemp;
+                    std::swap(temp[k*2*N + col], temp[max*2*N + col]);
                 }
             }
         }
 
-        ftemp = temp[ k*2*N + k ];
-        if ( ftemp == 0.0f ) // matrix cannot be inverted
+        const double ftemp = temp[k*2*N + k];
+        if( ftemp == 0.0f )  // Matrix cannot be inverted.
         {
             delete[] temp;
             return false;
         }
 
-        for ( col=k; col<2*N; col++ )
+        for( int col = k; col < 2 * N; col++ )
         {
-            temp[ k*2*N + col ] /= ftemp;
+            temp[k*2*N + col] /= ftemp;
         }
 
-        int i2 = k*2*N ;
-        for ( row=0; row<N; row++ )
+        const int i2 = k * 2 * N;
+        for( int row = 0; row < N; row++ )
         {
-            if ( row != k )
+            if( row != k )
             {
-                int i1 = row*2*N;
-                ftemp = temp[ i1 + k ];
-                for ( col=k; col<2*N; col++ )
+                const int i1 = row * 2 * N;
+                const double ftemp2 = temp[ i1 + k ];
+                for( int col = k; col < 2*N; col++ )
                 {
-                    temp[ i1 + col ] -= ftemp * temp[ i2 + col ];
+                    temp[i1 + col] -= ftemp2 * temp[i2 + col];
                 }
             }
         }
     }
 
-    // Retrieve inverse from the right side of temp
-
-    for (row = 0; row < N; row++)
+    // Retrieve inverse from the right side of temp.
+    for( int row = 0; row < N; row++ )
     {
-        for (col = 0; col < N; col++)
+        for( int col = 0; col < N; col++ )
         {
             output[row*N + col] = temp[row*2*N + col + N ];
         }
     }
+    delete [] temp;
 
-#if 0
-    fprintf(stderr, "Matrix Inversion result matrix:\n");
-    for ( row=0; row<N; row++ )
+#if DEBUG_VERBOSE
+    fprintf(stderr, "Matrix Inversion result matrix:\n");/*ok*/
+    for( int row = 0; row < N; row++ )
     {
-        for ( col=0; col<N; col++ )
+        for( int col = 0; col < N; col++ )
         {
-            fprintf(stderr, "%5.2f ", output[row*N + col ]  );
+            fprintf(stderr, "%5.2f ", output[row*N + col]);/*ok*/
         }
-        fprintf(stderr, "\n");
+        fprintf(stderr, "\n");/*ok*/
     }
 #endif
 
-    delete [] temp;       // free memory
     return true;
 }
-#endif
+
+/*! @endcond */
diff --git a/alg/thinplatespline.h b/alg/thinplatespline.h
index 91ab052..880af25 100644
--- a/alg/thinplatespline.h
+++ b/alg/thinplatespline.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: thinplatespline.h 33715 2016-03-13 08:52:06Z goatbar $
+ * $Id: thinplatespline.h 36411 2016-11-21 22:03:48Z rouault $
  *
  * Project:  GDAL Warp API
  * Purpose:  Declarations for 2D Thin Plate Spline transformer.
@@ -30,20 +30,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef THINPLATESPLINE_H_INCLUDED
+#define THINPLATESPLINE_H_INCLUDED
+
+#ifndef DOXYGEN_SKIP
+
 #include "gdal_alg.h"
 #include "cpl_conv.h"
 
 typedef enum
 {
-	VIZ_GEOREF_SPLINE_ZERO_POINTS,
-	VIZ_GEOREF_SPLINE_ONE_POINT,
-	VIZ_GEOREF_SPLINE_TWO_POINTS,
-	VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL,
-	VIZ_GEOREF_SPLINE_FULL,
-
-	VIZ_GEOREF_SPLINE_POINT_WAS_ADDED,
-	VIZ_GEOREF_SPLINE_POINT_WAS_DELETED
-
+    VIZ_GEOREF_SPLINE_ZERO_POINTS,
+    VIZ_GEOREF_SPLINE_ONE_POINT,
+    VIZ_GEOREF_SPLINE_TWO_POINTS,
+    VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL,
+    VIZ_GEOREF_SPLINE_FULL,
+
+    VIZ_GEOREF_SPLINE_POINT_WAS_ADDED,
+    VIZ_GEOREF_SPLINE_POINT_WAS_DELETED
 } vizGeorefInterType;
 
 //#define VIZ_GEOREF_SPLINE_MAX_POINTS 40
@@ -55,7 +59,7 @@ class VizGeorefSpline2D
 
   public:
 
-    VizGeorefSpline2D(int nof_vars = 1) :
+    explicit VizGeorefSpline2D(int nof_vars = 1) :
         type(VIZ_GEOREF_SPLINE_ZERO_POINTS),
         _nof_vars(nof_vars),
         _nof_points(0),
@@ -116,32 +120,32 @@ class VizGeorefSpline2D
     }
 
     void dump_data_points()
-	{
-            for ( int i = 0; i < _nof_points; i++ )
-            {
-                fprintf(stderr, "X = %f Y = %f Vars = ", x[i], y[i]);
-                for ( int v = 0; v < _nof_vars; v++ )
-                    fprintf(stderr, "%f ", rhs[v][i+3]);
-                fprintf(stderr, "\n");
-            }
-	}
+    {
+        for ( int i = 0; i < _nof_points; i++ )
+        {
+            fprintf(stderr, "X = %f Y = %f Vars = ", x[i], y[i]);
+            for ( int v = 0; v < _nof_vars; v++ )
+                fprintf(stderr, "%f ", rhs[v][i+3]);
+            fprintf(stderr, "\n");
+        }
+    }
 
     int delete_list()
-	{
-            _nof_points = 0;
-            type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
-            if ( _AA )
-            {
-                CPLFree(_AA);
-                _AA = NULL;
-            }
-            if ( _Ainv )
-            {
-                CPLFree(_Ainv);
-                _Ainv = NULL;
-            }
-            return _nof_points;
-	}
+    {
+        _nof_points = 0;
+        type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
+        if ( _AA )
+        {
+            CPLFree(_AA);
+            _AA = NULL;
+        }
+        if ( _Ainv )
+        {
+            CPLFree(_Ainv);
+            _Ainv = NULL;
+        }
+        return _nof_points;
+    }
 #endif
 
     bool add_point( const double Px, const double Py, const double *Pvars );
@@ -184,5 +188,9 @@ class VizGeorefSpline2D
     int *index; // [VIZ_GEOREF_SPLINE_MAX_POINTS];
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(VizGeorefSpline2D);
+    CPL_DISALLOW_COPY_ASSIGN(VizGeorefSpline2D)
 };
+
+#endif /* #ifndef DOXYGEN_SKIP */
+
+#endif /* THINPLATESPLINE_H_INCLUDED */
diff --git a/apps/GNUmakefile b/apps/GNUmakefile
index a87cd0f..d48f96f 100644
--- a/apps/GNUmakefile
+++ b/apps/GNUmakefile
@@ -1,17 +1,17 @@
 # We get a full absolute path to the tree in this case so that when we
 # generate the various paths in the local gdal-config file they will work
-# from anywhere in the filesystem. 
+# from anywhere in the filesystem.
 
 include ../GDALmake.opt
 
-CPPFLAGS :=	-I$(GDAL_ROOT)/frmts/vrt $(CPPFLAGS) $(JSON_INCLUDE) -I$(GDAL_ROOT)/ogr/ogrsf_frmts/geojson
+CPPFLAGS :=	-I$(GDAL_ROOT)/frmts/vrt $(CPPFLAGS) $(JSON_INCLUDE) -I$(GDAL_ROOT)/ogr/ogrsf_frmts/geojson -I$(GDAL_ROOT)/ogr/ogrsf_frmts/generic
 LNK_FLAGS :=	$(LDFLAGS)
 DEP_LIBS =	$(EXE_DEP_LIBS) $(XTRAOBJ)
 
 BIN_LIST =	gdalinfo$(EXE) gdalserver$(EXE) gdal_translate$(EXE) \
 		gdaladdo$(EXE) gdalwarp$(EXE) nearblack$(EXE) gdalmanage$(EXE) \
 		gdalenhance$(EXE) gdaltransform$(EXE) gdaldem$(EXE) \
-		gdallocationinfo$(EXE) gdalsrsinfo$(EXE) 
+		gdallocationinfo$(EXE) gdalsrsinfo$(EXE)
 
 OBJ = commonutils.o gdalinfo_lib.o gdal_translate_lib.o gdalwarp_lib.o ogr2ogr_lib.o \
 	gdaldem_lib.o nearblack_lib.o gdal_grid_lib.o gdal_rasterize_lib.o gdalbuildvrt_lib.o
@@ -192,7 +192,7 @@ gdal-config:	gdal-config.in ../GDALmake.opt ./GNUmakefile ../VERSION
 	echo 'CONFIG_CFLAGS="-I$(GDAL_ROOT)/port -I$(GDAL_ROOT)/gcore -I$(GDAL_ROOT)/alg -I$(GDAL_ROOT)/ogr -I$(GDAL_ROOT)/ogr/ogrsf_frmts -I$(GDAL_ROOT)/frmts/vrt -I$(GDAL_ROOT)/apps"' >> gdal-config
 	echo 'CONFIG_DATA="$(GDAL_ROOT)/data"' >> gdal-config
 	echo 'CONFIG_VERSION="'`cat ../VERSION`'"' >> gdal-config
-	echo 'CONFIG_OGR_ENABLED=yes' >> gdal-config
+	echo 'CONFIG_OGR_ENABLED=yes' >> gdal-config  # Deprecated.  Always true.
 	echo 'CONFIG_GNM_ENABLED=$(GNM_ENABLED)' >> gdal-config
 	echo 'CONFIG_FORMATS="$(GDAL_FORMATS)"' >> gdal-config
 	cat gdal-config.in >> gdal-config
@@ -207,7 +207,7 @@ gdal-config-inst:	gdal-config.in ../GDALmake.opt ./GNUmakefile ../VERSION
 	echo 'CONFIG_CFLAGS="-I$(INST_INCLUDE)"' >> gdal-config-inst
 	echo 'CONFIG_DATA="$(INST_DATA)"' >> gdal-config-inst
 	echo 'CONFIG_VERSION="'`cat ../VERSION`'"' >> gdal-config-inst
-	echo 'CONFIG_OGR_ENABLED=yes' >> gdal-config-inst
+	echo 'CONFIG_OGR_ENABLED=yes' >> gdal-config-inst  # Deprecated.  Always true.
 	echo 'CONFIG_GNM_ENABLED=$(GNM_ENABLED)' >> gdal-config-inst
 	echo 'CONFIG_FORMATS="$(GDAL_FORMATS)"' >> gdal-config-inst
 	cat gdal-config.in >> gdal-config-inst
diff --git a/apps/commonutils.cpp b/apps/commonutils.cpp
index b067f2c..89b1980 100644
--- a/apps/commonutils.cpp
+++ b/apps/commonutils.cpp
@@ -1,133 +1,144 @@
-/******************************************************************************
- * $Id: commonutils.cpp 33921 2016-04-08 20:02:49Z rouault $
- *
- * Project:  GDAL Utilities
- * Purpose:  Common utility routines
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "commonutils.h"
-#include "cpl_string.h"
-#include "gdal.h"
-
-CPL_CVSID("$Id: commonutils.cpp 33921 2016-04-08 20:02:49Z rouault $");
-
-/* -------------------------------------------------------------------- */
-/*                   DoesDriverHandleExtension()                        */
-/* -------------------------------------------------------------------- */
-
-static bool DoesDriverHandleExtension( GDALDriverH hDriver, const char* pszExt )
-{
-    bool bRet = false;
-    const char* pszDriverExtensions = 
-        GDALGetMetadataItem( hDriver, GDAL_DMD_EXTENSIONS, NULL );
-    if( pszDriverExtensions )
-    {
-        char** papszTokens = CSLTokenizeString( pszDriverExtensions );
-        for(int j=0; papszTokens[j]; j++)
-        {
-            if( EQUAL(pszExt, papszTokens[j]) )
-            {
-                bRet = true;
-                break;
-            }
-        }
-        CSLDestroy(papszTokens);
-    }
-    return bRet;
-}
-
-/* -------------------------------------------------------------------- */
-/*                      CheckExtensionConsistency()                     */
-/*                                                                      */
-/*      Check that the target file extension is consistent with the     */
-/*      requested driver. Actually, we only warn in cases where the     */
-/*      inconsistency is blatant (use of an extension declared by one   */
-/*      or several drivers, and not by the selected one)                */
-/* -------------------------------------------------------------------- */
-
-void CheckExtensionConsistency(const char* pszDestFilename,
-                               const char* pszDriverName)
-{
-
-    CPLString osExt = CPLGetExtension(pszDestFilename);
-    if (osExt.size())
-    {
-        GDALDriverH hThisDrv = GDALGetDriverByName(pszDriverName);
-        if( hThisDrv != NULL && DoesDriverHandleExtension(hThisDrv, osExt) )
-            return;
-
-        int nDriverCount = GDALGetDriverCount();
-        CPLString osConflictingDriverList;
-        for(int i=0;i<nDriverCount;i++)
-        {
-            GDALDriverH hDriver = GDALGetDriver(i);
-            if( hDriver != hThisDrv && DoesDriverHandleExtension(hDriver, osExt) )
-            {
-                if (osConflictingDriverList.size())
-                    osConflictingDriverList += ", ";
-                osConflictingDriverList += GDALGetDriverShortName(hDriver);
-            }
-        }
-        if (osConflictingDriverList.size())
-        {
-            fprintf(stderr,
-                    "Warning: The target file has a '%s' extension, which is normally used by the %s driver%s,\n"
-                    "but the requested output driver is %s. Is it really what you want ?\n",
-                    osExt.c_str(),
-                    osConflictingDriverList.c_str(),
-                    strchr(osConflictingDriverList.c_str(), ',') ? "s" : "",
-                    pszDriverName);
-        }
-    }
-}
-
-/* -------------------------------------------------------------------- */
-/*                        EarlySetConfigOptions()                       */
-/* -------------------------------------------------------------------- */
-
-void EarlySetConfigOptions( int argc, char ** argv )
-{
-    /* Must process some config options before GDALAllRegister() or OGRRegisterAll(), */
-    /* but we can't call GDALGeneralCmdLineProcessor() or OGRGeneralCmdLineProcessor(), */
-    /* because it needs the drivers to be registered for the --format or --formats options */
-    for( int i = 1; i < argc; i++ )
-    {
-        if( EQUAL(argv[i],"--config") && i + 2 < argc &&
-            (EQUAL(argv[i + 1], "GDAL_SKIP") ||
-             EQUAL(argv[i + 1], "GDAL_DRIVER_PATH") ||
-             EQUAL(argv[i + 1], "OGR_SKIP") ||
-             EQUAL(argv[i + 1], "OGR_DRIVER_PATH")) )
-        {
-            CPLSetConfigOption( argv[i+1], argv[i+2] );
-
-            i += 2;
-        }
-        else if( EQUAL(argv[i],"--debug") && i + 1 < argc )
-        {
-            CPLSetConfigOption( "CPL_DEBUG", argv[i+1] );
-            i += 1;
-        }
-    }
-}
+/******************************************************************************
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  Common utility routines
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2011-2012, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "commonutils.h"
+
+#include <cstdio>
+#include <cstring>
+
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal.h"
+
+CPL_CVSID("$Id: commonutils.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+/* -------------------------------------------------------------------- */
+/*                   DoesDriverHandleExtension()                        */
+/* -------------------------------------------------------------------- */
+
+static bool DoesDriverHandleExtension( GDALDriverH hDriver, const char* pszExt )
+{
+    bool bRet = false;
+    const char* pszDriverExtensions =
+        GDALGetMetadataItem( hDriver, GDAL_DMD_EXTENSIONS, NULL );
+    if( pszDriverExtensions )
+    {
+        char** papszTokens = CSLTokenizeString( pszDriverExtensions );
+        for( int j = 0; papszTokens[j]; j++ )
+        {
+            if( EQUAL(pszExt, papszTokens[j]) )
+            {
+                bRet = true;
+                break;
+            }
+        }
+        CSLDestroy(papszTokens);
+    }
+    return bRet;
+}
+
+/* -------------------------------------------------------------------- */
+/*                      CheckExtensionConsistency()                     */
+/*                                                                      */
+/*      Check that the target file extension is consistent with the     */
+/*      requested driver. Actually, we only warn in cases where the     */
+/*      inconsistency is blatant (use of an extension declared by one   */
+/*      or several drivers, and not by the selected one)                */
+/* -------------------------------------------------------------------- */
+
+void CheckExtensionConsistency(const char* pszDestFilename,
+                               const char* pszDriverName)
+{
+
+    CPLString osExt = CPLGetExtension(pszDestFilename);
+    if( !osExt.empty() )
+    {
+        GDALDriverH hThisDrv = GDALGetDriverByName(pszDriverName);
+        if( hThisDrv != NULL && DoesDriverHandleExtension(hThisDrv, osExt) )
+            return;
+
+        const int nDriverCount = GDALGetDriverCount();
+        CPLString osConflictingDriverList;
+        for( int i = 0; i < nDriverCount; i++ )
+        {
+            GDALDriverH hDriver = GDALGetDriver(i);
+            if( hDriver != hThisDrv &&
+                DoesDriverHandleExtension(hDriver, osExt) )
+            {
+                if (!osConflictingDriverList.empty() )
+                    osConflictingDriverList += ", ";
+                osConflictingDriverList += GDALGetDriverShortName(hDriver);
+            }
+        }
+        if (!osConflictingDriverList.empty() )
+        {
+            fprintf(
+                stderr,
+                "Warning: The target file has a '%s' extension, "
+                "which is normally used by the %s driver%s, "
+                "but the requested output driver is %s. "
+                "Is it really what you want?\n",
+                osExt.c_str(),
+                osConflictingDriverList.c_str(),
+                strchr(osConflictingDriverList.c_str(), ',') ? "s" : "",
+                pszDriverName);
+        }
+    }
+}
+
+/* -------------------------------------------------------------------- */
+/*                        EarlySetConfigOptions()                       */
+/* -------------------------------------------------------------------- */
+
+void EarlySetConfigOptions( int argc, char ** argv )
+{
+    // Must process some config options before GDALAllRegister() or
+    // OGRRegisterAll(), but we can't call GDALGeneralCmdLineProcessor() or
+    // OGRGeneralCmdLineProcessor(), because it needs the drivers to be
+    // registered for the --format or --formats options.
+    for( int i = 1; i < argc; i++ )
+    {
+        if( EQUAL(argv[i],"--config") && i + 2 < argc &&
+            (EQUAL(argv[i + 1], "GDAL_SKIP") ||
+             EQUAL(argv[i + 1], "GDAL_DRIVER_PATH") ||
+             EQUAL(argv[i + 1], "OGR_SKIP") ||
+             EQUAL(argv[i + 1], "OGR_DRIVER_PATH")) )
+        {
+            CPLSetConfigOption( argv[i+1], argv[i+2] );
+
+            i += 2;
+        }
+        else if( EQUAL(argv[i],"--debug") && i + 1 < argc )
+        {
+            CPLSetConfigOption( "CPL_DEBUG", argv[i+1] );
+            i += 1;
+        }
+    }
+}
diff --git a/apps/commonutils.h b/apps/commonutils.h
index 846a1da..20fc464 100644
--- a/apps/commonutils.h
+++ b/apps/commonutils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: commonutils.h 31778 2015-11-26 14:15:36Z rouault $
+ * $Id: commonutils.h 34815 2016-07-28 20:00:17Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Common utility routines
@@ -34,8 +34,8 @@
 
 CPL_C_START
 
-void CPL_DLL CheckExtensionConsistency(const char* pszDestFilename,
-                               const char* pszDriverName);
+void CPL_DLL CheckExtensionConsistency( const char* pszDestFilename,
+                                        const char* pszDriverName );
 
 void CPL_DLL EarlySetConfigOptions( int argc, char ** argv );
 
diff --git a/apps/dumpoverviews.cpp b/apps/dumpoverviews.cpp
index c6e77fb..cc77e2b 100644
--- a/apps/dumpoverviews.cpp
+++ b/apps/dumpoverviews.cpp
@@ -1,5 +1,4 @@
 /* ****************************************************************************
- * $Id: dumpoverviews.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Dump overviews to external files.
@@ -33,7 +32,7 @@
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: dumpoverviews.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: dumpoverviews.cpp 35884 2016-10-24 05:56:50Z goatbar $");
 
 static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hBand,
                       const char *pszName );
@@ -55,11 +54,6 @@ static void Usage()
 int main( int argc, char ** argv )
 
 {
-    const char *pszSrcFilename = NULL;
-    int anReqOverviews[1000];
-    int nReqOverviewCount = 0;
-    bool bMasks = false;
-
     GDALAllRegister();
 
     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
@@ -69,6 +63,11 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Process arguments.                                              */
 /* -------------------------------------------------------------------- */
+    const char *pszSrcFilename = NULL;
+    int anReqOverviews[1000] = {};
+    int nReqOverviewCount = 0;
+    bool bMasks = false;
+
     for( int iArg = 1; iArg < argc; iArg++ )
     {
         if( EQUAL(argv[iArg],"-masks") )
@@ -103,26 +102,25 @@ int main( int argc, char ** argv )
 /* ==================================================================== */
 /*      Process all bands.                                              */
 /* ==================================================================== */
-    int iBand;
-    int nBandCount = GDALGetRasterCount( hSrcDS );
+    const int nBandCount = GDALGetRasterCount( hSrcDS );
 
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
         GDALRasterBandH hBaseBand = GDALGetRasterBand( hSrcDS, iBand+1 );
 
 /* -------------------------------------------------------------------- */
 /*      Process all overviews.                                          */
 /* -------------------------------------------------------------------- */
-        int iOverview;
-        int nOverviewCount = GDALGetOverviewCount( hBaseBand );
+        const int nOverviewCount = GDALGetOverviewCount( hBaseBand );
 
-        for( iOverview = 0; iOverview < nOverviewCount; iOverview++ )
+        for( int iOverview = 0; iOverview < nOverviewCount; iOverview++ )
         {
             GDALRasterBandH hSrcOver = GDALGetOverview( hBaseBand, iOverview );
 
-            if (hSrcOver == NULL)
+            if( hSrcOver == NULL )
             {
-                fprintf(stderr, "skipping overview %d as being null\n", iOverview);
+                fprintf(stderr, "skipping overview %d as being null\n",
+                        iOverview);
                 continue;
             }
 
@@ -131,9 +129,9 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
             if( nReqOverviewCount > 0 )
             {
-                int i;
+              int i = 0;  // Used after for.
 
-                for( i = 0; i < nReqOverviewCount; i++ )
+                for( ; i < nReqOverviewCount; i++ )
                 {
                     if( anReqOverviews[i] == iOverview )
                         break;
@@ -154,11 +152,11 @@ int main( int argc, char ** argv )
 
             if( bMasks )
             {
-                CPLString osFilename;
-                osFilename.Printf( "%s_%d_%d_mask.tif",
-                                CPLGetBasename(pszSrcFilename),
-                                iBand+1, iOverview );
-                DumpBand( hSrcDS, GDALGetMaskBand(hSrcOver), osFilename );
+                CPLString osMaskFilename;
+                osMaskFilename.Printf( "%s_%d_%d_mask.tif",
+                                       CPLGetBasename(pszSrcFilename),
+                                       iBand+1, iOverview );
+                DumpBand( hSrcDS, GDALGetMaskBand(hSrcOver), osMaskFilename );
             }
         }
 
@@ -194,18 +192,18 @@ static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hSrcOver,
 /* -------------------------------------------------------------------- */
 /*      Get base ds info.                                               */
 /* -------------------------------------------------------------------- */
-    double adfGeoTransform[6];
+    double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
     bool bHaveGT = GDALGetGeoTransform( hBaseDS, adfGeoTransform ) == CE_None;
 
-    int nOrigXSize = GDALGetRasterXSize( hBaseDS );
-    int nOrigYSize = GDALGetRasterYSize( hBaseDS );
+    const int nOrigXSize = GDALGetRasterXSize( hBaseDS );
+    const int nOrigYSize = GDALGetRasterYSize( hBaseDS );
 
 /* -------------------------------------------------------------------- */
 /*      Create matching output file.                                    */
 /* -------------------------------------------------------------------- */
-    int nXSize = GDALGetRasterBandXSize( hSrcOver );
-    int nYSize = GDALGetRasterBandYSize( hSrcOver );
-    GDALDataType eDT = GDALGetRasterDataType( hSrcOver );
+    const int nXSize = GDALGetRasterBandXSize( hSrcOver );
+    const int nYSize = GDALGetRasterBandYSize( hSrcOver );
+    const GDALDataType eDT = GDALGetRasterDataType( hSrcOver );
     GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
 
     GDALDatasetH hDstDS = GDALCreate( hDriver, pszName, nXSize, nYSize,
@@ -219,15 +217,15 @@ static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hSrcOver,
 /* -------------------------------------------------------------------- */
     if( bHaveGT )
     {
-        double adfOvGeoTransform[6];
+        double adfOvGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
 
         memcpy( adfOvGeoTransform, adfGeoTransform,
                 sizeof(double) * 6 );
 
-        adfOvGeoTransform[1] *= (nOrigXSize / (double) nXSize);
-        adfOvGeoTransform[2] *= (nOrigXSize / (double) nXSize);
-        adfOvGeoTransform[4] *= (nOrigYSize / (double) nYSize);
-        adfOvGeoTransform[5] *= (nOrigYSize / (double) nYSize);
+        adfOvGeoTransform[1] *= nOrigXSize / static_cast<double>(nXSize);
+        adfOvGeoTransform[2] *= nOrigXSize / static_cast<double>(nXSize);
+        adfOvGeoTransform[4] *= nOrigYSize / static_cast<double>(nYSize);
+        adfOvGeoTransform[5] *= nOrigYSize / static_cast<double>(nYSize);
 
         GDALSetGeoTransform( hDstDS, adfOvGeoTransform );
 
@@ -241,11 +239,22 @@ static void DumpBand( GDALDatasetH hBaseDS, GDALRasterBandH hSrcOver,
 
     for( int iLine = 0; iLine < nYSize; iLine++ )
     {
-        GDALRasterIO( hSrcOver, GF_Read, 0, iLine, nXSize, 1,
-                      pData, nXSize, 1, eDT, 0, 0 );
-        GDALRasterIO( GDALGetRasterBand( hDstDS, 1 ), GF_Write,
-                      0, iLine, nXSize, 1,
-                      pData, nXSize, 1, eDT, 0, 0 );
+        {
+            const CPLErr err =
+                GDALRasterIO( hSrcOver, GF_Read, 0, iLine, nXSize, 1,
+                              pData, nXSize, 1, eDT, 0, 0 );
+            if( err != CE_None )
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "GDALRasterIO read failed at %d.", iLine );
+        }
+
+        const CPLErr err =
+            GDALRasterIO( GDALGetRasterBand( hDstDS, 1 ), GF_Write,
+                          0, iLine, nXSize, 1,
+                          pData, nXSize, 1, eDT, 0, 0 );
+        if( err != CE_None )
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "GDALRasterIO write failed at %d.", iLine );
     }
     CPLFree( pData );
 
diff --git a/apps/gdal2ogr.c b/apps/gdal2ogr.c
index 76534ef..8712208 100644
--- a/apps/gdal2ogr.c
+++ b/apps/gdal2ogr.c
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal2ogr.c $
  *
  * Project:  GDAL Utilities
  * Purpose:  Create an OGR datasource from the values of a GDAL dataset
@@ -33,6 +32,8 @@
 #include "ogr_srs_api.h"
 #include "cpl_string.h"
 
+CPL_CVSID("$Id: gdal2ogr.c 34783 2016-07-26 15:05:37Z goatbar $");
+
 /************************************************************************/
 /*                               Usage()                                */
 /************************************************************************/
diff --git a/apps/gdal_contour.cpp b/apps/gdal_contour.cpp
index 65e3532..eb04bc4 100644
--- a/apps/gdal_contour.cpp
+++ b/apps/gdal_contour.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_contour.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  Contour Generator
  * Purpose:  Contour Generator mainline.
@@ -35,7 +34,7 @@
 #include "ogr_api.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gdal_contour.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: gdal_contour.cpp 36534 2016-11-27 23:48:27Z goatbar $");
 
 /************************************************************************/
 /*                            ArgIsNumeric()                            */
@@ -74,32 +73,41 @@ static void Usage(const char* pszErrorMsg = NULL)
 
 #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
     do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
+        Usage(CPLSPrintf("%s option requires %d argument(s)", \
+                         argv[i], nExtraArg)); } while( false )
 
 int main( int argc, char ** argv )
 
 {
-    GDALDatasetH	hSrcDS;
-    int i, b3D = FALSE, bNoDataSet = FALSE, bIgnoreNoData = FALSE;
+    GDALDatasetH hSrcDS;
+    int i;
+    int b3D = FALSE;
+    int bNoDataSet = FALSE;
+    int bIgnoreNoData = FALSE;
     int nBandIn = 1;
-    double dfInterval = 0.0, dfNoData = 0.0, dfOffset = 0.0;
+    double dfInterval = 0.0;
+    double dfNoData = 0.0;
+    double dfOffset = 0.0;
     const char *pszSrcFilename = NULL;
     const char *pszDstFilename = NULL;
     const char *pszElevAttrib = NULL;
     const char *pszFormat = "ESRI Shapefile";
-    char        **papszDSCO = NULL, **papszLCO = NULL;
+    char **papszDSCO = NULL;
+    char **papszLCO = NULL;
     double adfFixedLevels[1000];
-    int    nFixedLevelCount = 0;
+    int nFixedLevelCount = 0;
     const char *pszNewLayerName = "contour";
     int bQuiet = FALSE;
     GDALProgressFunc pfnProgress = NULL;
 
-    /* Check that we are running against at least GDAL 1.4 */
-    /* Note to developers : if we use newer API, please change the requirement */
+    // Check that we are running against at least GDAL 1.4.
+    // Note to developers: if we use newer API, please change the requirement.
     if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
     {
-        fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
-                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
+        fprintf(stderr,
+                "At least, GDAL >= 1.4.0 is required for this version of %s, "
+                "which was compiled against GDAL %s\n",
+                argv[0], GDAL_RELEASE_NAME);
         exit(1);
     }
 
@@ -115,7 +123,8 @@ int main( int argc, char ** argv )
     {
         if( EQUAL(argv[i], "--utility_version") )
         {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+            printf("%s was compiled against GDAL %s and "
+                   "is running against GDAL %s\n",
                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
             CSLDestroy( argv );
             return 0;
@@ -140,7 +149,8 @@ int main( int argc, char ** argv )
         else if( EQUAL(argv[i],"-fl") )
         {
             if( i >= argc-1 )
-                Usage(CPLSPrintf("%s option requires at least 1 argument", argv[i]));
+                Usage(CPLSPrintf("%s option requires at least 1 argument",
+                                 argv[i]));
             while( i < argc-1
                    && nFixedLevelCount
                              < (int)(sizeof(adfFixedLevels)/sizeof(double))
diff --git a/apps/gdal_grid_bin.cpp b/apps/gdal_grid_bin.cpp
index 5501f4c..feb082f 100644
--- a/apps/gdal_grid_bin.cpp
+++ b/apps/gdal_grid_bin.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_grid_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL scattered data gridding (interpolation) tool
@@ -31,7 +30,7 @@
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdal_grid_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: gdal_grid_bin.cpp 34654 2016-07-14 05:53:06Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
diff --git a/apps/gdal_grid_lib.cpp b/apps/gdal_grid_lib.cpp
index 72d98fc..25ba83a 100644
--- a/apps/gdal_grid_lib.cpp
+++ b/apps/gdal_grid_lib.cpp
@@ -1,5 +1,4 @@
 /* ****************************************************************************
- * $Id: gdal_grid_lib.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL scattered data gridding (interpolation) tool
@@ -28,20 +27,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_utils.h"
+#include "gdal_utils_priv.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <algorithm>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "gdal.h"
 #include "gdal_alg.h"
-#include "ogr_spatialref.h"
+#include "gdal_priv.h"
+#include "gdalgrid.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
 #include "ogrsf_frmts.h"
-#include "gdalgrid.h"
-#include "gdal_utils_priv.h"
-
-#include <cstdlib>
-#include <vector>
-#include <algorithm>
 
-CPL_CVSID("$Id: gdal_grid_lib.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: gdal_grid_lib.cpp 37481 2017-02-27 12:42:13Z rouault $");
 
 /************************************************************************/
 /*                          GDALGridOptions                             */
@@ -123,9 +135,10 @@ static void PrintAlgorithmAndOptions( GDALGridAlgorithm eAlgorithm,
         case GGA_InverseDistanceToAPowerNearestNeighbor:
             printf( "Algorithm name: \"%s\".\n", szAlgNameInvDistNearestNeighbor );
             CPLprintf( "Options are "
-                        "\"power=%f:radius=%f"
+                        "\"power=%f:smoothing=%f:radius=%f"
                     ":max_points=%lu:min_points=%lu:nodata=%f\"\n",
                 ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->dfPower,
+                ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->dfSmoothing,
                 ((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->dfRadius,
                 (unsigned long)((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->nMaxPoints,
                 (unsigned long)((GDALGridInverseDistanceToAPowerNearestNeighborOptions *)pOptions)->nMinPoints,
@@ -396,7 +409,7 @@ static CPLErr ProcessLayer( OGRLayerH hSrcLayer, GDALDatasetH hDstDS,
         OGRFeature::DestroyFeature( poFeat );
     }
 
-    if ( adfX.size() == 0 )
+    if ( adfX.empty() )
     {
         printf( "No point geometry found on layer %s, skipping.\n",
                 OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
@@ -449,7 +462,7 @@ static CPLErr ProcessLayer( OGRLayerH hSrcLayer, GDALDatasetH hDstDS,
 
     GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, nBand );
 
-    if (adfX.size() == 0)
+    if (adfX.empty())
     {
         // FIXME: Should have set to nodata value instead
         GDALFillRaster( hBand, 0.0 , 0.0 );
@@ -950,7 +963,7 @@ GDALGridOptions *GDALGridOptionsNew(char** papszArgv, GDALGridOptionsForBinary*
 /*      Handle command line arguments.                                  */
 /* -------------------------------------------------------------------- */
     int argc = CSLCount(papszArgv);
-    for( int i = 0; i < argc; i++ )
+    for( int i = 0; papszArgv != NULL && i < argc; i++ )
     {
         if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
         {
diff --git a/apps/gdal_rasterize_bin.cpp b/apps/gdal_rasterize_bin.cpp
index 1512d07..c012ee4 100644
--- a/apps/gdal_rasterize_bin.cpp
+++ b/apps/gdal_rasterize_bin.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_rasterize_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Rasterize OGR shapes into a GDAL raster.
@@ -30,8 +29,9 @@
 #include "cpl_string.h"
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdal_rasterize_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: gdal_rasterize_bin.cpp 37460 2017-02-26 02:06:36Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -42,7 +42,7 @@ static void Usage(const char* pszErrorMsg = NULL)
 {
     printf(
         "Usage: gdal_rasterize [-b band]* [-i] [-at]\n"
-        "       [-burn value]* | [-a attribute_name] [-3d] [-add]\n"
+        "       {[-burn value]* | [-a attribute_name] | [-3d]} [-add]\n"
         "       [-l layername]* [-where expression] [-sql select_statement]\n"
         "       [-dialect dialect] [-of format] [-a_srs srs_def]\n"
         "       [-co \"NAME=VALUE\"]* [-a_nodata value] [-init value]*\n"
@@ -53,7 +53,7 @@ static void Usage(const char* pszErrorMsg = NULL)
 
     if( pszErrorMsg != NULL )
         fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-    exit( 1 );
+    exit(1);
 }
 
 /************************************************************************/
@@ -62,14 +62,16 @@ static void Usage(const char* pszErrorMsg = NULL)
 
 static GDALRasterizeOptionsForBinary *GDALRasterizeOptionsForBinaryNew(void)
 {
-    return (GDALRasterizeOptionsForBinary*) CPLCalloc(  1, sizeof(GDALRasterizeOptionsForBinary) );
+    return static_cast<GDALRasterizeOptionsForBinary *>(
+        CPLCalloc(1, sizeof(GDALRasterizeOptionsForBinary)));
 }
 
 /************************************************************************/
 /*                       GDALRasterizeOptionsForBinaryFree()            */
 /************************************************************************/
 
-static void GDALRasterizeOptionsForBinaryFree( GDALRasterizeOptionsForBinary* psOptionsForBinary )
+static void GDALRasterizeOptionsForBinaryFree(
+    GDALRasterizeOptionsForBinary* psOptionsForBinary )
 {
     if( psOptionsForBinary )
     {
@@ -95,7 +97,7 @@ int main(int argc, char** argv)
 /*      Generic arg processing.                                         */
 /* -------------------------------------------------------------------- */
     GDALAllRegister();
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    argc = GDALGeneralCmdLineProcessor(argc, &argv, 0);
     if( argc < 1 )
         exit( -argc );
 
@@ -103,21 +105,24 @@ int main(int argc, char** argv)
     {
         if( EQUAL(argv[i], "--utility_version") )
         {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+            printf("%s was compiled against GDAL %s and "
+                   "is running against GDAL %s\n",
                    argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            CSLDestroy( argv );
+            CSLDestroy(argv);
             return 0;
         }
-        else if( EQUAL(argv[i],"--help") )
+        else if( EQUAL(argv[i], "--help") )
         {
             Usage();
         }
     }
 
-    GDALRasterizeOptionsForBinary* psOptionsForBinary = GDALRasterizeOptionsForBinaryNew();
-    /* coverity[tainted_data] */
-    GDALRasterizeOptions *psOptions = GDALRasterizeOptionsNew(argv + 1, psOptionsForBinary);
-    CSLDestroy( argv );
+    GDALRasterizeOptionsForBinary* psOptionsForBinary =
+        GDALRasterizeOptionsForBinaryNew();
+    // coverity[tainted_data]
+    GDALRasterizeOptions *psOptions =
+        GDALRasterizeOptionsNew(argv + 1, psOptionsForBinary);
+    CSLDestroy(argv);
 
     if( psOptions == NULL )
     {
@@ -138,11 +143,12 @@ int main(int argc, char** argv)
 /* -------------------------------------------------------------------- */
 /*      Open input file.                                                */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hInDS = GDALOpenEx( psOptionsForBinary->pszSource, GDAL_OF_VECTOR | GDAL_OF_VERBOSE_ERROR,
-                                     NULL, NULL, NULL );
+    GDALDatasetH hInDS = GDALOpenEx(
+        psOptionsForBinary->pszSource, GDAL_OF_VECTOR | GDAL_OF_VERBOSE_ERROR,
+        NULL, NULL, NULL);
 
     if( hInDS == NULL )
-        exit( 1 );
+        exit(1);
 
 /* -------------------------------------------------------------------- */
 /*      Open output file if it exists.                                  */
@@ -150,15 +156,56 @@ int main(int argc, char** argv)
     GDALDatasetH hDstDS = NULL;
     if( !(psOptionsForBinary->bCreateOutput) )
     {
-        CPLPushErrorHandler( CPLQuietErrorHandler );
-        hDstDS = GDALOpenEx( psOptionsForBinary->pszDest, GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR | GDAL_OF_UPDATE,
-                                        NULL, NULL, NULL );
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        hDstDS = GDALOpenEx(
+            psOptionsForBinary->pszDest,
+            GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR | GDAL_OF_UPDATE,
+            NULL, NULL, NULL );
         CPLPopErrorHandler();
     }
 
-    if (hDstDS == NULL && !psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet)
-        CheckExtensionConsistency(psOptionsForBinary->pszDest, psOptionsForBinary->pszFormat);
+    if( psOptionsForBinary->bCreateOutput || hDstDS == NULL )
+    {
+        GDALDriverManager *poDM = GetGDALDriverManager();
+        GDALDriver *poDriver =
+            poDM->GetDriverByName(psOptionsForBinary->pszFormat);
+        char** papszDriverMD = (poDriver) ? poDriver->GetMetadata(): NULL;
+        if( poDriver == NULL ||
+            !CPLTestBool(CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_RASTER,
+                                              "FALSE")) ||
+            !CPLTestBool(CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_CREATE,
+                                              "FALSE")) )
+        {
+            fprintf(stderr,
+                    "Output driver `%s' not recognised or does not support "
+                    "direct output file creation.\n",
+                    psOptionsForBinary->pszFormat);
+            fprintf(stderr,
+                    "The following format drivers are configured and "
+                    "support direct output:\n" );
+
+            for( int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++ )
+            {
+                GDALDriver* poIter = poDM->GetDriver(iDriver);
+                papszDriverMD = poIter->GetMetadata();
+                if( CPLTestBool(
+                        CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_RASTER,
+                                             "FALSE")) &&
+                    CPLTestBool(
+                        CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_CREATE,
+                                             "FALSE")) )
+                {
+                    fprintf(stderr,  "  -> `%s'\n", poIter->GetDescription());
+                }
+            }
+            exit(1);
+        }
+    }
 
+    if (hDstDS == NULL && !psOptionsForBinary->bQuiet &&
+        !psOptionsForBinary->bFormatExplicitlySet)
+        CheckExtensionConsistency(psOptionsForBinary->pszDest,
+                                  psOptionsForBinary->pszFormat);
 
     int bUsageError = FALSE;
     GDALDatasetH hRetDS = GDALRasterize(psOptionsForBinary->pszDest,
@@ -167,7 +214,7 @@ int main(int argc, char** argv)
                                         psOptions, &bUsageError);
     if(bUsageError == TRUE)
         Usage();
-    int nRetCode = (hRetDS) ? 0 : 1;
+    const int nRetCode = hRetDS ? 0 : 1;
 
     GDALClose(hInDS);
     GDALClose(hRetDS);
diff --git a/apps/gdal_rasterize_lib.cpp b/apps/gdal_rasterize_lib.cpp
index a0f66e2..613c305 100644
--- a/apps/gdal_rasterize_lib.cpp
+++ b/apps/gdal_rasterize_lib.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_rasterize_lib.cpp 36584 2016-11-30 17:46:24Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Rasterize OGR shapes into a GDAL raster.
@@ -28,17 +27,29 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_utils.h"
+#include "gdal_utils_priv.h"
+
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <vector>
+
+#include "commonutils.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
 #include "gdal.h"
 #include "gdal_alg.h"
-#include "cpl_conv.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
 #include "ogr_srs_api.h"
-#include "cpl_string.h"
-#include "commonutils.h"
-#include "gdal_utils_priv.h"
-#include <vector>
 
-CPL_CVSID("$Id: gdal_rasterize_lib.cpp 36584 2016-11-30 17:46:24Z rouault $");
+CPL_CVSID("$Id: gdal_rasterize_lib.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                            ArgIsNumeric()                            */
@@ -52,7 +63,6 @@ static bool ArgIsNumeric( const char *pszArg )
     return pszEnd != NULL && pszEnd[0] == '\0';
 }
 
-
 /************************************************************************/
 /*                          InvertGeometries()                          */
 /************************************************************************/
@@ -242,23 +252,20 @@ static CPLErr ProcessLayer(
 
         for( unsigned int iBand = 0; iBand < anBandList.size(); iBand++ )
         {
-            if( adfBurnValues.size() > 0 )
+            if( !adfBurnValues.empty() )
                 adfFullBurnValues.push_back(
-                    adfBurnValues[MIN(iBand,adfBurnValues.size()-1)] );
+                    adfBurnValues[
+                        std::min(iBand,
+                                 static_cast<unsigned int>(
+                                     adfBurnValues.size()) - 1)] );
             else if( pszBurnAttribute )
             {
                 adfFullBurnValues.push_back( OGR_F_GetFieldAsDouble( hFeat, iBurnField ) );
             }
-            /* I have made the 3D option exclusive to other options since it
-               can be used to modify the value from "-burn value" or
-               "-a attribute_name" */
-            if( b3D )
+            else if( b3D )
             {
-                // TODO: get geometry "z" value
                 /* Points and Lines will have their "z" values collected at the
-                   point and line levels respectively. However filled polygons
-                   (GDALdllImageFilledPolygon) can use some help by getting
-                   their "z" values here. */
+                   point and line levels respectively. Not implemented for polygons */
                 adfFullBurnValues.push_back( 0.0 );
             }
         }
@@ -276,13 +283,16 @@ static CPLErr ProcessLayer(
 /* -------------------------------------------------------------------- */
     if( bInverse )
     {
-        if( ahGeometries.size() == 0 )
+        if( ahGeometries.empty() )
         {
             for( unsigned int iBand = 0; iBand < anBandList.size(); iBand++ )
             {
-                if( adfBurnValues.size() > 0 )
+                if( !adfBurnValues.empty() )
                     adfFullBurnValues.push_back(
-                        adfBurnValues[MIN(iBand,adfBurnValues.size()-1)] );
+                        adfBurnValues[
+                            std::min(iBand,
+                                     static_cast<unsigned int>(
+                                        adfBurnValues.size()) - 1)] );
                 else /* FIXME? Not sure what to do exactly in the else case, but we must insert a value */
                     adfFullBurnValues.push_back( 0.0 );
             }
@@ -369,10 +379,10 @@ GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers,
             }
             else
             {
-                sEnvelop.MinX = MIN(sEnvelop.MinX, sLayerEnvelop.MinX);
-                sEnvelop.MinY = MIN(sEnvelop.MinY, sLayerEnvelop.MinY);
-                sEnvelop.MaxX = MAX(sEnvelop.MaxX, sLayerEnvelop.MaxX);
-                sEnvelop.MaxY = MAX(sEnvelop.MaxY, sLayerEnvelop.MaxY);
+                sEnvelop.MinX = std::min(sEnvelop.MinX, sLayerEnvelop.MinX);
+                sEnvelop.MinY = std::min(sEnvelop.MinY, sLayerEnvelop.MinY);
+                sEnvelop.MaxX = std::max(sEnvelop.MaxX, sLayerEnvelop.MaxX);
+                sEnvelop.MaxY = std::max(sEnvelop.MaxY, sLayerEnvelop.MaxY);
             }
         }
         else
@@ -449,9 +459,11 @@ GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers,
         }
     }
 
-    if (adfInitVals.size() != 0)
+    if (!adfInitVals.empty())
     {
-        for(iBand = 0; iBand < MIN(nBandCount,(int)adfInitVals.size()); iBand++)
+        for( iBand = 0;
+             iBand < std::min(nBandCount, static_cast<int>(adfInitVals.size()));
+             iBand++ )
         {
             GDALRasterBandH hBand = GDALGetRasterBand(hDstDS, iBand + 1);
             GDALFillRaster(hBand, adfInitVals[iBand], 0);
@@ -461,7 +473,6 @@ GDALDatasetH CreateOutputDataset(std::vector<OGRLayerH> ahLayers,
     return hDstDS;
 }
 
-
 struct GDALRasterizeOptions
 {
     /*! output format. The default is GeoTIFF(GTiff). Use the short format name. */
@@ -498,7 +509,6 @@ struct GDALRasterizeOptions
     int bTargetAlignedPixels;
 };
 
-
 /************************************************************************/
 /*                             GDALRasterize()                          */
 /************************************************************************/
@@ -591,29 +601,14 @@ GDALDatasetH GDALRasterize( const char *pszDest, GDALDatasetH hDstDS,
 /*      Find the output driver.                                         */
 /* -------------------------------------------------------------------- */
         hDriver = GDALGetDriverByName( psOptions->pszFormat );
+        char** papszDriverMD = (hDriver) ? GDALGetMetadata(hDriver, NULL): NULL;
         if( hDriver == NULL
-            || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
+            || !CPLTestBool( CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_RASTER, "FALSE") )
+            || !CPLTestBool( CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_CREATE, "FALSE") ) )
         {
-            int	iDr;
-
             CPLError( CE_Failure, CPLE_NotSupported,
                       "Output driver `%s' not recognised or does not support "
-                      " direct output file creation.", psOptions->pszFormat);
-            fprintf(stderr, "The following format drivers are configured\n"
-                    "and support direct output:\n" );
-
-            for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
-            {
-                hDriver = GDALGetDriver(iDr);
-
-                if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
-                {
-                    fprintf(stderr, "  %s: %s\n",
-                            GDALGetDriverShortName( hDriver  ),
-                            GDALGetDriverLongName( hDriver ) );
-                }
-            }
-            fprintf(stderr, "\n" );
+                      "direct output file creation.", psOptions->pszFormat);
             GDALRasterizeOptionsFree(psOptionsToFree);
             return NULL;
         }
@@ -800,7 +795,7 @@ GDALRasterizeOptions *GDALRasterizeOptionsNew(char** papszArgv,
 /*      Handle command line arguments.                                  */
 /* -------------------------------------------------------------------- */
     int argc = CSLCount(papszArgv);
-    for( int i = 0; i < argc; i++ )
+    for( int i = 0; papszArgv != NULL && i < argc; i++ )
     {
         if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
         {
@@ -1068,14 +1063,17 @@ GDALRasterizeOptions *GDALRasterizeOptionsNew(char** papszArgv,
         }
     }
 
-    if( psOptions->adfBurnValues.size() == 0 &&
-        psOptions->pszBurnAttribute == NULL && !(psOptions->b3D) )
+    int nExclusiveOptionsCount = 0;
+    nExclusiveOptionsCount += (!psOptions->adfBurnValues.empty()) ? 1 : 0;
+    nExclusiveOptionsCount += (psOptions->pszBurnAttribute != NULL) ? 1 : 0;
+    nExclusiveOptionsCount += (psOptions->b3D) ? 1 : 0;
+    if( nExclusiveOptionsCount != 1 )
     {
-        if( psOptionsForBinary == NULL )
+        if( nExclusiveOptionsCount == 0 && psOptionsForBinary == NULL )
             psOptions->adfBurnValues.push_back(255);
         else
         {
-            CPLError(CE_Failure, CPLE_NotSupported, "At least one of -3d, -burn or -a required." );
+            CPLError(CE_Failure, CPLE_NotSupported, "One and only one of -3d, -burn or -a is required." );
             GDALRasterizeOptionsFree(psOptions);
             return NULL;
         }
@@ -1094,10 +1092,10 @@ GDALRasterizeOptions *GDALRasterizeOptionsNew(char** papszArgv,
         {
             CPLError(CE_Failure, CPLE_NotSupported, "-tap option cannot be used without using -tr.");
             GDALRasterizeOptionsFree(psOptions);
-            return NULL;;
+            return NULL;
         }
 
-        if( psOptions->anBandList.size() != 0 )
+        if( !psOptions->anBandList.empty() )
         {
             CPLError(CE_Failure, CPLE_NotSupported, "-b option cannot be used when creating a GDAL dataset." );
             GDALRasterizeOptionsFree(psOptions);
@@ -1106,7 +1104,7 @@ GDALRasterizeOptions *GDALRasterizeOptionsNew(char** papszArgv,
 
         int nBandCount = 1;
 
-        if (psOptions->adfBurnValues.size() != 0)
+        if (!psOptions->adfBurnValues.empty())
             nBandCount = static_cast<int>(psOptions->adfBurnValues.size());
 
         if ((int)psOptions->adfInitVals.size() > nBandCount)
@@ -1124,7 +1122,7 @@ GDALRasterizeOptions *GDALRasterizeOptionsNew(char** papszArgv,
     }
     else
     {
-        if( psOptions->anBandList.size() == 0 )
+        if( psOptions->anBandList.empty() )
             psOptions->anBandList.push_back( 1 );
     }
 
diff --git a/apps/gdal_translate_bin.cpp b/apps/gdal_translate_bin.cpp
index bc8e71f..4d14a4f 100644
--- a/apps/gdal_translate_bin.cpp
+++ b/apps/gdal_translate_bin.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_translate_bin.cpp 34776 2016-07-25 21:22:15Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Image Translator Program
@@ -34,7 +33,7 @@
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdal_translate_bin.cpp 34776 2016-07-25 21:22:15Z rouault $");
+CPL_CVSID("$Id: gdal_translate_bin.cpp 37258 2017-01-31 14:12:05Z rouault $");
 
 /*  ******************************************************************* */
 /*                               Usage()                                */
@@ -169,7 +168,7 @@ int main( int argc, char ** argv )
     {
 #if defined(__MACH__) && defined(__APPLE__)
         // On Mach, the default limit is 256 files per process
-        // We should eventually dynamically query the limit
+        // TODO We should eventually dynamically query the limit for all OS
         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100");
 #else
         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
@@ -205,6 +204,38 @@ int main( int argc, char ** argv )
         GDALTranslateOptionsSetProgress(psOptions, GDALTermProgress, NULL);
     }
 
+    if( psOptionsForBinary->pszFormat )
+    {
+        GDALDriverH hDriver = GDALGetDriverByName( psOptionsForBinary->pszFormat );
+        if( hDriver == NULL )
+        {
+            int iDr;
+
+            fprintf(stderr, "Output driver `%s' not recognised.\n",
+                    psOptionsForBinary->pszFormat);
+            fprintf(stderr, "The following format drivers are configured and support output:\n" );
+            for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+            {
+                hDriver = GDALGetDriver(iDr);
+
+                if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
+                    (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
+                    || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
+                {
+                    fprintf(stderr, "  %s: %s\n",
+                            GDALGetDriverShortName( hDriver  ),
+                            GDALGetDriverLongName( hDriver ) );
+                }
+            }
+
+            GDALTranslateOptionsFree(psOptions);
+            GDALTranslateOptionsForBinaryFree(psOptionsForBinary);
+
+            GDALDestroyDriverManager();
+            exit(1);
+        }
+    }
+
     if (!psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet)
         CheckExtensionConsistency(psOptionsForBinary->pszDest, psOptionsForBinary->pszFormat);
 
@@ -225,8 +256,8 @@ int main( int argc, char ** argv )
 /*      Handle subdatasets.                                             */
 /* -------------------------------------------------------------------- */
     if( !psOptionsForBinary->bCopySubDatasets
-        && CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0
-        && GDALGetRasterCount(hDataset) == 0 )
+        && GDALGetRasterCount(hDataset) == 0
+        && CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 )
     {
         fprintf( stderr,
                  "Input file contains subdatasets. Please, select one of them for reading.\n" );
@@ -235,8 +266,8 @@ int main( int argc, char ** argv )
         exit( 1 );
     }
 
-    if( CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0
-        && psOptionsForBinary->bCopySubDatasets )
+    if( psOptionsForBinary->bCopySubDatasets &&
+        CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 )
     {
         char **papszSubdatasets = GDALGetMetadata(hDataset,"SUBDATASETS");
         char *pszSubDest = (char *) CPLMalloc(strlen(psOptionsForBinary->pszDest)+32);
@@ -289,7 +320,6 @@ int main( int argc, char ** argv )
 
         GDALDestroyDriverManager();
         return 0;
-
     }
 
     if( !psOptionsForBinary->bQuiet )
diff --git a/apps/gdal_translate_lib.cpp b/apps/gdal_translate_lib.cpp
index 9be69a7..5108a70 100644
--- a/apps/gdal_translate_lib.cpp
+++ b/apps/gdal_translate_lib.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_translate_lib.cpp 34813 2016-07-28 16:38:56Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Image Translator Program
@@ -29,16 +28,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi.h"
+#include "cpl_port.h"
+#include "gdal_utils.h"
+#include "gdal_utils_priv.h"
+
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+#include <limits>
+
+#include "commonutils.h"
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_priv.h"
+#include "gdal_vrt.h"
+#include "ogr_core.h"
 #include "ogr_spatialref.h"
 #include "vrtdataset.h"
-#include "commonutils.h"
-#include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdal_translate_lib.cpp 34813 2016-07-28 16:38:56Z rouault $");
+CPL_CVSID("$Id: gdal_translate_lib.cpp 37719 2017-03-16 14:51:42Z rouault $");
 
 static int ArgIsNumeric( const char * );
 static void AttachMetadata( GDALDatasetH, char ** );
@@ -243,7 +257,6 @@ struct GDALTranslateOptions
         a file containing the WKT. Note that this does not cause reprojection of the
         dataset to the specified SRS. */
     char *pszProjSRS;
-
 };
 
 /************************************************************************/
@@ -372,7 +385,7 @@ static int FixSrcDstWindow( double* padfSrcWin, double* padfDstWin,
         dfModifiedDstXOff = dfDstULX - dfDstXOff;
         dfModifiedDstXSize = (dfDstLRX - dfDstXOff) - dfModifiedDstXOff;
 
-        dfModifiedDstXOff = MAX(0,dfModifiedDstXOff);
+        dfModifiedDstXOff = std::max(0.0, dfModifiedDstXOff);
         if( dfModifiedDstXOff + dfModifiedDstXSize > dfDstXSize )
             dfModifiedDstXSize = dfDstXSize - dfModifiedDstXOff;
     }
@@ -382,7 +395,7 @@ static int FixSrcDstWindow( double* padfSrcWin, double* padfDstWin,
         dfModifiedDstYOff = dfDstULY - dfDstYOff;
         dfModifiedDstYSize = (dfDstLRY - dfDstYOff) - dfModifiedDstYOff;
 
-        dfModifiedDstYOff = MAX(0,dfModifiedDstYOff);
+        dfModifiedDstYOff = std::max(0.0, dfModifiedDstYOff);
         if( dfModifiedDstYOff + dfModifiedDstYSize > dfDstYSize )
             dfModifiedDstYSize = dfDstYSize - dfModifiedDstYOff;
     }
@@ -506,10 +519,10 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
                         GDALTranslateOptionsNew(NULL, NULL);
 
     GDALDatasetH hOutDS;
-    int			i;
-    int			nRasterXSize, nRasterYSize;
-    GDALDriverH		hDriver;
-    int			nOXSize = 0, nOYSize = 0;
+    int i;
+    int nRasterXSize, nRasterYSize;
+    GDALDriverH hDriver;
+    int nOXSize = 0, nOYSize = 0;
     const char          *pszProjection;
     const char *pszSource = NULL;
     int bGotBounds = FALSE;
@@ -571,7 +584,6 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
         CPLFree( psOptions->pszOutputSRS );
         psOptions->pszOutputSRS = CPLStrdup( pszSRS );
         CPLFree( pszSRS );
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -579,7 +591,7 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
 /* -------------------------------------------------------------------- */
 
     if( (psOptions->nOXSizePixel != 0 || psOptions->dfOXSizePct != 0.0 || psOptions->nOYSizePixel != 0 ||
-         psOptions->dfOYSizePct) && (psOptions->dfXRes != 0 && psOptions->dfYRes != 0) )
+         psOptions->dfOYSizePct != 0.0) && (psOptions->dfXRes != 0 && psOptions->dfYRes != 0) )
     {
         CPLError( CE_Failure, CPLE_IllegalArg, "-outsize and -tr options cannot be used at the same time.");
         if(pbUsageError)
@@ -609,7 +621,7 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
     }
 
 /* -------------------------------------------------------------------- */
-/*	Build band list to translate					*/
+/*      Build band list to translate                                    */
 /* -------------------------------------------------------------------- */
     if( psOptions->panBandList == NULL )
     {
@@ -629,11 +641,13 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
     {
         for( i = 0; i < psOptions->nBandCount; i++ )
         {
-            if( ABS(psOptions->panBandList[i]) > GDALGetRasterCount(hSrcDataset) )
+            if( std::abs(psOptions->panBandList[i]) >
+                GDALGetRasterCount(hSrcDataset) )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
+                CPLError(CE_Failure, CPLE_AppDefined,
                          "Band %d requested, but only bands 1 to %d available.",
-                         ABS(psOptions->panBandList[i]), GDALGetRasterCount(hSrcDataset) );
+                         std::abs(psOptions->panBandList[i]),
+                         GDALGetRasterCount(hSrcDataset) );
                 GDALTranslateOptionsFree(psOptions);
                 return NULL;
             }
@@ -679,7 +693,7 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
     if( psOptions->dfULX != 0.0 || psOptions->dfULY != 0.0
         || psOptions->dfLRX != 0.0 || psOptions->dfLRY != 0.0 )
     {
-        double	adfGeoTransform[6];
+        double adfGeoTransform[6];
 
         GDALGetGeoTransform( hSrcDataset, adfGeoTransform );
 
@@ -692,7 +706,7 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
             return NULL;
         }
 
-        if( osProjSRS.size() )
+        if( !osProjSRS.empty() )
         {
             pszProjection = GDALGetProjectionRef( hSrcDataset );
             if( pszProjection != NULL && strlen(pszProjection) > 0 )
@@ -728,12 +742,12 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
 
         psOptions->adfSrcWin[2] = (psOptions->dfLRX - psOptions->dfULX) / adfGeoTransform[1];
         psOptions->adfSrcWin[3] = (psOptions->dfLRY - psOptions->dfULY) / adfGeoTransform[5];
-        
+
         // In case of nearest resampling, round to integer pixels (#6610)
         if( psOptions->pszResampling == NULL ||
             EQUALN(psOptions->pszResampling, "NEAR", 4) )
         {
-            psOptions->adfSrcWin[0] = floor(psOptions->adfSrcWin[0] + 0.001); 
+            psOptions->adfSrcWin[0] = floor(psOptions->adfSrcWin[0] + 0.001);
             psOptions->adfSrcWin[1] = floor(psOptions->adfSrcWin[1] + 0.001);
             psOptions->adfSrcWin[2] = floor(psOptions->adfSrcWin[2] + 0.5);
             psOptions->adfSrcWin[3] = floor(psOptions->adfSrcWin[3] + 0.5);
@@ -806,25 +820,32 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
     hDriver = GDALGetDriverByName( psOptions->pszFormat );
     if( hDriver == NULL )
     {
-        int iDr;
+        CPLError( CE_Failure, CPLE_IllegalArg, "Output driver `%s' not recognised.",
+                  psOptions->pszFormat);
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
 
-        CPLError( CE_Failure, CPLE_IllegalArg, "Output driver `%s' not recognised.", psOptions->pszFormat);
-        CPLError( CE_Failure, CPLE_IllegalArg, "The following format drivers are configured and support output:" );
-        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
-        {
-            hDriver = GDALGetDriver(iDr);
+    char** papszDriverMD = GDALGetMetadata(hDriver, NULL);
 
-            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
-                (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
-                 || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
-            {
-                CPLError( CE_Failure, CPLE_IllegalArg, "  %s: %s",
-                        GDALGetDriverShortName( hDriver  ),
-                        GDALGetDriverLongName( hDriver ) );
-            }
-        }
-        if(pbUsageError)
-            *pbUsageError = TRUE;
+    if( !CPLTestBool( CSLFetchNameValueDef(papszDriverMD,
+                                           GDAL_DCAP_RASTER, "FALSE") ) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s driver has no raster capabilities.",
+                  psOptions->pszFormat );
+        GDALTranslateOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if( !CPLTestBool( CSLFetchNameValueDef(papszDriverMD,
+                                          GDAL_DCAP_CREATE, "FALSE") ) &&
+        !CPLTestBool( CSLFetchNameValueDef(papszDriverMD,
+                                          GDAL_DCAP_CREATECOPY, "FALSE") ))
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s driver has no creation capabilities.",
+                  psOptions->pszFormat );
         GDALTranslateOptionsFree(psOptions);
         return NULL;
     }
@@ -836,7 +857,6 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
 /*      virtual input source to copy from.                              */
 /* -------------------------------------------------------------------- */
 
-
     int bSpatialArrangementPreserved = (
            psOptions->adfSrcWin[0] == 0 && psOptions->adfSrcWin[1] == 0
         && psOptions->adfSrcWin[2] == GDALGetRasterXSize(hSrcDataset)
@@ -1027,7 +1047,8 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
 /* -------------------------------------------------------------------- */
 /*      Transfer generally applicable metadata.                         */
 /* -------------------------------------------------------------------- */
-    char** papszMetadata = CSLDuplicate(((GDALDataset*)hSrcDataset)->GetMetadata());
+    GDALDataset* poSrcDS = reinterpret_cast<GDALDataset*>(hSrcDataset);
+    char** papszMetadata = CSLDuplicate(poSrcDS->GetMetadata());
     if ( psOptions->nScaleRepeat > 0 || psOptions->bUnscale || psOptions->eOutputType != GDT_Unknown )
     {
         /* Remove TIFFTAG_MINSAMPLEVALUE and TIFFTAG_MAXSAMPLEVALUE */
@@ -1053,6 +1074,14 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
     if (pszInterleave)
         poVDS->SetMetadataItem("INTERLEAVE", pszInterleave, "IMAGE_STRUCTURE");
 
+    /* ISIS3 -> ISIS3 special case */
+    if( EQUAL(psOptions->pszFormat, "ISIS3") )
+    {
+        char** papszMD_ISIS3 = poSrcDS->GetMetadata("json:ISIS3");
+        if( papszMD_ISIS3 != NULL)
+            poVDS->SetMetadata( papszMD_ISIS3, "json:ISIS3" );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Transfer metadata that remains valid if the spatial             */
 /*      arrangement of the data is unaltered.                           */
@@ -1061,11 +1090,11 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
     {
         char **papszMD;
 
-        papszMD = ((GDALDataset*)hSrcDataset)->GetMetadata("RPC");
+        papszMD = poSrcDS->GetMetadata("RPC");
         if( papszMD != NULL )
             poVDS->SetMetadata( papszMD, "RPC" );
 
-        papszMD = ((GDALDataset*)hSrcDataset)->GetMetadata("GEOLOCATION");
+        papszMD = poSrcDS->GetMetadata("GEOLOCATION");
         if( papszMD != NULL )
             poVDS->SetMetadata( papszMD, "GEOLOCATION" );
     }
@@ -1073,7 +1102,7 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
     {
         char **papszMD;
 
-        papszMD = ((GDALDataset*)hSrcDataset)->GetMetadata("RPC");
+        papszMD = poSrcDS->GetMetadata("RPC");
         if( papszMD != NULL )
         {
             papszMD = CSLDuplicate(papszMD);
@@ -1112,15 +1141,17 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
 
     if (psOptions->nRGBExpand != 0)
     {
-        GDALRasterBand  *poSrcBand;
-        poSrcBand = ((GDALDataset *)
-                     hSrcDataset)->GetRasterBand(ABS(psOptions->panBandList[0]));
+        GDALRasterBand *poSrcBand =
+            ((GDALDataset *) hSrcDataset)->
+                GetRasterBand(std::abs(psOptions->panBandList[0]));
         if (psOptions->panBandList[0] < 0)
             poSrcBand = poSrcBand->GetMaskBand();
         GDALColorTable* poColorTable = poSrcBand->GetColorTable();
         if (poColorTable == NULL)
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "Error : band %d has no color table", ABS(psOptions->panBandList[0]));
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Error : band %d has no color table",
+                     std::abs(psOptions->panBandList[0]));
             GDALClose((GDALDatasetH) poVDS);
             GDALTranslateOptionsFree(psOptions);
             return NULL;
@@ -1184,7 +1215,8 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
         else
             nSrcBand = psOptions->panBandList[i];
 
-        poSrcBand = ((GDALDataset *) hSrcDataset)->GetRasterBand(ABS(nSrcBand));
+        poSrcBand =
+            ((GDALDataset *) hSrcDataset)->GetRasterBand(std::abs(nSrcBand));
 
 /* -------------------------------------------------------------------- */
 /*      Select output data type to match source.                        */
@@ -1239,7 +1271,7 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
                             nDstMax = 0x7FFFFFFF;
                             break;
                         default:
-                            CPLAssert(FALSE);
+                            CPLAssert(false);
                             break;
                     }
 
@@ -1339,7 +1371,7 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
 
         if( bScale && !bHaveScaleSrc )
         {
-            double	adfCMinMax[2];
+            double adfCMinMax[2];
             GDALComputeRasterMinMax( poSrcBand, TRUE, adfCMinMax );
             dfScaleSrcMin = adfCMinMax[0];
             dfScaleSrcMax = adfCMinMax[1];
@@ -1393,6 +1425,13 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
 
             poSource->SetColorTableComponent(nComponent);
 
+            int bSuccess;
+            double dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
+            if ( bSuccess )
+            {
+                poSource->SetNoDataValue(dfNoData);
+            } 
+
             poSimpleSource = poSource;
         }
         else
@@ -1449,7 +1488,13 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
                 bSignedByte = true;
             int bClamped = FALSE, bRounded = FALSE;
             double dfVal;
-            if( bSignedByte )
+            if( eBandType == GDT_Float32 && CPLIsInf(psOptions->dfNoDataReal) )
+            {
+                dfVal = std::numeric_limits<float>::infinity();
+                if( psOptions->dfNoDataReal < 0 )
+                    dfVal = -dfVal;
+            }
+            else if( bSignedByte )
             {
                 if( psOptions->dfNoDataReal < -128 )
                 {
@@ -1512,7 +1557,8 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
     if (psOptions->eMaskMode == MASK_USER)
     {
         GDALRasterBand *poSrcBand =
-            (GDALRasterBand*)GDALGetRasterBand(hSrcDataset, ABS(psOptions->nMaskBand));
+            (GDALRasterBand*)GDALGetRasterBand(hSrcDataset,
+                                               std::abs(psOptions->nMaskBand));
         if (poSrcBand && poVDS->CreateMaskBand(GMF_PER_DATASET) == CE_None)
         {
             VRTSourcedRasterBand* hMaskVRTBand = (VRTSourcedRasterBand*)
@@ -1563,18 +1609,30 @@ GDALDatasetH GDALTranslate( const char *pszDest, GDALDatasetH hSrcDataset,
 /* -------------------------------------------------------------------- */
 /*      Write to the output file using CopyCreate().                    */
 /* -------------------------------------------------------------------- */
-    hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS,
-                             psOptions->bStrict, psOptions->papszCreateOptions,
-                             psOptions->pfnProgress, psOptions->pProgressData );
-    hOutDS = GDALTranslateFlush(hOutDS);
+    if( EQUAL(psOptions->pszFormat, "VRT") &&
+        psOptions->papszCreateOptions == NULL )
+    {
+        poVDS->SetDescription(pszDest);
+        hOutDS = (GDALDatasetH) poVDS ;
+        if( !EQUAL(pszDest, "") )
+        {
+            hOutDS = GDALTranslateFlush(hOutDS);
+        }
+    }
+    else
+    {
+        hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS,
+                                psOptions->bStrict, psOptions->papszCreateOptions,
+                                psOptions->pfnProgress, psOptions->pProgressData );
+        hOutDS = GDALTranslateFlush(hOutDS);
 
-    GDALClose( (GDALDatasetH) poVDS );
+        GDALClose( (GDALDatasetH) poVDS );
+    }
 
     GDALTranslateOptionsFree(psOptions);
     return hOutDS;
 }
 
-
 /************************************************************************/
 /*                           AttachMetadata()                           */
 /************************************************************************/
@@ -1594,7 +1652,6 @@ static void AttachMetadata( GDALDatasetH hDS, char **papszMetadataOptions )
         GDALSetMetadataItem(hDS,pszKey,pszValue,NULL);
         CPLFree( pszKey );
     }
-
 }
 
 /************************************************************************/
@@ -1744,7 +1801,7 @@ GDALTranslateOptions *GDALTranslateOptionsNew(char** papszArgv, GDALTranslateOpt
 /*      Handle command line arguments.                                  */
 /* -------------------------------------------------------------------- */
     int argc = CSLCount(papszArgv);
-    for( int i = 0; i < argc; i++ )
+    for( int i = 0; papszArgv != NULL && i < argc; i++ )
     {
         if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
         {
@@ -1816,7 +1873,6 @@ GDALTranslateOptions *GDALTranslateOptionsNew(char** papszArgv, GDALTranslateOpt
             psOptions->panBandList[psOptions->nBandCount-1] = nBand;
             if (bMask)
                 psOptions->panBandList[psOptions->nBandCount-1] *= -1;
-
         }
         else if( EQUAL(papszArgv[i],"-mask") &&  papszArgv[i+1] )
         {
diff --git a/apps/gdal_utilities.dox b/apps/gdal_utilities.dox
index 58e4ef0..7a411e5 100644
--- a/apps/gdal_utilities.dox
+++ b/apps/gdal_utilities.dox
@@ -1,15 +1,15 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_utilities.dox 34813 2016-07-28 16:38:56Z rouault $ */
+/* $Id: gdal_utilities.dox 37978 2017-04-13 15:25:54Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
-/*! 
+/*!
 \page gdal_utilities GDAL Utilities
 \brief A collection of GDAL related programs.
 
-The following utility programs are distributed with GDAL. 
+The following utility programs are distributed with GDAL.
 
 <ul>
-<li> \ref gdalinfo - report information about a file.
+<li> \ref gdalinfo - Report information about a file.
 <li> \ref gdal_translate - Copy a raster file, with control of output format.
 <li> \ref gdaladdo - Add overviews to a file.
 <li> \ref gdalwarp - Warp an image into a new coordinate system.
@@ -44,38 +44,40 @@ The following utility programs are distributed with GDAL.
 \section gdal_utilities_creating Creating New Files
 
 Access an existing file to read it is generally quite simple.  Just
-indicate the name of the file or dataset on the command line.  However, 
+indicate the name of the file or dataset on the command line.  However,
 creating a file is more complicated.  It may be necessary to indicate the
 the format to create, various creation options affecting how it will
-be created and perhaps a coordinate system to be assigned.  Many of 
+be created and perhaps a coordinate system to be assigned.  Many of
 these options are handled similarly by different GDAL utilities, and are
 introduced here. <p>
 
 <dl>
-<dt> <b>-of</b> <i>format</i></dt><dd> 
-Select the format to create the new file as.  The formats are assigned short 
-names such as GTiff (for GeoTIFF) or HFA (for Erdas Imagine).  The list of 
+<dt> <b>-of</b> <i>format</i></dt><dd>
+Select the format to create the new file as.  The formats are assigned short
+names such as GTiff (for GeoTIFF) or HFA (for Erdas Imagine).  The list of
 all format codes can be listed with the <b>\-\-formats</b> switch.  Only
 formats list as "(rw)" (read-write) can be written.<p>
 Many utilities default
 to creating GeoTIFF files if a format is not specified.  File extensions
 are not used to guess output format, nor are extensions generally added
-by GDAL if not indicated in the filename by the user. 
+by GDAL if not indicated in the filename by the user.
 </dd>
 
-<dt> <b>-co</b> <i>NAME=VALUE</i></dt><dd> 
+<dt> <b>-co</b> <i>NAME=VALUE</i></dt><dd>
 Many formats have one or more optional creation options that can be used
 to control particulars about the file created.  For instance, the GeoTIFF
 driver supports creation options to control compression, and whether the file
 should be tiled.<p>
-The creation options available vary by format driver, and some simple 
+The creation options available vary by format driver, and some simple
 formats have no creation options at all.  A list of options supported
 for a format can be listed with the "--format <format>" command line
-option but the web page for the format is the definitive source of 
-information on driver creation options.<p>
+option but the web page for the format is the definitive source of
+information on driver creation options. See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a><p>
 </dd>
 
-<dt> <b>-a_srs</b> <i>SRS</i></dt><dd> 
+<dt> <b>-a_srs</b> <i>SRS</i></dt><dd>
 Several utilities, (gdal_translate and gdalwarp) include the ability
 to specify coordinate systems with command line options like
 <b>-a_srs</b> (assign SRS to output), <b>-s_srs</b> (source SRS) and
@@ -84,24 +86,24 @@ These utilities allow the coordinate system (SRS = spatial reference system)
 to be assigned in a variety of formats.<p>
 
 <ul>
-<li> <b>NAD27</b>/<b>NAD83</b>/<b>WGS84</b>/<b>WGS72</b>: 
+<li> <b>NAD27</b>/<b>NAD83</b>/<b>WGS84</b>/<b>WGS72</b>:
 These common geographic (lat/long) coordinate
-systems can be used directly by these names. 
+systems can be used directly by these names.
 
 <li> <b>EPSG:</b><i>n</i>: Coordinate systems (projected or geographic) can
 be selected based on their EPSG codes, for instance EPSG:27700 is the British
-National Grid.  A list of EPSG coordinate systems can be found in the GDAL 
-data files gcs.csv and pcs.csv. 
+National Grid.  A list of EPSG coordinate systems can be found in the GDAL
+data files gcs.csv and pcs.csv.
 
 <li> <i>PROJ.4 Definitions</i>: A PROJ.4 definition string can be used
-as a coordinate system.  For instance "+proj=utm +zone=11 +datum=WGS84".  
+as a coordinate system.  For instance "+proj=utm +zone=11 +datum=WGS84".
 Take care to keep the proj.4 string together as a single argument to the
 command (usually by double quoting). <p>
 
 <li> <i>OpenGIS Well Known Text</i>: The Open GIS Consortium has defined
 a textual format for describing coordinate systems as part of the Simple
 Features specifications.  This format is the internal working format
-for coordinate systems used in GDAL.  The name of a file containing a 
+for coordinate systems used in GDAL.  The name of a file containing a
 WKT coordinate system definition may be used a coordinate system argument,
 or the entire coordinate system itself may be used as a command line
 option (though escaping all the quotes in WKT is quite challenging). <p>
@@ -114,7 +116,7 @@ in a similar manner to WKT files, but the filename should be prefixed with
 <li> <i>Spatial References from URLs</i>: For example
 http://spatialreference.org/ref/user/north-pacific-albers-conic-equal-area/.<p>
 
-<li> <i>filename</i>: The name of a file containing WKT, PROJ.4 strings, or 
+<li> <i>filename</i>: The name of a file containing WKT, PROJ.4 strings, or
 XML/GML coordinate system definitions can be provided. <p>
 
 </ul>
@@ -122,7 +124,7 @@ XML/GML coordinate system definitions can be provided. <p>
 </dl>
 
 \section gdal_utilities_switches General Command Line Switches
-All GDAL command line utility programs support the following 
+All GDAL command line utility programs support the following
 "general" options.<p>
 
 <dl>
@@ -130,7 +132,7 @@ All GDAL command line utility programs support the following
 
 <dt> <b>\-\-formats</b></dt><dd> List all raster formats supported by this
 GDAL build (read-only and read-write) and exit. The format support is indicated
- as follows: 'ro' is read-only driver; 
+ as follows: 'ro' is read-only driver;
 'rw' is read or write (i.e. supports CreateCopy);
 'rw+' is read, write and update (i.e. supports Create).
 A 'v' is appended for formats supporting virtual IO (/vsimem, /vsigzip, /vsizip, etc).
@@ -140,34 +142,34 @@ Create() method (marked as rw+), not just the CreateCopy() method.
 </dd>
 
 <dt> <b>\-\-format</b> <i>format</i></dt><dd>
-List detailed information about a single format driver.  The <i>format</i> 
-should be the short name reported in the <b>\-\-formats</b> list, such as 
+List detailed information about a single format driver.  The <i>format</i>
+should be the short name reported in the <b>\-\-formats</b> list, such as
 GTiff.</dd>
 
 <dt> <b>\-\-optfile</b> <i>file</i></dt><dd>
 Read the named file and substitute the contents into the command line
 options list.  Lines beginning with # will be ignored.  Multi-word arguments
-may be kept together with double quotes. 
+may be kept together with double quotes.
 </dd>
 
 <dt> <b>\-\-config</b> <i>key value</i></dt><dd>
 Sets the named <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">
-configuration keyword</a> to the given value, as opposed to 
+configuration keyword</a> to the given value, as opposed to
 setting them as environment variables.  Some common configuration keywords
 are GDAL_CACHEMAX (memory used internally for caching in megabytes)
 and GDAL_DATA (path of the GDAL "data" directory).  Individual drivers may
-be influenced by other configuration options.  
+be influenced by other configuration options.
 </dd>
 
 <dt> <b>\-\-debug</b> <i>value</i></dt><dd>
 Control what debugging messages are emitted.  A value of <i>ON</i> will
 enable all debug messages.  A value of <i>OFF</i> will disable all debug
 messages.  Another value will select only debug messages containing that
-string in the debug prefix code.  
+string in the debug prefix code.
 </dd>
 
 <dt> <b>\-\-help-general</b></dt><dd>
-Gives a brief usage message for the generic GDAL command line options 
+Gives a brief usage message for the generic GDAL command line options
 and exit.
 </dd>
 
@@ -175,15 +177,20 @@ and exit.
 
 \htmlonly
 <p>
-$Id: gdal_utilities.dox 34813 2016-07-28 16:38:56Z rouault $
+$Id: gdal_utilities.dox 37978 2017-04-13 15:25:54Z rouault $
 </p>
 \endhtmlonly
 */
 
 *******************************************************************************
-/*! \page gdalinfo gdalinfo
+/*!
+\if man
+\page gdalinfo
+\else
+\page gdalinfo gdalinfo
+\endif
 
-lists information about a raster dataset
+Lists information about a raster dataset.
 
 \section gdalinfo_synopsis SYNOPSIS
 
@@ -197,7 +204,7 @@ gdalinfo [--help-general] [-json] [-mm] [-stats] [-hist] [-nogcp] [-nomd]
 \section gdalinfo_description DESCRIPTION
 
 The gdalinfo program lists various information about a GDAL supported
-raster dataset. 
+raster dataset.
 <dl>
 <dt> <b>-json</b></dt><dd> Display the output in json format.</dd>
 <dt> <b>-mm</b></dt><dd> Force computation of the actual min/max values for each
@@ -232,25 +239,25 @@ subdataset name.</dd>
 The gdalinfo will report all of the following (if known):
 
 <ul>
-<li> The format driver used to access the file. 
+<li> The format driver used to access the file.
 <li> Raster size (in pixels and lines).
 <li> The coordinate system for the file (in OGC WKT).
 <li> The geotransform associated with the file (rotational coefficients are
-currently not reported).  
+currently not reported).
 <li> Corner coordinates in georeferenced, and if possible lat/long based on
-the full geotransform (but not GCPs). 
+the full geotransform (but not GCPs).
 <li> Ground control points.
-<li> File wide (including subdatasets) metadata. 
+<li> File wide (including subdatasets) metadata.
 <li> Band data types.
 <li> Band color interpretations.
 <li> Band block size.
-<li> Band descriptions. 
+<li> Band descriptions.
 <li> Band min/max values (internally known and possibly computed).
 <li> Band checksum (if computation asked).
 <li> Band NODATA value.
-<li> Band overview resolutions available. 
-<li> Band unit type (i.e.. "meters" or "feet" for elevation bands). 
-<li> Band pseudo-color tables. 
+<li> Band overview resolutions available.
+<li> Band unit type (i.e.. "meters" or "feet" for elevation bands).
+<li> Band pseudo-color tables.
 </ul>
 
 \section gdalinfo_api C API
@@ -260,7 +267,7 @@ Starting with GDAL 2.1, this utility is also callable from C with GDALInfo().
 \section gdalinfo_example EXAMPLE
 
 \verbatim
-gdalinfo ~/openev/utm.tif 
+gdalinfo ~/openev/utm.tif
 Driver: GTiff/GeoTIFF
 Size is 512, 512
 Coordinate System is:
@@ -295,9 +302,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 */
 
 *******************************************************************************
-/*! \page gdal_translate gdal_translate
+/*!
+\if man
+\page gdal_translate
+\else
+\page gdal_translate gdal_translate
+\endif
 
-converts raster data between different formats
+Converts raster data between different formats.
 
 \section gdal_translate_synopsis SYNOPSIS
 
@@ -321,8 +333,8 @@ gdal_translate [--help-general]
 
 \section gdal_translate_description DESCRIPTION
 
-The gdal_translate utility can be used to convert raster data between 
-different formats, potentially performing some operations like subsettings, 
+The gdal_translate utility can be used to convert raster data between
+different formats, potentially performing some operations like subsettings,
 resampling, and rescaling pixels in the process.
 
 <dl>
@@ -338,7 +350,7 @@ to select a set of input bands to write to the output file, or to reorder
 bands. Starting with GDAL 1.8.0, <i>band</i> can also be set to "mask,1"
 (or just "mask") to mean the mask band of the first band of the input dataset.</dd>
 <dt> <b>-mask</b> <i>band</i>:</dt><dd> (GDAL >= 1.8.0) Select an input band
-<i>band</i> to create output dataset mask band. Bands are numbered from 1. 
+<i>band</i> to create output dataset mask band. Bands are numbered from 1.
 <i>band</i> can be set to "none" to avoid copying the global mask of the input dataset if
 it exists. Otherwise it is copied by default ("auto"), unless the mask is an alpha channel,
 or if it is explicitly used to be a regular band of the output dataset ("-b mask").
@@ -357,7 +369,7 @@ is as a fraction of the input image size. Starting with GDAL 2.0, if one of the
 while maintaining the aspect ratio of the source dataset.</dd>
 <dt> <b>-tr</b> xres yres :</dt><dd>  (starting with GDAL 2.0)
 set target resolution. The values must be expressed in georeferenced units.
-Both must be positive values. This is exclusive with -outsize and -a_ullr.
+Both must be positive values. This is mutually exclusive with -outsize and -a_ullr.
 </dd>
 <dt> <b>-r</b>
 <i>{nearest (default),bilinear,cubic,cubicspline,lanczos,average,mode}</i>:</dt><dd>
@@ -385,7 +397,7 @@ It is also possible to use the "-exponent_bn" syntax where bn is a band number
 one or several specific bands.
 </dd>
 <dt> <b>-unscale</b>:</dt><dd> Apply the scale/offset metadata for the bands
-to convert scaled values to unscaled values.  It is also often necessary to 
+to convert scaled values to unscaled values.  It is also often necessary to
 reset the output datatype with the <b>-ot</b> switch.</dd>
 <dt> <b>-srcwin</b> <i>xoff yoff xsize ysize</i>:</dt><dd> Selects a subwindow
 from the source image for copying based on pixel/line location.  </dd>
@@ -396,7 +408,7 @@ changed with -projwin_srs).
 Note: in GDAL 2.1.0 and 2.1.1, using -projwin with coordinates not aligned with
 pixels will result in a sub-pixel shift. This has been corrected in later versions.
 When selecting non-nearest neighbour resampling, starting with GDAL 2.1.0,
-sub-pixel accuracy is however used.</dd>
+sub-pixel accuracy is however used to get better results.</dd>
 <dt> <b>-projwin_srs</b> <i>srs_def</i>:</dt><dd> (GDAL >= 2.0) Specifies the SRS in
 which to interpret the coordinates given with -projwin. The <i>srs_def</i> may
 be any of the usual GDAL/OGR forms, complete WKT, PROJ.4, EPSG:n or a file
@@ -413,8 +425,8 @@ outside the source raster extent.</dd>
 output file.  The <i>srs_def</i> may be any of the usual GDAL/OGR forms,
 complete WKT, PROJ.4, EPSG:n or a file containing the WKT. </dd>
 <dt> <b>-a_ullr</b> <i>ulx uly lrx lry</i>:</dt><dd>
-Assign/override the georeferenced bounds of the output file.  This assigns 
-georeferenced bounds to the output file, ignoring what would have been derived 
+Assign/override the georeferenced bounds of the output file.  This assigns
+georeferenced bounds to the output file, ignoring what would have been derived
 from the source file. So this does not cause reprojection to the specified SRS. </dd>
 <dt> <b>-a_nodata</b> <i>value</i>:</dt><dd>
 Assign a specified nodata value to output bands. Starting with GDAL 1.8.0, can
@@ -425,15 +437,16 @@ value to be changed to the value specified with this option.</dd>
 <dt> <b>-mo</b> <i>"META-TAG=VALUE"</i>:</dt><dd> Passes a metadata key and
 value to set on the output dataset if possible.</dd>
 <dt> <b>-co</b> <i>"NAME=VALUE"</i>:</dt><dd> Passes a creation option to the
-output format driver.  Multiple <b>-co</b> options may be listed.  See format 
-specific documentation for legal creation options for each format.</dd>
+output format driver.  Multiple <b>-co</b> options may be listed. See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a>.</dd>
 <dt> <b>-gcp</b> <i>pixel line easting northing elevation</i>:</dt><dd>
-Add the indicated ground control point to the output dataset.  This option 
-may be provided multiple times to provide a set of GCPs. 
+Add the indicated ground control point to the output dataset.  This option
+may be provided multiple times to provide a set of GCPs.
 </dd>
 <dt> <b>-q</b>:</dt><dd> Suppress progress monitor and other non-error
 output.</dd>
-<dt> <b>-sds</b>:</dt><dd> Copy all subdatasets of this file to individual 
+<dt> <b>-sds</b>:</dt><dd> Copy all subdatasets of this file to individual
 output files.  Use with formats like HDF or OGDI that have subdatasets.
 The output file naming scheme has changed in GDAL 1.11 (e.g. ofile_1.tif, ofile_2.tif).</dd>
 <dt> <b>-stats</b>:</dt><dd> (GDAL >= 1.8.0) Force (re)computation of statistics.</dd>
@@ -471,9 +484,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 */
 
 *******************************************************************************
-/*! \page gdaladdo gdaladdo
+/*!
+\if man
+\page gdaladdo
+\else
+\page gdaladdo gdaladdo
+\endif
 
-builds or rebuilds overview images
+Builds or rebuilds overview images.
 
 \section gdaladdo_synopsis SYNOPSIS
 
@@ -486,7 +504,7 @@ gdaladdo [-r {nearest,average,gauss,cubic,cubicspline,lanczos,average_mp,average
 \section gdaladdo_description DESCRIPTION
 
 The gdaladdo utility can be used to build or rebuild overview images for
-most supported file formats with one of several downsampling algorithms. 
+most supported file formats with one of several downsampling algorithms.
 
 <dl>
 <dt> <b>-r</b>
@@ -505,12 +523,12 @@ external overview (for GeoTIFF especially). </dd>
 
 <i>Mode</i> (available from GDAL 1.6.0) selects the value which appears most often of all the sampled points.
 <i>average_mp</i> is unsuitable for use.
-<i>Average_magphase</i> averages complex data in mag/phase space.  
-<i>Nearest</i> and <i>average</i> are applicable to normal image data.  
+<i>Average_magphase</i> averages complex data in mag/phase space.
+<i>Nearest</i> and <i>average</i> are applicable to normal image data.
 <i>Nearest</i> applies a nearest neighbour (simple sampling) resampler, while
 <i>average</i> computes the average of all non-NODATA contributing pixels.
 <i>Cubic</i> resampling (available from GDAL 1.7.0) applies a cubic convolution kernel.
-<i>Gauss</i> resampling (available from GDAL 1.6.0) applies a Gaussian kernel before computing the overview, 
+<i>Gauss</i> resampling (available from GDAL 1.6.0) applies a Gaussian kernel before computing the overview,
 which can lead to better results than simple averaging in e.g case of sharp edges
 with high contrast or noisy patterns. The advised level values should be 2, 4, 8, ...
 so that a 3x3 resampling Gaussian kernel is selected.
@@ -519,7 +537,7 @@ so that a 3x3 resampling Gaussian kernel is selected.
 
 gdaladdo will honour properly NODATA_VALUES tuples (special dataset metadata) so
 that only a given RGB triplet (in case of a RGB image) will be considered as the
-nodata value and not each value of the triplet independently per band. 
+nodata value and not each value of the triplet independently per band.
 
 Selecting a level value like <i>2</i> causes an overview level that is 1/2
 the resolution (in each dimension) of the base layer to be computed.  If
@@ -534,18 +552,18 @@ already has overviews computed, you don't need to clean the existing overviews.
 
 Some format drivers do not support overviews at all.  Many format drivers
 store overviews in a secondary file with the extension .ovr that is actually
-in TIFF format.  By default, the GeoTIFF driver stores overviews internally to the file 
+in TIFF format.  By default, the GeoTIFF driver stores overviews internally to the file
 operated on (if it is writable), unless the -ro flag is specified.
 
-Most drivers also support an alternate overview format using Erdas Imagine 
-format.  To trigger this use the USE_RRD=YES configuration option.  This will 
-place the overviews in an associated .aux file suitable for direct use with 
+Most drivers also support an alternate overview format using Erdas Imagine
+format.  To trigger this use the USE_RRD=YES configuration option.  This will
+place the overviews in an associated .aux file suitable for direct use with
 Imagine or ArcGIS as well as GDAL applications.  (e.g. --config USE_RRD YES)
 
 \section gdaladdo_externalgtiffoverviews External overviews in GeoTIFF format
 
-External overviews created in TIFF format may be compressed using the COMPRESS_OVERVIEW 
-configuration option.  All compression methods, supported by the GeoTIFF 
+External overviews created in TIFF format may be compressed using the COMPRESS_OVERVIEW
+configuration option.  All compression methods, supported by the GeoTIFF
 driver, are available here. (e.g. --config COMPRESS_OVERVIEW DEFLATE).
 The photometric interpretation can be set with --config PHOTOMETRIC_OVERVIEW {RGB,YCBCR,...},
 and the interleaving with --config INTERLEAVE_OVERVIEW {PIXEL|BAND}.
@@ -619,9 +637,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 */
 
 *******************************************************************************
-/*! \page gdaltindex gdaltindex
+/*!
+\if man
+\page gdaltindex
+\else
+\page gdaltindex gdaltindex
+\endif
 
-Builds a shapefile as a raster tileindex
+Builds a shapefile as a raster tileindex.
 
 \section gdaltindex_synopsis SYNOPSIS
 
@@ -634,10 +657,10 @@ gdaltindex [-f format] [-tileindex field_name] [-write_absolute_path]
 
 \section gdaltindex_description DESCRIPTION
 
-This program builds a shapefile with a record for each input raster file, 
+This program builds a shapefile with a record for each input raster file,
 an attribute containing the filename, and a polygon geometry outlining the
-raster.  This output is suitable for use with <a href="http://mapserver.org/">MapServer</a> as a raster 
-tileindex. 
+raster.  This output is suitable for use with <a href="http://mapserver.org/">MapServer</a> as a raster
+tileindex.
 
 <dl>
 <dt><b>-f</b> format:</dt><dd> (GDAL >= 1.11)
@@ -655,10 +678,10 @@ tileindex.
 <dt><b>-t_srs</b> target_srs:</dt>
 <dd><p>Geometries of input files will be transformed to the desired target coordinate reference system. Using this option generates files that are not compatible with MapServer < 6.4. Default creates simple rectangular polygons in the same coordinate reference system as the input rasters.</p>
 </dd>
-<dt><b>-src_srs_name</b> field_name:</dt><dd> (GDAL >= 1.11) 
+<dt><b>-src_srs_name</b> field_name:</dt><dd> (GDAL >= 1.11)
 <p>The name of the field to store the SRS of each tile. This field name can be used as the value of the TILESRS keyword in MapServer >= 6.4.</p>
 </dd>
-<dt><b>-src_srs_format</b> type:</dt><dd> (GDAL >= 1.11) 
+<dt><b>-src_srs_format</b> type:</dt><dd> (GDAL >= 1.11)
 <p>The format in which the SRS of each tile must be written. Types can be AUTO, WKT, EPSG, PROJ.</p>
 </dd>
 <dt><b>-lyr_name</b> name:</dt>
@@ -678,9 +701,9 @@ tileindex.
 Examples:
 \endhtmlonly
 
-Produce a shapefile (<code>doq_index.shp</code>) with a record for every 
-image that the utility found in the <code>doq</code> folder. Each record holds 
-information that points to the location of the image and also a bounding rectangle 
+Produce a shapefile (<code>doq_index.shp</code>) with a record for every
+image that the utility found in the <code>doq</code> folder. Each record holds
+information that points to the location of the image and also a bounding rectangle
 shape showing the bounds of the image:
 
 \verbatim
@@ -702,9 +725,14 @@ Frank Warmerdam <warmerdam at pobox.com>
 
 
 *******************************************************************************
-/*! \page gdalbuildvrt gdalbuildvrt
+/*!
+\if man
+\page gdalbuildvrt
+\else
+\page gdalbuildvrt gdalbuildvrt
+\endif
 
-Builds a VRT from a list of datasets. (compiled by default since GDAL 1.6.1)
+Builds a VRT from a list of datasets.
 
 \section gdalbuildvrt_synopsis SYNOPSIS
 
@@ -715,9 +743,10 @@ gdalbuildvrt [-tileindex field_name]
              [-separate] [-b band]* [-sd subdataset]
              [-allow_projection_difference] [-q]
              [-addalpha] [-hidenodata]
-             [-srcnodata "value [value...]"] [-vrtnodata "value [value...]"] 
+             [-srcnodata "value [value...]"] [-vrtnodata "value [value...]"]
              [-a_srs srs_def]
              [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]
+             [-oo NAME=VALUE]*
              [-input_file_list my_list.txt] [-overwrite] output.vrt [gdalfile]*
 \endverbatim
 
@@ -754,11 +783,11 @@ in GDAL 1.6.1.
 
 <dl>
 
-<dt> <b>-tileindex</b>:</dt><dd> 
-Use the specified value as the tile index field, instead of the default value with is 'location'. 
+<dt> <b>-tileindex</b>:</dt><dd>
+Use the specified value as the tile index field, instead of the default value with is 'location'.
 </dd>
 
-<dt> <b>-resolution</b> {highest|lowest|average|user}:</dt><dd> 
+<dt> <b>-resolution</b> {highest|lowest|average|user}:</dt><dd>
 In case the resolution of all input files is not the same, the -resolution flag
 enables the user to control the way the output resolution is computed. 'average' is the default.
 'highest' will pick the smallest values of pixel dimensions within the set of source rasters.
@@ -797,14 +826,14 @@ dataset which doesn't report nodata value but is transparent in areas with no
 data.</dd>
 
 <dt> <b>-srcnodata</b> <em>value [value...]</em>:</dt><dd> (starting with GDAL 1.7.0)
-Set nodata values for input bands (different values can be supplied for each band). If 
-more than one value is supplied all values should be quoted to keep them 
+Set nodata values for input bands (different values can be supplied for each band). If
+more than one value is supplied all values should be quoted to keep them
 together as a single operating system argument. If the option is not specified, the
 intrinsic nodata settings on the source datasets will be used (if they exist). The value set by this option
 is written in the NODATA element of each ComplexSource element. Use a value of
 <tt>None</tt> to ignore intrinsic nodata settings on the source datasets.</dd>
 
-<dt> <b>-b</b> <i>band</i>:</dt><dd>(GDAL >= 1.10.0) 
+<dt> <b>-b</b> <i>band</i>:</dt><dd>(GDAL >= 1.10.0)
 Select an input <i>band</i> to be processed. Bands are numbered from 1.
 If input bands not set all bands will be added to vrt.
 Multiple <b>-b</b> switches may be used to select a set of input bands.</dd>
@@ -842,7 +871,10 @@ complete WKT, PROJ.4, EPSG:n or a file containing the WKT. </dd>
 <i>{nearest (default),bilinear,cubic,cubicspline,lanczos,average,mode}</i>:</dt><dd>
 (GDAL >= 2.0) Select a resampling algorithm.</dd>
 
-<dt> <b>-input_file_list</b>:</dt><dd> 
+<dt> <b>-oo</b> <em>NAME=VALUE</em>:</dt><dd>(starting with GDAL 2.2)
+Dataset open option (format specific)</dd>
+
+<dt> <b>-input_file_list</b>:</dt><dd>
 To specify a text file with an input filename on each line
 </dd>
 
@@ -887,9 +919,14 @@ Even Rouault <even.rouault at mines-paris.org>
 */
 
 *******************************************************************************
-/*! \page gdal_contour gdal_contour
+/*!
+\if man
+\page gdal_contour
+\else
+\page gdal_contour gdal_contour
+\endif
 
-builds vector contour lines from a raster elevation model
+Builds vector contour lines from a raster elevation model.
 
 \section gdal_contour_synopsis SYNOPSIS
 
@@ -899,13 +936,13 @@ Usage: gdal_contour [-b <band>] [-a <attribute_name>] [-3d] [-inodata]
                     [-f <formatname>] [[-dsco NAME=VALUE] ...] [[-lco NAME=VALUE] ...]
                     [-off <offset>] [-fl <level> <level>...]
                     [-nln <outlayername>]
-                    <src_filename> <dst_filename> 
+                    <src_filename> <dst_filename>
 \endverbatim
 
 \section gdal_contour_description DESCRIPTION
 
 This program generates a vector contour file from the input raster elevation
-model (DEM). 
+model (DEM).
 
 Starting from version 1.7 the contour line-strings will be oriented
 consistently. The high side will be on the right, i.e. a line string goes
@@ -964,15 +1001,20 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 */
 
 *******************************************************************************
-/*! \page gdal_rasterize gdal_rasterize
+/*!
+\if man
+\page gdal_rasterize
+\else
+\page gdal_rasterize gdal_rasterize
+\endif
 
-burns vector geometries into a raster
+Burns vector geometries into a raster.
 
 \section gdal_rasterize_synopsis SYNOPSIS
 
 \verbatim
 Usage: gdal_rasterize [-b band]* [-i] [-at]
-       [-burn value]* | [-a attribute_name] [-3d]
+       {[-burn value]* | [-a attribute_name] | [-3d]} [-add]
        [-l layername]* [-where expression] [-sql select_statement]
        [-dialect dialect] [-of format] [-a_srs srs_def]
        [-co "NAME=VALUE"]* [-a_nodata value] [-init value]*
@@ -985,8 +1027,8 @@ Usage: gdal_rasterize [-b band]* [-i] [-at]
 \section gdal_rasterize_description DESCRIPTION
 
 This program burns vector geometries (points, lines, and polygons) into the
-raster band(s) of a raster image.  Vectors are read from OGR supported vector 
-formats. 
+raster band(s) of a raster image.  Vectors are read from OGR supported vector
+formats.
 
 Note that on the fly reprojection of vector data to the coordinate system of the
 raster data is only supported since GDAL 2.1.0.
@@ -995,14 +1037,14 @@ Since GDAL 1.8.0, the target GDAL file can be created by gdal_rasterize. Either
 the -tr or -ts option must be used in that case.
 
 <dl>
-<dt> <b>-b</b> <em>band</em>: </dt><dd> 
-The band(s) to burn values into.  Multiple -b arguments may be used to burn 
+<dt> <b>-b</b> <em>band</em>: </dt><dd>
+The band(s) to burn values into.  Multiple -b arguments may be used to burn
 into a list of bands.  The default is to burn into band 1.</dd>
 
 <dt> <b>-i</b>: </dt><dd>
-Invert rasterization.  Burn the fixed burn value, or the burn value associated 
+Invert rasterization.  Burn the fixed burn value, or the burn value associated
 with the first feature into all parts of the image <em>not</em> inside the
-provided a polygon.</dd>
+provided polygon.</dd>
 
 <dt> <b>-at</b>: </dt><dd>
 Enables the ALL_TOUCHED rasterization option so that all pixels touched
@@ -1010,30 +1052,32 @@ by lines or polygons will be updated, not just those on the line render path,
 or whose center point is within the polygon.  Defaults to disabled for normal
 rendering rules.</dd>
 
-<dt> <b>-burn</b> <em>value</em>: </dt><dd> 
-A fixed value to burn into a band for all objects.  A list of -burn options 
+<dt> <b>-burn</b> <em>value</em>: </dt><dd>
+A fixed value to burn into a band for all objects.  A list of -burn options
 can be supplied, one per band being written to.</dd>
 
-<dt> <b>-a</b> <em>attribute_name</em>: </dt><dd> 
+<dt> <b>-a</b> <em>attribute_name</em>: </dt><dd>
 Identifies an attribute field on the features to be used for a burn-in value.
 The value will be burned into all output bands.</dd>
 
-<dt> <b>-3d</b>: </dt><dd> 
-Indicates that a burn value should be extracted from the "Z" values of the 
-feature. These values are added to the burn value given by "-burn value" or
-"-a attribute_name" if provided. As of now, only points and lines are drawn in
-3D.</dd>
+<dt> <b>-3d</b>: </dt><dd>
+Indicates that a burn value should be extracted from the "Z" values of the
+feature. As of now, only points and lines are drawn in 3D.</dd>
 
-<dt> <b>-l</b> <em>layername</em>: </dt><dd> 
-Indicates the layer(s) from the datasource that will be used for input 
+<dt> <b>-add</b>: </dt><dd>
+Instead of burning a new value, this adds the new value to the existing raster.
+Suitable for heatmaps for instance.</dd>
+
+<dt> <b>-l</b> <em>layername</em>: </dt><dd>
+Indicates the layer(s) from the datasource that will be used for input
 features.  May be specified multiple times, but at least one layer name or a
 -sql option must be specified.</dd>
 
-<dt> <b>-where</b> <em>expression</em>: </dt><dd> 
-An optional SQL WHERE style query expression to be applied to select features 
+<dt> <b>-where</b> <em>expression</em>: </dt><dd>
+An optional SQL WHERE style query expression to be applied to select features
 to burn in from the input layer(s). </dd>
 
-<dt> <b>-sql</b> <em>select_statement</em>: </dt><dd> 
+<dt> <b>-sql</b> <em>select_statement</em>: </dt><dd>
 An SQL statement to be evaluated against the datasource to produce a
 virtual layer of features to be burned in.</dd>
 
@@ -1063,15 +1107,16 @@ EPSG:n or a file containing the WKT. </dd>
 
 <dt> <b>-co</b> <i>"NAME=VALUE"</i>:</dt><dd> (GDAL >= 1.8.0)
 Passes a creation option to the output format driver.  Multiple <b>-co</b>
-options may be listed.  See format specific documentation for legal creation
-options for each format.</dd>
+options may be listed. See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a>.</dd>
 
-<dt> <b>-te</b> <em>xmin ymin xmax ymax</em> :</dt><dd> (GDAL >= 1.8.0) 
+<dt> <b>-te</b> <em>xmin ymin xmax ymax</em> :</dt><dd> (GDAL >= 1.8.0)
 Set georeferenced extents. The values must be expressed in georeferenced units.
 If not specified, the extent of the output file will be the extent of the vector
 layers. </dd>
 
-<dt> <b>-tr</b> <em>xres yres</em> :</dt><dd> (GDAL >= 1.8.0) 
+<dt> <b>-tr</b> <em>xres yres</em> :</dt><dd> (GDAL >= 1.8.0)
 Set target resolution. The values must be expressed in georeferenced units.
 Both must be positive values.
 </dd>
@@ -1090,11 +1135,11 @@ For the output bands to be of the indicated data type. Defaults to Float64</dd>
 <dt> <b>-q</b>:</dt><dd> (GDAL >= 1.8.0) Suppress progress monitor and other
 non-error output.</dd>
 
-<dt> <em>src_datasource</em>: </dt><dd> 
+<dt> <em>src_datasource</em>: </dt><dd>
 Any OGR supported readable datasource.</dd>
 
-<dt> <em>dst_filename</em>: </dt><dd> 
-The GDAL supported output file.  Must support update mode access.  
+<dt> <em>dst_filename</em>: </dt><dd>
+The GDAL supported output file.  Must support update mode access.
 Before GDAL 1.8.0, gdal_rasterize could not create new output files.</dd>
 
 </dl>
@@ -1106,7 +1151,7 @@ Starting with GDAL 2.1, this utility is also callable from C with GDALRasterize(
 \section gdal_rasterize_example EXAMPLE
 
 The following would burn all polygons from mask.shp into the RGB TIFF
-file work.tif with the color red (RGB = 255,0,0).  
+file work.tif with the color red (RGB = 255,0,0).
 
 \verbatim
 gdal_rasterize -b 1 -b 2 -b 3 -burn 255 -burn 0 -burn 0 -l mask mask.shp work.tif
@@ -1126,9 +1171,14 @@ Frank Warmerdam <warmerdam at pobox.com>
 */
 
 *******************************************************************************
-/*! \page rgb2pct rgb2pct.py
+/*!
+\if man
+\page rgb2pct
+\else
+\page rgb2pct rgb2pct.py
+\endif
 
-Convert a 24bit RGB image to 8bit paletted
+Convert a 24bit RGB image to 8bit paletted.
 
 \section rgb2pct_synopsis SYNOPSIS
 
@@ -1139,10 +1189,10 @@ rgb2pct.py [-n colors | -pct palette_file] [-of format] source_file dest_file
 \section rgb2pct_description DESCRIPTION
 
 This utility will compute an optimal pseudo-color table for a given RGB image
-using a median cut algorithm on a downsampled RGB histogram.   Then it 
+using a median cut algorithm on a downsampled RGB histogram.   Then it
 converts the image into a pseudo-colored image using the color table.
-This conversion utilizes Floyd-Steinberg dithering (error diffusion) to 
-maximize output image visual quality. 
+This conversion utilizes Floyd-Steinberg dithering (error diffusion) to
+maximize output image visual quality.
 
 <dl>
 <dt> <b>-n</b> <i>colors</i>:</dt><dd> Select the number of colors in the generated
@@ -1160,13 +1210,13 @@ created.</dd>
 </dl>
 
 NOTE: rgb2pct.py is a Python script, and will only work if GDAL was built
-with Python support.  
+with Python support.
 
 \section rgb2pct_example EXAMPLE
 
 If it is desired to hand create the palette, likely the simplest text format
-is the GDAL VRT format.  In the following example a VRT was created in a 
-text editor with a small 4 color palette with the RGBA colors 238/238/238/255, 
+is the GDAL VRT format.  In the following example a VRT was created in a
+text editor with a small 4 color palette with the RGBA colors 238/238/238/255,
 237/237/237/255, 236/236/236/255 and 229/229/229/255.
 
 \verbatim
@@ -1182,7 +1232,7 @@ text editor with a small 4 color palette with the RGBA colors 238/238/238/255,
       <Entry c1="229" c2="229" c3="229" c4="255"/>
     </ColorTable>
   </VRTRasterBand>
-</VRTDataset> 
+</VRTDataset>
 \endverbatim
 
 \if man
@@ -1192,14 +1242,19 @@ Frank Warmerdam <warmerdam at pobox.com>
 */
 
 *******************************************************************************
-/*! \page pct2rgb pct2rgb.py
+/*!
+\if man
+\page pct2rgb
+\else
+\page pct2rgb pct2rgb.py
+\endif
 
-Convert an 8bit paletted image to 24bit RGB
+Convert an 8bit paletted image to 24bit RGB.
 
 \section pct2rgb_synopsis SYNOPSIS
 
 \htmlonly
-Usage: 
+Usage:
 \endhtmlonly
 
 \verbatim
@@ -1209,11 +1264,11 @@ pct2rgb.py [-of format] [-b band] [-rgba] source_file dest_file
 \section pct2rgb_description DESCRIPTION
 
 This utility will convert a pseudo-color band on the input file into an output
-RGB file of the desired format. 
+RGB file of the desired format.
 
 <dl>
 <dt> <b>-of</b> <i>format</i>:</dt><dd> Format to generated (defaults to GeoTIFF).</dd>
-<dt> <b>-b</b> <i>band</i>:</dt><dd> 
+<dt> <b>-b</b> <i>band</i>:</dt><dd>
 Band to convert to RGB, defaults to 1.</dd>
 <dt> <b>-rgba:</b></dt><dd> Generate a RGBA file (instead of a RGB file by default).</dd>
 <dt> <i>source_file</i>:</dt><dd> The input file. </dd>
@@ -1233,9 +1288,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 */
 
 *******************************************************************************
-/*! \page gdaltransform gdaltransform
-	
-transforms coordinates 
+/*!
+\if man
+\page gdaltransform
+\else
+\page gdaltransform gdaltransform
+\endif
+
+Transforms coordinates.
 
 \section gdaltransform_synopsis SYNOPSIS
 
@@ -1290,7 +1350,7 @@ no support for DMS input or output.
 
 If an input image file is provided, input is in pixel/line coordinates on that
 image.  If an output file is provided, output is in pixel/line coordinates
-on that image.  
+on that image.
 
 \section gdaltransform_example Reprojection Example
 
@@ -1301,23 +1361,23 @@ gdaltransform -s_srs EPSG:28992 -t_srs EPSG:31370
 177502 311865
 \endverbatim
 
-Produces the following output in meters in the "Belge 1972 / Belgian Lambert 
+Produces the following output in meters in the "Belge 1972 / Belgian Lambert
 72" projection:
 
 \verbatim
 244510.77404604 166154.532871342 -1046.79270555763
 \endverbatim
 
-\section gdaltransform_example Image RPC Example
+\section gdaltransform_rpc_example Image RPC Example
 
 The following command requests an RPC based transformation using the RPC
 model associated with the named file.  Because the -i (inverse) flag is
-used, the transformation is from output georeferenced (WGS84) coordinates 
-back to image coordinates. 
+used, the transformation is from output georeferenced (WGS84) coordinates
+back to image coordinates.
 
 \verbatim
 gdaltransform -i -rpc 06OCT20025052-P2AS-005553965230_01_P001.TIF
-125.67206 39.85307 50                    
+125.67206 39.85307 50
 \endverbatim
 
 Produces this output measured in pixels and lines on the image:
@@ -1331,9 +1391,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Jan Hartmann <j.l.h.hartmann at uva.nl>
 \endif
 */
 *******************************************************************************
-/*! \page nearblack nearblack
+/*!
+\if man
+\page nearblack
+\else
+\page nearblack nearblack
+\endif
 
-convert nearly black/white borders to black
+Convert nearly black/white borders to black.
 
 \section nearblack_synopsis SYNOPSIS
 
@@ -1356,43 +1421,44 @@ created.  Newly created files are created with the HFA driver by default
 <dt> <b>-of</b> <i>format</i>:</dt><dd> (GDAL 1.8.0 or later) Select the output format.
 Use the short format name (GTiff for GeoTIFF for example).</dd>
 <dt> <b>-co</b> <i>"NAME=VALUE"</i>:</dt><dd> (GDAL 1.8.0 or later) Passes a creation option to the
-output format driver.  Multiple <b>-co</b> options may be listed.  See format 
-specific documentation for legal creation options for each format. Only valid when creating a new file</dd>
-<dt> <b>-white</b>:</dt><dd> 
+output format driver.  Multiple <b>-co</b> options may be listed. See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a>. Only valid when creating a new file</dd>
+<dt> <b>-white</b>:</dt><dd>
 Search for nearly white (255) pixels instead of nearly black pixels.
 </dd>
 <dt> <b>-color</b> <i>c1,c2,c3...cn</i>:</dt><dd> (GDAL >= 1.9.0)
 Search for pixels near the specified color. May be specified multiple times.
 When -color is specified, the pixels that are considered as the collar are set to 0.
 </dd>
-<dt> <b>-near</b> <i>dist</i>:</dt><dd> 
-Select how far from black, white or custom colors the pixel values can be and still considered near black, white or custom color.  Defaults to 15. 
+<dt> <b>-near</b> <i>dist</i>:</dt><dd>
+Select how far from black, white or custom colors the pixel values can be and still considered near black, white or custom color.  Defaults to 15.
 </dd>
-<dt> <b>-nb</b> <i>non_black_pixels</i>:</dt><dd> 
-number of non-black pixels that can be encountered before the giving up search inwards. Defaults to 2. 
+<dt> <b>-nb</b> <i>non_black_pixels</i>:</dt><dd>
+number of non-black pixels that can be encountered before the giving up search inwards. Defaults to 2.
 </dd>
-<dt> <b>-setalpha</b>:</dt><dd> (GDAL 1.8.0 or later) 
+<dt> <b>-setalpha</b>:</dt><dd> (GDAL 1.8.0 or later)
 Adds an alpha band if the output file is specified and the input file has 3 bands,
 or sets the alpha band of the output file if it is specified and the input file has 4 bands,
 or sets the alpha band of the input file if it has 4 bands and no output file is specified.
 The alpha band is set to 0 in the image collar and to 255 elsewhere.
 </dd>
-<dt> <b>-setmask</b>:</dt><dd> (GDAL 1.8.0 or later) 
+<dt> <b>-setmask</b>:</dt><dd> (GDAL 1.8.0 or later)
 Adds a mask band to the output file,
 or adds a mask band to the input file if it does not already have one and no output file is specified.
 The mask band is set to 0 in the image collar and to 255 elsewhere.
 </dd>
 <dt> <b>-q</b>:</dt><dd> (GDAL 1.8.0 or later) Suppress progress monitor and other non-error
 output.</dd>
-<dt> <i>infile</i>:</dt><dd> 
-The input file.  Any GDAL supported format, any number of bands, normally 8bit 
+<dt> <i>infile</i>:</dt><dd>
+The input file.  Any GDAL supported format, any number of bands, normally 8bit
 Byte bands.
 </dd>
 </dl>
 
-The algorithm processes the image one scanline at a time.  A scan "in" is done 
-from either end setting pixels to black or white until at least 
-"non_black_pixels" pixels that are more than "dist" gray levels away from 
+The algorithm processes the image one scanline at a time.  A scan "in" is done
+from either end setting pixels to black or white until at least
+"non_black_pixels" pixels that are more than "dist" gray levels away from
 black, white or custom colors have been encountered at which point the scan stops.  The nearly
 black, white or custom color pixels are set to black or white. The algorithm also scans from
 top to bottom and from bottom to top to identify indentations in the top or bottom.
@@ -1400,7 +1466,7 @@ top to bottom and from bottom to top to identify indentations in the top or bott
 The processing is all done in 8bit (Bytes).
 
 If the output file is omitted, the processed results will be written back
-to the input file - which must support update. 
+to the input file - which must support update.
 
 \section nearblack_api C API
 
@@ -1413,9 +1479,14 @@ Frank Warmerdam <warmerdam at pobox.com>
 */
 
 *******************************************************************************
-/*! \page gdal_merge gdal_merge.py
+/*!
+\if man
+\page gdal_merge
+\else
+\page gdal_merge gdal_merge.py
+\endif
 
-mosaics a set of images
+Mosaics a set of images.
 
 \section gdal_merge_synopsis SYNOPSIS
 
@@ -1430,20 +1501,23 @@ gdal_merge.py [-o out_filename] [-of out_format] [-co NAME=VALUE]*
 \section gdal_merge_description DESCRIPTION
 
 This utility will automatically mosaic a set of images.  All the images must
-be in the same coordinate system and have a matching number of bands, but 
+be in the same coordinate system and have a matching number of bands, but
 they may be overlapping, and at different resolutions. In areas of overlap,
 the last image will be copied over earlier ones.
 
 <dl>
 <dt> <b>-o</b> <i>out_filename</i>:</dt><dd> The name of the output file,
 which will be created if it does not already exist (defaults to "out.tif").</dd>
-<dt> <b>-of</b> <i>format</i>:</dt><dd> 
-Output format, defaults to GeoTIFF (GTiff). 
+<dt> <b>-of</b> <i>format</i>:</dt><dd>
+Output format, defaults to GeoTIFF (GTiff).
 </dd>
-<dt> <b>-co</b> <i>NAME=VALUE</i>:</dt><dd> 
+<dt> <b>-co</b> <i>NAME=VALUE</i>:</dt><dd>
 Creation option for output file.  Multiple options can be specified.
+See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a>
 </dd>
-<dt> <b>-ot</b> <i>datatype</i>:</dt><dd> 
+<dt> <b>-ot</b> <i>datatype</i>:</dt><dd>
 Force the output image bands to have a specific type. Use type names (i.e. Byte, Int16,...)
 </dd>
 <dt> <b>-ps</b> <i>pixelsize_x pixelsize_y</i>:</dt><dd> Pixel size to be used for the
@@ -1454,32 +1528,32 @@ be used.</dd>
 the coordinates of the extent of the output file to the values of the -tr,
 such that the aligned extent includes the minimum extent.</dd>
 
-<dt> <b>-ul_lr</b> <i>ulx uly lrx lry</i>:</dt><dd> The extents of the output file. 
+<dt> <b>-ul_lr</b> <i>ulx uly lrx lry</i>:</dt><dd> The extents of the output file.
 If not specified the aggregate extents of all input files will be
 used.</dd>
 <dt>
 <dt> <b>-v</b>:</dt><dd> Generate verbose output of mosaicing operations as they are done.</dd>
-<dt> <b>-separate</b>:</dt><dd> 
-Place each input file into a separate band. 
+<dt> <b>-separate</b>:</dt><dd>
+Place each input file into a separate band.
 </dd>
-<dt> <b>-pct</b>:</dt><dd> 
+<dt> <b>-pct</b>:</dt><dd>
 Grab a pseudo-color table from the first input image, and use it for the output.
 Merging pseudo-colored images this way assumes that all input files use the same
 color table.
 </dd>
-<dt> <b>-n</b> <i>nodata_value</i>:</dt><dd> 
-Ignore pixels from files being merged in with this pixel value. 
+<dt> <b>-n</b> <i>nodata_value</i>:</dt><dd>
+Ignore pixels from files being merged in with this pixel value.
 </dd>
 <dt> <b>-a_nodata</b> <i>output_nodata_value</i>:</dt><dd>
 (GDAL >= 1.9.0) Assign a specified nodata value to output bands.</dd>
-<dt> <b>-init</b> <i>"value(s)"</i>:</dt><dd> 
+<dt> <b>-init</b> <i>"value(s)"</i>:</dt><dd>
 Pre-initialize the output image bands with these values.  However, it is not
 marked as the nodata value in the output file.  If only one value is given, the
-same value is used in all the bands. 
+same value is used in all the bands.
 </dd>
-<dt> <b>-createonly</b>:</dt><dd> 
+<dt> <b>-createonly</b>:</dt><dd>
 The output file is created (and potentially pre-initialized) but no input
-image data is copied into it.  
+image data is copied into it.
 </dd>
 </dl>
 
@@ -1508,9 +1582,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 */
 
 *******************************************************************************
-/*! \page gdal2tiles gdal2tiles.py
+/*!
+\if man
+\page gdal2tiles
+\else
+\page gdal2tiles gdal2tiles.py
+\endif
 
-generates directory with TMS tiles, KMLs and simple web viewers
+Generates directory with TMS tiles, KMLs and simple web viewers.
 
 \section gdal2tiles_synopsis SYNOPSIS
 
@@ -1534,7 +1613,7 @@ GDAL2Tiles also creates the necessary metadata for Google Earth (KML
 SuperOverlay), in case the supplied map uses EPSG:4326 projection.
 
 World files and embedded georeferencing is used during tile generation, but you
-can publish a picture without proper georeferencing too. 
+can publish a picture without proper georeferencing too.
 
 <dl>
 <dt> <b>-p</b> <i>PROFILE</i>, --profile=<i>PROFILE</i>:</dt>
@@ -1598,9 +1677,14 @@ Klokan Petr Pridal <klokan at klokan.cz> as a Google SoC 2007 Project.
 */
 
 *******************************************************************************
-/*! \page gdal-config gdal-config
+/*!
+\if man
+\page gdal-config
+\else
+\page gdal-config gdal-config
+\endif
 
-determines various information about a GDAL installation
+Determines various information about a GDAL installation.
 
 \section gdal_config_synopsis SYNOPSIS
 
@@ -1620,7 +1704,7 @@ Options:
 This utility script (available on Unix systems) can be used to determine
 various information about a GDAL installation.  It is normally just used
 by configure scripts for applications using GDAL but can be queried by an
-end user. 
+end user.
 
 <dl>
 <dt> <b>\-\-prefix</b>:</dt><dd> the top level directory for the GDAL
@@ -1632,17 +1716,22 @@ modules using GDAL.</dd>
 <dt> <b>\-\-version</b>:</dt><dd> Reports the GDAL version.</dd>
 <dt> <b>\-\-ogr-enabled</b>:</dt><dd> Reports "yes" or "no" to standard output depending
 on whether OGR is built into GDAL.</dd>
-<dt> <b>\-\-formats</b>:</dt><dd> Reports which formats are configured into GDAL 
-to stdout.  
+<dt> <b>\-\-formats</b>:</dt><dd> Reports which formats are configured into GDAL
+to stdout.
 </dd>
 </dl>
 
 */
 
 *******************************************************************************
-/*! \page gdal_retile gdal_retile.py
+/*!
+\if man
+\page gdal_retile
+\else
+\page gdal_retile gdal_retile.py
+\endif
 
-gdal_retile.py retiles a set of tiles and/or build tiled pyramid levels
+Retiles a set of tiles and/or build tiled pyramid levels.
 
 \if man
 \section retile_synopsis SYNOPSIS
@@ -1655,6 +1744,7 @@ Usage:
 \verbatim
 
 gdal_retile.py [-v] [-co NAME=VALUE]* [-of out_format] [-ps pixelWidth pixelHeight]
+               [-overlap val_in_pixel]
                [-ot  {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
                       CInt16/CInt32/CFloat32/CFloat64}]'
                [ -tileIndex tileIndexName [-tileIndexField tileIndexFieldName]]
@@ -1662,7 +1752,7 @@ gdal_retile.py [-v] [-co NAME=VALUE]* [-of out_format] [-ps pixelWidth pixelHeig
                [-s_srs srs_def]  [-pyramidOnly]
                [-r {near/bilinear/cubic/cubicspline/lanczos}]
                -levels numberoflevels
-               [-useDirForEachRow]   
+               [-useDirForEachRow]
                -targetDir TileDirectory input_files
 
 \endverbatim
@@ -1688,6 +1778,9 @@ Output format, defaults to GeoTIFF (GTiff).
 </dd>
 <dt> <b>-co</b> <i>NAME=VALUE</i>:</dt><dd>
 Creation option for output file.  Multiple options can be specified.
+See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a>
 </dd>
 <dt> <b>-ot</b> <i>datatype</i>:</dt><dd>
 Force the output image bands to have a specific type. Use type names (i.e. Byte, Int16,...)
@@ -1695,6 +1788,9 @@ Force the output image bands to have a specific type. Use type names (i.e. Byte,
 <dt> <b>-ps</b> <i>pixelsize_x pixelsize_y</i>:</dt><dd> Pixel size to be used for the
 output file.  If not specified, 256 x 256 is the default
 </dd>
+<dt> <b>-overlap</b> <i>val_in_pixel</i>:</dt><dd> (GDAL >= 2.2) Overlap in
+pixels between consecutive tiles. If not specified, 0 is the default
+</dd>
 <dt> <b>-levels</b> <i>numberOfLevels</i>:</dt><dd>
 Number of pyramids levels to build.
 </dd>
@@ -1731,8 +1827,8 @@ The column delimiter used in the CSV file, default value is a semicolon ";"
 </dd>
 <dt> <b>-useDirForEachRow</b>:</dt><dd>
 Normally the tiles of the base image are stored as described in <b>-targetDir</b>.
-For large images, some file systems have performance problems if the number of files 
-in a directory is to big, causing gdal_retile not to finish in reasonable time. 
+For large images, some file systems have performance problems if the number of files
+in a directory is to big, causing gdal_retile not to finish in reasonable time.
 Using this parameter creates a different output structure. The tiles of the base image
 are stored in a sub-directory called 0, the pyramids in sub-directories numbered 1,2,....
 Within each of these directories another level of sub-directories is created, numbered from
@@ -1752,32 +1848,37 @@ Christian Mueller <christian.mueller at nvoe.at>
 */
 
 *******************************************************************************
-/*! \page gdal_grid gdal_grid
+/*!
+\if man
+\page gdal_grid
+\else
+\page gdal_grid gdal_grid
+\endif
 
-creates regular grid from the scattered data
+Creates regular grid from the scattered data.
 
 \section gdal_grid_synopsis SYNOPSIS
 
 \verbatim
 gdal_grid [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
           CInt16/CInt32/CFloat32/CFloat64}]
-	  [-of format] [-co "NAME=VALUE"]
-	  [-zfield field_name] [-z_increase increase_value] [-z_multiply multiply_value]
-	  [-a_srs srs_def] [-spat xmin ymin xmax ymax]
+          [-of format] [-co "NAME=VALUE"]
+          [-zfield field_name] [-z_increase increase_value] [-z_multiply multiply_value]
+          [-a_srs srs_def] [-spat xmin ymin xmax ymax]
           [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]
           [-clipsrcsql sql_statement] [-clipsrclayer layer]
           [-clipsrcwhere expression]
-	  [-l layername]* [-where expression] [-sql select_statement]
-	  [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]
-	  [-a algorithm[:parameter1=value1]*] [-q]
-	  <src_datasource> <dst_filename>
+          [-l layername]* [-where expression] [-sql select_statement]
+          [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]
+          [-a algorithm[:parameter1=value1]*] [-q]
+          <src_datasource> <dst_filename>
 \endverbatim
 
 \section gdal_grid_description DESCRIPTION
 
 This program creates regular grid (raster) from the scattered data read from
 the OGR datasource. Input data will be interpolated to fill grid nodes with
-values, you can choose from various interpolation methods. 
+values, you can choose from various interpolation methods.
 
 Starting with GDAL 1.10, it is possible to set the <b>GDAL_NUM_THREADS</b>
 configuration option to parallelize the processing. The value to specify is
@@ -1815,9 +1916,9 @@ containing Z value).</dd>
 on the features to be used to get a Z value from. The addition should be the same
 unit as Z value. The result value will be Z value + Z increase value. The default value is 0.</dd>
 
-<dt> <b>-z_multiply</b> <i>multiply_value</i>:</dt><dd> This is multiplication 
-ratio for Z field. This can be used for shift from e.g. foot to meters or from 
-elevation to deep. The result value will be (Z value + Z increase value) * Z multiply value. 
+<dt> <b>-z_multiply</b> <i>multiply_value</i>:</dt><dd> This is multiplication
+ratio for Z field. This can be used for shift from e.g. foot to meters or from
+elevation to deep. The result value will be (Z value + Z increase value) * Z multiply value.
 The default value is 1.</dd>
 
 <dt> <b>-a</b> <i>[algorithm[:parameter1=value1][:parameter2=value2]...]</i>:
@@ -1852,25 +1953,26 @@ datasource that will be used for input features.  May be specified multiple
 times, but at least one layer name or a <b>-sql</b> option must be
 specified.</dd>
 
-<dt> <b>-where</b> <em>expression</em>: </dt><dd> 
-An optional SQL WHERE style query expression to be applied to select features 
+<dt> <b>-where</b> <em>expression</em>: </dt><dd>
+An optional SQL WHERE style query expression to be applied to select features
 to process from the input layer(s). </dd>
 
-<dt> <b>-sql</b> <em>select_statement</em>: </dt><dd> 
+<dt> <b>-sql</b> <em>select_statement</em>: </dt><dd>
 An SQL statement to be evaluated against the datasource to produce a
 virtual layer of features to be processed.</dd>
 
 <dt> <b>-co</b> <i>"NAME=VALUE"</i>:</dt><dd> Passes a creation option to the
-output format driver.  Multiple <b>-co</b> options may be listed.  See format 
-specific documentation for legal creation options for each format.</dd>
+output format driver.  Multiple <b>-co</b> options may be listed. See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a>.</dd>
 
 <dt> <b>-q</b>:</dt><dd> Suppress progress monitor and other non-error
 output.</dd>
 
-<dt> <em>src_datasource</em>: </dt><dd> 
+<dt> <em>src_datasource</em>: </dt><dd>
 Any OGR supported readable datasource.</dd>
 
-<dt> <em>dst_filename</em>: </dt><dd> 
+<dt> <em>dst_filename</em>: </dt><dd>
 The GDAL supported output file.</dd>
 
 </dl>
@@ -1909,18 +2011,19 @@ non-zero). Default is 0.</dd>
 
 \subsection gdal_grid_algorithms_invdist_nearest_neighbor invdistnn
 
-(Since GDAL 2.1) Inverse distance to a power with nearest neighbor searching, ideal when 
+(Since GDAL 2.1) Inverse distance to a power with nearest neighbor searching, ideal when
 max_points is used. It has following parameters:
 
 <dl>
 <dt><i>power</i>:</dt> <dd>Weighting power (default 2.0).</dd>
-<dt><i>radius</i>:</dt> <dd>The radius of the search circle, which should be 
+<dt><i>smoothing</i>:</dt> <dd>Smoothing parameter (default 0.0).</dd>
+<dt><i>radius</i>:</dt> <dd>The radius of the search circle, which should be
 non-zero. Default is 1.0.</dd>
 <dt><i>max_points</i>:</dt> <dd>Maximum number of data points to use. Do not
-search for more points than this number. Found points will be ranked from 
+search for more points than this number. Found points will be ranked from
 nearest to furthest distance when weighting. Default is 12.</dd>
 <dt><i>min_points</i>:</dt> <dd>Minimum number of data points to use. If less
-amount of points found the grid node is considered empty and will be filled 
+amount of points found the grid node is considered empty and will be filled
 with NODATA marker. Default is 0.</dd>
 <dt><i>nodata</i>:</dt> <dd>NODATA marker to fill empty points (default
 0.0).</dd>
@@ -2067,9 +2170,9 @@ content:
 \verbatim
 <OGRVRTDataSource>
     <OGRVRTLayer name="dem">
-        <SrcDataSource>dem.csv</SrcDataSource> 
-	<GeometryType>wkbPoint</GeometryType> 
-	<GeometryField encoding="PointFromColumns" x="Easting" y="Northing" z="Elevation"/> 
+        <SrcDataSource>dem.csv</SrcDataSource>
+        <GeometryType>wkbPoint</GeometryType>
+        <GeometryField encoding="PointFromColumns" x="Easting" y="Northing" z="Elevation"/>
     </OGRVRTLayer>
 </OGRVRTDataSource>
 \endverbatim
@@ -2123,9 +2226,14 @@ Andrey Kiselev <dron at ak4719.spb.edu>
 
 
 *******************************************************************************
-/*! \page gdaldem gdaldem
+/*!
+\if man
+\page gdaldem
+\else
+\page gdaldem gdaldem
+\endif
 
-Tools to analyze and visualize DEMs. (since GDAL 1.7.0)
+Tools to analyze and visualize DEMs.
 
 \section gdaldem_synopsis SYNOPSIS
 
@@ -2139,7 +2247,7 @@ Usage:
     gdaldem hillshade input_dem output_hillshade
                 [-z ZFactor (default=1)] [-s scale* (default=1)]"
                 [-az Azimuth (default=315)] [-alt Altitude (default=45)]
-                [-alg ZevenbergenThorne] [-combined]
+                [-alg ZevenbergenThorne] [-combined | -multidirectional]
                 [-compute_edges] [-b Band (default=1)] [-of format] [-co "NAME=VALUE"]* [-q]
 
 - To generate a slope map from any GDAL-supported elevation raster :
@@ -2160,15 +2268,15 @@ Usage:
                 [-alpha] [-exact_color_entry | -nearest_color_entry]
                 [-b Band (default=1)] [-of format] [-co "NAME=VALUE"]* [-q]
     where color_text_file contains lines of the format "elevation_value red green blue"
-    
+
 - To generate a Terrain Ruggedness Index (TRI) map from any GDAL-supported elevation raster:
     gdaldem TRI input_dem output_TRI_map
                 [-compute_edges] [-b Band (default=1)] [-of format] [-q]
-            
+
 - To generate a Topographic Position Index (TPI) map from any GDAL-supported elevation raster:
     gdaldem TPI input_dem output_TPI_map
                 [-compute_edges] [-b Band (default=1)] [-of format] [-q]
-            
+
 - To generate a roughness map from any GDAL-supported elevation raster:
     gdaldem roughness input_dem output_roughness_map
                 [-compute_edges] [-b Band (default=1)] [-of format] [-q]
@@ -2176,10 +2284,10 @@ Usage:
 Notes :
   gdaldem generally assumes that x, y and z units are identical.  If x (east-west)
   and y (north-south) units are identical, but z (elevation) units are different, the
-  scale (-s) option can be used to set the ratio of vertical units to horizontal.  For 
-  LatLong projections near the equator, where units of latitude and units of 
+  scale (-s) option can be used to set the ratio of vertical units to horizontal.  For
+  LatLong projections near the equator, where units of latitude and units of
   longitude are similar, elevation (z) units can be converted to be compatible
-  by using scale=370400 (if elevation is in feet) or scale=111120 (if elevation is in 
+  by using scale=370400 (if elevation is in feet) or scale=111120 (if elevation is in
   meters).  For locations not near the equator, it would be best to reproject your
   grid using gdalwarp before using gdaldem.
 
@@ -2209,8 +2317,9 @@ is GeoTIFF (GTiff).  Use the short format name.</dd>
 <dt> <b>-alg</b> <i>ZevenbergenThorne</i>:</dt><dd> (GDAL >= 1.8.0) Use Zevenbergen & Thorne formula, instead of Horn's formula, to compute slope & aspect. The literature suggests Zevenbergen & Thorne to be more suited to smooth landscapes, whereas Horn's formula to perform better on rougher terrain.</dd>
 <dt> <b>-b</b> <i>band</i>:</dt><dd> Select an input <i>band</i> to be processed. Bands are numbered from 1.</dd>
 <dt> <b>-co</b> <i>"NAME=VALUE"</i>:</dt><dd> Passes a creation option to the
-output format driver.  Multiple <b>-co</b> options may be listed.  See format 
-specific documentation for legal creation options for each format.</dd>
+output format driver.  Multiple <b>-co</b> options may be listed. See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a></dd>
 <dt> <b>-q</b>:</dt><dd> Suppress progress monitor and other non-error
 output.</dd>
 </dl>
@@ -2238,9 +2347,12 @@ The following specific options are available :
 <dt> <b>-s</b> <i>scale</i>:</dt><dd>ratio of vertical units to horizontal. If the horizontal unit of the source DEM is degrees (e.g Lat/Long WGS84 projection), you can use scale=111120 if the vertical units are meters (or scale=370400 if they are in feet)</dd>
 <dt> <b>-az</b> <i>azimuth</i>:</dt><dd>azimuth of the light, in degrees. 0 if it comes from the top of the raster, 90 from the east, ... The default value, 315, should rarely be changed as it is the value generally used to generate shaded maps.</dd>
 <dt> <b>-alt</b> <i>altitude</i>:</dt><dd>altitude of the light, in degrees. 90 if the light comes from above the DEM, 0 if it is raking light.</dd>
-<dt> <b>-combined</b> <i>combined shading</i>:</dt><dd>(starting with GDAL 1.10) a combination of slope and oblique shading.</dd>
+<dt> <b>-combined</b>:</dt><dd>(starting with GDAL 1.10) combined shading, a combination of slope and oblique shading.</dd>
+<dt> <b>-multidirectional</b>:</dt><dd>(starting with GDAL 2.2) multidirectional shading, a combination of hillshading illuminated from 225 deg, 270 deg, 315 deg, and 360 deg azimuth.</dd>
 </dl>
 
+Multidirectional hillshading applies the formula of http://pubs.usgs.gov/of/1992/of92-422/of92-422.pdf.
+
 \subsection gdaldem_slope slope
 
 This command will take a DEM raster and output a 32-bit float raster with slope values.
@@ -2316,7 +2428,7 @@ For example :
 50%   190 185 135
 700    240 250 150
 0      50  180  50
-nv     0   0   0   0 
+nv     0   0   0   0
 \endverbatim
 
 \subsection gdaldem_TRI TRI
@@ -2356,7 +2468,7 @@ Matthew Perry <perrygeo at gmail.com>, Even Rouault <even.rouault at mines-paris.org>,
 
 Derived from code by Michael Shapiro, Olga Waupotitsch, Marjorie Larson, Jim Westervelt :
 U.S. Army CERL, 1993. GRASS 4.1 Reference Manual. U.S. Army Corps of Engineers,
-Construction Engineering Research Laboratories, Champaign, Illinois, 1-425. 
+Construction Engineering Research Laboratories, Champaign, Illinois, 1-425.
 
 \section gdaldem_seealso See also
 
@@ -2372,9 +2484,14 @@ http://grass.osgeo.org/grass64/manuals/html64_user/r.colors.html
 
 
 *******************************************************************************
-/*! \page gdalsrsinfo gdalsrsinfo
-	
-lists info about a given SRS in number of formats (WKT, PROJ.4, etc.)
+/*!
+\if man
+\page gdalsrsinfo
+\else
+\page gdalsrsinfo gdalsrsinfo
+\endif
+
+Lists info about a given SRS in number of formats (WKT, PROJ.4, etc.)
 
 \section gdalsrsinfo_synopsis SYNOPSIS
 
@@ -2384,7 +2501,7 @@ Usage: gdalsrsinfo [options] srs_def
 srs_def may be the filename of a dataset supported by GDAL/OGR from which to extract SRS information
 OR any of the usual GDAL/OGR forms (complete WKT, PROJ.4, EPSG:n or a file containing the SRS)
 
-Options: 
+Options:
    [--help-general] [-h]  Show help and exit
    [-p]                   Pretty-print where applicable (e.g. WKT)
    [-V]                   Validate SRS
@@ -2415,7 +2532,7 @@ Output types:
 - <b>xml</b>   XML format (GML based)
 
 \n
-\section gdal_grid_example EXAMPLE
+\section gdalsrsinfo_example EXAMPLE
 
 \verbatim
 $  gdalsrsinfo   "EPSG:4326"
@@ -2524,9 +2641,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Etienne Tourigny <etourigny.dev-at-gmail-
 */
 
 *******************************************************************************
-/*! \page gdalmanage gdalmanage
+/*!
+\if man
+\page gdalmanage
+\else
+\page gdalmanage gdalmanage
+\endif
 
-Identify, delete, rename and copy raster data files
+Identify, delete, rename and copy raster data files.
 
 \section gdalmanage_synopsis SYNOPSIS
 
@@ -2614,7 +2736,12 @@ Tyler Mitchell <spatialguru at shaw.ca>
 */
 
 *******************************************************************************
-/*! \page gdal_pansharpen gdal_pansharpen.py
+/*!
+\if man
+\page gdal_pansharpen
+\else
+\page gdal_pansharpen gdal_pansharpen.py
+\endif
 
 Perform a pansharpen operation.
 
@@ -2667,8 +2794,9 @@ setting.</dd>
 Select behaviour when bands have not the same extent. See <i>SpatialExtentAdjustment</i>
 documentation in  <a href="gdal_vrttut.html#gdal_vrttut_pansharpen">VRT tutorial</a></dd>
 <dt> <b>-co</b> <i>"NAME=VALUE"</i>:</dt><dd> Passes a creation option to the
-output format driver.  Multiple <b>-co</b> options may be listed.  See format 
-specific documentation for legal creation options for each format.</dd>
+output format driver.  Multiple <b>-co</b> options may be listed. See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a>.</dd>
 <dt> <b>-q</b>:</dt><dd> Suppress progress monitor and other non-error
 output.</dd>
 <dt> <i>pan_dataset</i></dt><dd> Dataset with panchromatic band (first band will be used).</dd>
diff --git a/apps/gdal_utils.h b/apps/gdal_utils.h
index 1777131..fb7162b 100644
--- a/apps/gdal_utils.h
+++ b/apps/gdal_utils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gdal_utils.h 35884 2016-10-24 05:56:50Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Utilities Public Declarations.
@@ -48,6 +48,7 @@ CPL_C_START
 /*! Options for GDALInfo(). Opaque type */
 typedef struct GDALInfoOptions GDALInfoOptions;
 
+/** Opaque type */
 typedef struct GDALInfoOptionsForBinary GDALInfoOptionsForBinary;
 
 GDALInfoOptions CPL_DLL *GDALInfoOptionsNew(char** papszArgv, GDALInfoOptionsForBinary* psOptionsForBinary);
@@ -56,10 +57,10 @@ void CPL_DLL GDALInfoOptionsFree( GDALInfoOptions *psOptions );
 
 char CPL_DLL *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions );
 
-
 /*! Options for GDALTranslate(). Opaque type */
 typedef struct GDALTranslateOptions GDALTranslateOptions;
 
+/** Opaque type */
 typedef struct GDALTranslateOptionsForBinary GDALTranslateOptionsForBinary;
 
 GDALTranslateOptions CPL_DLL *GDALTranslateOptionsNew(char** papszArgv,
@@ -79,6 +80,7 @@ GDALDatasetH CPL_DLL GDALTranslate(const char *pszDestFilename,
 /*! Options for GDALWarp(). Opaque type */
 typedef struct GDALWarpAppOptions GDALWarpAppOptions;
 
+/** Opaque type */
 typedef struct GDALWarpAppOptionsForBinary GDALWarpAppOptionsForBinary;
 
 GDALWarpAppOptions CPL_DLL *GDALWarpAppOptionsNew(char** papszArgv,
@@ -100,6 +102,7 @@ GDALDatasetH CPL_DLL GDALWarp( const char *pszDest, GDALDatasetH hDstDS,
 /*! Options for GDALVectorTranslate(). Opaque type */
 typedef struct GDALVectorTranslateOptions GDALVectorTranslateOptions;
 
+/** Opaque type */
 typedef struct GDALVectorTranslateOptionsForBinary GDALVectorTranslateOptionsForBinary;
 
 GDALVectorTranslateOptions CPL_DLL *GDALVectorTranslateOptionsNew(char** papszArgv,
@@ -115,10 +118,10 @@ GDALDatasetH CPL_DLL GDALVectorTranslate( const char *pszDest, GDALDatasetH hDst
                                GDALDatasetH *pahSrcDS,
                                const GDALVectorTranslateOptions *psOptions, int *pbUsageError );
 
-
 /*! Options for GDALDEMProcessing(). Opaque type */
 typedef struct GDALDEMProcessingOptions GDALDEMProcessingOptions;
 
+/** Opaque type */
 typedef struct GDALDEMProcessingOptionsForBinary GDALDEMProcessingOptionsForBinary;
 
 GDALDEMProcessingOptions CPL_DLL *GDALDEMProcessingOptionsNew(char** papszArgv,
@@ -140,6 +143,7 @@ GDALDatasetH CPL_DLL GDALDEMProcessing(const char *pszDestFilename,
 /*! Options for GDALNearblack(). Opaque type */
 typedef struct GDALNearblackOptions GDALNearblackOptions;
 
+/** Opaque type */
 typedef struct GDALNearblackOptionsForBinary GDALNearblackOptionsForBinary;
 
 GDALNearblackOptions CPL_DLL *GDALNearblackOptionsNew(char** papszArgv,
@@ -158,6 +162,7 @@ GDALDatasetH CPL_DLL GDALNearblack( const char *pszDest, GDALDatasetH hDstDS,
 /*! Options for GDALGrid(). Opaque type */
 typedef struct GDALGridOptions GDALGridOptions;
 
+/** Opaque type */
 typedef struct GDALGridOptionsForBinary GDALGridOptionsForBinary;
 
 GDALGridOptions CPL_DLL *GDALGridOptionsNew(char** papszArgv,
@@ -176,6 +181,7 @@ GDALDatasetH CPL_DLL GDALGrid( const char *pszDest,
 /*! Options for GDALRasterize(). Opaque type */
 typedef struct GDALRasterizeOptions GDALRasterizeOptions;
 
+/** Opaque type */
 typedef struct GDALRasterizeOptionsForBinary GDALRasterizeOptionsForBinary;
 
 GDALRasterizeOptions CPL_DLL *GDALRasterizeOptionsNew(char** papszArgv,
@@ -194,6 +200,7 @@ GDALDatasetH CPL_DLL GDALRasterize( const char *pszDest, GDALDatasetH hDstDS,
 /*! Options for GDALBuildVRT(). Opaque type */
 typedef struct GDALBuildVRTOptions GDALBuildVRTOptions;
 
+/** Opaque type */
 typedef struct GDALBuildVRTOptionsForBinary GDALBuildVRTOptionsForBinary;
 
 GDALBuildVRTOptions CPL_DLL *GDALBuildVRTOptionsNew(char** papszArgv,
diff --git a/apps/gdal_utils_priv.h b/apps/gdal_utils_priv.h
index 6cc13c2..8c3bb0a 100644
--- a/apps/gdal_utils_priv.h
+++ b/apps/gdal_utils_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gdal_utils_priv.h 34921 2016-08-04 22:26:31Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Utilities Private Declarations.
@@ -30,6 +30,8 @@
 #ifndef GDAL_UTILS_PRIV_H_INCLUDED
 #define GDAL_UTILS_PRIV_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "cpl_port.h"
 #include "gdal_utils.h"
 
@@ -146,4 +148,6 @@ struct GDALBuildVRTOptionsForBinary
 
 CPL_C_END
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* GDAL_UTILS_PRIV_H_INCLUDED */
diff --git a/apps/gdaladdo.cpp b/apps/gdaladdo.cpp
index 54c0851..7e98abb 100644
--- a/apps/gdaladdo.cpp
+++ b/apps/gdaladdo.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaladdo.cpp 33843 2016-04-01 08:37:57Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line application to build overviews.
@@ -31,7 +30,7 @@
 #include "gdal_priv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: gdaladdo.cpp 33843 2016-04-01 08:37:57Z rouault $");
+CPL_CVSID("$Id: gdaladdo.cpp 36536 2016-11-27 23:50:21Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -102,7 +101,8 @@ static void CPL_STDCALL GDALAddoErrorHandler( CPLErr eErr, CPLErrorNum errNum, c
 
 #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
     do { if (iArg + nExtraArg >= nArgc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
+        Usage(CPLSPrintf("%s option requires %d argument(s)", \
+                         papszArgv[iArg], nExtraArg)); } while( false )
 
 int main( int nArgc, char ** papszArgv )
 
diff --git a/apps/gdalasyncread.cpp b/apps/gdalasyncread.cpp
index 1f0069e..081cce5 100644
--- a/apps/gdalasyncread.cpp
+++ b/apps/gdalasyncread.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalasyncread.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL Async Image Reader, primarily for testing async api.
@@ -33,7 +32,7 @@
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdalasyncread.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: gdalasyncread.cpp 35931 2016-10-25 16:20:52Z goatbar $");
 
 /* ******************************************************************** */
 /*                               Usage()                                */
@@ -76,15 +75,15 @@ static void Usage()
 int main( int argc, char ** argv )
 
 {
-    GDALDatasetH	hSrcDS, hDstDS;
+    GDALDatasetH        hSrcDS, hDstDS;
     GDALDataset *       poSrcDS, *poDstDS = NULL;
-    int			i;
-    int			nRasterXSize, nRasterYSize;
-    const char		*pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
-    GDALDriverH		hDriver;
-    int			*panBandList = NULL, nBandCount = 0, bDefBands = TRUE;
-    GDALDataType	eOutputType = GDT_Unknown;
-    int			nOXSize = 0, nOYSize = 0;
+    int                 i;
+    int                 nRasterXSize, nRasterYSize;
+    const char          *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
+    GDALDriverH         hDriver;
+    int                 *panBandList = NULL, nBandCount = 0, bDefBands = TRUE;
+    GDALDataType        eOutputType = GDT_Unknown;
+    int                 nOXSize = 0, nOYSize = 0;
     char                **papszCreateOptions = NULL;
     char                **papszAsyncOptions = NULL;
     int                 anSrcWin[4];
@@ -296,7 +295,7 @@ int main( int argc, char ** argv )
     }
 
 /* -------------------------------------------------------------------- */
-/*	Build band list to translate					*/
+/*      Build band list to translate                                    */
 /* -------------------------------------------------------------------- */
     if( nBandCount == 0 )
     {
@@ -492,8 +491,10 @@ int main( int argc, char ** argv )
 /*      Fetch an update and write it to the output file.                */
 /* ==================================================================== */
 
-
-        int nUpXOff, nUpYOff, nUpXSize, nUpYSize;
+        int nUpXOff;
+        int nUpYOff;
+        int nUpXSize;
+        int nUpYSize;
 
         eAStatus = poAsyncReq->GetNextUpdatedRegion( dfTimeout,
                                                      &nUpXOff, &nUpYOff,
@@ -529,8 +530,9 @@ int main( int argc, char ** argv )
             hDstDS = NULL;
         }
         else
+        {
             GDALFlushCache( hDstDS );
-
+        }
     } while( eAStatus != GARIO_ERROR && eAStatus != GARIO_COMPLETE
              && eErr == CE_None );
 
diff --git a/apps/gdalbuildvrt_bin.cpp b/apps/gdalbuildvrt_bin.cpp
index b96ac28..3520bdd 100644
--- a/apps/gdalbuildvrt_bin.cpp
+++ b/apps/gdalbuildvrt_bin.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalbuildvrt_bin.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line application to build VRT datasets from raster products or content of SHP tile index
@@ -32,7 +31,7 @@
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdalbuildvrt_bin.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+CPL_CVSID("$Id: gdalbuildvrt_bin.cpp 37978 2017-04-13 15:25:54Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -53,6 +52,7 @@ static void Usage(const char* pszErrorMsg)
             "                    [-srcnodata \"value [value...]\"] [-vrtnodata \"value [value...]\"] \n"
             "                    [-a_srs srs_def]\n"
             "                    [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]\n"
+            "                    [-oo NAME=VALUE]*\n"
             "                    [-input_file_list my_list.txt] [-overwrite] output.vrt [gdalfile]*\n"
             "\n"
             "e.g.\n"
diff --git a/apps/gdalbuildvrt_lib.cpp b/apps/gdalbuildvrt_lib.cpp
index 6f8172d..f9e4efa 100644
--- a/apps/gdalbuildvrt_lib.cpp
+++ b/apps/gdalbuildvrt_lib.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalbuildvrt_lib.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line application to build VRT datasets from raster products
@@ -28,17 +27,35 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h"
-#include "gdal_proxy.h"
+#include "ogr_api.h"
+#include "ogr_srs_api.h"
+
+#include "cpl_port.h"
 #include "gdal_utils.h"
 #include "gdal_utils_priv.h"
-#include "gdal_vrt.h"
-#include "vrtdataset.h"
 
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_vrt.h"
+#include "gdal_priv.h"
+#include "gdal_proxy.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
 #include "ogr_srs_api.h"
+#include "vrtdataset.h"
 
-CPL_CVSID("$Id: gdalbuildvrt_lib.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+CPL_CVSID("$Id: gdalbuildvrt_lib.cpp 37978 2017-04-13 15:25:54Z rouault $");
 
 #define GEOTRSFRM_TOPLEFT_X            0
 #define GEOTRSFRM_WE_RES               1
@@ -90,7 +107,6 @@ static int ArgIsNumeric( const char *pszArg )
     return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
 }
 
-
 /************************************************************************/
 /*                         GetSrcDstWin()                               */
 /************************************************************************/
@@ -180,6 +196,7 @@ class VRTBuilder
     char               *pszVRTNoData;
     char               *pszOutputSRS;
     char               *pszResampling;
+    char              **papszOpenOptions;
 
     /* Internal variables */
     char               *pszProjectionRef;
@@ -219,14 +236,14 @@ class VRTBuilder
                            int bAddAlpha, int bHideNoData, int nSubdataset,
                            const char* pszSrcNoData, const char* pszVRTNoData,
                            const char* pszOutputSRS,
-                           const char* pszResampling);
+                           const char* pszResampling,
+                           const char* const* papszOpenOptionsIn );
 
                ~VRTBuilder();
 
         GDALDataset*     Build(GDALProgressFunc pfnProgress, void * pProgressData);
 };
 
-
 /************************************************************************/
 /*                          VRTBuilder()                                */
 /************************************************************************/
@@ -244,12 +261,14 @@ VRTBuilder::VRTBuilder(const char* pszOutputFilenameIn,
                        int bAddAlphaIn, int bHideNoDataIn, int nSubdatasetIn,
                        const char* pszSrcNoDataIn, const char* pszVRTNoDataIn,
                        const char* pszOutputSRSIn,
-                       const char* pszResamplingIn)
+                       const char* pszResamplingIn,
+                       const char* const * papszOpenOptionsIn )
 {
     pszOutputFilename = CPLStrdup(pszOutputFilenameIn);
     nInputFiles = nInputFilesIn;
     pahSrcDS = NULL;
     ppszInputFilenames = NULL;
+    papszOpenOptions = CSLDuplicate(const_cast<char**>(papszOpenOptionsIn));
 
     if( ppszInputFilenamesIn )
     {
@@ -357,6 +376,7 @@ VRTBuilder::~VRTBuilder()
     CPLFree(padfVRTNoData);
     CPLFree(pszOutputSRS);
     CPLFree(pszResampling);
+    CSLDestroy(papszOpenOptions);
 }
 
 /************************************************************************/
@@ -720,7 +740,6 @@ int VRTBuilder::AnalyseRaster( GDALDatasetH hDS, DatasetProperty* psDatasetPrope
                     }
                 }
             }
-
         }
         if (!bUserExtent)
         {
@@ -745,15 +764,15 @@ int VRTBuilder::AnalyseRaster( GDALDatasetH hDS, DatasetProperty* psDatasetPrope
         }
         else if (resolutionStrategy == HIGHEST_RESOLUTION)
         {
-            we_res = MIN(we_res, padfGeoTransform[GEOTRSFRM_WE_RES]);
-            /* Yes : as ns_res is negative, the highest resolution is the max value */
-            ns_res = MAX(ns_res, padfGeoTransform[GEOTRSFRM_NS_RES]);
+            we_res = std::min(we_res, padfGeoTransform[GEOTRSFRM_WE_RES]);
+            //ns_res is negative, the highest resolution is the max value.
+            ns_res = std::max(ns_res, padfGeoTransform[GEOTRSFRM_NS_RES]);
         }
         else
         {
-            we_res = MAX(we_res, padfGeoTransform[GEOTRSFRM_WE_RES]);
-            /* Yes : as ns_res is negative, the lowest resolution is the min value */
-            ns_res = MIN(ns_res, padfGeoTransform[GEOTRSFRM_NS_RES]);
+            we_res = std::max(we_res, padfGeoTransform[GEOTRSFRM_WE_RES]);
+            // ns_res is negative, the lowest resolution is the min value.
+            ns_res = std::min(ns_res, padfGeoTransform[GEOTRSFRM_NS_RES]);
         }
     }
 
@@ -801,6 +820,9 @@ void VRTBuilder::CreateVRTSeparate(VRTDatasetH hVRTDS)
                                         psDatasetProperties->nRasterYSize,
                                         GA_ReadOnly, TRUE, pszProjectionRef,
                                         psDatasetProperties->adfGeoTransform);
+        reinterpret_cast<GDALProxyPoolDataset*>(hProxyDS)->
+                                        SetOpenOptions( papszOpenOptions );
+
         GDALProxyPoolDatasetAddSrcBandDescription(hProxyDS,
                                             psDatasetProperties->firstBandType,
                                             psDatasetProperties->nBlockXSize,
@@ -878,16 +900,21 @@ void VRTBuilder::CreateVRTNonSeparate(VRTDatasetH hVRTDS)
         poMaskVRTBand = (VRTSourcedRasterBand*)GDALGetMaskBand(GDALGetRasterBand(hVRTDS, 1));
     }
 
-
-    for(int i=0;i<nInputFiles;i++)
+    for( int i = 0; i < nInputFiles; i++ )
     {
         DatasetProperty* psDatasetProperties = &pasDatasetProperties[i];
 
         if (psDatasetProperties->isFileOK == FALSE)
             continue;
 
-        double dfSrcXOff, dfSrcYOff, dfSrcXSize, dfSrcYSize,
-            dfDstXOff, dfDstYOff, dfDstXSize, dfDstYSize;
+        double dfSrcXOff;
+        double dfSrcYOff;
+        double dfSrcXSize;
+        double dfSrcYSize;
+        double dfDstXOff;
+        double dfDstYOff;
+        double dfDstXSize;
+        double dfDstYSize;
         if ( ! GetSrcDstWin(psDatasetProperties,
                         we_res, ns_res, minX, minY, maxX, maxY,
                         &dfSrcXOff, &dfSrcYOff, &dfSrcXSize, &dfSrcYSize,
@@ -902,6 +929,8 @@ void VRTBuilder::CreateVRTNonSeparate(VRTDatasetH hVRTDS)
                                         psDatasetProperties->nRasterYSize,
                                         GA_ReadOnly, TRUE, pszProjectionRef,
                                         psDatasetProperties->adfGeoTransform);
+        reinterpret_cast<GDALProxyPoolDataset*>(hProxyDS)->
+                                        SetOpenOptions( papszOpenOptions );
 
         for(int j=0;j<nMaxBandNo;j++)
         {
@@ -1037,7 +1066,10 @@ GDALDataset* VRTBuilder::Build(GDALProgressFunc pfnProgress, void * pProgressDat
             padfSrcNoData = (double *) CPLMalloc(sizeof(double) * nSrcNoDataCount);
             for(int i=0;i<nSrcNoDataCount;i++)
             {
-                if( !ArgIsNumeric(papszTokens[i]) && !EQUAL(papszTokens[i], "nan") )
+                if( !ArgIsNumeric(papszTokens[i]) &&
+                    !EQUAL(papszTokens[i], "nan") &&
+                    !EQUAL(papszTokens[i], "-inf") &&
+                    !EQUAL(papszTokens[i], "inf") )
                 {
                     CPLError(CE_Failure, CPLE_IllegalArg, "Invalid -srcnodata value");
                     CSLDestroy(papszTokens);
@@ -1062,7 +1094,10 @@ GDALDataset* VRTBuilder::Build(GDALProgressFunc pfnProgress, void * pProgressDat
             padfVRTNoData = (double *) CPLMalloc(sizeof(double) * nVRTNoDataCount);
             for(int i=0;i<nVRTNoDataCount;i++)
             {
-                if( !ArgIsNumeric(papszTokens[i]) && !EQUAL(papszTokens[i], "nan") )
+                if( !ArgIsNumeric(papszTokens[i]) &&
+                    !EQUAL(papszTokens[i], "nan") &&
+                    !EQUAL(papszTokens[i], "-inf") &&
+                    !EQUAL(papszTokens[i], "inf") )
                 {
                     CPLError(CE_Failure, CPLE_IllegalArg, "Invalid -vrtnodata value");
                     CSLDestroy(papszTokens);
@@ -1086,7 +1121,9 @@ GDALDataset* VRTBuilder::Build(GDALProgressFunc pfnProgress, void * pProgressDat
 
         GDALDatasetH hDS =
             (pahSrcDS) ? pahSrcDS[i] :
-                         GDALOpen(ppszInputFilenames[i], GA_ReadOnly );
+                GDALOpenEx( ppszInputFilenames[i],
+                            GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL,
+                            papszOpenOptions, NULL );
         pasDatasetProperties[i].isFileOK = FALSE;
 
         if (hDS)
@@ -1290,6 +1327,7 @@ struct GDALBuildVRTOptions
     int nBandCount;
     int nMaxBandNo;
     char* pszResampling;
+    char** papszOpenOptions;
 
     /*! allow or suppress progress monitor and other non-error output */
     int bQuiet;
@@ -1321,6 +1359,7 @@ GDALBuildVRTOptions* GDALBuildVRTOptionsClone(const GDALBuildVRTOptions *psOptio
         psOptions->panBandList = static_cast<int*>(CPLMalloc(sizeof(int) * psOptionsIn->nBandCount));
         memcpy(psOptions->panBandList, psOptionsIn->panBandList, sizeof(int) * psOptionsIn->nBandCount);
     }
+    if( psOptionsIn->papszOpenOptions ) psOptions->papszOpenOptions = CSLDuplicate(psOptionsIn->papszOpenOptions);
     return psOptions;
 }
 
@@ -1433,7 +1472,8 @@ GDALDatasetH GDALBuildVRT( const char *pszDest,
                         psOptions->bSeparate, psOptions->bAllowProjectionDifference,
                         psOptions->bAddAlpha, psOptions->bHideNoData, psOptions->nSubdataset,
                         psOptions->pszSrcNoData, psOptions->pszVRTNoData,
-                        psOptions->pszOutputSRS, psOptions->pszResampling);
+                        psOptions->pszOutputSRS, psOptions->pszResampling,
+                        psOptions->papszOpenOptions);
 
     GDALDatasetH hDstDS =
         (GDALDatasetH)oBuilder.Build(psOptions->pfnProgress, psOptions->pProgressData);
@@ -1505,7 +1545,7 @@ GDALBuildVRTOptions *GDALBuildVRTOptionsNew(char** papszArgv,
 /*      Parse arguments.                                                */
 /* -------------------------------------------------------------------- */
     int argc = CSLCount(papszArgv);
-    for( int iArg = 0; iArg < argc; iArg++ )
+    for( int iArg = 0; papszArgv != NULL && iArg < argc; iArg++ )
     {
         if( EQUAL(papszArgv[iArg],"-tileindex") && iArg + 1 < argc )
         {
@@ -1669,6 +1709,12 @@ GDALBuildVRTOptions *GDALBuildVRTOptionsNew(char** papszArgv,
             CPLFree(psOptions->pszResampling);
             psOptions->pszResampling = CPLStrdup(papszArgv[++iArg]);
         }
+        else if( EQUAL(papszArgv[iArg], "-oo") && iArg+1 < argc )
+        {
+            psOptions->papszOpenOptions =
+                    CSLAddString( psOptions->papszOpenOptions,
+                                  papszArgv[++iArg] );
+        }
         else if( papszArgv[iArg][0] == '-' )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
@@ -1721,6 +1767,7 @@ void GDALBuildVRTOptionsFree( GDALBuildVRTOptions *psOptions )
         CPLFree( psOptions->pszOutputSRS );
         CPLFree( psOptions->panBandList );
         CPLFree( psOptions->pszResampling );
+        CSLDestroy( psOptions->papszOpenOptions );
     }
 
     CPLFree(psOptions);
diff --git a/apps/gdaldem_bin.cpp b/apps/gdaldem_bin.cpp
index b9fcf70..90c4e32 100644
--- a/apps/gdaldem_bin.cpp
+++ b/apps/gdaldem_bin.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaldem_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL DEM Utilities
  * Purpose:
@@ -37,7 +36,7 @@
 #include "gdal_priv.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: gdaldem_bin.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: gdaldem_bin.cpp 35600 2016-10-02 18:21:54Z rouault $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -51,7 +50,7 @@ static void Usage(const char* pszErrorMsg = NULL)
             "     gdaldem hillshade input_dem output_hillshade \n"
             "                 [-z ZFactor (default=1)] [-s scale* (default=1)] \n"
             "                 [-az Azimuth (default=315)] [-alt Altitude (default=45)]\n"
-            "                 [-alg ZevenbergenThorne] [-combined]\n"
+            "                 [-alg ZevenbergenThorne] [-combined | -multidirectional]\n"
             "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
             "\n"
             " - To generates a slope map from any GDAL-supported elevation raster :\n\n"
@@ -101,14 +100,16 @@ static void Usage(const char* pszErrorMsg = NULL)
 
 static GDALDEMProcessingOptionsForBinary *GDALDEMProcessingOptionsForBinaryNew(void)
 {
-    return (GDALDEMProcessingOptionsForBinary*) CPLCalloc(  1, sizeof(GDALDEMProcessingOptionsForBinary) );
+    return static_cast<GDALDEMProcessingOptionsForBinary *>(
+        CPLCalloc(  1, sizeof(GDALDEMProcessingOptionsForBinary) ));
 }
 
 /************************************************************************/
 /*                       GDALDEMProcessingOptionsForBinaryFree()            */
 /************************************************************************/
 
-static void GDALDEMProcessingOptionsForBinaryFree( GDALDEMProcessingOptionsForBinary* psOptionsForBinary )
+static void GDALDEMProcessingOptionsForBinaryFree(
+    GDALDEMProcessingOptionsForBinary* psOptionsForBinary )
 {
     if( psOptionsForBinary )
     {
@@ -128,7 +129,7 @@ int main( int argc, char ** argv )
 
 {
     /* Check strict compilation and runtime library version as we use C++ API */
-    if (! GDAL_CHECK_VERSION(argv[0]))
+    if( ! GDAL_CHECK_VERSION(argv[0]) )
         exit(1);
 
     EarlySetConfigOptions(argc, argv);
@@ -144,7 +145,8 @@ int main( int argc, char ** argv )
         Usage("Not enough arguments.");
     }
 
-    if( EQUAL(argv[1], "--utility_version") || EQUAL(argv[1], "--utility-version") )
+    if( EQUAL(argv[1], "--utility_version") ||
+        EQUAL(argv[1], "--utility-version") )
     {
         printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                 argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
@@ -154,8 +156,10 @@ int main( int argc, char ** argv )
     else if( EQUAL(argv[1],"--help") )
         Usage();
 
-    GDALDEMProcessingOptionsForBinary* psOptionsForBinary = GDALDEMProcessingOptionsForBinaryNew();
-    GDALDEMProcessingOptions *psOptions = GDALDEMProcessingOptionsNew(argv + 1, psOptionsForBinary);
+    GDALDEMProcessingOptionsForBinary* psOptionsForBinary =
+        GDALDEMProcessingOptionsForBinaryNew();
+    GDALDEMProcessingOptions *psOptions =
+        GDALDEMProcessingOptionsNew(argv + 1, psOptionsForBinary);
     CSLDestroy( argv );
 
     if( psOptions == NULL )
@@ -172,7 +176,8 @@ int main( int argc, char ** argv )
     {
         Usage("Missing source.");
     }
-    if ( EQUAL(psOptionsForBinary->pszProcessing, "color-relief") && psOptionsForBinary->pszColorFilename == NULL )
+    if ( EQUAL(psOptionsForBinary->pszProcessing, "color-relief") &&
+         psOptionsForBinary->pszColorFilename == NULL )
     {
         Usage("Missing color file.");
     }
@@ -181,11 +186,16 @@ int main( int argc, char ** argv )
         Usage("Missing destination.");
     }
 
-    if (!psOptionsForBinary->bQuiet && !psOptionsForBinary->bFormatExplicitlySet)
-        CheckExtensionConsistency(psOptionsForBinary->pszDstFilename, psOptionsForBinary->pszFormat);
+    if( !psOptionsForBinary->bQuiet &&
+        !psOptionsForBinary->bFormatExplicitlySet)
+    {
+        CheckExtensionConsistency(psOptionsForBinary->pszDstFilename,
+                                  psOptionsForBinary->pszFormat);
+    }
 
-    // Open Dataset and get raster band
-    GDALDatasetH hSrcDataset = GDALOpen( psOptionsForBinary->pszSrcFilename, GA_ReadOnly );
+    // Open Dataset and get raster band.
+    GDALDatasetH hSrcDataset =
+        GDALOpen( psOptionsForBinary->pszSrcFilename, GA_ReadOnly );
 
     if( hSrcDataset == NULL )
     {
@@ -197,13 +207,14 @@ int main( int argc, char ** argv )
     }
 
     int bUsageError = FALSE;
-    GDALDatasetH hOutDS = GDALDEMProcessing(psOptionsForBinary->pszDstFilename, hSrcDataset,
-                               psOptionsForBinary->pszProcessing,
-                               psOptionsForBinary->pszColorFilename,
-                               psOptions, &bUsageError);
-    if(bUsageError == TRUE)
+    GDALDatasetH hOutDS =
+        GDALDEMProcessing(psOptionsForBinary->pszDstFilename, hSrcDataset,
+                          psOptionsForBinary->pszProcessing,
+                          psOptionsForBinary->pszColorFilename,
+                          psOptions, &bUsageError);
+    if( bUsageError )
         Usage();
-    int nRetCode = (hOutDS) ? 0 : 1;
+    const int nRetCode = hOutDS ? 0 : 1;
 
     GDALClose(hSrcDataset);
     GDALClose(hOutDS);
diff --git a/apps/gdaldem_lib.cpp b/apps/gdaldem_lib.cpp
index 5ad1979..3772c56 100644
--- a/apps/gdaldem_lib.cpp
+++ b/apps/gdaldem_lib.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaldem_lib.cpp 34979 2016-08-08 09:30:34Z rouault $
  *
  * Project:  GDAL DEM Utilities
  * Purpose:
@@ -84,21 +83,42 @@
  *  on the continental slope Marine Geodesy, 2007, 30, 3-35
  ****************************************************************************/
 
-#include "cpl_vsi.h"
+// Include before others for mingw for VSIStatBufL
+#include "cpl_conv.h"
+
+#include "cpl_port.h"
+#include "gdal_utils.h"
+#include "gdal_utils_priv.h"
+
+#include <cfloat>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
 #include <algorithm>
-#include <float.h>
-#include <stdlib.h>
-#include <math.h>
+#include <limits>
 
-#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "gdal.h"
 #include "gdal_priv.h"
-#include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdaldem_lib.cpp 34979 2016-08-08 09:30:34Z rouault $");
+#if defined(__SSE2__) || defined(_M_X64)
+#define HAVE_16_SSE_REG
+#define HAVE_SSE2
+#include "emmintrin.h"
+#endif
 
-#define INTERPOL(a,b) ((bSrcHasNoData && (ARE_REAL_EQUAL(a, fSrcNoDataValue) || ARE_REAL_EQUAL(b, fSrcNoDataValue))) ? fSrcNoDataValue : 2 * (a) - (b))
+CPL_CVSID("$Id: gdaldem_lib.cpp 37897 2017-04-05 10:20:11Z ilucena $");
+
+static const double kdfDegreesToRadians = M_PI / 180.0;
+static const double kdfRadiansToDegrees = 180.0 / M_PI;
 
 typedef enum
 {
@@ -123,13 +143,14 @@ struct GDALDEMProcessingOptions
     double az;
     double alt;
     int slopeFormat;
-    int bAddAlpha;
-    int bZeroForFlat;
-    int bAngleAsAzimuth ;
+    bool bAddAlpha;
+    bool bZeroForFlat;
+    bool bAngleAsAzimuth;
     ColorSelectionMode eColorSelectionMode;
-    int bComputeAtEdges;
-    int bZevenbergenThorne;
-    int bCombined;
+    bool bComputeAtEdges;
+    bool bZevenbergenThorne;
+    bool bCombined;
+    bool bMultiDirectional;
     char** papszCreateOptions;
     int nBand;
 };
@@ -138,30 +159,85 @@ struct GDALDEMProcessingOptions
 /*                          ComputeVal()                                */
 /************************************************************************/
 
-typedef float (*GDALGeneric3x3ProcessingAlg) (float* pafWindow, float fDstNoDataValue, void* pData);
+template<class T>
+struct GDALGeneric3x3ProcessingAlg
+{
+    typedef float (*type) (const T* pafWindow, float fDstNoDataValue, void* pData);
+};
+
+template<class T>
+struct GDALGeneric3x3ProcessingAlg_multisample
+{
+    typedef int (*type)  (const T* pafThreeLineWin,
+                          int nLine1Off,
+                          int nLine2Off,
+                          int nLine3Off,
+                          int nXSize,
+                          void* pData,
+                          float* pafOutputBuf);
+};
+
+template<class T>
+static float ComputeVal( bool bSrcHasNoData, T fSrcNoDataValue,
+                         bool bIsSrcNoDataNan,
+                         T* afWin, float fDstNoDataValue,
+                         typename GDALGeneric3x3ProcessingAlg<T>::type pfnAlg,
+                         void* pData,
+                         bool bComputeAtEdges );
+
+template<>
+float ComputeVal( bool bSrcHasNoData, float fSrcNoDataValue,
+                  bool bIsSrcNoDataNan,
+                  float* afWin, float fDstNoDataValue,
+                  GDALGeneric3x3ProcessingAlg<float>::type pfnAlg,
+                  void* pData,
+                  bool bComputeAtEdges )
+{
+    if( bSrcHasNoData &&
+        ((!bIsSrcNoDataNan && ARE_REAL_EQUAL(afWin[4], fSrcNoDataValue)) ||
+         (bIsSrcNoDataNan && CPLIsNan(afWin[4]))) )
+    {
+        return fDstNoDataValue;
+    }
+    else if( bSrcHasNoData )
+    {
+        for( int k = 0; k < 9; k++ )
+        {
+            if( (!bIsSrcNoDataNan &&
+                 ARE_REAL_EQUAL(afWin[k], fSrcNoDataValue)) ||
+                (bIsSrcNoDataNan && CPLIsNan(afWin[k])) )
+            {
+                if( bComputeAtEdges )
+                    afWin[k] = afWin[4];
+                else
+                    return fDstNoDataValue;
+            }
+        }
+    }
+
+    return pfnAlg(afWin, fDstNoDataValue, pData);
+}
 
-static float ComputeVal(int bSrcHasNoData, float fSrcNoDataValue,
-                        int bIsSrcNoDataNan,
-                        float* afWin, float fDstNoDataValue,
-                        GDALGeneric3x3ProcessingAlg pfnAlg,
-                        void* pData,
-                        int bComputeAtEdges)
+// TODO.................
+template<>
+float ComputeVal( bool bSrcHasNoData, GInt32 fSrcNoDataValue,
+                  bool /* bIsSrcNoDataNan */,
+                  GInt32* afWin, float fDstNoDataValue,
+                  GDALGeneric3x3ProcessingAlg<GInt32>::type pfnAlg,
+                  void* pData,
+                  bool bComputeAtEdges )
 {
-    if (bSrcHasNoData &&
-            ((!bIsSrcNoDataNan && ARE_REAL_EQUAL(afWin[4], fSrcNoDataValue)) ||
-             (bIsSrcNoDataNan && CPLIsNan(afWin[4]))))
+    if( bSrcHasNoData && afWin[4] == fSrcNoDataValue )
     {
         return fDstNoDataValue;
     }
-    else if (bSrcHasNoData)
+    else if( bSrcHasNoData )
     {
-        int k;
-        for(k=0;k<9;k++)
+        for( int k = 0; k < 9; k++ )
         {
-            if ((!bIsSrcNoDataNan && ARE_REAL_EQUAL(afWin[k], fSrcNoDataValue)) ||
-                (bIsSrcNoDataNan && CPLIsNan(afWin[k])))
+            if( afWin[k] == fSrcNoDataValue )
             {
-                if (bComputeAtEdges)
+                if( bComputeAtEdges )
                     afWin[k] = afWin[4];
                 else
                     return fDstNoDataValue;
@@ -173,30 +249,47 @@ static float ComputeVal(int bSrcHasNoData, float fSrcNoDataValue,
 }
 
 /************************************************************************/
+/*                           INTERPOL()                                 */
+/************************************************************************/
+
+template<class T> static T INTERPOL(T a, T b, int bSrcHasNodata, T fSrcNoDataValue);
+
+template<>
+float INTERPOL(float a, float b, int bSrcHasNoData, float fSrcNoDataValue)
+{
+    return ((bSrcHasNoData && (ARE_REAL_EQUAL(a, fSrcNoDataValue) ||
+                               ARE_REAL_EQUAL(b, fSrcNoDataValue))) ?
+                                            fSrcNoDataValue : 2 * (a) - (b));
+}
+
+template<>
+GInt32 INTERPOL(GInt32 a, GInt32 b, int bSrcHasNoData, GInt32 fSrcNoDataValue)
+{
+    if( bSrcHasNoData && ((a == fSrcNoDataValue) || (b == fSrcNoDataValue)) )
+        return fSrcNoDataValue;
+    int nVal = 2 * a - b;
+    if( bSrcHasNoData && fSrcNoDataValue == nVal )
+        return nVal + 1;
+    return nVal;
+}
+
+/************************************************************************/
 /*                  GDALGeneric3x3Processing()                          */
 /************************************************************************/
 
+template<class T>
 static
-CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
-                                   GDALRasterBandH hDstBand,
-                                   GDALGeneric3x3ProcessingAlg pfnAlg,
-                                   void* pData,
-                                   int bComputeAtEdges,
-                                   GDALProgressFunc pfnProgress,
-                                   void * pProgressData)
-{
-    CPLErr eErr;
-    float *pafThreeLineWin; /* 3 line rotating source buffer */
-    float *pafOutputBuf;     /* 1 line destination buffer */
-    int i, j;
-
-    int bSrcHasNoData, bDstHasNoData;
-    float fSrcNoDataValue = 0.0, fDstNoDataValue = 0.0;
-
-    int nXSize = GDALGetRasterBandXSize(hSrcBand);
-    int nYSize = GDALGetRasterBandYSize(hSrcBand);
-
-    if (pfnProgress == NULL)
+CPLErr GDALGeneric3x3Processing(
+    GDALRasterBandH hSrcBand,
+    GDALRasterBandH hDstBand,
+    typename GDALGeneric3x3ProcessingAlg<T>::type pfnAlg,
+    typename GDALGeneric3x3ProcessingAlg_multisample<T>::type pfnAlg_multisample,
+    void *pData,
+    bool bComputeAtEdges,
+    GDALProgressFunc pfnProgress,
+    void *pProgressData )
+{
+    if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
 /* -------------------------------------------------------------------- */
@@ -208,8 +301,13 @@ CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
         return CE_Failure;
     }
 
-    pafOutputBuf = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nXSize);
-    pafThreeLineWin  = (float *) VSI_MALLOC2_VERBOSE(3*sizeof(float),(nXSize+1));
+    const int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    const int nYSize = GDALGetRasterBandYSize(hSrcBand);
+
+    // 1 line destination buffer.
+    float *pafOutputBuf = (float *) VSI_MALLOC2_VERBOSE(sizeof(float), nXSize);
+    // 3 line rotating source buffer.
+    T *pafThreeLineWin  = (T *) VSI_MALLOC2_VERBOSE(3 * sizeof(T), nXSize + 1);
     if( pafOutputBuf == NULL || pafThreeLineWin == NULL )
     {
         VSIFree(pafOutputBuf);
@@ -217,11 +315,52 @@ CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
         return CE_Failure;
     }
 
-    fSrcNoDataValue = (float) GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
-    fDstNoDataValue = (float) GDALGetRasterNoDataValue(hDstBand, &bDstHasNoData);
-    if (!bDstHasNoData)
+    GDALDataType eReadDT;
+    int bSrcHasNoData = FALSE;
+    const double dfNoDataValue =
+        GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
+
+    int bIsSrcNoDataNan = FALSE;
+    T fSrcNoDataValue = 0;
+    if( std::numeric_limits<T>::is_integer )
+    {
+        eReadDT = GDT_Int32;
+        if( bSrcHasNoData )
+        {
+            GDALDataType eSrcDT = GDALGetRasterDataType( hSrcBand );
+            CPLAssert( eSrcDT == GDT_Byte ||
+                       eSrcDT == GDT_UInt16 ||
+                       eSrcDT == GDT_Int16 );
+            const int nMinVal =
+                (eSrcDT == GDT_Byte ) ? 0 : (eSrcDT == GDT_UInt16) ? 0 : -32768;
+            const int nMaxVal =
+                (eSrcDT == GDT_Byte )
+                ? 255
+                : (eSrcDT == GDT_UInt16) ? 65535 : 32767;
+
+            if( fabs(dfNoDataValue - floor(dfNoDataValue + 0.5)) < 1e-2 &&
+                dfNoDataValue >= nMinVal && dfNoDataValue <= nMaxVal )
+            {
+                fSrcNoDataValue = static_cast<T>(floor(dfNoDataValue + 0.5));
+            }
+            else
+            {
+                bSrcHasNoData = FALSE;
+            }
+        }
+    }
+    else
+    {
+        eReadDT = GDT_Float32;
+        fSrcNoDataValue = static_cast<T>(dfNoDataValue);
+        bIsSrcNoDataNan = bSrcHasNoData && CPLIsNan(dfNoDataValue);
+    }
+
+    int bDstHasNoData = FALSE;
+    float fDstNoDataValue =
+        static_cast<float>(GDALGetRasterNoDataValue(hDstBand, &bDstHasNoData));
+    if( !bDstHasNoData )
         fDstNoDataValue = 0.0;
-    int bIsSrcNoDataNan = bSrcHasNoData && CPLIsNan(fSrcNoDataValue);
 
     int nLine1Off = 0*nXSize;
     int nLine2Off = 1*nXSize;
@@ -235,44 +374,74 @@ CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
     //      6 7 8
 
     /* Preload the first 2 lines */
-    for ( i = 0; i < 2 && i < nYSize; i++)
+
+    bool abLineHasNoDataValue[3] = {
+        CPL_TO_BOOL(bSrcHasNoData),
+        CPL_TO_BOOL(bSrcHasNoData),
+        CPL_TO_BOOL(bSrcHasNoData)
+    };
+
+    // Create an extra scope for VC12 to ignore i.
     {
-        if( GDALRasterIO(   hSrcBand,
-                        GF_Read,
-                        0, i,
-                        nXSize, 1,
-                        pafThreeLineWin + i * nXSize,
-                        nXSize, 1,
-                        GDT_Float32,
-                        0, 0) != CE_None )
+      for( int i = 0; i < 2 && i < nYSize; i++ )
+      {
+        if( GDALRasterIO( hSrcBand,
+                          GF_Read,
+                          0, i,
+                          nXSize, 1,
+                          pafThreeLineWin + i * nXSize,
+                          nXSize, 1,
+                          eReadDT,
+                          0, 0) != CE_None )
         {
-            eErr = CE_Failure;
-            goto end;
+            CPLFree(pafOutputBuf);
+            CPLFree(pafThreeLineWin);
+
+            return CE_Failure;
         }
-    }
+        if( std::numeric_limits<T>::is_integer && bSrcHasNoData )
+        {
+            abLineHasNoDataValue[i] = false;
+            for( int iX = 0; iX < nXSize; iX++ )
+            {
+                if( pafThreeLineWin[i * nXSize + iX] == fSrcNoDataValue )
+                {
+                    abLineHasNoDataValue[i] = true;
+                    break;
+                }
+            }
+        }
+      }
+    }  // End extra scope for VC12
 
-    if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
+    CPLErr eErr = CE_None;
+    if( bComputeAtEdges && nXSize >= 2 && nYSize >= 2 )
     {
-        for (j = 0; j < nXSize; j++)
+        for( int j = 0; j < nXSize; j++ )
         {
-            float afWin[9];
             int jmin = (j == 0) ? j : j - 1;
             int jmax = (j == nXSize - 1) ? j : j + 1;
 
-            afWin[0] = INTERPOL(pafThreeLineWin[jmin], pafThreeLineWin[nXSize + jmin]);
-            afWin[1] = INTERPOL(pafThreeLineWin[j],    pafThreeLineWin[nXSize + j]);
-            afWin[2] = INTERPOL(pafThreeLineWin[jmax], pafThreeLineWin[nXSize + jmax]);
-            afWin[3] = pafThreeLineWin[jmin];
-            afWin[4] = pafThreeLineWin[j];
-            afWin[5] = pafThreeLineWin[jmax];
-            afWin[6] = pafThreeLineWin[nXSize + jmin];
-            afWin[7] = pafThreeLineWin[nXSize + j];
-            afWin[8] = pafThreeLineWin[nXSize + jmax];
-
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
+            T afWin[9] = {
+                INTERPOL(pafThreeLineWin[jmin], pafThreeLineWin[nXSize + jmin],
+                         bSrcHasNoData, fSrcNoDataValue),
+                INTERPOL(pafThreeLineWin[j],    pafThreeLineWin[nXSize + j],
+                         bSrcHasNoData, fSrcNoDataValue),
+                INTERPOL(pafThreeLineWin[jmax], pafThreeLineWin[nXSize + jmax],
+                         bSrcHasNoData, fSrcNoDataValue),
+                pafThreeLineWin[jmin],
+                pafThreeLineWin[j],
+                pafThreeLineWin[jmax],
+                pafThreeLineWin[nXSize + jmin],
+                pafThreeLineWin[nXSize + j],
+                pafThreeLineWin[nXSize + jmax]
+            };
+            pafOutputBuf[j] = ComputeVal(
+                CPL_TO_BOOL(bSrcHasNoData),
+                fSrcNoDataValue,
+                CPL_TO_BOOL(bIsSrcNoDataNan),
+                afWin, fDstNoDataValue,
+                pfnAlg, pData, bComputeAtEdges);
         }
         eErr = GDALRasterIO(hDstBand, GF_Write,
                     0, 0, nXSize, 1,
@@ -281,7 +450,7 @@ CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
     else
     {
         // Exclude the edges
-        for (j = 0; j < nXSize; j++)
+        for( int j = 0; j < nXSize; j++ )
         {
             pafOutputBuf[j] = fDstNoDataValue;
         }
@@ -289,7 +458,7 @@ CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
                     0, 0, nXSize, 1,
                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
 
-        if (eErr == CE_None && nYSize > 1)
+        if( eErr == CE_None && nYSize > 1 )
         {
             eErr = GDALRasterIO(hDstBand, GF_Write,
                         0, nYSize - 1, nXSize, 1,
@@ -297,10 +466,15 @@ CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
         }
     }
     if( eErr != CE_None )
-        goto end;
+    {
+        CPLFree(pafOutputBuf);
+        CPLFree(pafThreeLineWin);
 
+        return eErr;
+    }
 
-    for ( i = 1; i < nYSize-1; i++)
+    int i = 1;  // Used after for.
+    for( ; i < nYSize-1; i++ )
     {
         /* Read third line of the line buffer */
         eErr = GDALRasterIO(   hSrcBand,
@@ -309,135 +483,279 @@ CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
                         nXSize, 1,
                         pafThreeLineWin + nLine3Off,
                         nXSize, 1,
-                        GDT_Float32,
+                        eReadDT,
                         0, 0);
-        if (eErr != CE_None)
-            goto end;
-
-        if (bComputeAtEdges && nXSize >= 2)
-        {
-            float afWin[9];
-
-            j = 0;
-            afWin[0] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j+1]);
-            afWin[1] = pafThreeLineWin[nLine1Off + j];
-            afWin[2] = pafThreeLineWin[nLine1Off + j+1];
-            afWin[3] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j+1]);
-            afWin[4] = pafThreeLineWin[nLine2Off + j];
-            afWin[5] = pafThreeLineWin[nLine2Off + j+1];
-            afWin[6] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j+1]);
-            afWin[7] = pafThreeLineWin[nLine3Off + j];
-            afWin[8] = pafThreeLineWin[nLine3Off + j+1];
-
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
-            j = nXSize - 1;
+        if( eErr != CE_None )
+        {
+            CPLFree(pafOutputBuf);
+            CPLFree(pafThreeLineWin);
 
-            afWin[0] = pafThreeLineWin[nLine1Off + j-1];
-            afWin[1] = pafThreeLineWin[nLine1Off + j];
-            afWin[2] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j-1]);
-            afWin[3] = pafThreeLineWin[nLine2Off + j-1];
-            afWin[4] = pafThreeLineWin[nLine2Off + j];
-            afWin[5] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j-1]);
-            afWin[6] = pafThreeLineWin[nLine3Off + j-1];
-            afWin[7] = pafThreeLineWin[nLine3Off + j];
-            afWin[8] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j-1]);
-
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
+            return eErr;
+        }
+
+        // In case none of the 3 lines have nodata values, then no need to
+        // check it in ComputeVal()
+        bool bOneOfThreeLinesHasNoData = CPL_TO_BOOL(bSrcHasNoData);
+        if( std::numeric_limits<T>::is_integer && bSrcHasNoData )
+        {
+            bool bLastLineHasNoDataValue = false;
+            int iX = 0;
+            for( ; iX + 3 < nXSize; iX +=4 )
+            {
+                if( pafThreeLineWin[nLine3Off + iX] == fSrcNoDataValue ||
+                    pafThreeLineWin[nLine3Off + iX + 1] == fSrcNoDataValue ||
+                    pafThreeLineWin[nLine3Off + iX + 2] == fSrcNoDataValue ||
+                    pafThreeLineWin[nLine3Off + iX + 3] == fSrcNoDataValue )
+                {
+                    bLastLineHasNoDataValue = true;
+                    break;
+                }
+            }
+            if( !bLastLineHasNoDataValue )
+            {
+                for( ; iX < nXSize; iX++ )
+                {
+                    if( pafThreeLineWin[nLine3Off + iX] == fSrcNoDataValue )
+                    {
+                        bLastLineHasNoDataValue = true;
+                    }
+                }
+            }
+            abLineHasNoDataValue[nLine3Off / nXSize] = bLastLineHasNoDataValue;
+
+            bOneOfThreeLinesHasNoData = abLineHasNoDataValue[0] ||
+                                abLineHasNoDataValue[1] ||
+                                abLineHasNoDataValue[2];
+        }
+
+        if( bComputeAtEdges && nXSize >= 2 )
+        {
+            int j = 0;
+            T afWin[9] = {
+                INTERPOL(pafThreeLineWin[nLine1Off + j],
+                         pafThreeLineWin[nLine1Off + j+1],
+                         bSrcHasNoData, fSrcNoDataValue),
+                pafThreeLineWin[nLine1Off + j],
+                pafThreeLineWin[nLine1Off + j+1],
+                INTERPOL(pafThreeLineWin[nLine2Off + j],
+                         pafThreeLineWin[nLine2Off + j+1],
+                         bSrcHasNoData, fSrcNoDataValue),
+                pafThreeLineWin[nLine2Off + j],
+                pafThreeLineWin[nLine2Off + j+1],
+                INTERPOL(pafThreeLineWin[nLine3Off + j],
+                         pafThreeLineWin[nLine3Off + j+1],
+                         bSrcHasNoData, fSrcNoDataValue),
+                pafThreeLineWin[nLine3Off + j],
+                pafThreeLineWin[nLine3Off + j+1]
+            };
+
+            pafOutputBuf[j] =
+                ComputeVal(
+                    CPL_TO_BOOL(bOneOfThreeLinesHasNoData),
+                    fSrcNoDataValue,
+                    CPL_TO_BOOL(bIsSrcNoDataNan),
+                    afWin, fDstNoDataValue,
+                    pfnAlg, pData, bComputeAtEdges);
         }
         else
         {
             // Exclude the edges
             pafOutputBuf[0] = fDstNoDataValue;
-            if (nXSize > 1)
-                pafOutputBuf[nXSize - 1] = fDstNoDataValue;
         }
 
-        for (j = 1; j < nXSize - 1; j++)
+        int j = 1;
+        if( pfnAlg_multisample && !bOneOfThreeLinesHasNoData )
+        {
+            j = pfnAlg_multisample(pafThreeLineWin,
+                                   nLine1Off,
+                                   nLine2Off,
+                                   nLine3Off,
+                                   nXSize,
+                                   pData,
+                                   pafOutputBuf);
+        }
+
+        for( ; j < nXSize - 1; j++ )
         {
-            float afWin[9];
-            afWin[0] = pafThreeLineWin[nLine1Off + j-1];
-            afWin[1] = pafThreeLineWin[nLine1Off + j];
-            afWin[2] = pafThreeLineWin[nLine1Off + j+1];
-            afWin[3] = pafThreeLineWin[nLine2Off + j-1];
-            afWin[4] = pafThreeLineWin[nLine2Off + j];
-            afWin[5] = pafThreeLineWin[nLine2Off + j+1];
-            afWin[6] = pafThreeLineWin[nLine3Off + j-1];
-            afWin[7] = pafThreeLineWin[nLine3Off + j];
-            afWin[8] = pafThreeLineWin[nLine3Off + j+1];
+            T afWin[9] = {
+                pafThreeLineWin[nLine1Off + j-1],
+                pafThreeLineWin[nLine1Off + j],
+                pafThreeLineWin[nLine1Off + j+1],
+                pafThreeLineWin[nLine2Off + j-1],
+                pafThreeLineWin[nLine2Off + j],
+                pafThreeLineWin[nLine2Off + j+1],
+                pafThreeLineWin[nLine3Off + j-1],
+                pafThreeLineWin[nLine3Off + j],
+                pafThreeLineWin[nLine3Off + j+1]
+            };
 
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
+            pafOutputBuf[j] =
+                ComputeVal(
+                    CPL_TO_BOOL(bOneOfThreeLinesHasNoData),
+                    fSrcNoDataValue,
+                    CPL_TO_BOOL(bIsSrcNoDataNan),
+                    afWin, fDstNoDataValue,
+                    pfnAlg, pData, bComputeAtEdges);
+        }
+
+        if( bComputeAtEdges && nXSize >= 2 )
+        {
+            j = nXSize - 1;
+
+            T afWin[9] = {
+                pafThreeLineWin[nLine1Off + j-1],
+                pafThreeLineWin[nLine1Off + j],
+                INTERPOL(pafThreeLineWin[nLine1Off + j],
+                         pafThreeLineWin[nLine1Off + j-1],
+                         bSrcHasNoData, fSrcNoDataValue),
+                pafThreeLineWin[nLine2Off + j-1],
+                pafThreeLineWin[nLine2Off + j],
+                INTERPOL(pafThreeLineWin[nLine2Off + j],
+                         pafThreeLineWin[nLine2Off + j-1],
+                         bSrcHasNoData, fSrcNoDataValue),
+                pafThreeLineWin[nLine3Off + j-1],
+                pafThreeLineWin[nLine3Off + j],
+                INTERPOL(pafThreeLineWin[nLine3Off + j],
+                         pafThreeLineWin[nLine3Off + j-1],
+                         bSrcHasNoData, fSrcNoDataValue)
+            };
+
+            pafOutputBuf[j] =
+                ComputeVal(
+                    CPL_TO_BOOL(bOneOfThreeLinesHasNoData),
+                    fSrcNoDataValue,
+                    CPL_TO_BOOL(bIsSrcNoDataNan),
+                    afWin, fDstNoDataValue,
+                    pfnAlg, pData, bComputeAtEdges);
+        }
+        else
+        {
+            // Exclude the edges
+            if( nXSize > 1 )
+                pafOutputBuf[nXSize - 1] = fDstNoDataValue;
         }
 
         /* -----------------------------------------
          * Write Line to Raster
          */
         eErr = GDALRasterIO(hDstBand, GF_Write, 0, i, nXSize, 1,
-                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
-        if (eErr != CE_None)
-            goto end;
+                            pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+        if( eErr != CE_None )
+        {
+            CPLFree(pafOutputBuf);
+            CPLFree(pafThreeLineWin);
+
+            return eErr;
+        }
 
         if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
             eErr = CE_Failure;
-            goto end;
+
+            CPLFree(pafOutputBuf);
+            CPLFree(pafThreeLineWin);
+
+            return eErr;
         }
 
-        int nTemp = nLine1Off;
+        const int nTemp = nLine1Off;
         nLine1Off = nLine2Off;
         nLine2Off = nLine3Off;
         nLine3Off = nTemp;
     }
 
-    if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
+    if( bComputeAtEdges && nXSize >= 2 && nYSize >= 2 )
     {
-        for (j = 0; j < nXSize; j++)
+        for( int j = 0; j < nXSize; j++ )
         {
-            float afWin[9];
             int jmin = (j == 0) ? j : j - 1;
             int jmax = (j == nXSize - 1) ? j : j + 1;
 
-            afWin[0] = pafThreeLineWin[nLine1Off + jmin];
-            afWin[1] = pafThreeLineWin[nLine1Off + j];
-            afWin[2] = pafThreeLineWin[nLine1Off + jmax];
-            afWin[3] = pafThreeLineWin[nLine2Off + jmin];
-            afWin[4] = pafThreeLineWin[nLine2Off + j];
-            afWin[5] = pafThreeLineWin[nLine2Off + jmax];
-            afWin[6] = INTERPOL(pafThreeLineWin[nLine2Off + jmin], pafThreeLineWin[nLine1Off + jmin]);
-            afWin[7] = INTERPOL(pafThreeLineWin[nLine2Off + j],    pafThreeLineWin[nLine1Off + j]);
-            afWin[8] = INTERPOL(pafThreeLineWin[nLine2Off + jmax], pafThreeLineWin[nLine1Off + jmax]);
-
-            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                         bIsSrcNoDataNan,
-                                         afWin, fDstNoDataValue,
-                                         pfnAlg, pData, bComputeAtEdges);
+            T afWin[9] = {
+                pafThreeLineWin[nLine1Off + jmin],
+                pafThreeLineWin[nLine1Off + j],
+                pafThreeLineWin[nLine1Off + jmax],
+                pafThreeLineWin[nLine2Off + jmin],
+                pafThreeLineWin[nLine2Off + j],
+                pafThreeLineWin[nLine2Off + jmax],
+                INTERPOL(pafThreeLineWin[nLine2Off + jmin],
+                         pafThreeLineWin[nLine1Off + jmin],
+                         bSrcHasNoData, fSrcNoDataValue),
+                INTERPOL(pafThreeLineWin[nLine2Off + j],
+                         pafThreeLineWin[nLine1Off + j],
+                         bSrcHasNoData, fSrcNoDataValue),
+                INTERPOL(pafThreeLineWin[nLine2Off + jmax],
+                         pafThreeLineWin[nLine1Off + jmax],
+                         bSrcHasNoData, fSrcNoDataValue),
+            };
+
+            pafOutputBuf[j] = ComputeVal(
+                CPL_TO_BOOL(bSrcHasNoData),
+                fSrcNoDataValue,
+                CPL_TO_BOOL(bIsSrcNoDataNan),
+                afWin, fDstNoDataValue,
+                pfnAlg, pData, bComputeAtEdges);
         }
         eErr = GDALRasterIO(hDstBand, GF_Write,
-                     0, i, nXSize, 1,
-                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+                            0, i, nXSize, 1,
+                            pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
         if( eErr != CE_None )
-            goto end;
+        {
+            CPLFree(pafOutputBuf);
+            CPLFree(pafThreeLineWin);
+
+            return eErr;
+        }
     }
 
     pfnProgress( 1.0, NULL, pProgressData );
     eErr = CE_None;
 
-end:
     CPLFree(pafOutputBuf);
     CPLFree(pafThreeLineWin);
 
     return eErr;
 }
 
+/************************************************************************/
+/*                            GradientAlg                               */
+/************************************************************************/
+
+typedef enum
+{
+    HORN,
+    ZEVENBERGEN_THORNE
+} GradientAlg;
+
+template<class T, GradientAlg alg> struct Gradient
+{
+    static void inline calc(const T* afWin, double inv_ewres, double inv_nsres,
+                            double&x, double&y);
+};
+
+template<class T> struct Gradient<T, HORN>
+{
+    static void calc(const T* afWin, double inv_ewres, double inv_nsres,
+                     double&x, double&y)
+    {
+        x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+             (afWin[2] + afWin[5] + afWin[5] + afWin[8])) * inv_ewres;
+
+        y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+             (afWin[0] + afWin[1] + afWin[1] + afWin[2])) * inv_nsres;
+    }
+};
+
+template<class T> struct Gradient<T, ZEVENBERGEN_THORNE>
+{
+    static void calc(const T* afWin, double inv_ewres, double inv_nsres,
+                     double&x, double&y)
+    {
+        x = (afWin[3] - afWin[5]) * inv_ewres;
+        y = (afWin[7] - afWin[1]) * inv_nsres;
+    }
+};
 
 /************************************************************************/
 /*                         GDALHillshade()                              */
@@ -445,13 +763,21 @@ end:
 
 typedef struct
 {
-    double nsres;
-    double ewres;
+    double inv_nsres;
+    double inv_ewres;
     double sin_altRadians;
-    double cos_altRadians_mul_z_scale_factor;
+    double cos_alt_mul_z;
     double azRadians;
-    double square_z_scale_factor;
-    double square_M_PI_2;
+    double cos_az_mul_cos_alt_mul_z;
+    double sin_az_mul_cos_alt_mul_z;
+    double square_z;
+    double sin_altRadians_mul_254;
+    double cos_az_mul_cos_alt_mul_z_mul_254;
+    double sin_az_mul_cos_alt_mul_z_mul_254;
+
+    double square_z_mul_square_inv_res;
+    double cos_az_mul_cos_alt_mul_z_mul_254_mul_inv_res;
+    double sin_az_mul_cos_alt_mul_z_mul_254_mul_inv_res;
 } GDALHillshadeAlgData;
 
 /* Unoptimized formulas are :
@@ -463,168 +789,425 @@ typedef struct
         (afWin[0] + afWin[1] + afWin[1] + afWin[2])) /
         (8.0 * psData->nsres * psData->scale);
 
-    slope = M_PI / 2 - atan(sqrt(x*x + y*y));
+    slope = atan(sqrt(x*x + y*y));
 
     aspect = atan2(y,x);
 
-    cang = sin(alt * degreesToRadians) * sin(slope) +
-           cos(alt * degreesToRadians) * cos(slope) *
-           cos(az * degreesToRadians - M_PI/2 - aspect);
-*/
+    cang = sin(alt) * cos(slope) +
+           cos(alt) * sin(slope) *
+           cos(az - M_PI/2 - aspect);
 
-static
-float GDALHillshadeAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
-{
-    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
-    double x, y, aspect, xx_plus_yy, cang;
+We can avoid a lot of trigonometric computations:
 
-    // First Slope ...
-    x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
-        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
+    since cos(atan(x)) = 1 / sqrt(1+x^2)
+      ==> cos(slope) = 1 / sqrt(1+ x*x+y*y)
 
-    y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
-        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
+      and sin(atan(x)) = x / sqrt(1+x^2)
+      ==> sin(slope) = sqrt(x*x + y*y) / sqrt(1+ x*x+y*y)
 
-    xx_plus_yy = x * x + y * y;
+      and cos(az - M_PI/2 - aspect)
+        = cos(-az + M_PI/2 + aspect)
+        = cos(M_PI/2 - (az - aspect))
+        = sin(az - aspect)
+        = -sin(aspect-az)
 
-    // ... then aspect...
-    aspect = atan2(y,x);
+==> cang = (sin(alt) - cos(alt) * sqrt(x*x + y*y)  * sin(aspect-as)) /
+           sqrt(1+ x*x+y*y)
 
-    // ... then the shade value
-    cang = (psData->sin_altRadians -
-           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
-           sin(aspect - psData->azRadians)) /
-           sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
+    But:
+    sin(aspect - az) = sin(aspect)*cos(az) - cos(aspect)*sin(az))
 
-    if (cang <= 0.0)
-        cang = 1.0;
-    else
-        cang = 1.0 + (254.0 * cang);
+and as sin(aspect)=sin(atan2(y,x)) = y / sqrt(xx_plus_yy)
+   and cos(aspect)=cos(atan2(y,x)) = x / sqrt(xx_plus_yy)
+
+    sin(aspect - az) = (y * cos(az) - x * sin(az)) / sqrt(xx_plus_yy)
 
-    return (float) cang;
+so we get a final formula with just one transcendental function
+(reciprocal of square root):
+
+    cang = (psData->sin_altRadians -
+           (y * psData->cos_az_mul_cos_alt_mul_z -
+            x * psData->sin_az_mul_cos_alt_mul_z)) /
+           sqrt(1 + psData->square_z * xx_plus_yy);
+*/
+
+#ifdef HAVE_SSE2
+inline double ApproxADivByInvSqrtB( double a, double b )
+{
+    __m128d regB = _mm_load_sd( &b );
+    __m128d regB_half = _mm_mul_sd( regB, _mm_set1_pd( 0.5 ) );
+    // Compute rough approximation of 1 / sqrt(b) with _mm_rsqrt_ss
+    regB = _mm_cvtss_sd( regB, _mm_rsqrt_ss(
+                            _mm_cvtsd_ss( _mm_setzero_ps(), regB ) ) );
+    // And perform one step of Newton-Raphson approximation to improve it
+    // approx_inv_sqrt_x = approx_inv_sqrt_x*(1.5 -
+    //                            0.5*x*approx_inv_sqrt_x*approx_inv_sqrt_x);
+    regB = _mm_mul_sd(regB, _mm_sub_sd( _mm_set1_pd( 1.5 ),
+                                        _mm_mul_sd(regB_half,
+                                                   _mm_mul_sd(regB, regB)) ) );
+    double dOut;
+    _mm_store_sd( &dOut, regB );
+    return a * dOut;
 }
+#else
+inline double ApproxADivByInvSqrtB( double a, double b )
+{
+    return a / sqrt(b);
+}
+#endif
 
+template<class T, GradientAlg alg>
 static
-float GDALHillshadeCombinedAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+float GDALHillshadeAlg (const T* afWin, float /*fDstNoDataValue*/, void* pData)
 {
     GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
-    double x, y, aspect, xx_plus_yy, cang;
 
     // First Slope ...
-    x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
-        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
+    double x, y;
+    Gradient<T, alg>::calc(afWin, psData->inv_ewres, psData->inv_nsres, x, y);
 
-    y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
-        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
-
-    xx_plus_yy = x * x + y * y;
-
-    // ... then aspect...
-    aspect = atan2(y,x);
-    double slope = xx_plus_yy * psData->square_z_scale_factor;
+    const double xx_plus_yy = x * x + y * y;
 
     // ... then the shade value
-    cang = acos((psData->sin_altRadians -
-           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
-           sin(aspect - psData->azRadians)) /
-           sqrt(1 + slope));
+    const double cang_mul_254 =
+        ApproxADivByInvSqrtB(
+            psData->sin_altRadians_mul_254 -
+            (y * psData->cos_az_mul_cos_alt_mul_z_mul_254 -
+             x * psData->sin_az_mul_cos_alt_mul_z_mul_254),
+            1 + psData->square_z * xx_plus_yy);
 
-    // combined shading
-    cang = 1 - cang * atan(sqrt(slope)) / psData->square_M_PI_2;
-
-    if (cang <= 0.0)
-        cang = 1.0;
-    else
-        cang = 1.0 + (254.0 * cang);
+    const double cang = cang_mul_254 <= 0.0 ? 1.0 : 1.0 + cang_mul_254;
 
-    return (float) cang;
+    return static_cast<float>(cang);
 }
 
+template<class T>
 static
-float GDALHillshadeZevenbergenThorneAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+float GDALHillshadeAlg_same_res (const T* afWin, float /*fDstNoDataValue*/, void* pData)
 {
     GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
-    double x, y, aspect, xx_plus_yy, cang;
 
     // First Slope ...
-    x = (afWin[3] - afWin[5]) / psData->ewres;
-
-    y = (afWin[7] - afWin[1]) / psData->nsres;
+    /*x = (afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+        (afWin[2] + afWin[5] + afWin[5] + afWin[8]);
+
+    y = (afWin[0] + afWin[1] + afWin[1] + afWin[2]) -
+        (afWin[6] + afWin[7] + afWin[7] + afWin[8]);*/
+
+    T accX = afWin[0] - afWin[8];
+    const T six_minus_two = afWin[6] - afWin[2];
+    T accY = accX;
+    const T three_minus_five = afWin[3] - afWin[5];
+    const T one_minus_seven = afWin[1] - afWin[7];
+    accX += three_minus_five;
+    accY += one_minus_seven;
+    accX += three_minus_five;
+    accY += one_minus_seven;
+    accX += six_minus_two;
+    accY -= six_minus_two;
+    const double x = accX;
+    const double y = accY;
+
+    const double xx_plus_yy = x * x + y * y;
 
-    xx_plus_yy = x * x + y * y;
+    // ... then the shade value
+    const double cang_mul_254 =
+        ApproxADivByInvSqrtB(
+            psData->sin_altRadians_mul_254 +
+            (x * psData->sin_az_mul_cos_alt_mul_z_mul_254_mul_inv_res +
+             y * psData->cos_az_mul_cos_alt_mul_z_mul_254_mul_inv_res),
+            1 + psData->square_z_mul_square_inv_res * xx_plus_yy);
 
-    // ... then aspect...
-    aspect = atan2(y,x);
+    const double cang = cang_mul_254 <= 0.0 ? 1.0 : 1.0 + cang_mul_254;
 
-    // ... then the shade value
-    cang = (psData->sin_altRadians -
-           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
-           sin(aspect - psData->azRadians)) /
-           sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
+    return static_cast<float>(cang);
+}
 
-    if (cang <= 0.0)
-        cang = 1.0;
-    else
-        cang = 1.0 + (254.0 * cang);
+#ifdef HAVE_16_SSE_REG
+template<class T>
+static
+int GDALHillshadeAlg_same_res_multisample( const T* pafThreeLineWin,
+                                           int nLine1Off,
+                                           int nLine2Off,
+                                           int nLine3Off,
+                                           int nXSize,
+                                           void* pData,
+                                           float* pafOutputBuf )
+{
+    // Only valid for T == int
 
-    return (float) cang;
+    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
+    const __m128d reg_fact_x = _mm_load1_pd(
+                      &(psData->sin_az_mul_cos_alt_mul_z_mul_254_mul_inv_res));
+    const __m128d reg_fact_y = _mm_load1_pd (
+                      &(psData->cos_az_mul_cos_alt_mul_z_mul_254_mul_inv_res));
+    const __m128d reg_constant_num = _mm_load1_pd(
+                      &(psData->sin_altRadians_mul_254));
+    const __m128d reg_constant_denom = _mm_load1_pd(
+                      &(psData->square_z_mul_square_inv_res));
+    const __m128d reg_half = _mm_set1_pd(0.5);
+    const __m128d reg_one = _mm_add_pd(reg_half, reg_half);
+    const __m128 reg_one_float = _mm_set1_ps(1);
+
+    int j = 1;  // Used after for.
+    for( ; j < nXSize - 4; j+= 4 )
+    {
+        const T* firstLine  = pafThreeLineWin + nLine1Off + j-1;
+        const T* secondLine = pafThreeLineWin + nLine2Off + j-1;
+        const T* thirdLine  = pafThreeLineWin + nLine3Off + j-1;
+
+        __m128i firstLine0 = _mm_loadu_si128( (__m128i const*)firstLine );
+        __m128i firstLine1 = _mm_loadu_si128( (__m128i const*)(firstLine + 1) );
+        __m128i firstLine2 = _mm_loadu_si128( (__m128i const*)(firstLine + 2) );
+        __m128i thirdLine0 = _mm_loadu_si128( (__m128i const*)thirdLine );
+        __m128i thirdLine1 = _mm_loadu_si128( (__m128i const*)(thirdLine + 1) );
+        __m128i thirdLine2 = _mm_loadu_si128( (__m128i const*)(thirdLine + 2) );
+        __m128i accX = _mm_sub_epi32( firstLine0, thirdLine2);
+        const __m128i six_minus_two = _mm_sub_epi32( thirdLine0, firstLine2 );
+        __m128i accY = accX;
+        const __m128i three_minus_five = _mm_sub_epi32(
+                          _mm_loadu_si128( (__m128i const*)secondLine ),
+                          _mm_loadu_si128( (__m128i const*)(secondLine+2) ) );
+        const __m128i one_minus_seven = _mm_sub_epi32( firstLine1, thirdLine1 );
+        accX = _mm_add_epi32(accX, three_minus_five);
+        accY = _mm_add_epi32(accY, one_minus_seven);
+        accX = _mm_add_epi32(accX, three_minus_five);
+        accY = _mm_add_epi32(accY, one_minus_seven);
+        accX = _mm_add_epi32(accX, six_minus_two);
+        accY = _mm_sub_epi32(accY, six_minus_two);
+
+        __m128d reg_x0 = _mm_cvtepi32_pd(accX);
+        __m128d reg_x1 = _mm_cvtepi32_pd(_mm_srli_si128(accX, 8));
+        __m128d reg_y0 = _mm_cvtepi32_pd(accY);
+        __m128d reg_y1 = _mm_cvtepi32_pd(_mm_srli_si128(accY, 8));
+        __m128d reg_xx_plus_yy0 = _mm_add_pd( _mm_mul_pd(reg_x0, reg_x0),
+                                              _mm_mul_pd(reg_y0, reg_y0) );
+        __m128d reg_xx_plus_yy1 = _mm_add_pd( _mm_mul_pd(reg_x1, reg_x1),
+                                              _mm_mul_pd(reg_y1, reg_y1) );
+
+        __m128d reg_numerator0 = _mm_add_pd(reg_constant_num,
+                  _mm_add_pd( _mm_mul_pd(reg_fact_x, reg_x0),
+                              _mm_mul_pd(reg_fact_y, reg_y0) ) );
+        __m128d reg_numerator1 = _mm_add_pd(reg_constant_num,
+                  _mm_add_pd( _mm_mul_pd(reg_fact_x, reg_x1),
+                              _mm_mul_pd(reg_fact_y, reg_y1) ) );
+        __m128d reg_denominator0 = _mm_add_pd(reg_one,
+                              _mm_mul_pd(reg_constant_denom, reg_xx_plus_yy0));
+        __m128d reg_denominator1 = _mm_add_pd(reg_one,
+                              _mm_mul_pd(reg_constant_denom, reg_xx_plus_yy1));
+
+        __m128d regB0 = reg_denominator0;
+        __m128d regB1 = reg_denominator1;
+        __m128d regB0_half = _mm_mul_pd( regB0, reg_half );
+        __m128d regB1_half = _mm_mul_pd( regB1, reg_half );
+        // Compute rough approximation of 1 / sqrt(b) with _mm_rsqrt_ps
+        regB0 = _mm_cvtps_pd( _mm_rsqrt_ps( _mm_cvtpd_ps( regB0 ) ) );
+        regB1 = _mm_cvtps_pd( _mm_rsqrt_ps( _mm_cvtpd_ps( regB1 ) ) );
+        // And perform one step of Newton-Raphson approximation to improve it
+        // approx_inv_sqrt_x = approx_inv_sqrt_x*(1.5 -
+        //                            0.5*x*approx_inv_sqrt_x*approx_inv_sqrt_x);
+        const __m128d reg_one_and_a_half = _mm_add_pd(reg_one, reg_half);
+        regB0 = _mm_mul_pd(regB0, _mm_sub_pd( reg_one_and_a_half,
+                                             _mm_mul_pd(regB0_half,
+                                                  _mm_mul_pd(regB0, regB0)) ) );
+        regB1 = _mm_mul_pd(regB1, _mm_sub_pd( reg_one_and_a_half,
+                                            _mm_mul_pd(regB1_half,
+                                                  _mm_mul_pd(regB1, regB1)) ) );
+        reg_numerator0 = _mm_mul_pd(reg_numerator0, regB0);
+        reg_numerator1 = _mm_mul_pd(reg_numerator1, regB1);
+
+        __m128 res = _mm_castsi128_ps(
+          _mm_unpacklo_epi64 (_mm_castps_si128(_mm_cvtpd_ps(reg_numerator0)),
+                              _mm_castps_si128(_mm_cvtpd_ps(reg_numerator1))));
+        res = _mm_add_ps(res, reg_one_float);
+        res = _mm_max_ps(res, reg_one_float);
+
+        _mm_storeu_ps( pafOutputBuf + j, res);
+    }
+    return j;
 }
+#endif
 
+static const double INV_SQUARE_OF_HALF_PI = 1.0 / ((M_PI*M_PI)/4);
+
+template<class T, GradientAlg alg>
 static
-float GDALHillshadeZevenbergenThorneCombinedAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+float GDALHillshadeCombinedAlg (const T* afWin, float /*fDstNoDataValue*/, void* pData)
 {
     GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
-    double x, y, aspect, xx_plus_yy, cang;
 
     // First Slope ...
-    x = (afWin[3] - afWin[5]) / psData->ewres;
-
-    y = (afWin[7] - afWin[1]) / psData->nsres;
+    double x, y;
+    Gradient<T, alg>::calc(afWin, psData->inv_ewres, psData->inv_nsres, x, y);
 
-    xx_plus_yy = x * x + y * y;
+    const double xx_plus_yy = x * x + y * y;
 
-    // ... then aspect...
-    aspect = atan2(y,x);
-    double slope = xx_plus_yy * psData->square_z_scale_factor;
+    const double slope = xx_plus_yy * psData->square_z;
 
     // ... then the shade value
-    cang = acos((psData->sin_altRadians -
-           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
-           sin(aspect - psData->azRadians)) /
-           sqrt(1 + slope));
+    double cang =
+        acos(
+            ApproxADivByInvSqrtB(
+                psData->sin_altRadians -
+                (y * psData->cos_az_mul_cos_alt_mul_z -
+                 x * psData->sin_az_mul_cos_alt_mul_z),
+                1 + slope));
 
     // combined shading
-    cang = 1 - cang * atan(sqrt(slope)) / psData->square_M_PI_2;
+    cang = 1 - cang * atan(sqrt(slope)) * INV_SQUARE_OF_HALF_PI;
 
-    if (cang <= 0.0)
-        cang = 1.0;
-    else
-        cang = 1.0 + (254.0 * cang);
+    const float fcang =
+        cang <= 0.0
+        ? 1.0f
+        : static_cast<float>(1.0 + (254.0 * cang));
 
-    return (float) cang;
+    return fcang;
 }
 
 static
-void*  GDALCreateHillshadeData(double* adfGeoTransform,
+void* GDALCreateHillshadeData( double* adfGeoTransform,
                                double z,
                                double scale,
                                double alt,
                                double az,
-                               int bZevenbergenThorne)
+                               bool bZevenbergenThorne )
 {
     GDALHillshadeAlgData* pData =
-        (GDALHillshadeAlgData*)CPLMalloc(sizeof(GDALHillshadeAlgData));
+        (GDALHillshadeAlgData*)CPLCalloc(1, sizeof(GDALHillshadeAlgData));
+
+    pData->inv_nsres = 1.0 / adfGeoTransform[5];
+    pData->inv_ewres = 1.0 / adfGeoTransform[1];
+    pData->sin_altRadians = sin(alt * kdfDegreesToRadians);
+    pData->azRadians = az * kdfDegreesToRadians;
+    const double z_scaled = z / ((bZevenbergenThorne ? 2 : 8) * scale);
+    pData->cos_alt_mul_z =
+        cos(alt * kdfDegreesToRadians) * z_scaled;
+    pData->cos_az_mul_cos_alt_mul_z =
+        cos(pData->azRadians) * pData->cos_alt_mul_z;
+    pData->sin_az_mul_cos_alt_mul_z =
+        sin(pData->azRadians) * pData->cos_alt_mul_z;
+    pData->square_z = z_scaled * z_scaled;
+
+    pData->sin_altRadians_mul_254 = 254.0 *
+                                    pData->sin_altRadians;
+    pData->cos_az_mul_cos_alt_mul_z_mul_254 = 254.0 *
+        pData->cos_az_mul_cos_alt_mul_z;
+    pData->sin_az_mul_cos_alt_mul_z_mul_254 = 254.0 *
+        pData->sin_az_mul_cos_alt_mul_z;
+
+    if( adfGeoTransform[1] == -adfGeoTransform[5] )
+    {
+        pData->square_z_mul_square_inv_res =
+          pData->square_z * pData->inv_ewres * pData->inv_ewres;
+        pData->cos_az_mul_cos_alt_mul_z_mul_254_mul_inv_res =
+          pData->cos_az_mul_cos_alt_mul_z_mul_254 * -pData->inv_ewres;
+        pData->sin_az_mul_cos_alt_mul_z_mul_254_mul_inv_res =
+          pData->sin_az_mul_cos_alt_mul_z_mul_254 * pData->inv_ewres;
+    }
+
+    return pData;
+}
+
+/************************************************************************/
+/*                   GDALHillshadeMultiDirectional()                    */
+/************************************************************************/
+
+typedef struct
+{
+    double inv_nsres;
+    double inv_ewres;
+    double square_z;
+    double sin_altRadians_mul_127;
+    double sin_altRadians_mul_254;
+
+    double cos_alt_mul_z_mul_127;
+    double cos225_az_mul_cos_alt_mul_z_mul_127;
+
+} GDALHillshadeMultiDirectionalAlgData;
+
+template<class T, GradientAlg alg>
+static
+float GDALHillshadeMultiDirectionalAlg (const T* afWin,
+                                        float /*fDstNoDataValue*/,
+                                        void* pData)
+{
+    const GDALHillshadeMultiDirectionalAlgData* psData =
+                            (const GDALHillshadeMultiDirectionalAlgData*)pData;
+
+    // First Slope ...
+    double x, y;
+    Gradient<T, alg>::calc(afWin, psData->inv_ewres, psData->inv_nsres, x, y);
+
+    // See http://pubs.usgs.gov/of/1992/of92-422/of92-422.pdf
+    // W225 = sin^2(aspect - 225) = 0.5 * (1 - 2 * sin(aspect) * cos(aspect))
+    // W270 = sin^2(aspect - 270) = cos^2(aspect)
+    // W315 = sin^2(aspect - 315) = 0.5 * (1 + 2 * sin(aspect) * cos(aspect))
+    // W360 = sin^2(aspect - 360) = sin^2(aspect)
+    // hillshade=  0.5 * (W225 * hillshade(az=225) +
+    //                    W270 * hillshade(az=270) +
+    //                    W315 * hillshade(az=315) +
+    //                    W360 * hillshade(az=360))
+
+    const double xx = x * x;
+    const double yy = y * y;
+    const double xx_plus_yy = xx + yy;
+
+    // ... then the shade value from different azimuth
+    double val225_mul_127 = psData->sin_altRadians_mul_127 +
+                            (x-y) * psData->cos225_az_mul_cos_alt_mul_z_mul_127;
+    val225_mul_127 = ( val225_mul_127 <= 0.0) ? 0.0 : val225_mul_127;
+    double val270_mul_127 = psData->sin_altRadians_mul_127 -
+                            x * psData->cos_alt_mul_z_mul_127;
+    val270_mul_127 = ( val270_mul_127 <= 0.0) ? 0.0 : val270_mul_127;
+    double val315_mul_127 = psData->sin_altRadians_mul_127 +
+                            (x+y) * psData->cos225_az_mul_cos_alt_mul_z_mul_127;
+    val315_mul_127 = ( val315_mul_127 <= 0.0) ? 0.0 : val315_mul_127;
+    double val360_mul_127 = psData->sin_altRadians_mul_127 -
+                            y * psData->cos_alt_mul_z_mul_127;
+    val360_mul_127 = ( val360_mul_127 <= 0.0) ? 0.0 : val360_mul_127;
+
+    // ... then the weighted shading
+    const double weight_225 = 0.5 * xx_plus_yy - x * y;
+    const double weight_270 = xx;
+    const double weight_315 = xx_plus_yy - weight_225;
+    const double weight_360 = yy;
+    const double cang_mul_127 = ApproxADivByInvSqrtB(
+                  (weight_225 * val225_mul_127 +
+                   weight_270 * val270_mul_127 +
+                   weight_315 * val315_mul_127 +
+                   weight_360 * val360_mul_127) / xx_plus_yy,
+            1 + psData->square_z * xx_plus_yy);
+
+    const double cang = 1.0 + (
+        (xx_plus_yy == 0.0) ? psData->sin_altRadians_mul_254 : cang_mul_127);
+
+    return static_cast<float>(cang);
+}
+
+static
+void* GDALCreateHillshadeMultiDirectionalData( double* adfGeoTransform,
+                                               double z,
+                                               double scale,
+                                               double alt,
+                                               bool bZevenbergenThorne )
+{
+    GDALHillshadeMultiDirectionalAlgData* pData =
+        (GDALHillshadeMultiDirectionalAlgData*)CPLCalloc(
+                        1, sizeof(GDALHillshadeMultiDirectionalAlgData));
+
+    pData->inv_nsres = 1.0 / adfGeoTransform[5];
+    pData->inv_ewres = 1.0 / adfGeoTransform[1];
+    const double z_scaled = z / ((bZevenbergenThorne ? 2 : 8) * scale);
+    const double cos_alt_mul_z =
+        cos(alt * kdfDegreesToRadians) * z_scaled;
+    pData->square_z = z_scaled * z_scaled;
+
+    pData->sin_altRadians_mul_127 = 127.0 * sin(alt * kdfDegreesToRadians);
+    pData->sin_altRadians_mul_254 = 254.0 * sin(alt * kdfDegreesToRadians);
+    pData->cos_alt_mul_z_mul_127 = 127.0 * cos_alt_mul_z;
+    pData->cos225_az_mul_cos_alt_mul_z_mul_127 = 127.0 *
+        cos(225 * kdfDegreesToRadians) * cos_alt_mul_z;
 
-    const double degreesToRadians = M_PI / 180.0;
-    pData->nsres = adfGeoTransform[5];
-    pData->ewres = adfGeoTransform[1];
-    pData->sin_altRadians = sin(alt * degreesToRadians);
-    pData->azRadians = az * degreesToRadians;
-    double z_scale_factor = z / (((bZevenbergenThorne) ? 2 : 8) * scale);
-    pData->cos_altRadians_mul_z_scale_factor =
-        cos(alt * degreesToRadians) * z_scale_factor;
-    pData->square_z_scale_factor = z_scale_factor * z_scale_factor;
-    pData->square_M_PI_2 = (M_PI*M_PI)/4;
     return pData;
 }
 
@@ -640,50 +1223,50 @@ typedef struct
     int    slopeFormat;
 } GDALSlopeAlgData;
 
+template<class T>
 static
-float GDALSlopeHornAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+float GDALSlopeHornAlg( const T* afWin, float /*fDstNoDataValue*/, void* pData )
 {
-    const double radiansToDegrees = 180.0 / M_PI;
     GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
-    double dx, dy, key;
 
-    dx = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+    const double dx = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
           (afWin[2] + afWin[5] + afWin[5] + afWin[8]))/psData->ewres;
 
-    dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+    const double dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
           (afWin[0] + afWin[1] + afWin[1] + afWin[2]))/psData->nsres;
 
-    key = (dx * dx + dy * dy);
+    const double key = (dx * dx + dy * dy);
 
-    if (psData->slopeFormat == 1)
-        return (float) (atan(sqrt(key) / (8*psData->scale)) * radiansToDegrees);
-    else
-        return (float) (100*(sqrt(key) / (8*psData->scale)));
+    if( psData->slopeFormat == 1 )
+        return static_cast<float>(
+            atan(sqrt(key) / (8*psData->scale)) * kdfRadiansToDegrees);
+
+    return static_cast<float>(100*(sqrt(key) / (8*psData->scale)));
 }
 
+template<class T>
 static
-float GDALSlopeZevenbergenThorneAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, void* pData)
+float GDALSlopeZevenbergenThorneAlg( const T* afWin,
+                                     float /*fDstNoDataValue*/,
+                                     void* pData )
 {
-    const double radiansToDegrees = 180.0 / M_PI;
     GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
-    double dx, dy, key;
-
-    dx = (afWin[3] - afWin[5])/psData->ewres;
 
-    dy = (afWin[7] - afWin[1])/psData->nsres;
+    const double dx = (afWin[3] - afWin[5]) / psData->ewres;
+    const double dy = (afWin[7] - afWin[1]) / psData->nsres;
+    const double key = dx * dx + dy * dy;
 
-    key = (dx * dx + dy * dy);
+    if( psData->slopeFormat == 1 )
+        return static_cast<float>(
+            atan(sqrt(key) / (2*psData->scale)) * kdfRadiansToDegrees);
 
-    if (psData->slopeFormat == 1)
-        return (float) (atan(sqrt(key) / (2*psData->scale)) * radiansToDegrees);
-    else
-        return (float) (100*(sqrt(key) / (2*psData->scale)));
+    return static_cast<float>(100*(sqrt(key) / (2*psData->scale)));
 }
 
 static
-void*  GDALCreateSlopeData(double* adfGeoTransform,
+void* GDALCreateSlopeData( double* adfGeoTransform,
                            double scale,
-                           int slopeFormat)
+                           int slopeFormat )
 {
     GDALSlopeAlgData* pData =
         (GDALSlopeAlgData*)CPLMalloc(sizeof(GDALSlopeAlgData));
@@ -701,89 +1284,83 @@ void*  GDALCreateSlopeData(double* adfGeoTransform,
 
 typedef struct
 {
-    int bAngleAsAzimuth;
+    bool bAngleAsAzimuth;
 } GDALAspectAlgData;
 
+template<class T>
 static
-float GDALAspectAlg (float* afWin, float fDstNoDataValue, void* pData)
+float GDALAspectAlg( const T* afWin, float fDstNoDataValue, void* pData )
 {
-    const double degreesToRadians = M_PI / 180.0;
     GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
-    double dx, dy;
-    float aspect;
 
-    dx = ((afWin[2] + afWin[5] + afWin[5] + afWin[8]) -
+    const double dx = ((afWin[2] + afWin[5] + afWin[5] + afWin[8]) -
           (afWin[0] + afWin[3] + afWin[3] + afWin[6]));
 
-    dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+    const double dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
           (afWin[0] + afWin[1] + afWin[1] + afWin[2]));
 
-    aspect = (float) (atan2(dy,-dx) / degreesToRadians);
+    float aspect = static_cast<float>(atan2(dy,-dx) / kdfDegreesToRadians);
 
-    if (dx == 0 && dy == 0)
+    if( dx == 0 && dy == 0 )
     {
         /* Flat area */
         aspect = fDstNoDataValue;
     }
-    else if ( psData->bAngleAsAzimuth )
+    else if( psData->bAngleAsAzimuth )
     {
-        if (aspect > 90.0)
+        if( aspect > 90.0f )
             aspect = 450.0f - aspect;
         else
             aspect = 90.0f - aspect;
     }
     else
     {
-        if (aspect < 0)
-            aspect += 360.0;
+        if( aspect < 0 )
+            aspect += 360.0f;
     }
 
-    if (aspect == 360.0)
+    if( aspect == 360.0f )
         aspect = 0.0;
 
     return aspect;
 }
 
+template<class T>
 static
-float GDALAspectZevenbergenThorneAlg (float* afWin, float fDstNoDataValue, void* pData)
+float GDALAspectZevenbergenThorneAlg( const T* afWin, float fDstNoDataValue,
+                                      void* pData )
 {
-    const double degreesToRadians = M_PI / 180.0;
     GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
-    double dx, dy;
-    float aspect;
-
-    dx = (afWin[5] - afWin[3]);
-
-    dy = (afWin[7] - afWin[1]);
 
-    aspect = (float) (atan2(dy,-dx) / degreesToRadians);
-
-    if (dx == 0 && dy == 0)
+    const double dx = afWin[5] - afWin[3];
+    const double dy = afWin[7] - afWin[1];
+    float aspect = static_cast<float>(atan2(dy,-dx) / kdfDegreesToRadians);
+    if( dx == 0 && dy == 0 )
     {
         /* Flat area */
         aspect = fDstNoDataValue;
     }
-    else if ( psData->bAngleAsAzimuth )
+    else if( psData->bAngleAsAzimuth )
     {
-        if (aspect > 90.0)
+        if( aspect > 90.0f )
             aspect = 450.0f - aspect;
         else
             aspect = 90.0f - aspect;
     }
     else
     {
-        if (aspect < 0)
-            aspect += 360.0;
+        if( aspect < 0 )
+            aspect += 360.0f;
     }
 
-    if (aspect == 360.0)
+    if( aspect == 360.0f )
         aspect = 0.0;
 
     return aspect;
 }
 
 static
-void*  GDALCreateAspectData(int bAngleAsAzimuth)
+void *GDALCreateAspectData( bool bAngleAsAzimuth )
 {
     GDALAspectAlgData* pData =
         (GDALAspectAlgData*)CPLMalloc(sizeof(GDALAspectAlgData));
@@ -826,18 +1403,18 @@ static void GDALColorReliefProcessColors(ColorAssociation **ppasColorAssociation
             (nColorAssociation > 0) ? &pasColorAssociation[0] : NULL;
     int nAdded = 0;
     int nRepeatedEntryIndex = 0;
-    for (int i = 1; i < nColorAssociation; ++i)
+    for( int i = 1; i < nColorAssociation; ++i )
     {
         ColorAssociation *pCurrent = &pasColorAssociation[i];
 
         // NaN comparison is always false, so it handles itself
-        if (bSrcHasNoData && pCurrent->dfVal == dfSrcNoDataValue)
+        if( bSrcHasNoData && pCurrent->dfVal == dfSrcNoDataValue )
         {
-            // check if there is enough distance between the nodata value and its
-            // predecessor
-            double dfNewValue =
-                    pCurrent->dfVal - ABS(pCurrent->dfVal) * DBL_EPSILON;
-            if (dfNewValue > pPrevious->dfVal)
+            // Check if there is enough distance between the nodata value and
+            // its predecessor.
+            const double dfNewValue =
+                pCurrent->dfVal - std::abs(pCurrent->dfVal) * DBL_EPSILON;
+            if( dfNewValue > pPrevious->dfVal )
             {
                 // add one just below the nodata value
                 ++nAdded;
@@ -850,12 +1427,13 @@ static void GDALColorReliefProcessColors(ColorAssociation **ppasColorAssociation
                 pasColorAssociation[nColorAssociation + nAdded - 1].dfVal = dfNewValue;
             }
         }
-        else if (bSrcHasNoData && pPrevious->dfVal == dfSrcNoDataValue)
+        else if( bSrcHasNoData && pPrevious->dfVal == dfSrcNoDataValue )
         {
-            // check if there is enough distance between the nodata value and its
-            // successor
-            double dfNewValue = pPrevious->dfVal + ABS(pPrevious->dfVal) * DBL_EPSILON;
-            if (dfNewValue < pCurrent->dfVal)
+            // Check if there is enough distance between the nodata value and
+            // its successor.
+            const double dfNewValue =
+                pPrevious->dfVal + std::abs(pPrevious->dfVal) * DBL_EPSILON;
+            if( dfNewValue < pCurrent->dfVal )
             {
                 // add one just above the nodata value
                 ++nAdded;
@@ -868,44 +1446,51 @@ static void GDALColorReliefProcessColors(ColorAssociation **ppasColorAssociation
                 pasColorAssociation[nColorAssociation + nAdded - 1].dfVal = dfNewValue;
             }
         }
-        else if (nRepeatedEntryIndex == 0 && pCurrent->dfVal == pPrevious->dfVal)
+        else if( nRepeatedEntryIndex == 0 &&
+                 pCurrent->dfVal == pPrevious->dfVal )
         {
             // second of a series of equivalent entries
             nRepeatedEntryIndex = i;
         }
-        else if (nRepeatedEntryIndex != 0 && pCurrent->dfVal != pPrevious->dfVal)
+        else if( nRepeatedEntryIndex != 0 &&
+                 pCurrent->dfVal != pPrevious->dfVal )
         {
-            // get the distance between the predecessor and successor of the equivalent
-            // entries
-            double dfTotalDist, dfLeftDist;
-            if (nRepeatedEntryIndex >= 2)
+            // Get the distance between the predecessor and successor of the
+            // equivalent entries.
+            double dfTotalDist = 0.0;
+            double dfLeftDist = 0.0;
+            if( nRepeatedEntryIndex >= 2 )
             {
-                ColorAssociation *pLower = &pasColorAssociation[nRepeatedEntryIndex - 2];
+                ColorAssociation *pLower =
+                    &pasColorAssociation[nRepeatedEntryIndex - 2];
                 dfTotalDist = pCurrent->dfVal - pLower->dfVal;
                 dfLeftDist = pPrevious->dfVal - pLower->dfVal;
             }
             else
             {
                 dfTotalDist = pCurrent->dfVal - pPrevious->dfVal;
-                dfLeftDist = 0;
             }
 
             // check if this distance is enough
-            int nEquivalentCount = i - nRepeatedEntryIndex + 1;
-            if (dfTotalDist > ABS(pPrevious->dfVal) * nEquivalentCount * DBL_EPSILON)
+            const int nEquivalentCount = i - nRepeatedEntryIndex + 1;
+            if( dfTotalDist >
+                std::abs(pPrevious->dfVal) * nEquivalentCount * DBL_EPSILON )
             {
                 // balance the alterations
-                double dfMultiplier = 0.5 - nEquivalentCount * dfLeftDist / dfTotalDist;
-                for (int j = nRepeatedEntryIndex - 1; j < i; ++j)
+                double dfMultiplier =
+                    0.5 - nEquivalentCount * dfLeftDist / dfTotalDist;
+                for( int j = nRepeatedEntryIndex - 1; j < i; ++j )
                 {
                     pasColorAssociation[j].dfVal +=
-                            (ABS(pPrevious->dfVal) * dfMultiplier) * DBL_EPSILON;
+                        (std::abs(pPrevious->dfVal) * dfMultiplier) *
+                        DBL_EPSILON;
                     dfMultiplier += 1.0;
                 }
             }
             else
             {
-                // fallback to the old behaviour: keep equivalent entries as they are
+                // Fallback to the old behaviour: keep equivalent entries as
+                // they are.
             }
 
             nRepeatedEntryIndex = 0;
@@ -913,7 +1498,7 @@ static void GDALColorReliefProcessColors(ColorAssociation **ppasColorAssociation
         pPrevious = pCurrent;
     }
 
-    if (nAdded)
+    if( nAdded )
     {
         std::stable_sort(pasColorAssociation,
                          pasColorAssociation + nColorAssociation + nAdded,
@@ -923,19 +1508,16 @@ static void GDALColorReliefProcessColors(ColorAssociation **ppasColorAssociation
     }
 }
 
-static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
-                                   int nColorAssociation,
-                                   double dfVal,
-                                   ColorSelectionMode eColorSelectionMode,
-                                   int* pnR,
-                                   int* pnG,
-                                   int* pnB,
-                                   int* pnA)
+static bool GDALColorReliefGetRGBA( ColorAssociation* pasColorAssociation,
+                                    int nColorAssociation,
+                                    double dfVal,
+                                    ColorSelectionMode eColorSelectionMode,
+                                    int* pnR,
+                                    int* pnG,
+                                    int* pnB,
+                                    int* pnA)
 {
-    int i;
     int lower = 0;
-    int upper = nColorAssociation - 1;
-    int mid;
 
     // Special case for NaN
     if( CPLIsNan(pasColorAssociation[0].dfVal) )
@@ -946,28 +1528,32 @@ static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
             *pnG = pasColorAssociation[0].nG;
             *pnB = pasColorAssociation[0].nB;
             *pnA = pasColorAssociation[0].nA;
-            return TRUE;
+            return true;
         }
         else
+        {
             lower = 1;
+        }
     }
 
-    /* Find the index of the first element in the LUT input array that */
-    /* is not smaller than the dfVal value. */
+    // Find the index of the first element in the LUT input array that
+    // is not smaller than the dfVal value.
+    int i = 0;
+    int upper = nColorAssociation - 1;
     while( true )
     {
-        mid = (lower + upper) / 2;
-        if (upper - lower <= 1)
+        const int mid = (lower + upper) / 2;
+        if( upper - lower <= 1 )
         {
-            if (dfVal <= pasColorAssociation[lower].dfVal)
+            if( dfVal <= pasColorAssociation[lower].dfVal )
                 i = lower;
-            else if (dfVal <= pasColorAssociation[upper].dfVal)
+            else if( dfVal <= pasColorAssociation[upper].dfVal )
                 i = upper;
             else
                 i = upper + 1;
             break;
         }
-        else if (pasColorAssociation[mid].dfVal >= dfVal)
+        else if( pasColorAssociation[mid].dfVal >= dfVal )
         {
             upper = mid;
         }
@@ -977,16 +1563,16 @@ static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
         }
     }
 
-    if (i == 0)
+    if( i == 0 )
     {
-        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
-            pasColorAssociation[0].dfVal != dfVal)
+        if( eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
+            pasColorAssociation[0].dfVal != dfVal )
         {
             *pnR = 0;
             *pnG = 0;
             *pnB = 0;
             *pnA = 0;
-            return FALSE;
+            return false;
         }
         else
         {
@@ -994,19 +1580,19 @@ static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
             *pnG = pasColorAssociation[0].nG;
             *pnB = pasColorAssociation[0].nB;
             *pnA = pasColorAssociation[0].nA;
-            return TRUE;
+            return true;
         }
     }
-    else if (i == nColorAssociation)
+    else if( i == nColorAssociation )
     {
-        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
-            pasColorAssociation[i-1].dfVal != dfVal)
+        if( eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
+            pasColorAssociation[i-1].dfVal != dfVal )
         {
             *pnR = 0;
             *pnG = 0;
             *pnB = 0;
             *pnA = 0;
-            return FALSE;
+            return false;
         }
         else
         {
@@ -1014,81 +1600,87 @@ static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
             *pnG = pasColorAssociation[i-1].nG;
             *pnB = pasColorAssociation[i-1].nB;
             *pnA = pasColorAssociation[i-1].nA;
-            return TRUE;
+            return true;
         }
     }
     else
     {
-        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
-            pasColorAssociation[i-1].dfVal != dfVal)
+        if( eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
+            pasColorAssociation[i-1].dfVal != dfVal )
         {
             *pnR = 0;
             *pnG = 0;
             *pnB = 0;
             *pnA = 0;
-            return FALSE;
+            return false;
         }
 
-        if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY &&
-            pasColorAssociation[i-1].dfVal != dfVal)
+        if( eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY &&
+            pasColorAssociation[i-1].dfVal != dfVal )
         {
-            int index;
-            if (dfVal - pasColorAssociation[i-1].dfVal <
-                pasColorAssociation[i].dfVal - dfVal)
-                index = i -1;
-            else
-                index = i;
+            int index = i;
+            if( dfVal - pasColorAssociation[i-1].dfVal <
+                pasColorAssociation[i].dfVal - dfVal )
+            {
+                --index;
+            }
 
             *pnR = pasColorAssociation[index].nR;
             *pnG = pasColorAssociation[index].nG;
             *pnB = pasColorAssociation[index].nB;
             *pnA = pasColorAssociation[index].nA;
-            return TRUE;
+            return true;
         }
 
-        if (pasColorAssociation[i-1].dfVal == dfVal)
+        if( pasColorAssociation[i-1].dfVal == dfVal )
         {
             *pnR = pasColorAssociation[i-1].nR;
             *pnG = pasColorAssociation[i-1].nG;
             *pnB = pasColorAssociation[i-1].nB;
             *pnA = pasColorAssociation[i-1].nA;
-            return TRUE;
+            return true;
         }
 
-        double dfRatio = (dfVal - pasColorAssociation[i-1].dfVal) /
+        const double dfRatio =
+            (dfVal - pasColorAssociation[i-1].dfVal) /
             (pasColorAssociation[i].dfVal - pasColorAssociation[i-1].dfVal);
-        *pnR = (int)(0.45 + pasColorAssociation[i-1].nR + dfRatio *
-                (pasColorAssociation[i].nR - pasColorAssociation[i-1].nR));
-        if (*pnR < 0) *pnR = 0;
-        else if (*pnR > 255) *pnR = 255;
-        *pnG = (int)(0.45 + pasColorAssociation[i-1].nG + dfRatio *
-                (pasColorAssociation[i].nG - pasColorAssociation[i-1].nG));
-        if (*pnG < 0) *pnG = 0;
-        else if (*pnG > 255) *pnG = 255;
-        *pnB = (int)(0.45 + pasColorAssociation[i-1].nB + dfRatio *
-                (pasColorAssociation[i].nB - pasColorAssociation[i-1].nB));
-        if (*pnB < 0) *pnB = 0;
-        else if (*pnB > 255) *pnB = 255;
-        *pnA = (int)(0.45 + pasColorAssociation[i-1].nA + dfRatio *
-                (pasColorAssociation[i].nA - pasColorAssociation[i-1].nA));
-        if (*pnA < 0) *pnA = 0;
-        else if (*pnA > 255) *pnA = 255;
-
-        return TRUE;
+        *pnR = static_cast<int>(
+            0.45 + pasColorAssociation[i-1].nR + dfRatio *
+            (pasColorAssociation[i].nR - pasColorAssociation[i-1].nR));
+        if( *pnR < 0 ) *pnR = 0;
+        else if( *pnR > 255 ) *pnR = 255;
+        *pnG = static_cast<int>(
+            0.45 + pasColorAssociation[i-1].nG + dfRatio *
+            (pasColorAssociation[i].nG - pasColorAssociation[i-1].nG));
+        if( *pnG < 0 ) *pnG = 0;
+        else if( *pnG > 255 ) *pnG = 255;
+        *pnB = static_cast<int>(
+            0.45 + pasColorAssociation[i-1].nB + dfRatio *
+            (pasColorAssociation[i].nB - pasColorAssociation[i-1].nB));
+        if( *pnB < 0 ) *pnB = 0;
+        else if( *pnB > 255 ) *pnB = 255;
+        *pnA = static_cast<int>(
+            0.45 + pasColorAssociation[i-1].nA + dfRatio *
+            (pasColorAssociation[i].nA - pasColorAssociation[i-1].nA));
+        if( *pnA < 0 ) *pnA = 0;
+        else if( *pnA > 255 ) *pnA = 255;
+
+        return true;
     }
 }
 
 /* dfPct : percentage between 0 and 1 */
-static double GDALColorReliefGetAbsoluteValFromPct(GDALRasterBandH hSrcBand,
-                                                   double dfPct)
+static double GDALColorReliefGetAbsoluteValFromPct( GDALRasterBandH hSrcBand,
+                                                    double dfPct )
 {
-    double dfMin, dfMax;
-    int bSuccessMin, bSuccessMax;
-    dfMin = GDALGetRasterMinimum(hSrcBand, &bSuccessMin);
-    dfMax = GDALGetRasterMaximum(hSrcBand, &bSuccessMax);
-    if (!bSuccessMin || !bSuccessMax)
-    {
-        double dfMean, dfStdDev;
+    int bSuccessMin = FALSE;
+    int bSuccessMax = FALSE;
+    double dfMin = GDALGetRasterMinimum(hSrcBand, &bSuccessMin);
+    double dfMax = GDALGetRasterMaximum(hSrcBand, &bSuccessMax);
+    if( !bSuccessMin || !bSuccessMax )
+    {
+        double dfMean = 0.0;
+        double dfStdDev = 0.0;
         fprintf(stderr, "Computing source raster statistics...\n");
         GDALComputeRasterStatistics(hSrcBand, FALSE, &dfMin, &dfMax,
                                     &dfMean, &dfStdDev, NULL, NULL);
@@ -1122,33 +1714,37 @@ static const NamedColor namedColors[] = {
 };
 
 static
-int GDALColorReliefFindNamedColor(const char *pszColorName, int *pnR, int *pnG, int *pnB)
+bool GDALColorReliefFindNamedColor( const char *pszColorName,
+                                    int *pnR, int *pnG, int *pnB )
 {
-    unsigned int i;
-
-    *pnR = *pnG = *pnB = 0;
-    for (i = 0; i < sizeof(namedColors) / sizeof(namedColors[0]); i++)
+    *pnR = 0;
+    *pnG = 0;
+    *pnB = 0;
+    for( unsigned int i = 0;
+         i < sizeof(namedColors) / sizeof(namedColors[0]);
+         i++ )
     {
-        if (EQUAL(pszColorName, namedColors[i].name))
+        if( EQUAL(pszColorName, namedColors[i].name) )
         {
-            *pnR = (int)(255. * namedColors[i].r);
-            *pnG = (int)(255. * namedColors[i].g);
-            *pnB = (int)(255. * namedColors[i].b);
-            return TRUE;
+            *pnR = static_cast<int>(255.0 * namedColors[i].r);
+            *pnG = static_cast<int>(255.0 * namedColors[i].g);
+            *pnB = static_cast<int>(255.0 * namedColors[i].b);
+            return true;
         }
     }
-    return FALSE;
+    return false;
 }
 
 static
-ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
-                                                const char* pszColorFilename,
-                                                int* pnColors)
+ColorAssociation* GDALColorReliefParseColorFile( GDALRasterBandH hSrcBand,
+                                                 const char* pszColorFilename,
+                                                 int* pnColors )
 {
     VSILFILE* fpColorFile = VSIFOpenL(pszColorFilename, "rt");
-    if (fpColorFile == NULL)
+    if( fpColorFile == NULL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", pszColorFilename);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find %s", pszColorFilename);
         *pnColors = 0;
         return NULL;
     }
@@ -1159,34 +1755,35 @@ ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
     int bSrcHasNoData = FALSE;
     double dfSrcNoDataValue = GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
 
-    const char* pszLine;
-    int bIsGMT_CPT = FALSE;
-    while ((pszLine = CPLReadLineL(fpColorFile)) != NULL)
+    const char* pszLine = NULL;
+    bool bIsGMT_CPT = false;
+    while( (pszLine = CPLReadLineL(fpColorFile)) != NULL )
     {
-        if (pszLine[0] == '#' && strstr(pszLine, "COLOR_MODEL"))
+        if( pszLine[0] == '#' && strstr(pszLine, "COLOR_MODEL") )
         {
-            if (strstr(pszLine, "COLOR_MODEL = RGB") == NULL)
+            if( strstr(pszLine, "COLOR_MODEL = RGB") == NULL )
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "Only COLOR_MODEL = RGB is supported");
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Only COLOR_MODEL = RGB is supported");
                 CPLFree(pasColorAssociation);
                 *pnColors = 0;
                 return NULL;
             }
-            bIsGMT_CPT = TRUE;
+            bIsGMT_CPT = true;
         }
 
         char** papszFields = CSLTokenizeStringComplex(pszLine, " ,\t:",
                                                       FALSE, FALSE );
         /* Skip comment lines */
-        int nTokens = CSLCount(papszFields);
-        if (nTokens >= 1 && (papszFields[0][0] == '#' ||
-                             papszFields[0][0] == '/'))
+        const int nTokens = CSLCount(papszFields);
+        if( nTokens >= 1 && (papszFields[0][0] == '#' ||
+                             papszFields[0][0] == '/') )
         {
             CSLDestroy(papszFields);
             continue;
         }
 
-        if (bIsGMT_CPT && nTokens == 8)
+        if( bIsGMT_CPT && nTokens == 8 )
         {
             pasColorAssociation =
                     (ColorAssociation*)CPLRealloc(pasColorAssociation,
@@ -1206,13 +1803,13 @@ ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
             pasColorAssociation[nColorAssociation].nA = 255;
             nColorAssociation++;
         }
-        else if (bIsGMT_CPT && nTokens == 4)
+        else if( bIsGMT_CPT && nTokens == 4 )
         {
-            /* The first token might be B (background), F (foreground) or N (nodata) */
-            /* Just interested in N */
-            if (EQUAL(papszFields[0], "N") && bSrcHasNoData)
+            // The first token might be B (background), F (foreground) or N
+            // (nodata) Just interested in N.
+            if( EQUAL(papszFields[0], "N") && bSrcHasNoData )
             {
-                 pasColorAssociation =
+                pasColorAssociation =
                     (ColorAssociation*)CPLRealloc(pasColorAssociation,
                            (nColorAssociation + 1) * sizeof(ColorAssociation));
 
@@ -1224,17 +1821,20 @@ ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
                 nColorAssociation++;
             }
         }
-        else if (!bIsGMT_CPT && nTokens >= 2)
+        else if( !bIsGMT_CPT && nTokens >= 2 )
         {
             pasColorAssociation =
                     (ColorAssociation*)CPLRealloc(pasColorAssociation,
                            (nColorAssociation + 1) * sizeof(ColorAssociation));
-            if (EQUAL(papszFields[0], "nv") && bSrcHasNoData)
+            if( EQUAL(papszFields[0], "nv") && bSrcHasNoData )
+            {
                 pasColorAssociation[nColorAssociation].dfVal = dfSrcNoDataValue;
-            else if (strlen(papszFields[0]) > 1 && papszFields[0][strlen(papszFields[0])-1] == '%')
+            }
+            else if( strlen(papszFields[0]) > 1 &&
+                     papszFields[0][strlen(papszFields[0])-1] == '%' )
             {
-                double dfPct = CPLAtof(papszFields[0]) / 100.;
-                if (dfPct < 0.0 || dfPct > 1.0)
+                const double dfPct = CPLAtof(papszFields[0]) / 100.0;
+                if( dfPct < 0.0 || dfPct > 1.0 )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
                              "Wrong value for a percentage : %s", papszFields[0]);
@@ -1245,12 +1845,14 @@ ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
                     return NULL;
                 }
                 pasColorAssociation[nColorAssociation].dfVal =
-                        GDALColorReliefGetAbsoluteValFromPct(hSrcBand, dfPct);
+                    GDALColorReliefGetAbsoluteValFromPct(hSrcBand, dfPct);
             }
             else
+            {
                 pasColorAssociation[nColorAssociation].dfVal = CPLAtof(papszFields[0]);
+            }
 
-            if (nTokens >= 4)
+            if( nTokens >= 4 )
             {
                 pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
                 pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
@@ -1260,8 +1862,11 @@ ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
             }
             else
             {
-                int nR, nG, nB;
-                if (!GDALColorReliefFindNamedColor(papszFields[1], &nR, &nG, &nB))
+                int nR = 0;
+                int nG = 0;
+                int nB = 0;
+                if( !GDALColorReliefFindNamedColor(papszFields[1],
+                                                   &nR, &nG, &nB) )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
                              "Unknown color : %s", papszFields[1]);
@@ -1274,17 +1879,17 @@ ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
                 pasColorAssociation[nColorAssociation].nR = nR;
                 pasColorAssociation[nColorAssociation].nG = nG;
                 pasColorAssociation[nColorAssociation].nB = nB;
-                            pasColorAssociation[nColorAssociation].nA =
+                pasColorAssociation[nColorAssociation].nA =
                     (CSLCount(papszFields) >= 3 ) ? atoi(papszFields[2]) : 255;
             }
 
-            nColorAssociation ++;
+            nColorAssociation++;
         }
         CSLDestroy(papszFields);
     }
     VSIFCloseL(fpColorFile);
 
-    if (nColorAssociation == 0)
+    if( nColorAssociation == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "No color association found in %s", pszColorFilename);
@@ -1306,23 +1911,25 @@ GByte* GDALColorReliefPrecompute(GDALRasterBandH hSrcBand,
                                  ColorSelectionMode eColorSelectionMode,
                                  int* pnIndexOffset)
 {
-    GDALDataType eDT = GDALGetRasterDataType(hSrcBand);
+    const GDALDataType eDT = GDALGetRasterDataType(hSrcBand);
     GByte* pabyPrecomputed = NULL;
-    int nIndexOffset = (eDT == GDT_Int16) ? 32768 : 0;
+    const int nIndexOffset = (eDT == GDT_Int16) ? 32768 : 0;
     *pnIndexOffset = nIndexOffset;
-    int nXSize = GDALGetRasterBandXSize(hSrcBand);
-    int nYSize = GDALGetRasterBandXSize(hSrcBand);
-    if (eDT == GDT_Byte ||
-        ((eDT == GDT_Int16 || eDT == GDT_UInt16) && nXSize * nYSize > 65536))
+    const int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    const int nYSize = GDALGetRasterBandXSize(hSrcBand);
+    if( eDT == GDT_Byte ||
+        ((eDT == GDT_Int16 || eDT == GDT_UInt16) && nXSize * nYSize > 65536) )
     {
-        int iMax = (eDT == GDT_Byte) ? 256: 65536;
+        const int iMax = (eDT == GDT_Byte) ? 256: 65536;
         pabyPrecomputed = (GByte*) VSI_MALLOC2_VERBOSE(4, iMax);
-        if (pabyPrecomputed)
+        if( pabyPrecomputed )
         {
-            int i;
-            for(i=0;i<iMax;i++)
+            for( int i = 0; i < iMax; i++ )
             {
-                int nR, nG, nB, nA;
+                int nR = 0;
+                int nG = 0;
+                int nB = 0;
+                int nA = 0;
                 GDALColorReliefGetRGBA  (pasColorAssociation,
                                          nColorAssociation,
                                          i - nIndexOffset,
@@ -1363,17 +1970,19 @@ class GDALColorReliefDataset : public GDALDataset
     int                nCurBlockYOff;
 
   public:
-                        GDALColorReliefDataset(GDALDatasetH hSrcDS,
-                                            GDALRasterBandH hSrcBand,
-                                            const char* pszColorFilename,
-                                            ColorSelectionMode eColorSelectionMode,
-                                            int bAlpha);
+                        GDALColorReliefDataset(
+                            GDALDatasetH hSrcDS,
+                            GDALRasterBandH hSrcBand,
+                            const char* pszColorFilename,
+                            ColorSelectionMode eColorSelectionMode,
+                            int bAlpha);
                        ~GDALColorReliefDataset();
 
-    bool                InitOK() const { return pafSourceBuf != NULL || panSourceBuf != NULL; }
+    bool        InitOK() const
+        { return pafSourceBuf != NULL || panSourceBuf != NULL; }
 
-    CPLErr      GetGeoTransform( double * padfGeoTransform );
-    const char *GetProjectionRef();
+    CPLErr      GetGeoTransform( double * padfGeoTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
 /************************************************************************/
@@ -1386,36 +1995,42 @@ class GDALColorReliefRasterBand : public GDALRasterBand
 {
     friend class GDALColorReliefDataset;
 
-
   public:
                  GDALColorReliefRasterBand( GDALColorReliefDataset *, int );
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
 GDALColorReliefDataset::GDALColorReliefDataset(
-                                     GDALDatasetH hSrcDSIn,
-                                     GDALRasterBandH hSrcBandIn,
-                                     const char* pszColorFilename,
-                                     ColorSelectionMode eColorSelectionModeIn,
-                                     int bAlpha)
-{
-    hSrcDS = hSrcDSIn;
-    hSrcBand = hSrcBandIn;
-    nColorAssociation = 0;
+    GDALDatasetH hSrcDSIn,
+    GDALRasterBandH hSrcBandIn,
+    const char* pszColorFilename,
+    ColorSelectionMode eColorSelectionModeIn,
+    int bAlpha ) :
+    hSrcDS(hSrcDSIn),
+    hSrcBand(hSrcBandIn),
+    nColorAssociation(0),
+    pasColorAssociation(NULL),
+    eColorSelectionMode(eColorSelectionModeIn),
+    pabyPrecomputed(NULL),
+    nIndexOffset(0),
+    pafSourceBuf(NULL),
+    panSourceBuf(NULL),
+    nCurBlockXOff(-1),
+    nCurBlockYOff(-1)
+{
     pasColorAssociation =
             GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
                                           &nColorAssociation);
-    eColorSelectionMode = eColorSelectionModeIn;
 
     nRasterXSize = GDALGetRasterXSize(hSrcDS);
     nRasterYSize = GDALGetRasterYSize(hSrcDS);
 
-    int nBlockXSize, nBlockYSize;
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
     GDALGetBlockSize( hSrcBand, &nBlockXSize, &nBlockYSize);
 
-    nIndexOffset = 0;
     pabyPrecomputed =
         GDALColorReliefPrecompute(hSrcBand,
                                   pasColorAssociation,
@@ -1423,20 +2038,17 @@ GDALColorReliefDataset::GDALColorReliefDataset(
                                   eColorSelectionMode,
                                   &nIndexOffset);
 
-    int i;
-    for(i=0;i<((bAlpha) ? 4 : 3);i++)
+    for( int i = 0; i < ((bAlpha) ? 4 : 3); i++ )
     {
         SetBand(i + 1, new GDALColorReliefRasterBand(this, i+1));
     }
 
-    pafSourceBuf = NULL;
-    panSourceBuf = NULL;
-    if (pabyPrecomputed)
-        panSourceBuf = (int *) VSI_MALLOC3_VERBOSE(sizeof(int),nBlockXSize,nBlockYSize);
+    if( pabyPrecomputed )
+        panSourceBuf = static_cast<int *>(
+            VSI_MALLOC3_VERBOSE(sizeof(int), nBlockXSize, nBlockYSize));
     else
-        pafSourceBuf = (float *) VSI_MALLOC3_VERBOSE(sizeof(float),nBlockXSize,nBlockYSize);
-    nCurBlockXOff = -1;
-    nCurBlockYOff = -1;
+        pafSourceBuf = static_cast<float *>(
+            VSI_MALLOC3_VERBOSE(sizeof(float), nBlockXSize, nBlockYSize));
 }
 
 GDALColorReliefDataset::~GDALColorReliefDataset()
@@ -1458,7 +2070,7 @@ const char *GDALColorReliefDataset::GetProjectionRef()
 }
 
 GDALColorReliefRasterBand::GDALColorReliefRasterBand(
-                                    GDALColorReliefDataset * poDSIn, int nBandIn)
+    GDALColorReliefDataset * poDSIn, int nBandIn)
 {
     poDS = poDSIn;
     nBand = nBandIn;
@@ -1471,61 +2083,61 @@ CPLErr GDALColorReliefRasterBand::IReadBlock( int nBlockXOff,
                                               void *pImage )
 {
     GDALColorReliefDataset * poGDS = (GDALColorReliefDataset *) poDS;
-    int nReqXSize, nReqYSize;
+    const int nReqXSize =
+        (nBlockXOff + 1) * nBlockXSize >= nRasterXSize
+        ? nRasterXSize - nBlockXOff * nBlockXSize
+        : nBlockXSize;
 
-    if ((nBlockXOff + 1) * nBlockXSize >= nRasterXSize)
-        nReqXSize = nRasterXSize - nBlockXOff * nBlockXSize;
-    else
-        nReqXSize = nBlockXSize;
-
-    if ((nBlockYOff + 1) * nBlockYSize >= nRasterYSize)
-        nReqYSize = nRasterYSize - nBlockYOff * nBlockYSize;
-    else
-        nReqYSize = nBlockYSize;
+    const int nReqYSize =
+        (nBlockYOff + 1) * nBlockYSize >= nRasterYSize
+        ? nRasterYSize - nBlockYOff * nBlockYSize
+        : nBlockYSize;
 
-    if ( poGDS->nCurBlockXOff != nBlockXOff ||
-         poGDS->nCurBlockYOff != nBlockYOff )
+    if( poGDS->nCurBlockXOff != nBlockXOff ||
+        poGDS->nCurBlockYOff != nBlockYOff )
     {
         poGDS->nCurBlockXOff = nBlockXOff;
         poGDS->nCurBlockYOff = nBlockYOff;
 
-        CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
-                            GF_Read,
-                            nBlockXOff * nBlockXSize,
-                            nBlockYOff * nBlockYSize,
-                            nReqXSize, nReqYSize,
-                            (poGDS->panSourceBuf) ?
-                                (void*) poGDS->panSourceBuf :
-                                (void* )poGDS->pafSourceBuf,
-                            nReqXSize, nReqYSize,
-                            (poGDS->panSourceBuf) ? GDT_Int32 : GDT_Float32,
-                            0, 0);
-        if (eErr != CE_None)
+        const CPLErr eErr =
+            GDALRasterIO( poGDS->hSrcBand,
+                          GF_Read,
+                          nBlockXOff * nBlockXSize,
+                          nBlockYOff * nBlockYSize,
+                          nReqXSize, nReqYSize,
+                          (poGDS->panSourceBuf) ?
+                          (void*) poGDS->panSourceBuf :
+                          (void* )poGDS->pafSourceBuf,
+                          nReqXSize, nReqYSize,
+                          (poGDS->panSourceBuf) ? GDT_Int32 : GDT_Float32,
+                          0, 0);
+        if( eErr != CE_None )
         {
             memset(pImage, 0, nBlockXSize * nBlockYSize);
             return eErr;
         }
     }
 
-    int x, y, j = 0;
-    if (poGDS->panSourceBuf)
+    int j = 0;
+    if( poGDS->panSourceBuf )
     {
-        for( y = 0; y < nReqYSize; y++ )
+        for( int y = 0; y < nReqYSize; y++ )
         {
-            for( x = 0; x < nReqXSize; x++ )
+            for( int x = 0; x < nReqXSize; x++ )
             {
-                int nIndex = poGDS->panSourceBuf[j] + poGDS->nIndexOffset;
-                ((GByte*)pImage)[y * nBlockXSize + x] = poGDS->pabyPrecomputed[4*nIndex + nBand-1];
+                const int nIndex = poGDS->panSourceBuf[j] + poGDS->nIndexOffset;
+                ((GByte*)pImage)[y * nBlockXSize + x] =
+                    poGDS->pabyPrecomputed[4*nIndex + nBand-1];
                 j++;
             }
         }
     }
     else
     {
-        int anComponents[4];
-        for( y = 0; y < nReqYSize; y++ )
+        int anComponents[4] = { 0, 0, 0, 0 };
+        for( int y = 0; y < nReqYSize; y++ )
         {
-            for( x = 0; x < nReqXSize; x++ )
+            for( int x = 0; x < nReqXSize; x++ )
             {
                 GDALColorReliefGetRGBA  (poGDS->pasColorAssociation,
                                         poGDS->nColorAssociation,
@@ -1535,7 +2147,8 @@ CPLErr GDALColorReliefRasterBand::IReadBlock( int nBlockXOff,
                                         &anComponents[1],
                                         &anComponents[2],
                                         &anComponents[3]);
-                ((GByte*)pImage)[y * nBlockXSize + x] = (GByte) anComponents[nBand-1];
+                ((GByte*)pImage)[y * nBlockXSize + x] =
+                    (GByte) anComponents[nBand-1];
                 j++;
             }
         }
@@ -1549,9 +2162,8 @@ GDALColorInterp GDALColorReliefRasterBand::GetColorInterpretation()
     return (GDALColorInterp)(GCI_RedBand + nBand - 1);
 }
 
-
 static
-CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
+CPLErr GDALColorRelief( GDALRasterBandH hSrcBand,
                         GDALRasterBandH hDstBand1,
                         GDALRasterBandH hDstBand2,
                         GDALRasterBandH hDstBand3,
@@ -1559,29 +2171,22 @@ CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
                         const char* pszColorFilename,
                         ColorSelectionMode eColorSelectionMode,
                         GDALProgressFunc pfnProgress,
-                        void * pProgressData)
+                        void * pProgressData )
 {
-    CPLErr eErr;
-
-    if (hSrcBand == NULL || hDstBand1 == NULL || hDstBand2 == NULL ||
-        hDstBand3 == NULL)
+    if( hSrcBand == NULL || hDstBand1 == NULL || hDstBand2 == NULL ||
+        hDstBand3 == NULL )
         return CE_Failure;
 
     int nColorAssociation = 0;
     ColorAssociation* pasColorAssociation =
-            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
-                                          &nColorAssociation);
-    if (pasColorAssociation == NULL)
+        GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
+                                      &nColorAssociation);
+    if( pasColorAssociation == NULL )
         return CE_Failure;
 
-    int nXSize = GDALGetRasterBandXSize(hSrcBand);
-    int nYSize = GDALGetRasterBandYSize(hSrcBand);
-
-    if (pfnProgress == NULL)
+    if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
-    int nR = 0, nG = 0, nB = 0, nA = 0;
-
 /* -------------------------------------------------------------------- */
 /*      Precompute the map from values to RGBA quadruplets              */
 /*      for GDT_Byte, GDT_Int16 or GDT_UInt16                           */
@@ -1598,50 +2203,78 @@ CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
 /*      Initialize progress counter.                                    */
 /* -------------------------------------------------------------------- */
 
+    const int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    const int nYSize = GDALGetRasterBandYSize(hSrcBand);
+
     float* pafSourceBuf = NULL;
     int* panSourceBuf = NULL;
-    if (pabyPrecomputed)
-        panSourceBuf = (int *) VSI_MALLOC2_VERBOSE(sizeof(int),nXSize);
+    if( pabyPrecomputed )
+        panSourceBuf = static_cast<int *>(
+            VSI_MALLOC2_VERBOSE(sizeof(int), nXSize));
     else
-        pafSourceBuf = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nXSize);
-    GByte* pabyDestBuf1  = (GByte*) VSI_MALLOC2_VERBOSE(4, nXSize );
-    GByte* pabyDestBuf2  =  pabyDestBuf1 + nXSize;
-    GByte* pabyDestBuf3  =  pabyDestBuf2 + nXSize;
-    GByte* pabyDestBuf4  =  pabyDestBuf3 + nXSize;
-    int i, j;
+        pafSourceBuf = static_cast<float *>(
+            VSI_MALLOC2_VERBOSE(sizeof(float), nXSize));
+    GByte* pabyDestBuf1 = static_cast<GByte *>(VSI_MALLOC2_VERBOSE(4, nXSize));
+    GByte* pabyDestBuf2 =  pabyDestBuf1 + nXSize;
+    GByte* pabyDestBuf3 =  pabyDestBuf2 + nXSize;
+    GByte* pabyDestBuf4 =  pabyDestBuf3 + nXSize;
 
     if( (pabyPrecomputed != NULL && panSourceBuf == NULL) ||
         (pabyPrecomputed == NULL && pafSourceBuf == NULL) ||
         pabyDestBuf1 == NULL )
     {
-        eErr = CE_Failure;
-        goto end;
+        VSIFree(pabyPrecomputed);
+        CPLFree(pafSourceBuf);
+        CPLFree(panSourceBuf);
+        CPLFree(pabyDestBuf1);
+        CPLFree(pasColorAssociation);
+
+        return CE_Failure;
     }
 
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     {
         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-        eErr = CE_Failure;
-        goto end;
+        VSIFree(pabyPrecomputed);
+        CPLFree(pafSourceBuf);
+        CPLFree(panSourceBuf);
+        CPLFree(pabyDestBuf1);
+        CPLFree(pasColorAssociation);
+
+        return CE_Failure;
     }
 
-    for ( i = 0; i < nYSize; i++)
+    int nR = 0;
+    int nG = 0;
+    int nB = 0;
+    int nA = 0;
+
+    for( int i = 0; i < nYSize; i++ )
     {
         /* Read source buffer */
-        eErr = GDALRasterIO(   hSrcBand,
-                        GF_Read,
-                        0, i,
-                        nXSize, 1,
-                        (panSourceBuf) ? (void*) panSourceBuf : (void* )pafSourceBuf,
-                        nXSize, 1,
-                        (panSourceBuf) ? GDT_Int32 : GDT_Float32,
-                        0, 0);
-        if (eErr != CE_None)
-            goto end;
+        CPLErr eErr = GDALRasterIO( hSrcBand,
+                                    GF_Read,
+                                    0, i,
+                                    nXSize, 1,
+                                    panSourceBuf
+                                    ? (void*) panSourceBuf
+                                    : (void*) pafSourceBuf,
+                                    nXSize, 1,
+                                    panSourceBuf ? GDT_Int32 : GDT_Float32,
+                                    0, 0);
+        if( eErr != CE_None )
+        {
+            VSIFree(pabyPrecomputed);
+            CPLFree(pafSourceBuf);
+            CPLFree(panSourceBuf);
+            CPLFree(pabyDestBuf1);
+            CPLFree(pasColorAssociation);
+            return eErr;
+        }
 
-        if (pabyPrecomputed)
+        if( pabyPrecomputed )
         {
-            for ( j = 0; j < nXSize; j++)
+            for( int j = 0; j < nXSize; j++ )
             {
                 int nIndex = panSourceBuf[j] + nIndexOffset;
                 pabyDestBuf1[j] = pabyPrecomputed[4 * nIndex];
@@ -1652,7 +2285,7 @@ CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
         }
         else
         {
-            for ( j = 0; j < nXSize; j++)
+            for( int j = 0; j < nXSize; j++ )
             {
                 GDALColorReliefGetRGBA  (pasColorAssociation,
                                          nColorAssociation,
@@ -1662,10 +2295,10 @@ CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
                                          &nG,
                                          &nB,
                                          &nA);
-                pabyDestBuf1[j] = (GByte) nR;
-                pabyDestBuf2[j] = (GByte) nG;
-                pabyDestBuf3[j] = (GByte) nB;
-                pabyDestBuf4[j] = (GByte) nA;
+                pabyDestBuf1[j] = static_cast<GByte>(nR);
+                pabyDestBuf2[j] = static_cast<GByte>(nG);
+                pabyDestBuf3[j] = static_cast<GByte>(nB);
+                pabyDestBuf4[j] = static_cast<GByte>(nA);
             }
         }
 
@@ -1673,54 +2306,91 @@ CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
          * Write Line to Raster
          */
         eErr = GDALRasterIO(hDstBand1,
-                      GF_Write,
-                      0, i, nXSize,
-                      1, pabyDestBuf1, nXSize, 1, GDT_Byte, 0, 0);
-        if (eErr != CE_None)
-            goto end;
+                            GF_Write,
+                            0, i, nXSize,
+                            1, pabyDestBuf1, nXSize, 1, GDT_Byte, 0, 0);
+        if( eErr != CE_None )
+        {
+            VSIFree(pabyPrecomputed);
+            CPLFree(pafSourceBuf);
+            CPLFree(panSourceBuf);
+            CPLFree(pabyDestBuf1);
+            CPLFree(pasColorAssociation);
+
+            return eErr;
+        }
 
         eErr = GDALRasterIO(hDstBand2,
-                      GF_Write,
-                      0, i, nXSize,
-                      1, pabyDestBuf2, nXSize, 1, GDT_Byte, 0, 0);
-        if (eErr != CE_None)
-            goto end;
+                            GF_Write,
+                            0, i, nXSize,
+                            1, pabyDestBuf2, nXSize, 1, GDT_Byte, 0, 0);
+        if( eErr != CE_None )
+        {
+            VSIFree(pabyPrecomputed);
+            CPLFree(pafSourceBuf);
+            CPLFree(panSourceBuf);
+            CPLFree(pabyDestBuf1);
+            CPLFree(pasColorAssociation);
+
+            return eErr;
+        }
 
         eErr = GDALRasterIO(hDstBand3,
-                      GF_Write,
-                      0, i, nXSize,
-                      1, pabyDestBuf3, nXSize, 1, GDT_Byte, 0, 0);
-        if (eErr != CE_None)
-            goto end;
+                            GF_Write,
+                            0, i, nXSize,
+                            1, pabyDestBuf3, nXSize, 1, GDT_Byte, 0, 0);
+        if( eErr != CE_None )
+        {
+            VSIFree(pabyPrecomputed);
+            CPLFree(pafSourceBuf);
+            CPLFree(panSourceBuf);
+            CPLFree(pabyDestBuf1);
+            CPLFree(pasColorAssociation);
 
-        if (hDstBand4)
+            return eErr;
+        }
+
+        if( hDstBand4 )
         {
             eErr = GDALRasterIO(hDstBand4,
                         GF_Write,
                         0, i, nXSize,
                         1, pabyDestBuf4, nXSize, 1, GDT_Byte, 0, 0);
-            if (eErr != CE_None)
-                goto end;
+            if( eErr != CE_None )
+            {
+                VSIFree(pabyPrecomputed);
+                CPLFree(pafSourceBuf);
+                CPLFree(panSourceBuf);
+                CPLFree(pabyDestBuf1);
+                CPLFree(pasColorAssociation);
+
+                return eErr;
+            }
         }
 
         if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-            eErr = CE_Failure;
-            goto end;
+
+            VSIFree(pabyPrecomputed);
+            CPLFree(pafSourceBuf);
+            CPLFree(panSourceBuf);
+            CPLFree(pabyDestBuf1);
+            CPLFree(pasColorAssociation);
+
+            return CE_Failure;
         }
     }
+
     pfnProgress( 1.0, NULL, pProgressData );
-    eErr = CE_None;
 
-end:
     VSIFree(pabyPrecomputed);
     CPLFree(pafSourceBuf);
     CPLFree(panSourceBuf);
     CPLFree(pabyDestBuf1);
     CPLFree(pasColorAssociation);
 
-    return eErr;
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1728,120 +2398,143 @@ end:
 /************************************************************************/
 
 static
-CPLErr GDALGenerateVRTColorRelief(const char* pszDstFilename,
-                               GDALDatasetH hSrcDataset,
-                               GDALRasterBandH hSrcBand,
-                               const char* pszColorFilename,
-                               ColorSelectionMode eColorSelectionMode,
-                               int bAddAlpha)
+CPLErr GDALGenerateVRTColorRelief( const char* pszDstFilename,
+                                   GDALDatasetH hSrcDataset,
+                                   GDALRasterBandH hSrcBand,
+                                   const char* pszColorFilename,
+                                   ColorSelectionMode eColorSelectionMode,
+                                   bool bAddAlpha )
 {
-
     int nColorAssociation = 0;
     ColorAssociation* pasColorAssociation =
             GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
                                           &nColorAssociation);
-    if (pasColorAssociation == NULL)
+    if( pasColorAssociation == NULL )
         return CE_Failure;
 
-    int nXSize = GDALGetRasterBandXSize(hSrcBand);
-    int nYSize = GDALGetRasterBandYSize(hSrcBand);
-
     VSILFILE* fp = VSIFOpenL(pszDstFilename, "wt");
-    if (fp == NULL)
+    if( fp == NULL )
     {
         CPLFree(pasColorAssociation);
         return CE_Failure;
     }
 
-    bool bOK = VSIFPrintfL(fp, "<VRTDataset rasterXSize=\"%d\" rasterYSize=\"%d\">\n", nXSize, nYSize) > 0;
+    const int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    const int nYSize = GDALGetRasterBandYSize(hSrcBand);
+
+    bool bOK =
+        VSIFPrintfL(fp,
+                    "<VRTDataset rasterXSize=\"%d\" rasterYSize=\"%d\">\n",
+                    nXSize, nYSize) > 0;
     const char* pszProjectionRef = GDALGetProjectionRef(hSrcDataset);
-    if (pszProjectionRef && pszProjectionRef[0] != '\0')
+    if( pszProjectionRef && pszProjectionRef[0] != '\0' )
     {
         char* pszEscapedString = CPLEscapeString(pszProjectionRef, -1, CPLES_XML);
         bOK &= VSIFPrintfL(fp, "  <SRS>%s</SRS>\n", pszEscapedString) > 0;
         VSIFree(pszEscapedString);
     }
-    double adfGT[6];
-    if (GDALGetGeoTransform(hSrcDataset, adfGT) == CE_None)
+    double adfGT[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+    if( GDALGetGeoTransform(hSrcDataset, adfGT) == CE_None )
     {
-        bOK &= VSIFPrintfL(fp, "  <GeoTransform> %.16g, %.16g, %.16g, "
-                        "%.16g, %.16g, %.16g</GeoTransform>\n",
-                        adfGT[0], adfGT[1], adfGT[2], adfGT[3], adfGT[4], adfGT[5]) > 0;
+        bOK &= VSIFPrintfL(fp,
+                           "  <GeoTransform> %.16g, %.16g, %.16g, "
+                           "%.16g, %.16g, %.16g</GeoTransform>\n",
+                           adfGT[0], adfGT[1], adfGT[2],
+                           adfGT[3], adfGT[4], adfGT[5]) > 0;
     }
-    int nBands = 3 + (bAddAlpha ? 1 : 0);
-    int iBand;
 
-    int nBlockXSize, nBlockYSize;
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
     GDALGetBlockSize(hSrcBand, &nBlockXSize, &nBlockYSize);
 
-    int bRelativeToVRT;
+    int bRelativeToVRT = FALSE;
     CPLString osPath = CPLGetPath(pszDstFilename);
     char* pszSourceFilename = CPLStrdup(
         CPLExtractRelativePath( osPath.c_str(), GDALGetDescription(hSrcDataset),
                                 &bRelativeToVRT ));
 
-    for(iBand = 0; iBand < nBands; iBand++)
-    {
-        bOK &= VSIFPrintfL(fp, "  <VRTRasterBand dataType=\"Byte\" band=\"%d\">\n", iBand + 1) > 0;
-        bOK &= VSIFPrintfL(fp, "    <ColorInterp>%s</ColorInterp>\n",
-                    GDALGetColorInterpretationName((GDALColorInterp)(GCI_RedBand + iBand))) > 0;
-        bOK &= VSIFPrintfL(fp, "    <ComplexSource>\n") > 0;
-        bOK &= VSIFPrintfL(fp, "      <SourceFilename relativeToVRT=\"%d\">%s</SourceFilename>\n",
-                        bRelativeToVRT, pszSourceFilename) > 0;
-        bOK &= VSIFPrintfL(fp, "      <SourceBand>%d</SourceBand>\n", GDALGetBandNumber(hSrcBand)) > 0;
-        bOK &= VSIFPrintfL(fp, "      <SourceProperties RasterXSize=\"%d\" "
-                        "RasterYSize=\"%d\" DataType=\"%s\" "
-                        "BlockXSize=\"%d\" BlockYSize=\"%d\"/>\n",
-                        nXSize, nYSize,
-                        GDALGetDataTypeName(GDALGetRasterDataType(hSrcBand)),
-                        nBlockXSize, nBlockYSize) > 0;
-        bOK &= VSIFPrintfL(fp, "      <SrcRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
-                        nXSize, nYSize) > 0;
-        bOK &= VSIFPrintfL(fp, "      <DstRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
-                        nXSize, nYSize) > 0;
+    const int nBands = 3 + (bAddAlpha ? 1 : 0);
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+        bOK &= VSIFPrintfL(
+            fp,
+            "  <VRTRasterBand dataType=\"Byte\" band=\"%d\">\n", iBand + 1) > 0;
+        bOK &= VSIFPrintfL(
+            fp, "    <ColorInterp>%s</ColorInterp>\n",
+            GDALGetColorInterpretationName((GDALColorInterp)(GCI_RedBand + iBand))) > 0;
+        bOK &= VSIFPrintfL(
+            fp, "    <ComplexSource>\n") > 0;
+        bOK &= VSIFPrintfL(
+            fp,
+            "      <SourceFilename relativeToVRT=\"%d\">%s</SourceFilename>\n",
+            bRelativeToVRT, pszSourceFilename) > 0;
+        bOK &= VSIFPrintfL(
+            fp, "      <SourceBand>%d</SourceBand>\n",
+            GDALGetBandNumber(hSrcBand)) > 0;
+        bOK &= VSIFPrintfL(
+            fp, "      <SourceProperties RasterXSize=\"%d\" "
+            "RasterYSize=\"%d\" DataType=\"%s\" "
+            "BlockXSize=\"%d\" BlockYSize=\"%d\"/>\n",
+            nXSize, nYSize,
+            GDALGetDataTypeName(GDALGetRasterDataType(hSrcBand)),
+            nBlockXSize, nBlockYSize) > 0;
+        bOK &= VSIFPrintfL(
+            fp,
+            "      "
+            "<SrcRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
+            nXSize, nYSize) > 0;
+        bOK &= VSIFPrintfL(
+            fp,
+            "      "
+            "<DstRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
+            nXSize, nYSize) > 0;
 
         bOK &= VSIFPrintfL(fp, "      <LUT>") > 0;
-        int iColor;
-#define EPSILON 1e-8
-        for(iColor=0;iColor<nColorAssociation;iColor++)
+
+        for( int iColor = 0; iColor < nColorAssociation; iColor++ )
         {
-            if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
+            if( eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY )
             {
-                if (iColor > 1)
+                if( iColor > 1 )
                     bOK &= VSIFPrintfL(fp, ",") > 0;
             }
-            else if (iColor > 0)
+            else if( iColor > 0 )
                 bOK &= VSIFPrintfL(fp, ",") > 0;
 
-            double dfVal = pasColorAssociation[iColor].dfVal;
+            const double dfVal = pasColorAssociation[iColor].dfVal;
 
-            if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
+            if( eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY )
             {
-                bOK &= VSIFPrintfL(fp, "%.18g:0,", dfVal - fabs(dfVal) * DBL_EPSILON) > 0;
+                bOK &= VSIFPrintfL(fp, "%.18g:0,",
+                                   dfVal - fabs(dfVal) * DBL_EPSILON) > 0;
             }
-            else if (iColor > 0 &&
-                     eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
+            else if( iColor > 0 &&
+                     eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY )
             {
-                double dfMidVal = (dfVal + pasColorAssociation[iColor-1].dfVal) / 2;
-                bOK &= VSIFPrintfL(fp, "%.18g:%d", dfMidVal - fabs(dfMidVal) * DBL_EPSILON,
-                        (iBand == 0) ? pasColorAssociation[iColor-1].nR :
-                        (iBand == 1) ? pasColorAssociation[iColor-1].nG :
-                        (iBand == 2) ? pasColorAssociation[iColor-1].nB :
-                                       pasColorAssociation[iColor-1].nA) > 0;
-                bOK &= VSIFPrintfL(fp, ",%.18g:%d", dfMidVal ,
-                        (iBand == 0) ? pasColorAssociation[iColor].nR :
-                        (iBand == 1) ? pasColorAssociation[iColor].nG :
-                        (iBand == 2) ? pasColorAssociation[iColor].nB :
-                                       pasColorAssociation[iColor].nA) > 0;
-
+                const double dfMidVal =
+                    (dfVal + pasColorAssociation[iColor-1].dfVal) / 2.0;
+                bOK &= VSIFPrintfL(
+                    fp, "%.18g:%d",
+                    dfMidVal - fabs(dfMidVal) * DBL_EPSILON,
+                    (iBand == 0) ? pasColorAssociation[iColor-1].nR :
+                    (iBand == 1) ? pasColorAssociation[iColor-1].nG :
+                    (iBand == 2) ? pasColorAssociation[iColor-1].nB :
+                    pasColorAssociation[iColor-1].nA) > 0;
+                bOK &= VSIFPrintfL(
+                    fp, ",%.18g:%d", dfMidVal,
+                    (iBand == 0) ? pasColorAssociation[iColor].nR :
+                    (iBand == 1) ? pasColorAssociation[iColor].nG :
+                    (iBand == 2) ? pasColorAssociation[iColor].nB :
+                    pasColorAssociation[iColor].nA) > 0;
             }
 
-            if (eColorSelectionMode != COLOR_SELECTION_NEAREST_ENTRY)
+            if( eColorSelectionMode != COLOR_SELECTION_NEAREST_ENTRY )
             {
-                if (dfVal != (double)(int)dfVal)
+                if( dfVal != static_cast<double>(static_cast<int>(dfVal)) )
                     bOK &= VSIFPrintfL(fp, "%.18g", dfVal) > 0;
                 else
-                    bOK &= VSIFPrintfL(fp, "%d", (int)dfVal) > 0;
+                    bOK &= VSIFPrintfL(fp, "%d", static_cast<int>(dfVal)) > 0;
                 bOK &= VSIFPrintfL(fp, ":%d",
                             (iBand == 0) ? pasColorAssociation[iColor].nR :
                             (iBand == 1) ? pasColorAssociation[iColor].nG :
@@ -1849,11 +2542,11 @@ CPLErr GDALGenerateVRTColorRelief(const char* pszDstFilename,
                                            pasColorAssociation[iColor].nA) > 0;
             }
 
-            if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
+            if( eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY )
             {
-                bOK &= VSIFPrintfL(fp, ",%.18g:0", dfVal + fabs(dfVal) * DBL_EPSILON) > 0;
+                bOK &= VSIFPrintfL(fp, ",%.18g:0",
+                                   dfVal + fabs(dfVal) * DBL_EPSILON) > 0;
             }
-
         }
         bOK &= VSIFPrintfL(fp, "</LUT>\n") > 0;
 
@@ -1872,36 +2565,41 @@ CPLErr GDALGenerateVRTColorRelief(const char* pszDstFilename,
     return (bOK) ? CE_None : CE_Failure;
 }
 
-
 /************************************************************************/
 /*                         GDALTRIAlg()                                 */
 /************************************************************************/
 
+template<class T> static T MyAbs(T x);
+
+template<> float MyAbs( float x ) { return fabsf(x); }
+template<> int MyAbs( int x ) { return x >= 0 ? x : -x; }
+
+template<class T>
 static
-float GDALTRIAlg (float* afWin,
-                  CPL_UNUSED float fDstNoDataValue,
-                  CPL_UNUSED void* pData)
+float GDALTRIAlg( const T* afWin,
+                  float /*fDstNoDataValue*/,
+                  void* /*pData*/ )
 {
     // Terrain Ruggedness is average difference in height
-    return (fabs(afWin[0]-afWin[4]) +
-            fabs(afWin[1]-afWin[4]) +
-            fabs(afWin[2]-afWin[4]) +
-            fabs(afWin[3]-afWin[4]) +
-            fabs(afWin[5]-afWin[4]) +
-            fabs(afWin[6]-afWin[4]) +
-            fabs(afWin[7]-afWin[4]) +
-            fabs(afWin[8]-afWin[4]))/8;
+    return (MyAbs(afWin[0]-afWin[4]) +
+            MyAbs(afWin[1]-afWin[4]) +
+            MyAbs(afWin[2]-afWin[4]) +
+            MyAbs(afWin[3]-afWin[4]) +
+            MyAbs(afWin[5]-afWin[4]) +
+            MyAbs(afWin[6]-afWin[4]) +
+            MyAbs(afWin[7]-afWin[4]) +
+            MyAbs(afWin[8]-afWin[4])) * 0.125f;
 }
 
-
 /************************************************************************/
 /*                         GDALTPIAlg()                                 */
 /************************************************************************/
 
+template<class T>
 static
-float GDALTPIAlg (float* afWin,
-                  CPL_UNUSED float fDstNoDataValue,
-                  CPL_UNUSED void* pData)
+float GDALTPIAlg( const T* afWin,
+                  float /*fDstNoDataValue*/,
+                  void* /*pData*/ )
 {
     // Terrain Position is the difference between
     // The central cell and the mean of the surrounding cells
@@ -1913,34 +2611,36 @@ float GDALTPIAlg (float* afWin,
               afWin[5]+
               afWin[6]+
               afWin[7]+
-              afWin[8])/8);
+              afWin[8]) * 0.125f );
 }
 
 /************************************************************************/
 /*                     GDALRoughnessAlg()                               */
 /************************************************************************/
 
+template<class T>
 static
-float GDALRoughnessAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, CPL_UNUSED void* pData)
+float GDALRoughnessAlg( const T* afWin, float /*fDstNoDataValue*/,
+                        void* /*pData*/ )
 {
     // Roughness is the largest difference
     //  between any two cells
 
-    float pafRoughnessMin = afWin[0];
-    float pafRoughnessMax = afWin[0];
+    T pafRoughnessMin = afWin[0];
+    T pafRoughnessMax = afWin[0];
 
-    for ( int k = 1; k < 9; k++)
+    for( int k = 1; k < 9; k++ )
     {
-        if (afWin[k] > pafRoughnessMax)
+        if( afWin[k] > pafRoughnessMax )
         {
             pafRoughnessMax=afWin[k];
         }
-        if (afWin[k] < pafRoughnessMin)
+        if( afWin[k] < pafRoughnessMin )
         {
             pafRoughnessMin=afWin[k];
         }
     }
-    return pafRoughnessMax - pafRoughnessMin;
+    return static_cast<float>(pafRoughnessMax - pafRoughnessMin);
 }
 
 /************************************************************************/
@@ -1949,39 +2649,42 @@ float GDALRoughnessAlg (float* afWin, CPL_UNUSED float fDstNoDataValue, CPL_UNUS
 /* ==================================================================== */
 /************************************************************************/
 
+template<class T>
 class GDALGeneric3x3RasterBand;
 
+template<class T>
 class GDALGeneric3x3Dataset : public GDALDataset
 {
-    friend class GDALGeneric3x3RasterBand;
+    friend class GDALGeneric3x3RasterBand<T>;
 
-    GDALGeneric3x3ProcessingAlg pfnAlg;
+    typename GDALGeneric3x3ProcessingAlg<T>::type pfnAlg;
     void*              pAlgData;
     GDALDatasetH       hSrcDS;
     GDALRasterBandH    hSrcBand;
-    float*             apafSourceBuf[3];
+    T*                 apafSourceBuf[3];
     int                bDstHasNoData;
     double             dfDstNoDataValue;
     int                nCurLine;
-    int                bComputeAtEdges;
+    bool               bComputeAtEdges;
 
   public:
-                        GDALGeneric3x3Dataset(GDALDatasetH hSrcDS,
-                                              GDALRasterBandH hSrcBand,
-                                              GDALDataType eDstDataType,
-                                              int bDstHasNoData,
-                                              double dfDstNoDataValue,
-                                              GDALGeneric3x3ProcessingAlg pfnAlg,
-                                              void* pAlgData,
-                                              int bComputeAtEdges);
+                        GDALGeneric3x3Dataset(
+                            GDALDatasetH hSrcDS,
+                            GDALRasterBandH hSrcBand,
+                            GDALDataType eDstDataType,
+                            int bDstHasNoData,
+                            double dfDstNoDataValue,
+                            typename GDALGeneric3x3ProcessingAlg<T>::type pfnAlg,
+                            void* pAlgData,
+                            bool bComputeAtEdges );
                        ~GDALGeneric3x3Dataset();
 
     bool                InitOK() const { return apafSourceBuf[0] != NULL &&
                                                 apafSourceBuf[1] != NULL &&
                                                 apafSourceBuf[2] != NULL; }
 
-    CPLErr      GetGeoTransform( double * padfGeoTransform );
-    const char *GetProjectionRef();
+    CPLErr      GetGeoTransform( double * padfGeoTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
 /************************************************************************/
@@ -1990,125 +2693,165 @@ class GDALGeneric3x3Dataset : public GDALDataset
 /* ==================================================================== */
 /************************************************************************/
 
+template<class T>
 class GDALGeneric3x3RasterBand : public GDALRasterBand
 {
-    friend class GDALGeneric3x3Dataset;
+    friend class GDALGeneric3x3Dataset<T>;
     int bSrcHasNoData;
-    float fSrcNoDataValue;
+    T fSrcNoDataValue;
     int bIsSrcNoDataNan;
+    GDALDataType eReadDT;
 
-    void                    InitWidthNoData(void* pImage);
+    void                    InitWidthNoData( void* pImage );
 
   public:
-                 GDALGeneric3x3RasterBand( GDALGeneric3x3Dataset *poDS,
+                 GDALGeneric3x3RasterBand( GDALGeneric3x3Dataset<T> *poDS,
                                            GDALDataType eDstDataType );
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual double          GetNoDataValue( int* pbHasNoData );
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual double          GetNoDataValue( int* pbHasNoData ) override;
 };
 
-GDALGeneric3x3Dataset::GDALGeneric3x3Dataset(
-                                     GDALDatasetH hSrcDSIn,
-                                     GDALRasterBandH hSrcBandIn,
-                                     GDALDataType eDstDataType,
-                                     int bDstHasNoDataIn,
-                                     double dfDstNoDataValueIn,
-                                     GDALGeneric3x3ProcessingAlg pfnAlgIn,
-                                     void* pAlgDataIn,
-                                     int bComputeAtEdgesIn)
-{
-    hSrcDS = hSrcDSIn;
-    hSrcBand = hSrcBandIn;
-    pfnAlg = pfnAlgIn;
-    pAlgData = pAlgDataIn;
-    bDstHasNoData = bDstHasNoDataIn;
-    dfDstNoDataValue = dfDstNoDataValueIn;
-    bComputeAtEdges = bComputeAtEdgesIn;
-
+template<class T>
+GDALGeneric3x3Dataset<T>::GDALGeneric3x3Dataset(
+    GDALDatasetH hSrcDSIn,
+    GDALRasterBandH hSrcBandIn,
+    GDALDataType eDstDataType,
+    int bDstHasNoDataIn,
+    double dfDstNoDataValueIn,
+    typename GDALGeneric3x3ProcessingAlg<T>::type pfnAlgIn,
+    void* pAlgDataIn,
+    bool bComputeAtEdgesIn ) :
+    pfnAlg(pfnAlgIn),
+    pAlgData(pAlgDataIn),
+    hSrcDS(hSrcDSIn),
+    hSrcBand(hSrcBandIn),
+    bDstHasNoData(bDstHasNoDataIn),
+    dfDstNoDataValue(dfDstNoDataValueIn),
+    nCurLine(-1),
+    bComputeAtEdges(bComputeAtEdgesIn)
+{
     CPLAssert(eDstDataType == GDT_Byte || eDstDataType == GDT_Float32);
 
     nRasterXSize = GDALGetRasterXSize(hSrcDS);
     nRasterYSize = GDALGetRasterYSize(hSrcDS);
 
-    SetBand(1, new GDALGeneric3x3RasterBand(this, eDstDataType));
-
-    apafSourceBuf[0] = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nRasterXSize);
-    apafSourceBuf[1] = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nRasterXSize);
-    apafSourceBuf[2] = (float *) VSI_MALLOC2_VERBOSE(sizeof(float),nRasterXSize);
+    SetBand(1, new GDALGeneric3x3RasterBand<T>(this, eDstDataType));
 
-    nCurLine = -1;
+    apafSourceBuf[0] = (T *) VSI_MALLOC2_VERBOSE(sizeof(T),nRasterXSize);
+    apafSourceBuf[1] = (T *) VSI_MALLOC2_VERBOSE(sizeof(T),nRasterXSize);
+    apafSourceBuf[2] = (T *) VSI_MALLOC2_VERBOSE(sizeof(T),nRasterXSize);
 }
 
-GDALGeneric3x3Dataset::~GDALGeneric3x3Dataset()
+template<class T>
+GDALGeneric3x3Dataset<T>::~GDALGeneric3x3Dataset()
 {
     CPLFree(apafSourceBuf[0]);
     CPLFree(apafSourceBuf[1]);
     CPLFree(apafSourceBuf[2]);
 }
 
-CPLErr GDALGeneric3x3Dataset::GetGeoTransform( double * padfGeoTransform )
+template<class T>
+CPLErr GDALGeneric3x3Dataset<T>::GetGeoTransform( double * padfGeoTransform )
 {
     return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
 }
 
-const char *GDALGeneric3x3Dataset::GetProjectionRef()
+template<class T>
+const char *GDALGeneric3x3Dataset<T>::GetProjectionRef()
 {
     return GDALGetProjectionRef(hSrcDS);
 }
 
-GDALGeneric3x3RasterBand::GDALGeneric3x3RasterBand(GDALGeneric3x3Dataset *poDSIn,
-                                                   GDALDataType eDstDataType)
+template<class T>
+GDALGeneric3x3RasterBand<T>::GDALGeneric3x3RasterBand(
+    GDALGeneric3x3Dataset<T> *poDSIn,
+    GDALDataType eDstDataType ) :
+    bSrcHasNoData(FALSE),
+    fSrcNoDataValue(0),
+    bIsSrcNoDataNan(FALSE),
+    eReadDT(GDT_Unknown)
 {
     poDS = poDSIn;
-    this->nBand = 1;
+    nBand = 1;
     eDataType = eDstDataType;
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 
-    bSrcHasNoData = FALSE;
-    fSrcNoDataValue = (float)GDALGetRasterNoDataValue(poDSIn->hSrcBand,
-                                                      &bSrcHasNoData);
-    bIsSrcNoDataNan = bSrcHasNoData && CPLIsNan(fSrcNoDataValue);
+    const double dfNoDataValue = GDALGetRasterNoDataValue(poDSIn->hSrcBand,
+                                                          &bSrcHasNoData);
+    if( std::numeric_limits<T>::is_integer )
+    {
+        eReadDT = GDT_Int32;
+        if( bSrcHasNoData )
+        {
+            GDALDataType eSrcDT = GDALGetRasterDataType(poDSIn->hSrcBand);
+            CPLAssert( eSrcDT == GDT_Byte ||
+                       eSrcDT == GDT_UInt16 ||
+                       eSrcDT == GDT_Int16 );
+            const int nMinVal =
+                (eSrcDT == GDT_Byte ) ? 0 : (eSrcDT == GDT_UInt16) ? 0 : -32768;
+            const int nMaxVal =
+                (eSrcDT == GDT_Byte )
+                ? 255
+                : (eSrcDT == GDT_UInt16) ? 65535 : 32767;
+
+            if( fabs(dfNoDataValue - floor(dfNoDataValue + 0.5)) < 1e-2 &&
+                dfNoDataValue >= nMinVal && dfNoDataValue <= nMaxVal )
+            {
+                fSrcNoDataValue = static_cast<T>(floor(dfNoDataValue + 0.5));
+            }
+            else
+            {
+                bSrcHasNoData = FALSE;
+            }
+        }
+    }
+    else
+    {
+        eReadDT = GDT_Float32;
+        fSrcNoDataValue = static_cast<T>(dfNoDataValue);
+        bIsSrcNoDataNan = bSrcHasNoData && CPLIsNan(dfNoDataValue);
+    }
 }
 
-void   GDALGeneric3x3RasterBand::InitWidthNoData(void* pImage)
+template<class T>
+void GDALGeneric3x3RasterBand<T>::InitWidthNoData(void* pImage)
 {
-    int j;
-    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
-    if (eDataType == GDT_Byte)
+    GDALGeneric3x3Dataset<T> * poGDS = (GDALGeneric3x3Dataset<T> *) poDS;
+    if( eDataType == GDT_Byte )
     {
-        for(j=0;j<nBlockXSize;j++)
+        for( int j = 0; j < nBlockXSize; j++ )
             ((GByte*)pImage)[j] = (GByte) poGDS->dfDstNoDataValue;
     }
     else
     {
-        for(j=0;j<nBlockXSize;j++)
-            ((float*)pImage)[j] = (float) poGDS->dfDstNoDataValue;
+        for( int j = 0; j < nBlockXSize; j++ )
+            ((float*)pImage)[j] = static_cast<float>(poGDS->dfDstNoDataValue);
     }
 }
 
-CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
-                                             int nBlockYOff,
-                                             void *pImage )
+template<class T>
+CPLErr GDALGeneric3x3RasterBand<T>::IReadBlock( int /*nBlockXOff*/,
+                                                int nBlockYOff,
+                                                void *pImage )
 {
-    int i, j;
-    float fVal;
-    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
+    GDALGeneric3x3Dataset<T> * poGDS = (GDALGeneric3x3Dataset<T> *) poDS;
 
-    if (poGDS->bComputeAtEdges && nRasterXSize >= 2 && nRasterYSize >= 2)
+    if( poGDS->bComputeAtEdges && nRasterXSize >= 2 && nRasterYSize >= 2 )
     {
-        if (nBlockYOff == 0)
+        if( nBlockYOff == 0 )
         {
-            for(i=0;i<2;i++)
+            for( int i = 0; i < 2; i++ )
             {
                 CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
                                     GF_Read,
                                     0, i, nBlockXSize, 1,
                                     poGDS->apafSourceBuf[i+1],
                                     nBlockXSize, 1,
-                                    GDT_Float32,
+                                    eReadDT,
                                     0, 0);
-                if (eErr != CE_None)
+                if( eErr != CE_None )
                 {
                     InitWidthNoData(pImage);
                     return eErr;
@@ -2116,30 +2859,41 @@ CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             }
             poGDS->nCurLine = 0;
 
-            for (j = 0; j < nRasterXSize; j++)
+            for( int j = 0; j < nRasterXSize; j++ )
             {
-                float afWin[9];
                 int jmin = (j == 0) ? j : j - 1;
                 int jmax = (j == nRasterXSize - 1) ? j : j + 1;
 
-                afWin[0] = INTERPOL(poGDS->apafSourceBuf[1][jmin], poGDS->apafSourceBuf[2][jmin]);
-                afWin[1] = INTERPOL(poGDS->apafSourceBuf[1][j],    poGDS->apafSourceBuf[2][j]);
-                afWin[2] = INTERPOL(poGDS->apafSourceBuf[1][jmax], poGDS->apafSourceBuf[2][jmax]);
-                afWin[3] = poGDS->apafSourceBuf[1][jmin];
-                afWin[4] = poGDS->apafSourceBuf[1][j];
-                afWin[5] = poGDS->apafSourceBuf[1][jmax];
-                afWin[6] = poGDS->apafSourceBuf[2][jmin];
-                afWin[7] = poGDS->apafSourceBuf[2][j];
-                afWin[8] = poGDS->apafSourceBuf[2][jmax];
-
-                fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                  bIsSrcNoDataNan,
-                                    afWin, (float) poGDS->dfDstNoDataValue,
-                                    poGDS->pfnAlg,
-                                    poGDS->pAlgData,
-                                    poGDS->bComputeAtEdges);
-
-                if (eDataType == GDT_Byte)
+                T afWin[9] = {
+                    INTERPOL(poGDS->apafSourceBuf[1][jmin],
+                             poGDS->apafSourceBuf[2][jmin],
+                             bSrcHasNoData, fSrcNoDataValue),
+                    INTERPOL(poGDS->apafSourceBuf[1][j],
+                             poGDS->apafSourceBuf[2][j],
+                             bSrcHasNoData, fSrcNoDataValue),
+                    INTERPOL(poGDS->apafSourceBuf[1][jmax],
+                             poGDS->apafSourceBuf[2][jmax],
+                             bSrcHasNoData, fSrcNoDataValue),
+                    poGDS->apafSourceBuf[1][jmin],
+                    poGDS->apafSourceBuf[1][j],
+                    poGDS->apafSourceBuf[1][jmax],
+                    poGDS->apafSourceBuf[2][jmin],
+                    poGDS->apafSourceBuf[2][j],
+                    poGDS->apafSourceBuf[2][jmax]
+                };
+
+                const float fVal =
+                    ComputeVal(
+                        CPL_TO_BOOL(bSrcHasNoData),
+                        fSrcNoDataValue,
+                        CPL_TO_BOOL(bIsSrcNoDataNan),
+                        afWin,
+                        static_cast<float>(poGDS->dfDstNoDataValue),
+                        poGDS->pfnAlg,
+                        poGDS->pAlgData,
+                        poGDS->bComputeAtEdges);
+
+                if( eDataType == GDT_Byte )
                     ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
                 else
                     ((float*)pImage)[j] = fVal;
@@ -2147,20 +2901,21 @@ CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
             return CE_None;
         }
-        else if (nBlockYOff == nRasterYSize - 1)
+        else if( nBlockYOff == nRasterYSize - 1 )
         {
-            if (poGDS->nCurLine != nRasterYSize - 2)
+            if( poGDS->nCurLine != nRasterYSize - 2 )
             {
-                for(i=0;i<2;i++)
+                for( int i = 0; i < 2; i++ )
                 {
-                    CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
-                                        GF_Read,
-                                        0, nRasterYSize - 2 + i, nBlockXSize, 1,
-                                        poGDS->apafSourceBuf[i+1],
-                                        nBlockXSize, 1,
-                                        GDT_Float32,
-                                        0, 0);
-                    if (eErr != CE_None)
+                    CPLErr eErr = GDALRasterIO(
+                        poGDS->hSrcBand,
+                        GF_Read,
+                        0, nRasterYSize - 2 + i, nBlockXSize, 1,
+                        poGDS->apafSourceBuf[i+1],
+                        nBlockXSize, 1,
+                        eReadDT,
+                        0, 0);
+                    if( eErr != CE_None )
                     {
                         InitWidthNoData(pImage);
                         return eErr;
@@ -2168,30 +2923,41 @@ CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                 }
             }
 
-            for (j = 0; j < nRasterXSize; j++)
+            for( int j = 0; j < nRasterXSize; j++ )
             {
-                float afWin[9];
                 int jmin = (j == 0) ? j : j - 1;
                 int jmax = (j == nRasterXSize - 1) ? j : j + 1;
 
-                afWin[0] = poGDS->apafSourceBuf[1][jmin];
-                afWin[1] = poGDS->apafSourceBuf[1][j];
-                afWin[2] = poGDS->apafSourceBuf[1][jmax];
-                afWin[3] = poGDS->apafSourceBuf[2][jmin];
-                afWin[4] = poGDS->apafSourceBuf[2][j];
-                afWin[5] = poGDS->apafSourceBuf[2][jmax];
-                afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][jmin], poGDS->apafSourceBuf[1][jmin]);
-                afWin[7] = INTERPOL(poGDS->apafSourceBuf[2][j],    poGDS->apafSourceBuf[1][j]);
-                afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][jmax], poGDS->apafSourceBuf[1][jmax]);
-
-                fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                                  bIsSrcNoDataNan,
-                                    afWin, (float) poGDS->dfDstNoDataValue,
-                                    poGDS->pfnAlg,
-                                    poGDS->pAlgData,
-                                    poGDS->bComputeAtEdges);
-
-                if (eDataType == GDT_Byte)
+                T afWin[9] = {
+                    poGDS->apafSourceBuf[1][jmin],
+                    poGDS->apafSourceBuf[1][j],
+                    poGDS->apafSourceBuf[1][jmax],
+                    poGDS->apafSourceBuf[2][jmin],
+                    poGDS->apafSourceBuf[2][j],
+                    poGDS->apafSourceBuf[2][jmax],
+                    INTERPOL(poGDS->apafSourceBuf[2][jmin],
+                             poGDS->apafSourceBuf[1][jmin],
+                             bSrcHasNoData, fSrcNoDataValue),
+                    INTERPOL(poGDS->apafSourceBuf[2][j],
+                             poGDS->apafSourceBuf[1][j],
+                             bSrcHasNoData, fSrcNoDataValue),
+                    INTERPOL(poGDS->apafSourceBuf[2][jmax],
+                             poGDS->apafSourceBuf[1][jmax],
+                             bSrcHasNoData, fSrcNoDataValue)
+                };
+
+                const float fVal =
+                    ComputeVal(
+                        CPL_TO_BOOL(bSrcHasNoData),
+                        fSrcNoDataValue,
+                        CPL_TO_BOOL(bIsSrcNoDataNan),
+                        afWin,
+                        static_cast<float>(poGDS->dfDstNoDataValue),
+                        poGDS->pfnAlg,
+                        poGDS->pAlgData,
+                        poGDS->bComputeAtEdges);
+
+                if( eDataType == GDT_Byte )
                     ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
                 else
                     ((float*)pImage)[j] = fVal;
@@ -2200,17 +2966,17 @@ CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             return CE_None;
         }
     }
-    else if ( nBlockYOff == 0 || nBlockYOff == nRasterYSize - 1)
+    else if( nBlockYOff == 0 || nBlockYOff == nRasterYSize - 1 )
     {
         InitWidthNoData(pImage);
         return CE_None;
     }
 
-    if ( poGDS->nCurLine != nBlockYOff )
+    if( poGDS->nCurLine != nBlockYOff )
     {
-        if (poGDS->nCurLine + 1 == nBlockYOff)
+        if( poGDS->nCurLine + 1 == nBlockYOff )
         {
-            float* pafTmp =  poGDS->apafSourceBuf[0];
+            T* pafTmp = poGDS->apafSourceBuf[0];
             poGDS->apafSourceBuf[0] = poGDS->apafSourceBuf[1];
             poGDS->apafSourceBuf[1] = poGDS->apafSourceBuf[2];
             poGDS->apafSourceBuf[2] = pafTmp;
@@ -2220,10 +2986,10 @@ CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                     0, nBlockYOff + 1, nBlockXSize, 1,
                                     poGDS->apafSourceBuf[2],
                                     nBlockXSize, 1,
-                                    GDT_Float32,
+                                    eReadDT,
                                     0, 0);
 
-            if (eErr != CE_None)
+            if( eErr != CE_None )
             {
                 InitWidthNoData(pImage);
                 return eErr;
@@ -2231,16 +2997,17 @@ CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         }
         else
         {
-            for(i=0;i<3;i++)
+            for( int i = 0; i < 3; i++ )
             {
-                CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
-                                    GF_Read,
-                                    0, nBlockYOff + i - 1, nBlockXSize, 1,
-                                    poGDS->apafSourceBuf[i],
-                                    nBlockXSize, 1,
-                                    GDT_Float32,
-                                    0, 0);
-                if (eErr != CE_None)
+                const CPLErr eErr =
+                    GDALRasterIO(poGDS->hSrcBand,
+                                 GF_Read,
+                                 0, nBlockYOff + i - 1, nBlockXSize, 1,
+                                 poGDS->apafSourceBuf[i],
+                                 nBlockXSize, 1,
+                                 eReadDT,
+                                 0, 0);
+                if( eErr != CE_None )
                 {
                     InitWidthNoData(pImage);
                     return eErr;
@@ -2251,108 +3018,126 @@ CPLErr GDALGeneric3x3RasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         poGDS->nCurLine = nBlockYOff;
     }
 
-    if (poGDS->bComputeAtEdges && nRasterXSize >= 2)
-    {
-        float afWin[9];
-
-        j = 0;
-        afWin[0] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j+1]);
-        afWin[1] = poGDS->apafSourceBuf[0][j];
-        afWin[2] = poGDS->apafSourceBuf[0][j+1];
-        afWin[3] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j+1]);
-        afWin[4] = poGDS->apafSourceBuf[1][j];
-        afWin[5] = poGDS->apafSourceBuf[1][j+1];
-        afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j+1]);
-        afWin[7] = poGDS->apafSourceBuf[2][j];
-        afWin[8] = poGDS->apafSourceBuf[2][j+1];
-
-        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                          bIsSrcNoDataNan,
-                                    afWin, (float) poGDS->dfDstNoDataValue,
-                                    poGDS->pfnAlg,
-                                    poGDS->pAlgData,
-                                    poGDS->bComputeAtEdges);
-
-        if (eDataType == GDT_Byte)
-            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
-        else
-            ((float*)pImage)[j] = fVal;
+    if( poGDS->bComputeAtEdges && nRasterXSize >= 2 )
+    {
+        int j = 0;
+        T afWin[9] = {
+            INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j+1],
+                     bSrcHasNoData, fSrcNoDataValue),
+            poGDS->apafSourceBuf[0][j],
+            poGDS->apafSourceBuf[0][j+1],
+            INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j+1],
+                     bSrcHasNoData, fSrcNoDataValue),
+            poGDS->apafSourceBuf[1][j],
+            poGDS->apafSourceBuf[1][j+1],
+            INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j+1],
+                     bSrcHasNoData, fSrcNoDataValue),
+            poGDS->apafSourceBuf[2][j],
+            poGDS->apafSourceBuf[2][j+1]
+        };
+
+        {
+            const float fVal =
+                ComputeVal(
+                    CPL_TO_BOOL(bSrcHasNoData),
+                    fSrcNoDataValue,
+                    CPL_TO_BOOL(bIsSrcNoDataNan),
+                    afWin,
+                    static_cast<float>(poGDS->dfDstNoDataValue),
+                    poGDS->pfnAlg,
+                    poGDS->pAlgData,
+                    poGDS->bComputeAtEdges);
+
+            if( eDataType == GDT_Byte )
+                ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+            else
+                ((float*)pImage)[j] = fVal;
+        }
 
         j = nRasterXSize - 1;
 
         afWin[0] = poGDS->apafSourceBuf[0][j-1];
         afWin[1] = poGDS->apafSourceBuf[0][j];
-        afWin[2] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j-1]);
+        afWin[2] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j-1], bSrcHasNoData, fSrcNoDataValue);
         afWin[3] = poGDS->apafSourceBuf[1][j-1];
         afWin[4] = poGDS->apafSourceBuf[1][j];
-        afWin[5] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j-1]);
+        afWin[5] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j-1], bSrcHasNoData, fSrcNoDataValue);
         afWin[6] = poGDS->apafSourceBuf[2][j-1];
         afWin[7] = poGDS->apafSourceBuf[2][j];
-        afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j-1]);
-
-        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                          bIsSrcNoDataNan,
-                                    afWin, (float) poGDS->dfDstNoDataValue,
-                                    poGDS->pfnAlg,
-                                    poGDS->pAlgData,
-                                    poGDS->bComputeAtEdges);
-
-        if (eDataType == GDT_Byte)
+        afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j-1], bSrcHasNoData, fSrcNoDataValue);
+
+        const float fVal =
+            ComputeVal(
+                CPL_TO_BOOL(bSrcHasNoData),
+                fSrcNoDataValue,
+                CPL_TO_BOOL(bIsSrcNoDataNan),
+                afWin,
+                static_cast<float>(poGDS->dfDstNoDataValue),
+                poGDS->pfnAlg,
+                poGDS->pAlgData,
+                poGDS->bComputeAtEdges);
+
+        if( eDataType == GDT_Byte )
             ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
         else
             ((float*)pImage)[j] = fVal;
     }
     else
     {
-        if (eDataType == GDT_Byte)
+        if( eDataType == GDT_Byte )
         {
             ((GByte*)pImage)[0] = (GByte) poGDS->dfDstNoDataValue;
-            if (nBlockXSize > 1)
+            if( nBlockXSize > 1 )
                 ((GByte*)pImage)[nBlockXSize - 1] = (GByte) poGDS->dfDstNoDataValue;
         }
         else
         {
-            ((float*)pImage)[0] = (float) poGDS->dfDstNoDataValue;
-            if (nBlockXSize > 1)
-                ((float*)pImage)[nBlockXSize - 1] = (float) poGDS->dfDstNoDataValue;
-        }
-    }
-
-
-    for(j=1;j<nBlockXSize - 1;j++)
-    {
-        float afWin[9];
-        afWin[0] = poGDS->apafSourceBuf[0][j-1];
-        afWin[1] = poGDS->apafSourceBuf[0][j];
-        afWin[2] = poGDS->apafSourceBuf[0][j+1];
-        afWin[3] = poGDS->apafSourceBuf[1][j-1];
-        afWin[4] = poGDS->apafSourceBuf[1][j];
-        afWin[5] = poGDS->apafSourceBuf[1][j+1];
-        afWin[6] = poGDS->apafSourceBuf[2][j-1];
-        afWin[7] = poGDS->apafSourceBuf[2][j];
-        afWin[8] = poGDS->apafSourceBuf[2][j+1];
-
-        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
-                          bIsSrcNoDataNan,
-                                afWin, (float) poGDS->dfDstNoDataValue,
-                                poGDS->pfnAlg,
-                                poGDS->pAlgData,
-                                poGDS->bComputeAtEdges);
-
-        if (eDataType == GDT_Byte)
+            ((float*)pImage)[0] = static_cast<float>(poGDS->dfDstNoDataValue);
+            if( nBlockXSize > 1 )
+                ((float*)pImage)[nBlockXSize - 1] =
+                    static_cast<float>(poGDS->dfDstNoDataValue);
+        }
+    }
+
+    for( int j = 1; j < nBlockXSize - 1; j++ )
+    {
+        T afWin[9] = {
+            poGDS->apafSourceBuf[0][j-1],
+            poGDS->apafSourceBuf[0][j],
+            poGDS->apafSourceBuf[0][j+1],
+            poGDS->apafSourceBuf[1][j-1],
+            poGDS->apafSourceBuf[1][j],
+            poGDS->apafSourceBuf[1][j+1],
+            poGDS->apafSourceBuf[2][j-1],
+            poGDS->apafSourceBuf[2][j],
+            poGDS->apafSourceBuf[2][j+1]
+        };
+
+        const float fVal =
+            ComputeVal(
+                CPL_TO_BOOL(bSrcHasNoData),
+                fSrcNoDataValue,
+                CPL_TO_BOOL(bIsSrcNoDataNan),
+                afWin,
+                static_cast<float>(poGDS->dfDstNoDataValue),
+                poGDS->pfnAlg,
+                poGDS->pAlgData,
+                poGDS->bComputeAtEdges);
+
+        if( eDataType == GDT_Byte )
             ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
         else
             ((float*)pImage)[j] = fVal;
-
     }
 
     return CE_None;
 }
 
-double GDALGeneric3x3RasterBand::GetNoDataValue( int* pbHasNoData )
+template<class T>
+double GDALGeneric3x3RasterBand<T>::GetNoDataValue( int* pbHasNoData )
 {
-    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
-    if (pbHasNoData)
+    GDALGeneric3x3Dataset<T> * poGDS = (GDALGeneric3x3Dataset<T> *) poDS;
+    if( pbHasNoData )
         *pbHasNoData = poGDS->bDstHasNoData;
     return poGDS->dfDstNoDataValue;
 }
@@ -2385,31 +3170,31 @@ typedef enum
 
 static Algorithm GetAlgorithm(const char* pszProcessing)
 {
-    if ( EQUAL(pszProcessing, "shade") || EQUAL(pszProcessing, "hillshade") )
+    if( EQUAL(pszProcessing, "shade") || EQUAL(pszProcessing, "hillshade") )
     {
         return HILL_SHADE;
     }
-    else if ( EQUAL(pszProcessing, "slope") )
+    else if( EQUAL(pszProcessing, "slope") )
     {
         return SLOPE;
     }
-    else if ( EQUAL(pszProcessing, "aspect") )
+    else if( EQUAL(pszProcessing, "aspect") )
     {
         return ASPECT;
     }
-    else if ( EQUAL(pszProcessing, "color-relief") )
+    else if( EQUAL(pszProcessing, "color-relief") )
     {
         return COLOR_RELIEF;
     }
-    else if ( EQUAL(pszProcessing, "TRI") )
+    else if( EQUAL(pszProcessing, "TRI") )
     {
         return TRI;
     }
-    else if ( EQUAL(pszProcessing, "TPI") )
+    else if( EQUAL(pszProcessing, "TPI") )
     {
         return TPI;
     }
-    else if ( EQUAL(pszProcessing, "roughness") )
+    else if( EQUAL(pszProcessing, "roughness") )
     {
         return ROUGHNESS;
     }
@@ -2448,12 +3233,12 @@ static Algorithm GetAlgorithm(const char* pszProcessing)
  * @since GDAL 2.1
  */
 
-GDALDatasetH GDALDEMProcessing(const char *pszDest,
-                               GDALDatasetH hSrcDataset,
-                               const char* pszProcessing,
-                               const char* pszColorFilename,
-                               const GDALDEMProcessingOptions *psOptionsIn,
-                               int *pbUsageError)
+GDALDatasetH GDALDEMProcessing( const char *pszDest,
+                                GDALDatasetH hSrcDataset,
+                                const char* pszProcessing,
+                                const char* pszColorFilename,
+                                const GDALDEMProcessingOptions *psOptionsIn,
+                                int *pbUsageError )
 {
     if( hSrcDataset == NULL )
     {
@@ -2506,51 +3291,64 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest,
         return NULL;
     }
 
+    if( psOptionsIn->bCombined && eUtilityMode != HILL_SHADE )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "-combined can only be used with hillshade");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
+
+    if( psOptionsIn->bMultiDirectional && eUtilityMode != HILL_SHADE )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "-multidirectional can only be used with hillshade");
+
+        if(pbUsageError)
+            *pbUsageError = TRUE;
+        return NULL;
+    }
 
     GDALDEMProcessingOptions* psOptionsToFree = NULL;
-    const GDALDEMProcessingOptions* psOptions;
-    if( psOptionsIn )
-        psOptions = psOptionsIn;
-    else
+    const GDALDEMProcessingOptions* psOptions = psOptionsIn;
+    if( !psOptions )
     {
         psOptionsToFree = GDALDEMProcessingOptionsNew(NULL, NULL);
         psOptions = psOptionsToFree;
     }
 
-    double  adfGeoTransform[6];
-
-    GDALDatasetH hDstDataset = NULL;
-    GDALRasterBandH hSrcBand = NULL;
-    GDALRasterBandH hDstBand = NULL;
-    GDALDriverH hDriver = NULL;
+    double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
 
-    int nXSize = GDALGetRasterXSize(hSrcDataset);
-    int nYSize = GDALGetRasterYSize(hSrcDataset);
+    const int nXSize = GDALGetRasterXSize(hSrcDataset);
+    const int nYSize = GDALGetRasterYSize(hSrcDataset);
 
-    if( psOptions->nBand <= 0 || psOptions->nBand > GDALGetRasterCount(hSrcDataset) )
+    if( psOptions->nBand <= 0 ||
+        psOptions->nBand > GDALGetRasterCount(hSrcDataset) )
     {
         CPLError(CE_Failure, CPLE_IllegalArg,
                  "Unable to fetch band #%d", psOptions->nBand );
         GDALDEMProcessingOptionsFree(psOptionsToFree);
         return NULL;
     }
-    hSrcBand = GDALGetRasterBand( hSrcDataset, psOptions->nBand );
+    GDALRasterBandH hSrcBand =
+        GDALGetRasterBand( hSrcDataset, psOptions->nBand );
 
     GDALGetGeoTransform(hSrcDataset, adfGeoTransform);
 
-    hDriver = GDALGetDriverByName(psOptions->pszFormat);
+    GDALDriverH hDriver = GDALGetDriverByName(psOptions->pszFormat);
     if( hDriver == NULL
         || (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
             GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) == NULL))
     {
-        int	iDr;
-
-        CPLError(CE_Failure, CPLE_AppDefined, "Output driver `%s' not recognised to have output support.",
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Output driver `%s' not recognised to have output support.",
                  psOptions->pszFormat );
         fprintf( stderr, "The following format drivers are configured\n"
-                "and support output:\n" );
+                 "and support output:\n" );
 
-        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        for( int iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
         {
             hDriver = GDALGetDriver(iDr);
 
@@ -2567,88 +3365,151 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest,
         return NULL;
     }
 
-    double dfDstNoDataValue = 0;
-    int bDstHasNoData = FALSE;
+    double dfDstNoDataValue = 0.0;
+    bool bDstHasNoData = false;
     void* pData = NULL;
-    GDALGeneric3x3ProcessingAlg pfnAlg = NULL;
+    GDALGeneric3x3ProcessingAlg<float>::type pfnAlgFloat = NULL;
+    GDALGeneric3x3ProcessingAlg<GInt32>::type pfnAlgInt32 = NULL;
+    GDALGeneric3x3ProcessingAlg_multisample<GInt32>::type pfnAlgInt32_multisample = NULL;
 
-    if (eUtilityMode == HILL_SHADE)
+    if( eUtilityMode == HILL_SHADE && psOptions->bMultiDirectional )
     {
         dfDstNoDataValue = 0;
-        bDstHasNoData = TRUE;
-        pData = GDALCreateHillshadeData   (adfGeoTransform,
-                                           psOptions->z,
-                                           psOptions->scale,
-                                           psOptions->alt,
-                                           psOptions->az,
-                                           psOptions->bZevenbergenThorne);
-        if (psOptions->bZevenbergenThorne)
-        {
-            if(!psOptions->bCombined)
-                pfnAlg = GDALHillshadeZevenbergenThorneAlg;
+        bDstHasNoData = true;
+        pData = GDALCreateHillshadeMultiDirectionalData(adfGeoTransform,
+                                                        psOptions->z,
+                                                        psOptions->scale,
+                                                        psOptions->alt,
+                                                        psOptions->bZevenbergenThorne);
+        if( psOptions->bZevenbergenThorne )
+        {
+            pfnAlgFloat = GDALHillshadeMultiDirectionalAlg<float, ZEVENBERGEN_THORNE>;
+            pfnAlgInt32 = GDALHillshadeMultiDirectionalAlg<GInt32, ZEVENBERGEN_THORNE>;
+        }
+        else
+        {
+            pfnAlgFloat = GDALHillshadeMultiDirectionalAlg<float, HORN>;
+            pfnAlgInt32 = GDALHillshadeMultiDirectionalAlg<GInt32, HORN>;
+        }
+    }
+    else if( eUtilityMode == HILL_SHADE )
+    {
+        dfDstNoDataValue = 0;
+        bDstHasNoData = true;
+        pData = GDALCreateHillshadeData(adfGeoTransform,
+                                        psOptions->z,
+                                        psOptions->scale,
+                                        psOptions->alt,
+                                        psOptions->az,
+                                        psOptions->bZevenbergenThorne);
+        if( psOptions->bZevenbergenThorne )
+        {
+            if( !psOptions->bCombined )
+            {
+                pfnAlgFloat = GDALHillshadeAlg<float, ZEVENBERGEN_THORNE>;
+                pfnAlgInt32 = GDALHillshadeAlg<GInt32, ZEVENBERGEN_THORNE>;
+            }
             else
-                pfnAlg = GDALHillshadeZevenbergenThorneCombinedAlg;
+            {
+                pfnAlgFloat = GDALHillshadeCombinedAlg<float, ZEVENBERGEN_THORNE>;
+                pfnAlgInt32 = GDALHillshadeCombinedAlg<GInt32, ZEVENBERGEN_THORNE>;
+            }
         }
         else
         {
-            if(!psOptions->bCombined)
-                pfnAlg = GDALHillshadeAlg;
+            if( !psOptions->bCombined )
+            {
+                if( adfGeoTransform[1] == -adfGeoTransform[5] )
+                {
+                    pfnAlgFloat = GDALHillshadeAlg_same_res<float>;
+                    pfnAlgInt32 = GDALHillshadeAlg_same_res<GInt32>;
+#ifdef HAVE_16_SSE_REG
+                    pfnAlgInt32_multisample =
+                                GDALHillshadeAlg_same_res_multisample<GInt32>;
+#endif
+                }
+                else
+                {
+                    pfnAlgFloat = GDALHillshadeAlg<float, HORN>;
+                    pfnAlgInt32 = GDALHillshadeAlg<GInt32, HORN>;
+                }
+            }
             else
-                pfnAlg = GDALHillshadeCombinedAlg;
+            {
+                pfnAlgFloat = GDALHillshadeCombinedAlg<float, HORN>;
+                pfnAlgInt32 = GDALHillshadeCombinedAlg<GInt32, HORN>;
+            }
         }
     }
-    else if (eUtilityMode == SLOPE)
+    else if( eUtilityMode == SLOPE )
     {
         dfDstNoDataValue = -9999;
-        bDstHasNoData = TRUE;
+        bDstHasNoData = true;
 
         pData = GDALCreateSlopeData(adfGeoTransform, psOptions->scale, psOptions->slopeFormat);
-        if (psOptions->bZevenbergenThorne)
-            pfnAlg = GDALSlopeZevenbergenThorneAlg;
+        if( psOptions->bZevenbergenThorne )
+        {
+            pfnAlgFloat = GDALSlopeZevenbergenThorneAlg<float>;
+            pfnAlgInt32 = GDALSlopeZevenbergenThorneAlg<GInt32>;
+        }
         else
-            pfnAlg = GDALSlopeHornAlg;
+        {
+            pfnAlgFloat = GDALSlopeHornAlg<float>;
+            pfnAlgInt32 = GDALSlopeHornAlg<GInt32>;
+        }
     }
 
-    else if (eUtilityMode == ASPECT)
+    else if( eUtilityMode == ASPECT )
     {
-        if (!psOptions->bZeroForFlat)
+        if( !psOptions->bZeroForFlat )
         {
             dfDstNoDataValue = -9999;
-            bDstHasNoData = TRUE;
+            bDstHasNoData = true;
         }
 
         pData = GDALCreateAspectData(psOptions->bAngleAsAzimuth);
-        if (psOptions->bZevenbergenThorne)
-            pfnAlg = GDALAspectZevenbergenThorneAlg;
+        if( psOptions->bZevenbergenThorne )
+        {
+            pfnAlgFloat = GDALAspectZevenbergenThorneAlg<float>;
+            pfnAlgInt32 = GDALAspectZevenbergenThorneAlg<GInt32>;
+        }
         else
-            pfnAlg = GDALAspectAlg;
+        {
+            pfnAlgFloat = GDALAspectAlg<float>;
+            pfnAlgInt32 = GDALAspectAlg<GInt32>;
+        }
     }
-    else if (eUtilityMode == TRI)
+    else if( eUtilityMode == TRI )
     {
         dfDstNoDataValue = -9999;
-        bDstHasNoData = TRUE;
-        pfnAlg = GDALTRIAlg;
+        bDstHasNoData = true;
+        pfnAlgFloat = GDALTRIAlg<float>;
+        pfnAlgInt32 = GDALTRIAlg<GInt32>;
     }
-    else if (eUtilityMode == TPI)
+    else if( eUtilityMode == TPI )
     {
         dfDstNoDataValue = -9999;
-        bDstHasNoData = TRUE;
-        pfnAlg = GDALTPIAlg;
+        bDstHasNoData = true;
+        pfnAlgFloat = GDALTPIAlg<float>;
+        pfnAlgInt32 = GDALTPIAlg<GInt32>;
     }
-    else if (eUtilityMode == ROUGHNESS)
+    else if( eUtilityMode == ROUGHNESS )
     {
         dfDstNoDataValue = -9999;
-        bDstHasNoData = TRUE;
-        pfnAlg = GDALRoughnessAlg;
+        bDstHasNoData = true;
+        pfnAlgFloat = GDALRoughnessAlg<float>;
+        pfnAlgInt32 = GDALRoughnessAlg<GInt32>;
     }
 
-    GDALDataType eDstDataType = (eUtilityMode == HILL_SHADE ||
-                                 eUtilityMode == COLOR_RELIEF) ? GDT_Byte :
-                                                               GDT_Float32;
+    const GDALDataType eDstDataType =
+        (eUtilityMode == HILL_SHADE ||
+         eUtilityMode == COLOR_RELIEF)
+        ? GDT_Byte
+        : GDT_Float32;
 
     if( EQUAL(psOptions->pszFormat, "VRT") )
     {
-        if (eUtilityMode == COLOR_RELIEF)
+        if( eUtilityMode == COLOR_RELIEF )
         {
             GDALGenerateVRTColorRelief(pszDest,
                                        hSrcDataset,
@@ -2695,7 +3556,8 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest,
         else
         {
             VSIStatBufL sStat;
-            if( VSIStatExL(pszDest, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
+            if( VSIStatExL(pszDest, &sStat,
+                           VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
                 S_ISFIFO(sStat.st_mode) )
             {
                 bForceUseIntermediateDataset = true;
@@ -2704,20 +3566,23 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest,
 #endif
     }
 
+    const GDALDataType eSrcDT = GDALGetRasterDataType(hSrcBand);
+
     if( GDALGetMetadataItem( hDriver, GDAL_DCAP_RASTER, NULL) != NULL &&
-        ((bForceUseIntermediateDataset || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL) &&
+        ((bForceUseIntermediateDataset ||
+          GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL) &&
          GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL) )
     {
-        GDALDatasetH hIntermediateDataset;
+        GDALDatasetH hIntermediateDataset = NULL;
 
-        if (eUtilityMode == COLOR_RELIEF)
+        if( eUtilityMode == COLOR_RELIEF )
         {
             GDALColorReliefDataset* poDS =
-                new GDALColorReliefDataset (hSrcDataset,
-                                            hSrcBand,
-                                            pszColorFilename,
-                                            psOptions->eColorSelectionMode,
-                                            psOptions->bAddAlpha);
+                new GDALColorReliefDataset(hSrcDataset,
+                                           hSrcBand,
+                                           pszColorFilename,
+                                           psOptions->eColorSelectionMode,
+                                           psOptions->bAddAlpha);
             if( !(poDS->InitOK()) )
             {
                 delete poDS;
@@ -2729,28 +3594,54 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest,
         }
         else
         {
-            GDALGeneric3x3Dataset* poDS =
-                new GDALGeneric3x3Dataset(hSrcDataset, hSrcBand,
-                                          eDstDataType,
-                                          bDstHasNoData,
-                                          dfDstNoDataValue,
-                                          pfnAlg,
-                                          pData,
-                                          psOptions->bComputeAtEdges);
-            if( !(poDS->InitOK()) )
+            if( eSrcDT == GDT_Byte ||
+                eSrcDT == GDT_Int16 ||
+                eSrcDT == GDT_UInt16 )
             {
-                delete poDS;
-                CPLFree(pData);
-                GDALDEMProcessingOptionsFree(psOptionsToFree);
-                return NULL;
+                GDALGeneric3x3Dataset<GInt32>* poDS =
+                    new GDALGeneric3x3Dataset<GInt32>(hSrcDataset, hSrcBand,
+                                            eDstDataType,
+                                            bDstHasNoData,
+                                            dfDstNoDataValue,
+                                            pfnAlgInt32,
+                                            pData,
+                                            psOptions->bComputeAtEdges);
+
+                if( !(poDS->InitOK()) )
+                {
+                    delete poDS;
+                    CPLFree(pData);
+                    GDALDEMProcessingOptionsFree(psOptionsToFree);
+                    return NULL;
+                }
+                hIntermediateDataset = (GDALDatasetH)poDS;
+            }
+            else
+            {
+                GDALGeneric3x3Dataset<float>* poDS =
+                    new GDALGeneric3x3Dataset<float>(hSrcDataset, hSrcBand,
+                                            eDstDataType,
+                                            bDstHasNoData,
+                                            dfDstNoDataValue,
+                                            pfnAlgFloat,
+                                            pData,
+                                            psOptions->bComputeAtEdges);
+
+                if( !(poDS->InitOK()) )
+                {
+                    delete poDS;
+                    CPLFree(pData);
+                    GDALDEMProcessingOptionsFree(psOptionsToFree);
+                    return NULL;
+                }
+                hIntermediateDataset = (GDALDatasetH)poDS;
             }
-            hIntermediateDataset = (GDALDatasetH)poDS;
         }
 
         GDALDatasetH hOutDS = GDALCreateCopy(
-                                 hDriver, pszDest, hIntermediateDataset,
-                                 TRUE, psOptions->papszCreateOptions,
-                                 pfnProgress, pProgressData );
+            hDriver, pszDest, hIntermediateDataset,
+            TRUE, psOptions->papszCreateOptions,
+            pfnProgress, pProgressData );
 
         GDALClose(hIntermediateDataset);
 
@@ -2760,19 +3651,19 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest,
         return hOutDS;
     }
 
-    int nDstBands;
-    if (eUtilityMode == COLOR_RELIEF)
-        nDstBands = (psOptions->bAddAlpha) ? 4 : 3;
-    else
-        nDstBands = 1;
+    const int nDstBands =
+        eUtilityMode == COLOR_RELIEF
+        ? ((psOptions->bAddAlpha) ? 4 : 3)
+        : 1;
 
-    hDstDataset = GDALCreate(   hDriver,
-                                pszDest,
-                                nXSize,
-                                nYSize,
-                                nDstBands,
-                                eDstDataType,
-                                psOptions->papszCreateOptions);
+    GDALDatasetH hDstDataset =
+        GDALCreate( hDriver,
+                    pszDest,
+                    nXSize,
+                    nYSize,
+                    nDstBands,
+                    eDstDataType,
+                    psOptions->papszCreateOptions );
 
     if( hDstDataset == NULL )
     {
@@ -2783,32 +3674,45 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest,
         return NULL;
     }
 
-    hDstBand = GDALGetRasterBand( hDstDataset, 1 );
+    GDALRasterBandH hDstBand = GDALGetRasterBand( hDstDataset, 1 );
 
     GDALSetGeoTransform(hDstDataset, adfGeoTransform);
     GDALSetProjection(hDstDataset, GDALGetProjectionRef(hSrcDataset));
 
-    if (eUtilityMode == COLOR_RELIEF)
+    if( eUtilityMode == COLOR_RELIEF )
     {
         GDALColorRelief (hSrcBand,
                          GDALGetRasterBand(hDstDataset, 1),
                          GDALGetRasterBand(hDstDataset, 2),
                          GDALGetRasterBand(hDstDataset, 3),
-                         (psOptions->bAddAlpha) ? GDALGetRasterBand(hDstDataset, 4) : NULL,
+                         psOptions->bAddAlpha ? GDALGetRasterBand(hDstDataset, 4) : NULL,
                          pszColorFilename,
                          psOptions->eColorSelectionMode,
                          pfnProgress, pProgressData);
     }
     else
     {
-        if (bDstHasNoData)
+        if( bDstHasNoData )
             GDALSetRasterNoDataValue(hDstBand, dfDstNoDataValue);
 
-        GDALGeneric3x3Processing(hSrcBand, hDstBand,
-                                 pfnAlg, pData,
-                                 psOptions->bComputeAtEdges,
-                                 pfnProgress, pProgressData);
-
+        if( eSrcDT == GDT_Byte || eSrcDT == GDT_Int16 || eSrcDT == GDT_UInt16 )
+        {
+            GDALGeneric3x3Processing<GInt32>(hSrcBand, hDstBand,
+                                             pfnAlgInt32,
+                                             pfnAlgInt32_multisample,
+                                             pData,
+                                             psOptions->bComputeAtEdges,
+                                             pfnProgress, pProgressData);
+        }
+        else
+        {
+            GDALGeneric3x3Processing<float>(hSrcBand, hDstBand,
+                                            pfnAlgFloat,
+                                            NULL,
+                                            pData,
+                                            psOptions->bComputeAtEdges,
+                                            pfnProgress, pProgressData);
+        }
     }
 
     CPLFree(pData);
@@ -2825,7 +3729,7 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest,
  * Allocates a GDALDEMProcessingOptions struct.
  *
  * @param papszArgv NULL terminated list of options (potentially including filename and open options too), or NULL.
- *                  The accepted options are the ones of the <a href="gdal_translate.html">gdal_translate</a> utility.
+ *                  The accepted options are the ones of the <a href="gdaldem.html">gdaldem</a> utility.
  * @param psOptionsForBinary (output) may be NULL (and should generally be NULL),
  *                           otherwise (gdal_translate_bin.cpp use case) must be allocated with
  *                           GDALDEMProcessingOptionsForBinaryNew() prior to this function. Will be
@@ -2835,10 +3739,13 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest,
  * @since GDAL 2.1
  */
 
-GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
-                                                      GDALDEMProcessingOptionsForBinary* psOptionsForBinary)
+GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(
+    char** papszArgv,
+    GDALDEMProcessingOptionsForBinary* psOptionsForBinary )
 {
-    GDALDEMProcessingOptions *psOptions = (GDALDEMProcessingOptions *) CPLCalloc( 1, sizeof(GDALDEMProcessingOptions) );
+    GDALDEMProcessingOptions *psOptions =
+        static_cast<GDALDEMProcessingOptions *>(
+            CPLCalloc(1, sizeof(GDALDEMProcessingOptions)));
     Algorithm eUtilityMode = INVALID;
 
     psOptions->pszFormat = CPLStrdup("GTiff");
@@ -2850,21 +3757,23 @@ GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
     psOptions->alt = 45.0;
     // 0 = 'percent' or 1 = 'degrees'
     psOptions->slopeFormat = 1;
-    psOptions->bAddAlpha = FALSE;
-    psOptions->bZeroForFlat = FALSE;
-    psOptions->bAngleAsAzimuth = TRUE;
+    psOptions->bAddAlpha = false;
+    psOptions->bZeroForFlat = false;
+    psOptions->bAngleAsAzimuth = true;
     psOptions->eColorSelectionMode = COLOR_SELECTION_INTERPOLATE;
-    psOptions->bComputeAtEdges = FALSE;
-    psOptions->bZevenbergenThorne = FALSE;
-    psOptions->bCombined = FALSE;
+    psOptions->bComputeAtEdges = false;
+    psOptions->bZevenbergenThorne = false;
+    psOptions->bCombined = false;
+    psOptions->bMultiDirectional = false;
     psOptions->nBand = 1;
     psOptions->papszCreateOptions = NULL;
+    bool bAzimuthSpecified = false;
 
 /* -------------------------------------------------------------------- */
 /*      Handle command line arguments.                                  */
 /* -------------------------------------------------------------------- */
     int argc = CSLCount(papszArgv);
-    for( int i = 0; i < argc; i++ )
+    for( int i = 0; papszArgv != NULL && i < argc; i++ )
     {
         if( i == 0 && psOptionsForBinary )
         {
@@ -2896,46 +3805,51 @@ GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
                 psOptionsForBinary->bQuiet = TRUE;
         }
 
-        else if( (EQUAL(papszArgv[i], "--z") || EQUAL(papszArgv[i], "-z")) && i+1<argc)
+        else if( (EQUAL(papszArgv[i], "--z") || EQUAL(papszArgv[i], "-z")) &&
+                 i + 1 < argc )
         {
             ++i;
             if( !ArgIsNumeric(papszArgv[i]) )
             {
-                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for -z");
+                CPLError(CE_Failure, CPLE_IllegalArg,
+                         "Numeric value expected for -z");
                 GDALDEMProcessingOptionsFree(psOptions);
                 return NULL;
             }
             psOptions->z = CPLAtof(papszArgv[i]);
         }
-        else if ( EQUAL(papszArgv[i], "-p") )
+        else if( EQUAL(papszArgv[i], "-p") )
         {
             psOptions->slopeFormat = 0;
         }
-        else if ( EQUAL(papszArgv[i], "-alg") && i+1<argc)
+        else if( EQUAL(papszArgv[i], "-alg") && i+1<argc )
         {
-            i ++;
-            if (EQUAL(papszArgv[i], "ZevenbergenThorne"))
-                psOptions->bZevenbergenThorne = TRUE;
-            else if (!EQUAL(papszArgv[i], "Horn"))
+            i++;
+            if( EQUAL(papszArgv[i], "ZevenbergenThorne") )
             {
-                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for %s", papszArgv[i-1]);
+                psOptions->bZevenbergenThorne = true;
+            }
+            else if( !EQUAL(papszArgv[i], "Horn") )
+            {
+                CPLError(CE_Failure, CPLE_IllegalArg,
+                         "Numeric value expected for %s", papszArgv[i-1]);
                 GDALDEMProcessingOptionsFree(psOptions);
                 return NULL;
             }
         }
-        else if ( EQUAL(papszArgv[i], "-trigonometric"))
+        else if( EQUAL(papszArgv[i], "-trigonometric") )
         {
-            psOptions->bAngleAsAzimuth = FALSE;
+            psOptions->bAngleAsAzimuth = false;
         }
-        else if ( EQUAL(papszArgv[i], "-zero_for_flat"))
+        else if( EQUAL(papszArgv[i], "-zero_for_flat") )
         {
-            psOptions->bZeroForFlat = TRUE;
+            psOptions->bZeroForFlat = true;
         }
-        else if ( EQUAL(papszArgv[i], "-exact_color_entry"))
+        else if( EQUAL(papszArgv[i], "-exact_color_entry") )
         {
             psOptions->eColorSelectionMode = COLOR_SELECTION_EXACT_ENTRY;
         }
-        else if ( EQUAL(papszArgv[i], "-nearest_color_entry"))
+        else if( EQUAL(papszArgv[i], "-nearest_color_entry") )
         {
             psOptions->eColorSelectionMode = COLOR_SELECTION_NEAREST_ENTRY;
         }
@@ -2949,7 +3863,8 @@ GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
             ++i;
             if( !ArgIsNumeric(papszArgv[i]) )
             {
-                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for %s", papszArgv[i-1]);
+                CPLError(CE_Failure, CPLE_IllegalArg,
+                         "Numeric value expected for %s", papszArgv[i-1]);
                 GDALDEMProcessingOptionsFree(psOptions);
                 return NULL;
             }
@@ -2965,23 +3880,26 @@ GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
             ++i;
             if( !ArgIsNumeric(papszArgv[i]) )
             {
-                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for %s", papszArgv[i-1]);
+                CPLError(CE_Failure, CPLE_IllegalArg,
+                         "Numeric value expected for %s", papszArgv[i-1]);
                 GDALDEMProcessingOptionsFree(psOptions);
                 return NULL;
             }
+            bAzimuthSpecified = true;
             psOptions->az = CPLAtof(papszArgv[i]);
         }
-        else if( eUtilityMode == HILL_SHADE &&
+        else if(
             (EQUAL(papszArgv[i], "--alt") ||
              EQUAL(papszArgv[i], "-alt") ||
-             EQUAL(papszArgv[i], "--alt") ||
-             EQUAL(papszArgv[i], "-alt")) && i+1<argc
+             EQUAL(papszArgv[i], "--altitude") ||
+             EQUAL(papszArgv[i], "-altitude")) && i+1<argc
           )
         {
             ++i;
             if( !ArgIsNumeric(papszArgv[i]) )
             {
-                CPLError(CE_Failure, CPLE_IllegalArg, "Numeric value expected for %s", papszArgv[i-1]);
+                CPLError(CE_Failure, CPLE_IllegalArg,
+                         "Numeric value expected for %s", papszArgv[i-1]);
                 GDALDEMProcessingOptionsFree(psOptions);
                 return NULL;
             }
@@ -2992,17 +3910,22 @@ GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
              EQUAL(papszArgv[i], "--combined"))
           )
         {
-            psOptions->bCombined = TRUE;
+            psOptions->bCombined = true;
+        }
+        else if( EQUAL(papszArgv[i], "-multidirectional") ||
+                 EQUAL(papszArgv[i], "--multidirectional") )
+        {
+            psOptions->bMultiDirectional = true;
         }
         else if(
                  EQUAL(papszArgv[i], "-alpha"))
         {
-            psOptions->bAddAlpha = TRUE;
+            psOptions->bAddAlpha = true;
         }
         else if(
                  EQUAL(papszArgv[i], "-compute_edges"))
         {
-            psOptions->bComputeAtEdges = TRUE;
+            psOptions->bComputeAtEdges = true;
         }
         else if( i + 1 < argc &&
             (EQUAL(papszArgv[i], "--b") ||
@@ -3013,7 +3936,8 @@ GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
         }
         else if( EQUAL(papszArgv[i],"-co") && i+1<argc )
         {
-            psOptions->papszCreateOptions = CSLAddString( psOptions->papszCreateOptions, papszArgv[++i] );
+            psOptions->papszCreateOptions =
+                CSLAddString( psOptions->papszCreateOptions, papszArgv[++i] );
         }
         else if( papszArgv[i][0] == '-' )
         {
@@ -3026,7 +3950,9 @@ GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
         {
             psOptionsForBinary->pszSrcFilename = CPLStrdup(papszArgv[i]);
         }
-        else if( psOptionsForBinary && eUtilityMode == COLOR_RELIEF && psOptionsForBinary->pszColorFilename == NULL )
+        else if( psOptionsForBinary &&
+                 eUtilityMode == COLOR_RELIEF &&
+                 psOptionsForBinary->pszColorFilename == NULL )
         {
             psOptionsForBinary->pszColorFilename = CPLStrdup(papszArgv[i]);
         }
@@ -3043,6 +3969,23 @@ GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
         }
     }
 
+    if( psOptions->bMultiDirectional &&
+        psOptions->bCombined)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "-multidirectional and -combined cannot be used together");
+        GDALDEMProcessingOptionsFree(psOptions);
+        return NULL;
+    }
+
+    if( psOptions->bMultiDirectional && bAzimuthSpecified )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "-multidirectional and -az cannot be used together");
+        GDALDEMProcessingOptionsFree(psOptions);
+        return NULL;
+    }
+
     if( psOptionsForBinary )
     {
         psOptionsForBinary->pszFormat = CPLStrdup(psOptions->pszFormat);
@@ -3063,7 +4006,7 @@ GDALDEMProcessingOptions *GDALDEMProcessingOptionsNew(char** papszArgv,
  * @since GDAL 2.1
  */
 
-void GDALDEMProcessingOptionsFree(GDALDEMProcessingOptions *psOptions)
+void GDALDEMProcessingOptionsFree( GDALDEMProcessingOptions *psOptions )
 {
     if( psOptions )
     {
@@ -3089,7 +4032,8 @@ void GDALDEMProcessingOptionsFree(GDALDEMProcessingOptions *psOptions)
  */
 
 void GDALDEMProcessingOptionsSetProgress( GDALDEMProcessingOptions *psOptions,
-                                      GDALProgressFunc pfnProgress, void *pProgressData )
+                                          GDALProgressFunc pfnProgress,
+                                          void *pProgressData )
 {
     psOptions->pfnProgress = pfnProgress;
     psOptions->pProgressData = pProgressData;
diff --git a/apps/gdalenhance.cpp b/apps/gdalenhance.cpp
index ad1701e..8ba5cf3 100644
--- a/apps/gdalenhance.cpp
+++ b/apps/gdalenhance.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalenhance.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line application to do image enhancement.
@@ -35,7 +34,9 @@
 #include "vrtdataset.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: gdalenhance.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: gdalenhance.cpp 36025 2016-10-29 13:37:48Z goatbar $");
 
 static int
 ComputeEqualizationLUTs( GDALDatasetH hDataset,  int nLUTBins,
@@ -85,12 +86,12 @@ static void Usage()
 int main( int argc, char ** argv )
 
 {
-    GDALDatasetH	hDataset, hOutDS;
-    int			i;
-    const char		*pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
+    GDALDatasetH        hDataset, hOutDS;
+    int                 i;
+    const char          *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
     int bFormatExplicitlySet = FALSE;
-    GDALDriverH		hDriver;
-    GDALDataType	eOutputType = GDT_Unknown;
+    GDALDriverH         hDriver;
+    GDALDataType        eOutputType = GDT_Unknown;
     char                **papszCreateOptions = NULL;
     GDALProgressFunc    pfnProgress = GDALTermProgress;
     int                 nLUTBins = 256;
@@ -556,8 +557,7 @@ ComputeEqualizationLUTs( GDALDatasetH hDataset, int nLUTBins,
             iHist = (iLUT * nHistSize) / nLUTBins;
             int nValue = (int) ((panCumHist[iHist] * nLUTBins) / nTotal);
 
-            panLUT[iLUT] = MAX(0,MIN(nLUTBins-1,nValue));
-
+            panLUT[iLUT] = std::max(0, std::min(nLUTBins - 1, nValue));
         }
 
         (*ppapanLUTs)[iBand] = panLUT;
@@ -615,8 +615,9 @@ static CPLErr EnhancerCallback( void *hCBData,
             continue;
         }
 
-        int iBin = (int) ((pafSrcImage[iPixel] - psEInfo->dfScaleMin)*dfScale);
-        iBin = MAX(0,MIN(psEInfo->nLUTBins-1,iBin));
+        int iBin = static_cast<int>(
+            (pafSrcImage[iPixel] - psEInfo->dfScaleMin) * dfScale);
+        iBin = std::max(0, std::min(psEInfo->nLUTBins - 1, iBin));
 
         if( psEInfo->panLUT )
             pabyOutImage[iPixel] = (GByte) psEInfo->panLUT[iBin];
diff --git a/apps/gdalflattenmask.c b/apps/gdalflattenmask.c
index 0b93575..62fa5d2 100644
--- a/apps/gdalflattenmask.c
+++ b/apps/gdalflattenmask.c
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalflattenmask.c $
  *
  * Project:  GDAL Utilities
  * Purpose:  GDAL mask flattening utility
@@ -31,6 +30,8 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
+CPL_CVSID("$Id: gdalflattenmask.c 36535 2016-11-27 23:49:35Z goatbar $");
+
 /************************************************************************/
 /*                               Usage()                                */
 /************************************************************************/
@@ -284,7 +285,7 @@ int main(int argc, char* argv[])
                     }
 
                     default:
-                        CPLAssert(0);
+                        CPLAssert(false);
                         break;
                 }
             }
@@ -306,7 +307,8 @@ int main(int argc, char* argv[])
         GDALRasterBandH hMaskBand = GDALGetMaskBand(hSrcBand);
         int nMaskFlag = GDALGetMaskFlags(hSrcBand);
 
-        int iCol, iLine;
+        int iCol;
+        int iLine;
         for(iLine = 0; iLine < nYSize; iLine++)
         {
             GDALRasterIO( hMaskBand, GF_Read, 0, iLine, nXSize, 1,
diff --git a/apps/gdalinfo_bin.cpp b/apps/gdalinfo_bin.cpp
index 66e06ab..17474d2 100644
--- a/apps/gdalinfo_bin.cpp
+++ b/apps/gdalinfo_bin.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalinfo_bin.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line application to list info about a file.
@@ -34,7 +33,7 @@
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdalinfo_bin.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: gdalinfo_bin.cpp 35931 2016-10-25 16:20:52Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -54,7 +53,6 @@ static void Usage(const char* pszErrorMsg = NULL)
     exit( 1 );
 }
 
-
 /************************************************************************/
 /*                         GDALInfoOptionsForBinary()                   */
 /************************************************************************/
@@ -207,7 +205,6 @@ int main( int argc, char ** argv )
                      "gdalinfo warning: subdataset %d of %d requested. "
                      "Reading the main dataset.\n",
                      psOptionsForBinary->nSubdataset, nSubdatasets );
-
         }
     }
 
@@ -237,5 +234,4 @@ int main( int argc, char ** argv )
     CPLCleanupTLS();
 
     exit( 0 );
-
 }
diff --git a/apps/gdalinfo_lib.cpp b/apps/gdalinfo_lib.cpp
index dc84056..7af3ba0 100644
--- a/apps/gdalinfo_lib.cpp
+++ b/apps/gdalinfo_lib.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalinfo_lib.cpp 36077 2016-11-02 12:41:41Z rouault $
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line application to list info about a file.
@@ -29,23 +28,38 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_utils.h"
+#include "gdal_utils_priv.h"
+
+#include <cmath>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include <string>
 #include <vector>
 
+#include "commonutils.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "gdal.h"
 #include "gdal_alg.h"
-#include "ogr_srs_api.h"
-#include "cpl_string.h"
-#include "cpl_conv.h"
-#include "commonutils.h"
-#include "json.h"
-#include "ogrgeojsonwriter.h"
-#include "gdal_utils_priv.h"
 #include "gdal_priv.h"
 #include "gdal_rat.h"
+#include "ogr_api.h"
+#include "ogr_json_header.h"
+#include "ogr_srs_api.h"
+#include "ogrgeojsonwriter.h"
 
 using std::vector;
 
-CPL_CVSID("$Id: gdalinfo_lib.cpp 36077 2016-11-02 12:41:41Z rouault $");
+CPL_CVSID("$Id: gdalinfo_lib.cpp 37502 2017-02-28 10:25:01Z rouault $");
 
 /*! output format */
 typedef enum {
@@ -57,8 +71,8 @@ typedef enum {
 /*                           GDALInfoOptions                            */
 /************************************************************************/
 
-/** Options for use with GDALInfo(). GDALInfoOptions* must be allocated and freed with GDALInfoOptionsNew() and
- * GDALInfoOptionsFree() respectively.
+/** Options for use with GDALInfo(). GDALInfoOptions* must be allocated and
+ * freed with GDALInfoOptionsNew() and GDALInfoOptionsFree() respectively.
  */
 struct GDALInfoOptions
 {
@@ -73,12 +87,14 @@ struct GDALInfoOptions
     /*! report a PROJ.4 string corresponding to the file's coordinate system */
     int bReportProj4;
 
-    /*! read and display image statistics. Force computation if no statistics are stored in an image */
+    /*! read and display image statistics. Force computation if no statistics
+        are stored in an image */
     int bStats;
 
-    /*! read and display image statistics. Force computation if no statistics are stored in an image.
-        However, they may be computed based on overviews or a subset of all tiles. Useful if you are
-        in a hurry and don't want precise stats. */
+    /*! read and display image statistics. Force computation if no statistics
+        are stored in an image.  However, they may be computed based on
+        overviews or a subset of all tiles. Useful if you are in a hurry and
+        don't want precise stats. */
     int bApproxStats;
 
     int bSample;
@@ -86,11 +102,13 @@ struct GDALInfoOptions
     /*! force computation of the checksum for each band in the dataset */
     int bComputeChecksum;
 
-    /*! allow or suppress ground control points list printing. It may be useful for datasets with huge amount
-        of GCPs, such as L1B AVHRR or HDF4 MODIS which contain thousands of them. */
+    /*! allow or suppress ground control points list printing. It may be useful
+        for datasets with huge amount of GCPs, such as L1B AVHRR or HDF4 MODIS
+        which contain thousands of them. */
     int bShowGCPs;
 
-    /*! allow or suppress metadata printing. Some datasets may contain a lot of metadata strings. */
+    /*! allow or suppress metadata printing. Some datasets may contain a lot of
+        metadata strings. */
     int bShowMetadata;
 
     /*! allow or suppress printing of raster attribute table */
@@ -105,26 +123,24 @@ struct GDALInfoOptions
     /*! display the file list or the first file of the file list */
     int bShowFileList;
 
-    /*! report metadata for the specified domains. "all" can be used to report metadata
-        in all domains.
+    /*! report metadata for the specified domains. "all" can be used to report
+        metadata in all domains.
         */
     char **papszExtraMDDomains;
 
     bool bStdoutOutput;
 };
 
-
 static int
 GDALInfoReportCorner( const GDALInfoOptions* psOptions,
                       GDALDatasetH hDataset,
                       OGRCoordinateTransformationH hTransform,
-                      OGRCoordinateTransformationH hTransformWGS84,
                       const char * corner_name,
                       double x,
                       double y,
                       bool bJson,
                       json_object *poCornerCoordinates,
-                      json_object *poWGS84ExtentCoordinates,
+                      json_object *poLongLatExtentCoordinates,
                       CPLString& osStr );
 
 static void
@@ -135,12 +151,11 @@ GDALInfoReportMetadata( const GDALInfoOptions* psOptions,
                         json_object *poMetadata,
                         CPLString& osStr );
 
+static void Concat( CPLString& osRet, bool bStdoutOutput,
+                    const char* pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (3, 4);
 
-static void Concat(CPLString& osRet, bool bStdoutOutput,
-                   const char* pszFormat, ...) CPL_PRINT_FUNC_FORMAT (3, 4);
-
-static void Concat(CPLString& osRet, bool bStdoutOutput,
-                   const char* pszFormat, ... )
+static void Concat( CPLString& osRet, bool bStdoutOutput,
+                    const char* pszFormat, ... )
 {
     va_list args;
     va_start( args, pszFormat );
@@ -199,7 +214,9 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
     }
 
     CPLString osStr;
-    json_object *poJsonObject = NULL, *poBands = NULL, *poMetadata = NULL;
+    json_object *poJsonObject = NULL;
+    json_object *poBands = NULL;
+    json_object *poMetadata = NULL;
 
     const bool bJson = psOptions->eFormat == GDALINFO_FORMAT_JSON;
 
@@ -207,18 +224,23 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
 /*      Report general info.                                            */
 /* -------------------------------------------------------------------- */
     GDALDriverH hDriver = GDALGetDatasetDriver( hDataset );
-    if(bJson)
+    if( bJson )
     {
-        json_object *poDescription = json_object_new_string(GDALGetDescription(hDataset));
-        json_object *poDriverShortName = json_object_new_string(GDALGetDriverShortName(hDriver));
-        json_object *poDriverLongName = json_object_new_string(GDALGetDriverLongName(hDriver));
+        json_object *poDescription =
+            json_object_new_string(GDALGetDescription(hDataset));
+        json_object *poDriverShortName =
+            json_object_new_string(GDALGetDriverShortName(hDriver));
+        json_object *poDriverLongName =
+            json_object_new_string(GDALGetDriverLongName(hDriver));
         poJsonObject = json_object_new_object();
         poBands = json_object_new_array();
         poMetadata = json_object_new_object();
 
         json_object_object_add(poJsonObject, "description", poDescription);
-        json_object_object_add(poJsonObject, "driverShortName", poDriverShortName);
-        json_object_object_add(poJsonObject, "driverLongName", poDriverLongName);
+        json_object_object_add(poJsonObject, "driverShortName",
+                               poDriverShortName);
+        json_object_object_add(poJsonObject, "driverLongName",
+                               poDriverLongName);
     }
     else
     {
@@ -231,26 +253,29 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
 
     if( papszFileList == NULL || *papszFileList == NULL )
     {
-        if(bJson)
+        if( bJson )
         {
             json_object *poFiles = json_object_new_array();
             json_object_object_add(poJsonObject, "files", poFiles);
         }
         else
+        {
             Concat( osStr, psOptions->bStdoutOutput,
                     "Files: none associated\n" );
+        }
     }
     else
     {
-        if(bJson)
+        if( bJson )
         {
             if( psOptions->bShowFileList )
             {
                 json_object *poFiles = json_object_new_array();
 
-                for(int i = 0; papszFileList[i] != NULL; i++)
+                for( int i = 0; papszFileList[i] != NULL; i++ )
                 {
-                    json_object *poFile = json_object_new_string(papszFileList[i]);
+                    json_object *poFile =
+                        json_object_new_string(papszFileList[i]);
 
                     json_object_array_add(poFiles, poFile);
                 }
@@ -260,30 +285,37 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         }
         else
         {
-            Concat(osStr, psOptions->bStdoutOutput, "Files: %s\n", papszFileList[0] );
+            Concat(osStr, psOptions->bStdoutOutput,
+                   "Files: %s\n", papszFileList[0] );
             if( psOptions->bShowFileList )
             {
                 for( int i = 1; papszFileList[i] != NULL; i++ )
-                    Concat(osStr, psOptions->bStdoutOutput, "       %s\n", papszFileList[i] );
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "       %s\n", papszFileList[i] );
             }
         }
-
     }
     CSLDestroy( papszFileList );
 
-    if(bJson)
+    if( bJson )
     {
         json_object *poSize = json_object_new_array();
-        json_object *poSizeX = json_object_new_int(GDALGetRasterXSize(hDataset));
-        json_object *poSizeY = json_object_new_int(GDALGetRasterYSize(hDataset));
+        json_object *poSizeX =
+            json_object_new_int(GDALGetRasterXSize(hDataset));
+        json_object *poSizeY =
+            json_object_new_int(GDALGetRasterYSize(hDataset));
 
         json_object_array_add(poSize, poSizeX);
         json_object_array_add(poSize, poSizeY);
         json_object_object_add(poJsonObject, "size", poSize);
     }
     else
-        Concat(osStr, psOptions->bStdoutOutput, "Size is %d, %d\n", GDALGetRasterXSize( hDataset ),
-            GDALGetRasterYSize( hDataset ) );
+    {
+        Concat(osStr, psOptions->bStdoutOutput,
+               "Size is %d, %d\n",
+               GDALGetRasterXSize( hDataset ),
+               GDALGetRasterYSize( hDataset ) );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Report projection.                                              */
@@ -292,43 +324,47 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
     {
         json_object *poCoordinateSystem = NULL;
 
-        if(bJson)
+        if( bJson )
             poCoordinateSystem = json_object_new_object();
 
-        char *pszProjection
-            = const_cast<char *>( GDALGetProjectionRef( hDataset ) );
+        char *pszProjection =
+            const_cast<char *>( GDALGetProjectionRef( hDataset ) );
 
-        OGRSpatialReferenceH hSRS
-            = OSRNewSpatialReference(NULL);
+        OGRSpatialReferenceH hSRS =
+            OSRNewSpatialReference(NULL);
         if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
         {
-            char    *pszPrettyWkt = NULL;
+            char *pszPrettyWkt = NULL;
 
             OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
 
-            if(bJson)
+            if( bJson )
             {
                 json_object *poWkt = json_object_new_string(pszPrettyWkt);
                 json_object_object_add(poCoordinateSystem, "wkt", poWkt);
             }
             else
+            {
                 Concat( osStr, psOptions->bStdoutOutput,
                         "Coordinate System is:\n%s\n",
                         pszPrettyWkt );
+            }
             CPLFree( pszPrettyWkt );
         }
         else
         {
-            if(bJson)
+            if( bJson )
             {
-                json_object *poWkt = json_object_new_string(GDALGetProjectionRef(hDataset));
+                json_object *poWkt =
+                    json_object_new_string(GDALGetProjectionRef(hDataset));
                 json_object_object_add(poCoordinateSystem, "wkt", poWkt);
             }
             else
+            {
                 Concat( osStr, psOptions->bStdoutOutput,
                         "Coordinate System is `%s'\n",
                         GDALGetProjectionRef( hDataset ) );
-
+            }
         }
 
         if ( psOptions->bReportProj4 )
@@ -336,18 +372,20 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
             char *pszProj4 = NULL;
             OSRExportToProj4( hSRS, &pszProj4 );
 
-            if(bJson)
+            if( bJson )
             {
                 json_object *proj4 = json_object_new_string(pszProj4);
                 json_object_object_add(poCoordinateSystem, "proj4", proj4);
             }
             else
-                Concat(osStr, psOptions->bStdoutOutput, "PROJ.4 string is:\n\'%s\'\n",pszProj4);
+                Concat(osStr, psOptions->bStdoutOutput,
+                       "PROJ.4 string is:\n\'%s\'\n",pszProj4);
             CPLFree( pszProj4 );
         }
 
-        if(bJson)
-            json_object_object_add(poJsonObject, "coordinateSystem", poCoordinateSystem);
+        if( bJson )
+            json_object_object_add(poJsonObject, "coordinateSystem",
+                                   poCoordinateSystem);
 
         OSRDestroySpatialReference( hSRS );
     }
@@ -355,20 +393,24 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
 /* -------------------------------------------------------------------- */
 /*      Report Geotransform.                                            */
 /* -------------------------------------------------------------------- */
-    double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+    double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
     if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
     {
-        if(bJson)
+        if( bJson )
         {
             json_object *poGeoTransform = json_object_new_array();
 
             for( int i = 0; i < 6; i++ )
             {
-                json_object *poGeoTransformCoefficient = json_object_new_double_with_precision(adfGeoTransform[i], 16);
-                json_object_array_add(poGeoTransform, poGeoTransformCoefficient);
+                json_object *poGeoTransformCoefficient =
+                    json_object_new_double_with_precision(adfGeoTransform[i],
+                                                          16);
+                json_object_array_add(poGeoTransform,
+                                      poGeoTransformCoefficient);
             }
 
-            json_object_object_add(poJsonObject, "geoTransform", poGeoTransform);
+            json_object_object_add(poJsonObject, "geoTransform",
+                                   poGeoTransform);
         }
         else
         {
@@ -383,6 +425,7 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                         adfGeoTransform[1], adfGeoTransform[5] );
             }
             else
+            {
                 Concat( osStr, psOptions->bStdoutOutput, "GeoTransform =\n"
                         "  %.16g, %.16g, %.16g\n"
                         "  %.16g, %.16g, %.16g\n",
@@ -392,8 +435,8 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                         adfGeoTransform[3],
                         adfGeoTransform[4],
                         adfGeoTransform[5] );
+            }
         }
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -407,17 +450,17 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         {
             json_object *poGCPCoordinateSystem = NULL;
 
-            char *pszProjection
-                = const_cast<char *>( GDALGetGCPProjection( hDataset ) );
+            char *pszProjection =
+                const_cast<char *>( GDALGetGCPProjection( hDataset ) );
 
-            OGRSpatialReferenceH hSRS
-                = OSRNewSpatialReference(NULL);
+            OGRSpatialReferenceH hSRS =
+                OSRNewSpatialReference(NULL);
             if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
             {
-                char    *pszPrettyWkt = NULL;
+                char *pszPrettyWkt = NULL;
 
                 OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
-                if(bJson)
+                if( bJson )
                 {
                     json_object *poWkt = json_object_new_string(pszPrettyWkt);
                     poGCPCoordinateSystem = json_object_new_object();
@@ -425,26 +468,33 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                     json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
                 }
                 else
-                    Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = \n%s\n", pszPrettyWkt );
+                {
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "GCP Projection = \n%s\n", pszPrettyWkt );
+                }
                 CPLFree( pszPrettyWkt );
             }
             else
             {
                 if(bJson)
                 {
-                    json_object *poWkt = json_object_new_string(GDALGetGCPProjection(hDataset));
+                    json_object *poWkt =
+                        json_object_new_string(GDALGetGCPProjection(hDataset));
                     poGCPCoordinateSystem = json_object_new_object();
 
                     json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt);
                 }
                 else
-                    Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = %s\n",
-                        GDALGetGCPProjection( hDataset ) );
-
+                {
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "GCP Projection = %s\n",
+                           GDALGetGCPProjection( hDataset ) );
+                }
             }
 
             if(bJson)
-                json_object_object_add(poGCPs, "coordinateSystem", poGCPCoordinateSystem);
+                json_object_object_add(poGCPs, "coordinateSystem",
+                                       poGCPCoordinateSystem);
             OSRDestroySpatialReference( hSRS );
         }
 
@@ -453,16 +503,22 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         for( int i = 0; i < GDALGetGCPCount(hDataset); i++ )
         {
             const GDAL_GCP *psGCP = GDALGetGCPs( hDataset ) + i;
-            if(bJson)
+            if( bJson )
             {
                 json_object *poGCP = json_object_new_object();
                 json_object *poId = json_object_new_string(psGCP->pszId);
                 json_object *poInfo = json_object_new_string(psGCP->pszInfo);
-                json_object *poPixel = json_object_new_double_with_precision(psGCP->dfGCPPixel, 15);
-                json_object *poLine = json_object_new_double_with_precision(psGCP->dfGCPLine, 15);
-                json_object *poX = json_object_new_double_with_precision(psGCP->dfGCPX, 15);
-                json_object *poY = json_object_new_double_with_precision(psGCP->dfGCPY, 15);
-                json_object *poZ = json_object_new_double_with_precision(psGCP->dfGCPZ, 15);
+                json_object *poPixel =
+                    json_object_new_double_with_precision(psGCP->dfGCPPixel,
+                                                          15);
+                json_object *poLine =
+                    json_object_new_double_with_precision(psGCP->dfGCPLine, 15);
+                json_object *poX =
+                    json_object_new_double_with_precision(psGCP->dfGCPX, 15);
+                json_object *poY =
+                    json_object_new_double_with_precision(psGCP->dfGCPY, 15);
+                json_object *poZ =
+                    json_object_new_double_with_precision(psGCP->dfGCPZ, 15);
 
                 json_object_object_add(poGCP, "id", poId);
                 json_object_object_add(poGCP, "info", poInfo);
@@ -474,13 +530,16 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                 json_object_array_add(poGCPList, poGCP);
             }
             else
-                Concat(osStr, psOptions->bStdoutOutput, "GCP[%3d]: Id=%s, Info=%s\n"
-                    "          (%.15g,%.15g) -> (%.15g,%.15g,%.15g)\n",
+            {
+                Concat(osStr, psOptions->bStdoutOutput,
+                       "GCP[%3d]: Id=%s, Info=%s\n"
+                       "          (%.15g,%.15g) -> (%.15g,%.15g,%.15g)\n",
                     i, psGCP->pszId, psGCP->pszInfo,
                     psGCP->dfGCPPixel, psGCP->dfGCPLine,
                     psGCP->dfGCPX, psGCP->dfGCPY, psGCP->dfGCPZ );
+            }
         }
-        if(bJson)
+        if( bJson )
         {
             json_object_object_add(poGCPs, "gcpList", poGCPList);
             json_object_object_add(poJsonObject, "gcps", poGCPs);
@@ -491,8 +550,9 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
 /*      Report metadata.                                                */
 /* -------------------------------------------------------------------- */
 
-    GDALInfoReportMetadata( psOptions, hDataset, false, bJson, poMetadata, osStr );
-    if(bJson)
+    GDALInfoReportMetadata( psOptions, hDataset, false,
+                            bJson, poMetadata, osStr );
+    if( bJson )
     {
         if( psOptions->bShowMetadata )
             json_object_object_add( poJsonObject, "metadata", poMetadata );
@@ -508,21 +568,28 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         pszProjection = GDALGetProjectionRef(hDataset);
 
     OGRCoordinateTransformationH hTransform = NULL;
-    OGRCoordinateTransformationH hTransformWGS84 = NULL;
+    bool bTransformToWGS84 = false;
 
     if( pszProjection != NULL && strlen(pszProjection) > 0 )
     {
-        OGRSpatialReferenceH hProj, hLatLong = NULL, hLatLongWGS84 = NULL;
+        OGRSpatialReferenceH hLatLong = NULL;
 
-        hProj = OSRNewSpatialReference( pszProjection );
+        OGRSpatialReferenceH hProj = OSRNewSpatialReference( pszProjection );
         if( hProj != NULL )
         {
-            hLatLong = OSRCloneGeogCS( hProj );
-
-            if(bJson)
+            OGRErr eErr = OGRERR_NONE;
+            // Check that it looks like Earth before trying to reproject to wgs84...
+            if(bJson &&
+               fabs( OSRGetSemiMajor(hProj, &eErr) - 6378137.0) < 10000.0 &&
+               eErr == OGRERR_NONE )
+            {
+                bTransformToWGS84 = true;
+                hLatLong = OSRNewSpatialReference( NULL );
+                OSRSetWellKnownGeogCS( hLatLong, "WGS84" );
+            }
+            else
             {
-                hLatLongWGS84 = OSRNewSpatialReference( NULL );
-                OSRSetWellKnownGeogCS( hLatLongWGS84, "WGS84" );
+                hLatLong = OSRCloneGeogCS( hProj );
             }
         }
 
@@ -535,15 +602,6 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
             OSRDestroySpatialReference( hLatLong );
         }
 
-        if( hLatLongWGS84 != NULL )
-        {
-            CPLPushErrorHandler( CPLQuietErrorHandler );
-            hTransformWGS84 = OCTNewCoordinateTransformation( hProj, hLatLongWGS84 );
-            CPLPopErrorHandler();
-
-            OSRDestroySpatialReference( hLatLongWGS84 );
-        }
-
         if( hProj != NULL )
             OSRDestroySpatialReference( hProj );
     }
@@ -551,51 +609,77 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
 /* -------------------------------------------------------------------- */
 /*      Report corners.                                                 */
 /* -------------------------------------------------------------------- */
-    if(bJson)
+    if( bJson )
     {
         json_object *poLinearRing = json_object_new_array();
         json_object *poCornerCoordinates = json_object_new_object();
-        json_object *poWGS84Extent = json_object_new_object();
-        json_object *poWGS84ExtentType = json_object_new_string("Polygon");
-        json_object *poWGS84ExtentCoordinates = json_object_new_array();
-
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperLeft",
-                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerLeft",
-                              0.0, GDALGetRasterYSize(hDataset), bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "lowerRight",
-                              GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset),
-                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperRight",
-                              GDALGetRasterXSize(hDataset), 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "center",
-                              GDALGetRasterXSize(hDataset)/2.0, GDALGetRasterYSize(hDataset)/2.0,
-                              bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "upperLeft",
-                              0.0, 0.0, bJson, poCornerCoordinates, poWGS84ExtentCoordinates, osStr );
-
-        json_object_object_add( poJsonObject, "cornerCoordinates", poCornerCoordinates );
-        json_object_object_add( poWGS84Extent, "type", poWGS84ExtentType );
-        json_object_array_add( poLinearRing, poWGS84ExtentCoordinates );
-        json_object_object_add( poWGS84Extent, "coordinates", poLinearRing );
-        json_object_object_add( poJsonObject, "wgs84Extent", poWGS84Extent );
+        json_object *poLongLatExtent = json_object_new_object();
+        json_object *poLongLatExtentType = json_object_new_string("Polygon");
+        json_object *poLongLatExtentCoordinates = json_object_new_array();
+
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "upperLeft",
+                              0.0, 0.0, bJson, poCornerCoordinates,
+                              poLongLatExtentCoordinates, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "lowerLeft",
+                              0.0, GDALGetRasterYSize(hDataset), bJson,
+                              poCornerCoordinates, poLongLatExtentCoordinates,
+                              osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "lowerRight",
+                              GDALGetRasterXSize(hDataset),
+                              GDALGetRasterYSize(hDataset),
+                              bJson, poCornerCoordinates,
+                              poLongLatExtentCoordinates, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "upperRight",
+                              GDALGetRasterXSize(hDataset), 0.0, bJson,
+                              poCornerCoordinates, poLongLatExtentCoordinates,
+                              osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "center",
+                              GDALGetRasterXSize(hDataset) / 2.0,
+                              GDALGetRasterYSize(hDataset) / 2.0,
+                              bJson, poCornerCoordinates,
+                              poLongLatExtentCoordinates, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "upperLeft",
+                              0.0, 0.0, bJson, poCornerCoordinates,
+                              poLongLatExtentCoordinates, osStr );
+
+        json_object_object_add( poJsonObject, "cornerCoordinates",
+                                poCornerCoordinates );
+        json_object_object_add( poLongLatExtent, "type", poLongLatExtentType );
+        json_object_array_add( poLinearRing, poLongLatExtentCoordinates );
+        json_object_object_add( poLongLatExtent, "coordinates", poLinearRing );
+        json_object_object_add( poJsonObject,
+                bTransformToWGS84 ? "wgs84Extent": "extent", poLongLatExtent );
     }
     else
     {
         Concat(osStr, psOptions->bStdoutOutput, "Corner Coordinates:\n" );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Upper Left",
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "Upper Left",
                               0.0, 0.0, bJson, NULL, NULL, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Lower Left",
-                              0.0, GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Upper Right",
-                              GDALGetRasterXSize(hDataset), 0.0, bJson, NULL, NULL, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Lower Right",
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "Lower Left",
+                              0.0, GDALGetRasterYSize(hDataset), bJson,
+                              NULL, NULL, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "Upper Right",
+                              GDALGetRasterXSize(hDataset), 0.0, bJson,
+                              NULL, NULL, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "Lower Right",
                               GDALGetRasterXSize(hDataset),
-                              GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr );
-        GDALInfoReportCorner( psOptions, hDataset, hTransform, hTransformWGS84, "Center",
+                              GDALGetRasterYSize(hDataset), bJson,
+                              NULL, NULL, osStr );
+        GDALInfoReportCorner( psOptions, hDataset, hTransform,
+                              "Center",
                               GDALGetRasterXSize(hDataset)/2.0,
-                              GDALGetRasterYSize(hDataset)/2.0, bJson, NULL, NULL, osStr );
-
+                              GDALGetRasterYSize(hDataset)/2.0, bJson,
+                              NULL, NULL, osStr );
     }
 
     if( hTransform != NULL )
@@ -604,12 +688,6 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         hTransform = NULL;
     }
 
-    if( hTransformWGS84 != NULL )
-    {
-        OCTDestroyCoordinateTransformation( hTransformWGS84 );
-        hTransformWGS84 = NULL;
-    }
-
 /* ==================================================================== */
 /*      Loop over bands.                                                */
 /* ==================================================================== */
@@ -618,7 +696,7 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         json_object *poBand = NULL;
         json_object *poBandMetadata = NULL;
 
-        if(bJson)
+        if( bJson )
         {
             poBand = json_object_new_object();
             poBandMetadata = json_object_new_object();
@@ -632,7 +710,7 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
             float * const pafSample = &ofSample[0];
             const int nCount =
                 GDALGetRandomRasterSample( hBand, 10000, pafSample );
-            if(!bJson)
+            if( !bJson )
                 Concat( osStr, psOptions->bStdoutOutput,
                         "Got %d samples.\n", nCount );
         }
@@ -640,42 +718,53 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         int nBlockXSize = 0;
         int nBlockYSize = 0;
         GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
-        if(bJson)
+        if( bJson )
         {
             json_object *poBandNumber = json_object_new_int(iBand+1);
             json_object *poBlock = json_object_new_array();
-            json_object *poType = json_object_new_string(GDALGetDataTypeName(GDALGetRasterDataType(hBand)));
-            json_object *poColorInterp = json_object_new_string(GDALGetColorInterpretationName(
-                GDALGetRasterColorInterpretation(hBand)));
+            json_object *poType =
+                json_object_new_string(
+                    GDALGetDataTypeName(GDALGetRasterDataType(hBand)));
+            json_object *poColorInterp =
+                json_object_new_string(
+                    GDALGetColorInterpretationName(
+                        GDALGetRasterColorInterpretation(hBand)));
 
             json_object_array_add(poBlock, json_object_new_int(nBlockXSize));
             json_object_array_add(poBlock, json_object_new_int(nBlockYSize));
             json_object_object_add(poBand, "band", poBandNumber);
             json_object_object_add(poBand, "block", poBlock);
             json_object_object_add(poBand, "type", poType);
-            json_object_object_add(poBand, "colorInterpretation", poColorInterp);
+            json_object_object_add(poBand, "colorInterpretation",
+                                   poColorInterp);
         }
         else
+        {
             Concat( osStr, psOptions->bStdoutOutput,
                     "Band %d Block=%dx%d Type=%s, ColorInterp=%s\n",
-                    iBand+1,
+                    iBand + 1,
                     nBlockXSize, nBlockYSize,
                     GDALGetDataTypeName(
                         GDALGetRasterDataType(hBand)),
                     GDALGetColorInterpretationName(
                         GDALGetRasterColorInterpretation(hBand)) );
+        }
 
         if( GDALGetDescription( hBand ) != NULL
             && strlen(GDALGetDescription( hBand )) > 0 )
         {
             if(bJson)
             {
-                json_object *poBandDescription = json_object_new_string(GDALGetDescription(hBand));
-                json_object_object_add(poBand, "description", poBandDescription);
+                json_object *poBandDescription =
+                    json_object_new_string(GDALGetDescription(hBand));
+                json_object_object_add(poBand, "description",
+                                       poBandDescription);
             }
             else
+            {
                 Concat( osStr, psOptions->bStdoutOutput, "  Description = %s\n",
                         GDALGetDescription(hBand) );
+            }
         }
 
         {
@@ -685,27 +774,35 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
             const double dfMax = GDALGetRasterMaximum( hBand, &bGotMax );
             if( bGotMin || bGotMax || psOptions->bComputeMinMax )
             {
-                if(!bJson)
+                if( !bJson )
                     Concat(osStr, psOptions->bStdoutOutput, "  " );
                 if( bGotMin )
                 {
-                    if(bJson)
+                    if( bJson )
                     {
-                        json_object *poMin = json_object_new_double_with_precision(dfMin, 3);
+                        json_object *poMin =
+                            json_object_new_double_with_precision(dfMin, 3);
                         json_object_object_add(poBand, "min", poMin);
                     }
                     else
-                        Concat(osStr, psOptions->bStdoutOutput, "Min=%.3f ", dfMin );
+                    {
+                        Concat(osStr, psOptions->bStdoutOutput,
+                               "Min=%.3f ", dfMin );
+                    }
                 }
                 if( bGotMax )
                 {
-                    if(bJson)
+                    if( bJson )
                     {
-                        json_object *poMax = json_object_new_double_with_precision(dfMax, 3);
+                        json_object *poMax =
+                            json_object_new_double_with_precision(dfMax, 3);
                         json_object_object_add(poBand, "max", poMax);
                     }
                     else
-                        Concat(osStr, psOptions->bStdoutOutput, "Max=%.3f ", dfMax );
+                    {
+                        Concat(osStr, psOptions->bStdoutOutput,
+                               "Max=%.3f ", dfMax );
+                    }
                 }
 
                 if( psOptions->bComputeMinMax )
@@ -713,18 +810,27 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                     CPLErrorReset();
                     double adfCMinMax[2] = {0.0, 0.0};
                     GDALComputeRasterMinMax( hBand, FALSE, adfCMinMax );
-                    if (CPLGetLastErrorType() == CE_None)
+                    if( CPLGetLastErrorType() == CE_None )
                     {
-                        if(bJson)
+                        if( bJson )
                         {
-                            json_object *poComputedMin = json_object_new_double_with_precision(adfCMinMax[0], 3);
-                            json_object *poComputedMax = json_object_new_double_with_precision(adfCMinMax[1], 3);
-                            json_object_object_add(poBand, "computedMin", poComputedMin);
-                            json_object_object_add(poBand, "computedMax", poComputedMax);
+                            json_object *poComputedMin =
+                                json_object_new_double_with_precision(
+                                    adfCMinMax[0], 3);
+                            json_object *poComputedMax =
+                                json_object_new_double_with_precision(
+                                    adfCMinMax[1], 3);
+                            json_object_object_add(poBand, "computedMin",
+                                                   poComputedMin);
+                            json_object_object_add(poBand, "computedMax",
+                                                   poComputedMax);
                         }
                         else
-                            Concat(osStr, psOptions->bStdoutOutput, "  Computed Min/Max=%.3f,%.3f",
-                              adfCMinMax[0], adfCMinMax[1] );
+                        {
+                            Concat(osStr, psOptions->bStdoutOutput,
+                                   "  Computed Min/Max=%.3f,%.3f",
+                                   adfCMinMax[0], adfCMinMax[1] );
+                        }
                     }
                 }
                 if(!bJson)
@@ -742,12 +848,16 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                                                &dfMean, &dfStdDev );
         if( eErr == CE_None )
         {
-            if(bJson)
+            if( bJson )
             {
-                json_object *poMinimum = json_object_new_double_with_precision(dfMinStat, 3);
-                json_object *poMaximum = json_object_new_double_with_precision(dfMaxStat, 3);
-                json_object *poMean = json_object_new_double_with_precision(dfMean, 3);
-                json_object *poStdDev = json_object_new_double_with_precision(dfStdDev, 3);
+                json_object *poMinimum =
+                    json_object_new_double_with_precision(dfMinStat, 3);
+                json_object *poMaximum =
+                    json_object_new_double_with_precision(dfMaxStat, 3);
+                json_object *poMean =
+                    json_object_new_double_with_precision(dfMean, 3);
+                json_object *poStdDev =
+                    json_object_new_double_with_precision(dfStdDev, 3);
 
                 json_object_object_add(poBand, "minimum", poMinimum);
                 json_object_object_add(poBand, "maximum", poMaximum);
@@ -755,16 +865,19 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                 json_object_object_add(poBand, "stdDev", poStdDev);
             }
             else
-                Concat(osStr, psOptions->bStdoutOutput, "  Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n",
-                    dfMinStat, dfMaxStat, dfMean, dfStdDev );
+            {
+                Concat(osStr, psOptions->bStdoutOutput,
+                       "  Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n",
+                       dfMinStat, dfMaxStat, dfMean, dfStdDev );
+            }
         }
 
         if( psOptions->bReportHistograms )
         {
-            int nBucketCount;
+            int nBucketCount = 0;
             GUIntBig *panHistogram = NULL;
 
-            if(bJson)
+            if( bJson )
                 eErr = GDALGetDefaultHistogramEx( hBand, &dfMinStat, &dfMaxStat,
                                                   &nBucketCount, &panHistogram,
                                                   TRUE, GDALDummyProgress,
@@ -776,9 +889,10 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                                                   NULL );
             if( eErr == CE_None )
             {
-                json_object *poHistogram = NULL, *poBuckets = NULL;
+                json_object *poHistogram = NULL;
+                json_object *poBuckets = NULL;
 
-                if(bJson)
+                if( bJson )
                 {
                     json_object *poCount = json_object_new_int(nBucketCount);
                     json_object *poMin = json_object_new_double(dfMinStat);
@@ -791,67 +905,87 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                     json_object_object_add(poHistogram, "max", poMax);
                 }
                 else
-                    Concat(osStr, psOptions->bStdoutOutput, "  %d buckets from %g to %g:\n  ",
-                        nBucketCount, dfMinStat, dfMaxStat );
+                {
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "  %d buckets from %g to %g:\n  ",
+                           nBucketCount, dfMinStat, dfMaxStat );
+                }
 
                 for( int iBucket = 0; iBucket < nBucketCount; iBucket++ )
                 {
                     if(bJson)
                     {
-                        json_object *poBucket = json_object_new_int64(panHistogram[iBucket]);
+                        json_object *poBucket =
+                            json_object_new_int64(panHistogram[iBucket]);
                         json_object_array_add(poBuckets, poBucket);
                     }
                     else
-                        Concat(osStr, psOptions->bStdoutOutput, CPL_FRMT_GUIB " ", panHistogram[iBucket] );
+                        Concat(osStr, psOptions->bStdoutOutput,
+                               CPL_FRMT_GUIB " ", panHistogram[iBucket] );
                 }
-                if(bJson)
+                if( bJson )
                 {
                     json_object_object_add(poHistogram, "buckets", poBuckets);
                     json_object_object_add(poBand, "histogram", poHistogram);
                 }
                 else
+                {
                     Concat(osStr, psOptions->bStdoutOutput, "\n" );
+                }
                 CPLFree( panHistogram );
             }
         }
 
         if ( psOptions->bComputeChecksum)
         {
-            int nBandChecksum = GDALChecksumImage(hBand, 0, 0,
-                                      GDALGetRasterXSize(hDataset),
-                                      GDALGetRasterYSize(hDataset));
-            if(bJson)
+            const int nBandChecksum =
+                GDALChecksumImage(hBand, 0, 0,
+                                  GDALGetRasterXSize(hDataset),
+                                  GDALGetRasterYSize(hDataset));
+            if( bJson )
             {
                 json_object *poChecksum = json_object_new_int(nBandChecksum);
                 json_object_object_add(poBand, "checksum", poChecksum);
             }
             else
-                Concat(osStr, psOptions->bStdoutOutput, "  Checksum=%d\n", nBandChecksum );
+            {
+                Concat(osStr, psOptions->bStdoutOutput,
+                       "  Checksum=%d\n", nBandChecksum );
+            }
         }
 
         int bGotNodata = FALSE;
         const double dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata );
         if( bGotNodata )
         {
-            if (CPLIsNan(dfNoData))
+            if( CPLIsNan(dfNoData) )
             {
-                if(bJson)
+                if( bJson )
                 {
                     json_object *poNoDataValue = json_object_new_string("nan");
-                    json_object_object_add(poBand, "noDataValue", poNoDataValue);
+                    json_object_object_add(poBand, "noDataValue",
+                                           poNoDataValue);
                 }
                 else
-                    Concat(osStr, psOptions->bStdoutOutput, "  NoData Value=nan\n" );
+                {
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "  NoData Value=nan\n" );
+                }
             }
             else
             {
                 if(bJson)
                 {
-                    json_object *poNoDataValue = json_object_new_double_with_precision(dfNoData, 18);
-                    json_object_object_add(poBand, "noDataValue", poNoDataValue);
+                    json_object *poNoDataValue =
+                        json_object_new_double_with_precision(dfNoData, 18);
+                    json_object_object_add(poBand, "noDataValue",
+                                           poNoDataValue);
                 }
                 else
-                    Concat(osStr, psOptions->bStdoutOutput, "  NoData Value=%.18g\n", dfNoData );
+                {
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "  NoData Value=%.18g\n", dfNoData );
+                }
             }
         }
 
@@ -859,7 +993,7 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         {
             json_object *poOverviews = NULL;
 
-            if(bJson)
+            if( bJson )
                 poOverviews = json_object_new_array();
             else
                 Concat(osStr, psOptions->bStdoutOutput, "  Overviews: " );
@@ -868,7 +1002,7 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                  iOverview < GDALGetOverviewCount(hBand);
                  iOverview++ )
             {
-                if(!bJson)
+                if( !bJson )
                     if( iOverview != 0 )
                         Concat(osStr, psOptions->bStdoutOutput, ", " );
 
@@ -878,39 +1012,54 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                     if(bJson)
                     {
                         json_object *poOverviewSize = json_object_new_array();
-                        json_object *poOverviewSizeX = json_object_new_int( GDALGetRasterBandXSize( hOverview) );
-                        json_object *poOverviewSizeY = json_object_new_int( GDALGetRasterBandYSize( hOverview) );
+                        json_object *poOverviewSizeX =
+                            json_object_new_int(
+                                GDALGetRasterBandXSize( hOverview) );
+                        json_object *poOverviewSizeY =
+                            json_object_new_int(
+                                GDALGetRasterBandYSize( hOverview) );
 
                         json_object *poOverview = json_object_new_object();
-                        json_object_array_add( poOverviewSize, poOverviewSizeX );
-                        json_object_array_add( poOverviewSize, poOverviewSizeY );
-                        json_object_object_add( poOverview, "size", poOverviewSize );
+                        json_object_array_add( poOverviewSize,
+                                               poOverviewSizeX );
+                        json_object_array_add( poOverviewSize,
+                                               poOverviewSizeY );
+                        json_object_object_add( poOverview, "size",
+                                                poOverviewSize );
 
                         if(psOptions->bComputeChecksum)
                         {
-                            int nOverviewChecksum = GDALChecksumImage(hOverview, 0, 0,
-                                        GDALGetRasterBandXSize(hOverview),
-                                        GDALGetRasterBandYSize(hOverview));
-                            json_object *poOverviewChecksum = json_object_new_int(nOverviewChecksum);
-                            json_object_object_add(poOverview, "checksum", poOverviewChecksum);
+                            const int nOverviewChecksum =
+                                GDALChecksumImage(
+                                    hOverview, 0, 0,
+                                    GDALGetRasterBandXSize(hOverview),
+                                    GDALGetRasterBandYSize(hOverview));
+                            json_object *poOverviewChecksum =
+                                json_object_new_int(nOverviewChecksum);
+                            json_object_object_add(poOverview, "checksum",
+                                                   poOverviewChecksum);
                         }
                         json_object_array_add(poOverviews, poOverview);
                     }
                     else
+                    {
                         Concat(osStr, psOptions->bStdoutOutput, "%dx%d",
                             GDALGetRasterBandXSize( hOverview ),
                             GDALGetRasterBandYSize( hOverview ) );
+                    }
 
-                    const char *pszResampling
-                        = GDALGetMetadataItem( hOverview, "RESAMPLING", "" );
+                    const char *pszResampling =
+                         GDALGetMetadataItem( hOverview, "RESAMPLING", "" );
 
                     if( pszResampling != NULL && !bJson
                         && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
                         Concat(osStr, psOptions->bStdoutOutput, "*" );
                 }
                 else
+                {
                     if(!bJson)
                         Concat(osStr, psOptions->bStdoutOutput, "(null)" );
+                }
             }
             if(bJson)
                 json_object_object_add(poBand, "overviews", poOverviews);
@@ -919,7 +1068,8 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
 
             if ( psOptions->bComputeChecksum && !bJson )
             {
-                Concat(osStr, psOptions->bStdoutOutput, "  Overviews checksum: " );
+                Concat(osStr, psOptions->bStdoutOutput,
+                       "  Overviews checksum: " );
 
                 for( int iOverview = 0;
                      iOverview < GDALGetOverviewCount(hBand);
@@ -949,14 +1099,17 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
 
         if( GDALHasArbitraryOverviews( hBand ) && !bJson )
         {
-            Concat(osStr, psOptions->bStdoutOutput, "  Overviews: arbitrary\n" );
+            Concat(osStr, psOptions->bStdoutOutput,
+                   "  Overviews: arbitrary\n" );
         }
 
         const int nMaskFlags = GDALGetMaskFlags( hBand );
         if( (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 )
         {
             GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand) ;
-            json_object *poMask = NULL, *poFlags = NULL, *poMaskOverviews = NULL;
+            json_object *poMask = NULL;
+            json_object *poFlags = NULL;
+            json_object *poMaskOverviews = NULL;
 
             if(bJson)
             {
@@ -969,7 +1122,8 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
             {
                 if(bJson)
                 {
-                    json_object *poFlag = json_object_new_string( "PER_DATASET" );
+                    json_object *poFlag =
+                        json_object_new_string( "PER_DATASET" );
                     json_object_array_add( poFlags, poFlag );
                 }
                 else
@@ -993,7 +1147,9 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                     json_object_array_add( poFlags, poFlag );
                 }
                 else
+                {
                     Concat(osStr, psOptions->bStdoutOutput, "NODATA " );
+                }
             }
             if( nMaskFlags & GMF_ALL_VALID )
             {
@@ -1017,7 +1173,8 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                 GDALGetOverviewCount(hMaskBand) > 0 )
             {
                 if(!bJson)
-                    Concat(osStr, psOptions->bStdoutOutput, "  Overviews of mask band: " );
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "  Overviews of mask band: " );
 
                 for( int iOverview = 0;
                      iOverview < GDALGetOverviewCount(hMaskBand);
@@ -1042,21 +1199,28 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                     if(bJson)
                     {
                         json_object *poMaskOverviewSizeX =
-                            json_object_new_int(GDALGetRasterBandXSize(hOverview));
+                            json_object_new_int(
+                                GDALGetRasterBandXSize(hOverview));
                         json_object *poMaskOverviewSizeY =
-                            json_object_new_int(GDALGetRasterBandYSize(hOverview));
-
-                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeX);
-                        json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeY);
-                        json_object_object_add(poMaskOverview, "size", poMaskOverviewSize);
+                            json_object_new_int(
+                                GDALGetRasterBandYSize(hOverview));
+
+                        json_object_array_add(poMaskOverviewSize,
+                                              poMaskOverviewSizeX);
+                        json_object_array_add(poMaskOverviewSize,
+                                              poMaskOverviewSizeY);
+                        json_object_object_add(poMaskOverview, "size",
+                                               poMaskOverviewSize);
                         json_object_array_add(poMaskOverviews, poMaskOverview);
                     }
                     else
+                    {
                         Concat( osStr, psOptions->bStdoutOutput, "%dx%d",
                                 GDALGetRasterBandXSize( hOverview ),
                                 GDALGetRasterBandYSize( hOverview ) );
+                    }
                 }
-                if(!bJson)
+                if( !bJson )
                     Concat(osStr, psOptions->bStdoutOutput, "\n" );
             }
             if(bJson)
@@ -1068,13 +1232,17 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
 
         if( strlen(GDALGetRasterUnitType(hBand)) > 0 )
         {
-            if(bJson)
+            if( bJson )
             {
-                json_object *poUnit = json_object_new_string(GDALGetRasterUnitType(hBand));
+                json_object *poUnit =
+                    json_object_new_string(GDALGetRasterUnitType(hBand));
                 json_object_object_add(poBand, "unit", poUnit);
             }
             else
-                Concat(osStr, psOptions->bStdoutOutput, "  Unit Type: %s\n", GDALGetRasterUnitType(hBand) );
+            {
+                Concat(osStr, psOptions->bStdoutOutput,
+                       "  Unit Type: %s\n", GDALGetRasterUnitType(hBand) );
+            }
         }
 
         if( GDALGetRasterCategoryNames(hBand) != NULL )
@@ -1082,7 +1250,7 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
             char **papszCategories = GDALGetRasterCategoryNames(hBand);
             json_object *poCategories = NULL;
 
-            if(bJson)
+            if( bJson )
                 poCategories = json_object_new_array();
             else
                 Concat(osStr, psOptions->bStdoutOutput, "  Categories:\n" );
@@ -1091,11 +1259,13 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
             {
                 if(bJson)
                 {
-                    json_object *poCategoryName = json_object_new_string(papszCategories[i]);
+                    json_object *poCategoryName =
+                        json_object_new_string(papszCategories[i]);
                     json_object_array_add(poCategories, poCategoryName);
                 }
                 else
-                    Concat(osStr, psOptions->bStdoutOutput, "    %3d: %s\n", i, papszCategories[i] );
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "    %3d: %s\n", i, papszCategories[i] );
             }
             if(bJson)
                 json_object_object_add(poBand, "categories", poCategories);
@@ -1105,7 +1275,7 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         if( GDALGetRasterScale( hBand, &bSuccess ) != 1.0
             || GDALGetRasterOffset( hBand, &bSuccess ) != 0.0 )
         {
-            if(bJson)
+            if( bJson )
             {
                 json_object *poOffset = json_object_new_double_with_precision(
                     GDALGetRasterOffset(hBand, &bSuccess), 15);
@@ -1115,13 +1285,17 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                 json_object_object_add(poBand, "scale", poScale);
             }
             else
-                Concat(osStr, psOptions->bStdoutOutput, "  Offset: %.15g,   Scale:%.15g\n",
+            {
+                Concat(osStr, psOptions->bStdoutOutput,
+                       "  Offset: %.15g,   Scale:%.15g\n",
                     GDALGetRasterOffset( hBand, &bSuccess ),
                     GDALGetRasterScale( hBand, &bSuccess ) );
+            }
         }
 
-        GDALInfoReportMetadata( psOptions, hBand, true, bJson, poBandMetadata, osStr );
-        if(bJson)
+        GDALInfoReportMetadata( psOptions, hBand, true, bJson,
+                                poBandMetadata, osStr );
+        if( bJson )
         {
             if (psOptions->bShowMetadata)
                 json_object_object_add( poBand, "metadata", poBandMetadata );
@@ -1133,7 +1307,7 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex
             && (hTable = GDALGetRasterColorTable( hBand )) != NULL )
         {
-            if(!bJson)
+            if( !bJson )
                 Concat( osStr, psOptions->bStdoutOutput,
                         "  Color Table (%s with %d entries)\n",
                         GDALGetPaletteInterpretationName(
@@ -1144,11 +1318,13 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
             {
                 json_object *poEntries = NULL;
 
-                if(bJson)
+                if( bJson )
                 {
-                    json_object *poPalette = json_object_new_string(GDALGetPaletteInterpretationName(
-                        GDALGetPaletteInterpretation(hTable)));
-                    json_object *poCount = json_object_new_int(GDALGetColorEntryCount(hTable));
+                    json_object *poPalette =
+                        json_object_new_string(GDALGetPaletteInterpretationName(
+                            GDALGetPaletteInterpretation(hTable)));
+                    json_object *poCount =
+                        json_object_new_int(GDALGetColorEntryCount(hTable));
 
                     json_object *poColorTable = json_object_new_object();
 
@@ -1162,7 +1338,7 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
 
                 for( int i = 0; i < GDALGetColorEntryCount( hTable ); i++ )
                 {
-                    GDALColorEntry  sEntry;
+                    GDALColorEntry sEntry;
 
                     GDALGetColorEntryAsRGB( hTable, i, &sEntry );
 
@@ -1181,12 +1357,15 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
                         json_object_array_add(poEntries, poEntry);
                     }
                     else
-                        Concat(osStr, psOptions->bStdoutOutput, "  %3d: %d,%d,%d,%d\n",
-                            i,
-                            sEntry.c1,
-                            sEntry.c2,
-                            sEntry.c3,
-                            sEntry.c4 );
+                    {
+                        Concat(osStr, psOptions->bStdoutOutput,
+                               "  %3d: %d,%d,%d,%d\n",
+                               i,
+                               sEntry.c1,
+                               sEntry.c2,
+                               sEntry.c3,
+                               sEntry.c4 );
+                    }
                 }
             }
         }
@@ -1195,14 +1374,16 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
         {
             GDALRasterAttributeTableH hRAT = GDALGetDefaultRAT( hBand );
 
-            if(bJson)
+            if( bJson )
             {
-                json_object *poRAT = (json_object*) GDALRATSerializeJSON( hRAT );
+                json_object *poRAT =
+                    (json_object*) GDALRATSerializeJSON( hRAT );
                 json_object_object_add( poJsonObject, "rat", poRAT );
             }
             else
             {
-                CPLXMLNode *psTree = ((GDALRasterAttributeTable *) hRAT)->Serialize();
+                CPLXMLNode *psTree =
+                    ((GDALRasterAttributeTable *) hRAT)->Serialize();
                 char *pszXMLText = CPLSerializeXMLTree( psTree );
                 CPLDestroyXMLNode( psTree );
                 Concat(osStr, psOptions->bStdoutOutput, "%s\n", pszXMLText );
@@ -1216,7 +1397,9 @@ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions )
     if(bJson)
     {
         json_object_object_add(poJsonObject, "bands", poBands);
-        Concat(osStr, psOptions->bStdoutOutput, "%s", json_object_to_json_string_ext(poJsonObject, JSON_C_TO_STRING_PRETTY));
+        Concat(osStr, psOptions->bStdoutOutput, "%s",
+               json_object_to_json_string_ext(poJsonObject,
+                                              JSON_C_TO_STRING_PRETTY));
         json_object_put(poJsonObject);
     }
 
@@ -1234,13 +1417,12 @@ static int
 GDALInfoReportCorner( const GDALInfoOptions* psOptions,
                       GDALDatasetH hDataset,
                       OGRCoordinateTransformationH hTransform,
-                      OGRCoordinateTransformationH hTransformWGS84,
                       const char * corner_name,
                       double x,
                       double y,
                       bool bJson,
                       json_object *poCornerCoordinates,
-                      json_object *poWGS84ExtentCoordinates,
+                      json_object *poLongLatExtentCoordinates,
                       CPLString& osStr )
 
 {
@@ -1266,47 +1448,64 @@ GDALInfoReportCorner( const GDALInfoOptions* psOptions,
         if( bJson )
         {
             json_object * const poCorner = json_object_new_array();
-            json_object * const poX = json_object_new_double_with_precision( x, 1 );
-            json_object * const poY = json_object_new_double_with_precision( y, 1 );
+            json_object * const poX =
+                json_object_new_double_with_precision( x, 1 );
+            json_object * const poY =
+                json_object_new_double_with_precision( y, 1 );
             json_object_array_add( poCorner, poX );
             json_object_array_add( poCorner, poY );
-            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
+            json_object_object_add( poCornerCoordinates, corner_name,
+                                    poCorner );
         }
         else
+        {
             Concat(osStr, psOptions->bStdoutOutput, "(%7.1f,%7.1f)\n", x, y );
+        }
         return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Report the georeferenced coordinates.                           */
 /* -------------------------------------------------------------------- */
-    if( ABS(dfGeoX) < 181 && ABS(dfGeoY) < 91 )
+    if( std::abs(dfGeoX) < 181 && std::abs(dfGeoY) < 91 )
     {
         if(bJson)
         {
             json_object * const poCorner = json_object_new_array();
-            json_object * const poX = json_object_new_double_with_precision( dfGeoX, 7 );
-            json_object * const poY = json_object_new_double_with_precision( dfGeoY, 7 );
+            json_object * const poX =
+                json_object_new_double_with_precision( dfGeoX, 7 );
+            json_object * const poY =
+                json_object_new_double_with_precision( dfGeoY, 7 );
             json_object_array_add( poCorner, poX );
             json_object_array_add( poCorner, poY );
-            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
+            json_object_object_add( poCornerCoordinates, corner_name,
+                                    poCorner );
         }
         else
-            Concat(osStr, psOptions->bStdoutOutput, "(%12.7f,%12.7f) ", dfGeoX, dfGeoY );
+        {
+            Concat(osStr, psOptions->bStdoutOutput,
+                   "(%12.7f,%12.7f) ", dfGeoX, dfGeoY );
+        }
     }
     else
     {
         if(bJson)
         {
             json_object * const poCorner = json_object_new_array();
-            json_object * const poX = json_object_new_double_with_precision( dfGeoX, 3 );
-            json_object * const poY = json_object_new_double_with_precision( dfGeoY, 3 );
+            json_object * const poX =
+                json_object_new_double_with_precision( dfGeoX, 3 );
+            json_object * const poY =
+                json_object_new_double_with_precision( dfGeoY, 3 );
             json_object_array_add( poCorner, poX );
             json_object_array_add( poCorner, poY );
-            json_object_object_add( poCornerCoordinates, corner_name, poCorner );
+            json_object_object_add( poCornerCoordinates, corner_name,
+                                    poCorner );
         }
         else
-            Concat(osStr, psOptions->bStdoutOutput, "(%12.3f,%12.3f) ", dfGeoX, dfGeoY );
+        {
+            Concat(osStr, psOptions->bStdoutOutput,
+                   "(%12.3f,%12.3f) ", dfGeoX, dfGeoY );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1315,15 +1514,17 @@ GDALInfoReportCorner( const GDALInfoOptions* psOptions,
     if(bJson)
     {
         double dfZ = 0.0;
-        if( hTransformWGS84 != NULL && !EQUAL( corner_name, "center" )
-        && OCTTransform(hTransformWGS84,1,&dfGeoX,&dfGeoY,&dfZ) )
+        if( hTransform != NULL && !EQUAL( corner_name, "center" )
+        && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,&dfZ) )
         {
             json_object * const poCorner = json_object_new_array();
-            json_object * const poX = json_object_new_double_with_precision( dfGeoX, 7 );
-            json_object * const poY = json_object_new_double_with_precision( dfGeoY, 7 );
+            json_object * const poX =
+                json_object_new_double_with_precision( dfGeoX, 7 );
+            json_object * const poY =
+                json_object_new_double_with_precision( dfGeoY, 7 );
             json_object_array_add( poCorner, poX );
             json_object_array_add( poCorner, poY );
-            json_object_array_add( poWGS84ExtentCoordinates , poCorner );
+            json_object_array_add( poLongLatExtentCoordinates , poCorner );
         }
     }
     else
@@ -1332,8 +1533,10 @@ GDALInfoReportCorner( const GDALInfoOptions* psOptions,
         if( hTransform != NULL
         && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,&dfZ) )
         {
-            Concat(osStr, psOptions->bStdoutOutput, "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) );
-            Concat(osStr, psOptions->bStdoutOutput, "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) );
+            Concat(osStr, psOptions->bStdoutOutput,
+                   "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) );
+            Concat(osStr, psOptions->bStdoutOutput,
+                   "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) );
         }
         Concat(osStr, psOptions->bStdoutOutput, "\n" );
     }
@@ -1341,7 +1544,6 @@ GDALInfoReportCorner( const GDALInfoOptions* psOptions,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                       GDALInfoPrintMetadata()                        */
 /************************************************************************/
@@ -1350,22 +1552,25 @@ static void GDALInfoPrintMetadata( const GDALInfoOptions* psOptions,
                                    const char *pszDomain,
                                    const char *pszDisplayedname,
                                    const char *pszIndent,
-                                   int bJson,
+                                   int bJsonOutput,
                                    json_object *poMetadata,
                                    CPLString& osStr )
 {
-    bool bIsxml = false;
-
-    if (pszDomain != NULL && STARTS_WITH_CI(pszDomain, "xml:"))
-        bIsxml = true;
+    const bool bIsxml =
+        pszDomain != NULL &&
+        STARTS_WITH_CI(pszDomain, "xml:");
+    const bool bMDIsJson =
+        pszDomain != NULL &&
+        STARTS_WITH_CI(pszDomain, "json:");
 
     char **papszMetadata = GDALGetMetadata( hObject, pszDomain );
     if( papszMetadata != NULL && *papszMetadata != NULL )
     {
         json_object *poDomain =
-            (bJson && !bIsxml) ? json_object_new_object() : NULL;
+            (bJsonOutput && !bIsxml && !bMDIsJson) ?
+                                            json_object_new_object() : NULL;
 
-        if(!bJson)
+        if( !bJsonOutput )
             Concat( osStr, psOptions->bStdoutOutput, "%s%s:\n", pszIndent,
                     pszDisplayedname );
 
@@ -1373,13 +1578,28 @@ static void GDALInfoPrintMetadata( const GDALInfoOptions* psOptions,
 
         for( int i = 0; papszMetadata[i] != NULL; i++ )
         {
-            if(bJson)
+            if( bJsonOutput )
             {
-                if(bIsxml)
+                if( bIsxml )
                 {
                     poValue = json_object_new_string( papszMetadata[i] );
                     break;
                 }
+                else if( bMDIsJson )
+                {
+                    json_tokener* jstok = json_tokener_new();
+                    poValue = json_tokener_parse_ex(jstok, papszMetadata[i], -1);
+                    if( jstok->err != json_tokener_success)
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                    "JSon parsing error: %s (at offset %d)",
+                                    json_tokener_error_desc(jstok->err),
+                                    jstok->char_offset);
+                        poValue = NULL;
+                    }
+                    json_tokener_free(jstok);
+                    break;
+                }
                 else
                 {
                     char *pszKey = NULL;
@@ -1395,17 +1615,20 @@ static void GDALInfoPrintMetadata( const GDALInfoOptions* psOptions,
             }
             else
             {
-                if (bIsxml)
-                    Concat(osStr, psOptions->bStdoutOutput, "%s%s\n", pszIndent, papszMetadata[i] );
+                if (bIsxml || bMDIsJson)
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "%s%s\n", pszIndent, papszMetadata[i] );
                 else
-                    Concat(osStr, psOptions->bStdoutOutput, "%s  %s\n", pszIndent, papszMetadata[i] );
-
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "%s  %s\n", pszIndent, papszMetadata[i] );
             }
         }
-        if(bJson)
+        if(bJsonOutput)
         {
-            if(bIsxml)
+            if(bIsxml || bMDIsJson)
+            {
                 json_object_object_add( poMetadata, pszDomain, poValue );
+            }
             else
             {
                 if(pszDomain == NULL)
@@ -1415,7 +1638,6 @@ static void GDALInfoPrintMetadata( const GDALInfoOptions* psOptions,
             }
         }
     }
-
 }
 
 /************************************************************************/
@@ -1442,31 +1664,34 @@ static void GDALInfoReportMetadata( const GDALInfoOptions* psOptions,
 
         if( papszMDDList != NULL )
         {
-            if(!bJson)
-                Concat(osStr, psOptions->bStdoutOutput, "%sMetadata domains:\n", pszIndent );
+            if( !bJson )
+                Concat(osStr, psOptions->bStdoutOutput,
+                       "%sMetadata domains:\n", pszIndent );
         }
 
         while( papszIter != NULL && *papszIter != NULL )
         {
             if( EQUAL(*papszIter, "") )
             {
-                if(bJson)
+                if( bJson )
                     poMDD = json_object_new_string( *papszIter );
                 else
-                    Concat(osStr, psOptions->bStdoutOutput, "%s  (default)\n", pszIndent);
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "%s  (default)\n", pszIndent);
             }
             else
             {
-                if(bJson)
+                if( bJson )
                     poMDD = json_object_new_string( *papszIter );
                 else
-                    Concat(osStr, psOptions->bStdoutOutput, "%s  %s\n", pszIndent, *papszIter );
+                    Concat(osStr, psOptions->bStdoutOutput,
+                           "%s  %s\n", pszIndent, *papszIter );
             }
-            if(bJson)
+            if( bJson )
                 json_object_array_add( poListMDD, poMDD );
             papszIter ++;
         }
-        if(bJson)
+        if( bJson )
             json_object_object_add( poMetadata, "metadataDomains", poListMDD );
         CSLDestroy(papszMDDList);
     }
@@ -1477,12 +1702,14 @@ static void GDALInfoReportMetadata( const GDALInfoOptions* psOptions,
     /* -------------------------------------------------------------------- */
     /*      Report default Metadata domain.                                 */
     /* -------------------------------------------------------------------- */
-    GDALInfoPrintMetadata( psOptions, hObject, NULL, "Metadata", pszIndent, bJson, poMetadata, osStr );
+    GDALInfoPrintMetadata( psOptions, hObject, NULL, "Metadata",
+                           pszIndent, bJson, poMetadata, osStr );
 
     /* -------------------------------------------------------------------- */
     /*      Report extra Metadata domains                                   */
     /* -------------------------------------------------------------------- */
-    if (psOptions->papszExtraMDDomains != NULL) {
+    if( psOptions->papszExtraMDDomains != NULL )
+    {
         char **papszExtraMDDomainsExpanded = NULL;
 
         if( EQUAL(psOptions->papszExtraMDDomains[0], "all") &&
@@ -1508,7 +1735,8 @@ static void GDALInfoReportMetadata( const GDALInfoOptions* psOptions,
         }
         else
         {
-            papszExtraMDDomainsExpanded = CSLDuplicate(psOptions->papszExtraMDDomains);
+            papszExtraMDDomainsExpanded =
+                CSLDuplicate(psOptions->papszExtraMDDomains);
         }
 
         for( int iMDD = 0; papszExtraMDDomainsExpanded != NULL &&
@@ -1546,11 +1774,13 @@ static void GDALInfoReportMetadata( const GDALInfoOptions* psOptions,
 
     if (!bIsBand)
     {
-        GDALInfoPrintMetadata( psOptions, hObject, "SUBDATASETS", "Subdatasets", pszIndent, bJson, poMetadata, osStr );
-        GDALInfoPrintMetadata( psOptions, hObject, "GEOLOCATION", "Geolocation", pszIndent, bJson, poMetadata, osStr );
-        GDALInfoPrintMetadata( psOptions, hObject, "RPC", "RPC Metadata", pszIndent, bJson, poMetadata, osStr );
+        GDALInfoPrintMetadata( psOptions, hObject, "SUBDATASETS", "Subdatasets",
+                               pszIndent, bJson, poMetadata, osStr );
+        GDALInfoPrintMetadata( psOptions, hObject, "GEOLOCATION", "Geolocation",
+                               pszIndent, bJson, poMetadata, osStr );
+        GDALInfoPrintMetadata( psOptions, hObject, "RPC", "RPC Metadata",
+                               pszIndent, bJson, poMetadata, osStr );
     }
-
 }
 
 /************************************************************************/
@@ -1571,8 +1801,9 @@ static void GDALInfoReportMetadata( const GDALInfoOptions* psOptions,
  * @since GDAL 2.1
  */
 
-GDALInfoOptions *GDALInfoOptionsNew(char** papszArgv,
-                                    GDALInfoOptionsForBinary* psOptionsForBinary)
+GDALInfoOptions *GDALInfoOptionsNew(
+    char** papszArgv,
+    GDALInfoOptionsForBinary* psOptionsForBinary )
 {
     bool bGotFilename = false;
     GDALInfoOptions *psOptions = static_cast<GDALInfoOptions *>(
diff --git a/apps/gdallocationinfo.cpp b/apps/gdallocationinfo.cpp
index d62c904..9012180 100644
--- a/apps/gdallocationinfo.cpp
+++ b/apps/gdallocationinfo.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdallocationinfo.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Command line raster query tool.
@@ -34,7 +33,7 @@
 #include "cpl_minixml.h"
 #include <vector>
 
-CPL_CVSID("$Id: gdallocationinfo.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: gdallocationinfo.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /******************************************************************************/
 /*! \page gdallocationinfo gdallocationinfo
@@ -58,7 +57,7 @@ Usage: gdallocationinfo [--help-general] [-xml] [-lifonly] [-valonly]
 
 <p>
 The gdallocationinfo utility provide a mechanism to query information about
-a pixel given it's location in one of a variety of coordinate systems.  Several
+a pixel given its location in one of a variety of coordinate systems.  Several
 reporting options are provided.
 
 <p>
@@ -331,7 +330,7 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      If no bands were requested, we will query them all.             */
 /* -------------------------------------------------------------------- */
-    if( anBandList.size() == 0 )
+    if( anBandList.empty() )
     {
         for( int i = 0; i < GDALGetRasterCount( hSrcDS ); i++ )
             anBandList.push_back( i+1 );
@@ -603,7 +602,6 @@ int main( int argc, char ** argv )
         {
             inputAvailable = 0;
         }
-
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/apps/gdalmanage.cpp b/apps/gdalmanage.cpp
index 8ab462c..3c9850d 100644
--- a/apps/gdalmanage.cpp
+++ b/apps/gdalmanage.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalmanage.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line utility for GDAL identify, delete, rename and copy
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: gdalmanage.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: gdalmanage.cpp 34654 2016-07-14 05:53:06Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
diff --git a/apps/gdalserver.c b/apps/gdalserver.c
index 326f122..ae7ec4c 100644
--- a/apps/gdalserver.c
+++ b/apps/gdalserver.c
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalserver.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Server application that is forked by libgdal
@@ -87,7 +86,7 @@ int  CPL_DLL  GDALServerLoopInstanceRunIteration(void* pInstance);
 void CPL_DLL  GDALServerLoopInstanceDestroy(void* pInstance);
 CPL_C_END
 
-CPL_CVSID("$Id: gdalserver.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gdalserver.c 36420 2016-11-21 23:13:06Z rouault $");
 
 static int bVerbose = FALSE;
 
@@ -122,6 +121,7 @@ static void Usage(const char* pszErrorMsg)
     printf("\n");
 
     if( pszErrorMsg != NULL )
+        // cppcheck-suppress nullPointer
         fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
 
     exit( 1 );
@@ -191,6 +191,8 @@ static CPL_SOCKET CreateSocketAndBindAndListen(const char* pszService,
 
     struct sockaddr_in sockAddrIn;
 
+    memset( &sockAddrIn, 0, sizeof(sockAddrIn) );
+
     if( pnFamily )   *pnFamily = AF_INET;
     if( pnSockType ) *pnSockType = SOCK_STREAM;
     if( pnProtocol ) *pnProtocol = IPPROTO_TCP;
@@ -441,6 +443,7 @@ static int RunServer(CPL_UNUSED const char* pszApplication,
     {
         struct sockaddr_un sockAddrUnix;
         int len;
+        memset( &sockAddrUnix, 0, sizeof(sockAddrUnix) );
 
         nListenSocket = socket(AF_UNIX, SOCK_STREAM, 0);
         if (nListenSocket < 0)
@@ -485,6 +488,8 @@ static int RunServer(CPL_UNUSED const char* pszApplication,
         fd_set read_fds;
         int nMaxSocket;
 
+        memset(&tv, 0, sizeof(tv));
+
         /* Select on the listen socket, and rip zombie children every second */
         do
         {
diff --git a/apps/gdalsrsinfo.cpp b/apps/gdalsrsinfo.cpp
index db094be..892014b 100644
--- a/apps/gdalsrsinfo.cpp
+++ b/apps/gdalsrsinfo.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line application to list info about a given CRS.
@@ -37,7 +36,7 @@
 #include "ogrsf_frmts.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: gdalsrsinfo.cpp 36537 2016-11-27 23:51:56Z goatbar $");
 
 bool FindSRS( const char *pszInput, OGRSpatialReference &oSRS );
 CPLErr PrintSRS( const OGRSpatialReference &oSRS,
@@ -78,14 +77,14 @@ static void Usage(const char* pszErrorMsg = NULL)
     exit( 1 );
 }
 
-
 /************************************************************************/
 /*                                main()                                */
 /************************************************************************/
 
 #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
     do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
+        Usage(CPLSPrintf("%s option requires %d argument(s)", \
+                         argv[i], nExtraArg)); } while( false )
 
 int main( int argc, char ** argv )
 
@@ -360,11 +359,9 @@ bool FindSRS( const char *pszInput, OGRSpatialReference &oSRS )
     if( !bDebug )
         CPLSetErrorHandler ( oErrorHandler );
 
-
     return bGotSRS;
 }
 
-
 /************************************************************************/
 /*                      PrintSRS()                                      */
 /*                                                                      */
@@ -582,7 +579,6 @@ int SearchCSVForWKT( const char *pszFileCSV, const char *pszTarget )
     VSIFCloseL( fp );
 
     return nFound;
-
 }
 
 /* TODO
diff --git a/apps/gdaltindex.c b/apps/gdaltindex.c
deleted file mode 100644
index ecac776..0000000
--- a/apps/gdaltindex.c
+++ /dev/null
@@ -1,654 +0,0 @@
-/******************************************************************************
- * $Id: gdaltindex.c 33720 2016-03-15 00:39:53Z goatbar $
- *
- * Project:  MapServer
- * Purpose:  Commandline App to build tile index for raster files.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2001, Frank Warmerdam, DM Solutions Group Inc
- * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_api.h"
-#include "ogr_srs_api.h"
-#include "gdal.h"
-#include "cpl_port.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-
-CPL_CVSID("$Id: gdaltindex.c 33720 2016-03-15 00:39:53Z goatbar $");
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage(const char* pszErrorMsg)
-
-{
-    fprintf(stdout, "%s",
-            "\n"
-            "Usage: gdaltindex [-f format] [-tileindex field_name] [-write_absolute_path] \n"
-            "                  [-skip_different_projection] [-t_srs target_srs]\n"
-            "                  [-src_srs_name field_name] [-src_srs_format [AUTO|WKT|EPSG|PROJ]\n"
-            "                  [-lyr_name name] index_file [gdal_file]*\n"
-            "\n"
-            "e.g.\n"
-            "  % gdaltindex doq_index.shp doq/*.tif\n"
-            "\n"
-            "NOTES:\n"
-            "  o The shapefile (index_file) will be created if it doesn't already exist.\n"
-            "  o The default tile index field is 'location'.\n"
-            "  o Raster filenames will be put in the file exactly as they are specified\n"
-            "    on the commandline unless the option -write_absolute_path is used.\n"
-            "  o If -skip_different_projection is specified, only files with same projection ref\n"
-            "    as files already inserted in the tileindex will be inserted (unless t_srs is specified).\n"
-            "  o If -t_srs is specified, geometries of input files will be transformed to the desired\n"
-            "    target coordinate reference system.\n"
-            "    Note that using this option generates files that are NOT compatible with MapServer < 6.4.\n"
-            "  o Simple rectangular polygons are generated in the same coordinate reference system\n"
-            "    as the rasters, or in target reference system if the -t_srs option is used.\n");
-
-    if( pszErrorMsg != NULL )
-        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
-
-    exit(1);
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
-    do { if (i_arg + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i_arg], nExtraArg)); } while(0)
-
-typedef enum
-{
-    FORMAT_AUTO,
-    FORMAT_WKT,
-    FORMAT_EPSG,
-    FORMAT_PROJ
-} SrcSRSFormat;
-
-int main(int argc, char *argv[])
-{
-    const char* pszIndexLayerName = NULL;
-    const char *index_filename = NULL;
-    const char *tile_index = "location";
-    const char* pszDriverName = "ESRI Shapefile";
-    size_t nMaxFieldSize = 254;
-    int		i_arg, ti_field;
-    OGRDataSourceH hTileIndexDS;
-    OGRLayerH hLayer = NULL;
-    OGRFeatureDefnH hFDefn;
-    int write_absolute_path = FALSE;
-    char* current_path = NULL;
-    int i;
-    int nExistingFiles;
-    int skip_different_projection = FALSE;
-    char** existingFilesTab = NULL;
-    int alreadyExistingProjectionRefValid = FALSE;
-    char* alreadyExistingProjectionRef = NULL;
-    const char *pszTargetSRS = "";
-    int bSetTargetSRS = FALSE;
-    OGRSpatialReferenceH hTargetSRS = NULL;
-    const char* pszSrcSRSName = NULL;
-    int i_SrcSRSName = -1;
-    int bSrcSRSFormatSpecified = FALSE;
-    SrcSRSFormat eSrcSRSFormat = FORMAT_AUTO;
-
-    /* Check that we are running against at least GDAL 1.4 */
-    /* Note to developers : if we use newer API, please change the requirement */
-    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
-    {
-        fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
-                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
-        exit(1);
-    }
-
-    GDALAllRegister();
-    OGRRegisterAll();
-
-    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
-    if( argc < 1 )
-        exit( -argc );
-
-/* -------------------------------------------------------------------- */
-/*      Get commandline arguments other than the GDAL raster filenames. */
-/* -------------------------------------------------------------------- */
-    for( i_arg = 1; i_arg < argc; i_arg++ )
-    {
-        if( EQUAL(argv[i_arg], "--utility_version") )
-        {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
-            CSLDestroy( argv );
-            return 0;
-        }
-        else if( EQUAL(argv[i_arg],"--help") )
-            Usage(NULL);
-        else if( strcmp(argv[i_arg],"-f") == 0 )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszDriverName = argv[++i_arg];
-            if( !EQUAL(pszDriverName, "ESRI Shapefile") )
-                nMaxFieldSize = 0;
-        }
-        else if( strcmp(argv[i_arg],"-lyr_name") == 0 )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszIndexLayerName = argv[++i_arg];
-        }
-        else if( strcmp(argv[i_arg],"-tileindex") == 0 )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            tile_index = argv[++i_arg];
-        }
-        else if( strcmp(argv[i_arg],"-t_srs") == 0 )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszTargetSRS = argv[++i_arg];
-            bSetTargetSRS = TRUE;
-        }
-        else if ( strcmp(argv[i_arg],"-write_absolute_path") == 0 )
-        {
-            write_absolute_path = TRUE;
-        }
-        else if ( strcmp(argv[i_arg],"-skip_different_projection") == 0 )
-        {
-            skip_different_projection = TRUE;
-        }
-        else if( strcmp(argv[i_arg], "-src_srs_name") == 0 )
-        {
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszSrcSRSName = argv[++i_arg];
-        }
-        else if( strcmp(argv[i_arg], "-src_srs_format") == 0 )
-        {
-            const char* pszFormat;
-            bSrcSRSFormatSpecified = TRUE;
-            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
-            pszFormat = argv[++i_arg];
-            if( EQUAL(pszFormat, "AUTO") )
-                eSrcSRSFormat = FORMAT_AUTO;
-            else if( EQUAL(pszFormat, "WKT") )
-                eSrcSRSFormat = FORMAT_WKT;
-            else if( EQUAL(pszFormat, "EPSG") )
-                eSrcSRSFormat = FORMAT_EPSG;
-            else if( EQUAL(pszFormat, "PROJ") )
-                eSrcSRSFormat = FORMAT_PROJ;
-        }
-        else if( argv[i_arg][0] == '-' )
-            Usage(CPLSPrintf("Unknown option name '%s'", argv[i_arg]));
-        else if( index_filename == NULL )
-        {
-            index_filename = argv[i_arg];
-            i_arg++;
-            break;
-        }
-    }
-
-    if( index_filename == NULL )
-        Usage("No index filename specified.");
-    if( i_arg == argc )
-        Usage("No file to index specified.");
-    if( bSrcSRSFormatSpecified && pszSrcSRSName == NULL )
-        Usage("-src_srs_name must be specified when -src_srs_format is specified.");
-
-/* -------------------------------------------------------------------- */
-/*      Create and validate target SRS if given.                        */
-/* -------------------------------------------------------------------- */
-   if( bSetTargetSRS )
-   {
-       if ( skip_different_projection )
-       {
-           fprintf( stderr,
-                    "Warning : -skip_different_projection does not apply "
-                    "when -t_srs is requested.\n" );
-       }
-       hTargetSRS = OSRNewSpatialReference("");
-       /* coverity[tainted_data] */
-       if( OSRSetFromUserInput( hTargetSRS, pszTargetSRS ) != CE_None )
-       {
-           OSRDestroySpatialReference( hTargetSRS );
-           fprintf( stderr, "Invalid target SRS `%s'.\n",
-                    pszTargetSRS );
-           exit(1);
-       }
-   }
-
-/* -------------------------------------------------------------------- */
-/*      Open or create the target datasource                            */
-/* -------------------------------------------------------------------- */
-    hTileIndexDS = OGROpen( index_filename, TRUE, NULL );
-    if (hTileIndexDS != NULL)
-    {
-        if( OGR_DS_GetLayerCount(hTileIndexDS) == 1 )
-            hLayer = OGR_DS_GetLayer(hTileIndexDS, 0);
-        else
-        {
-            if( pszIndexLayerName == NULL )
-            {
-                printf( "-lyr_name must be specified.\n" );
-                exit( 1 );
-            }
-            CPLPushErrorHandler(CPLQuietErrorHandler);
-            hLayer = OGR_DS_GetLayerByName(hTileIndexDS, pszIndexLayerName);
-            CPLPopErrorHandler();
-        }
-    }
-    else
-    {
-        OGRSFDriverH hDriver;
-
-        printf( "Creating new index file...\n" );
-        hDriver = OGRGetDriverByName( pszDriverName );
-        if( hDriver == NULL )
-        {
-            printf( "%s driver not available.\n", pszDriverName );
-            exit( 1 );
-        }
-
-        hTileIndexDS = OGR_Dr_CreateDataSource( hDriver, index_filename, NULL );
-    }
-
-    if( hTileIndexDS != NULL && hLayer == NULL )
-    {
-        OGRSpatialReferenceH hSpatialRef = NULL;
-        char* pszLayerName;
-        if( pszIndexLayerName == NULL )
-        {
-            VSIStatBuf sStat;
-            if( EQUAL(pszDriverName, "ESRI Shapefile") ||
-                VSIStat(index_filename, &sStat) == 0 )
-                pszLayerName = CPLStrdup(CPLGetBasename(index_filename));
-            else
-            {
-                printf( "-lyr_name must be specified.\n" );
-                exit( 1 );
-            }
-        }
-        else
-            pszLayerName = CPLStrdup(pszIndexLayerName);
-
-        /* get spatial reference for output file from target SRS (if set) */
-        /* or from first input file */
-        if( bSetTargetSRS )
-        {
-            hSpatialRef = OSRClone( hTargetSRS );
-        }
-        else
-        {
-            GDALDatasetH hDS = GDALOpen( argv[i_arg], GA_ReadOnly );
-            if (hDS)
-            {
-                const char* pszWKT = GDALGetProjectionRef(hDS);
-                if (pszWKT != NULL && pszWKT[0] != '\0')
-                {
-                    hSpatialRef = OSRNewSpatialReference(pszWKT);
-                }
-                GDALClose(hDS);
-            }
-        }
-
-        hLayer = OGR_DS_CreateLayer( hTileIndexDS, pszLayerName, hSpatialRef, wkbPolygon, NULL );
-        CPLFree(pszLayerName);
-        if (hSpatialRef)
-            OSRRelease(hSpatialRef);
-
-        if (hLayer)
-        {
-            OGRFieldDefnH hFieldDefn = OGR_Fld_Create( tile_index, OFTString );
-            if( nMaxFieldSize )
-                OGR_Fld_SetWidth( hFieldDefn, (int)nMaxFieldSize);
-            OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
-            OGR_Fld_Destroy(hFieldDefn);
-            if( pszSrcSRSName != NULL )
-            {
-                hFieldDefn = OGR_Fld_Create( pszSrcSRSName, OFTString );
-                if( nMaxFieldSize )
-                    OGR_Fld_SetWidth( hFieldDefn, (int)nMaxFieldSize);
-                OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
-                OGR_Fld_Destroy(hFieldDefn);
-            }
-        }
-    }
-
-    if( hTileIndexDS == NULL || hLayer == NULL )
-    {
-        fprintf( stderr, "Unable to open/create shapefile `%s'.\n",
-                 index_filename );
-        exit(2);
-    }
-
-    hFDefn = OGR_L_GetLayerDefn(hLayer);
-
-    ti_field = OGR_FD_GetFieldIndex( hFDefn, tile_index );
-    if( ti_field < 0 )
-    {
-        fprintf( stderr, "Unable to find field `%s' in file `%s'.\n",
-                 tile_index, index_filename );
-        exit(2);
-    }
-
-    if( pszSrcSRSName != NULL )
-        i_SrcSRSName = OGR_FD_GetFieldIndex( hFDefn, pszSrcSRSName );
-
-    /* Load in memory existing file names in SHP */
-    nExistingFiles = (int)OGR_L_GetFeatureCount(hLayer, FALSE);
-    if( nExistingFiles < 0)
-        nExistingFiles = 0;
-    if (nExistingFiles > 0)
-    {
-        OGRFeatureH hFeature;
-        existingFilesTab = (char**)CPLMalloc(nExistingFiles * sizeof(char*));
-        for(i=0;i<nExistingFiles;i++)
-        {
-            hFeature = OGR_L_GetNextFeature(hLayer);
-            existingFilesTab[i] = CPLStrdup(OGR_F_GetFieldAsString( hFeature, ti_field ));
-            if (i == 0)
-            {
-                GDALDatasetH hDS = GDALOpen(existingFilesTab[i], GA_ReadOnly );
-                if (hDS)
-                {
-                    alreadyExistingProjectionRefValid = TRUE;
-                    alreadyExistingProjectionRef = CPLStrdup(GDALGetProjectionRef(hDS));
-                    GDALClose(hDS);
-                }
-            }
-            OGR_F_Destroy( hFeature );
-        }
-    }
-
-    if (write_absolute_path)
-    {
-        current_path = CPLGetCurrentDir();
-        if (current_path == NULL)
-        {
-            fprintf( stderr, "This system does not support the CPLGetCurrentDir call. "
-                             "The option -write_absolute_path will have no effect\n");
-            write_absolute_path = FALSE;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      loop over GDAL files, processing.                               */
-/* -------------------------------------------------------------------- */
-    for( ; i_arg < argc; i_arg++ )
-    {
-        GDALDatasetH	hDS;
-        double	        adfGeoTransform[6];
-        double		adfX[5], adfY[5];
-        int		nXSize, nYSize;
-        char* fileNameToWrite;
-        const char* projectionRef;
-        VSIStatBuf sStatBuf;
-        int k;
-        OGRFeatureH hFeature;
-        OGRGeometryH hPoly, hRing;
-        OGRSpatialReferenceH hSourceSRS = NULL;
-
-        /* Make sure it is a file before building absolute path name */
-        if (write_absolute_path && CPLIsFilenameRelative( argv[i_arg] ) &&
-            VSIStat( argv[i_arg], &sStatBuf ) == 0)
-        {
-            fileNameToWrite = CPLStrdup(CPLProjectRelativeFilename(current_path, argv[i_arg]));
-        }
-        else
-        {
-            fileNameToWrite = CPLStrdup(argv[i_arg]);
-        }
-
-        /* Checks that file is not already in tileindex */
-        for(i=0;i<nExistingFiles;i++)
-        {
-            if (EQUAL(fileNameToWrite, existingFilesTab[i]))
-            {
-                fprintf(stderr, "File %s is already in tileindex. Skipping it.\n",
-                        fileNameToWrite);
-                break;
-            }
-        }
-        if (i != nExistingFiles)
-        {
-            CPLFree(fileNameToWrite);
-            continue;
-        }
-
-        hDS = GDALOpen( argv[i_arg], GA_ReadOnly );
-        if( hDS == NULL )
-        {
-            fprintf( stderr, "Unable to open %s, skipping.\n",
-                     argv[i_arg] );
-            CPLFree(fileNameToWrite);
-            continue;
-        }
-
-        GDALGetGeoTransform( hDS, adfGeoTransform );
-        if( adfGeoTransform[0] == 0.0
-            && adfGeoTransform[1] == 1.0
-            && adfGeoTransform[3] == 0.0
-            && ABS(adfGeoTransform[5]) == 1.0 )
-        {
-            fprintf( stderr,
-                     "It appears no georeferencing is available for\n"
-                     "`%s', skipping.\n",
-                     argv[i_arg] );
-            GDALClose( hDS );
-            CPLFree(fileNameToWrite);
-            continue;
-        }
-
-        projectionRef = GDALGetProjectionRef(hDS);
-
-        /* if not set target srs, test that the current file uses same projection as others */
-        if( !bSetTargetSRS )
-        {
-            if (alreadyExistingProjectionRefValid)
-            {
-                int projectionRefNotNull, alreadyExistingProjectionRefNotNull;
-                projectionRefNotNull = projectionRef && projectionRef[0];
-                alreadyExistingProjectionRefNotNull = alreadyExistingProjectionRef && alreadyExistingProjectionRef[0];
-                if ((projectionRefNotNull &&
-                     alreadyExistingProjectionRefNotNull &&
-                     EQUAL(projectionRef, alreadyExistingProjectionRef) == 0) ||
-                    (projectionRefNotNull != alreadyExistingProjectionRefNotNull))
-                {
-                    fprintf(stderr, "Warning : %s is not using the same projection system as "
-                            "other files in the tileindex.\n"
-			    "This may cause problems when using it in MapServer for example.\n"
-                            "Use -t_srs option to set target projection system (not supported by MapServer).\n"
-                            "%s\n", argv[i_arg],
-                            (skip_different_projection) ? "Skipping this file." : "");
-                    if (skip_different_projection)
-                    {
-                        CPLFree(fileNameToWrite);
-                        GDALClose( hDS );
-                        continue;
-                    }
-                }
-            }
-            else
-            {
-                alreadyExistingProjectionRefValid = TRUE;
-                alreadyExistingProjectionRef = CPLStrdup(projectionRef);
-            }
-        }
-
-        nXSize = GDALGetRasterXSize( hDS );
-        nYSize = GDALGetRasterYSize( hDS );
-
-        adfX[0] = adfGeoTransform[0]
-            + 0 * adfGeoTransform[1]
-            + 0 * adfGeoTransform[2];
-        adfY[0] = adfGeoTransform[3]
-            + 0 * adfGeoTransform[4]
-            + 0 * adfGeoTransform[5];
-
-        adfX[1] = adfGeoTransform[0]
-            + nXSize * adfGeoTransform[1]
-            + 0 * adfGeoTransform[2];
-        adfY[1] = adfGeoTransform[3]
-            + nXSize * adfGeoTransform[4]
-            + 0 * adfGeoTransform[5];
-
-        adfX[2] = adfGeoTransform[0]
-            + nXSize * adfGeoTransform[1]
-            + nYSize * adfGeoTransform[2];
-        adfY[2] = adfGeoTransform[3]
-            + nXSize * adfGeoTransform[4]
-            + nYSize * adfGeoTransform[5];
-
-        adfX[3] = adfGeoTransform[0]
-            + 0 * adfGeoTransform[1]
-            + nYSize * adfGeoTransform[2];
-        adfY[3] = adfGeoTransform[3]
-            + 0 * adfGeoTransform[4]
-            + nYSize * adfGeoTransform[5];
-
-        adfX[4] = adfGeoTransform[0]
-            + 0 * adfGeoTransform[1]
-            + 0 * adfGeoTransform[2];
-        adfY[4] = adfGeoTransform[3]
-            + 0 * adfGeoTransform[4]
-            + 0 * adfGeoTransform[5];
-
-        if( (bSetTargetSRS || i_SrcSRSName >= 0) && projectionRef != NULL && projectionRef[0] != '\0' )
-            hSourceSRS = OSRNewSpatialReference( projectionRef );
-
-        /* if set target srs, do the forward transformation of all points */
-        if( bSetTargetSRS && projectionRef != NULL && projectionRef[0] != '\0' )
-        {
-            OGRCoordinateTransformationH hCT = NULL;
-            if( hSourceSRS && !OSRIsSame( hSourceSRS, hTargetSRS ) )
-            {
-                hCT = OCTNewCoordinateTransformation( hSourceSRS, hTargetSRS );
-                if( hCT == NULL || !OCTTransform( hCT, 5, adfX, adfY, NULL ) )
-                {
-                    fprintf( stderr,
-                             "Warning : unable to transform points from source SRS `%s' to target SRS `%s'\n"
-                             "for file `%s' - file skipped\n",
-                             projectionRef, pszTargetSRS, fileNameToWrite );
-                    if ( hCT )
-                        OCTDestroyCoordinateTransformation( hCT );
-                    if ( hSourceSRS )
-                        OSRDestroySpatialReference( hSourceSRS );
-                    continue;
-                }
-                if ( hCT )
-                    OCTDestroyCoordinateTransformation( hCT );
-            }
-        }
-
-        hFeature = OGR_F_Create( OGR_L_GetLayerDefn( hLayer ) );
-        OGR_F_SetFieldString( hFeature, ti_field, fileNameToWrite );
-
-        if( i_SrcSRSName >= 0 && hSourceSRS != NULL )
-        {
-            const char* pszAuthorityCode = OSRGetAuthorityCode(hSourceSRS, NULL);
-            const char* pszAuthorityName = OSRGetAuthorityName(hSourceSRS, NULL);
-            if( eSrcSRSFormat == FORMAT_AUTO )
-            {
-                if( pszAuthorityName != NULL && pszAuthorityCode != NULL )
-                    OGR_F_SetFieldString( hFeature, i_SrcSRSName,
-                                        CPLSPrintf("%s:%s", pszAuthorityName, pszAuthorityCode) );
-                else if( nMaxFieldSize == 0 || strlen(projectionRef) <= nMaxFieldSize )
-                    OGR_F_SetFieldString( hFeature, i_SrcSRSName, projectionRef );
-                else
-                {
-                    char* pszProj4 = NULL;
-                    if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE )
-                    {
-                        OGR_F_SetFieldString( hFeature, i_SrcSRSName, pszProj4 );
-                        CPLFree(pszProj4);
-                    }
-                    else
-                        OGR_F_SetFieldString( hFeature, i_SrcSRSName, projectionRef );
-                }
-            }
-            else if( eSrcSRSFormat == FORMAT_WKT )
-            {
-                if( nMaxFieldSize == 0 || strlen(projectionRef) <= nMaxFieldSize )
-                    OGR_F_SetFieldString( hFeature, i_SrcSRSName, projectionRef );
-            }
-            else if( eSrcSRSFormat == FORMAT_PROJ )
-            {
-                char* pszProj4 = NULL;
-                if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE )
-                {
-                    OGR_F_SetFieldString( hFeature, i_SrcSRSName, pszProj4 );
-                    CPLFree(pszProj4);
-                }
-            }
-            else if( eSrcSRSFormat == FORMAT_EPSG )
-            {
-                if( pszAuthorityName != NULL && pszAuthorityCode != NULL )
-                    OGR_F_SetFieldString( hFeature, i_SrcSRSName,
-                                        CPLSPrintf("%s:%s", pszAuthorityName, pszAuthorityCode) );
-            }
-        }
-        if( hSourceSRS )
-            OSRDestroySpatialReference( hSourceSRS );
-
-        hPoly = OGR_G_CreateGeometry(wkbPolygon);
-        hRing = OGR_G_CreateGeometry(wkbLinearRing);
-        for(k=0;k<5;k++)
-            OGR_G_SetPoint_2D(hRing, k, adfX[k], adfY[k]);
-        OGR_G_AddGeometryDirectly( hPoly, hRing );
-        OGR_F_SetGeometryDirectly( hFeature, hPoly );
-
-        if( OGR_L_CreateFeature( hLayer, hFeature ) != OGRERR_NONE )
-        {
-           printf( "Failed to create feature in shapefile.\n" );
-           break;
-        }
-
-        OGR_F_Destroy( hFeature );
-
-        CPLFree(fileNameToWrite);
-
-        GDALClose( hDS );
-    }
-
-    CPLFree(current_path);
-
-    if (nExistingFiles)
-    {
-        for(i=0;i<nExistingFiles;i++)
-        {
-            CPLFree(existingFilesTab[i]);
-        }
-        CPLFree(existingFilesTab);
-    }
-    CPLFree(alreadyExistingProjectionRef);
-
-    if ( hTargetSRS )
-        OSRDestroySpatialReference( hTargetSRS );
-
-    OGR_DS_Destroy( hTileIndexDS );
-
-    GDALDestroyDriverManager();
-    OGRCleanupAll();
-    CSLDestroy(argv);
-
-    exit( 0 );
-}
diff --git a/apps/gdaltindex.cpp b/apps/gdaltindex.cpp
new file mode 100644
index 0000000..e1ce951
--- /dev/null
+++ b/apps/gdaltindex.cpp
@@ -0,0 +1,705 @@
+/******************************************************************************
+ *
+ * Project:  MapServer
+ * Purpose:  Commandline App to build tile index for raster files.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2001, Frank Warmerdam, DM Solutions Group Inc
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_port.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal.h"
+#include "ogr_api.h"
+#include "ogr_srs_api.h"
+
+#include <cmath>
+
+CPL_CVSID("$Id: gdaltindex.cpp 37859 2017-03-30 11:41:05Z rouault $");
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg)
+
+{
+    fprintf(stdout, "%s",
+            "\n"
+            "Usage: gdaltindex [-f format] [-tileindex field_name] [-write_absolute_path] \n"
+            "                  [-skip_different_projection] [-t_srs target_srs]\n"
+            "                  [-src_srs_name field_name] [-src_srs_format [AUTO|WKT|EPSG|PROJ]\n"
+            "                  [-lyr_name name] index_file [gdal_file]*\n"
+            "\n"
+            "e.g.\n"
+            "  % gdaltindex doq_index.shp doq/*.tif\n"
+            "\n"
+            "NOTES:\n"
+            "  o The shapefile (index_file) will be created if it doesn't already exist.\n"
+            "  o The default tile index field is 'location'.\n"
+            "  o Raster filenames will be put in the file exactly as they are specified\n"
+            "    on the commandline unless the option -write_absolute_path is used.\n"
+            "  o If -skip_different_projection is specified, only files with same projection ref\n"
+            "    as files already inserted in the tileindex will be inserted (unless t_srs is specified).\n"
+            "  o If -t_srs is specified, geometries of input files will be transformed to the desired\n"
+            "    target coordinate reference system.\n"
+            "    Note that using this option generates files that are NOT compatible with MapServer < 6.4.\n"
+            "  o Simple rectangular polygons are generated in the same coordinate reference system\n"
+            "    as the rasters, or in target reference system if the -t_srs option is used.\n");
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    exit(1);
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
+    do { if (iArg + nExtraArg >= argc) \
+        Usage(CPLSPrintf("%s option requires %d argument(s)", \
+                         argv[iArg], nExtraArg)); } while( false )
+
+typedef enum
+{
+    FORMAT_AUTO,
+    FORMAT_WKT,
+    FORMAT_EPSG,
+    FORMAT_PROJ
+} SrcSRSFormat;
+
+int main( int argc, char *argv[] )
+{
+    // Check that we are running against at least GDAL 1.4.
+    // Note to developers: if we use newer API, please change the requirement.
+    if( atoi(GDALVersionInfo("VERSION_NUM")) < 1400 )
+    {
+        fprintf(stderr,
+                "At least, GDAL >= 1.4.0 is required for this version of %s, "
+                "which was compiled against GDAL %s\n",
+                argv[0], GDAL_RELEASE_NAME);
+        exit(1);
+    }
+
+    GDALAllRegister();
+    OGRRegisterAll();
+
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+/* -------------------------------------------------------------------- */
+/*      Get commandline arguments other than the GDAL raster filenames. */
+/* -------------------------------------------------------------------- */
+    const char* pszIndexLayerName = NULL;
+    const char *index_filename = NULL;
+    const char *tile_index = "location";
+    const char* pszDriverName = "ESRI Shapefile";
+    size_t nMaxFieldSize = 254;
+    bool write_absolute_path = false;
+    char* current_path = NULL;
+    bool skip_different_projection = false;
+    const char *pszTargetSRS = "";
+    bool bSetTargetSRS = false;
+    const char* pszSrcSRSName = NULL;
+    int i_SrcSRSName = -1;
+    bool bSrcSRSFormatSpecified = false;
+    SrcSRSFormat eSrcSRSFormat = FORMAT_AUTO;
+
+    int iArg = 1;  // Used after for.
+    for( ; iArg < argc; iArg++ )
+    {
+        if( EQUAL(argv[iArg], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against "
+                   "GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            CSLDestroy( argv );
+            return 0;
+        }
+        else if( EQUAL(argv[iArg],"--help") )
+            Usage(NULL);
+        else if( strcmp(argv[iArg],"-f") == 0 )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszDriverName = argv[++iArg];
+            if( !EQUAL(pszDriverName, "ESRI Shapefile") )
+                nMaxFieldSize = 0;
+        }
+        else if( strcmp(argv[iArg],"-lyr_name") == 0 )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszIndexLayerName = argv[++iArg];
+        }
+        else if( strcmp(argv[iArg],"-tileindex") == 0 )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            tile_index = argv[++iArg];
+        }
+        else if( strcmp(argv[iArg],"-t_srs") == 0 )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszTargetSRS = argv[++iArg];
+            bSetTargetSRS = true;
+        }
+        else if ( strcmp(argv[iArg],"-write_absolute_path") == 0 )
+        {
+            write_absolute_path = true;
+        }
+        else if ( strcmp(argv[iArg],"-skip_different_projection") == 0 )
+        {
+            skip_different_projection = true;
+        }
+        else if( strcmp(argv[iArg], "-src_srs_name") == 0 )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszSrcSRSName = argv[++iArg];
+        }
+        else if( strcmp(argv[iArg], "-src_srs_format") == 0 )
+        {
+            const char* pszFormat;
+            bSrcSRSFormatSpecified = true;
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszFormat = argv[++iArg];
+            if( EQUAL(pszFormat, "AUTO") )
+                eSrcSRSFormat = FORMAT_AUTO;
+            else if( EQUAL(pszFormat, "WKT") )
+                eSrcSRSFormat = FORMAT_WKT;
+            else if( EQUAL(pszFormat, "EPSG") )
+                eSrcSRSFormat = FORMAT_EPSG;
+            else if( EQUAL(pszFormat, "PROJ") )
+                eSrcSRSFormat = FORMAT_PROJ;
+        }
+        else if( argv[iArg][0] == '-' )
+            Usage(CPLSPrintf("Unknown option name '%s'", argv[iArg]));
+        else if( index_filename == NULL )
+        {
+            index_filename = argv[iArg];
+            iArg++;
+            break;
+        }
+    }
+
+    if( index_filename == NULL )
+        Usage("No index filename specified.");
+    if( iArg == argc )
+        Usage("No file to index specified.");
+    if( bSrcSRSFormatSpecified && pszSrcSRSName == NULL )
+        Usage("-src_srs_name must be specified when -src_srs_format is "
+              "specified.");
+
+/* -------------------------------------------------------------------- */
+/*      Create and validate target SRS if given.                        */
+/* -------------------------------------------------------------------- */
+    OGRSpatialReferenceH hTargetSRS = NULL;
+    if( bSetTargetSRS )
+    {
+        if( skip_different_projection )
+        {
+            fprintf( stderr,
+                     "Warning : -skip_different_projection does not apply "
+                     "when -t_srs is requested.\n" );
+        }
+        hTargetSRS = OSRNewSpatialReference("");
+        // coverity[tainted_data]
+        if( OSRSetFromUserInput( hTargetSRS, pszTargetSRS ) != CE_None )
+        {
+            OSRDestroySpatialReference( hTargetSRS );
+            fprintf( stderr, "Invalid target SRS `%s'.\n",
+                     pszTargetSRS );
+            exit(1);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Open or create the target datasource                            */
+/* -------------------------------------------------------------------- */
+    OGRDataSourceH hTileIndexDS = OGROpen( index_filename, TRUE, NULL );
+    OGRLayerH hLayer = NULL;
+    if( hTileIndexDS != NULL )
+    {
+        if( OGR_DS_GetLayerCount(hTileIndexDS) == 1 )
+        {
+            hLayer = OGR_DS_GetLayer(hTileIndexDS, 0);
+        }
+        else
+        {
+            if( pszIndexLayerName == NULL )
+            {
+                printf( "-lyr_name must be specified.\n" );
+                exit( 1 );
+            }
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+            hLayer = OGR_DS_GetLayerByName(hTileIndexDS, pszIndexLayerName);
+            CPLPopErrorHandler();
+        }
+    }
+    else
+    {
+        printf( "Creating new index file...\n" );
+        OGRSFDriverH hDriver = OGRGetDriverByName( pszDriverName );
+        if( hDriver == NULL )
+        {
+            printf( "%s driver not available.\n", pszDriverName );
+            exit( 1 );
+        }
+
+        hTileIndexDS = OGR_Dr_CreateDataSource( hDriver, index_filename, NULL );
+    }
+
+    if( hTileIndexDS != NULL && hLayer == NULL )
+    {
+        OGRSpatialReferenceH hSpatialRef = NULL;
+        char* pszLayerName = NULL;
+        if( pszIndexLayerName == NULL )
+        {
+            VSIStatBuf sStat;
+            if( EQUAL(pszDriverName, "ESRI Shapefile") ||
+                VSIStat(index_filename, &sStat) == 0 )
+            {
+                pszLayerName = CPLStrdup(CPLGetBasename(index_filename));
+            }
+            else
+            {
+                printf( "-lyr_name must be specified.\n" );
+                exit( 1 );
+            }
+        }
+        else
+        {
+            pszLayerName = CPLStrdup(pszIndexLayerName);
+        }
+
+        /* get spatial reference for output file from target SRS (if set) */
+        /* or from first input file */
+        if( bSetTargetSRS )
+        {
+            hSpatialRef = OSRClone( hTargetSRS );
+        }
+        else
+        {
+            GDALDatasetH hDS = GDALOpen( argv[iArg], GA_ReadOnly );
+            if( hDS )
+            {
+                const char* pszWKT = GDALGetProjectionRef(hDS);
+                if (pszWKT != NULL && pszWKT[0] != '\0')
+                {
+                    hSpatialRef = OSRNewSpatialReference(pszWKT);
+                }
+                GDALClose(hDS);
+            }
+        }
+
+        hLayer =
+            OGR_DS_CreateLayer( hTileIndexDS, pszLayerName, hSpatialRef,
+                                wkbPolygon, NULL );
+        CPLFree(pszLayerName);
+        if( hSpatialRef )
+            OSRRelease(hSpatialRef);
+
+        if( hLayer )
+        {
+            OGRFieldDefnH hFieldDefn = OGR_Fld_Create( tile_index, OFTString );
+            if( nMaxFieldSize )
+                OGR_Fld_SetWidth( hFieldDefn, static_cast<int>(nMaxFieldSize));
+            OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
+            OGR_Fld_Destroy(hFieldDefn);
+            if( pszSrcSRSName != NULL )
+            {
+                hFieldDefn = OGR_Fld_Create( pszSrcSRSName, OFTString );
+                if( nMaxFieldSize )
+                    OGR_Fld_SetWidth( hFieldDefn, (int)nMaxFieldSize);
+                OGR_L_CreateField( hLayer, hFieldDefn, TRUE );
+                OGR_Fld_Destroy(hFieldDefn);
+            }
+        }
+    }
+
+    if( hTileIndexDS == NULL || hLayer == NULL )
+    {
+        fprintf( stderr, "Unable to open/create shapefile `%s'.\n",
+                 index_filename );
+        exit(2);
+    }
+
+    OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hLayer);
+
+    const int ti_field = OGR_FD_GetFieldIndex( hFDefn, tile_index );
+    if( ti_field < 0 )
+    {
+        fprintf( stderr, "Unable to find field `%s' in file `%s'.\n",
+                 tile_index, index_filename );
+        exit(2);
+    }
+
+    if( pszSrcSRSName != NULL )
+        i_SrcSRSName = OGR_FD_GetFieldIndex( hFDefn, pszSrcSRSName );
+
+    // Load in memory existing file names in SHP.
+    int nExistingFiles = static_cast<int>(OGR_L_GetFeatureCount(hLayer, FALSE));
+    if( nExistingFiles < 0)
+        nExistingFiles = 0;
+
+    char** existingFilesTab = NULL;
+    bool alreadyExistingProjectionRefValid = false;
+    char* alreadyExistingProjectionRef = NULL;
+    if( nExistingFiles > 0 )
+    {
+        OGRFeatureH hFeature = NULL;
+        existingFilesTab = static_cast<char **>(
+            CPLMalloc(nExistingFiles * sizeof(char*)));
+        for( int i = 0; i < nExistingFiles; i++ )
+        {
+            hFeature = OGR_L_GetNextFeature(hLayer);
+            existingFilesTab[i] =
+                CPLStrdup(OGR_F_GetFieldAsString( hFeature, ti_field ));
+            if( i == 0 )
+            {
+                GDALDatasetH hDS = GDALOpen(existingFilesTab[i], GA_ReadOnly );
+                if( hDS )
+                {
+                    alreadyExistingProjectionRefValid = true;
+                    alreadyExistingProjectionRef =
+                        CPLStrdup(GDALGetProjectionRef(hDS));
+                    GDALClose(hDS);
+                }
+            }
+            OGR_F_Destroy( hFeature );
+        }
+    }
+
+    if( write_absolute_path )
+    {
+        current_path = CPLGetCurrentDir();
+        if (current_path == NULL)
+        {
+            fprintf( stderr,
+                     "This system does not support the CPLGetCurrentDir call. "
+                     "The option -write_absolute_path will have no effect\n" );
+            write_absolute_path = FALSE;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      loop over GDAL files, processing.                               */
+/* -------------------------------------------------------------------- */
+    for( ; iArg < argc; iArg++ )
+    {
+        char *fileNameToWrite = NULL;
+        VSIStatBuf sStatBuf;
+
+        // Make sure it is a file before building absolute path name.
+        if( write_absolute_path && CPLIsFilenameRelative( argv[iArg] ) &&
+            VSIStat( argv[iArg], &sStatBuf ) == 0 )
+        {
+            fileNameToWrite =
+                CPLStrdup(CPLProjectRelativeFilename(current_path, argv[iArg]));
+        }
+        else
+        {
+            fileNameToWrite = CPLStrdup(argv[iArg]);
+        }
+
+        // Checks that file is not already in tileindex.
+        {
+            int i = 0;  // Used after for.
+            for( ; i < nExistingFiles; i++ )
+            {
+                if (EQUAL(fileNameToWrite, existingFilesTab[i]))
+                {
+                    fprintf(stderr,
+                            "File %s is already in tileindex. Skipping it.\n",
+                            fileNameToWrite);
+                    break;
+                }
+            }
+            if (i != nExistingFiles)
+            {
+                CPLFree(fileNameToWrite);
+                continue;
+            }
+        }
+
+        GDALDatasetH hDS = GDALOpen( argv[iArg], GA_ReadOnly );
+        if( hDS == NULL )
+        {
+            fprintf( stderr, "Unable to open %s, skipping.\n",
+                     argv[iArg] );
+            CPLFree(fileNameToWrite);
+            continue;
+        }
+
+        double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+        GDALGetGeoTransform( hDS, adfGeoTransform );
+        if( adfGeoTransform[0] == 0.0
+            && adfGeoTransform[1] == 1.0
+            && adfGeoTransform[3] == 0.0
+            && std::abs(adfGeoTransform[5]) == 1.0 )
+        {
+            fprintf( stderr,
+                     "It appears no georeferencing is available for\n"
+                     "`%s', skipping.\n",
+                     argv[iArg] );
+            GDALClose( hDS );
+            CPLFree(fileNameToWrite);
+            continue;
+        }
+
+        const char *projectionRef = GDALGetProjectionRef(hDS);
+
+        // If not set target srs, test that the current file uses same
+        // projection as others.
+        if( !bSetTargetSRS )
+        {
+            if( alreadyExistingProjectionRefValid )
+            {
+                int projectionRefNotNull, alreadyExistingProjectionRefNotNull;
+                projectionRefNotNull = projectionRef && projectionRef[0];
+                alreadyExistingProjectionRefNotNull =
+                    alreadyExistingProjectionRef &&
+                    alreadyExistingProjectionRef[0];
+                if ((projectionRefNotNull &&
+                     alreadyExistingProjectionRefNotNull &&
+                     EQUAL(projectionRef, alreadyExistingProjectionRef) == 0) ||
+                    (projectionRefNotNull != alreadyExistingProjectionRefNotNull))
+                {
+                    fprintf(
+                        stderr,
+                        "Warning : %s is not using the same projection system "
+                        "as other files in the tileindex.\n"
+                        "This may cause problems when using it in MapServer "
+                        "for example.\n"
+                        "Use -t_srs option to set target projection system "
+                        "(not supported by MapServer).\n"
+                        "%s\n", argv[iArg],
+                        skip_different_projection ? "Skipping this file." : "");
+                    if( skip_different_projection )
+                    {
+                        CPLFree(fileNameToWrite);
+                        GDALClose( hDS );
+                        continue;
+                    }
+                }
+            }
+            else
+            {
+                alreadyExistingProjectionRefValid = true;
+                alreadyExistingProjectionRef = CPLStrdup(projectionRef);
+            }
+        }
+
+        const int nXSize = GDALGetRasterXSize( hDS );
+        const int nYSize = GDALGetRasterYSize( hDS );
+
+        double adfX[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
+        double adfY[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
+        adfX[0] = adfGeoTransform[0]
+            + 0 * adfGeoTransform[1]
+            + 0 * adfGeoTransform[2];
+        adfY[0] = adfGeoTransform[3]
+            + 0 * adfGeoTransform[4]
+            + 0 * adfGeoTransform[5];
+
+        adfX[1] = adfGeoTransform[0]
+            + nXSize * adfGeoTransform[1]
+            + 0 * adfGeoTransform[2];
+        adfY[1] = adfGeoTransform[3]
+            + nXSize * adfGeoTransform[4]
+            + 0 * adfGeoTransform[5];
+
+        adfX[2] = adfGeoTransform[0]
+            + nXSize * adfGeoTransform[1]
+            + nYSize * adfGeoTransform[2];
+        adfY[2] = adfGeoTransform[3]
+            + nXSize * adfGeoTransform[4]
+            + nYSize * adfGeoTransform[5];
+
+        adfX[3] = adfGeoTransform[0]
+            + 0 * adfGeoTransform[1]
+            + nYSize * adfGeoTransform[2];
+        adfY[3] = adfGeoTransform[3]
+            + 0 * adfGeoTransform[4]
+            + nYSize * adfGeoTransform[5];
+
+        adfX[4] = adfGeoTransform[0]
+            + 0 * adfGeoTransform[1]
+            + 0 * adfGeoTransform[2];
+        adfY[4] = adfGeoTransform[3]
+            + 0 * adfGeoTransform[4]
+            + 0 * adfGeoTransform[5];
+
+        OGRSpatialReferenceH hSourceSRS = NULL;
+        if( (bSetTargetSRS || i_SrcSRSName >= 0) &&
+            projectionRef != NULL &&
+            projectionRef[0] != '\0' )
+        {
+            hSourceSRS = OSRNewSpatialReference( projectionRef );
+        }
+
+        // If set target srs, do the forward transformation of all points.
+        if( bSetTargetSRS && projectionRef != NULL && projectionRef[0] != '\0' )
+        {
+            OGRCoordinateTransformationH hCT = NULL;
+            if( hSourceSRS && !OSRIsSame( hSourceSRS, hTargetSRS ) )
+            {
+                hCT = OCTNewCoordinateTransformation( hSourceSRS, hTargetSRS );
+                if( hCT == NULL || !OCTTransform( hCT, 5, adfX, adfY, NULL ) )
+                {
+                    fprintf(
+                        stderr,
+                        "Warning : unable to transform points from source "
+                        "SRS `%s' to target SRS `%s'\n"
+                        "for file `%s' - file skipped\n",
+                        projectionRef, pszTargetSRS, fileNameToWrite );
+                    if( hCT )
+                        OCTDestroyCoordinateTransformation( hCT );
+                    if( hSourceSRS )
+                        OSRDestroySpatialReference( hSourceSRS );
+                    continue;
+                }
+                if( hCT )
+                    OCTDestroyCoordinateTransformation( hCT );
+            }
+        }
+
+        OGRFeatureH hFeature = OGR_F_Create( OGR_L_GetLayerDefn( hLayer ) );
+        OGR_F_SetFieldString( hFeature, ti_field, fileNameToWrite );
+
+        if( i_SrcSRSName >= 0 && hSourceSRS != NULL )
+        {
+            const char* pszAuthorityCode =
+                OSRGetAuthorityCode(hSourceSRS, NULL);
+            const char* pszAuthorityName =
+                OSRGetAuthorityName(hSourceSRS, NULL);
+            if( eSrcSRSFormat == FORMAT_AUTO )
+            {
+                if( pszAuthorityName != NULL && pszAuthorityCode != NULL )
+                {
+                    OGR_F_SetFieldString(
+                        hFeature, i_SrcSRSName,
+                        CPLSPrintf("%s:%s",
+                                   pszAuthorityName, pszAuthorityCode) );
+                }
+                else if( nMaxFieldSize == 0 ||
+                         strlen(projectionRef) <= nMaxFieldSize )
+                {
+                    OGR_F_SetFieldString(hFeature, i_SrcSRSName, projectionRef);
+                }
+                else
+                {
+                    char* pszProj4 = NULL;
+                    if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE )
+                    {
+                        OGR_F_SetFieldString( hFeature, i_SrcSRSName,
+                                              pszProj4 );
+                        CPLFree(pszProj4);
+                    }
+                    else
+                    {
+                        OGR_F_SetFieldString( hFeature, i_SrcSRSName,
+                                              projectionRef );
+                    }
+                }
+            }
+            else if( eSrcSRSFormat == FORMAT_WKT )
+            {
+                if( nMaxFieldSize == 0 ||
+                    strlen(projectionRef) <= nMaxFieldSize )
+                {
+                    OGR_F_SetFieldString( hFeature, i_SrcSRSName,
+                                          projectionRef );
+                }
+                else
+                {
+                    fprintf(stderr,
+                            "Cannot write WKT for file %s as it is too long!\n",
+                            fileNameToWrite);
+                }
+            }
+            else if( eSrcSRSFormat == FORMAT_PROJ )
+            {
+                char* pszProj4 = NULL;
+                if( OSRExportToProj4(hSourceSRS, &pszProj4) == OGRERR_NONE )
+                {
+                    OGR_F_SetFieldString( hFeature, i_SrcSRSName, pszProj4 );
+                    CPLFree(pszProj4);
+                }
+            }
+            else if( eSrcSRSFormat == FORMAT_EPSG )
+            {
+                if( pszAuthorityName != NULL && pszAuthorityCode != NULL )
+                    OGR_F_SetFieldString(
+                        hFeature, i_SrcSRSName,
+                        CPLSPrintf("%s:%s",
+                                   pszAuthorityName, pszAuthorityCode) );
+            }
+        }
+        if( hSourceSRS )
+            OSRDestroySpatialReference( hSourceSRS );
+
+        OGRGeometryH hPoly = OGR_G_CreateGeometry(wkbPolygon);
+        OGRGeometryH hRing = OGR_G_CreateGeometry(wkbLinearRing);
+        for( int k = 0; k < 5; k++ )
+            OGR_G_SetPoint_2D(hRing, k, adfX[k], adfY[k]);
+        OGR_G_AddGeometryDirectly( hPoly, hRing );
+        OGR_F_SetGeometryDirectly( hFeature, hPoly );
+
+        if( OGR_L_CreateFeature( hLayer, hFeature ) != OGRERR_NONE )
+        {
+           printf( "Failed to create feature in shapefile.\n" );
+           break;
+        }
+
+        OGR_F_Destroy( hFeature );
+
+        CPLFree(fileNameToWrite);
+
+        GDALClose( hDS );
+    }
+
+    CPLFree(current_path);
+
+    if (nExistingFiles)
+    {
+        for( int i = 0; i < nExistingFiles; i++ )
+        {
+            CPLFree(existingFilesTab[i]);
+        }
+        CPLFree(existingFilesTab);
+    }
+    CPLFree(alreadyExistingProjectionRef);
+
+    if ( hTargetSRS )
+        OSRDestroySpatialReference( hTargetSRS );
+
+    OGR_DS_Destroy( hTileIndexDS );
+
+    GDALDestroyDriverManager();
+    OGRCleanupAll();
+    CSLDestroy(argv);
+
+    exit( 0 );
+}
diff --git a/apps/gdaltorture.cpp b/apps/gdaltorture.cpp
index ae11b80..4af39fb 100644
--- a/apps/gdaltorture.cpp
+++ b/apps/gdaltorture.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaltorture.cpp  $
  *
  * Project:  GDAL Utilities
  * Purpose:  Command line utility to torture GDAL API on datasets
@@ -31,7 +30,7 @@
 #include "cpl_string.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: gdaltorture.cpp $");
+CPL_CVSID("$Id: gdaltorture.cpp 35884 2016-10-24 05:56:50Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -184,7 +183,6 @@ static void TortureDS(const char *pszTarget, int bReadWriteOperations)
     GDALClose(hDS);
 }
 
-
 /************************************************************************/
 /*                       ProcessTortureTarget()                         */
 /************************************************************************/
diff --git a/apps/gdaltransform.cpp b/apps/gdaltransform.cpp
index c134f89..6c5b00f 100644
--- a/apps/gdaltransform.cpp
+++ b/apps/gdaltransform.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalwarp.cpp 12380 2007-10-12 17:35:00Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Command line point transformer.
@@ -32,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdaltransform.cpp 12380 2007-10-12 17:35:00Z rouault $");
+CPL_CVSID("$Id: gdaltransform.cpp 36537 2016-11-27 23:51:56Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -89,7 +88,8 @@ static char *SanitizeSRS( const char *pszUserInput )
 
 #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
     do { if (i + nExtraArg >= argc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
+        Usage(CPLSPrintf("%s option requires %d argument(s)", \
+                         argv[i], nExtraArg)); } while( false )
 
 int main( int argc, char ** argv )
 
diff --git a/apps/gdalwarp_bin.cpp b/apps/gdalwarp_bin.cpp
index 6e611f2..1d12828 100644
--- a/apps/gdalwarp_bin.cpp
+++ b/apps/gdalwarp_bin.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalwarp_bin.cpp 34776 2016-07-25 21:22:15Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Test program for high performance warper API.
@@ -34,7 +33,7 @@
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: gdalwarp_bin.cpp 34776 2016-07-25 21:22:15Z rouault $");
+CPL_CVSID("$Id: gdalwarp_bin.cpp 37723 2017-03-16 17:07:53Z rouault $");
 
 /******************************************************************************/
 /*! \page gdalwarp gdalwarp
@@ -49,13 +48,14 @@ Usage:
 
 \verbatim
 gdalwarp [--help-general] [--formats]
-    [-s_srs srs_def] [-t_srs srs_def] [-to "NAME=VALUE"]
+    [-s_srs srs_def] [-t_srs srs_def] [-to "NAME=VALUE"] [-novshiftgrid]
     [-order n | -tps | -rpc | -geoloc] [-et err_threshold]
     [-refine_gcps tolerance [minimum_gcps]]
     [-te xmin ymin xmax ymax] [-te_srs srs_def]
     [-tr xres yres] [-tap] [-ts width height]
     [-ovr level|AUTO|AUTO-n|NONE] [-wo "NAME=VALUE"] [-ot Byte/Int16/...] [-wt Byte/Int16]
-    [-srcnodata "value [value...]"] [-dstnodata "value [value...]"] -dstalpha
+    [-srcnodata "value [value...]"] [-dstnodata "value [value...]"]
+    [-srcalpha|-nosrcalpha] [-dstalpha]
     [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]
     [-cutline datasource] [-cl layer] [-cwhere expression]
     [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]
@@ -79,14 +79,23 @@ with control information.
 The coordinate systems that can be passed are anything supported by the
 OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
 (i.e. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prj file
-containing well known text.</dd>
+containing well known text. Starting with GDAL 2.2, if the SRS has an explicit
+vertical datum that points to a PROJ.4 geoidgrids, and the input dataset is a
+single band dataset, a vertical correction will be applied to the values of the
+dataset.</dd>
 <dt> <b>-t_srs</b> <em>srs_def</em>:</dt><dd> target spatial reference set.
 The coordinate systems that can be passed are anything supported by the
 OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
 (i.e. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prj file
-containing well known text.</dd>
+containing well known text. Starting with GDAL 2.2, if the SRS has an explicit
+vertical datum that points to a PROJ.4 geoidgrids, and the input dataset is a
+single band dataset, a vertical correction will be applied to the values of the
+dataset.</dd>
 <dt> <b>-to</b> <em>NAME=VALUE</em>:</dt><dd> set a transformer option suitable
 to pass to GDALCreateGenImgProjTransformer2(). </dd>
+<dt> <b>-novshiftgrid</b></dt><dd> (GDAL >= 2.2) Disable the use of vertical
+datum shift grids when one of the source or target SRS has an explicit vertical
+datum, and the input dataset is a single band dataset.</dd>
 <dt> <b>-order</b> <em>n</em>:</dt><dd> order of polynomial used for warping
 (1 to 3). The default is to select a polynomial order based on the number of
 GCPs.</dd>
@@ -168,6 +177,10 @@ as a single operating system argument.  New files will be initialized to this
 value and if possible the nodata value will be recorded in the output
 file. Use a value of <tt>None</tt> to ensure that nodata is not defined (GDAL>=1.11).
 If this argument is not used then nodata values will be copied from the source dataset (GDAL>=1.11).</dd>
+<dt> <b>-srcalpha</b>:</dt><dd> Force the last band of a source image to be
+considered as a source alpha band. </dd>
+<dt> <b>-nosrcalpha</b>:</dt><dd> Prevent the alpha band of a source image to be
+considered as such (it will be warped as a regular band) (GDAL>=2.2). </dd>
 <dt> <b>-dstalpha</b>:</dt><dd> Create an output alpha band to identify
 nodata (unset/transparent) pixels. </dd>
 <dt> <b>-wm</b> <em>memory_in_mb</em>:</dt><dd> Set the amount of memory (in
@@ -178,8 +191,9 @@ input/output operation simultaneously.</dd>
 <dt> <b>-q</b>:</dt><dd> Be quiet.</dd>
 <dt> <b>-of</b> <em>format</em>:</dt><dd> Select the output format. The default is GeoTIFF (GTiff). Use the short format name. </dd>
 <dt> <b>-co</b> <em>"NAME=VALUE"</em>:</dt><dd> passes a creation option to
-the output format driver. Multiple <b>-co</b> options may be listed. See
-format specific documentation for legal creation options for each format.
+the output format driver. Multiple <b>-co</b> options may be listed. See <a class="el"
+href="formats_list.html" title="GDAL Raster Formats">format specific
+documentation for legal creation options for each format</a>
 </dd>
 
 <dt> <b>-cutline</b> <em>datasource</em>:</dt><dd>Enable use of a blend cutline from the name OGR support datasource.</dd>
@@ -216,23 +230,45 @@ features must be in the SRS of the destination file. When writing to a
 not yet existing target dataset, its extent will be the one of the
 original raster unless -te or -crop_to_cutline are specified.
 
+When doing vertical shift adjustments, the transformer option -to ERROR_ON_MISSING_VERT_SHIFT=YES
+can be used to error out as soon as a vertical shift value is missing (instead of 
+0 being used).
+
 <p>
-\section gdalwarp_example EXAMPLE
+\section gdalwarp_examples EXAMPLES
 
-For instance, an eight bit spot scene stored in GeoTIFF with
+- For instance, an eight bit spot scene stored in GeoTIFF with
 control points mapping the corners to lat/long could be warped to a UTM
 projection with a command like this:<p>
 
 \verbatim
-gdalwarp -t_srs '+proj=utm +zone=11 +datum=WGS84' raw_spot.tif utm11.tif
+gdalwarp -t_srs '+proj=utm +zone=11 +datum=WGS84' -overwrite raw_spot.tif utm11.tif
 \endverbatim
 
-For instance, the second channel of an ASTER image stored in HDF with
+- For instance, the second channel of an ASTER image stored in HDF with
 control points mapping the corners to lat/long could be warped to a UTM
 projection with a command like this:<p>
 
 \verbatim
-gdalwarp HDF4_SDS:ASTER_L1B:"pg-PR1B0000-2002031402_100_001":2 pg-PR1B0000-2002031402_100_001_2.tif
+gdalwarp -overwrite HDF4_SDS:ASTER_L1B:"pg-PR1B0000-2002031402_100_001":2 pg-PR1B0000-2002031402_100_001_2.tif
+\endverbatim
+
+- (GDAL >= 2.2) To apply a cutline on a un-georeferenced image and clip from pixel (220,60) to pixel (1160,690):<p>
+
+\verbatim
+gdalwarp -overwrite -to SRC_METHOD=NO_GEOTRANSFORM -to DST_METHOD=NO_GEOTRANSFORM -te 220 60 1160 690 -cutline cutline.csv in.png out.tif
+\endverbatim
+
+where cutline.csv content is like:
+\verbatim
+id,WKT
+1,"POLYGON((....))"
+\endverbatim
+
+- (GDAL >= 2.2) To transform a DEM from geoid elevations (using EGM96) to WGS84 ellipsoidal heights:<p>
+
+\verbatim
+gdalwarp -override in_dem.tif out_dem.tif -s_srs EPSG:4326+5773 -t_srs EPSG:4979
 \endverbatim
 
 <p>
@@ -286,7 +322,7 @@ static void Usage(const char* pszErrorMsg = NULL)
 {
     printf(
         "Usage: gdalwarp [--help-general] [--formats]\n"
-        "    [-s_srs srs_def] [-t_srs srs_def] [-to \"NAME=VALUE\"]\n"
+        "    [-s_srs srs_def] [-t_srs srs_def] [-to \"NAME=VALUE\"] [-novshiftgrid]\n"
         "    [-order n | -tps | -rpc | -geoloc] [-et err_threshold]\n"
         "    [-refine_gcps tolerance [minimum_gcps]]\n"
         "    [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]\n"
@@ -383,7 +419,7 @@ int main( int argc, char ** argv )
     {
 #if defined(__MACH__) && defined(__APPLE__)
         // On Mach, the default limit is 256 files per process
-        // We should eventually dynamically query the limit
+        // TODO We should eventually dynamically query the limit for all OS
         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100");
 #else
         CPLSetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "450");
@@ -518,12 +554,13 @@ int main( int argc, char ** argv )
     GDALWarpAppOptionsFree(psOptions);
     GDALWarpAppOptionsForBinaryFree(psOptionsForBinary);
 
+    // Close first hOutDS since it might reference sources (case of VRT)
+    GDALClose( hOutDS ? hOutDS : hDstDS );
     for(int i = 0; i < nSrcCount; i++)
     {
         GDALClose(pahSrcDS[i]);
     }
     CPLFree(pahSrcDS);
-    GDALClose( hOutDS ? hOutDS : hDstDS );
 
     GDALDumpOpenDatasets( stderr );
 
diff --git a/apps/gdalwarp_lib.cpp b/apps/gdalwarp_lib.cpp
index 457c2d4..4e2895b 100644
--- a/apps/gdalwarp_lib.cpp
+++ b/apps/gdalwarp_lib.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalwarp_lib.cpp 35888 2016-10-24 10:45:24Z rouault $
  *
  * Project:  High Performance Image Reprojector
  * Purpose:  Test program for high performance warper API.
@@ -30,19 +29,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdalwarper.h"
-#include "cpl_string.h"
+#include "cpl_port.h"
+#include "gdal_utils.h"
+#include "gdal_utils_priv.h"
+
+#include <cctype>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+#include <vector>
+
+#include "commonutils.h"
+#include "cpl_conv.h"
 #include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "gdal_priv.h"
+#include "gdalwarper.h"
+#include "ogr_api.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
 #include "ogr_spatialref.h"
-#include "ogr_api.h"
-#include "commonutils.h"
-#include "gdal_priv.h"
-#include <vector>
-#include <algorithm>
-#include "gdal_utils_priv.h"
+#include "ogr_srs_api.h"
+#include "vrtdataset.h"
 
-CPL_CVSID("$Id: gdalwarp_lib.cpp 35888 2016-10-24 10:45:24Z rouault $");
+CPL_CVSID("$Id: gdalwarp_lib.cpp 37987 2017-04-14 07:42:50Z rouault $");
 
 /************************************************************************/
 /*                        GDALWarpAppOptions                            */
@@ -96,10 +112,14 @@ struct GDALWarpAppOptions
     void *pProgressData;
 
     /*! creates an output alpha band to identify nodata (unset/transparent) pixels
-        when set to TRUE */
-    int bEnableDstAlpha;
+        when set to true */
+    bool bEnableDstAlpha;
 
-    int bEnableSrcAlpha;
+    /*! forces the last band of an input file to be considered as alpha band. */
+    bool bEnableSrcAlpha;
+
+    /*! Prevent a source alpha band from being considered as such */
+    bool bDisableSrcAlpha;
 
     /*! output format. The default is GeoTIFF (GTiff). Use the short format name. */
     char *pszFormat;
@@ -182,18 +202,21 @@ struct GDALWarpAppOptions
     char *pszMDConflictValue;
 
     /*! set the color interpretation of the bands of the target dataset from the source dataset */
-    int bSetColorInterpretation;
+    bool bSetColorInterpretation;
 
     /*! overview level of source files to be used */
     int nOvLevel;
+
+    /*! Whether to disable vertical grid shift adjustment */
+    bool bNoVShiftGrid;
 };
 
 static CPLErr
 LoadCutline( const char *pszCutlineDSName, const char *pszCLayer,
              const char *pszCWHERE, const char *pszCSQL,
-             void **phCutlineRet );
+             OGRGeometryH *phCutlineRet );
 static CPLErr
-TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
+TransformCutlineToSource( GDALDatasetH hSrcDS, OGRGeometryH hCutline,
                           char ***ppapszWarpOptions, char **papszTO );
 
 static GDALDatasetH
@@ -201,7 +224,7 @@ GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFile
                       const char *pszFormat, char **papszTO,
                       char ***ppapszCreateOptions, GDALDataType eDT,
                       void ** phTransformArg,
-                      int bSetColorInterpretation,
+                      bool bSetColorInterpretation,
                       GDALWarpAppOptions *psOptions);
 
 static void
@@ -256,10 +279,10 @@ static double GetAverageSegmentLength(OGRGeometryH hGeom)
 /*                           CropToCutline()                            */
 /************************************************************************/
 
-static CPLErr CropToCutline( void* hCutline, char** papszTO, int nSrcCount, GDALDatasetH *pahSrcDS,
+static CPLErr CropToCutline( OGRGeometryH hCutline, char** papszTO, int nSrcCount, GDALDatasetH *pahSrcDS,
                            double& dfMinX, double& dfMinY, double& dfMaxX, double &dfMaxY )
 {
-    OGRGeometryH hCutlineGeom = OGR_G_Clone( (OGRGeometryH) hCutline );
+    OGRGeometryH hCutlineGeom = OGR_G_Clone( hCutline );
     OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hCutlineGeom );
     const char *pszThisTargetSRS = CSLFetchNameValue( papszTO, "DST_SRS" );
     const char *pszThisSourceSRS = CSLFetchNameValue(papszTO, "SRC_SRS");
@@ -296,6 +319,21 @@ static CPLErr CropToCutline( void* hCutline, char** papszTO, int nSrcCount, GDAL
 
         if( pszProjection == NULL || pszProjection[0] == '\0' )
         {
+            if( pszThisTargetSRS == NULL && hCutlineSRS == NULL )
+            {
+                OGREnvelope sEnvelope;
+                OGR_G_GetEnvelope(hCutlineGeom, &sEnvelope);
+
+                dfMinX = sEnvelope.MinX;
+                dfMinY = sEnvelope.MinY;
+                dfMaxX = sEnvelope.MaxX;
+                dfMaxY = sEnvelope.MaxY;
+
+                OGR_G_DestroyGeometry(hCutlineGeom);
+
+                return CE_None;
+            }
+
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot compute bounding box of cutline.");
             OGR_G_DestroyGeometry(hCutlineGeom);
             return CE_Failure;
@@ -309,7 +347,6 @@ static CPLErr CropToCutline( void* hCutline, char** papszTO, int nSrcCount, GDAL
             OGR_G_DestroyGeometry(hCutlineGeom);
             return CE_Failure;
         }
-
     }
 
     if ( pszThisTargetSRS != NULL )
@@ -352,8 +389,7 @@ static CPLErr CropToCutline( void* hCutline, char** papszTO, int nSrcCount, GDAL
 
         for(int nIter=0;nIter<10;nIter++)
         {
-            if( hTransformedGeom != NULL )
-                OGR_G_DestroyGeometry(hTransformedGeom);
+            OGR_G_DestroyGeometry(hTransformedGeom);
             hTransformedGeom = OGR_G_Clone(hGeomInSrcSRS);
             if( hCTSrcToDst != NULL )
                 OGR_G_Transform( hTransformedGeom, hCTSrcToDst );
@@ -398,7 +434,6 @@ static CPLErr CropToCutline( void* hCutline, char** papszTO, int nSrcCount, GDAL
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                          GDALWarpAppOptionsClone()                   */
 /************************************************************************/
@@ -424,6 +459,227 @@ GDALWarpAppOptions* GDALWarpAppOptionsClone(const GDALWarpAppOptions *psOptionsI
 }
 
 /************************************************************************/
+/*                           Is3DGeogcs()                               */
+/************************************************************************/
+
+static bool Is3DGeogcs( const OGRSpatialReference& oSRS )
+{
+    const char* pszName = oSRS.GetAuthorityName(NULL);
+    const char* pszCode = oSRS.GetAuthorityCode(NULL);
+    // Yep, we only support that EPSG:4979, ie WGS 84 3D
+    return pszName != NULL && EQUAL(pszName, "EPSG") &&
+           pszCode != NULL && EQUAL(pszCode, "4979");
+}
+
+/************************************************************************/
+/*                      ApplyVerticalShiftGrid()                        */
+/************************************************************************/
+
+static GDALDatasetH ApplyVerticalShiftGrid( GDALDatasetH hWrkSrcDS,
+                                            const GDALWarpAppOptions* psOptions,
+                                            GDALDatasetH hVRTDS,
+                                            bool& bErrorOccurredOut )
+{
+    bErrorOccurredOut = false;
+    // Check if we must do vertical shift grid transform
+    double adfGT[6];
+    const char* pszSrcWKT = CSLFetchNameValueDef(
+                                    psOptions->papszTO, "SRC_SRS",
+                                    GDALGetProjectionRef(hWrkSrcDS) );
+    const char* pszDstWKT = CSLFetchNameValue( psOptions->papszTO, "DST_SRS" );
+    if( GDALGetRasterCount(hWrkSrcDS) == 1 &&
+        GDALGetGeoTransform(hWrkSrcDS, adfGT) == CE_None &&
+        pszSrcWKT != NULL && pszSrcWKT[0] != '\0' &&
+        pszDstWKT != NULL )
+    {
+        OGRSpatialReference oSRSSrc;
+        OGRSpatialReference oSRSDst;
+        if( oSRSSrc.SetFromUserInput( pszSrcWKT ) == OGRERR_NONE &&
+            oSRSDst.SetFromUserInput( pszDstWKT ) == OGRERR_NONE &&
+            (oSRSSrc.IsCompound() || Is3DGeogcs(oSRSSrc) ||
+             oSRSDst.IsCompound() || Is3DGeogcs(oSRSDst)) )
+        {
+            const char *pszSrcProj4Geoids =
+                oSRSSrc.GetExtension( "VERT_DATUM", "PROJ4_GRIDS" );
+            const char *pszDstProj4Geoids =
+                oSRSDst.GetExtension( "VERT_DATUM", "PROJ4_GRIDS" );
+
+            if( oSRSSrc.IsCompound() && pszSrcProj4Geoids == NULL )
+            {
+                CPLDebug("GDALWARP", "Source SRS is a compound CRS but lacks "
+                         "+geoidgrids");
+            }
+
+            if( oSRSDst.IsCompound() && pszDstProj4Geoids == NULL )
+            {
+                CPLDebug("GDALWARP", "Target SRS is a compound CRS but lacks "
+                         "+geoidgrids");
+            }
+
+            if( pszSrcProj4Geoids != NULL && pszDstProj4Geoids != NULL &&
+                EQUAL(pszSrcProj4Geoids, pszDstProj4Geoids) )
+            {
+                pszSrcProj4Geoids = NULL;
+                pszDstProj4Geoids = NULL;
+            }
+
+            // Select how to go from input dataset units to meters
+            const char* pszUnit =
+                GDALGetRasterUnitType( GDALGetRasterBand(hWrkSrcDS, 1) );
+            double dfToMeterSrc = 1.0;
+            if( pszUnit && (EQUAL(pszUnit, "m") ||
+                            EQUAL(pszUnit, "meter")||
+                            EQUAL(pszUnit, "metre")) )
+            {
+            }
+            else if( pszUnit && (EQUAL(pszUnit, "ft") ||
+                                 EQUAL(pszUnit, "foot")) )
+            {
+                dfToMeterSrc = CPLAtof(SRS_UL_FOOT_CONV);
+            }
+            else
+            {
+                if( pszUnit && !EQUAL(pszUnit, "") )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Unknown units=%s", pszUnit);
+                }
+                if( oSRSSrc.IsCompound() )
+                {
+                    dfToMeterSrc =
+                        oSRSSrc.GetTargetLinearUnits("VERT_CS");
+                }
+                else if( oSRSSrc.IsProjected() )
+                {
+                    dfToMeterSrc = oSRSSrc.GetLinearUnits();
+                }
+            }
+
+            double dfToMeterDst = 1.0;
+            if( oSRSDst.IsCompound() )
+            {
+                dfToMeterDst =
+                    oSRSDst.GetTargetLinearUnits("VERT_CS");
+            }
+            else if( oSRSDst.IsProjected() )
+            {
+                dfToMeterDst = oSRSDst.GetLinearUnits();
+            }
+
+            char** papszOptions = NULL;
+            if( psOptions->eOutputType != GDT_Unknown )
+            {
+                papszOptions = CSLSetNameValue(papszOptions,
+                        "DATATYPE",
+                        GDALGetDataTypeName(psOptions->eOutputType));
+            }
+            papszOptions = CSLSetNameValue(papszOptions,
+                "ERROR_ON_MISSING_VERT_SHIFT",
+                CSLFetchNameValue(psOptions->papszTO,
+                                  "ERROR_ON_MISSING_VERT_SHIFT"));
+            papszOptions = CSLSetNameValue(papszOptions, "SRC_SRS",
+                                           pszSrcWKT);
+
+            if( pszSrcProj4Geoids != NULL )
+            {
+                int bError = FALSE;
+                GDALDatasetH hGridDataset =
+                    GDALOpenVerticalShiftGrid(pszSrcProj4Geoids, &bError);
+                if( bError && hGridDataset == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot open %s.", pszSrcProj4Geoids);
+                    bErrorOccurredOut = true;
+                    CSLDestroy(papszOptions);
+                    return hWrkSrcDS;
+                }
+                else if( hGridDataset != NULL )
+                {
+                    // Transform from source vertical datum to WGS84
+                    GDALDatasetH hTmpDS = GDALApplyVerticalShiftGrid(
+                        hWrkSrcDS, hGridDataset, FALSE,
+                        dfToMeterSrc, 1.0, papszOptions );
+                    GDALReleaseDataset(hGridDataset);
+                    if( hTmpDS == NULL )
+                    {
+                        bErrorOccurredOut = true;
+                        CSLDestroy(papszOptions);
+                        return hWrkSrcDS;
+                    }
+                    else
+                    {
+                        if( hVRTDS )
+                        {
+                            VRTWarpedDataset* poVRTDS =
+                                reinterpret_cast<VRTWarpedDataset*>(hVRTDS);
+                            poVRTDS->SetApplyVerticalShiftGrid(
+                                pszSrcProj4Geoids,
+                                false,
+                                dfToMeterSrc, 1.0, papszOptions );
+                        }
+                        CPLDebug("GDALWARP", "Adjusting source dataset "
+                                 "with source vertical datum using %s",
+                                 pszSrcProj4Geoids);
+                        GDALReleaseDataset(hWrkSrcDS);
+                        hWrkSrcDS = hTmpDS;
+                        dfToMeterSrc = 1.0;
+                    }
+                }
+            }
+
+            if( pszDstProj4Geoids != NULL )
+            {
+                int bError = FALSE;
+                GDALDatasetH hGridDataset =
+                    GDALOpenVerticalShiftGrid(pszDstProj4Geoids, &bError);
+                if( bError && hGridDataset == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot open %s.", pszDstProj4Geoids);
+                    bErrorOccurredOut = true;
+                    CSLDestroy(papszOptions);
+                    return hWrkSrcDS;
+                }
+                else if( hGridDataset != NULL )
+                {
+                    // Transform from WGS84 to target vertical datum
+                    GDALDatasetH hTmpDS = GDALApplyVerticalShiftGrid(
+                        hWrkSrcDS, hGridDataset, TRUE,
+                        dfToMeterSrc, dfToMeterDst, papszOptions );
+                    GDALReleaseDataset(hGridDataset);
+                    if( hTmpDS == NULL )
+                    {
+                        bErrorOccurredOut = true;
+                        CSLDestroy(papszOptions);
+                        return hWrkSrcDS;
+                    }
+                    else
+                    {
+                        if( hVRTDS )
+                        {
+                            VRTWarpedDataset* poVRTDS =
+                                reinterpret_cast<VRTWarpedDataset*>(hVRTDS);
+                            poVRTDS->SetApplyVerticalShiftGrid(
+                                pszDstProj4Geoids,
+                                true,
+                                dfToMeterSrc, dfToMeterDst, papszOptions );
+                        }
+                        CPLDebug("GDALWARP", "Adjusting source dataset "
+                                 "with target vertical datum using %s",
+                                 pszDstProj4Geoids);
+                        GDALReleaseDataset(hWrkSrcDS);
+                        hWrkSrcDS = hTmpDS;
+                    }
+                }
+            }
+
+            CSLDestroy(papszOptions);
+        }
+    }
+    return hWrkSrcDS;
+}
+
+/************************************************************************/
 /*                             GDALWarp()                               */
 /************************************************************************/
 
@@ -442,7 +698,7 @@ GDALWarpAppOptions* GDALWarpAppOptionsClone(const GDALWarpAppOptions *psOptionsI
  * @param pahSrcDS the list of input datasets.
  * @param psOptionsIn the options struct returned by GDALWarpAppOptionsNew() or NULL.
  * @param pbUsageError the pointer to int variable to determine any usage error has occurred.
- * @return the output dataset (new dataset that must be closed using GDALClose(), or hDstDS is not NULL) or NULL in case of error.
+ * @return the output dataset (new dataset that must be closed using GDALClose(), or hDstDS if not NULL) or NULL in case of error.
  *
  * @since GDAL 2.1
  */
@@ -462,17 +718,26 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
     if( pszDest == NULL )
         pszDest = GDALGetDescription(hDstDS);
 
-    int bMustCloseDstDSInCaseOfError = (hDstDS == NULL);
+#ifdef DEBUG
+    GDALDataset* poDstDS = reinterpret_cast<GDALDataset*>(hDstDS);
+    const int nExpectedRefCountAtEnd = ( poDstDS != NULL ) ? poDstDS->GetRefCount() : 1;
+#endif
+    const bool bDropDstDSRef = (hDstDS != NULL);
+    if( hDstDS != NULL )
+        GDALReferenceDataset(hDstDS);
     GDALTransformerFunc pfnTransformer = NULL;
     void *hTransformArg = NULL;
     int bHasGotErr = FALSE;
     int bVRT = FALSE;
-    void *hCutline = NULL;
+    OGRGeometryH hCutline = NULL;
 
     GDALWarpAppOptions* psOptions =
         (psOptionsIn) ? GDALWarpAppOptionsClone(psOptionsIn) :
                         GDALWarpAppOptionsNew(NULL, NULL);
 
+    psOptions->papszTO = CSLSetNameValue(psOptions->papszTO,
+                                         "STRIP_VERT_CS", "YES");
+
     if( EQUAL(psOptions->pszFormat,"VRT") )
     {
         if( hDstDS != NULL )
@@ -600,8 +865,10 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
     if( psOptions->pszCutlineDSName != NULL )
     {
         CPLErr eError;
-        eError = LoadCutline( psOptions->pszCutlineDSName, psOptions->pszCLayer, psOptions->pszCWHERE, psOptions->pszCSQL,
-                     &hCutline );
+        eError = LoadCutline( psOptions->pszCutlineDSName,
+                              psOptions->pszCLayer,
+                              psOptions->pszCWHERE, psOptions->pszCSQL,
+                              &hCutline );
         if(eError == CE_Failure)
         {
             GDALWarpAppOptionsFree(psOptions);
@@ -617,7 +884,7 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
         if(eError == CE_Failure)
         {
             GDALWarpAppOptionsFree(psOptions);
-            OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+            OGR_G_DestroyGeometry( hCutline );
             return NULL;
         }
     }
@@ -626,7 +893,7 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
 /*      If not, we need to create it.                                   */
 /* -------------------------------------------------------------------- */
     void* hUniqueTransformArg = NULL;
-    int bInitDestSetByUser = ( CSLFetchNameValue( psOptions->papszWarpOptions, "INIT_DEST" ) != NULL );
+    const bool bInitDestSetByUser = ( CSLFetchNameValue( psOptions->papszWarpOptions, "INIT_DEST" ) != NULL );
 
     const char* pszWarpThreads = CSLFetchNameValue(psOptions->papszWarpOptions, "NUM_THREADS");
     if( pszWarpThreads != NULL )
@@ -637,6 +904,21 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
 
     if( hDstDS == NULL )
     {
+        if( nSrcCount == 1 && pahSrcDS[0] != NULL && !psOptions->bDisableSrcAlpha )
+        {
+            if( GDALGetRasterCount(pahSrcDS[0]) > 0 &&
+                GDALGetRasterColorInterpretation(
+                    GDALGetRasterBand(pahSrcDS[0],GDALGetRasterCount(pahSrcDS[0])) )
+                == GCI_AlphaBand )
+            {
+                psOptions->bEnableSrcAlpha = true;
+                psOptions->bEnableDstAlpha = true;
+                if( !psOptions->bQuiet )
+                    printf( "Using band %d of source image as alpha.\n",
+                            GDALGetRasterCount(pahSrcDS[0]) );
+            }
+        }
+
         hDstDS = GDALWarpCreateOutput( nSrcCount, pahSrcDS, pszDest,psOptions->pszFormat,
                                        psOptions->papszTO, &psOptions->papszCreateOptions,
                                        psOptions->eOutputType, &hUniqueTransformArg,
@@ -644,14 +926,14 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
                                        psOptions);
         if(hDstDS == NULL)
         {
-            if( hUniqueTransformArg )
-                GDALDestroyTransformer( hUniqueTransformArg );
+            GDALDestroyTransformer( hUniqueTransformArg );
             GDALWarpAppOptionsFree(psOptions);
-            if( hCutline != NULL )
-                OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+            OGR_G_DestroyGeometry( hCutline );
             return NULL;
         }
-
+#ifdef DEBUG
+        poDstDS = reinterpret_cast<GDALDataset*>(hDstDS);
+#endif
         psOptions->bCreateOutput = TRUE;
 
         if( !bInitDestSetByUser )
@@ -672,18 +954,27 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
         psOptions->papszCreateOptions = NULL;
     }
 
-    if( hDstDS == NULL )
+/* -------------------------------------------------------------------- */
+/*      Detect if output has alpha channel.                             */
+/* -------------------------------------------------------------------- */
+    bool bEnableDstAlpha = psOptions->bEnableDstAlpha;
+    if( !bEnableDstAlpha
+        && GDALGetRasterCount(hDstDS)
+        && GDALGetRasterColorInterpretation(
+            GDALGetRasterBand(hDstDS,GDALGetRasterCount(hDstDS)))
+        == GCI_AlphaBand && !psOptions->bDisableSrcAlpha )
     {
-        GDALWarpAppOptionsFree(psOptions);
-        return NULL;
+        if( !psOptions->bQuiet )
+            printf( "Using band %d of destination image as alpha.\n",
+                    GDALGetRasterCount(hDstDS) );
+
+        bEnableDstAlpha = true;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Loop over all source files, processing each in turn.            */
 /* -------------------------------------------------------------------- */
-    int iSrc;
-
-    for( iSrc = 0; iSrc < nSrcCount; iSrc++ )
+    for( int iSrc = 0; iSrc < nSrcCount; iSrc++ )
     {
         GDALDatasetH hSrcDS;
 
@@ -694,10 +985,8 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
         if( hSrcDS == NULL )
         {
             GDALWarpAppOptionsFree(psOptions);
-            if( hCutline != NULL )
-                OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
-            if( bMustCloseDstDSInCaseOfError )
-                GDALClose(hDstDS);
+            OGR_G_DestroyGeometry( hCutline );
+            GDALReleaseDataset(hDstDS);
             return NULL;
         }
 
@@ -708,10 +997,8 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Input file %s has no raster bands.", GDALGetDescription(hSrcDS) );
             GDALWarpAppOptionsFree(psOptions);
-            if( hCutline != NULL )
-                OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
-            if( bMustCloseDstDSInCaseOfError )
-                GDALClose(hDstDS);
+            OGR_G_DestroyGeometry( hCutline );
+            GDALReleaseDataset(hDstDS);
             return NULL;
         }
 
@@ -719,6 +1006,21 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
             printf( "Processing input file %s.\n", GDALGetDescription(hSrcDS) );
 
 /* -------------------------------------------------------------------- */
+/*      Do we have a source alpha band?                                 */
+/* -------------------------------------------------------------------- */
+        bool bEnableSrcAlpha = psOptions->bEnableSrcAlpha;
+        if( GDALGetRasterColorInterpretation(
+                GDALGetRasterBand(hSrcDS,GDALGetRasterCount(hSrcDS)) )
+            == GCI_AlphaBand
+            && !bEnableSrcAlpha && !psOptions->bDisableSrcAlpha )
+        {
+            bEnableSrcAlpha = true;
+            if( !psOptions->bQuiet )
+                printf( "Using band %d of source image as alpha.\n",
+                        GDALGetRasterCount(hSrcDS) );
+        }
+
+/* -------------------------------------------------------------------- */
 /*      Get the metadata of the first source DS and copy it to the      */
 /*      destination DS. Copy Band-level metadata and other info, only   */
 /*      if source and destination band count are equal. Any values that */
@@ -743,7 +1045,7 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
                 for( int i = 0; papszMetadata != NULL && papszMetadata[i] != NULL; i++ )
                 {
                     // Do not preserve NODATA_VALUES when the output includes an alpha band
-                    if( psOptions->bEnableDstAlpha &&
+                    if( bEnableDstAlpha &&
                         STARTS_WITH_CI(papszMetadata[i], "NODATA_VALUES=") )
                     {
                         continue;
@@ -760,6 +1062,14 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
 
                 CSLDestroy(papszMetadataNew);
 
+                /* ISIS3 -> ISIS3 special case */
+                if( EQUAL(psOptions->pszFormat, "ISIS3") )
+                {
+                    char** papszMD_ISIS3 = GDALGetMetadata( hSrcDS, "json:ISIS3");
+                    if( papszMD_ISIS3 != NULL)
+                        GDALSetMetadata(hDstDS, papszMD_ISIS3, "json:ISIS3");
+                }
+
                 /* copy band-level metadata and other info */
                 if ( GDALGetRasterCount( hSrcDS ) == GDALGetRasterCount( hDstDS ) )
                 {
@@ -847,21 +1157,6 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
         }
 
 /* -------------------------------------------------------------------- */
-/*      Do we have a source alpha band?                                 */
-/* -------------------------------------------------------------------- */
-        int bEnableSrcAlpha = psOptions->bEnableSrcAlpha;
-        if( GDALGetRasterColorInterpretation(
-                GDALGetRasterBand(hSrcDS,GDALGetRasterCount(hSrcDS)) )
-            == GCI_AlphaBand
-            && !bEnableSrcAlpha )
-        {
-            bEnableSrcAlpha = TRUE;
-            if( !psOptions->bQuiet )
-                printf( "Using band %d of source image as alpha.\n",
-                        GDALGetRasterCount(hSrcDS) );
-        }
-
-/* -------------------------------------------------------------------- */
 /*      Create a transformation object from the source to               */
 /*      destination coordinate system.                                  */
 /* -------------------------------------------------------------------- */
@@ -874,10 +1169,8 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
         if( hTransformArg == NULL )
         {
             GDALWarpAppOptionsFree(psOptions);
-            if( hCutline != NULL )
-                OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
-            if( bMustCloseDstDSInCaseOfError )
-                GDALClose(hDstDS);
+            OGR_G_DestroyGeometry( hCutline );
+            GDALReleaseDataset(hDstDS);
             return NULL;
         }
 
@@ -921,14 +1214,14 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
                     {
                         CPLDebug("WARP", "Selecting overview level %d for %s",
                                  iOvr, GDALGetDescription(hSrcDS));
-                        poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, iOvr, FALSE, FALSE );
+                        poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, iOvr, FALSE );
                     }
                 }
             }
         }
         else if( psOptions->nOvLevel >= 0 )
         {
-            poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, psOptions->nOvLevel, TRUE, FALSE );
+            poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, psOptions->nOvLevel, TRUE );
             if( poSrcOvrDS == NULL )
             {
                 if( !psOptions->bQuiet )
@@ -938,7 +1231,7 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
                             psOptions->nOvLevel, GDALGetDescription(hSrcDS), nOvCount - 1);
                 }
                 if( nOvCount > 0 )
-                    poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, nOvCount - 1, FALSE, FALSE );
+                    poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, nOvCount - 1, FALSE );
             }
             else
             {
@@ -947,8 +1240,29 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
             }
         }
 
+        if( poSrcOvrDS == NULL )
+            GDALReferenceDataset(hSrcDS);
+
         GDALDatasetH hWrkSrcDS = (poSrcOvrDS) ? (GDALDatasetH)poSrcOvrDS : hSrcDS;
 
+        if( !psOptions->bNoVShiftGrid )
+        {
+            bool bErrorOccurred = false;
+            hWrkSrcDS = ApplyVerticalShiftGrid( hWrkSrcDS,
+                                                psOptions,
+                                                bVRT ? hDstDS : NULL,
+                                                bErrorOccurred );
+            if( bErrorOccurred )
+            {
+                GDALDestroyTransformer( hTransformArg );
+                GDALWarpAppOptionsFree(psOptions);
+                OGR_G_DestroyGeometry( hCutline );
+                GDALReleaseDataset(hWrkSrcDS);
+                GDALReleaseDataset(hDstDS);
+                return NULL;
+            }
+        }
+
         /* We need to recreate the transform when operating on an overview */
         if( poSrcOvrDS != NULL )
         {
@@ -1021,20 +1335,6 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
         if( bEnableSrcAlpha )
             psWO->nSrcAlphaBand = GDALGetRasterCount(hWrkSrcDS);
 
-        int bEnableDstAlpha = psOptions->bEnableDstAlpha;
-        if( !bEnableDstAlpha
-            && GDALGetRasterCount(hDstDS) == psWO->nBandCount+1
-            && GDALGetRasterColorInterpretation(
-                GDALGetRasterBand(hDstDS,GDALGetRasterCount(hDstDS)))
-            == GCI_AlphaBand )
-        {
-            if( !psOptions->bQuiet )
-                printf( "Using band %d of destination image as alpha.\n",
-                        GDALGetRasterCount(hDstDS) );
-
-            bEnableDstAlpha = TRUE;
-        }
-
         if( bEnableDstAlpha )
             psWO->nDstAlphaBand = GDALGetRasterCount(hDstDS);
 
@@ -1068,8 +1368,13 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
 
             CSLDestroy( papszTokens );
 
-            psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
+            if( psWO->nBandCount > 1 &&
+                CSLFetchNameValue(psWO->papszWarpOptions, "UNIFIED_SRC_NODATA") == NULL )
+            {
+                CPLDebug("WARP", "Set UNIFIED_SRC_NODATA=YES");
+                psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
                                                "UNIFIED_SRC_NODATA", "YES" );
+            }
         }
 
 /* -------------------------------------------------------------------- */
@@ -1289,16 +1594,12 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
                                       psOptions->papszTO );
             if(eError == CE_Failure)
             {
-                if( hTransformArg != NULL )
-                    GDALDestroyTransformer( hTransformArg );
+                GDALDestroyTransformer( hTransformArg );
                 GDALDestroyWarpOptions( psWO );
                 GDALWarpAppOptionsFree(psOptions);
-                if( hCutline != NULL )
-                    OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
-                if( bMustCloseDstDSInCaseOfError )
-                    GDALClose(hDstDS);
-                if( poSrcOvrDS )
-                    delete poSrcOvrDS;
+                OGR_G_DestroyGeometry( hCutline );
+                GDALReleaseDataset(hWrkSrcDS);
+                GDALReleaseDataset(hDstDS);
                 return NULL;
             }
         }
@@ -1311,44 +1612,31 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
         if( bVRT )
         {
             GDALSetMetadataItem(hDstDS, "SrcOvrLevel", CPLSPrintf("%d", psOptions->nOvLevel), NULL);
-            if( GDALInitializeWarpedVRT( hDstDS, psWO ) != CE_None )
+            CPLErr eErr = GDALInitializeWarpedVRT( hDstDS, psWO );
+            GDALDestroyWarpOptions( psWO );
+            GDALWarpAppOptionsFree(psOptions);
+            OGR_G_DestroyGeometry( hCutline );
+            GDALReleaseDataset(hWrkSrcDS);
+            if( eErr != CE_None )
             {
-                if( hTransformArg != NULL )
-                    GDALDestroyTransformer( hTransformArg );
-                GDALDestroyWarpOptions( psWO );
-                GDALWarpAppOptionsFree(psOptions);
-                if( hCutline != NULL )
-                    OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
-                if( bMustCloseDstDSInCaseOfError )
-                    GDALClose(hDstDS);
-                if( poSrcOvrDS )
-                    delete poSrcOvrDS;
+                GDALDestroyTransformer( hTransformArg );
+                GDALReleaseDataset(hDstDS);
                 return NULL;
             }
-
-            // We need to close it before destroying poSrcOvrDS and warping options
-            CPLString osDstFilename(GDALGetDescription(hDstDS));
-
-            char** papszContent = NULL;
-            if( osDstFilename.size() == 0 )
-                papszContent = CSLDuplicate(GDALGetMetadata(hDstDS, "xml:VRT"));
-
-            GDALClose(hDstDS);
-
-            if( poSrcOvrDS )
-                delete poSrcOvrDS;
-
-            GDALDestroyWarpOptions( psWO );
-
-            GDALWarpAppOptionsFree(psOptions);
-            if( papszContent == NULL )
-                return GDALOpen(osDstFilename, GA_Update);
-            else
+            // In case of success, hDstDS has become the owner of hTransformArg
+            // so do not free it.
+            if( !EQUAL(pszDest, "") )
             {
-                GDALDatasetH hDSRet = GDALOpen(papszContent[0], GA_ReadOnly);
-                CSLDestroy(papszContent);
-                return hDSRet;
+                CPLErr eErrBefore = CPLGetLastErrorType();
+                GDALFlushCache( hDstDS );
+                if (eErrBefore == CE_None &&
+                    CPLGetLastErrorType() != CE_None)
+                {
+                    GDALReleaseDataset(hDstDS);
+                    hDstDS = NULL;
+                }
             }
+            return hDstDS;
         }
 
 /* -------------------------------------------------------------------- */
@@ -1370,17 +1658,19 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
             if (eErr != CE_None)
                 bHasGotErr = TRUE;
         }
+        else
+        {
+            bHasGotErr = TRUE;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-        if( hTransformArg != NULL )
-            GDALDestroyTransformer( hTransformArg );
+        GDALDestroyTransformer( hTransformArg );
 
         GDALDestroyWarpOptions( psWO );
 
-        if( poSrcOvrDS )
-            delete poSrcOvrDS;
+        GDALReleaseDataset(hWrkSrcDS);
     }
 
 /* -------------------------------------------------------------------- */
@@ -1394,13 +1684,20 @@ GDALDatasetH GDALWarp( const char *pszDest, GDALDatasetH hDstDS, int nSrcCount,
         bHasGotErr = TRUE;
     }
 
-    if( hCutline != NULL )
-        OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+    OGR_G_DestroyGeometry( hCutline );
 
     GDALWarpAppOptionsFree(psOptions);
 
-    if( bHasGotErr && bMustCloseDstDSInCaseOfError )
-        GDALClose(hDstDS);
+    if( bHasGotErr || bDropDstDSRef )
+        GDALReleaseDataset(hDstDS);
+
+#ifdef DEBUG
+    if( !bHasGotErr || bDropDstDSRef )
+    {
+        CPLAssert( poDstDS->GetRefCount() == nExpectedRefCountAtEnd );
+    }
+#endif
+
     return (bHasGotErr) ? NULL : hDstDS;
 }
 
@@ -1427,7 +1724,18 @@ static bool ValidateCutline(OGRGeometryH hGeom)
             char *pszWKT = NULL;
             OGR_G_ExportToWkt( hGeom, &pszWKT );
             CPLDebug("GDALWARP", "WKT = \"%s\"", pszWKT ? pszWKT : "(null)");
-            //fprintf(stderr, "WKT = \"%s\"\n", pszWKT ? pszWKT : "(null)");
+            const char* pszFile = CPLGetConfigOption("GDALWARP_DUMP_WKT_TO_FILE", NULL);
+            if( pszFile && pszWKT )
+            {
+                FILE* f = EQUAL(pszFile, "stderr") ? stderr : fopen(pszFile, "wb");
+                if( f )
+                {
+                    fprintf(f, "id,WKT\n");
+                    fprintf(f, "1,\"%s\"\n", pszWKT);
+                    if( !EQUAL(pszFile, "stderr") )
+                        fclose(f);
+                }
+            }
             CPLFree( pszWKT );
 
             if( CPLTestBool(CPLGetConfigOption("GDALWARP_IGNORE_BAD_CUTLINE", "NO")) )
@@ -1449,6 +1757,40 @@ static bool ValidateCutline(OGRGeometryH hGeom)
 }
 
 /************************************************************************/
+/*                     LooseValidateCutline()                           */
+/*                                                                      */
+/*  Same as OGR_G_IsValid() except that it processes polygon per polygon*/
+/*  without paying attention to MultiPolygon specific validity rules.   */
+/************************************************************************/
+
+static bool LooseValidateCutline(OGRGeometryH hGeom)
+{
+    OGRwkbGeometryType eType = wkbFlatten(OGR_G_GetGeometryType( hGeom ));
+    if( eType == wkbMultiPolygon )
+    {
+        for( int iGeom = 0; iGeom < OGR_G_GetGeometryCount( hGeom ); iGeom++ )
+        {
+            OGRGeometryH hPoly = OGR_G_GetGeometryRef(hGeom,iGeom);
+            if( !LooseValidateCutline(hPoly) )
+                return false;
+        }
+    }
+    else if( eType == wkbPolygon )
+    {
+        if( OGRGeometryFactory::haveGEOS() && !OGR_G_IsValid(hGeom) )
+        {
+            return false;
+        }
+    }
+    else
+    {
+        return false;
+    }
+
+    return true;
+}
+
+/************************************************************************/
 /*                            LoadCutline()                             */
 /*                                                                      */
 /*      Load blend cutline from OGR datasource.                         */
@@ -1457,7 +1799,7 @@ static bool ValidateCutline(OGRGeometryH hGeom)
 static CPLErr
 LoadCutline( const char *pszCutlineDSName, const char *pszCLayer,
              const char *pszCWHERE, const char *pszCSQL,
-             void **phCutlineRet )
+             OGRGeometryH* phCutlineRet )
 
 {
     OGRRegisterAll();
@@ -1555,7 +1897,7 @@ LoadCutline( const char *pszCutlineDSName, const char *pszCLayer,
     OGR_G_AssignSpatialReference(
         hMultiPolygon, OGR_L_GetSpatialRef(hLayer) );
 
-    *phCutlineRet = (void *) hMultiPolygon;
+    *phCutlineRet = hMultiPolygon;
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
@@ -1590,10 +1932,9 @@ GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFile
                       const char *pszFormat, char **papszTO,
                       char ***ppapszCreateOptions, GDALDataType eDT,
                       void ** phTransformArg,
-                      int bSetColorInterpretation,
+                      bool bSetColorInterpretation,
                       GDALWarpAppOptions *psOptions)
 
-
 {
     GDALDriverH hDriver;
     GDALDatasetH hDstDS;
@@ -1708,8 +2049,9 @@ GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFile
 
             for(int iBand = 0; iBand < nDstBandCount; iBand++)
             {
-                apeColorInterpretations.push_back(
-                    GDALGetRasterColorInterpretation(GDALGetRasterBand(pahSrcDS[iSrc],iBand+1)) );
+                GDALColorInterp eInterp =
+                    GDALGetRasterColorInterpretation(GDALGetRasterBand(pahSrcDS[iSrc],iBand+1));
+                apeColorInterpretations.push_back( eInterp );
             }
         }
 
@@ -1736,7 +2078,7 @@ GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFile
                 pszThisSourceSRS = "";
         }
 
-        if( osThisTargetSRS.size() == 0 )
+        if( osThisTargetSRS.empty() )
             osThisTargetSRS = pszThisSourceSRS;
 
 /* -------------------------------------------------------------------- */
@@ -1846,16 +2188,17 @@ GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFile
                 dfWrkMaxY = adfExtent[3];
                 dfWrkMinY = adfExtent[1];
                 dfWrkResX = adfThisGeoTransform[1];
-                dfWrkResY = ABS(adfThisGeoTransform[5]);
+                dfWrkResY = std::abs(adfThisGeoTransform[5]);
             }
             else
             {
-                dfWrkMinX = MIN(dfWrkMinX,adfExtent[0]);
-                dfWrkMaxX = MAX(dfWrkMaxX,adfExtent[2]);
-                dfWrkMaxY = MAX(dfWrkMaxY,adfExtent[3]);
-                dfWrkMinY = MIN(dfWrkMinY,adfExtent[1]);
-                dfWrkResX = MIN(dfWrkResX,adfThisGeoTransform[1]);
-                dfWrkResY = MIN(dfWrkResY,ABS(adfThisGeoTransform[5]));
+                dfWrkMinX = std::min(dfWrkMinX, adfExtent[0]);
+                dfWrkMaxX = std::max(dfWrkMaxX, adfExtent[2]);
+                dfWrkMaxY = std::max(dfWrkMaxY, adfExtent[3]);
+                dfWrkMinY = std::min(dfWrkMinY,adfExtent[1]);
+                dfWrkResX = std::min(dfWrkResX,adfThisGeoTransform[1]);
+                dfWrkResY =
+                    std::min(dfWrkResY, std::abs(adfThisGeoTransform[5]));
             }
         }
 
@@ -2022,6 +2365,27 @@ GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFile
     if( psOptions->bEnableDstAlpha )
         nDstBandCount++;
 
+    if( EQUAL(pszFormat, "GTiff") )
+    {
+
+/* -------------------------------------------------------------------- */
+/*      Automatically set PHOTOMETRIC=RGB for GTiff when appropriate    */
+/* -------------------------------------------------------------------- */
+        if ( apeColorInterpretations.size() >= 3 &&
+            apeColorInterpretations[0] == GCI_RedBand &&
+            apeColorInterpretations[1] == GCI_GreenBand &&
+            apeColorInterpretations[2] == GCI_BlueBand &&
+            CSLFetchNameValue( *ppapszCreateOptions, "PHOTOMETRIC" ) == NULL )
+        {
+            *ppapszCreateOptions = CSLSetNameValue(*ppapszCreateOptions,
+                                                "PHOTOMETRIC", "RGB");
+        }
+
+        /* The GTiff driver now supports writing band color interpretation */
+        /* in the TIFF_GDAL_METADATA tag */
+        bSetColorInterpretation = true;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
@@ -2054,8 +2418,7 @@ GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFile
     }
     else
     {
-        adfDstGeoTransform[0] = 0.0;
-        adfDstGeoTransform[3] = 0.0;
+        adfDstGeoTransform[3] += adfDstGeoTransform[5] * nLines;
         adfDstGeoTransform[5] = fabs(adfDstGeoTransform[5]);
     }
 
@@ -2065,9 +2428,9 @@ GDALWarpCreateOutput( int nSrcCount, GDALDatasetH *pahSrcDS, const char *pszFile
 /* -------------------------------------------------------------------- */
 /*      Try to set color interpretation of source bands to target       */
 /*      dataset.                                                        */
-/*      FIXME? We should likely do that for other drivers than VRT      */
-/*      but it might create spurious .aux.xml files (at least with HFA, */
-/*      and netCDF)                                                     */
+/*      FIXME? We should likely do that for other drivers than VRT &    */
+/*      GTiff  but it might create spurious .aux.xml files (at least    */
+/*      with HFA, and netCDF)                                           */
 /* -------------------------------------------------------------------- */
     if( bVRT || bSetColorInterpretation )
     {
@@ -2117,11 +2480,11 @@ public:
 
     void         *hSrcImageTransformer;
 
-    virtual OGRSpatialReference *GetSourceCS() { return NULL; }
-    virtual OGRSpatialReference *GetTargetCS() { return NULL; }
+    virtual OGRSpatialReference *GetSourceCS() override { return NULL; }
+    virtual OGRSpatialReference *GetTargetCS() override { return NULL; }
 
     virtual int Transform( int nCount,
-                           double *x, double *y, double *z = NULL ) {
+                           double *x, double *y, double *z = NULL ) override {
         int nResult;
 
         int *pabSuccess = (int *) CPLCalloc(sizeof(int),nCount);
@@ -2133,7 +2496,7 @@ public:
 
     virtual int TransformEx( int nCount,
                              double *x, double *y, double *z = NULL,
-                             int *pabSuccess = NULL ) {
+                             int *pabSuccess = NULL ) override {
         return GDALGenImgProjTransform( hSrcImageTransformer, TRUE,
                                         nCount, x, y, z, pabSuccess );
     }
@@ -2183,7 +2546,7 @@ double GetMaximumSegmentLength( OGRGeometry* poGeom )
         }
 
         default:
-            CPLAssert(0);
+            CPLAssert(false);
             return 0.0;
     }
 }
@@ -2194,19 +2557,18 @@ double GetMaximumSegmentLength( OGRGeometry* poGeom )
 /*      Transform cutline from its SRS to source pixel/line coordinates.*/
 /************************************************************************/
 static CPLErr
-TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
+TransformCutlineToSource( GDALDatasetH hSrcDS, OGRGeometryH hCutline,
                           char ***ppapszWarpOptions, char **papszTO_In )
 
 {
-    OGRGeometryH hMultiPolygon = OGR_G_Clone( (OGRGeometryH) hCutline );
-    char **papszTO = CSLDuplicate( papszTO_In );
+    OGRGeometryH hMultiPolygon = OGR_G_Clone( hCutline );
 
 /* -------------------------------------------------------------------- */
 /*      Checkout that if there's a cutline SRS, there's also a raster   */
 /*      one.                                                            */
 /* -------------------------------------------------------------------- */
     OGRSpatialReferenceH  hRasterSRS = NULL;
-    const char *pszProjection = CSLFetchNameValue( papszTO, "SRC_SRS" );
+    const char *pszProjection = CSLFetchNameValue( papszTO_In, "SRC_SRS" );
     if( pszProjection == NULL )
     {
         char** papszMD;
@@ -2232,7 +2594,35 @@ TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
         }
     }
 
+/* -------------------------------------------------------------------- */
+/*      Extract the cutline SRS.                                        */
+/* -------------------------------------------------------------------- */
     OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hMultiPolygon );
+
+/* -------------------------------------------------------------------- */
+/*      Detect if there's no transform at all involved, in which case   */
+/*      we can avoid densification.                                     */
+/* -------------------------------------------------------------------- */
+    bool bMayNeedDensify = true;
+    if( hRasterSRS != NULL && hCutlineSRS != NULL &&
+        OSRIsSame(hRasterSRS, hCutlineSRS) &&
+        GDALGetGCPCount( hSrcDS ) == 0 &&
+        GDALGetMetadata( hSrcDS, "RPC" ) == NULL &&
+        GDALGetMetadata( hSrcDS, "GEOLOCATION" ) == NULL )
+    {
+        char **papszTOTmp = CSLDuplicate( papszTO_In );
+        papszTOTmp = CSLSetNameValue(papszTOTmp, "SRC_SRS", NULL);
+        papszTOTmp = CSLSetNameValue(papszTOTmp, "DST_SRS", NULL);
+        if( CSLCount(papszTOTmp) == 0 )
+        {
+            bMayNeedDensify = false;
+        }
+        CSLDestroy(papszTOTmp);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Compare source raster SRS and cutline SRS                       */
+/* -------------------------------------------------------------------- */
     if( hRasterSRS != NULL && hCutlineSRS != NULL )
     {
         /* OK, we will reproject */
@@ -2254,9 +2644,7 @@ TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
     if( hRasterSRS != NULL )
         OSRDestroySpatialReference(hRasterSRS);
 
-/* -------------------------------------------------------------------- */
-/*      Extract the cutline SRS WKT.                                    */
-/* -------------------------------------------------------------------- */
+    char **papszTO = CSLDuplicate( papszTO_In );
     if( hCutlineSRS != NULL )
     {
         char *pszCutlineSRS_WKT = NULL;
@@ -2305,10 +2693,19 @@ TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
                             reinterpret_cast<OGRGeometry*>(hMultiPolygon) );
 
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    const bool bWasValidInitialy = OGR_G_IsValid(hMultiPolygon) != FALSE;
+    const bool bWasValidInitialy = LooseValidateCutline(hMultiPolygon);
     CPLPopErrorHandler();
+    if( !bWasValidInitialy )
+    {
+        CPLDebug("WARP", "Cutline is not valid after initial reprojection");
+        char *pszWKT = NULL;
+        OGR_G_ExportToWkt( hMultiPolygon, &pszWKT );
+        CPLDebug("GDALWARP", "WKT = \"%s\"", pszWKT ? pszWKT : "(null)");
+        CPLFree(pszWKT);
+    }
+
     bool bDensify = false;
-    if( eErr == OGRERR_NONE && dfInitialMaxLengthInPixels > 1.0 )
+    if( bMayNeedDensify && eErr == OGRERR_NONE && dfInitialMaxLengthInPixels > 1.0 )
     {
         const char* pszDensifyCutline = CPLGetConfigOption("GDALWARP_DENSIFY_CUTLINE", "YES");
         if( EQUAL(pszDensifyCutline, "ONLY_IF_INVALID") )
@@ -2335,11 +2732,20 @@ TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
 
         // Densify and reproject with the aim of having a 1 pixel density
         double dfSegmentSize = dfMaxLengthInSpatUnits / dfInitialMaxLengthInPixels;
-        for(int i=0;i<10;i++)
+        const int MAX_ITERATIONS = 10;
+        for(int i=0;i<MAX_ITERATIONS;i++)
         {
             OGR_G_DestroyGeometry( hMultiPolygon );
-            hMultiPolygon = OGR_G_Clone( (OGRGeometryH) hCutline );
+            hMultiPolygon = OGR_G_Clone( hCutline );
             OGR_G_Segmentize(hMultiPolygon, dfSegmentSize);
+            if( i == MAX_ITERATIONS - 1 )
+            {
+                char* pszWKT = NULL;
+                OGR_G_ExportToWkt(hMultiPolygon, &pszWKT);
+                CPLDebug("WARP", "WKT of polygon after densification with segment size = %f: %s",
+                         dfSegmentSize, pszWKT);
+                CPLFree(pszWKT);
+            }
             eErr = OGR_G_Transform( hMultiPolygon,
                         (OGRCoordinateTransformationH) &oTransformer );
             if( eErr == OGRERR_NONE )
@@ -2352,10 +2758,23 @@ TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
                     // invalid polygon due to the non-linearity of RPC DEM transformation,
                     // so in those cases, try a less dense cutline
                     CPLPushErrorHandler(CPLQuietErrorHandler);
-                    const bool bIsValid = OGR_G_IsValid(hMultiPolygon) != FALSE;
+                    const bool bIsValid = LooseValidateCutline(hMultiPolygon);
                     CPLPopErrorHandler();
                     if( !bIsValid )
                     {
+                        if( i == MAX_ITERATIONS - 1 )
+                        {
+                            char* pszWKT = NULL;
+                            OGR_G_ExportToWkt(hMultiPolygon, &pszWKT);
+                            CPLDebug("WARP",
+                                     "After densification, cutline maximum "
+                                     "segment size is now %.0f pixel, "
+                                     "but cutline is invalid. %s",
+                                     dfMaxLengthInPixels,
+                                     pszWKT);
+                            CPLFree(pszWKT);
+                            break;
+                        }
                         CPLDebug("WARP", "After densification, cutline maximum segment size is now %.0f pixel, "
                                  "but cutline is invalid. So trying a less dense cutline.",
                                  dfMaxLengthInPixels);
@@ -2502,8 +2921,9 @@ GDALWarpAppOptions *GDALWarpAppOptionsNew(char** papszArgv,
     psOptions->bQuiet = TRUE;
     psOptions->pfnProgress = GDALDummyProgress;
     psOptions->pProgressData = NULL;
-    psOptions->bEnableDstAlpha = FALSE;
-    psOptions->bEnableSrcAlpha = FALSE;
+    psOptions->bEnableDstAlpha = false;
+    psOptions->bEnableSrcAlpha = false;
+    psOptions->bDisableSrcAlpha = false;
     psOptions->pszFormat = CPLStrdup("GTiff");
     psOptions->bCreateOutput = FALSE;
     psOptions->papszWarpOptions = NULL;
@@ -2525,14 +2945,15 @@ GDALWarpAppOptions *GDALWarpAppOptionsNew(char** papszArgv,
     psOptions->bCopyMetadata = TRUE;
     psOptions->bCopyBandInfo = TRUE;
     psOptions->pszMDConflictValue = CPLStrdup("*");
-    psOptions->bSetColorInterpretation = FALSE;
+    psOptions->bSetColorInterpretation = false;
     psOptions->nOvLevel = -2;
+    psOptions->bNoVShiftGrid = false;
 
 /* -------------------------------------------------------------------- */
 /*      Parse arguments.                                                */
 /* -------------------------------------------------------------------- */
     int argc = CSLCount(papszArgv);
-    for( int i = 0; i < argc; i++ )
+    for( int i = 0; papszArgv != NULL && i < argc; i++ )
     {
         if( EQUAL(papszArgv[i],"-tps") || EQUAL(papszArgv[i],"-rpc") || EQUAL(papszArgv[i],"-geoloc")  )
         {
@@ -2568,11 +2989,15 @@ GDALWarpAppOptions *GDALWarpAppOptionsNew(char** papszArgv,
         }
         else if( EQUAL(papszArgv[i],"-dstalpha") )
         {
-            psOptions->bEnableDstAlpha = TRUE;
+            psOptions->bEnableDstAlpha = true;
         }
         else if( EQUAL(papszArgv[i],"-srcalpha") )
         {
-            psOptions->bEnableSrcAlpha = TRUE;
+            psOptions->bEnableSrcAlpha = true;
+        }
+        else if( EQUAL(papszArgv[i],"-nosrcalpha") )
+        {
+            psOptions->bDisableSrcAlpha = true;
         }
         else if( EQUAL(papszArgv[i],"-of") && i+1 < argc )
         {
@@ -2862,7 +3287,7 @@ GDALWarpAppOptions *GDALWarpAppOptionsNew(char** papszArgv,
             psOptions->pszMDConflictValue = CPLStrdup(papszArgv[++i]);
         }
         else if( EQUAL(papszArgv[i],"-setci") )
-            psOptions->bSetColorInterpretation = TRUE;
+            psOptions->bSetColorInterpretation = true;
         else if( EQUAL(papszArgv[i], "-oo") && i+1 < argc )
         {
             if( psOptionsForBinary )
@@ -2895,6 +3320,10 @@ GDALWarpAppOptions *GDALWarpAppOptionsNew(char** papszArgv,
                 return NULL;
             }
         }
+        else if( EQUAL(papszArgv[i],"-novshiftgrid") )
+        {
+            psOptions->bNoVShiftGrid = true;
+        }
         else if( papszArgv[i][0] == '-' )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
@@ -2912,6 +3341,14 @@ GDALWarpAppOptions *GDALWarpAppOptionsNew(char** papszArgv,
         }
     }
 
+    if( psOptions->bEnableSrcAlpha && psOptions->bDisableSrcAlpha )
+    {
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "-srcalpha and -nosrcalpha cannot be used together");
+        GDALWarpAppOptionsFree(psOptions);
+        return NULL;
+    }
+
     if( psOptionsForBinary )
         psOptionsForBinary->bCreateOutput = psOptions->bCreateOutput;
 
diff --git a/apps/gdalwarpsimple.c b/apps/gdalwarpsimple.c
index bade362..526e698 100644
--- a/apps/gdalwarpsimple.c
+++ b/apps/gdalwarpsimple.c
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalwarpsimple.c 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Mapinfo Image Warper
  * Purpose:  Commandline program for doing a variety of image warps, including
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gdalwarpsimple.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gdalwarpsimple.c 35226 2016-08-28 13:49:13Z goatbar $");
 
 static GDALDatasetH
 GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
@@ -41,8 +40,8 @@ GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
                       const char *pszTargetSRS, int nOrder,
                       char **papszCreateOptions );
 
-static double	       dfMinX=0.0, dfMinY=0.0, dfMaxX=0.0, dfMaxY=0.0;
-static double	       dfXRes=0.0, dfYRes=0.0;
+static double          dfMinX=0.0, dfMinY=0.0, dfMaxX=0.0, dfMaxY=0.0;
+static double          dfXRes=0.0, dfYRes=0.0;
 static int             nForcePixels=0, nForceLines=0;
 
 /************************************************************************/
@@ -95,7 +94,7 @@ char *SanitizeSRS( const char *pszUserInput )
 int main( int argc, char ** argv )
 
 {
-    GDALDatasetH	hSrcDS, hDstDS;
+    GDALDatasetH        hSrcDS, hDstDS;
     const char         *pszFormat = "GTiff";
     char               *pszTargetSRS = NULL;
     char               *pszSourceSRS = NULL;
@@ -343,7 +342,7 @@ GDALWarpCreateOutput( GDALDatasetH hSrcDS, const char *pszFilename,
     if( hDriver == NULL
         || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
     {
-        int	iDr;
+        int iDr;
 
         printf( "Output driver `%s' not recognised or does not support\n",
                 pszFormat );
diff --git a/apps/gnm_utilities.dox b/apps/gnm_utilities.dox
index 793354c..763585e 100644
--- a/apps/gnm_utilities.dox
+++ b/apps/gnm_utilities.dox
@@ -30,7 +30,7 @@ gnmmanage [--help][-q][-quiet][--long-usage]
           [delete]
           [change [-bl gfid][-unbl gfid][-unblall]]
           gnm_name [layer [layer ...]]
-          
+
 \endverbatim
 
 \section gnmmanage_description DESCRIPTION
@@ -109,7 +109,7 @@ gnmanalyse [--help][-q][-quiet][--long-usage]
 
 \section gnmanalyse_description DESCRIPTION
 
-The gnmanalyse program provides analysing capabilities of geographical networks in GDAL. The results of calculations are return in an OGRLayer format or as a console text output if such layer is undefined. All calculations are made considering the blocking state of features. 
+The gnmanalyse program provides analysing capabilities of geographical networks in GDAL. The results of calculations are return in an OGRLayer format or as a console text output if such layer is undefined. All calculations are made considering the blocking state of features.
 
 <dl>
 
@@ -133,7 +133,7 @@ The gnmanalyse program provides analysing capabilities of geographical networks
 </dl>
 
 \if man
-\section gnmmanage_author AUTHORS
+\section gnmanalyse_author AUTHORS
 Mikhail Gusev <gusevmihs at gmail.com>
 Dmitry Baryshnikov <polimax at mail.ru>
 \endif
diff --git a/apps/gnmanalyse.cpp b/apps/gnmanalyse.cpp
index 9bab435..bf8f159 100755
--- a/apps/gnmanalyse.cpp
+++ b/apps/gnmanalyse.cpp
@@ -27,10 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gnm.h"
 #include "commonutils.h"
+#include "gnm.h"
+#include "gnm_priv.h"
 #include "ogr_p.h"
 
+CPL_CVSID("$Id: gnmanalyse.cpp 36533 2016-11-27 23:45:39Z goatbar $");
+
 enum operation
 {
     op_unknown = 0, /** no operation */
@@ -359,7 +362,7 @@ static void ReportOnLayer( OGRLayer * poLayer, int bVerbose )
     do { if (iArg + nExtraArg >= nArgc) \
         Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], \
                 nExtraArg)); \
-        } while(0)
+        } while( false )
 
 int main( int nArgc, char ** papszArgv )
 
@@ -403,8 +406,6 @@ int main( int nArgc, char ** papszArgv )
         exit( -nArgc );
     }
 
-
-
     for( int iArg = 1; iArg < nArgc; iArg++ )
     {
         if( EQUAL(papszArgv[1], "--utility_version") )
diff --git a/apps/gnmmanage.cpp b/apps/gnmmanage.cpp
index 7c52708..af71249 100755
--- a/apps/gnmmanage.cpp
+++ b/apps/gnmmanage.cpp
@@ -27,16 +27,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal.h"
 #include "commonutils.h"
 #include "cpl_string.h"
+#include "gdal.h"
 #include "gnm.h"
+#include "gnm_priv.h"
 
 //#include "ogr_p.h"
 //#include "gnm.h"
 //#include "gnm_api.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: gnmmanage.cpp 36533 2016-11-27 23:45:39Z goatbar $");
 
 enum operation
 {
@@ -93,27 +94,27 @@ static void Usage(const char* pszAdditionalMsg, int bShort)
         const char *pszRFlag = "", *pszWFlag, *pszVirtualIO, *pszSubdatasets;
         char** papszMD = GDALGetMetadata( hDriver, NULL );
 
-        if( CSLFetchBoolean( papszMD, GDAL_DCAP_RASTER, FALSE ) )
+        if( CPLFetchBool( papszMD, GDAL_DCAP_RASTER, false ) )
             continue;
-        if( CSLFetchBoolean( papszMD, GDAL_DCAP_VECTOR, FALSE ) )
+        if( CPLFetchBool( papszMD, GDAL_DCAP_VECTOR, false ) )
             continue;
 
-        if( CSLFetchBoolean( papszMD, GDAL_DCAP_OPEN, FALSE ) )
+        if( CPLFetchBool( papszMD, GDAL_DCAP_OPEN, false ) )
             pszRFlag = "r";
 
-        if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATE, FALSE ) )
+        if( CPLFetchBool( papszMD, GDAL_DCAP_CREATE, false ) )
             pszWFlag = "w+";
-        else if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATECOPY, FALSE ) )
+        else if( CPLFetchBool( papszMD, GDAL_DCAP_CREATECOPY, false ) )
             pszWFlag = "w";
         else
             pszWFlag = "o";
 
-        if( CSLFetchBoolean( papszMD, GDAL_DCAP_VIRTUALIO, FALSE ) )
+        if( CPLFetchBool( papszMD, GDAL_DCAP_VIRTUALIO, false ) )
             pszVirtualIO = "v";
         else
             pszVirtualIO = "";
 
-        if( CSLFetchBoolean( papszMD, GDAL_DMD_SUBDATASETS, FALSE ) )
+        if( CPLFetchBool( papszMD, GDAL_DMD_SUBDATASETS, false ) )
             pszSubdatasets = "s";
         else
             pszSubdatasets = "";
@@ -153,14 +154,14 @@ static void Usage(int bShort = TRUE)
     Usage(NULL, bShort);
 }
 
-
 /************************************************************************/
 /*                                main()                                */
 /************************************************************************/
 
 #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
     do { if (iArg + nExtraArg >= nArgc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
+        Usage(CPLSPrintf("%s option requires %d argument(s)", \
+                         papszArgv[iArg], nExtraArg)); } while( false )
 
 int main( int nArgc, char ** papszArgv )
 
@@ -387,7 +388,11 @@ int main( int nArgc, char ** papszArgv )
             exit(1);
         }
 
-        CPLAssert( poDriver != NULL);
+        if( poDriver == NULL )
+        {
+            CPLAssert( false );
+            exit(1);
+        }
 
         printf( "INFO: Open of `%s'\n      using driver `%s' successful.\n",
                     pszDataSource, poDriver->GetDescription() );
@@ -469,7 +474,6 @@ int main( int nArgc, char ** papszArgv )
                 }
             }
         }
-
     }
     else if(stOper == op_create)
     {
@@ -514,7 +518,7 @@ int main( int nArgc, char ** papszArgv )
 
         char** papszMD = poDriver->GetMetadata();
 
-        if( !CSLFetchBoolean( papszMD, GDAL_DCAP_GNM, FALSE ) )
+        if( !CPLFetchBool( papszMD, GDAL_DCAP_GNM, false ) )
             Usage("not a GNM driver");
 
         poDS = (GNMNetwork*) poDriver->Create( pszPath, 0, 0, 0, GDT_Unknown,
@@ -534,7 +538,6 @@ int main( int nArgc, char ** papszArgv )
                    "new dataset at %s\n", CPLFormFilename(pszPath,
                     pszNetworkName, NULL));
         }
-
     }
     else if(stOper == op_import)
     {
@@ -544,7 +547,6 @@ int main( int nArgc, char ** papszArgv )
         if(pszInputDataset == NULL)
             Usage("No input dataset name provided");
 
-
         // open
         poDS = (GNMNetwork*) GDALOpenEx( pszDataSource,
                              GDAL_OF_READONLY | GDAL_OF_GNM, NULL, NULL, NULL );
@@ -786,7 +788,6 @@ int main( int nArgc, char ** papszArgv )
         {
             printf("Features connected successfully\n");
         }
-
     }
     else if(stOper == op_delete)
     {
diff --git a/apps/makefile.vc b/apps/makefile.vc
index 80f7d5f..6e33f33 100644
--- a/apps/makefile.vc
+++ b/apps/makefile.vc
@@ -3,14 +3,12 @@ GDAL_ROOT	=	..
 
 XTRAOBJ =	$(SETARGV)
 
-LIBS	=	$(GDAL_ROOT)\gdal_i.lib
-
-XTRAFLAGS =	-I..\gcore -I..\port -I..\frmts\vrt -I..\alg -I..\ogr -I..\ogr\ogrsf_frmts  $(GEOS_CFLAGS) -I..\ogr\ogrsf_frmts\geojson\libjson -I..\ogr\ogrsf_frmts\geojson
-
-EXTRAFLAGS =    -I..\frmts\vrt -I..\ogr\ogrsf_frmts\geojson\libjson -I..\ogr\ogrsf_frmts\geojson
+EXTRAFLAGS =	-I..\gcore -I..\port -I..\frmts\vrt -I..\alg -I..\ogr -I..\ogr\ogrsf_frmts  $(GEOS_CFLAGS) -I..\ogr\ogrsf_frmts\geojson\libjson -I..\ogr\ogrsf_frmts\geojson -I..\ogr\ogrsf_frmts\generic
 
 !INCLUDE ..\nmake.opt
 
+LIBS	=	$(GDALLIB)
+
 !IFDEF INCLUDE_OGR_FRMTS
 OGR_PROGRAMS =	gdal_contour.exe gdaltindex.exe gdal_rasterize.exe \
 		gdal_grid.exe ogrinfo.exe ogr2ogr.exe ogrtindex.exe ogrlineref.exe\
@@ -35,170 +33,170 @@ OBJ = commonutils.obj gdalinfo_lib.obj gdal_translate_lib.obj gdalwarp_lib.obj o
 appslib: $(OBJ)
 
 gdalinfo.exe:	gdalinfo_bin.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalinfo_bin.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalinfo_bin.cpp $(XTRAOBJ) $(LIBS) \
 		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdalserver.exe:	gdalserver.c $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalserver.c ws2_32.lib $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalserver.c ws2_32.lib $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdal_translate.exe:	gdal_translate_bin.cpp $(GDALLIB) $(XTRAOBJ)
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_translate_bin.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdal_translate_bin.cpp $(XTRAOBJ) $(LIBS) \
 		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdaladdo.exe:	gdaladdo.cpp $(GDALLIB) $(XTRAOBJ)
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdaladdo.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdaladdo.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdalwarpsimple.exe:	gdalwarpsimple.c $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalwarpsimple.c $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalwarpsimple.c $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdaltransform.exe:	gdaltransform.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdaltransform.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdaltransform.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdallocationinfo.exe:	gdallocationinfo.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdallocationinfo.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdallocationinfo.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdalsrsinfo.exe:	gdalsrsinfo.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalsrsinfo.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalsrsinfo.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdalwarp.exe:	gdalwarp_bin.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalwarp_bin.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalwarp_bin.cpp $(XTRAOBJ) $(LIBS) \
 		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdal_contour.exe:	gdal_contour.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_contour.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdal_contour.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 nearblack.exe:	nearblack_bin.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) nearblack_bin.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) nearblack_bin.cpp $(XTRAOBJ) $(LIBS) \
 		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdalenhance.exe:	gdalenhance.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalenhance.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalenhance.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdaldem.exe:	gdaldem_bin.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdaldem_bin.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdaldem_bin.cpp $(XTRAOBJ) $(LIBS) \
 		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdal_grid.exe:	gdal_grid_bin.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_grid_bin.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdal_grid_bin.cpp $(XTRAOBJ) $(LIBS) \
 		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
 gdalmanage.exe:	gdalmanage.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalmanage.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalmanage.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
-gdaltindex.exe:	gdaltindex.c $(GDALLIB) $(XTRAOBJ)
-	$(CC) /I$(GDAL_ROOT) $(XTRAFLAGS) $(CFLAGS) gdaltindex.c \
+gdaltindex.exe:	gdaltindex.cpp $(GDALLIB) $(XTRAOBJ)
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdaltindex.cpp \
 		$(XTRAOBJ) $(LIBS) /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdal_rasterize.exe:	gdal_rasterize_bin.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal_rasterize_bin.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdal_rasterize_bin.cpp $(XTRAOBJ) $(LIBS) \
 		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
 multireadtest.exe:	multireadtest.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) multireadtest.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) multireadtest.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdalasyncread.exe:	gdalasyncread.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalasyncread.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalasyncread.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 testreprojmulti.exe:	testreprojmulti.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) testreprojmulti.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) testreprojmulti.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 ogr2ogr.exe:	ogr2ogr_bin.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) ogr2ogr_bin.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) ogr2ogr_bin.cpp $(XTRAOBJ) $(LIBS) \
 		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 ogrinfo.exe:	ogrinfo.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) ogrinfo.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) ogrinfo.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 ogrtindex.exe:	ogrtindex.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) ogrtindex.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) ogrtindex.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
 ogrlineref.exe:	ogrlineref.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) ogrlineref.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) ogrlineref.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 testepsg.exe:	testepsg.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) testepsg.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) testepsg.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 test_ogrsf.exe:	test_ogrsf.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) test_ogrsf.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) test_ogrsf.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdalbuildvrt.exe:	gdalbuildvrt_bin.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalbuildvrt_bin.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalbuildvrt_bin.cpp $(XTRAOBJ) $(LIBS) \
 		/Fe$@ /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 dumpoverviews.exe:	dumpoverviews.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) dumpoverviews.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) dumpoverviews.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdalflattenmask.exe:	gdalflattenmask.c $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdalflattenmask.c $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdalflattenmask.c $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdaltorture.exe:	gdaltorture.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdaltorture.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdaltorture.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 gdal2ogr.exe:	gdal2ogr.c $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gdal2ogr.c $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gdal2ogr.c $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-    
+
 gnmmanage.exe:	gnmmanage.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gnmmanage.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gnmmanage.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
-	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1	
+	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
 
 gnmanalyse.exe:	gnmanalyse.cpp $(GDALLIB) $(XTRAOBJ) 
-	$(CC) $(XTRAFLAGS) $(CFLAGS) gnmanalyse.cpp $(XTRAOBJ) $(LIBS) \
+	$(CC) $(EXTRAFLAGS) $(CFLAGS) gnmanalyse.cpp $(XTRAOBJ) $(LIBS) \
 		/link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1
-	
+
 clean:
 	-del *.obj
 	-del *.exe
diff --git a/apps/multireadtest.cpp b/apps/multireadtest.cpp
index 74c1f2b..4121e88 100644
--- a/apps/multireadtest.cpp
+++ b/apps/multireadtest.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: multireadtest.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Multi-threading test application.
@@ -32,7 +31,7 @@
 #include "cpl_multiproc.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: multireadtest.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: multireadtest.cpp 35884 2016-10-24 05:56:50Z goatbar $");
 
 static int nThreadCount = 4, nIterations = 1, bLockOnOpen = TRUE;
 static int nOpenIterations = 1;
@@ -56,7 +55,6 @@ static void Usage()
     exit( 1 );
 }
 
-
 /************************************************************************/
 /*                                main()                                */
 /************************************************************************/
@@ -108,6 +106,8 @@ int main( int argc, char ** argv )
     GDALDatasetH hDS;
 
     GDALAllRegister();
+    for( int i = 0; i < 2; i++ )
+    {
     hDS = GDALOpen( pszFilename, GA_ReadOnly );
     if( hDS == NULL )
         exit( 1 );
@@ -118,6 +118,7 @@ int main( int argc, char ** argv )
                                    GDALGetRasterYSize( hDS ) );
 
     GDALClose( hDS );
+    }
 
     printf( "Got checksum %d, launching %d worker threads on %s, %d iterations.\n",
             nChecksum, nThreadCount, pszFilename, nIterations );
@@ -155,7 +156,6 @@ int main( int argc, char ** argv )
     return 0;
 }
 
-
 /************************************************************************/
 /*                             WorkerFunc()                             */
 /************************************************************************/
diff --git a/apps/nearblack_bin.cpp b/apps/nearblack_bin.cpp
index e834200..b595894 100644
--- a/apps/nearblack_bin.cpp
+++ b/apps/nearblack_bin.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: nearblack_bin.cpp 33011 2016-01-15 22:20:29Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Convert nearly black or nearly white border to exact black/white.
@@ -31,7 +30,7 @@
 #include "commonutils.h"
 #include "gdal_utils_priv.h"
 
-CPL_CVSID("$Id: nearblack_bin.cpp 33011 2016-01-15 22:20:29Z goatbar $");
+CPL_CVSID("$Id: nearblack_bin.cpp 35226 2016-08-28 13:49:13Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -88,7 +87,7 @@ int main(int argc, char** argv)
 /* -------------------------------------------------------------------- */
     GDALAllRegister();
     if( CPLGetConfigOption("GDAL_CACHEMAX", NULL) == NULL )
-	GDALSetCacheMax( 100000000 );
+        GDALSetCacheMax( 100000000 );
     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
     if( argc < 1 )
         exit( -argc );
diff --git a/apps/nearblack_lib.cpp b/apps/nearblack_lib.cpp
index 4db0fb2..1121ecc 100644
--- a/apps/nearblack_lib.cpp
+++ b/apps/nearblack_lib.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: nearblack_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  GDAL Utilities
  * Purpose:  Convert nearly black or nearly white border to exact black/white.
@@ -28,13 +27,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal.h"
+#include "cpl_port.h"
+#include "gdal_utils.h"
+#include "gdal_utils_priv.h"
+
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+#include <memory>
+#include <vector>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
-#include <vector>
-#include "gdal_utils_priv.h"
+#include "gdal.h"
 
-CPL_CVSID("$Id: nearblack_lib.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: nearblack_lib.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 typedef std::vector<int> Color;
 typedef std::vector< Color > Colors;
@@ -228,7 +238,7 @@ GDALDatasetH CPL_DLL GDALNearblack( const char *pszDest, GDALDatasetH hDstDS,
 
     /***** set a color if there are no colors set? *****/
 
-    if ( oColors.size() == 0) {
+    if ( oColors.empty()) {
         Color oColor;
 
         /***** loop over the bands to get the right number of values *****/
@@ -483,7 +493,6 @@ GDALDatasetH CPL_DLL GDALNearblack( const char *pszDest, GDALDatasetH hDstDS,
             }
         }
 
-
         if( !(psOptions->pfnProgress( 0.5 + 0.5 * (nYSize-iLine) / (double) nYSize, NULL, psOptions->pProgressData )) )
         {
             if( bCloseOutDSOnError )
@@ -525,7 +534,7 @@ static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
 
     if( bDoVerticalCheck )
     {
-        int nXSize = MAX(iStart+1,iEnd+1);
+        const int nXSize = std::max(iStart + 1, iEnd + 1);
 
         for( i = 0; i < nXSize; i++ )
         {
@@ -694,10 +703,8 @@ static void ProcessLine( GByte *pabyLine, GByte *pabyMask, int iStart,
             }
         }
     }
-
 }
 
-
 /************************************************************************/
 /*                            IsInt()                                   */
 /************************************************************************/
@@ -757,7 +764,7 @@ GDALNearblackOptions *GDALNearblackOptionsNew(char** papszArgv,
 /*      Handle command line arguments.                                  */
 /* -------------------------------------------------------------------- */
     int argc = CSLCount(papszArgv);
-    for( int i = 0; i < argc; i++ )
+    for( int i = 0; papszArgv != NULL && i < argc; i++ )
     {
         if( EQUAL(papszArgv[i],"-of") && i < argc-1 )
         {
@@ -827,7 +834,7 @@ GDALNearblackOptions *GDALNearblackOptionsNew(char** papszArgv,
 
             /***** check if the number of bands is consistent *****/
 
-            if ( psOptions->oColors.size() > 0 &&
+            if ( !psOptions->oColors.empty() &&
                  psOptions->oColors.front().size() != oColor.size() )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
diff --git a/apps/ogr2ogr_bin.cpp b/apps/ogr2ogr_bin.cpp
index 054cd9a..7b96e6c 100644
--- a/apps/ogr2ogr_bin.cpp
+++ b/apps/ogr2ogr_bin.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr2ogr_bin.cpp 34578 2016-07-07 10:26:20Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for translating between formats.
@@ -32,8 +31,10 @@
 #include "ogr_p.h"
 #include "gdal_utils_priv.h"
 #include "commonutils.h"
+#include <vector>
+#include <algorithm>
 
-CPL_CVSID("$Id: ogr2ogr_bin.cpp 34578 2016-07-07 10:26:20Z rouault $");
+CPL_CVSID("$Id: ogr2ogr_bin.cpp 37362 2017-02-12 21:04:36Z rouault $");
 
 static void Usage(int bShort = TRUE);
 static void Usage(const char* pszAdditionalMsg, int bShort = TRUE);
@@ -196,7 +197,6 @@ int main( int nArgc, char ** papszArgv )
     {
         CheckDestDataSourceNameConsistency(psOptionsForBinary->pszDestDataSource,
                                            psOptionsForBinary->pszFormat);
-
     }
 /* -------------------------------------------------------------------- */
 /*      Open data source.                                               */
@@ -239,15 +239,20 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
     if( hDS == NULL )
     {
-        OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+        GDALDriverManager *poDM = GetGDALDriverManager();
 
         fprintf( stderr, "FAILURE:\n"
                 "Unable to open datasource `%s' with the following drivers.\n",
                 psOptionsForBinary->pszDataSource );
 
-        for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+        for( int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++ )
         {
-            fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetDescription() );
+            GDALDriver* poIter = poDM->GetDriver(iDriver);
+            char** papszDriverMD = poIter->GetMetadata();
+            if( CPLTestBool( CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_VECTOR, "FALSE") ) )
+            {
+                fprintf( stderr,  "  -> `%s'\n", poIter->GetDescription() );
+            }
         }
 
         GDALVectorTranslateOptionsFree(psOptions);
@@ -255,6 +260,33 @@ int main( int nArgc, char ** papszArgv )
         goto exit;
     }
 
+    if( hODS != NULL )
+    {
+        GDALDriverManager *poDM = GetGDALDriverManager();
+
+        GDALDriver* poDriver = poDM->GetDriverByName(psOptionsForBinary->pszFormat);
+        if( poDriver == NULL )
+        {
+            fprintf( stderr,  "Unable to find driver `%s'.\n", psOptionsForBinary->pszFormat );
+            fprintf( stderr,  "The following drivers are available:\n" );
+
+            for( int iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++ )
+            {
+                GDALDriver* poIter = poDM->GetDriver(iDriver);
+                char** papszDriverMD = poIter->GetMetadata();
+                if( CPLTestBool( CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_VECTOR, "FALSE") ) &&
+                    (CPLTestBool( CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_CREATE, "FALSE") ) ||
+                     CPLTestBool( CSLFetchNameValueDef(papszDriverMD, GDAL_DCAP_CREATECOPY, "FALSE") )) )
+                {
+                    fprintf( stderr,  "  -> `%s'\n", poIter->GetDescription() );
+                }
+            }
+            GDALVectorTranslateOptionsFree(psOptions);
+            GDALVectorTranslateOptionsForBinaryFree(psOptionsForBinary);
+            goto exit;
+        }
+    }
+
     if( !(psOptionsForBinary->bQuiet) )
     {
         GDALVectorTranslateOptionsSetProgress(psOptions, GDALTermProgress, NULL);
@@ -291,23 +323,27 @@ static void Usage(int bShort)
     Usage(NULL, bShort);
 }
 
+static bool StringCISortFunction(const CPLString& a, const CPLString& b)
+{
+    return STRCASECMP(a.c_str(), b.c_str()) < 0;
+}
+
 static void Usage(const char* pszAdditionalMsg, int bShort)
 
 {
     OGRSFDriverRegistrar        *poR = OGRSFDriverRegistrar::GetRegistrar();
 
-
     printf( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]\n"
             "               [-select field_list] [-where restricted_where|@filename]\n"
             "               [-progress] [-sql <sql statement>|@filename] [-dialect dialect]\n"
-            "               [-preserve_fid] [-fid FID]\n"
+            "               [-preserve_fid] [-fid FID] [-limit nb_features]\n"
             "               [-spat xmin ymin xmax ymax] [-spat_srs srs_def] [-geomfield field]\n"
             "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
             "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
             "               dst_datasource_name src_datasource_name\n"
             "               [-lco NAME=VALUE] [-nln name] \n"
-            "               [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR]\n"
-            "               [-dim 2|3|layer_dim] [layer [layer ...]]\n"
+            "               [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR|CONVERT_TO_CURVE]\n"
+            "               [-dim XY|XYZ|XYM|XYZM|layer_dim] [layer [layer ...]]\n"
             "\n"
             "Advanced options :\n"
             "               [-gt n] [-ds_transaction]\n"
@@ -340,12 +376,18 @@ static void Usage(const char* pszAdditionalMsg, int bShort)
 
     printf("\n -f format_name: output file format name, possible values are:\n");
 
+    std::vector<CPLString> aoSetDrivers;
     for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
     {
         GDALDriver *poDriver = poR->GetDriver(iDriver);
 
         if( CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
-            printf( "     -f \"%s\"\n", poDriver->GetDescription() );
+            aoSetDrivers.push_back( poDriver->GetDescription() );
+    }
+    std::sort (aoSetDrivers.begin(), aoSetDrivers.end(), StringCISortFunction);
+    for( size_t i = 0; i < aoSetDrivers.size(); i++ )
+    {
+        printf( "     -f \"%s\"\n", aoSetDrivers[i].c_str() );
     }
 
     printf( " -append: Append to existing layer instead of creating new if it exists\n"
diff --git a/apps/ogr2ogr_lib.cpp b/apps/ogr2ogr_lib.cpp
index efeb7e0..df845ad 100644
--- a/apps/ogr2ogr_lib.cpp
+++ b/apps/ogr2ogr_lib.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr2ogr_lib.cpp 34858 2016-08-02 12:42:28Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for translating between formats.
@@ -29,20 +28,40 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogrsf_frmts.h"
-#include "ogr_p.h"
+#include "cpl_port.h"
+#include "gdal_utils.h"
+#include "gdal_utils_priv.h"
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "commonutils.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
 #include "cpl_error.h"
-#include "ogr_api.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "gdal.h"
-#include "gdal_utils_priv.h"
 #include "gdal_alg.h"
-#include "commonutils.h"
-#include <map>
-#include <vector>
+#include "gdal_priv.h"
+#include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_featurestyle.h"
+#include "ogr_geometry.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
+#include "ogrlayerdecorator.h"
+#include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogr2ogr_lib.cpp 34858 2016-08-02 12:42:28Z rouault $");
+CPL_CVSID("$Id: ogr2ogr_lib.cpp 37467 2017-02-26 02:21:33Z goatbar $");
 
 typedef enum
 {
@@ -317,6 +336,9 @@ struct GDALVectorTranslateOptions
 
     /*! Whether layer and feature native data must be transferred. */
     bool bNativeData;
+
+    /*! Maximum number of features, or -1 if no limit. */
+    GIntBig nLimit;
 };
 
 typedef struct
@@ -343,6 +365,7 @@ typedef struct
 class SetupTargetLayer
 {
 public:
+    GDALDataset          *m_poSrcDS;
     GDALDataset          *m_poDstDS;
     char                **m_papszLCO;
     OGRSpatialReference  *m_poOutputSRS;
@@ -373,7 +396,8 @@ public:
 
     TargetLayerInfo*            Setup(OGRLayer * poSrcLayer,
                                       const char *pszNewLayerName,
-                                      GDALVectorTranslateOptions *psOptions);
+                                      GDALVectorTranslateOptions *psOptions,
+                                      GIntBig& nTotalEventsDone);
 };
 
 class LayerTranslator
@@ -396,12 +420,14 @@ public:
     OGRGeometry                  *m_poClipSrc;
     OGRGeometry                  *m_poClipDst;
     bool                          m_bExplodeCollections;
-    vsi_l_offset                  m_nSrcFileSize;
     bool                          m_bNativeData;
+    GIntBig                       m_nLimit;
 
-    int                 Translate(TargetLayerInfo* psInfo,
+    int                 Translate(OGRFeature* poFeatureIn,
+                                  TargetLayerInfo* psInfo,
                                   GIntBig nCountLayerFeatures,
                                   GIntBig* pnReadFeatureCount,
+                                  GIntBig& nTotalEventsDone,
                                   GDALProgressFunc pfnProgress,
                                   void *pProgressArg,
                                   GDALVectorTranslateOptions *psOptions);
@@ -410,7 +436,8 @@ public:
 static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
                                                  const char* pszNewLayerName,
                                                  bool bOverwrite,
-                                                 bool* pbErrorOccurred);
+                                                 bool* pbErrorOccurred,
+                                                 bool* pbOverwriteActuallyDone);
 
 static void FreeTargetLayerInfo(TargetLayerInfo* psInfo);
 
@@ -492,7 +519,6 @@ static OGRGeometry* LoadGeometry( const char* pszDS,
     return poGeom;
 }
 
-
 /************************************************************************/
 /*                     OGRSplitListFieldLayer                           */
 /************************************************************************/
@@ -518,62 +544,62 @@ class OGRSplitListFieldLayer : public OGRLayer
   public:
                                  OGRSplitListFieldLayer(OGRLayer* poSrcLayer,
                                                         int nMaxSplitListSubFields);
-                                ~OGRSplitListFieldLayer();
+                        virtual ~OGRSplitListFieldLayer();
 
     bool                        BuildLayerDefn(GDALProgressFunc pfnProgress,
                                                 void *pProgressArg);
 
-    virtual OGRFeature          *GetNextFeature();
-    virtual OGRFeature          *GetFeature(GIntBig nFID);
-    virtual OGRFeatureDefn      *GetLayerDefn();
+    virtual OGRFeature          *GetNextFeature() override;
+    virtual OGRFeature          *GetFeature(GIntBig nFID) override;
+    virtual OGRFeatureDefn      *GetLayerDefn() override;
 
-    virtual void                 ResetReading() { poSrcLayer->ResetReading(); }
-    virtual int                  TestCapability(const char*) { return FALSE; }
+    virtual void                 ResetReading() override { poSrcLayer->ResetReading(); }
+    virtual int                  TestCapability(const char*) override { return FALSE; }
 
-    virtual GIntBig              GetFeatureCount( int bForce = TRUE )
+    virtual GIntBig              GetFeatureCount( int bForce = TRUE ) override
     {
         return poSrcLayer->GetFeatureCount(bForce);
     }
 
-    virtual OGRSpatialReference *GetSpatialRef()
+    virtual OGRSpatialReference *GetSpatialRef() override
     {
         return poSrcLayer->GetSpatialRef();
     }
 
-    virtual OGRGeometry         *GetSpatialFilter()
+    virtual OGRGeometry         *GetSpatialFilter() override
     {
         return poSrcLayer->GetSpatialFilter();
     }
 
-    virtual OGRStyleTable       *GetStyleTable()
+    virtual OGRStyleTable       *GetStyleTable() override
     {
         return poSrcLayer->GetStyleTable();
     }
 
-    virtual void                 SetSpatialFilter( OGRGeometry *poGeom )
+    virtual void                 SetSpatialFilter( OGRGeometry *poGeom ) override
     {
         poSrcLayer->SetSpatialFilter(poGeom);
     }
 
-    virtual void                 SetSpatialFilter( int iGeom, OGRGeometry *poGeom )
+    virtual void                 SetSpatialFilter( int iGeom, OGRGeometry *poGeom ) override
     {
         poSrcLayer->SetSpatialFilter(iGeom, poGeom);
     }
 
     virtual void                 SetSpatialFilterRect( double dfMinX, double dfMinY,
-                                                       double dfMaxX, double dfMaxY )
+                                                       double dfMaxX, double dfMaxY ) override
     {
         poSrcLayer->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
     }
 
     virtual void                 SetSpatialFilterRect( int iGeom,
                                                        double dfMinX, double dfMinY,
-                                                       double dfMaxX, double dfMaxY )
+                                                       double dfMaxX, double dfMaxY ) override
     {
         poSrcLayer->SetSpatialFilterRect(iGeom, dfMinX, dfMinY, dfMaxX, dfMaxY);
     }
 
-    virtual OGRErr               SetAttributeFilter( const char *pszFilter )
+    virtual OGRErr               SetAttributeFilter( const char *pszFilter ) override
     {
         return poSrcLayer->SetAttributeFilter(pszFilter);
     }
@@ -686,7 +712,8 @@ bool OGRSplitListFieldLayer::BuildLayerDefn(GDALProgressFunc pfnProgress,
                         break;
                     }
                     default:
-                        CPLAssert(0);
+                        // cppcheck-suppress knownConditionTrueFalse
+                        CPLAssert(false);
                         break;
                 }
                 if (nCount > pasListFields[i].nMaxOccurrences)
@@ -764,7 +791,6 @@ bool OGRSplitListFieldLayer::BuildLayerDefn(GDALProgressFunc pfnProgress,
     return true;
 }
 
-
 /************************************************************************/
 /*                       TranslateFeature()                             */
 /************************************************************************/
@@ -935,11 +961,11 @@ public:
             poSRS->Dereference();
     }
 
-    virtual OGRSpatialReference *GetSourceCS() { return poSRS; }
-    virtual OGRSpatialReference *GetTargetCS() { return poSRS; }
+    virtual OGRSpatialReference *GetSourceCS() override { return poSRS; }
+    virtual OGRSpatialReference *GetTargetCS() override { return poSRS; }
 
     virtual int Transform( int nCount,
-                           double *x, double *y, double *z = NULL )
+                           double *x, double *y, double *z = NULL ) override
     {
         int *pabSuccess = (int *) CPLMalloc(sizeof(int) * nCount );
 
@@ -961,7 +987,7 @@ public:
 
     virtual int TransformEx( int nCount,
                              double *x, double *y, double *z = NULL,
-                             int *pabSuccess = NULL )
+                             int *pabSuccess = NULL ) override
     {
         if( bUseTPS )
             return GDALTPSTransform( hTransformArg, FALSE,
@@ -995,20 +1021,20 @@ public:
         OGRCoordinateTransformation::DestroyCT(poCT2);
     }
 
-    virtual OGRSpatialReference *GetSourceCS()
+    virtual OGRSpatialReference *GetSourceCS() override
     {
         return poCT1 ? poCT1->GetSourceCS() :
                poCT2 ? poCT2->GetSourceCS() : NULL;
     }
 
-    virtual OGRSpatialReference *GetTargetCS()
+    virtual OGRSpatialReference *GetTargetCS() override
     {
         return poCT2 ? poCT2->GetTargetCS() :
                poCT1 ? poCT1->GetTargetCS() : NULL;
     }
 
     virtual int Transform( int nCount,
-                           double *x, double *y, double *z = NULL )
+                           double *x, double *y, double *z = NULL ) override
     {
         int nResult = TRUE;
         if( poCT1 )
@@ -1020,7 +1046,7 @@ public:
 
     virtual int TransformEx( int nCount,
                              double *x, double *y, double *z = NULL,
-                             int *pabSuccess = NULL )
+                             int *pabSuccess = NULL ) override
     {
         int nResult = TRUE;
         if( poCT1 )
@@ -1094,7 +1120,7 @@ static int GetFieldType(const char* pszArg, int* pnSubFieldType)
              {
                  *pnSubFieldType = -1;
                  CPLString osArgSubType = pszOpenParenthesis + 1;
-                 if( osArgSubType.size() && osArgSubType[osArgSubType.size()-1] == ')' )
+                 if( !osArgSubType.empty() && osArgSubType.back() == ')' )
                      osArgSubType.resize(osArgSubType.size()-1);
                  for( int iSubType = 0; iSubType <= (int) OFSTMaxSubType; iSubType++ )
                  {
@@ -1182,6 +1208,648 @@ GDALVectorTranslateOptions* GDALVectorTranslateOptionsClone(const GDALVectorTran
     return psOptions;
 }
 
+class GDALVectorTranslateWrappedDataset: public GDALDataset
+{
+                GDALDataset* m_poBase;
+                OGRSpatialReference* m_poOutputSRS;
+                bool m_bTransform;
+
+                std::vector<OGRLayer*> m_apoLayers;
+                std::vector<OGRLayer*> m_apoHiddenLayers;
+
+                GDALVectorTranslateWrappedDataset(
+                                    GDALDataset* poBase,
+                                    OGRSpatialReference* poOutputSRS,
+                                    bool bTransform);
+public:
+
+       virtual ~GDALVectorTranslateWrappedDataset();
+
+       virtual int GetLayerCount() override
+                        { return static_cast<int>(m_apoLayers.size()); }
+       virtual OGRLayer* GetLayer(int nIdx) override;
+       virtual OGRLayer* GetLayerByName(const char* pszName) override;
+
+       virtual OGRLayer *  ExecuteSQL( const char *pszStatement,
+                                        OGRGeometry *poSpatialFilter,
+                                        const char *pszDialect ) override;
+       virtual void        ReleaseResultSet( OGRLayer * poResultsSet ) override;
+
+       static GDALVectorTranslateWrappedDataset* New(
+                                          GDALDataset* poBase,
+                                          OGRSpatialReference* poOutputSRS,
+                                          bool bTransform );
+};
+
+class GDALVectorTranslateWrappedLayer: public OGRLayerDecorator
+{
+    std::vector<OGRCoordinateTransformation*> m_apoCT;
+    OGRFeatureDefn* m_poFDefn;
+
+            GDALVectorTranslateWrappedLayer(OGRLayer* poBaseLayer,
+                                            bool bOwnBaseLayer);
+            OGRFeature* TranslateFeature(OGRFeature* poSrcFeat);
+public:
+
+        virtual ~GDALVectorTranslateWrappedLayer();
+        virtual OGRFeatureDefn* GetLayerDefn() override { return m_poFDefn; }
+        virtual OGRFeature* GetNextFeature() override;
+        virtual OGRFeature* GetFeature(GIntBig nFID) override;
+
+        static GDALVectorTranslateWrappedLayer* New(
+                                        OGRLayer* poBaseLayer,
+                                        bool bOwnBaseLayer,
+                                        OGRSpatialReference* poOutputSRS,
+                                        bool bTransform);
+};
+
+GDALVectorTranslateWrappedLayer::GDALVectorTranslateWrappedLayer(
+                    OGRLayer* poBaseLayer, bool bOwnBaseLayer) :
+        OGRLayerDecorator(poBaseLayer, bOwnBaseLayer),
+        m_apoCT( poBaseLayer->GetLayerDefn()->GetGeomFieldCount(),
+                 static_cast<OGRCoordinateTransformation*>(NULL) ),
+        m_poFDefn( NULL )
+{
+}
+
+GDALVectorTranslateWrappedLayer* GDALVectorTranslateWrappedLayer::New(
+                    OGRLayer* poBaseLayer,
+                    bool bOwnBaseLayer,
+                    OGRSpatialReference* poOutputSRS,
+                    bool bTransform )
+{
+    GDALVectorTranslateWrappedLayer* poNew =
+                new GDALVectorTranslateWrappedLayer(poBaseLayer, bOwnBaseLayer);
+    poNew->m_poFDefn = poBaseLayer->GetLayerDefn()->Clone();
+    poNew->m_poFDefn->Reference();
+    if( poOutputSRS )
+    {
+        for( int i=0; i < poNew->m_poFDefn->GetGeomFieldCount(); i++ )
+        {
+            if( bTransform )
+            {
+                OGRSpatialReference* poSourceSRS =
+                    poBaseLayer->GetLayerDefn()->
+                                        GetGeomFieldDefn(i)->GetSpatialRef();
+                if( poSourceSRS == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Layer %s has no source SRS for geometry field %s",
+                             poBaseLayer->GetName(),
+                             poBaseLayer->GetLayerDefn()->
+                                        GetGeomFieldDefn(i)->GetNameRef());
+                    delete poNew;
+                    return NULL;
+                }
+                else
+                {
+                    poNew->m_apoCT[i] = OGRCreateCoordinateTransformation(
+                                                                   poSourceSRS,
+                                                                   poOutputSRS);
+                    if( poNew->m_apoCT[i] == NULL )
+                    {
+                        char        *pszWKT = NULL;
+
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                            "Failed to create coordinate transformation between the\n"
+                            "following coordinate systems.  This may be because they\n"
+                            "are not transformable, or because projection services\n"
+                            "(PROJ.4 DLL/.so) could not be loaded." );
+
+                        poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Source:\n%s", pszWKT );
+                        CPLFree(pszWKT);
+
+                        poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Target:\n%s", pszWKT );
+                        CPLFree(pszWKT);
+
+                        delete poNew;
+                        return NULL;
+                    }
+                }
+            }
+            poNew->m_poFDefn->GetGeomFieldDefn(i)->SetSpatialRef( poOutputSRS );
+        }
+    }
+    return poNew;
+}
+
+GDALVectorTranslateWrappedLayer::~GDALVectorTranslateWrappedLayer()
+{
+    if( m_poFDefn )
+        m_poFDefn->Release();
+    for( size_t i = 0; i < m_apoCT.size(); ++i )
+        delete m_apoCT[i];
+}
+
+OGRFeature* GDALVectorTranslateWrappedLayer::GetNextFeature()
+{
+    return TranslateFeature(OGRLayerDecorator::GetNextFeature());
+}
+
+OGRFeature* GDALVectorTranslateWrappedLayer::GetFeature(GIntBig nFID)
+{
+    return TranslateFeature(OGRLayerDecorator::GetFeature(nFID));
+}
+
+OGRFeature* GDALVectorTranslateWrappedLayer::TranslateFeature(
+                                                    OGRFeature* poSrcFeat )
+{
+    if( poSrcFeat == NULL )
+        return NULL;
+    OGRFeature* poNewFeat = new OGRFeature(m_poFDefn);
+    poNewFeat->SetFrom(poSrcFeat);
+    poNewFeat->SetFID(poSrcFeat->GetFID());
+    for( int i=0; i < poNewFeat->GetGeomFieldCount(); i++ )
+    {
+        OGRGeometry* poGeom = poNewFeat->GetGeomFieldRef(i);
+        if( poGeom )
+        {
+            if( m_apoCT[i] )
+                poGeom->transform( m_apoCT[i] );
+            poGeom->assignSpatialReference(
+                    m_poFDefn->GetGeomFieldDefn(i)->GetSpatialRef() );
+        }
+    }
+    delete poSrcFeat;
+    return poNewFeat;
+}
+
+
+GDALVectorTranslateWrappedDataset::GDALVectorTranslateWrappedDataset(
+                                    GDALDataset* poBase,
+                                    OGRSpatialReference* poOutputSRS,
+                                    bool bTransform):
+                                                m_poBase(poBase),
+                                                m_poOutputSRS(poOutputSRS),
+                                                m_bTransform(bTransform)
+{
+    SetDescription( poBase->GetDescription() );
+    if( poBase->GetDriver() )
+    {
+        poDriver = new GDALDriver();
+        poDriver->SetDescription( poBase->GetDriver()->GetDescription() );
+    }
+}
+
+GDALVectorTranslateWrappedDataset* GDALVectorTranslateWrappedDataset::New(
+                        GDALDataset* poBase,
+                        OGRSpatialReference* poOutputSRS,
+                        bool bTransform )
+{
+    GDALVectorTranslateWrappedDataset* poNew =
+                                new GDALVectorTranslateWrappedDataset(
+                                                                poBase,
+                                                                poOutputSRS,
+                                                                bTransform);
+    for(int i = 0; i < poBase->GetLayerCount(); i++ )
+    {
+        OGRLayer* poLayer = GDALVectorTranslateWrappedLayer::New(
+                            poBase->GetLayer(i), false, poOutputSRS, bTransform);
+        if(poLayer == NULL )
+        {
+            delete poNew;
+            return NULL;
+        }
+        poNew->m_apoLayers.push_back(poLayer);
+    }
+    return poNew;
+}
+
+GDALVectorTranslateWrappedDataset::~GDALVectorTranslateWrappedDataset()
+{
+    delete poDriver;
+    for(size_t i = 0; i < m_apoLayers.size(); i++ )
+    {
+        delete m_apoLayers[i];
+    }
+    for(size_t i = 0; i < m_apoHiddenLayers.size(); i++ )
+    {
+        delete m_apoHiddenLayers[i];
+    }
+}
+
+OGRLayer* GDALVectorTranslateWrappedDataset::GetLayer(int i)
+{
+    if( i < 0 || i >= static_cast<int>(m_apoLayers.size()) )
+        return NULL;
+    return m_apoLayers[i];
+}
+
+OGRLayer* GDALVectorTranslateWrappedDataset::GetLayerByName(const char* pszName)
+{
+    for(size_t i = 0; i < m_apoLayers.size(); i++ )
+    {
+        if( strcmp(m_apoLayers[i]->GetName(), pszName) == 0 )
+            return m_apoLayers[i];
+    }
+    for(size_t i = 0; i < m_apoHiddenLayers.size(); i++ )
+    {
+        if( strcmp(m_apoHiddenLayers[i]->GetName(), pszName) == 0 )
+            return m_apoHiddenLayers[i];
+    }
+    for(size_t i = 0; i < m_apoLayers.size(); i++ )
+    {
+        if( EQUAL(m_apoLayers[i]->GetName(), pszName) )
+            return m_apoLayers[i];
+    }
+    for(size_t i = 0; i < m_apoHiddenLayers.size(); i++ )
+    {
+        if( EQUAL(m_apoHiddenLayers[i]->GetName(), pszName) )
+            return m_apoHiddenLayers[i];
+    }
+
+    OGRLayer* poLayer = m_poBase->GetLayerByName(pszName);
+    if( poLayer == NULL )
+        return NULL;
+    poLayer = GDALVectorTranslateWrappedLayer::New(
+                                poLayer, false, m_poOutputSRS, m_bTransform);
+    if( poLayer == NULL )
+        return NULL;
+
+    // Replicate source dataset behaviour: if the fact of calling
+    // GetLayerByName() on a initially hidden layer makes it visible through
+    // GetLayerCount()/GetLayer(), do the same. Otherwise we are going to
+    // maintain it hidden as well.
+    for( int i = 0; i < m_poBase->GetLayerCount(); i++ )
+    {
+        if( m_poBase->GetLayer(i) == poLayer )
+        {
+            m_apoLayers.push_back(poLayer);
+            return poLayer;
+        }
+    }
+    m_apoHiddenLayers.push_back(poLayer);
+    return poLayer;
+}
+
+
+OGRLayer *  GDALVectorTranslateWrappedDataset::ExecuteSQL(
+                                        const char *pszStatement,
+                                        OGRGeometry *poSpatialFilter,
+                                        const char *pszDialect )
+{
+    OGRLayer* poLayer = m_poBase->ExecuteSQL(pszStatement,
+                                                poSpatialFilter, pszDialect);
+    if( poLayer == NULL )
+        return NULL;
+    return GDALVectorTranslateWrappedLayer::New(
+                                poLayer, true, m_poOutputSRS, m_bTransform);
+}
+
+void GDALVectorTranslateWrappedDataset:: ReleaseResultSet(
+                                                    OGRLayer * poResultsSet )
+{
+    delete poResultsSet;
+}
+
+
+/************************************************************************/
+/*                     GDALVectorTranslateCreateCopy()                  */
+/************************************************************************/
+
+static GDALDataset* GDALVectorTranslateCreateCopy(
+                                    GDALDriver* poDriver,
+                                    const char* pszDest,
+                                    GDALDataset* poDS,
+                                    const GDALVectorTranslateOptions* psOptions)
+{
+    const char* const szErrorMsg = "%s not supported by this output driver";
+    GDALDataset* poWrkSrcDS = poDS;
+    OGRSpatialReference oOutputSRS; // Leave it in global scope
+
+    if( psOptions->bSkipFailures )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-skipfailures");
+        return NULL;
+    }
+    if( psOptions->nLayerTransaction >= 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-lyr_transaction or -ds_transaction");
+        return NULL;
+    }
+    if( psOptions->nFIDToFetch >= 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-fid");
+        return NULL;
+    }
+    if( psOptions->papszLCO )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-lco");
+        return NULL;
+    }
+    if( psOptions->bAddMissingFields )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-addfields");
+        return NULL;
+    }
+    if( psOptions->pszSourceSRSDef )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-s_srs");
+        return NULL;
+    }
+    if( !psOptions->bExactFieldNameMatch )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-relaxedFieldNameMatch");
+        return NULL;
+    }
+    if( psOptions->pszNewLayerName )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-nln");
+        return NULL;
+    }
+    if( psOptions->papszSelFields )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-select");
+        return NULL;
+    }
+    if( psOptions->pszSQLStatement )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-sql");
+        return NULL;
+    }
+    if( psOptions->pszDialect )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-dialect");
+        return NULL;
+    }
+    if( psOptions->eGType != GEOMTYPE_UNCHANGED ||
+        psOptions->eGeomTypeConversion != GTC_DEFAULT )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-nlt");
+        return NULL;
+    }
+    if( psOptions->papszFieldTypesToString )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-fieldTypeToString");
+        return NULL;
+    }
+    if( psOptions->papszMapFieldType )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-mapFieldType");
+        return NULL;
+    }
+    if( psOptions->bUnsetFieldWidth )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-unsetFieldWidth");
+        return NULL;
+    }
+    if( psOptions->bWrapDateline )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-wrapdateline");
+        return NULL;
+    }
+    if( psOptions->bClipSrc )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipsrc");
+        return NULL;
+    }
+    if( psOptions->pszClipSrcSQL )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipsrcsql");
+        return NULL;
+    }
+    if( psOptions->pszClipSrcLayer )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipsrclayer");
+        return NULL;
+    }
+    if( psOptions->pszClipSrcWhere )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipsrcwhere");
+        return NULL;
+    }
+    if( psOptions->pszClipDstDS || psOptions->hClipDst )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipdst");
+        return NULL;
+    }
+    if( psOptions->pszClipDstSQL )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipdstsql");
+        return NULL;
+    }
+    if( psOptions->pszClipDstLayer )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipdstlayer");
+        return NULL;
+    }
+    if( psOptions->pszClipDstWhere )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-clipdstwhere");
+        return NULL;
+    }
+    if( psOptions->bSplitListFields )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-splitlistfields");
+        return NULL;
+    }
+    if( psOptions->nMaxSplitListSubFields >= 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-maxsubfields");
+        return NULL;
+    }
+    if( psOptions->bExplodeCollections )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-explodecollections");
+        return NULL;
+    }
+    if( psOptions->pszZField )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-zfield");
+        return NULL;
+    }
+    if( psOptions->nGCPCount )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-gcp");
+        return NULL;
+    }
+    if( psOptions->papszFieldMap )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-fieldmap");
+        return NULL;
+    }
+    if( psOptions->bForceNullable )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-forceNullable");
+        return NULL;
+    }
+    if( psOptions->bUnsetDefault )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-unsetDefault");
+        return NULL;
+    }
+    if( psOptions->bUnsetFid )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-unsetFid");
+        return NULL;
+    }
+    if( !psOptions->bCopyMD )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-nomd");
+        return NULL;
+    }
+    if( !psOptions->bNativeData )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-noNativeData");
+        return NULL;
+    }
+    if( psOptions->nLimit >= 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-limit");
+        return NULL;
+    }
+    if( psOptions->papszMetadataOptions )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-mo");
+        return NULL;
+    }
+
+    if( psOptions->pszOutputSRSDef )
+    {
+        if( oOutputSRS.SetFromUserInput( psOptions->pszOutputSRSDef ) !=
+                                                                OGRERR_NONE )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Failed to process SRS definition: %s",
+                      psOptions->pszOutputSRSDef );
+            return NULL;
+        }
+        poWrkSrcDS = GDALVectorTranslateWrappedDataset::New(
+            poDS, &oOutputSRS, psOptions->bTransform);
+        if( poWrkSrcDS == NULL )
+            return NULL;
+    }
+
+    if( psOptions->pszWHERE )
+    {
+        // Hack for GMLAS driver
+        if( EQUAL(poDriver->GetDescription(), "GMLAS") )
+        {
+            if( psOptions->papszLayers == NULL )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "-where not supported by this output driver "
+                         "without explicit layer name(s)");
+                if( poWrkSrcDS != poDS )
+                    delete poWrkSrcDS;
+                return NULL;
+            }
+            else
+            {
+                char** papszIter = psOptions->papszLayers;
+                for( ; *papszIter != NULL; ++papszIter )
+                {
+                    OGRLayer* poSrcLayer = poDS->GetLayerByName(*papszIter);
+                    if( poSrcLayer != NULL )
+                    {
+                        poSrcLayer->SetAttributeFilter( psOptions->pszWHERE );
+                    }
+                }
+            }
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg, "-where");
+            if( poWrkSrcDS != poDS )
+                delete poWrkSrcDS;
+            return NULL;
+        }
+    }
+
+    if( psOptions->hSpatialFilter )
+    {
+        for( int i=0; i<poWrkSrcDS->GetLayerCount();++i)
+        {
+            OGRLayer* poSrcLayer = poWrkSrcDS->GetLayer(i);
+            if( poSrcLayer &&
+                poSrcLayer->GetLayerDefn()->GetGeomFieldCount() > 0 &&
+                (psOptions->papszLayers == NULL ||
+                 CSLFindString(psOptions->papszLayers,
+                               poSrcLayer->GetName())>=0) )
+            {
+                if( psOptions->pszGeomField != NULL )
+                {
+                    const int iGeomField = poSrcLayer->GetLayerDefn()->
+                            GetGeomFieldIndex(psOptions->pszGeomField);
+                    if( iGeomField >= 0 )
+                        poSrcLayer->SetSpatialFilter( iGeomField,
+                            reinterpret_cast<OGRGeometry*>(
+                                                psOptions->hSpatialFilter) );
+                    else
+                        CPLError( CE_Warning, CPLE_AppDefined,
+                                  "Cannot find geometry field %s in layer %s. "
+                                  "Applying to first geometry field",
+                                  psOptions->pszGeomField,
+                                  poSrcLayer->GetName() );
+                }
+                else
+                {
+                    poSrcLayer->SetSpatialFilter(
+                        reinterpret_cast<OGRGeometry*>(
+                                            psOptions->hSpatialFilter) );
+                }
+            }
+        }
+    }
+
+    char** papszDSCO = CSLDuplicate(psOptions->papszDSCO);
+    if( psOptions->papszLayers )
+    {
+        // Hack for GMLAS driver
+        if( EQUAL(poDriver->GetDescription(), "GMLAS") )
+        {
+            CPLString osLayers;
+            char** papszIter = psOptions->papszLayers;
+            for( ; *papszIter != NULL; ++papszIter )
+            {
+                if( !osLayers.empty() )
+                    osLayers += ",";
+                osLayers += *papszIter;
+            }
+            papszDSCO = CSLSetNameValue(papszDSCO, "LAYERS", osLayers);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, szErrorMsg,
+                     "Specifying layers");
+            CSLDestroy(papszDSCO);
+            if( poWrkSrcDS != poDS )
+                delete poWrkSrcDS;
+            return NULL;
+        }
+    }
+
+    // Hack for GMLAS driver (this speed up deletion by avoiding the GML
+    // driver to try parsing a pre-existing file). Could be potentially
+    // removed if the GML driver implemented fast dataset opening (ie
+    // without parsing) and GetFileList()
+    if( EQUAL(poDriver->GetDescription(), "GMLAS") )
+    {
+        GDALDriverH hIdentifyingDriver = GDALIdentifyDriver(pszDest, NULL);
+        if( hIdentifyingDriver != NULL &&
+            EQUAL( GDALGetDescription(hIdentifyingDriver), "GML" ) )
+        {
+            VSIUnlink( pszDest );
+            VSIUnlink( CPLResetExtension(pszDest, "gfs") );
+        }
+    }
+
+    GDALDataset* poOut = poDriver->CreateCopy(pszDest, poWrkSrcDS, FALSE,
+                                              papszDSCO,
+                                              psOptions->pfnProgress,
+                                              psOptions->pProgressData);
+    CSLDestroy(papszDSCO);
+
+    if( poWrkSrcDS != poDS )
+        delete poWrkSrcDS;
+
+    return poOut;
+}
+
 /************************************************************************/
 /*                           GDALVectorTranslate()                      */
 /************************************************************************/
@@ -1390,6 +2058,15 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
             return NULL;
         }
     }
+    else if( !bUpdate && strcmp(osDestFilename, poDS->GetDescription()) == 0 &&
+             !EQUAL(psOptions->pszFormat, "Memory") )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Source and destination datasets must be different "
+                  "in non-update mode." );
+        GDALVectorTranslateOptionsFree(psOptions);
+        return NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Try opening the output datasource as an existing, writable      */
@@ -1445,25 +2122,42 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
     bool bNewDataSource = false;
     if( !bUpdate )
     {
-        OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+        GDALDriverManager *poDM = GetGDALDriverManager();
 
-        poDriver = poR->GetDriverByName(psOptions->pszFormat);
+        poDriver = poDM->GetDriverByName(psOptions->pszFormat);
         if( poDriver == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "Unable to find driver `%s'.", psOptions->pszFormat );
-            fprintf( stderr,  "The following drivers are available:\n" );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to find driver `%s'.", psOptions->pszFormat );
+            GDALVectorTranslateOptionsFree(psOptions);
+            return NULL;
+        }
 
-            for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
-            {
-                fprintf( stderr,  "  -> `%s'\n", poR->GetDriver(iDriver)->GetDescription() );
-            }
+        char** papszDriverMD = poDriver->GetMetadata();
+        if( !CPLTestBool( CSLFetchNameValueDef(papszDriverMD,
+                                               GDAL_DCAP_VECTOR, "FALSE") ) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "%s driver has no vector capabilities.",
+                      psOptions->pszFormat );
             GDALVectorTranslateOptionsFree(psOptions);
             return NULL;
         }
 
-        if( !CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
+        if( !CPLTestBool( CSLFetchNameValueDef(papszDriverMD,
+                                               GDAL_DCAP_CREATE, "FALSE") ) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "%s driver does not support data source creation.",
+            if( CPLTestBool( CSLFetchNameValueDef(papszDriverMD,
+                                            GDAL_DCAP_CREATECOPY, "FALSE") ) )
+            {
+                poODS = GDALVectorTranslateCreateCopy(poDriver, pszDest,
+                                                      poDS, psOptions);
+                GDALVectorTranslateOptionsFree(psOptions);
+                return poODS;
+            }
+
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "%s driver does not support data source creation.",
                     psOptions->pszFormat );
             GDALVectorTranslateOptionsFree(psOptions);
             return NULL;
@@ -1538,8 +2232,32 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
         }
     }
 
+/* -------------------------------------------------------------------- */
+/*      For random reading                                              */
+/* -------------------------------------------------------------------- */
+    const bool bRandomLayerReading = CPL_TO_BOOL(
+                                    poDS->TestCapability(ODsCRandomLayerRead));
+    if( bRandomLayerReading &&
+        !poODS->TestCapability(ODsCRandomLayerWrite) &&
+        !psOptions->bQuiet )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                    "Input datasource uses random layer reading, but "
+                    "output datasource does not support random layer writing");
+    }
+
     if( psOptions->nLayerTransaction < 0 )
-        psOptions->nLayerTransaction = !poODS->TestCapability(ODsCTransactions);
+    {
+        if( bRandomLayerReading )
+            psOptions->nLayerTransaction = FALSE;
+        else
+            psOptions->nLayerTransaction = !poODS->TestCapability(ODsCTransactions);
+    }
+    else if( psOptions->nLayerTransaction &&
+             bRandomLayerReading )
+    {
+        psOptions->nLayerTransaction = false;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Parse the output SRS definition if possible.                    */
@@ -1616,21 +2334,10 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
     }
 
 /* -------------------------------------------------------------------- */
-/*      For OSM file.                                                   */
-/* -------------------------------------------------------------------- */
-    int         bSrcIsOSM = (strcmp(poDS->GetDriverName(), "OSM") == 0);
-    vsi_l_offset nSrcFileSize = 0;
-    if( bSrcIsOSM && strcmp(poDS->GetDescription(), "/vsistdin/") != 0)
-    {
-        VSIStatBufL sStat;
-        if( VSIStatL(poDS->GetDescription(), &sStat) == 0 )
-            nSrcFileSize = sStat.st_size;
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Create layer setup and transformer objects.                     */
 /* -------------------------------------------------------------------- */
     SetupTargetLayer oSetup;
+    oSetup.m_poSrcDS = poDS;
     oSetup.m_poDstDS = poODS;
     oSetup.m_papszLCO = psOptions->papszLCO;
     oSetup.m_poOutputSRS = poOutputSRS;
@@ -1677,8 +2384,8 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
     oTranslator.m_poClipSrc = (OGRGeometry *)psOptions->hClipSrc;
     oTranslator.m_poClipDst = (OGRGeometry *)psOptions->hClipDst;
     oTranslator.m_bExplodeCollections = psOptions->bExplodeCollections;
-    oTranslator.m_nSrcFileSize = nSrcFileSize;
     oTranslator.m_bNativeData = psOptions->bNativeData;
+    oTranslator.m_nLimit = psOptions->nLimit;
 
     if( psOptions->nGroupTransactions )
     {
@@ -1686,6 +2393,8 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
             poODS->StartTransaction(psOptions->bForceTransaction);
     }
 
+    GIntBig nTotalEventsDone = 0;
+
 /* -------------------------------------------------------------------- */
 /*      Special case for -sql clause.  No source layers required.       */
 /* -------------------------------------------------------------------- */
@@ -1694,7 +2403,7 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
         /* Special case: if output=input, then we must likely destroy the */
         /* old table before to avoid transaction issues. */
         if( poDS == poODS && psOptions->pszNewLayerName != NULL && bOverwrite )
-            GetLayerAndOverwriteIfNecessary(poODS, psOptions->pszNewLayerName, bOverwrite, NULL);
+            GetLayerAndOverwriteIfNecessary(poODS, psOptions->pszNewLayerName, bOverwrite, NULL, NULL);
 
         if( psOptions->pszWHERE != NULL )
             CPLError( CE_Warning, CPLE_AppDefined, "-where clause ignored in combination with -sql." );
@@ -1723,7 +2432,7 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
             void        *pProgressArg = NULL;
             if (psOptions->bDisplayProgress)
             {
-                if (bSrcIsOSM)
+                if (bRandomLayerReading)
                 {
                     pfnProgress = psOptions->pfnProgress;
                     pProgressArg = psOptions->pProgressData;
@@ -1768,13 +2477,15 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
 
             TargetLayerInfo* psInfo = oSetup.Setup(poPassedLayer,
                                                    psOptions->pszNewLayerName,
-                                                   psOptions);
+                                                   psOptions,
+                                                   nTotalEventsDone);
 
             poPassedLayer->ResetReading();
 
             if( psInfo == NULL ||
-                !oTranslator.Translate( psInfo,
+                !oTranslator.Translate( NULL, psInfo,
                                         nCountLayerFeatures, NULL,
+                                        nTotalEventsDone,
                                         pfnProgress, pProgressArg, psOptions ))
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
@@ -1801,11 +2512,8 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
 /* -------------------------------------------------------------------- */
 /*      Special case for layer interleaving mode.                       */
 /* -------------------------------------------------------------------- */
-    else if( bSrcIsOSM &&
-                CPLTestBool(CPLGetConfigOption("OGR_INTERLEAVED_READING", "YES")) )
+    else if( bRandomLayerReading )
     {
-        CPLSetConfigOption("OGR_INTERLEAVED_READING", "YES");
-
         if (psOptions->bSplitListFields)
         {
             CPLError( CE_Failure, CPLE_AppDefined, "-splitlistfields not supported in this mode" );
@@ -1815,6 +2523,23 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
             return NULL;
         }
 
+        // Make sure to probe all layers in case some are by default invisible
+        for( char** papszIter = psOptions->papszLayers;
+                    papszIter && *papszIter; ++papszIter )
+        {
+            OGRLayer        *poLayer = poDS->GetLayerByName(*papszIter);
+
+            if( poLayer == NULL )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Couldn't fetch requested layer %s!",
+                          *papszIter );
+                GDALVectorTranslateOptionsFree(psOptions);
+                if( hDstDS == NULL ) GDALClose( poODS );
+                delete poGCPCoordTrans;
+                return NULL;
+            }
+        }
+
         int nSrcLayerCount = poDS->GetLayerCount();
         AssociatedLayers* pasAssocLayers =
             (AssociatedLayers* ) CPLCalloc(nSrcLayerCount, sizeof(AssociatedLayers));
@@ -1834,7 +2559,7 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
 
         GDALProgressFunc pfnProgress = NULL;
         void        *pProgressArg = NULL;
-        if ( psOptions->bDisplayProgress && bSrcIsOSM )
+        if ( !psOptions->bQuiet )
         {
             pfnProgress = psOptions->pfnProgress;
             pProgressArg = psOptions->pProgressData;
@@ -1843,11 +2568,10 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
 /* -------------------------------------------------------------------- */
 /*      If no target layer specified, use all source layers.            */
 /* -------------------------------------------------------------------- */
-        int iLayer;
         if ( CSLCount(psOptions->papszLayers) == 0)
         {
             psOptions->papszLayers = (char**) CPLCalloc(sizeof(char*), nSrcLayerCount + 1);
-            for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
+            for( int iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
             {
                 OGRLayer        *poLayer = poDS->GetLayer(iLayer);
 
@@ -1866,10 +2590,11 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
         }
         else
         {
+            bool bSrcIsOSM = (strcmp(poDS->GetDriverName(), "OSM") == 0);
             if ( bSrcIsOSM )
             {
                 CPLString osInterestLayers = "SET interest_layers =";
-                for( iLayer = 0; psOptions->papszLayers[iLayer] != NULL; iLayer++ )
+                for( int iLayer = 0; psOptions->papszLayers[iLayer] != NULL; iLayer++ )
                 {
                     if( iLayer != 0 ) osInterestLayers += ",";
                     osInterestLayers += psOptions->papszLayers[iLayer];
@@ -1880,9 +2605,11 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
         }
 
 /* -------------------------------------------------------------------- */
-/*      First pass to set filters and create target layers.             */
+/*      First pass to set filters.                                      */
 /* -------------------------------------------------------------------- */
-        for( iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
+        std::map<OGRLayer*, int> oMapLayerToIdx;
+
+        for( int iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
         {
             OGRLayer        *poLayer = poDS->GetLayer(iLayer);
             if( poLayer == NULL )
@@ -1903,8 +2630,10 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
                 {
                     if( poLayer->SetAttributeFilter( psOptions->pszWHERE ) != OGRERR_NONE )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined, "SetAttributeFilter(%s) on layer '%s' failed.",
-                                 psOptions->pszWHERE, poLayer->GetName() );
+                        CPLError( CE_Failure,
+                                  CPLE_AppDefined,
+                                  "SetAttributeFilter(%s) on layer '%s' failed.",
+                                  psOptions->pszWHERE, poLayer->GetName() );
                         if (!psOptions->bSkipFailures)
                         {
                             GDALVectorTranslateOptionsFree(psOptions);
@@ -1915,85 +2644,130 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
                     }
                 }
 
-                ApplySpatialFilter(poLayer, (OGRGeometry*)psOptions->hSpatialFilter, poSpatSRS, psOptions->pszGeomField, poSourceSRS );
+                ApplySpatialFilter(poLayer,
+                                   (OGRGeometry*)psOptions->hSpatialFilter,
+                                   poSpatSRS, psOptions->pszGeomField,
+                                   poSourceSRS );
 
-                TargetLayerInfo* psInfo = oSetup.Setup(poLayer,
-                                                       psOptions->pszNewLayerName,
-                                                       psOptions);
-
-                if( psInfo == NULL && !psOptions->bSkipFailures )
-                {
-                    GDALVectorTranslateOptionsFree(psOptions);
-                    if( hDstDS == NULL ) GDALClose( poODS );
-                    delete poGCPCoordTrans;
-                    return NULL;
-                }
-
-                pasAssocLayers[iLayer].psInfo = psInfo;
-            }
-            else
-            {
-                pasAssocLayers[iLayer].psInfo = NULL;
+                oMapLayerToIdx[ poLayer ] = iLayer;
             }
+            pasAssocLayers[iLayer].psInfo = NULL;
         }
 
 /* -------------------------------------------------------------------- */
 /*      Second pass to process features in a interleaved layer mode.    */
 /* -------------------------------------------------------------------- */
-        bool bHasLayersNonEmpty;
-        do
-        {
-            bHasLayersNonEmpty = false;
-
-            for( iLayer = 0; iLayer < nSrcLayerCount;  iLayer++ )
+        bool bTargetLayersHaveBeenCreated = false;
+        while( true )
+        {
+            OGRLayer* poFeatureLayer = NULL;
+            OGRFeature* poFeature = poDS->GetNextFeature(&poFeatureLayer,
+                                                         NULL,
+                                                         pfnProgress,
+                                                         pProgressArg);
+            if( poFeature == NULL )
+                break;
+            std::map<OGRLayer*, int>::const_iterator oIter =
+                                                oMapLayerToIdx.find(poFeatureLayer);
+            if( oIter == oMapLayerToIdx.end() )
             {
-                OGRLayer        *poLayer = pasAssocLayers[iLayer].poSrcLayer;
-                TargetLayerInfo *psInfo = pasAssocLayers[iLayer].psInfo;
-                GIntBig nReadFeatureCount = 0;
-
-                if( psInfo )
+                // Feature in a layer that is not a layer of interest.
+                OGRFeature::DestroyFeature(poFeature);
+            }
+            else
+            {
+                if( !bTargetLayersHaveBeenCreated )
                 {
-                    if( !oTranslator.Translate( psInfo,
-                                                0, &nReadFeatureCount,
-                                                pfnProgress, pProgressArg, psOptions )
-                        && !psOptions->bSkipFailures )
+                    // We defer target layer creation at the first feature
+                    // retrieved since getting the layer definition can be
+                    // costly (case of the GMLAS driver) and thus we'd better
+                    // taking advantage from the progress callback of
+                    // GetNextFeature.
+                    bTargetLayersHaveBeenCreated = true;
+                    for( int iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                "Terminating translation prematurely after failed\n"
-                                "translation of layer %s (use -skipfailures to skip errors)",
-                                poLayer->GetName() );
+                        OGRLayer        *poLayer = poDS->GetLayer(iLayer);
+                        if( CSLFindString(psOptions->papszLayers, poLayer->GetName()) < 0 )
+                            continue;
 
-                        nRetCode = 1;
-                        break;
+                        TargetLayerInfo* psInfo = oSetup.Setup(poLayer,
+                                                               psOptions->pszNewLayerName,
+                                                               psOptions,
+                                                               nTotalEventsDone);
+
+                        if( psInfo == NULL && !psOptions->bSkipFailures )
+                        {
+                            GDALVectorTranslateOptionsFree(psOptions);
+                            if( hDstDS == NULL ) GDALClose( poODS );
+                            delete poGCPCoordTrans;
+                            OGRFeature::DestroyFeature(poFeature);
+                            return NULL;
+                        }
+
+                        pasAssocLayers[iLayer].psInfo = psInfo;
                     }
+                    if( nRetCode )
+                        break;
                 }
-                else
+
+                int iLayer = oIter->second;
+                TargetLayerInfo *psInfo = pasAssocLayers[iLayer].psInfo;
+                if( (psInfo == NULL ||
+                     !oTranslator.Translate( poFeature, psInfo,
+                                            0, NULL,
+                                            nTotalEventsDone,
+                                            NULL, NULL, psOptions ))
+                    && !psOptions->bSkipFailures )
                 {
-                    /* No matching target layer : just consumes the features */
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                            "Terminating translation prematurely after failed\n"
+                            "translation of layer %s (use -skipfailures to skip errors)",
+                            poFeatureLayer->GetName() );
 
-                    OGRFeature* poFeature;
-                    while( (poFeature = poLayer->GetNextFeature()) != NULL )
-                    {
-                        nReadFeatureCount ++;
-                        OGRFeature::DestroyFeature(poFeature);
-                    }
+                    nRetCode = 1;
+                    break;
                 }
-
-                if( nReadFeatureCount != 0 )
-                    bHasLayersNonEmpty = true;
+                if( psInfo == NULL )
+                    OGRFeature::DestroyFeature(poFeature);
             }
-        }
-        while( bHasLayersNonEmpty );
+        }  // while true
 
         if (pfnProgress)
         {
             pfnProgress(1.0, "", pProgressArg);
         }
 
+        if( !bTargetLayersHaveBeenCreated )
+        {
+            // bTargetLayersHaveBeenCreated not used after here.
+            // bTargetLayersHaveBeenCreated = true;
+            for( int iLayer = 0; iLayer < nSrcLayerCount; iLayer++ )
+            {
+                OGRLayer        *poLayer = poDS->GetLayer(iLayer);
+                if( CSLFindString(psOptions->papszLayers, poLayer->GetName()) < 0 )
+                    continue;
+
+                TargetLayerInfo* psInfo = oSetup.Setup(poLayer,
+                                                       psOptions->pszNewLayerName,
+                                                       psOptions,
+                                                       nTotalEventsDone);
+
+                if( psInfo == NULL && !psOptions->bSkipFailures )
+                {
+                    GDALVectorTranslateOptionsFree(psOptions);
+                    if( hDstDS == NULL ) GDALClose( poODS );
+                    delete poGCPCoordTrans;
+                    return NULL;
+                }
+
+                pasAssocLayers[iLayer].psInfo = psInfo;
+            }
+        }
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
-        for( iLayer = 0; iLayer < nSrcLayerCount;  iLayer++ )
+        for( int iLayer = 0; iLayer < nSrcLayerCount;  iLayer++ )
         {
             if( pasAssocLayers[iLayer].psInfo )
                 FreeTargetLayerInfo(pasAssocLayers[iLayer].psInfo);
@@ -2109,7 +2883,7 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
 
             ApplySpatialFilter(poLayer, (OGRGeometry*)psOptions->hSpatialFilter, poSpatSRS, psOptions->pszGeomField, poSourceSRS);
 
-            if (psOptions->bDisplayProgress && !bSrcIsOSM)
+            if (psOptions->bDisplayProgress)
             {
                 if (!poLayer->TestCapability(OLCFastFeatureCount))
                 {
@@ -2170,15 +2944,9 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
                 pProgressArg = NULL;
             }
 
-
             if (psOptions->bDisplayProgress)
             {
-                if ( bSrcIsOSM )
-                {
-                    pfnProgress = psOptions->pfnProgress;
-                    pProgressArg = psOptions->pProgressData;
-                }
-                else if( nCountLayersFeatures != 0 )
+                if( nCountLayersFeatures != 0 )
                 {
                     pfnProgress = GDALScaledProgress;
                     GIntBig nStart = 0;
@@ -2196,13 +2964,15 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
 
             TargetLayerInfo* psInfo = oSetup.Setup(poPassedLayer,
                                                    psOptions->pszNewLayerName,
-                                                   psOptions);
+                                                   psOptions,
+                                                   nTotalEventsDone);
 
             poPassedLayer->ResetReading();
 
             if( (psInfo == NULL ||
-                !oTranslator.Translate( psInfo,
+                !oTranslator.Translate( NULL, psInfo,
                                         panLayerCountFeatures[iLayer], NULL,
+                                        nTotalEventsDone,
                                         pfnProgress, pProgressArg, psOptions ))
                 && !psOptions->bSkipFailures )
             {
@@ -2219,7 +2989,7 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
             if (poPassedLayer != poLayer)
                 delete poPassedLayer;
 
-            if (psOptions->bDisplayProgress && !bSrcIsOSM)
+            if (psOptions->bDisplayProgress)
                 GDALDestroyScaledProgress(pProgressArg);
         }
 
@@ -2255,7 +3025,6 @@ GDALDatasetH GDALVectorTranslate( const char *pszDest, GDALDatasetH hDstDS, int
     }
 }
 
-
 /************************************************************************/
 /*                               SetZ()                                 */
 /************************************************************************/
@@ -2331,10 +3100,13 @@ static int ForceCoordDimension(int eGType, int nCoordDim)
 static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
                                                  const char* pszNewLayerName,
                                                  bool bOverwrite,
-                                                 bool* pbErrorOccurred)
+                                                 bool* pbErrorOccurred,
+                                                 bool* pbOverwriteActuallyDone)
 {
     if( pbErrorOccurred )
         *pbErrorOccurred = false;
+    if( pbOverwriteActuallyDone )
+        *pbOverwriteActuallyDone = false;
 
     /* GetLayerByName() can instantiate layers that would have been */
     /* 'hidden' otherwise, for example, non-spatial tables in a */
@@ -2375,6 +3147,11 @@ static OGRLayer* GetLayerAndOverwriteIfNecessary(GDALDataset *poDstDS,
             if( pbErrorOccurred )
                 *pbErrorOccurred = true;
         }
+        else
+        {
+            if( pbOverwriteActuallyDone )
+                *pbOverwriteActuallyDone = true;
+        }
         poDstLayer = NULL;
     }
 
@@ -2391,8 +3168,15 @@ static OGRwkbGeometryType ConvertType(GeomTypeConversion eGeomTypeConversion,
     OGRwkbGeometryType eRetType = eGType;
     if ( eGeomTypeConversion == GTC_PROMOTE_TO_MULTI )
     {
-        if( !OGR_GT_IsSubClassOf(eGType, wkbGeometryCollection) )
+        if( eGType == wkbTriangle || eGType == wkbTIN ||
+            eGType == wkbPolyhedralSurface )
+        {
+            eRetType = wkbMultiPolygon;
+        }
+        else if( !OGR_GT_IsSubClassOf(eGType, wkbGeometryCollection) )
+        {
             eRetType = OGR_GT_GetCollection(eGType);
+        }
     }
     else if ( eGeomTypeConversion == GTC_CONVERT_TO_LINEAR )
         eRetType = OGR_GT_GetLinear(eGType);
@@ -2524,7 +3308,8 @@ void DoFieldTypeConversion(GDALDataset* poDstDS, OGRFieldDefn& oFieldDefn,
 
 TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
                                          const char* pszNewLayerName,
-                                         GDALVectorTranslateOptions *psOptions)
+                                         GDALVectorTranslateOptions *psOptions,
+                                         GIntBig& nTotalEventsDone)
 {
     OGRLayer    *poDstLayer;
     OGRFeatureDefn *poSrcFDefn;
@@ -2588,7 +3373,7 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
     OGRSpatialReference* poOutputSRS = m_poOutputSRS;
     if( poOutputSRS == NULL && !m_bNullifyOutputSRS )
     {
-        if( nSrcGeomFieldCount == 1 || anRequestedGeomFields.size() == 0 )
+        if( nSrcGeomFieldCount == 1 || anRequestedGeomFields.empty() )
             poOutputSRS = poSrcLayer->GetSpatialRef();
         else if( anRequestedGeomFields.size() == 1 )
         {
@@ -2615,10 +3400,12 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
 /* -------------------------------------------------------------------- */
 
     bool bErrorOccurred;
+    bool bOverwriteActuallyDone;
     poDstLayer = GetLayerAndOverwriteIfNecessary(m_poDstDS,
                                                  pszNewLayerName,
                                                  m_bOverwrite,
-                                                 &bErrorOccurred);
+                                                 &bErrorOccurred,
+                                                 &bOverwriteActuallyDone);
     if( bErrorOccurred )
         return NULL;
 
@@ -2630,15 +3417,16 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
         if( !m_poDstDS->TestCapability( ODsCCreateLayer ) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-              "Layer %s not found, and CreateLayer not supported by driver.",
-                     pszNewLayerName );
+                      "Layer '%s' does not already exist in the output dataset, and "
+                      "cannot be created by the output driver.",
+                      pszNewLayerName );
             return NULL;
         }
 
         bool bForceGType = ( eGType != GEOMTYPE_UNCHANGED );
         if( !bForceGType )
         {
-            if( anRequestedGeomFields.size() == 0 )
+            if( anRequestedGeomFields.empty() )
             {
                 eGType = poSrcFDefn->GetGeomType();
             }
@@ -2687,7 +3475,7 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
         char** papszLCOTemp = CSLDuplicate(m_papszLCO);
 
         int eGCreateLayerType = eGType;
-        if( anRequestedGeomFields.size() == 0 &&
+        if( anRequestedGeomFields.empty() &&
             nSrcGeomFieldCount > 1 &&
             m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
         {
@@ -2701,7 +3489,7 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
         // If the source feature has a single geometry column that is not nullable
         // and that ODsCCreateGeomFieldAfterCreateLayer is available, use it
         // so as to be able to set the not null constraint (if the driver supports it)
-        else if( anRequestedGeomFields.size() == 0 &&
+        else if( anRequestedGeomFields.empty() &&
                  nSrcGeomFieldCount == 1 &&
                  m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) &&
                  !poSrcFDefn->GetGeomFieldDefn(0)->IsNullable() &&
@@ -2713,7 +3501,7 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
         // If the source feature first geometry column is not nullable
         // and that GEOMETRY_NULLABLE creation option is available, use it
         // so as to be able to set the not null constraint (if the driver supports it)
-        else if( anRequestedGeomFields.size() == 0 &&
+        else if( anRequestedGeomFields.empty() &&
                  nSrcGeomFieldCount >= 1 &&
                  !poSrcFDefn->GetGeomFieldDefn(0)->IsNullable() &&
                  m_poDstDS->GetDriver()->GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST) != NULL &&
@@ -2724,6 +3512,19 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
             papszLCOTemp = CSLSetNameValue(papszLCOTemp, "GEOMETRY_NULLABLE", "NO");
             CPLDebug("GDALVectorTranslate", "Using GEOMETRY_NULLABLE=NO");
         }
+        // Special case for conversion from GMLAS driver to ensure that
+        // source geometry field name will be used as much as possible
+        // FIXME: why not make this general behaviour ?
+        else if( anRequestedGeomFields.empty() &&
+                 nSrcGeomFieldCount == 1 &&
+                 m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) &&
+                 m_poSrcDS != NULL &&
+                 m_poSrcDS->GetDriver() != NULL &&
+                 EQUAL(m_poSrcDS->GetDriver()->GetDescription(), "GMLAS") )
+        {
+            anRequestedGeomFields.push_back(0);
+            eGCreateLayerType = wkbNone;
+        }
 
         // Force FID column as 64 bit if the source feature has a 64 bit FID,
         // the target driver supports 64 bit FID and the user didn't set it
@@ -2802,7 +3603,7 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
             CSLDestroy(papszDomains);
         }
 
-        if( anRequestedGeomFields.size() == 0 &&
+        if( anRequestedGeomFields.empty() &&
             nSrcGeomFieldCount > 1 &&
             m_poDstDS->TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
         {
@@ -3099,6 +3900,7 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
                     poDstFDefn = poDstLayer->GetLayerDefn();
 
                 /* Sanity check : if it fails, the driver is buggy */
+                // cppcheck-suppress nullPointerRedundantCheck
                 if (poDstFDefn != NULL &&
                     poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
                 {
@@ -3146,6 +3948,26 @@ TargetLayerInfo* SetupTargetLayer::Setup(OGRLayer* poSrcLayer,
         }
     }
 
+    if( bOverwriteActuallyDone &&
+        EQUAL(m_poDstDS->GetDriver()->GetDescription(), "PostgreSQL") &&
+        !psOptions->nLayerTransaction &&
+        psOptions->nGroupTransactions >= 0 &&
+        CPLTestBool(CPLGetConfigOption("PG_COMMIT_WHEN_OVERWRITING", "YES")) )
+    {
+        CPLDebug("GDALVectorTranslate",
+                 "Forcing transaction commit as table overwriting occurred");
+        // Commit when overwriting as this consumes a lot of PG resources
+        // and could result in """out of shared memory.
+        // You might need to increase max_locks_per_transaction."""" errors
+        if( m_poDstDS->CommitTransaction() == OGRERR_FAILURE ||
+            m_poDstDS->StartTransaction(psOptions->bForceTransaction) == OGRERR_FAILURE )
+        {
+            VSIFree(panMap);
+            return NULL;
+        }
+        nTotalEventsDone = 0;
+    }
+
     TargetLayerInfo* psInfo = (TargetLayerInfo*)
                                             CPLMalloc(sizeof(TargetLayerInfo));
     psInfo->nFeaturesRead = 0;
@@ -3318,7 +4140,7 @@ static bool SetupCT( TargetLayerInfo* psInfo,
             {
                 papszTransformOptions =
                     CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
-                if( osDateLineOffset.size() )
+                if( !osDateLineOffset.empty() )
                 {
                     CPLString soOffset("DATELINEOFFSET=");
                     soOffset += osDateLineOffset;
@@ -3330,7 +4152,7 @@ static bool SetupCT( TargetLayerInfo* psInfo,
             {
                 papszTransformOptions =
                     CSLAddString(papszTransformOptions, "WRAPDATELINE=YES");
-                if( osDateLineOffset.size() )
+                if( !osDateLineOffset.empty() )
                 {
                     CPLString soOffset("DATELINEOFFSET=");
                     soOffset += osDateLineOffset;
@@ -3357,9 +4179,11 @@ static bool SetupCT( TargetLayerInfo* psInfo,
 /*                     LayerTranslator::Translate()                     */
 /************************************************************************/
 
-int LayerTranslator::Translate( TargetLayerInfo* psInfo,
+int LayerTranslator::Translate( OGRFeature* poFeatureIn,
+                                TargetLayerInfo* psInfo,
                                 GIntBig nCountLayerFeatures,
                                 GIntBig* pnReadFeatureCount,
+                                GIntBig& nTotalEventsDone,
                                 GDALProgressFunc pfnProgress,
                                 void *pProgressArg,
                                 GDALVectorTranslateOptions *psOptions )
@@ -3389,7 +4213,6 @@ int LayerTranslator::Translate( TargetLayerInfo* psInfo,
             poOutputSRS = poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(
                 psInfo->iRequestedSrcGeomField)->GetSpatialRef();
         }
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -3404,7 +4227,7 @@ int LayerTranslator::Translate( TargetLayerInfo* psInfo,
     {
         if( psOptions->nLayerTransaction )
         {
-            if( poDstLayer->StartTransaction() != OGRERR_NONE )
+            if( poDstLayer->StartTransaction() == OGRERR_FAILURE )
                 return false;
         }
     }
@@ -3414,10 +4237,14 @@ int LayerTranslator::Translate( TargetLayerInfo* psInfo,
     {
         OGRFeature      *poDstFeature = NULL;
 
-        if( psOptions->nFIDToFetch != OGRNullFID )
+        if( poFeatureIn != NULL )
+            poFeature = poFeatureIn;
+        else if( psOptions->nFIDToFetch != OGRNullFID )
             poFeature = poSrcLayer->GetFeature(psOptions->nFIDToFetch);
         else
             poFeature = poSrcLayer->GetNextFeature();
+        if( m_nLimit >= 0 && psInfo->nFeaturesRead >= m_nLimit )
+            break;
 
         if( poFeature == NULL )
             break;
@@ -3457,27 +4284,28 @@ int LayerTranslator::Translate( TargetLayerInfo* psInfo,
 
         for(int iPart = 0; iPart < nIters; iPart++)
         {
-            if( ++nFeaturesInTransaction == psOptions->nGroupTransactions )
+            if( psOptions->nLayerTransaction &&
+                ++nFeaturesInTransaction == psOptions->nGroupTransactions )
             {
-                if( psOptions->nLayerTransaction )
+                if( poDstLayer->CommitTransaction() == OGRERR_FAILURE ||
+                    poDstLayer->StartTransaction() == OGRERR_FAILURE )
                 {
-                    if( poDstLayer->CommitTransaction() != OGRERR_NONE ||
-                        poDstLayer->StartTransaction() != OGRERR_NONE )
-                    {
-                        OGRFeature::DestroyFeature( poFeature );
-                        return false;
-                    }
+                    OGRFeature::DestroyFeature( poFeature );
+                    return false;
                 }
-                else
+                nFeaturesInTransaction = 0;
+            }
+            else if( !psOptions->nLayerTransaction &&
+                     psOptions->nGroupTransactions >= 0 &&
+                     ++nTotalEventsDone >= psOptions->nGroupTransactions )
+            {
+                if( m_poODS->CommitTransaction() == OGRERR_FAILURE ||
+                        m_poODS->StartTransaction(psOptions->bForceTransaction) == OGRERR_FAILURE )
                 {
-                    if( m_poODS->CommitTransaction() != OGRERR_NONE ||
-                        m_poODS->StartTransaction(psOptions->bForceTransaction) != OGRERR_NONE )
-                    {
-                        OGRFeature::DestroyFeature( poFeature );
-                        return false;
-                    }
+                    OGRFeature::DestroyFeature( poFeature );
+                    return false;
                 }
-                nFeaturesInTransaction = 0;
+                nTotalEventsDone = 0;
             }
 
             CPLErrorReset();
@@ -3533,7 +4361,7 @@ int LayerTranslator::Translate( TargetLayerInfo* psInfo,
             if( bPreserveFID )
                 poDstFeature->SetFID( poFeature->GetFID() );
             else if( psInfo->iSrcFIDField >= 0 &&
-                     poFeature->IsFieldSet(psInfo->iSrcFIDField))
+                     poFeature->IsFieldSetAndNotNull(psInfo->iSrcFIDField))
                 poDstFeature->SetFID( poFeature->GetFieldAsInteger64(psInfo->iSrcFIDField) );
 
             /* Erase native data if asked explicitly */
@@ -3703,7 +4531,7 @@ int LayerTranslator::Translate( TargetLayerInfo* psInfo,
             {
                 nFeaturesWritten ++;
                 if( (bPreserveFID && poDstFeature->GetFID() != poFeature->GetFID()) ||
-                    (!bPreserveFID && psInfo->iSrcFIDField >= 0 && poFeature->IsFieldSet(psInfo->iSrcFIDField) &&
+                    (!bPreserveFID && psInfo->iSrcFIDField >= 0 && poFeature->IsFieldSetAndNotNull(psInfo->iSrcFIDField) &&
                      poDstFeature->GetFID() != poFeature->GetFieldAsInteger64(psInfo->iSrcFIDField)) )
                 {
                     CPLError( CE_Warning, CPLE_AppDefined,
@@ -3756,29 +4584,7 @@ end_loop:
         bool bGoOn = true;
         if (pfnProgress)
         {
-            if (m_nSrcFileSize != 0)
-            {
-                if ((nCount % 1000) == 0)
-                {
-                    OGRLayer* poFCLayer = m_poSrcDS->ExecuteSQL("GetBytesRead()", NULL, NULL);
-                    if( poFCLayer != NULL )
-                    {
-                        OGRFeature* poFeat = poFCLayer->GetNextFeature();
-                        if( poFeat )
-                        {
-                            const char* pszReadSize = poFeat->GetFieldAsString(0);
-                            GUIntBig nReadSize = CPLScanUIntBig( pszReadSize, 32 );
-                            bGoOn = pfnProgress(nReadSize * 1.0 / m_nSrcFileSize, "", pProgressArg) != FALSE;
-                            OGRFeature::DestroyFeature( poFeat );
-                        }
-                    }
-                    m_poSrcDS->ReleaseResultSet(poFCLayer);
-                }
-            }
-            else
-            {
-                bGoOn = pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg) != FALSE;
-            }
+            bGoOn = pfnProgress(nCount * 1.0 / nCountLayerFeatures, "", pProgressArg) != FALSE;
         }
         if( !bGoOn )
         {
@@ -3791,6 +4597,8 @@ end_loop:
 
         if( psOptions->nFIDToFetch != OGRNullFID )
             break;
+        if( poFeatureIn != NULL )
+            break;
     }
 
     if( psOptions->nGroupTransactions )
@@ -3802,8 +4610,11 @@ end_loop:
         }
     }
 
-    CPLDebug("GDALVectorTranslate", CPL_FRMT_GIB " features written in layer '%s'",
-             nFeaturesWritten, poDstLayer->GetName());
+    if( poFeatureIn == NULL )
+    {
+        CPLDebug("GDALVectorTranslate", CPL_FRMT_GIB " features written in layer '%s'",
+                nFeaturesWritten, poDstLayer->GetName());
+    }
 
     return bRet;
 }
@@ -3906,9 +4717,10 @@ GDALVectorTranslateOptions *GDALVectorTranslateOptionsNew(char** papszArgv,
     psOptions->nTransformOrder = 0;  /* Default to 0 for now... let the lib decide */
     psOptions->hSpatialFilter = NULL;
     psOptions->bNativeData = true;
+    psOptions->nLimit = -1;
 
     int nArgc = CSLCount(papszArgv);
-    for( int i = 0; i < nArgc; i++ )
+    for( int i = 0; papszArgv != NULL && i < nArgc; i++ )
     {
         if( EQUAL(papszArgv[i],"-q") || EQUAL(papszArgv[i],"-quiet") )
         {
@@ -3918,7 +4730,8 @@ GDALVectorTranslateOptions *GDALVectorTranslateOptionsNew(char** papszArgv,
         else if( EQUAL(papszArgv[i],"-f") && i+1 < nArgc )
         {
             CPLFree(psOptions->pszFormat);
-            psOptions->pszFormat = CPLStrdup(papszArgv[++i]);
+            const char* pszFormatArg = papszArgv[++i];
+            psOptions->pszFormat = CPLStrdup(pszFormatArg);
             if( psOptionsForBinary )
             {
                 psOptionsForBinary->bFormatExplicitlySet = TRUE;
@@ -4483,6 +5296,10 @@ GDALVectorTranslateOptions *GDALVectorTranslateOptionsNew(char** papszArgv,
             psOptions->papszMetadataOptions = CSLAddString( psOptions->papszMetadataOptions,
                                                  papszArgv[++i] );
         }
+        else if( EQUAL(papszArgv[i],"-limit") && i+1 < nArgc )
+        {
+            psOptions->nLimit = CPLAtoGIntBig( papszArgv[++i] );
+        }
         else if( papszArgv[i][0] == '-' )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
diff --git a/apps/ogr_utilities.dox b/apps/ogr_utilities.dox
index 6d7a5c2..07b9bb5 100644
--- a/apps/ogr_utilities.dox
+++ b/apps/ogr_utilities.dox
@@ -9,10 +9,11 @@ toolkit:
 <li> \ref ogr2ogr - Converts simple features data between file formats
 <li> \ref ogrtindex - Creates a tileindex
 <li> \ref ogrlineref - Create linear reference and provide some calculations using it
+<li> \ref ogrmerge - Merge several vector datasets into a single one
 </ul>
 
-\section gdal_utilities_switches General Command Line Switches
-All GDAL OGR command line utility programs support the following 
+\section ogr_utilities_switches General Command Line Switches
+All GDAL OGR command line utility programs support the following
 "general" options.<p>
 
 <dl>
@@ -20,7 +21,7 @@ All GDAL OGR command line utility programs support the following
 
 <dt> <b>\-\-formats</b></dt><dd> List all vector formats supported by this
 GDAL build (read-only and read-write) and exit. The format support is indicated
- as follows: 'ro' is read-only driver; 
+ as follows: 'ro' is read-only driver;
 'rw' is read or write (i.e. supports CreateCopy);
 'rw+' is read, write and update (i.e. supports Create).
 A 'v' is appended for formats supporting virtual IO (/vsimem, /vsigzip, /vsizip, etc).
@@ -28,34 +29,34 @@ A 's' is appended for formats supporting subdatasets.
 </dd>
 
 <dt> <b>\-\-format</b> <i>format</i></dt><dd>
-List detailed information about a single format driver.  The <i>format</i> 
-should be the short name reported in the <b>\-\-formats</b> list, such as 
+List detailed information about a single format driver.  The <i>format</i>
+should be the short name reported in the <b>\-\-formats</b> list, such as
 GML.</dd>
 
 <dt> <b>\-\-optfile</b> <i>file</i></dt><dd>
 Read the named file and substitute the contents into the command line
 options list.  Lines beginning with # will be ignored.  Multi-word arguments
-may be kept together with double quotes. 
+may be kept together with double quotes.
 </dd>
 
 <dt> <b>\-\-config</b> <i>key value</i></dt><dd>
 Sets the named <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">
-configuration keyword</a> to the given value, as opposed to 
+configuration keyword</a> to the given value, as opposed to
 setting them as environment variables.  Some common configuration keywords
 are SHAPE_ENCODING (force shapefile driver to read DBF files with the given
 character encoding) and CPL_TEMPDIR (define the location of temporary files).
-Individual drivers may be influenced by other configuration options.  
+Individual drivers may be influenced by other configuration options.
 </dd>
 
 <dt> <b>\-\-debug</b> <i>value</i></dt><dd>
 Control what debugging messages are emitted.  A value of <i>ON</i> will
 enable all debug messages.  A value of <i>OFF</i> will disable all debug
 messages.  Another value will select only debug messages containing that
-string in the debug prefix code.  
+string in the debug prefix code.
 </dd>
 
 <dt> <b>\-\-help-general</b></dt><dd>
-Gives a brief usage message for the generic GDAL OGR command line options 
+Gives a brief usage message for the generic GDAL OGR command line options
 and exit.
 </dd>
 
@@ -64,9 +65,14 @@ and exit.
 
 */
 
-/*! \page ogrinfo ogrinfo
+/*!
+\if man
+\page ogrinfo
+\else
+\page ogrinfo ogrinfo
+\endif
 
-lists information about an OGR supported data source
+Lists information about an OGR supported data source.
 
 \section ogrinfo_synopsis SYNOPSIS
 
@@ -75,9 +81,9 @@ Usage:
 \endhtmlonly
 
 \verbatim
-ogrinfo [--help-general] [-ro] [-q] [-where restricted_where|@filename]
+ogrinfo [--help-general] [-ro] [-q] [-where restricted_where|\@filename]
         [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]
-        [-sql statement|@filename] [-dialect dialect] [-al] [-so] [-fields={YES/NO}]
+        [-sql statement|\@filename] [-dialect dialect] [-al] [-rl] [-so] [-fields={YES/NO}]
         [-geom={YES/NO/SUMMARY/WKT/ISO_WKT}] [-formats] [[-oo NAME=VALUE] ...]
         [-nomd] [-listmdd] [-mdd domain|`all`]*
         [-nocount] [-noextent]
@@ -88,23 +94,27 @@ ogrinfo [--help-general] [-ro] [-q] [-where restricted_where|@filename]
 \section ogrinfo_description DESCRIPTION
 
 The ogrinfo program lists various information about an OGR supported data
-source to stdout (the terminal). 
+source to stdout (the terminal).
 
 <dl>
 <dt> <b>-ro</b>:</dt><dd> Open the data source in read-only mode.  </dd>
 <dt> <b>-al</b>:</dt><dd> List all features of all layers (used instead of having to
 give layer names as arguments).</dd>
-<dt> <b>-so</b>:</dt><dd> Summary Only: suppress listing of features, show only the 
+<dt> <b>-rl</b>:</dt><dd> (Available in GDAL 2.2) Enable random layer reading mode,
+i.e. iterate over features in the order they are found in the dataset, and not
+layer per layer. This can be significantly faster for some formats (for example
+OSM, GMLAS).</dd>
+<dt> <b>-so</b>:</dt><dd> Summary Only: suppress listing of features, show only the
 summary information like projection, schema, feature count and
 extents.</dd>
 <dt> <b>-q</b>:</dt><dd> Quiet verbose reporting of various information, including
 coordinate system, layer schema, extents, and feature count. </dd>
 <dt> <b>-where</b> <i>restricted_where</i>:</dt><dd> An attribute query in a restricted
 form of the queries used in the SQL WHERE statement.   Only features matching
-the attribute query will be reported. Starting with GDAL 2.1, the @filename syntax
+the attribute query will be reported. Starting with GDAL 2.1, the @\filename syntax
 can be used to indicate that the content is in the pointed filename.</dd>
 <dt> <b>-sql</b> <i>statement</i>:</dt><dd> Execute the indicated SQL statement
-and return the result. Starting with GDAL 2.1, the @filename syntax
+and return the result. Starting with GDAL 2.1, the \@filename syntax
 can be used to indicate that the content is in the pointed filename.</dd>
 <dt> <b>-dialect</b> <em>dialect</em>:</dt><dd> SQL dialect.  In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL.
 Starting with GDAL 1.10, the "SQLITE" dialect can also be used with any datasource.</dd>
@@ -113,7 +123,7 @@ features within the rectangle will be reported.</dd>
 <dt> <b>-geomfield</b> <i>field</i>:</dt><dd> (OGR >= 1.11) Name of the geometry field
 on which the spatial filter operates on.</dd>
 <dt> <b>-fid</b> <i>fid</i>:</dt><dd> If provided, only the feature with this feature
-id will be reported.  Operates exclusive of the spatial or attribute 
+id will be reported.  Operates exclusive of the spatial or attribute
 queries. Note: if you want to select several features based on their feature id, you can
 also use the fact the 'fid' is a special field recognized by OGR SQL. So, '-where "fid in (1,3,5)"'
 would select features 1, 3 and 5.</dd>
@@ -137,8 +147,8 @@ of metadata strings.</dd>
 <dt> <b>-noextent</b></dt><dd>(starting with GDAL 2.0)  Suppress spatial extent printing.</dd>
 <dt> <b>\-\-formats</b>:</dt><dd> List the format drivers that are
 enabled.</dd>
-<dt> <i>datasource_name</i>:</dt><dd> The data source to open.  May be a filename, 
-directory or other virtual name.  See the <a href="ogr/ogr_formats.html">OGR Vector
+<dt> <i>datasource_name</i>:</dt><dd> The data source to open.  May be a filename,
+directory or other virtual name.  See the <a href="ogr_formats.html">OGR Vector
 Formats</a> list for supported datasources.</dd>
 <dt> <i>layer</i>:</dt><dd> One or more layer names may be reported.</dd>
 </dl>
@@ -146,8 +156,8 @@ Formats</a> list for supported datasources.</dd>
 If no layer names are passed then ogrinfo will report a list of available
 layers (and their layer wide geometry type).  If layer name(s) are given then
 their extents, coordinate system, feature count, geometry type, schema and
-all features matching query parameters will be reported to the terminal. 
-If no query parameters are provided, all features are reported.  
+all features matching query parameters will be reported to the terminal.
+If no query parameters are provided, all features are reported.
 
 Geometries are reported in OGC WKT format.
 
@@ -164,7 +174,7 @@ using driver `UK .NTF' successful.
 4: FEATURE_CLASSES (None)
 \endverbatim
 
-Example using an attribute query is used to restrict the output of the 
+Example using an attribute query is used to restrict the output of the
 features in a layer:
 \verbatim
 % ogrinfo -ro -where 'GLOBAL_LINK_ID=185878' wrk/SHETLAND_ISLANDS.NTF BL2000_LINK
@@ -227,9 +237,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
 
-/*! \page ogr2ogr ogr2ogr
+/*!
+\if man
+\page ogr2ogr
+\else
+\page ogr2ogr ogr2ogr
+\endif
 
-converts simple features data between file formats
+Converts simple features data between file formats.
 
 \section ogr2ogr_synopsis SYNOPSIS
 
@@ -239,15 +254,15 @@ Usage:
 
 \verbatim
 Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
-               [-select field_list] [-where restricted_where|@filename] 
-               [-progress] [-sql <sql statement>|@filename] [-dialect dialect]
-               [-preserve_fid] [-fid FID]
+               [-select field_list] [-where restricted_where|\@filename]
+               [-progress] [-sql <sql statement>|\@filename] [-dialect dialect]
+               [-preserve_fid] [-fid FID] [-limit nb_features]
                [-spat xmin ymin xmax ymax] [-spat_srs srs_def] [-geomfield field]
                [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]
                [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]
                dst_datasource_name src_datasource_name
                [-lco NAME=VALUE] [-nln name]
-               [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR]
+               [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR|CONVERT_TO_CURVE]
                [-dim XY|XYZ|XYM|XYZM|2|3|layer_dim] [layer [layer ...]]
 
 Advanced options :
@@ -277,19 +292,19 @@ Advanced options :
 
 This program can be used to convert simple features data between file formats
 performing various operations during the process such as spatial or attribute
-selections, reducing the set of attributes, setting the output coordinate 
+selections, reducing the set of attributes, setting the output coordinate
 system or even reprojecting the features during translation.
 
 <dl>
 <dt><b> -f</b><em> format_name</em>:</dt><dd> output file format name (default is ESRI Shapefile), some possible values are:
-	 \verbatim
+  \verbatim
      -f "ESRI Shapefile"
      -f "TIGER"
      -f "MapInfo File"
      -f "GML"
      -f "PostgreSQL"
-	 \endverbatim
-	 </dd>
+  \endverbatim
+  </dd>
 <dt><b>-append</b>:</dt><dd> Append to existing layer instead of creating
 new</dd>
 <dt><b>-overwrite</b>:</dt><dd> Delete the output layer and recreate it empty</dd>
@@ -302,12 +317,12 @@ same name is found.) Starting with OGR 1.11, geometry fields can also be specifi
 in the list.</dd>
 <dt> <b>-progress</b>:</dt><dd> (starting with GDAL 1.7.0) Display progress on terminal. Only works if input layers have the "fast feature count" capability.</dd>
 <dt> <b>-sql</b> <em>sql_statement</em>:</dt><dd> SQL statement to execute.
-The resulting table/layer will be saved to the output. Starting with GDAL 2.1, the @filename syntax
+The resulting table/layer will be saved to the output. Starting with GDAL 2.1, the \@filename syntax
 can be used to indicate that the content is in the pointed filename.</dd>
 <dt> <b>-dialect</b> <em>dialect</em>:</dt><dd> SQL dialect.  In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL.
 Starting with GDAL 1.10, the "SQLITE" dialect can also be used with any datasource.</dd>
 <dt> <b>-where</b><em> restricted_where</em>:</dt><dd> Attribute query (like SQL WHERE).
-Starting with GDAL 2.1, the @filename syntax can be used to indicate that the content is in the pointed filename.</dd>
+Starting with GDAL 2.1, the \@filename syntax can be used to indicate that the content is in the pointed filename.</dd>
 <dt> <b>-skipfailures</b>:</dt><dd>Continue after a failure, skipping the failed feature.</dd>
 <dt> <b>-spat</b><em> xmin ymin xmax ymax</em>:</dt><dd> spatial query extents, in the
 SRS of the source layer(s) (or the one specified with -spat_srs). Only features
@@ -331,7 +346,10 @@ multilinestrings to multilinestrings. Can be useful when converting
 shapefiles to PostGIS and other target drivers that implement strict
 checks for geometry types. Starting with GDAL 2.0, CONVERT_TO_LINEAR
 can be used to to convert non-linear geometries types into linear
-geometries by approximating them. Starting with 2.1 the type can be
+geometries by approximating them, and CONVERT_TO_CURVE to promote a
+non-linear type to its generalized curve type (POLYGON to CURVEPOLYGON,
+MULTIPOLYGON to MULTISURFACE, LINESTRING to COMPOUNDCURVE, MULTILINESTRING to
+MULTICURVE). Starting with 2.1 the type can be
 defined as measured ("25D" remains as an alias for single "Z").</dd>
 <dt> <b>-dim</b><em> val</em>:</dt><dd>(starting with GDAL 1.10) Force
 the coordinate dimension to val (valid values are XY, XYZ, XYM, and
@@ -350,10 +368,12 @@ has a FID layer creation option. In which case the name of the source FID column
 be used and source feature IDs will be attempted to be preserved. This behaviour
 can be disabled by setting -unsetFid</dd>
 <dt> <b>-fid</b> <i>fid</i>:</dt><dd> If provided, only the feature with this feature
-id will be reported.  Operates exclusive of the spatial or attribute 
+id will be reported.  Operates exclusive of the spatial or attribute
 queries.  Note: if you want to select several features based on their feature id, you can
 also use the fact the 'fid' is a special field recognized by OGR SQL. So, '-where "fid in (1,3,5)"'
 would select features 1, 3 and 5.</dd>
+<dt> <b>-limit</b> <i>nb_features</i>:</dt><dd> (starting with GDAL 2.2): to
+limit the number of features, per layer.</dd>
 </dl>
 
 Srs_def can be a full WKT definition (hard to escape properly), or a well
@@ -411,19 +431,19 @@ Note that this does not influence the field types used by the source driver, and
 <dt> <b>-maxsubfields</b> <em>val</em>:</dt><dd>To be combined with -splitlistfields to limit the number of subfields created for each split field.</dd>
 <dt> <b>-explodecollections</b>:</dt><dd>(starting with GDAL 1.8.0) produce one feature for each geometry in any kind of geometry collection in the source file</dd>
 <dt> <b>-zfield</b> <em>field_name</em>:</dt><dd>(starting with GDAL 1.8.0) Uses the specified field to fill the Z coordinate of geometries</dd>
-<dt> <b>-gcp</b> <i>ungeoref_x ungeoref_y georef_x georef_y elevation</i>:</dt><dd>(starting with GDAL 1.10.0) 
-Add the indicated ground control point.  This option may be provided multiple times to provide a set of GCPs. 
+<dt> <b>-gcp</b> <i>ungeoref_x ungeoref_y georef_x georef_y elevation</i>:</dt><dd>(starting with GDAL 1.10.0)
+Add the indicated ground control point.  This option may be provided multiple times to provide a set of GCPs.
 </dd>
 <dt> <b>-order</b> <em>n</em>:</dt><dd>(starting with GDAL 1.10.0) order of polynomial used for warping
 (1 to 3). The default is to select a polynomial order based on the number of
 GCPs.</dd>
 <dt> <b>-tps</b>:</dt><dd>(starting with GDAL 1.10.0) Force use of thin plate spline transformer based on
 available GCPs.</dd>
-<dt> <b>-fieldmap</b>:</dt><dd>(starting with GDAL 1.10.0) Specifies the list of field indexes to be copied 
-from the source to the destination. The (n)th value specified in the list is the index of the field in the 
-target layer definition in which the n(th) field of the source layer must be copied. Index count starts at 
-zero. There must be exactly as many values in the list as the count of the fields in the source layer. 
-We can use the 'identity' setting to specify that the fields should be transferred by using the same order. 
+<dt> <b>-fieldmap</b>:</dt><dd>(starting with GDAL 1.10.0) Specifies the list of field indexes to be copied
+from the source to the destination. The (n)th value specified in the list is the index of the field in the
+target layer definition in which the n(th) field of the source layer must be copied. Index count starts at
+zero. There must be exactly as many values in the list as the count of the fields in the source layer.
+We can use the 'identity' setting to specify that the fields should be transferred by using the same order.
 This setting should be used along with the -append setting.</dd>
 <dt> <b>-addfields</b>:</dt><dd>(starting with GDAL 1.11) This is a specialized version of
 -append. Contrary to -append, -addfields has the effect of adding, to existing target layers,
@@ -462,8 +482,8 @@ This number is specified with the -gt option. For example, for SQLite, explicitl
 populating some table containing many hundredth thousand or million rows. However, note that
 if there are failed insertions, the scope of -skipfailures is a whole transaction.
 
-For PostgreSQL, the PG_USE_COPY config option can be set to YES for significantly insertion
-performance boot. See the PG driver documentation page.
+For PostgreSQL, the PG_USE_COPY config option can be set to YES for a significant insertion
+performance boost. See the PG driver documentation page.
 
 More generally, consult the documentation page of the input and output drivers for performance hints.
 
@@ -485,9 +505,9 @@ Example reprojecting from ETRS_1989_LAEA_52N_10E to EPSG:4326 and clipping to a
 % ogr2ogr -wrapdateline -t_srs EPSG:4326 -clipdst -5 40 15 55 france_4326.shp europe_laea.shp
 \endverbatim
 
-Example for using the -fieldmap setting. The first field of the source layer is used to 
-fill the third field (index 2 = third field) of the target layer, the second field of the 
-source layer is ignored, the third field of the source layer used to fill the fifth field 
+Example for using the -fieldmap setting. The first field of the source layer is used to
+fill the third field (index 2 = third field) of the target layer, the second field of the
+source layer is ignored, the third field of the source layer used to fill the fifth field
 of the target layer.
 
 \verbatim
@@ -502,9 +522,14 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 \endif
 */
 
-/*! \page ogrtindex ogrtindex
+/*!
+\if man
+\page ogrtindex
+\else
+\page ogrtindex ogrtindex
+\endif
 
-creates a tileindex
+Creates a tileindex.
 
 \section ogrtindex_synopsis SYNOPSIS
 
@@ -515,6 +540,9 @@ Usage:
 \verbatim
 ogrtindex [-lnum n]... [-lname name]... [-f output_format]
           [-write_absolute_path] [-skip_different_projection]
+          [-t_srs target_srs]
+          [-src_srs_name field_name] [-src_srs_format [AUTO|WKT|EPSG|PROJ]
+          [-accept_different_schemas]
                  output_dataset src_dataset...
 \endverbatim
 
@@ -522,9 +550,9 @@ ogrtindex [-lnum n]... [-lname name]... [-f output_format]
 
 The ogrtindex program can be used to create a tileindex - a file containing
 a list of the identities of a bunch of other files along with there spatial
-extents.  This is primarily intended to be used with  
+extents.  This is primarily intended to be used with
 <a href="http://mapserver.org/">MapServer</a> for tiled access
-to layers using the OGR connection type. 
+to layers using the OGR connection type.
 
 <dl>
 <dt><b>-lnum</b> <em>n</em>:</dt><dd> Add layer number 'n' from each source
@@ -538,9 +566,23 @@ to layers using the OGR connection type.
 <dt><b>-write_absolute_path</b>:</dt><dd> Filenames are written with absolute paths</dd>
 <dt><b>-skip_different_projection</b>:</dt><dd> Only layers with same projection ref
         as layers already inserted in the tileindex will be inserted.</dd>
-<dt><b>-accept_different_schemas</b>:</dt><dd> By default ogrtindex checks that all 
+<dt><b>-t_srs</b> target_srs:</dt><dd> (GDAL >= 2.2)
+<p>Extent of input files will be transformed to the desired target
+coordinate reference system. Using this option generates files that are not
+compatible with MapServer < 7.2. Default creates simple rectangular polygons
+in the same coordinate reference system as the input rasters.</p>
+</dd>
+<dt><b>-src_srs_name</b> field_name:</dt><dd> (GDAL >= 2.2)
+<p>The name of the field to store the SRS of each tile. This field name can be
+used as the value of the TILESRS keyword in MapServer >= 7.2.</p>
+</dd>
+<dt><b>-src_srs_format</b> type:</dt><dd> (GDAL >= 2.2)
+<p>The format in which the SRS of each tile must be written.
+Types can be AUTO, WKT, EPSG, PROJ.</p>
+</dd>
+<dt><b>-accept_different_schemas</b>:</dt><dd> By default ogrtindex checks that all
         layers inserted into the index have the same attribute schemas. If you specify
-        this option, this test will be disabled. Be aware that resulting index may be 
+        this option, this test will be disabled. Be aware that resulting index may be
         incompatible with MapServer!</dd>
 </dl>
 
@@ -549,11 +591,7 @@ all layers in source datasets should be added to the tile index
 as independent records.
 
 If the tile index already exists it will be appended to, otherwise it will
-be created.  
-
-It is a flaw of the current ogrtindex program that no attempt is made to
-copy the coordinate system definition from the source datasets to the tile
-index (as is expected by MapServer when PROJECTION AUTO is in use).   
+be created.
 
 \section ogrtindex_example EXAMPLE
 
@@ -571,12 +609,17 @@ Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
 
 */
 
-/*! \page ogrlineref ogrlineref
+/*!
+\if man
+\page ogrlineref
+\else
+\page ogrlineref ogrlineref
+\endif
 
 The utility can be used for:
 - create linear reference file from input data
 - return the "linear referenced" distance for the projection of the input coordinates (point) on the path
-- return the coordinates (point) on the path according to the "linear referenced" distance 
+- return the coordinates (point) on the path according to the "linear referenced" distance
 - return the portion of the path according to the "linear referenced" begin and end distances
 
 \section ogrlineref_synopsis SYNOPSIS
@@ -601,9 +644,9 @@ ogrlineref [--help-general] [-progress] [-quiet]
 \section ogrlineref_description DESCRIPTION
 
 The ogrlineref program can be used to create a linear reference - a file containing
-a segments of special length (e.g. 1 km in reference units) and get coordinates, 
+a segments of special length (e.g. 1 km in reference units) and get coordinates,
 linear referenced distances or sublines (subpaths) from this file. The utility not
-required the M or Z values in geometry. The results can be stored in any OGR supported 
+required the M or Z values in geometry. The results can be stored in any OGR supported
 format. Also some information is written to the stdout.
 
 <dl>
@@ -612,30 +655,30 @@ format. Also some information is written to the stdout.
 <dt><b>-quiet</b>:</dt><dd> Suppress all messages except errors and results.</dd>
 <dt><b>-f</b> <em>format_name</em>:</dt><dd> Select an output format name.
     The default is to create a shapefile.</dd>
-<dt> <b>-dsco</b> <em>NAME=VALUE</em>:</dt><dd> Dataset creation option 
+<dt> <b>-dsco</b> <em>NAME=VALUE</em>:</dt><dd> Dataset creation option
     (format specific)</dd>
-<dt> <b>-lco</b><em>  NAME=VALUE</em>:</dt><dd> Layer creation option 
+<dt> <b>-lco</b><em>  NAME=VALUE</em>:</dt><dd> Layer creation option
     (format specific)</dd>
 <dt><b>-create</b>:</dt><dd> Create the linear reference file (linestring of parts).</dd>
-<dt> <b>-l</b><em>src_line_datasource_name</em>:</dt><dd> The path to input linestring 
+<dt> <b>-l</b><em>src_line_datasource_name</em>:</dt><dd> The path to input linestring
     datasource (e.g. the road)</dd>
 <dt> <b>-ln</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
-<dt> <b>-lf</b><em>field_name</em>:</dt><dd> The field name of unique values to 
+<dt> <b>-lf</b><em>field_name</em>:</dt><dd> The field name of unique values to
     separate the input lines (e.g. the set of roads)</dd>
-<dt> <b>-p</b><em>src_repers_datasource_name</em>:</dt><dd> The path to linear 
+<dt> <b>-p</b><em>src_repers_datasource_name</em>:</dt><dd> The path to linear
     references points (e.g. the road mile-stones)</dd>
 <dt> <b>-pn</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
-<dt> <b>-pm</b><em>pos_field_name</em>:</dt><dd> The field name of distances 
+<dt> <b>-pm</b><em>pos_field_name</em>:</dt><dd> The field name of distances
     along path (e.g. mile-stones values)</dd>
-<dt> <b>-pf</b><em>field_name</em>:</dt><dd> The field name of unique values to 
+<dt> <b>-pf</b><em>field_name</em>:</dt><dd> The field name of unique values to
     map input reference points to lines</dd>
-<dt> <b>-r</b><em>src_parts_datasource_name</em>:</dt><dd> The path to linear 
+<dt> <b>-r</b><em>src_parts_datasource_name</em>:</dt><dd> The path to linear
     reference file</dd>
 <dt> <b>-rn</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
-<dt> <b>-o</b><em>dst_datasource_name</em>:</dt><dd> The path to output linear 
+<dt> <b>-o</b><em>dst_datasource_name</em>:</dt><dd> The path to output linear
     reference file (linestring datasource)</dd>
 <dt> <b>-on</b><em>layer_name</em>:</dt><dd> The layer name in datasource</dd>
-<dt> <b>-of</b><em>field_name</em>:</dt><dd> The field name for storing the 
+<dt> <b>-of</b><em>field_name</em>:</dt><dd> The field name for storing the
     unique values of input lines</dd>
 <dt> <b>-s</b><em>step</em>:</dt><dd> The part size in linear units</dd>
 <dt> <b>-get_pos</b>:</dt><dd> Return linear referenced position for input X, Y</dd>
@@ -643,7 +686,7 @@ format. Also some information is written to the stdout.
 <dt> <b>-y</b><em>lat</em>:</dt><dd> Input Y coordinate</dd>
 <dt> <b>-get_coord</b>:</dt><dd> Return point on path for input linear distance</dd>
 <dt> <b>-m</b><em>position</em>:</dt><dd> The input linear distance</dd>
-<dt> <b>-get_subline</b>:</dt><dd> Return the portion of the input path from and to 
+<dt> <b>-get_subline</b>:</dt><dd> Return the portion of the input path from and to
     input linear positions</dd>
 <dt> <b>-mb</b><em>position</em>:</dt><dd> The input begin linear distance</dd>
 <dt> <b>-me</b><em>position</em>:</dt><dd> The input end linear distance</dd>
diff --git a/apps/ogrdissolve.cpp b/apps/ogrdissolve.cpp
index 430316e..d5699f5 100644
--- a/apps/ogrdissolve.cpp
+++ b/apps/ogrdissolve.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdissolve.cpp 11636 2007-06-10 06:02:56Z mloskot $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Allow a user to dissolve geometries based on an attribute.
@@ -34,7 +33,7 @@
 #include "ogr_api.h"
 #include <map>
 #include <list>
-CPL_CVSID("$Id: ogr2ogr.cpp 11636 2007-06-10 06:02:56Z mloskot $");
+CPL_CVSID("$Id: ogrdissolve.cpp 35931 2016-10-25 16:20:52Z goatbar $");
 
 static void Usage();
 
@@ -513,7 +512,6 @@ static void Usage()
     exit( 1 );
 }
 
-
 StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
                                         const char** papszFields) {
 
@@ -559,7 +557,6 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
         } else {
             CPLDebug("CollectGeometries", "Geometry was invalid not adding!!!!");
         }
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -604,7 +601,6 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
               CPLString fid = ipos->first;
               CPLDebug ("CollectGeometries", "First %s Second %d", ipos->first.c_str(), ipos->second);
 
-
              OGRGeometryCollection* geom = new OGRGeometryCollection;
 
              for (pos = poGeometriesMap.lower_bound(fid);
@@ -634,7 +630,6 @@ StringGeometryMap* CollectGeometries(   OGRLayer* poSrcLayer,
                             collections_i->second->getNumGeometries());
                 OGRGeometry* buffer = collections_i->second->Buffer(0);
                 buffers->insert(std::make_pair(collections_i->first, buffer));
-
     }
 
     for (collections_i = poCollections.begin();
@@ -678,22 +673,26 @@ GeometriesList* FlattenGeometries(GeometriesList* input) {
                             "Collapsing wkbMultiPolygon geometries......"
                             );
                 }
-                if (iGType == wkbGeometryCollection) {
-                        OGRGeometryCollection* geom = (OGRGeometryCollection*)buffer;
-                        GeometriesList* collection = new GeometriesList;
-                            GeometriesList::const_iterator g_i;
-                        for (int i=0; i< geom->getNumGeometries(); i++) {
-                            OGRGeometry* g = (OGRGeometry*)geom->getGeometryRef(i);
-                            collection->push_back(g);
-                        }
-                            GeometriesList* collapsed = FlattenGeometries(collection);
-                            for (g_i=collapsed->begin(); g_i!=collapsed->end(); g_i++){
-                               output->push_back((OGRGeometry*)(*g_i));
-                CPLDebug(   "CollectGeometries",
-                            "Collapsing wkbGeometryCollection geometries......"
-                            );
-
-                            }
+                if (iGType == wkbGeometryCollection)
+                {
+                    OGRGeometryCollection* geom = (OGRGeometryCollection*)buffer;
+                    GeometriesList* collection = new GeometriesList;
+                    GeometriesList::const_iterator g_i;
+                    for (int i=0; i< geom->getNumGeometries(); i++)
+                    {
+                        OGRGeometry* g = (OGRGeometry*)geom->getGeometryRef(i);
+                        collection->push_back(g);
+                    }
+                    GeometriesList* collapsed = FlattenGeometries(collection);
+                    for( g_i = collapsed->begin();
+                         g_i != collapsed->end();
+                         g_i++ )
+                    {
+                        output->push_back((OGRGeometry*)(*g_i));
+                        CPLDebug(
+                            "CollectGeometries",
+                            "Collapsing wkbGeometryCollection geometries." );
+                    }
                 }
                 // CPLDebug(   "CollectGeometries",
                 //             "Buffered Geometry size %d",
diff --git a/apps/ogrinfo.cpp b/apps/ogrinfo.cpp
index 76666ce..f592093 100644
--- a/apps/ogrinfo.cpp
+++ b/apps/ogrinfo.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrinfo.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for viewing OGR driver data.
@@ -36,7 +35,9 @@
 #include "cpl_multiproc.h"
 #include "commonutils.h"
 
-CPL_CVSID("$Id: ogrinfo.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+#include <set>
+
+CPL_CVSID("$Id: ogrinfo.cpp 36537 2016-11-27 23:51:56Z goatbar $");
 
 int     bReadOnly = FALSE;
 int     bVerbose = TRUE;
@@ -78,7 +79,8 @@ static void RemoveBOM(GByte* pabyData)
 
 #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
     do { if (iArg + nExtraArg >= nArgc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
+        Usage(CPLSPrintf("%s option requires %d argument(s)", \
+                         papszArgv[iArg], nExtraArg)); } while( false )
 
 int main( int nArgc, char ** papszArgv )
 
@@ -97,6 +99,7 @@ int main( int nArgc, char ** papszArgv )
     int                 bListMDD = FALSE;
     int                  bShowMetadata = TRUE;
     int         bFeatureCount = TRUE, bExtent = TRUE;
+    bool        bDatasetGetNextFeature = false;
 
     /* Check strict compilation and runtime library version as we use C++ API */
     if (! GDAL_CHECK_VERSION(papszArgv[0]))
@@ -254,6 +257,8 @@ int main( int nArgc, char ** papszArgv )
             bFeatureCount = FALSE;
         else if( EQUAL(papszArgv[iArg], "-noextent") )
             bExtent = FALSE;
+        else if( EQUAL(papszArgv[iArg],"-rl"))
+            bDatasetGetNextFeature = true;
         else if( papszArgv[iArg][0] == '-' )
         {
             Usage(CPLSPrintf("Unknown option name '%s'", papszArgv[iArg]));
@@ -273,6 +278,11 @@ int main( int nArgc, char ** papszArgv )
     if( pszDialect != NULL && pszWHERE != NULL && pszSQLStatement == NULL )
         printf("Warning: -dialect is ignored with -where. Use -sql instead");
 
+    if( bDatasetGetNextFeature && pszSQLStatement )
+    {
+        Usage("-rl is incompatible with -sql");
+    }
+
 #ifdef __AFL_HAVE_MANUAL_CONTROL
     while (__AFL_LOOP(1000)) {
 #endif
@@ -342,10 +352,88 @@ int main( int nArgc, char ** papszArgv )
                             bShowMetadata,
                             papszExtraMDDomains );
 
+    if( bDatasetGetNextFeature )
+    {
+        nRepeatCount = 0;  // skip layer reporting.
+
+/* -------------------------------------------------------------------- */
+/*      Set filters if provided.                                        */
+/* -------------------------------------------------------------------- */
+        if( pszWHERE != NULL || poSpatialFilter != NULL )
+        {
+            for( int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
+            {
+                OGRLayer        *poLayer = poDS->GetLayer(iLayer);
+
+                if( poLayer == NULL )
+                {
+                    printf( "FAILURE: Couldn't fetch advertised layer %d!\n",
+                            iLayer );
+                    exit( 1 );
+                }
+
+                if( pszWHERE != NULL )
+                {
+                    if (poLayer->SetAttributeFilter( pszWHERE ) != OGRERR_NONE )
+                    {
+                        printf( "WARNING: SetAttributeFilter(%s) failed on layer %s.\n",
+                                pszWHERE, poLayer->GetName() );
+                    }
+                }
+
+                if( poSpatialFilter != NULL )
+                {
+                    if( pszGeomField != NULL )
+                    {
+                        OGRFeatureDefn      *poDefn = poLayer->GetLayerDefn();
+                        int iGeomField = poDefn->GetGeomFieldIndex(pszGeomField);
+                        if( iGeomField >= 0 )
+                            poLayer->SetSpatialFilter( iGeomField, poSpatialFilter );
+                        else
+                            printf("WARNING: Cannot find geometry field %s.\n",
+                                pszGeomField);
+                    }
+                    else
+                        poLayer->SetSpatialFilter( poSpatialFilter );
+                }
+            }
+        }
+
+        std::set<OGRLayer*> oSetLayers;
+        while( true )
+        {
+            OGRLayer* poLayer = NULL;
+            OGRFeature* poFeature = poDS->GetNextFeature( &poLayer, NULL,
+                                                          NULL, NULL );
+            if( poFeature == NULL )
+                break;
+            if( papszLayers == NULL || poLayer == NULL ||
+                CSLFindString(papszLayers, poLayer->GetName()) >= 0 )
+            {
+                if( bVerbose && poLayer != NULL &&
+                    oSetLayers.find(poLayer) == oSetLayers.end() )
+                {
+                    oSetLayers.insert(poLayer);
+                    int bSummaryOnlyBackup = bSummaryOnly;
+                    bSummaryOnly = TRUE;
+                    ReportOnLayer( poLayer, NULL, NULL, NULL,
+                                   bListMDD, bShowMetadata,
+                                   papszExtraMDDomains,
+                                   bFeatureCount,
+                                   bExtent );
+                    bSummaryOnly = bSummaryOnlyBackup;
+                }
+                if( !bSuperQuiet && !bSummaryOnly )
+                    poFeature->DumpReadable( NULL, papszOptions );
+            }
+            OGRFeature::DestroyFeature( poFeature );
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Special case for -sql clause.  No source layers required.       */
 /* -------------------------------------------------------------------- */
-    if( pszSQLStatement != NULL )
+    else if( pszSQLStatement != NULL )
     {
         nRepeatCount = 0;  // skip layer reporting.
 
@@ -507,7 +595,7 @@ static void Usage(const char* pszErrorMsg)
 {
     printf( "Usage: ogrinfo [--help-general] [-ro] [-q] [-where restricted_where|@filename]\n"
             "               [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]\n"
-            "               [-sql statement|@filename] [-dialect sql_dialect] [-al] [-so] [-fields={YES/NO}]\n"
+            "               [-sql statement|@filename] [-dialect sql_dialect] [-al] [-rl] [-so] [-fields={YES/NO}]\n"
             "               [-geom={YES/NO/SUMMARY}] [-formats] [[-oo NAME=VALUE] ...]\n"
             "               [-nomd] [-listmdd] [-mdd domain|`all`]*\n"
             "               [-nocount] [-noextent]\n"
@@ -828,5 +916,4 @@ static void GDALInfoReportMetadata( GDALMajorObjectH hObject,
 
         CSLDestroy(papszExtraMDDomainsExpanded);
     }
-
 }
diff --git a/apps/ogrlineref.cpp b/apps/ogrlineref.cpp
index b623bc0..22c17b0 100644
--- a/apps/ogrlineref.cpp
+++ b/apps/ogrlineref.cpp
@@ -40,6 +40,8 @@
 #include "cpl_error.h"
 #include "ogr_geos.h"
 
+CPL_CVSID("$Id: ogrlineref.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 #define FIELD_START "beg"
 #define FIELD_FINISH "end"
 #define FIELD_SCALE_FACTOR "scale"
@@ -77,7 +79,6 @@ static void Usage(const char* pszAdditionalMsg, int bShort)
 {
     OGRSFDriverRegistrar        *poR = OGRSFDriverRegistrar::GetRegistrar();
 
-
     printf("Usage: ogrlineref [--help-general] [-progress] [-quiet]\n"
         "               [-f format_name] [[-dsco NAME=VALUE] ...] [[-lco NAME=VALUE]...]\n"
         "               [-create]\n"
@@ -207,7 +208,7 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
         {
             fprintf(stderr,
                 "Layer %s not found, and CreateLayer not supported by driver.\n",
-                pszNewLayerName);
+                szLayerName.c_str());
             return NULL;
         }
 
@@ -220,7 +221,7 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
             eGType = wkbNone;
         }
 
-        poDstLayer = poDstDS->CreateLayer(pszNewLayerName, poOutputSRS,
+        poDstLayer = poDstDS->CreateLayer(szLayerName, poOutputSRS,
             (OGRwkbGeometryType)eGType,
             papszLCO);
 
@@ -243,7 +244,7 @@ static OGRLayer* SetupTargetLayer(OGRLayer * poSrcLayer, GDALDataset *poDstDS, c
     else
     {
         fprintf(stderr, "FAILED: Layer %s already exists.\n",
-            pszNewLayerName);
+            szLayerName.c_str ());
         return NULL;
     }
 
@@ -320,7 +321,7 @@ void CheckDestDataSourceNameConsistency(const char* pszDestFilename,
                                                { "bna"    , "BNA" },
                                                { "csv"    , "CSV" },
                                                { "gml"    , "GML" },
-                                               { "kml"    , "KML/LIBKML" },
+                                               { "kml"    , "KML" },
                                                { "kmz"    , "LIBKML" },
                                                { "json"   , "GeoJSON" },
                                                { "geojson", "GeoJSON" },
@@ -471,7 +472,7 @@ static OGRErr CreateSubline(OGRLayer* const poPkLayer,
 
     OGRLineString SubLine;
 
-    if (moParts.size() == 0)
+    if (moParts.empty())
     {
         fprintf(stderr, "Get parts for positions %f - %f failed\n", dfPosBeg, dfPosEnd);
         return OGRERR_FAILURE;
@@ -937,7 +938,6 @@ static OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* cons
         delete oIter->second;
     }
 
-
     if (!bQuiet)
     {
         fprintf(stdout, "\nSuccess!\n\n");
@@ -948,7 +948,6 @@ static OGRErr CreatePartsFromLineString(OGRLineString* pPathGeom, OGRLayer* cons
         GDALDestroyScaledProgress(pProgressArg);
     }
 
-
     return OGRERR_NONE;
 }
 #endif
@@ -1187,7 +1186,8 @@ static OGRErr GetCoordinates(OGRLayer* const poPkLayer,
 
 #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
     do { if (iArg + nExtraArg >= nArgc) \
-        Usage(CPLSPrintf("%s option requires %d argument(s)", papszArgv[iArg], nExtraArg)); } while(0)
+        Usage(CPLSPrintf("%s option requires %d argument(s)", \
+                         papszArgv[iArg], nExtraArg)); } while( false )
 
 int main( int nArgc, char ** papszArgv )
 
@@ -1440,7 +1440,6 @@ int main( int nArgc, char ** papszArgv )
         }
     }
 
-
     if(stOper == op_create)
     {
 #ifdef HAVE_GEOS_PROJECT
diff --git a/apps/ogrtindex.cpp b/apps/ogrtindex.cpp
index 6b3ebfe..bfe81de 100644
--- a/apps/ogrtindex.cpp
+++ b/apps/ogrtindex.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrtindex.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Program to generate a UMN MapServer compatible tile index for a
@@ -29,36 +28,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogrsf_frmts.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_api.h"
+#include "ogrsf_frmts.h"
 
 #include <cassert>
 
-CPL_CVSID("$Id: ogrtindex.cpp 33615 2016-03-02 20:19:22Z goatbar $");
+CPL_CVSID("$Id: ogrtindex.cpp 37862 2017-03-30 12:17:31Z rouault $");
 
 static void Usage();
 
+typedef enum
+{
+    FORMAT_AUTO,
+    FORMAT_WKT,
+    FORMAT_EPSG,
+    FORMAT_PROJ
+} SrcSRSFormat;
+
 /************************************************************************/
 /*                                main()                                */
 /************************************************************************/
 
-int main( int nArgc, char ** papszArgv )
+int main( int nArgc, char **papszArgv )
 
 {
-    int   nFirstSourceDataset = -1, bLayersWildcarded = TRUE, iArg;
-    const char *pszFormat = "ESRI Shapefile";
-    const char *pszTileIndexField = "LOCATION";
-    const char *pszOutputName = NULL;
-    int write_absolute_path = FALSE;
-    int skip_different_projection = FALSE;
-    char* current_path = NULL;
-    int accept_different_schemas = FALSE;
-    int bFirstWarningForNonMatchingAttributes = TRUE;
-
-    /* Check strict compilation and runtime library version as we use C++ API */
-    if (! GDAL_CHECK_VERSION(papszArgv[0]))
+    // Check strict compilation and runtime library version as we use C++ API.
+    if( !GDAL_CHECK_VERSION(papszArgv[0]) )
         exit(1);
 /* -------------------------------------------------------------------- */
 /*      Register format(s).                                             */
@@ -68,29 +65,51 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Processing command line arguments.                              */
 /* -------------------------------------------------------------------- */
-    for( iArg = 1; iArg < nArgc; iArg++ )
+    int nFirstSourceDataset = -1;
+    bool bLayersWildcarded = true;
+    const char *pszFormat = "ESRI Shapefile";
+    const char *pszTileIndexField = "LOCATION";
+    const char *pszOutputName = NULL;
+    bool write_absolute_path = false;
+    bool skip_different_projection = false;
+    char* current_path = NULL;
+    bool accept_different_schemas = false;
+    bool bFirstWarningForNonMatchingAttributes = true;
+    const char *pszTargetSRS = "";
+    bool bSetTargetSRS = false;
+    const char* pszSrcSRSName = NULL;
+    int i_SrcSRSName = -1;
+    bool bSrcSRSFormatSpecified = false;
+    SrcSRSFormat eSrcSRSFormat = FORMAT_AUTO;
+    size_t nMaxFieldSize = 254;
+
+    for( int iArg = 1; iArg < nArgc; iArg++ )
     {
         if( EQUAL(papszArgv[iArg], "--utility_version") )
         {
-            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
-                   papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            printf("%s was compiled against GDAL %s and "
+                   "is running against GDAL %s\n",
+                   papszArgv[0], GDAL_RELEASE_NAME,
+                   GDALVersionInfo("RELEASE_NAME"));
             return 0;
         }
         else if( EQUAL(papszArgv[iArg],"-f") && iArg < nArgc-1 )
         {
             pszFormat = papszArgv[++iArg];
+            if( !EQUAL(pszFormat, "ESRI Shapefile") )
+                nMaxFieldSize = 0;
         }
         else if( EQUAL(papszArgv[iArg],"-write_absolute_path"))
         {
-            write_absolute_path = TRUE;
+            write_absolute_path = true;
         }
         else if( EQUAL(papszArgv[iArg],"-skip_different_projection"))
         {
-            skip_different_projection = TRUE;
+            skip_different_projection = true;
         }
         else if( EQUAL(papszArgv[iArg],"-accept_different_schemas"))
         {
-            accept_different_schemas = TRUE;
+            accept_different_schemas = true;
         }
         else if( EQUAL(papszArgv[iArg],"-tileindex") && iArg < nArgc-1 )
         {
@@ -100,7 +119,30 @@ int main( int nArgc, char ** papszArgv )
                  || EQUAL(papszArgv[iArg],"-lname") )
         {
             iArg++;
-            bLayersWildcarded = FALSE;
+            bLayersWildcarded = false;
+        }
+        else if( strcmp(papszArgv[iArg],"-t_srs") == 0 && iArg < nArgc-1 )
+        {
+            pszTargetSRS = papszArgv[++iArg];
+            bSetTargetSRS = true;
+        }
+        else if( strcmp(papszArgv[iArg], "-src_srs_name") == 0 && iArg < nArgc-1 )
+        {
+            pszSrcSRSName = papszArgv[++iArg];
+        }
+        else if( strcmp(papszArgv[iArg], "-src_srs_format") == 0 && iArg < nArgc-1 )
+        {
+            const char* pszSRSFormat;
+            bSrcSRSFormatSpecified = true;
+            pszSRSFormat = papszArgv[++iArg];
+            if( EQUAL(pszSRSFormat, "AUTO") )
+                eSrcSRSFormat = FORMAT_AUTO;
+            else if( EQUAL(pszSRSFormat, "WKT") )
+                eSrcSRSFormat = FORMAT_WKT;
+            else if( EQUAL(pszSRSFormat, "EPSG") )
+                eSrcSRSFormat = FORMAT_EPSG;
+            else if( EQUAL(pszSRSFormat, "PROJ") )
+                eSrcSRSFormat = FORMAT_PROJ;
         }
         else if( papszArgv[iArg][0] == '-' )
             Usage();
@@ -113,24 +155,53 @@ int main( int nArgc, char ** papszArgv )
     if( pszOutputName == NULL || nFirstSourceDataset == -1 )
         Usage();
 
+    if( bSrcSRSFormatSpecified && pszSrcSRSName == NULL )
+    {
+        fprintf( stderr,"-src_srs_name must be specified when -src_srs_format is "
+                "specified.\n" );
+        Usage();
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create and validate target SRS if given.                        */
+/* -------------------------------------------------------------------- */
+    OGRSpatialReference* poTargetSRS = NULL;
+    if( bSetTargetSRS )
+    {
+        if( skip_different_projection )
+        {
+            fprintf( stderr,
+                     "Warning : -skip_different_projection does not apply "
+                     "when -t_srs is requested.\n" );
+        }
+        poTargetSRS = new OGRSpatialReference();
+        // coverity[tainted_data]
+        if( poTargetSRS->SetFromUserInput( pszTargetSRS ) != CE_None )
+        {
+            delete poTargetSRS;
+            fprintf( stderr, "Invalid target SRS `%s'.\n",
+                     pszTargetSRS );
+            exit(1);
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Try to open as an existing dataset for update access.           */
 /* -------------------------------------------------------------------- */
-    GDALDataset *poDstDS;
     OGRLayer *poDstLayer = NULL;
 
-    poDstDS = (GDALDataset*) OGROpen( pszOutputName, TRUE, NULL );
+    GDALDataset *poDstDS = reinterpret_cast<GDALDataset*>(
+        OGROpen( pszOutputName, TRUE, NULL ) );
 
 /* -------------------------------------------------------------------- */
 /*      If that failed, find the driver so we can create the tile index.*/
 /* -------------------------------------------------------------------- */
     if( poDstDS == NULL )
     {
-        OGRSFDriverRegistrar     *poR = OGRSFDriverRegistrar::GetRegistrar();
-        GDALDriver              *poDriver = NULL;
-        int                      iDriver;
+        OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+        GDALDriver *poDriver = NULL;
 
-        for( iDriver = 0;
+        for( int iDriver = 0;
              iDriver < poR->GetDriverCount() && poDriver == NULL;
              iDriver++ )
         {
@@ -145,17 +216,20 @@ int main( int nArgc, char ** papszArgv )
             fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
             fprintf( stderr, "The following drivers are available:\n" );
 
-            for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+            for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
             {
-                fprintf( stderr, "  -> `%s'\n", poR->GetDriver(iDriver)->GetDescription() );
+                fprintf( stderr, "  -> `%s'\n",
+                         poR->GetDriver(iDriver)->GetDescription() );
             }
             exit( 1 );
         }
 
-        if( !CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(), GDAL_DCAP_CREATE, "FALSE") ) )
+        if( !CPLTestBool( CSLFetchNameValueDef(poDriver->GetMetadata(),
+                                               GDAL_DCAP_CREATE, "FALSE") ) )
         {
-            fprintf( stderr, "%s driver does not support data source creation.\n",
-                    pszFormat );
+            fprintf( stderr,
+                     "%s driver does not support data source creation.\n",
+                     pszFormat );
             exit( 1 );
         }
 
@@ -173,45 +247,48 @@ int main( int nArgc, char ** papszArgv )
 
         if( poDstDS->GetLayerCount() == 0 )
         {
-            OGRFieldDefn oLocation( pszTileIndexField, OFTString );
-
-            oLocation.SetWidth( 200 );
-
-            if( nFirstSourceDataset < nArgc && papszArgv[nFirstSourceDataset][0] == '-' )
+            if( nFirstSourceDataset < nArgc &&
+                papszArgv[nFirstSourceDataset][0] == '-' )
             {
                 nFirstSourceDataset++;
             }
 
             OGRSpatialReference* poSrcSpatialRef = NULL;
-
-            /* Fetches the SRS of the first layer and use it when creating the tileindex layer */
-            if (nFirstSourceDataset < nArgc)
+            if( bSetTargetSRS )
+            {
+            // Fetches the SRS from target SRS (if set), or from the SRS of
+            // the first layer and use it when creating the
+            // tileindex layer.
+                poSrcSpatialRef = poTargetSRS->Clone();
+            }
+            else if( nFirstSourceDataset < nArgc )
             {
-                GDALDataset* poDS = (GDALDataset*) OGROpen(papszArgv[nFirstSourceDataset], FALSE, NULL);
-                if (poDS)
+                GDALDataset* poDS = reinterpret_cast<GDALDataset*>(
+                    OGROpen(papszArgv[nFirstSourceDataset], FALSE, NULL));
+                if( poDS != NULL )
                 {
-                    int iLayer;
-
-                    for( iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
+                    for( int iLayer = 0;
+                         iLayer < poDS->GetLayerCount();
+                         iLayer++ )
                     {
-                        int bRequested = bLayersWildcarded;
+                        bool bRequested = bLayersWildcarded;
                         OGRLayer *poLayer = poDS->GetLayer(iLayer);
 
-                        for( iArg = 1; iArg < nArgc && !bRequested; iArg++ )
+                        for( int iArg = 1; iArg < nArgc && !bRequested; iArg++ )
                         {
                             if( EQUAL(papszArgv[iArg],"-lnum")
                                 && atoi(papszArgv[iArg+1]) == iLayer )
-                                bRequested = TRUE;
-                            else if( EQUAL(papszArgv[iArg],"-lname")
-                                     && EQUAL(papszArgv[iArg+1],
-                                              poLayer->GetLayerDefn()->GetName()) )
-                                bRequested = TRUE;
+                                bRequested = true;
+                            else if( EQUAL(papszArgv[iArg],"-lname") &&
+                                     EQUAL(papszArgv[iArg+1],
+                                           poLayer->GetLayerDefn()->GetName()) )
+                                bRequested = true;
                         }
 
                         if( !bRequested )
                             continue;
 
-                        if ( poLayer->GetSpatialRef() )
+                        if( poLayer->GetSpatialRef() )
                             poSrcSpatialRef = poLayer->GetSpatialRef()->Clone();
                         break;
                     }
@@ -221,7 +298,16 @@ int main( int nArgc, char ** papszArgv )
             }
 
             poDstLayer = poDstDS->CreateLayer( "tileindex", poSrcSpatialRef );
-            poDstLayer->CreateField( &oLocation, OFTString );
+
+            OGRFieldDefn oLocation( pszTileIndexField, OFTString );
+            oLocation.SetWidth( 200 );
+            poDstLayer->CreateField( &oLocation );
+
+            if( pszSrcSRSName != NULL )
+            {
+                OGRFieldDefn oSrcSRSNameField( pszSrcSRSName, OFTString );
+                poDstLayer->CreateField( &oSrcSRSNameField );
+            }
 
             OGRSpatialReference::DestroySpatialReference( poSrcSpatialRef );
         }
@@ -230,7 +316,6 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Identify target layer and field.                                */
 /* -------------------------------------------------------------------- */
-    int   iTileIndexField;
 
     poDstLayer = poDstDS->GetLayer(0);
     if( poDstLayer == NULL )
@@ -239,7 +324,7 @@ int main( int nArgc, char ** papszArgv )
         exit( 1 );
     }
 
-    iTileIndexField =
+    int iTileIndexField =
         poDstLayer->GetLayerDefn()->GetFieldIndex( pszTileIndexField );
     if( iTileIndexField == -1 )
     {
@@ -248,101 +333,107 @@ int main( int nArgc, char ** papszArgv )
         exit( 1 );
     }
 
+    if( pszSrcSRSName != NULL )
+        i_SrcSRSName = poDstLayer->GetLayerDefn()->GetFieldIndex( pszSrcSRSName );
+
     OGRFeatureDefn* poFeatureDefn = NULL;
 
-    /* Load in memory existing file names in SHP */
-    int nExistingLayers = 0;
-    char** existingLayersTab = NULL;
+    // Load in memory existing file names in SHP.
+    char **existingLayersTab = NULL;
     OGRSpatialReference* alreadyExistingSpatialRef = NULL;
-    int alreadyExistingSpatialRefValid = FALSE;
-    nExistingLayers = (int)poDstLayer->GetFeatureCount();
-    if (nExistingLayers)
+    bool alreadyExistingSpatialRefValid = false;
+    const int nExistingLayers = static_cast<int>(poDstLayer->GetFeatureCount());
+    if( nExistingLayers )
     {
-        int i;
-        existingLayersTab = (char**)CPLMalloc(nExistingLayers * sizeof(char*));
-        for(i=0;i<nExistingLayers;i++)
+        existingLayersTab = static_cast<char **>(
+            CPLMalloc(nExistingLayers * sizeof(char*)));
+        for( int i = 0; i < nExistingLayers; i++ )
         {
             OGRFeature* feature = poDstLayer->GetNextFeature();
-            existingLayersTab[i] = CPLStrdup(feature->GetFieldAsString( iTileIndexField));
-            if (i == 0)
+            existingLayersTab[i] =
+                CPLStrdup(feature->GetFieldAsString( iTileIndexField));
+            if( i == 0 )
             {
-                GDALDataset       *poDS;
                 char* filename = CPLStrdup(existingLayersTab[i]);
-                int j;
-                for(j=static_cast<int>(strlen(filename))-1;j>=0;j--)
+                // j used after for.
+                int j = static_cast<int>(strlen(filename)) - 1;
+                for( ; j >= 0; j-- )
                 {
-                    if (filename[j] == ',')
+                    if( filename[j] == ',' )
                         break;
                 }
-                if (j >= 0)
+                GDALDataset *poDS = NULL;
+                if( j >= 0 )
                 {
-                    int iLayer = atoi(filename + j + 1);
+                    const int iLayer = atoi(filename + j + 1);
                     filename[j] = 0;
-                    poDS = (GDALDataset*) OGROpen(filename, FALSE, NULL);
-                    if (poDS)
+                    poDS = reinterpret_cast<GDALDataset *>(
+                        OGROpen(filename, FALSE, NULL));
+                    if( poDS != NULL )
                     {
                         OGRLayer *poLayer = poDS->GetLayer(iLayer);
-                        if (poLayer)
+                        if( poLayer )
                         {
-                            alreadyExistingSpatialRefValid = TRUE;
+                            alreadyExistingSpatialRefValid = true;
                             alreadyExistingSpatialRef =
-                                    (poLayer->GetSpatialRef()) ? poLayer->GetSpatialRef()->Clone() : NULL;
+                                poLayer->GetSpatialRef() ?
+                                poLayer->GetSpatialRef()->Clone() : NULL;
 
-                            if (poFeatureDefn == NULL)
+                            if( poFeatureDefn == NULL )
                                 poFeatureDefn = poLayer->GetLayerDefn()->Clone();
                         }
-                        GDALClose( (GDALDatasetH)poDS );
+                        GDALClose( poDS );
                     }
                 }
             }
         }
     }
 
-
-    if (write_absolute_path)
+    if( write_absolute_path )
     {
         current_path = CPLGetCurrentDir();
-        if (current_path == NULL)
+        if( current_path == NULL )
         {
-            fprintf( stderr, "This system does not support the CPLGetCurrentDir call. "
-                             "The option -write_absolute_path will have no effect\n");
-            write_absolute_path = FALSE;
+            fprintf( stderr,
+                     "This system does not support the CPLGetCurrentDir call. "
+                     "The option -write_absolute_path will have no effect\n" );
+            write_absolute_path = false;
         }
     }
 /* ==================================================================== */
 /*      Process each input datasource in turn.                          */
 /* ==================================================================== */
-
-	for(; nFirstSourceDataset < nArgc; nFirstSourceDataset++ )
+    for( ; nFirstSourceDataset < nArgc; nFirstSourceDataset++ )
     {
-        int i;
-        GDALDataset       *poDS;
-
         if( papszArgv[nFirstSourceDataset][0] == '-' )
         {
             nFirstSourceDataset++;
             continue;
         }
 
-        char* fileNameToWrite;
+        char* fileNameToWrite = NULL;
         VSIStatBuf sStatBuf;
 
-        if (write_absolute_path && CPLIsFilenameRelative( papszArgv[nFirstSourceDataset] ) &&
-            VSIStat( papszArgv[nFirstSourceDataset], &sStatBuf ) == 0)
+        if( write_absolute_path &&
+            CPLIsFilenameRelative( papszArgv[nFirstSourceDataset] ) &&
+            VSIStat( papszArgv[nFirstSourceDataset], &sStatBuf ) == 0 )
         {
-            fileNameToWrite = CPLStrdup(CPLProjectRelativeFilename(current_path,papszArgv[nFirstSourceDataset]));
+            fileNameToWrite =
+                CPLStrdup(CPLProjectRelativeFilename(
+                    current_path, papszArgv[nFirstSourceDataset]));
         }
         else
         {
             fileNameToWrite = CPLStrdup(papszArgv[nFirstSourceDataset]);
         }
 
-        poDS = (GDALDataset*) OGROpen( papszArgv[nFirstSourceDataset], FALSE, NULL );
+        GDALDataset *poDS = reinterpret_cast<GDALDataset*>(
+            OGROpen( papszArgv[nFirstSourceDataset], FALSE, NULL ) );
 
         if( poDS == NULL )
         {
             fprintf( stderr, "Failed to open dataset %s, skipping.\n",
-                    papszArgv[nFirstSourceDataset] );
+                     papszArgv[nFirstSourceDataset] );
             CPLFree(fileNameToWrite);
             continue;
         }
@@ -350,167 +441,285 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Check all layers, and see if they match requests.               */
 /* -------------------------------------------------------------------- */
-        int iLayer;
-
-        for( iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
+        for( int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
         {
-            int bRequested = bLayersWildcarded;
+            bool bRequested = bLayersWildcarded;
             OGRLayer *poLayer = poDS->GetLayer(iLayer);
 
-            for( iArg = 1; iArg < nArgc && !bRequested; iArg++ )
+            for( int iArg = 1; iArg < nArgc && !bRequested; iArg++ )
             {
                 if( EQUAL(papszArgv[iArg],"-lnum")
                     && atoi(papszArgv[iArg+1]) == iLayer )
-                    bRequested = TRUE;
-                else if( EQUAL(papszArgv[iArg],"-lname")
+                    bRequested = true;
+                else if( EQUAL(papszArgv[iArg], "-lname" )
                          && EQUAL(papszArgv[iArg+1],
                                   poLayer->GetLayerDefn()->GetName()) )
-                    bRequested = TRUE;
+                    bRequested = true;
             }
 
             if( !bRequested )
                 continue;
 
-            /* Checks that the layer is not already in tileindex */
-            for(i=0;i<nExistingLayers;i++)
+            // Checks that the layer is not already in tileindex.
+            int i = 0;  // Used after for.
+            for( ; i < nExistingLayers; i++ )
             {
-                char        szLocation[5000];
+                char szLocation[5000] = {};
                 snprintf( szLocation, sizeof(szLocation), "%s,%d",
-                        fileNameToWrite, iLayer );
-                if (EQUAL(szLocation, existingLayersTab[i]))
+                          fileNameToWrite, iLayer );
+                if( EQUAL(szLocation, existingLayersTab[i]) )
                 {
-                    fprintf(stderr, "Layer %d of %s is already in tileindex. Skipping it.\n",
+                    fprintf(stderr, "Layer %d of %s is already in tileindex. "
+                            "Skipping it.\n",
                             iLayer, papszArgv[nFirstSourceDataset]);
                     break;
                 }
             }
-            if (i != nExistingLayers)
+            if( i != nExistingLayers )
             {
                 continue;
             }
 
             OGRSpatialReference* spatialRef = poLayer->GetSpatialRef();
-            if (alreadyExistingSpatialRefValid)
+            // If not set target srs, test that the current file uses same
+            // projection as others.
+            if( !bSetTargetSRS )
             {
-                if ((spatialRef != NULL && alreadyExistingSpatialRef != NULL &&
-                     spatialRef->IsSame(alreadyExistingSpatialRef) == FALSE) ||
-                    ((spatialRef != NULL) != (alreadyExistingSpatialRef != NULL)))
+                if( alreadyExistingSpatialRefValid )
                 {
-                    fprintf(stderr, "Warning : layer %d of %s is not using the same projection system as "
-                                "other files in the tileindex. This may cause problems when "
-                                "using it in MapServer for example.%s\n", iLayer, papszArgv[nFirstSourceDataset],
-                                (skip_different_projection) ? " Skipping it" : "");
-                    if (skip_different_projection)
+                    if( (spatialRef != NULL && alreadyExistingSpatialRef != NULL &&
+                        spatialRef->IsSame(alreadyExistingSpatialRef) == FALSE) ||
+                        ((spatialRef != NULL) !=
+                        (alreadyExistingSpatialRef != NULL)) )
                     {
-                        continue;
+                        fprintf(
+                            stderr,
+                            "Warning : layer %d of %s is not using the same "
+                            "projection system as other files in the tileindex. "
+                            "This may cause problems when using it in MapServer "
+                            "for example.%s\n",
+                            iLayer, papszArgv[nFirstSourceDataset],
+                            skip_different_projection ? " Skipping it" : "");
+                        if( skip_different_projection )
+                        {
+                            continue;
+                        }
                     }
                 }
-            }
-            else
-            {
-                alreadyExistingSpatialRefValid = TRUE;
-                alreadyExistingSpatialRef = (spatialRef) ? spatialRef->Clone() : NULL;
+                else
+                {
+                    alreadyExistingSpatialRefValid = true;
+                    alreadyExistingSpatialRef =
+                        spatialRef ? spatialRef->Clone() : NULL;
+                }
             }
 
 /* -------------------------------------------------------------------- */
-/*		Check if all layers in dataset have the same attributes	schema. */
+/*      Check if all layers in dataset have the same attributes schema. */
 /* -------------------------------------------------------------------- */
-			if( poFeatureDefn == NULL )
-			{
-				poFeatureDefn = poLayer->GetLayerDefn()->Clone();
-			}
-			else if ( !accept_different_schemas )
-			{
-				OGRFeatureDefn* poFeatureDefnCur = poLayer->GetLayerDefn();
-				assert(NULL != poFeatureDefnCur);
-
-				int fieldCount = poFeatureDefnCur->GetFieldCount();
-
-				if( fieldCount != poFeatureDefn->GetFieldCount())
-				{
-					fprintf( stderr, "Number of attributes of layer %s of %s does not match ... skipping it.\n",
-                             poLayer->GetLayerDefn()->GetName(), papszArgv[nFirstSourceDataset]);
-                    if (bFirstWarningForNonMatchingAttributes)
+            if( poFeatureDefn == NULL )
+            {
+                poFeatureDefn = poLayer->GetLayerDefn()->Clone();
+            }
+            else if( !accept_different_schemas )
+            {
+                OGRFeatureDefn* poFeatureDefnCur = poLayer->GetLayerDefn();
+                assert(NULL != poFeatureDefnCur);
+
+                const int fieldCount = poFeatureDefnCur->GetFieldCount();
+
+                if( fieldCount != poFeatureDefn->GetFieldCount())
+                {
+                    fprintf( stderr, "Number of attributes of layer %s of %s "
+                             "does not match ... skipping it.\n",
+                             poLayer->GetLayerDefn()->GetName(),
+                             papszArgv[nFirstSourceDataset]);
+                    if( bFirstWarningForNonMatchingAttributes )
                     {
-                        fprintf( stderr, "Note : you can override this behaviour with -accept_different_schemas option\n"
-                                         "but this may result in a tileindex incompatible with MapServer\n");
-                        bFirstWarningForNonMatchingAttributes = FALSE;
+                        fprintf(
+                            stderr, "Note : you can override this "
+                            "behaviour with -accept_different_schemas option\n"
+                            "but this may result in a tileindex incompatible "
+                            "with MapServer\n");
+                        bFirstWarningForNonMatchingAttributes = false;
                     }
-					continue;
-				}
-
-                int bSkip = FALSE;
-				for( int fn = 0; fn < poFeatureDefnCur->GetFieldCount(); fn++ )
-				{
- 					OGRFieldDefn* poField = poFeatureDefn->GetFieldDefn(fn);
- 					OGRFieldDefn* poFieldCur = poFeatureDefnCur->GetFieldDefn(fn);
-
-					/* XXX - Should those pointers be checked against NULL? */
-					assert(NULL != poField);
-					assert(NULL != poFieldCur);
-
-					if( poField->GetType() != poFieldCur->GetType()
-						|| poField->GetWidth() != poFieldCur->GetWidth()
-						|| poField->GetPrecision() != poFieldCur->GetPrecision()
-						|| !EQUAL( poField->GetNameRef(), poFieldCur->GetNameRef() ) )
-					{
-						fprintf( stderr, "Schema of attributes of layer %s of %s does not match ... skipping it.\n",
-                                 poLayer->GetLayerDefn()->GetName(), papszArgv[nFirstSourceDataset]);
-                        if (bFirstWarningForNonMatchingAttributes)
+                    continue;
+                }
+
+                bool bSkip = false;
+                for( int fn = 0; fn < poFeatureDefnCur->GetFieldCount(); fn++ )
+                {
+                    OGRFieldDefn* poField = poFeatureDefn->GetFieldDefn(fn);
+                    OGRFieldDefn* poFieldCur =
+                        poFeatureDefnCur->GetFieldDefn(fn);
+
+                    // XXX - Should those pointers be checked against NULL?
+                    assert(NULL != poField);
+                    assert(NULL != poFieldCur);
+
+                    if( poField->GetType() != poFieldCur->GetType()
+                        || poField->GetWidth() != poFieldCur->GetWidth()
+                        || poField->GetPrecision() != poFieldCur->GetPrecision()
+                        || !EQUAL( poField->GetNameRef(),
+                                   poFieldCur->GetNameRef() ) )
+                    {
+                        fprintf(
+                            stderr, "Schema of attributes of layer %s of %s "
+                            "does not match. Skipping it.\n",
+                            poLayer->GetLayerDefn()->GetName(),
+                            papszArgv[nFirstSourceDataset]);
+                        if( bFirstWarningForNonMatchingAttributes )
                         {
-                            fprintf( stderr, "Note : you can override this behaviour with -accept_different_schemas option\n"
-                                             "but this may result in a tileindex incompatible with MapServer\n");
-                            bFirstWarningForNonMatchingAttributes = FALSE;
+                            fprintf(
+                                stderr, "Note : you can override this "
+                                "behaviour with -accept_different_schemas "
+                                "option,\nbut this may result in a tileindex "
+                                "incompatible with MapServer\n");
+                            bFirstWarningForNonMatchingAttributes = false;
                         }
-                        bSkip = TRUE;
+                        bSkip = true;
                         break;
-					}
-				}
+                    }
+                }
 
-                if (bSkip)
+                if( bSkip )
                     continue;
-			}
-
+            }
 
 /* -------------------------------------------------------------------- */
 /*      Get layer extents, and create a corresponding polygon           */
 /*      geometry.                                                       */
 /* -------------------------------------------------------------------- */
             OGREnvelope sExtents;
-            OGRPolygon oRegion;
-            OGRLinearRing oRing;
 
             if( poLayer->GetExtent( &sExtents, TRUE ) != OGRERR_NONE )
             {
-                fprintf( stderr, "GetExtent() failed on layer %s of %s, skipping.\n",
-                        poLayer->GetLayerDefn()->GetName(),
-                        papszArgv[nFirstSourceDataset] );
+                fprintf( stderr,
+                         "GetExtent() failed on layer %s of %s, skipping.\n",
+                         poLayer->GetLayerDefn()->GetName(),
+                         papszArgv[nFirstSourceDataset] );
                 continue;
             }
 
+            OGRLinearRing oRing;
             oRing.addPoint( sExtents.MinX, sExtents.MinY );
             oRing.addPoint( sExtents.MinX, sExtents.MaxY );
             oRing.addPoint( sExtents.MaxX, sExtents.MaxY );
             oRing.addPoint( sExtents.MaxX, sExtents.MinY );
             oRing.addPoint( sExtents.MinX, sExtents.MinY );
 
+            OGRPolygon oRegion;
             oRegion.addRing( &oRing );
 
+            // If set target srs, do the forward transformation of all points.
+            if( bSetTargetSRS && spatialRef != NULL )
+            {
+                OGRCoordinateTransformation* poCT = NULL;
+                if( !spatialRef->IsSame( poTargetSRS ) )
+                {
+                    poCT = OGRCreateCoordinateTransformation( spatialRef, poTargetSRS );
+                    if( poCT == NULL || oRegion.transform(poCT) == OGRERR_FAILURE )
+                    {
+                        char* pszSourceWKT = NULL;
+                        spatialRef->exportToWkt(&pszSourceWKT);
+                        fprintf(
+                            stderr,
+                            "Warning : unable to transform points from source "
+                            "SRS `%s' to target SRS `%s'\n"
+                            "for file `%s' - file skipped\n",
+                            pszSourceWKT, pszTargetSRS, papszArgv[nFirstSourceDataset] );
+                        CPLFree(pszSourceWKT);
+                        delete poCT;
+                        continue;
+                    }
+                    delete poCT;
+                }
+            }
+
 /* -------------------------------------------------------------------- */
 /*      Add layer to tileindex.                                         */
 /* -------------------------------------------------------------------- */
-            char        szLocation[5000];
             OGRFeature  oTileFeat( poDstLayer->GetLayerDefn() );
 
+            char szLocation[5000] = {};
             snprintf( szLocation, sizeof(szLocation), "%s,%d",
-                     fileNameToWrite, iLayer );
+                      fileNameToWrite, iLayer );
             oTileFeat.SetGeometry( &oRegion );
             oTileFeat.SetField( iTileIndexField, szLocation );
 
+            if( i_SrcSRSName >= 0 && spatialRef != NULL )
+            {
+                const char* pszAuthorityCode =
+                    spatialRef->GetAuthorityCode(NULL);
+                const char* pszAuthorityName =
+                    spatialRef->GetAuthorityName(NULL);
+                char* pszWKT = NULL;
+                spatialRef->exportToWkt(&pszWKT);
+                if( eSrcSRSFormat == FORMAT_AUTO )
+                {
+                    if( pszAuthorityName != NULL && pszAuthorityCode != NULL )
+                    {
+                        oTileFeat.SetField(i_SrcSRSName,
+                            CPLSPrintf("%s:%s",
+                                    pszAuthorityName, pszAuthorityCode) );
+                    }
+                    else if( nMaxFieldSize == 0 ||
+                            strlen(pszWKT) <= nMaxFieldSize )
+                    {
+                        oTileFeat.SetField(i_SrcSRSName, pszWKT);
+                    }
+                    else
+                    {
+                        char* pszProj4 = NULL;
+                        if( spatialRef->exportToProj4(&pszProj4) == OGRERR_NONE )
+                        {
+                            oTileFeat.SetField(i_SrcSRSName, pszProj4 );
+                            CPLFree(pszProj4);
+                        }
+                        else
+                        {
+                            oTileFeat.SetField(i_SrcSRSName, pszWKT);
+                        }
+                    }
+                }
+                else if( eSrcSRSFormat == FORMAT_WKT )
+                {
+                    if( nMaxFieldSize == 0 ||
+                        strlen(pszWKT) <= nMaxFieldSize )
+                    {
+                        oTileFeat.SetField(i_SrcSRSName, pszWKT );
+                    }
+                    else
+                    {
+                        fprintf(stderr,
+                                "Cannot write WKT for file %s as it is too long!\n",
+                                fileNameToWrite);
+                    }
+                }
+                else if( eSrcSRSFormat == FORMAT_PROJ )
+                {
+                    char* pszProj4 = NULL;
+                    if( spatialRef->exportToProj4(&pszProj4) == OGRERR_NONE )
+                    {
+                        oTileFeat.SetField(i_SrcSRSName, pszProj4 );
+                        CPLFree(pszProj4);
+                    }
+                }
+                else if( eSrcSRSFormat == FORMAT_EPSG )
+                {
+                    if( pszAuthorityName != NULL && pszAuthorityCode != NULL )
+                        oTileFeat.SetField(i_SrcSRSName,
+                            CPLSPrintf("%s:%s",
+                                    pszAuthorityName, pszAuthorityCode) );
+                }
+                CPLFree(pszWKT);
+            }
             if( poDstLayer->CreateFeature( &oTileFeat ) != OGRERR_NONE )
             {
-                fprintf( stderr, "Failed to create feature on tile index ... terminating." );
-                GDALClose( (GDALDatasetH) poDstDS );
+                fprintf( stderr,
+                         "Failed to create feature on tile index. "
+                         "Terminating." );
+                GDALClose( poDstDS );
                 exit( 1 );
             }
         }
@@ -519,24 +728,25 @@ int main( int nArgc, char ** papszArgv )
 /*      Cleanup this data source.                                       */
 /* -------------------------------------------------------------------- */
         CPLFree(fileNameToWrite);
-        GDALClose( (GDALDatasetH)poDS );
+        GDALClose( poDS );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Close tile index and clear buffers.                             */
 /* -------------------------------------------------------------------- */
-    GDALClose( (GDALDatasetH) poDstDS );
-	OGRFeatureDefn::DestroyFeatureDefn( poFeatureDefn );
+    GDALClose( poDstDS );
+    OGRFeatureDefn::DestroyFeatureDefn( poFeatureDefn );
 
-    if (alreadyExistingSpatialRef != NULL)
-        OGRSpatialReference::DestroySpatialReference( alreadyExistingSpatialRef );
+    if( alreadyExistingSpatialRef != NULL )
+        OGRSpatialReference::DestroySpatialReference(
+            alreadyExistingSpatialRef );
+    delete poTargetSRS;
 
     CPLFree(current_path);
 
-    if (nExistingLayers)
+    if( nExistingLayers )
     {
-        int i;
-        for(i=0;i<nExistingLayers;i++)
+        for( int i = 0; i < nExistingLayers; i++ )
         {
             CPLFree(existingLayersTab[i]);
         }
@@ -557,6 +767,8 @@ static void Usage()
 {
     printf( "Usage: ogrtindex [-lnum n]... [-lname name]... [-f output_format]\n"
             "                 [-write_absolute_path] [-skip_different_projection]\n"
+            "                 [-t_srs target_srs]\n"
+            "                 [-src_srs_name field_name] [-src_srs_format [AUTO|WKT|EPSG|PROJ]\n"
             "                 [-accept_different_schemas]\n"
             "                 output_dataset src_dataset...\n" );
     printf( "\n" );
@@ -575,6 +787,12 @@ static void Usage()
             "                             into the index have the same attribute schemas. If you\n"
             "                             specify this option, this test will be disabled. Be aware that\n"
             "                             resulting index may be incompatible with MapServer!\n" );
+    printf(
+            "  - If -t_srs is specified, geometries of input files will be transformed to the desired\n"
+            "    target coordinate reference system.\n"
+            "    Note that using this option generates files that are NOT compatible with MapServer < 7.2.\n"
+            "  - Simple rectangular polygons are generated in the same coordinate reference system\n"
+            "    as the vectors, or in target reference system if the -t_srs option is used.\n");
     printf( "\n" );
     printf( "If no -lnum or -lname arguments are given it is assumed that\n"
             "all layers in source datasets should be added to the tile index\n"
diff --git a/apps/test_ogrsf.cpp b/apps/test_ogrsf.cpp
index 34c7d84..c593e53 100644
--- a/apps/test_ogrsf.cpp
+++ b/apps/test_ogrsf.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: test_ogrsf.cpp 33647 2016-03-05 16:43:00Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Formal test harness for OGRLayer implementations.
@@ -35,9 +34,10 @@
 #include "ogr_p.h"
 #include "commonutils.h"
 
+#include <algorithm>
 #include <limits>
 
-CPL_CVSID("$Id: test_ogrsf.cpp 33647 2016-03-05 16:43:00Z rouault $");
+CPL_CVSID("$Id: test_ogrsf.cpp 37495 2017-02-27 18:31:22Z rouault $");
 
 int     bReadOnly = FALSE;
 int     bVerbose = TRUE;
@@ -87,6 +87,16 @@ static const char* Log(const char* pszMsg, int nLineNumber)
 #define LOG_ACTION(action) (Log(#action, __LINE__), (action))
 
 /************************************************************************/
+/*                      DestroyFeatureAndNullify()                      */
+/************************************************************************/
+
+static void DestroyFeatureAndNullify( OGRFeature*& poFeature )
+{
+    OGRFeature::DestroyFeature(poFeature);
+    poFeature = NULL;
+}
+
+/************************************************************************/
 /*                                main()                                */
 /************************************************************************/
 
@@ -371,7 +381,7 @@ static int TestDataset( GDALDriver** ppoDriver )
         poDS->ReleaseResultSet(poResultSet);
 
         bRetLocal = TestDSErrorConditions(poDS);
-        bRet &= TestDSErrorConditions(poDS);
+        bRet &= bRetLocal;
 
         bRetLocal = TestVirtualIO(poDS);
         bRet &= bRetLocal;
@@ -402,7 +412,7 @@ static int TestDataset( GDALDriver** ppoDriver )
         }
 
         bRetLocal = TestDSErrorConditions(poDS);
-        bRet &= TestDSErrorConditions(poDS);
+        bRet &= bRetLocal;
 
         bRetLocal = TestVirtualIO(poDS);
         bRet &= bRetLocal;
@@ -444,7 +454,7 @@ static int TestDataset( GDALDriver** ppoDriver )
         }
 
         bRetLocal = TestDSErrorConditions(poDS);
-        bRet &= TestDSErrorConditions(poDS);
+        bRet &= bRetLocal;
 
         bRetLocal = TestVirtualIO(poDS);
         bRet &= bRetLocal;
@@ -827,7 +837,8 @@ static int TestCreateLayer( GDALDriver* poDriver, OGRwkbGeometryType eGeomType )
         /* Those drivers are expected not to store a layer geometry type */
         !EQUAL(poDriver->GetDescription(), "KML") &&
         !EQUAL(poDriver->GetDescription(), "LIBKML") &&
-        !EQUAL(poDriver->GetDescription(), "PDF") )
+        !EQUAL(poDriver->GetDescription(), "PDF") &&
+        !EQUAL(poDriver->GetDescription(), "GeoJSON") )
     {
         /* Reopen dataset */
         poDS = LOG_ACTION((GDALDataset*)GDALOpenEx( osFilename,
@@ -1256,7 +1267,7 @@ static int TestOGRLayerFeatureCount( GDALDataset* poDS, OGRLayer *poLayer, int b
             }
         }
 
-        OGRFeature::DestroyFeature(poFeature);
+        DestroyFeatureAndNullify(poFeature);
     }
 
     /* mapogr.cpp doesn't like errors after GetNextFeature() */
@@ -1304,7 +1315,7 @@ static int TestOGRLayerFeatureCount( GDALDataset* poDS, OGRLayer *poLayer, int b
                 printf( "ERROR: Claimed feature count " CPL_FRMT_GIB " doesn't match '%s' one, " CPL_FRMT_GIB ".\n",
                         nClaimedFC, osSQL.c_str(), poFeatCount->GetFieldAsInteger64(0) );
             }
-            OGRFeature::DestroyFeature(poFeatCount);
+            DestroyFeatureAndNullify(poFeatCount);
             poDS->ReleaseResultSet(poSQLLyr);
         }
     }
@@ -1390,7 +1401,7 @@ static int TestOGRLayerRandomRead( OGRLayer *poLayer )
         goto end;
     }
 
-    OGRFeature::DestroyFeature(poFeature);
+    DestroyFeatureAndNullify(poFeature);
 
 /* -------------------------------------------------------------------- */
 /*      Test feature 5.                                                 */
@@ -1407,7 +1418,7 @@ static int TestOGRLayerRandomRead( OGRLayer *poLayer )
         goto end;
     }
 
-    OGRFeature::DestroyFeature(poFeature);
+    DestroyFeatureAndNullify(poFeature);
 
 /* -------------------------------------------------------------------- */
 /*      Test feature 2 again                                            */
@@ -1428,18 +1439,17 @@ static int TestOGRLayerRandomRead( OGRLayer *poLayer )
         printf( "INFO: Random read test passed.\n" );
 
 end:
-    OGRFeature::DestroyFeature(poFeature);
+    DestroyFeatureAndNullify(poFeature);
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
     for( iFeature = 0; iFeature < 5; iFeature++ )
-        OGRFeature::DestroyFeature(papoFeatures[iFeature]);
+        DestroyFeatureAndNullify(papoFeatures[iFeature]);
 
     return bRet;
 }
 
-
 /************************************************************************/
 /*                       TestOGRLayerSetNextByIndex()                   */
 /*                                                                      */
@@ -1504,7 +1514,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
         goto end;
     }
 
-    OGRFeature::DestroyFeature(poFeature);
+    DestroyFeatureAndNullify(poFeature);
 
     poFeature = LOG_ACTION(poLayer->GetNextFeature());
     if( poFeature == NULL || !poFeature->Equal( papoFeatures[2] ) )
@@ -1518,8 +1528,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
         goto end;
     }
 
-    OGRFeature::DestroyFeature(poFeature);
-    poFeature = NULL;
+    DestroyFeatureAndNullify(poFeature);
 
 /* -------------------------------------------------------------------- */
 /*      Test feature at index 3.                                        */
@@ -1543,7 +1552,7 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
         goto end;
     }
 
-    OGRFeature::DestroyFeature(poFeature);
+    DestroyFeatureAndNullify(poFeature);
 
     poFeature = LOG_ACTION(poLayer->GetNextFeature());
     if( !poFeature->Equal( papoFeatures[4] ) )
@@ -1557,18 +1566,17 @@ static int TestOGRLayerSetNextByIndex( OGRLayer *poLayer )
         goto end;
     }
 
-
     if( bVerbose )
         printf( "INFO: SetNextByIndex() read test passed.\n" );
 
 end:
-    OGRFeature::DestroyFeature(poFeature);
+    DestroyFeatureAndNullify(poFeature);
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
     for( iFeature = 0; iFeature < 5; iFeature++ )
-        OGRFeature::DestroyFeature(papoFeatures[iFeature]);
+        DestroyFeatureAndNullify(papoFeatures[iFeature]);
 
     return bRet;
 }
@@ -1672,7 +1680,7 @@ static int TestOGRLayerRandomWrite( OGRLayer *poLayer )
     {
         printf( "INFO: Random write test passed.\n" );
     }
-    OGRFeature::DestroyFeature(poFeature);
+    DestroyFeatureAndNullify(poFeature);
 
 /* -------------------------------------------------------------------- */
 /*      Re-invert the features to restore to original state             */
@@ -1698,7 +1706,7 @@ end:
 /* -------------------------------------------------------------------- */
 
     for( iFeature = 0; iFeature < 5; iFeature++ )
-        OGRFeature::DestroyFeature(papoFeatures[iFeature]);
+        DestroyFeatureAndNullify(papoFeatures[iFeature]);
 
     return bRet;
 }
@@ -1749,7 +1757,7 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
                     "      target feature has no geometry.\n",
                     poTargetFeature->GetDefnRef()->GetName() );
         }
-        OGRFeature::DestroyFeature(poTargetFeature);
+        DestroyFeatureAndNullify(poTargetFeature);
         return bRet;
     }
 
@@ -1762,7 +1770,8 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
         sLayerExtent.MinX < sLayerExtent.MaxX &&
         sLayerExtent.MinY < sLayerExtent.MaxY )
     {
-        epsilon = MIN( sLayerExtent.MaxX - sLayerExtent.MinX, sLayerExtent.MaxY - sLayerExtent.MinY ) / 10.0;
+        epsilon = std::min(sLayerExtent.MaxX - sLayerExtent.MinX,
+                           sLayerExtent.MaxY - sLayerExtent.MinY) / 10.0;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1784,18 +1793,19 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
 /* -------------------------------------------------------------------- */
     LOG_ACTION(poLayer->ResetReading());
 
+    bool bFound = false;
+    GIntBig nIterCount = 0;
     while( (poFeature = LOG_ACTION(poLayer->GetNextFeature())) != NULL )
     {
         if( poFeature->Equal(poTargetFeature) )
         {
-            OGRFeature::DestroyFeature(poFeature);
-            break;
+            bFound = true;
         }
-        else
-            OGRFeature::DestroyFeature(poFeature);
+        nIterCount ++;
+        DestroyFeatureAndNullify(poFeature);
     }
 
-    if( poFeature == NULL )
+    if( !bFound )
     {
         bRet = FALSE;
         printf( "ERROR: Spatial filter (%d) eliminated a feature unexpectedly!\n",
@@ -1808,6 +1818,35 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
 
     nInclusiveCount = LOG_ACTION(poLayer->GetFeatureCount());
 
+    // Identity check doesn't always work depending on feature geometries
+    if( nIterCount > nInclusiveCount )
+    {
+        bRet = FALSE;
+        printf( "ERROR: GetFeatureCount() with spatial filter smaller (%d) than "
+                "count while iterating over features (%d).\n",
+                static_cast<int>(nInclusiveCount), static_cast<int>(nIterCount));
+    }
+
+    LOG_ACTION(poLayer->SetAttributeFilter("1=1"));
+    GIntBig nShouldBeSame = LOG_ACTION(poLayer->GetFeatureCount());
+    LOG_ACTION(poLayer->SetAttributeFilter(NULL));
+    if( nShouldBeSame != nInclusiveCount )
+    {
+        bRet = FALSE;
+        printf( "ERROR: Attribute filter seems to be make spatial "
+                "filter fail with GetFeatureCount().\n" );
+    }
+
+    LOG_ACTION(poLayer->SetAttributeFilter("1=0"));
+    GIntBig nShouldBeZero = LOG_ACTION(poLayer->GetFeatureCount());
+    LOG_ACTION(poLayer->SetAttributeFilter(NULL));
+    if( nShouldBeZero != 0 )
+    {
+        bRet = FALSE;
+        printf( "ERROR: Attribute filter seems to be ignored in "
+                "GetFeatureCount() when spatial filter is set.\n" );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Construct exclusive filter.                                     */
 /* -------------------------------------------------------------------- */
@@ -1830,11 +1869,11 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
     {
         if( poFeature->Equal(poTargetFeature) )
         {
-            OGRFeature::DestroyFeature(poFeature);
+            DestroyFeatureAndNullify(poFeature);
             break;
         }
         else
-            OGRFeature::DestroyFeature(poFeature);
+            DestroyFeatureAndNullify(poFeature);
     }
 
     if( poFeature != NULL )
@@ -1868,7 +1907,7 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
         printf( "INFO: Spatial filter is ignored by GetFeature() as expected.\n");
     }
     if( poFeature != NULL )
-        OGRFeature::DestroyFeature(poFeature);
+        DestroyFeatureAndNullify(poFeature);
 
     if( bRet )
     {
@@ -1877,11 +1916,11 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
         {
             if( poFeature->Equal(poTargetFeature) )
             {
-                OGRFeature::DestroyFeature(poFeature);
+                DestroyFeatureAndNullify(poFeature);
                 break;
             }
             else
-                OGRFeature::DestroyFeature(poFeature);
+                DestroyFeatureAndNullify(poFeature);
         }
         if( poFeature != NULL )
         {
@@ -1890,7 +1929,7 @@ static int TestSpatialFilter( OGRLayer *poLayer, int iGeomField )
         }
     }
 
-    OGRFeature::DestroyFeature(poTargetFeature);
+    DestroyFeatureAndNullify(poTargetFeature);
 
 /* -------------------------------------------------------------------- */
 /*     Test infinity envelope                                           */
@@ -1995,7 +2034,8 @@ static int TestFullSpatialFilter( OGRLayer *poLayer, int iGeomField )
         sLayerExtent.MinX < sLayerExtent.MaxX &&
         sLayerExtent.MinY < sLayerExtent.MaxY )
     {
-        epsilon = MIN( sLayerExtent.MaxX - sLayerExtent.MinX, sLayerExtent.MaxY - sLayerExtent.MinY ) / 10.0;
+        epsilon = std::min(sLayerExtent.MaxX - sLayerExtent.MinX,
+                           sLayerExtent.MaxY - sLayerExtent.MinY) / 10.0;
     }
 
     GIntBig nTotalFeatureCount = LOG_ACTION(poLayer->GetFeatureCount());
@@ -2022,7 +2062,7 @@ static int TestFullSpatialFilter( OGRLayer *poLayer, int iGeomField )
         OGRGeometry* poGeom = poTargetFeature->GetGeomFieldRef(iGeomField);
         if( poGeom == NULL || poGeom->IsEmpty() )
         {
-            OGRFeature::DestroyFeature(poTargetFeature);
+            DestroyFeatureAndNullify(poTargetFeature);
             continue;
         }
 
@@ -2047,27 +2087,29 @@ static int TestFullSpatialFilter( OGRLayer *poLayer, int iGeomField )
 /* -------------------------------------------------------------------- */
         LOG_ACTION(poLayer->ResetReading());
 
+        bool bFound = false;
         while( (poFeature = LOG_ACTION(poLayer->GetNextFeature())) != NULL )
         {
             if( poFeature->Equal(poTargetFeature) )
             {
-                OGRFeature::DestroyFeature(poFeature);
+                bFound = true;
+                DestroyFeatureAndNullify(poFeature);
                 break;
             }
             else
-                OGRFeature::DestroyFeature(poFeature);
+                DestroyFeatureAndNullify(poFeature);
         }
 
-        if( poFeature == NULL )
+        if( !bFound )
         {
             bRet = FALSE;
             printf( "ERROR: Spatial filter (%d) eliminated feature " CPL_FRMT_GIB " unexpectedly!\n",
                     iGeomField, poTargetFeature->GetFID());
-            OGRFeature::DestroyFeature(poTargetFeature);
+            DestroyFeatureAndNullify(poTargetFeature);
             break;
         }
 
-        OGRFeature::DestroyFeature(poTargetFeature);
+        DestroyFeatureAndNullify(poTargetFeature);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2101,7 +2143,7 @@ static int TestSpatialFilter( OGRLayer *poLayer )
         }
         return TRUE;
     }
-    OGRFeature::DestroyFeature(poTargetFeature);
+    DestroyFeatureAndNullify(poTargetFeature);
 
     int nGeomFieldCount = LOG_ACTION(poLayer->GetLayerDefn()->GetGeomFieldCount());
     if( nGeomFieldCount == 0 )
@@ -2142,7 +2184,6 @@ static int TestSpatialFilter( OGRLayer *poLayer )
     return bRet;
 }
 
-
 /************************************************************************/
 /*                      TestAttributeFilter()                           */
 /*                                                                      */
@@ -2183,7 +2224,7 @@ static int TestAttributeFilter( CPL_UNUSED GDALDataset* poDS, OGRLayer *poLayer
     for(i=0;i<poTargetFeature->GetFieldCount();i++)
     {
         eType = poTargetFeature->GetFieldDefnRef(i)->GetType();
-        if (poTargetFeature->IsFieldSet(i) &&
+        if (poTargetFeature->IsFieldSetAndNotNull(i) &&
             (eType == OFTString || eType == OFTInteger || eType == OFTReal))
         {
             break;
@@ -2197,7 +2238,7 @@ static int TestAttributeFilter( CPL_UNUSED GDALDataset* poDS, OGRLayer *poLayer
                     "      Could not find non NULL field.\n",
                     poLayer->GetName() );
         }
-        OGRFeature::DestroyFeature(poTargetFeature);
+        DestroyFeatureAndNullify(poTargetFeature);
         return bRet;
     }
 
@@ -2235,18 +2276,20 @@ static int TestAttributeFilter( CPL_UNUSED GDALDataset* poDS, OGRLayer *poLayer
 /* -------------------------------------------------------------------- */
     LOG_ACTION(poLayer->ResetReading());
 
+    bool bFoundFeature = false;
     while( (poFeature = LOG_ACTION(poLayer->GetNextFeature())) != NULL )
     {
         if( poFeature->Equal(poTargetFeature) )
         {
-            OGRFeature::DestroyFeature(poFeature);
+            bFoundFeature = true;
+            DestroyFeatureAndNullify(poFeature);
             break;
         }
         else
-            OGRFeature::DestroyFeature(poFeature);
+            DestroyFeatureAndNullify(poFeature);
     }
 
-    if( poFeature == NULL )
+    if( !bFoundFeature )
     {
         bRet = FALSE;
         printf( "ERROR: Attribute filter eliminated a feature unexpectedly!\n");
@@ -2291,11 +2334,11 @@ static int TestAttributeFilter( CPL_UNUSED GDALDataset* poDS, OGRLayer *poLayer
     {
         if( poFeature->Equal(poTargetFeature) )
         {
-            OGRFeature::DestroyFeature(poFeature);
+            DestroyFeatureAndNullify(poFeature);
             break;
         }
         else
-            OGRFeature::DestroyFeature(poFeature);
+            DestroyFeatureAndNullify(poFeature);
         nExclusiveCountWhileIterating ++;
     }
 
@@ -2309,11 +2352,11 @@ static int TestAttributeFilter( CPL_UNUSED GDALDataset* poDS, OGRLayer *poLayer
     {
         if( poFeature3->Equal(poTargetFeature) )
         {
-            OGRFeature::DestroyFeature(poFeature3);
+            DestroyFeatureAndNullify(poFeature3);
             break;
         }
         else
-            OGRFeature::DestroyFeature(poFeature3);
+            DestroyFeatureAndNullify(poFeature3);
     }
 
     LOG_ACTION(poLayer->SetAttributeFilter( NULL ));
@@ -2358,9 +2401,9 @@ static int TestAttributeFilter( CPL_UNUSED GDALDataset* poDS, OGRLayer *poLayer
     }
 
     if( poFeature2 != NULL )
-        OGRFeature::DestroyFeature(poFeature2);
+        DestroyFeatureAndNullify(poFeature2);
 
-    OGRFeature::DestroyFeature(poTargetFeature);
+    DestroyFeatureAndNullify(poTargetFeature);
 
     return bRet;
 }
@@ -2430,7 +2473,7 @@ static int TestOGRLayerUTF8 ( OGRLayer *poLayer )
                 }
             }
         }
-        OGRFeature::DestroyFeature(poFeature);
+        DestroyFeatureAndNullify(poFeature);
     }
 
     if (!bFoundString)
@@ -2651,7 +2694,7 @@ static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
     {
         printf( "INFO: Delete Feature test passed.\n" );
     }
-    OGRFeature::DestroyFeature(poFeatureTest);
+    DestroyFeatureAndNullify(poFeatureTest);
 
 /* -------------------------------------------------------------------- */
 /*      Re-insert the features to restore to original state             */
@@ -2686,14 +2729,14 @@ static int TestOGRLayerDeleteAndCreateFeature( OGRLayer *poLayer )
     {
         printf( "INFO: Create Feature test passed.\n" );
     }
-    OGRFeature::DestroyFeature(poFeatureTest);
+    DestroyFeatureAndNullify(poFeatureTest);
 
 end:
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
 
-    OGRFeature::DestroyFeature(poFeature);
+    DestroyFeatureAndNullify(poFeature);
 
     return bRet;
 }
@@ -2893,7 +2936,7 @@ static int TestOGRLayerIgnoreFields( OGRLayer* poLayer )
         {
             for(int i=0;i<poFeature->GetFieldCount();i++)
             {
-                if( poFeature->IsFieldSet(i) )
+                if( poFeature->IsFieldSetAndNotNull(i) )
                 {
                     iFieldNonEmpty = i;
                     break;
@@ -2904,7 +2947,7 @@ static int TestOGRLayerIgnoreFields( OGRLayer* poLayer )
         {
             for(int i=0;i<poFeature->GetFieldCount();i++)
             {
-                if( i != iFieldNonEmpty && poFeature->IsFieldSet(i) )
+                if( i != iFieldNonEmpty && poFeature->IsFieldSetAndNotNull(i) )
                 {
                     iFieldNonEmpty2 = i;
                     break;
@@ -2950,7 +2993,7 @@ static int TestOGRLayerIgnoreFields( OGRLayer* poLayer )
     LOG_ACTION(poLayer->ResetReading());
     while( (poFeature = LOG_ACTION(poLayer->GetNextFeature())) != NULL )
     {
-        if( iFieldNonEmpty >= 0 && poFeature->IsFieldSet(iFieldNonEmpty) )
+        if( iFieldNonEmpty >= 0 && poFeature->IsFieldSetAndNotNull(iFieldNonEmpty) )
         {
             delete poFeature;
             printf( "ERROR: After SetIgnoredFields(), found a non empty field that should have been ignored.\n" );
@@ -2958,7 +3001,7 @@ static int TestOGRLayerIgnoreFields( OGRLayer* poLayer )
             return FALSE;
         }
 
-        if( iFieldNonEmpty2 >= 0 && poFeature->IsFieldSet(iFieldNonEmpty2) )
+        if( iFieldNonEmpty2 >= 0 && poFeature->IsFieldSetAndNotNull(iFieldNonEmpty2) )
             bFoundNonEmpty2 = TRUE;
 
         if( bGeomNonEmpty && poFeature->GetGeometryRef() != NULL)
@@ -3107,10 +3150,9 @@ static int TestLayerSQL( GDALDataset* poDS, OGRLayer * poLayer )
         }
     }
 
-    OGRFeature::DestroyFeature(poLayerFeat);
-    poLayerFeat = NULL;
-    OGRFeature::DestroyFeature(poSQLFeat);
-    poSQLFeat = NULL;
+    DestroyFeatureAndNullify(poLayerFeat);
+    DestroyFeatureAndNullify(poSQLFeat);
+
     if( poSQLLyr )
     {
         LOG_ACTION(poDS->ReleaseResultSet(poSQLLyr));
@@ -3119,7 +3161,14 @@ static int TestLayerSQL( GDALDataset* poDS, OGRLayer * poLayer )
 
     /* Try ResetReading(), GetNextFeature(), ResetReading(), GetNextFeature() */
     poSQLLyr = LOG_ACTION(poDS->ExecuteSQL(osSQL.c_str(), NULL, NULL));
-
+    if( poSQLLyr == NULL )
+    {
+        printf( "ERROR: ExecuteSQL(%s) failed at line %d "
+                "(but succeeded before).\n",
+                osSQL.c_str(), __LINE__ );
+        bRet = FALSE;
+        return bRet;
+    }
     LOG_ACTION(poSQLLyr->ResetReading());
 
     poSQLFeat = LOG_ACTION(poSQLLyr->GetNextFeature());
@@ -3128,8 +3177,7 @@ static int TestLayerSQL( GDALDataset* poDS, OGRLayer * poLayer )
         printf( "ERROR: Should have got feature (1)\n" );
         bRet = FALSE;
     }
-    OGRFeature::DestroyFeature(poSQLFeat);
-    poSQLFeat = NULL;
+    DestroyFeatureAndNullify(poSQLFeat);
 
     LOG_ACTION(poSQLLyr->ResetReading());
 
@@ -3139,28 +3187,67 @@ static int TestLayerSQL( GDALDataset* poDS, OGRLayer * poLayer )
         printf( "ERROR: Should have got feature (2)\n" );
         bRet = FALSE;
     }
-    OGRFeature::DestroyFeature(poSQLFeat);
-    poSQLFeat = NULL;
+    DestroyFeatureAndNullify(poSQLFeat);
 
-    if( poSQLLyr )
+    LOG_ACTION(poDS->ReleaseResultSet(poSQLLyr));
+
+    /* Return an empty layer */
+    osSQL.Printf("SELECT * FROM %s WHERE 0 = 1", GetLayerNameForSQL(poDS, poLayer->GetName()));
+
+    poSQLLyr = LOG_ACTION(poDS->ExecuteSQL(osSQL.c_str(), NULL, NULL));
+    if (poSQLLyr)
     {
+        poSQLFeat = LOG_ACTION(poSQLLyr->GetNextFeature());
+        if (poSQLFeat != NULL)
+        {
+            bRet = FALSE;
+            printf( "ERROR: ExecuteSQL() should have returned a layer without features.\n" );
+        }
+        DestroyFeatureAndNullify(poSQLFeat);
+
         LOG_ACTION(poDS->ReleaseResultSet(poSQLLyr));
-        poSQLLyr = NULL;
+    }
+    else
+    {
+        printf( "ERROR: ExecuteSQL() should have returned a non-NULL result.\n");
+        bRet = FALSE;
     }
 
-    /* Return an empty layer */
+    // Test that installing a spatial filter on an empty layer at ExecuteSQL()
+    // does not raise an error
     osSQL.Printf("SELECT * FROM %s WHERE 0 = 1", GetLayerNameForSQL(poDS, poLayer->GetName()));
 
-    poSQLLyr = LOG_ACTION(poDS->ExecuteSQL(osSQL.c_str(), NULL, NULL));
+    OGRPolygon oPoly;
+    OGRLinearRing oRing;
+    oRing.setPoint( 0, 0, 0 );
+    oRing.setPoint( 1, 0, 1 );
+    oRing.setPoint( 2, 1, 1 );
+    oRing.setPoint( 3, 1, 0 );
+    oRing.setPoint( 4, 0, 0 );
+    oPoly.addRing( &oRing );
+
+    CPLErrorReset();
+    poSQLLyr = LOG_ACTION(poDS->ExecuteSQL(osSQL.c_str(), &oPoly, NULL));
+    if( CPLGetLastErrorType() != CE_None )
+    {
+        bRet = FALSE;
+        printf( "ERROR: ExecuteSQL() triggered an unexpected error.\n" );
+    }
     if (poSQLLyr)
     {
+        CPLErrorReset();
         poSQLFeat = LOG_ACTION(poSQLLyr->GetNextFeature());
+        if( CPLGetLastErrorType() != CE_None )
+        {
+            bRet = FALSE;
+            printf( "ERROR: GetNextFeature() triggered an unexpected error.\n" );
+        }
         if (poSQLFeat != NULL)
         {
             bRet = FALSE;
             printf( "ERROR: ExecuteSQL() should have returned a layer without features.\n" );
         }
-        OGRFeature::DestroyFeature(poSQLFeat);
+        DestroyFeatureAndNullify(poSQLFeat);
         LOG_ACTION(poDS->ReleaseResultSet(poSQLLyr));
     }
     else
@@ -3271,7 +3358,6 @@ static int TestOGRLayer( GDALDataset* poDS, OGRLayer * poLayer, int bIsSQLLayer
 /* -------------------------------------------------------------------- */
     bRet &= TestLayerErrorConditions( poLayer );
 
-
 /* -------------------------------------------------------------------- */
 /*      Test some SQL.                                                  */
 /* -------------------------------------------------------------------- */
@@ -3408,14 +3494,14 @@ static int TestInterleavedReading( const char* pszDataSourceIn, char** papszLaye
     }
 
 bye:
-    OGRFeature::DestroyFeature(poFeature11_Ref);
-    OGRFeature::DestroyFeature(poFeature12_Ref);
-    OGRFeature::DestroyFeature(poFeature21_Ref);
-    OGRFeature::DestroyFeature(poFeature22_Ref);
-    OGRFeature::DestroyFeature(poFeature11);
-    OGRFeature::DestroyFeature(poFeature21);
-    OGRFeature::DestroyFeature(poFeature12);
-    OGRFeature::DestroyFeature(poFeature22);
+    DestroyFeatureAndNullify(poFeature11_Ref);
+    DestroyFeatureAndNullify(poFeature12_Ref);
+    DestroyFeatureAndNullify(poFeature21_Ref);
+    DestroyFeatureAndNullify(poFeature22_Ref);
+    DestroyFeatureAndNullify(poFeature11);
+    DestroyFeatureAndNullify(poFeature21);
+    DestroyFeatureAndNullify(poFeature12);
+    DestroyFeatureAndNullify(poFeature22);
     if( poDS != NULL)
         LOG_ACTION(GDALClose( (GDALDatasetH)poDS ));
     if( poDS2 != NULL )
diff --git a/apps/testepsg.cpp b/apps/testepsg.cpp
index 93f29e4..7f5b10e 100644
--- a/apps/testepsg.cpp
+++ b/apps/testepsg.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: testepsg.cpp 33615 2016-03-02 20:19:22Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Test mainline for translating EPSG definitions into WKT.
@@ -27,12 +26,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
-#include "ogr_core.h"
 #include "cpl_conv.h"
+#include "cpl_multiproc.h"
 #include "cpl_string.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
-#include "cpl_multiproc.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: testepsg.cpp 36556 2016-11-29 23:39:59Z goatbar $");
 
 static void Usage()
 
@@ -49,8 +50,7 @@ int main( int nArgc, char ** papszArgv )
 
 {
     OGRSpatialReference oSRS;
-    int i;
-    int bReportXML = FALSE;
+    bool bReportXML = false;
 
 /* -------------------------------------------------------------------- */
 /*      Processing command line arguments.                              */
@@ -60,17 +60,17 @@ int main( int nArgc, char ** papszArgv )
     if( nArgc < 2 )
         Usage();
 
-    for( i = 1; i < nArgc; i++ )
+    for( int i = 1; i < nArgc; i++ )
     {
         if( EQUAL(papszArgv[i],"-xml") )
-            bReportXML = TRUE;
+            bReportXML = true;
 
         else if( EQUAL(papszArgv[i],"-t") && i < nArgc - 4 )
         {
-            OGRSpatialReference oSourceSRS, oTargetSRS;
+            OGRSpatialReference oSourceSRS;
+            OGRSpatialReference oTargetSRS;
             OGRCoordinateTransformation *poCT;
-            double                      x, y, z_orig, z;
-            int                         nArgsUsed = 4;
+            int nArgsUsed = 4;
 
             if( oSourceSRS.SetFromUserInput(papszArgv[i+1]) != OGRERR_NONE )
             {
@@ -89,8 +89,10 @@ int main( int nArgc, char ** papszArgv )
 
             poCT = OGRCreateCoordinateTransformation( &oSourceSRS,
                                                       &oTargetSRS );
-            x = CPLAtof( papszArgv[i+3] );
-            y = CPLAtof( papszArgv[i+4] );
+            double x = CPLAtof( papszArgv[i+3] );
+            double y = CPLAtof( papszArgv[i+4] );
+            double z_orig = 0.0;
+            double z = 0.0;
             if( i < nArgc - 5
                 && (CPLAtof(papszArgv[i+5]) > 0.0 || papszArgv[i+5][0] == '0') )
             {
@@ -98,7 +100,9 @@ int main( int nArgc, char ** papszArgv )
                 nArgsUsed++;
             }
             else
+            {
                 z_orig = z = 0;
+            }
 
             if( poCT == NULL || !poCT->Transform( 1, &x, &y, &z ) )
                 printf( "Transformation failed.\n" );
@@ -164,10 +168,9 @@ int main( int nArgc, char ** papszArgv )
                         papszArgv[i], pszWKT );
                 CPLFree( pszWKT );
 
-
                 if( bReportXML )
                 {
-                    char       *pszRawXML;
+                    char *pszRawXML = NULL;
                     if( oSRS.exportToXML(&pszRawXML) == OGRERR_NONE )
                     {
                         printf( "XML[%s] =\n%s\n",
diff --git a/apps/testreprojmulti.cpp b/apps/testreprojmulti.cpp
index 6b9fecc..80709e1 100644
--- a/apps/testreprojmulti.cpp
+++ b/apps/testreprojmulti.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: testreprojmulti.cpp 33011 2016-01-15 22:20:29Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Test multi-threaded reprojection
@@ -34,7 +33,7 @@
 #include "cpl_multiproc.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: testreprojmulti.cpp 33011 2016-01-15 22:20:29Z goatbar $");
+CPL_CVSID("$Id: testreprojmulti.cpp 34654 2016-07-14 05:53:06Z goatbar $");
 
 double* padfRefX;
 double* padfRefY;
diff --git a/bridge/Makefile b/bridge/Makefile
deleted file mode 100644
index cf32472..0000000
--- a/bridge/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-
-bridge_test:	bridge_test.cpp gbgetsymbol.cpp gdalbridge.cpp
-	$(CXX) -Wall -g bridge_test.cpp gbgetsymbol.cpp gdalbridge.cpp -ldl \
-		-o bridge_test
-
-clean:
-	rm *.o bridge_test
-
-
-
-
diff --git a/bridge/bridge_test.cpp b/bridge/bridge_test.cpp
deleted file mode 100644
index e8df0af..0000000
--- a/bridge/bridge_test.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/******************************************************************************
- * $Id: bridge_test.cpp 33713 2016-03-12 17:41:57Z goatbar $
- *
- * Project:  GDAL Bridge
- * Purpose:  Simple mainline for testing bridge.  This is a slightly modified
- *           apps/gdalinfo.c.
- * Author:   Frank Warmerdam, warmerda at home.com
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include "gdalbridge.h"
-
-static int
-GDALInfoReportCorner( GDALDatasetH hDataset,
-                      const char * corner_name,
-                      double x, double y );
-
-int main( int argc, char ** argv )
-
-{
-    GDALDatasetH	hDataset;
-    GDALRasterBandH	hBand;
-    int			i, iBand;
-    double		adfGeoTransform[6];
-    GDALDriverH		hDriver;
-    char		**papszMetadata;
-    int                 bComputeMinMax = FALSE;
-
-    if( !GDALBridgeInitialize( "..", stderr ) )
-    {
-        fprintf( stderr, "Unable to initialize GDAL bridge.\n" );
-        exit( 10 );
-    }
-
-    if( argc > 1 && strcmp(argv[1],"-mm") == 0 )
-    {
-        bComputeMinMax = TRUE;
-        argv++;
-    }
-
-    GDALAllRegister();
-
-    hDataset = GDALOpen( argv[1], GA_ReadOnly );
-
-    if( hDataset == NULL )
-    {
-        fprintf( stderr,
-                 "GDALOpen failed - %d\n%s\n",
-                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
-        exit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report general info.                                            */
-/* -------------------------------------------------------------------- */
-    hDriver = GDALGetDatasetDriver( hDataset );
-    printf( "Driver: %s/%s\n",
-            GDALGetDriverShortName( hDriver ),
-            GDALGetDriverLongName( hDriver ) );
-
-    printf( "Size is %d, %d\n",
-            GDALGetRasterXSize( hDataset ),
-            GDALGetRasterYSize( hDataset ) );
-
-/* -------------------------------------------------------------------- */
-/*      Report projection.                                              */
-/* -------------------------------------------------------------------- */
-    if( GDALGetProjectionRef( hDataset ) != NULL )
-    {
-        OGRSpatialReferenceH  hSRS;
-        char		      *pszProjection;
-
-        pszProjection = (char *) GDALGetProjectionRef( hDataset );
-
-        hSRS = OSRNewSpatialReference(NULL);
-        if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
-        {
-            char	*pszPrettyWkt = NULL;
-
-            OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
-            printf( "Coordinate System is:\n%s\n", pszPrettyWkt );
-        }
-        else
-            printf( "Coordinate System is `%s'\n",
-                    GDALGetProjectionRef( hDataset ) );
-
-        OSRDestroySpatialReference( hSRS );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report Geotransform.                                            */
-/* -------------------------------------------------------------------- */
-    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
-    {
-        printf( "Origin = (%.6f,%.6f)\n",
-                adfGeoTransform[0], adfGeoTransform[3] );
-
-        printf( "Pixel Size = (%.6f,%.6f)\n",
-                adfGeoTransform[1], adfGeoTransform[5] );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report GCPs.                                                    */
-/* -------------------------------------------------------------------- */
-    if( GDALGetGCPCount( hDataset ) > 0 )
-    {
-        printf( "GCP Projection = %s\n", GDALGetGCPProjection(hDataset) );
-        for( i = 0; i < GDALGetGCPCount(hDataset); i++ )
-        {
-            const GDAL_GCP	*psGCP;
-
-            psGCP = GDALGetGCPs( hDataset ) + i;
-
-            printf( "GCP[%3d]: Id=%s, Info=%s\n"
-                    "          (%g,%g) -> (%g,%g,%g)\n",
-                    i, psGCP->pszId, psGCP->pszInfo,
-                    psGCP->dfGCPPixel, psGCP->dfGCPLine,
-                    psGCP->dfGCPX, psGCP->dfGCPY, psGCP->dfGCPZ );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report metadata.                                                */
-/* -------------------------------------------------------------------- */
-    papszMetadata = GDALGetMetadata( hDataset, NULL );
-    if( papszMetadata != NULL )
-    {
-        printf( "Metadata:\n" );
-        for( i = 0; papszMetadata[i] != NULL; i++ )
-        {
-            printf( "  %s\n", papszMetadata[i] );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report subdatasets.                                             */
-/* -------------------------------------------------------------------- */
-    papszMetadata = GDALGetMetadata( hDataset, "SUBDATASETS" );
-    if( papszMetadata != NULL )
-    {
-        printf( "Subdatasets:\n" );
-        for( i = 0; papszMetadata[i] != NULL; i++ )
-        {
-            printf( "  %s\n", papszMetadata[i] );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report corners.                                                 */
-/* -------------------------------------------------------------------- */
-    printf( "Corner Coordinates:\n" );
-    GDALInfoReportCorner( hDataset, "Upper Left",
-                          0.0, 0.0 );
-    GDALInfoReportCorner( hDataset, "Lower Left",
-                          0.0, GDALGetRasterYSize(hDataset));
-    GDALInfoReportCorner( hDataset, "Upper Right",
-                          GDALGetRasterXSize(hDataset), 0.0 );
-    GDALInfoReportCorner( hDataset, "Lower Right",
-                          GDALGetRasterXSize(hDataset),
-                          GDALGetRasterYSize(hDataset) );
-    GDALInfoReportCorner( hDataset, "Center",
-                          GDALGetRasterXSize(hDataset)/2.0,
-                          GDALGetRasterYSize(hDataset)/2.0 );
-
-/* ==================================================================== */
-/*      Loop over bands.                                                */
-/* ==================================================================== */
-    for( iBand = 0; iBand < GDALGetRasterCount( hDataset ); iBand++ )
-    {
-        double      dfMin, dfMax, adfCMinMax[2], dfNoData;
-        int         bGotMin, bGotMax, bGotNodata;
-        int         nBlockXSize, nBlockYSize;
-
-        hBand = GDALGetRasterBand( hDataset, iBand+1 );
-        GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
-        printf( "Band %d Block=%dx%d Type=%d, ColorInterp=%d\n", iBand+1,
-                nBlockXSize, nBlockYSize,
-                GDALGetRasterDataType(hBand),
-                GDALGetRasterColorInterpretation(hBand) );
-
-        dfMin = GDALGetRasterMinimum( hBand, &bGotMin );
-        dfMax = GDALGetRasterMaximum( hBand, &bGotMax );
-        printf( "  Min=%.3f/%d, Max=%.3f/%d",  dfMin, bGotMin, dfMax, bGotMax);
-
-        if( bComputeMinMax )
-        {
-            GDALComputeRasterMinMax( hBand, TRUE, adfCMinMax );
-            printf( ", Computed Min/Max=%.3f,%.3f",
-                    adfCMinMax[0], adfCMinMax[1] );
-        }
-        printf( "\n" );
-
-        dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata );
-        if( bGotNodata )
-        {
-            printf( "  NoData Value=%g\n", dfNoData );
-        }
-
-        if( GDALGetOverviewCount(hBand) > 0 )
-        {
-            int		iOverview;
-
-            printf( "  Overviews: " );
-            for( iOverview = 0;
-                 iOverview < GDALGetOverviewCount(hBand);
-                 iOverview++ )
-            {
-                GDALRasterBandH	hOverview;
-
-                if( iOverview != 0 )
-                    printf( ", " );
-
-                hOverview = GDALGetOverview( hBand, iOverview );
-                printf( "%dx%d",
-                        GDALGetRasterBandXSize( hOverview ),
-                        GDALGetRasterBandYSize( hOverview ) );
-            }
-            printf( "\n" );
-        }
-
-        papszMetadata = GDALGetMetadata( hBand, NULL );
-        if( papszMetadata != NULL )
-        {
-            printf( "Metadata:\n" );
-            for( i = 0; papszMetadata[i] != NULL; i++ )
-            {
-                printf( "  %s\n", papszMetadata[i] );
-            }
-        }
-
-        if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex )
-        {
-            GDALColorTableH	hTable;
-            int			i;
-
-            hTable = GDALGetRasterColorTable( hBand );
-            printf( "  Color Table (%s with %d entries)\n",
-                    GDALGetPaletteInterpretationName(
-                        GDALGetPaletteInterpretation( hTable )),
-                    GDALGetColorEntryCount( hTable ) );
-
-            for( i = 0; i < GDALGetColorEntryCount( hTable ); i++ )
-            {
-                GDALColorEntry	sEntry;
-
-                GDALGetColorEntryAsRGB( hTable, i, &sEntry );
-                printf( "  %3d: %d,%d,%d,%d\n",
-                        i,
-                        sEntry.c1,
-                        sEntry.c2,
-                        sEntry.c3,
-                        sEntry.c4 );
-            }
-        }
-    }
-
-    GDALClose( hDataset );
-
-    exit( 0 );
-}
-
-/************************************************************************/
-/*                        GDALInfoReportCorner()                        */
-/************************************************************************/
-
-static int
-GDALInfoReportCorner( GDALDatasetH hDataset,
-                      const char * corner_name,
-                      double x, double y )
-
-{
-    double	dfGeoX, dfGeoY;
-    const char  *pszProjection;
-    double	adfGeoTransform[6];
-    OGRCoordinateTransformationH hTransform = NULL;
-
-    printf( "%-11s ", corner_name );
-
-/* -------------------------------------------------------------------- */
-/*      Transform the point into georeferenced coordinates.             */
-/* -------------------------------------------------------------------- */
-    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
-    {
-        pszProjection = GDALGetProjectionRef(hDataset);
-
-        dfGeoX = adfGeoTransform[0] + adfGeoTransform[1] * x
-            + adfGeoTransform[2] * y;
-        dfGeoY = adfGeoTransform[3] + adfGeoTransform[4] * x
-            + adfGeoTransform[5] * y;
-    }
-
-    else
-    {
-        printf( "(%7.1f,%7.1f)\n", x, y );
-        return FALSE;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report the georeferenced coordinates.                           */
-/* -------------------------------------------------------------------- */
-    if( fabs(dfGeoX) < 181 && fabs(dfGeoY) < 91 )
-    {
-        printf( "(%12.7f,%12.7f) ", dfGeoX, dfGeoY );
-
-    }
-    else
-    {
-        printf( "(%12.3f,%12.3f) ", dfGeoX, dfGeoY );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Setup transformation to lat/long.                               */
-/* -------------------------------------------------------------------- */
-    if( pszProjection != NULL && strlen(pszProjection) > 0 )
-    {
-        OGRSpatialReferenceH hProj, hLatLong = NULL;
-
-        hProj = OSRNewSpatialReference( pszProjection );
-        if( hProj != NULL )
-            hLatLong = OSRCloneGeogCS( hProj );
-
-        if( hLatLong != NULL )
-        {
-            hTransform = OCTNewCoordinateTransformation( hProj, hLatLong );
-            OSRDestroySpatialReference( hLatLong );
-        }
-
-        if( hProj != NULL )
-            OSRDestroySpatialReference( hProj );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Transform to latlong and report.                                */
-/* -------------------------------------------------------------------- */
-    if( hTransform != NULL
-        && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,NULL) )
-    {
-
-        printf( "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) );
-        printf( "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) );
-    }
-
-    if( hTransform != NULL )
-        OCTDestroyCoordinateTransformation( hTransform );
-
-    printf( "\n" );
-
-    return TRUE;
-}
diff --git a/bridge/gbgetsymbol.cpp b/bridge/gbgetsymbol.cpp
deleted file mode 100644
index e48e927..0000000
--- a/bridge/gbgetsymbol.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/******************************************************************************
- * $Id: gbgetsymbol.cpp 32058 2015-12-07 05:09:48Z goatbar $
- *
- * Project:  GDAL Bridge
- * Purpose:  Fetch a function pointer from a shared library / DLL.
- * Author:   Frank Warmerdam, warmerda at home.com
- *
- * Adapted from cplgetsymbol.cpp.
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include <stdio.h>
-#include "gdalbridge.h"
-
-/* ==================================================================== */
-/*                  Unix Implementation                                 */
-/* ==================================================================== */
-#if defined(__unix__) || defined(unix)
-
-#include <dlfcn.h>
-
-/************************************************************************/
-/*                            GBGetSymbol()                             */
-/*                                                                      */
-/*      Note that this function doesn't:                                */
-/*       o prevent the reference count on the library from going up     */
-/*         for every request, or given any opportunity to unload        */
-/*         the library.                                                 */
-/*       o Attempt to look for the library in non-standard              */
-/*         locations.                                                   */
-/*       o Attempt to try variations on the symbol name, like           */
-/*         pre-pending or post-pending an underscore.                   */
-/************************************************************************/
-
-void *GBGetSymbol( const char * pszLibrary, const char * pszSymbolName )
-
-{
-    void *pLibrary;
-    void *pSymbol;
-
-    pLibrary = dlopen(pszLibrary, RTLD_LAZY);
-    if( pLibrary == NULL )
-    {
-        return NULL;
-    }
-
-    pSymbol = dlsym( pLibrary, pszSymbolName );
-
-    if( pSymbol == NULL )
-    {
-        fprintf( stderr, "GBGetSymbol(): %s\n", dlerror() );
-        return NULL;
-    }
-
-    return( pSymbol );
-}
-
-#endif /* def __unix__ && defined(HAVE_DLFCN_H) */
-
-/* ==================================================================== */
-/*                 Windows Implementation                               */
-/* ==================================================================== */
-#ifdef _WIN32
-
-#include <windows.h>
-
-/************************************************************************/
-/*                             GBGetSymbol()                            */
-/*                                                                      */
-/*      Note that this function doesn't:                                */
-/*       o prevent the reference count on the library from going up     */
-/*         for every request, or given any opportunity to unload        */
-/*         the library.                                                 */
-/*       o Attempt to look for the library in non-standard              */
-/*         locations.                                                   */
-/*       o Attempt to try variations on the symbol name, like           */
-/*         pre-pending or post-pending an underscore.                   */
-/************************************************************************/
-
-void *GBGetSymbol( const char * pszLibrary, const char * pszSymbolName )
-
-{
-    void *pLibrary;
-    void *pSymbol;
-
-    pLibrary = LoadLibrary(pszLibrary);
-    if( pLibrary == NULL )
-    {
-        return NULL;
-    }
-
-    pSymbol = GetProcAddress( (HINSTANCE) pLibrary, pszSymbolName );
-
-    if( pSymbol == NULL )
-    {
-        fprintf( stderr,
-                 "GBGetSymbol(): Can't find requested entry point: %s\n",
-                 pszSymbolName );
-        return NULL;
-    }
-
-    return( pSymbol );
-}
-
-#endif /* def _WIN32 */
-
diff --git a/bridge/gdalbridge.cpp b/bridge/gdalbridge.cpp
deleted file mode 100644
index 9b0a5e9..0000000
--- a/bridge/gdalbridge.cpp
+++ /dev/null
@@ -1,520 +0,0 @@
-/******************************************************************************
- * $Id: gdalbridge.cpp 33713 2016-03-12 17:41:57Z goatbar $
- *
- * Project:  GDAL Bridge
- * Purpose:  Implementation of GDALBridgeInitialize()
- * Author:   Frank Warmerdam, warmerda at home.com
- *
- * Adapted from cplgetsymbol.cpp.
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-/* ==================================================================== */
-/*      We #define GDAL_ENTRY to nothing so that when the include 	*/
-/*	file is include the real definition of the function pointer     */
-/*      variables will occur in this files object file.                 */
-/* ==================================================================== */
-
-#define GDAL_ENTRY
-#define GDAL_NULL	= NULL
-
-#include "gdalbridge.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef _WIN32
-#define PATH_SEP '\\'
-static const char *papszSOFilenames[] = {
-	 "gdal11.dll"
-	,"gdal.1.0.dll"
-	, NULL };
-#else
-#define PATH_SEP '/'
-static const char *papszSOFilenames[] = {
-	 "libgdal.1.1.so"
-	,"gdal.1.0.so"
-	,"gdal.so.1.0"
-	,"libgdal.so.1"
-	, NULL };
-#endif
-
-#define MAX_SYMBOL	1024
-
-/************************************************************************/
-/*                          GBGetSymbolCheck()                          */
-/*                                                                      */
-/*      Get a symbol, and on error add the missing entry point to a     */
-/*      list of missing entry points.                                   */
-/************************************************************************/
-
-static void *GBGetSymbolCheck( const char *pszLibrary,
-                               const char *pszSymbolName,
-                               char **papszErrorList )
-
-{
-    void	*pReturn;
-
-    pReturn = GBGetSymbol( pszLibrary, pszSymbolName );
-
-    if( pReturn == NULL && papszErrorList != NULL )
-    {
-        int	i;
-
-        for( i = 0; papszErrorList[i] != NULL; i++ ) {}
-
-        if( i < MAX_SYMBOL-1 )
-        {
-            papszErrorList[i] = CPLStrdup( pszSymbolName );
-            papszErrorList[i+1] = NULL;
-        }
-    }
-
-    return pReturn;
-}
-
-/************************************************************************/
-/*                        GDALBridgeInitialize()                        */
-/************************************************************************/
-
-int GDALBridgeInitialize( const char * pszTargetDir, FILE *fpReportFailure )
-
-{
-    char	szPath[2048];
-    void	*pfnTest = NULL;
-    int		iSOFile;
-    char        *apszFailed[MAX_SYMBOL];
-
-/* -------------------------------------------------------------------- */
-/*      Do we want to force reporting on?                               */
-/* -------------------------------------------------------------------- */
-    if( fpReportFailure == NULL
-        && (getenv("CPL_DEBUG") != NULL || getenv("GB_DEBUG") != NULL) )
-    {
-        fpReportFailure = stderr;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      The first phase is to try and find the shared library.          */
-/* -------------------------------------------------------------------- */
-    for( iSOFile = 0;
-         papszSOFilenames[iSOFile] != NULL && pfnTest == NULL;
-         iSOFile++ )
-    {
-        if( pszTargetDir != NULL )
-        {
-            sprintf( szPath, "%s%c%s",
-                     pszTargetDir, PATH_SEP, papszSOFilenames[iSOFile] );
-            pfnTest = GBGetSymbol( szPath, "GDALOpen" );
-        }
-
-        if( pfnTest == NULL && getenv( "GDAL_HOME" ) != NULL )
-        {
-            sprintf( szPath,
-                     "%s%c%s", getenv("GDAL_HOME"),
-                     PATH_SEP, papszSOFilenames[iSOFile] );
-            pfnTest = GBGetSymbol( szPath, "GDALOpen" );
-        }
-
-        if( pfnTest == NULL )
-        {
-            sprintf( szPath, papszSOFilenames[iSOFile] );
-            pfnTest = GBGetSymbol( szPath, "GDALOpen" );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Did we fail to even find the DLL/.so?                           */
-/* -------------------------------------------------------------------- */
-    if( pfnTest == NULL )
-    {
-
-        if( fpReportFailure == NULL )
-            return FALSE;
-
-
-        fprintf( fpReportFailure,
-                 "GBBridgeInitialize() failed to find an suitable GDAL .DLL/.so file.\n" );
-        fprintf( fpReportFailure,
-                 "The following filenames were searched for:\n" );
-
-        for( iSOFile = 0; papszSOFilenames[iSOFile] != NULL; iSOFile++ )
-            fprintf( fpReportFailure, "  o %s\n", papszSOFilenames[iSOFile] );
-
-        fprintf( fpReportFailure, "\n" );
-        fprintf( fpReportFailure, "The following locations were searched:\n" );
-
-        if( pszTargetDir != NULL )
-            fprintf( fpReportFailure, "  o %s\n", pszTargetDir );
-
-        if( getenv( "GDAL_HOME" ) != NULL )
-            fprintf( fpReportFailure, "  o %s\n", getenv( "GDAL_HOME" ) );
-
-        fprintf( fpReportFailure, "  o System default locations.\n" );
-        fprintf( fpReportFailure, "\n" );
-
-        fprintf( fpReportFailure, "\n" );
-#ifdef __unix__
-        if( getenv("LD_LIBRARY_PATH") != NULL )
-        {
-            fprintf( fpReportFailure,
-                     "System default locations may be influenced by:\n" );
-            fprintf( fpReportFailure,
-                     "LD_LIBRARY_PATH = %s\n", getenv("LD_LIBRARY_PATH") );
-        }
-#else
-        if( getenv("PATH") != NULL )
-        {
-            fprintf( fpReportFailure,
-                     "System default locations may be influenced by:\n" );
-            fprintf( fpReportFailure,
-                     "PATH = %s\n", getenv("PATH") );
-        }
-#endif
-
-        return FALSE;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Start loading functions.                                        */
-/* -------------------------------------------------------------------- */
-    apszFailed[0] = NULL;
-
-    GDALGetDataTypeSize = (int (*)(GDALDataType))
-        GBGetSymbolCheck( szPath, "GDALGetDataTypeSize", apszFailed );
-
-    GDALAllRegister = (void (*)(void))
-        GBGetSymbolCheck( szPath, "GDALAllRegister", apszFailed );
-
-    GDALCreate = (GDALDatasetH (*)(GDALDriverH, const char *, int, int, int,
-                                   GDALDataType, char ** ))
-        GBGetSymbolCheck( szPath, "GDALCreate", apszFailed );
-
-    GDALOpen = (GDALDatasetH (*)(const char *, GDALAccess))
-        GBGetSymbolCheck( szPath, "GDALOpen", apszFailed );
-
-    GDALGetDriverByName = (GDALDriverH (*)(const char *))
-        GBGetSymbolCheck( szPath, "GDALGetDriverByName", apszFailed );
-
-    GDALGetDriverShortName = (const char *(*)(GDALDriverH))
-        GBGetSymbolCheck( szPath, "GDALGetDriverShortName", apszFailed );
-
-    GDALGetDriverLongName = (const char *(*)(GDALDriverH))
-        GBGetSymbolCheck( szPath, "GDALGetDriverLongName", apszFailed );
-
-    GDALGetDatasetDriver = (GDALDriverH (*)(GDALDatasetH))
-        GBGetSymbolCheck( szPath, "GDALGetDatasetDriver", apszFailed );
-
-    GDALClose = (void (*)(GDALDatasetH))
-        GBGetSymbolCheck( szPath, "GDALClose", apszFailed );
-
-    GDALGetRasterXSize = (int (*)(GDALDatasetH))
-        GBGetSymbolCheck( szPath, "GDALGetRasterXSize", apszFailed );
-
-    GDALGetRasterYSize = (int (*)(GDALDatasetH))
-        GBGetSymbolCheck( szPath, "GDALGetRasterYSize", apszFailed );
-
-    GDALGetRasterCount = (int (*)(GDALDatasetH))
-        GBGetSymbolCheck( szPath, "GDALGetRasterCount", apszFailed );
-
-    GDALGetRasterBand = (GDALRasterBandH (*)(GDALDatasetH, int))
-        GBGetSymbolCheck( szPath, "GDALGetRasterBand", apszFailed );
-
-    GDALGetProjectionRef = (const char *(*)(GDALDatasetH))
-        GBGetSymbolCheck( szPath, "GDALGetProjectionRef", apszFailed );
-
-    GDALSetProjection = (CPLErr (*)(GDALDatasetH, const char *))
-        GBGetSymbolCheck( szPath, "GDALSetProjection", apszFailed );
-
-    GDALGetGeoTransform = (CPLErr (*)(GDALDatasetH, double *))
-        GBGetSymbolCheck( szPath, "GDALGetGeoTransform", apszFailed );
-
-    GDALSetGeoTransform = (CPLErr (*)(GDALDatasetH, double *))
-        GBGetSymbolCheck( szPath, "GDALSetGeoTransform", apszFailed );
-
-    GDALGetInternalHandle = (void *(*)(GDALDatasetH, const char *))
-        GBGetSymbolCheck( szPath, "GDALGetInternalHandle", apszFailed );
-
-    GDALGetGCPCount = (int (*)(GDALDatasetH))
-        GBGetSymbolCheck( szPath, "GDALGetGCPCount", apszFailed );
-
-    GDALGetGCPProjection = (const char *(*)(GDALDatasetH))
-        GBGetSymbolCheck( szPath, "GDALGetGCPProjection", apszFailed );
-
-    GDALGetGCPs = (const GDAL_GCP *(*)(GDALDatasetH))
-        GBGetSymbolCheck( szPath, "GDALGetGCPs", apszFailed );
-
-    GDALGetRasterDataType = (GDALDataType (*)(GDALRasterBandH))
-        GBGetSymbolCheck( szPath, "GDALGetRasterDataType", apszFailed );
-
-    GDALGetRasterBandXSize = (int (*)(GDALRasterBandH))
-        GBGetSymbolCheck( szPath, "GDALGetRasterBandXSize", apszFailed );
-
-    GDALGetRasterBandYSize = (int (*)(GDALRasterBandH))
-        GBGetSymbolCheck( szPath, "GDALGetRasterBandYSize", apszFailed );
-
-    GDALGetBlockSize = (void (*)(GDALRasterBandH, int *, int *))
-        GBGetSymbolCheck( szPath, "GDALGetBlockSize", apszFailed );
-
-    GDALRasterIO = (CPLErr (*)(GDALRasterBandH, GDALRWFlag, int, int, int, int,
-                               void *, int, int, GDALDataType, int, int ))
-        GBGetSymbolCheck( szPath, "GDALRasterIO", apszFailed );
-
-    GDALReadBlock = (CPLErr (*)(GDALRasterBandH, int, int, void *))
-        GBGetSymbolCheck( szPath, "GDALReadBlock", apszFailed );
-
-    GDALWriteBlock = (CPLErr (*)(GDALRasterBandH, int, int, void *))
-        GBGetSymbolCheck( szPath, "GDALWriteBlock", apszFailed );
-
-    GDALGetOverviewCount = (int (*)(GDALRasterBandH))
-        GBGetSymbolCheck( szPath, "GDALGetOverviewCount", apszFailed );
-
-    GDALGetOverview = (GDALRasterBandH (*)(GDALRasterBandH, int))
-        GBGetSymbolCheck( szPath, "GDALGetOverview", apszFailed );
-
-    GDALGetRasterNoDataValue = (double (*)(GDALRasterBandH, int*))
-        GBGetSymbolCheck( szPath, "GDALGetRasterNoDataValue", apszFailed );
-
-    GDALSetRasterNoDataValue = (CPLErr (*)(GDALRasterBandH, double))
-        GBGetSymbolCheck( szPath, "GDALSetRasterNoDataValue", apszFailed );
-
-    GDALFillRaster = (CPLErr (*)(GDALRasterBandH, double, double))
-        GBGetSymbolCheck( szPath, "GDALFillRaster", apszFailed );
-
-    GDALGetRasterMinimum = (double (*)(GDALRasterBandH, int *))
-        GBGetSymbolCheck( szPath, "GDALGetRasterMinimum", apszFailed );
-
-    GDALGetRasterMaximum = (double (*)(GDALRasterBandH, int *))
-        GBGetSymbolCheck( szPath, "GDALGetRasterMaximum", apszFailed );
-
-    GDALComputeRasterMinMax = (void (*)(GDALRasterBandH, int, double *))
-        GBGetSymbolCheck( szPath, "GDALComputeRasterMinMax", apszFailed );
-
-    GDALGetRasterColorInterpretation = (GDALColorInterp (*)(GDALRasterBandH))
-        GBGetSymbolCheck( szPath, "GDALGetRasterColorInterpretation", apszFailed );
-
-    GDALGetColorInterpretationName = (const char *(*)(GDALColorInterp))
-        GBGetSymbolCheck( szPath, "GDALGetColorInterpretationName", apszFailed );
-
-    GDALGetRasterColorTable = (GDALColorTableH (*)(GDALRasterBandH))
-        GBGetSymbolCheck( szPath, "GDALGetRasterColorTable", apszFailed );
-
-    GDALDecToDMS = (const char *(*)(double, const char *, int ))
-        GBGetSymbolCheck( szPath, "GDALDecToDMS", apszFailed );
-
-    GDALGetPaletteInterpretation = (GDALPaletteInterp (*)(GDALColorTableH))
-        GBGetSymbolCheck( szPath, "GDALGetPaletteInterpretation", apszFailed );
-
-    GDALGetPaletteInterpretationName = (const char *(*)(GDALPaletteInterp))
-        GBGetSymbolCheck( szPath, "GDALGetPaletteInterpretationName", apszFailed );
-
-    GDALGetColorEntryCount = (int (*)(GDALColorTableH))
-        GBGetSymbolCheck( szPath, "GDALGetColorEntryCount", apszFailed );
-
-    GDALGetColorEntry = (const GDALColorEntry *(*)(GDALColorTableH,int))
-        GBGetSymbolCheck( szPath, "GDALGetColorEntry", apszFailed );
-
-    GDALGetColorEntryAsRGB = (int (*)(GDALColorTableH,int,
-                                      GDALColorEntry*))
-        GBGetSymbolCheck( szPath, "GDALGetColorEntryAsRGB", apszFailed );
-
-    GDALSetColorEntry = (void (*)(GDALColorTableH, int, const GDALColorEntry*))
-        GBGetSymbolCheck( szPath, "GDALSetColorEntry", apszFailed );
-
-/* -------------------------------------------------------------------- */
-/*      GDALMajorObject                                                 */
-/* -------------------------------------------------------------------- */
-    GDALGetMetadata = (char **(*)(GDALMajorObjectH, const char *))
-        GBGetSymbolCheck( szPath, "GDALGetMetadata", apszFailed );
-
-    GDALSetMetadata = (CPLErr(*)(GDALMajorObjectH, char **, const char *))
-        GBGetSymbolCheck( szPath, "GDALSetMetadata", apszFailed );
-
-    GDALGetMetadataItem = (const char *(*)(GDALMajorObjectH, const char *,
-                                           const char *))
-        GBGetSymbolCheck( szPath, "GDALGetMetadataItem", apszFailed );
-
-    GDALSetMetadataItem = (CPLErr (*)(GDALMajorObjectH, const char *,
-                                      const char *, const char *))
-        GBGetSymbolCheck( szPath, "GDALSetMetadataItem", apszFailed );
-
-/* -------------------------------------------------------------------- */
-/*      CPL                                                             */
-/* -------------------------------------------------------------------- */
-    CPLErrorReset = (void (*)())
-        GBGetSymbolCheck( szPath, "CPLErrorReset", apszFailed );
-
-    CPLGetLastErrorNo = (int (*)())
-        GBGetSymbolCheck( szPath, "CPLGetLastErrorNo", apszFailed );
-
-    CPLGetLastErrorType = (CPLErr (*)())
-        GBGetSymbolCheck( szPath, "CPLGetLastErrorType", apszFailed );
-
-    CPLGetLastErrorMsg = (const char *(*)())
-        GBGetSymbolCheck( szPath, "CPLGetLastErrorMsg", apszFailed );
-
-    CPLPushErrorHandler = (void (*)(CPLErrorHandler))
-        GBGetSymbolCheck( szPath, "CPLPushErrorHandler", apszFailed );
-
-    CPLPopErrorHandler = (void (*)())
-        GBGetSymbolCheck( szPath, "CPLPopErrorHandler", apszFailed );
-
-/* -------------------------------------------------------------------- */
-/*      OSR API                                                         */
-/* -------------------------------------------------------------------- */
-    OSRNewSpatialReference = (OGRSpatialReferenceH (*)( const char * ))
-        GBGetSymbolCheck( szPath, "OSRNewSpatialReference", apszFailed );
-
-    OSRCloneGeogCS = (OGRSpatialReferenceH (*)(OGRSpatialReferenceH))
-        GBGetSymbolCheck( szPath, "OSRCloneGeogCS", apszFailed );
-
-    OSRDestroySpatialReference = (void (*)(OGRSpatialReferenceH))
-        GBGetSymbolCheck( szPath, "OSRDestroySpatialReference", apszFailed );
-
-    OSRReference = (int (*)(OGRSpatialReferenceH))
-        GBGetSymbolCheck( szPath, "OSRReference", apszFailed );
-
-    OSRDereference = (int (*)(OGRSpatialReferenceH))
-        GBGetSymbolCheck( szPath, "OSRDereference", apszFailed );
-
-    OSRImportFromEPSG = (OGRErr (*)(OGRSpatialReferenceH,int))
-        GBGetSymbolCheck( szPath, "OSRImportFromEPSG", apszFailed );
-
-    OSRImportFromWkt = (OGRErr (*)(OGRSpatialReferenceH,char **))
-        GBGetSymbolCheck( szPath, "OSRImportFromWkt", apszFailed );
-
-    OSRImportFromProj4 = (OGRErr (*)(OGRSpatialReferenceH,const char *))
-        GBGetSymbolCheck( szPath, "OSRImportFromProj4", apszFailed );
-
-    OSRExportToWkt = (OGRErr (*)(OGRSpatialReferenceH, char **))
-        GBGetSymbolCheck( szPath, "OSRExportToWkt", apszFailed );
-
-    OSRExportToPrettyWkt = (OGRErr (*)(OGRSpatialReferenceH, char **, int))
-        GBGetSymbolCheck( szPath, "OSRExportToPrettyWkt", apszFailed );
-
-    OSRExportToProj4 = (OGRErr (*)(OGRSpatialReferenceH, char **))
-        GBGetSymbolCheck( szPath, "OSRExportToProj4", apszFailed );
-
-    OSRSetAttrValue = (OGRErr (*)(OGRSpatialReferenceH, const char *,
-                                  const char *))
-        GBGetSymbolCheck( szPath, "OSRSetAttrValue", apszFailed );
-
-    OSRGetAttrValue = (const char *(*)(OGRSpatialReferenceH, const char *,int))
-        GBGetSymbolCheck( szPath, "OSRGetAttrValue", apszFailed );
-
-    OSRSetLinearUnits = (OGRErr (*)(OGRSpatialReferenceH, const char *,double))
-        GBGetSymbolCheck( szPath, "OSRSetLinearUnits", apszFailed );
-
-    OSRGetLinearUnits = (double (*)(OGRSpatialReferenceH, char **))
-        GBGetSymbolCheck( szPath, "OSRGetLinearUnits", apszFailed );
-
-    OSRIsGeographic = (int (*)(OGRSpatialReferenceH))
-        GBGetSymbolCheck( szPath, "OSRIsGeographic", apszFailed );
-
-    OSRIsProjected = (int (*)(OGRSpatialReferenceH))
-        GBGetSymbolCheck( szPath, "OSRIsProjected", apszFailed );
-
-    OSRIsSameGeogCS = (int (*)(OGRSpatialReferenceH,OGRSpatialReferenceH))
-        GBGetSymbolCheck( szPath, "OSRIsSameGeogCS", apszFailed );
-
-    OSRIsSame = (int (*)(OGRSpatialReferenceH,OGRSpatialReferenceH))
-        GBGetSymbolCheck( szPath, "OSRIsSame", apszFailed );
-
-    OSRSetProjCS = (OGRErr (*)(OGRSpatialReferenceH,const char*))
-        GBGetSymbolCheck( szPath, "OSRSetProjCS", apszFailed );
-
-    OSRSetWellKnownGeogCS = (OGRErr (*)(OGRSpatialReferenceH, const char *))
-        GBGetSymbolCheck( szPath, "OSRSetWellKnownGeogCS", apszFailed );
-
-    OSRSetGeogCS = (OGRErr (*)( OGRSpatialReferenceH hSRS,
-                                const char * pszGeogName,
-                                const char * pszDatumName,
-                                const char * pszEllipsoidName,
-                                double dfSemiMajor, double dfInvFlattening,
-                                const char * pszPMName /* = NULL */,
-                                double dfPMOffset /* = 0.0 */,
-                                const char * pszUnits /* = NULL */,
-                                double dfConvertToRadians /* = 0.0 */ ))
-        GBGetSymbolCheck( szPath, "OSRSetGeogCS", apszFailed );
-
-    OSRGetSemiMajor = (double (*)(OGRSpatialReferenceH, OGRErr *))
-        GBGetSymbolCheck( szPath, "OSRGetSemiMajor", apszFailed );
-
-    OSRGetSemiMinor = (double (*)(OGRSpatialReferenceH, OGRErr *))
-        GBGetSymbolCheck( szPath, "OSRGetSemiMinor", apszFailed );
-
-    OSRGetInvFlattening = (double (*)(OGRSpatialReferenceH, OGRErr *))
-        GBGetSymbolCheck( szPath, "OSRGetInvFlattening", apszFailed );
-
-    OSRSetAuthority = (OGRErr (*)(OGRSpatialReferenceH, const char *,
-                                  const char *, int))
-        GBGetSymbolCheck( szPath, "OSRSetAuthority", apszFailed );
-
-    OSRSetProjParm = (OGRErr (*)(OGRSpatialReferenceH, const char *, double))
-        GBGetSymbolCheck( szPath, "OSRSetProjParm", apszFailed );
-
-    OSRGetProjParm = (double (*)(OGRSpatialReferenceH, const char *,
-                                 double, OGRErr *))
-        GBGetSymbolCheck( szPath, "OSRGetProjParm", apszFailed );
-
-    OSRSetUTM = (OGRErr (*)(OGRSpatialReferenceH, int, int))
-        GBGetSymbolCheck( szPath, "OSRSetUTM", apszFailed );
-
-    OSRGetUTMZone = (int (*)(OGRSpatialReferenceH, int *))
-        GBGetSymbolCheck( szPath, "OSRGetUTMZone", apszFailed );
-
-    OCTNewCoordinateTransformation = (OGRCoordinateTransformationH
-                     (*)(OGRSpatialReferenceH, OGRSpatialReferenceH))
-        GBGetSymbolCheck( szPath, "OCTNewCoordinateTransformation",apszFailed);
-
-    OCTDestroyCoordinateTransformation =
-        (void (*)(OGRCoordinateTransformationH))
-        GBGetSymbolCheck( szPath, "OCTDestroyCoordinateTransformation",
-                          apszFailed );
-
-    OCTTransform = (int (*)(OGRCoordinateTransformationH, int,
-                            double *, double *, double *))
-        GBGetSymbolCheck( szPath, "OCTTransform", apszFailed );
-
-/* -------------------------------------------------------------------- */
-/*      Did we fail to find any entry points?                           */
-/* -------------------------------------------------------------------- */
-    if( apszFailed[0] != NULL && fpReportFailure != NULL )
-    {
-        int	iError;
-
-        fprintf( fpReportFailure,
-                 "While a GDAL .DLL/.so was found at `%s'\n"
-                 "it appears to be missing the following entry points.\n"
-                 "Consider upgrading to a more recent GDAL library.\n",
-                 szPath );
-
-        for( iError = 0; apszFailed[iError] != NULL; iError++ )
-        {
-            fprintf( fpReportFailure, "  o %s\n", apszFailed[iError] );
-            CPLFree( apszFailed[iError] );
-        }
-    }
-
-    return apszFailed[0] == NULL;
-}
diff --git a/bridge/gdalbridge.h b/bridge/gdalbridge.h
deleted file mode 100644
index 57f9f97..0000000
--- a/bridge/gdalbridge.h
+++ /dev/null
@@ -1,721 +0,0 @@
-/******************************************************************************
- * $Id: gdalbridge.h 33713 2016-03-12 17:41:57Z goatbar $
- *
- * Project:  GDAL Bridge
- * Purpose:  Declarations for GDAL Bridge support.
- * Author:   Frank Warmerdam, warmerda at home.com
- *
- * This file needs to be kept up to date with the contents of gdal.h by hand.
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef GDALBRIDGE_H_INCLUDED
-#define GDALBRIDGE_H_INCLUDED
-
-/* -------------------------------------------------------------------- */
-/*      Start C context.                                                */
-/* -------------------------------------------------------------------- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdio.h>
-
-/* ==================================================================== */
-/*      Standard types and defines normally supplied by cpl_port.h.     */
-/* ==================================================================== */
-#if UINT_MAX == 65535
-typedef long            GInt32;
-typedef unsigned long   GUInt32;
-#else
-typedef int             GInt32;
-typedef unsigned int    GUInt32;
-#endif
-
-typedef short           GInt16;
-typedef unsigned short  GUInt16;
-typedef unsigned char   GByte;
-typedef int             GBool;
-
-#ifndef FALSE
-#  define FALSE		0
-#  define TRUE		1
-#endif
-
-#ifndef NULL
-#  define NULL		0
-#endif
-
-#ifndef GDAL_ENTRY
-#  define GDAL_ENTRY extern
-#  define GDAL_NULL
-#endif
-
-/* -------------------------------------------------------------------- */
-/*      Significant constants.                                          */
-/* -------------------------------------------------------------------- */
-
-/*! Pixel data types */
-typedef enum {
-    /*! Unknown or unspecified type */ 		    GDT_Unknown = 0,
-    /*! Eight bit unsigned integer */ 		    GDT_Byte = 1,
-    /*! Sixteen bit unsigned integer */         GDT_UInt16 = 2,
-    /*! Sixteen bit signed integer */           GDT_Int16 = 3,
-    /*! Thirty two bit unsigned integer */      GDT_UInt32 = 4,
-    /*! Thirty two bit signed integer */        GDT_Int32 = 5,
-    /*! Thirty two bit floating point */        GDT_Float32 = 6,
-    /*! Sixty four bit floating point */        GDT_Float64 = 7,
-    /*! Complex Int16 */                        GDT_CInt16 = 8,
-    /*! Complex Int32 */                        GDT_CInt32 = 9,
-    /*! Complex Float32 */                      GDT_CFloat32 = 10,
-    /*! Complex Float64 */                      GDT_CFloat64 = 11,
-    GDT_TypeCount = 12		/* maximum type # + 1 */
-} GDALDataType;
-
-GDAL_ENTRY int	(*pfnGDALGetDataTypeSize)( GDALDataType ) GDAL_NULL;
-#define GDALGetDataTypeSize pfnGDALGetDataTypeSize
-
-typedef enum {
-    GA_ReadOnly = 0,
-    GA_Update = 1
-} GDALAccess;
-
-typedef enum {
-    GF_Read = 0,
-    GF_Write = 1
-} GDALRWFlag;
-
-/*! Types of color interpretation for raster bands. */
-typedef enum
-{
-    GCI_Undefined=0,
-    /*! Greyscale */                                      GCI_GrayIndex=1,
-    /*! Paletted (see associated color table) */          GCI_PaletteIndex=2,
-    /*! Red band of RGBA image */                         GCI_RedBand=3,
-    /*! Green band of RGBA image */                       GCI_GreenBand=4,
-    /*! Blue band of RGBA image */                        GCI_BlueBand=5,
-    /*! Alpha (0=transparent, 255=opaque) */              GCI_AlphaBand=6,
-    /*! Hue band of HLS image */                          GCI_HueBand=7,
-    /*! Saturation band of HLS image */                   GCI_SaturationBand=8,
-    /*! Lightness band of HLS image */                    GCI_LightnessBand=9,
-    /*! Cyan band of CMYK image */                        GCI_CyanBand=10,
-    /*! Magenta band of CMYK image */                     GCI_MagentaBand=11,
-    /*! Yellow band of CMYK image */                      GCI_YellowBand=12,
-    /*! Black band of CMLY image */                       GCI_BlackBand=13
-} GDALColorInterp;
-
-/*! Types of color interpretations for a GDALColorTable. */
-typedef enum
-{
-  /*! Grayscale (in GDALColorEntry.c1) */                      GPI_Gray=0,
-  /*! Red, Green, Blue and Alpha in (in c1, c2, c3 and c4) */  GPI_RGB=1,
-  /*! Cyan, Magenta, Yellow and Black (in c1, c2, c3 and c4)*/ GPI_CMYK=2,
-  /*! Hue, Lightness and Saturation (in c1, c2, and c3) */     GPI_HLS=3
-} GDALPaletteInterp;
-
-/* -------------------------------------------------------------------- */
-/*      GDAL Specific error codes.                                      */
-/*                                                                      */
-/*      error codes 100 to 299 reserved for GDAL.                       */
-/* -------------------------------------------------------------------- */
-typedef enum
-{
-    CE_None = 0,
-    CE_Log = 1,
-    CE_Warning = 2,
-    CE_Failure = 3,
-    CE_Fatal = 4
-
-} CPLErr;
-
-#define CPLE_AppDefined			1
-#define CPLE_OutOfMemory		2
-#define CPLE_FileIO			3
-#define CPLE_OpenFailed			4
-#define CPLE_IllegalArg			5
-#define CPLE_NotSupported		6
-#define CPLE_AssertionFailed		7
-#define CPLE_NoWriteAccess		8
-
-#define CPLE_WrongFormat	200
-
-typedef int OGRErr;
-
-#define OGRERR_NONE                0
-#define OGRERR_NOT_ENOUGH_DATA     1    /* not enough data to deserialize */
-#define OGRERR_NOT_ENOUGH_MEMORY   2
-#define OGRERR_UNSUPPORTED_GEOMETRY_TYPE 3
-#define OGRERR_UNSUPPORTED_OPERATION 4
-#define OGRERR_CORRUPT_DATA        5
-#define OGRERR_FAILURE             6
-#define OGRERR_UNSUPPORTED_SRS     7
-
-/* -------------------------------------------------------------------- */
-/*      Important CPL Functions.                                        */
-/* -------------------------------------------------------------------- */
-typedef void (*CPLErrorHandler)(CPLErr, int, const char*);
-
-GDAL_ENTRY void (*pfnCPLErrorReset)() GDAL_NULL;
-#define CPLErrorReset pfnCPLErrorReset
-
-GDAL_ENTRY int (*pfnCPLGetLastErrorNo)() GDAL_NULL;
-#define CPLGetLastErrorNo pfnCPLGetLastErrorNo
-
-GDAL_ENTRY CPLErr (*pfnCPLGetLastErrorType)() GDAL_NULL;
-#define CPLGetLastErrorType pfnCPLGetLastErrorType
-
-GDAL_ENTRY const char *(*pfnCPLGetLastErrorMsg)() GDAL_NULL;
-#define CPLGetLastErrorMsg pfnCPLGetLastErrorMsg
-
-GDAL_ENTRY void (*pfnCPLPushErrorHandler)( CPLErrorHandler ) GDAL_NULL;
-#define CPLPushErrorHandler pfnCPLPushErrorHandler
-
-GDAL_ENTRY void (*pfnCPLPopErrorHandler)() GDAL_NULL;
-#define CPLPopErrorHandler pfnCPLPopErrorHandler
-
-/* -------------------------------------------------------------------- */
-/*      Define handle types related to various internal classes.        */
-/* -------------------------------------------------------------------- */
-
-typedef void *GDALMajorObjectH;
-typedef void *GDALDatasetH;
-typedef void *GDALRasterBandH;
-typedef void *GDALDriverH;
-typedef void *GDALColorTableH;
-typedef void *OGRSpatialReferenceH;
-typedef void *OGRCoordinateTransformationH;
-
-/* ==================================================================== */
-/*      GDAL_GCP                                                        */
-/* ==================================================================== */
-
-/** Ground Control Point */
-typedef struct
-{
-    /** Unique identifier, often numeric */
-    char	*pszId;
-
-    /** Informational message or "" */
-    char	*pszInfo;
-
-    /** Pixel (x) location of GCP on raster */
-    double 	dfGCPPixel;
-    /** Line (y) location of GCP on raster */
-    double	dfGCPLine;
-
-    /** X position of GCP in georeferenced space */
-    double	dfGCPX;
-
-    /** Y position of GCP in georeferenced space */
-    double	dfGCPY;
-
-    /** Elevation of GCP, or zero if not known */
-    double	dfGCPZ;
-} GDAL_GCP;
-
-/* ==================================================================== */
-/*      Registration/driver related.                                    */
-/* ==================================================================== */
-
-GDAL_ENTRY void (*pfnGDALAllRegister)( void ) GDAL_NULL;
-#define GDALAllRegister pfnGDALAllRegister
-
-GDAL_ENTRY GDALDatasetH (*pfnGDALCreate)( GDALDriverH hDriver, const char *,
-                                          int, int, int, GDALDataType,
-                                          char ** ) GDAL_NULL;
-#define GDALCreate pfnGDALCreate
-
-
-GDAL_ENTRY GDALDatasetH (*pfnGDALOpen)( const char *, GDALAccess ) GDAL_NULL;
-#define GDALOpen pfnGDALOpen
-
-GDAL_ENTRY GDALDriverH (*pfnGDALGetDriverByName)( const char * ) GDAL_NULL;
-#define GDALGetDriverByName pfnGDALGetDriverByName
-
-GDAL_ENTRY const char *(*pfnGDALGetDriverShortName)(GDALDriverH) GDAL_NULL;
-#define GDALGetDriverShortName pfnGDALGetDriverShortName
-
-GDAL_ENTRY const char *(*pfnGDALGetDriverLongName)(GDALDriverH) GDAL_NULL;
-#define GDALGetDriverLongName pfnGDALGetDriverLongName
-
-GDAL_ENTRY GDALDriverH (*pfnGDALIdentifyDriver)( const char *, char ** ) GDAL_NULL;
-#define GDALIdentifyDriver pfnGDALIdentifyDriver
-
-/* ==================================================================== */
-/*      GDALMajorObject                                                 */
-/* ==================================================================== */
-
-GDAL_ENTRY char **(*pfnGDALGetMetadata)( GDALMajorObjectH,
-                                         const char * ) GDAL_NULL;
-#define GDALGetMetadata pfnGDALGetMetadata
-
-GDAL_ENTRY CPLErr (*pfnGDALSetMetadata)( GDALMajorObjectH, char **,
-                                         const char * ) GDAL_NULL;
-#define GDALSetMetadata pfnGDALSetMetadata
-
-GDAL_ENTRY const char *(*pfnGDALGetMetadataItem)( GDALMajorObjectH,
-                                      const char *, const char * ) GDAL_NULL;
-#define GDALGetMetadataItem pfnGDALGetMetadataItem
-
-GDAL_ENTRY CPLErr (*pfnGDALSetMetadataItem)( GDALMajorObjectH,
-                                             const char *, const char *,
-                                             const char * ) GDAL_NULL;
-#define GDALSetMetadataItem pfnGDALSetMetadataItem
-
-GDAL_ENTRY const char *(*pfnGDALGetDescription)( GDALMajorObjectH ) GDAL_NULL;
-#define GDALGetDescription pfnGDALGetDescription
-
-/* ==================================================================== */
-/*      GDALDataset class ... normally this represents one file.        */
-/* ==================================================================== */
-
-GDAL_ENTRY void (*pfnGDALClose)( GDALDatasetH ) GDAL_NULL;
-#define GDALClose pfnGDALClose
-
-GDAL_ENTRY GDALDriverH (*pfnGDALGetDatasetDriver)( GDALDatasetH ) GDAL_NULL;
-#define GDALGetDatasetDriver pfnGDALGetDatasetDriver
-
-GDAL_ENTRY int (*pfnGDALGetRasterXSize)( GDALDatasetH ) GDAL_NULL;
-#define GDALGetRasterXSize pfnGDALGetRasterXSize
-
-GDAL_ENTRY int (*pfnGDALGetRasterYSize)( GDALDatasetH ) GDAL_NULL;
-#define GDALGetRasterYSize pfnGDALGetRasterYSize
-
-GDAL_ENTRY int (*pfnGDALGetRasterCount)( GDALDatasetH ) GDAL_NULL;
-#define GDALGetRasterCount pfnGDALGetRasterCount
-
-GDAL_ENTRY GDALRasterBandH
-               (*pfnGDALGetRasterBand)( GDALDatasetH, int) GDAL_NULL;
-#define GDALGetRasterBand pfnGDALGetRasterBand
-
-GDAL_ENTRY const char *(*pfnGDALGetProjectionRef)( GDALDatasetH ) GDAL_NULL;
-#define GDALGetProjectionRef pfnGDALGetProjectionRef
-
-GDAL_ENTRY CPLErr (*pfnGDALSetProjection)( GDALDatasetH,
-                                           const char * ) GDAL_NULL;
-#define GDALSetProjection pfnGDALSetProjection
-
-GDAL_ENTRY CPLErr (*pfnGDALGetGeoTransform)( GDALDatasetH, double* ) GDAL_NULL;
-#define GDALGetGeoTransform pfnGDALGetGeoTransform
-
-GDAL_ENTRY CPLErr (*pfnGDALSetGeoTransform)( GDALDatasetH, double* ) GDAL_NULL;
-#define GDALSetGeoTransform pfnGDALSetGeoTransform
-
-GDAL_ENTRY void *(*pfnGDALGetInternalHandle)( GDALDatasetH,
-                                              const char * ) GDAL_NULL;
-#define GDALGetInternalHandle pfnGDALGetInternalHandle
-
-GDAL_ENTRY int (*pfnGDALGetGCPCount)( GDALDatasetH ) GDAL_NULL;
-#define GDALGetGCPCount pfnGDALGetGCPCount
-
-GDAL_ENTRY const char *(*pfnGDALGetGCPProjection)( GDALDatasetH ) GDAL_NULL;
-#define GDALGetGCPProjection pfnGDALGetGCPProjection
-
-GDAL_ENTRY const GDAL_GCP *(*pfnGDALGetGCPs)( GDALDatasetH ) GDAL_NULL;
-#define GDALGetGCPs pfnGDALGetGCPs
-
-/* ==================================================================== */
-/*      GDALRasterBand ... one band/channel in a dataset.               */
-/* ==================================================================== */
-
-GDAL_ENTRY GDALDataType (*pGDALGetRasterDataType)( GDALRasterBandH ) GDAL_NULL;
-#define GDALGetRasterDataType pGDALGetRasterDataType
-
-GDAL_ENTRY void (*pGDALGetBlockSize)( GDALRasterBandH,
-                                      int * pnXSize, int * pnYSize ) GDAL_NULL;
-#define GDALGetBlockSize pGDALGetBlockSize
-
-GDAL_ENTRY CPLErr (*pGDALRasterIO)( GDALRasterBandH hRBand, GDALRWFlag eRWFlag,
-                                    int nDSXOff, int nDSYOff,
-                                    int nDSXSize, int nDSYSize,
-                                    void * pBuffer, int nBXSize, int nBYSize,
-                                    GDALDataType eBDataType,
-                                   int nPixelSpace, int nLineSpace ) GDAL_NULL;
-#define GDALRasterIO pGDALRasterIO
-
-GDAL_ENTRY CPLErr (*pGDALReadBlock)( GDALRasterBandH,
-                                     int, int, void * ) GDAL_NULL;
-#define GDALReadBlock pGDALReadBlock
-
-GDAL_ENTRY CPLErr (*pGDALWriteBlock)( GDALRasterBandH,
-                                      int, int, void * ) GDAL_NULL;
-#define GDALWriteBlock pGDALWriteBlock
-
-GDAL_ENTRY int (*pGDALGetOverviewCount)( GDALRasterBandH ) GDAL_NULL;
-#define GDALGetOverviewCount pGDALGetOverviewCount
-
-GDAL_ENTRY GDALRasterBandH (*pGDALGetOverview)( GDALRasterBandH, int ) GDAL_NULL;
-#define GDALGetOverview pGDALGetOverview
-
-GDAL_ENTRY double (*pGDALGetRasterNoDataValue)( GDALRasterBandH, int * )
-    GDAL_NULL;
-#define GDALGetRasterNoDataValue pGDALGetRasterNoDataValue
-
-GDAL_ENTRY CPLErr (*pGDALSetRasterNoDataValue)( GDALRasterBandH, double )
-    GDAL_NULL;
-#define GDALSetRasterNoDataValue pGDALSetRasterNoDataValue
-
-GDAL_ENTRY CPLErr (*pGDALFillRaster)( GDALRasterBandH, double, double )
-    GDAL_NULL;
-#define GDALFillRaster pGDALFillRaster
-
-GDAL_ENTRY double (*pGDALGetRasterMinimum)( GDALRasterBandH, int * ) GDAL_NULL;
-#define GDALGetRasterMinimum pGDALGetRasterMinimum
-
-GDAL_ENTRY double (*pGDALGetRasterMaximum)( GDALRasterBandH, int * ) GDAL_NULL;
-#define GDALGetRasterMaximum pGDALGetRasterMaximum
-
-GDAL_ENTRY void (*pGDALComputeRasterMinMax)( GDALRasterBandH, int,
-                                             double * ) GDAL_NULL;
-#define GDALComputeRasterMinMax pGDALComputeRasterMinMax
-
-GDAL_ENTRY GDALColorInterp (*pGDALGetRasterColorInterpretation)
-						( GDALRasterBandH ) GDAL_NULL;
-#define GDALGetRasterColorInterpretation pGDALGetRasterColorInterpretation
-
-GDAL_ENTRY const char *(*pGDALGetColorInterpretationName)( GDALColorInterp ) GDAL_NULL;
-#define GDALGetColorInterpretationName pGDALGetColorInterpretationName
-
-GDAL_ENTRY GDALColorTableH (*pGDALGetRasterColorTable)( GDALRasterBandH ) GDAL_NULL;
-#define GDALGetRasterColorTable pGDALGetRasterColorTable
-
-GDAL_ENTRY int (*pfnGDALGetRasterBandXSize)( GDALRasterBandH ) GDAL_NULL;
-#define GDALGetRasterBandXSize pfnGDALGetRasterBandXSize
-
-GDAL_ENTRY int (*pfnGDALGetRasterBandYSize)( GDALRasterBandH ) GDAL_NULL;
-#define GDALGetRasterBandYSize pfnGDALGetRasterBandYSize
-
-/* ==================================================================== */
-/*      Color tables.                                                   */
-/* ==================================================================== */
-/** Color tuple */
-typedef struct
-{
-    /*! gray, red, cyan or hue */
-    short      c1;
-
-    /*! green, magenta, or lightness */
-    short      c2;
-
-    /*! blue, yellow, or saturation */
-    short      c3;
-
-    /*! alpha or blackband */
-    short      c4;
-} GDALColorEntry;
-
-GDAL_ENTRY GDALPaletteInterp (*pGDALGetPaletteInterpretation)( GDALColorTableH ) GDAL_NULL;
-#define GDALGetPaletteInterpretation pGDALGetPaletteInterpretation
-
-GDAL_ENTRY const char *(*pGDALGetPaletteInterpretationName)(GDALPaletteInterp) GDAL_NULL;
-#define GDALGetPaletteInterpretationName pGDALGetPaletteInterpretationName
-
-GDAL_ENTRY int (*pGDALGetColorEntryCount)( GDALColorTableH ) GDAL_NULL;
-#define GDALGetColorEntryCount pGDALGetColorEntryCount
-
-GDAL_ENTRY const GDALColorEntry *(*pGDALGetColorEntry)( GDALColorTableH, int ) GDAL_NULL;
-#define GDALGetColorEntry pGDALGetColorEntry
-
-GDAL_ENTRY int (*pGDALGetColorEntryAsRGB)( GDALColorTableH, int,
-                                           GDALColorEntry *) GDAL_NULL;
-#define GDALGetColorEntryAsRGB pGDALGetColorEntryAsRGB
-
-GDAL_ENTRY void (*pGDALSetColorEntry)( GDALColorTableH, int,
-                                       const GDALColorEntry * ) GDAL_NULL;
-#define GDALSetColorEntry pGDALSetColorEntry
-
-/* ==================================================================== */
-/*      Projections                                                     */
-/* ==================================================================== */
-
-GDAL_ENTRY const char *(*pGDALDecToDMS)( double, const char *, int ) GDAL_NULL;
-#define GDALDecToDMS pGDALDecToDMS
-
-/* -------------------------------------------------------------------- */
-/*      ogr_srs_api.h services.                                         */
-/* -------------------------------------------------------------------- */
-
-GDAL_ENTRY OGRSpatialReferenceH
-	(*pOSRNewSpatialReference)( const char * ) GDAL_NULL;
-#define OSRNewSpatialReference pOSRNewSpatialReference
-
-GDAL_ENTRY OGRSpatialReferenceH
-	(*pOSRCloneGeogCS)( OGRSpatialReferenceH ) GDAL_NULL;
-#define OSRCloneGeogCS pOSRCloneGeogCS
-
-GDAL_ENTRY void
-	(*pOSRDestroySpatialReference)( OGRSpatialReferenceH ) GDAL_NULL;
-#define OSRDestroySpatialReference pOSRDestroySpatialReference
-
-GDAL_ENTRY int (*pOSRReference)( OGRSpatialReferenceH ) GDAL_NULL;
-#define OSRReference pOSRReference
-
-GDAL_ENTRY int (*pOSRDereference)( OGRSpatialReferenceH ) GDAL_NULL;
-#define OSRDereference pOSRDereference
-
-GDAL_ENTRY OGRErr (*pOSRImportFromEPSG)( OGRSpatialReferenceH, int ) GDAL_NULL;
-#define OSRImportFromEPSG pOSRImportFromEPSG
-
-GDAL_ENTRY OGRErr
-	(*pOSRImportFromWkt)( OGRSpatialReferenceH, char ** ) GDAL_NULL;
-#define OSRImportFromWkt pOSRImportFromWkt
-
-GDAL_ENTRY OGRErr
-	(*pOSRImportFromProj4)( OGRSpatialReferenceH, const char *) GDAL_NULL;
-#define OSRImportFromProj4 pOSRImportFromProj4
-
-GDAL_ENTRY OGRErr
-	(*pOSRExportToWkt)( OGRSpatialReferenceH, char ** ) GDAL_NULL;
-#define OSRExportToWkt pOSRExportToWkt
-
-GDAL_ENTRY OGRErr
-       (*pOSRExportToPrettyWkt)( OGRSpatialReferenceH, char **, int) GDAL_NULL;
-#define OSRExportToPrettyWkt pOSRExportToPrettyWkt
-
-GDAL_ENTRY OGRErr
-	(*pOSRExportToProj4)( OGRSpatialReferenceH, char **) GDAL_NULL;
-#define OSRExportToProj4 pOSRExportToProj4
-
-GDAL_ENTRY OGRErr
-	(*pOSRSetAttrValue)( OGRSpatialReferenceH hSRS,
-                             const char * pszNodePath,
-                             const char * pszNewNodeValue ) GDAL_NULL;
-#define OSRSetAttrValue pOSRSetAttrValue
-
-GDAL_ENTRY const char * (*pOSRGetAttrValue)( OGRSpatialReferenceH hSRS,
-                           const char * pszName, int iChild ) GDAL_NULL;
-#define OSRGetAttrValue pOSRGetAttrValue
-
-GDAL_ENTRY OGRErr (*pOSRSetLinearUnits)( OGRSpatialReferenceH, const char *,
-                                         double ) GDAL_NULL;
-#define OSRSetLinearUnits pOSRSetLinearUnits
-
-GDAL_ENTRY double (*pOSRGetLinearUnits)( OGRSpatialReferenceH,
-                                         char ** ) GDAL_NULL;
-#define OSRGetLinearUnits pOSRGetLinearUnits
-
-GDAL_ENTRY int (*pOSRIsGeographic)( OGRSpatialReferenceH ) GDAL_NULL;
-#define OSRIsGeographic pOSRIsGeographic
-
-GDAL_ENTRY int (*pOSRIsProjected)( OGRSpatialReferenceH ) GDAL_NULL;
-#define OSRIsProjected pOSRIsProjected
-
-GDAL_ENTRY int (*pOSRIsSameGeogCS)( OGRSpatialReferenceH,
-                                    OGRSpatialReferenceH ) GDAL_NULL;
-#define OSRIsSameGeogCS pOSRIsSameGeogCS
-
-GDAL_ENTRY int (*pOSRIsSame)( OGRSpatialReferenceH,
-                              OGRSpatialReferenceH ) GDAL_NULL;
-#define OSRIsSame pOSRIsSame
-
-GDAL_ENTRY OGRErr (*pOSRSetProjCS)( OGRSpatialReferenceH hSRS,
-                                    const char * pszName ) GDAL_NULL;
-#define OSRSetProjCS pOSRSetProjCS
-
-GDAL_ENTRY OGRErr (*pOSRSetWellKnownGeogCS)( OGRSpatialReferenceH hSRS,
-                                             const char * pszName ) GDAL_NULL;
-#define OSRSetWellKnownGeogCS pOSRSetWellKnownGeogCS
-
-GDAL_ENTRY OGRErr (*pOSRSetGeogCS)( OGRSpatialReferenceH hSRS,
-                      const char * pszGeogName,
-                      const char * pszDatumName,
-                      const char * pszEllipsoidName,
-                      double dfSemiMajor, double dfInvFlattening,
-                      const char * pszPMName /* = NULL */,
-                      double dfPMOffset /* = 0.0 */,
-                      const char * pszUnits /* = NULL */,
-                      double dfConvertToRadians /* = 0.0 */ ) GDAL_NULL;
-#define OSRSetGeogCS pOSRSetGeogCS
-
-GDAL_ENTRY double (*pOSRGetSemiMajor)( OGRSpatialReferenceH,
-                                       OGRErr * /* = NULL */ ) GDAL_NULL;
-#define OSRGetSemiMajor pOSRGetSemiMajor
-
-GDAL_ENTRY double (*pOSRGetSemiMinor)( OGRSpatialReferenceH,
-                                       OGRErr * /* = NULL */ ) GDAL_NULL;
-#define OSRGetSemiMinor pOSRGetSemiMinor
-
-GDAL_ENTRY double (*pOSRGetInvFlattening)( OGRSpatialReferenceH,
-                                           OGRErr * /*=NULL*/) GDAL_NULL;
-#define OSRGetInvFlattening pOSRGetInvFlattening
-
-GDAL_ENTRY OGRErr (*pOSRSetAuthority)( OGRSpatialReferenceH hSRS,
-                                       const char * pszTargetKey,
-                                       const char * pszAuthority,
-                                       int nCode ) GDAL_NULL;
-#define OSRSetAuthority pOSRSetAuthority
-
-GDAL_ENTRY OGRErr (*pOSRSetProjParm)( OGRSpatialReferenceH,
-                                      const char *, double ) GDAL_NULL;
-#define OSRSetProjParm pOSRSetProjParm
-
-GDAL_ENTRY double (*pOSRGetProjParm)( OGRSpatialReferenceH hSRS,
-                                      const char * pszParmName,
-                                      double dfDefault /* = 0.0 */,
-                                      OGRErr * /* = NULL */ ) GDAL_NULL;
-#define OSRGetProjParm pOSRGetProjParm
-
-GDAL_ENTRY OGRErr (*pOSRSetUTM)( OGRSpatialReferenceH hSRS,
-                                 int nZone, int bNorth ) GDAL_NULL;
-#define OSRSetUTM pOSRSetUTM
-
-GDAL_ENTRY int (*pOSRGetUTMZone)( OGRSpatialReferenceH hSRS,
-                                  int *pbNorth ) GDAL_NULL;
-#define OSRGetUTMZone pOSRGetUTMZone
-
-GDAL_ENTRY OGRCoordinateTransformationH (*pOCTNewCoordinateTransformation)
-    			( OGRSpatialReferenceH hSourceSRS,
-                          OGRSpatialReferenceH hTargetSRS ) GDAL_NULL;
-#define OCTNewCoordinateTransformation pOCTNewCoordinateTransformation
-
-GDAL_ENTRY void (*pOCTDestroyCoordinateTransformation)
-			( OGRCoordinateTransformationH ) GDAL_NULL;
-#define OCTDestroyCoordinateTransformation pOCTDestroyCoordinateTransformation
-
-GDAL_ENTRY int (*pOCTTransform)( OGRCoordinateTransformationH hCT,
-                                 int nCount, double *x, double *y,
-                                 double *z ) GDAL_NULL;
-#define OCTTransform pOCTTransform
-
-/* ==================================================================== */
-/*      Some "standard" strings.                                        */
-/* ==================================================================== */
-#ifndef SRS_PT_ALBERS_CONIC_EQUAL_AREA
-
-#define SRS_PT_ALBERS_CONIC_EQUAL_AREA                                  \
-                                "Albers_Conic_Equal_Area"
-#define SRS_PT_AZIMUTHAL_EQUIDISTANT "Azimuthal_Equidistant"
-#define SRS_PT_CASSINI_SOLDNER  "Cassini_Soldner"
-#define SRS_PT_CYLINDRICAL_EQUAL_AREA "Cylindrical_Equal_Area"
-#define SRS_PT_ECKERT_IV        "Eckert_IV"
-#define SRS_PT_ECKERT_VI        "Eckert_VI"
-#define SRS_PT_EQUIDISTANT_CONIC "Equidistant_Conic"
-#define SRS_PT_EQUIRECTANGULAR  "Equirectangular"
-#define SRS_PT_GALL_STEREOGRAPHIC "Gall_Stereographic"
-#define SRS_PT_GNOMONIC         "Gnomonic"
-#define SRS_PT_HOTINE_OBLIQUE_MERCATOR                                  \
-                                "Hotine_Oblique_Mercator"
-#define SRS_PT_LABORDE_OBLIQUE_MERCATOR                                 \
-                                "Laborde_Oblique_Mercator"
-#define SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP                              \
-                                "Lambert_Conformal_Conic_1SP"
-#define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP                              \
-                                "Lambert_Conformal_Conic_2SP"
-#define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM                      \
-                                "Lambert_Conformal_Conic_2SP_Belgium)"
-#define SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA                     \
-                                "Lambert_Azimuthal_Equal_Area"
-#define SRS_PT_MERCATOR_1SP     "Mercator_1SP"
-#define SRS_PT_MERCATOR_2SP     "Mercator_2SP"
-#define SRS_PT_MILLER_CYLINDRICAL "Miller_Cylindrical"
-#define SRS_PT_MOLLWEIDE        "Mollweide"
-#define SRS_PT_NEW_ZEALAND_MAP_GRID                                     \
-                                "New_Zealand_Map_Grid"
-#define SRS_PT_OBLIQUE_STEREOGRAPHIC                                    \
-                                "Oblique_Stereographic"
-#define SRS_PT_ORTHOGRAPHIC     "Orthographic"
-#define SRS_PT_POLAR_STEREOGRAPHIC                                      \
-                                "Polar_Stereographic"
-#define SRS_PT_POLYCONIC        "Polyconic"
-#define SRS_PT_ROBINSON         "Robinson"
-#define SRS_PT_SINUSOIDAL       "Sinusoidal"
-#define SRS_PT_STEREOGRAPHIC    "Stereographic"
-#define SRS_PT_SWISS_OBLIQUE_CYLINDRICAL                                \
-                                "Swiss_Oblique_Cylindrical"
-#define SRS_PT_TRANSVERSE_MERCATOR                                      \
-                                "Transverse_Mercator"
-#define SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED                       \
-                                "Transverse_Mercator_South_Orientated"
-#define SRS_PT_TUNISIA_MINING_GRID                                      \
-                                "Tunisia_Mining_Grid"
-#define SRS_PT_VANDERGRINTEN    "VanDerGrinten"
-
-#define SRS_PP_CENTRAL_MERIDIAN         "central_meridian"
-#define SRS_PP_SCALE_FACTOR             "scale_factor"
-#define SRS_PP_STANDARD_PARALLEL_1      "standard_parallel_1"
-#define SRS_PP_STANDARD_PARALLEL_2      "standard_parallel_2"
-#define SRS_PP_LONGITUDE_OF_CENTER      "longitude_of_center"
-#define SRS_PP_LATITUDE_OF_CENTER       "latitude_of_center"
-#define SRS_PP_LONGITUDE_OF_ORIGIN      "longitude_of_origin"
-#define SRS_PP_LATITUDE_OF_ORIGIN       "latitude_of_origin"
-#define SRS_PP_FALSE_EASTING            "false_easting"
-#define SRS_PP_FALSE_NORTHING           "false_northing"
-#define SRS_PP_AZIMUTH                  "azimuth"
-#define SRS_PP_LONGITUDE_OF_POINT_1     "longitude_of_point_1"
-#define SRS_PP_LATITUDE_OF_POINT_1      "latitude_of_point_1"
-#define SRS_PP_LONGITUDE_OF_POINT_2     "longitude_of_point_2"
-#define SRS_PP_LATITUDE_OF_POINT_2      "latitude_of_point_2"
-#define SRS_PP_LONGITUDE_OF_POINT_3     "longitude_of_point_3"
-#define SRS_PP_LATITUDE_OF_POINT_3      "latitude_of_point_3"
-#define SRS_PP_RECTIFIED_GRID_ANGLE     "rectified_grid_angle"
-#define SRS_PP_LANDSAT_NUMBER           "landsat_number"
-#define SRS_PP_PATH_NUMBER              "path_number"
-#define SRS_PP_PERSPECTIVE_POINT_HEIGHT "perspective_point_height"
-#define SRS_PP_FIPSZONE                 "fipszone"
-#define SRS_PP_ZONE                     "zone"
-
-#define SRS_UL_METER            "Meter"
-#define SRS_UL_FOOT             "Foot (International)" /* or just "FOOT"? */
-#define SRS_UL_FOOT_CONV                    "0.3048"
-#define SRS_UL_US_FOOT          "U.S. Foot" /* or "US survey foot" */
-#define SRS_UL_US_FOOT_CONV                 "0.3048006"
-#define SRS_UL_NAUTICAL_MILE    "Nautical Mile"
-#define SRS_UL_NAUTICAL_MILE_CONV           "1852.0"
-#define SRS_UL_LINK             "Link"          /* Based on US Foot */
-#define SRS_UL_LINK_CONV                    "0.20116684023368047"
-#define SRS_UL_CHAIN            "Chain"         /* based on US Foot */
-#define SRS_UL_CHAIN_CONV                   "2.0116684023368047"
-#define SRS_UL_ROD              "Rod"           /* based on US Foot */
-#define SRS_UL_ROD_CONV                     "5.02921005842012"
-
-#define SRS_UA_DEGREE           "degree"
-#define SRS_UA_DEGREE_CONV                  "0.0174532925199433"
-#define SRS_UA_RADIAN           "radian"
-
-#define SRS_PM_GREENWICH        "Greenwich"
-
-#define SRS_DN_NAD27            "North American Datum 1927"
-#define SRS_DN_NAD83            "North American Datum 1983"
-#define SRS_DN_WGS84            "World Geodetic System 1984"
-
-#define SRS_WGS84_SEMIMAJOR     6378137.0
-#define SRS_WGS84_INVFLATTENING 298.257223563
-
-#endif
-
-/* -------------------------------------------------------------------- */
-/*      This is the real entry point.  It tries to load the shared      */
-/*      libraries (given a hint of a directory it might be in).  It     */
-/*      returns TRUE if it succeeds, or FALSE otherwise.                */
-/* -------------------------------------------------------------------- */
-int	GDALBridgeInitialize( const char *, FILE * );
-void	*GBGetSymbol( const char *, const char * );
-
-/* -------------------------------------------------------------------- */
-/*      Terminate C context.                                            */
-/* -------------------------------------------------------------------- */
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ndef GDALBRIDGE_H_INCLUDED */
diff --git a/ci/travis/android/before_install.sh b/ci/travis/android/before_install.sh
new file mode 100755
index 0000000..4649879
--- /dev/null
+++ b/ci/travis/android/before_install.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+set -e
+
+wget http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2
+tar xjf android-ndk-r9d-linux-x86_64.tar.bz2
+android-ndk-r9d/build/tools/make-standalone-toolchain.sh --system=linux-x86_64 --platform=android-8 --install-dir=$HOME/android-8-toolchain
diff --git a/ci/travis/android/install.sh b/ci/travis/android/install.sh
new file mode 100755
index 0000000..0a93622
--- /dev/null
+++ b/ci/travis/android/install.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -e
+
+export CCACHE_CPP2=yes
+
+unset CC
+unset CXX
+export PATH=$HOME/android-8-toolchain/bin:$PATH
+
+cd gdal
+CC="ccache arm-linux-androideabi-gcc" CXX="ccache arm-linux-androideabi-g++" CFLAGS="-mthumb" CXXFLAGS="-mthumb" LIBS="-lsupc++ -lstdc++" ./configure --host=arm-linux-androideabi
+make USER_DEFS="-Wextra -Werror" -j3
diff --git a/ci/travis/android/script.sh b/ci/travis/android/script.sh
new file mode 100755
index 0000000..ddb49c4
--- /dev/null
+++ b/ci/travis/android/script.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+set -e
+
+echo "finished"
diff --git a/ci/travis/big_endian/before_install.sh b/ci/travis/big_endian/before_install.sh
new file mode 100755
index 0000000..1d46a68
--- /dev/null
+++ b/ci/travis/big_endian/before_install.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+set -e
+
+wget https://releases.linaro.org/components/toolchain/binaries/5.1-2015.08/armeb-linux-gnueabihf/gcc-linaro-5.1-2015.08-x86_64_armeb-linux-gnueabihf.tar.xz
+tar xJf  gcc-linaro-5.1-2015.08-x86_64_armeb-linux-gnueabihf.tar.xz
diff --git a/ci/travis/big_endian/install.sh b/ci/travis/big_endian/install.sh
new file mode 100755
index 0000000..b38e910
--- /dev/null
+++ b/ci/travis/big_endian/install.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+set -e
+
+export PATH=$PWD/gcc-linaro-5.1-2015.08-x86_64_armeb-linux-gnueabihf/bin:$PATH
+unset CC
+unset CXX
+
+cd gdal
+export CCACHE_CPP2=yes
+CC="ccache armeb-linux-gnueabihf-gcc" CXX="ccache armeb-linux-gnueabihf-g++" ./configure --host=armeb-linux-gnueabihf --without-libtool
+make USER_DEFS="-Werror" -j3
+cd apps
+make USER_DEFS="-Werror" test_ogrsf
diff --git a/ci/travis/big_endian/script.sh b/ci/travis/big_endian/script.sh
new file mode 100755
index 0000000..ddb49c4
--- /dev/null
+++ b/ci/travis/big_endian/script.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+set -e
+
+echo "finished"
diff --git a/ci/travis/gcc48_stdcpp11/before_install.sh b/ci/travis/gcc48_stdcpp11/before_install.sh
new file mode 100755
index 0000000..ff90ed3
--- /dev/null
+++ b/ci/travis/gcc48_stdcpp11/before_install.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+set -e
+
+sudo mv /etc/apt/sources.list.d/pgdg* /tmp
+sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.1-postgis-2.2-scripts postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1
+sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
+sudo add-apt-repository -y ppa:marlam/gta
+#http://ubuntuhandbook.org/index.php/2013/08/install-gcc-4-8-via-ppa-in-ubuntu-12-04-13-04/
+sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
+sudo apt-get update -qq
+sudo apt-get install python-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjdk-7-jdk libepsilon-dev libgt [...]
+sudo apt-get install python-lxml
+sudo apt-get install python-pip
+sudo apt-get install libogdi3.2-dev
+# Boost for Mongo
+#sudo apt-get install libboost-regex-dev libboost-system-dev libboost-thread-dev
+sudo apt-get install gcc-4.8 g++-4.8
+#sudo pip install pyflakes
+#pyflakes autotest
+#pyflakes gdal/swig/python/scripts
+#pyflakes gdal/swig/python/samples
+psql -c "drop database if exists autotest" -U postgres
+psql -c "create database autotest" -U postgres
+psql -c "create extension postgis" -d autotest -U postgres
+mysql -e "create database autotest;"
+mysql -e "GRANT ALL ON autotest.* TO 'root'@'localhost';" -u root
+mysql -e "GRANT ALL ON autotest.* TO 'travis'@'localhost';" -u root
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/FileGDB_API_1_2-64.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libecwj2-ubuntu12.04-64bit.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libkml-r864-64bit.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+#wget http://even.rouault.free.fr/mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+tar xzf MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/include/* /usr/local/include
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/lib/* /usr/local/lib
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/include/* /usr/local/include
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/lib/* /usr/local/lib
+tar xzf FileGDB_API_1_2-64.tar.gz
+sudo cp -r FileGDB_API/include/* /usr/local/include
+sudo cp -r FileGDB_API/lib/* /usr/local/lib
+tar xzf install-libecwj2-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-libecwj2/include/* /usr/local/include
+sudo cp -r install-libecwj2/lib/* /usr/local/lib
+tar xzf install-libkml-r864-64bit.tar.gz
+sudo cp -r install-libkml/include/* /usr/local/include
+sudo cp -r install-libkml/lib/* /usr/local/lib
+tar xzf install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-openjpeg/include/* /usr/local/include
+sudo cp -r install-openjpeg/lib/* /usr/local/lib
+#tar xzf mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+#sudo cp -r mongo-cxx-1.0.2-install/include/* /usr/local/include
+#sudo cp -r mongo-cxx-1.0.2-install/lib/* /usr/local/lib
+wget https://bitbucket.org/chchrsc/kealib/get/c6d36f3db5e4.zip
+unzip c6d36f3db5e4.zip
+cd chchrsc-kealib-c6d36f3db5e4/trunk
+cmake . -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DHDF5_INCLUDE_DIR=/usr/include -DHDF5_LIB_PATH=/usr/lib -DLIBKEA_WITH_GDAL=OFF
+make -j4
+sudo make install
+cd ../..
+wget http://even.rouault.free.fr/install-pdfium-static-64bit.tar.bz2
+tar xjf install-pdfium-static-64bit.tar.bz2
+sudo cp -r install-pdfium-static/include/pdfium /usr/local/include
+sudo cp -r install-pdfium-static/lib/pdfium /usr/local/lib
+sudo ldconfig
diff --git a/ci/travis/gcc48_stdcpp11/install.sh b/ci/travis/gcc48_stdcpp11/install.sh
new file mode 100755
index 0000000..ea9fe69
--- /dev/null
+++ b/ci/travis/gcc48_stdcpp11/install.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+export CCACHE_CPP2=yes
+
+# Disable --with-fgdb=/usr/local since it causes /usr/local/include/GeodatabaseManagement.h:56:1: error: expected constructor, destructor, or type conversion before ‘(’ token EXT_FILEGDB_API fgdbError CreateGeodatabase(const std::wstring& path, Geodatabase& geodatabase);
+# Disable --with-mongocxx=/usr/local since it should also likely be compiled with C+11, but this fails because boost itself should probably be
+CC="ccache gcc-4.8 -std=c11" CXX="ccache g++-4.8 -std=c++11 -Wzero-as-null-pointer-constant -DNULL_AS_NULLPTR" ./configure --prefix=/usr --without-libtool --with-jpeg12 --with-python --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-gta --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local  --with-libkml --with-openjpeg=/usr/local --with-pdfium=/usr/local --ena [...]
+make USER_DEFS="-Wextra -Werror" -j3
+cd apps
+make USER_DEFS="-Wextra -Werror" test_ogrsf
+cd ..
+cd swig/java
+cat java.opt | sed "s/JAVA_HOME =.*/JAVA_HOME = \/usr\/lib\/jvm\/java-7-openjdk-amd64\//" > java.opt.tmp
+mv java.opt.tmp java.opt
+make
+cd ../..
+cd swig/perl
+make generate
+make
+cd ../..
+sudo rm -f /usr/lib/libgdal.so*
+sudo make install
+sudo ldconfig
+cd ../autotest/cpp
+make -j3
+cd ../../gdal
+wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/mdb-sqlite/mdb-sqlite-1.0.2.tar.bz2
+tar xjvf mdb-sqlite-1.0.2.tar.bz2
+sudo cp mdb-sqlite-1.0.2/lib/*.jar /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/ext
diff --git a/ci/travis/gcc48_stdcpp11/script.sh b/ci/travis/gcc48_stdcpp11/script.sh
new file mode 100755
index 0000000..4f6129a
--- /dev/null
+++ b/ci/travis/gcc48_stdcpp11/script.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+
+export GDAL_DRIVER_PATH=$PWD/frmts/pdf
+# Perl unit tests
+cd swig/perl
+make test
+cd ../..
+# Java unit tests
+cd swig/java
+make test
+cd ../..
+# CPP unit tests
+cd ../autotest
+cd cpp
+GDAL_SKIP=JP2ECW make quick_test
+# Compile and test vsipreload
+make vsipreload.so
+LD_PRELOAD=./vsipreload.so gdalinfo /vsicurl/http://download.osgeo.org/gdal/data/ecw/spif83.ecw
+LD_PRELOAD=./vsipreload.so sqlite3  /vsicurl/http://download.osgeo.org/gdal/data/sqlite3/polygon.db "select * from polygon limit 10"
+cd ..
+# Download a sample file
+mkdir -p ogr/tmp/cache/
+cd ogr/tmp/cache/
+wget http://download.osgeo.org/gdal/data/pgeo/PGeoTest.zip
+unzip PGeoTest.zip
+cd ../../..
+# Run ogr_fgdb.py in isolation from the rest
+#cd ogr
+#python ogr_fgdb.py
+#mkdir disabled
+#mv ogr_fgdb.* disabled
+#cd ..
+# Run ogr_pgeo.py in isolation from the rest
+cd ogr
+python ogr_pgeo.py
+mv ogr_pgeo.* disabled
+cd ..
+# Run all the Python autotests
+GDAL_SKIP="JP2ECW ECW" python run_all.py
+# A bit messy, but force testing with libspatialite 4.0dev (that has been patched a bit to remove any hard-coded SRS definition so it is very small)
+cd ogr
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/libspatialite4.0dev_ubuntu12.04-64bit_srs_stripped.tar.gz
+tar xzf libspatialite4.0dev_ubuntu12.04-64bit_srs_stripped.tar.gz
+ln -s install-libspatialite-4.0dev/lib/libspatialite.so.5.0.1 libspatialite.so.3
+LD_LIBRARY_PATH=$PWD python ogr_sqlite.py
+cd ..
diff --git a/ci/travis/gcc52_stdcpp14_sanitize/before_install.sh b/ci/travis/gcc52_stdcpp14_sanitize/before_install.sh
new file mode 100755
index 0000000..a1004ca
--- /dev/null
+++ b/ci/travis/gcc52_stdcpp14_sanitize/before_install.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+set -e
+
+sudo mv /etc/apt/sources.list.d/pgdg* /tmp
+sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.1-postgis-2.2-scripts postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1
+sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
+sudo add-apt-repository -y ppa:marlam/gta
+sudo apt-get update -qq
+sudo apt-get install python-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjdk-7-jdk libepsilon-dev libgt [...]
+sudo apt-get install python-lxml
+sudo apt-get install python-pip
+sudo apt-get install libogdi3.2-dev
+# Boost for Mongo
+#sudo apt-get install libboost-regex-dev libboost-system-dev libboost-thread-dev
+psql -c "drop database if exists autotest" -U postgres
+psql -c "create database autotest" -U postgres
+psql -c "create extension postgis" -d autotest -U postgres
+mysql -e "create database autotest;"
+mysql -e "GRANT ALL ON autotest.* TO 'root'@'localhost';" -u root
+mysql -e "GRANT ALL ON autotest.* TO 'travis'@'localhost';" -u root
+#wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/FileGDB_API_1_2-64.tar.gz
+#wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libecwj2-ubuntu12.04-64bit.tar.gz
+#wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libkml-r864-64bit.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+#wget http://even.rouault.free.fr/mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+wget http://even.rouault.free.fr/install-gcc-5.2.0.tar.bz2
+#tar xzf MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+#sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/include/* /usr/local/include
+#sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/lib/* /usr/local/lib
+#sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/include/* /usr/local/include
+#sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/lib/* /usr/local/lib
+#tar xzf FileGDB_API_1_2-64.tar.gz
+#sudo cp -r FileGDB_API/include/* /usr/local/include
+#sudo cp -r FileGDB_API/lib/* /usr/local/lib
+tar xzf install-libecwj2-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-libecwj2/include/* /usr/local/include
+sudo cp -r install-libecwj2/lib/* /usr/local/lib
+#tar xzf install-libkml-r864-64bit.tar.gz
+#sudo cp -r install-libkml/include/* /usr/local/include
+#sudo cp -r install-libkml/lib/* /usr/local/lib
+tar xzf install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-openjpeg/include/* /usr/local/include
+sudo cp -r install-openjpeg/lib/* /usr/local/lib
+#tar xzf mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+#sudo cp -r mongo-cxx-1.0.2-install/include/* /usr/local/include
+#sudo cp -r mongo-cxx-1.0.2-install/lib/* /usr/local/lib
+#wget https://bitbucket.org/chchrsc/kealib/get/c6d36f3db5e4.zip
+#unzip c6d36f3db5e4.zip
+#cd chchrsc-kealib-c6d36f3db5e4/trunk
+#cmake . -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DHDF5_INCLUDE_DIR=/usr/include -DHDF5_LIB_PATH=/usr/lib -DLIBKEA_WITH_GDAL=OFF
+#make -j4
+#sudo make install
+#cd ../..
+tar xjf install-gcc-5.2.0.tar.bz2
+export PATH=$PWD/install-gcc-5.2.0/bin:$PATH
+export LD_LIBRARY_PATH=$PWD/install-gcc-5.2.0/lib64
+export PRELOAD=$PWD/install-gcc-5.2.0/lib64/libasan.so.2.0.0:$PWD/install-gcc-5.2.0/lib64/libubsan.so.0.0.0
+#export PRELOAD=$PWD/install-gcc-5.2.0/lib64/libubsan.so.0.0.0
+export ASAN_OPTIONS=allocator_may_return_null=1 
+sudo ldconfig
diff --git a/ci/travis/gcc52_stdcpp14_sanitize/install.sh b/ci/travis/gcc52_stdcpp14_sanitize/install.sh
new file mode 100755
index 0000000..6d4ba32
--- /dev/null
+++ b/ci/travis/gcc52_stdcpp14_sanitize/install.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+set -e
+
+export PATH=$PWD/install-gcc-5.2.0/bin:$PATH
+export LD_LIBRARY_PATH=$PWD/install-gcc-5.2.0/lib64
+export PRELOAD=$PWD/install-gcc-5.2.0/lib64/libasan.so.2.0.0:$PWD/install-gcc-5.2.0/lib64/libubsan.so.0.0.0
+#export PRELOAD=$PWD/install-gcc-5.2.0/lib64/libubsan.so.0.0.0
+export ASAN_OPTIONS=allocator_may_return_null=1 
+
+cd gdal
+export CCACHE_CPP2=yes
+
+# Disable --with-fgdb=/usr/local since it causes /usr/local/include/GeodatabaseManagement.h:56:1: error: expected constructor, destructor, or type conversion before ‘(’ token EXT_FILEGDB_API fgdbError CreateGeodatabase(const std::wstring& path, Geodatabase& geodatabase);
+# Disable --with-mongocxx=/usr/local since it should also likely be compiled with C+11, but this fails because boost itself should probably be
+CC="ccache gcc" CXX="ccache g++ -std=c++14" CPPFLAGS="-DMAKE_SANITIZE_HAPPY -fsanitize=undefined -fsanitize=address" LDFLAGS="-fsanitize=undefined -fsanitize=address" ./configure --prefix=/usr --without-libtool --enable-debug --with-jpeg12 --with-poppler --without-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-epsilon --with-gta --with-ecw=/usr/local --with-openjpeg=/usr/local --with-libtiff=internal --with-rename-internal-libtiff-symbols --with-hide-internal-sym [...]
+make USER_DEFS="-Werror" -j3
+cd apps
+make USER_DEFS="-Werror" test_ogrsf
+cd ..
+cd swig/python
+CPPFLAGS="-fsanitize=undefined -fsanitize=address" python setup.py build
+cd ../..
+#cd swig/java
+#cat java.opt | sed "s/JAVA_HOME =.*/JAVA_HOME = \/usr\/lib\/jvm\/java-7-openjdk-amd64\//" > java.opt.tmp
+#mv java.opt.tmp java.opt
+#make
+#cd ../..
+#cd swig/perl
+#make generate
+#make
+#cd ../..
+sudo rm -f /usr/lib/libgdal.so*
+sudo make install
+cd swig/python
+sudo python setup.py install
+cd ../..
+sudo ldconfig
+#g++ -Wall -DDEBUG -fPIC -g ogr/ogrsf_frmts/null/ogrnulldriver.cpp  -shared -o ogr_NULL.so -L. -lgdal -Iport -Igcore -Iogr -Iogr/ogrsf_frmts
+#GDAL_DRIVER_PATH=$PWD ogr2ogr -f null null ../autotest/ogr/data/poly.shp
+cd ../autotest/cpp
+make -j3
+cd ../../gdal
+#wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/mdb-sqlite/mdb-sqlite-1.0.2.tar.bz2
+#tar xjvf mdb-sqlite-1.0.2.tar.bz2
+#sudo cp mdb-sqlite-1.0.2/lib/*.jar /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/ext
diff --git a/ci/travis/gcc52_stdcpp14_sanitize/script.sh b/ci/travis/gcc52_stdcpp14_sanitize/script.sh
new file mode 100755
index 0000000..e583c4d
--- /dev/null
+++ b/ci/travis/gcc52_stdcpp14_sanitize/script.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+set -e
+
+export PATH=$PWD/install-gcc-5.2.0/bin:$PATH
+export LD_LIBRARY_PATH=$PWD/install-gcc-5.2.0/lib64
+export PRELOAD=$PWD/install-gcc-5.2.0/lib64/libasan.so.2.0.0:$PWD/install-gcc-5.2.0/lib64/libubsan.so.0.0.0
+#export PRELOAD=$PWD/install-gcc-5.2.0/lib64/libubsan.so.0.0.0
+export ASAN_OPTIONS=allocator_may_return_null=1 
+
+cd gdal
+
+# Perl unit tests
+#cd swig/perl
+#make test
+#cd ../..
+# Java unit tests
+#cd swig/java
+#make test
+#cd ../..
+# CPP unit tests
+cd ../autotest
+#cd cpp
+#GDAL_SKIP=JP2ECW make quick_test
+# Compile and test vsipreload
+#make vsipreload.so
+#LD_PRELOAD=./vsipreload.so gdalinfo /vsicurl/http://download.osgeo.org/gdal/data/ecw/spif83.ecw
+#LD_PRELOAD=./vsipreload.so sqlite3  /vsicurl/http://download.osgeo.org/gdal/data/sqlite3/polygon.db "select * from polygon limit 10"
+#cd ..
+# Download a sample file
+#mkdir -p ogr/tmp/cache/
+#cd ogr/tmp/cache/
+#wget http://download.osgeo.org/gdal/data/pgeo/PGeoTest.zip
+#unzip PGeoTest.zip
+#cd ../../..
+# Run ogr_fgdb.py in isolation from the rest
+cd ogr
+#python ogr_fgdb.py
+mkdir disabled
+mv ogr_fgdb.* disabled
+cd ..
+# Run ogr_pgeo.py in isolation from the rest
+cd ogr
+#python ogr_pgeo.py
+mv ogr_pgeo.* disabled
+cd ..
+# Run all the Python autotests
+SKIP_MEM_INTENSIVE_TEST=YES SKIP_VIRTUALMEM=YES LD_PRELOAD=$PRELOAD ASAN_OPTIONS=detect_leaks=0 GDALTEST_ASAN_OPTIONS=detect_leaks=1,print_suppressions=0,suppressions=$PWD/asan_suppressions.txt python run_all.py -run_as_external
+# A bit messy, but force testing with libspatialite 4.0dev (that has been patched a bit to remove any hard-coded SRS definition so it is very small)
+#cd ogr
+#wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/libspatialite4.0dev_ubuntu12.04-64bit_srs_stripped.tar.gz
+#tar xzf libspatialite4.0dev_ubuntu12.04-64bit_srs_stripped.tar.gz
+#ln -s install-libspatialite-4.0dev/lib/libspatialite.so.5.0.1 libspatialite.so.3
+#LD_PRELOAD=$PRELOAD LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD python ogr_sqlite.py
+#cd ..
diff --git a/ci/travis/mingw/before_install.sh b/ci/travis/mingw/before_install.sh
new file mode 100755
index 0000000..4d605d3
--- /dev/null
+++ b/ci/travis/mingw/before_install.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -e
+
+sudo apt-get update -qq
+sudo apt-get install -qq ccache
+sudo apt-get install -qq wine swig curl
+sudo apt-get install -qq mingw32
diff --git a/ci/travis/mingw/install.sh b/ci/travis/mingw/install.sh
new file mode 100755
index 0000000..88671a8
--- /dev/null
+++ b/ci/travis/mingw/install.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+set -e
+
+export CCACHE_CPP2=yes
+
+curl http://download.osgeo.org/proj/proj-4.9.2.tar.gz > proj-4.9.2.tar.gz
+tar xvzf proj-4.9.2.tar.gz
+cd proj-4.9.2/nad
+curl http://download.osgeo.org/proj/proj-datumgrid-1.5.tar.gz > proj-datumgrid-1.5.tar.gz
+tar xvzf proj-datumgrid-1.5.tar.gz
+cd ..
+CC="ccache i586-mingw32msvc-gcc" CXX="ccache i586-mingw32msvc-g++" LD=i586-mingw32msvc-ld ./configure --host=i586-mingw32msvc
+make -j3
+cd ..
+# build GDAL
+cd gdal
+CC="ccache i586-mingw32msvc-gcc" CXX="ccache i586-mingw32msvc-g++" ./configure --enable-debug --host=i586-mingw32msvc
+LD=i586-mingw32msvc-ld make USER_DEFS="-Wextra -Werror" -j3
+cd apps
+LD=i586-mingw32msvc-ld make USER_DEFS="-Wextra -Werror" test_ogrsf.exe
+cd ..
+ln -sf $PWD/.libs/libgdal-20.dll $HOME/.wine/drive_c/windows
+#ln -sf /usr/lib/gcc/i686-w64-mingw32/4.6/libgcc_s_sjlj-1.dll $HOME/.wine/drive_c/windows
+#ln -sf /usr/lib/gcc/i686-w64-mingw32/4.6/libstdc++-6.dll $HOME/.wine/drive_c/windows
+ln -sf $PWD/../proj-4.9.2/src/.libs/libproj-9.dll $HOME/.wine/drive_c/windows
+wine apps/.libs/gdalinfo.exe  --version
+wget http://www.python.org/ftp/python/2.7.3/python-2.7.3.msi
+wine msiexec /i python-2.7.3.msi
+cd swig/python
+#sed "s/i586-mingw32msvc/i686-w64-mingw32/" < fallback_build_mingw32_under_unix.sh > tmp.sh
+#mv tmp.sh fallback_build_mingw32_under_unix.sh
+CXX=i586-mingw32msvc-g++ bash fallback_build_mingw32_under_unix.sh 
+cd ../..
diff --git a/ci/travis/mingw/script.sh b/ci/travis/mingw/script.sh
new file mode 100755
index 0000000..cbd0437
--- /dev/null
+++ b/ci/travis/mingw/script.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+
+cd ../autotest
+# Does not work under wine
+rm gcore/gdal_api_proxy.py
+rm gcore/rfc30.py
+
+# For some reason this crashes in the matrix .travis.yml but not in standalone branch
+rm pyscripts/test_gdal2tiles.py
+
+# Run all the Python autotests
+GDAL_DATA=$PWD/../gdal/data PYTHONPATH=$PWD/../gdal/swig/python/build/lib.win32-2.7 PATH=$PWD/../gdal:$PWD/../gdal/apps/.libs:$PWD:$PATH $HOME/.wine/drive_c/Python27/python.exe run_all.py
diff --git a/ci/travis/mingw_w64/before_install.sh b/ci/travis/mingw_w64/before_install.sh
new file mode 100755
index 0000000..73bf782
--- /dev/null
+++ b/ci/travis/mingw_w64/before_install.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+set -e
+
+cat /etc/apt/sources.list
+ls -al /etc/apt/sources.list.d
+sudo apt-get update -qq
+sudo apt-get install ccache
+sudo apt-get install binutils-mingw-w64-i686
+sudo apt-get install gcc-mingw-w64-i686
+sudo apt-get install g++-mingw-w64-i686
+sudo apt-get install g++-mingw-w64
+sudo apt-get install mingw-w64-tools
+sudo apt-get install -y wine1.4-amd64
diff --git a/ci/travis/mingw_w64/install.sh b/ci/travis/mingw_w64/install.sh
new file mode 100755
index 0000000..c816e6c
--- /dev/null
+++ b/ci/travis/mingw_w64/install.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+set -e
+
+export CCACHE_CPP2=yes
+
+wine64 cmd /c dir
+ln -s /usr/lib/gcc/x86_64-w64-mingw32/4.6/libstdc++-6.dll  $HOME/.wine/drive_c/windows
+ln -s /usr/lib/gcc/x86_64-w64-mingw32/4.6/libgcc_s_sjlj-1.dll  $HOME/.wine/drive_c/windows
+# build proj
+curl http://download.osgeo.org/proj/proj-4.9.2.tar.gz > proj-4.9.2.tar.gz
+tar xvzf proj-4.9.2.tar.gz
+cd proj-4.9.2/nad
+curl http://download.osgeo.org/proj/proj-datumgrid-1.5.tar.gz > proj-datumgrid-1.5.tar.gz
+tar xvzf proj-datumgrid-1.5.tar.gz
+cd ..
+CC="ccache x86_64-w64-mingw32-gcc" CXX="ccache x86_64-w64-mingw32-g++" LD=x86_64-w64-mingw32-ld ./configure --host=x86_64-w64-mingw32
+make -j3
+cd ..
+# build GDAL
+cd gdal
+CC="ccache x86_64-w64-mingw32-gcc" CXX="ccache x86_64-w64-mingw32-g++" ./configure --host=x86_64-w64-mingw32
+make USER_DEFS="-Wextra -Werror" -j3
+cd apps
+make USER_DEFS="-Wextra -Werror" test_ogrsf.exe
+cd ..
+ln -sf $PWD/.libs/libgdal-20.dll $HOME/.wine/drive_c/windows
+ln -sf $PWD/../proj-4.9.2/src/.libs/libproj-9.dll $HOME/.wine/drive_c/windows
+# Python bindings
+wget http://www.python.org/ftp/python/2.7.3/python-2.7.3.amd64.msi
+wine64 msiexec /i python-2.7.3.amd64.msi
+cd swig/python
+gendef $HOME/.wine/drive_c/Python27/python27.dll
+x86_64-w64-mingw32-dlltool --dllname $HOME/.wine/drive_c/Python27/python27.dll --input-def python27.def --output-lib $HOME/.wine/drive_c/Python27/libs/libpython27.a
+CXX=x86_64-w64-mingw32-g++ bash fallback_build_mingw32_under_unix.sh 
+cd ../..
diff --git a/ci/travis/mingw_w64/script.sh b/ci/travis/mingw_w64/script.sh
new file mode 100755
index 0000000..9758e30
--- /dev/null
+++ b/ci/travis/mingw_w64/script.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+
+wine64 apps/gdalinfo.exe --version
+cd ../autotest
+# Does not work under wine
+rm gcore/gdal_api_proxy.py
+rm gcore/rfc30.py
+
+# For some reason this crashes in the matrix .travis.yml but not in standalone branch
+rm pyscripts/test_gdal2tiles.py
+
+# Run all the Python autotests
+GDAL_DATA=$PWD/../gdal/data PYTHONPATH=$PWD/../gdal/swig/python/build/lib.win-amd64-2.7 PATH=$PWD/../gdal:$PWD/../gdal/apps/.libs:$PWD:$PATH $HOME/.wine/drive_c/Python27/python.exe run_all.py
diff --git a/ci/travis/osx/before_install.sh b/ci/travis/osx/before_install.sh
new file mode 100755
index 0000000..7ef1bad
--- /dev/null
+++ b/ci/travis/osx/before_install.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -e
+
+brew update
+brew uninstall postgis gdal
+brew install sqlite3
+brew install ccache
diff --git a/ci/travis/osx/install.sh b/ci/travis/osx/install.sh
new file mode 100755
index 0000000..4a9c508
--- /dev/null
+++ b/ci/travis/osx/install.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+set -e
+
+# build proj
+brew list --versions
+curl http://download.osgeo.org/proj/proj-4.9.3.tar.gz > proj-4.9.3.tar.gz
+tar xvzf proj-4.9.3.tar.gz
+cd proj-4.9.3/nad
+curl http://download.osgeo.org/proj/proj-datumgrid-1.5.tar.gz > proj-datumgrid-1.5.tar.gz
+tar xvzf proj-datumgrid-1.5.tar.gz
+cd ..
+./configure --prefix=$HOME/install-proj
+make -j3
+make install
+cd ..
+# build GDAL
+cd gdal
+CC="ccache gcc" CXX="ccache g++" ./configure --prefix=$HOME/install-gdal --enable-debug --with-jpeg12 --with-python --with-geotiff=internal --with-png=internal --with-static-proj4=$HOME/install-proj --with-sqlite3=/usr/local/opt/sqlite
+make USER_DEFS="-Wextra -Werror" -j3
+cd apps
+make USER_DEFS="-Wextra -Werror" test_ogrsf
+echo "Show which shared libs got used:"
+otool -L .libs/ogrinfo
+cd ..
+make install
+export PATH=$HOME/install-gdal/bin:$PWD/apps/.libs:$PATH
+export DYLD_LIBRARY_PATH=$HOME/install-gdal/lib
+export GDAL_DATA=$HOME/install-gdal/share/gdal
+export PYTHONPATH=$PWD/swig/python/build/lib.macosx-10.11-x86_64-2.7
+cd ../autotest/cpp
+echo $PATH
+#sudo rm -rf /usr/local/Cellar/gdal/1.10.1_1/*
+#sudo ln -s /usr/bin /usr/local/Cellar/gdal/1.10.1_1
+#sudo ln -s /usr/lib /usr/local/Cellar/gdal/1.10.1_1
+#sudo ln -s /usr/include /usr/local/Cellar/gdal/1.10.1_1
+#sudo mkdir /usr/local/Cellar/gdal/1.10.1_1/share
+#sudo ln -s /usr/share/gdal /usr/local/Cellar/gdal/1.10.1_1/share
+gdal-config --version
+gdal-config --cflags
+gdal-config --libs
+make -j3
+cd ../../gdal
diff --git a/ci/travis/osx/script.sh b/ci/travis/osx/script.sh
new file mode 100755
index 0000000..a35d576
--- /dev/null
+++ b/ci/travis/osx/script.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+# CPP unit tests
+cd ../autotest
+cd cpp
+GDAL_SKIP=JP2ECW make quick_test
+cd ..
+# Run all the Python autotests
+#make -j test
+python run_all.py
diff --git a/ci/travis/precise_32bit/before_install.sh b/ci/travis/precise_32bit/before_install.sh
new file mode 100755
index 0000000..9c2c41f
--- /dev/null
+++ b/ci/travis/precise_32bit/before_install.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+set -e
+
+export chroot="$PWD"/buildroot.i386
+mkdir -p "$chroot$PWD"
+sudo apt-get update
+sudo apt-get install -y debootstrap
+export LC_ALL=en_US
+sudo i386 debootstrap --arch=i386 precise "$chroot"
+sudo mount --rbind "$PWD" "$chroot$PWD"
+sudo mount --rbind /dev/pts "$chroot/dev/pts"
+sudo mount --rbind /proc "$chroot/proc"
+sudo su -c 'echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> buildroot.i386/etc/apt/sources.list'
+sudo i386 chroot "$chroot" apt-get update
+sudo i386 chroot "$chroot" apt-get install -y clang
+sudo i386 chroot "$chroot" apt-get install -y python-software-properties
+sudo i386 chroot "$chroot" add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
+sudo i386 chroot "$chroot" add-apt-repository -y ppa:marlam/gta
+sudo i386 chroot "$chroot" apt-get update
+# Disable postgresql since it draws ssl-cert that doesn't install cleanly
+# postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev
+sudo i386 chroot "$chroot" apt-get install -y python-numpy libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev libepsilon-dev libgta-dev liblcms2-2 libpcre3-dev libcrypto++-dev
+sudo i386 chroot "$chroot" apt-get install -y make
+sudo i386 chroot "$chroot" apt-get install -y python-dev
+sudo i386 chroot "$chroot" apt-get install -y g++
diff --git a/ci/travis/precise_32bit/install.sh b/ci/travis/precise_32bit/install.sh
new file mode 100755
index 0000000..8277507
--- /dev/null
+++ b/ci/travis/precise_32bit/install.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+set -e
+
+export chroot="$PWD"/buildroot.i386
+export LC_ALL=en_US
+
+sudo i386 chroot "$chroot" sh -c "cd $PWD/gdal && CC=clang CXX=clang ./configure --prefix=/usr --without-libtool --enable-debug --with-jpeg12 --with-python --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-epsilon --with-gta"
+sudo i386 chroot "$chroot" sh -c "cd $PWD/gdal && make USER_DEFS=-Werror -j3"
+sudo i386 chroot "$chroot" sh -c "cd $PWD/gdal/apps && make USER_DEFS=-Werror -j3 test_ogrsf"
+sudo i386 chroot "$chroot" sh -c "rm -f /usr/lib/libgdal.so*"
+sudo i386 chroot "$chroot" sh -c "cd $PWD/gdal && make install"
+sudo i386 chroot "$chroot" sh -c "sudo ldconfig"
+sudo i386 chroot "$chroot" sh -c "cd $PWD/autotest/cpp && make -j3"
\ No newline at end of file
diff --git a/ci/travis/precise_32bit/script.sh b/ci/travis/precise_32bit/script.sh
new file mode 100755
index 0000000..4263225
--- /dev/null
+++ b/ci/travis/precise_32bit/script.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -e
+
+export chroot="$PWD"/buildroot.i386
+export LC_ALL=en_US
+
+sudo i386 chroot "$chroot" sh -c "cd $PWD/autotest/cpp && make quick_test"
+# Compile and test vsipreload
+sudo i386 chroot "$chroot" sh -c "cd $PWD/autotest/cpp && make vsipreload.so"
+# Run all the Python autotests
+sudo i386 chroot "$chroot" sh -c "cd $PWD/autotest && python run_all.py"
diff --git a/ci/travis/precise_clang/before_install.sh b/ci/travis/precise_clang/before_install.sh
new file mode 100755
index 0000000..f958b20
--- /dev/null
+++ b/ci/travis/precise_clang/before_install.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+set -e
+
+sudo mv /etc/apt/sources.list.d/pgdg* /tmp
+sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.1-postgis-2.2-scripts postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1
+sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
+sudo add-apt-repository -y ppa:marlam/gta
+sudo apt-get update -qq
+sudo apt-get install ccache python-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjdk-7-jdk libepsilon-de [...]
+sudo apt-get install python-lxml
+sudo apt-get install python-pip
+sudo apt-get install libogdi3.2-dev
+# Boost for Mongo
+sudo apt-get install libboost-regex-dev libboost-system-dev libboost-thread-dev
+sudo pip install pyflakes
+sudo apt-get install doxygen texlive-latex-base
+pyflakes autotest
+pyflakes gdal/swig/python/scripts
+pyflakes gdal/swig/python/samples
+psql -c "drop database if exists autotest" -U postgres
+psql -c "create database autotest" -U postgres
+psql -c "create extension postgis" -d autotest -U postgres
+mysql -e "create database autotest;"
+mysql -e "GRANT ALL ON autotest.* TO 'root'@'localhost';" -u root
+mysql -e "GRANT ALL ON autotest.* TO 'travis'@'localhost';" -u root
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/FileGDB_API_1_2-64.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libecwj2-ubuntu12.04-64bit.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libkml-r864-64bit.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+wget http://even.rouault.free.fr/mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+tar xzf MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/include/* /usr/local/include
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/lib/* /usr/local/lib
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/include/* /usr/local/include
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/lib/* /usr/local/lib
+tar xzf FileGDB_API_1_2-64.tar.gz
+sudo cp -r FileGDB_API/include/* /usr/local/include
+sudo cp -r FileGDB_API/lib/* /usr/local/lib
+tar xzf install-libecwj2-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-libecwj2/include/* /usr/local/include
+sudo cp -r install-libecwj2/lib/* /usr/local/lib
+tar xzf install-libkml-r864-64bit.tar.gz
+sudo cp -r install-libkml/include/* /usr/local/include
+sudo cp -r install-libkml/lib/* /usr/local/lib
+tar xzf install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-openjpeg/include/* /usr/local/include
+sudo cp -r install-openjpeg/lib/* /usr/local/lib
+tar xzf mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+sudo cp -r mongo-cxx-1.0.2-install/include/* /usr/local/include
+sudo cp -r mongo-cxx-1.0.2-install/lib/* /usr/local/lib
+wget https://bitbucket.org/chchrsc/kealib/get/c6d36f3db5e4.zip
+unzip c6d36f3db5e4.zip
+cd chchrsc-kealib-c6d36f3db5e4/trunk
+cmake . -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DHDF5_INCLUDE_DIR=/usr/include -DHDF5_LIB_PATH=/usr/lib -DLIBKEA_WITH_GDAL=OFF
+make -j4
+sudo make install
+cd ../..
+sudo ldconfig
diff --git a/ci/travis/precise_clang/install.sh b/ci/travis/precise_clang/install.sh
new file mode 100755
index 0000000..8b2583e
--- /dev/null
+++ b/ci/travis/precise_clang/install.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+export CCACHE_CPP2=yes
+
+scripts/detect_tabulations.sh
+scripts/detect_printf.sh
+scripts/detect_self_assignment.sh
+
+CC="ccache clang" CXX="ccache clang" ./configure --prefix=/usr --without-libtool --without-cpp11 --enable-debug --with-jpeg12 --with-python --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-gta --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local --with-fgdb=/usr/local --with-libkml --with-openjpeg=/usr/local --with-mongocxx=/usr/local
+make docs >docs_log.txt 2>&1
+if cat docs_log.txt | grep -i warning | grep -v russian | grep -v brazilian; then echo "Doxygen warnings found" && cat docs_log.txt && /bin/false; else echo "No Doxygen warnings found"; fi
+make man >man_log.txt 2>&1
+if cat man_log.txt | grep -i warning; then echo "Doxygen warnings found" && cat docs_log.txt && /bin/false; else echo "No Doxygen warnings found"; fi
+make USER_DEFS="-Wextra -Werror" -j3
+cd apps
+make USER_DEFS="-Wextra -Werror" test_ogrsf
+cd ..
+cd swig/java
+cat java.opt | sed "s/JAVA_HOME =.*/JAVA_HOME = \/usr\/lib\/jvm\/java-7-openjdk-amd64\//" > java.opt.tmp
+mv java.opt.tmp java.opt
+make
+git checkout java.opt
+cd ../..
+cd swig/perl
+make generate
+make
+cd ../..
+sudo rm -f /usr/lib/libgdal.so*
+sudo make install
+sudo ldconfig
+cd ../autotest/cpp
+make -j3
+cd ../../gdal
+wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/mdb-sqlite/mdb-sqlite-1.0.2.tar.bz2
+tar xjvf mdb-sqlite-1.0.2.tar.bz2
+sudo cp mdb-sqlite-1.0.2/lib/*.jar /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/ext
diff --git a/ci/travis/precise_clang/script.sh b/ci/travis/precise_clang/script.sh
new file mode 100755
index 0000000..a754f8f
--- /dev/null
+++ b/ci/travis/precise_clang/script.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+# When run in the same process after ogr_pgeo.py (with the MDB driver), FileGDB tests fail.
+# Run it in isolation
+# Perl unit tests
+cd swig/perl
+make test
+cd ../..
+# Java unit tests
+cd swig/java
+make test
+cd ../..
+# CPP unit tests
+cd ../autotest
+cd cpp
+GDAL_SKIP=JP2ECW make quick_test
+# Compile and test vsipreload
+make vsipreload.so
+LD_PRELOAD=./vsipreload.so gdalinfo /vsicurl/http://download.osgeo.org/gdal/data/ecw/spif83.ecw
+LD_PRELOAD=./vsipreload.so sqlite3  /vsicurl/http://download.osgeo.org/gdal/data/sqlite3/polygon.db "select * from polygon limit 10"
+cd ..
+# Download a sample file
+mkdir -p ogr/tmp/cache/
+cd ogr/tmp/cache/
+wget http://download.osgeo.org/gdal/data/pgeo/PGeoTest.zip
+unzip PGeoTest.zip
+cd ../../..
+# Run ogr_fgdb.py in isolation from the rest
+cd ogr
+python ogr_fgdb.py
+mkdir disabled
+mv ogr_fgdb.* disabled
+cd ..
+# Run ogr_pgeo.py in isolation from the rest
+cd ogr
+python ogr_pgeo.py
+mv ogr_pgeo.* disabled
+cd ..
+# Run all the Python autotests
+GDAL_SKIP="JP2ECW ECW" python run_all.py
+# A bit messy, but force testing with libspatialite 4.0dev (that has been patched a bit to remove any hard-coded SRS definition so it is very small)
+cd ogr
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/libspatialite4.0dev_ubuntu12.04-64bit_srs_stripped.tar.gz
+tar xzf libspatialite4.0dev_ubuntu12.04-64bit_srs_stripped.tar.gz
+ln -s install-libspatialite-4.0dev/lib/libspatialite.so.5.0.1 libspatialite.so.3
+LD_LIBRARY_PATH=$PWD python ogr_sqlite.py
+cd ..
+
+git checkout ogr/ogr_fgdb.py
+git checkout ogr/ogr_pgeo.py
+if test `git diff | wc -l` != "0"; then
+    echo "Files have been modified duing testsuite run:"
+    git diff
+    exit 1
+fi
diff --git a/ci/travis/python3/before_install.sh b/ci/travis/python3/before_install.sh
new file mode 100755
index 0000000..9b94187
--- /dev/null
+++ b/ci/travis/python3/before_install.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+set -e
+
+sudo mv /etc/apt/sources.list.d/pgdg* /tmp
+sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.1-postgis-2.2-scripts postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1
+sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
+sudo add-apt-repository -y ppa:marlam/gta
+sudo apt-get update -qq
+sudo apt-get install ccache python3 python3-dev python3-numpy postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev openjd [...]
+sudo apt-get install python3-lxml
+sudo apt-get install libogdi3.2-dev
+# Boost for Mongo
+sudo apt-get install libboost-regex-dev libboost-system-dev libboost-thread-dev
+psql -c "drop database if exists autotest" -U postgres
+psql -c "create database autotest" -U postgres
+psql -c "create extension postgis" -d autotest -U postgres
+mysql -e "create database autotest;"
+mysql -e "GRANT ALL ON autotest.* TO 'root'@'localhost';" -u root
+mysql -e "GRANT ALL ON autotest.* TO 'travis'@'localhost';" -u root
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/FileGDB_API_1_2-64.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libecwj2-ubuntu12.04-64bit.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libkml-r864-64bit.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+wget http://even.rouault.free.fr/mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+tar xzf MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/include/* /usr/local/include
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/lib/* /usr/local/lib
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/include/* /usr/local/include
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/lib/* /usr/local/lib
+tar xzf FileGDB_API_1_2-64.tar.gz
+sudo cp -r FileGDB_API/include/* /usr/local/include
+sudo cp -r FileGDB_API/lib/* /usr/local/lib
+tar xzf install-libecwj2-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-libecwj2/include/* /usr/local/include
+sudo cp -r install-libecwj2/lib/* /usr/local/lib
+tar xzf install-libkml-r864-64bit.tar.gz
+sudo cp -r install-libkml/include/* /usr/local/include
+sudo cp -r install-libkml/lib/* /usr/local/lib
+tar xzf install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-openjpeg/include/* /usr/local/include
+sudo cp -r install-openjpeg/lib/* /usr/local/lib
+tar xzf mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+sudo cp -r mongo-cxx-1.0.2-install/include/* /usr/local/include
+sudo cp -r mongo-cxx-1.0.2-install/lib/* /usr/local/lib
+wget https://bitbucket.org/chchrsc/kealib/get/c6d36f3db5e4.zip
+unzip c6d36f3db5e4.zip
+cd chchrsc-kealib-c6d36f3db5e4/trunk
+cmake . -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DHDF5_INCLUDE_DIR=/usr/include -DHDF5_LIB_PATH=/usr/lib -DLIBKEA_WITH_GDAL=OFF
+make -j4
+sudo make install
+cd ../..
+sudo ldconfig
diff --git a/ci/travis/python3/install.sh b/ci/travis/python3/install.sh
new file mode 100755
index 0000000..b8649f4
--- /dev/null
+++ b/ci/travis/python3/install.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+export CCACHE_CPP2=yes
+
+CC="ccache gcc" CXX="ccache g++" ./configure --prefix=/usr --without-libtool --enable-debug --with-jpeg12 --with-python=/usr/bin/python3 --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-gta --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local --with-fgdb=/usr/local --with-libkml --with-openjpeg=/usr/local --with-mongocxx=/usr/local
+make USER_DEFS="-Wextra -Werror" -j3
+cd apps
+make USER_DEFS="-Wextra -Werror" test_ogrsf
+cd ..
+#cd swig/java
+#cat java.opt | sed "s/JAVA_HOME =.*/JAVA_HOME = \/usr\/lib\/jvm\/java-7-openjdk-amd64\//" > java.opt.tmp
+#mv java.opt.tmp java.opt
+#make
+#cd ../..
+#cd swig/perl
+#make generate
+#make
+#cd ../..
+#sudo rm -f /usr/lib/libgdal.so*
+sudo make install
+sudo ldconfig
+g++ -DGDAL_COMPILATION -Wall -DDEBUG -fPIC -g ogr/ogrsf_frmts/null/ogrnulldriver.cpp  -shared -o ogr_NULL.so -L. -lgdal -Iport -Igcore -Iogr -Iogr/ogrsf_frmts
+GDAL_DRIVER_PATH=$PWD ogr2ogr -f null null ../autotest/ogr/data/poly.shp
+cd ../autotest/cpp
+make -j3
+cd ../../gdal
+wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/mdb-sqlite/mdb-sqlite-1.0.2.tar.bz2
+tar xjvf mdb-sqlite-1.0.2.tar.bz2
+sudo cp mdb-sqlite-1.0.2/lib/*.jar /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/ext
diff --git a/ci/travis/python3/script.sh b/ci/travis/python3/script.sh
new file mode 100755
index 0000000..8e408bb
--- /dev/null
+++ b/ci/travis/python3/script.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+
+# Perl unit tests
+#cd swig/perl
+#make test
+#cd ../..
+# Java unit tests
+#cd swig/java
+#make test
+#cd ../..
+# CPP unit tests
+cd ../autotest
+#cd cpp
+#GDAL_SKIP=JP2ECW make quick_test
+# Compile and test vsipreload
+#make vsipreload.so
+#LD_PRELOAD=./vsipreload.so gdalinfo /vsicurl/http://download.osgeo.org/gdal/data/ecw/spif83.ecw
+#LD_PRELOAD=./vsipreload.so sqlite3  /vsicurl/http://download.osgeo.org/gdal/data/sqlite3/polygon.db "select * from polygon limit 10"
+#cd ..
+# Download a sample file
+mkdir -p ogr/tmp/cache/
+cd ogr/tmp/cache/
+wget http://download.osgeo.org/gdal/data/pgeo/PGeoTest.zip
+unzip PGeoTest.zip
+cd ../../..
+# Run ogr_fgdb.py in isolation from the rest
+cd ogr
+python3 ogr_fgdb.py
+mkdir disabled
+mv ogr_fgdb.* disabled
+cd ..
+# Run ogr_pgeo.py in isolation from the rest
+cd ogr
+python3 ogr_pgeo.py
+mv ogr_pgeo.* disabled
+cd ..
+# Run all the Python autotests
+GDAL_SKIP="JP2ECW ECW" python3 run_all.py
+# A bit messy, but force testing with libspatialite 4.0dev (that has been patched a bit to remove any hard-coded SRS definition so it is very small)
+cd ogr
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/libspatialite4.0dev_ubuntu12.04-64bit_srs_stripped.tar.gz
+tar xzf libspatialite4.0dev_ubuntu12.04-64bit_srs_stripped.tar.gz
+ln -s install-libspatialite-4.0dev/lib/libspatialite.so.5.0.1 libspatialite.so.3
+LD_LIBRARY_PATH=$PWD python3 ogr_sqlite.py
+cd ..
diff --git a/ci/travis/trusty_clang/before_install.sh b/ci/travis/trusty_clang/before_install.sh
new file mode 100755
index 0000000..a2327ce
--- /dev/null
+++ b/ci/travis/trusty_clang/before_install.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+set -e
+
+sudo dpkg -l | grep geos
+sudo apt-get purge -y libgeos* libspatialite*
+find  /etc/apt/sources.list.d
+sudo mv /etc/apt/sources.list.d/pgdg* /tmp
+#sudo apt-get remove postgis libpq5 libpq-dev postgresql-9.1-postgis postgresql-9.2-postgis postgresql-9.3-postgis postgresql-9.1 postgresql-9.2 postgresql-9.3 libgdal1
+#sudo apt-get remove -y postgresql-9.1
+sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
+sudo add-apt-repository -y ppa:marlam/gta
+sudo apt-get update
+# postgis postgresql-9.5 postgresql-client-9.5 postgresql-9.5-postgis-2.2 libpq-dev
+sudo apt-get install -y ccache python-numpy libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev  libepsilon-dev libgta-dev liblcms2-2 libpcre3-dev mercurial cmake libcrypto++-dev
+sudo apt-get install -y python-lxml
+sudo apt-get install -y python-pip
+sudo apt-get install -y libqhull-dev
+sudo apt-get install -y libogdi3.2-dev
+# Boost for Mongo
+#sudo apt-get install -y libboost-regex-dev libboost-system-dev libboost-thread-dev
+sudo pip install pyflakes
+pyflakes autotest
+pyflakes gdal/swig/python/scripts
+pyflakes gdal/swig/python/samples
+#psql -c "drop database if exists autotest" -U postgres
+#psql -c "create database autotest" -U postgres
+#psql -c "create extension postgis" -d autotest -U postgres
+#mysql -e "create database autotest;"
+#mysql -e "GRANT ALL ON autotest.* TO 'root'@'localhost';" -u root
+#mysql -e "GRANT ALL ON autotest.* TO 'travis'@'localhost';" -u root
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/FileGDB_API_1_2-64.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libecwj2-ubuntu12.04-64bit.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-libkml-r864-64bit.tar.gz
+wget http://s3.amazonaws.com/etc-data.koordinates.com/gdal-travisci/install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+#wget http://even.rouault.free.fr/mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+tar xzf MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44.tar.gz
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/include/* /usr/local/include
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Raster_DSDK/lib/* /usr/local/lib
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/include/* /usr/local/include
+sudo cp -r MrSID_DSDK-8.5.0.3422-linux.x86-64.gcc44/Lidar_DSDK/lib/* /usr/local/lib
+tar xzf FileGDB_API_1_2-64.tar.gz
+sudo cp -r FileGDB_API/include/* /usr/local/include
+sudo cp -r FileGDB_API/lib/* /usr/local/lib
+tar xzf install-libecwj2-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-libecwj2/include/* /usr/local/include
+sudo cp -r install-libecwj2/lib/* /usr/local/lib
+tar xzf install-libkml-r864-64bit.tar.gz
+sudo cp -r install-libkml/include/* /usr/local/include
+sudo cp -r install-libkml/lib/* /usr/local/lib
+tar xzf install-openjpeg-2.0.0-ubuntu12.04-64bit.tar.gz
+sudo cp -r install-openjpeg/include/* /usr/local/include
+sudo cp -r install-openjpeg/lib/* /usr/local/lib
+#tar xzf mongo-cxx-1.0.2-install-ubuntu12.04-64bit.tar.gz
+#sudo cp -r mongo-cxx-1.0.2-install/include/* /usr/local/include
+#sudo cp -r mongo-cxx-1.0.2-install/lib/* /usr/local/lib
+wget https://bitbucket.org/chchrsc/kealib/get/c6d36f3db5e4.zip
+unzip c6d36f3db5e4.zip
+cd chchrsc-kealib-c6d36f3db5e4/trunk
+cmake . -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DHDF5_INCLUDE_DIR=/usr/include -DHDF5_LIB_PATH=/usr/lib -DLIBKEA_WITH_GDAL=OFF
+make -j4
+sudo make install
+cd ../..
+sudo ldconfig
diff --git a/ci/travis/trusty_clang/install.sh b/ci/travis/trusty_clang/install.sh
new file mode 100755
index 0000000..cc81e7f
--- /dev/null
+++ b/ci/travis/trusty_clang/install.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+set -e
+
+cd gdal
+# --with-mongocxx=/usr/local
+export CCACHE_CPP2=yes
+CC="ccache clang" CXX="ccache clang" LDFLAGS="-lstdc++" ./configure --prefix=/usr --without-libtool --with-jpeg12 --with-python --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-java --with-mdb --with-jvm-lib-add-rpath --with-epsilon --with-gta --with-ecw=/usr/local --with-mrsid=/usr/local --with-mrsid-lidar=/usr/local --with-fgdb=/usr/local --with-libkml --with-openjpeg=/usr/local
+# Those ln -s are weird but otherwise Python bindings build fail with clang not being found
+sudo ln -s /usr/local/clang-3.5.0/bin/clang /usr/bin/clang
+sudo ln -s /usr/local/clang-3.5.0/bin/clang++ /usr/bin/clang++
+make USER_DEFS="-Wextra -Werror" -j3
+cd apps
+make USER_DEFS="-Wextra -Werror" test_ogrsf
+cd ..
+cd swig/java
+cat java.opt | sed "s/JAVA_HOME =.*/JAVA_HOME = \/usr\/lib\/jvm\/java-8-openjdk-amd64\//" > java.opt.tmp
+mv java.opt.tmp java.opt
+export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
+export PATH=$JAVA_HOME/jre/bin:$PATH
+java -version
+make
+cd ../..
+cd swig/perl
+make generate
+make
+cd ../..
+sudo rm -f /usr/lib/libgdal.so*
+sudo rm -f /usr/include/gdal*.h /usr/include/ogr*.h /usr/include/gnm*.h /usr/include/cpl*.h 
+sudo make install
+
+# Check that override is not used in public headers
+if grep override /usr/include/gdal*.h /usr/include/ogr*.h /usr/include/gnm*.h /usr/include/cpl*.h | grep -v "One can override" | grep -v cpl_port | grep -v "Use this file to override"; then echo "Error: override keyword found in public headers instead of CPL_OVERRIDE" && /bin/false; fi 
+
+sudo ldconfig
+cd ../autotest/cpp
+make -j3
+cd ../../gdal
+wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/mdb-sqlite/mdb-sqlite-1.0.2.tar.bz2
+tar xjvf mdb-sqlite-1.0.2.tar.bz2
+sudo cp mdb-sqlite-1.0.2/lib/*.jar /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/ext
diff --git a/ci/travis/trusty_clang/script.sh b/ci/travis/trusty_clang/script.sh
new file mode 100755
index 0000000..8d40517
--- /dev/null
+++ b/ci/travis/trusty_clang/script.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+set -e
+
+# When run in the same process after ogr_pgeo.py (with the MDB driver), FileGDB tests fail.
+# Run it in isolation
+export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
+export PATH=$JAVA_HOME/jre/bin:$PATH
+
+cd gdal
+# Perl unit tests
+cd swig/perl
+make test
+cd ../..
+# Java unit tests
+cd swig/java
+make test
+cd ../..
+# CPP unit tests
+cd ../autotest
+cd cpp
+GDAL_SKIP=JP2ECW make quick_test
+# Compile and test vsipreload
+make vsipreload.so
+LD_PRELOAD=./vsipreload.so gdalinfo /vsicurl/http://download.osgeo.org/gdal/data/ecw/spif83.ecw
+LD_PRELOAD=./vsipreload.so sqlite3  /vsicurl/http://download.osgeo.org/gdal/data/sqlite3/polygon.db "select * from polygon limit 10"
+cd ..
+# Download a sample file
+mkdir -p ogr/tmp/cache/
+cd ogr/tmp/cache/
+wget http://download.osgeo.org/gdal/data/pgeo/PGeoTest.zip
+unzip PGeoTest.zip
+cd ../../..
+# Run ogr_fgdb.py in isolation from the rest
+export PYTHONPATH=/usr/lib/python2.7/dist-packages
+cd ogr
+python ogr_fgdb.py
+mkdir disabled
+mv ogr_fgdb.* disabled
+cd ..
+# Run ogr_pgeo.py in isolation from the rest
+cd ogr
+python ogr_pgeo.py
+mv ogr_pgeo.* disabled
+cd ..
+# Run all the Python autotests
+GDAL_SKIP="JP2ECW ECW" python run_all.py
diff --git a/ci/travis/ubuntu_1604/before_install.sh b/ci/travis/ubuntu_1604/before_install.sh
new file mode 100755
index 0000000..233b4b1
--- /dev/null
+++ b/ci/travis/ubuntu_1604/before_install.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+set -e
+
+export chroot="$PWD"/xenial
+mkdir -p "$chroot$PWD"
+sudo apt-get update
+sudo apt-get install -y debootstrap
+export LC_ALL=en_US
+sudo debootstrap xenial "$chroot"
+sudo mount --rbind "$PWD" "$chroot$PWD"
+sudo mount --rbind /dev/pts "$chroot/dev/pts"
+sudo mount --rbind /proc "$chroot/proc"
+sudo su -c 'echo "deb http://archive.ubuntu.com/ubuntu xenial universe" >> xenial/etc/apt/sources.list'
+sudo chroot "$chroot" apt-get update
+#sudo chroot "$chroot" apt-get install -y clang
+sudo chroot "$chroot" apt-get install -y software-properties-common python-software-properties
+sudo chroot "$chroot" add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
+sudo chroot "$chroot" apt-get update
+# Disable postgresql since it draws ssl-cert that doesn't install cleanly
+# postgis postgresql-9.1 postgresql-client-9.1 postgresql-9.1-postgis-2.1 postgresql-9.1-postgis-2.1-scripts libpq-dev
+sudo chroot "$chroot" apt-get install -y --allow-unauthenticated python-numpy libpng12-dev libjpeg-dev libgif-dev liblzma-dev libgeos-dev libcurl4-gnutls-dev libproj-dev libxml2-dev libexpat-dev libxerces-c-dev libnetcdf-dev netcdf-bin libpoppler-dev libpoppler-private-dev libspatialite-dev gpsbabel swig libhdf4-alt-dev libhdf5-serial-dev libpodofo-dev poppler-utils libfreexl-dev unixodbc-dev libwebp-dev libepsilon-dev liblcms2-2 libpcre3-dev libcrypto++-dev libdap-dev libfyba-dev libkml [...]
+sudo chroot "$chroot" apt-get install -y doxygen texlive-latex-base
+sudo chroot "$chroot" apt-get install -y make
+sudo chroot "$chroot" apt-get install -y python-dev
+sudo chroot "$chroot" apt-get install -y g++
+sudo chroot "$chroot" apt-get install -y libsfcgal-dev
+sudo chroot "$chroot" apt-get install -y fossil libgeotiff-dev libcharls-dev libopenjp2-7-dev libcairo2-dev
+wget http://llvm.org/releases/3.9.0/clang+llvm-3.9.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
+tar xJf clang+llvm-3.9.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
+
+wget https://github.com/Esri/file-geodatabase-api/raw/master/FileGDB_API_1.5/FileGDB_API_1_5_64gcc51.tar.gz
+tar xzf FileGDB_API_1_5_64gcc51.tar.gz
+sudo cp FileGDB_API-64gcc51/lib/* "$chroot/usr/lib"
+sudo chroot "$chroot" ldconfig
+
+sudo chroot "$chroot" apt-get install -y pyflakes3
+sudo chroot "$chroot" sh -c "cd $PWD && pyflakes3 autotest"
+sudo chroot "$chroot" sh -c "cd $PWD && pyflakes3 gdal/swig/python/scripts"
+sudo chroot "$chroot" sh -c "cd $PWD && pyflakes3 gdal/swig/python/samples"
+
+sudo chroot "$chroot" apt-get install -y cppcheck bash
diff --git a/ci/travis/ubuntu_1604/install.sh b/ci/travis/ubuntu_1604/install.sh
new file mode 100755
index 0000000..2654976
--- /dev/null
+++ b/ci/travis/ubuntu_1604/install.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+set -e
+
+export chroot="$PWD"/xenial
+export LC_ALL=en_US
+
+sudo chroot "$chroot" sh -c "fossil clone https://www.gaia-gis.it/fossil/librasterlite2 librasterlite2.fossil && mkdir rl2 && cd rl2 && fossil open ../librasterlite2.fossil && ./configure --prefix=/usr && make -j3 && make -j3 install"
+
+sudo chroot "$chroot" sh -c "cd $PWD/gdal && CC=$PWD/clang+llvm-3.9.0-x86_64-linux-gnu-ubuntu-16.04/bin/clang CXX=$PWD/clang+llvm-3.9.0-x86_64-linux-gnu-ubuntu-16.04/bin/clang LDFLAGS='-lstdc++' ./configure --prefix=/usr --without-libtool --enable-debug --with-jpeg12 --with-python --with-poppler --with-podofo --with-spatialite --with-mysql --with-liblzma --with-webp --with-epsilon --with-static-proj4 --with-poppler --with-podofo --with-hdf5 --with-dods-root=/usr --with-sosi --with-mysql  [...]
+
+sudo chroot "$chroot" bash -c "cd $PWD/gdal && scripts/cppcheck.sh"
+
+sudo chroot "$chroot" sh -c "cd $PWD/gdal && make docs >docs_log.txt 2>&1"
+sudo chroot "$chroot" sh -c "cd $PWD/gdal && if cat docs_log.txt | grep -i warning | grep -v russian | grep -v brazilian | grep -v setlocale | grep -v 'has become obsolete' | grep -v 'To avoid this warning'; then echo 'Doxygen warnings found' && cat docs_log.txt && /bin/false; else echo 'No Doxygen warnings found'; fi"
+sudo chroot "$chroot" sh -c "cd $PWD/gdal && make man >man_log.txt 2>&1"
+sudo chroot "$chroot" sh -c "cd $PWD/gdal && if cat man_log.txt | grep -i warning | grep -v setlocale | grep -v 'has become obsolete' | grep -v 'To avoid this warning'; then echo 'Doxygen warnings found' && cat docs_log.txt && /bin/false; else echo 'No Doxygen warnings found'; fi"
+sudo chroot "$chroot" sh -c "cd $PWD/gdal && make USER_DEFS=-Werror -j3"
+sudo chroot "$chroot" sh -c "cd $PWD/gdal/apps && make USER_DEFS=-Werror -j3 test_ogrsf"
+sudo chroot "$chroot" sh -c "rm -f /usr/lib/libgdal.so*"
+sudo chroot "$chroot" sh -c "cd $PWD/gdal && make install"
+sudo chroot "$chroot" sh -c "sudo ldconfig"
+sudo chroot "$chroot" sh -c "cd $PWD/autotest/cpp && make -j3"
diff --git a/ci/travis/ubuntu_1604/script.sh b/ci/travis/ubuntu_1604/script.sh
new file mode 100755
index 0000000..1c60164
--- /dev/null
+++ b/ci/travis/ubuntu_1604/script.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+set -e
+
+export chroot="$PWD"/xenial
+export LC_ALL=en_US
+
+sudo chroot "$chroot" sh -c "cd $PWD/autotest/cpp && make quick_test"
+# Compile and test vsipreload
+sudo chroot "$chroot" sh -c "cd $PWD/autotest/cpp && make vsipreload.so"
+# Run all the Python autotests
+
+# Run ogr_fgdb test in isolation due to likely conflict with libxml2
+sudo chroot "$chroot" sh -c "cd $PWD/autotest/ogr && python ogr_fgdb.py && cd ../../.."
+rm autotest/ogr/ogr_fgdb.py
+
+sudo chroot "$chroot" sh -c "cd $PWD/autotest && python run_all.py"
\ No newline at end of file
diff --git a/configure b/configure
index 0ecb455..8061957 100755
--- a/configure
+++ b/configure
@@ -675,7 +675,13 @@ FREEXL_INCLUDE
 HAVE_FREEXL
 OPENCL_LIB
 OPENCL_FLAGS
+QHULL_INCLUDE_SUBDIR_IS_LIBQHULL
 QHULL_SETTING
+SFCGAL_CONFIG
+SFCGAL_VERSION
+HAVE_SFCGAL
+SFCGAL_CFLAGS
+SFCGAL_LIBS
 GEOS_CONFIG
 GEOS_VERSION
 HAVE_GEOS
@@ -687,9 +693,11 @@ SDE_ENABLED
 IDB_LIB
 IDB_INC
 HAVE_IDB
-DWGDIRECT
-DWG_PLT
+HAVE_TEIGHA
+TEIGHA_DIR
 HAVE_PCRE
+RASTERLITE2_CFLAGS
+HAVE_RASTERLITE2
 SQLITE_HAS_COLUMN_METADATA
 HAVE_SQLITE
 SQLITE_INC
@@ -720,7 +728,6 @@ LIBKML_VERSION
 LIBKML_LDLAGS
 LIBKML_LIBS
 LIBKML_CFLAGS
-PKG_CONFIG
 EXPAT_INCLUDE
 HAVE_EXPAT
 EXPAT_VERSION
@@ -729,9 +736,9 @@ EXPAT_CFLAGS
 HAVE_NAS
 XERCES_INCLUDE
 HAVE_XERCES
-XERCES_VERSION
 XERCES_LDFLAGS
 XERCES_CFLAGS
+XERCES_VERSION
 INGRES_INC
 INGRES_LIB
 II_SYSTEM
@@ -745,6 +752,7 @@ OPT_GDAL_FORMATS
 ORACLE_OCI_LDFLAGS
 ORACLE_OCI_CFLAGS
 ORACLE_OCI_VERSION
+JP2LURA_INCLUDE
 MRSID_LIDAR_LIBS
 MRSID_LIDAR_INCLUDE
 MRSID_LIBS
@@ -773,6 +781,9 @@ HAVE_KEA
 KEA_CONFIG
 HDF5_INCLUDE
 HAVE_HDF5
+HDF5_LIBS
+HDF5_CFLAGS
+PKG_CONFIG
 HDF4_HAS_MAXOPENFILES
 HDF4_INCLUDE
 HAVE_HDF4
@@ -817,12 +828,12 @@ LIBZ_SETTING
 RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS
 RENAME_INTERNAL_LIBTIFF_SYMBOLS
 HAVE_HIDE_INTERNAL_SYMBOLS
+CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT
 CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT
-CFLAGS_NO_LTO_IF_AVX_NONDEFAULT
-HAVE_AVX_AT_COMPILE_TIME
 AVXFLAGS
-HAVE_SSE_AT_COMPILE_TIME
+SSSE3FLAGS
 SSEFLAGS
+HAVE_GCC_BSWAP
 HAVE_GCC_ATOMIC_BUILTINS
 CXXFLAGS_NOFTRAPV
 CFLAGS_NOFTRAPV
@@ -861,6 +872,8 @@ NO_SIGN_COMPARE
 NO_UNUSED_PARAMETER_FLAG
 C_WFLAGS
 CXX_WFLAGS
+CXX11_SUPPORT
+HAVE_CXX11
 ac_ct_CXX
 CXXFLAGS
 CXX
@@ -921,6 +934,7 @@ SHELL'
 ac_subst_files=''
 ac_user_opts='
 enable_option_checking
+with_cpp11
 enable_shared
 enable_static
 with_pic
@@ -933,6 +947,7 @@ with_ld_shared
 with_unix_stdio_64
 enable_debug
 with_sse
+with_ssse3
 with_avx
 enable_lto
 with_hide_internal_symbols
@@ -975,6 +990,7 @@ with_kakadu
 with_mrsid
 with_jp2mrsid
 with_mrsid_lidar
+with_jp2lura
 with_msg
 with_bsb
 with_oci
@@ -1000,14 +1016,17 @@ with_xml2
 with_spatialite
 with_spatialite_soname
 with_sqlite3
+with_rasterlite2
 with_pcre
-with_dwgdirect
+with_teigha
+with_teigha_plt
 with_idb
 with_sde
 with_sde_version
 with_epsilon
 with_webp
 with_geos
+with_sfcgal
 with_qhull
 with_opencl
 with_opencl_include
@@ -1025,7 +1044,7 @@ with_pdfium_lib
 with_pdfium_extra_lib_for_test
 with_static_proj4
 with_gdal_ver
-with_
+with_macosx_framework
 with_perl
 with_php
 with_python
@@ -1036,6 +1055,7 @@ with_jvm_lib_add_rpath
 with_rasdaman
 with_armadillo
 with_cryptopp
+with_mrf
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1051,6 +1071,8 @@ CCC
 CPP
 CXXCPP
 PKG_CONFIG
+HDF5_CFLAGS
+HDF5_LIBS
 LIBKML_CFLAGS
 LIBKML_LIBS'
 
@@ -1690,6 +1712,7 @@ Optional Features:
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --without-cpp11         Disable C++11 compiler options
   --with-pic              try to use only PIC/non-PIC objects [default=use
                           both]
   --with-gnu-ld           assume the C compiler uses GNU ld [default=no]
@@ -1699,6 +1722,7 @@ Optional Packages:
   --without-ld-shared   Disable shared library support
   --with-unix-stdio-64=ARG Utilize 64 stdio api (yes/no)
   --with-sse=ARG        Detect SSE availability for some optimized routines (ARG=yes(default), no)
+  --with-ssse3=ARG        Detect SSSE3 availability for some optimized routines (ARG=yes(default), no)
   --with-avx=ARG        Detect AVX availability for some optimized routines (ARG=yes(default), no)
   --with-hide-internal-symbols=ARG Try to hide internal symbols (ARG=yes/no)
   --with-rename-internal-libtiff-symbols=ARG Prefix internal libtiff symbols with gdal_ (ARG=yes/no)
@@ -1742,6 +1766,7 @@ Optional Packages:
   --with-mrsid=ARG      Include MrSID support (ARG=path to MrSID DSDK or no)
   --with-jp2mrsid=ARG   Enable MrSID JPEG2000 support (ARG=yes/no)
   --with-mrsid_lidar=ARG      Include MrSID/MG4 LiDAR support (ARG=path to LizardTech LiDAR SDK or no)
+  --with-j2lura=ARG    Include JP2Lua support (ARG=no, lura SDK install path)
   --with-msg=ARG          Enable MSG driver (ARG=yes or no)
   --without-bsb           Disable BSB driver (legal issues pending
   --with-oci=[ARG]        use Oracle OCI API from given Oracle home
@@ -1774,9 +1799,10 @@ Optional Packages:
   --with-spatialite-soname=ARG Spatialite shared object name (e.g. libspatialite.so), only used if --with-spatiliate=dlopen
   --with-sqlite3=[ARG]    use SQLite 3 library [default=yes], optionally
                           specify the prefix for sqlite3 library
+  --with-rasterlite2=ARG Include RasterLite2 support (ARG=no(default), yes or path)
   --with-pcre             Include libpcre support (REGEXP support for SQLite)
-  --with-dwgdirect=path Include DWG direct support
-  --with-dwg-plt=platform DWGdirect Platform, defaults to lnxX86
+  --with-teigha=path Include Teigha DWG/DGN support
+  --with-teigha-plt=platform Teigha platform
   --with-idb=DIR        Include Informix DataBlade support (DIR points to Informix root)
   --with-sde=DIR        Include ESRI SDE support (DIR is SDE's install dir).
   --with-sde-version=VERSION NUMBER  Set ESRI SDE version number (Default is 80).
@@ -1784,6 +1810,8 @@ Optional Packages:
   --with-webp=ARG    Include WEBP support (ARG=no, yes or libwebp install root path)
   --with-geos=ARG         Include GEOS support (ARG=yes, no or geos-config
                           path)
+  --with-sfcgal=ARG       Include SFCGAL support (ARG=yes, no or sfcgal-config
+                          path)
   --with-qhull=ARG     Include QHull support (ARG=no, yes, internal)
   --with-opencl=ARG       Include OpenCL (GPU) support
   --with-opencl-include=ARG OpenCL Include directory (with a CL subdirectory)
@@ -1806,7 +1834,7 @@ Optional Packages:
   --with-python=ARG   Enable python bindings (ARG=yes, no, or path to python binary)
   --with-java       Include Java support (ARG=yes, no or JDK home path)  [default=no]
   --with-mdb       Include MDB driver
-  --with-jvm-lib=ARG        ARG points to Java libjvm path
+  --with-jvm-lib=ARG        ARG is dlopen or points to Java libjvm path
   --with-jvm-lib-add-rpath    Add the libjvm path to the RPATH (no by default)
   --with-rasdaman=DIR        Include rasdaman support (DIR is rasdaman's install dir).
   --with-armadillo=ARG       Include Armadillo support for faster TPS transform computation (ARG=yes/no/path to armadillo install root) [default=no]
@@ -1826,6 +1854,8 @@ Some influential environment variables:
   CPP         C preprocessor
   CXXCPP      C++ preprocessor
   PKG_CONFIG  path to pkg-config utility
+  HDF5_CFLAGS C compiler flags for HDF5, overriding pkg-config
+  HDF5_LIBS   linker flags for HDF5, overriding pkg-config
   LIBKML_CFLAGS
               C compiler flags for LIBKML, overriding pkg-config
   LIBKML_LIBS linker flags for LIBKML, overriding pkg-config
@@ -4281,14 +4311,90 @@ case ".$ac_cv_cxxflags_warn_all" in
  ;;
 esac
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wextra" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wextra... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wextra+:} false; then :
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -we10006" >&5
+$as_echo_n "checking whether C compiler accepts -Werror -we10006... " >&6; }
+if ${ax_cv_check_cflags___Werror__we10006+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS  -Werror -we10006"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ax_cv_check_cflags___Werror__we10006=yes
+else
+  ax_cv_check_cflags___Werror__we10006=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__we10006" >&5
+$as_echo "$ax_cv_check_cflags___Werror__we10006" >&6; }
+if test "x$ax_cv_check_cflags___Werror__we10006" = xyes; then :
+  ERROR_ON_UNKNOWN_OPTIONS="-Werror -we10006"
+else
+  ERROR_ON_UNKNOWN_OPTIONS="-Werror"
+fi
+
+
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-diag-disable 188,1684,2259,2304,3280,11074,11076" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -diag-disable 188,1684,2259,2304,3280,11074,11076" >&5
+$as_echo_n "checking whether C compiler accepts -diag-disable 188,1684,2259,2304,3280,11074,11076... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -diag-disable 188,1684,2259,2304,3280,11074,11076"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_CACHEVAR=yes"
+else
+  eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+  C_WFLAGS="$C_WFLAGS -diag-disable 188,1684,2259,2304,3280,11074,11076" CXX_WFLAGS="$CXX_WFLAGS -diag-disable 188,1684,2259,2304,3280,11074,11076"
+else
+  :
+fi
+
+
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wextra" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wextra" >&5
+$as_echo_n "checking whether C compiler accepts -Wextra... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wextra"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wextra"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4301,29 +4407,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wextra=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wextra=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wextra" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wextra" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wextra" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wextra" CXX_WFLAGS="$CXX_WFLAGS -Wextra"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Winit-self" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Winit-self... " >&6; }
-if ${ax_cv_check_cflags___Werror__Winit_self+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Winit-self" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Winit-self" >&5
+$as_echo_n "checking whether C compiler accepts -Winit-self... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Winit-self"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Winit-self"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4336,29 +4444,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Winit_self=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Winit_self=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Winit_self" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Winit_self" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Winit_self" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Winit-self" CXX_WFLAGS="$CXX_WFLAGS -Winit-self"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wunused-parameter" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wunused-parameter... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wunused_parameter+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wunused-parameter" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wunused-parameter" >&5
+$as_echo_n "checking whether C compiler accepts -Wunused-parameter... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wunused-parameter"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wunused-parameter"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4371,29 +4481,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wunused_parameter=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wunused_parameter=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wunused_parameter" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wunused_parameter" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wunused_parameter" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wunused-parameter" CXX_WFLAGS="$CXX_WFLAGS -Wunused-parameter" NO_UNUSED_PARAMETER_FLAG="-Wno-unused-parameter"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wmissing-prototypes" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wmissing-prototypes... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wmissing_prototypes+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wmissing-prototypes" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wmissing-prototypes" >&5
+$as_echo_n "checking whether C compiler accepts -Wmissing-prototypes... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wmissing-prototypes"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wmissing-prototypes"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4406,29 +4518,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wmissing_prototypes=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wmissing_prototypes=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wmissing_prototypes" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wmissing_prototypes" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wmissing_prototypes" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wmissing-prototypes"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wmissing-declarations" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wmissing-declarations... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wmissing_declarations+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wmissing-declarations" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wmissing-declarations" >&5
+$as_echo_n "checking whether C compiler accepts -Wmissing-declarations... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wmissing-declarations"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wmissing-declarations"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4441,29 +4555,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wmissing_declarations=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wmissing_declarations=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wmissing_declarations" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wmissing_declarations" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wmissing_declarations" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wmissing-declarations"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wformat" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wformat... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wformat+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wformat" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wformat" >&5
+$as_echo_n "checking whether C compiler accepts -Wformat... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wformat"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wformat"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4476,29 +4592,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wformat=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wformat=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wformat" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wformat" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wformat" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wformat" CXX_WFLAGS="$CXX_WFLAGS -Wformat"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wformat -Werror=format-security -Wno-format-nonliteral" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wformat -Werror=format-security -Wno-format-nonliteral... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wformat -Werror=format-security -Wno-format-nonliteral" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wformat -Werror=format-security -Wno-format-nonliteral" >&5
+$as_echo_n "checking whether C compiler accepts -Wformat -Werror=format-security -Wno-format-nonliteral... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wformat -Werror=format-security -Wno-format-nonliteral"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wformat -Werror=format-security -Wno-format-nonliteral"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4511,29 +4629,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wformat__Werror_format_security__Wno_format_nonliteral" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Werror=format-security -Wno-format-nonliteral" CXX_WFLAGS="$CXX_WFLAGS -Werror=format-security -Wno-format-nonliteral"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wshorten-64-to-32" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wshorten-64-to-32... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wshorten_64_to_32+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wshorten-64-to-32" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wshorten-64-to-32" >&5
+$as_echo_n "checking whether C compiler accepts -Wshorten-64-to-32... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wshorten-64-to-32"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wshorten-64-to-32"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4546,29 +4666,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wshorten_64_to_32=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wshorten_64_to_32=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wshorten_64_to_32" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wshorten_64_to_32" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wshorten_64_to_32" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wshorten-64-to-32" CXX_WFLAGS="$CXX_WFLAGS -Wshorten-64-to-32"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wlogical-op" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wlogical-op... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wlogical_op+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wlogical-op" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wlogical-op" >&5
+$as_echo_n "checking whether C compiler accepts -Wlogical-op... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wlogical-op"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wlogical-op"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4581,29 +4703,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wlogical_op=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wlogical_op=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wlogical_op" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wlogical_op" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wlogical_op" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wlogical-op" CXX_WFLAGS="$CXX_WFLAGS -Wlogical-op" NO_LOGICAL_OP_FLAG="-Wno-logical-op"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wshadow" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wshadow... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wshadow+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wshadow" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wshadow" >&5
+$as_echo_n "checking whether C compiler accepts -Wshadow... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wshadow"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wshadow"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4616,30 +4740,32 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wshadow=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wshadow=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wshadow" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wshadow" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wshadow" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wshadow" CXX_WFLAGS="$CXX_WFLAGS -Wshadow"
 else
   :
 fi
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Werror=vla" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Werror=vla... " >&6; }
-if ${ax_cv_check_cflags___Werror__Werror_vla+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Werror=vla" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror=vla" >&5
+$as_echo_n "checking whether C compiler accepts -Werror=vla... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Werror=vla"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Werror=vla"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4652,29 +4778,31 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Werror_vla=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Werror_vla=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Werror_vla" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Werror_vla" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Werror_vla" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Werror=vla" CXX_WFLAGS="$CXX_WFLAGS -Werror=vla"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Werror=declaration-after-statement" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Werror=declaration-after-statement... " >&6; }
-if ${ax_cv_check_cflags___Werror__Werror_declaration_after_statement+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Werror=declaration-after-statement" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror=declaration-after-statement" >&5
+$as_echo_n "checking whether C compiler accepts -Werror=declaration-after-statement... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Werror=declaration-after-statement"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Werror=declaration-after-statement"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4687,16 +4815,17 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Werror_declaration_after_statement=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Werror_declaration_after_statement=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Werror_declaration_after_statement" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Werror_declaration_after_statement" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Werror_declaration_after_statement" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wdeclaration-after-statement"
 else
   :
@@ -4704,14 +4833,15 @@ fi
 
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wnull-dereference" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wnull-dereference... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wnull_dereference+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wdate-time" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wdate-time" >&5
+$as_echo_n "checking whether C compiler accepts -Wdate-time... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wnull-dereference"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wdate-time"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4724,29 +4854,69 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wnull_dereference=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wnull_dereference=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wnull_dereference" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wnull_dereference" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wnull_dereference" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+  C_WFLAGS="$C_WFLAGS -Wdate-time" CXX_WFLAGS="$CXX_WFLAGS -Wdate-time"
+else
+  :
+fi
+
+
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wnull-dereference" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wnull-dereference" >&5
+$as_echo_n "checking whether C compiler accepts -Wnull-dereference... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wnull-dereference"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_CACHEVAR=yes"
+else
+  eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wnull-dereference" CXX_WFLAGS="$CXX_WFLAGS -Wnull-dereference"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wduplicated-cond" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wduplicated-cond... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wduplicated_cond+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wduplicated-cond" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wduplicated-cond" >&5
+$as_echo_n "checking whether C compiler accepts -Wduplicated-cond... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wduplicated-cond"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wduplicated-cond"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4759,30 +4929,32 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wduplicated_cond=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wduplicated_cond=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wduplicated_cond" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wduplicated_cond" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wduplicated_cond" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   C_WFLAGS="$C_WFLAGS -Wduplicated-cond" CXX_WFLAGS="$CXX_WFLAGS -Wduplicated-cond"
 else
   :
 fi
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Werror -Wno-sign-compare" >&5
-$as_echo_n "checking whether C compiler accepts -Werror -Wno-sign-compare... " >&6; }
-if ${ax_cv_check_cflags___Werror__Wno_sign_compare+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wno-sign-compare" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wno-sign-compare" >&5
+$as_echo_n "checking whether C compiler accepts -Wno-sign-compare... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CFLAGS
-  CFLAGS="$CFLAGS  -Werror -Wno-sign-compare"
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wno-sign-compare"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4795,22 +4967,137 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  ax_cv_check_cflags___Werror__Wno_sign_compare=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cflags___Werror__Wno_sign_compare=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___Werror__Wno_sign_compare" >&5
-$as_echo "$ax_cv_check_cflags___Werror__Wno_sign_compare" >&6; }
-if test "x$ax_cv_check_cflags___Werror__Wno_sign_compare" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   NO_SIGN_COMPARE="-Wno-sign-compare"
 else
   :
 fi
 
 
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wcomma" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wcomma" >&5
+$as_echo_n "checking whether C compiler accepts -Wcomma... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wcomma"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_CACHEVAR=yes"
+else
+  eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+  C_WFLAGS="$C_WFLAGS -Wcomma" CXX_WFLAGS="$CXX_WFLAGS -Wcomma"
+else
+  :
+fi
+
+
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wfloat-conversion" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wfloat-conversion" >&5
+$as_echo_n "checking whether C compiler accepts -Wfloat-conversion... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wfloat-conversion"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_CACHEVAR=yes"
+else
+  eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+  C_WFLAGS="$C_WFLAGS -Wfloat-conversion" CXX_WFLAGS="$CXX_WFLAGS -Wfloat-conversion"
+else
+  :
+fi
+
+
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wdocumentation -Wno-documentation-deprecated-sync" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -Wdocumentation -Wno-documentation-deprecated-sync" >&5
+$as_echo_n "checking whether C compiler accepts -Wdocumentation -Wno-documentation-deprecated-sync... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wdocumentation -Wno-documentation-deprecated-sync"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$as_CACHEVAR=yes"
+else
+  eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+  C_WFLAGS="$C_WFLAGS -Wdocumentation -Wno-documentation-deprecated-sync" CXX_WFLAGS="$CXX_WFLAGS -Wdocumentation -Wno-documentation-deprecated-sync"
+else
+  :
+fi
+
+
 
 ac_ext=cpp
 ac_cpp='$CXXCPP $CPPFLAGS'
@@ -4818,14 +5105,15 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Wunused-private-field" >&5
-$as_echo_n "checking whether C++ compiler accepts -Werror -Wunused-private-field... " >&6; }
-if ${ax_cv_check_cxxflags___Werror__Wunused_private_field+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wunused-private-field" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Wunused-private-field" >&5
+$as_echo_n "checking whether C++ compiler accepts -Wunused-private-field... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CXXFLAGS
-  CXXFLAGS="$CXXFLAGS  -Werror -Wunused-private-field"
+  CXXFLAGS="$CXXFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wunused-private-field"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4838,29 +5126,31 @@ main ()
 }
 _ACEOF
 if ac_fn_cxx_try_compile "$LINENO"; then :
-  ax_cv_check_cxxflags___Werror__Wunused_private_field=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cxxflags___Werror__Wunused_private_field=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CXXFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Wunused_private_field" >&5
-$as_echo "$ax_cv_check_cxxflags___Werror__Wunused_private_field" >&6; }
-if test "x$ax_cv_check_cxxflags___Werror__Wunused_private_field" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   CXX_WFLAGS="$CXX_WFLAGS -Wunused-private-field"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Wmissing-prototypes" >&5
-$as_echo_n "checking whether C++ compiler accepts -Werror -Wmissing-prototypes... " >&6; }
-if ${ax_cv_check_cxxflags___Werror__Wmissing_prototypes+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wmissing-prototypes" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Wmissing-prototypes" >&5
+$as_echo_n "checking whether C++ compiler accepts -Wmissing-prototypes... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CXXFLAGS
-  CXXFLAGS="$CXXFLAGS  -Werror -Wmissing-prototypes"
+  CXXFLAGS="$CXXFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wmissing-prototypes"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4873,29 +5163,31 @@ main ()
 }
 _ACEOF
 if ac_fn_cxx_try_compile "$LINENO"; then :
-  ax_cv_check_cxxflags___Werror__Wmissing_prototypes=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cxxflags___Werror__Wmissing_prototypes=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CXXFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Wmissing_prototypes" >&5
-$as_echo "$ax_cv_check_cxxflags___Werror__Wmissing_prototypes" >&6; }
-if test "x$ax_cv_check_cxxflags___Werror__Wmissing_prototypes" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   CXX_WFLAGS="$CXX_WFLAGS -Wmissing-prototypes"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Wmissing-declarations" >&5
-$as_echo_n "checking whether C++ compiler accepts -Werror -Wmissing-declarations... " >&6; }
-if ${ax_cv_check_cxxflags___Werror__Wmissing_declarations+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wmissing-declarations" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Wmissing-declarations" >&5
+$as_echo_n "checking whether C++ compiler accepts -Wmissing-declarations... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CXXFLAGS
-  CXXFLAGS="$CXXFLAGS  -Werror -Wmissing-declarations"
+  CXXFLAGS="$CXXFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wmissing-declarations"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4908,29 +5200,844 @@ main ()
 }
 _ACEOF
 if ac_fn_cxx_try_compile "$LINENO"; then :
-  ax_cv_check_cxxflags___Werror__Wmissing_declarations=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cxxflags___Werror__Wmissing_declarations=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CXXFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Wmissing_declarations" >&5
-$as_echo "$ax_cv_check_cxxflags___Werror__Wmissing_declarations" >&6; }
-if test "x$ax_cv_check_cxxflags___Werror__Wmissing_declarations" = xyes; then :
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
   CXX_WFLAGS="$CXX_WFLAGS -Wmissing-declarations"
 else
   :
 fi
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Wnon-virtual-dtor" >&5
-$as_echo_n "checking whether C++ compiler accepts -Werror -Wnon-virtual-dtor... " >&6; }
-if ${ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor+:} false; then :
+as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wnon-virtual-dtor" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Wnon-virtual-dtor" >&5
+$as_echo_n "checking whether C++ compiler accepts -Wnon-virtual-dtor... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CXXFLAGS
+  CXXFLAGS="$CXXFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wnon-virtual-dtor"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  eval "$as_CACHEVAR=yes"
+else
+  eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CXXFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+  CXX_WFLAGS="$CXX_WFLAGS -Wnon-virtual-dtor" NO_NON_VIRTUAL_DTOR_FLAG="-Wno-non-virtual-dtor"
+else
+  :
+fi
+
+
+as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags_$ERROR_ON_UNKNOWN_OPTIONS_-Woverloaded-virtual" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Woverloaded-virtual" >&5
+$as_echo_n "checking whether C++ compiler accepts -Woverloaded-virtual... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CXXFLAGS
+  CXXFLAGS="$CXXFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Woverloaded-virtual"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  eval "$as_CACHEVAR=yes"
+else
+  eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CXXFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+  CXX_WFLAGS="$CXX_WFLAGS -Woverloaded-virtual"
+else
+  :
+fi
+
+
+as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags_$ERROR_ON_UNKNOWN_OPTIONS_-fno-operator-names" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -fno-operator-names" >&5
+$as_echo_n "checking whether C++ compiler accepts -fno-operator-names... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+  ax_check_save_flags=$CXXFLAGS
+  CXXFLAGS="$CXXFLAGS $ERROR_ON_UNKNOWN_OPTIONS -fno-operator-names"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  eval "$as_CACHEVAR=yes"
+else
+  eval "$as_CACHEVAR=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  CXXFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+  CXX_WFLAGS="$CXX_WFLAGS -fno-operator-names"
+else
+  :
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+CXX11_SUPPORT=no
+
+# Check whether --with-cpp11 was given.
+if test "${with_cpp11+set}" = set; then :
+  withval=$with_cpp11;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if use C++11 compiler options" >&5
+$as_echo_n "checking if use C++11 compiler options... " >&6; }
+if test "$with_cpp11" = "yes" -o "$with_cpp11" = "" ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking C++ compiler compatibility with C++11" >&5
+$as_echo_n "checking C++ compiler compatibility with C++11... " >&6; }
+          ax_cxx_compile_cxx11_required=false
+  ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+  ac_success=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5
+$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; }
+if ${ax_cv_cxx_compile_cxx11+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ax_cv_cxx_compile_cxx11=yes
+else
+  ax_cv_cxx_compile_cxx11=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5
+$as_echo "$ax_cv_cxx_compile_cxx11" >&6; }
+  if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+    ac_success=yes
+  fi
+
+    if test x$ac_success = xno; then
+    for switch in -std=gnu++11 -std=gnu++0x; do
+      cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh`
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5
+$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; }
+if eval \${$cachevar+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_CXX="$CXX"
+         CXX="$CXX $switch"
+         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  eval $cachevar=yes
+else
+  eval $cachevar=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+         CXX="$ac_save_CXX"
+fi
+eval ac_res=\$$cachevar
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+      if eval test x\$$cachevar = xyes; then
+        CXX="$CXX $switch"
+        if test -n "$CXXCPP" ; then
+          CXXCPP="$CXXCPP $switch"
+        fi
+        ac_success=yes
+        break
+      fi
+    done
+  fi
+
+
+  ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+  if test x$ax_cxx_compile_cxx11_required = xtrue; then
+    if test x$ac_success = xno; then
+      as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5
+    fi
+  fi
+  if test x$ac_success = xno; then
+    HAVE_CXX11=0
+    { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5
+$as_echo "$as_me: No compiler with C++11 support was found" >&6;}
+  else
+    HAVE_CXX11=1
+
+$as_echo "#define HAVE_CXX11 1" >>confdefs.h
+
+  fi
+
+
+
+    if test "$HAVE_CXX11" = "1"; then
+        CXX11_SUPPORT=yes
+    fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
+$as_echo "enabled" >&6; }
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled by user" >&5
+$as_echo "disabled by user" >&6; }
+fi
+CXX11_SUPPORT=$CXX11_SUPPORT
+
+
+if test "$CXX11_SUPPORT" = "yes"; then
+        ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+        as_CACHEVAR=`$as_echo "ax_cv_check_cxxflags_$ERROR_ON_UNKNOWN_OPTIONS_-Wsuggest-override" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Wsuggest-override" >&5
+$as_echo_n "checking whether C++ compiler accepts -Wsuggest-override... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
   $as_echo_n "(cached) " >&6
 else
 
   ax_check_save_flags=$CXXFLAGS
-  CXXFLAGS="$CXXFLAGS  -Werror -Wnon-virtual-dtor"
+  CXXFLAGS="$CXXFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wsuggest-override"
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -4943,69 +6050,45 @@ main ()
 }
 _ACEOF
 if ac_fn_cxx_try_compile "$LINENO"; then :
-  ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor=yes
+  eval "$as_CACHEVAR=yes"
 else
-  ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor=no
+  eval "$as_CACHEVAR=no"
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   CXXFLAGS=$ax_check_save_flags
 fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor" >&5
-$as_echo "$ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor" >&6; }
-if test "x$ax_cv_check_cxxflags___Werror__Wnon_virtual_dtor" = xyes; then :
-  CXX_WFLAGS="$CXX_WFLAGS -Wnon-virtual-dtor" NO_NON_VIRTUAL_DTOR_FLAG="-Wno-non-virtual-dtor"
+eval ac_res=\$$as_CACHEVAR
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_CACHEVAR"\" = x"yes"; then :
+  CXX_WFLAGS="$CXX_WFLAGS -Wsuggest-override"
 else
   :
 fi
 
+    ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -Woverloaded-virtual" >&5
-$as_echo_n "checking whether C++ compiler accepts -Werror -Woverloaded-virtual... " >&6; }
-if ${ax_cv_check_cxxflags___Werror__Woverloaded_virtual+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-  ax_check_save_flags=$CXXFLAGS
-  CXXFLAGS="$CXXFLAGS  -Werror -Woverloaded-virtual"
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-  ax_cv_check_cxxflags___Werror__Woverloaded_virtual=yes
-else
-  ax_cv_check_cxxflags___Werror__Woverloaded_virtual=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  CXXFLAGS=$ax_check_save_flags
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__Woverloaded_virtual" >&5
-$as_echo "$ax_cv_check_cxxflags___Werror__Woverloaded_virtual" >&6; }
-if test "x$ax_cv_check_cxxflags___Werror__Woverloaded_virtual" = xyes; then :
-  CXX_WFLAGS="$CXX_WFLAGS -Woverloaded-virtual"
-else
-  :
 fi
 
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ compiler accepts -Werror -fno-operator-names" >&5
-$as_echo_n "checking whether C++ compiler accepts -Werror -fno-operator-names... " >&6; }
-if ${ax_cv_check_cxxflags___Werror__fno_operator_names+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-  ax_check_save_flags=$CXXFLAGS
-  CXXFLAGS="$CXXFLAGS  -Werror -fno-operator-names"
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+SAVED_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wimplicit-fallthrough"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if -Wimplicit-fallthrough can be enabled" >&5
+$as_echo_n "checking if -Wimplicit-fallthrough can be enabled... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-
+#if !(__cplusplus >= 201103L && ( (defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))) || ((defined(__GNUC__) && __GNUC__ >= 7)) ) )
+    #error "not (C++11 and (clang >= 3.7 or gcc >= 7))"
+    #endif
 int
 main ()
 {
@@ -5015,22 +6098,15 @@ main ()
 }
 _ACEOF
 if ac_fn_cxx_try_compile "$LINENO"; then :
-  ax_cv_check_cxxflags___Werror__fno_operator_names=yes
+  CXX_WFLAGS="$CXX_WFLAGS -Wimplicit-fallthrough"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
 else
-  ax_cv_check_cxxflags___Werror__fno_operator_names=no
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  CXXFLAGS=$ax_check_save_flags
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cxxflags___Werror__fno_operator_names" >&5
-$as_echo "$ax_cv_check_cxxflags___Werror__fno_operator_names" >&6; }
-if test "x$ax_cv_check_cxxflags___Werror__fno_operator_names" = xyes; then :
-  CXX_WFLAGS="$CXX_WFLAGS -fno-operator-names"
-else
-  :
-fi
-
-
+CXXFLAGS=$SAVED_CXXFLAGS
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -5038,6 +6114,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
+
 CXX_WFLAGS=$CXX_WFLAGS
 
 C_WFLAGS=$C_WFLAGS
@@ -16873,7 +17950,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 
-if test "x$CXX" == x ; then
+if test "x$CXX" = x ; then
   as_fn_error $? "\"You don't have a working C++ compiler.\"" "$LINENO" 5
 fi
 
@@ -17014,6 +18091,8 @@ fi
   if test "$with_ld_shared" != "" ; then
     if test "$with_ld_shared" = "no" ; then
       echo "user disabled shared library support."
+    elif test "$with_ld_shared" = "yes" ; then
+      as_fn_error $? "--with-ld-shared not supported" "$LINENO" 5
     else
       echo "using user supplied .so link command ... $with_ld_shared"
     fi
@@ -17971,6 +19050,16 @@ _ACEOF
 
 fi
 
+ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
+if test "x$ac_cv_type_uintptr_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_UINTPTR_T 1
+_ACEOF
+
+
+fi
+
 
 HAVE_IEEEFP=1
 
@@ -18109,6 +19198,17 @@ _ACEOF
 fi
 done
 
+for ac_func in posix_memalign
+do :
+  ac_fn_c_check_func "$LINENO" "posix_memalign" "ac_cv_func_posix_memalign"
+if test "x$ac_cv_func_posix_memalign" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_POSIX_MEMALIGN 1
+_ACEOF
+
+fi
+done
+
 for ac_func in vfork
 do :
   ac_fn_c_check_func "$LINENO" "vfork" "ac_cv_func_vfork"
@@ -18367,12 +19467,76 @@ else
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 fi
-rm -f atomicbuiltins.* atomicbuiltins
+rm -rf atomicbuiltins.* atomicbuiltins
 
 HAVE_GCC_ATOMIC_BUILTINS=$HAVE_GCC_ATOMIC_BUILTINS
 
 
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether GCC bswap builtins are available" >&5
+$as_echo_n "checking whether GCC bswap builtins are available... " >&6; }
+
+rm -f bswapbuiltins.c
+echo '#include <x86intrin.h>' > bswapbuiltins.c
+echo 'int main(int argc, char** argv) { (void)__builtin_bswap32(0); (void)__builtin_bswap64(0); return 0; } ' >> bswapbuiltins.c
+if test -z "`${CC} ${CFLAGS} bswapbuiltins.c -o bswapbuiltins 2>&1`" ; then
+    HAVE_GCC_BSWAP=yes
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GCC_BSWAP 1
+_ACEOF
+
+else
+    HAVE_GCC_BSWAP=no
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -rf bswapbuiltins.* bswapbuiltins
+
+HAVE_GCC_BSWAP=$HAVE_GCC_BSWAP
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __uint128_t" >&5
+$as_echo_n "checking for __uint128_t... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+
+      unsigned long long v1 = 1024ULL;
+      unsigned long long v2 = 0x8000000000000000ULL;
+      __uint128_t u = ((__uint128_t)v1)*((__uint128_t)v2);
+      return u == 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_UINT128_T 1
+_ACEOF
+
+
+else
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
 
 # Check whether --with-sse was given.
 if test "${with_sse+set}" = set; then :
@@ -18435,7 +19599,12 @@ $as_echo "no" >&6; }
        esac
     fi
 
-    rm -f detectsse*
+    if test "$HAVE_SSE_AT_COMPILE_TIME" = "yes"; then
+        CFLAGS="-DHAVE_SSE_AT_COMPILE_TIME $CFLAGS"
+        CXXFLAGS="-DHAVE_SSE_AT_COMPILE_TIME $CXXFLAGS"
+    fi
+
+    rm -rf detectsse*
 else
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -18443,7 +19612,82 @@ fi
 
 SSEFLAGS=$SSEFLAGS
 
-HAVE_SSE_AT_COMPILE_TIME=$HAVE_SSE_AT_COMPILE_TIME
+
+
+
+# Check whether --with-ssse3 was given.
+if test "${with_ssse3+set}" = set; then :
+  withval=$with_ssse3;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSSE3 is available at compile time" >&5
+$as_echo_n "checking whether SSSE3 is available at compile time... " >&6; }
+
+if test "$with_ssse3" = "yes" -o "$with_ssse3" = ""; then
+
+    rm -f detectssse3.cpp
+    echo '#ifdef __SSSE3__' > detectssse3.cpp
+    echo '#include <tmmintrin.h>' >> detectssse3.cpp
+    echo 'void foo() { __m128i xmm_i = _mm_set1_epi16(0); xmm_i = _mm_shuffle_epi8(xmm_i, xmm_i); }  int main() { return 0; }' >> detectssse3.cpp
+    echo '#else' >> detectssse3.cpp
+    echo 'some_error' >> detectssse3.cpp
+    echo '#endif' >> detectssse3.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o detectssse3 detectssse3.cpp 2>&1`" ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+        SSSE3FLAGS=""
+        HAVE_SSSE3_AT_COMPILE_TIME=yes
+    else
+        if test -z "`${CXX} ${CXXFLAGS} -mssse3 -o detectssse3 detectssse3.cpp 2>&1`" ; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+            SSSE3FLAGS="-mssse3"
+            HAVE_SSSE3_AT_COMPILE_TIME=yes
+        else
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+            if test "$with_ssse3" = "yes"; then
+                as_fn_error $? "--with-ssse3 was requested, but SSSE3 is not available" "$LINENO" 5
+            fi
+        fi
+    fi
+
+                    if test "$HAVE_SSSE3_AT_COMPILE_TIME" = "yes"; then
+       case $host_os in
+         solaris*)
+           { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether SSSE3 is available and needed at runtime" >&5
+$as_echo_n "checking whether SSSE3 is available and needed at runtime... " >&6; }
+           if ./detectssse3; then
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+           else
+             { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+             if test "$with_ssse3" = "yes"; then
+               echo "Caution: the generated binaries will not run on this system."
+             else
+               echo "Disabling SSSE3 as it is not explicitly required"
+               HAVE_SSSE3_AT_COMPILE_TIME=""
+               SSSE3FLAGS=""
+             fi
+           fi
+           ;;
+       esac
+    fi
+
+    if test "$HAVE_SSSE3_AT_COMPILE_TIME" = "yes"; then
+        CFLAGS="-DHAVE_SSSE3_AT_COMPILE_TIME $CFLAGS"
+        CXXFLAGS="-DHAVE_SSSE3_AT_COMPILE_TIME $CXXFLAGS"
+    fi
+
+    rm -rf detectssse3*
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+SSSE3FLAGS=$SSSE3FLAGS
 
 
 
@@ -18514,7 +19758,12 @@ $as_echo "no" >&6; }
        esac
     fi
 
-    rm -f detectavx*
+    if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
+        CFLAGS="-DHAVE_AVX_AT_COMPILE_TIME $CFLAGS"
+        CXXFLAGS="-DHAVE_AVX_AT_COMPILE_TIME $CXXFLAGS"
+    fi
+
+    rm -rf detectavx*
 else
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
@@ -18522,8 +19771,6 @@ fi
 
 AVXFLAGS=$AVXFLAGS
 
-HAVE_AVX_AT_COMPILE_TIME=$HAVE_AVX_AT_COMPILE_TIME
-
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking to enable LTO (link time optimization) build" >&5
@@ -18535,8 +19782,8 @@ if test "${enable_lto+set}" = set; then :
 fi
 
 
-CFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CFLAGS"
 CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
+CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT="$CXXFLAGS"
 
 if test "x$enable_lto" = "xyes" ; then
 
@@ -18551,10 +19798,14 @@ if test "x$enable_lto" = "xyes" ; then
 
       if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
     if test "$AVXFLAGS" = ""; then
-        CFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CFLAGS"
         CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
     fi
   fi
+  if test "$HAVE_SSSE3_AT_COMPILE_TIME" = "yes"; then
+    if test "$SSSE3FLAGS" = ""; then
+        CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT="$CXXFLAGS"
+    fi
+  fi
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
@@ -18563,10 +19814,10 @@ else
 $as_echo "no" >&6; }
 fi
 
-CFLAGS_NO_LTO_IF_AVX_NONDEFAULT=$CFLAGS_NO_LTO_IF_AVX_NONDEFAULT
-
 CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT=$CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT
 
+CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT=$CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT
+
 
 
 echo "#include <winsock2.h>" > test_ws2_32.c
@@ -18579,6 +19830,17 @@ fi
 rm -f test_ws2_32*
 
 
+echo "#include <windows.h>" > test_psapi.c
+echo "#include <psapi.h>" >> test_psapi.c
+echo "void foo() {}" >> test_psapi.c
+
+if test -z "`${CC} -c test_psapi.c 2>&1`" ; then
+  LIBS="$LIBS -lpsapi"
+fi
+rm -f test_psapi*
+
+
+
 echo "#include <sys/types.h>" > test_getaddrinfo.c
 echo "#include <sys/socket.h>" >> test_getaddrinfo.c
 echo "#include <netdb.h>" >> test_getaddrinfo.c
@@ -20390,108 +21652,6 @@ fi
   if test "${HAVE_PG}" = "yes" ; then
     LIBS=-L`$PG_CONFIG --libdir`" -lpq $LIBS"
     PG_INC=-I`$PG_CONFIG --includedir`" -I"`$PG_CONFIG --includedir-server`
-
-    PG_EXTRA_DEC=""
-    saved_LIBS="$LIBS"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQputCopyData in -lpq" >&5
-$as_echo_n "checking for PQputCopyData in -lpq... " >&6; }
-if ${ac_cv_lib_pq_PQputCopyData+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpq  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char PQputCopyData ();
-int
-main ()
-{
-return PQputCopyData ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_pq_PQputCopyData=yes
-else
-  ac_cv_lib_pq_PQputCopyData=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQputCopyData" >&5
-$as_echo "$ac_cv_lib_pq_PQputCopyData" >&6; }
-if test "x$ac_cv_lib_pq_PQputCopyData" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBPQ 1
-_ACEOF
-
-  LIBS="-lpq $LIBS"
-
-else
-  DEFINE_PG_PRE74=-DPG_PRE74
-fi
-
-    LIBS="$saved_LIBS"
-    if test "$DEFINE_PG_PRE74" != "" ; then
-      echo "The PostgreSQL client version is before 7.4. You will not be able to use binary cursors."
-    fi
-
-    saved_LIBS="$LIBS"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PQescapeStringConn in -lpq" >&5
-$as_echo_n "checking for PQescapeStringConn in -lpq... " >&6; }
-if ${ac_cv_lib_pq_PQescapeStringConn+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_check_lib_save_LIBS=$LIBS
-LIBS="-lpq  $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char PQescapeStringConn ();
-int
-main ()
-{
-return PQescapeStringConn ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
-  ac_cv_lib_pq_PQescapeStringConn=yes
-else
-  ac_cv_lib_pq_PQescapeStringConn=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pq_PQescapeStringConn" >&5
-$as_echo "$ac_cv_lib_pq_PQescapeStringConn" >&6; }
-if test "x$ac_cv_lib_pq_PQescapeStringConn" = xyes; then :
-  DEFINE_PG_HAS_PQESCAPESTRINGCONN=-DPG_HAS_PQESCAPESTRINGCONN
-fi
-
-    LIBS="$saved_LIBS"
-    if test "$DEFINE_PG_HAS_PQESCAPESTRINGCONN" = "" ; then
-      echo "falling back to using PQescapeString. You should upgrade at least to security releases 8.1.4, 8.0.8, 7.4.13, 7.3.15."
-    fi
-
-    PG_INC="${PG_INC} ${DEFINE_PG_PRE74} ${DEFINE_PG_HAS_PQESCAPESTRINGCONN}"
   fi
 
 fi
@@ -22234,30 +23394,49 @@ if test -z "$with_sosi" -o "$with_sosi" = "no" ; then
 
   echo "SOSI support disabled."
 
-elif test "$with_sosi" = "yes" -o "$with_sosi" = "" ; then
+elif test "$with_sosi" = "yes" ; then
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libfyba.a, libfygm.a and libfyut.a in /usr/local/lib" >&5
-$as_echo_n "checking for libfyba.a, libfygm.a and libfyut.a in /usr/local/lib... " >&6; }
-    if test -r /usr/local/lib/libfyba.a -a -r /usr/local/lib/libfygm.a -a -r /usr/local/lib/libfyut.a ; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libfyba" >&5
+$as_echo_n "checking for libfyba... " >&6; }
+
+    rm -f testfyba.*
+    rm -f testfyba
+    echo "#include <fyba.h>" > testfyba.cpp
+    echo "int main() { LC_Init(); return 0; }" >> testfyba.cpp
+    if test  -r /usr/include/fyba -a -z "`${CXX} ${CPPFLAGS} -I/usr/include/fyba -DLINUX testfyba.cpp -lfyba -lfygm -lfyut -o testfyba 2>&1`" ; then
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
 $as_echo "found" >&6; }
         SOSI_ENABLED=yes
-        SOSI_LIB="/usr/local/lib/libfyba.a /usr/local/lib/libfygm.a /usr/local/lib/libfyut.a"
+        SOSI_LIB="-lfyba -lfygm -lfyut"
+        SOSI_INC="-I/usr/include/fyba"
     else
-        as_fn_error $? "not found." "$LINENO" 5
-    fi
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libfyba.a, libfygm.a and libfyut.a in /usr/local/lib" >&5
+$as_echo_n "checking for libfyba.a, libfygm.a and libfyut.a in /usr/local/lib... " >&6; }
+        if test -r /usr/local/lib/libfyba.a -a -r /usr/local/lib/libfygm.a -a -r /usr/local/lib/libfyut.a ; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+            SOSI_ENABLED=yes
+            SOSI_LIB="/usr/local/lib/libfyba.a /usr/local/lib/libfygm.a /usr/local/lib/libfyut.a"
+        else
+            as_fn_error $? "not found." "$LINENO" 5
+        fi
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fyba.h, fygm.h and fyut.h in /usr/local/include/fyba" >&5
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fyba.h, fygm.h and fyut.h in /usr/local/include/fyba" >&5
 $as_echo_n "checking for fyba.h, fygm.h and fyut.h in /usr/local/include/fyba... " >&6; }
-    if test -r /usr/local/include/fyba/fyba.h -a -r /usr/local/include/fyba/fygm.h -a -r /usr/local/include/fyba/fyut.h ; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+        if test -r /usr/local/include/fyba/fyba.h -a -r /usr/local/include/fyba/fygm.h -a -r /usr/local/include/fyba/fyut.h ; then
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
 $as_echo "found" >&6; }
-        SOSI_ENABLED=yes
-        SOSI_INC="-I/usr/local/include/fyba"
-    else
-        as_fn_error $? "not found." "$LINENO" 5
+            SOSI_ENABLED=yes
+            SOSI_INC="-I/usr/local/include/fyba"
+        else
+            as_fn_error $? "not found." "$LINENO" 5
+        fi
     fi
 
+    rm -f testfyba.*
+    rm -f testfyba
 else
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libfyba.a, libfygm.a and libfyut.a in $with_sosi/lib" >&5
@@ -22797,7 +23976,202 @@ if test "$with_hdf5" = "no" ; then
 
 elif test "$with_hdf5" = "yes" -o "$with_hdf5" = "" ; then
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for H5Fopen in -lhdf5" >&5
+  HDF5_CFLAGS=""
+  HDF5_LIBS=""
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+	if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+  ac_pt_PKG_CONFIG=$PKG_CONFIG
+  # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $ac_pt_PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_pt_PKG_CONFIG" = x; then
+    PKG_CONFIG=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    PKG_CONFIG=$ac_pt_PKG_CONFIG
+  fi
+else
+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+	_pkg_min_version=0.25
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	else
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+		PKG_CONFIG=""
+	fi
+
+fi # check and set $PKG_CONFIG
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for HDF5" >&5
+$as_echo_n "checking for HDF5... " >&6; }
+
+if test -n "$PKG_CONFIG"; then
+    if test -n "$HDF5_CFLAGS"; then
+        pkg_cv_HDF5_CFLAGS="$HDF5_CFLAGS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"hdf5\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "hdf5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_HDF5_CFLAGS=`$PKG_CONFIG --cflags "hdf5" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+	pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+    if test -n "$HDF5_LIBS"; then
+        pkg_cv_HDF5_LIBS="$HDF5_LIBS"
+    else
+        if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"hdf5\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "hdf5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_HDF5_LIBS=`$PKG_CONFIG --libs "hdf5" 2>/dev/null`
+else
+  pkg_failed=yes
+fi
+    fi
+else
+	pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+	        HDF5_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "hdf5"`
+        else
+	        HDF5_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "hdf5"`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$HDF5_PKG_ERRORS" >&5
+
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+                HAVE_HDF5=no
+elif test $pkg_failed = untried; then
+	HAVE_HDF5=no
+else
+	HDF5_CFLAGS=$pkg_cv_HDF5_CFLAGS
+	HDF5_LIBS=$pkg_cv_HDF5_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	HAVE_HDF5=yes
+fi
+
+  if test "$HAVE_HDF5" = "yes"; then
+
+    # Test that the package found is for the right architecture
+    saved_LIBS="$LIBS"
+    LIBS="$HDF5_LIBS"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for H5Fopen in -lhdf5" >&5
 $as_echo_n "checking for H5Fopen in -lhdf5... " >&6; }
 if ${ac_cv_lib_hdf5_H5Fopen+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -22839,13 +24213,65 @@ else
   HAVE_HDF5=no
 fi
 
+    LIBS="$saved_LIBS"
+
+    if test "$HAVE_HDF5" = "yes"; then
+        LIBS="$HDF5_LIBS $LIBS"
+        HDF5_INCLUDE="$HDF5_CFLAGS"
+    fi
+
+  else
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for H5Fopen in -lhdf5" >&5
+$as_echo_n "checking for H5Fopen in -lhdf5... " >&6; }
+if ${ac_cv_lib_hdf5_H5Fopen+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lhdf5  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char H5Fopen ();
+int
+main ()
+{
+return H5Fopen ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_hdf5_H5Fopen=yes
+else
+  ac_cv_lib_hdf5_H5Fopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hdf5_H5Fopen" >&5
+$as_echo "$ac_cv_lib_hdf5_H5Fopen" >&6; }
+if test "x$ac_cv_lib_hdf5_H5Fopen" = xyes; then :
+  HAVE_HDF5=yes
+else
+  HAVE_HDF5=no
+fi
 
-  if test "$HAVE_HDF5" = "yes" ; then
-    LIBS="-lhdf5 $LIBS"
-  fi
 
-  if test "$HAVE_HDF5" = "yes" -a -r /usr/include/hdf5.h ; then
-    HDF5_INCLUDE="-I/usr/include"
+    if test "$HAVE_HDF5" = "yes" ; then
+        LIBS="-lhdf5 $LIBS"
+    fi
+
+        if test "$HAVE_HDF5" = "yes" -a -r /usr/include/hdf5.h ; then
+        HDF5_INCLUDE="-I/usr/include"
+    fi
   fi
 
 else
@@ -23841,6 +25267,7 @@ fi
 
 
 FGDB_ENABLED=no
+FGDB_LIB=
 
 if test "$with_fgdb" = "no" ; then
 
@@ -23901,6 +25328,51 @@ $as_echo "found." >&6; }
 
 fi
 
+if test "$FGDB_LIB" != ""; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pj_datums in -lFileGDBAPI" >&5
+$as_echo_n "checking for pj_datums in -lFileGDBAPI... " >&6; }
+if ${ac_cv_lib_FileGDBAPI_pj_datums+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lFileGDBAPI $FGDB_LIB $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pj_datums ();
+int
+main ()
+{
+return pj_datums ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_FileGDBAPI_pj_datums=yes
+else
+  ac_cv_lib_FileGDBAPI_pj_datums=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_FileGDBAPI_pj_datums" >&5
+$as_echo "$ac_cv_lib_FileGDBAPI_pj_datums" >&6; }
+if test "x$ac_cv_lib_FileGDBAPI_pj_datums" = xyes; then :
+  FGDB_HAS_PROJ4=yes
+else
+  FGDB_HAS_PROJ4=no
+fi
+
+fi
+
 FGDB_ENABLED=$FGDB_ENABLED
 
 FGDB_LIB=$FGDB_LIB
@@ -24361,6 +25833,96 @@ fi
 
 
 
+# Check whether --with-jp2lura was given.
+if test "${with_jp2lura+set}" = set; then :
+  withval=$with_jp2lura;
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JP2Lura support" >&5
+$as_echo_n "checking for JP2Lura support... " >&6; }
+
+HAVE_JP2LURA=no
+JP2LURA_INCLUDE=
+
+if test "$with_jp2lura" != "" -a "$with_jp2lura" != "no" ; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lwf_jp2.h" >&5
+$as_echo_n "checking for lwf_jp2.h... " >&6; }
+  if test -f "$with_jp2lura/include/lwf_jp2.h"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+    as_fn_error $? "JP2Lura support requested but header not found" "$LINENO" 5
+  fi
+  JP2LURA_INCLUDE="-I$with_jp2lura/include"
+
+  # mingw support
+  if test -f "$with_jp2lura/library/lwf_jp2.lib"; then
+      ln -s "$with_jp2lura/library/lwf_jp2.lib" "$with_jp2lura/library/lib_lwf_jp2.a"
+  fi
+
+  ORIG_LIBS="$LIBS"
+  LIBS="-L$with_jp2lura/library"
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for JP2_Decompress_SetLicense in -l_lwf_jp2" >&5
+$as_echo_n "checking for JP2_Decompress_SetLicense in -l_lwf_jp2... " >&6; }
+if ${ac_cv_lib__lwf_jp2_JP2_Decompress_SetLicense+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-l_lwf_jp2 -lm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char JP2_Decompress_SetLicense ();
+int
+main ()
+{
+return JP2_Decompress_SetLicense ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib__lwf_jp2_JP2_Decompress_SetLicense=yes
+else
+  ac_cv_lib__lwf_jp2_JP2_Decompress_SetLicense=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib__lwf_jp2_JP2_Decompress_SetLicense" >&5
+$as_echo "$ac_cv_lib__lwf_jp2_JP2_Decompress_SetLicense" >&6; }
+if test "x$ac_cv_lib__lwf_jp2_JP2_Decompress_SetLicense" = xyes; then :
+  HAVE_JP2LURA="yes"
+fi
+
+
+  if test "$HAVE_JP2LURA" = "no" ; then
+    as_fn_error $? "JP2Lura support requested but library not found" "$LINENO" 5
+  fi
+
+  LIBS="-L$with_jp2lura/library -l_lwf_jp2 -lm $ORIG_LIBS"
+fi
+
+JP2LURA_INCLUDE=$JP2LURA_INCLUDE
+
+
+if test "$HAVE_JP2LURA" != "no" ; then
+  OPT_GDAL_FORMATS="jp2lura $OPT_GDAL_FORMATS"
+fi
+
+
+
 # Check whether --with-msg was given.
 if test "${with_msg+set}" = set; then :
   withval=$with_msg;
@@ -24790,10 +26352,7 @@ OPT_GDAL_FORMATS=$OPT_GDAL_FORMATS
 
 
 
-OGR_ENABLED=yes
-
-
-GNM_ENABLED=no
+GNM_ENABLED=yes
 
 
 # Check whether --with-gnm was given.
@@ -24802,15 +26361,14 @@ if test "${with_gnm+set}" = set; then :
 fi
 
 
-if test "$with_gnm" = "" ; then
+if test "$with_gnm" = "no" ; then
   GNM_ENABLED=no
-  echo "GNM support disabled."
-elif test "$with_gnm" = "yes"; then
-  echo checking for GNM ... enabled
-  GNM_ENABLED=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled by user" >&5
+$as_echo "disabled by user" >&6; }
 else
-  echo checking for GNM ... disabled by user
-  GNM_ENABLED=no
+  GNM_ENABLED=yes
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
+$as_echo "enabled" >&6; }
 fi
 GNM_ENABLED=$GNM_ENABLED
 
@@ -24959,7 +26517,7 @@ INGRES_INC=$INGRES_INC
 
 
 
-XERCES_REQ_VERSION="2.7.0"
+XERCES_REQ_VERSION="3.1.0"
 
 
 # Check whether --with-xerces was given.
@@ -25045,7 +26603,7 @@ fi
         CPPFLAGS="$CPPFLAGS -I$xerces_include_dir -I$xerces_include_dir2"
 
         saved_LIBS="$LIBS"
-        LIBS="$LIBS $xerces_lib_flags"
+        LIBS="$xerces_lib_flags $LIBS"
 
                                 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Xerces C++ Parser headers in $xerces_include_dir and $xerces_include_dir2" >&5
 $as_echo_n "checking for Xerces C++ Parser headers in $xerces_include_dir and $xerces_include_dir2... " >&6; }
@@ -25161,13 +26719,10 @@ $as_echo_n "checking for Xerces C++ Parser... " >&6; }
 
     if test "$run_xerces_test" = "yes"; then
         if test "$xerces_header_found" = "yes" -a "$xerces_lib_found" = "yes"; then
-
-
-
-
             HAVE_XERCES="yes"
         else
             XERCES_CFLAGS=""
+            XERCES_LDFLAGS=""
             HAVE_XERCES="no"
         fi
 
@@ -25217,8 +26772,15 @@ $as_echo "yes" >&6; }
                     else
                         { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-                        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Found Xerces C++ Parser $XERCES_VERSION, which is older than required. Possible compilation failure." >&5
-$as_echo "$as_me: WARNING: Found Xerces C++ Parser $XERCES_VERSION, which is older than required. Possible compilation failure." >&2;}
+                        if test "$xerces_requested" = "yes"; then
+                            as_fn_error $? "Found Xerces C++ Parser $XERCES_VERSION, which is older than required." "$LINENO" 5
+                        else
+                            { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Found Xerces C++ Parser $XERCES_VERSION, which is older than required. Disabling it" >&5
+$as_echo "$as_me: WARNING: Found Xerces C++ Parser $XERCES_VERSION, which is older than required. Disabling it" >&2;}
+                            XERCES_CFLAGS=""
+                            XERCES_LDFLAGS=""
+                            HAVE_XERCES="no"
+                        fi
                     fi
                 else
                     { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
@@ -25229,6 +26791,9 @@ $as_echo "$as_me: WARNING: Missing header XercesVersion.hpp. Unable to determine
             fi
         fi
 
+
+
+
     else
         HAVE_XERCES="no"
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HAVE_XERCES" >&5
@@ -25876,6 +27441,65 @@ $as_echo "yes" >&6; }
 fi
 
     if test -n "$LIBKML_VERSION" -a -n "$libkml_prefix"; then
+        # Test that the package found is for the right architecture
+        saved_CPPFLAGS="$CPPFLAGS"
+        saved_LIBS="$LIBS"
+        CPPFLAGS="$CPPFLAGS $LIBKML_CFLAGS"
+        LIBS="$LIBKML_LIBS"
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libkml can be linked" >&5
+$as_echo_n "checking if libkml can be linked... " >&6; }
+        ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+#include <kml/dom.h>
+
+int
+main ()
+{
+
+kmldom::KmlFactory* factory = kmldom::KmlFactory::GetFactory();
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+            HAVE_LIBKML=yes
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+            HAVE_LIBKML=no
+            { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+        ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+        CPPFLAGS="$saved_CPPFLAGS"
+        LIBS="$saved_LIBS"
+    fi
+
+    if test "$HAVE_LIBKML" = "yes"; then
         HAVE_LIBKML="yes"
 
 	LIBKML_LDFLAGS="$LIBKML_LIBS"
@@ -26815,7 +28439,7 @@ $as_echo "libdap $LIBDAP_VER" >&6; }
                         rm -f islibdappost310.*
         echo '#include "Connect.h"' > islibdappost310.cpp
         echo 'int main(int argc, char** argv) { return 0; } ' >> islibdappost310.cpp
-        if test -z "`${CXX} islibdappost310.cpp -c ${DODS_INC} ${CPPFLAGS} 2>&1`" ; then
+        if test -z "`${CXX} ${CXXFLAGS} islibdappost310.cpp -c ${DODS_INC} ${CPPFLAGS} 2>&1`" ; then
                     DODS_INC="$DODS_INC -DLIBDAP_310 -DLIBDAP_39"
             { $as_echo "$as_me:${as_lineno-$LINENO}: result: libdap >= 3.10" >&5
 $as_echo "libdap >= 3.10" >&6; }
@@ -26828,7 +28452,7 @@ $as_echo "libdap < 3.10" >&6; }
             echo '#include "AttrTable.h"' >> islibdappre39.cpp
             echo 'using namespace libdap;' >> islibdappre39.cpp
             echo 'int main(int argc, char** argv) { DAS oDAS; AttrTable& oAttrTable = oDAS; } ' >> islibdappre39.cpp
-            if test -z "`${CXX} islibdappre39.cpp -c ${DODS_INC} 2>&1`" ; then
+            if test -z "`${CXX} ${CXXFLAGS} islibdappre39.cpp -c ${DODS_INC} 2>&1`" ; then
                             { $as_echo "$as_me:${as_lineno-$LINENO}: result: libdap < 3.9" >&5
 $as_echo "libdap < 3.9" >&6; }
             else
@@ -28047,6 +29671,148 @@ SQLITE_HAS_COLUMN_METADATA=$SQLITE_HAS_COLUMN_METADATA
 HAVE_SQLITE=$HAVE_SQLITE3
 
 
+
+# Check whether --with-rasterlite2 was given.
+if test "${with_rasterlite2+set}" = set; then :
+  withval=$with_rasterlite2;
+fi
+
+
+HAVE_RASTERLITE2=no
+RASTERLITE2_CFLAGS=
+
+if test -z "$with_rasterlite2" -o "$with_rasterlite2" = "no"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: rasterlite2 support disabled" >&5
+$as_echo "$as_me: rasterlite2 support disabled" >&6;}
+elif test "$with_rasterlite2" = "yes"; then
+    for ac_header in rasterlite2/rasterlite2.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "rasterlite2/rasterlite2.h" "ac_cv_header_rasterlite2_rasterlite2_h" "$ac_includes_default"
+if test "x$ac_cv_header_rasterlite2_rasterlite2_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_RASTERLITE2_RASTERLITE2_H 1
+_ACEOF
+
+fi
+
+done
+
+    if test "$ac_cv_header_rasterlite2_rasterlite2_h" = "yes"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl2_load_raw_tiles_into_dbms in -lrasterlite2" >&5
+$as_echo_n "checking for rl2_load_raw_tiles_into_dbms in -lrasterlite2... " >&6; }
+if ${ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrasterlite2  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rl2_load_raw_tiles_into_dbms ();
+int
+main ()
+{
+return rl2_load_raw_tiles_into_dbms ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms=yes
+else
+  ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms" >&5
+$as_echo "$ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms" >&6; }
+if test "x$ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms" = xyes; then :
+  HAVE_RASTERLITE2=yes
+else
+  HAVE_RASTERLITE2=no
+fi
+
+        if test "$HAVE_RASTERLITE2" = "yes"; then
+            LIBS="$LIBS -lrasterlite2 -lsqlite3"
+        else
+            as_fn_error $? "did not find rl2_load_raw_tiles_into_dbms" "$LINENO" 5
+        fi
+    else
+        as_fn_error $? "did not find rasterlite2.h" "$LINENO" 5
+    fi
+else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for include/rasterlite2/rasterlite2.h" >&5
+$as_echo_n "checking for include/rasterlite2/rasterlite2.h... " >&6; }
+    if test -f "$with_rasterlite2/include/rasterlite2/rasterlite2.h"; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
+$as_echo "found" >&6; }
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rl2_load_raw_tiles_into_dbms in -lrasterlite2" >&5
+$as_echo_n "checking for rl2_load_raw_tiles_into_dbms in -lrasterlite2... " >&6; }
+if ${ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrasterlite2 -L$with_rasterlite2/lib $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char rl2_load_raw_tiles_into_dbms ();
+int
+main ()
+{
+return rl2_load_raw_tiles_into_dbms ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms=yes
+else
+  ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms" >&5
+$as_echo "$ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms" >&6; }
+if test "x$ac_cv_lib_rasterlite2_rl2_load_raw_tiles_into_dbms" = xyes; then :
+  HAVE_RASTERLITE2=yes
+else
+  HAVE_RASTERLITE2=no
+fi
+
+        if test "$HAVE_RASTERLITE2" = "yes"; then
+            RASTERLITE2_CFLAGS="-I$with_rasterlite2/include"
+            LIBS="$LIBS -L$with_rasterlite2/lib -lrasterlite2 -lsqlite3"
+        else
+            as_fn_error $? "did not find rl2_load_raw_tiles_into_dbms" "$LINENO" 5
+        fi
+    else
+        as_fn_error $? "did not find rasterlite2.h" "$LINENO" 5
+    fi
+fi
+
+HAVE_RASTERLITE2=$HAVE_RASTERLITE2
+
+RASTERLITE2_CFLAGS=$RASTERLITE2_CFLAGS
+
+
+
 HAVE_PCRE=no
 
 
@@ -28134,39 +29900,47 @@ fi
 
 
 
-DWGDIRECT=
-DWG_PLT=
+TEIGHA_DIR=
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Checking for DWGdirect" >&5
-$as_echo_n "checking Checking for DWGdirect... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Checking for Teigha" >&5
+$as_echo_n "checking Checking for Teigha... " >&6; }
 
-# Check whether --with-dwgdirect was given.
-if test "${with_dwgdirect+set}" = set; then :
-  withval=$with_dwgdirect;
+# Check whether --with-teigha was given.
+if test "${with_teigha+set}" = set; then :
+  withval=$with_teigha;
 fi
 
 
-if test -z "$with_dwgdirect" -o "$with_dwgdirect" = "no"; then
+if test -z "$with_teigha" -o "$with_teigha" = "no"; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
 $as_echo "disabled" >&6; }
-    HAVE_DWGDIRECT=no
+    HAVE_TEIGHA=no
 else
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled" >&5
 $as_echo "enabled" >&6; }
 
 
-# Check whether --with-dwgdirect was given.
-if test "${with_dwgdirect+set}" = set; then :
-  withval=$with_dwgdirect;
-fi
-
-    if test "x$with_dwg_plt" != "x" ; then
-        DWG_PLT=$with_dwg_plt
+# Check whether --with-teigha-plt was given.
+if test "${with_teigha_plt+set}" = set; then :
+  withval=$with_teigha_plt;
+fi
+
+    if test "x$with_teigha_plt" != "x" ; then
+        TEIGHA_DIR=$with_teigha
+        HAVE_TEIGHA=yes
+        TEIGHA_PLT=$with_teigha_plt
+        LIBS="${LIBS} ${TEIGHA_DIR}/bin/${TEIGHA_PLT}/TG_Db.tx"
+        LIBS="${LIBS} ${TEIGHA_DIR}/lib/${TEIGHA_PLT}/libTG_ExamplesCommon.a"
+        LIBS="${LIBS} ${TEIGHA_DIR}/lib/${TEIGHA_PLT}/libTD_ExamplesCommon.a"
+        LIBS="${LIBS} ${TEIGHA_DIR}/lib/${TEIGHA_PLT}/libTD_Key.a"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_Db"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_DbRoot"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_Root"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_Ge"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_Alloc"
     else
-        DWG_PLT=lnxX86
+        as_fn_error $? "--with-teigha-plt not specified" "$LINENO" 5
     fi
-    DWGDIRECT=$with_dwgdirect
-    HAVE_DWGDIRECT=yes
 fi
 
 
@@ -28723,7 +30497,7 @@ fi
 
 WEBP_SETTING=no
 
-if test "$with_webp" = "yes" ; then
+if test "$with_webp" = "yes" -o "$with_webp" = "" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for WebPDecodeRGB in -lwebp" >&5
 $as_echo_n "checking for WebPDecodeRGB in -lwebp... " >&6; }
@@ -29108,6 +30882,281 @@ fi
 
 
 
+
+
+
+
+
+
+# Check whether --with-sfcgal was given.
+if test "${with_sfcgal+set}" = set; then :
+  withval=$with_sfcgal;
+fi
+
+
+  ac_sfcgal_config_auto=no
+
+  if test x"$with_sfcgal" = x"no" ; then
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: SFCGAL support disabled" >&5
+$as_echo "SFCGAL support disabled" >&6; }
+    SFCGAL_CONFIG=no
+
+  elif test x"$with_sfcgal" = x"yes" -o x"$with_sfcgal" = x"" ; then
+
+    # Extract the first word of "sfcgal-config", so it can be a program name with args.
+set dummy sfcgal-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_SFCGAL_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $SFCGAL_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_SFCGAL_CONFIG="$SFCGAL_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_SFCGAL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_SFCGAL_CONFIG" && ac_cv_path_SFCGAL_CONFIG="no"
+  ;;
+esac
+fi
+SFCGAL_CONFIG=$ac_cv_path_SFCGAL_CONFIG
+if test -n "$SFCGAL_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SFCGAL_CONFIG" >&5
+$as_echo "$SFCGAL_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    ac_sfcgal_config_auto=yes
+
+  else
+
+   ac_sfcgal_config=`basename "$with_sfcgal"`
+   ac_sfcgal_config_dir=`$as_dirname -- "$with_sfcgal" ||
+$as_expr X"$with_sfcgal" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$with_sfcgal" : 'X\(//\)[^/]' \| \
+	 X"$with_sfcgal" : 'X\(//\)$' \| \
+	 X"$with_sfcgal" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$with_sfcgal" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+   # Extract the first word of ""$ac_sfcgal_config"", so it can be a program name with args.
+set dummy "$ac_sfcgal_config"; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_SFCGAL_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$SFCGAL_CONFIG"; then
+  ac_cv_prog_SFCGAL_CONFIG="$SFCGAL_CONFIG" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in "$ac_sfcgal_config_dir"
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "
+   "; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_SFCGAL_CONFIG="$with_sfcgal"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_SFCGAL_CONFIG
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set SFCGAL_CONFIG to just the basename; use the full file name.
+    shift
+    ac_cv_prog_SFCGAL_CONFIG="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+  test -z "$ac_cv_prog_SFCGAL_CONFIG" && ac_cv_prog_SFCGAL_CONFIG="no"
+fi
+fi
+SFCGAL_CONFIG=$ac_cv_prog_SFCGAL_CONFIG
+if test -n "$SFCGAL_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SFCGAL_CONFIG" >&5
+$as_echo "$SFCGAL_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+  fi
+
+  if test x"$SFCGAL_CONFIG" != x"no" ; then
+
+    min_sfcgal_version=1.2.2
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SFCGAL version >= $min_sfcgal_version" >&5
+$as_echo_n "checking for SFCGAL version >= $min_sfcgal_version... " >&6; }
+
+    sfcgal_major_version=`$SFCGAL_CONFIG --version | \
+       sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'`
+    sfcgal_minor_version=`$SFCGAL_CONFIG --version | \
+       sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'`
+    sfcgal_micro_version=`$SFCGAL_CONFIG --version | \
+       sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'`
+
+    req_major=`echo $min_sfcgal_version | \
+       sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'`
+    req_minor=`echo $min_sfcgal_version | \
+       sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'`
+    req_micro=`echo $min_sfcgal_version | \
+       sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'`
+
+    version_ok="no"
+    ac_req_version=`expr $req_major \* 100000 \+  $req_minor \* 100 \+ $req_micro`
+    ac_sfcgal_version=`expr $sfcgal_major_version \* 100000 \+  $sfcgal_minor_version \* 100 \+ $sfcgal_micro_version`
+
+    if test $ac_req_version -le $ac_sfcgal_version; then
+        version_ok="yes"
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+    fi
+
+    if test $version_ok = "no"; then
+
+      HAVE_SFCGAL="no"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+      if test $ac_sfcgal_config_auto = "yes" ; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SFCGAL was found on your system, but sfcgal-config reports version ${sfcgal_major_version}.${sfcgal_minor_version}.${sfcgal_micro_version}, need at least $min_sfcgal_version. SFCGAL support disabled." >&5
+$as_echo "$as_me: WARNING: SFCGAL was found on your system, but sfcgal-config reports version ${sfcgal_major_version}.${sfcgal_minor_version}.${sfcgal_micro_version}, need at least $min_sfcgal_version. SFCGAL support disabled." >&2;}
+      else
+        as_fn_error $? "sfcgal-config reports version ${sfcgal_major_version}.${sfcgal_minor_version}.${sfcgal_micro_version}, need at least $min_sfcgal_version or configure --without-sfcgal" "$LINENO" 5
+      fi
+
+    else
+
+      HAVE_SFCGAL="no"
+
+      SFCGAL_LIBS="`${SFCGAL_CONFIG} --libs`"
+      SFCGAL_CFLAGS="`${SFCGAL_CONFIG} --cflags`"
+      SFCGAL_VERSION="`${SFCGAL_CONFIG} --version`"
+
+      ax_save_LIBS="${LIBS}"
+      LIBS=${SFCGAL_LIBS}
+      ax_save_CFLAGS="${CFLAGS}"
+      CFLAGS="${SFCGAL_CFLAGS}"
+
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sfcgal_version in -lSFCGAL" >&5
+$as_echo_n "checking for sfcgal_version in -lSFCGAL... " >&6; }
+if ${ac_cv_lib_SFCGAL_sfcgal_version+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lSFCGAL
+       $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sfcgal_version ();
+int
+main ()
+{
+return sfcgal_version ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_SFCGAL_sfcgal_version=yes
+else
+  ac_cv_lib_SFCGAL_sfcgal_version=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SFCGAL_sfcgal_version" >&5
+$as_echo "$ac_cv_lib_SFCGAL_sfcgal_version" >&6; }
+if test "x$ac_cv_lib_SFCGAL_sfcgal_version" = xyes; then :
+  HAVE_SFCGAL="yes"
+else
+  HAVE_SFCGAL="no"
+fi
+
+
+
+      if test x"$HAVE_SFCGAL" = "xno"; then
+          SFCGAL_CFLAGS=""
+      fi
+
+      CFLAGS="${ax_save_CFLAGS}"
+      LIBS="${ax_save_LIBS}"
+
+    fi
+
+  fi
+
+HAVE_SFCGAL_RESULT="no"
+if test "${HAVE_SFCGAL}" = "yes" ; then
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: Using C API from SFCGAL $SFCGAL_VERSION" >&5
+$as_echo "$as_me: Using C API from SFCGAL $SFCGAL_VERSION" >&6;}
+  LIBS="${SFCGAL_LIBS} ${LIBS}"
+  HAVE_SFCGAL_RESULT="yes"
+fi
+
+
+
 # Check whether --with-qhull was given.
 if test "${with_qhull+set}" = set; then :
   withval=$with_qhull;
@@ -29182,11 +31231,7 @@ fi
 
     if test "$QHULL_SETTING" = "yes"; then
         QHULL_SETTING=external
-        if test -f /usr/include/qhull/libqhull.h; then
-            EXTRA_INCLUDES="-I/usr/include/qhull $EXTRA_INCLUDES"
-        else
-            EXTRA_INCLUDES="-I/usr/local/include/qhull $EXTRA_INCLUDES"
-        fi
+        QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=0
         LIBS="-lqhull $LIBS"
     fi
   fi
@@ -29247,11 +31292,7 @@ fi
 
     if test "$QHULL_SETTING" = "yes"; then
         QHULL_SETTING=external
-        if test -f /usr/include/libqhull/libqhull.h; then
-            EXTRA_INCLUDES="-I/usr/include/libqhull $EXTRA_INCLUDES"
-        else
-            EXTRA_INCLUDES="-I/usr/local/include/libqhull $EXTRA_INCLUDES"
-        fi
+        QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=1
         LIBS="-lqhull $LIBS"
     fi
   fi
@@ -29261,14 +31302,18 @@ fi
         as_fn_error $? "--with-qhull requested, but library not found!" "$LINENO" 5
     else
         QHULL_SETTING=internal
+        QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=1
     fi
   fi
 else
   QHULL_SETTING=internal
+  QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=1
 fi
 
 QHULL_SETTING=$QHULL_SETTING
 
+QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=$QHULL_INCLUDE_SUBDIR_IS_LIBQHULL
+
 
 
 OPENCL_SETTING=no
@@ -30290,7 +32335,7 @@ fi
         rm -f testpodofo.*
         echo '#include <podofo.h>' > testpodofo.cpp
         echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
-        ${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB} 2>/dev/null
+        ${CXX} ${CXXFLAGS} ${LDFLAGS} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB} 2>/dev/null
         RETVAL=$?
         if test $RETVAL -eq 0; then
             HAVE_PODOFO=yes
@@ -30330,7 +32375,7 @@ fi
         rm -f testpodofo.*
         echo '#include <podofo.h>' > testpodofo.cpp
         echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
-        ${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>/dev/null
+        ${CXX} ${CXXFLAGS} ${LDFLAGS} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>/dev/null
         RETVAL=$?
         if test $RETVAL -eq 0; then
             HAVE_PODOFO=yes
@@ -30405,7 +32450,7 @@ fi
         if test ! -z "`uname | grep Darwin`" ; then
           TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
         fi
-        if test -z "`${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${PDFIUM_LIB}  2>&1`" ; then
+        if ${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${PDFIUM_LIB} >/dev/null 2>/dev/null; then
             HAVE_PDFIUM=yes
             CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
             if test "$PDF_PLUGIN" = "no"; then
@@ -30454,7 +32499,7 @@ fi
         if test ! -z "`uname | grep Darwin`" ; then
           TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
         fi
-        if test -z "`${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${TEST_PDFIUM_LIB} 2>&1`" ; then
+        if ${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${TEST_PDFIUM_LIB} >/dev/null 2>/dev/null; then
             HAVE_PDFIUM=yes
             CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
             if test "$PDF_PLUGIN" = "no"; then
@@ -30471,6 +32516,10 @@ $as_echo "no" >&6; }
         rm -f testpdfium.*
         rm -f testpdfium
     fi
+
+    if test "$HAVE_PDFIUM" = "no" -a "$with_pdfium" != ""; then
+        as_fn_error $? "pdfium requested but not found" "$LINENO" 5
+    fi
 else
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5
 $as_echo "disabled" >&6; }
@@ -30854,9 +32903,9 @@ if test ! -z "`uname | grep Darwin`" ; then
 
   MACOSX_FRAMEWORK=no
 
-# Check whether --with- was given.
-if test "${with_+set}" = set; then :
-  withval=$with_;
+# Check whether --with-macosx-framework was given.
+if test "${with_macosx_framework+set}" = set; then :
+  withval=$with_macosx_framework;
 fi
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Mac OS X Framework build" >&5
@@ -31095,15 +33144,18 @@ if test "x$with_java" = "xyes"; then
 
     JAVA_6_TEST_DIR=
     JAVA_7_TEST_DIR=
+    JAVA_8_TEST_DIR=
     JAVA_MAC_TEST_DIR=
     case "$host_cpu" in
         i*86*)
             JAVA_6_TEST_DIR=/usr/lib/jvm/java-6-openjdk-i386
             JAVA_7_TEST_DIR=/usr/lib/jvm/java-7-openjdk-i386
+            JAVA_8_TEST_DIR=/usr/lib/jvm/java-8-openjdk-i386
             ;;
         x86_64*)
             JAVA_6_TEST_DIR=/usr/lib/jvm/java-6-openjdk-amd64
             JAVA_7_TEST_DIR=/usr/lib/jvm/java-7-openjdk-amd64
+            JAVA_8_TEST_DIR=/usr/lib/jvm/java-8-openjdk-amd64
             ;;
         *)
             ;;
@@ -31114,7 +33166,10 @@ if test "x$with_java" = "xyes"; then
         ;;
     esac
 
-    if test "x$JAVA_7_TEST_DIR" != "x" -a -d "$JAVA_7_TEST_DIR/include"; then
+    if test "x$JAVA_8_TEST_DIR" != "x" -a -d "$JAVA_8_TEST_DIR/include"; then
+        with_java="$JAVA_8_TEST_DIR"
+
+    elif test "x$JAVA_7_TEST_DIR" != "x" -a -d "$JAVA_7_TEST_DIR/include"; then
         with_java="$JAVA_7_TEST_DIR"
 
     elif test "x$JAVA_6_TEST_DIR" != "x" -a -d "$JAVA_6_TEST_DIR/include"; then
@@ -31234,7 +33289,14 @@ if test "${with_jvm_lib_add_rpath+set}" = set; then :
 fi
 
 
-    if test "x$with_jvm_lib" != "x"; then
+    if test "x$with_jvm_lib" = "xdlopen"; then
+
+cat >>confdefs.h <<_ACEOF
+#define JVM_LIB_DLOPEN 1
+_ACEOF
+
+        JVM_LIB="-ldl"
+    elif test "x$with_jvm_lib" != "x"; then
         if test -d "$with_jvm_lib"; then
             saved_LDFLAGS="$LDFLAGS"
             LDFLAGS="$LDFLAGS -L$with_jvm_lib"
@@ -31747,7 +33809,7 @@ elif test "$with_cryptopp" = "yes" -o "$with_cryptopp" = "" ; then
     # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
     echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
     echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
-    ${CXX} ${CXXFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
+    ${CXX} ${CXXFLAGS} ${LDFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
     RETVAL=$?
     if test $RETVAL -eq 0; then
         HAVE_CRYPTOPP=yes
@@ -31771,7 +33833,7 @@ $as_echo_n "checking if cryptopp has all cipher methods builtin... " >&6; }
         rm -f testcryptopp.*
         echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
         echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
-        ${CXX} ${CXXFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
+        ${CXX} ${CXXFLAGS} ${LDFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
         RETVAL=$?
         if test $RETVAL -eq 0; then
             USE_ONLY_CRYPTODLL_ALG=no
@@ -31793,7 +33855,7 @@ else
     # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
     echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
     echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
-    ${CXX} ${CXXFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
+    ${CXX} ${CXXFLAGS} ${LDFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
     RETVAL=$?
     if test $RETVAL -eq 0; then
         HAVE_CRYPTOPP=yes
@@ -31815,7 +33877,7 @@ $as_echo_n "checking if cryptopp has all cipher methods builtin... " >&6; }
         rm -f testcryptopp.*
         echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
         echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
-        ${CXX} ${CXXFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
+        ${CXX} ${CXXFLAGS} ${LDFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
         RETVAL=$?
         if test $RETVAL -eq 0; then
             USE_ONLY_CRYPTODLL_ALG=no
@@ -31840,9 +33902,9 @@ USE_ONLY_CRYPTODLL_ALG=$USE_ONLY_CRYPTODLL_ALG
 
 
 
-# Check whether --with-grib was given.
-if test "${with_grib+set}" = set; then :
-  withval=$with_grib;
+# Check whether --with-mrf was given.
+if test "${with_mrf+set}" = set; then :
+  withval=$with_mrf;
 fi
 
 
@@ -34295,6 +36357,9 @@ echo "  C compiler:                ${CC} ${CFLAGS}"
 echo "  C++ compiler:              ${CXX} ${CXXFLAGS}"
 
 
+echo "  C++11 support:             ${CXX11_SUPPORT}"
+
+
 echo ""
 
 
@@ -34388,6 +36453,9 @@ echo "  MrSID support:             ${HAVE_MRSID}"
 echo "  MrSID/MG4 Lidar support:   ${HAVE_MRSID_LIDAR}"
 
 
+echo "  JP2Lura support:           ${HAVE_JP2LURA}"
+
+
 echo "  MSG support:               ${HAVE_MSG}"
 
 
@@ -34474,7 +36542,10 @@ echo "  SpatiaLite shared obj name:${SPATIALITE_SONAME}"
 
 fi
 
-echo "  DWGdirect support          ${HAVE_DWGDIRECT}"
+echo "  RasterLite2 support:       ${HAVE_RASTERLITE2}"
+
+
+echo "  Teigha (DWG and DGNv8):    ${HAVE_TEIGHA}"
 
 
 echo "  INFORMIX DataBlade support:${HAVE_IDB}"
@@ -34483,6 +36554,9 @@ echo "  INFORMIX DataBlade support:${HAVE_IDB}"
 echo "  GEOS support:              ${HAVE_GEOS_RESULT}"
 
 
+echo "  SFCGAL support:            ${HAVE_SFCGAL_RESULT}"
+
+
 echo "  QHull support:             ${QHULL_SETTING}"
 
 
@@ -34568,3 +36642,8 @@ if test "$HAVE_LIBXML2" = "yes" -a "$FGDB_ENABLED" = "yes"; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-libxml2 and --with-fgdb are both available. There might be some incompatibility between system libxml2 and the embedded copy within libFileGDBAPI" >&5
 $as_echo "$as_me: WARNING: --with-libxml2 and --with-fgdb are both available. There might be some incompatibility between system libxml2 and the embedded copy within libFileGDBAPI" >&2;}
 fi
+
+if test "$PROJ_STATIC" = "no" -a "$FGDB_ENABLED" = "yes" -a "$FGDB_HAS_PROJ4" = "yes"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --without-static-proj and --with-fgdb are both available. There might be some incompatibility between system libproj and the embedded copy within libFileGDBAPI" >&5
+$as_echo "$as_me: WARNING: --without-static-proj and --with-fgdb are both available. There might be some incompatibility between system libproj and the embedded copy within libFileGDBAPI" >&2;}
+fi
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..7edff14
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,5510 @@
+dnl ***************************************************************************
+dnl $Id: configure.ac 37968 2017-04-12 07:16:55Z rouault $
+dnl
+dnl Project:  GDAL
+dnl Purpose:  Configure source file.
+dnl Author:   Frank Warmerdam, warmerdam at pobox.com
+dnl
+dnl ***************************************************************************
+dnl Copyright (c) 2000, Frank Warmerdam
+dnl
+dnl Permission is hereby granted, free of charge, to any person obtaining a
+dnl copy of this software and associated documentation files (the "Software"),
+dnl to deal in the Software without restriction, including without limitation
+dnl the rights to use, copy, modify, merge, publish, distribute, sublicense,
+dnl and/or sell copies of the Software, and to permit persons to whom the
+dnl Software is furnished to do so, subject to the following conditions:
+dnl
+dnl The above copyright notice and this permission notice shall be included
+dnl in all copies or substantial portions of the Software.
+dnl
+dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+dnl OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+dnl FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+dnl THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+dnl DEALINGS IN THE SOFTWARE.
+dnl ***************************************************************************
+
+dnl Disable configure caching ... it causes lots of hassles.
+define([AC_CACHE_LOAD], )
+define([AC_CACHE_SAVE], )
+
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(GDALmake.opt.in)
+AC_CONFIG_MACRO_DIR(m4)
+AC_CONFIG_HEADERS([port/cpl_config.h:port/cpl_config.h.in])
+AH_BOTTOM([#include "cpl_config_extras.h"])
+
+dnl We require autoconf 2.52+ for libtool support on cygwin/mingw hosts
+AC_PREREQ(2.52)
+
+dnl Compute the canonical host-system (the system we are building for)
+dnl type variable $host
+AC_CANONICAL_HOST
+
+dnl Enable as much warnings as possible
+AX_CFLAGS_WARN_ALL(C_WFLAGS)
+AX_CXXFLAGS_WARN_ALL(CXX_WFLAGS)
+
+dnl For ICC: it needs -we10006 instead of -Werror to turn unknown options to errors
+dnl Some gcc/clang versions might succeed on this test, so also include -Werror in ERROR_ON_UNKNOWN_OPTIONS
+AX_CHECK_COMPILE_FLAG([-Werror -we10006],[ERROR_ON_UNKNOWN_OPTIONS="-Werror -we10006"],[ERROR_ON_UNKNOWN_OPTIONS="-Werror"])
+
+dnl A few ICC warnings to turn off
+dnl warning #188: enumerated type mixed with another type  (needed on libcsf)
+dnl warning #1684: conversion from pointer to same-sized integral type (potential portability problem)  (needed on frmts/mrf)
+dnl warning #2259: non-pointer conversion from "size_t={unsigned long}" to "int" may lose significant bits
+dnl warning #2304: non-explicit constructor with single argument may cause implicit type conversion
+dnl warning #3280: declaration hides member
+dnl remark #11074: Inlining inhibited by limit max-size
+dnl remark #11076: To get full report use -qopt-report=4 -qopt-report-phase ipo
+AX_CHECK_COMPILE_FLAG([-diag-disable 188,1684,2259,2304,3280,11074,11076],[C_WFLAGS="$C_WFLAGS -diag-disable 188,1684,2259,2304,3280,11074,11076" CXX_WFLAGS="$CXX_WFLAGS -diag-disable 188,1684,2259,2304,3280,11074,11076"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+AX_CHECK_COMPILE_FLAG([-Wextra],[C_WFLAGS="$C_WFLAGS -Wextra" CXX_WFLAGS="$CXX_WFLAGS -Wextra"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Winit-self],[C_WFLAGS="$C_WFLAGS -Winit-self" CXX_WFLAGS="$CXX_WFLAGS -Winit-self"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wunused-parameter], [C_WFLAGS="$C_WFLAGS -Wunused-parameter" CXX_WFLAGS="$CXX_WFLAGS -Wunused-parameter" NO_UNUSED_PARAMETER_FLAG="-Wno-unused-parameter"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wmissing-prototypes], [C_WFLAGS="$C_WFLAGS -Wmissing-prototypes"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wmissing-declarations], [C_WFLAGS="$C_WFLAGS -Wmissing-declarations"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wformat], [C_WFLAGS="$C_WFLAGS -Wformat" CXX_WFLAGS="$CXX_WFLAGS -Wformat"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wformat -Werror=format-security -Wno-format-nonliteral], [C_WFLAGS="$C_WFLAGS -Werror=format-security -Wno-format-nonliteral" CXX_WFLAGS="$CXX_WFLAGS -Werror=format-security -Wno-format-nonliteral"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wshorten-64-to-32], [C_WFLAGS="$C_WFLAGS -Wshorten-64-to-32" CXX_WFLAGS="$CXX_WFLAGS -Wshorten-64-to-32"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wlogical-op], [C_WFLAGS="$C_WFLAGS -Wlogical-op" CXX_WFLAGS="$CXX_WFLAGS -Wlogical-op" NO_LOGICAL_OP_FLAG="-Wno-logical-op"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wshadow], [C_WFLAGS="$C_WFLAGS -Wshadow" CXX_WFLAGS="$CXX_WFLAGS -Wshadow"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl Error out on things that will fail with MSVC
+AX_CHECK_COMPILE_FLAG([-Werror=vla], [C_WFLAGS="$C_WFLAGS -Werror=vla" CXX_WFLAGS="$CXX_WFLAGS -Werror=vla"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Werror=declaration-after-statement], [C_WFLAGS="$C_WFLAGS -Wdeclaration-after-statement"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl -Wclobbered is not reliable on most gcc versions
+dnl AX_CHECK_COMPILE_FLAG([-Wno-clobbered], [C_WFLAGS="$C_WFLAGS -Wno-clobbered" CXX_WFLAGS="$CXX_WFLAGS -Wno-clobbered"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl Warn when macros __TIME__, __DATE__ or __TIMESTAMP__ are encountered as they might prevent bit-wise-identical reproducible compilations. 
+AX_CHECK_COMPILE_FLAG([-Wdate-time], [C_WFLAGS="$C_WFLAGS -Wdate-time" CXX_WFLAGS="$CXX_WFLAGS -Wdate-time"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl GCC 6 warnings
+AX_CHECK_COMPILE_FLAG([-Wnull-dereference], [C_WFLAGS="$C_WFLAGS -Wnull-dereference" CXX_WFLAGS="$CXX_WFLAGS -Wnull-dereference"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wduplicated-cond], [C_WFLAGS="$C_WFLAGS -Wduplicated-cond" CXX_WFLAGS="$CXX_WFLAGS -Wduplicated-cond"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+AX_CHECK_COMPILE_FLAG([-Wno-sign-compare], [NO_SIGN_COMPARE="-Wno-sign-compare"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl clang >= 3.9
+AX_CHECK_COMPILE_FLAG([-Wcomma], [C_WFLAGS="$C_WFLAGS -Wcomma" CXX_WFLAGS="$CXX_WFLAGS -Wcomma"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl clang and gcc 5
+AX_CHECK_COMPILE_FLAG([-Wfloat-conversion], [C_WFLAGS="$C_WFLAGS -Wfloat-conversion" CXX_WFLAGS="$CXX_WFLAGS -Wfloat-conversion"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl clang >= 3.2
+AX_CHECK_COMPILE_FLAG([-Wdocumentation -Wno-documentation-deprecated-sync], [C_WFLAGS="$C_WFLAGS -Wdocumentation -Wno-documentation-deprecated-sync" CXX_WFLAGS="$CXX_WFLAGS -Wdocumentation -Wno-documentation-deprecated-sync"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl C++ specific stuff
+
+AC_LANG_PUSH([C++])
+AX_CHECK_COMPILE_FLAG([-Wunused-private-field], [CXX_WFLAGS="$CXX_WFLAGS -Wunused-private-field"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wmissing-prototypes], [CXX_WFLAGS="$CXX_WFLAGS -Wmissing-prototypes"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wmissing-declarations], [CXX_WFLAGS="$CXX_WFLAGS -Wmissing-declarations"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+AX_CHECK_COMPILE_FLAG([-Wnon-virtual-dtor], [CXX_WFLAGS="$CXX_WFLAGS -Wnon-virtual-dtor" NO_NON_VIRTUAL_DTOR_FLAG="-Wno-non-virtual-dtor"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl Clang enables -Woverloaded-virtual if -Wall is defined, but not GCC
+AX_CHECK_COMPILE_FLAG([-Woverloaded-virtual], [CXX_WFLAGS="$CXX_WFLAGS -Woverloaded-virtual"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+dnl Forbid use of 'or', 'and', ... alias operators
+AX_CHECK_COMPILE_FLAG([-fno-operator-names], [CXX_WFLAGS="$CXX_WFLAGS -fno-operator-names"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+
+AC_LANG_POP([C++])
+
+CXX11_SUPPORT=no
+AC_ARG_WITH([cpp11],
+	    AS_HELP_STRING([--without-cpp11],
+	       [Disable C++11 compiler options]),,)
+
+AC_MSG_CHECKING([if use C++11 compiler options])
+if test "$with_cpp11" = "yes" -o "$with_cpp11" = "" ; then
+    dnl Check C++ compiler compatibility with C++11
+    AC_MSG_CHECKING([C++ compiler compatibility with C++11])
+    AX_CXX_COMPILE_STDCXX_11([ext],[optional])
+
+    if [test "$HAVE_CXX11" = "1"]; then
+        CXX11_SUPPORT=yes
+    fi
+    AC_MSG_RESULT([enabled])
+else
+    AC_MSG_RESULT([disabled by user])
+fi
+AC_SUBST(CXX11_SUPPORT,$CXX11_SUPPORT)
+
+if [test "$CXX11_SUPPORT" = "yes"]; then
+    dnl Available in GCC 5.1
+    AC_LANG_PUSH([C++])
+        AX_CHECK_COMPILE_FLAG([-Wsuggest-override], [CXX_WFLAGS="$CXX_WFLAGS -Wsuggest-override"],,[$ERROR_ON_UNKNOWN_OPTIONS])
+    AC_LANG_POP([C++])
+fi
+
+dnl Enable -Wimplicit-fallthrough only if C++11 is enabled since CPL_FALLTHROUGH is only active then
+AC_LANG_PUSH([C++])
+SAVED_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS $ERROR_ON_UNKNOWN_OPTIONS -Wimplicit-fallthrough"
+AC_MSG_CHECKING([if -Wimplicit-fallthrough can be enabled])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+  [[#if !(__cplusplus >= 201103L && ( (defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))) || ((defined(__GNUC__) && __GNUC__ >= 7)) ) )
+    #error "not (C++11 and (clang >= 3.7 or gcc >= 7))"
+    #endif]])],
+  [CXX_WFLAGS="$CXX_WFLAGS -Wimplicit-fallthrough"]
+  [AC_MSG_RESULT([yes])],
+  [AC_MSG_RESULT([no])])
+CXXFLAGS=$SAVED_CXXFLAGS
+AC_LANG_POP([C++])
+
+
+AC_SUBST(CXX_WFLAGS,$CXX_WFLAGS)
+AC_SUBST(C_WFLAGS,$C_WFLAGS)
+AC_SUBST(NO_UNUSED_PARAMETER_FLAG,$NO_UNUSED_PARAMETER_FLAG)
+AC_SUBST(NO_SIGN_COMPARE,$NO_SIGN_COMPARE)
+AC_SUBST(NO_NON_VIRTUAL_DTOR_FLAG,$NO_NON_VIRTUAL_DTOR_FLAG)
+AC_SUBST(NO_LOGICAL_OP_FLAG,$NO_LOGICAL_OP_FLAG)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_CXX
+AC_LIBTOOL_WIN32_DLL
+AC_PROG_LIBTOOL
+
+dnl Check that CXX is really a working compiler
+AC_LANG_PUSH([C++])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
+  [[#ifndef __cplusplus
+    #error "broken C++"
+    #endif]])],,
+  [CXX=;])
+AC_LANG_POP([C++])
+
+if test "x$CXX" = x ; then
+  AC_MSG_ERROR("You don't have a working C++ compiler.")
+fi
+
+dnl switch between libtool and native build system
+AC_ARG_WITH(libtool, [  --without-libtool     Don't use libtool to build the library],,)
+
+if test "$with_libtool" = "no"; then
+AC_PROG_RANLIB
+
+dnl AC_COMPILER_PIC as expanded by autoconf-2.68 doesn't work for the C++ part with clang++ 3.0 that doesn't like compiling .c programs
+dnl so we inline the expanded code and fix it at hand.
+dnl AC_COMPILER_PIC
+	echo 'void f(){}' > conftest.c
+	if test -z "`${CC-cc} $CFLAGS -fPIC -c conftest.c 2>&1`"; then
+	  CFLAGS="$CFLAGS -fPIC"
+	fi
+	echo 'void f(){}' > conftest.cpp
+	if test -z "`${CXX-g++} $CXXFLAGS -fPIC -c conftest.cpp 2>&1`"; then
+	  CXXFLAGS="$CXXFLAGS -fPIC"
+	fi
+	rm -f conftest*
+
+AC_LD_SHARED
+else
+with_libtool=yes
+fi
+AC_SUBST(HAVE_LIBTOOL,$with_libtool)
+
+dnl Checks for libraries.
+AC_CHECK_LIB(dl,dlopen,,,)
+
+dnl Needed on Solaris.
+AC_CHECK_LIB(rt,nanosleep,,,)
+
+dnl We don't need to add math library to all targets
+case "${host_os}" in
+    cygwin* | mingw32* | pw32* | beos* | darwin*)
+        ;;
+    *)
+	AC_CHECK_LIB(m,sin,,,)
+        ;;
+esac
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(assert.h fcntl.h unistd.h dbmalloc.h dlfcn.h stdint.h limits.h locale.h values.h float.h errno.h direct.h)
+
+AC_C_BIGENDIAN
+
+dnl Check for 64 bit file API
+AC_HAVE_LONG_LONG
+AC_UNIX_STDIO_64
+
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(unsigned long)
+AC_CHECK_SIZEOF(void*)
+dnl Some compilers (IBM VisualAge) has these types defined, so check it here.
+dnl These types are used in internal libtiff.
+AC_CHECK_TYPES([int8, int16, int32],,,
+[
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+])
+AC_CHECK_TYPES(uintptr_t)
+
+dnl We need the following lines for libtiff too.
+HAVE_IEEEFP=1
+AC_DEFINE_UNQUOTED(HAVE_IEEEFP, $HAVE_IEEEFP, [Define as 0 or 1 according to the floating point format supported by the machine])
+
+dnl Check the native cpu bit order (also libtiff stuff).
+AC_MSG_CHECKING([native cpu bit order])
+case "$host_cpu" in
+    i*86*|x86_64*)
+        HOST_FILLORDER=FILLORDER_LSB2MSB
+	AC_MSG_RESULT([lsb2msb])
+	;;
+    *)
+	HOST_FILLORDER=FILLORDER_MSB2LSB
+	AC_MSG_RESULT([msb2lsb])
+        ;;
+esac
+AC_DEFINE_UNQUOTED(HOST_FILLORDER, $HOST_FILLORDER, [Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB)])
+
+dnl Checks for library functions.
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS(snprintf vsnprintf)
+AC_CHECK_FUNCS(atoll)
+AC_CHECK_FUNCS(strtof)
+AC_CHECK_FUNCS(getcwd)
+
+dnl Check for declarations
+AC_CHECK_DECLS(strtof)
+
+AC_CHECK_FUNCS(readlink)
+AC_CHECK_FUNCS(lstat)
+AC_CHECK_FUNCS(posix_spawnp)
+AC_CHECK_FUNCS(posix_memalign)
+AC_CHECK_FUNCS(vfork)
+AC_CHECK_FUNCS(mmap)
+AC_CHECK_FUNCS(statvfs)
+AC_CHECK_FUNCS(statvfs64)
+
+dnl Make sure at least these are checked under C++.  Prototypes missing on
+dnl some platforms.
+
+AC_LANG_PUSH(C++)
+AC_CHECK_FUNC_CUSTOM(gmtime_r,[#include <time.h>],[time_t t; struct tm ltime; t = time(0); gmtime_r( &t, &ltime );])
+AC_CHECK_FUNC_CUSTOM(localtime_r,[#include <time.h>],[time_t t; struct tm ltime; t = time(0); localtime_r( &t, &ltime );])
+AC_LANG_POP(C++)
+
+AC_MSG_CHECKING([for uselocale])
+AC_TRY_COMPILE(
+  [
+#define _XOPEN_SOURCE 700
+#include <locale.h>
+  ], [
+    locale_t alocale = newlocale (LC_NUMERIC_MASK, "C", 0);
+    locale_t oldlocale = uselocale(alocale);
+    uselocale(oldlocale);
+    freelocale(alocale);
+    return 0;
+  ],
+  [
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_USELOCALE, 1,
+          [Define to 1 if you have the `uselocale' function.])
+  ], [
+    AC_MSG_RESULT([no])
+])
+
+
+OPT_GDAL_FORMATS=
+EXTRA_INCLUDES=
+
+dnl ---------------------------------------------------------------------------
+dnl Check for --enable-debug
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([to enable debug build])
+
+AC_ARG_ENABLE(debug,
+	      AS_HELP_STRING([--enable-debug],
+			     [enable debugging (disabled by default)]),
+	      [HAVE_DEBUG=$enableval], [HAVE_DEBUG=yes])
+
+CFLAGS_NOFTRAPV="$CFLAGS"
+CXXFLAGS_NOFTRAPV="$CXXFLAGS"
+
+if test "x$enable_debug" = "xyes" ; then
+
+  dnl Try to strip out optimization.
+
+  CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-O2 //"`
+  CFLAGS=`echo "$CFLAGS " | sed "s/-O2 //"`
+  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-O //"`
+  CFLAGS=`echo "$CFLAGS" | sed "s/-O //"`
+
+  dnl remove existing -g to avoid duplicates.
+
+  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-g //"`
+  CFLAGS=`echo "$CFLAGS" | sed "s/-g //"`
+
+  dnl add -g and -DDEBUG
+
+  CXXFLAGS="$CXXFLAGS -g -DDEBUG"
+  CFLAGS="$CFLAGS -g -DDEBUG"
+
+  CFLAGS_NOFTRAPV="$CFLAGS"
+  CXXFLAGS_NOFTRAPV="$CXXFLAGS"
+
+  AC_MSG_RESULT([yes, modified CFLAGS="$CFLAGS"])
+
+  # Some clang version on 32 bits have linking error with 64bit operations (undefined reference to `__mulodi4')
+  AC_MSG_CHECKING([whether -ftrapv can be used])
+  rm -f testftrapv.c
+  echo 'int main(int argc, char** argv) { return (long long)argc * argc; } ' > testftrapv.c
+  if test -z "`${CC} ${CFLAGS} -ftrapv testftrapv.c -o testftrapv 2>&1`" ; then
+    AC_MSG_RESULT([yes])
+    CFLAGS="$CFLAGS -ftrapv"
+    CXXFLAGS="$CXXFLAGS -ftrapv"
+  else
+    AC_MSG_RESULT([no])
+  fi
+  rm -f testftrapv.* testftrapv
+
+else
+  AC_MSG_RESULT([no, CFLAGS="$CFLAGS"])
+fi
+
+AC_SUBST(CFLAGS_NOFTRAPV,$CFLAGS_NOFTRAPV)
+AC_SUBST(CXXFLAGS_NOFTRAPV,$CXXFLAGS_NOFTRAPV)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if GCC 4.1 atomic builtins are really available
+dnl (some GCC versions are broken w.r.t this on some exotic architectures...)
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([whether GCC 4.1 atomic builtins are available])
+
+rm -f atomicbuiltins.c
+echo 'int main(int argc, char** argv) { int i; __sync_add_and_fetch(&i, 1); __sync_sub_and_fetch(&i, 1); __sync_bool_compare_and_swap(&i, 0, 1); return 0; } ' > atomicbuiltins.c
+if test -z "`${CC} ${CFLAGS} atomicbuiltins.c -o atomicbuiltins 2>&1`" ; then
+    HAVE_GCC_ATOMIC_BUILTINS=yes
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_GCC_ATOMIC_BUILTINS,1, [Define to 1 if GCC atomic builtins are available])
+else
+    HAVE_GCC_ATOMIC_BUILTINS=no
+    AC_MSG_RESULT([no])
+fi
+rm -rf atomicbuiltins.* atomicbuiltins
+
+AC_SUBST(HAVE_GCC_ATOMIC_BUILTINS,$HAVE_GCC_ATOMIC_BUILTINS)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if GCC bswap builtins are available
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([whether GCC bswap builtins are available])
+
+rm -f bswapbuiltins.c
+echo '#include <x86intrin.h>' > bswapbuiltins.c
+echo 'int main(int argc, char** argv) { (void)__builtin_bswap32(0); (void)__builtin_bswap64(0); return 0; } ' >> bswapbuiltins.c
+if test -z "`${CC} ${CFLAGS} bswapbuiltins.c -o bswapbuiltins 2>&1`" ; then
+    HAVE_GCC_BSWAP=yes
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_GCC_BSWAP,1, [Define to 1 if GCC bswap builtins are available])
+else
+    HAVE_GCC_BSWAP=no
+    AC_MSG_RESULT([no])
+fi
+rm -rf bswapbuiltins.* bswapbuiltins
+
+AC_SUBST(HAVE_GCC_BSWAP,$HAVE_GCC_BSWAP)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if __uint128_t is available and usable
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([for __uint128_t])
+AC_TRY_COMPILE(
+  [
+  ], [
+      unsigned long long v1 = 1024ULL;
+      unsigned long long v2 = 0x8000000000000000ULL;
+      __uint128_t u = ((__uint128_t)v1)*((__uint128_t)v2);
+      return u == 0;
+  ],
+  [
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_UINT128_T, 1,
+          [Define to 1 if the system has the type __uint128_t])
+  ], [
+    AC_MSG_RESULT([no])
+])
+
+dnl ---------------------------------------------------------------------------
+dnl Check SSE availability
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(sse,
+[  --with-sse[=ARG]        Detect SSE availability for some optimized routines (ARG=yes(default), no)],,)
+
+AC_MSG_CHECKING([whether SSE is available at compile time])
+
+if test "$with_sse" = "yes" -o "$with_sse" = ""; then
+
+    rm -f detectsse.cpp
+    echo '#ifdef __SSE__' > detectsse.cpp
+    echo '#include <xmmintrin.h>' >> detectsse.cpp
+    echo 'void foo() { float fEpsilon = 0.0000000000001f; __m128 xmm_small = _mm_load1_ps(&fEpsilon); }  int main() { return 0; }' >> detectsse.cpp
+    echo '#else' >> detectsse.cpp
+    echo 'some_error' >> detectsse.cpp
+    echo '#endif' >> detectsse.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o detectsse detectsse.cpp 2>&1`" ; then
+        AC_MSG_RESULT([yes])
+        SSEFLAGS=""
+        HAVE_SSE_AT_COMPILE_TIME=yes
+    else
+        if test -z "`${CXX} ${CXXFLAGS} -msse -o detectsse detectsse.cpp 2>&1`" ; then
+            AC_MSG_RESULT([yes])
+            SSEFLAGS="-msse"
+            HAVE_SSE_AT_COMPILE_TIME=yes
+        else
+            AC_MSG_RESULT([no])
+            if test "$with_sse" = "yes"; then
+                AC_MSG_ERROR([--with-sse was requested, but SSE is not available])
+            fi
+        fi
+    fi
+
+    dnl On Solaris, the presence of SSE instructions is flagged in the binary
+    dnl and prevent it to run on non SSE hardware even if the instructions are
+    dnl not executed. So if the user did not explicitly requires SSE, test that
+    dnl we can run SSE binaries
+    if test "$HAVE_SSE_AT_COMPILE_TIME" = "yes"; then
+       case $host_os in
+         solaris*)
+           AC_MSG_CHECKING([whether SSE is available and needed at runtime])
+           if ./detectsse; then
+             AC_MSG_RESULT([yes])
+           else
+             AC_MSG_RESULT([no])
+             if test "$with_sse" = "yes"; then
+               echo "Caution: the generated binaries will not run on this system."
+             else
+               echo "Disabling SSE as it is not explicitly required"
+               HAVE_SSE_AT_COMPILE_TIME=""
+               SSEFLAGS=""
+             fi
+           fi
+           ;;
+       esac
+    fi
+
+    if test "$HAVE_SSE_AT_COMPILE_TIME" = "yes"; then
+        CFLAGS="-DHAVE_SSE_AT_COMPILE_TIME $CFLAGS"
+        CXXFLAGS="-DHAVE_SSE_AT_COMPILE_TIME $CXXFLAGS"
+    fi
+
+    rm -rf detectsse*
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(SSEFLAGS,$SSEFLAGS)
+
+dnl ---------------------------------------------------------------------------
+dnl Check SSSE3 availability
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(ssse3,
+[  --with-ssse3[=ARG]        Detect SSSE3 availability for some optimized routines (ARG=yes(default), no)],,)
+
+AC_MSG_CHECKING([whether SSSE3 is available at compile time])
+
+if test "$with_ssse3" = "yes" -o "$with_ssse3" = ""; then
+
+    rm -f detectssse3.cpp
+    echo '#ifdef __SSSE3__' > detectssse3.cpp
+    echo '#include <tmmintrin.h>' >> detectssse3.cpp
+    echo 'void foo() { __m128i xmm_i = _mm_set1_epi16(0); xmm_i = _mm_shuffle_epi8(xmm_i, xmm_i); }  int main() { return 0; }' >> detectssse3.cpp
+    echo '#else' >> detectssse3.cpp
+    echo 'some_error' >> detectssse3.cpp
+    echo '#endif' >> detectssse3.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o detectssse3 detectssse3.cpp 2>&1`" ; then
+        AC_MSG_RESULT([yes])
+        SSSE3FLAGS=""
+        HAVE_SSSE3_AT_COMPILE_TIME=yes
+    else
+        if test -z "`${CXX} ${CXXFLAGS} -mssse3 -o detectssse3 detectssse3.cpp 2>&1`" ; then
+            AC_MSG_RESULT([yes])
+            SSSE3FLAGS="-mssse3"
+            HAVE_SSSE3_AT_COMPILE_TIME=yes
+        else
+            AC_MSG_RESULT([no])
+            if test "$with_ssse3" = "yes"; then
+                AC_MSG_ERROR([--with-ssse3 was requested, but SSSE3 is not available])
+            fi
+        fi
+    fi
+
+    dnl On Solaris, the presence of SSSE3 instructions is flagged in the binary
+    dnl and prevent it to run on non SSSE3 hardware even if the instructions are
+    dnl not executed. So if the user did not explicitly requires SSSE3, test that
+    dnl we can run SSSE3 binaries
+    if test "$HAVE_SSSE3_AT_COMPILE_TIME" = "yes"; then
+       case $host_os in
+         solaris*)
+           AC_MSG_CHECKING([whether SSSE3 is available and needed at runtime])
+           if ./detectssse3; then
+             AC_MSG_RESULT([yes])
+           else
+             AC_MSG_RESULT([no])
+             if test "$with_ssse3" = "yes"; then
+               echo "Caution: the generated binaries will not run on this system."
+             else
+               echo "Disabling SSSE3 as it is not explicitly required"
+               HAVE_SSSE3_AT_COMPILE_TIME=""
+               SSSE3FLAGS=""
+             fi
+           fi
+           ;;
+       esac
+    fi
+
+    if test "$HAVE_SSSE3_AT_COMPILE_TIME" = "yes"; then
+        CFLAGS="-DHAVE_SSSE3_AT_COMPILE_TIME $CFLAGS"
+        CXXFLAGS="-DHAVE_SSSE3_AT_COMPILE_TIME $CXXFLAGS"
+    fi
+
+    rm -rf detectssse3*
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(SSSE3FLAGS,$SSSE3FLAGS)
+
+dnl ---------------------------------------------------------------------------
+dnl Check AVX availability
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(avx,
+[  --with-avx[=ARG]        Detect AVX availability for some optimized routines (ARG=yes(default), no)],,)
+
+AC_MSG_CHECKING([whether AVX is available at compile time])
+
+if test "$with_avx" = "yes" -o "$with_avx" = ""; then
+
+    rm -f detectavx.cpp
+    echo '#ifdef __AVX__' > detectavx.cpp
+    echo '#include <immintrin.h>' >> detectavx.cpp
+    echo 'int foo() { unsigned int nXCRLow, nXCRHigh;' >> detectavx.cpp
+    echo '__asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0));' >> detectavx.cpp
+    echo 'float fEpsilon = 0.0000000000001f;' >> detectavx.cpp
+    echo '__m256 ymm_small = _mm256_set_ps(fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon);' >> detectavx.cpp
+    echo 'return (int)nXCRLow + _mm256_movemask_ps(ymm_small); }' >> detectavx.cpp
+    echo 'int main(int argc, char**) { if( argc == 0 ) return foo(); return 0; }' >> detectavx.cpp
+    echo '#else' >> detectavx.cpp
+    echo 'some_error' >> detectavx.cpp
+    echo '#endif' >> detectavx.cpp
+    if test -z "`${CXX} ${CXXFLAGS} -o detectavx detectavx.cpp 2>&1`" ; then
+        AC_MSG_RESULT([yes])
+        AVXFLAGS=""
+        HAVE_AVX_AT_COMPILE_TIME=yes
+    else
+        if test -z "`${CXX} ${CXXFLAGS} -mavx -o detectavx detectavx.cpp 2>&1`" ; then
+            AC_MSG_RESULT([yes])
+            AVXFLAGS="-mavx"
+            HAVE_AVX_AT_COMPILE_TIME=yes
+        else
+            AC_MSG_RESULT([no])
+            if test "$with_avx" = "yes"; then
+                AC_MSG_ERROR([--with-avx was requested, but AVX is not available])
+            fi
+        fi
+    fi
+
+    dnl On Solaris, the presence of AVX instructions is flagged in the binary
+    dnl and prevent it to run on non AVX hardware even if the instructions are
+    dnl not executed. So if the user did not explicitly requires AVX, test that
+    dnl we can run AVX binaries
+    if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
+       case $host_os in
+         solaris*)
+           AC_MSG_CHECKING([whether AVX is available and needed at runtime])
+           if ./detectavx; then
+             AC_MSG_RESULT([yes])
+           else
+             AC_MSG_RESULT([no])
+             if test "$with_avx" = "yes"; then
+               echo "Caution: the generated binaries will not run on this system."
+             else
+               echo "Disabling AVX as it is not explicitly required"
+               AVXFLAGS=""
+               HAVE_AVX_AT_COMPILE_TIME=""
+             fi
+           fi
+           ;;
+       esac
+    fi
+
+    if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
+        CFLAGS="-DHAVE_AVX_AT_COMPILE_TIME $CFLAGS"
+        CXXFLAGS="-DHAVE_AVX_AT_COMPILE_TIME $CXXFLAGS"
+    fi
+
+    rm -rf detectavx*
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(AVXFLAGS,$AVXFLAGS)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for --enable-lto
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([to enable LTO (link time optimization) build])
+
+AC_ARG_ENABLE(lto,
+              AS_HELP_STRING([--enable-lto],
+                             [enable LTO(link time optimization) (disabled by default)]))
+
+CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
+CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT="$CXXFLAGS"
+
+if test "x$enable_lto" = "xyes" ; then
+
+  dnl remove existing -g.
+
+  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-g //"`
+  CFLAGS=`echo "$CFLAGS" | sed "s/-g //"`
+
+  dnl add -flto
+
+  CXXFLAGS="$CXXFLAGS -flto"
+  CFLAGS="$CFLAGS -flto"
+  LDFLAGS="$LDFLAGS -flto"
+
+  dnl in case we have avx available by default, then we can compile everything
+  dnl with -flto
+  if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
+    if test "$AVXFLAGS" = ""; then
+        CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
+    fi
+  fi
+  if test "$HAVE_SSSE3_AT_COMPILE_TIME" = "yes"; then
+    if test "$SSSE3FLAGS" = ""; then
+        CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT="$CXXFLAGS"
+    fi
+  fi
+
+  AC_MSG_RESULT([yes])
+else
+  AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT,$CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT)
+AC_SUBST(CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT,$CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if we need -lws2_32 (mingw)
+dnl ---------------------------------------------------------------------------
+
+echo "#include <winsock2.h>" > test_ws2_32.c
+echo "#include <ws2tcpip.h>" >> test_ws2_32.c
+echo "void foo() {}" >> test_ws2_32.c
+
+if test -z "`${CC} -c test_ws2_32.c 2>&1`" ; then
+  LIBS="$LIBS -lws2_32"
+fi
+rm -f test_ws2_32*
+
+dnl ---------------------------------------------------------------------------
+dnl Check if we need -lpsapi (mingw)
+dnl ---------------------------------------------------------------------------
+
+echo "#include <windows.h>" > test_psapi.c
+echo "#include <psapi.h>" >> test_psapi.c
+echo "void foo() {}" >> test_psapi.c
+
+if test -z "`${CC} -c test_psapi.c 2>&1`" ; then
+  LIBS="$LIBS -lpsapi"
+fi
+rm -f test_psapi*
+
+
+dnl ---------------------------------------------------------------------------
+dnl Check if we have getaddrinfo
+dnl ---------------------------------------------------------------------------
+
+echo "#include <sys/types.h>" > test_getaddrinfo.c
+echo "#include <sys/socket.h>" >> test_getaddrinfo.c
+echo "#include <netdb.h>" >> test_getaddrinfo.c
+echo "void test() { getaddrinfo(0,0,0,0); }"  >> test_getaddrinfo.c
+
+HAVE_GETADDRINFO=NO
+if test -z "`${CC} -c test_getaddrinfo.c 2>&1`" ; then
+  AC_DEFINE_UNQUOTED(HAVE_GETADDRINFO,1, [Define to 1 if you have the `getaddrinfo' function.])
+fi
+rm -f test_getaddrinfo*
+
+dnl ---------------------------------------------------------------------------
+dnl Check if user requests hiding internal symbols
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(hide_internal_symbols,[  --with-hide-internal-symbols[=ARG] Try to hide internal symbols (ARG=yes/no)],,)
+
+HAVE_HIDE_INTERNAL_SYMBOLS=no
+
+if test "$with_hide_internal_symbols" = "yes"; then
+
+    AC_MSG_CHECKING([whether we should hide internal symbols])
+
+    rm -f hiddensymbols.c
+    echo 'int visible() { return 0; } __attribute__ ((visibility("default")))' >> hiddensymbols.c
+    echo 'int hidden() { return 0; }' >> hiddensymbols.c
+    if test -z "`${CC} -fvisibility=hidden -c hiddensymbols.c 2>&1`" ; then
+      HAVE_HIDE_INTERNAL_SYMBOLS=yes
+    else
+      HAVE_HIDE_INTERNAL_SYMBOLS=no
+    fi
+    if test "$HAVE_HIDE_INTERNAL_SYMBOLS" = "yes"; then
+        AC_MSG_RESULT([yes])
+        CFLAGS="$CFLAGS -fvisibility=hidden"
+        CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
+    else
+        AC_MSG_RESULT([no])
+    fi
+    rm -f hiddensymbols.*
+else
+  AC_MSG_CHECKING([whether we should hide internal symbols])
+  AC_MSG_RESULT([no])
+fi
+
+if test "$HAVE_HIDE_INTERNAL_SYMBOLS" = "yes" ; then
+  AC_DEFINE_UNQUOTED(USE_GCC_VISIBILITY_FLAG,1, [Define to 1 if you want to use the -fvisibility GCC flag])
+fi
+
+AC_SUBST(HAVE_HIDE_INTERNAL_SYMBOLS,$HAVE_HIDE_INTERNAL_SYMBOLS)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if user requests renaming internal libtiff symbols
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(rename_internal_libtiff_symbols,[  --with-rename-internal-libtiff-symbols[=ARG] Prefix internal libtiff symbols with gdal_ (ARG=yes/no)],,)
+if test "$with_rename_internal_libtiff_symbols" = ""; then
+    with_rename_internal_libtiff_symbols=no
+fi
+AC_SUBST(RENAME_INTERNAL_LIBTIFF_SYMBOLS,$with_rename_internal_libtiff_symbols)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if user requests renaming internal libgeotiff symbols
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(rename_internal_libgeotiff_symbols,[  --with-rename-internal-libgeotiff-symbols[=ARG] Prefix internal libgeotiff symbols with gdal_ (ARG=yes/no)],,)
+if test "$with_rename_internal_libgeotiff_symbols" = ""; then
+    with_rename_internal_libgeotiff_symbols=no
+fi
+AC_SUBST(RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS,$with_rename_internal_libgeotiff_symbols)
+
+
+dnl ---------------------------------------------------------------------------
+dnl Check if user requests /usr/local to be included.
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([for local include/lib path])
+
+AC_ARG_WITH(local,[  --with-local[=dir]      Include /usr/local or other local tree for INCLUDE/LIBS],,)
+
+if test "$with_local" != "no" -a "$with_local" != "" ; then
+
+  if test "$with_local" = "yes" ; then
+    ADD_PREFIX=/usr/local
+  else
+    ADD_PREFIX=$with_local
+  fi
+
+  AC_MSG_RESULT(adding $ADD_PREFIX)
+
+  LIBS="$LIBS -L$ADD_PREFIX/lib"
+  CPPFLAGS="$CPPFLAGS -I$ADD_PREFIX/include"
+else
+  AC_MSG_RESULT([none])
+fi
+
+dnl ---------------------------------------------------------------------
+dnl ENABLE THREADS ONLY IF REQUESTED.
+dnl ---------------------------------------------------------------------
+
+THREAD_LIB=""
+THREAD_FLAG=""
+PTHREAD_ENABLED="no"
+
+AC_ARG_WITH(threads,
+[  --with-threads[=ARG]    Include thread safe support (ARG=yes(default), no or linkopt)],,)
+
+if test "$with_threads" = "yes" -o "$with_threads" = "" ; then
+
+  AC_CHECK_LIB(pthread,pthread_create,THREAD_FLAG=CPL_MULTIPROC_PTHREAD,,,)
+
+  if test -n "$THREAD_FLAG" ; then
+      THREAD_LIB="-lpthread"
+  else
+    # For Android, pthread_create is in Bionic libc
+    unset ac_cv_lib_pthread_pthread_create
+    AC_CHECK_LIB(c,pthread_create,THREAD_FLAG=CPL_MULTIPROC_PTHREAD,,,)
+  fi
+
+  AC_MSG_CHECKING([for PTHREAD_MUTEX_RECURSIVE])
+
+  AC_TRY_COMPILE(
+  [
+#define _GNU_SOURCE
+#include <pthread.h>
+  ], [
+    return (PTHREAD_MUTEX_RECURSIVE);
+  ],
+  [
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_PTHREAD_MUTEX_RECURSIVE, 1,
+          [Define to 1 if you have the `PTHREAD_MUTEX_RECURSIVE' constant.])
+  ], [
+    AC_MSG_RESULT([no])
+  ])
+
+
+
+  AC_MSG_CHECKING([for PTHREAD_MUTEX_ADAPTIVE_NP])
+
+  AC_TRY_COMPILE(
+  [
+#define _GNU_SOURCE
+#include <pthread.h>
+  ], [
+    return PTHREAD_MUTEX_ADAPTIVE_NP;
+  ],
+  [
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP, 1,
+          [Define to 1 if you have the `PTHREAD_MUTEX_ADAPTIVE_NP' constant.])
+  ], [
+    AC_MSG_RESULT([no])
+  ])
+
+  AC_MSG_CHECKING([for pthread_spinlock_t])
+
+  AC_TRY_COMPILE(
+  [
+#define _GNU_SOURCE
+#include <pthread.h>
+  ], [
+    pthread_spinlock_t spin;
+    return 1;
+  ],
+  [
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(HAVE_PTHREAD_SPINLOCK, 1,
+          [Define to 1 if you have the `pthread_spinlock_t' type.])
+  ], [
+    AC_MSG_RESULT([no])
+  ])
+
+elif test "$with_threads" != "no" ; then
+
+  THREAD_FLAG=CPL_MULTIPROC_PTHREAD
+  THREAD_LIB="$with_threads"
+
+  AC_CHECKING(whether we should include thread/mutex support...)
+  AC_MSG_RESULT([        using threads with link options "$THREAD_LIB".])
+
+else
+  AC_CHECKING(whether we should include thread/mutex support...)
+  AC_MSG_RESULT([        thread safe support disabled.])
+fi
+
+if test "$THREAD_FLAG" = "CPL_MULTIPROC_PTHREAD" ; then
+  AC_DEFINE_UNQUOTED(CPL_MULTIPROC_PTHREAD,1, [Define if you want to use pthreads based multiprocessing support])
+  PTHREAD_ENABLED="yes"
+fi
+
+LIBS="$THREAD_LIB $LIBS"
+
+dnl ---------------------------------------------------------------------------
+dnl Check if mremap() with 5 args is available
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([for 5 args mremap()])
+
+AC_TRY_COMPILE(
+[
+#define _GNU_SOURCE
+#include <sys/mman.h>
+], [
+return (mremap(0,0,0,0,0));
+],
+[
+AC_MSG_RESULT([yes])
+AC_DEFINE_UNQUOTED(HAVE_5ARGS_MREMAP, 1,
+        [Define to 1 if you have the 5 args `mremap' function.])
+], [
+AC_MSG_RESULT([no])
+])
+
+dnl ---------------------------------------------------------------------------
+dnl Check if _SC_PHYS_PAGES is available
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([for _SC_PHYS_PAGES])
+
+AC_TRY_COMPILE(
+[
+#include <unistd.h>
+], [
+return (sysconf(_SC_PHYS_PAGES));
+],
+[
+AC_MSG_RESULT([yes])
+AC_DEFINE_UNQUOTED(HAVE_SC_PHYS_PAGES, 1,
+        [Define to 1 if you have the _SC_PHYS_PAGES' constant.])
+], [
+AC_MSG_RESULT([no])
+])
+
+dnl ---------------------------------------------------------------------------
+dnl Check if libz is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(libz,[  --with-libz[=ARG]       Include libz support (ARG=internal or libz directory)],,)
+
+if test "$with_libz" = "external" -o "$with_libz" = "" -o "$with_libz" = "yes" ; then
+
+  AC_CHECK_LIB(z,deflateInit_,LIBZ_SETTING=external,LIBZ_SETTING=internal,)
+
+  if test "$LIBZ_SETTING" = "external" ; then
+    AC_CHECK_LIB(z,inflateCopy,LIBZ_SETTING=external,LIBZ_SETTING=internal,)
+    if test "$LIBZ_SETTING" = "external" ; then
+        AC_MSG_RESULT([using pre-installed libz])
+    else
+        AC_MSG_RESULT([using internal libz code as inflateCopy is missing])
+    fi
+  else
+    AC_MSG_RESULT([using internal libz code as deflateInit_ is missing])
+  fi
+
+elif test "$with_libz" != "no" -a "$with_libz" != "internal" ; then
+
+  LIBS="-L$with_libz -L$with_libz/lib $LIBS"
+
+  AC_CHECK_LIB(z,deflateInit_,LIBZ_SETTING=external,LIBZ_SETTING=internal,-L$with_libz -L$with_libz/lib -lz)
+  if test "$LIBZ_SETTING" = "external" ; then
+    AC_CHECK_LIB(z,inflateCopy,LIBZ_SETTING=external,LIBZ_SETTING=internal,-L$with_libz -L$with_libz/lib -lz)
+     if test "$LIBZ_SETTING" = "external" ; then
+        AC_MSG_RESULT([using libz library from $with_libz])
+    else
+        AC_MSG_RESULT([using internal libz code as inflateCopy from $with_libz is missing])
+    fi
+  else
+    AC_MSG_RESULT([using internal libz code as deflateInit_ from $with_libz is missing])
+  fi
+
+fi
+
+if test "$LIBZ_SETTING" = "external" ; then
+  LIBS="-lz $LIBS"
+  if test "$with_libz" != "" -a "$with_libz" != "yes" -a "$with_libz" != "external" ; then
+    EXTRA_INCLUDES="-I$with_libz -I$with_libz/include $EXTRA_INCLUDES"
+  fi
+elif test "$with_libz" = "no" ; then
+  LIBZ_SETTING=no
+  AC_MSG_RESULT([not using libz at all.])
+else
+  LIBZ_SETTING=internal
+  OPT_GDAL_FORMATS="zlib $OPT_GDAL_FORMATS"
+  AC_MSG_RESULT([using internal libz code.])
+fi
+
+AC_SUBST(LIBZ_SETTING,$LIBZ_SETTING)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for iconv/libiconv.
+dnl A rationale for this macro is described in "GNU `gettext' utilities"
+dnl manual at
+dnl http://www.gnu.org/software/gettext/manual/html_node/AM_005fICONV.html
+dnl ---------------------------------------------------------------------------
+AM_ICONV
+
+dnl Extra test needed for GCC 4.5 on Solaris 11, where there is
+dnl a different behaviour if the tests are compiled with gcc or g++.
+dnl So we introduce a ICONV_CPP_CONST that must be used instead of
+dnl ICONV_CONST when used from .cpp files.
+if test "$am_func_iconv" = "yes"; then
+    rm -f testiconv.*
+    echo '#include <iconv.h>' > testiconv.cpp
+    echo 'int main(int argc, char** argv) { iconv_t cd = 0; return iconv (cd, (const char **) 0, 0, 0, 0); } ' >> testiconv.cpp
+    if test -z "`${CXX} ${CPPFLAGS} testiconv.cpp -c 2>&1`" ; then
+        AC_MSG_RESULT([using ICONV_CPP_CONST="const"])
+        ICONV_CPP_CONST="const"
+    else
+        AC_MSG_RESULT([using ICONV_CPP_CONST=""])
+        ICONV_CPP_CONST=""
+    fi
+    rm -f testiconv.*
+
+    AC_DEFINE_UNQUOTED(ICONV_CPP_CONST,$ICONV_CPP_CONST, [For.cpp files, define as const if the declaration of iconv() needs const.])
+fi
+
+
+dnl ---------------------------------------------------------------------------
+dnl Check if liblzma is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(liblzma,[  --with-liblzma[=ARG]       Include liblzma support (ARG=yes/no)],,)
+
+if test "$with_liblzma" = "yes" ; then
+  AC_CHECK_LIB(lzma,lzma_code,LIBLZMA_SETTING=yes,LIBLZMA_SETTING=no,)
+
+  if test "$LIBLZMA_SETTING" = "yes" ; then
+    LIBS="-llzma $LIBS"
+  fi
+else
+    LIBLZMA_SETTING=no
+fi
+
+AC_SUBST(LIBLZMA_SETTING,$LIBLZMA_SETTING)
+
+dnl ---------------------------------------------------------------------------
+dnl Select an PostgreSQL Library to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+PG_CONFIG=no
+
+AC_ARG_WITH(pg,
+	    AS_HELP_STRING([--with-pg[=ARG]],
+	       [Include PostgreSQL GDAL/OGR Support (ARG=path to pg_config)]),,)
+
+if test "x$with_pg" = "xyes" -o "x$with_pg" = "x" ; then
+  AC_PATH_PROG(PG_CONFIG, pg_config, no)
+else
+  PG_CONFIG=$with_pg
+fi
+
+AC_MSG_CHECKING([for PostgreSQL])
+
+if test "x$PG_CONFIG" = "xno" ; then
+
+  HAVE_PG=no
+  PG_LIB=
+  PG_INC=
+
+  AC_MSG_RESULT([no])
+
+else
+  if test -d ${PG_CONFIG} ; then
+      AC_MSG_RESULT([no])
+      AC_MSG_ERROR([--with-pg argument is a directory.  It should be the path to the pg_config script, often somewhere like /usr/local/pgsql/bin/pg_config.])
+  fi
+
+  if test \! -x ${PG_CONFIG} ; then
+      AC_MSG_RESULT([no])
+      AC_MSG_ERROR([--with-pg argument is a not an executable file.  It should be the path to the pg_config script, often somewhere like /usr/local/pgsql/bin/pg_config.])
+  fi
+
+  AC_MSG_RESULT([yes])
+
+  AC_CHECK_LIB(pq,PQconnectdb,HAVE_PG=yes,HAVE_PG=no,-L`$PG_CONFIG --libdir`)
+
+  if test "${HAVE_PG}" = "yes" ; then
+    LIBS=-L`$PG_CONFIG --libdir`" -lpq $LIBS"
+    PG_INC=-I`$PG_CONFIG --includedir`" -I"`$PG_CONFIG --includedir-server`
+  fi
+
+fi
+
+AC_SUBST(HAVE_PG,$HAVE_PG)
+AC_SUBST(PG_INC,$PG_INC)
+AC_SUBST(PG_LIB,$PG_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if we should build with GRASS support.
+dnl ---------------------------------------------------------------------------
+
+GRASS_SETTING=no
+GRASS_INCLUDE=
+HAVE_GRASS=no
+export GRASS_INCLUDE GRASS_SETTING
+
+AC_ARG_WITH(grass,[  --with-grass[=ARG]      Include GRASS support (GRASS 5.7+, ARG=GRASS install tree dir)],,)
+
+AC_ARG_WITH(libgrass,[  --with-libgrass[=ARG]   Include GRASS support based on libgrass (GRASS 5.0+)],,)
+
+# default use of grass libraries off since we can't easily auto-find them.
+if test "$with_grass" = "" ; then
+  with_grass=no
+fi
+
+# Check for GRASS 5.7.0 or later library use.
+# TODO: separate libs for rasters and vectors
+if test "$with_grass" != "yes" -a "$with_grass" != "no" ; then
+
+  AC_CHECK_LIB(grass_gis,G_is_initialized,GRASS_SETTING=grass70+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
+  if test "$GRASS_SETTING" = "no" ; then
+    AC_CHECK_LIB(grass_gis,G_asprintf,GRASS_SETTING=grass57+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
+  fi
+
+  if test "$GRASS_SETTING" != "no" ; then
+    if test "$GRASS_SETTING" = "grass70+" ; then
+      G_RASTLIBS="-lgrass_raster -lgrass_imagery"
+      G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
+      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
+    else
+      G_RASTLIBS="-lgrass_I"
+      G_VECTLIBS="-lgrass_vect -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
+      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_vask -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
+    fi
+    GRASS_INCLUDE="-I$with_grass/include"
+    GRASS_GISBASE="$with_grass"
+    HAVE_GRASS=yes
+  else
+    AC_MSG_ERROR([--with-grass=$with_grass requested, but libraries not found!])
+  fi
+
+# Check if libgrass is disabled.
+elif test "$with_libgrass" = "no" ; then
+
+  echo "GRASS support disabled."
+
+elif test "$with_libgrass" = "yes" -o "$with_libgrass" = "" ; then
+
+  AC_CHECK_LIB(grass5,G_gisinit_2,GRASS_SETTING=libgrass,GRASS_SETTING=no,)
+
+  if test "$GRASS_SETTING" = "libgrass" ; then
+    LIBS="-lgrass5 $LIBS"
+  fi
+
+else
+
+  AC_CHECK_LIB(grass5,G_gisinit_2,GRASS_SETTING=libgrass,GRASS_SETTING=no,-L$with_libgrass/lib)
+
+  if test "$GRASS_SETTING" = "libgrass" ; then
+    LIBS="-L$with_libgrass -L$with_libgrass/lib -lgrass5 $LIBS"
+    GRASS_INCLUDE="-I$with_libgrass -I$with_libgrass/include $EXTRA_INCLUDES"
+  else
+    AC_MSG_ERROR([--with-libgrass=$with_grass requested, but libgrass5 not found!])
+  fi
+fi
+
+AC_SUBST(GRASS_SETTING,$GRASS_SETTING)
+AC_SUBST(GRASS_INCLUDE,$GRASS_INCLUDE)
+AC_SUBST(GRASS_GISBASE,$GRASS_GISBASE)
+AC_SUBST(HAVE_GRASS)
+
+if test "$GRASS_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="grass $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if cfitsio library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(cfitsio,[  --with-cfitsio[=ARG]    Include FITS support (ARG=no or libcfitsio path)],,)
+
+if test "$with_cfitsio" = "no" ; then
+
+  FITS_SETTING=no
+
+  echo "FITS support disabled."
+
+elif test "$with_cfitsio" = "yes" -o "$with_cfitsio" = "" ; then
+
+  AC_CHECK_LIB(cfitsio,ffopen,FITS_SETTING=external,FITS_SETTING=no,)
+
+  if test "$FITS_SETTING" = "external" ; then
+    LIBS="-lcfitsio $LIBS"
+    echo "using pre-installed libcfitsio."
+  else
+    echo "libcfitsio not found - FITS support disabled"
+  fi
+
+dnl Fedora has cfitsio headers in /usr/include/cfitsio
+  if test "$FITS_SETTING" = "external" -a -d /usr/include/cfitsio ; then
+    EXTRA_INCLUDES="-I/usr/include/cfitsio $EXTRA_INCLUDES"
+  fi
+
+else
+
+  FITS_SETTING=external
+  LIBS="-L$with_cfitsio -L$with_cfitsio/lib -lcfitsio $LIBS"
+  EXTRA_INCLUDES="-I$with_cfitsio -I$with_cfitsio/include $EXTRA_INCLUDES"
+
+  echo "using libcfitsio from $with_cfitsio."
+fi
+
+AC_SUBST(FITS_SETTING,$FITS_SETTING)
+
+if test "$FITS_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="fits $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if PCRaster (libcsf) library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(pcraster,[  --with-pcraster[=ARG]   Include PCRaster (libcsf) support (ARG=internal, no or path)],,)
+
+if test "$with_pcraster" = "no" ; then
+
+  PCRASTER_SETTING=no
+
+  echo "PCRaster support disabled."
+
+elif test "$with_pcraster" = "yes" -o "$with_pcraster" = "" ; then
+
+  AC_CHECK_LIB(csf,Mopen,PCRASTER_SETTING=external,PCRASTER_SETTING=internal,$LIBS)
+  AC_CHECK_HEADERS(csf.h)
+
+  if test "$PCRASTER_SETTING" = "external" -a "$ac_cv_header_csf_h" = "no" ; then
+    PCRASTER_SETTING=internal
+  fi
+
+  if test "$PCRASTER_SETTING" = "external" ; then
+    LIBS="-lcsf $LIBS"
+    echo "using pre-installed libcsf."
+  else
+    echo "using internal csf code."
+  fi
+
+elif test "$with_pcraster" = "internal" ; then
+
+  PCRASTER_SETTING=internal
+
+  echo "using internal csf code."
+
+else
+
+  PCRASTER_SETTING=external
+  LIBS="-L$with_pcraster/lib -lcsf $LIBS"
+  EXTRA_INCLUDES="-I$with_pcraster/include $EXTRA_INCLUDES"
+
+  echo "using libcsf from $with_pcraster."
+
+fi
+
+AC_SUBST(PCRASTER_SETTING,$PCRASTER_SETTING)
+
+if test "$PCRASTER_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="pcraster $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Select a PNG Library to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([png], [  --with-png[=ARG]        Include PNG support (ARG=internal, no or path)],,)
+
+AC_MSG_CHECKING([for libpng])
+
+if test "$with_png" = "no" ; then
+
+  PNG_SETTING=no
+
+  echo "png support disabled."
+
+elif test "$with_png" = "yes" -o "$with_png" = "" ; then
+
+  AC_CHECK_LIB([png], [png_set_IHDR], [PNG_SETTING=external], [PNG_SETTING=internal], [$LIBS])
+  AC_CHECK_HEADERS([png.h])
+
+  if test "$PNG_SETTING" = "external" -a "$ac_cv_header_png_h" = "no" ; then
+    PNG_SETTING=internal
+  fi
+  if test "$PNG_SETTING" = "external" ; then
+    LIBS="-lpng $LIBS"
+    echo "using pre-installed libpng."
+  else
+    echo "using internal png code."
+  fi
+
+elif test "$with_png" = "internal" ; then
+
+  PNG_SETTING=internal
+
+  echo "using internal png code."
+
+else
+
+  PNG_SETTING=external
+  LIBS="-L$with_png -L$with_png/lib -lpng $LIBS"
+  EXTRA_INCLUDES="-I$with_png -I$with_png/include $EXTRA_INCLUDES"
+
+  echo "using libpng from $with_png."
+
+fi
+
+AC_SUBST([PNG_SETTING], [$PNG_SETTING])
+
+if test "$PNG_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="png $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Enable DDS driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([dds], [  --with-dds[=ARG]        Include DDS support (ARG=no, or path)],,)
+
+AC_MSG_CHECKING([for libcrunch])
+
+if test "$with_dds" = "no" -o "$with_dds" = ""; then
+
+  DDS_SETTING="no"
+  CRUNCHDIR=""
+
+  echo "dds support disabled."
+
+else
+
+  DDS_SETTING=yes
+  CRUNCHDIR="$with_dds"
+  LIBS="-L$with_dds/lib/ -lcrunch $LIBS"
+  echo "using libcrunch from $with_dds."
+
+fi
+
+AC_SUBST(CRUNCHDIR,$CRUNCHDIR)
+AC_SUBST([DDS_SETTING], [$DDS_SETTING])
+
+if test "$DDS_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="dds $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if GTA library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([gta],[  --with-gta[=ARG]        Include GTA support (ARG=no or libgta tree prefix)],,)
+
+if test "$with_gta" = "no" ; then
+
+  GTA_SETTING=no
+
+  echo "GTA support disabled."
+
+elif test "$with_gta" = "yes" -o "$with_gta" = "" ; then
+
+  AC_CHECK_LIB([gta], [gta_version], [GTA_SETTING=yes], [GTA_SETTING=no],)
+
+  if test "$GTA_SETTING" = "yes" ; then
+    LIBS="-lgta $LIBS"
+    echo "using pre-installed libgta."
+  else
+    echo "libgta not found - GTA support disabled"
+  fi
+
+else
+
+  GTA_SETTING=yes
+  LIBS="-L$with_gta -L$with_gta/lib -lgta $LIBS"
+  EXTRA_INCLUDES="-I$with_gta -I$with_gta/include $EXTRA_INCLUDES"
+
+  echo "using libgta from $with_gta."
+fi
+
+AC_SUBST([GTA_SETTING], [$GTA_SETTING])
+
+if test "$GTA_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="gta $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Select PCIDSK options.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([pcidsk], [  --with-pcidsk[=ARG]     Path to external PCIDSK SDK or internal (default)],,)
+
+AC_MSG_CHECKING([for PCIDSK])
+
+PCIDSK_LIB=
+PCIDSK_INCLUDE=
+
+if test "$with_pcidsk" = "no" ; then
+
+  PCIDSK_SETTING=no
+
+  echo "pcidsk support disabled."
+
+elif test "$with_pcidsk" = "" -o "$with_pcidsk" = "yes" -o "$with_pcidsk" = "internal" ; then
+
+  PCIDSK_SETTING=internal
+
+  echo "using internal libpcidsk."
+
+else
+
+  PCIDSK_SETTING=external
+  PCIDSK_LIB="-L$with_pcidsk/lib -lpcidsk"
+  PCIDSK_INCLUDE="-I$with_pcidsk/include -I$with_pcidsk/include/pcidsk"
+
+  echo "using libpcidsk from $with_pcidsk."
+
+fi
+
+if test "$with_pcidsk" != "no" ; then
+
+  AC_SUBST([PCIDSK_SETTING], [$PCIDSK_SETTING])
+  AC_SUBST([PCIDSK_LIB], [$PCIDSK_LIB])
+  AC_SUBST([PCIDSK_INCLUDE], [$PCIDSK_INCLUDE])
+
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Select a libtiff library to use.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(libtiff,[  --with-libtiff=ARG    Libtiff library to use (ARG=internal, yes or path)],,)
+
+AC_MSG_CHECKING([for libtiff])
+
+if test "x${with_libtiff}" = "xyes" -o "x${with_libtiff}" = "x" ; then
+
+  dnl Only automatically pick up the external libtiff if it is >= 4.0.
+  AC_CHECK_LIB(tiff,TIFFScanlineSize64,TIFF_SETTING=external HAVE_BIGTIFF=yes,TIFF_SETTING=internal HAVE_BIGTIFF=yes,)
+
+  if test "$TIFF_SETTING" = "external" ; then
+    dnl Cygwin takes a somewhat restrictive view of what should be exported
+    dnl from the dll, so don't use the external library if missing semi-private
+    dnl functions.
+    AC_CHECK_LIB(tiff,_TIFFsetDoubleArray,TIFF_SETTING=external,TIFF_SETTING=internal,)
+  fi
+
+  if test "$TIFF_SETTING" = "external" ; then
+    LIBS="-ltiff $LIBS"
+    AC_MSG_RESULT([using pre-installed libtiff.])
+  else
+    AC_MSG_RESULT([using internal TIFF code.])
+  fi
+
+elif test "x${with_libtiff}" = "xinternal" ; then
+
+  TIFF_SETTING=internal
+  HAVE_BIGTIFF=yes
+
+  AC_MSG_RESULT([using internal TIFF code.])
+
+else
+
+  TIFF_SETTING=external
+  if test -r "$with_libtiff/tiff.h" ; then
+    LIBS="-L$with_libtiff -ltiff $LIBS"
+    EXTRA_INCLUDES="-I$with_libtiff $EXTRA_INCLUDES"
+  else
+    LIBS="-L$with_libtiff/lib -ltiff $LIBS"
+    EXTRA_INCLUDES="-I$with_libtiff/include $EXTRA_INCLUDES"
+  fi
+
+  AC_MSG_RESULT([using libtiff from ${with_libtiff}.])
+
+  dnl Check for the BigTIFF enabled library (libtiff >= 4.0)
+  AC_CHECK_LIB(tiff,TIFFScanlineSize64,HAVE_BIGTIFF=yes,HAVE_BIGTIFF=no,)
+
+fi
+
+if test "${HAVE_BIGTIFF}" = "yes" ; then
+  TIFF_OPTS="-DBIGTIFF_SUPPORT"
+
+  LOC_MSG([BigTIFF support enabled.])
+fi
+
+AC_SUBST(TIFF_SETTING,${TIFF_SETTING})
+AC_SUBST(TIFF_OPTS,${TIFF_OPTS})
+
+dnl ---------------------------------------------------------------------------
+dnl Select a libgeotiff library to use.
+dnl ---------------------------------------------------------------------------
+
+GEOTIFF_INCLUDE=
+AC_ARG_WITH(geotiff,[  --with-geotiff=ARG    Libgeotiff library to use (ARG=internal, yes or path)],,)
+
+if test "$with_geotiff" = "yes" -o "$with_geotiff" = "" ; then
+
+  if test "$TIFF_SETTING" = "internal" ; then
+    GEOTIFF_SETTING=internal
+  else
+    dnl We now require libgeotiff 1.2.1 (for XTIFFClientOpen).
+    AC_CHECK_LIB(geotiff,XTIFFClientOpen,GEOTIFF_SETTING=external,GEOTIFF_SETTING=internal)
+
+  fi
+
+  if test "$GEOTIFF_SETTING" = "external" ; then
+
+    dnl Now search for headers
+    if test -r /usr/include/geotiff.h ; then
+      GEOTIFF_INCLUDE=
+    dnl Debian (at least some versions of it) install in /usr/include/geotiff
+    elif test -r /usr/include/geotiff/geotiff.h ; then
+      GEOTIFF_INCLUDE="-I/usr/include/geotiff"
+    dnl Fedora and OpenSuse in /usr/include/libgeotiff (#4706)
+    elif test -r /usr/include/libgeotiff/geotiff.h ; then
+      GEOTIFF_INCLUDE="-I/usr/include/libgeotiff"
+    else
+      AC_CHECK_HEADERS([geotiff.h])
+      if test "$ac_cv_header_geotiff_h" = "no" ; then
+        AC_MSG_ERROR([cannot find geotiff.h])
+      fi
+    fi
+
+    LIBS="-lgeotiff $LIBS"
+    echo "using pre-installed libgeotiff."
+
+  else
+
+    echo "using internal GeoTIFF code."
+
+  fi
+
+elif test "$with_geotiff" = "internal" ; then
+
+  GEOTIFF_SETTING=internal
+
+  echo "using internal GeoTIFF code."
+
+else
+
+  GEOTIFF_SETTING=external
+
+  dnl We now require libgeotiff 1.2.1 (for XTIFFClientOpen).
+  dnl first check if $with_geotiff/lib has the library:
+  AC_CHECK_LIB(geotiff,XTIFFClientOpen,GEOTIFF_SETTING=external,GEOTIFF_SETTING=not_found,-L$with_geotiff/lib)
+
+  if test $GEOTIFF_SETTING = "external" ; then
+    LIBS="-L$with_geotiff/lib -lgeotiff $LIBS"
+    if test  -d $with_geotiff/include ; then
+      EXTRA_INCLUDES="-I$with_geotiff/include $EXTRA_INCLUDES"
+    fi
+  else
+    dnl check if $with_geotiff itself contains the header and library (e.g. as an uninstalled build directory would)
+    AC_CHECK_LIB(geotiff,XTIFFClientOpen,GEOTIFF_SETTING=external,AC_MSG_ERROR([We require at least GeoTIFF 1.2.1. Consider using the one supplied with GDAL]),-L$with_geotiff)
+    if test $GEOTIFF_SETTING = "external" ; then
+      LIBS="-L$with_geotiff -lgeotiff $LIBS"
+      EXTRA_INCLUDES="-I$with_geotiff $EXTRA_INCLUDES"
+    fi
+  fi
+
+  echo "using libgeotiff from $with_geotiff."
+fi
+
+AC_SUBST(GEOTIFF_SETTING,$GEOTIFF_SETTING)
+AC_SUBST(GEOTIFF_INCLUDE,$GEOTIFF_INCLUDE)
+
+dnl ---------------------------------------------------------------------------
+dnl Select a JPEG Library to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(jpeg,[  --with-jpeg[=ARG]       Include JPEG support (ARG=internal, no or path)],,)
+
+if test "$with_jpeg" = "no" ; then
+
+  JPEG_SETTING=no
+
+  echo "jpeg support disabled."
+
+elif test "$with_jpeg" = "yes" -o "$with_jpeg" = "" ; then
+
+  AC_CHECK_LIB(jpeg,jpeg_read_scanlines,JPEG_SETTING=external,JPEG_SETTING=internal,)
+  AC_CHECK_HEADERS(jpeglib.h)
+
+  if test "$JPEG_SETTING" = "external" -a "$ac_cv_header_jpeglib_h" = "no" ; then
+    JPEG_SETTING=internal
+  fi
+
+  if test "$JPEG_SETTING" = "external" -a "$TIFF_SETTING" = "internal" ; then
+    AC_MSG_CHECKING([for width_in_blocks in jpeglib.h])
+
+    rm -f conftest.c
+    echo '#include <stdio.h>' >> conftest.c
+    echo '#include "jpeglib.h"' >> conftest.c
+    echo 'int main() { jpeg_component_info *comptr=0; int i; i = comptr->width_in_blocks; }' >> conftest.c
+    if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
+      AC_MSG_RESULT([yes])
+    else
+      AC_MSG_RESULT([no])
+      JPEG_SETTING=internal
+    fi
+    rm -f conftest*
+  fi
+
+  if test "$JPEG_SETTING" = "external" ; then
+    LIBS="-ljpeg $LIBS"
+    echo "using pre-installed libjpeg."
+  else
+    echo "using internal jpeg code."
+  fi
+
+elif test "$with_jpeg" = "internal" ; then
+
+  JPEG_SETTING=internal
+
+  echo "using internal jpeg code."
+
+else
+
+  JPEG_SETTING=external
+  LIBS="-L$with_jpeg -L$with_jpeg/lib -ljpeg $LIBS"
+  EXTRA_INCLUDES="-I$with_jpeg -I$with_jpeg/include $EXTRA_INCLUDES"
+
+  echo "using libjpeg from $with_jpeg."
+
+fi
+
+AC_SUBST(JPEG_SETTING,$JPEG_SETTING)
+
+if test "$JPEG_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="jpeg $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check for BSB in the local tree.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([jpeg12],
+	    AS_HELP_STRING([--without-jpeg12],
+	       [Disable JPEG 8/12bit TIFF support]),,)
+
+TIFF_JPEG12_ENABLED=no
+AC_MSG_CHECKING([for jpeg12])
+if test "$with_jpeg12" = yes ; then
+    AC_MSG_RESULT([enabled])
+    JPEG12_ENABLED=yes
+
+    echo '#include <stdlib.h>' > check_jpeg_abi.c
+    echo '#include <stdio.h>' >> check_jpeg_abi.c
+    echo '#include "jpeglib.h"' >> check_jpeg_abi.c
+    echo '#if JPEG_LIB_VERSION == 62' >> check_jpeg_abi.c
+    echo 'int main() { return 0; }' >> check_jpeg_abi.c
+    echo '#else' >> check_jpeg_abi.c
+    echo '#error "ABI difference"' >> check_jpeg_abi.c
+    echo '#endif' >> check_jpeg_abi.c
+    if test -z "`${CC} ${CFLAGS} ${EXTRA_INCLUDES} check_jpeg_abi.c -c -o check_jpeg_abi.o 2>&1`" ; then
+      TIFF_JPEG12_ENABLED=yes
+    else
+      TIFF_JPEG12_ENABLED=no
+      AC_MSG_WARN([Internal libjpeg12 has not the same ABI as libjpeg 8 bit. Disabling JPEG-in-TIFF 12 bit])
+    fi
+    rm -f check_jpeg_abi.*
+
+elif test x"$with_jpeg12" = x ; then
+    if test "$JPEG_SETTING" = "internal" -a "$TIFF_SETTING" = "internal" ; then
+      AC_MSG_RESULT([enabled])
+      JPEG12_ENABLED=yes
+      TIFF_JPEG12_ENABLED=yes
+    else
+      JPEG12_ENABLED=no
+      AC_MSG_RESULT([disabled, libjpeg or libtiff not internal])
+    fi
+else
+    JPEG12_ENABLED=no
+    AC_MSG_RESULT([disabled by user])
+fi
+
+AC_SUBST(JPEG12_ENABLED,$JPEG12_ENABLED)
+AC_SUBST(TIFF_JPEG12_ENABLED,$TIFF_JPEG12_ENABLED)
+
+dnl ---------------------------------------------------------------------------
+dnl Select a GIF Library to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(gif,[  --with-gif[=ARG]        Include GIF support (ARG=internal, no or path)],,)
+
+if test "$with_gif" = "no" ; then
+
+  GIF_SETTING=no
+
+  echo "gif support disabled."
+
+elif test "$with_gif" = "yes" -o "$with_gif" = "" ; then
+
+  AC_CHECK_LIB(gif,DGifOpenFileName,GIF_SETTING=external,GIF_SETTING=internal,)
+  AC_CHECK_HEADERS(gif_lib.h)
+
+  if test "$GIF_SETTING" = "external" ; then
+    LIBS="-lgif $LIBS"
+    echo "using pre-installed libgif."
+  else
+    echo "using internal gif code."
+  fi
+
+elif test "$with_gif" = "internal" ; then
+
+  GIF_SETTING=internal
+
+  echo "using internal gif code."
+
+else
+
+  GIF_SETTING=external
+  LIBS="-L$with_gif -L$with_gif/lib -lgif $LIBS"
+  EXTRA_INCLUDES="-I$with_gif -I$with_gif/include $EXTRA_INCLUDES"
+
+  echo "using libgif from $with_gif."
+
+fi
+
+AC_SUBST(GIF_SETTING,$GIF_SETTING)
+
+if test "$GIF_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="gif $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Select an OGDI Library to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+OGDI_INCLUDE=
+export OGDI_INCLUDE
+
+AC_ARG_WITH(ogdi,[  --with-ogdi[=ARG]       Include OGDI support (ARG=path)],,)
+
+if test "$with_ogdi" = "no" ; then
+
+  HAVE_OGDI=no
+
+  echo "ogdi support disabled."
+
+elif test "$with_ogdi" = "yes" -o "$with_ogdi" = "" ; then
+
+  AC_CHECK_HEADERS(ecs.h)
+
+  if test "$ac_cv_header_ecs_h" = "no" ; then
+    if test -f "/usr/include/ogdi/ecs.h"; then
+        OGDI_INCLUDE="-I/usr/include/ogdi"
+    elif test -f "/usr/local/include/ogdi/ecs.h"; then
+        OGDI_INCLUDE="-I/usr/local/include/ogdi"
+    elif test -f "/usr/include/ecs.h"; then
+        OGDI_INCLUDE="-I/usr/include"
+    elif test -f "/usr/local/include/ecs.h"; then
+        OGDI_INCLUDE="-I/usr/local/include"
+    fi
+  fi
+
+  if test "$OGDI_INCLUDE" != "" -o "$ac_cv_header_ecs_h" = "yes"; then
+    AC_CHECK_LIB(ogdi,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,)
+    if test "$HAVE_OGDI" = "yes" ; then
+      LIBS="-logdi $LIBS"
+    else
+      dnl For backward compatibility. Retry with ogdi31 as a name
+      AC_CHECK_LIB(ogdi31,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,)
+      if test "$HAVE_OGDI" = "yes" ; then
+        LIBS="-logdi31 $LIBS"
+      fi
+    fi
+  else
+    HAVE_OGDI=no
+  fi
+
+else
+
+  AC_CHECK_LIB(ogdi,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,-L$with_ogdi -L$with_ogdi/lib -logdi)
+  if test "$HAVE_OGDI" = "yes" ; then
+    if test -f "$with_ogdi/ecs.h" -o -f "$with_ogdi/include/ecs.h"; then
+        LIBS="-L$with_ogdi -L$with_ogdi/lib -logdi $LIBS"
+        OGDI_INCLUDE="-I$with_ogdi -I$with_ogdi/include"
+
+        echo "using libogdi from $with_ogdi."
+     else
+        HAVE_OGDI=no
+        AC_MSG_ERROR([ecs.h not found.])
+     fi
+  else
+    dnl For backward compatibility. Retry with ogdi31 as a name
+    AC_CHECK_LIB(ogdi31,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,-L$with_ogdi -L$with_ogdi/lib -logdi31)
+    if test "$HAVE_OGDI" = "yes" ; then
+      if test -f "$with_ogdi/ecs.h" -o -f "$with_ogdi/include/ecs.h"; then
+        LIBS="-L$with_ogdi -L$with_ogdi/lib -logdi31 $LIBS"
+        OGDI_INCLUDE="-I$with_ogdi -I$with_ogdi/include"
+
+        echo "using libogdi31 from $with_ogdi."
+      else
+        HAVE_OGDI=no
+        AC_MSG_ERROR([ecs.h not found.])
+      fi
+    else
+      AC_MSG_ERROR([libogdi not found.])
+    fi
+  fi
+
+fi
+
+AC_SUBST(HAVE_OGDI,$HAVE_OGDI)
+AC_SUBST(OGDI_INCLUDE,$OGDI_INCLUDE)
+
+if test "$HAVE_OGDI" != "no" ; then
+  OPT_GDAL_FORMATS="ogdi $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Select FME_HOME or disable FME support.
+dnl ---------------------------------------------------------------------------
+
+X_FME_HOME=
+export X_FME_HOME
+
+AC_ARG_WITH(fme,[  --with-fme[=ARG]        Include FMEObjects support (ARG=FME_HOME path)],,)
+
+AC_MSG_CHECKING([for FMEObjects])
+
+if test "$with_fme" = "no" ; then
+
+  AC_MSG_RESULT([disabled by user])
+
+elif test "$with_fme" = "yes" ; then
+
+  if test "$FME_HOME" = "" ; then
+    AC_MSG_ERROR([no, FME_HOME not defined!])
+  elif test -f $FME_HOME/fmeobjects/cpp/isession.h ; then
+    AC_MSG_RESULT([yes])
+    X_FME_HOME=$FME_HOME
+  else
+    AC_MSG_ERROR([FME_HOME defined, but $FME_HOME/fmeobjects/cpp/issesion.h not found.])
+  fi
+
+elif test "$with_fme" = "" ; then
+
+  if test "$FME_HOME" = "" ; then
+    AC_MSG_RESULT([no])
+  elif test -f $FME_HOME/fmeobjects/cpp/isession.h ; then
+    AC_MSG_RESULT([yes])
+    X_FME_HOME=$FME_HOME
+  else
+    AC_MSG_RESULT([no, FME_HOME defined, but $FME_HOME/fmeobjects/cpp/issesion.h not found.])
+  fi
+
+else
+
+  if test -f $with_fme/fmeobjects/cpp/isession.h ; then
+    AC_MSG_RESULT([yes])
+    X_FME_HOME=$with_fme
+  else
+    AC_MSG_ERROR([$with_fme/fmeobjects/cpp/issesion.h not found!])
+  fi
+
+fi
+
+AC_SUBST(X_FME_HOME,$X_FME_HOME)
+
+dnl ---------------------------------------------------------------------------
+dnl Select a SOSI lib to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(sosi,[  --with-sosi[=ARG]        Include SOSI support (ARG=SOSI lib Path, yes or no)],,)
+
+if test -z "$with_sosi" -o "$with_sosi" = "no" ; then
+
+  SOSI_ENABLED=no
+
+  echo "SOSI support disabled."
+
+elif test "$with_sosi" = "yes" ; then
+
+    AC_MSG_CHECKING([for libfyba])
+
+    rm -f testfyba.*
+    rm -f testfyba
+    echo "#include <fyba.h>" > testfyba.cpp
+    echo "int main() { LC_Init(); return 0; }" >> testfyba.cpp
+    if test  -r /usr/include/fyba -a -z "`${CXX} ${CPPFLAGS} -I/usr/include/fyba -DLINUX testfyba.cpp -lfyba -lfygm -lfyut -o testfyba 2>&1`" ; then
+        AC_MSG_RESULT([found])
+        SOSI_ENABLED=yes
+        SOSI_LIB="-lfyba -lfygm -lfyut"
+        SOSI_INC="-I/usr/include/fyba"
+    else
+        AC_MSG_RESULT([not found])
+        AC_MSG_CHECKING([for libfyba.a, libfygm.a and libfyut.a in /usr/local/lib])
+        if test -r /usr/local/lib/libfyba.a -a -r /usr/local/lib/libfygm.a -a -r /usr/local/lib/libfyut.a ; then
+            AC_MSG_RESULT([found])
+            SOSI_ENABLED=yes
+            SOSI_LIB="/usr/local/lib/libfyba.a /usr/local/lib/libfygm.a /usr/local/lib/libfyut.a"
+        else
+            AC_MSG_ERROR([not found.])
+        fi
+
+        AC_MSG_CHECKING([for fyba.h, fygm.h and fyut.h in /usr/local/include/fyba])
+        if test -r /usr/local/include/fyba/fyba.h -a -r /usr/local/include/fyba/fygm.h -a -r /usr/local/include/fyba/fyut.h ; then
+            AC_MSG_RESULT([found])
+            SOSI_ENABLED=yes
+            SOSI_INC="-I/usr/local/include/fyba"
+        else
+            AC_MSG_ERROR([not found.])
+        fi
+    fi
+
+    rm -f testfyba.*
+    rm -f testfyba
+else
+
+  AC_MSG_CHECKING([for libfyba.a, libfygm.a and libfyut.a in $with_sosi/lib])
+  if test -r $with_sosi/lib/libfyba.a -a -r $with_sosi/lib/libfygm.a -a -r $with_sosi/lib/libfyut.a ; then
+    AC_MSG_RESULT([found.])
+    SOSI_LIB="$with_sosi/lib/libfyba.a $with_sosi/lib/libfygm.a $with_sosi/lib/libfyut.a"
+    SOSI_ENABLED=yes
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+  AC_MSG_CHECKING([for fyba.h in $with_sosi/include/fyba])
+  if test -r $with_sosi/include/fyba/fyba.h -a -r $with_sosi/include/fyba/fygm.h -a -r $with_sosi/include/fyba/fyut.h ; then
+    AC_MSG_RESULT([found.])
+    SOSI_INC="-I$with_sosi/include/fyba"
+    SOSI_ENABLED=yes
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+fi
+
+AC_SUBST(SOSI_ENABLED, $SOSI_ENABLED)
+AC_SUBST(SOSI_LIB, $SOSI_LIB)
+AC_SUBST(SOSI_INC, $SOSI_INC)
+
+dnl ---------------------------------------------------------------------------
+dnl MongoCXX driver
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(mongocxx,[  --with-mongocxx[=ARG]        Include MongoCXX support (ARG=Path, yes or no)],,)
+
+MONGODB_ENABLED=no
+
+if test "$with_mongocxx" = "no" ; then
+
+  echo "MONGODB support disabled."
+
+elif test "$with_mongocxx" = "yes" -o "$with_mongocxx" = "" ; then
+
+    AC_MSG_CHECKING([for MongoCXX])
+
+    rm -f testmongocxx.*
+    rm -f testmongocxx
+    echo "#include <mongo/client/dbclient.h>" > testmongocxx.cpp
+    echo "using namespace mongo;" >> testmongocxx.cpp
+    echo "int main() { client::initialize(client::Options()); return 0; }" >> testmongocxx.cpp
+    if test -z "`${CXX} ${CPPFLAGS} testmongocxx.cpp -lmongoclient -lboost_system -lboost_thread -lboost_regex -o testmongocxx 2>&1`" ; then
+        AC_MSG_RESULT([MongoCXX found])
+        MONGODB_ENABLED="yes"
+        MONGODB_LIB=" -lmongoclient -lboost_system -lboost_thread -lboost_regex"
+    else
+        if test "$with_mongocxx" = "yes"; then
+            AC_MSG_ERROR([MongoCXX not found.])
+        else
+            AC_MSG_RESULT([MongoCXX not found.])
+        fi
+    fi
+    rm -f testmongocxx.*
+    rm -f testmongocxx
+
+else
+
+  AC_ARG_WITH(boost-lib-path,
+          [  --with-boost-lib-path=ARG   Path to boost libraries for mongocxx client],,,)
+
+  AC_MSG_CHECKING([for libmongoclient.so in in $with_mongocxx/lib])
+  MONGODB_ENABLED=yes
+  if test -r $with_mongocxx/lib/libmongoclient.so; then
+    AC_MSG_RESULT([found.])
+    MONGODB_LIB="-L$with_mongocxx/lib -lmongoclient"
+  elif test -r $with_mongocxx/lib/libmongoclient.dylib; then
+    AC_MSG_RESULT([found.])
+    MONGODB_LIB="-L$with_mongocxx/lib -lmongoclient"
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+  if test "$with_boost_lib_path" = "" ; then
+    MONGODB_LIB="$MONGODB_LIB -lboost_system -lboost_thread -lboost_regex"
+  else
+    MONGODB_LIB="$MONGODB_LIB -L$with_boost_lib_path -lboost_system -lboost_thread -lboost_regex"
+  fi
+
+  AC_MSG_CHECKING([for mongo/client/dbclient.h in $with_mongocxx/include])
+  if test -r $with_mongocxx/include/mongo/client/dbclient.h ; then
+    AC_MSG_RESULT([found.])
+    MONGODB_INC="-I$with_mongocxx/include"
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+fi
+
+AC_SUBST(MONGODB_ENABLED, $MONGODB_ENABLED)
+AC_SUBST(MONGODB_LIB, $MONGODB_LIB)
+AC_SUBST(MONGODB_INC, $MONGODB_INC)
+
+dnl ---------------------------------------------------------------------------
+dnl Select an HDF4 Library to use, or disable driver.
+dnl
+dnl We assume the user will have libjpeg and libz from other sources when
+dnl linking against static HDF4 libraries.
+dnl ---------------------------------------------------------------------------
+
+HDF4_INCLUDE=""
+
+AC_ARG_WITH(hdf4,[  --with-hdf4[=ARG]       Include HDF4 support (ARG=path)],,)
+
+if test x"$with_hdf4" = x"no" ; then
+
+  HAVE_HDF4=no
+
+  echo "hdf4 support disabled."
+
+else
+
+  if test x"$with_hdf4" = x"yes" -o x"$with_hdf4" = x"" ; then
+dnl Fedora has hdf static libraries in /usr/lib/hdf
+    if test -d /usr/lib64/hdf; then
+      HDF_LIB_DIR="/usr/lib64/hdf"
+    elif test -d /usr/lib/hdf; then
+      HDF_LIB_DIR="/usr/lib/hdf"
+    else
+      HDF_LIB_DIR=""
+    fi
+  else
+    if test -d $with_hdf4/lib ; then
+      HDF_LIB_DIR="$with_hdf4/lib"
+    else
+      HDF_LIB_DIR="$with_hdf4"
+    fi
+  fi
+
+  ORIG_LIBS="$LIBS"
+  if test "$HDF_LIB_DIR" != "" ; then
+    LIBS="-L$HDF_LIB_DIR $LIBS"
+  fi
+
+dnl Debian supplies the HDF4 library which does not conflict with NetCDF.
+dnl Test for Debian flavor first. Hint: install the libhdf4-alt-dev package.
+  AC_CHECK_LIB(mfhdfalt,SDreaddata,HDF_LIB_NAME="-lmfhdfalt -ldfalt",HDF_LIB_NAME=missing,-ldfalt)
+
+dnl If it fails, test again for normal libmfhdf/libdf
+  if test "$HDF_LIB_NAME" = "missing" ; then
+    unset ac_cv_lib_mfhdf_SDreaddata
+    AC_CHECK_LIB(mfhdf,SDreaddata,HDF_LIB_NAME="-lmfhdf -ldf",HDF_LIB_NAME=missing,-ldf)
+    if test "$HDF_LIB_NAME" = "missing" ; then
+      unset ac_cv_lib_mfhdf_SDreaddata
+      AC_CHECK_LIB(hdf4,SDreaddata,HDF_LIB_NAME=-lhdf4,HDF_LIB_NAME=missing,)
+    fi
+  fi
+
+dnl Test again, with -ldf, -ljpeg and -lz this time.
+  if test "$HDF_LIB_NAME" = "missing" ; then
+    unset ac_cv_lib_mfhdf_SDreaddata
+    AC_CHECK_LIB(mfhdf,SDreaddata,HDF_LIB_NAME="-lmfhdf -ldf",HDF_LIB_NAME=missing,-ldf -ljpeg -lz)
+  fi
+
+dnl Not found... again, with -lsz.
+  if test "$HDF_LIB_NAME" = "missing" ; then
+    unset ac_cv_lib_mfhdf_SDreaddata
+    AC_CHECK_LIB(mfhdf,SDreaddata,HDF_LIB_NAME="-lmfhdf -ldf -lsz",HDF_LIB_NAME=missing,-ldf -lsz -ljpeg -lz)
+  fi
+
+  if test "$HDF_LIB_NAME" != "missing" ; then
+
+    if test "$HDF_LIB_DIR" != "" ; then
+      LIBS="-L$HDF_LIB_DIR $HDF_LIB_NAME $ORIG_LIBS"
+    else
+      LIBS="$HDF_LIB_NAME $ORIG_LIBS"
+    fi
+
+    dnl HDF4 library newer than 4.2.5 has a SDreset_maxopenfiles/SDget_maxopenfiles interface
+    dnl which allows opening many HDF files simultaneously (the max number of files was previously
+    dnl hardcoded and too low, smth. like 32). Search for it and use if available.
+    AC_CHECK_LIB(mfhdfalt,SDget_maxopenfiles,HDF4_HAS_MAXOPENFILES=yes,HDF4_HAS_MAXOPENFILES=no,$HDF_LIB_NAME)
+    if test "$HDF4_HAS_MAXOPENFILES" = "no" ; then
+      AC_CHECK_LIB(mfhdf,SDget_maxopenfiles,HDF4_HAS_MAXOPENFILES=yes,HDF4_HAS_MAXOPENFILES=no,$HDF_LIB_NAME)
+    fi
+
+  dnl Now search for headers
+    if test "$with_hdf4" = "yes" -o "$with_hdf4" = "" -a -r /usr/include/hdf/hdf.h ; then
+      HDF4_INCLUDE="-I/usr/include/hdf"
+    elif test -r "$with_hdf4/hdf/hdf.h" ; then
+      HDF4_INCLUDE="-I$with_hdf4/hdf"
+    elif test -r "$with_hdf4/include/hdf/hdf.h" ; then
+      HDF4_INCLUDE="-I$with_hdf4/include/hdf"
+    elif test -r "$with_hdf4/include/hdf.h" ; then
+      HDF4_INCLUDE="-I$with_hdf4/include"
+    elif test -r "$with_hdf4/hdf.h" ; then
+      HDF4_INCLUDE="-I$with_hdf4"
+    fi
+
+    HAVE_HDF4=yes
+
+  else
+
+    if test x"$with_hdf4" != x"" ; then
+      AC_MSG_ERROR([HDF4 support requested with arg "$with_hdf4", but neither hdf4 nor mfhdf lib found])
+    else
+      LIBS="$ORIG_LIBS"
+      HAVE_HDF4=no
+    fi
+
+  fi
+
+fi
+
+AC_SUBST(HAVE_HDF4,$HAVE_HDF4)
+AC_SUBST(HDF4_INCLUDE,$HDF4_INCLUDE)
+AC_SUBST(HDF4_HAS_MAXOPENFILES,$HDF4_HAS_MAXOPENFILES)
+
+if test "$HAVE_HDF4" != "no" ; then
+  OPT_GDAL_FORMATS="hdf4 $OPT_GDAL_FORMATS"
+fi
+
+
+dnl ---------------------------------------------------------------------------
+dnl Select an HDF5 Library to use, or disable driver.
+dnl
+dnl ---------------------------------------------------------------------------
+
+HDF5_INCLUDE=""
+
+AC_ARG_WITH(hdf5,[  --with-hdf5[=ARG]       Include HDF5 support (ARG=path)],,)
+
+if test "$with_hdf5" = "no" ; then
+
+  HAVE_HDF5=no
+
+  echo "hdf5 support disabled."
+
+elif test "$with_hdf5" = "yes" -o "$with_hdf5" = "" ; then
+
+  HDF5_CFLAGS=""
+  HDF5_LIBS=""
+  PKG_PROG_PKG_CONFIG([0.25]) # check and set $PKG_CONFIG
+  PKG_CHECK_MODULES([HDF5], [hdf5], [HAVE_HDF5=yes], [HAVE_HDF5=no])
+
+  if test "$HAVE_HDF5" = "yes"; then
+
+    # Test that the package found is for the right architecture
+    saved_LIBS="$LIBS"
+    LIBS="$HDF5_LIBS"
+    AC_CHECK_LIB(hdf5,H5Fopen, [HAVE_HDF5=yes], [HAVE_HDF5=no])
+    LIBS="$saved_LIBS"
+
+    if test "$HAVE_HDF5" = "yes"; then
+        LIBS="$HDF5_LIBS $LIBS"
+        HDF5_INCLUDE="$HDF5_CFLAGS"
+    fi
+
+  else
+
+    AC_CHECK_LIB(hdf5,H5Fopen,HAVE_HDF5=yes,HAVE_HDF5=no,)
+
+    if test "$HAVE_HDF5" = "yes" ; then
+        LIBS="-lhdf5 $LIBS"
+    fi
+
+    dnl Some Linux distros install hdf include files here.
+    if test "$HAVE_HDF5" = "yes" -a -r /usr/include/hdf5.h ; then
+        HDF5_INCLUDE="-I/usr/include"
+    fi
+  fi
+
+else
+
+  if test -d $with_hdf5/lib ; then
+    HDF5_LIB_DIR=$with_hdf5/lib
+  else
+    HDF5_LIB_DIR=$with_hdf5
+  fi
+
+  ORIG_LIBS="$LIBS"
+  LIBS="-L$HDF5_LIB_DIR $LIBS -lhdf5"
+
+  AC_CHECK_LIB(hdf5,H5Fopen,HDF5_LIB_NAME="-lhdf5 ",HDF5_LIB_NAME=missing,-lhdf5)
+
+  if test "$HDF5_LIB_NAME" = "missing" ; then
+    AC_MSG_ERROR([HDF5 support requested with arg $with_hdf5, but no hdf5 lib found])
+  fi
+
+  LIBS="-L$HDF5_LIB_DIR $HDF5_LIB_NAME $ORIG_LIBS"
+
+  if test -r "$with_hdf5/hdf5/hdf5.h" ; then
+    HDF5_INCLUDE="-I$with_hdf5/hdf5"
+  elif test -r "$with_hdf5/include/hdf5/hdf5.h" ; then
+    HDF5_INCLUDE="-I$with_hdf5/include/hdf5"
+  elif test -r "$with_hdf5/include/hdf5.h" ; then
+    HDF5_INCLUDE="-I$with_hdf5/include"
+  elif test -r "$with_hdf5/hdf.h" ; then
+    HDF5_INCLUDE="-I$with_hdf5"
+  fi
+
+  HAVE_HDF5=yes
+fi
+
+AC_SUBST(HAVE_HDF5,$HAVE_HDF5)
+AC_SUBST(HDF5_INCLUDE,$HDF5_INCLUDE)
+
+if test "$HAVE_HDF5" != "no" ; then
+  OPT_GDAL_FORMATS="hdf5 $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if kealib library is available.
+dnl ---------------------------------------------------------------------------
+
+KEA_CONFIG=no
+
+AC_ARG_WITH(kea,[  --with-kea[=ARG]      Include kealib (ARG=path to kea-config) [[default=yes]]],,)
+
+if test "$with_kea" = "yes" -o "x$with_kea" = "x" ; then
+  AC_PATH_PROG(KEA_CONFIG, kea-config, no)
+else
+   KEA_CONFIG=$with_kea
+fi
+
+AC_MSG_CHECKING([for kea])
+
+if test "$KEA_CONFIG" = "no" ; then
+
+  HAVE_KEA=no
+  KEA_LIB=
+  KEA_INC=
+
+  AC_MSG_RESULT([no])
+
+else
+  if test -d $KEA_CONFIG ; then
+      AC_MSG_RESULT([no])
+      AC_MSG_ERROR([--with-kea argument is a directory.  It should be the path to the kea_config script, often somewhere like /usr/local/bin/kea_config.])
+  fi
+
+  if test \! -x $KEA_CONFIG ; then
+      AC_MSG_RESULT([no])
+      AC_MSG_ERROR([--with-kea argument is a not an executable file.  It should be the path to the kea_config script, often somewhere like /usr/local/bin/kea_config.])
+  fi
+
+  HAVE_KEA=yes
+  KEA_LIB="`$KEA_CONFIG --libs --hdflibs`"
+  KEA_INC="`$KEA_CONFIG --cflags --hdfcflags`"
+  AC_MSG_RESULT([yes])
+fi
+
+AC_SUBST(HAVE_KEA,$HAVE_KEA)
+AC_SUBST(KEA_INC,$KEA_INC)
+AC_SUBST(KEA_LIB,$KEA_LIB)
+
+if test "$HAVE_KEA" != "no" ; then
+  OPT_GDAL_FORMATS="kea $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if netcdf library is available.
+dnl ---------------------------------------------------------------------------
+
+NETCDF_SETTING=
+NETCDF_ROOT=
+NETCDF_HAS_NC4=
+NETCDF_HAS_HDF4=
+NETCDF_NCCONFIG=
+
+AC_ARG_WITH([netcdf],[  --with-netcdf[=ARG]     Include netCDF support (ARG=no or netCDF tree prefix)],,)
+
+if test "$with_netcdf" = "no" ; then
+
+  NETCDF_SETTING=no
+
+  echo "netCDF support disabled."
+
+else
+
+  dnl find nc-config location
+  unset ac_cv_path_NETCDF_NCCONFIG
+  if test "$with_netcdf" = "yes" -o "$with_netcdf" = "" ; then
+    AC_PATH_PROG(NETCDF_NCCONFIG, nc-config, no)
+  else
+    tmp_path="$with_netcdf/bin$PATH_SEPARATOR$with_netcdf"
+    AC_PATH_PROG(NETCDF_NCCONFIG, nc-config, no, $tmp_path)
+  fi
+
+  dnl test nc-config
+  if test "$NETCDF_NCCONFIG" = "no" ; then
+    echo "        did not find nc-config, some features may be missing"
+    echo "        use --with-netcdf=/path/to/netcdf or add nc-config to PATH"
+    NETCDF_NCCONFIG=
+  elif test "`$NETCDF_NCCONFIG --version`" = "" ; then
+    echo "did not get netCDF version from $NETCDF_NCCONFIG ... using fallback"
+    NETCDF_NCCONFIG=
+  fi
+
+  dnl test linking using flags from nc-config
+  if test "$NETCDF_NCCONFIG" != "" ; then
+
+    AC_MSG_CHECKING([libnetcdf compiler and linker flags with nc-config])
+    NETCDF_VERSION=`$NETCDF_NCCONFIG --version`
+    NETCDF_PREFIX=`$NETCDF_NCCONFIG --prefix`
+    NETCDF_INCLUDEDIR=`$NETCDF_NCCONFIG --includedir`
+    NETCDF_LIBS=`$NETCDF_NCCONFIG --libs`
+    echo ""
+    AC_MSG_RESULT([ got version="$NETCDF_VERSION", prefix="$NETCDF_PREFIX",
+ libs="$NETCDF_LIBS", includedir="$NETCDF_INCLUDEDIR"])
+
+    AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no], $NETCDF_LIBS)
+
+    if test "$NETCDF_SETTING" = "yes" ; then
+      EXTRA_INCLUDES="-I$NETCDF_INCLUDEDIR $EXTRA_INCLUDES"
+      NETCDF_ROOT=$NETCDF_PREFIX
+      LIBS="$NETCDF_LIBS $LIBS"
+    fi
+
+dnl previous behaviour without nc-config
+
+dnl test linking using default settings
+elif test "$with_netcdf" = "yes" -o "$with_netcdf" = "" ; then
+
+  AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no],)
+
+  if test "$NETCDF_SETTING" = "yes" ; then
+
+    dnl Fedora has netcdf headers in /usr/include/netcdf
+    if test -d /usr/include/netcdf ; then
+      EXTRA_INCLUDES="-I/usr/include/netcdf $EXTRA_INCLUDES"
+      NETCDF_ROOT="/usr"
+    dnl RHEL 5 has netcdf headers in /usr/include/netcdf-3
+    elif test -d /usr/include/netcdf-3 ; then
+      EXTRA_INCLUDES="-I/usr/include/netcdf-3 $EXTRA_INCLUDES"
+      NETCDF_ROOT="/usr"
+    dnl ubuntu and fedora have netcdf headers in /usr/include
+    elif test -f /usr/include/netcdf.h ; then
+      NETCDF_ROOT="/usr"
+    dnl try /usr/local
+    elif test -f /usr/local/include/netcdf.h ; then
+      NETCDF_ROOT="/usr/local"
+    dnl print warning if include cannot be found
+    else
+      echo "using pre-installed libnetcdf."
+      echo -n "libnetcdf is installed but its location cannot be found, "
+      echo "use --with-netcdf=/path_to_netcdf for proper support"
+    fi
+
+    LIBS="-lnetcdf $LIBS"
+    if test "$NETCDF_ROOT" != "" ; then
+      echo "using pre-installed libnetcdf from "$NETCDF_ROOT
+    fi
+
+  else
+    echo "libnetcdf not found ... netCDF support disabled"
+  fi
+
+dnl test linking using --with_netcdf dir
+else
+
+  AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no],-L$with_netcdf -L$with_netcdf/lib)
+
+  if test "$NETCDF_SETTING" = "yes" ; then
+
+    NETCDF_SETTING=yes
+    NETCDF_ROOT="$with_netcdf"
+
+    if test -d $with_netcdf/lib ; then
+      LIBS="-L$with_netcdf/lib -lnetcdf $LIBS"
+      EXTRA_INCLUDES="-I$with_netcdf/include $EXTRA_INCLUDES"
+    else
+      LIBS="-L$with_netcdf -lnetcdf $LIBS"
+      EXTRA_INCLUDES="-I$with_netcdf $EXTRA_INCLUDES"
+    fi
+
+    echo "using libnetcdf from $with_netcdf"
+
+  else
+    echo "libnetcdf not found in "$with_netcdf" ... netCDF support disabled"
+  fi
+
+fi
+
+dnl test for NC4 and HDF4 support with nc-config
+  if test "$NETCDF_SETTING" = "yes" ; then
+
+    if test "$NETCDF_NCCONFIG" != "" ; then
+
+      AC_MSG_CHECKING([for netcdf-4 (and HDF5) support in libnetcdf])
+        if test "x$($NETCDF_NCCONFIG --has-nc4)" = "xyes"; then :
+          AC_MSG_RESULT([yes])
+          NETCDF_HAS_NC4=yes
+        else
+          AC_MSG_RESULT([no])
+          NETCDF_HAS_NC4=no
+        fi
+
+      AC_MSG_CHECKING([for HDF4 support in libnetcdf])
+        if test "x$($NETCDF_NCCONFIG --has-hdf4)" = "xyes"; then :
+          AC_MSG_RESULT([yes])
+          NETCDF_HAS_HDF4=yes
+        else
+          AC_MSG_RESULT([no])
+          NETCDF_HAS_HDF4=no
+        fi
+
+    else
+      NETCDF_HAS_NC4=no
+      NETCDF_HAS_HDF4=no
+    fi
+fi
+
+fi
+
+dnl export results
+
+AC_SUBST([NETCDF_SETTING], [$NETCDF_SETTING])
+
+if test "$NETCDF_SETTING" != "no" ; then
+
+   AC_SUBST([NETCDF_ROOT], [$NETCDF_ROOT])
+   AC_SUBST([NETCDF_HAS_NC4], [$NETCDF_HAS_NC4])
+   AC_SUBST([NETCDF_HAS_HDF4], [$NETCDF_HAS_HDF4])
+
+   OPT_GDAL_FORMATS="netcdf $OPT_GDAL_FORMATS"
+
+fi
+
+
+dnl ---------------------------------------------------------------------------
+dnl Select a JasPer Library to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(jasper,[  --with-jasper[=ARG]     Include JPEG-2000 support via JasPer library (ARG=path)],,)
+
+if test "$with_jasper" = "no" ; then
+
+  HAVE_JASPER=no
+
+  AC_MSG_NOTICE([JasPer (JPEG2000) support disabled.])
+
+elif test "$with_jasper" = "yes" -o "$with_jasper" = "" ; then
+
+  AC_CHECK_LIB(jasper,jpc_decode,HAVE_JASPER=yes,HAVE_JASPER=no,)
+  AC_CHECK_LIB(jasper,jp2_decode,HAVE_JASPER=yes,HAVE_JASPER=no,)
+  AC_CHECK_LIB(jasper,pgx_decode,HAVE_JASPER=yes,HAVE_JASPER=no,)
+
+  if test "$HAVE_JASPER" = "yes" ; then
+    LIBS="-ljasper $LIBS"
+  fi
+else
+
+  HAVE_JASPER=yes
+  LIBS="-L$with_jasper -L$with_jasper/lib -ljasper $LIBS"
+  EXTRA_INCLUDES="-I$with_jasper -I$with_jasper/include $EXTRA_INCLUDES"
+
+  AC_MSG_NOTICE([using JasPer library from $with_jasper.])
+fi
+
+if test "$HAVE_JASPER" != "no" ; then
+  OPT_GDAL_FORMATS="jpeg2000 $OPT_GDAL_FORMATS"
+
+  dnl Test whether we have UUID JasPer hack
+
+  AC_CHECK_LIB(jasper,jp2_encode_uuid,HAVE_JASPER_UUID=yes,HAVE_JASPER_UUID=no,)
+
+  if test "$HAVE_JASPER_UUID" = "yes" ; then
+    AC_MSG_NOTICE([hacked JasPer version found (JasPer UUID), GeoJP2 enabled.])
+    JASPER_FLAGS=-DHAVE_JASPER_UUID
+  else
+    AC_MSG_NOTICE([hacked JasPer version not found, GeoJP2 disabled.])
+  fi
+fi
+
+AC_SUBST([HAVE_JASPER],$HAVE_JASPER)
+AC_SUBST([JASPER_FLAGS],$JASPER_FLAGS)
+
+
+dnl ---------------------------------------------------------------------------
+dnl Select a OpenJPEG Library to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(openjpeg,[  --with-openjpeg[=ARG]     Include JPEG-2000 support via OpenJPEG 2.0 library (ARG=path)],,)
+
+HAVE_OPENJPEG=no
+
+if test "$with_openjpeg" = "no" ; then
+
+  AC_MSG_NOTICE([OpenJPEG (JPEG2000) support disabled.])
+
+elif test "$with_openjpeg" = "yes" -o "$with_openjpeg" = "" ; then
+
+  AC_CHECK_HEADERS([openjpeg-2.0/openjpeg.h])
+  if test "$ac_cv_header_openjpeg_2_0_openjpeg_h" = "yes"; then
+    AC_CHECK_LIB(openjp2,opj_stream_set_user_data_length,HAVE_OPENJPEG=yes,HAVE_OPENJPEG=no,)
+    if test "$HAVE_OPENJPEG" = "yes"; then
+        LIBS="-lopenjp2 $LIBS"
+    fi
+  else
+    AC_CHECK_HEADERS([openjpeg-2.1/openjpeg.h])
+    if test "$ac_cv_header_openjpeg_2_1_openjpeg_h" = "yes"; then
+        AC_CHECK_LIB(openjp2,opj_stream_set_user_data_length,HAVE_OPENJPEG=yes,HAVE_OPENJPEG=no,)
+        if test "$HAVE_OPENJPEG" = "yes"; then
+            OPENJPEG_VERSION=20100
+            LIBS="-lopenjp2 $LIBS"
+        fi
+    fi
+  fi
+else
+
+  HAVE_OPENJPEG=yes
+  if test -r $with_openjpeg/include/openjpeg-2.0/openjpeg.h ; then
+    EXTRA_INCLUDES="-I$with_openjpeg/include $EXTRA_INCLUDES"
+  elif test -r $with_openjpeg/include/openjpeg-2.1/openjpeg.h ; then
+    OPENJPEG_VERSION=20100
+    EXTRA_INCLUDES="-I$with_openjpeg/include $EXTRA_INCLUDES"
+  else
+    AC_MSG_ERROR([openjpeg.h not found in $with_openjpeg/include/openjpeg-2.0 or $with_openjpeg/include/openjpeg-2.1])
+  fi
+
+  AC_CHECK_LIB(openjp2,opj_stream_set_user_data_length,HAVE_OPENJPEG=yes,HAVE_OPENJPEG=no,-L$with_openjpeg/lib)
+
+  if test "$HAVE_OPENJPEG" = "yes"; then
+      LIBS="-L$with_openjpeg/lib -lopenjp2 $LIBS"
+      AC_MSG_NOTICE([using OpenJPEG v2 library from $with_openjpeg.])
+  fi
+fi
+
+if test "$HAVE_OPENJPEG" != "no" ; then
+  OPT_GDAL_FORMATS="openjpeg $OPT_GDAL_FORMATS"
+fi
+
+AC_SUBST([HAVE_OPENJPEG],$HAVE_OPENJPEG)
+AC_SUBST([OPENJPEG_VERSION],$OPENJPEG_VERSION)
+
+dnl ---------------------------------------------------------------------------
+dnl Select a FGDB API to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(fgdb,[  --with-fgdb[=ARG]        Include ESRI File Geodatabase support (ARG=FGDP API Path, yes or no)],,)
+
+FGDB_ENABLED=no
+FGDB_LIB=
+
+if test "$with_fgdb" = "no" ; then
+
+  echo "FGDB support disabled."
+
+elif test "$with_fgdb" = "yes" -o "$with_fgdb" = "" ; then
+
+    AC_MSG_CHECKING([for FileGDBAPI])
+
+    rm -f testfgdb.*
+    rm -f testfgdb
+    echo "#include <FileGDBAPI.h>" > testfgdb.cpp
+    echo "using namespace FileGDBAPI;" >> testfgdb.cpp
+    echo "int main() { Geodatabase oDB; std::wstring osStr; ::OpenGeodatabase(osStr, oDB); return 0; }" >> testfgdb.cpp
+    if test -z "`${CXX} ${CPPFLAGS} testfgdb.cpp -lFileGDBAPI -lfgdbunixrtl -o testfgdb 2>&1`" ; then
+        AC_MSG_RESULT([FileGDBAPI found])
+        FGDB_ENABLED="yes"
+        FGDB_LIB="-lFileGDBAPI -lfgdbunixrtl"
+    else
+        if test "$with_fgdb" = "yes"; then
+            AC_MSG_ERROR([FileGDBAPI not found.])
+        else
+            AC_MSG_RESULT([FileGDBAPI not found.])
+        fi
+    fi
+    rm -f testfgdb.*
+    rm -f testfgdb
+
+else
+
+  AC_MSG_CHECKING([for libFileGDBAPI.so in in $with_fgdb/lib])
+  FGDB_ENABLED=yes
+  if test -r $with_fgdb/lib/libFileGDBAPI.so -a -r $with_fgdb/lib/libfgdbunixrtl.so ; then
+    AC_MSG_RESULT([found.])
+    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdbunixrtl"
+  elif test -r $with_fgdb/lib/libFileGDBAPI.dylib -a -r $with_fgdb/lib/libfgdbunixrtl.dylib ; then
+    AC_MSG_RESULT([found.])
+    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdbunixrtl"
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+  AC_MSG_CHECKING([for FileGDBAPI.h in $with_fgdb/include])
+  if test -r $with_fgdb/include/FileGDBAPI.h ; then
+    AC_MSG_RESULT([found.])
+    FGDB_INC="-I$with_fgdb/include"
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+
+fi
+
+if test "$FGDB_LIB" != ""; then
+  dnl pj_datums is not a function but an object, but for linking that doesn't matter.
+  AC_CHECK_LIB(FileGDBAPI,pj_datums,FGDB_HAS_PROJ4=yes,FGDB_HAS_PROJ4=no,$FGDB_LIB)
+fi
+
+AC_SUBST(FGDB_ENABLED, $FGDB_ENABLED)
+AC_SUBST(FGDB_LIB, $FGDB_LIB)
+AC_SUBST(FGDB_INC, $FGDB_INC)
+
+dnl ---------------------------------------------------------------------------
+dnl Select a ECW Library to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+ECW_FLAGS=
+ECW_LIBS=
+ECW_INCLUDE=
+
+AC_ARG_WITH(ecw,[  --with-ecw[=ARG]        Include ECW support (ARG=ECW SDK Path, yes or no)],,)
+
+if test ! -z "`uname | grep Darwin`" ; then
+  CARBON_FRAMEWORK="-framework Carbon"
+else
+  CARBON_FRAMEWORK=
+fi
+
+if test "$with_ecw" = "no" ; then
+
+  ECW_SETTING=no
+
+  echo "ECW support disabled."
+
+elif test "$with_ecw" = "yes" -o "$with_ecw" = "" ; then
+
+  AC_CHECK_LIB(NCSEcw,NCScbmOpenFileView,ECW_SETTING=yes,ECW_SETTING=no,-lNCSCnet -lNCSUtil)
+
+  if test "$ECW_SETTING" = "yes" ; then
+    ECW_LIBS="-lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil"
+  fi
+
+  if test "$ECW_SETTING" = "no" ; then
+    AC_CHECK_LIB(ecwj2,NCScbmOpenFileView,ECW_SETTING=yes,ECW_SETTING=no,$CARBON_FRAMEWORK)
+    if test "$ECW_SETTING" = "yes" ; then
+      ECW_LIBS="-lecwj2 $CARBON_FRAMEWORK"
+    fi
+  fi
+else
+
+  AC_MSG_CHECKING([for libNCSEcw.a or libecwj2])
+  ECW_ARCH=x86
+  ECW_CONF="release"
+  ECW_FLAGS="-DLINUX -DX86 -DPOSIX -DHAVE_COMPRESS -DECW_COMPRESS_RW_SDK_VERSION"
+  ECW_FRAMEWORK_COCOA=""
+  if test "`arch`" = "x86_64" ; then
+    ECW_ARCH="x64"
+  fi
+  if test ! -z "`uname | grep Darwin`" ; then
+    ECW_ARCH=""
+    ECW_CONF=""
+    ECW_FLAGS=""
+    ECW_FRAMEWORK_COCOA=" -framework Cocoa "
+  fi
+
+  ECW_SETTING=yes
+  if test -r $with_ecw/lib/libNCSCnet.so -o -r $with_ecw/lib/libNCSCnet.dylib ; then
+    ECW_LIBS="-L$with_ecw/lib -lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil"
+    AC_MSG_RESULT([found in $with_ecw/lib.])
+  elif test -r $with_ecw/lib/libNCSCNet.so -o -r $with_ecw/lib/libNCSCNet.dylib ; then
+    ECW_LIBS="-L$with_ecw/lib -lNCSEcw -lNCSEcwC -lNCSCNet -lNCSUtil"
+    AC_MSG_RESULT([found in $with_ecw/lib.])
+  elif test -r $with_ecw/bin/libNCSEcw.so -o -r $with_ecw/bin/libNCSEcw.dylib ; then
+    ECW_LIBS="-L$with_ecw/bin -lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil"
+    AC_MSG_RESULT([found in $with_ecw/bin.])
+  elif test -r $with_ecw/lib/libecwj2.dylib ; then
+    ECW_LIBS="-L$with_ecw/lib -lecwj2 $CARBON_FRAMEWORK"
+    AC_MSG_RESULT([found libecwj2 in $with_ecw/lib.])
+
+  # ECW SDK 5.0 style and also for the case where license type is included in path i.e. specific license type is requested.
+  elif test -r $with_ecw/lib/$ECW_ARCH/$ECW_CONF/libNCSEcw.a ; then
+    ECW_LIBDIR=$with_ecw/lib/$ECW_ARCH/$ECW_CONF
+    ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw $ECW_FRAMEWORK_COCOA"
+    AC_MSG_RESULT([found Intergraph 5.x+ SDK in ${ECW_LIBDIR}.])
+ # ECWJP2 SDK 5.1 style
+  elif test -d $with_ecw; then
+    for ecw_license_type in "Desktop_Read-Write" "Server_Read-Only_EndUser" "Server_Read-Only" "Server_Read-Write" "Desktop_Read-Only"
+      do
+        ECW_LIBDIR=$with_ecw/$ecw_license_type/lib/$ECW_ARCH/$ECW_CONF
+        if test -r $ECW_LIBDIR/libNCSEcw.a; then
+          ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw $ECW_FRAMEWORK_COCOA"
+          with_ecw=$with_ecw/$ecw_license_type
+          AC_MSG_RESULT([found Intergraph 5.x+ SDK in ${ECW_LIBDIR}.])
+          break
+        fi
+      done
+ else
+    AC_MSG_ERROR([not found in $with_ecw.])
+  fi
+
+  AC_MSG_CHECKING([for NCSECWClient.h in $with_ecw/include])
+  if test -r $with_ecw/include/NCSECWClient.h ; then
+    AC_MSG_RESULT([found.])
+    ECW_INCLUDE="-I$with_ecw/include"
+  else
+    AC_MSG_ERROR([not found.])
+  fi
+  AC_MSG_CHECKING([for ECWJP2BuildNumber.h in $with_ecw/include])
+  if test -r $with_ecw/include/ECWJP2BuildNumber.h ; then
+    AC_MSG_RESULT([found.])
+    ECW_FLAGS="-DHAVE_ECW_BUILDNUMBER_H $ECW_FLAGS"
+  else
+    AC_MSG_RESULT([not found.])
+  fi
+fi
+
+AC_SUBST(ECW_SETTING,$ECW_SETTING)
+AC_SUBST(ECW_LIBS,$ECW_LIBS)
+AC_SUBST(ECW_FLAGS,$ECW_FLAGS)
+AC_SUBST(ECW_INCLUDE,$ECW_INCLUDE)
+
+if test "$ECW_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="ecw $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Select Kakadu library or disable driver.
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([for Kakadu JPEG2000 support])
+
+AC_ARG_WITH(kakadu,[  --with-kakadu[=ARG]     Include Kakadu/JPEG2000 support],,)
+
+if test "$with_kakadu" = "no" -o "$with_kakadu" = "" ; then
+  KAKDIR=
+  AC_MSG_RESULT([not requested.])
+  HAVE_KAKADU=no
+elif test "$with_kakadu" = "yes" ; then
+  AC_MSG_ERROR([
+For JPEG2000 support using Kakadu you need provide the path to the Kakadu
+build directory.  Note that Kakadu is *not* free software.])
+else
+  KAKDIR=$with_kakadu
+  OPT_GDAL_FORMATS="jp2kak jpipkak $OPT_GDAL_FORMATS"
+  LIBS="$LIBS -L$with_kakadu/lib -lkdu"
+  AC_MSG_RESULT([requested.])
+  HAVE_KAKADU=yes
+fi
+
+AC_SUBST(KAKDIR,$KAKDIR)
+
+dnl ---------------------------------------------------------------------------
+dnl Select MrSID library or disable driver.
+dnl ---------------------------------------------------------------------------
+MRSID_FLAGS=
+HAVE_MRSID=no
+
+AC_ARG_WITH(mrsid,[  --with-mrsid[=ARG]      Include MrSID support (ARG=path to MrSID DSDK or no)],,)
+
+AC_ARG_WITH(jp2mrsid,[  --with-jp2mrsid[=ARG]   Enable MrSID JPEG2000 support (ARG=yes/no)],,)
+
+if test "x$with_mrsid" = "xno"  -o "x$with_mrsid" = "x" ; then
+
+  HAVE_MRSID=no
+
+  AC_MSG_NOTICE([MrSID support disabled.])
+
+else
+
+  MRSID_BASE="$with_mrsid/include"
+
+  AC_MSG_CHECKING([for lt_base.h in $MRSID_BASE/support])
+  if test -r "$MRSID_BASE/support/lt_base.h" ; then
+
+    AC_MSG_RESULT([found MrSID DSDK version 4.x or newer.])
+    HAVE_MRSID=yes
+    MRSID_INCLUDE="-I$MRSID_BASE/base -I$MRSID_BASE/metadata -I$MRSID_BASE/mrsid_readers -I$MRSID_BASE/j2k_readers -I$MRSID_BASE/support"
+
+  else
+
+    AC_MSG_RESULT([not found.])
+
+    AC_MSG_CHECKING([for lt_base.h in $MRSID_BASE])
+    if test -r "$MRSID_BASE/lt_base.h" ; then
+
+      AC_MSG_RESULT([found MrSID DSDK version 7.x or newer.]);
+      HAVE_MRSID=yes
+      MRSID_INCLUDE="-I$MRSID_BASE"
+
+    fi
+
+  fi
+
+  if test $HAVE_MRSID = yes ; then
+
+    MRSID_LIBS="-lpthread"
+
+    if test -r "$with_mrsid/lib/libltiesdk.a" ; then # v8+ esdk contains dsdk
+      _LIBPART=lib
+      MRSID_LIBS="-lltiesdk $MRSID_LIBS"
+    elif test -e "$with_mrsid/lib/libltidsdk.a" \
+           -o -e "$with_mrsid/lib/libltidsdk.so" \
+           -o -e "$with_mrsid/lib/libltidsdk.dylib" ; then
+      _LIBPART=lib
+      MRSID_LIBS="-lltidsdk $MRSID_LIBS"
+    else
+      _LIBPART=lib/Release
+      MRSID_LIBS="-lltidsdk $MRSID_LIBS"
+    fi
+
+    AC_MSG_CHECKING([for MG3ImageWriter.h in $with_mrsid/include/mrsid_writers])
+    if test -r "$with_mrsid/include/mrsid_writers/MG3ImageWriter.h" ; then
+      AC_MSG_RESULT([found MrSID ESDK version 4.x or newer.])
+      MRSID_FLAGS="-DMRSID_ESDK $MRSID_FLAGS"
+      MRSID_INCLUDE="-I$with_mrsid/include/mrsid_writers -I$with_mrsid/include/j2k_writers $MRSID_INCLUDE"
+      if test -r $with_mrsid/3rd-party/lib/Release/libcryptopp.a ; then
+        MRSID_LIBS="-lltiesdk -lcryptopp -lxmlparse $MRSID_LIBS"
+      else
+        MRSID_LIBS="-lltiesdk -lxmlparse $MRSID_LIBS"
+      fi
+    else
+      AC_MSG_RESULT([no encoding support.])
+    fi
+
+    AC_MSG_CHECKING([for MrSID JPEG2000 support])
+    if test "x$with_jp2mrsid" = "xyes" -a "$HAVE_KAKADU" = "yes" ; then
+      # SDK v8 or later don't seem to conflict with Kakadu
+      major_version=`cat $with_mrsid/include/lti_version.h | grep MAJOR | sed 's/#define LTI_SDK_MAJOR[ ]*\(.*\)/\1/'`
+      if test "x$major_version" != "x"; then
+        if test "$major_version" -ge 8; then
+            V8_OR_LATER=yes
+        fi
+      fi
+      if test "x$V8_OR_LATER" = "x"; then
+        AC_MSG_ERROR([MrSID JPEG2000 support requested, but this is incompatible with use of standalone Kakadu])
+      fi
+    fi
+
+    MRSID_KAKADU_LIB=""
+    if test "$HAVE_KAKADU" = "no" ; then
+      if test x"$with_jp2mrsid" = x"" -o x"$with_jp2mrsid" = x"yes" ; then
+        if test -r "$with_mrsid/3rd-party/$_LIBPART/libltikdu.a" ; then
+          with_jp2mrsid=yes
+          MRSID_KAKADU_LIB=-lltikdu
+        elif test -r "$with_mrsid/3rd-party/$_LIBPART/liblt_kakadu.a" ; then
+          with_jp2mrsid=yes
+          MRSID_KAKADU_LIB=-llt_kakadu
+        elif test -e "$with_mrsid/lib/libltidsdk.so" \
+               -o -e "$with_mrsid/lib/libltidsdk.dylib"; then # v8+ .so has kdu
+          with_jp2mrsid=yes
+        elif test x"$with_jp2mrsid" = x"yes" ; then
+          AC_MSG_ERROR([MrSID JPEG2000 support requested, but libltikdu.a not found.])
+        else
+          with_jp2mrsid=no
+        fi
+      fi
+    fi
+
+    if test "x$with_jp2mrsid" = "xyes" ; then
+      MRSID_LIBS="$MRSID_LIBS $MRSID_KAKADU_LIB"
+      MRSID_FLAGS="-DMRSID_J2K $MRSID_FLAGS"
+      AC_MSG_RESULT([enabled])
+    else
+      AC_MSG_RESULT([disabled])
+    fi
+
+    MRSID_LIBS="-L$with_mrsid/$_LIBPART $MRSID_LIBS"
+    MRSID_LIBS="-L$with_mrsid/3rd-party/$_LIBPART $MRSID_LIBS"
+
+  else
+    HAVE_MRSID=no
+    AC_MSG_RESULT([not found.])
+    AC_MSG_ERROR([  MrSID requested, but components not found.])
+  fi
+fi
+
+AC_SUBST(MRSID_INCLUDE,$MRSID_INCLUDE)
+AC_SUBST(MRSID_FLAGS,$MRSID_FLAGS)
+AC_SUBST(MRSID_LIBS,$MRSID_LIBS)
+
+if test "$HAVE_MRSID" != "no" ; then
+  CPPFLAGS="-D_REENTRANT $CPPFLAGS"
+  OPT_GDAL_FORMATS="mrsid $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Select MrSID/MG4 Lidar library or disable driver.
+dnl ---------------------------------------------------------------------------
+
+MRSID_LIDAR_FLAGS=
+HAVE_MRSID_LIDAR=no
+
+AC_ARG_WITH(mrsid_lidar,[  --with-mrsid_lidar[=ARG]      Include MrSID/MG4 LiDAR support (ARG=path to LizardTech LiDAR SDK or no)],,)
+
+if test "x$with_mrsid_lidar" = "xno"  -o "x$with_mrsid_lidar" = "x" ; then
+  HAVE_MRSID_LIDAR=no
+  AC_MSG_NOTICE([MrSID/MG4 Lidar support disabled.])
+else
+  MRSID_LIDAR_BASE="$with_mrsid_lidar"
+
+  if test -r "$MRSID_LIDAR_BASE/include/lidar/Version.h" ; then
+    AC_MSG_RESULT([found LizardTech LiDAR SDK 1.1 or newer.])
+    HAVE_MRSID_LIDAR=yes
+  else
+    HAVE_MRSID_LIDAR=no
+    AC_MSG_RESULT([not found.])
+    AC_MSG_ERROR([  MrSID/MG4 Lidar requested, but components not found.])
+  fi
+
+  if test $HAVE_MRSID_LIDAR = yes ; then
+    if test -e "$MRSID_LIDAR_BASE/lib/liblti_lidar_dsdk.so" \
+         -o -e "$MRSID_LIDAR_BASE/lib/liblti_lidar_dsdk.dylib"; then
+      MRSID_LIDAR_LIBS="-L$MRSID_LIDAR_BASE/lib -llti_lidar_dsdk"
+      MRSID_LIDAR_INCLUDE="-I$MRSID_LIDAR_BASE/include"
+    else
+      MRSID_LIDAR_LIBS="-L$MRSID_LIDAR_BASE/lib/Release -llti_lidar_dsdk"
+      MRSID_LIDAR_INCLUDE="-I$MRSID_LIDAR_BASE/include"
+    fi
+  fi
+fi
+
+AC_SUBST(MRSID_LIDAR_INCLUDE,$MRSID_LIDAR_INCLUDE)
+AC_SUBST(MRSID_LIDAR_LIBS,$MRSID_LIDAR_LIBS)
+
+if test "$HAVE_MRSID_LIDAR" != "no" ; then
+  OPT_GDAL_FORMATS="mrsid_lidar $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if LuraTech library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(jp2lura,[  --with-j2lura[=ARG]    Include JP2Lua support (ARG=no, lura SDK install path)],,)
+
+AC_MSG_CHECKING([for JP2Lura support])
+
+HAVE_JP2LURA=no
+JP2LURA_INCLUDE=
+
+if test "$with_jp2lura" != "" -a "$with_jp2lura" != "no" ; then
+  AC_MSG_CHECKING([for lwf_jp2.h])
+  if test -f "$with_jp2lura/include/lwf_jp2.h"; then
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+    AC_MSG_ERROR([JP2Lura support requested but header not found])
+  fi
+  JP2LURA_INCLUDE="-I$with_jp2lura/include"
+
+  # mingw support
+  if test -f "$with_jp2lura/library/lwf_jp2.lib"; then
+      ln -s "$with_jp2lura/library/lwf_jp2.lib" "$with_jp2lura/library/lib_lwf_jp2.a"
+  fi
+
+  ORIG_LIBS="$LIBS"
+  LIBS="-L$with_jp2lura/library"
+
+  AC_CHECK_LIB(_lwf_jp2,JP2_Decompress_SetLicense,HAVE_JP2LURA="yes",,-lm)
+
+  if test "$HAVE_JP2LURA" = "no" ; then
+    AC_MSG_ERROR([JP2Lura support requested but library not found])
+  fi
+
+  LIBS="-L$with_jp2lura/library -l_lwf_jp2 -lm $ORIG_LIBS"
+fi
+
+AC_SUBST([JP2LURA_INCLUDE], [$JP2LURA_INCLUDE])
+
+if test "$HAVE_JP2LURA" != "no" ; then
+  OPT_GDAL_FORMATS="jp2lura $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Enable MSG format if EUMETSAT Wavelet Transform Software
+dnl available in the local tree
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([msg],
+	    AS_HELP_STRING([--with-msg[=ARG]],
+	       [Enable MSG driver (ARG=yes or no)]),,)
+
+HAVE_MSG=no
+HAVE_EUMETSATWT=no
+
+if test "x$with_msg" = "xyes" ; then
+    AC_MSG_CHECKING([for EUMETSAT Wavelet Transformation Software])
+
+    if test -d "frmts/msg/PublicDecompWT" -a \
+        -f "frmts/msg/PublicDecompWT/COMP/Inc/CImage.h"; then
+        HAVE_EUMETSATWT=yes
+    else
+        HAVE_EUMETSATWT=no
+    fi
+    AC_MSG_RESULT([$HAVE_EUMETSATWT])
+fi
+
+AC_MSG_CHECKING([for MSG])
+
+if test "x$with_msg" = "xyes" -o "x$with_msg" = "x" \
+    -a "x$HAVE_EUMETSATWT" = "xyes"; then
+    OPT_GDAL_FORMATS="msg $OPT_GDAL_FORMATS"
+    HAVE_MSG=yes
+    AC_MSG_RESULT([enabled])
+else
+    HAVE_MSG=no
+    AC_MSG_RESULT([not requested])
+fi
+
+
+dnl ---------------------------------------------------------------------------
+dnl Check for BSB in the local tree.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([bsb],
+	    AS_HELP_STRING([--without-bsb],
+	       [Disable BSB driver (legal issues pending]),,)
+
+AC_MSG_CHECKING([for BSB])
+if test "$with_bsb" = yes -o x"$with_bsb" = x ; then
+    OPT_GDAL_FORMATS="bsb $OPT_GDAL_FORMATS"
+    AC_MSG_RESULT([enabled])
+else
+    AC_MSG_RESULT([disabled by user])
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check for GeoRaster in the local tree.
+dnl ---------------------------------------------------------------------------
+
+ORACLE_OCI_REQ_VERSION="10.0.1"
+AX_LIB_ORACLE_OCI($ORACLE_OCI_REQ_VERSION)
+
+if test "$HAVE_ORACLE_OCI" = "yes"; then
+    OPT_GDAL_FORMATS="georaster $OPT_GDAL_FORMATS"
+    HAVE_GEORASTER=yes
+else
+    HAVE_GEORASTER=no
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check for GRIB in the local tree.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([grib],
+	    AS_HELP_STRING([--without-grib],
+	       [Disable GRIB driver]),,)
+
+AC_MSG_CHECKING([for GRIB])
+if test "$with_grib" = yes -o x"$with_grib" = x ; then
+    OPT_GDAL_FORMATS="grib $OPT_GDAL_FORMATS"
+    HAVE_GRIB=yes
+    AC_MSG_RESULT([enabled])
+else
+    HAVE_GRIB=no
+    AC_MSG_RESULT([disabled by user])
+fi
+
+
+dnl ---------------------------------------------------------------------------
+
+AC_SUBST([OPT_GDAL_FORMATS], [$OPT_GDAL_FORMATS])
+
+dnl ---------------------------------------------------------------------------
+
+GNM_ENABLED=yes
+
+AC_ARG_WITH(gnm,[  --with-gnm            Build GNM into shared library],,)
+
+if test "$with_gnm" = "no" ; then
+  GNM_ENABLED=no
+  AC_MSG_RESULT([disabled by user])
+else
+  GNM_ENABLED=yes
+  AC_MSG_RESULT([enabled])
+fi
+AC_SUBST(GNM_ENABLED,$GNM_ENABLED)
+
+dnl ---------------------------------------------------------------------------
+dnl Select an MySQL Library to use, or disable driver.
+dnl ---------------------------------------------------------------------------
+
+MYSQL_CONFIG=no
+
+AC_ARG_WITH(mysql,[  --with-mysql[=ARG]      Include MySQL (ARG=path to mysql_config) [[default=no]]],,)
+
+if test "$with_mysql" = "yes" ; then
+  AC_PATH_PROG(MYSQL_CONFIG, mysql_config, no)
+else
+    if test "x$with_mysql" != "x" ; then
+      MYSQL_CONFIG=$with_mysql
+    fi
+fi
+
+AC_MSG_CHECKING([for MySQL])
+
+if test "$MYSQL_CONFIG" = "no" ; then
+
+  HAVE_MYSQL=no
+  MYSQL_LIB=
+  MYSQL_INC=
+
+  AC_MSG_RESULT([no])
+
+else
+  if test -d $MYSQL_CONFIG ; then
+      AC_MSG_RESULT([no])
+      AC_MSG_ERROR([--with-mysql argument is a directory.  It should be the path to the mysql_config script, often somewhere like /usr/local/bin/mysql_config.])
+  fi
+
+  if test \! -x $MYSQL_CONFIG ; then
+      AC_MSG_RESULT([no])
+      AC_MSG_ERROR([--with-mysql argument is a not an executable file.  It should be the path to the mysql_config script, often somewhere like /usr/local/bin/mysql_config.])
+  fi
+
+  MYSQL_VERSION="`$MYSQL_CONFIG --version`"
+  MYSQL_MAJOR_VERSION=${MYSQL_VERSION%%'.'*}
+
+  if test $MYSQL_MAJOR_VERSION -le 3 ; then
+    HAVE_MYSQL=no
+    AC_MSG_RESULT([no, mysql is pre-4.x])
+  else
+      HAVE_MYSQL=yes
+      MYSQL_LIB="`$MYSQL_CONFIG --libs`"
+      MYSQL_INC="`$MYSQL_CONFIG --include`"
+      AC_MSG_RESULT([yes])
+  fi
+fi
+
+AC_SUBST(HAVE_MYSQL,$HAVE_MYSQL)
+AC_SUBST(MYSQL_INC,$MYSQL_INC)
+AC_SUBST(MYSQL_LIB,$MYSQL_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl INGRES support.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(ingres,[  --with-ingres=ARG     Include Ingres (ARG=$II_SYSTEM)],,)
+
+AC_MSG_CHECKING([for Ingres])
+
+if test "$with_ingres" = "no" -o "x$with_ingres" = "x" ; then
+  HAVE_INGRES=no
+  II_SYSTEM=
+  INGRES_LIB=
+  INGRES_INC=
+  AC_MSG_RESULT([no])
+elif test "$with_ingres" = "yes" ; then
+  AC_MSG_ERROR([--with-ingres requires a path argument ($II_SYSTEM)])
+else
+  HAVE_INGRES=yes
+  II_SYSTEM=$with_ingres
+  INGRES_LIB="-L$II_SYSTEM/ingres/lib \
+	-liiapi.1 -lcompat.1 -lq.1 -lframe.1"
+  INGRES_INC=-I$II_SYSTEM/ingres/files
+fi
+
+AC_SUBST(HAVE_INGRES,$HAVE_INGRES)
+AC_SUBST(II_SYSTEM,$II_SYSTEM)
+AC_SUBST(INGRES_LIB,$INGRES_LIB)
+AC_SUBST(INGRES_INC,$INGRES_INC)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for Xerces C++ Parser support.
+dnl ---------------------------------------------------------------------------
+
+XERCES_REQ_VERSION="3.1.0"
+AX_LIB_XERCES($XERCES_REQ_VERSION)
+
+if test "$HAVE_XERCES" = "yes"; then
+    LIBS="$XERCES_LDFLAGS $LIBS"
+fi
+
+AC_SUBST([HAVE_XERCES], $HAVE_XERCES)
+AC_SUBST([XERCES_INCLUDE], $XERCES_CFLAGS)
+
+dnl ---------------------------------------------------------------------------
+dnl Enable NAS if we have Xerces.
+dnl ---------------------------------------------------------------------------
+
+if test "$HAVE_XERCES" = "yes" ; then
+  HAVE_NAS=yes
+else
+  HAVE_NAS=no
+fi
+AC_SUBST([HAVE_NAS], $HAVE_NAS)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for Expat configuration.
+dnl ---------------------------------------------------------------------------
+
+dnl Expat 1.95.0 released in 2000-09-28
+EXPAT_REQ_VERSION="1.95.0"
+AX_LIB_EXPAT($EXPAT_REQ_VERSION)
+
+if test "$HAVE_EXPAT" = "yes"; then
+    LIBS="$EXPAT_LDFLAGS $LIBS"
+fi
+
+AC_SUBST([HAVE_EXPAT], $HAVE_EXPAT)
+AC_SUBST([EXPAT_INCLUDE], $EXPAT_CFLAGS)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for Google libkml support.
+dnl ---------------------------------------------------------------------------
+
+LIBKML_REQ_VERSION="1.3.0"
+AX_LIB_LIBKML($LIBKML_REQ_VERSION)
+
+if test "$HAVE_LIBKML" = "yes"; then
+    LIBS="$LIBKML_LDFLAGS $LIBS"
+fi
+
+AC_SUBST([HAVE_LIBKML], $HAVE_LIBKML)
+AC_SUBST([LIBKML_INCLUDE], $LIBKML_CFLAGS)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for ODBC support.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(odbc,[  --with-odbc[=ARG]       Include ODBC support (ARG=no or path)],,)
+
+if test "$with_odbc" = "no" ; then
+
+  ODBC_SETTING=no
+
+  echo "ODBC support disabled."
+
+elif test "$with_odbc" = "yes" -o "$with_odbc" = "" ; then
+  ODBC_SETTING=no
+
+  echo "check for unixODBC"
+  AC_CHECK_LIB(odbc,SQLConnect,[ODBC_LIBS="-lodbc -lodbcinst"])
+  AC_CHECK_LIB(odbcinst,SQLInstallDriverEx,ODBC_SETTING=yes)
+
+  if test "$ODBC_SETTING" = "no" ; then
+    echo "check for windows ODBC"
+    AC_CHECK_LIB(odbc32,main,[ODBC_LIBS="-lodbc32 -lodbccp32"])
+    AC_CHECK_LIB(odbccp32,SQLInstallDriverEx,ODBC_SETTING=yes)
+  fi
+
+  if test "$ODBC_SETTING" = "yes" ; then
+    AC_CHECK_HEADERS(sql.h,,[ODBC_SETTING=no],
+[#ifdef _WIN32
+# include <windows.h>
+#endif
+])
+    if test "$ODBC_SETTING" = "no" ; then
+      if test -f /usr/local/include/sql.h ; then
+        ODBC_SETTING=yes
+        echo "using sql.h from /usr/local/include"
+      elif test -f /usr/include/sql.h ; then
+        ODBC_SETTING=yes
+        echo "using sql.h from /usr/include"
+      else
+        echo "sql.h not found"
+      fi
+    fi
+  fi
+
+  if test "$ODBC_SETTING" = "yes"  ; then
+    LIBS="$ODBC_LIBS $LIBS"
+  fi
+
+else
+
+  ODBC_SETTING=yes
+  ODBC_LIBS=""
+  AC_CHECK_LIB(odbc,SQLConnect,ODBC_LIBS="-lodbc -lodbcinst")
+  AC_CHECK_LIB(odbc32,main,ODBC_LIBS="-lodbc32 -lodbccp32")
+  if test "$ODBC_LIBS" = ""; then
+    AC_MSG_ERROR([Cannot find ODBC libs])
+  fi
+  LIBS="-L$with_odbc -L$with_odbc/lib $ODBC_LIBS $LIBS"
+  EXTRA_INCLUDES="-I$with_odbc -I$with_odbc/include $EXTRA_INCLUDES"
+
+  echo "using odbc library from $with_odbc."
+fi
+
+AC_SUBST(ODBC_SETTING,$ODBC_SETTING)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for OCI support.
+dnl ---------------------------------------------------------------------------
+
+ORACLE_OCI_REQ_VERSION="8.1.7"
+AX_LIB_ORACLE_OCI($ORACLE_OCI_REQ_VERSION)
+
+if test "$HAVE_ORACLE_OCI" = "yes"; then
+    OCI_INCLUDE="$ORACLE_OCI_CFLAGS"
+    LIBS="$ORACLE_OCI_LDFLAGS $LIBS"
+fi
+
+AC_SUBST([HAVE_OCI], [$HAVE_ORACLE_OCI])
+AC_SUBST([OCI_INCLUDE], $[OCI_INCLUDE])
+
+dnl ---------------------------------------------------------------------------
+dnl Check for DODS.
+dnl ---------------------------------------------------------------------------
+
+HAVE_DODS=no
+
+AC_MSG_CHECKING(for DODS)
+AC_ARG_WITH(dods_root,
+    [  --with-dods-root[=ARG]  Include DODS support (ARG=no or absolute path)],
+    ,,)
+
+if test -z "$with_dods_root" -o "$with_dods_root" = "no"; then
+    AC_MSG_RESULT(disabled)
+elif test "$with_dods_root" = "yes" ; then
+    AC_MSG_ERROR([--with-dods-root requires path to dods root as argument])
+else
+    DODS_LIB=$with_dods_root/lib
+    DODS_INC="-I$with_dods_root/include -I$with_dods_root/include/libdap -I$with_dods_root/include/dap"
+    DODS_BIN=$with_dods_root/bin
+
+    dnl Check libdap version the sane way (if possible through dap-config)
+    if test -x $DODS_BIN/dap-config ; then
+        LIBDAP_VER=`${DODS_BIN}/dap-config --version |awk '{print \$2}'`
+        LIBDAP_CFLAGS=`${DODS_BIN}/dap-config --cflags`
+        dnl The dods driver needs LIBDAP_320 and LIBDAP_39 defined to include the right headers
+        DODS_INC="$DODS_INC $LIBDAP_CFLAGS -DLIBDAP_310 -DLIBDAP_39"
+        dnl libs from dap-config gets added further down
+        AC_MSG_RESULT([libdap $LIBDAP_VER])
+    else
+        dnl Check the version by compiling test programs
+
+        dnl Test if we have libdap >= 3.10
+        dnl From libdap 3.10, AISConnect.h has been renamed as Connect.h
+        rm -f islibdappost310.*
+        echo '#include "Connect.h"' > islibdappost310.cpp
+        echo 'int main(int argc, char** argv) { return 0; } ' >> islibdappost310.cpp
+        if test -z "`${CXX} ${CXXFLAGS} islibdappost310.cpp -c ${DODS_INC} ${CPPFLAGS} 2>&1`" ; then
+        dnl yes, libdap >= 3.10
+            DODS_INC="$DODS_INC -DLIBDAP_310 -DLIBDAP_39"
+            AC_MSG_RESULT([libdap >= 3.10])
+        else
+            AC_MSG_RESULT([libdap < 3.10])
+
+            dnl Test if we have libdap < 3.9
+            dnl Before libdap < 3.9, DAS derived from AttrTable class
+            dnl I wish they had defines with version numbers instead of this test !
+            rm -f islibdappre39.*
+            echo '#include "DAS.h"' > islibdappre39.cpp
+            echo '#include "AttrTable.h"' >> islibdappre39.cpp
+            echo 'using namespace libdap;' >> islibdappre39.cpp
+            echo 'int main(int argc, char** argv) { DAS oDAS; AttrTable& oAttrTable = oDAS; } ' >> islibdappre39.cpp
+            if test -z "`${CXX} ${CXXFLAGS} islibdappre39.cpp -c ${DODS_INC} 2>&1`" ; then
+            dnl yes, libdap < 3.9
+                AC_MSG_RESULT([libdap < 3.9])
+            else
+                DODS_INC="$DODS_INC -DLIBDAP_39"
+                AC_MSG_RESULT([libdap >= 3.9])
+            fi
+            rm -f islibdappre39.*
+
+        fi
+        rm -f islibdappost310.*
+    fi
+
+
+    dnl Add the DODS libraries to LIBS
+    if test -x $DODS_BIN/opendap-config ; then
+      dnl OPeNDAP 3.4 and earlier lack opendap-config, but use it if avail.
+      LIBS="$LIBS `$DODS_BIN/opendap-config --libs`"
+    elif test -x $DODS_BIN/dap-config ; then
+      dnl OPeNDAP 3.4 and earlier lack opendap-config, but use it if avail.
+      LIBS="$LIBS `$DODS_BIN/dap-config --libs`"
+    else
+      dnl Otherwise try to put things together in a more primitive way.
+      LIBS="$LIBS -L$DODS_LIB -ldap++ -lpthread -lrx"
+
+      dnl Add curl to LIBS; it might be local to DODS or generally installed
+      if test -x $DODS_BIN/curl-config; then
+          LIBS="$LIBS  `$DODS_BIN/curl-config --libs`"
+      elif which curl-config > /dev/null 2>&1; then
+          LIBS="$LIBS  `curl-config --libs`"
+      else
+          AC_MSG_ERROR([You gave a dods root, but I can't find curl!])
+      fi
+
+      if test -x $DODS_BIN/xml2-config; then
+          LIBS="$LIBS `$DODS_BIN/xml2-config --libs`"
+      elif which xml2-config > /dev/null 2>&1; then
+          LIBS="$LIBS  `xml2-config --libs`"
+      else
+          AC_MSG_ERROR([You gave a dods root, but I can't find xml2!])
+      fi
+    fi
+
+    OPT_GDAL_FORMATS="dods $OPT_GDAL_FORMATS"
+    DODSDEF=-DFRMT_dods
+    AC_MSG_RESULT(setting DODS root directory to $with_dods_root)
+    HAVE_DODS=yes
+fi
+
+dnl This is used by the GNUmakefile in frmts/dods (via GDALmake.opt)
+AC_SUBST(DODS_INC)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for curl (i.e. for wcs).
+dnl ---------------------------------------------------------------------------
+CURL_SETTING=no
+CURL_INC=
+CURL_LIB=
+
+AC_ARG_WITH(curl,
+    [  --with-curl[=ARG]       Include curl (ARG=path to curl-config.)],,,)
+
+dnl Clear some cache variables
+unset ac_cv_path_LIBCURL
+
+if test "`basename xx/$with_curl`" = "curl-config" ; then
+  LIBCURL_CONFIG="$with_curl"
+elif test "$with_curl" = "no" ; then
+  LIBCURL_CONFIG=no
+else
+  AC_PATH_PROG(LIBCURL_CONFIG, curl-config, no)
+fi
+
+if test "$LIBCURL_CONFIG" != "no" ; then
+
+  CURL_VERNUM=`$LIBCURL_CONFIG --vernum`
+  CURL_VER=`$LIBCURL_CONFIG --version | awk '{print $2}'`
+
+  AC_MSG_RESULT([        found libcurl version $CURL_VER])
+
+  AC_CHECK_LIB(curl,curl_global_init,CURL_SETTING=yes,CURL_SETTING=no,`$LIBCURL_CONFIG --libs`)
+
+fi
+
+if test "$CURL_SETTING" = "yes" ; then
+
+  CURL_INC=`$LIBCURL_CONFIG --cflags`
+  CURL_LIB=`$LIBCURL_CONFIG --libs`
+  OPT_GDAL_FORMATS="wcs wms plmosaic wmts $OPT_GDAL_FORMATS"
+
+fi
+
+AC_SUBST(CURL_SETTING,$CURL_SETTING)
+AC_SUBST(CURL_INC,    $CURL_INC)
+AC_SUBST(CURL_LIB,    $CURL_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for libxml2.
+dnl ---------------------------------------------------------------------------
+
+HAVE_LIBXML2=no
+LIBXML2_INC=
+LIBXML2_LIB=
+
+AC_ARG_WITH(xml2,
+    [  --with-xml2[=ARG]       Include libxml2 (ARG=path to xml2-config.)],,,)
+
+if test "`basename xx/$with_xml2`" = "xml2-config" ; then
+  LIBXML2_CONFIG="$with_xml2"
+elif test "$with_xml2" = "no" ; then
+  LIBXML2_CONFIG=no
+else
+  AC_PATH_PROG(LIBXML2_CONFIG, xml2-config, no)
+fi
+
+if test "$LIBXML2_CONFIG" != "no" ; then
+
+  AC_CHECK_LIB(xml2,xmlParseDoc,HAVE_LIBXML2=yes,HAVE_LIBXML2=no,`$LIBXML2_CONFIG --libs`)
+
+fi
+
+if test "$HAVE_LIBXML2" = "yes" ; then
+
+  LIBXML2_INC=`$LIBXML2_CONFIG --cflags`
+  LIBXML2_LIB=`$LIBXML2_CONFIG --libs`
+
+fi
+
+AC_SUBST(HAVE_LIBXML2,$HAVE_LIBXML2)
+AC_SUBST(LIBXML2_INC, $LIBXML2_INC)
+AC_SUBST(LIBXML2_LIB, $LIBXML2_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for SpatiaLite.
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING(for spatialite)
+
+AC_ARG_WITH(spatialite,
+    [  --with-spatialite=ARG Include SpatiaLite support (ARG=no(default), yes, dlopen (only supported for Spatialite >= 4.1.2) or path)],
+    ,,)
+
+AC_ARG_WITH(spatialite-soname,
+    [  --with-spatialite-soname=ARG Spatialite shared object name (e.g. libspatialite.so), only used if --with-spatiliate=dlopen],
+    ,,)
+
+HAVE_SPATIALITE=no
+SPATIALITE_AMALGAMATION=no
+
+if test -z "$with_spatialite" -o "$with_spatialite" = "no"; then
+    AC_MSG_RESULT(disabled)
+elif test "$with_spatialite" = "yes"; then
+    AC_CHECK_HEADERS(sqlite3.h)
+    if test "$ac_cv_header_sqlite3_h" = "yes"; then
+        AC_MSG_CHECKING([for spatialite.h in /usr/include or /usr/local/include])
+        if test -f "/usr/include/spatialite.h" -o -f "/usr/local/include/spatialite.h"; then
+            AC_MSG_RESULT(found)
+            AC_CHECK_LIB(spatialite,spatialite_init,SPATIALITE_INIT_FOUND=yes,SPATIALITE_INIT_FOUND=no,)
+            if test "$SPATIALITE_INIT_FOUND" = "yes"; then
+                HAVE_SPATIALITE=yes
+                SPATIALITE_LIBS="-lspatialite -lsqlite3"
+                LIBS="$LIBS $SPATIALITE_LIBS"
+                HAVE_SQLITE3=yes
+            fi
+        else
+            AC_MSG_RESULT(not found : spatialite support disabled)
+        fi
+    fi
+elif test "$with_spatialite" = "dlopen"; then
+  HAVE_SPATIALITE=dlopen
+  AC_MSG_RESULT(dlopen)
+
+  if test "$with_spatialite_soname" != ""; then
+      SPATIALITE_SONAME="$with_spatialite_soname"
+  else
+      SPATIALITE_SONAME="spatialite.so"
+  fi
+else
+    AC_CHECK_LIB(spatialite,spatialite_init,SPATIALITE_INIT_FOUND=yes,SPATIALITE_INIT_FOUND=no,-L$with_spatialite/lib -lspatialite)
+    if test -f "$with_spatialite/include/spatialite.h" -a \
+        -f "$with_spatialite/include/spatialite/sqlite3.h" -a \
+        "$SPATIALITE_INIT_FOUND" = "yes"; then
+
+        AC_MSG_RESULT(enabled)
+        HAVE_SPATIALITE=yes
+        SPATIALITE_AMALGAMATION=yes
+
+        # SpatiaLite amalgamation availability implies SQLite availability
+        # Caution : don't include the include/spatialite subdir in the include dir
+        # as there's a spatialite.h file in it, which we don't want to include.
+        # We want to include include/spatialite.h instead !
+        SQLITE3_CFLAGS="-I$with_spatialite/include"
+        SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
+        LIBS="$LIBS $SPATIALITE_LIBS"
+        HAVE_SQLITE3=yes
+
+    elif test -f "$with_spatialite/include/spatialite.h" -a \
+        "$SPATIALITE_INIT_FOUND" = "yes"; then
+
+        SQLITE3_REQ_VERSION="3.0.0"
+        AX_LIB_SQLITE3($SQLITE3_REQ_VERSION)
+
+        if test "$HAVE_SQLITE3" = "yes"; then
+            SPATIALITE_INC="-I$with_spatialite/include"
+            HAVE_SPATIALITE=yes
+            SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
+            LIBS="$SQLITE3_LDFLAGS $LIBS $SPATIALITE_LIBS"
+            AC_MSG_RESULT(spatialite enabled)
+        else
+            AC_MSG_RESULT(spatialite disabled)
+        fi
+    else
+        AC_MSG_RESULT(disabled)
+    fi
+fi
+
+if test "$HAVE_SPATIALITE" = "yes"; then
+    ax_save_LIBS="${LIBS}"
+    LIBS="$SPATIALITE_LIBS"
+    AC_CHECK_LIB(spatialite,spatialite_target_cpu,SPATIALITE_412_OR_LATER=yes,SPATIALITE_412_OR_LATER=no)
+    LIBS="${ax_save_LIBS}"
+fi
+
+AC_SUBST([HAVE_SPATIALITE], $HAVE_SPATIALITE)
+AC_SUBST([SPATIALITE_SONAME], $SPATIALITE_SONAME)
+AC_SUBST([SPATIALITE_INC], $SPATIALITE_INC)
+AC_SUBST([SPATIALITE_AMALGAMATION], $SPATIALITE_AMALGAMATION)
+AC_SUBST([SPATIALITE_412_OR_LATER], $SPATIALITE_412_OR_LATER)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for SQLite (only if SpatiaLite is not detected)
+dnl ---------------------------------------------------------------------------
+
+if test "${HAVE_SPATIALITE}" = "no" -o "${HAVE_SPATIALITE}" = "dlopen" ; then
+    SQLITE3_REQ_VERSION="3.0.0"
+    AX_LIB_SQLITE3($SQLITE3_REQ_VERSION)
+
+    if test "$HAVE_SQLITE3" = "yes"; then
+        LIBS="$SQLITE3_LDFLAGS $LIBS"
+    fi
+fi
+
+if test "$HAVE_SQLITE3" = "yes"; then
+    AC_CHECK_LIB(sqlite3,sqlite3_column_table_name,SQLITE_HAS_COLUMN_METADATA=yes,SQLITE_HAS_COLUMN_METADATA=no,$LIBS)
+fi
+
+AC_SUBST([SQLITE_INC], $SQLITE3_CFLAGS)
+AC_SUBST([HAVE_SQLITE], $HAVE_SQLITE3)
+AC_SUBST([SQLITE_HAS_COLUMN_METADATA], $SQLITE_HAS_COLUMN_METADATA)
+HAVE_SQLITE=$HAVE_SQLITE3
+
+dnl ---------------------------------------------------------------------------
+dnl Check for librasterlite2.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(rasterlite2,
+    [  --with-rasterlite2=ARG Include RasterLite2 support (ARG=no(default), yes or path)],
+    ,,)
+
+HAVE_RASTERLITE2=no
+RASTERLITE2_CFLAGS=
+
+if test -z "$with_rasterlite2" -o "$with_rasterlite2" = "no"; then
+    AC_MSG_NOTICE([rasterlite2 support disabled])
+elif test "$with_rasterlite2" = "yes"; then
+    AC_CHECK_HEADERS(rasterlite2/rasterlite2.h)
+    if test "$ac_cv_header_rasterlite2_rasterlite2_h" = "yes"; then
+        AC_CHECK_LIB(rasterlite2,rl2_load_raw_tiles_into_dbms,HAVE_RASTERLITE2=yes,HAVE_RASTERLITE2=no,)
+        if test "$HAVE_RASTERLITE2" = "yes"; then
+            LIBS="$LIBS -lrasterlite2 -lsqlite3"
+        else
+            AC_MSG_ERROR([did not find rl2_load_raw_tiles_into_dbms])
+        fi
+    else
+        AC_MSG_ERROR([did not find rasterlite2.h])
+    fi
+else
+    AC_MSG_CHECKING([for include/rasterlite2/rasterlite2.h])
+    if test -f "$with_rasterlite2/include/rasterlite2/rasterlite2.h"; then
+        AC_MSG_RESULT([found])
+        AC_CHECK_LIB(rasterlite2,rl2_load_raw_tiles_into_dbms,HAVE_RASTERLITE2=yes,HAVE_RASTERLITE2=no,-L$with_rasterlite2/lib)
+        if test "$HAVE_RASTERLITE2" = "yes"; then
+            RASTERLITE2_CFLAGS="-I$with_rasterlite2/include"
+            LIBS="$LIBS -L$with_rasterlite2/lib -lrasterlite2 -lsqlite3"
+        else
+            AC_MSG_ERROR([did not find rl2_load_raw_tiles_into_dbms])
+        fi
+    else
+        AC_MSG_ERROR([did not find rasterlite2.h])
+    fi
+fi
+
+AC_SUBST([HAVE_RASTERLITE2], $HAVE_RASTERLITE2)
+AC_SUBST([RASTERLITE2_CFLAGS], $RASTERLITE2_CFLAGS)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for PCRE.
+dnl ---------------------------------------------------------------------------
+
+HAVE_PCRE=no
+
+AC_ARG_WITH(pcre,
+    [  --with-pcre             Include libpcre support (REGEXP support for SQLite)],
+    ,,)
+
+if test "$with_pcre" = "no"; then
+    AC_MSG_RESULT(disabled)
+    HAVE_PCRE=no
+else
+    AC_CHECK_HEADERS([pcre.h])
+    if test "$ac_cv_header_pcre_h" = "no" ; then
+        if test "$with_pcre" = "yes"; then
+            AC_MSG_ERROR([cannot find pcre.h])
+        fi
+    else
+        AC_CHECK_LIB(pcre,pcre_compile,HAVE_PCRE=yes,HAVE_PCRE=no,)
+        if test "$HAVE_PCRE" = "yes" ; then
+            HAVE_PCRE=yes
+            LIBS="$LIBS -lpcre"
+        else
+            if test "$with_pcre" = "yes"; then
+                AC_MSG_ERROR([cannot find libpcre])
+            fi
+        fi
+    fi
+fi
+
+AC_SUBST(HAVE_PCRE)
+
+dnl ---------------------------------------------------------------------------
+dnl Check for Teigha.
+dnl ---------------------------------------------------------------------------
+
+TEIGHA_DIR=
+
+AC_MSG_CHECKING(Checking for Teigha)
+AC_ARG_WITH(teigha,
+    [  --with-teigha[=path] Include Teigha DWG/DGN support],
+    ,,)
+
+if test -z "$with_teigha" -o "$with_teigha" = "no"; then
+    AC_MSG_RESULT(disabled)
+    HAVE_TEIGHA=no
+else
+    AC_MSG_RESULT(enabled)
+
+    AC_ARG_WITH(teigha-plt,
+      [  --with-teigha-plt[=platform] Teigha platform],
+      ,,)
+    if test "x$with_teigha_plt" != "x" ; then
+        TEIGHA_DIR=$with_teigha
+        HAVE_TEIGHA=yes
+        TEIGHA_PLT=$with_teigha_plt
+        LIBS="${LIBS} ${TEIGHA_DIR}/bin/${TEIGHA_PLT}/TG_Db.tx"
+        LIBS="${LIBS} ${TEIGHA_DIR}/lib/${TEIGHA_PLT}/libTG_ExamplesCommon.a"
+        LIBS="${LIBS} ${TEIGHA_DIR}/lib/${TEIGHA_PLT}/libTD_ExamplesCommon.a"
+        LIBS="${LIBS} ${TEIGHA_DIR}/lib/${TEIGHA_PLT}/libTD_Key.a"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_Db"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_DbRoot"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_Root"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_Ge"
+        LIBS="${LIBS} -L${TEIGHA_DIR}/bin/${TEIGHA_PLT} -lTD_Alloc"
+    else
+        AC_MSG_ERROR([--with-teigha-plt not specified])
+    fi
+fi
+
+AC_SUBST(TEIGHA_DIR)
+AC_SUBST(HAVE_TEIGHA)
+
+dnl ---------------------------------------------------------------------------
+dnl Select Informix DataBlade support
+dnl ---------------------------------------------------------------------------
+
+HAVE_IDB=no
+
+AC_ARG_WITH(idb,[  --with-idb=DIR        Include Informix DataBlade support (DIR points to Informix root)],,)
+
+if test x"${with_idb}" = x"no" ; then
+  AC_MSG_NOTICE(["IBM Informix DataBlade support disabled."])
+else
+  if test x"${with_idb}" = x ; then
+    with_idb=$INFORMIXDIR
+  fi
+
+  if test -e "${with_idb}/incl/c++/it.h" ; then
+
+    LIBS_DIRS="-L${with_idb}/lib/ -L${with_idb}/lib/esql"
+    LIBS_ESQL="-lifsql -lifasf -lifgen -lifos -lifgls -lifglx ${with_idb}/lib/esql/checkapi.o"
+    LIBS_LIBMI="-L${with_idb}/lib/dmi -lifdmi"
+    LIBS_CPPIF="-L${with_idb}/lib/c++ -lifc++"
+
+    IDB_INC="-I${with_idb}/incl/ -I${with_idb}/incl/dmi -I${with_idb}/incl/c++"
+    IDB_LIB="${LIBS_DIRS} ${LIBS_ESQL} ${LIBS_LIBMI} ${LIBS_CPPIF}"
+
+    ax_save_LIBS="${LIBS}"
+    LIBS="${IDB_LIB} -ldl -lcrypt"
+    AC_CHECK_LIB(ifsql,ifx_srvinfo,HAVE_IDB=yes,HAVE_IDB=no,)
+    LIBS="${ax_save_LIBS}"
+
+  fi
+
+  if test "${HAVE_IDB}" = "yes" ; then
+    AC_MSG_NOTICE([using Informix C++ client library from $with_idb.])
+  else
+    AC_MSG_NOTICE([IBM Informix DataBlade not supported.])
+  fi
+
+fi
+
+AC_SUBST(HAVE_IDB,${HAVE_IDB})
+AC_SUBST(IDB_INC,${IDB_INC})
+AC_SUBST(IDB_LIB,${IDB_LIB})
+
+dnl ---------------------------------------------------------------------
+dnl Find ESRI SDE ONLY IF REQUESTED.
+dnl ---------------------------------------------------------------------
+
+SDE_ENABLED=no
+
+AC_CHECKING(whether we should include ESRI SDE support)
+AC_ARG_WITH(sde,
+[  --with-sde[=DIR]        Include ESRI SDE support (DIR is SDE's install dir).],,)
+
+AC_ARG_WITH(sde-version,
+[  --with-sde-version[=VERSION NUMBER]  Set ESRI SDE version number (Default is 80).],SDE_VERSION=$with_sde_version,SDE_VERSION=80)
+
+if test -z "$SDE_VERSION" -o `expr "$SDE_VERSION" \>\= 92` = 1; then
+SDE_VERSION=""
+fi
+if test "$with_sde" = "yes" ; then
+
+  AC_CHECK_LIB(sde$SDE_VERSION,SE_connection_create,SDE_ENABLED=yes,,,)
+
+  if test -n "$SDE_ENABLED" ; then
+      SDE_LIB="-lsde$SDE_VERSION -lpe$SDE_VERSION -lsg$SDE_VERSION"
+      AC_CHECK_LIB(pthread, main, SDE_LIB="$SDE_LIB -lpthread",,)
+      AC_CHECK_LIB(socket, main, SDE_LIB="$SDE_LIB -lsocket",,)
+      AC_CHECK_LIB(dl, main, SDE_LIB="$SDE_LIB -ldl",,)
+      AC_MSG_RESULT([        using ESRI SDE from system libs.])
+  else
+      AC_MSG_WARN([        ESRI SDE not found in system libs... use --with-sde=DIR.])
+  fi
+
+elif test -n "$with_sde" -a "$with_sde" != "no" ; then
+
+  SDE_DIR=$with_sde
+
+  test -f $SDE_DIR/arcsde/coverages/include/sdetype.h && SDE_INCDIR="$SDE_DIR/arcsde/coverages/include"
+  test -f $SDE_DIR/include/sdetype.h && SDE_INCDIR="$SDE_DIR/include"
+  test -f $SDE_DIR/sdetype.h && SDE_INCDIR="$SDE_DIR"
+
+  test -f $SDE_DIR/lib/libsde$SDE_VERSION.a && SDE_LIBDIR="$SDE_DIR/lib"
+  test -f $SDE_DIR/lib64/libsde$SDE_VERSION.a && SDE_LIBDIR="$SDE_DIR/lib64"
+  test -f $SDE_DIR/libsde$SDE_VERSION.a && SDE_LIBDIR="$SDE_DIR"
+
+  test -f $SDE_DIR/lib/libsde$SDE_VERSION.so -o -f $SDE_DIR/lib/libsde$SDE_VERSION.sl && SDE_LIBDIR="$SDE_DIR/lib"
+  test -f $SDE_DIR/lib64/libsde$SDE_VERSION.so -o -f $SDE_DIR/lib64/libsde$SDE_VERSION.sl && SDE_LIBDIR="$SDE_DIR/lib64"
+  test -f $SDE_DIR/libsde$SDE_VERSION.so -o -f $SDE_DIR/libsde$SDE_VERSION.sl && SDE_LIBDIR="$SDE_DIR"
+
+  if test -n "$SDE_INCDIR" -a -n "$SDE_LIBDIR" ; then
+      SDE_INC=-I$SDE_INCDIR
+      SDE_LIB="-L$SDE_LIBDIR -lsde$SDE_VERSION -lpe$SDE_VERSION -lsg$SDE_VERSION"
+      AC_CHECK_LIB(pthread, main, SDE_LIB="$SDE_LIB -lpthread",,)
+      AC_CHECK_LIB(socket, main, SDE_LIB="$SDE_LIB -lsocket",,)
+      AC_CHECK_LIB(dl, main, SDE_LIB="$SDE_LIB -ldl",,)
+  else
+      AC_MSG_ERROR("Could not find sdetype.h or libsde$SDE_VERSION.a/libsde$SDE_VERSION.so in $SDE_DIR.")
+  fi
+
+  if test "`arch`" = "x86_64" ; then
+    AC_MSG_RESULT([        Adding -DSDE64 for 64bit platform.])
+    SDE_INC="$SDE_INC -DSDE64"
+  fi
+
+  SDE_ENABLED=yes
+  OPT_GDAL_FORMATS="sde $OPT_GDAL_FORMATS"
+  AC_MSG_RESULT([        using ESRI SDE from $SDE_DIR.])
+
+else
+
+  AC_MSG_RESULT([        ESRI SDE support not requested.])
+fi
+
+AC_SUBST(SDE_ENABLED,$SDE_ENABLED)
+AC_SUBST(SDE_INC,    $SDE_INC)
+AC_SUBST(SDE_LIB,    $SDE_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if epsilon library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(epsilon,[  --with-epsilon[=ARG]    Include EPSILON support (ARG=no, yes or libepsilon install root path)],,)
+
+EPSILON_SETTING=no
+
+if test "$with_epsilon" = "yes" ; then
+
+  AC_CHECK_LIB(epsilon,eps_read_block_header,EPSILON_SETTING=yes,EPSILON_SETTING=no,)
+
+  if test "$EPSILON_SETTING" = "yes" ; then
+    LIBS="-lepsilon $LIBS"
+  else
+    echo "libepsilon not found - EPSILON support disabled"
+  fi
+
+elif test "$with_epsilon" != "no" -a "$with_epsilon" != ""; then
+
+  AC_CHECK_LIB(epsilon,eps_read_block_header,EPSILON_SETTING=yes,EPSILON_SETTING=no,-L$with_epsilon/lib -lepsilon)
+
+  if test "$EPSILON_SETTING" = "yes" ; then
+    LIBS="-L$with_epsilon/lib -lepsilon $LIBS"
+    EXTRA_INCLUDES="-I$with_epsilon/include $EXTRA_INCLUDES"
+  else
+    echo "libepsilon not found - EPSILON support disabled"
+  fi
+
+fi
+
+if test "$EPSILON_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="epsilon $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if webp library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(webp,[  --with-webp[=ARG]    Include WEBP support (ARG=no, yes or libwebp install root path)],,)
+
+WEBP_SETTING=no
+
+if test "$with_webp" = "yes" -o "$with_webp" = "" ; then
+
+  AC_CHECK_LIB(webp,WebPDecodeRGB,WEBP_SETTING=yes,WEBP_SETTING=no,)
+
+  if test "$WEBP_SETTING" = "yes" ; then
+    LIBS="-lwebp $LIBS"
+  else
+    echo "libwebp not found - WEBP support disabled"
+  fi
+
+elif test "$with_webp" != "no" -a "$with_webp" != ""; then
+
+  AC_CHECK_LIB(webp,WebPDecodeRGB,WEBP_SETTING=yes,WEBP_SETTING=no,-L$with_webp/lib -lwebp)
+
+  if test "$WEBP_SETTING" = "yes" ; then
+    LIBS="-L$with_webp/lib -lwebp $LIBS"
+    EXTRA_INCLUDES="-I$with_webp/include $EXTRA_INCLUDES"
+  else
+    echo "libwebp not found - WEBP support disabled"
+  fi
+
+fi
+
+if test "$WEBP_SETTING" != "no" ; then
+  OPT_GDAL_FORMATS="webp $OPT_GDAL_FORMATS"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if geos library is available.
+dnl ---------------------------------------------------------------------------
+
+GEOS_INIT(3.1.0)
+HAVE_GEOS_RESULT="no"
+if test "${HAVE_GEOS}" = "yes" ; then
+
+  AC_MSG_NOTICE([Using C API from GEOS $GEOS_VERSION])
+  LIBS="${GEOS_LIBS} ${LIBS}"
+  HAVE_GEOS_RESULT="yes"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if SFCGAL library is available.
+dnl ---------------------------------------------------------------------------
+
+SFCGAL_INIT(1.2.2)
+HAVE_SFCGAL_RESULT="no"
+if test "${HAVE_SFCGAL}" = "yes" ; then
+
+  AC_MSG_NOTICE([Using C API from SFCGAL $SFCGAL_VERSION])
+  LIBS="${SFCGAL_LIBS} ${LIBS}"
+  HAVE_SFCGAL_RESULT="yes"
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Check if QHull library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(qhull,[  --with-qhull[=ARG]     Include QHull support (ARG=no, yes, internal)],,)
+
+QHULL_SETTING=no
+
+if test "$with_qhull" = "no" ; then
+
+  AC_MSG_NOTICE([QHull support disabled.])
+
+elif test "$with_qhull" = "yes" -o "$with_qhull" = "" ; then
+
+  # Only qhull 2012 is reliable on certain datasets. Older Ubuntu have
+  # qhull/qhull.h
+  AC_CHECK_HEADERS([qhull/libqhull.h])
+  if test "$ac_cv_header_qhull_libqhull_h" = "yes"; then
+    AC_CHECK_LIB(qhull,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
+    if test "$QHULL_SETTING" = "yes"; then
+        QHULL_SETTING=external
+        QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=0
+        LIBS="-lqhull $LIBS"
+    fi
+  fi
+  AC_CHECK_HEADERS([libqhull/libqhull.h])
+  if test "$ac_cv_header_libqhull_libqhull_h" = "yes"; then
+    AC_CHECK_LIB(qhull,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
+    if test "$QHULL_SETTING" = "yes"; then
+        QHULL_SETTING=external
+        QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=1
+        LIBS="-lqhull $LIBS"
+    fi
+  fi
+
+  if test "$QHULL_SETTING" = "no" ; then
+    if test "$with_qhull" = "yes"; then
+        AC_MSG_ERROR([--with-qhull requested, but library not found!])
+    else
+        QHULL_SETTING=internal
+        QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=1
+    fi
+  fi
+else
+  QHULL_SETTING=internal
+  QHULL_INCLUDE_SUBDIR_IS_LIBQHULL=1
+fi
+
+AC_SUBST([QHULL_SETTING],$QHULL_SETTING)
+AC_SUBST([QHULL_INCLUDE_SUBDIR_IS_LIBQHULL],$QHULL_INCLUDE_SUBDIR_IS_LIBQHULL)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if opencl library is available.
+dnl ---------------------------------------------------------------------------
+
+OPENCL_SETTING=no
+OPENCL_FLAGS=
+OPENCL_LIB=
+
+AC_ARG_WITH(opencl,
+    [  --with-opencl[=ARG]       Include OpenCL (GPU) support],,,)
+
+AC_MSG_CHECKING([for OpenCL support])
+
+if test "$with_opencl" = "yes" ; then
+
+  AC_ARG_WITH(opencl-include,
+      [  --with-opencl-include=ARG OpenCL Include directory (with a CL subdirectory)],,,)
+
+  OPENCL_SETTING=yes
+
+  if test "x$with_opencl_include" = "x" ; then
+    OPENCL_FLAGS=-DHAVE_OPENCL
+    if test -z "`uname | grep Darwin`" ; then
+        AC_CHECK_HEADERS([CL/opencl.h])
+        if test "$ac_cv_header_CL_opencl_h" = "no" ; then
+            AC_MSG_ERROR([cannot find CL/opencl.h])
+        fi
+    fi
+  else
+    OPENCL_FLAGS="-I$with_opencl_include -DHAVE_OPENCL"
+  fi
+
+  AC_ARG_WITH(opencl-lib,
+      [  --with-opencl-lib=ARG   OpenCL Link Flags (i.e. -L/xxx -lOpenCL)],,,)
+
+  if test "x$with_opencl_lib" = "x" ; then
+    if test ! -z "`uname | grep Darwin`" ; then
+      OPENCL_LIB="-framework OpenCL"
+    else
+      AC_CHECK_LIB(OpenCL,clGetPlatformIDs,OPENCL_LIB=-lOpenCL,OPENCL_LIB=missing)
+      if test "$OPENCL_LIB" = "missing"; then
+        AC_MSG_ERROR([--with-opencl requested, but libraries not found!])
+      fi
+    fi
+  else
+    OPENCL_LIB="$with_opencl_lib"
+  fi
+
+fi
+
+AC_MSG_RESULT([$OPENCL_SETTING])
+
+AC_SUBST(OPENCL_FLAGS,  $OPENCL_FLAGS)
+AC_SUBST(OPENCL_LIB,    $OPENCL_LIB)
+
+
+dnl ---------------------------------------------------------------------------
+dnl Check if FreeXL library is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(freexl,[  --with-freexl[=ARG]    Include freexl support (ARG=no, yes (default) or libfreexl install path)],,)
+
+AC_MSG_CHECKING([for FreeXL support])
+
+HAVE_FREEXL=no
+FREEXL_INCLUDE=
+
+if test "$with_freexl" = "" -o "$with_freexl" = "yes" ; then
+  AC_CHECK_HEADERS(freexl.h)
+  AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl",FREEXL_LIBS=missing)
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -lm",FREEXL_LIBS=missing,-lm)
+  fi
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -liconv",FREEXL_LIBS=missing,-liconv)
+  fi
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -liconv -lm",FREEXL_LIBS=missing,-liconv -lm)
+  fi
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -liconv -lcharset",FREEXL_LIBS=missing,-liconv -lcharset)
+  fi
+
+  if test "$FREEXL_LIBS" != "missing" -a "$ac_cv_header_freexl_h" = "yes" ; then
+
+    # Check that freexl is recent enough
+    rm -f testrlist.*
+    echo '#include <freexl.h>' > testfreexl.c
+    echo 'int main(int argc, char** argv) { FreeXL_CellValue s; freexl_get_cell_value (0,0,0,&s); return 0; } ' >> testfreexl.c
+    if test -z "`${CC} ${CFLAGS} testfreexl.c -c 2>&1`" ; then
+        HAVE_FREEXL=yes
+        LIBS="$FREEXL_LIBS $LIBS"
+    else
+        HAVE_FREEXL=no
+        AC_MSG_RESULT([freexl too old. Needs freexl >= 1.0])
+    fi
+    rm -f testfreexl.*
+
+  else
+    HAVE_FREEXL=no
+    echo "libfreexl not found - FreeXL support disabled"
+  fi
+
+elif test "$with_freexl" != "no"; then
+
+  AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl",FREEXL_LIBS=missing,-L$with_freexl/lib)
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -lm",FREEXL_LIBS=missing,-L$with_freexl/lib -lm)
+  fi
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv",FREEXL_LIBS=missing,-L$with_freexl/lib -liconv)
+  fi
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv -lm",FREEXL_LIBS=missing,-L$with_freexl/lib -liconv -lm)
+  fi
+
+  if test "$FREEXL_LIBS" = "missing"; then
+    unset ac_cv_lib_freexl_freexl_open
+    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv -lcharset",FREEXL_LIBS=missing,-L$with_freexl/lib -liconv -lcharset)
+  fi
+
+  if test "$FREEXL_LIBS" != "missing" -a -f "$with_freexl/include/freexl.h" ; then
+
+    # Check that freexl is recent enough
+    rm -f testrlist.*
+    echo '#include <freexl.h>' > testfreexl.c
+    echo 'int main(int argc, char** argv) { FreeXL_CellValue s; freexl_get_cell_value (0,0,0,&s); return 0; } ' >> testfreexl.c
+    if test -z "`${CC} ${CFLAGS} -I$with_freexl/include testfreexl.c -c 2>&1`" ; then
+        HAVE_FREEXL=yes
+        LIBS="$FREEXL_LIBS $LIBS"
+        FREEXL_INCLUDE="-I$with_freexl/include"
+    else
+        HAVE_FREEXL=no
+        AC_MSG_RESULT([freexl too old. Needs freexl >= 1.0])
+    fi
+    rm -f testfreexl.*
+
+  else
+    HAVE_FREEXL=no
+    echo "libfreexl not found - FreeXL support disabled"
+  fi
+
+fi
+
+AC_SUBST(HAVE_FREEXL,  $HAVE_FREEXL)
+AC_SUBST(FREEXL_INCLUDE,  $FREEXL_INCLUDE)
+
+
+dnl ---------------------------------------------------------------------------
+dnl Check if libjson-c is available.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(libjson-c,[  --with-libjson-c[=ARG]       Include libjson-c support (ARG=internal or libjson-c directory)],,)
+
+if test "$with_libjson_c" = "external" -o "$with_libjson_c" = "" -o "$with_libjson_c" = "yes" ; then
+  AC_CHECK_LIB(json-c,json_object_set_serializer,LIBJSONC_SETTING=external,LIBJSONC_SETTING=internal,)
+elif test "$with_libjson_c" = "internal" ; then
+  LIBJSONC_SETTING=internal
+elif test "$with_libjson_c" != "no"; then
+  LIBS="-L$with_libjson_c/lib $LIBS"
+  AC_CHECK_LIB(json-c,json_object_set_serializer,LIBJSONC_SETTING=external,LIBJSONC_SETTING=internal,-L$with_libjson_c/lib)
+else
+  AC_MSG_ERROR([libjson-c (internal or external) is required])
+fi
+
+if test "$LIBJSONC_SETTING" = "external" ; then
+  AC_MSG_RESULT([using pre-installed libjson-c])
+  LIBS="-ljson-c $LIBS"
+  if test "$with_libjson_c" != "" -a "$with_libjson_c" != "yes" -a "$with_libjson_c" != "external" ; then
+    JSON_INCLUDE="-I$with_libjson_c/include/json-c"
+  elif test -f "/usr/include/json-c/json.h"; then
+    JSON_INCLUDE="-I/usr/include/json-c"
+  elif test -f "/usr/local/include/json-c/json.h"; then
+    JSON_INCLUDE="-I/usr/local/include/json-c"
+  else
+    AC_MSG_ERROR([could not find json-c/json.h])
+  fi
+else
+    JSON_INCLUDE="-I\$(GDAL_ROOT)/ogr/ogrsf_frmts/geojson/libjson"
+    AC_MSG_RESULT([using internal libjson-c code])
+fi
+
+AC_SUBST(LIBJSONC_SETTING,$LIBJSONC_SETTING)
+AC_SUBST(JSON_INCLUDE,$JSON_INCLUDE)
+
+
+dnl ---------------------------------------------------------------------------
+dnl Check if we must enable PAM
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([whether to enable PAM])
+
+AC_ARG_WITH(pam,[  --without-pam         Disable PAM (.aux.xml) support],,)
+
+export PAM_SETTING=
+
+if test "x$with_pam" = "xno" ; then
+  AC_MSG_RESULT([no])
+else
+  AC_MSG_RESULT([yes])
+  PAM_SETTING=-DPAM_ENABLED
+fi
+
+AC_SUBST(PAM_SETTING, $PAM_SETTING)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if the PDF driver should be built as a plugin
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([whether to build PDF driver as a plugin])
+
+AC_ARG_ENABLE(pdf_plugin,
+              AS_HELP_STRING([--enable-pdf-plugin],
+                             [enable PDF driver as a plugin (included in libgdal by default)]),,)
+
+PDF_PLUGIN=no
+if test "x$enable_pdf_plugin" = "xyes" ; then
+
+  PDF_PLUGIN=yes
+
+  AC_MSG_RESULT([yes])
+else
+  AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(PDF_PLUGIN, $PDF_PLUGIN)
+
+
+dnl ---------------------------------------------------------------------------
+dnl Check if libpoppler is available
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(poppler,[  --with-poppler[=ARG]    Include poppler(for PDF) support (ARG=no(default), yes or poppler install path)],,)
+
+HAVE_POPPLER=no
+POPPLER_HAS_OPTCONTENT=no
+POPPLER_BASE_STREAM_HAS_TWO_ARGS=no
+POPPLER_0_20_OR_LATER=no
+
+AC_MSG_CHECKING([for poppler])
+
+if test "$with_poppler" != "no" -a "$with_poppler" != ""; then
+
+    if test "$with_poppler" = "yes" ; then
+        TEST_POPPLER_INC="-I/usr/include -I/usr/include/poppler"
+        TEST_POPPLER_LIB="-lpoppler"
+    else
+        TEST_POPPLER_INC="-I$with_poppler/include -I$with_poppler/include/poppler"
+        TEST_POPPLER_LIB="-L$with_poppler/lib -lpoppler"
+    fi
+
+    # Check that we can accept Page::pageObj private member
+    rm -f testpoppler.*
+    echo '#define private public' > testpoppler.cpp
+    echo '#include <poppler/Page.h>' >> testpoppler.cpp
+    echo '#include <poppler/splash/SplashBitmap.h>' >> testpoppler.cpp
+    echo 'int main(int argc, char** argv) { return &(((Page*)0x8000)->pageObj) == 0; } ' >> testpoppler.cpp
+
+    if test -z "`${CXX} testpoppler.cpp -o testpoppler ${TEST_POPPLER_INC} ${TEST_POPPLER_LIB} 2>&1`" ; then
+        HAVE_POPPLER=yes
+    else
+        # poppler 0.23.0 needs to be linked against pthread
+        TEST_POPPLER_LIB="${TEST_POPPLER_LIB} -lpthread"
+        if test -z "`${CXX} testpoppler.cpp -o testpoppler ${TEST_POPPLER_INC} ${TEST_POPPLER_LIB} 2>&1`" ; then
+            HAVE_POPPLER=yes
+        fi
+    fi
+
+    if test "$HAVE_POPPLER" = "yes"; then
+        if test "$PDF_PLUGIN" = "no"; then
+            LIBS="${TEST_POPPLER_LIB} ${LIBS}"
+        fi
+        AC_MSG_RESULT([yes])
+        POPPLER_INC=$TEST_POPPLER_INC
+        POPPLER_PLUGIN_LIB="${TEST_POPPLER_LIB}"
+
+        # And now try another dirty thing, but this one is
+        # optional.
+        AC_MSG_CHECKING([if Catalog::optContent exists])
+        rm -f testpoppler.*
+        echo '#define private public' > testpoppler.cpp
+        echo '#include <poppler/Object.h>' >> testpoppler.cpp
+        echo '#include <poppler/Catalog.h>' >> testpoppler.cpp
+        echo 'int main(int argc, char** argv) { return &(((Catalog*)0x8000)->optContent) == 0; }' >> testpoppler.cpp
+        if test -z "`${CXX} testpoppler.cpp -c ${POPPLER_INC} 2>&1`" ; then
+            POPPLER_HAS_OPTCONTENT=yes
+            AC_MSG_RESULT([yes])
+        else
+            AC_MSG_RESULT([no])
+        fi
+
+        # And now we check if we have Poppler >= 0.16.0
+        AC_MSG_CHECKING([if BaseStream constructor needs 2 arguments])
+        rm -f testpoppler.*
+        echo '#include <poppler/Object.h>' > testpoppler.cpp
+        echo '#include <poppler/Stream.h>' >> testpoppler.cpp
+        echo 'class TestStream: public BaseStream {' >> testpoppler.cpp
+        echo 'public:' >> testpoppler.cpp
+        echo '  TestStream() : BaseStream(0,0) {}' >> testpoppler.cpp
+        echo '};' >> testpoppler.cpp
+        echo 'int main(int argc, char** argv) { return 0; }' >> testpoppler.cpp
+        if test -z "`${CXX} testpoppler.cpp -c ${POPPLER_INC} 2>&1`" ; then
+            POPPLER_BASE_STREAM_HAS_TWO_ARGS=yes
+            AC_MSG_RESULT([yes])
+
+            # And now we check if we have Poppler >= 0.20.0
+            AC_MSG_CHECKING([if we have Poppler >= 0.20.0])
+            rm -f testpoppler.*
+            echo '#include <poppler/Error.h>' > testpoppler.cpp
+            echo 'int main(int argc, char** argv) { setErrorCallback(0,0); return 0; }' >> testpoppler.cpp
+            if test -z "`${CXX} testpoppler.cpp -c ${POPPLER_INC} 2>&1`" ; then
+                POPPLER_0_20_OR_LATER=yes
+                AC_MSG_RESULT([yes])
+
+                # And now we check if we have Poppler >= 0.23.0
+                AC_MSG_CHECKING([if we have Poppler >= 0.23.0])
+                rm -f testpoppler.*
+                echo '#include <poppler/Object.h>' > testpoppler.cpp
+                echo '#include <poppler/Stream.h>' >> testpoppler.cpp
+                echo 'class TestStream: public BaseStream {' >> testpoppler.cpp
+                echo 'public:' >> testpoppler.cpp
+                echo '  TestStream() : BaseStream(0,0) {}' >> testpoppler.cpp
+                echo '  ~TestStream() {}' >> testpoppler.cpp
+                echo '  virtual BaseStream *copy() { return BaseStream::copy(); }' >> testpoppler.cpp
+                echo '};' >> testpoppler.cpp
+                echo 'int main(int argc, char** argv) { return 0; }' >> testpoppler.cpp
+                if test -z "`${CXX} testpoppler.cpp -c ${POPPLER_INC} 2>&1`" ; then
+                    POPPLER_0_23_OR_LATER=yes
+                    AC_MSG_RESULT([yes])
+                else
+                    AC_MSG_RESULT([no])
+                fi
+
+            else
+                AC_MSG_RESULT([no])
+            fi
+
+        else
+            AC_MSG_RESULT([no])
+        fi
+    else
+        AC_MSG_RESULT([no])
+    fi
+    rm -f testpoppler.*
+    rm -f testpoppler
+else
+    AC_MSG_RESULT([disabled])
+fi
+
+AC_SUBST(HAVE_POPPLER, $HAVE_POPPLER)
+AC_SUBST(POPPLER_HAS_OPTCONTENT, $POPPLER_HAS_OPTCONTENT)
+AC_SUBST(POPPLER_BASE_STREAM_HAS_TWO_ARGS, $POPPLER_BASE_STREAM_HAS_TWO_ARGS)
+AC_SUBST(POPPLER_0_20_OR_LATER, $POPPLER_0_20_OR_LATER)
+AC_SUBST(POPPLER_0_23_OR_LATER, $POPPLER_0_23_OR_LATER)
+AC_SUBST(POPPLER_INC, $POPPLER_INC)
+AC_SUBST(POPPLER_PLUGIN_LIB, $POPPLER_PLUGIN_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if libpodofo is available
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(podofo,[  --with-podofo[=ARG]    Include podofo(for PDF) support (ARG=no(default), yes or podofo install path)],,)
+
+HAVE_PODOFO=no
+
+AC_MSG_CHECKING([for podofo])
+
+if test "$with_podofo" != "no" -a "$with_podofo" != ""; then
+
+    AC_ARG_WITH(podofo-lib,
+      [  --with-podofo-lib=ARG   podofo Link Flags (i.e. -L/xxx -lpodofo ...). Mainly for static libpodofo],,,)
+
+    if test "$with_podofo" = "yes" ; then
+        TEST_PODOFO_INC="-I/usr/include -I/usr/include/podofo"
+        PODOFO_LIB="-lpodofo"
+    else
+        TEST_PODOFO_INC="-I$with_podofo/include -I$with_podofo/include/podofo"
+        PODOFO_LIB="-L$with_podofo/lib -lpodofo"
+    fi
+
+    if test "x$with_podofo_lib" = "x" ; then
+        rm -f testpodofo.*
+        echo '#include <podofo.h>' > testpodofo.cpp
+        echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
+        ${CXX} ${CXXFLAGS} ${LDFLAGS} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB} 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
+            HAVE_PODOFO=yes
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PODOFO_LIB} ${LIBS}"
+            fi
+            PODOFO_INC=$TEST_PODOFO_INC
+            PODOFO_PLUGIN_LIB="${PODOFO_LIB}"
+            AC_MSG_RESULT([yes])
+        fi
+        rm -f testpodofo.*
+        rm -f testpodofo
+    fi
+
+    if test "$HAVE_PODOFO" = "no"; then
+        if test "x$with_podofo_lib" != "x" ; then
+            PODOFO_LIB="$with_podofo_lib"
+        else
+            # This may be a static libpodofo.a, so add dependent libraries.
+            PODOFO_LIB="$PODOFO_LIB -lfreetype -lfontconfig -lpthread"
+        fi
+
+        AC_ARG_WITH(podofo-extra-lib-for-test,
+          [  --with-podofo-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (i.e. -ljpeg ...). Mainly for static libpodofo],,,)
+
+        if test "x$with_podofo_extra_lib_for_test" = "x" ; then
+            TEST_PODOFO_LIB="$PODOFO_LIB"
+        else
+            TEST_PODOFO_LIB="$PODOFO_LIB $with_podofo_extra_lib_for_test"
+        fi
+
+        rm -f testpodofo.*
+        echo '#include <podofo.h>' > testpodofo.cpp
+        echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
+        ${CXX} ${CXXFLAGS} ${LDFLAGS} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
+            HAVE_PODOFO=yes
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PODOFO_LIB} ${LIBS}"
+            fi
+            PODOFO_INC=$TEST_PODOFO_INC
+            PODOFO_PLUGIN_LIB="${PODOFO_LIB}"
+            AC_MSG_RESULT([yes])
+        else
+            AC_MSG_RESULT([no])
+        fi
+        rm -f testpodofo.*
+        rm -f testpodofo
+    fi
+else
+    AC_MSG_RESULT([disabled])
+fi
+
+AC_SUBST(HAVE_PODOFO, $HAVE_PODOFO)
+AC_SUBST(PODOFO_INC, $PODOFO_INC)
+AC_SUBST(PODOFO_PLUGIN_LIB, $PODOFO_PLUGIN_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl Check if libpdfium is available
+dnl
+dnl Support for open-source PDFium library
+dnl
+dnl Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
+dnl Author: Martin Mikita <martin.mikita at klokantech.com>, xmikit00 @ FIT VUT Brno
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(pdfium,[  --with-pdfium[=ARG]    Include pdfium (for PDF) support (ARG=no(default), yes or pdfium install path)],,)
+
+HAVE_PDFIUM=no
+
+AC_MSG_CHECKING([for pdfium])
+
+if test "$with_pdfium" != "no" -a "$with_pdfium" != ""; then
+
+    AC_ARG_WITH(pdfium-lib,
+      [  --with-pdfium-lib=ARG   pdfium Link Flags (i.e. -L/xxx -lpdfium ...). Mainly for static libpdfium],,,)
+
+    if test "$with_pdfium" = "yes" ; then
+        TEST_PDFIUM_INC="-I/usr/include -I/usr/include/pdfium"
+        PDFIUM_LIB="-lpdfium"
+        PDFIUM_LIBDIR="/usr"
+    else
+        TEST_PDFIUM_INC="-I$with_pdfium -I$with_pdfium/include -I$with_pdfium/include/pdfium"
+        PDFIUM_LIB="-L$with_pdfium -L$with_pdfium/lib -lpdfium"
+        PDFIUM_LIBDIR="$with_pdfium"
+    fi
+
+    if test ! -z "`uname | grep Darwin`" ; then
+        PDFIUM_LIB="-stdlib=libstdc++ $PDFIUM_LIB"
+    fi
+
+    if test "x$with_pdfium_lib" = "x" ; then
+        rm -f testpdfium.*
+        echo '#include <fpdfview.h>' > testpdfium.cpp
+        echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
+        echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
+        TEST_CXX_FLAGS="-std=c++0x"
+        if test ! -z "`uname | grep Darwin`" ; then
+          TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
+        fi
+        if ${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${PDFIUM_LIB} >/dev/null 2>/dev/null; then
+            HAVE_PDFIUM=yes
+            CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PDFIUM_LIB} ${LIBS}"
+            fi
+            PDFIUM_PLUGIN_LIB="${PDFIUM_LIB}"
+            PDFIUM_INC=$TEST_PDFIUM_INC
+            AC_MSG_RESULT([yes])
+        fi
+        rm -f testpdfium.*
+        rm -f testpdfium
+    fi
+
+    if test "$HAVE_PDFIUM" = "no"; then
+        if test "x$with_pdfium_lib" != "x" ; then
+            PDFIUM_LIB="$with_pdfium_lib"
+        else
+            # This may be a static libpdfium.a, so add dependent libraries.
+            PDFIUM_LIB="-L$PDFIUM_LIBDIR -L$PDFIUM_LIBDIR/lib/pdfium -lpdfium -lfpdfdoc -lfpdfapi -lfpdftext -lformfiller -lpdfwindow"
+            PDFIUM_LIB="$PDFIUM_LIB -lfxedit -lfpdfdoc -lfxcodec -lfx_libopenjpeg -lfx_lcms2 -lfx_libjpeg -lfx_zlib"
+            PDFIUM_LIB="$PDFIUM_LIB -lfdrm -lfxge -lfreetype -lfx_agg -lfxcrt -lbigint"
+            if test ! -z "`uname | grep Darwin`" ; then
+                PDFIUM_LIB="-framework AppKit -framework CoreFoundation $PDFIUM_LIB"
+            fi
+        fi
+
+        AC_ARG_WITH(pdfium-extra-lib-for-test,
+          [  --with-pdfium-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (i.e. -ljpeg ...). Mainly for static libpdfium],,,)
+
+        if test "x$with_pdfium_extra_lib_for_test" = "x" ; then
+            TEST_PDFIUM_LIB="$PDFIUM_LIB"
+        else
+            TEST_PDFIUM_LIB="$PDFIUM_LIB $with_pdfium_extra_lib_for_test"
+        fi
+
+        rm -f testpdfium.*
+        echo '#include <fpdfview.h>' > testpdfium.cpp
+        echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
+        echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
+        TEST_CXX_FLAGS="-std=c++0x"
+        if test ! -z "`uname | grep Darwin`" ; then
+          TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
+        fi
+        if ${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${TEST_PDFIUM_LIB} >/dev/null 2>/dev/null; then
+            HAVE_PDFIUM=yes
+            CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
+            if test "$PDF_PLUGIN" = "no"; then
+                LIBS="${PDFIUM_LIB} ${LIBS}"
+            fi
+            PDFIUM_PLUGIN_LIB="${PDFIUM_LIB}"
+            PDFIUM_INC=$TEST_PDFIUM_INC
+            AC_MSG_RESULT([yes])
+        else
+            AC_MSG_RESULT([no])
+        fi
+        rm -f testpdfium.*
+        rm -f testpdfium
+    fi
+
+    if test "$HAVE_PDFIUM" = "no" -a "$with_pdfium" != ""; then
+        AC_MSG_ERROR([pdfium requested but not found])
+    fi
+else
+    AC_MSG_RESULT([disabled])
+fi
+
+AC_SUBST(HAVE_PDFIUM, $HAVE_PDFIUM)
+AC_SUBST(PDFIUM_INC, $PDFIUM_INC)
+AC_SUBST(PDFIUM_PLUGIN_LIB, $PDFIUM_PLUGIN_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl PROJ.4 related stuff.
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([how to link PROJ.4 library])
+
+AC_ARG_WITH(static_proj4,[  --with-static-proj4=ARG Compile with PROJ.4 statically (ARG=no or path)],,)
+
+if test "x$with_static_proj4" = "xno" -o "x$with_static_proj4" = "x"; then
+
+  PROJ_STATIC=no
+  AC_MSG_RESULT([link dynamically.])
+
+else
+
+  PROJ_STATIC=yes
+  AC_MSG_RESULT([link statically.])
+
+  ORIG_LIBS="$LIBS"
+  PROJ_LIB="-lproj"
+
+  if test "x$with_static_proj4" = "xyes" ; then
+    LIBS="$PROJ_LIB $ORIG_LIBS"
+    AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
+  else
+
+    LIBS="-L$with_static_proj4/lib $PROJ_LIB $ORIG_LIBS"
+    AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
+
+    if test "$PROJ_STATIC" = "no"; then
+      dnl Disable previous value cached by the previous AC_CHECK_LIB test :
+      dnl AC_CHECK_LIB caches the result value for a couple (function, library)
+      dnl in a variable named "ac_cv_lib_<library name>_<function name>".
+      dnl In order to try to locate the library in different locations, using
+      dnl different values of LIBS, we have to 'unset' this variable after
+      dnl each negative test.
+
+      unset ac_cv_lib_proj_pj_init
+
+      LIBS="-L$with_static_proj4/src $PROJ_LIB $ORIG_LIBS"
+      AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
+    fi
+
+    if test "$PROJ_STATIC" = "no"; then
+      unset ac_cv_lib_proj_pj_init
+      LIBS="-L$with_static_proj4/src/.libs $PROJ_LIB $ORIG_LIBS"
+      AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
+    fi
+
+    if test "$PROJ_STATIC" = "no"; then
+      unset ac_cv_lib_proj_pj_init
+      LIBS="-L$with_static_proj4 $PROJ_LIB $ORIG_LIBS"
+      AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
+    fi
+
+    if test "$PROJ_STATIC" = "no"; then
+      unset ac_cv_lib_proj_pj_init
+      LIBS="$PROJ_LIB $ORIG_LIBS"
+      AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
+    fi
+
+  fi
+
+  if test "$PROJ_STATIC" = "no"; then
+    LIBS="$ORIG_LIBS"
+  fi
+
+  if test -r "$with_static_proj4/src/proj_api.h" ; then
+    PROJ_INCLUDE="-I$with_static_proj4/src"
+  elif test -r "$with_static_proj4/include/proj_api.h" ; then
+    PROJ_INCLUDE="-I$with_static_proj4/include"
+  elif test -r "$with_static_proj4/proj_api.h" ; then
+    PROJ_INCLUDE="-I$with_static_proj4"
+  fi
+
+fi
+
+AC_SUBST(PROJ_STATIC)
+AC_SUBST(PROJ_INCLUDE)
+
+dnl ---------------------------------------------------------------------------
+dnl Get/override version.
+dnl ---------------------------------------------------------------------------
+
+
+AC_ARG_WITH(gdal-ver,[  --with-gdal-ver=ARG   Override GDAL version ],,)
+GDAL_VERSION_MAJOR=`grep "#*define.GDAL_VERSION_MAJOR.*" gcore/gdal_version.h | awk '{print $4}'`
+GDAL_VERSION_MINOR=`grep "#*define.GDAL_VERSION_MINOR.*" gcore/gdal_version.h | awk '{print $4}'`
+GDAL_VERSION_REV=`grep "#*define.GDAL_VERSION_REV.*" gcore/gdal_version.h | awk '{print $4}'`
+
+AC_MSG_RESULT([checking GDAL version information from gdal_version.h: $GDAL_VERSION_MAJOR.$GDAL_VERSION_MINOR.$GDAL_VERSION_REV])
+
+AC_SUBST(GDAL_VERSION_MAJOR,    "$GDAL_VERSION_MAJOR")
+AC_SUBST(GDAL_VERSION_MINOR,    "$GDAL_VERSION_MINOR")
+AC_SUBST(GDAL_VERSION_REV,    "$GDAL_VERSION_REV")
+
+if test "x$with_gdal_ver" != "x"; then
+
+  GDAL_VER=$with_gdal_ver
+  AC_MSG_RESULT([  overridden GDAL version: $GDAL_VER])
+else
+
+  GDAL_VER=$GDAL_VERSION_MAJOR.$GDAL_VERSION_MINOR.$GDAL_VERSION_REV
+
+fi
+
+AC_SUBST(GDAL_VER, $GDAL_VER)
+echo $GDAL_VER > VERSION
+
+dnl ---------------------------------------------------------------------------
+dnl MacOS X Framework Build
+
+if test ! -z "`uname | grep Darwin`" ; then
+
+  CXXFLAGS="$ARCHFLAGS $CXXFLAGS"
+  CFLAGS="$ARCHFLAGS $CFLAGS"
+  LIBS="$ARCHFLAGS $LIBS"
+
+  MACOSX_FRAMEWORK=no
+  AC_ARG_WITH(macosx-framework,[  --with-macosx-framework         Build and install GDAL as a Mac OS X Framework],,)
+  AC_MSG_CHECKING([for Mac OS X Framework build])
+  if test "$with_macosx_framework" = yes ; then
+    MACOSX_FRAMEWORK=yes
+    AC_MSG_RESULT([enabled])
+    AC_DEFINE_UNQUOTED(MACOSX_FRAMEWORK,1, [Define for Mac OSX Framework build])
+    prefix="/Library/Frameworks/GDAL.framework/Versions/${GDAL_VERSION_MAJOR}.${GDAL_VERSION_MINOR}"
+    exec_prefix='${prefix}'
+    includedir='${prefix}/Headers'
+    datadir='${prefix}/Resources/gdal'
+    libdir='${exec_prefix}'
+    bindir='${exec_prefix}/Programs'
+    docdir='${prefix}/Resources/doc'
+    mandir='${prefix}/Resources/man'
+  else
+    AC_MSG_RESULT([disabled])
+  fi
+  AC_SUBST(MACOSX_FRAMEWORK, $MACOSX_FRAMEWORK)
+fi
+
+AC_SUBST(EXTRA_INCLUDES,$EXTRA_INCLUDES)
+
+dnl ---------------------------------------------------------------------------
+dnl Check whether we need to add specific suffix for executables (.EXE when
+dnl building for Windows). This test should work for the case of
+dnl cross-compilation too.
+dnl ---------------------------------------------------------------------------
+case "${host_os}" in
+    cygwin* | mingw32* | pw32*)
+      EXE_EXT=.exe
+      SO_EXT=dll
+      ;;
+    *)
+      EXE_EXT=
+      ;;
+esac
+
+AC_SUBST(EXE_EXT)
+AC_SUBST(SO_EXT)
+
+dnl ---------------------------------------------------------------------------
+dnl Which "true" program should we use?
+dnl ---------------------------------------------------------------------------
+BINTRUE=/bin/true
+
+if test -f /bin/true.exe ; then
+  BINTRUE=/bin/true.exe
+fi
+if test -f /usr/bin/true ; then
+  BINTRUE=/usr/bin/true
+fi
+
+export BINTRUE
+
+AC_SUBST(BINTRUE,$BINTRUE)
+
+dnl ---------------------------------------------------------------------------
+dnl If datadir is set to @prefix@/share, the modify it to be
+dnl @prefix@/share/gdal.  I wish we could default this.
+dnl ---------------------------------------------------------------------------
+if test "$datadir" = '${prefix}/share' ; then
+  datadir='${prefix}/share/gdal'
+fi
+
+if test "$datadir" = '${datarootdir}' \
+     -a "$datarootdir" = '${prefix}/share' ; then
+  datarootdir='${prefix}/share/gdal'
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl By default mandir is $datarootdir/man which would be
+dnl /usr/local/share/gdal/man but we want man pages in /usr/local/man.
+dnl ---------------------------------------------------------------------------
+mandir='${prefix}/man'
+
+dnl ---------------------------------------------------------------------------
+dnl Capture GDAL_PREFIX for the cpl_config.h include file.
+dnl ---------------------------------------------------------------------------
+
+if test "$prefix" = "NONE" ; then
+  GDAL_PREFIX=/usr/local
+else
+  GDAL_PREFIX=${prefix}
+fi
+
+export GDAL_PREFIX
+AC_DEFINE_UNQUOTED(GDAL_PREFIX,["]$GDAL_PREFIX["], [--prefix directory for GDAL install])
+
+dnl ---------------------------------------------------------------------------
+dnl Perl bindings.
+dnl ---------------------------------------------------------------------------
+
+BINDINGS=
+
+AC_ARG_WITH(perl,[  --with-perl           Enable perl bindings],,)
+
+AC_MSG_CHECKING([for perl bindings])
+if test "$with_perl" = "yes" ; then
+  BINDINGS="perl $BINDINGS"
+  AC_MSG_RESULT([enabled])
+else
+  AC_MSG_RESULT([disabled])
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl PHP bindings.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(php,[  --with-php            Enable php bindings],,)
+
+AC_MSG_CHECKING([for php bindings])
+if test "$with_php" = "yes" ; then
+  BINDINGS="php $BINDINGS"
+  AC_MSG_RESULT([enabled])
+else
+  AC_MSG_RESULT([disabled])
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Ruby bindings.
+dnl ---------------------------------------------------------------------------
+
+dnl AC_ARG_WITH(ruby,[  --with-ruby           Enable Ruby bindings],,)
+
+dnl AC_MSG_CHECKING([for ruby bindings])
+dnl if test "$with_ruby" = "yes" ; then
+dnl   BINDINGS="ruby $BINDINGS"
+dnl   AC_MSG_RESULT([enabled])
+dnl else
+dnl   AC_MSG_RESULT([disabled])
+dnl fi
+
+dnl ---------------------------------------------------------------------------
+dnl NG Python bindings.
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(python,[  --with-python=ARG   Enable python bindings (ARG=yes, no, or path to python binary)],,)
+
+AC_MSG_CHECKING([for python bindings])
+if test "$with_python" = "yes" ; then
+  dnl
+  dnl Check for Python executable in PATH
+  dnl
+  AC_CHECK_PROGS([PYTHON], [python python3 python2])
+  if test "x$PYTHON" = "x"; then
+    AC_MSG_ERROR([--with-python requested, but Python not found!])
+  fi
+elif test "x$with_python" != "x" -a "$with_python" != "no" ; then
+  PYTHON="$with_python"
+  if test "`$PYTHON -c 'print(1)'`" != "1"; then
+    AC_MSG_ERROR([--with-python requested, but Python not found!])
+  fi
+  AC_MSG_RESULT([enabled])
+else
+  PYTHON=""
+  AC_MSG_RESULT([disabled])
+fi
+
+if test "x$PYTHON" != "x"; then
+  BINDINGS="python $BINDINGS"
+
+  AC_MSG_CHECKING([for python setuptools])
+  SETUPTEST='try:
+  import setuptools
+  print(1)
+except ImportError:
+  pass'
+  PY_HAVE_SETUPTOOLS=`$PYTHON -c "$SETUPTEST"`
+  if test "$PY_HAVE_SETUPTOOLS" = "1"; then
+    AC_MSG_RESULT([found])
+  else
+    AC_MSG_RESULT([not found])
+  fi
+fi
+
+AC_SUBST([PY_HAVE_SETUPTOOLS])
+AC_SUBST([BINDINGS])
+
+dnl ---------------------------------------------------------------------------
+dnl Java support
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(java,[  --with-java       Include Java support (ARG=yes, no or JDK home path)  [[default=no]]],,)
+
+AC_MSG_CHECKING([whether we should include Java support])
+
+JAVA_HOME=""
+JAVA_INC=""
+mac_java_fw=""
+
+if test "x$with_java" = "xyes"; then
+
+dnl Ubuntu
+    JAVA_6_TEST_DIR=
+    JAVA_7_TEST_DIR=
+    JAVA_8_TEST_DIR=
+    JAVA_MAC_TEST_DIR=
+    case "$host_cpu" in
+        i*86*)
+            JAVA_6_TEST_DIR=/usr/lib/jvm/java-6-openjdk-i386
+            JAVA_7_TEST_DIR=/usr/lib/jvm/java-7-openjdk-i386
+            JAVA_8_TEST_DIR=/usr/lib/jvm/java-8-openjdk-i386
+            ;;
+        x86_64*)
+            JAVA_6_TEST_DIR=/usr/lib/jvm/java-6-openjdk-amd64
+            JAVA_7_TEST_DIR=/usr/lib/jvm/java-7-openjdk-amd64
+            JAVA_8_TEST_DIR=/usr/lib/jvm/java-8-openjdk-amd64
+            ;;
+        *)
+            ;;
+    esac
+    case "${host_os}" in
+      darwin*)
+        JAVA_MAC_TEST_DIR=$(/usr/libexec/java_home)
+        ;;
+    esac
+
+    if test "x$JAVA_8_TEST_DIR" != "x" -a -d "$JAVA_8_TEST_DIR/include"; then
+        with_java="$JAVA_8_TEST_DIR"
+
+    elif test "x$JAVA_7_TEST_DIR" != "x" -a -d "$JAVA_7_TEST_DIR/include"; then
+        with_java="$JAVA_7_TEST_DIR"
+
+    elif test "x$JAVA_6_TEST_DIR" != "x" -a -d "$JAVA_6_TEST_DIR/include"; then
+        with_java="$JAVA_6_TEST_DIR"
+
+    elif test -d /usr/lib/jvm/java-6-openjdk; then
+        with_java="/usr/lib/jvm/java-6-openjdk"
+
+dnl RHEL6
+    elif test -d /usr/lib/jvm/java-openjdk; then
+        with_java="/usr/lib/jvm/java-openjdk"
+
+
+dnl OpenSolaris
+    elif test -d /usr/java; then
+        with_java="/usr/java"
+
+dnl Mac OS X
+    elif test "x$JAVA_MAC_TEST_DIR" != "x"; then
+        if test -d "$JAVA_MAC_TEST_DIR/bundle"; then
+            # Mac default 1.6.0_x framework
+            # test for ./bundle first, since older installs also have ./include
+            with_java="$JAVA_MAC_TEST_DIR"
+            mac_java_fw="JavaVM"
+        elif test -d "$JAVA_MAC_TEST_DIR/include"; then
+            # Oracle Java install
+            with_java="$JAVA_MAC_TEST_DIR"
+        fi
+    else
+        AC_MSG_ERROR("cannot find JDK root directory.")
+    fi
+
+    if test \! -d "$with_java/include" && test \! -d "$with_java/bundle"; then
+        AC_MSG_ERROR("$with_java is not a valid JDK.")
+    fi
+fi
+
+if test "x$JAVA_INC" != "x"; then
+    AC_MSG_RESULT([yes])
+elif test "x$with_java" != "x" -a "x$with_java" != "xno"; then
+
+    if test -d "$with_java/bundle" && test -d "/System/Library/Frameworks/JavaVM.framework/Headers"; then
+        # Mac default 1.6.0_x framework
+        # test for ./bundle first, since older installs also have ./include
+        JAVA_HOME="$with_java"
+        JAVA_INC="-I/System/Library/Frameworks/JavaVM.framework/Headers"
+        mac_java_fw="JavaVM"
+        AC_MSG_RESULT([yes])
+    elif test -d "$with_java/include"; then
+        if test -d "$with_java/include/linux"; then
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
+            AC_MSG_RESULT([yes])
+        elif test -d "$with_java/include/solaris"; then
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/solaris"
+            AC_MSG_RESULT([yes])
+        elif test -d "$with_java/include/freebsd"; then
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/freebsd"
+            AC_MSG_RESULT([yes])
+        elif test -d "$with_java/include/darwin"; then
+            # Oracle Java install, use instead of Mac default 1.6.0_x
+            JAVA_HOME="$with_java"
+            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/darwin"
+            AC_MSG_RESULT([yes])
+        else
+            AC_MSG_ERROR("Cannot find $with_java/include/linux or solaris or freebsd or darwin directory.")
+        fi
+    else
+        AC_MSG_ERROR("Cannot find $with_java/include or <mac_java_framework>/Headers directory.")
+    fi
+
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(JAVA_HOME,$JAVA_HOME)
+AC_SUBST(JAVA_INC,$JAVA_INC)
+
+dnl ---------------------------------------------------------------------------
+dnl MDB driver
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(mdb,[  --with-mdb       Include MDB driver],,)
+
+AC_MSG_CHECKING([whether we should include MDB support])
+
+MDB_ENABLED=no
+JVM_LIB=""
+
+if test "$with_mdb" = "yes" ; then
+    if test "x$JAVA_INC" = "x"; then
+        AC_MSG_ERROR("--with-java must be specified.")
+    fi
+
+    AC_ARG_WITH(jvm-lib,          [  --with-jvm-lib=[ARG]        ARG is dlopen or points to Java libjvm path],,)
+
+    AC_ARG_WITH(jvm-lib-add-rpath,[  --with-jvm-lib-add-rpath    Add the libjvm path to the RPATH (no by default)],,)
+
+    if test "x$with_jvm_lib" = "xdlopen"; then
+        AC_DEFINE_UNQUOTED(JVM_LIB_DLOPEN, 1, [Define to 1 if libjvm.so should be dlopen'd])
+        JVM_LIB="-ldl"
+    elif test "x$with_jvm_lib" != "x"; then
+        if test -d "$with_jvm_lib"; then
+            saved_LDFLAGS="$LDFLAGS"
+            LDFLAGS="$LDFLAGS -L$with_jvm_lib"
+            if test "x$mac_java_fw" != "x"; then
+                AC_CHECK_FW_FUNC($mac_java_fw,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            else
+                AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            fi
+            LDFLAGS="$saved_LDFLAGS"
+            if test "$HAS_LIB_JVM" = "yes"; then
+                JVM_LIB="-L$with_jvm_lib -ljvm"
+                if test "x$mac_java_fw" != "x"; then
+                    JVM_LIB="-framework $mac_java_fw"
+                fi
+                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
+                    case "${host_os}" in
+                      darwin*)
+                          if test "x$mac_java_fw" = "x"; then
+                              JVM_LIB="-Wl,-rpath,$with_jvm_lib -L$with_jvm_lib -lazy-ljvm"
+                          fi
+                          ;;
+                      *)
+                          JVM_LIB="-Wl,-rpath=$with_jvm_lib $JVM_LIB"
+                          ;;
+                    esac
+                fi
+            else
+                AC_MSG_ERROR("--with-jvm-lib must point to a directory with a libjvm.")
+            fi
+        else
+            AC_MSG_ERROR("--with-jvm-lib must point to a directory.")
+        fi
+    elif test "x$JAVA_HOME" != "x"; then
+        TEST_DIR="$JAVA_HOME/jre/lib/amd64/server"
+        if test -d "$JAVA_HOME/jre/lib/server"; then
+            # Oracle Java install on Mac
+            TEST_DIR="$JAVA_HOME/jre/lib/server"
+        fi
+        if test "x$mac_java_fw" != "x"; then
+            # Mac default 1.6.0_x framework, TEST_DIR not used
+            TEST_DIR="$with_java"
+        fi
+        if test "x$JVM_LIB" = "x" -a -d "$TEST_DIR"; then
+            unset ac_cv_lib_jvm_JNI_CreateJavaVM
+            saved_LDFLAGS="$LDFLAGS"
+            LDFLAGS="$LDFLAGS -L$TEST_DIR"
+            if test "x$mac_java_fw" != "x"; then
+                AC_CHECK_FW_FUNC($mac_java_fw,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            else
+                AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            fi
+            LDFLAGS="$saved_LDFLAGS"
+            if test "$HAS_LIB_JVM" = "yes"; then
+                JVM_LIB="-L$TEST_DIR -ljvm"
+                if test "x$mac_java_fw" != "x"; then
+                    JVM_LIB="-framework $mac_java_fw"
+                fi
+                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
+                    case "${host_os}" in
+                      darwin*)
+                          if test "x$mac_java_fw" = "x"; then
+                              JVM_LIB="-Wl,-rpath,$TEST_DIR -L$TEST_DIR -lazy-ljvm"
+                          fi
+                          ;;
+                      *)
+                          JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                          ;;
+                    esac
+                fi
+            fi
+        fi
+
+        TEST_DIR="$JAVA_HOME/jre/lib/i386/server"
+        if test "x$JVM_LIB" = "x" -a -d "$TEST_DIR"; then
+            unset ac_cv_lib_jvm_JNI_CreateJavaVM
+            saved_LDFLAGS="$LDFLAGS"
+            LDFLAGS="$LDFLAGS -L$TEST_DIR"
+            AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
+            LDFLAGS="$saved_LDFLAGS"
+            if test "$HAS_LIB_JVM" = "yes"; then
+                JVM_LIB="-L$TEST_DIR -ljvm"
+                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
+                    JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
+                fi
+            fi
+        fi
+
+        if test "x$JVM_LIB" = "x"; then
+            AC_MSG_ERROR("--with-jvm-lib must be specified.")
+        fi
+    else
+        AC_MSG_ERROR("--with-jvm-lib must be specified.")
+    fi
+
+    MDB_ENABLED=yes
+    AC_MSG_RESULT([yes])
+
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(MDB_ENABLED,$MDB_ENABLED)
+AC_SUBST(JVM_LIB,$JVM_LIB)
+
+
+dnl ---------------------------------------------------------------------------
+dnl Select Rasdaman or disable driver.
+dnl ---------------------------------------------------------------------------
+
+RASDAMAN_ENABLED=no
+
+AC_CHECKING(whether we should include rasdaman support)
+AC_ARG_WITH(rasdaman,
+[  --with-rasdaman[=DIR]        Include rasdaman support (DIR is rasdaman's install dir).],,)
+
+if test "$with_rasdaman" = "yes" ; then
+
+  AC_CHECK_LIB(raslib,main,RASDAMAN_ENABLED=yes,,,)
+
+  if test -n "$RASDAMAN_ENABLED" ; then
+      RASDAMAN_LIB="-lrasodmg -lclientcomm -lcompression -lnetwork -lraslib"
+      OPT_GDAL_FORMATS="rasdaman $OPT_GDAL_FORMATS"
+      AC_MSG_RESULT([        using rasdaman from system libs.])
+  else
+      AC_MSG_WARN([        rasdaman not found in system libs... use --with-rasdaman=DIR.])
+  fi
+
+elif test -n "$with_rasdaman" -a "$with_rasdaman" != "no" ; then
+
+  RASDAMAN_DIR=$with_rasdaman
+
+  if test -f $RASDAMAN_DIR/include/rasdaman.hh -a -d$RASDAMAN_DIR/lib ; then
+      RASDAMAN_INC=-I$RASDAMAN_DIR/include
+      RASDAMAN_LIB="-L$RASDAMAN_DIR/lib -lrasodmg -lclientcomm -lcompression -lnetwork -lraslib"
+  else
+      AC_MSG_ERROR("Could not find rasdaman.hh or libraslib.a in $RASDAMAN_DIR.")
+  fi
+
+  RASDAMAN_ENABLED=yes
+  OPT_GDAL_FORMATS="rasdaman $OPT_GDAL_FORMATS"
+  AC_MSG_RESULT([        using rasdaman from $RASDAMAN_DIR.])
+
+else
+
+  AC_MSG_RESULT([        rasdaman support not requested.])
+fi
+
+AC_SUBST(RASDAMAN_ENABLED,$RASDAMAN_ENABLED)
+AC_SUBST(RASDAMAN_INC,    $RASDAMAN_INC)
+AC_SUBST(RASDAMAN_LIB,    $RASDAMAN_LIB)
+
+dnl ---------------------------------------------------------------------------
+dnl Armadillo support
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(armadillo,[  --with-armadillo=ARG       Include Armadillo support for faster TPS transform computation (ARG=yes/no/path to armadillo install root) [[default=no]]],,)
+
+AC_MSG_CHECKING([whether we should include Armadillo support])
+
+HAVE_ARMADILLO=no
+
+if test "$with_armadillo" = "yes" ; then
+    rm -f testarmadillo.*
+    rm -f testarmadillo
+    echo '#include <armadillo>' > testarmadillo.cpp
+    echo 'int main(int argc, char** argv) { arma::mat matInput(2,2); const arma::mat& matInv = arma::inv(matInput); return 0; } ' >> testarmadillo.cpp
+    if test -z "`${CXX} ${CPPFLAGS} testarmadillo.cpp -o testarmadillo -larmadillo 2>&1`" ; then
+        HAVE_ARMADILLO=yes
+        LIBS="-larmadillo ${LIBS}"
+        AC_MSG_RESULT([yes])
+    else
+        dnl Try adding -llapack (#4923)
+        if test -z "`${CXX} ${CPPFLAGS} testarmadillo.cpp -o testarmadillo -larmadillo -llapack 2>&1`" ; then
+            HAVE_ARMADILLO=yes
+            LIBS="-larmadillo -llapack ${LIBS}"
+            AC_MSG_RESULT([yes])
+        else
+            # clang 3.4 needs linking against libstdc++ (ubuntu 14.04)
+            if test -z "`${CXX} ${CPPFLAGS} testarmadillo.cpp -o testarmadillo -larmadillo -lstdc++ 2>&1`" ; then
+                HAVE_ARMADILLO=yes
+                LIBS="-larmadillo -lstdc++ ${LIBS}"
+                AC_MSG_RESULT([yes])
+            else
+                AC_MSG_RESULT([no])
+            fi
+        fi
+    fi
+    rm -f testarmadillo.*
+    rm -f testarmadillo
+
+elif test -n "$with_armadillo" -a "$with_armadillo" != "no" ; then
+
+    rm -f testarmadillo.*
+    rm -f testarmadillo
+    echo '#include <armadillo>' > testarmadillo.cpp
+    echo 'int main(int argc, char** argv) { arma::mat matInput(2,2); const arma::mat& matInv = arma::inv(matInput); return 0; } ' >> testarmadillo.cpp
+    if test -z "`${CXX} ${CPPFLAGS} -I$with_armadillo/include testarmadillo.cpp -o testarmadillo -L$with_armadillo/lib -larmadillo 2>&1`" ; then
+        HAVE_ARMADILLO=yes
+        LIBS="-L$with_armadillo/lib -larmadillo ${LIBS}"
+        EXTRA_INCLUDES="-I$with_armadillo/include $EXTRA_INCLUDES"
+        AC_MSG_RESULT([yes])
+    else
+        dnl Try adding -llapack (#4923)
+        if test -z "`${CXX} ${CPPFLAGS} -I$with_armadillo/include testarmadillo.cpp -o testarmadillo -L$with_armadillo/lib -larmadillo -llapack 2>&1`" ; then
+            HAVE_ARMADILLO=yes
+            LIBS="-L$with_armadillo/lib -larmadillo -llapack ${LIBS}"
+            EXTRA_INCLUDES="-I$with_armadillo/include $EXTRA_INCLUDES"
+            AC_MSG_RESULT([yes])
+        else
+            AC_MSG_RESULT([no])
+        fi
+    fi
+    rm -f testarmadillo.*
+    rm -f testarmadillo
+
+else
+    AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(HAVE_ARMADILLO,$HAVE_ARMADILLO)
+
+dnl ---------------------------------------------------------------------------
+dnl libcryptopp
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH(cryptopp,[  --with-cryptopp[=ARG]       Include cryptopp support (ARG=yes, no or path)],,)
+
+HAVE_CRYPTOPP=no
+USE_ONLY_CRYPTODLL_ALG=yes
+
+AC_MSG_CHECKING([for cryptopp])
+
+if test "$with_cryptopp" = "no" ; then
+
+  AC_MSG_RESULT([disabled])
+
+elif test "$with_cryptopp" = "yes" -o "$with_cryptopp" = "" ; then
+
+    rm -f testcryptopp.*
+    echo '#include <cryptopp/aes.h>' > testcryptopp.cpp
+    # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
+    echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
+    echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+    ${CXX} ${CXXFLAGS} ${LDFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
+    RETVAL=$?
+    if test $RETVAL -eq 0; then
+        HAVE_CRYPTOPP=yes
+        LIBS="-lcryptopp ${LIBS}"
+        AC_MSG_RESULT([yes])
+    else
+        AC_MSG_RESULT([no])
+        if test "$with_cryptopp" = "yes"; then
+            AC_MSG_ERROR([--with-cryptopp was requested, but not available])
+        fi
+    fi
+    rm -f testcryptopp.*
+    rm -f testcryptopp
+
+    if test "$HAVE_CRYPTOPP" = "yes"; then
+
+        AC_MSG_CHECKING([if cryptopp has all cipher methods builtin])
+        rm -f testcryptopp.*
+        echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
+        echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+        ${CXX} ${CXXFLAGS} ${LDFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
+            USE_ONLY_CRYPTODLL_ALG=no
+            AC_MSG_RESULT([yes])
+        else
+            USE_ONLY_CRYPTODLL_ALG=yes
+            AC_MSG_RESULT([no])
+        fi
+        rm -f testcryptopp.*
+        rm -f testcryptopp
+    fi
+
+else
+
+    rm -f testcryptopp.*
+    echo '#include <cryptopp/aes.h>' > testcryptopp.cpp
+    # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
+    echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
+    echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+    ${CXX} ${CXXFLAGS} ${LDFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
+    RETVAL=$?
+    if test $RETVAL -eq 0; then
+        HAVE_CRYPTOPP=yes
+        LIBS="-L$with_cryptopp/lib -lcryptopp ${LIBS}"
+        EXTRA_INCLUDES="-I$with_cryptopp/include $EXTRA_INCLUDES"
+        AC_MSG_RESULT([yes])
+    else
+        AC_MSG_RESULT([no])
+    fi
+    rm -f testcryptopp.*
+    rm -f testcryptopp
+
+    if test "$HAVE_CRYPTOPP" = "yes"; then
+
+        AC_MSG_CHECKING([if cryptopp has all cipher methods builtin])
+        rm -f testcryptopp.*
+        echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
+        echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
+        ${CXX} ${CXXFLAGS} ${LDFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
+        RETVAL=$?
+        if test $RETVAL -eq 0; then
+            USE_ONLY_CRYPTODLL_ALG=no
+            AC_MSG_RESULT([yes])
+        else
+            USE_ONLY_CRYPTODLL_ALG=yes
+            AC_MSG_RESULT([no])
+        fi
+        rm -f testcryptopp.*
+        rm -f testcryptopp
+    fi
+
+fi
+
+AC_SUBST(HAVE_CRYPTOPP,$HAVE_CRYPTOPP)
+AC_SUBST(USE_ONLY_CRYPTODLL_ALG,$USE_ONLY_CRYPTODLL_ALG)
+
+
+dnl ---------------------------------------------------------------------------
+dnl Whether to include MRF in the build
+dnl ---------------------------------------------------------------------------
+
+AC_ARG_WITH([mrf],
+            AS_HELP_STRING([--without-mrf],
+               [Disable MRF driver]),,)
+
+AC_MSG_CHECKING([for MRF])
+if test "$with_mrf" = yes -o x"$with_mrf" = x ; then
+    OPT_GDAL_FORMATS="mrf $OPT_GDAL_FORMATS"
+    HAVE_MRF=yes
+    AC_MSG_RESULT([enabled])
+else
+    HAVE_MRF=no
+    AC_MSG_RESULT([disabled by user])
+fi
+
+dnl ---------------------------------------------------------------------------
+dnl Test if sprintf can be overloaded with _XOPEN_SOURCE being defined or other,
+dnl includes being included before, which mingw64 4.8 doesn't like (#6390)
+dnl ---------------------------------------------------------------------------
+
+AC_MSG_CHECKING([if sprintf can be overloaded for GDAL compilation])
+echo '#define _XOPEN_SOURCE' > testdeprecated.cpp
+echo '#include <vector>' >> testdeprecated.cpp
+echo '#include <stdio.h>' >> testdeprecated.cpp
+echo 'extern "C"' >> testdeprecated.cpp
+echo '{' >> testdeprecated.cpp
+echo 'int sprintf(char *str, const char* fmt, ...);' >> testdeprecated.cpp
+echo '}' >> testdeprecated.cpp
+${CXX} ${CXXFLAGS} testdeprecated.cpp -c 2>/dev/null
+RETVAL=$?
+if test $RETVAL -eq 0; then
+    AC_MSG_RESULT([yes])
+else
+    CPPFLAGS="$CPPFLAGS -DDONT_DEPRECATE_SPRINTF"
+    AC_MSG_RESULT([no])
+fi
+rm -f testdeprecated.*
+rm -f testdeprecated
+
+AC_OUTPUT(GDALmake.opt)
+
+dnl ---------------------------------------------------------------------------
+dnl Display configuration status
+dnl ---------------------------------------------------------------------------
+
+LOC_MSG()
+LOC_MSG([GDAL is now configured for ${host}])
+LOC_MSG()
+LOC_MSG([  Installation directory:    ${prefix}])
+LOC_MSG([  C compiler:                ${CC} ${CFLAGS}])
+LOC_MSG([  C++ compiler:              ${CXX} ${CXXFLAGS}])
+LOC_MSG([  C++11 support:             ${CXX11_SUPPORT}])
+LOC_MSG()
+LOC_MSG([  LIBTOOL support:           ${with_libtool}])
+LOC_MSG()
+LOC_MSG([  LIBZ support:              ${LIBZ_SETTING}])
+LOC_MSG([  LIBLZMA support:           ${LIBLZMA_SETTING}])
+LOC_MSG([  cryptopp support:          ${HAVE_CRYPTOPP}])
+LOC_MSG([  GRASS support:             ${GRASS_SETTING}])
+LOC_MSG([  CFITSIO support:           ${FITS_SETTING}])
+LOC_MSG([  PCRaster support:          ${PCRASTER_SETTING}])
+LOC_MSG([  LIBPNG support:            ${PNG_SETTING}])
+LOC_MSG([  DDS support:               ${DDS_SETTING}])
+LOC_MSG([  GTA support:               ${GTA_SETTING}])
+LOC_MSG([  LIBTIFF support:           ${TIFF_SETTING} (BigTIFF=${HAVE_BIGTIFF})])
+LOC_MSG([  LIBGEOTIFF support:        ${GEOTIFF_SETTING}])
+LOC_MSG([  LIBJPEG support:           ${JPEG_SETTING}])
+LOC_MSG([  12 bit JPEG:               ${JPEG12_ENABLED}])
+LOC_MSG([  12 bit JPEG-in-TIFF:       ${TIFF_JPEG12_ENABLED}])
+LOC_MSG([  LIBGIF support:            ${GIF_SETTING}])
+LOC_MSG([  OGDI support:              ${HAVE_OGDI}])
+LOC_MSG([  HDF4 support:              ${HAVE_HDF4}])
+LOC_MSG([  HDF5 support:              ${HAVE_HDF5}])
+LOC_MSG([  Kea support:               ${HAVE_KEA}])
+LOC_MSG([  NetCDF support:            ${NETCDF_SETTING}])
+LOC_MSG([  Kakadu support:            ${HAVE_KAKADU}])
+if test "x$HAVE_JASPER_UUID" != "x" ; then
+  LOC_MSG([  JasPer support:            ${HAVE_JASPER} (GeoJP2=${HAVE_JASPER_UUID})])
+else
+  LOC_MSG([  JasPer support:            ${HAVE_JASPER}])
+fi
+LOC_MSG([  OpenJPEG support:          ${HAVE_OPENJPEG}])
+LOC_MSG([  ECW support:               ${ECW_SETTING}])
+LOC_MSG([  MrSID support:             ${HAVE_MRSID}])
+LOC_MSG([  MrSID/MG4 Lidar support:   ${HAVE_MRSID_LIDAR}])
+LOC_MSG([  JP2Lura support:           ${HAVE_JP2LURA}])
+LOC_MSG([  MSG support:               ${HAVE_MSG}])
+LOC_MSG([  GRIB support:              ${HAVE_GRIB}])
+LOC_MSG([  EPSILON support:           ${EPSILON_SETTING}])
+LOC_MSG([  WebP support:              ${WEBP_SETTING}])
+LOC_MSG([  cURL support (wms/wcs/...):${CURL_SETTING}])
+LOC_MSG([  PostgreSQL support:        ${HAVE_PG}])
+LOC_MSG([  MRF support:               ${HAVE_MRF}])
+LOC_MSG([  MySQL support:             ${HAVE_MYSQL}])
+LOC_MSG([  Ingres support:            ${HAVE_INGRES}])
+LOC_MSG([  Xerces-C support:          ${HAVE_XERCES}])
+LOC_MSG([  NAS support:               ${HAVE_NAS}])
+LOC_MSG([  Expat support:             ${HAVE_EXPAT}])
+LOC_MSG([  libxml2 support:           ${HAVE_LIBXML2}])
+LOC_MSG([  Google libkml support:     ${HAVE_LIBKML}])
+LOC_MSG([  ODBC support:              ${ODBC_SETTING}])
+LOC_MSG([  PGeo support:              ${ODBC_SETTING}])
+LOC_MSG([  FGDB support:              ${FGDB_ENABLED}])
+LOC_MSG([  MDB support:               ${MDB_ENABLED}])
+LOC_MSG([  PCIDSK support:            ${PCIDSK_SETTING}])
+LOC_MSG([  OCI support:               ${HAVE_OCI}])
+LOC_MSG([  GEORASTER support:         ${HAVE_GEORASTER}])
+LOC_MSG([  SDE support:               ${SDE_ENABLED}])
+LOC_MSG([  Rasdaman support:          ${RASDAMAN_ENABLED}])
+LOC_MSG([  DODS support:              ${HAVE_DODS}])
+LOC_MSG([  SQLite support:            ${HAVE_SQLITE}])
+LOC_MSG([  PCRE support:              ${HAVE_PCRE}])
+LOC_MSG([  SpatiaLite support:        ${HAVE_SPATIALITE}])
+if test "x$SPATIALITE_SONAME" != "x"; then
+LOC_MSG([  SpatiaLite shared obj name:${SPATIALITE_SONAME}])
+fi
+LOC_MSG([  RasterLite2 support:       ${HAVE_RASTERLITE2}])
+LOC_MSG([  Teigha (DWG and DGNv8):    ${HAVE_TEIGHA}])
+LOC_MSG([  INFORMIX DataBlade support:${HAVE_IDB}])
+LOC_MSG([  GEOS support:              ${HAVE_GEOS_RESULT}])
+LOC_MSG([  SFCGAL support:            ${HAVE_SFCGAL_RESULT}])
+LOC_MSG([  QHull support:             ${QHULL_SETTING}])
+LOC_MSG([  Poppler support:           ${HAVE_POPPLER}])
+LOC_MSG([  Podofo support:            ${HAVE_PODOFO}])
+LOC_MSG([  PDFium support:            ${HAVE_PDFIUM}])
+LOC_MSG([  OpenCL support:            ${OPENCL_SETTING}])
+LOC_MSG([  Armadillo support:         ${HAVE_ARMADILLO}])
+LOC_MSG([  FreeXL support:            ${HAVE_FREEXL}])
+LOC_MSG([  SOSI support:              ${SOSI_ENABLED}])
+LOC_MSG([  MongoDB support:           ${MONGODB_ENABLED}])
+LOC_MSG()
+if test ! -z "`uname | grep Darwin`" ; then
+  LOC_MSG([  Mac OS X Framework :       ${MACOSX_FRAMEWORK}])
+fi
+LOC_MSG()
+if test -z "$BINDINGS"; then
+    WHAT_BINDINGS="no"
+else
+    WHAT_BINDINGS="$BINDINGS"
+fi
+LOC_MSG([  SWIG Bindings:             ${WHAT_BINDINGS}])
+LOC_MSG()
+LOC_MSG([  Statically link PROJ.4:    ${PROJ_STATIC}])
+LOC_MSG([  enable GNM building:       ${GNM_ENABLED}])
+LOC_MSG([  enable pthread support:    ${PTHREAD_ENABLED}])
+LOC_MSG([  enable POSIX iconv support:${am_cv_func_iconv}])
+LOC_MSG([  hide internal symbols:     ${HAVE_HIDE_INTERNAL_SYMBOLS}])
+LOC_MSG()
+
+if test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes"  -a "$HAVE_PDFIUM" = "yes"; then
+    AC_MSG_WARN([--with-podofo, --with-poppler and --with-pdfium available. This is unusual setup, but will work. Pdfium will be used by default...])
+elif test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes" ; then
+    AC_MSG_WARN([--with-podofo and --with-poppler are both available. This is unusual setup, but will work. Poppler will be used by default...])
+elif test "$HAVE_POPPLER" = "yes" -a "$HAVE_PDFIUM" = "yes" ; then
+    AC_MSG_WARN([--with-poppler and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default...])
+elif test "$HAVE_PODOFO" = "yes" -a "$HAVE_PDFIUM" = "yes" ; then
+    AC_MSG_WARN([--with-podofo and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default...])
+fi
+
+if test "$HAVE_LIBXML2" = "yes" -a "$FGDB_ENABLED" = "yes"; then
+    AC_MSG_WARN([--with-libxml2 and --with-fgdb are both available. There might be some incompatibility between system libxml2 and the embedded copy within libFileGDBAPI])
+fi
+
+dnl FileGDB v1.5
+if test "$PROJ_STATIC" = "no" -a "$FGDB_ENABLED" = "yes" -a "$FGDB_HAS_PROJ4" = "yes"; then
+    AC_MSG_WARN([--without-static-proj and --with-fgdb are both available. There might be some incompatibility between system libproj and the embedded copy within libFileGDBAPI])
+fi
diff --git a/configure.in b/configure.in
deleted file mode 100644
index 556d2ab..0000000
--- a/configure.in
+++ /dev/null
@@ -1,5156 +0,0 @@
-dnl ***************************************************************************
-dnl $Id: configure.in 36874 2016-12-15 01:53:28Z rouault $
-dnl
-dnl Project:  GDAL
-dnl Purpose:  Configure source file.
-dnl Author:   Frank Warmerdam, warmerdam at pobox.com
-dnl
-dnl ***************************************************************************
-dnl Copyright (c) 2000, Frank Warmerdam
-dnl
-dnl Permission is hereby granted, free of charge, to any person obtaining a
-dnl copy of this software and associated documentation files (the "Software"),
-dnl to deal in the Software without restriction, including without limitation
-dnl the rights to use, copy, modify, merge, publish, distribute, sublicense,
-dnl and/or sell copies of the Software, and to permit persons to whom the
-dnl Software is furnished to do so, subject to the following conditions:
-dnl
-dnl The above copyright notice and this permission notice shall be included
-dnl in all copies or substantial portions of the Software.
-dnl
-dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-dnl OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-dnl FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-dnl THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-dnl DEALINGS IN THE SOFTWARE.
-dnl ***************************************************************************
-
-dnl Disable configure caching ... it causes lots of hassles.
-define([AC_CACHE_LOAD], )
-define([AC_CACHE_SAVE], )
-
-dnl Process this file with autoconf to produce a configure script.
-AC_INIT(GDALmake.opt.in)
-AC_CONFIG_MACRO_DIR(m4)
-AC_CONFIG_HEADERS([port/cpl_config.h:port/cpl_config.h.in])
-AH_BOTTOM([#include "cpl_config_extras.h"])
-
-dnl We require autoconf 2.52+ for libtool support on cygwin/mingw hosts
-AC_PREREQ(2.52)
-
-dnl Compute the canonical host-system (the system we are building for)
-dnl type variable $host
-AC_CANONICAL_HOST
-
-dnl Enable as much warnings as possible
-AX_CFLAGS_WARN_ALL(C_WFLAGS)
-AX_CXXFLAGS_WARN_ALL(CXX_WFLAGS)
-AX_CHECK_COMPILE_FLAG([-Werror -Wextra],[C_WFLAGS="$C_WFLAGS -Wextra" CXX_WFLAGS="$CXX_WFLAGS -Wextra"])
-AX_CHECK_COMPILE_FLAG([-Werror -Winit-self],[C_WFLAGS="$C_WFLAGS -Winit-self" CXX_WFLAGS="$CXX_WFLAGS -Winit-self"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wunused-parameter], [C_WFLAGS="$C_WFLAGS -Wunused-parameter" CXX_WFLAGS="$CXX_WFLAGS -Wunused-parameter" NO_UNUSED_PARAMETER_FLAG="-Wno-unused-parameter"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wmissing-prototypes], [C_WFLAGS="$C_WFLAGS -Wmissing-prototypes"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wmissing-declarations], [C_WFLAGS="$C_WFLAGS -Wmissing-declarations"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wformat], [C_WFLAGS="$C_WFLAGS -Wformat" CXX_WFLAGS="$CXX_WFLAGS -Wformat"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wformat -Werror=format-security -Wno-format-nonliteral], [C_WFLAGS="$C_WFLAGS -Werror=format-security -Wno-format-nonliteral" CXX_WFLAGS="$CXX_WFLAGS -Werror=format-security -Wno-format-nonliteral"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wshorten-64-to-32], [C_WFLAGS="$C_WFLAGS -Wshorten-64-to-32" CXX_WFLAGS="$CXX_WFLAGS -Wshorten-64-to-32"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wlogical-op], [C_WFLAGS="$C_WFLAGS -Wlogical-op" CXX_WFLAGS="$CXX_WFLAGS -Wlogical-op" NO_LOGICAL_OP_FLAG="-Wno-logical-op"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wshadow], [C_WFLAGS="$C_WFLAGS -Wshadow" CXX_WFLAGS="$CXX_WFLAGS -Wshadow"])
-
-dnl Error out on things that will fail with MSVC
-AX_CHECK_COMPILE_FLAG([-Werror -Werror=vla], [C_WFLAGS="$C_WFLAGS -Werror=vla" CXX_WFLAGS="$CXX_WFLAGS -Werror=vla"])
-AX_CHECK_COMPILE_FLAG([-Werror -Werror=declaration-after-statement], [C_WFLAGS="$C_WFLAGS -Wdeclaration-after-statement"])
-
-dnl -Wclobbered is not reliable on most gcc versions
-dnl AX_CHECK_COMPILE_FLAG([-Werror -Wno-clobbered], [C_WFLAGS="$C_WFLAGS -Wno-clobbered" CXX_WFLAGS="$CXX_WFLAGS -Wno-clobbered"])
-
-dnl GCC 6 warnings
-AX_CHECK_COMPILE_FLAG([-Werror -Wnull-dereference], [C_WFLAGS="$C_WFLAGS -Wnull-dereference" CXX_WFLAGS="$CXX_WFLAGS -Wnull-dereference"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wduplicated-cond], [C_WFLAGS="$C_WFLAGS -Wduplicated-cond" CXX_WFLAGS="$CXX_WFLAGS -Wduplicated-cond"])
-
-AX_CHECK_COMPILE_FLAG([-Werror -Wno-sign-compare], [NO_SIGN_COMPARE="-Wno-sign-compare"])
-
-dnl C++ specific stuff
-
-AC_LANG_PUSH([C++])
-AX_CHECK_COMPILE_FLAG([-Werror -Wunused-private-field], [CXX_WFLAGS="$CXX_WFLAGS -Wunused-private-field"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wmissing-prototypes], [CXX_WFLAGS="$CXX_WFLAGS -Wmissing-prototypes"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wmissing-declarations], [CXX_WFLAGS="$CXX_WFLAGS -Wmissing-declarations"])
-AX_CHECK_COMPILE_FLAG([-Werror -Wnon-virtual-dtor], [CXX_WFLAGS="$CXX_WFLAGS -Wnon-virtual-dtor" NO_NON_VIRTUAL_DTOR_FLAG="-Wno-non-virtual-dtor"])
-
-dnl Clang enables -Woverloaded-virtual if -Wall is defined, but not GCC
-AX_CHECK_COMPILE_FLAG([-Werror -Woverloaded-virtual], [CXX_WFLAGS="$CXX_WFLAGS -Woverloaded-virtual"])
-
-dnl Forbid use of 'or', 'and', ... alias operators
-AX_CHECK_COMPILE_FLAG([-Werror -fno-operator-names], [CXX_WFLAGS="$CXX_WFLAGS -fno-operator-names"])
-
-AC_LANG_POP([C++])
-
-AC_SUBST(CXX_WFLAGS,$CXX_WFLAGS)
-AC_SUBST(C_WFLAGS,$C_WFLAGS)
-AC_SUBST(NO_UNUSED_PARAMETER_FLAG,$NO_UNUSED_PARAMETER_FLAG)
-AC_SUBST(NO_SIGN_COMPARE,$NO_SIGN_COMPARE)
-AC_SUBST(NO_NON_VIRTUAL_DTOR_FLAG,$NO_NON_VIRTUAL_DTOR_FLAG)
-AC_SUBST(NO_LOGICAL_OP_FLAG,$NO_LOGICAL_OP_FLAG)
-
-dnl Checks for programs.
-AC_PROG_CC
-AC_PROG_CXX
-AC_LIBTOOL_WIN32_DLL
-AC_PROG_LIBTOOL
-
-dnl Check that CXX is really a working compiler
-AC_LANG_PUSH([C++])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
-  [[#ifndef __cplusplus
-    #error "broken C++"
-    #endif]])],,
-  [CXX=;])
-AC_LANG_POP([C++])
-
-if test "x$CXX" == x ; then
-  AC_MSG_ERROR("You don't have a working C++ compiler.")
-fi
-
-dnl switch between libtool and native build system
-AC_ARG_WITH(libtool, [  --without-libtool     Don't use libtool to build the library],,)
-
-if test "$with_libtool" = "no"; then
-AC_PROG_RANLIB
-
-dnl AC_COMPILER_PIC as expanded by autoconf-2.68 doesn't work for the C++ part with clang++ 3.0 that doesn't like compiling .c programs
-dnl so we inline the expanded code and fix it at hand.
-dnl AC_COMPILER_PIC
-	echo 'void f(){}' > conftest.c
-	if test -z "`${CC-cc} $CFLAGS -fPIC -c conftest.c 2>&1`"; then
-	  CFLAGS="$CFLAGS -fPIC"
-	fi
-	echo 'void f(){}' > conftest.cpp
-	if test -z "`${CXX-g++} $CXXFLAGS -fPIC -c conftest.cpp 2>&1`"; then
-	  CXXFLAGS="$CXXFLAGS -fPIC"
-	fi
-	rm -f conftest*
-
-AC_LD_SHARED
-else
-with_libtool=yes
-fi
-AC_SUBST(HAVE_LIBTOOL,$with_libtool)
-
-dnl Checks for libraries.
-AC_CHECK_LIB(dl,dlopen,,,)
-
-dnl Needed on Solaris.
-AC_CHECK_LIB(rt,nanosleep,,,)
-
-dnl We don't need to add math library to all targets
-case "${host_os}" in
-    cygwin* | mingw32* | pw32* | beos* | darwin*)
-        ;;
-    *)
-	AC_CHECK_LIB(m,sin,,,)
-        ;;
-esac
-
-dnl Checks for header files.
-AC_HEADER_STDC
-AC_CHECK_HEADERS(assert.h fcntl.h unistd.h dbmalloc.h dlfcn.h stdint.h limits.h locale.h values.h float.h errno.h direct.h)
-
-AC_C_BIGENDIAN
-
-dnl Check for 64 bit file API
-AC_HAVE_LONG_LONG
-AC_UNIX_STDIO_64
-
-AC_CHECK_SIZEOF(int)
-AC_CHECK_SIZEOF(unsigned long)
-AC_CHECK_SIZEOF(void*)
-dnl Some compilers (IBM VisualAge) has these types defined, so check it here.
-dnl These types are used in internal libtiff.
-AC_CHECK_TYPES([int8, int16, int32],,,
-[
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-])
-
-dnl We need the following lines for libtiff too.
-HAVE_IEEEFP=1
-AC_DEFINE_UNQUOTED(HAVE_IEEEFP, $HAVE_IEEEFP, [Define as 0 or 1 according to the floating point format supported by the machine])
-
-dnl Check the native cpu bit order (also libtiff stuff).
-AC_MSG_CHECKING([native cpu bit order])
-case "$host_cpu" in
-    i*86*|x86_64*)
-        HOST_FILLORDER=FILLORDER_LSB2MSB
-	AC_MSG_RESULT([lsb2msb])
-	;;
-    *)
-	HOST_FILLORDER=FILLORDER_MSB2LSB
-	AC_MSG_RESULT([msb2lsb])
-        ;;
-esac
-AC_DEFINE_UNQUOTED(HOST_FILLORDER, $HOST_FILLORDER, [Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB)])
-
-dnl Checks for library functions.
-AC_FUNC_VPRINTF
-AC_CHECK_FUNCS(snprintf vsnprintf)
-AC_CHECK_FUNCS(atoll)
-AC_CHECK_FUNCS(strtof)
-AC_CHECK_FUNCS(getcwd)
-
-dnl Check for declarations
-AC_CHECK_DECLS(strtof)
-
-AC_CHECK_FUNCS(readlink)
-AC_CHECK_FUNCS(lstat)
-AC_CHECK_FUNCS(posix_spawnp)
-AC_CHECK_FUNCS(vfork)
-AC_CHECK_FUNCS(mmap)
-AC_CHECK_FUNCS(statvfs)
-AC_CHECK_FUNCS(statvfs64)
-
-dnl Make sure at least these are checked under C++.  Prototypes missing on
-dnl some platforms.
-
-AC_LANG_PUSH(C++)
-AC_CHECK_FUNC_CUSTOM(gmtime_r,[#include <time.h>],[time_t t; struct tm ltime; t = time(0); gmtime_r( &t, &ltime );])
-AC_CHECK_FUNC_CUSTOM(localtime_r,[#include <time.h>],[time_t t; struct tm ltime; t = time(0); localtime_r( &t, &ltime );])
-AC_LANG_POP(C++)
-
-AC_MSG_CHECKING([for uselocale])
-AC_TRY_COMPILE(
-  [
-#define _XOPEN_SOURCE 700
-#include <locale.h>
-  ], [
-    locale_t alocale = newlocale (LC_NUMERIC_MASK, "C", 0);
-    locale_t oldlocale = uselocale(alocale);
-    uselocale(oldlocale);
-    freelocale(alocale);
-    return 0;
-  ],
-  [
-    AC_MSG_RESULT([yes])
-    AC_DEFINE_UNQUOTED(HAVE_USELOCALE, 1,
-          [Define to 1 if you have the `uselocale' function.])
-  ], [
-    AC_MSG_RESULT([no])
-])
-
-
-OPT_GDAL_FORMATS=
-EXTRA_INCLUDES=
-
-dnl ---------------------------------------------------------------------------
-dnl Check for --enable-debug
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([to enable debug build])
-
-AC_ARG_ENABLE(debug,
-	      AS_HELP_STRING([--enable-debug],
-			     [enable debugging (disabled by default)]),
-	      [HAVE_DEBUG=$enableval], [HAVE_DEBUG=yes])
-
-CFLAGS_NOFTRAPV="$CFLAGS"
-CXXFLAGS_NOFTRAPV="$CXXFLAGS"
-
-if test "x$enable_debug" = "xyes" ; then
-
-  dnl Try to strip out optimization.
-
-  CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-O2 //"`
-  CFLAGS=`echo "$CFLAGS " | sed "s/-O2 //"`
-  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-O //"`
-  CFLAGS=`echo "$CFLAGS" | sed "s/-O //"`
-
-  dnl remove existing -g to avoid duplicates.
-
-  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-g //"`
-  CFLAGS=`echo "$CFLAGS" | sed "s/-g //"`
-
-  dnl add -g and -DDEBUG
-
-  CXXFLAGS="$CXXFLAGS -g -DDEBUG"
-  CFLAGS="$CFLAGS -g -DDEBUG"
-
-  CFLAGS_NOFTRAPV="$CFLAGS"
-  CXXFLAGS_NOFTRAPV="$CXXFLAGS"
-
-  AC_MSG_RESULT([yes, modified CFLAGS="$CFLAGS"])
-
-  # Some clang version on 32 bits have linking error with 64bit operations (undefined reference to `__mulodi4')
-  AC_MSG_CHECKING([whether -ftrapv can be used])
-  rm -f testftrapv.c
-  echo 'int main(int argc, char** argv) { return (long long)argc * argc; } ' > testftrapv.c
-  if test -z "`${CC} ${CFLAGS} -ftrapv testftrapv.c -o testftrapv 2>&1`" ; then
-    AC_MSG_RESULT([yes])
-    CFLAGS="$CFLAGS -ftrapv"
-    CXXFLAGS="$CXXFLAGS -ftrapv"
-  else
-    AC_MSG_RESULT([no])
-  fi
-  rm -f testftrapv.* testftrapv
-
-else
-  AC_MSG_RESULT([no, CFLAGS="$CFLAGS"])
-fi
-
-AC_SUBST(CFLAGS_NOFTRAPV,$CFLAGS_NOFTRAPV)
-AC_SUBST(CXXFLAGS_NOFTRAPV,$CXXFLAGS_NOFTRAPV)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if GCC 4.1 atomic builtins are really available
-dnl (some GCC versions are broken w.r.t this on some exotic architectures...)
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([whether GCC 4.1 atomic builtins are available])
-
-rm -f atomicbuiltins.c
-echo 'int main(int argc, char** argv) { int i; __sync_add_and_fetch(&i, 1); __sync_sub_and_fetch(&i, 1); __sync_bool_compare_and_swap(&i, 0, 1); return 0; } ' > atomicbuiltins.c
-if test -z "`${CC} ${CFLAGS} atomicbuiltins.c -o atomicbuiltins 2>&1`" ; then
-    HAVE_GCC_ATOMIC_BUILTINS=yes
-    AC_MSG_RESULT([yes])
-    AC_DEFINE_UNQUOTED(HAVE_GCC_ATOMIC_BUILTINS,1, [Define to 1 if GCC atomic builtins are available])
-else
-    HAVE_GCC_ATOMIC_BUILTINS=no
-    AC_MSG_RESULT([no])
-fi
-rm -f atomicbuiltins.* atomicbuiltins
-
-AC_SUBST(HAVE_GCC_ATOMIC_BUILTINS,$HAVE_GCC_ATOMIC_BUILTINS)
-
-dnl ---------------------------------------------------------------------------
-dnl Check SSE availability
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(sse,
-[  --with-sse[=ARG]        Detect SSE availability for some optimized routines (ARG=yes(default), no)],,)
-
-AC_MSG_CHECKING([whether SSE is available at compile time])
-
-if test "$with_sse" = "yes" -o "$with_sse" = ""; then
-
-    rm -f detectsse.cpp
-    echo '#ifdef __SSE__' > detectsse.cpp
-    echo '#include <xmmintrin.h>' >> detectsse.cpp
-    echo 'void foo() { float fEpsilon = 0.0000000000001f; __m128 xmm_small = _mm_load1_ps(&fEpsilon); }  int main() { return 0; }' >> detectsse.cpp
-    echo '#else' >> detectsse.cpp
-    echo 'some_error' >> detectsse.cpp
-    echo '#endif' >> detectsse.cpp
-    if test -z "`${CXX} ${CXXFLAGS} -o detectsse detectsse.cpp 2>&1`" ; then
-        AC_MSG_RESULT([yes])
-        SSEFLAGS=""
-        HAVE_SSE_AT_COMPILE_TIME=yes
-    else
-        if test -z "`${CXX} ${CXXFLAGS} -msse -o detectsse detectsse.cpp 2>&1`" ; then
-            AC_MSG_RESULT([yes])
-            SSEFLAGS="-msse"
-            HAVE_SSE_AT_COMPILE_TIME=yes
-        else
-            AC_MSG_RESULT([no])
-            if test "$with_sse" = "yes"; then
-                AC_MSG_ERROR([--with-sse was requested, but SSE is not available])
-            fi
-        fi
-    fi
-
-    dnl On Solaris, the presence of SSE instructions is flagged in the binary
-    dnl and prevent it to run on non SSE hardware even if the instructions are
-    dnl not executed. So if the user did not explicitly requires SSE, test that
-    dnl we can run SSE binaries
-    if test "$HAVE_SSE_AT_COMPILE_TIME" = "yes"; then
-       case $host_os in
-         solaris*)
-           AC_MSG_CHECKING([whether SSE is available and needed at runtime])
-           if ./detectsse; then
-             AC_MSG_RESULT([yes])
-           else
-             AC_MSG_RESULT([no])
-             if test "$with_sse" = "yes"; then
-               echo "Caution: the generated binaries will not run on this system."
-             else
-               echo "Disabling SSE as it is not explicitly required"
-               HAVE_SSE_AT_COMPILE_TIME=""
-               SSEFLAGS=""
-             fi
-           fi
-           ;;
-       esac
-    fi
-
-    rm -f detectsse*
-else
-    AC_MSG_RESULT([no])
-fi
-
-AC_SUBST(SSEFLAGS,$SSEFLAGS)
-AC_SUBST(HAVE_SSE_AT_COMPILE_TIME,$HAVE_SSE_AT_COMPILE_TIME)
-
-dnl ---------------------------------------------------------------------------
-dnl Check AVX availability
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(avx,
-[  --with-avx[=ARG]        Detect AVX availability for some optimized routines (ARG=yes(default), no)],,)
-
-AC_MSG_CHECKING([whether AVX is available at compile time])
-
-if test "$with_avx" = "yes" -o "$with_avx" = ""; then
-
-    rm -f detectavx.cpp
-    echo '#ifdef __AVX__' > detectavx.cpp
-    echo '#include <immintrin.h>' >> detectavx.cpp
-    echo 'int foo() { unsigned int nXCRLow, nXCRHigh;' >> detectavx.cpp
-    echo '__asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0));' >> detectavx.cpp
-    echo 'float fEpsilon = 0.0000000000001f;' >> detectavx.cpp
-    echo '__m256 ymm_small = _mm256_set_ps(fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon,fEpsilon);' >> detectavx.cpp
-    echo 'return (int)nXCRLow + _mm256_movemask_ps(ymm_small); }' >> detectavx.cpp
-    echo 'int main(int argc, char**) { if( argc == 0 ) return foo(); return 0; }' >> detectavx.cpp
-    echo '#else' >> detectavx.cpp
-    echo 'some_error' >> detectavx.cpp
-    echo '#endif' >> detectavx.cpp
-    if test -z "`${CXX} ${CXXFLAGS} -o detectavx detectavx.cpp 2>&1`" ; then
-        AC_MSG_RESULT([yes])
-        AVXFLAGS=""
-        HAVE_AVX_AT_COMPILE_TIME=yes
-    else
-        if test -z "`${CXX} ${CXXFLAGS} -mavx -o detectavx detectavx.cpp 2>&1`" ; then
-            AC_MSG_RESULT([yes])
-            AVXFLAGS="-mavx"
-            HAVE_AVX_AT_COMPILE_TIME=yes
-        else
-            AC_MSG_RESULT([no])
-            if test "$with_avx" = "yes"; then
-                AC_MSG_ERROR([--with-avx was requested, but AVX is not available])
-            fi
-        fi
-    fi
-
-    dnl On Solaris, the presence of AVX instructions is flagged in the binary
-    dnl and prevent it to run on non AVX hardware even if the instructions are
-    dnl not executed. So if the user did not explicitly requires AVX, test that
-    dnl we can run AVX binaries
-    if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
-       case $host_os in
-         solaris*)
-           AC_MSG_CHECKING([whether AVX is available and needed at runtime])
-           if ./detectavx; then
-             AC_MSG_RESULT([yes])
-           else
-             AC_MSG_RESULT([no])
-             if test "$with_avx" = "yes"; then
-               echo "Caution: the generated binaries will not run on this system."
-             else
-               echo "Disabling AVX as it is not explicitly required"
-               AVXFLAGS=""
-               HAVE_AVX_AT_COMPILE_TIME=""
-             fi
-           fi
-           ;;
-       esac
-    fi
-
-    rm -f detectavx*
-else
-    AC_MSG_RESULT([no])
-fi
-
-AC_SUBST(AVXFLAGS,$AVXFLAGS)
-AC_SUBST(HAVE_AVX_AT_COMPILE_TIME,$HAVE_AVX_AT_COMPILE_TIME)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for --enable-lto
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([to enable LTO (link time optimization) build])
-
-AC_ARG_ENABLE(lto,
-              AS_HELP_STRING([--enable-lto],
-                             [enable LTO(link time optimization) (disabled by default)]))
-
-CFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CFLAGS"
-CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
-
-if test "x$enable_lto" = "xyes" ; then
-
-  dnl remove existing -g.
-
-  CXXFLAGS=`echo "$CXXFLAGS" | sed "s/-g //"`
-  CFLAGS=`echo "$CFLAGS" | sed "s/-g //"`
-
-  dnl add -flto
-
-  CXXFLAGS="$CXXFLAGS -flto"
-  CFLAGS="$CFLAGS -flto"
-  LDFLAGS="$LDFLAGS -flto"
-
-  dnl in case we have avx available by default, then we can compile everything
-  dnl with -flto
-  if test "$HAVE_AVX_AT_COMPILE_TIME" = "yes"; then
-    if test "$AVXFLAGS" = ""; then
-        CFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CFLAGS"
-        CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT="$CXXFLAGS"
-    fi
-  fi
-
-  AC_MSG_RESULT([yes])
-else
-  AC_MSG_RESULT([no])
-fi
-
-AC_SUBST(CFLAGS_NO_LTO_IF_AVX_NONDEFAULT,$CFLAGS_NO_LTO_IF_AVX_NONDEFAULT)
-AC_SUBST(CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT,$CXXFLAGS_NO_LTO_IF_AVX_NONDEFAULT)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if we need -lws2_32
-dnl ---------------------------------------------------------------------------
-
-echo "#include <winsock2.h>" > test_ws2_32.c
-echo "#include <ws2tcpip.h>" >> test_ws2_32.c
-echo "void foo() {}" >> test_ws2_32.c
-
-if test -z "`${CC} -c test_ws2_32.c 2>&1`" ; then
-  LIBS="$LIBS -lws2_32"
-fi
-rm -f test_ws2_32*
-
-dnl ---------------------------------------------------------------------------
-dnl Check if we have getaddrinfo
-dnl ---------------------------------------------------------------------------
-
-echo "#include <sys/types.h>" > test_getaddrinfo.c
-echo "#include <sys/socket.h>" >> test_getaddrinfo.c
-echo "#include <netdb.h>" >> test_getaddrinfo.c
-echo "void test() { getaddrinfo(0,0,0,0); }"  >> test_getaddrinfo.c
-
-HAVE_GETADDRINFO=NO
-if test -z "`${CC} -c test_getaddrinfo.c 2>&1`" ; then
-  AC_DEFINE_UNQUOTED(HAVE_GETADDRINFO,1, [Define to 1 if you have the `getaddrinfo' function.])
-fi
-rm -f test_getaddrinfo*
-
-dnl ---------------------------------------------------------------------------
-dnl Check if user requests hiding internal symbols
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(hide_internal_symbols,[  --with-hide-internal-symbols[=ARG] Try to hide internal symbols (ARG=yes/no)],,)
-
-HAVE_HIDE_INTERNAL_SYMBOLS=no
-
-if test "$with_hide_internal_symbols" = "yes"; then
-
-    AC_MSG_CHECKING([whether we should hide internal symbols])
-
-    rm -f hiddensymbols.c
-    echo 'int visible() { return 0; } __attribute__ ((visibility("default")))' >> hiddensymbols.c
-    echo 'int hidden() { return 0; }' >> hiddensymbols.c
-    if test -z "`${CC} -fvisibility=hidden -c hiddensymbols.c 2>&1`" ; then
-      HAVE_HIDE_INTERNAL_SYMBOLS=yes
-    else
-      HAVE_HIDE_INTERNAL_SYMBOLS=no
-    fi
-    if test "$HAVE_HIDE_INTERNAL_SYMBOLS" = "yes"; then
-        AC_MSG_RESULT([yes])
-        CFLAGS="$CFLAGS -fvisibility=hidden"
-        CXXFLAGS="$CXXFLAGS -fvisibility=hidden"
-    else
-        AC_MSG_RESULT([no])
-    fi
-    rm -f hiddensymbols.*
-else
-  AC_MSG_CHECKING([whether we should hide internal symbols])
-  AC_MSG_RESULT([no])
-fi
-
-if test "$HAVE_HIDE_INTERNAL_SYMBOLS" = "yes" ; then
-  AC_DEFINE_UNQUOTED(USE_GCC_VISIBILITY_FLAG,1, [Define to 1 if you want to use the -fvisibility GCC flag])
-fi
-
-AC_SUBST(HAVE_HIDE_INTERNAL_SYMBOLS,$HAVE_HIDE_INTERNAL_SYMBOLS)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if user requests renaming internal libtiff symbols
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(rename_internal_libtiff_symbols,[  --with-rename-internal-libtiff-symbols[=ARG] Prefix internal libtiff symbols with gdal_ (ARG=yes/no)],,)
-if test "$with_rename_internal_libtiff_symbols" = ""; then
-    with_rename_internal_libtiff_symbols=no
-fi
-AC_SUBST(RENAME_INTERNAL_LIBTIFF_SYMBOLS,$with_rename_internal_libtiff_symbols)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if user requests renaming internal libgeotiff symbols
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(rename_internal_libgeotiff_symbols,[  --with-rename-internal-libgeotiff-symbols[=ARG] Prefix internal libgeotiff symbols with gdal_ (ARG=yes/no)],,)
-if test "$with_rename_internal_libgeotiff_symbols" = ""; then
-    with_rename_internal_libgeotiff_symbols=no
-fi
-AC_SUBST(RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS,$with_rename_internal_libgeotiff_symbols)
-
-
-dnl ---------------------------------------------------------------------------
-dnl Check if user requests /usr/local to be included.
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([for local include/lib path])
-
-AC_ARG_WITH(local,[  --with-local[=dir]      Include /usr/local or other local tree for INCLUDE/LIBS],,)
-
-if test "$with_local" != "no" -a "$with_local" != "" ; then
-
-  if test "$with_local" = "yes" ; then
-    ADD_PREFIX=/usr/local
-  else
-    ADD_PREFIX=$with_local
-  fi
-
-  AC_MSG_RESULT(adding $ADD_PREFIX)
-
-  LIBS="$LIBS -L$ADD_PREFIX/lib"
-  CPPFLAGS="$CPPFLAGS -I$ADD_PREFIX/include"
-else
-  AC_MSG_RESULT([none])
-fi
-
-dnl ---------------------------------------------------------------------
-dnl ENABLE THREADS ONLY IF REQUESTED.
-dnl ---------------------------------------------------------------------
-
-THREAD_LIB=""
-THREAD_FLAG=""
-PTHREAD_ENABLED="no"
-
-AC_ARG_WITH(threads,
-[  --with-threads[=ARG]    Include thread safe support (ARG=yes(default), no or linkopt)],,)
-
-if test "$with_threads" = "yes" -o "$with_threads" = "" ; then
-
-  AC_CHECK_LIB(pthread,pthread_create,THREAD_FLAG=CPL_MULTIPROC_PTHREAD,,,)
-
-  if test -n "$THREAD_FLAG" ; then
-      THREAD_LIB="-lpthread"
-  else
-    # For Android, pthread_create is in Bionic libc
-    unset ac_cv_lib_pthread_pthread_create
-    AC_CHECK_LIB(c,pthread_create,THREAD_FLAG=CPL_MULTIPROC_PTHREAD,,,)
-  fi
-
-  AC_MSG_CHECKING([for PTHREAD_MUTEX_RECURSIVE])
-
-  AC_TRY_COMPILE(
-  [
-#define _GNU_SOURCE
-#include <pthread.h>
-  ], [
-    return (PTHREAD_MUTEX_RECURSIVE);
-  ],
-  [
-    AC_MSG_RESULT([yes])
-    AC_DEFINE_UNQUOTED(HAVE_PTHREAD_MUTEX_RECURSIVE, 1,
-          [Define to 1 if you have the `PTHREAD_MUTEX_RECURSIVE' constant.])
-  ], [
-    AC_MSG_RESULT([no])
-  ])
-
-
-
-  AC_MSG_CHECKING([for PTHREAD_MUTEX_ADAPTIVE_NP])
-
-  AC_TRY_COMPILE(
-  [
-#define _GNU_SOURCE
-#include <pthread.h>
-  ], [
-    return PTHREAD_MUTEX_ADAPTIVE_NP;
-  ],
-  [
-    AC_MSG_RESULT([yes])
-    AC_DEFINE_UNQUOTED(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP, 1,
-          [Define to 1 if you have the `PTHREAD_MUTEX_ADAPTIVE_NP' constant.])
-  ], [
-    AC_MSG_RESULT([no])
-  ])
-
-  AC_MSG_CHECKING([for pthread_spinlock_t])
-
-  AC_TRY_COMPILE(
-  [
-#define _GNU_SOURCE
-#include <pthread.h>
-  ], [
-    pthread_spinlock_t spin;
-    return 1;
-  ],
-  [
-    AC_MSG_RESULT([yes])
-    AC_DEFINE_UNQUOTED(HAVE_PTHREAD_SPINLOCK, 1,
-          [Define to 1 if you have the `pthread_spinlock_t' type.])
-  ], [
-    AC_MSG_RESULT([no])
-  ])
-
-elif test "$with_threads" != "no" ; then
-
-  THREAD_FLAG=CPL_MULTIPROC_PTHREAD
-  THREAD_LIB="$with_threads"
-
-  AC_CHECKING(whether we should include thread/mutex support...)
-  AC_MSG_RESULT([        using threads with link options "$THREAD_LIB".])
-
-else
-  AC_CHECKING(whether we should include thread/mutex support...)
-  AC_MSG_RESULT([        thread safe support disabled.])
-fi
-
-if test "$THREAD_FLAG" = "CPL_MULTIPROC_PTHREAD" ; then
-  AC_DEFINE_UNQUOTED(CPL_MULTIPROC_PTHREAD,1, [Define if you want to use pthreads based multiprocessing support])
-  PTHREAD_ENABLED="yes"
-fi
-
-LIBS="$THREAD_LIB $LIBS"
-
-dnl ---------------------------------------------------------------------------
-dnl Check if mremap() with 5 args is available
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([for 5 args mremap()])
-
-AC_TRY_COMPILE(
-[
-#define _GNU_SOURCE
-#include <sys/mman.h>
-], [
-return (mremap(0,0,0,0,0));
-],
-[
-AC_MSG_RESULT([yes])
-AC_DEFINE_UNQUOTED(HAVE_5ARGS_MREMAP, 1,
-        [Define to 1 if you have the 5 args `mremap' function.])
-], [
-AC_MSG_RESULT([no])
-])
-
-dnl ---------------------------------------------------------------------------
-dnl Check if _SC_PHYS_PAGES is available
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([for _SC_PHYS_PAGES])
-
-AC_TRY_COMPILE(
-[
-#include <unistd.h>
-], [
-return (sysconf(_SC_PHYS_PAGES));
-],
-[
-AC_MSG_RESULT([yes])
-AC_DEFINE_UNQUOTED(HAVE_SC_PHYS_PAGES, 1,
-        [Define to 1 if you have the _SC_PHYS_PAGES' constant.])
-], [
-AC_MSG_RESULT([no])
-])
-
-dnl ---------------------------------------------------------------------------
-dnl Check if libz is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(libz,[  --with-libz[=ARG]       Include libz support (ARG=internal or libz directory)],,)
-
-if test "$with_libz" = "external" -o "$with_libz" = "" -o "$with_libz" = "yes" ; then
-
-  AC_CHECK_LIB(z,deflateInit_,LIBZ_SETTING=external,LIBZ_SETTING=internal,)
-
-  if test "$LIBZ_SETTING" = "external" ; then
-    AC_CHECK_LIB(z,inflateCopy,LIBZ_SETTING=external,LIBZ_SETTING=internal,)
-    if test "$LIBZ_SETTING" = "external" ; then
-        AC_MSG_RESULT([using pre-installed libz])
-    else
-        AC_MSG_RESULT([using internal libz code as inflateCopy is missing])
-    fi
-  else
-    AC_MSG_RESULT([using internal libz code as deflateInit_ is missing])
-  fi
-
-elif test "$with_libz" != "no" -a "$with_libz" != "internal" ; then
-
-  LIBS="-L$with_libz -L$with_libz/lib $LIBS"
-
-  AC_CHECK_LIB(z,deflateInit_,LIBZ_SETTING=external,LIBZ_SETTING=internal,-L$with_libz -L$with_libz/lib -lz)
-  if test "$LIBZ_SETTING" = "external" ; then
-    AC_CHECK_LIB(z,inflateCopy,LIBZ_SETTING=external,LIBZ_SETTING=internal,-L$with_libz -L$with_libz/lib -lz)
-     if test "$LIBZ_SETTING" = "external" ; then
-        AC_MSG_RESULT([using libz library from $with_libz])
-    else
-        AC_MSG_RESULT([using internal libz code as inflateCopy from $with_libz is missing])
-    fi
-  else
-    AC_MSG_RESULT([using internal libz code as deflateInit_ from $with_libz is missing])
-  fi
-
-fi
-
-if test "$LIBZ_SETTING" = "external" ; then
-  LIBS="-lz $LIBS"
-  if test "$with_libz" != "" -a "$with_libz" != "yes" -a "$with_libz" != "external" ; then
-    EXTRA_INCLUDES="-I$with_libz -I$with_libz/include $EXTRA_INCLUDES"
-  fi
-elif test "$with_libz" = "no" ; then
-  LIBZ_SETTING=no
-  AC_MSG_RESULT([not using libz at all.])
-else
-  LIBZ_SETTING=internal
-  OPT_GDAL_FORMATS="zlib $OPT_GDAL_FORMATS"
-  AC_MSG_RESULT([using internal libz code.])
-fi
-
-AC_SUBST(LIBZ_SETTING,$LIBZ_SETTING)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for iconv/libiconv.
-dnl A rationale for this macro is described in "GNU `gettext' utilities"
-dnl manual at
-dnl http://www.gnu.org/software/gettext/manual/html_node/AM_005fICONV.html
-dnl ---------------------------------------------------------------------------
-AM_ICONV
-
-dnl Extra test needed for GCC 4.5 on Solaris 11, where there is
-dnl a different behaviour if the tests are compiled with gcc or g++.
-dnl So we introduce a ICONV_CPP_CONST that must be used instead of
-dnl ICONV_CONST when used from .cpp files.
-if test "$am_func_iconv" = "yes"; then
-    rm -f testiconv.*
-    echo '#include <iconv.h>' > testiconv.cpp
-    echo 'int main(int argc, char** argv) { iconv_t cd = 0; return iconv (cd, (const char **) 0, 0, 0, 0); } ' >> testiconv.cpp
-    if test -z "`${CXX} ${CPPFLAGS} testiconv.cpp -c 2>&1`" ; then
-        AC_MSG_RESULT([using ICONV_CPP_CONST="const"])
-        ICONV_CPP_CONST="const"
-    else
-        AC_MSG_RESULT([using ICONV_CPP_CONST=""])
-        ICONV_CPP_CONST=""
-    fi
-    rm -f testiconv.*
-
-    AC_DEFINE_UNQUOTED(ICONV_CPP_CONST,$ICONV_CPP_CONST, [For.cpp files, define as const if the declaration of iconv() needs const.])
-fi
-
-
-dnl ---------------------------------------------------------------------------
-dnl Check if liblzma is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(liblzma,[  --with-liblzma[=ARG]       Include liblzma support (ARG=yes/no)],,)
-
-if test "$with_liblzma" = "yes" ; then
-  AC_CHECK_LIB(lzma,lzma_code,LIBLZMA_SETTING=yes,LIBLZMA_SETTING=no,)
-
-  if test "$LIBLZMA_SETTING" = "yes" ; then
-    LIBS="-llzma $LIBS"
-  fi
-else
-    LIBLZMA_SETTING=no
-fi
-
-AC_SUBST(LIBLZMA_SETTING,$LIBLZMA_SETTING)
-
-dnl ---------------------------------------------------------------------------
-dnl Select an PostgreSQL Library to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-PG_CONFIG=no
-
-AC_ARG_WITH(pg,
-	    AS_HELP_STRING([--with-pg[=ARG]],
-	       [Include PostgreSQL GDAL/OGR Support (ARG=path to pg_config)]),,)
-
-if test "x$with_pg" = "xyes" -o "x$with_pg" = "x" ; then
-  AC_PATH_PROG(PG_CONFIG, pg_config, no)
-else
-  PG_CONFIG=$with_pg
-fi
-
-AC_MSG_CHECKING([for PostgreSQL])
-
-if test "x$PG_CONFIG" = "xno" ; then
-
-  HAVE_PG=no
-  PG_LIB=
-  PG_INC=
-
-  AC_MSG_RESULT([no])
-
-else
-  if test -d ${PG_CONFIG} ; then
-      AC_MSG_RESULT([no])
-      AC_MSG_ERROR([--with-pg argument is a directory.  It should be the path to the pg_config script, often somewhere like /usr/local/pgsql/bin/pg_config.])
-  fi
-
-  if test \! -x ${PG_CONFIG} ; then
-      AC_MSG_RESULT([no])
-      AC_MSG_ERROR([--with-pg argument is a not an executable file.  It should be the path to the pg_config script, often somewhere like /usr/local/pgsql/bin/pg_config.])
-  fi
-
-  AC_MSG_RESULT([yes])
-
-  AC_CHECK_LIB(pq,PQconnectdb,HAVE_PG=yes,HAVE_PG=no,-L`$PG_CONFIG --libdir`)
-
-  if test "${HAVE_PG}" = "yes" ; then
-    LIBS=-L`$PG_CONFIG --libdir`" -lpq $LIBS"
-    PG_INC=-I`$PG_CONFIG --includedir`" -I"`$PG_CONFIG --includedir-server`
-
-    PG_EXTRA_DEC=""
-    saved_LIBS="$LIBS"
-    AC_CHECK_LIB(pq,PQputCopyData,,DEFINE_PG_PRE74=-DPG_PRE74,)
-    LIBS="$saved_LIBS"
-    if test "$DEFINE_PG_PRE74" != "" ; then
-      echo "The PostgreSQL client version is before 7.4. You will not be able to use binary cursors."
-    fi
-
-    saved_LIBS="$LIBS"
-    AC_CHECK_LIB(pq,PQescapeStringConn,DEFINE_PG_HAS_PQESCAPESTRINGCONN=-DPG_HAS_PQESCAPESTRINGCONN,,)
-    LIBS="$saved_LIBS"
-    if test "$DEFINE_PG_HAS_PQESCAPESTRINGCONN" = "" ; then
-      echo "falling back to using PQescapeString. You should upgrade at least to security releases 8.1.4, 8.0.8, 7.4.13, 7.3.15."
-    fi
-
-    PG_INC="${PG_INC} ${DEFINE_PG_PRE74} ${DEFINE_PG_HAS_PQESCAPESTRINGCONN}"
-  fi
-
-fi
-
-AC_SUBST(HAVE_PG,$HAVE_PG)
-AC_SUBST(PG_INC,$PG_INC)
-AC_SUBST(PG_LIB,$PG_LIB)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if we should build with GRASS support.
-dnl ---------------------------------------------------------------------------
-
-GRASS_SETTING=no
-GRASS_INCLUDE=
-HAVE_GRASS=no
-export GRASS_INCLUDE GRASS_SETTING
-
-AC_ARG_WITH(grass,[  --with-grass[=ARG]      Include GRASS support (GRASS 5.7+, ARG=GRASS install tree dir)],,)
-
-AC_ARG_WITH(libgrass,[  --with-libgrass[=ARG]   Include GRASS support based on libgrass (GRASS 5.0+)],,)
-
-# default use of grass libraries off since we can't easily auto-find them.
-if test "$with_grass" = "" ; then
-  with_grass=no
-fi
-
-# Check for GRASS 5.7.0 or later library use.
-# TODO: separate libs for rasters and vectors
-if test "$with_grass" != "yes" -a "$with_grass" != "no" ; then
-
-  AC_CHECK_LIB(grass_gis,G_is_initialized,GRASS_SETTING=grass70+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
-  if test "$GRASS_SETTING" = "no" ; then
-    AC_CHECK_LIB(grass_gis,G_asprintf,GRASS_SETTING=grass57+,GRASS_SETTING=no,-L$with_grass/lib -lgrass_datetime)
-  fi
-
-  if test "$GRASS_SETTING" != "no" ; then
-    if test "$GRASS_SETTING" = "grass70+" ; then
-      G_RASTLIBS="-lgrass_raster -lgrass_imagery"
-      G_VECTLIBS="-lgrass_vector -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
-      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
-    else
-      G_RASTLIBS="-lgrass_I"
-      G_VECTLIBS="-lgrass_vect -lgrass_dig2 -lgrass_dgl -lgrass_rtree -lgrass_linkm -lgrass_dbmiclient -lgrass_dbmibase"
-      LIBS="-L$with_grass/lib $G_VECTLIBS $G_RASTLIBS -lgrass_gproj -lgrass_vask -lgrass_gmath -lgrass_gis -lgrass_datetime $LIBS"
-    fi
-    GRASS_INCLUDE="-I$with_grass/include"
-    GRASS_GISBASE="$with_grass"
-    HAVE_GRASS=yes
-  else
-    AC_MSG_ERROR([--with-grass=$with_grass requested, but libraries not found!])
-  fi
-
-# Check if libgrass is disabled.
-elif test "$with_libgrass" = "no" ; then
-
-  echo "GRASS support disabled."
-
-elif test "$with_libgrass" = "yes" -o "$with_libgrass" = "" ; then
-
-  AC_CHECK_LIB(grass5,G_gisinit_2,GRASS_SETTING=libgrass,GRASS_SETTING=no,)
-
-  if test "$GRASS_SETTING" = "libgrass" ; then
-    LIBS="-lgrass5 $LIBS"
-  fi
-
-else
-
-  AC_CHECK_LIB(grass5,G_gisinit_2,GRASS_SETTING=libgrass,GRASS_SETTING=no,-L$with_libgrass/lib)
-
-  if test "$GRASS_SETTING" = "libgrass" ; then
-    LIBS="-L$with_libgrass -L$with_libgrass/lib -lgrass5 $LIBS"
-    GRASS_INCLUDE="-I$with_libgrass -I$with_libgrass/include $EXTRA_INCLUDES"
-  else
-    AC_MSG_ERROR([--with-libgrass=$with_grass requested, but libgrass5 not found!])
-  fi
-fi
-
-AC_SUBST(GRASS_SETTING,$GRASS_SETTING)
-AC_SUBST(GRASS_INCLUDE,$GRASS_INCLUDE)
-AC_SUBST(GRASS_GISBASE,$GRASS_GISBASE)
-AC_SUBST(HAVE_GRASS)
-
-if test "$GRASS_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="grass $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check if cfitsio library is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(cfitsio,[  --with-cfitsio[=ARG]    Include FITS support (ARG=no or libcfitsio path)],,)
-
-if test "$with_cfitsio" = "no" ; then
-
-  FITS_SETTING=no
-
-  echo "FITS support disabled."
-
-elif test "$with_cfitsio" = "yes" -o "$with_cfitsio" = "" ; then
-
-  AC_CHECK_LIB(cfitsio,ffopen,FITS_SETTING=external,FITS_SETTING=no,)
-
-  if test "$FITS_SETTING" = "external" ; then
-    LIBS="-lcfitsio $LIBS"
-    echo "using pre-installed libcfitsio."
-  else
-    echo "libcfitsio not found - FITS support disabled"
-  fi
-
-dnl Fedora has cfitsio headers in /usr/include/cfitsio
-  if test "$FITS_SETTING" = "external" -a -d /usr/include/cfitsio ; then
-    EXTRA_INCLUDES="-I/usr/include/cfitsio $EXTRA_INCLUDES"
-  fi
-
-else
-
-  FITS_SETTING=external
-  LIBS="-L$with_cfitsio -L$with_cfitsio/lib -lcfitsio $LIBS"
-  EXTRA_INCLUDES="-I$with_cfitsio -I$with_cfitsio/include $EXTRA_INCLUDES"
-
-  echo "using libcfitsio from $with_cfitsio."
-fi
-
-AC_SUBST(FITS_SETTING,$FITS_SETTING)
-
-if test "$FITS_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="fits $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check if PCRaster (libcsf) library is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(pcraster,[  --with-pcraster[=ARG]   Include PCRaster (libcsf) support (ARG=internal, no or path)],,)
-
-if test "$with_pcraster" = "no" ; then
-
-  PCRASTER_SETTING=no
-
-  echo "PCRaster support disabled."
-
-elif test "$with_pcraster" = "yes" -o "$with_pcraster" = "" ; then
-
-  AC_CHECK_LIB(csf,Mopen,PCRASTER_SETTING=external,PCRASTER_SETTING=internal,$LIBS)
-  AC_CHECK_HEADERS(csf.h)
-
-  if test "$PCRASTER_SETTING" = "external" -a "$ac_cv_header_csf_h" = "no" ; then
-    PCRASTER_SETTING=internal
-  fi
-
-  if test "$PCRASTER_SETTING" = "external" ; then
-    LIBS="-lcsf $LIBS"
-    echo "using pre-installed libcsf."
-  else
-    echo "using internal csf code."
-  fi
-
-elif test "$with_pcraster" = "internal" ; then
-
-  PCRASTER_SETTING=internal
-
-  echo "using internal csf code."
-
-else
-
-  PCRASTER_SETTING=external
-  LIBS="-L$with_pcraster/lib -lcsf $LIBS"
-  EXTRA_INCLUDES="-I$with_pcraster/include $EXTRA_INCLUDES"
-
-  echo "using libcsf from $with_pcraster."
-
-fi
-
-AC_SUBST(PCRASTER_SETTING,$PCRASTER_SETTING)
-
-if test "$PCRASTER_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="pcraster $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Select a PNG Library to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([png], [  --with-png[=ARG]        Include PNG support (ARG=internal, no or path)],,)
-
-AC_MSG_CHECKING([for libpng])
-
-if test "$with_png" = "no" ; then
-
-  PNG_SETTING=no
-
-  echo "png support disabled."
-
-elif test "$with_png" = "yes" -o "$with_png" = "" ; then
-
-  AC_CHECK_LIB([png], [png_set_IHDR], [PNG_SETTING=external], [PNG_SETTING=internal], [$LIBS])
-  AC_CHECK_HEADERS([png.h])
-
-  if test "$PNG_SETTING" = "external" -a "$ac_cv_header_png_h" = "no" ; then
-    PNG_SETTING=internal
-  fi
-  if test "$PNG_SETTING" = "external" ; then
-    LIBS="-lpng $LIBS"
-    echo "using pre-installed libpng."
-  else
-    echo "using internal png code."
-  fi
-
-elif test "$with_png" = "internal" ; then
-
-  PNG_SETTING=internal
-
-  echo "using internal png code."
-
-else
-
-  PNG_SETTING=external
-  LIBS="-L$with_png -L$with_png/lib -lpng $LIBS"
-  EXTRA_INCLUDES="-I$with_png -I$with_png/include $EXTRA_INCLUDES"
-
-  echo "using libpng from $with_png."
-
-fi
-
-AC_SUBST([PNG_SETTING], [$PNG_SETTING])
-
-if test "$PNG_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="png $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Enable DDS driver.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([dds], [  --with-dds[=ARG]        Include DDS support (ARG=no, or path)],,)
-
-AC_MSG_CHECKING([for libcrunch])
-
-if test "$with_dds" = "no" -o "$with_dds" = ""; then
-
-  DDS_SETTING="no"
-  CRUNCHDIR=""
-
-  echo "dds support disabled."
-
-else
-
-  DDS_SETTING=yes
-  CRUNCHDIR="$with_dds"
-  LIBS="-L$with_dds/lib/ -lcrunch $LIBS"
-  echo "using libcrunch from $with_dds."
-
-fi
-
-AC_SUBST(CRUNCHDIR,$CRUNCHDIR)
-AC_SUBST([DDS_SETTING], [$DDS_SETTING])
-
-if test "$DDS_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="dds $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check if GTA library is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([gta],[  --with-gta[=ARG]        Include GTA support (ARG=no or libgta tree prefix)],,)
-
-if test "$with_gta" = "no" ; then
-
-  GTA_SETTING=no
-
-  echo "GTA support disabled."
-
-elif test "$with_gta" = "yes" -o "$with_gta" = "" ; then
-
-  AC_CHECK_LIB([gta], [gta_version], [GTA_SETTING=yes], [GTA_SETTING=no],)
-
-  if test "$GTA_SETTING" = "yes" ; then
-    LIBS="-lgta $LIBS"
-    echo "using pre-installed libgta."
-  else
-    echo "libgta not found - GTA support disabled"
-  fi
-
-else
-
-  GTA_SETTING=yes
-  LIBS="-L$with_gta -L$with_gta/lib -lgta $LIBS"
-  EXTRA_INCLUDES="-I$with_gta -I$with_gta/include $EXTRA_INCLUDES"
-
-  echo "using libgta from $with_gta."
-fi
-
-AC_SUBST([GTA_SETTING], [$GTA_SETTING])
-
-if test "$GTA_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="gta $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Select PCIDSK options.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([pcidsk], [  --with-pcidsk[=ARG]     Path to external PCIDSK SDK or internal (default)],,)
-
-AC_MSG_CHECKING([for PCIDSK])
-
-PCIDSK_LIB=
-PCIDSK_INCLUDE=
-
-if test "$with_pcidsk" = "no" ; then
-
-  PCIDSK_SETTING=no
-
-  echo "pcidsk support disabled."
-
-elif test "$with_pcidsk" = "" -o "$with_pcidsk" = "yes" -o "$with_pcidsk" = "internal" ; then
-
-  PCIDSK_SETTING=internal
-
-  echo "using internal libpcidsk."
-
-else
-
-  PCIDSK_SETTING=external
-  PCIDSK_LIB="-L$with_pcidsk/lib -lpcidsk"
-  PCIDSK_INCLUDE="-I$with_pcidsk/include -I$with_pcidsk/include/pcidsk"
-
-  echo "using libpcidsk from $with_pcidsk."
-
-fi
-
-if test "$with_pcidsk" != "no" ; then
-
-  AC_SUBST([PCIDSK_SETTING], [$PCIDSK_SETTING])
-  AC_SUBST([PCIDSK_LIB], [$PCIDSK_LIB])
-  AC_SUBST([PCIDSK_INCLUDE], [$PCIDSK_INCLUDE])
-
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Select a libtiff library to use.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(libtiff,[  --with-libtiff=ARG    Libtiff library to use (ARG=internal, yes or path)],,)
-
-AC_MSG_CHECKING([for libtiff])
-
-if test "x${with_libtiff}" = "xyes" -o "x${with_libtiff}" = "x" ; then
-
-  dnl Only automatically pick up the external libtiff if it is >= 4.0.
-  AC_CHECK_LIB(tiff,TIFFScanlineSize64,TIFF_SETTING=external HAVE_BIGTIFF=yes,TIFF_SETTING=internal HAVE_BIGTIFF=yes,)
-
-  if test "$TIFF_SETTING" = "external" ; then
-    dnl Cygwin takes a somewhat restrictive view of what should be exported
-    dnl from the dll, so don't use the external library if missing semi-private
-    dnl functions.
-    AC_CHECK_LIB(tiff,_TIFFsetDoubleArray,TIFF_SETTING=external,TIFF_SETTING=internal,)
-  fi
-
-  if test "$TIFF_SETTING" = "external" ; then
-    LIBS="-ltiff $LIBS"
-    AC_MSG_RESULT([using pre-installed libtiff.])
-  else
-    AC_MSG_RESULT([using internal TIFF code.])
-  fi
-
-elif test "x${with_libtiff}" = "xinternal" ; then
-
-  TIFF_SETTING=internal
-  HAVE_BIGTIFF=yes
-
-  AC_MSG_RESULT([using internal TIFF code.])
-
-else
-
-  TIFF_SETTING=external
-  if test -r "$with_libtiff/tiff.h" ; then
-    LIBS="-L$with_libtiff -ltiff $LIBS"
-    EXTRA_INCLUDES="-I$with_libtiff $EXTRA_INCLUDES"
-  else
-    LIBS="-L$with_libtiff/lib -ltiff $LIBS"
-    EXTRA_INCLUDES="-I$with_libtiff/include $EXTRA_INCLUDES"
-  fi
-
-  AC_MSG_RESULT([using libtiff from ${with_libtiff}.])
-
-  dnl Check for the BigTIFF enabled library (libtiff >= 4.0)
-  AC_CHECK_LIB(tiff,TIFFScanlineSize64,HAVE_BIGTIFF=yes,HAVE_BIGTIFF=no,)
-
-fi
-
-if test "${HAVE_BIGTIFF}" = "yes" ; then
-  TIFF_OPTS="-DBIGTIFF_SUPPORT"
-
-  LOC_MSG([BigTIFF support enabled.])
-fi
-
-AC_SUBST(TIFF_SETTING,${TIFF_SETTING})
-AC_SUBST(TIFF_OPTS,${TIFF_OPTS})
-
-dnl ---------------------------------------------------------------------------
-dnl Select a libgeotiff library to use.
-dnl ---------------------------------------------------------------------------
-
-GEOTIFF_INCLUDE=
-AC_ARG_WITH(geotiff,[  --with-geotiff=ARG    Libgeotiff library to use (ARG=internal, yes or path)],,)
-
-if test "$with_geotiff" = "yes" -o "$with_geotiff" = "" ; then
-
-  if test "$TIFF_SETTING" = "internal" ; then
-    GEOTIFF_SETTING=internal
-  else
-    dnl We now require libgeotiff 1.2.1 (for XTIFFClientOpen).
-    AC_CHECK_LIB(geotiff,XTIFFClientOpen,GEOTIFF_SETTING=external,GEOTIFF_SETTING=internal)
-
-  fi
-
-  if test "$GEOTIFF_SETTING" = "external" ; then
-
-    dnl Now search for headers
-    if test -r /usr/include/geotiff.h ; then
-      GEOTIFF_INCLUDE=
-    dnl Debian (at least some versions of it) install in /usr/include/geotiff
-    elif test -r /usr/include/geotiff/geotiff.h ; then
-      GEOTIFF_INCLUDE="-I/usr/include/geotiff"
-    dnl Fedora and OpenSuse in /usr/include/libgeotiff (#4706)
-    elif test -r /usr/include/libgeotiff/geotiff.h ; then
-      GEOTIFF_INCLUDE="-I/usr/include/libgeotiff"
-    else
-      AC_CHECK_HEADERS([geotiff.h])
-      if test "$ac_cv_header_geotiff_h" = "no" ; then
-        AC_MSG_ERROR([cannot find geotiff.h])
-      fi
-    fi
-
-    LIBS="-lgeotiff $LIBS"
-    echo "using pre-installed libgeotiff."
-
-  else
-
-    echo "using internal GeoTIFF code."
-
-  fi
-
-elif test "$with_geotiff" = "internal" ; then
-
-  GEOTIFF_SETTING=internal
-
-  echo "using internal GeoTIFF code."
-
-else
-
-  GEOTIFF_SETTING=external
-
-  dnl We now require libgeotiff 1.2.1 (for XTIFFClientOpen).
-  dnl first check if $with_geotiff/lib has the library:
-  AC_CHECK_LIB(geotiff,XTIFFClientOpen,GEOTIFF_SETTING=external,GEOTIFF_SETTING=not_found,-L$with_geotiff/lib)
-
-  if test $GEOTIFF_SETTING = "external" ; then
-    LIBS="-L$with_geotiff/lib -lgeotiff $LIBS"
-    if test  -d $with_geotiff/include ; then
-      EXTRA_INCLUDES="-I$with_geotiff/include $EXTRA_INCLUDES"
-    fi
-  else
-    dnl check if $with_geotiff itself contains the header and library (e.g. as an uninstalled build directory would)
-    AC_CHECK_LIB(geotiff,XTIFFClientOpen,GEOTIFF_SETTING=external,AC_MSG_ERROR([We require at least GeoTIFF 1.2.1. Consider using the one supplied with GDAL]),-L$with_geotiff)
-    if test $GEOTIFF_SETTING = "external" ; then
-      LIBS="-L$with_geotiff -lgeotiff $LIBS"
-      EXTRA_INCLUDES="-I$with_geotiff $EXTRA_INCLUDES"
-    fi
-  fi
-
-  echo "using libgeotiff from $with_geotiff."
-fi
-
-AC_SUBST(GEOTIFF_SETTING,$GEOTIFF_SETTING)
-AC_SUBST(GEOTIFF_INCLUDE,$GEOTIFF_INCLUDE)
-
-dnl ---------------------------------------------------------------------------
-dnl Select a JPEG Library to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(jpeg,[  --with-jpeg[=ARG]       Include JPEG support (ARG=internal, no or path)],,)
-
-if test "$with_jpeg" = "no" ; then
-
-  JPEG_SETTING=no
-
-  echo "jpeg support disabled."
-
-elif test "$with_jpeg" = "yes" -o "$with_jpeg" = "" ; then
-
-  AC_CHECK_LIB(jpeg,jpeg_read_scanlines,JPEG_SETTING=external,JPEG_SETTING=internal,)
-  AC_CHECK_HEADERS(jpeglib.h)
-
-  if test "$JPEG_SETTING" = "external" -a "$ac_cv_header_jpeglib_h" = "no" ; then
-    JPEG_SETTING=internal
-  fi
-
-  if test "$JPEG_SETTING" = "external" -a "$TIFF_SETTING" = "internal" ; then
-    AC_MSG_CHECKING([for width_in_blocks in jpeglib.h])
-
-    rm -f conftest.c
-    echo '#include <stdio.h>' >> conftest.c
-    echo '#include "jpeglib.h"' >> conftest.c
-    echo 'int main() { jpeg_component_info *comptr=0; int i; i = comptr->width_in_blocks; }' >> conftest.c
-    if test -z "`${CC} -o conftest conftest.c 2>&1`" ; then
-      AC_MSG_RESULT([yes])
-    else
-      AC_MSG_RESULT([no])
-      JPEG_SETTING=internal
-    fi
-    rm -f conftest*
-  fi
-
-  if test "$JPEG_SETTING" = "external" ; then
-    LIBS="-ljpeg $LIBS"
-    echo "using pre-installed libjpeg."
-  else
-    echo "using internal jpeg code."
-  fi
-
-elif test "$with_jpeg" = "internal" ; then
-
-  JPEG_SETTING=internal
-
-  echo "using internal jpeg code."
-
-else
-
-  JPEG_SETTING=external
-  LIBS="-L$with_jpeg -L$with_jpeg/lib -ljpeg $LIBS"
-  EXTRA_INCLUDES="-I$with_jpeg -I$with_jpeg/include $EXTRA_INCLUDES"
-
-  echo "using libjpeg from $with_jpeg."
-
-fi
-
-AC_SUBST(JPEG_SETTING,$JPEG_SETTING)
-
-if test "$JPEG_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="jpeg $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check for BSB in the local tree.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([jpeg12],
-	    AS_HELP_STRING([--without-jpeg12],
-	       [Disable JPEG 8/12bit TIFF support]),,)
-
-TIFF_JPEG12_ENABLED=no
-AC_MSG_CHECKING([for jpeg12])
-if test "$with_jpeg12" = yes ; then
-    AC_MSG_RESULT([enabled])
-    JPEG12_ENABLED=yes
-
-    echo '#include <stdlib.h>' > check_jpeg_abi.c
-    echo '#include <stdio.h>' >> check_jpeg_abi.c
-    echo '#include "jpeglib.h"' >> check_jpeg_abi.c
-    echo '#if JPEG_LIB_VERSION == 62' >> check_jpeg_abi.c
-    echo 'int main() { return 0; }' >> check_jpeg_abi.c
-    echo '#else' >> check_jpeg_abi.c
-    echo '#error "ABI difference"' >> check_jpeg_abi.c
-    echo '#endif' >> check_jpeg_abi.c
-    if test -z "`${CC} ${CFLAGS} ${EXTRA_INCLUDES} check_jpeg_abi.c -c -o check_jpeg_abi.o 2>&1`" ; then
-      TIFF_JPEG12_ENABLED=yes
-    else
-      TIFF_JPEG12_ENABLED=no
-      AC_MSG_WARN([Internal libjpeg12 has not the same ABI as libjpeg 8 bit. Disabling JPEG-in-TIFF 12 bit])
-    fi
-    rm -f check_jpeg_abi.*
-
-elif test x"$with_jpeg12" = x ; then
-    if test "$JPEG_SETTING" = "internal" -a "$TIFF_SETTING" = "internal" ; then
-      AC_MSG_RESULT([enabled])
-      JPEG12_ENABLED=yes
-      TIFF_JPEG12_ENABLED=yes
-    else
-      JPEG12_ENABLED=no
-      AC_MSG_RESULT([disabled, libjpeg or libtiff not internal])
-    fi
-else
-    JPEG12_ENABLED=no
-    AC_MSG_RESULT([disabled by user])
-fi
-
-AC_SUBST(JPEG12_ENABLED,$JPEG12_ENABLED)
-AC_SUBST(TIFF_JPEG12_ENABLED,$TIFF_JPEG12_ENABLED)
-
-dnl ---------------------------------------------------------------------------
-dnl Select a GIF Library to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(gif,[  --with-gif[=ARG]        Include GIF support (ARG=internal, no or path)],,)
-
-if test "$with_gif" = "no" ; then
-
-  GIF_SETTING=no
-
-  echo "gif support disabled."
-
-elif test "$with_gif" = "yes" -o "$with_gif" = "" ; then
-
-  AC_CHECK_LIB(gif,DGifOpenFileName,GIF_SETTING=external,GIF_SETTING=internal,)
-  AC_CHECK_HEADERS(gif_lib.h)
-
-  if test "$GIF_SETTING" = "external" ; then
-    LIBS="-lgif $LIBS"
-    echo "using pre-installed libgif."
-  else
-    echo "using internal gif code."
-  fi
-
-elif test "$with_gif" = "internal" ; then
-
-  GIF_SETTING=internal
-
-  echo "using internal gif code."
-
-else
-
-  GIF_SETTING=external
-  LIBS="-L$with_gif -L$with_gif/lib -lgif $LIBS"
-  EXTRA_INCLUDES="-I$with_gif -I$with_gif/include $EXTRA_INCLUDES"
-
-  echo "using libgif from $with_gif."
-
-fi
-
-AC_SUBST(GIF_SETTING,$GIF_SETTING)
-
-if test "$GIF_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="gif $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Select an OGDI Library to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-OGDI_INCLUDE=
-export OGDI_INCLUDE
-
-AC_ARG_WITH(ogdi,[  --with-ogdi[=ARG]       Include OGDI support (ARG=path)],,)
-
-if test "$with_ogdi" = "no" ; then
-
-  HAVE_OGDI=no
-
-  echo "ogdi support disabled."
-
-elif test "$with_ogdi" = "yes" -o "$with_ogdi" = "" ; then
-
-  AC_CHECK_HEADERS(ecs.h)
-
-  if test "$ac_cv_header_ecs_h" = "no" ; then
-    if test -f "/usr/include/ogdi/ecs.h"; then
-        OGDI_INCLUDE="-I/usr/include/ogdi"
-    elif test -f "/usr/local/include/ogdi/ecs.h"; then
-        OGDI_INCLUDE="-I/usr/local/include/ogdi"
-    elif test -f "/usr/include/ecs.h"; then
-        OGDI_INCLUDE="-I/usr/include"
-    elif test -f "/usr/local/include/ecs.h"; then
-        OGDI_INCLUDE="-I/usr/local/include"
-    fi
-  fi
-
-  if test "$OGDI_INCLUDE" != "" -o "$ac_cv_header_ecs_h" = "yes"; then
-    AC_CHECK_LIB(ogdi,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,)
-    if test "$HAVE_OGDI" = "yes" ; then
-      LIBS="-logdi $LIBS"
-    else
-      dnl For backward compatibility. Retry with ogdi31 as a name
-      AC_CHECK_LIB(ogdi31,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,)
-      if test "$HAVE_OGDI" = "yes" ; then
-        LIBS="-logdi31 $LIBS"
-      fi
-    fi
-  else
-    HAVE_OGDI=no
-  fi
-
-else
-
-  AC_CHECK_LIB(ogdi,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,-L$with_ogdi -L$with_ogdi/lib -logdi)
-  if test "$HAVE_OGDI" = "yes" ; then
-    if test -f "$with_ogdi/ecs.h" -o -f "$with_ogdi/include/ecs.h"; then
-        LIBS="-L$with_ogdi -L$with_ogdi/lib -logdi $LIBS"
-        OGDI_INCLUDE="-I$with_ogdi -I$with_ogdi/include"
-
-        echo "using libogdi from $with_ogdi."
-     else
-        HAVE_OGDI=no
-        AC_MSG_ERROR([ecs.h not found.])
-     fi
-  else
-    dnl For backward compatibility. Retry with ogdi31 as a name
-    AC_CHECK_LIB(ogdi31,cln_GetLayerCapabilities,HAVE_OGDI=yes,HAVE_OGDI=no,-L$with_ogdi -L$with_ogdi/lib -logdi31)
-    if test "$HAVE_OGDI" = "yes" ; then
-      if test -f "$with_ogdi/ecs.h" -o -f "$with_ogdi/include/ecs.h"; then
-        LIBS="-L$with_ogdi -L$with_ogdi/lib -logdi31 $LIBS"
-        OGDI_INCLUDE="-I$with_ogdi -I$with_ogdi/include"
-
-        echo "using libogdi31 from $with_ogdi."
-      else
-        HAVE_OGDI=no
-        AC_MSG_ERROR([ecs.h not found.])
-      fi
-    else
-      AC_MSG_ERROR([libogdi not found.])
-    fi
-  fi
-
-fi
-
-AC_SUBST(HAVE_OGDI,$HAVE_OGDI)
-AC_SUBST(OGDI_INCLUDE,$OGDI_INCLUDE)
-
-if test "$HAVE_OGDI" != "no" ; then
-  OPT_GDAL_FORMATS="ogdi $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Select FME_HOME or disable FME support.
-dnl ---------------------------------------------------------------------------
-
-X_FME_HOME=
-export X_FME_HOME
-
-AC_ARG_WITH(fme,[  --with-fme[=ARG]        Include FMEObjects support (ARG=FME_HOME path)],,)
-
-AC_MSG_CHECKING([for FMEObjects])
-
-if test "$with_fme" = "no" ; then
-
-  AC_MSG_RESULT([disabled by user])
-
-elif test "$with_fme" = "yes" ; then
-
-  if test "$FME_HOME" = "" ; then
-    AC_MSG_ERROR([no, FME_HOME not defined!])
-  elif test -f $FME_HOME/fmeobjects/cpp/isession.h ; then
-    AC_MSG_RESULT([yes])
-    X_FME_HOME=$FME_HOME
-  else
-    AC_MSG_ERROR([FME_HOME defined, but $FME_HOME/fmeobjects/cpp/issesion.h not found.])
-  fi
-
-elif test "$with_fme" = "" ; then
-
-  if test "$FME_HOME" = "" ; then
-    AC_MSG_RESULT([no])
-  elif test -f $FME_HOME/fmeobjects/cpp/isession.h ; then
-    AC_MSG_RESULT([yes])
-    X_FME_HOME=$FME_HOME
-  else
-    AC_MSG_RESULT([no, FME_HOME defined, but $FME_HOME/fmeobjects/cpp/issesion.h not found.])
-  fi
-
-else
-
-  if test -f $with_fme/fmeobjects/cpp/isession.h ; then
-    AC_MSG_RESULT([yes])
-    X_FME_HOME=$with_fme
-  else
-    AC_MSG_ERROR([$with_fme/fmeobjects/cpp/issesion.h not found!])
-  fi
-
-fi
-
-AC_SUBST(X_FME_HOME,$X_FME_HOME)
-
-dnl ---------------------------------------------------------------------------
-dnl Select a SOSI lib to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(sosi,[  --with-sosi[=ARG]        Include SOSI support (ARG=SOSI lib Path, yes or no)],,)
-
-if test -z "$with_sosi" -o "$with_sosi" = "no" ; then
-
-  SOSI_ENABLED=no
-
-  echo "SOSI support disabled."
-
-elif test "$with_sosi" = "yes" -o "$with_sosi" = "" ; then
-
-    AC_MSG_CHECKING([for libfyba.a, libfygm.a and libfyut.a in /usr/local/lib])
-    if test -r /usr/local/lib/libfyba.a -a -r /usr/local/lib/libfygm.a -a -r /usr/local/lib/libfyut.a ; then
-        AC_MSG_RESULT([found])
-        SOSI_ENABLED=yes
-        SOSI_LIB="/usr/local/lib/libfyba.a /usr/local/lib/libfygm.a /usr/local/lib/libfyut.a"
-    else
-        AC_MSG_ERROR([not found.])
-    fi
-
-    AC_MSG_CHECKING([for fyba.h, fygm.h and fyut.h in /usr/local/include/fyba])
-    if test -r /usr/local/include/fyba/fyba.h -a -r /usr/local/include/fyba/fygm.h -a -r /usr/local/include/fyba/fyut.h ; then
-        AC_MSG_RESULT([found])
-        SOSI_ENABLED=yes
-        SOSI_INC="-I/usr/local/include/fyba"
-    else
-        AC_MSG_ERROR([not found.])
-    fi
-
-else
-
-  AC_MSG_CHECKING([for libfyba.a, libfygm.a and libfyut.a in $with_sosi/lib])
-  if test -r $with_sosi/lib/libfyba.a -a -r $with_sosi/lib/libfygm.a -a -r $with_sosi/lib/libfyut.a ; then
-    AC_MSG_RESULT([found.])
-    SOSI_LIB="$with_sosi/lib/libfyba.a $with_sosi/lib/libfygm.a $with_sosi/lib/libfyut.a"
-    SOSI_ENABLED=yes
-  else
-    AC_MSG_ERROR([not found.])
-  fi
-
-  AC_MSG_CHECKING([for fyba.h in $with_sosi/include/fyba])
-  if test -r $with_sosi/include/fyba/fyba.h -a -r $with_sosi/include/fyba/fygm.h -a -r $with_sosi/include/fyba/fyut.h ; then
-    AC_MSG_RESULT([found.])
-    SOSI_INC="-I$with_sosi/include/fyba"
-    SOSI_ENABLED=yes
-  else
-    AC_MSG_ERROR([not found.])
-  fi
-
-fi
-
-AC_SUBST(SOSI_ENABLED, $SOSI_ENABLED)
-AC_SUBST(SOSI_LIB, $SOSI_LIB)
-AC_SUBST(SOSI_INC, $SOSI_INC)
-
-dnl ---------------------------------------------------------------------------
-dnl MongoCXX driver
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(mongocxx,[  --with-mongocxx[=ARG]        Include MongoCXX support (ARG=Path, yes or no)],,)
-
-MONGODB_ENABLED=no
-
-if test "$with_mongocxx" = "no" ; then
-
-  echo "MONGODB support disabled."
-
-elif test "$with_mongocxx" = "yes" -o "$with_mongocxx" = "" ; then
-
-    AC_MSG_CHECKING([for MongoCXX])
-
-    rm -f testmongocxx.*
-    rm -f testmongocxx
-    echo "#include <mongo/client/dbclient.h>" > testmongocxx.cpp
-    echo "using namespace mongo;" >> testmongocxx.cpp
-    echo "int main() { client::initialize(client::Options()); return 0; }" >> testmongocxx.cpp
-    if test -z "`${CXX} ${CPPFLAGS} testmongocxx.cpp -lmongoclient -lboost_system -lboost_thread -lboost_regex -o testmongocxx 2>&1`" ; then
-        AC_MSG_RESULT([MongoCXX found])
-        MONGODB_ENABLED="yes"
-        MONGODB_LIB=" -lmongoclient -lboost_system -lboost_thread -lboost_regex"
-    else
-        if test "$with_mongocxx" = "yes"; then
-            AC_MSG_ERROR([MongoCXX not found.])
-        else
-            AC_MSG_RESULT([MongoCXX not found.])
-        fi
-    fi
-    rm -f testmongocxx.*
-    rm -f testmongocxx
-
-else
-
-  AC_ARG_WITH(boost-lib-path,
-          [  --with-boost-lib-path=ARG   Path to boost libraries for mongocxx client],,,)
-
-  AC_MSG_CHECKING([for libmongoclient.so in in $with_mongocxx/lib])
-  MONGODB_ENABLED=yes
-  if test -r $with_mongocxx/lib/libmongoclient.so; then
-    AC_MSG_RESULT([found.])
-    MONGODB_LIB="-L$with_mongocxx/lib -lmongoclient"
-  elif test -r $with_mongocxx/lib/libmongoclient.dylib; then
-    AC_MSG_RESULT([found.])
-    MONGODB_LIB="-L$with_mongocxx/lib -lmongoclient"
-  else
-    AC_MSG_ERROR([not found.])
-  fi
-
-  if test "$with_boost_lib_path" = "" ; then
-    MONGODB_LIB="$MONGODB_LIB -lboost_system -lboost_thread -lboost_regex"
-  else
-    MONGODB_LIB="$MONGODB_LIB -L$with_boost_lib_path -lboost_system -lboost_thread -lboost_regex"
-  fi
-
-  AC_MSG_CHECKING([for mongo/client/dbclient.h in $with_mongocxx/include])
-  if test -r $with_mongocxx/include/mongo/client/dbclient.h ; then
-    AC_MSG_RESULT([found.])
-    MONGODB_INC="-I$with_mongocxx/include"
-  else
-    AC_MSG_ERROR([not found.])
-  fi
-
-fi
-
-AC_SUBST(MONGODB_ENABLED, $MONGODB_ENABLED)
-AC_SUBST(MONGODB_LIB, $MONGODB_LIB)
-AC_SUBST(MONGODB_INC, $MONGODB_INC)
-
-dnl ---------------------------------------------------------------------------
-dnl Select an HDF4 Library to use, or disable driver.
-dnl
-dnl We assume the user will have libjpeg and libz from other sources when
-dnl linking against static HDF4 libraries.
-dnl ---------------------------------------------------------------------------
-
-HDF4_INCLUDE=""
-
-AC_ARG_WITH(hdf4,[  --with-hdf4[=ARG]       Include HDF4 support (ARG=path)],,)
-
-if test x"$with_hdf4" = x"no" ; then
-
-  HAVE_HDF4=no
-
-  echo "hdf4 support disabled."
-
-else
-
-  if test x"$with_hdf4" = x"yes" -o x"$with_hdf4" = x"" ; then
-dnl Fedora has hdf static libraries in /usr/lib/hdf
-    if test -d /usr/lib64/hdf; then
-      HDF_LIB_DIR="/usr/lib64/hdf"
-    elif test -d /usr/lib/hdf; then
-      HDF_LIB_DIR="/usr/lib/hdf"
-    else
-      HDF_LIB_DIR=""
-    fi
-  else
-    if test -d $with_hdf4/lib ; then
-      HDF_LIB_DIR="$with_hdf4/lib"
-    else
-      HDF_LIB_DIR="$with_hdf4"
-    fi
-  fi
-
-  ORIG_LIBS="$LIBS"
-  if test "$HDF_LIB_DIR" != "" ; then
-    LIBS="-L$HDF_LIB_DIR $LIBS"
-  fi
-
-dnl Debian supplies the HDF4 library which does not conflict with NetCDF.
-dnl Test for Debian flavor first. Hint: install the libhdf4-alt-dev package.
-  AC_CHECK_LIB(mfhdfalt,SDreaddata,HDF_LIB_NAME="-lmfhdfalt -ldfalt",HDF_LIB_NAME=missing,-ldfalt)
-
-dnl If it fails, test again for normal libmfhdf/libdf
-  if test "$HDF_LIB_NAME" = "missing" ; then
-    unset ac_cv_lib_mfhdf_SDreaddata
-    AC_CHECK_LIB(mfhdf,SDreaddata,HDF_LIB_NAME="-lmfhdf -ldf",HDF_LIB_NAME=missing,-ldf)
-    if test "$HDF_LIB_NAME" = "missing" ; then
-      unset ac_cv_lib_mfhdf_SDreaddata
-      AC_CHECK_LIB(hdf4,SDreaddata,HDF_LIB_NAME=-lhdf4,HDF_LIB_NAME=missing,)
-    fi
-  fi
-
-dnl Test again, with -ldf, -ljpeg and -lz this time.
-  if test "$HDF_LIB_NAME" = "missing" ; then
-    unset ac_cv_lib_mfhdf_SDreaddata
-    AC_CHECK_LIB(mfhdf,SDreaddata,HDF_LIB_NAME="-lmfhdf -ldf",HDF_LIB_NAME=missing,-ldf -ljpeg -lz)
-  fi
-
-dnl Not found... again, with -lsz.
-  if test "$HDF_LIB_NAME" = "missing" ; then
-    unset ac_cv_lib_mfhdf_SDreaddata
-    AC_CHECK_LIB(mfhdf,SDreaddata,HDF_LIB_NAME="-lmfhdf -ldf -lsz",HDF_LIB_NAME=missing,-ldf -lsz -ljpeg -lz)
-  fi
-
-  if test "$HDF_LIB_NAME" != "missing" ; then
-
-    if test "$HDF_LIB_DIR" != "" ; then
-      LIBS="-L$HDF_LIB_DIR $HDF_LIB_NAME $ORIG_LIBS"
-    else
-      LIBS="$HDF_LIB_NAME $ORIG_LIBS"
-    fi
-
-    dnl HDF4 library newer than 4.2.5 has a SDreset_maxopenfiles/SDget_maxopenfiles interface
-    dnl which allows opening many HDF files simultaneously (the max number of files was previously
-    dnl hardcoded and too low, smth. like 32). Search for it and use if available.
-    AC_CHECK_LIB(mfhdfalt,SDget_maxopenfiles,HDF4_HAS_MAXOPENFILES=yes,HDF4_HAS_MAXOPENFILES=no,$HDF_LIB_NAME)
-    if test "$HDF4_HAS_MAXOPENFILES" = "no" ; then
-      AC_CHECK_LIB(mfhdf,SDget_maxopenfiles,HDF4_HAS_MAXOPENFILES=yes,HDF4_HAS_MAXOPENFILES=no,$HDF_LIB_NAME)
-    fi
-
-  dnl Now search for headers
-    if test "$with_hdf4" = "yes" -o "$with_hdf4" = "" -a -r /usr/include/hdf/hdf.h ; then
-      HDF4_INCLUDE="-I/usr/include/hdf"
-    elif test -r "$with_hdf4/hdf/hdf.h" ; then
-      HDF4_INCLUDE="-I$with_hdf4/hdf"
-    elif test -r "$with_hdf4/include/hdf/hdf.h" ; then
-      HDF4_INCLUDE="-I$with_hdf4/include/hdf"
-    elif test -r "$with_hdf4/include/hdf.h" ; then
-      HDF4_INCLUDE="-I$with_hdf4/include"
-    elif test -r "$with_hdf4/hdf.h" ; then
-      HDF4_INCLUDE="-I$with_hdf4"
-    fi
-
-    HAVE_HDF4=yes
-
-  else
-
-    if test x"$with_hdf4" != x"" ; then
-      AC_MSG_ERROR([HDF4 support requested with arg "$with_hdf4", but neither hdf4 nor mfhdf lib found])
-    else
-      LIBS="$ORIG_LIBS"
-      HAVE_HDF4=no
-    fi
-
-  fi
-
-fi
-
-AC_SUBST(HAVE_HDF4,$HAVE_HDF4)
-AC_SUBST(HDF4_INCLUDE,$HDF4_INCLUDE)
-AC_SUBST(HDF4_HAS_MAXOPENFILES,$HDF4_HAS_MAXOPENFILES)
-
-if test "$HAVE_HDF4" != "no" ; then
-  OPT_GDAL_FORMATS="hdf4 $OPT_GDAL_FORMATS"
-fi
-
-
-dnl ---------------------------------------------------------------------------
-dnl Select an HDF5 Library to use, or disable driver.
-dnl
-dnl ---------------------------------------------------------------------------
-
-HDF5_INCLUDE=""
-
-AC_ARG_WITH(hdf5,[  --with-hdf5[=ARG]       Include HDF5 support (ARG=path)],,)
-
-if test "$with_hdf5" = "no" ; then
-
-  HAVE_HDF5=no
-
-  echo "hdf5 support disabled."
-
-elif test "$with_hdf5" = "yes" -o "$with_hdf5" = "" ; then
-
-  AC_CHECK_LIB(hdf5,H5Fopen,HAVE_HDF5=yes,HAVE_HDF5=no,)
-
-  if test "$HAVE_HDF5" = "yes" ; then
-    LIBS="-lhdf5 $LIBS"
-  fi
-
-dnl Some Linux distros install hdf include files here.
-  if test "$HAVE_HDF5" = "yes" -a -r /usr/include/hdf5.h ; then
-    HDF5_INCLUDE="-I/usr/include"
-  fi
-
-else
-
-  if test -d $with_hdf5/lib ; then
-    HDF5_LIB_DIR=$with_hdf5/lib
-  else
-    HDF5_LIB_DIR=$with_hdf5
-  fi
-
-  ORIG_LIBS="$LIBS"
-  LIBS="-L$HDF5_LIB_DIR $LIBS -lhdf5"
-
-  AC_CHECK_LIB(hdf5,H5Fopen,HDF5_LIB_NAME="-lhdf5 ",HDF5_LIB_NAME=missing,-lhdf5)
-
-  if test "$HDF5_LIB_NAME" = "missing" ; then
-    AC_MSG_ERROR([HDF5 support requested with arg $with_hdf5, but no hdf5 lib found])
-  fi
-
-  LIBS="-L$HDF5_LIB_DIR $HDF5_LIB_NAME $ORIG_LIBS"
-
-  if test -r "$with_hdf5/hdf5/hdf5.h" ; then
-    HDF5_INCLUDE="-I$with_hdf5/hdf5"
-  elif test -r "$with_hdf5/include/hdf5/hdf5.h" ; then
-    HDF5_INCLUDE="-I$with_hdf5/include/hdf5"
-  elif test -r "$with_hdf5/include/hdf5.h" ; then
-    HDF5_INCLUDE="-I$with_hdf5/include"
-  elif test -r "$with_hdf5/hdf.h" ; then
-    HDF5_INCLUDE="-I$with_hdf5"
-  fi
-
-  HAVE_HDF5=yes
-fi
-
-AC_SUBST(HAVE_HDF5,$HAVE_HDF5)
-AC_SUBST(HDF5_INCLUDE,$HDF5_INCLUDE)
-
-if test "$HAVE_HDF5" != "no" ; then
-  OPT_GDAL_FORMATS="hdf5 $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check if kealib library is available.
-dnl ---------------------------------------------------------------------------
-
-KEA_CONFIG=no
-
-AC_ARG_WITH(kea,[  --with-kea[=ARG]      Include kealib (ARG=path to kea-config) [[default=yes]]],,)
-
-if test "$with_kea" = "yes" -o "x$with_kea" = "x" ; then
-  AC_PATH_PROG(KEA_CONFIG, kea-config, no)
-else
-   KEA_CONFIG=$with_kea
-fi
-
-AC_MSG_CHECKING([for kea])
-
-if test "$KEA_CONFIG" = "no" ; then
-
-  HAVE_KEA=no
-  KEA_LIB=
-  KEA_INC=
-
-  AC_MSG_RESULT([no])
-
-else
-  if test -d $KEA_CONFIG ; then
-      AC_MSG_RESULT([no])
-      AC_MSG_ERROR([--with-kea argument is a directory.  It should be the path to the kea_config script, often somewhere like /usr/local/bin/kea_config.])
-  fi
-
-  if test \! -x $KEA_CONFIG ; then
-      AC_MSG_RESULT([no])
-      AC_MSG_ERROR([--with-kea argument is a not an executable file.  It should be the path to the kea_config script, often somewhere like /usr/local/bin/kea_config.])
-  fi
-
-  HAVE_KEA=yes
-  KEA_LIB="`$KEA_CONFIG --libs --hdflibs`"
-  KEA_INC="`$KEA_CONFIG --cflags --hdfcflags`"
-  AC_MSG_RESULT([yes])
-fi
-
-AC_SUBST(HAVE_KEA,$HAVE_KEA)
-AC_SUBST(KEA_INC,$KEA_INC)
-AC_SUBST(KEA_LIB,$KEA_LIB)
-
-if test "$HAVE_KEA" != "no" ; then
-  OPT_GDAL_FORMATS="kea $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check if netcdf library is available.
-dnl ---------------------------------------------------------------------------
-
-NETCDF_SETTING=
-NETCDF_ROOT=
-NETCDF_HAS_NC4=
-NETCDF_HAS_HDF4=
-NETCDF_NCCONFIG=
-
-AC_ARG_WITH([netcdf],[  --with-netcdf[=ARG]     Include netCDF support (ARG=no or netCDF tree prefix)],,)
-
-if test "$with_netcdf" = "no" ; then
-
-  NETCDF_SETTING=no
-
-  echo "netCDF support disabled."
-
-else
-
-  dnl find nc-config location
-  unset ac_cv_path_NETCDF_NCCONFIG
-  if test "$with_netcdf" = "yes" -o "$with_netcdf" = "" ; then
-    AC_PATH_PROG(NETCDF_NCCONFIG, nc-config, no)
-  else
-    tmp_path="$with_netcdf/bin$PATH_SEPARATOR$with_netcdf"
-    AC_PATH_PROG(NETCDF_NCCONFIG, nc-config, no, $tmp_path)
-  fi
-
-  dnl test nc-config
-  if test "$NETCDF_NCCONFIG" = "no" ; then
-    echo "        did not find nc-config, some features may be missing"
-    echo "        use --with-netcdf=/path/to/netcdf or add nc-config to PATH"
-    NETCDF_NCCONFIG=
-  elif test "`$NETCDF_NCCONFIG --version`" = "" ; then
-    echo "did not get netCDF version from $NETCDF_NCCONFIG ... using fallback"
-    NETCDF_NCCONFIG=
-  fi
-
-  dnl test linking using flags from nc-config
-  if test "$NETCDF_NCCONFIG" != "" ; then
-
-    AC_MSG_CHECKING([libnetcdf compiler and linker flags with nc-config])
-    NETCDF_VERSION=`$NETCDF_NCCONFIG --version`
-    NETCDF_PREFIX=`$NETCDF_NCCONFIG --prefix`
-    NETCDF_INCLUDEDIR=`$NETCDF_NCCONFIG --includedir`
-    NETCDF_LIBS=`$NETCDF_NCCONFIG --libs`
-    echo ""
-    AC_MSG_RESULT([ got version="$NETCDF_VERSION", prefix="$NETCDF_PREFIX",
- libs="$NETCDF_LIBS", includedir="$NETCDF_INCLUDEDIR"])
-
-    AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no], $NETCDF_LIBS)
-
-    if test "$NETCDF_SETTING" = "yes" ; then
-      EXTRA_INCLUDES="-I$NETCDF_INCLUDEDIR $EXTRA_INCLUDES"
-      NETCDF_ROOT=$NETCDF_PREFIX
-      LIBS="$NETCDF_LIBS $LIBS"
-    fi
-
-dnl previous behaviour without nc-config
-
-dnl test linking using default settings
-elif test "$with_netcdf" = "yes" -o "$with_netcdf" = "" ; then
-
-  AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no],)
-
-  if test "$NETCDF_SETTING" = "yes" ; then
-
-    dnl Fedora has netcdf headers in /usr/include/netcdf
-    if test -d /usr/include/netcdf ; then
-      EXTRA_INCLUDES="-I/usr/include/netcdf $EXTRA_INCLUDES"
-      NETCDF_ROOT="/usr"
-    dnl RHEL 5 has netcdf headers in /usr/include/netcdf-3
-    elif test -d /usr/include/netcdf-3 ; then
-      EXTRA_INCLUDES="-I/usr/include/netcdf-3 $EXTRA_INCLUDES"
-      NETCDF_ROOT="/usr"
-    dnl ubuntu and fedora have netcdf headers in /usr/include
-    elif test -f /usr/include/netcdf.h ; then
-      NETCDF_ROOT="/usr"
-    dnl try /usr/local
-    elif test -f /usr/local/include/netcdf.h ; then
-      NETCDF_ROOT="/usr/local"
-    dnl print warning if include cannot be found
-    else
-      echo "using pre-installed libnetcdf."
-      echo -n "libnetcdf is installed but its location cannot be found, "
-      echo "use --with-netcdf=/path_to_netcdf for proper support"
-    fi
-
-    LIBS="-lnetcdf $LIBS"
-    if test "$NETCDF_ROOT" != "" ; then
-      echo "using pre-installed libnetcdf from "$NETCDF_ROOT
-    fi
-
-  else
-    echo "libnetcdf not found ... netCDF support disabled"
-  fi
-
-dnl test linking using --with_netcdf dir
-else
-
-  AC_CHECK_LIB([netcdf], [nc_open], [NETCDF_SETTING=yes], [NETCDF_SETTING=no],-L$with_netcdf -L$with_netcdf/lib)
-
-  if test "$NETCDF_SETTING" = "yes" ; then
-
-    NETCDF_SETTING=yes
-    NETCDF_ROOT="$with_netcdf"
-
-    if test -d $with_netcdf/lib ; then
-      LIBS="-L$with_netcdf/lib -lnetcdf $LIBS"
-      EXTRA_INCLUDES="-I$with_netcdf/include $EXTRA_INCLUDES"
-    else
-      LIBS="-L$with_netcdf -lnetcdf $LIBS"
-      EXTRA_INCLUDES="-I$with_netcdf $EXTRA_INCLUDES"
-    fi
-
-    echo "using libnetcdf from $with_netcdf"
-
-  else
-    echo "libnetcdf not found in "$with_netcdf" ... netCDF support disabled"
-  fi
-
-fi
-
-dnl test for NC4 and HDF4 support with nc-config
-  if test "$NETCDF_SETTING" = "yes" ; then
-
-    if test "$NETCDF_NCCONFIG" != "" ; then
-
-      AC_MSG_CHECKING([for netcdf-4 (and HDF5) support in libnetcdf])
-        if test "x$($NETCDF_NCCONFIG --has-nc4)" = "xyes"; then :
-          AC_MSG_RESULT([yes])
-          NETCDF_HAS_NC4=yes
-        else
-          AC_MSG_RESULT([no])
-          NETCDF_HAS_NC4=no
-        fi
-
-      AC_MSG_CHECKING([for HDF4 support in libnetcdf])
-        if test "x$($NETCDF_NCCONFIG --has-hdf4)" = "xyes"; then :
-          AC_MSG_RESULT([yes])
-          NETCDF_HAS_HDF4=yes
-        else
-          AC_MSG_RESULT([no])
-          NETCDF_HAS_HDF4=no
-        fi
-
-    else
-      NETCDF_HAS_NC4=no
-      NETCDF_HAS_HDF4=no
-    fi
-fi
-
-fi
-
-dnl export results
-
-AC_SUBST([NETCDF_SETTING], [$NETCDF_SETTING])
-
-if test "$NETCDF_SETTING" != "no" ; then
-
-   AC_SUBST([NETCDF_ROOT], [$NETCDF_ROOT])
-   AC_SUBST([NETCDF_HAS_NC4], [$NETCDF_HAS_NC4])
-   AC_SUBST([NETCDF_HAS_HDF4], [$NETCDF_HAS_HDF4])
-
-   OPT_GDAL_FORMATS="netcdf $OPT_GDAL_FORMATS"
-
-fi
-
-
-dnl ---------------------------------------------------------------------------
-dnl Select a JasPer Library to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(jasper,[  --with-jasper[=ARG]     Include JPEG-2000 support via JasPer library (ARG=path)],,)
-
-if test "$with_jasper" = "no" ; then
-
-  HAVE_JASPER=no
-
-  AC_MSG_NOTICE([JasPer (JPEG2000) support disabled.])
-
-elif test "$with_jasper" = "yes" -o "$with_jasper" = "" ; then
-
-  AC_CHECK_LIB(jasper,jpc_decode,HAVE_JASPER=yes,HAVE_JASPER=no,)
-  AC_CHECK_LIB(jasper,jp2_decode,HAVE_JASPER=yes,HAVE_JASPER=no,)
-  AC_CHECK_LIB(jasper,pgx_decode,HAVE_JASPER=yes,HAVE_JASPER=no,)
-
-  if test "$HAVE_JASPER" = "yes" ; then
-    LIBS="-ljasper $LIBS"
-  fi
-else
-
-  HAVE_JASPER=yes
-  LIBS="-L$with_jasper -L$with_jasper/lib -ljasper $LIBS"
-  EXTRA_INCLUDES="-I$with_jasper -I$with_jasper/include $EXTRA_INCLUDES"
-
-  AC_MSG_NOTICE([using JasPer library from $with_jasper.])
-fi
-
-if test "$HAVE_JASPER" != "no" ; then
-  OPT_GDAL_FORMATS="jpeg2000 $OPT_GDAL_FORMATS"
-
-  dnl Test whether we have UUID JasPer hack
-
-  AC_CHECK_LIB(jasper,jp2_encode_uuid,HAVE_JASPER_UUID=yes,HAVE_JASPER_UUID=no,)
-
-  if test "$HAVE_JASPER_UUID" = "yes" ; then
-    AC_MSG_NOTICE([hacked JasPer version found (JasPer UUID), GeoJP2 enabled.])
-    JASPER_FLAGS=-DHAVE_JASPER_UUID
-  else
-    AC_MSG_NOTICE([hacked JasPer version not found, GeoJP2 disabled.])
-  fi
-fi
-
-AC_SUBST([HAVE_JASPER],$HAVE_JASPER)
-AC_SUBST([JASPER_FLAGS],$JASPER_FLAGS)
-
-
-dnl ---------------------------------------------------------------------------
-dnl Select a OpenJPEG Library to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(openjpeg,[  --with-openjpeg[=ARG]     Include JPEG-2000 support via OpenJPEG 2.0 library (ARG=path)],,)
-
-HAVE_OPENJPEG=no
-
-if test "$with_openjpeg" = "no" ; then
-
-  AC_MSG_NOTICE([OpenJPEG (JPEG2000) support disabled.])
-
-elif test "$with_openjpeg" = "yes" -o "$with_openjpeg" = "" ; then
-
-  AC_CHECK_HEADERS([openjpeg-2.0/openjpeg.h])
-  if test "$ac_cv_header_openjpeg_2_0_openjpeg_h" = "yes"; then
-    AC_CHECK_LIB(openjp2,opj_stream_set_user_data_length,HAVE_OPENJPEG=yes,HAVE_OPENJPEG=no,)
-    if test "$HAVE_OPENJPEG" = "yes"; then
-        LIBS="-lopenjp2 $LIBS"
-    fi
-  else
-    AC_CHECK_HEADERS([openjpeg-2.1/openjpeg.h])
-    if test "$ac_cv_header_openjpeg_2_1_openjpeg_h" = "yes"; then
-        AC_CHECK_LIB(openjp2,opj_stream_set_user_data_length,HAVE_OPENJPEG=yes,HAVE_OPENJPEG=no,)
-        if test "$HAVE_OPENJPEG" = "yes"; then
-            OPENJPEG_VERSION=20100
-            LIBS="-lopenjp2 $LIBS"
-        fi
-    fi
-  fi
-else
-
-  HAVE_OPENJPEG=yes
-  if test -r $with_openjpeg/include/openjpeg-2.0/openjpeg.h ; then
-    EXTRA_INCLUDES="-I$with_openjpeg/include $EXTRA_INCLUDES"
-  elif test -r $with_openjpeg/include/openjpeg-2.1/openjpeg.h ; then
-    OPENJPEG_VERSION=20100
-    EXTRA_INCLUDES="-I$with_openjpeg/include $EXTRA_INCLUDES"
-  else
-    AC_MSG_ERROR([openjpeg.h not found in $with_openjpeg/include/openjpeg-2.0 or $with_openjpeg/include/openjpeg-2.1])
-  fi
-
-  AC_CHECK_LIB(openjp2,opj_stream_set_user_data_length,HAVE_OPENJPEG=yes,HAVE_OPENJPEG=no,-L$with_openjpeg/lib)
-
-  if test "$HAVE_OPENJPEG" = "yes"; then
-      LIBS="-L$with_openjpeg/lib -lopenjp2 $LIBS"
-      AC_MSG_NOTICE([using OpenJPEG v2 library from $with_openjpeg.])
-  fi
-fi
-
-if test "$HAVE_OPENJPEG" != "no" ; then
-  OPT_GDAL_FORMATS="openjpeg $OPT_GDAL_FORMATS"
-fi
-
-AC_SUBST([HAVE_OPENJPEG],$HAVE_OPENJPEG)
-AC_SUBST([OPENJPEG_VERSION],$OPENJPEG_VERSION)
-
-dnl ---------------------------------------------------------------------------
-dnl Select a FGDB API to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(fgdb,[  --with-fgdb[=ARG]        Include ESRI File Geodatabase support (ARG=FGDP API Path, yes or no)],,)
-
-FGDB_ENABLED=no
-
-if test "$with_fgdb" = "no" ; then
-
-  echo "FGDB support disabled."
-
-elif test "$with_fgdb" = "yes" -o "$with_fgdb" = "" ; then
-
-    AC_MSG_CHECKING([for FileGDBAPI])
-
-    rm -f testfgdb.*
-    rm -f testfgdb
-    echo "#include <FileGDBAPI.h>" > testfgdb.cpp
-    echo "using namespace FileGDBAPI;" >> testfgdb.cpp
-    echo "int main() { Geodatabase oDB; std::wstring osStr; ::OpenGeodatabase(osStr, oDB); return 0; }" >> testfgdb.cpp
-    if test -z "`${CXX} ${CPPFLAGS} testfgdb.cpp -lFileGDBAPI -lfgdbunixrtl -o testfgdb 2>&1`" ; then
-        AC_MSG_RESULT([FileGDBAPI found])
-        FGDB_ENABLED="yes"
-        FGDB_LIB="-lFileGDBAPI -lfgdbunixrtl"
-    else
-        if test "$with_fgdb" = "yes"; then
-            AC_MSG_ERROR([FileGDBAPI not found.])
-        else
-            AC_MSG_RESULT([FileGDBAPI not found.])
-        fi
-    fi
-    rm -f testfgdb.*
-    rm -f testfgdb
-
-else
-
-  AC_MSG_CHECKING([for libFileGDBAPI.so in in $with_fgdb/lib])
-  FGDB_ENABLED=yes
-  if test -r $with_fgdb/lib/libFileGDBAPI.so -a -r $with_fgdb/lib/libfgdbunixrtl.so ; then
-    AC_MSG_RESULT([found.])
-    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdbunixrtl"
-  elif test -r $with_fgdb/lib/libFileGDBAPI.dylib -a -r $with_fgdb/lib/libfgdbunixrtl.dylib ; then
-    AC_MSG_RESULT([found.])
-    FGDB_LIB="-L$with_fgdb/lib -lFileGDBAPI -lfgdbunixrtl"
-  else
-    AC_MSG_ERROR([not found.])
-  fi
-
-  AC_MSG_CHECKING([for FileGDBAPI.h in $with_fgdb/include])
-  if test -r $with_fgdb/include/FileGDBAPI.h ; then
-    AC_MSG_RESULT([found.])
-    FGDB_INC="-I$with_fgdb/include"
-  else
-    AC_MSG_ERROR([not found.])
-  fi
-
-fi
-
-AC_SUBST(FGDB_ENABLED, $FGDB_ENABLED)
-AC_SUBST(FGDB_LIB, $FGDB_LIB)
-AC_SUBST(FGDB_INC, $FGDB_INC)
-
-dnl ---------------------------------------------------------------------------
-dnl Select a ECW Library to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-ECW_FLAGS=
-ECW_LIBS=
-ECW_INCLUDE=
-
-AC_ARG_WITH(ecw,[  --with-ecw[=ARG]        Include ECW support (ARG=ECW SDK Path, yes or no)],,)
-
-if test ! -z "`uname | grep Darwin`" ; then
-  CARBON_FRAMEWORK="-framework Carbon"
-else
-  CARBON_FRAMEWORK=
-fi
-
-if test "$with_ecw" = "no" ; then
-
-  ECW_SETTING=no
-
-  echo "ECW support disabled."
-
-elif test "$with_ecw" = "yes" -o "$with_ecw" = "" ; then
-
-  AC_CHECK_LIB(NCSEcw,NCScbmOpenFileView,ECW_SETTING=yes,ECW_SETTING=no,-lNCSCnet -lNCSUtil)
-
-  if test "$ECW_SETTING" = "yes" ; then
-    ECW_LIBS="-lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil"
-  fi
-
-  if test "$ECW_SETTING" = "no" ; then
-    AC_CHECK_LIB(ecwj2,NCScbmOpenFileView,ECW_SETTING=yes,ECW_SETTING=no,$CARBON_FRAMEWORK)
-    if test "$ECW_SETTING" = "yes" ; then
-      ECW_LIBS="-lecwj2 $CARBON_FRAMEWORK"
-    fi
-  fi
-else
-
-  AC_MSG_CHECKING([for libNCSEcw.a or libecwj2])
-  ECW_ARCH=x86
-  ECW_CONF="release"
-  ECW_FLAGS="-DLINUX -DX86 -DPOSIX -DHAVE_COMPRESS -DECW_COMPRESS_RW_SDK_VERSION"
-  ECW_FRAMEWORK_COCOA=""
-  if test "`arch`" = "x86_64" ; then
-    ECW_ARCH="x64"
-  fi
-  if test ! -z "`uname | grep Darwin`" ; then
-    ECW_ARCH=""
-    ECW_CONF=""
-    ECW_FLAGS=""
-    ECW_FRAMEWORK_COCOA=" -framework Cocoa "
-  fi
-
-  ECW_SETTING=yes
-  if test -r $with_ecw/lib/libNCSCnet.so -o -r $with_ecw/lib/libNCSCnet.dylib ; then
-    ECW_LIBS="-L$with_ecw/lib -lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil"
-    AC_MSG_RESULT([found in $with_ecw/lib.])
-  elif test -r $with_ecw/lib/libNCSCNet.so -o -r $with_ecw/lib/libNCSCNet.dylib ; then
-    ECW_LIBS="-L$with_ecw/lib -lNCSEcw -lNCSEcwC -lNCSCNet -lNCSUtil"
-    AC_MSG_RESULT([found in $with_ecw/lib.])
-  elif test -r $with_ecw/bin/libNCSEcw.so -o -r $with_ecw/bin/libNCSEcw.dylib ; then
-    ECW_LIBS="-L$with_ecw/bin -lNCSEcw -lNCSEcwC -lNCSCnet -lNCSUtil"
-    AC_MSG_RESULT([found in $with_ecw/bin.])
-  elif test -r $with_ecw/lib/libecwj2.dylib ; then
-    ECW_LIBS="-L$with_ecw/lib -lecwj2 $CARBON_FRAMEWORK"
-    AC_MSG_RESULT([found libecwj2 in $with_ecw/lib.])
-
-  # ECW SDK 5.0 style and also for the case where license type is included in path i.e. specific license type is requested.
-  elif test -r $with_ecw/lib/$ECW_ARCH/$ECW_CONF/libNCSEcw.a ; then
-    ECW_LIBDIR=$with_ecw/lib/$ECW_ARCH/$ECW_CONF
-    ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw $ECW_FRAMEWORK_COCOA"
-    AC_MSG_RESULT([found Intergraph 5.x+ SDK in ${ECW_LIBDIR}.])
- # ECWJP2 SDK 5.1 style
-  elif test -d $with_ecw; then
-    for ecw_license_type in "Desktop_Read-Write" "Server_Read-Only_EndUser" "Server_Read-Only" "Server_Read-Write" "Desktop_Read-Only"
-      do
-        ECW_LIBDIR=$with_ecw/$ecw_license_type/lib/$ECW_ARCH/$ECW_CONF
-        if test -r $ECW_LIBDIR/libNCSEcw.a; then
-          ECW_LIBS="-L$ECW_LIBDIR -lNCSEcw $ECW_FRAMEWORK_COCOA"
-          with_ecw=$with_ecw/$ecw_license_type
-          AC_MSG_RESULT([found Intergraph 5.x+ SDK in ${ECW_LIBDIR}.])
-          break
-        fi
-      done
- else
-    AC_MSG_ERROR([not found in $with_ecw.])
-  fi
-
-  AC_MSG_CHECKING([for NCSECWClient.h in $with_ecw/include])
-  if test -r $with_ecw/include/NCSECWClient.h ; then
-    AC_MSG_RESULT([found.])
-    ECW_INCLUDE="-I$with_ecw/include"
-  else
-    AC_MSG_ERROR([not found.])
-  fi
-  AC_MSG_CHECKING([for ECWJP2BuildNumber.h in $with_ecw/include])
-  if test -r $with_ecw/include/ECWJP2BuildNumber.h ; then
-    AC_MSG_RESULT([found.])
-    ECW_FLAGS="-DHAVE_ECW_BUILDNUMBER_H $ECW_FLAGS"
-  else
-    AC_MSG_RESULT([not found.])
-  fi
-fi
-
-AC_SUBST(ECW_SETTING,$ECW_SETTING)
-AC_SUBST(ECW_LIBS,$ECW_LIBS)
-AC_SUBST(ECW_FLAGS,$ECW_FLAGS)
-AC_SUBST(ECW_INCLUDE,$ECW_INCLUDE)
-
-if test "$ECW_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="ecw $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Select Kakadu library or disable driver.
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([for Kakadu JPEG2000 support])
-
-AC_ARG_WITH(kakadu,[  --with-kakadu[=ARG]     Include Kakadu/JPEG2000 support],,)
-
-if test "$with_kakadu" = "no" -o "$with_kakadu" = "" ; then
-  KAKDIR=
-  AC_MSG_RESULT([not requested.])
-  HAVE_KAKADU=no
-elif test "$with_kakadu" = "yes" ; then
-  AC_MSG_ERROR([
-For JPEG2000 support using Kakadu you need provide the path to the Kakadu
-build directory.  Note that Kakadu is *not* free software.])
-else
-  KAKDIR=$with_kakadu
-  OPT_GDAL_FORMATS="jp2kak jpipkak $OPT_GDAL_FORMATS"
-  LIBS="$LIBS -L$with_kakadu/lib -lkdu"
-  AC_MSG_RESULT([requested.])
-  HAVE_KAKADU=yes
-fi
-
-AC_SUBST(KAKDIR,$KAKDIR)
-
-dnl ---------------------------------------------------------------------------
-dnl Select MrSID library or disable driver.
-dnl ---------------------------------------------------------------------------
-MRSID_FLAGS=
-HAVE_MRSID=no
-
-AC_ARG_WITH(mrsid,[  --with-mrsid[=ARG]      Include MrSID support (ARG=path to MrSID DSDK or no)],,)
-
-AC_ARG_WITH(jp2mrsid,[  --with-jp2mrsid[=ARG]   Enable MrSID JPEG2000 support (ARG=yes/no)],,)
-
-if test "x$with_mrsid" = "xno"  -o "x$with_mrsid" = "x" ; then
-
-  HAVE_MRSID=no
-
-  AC_MSG_NOTICE([MrSID support disabled.])
-
-else
-
-  MRSID_BASE="$with_mrsid/include"
-
-  AC_MSG_CHECKING([for lt_base.h in $MRSID_BASE/support])
-  if test -r "$MRSID_BASE/support/lt_base.h" ; then
-
-    AC_MSG_RESULT([found MrSID DSDK version 4.x or newer.])
-    HAVE_MRSID=yes
-    MRSID_INCLUDE="-I$MRSID_BASE/base -I$MRSID_BASE/metadata -I$MRSID_BASE/mrsid_readers -I$MRSID_BASE/j2k_readers -I$MRSID_BASE/support"
-
-  else
-
-    AC_MSG_RESULT([not found.])
-
-    AC_MSG_CHECKING([for lt_base.h in $MRSID_BASE])
-    if test -r "$MRSID_BASE/lt_base.h" ; then
-
-      AC_MSG_RESULT([found MrSID DSDK version 7.x or newer.]);
-      HAVE_MRSID=yes
-      MRSID_INCLUDE="-I$MRSID_BASE"
-
-    fi
-
-  fi
-
-  if test $HAVE_MRSID = yes ; then
-
-    MRSID_LIBS="-lpthread"
-
-    if test -r "$with_mrsid/lib/libltiesdk.a" ; then # v8+ esdk contains dsdk
-      _LIBPART=lib
-      MRSID_LIBS="-lltiesdk $MRSID_LIBS"
-    elif test -e "$with_mrsid/lib/libltidsdk.a" \
-           -o -e "$with_mrsid/lib/libltidsdk.so" \
-           -o -e "$with_mrsid/lib/libltidsdk.dylib" ; then
-      _LIBPART=lib
-      MRSID_LIBS="-lltidsdk $MRSID_LIBS"
-    else
-      _LIBPART=lib/Release
-      MRSID_LIBS="-lltidsdk $MRSID_LIBS"
-    fi
-
-    AC_MSG_CHECKING([for MG3ImageWriter.h in $with_mrsid/include/mrsid_writers])
-    if test -r "$with_mrsid/include/mrsid_writers/MG3ImageWriter.h" ; then
-      AC_MSG_RESULT([found MrSID ESDK version 4.x or newer.])
-      MRSID_FLAGS="-DMRSID_ESDK $MRSID_FLAGS"
-      MRSID_INCLUDE="-I$with_mrsid/include/mrsid_writers -I$with_mrsid/include/j2k_writers $MRSID_INCLUDE"
-      if test -r $with_mrsid/3rd-party/lib/Release/libcryptopp.a ; then
-        MRSID_LIBS="-lltiesdk -lcryptopp -lxmlparse $MRSID_LIBS"
-      else
-        MRSID_LIBS="-lltiesdk -lxmlparse $MRSID_LIBS"
-      fi
-    else
-      AC_MSG_RESULT([no encoding support.])
-    fi
-
-    AC_MSG_CHECKING([for MrSID JPEG2000 support])
-    if test "x$with_jp2mrsid" = "xyes" -a "$HAVE_KAKADU" = "yes" ; then
-      # SDK v8 or later don't seem to conflict with Kakadu
-      major_version=`cat $with_mrsid/include/lti_version.h | grep MAJOR | sed 's/#define LTI_SDK_MAJOR[ ]*\(.*\)/\1/'`
-      if test "x$major_version" != "x"; then
-        if test "$major_version" -ge 8; then
-            V8_OR_LATER=yes
-        fi
-      fi
-      if test "x$V8_OR_LATER" = "x"; then
-        AC_MSG_ERROR([MrSID JPEG2000 support requested, but this is incompatible with use of standalone Kakadu])
-      fi
-    fi
-
-    MRSID_KAKADU_LIB=""
-    if test "$HAVE_KAKADU" = "no" ; then
-      if test x"$with_jp2mrsid" = x"" -o x"$with_jp2mrsid" = x"yes" ; then
-        if test -r "$with_mrsid/3rd-party/$_LIBPART/libltikdu.a" ; then
-          with_jp2mrsid=yes
-          MRSID_KAKADU_LIB=-lltikdu
-        elif test -r "$with_mrsid/3rd-party/$_LIBPART/liblt_kakadu.a" ; then
-          with_jp2mrsid=yes
-          MRSID_KAKADU_LIB=-llt_kakadu
-        elif test -e "$with_mrsid/lib/libltidsdk.so" \
-               -o -e "$with_mrsid/lib/libltidsdk.dylib"; then # v8+ .so has kdu
-          with_jp2mrsid=yes
-        elif test x"$with_jp2mrsid" = x"yes" ; then
-          AC_MSG_ERROR([MrSID JPEG2000 support requested, but libltikdu.a not found.])
-        else
-          with_jp2mrsid=no
-        fi
-      fi
-    fi
-
-    if test "x$with_jp2mrsid" = "xyes" ; then
-      MRSID_LIBS="$MRSID_LIBS $MRSID_KAKADU_LIB"
-      MRSID_FLAGS="-DMRSID_J2K $MRSID_FLAGS"
-      AC_MSG_RESULT([enabled])
-    else
-      AC_MSG_RESULT([disabled])
-    fi
-
-    MRSID_LIBS="-L$with_mrsid/$_LIBPART $MRSID_LIBS"
-    MRSID_LIBS="-L$with_mrsid/3rd-party/$_LIBPART $MRSID_LIBS"
-
-  else
-    HAVE_MRSID=no
-    AC_MSG_RESULT([not found.])
-    AC_MSG_ERROR([  MrSID requested, but components not found.])
-  fi
-fi
-
-AC_SUBST(MRSID_INCLUDE,$MRSID_INCLUDE)
-AC_SUBST(MRSID_FLAGS,$MRSID_FLAGS)
-AC_SUBST(MRSID_LIBS,$MRSID_LIBS)
-
-if test "$HAVE_MRSID" != "no" ; then
-  CPPFLAGS="-D_REENTRANT $CPPFLAGS"
-  OPT_GDAL_FORMATS="mrsid $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Select MrSID/MG4 Lidar library or disable driver.
-dnl ---------------------------------------------------------------------------
-
-MRSID_LIDAR_FLAGS=
-HAVE_MRSID_LIDAR=no
-
-AC_ARG_WITH(mrsid_lidar,[  --with-mrsid_lidar[=ARG]      Include MrSID/MG4 LiDAR support (ARG=path to LizardTech LiDAR SDK or no)],,)
-
-if test "x$with_mrsid_lidar" = "xno"  -o "x$with_mrsid_lidar" = "x" ; then
-  HAVE_MRSID_LIDAR=no
-  AC_MSG_NOTICE([MrSID/MG4 Lidar support disabled.])
-else
-  MRSID_LIDAR_BASE="$with_mrsid_lidar"
-
-  if test -r "$MRSID_LIDAR_BASE/include/lidar/Version.h" ; then
-    AC_MSG_RESULT([found LizardTech LiDAR SDK 1.1 or newer.])
-    HAVE_MRSID_LIDAR=yes
-  else
-    HAVE_MRSID_LIDAR=no
-    AC_MSG_RESULT([not found.])
-    AC_MSG_ERROR([  MrSID/MG4 Lidar requested, but components not found.])
-  fi
-
-  if test $HAVE_MRSID_LIDAR = yes ; then
-    if test -e "$MRSID_LIDAR_BASE/lib/liblti_lidar_dsdk.so" \
-         -o -e "$MRSID_LIDAR_BASE/lib/liblti_lidar_dsdk.dylib"; then
-      MRSID_LIDAR_LIBS="-L$MRSID_LIDAR_BASE/lib -llti_lidar_dsdk"
-      MRSID_LIDAR_INCLUDE="-I$MRSID_LIDAR_BASE/include"
-    else
-      MRSID_LIDAR_LIBS="-L$MRSID_LIDAR_BASE/lib/Release -llti_lidar_dsdk"
-      MRSID_LIDAR_INCLUDE="-I$MRSID_LIDAR_BASE/include"
-    fi
-  fi
-fi
-
-AC_SUBST(MRSID_LIDAR_INCLUDE,$MRSID_LIDAR_INCLUDE)
-AC_SUBST(MRSID_LIDAR_LIBS,$MRSID_LIDAR_LIBS)
-
-if test "$HAVE_MRSID_LIDAR" != "no" ; then
-  OPT_GDAL_FORMATS="mrsid_lidar $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Enable MSG format if EUMETSAT Wavelet Transform Software
-dnl available in the local tree
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([msg],
-	    AS_HELP_STRING([--with-msg[=ARG]],
-	       [Enable MSG driver (ARG=yes or no)]),,)
-
-HAVE_MSG=no
-HAVE_EUMETSATWT=no
-
-if test "x$with_msg" = "xyes" ; then
-    AC_MSG_CHECKING([for EUMETSAT Wavelet Transformation Software])
-
-    if test -d "frmts/msg/PublicDecompWT" -a \
-        -f "frmts/msg/PublicDecompWT/COMP/Inc/CImage.h"; then
-        HAVE_EUMETSATWT=yes
-    else
-        HAVE_EUMETSATWT=no
-    fi
-    AC_MSG_RESULT([$HAVE_EUMETSATWT])
-fi
-
-AC_MSG_CHECKING([for MSG])
-
-if test "x$with_msg" = "xyes" -o "x$with_msg" = "x" \
-    -a "x$HAVE_EUMETSATWT" = "xyes"; then
-    OPT_GDAL_FORMATS="msg $OPT_GDAL_FORMATS"
-    HAVE_MSG=yes
-    AC_MSG_RESULT([enabled])
-else
-    HAVE_MSG=no
-    AC_MSG_RESULT([not requested])
-fi
-
-
-dnl ---------------------------------------------------------------------------
-dnl Check for BSB in the local tree.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([bsb],
-	    AS_HELP_STRING([--without-bsb],
-	       [Disable BSB driver (legal issues pending]),,)
-
-AC_MSG_CHECKING([for BSB])
-if test "$with_bsb" = yes -o x"$with_bsb" = x ; then
-    OPT_GDAL_FORMATS="bsb $OPT_GDAL_FORMATS"
-    AC_MSG_RESULT([enabled])
-else
-    AC_MSG_RESULT([disabled by user])
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check for GeoRaster in the local tree.
-dnl ---------------------------------------------------------------------------
-
-ORACLE_OCI_REQ_VERSION="10.0.1"
-AX_LIB_ORACLE_OCI($ORACLE_OCI_REQ_VERSION)
-
-if test "$HAVE_ORACLE_OCI" = "yes"; then
-    OPT_GDAL_FORMATS="georaster $OPT_GDAL_FORMATS"
-    HAVE_GEORASTER=yes
-else
-    HAVE_GEORASTER=no
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check for GRIB in the local tree.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([grib],
-	    AS_HELP_STRING([--without-grib],
-	       [Disable GRIB driver]),,)
-
-AC_MSG_CHECKING([for GRIB])
-if test "$with_grib" = yes -o x"$with_grib" = x ; then
-    OPT_GDAL_FORMATS="grib $OPT_GDAL_FORMATS"
-    HAVE_GRIB=yes
-    AC_MSG_RESULT([enabled])
-else
-    HAVE_GRIB=no
-    AC_MSG_RESULT([disabled by user])
-fi
-
-
-dnl ---------------------------------------------------------------------------
-
-AC_SUBST([OPT_GDAL_FORMATS], [$OPT_GDAL_FORMATS])
-
-dnl ---------------------------------------------------------------------------
-
-dnl Always build with OGR support.
-OGR_ENABLED=yes
-
-dnl ---------------------------------------------------------------------------
-
-GNM_ENABLED=no
-
-AC_ARG_WITH(gnm,[  --with-gnm            Build GNM into shared library],,)
-
-if test "$with_gnm" = "" ; then
-  GNM_ENABLED=no
-  echo "GNM support disabled."
-elif test "$with_gnm" = "yes"; then
-  echo checking for GNM ... enabled
-  GNM_ENABLED=yes
-else
-  echo checking for GNM ... disabled by user
-  GNM_ENABLED=no
-fi
-AC_SUBST(GNM_ENABLED,$GNM_ENABLED)
-
-dnl ---------------------------------------------------------------------------
-dnl Select an MySQL Library to use, or disable driver.
-dnl ---------------------------------------------------------------------------
-
-MYSQL_CONFIG=no
-
-AC_ARG_WITH(mysql,[  --with-mysql[=ARG]      Include MySQL (ARG=path to mysql_config) [[default=no]]],,)
-
-if test "$with_mysql" = "yes" ; then
-  AC_PATH_PROG(MYSQL_CONFIG, mysql_config, no)
-else
-    if test "x$with_mysql" != "x" ; then
-      MYSQL_CONFIG=$with_mysql
-    fi
-fi
-
-AC_MSG_CHECKING([for MySQL])
-
-if test "$MYSQL_CONFIG" = "no" ; then
-
-  HAVE_MYSQL=no
-  MYSQL_LIB=
-  MYSQL_INC=
-
-  AC_MSG_RESULT([no])
-
-else
-  if test -d $MYSQL_CONFIG ; then
-      AC_MSG_RESULT([no])
-      AC_MSG_ERROR([--with-mysql argument is a directory.  It should be the path to the mysql_config script, often somewhere like /usr/local/bin/mysql_config.])
-  fi
-
-  if test \! -x $MYSQL_CONFIG ; then
-      AC_MSG_RESULT([no])
-      AC_MSG_ERROR([--with-mysql argument is a not an executable file.  It should be the path to the mysql_config script, often somewhere like /usr/local/bin/mysql_config.])
-  fi
-
-  MYSQL_VERSION="`$MYSQL_CONFIG --version`"
-  MYSQL_MAJOR_VERSION=${MYSQL_VERSION%%'.'*}
-
-  if test $MYSQL_MAJOR_VERSION -le 3 ; then
-    HAVE_MYSQL=no
-    AC_MSG_RESULT([no, mysql is pre-4.x])
-  else
-      HAVE_MYSQL=yes
-      MYSQL_LIB="`$MYSQL_CONFIG --libs`"
-      MYSQL_INC="`$MYSQL_CONFIG --include`"
-      AC_MSG_RESULT([yes])
-  fi
-fi
-
-AC_SUBST(HAVE_MYSQL,$HAVE_MYSQL)
-AC_SUBST(MYSQL_INC,$MYSQL_INC)
-AC_SUBST(MYSQL_LIB,$MYSQL_LIB)
-
-dnl ---------------------------------------------------------------------------
-dnl INGRES support.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(ingres,[  --with-ingres=ARG     Include Ingres (ARG=$II_SYSTEM)],,)
-
-AC_MSG_CHECKING([for Ingres])
-
-if test "$with_ingres" = "no" -o "x$with_ingres" = "x" ; then
-  HAVE_INGRES=no
-  II_SYSTEM=
-  INGRES_LIB=
-  INGRES_INC=
-  AC_MSG_RESULT([no])
-elif test "$with_ingres" = "yes" ; then
-  AC_MSG_ERROR([--with-ingres requires a path argument ($II_SYSTEM)])
-else
-  HAVE_INGRES=yes
-  II_SYSTEM=$with_ingres
-  INGRES_LIB="-L$II_SYSTEM/ingres/lib \
-	-liiapi.1 -lcompat.1 -lq.1 -lframe.1"
-  INGRES_INC=-I$II_SYSTEM/ingres/files
-fi
-
-AC_SUBST(HAVE_INGRES,$HAVE_INGRES)
-AC_SUBST(II_SYSTEM,$II_SYSTEM)
-AC_SUBST(INGRES_LIB,$INGRES_LIB)
-AC_SUBST(INGRES_INC,$INGRES_INC)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for Xerces C++ Parser support.
-dnl ---------------------------------------------------------------------------
-
-XERCES_REQ_VERSION="2.7.0"
-AX_LIB_XERCES($XERCES_REQ_VERSION)
-
-if test "$HAVE_XERCES" = "yes"; then
-    LIBS="$XERCES_LDFLAGS $LIBS"
-fi
-
-AC_SUBST([HAVE_XERCES], $HAVE_XERCES)
-AC_SUBST([XERCES_INCLUDE], $XERCES_CFLAGS)
-
-dnl ---------------------------------------------------------------------------
-dnl Enable NAS if we have Xerces.
-dnl ---------------------------------------------------------------------------
-
-if test "$HAVE_XERCES" = "yes" ; then
-  HAVE_NAS=yes
-else
-  HAVE_NAS=no
-fi
-AC_SUBST([HAVE_NAS], $HAVE_NAS)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for Expat configuration.
-dnl ---------------------------------------------------------------------------
-
-dnl Expat 1.95.0 released in 2000-09-28
-EXPAT_REQ_VERSION="1.95.0"
-AX_LIB_EXPAT($EXPAT_REQ_VERSION)
-
-if test "$HAVE_EXPAT" = "yes"; then
-    LIBS="$EXPAT_LDFLAGS $LIBS"
-fi
-
-AC_SUBST([HAVE_EXPAT], $HAVE_EXPAT)
-AC_SUBST([EXPAT_INCLUDE], $EXPAT_CFLAGS)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for Google libkml support.
-dnl ---------------------------------------------------------------------------
-
-LIBKML_REQ_VERSION="1.3.0"
-AX_LIB_LIBKML($LIBKML_REQ_VERSION)
-
-if test "$HAVE_LIBKML" = "yes"; then
-    LIBS="$LIBKML_LDFLAGS $LIBS"
-fi
-
-AC_SUBST([HAVE_LIBKML], $HAVE_LIBKML)
-AC_SUBST([LIBKML_INCLUDE], $LIBKML_CFLAGS)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for ODBC support.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(odbc,[  --with-odbc[=ARG]       Include ODBC support (ARG=no or path)],,)
-
-if test "$with_odbc" = "no" ; then
-
-  ODBC_SETTING=no
-
-  echo "ODBC support disabled."
-
-elif test "$with_odbc" = "yes" -o "$with_odbc" = "" ; then
-  ODBC_SETTING=no
-
-  echo "check for unixODBC"
-  AC_CHECK_LIB(odbc,SQLConnect,[ODBC_LIBS="-lodbc -lodbcinst"])
-  AC_CHECK_LIB(odbcinst,SQLInstallDriverEx,ODBC_SETTING=yes)
-
-  if test "$ODBC_SETTING" = "no" ; then
-    echo "check for windows ODBC"
-    AC_CHECK_LIB(odbc32,main,[ODBC_LIBS="-lodbc32 -lodbccp32"])
-    AC_CHECK_LIB(odbccp32,SQLInstallDriverEx,ODBC_SETTING=yes)
-  fi
-
-  if test "$ODBC_SETTING" = "yes" ; then
-    AC_CHECK_HEADERS(sql.h,,[ODBC_SETTING=no],
-[#ifdef _WIN32
-# include <windows.h>
-#endif
-])
-    if test "$ODBC_SETTING" = "no" ; then
-      if test -f /usr/local/include/sql.h ; then
-        ODBC_SETTING=yes
-        echo "using sql.h from /usr/local/include"
-      elif test -f /usr/include/sql.h ; then
-        ODBC_SETTING=yes
-        echo "using sql.h from /usr/include"
-      else
-        echo "sql.h not found"
-      fi
-    fi
-  fi
-
-  if test "$ODBC_SETTING" = "yes"  ; then
-    LIBS="$ODBC_LIBS $LIBS"
-  fi
-
-else
-
-  ODBC_SETTING=yes
-  ODBC_LIBS=""
-  AC_CHECK_LIB(odbc,SQLConnect,ODBC_LIBS="-lodbc -lodbcinst")
-  AC_CHECK_LIB(odbc32,main,ODBC_LIBS="-lodbc32 -lodbccp32")
-  if test "$ODBC_LIBS" = ""; then
-    AC_MSG_ERROR([Cannot find ODBC libs])
-  fi
-  LIBS="-L$with_odbc -L$with_odbc/lib $ODBC_LIBS $LIBS"
-  EXTRA_INCLUDES="-I$with_odbc -I$with_odbc/include $EXTRA_INCLUDES"
-
-  echo "using odbc library from $with_odbc."
-fi
-
-AC_SUBST(ODBC_SETTING,$ODBC_SETTING)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for OCI support.
-dnl ---------------------------------------------------------------------------
-
-ORACLE_OCI_REQ_VERSION="8.1.7"
-AX_LIB_ORACLE_OCI($ORACLE_OCI_REQ_VERSION)
-
-if test "$HAVE_ORACLE_OCI" = "yes"; then
-    OCI_INCLUDE="$ORACLE_OCI_CFLAGS"
-    LIBS="$ORACLE_OCI_LDFLAGS $LIBS"
-fi
-
-AC_SUBST([HAVE_OCI], [$HAVE_ORACLE_OCI])
-AC_SUBST([OCI_INCLUDE], $[OCI_INCLUDE])
-
-dnl ---------------------------------------------------------------------------
-dnl Check for DODS.
-dnl ---------------------------------------------------------------------------
-
-HAVE_DODS=no
-
-AC_MSG_CHECKING(for DODS)
-AC_ARG_WITH(dods_root,
-    [  --with-dods-root[=ARG]  Include DODS support (ARG=no or absolute path)],
-    ,,)
-
-if test -z "$with_dods_root" -o "$with_dods_root" = "no"; then
-    AC_MSG_RESULT(disabled)
-elif test "$with_dods_root" = "yes" ; then
-    AC_MSG_ERROR([--with-dods-root requires path to dods root as argument])
-else
-    DODS_LIB=$with_dods_root/lib
-    DODS_INC="-I$with_dods_root/include -I$with_dods_root/include/libdap -I$with_dods_root/include/dap"
-    DODS_BIN=$with_dods_root/bin
-
-    dnl Check libdap version the sane way (if possible through dap-config)
-    if test -x $DODS_BIN/dap-config ; then
-        LIBDAP_VER=`${DODS_BIN}/dap-config --version |awk '{print \$2}'`
-        LIBDAP_CFLAGS=`${DODS_BIN}/dap-config --cflags`
-        dnl The dods driver needs LIBDAP_320 and LIBDAP_39 defined to include the right headers
-        DODS_INC="$DODS_INC $LIBDAP_CFLAGS -DLIBDAP_310 -DLIBDAP_39"
-        dnl libs from dap-config gets added further down
-        AC_MSG_RESULT([libdap $LIBDAP_VER])
-    else
-        dnl Check the version by compiling test programs
-
-        dnl Test if we have libdap >= 3.10
-        dnl From libdap 3.10, AISConnect.h has been renamed as Connect.h
-        rm -f islibdappost310.*
-        echo '#include "Connect.h"' > islibdappost310.cpp
-        echo 'int main(int argc, char** argv) { return 0; } ' >> islibdappost310.cpp
-        if test -z "`${CXX} islibdappost310.cpp -c ${DODS_INC} ${CPPFLAGS} 2>&1`" ; then
-        dnl yes, libdap >= 3.10
-            DODS_INC="$DODS_INC -DLIBDAP_310 -DLIBDAP_39"
-            AC_MSG_RESULT([libdap >= 3.10])
-        else
-            AC_MSG_RESULT([libdap < 3.10])
-
-            dnl Test if we have libdap < 3.9
-            dnl Before libdap < 3.9, DAS derived from AttrTable class
-            dnl I wish they had defines with version numbers instead of this test !
-            rm -f islibdappre39.*
-            echo '#include "DAS.h"' > islibdappre39.cpp
-            echo '#include "AttrTable.h"' >> islibdappre39.cpp
-            echo 'using namespace libdap;' >> islibdappre39.cpp
-            echo 'int main(int argc, char** argv) { DAS oDAS; AttrTable& oAttrTable = oDAS; } ' >> islibdappre39.cpp
-            if test -z "`${CXX} islibdappre39.cpp -c ${DODS_INC} 2>&1`" ; then
-            dnl yes, libdap < 3.9
-                AC_MSG_RESULT([libdap < 3.9])
-            else
-                DODS_INC="$DODS_INC -DLIBDAP_39"
-                AC_MSG_RESULT([libdap >= 3.9])
-            fi
-            rm -f islibdappre39.*
-
-        fi
-        rm -f islibdappost310.*
-    fi
-
-
-    dnl Add the DODS libraries to LIBS
-    if test -x $DODS_BIN/opendap-config ; then
-      dnl OPeNDAP 3.4 and earlier lack opendap-config, but use it if avail.
-      LIBS="$LIBS `$DODS_BIN/opendap-config --libs`"
-    elif test -x $DODS_BIN/dap-config ; then
-      dnl OPeNDAP 3.4 and earlier lack opendap-config, but use it if avail.
-      LIBS="$LIBS `$DODS_BIN/dap-config --libs`"
-    else
-      dnl Otherwise try to put things together in a more primitive way.
-      LIBS="$LIBS -L$DODS_LIB -ldap++ -lpthread -lrx"
-
-      dnl Add curl to LIBS; it might be local to DODS or generally installed
-      if test -x $DODS_BIN/curl-config; then
-          LIBS="$LIBS  `$DODS_BIN/curl-config --libs`"
-      elif which curl-config > /dev/null 2>&1; then
-          LIBS="$LIBS  `curl-config --libs`"
-      else
-          AC_MSG_ERROR([You gave a dods root, but I can't find curl!])
-      fi
-
-      if test -x $DODS_BIN/xml2-config; then
-          LIBS="$LIBS `$DODS_BIN/xml2-config --libs`"
-      elif which xml2-config > /dev/null 2>&1; then
-          LIBS="$LIBS  `xml2-config --libs`"
-      else
-          AC_MSG_ERROR([You gave a dods root, but I can't find xml2!])
-      fi
-    fi
-
-    OPT_GDAL_FORMATS="dods $OPT_GDAL_FORMATS"
-    DODSDEF=-DFRMT_dods
-    AC_MSG_RESULT(setting DODS root directory to $with_dods_root)
-    HAVE_DODS=yes
-fi
-
-dnl This is used by the GNUmakefile in frmts/dods (via GDALmake.opt)
-AC_SUBST(DODS_INC)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for curl (i.e. for wcs).
-dnl ---------------------------------------------------------------------------
-CURL_SETTING=no
-CURL_INC=
-CURL_LIB=
-
-AC_ARG_WITH(curl,
-    [  --with-curl[=ARG]       Include curl (ARG=path to curl-config.)],,,)
-
-dnl Clear some cache variables
-unset ac_cv_path_LIBCURL
-
-if test "`basename xx/$with_curl`" = "curl-config" ; then
-  LIBCURL_CONFIG="$with_curl"
-elif test "$with_curl" = "no" ; then
-  LIBCURL_CONFIG=no
-else
-  AC_PATH_PROG(LIBCURL_CONFIG, curl-config, no)
-fi
-
-if test "$LIBCURL_CONFIG" != "no" ; then
-
-  CURL_VERNUM=`$LIBCURL_CONFIG --vernum`
-  CURL_VER=`$LIBCURL_CONFIG --version | awk '{print $2}'`
-
-  AC_MSG_RESULT([        found libcurl version $CURL_VER])
-
-  AC_CHECK_LIB(curl,curl_global_init,CURL_SETTING=yes,CURL_SETTING=no,`$LIBCURL_CONFIG --libs`)
-
-fi
-
-if test "$CURL_SETTING" = "yes" ; then
-
-  CURL_INC=`$LIBCURL_CONFIG --cflags`
-  CURL_LIB=`$LIBCURL_CONFIG --libs`
-  OPT_GDAL_FORMATS="wcs wms plmosaic wmts $OPT_GDAL_FORMATS"
-
-fi
-
-AC_SUBST(CURL_SETTING,$CURL_SETTING)
-AC_SUBST(CURL_INC,    $CURL_INC)
-AC_SUBST(CURL_LIB,    $CURL_LIB)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for libxml2.
-dnl ---------------------------------------------------------------------------
-
-HAVE_LIBXML2=no
-LIBXML2_INC=
-LIBXML2_LIB=
-
-AC_ARG_WITH(xml2,
-    [  --with-xml2[=ARG]       Include libxml2 (ARG=path to xml2-config.)],,,)
-
-if test "`basename xx/$with_xml2`" = "xml2-config" ; then
-  LIBXML2_CONFIG="$with_xml2"
-elif test "$with_xml2" = "no" ; then
-  LIBXML2_CONFIG=no
-else
-  AC_PATH_PROG(LIBXML2_CONFIG, xml2-config, no)
-fi
-
-if test "$LIBXML2_CONFIG" != "no" ; then
-
-  AC_CHECK_LIB(xml2,xmlParseDoc,HAVE_LIBXML2=yes,HAVE_LIBXML2=no,`$LIBXML2_CONFIG --libs`)
-
-fi
-
-if test "$HAVE_LIBXML2" = "yes" ; then
-
-  LIBXML2_INC=`$LIBXML2_CONFIG --cflags`
-  LIBXML2_LIB=`$LIBXML2_CONFIG --libs`
-
-fi
-
-AC_SUBST(HAVE_LIBXML2,$HAVE_LIBXML2)
-AC_SUBST(LIBXML2_INC, $LIBXML2_INC)
-AC_SUBST(LIBXML2_LIB, $LIBXML2_LIB)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for SpatiaLite.
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING(for spatialite)
-
-AC_ARG_WITH(spatialite,
-    [  --with-spatialite=ARG Include SpatiaLite support (ARG=no(default), yes, dlopen (only supported for Spatialite >= 4.1.2) or path)],
-    ,,)
-
-AC_ARG_WITH(spatialite-soname,
-    [  --with-spatialite-soname=ARG Spatialite shared object name (e.g. libspatialite.so), only used if --with-spatiliate=dlopen],
-    ,,)
-
-HAVE_SPATIALITE=no
-SPATIALITE_AMALGAMATION=no
-
-if test -z "$with_spatialite" -o "$with_spatialite" = "no"; then
-    AC_MSG_RESULT(disabled)
-elif test "$with_spatialite" = "yes"; then
-    AC_CHECK_HEADERS(sqlite3.h)
-    if test "$ac_cv_header_sqlite3_h" = "yes"; then
-        AC_MSG_CHECKING([for spatialite.h in /usr/include or /usr/local/include])
-        if test -f "/usr/include/spatialite.h" -o -f "/usr/local/include/spatialite.h"; then
-            AC_MSG_RESULT(found)
-            AC_CHECK_LIB(spatialite,spatialite_init,SPATIALITE_INIT_FOUND=yes,SPATIALITE_INIT_FOUND=no,)
-            if test "$SPATIALITE_INIT_FOUND" = "yes"; then
-                HAVE_SPATIALITE=yes
-                SPATIALITE_LIBS="-lspatialite -lsqlite3"
-                LIBS="$LIBS $SPATIALITE_LIBS"
-                HAVE_SQLITE3=yes
-            fi
-        else
-            AC_MSG_RESULT(not found : spatialite support disabled)
-        fi
-    fi
-elif test "$with_spatialite" = "dlopen"; then
-  HAVE_SPATIALITE=dlopen
-  AC_MSG_RESULT(dlopen)
-
-  if test "$with_spatialite_soname" != ""; then
-      SPATIALITE_SONAME="$with_spatialite_soname"
-  else
-      SPATIALITE_SONAME="spatialite.so"
-  fi
-else
-    AC_CHECK_LIB(spatialite,spatialite_init,SPATIALITE_INIT_FOUND=yes,SPATIALITE_INIT_FOUND=no,-L$with_spatialite/lib -lspatialite)
-    if test -f "$with_spatialite/include/spatialite.h" -a \
-        -f "$with_spatialite/include/spatialite/sqlite3.h" -a \
-        "$SPATIALITE_INIT_FOUND" = "yes"; then
-
-        AC_MSG_RESULT(enabled)
-        HAVE_SPATIALITE=yes
-        SPATIALITE_AMALGAMATION=yes
-
-        # SpatiaLite amalgamation availability implies SQLite availability
-        # Caution : don't include the include/spatialite subdir in the include dir
-        # as there's a spatialite.h file in it, which we don't want to include.
-        # We want to include include/spatialite.h instead !
-        SQLITE3_CFLAGS="-I$with_spatialite/include"
-        SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
-        LIBS="$LIBS $SPATIALITE_LIBS"
-        HAVE_SQLITE3=yes
-
-    elif test -f "$with_spatialite/include/spatialite.h" -a \
-        "$SPATIALITE_INIT_FOUND" = "yes"; then
-
-        SQLITE3_REQ_VERSION="3.0.0"
-        AX_LIB_SQLITE3($SQLITE3_REQ_VERSION)
-
-        if test "$HAVE_SQLITE3" = "yes"; then
-            SPATIALITE_INC="-I$with_spatialite/include"
-            HAVE_SPATIALITE=yes
-            SPATIALITE_LIBS="-L$with_spatialite/lib -lspatialite"
-            LIBS="$SQLITE3_LDFLAGS $LIBS $SPATIALITE_LIBS"
-            AC_MSG_RESULT(spatialite enabled)
-        else
-            AC_MSG_RESULT(spatialite disabled)
-        fi
-    else
-        AC_MSG_RESULT(disabled)
-    fi
-fi
-
-if test "$HAVE_SPATIALITE" = "yes"; then
-    ax_save_LIBS="${LIBS}"
-    LIBS="$SPATIALITE_LIBS"
-    AC_CHECK_LIB(spatialite,spatialite_target_cpu,SPATIALITE_412_OR_LATER=yes,SPATIALITE_412_OR_LATER=no)
-    LIBS="${ax_save_LIBS}"
-fi
-
-AC_SUBST([HAVE_SPATIALITE], $HAVE_SPATIALITE)
-AC_SUBST([SPATIALITE_SONAME], $SPATIALITE_SONAME)
-AC_SUBST([SPATIALITE_INC], $SPATIALITE_INC)
-AC_SUBST([SPATIALITE_AMALGAMATION], $SPATIALITE_AMALGAMATION)
-AC_SUBST([SPATIALITE_412_OR_LATER], $SPATIALITE_412_OR_LATER)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for SQLite (only if SpatiaLite is not detected)
-dnl ---------------------------------------------------------------------------
-
-if test "${HAVE_SPATIALITE}" = "no" -o "${HAVE_SPATIALITE}" = "dlopen" ; then
-    SQLITE3_REQ_VERSION="3.0.0"
-    AX_LIB_SQLITE3($SQLITE3_REQ_VERSION)
-
-    if test "$HAVE_SQLITE3" = "yes"; then
-        LIBS="$SQLITE3_LDFLAGS $LIBS"
-    fi
-fi
-
-if test "$HAVE_SQLITE3" = "yes"; then
-    AC_CHECK_LIB(sqlite3,sqlite3_column_table_name,SQLITE_HAS_COLUMN_METADATA=yes,SQLITE_HAS_COLUMN_METADATA=no,$LIBS)
-fi
-
-AC_SUBST([SQLITE_INC], $SQLITE3_CFLAGS)
-AC_SUBST([HAVE_SQLITE], $HAVE_SQLITE3)
-AC_SUBST([SQLITE_HAS_COLUMN_METADATA], $SQLITE_HAS_COLUMN_METADATA)
-HAVE_SQLITE=$HAVE_SQLITE3
-
-dnl ---------------------------------------------------------------------------
-dnl Check for PCRE.
-dnl ---------------------------------------------------------------------------
-
-HAVE_PCRE=no
-
-AC_ARG_WITH(pcre,
-    [  --with-pcre             Include libpcre support (REGEXP support for SQLite)],
-    ,,)
-
-if test "$with_pcre" = "no"; then
-    AC_MSG_RESULT(disabled)
-    HAVE_PCRE=no
-else
-    AC_CHECK_HEADERS([pcre.h])
-    if test "$ac_cv_header_pcre_h" = "no" ; then
-        if test "$with_pcre" = "yes"; then
-            AC_MSG_ERROR([cannot find pcre.h])
-        fi
-    else
-        AC_CHECK_LIB(pcre,pcre_compile,HAVE_PCRE=yes,HAVE_PCRE=no,)
-        if test "$HAVE_PCRE" = "yes" ; then
-            HAVE_PCRE=yes
-            LIBS="$LIBS -lpcre"
-        else
-            if test "$with_pcre" = "yes"; then
-                AC_MSG_ERROR([cannot find libpcre])
-            fi
-        fi
-    fi
-fi
-
-AC_SUBST(HAVE_PCRE)
-
-dnl ---------------------------------------------------------------------------
-dnl Check for DWGdirect.
-dnl ---------------------------------------------------------------------------
-
-DWGDIRECT=
-DWG_PLT=
-
-AC_MSG_CHECKING(Checking for DWGdirect)
-AC_ARG_WITH(dwgdirect,
-    [  --with-dwgdirect[=path] Include DWG direct support],
-    ,,)
-
-if test -z "$with_dwgdirect" -o "$with_dwgdirect" = "no"; then
-    AC_MSG_RESULT(disabled)
-    HAVE_DWGDIRECT=no
-else
-    AC_MSG_RESULT(enabled)
-
-    AC_ARG_WITH(dwgdirect,
-      [  --with-dwg-plt[=platform] DWGdirect Platform, defaults to lnxX86],
-      ,,)
-    if test "x$with_dwg_plt" != "x" ; then
-        DWG_PLT=$with_dwg_plt
-    else
-        DWG_PLT=lnxX86
-    fi
-    DWGDIRECT=$with_dwgdirect
-    HAVE_DWGDIRECT=yes
-fi
-
-dnl This is used by the GNUmakefile in frmts/dods (via GDALmake.opt)
-AC_SUBST(DWG_PLT)
-AC_SUBST(DWGDIRECT)
-
-dnl ---------------------------------------------------------------------------
-dnl Select Informix DataBlade support
-dnl ---------------------------------------------------------------------------
-
-HAVE_IDB=no
-
-AC_ARG_WITH(idb,[  --with-idb=DIR        Include Informix DataBlade support (DIR points to Informix root)],,)
-
-if test x"${with_idb}" = x"no" ; then
-  AC_MSG_NOTICE(["IBM Informix DataBlade support disabled."])
-else
-  if test x"${with_idb}" = x ; then
-    with_idb=$INFORMIXDIR
-  fi
-
-  if test -e "${with_idb}/incl/c++/it.h" ; then
-
-    LIBS_DIRS="-L${with_idb}/lib/ -L${with_idb}/lib/esql"
-    LIBS_ESQL="-lifsql -lifasf -lifgen -lifos -lifgls -lifglx ${with_idb}/lib/esql/checkapi.o"
-    LIBS_LIBMI="-L${with_idb}/lib/dmi -lifdmi"
-    LIBS_CPPIF="-L${with_idb}/lib/c++ -lifc++"
-
-    IDB_INC="-I${with_idb}/incl/ -I${with_idb}/incl/dmi -I${with_idb}/incl/c++"
-    IDB_LIB="${LIBS_DIRS} ${LIBS_ESQL} ${LIBS_LIBMI} ${LIBS_CPPIF}"
-
-    ax_save_LIBS="${LIBS}"
-    LIBS="${IDB_LIB} -ldl -lcrypt"
-    AC_CHECK_LIB(ifsql,ifx_srvinfo,HAVE_IDB=yes,HAVE_IDB=no,)
-    LIBS="${ax_save_LIBS}"
-
-  fi
-
-  if test "${HAVE_IDB}" = "yes" ; then
-    AC_MSG_NOTICE([using Informix C++ client library from $with_idb.])
-  else
-    AC_MSG_NOTICE([IBM Informix DataBlade not supported.])
-  fi
-
-fi
-
-AC_SUBST(HAVE_IDB,${HAVE_IDB})
-AC_SUBST(IDB_INC,${IDB_INC})
-AC_SUBST(IDB_LIB,${IDB_LIB})
-
-dnl ---------------------------------------------------------------------
-dnl Find ESRI SDE ONLY IF REQUESTED.
-dnl ---------------------------------------------------------------------
-
-SDE_ENABLED=no
-
-AC_CHECKING(whether we should include ESRI SDE support)
-AC_ARG_WITH(sde,
-[  --with-sde[=DIR]        Include ESRI SDE support (DIR is SDE's install dir).],,)
-
-AC_ARG_WITH(sde-version,
-[  --with-sde-version[=VERSION NUMBER]  Set ESRI SDE version number (Default is 80).],SDE_VERSION=$with_sde_version,SDE_VERSION=80)
-
-if test -z "$SDE_VERSION" -o `expr "$SDE_VERSION" \>\= 92` = 1; then
-SDE_VERSION=""
-fi
-if test "$with_sde" = "yes" ; then
-
-  AC_CHECK_LIB(sde$SDE_VERSION,SE_connection_create,SDE_ENABLED=yes,,,)
-
-  if test -n "$SDE_ENABLED" ; then
-      SDE_LIB="-lsde$SDE_VERSION -lpe$SDE_VERSION -lsg$SDE_VERSION"
-      AC_CHECK_LIB(pthread, main, SDE_LIB="$SDE_LIB -lpthread",,)
-      AC_CHECK_LIB(socket, main, SDE_LIB="$SDE_LIB -lsocket",,)
-      AC_CHECK_LIB(dl, main, SDE_LIB="$SDE_LIB -ldl",,)
-      AC_MSG_RESULT([        using ESRI SDE from system libs.])
-  else
-      AC_MSG_WARN([        ESRI SDE not found in system libs... use --with-sde=DIR.])
-  fi
-
-elif test -n "$with_sde" -a "$with_sde" != "no" ; then
-
-  SDE_DIR=$with_sde
-
-  test -f $SDE_DIR/arcsde/coverages/include/sdetype.h && SDE_INCDIR="$SDE_DIR/arcsde/coverages/include"
-  test -f $SDE_DIR/include/sdetype.h && SDE_INCDIR="$SDE_DIR/include"
-  test -f $SDE_DIR/sdetype.h && SDE_INCDIR="$SDE_DIR"
-
-  test -f $SDE_DIR/lib/libsde$SDE_VERSION.a && SDE_LIBDIR="$SDE_DIR/lib"
-  test -f $SDE_DIR/lib64/libsde$SDE_VERSION.a && SDE_LIBDIR="$SDE_DIR/lib64"
-  test -f $SDE_DIR/libsde$SDE_VERSION.a && SDE_LIBDIR="$SDE_DIR"
-
-  test -f $SDE_DIR/lib/libsde$SDE_VERSION.so -o -f $SDE_DIR/lib/libsde$SDE_VERSION.sl && SDE_LIBDIR="$SDE_DIR/lib"
-  test -f $SDE_DIR/lib64/libsde$SDE_VERSION.so -o -f $SDE_DIR/lib64/libsde$SDE_VERSION.sl && SDE_LIBDIR="$SDE_DIR/lib64"
-  test -f $SDE_DIR/libsde$SDE_VERSION.so -o -f $SDE_DIR/libsde$SDE_VERSION.sl && SDE_LIBDIR="$SDE_DIR"
-
-  if test -n "$SDE_INCDIR" -a -n "$SDE_LIBDIR" ; then
-      SDE_INC=-I$SDE_INCDIR
-      SDE_LIB="-L$SDE_LIBDIR -lsde$SDE_VERSION -lpe$SDE_VERSION -lsg$SDE_VERSION"
-      AC_CHECK_LIB(pthread, main, SDE_LIB="$SDE_LIB -lpthread",,)
-      AC_CHECK_LIB(socket, main, SDE_LIB="$SDE_LIB -lsocket",,)
-      AC_CHECK_LIB(dl, main, SDE_LIB="$SDE_LIB -ldl",,)
-  else
-      AC_MSG_ERROR("Could not find sdetype.h or libsde$SDE_VERSION.a/libsde$SDE_VERSION.so in $SDE_DIR.")
-  fi
-
-  if test "`arch`" = "x86_64" ; then
-    AC_MSG_RESULT([        Adding -DSDE64 for 64bit platform.])
-    SDE_INC="$SDE_INC -DSDE64"
-  fi
-
-  SDE_ENABLED=yes
-  OPT_GDAL_FORMATS="sde $OPT_GDAL_FORMATS"
-  AC_MSG_RESULT([        using ESRI SDE from $SDE_DIR.])
-
-else
-
-  AC_MSG_RESULT([        ESRI SDE support not requested.])
-fi
-
-AC_SUBST(SDE_ENABLED,$SDE_ENABLED)
-AC_SUBST(SDE_INC,    $SDE_INC)
-AC_SUBST(SDE_LIB,    $SDE_LIB)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if epsilon library is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(epsilon,[  --with-epsilon[=ARG]    Include EPSILON support (ARG=no, yes or libepsilon install root path)],,)
-
-EPSILON_SETTING=no
-
-if test "$with_epsilon" = "yes" ; then
-
-  AC_CHECK_LIB(epsilon,eps_read_block_header,EPSILON_SETTING=yes,EPSILON_SETTING=no,)
-
-  if test "$EPSILON_SETTING" = "yes" ; then
-    LIBS="-lepsilon $LIBS"
-  else
-    echo "libepsilon not found - EPSILON support disabled"
-  fi
-
-elif test "$with_epsilon" != "no" -a "$with_epsilon" != ""; then
-
-  AC_CHECK_LIB(epsilon,eps_read_block_header,EPSILON_SETTING=yes,EPSILON_SETTING=no,-L$with_epsilon/lib -lepsilon)
-
-  if test "$EPSILON_SETTING" = "yes" ; then
-    LIBS="-L$with_epsilon/lib -lepsilon $LIBS"
-    EXTRA_INCLUDES="-I$with_epsilon/include $EXTRA_INCLUDES"
-  else
-    echo "libepsilon not found - EPSILON support disabled"
-  fi
-
-fi
-
-if test "$EPSILON_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="epsilon $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check if webp library is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(webp,[  --with-webp[=ARG]    Include WEBP support (ARG=no, yes or libwebp install root path)],,)
-
-WEBP_SETTING=no
-
-if test "$with_webp" = "yes" ; then
-
-  AC_CHECK_LIB(webp,WebPDecodeRGB,WEBP_SETTING=yes,WEBP_SETTING=no,)
-
-  if test "$WEBP_SETTING" = "yes" ; then
-    LIBS="-lwebp $LIBS"
-  else
-    echo "libwebp not found - WEBP support disabled"
-  fi
-
-elif test "$with_webp" != "no" -a "$with_webp" != ""; then
-
-  AC_CHECK_LIB(webp,WebPDecodeRGB,WEBP_SETTING=yes,WEBP_SETTING=no,-L$with_webp/lib -lwebp)
-
-  if test "$WEBP_SETTING" = "yes" ; then
-    LIBS="-L$with_webp/lib -lwebp $LIBS"
-    EXTRA_INCLUDES="-I$with_webp/include $EXTRA_INCLUDES"
-  else
-    echo "libwebp not found - WEBP support disabled"
-  fi
-
-fi
-
-if test "$WEBP_SETTING" != "no" ; then
-  OPT_GDAL_FORMATS="webp $OPT_GDAL_FORMATS"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check if geos library is available.
-dnl ---------------------------------------------------------------------------
-
-GEOS_INIT(3.1.0)
-HAVE_GEOS_RESULT="no"
-if test "${HAVE_GEOS}" = "yes" ; then
-
-  AC_MSG_NOTICE([Using C API from GEOS $GEOS_VERSION])
-  LIBS="${GEOS_LIBS} ${LIBS}"
-  HAVE_GEOS_RESULT="yes"
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Check if QHull library is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(qhull,[  --with-qhull[=ARG]     Include QHull support (ARG=no, yes, internal)],,)
-
-QHULL_SETTING=no
-
-if test "$with_qhull" = "no" ; then
-
-  AC_MSG_NOTICE([QHull support disabled.])
-
-elif test "$with_qhull" = "yes" -o "$with_qhull" = "" ; then
-
-  # Only qhull 2012 is reliable on certain datasets. Older Ubuntu have
-  # qhull/qhull.h
-  AC_CHECK_HEADERS([qhull/libqhull.h])
-  if test "$ac_cv_header_qhull_libqhull_h" = "yes"; then
-    AC_CHECK_LIB(qhull,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
-    if test "$QHULL_SETTING" = "yes"; then
-        QHULL_SETTING=external
-        if test -f /usr/include/qhull/libqhull.h; then
-            EXTRA_INCLUDES="-I/usr/include/qhull $EXTRA_INCLUDES"
-        else
-            EXTRA_INCLUDES="-I/usr/local/include/qhull $EXTRA_INCLUDES"
-        fi
-        LIBS="-lqhull $LIBS"
-    fi
-  fi
-  AC_CHECK_HEADERS([libqhull/libqhull.h])
-  if test "$ac_cv_header_libqhull_libqhull_h" = "yes"; then
-    AC_CHECK_LIB(qhull,qh_new_qhull,QHULL_SETTING=yes,QHULL_SETTING=no,)
-    if test "$QHULL_SETTING" = "yes"; then
-        QHULL_SETTING=external
-        if test -f /usr/include/libqhull/libqhull.h; then
-            EXTRA_INCLUDES="-I/usr/include/libqhull $EXTRA_INCLUDES"
-        else
-            EXTRA_INCLUDES="-I/usr/local/include/libqhull $EXTRA_INCLUDES"
-        fi
-        LIBS="-lqhull $LIBS"
-    fi
-  fi
-
-  if test "$QHULL_SETTING" = "no" ; then
-    if test "$with_qhull" = "yes"; then
-        AC_MSG_ERROR([--with-qhull requested, but library not found!])
-    else
-        QHULL_SETTING=internal
-    fi
-  fi
-else
-  QHULL_SETTING=internal
-fi
-
-AC_SUBST([QHULL_SETTING],$QHULL_SETTING)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if opencl library is available.
-dnl ---------------------------------------------------------------------------
-
-OPENCL_SETTING=no
-OPENCL_FLAGS=
-OPENCL_LIB=
-
-AC_ARG_WITH(opencl,
-    [  --with-opencl[=ARG]       Include OpenCL (GPU) support],,,)
-
-AC_MSG_CHECKING([for OpenCL support])
-
-if test "$with_opencl" = "yes" ; then
-
-  AC_ARG_WITH(opencl-include,
-      [  --with-opencl-include=ARG OpenCL Include directory (with a CL subdirectory)],,,)
-
-  OPENCL_SETTING=yes
-
-  if test "x$with_opencl_include" = "x" ; then
-    OPENCL_FLAGS=-DHAVE_OPENCL
-    if test -z "`uname | grep Darwin`" ; then
-        AC_CHECK_HEADERS([CL/opencl.h])
-        if test "$ac_cv_header_CL_opencl_h" = "no" ; then
-            AC_MSG_ERROR([cannot find CL/opencl.h])
-        fi
-    fi
-  else
-    OPENCL_FLAGS="-I$with_opencl_include -DHAVE_OPENCL"
-  fi
-
-  AC_ARG_WITH(opencl-lib,
-      [  --with-opencl-lib=ARG   OpenCL Link Flags (i.e. -L/xxx -lOpenCL)],,,)
-
-  if test "x$with_opencl_lib" = "x" ; then
-    if test ! -z "`uname | grep Darwin`" ; then
-      OPENCL_LIB="-framework OpenCL"
-    else
-      AC_CHECK_LIB(OpenCL,clGetPlatformIDs,OPENCL_LIB=-lOpenCL,OPENCL_LIB=missing)
-      if test "$OPENCL_LIB" = "missing"; then
-        AC_MSG_ERROR([--with-opencl requested, but libraries not found!])
-      fi
-    fi
-  else
-    OPENCL_LIB="$with_opencl_lib"
-  fi
-
-fi
-
-AC_MSG_RESULT([$OPENCL_SETTING])
-
-AC_SUBST(OPENCL_FLAGS,  $OPENCL_FLAGS)
-AC_SUBST(OPENCL_LIB,    $OPENCL_LIB)
-
-
-dnl ---------------------------------------------------------------------------
-dnl Check if FreeXL library is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(freexl,[  --with-freexl[=ARG]    Include freexl support (ARG=no, yes (default) or libfreexl install path)],,)
-
-AC_MSG_CHECKING([for FreeXL support])
-
-HAVE_FREEXL=no
-FREEXL_INCLUDE=
-
-if test "$with_freexl" = "" -o "$with_freexl" = "yes" ; then
-  AC_CHECK_HEADERS(freexl.h)
-  AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl",FREEXL_LIBS=missing)
-
-  if test "$FREEXL_LIBS" = "missing"; then
-    unset ac_cv_lib_freexl_freexl_open
-    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -lm",FREEXL_LIBS=missing,-lm)
-  fi
-
-  if test "$FREEXL_LIBS" = "missing"; then
-    unset ac_cv_lib_freexl_freexl_open
-    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -liconv",FREEXL_LIBS=missing,-liconv)
-  fi
-
-  if test "$FREEXL_LIBS" = "missing"; then
-    unset ac_cv_lib_freexl_freexl_open
-    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -liconv -lm",FREEXL_LIBS=missing,-liconv -lm)
-  fi
-
-  if test "$FREEXL_LIBS" = "missing"; then
-    unset ac_cv_lib_freexl_freexl_open
-    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-lfreexl -liconv -lcharset",FREEXL_LIBS=missing,-liconv -lcharset)
-  fi
-
-  if test "$FREEXL_LIBS" != "missing" -a "$ac_cv_header_freexl_h" = "yes" ; then
-
-    # Check that freexl is recent enough
-    rm -f testrlist.*
-    echo '#include <freexl.h>' > testfreexl.c
-    echo 'int main(int argc, char** argv) { FreeXL_CellValue s; freexl_get_cell_value (0,0,0,&s); return 0; } ' >> testfreexl.c
-    if test -z "`${CC} ${CFLAGS} testfreexl.c -c 2>&1`" ; then
-        HAVE_FREEXL=yes
-        LIBS="$FREEXL_LIBS $LIBS"
-    else
-        HAVE_FREEXL=no
-        AC_MSG_RESULT([freexl too old. Needs freexl >= 1.0])
-    fi
-    rm -f testfreexl.*
-
-  else
-    HAVE_FREEXL=no
-    echo "libfreexl not found - FreeXL support disabled"
-  fi
-
-elif test "$with_freexl" != "no"; then
-
-  AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl",FREEXL_LIBS=missing,-L$with_freexl/lib)
-
-  if test "$FREEXL_LIBS" = "missing"; then
-    unset ac_cv_lib_freexl_freexl_open
-    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -lm",FREEXL_LIBS=missing,-L$with_freexl/lib -lm)
-  fi
-
-  if test "$FREEXL_LIBS" = "missing"; then
-    unset ac_cv_lib_freexl_freexl_open
-    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv",FREEXL_LIBS=missing,-L$with_freexl/lib -liconv)
-  fi
-
-  if test "$FREEXL_LIBS" = "missing"; then
-    unset ac_cv_lib_freexl_freexl_open
-    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv -lm",FREEXL_LIBS=missing,-L$with_freexl/lib -liconv -lm)
-  fi
-
-  if test "$FREEXL_LIBS" = "missing"; then
-    unset ac_cv_lib_freexl_freexl_open
-    AC_CHECK_LIB(freexl,freexl_open,FREEXL_LIBS="-L$with_freexl/lib -lfreexl -liconv -lcharset",FREEXL_LIBS=missing,-L$with_freexl/lib -liconv -lcharset)
-  fi
-
-  if test "$FREEXL_LIBS" != "missing" -a -f "$with_freexl/include/freexl.h" ; then
-
-    # Check that freexl is recent enough
-    rm -f testrlist.*
-    echo '#include <freexl.h>' > testfreexl.c
-    echo 'int main(int argc, char** argv) { FreeXL_CellValue s; freexl_get_cell_value (0,0,0,&s); return 0; } ' >> testfreexl.c
-    if test -z "`${CC} ${CFLAGS} -I$with_freexl/include testfreexl.c -c 2>&1`" ; then
-        HAVE_FREEXL=yes
-        LIBS="$FREEXL_LIBS $LIBS"
-        FREEXL_INCLUDE="-I$with_freexl/include"
-    else
-        HAVE_FREEXL=no
-        AC_MSG_RESULT([freexl too old. Needs freexl >= 1.0])
-    fi
-    rm -f testfreexl.*
-
-  else
-    HAVE_FREEXL=no
-    echo "libfreexl not found - FreeXL support disabled"
-  fi
-
-fi
-
-AC_SUBST(HAVE_FREEXL,  $HAVE_FREEXL)
-AC_SUBST(FREEXL_INCLUDE,  $FREEXL_INCLUDE)
-
-
-dnl ---------------------------------------------------------------------------
-dnl Check if libjson-c is available.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(libjson-c,[  --with-libjson-c[=ARG]       Include libjson-c support (ARG=internal or libjson-c directory)],,)
-
-if test "$with_libjson_c" = "external" -o "$with_libjson_c" = "" -o "$with_libjson_c" = "yes" ; then
-  AC_CHECK_LIB(json-c,json_object_set_serializer,LIBJSONC_SETTING=external,LIBJSONC_SETTING=internal,)
-elif test "$with_libjson_c" = "internal" ; then
-  LIBJSONC_SETTING=internal
-elif test "$with_libjson_c" != "no"; then
-  LIBS="-L$with_libjson_c/lib $LIBS"
-  AC_CHECK_LIB(json-c,json_object_set_serializer,LIBJSONC_SETTING=external,LIBJSONC_SETTING=internal,-L$with_libjson_c/lib)
-else
-  AC_MSG_ERROR([libjson-c (internal or external) is required])
-fi
-
-if test "$LIBJSONC_SETTING" = "external" ; then
-  AC_MSG_RESULT([using pre-installed libjson-c])
-  LIBS="-ljson-c $LIBS"
-  if test "$with_libjson_c" != "" -a "$with_libjson_c" != "yes" -a "$with_libjson_c" != "external" ; then
-    JSON_INCLUDE="-I$with_libjson_c/include/json-c"
-  elif test -f "/usr/include/json-c/json.h"; then
-    JSON_INCLUDE="-I/usr/include/json-c"
-  elif test -f "/usr/local/include/json-c/json.h"; then
-    JSON_INCLUDE="-I/usr/local/include/json-c"
-  else
-    AC_MSG_ERROR([could not find json-c/json.h])
-  fi
-else
-    JSON_INCLUDE="-I\$(GDAL_ROOT)/ogr/ogrsf_frmts/geojson/libjson"
-    AC_MSG_RESULT([using internal libjson-c code])
-fi
-
-AC_SUBST(LIBJSONC_SETTING,$LIBJSONC_SETTING)
-AC_SUBST(JSON_INCLUDE,$JSON_INCLUDE)
-
-
-dnl ---------------------------------------------------------------------------
-dnl Check if we must enable PAM
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([whether to enable PAM])
-
-AC_ARG_WITH(pam,[  --without-pam         Disable PAM (.aux.xml) support],,)
-
-export PAM_SETTING=
-
-if test "x$with_pam" = "xno" ; then
-  AC_MSG_RESULT([no])
-else
-  AC_MSG_RESULT([yes])
-  PAM_SETTING=-DPAM_ENABLED
-fi
-
-AC_SUBST(PAM_SETTING, $PAM_SETTING)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if the PDF driver should be built as a plugin
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([whether to build PDF driver as a plugin])
-
-AC_ARG_ENABLE(pdf_plugin,
-              AS_HELP_STRING([--enable-pdf-plugin],
-                             [enable PDF driver as a plugin (included in libgdal by default)]),,)
-
-PDF_PLUGIN=no
-if test "x$enable_pdf_plugin" = "xyes" ; then
-
-  PDF_PLUGIN=yes
-
-  AC_MSG_RESULT([yes])
-else
-  AC_MSG_RESULT([no])
-fi
-
-AC_SUBST(PDF_PLUGIN, $PDF_PLUGIN)
-
-
-dnl ---------------------------------------------------------------------------
-dnl Check if libpoppler is available
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(poppler,[  --with-poppler[=ARG]    Include poppler(for PDF) support (ARG=no(default), yes or poppler install path)],,)
-
-HAVE_POPPLER=no
-POPPLER_HAS_OPTCONTENT=no
-POPPLER_BASE_STREAM_HAS_TWO_ARGS=no
-POPPLER_0_20_OR_LATER=no
-
-AC_MSG_CHECKING([for poppler])
-
-if test "$with_poppler" != "no" -a "$with_poppler" != ""; then
-
-    if test "$with_poppler" = "yes" ; then
-        TEST_POPPLER_INC="-I/usr/include -I/usr/include/poppler"
-        TEST_POPPLER_LIB="-lpoppler"
-    else
-        TEST_POPPLER_INC="-I$with_poppler/include -I$with_poppler/include/poppler"
-        TEST_POPPLER_LIB="-L$with_poppler/lib -lpoppler"
-    fi
-
-    # Check that we can accept Page::pageObj private member
-    rm -f testpoppler.*
-    echo '#define private public' > testpoppler.cpp
-    echo '#include <poppler/Page.h>' >> testpoppler.cpp
-    echo '#include <poppler/splash/SplashBitmap.h>' >> testpoppler.cpp
-    echo 'int main(int argc, char** argv) { return &(((Page*)0x8000)->pageObj) == 0; } ' >> testpoppler.cpp
-
-    if test -z "`${CXX} testpoppler.cpp -o testpoppler ${TEST_POPPLER_INC} ${TEST_POPPLER_LIB} 2>&1`" ; then
-        HAVE_POPPLER=yes
-    else
-        # poppler 0.23.0 needs to be linked against pthread
-        TEST_POPPLER_LIB="${TEST_POPPLER_LIB} -lpthread"
-        if test -z "`${CXX} testpoppler.cpp -o testpoppler ${TEST_POPPLER_INC} ${TEST_POPPLER_LIB} 2>&1`" ; then
-            HAVE_POPPLER=yes
-        fi
-    fi
-
-    if test "$HAVE_POPPLER" = "yes"; then
-        if test "$PDF_PLUGIN" = "no"; then
-            LIBS="${TEST_POPPLER_LIB} ${LIBS}"
-        fi
-        AC_MSG_RESULT([yes])
-        POPPLER_INC=$TEST_POPPLER_INC
-        POPPLER_PLUGIN_LIB="${TEST_POPPLER_LIB}"
-
-        # And now try another dirty thing, but this one is
-        # optional.
-        AC_MSG_CHECKING([if Catalog::optContent exists])
-        rm -f testpoppler.*
-        echo '#define private public' > testpoppler.cpp
-        echo '#include <poppler/Object.h>' >> testpoppler.cpp
-        echo '#include <poppler/Catalog.h>' >> testpoppler.cpp
-        echo 'int main(int argc, char** argv) { return &(((Catalog*)0x8000)->optContent) == 0; }' >> testpoppler.cpp
-        if test -z "`${CXX} testpoppler.cpp -c ${POPPLER_INC} 2>&1`" ; then
-            POPPLER_HAS_OPTCONTENT=yes
-            AC_MSG_RESULT([yes])
-        else
-            AC_MSG_RESULT([no])
-        fi
-
-        # And now we check if we have Poppler >= 0.16.0
-        AC_MSG_CHECKING([if BaseStream constructor needs 2 arguments])
-        rm -f testpoppler.*
-        echo '#include <poppler/Object.h>' > testpoppler.cpp
-        echo '#include <poppler/Stream.h>' >> testpoppler.cpp
-        echo 'class TestStream: public BaseStream {' >> testpoppler.cpp
-        echo 'public:' >> testpoppler.cpp
-        echo '  TestStream() : BaseStream(0,0) {}' >> testpoppler.cpp
-        echo '};' >> testpoppler.cpp
-        echo 'int main(int argc, char** argv) { return 0; }' >> testpoppler.cpp
-        if test -z "`${CXX} testpoppler.cpp -c ${POPPLER_INC} 2>&1`" ; then
-            POPPLER_BASE_STREAM_HAS_TWO_ARGS=yes
-            AC_MSG_RESULT([yes])
-
-            # And now we check if we have Poppler >= 0.20.0
-            AC_MSG_CHECKING([if we have Poppler >= 0.20.0])
-            rm -f testpoppler.*
-            echo '#include <poppler/Error.h>' > testpoppler.cpp
-            echo 'int main(int argc, char** argv) { setErrorCallback(0,0); return 0; }' >> testpoppler.cpp
-            if test -z "`${CXX} testpoppler.cpp -c ${POPPLER_INC} 2>&1`" ; then
-                POPPLER_0_20_OR_LATER=yes
-                AC_MSG_RESULT([yes])
-
-                # And now we check if we have Poppler >= 0.23.0
-                AC_MSG_CHECKING([if we have Poppler >= 0.23.0])
-                rm -f testpoppler.*
-                echo '#include <poppler/Object.h>' > testpoppler.cpp
-                echo '#include <poppler/Stream.h>' >> testpoppler.cpp
-                echo 'class TestStream: public BaseStream {' >> testpoppler.cpp
-                echo 'public:' >> testpoppler.cpp
-                echo '  TestStream() : BaseStream(0,0) {}' >> testpoppler.cpp
-                echo '  ~TestStream() {}' >> testpoppler.cpp
-                echo '  virtual BaseStream *copy() { return BaseStream::copy(); }' >> testpoppler.cpp
-                echo '};' >> testpoppler.cpp
-                echo 'int main(int argc, char** argv) { return 0; }' >> testpoppler.cpp
-                if test -z "`${CXX} testpoppler.cpp -c ${POPPLER_INC} 2>&1`" ; then
-                    POPPLER_0_23_OR_LATER=yes
-                    AC_MSG_RESULT([yes])
-                else
-                    AC_MSG_RESULT([no])
-                fi
-
-            else
-                AC_MSG_RESULT([no])
-            fi
-
-        else
-            AC_MSG_RESULT([no])
-        fi
-    else
-        AC_MSG_RESULT([no])
-    fi
-    rm -f testpoppler.*
-    rm -f testpoppler
-else
-    AC_MSG_RESULT([disabled])
-fi
-
-AC_SUBST(HAVE_POPPLER, $HAVE_POPPLER)
-AC_SUBST(POPPLER_HAS_OPTCONTENT, $POPPLER_HAS_OPTCONTENT)
-AC_SUBST(POPPLER_BASE_STREAM_HAS_TWO_ARGS, $POPPLER_BASE_STREAM_HAS_TWO_ARGS)
-AC_SUBST(POPPLER_0_20_OR_LATER, $POPPLER_0_20_OR_LATER)
-AC_SUBST(POPPLER_0_23_OR_LATER, $POPPLER_0_23_OR_LATER)
-AC_SUBST(POPPLER_INC, $POPPLER_INC)
-AC_SUBST(POPPLER_PLUGIN_LIB, $POPPLER_PLUGIN_LIB)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if libpodofo is available
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(podofo,[  --with-podofo[=ARG]    Include podofo(for PDF) support (ARG=no(default), yes or podofo install path)],,)
-
-HAVE_PODOFO=no
-
-AC_MSG_CHECKING([for podofo])
-
-if test "$with_podofo" != "no" -a "$with_podofo" != ""; then
-
-    AC_ARG_WITH(podofo-lib,
-      [  --with-podofo-lib=ARG   podofo Link Flags (i.e. -L/xxx -lpodofo ...). Mainly for static libpodofo],,,)
-
-    if test "$with_podofo" = "yes" ; then
-        TEST_PODOFO_INC="-I/usr/include -I/usr/include/podofo"
-        PODOFO_LIB="-lpodofo"
-    else
-        TEST_PODOFO_INC="-I$with_podofo/include -I$with_podofo/include/podofo"
-        PODOFO_LIB="-L$with_podofo/lib -lpodofo"
-    fi
-
-    if test "x$with_podofo_lib" = "x" ; then
-        rm -f testpodofo.*
-        echo '#include <podofo.h>' > testpodofo.cpp
-        echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
-        ${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${PODOFO_LIB} 2>/dev/null
-        RETVAL=$?
-        if test $RETVAL -eq 0; then
-            HAVE_PODOFO=yes
-            if test "$PDF_PLUGIN" = "no"; then
-                LIBS="${PODOFO_LIB} ${LIBS}"
-            fi
-            PODOFO_INC=$TEST_PODOFO_INC
-            PODOFO_PLUGIN_LIB="${PODOFO_LIB}"
-            AC_MSG_RESULT([yes])
-        fi
-        rm -f testpodofo.*
-        rm -f testpodofo
-    fi
-
-    if test "$HAVE_PODOFO" = "no"; then
-        if test "x$with_podofo_lib" != "x" ; then
-            PODOFO_LIB="$with_podofo_lib"
-        else
-            # This may be a static libpodofo.a, so add dependent libraries.
-            PODOFO_LIB="$PODOFO_LIB -lfreetype -lfontconfig -lpthread"
-        fi
-
-        AC_ARG_WITH(podofo-extra-lib-for-test,
-          [  --with-podofo-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (i.e. -ljpeg ...). Mainly for static libpodofo],,,)
-
-        if test "x$with_podofo_extra_lib_for_test" = "x" ; then
-            TEST_PODOFO_LIB="$PODOFO_LIB"
-        else
-            TEST_PODOFO_LIB="$PODOFO_LIB $with_podofo_extra_lib_for_test"
-        fi
-
-        rm -f testpodofo.*
-        echo '#include <podofo.h>' > testpodofo.cpp
-        echo 'int main(int argc, char** argv) { PoDoFo::PdfError::EnableDebug( 0 ); return 0; } ' >> testpodofo.cpp
-        ${CXX} testpodofo.cpp -o testpodofo ${TEST_PODOFO_INC} ${TEST_PODOFO_LIB} 2>/dev/null
-        RETVAL=$?
-        if test $RETVAL -eq 0; then
-            HAVE_PODOFO=yes
-            if test "$PDF_PLUGIN" = "no"; then
-                LIBS="${PODOFO_LIB} ${LIBS}"
-            fi
-            PODOFO_INC=$TEST_PODOFO_INC
-            PODOFO_PLUGIN_LIB="${PODOFO_LIB}"
-            AC_MSG_RESULT([yes])
-        else
-            AC_MSG_RESULT([no])
-        fi
-        rm -f testpodofo.*
-        rm -f testpodofo
-    fi
-else
-    AC_MSG_RESULT([disabled])
-fi
-
-AC_SUBST(HAVE_PODOFO, $HAVE_PODOFO)
-AC_SUBST(PODOFO_INC, $PODOFO_INC)
-AC_SUBST(PODOFO_PLUGIN_LIB, $PODOFO_PLUGIN_LIB)
-
-dnl ---------------------------------------------------------------------------
-dnl Check if libpdfium is available
-dnl
-dnl Support for open-source PDFium library
-dnl
-dnl Copyright (C) 2015 Klokan Technologies GmbH (http://www.klokantech.com/)
-dnl Author: Martin Mikita <martin.mikita at klokantech.com>, xmikit00 @ FIT VUT Brno
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(pdfium,[  --with-pdfium[=ARG]    Include pdfium (for PDF) support (ARG=no(default), yes or pdfium install path)],,)
-
-HAVE_PDFIUM=no
-
-AC_MSG_CHECKING([for pdfium])
-
-if test "$with_pdfium" != "no" -a "$with_pdfium" != ""; then
-
-    AC_ARG_WITH(pdfium-lib,
-      [  --with-pdfium-lib=ARG   pdfium Link Flags (i.e. -L/xxx -lpdfium ...). Mainly for static libpdfium],,,)
-
-    if test "$with_pdfium" = "yes" ; then
-        TEST_PDFIUM_INC="-I/usr/include -I/usr/include/pdfium"
-        PDFIUM_LIB="-lpdfium"
-        PDFIUM_LIBDIR="/usr"
-    else
-        TEST_PDFIUM_INC="-I$with_pdfium -I$with_pdfium/include -I$with_pdfium/include/pdfium"
-        PDFIUM_LIB="-L$with_pdfium -L$with_pdfium/lib -lpdfium"
-        PDFIUM_LIBDIR="$with_pdfium"
-    fi
-
-    if test ! -z "`uname | grep Darwin`" ; then
-        PDFIUM_LIB="-stdlib=libstdc++ $PDFIUM_LIB"
-    fi
-
-    if test "x$with_pdfium_lib" = "x" ; then
-        rm -f testpdfium.*
-        echo '#include <fpdfview.h>' > testpdfium.cpp
-        echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
-        echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
-        TEST_CXX_FLAGS="-std=c++0x"
-        if test ! -z "`uname | grep Darwin`" ; then
-          TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
-        fi
-        if test -z "`${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${PDFIUM_LIB}  2>&1`" ; then
-            HAVE_PDFIUM=yes
-            CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
-            if test "$PDF_PLUGIN" = "no"; then
-                LIBS="${PDFIUM_LIB} ${LIBS}"
-            fi
-            PDFIUM_PLUGIN_LIB="${PDFIUM_LIB}"
-            PDFIUM_INC=$TEST_PDFIUM_INC
-            AC_MSG_RESULT([yes])
-        fi
-        rm -f testpdfium.*
-        rm -f testpdfium
-    fi
-
-    if test "$HAVE_PDFIUM" = "no"; then
-        if test "x$with_pdfium_lib" != "x" ; then
-            PDFIUM_LIB="$with_pdfium_lib"
-        else
-            # This may be a static libpdfium.a, so add dependent libraries.
-            PDFIUM_LIB="-L$PDFIUM_LIBDIR -L$PDFIUM_LIBDIR/lib/pdfium -lpdfium -lfpdfdoc -lfpdfapi -lfpdftext -lformfiller -lpdfwindow"
-            PDFIUM_LIB="$PDFIUM_LIB -lfxedit -lfpdfdoc -lfxcodec -lfx_libopenjpeg -lfx_lcms2 -lfx_libjpeg -lfx_zlib"
-            PDFIUM_LIB="$PDFIUM_LIB -lfdrm -lfxge -lfreetype -lfx_agg -lfxcrt -lbigint"
-            if test ! -z "`uname | grep Darwin`" ; then
-                PDFIUM_LIB="-framework AppKit -framework CoreFoundation $PDFIUM_LIB"
-            fi
-        fi
-
-        AC_ARG_WITH(pdfium-extra-lib-for-test,
-          [  --with-pdfium-extra-lib-for-test=ARG   Additional libraries to pass the detection test, but not used for libgdal linking (i.e. -ljpeg ...). Mainly for static libpdfium],,,)
-
-        if test "x$with_pdfium_extra_lib_for_test" = "x" ; then
-            TEST_PDFIUM_LIB="$PDFIUM_LIB"
-        else
-            TEST_PDFIUM_LIB="$PDFIUM_LIB $with_pdfium_extra_lib_for_test"
-        fi
-
-        rm -f testpdfium.*
-        echo '#include <fpdfview.h>' > testpdfium.cpp
-        echo '#include <core/include/fpdfapi/fpdf_page.h>' >> testpdfium.cpp
-        echo 'int main(int argc, char** argv) { FPDF_InitLibrary(); FPDF_DestroyLibrary(); return 0; } ' >> testpdfium.cpp
-        TEST_CXX_FLAGS="-std=c++0x"
-        if test ! -z "`uname | grep Darwin`" ; then
-          TEST_CXX_FLAGS="$TEST_CXX_FLAGS -stdlib=libstdc++"
-        fi
-        if test -z "`${CXX} $TEST_CXX_FLAGS testpdfium.cpp -o testpdfium ${TEST_PDFIUM_INC} ${TEST_PDFIUM_LIB} 2>&1`" ; then
-            HAVE_PDFIUM=yes
-            CXXFLAGS="$TEST_CXX_FLAGS $CXXFLAGS"
-            if test "$PDF_PLUGIN" = "no"; then
-                LIBS="${PDFIUM_LIB} ${LIBS}"
-            fi
-            PDFIUM_PLUGIN_LIB="${PDFIUM_LIB}"
-            PDFIUM_INC=$TEST_PDFIUM_INC
-            AC_MSG_RESULT([yes])
-        else
-            AC_MSG_RESULT([no])
-        fi
-        rm -f testpdfium.*
-        rm -f testpdfium
-    fi
-else
-    AC_MSG_RESULT([disabled])
-fi
-
-AC_SUBST(HAVE_PDFIUM, $HAVE_PDFIUM)
-AC_SUBST(PDFIUM_INC, $PDFIUM_INC)
-AC_SUBST(PDFIUM_PLUGIN_LIB, $PDFIUM_PLUGIN_LIB)
-
-dnl ---------------------------------------------------------------------------
-dnl PROJ.4 related stuff.
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([how to link PROJ.4 library])
-
-AC_ARG_WITH(static_proj4,[  --with-static-proj4=ARG Compile with PROJ.4 statically (ARG=no or path)],,)
-
-if test "x$with_static_proj4" = "xno" -o "x$with_static_proj4" = "x"; then
-
-  PROJ_STATIC=no
-  AC_MSG_RESULT([link dynamically.])
-
-else
-
-  PROJ_STATIC=yes
-  AC_MSG_RESULT([link statically.])
-
-  ORIG_LIBS="$LIBS"
-  PROJ_LIB="-lproj"
-
-  if test "x$with_static_proj4" = "xyes" ; then
-    LIBS="$PROJ_LIB $ORIG_LIBS"
-    AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
-  else
-
-    LIBS="-L$with_static_proj4/lib $PROJ_LIB $ORIG_LIBS"
-    AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
-
-    if test "$PROJ_STATIC" = "no"; then
-      dnl Disable previous value cached by the previous AC_CHECK_LIB test :
-      dnl AC_CHECK_LIB caches the result value for a couple (function, library)
-      dnl in a variable named "ac_cv_lib_<library name>_<function name>".
-      dnl In order to try to locate the library in different locations, using
-      dnl different values of LIBS, we have to 'unset' this variable after
-      dnl each negative test.
-
-      unset ac_cv_lib_proj_pj_init
-
-      LIBS="-L$with_static_proj4/src $PROJ_LIB $ORIG_LIBS"
-      AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
-    fi
-
-    if test "$PROJ_STATIC" = "no"; then
-      unset ac_cv_lib_proj_pj_init
-      LIBS="-L$with_static_proj4/src/.libs $PROJ_LIB $ORIG_LIBS"
-      AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
-    fi
-
-    if test "$PROJ_STATIC" = "no"; then
-      unset ac_cv_lib_proj_pj_init
-      LIBS="-L$with_static_proj4 $PROJ_LIB $ORIG_LIBS"
-      AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
-    fi
-
-    if test "$PROJ_STATIC" = "no"; then
-      unset ac_cv_lib_proj_pj_init
-      LIBS="$PROJ_LIB $ORIG_LIBS"
-      AC_CHECK_LIB(proj,pj_init,PROJ_STATIC=yes,PROJ_STATIC=no,)
-    fi
-
-  fi
-
-  if test "$PROJ_STATIC" = "no"; then
-    LIBS="$ORIG_LIBS"
-  fi
-
-  if test -r "$with_static_proj4/src/proj_api.h" ; then
-    PROJ_INCLUDE="-I$with_static_proj4/src"
-  elif test -r "$with_static_proj4/include/proj_api.h" ; then
-    PROJ_INCLUDE="-I$with_static_proj4/include"
-  elif test -r "$with_static_proj4/proj_api.h" ; then
-    PROJ_INCLUDE="-I$with_static_proj4"
-  fi
-
-fi
-
-AC_SUBST(PROJ_STATIC)
-AC_SUBST(PROJ_INCLUDE)
-
-dnl ---------------------------------------------------------------------------
-dnl Get/override version.
-dnl ---------------------------------------------------------------------------
-
-
-AC_ARG_WITH(gdal-ver,[  --with-gdal-ver=ARG   Override GDAL version ],,)
-GDAL_VERSION_MAJOR=`grep "#*define.GDAL_VERSION_MAJOR.*" gcore/gdal_version.h | awk '{print $4}'`
-GDAL_VERSION_MINOR=`grep "#*define.GDAL_VERSION_MINOR.*" gcore/gdal_version.h | awk '{print $4}'`
-GDAL_VERSION_REV=`grep "#*define.GDAL_VERSION_REV.*" gcore/gdal_version.h | awk '{print $4}'`
-
-AC_MSG_RESULT([checking GDAL version information from gdal_version.h: $GDAL_VERSION_MAJOR.$GDAL_VERSION_MINOR.$GDAL_VERSION_REV])
-
-AC_SUBST(GDAL_VERSION_MAJOR,    "$GDAL_VERSION_MAJOR")
-AC_SUBST(GDAL_VERSION_MINOR,    "$GDAL_VERSION_MINOR")
-AC_SUBST(GDAL_VERSION_REV,    "$GDAL_VERSION_REV")
-
-if test "x$with_gdal_ver" != "x"; then
-
-  GDAL_VER=$with_gdal_ver
-  AC_MSG_RESULT([  overridden GDAL version: $GDAL_VER])
-else
-
-  GDAL_VER=$GDAL_VERSION_MAJOR.$GDAL_VERSION_MINOR.$GDAL_VERSION_REV
-
-fi
-
-AC_SUBST(GDAL_VER, $GDAL_VER)
-echo $GDAL_VER > VERSION
-
-dnl ---------------------------------------------------------------------------
-dnl MacOS X Framework Build
-
-if test ! -z "`uname | grep Darwin`" ; then
-
-  CXXFLAGS="$ARCHFLAGS $CXXFLAGS"
-  CFLAGS="$ARCHFLAGS $CFLAGS"
-  LIBS="$ARCHFLAGS $LIBS"
-
-  MACOSX_FRAMEWORK=no
-  AC_ARG_WITH(,[  --with-macosx-framework         Build and install GDAL as a Mac OS X Framework],,)
-  AC_MSG_CHECKING([for Mac OS X Framework build])
-  if test "$with_macosx_framework" = yes ; then
-    MACOSX_FRAMEWORK=yes
-    AC_MSG_RESULT([enabled])
-    AC_DEFINE_UNQUOTED(MACOSX_FRAMEWORK,1, [Define for Mac OSX Framework build])
-    prefix="/Library/Frameworks/GDAL.framework/Versions/${GDAL_VERSION_MAJOR}.${GDAL_VERSION_MINOR}"
-    exec_prefix='${prefix}'
-    includedir='${prefix}/Headers'
-    datadir='${prefix}/Resources/gdal'
-    libdir='${exec_prefix}'
-    bindir='${exec_prefix}/Programs'
-    docdir='${prefix}/Resources/doc'
-    mandir='${prefix}/Resources/man'
-  else
-    AC_MSG_RESULT([disabled])
-  fi
-  AC_SUBST(MACOSX_FRAMEWORK, $MACOSX_FRAMEWORK)
-fi
-
-AC_SUBST(EXTRA_INCLUDES,$EXTRA_INCLUDES)
-
-dnl ---------------------------------------------------------------------------
-dnl Check whether we need to add specific suffix for executables (.EXE when
-dnl building for Windows). This test should work for the case of
-dnl cross-compilation too.
-dnl ---------------------------------------------------------------------------
-case "${host_os}" in
-    cygwin* | mingw32* | pw32*)
-      EXE_EXT=.exe
-      SO_EXT=dll
-      ;;
-    *)
-      EXE_EXT=
-      ;;
-esac
-
-AC_SUBST(EXE_EXT)
-AC_SUBST(SO_EXT)
-
-dnl ---------------------------------------------------------------------------
-dnl Which "true" program should we use?
-dnl ---------------------------------------------------------------------------
-BINTRUE=/bin/true
-
-if test -f /bin/true.exe ; then
-  BINTRUE=/bin/true.exe
-fi
-if test -f /usr/bin/true ; then
-  BINTRUE=/usr/bin/true
-fi
-
-export BINTRUE
-
-AC_SUBST(BINTRUE,$BINTRUE)
-
-dnl ---------------------------------------------------------------------------
-dnl If datadir is set to @prefix@/share, the modify it to be
-dnl @prefix@/share/gdal.  I wish we could default this.
-dnl ---------------------------------------------------------------------------
-if test "$datadir" = '${prefix}/share' ; then
-  datadir='${prefix}/share/gdal'
-fi
-
-if test "$datadir" = '${datarootdir}' \
-     -a "$datarootdir" = '${prefix}/share' ; then
-  datarootdir='${prefix}/share/gdal'
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl By default mandir is $datarootdir/man which would be
-dnl /usr/local/share/gdal/man but we want man pages in /usr/local/man.
-dnl ---------------------------------------------------------------------------
-mandir='${prefix}/man'
-
-dnl ---------------------------------------------------------------------------
-dnl Capture GDAL_PREFIX for the cpl_config.h include file.
-dnl ---------------------------------------------------------------------------
-
-if test "$prefix" = "NONE" ; then
-  GDAL_PREFIX=/usr/local
-else
-  GDAL_PREFIX=${prefix}
-fi
-
-export GDAL_PREFIX
-AC_DEFINE_UNQUOTED(GDAL_PREFIX,["]$GDAL_PREFIX["], [--prefix directory for GDAL install])
-
-dnl ---------------------------------------------------------------------------
-dnl Perl bindings.
-dnl ---------------------------------------------------------------------------
-
-BINDINGS=
-
-AC_ARG_WITH(perl,[  --with-perl           Enable perl bindings],,)
-
-AC_MSG_CHECKING([for perl bindings])
-if test "$with_perl" = "yes" ; then
-  BINDINGS="perl $BINDINGS"
-  AC_MSG_RESULT([enabled])
-else
-  AC_MSG_RESULT([disabled])
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl PHP bindings.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(php,[  --with-php            Enable php bindings],,)
-
-AC_MSG_CHECKING([for php bindings])
-if test "$with_php" = "yes" ; then
-  BINDINGS="php $BINDINGS"
-  AC_MSG_RESULT([enabled])
-else
-  AC_MSG_RESULT([disabled])
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Ruby bindings.
-dnl ---------------------------------------------------------------------------
-
-dnl AC_ARG_WITH(ruby,[  --with-ruby           Enable Ruby bindings],,)
-
-dnl AC_MSG_CHECKING([for ruby bindings])
-dnl if test "$with_ruby" = "yes" ; then
-dnl   BINDINGS="ruby $BINDINGS"
-dnl   AC_MSG_RESULT([enabled])
-dnl else
-dnl   AC_MSG_RESULT([disabled])
-dnl fi
-
-dnl ---------------------------------------------------------------------------
-dnl NG Python bindings.
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(python,[  --with-python=ARG   Enable python bindings (ARG=yes, no, or path to python binary)],,)
-
-AC_MSG_CHECKING([for python bindings])
-if test "$with_python" = "yes" ; then
-  dnl
-  dnl Check for Python executable in PATH
-  dnl
-  AC_CHECK_PROGS([PYTHON], [python python3 python2])
-  if test "x$PYTHON" = "x"; then
-    AC_MSG_ERROR([--with-python requested, but Python not found!])
-  fi
-elif test "x$with_python" != "x" -a "$with_python" != "no" ; then
-  PYTHON="$with_python"
-  if test "`$PYTHON -c 'print(1)'`" != "1"; then
-    AC_MSG_ERROR([--with-python requested, but Python not found!])
-  fi
-  AC_MSG_RESULT([enabled])
-else
-  PYTHON=""
-  AC_MSG_RESULT([disabled])
-fi
-
-if test "x$PYTHON" != "x"; then
-  BINDINGS="python $BINDINGS"
-
-  AC_MSG_CHECKING([for python setuptools])
-  SETUPTEST='try:
-  import setuptools
-  print(1)
-except ImportError:
-  pass'
-  PY_HAVE_SETUPTOOLS=`$PYTHON -c "$SETUPTEST"`
-  if test "$PY_HAVE_SETUPTOOLS" = "1"; then
-    AC_MSG_RESULT([found])
-  else
-    AC_MSG_RESULT([not found])
-  fi
-fi
-
-AC_SUBST([PY_HAVE_SETUPTOOLS])
-AC_SUBST([BINDINGS])
-
-dnl ---------------------------------------------------------------------------
-dnl Java support
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(java,[  --with-java       Include Java support (ARG=yes, no or JDK home path)  [[default=no]]],,)
-
-AC_MSG_CHECKING([whether we should include Java support])
-
-JAVA_HOME=""
-JAVA_INC=""
-mac_java_fw=""
-
-if test "x$with_java" = "xyes"; then
-
-dnl Ubuntu
-    JAVA_6_TEST_DIR=
-    JAVA_7_TEST_DIR=
-    JAVA_MAC_TEST_DIR=
-    case "$host_cpu" in
-        i*86*)
-            JAVA_6_TEST_DIR=/usr/lib/jvm/java-6-openjdk-i386
-            JAVA_7_TEST_DIR=/usr/lib/jvm/java-7-openjdk-i386
-            ;;
-        x86_64*)
-            JAVA_6_TEST_DIR=/usr/lib/jvm/java-6-openjdk-amd64
-            JAVA_7_TEST_DIR=/usr/lib/jvm/java-7-openjdk-amd64
-            ;;
-        *)
-            ;;
-    esac
-    case "${host_os}" in
-      darwin*)
-        JAVA_MAC_TEST_DIR=$(/usr/libexec/java_home)
-        ;;
-    esac
-
-    if test "x$JAVA_7_TEST_DIR" != "x" -a -d "$JAVA_7_TEST_DIR/include"; then
-        with_java="$JAVA_7_TEST_DIR"
-
-    elif test "x$JAVA_6_TEST_DIR" != "x" -a -d "$JAVA_6_TEST_DIR/include"; then
-        with_java="$JAVA_6_TEST_DIR"
-
-    elif test -d /usr/lib/jvm/java-6-openjdk; then
-        with_java="/usr/lib/jvm/java-6-openjdk"
-
-dnl RHEL6
-    elif test -d /usr/lib/jvm/java-openjdk; then
-        with_java="/usr/lib/jvm/java-openjdk"
-
-
-dnl OpenSolaris
-    elif test -d /usr/java; then
-        with_java="/usr/java"
-
-dnl Mac OS X
-    elif test "x$JAVA_MAC_TEST_DIR" != "x"; then
-        if test -d "$JAVA_MAC_TEST_DIR/bundle"; then
-            # Mac default 1.6.0_x framework
-            # test for ./bundle first, since older installs also have ./include
-            with_java="$JAVA_MAC_TEST_DIR"
-            mac_java_fw="JavaVM"
-        elif test -d "$JAVA_MAC_TEST_DIR/include"; then
-            # Oracle Java install
-            with_java="$JAVA_MAC_TEST_DIR"
-        fi
-    else
-        AC_MSG_ERROR("cannot find JDK root directory.")
-    fi
-
-    if test \! -d "$with_java/include" && test \! -d "$with_java/bundle"; then
-        AC_MSG_ERROR("$with_java is not a valid JDK.")
-    fi
-fi
-
-if test "x$JAVA_INC" != "x"; then
-    AC_MSG_RESULT([yes])
-elif test "x$with_java" != "x" -a "x$with_java" != "xno"; then
-
-    if test -d "$with_java/bundle" && test -d "/System/Library/Frameworks/JavaVM.framework/Headers"; then
-        # Mac default 1.6.0_x framework
-        # test for ./bundle first, since older installs also have ./include
-        JAVA_HOME="$with_java"
-        JAVA_INC="-I/System/Library/Frameworks/JavaVM.framework/Headers"
-        mac_java_fw="JavaVM"
-        AC_MSG_RESULT([yes])
-    elif test -d "$with_java/include"; then
-        if test -d "$with_java/include/linux"; then
-            JAVA_HOME="$with_java"
-            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
-            AC_MSG_RESULT([yes])
-        elif test -d "$with_java/include/solaris"; then
-            JAVA_HOME="$with_java"
-            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/solaris"
-            AC_MSG_RESULT([yes])
-        elif test -d "$with_java/include/freebsd"; then
-            JAVA_HOME="$with_java"
-            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/freebsd"
-            AC_MSG_RESULT([yes])
-        elif test -d "$with_java/include/darwin"; then
-            # Oracle Java install, use instead of Mac default 1.6.0_x
-            JAVA_HOME="$with_java"
-            JAVA_INC="-I$JAVA_HOME/include -I$JAVA_HOME/include/darwin"
-            AC_MSG_RESULT([yes])
-        else
-            AC_MSG_ERROR("Cannot find $with_java/include/linux or solaris or freebsd or darwin directory.")
-        fi
-    else
-        AC_MSG_ERROR("Cannot find $with_java/include or <mac_java_framework>/Headers directory.")
-    fi
-
-else
-    AC_MSG_RESULT([no])
-fi
-
-AC_SUBST(JAVA_HOME,$JAVA_HOME)
-AC_SUBST(JAVA_INC,$JAVA_INC)
-
-dnl ---------------------------------------------------------------------------
-dnl MDB driver
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(mdb,[  --with-mdb       Include MDB driver],,)
-
-AC_MSG_CHECKING([whether we should include MDB support])
-
-MDB_ENABLED=no
-JVM_LIB=""
-
-if test "$with_mdb" = "yes" ; then
-    if test "x$JAVA_INC" = "x"; then
-        AC_MSG_ERROR("--with-java must be specified.")
-    fi
-
-    AC_ARG_WITH(jvm-lib,          [  --with-jvm-lib=[ARG]        ARG points to Java libjvm path],,)
-
-    AC_ARG_WITH(jvm-lib-add-rpath,[  --with-jvm-lib-add-rpath    Add the libjvm path to the RPATH (no by default)],,)
-
-    if test "x$with_jvm_lib" != "x"; then
-        if test -d "$with_jvm_lib"; then
-            saved_LDFLAGS="$LDFLAGS"
-            LDFLAGS="$LDFLAGS -L$with_jvm_lib"
-            if test "x$mac_java_fw" != "x"; then
-                AC_CHECK_FW_FUNC($mac_java_fw,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
-            else
-                AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
-            fi
-            LDFLAGS="$saved_LDFLAGS"
-            if test "$HAS_LIB_JVM" = "yes"; then
-                JVM_LIB="-L$with_jvm_lib -ljvm"
-                if test "x$mac_java_fw" != "x"; then
-                    JVM_LIB="-framework $mac_java_fw"
-                fi
-                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
-                    case "${host_os}" in
-                      darwin*)
-                          if test "x$mac_java_fw" = "x"; then
-                              JVM_LIB="-Wl,-rpath,$with_jvm_lib -L$with_jvm_lib -lazy-ljvm"
-                          fi
-                          ;;
-                      *)
-                          JVM_LIB="-Wl,-rpath=$with_jvm_lib $JVM_LIB"
-                          ;;
-                    esac
-                fi
-            else
-                AC_MSG_ERROR("--with-jvm-lib must point to a directory with a libjvm.")
-            fi
-        else
-            AC_MSG_ERROR("--with-jvm-lib must point to a directory.")
-        fi
-    elif test "x$JAVA_HOME" != "x"; then
-        TEST_DIR="$JAVA_HOME/jre/lib/amd64/server"
-        if test -d "$JAVA_HOME/jre/lib/server"; then
-            # Oracle Java install on Mac
-            TEST_DIR="$JAVA_HOME/jre/lib/server"
-        fi
-        if test "x$mac_java_fw" != "x"; then
-            # Mac default 1.6.0_x framework, TEST_DIR not used
-            TEST_DIR="$with_java"
-        fi
-        if test "x$JVM_LIB" = "x" -a -d "$TEST_DIR"; then
-            unset ac_cv_lib_jvm_JNI_CreateJavaVM
-            saved_LDFLAGS="$LDFLAGS"
-            LDFLAGS="$LDFLAGS -L$TEST_DIR"
-            if test "x$mac_java_fw" != "x"; then
-                AC_CHECK_FW_FUNC($mac_java_fw,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
-            else
-                AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
-            fi
-            LDFLAGS="$saved_LDFLAGS"
-            if test "$HAS_LIB_JVM" = "yes"; then
-                JVM_LIB="-L$TEST_DIR -ljvm"
-                if test "x$mac_java_fw" != "x"; then
-                    JVM_LIB="-framework $mac_java_fw"
-                fi
-                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
-                    case "${host_os}" in
-                      darwin*)
-                          if test "x$mac_java_fw" = "x"; then
-                              JVM_LIB="-Wl,-rpath,$TEST_DIR -L$TEST_DIR -lazy-ljvm"
-                          fi
-                          ;;
-                      *)
-                          JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
-                          ;;
-                    esac
-                fi
-            fi
-        fi
-
-        TEST_DIR="$JAVA_HOME/jre/lib/i386/server"
-        if test "x$JVM_LIB" = "x" -a -d "$TEST_DIR"; then
-            unset ac_cv_lib_jvm_JNI_CreateJavaVM
-            saved_LDFLAGS="$LDFLAGS"
-            LDFLAGS="$LDFLAGS -L$TEST_DIR"
-            AC_CHECK_LIB(jvm,JNI_CreateJavaVM,HAS_LIB_JVM=yes,HAS_LIB_JVM=no,)
-            LDFLAGS="$saved_LDFLAGS"
-            if test "$HAS_LIB_JVM" = "yes"; then
-                JVM_LIB="-L$TEST_DIR -ljvm"
-                if test "x$with_jvm_lib_add_rpath" = "xyes"; then
-                    JVM_LIB="-Wl,-rpath=$TEST_DIR $JVM_LIB"
-                fi
-            fi
-        fi
-
-        if test "x$JVM_LIB" = "x"; then
-            AC_MSG_ERROR("--with-jvm-lib must be specified.")
-        fi
-    else
-        AC_MSG_ERROR("--with-jvm-lib must be specified.")
-    fi
-
-    MDB_ENABLED=yes
-    AC_MSG_RESULT([yes])
-
-else
-    AC_MSG_RESULT([no])
-fi
-
-AC_SUBST(MDB_ENABLED,$MDB_ENABLED)
-AC_SUBST(JVM_LIB,$JVM_LIB)
-
-
-dnl ---------------------------------------------------------------------------
-dnl Select Rasdaman or disable driver.
-dnl ---------------------------------------------------------------------------
-
-RASDAMAN_ENABLED=no
-
-AC_CHECKING(whether we should include rasdaman support)
-AC_ARG_WITH(rasdaman,
-[  --with-rasdaman[=DIR]        Include rasdaman support (DIR is rasdaman's install dir).],,)
-
-if test "$with_rasdaman" = "yes" ; then
-
-  AC_CHECK_LIB(raslib,main,RASDAMAN_ENABLED=yes,,,)
-
-  if test -n "$RASDAMAN_ENABLED" ; then
-      RASDAMAN_LIB="-lrasodmg -lclientcomm -lcompression -lnetwork -lraslib"
-      OPT_GDAL_FORMATS="rasdaman $OPT_GDAL_FORMATS"
-      AC_MSG_RESULT([        using rasdaman from system libs.])
-  else
-      AC_MSG_WARN([        rasdaman not found in system libs... use --with-rasdaman=DIR.])
-  fi
-
-elif test -n "$with_rasdaman" -a "$with_rasdaman" != "no" ; then
-
-  RASDAMAN_DIR=$with_rasdaman
-
-  if test -f $RASDAMAN_DIR/include/rasdaman.hh -a -d$RASDAMAN_DIR/lib ; then
-      RASDAMAN_INC=-I$RASDAMAN_DIR/include
-      RASDAMAN_LIB="-L$RASDAMAN_DIR/lib -lrasodmg -lclientcomm -lcompression -lnetwork -lraslib"
-  else
-      AC_MSG_ERROR("Could not find rasdaman.hh or libraslib.a in $RASDAMAN_DIR.")
-  fi
-
-  RASDAMAN_ENABLED=yes
-  OPT_GDAL_FORMATS="rasdaman $OPT_GDAL_FORMATS"
-  AC_MSG_RESULT([        using rasdaman from $RASDAMAN_DIR.])
-
-else
-
-  AC_MSG_RESULT([        rasdaman support not requested.])
-fi
-
-AC_SUBST(RASDAMAN_ENABLED,$RASDAMAN_ENABLED)
-AC_SUBST(RASDAMAN_INC,    $RASDAMAN_INC)
-AC_SUBST(RASDAMAN_LIB,    $RASDAMAN_LIB)
-
-dnl ---------------------------------------------------------------------------
-dnl Armadillo support
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(armadillo,[  --with-armadillo=ARG       Include Armadillo support for faster TPS transform computation (ARG=yes/no/path to armadillo install root) [[default=no]]],,)
-
-AC_MSG_CHECKING([whether we should include Armadillo support])
-
-HAVE_ARMADILLO=no
-
-if test "$with_armadillo" = "yes" ; then
-    rm -f testarmadillo.*
-    rm -f testarmadillo
-    echo '#include <armadillo>' > testarmadillo.cpp
-    echo 'int main(int argc, char** argv) { arma::mat matInput(2,2); const arma::mat& matInv = arma::inv(matInput); return 0; } ' >> testarmadillo.cpp
-    if test -z "`${CXX} ${CPPFLAGS} testarmadillo.cpp -o testarmadillo -larmadillo 2>&1`" ; then
-        HAVE_ARMADILLO=yes
-        LIBS="-larmadillo ${LIBS}"
-        AC_MSG_RESULT([yes])
-    else
-        dnl Try adding -llapack (#4923)
-        if test -z "`${CXX} ${CPPFLAGS} testarmadillo.cpp -o testarmadillo -larmadillo -llapack 2>&1`" ; then
-            HAVE_ARMADILLO=yes
-            LIBS="-larmadillo -llapack ${LIBS}"
-            AC_MSG_RESULT([yes])
-        else
-            # clang 3.4 needs linking against libstdc++ (ubuntu 14.04)
-            if test -z "`${CXX} ${CPPFLAGS} testarmadillo.cpp -o testarmadillo -larmadillo -lstdc++ 2>&1`" ; then
-                HAVE_ARMADILLO=yes
-                LIBS="-larmadillo -lstdc++ ${LIBS}"
-                AC_MSG_RESULT([yes])
-            else
-                AC_MSG_RESULT([no])
-            fi
-        fi
-    fi
-    rm -f testarmadillo.*
-    rm -f testarmadillo
-
-elif test -n "$with_armadillo" -a "$with_armadillo" != "no" ; then
-
-    rm -f testarmadillo.*
-    rm -f testarmadillo
-    echo '#include <armadillo>' > testarmadillo.cpp
-    echo 'int main(int argc, char** argv) { arma::mat matInput(2,2); const arma::mat& matInv = arma::inv(matInput); return 0; } ' >> testarmadillo.cpp
-    if test -z "`${CXX} ${CPPFLAGS} -I$with_armadillo/include testarmadillo.cpp -o testarmadillo -L$with_armadillo/lib -larmadillo 2>&1`" ; then
-        HAVE_ARMADILLO=yes
-        LIBS="-L$with_armadillo/lib -larmadillo ${LIBS}"
-        EXTRA_INCLUDES="-I$with_armadillo/include $EXTRA_INCLUDES"
-        AC_MSG_RESULT([yes])
-    else
-        dnl Try adding -llapack (#4923)
-        if test -z "`${CXX} ${CPPFLAGS} -I$with_armadillo/include testarmadillo.cpp -o testarmadillo -L$with_armadillo/lib -larmadillo -llapack 2>&1`" ; then
-            HAVE_ARMADILLO=yes
-            LIBS="-L$with_armadillo/lib -larmadillo -llapack ${LIBS}"
-            EXTRA_INCLUDES="-I$with_armadillo/include $EXTRA_INCLUDES"
-            AC_MSG_RESULT([yes])
-        else
-            AC_MSG_RESULT([no])
-        fi
-    fi
-    rm -f testarmadillo.*
-    rm -f testarmadillo
-
-else
-    AC_MSG_RESULT([no])
-fi
-
-AC_SUBST(HAVE_ARMADILLO,$HAVE_ARMADILLO)
-
-dnl ---------------------------------------------------------------------------
-dnl libcryptopp
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH(cryptopp,[  --with-cryptopp[=ARG]       Include cryptopp support (ARG=yes, no or path)],,)
-
-HAVE_CRYPTOPP=no
-USE_ONLY_CRYPTODLL_ALG=yes
-
-AC_MSG_CHECKING([for cryptopp])
-
-if test "$with_cryptopp" = "no" ; then
-
-  AC_MSG_RESULT([disabled])
-
-elif test "$with_cryptopp" = "yes" -o "$with_cryptopp" = "" ; then
-
-    rm -f testcryptopp.*
-    echo '#include <cryptopp/aes.h>' > testcryptopp.cpp
-    # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
-    echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
-    echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
-    ${CXX} ${CXXFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
-    RETVAL=$?
-    if test $RETVAL -eq 0; then
-        HAVE_CRYPTOPP=yes
-        LIBS="-lcryptopp ${LIBS}"
-        AC_MSG_RESULT([yes])
-    else
-        AC_MSG_RESULT([no])
-        if test "$with_cryptopp" = "yes"; then
-            AC_MSG_ERROR([--with-cryptopp was requested, but not available])
-        fi
-    fi
-    rm -f testcryptopp.*
-    rm -f testcryptopp
-
-    if test "$HAVE_CRYPTOPP" = "yes"; then
-
-        AC_MSG_CHECKING([if cryptopp has all cipher methods builtin])
-        rm -f testcryptopp.*
-        echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
-        echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
-        ${CXX} ${CXXFLAGS} testcryptopp.cpp -o testcryptopp -lcryptopp 2>/dev/null
-        RETVAL=$?
-        if test $RETVAL -eq 0; then
-            USE_ONLY_CRYPTODLL_ALG=no
-            AC_MSG_RESULT([yes])
-        else
-            USE_ONLY_CRYPTODLL_ALG=yes
-            AC_MSG_RESULT([no])
-        fi
-        rm -f testcryptopp.*
-        rm -f testcryptopp
-    fi
-
-else
-
-    rm -f testcryptopp.*
-    echo '#include <cryptopp/aes.h>' > testcryptopp.cpp
-    # Catch issue with clang++ (https://groups.google.com/forum/#!topic/cryptopp-users/DfWHy3bT0KI)
-    echo '#include <cryptopp/osrng.h>' >> testcryptopp.cpp
-    echo 'int main(int argc, char** argv) { CryptoPP::AES::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
-    ${CXX} ${CXXFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
-    RETVAL=$?
-    if test $RETVAL -eq 0; then
-        HAVE_CRYPTOPP=yes
-        LIBS="-L$with_cryptopp/lib -lcryptopp ${LIBS}"
-        EXTRA_INCLUDES="-I$with_cryptopp/include $EXTRA_INCLUDES"
-        AC_MSG_RESULT([yes])
-    else
-        AC_MSG_RESULT([no])
-    fi
-    rm -f testcryptopp.*
-    rm -f testcryptopp
-
-    if test "$HAVE_CRYPTOPP" = "yes"; then
-
-        AC_MSG_CHECKING([if cryptopp has all cipher methods builtin])
-        rm -f testcryptopp.*
-        echo '#include <cryptopp/blowfish.h>' > testcryptopp.cpp
-        echo 'int main(int argc, char** argv) { CryptoPP::Blowfish::Encryption oEnc; return 0; } ' >> testcryptopp.cpp
-        ${CXX} ${CXXFLAGS} testcryptopp.cpp -I$with_cryptopp/include -o testcryptopp -L$with_cryptopp/lib -lcryptopp 2>/dev/null
-        RETVAL=$?
-        if test $RETVAL -eq 0; then
-            USE_ONLY_CRYPTODLL_ALG=no
-            AC_MSG_RESULT([yes])
-        else
-            USE_ONLY_CRYPTODLL_ALG=yes
-            AC_MSG_RESULT([no])
-        fi
-        rm -f testcryptopp.*
-        rm -f testcryptopp
-    fi
-
-fi
-
-AC_SUBST(HAVE_CRYPTOPP,$HAVE_CRYPTOPP)
-AC_SUBST(USE_ONLY_CRYPTODLL_ALG,$USE_ONLY_CRYPTODLL_ALG)
-
-
-dnl ---------------------------------------------------------------------------
-dnl Whether to include MRF in the build
-dnl ---------------------------------------------------------------------------
-
-AC_ARG_WITH([grib],
-            AS_HELP_STRING([--without-mrf],
-               [Disable MRF driver]),,)
-
-AC_MSG_CHECKING([for MRF])
-if test "$with_mrf" = yes -o x"$with_mrf" = x ; then
-    OPT_GDAL_FORMATS="mrf $OPT_GDAL_FORMATS"
-    HAVE_MRF=yes
-    AC_MSG_RESULT([enabled])
-else
-    HAVE_MRF=no
-    AC_MSG_RESULT([disabled by user])
-fi
-
-dnl ---------------------------------------------------------------------------
-dnl Test if sprintf can be overloaded with _XOPEN_SOURCE being defined or other,
-dnl includes being included before, which mingw64 4.8 doesn't like (#6390)
-dnl ---------------------------------------------------------------------------
-
-AC_MSG_CHECKING([if sprintf can be overloaded for GDAL compilation])
-echo '#define _XOPEN_SOURCE' > testdeprecated.cpp
-echo '#include <vector>' >> testdeprecated.cpp
-echo '#include <stdio.h>' >> testdeprecated.cpp
-echo 'extern "C"' >> testdeprecated.cpp
-echo '{' >> testdeprecated.cpp
-echo 'int sprintf(char *str, const char* fmt, ...);' >> testdeprecated.cpp
-echo '}' >> testdeprecated.cpp
-${CXX} ${CXXFLAGS} testdeprecated.cpp -c 2>/dev/null
-RETVAL=$?
-if test $RETVAL -eq 0; then
-    AC_MSG_RESULT([yes])
-else
-    CPPFLAGS="$CPPFLAGS -DDONT_DEPRECATE_SPRINTF"
-    AC_MSG_RESULT([no])
-fi
-rm -f testdeprecated.*
-rm -f testdeprecated
-
-AC_OUTPUT(GDALmake.opt)
-
-dnl ---------------------------------------------------------------------------
-dnl Display configuration status
-dnl ---------------------------------------------------------------------------
-
-LOC_MSG()
-LOC_MSG([GDAL is now configured for ${host}])
-LOC_MSG()
-LOC_MSG([  Installation directory:    ${prefix}])
-LOC_MSG([  C compiler:                ${CC} ${CFLAGS}])
-LOC_MSG([  C++ compiler:              ${CXX} ${CXXFLAGS}])
-LOC_MSG()
-LOC_MSG([  LIBTOOL support:           ${with_libtool}])
-LOC_MSG()
-LOC_MSG([  LIBZ support:              ${LIBZ_SETTING}])
-LOC_MSG([  LIBLZMA support:           ${LIBLZMA_SETTING}])
-LOC_MSG([  cryptopp support:          ${HAVE_CRYPTOPP}])
-LOC_MSG([  GRASS support:             ${GRASS_SETTING}])
-LOC_MSG([  CFITSIO support:           ${FITS_SETTING}])
-LOC_MSG([  PCRaster support:          ${PCRASTER_SETTING}])
-LOC_MSG([  LIBPNG support:            ${PNG_SETTING}])
-LOC_MSG([  DDS support:               ${DDS_SETTING}])
-LOC_MSG([  GTA support:               ${GTA_SETTING}])
-LOC_MSG([  LIBTIFF support:           ${TIFF_SETTING} (BigTIFF=${HAVE_BIGTIFF})])
-LOC_MSG([  LIBGEOTIFF support:        ${GEOTIFF_SETTING}])
-LOC_MSG([  LIBJPEG support:           ${JPEG_SETTING}])
-LOC_MSG([  12 bit JPEG:               ${JPEG12_ENABLED}])
-LOC_MSG([  12 bit JPEG-in-TIFF:       ${TIFF_JPEG12_ENABLED}])
-LOC_MSG([  LIBGIF support:            ${GIF_SETTING}])
-LOC_MSG([  OGDI support:              ${HAVE_OGDI}])
-LOC_MSG([  HDF4 support:              ${HAVE_HDF4}])
-LOC_MSG([  HDF5 support:              ${HAVE_HDF5}])
-LOC_MSG([  Kea support:               ${HAVE_KEA}])
-LOC_MSG([  NetCDF support:            ${NETCDF_SETTING}])
-LOC_MSG([  Kakadu support:            ${HAVE_KAKADU}])
-if test "x$HAVE_JASPER_UUID" != "x" ; then
-  LOC_MSG([  JasPer support:            ${HAVE_JASPER} (GeoJP2=${HAVE_JASPER_UUID})])
-else
-  LOC_MSG([  JasPer support:            ${HAVE_JASPER}])
-fi
-LOC_MSG([  OpenJPEG support:          ${HAVE_OPENJPEG}])
-LOC_MSG([  ECW support:               ${ECW_SETTING}])
-LOC_MSG([  MrSID support:             ${HAVE_MRSID}])
-LOC_MSG([  MrSID/MG4 Lidar support:   ${HAVE_MRSID_LIDAR}])
-LOC_MSG([  MSG support:               ${HAVE_MSG}])
-LOC_MSG([  GRIB support:              ${HAVE_GRIB}])
-LOC_MSG([  EPSILON support:           ${EPSILON_SETTING}])
-LOC_MSG([  WebP support:              ${WEBP_SETTING}])
-LOC_MSG([  cURL support (wms/wcs/...):${CURL_SETTING}])
-LOC_MSG([  PostgreSQL support:        ${HAVE_PG}])
-LOC_MSG([  MRF support:               ${HAVE_MRF}])
-LOC_MSG([  MySQL support:             ${HAVE_MYSQL}])
-LOC_MSG([  Ingres support:            ${HAVE_INGRES}])
-LOC_MSG([  Xerces-C support:          ${HAVE_XERCES}])
-LOC_MSG([  NAS support:               ${HAVE_NAS}])
-LOC_MSG([  Expat support:             ${HAVE_EXPAT}])
-LOC_MSG([  libxml2 support:           ${HAVE_LIBXML2}])
-LOC_MSG([  Google libkml support:     ${HAVE_LIBKML}])
-LOC_MSG([  ODBC support:              ${ODBC_SETTING}])
-LOC_MSG([  PGeo support:              ${ODBC_SETTING}])
-LOC_MSG([  FGDB support:              ${FGDB_ENABLED}])
-LOC_MSG([  MDB support:               ${MDB_ENABLED}])
-LOC_MSG([  PCIDSK support:            ${PCIDSK_SETTING}])
-LOC_MSG([  OCI support:               ${HAVE_OCI}])
-LOC_MSG([  GEORASTER support:         ${HAVE_GEORASTER}])
-LOC_MSG([  SDE support:               ${SDE_ENABLED}])
-LOC_MSG([  Rasdaman support:          ${RASDAMAN_ENABLED}])
-LOC_MSG([  DODS support:              ${HAVE_DODS}])
-LOC_MSG([  SQLite support:            ${HAVE_SQLITE}])
-LOC_MSG([  PCRE support:              ${HAVE_PCRE}])
-LOC_MSG([  SpatiaLite support:        ${HAVE_SPATIALITE}])
-if test "x$SPATIALITE_SONAME" != "x"; then
-LOC_MSG([  SpatiaLite shared obj name:${SPATIALITE_SONAME}])
-fi
-LOC_MSG([  DWGdirect support          ${HAVE_DWGDIRECT}])
-LOC_MSG([  INFORMIX DataBlade support:${HAVE_IDB}])
-LOC_MSG([  GEOS support:              ${HAVE_GEOS_RESULT}])
-LOC_MSG([  QHull support:             ${QHULL_SETTING}])
-LOC_MSG([  Poppler support:           ${HAVE_POPPLER}])
-LOC_MSG([  Podofo support:            ${HAVE_PODOFO}])
-LOC_MSG([  PDFium support:            ${HAVE_PDFIUM}])
-LOC_MSG([  OpenCL support:            ${OPENCL_SETTING}])
-LOC_MSG([  Armadillo support:         ${HAVE_ARMADILLO}])
-LOC_MSG([  FreeXL support:            ${HAVE_FREEXL}])
-LOC_MSG([  SOSI support:              ${SOSI_ENABLED}])
-LOC_MSG([  MongoDB support:           ${MONGODB_ENABLED}])
-LOC_MSG()
-if test ! -z "`uname | grep Darwin`" ; then
-  LOC_MSG([  Mac OS X Framework :       ${MACOSX_FRAMEWORK}])
-fi
-LOC_MSG()
-if test -z "$BINDINGS"; then
-    WHAT_BINDINGS="no"
-else
-    WHAT_BINDINGS="$BINDINGS"
-fi
-LOC_MSG([  SWIG Bindings:             ${WHAT_BINDINGS}])
-LOC_MSG()
-LOC_MSG([  Statically link PROJ.4:    ${PROJ_STATIC}])
-LOC_MSG([  enable GNM building:       ${GNM_ENABLED}])
-LOC_MSG([  enable pthread support:    ${PTHREAD_ENABLED}])
-LOC_MSG([  enable POSIX iconv support:${am_cv_func_iconv}])
-LOC_MSG([  hide internal symbols:     ${HAVE_HIDE_INTERNAL_SYMBOLS}])
-LOC_MSG()
-
-if test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes"  -a "$HAVE_PDFIUM" = "yes"; then
-    AC_MSG_WARN([--with-podofo, --with-poppler and --with-pdfium available. This is unusual setup, but will work. Pdfium will be used by default...])
-elif test "$HAVE_PODOFO" = "yes" -a "$HAVE_POPPLER" = "yes" ; then
-    AC_MSG_WARN([--with-podofo and --with-poppler are both available. This is unusual setup, but will work. Poppler will be used by default...])
-elif test "$HAVE_POPPLER" = "yes" -a "$HAVE_PDFIUM" = "yes" ; then
-    AC_MSG_WARN([--with-poppler and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default...])
-elif test "$HAVE_PODOFO" = "yes" -a "$HAVE_PDFIUM" = "yes" ; then
-    AC_MSG_WARN([--with-podofo and --with-pdfium are both available. This is unusual setup, but will work. Pdfium will be used by default...])
-fi
-
-if test "$HAVE_LIBXML2" = "yes" -a "$FGDB_ENABLED" = "yes"; then
-    AC_MSG_WARN([--with-libxml2 and --with-fgdb are both available. There might be some incompatibility between system libxml2 and the embedded copy within libFileGDBAPI])
-fi
diff --git a/data/compdcs.csv b/data/compdcs.csv
index bfd7b4d..41edca1 100644
--- a/data/compdcs.csv
+++ b/data/compdcs.csv
@@ -152,3 +152,6 @@
 7421,"NTF (Paris) / Lambert zone II + NGF-IGN69 height",27572,5720,1,0
 7422,"NTF (Paris) / Lambert zone III + NGF-IGN69 height",27573,5720,1,0
 7423,"ETRS89 + EVRF2007 height",4258,5621,1,0
+7954,"Astro DOS 71 / UTM zone 30S + Jamestown 1971 height",7878,7888,1,0
+7955,"St. Helena Tritan / UTM zone 30S +  Tritan 2011 height",7883,7889,1,0
+7956,"SHMG2015 +  SHVD2015 height",7887,7890,1,0
diff --git a/data/coordinate_axis.csv b/data/coordinate_axis.csv
index 1bfc028..0dd4e48 100644
--- a/data/coordinate_axis.csv
+++ b/data/coordinate_axis.csv
@@ -31,9 +31,21 @@ coord_sys_code,coord_axis_name_code,coord_axis_orientation,coord_axis_abbreviati
 1038,9907,South along 75°W,Y,9001,2
 1039,9906,east,E,9002,1
 1039,9907,north,N,9002,2
+1040,1024,Ahead,x,9001,1
+1040,1025,Starboard,y,9001,2
+1040,1026,Upward,z,9001,3
+1041,1024,Ahead,x,9001,1
+1041,1025,Starboard,y,9001,2
+1041,1027,Downward,z,9001,3
+1042,1024,Ahead,y,9001,2
+1042,1025,Starboard,x,9001,1
+1042,1026,Upward,z,9001,3
 1043,9905,down,D,9003,1
 1044,9906,North along 90°W,E,9001,2
 1044,9907,North along 180°E,N,9001,1
+1045,1024,Ahead,y,9001,2
+1045,1025,Starboard,x,9001,1
+1045,1027,Downward,z,9001,3
 4400,9906,east,E,9001,1
 4400,9907,north,N,9001,2
 4401,9906,east,E,9062,1
diff --git a/data/datum_shift.csv b/data/datum_shift.csv
index 693842b..aa19e2c 100644
--- a/data/datum_shift.csv
+++ b/data/datum_shift.csv
@@ -25,7 +25,7 @@
 24,1875,4618,4326,"Derived at 1 station. Note: SAD69 not adopted in Trinidad and Tobago.",For military purposes only. Accuracy 25m in each axis.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-45,12,-33,,,,,0
 25,1876,4618,4326,"Derived at 5 stations. Note: SAD69 not adopted in Venezuela: see PSAD56 (CRS code 4248).","For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",3327,0.64,12.25,-73.38,-59.8,1,0,9603,-45,8,-33,,,,,0
 26,1877,4618,4326,"Derived by Brazilian Institute of Geography and Statistics (IBGE) in 1989 at Chua origin point. In use by Shell throughout Brazil. For use by Petrobras and ANP, replaced by tfm code 5882 from 1994.",Medium and small scale mapping. Valid for transforming GPS observations conducted in the period 1987 to 1993 inclusive.,1053,-35.71,7.04,-74.01,-25.28,1,0,9603,-66.87,4.37,-38.52,,,,,1
-27,5882,4618,4326,"Parameter values from SAD69 to SIRGAS 2000 (1) (tfm code 15485) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras throughout Brazil from 1994, relacing use of tfm code 1877.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).",1053,-35. [...]
+27,5882,4618,4326,"Parameter values from SAD69 to SIRGAS 2000 (1) (tfm code 15485) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras throughout Brazil from 1994, replacing use of tfm code 1877.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).",1053,-35 [...]
 28,6967,4618,4326,"Also used as a transformation from SAD69 to WGS 84 - see code 6974. Note: SAD69 adopted in Chile only south of 43°30'S.",Small and medium scale cartographic mapping.,4232,-32,-17.5,-71.77,-67,1,1,9603,-59,-11,-52,,,,,0
 29,6969,4618,4326,"Also used as a transformation from SAD69 to WGS 84 - see code 6976. Note: SAD69 adopted in Chile only south of 43°30'S.",Small and medium scale cartographic mapping.,4221,-43.5,-35.99,-74.48,-70.39,1,1,9603,-72,10,-32,,,,,0
 30,6974,4618,4326,"Derived at 8 stations. Along with transformations 6975 and 6976, replaces SAD69 to WGS 84 (5) (code 1868). Also used as a transformation from SAD69 to SIRGAS-Chile - see code 7448. Note: SAD69 adopted by Chile authorities only south of 43°30'S.",For military purposes only. Accuracy 2m in each axis.,4232,-32,-17.5,-71.77,-67,1,0,9603,-59,-11,-52,,,,,0
@@ -107,9 +107,9 @@
 106,1544,4147,4326,Derived in Vung Tau area.,Oil exploration.,1494,9.02,11.03,105.49,107.59,1,0,9603,-17.51,-108.32,-62.39,,,,,1
 107,1505,4148,4326,,For many purposes Hartebeesthoek94 datum can be considered to be coincident with WGS 84.,1215,-50.32,-22.13,13.33,42.85,1,0,9603,0,0,0,,,,,1
 108,1508,4149,4326,"Implemented in Bundesamt für Landestopographie programme GRANIT.","?",1286,45.82,47.81,5.96,10.49,1,1,9607,660.077,13.551,369.344,0.80482,0.57769,0.95224,5.66,0
-109,1510,4149,4326,"These parameters are strictly between CH1903+ and CHTRF95 but are used from CH1903 as an approximation which is within the accuracy of the distortions in the CH1903 network.",Accuracy 1.5 metres.,1286,45.82,47.81,5.96,10.49,1,1,9603,674.374,15.056,405.346,,,,,0
+109,1510,4149,4326,"These parameters are strictly between CH1903+ and CHTRF95 but are used from CH1903 as an approximation which is within the accuracy of the distortions in the CH1903 network.",Accuracy 1.5 metres.,1286,45.82,47.81,5.96,10.49,1,1,9603,674.374,15.056,405.346,,,,,1
 110,1753,4149,4326,"Implemented in Bundesamt für Landestopografie programme GRANIT. Used from 1987 to 1997. Not recommended for current usage - replaced by CH1903 to WGS 84 (2) (code 1766).",Used in programme GRANIT between 1987 and 1997.,1286,45.82,47.81,5.96,10.49,1,0,9607,660.077,13.551,369.344,0.80482,0.57769,0.95224,5.66,0
-111,1766,4149,4326,"These parameters are derive from CH1903+ to ETRS89 (code 1647) and are used at lesser precision from CH1903 to WGS 84 as an approximation which is within the accuracy of the distortions in the CH1903 network. Replaces CH1903 to WGS 84 (1) (code 1753).",Accuracy 1.5 metres.,1286,45.82,47.81,5.96,10.49,1,0,9603,674.4,15.1,405.3,,,,,1
+111,1766,4149,4326,"Parameters values from CH1903 to ETRS89 (1) (tfm code 1646) assuming ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces CH1903 to WGS 84 (1) (code 1753). Replaced by CH1903 to WGS 84 (3) (code 7788).","Parameter values originally from CH1903+ to ETRS89 (tfm code 1647) and are used in tfm code 1646 as an approximation from CH1903 to ETRS89 with a lesser accuracy of 1.5m which equates to the magnitude of distortions in th [...]
 112,1676,4150,4326,"Parameter values are from CH1903+ to CHTRF95 (1) (code 1509) assuming that CHTRF95 is equivalent to WGS 84. That transformation is also given as CH1903+ to ETRS89 (1) (code 1647). CHTRF95 is a realisation of ETRS89.","Approximation at the +/- 1m level.",1286,45.82,47.81,5.96,10.49,1,0,9603,674.374,15.056,405.346,,,,,1
 113,1511,4151,4326,,For many purposes CHTRF95 can be considered to be coincident with WGS 84.,1286,45.82,47.81,5.96,10.49,1,0,9603,0,0,0,,,,,1
 114,1580,4152,4326,"For many purposes NAD83(HARN) can be considered to be coincident with WGS 84.","Approximation at the +/- 1m level assuming that NAD83(HARN) is equivalent to WGS 84.",1337,-14.59,49.38,144.58,-64.51,1,0,9603,0,0,0,,,,,1
@@ -137,10 +137,10 @@
 136,1861,4159,4326,Derived by GEOID in 1994 from Transit satellite data. Used by TotalFinaElf.,Oil Exploration,2786,29.61,30.07,17.13,17.51,1,0,9603,-114.5,-96.1,-151.9,,,,,0
 137,1862,4159,4326,"Derived by Geoid in 2000 from ITRF connection by NAGECO for TotalFinaElf. For historic compatibility TFE use the 1994 tfm ELD79 to WGS 84 (3) (code 1861) rather than this transformation.",Oil Exploration,2786,29.61,30.07,17.13,17.51,1,0,9606,-194.513,-63.978,-25.759,-3.4027,3.756,-3.352,-0.9175,0
 138,1863,4159,4326,"Derived for the Great Man-made River Authority (GMRA).",Engineering survey and oil exploration,2786,29.61,30.07,17.13,17.51,1,0,9607,-389.691,64.502,210.209,-0.086,-14.314,6.39,0.9264,0
-139,15707,4159,4326,"Used by Petrocanada and previous licence holders in Amal field, concession 12.",Oil exploration and production,2987,29.1,29.8,20.8,21.4,1,0,9603,-118.996,-111.177,-198.687,,,,,0
-140,15778,4159,4326,"Derived by Total at stations SDL 130-03, 04 and 05 in May 2005.",Oil exploration and production.,3142,27.5,28.07,21.25,21.59,1,0,9603,-114.7,-98.5,-150.7,,,,,0
+139,15923,4159,4326,"Derived by SDL for Total in Cyrenaica blocks 2 & 4.",Oil and gas exploration.,3477,32,32.8,22.49,23,1,0,9603,-117.7,-100.3,-152.4,,,,,0
+140,15707,4159,4326,"Used by Petrocanada and previous licence holders in Amal field, concession 12.",Oil exploration and production,2987,29.1,29.8,20.8,21.4,1,0,9603,-118.996,-111.177,-198.687,,,,,0
 141,15909,4159,4326,Derived at 29 stations throughout Libya in May 2006.,For applications to an accuracy of 5 metres.,3271,19.49,33.23,9.31,25.21,1,0,9603,-115.8543,-99.0583,-152.4616,,,,,1
-142,15923,4159,4326,"Derived by SDL for Total in Cyrenaica blocks 2 & 4.",Oil and gas exploration.,3477,32,32.8,22.49,23,1,0,9603,-117.7,-100.3,-152.4,,,,,0
+142,15778,4159,4326,"Derived by Total at stations SDL 130-03, 04 and 05 in May 2005.",Oil exploration and production.,3142,27.5,28.07,21.25,21.59,1,0,9603,-114.7,-98.5,-150.7,,,,,0
 143,1080,4672,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,2889,-44.64,-43.3,-177.25,-175.54,1,0,9603,175,-38,113,,,,,1
 144,1081,4673,4326,Derived at 4 stations using concatenation through WGS72. Parameter vales are also used to transform CI1979 to NZGD2000 - see tfm code 1082.,For applications requiring 2m accuracy.,2889,-44.64,-43.3,-177.25,-175.54,1,0,9607,174.05,-25.49,112.57,0,0,-0.554,0.2263,1
 145,15894,4674,4326,,Accuracy 1m.,3418,-59.87,32.72,-122.19,-25.28,1,0,9603,0,0,0,,,,,1
@@ -163,14 +163,14 @@
 162,15773,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (1) (tfm code 15761).","Accuracy +/- 1 metre.",3131,-9.89,-9.64,-139.23,-138.75,1,0,9607,410.721,55.049,80.746,-2.5779,-2.3514,-0.6664,17.3311,1
 163,15774,4689,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from IGN63 Hiva Oa to RGPF (2) (tfm code 15762).","Accuracy +/- 2 metres.",3132,-10.08,-9.86,-139.19,-138.98,1,0,9607,374.716,-58.407,-0.957,-16.2111,-11.4626,-5.5357,-0.5409,0
 164,1675,4178,4326,"Parameter values from Pulkovo 1942(83) to ETRS89 (1) (code 1674) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.",Residuals under 2 m.,1343,50.2,54.74,9.92,15.04,1,0,9607,24,-123,-94,-0.02,0.25,0.13,1.1,0
-165,15996,4178,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.74,48.58,16.11,22.9,1,0,9603,28,-121,-77,,,,,0
-166,15998,4178,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,0,9603,26,-121,-78,,,,,1
+165,15998,4178,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,0,9603,26,-121,-78,,,,,1
+166,15996,4178,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.74,48.58,16.11,22.9,1,0,9603,28,-121,-77,,,,,0
 167,1645,4179,4326,"Parameter values from Pulkovo 1942(58) to ETRS89 (1) (code 1644). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3293,49,54.89,14.14,24.15,1,0,9606,33.4,-146.6,-76.3,-0.359,-0.053,0.844,-0.84,1
-168,15496,4179,4326,,Oil exploration,1197,43.44,48.27,20.26,31.41,1,0,9603,44.107,-116.147,-54.648,,,,,0
-169,15497,4179,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,0,9603,28,-121,-77,,,,,0
-170,15995,4179,4326,"Parameter values taken from Pulkovo 1942(58) to ETRS89 (4) (code 15994) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy of 1.5 to 3 metres horizontal, 3 to 5m vertical.",1197,43.44,48.27,20.26,31.41,1,0,9607,2.329,-147.042,-92.08,0.309,-0.325,-0.497,5.69,0
-171,15997,4179,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",3293,49,54.89,14.14,24.15,1,0,9603,23,-124,-82,,,,,0
-172,15999,4179,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,3212,39.64,42.67,19.22,21.06,1,0,9603,24,-130,-92,,,,,0
+168,15999,4179,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,3212,39.64,42.67,19.22,21.06,1,0,9603,24,-130,-92,,,,,0
+169,15496,4179,4326,,Oil exploration,1197,43.44,48.27,20.26,31.41,1,0,9603,44.107,-116.147,-54.648,,,,,0
+170,15497,4179,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,0,9603,28,-121,-77,,,,,0
+171,15995,4179,4326,"Parameter values taken from Pulkovo 1942(58) to ETRS89 (4) (code 15994) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy of 1.5 to 3 metres horizontal, 3 to 5m vertical.",1197,43.44,48.27,20.26,31.41,1,0,9607,2.329,-147.042,-92.08,0.309,-0.325,-0.497,5.69,0
+172,15997,4179,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",3293,49,54.89,14.14,24.15,1,0,9603,23,-124,-82,,,,,0
 173,1649,4180,4326,"Parameter values taken from EST97 to ETRS89 (1) (code 1648). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1090,57.52,60,20.37,28.2,1,0,9603,0,0,0,,,,,1
 174,1643,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (1) (code 1642). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1146,49.44,50.19,5.73,6.53,1,0,9606,-193,13.7,-39.3,-0.41,-2.933,2.688,0.43,0
 175,5486,4181,4326,"Parameter values from Luxembourg 1930 to ETRS89 (3) (code 5485) assuming ETRS89 and WGS 84 are coincident within the one metre level. Replaces tfm code 1643. For an equivalent transformation using the Molodensky-Badekas method see code 5484.",For applications to an accuracy of 1 metre.,1146,49.44,50.19,5.73,6.53,1,0,9607,-189.6806,18.3463,-42.7695,0.33746,3.09264,-2.53861,0.4598,1
@@ -184,645 +184,653 @@
 183,1768,4189,4326,,"Approximation at the +/- 1m level.",1251,0.64,16.75,-73.38,-58.95,1,0,9603,0,0,0,,,,,1
 184,1773,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.41,-21.78,-73.59,-52.63,1,0,9603,0,0,0,,,,,1
 185,15780,4190,4326,,"Approximation at the +/- 1m level.",1033,-58.41,-21.78,-73.59,-52.63,1,1,9603,0,0,0,,,,,0
-186,6964,4191,4326,"Parameter values from Albanian 1987 to ETRS89 (1) (code 6963). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Use only for horizontal coordinates; geoid heights must be calculated with ALBGEO3 software.",3212,39.64,42.67,19.22,21.06,1,0,9607,-44.183,-0.58,-38.489,2.3867,2.7072,-3.5196,-8.2703,1
-187,15873,4192,4326,Derived at Manoca tower assuming the pyramid on the tower and the centre of the tower reservoir are co-located. This assumption carries a few metres uncertainty.,Oil exploration.,2555,2.16,4.99,8.45,10.4,1,0,9603,-206.1,-174.7,-87.7,,,,,1
-188,1796,4193,4326,"Derived at two points, checked at a third by Stolt Comex Seaway and Geoid for Elf.",Oil industry,2555,2.16,4.99,8.45,10.4,1,0,9603,-70.9,-151.8,-41.4,,,,,1
-189,1797,4194,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",3362,59.74,79,-73.29,-42.52,1,0,9603,164,138,-189,,,,,1
-190,1798,4194,4326,,Topographic mapping.,3362,59.74,79,-73.29,-42.52,1,0,9606,163.511,127.533,-159.789,0,0,0.814,-0.6,0
-191,1799,4195,4326,,Topographic mapping.,2570,68.66,74.58,-29.69,-19.89,1,0,9606,105,326,-102.5,0,0,0.814,-0.6,1
-192,1800,4196,4326,,Topographic mapping.,2571,65.52,65.91,-38.86,-36.81,1,0,9606,-45,417,-3.5,0,0,0.814,-0.6,1
-193,15796,4709,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3200,24.67,24.89,141.2,141.42,1,0,9603,145,75,-272,,,,,1
-194,15798,4710,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3183,-16.08,-15.85,-5.85,-5.58,1,0,9603,-320,550,-494,,,,,1
-195,15799,4711,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1872,24.22,24.35,153.91,154.05,1,0,9603,124,-234,-25,,,,,1
-196,1281,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90 (1) (tfm code 1257) and PZ-90 to WGS 84 (2) (tfm code 1244). Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5043.",Accuracy 1 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,24.82,-131.21,-82.66,0,0,-0.16,-0.12,0
-197,5043,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90.02 to WGS 84. Replaces Pulkovo 1995 to WGS 84 (1), tfm code 1281.",Accuracy 1 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,24.47,-130.89,-81.56,0,0,-0.13,-0.22,1
-198,1100,4201,4326,Derived at 22 stations.,For military purposes only. Accuracy 5m in each axis.,1271,3.4,22.24,21.82,47.99,1,0,9603,-166,-15,204,,,,,1
-199,1101,4201,4326,"Derived at 1 station connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: the Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Burkino Faso.",For military purposes. Accuracy 25m in each axis.,1057,9.39,15.09,-5.53,2.4,1,0,9603,-118,-14,218,,,,,0
-200,1102,4201,4326,"Derived at 1 station connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: the Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Cameroon.",For military purposes. Accuracy 25m in each axis.,3226,1.65,13.09,8.45,16.21,1,0,9603,-134,-2,210,,,,,0
-201,1103,4201,4326,Derived at 8 stations.,For military purposes. Accuracy 3m in each axis.,1091,3.4,14.89,32.99,47.99,1,0,9603,-165,-11,206,,,,,0
-202,1104,4201,4326,"Derived at 1 station connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: the Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Mali.",For military purposes. Accuracy 25m in each axis.,1153,10.14,25.01,-12.25,4.26,1,0,9603,-123,-20,220,,,,,0
-203,1105,4201,4326,"Derived at 2 stations connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: The Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Senegal.",For military purposes. Accuracy 25m in each axis.,3304,12.29,16.7,-17.59,-11.36,1,0,9603,-128,-18,224,,,,,0
-204,1106,4201,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3311,3.49,22.24,21.82,38.66,1,0,9603,-161,-14,205,,,,,0
-205,1108,4202,4326,"Derived at 105 stations. Replaced by AGD66 to WGS 84 (20) (code 6905).",For military purposes only. Accuracy 3m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-133,-48,148,,,,,0
-206,1665,4202,4326,"Parameter values from AGD66 to GDA94 (2) (code 1458). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in A.C.T. 1m accuracy.,2283,-35.93,-35.12,148.76,149.4,1,0,9607,-129.193,-41.212,130.73,-0.246,-0.374,-0.329,-2.955,0
-207,1666,4202,4326,"Parameter values from AGD66 to GDA94 (4) (code 1460). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in NSW and Victoria. 1m accuracy.,2286,-39.2,-28.15,140.96,153.69,1,0,9607,-119.353,-48.301,139.484,-0.415,-0.26,-0.437,-0.613,0
-208,1667,4202,4326,"Parameter values from AGD66 to GDA94 (8) (code 1594). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Tasmania. 1m accuracy.,1282,-43.7,-39.52,143.77,148.55,1,0,9607,-120.271,-64.543,161.632,-0.217,0.067,0.129,2.499,0
-209,1668,4202,4326,"Parameter values from AGD66 to GDA94 (9) (code 1595). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Northern Territory. 1m accuracy.,2284,-26.01,-10.86,128.99,138,1,0,9607,-124.133,-42.003,137.4,0.008,-0.557,-0.178,-1.854,0
-210,5841,4202,4326,Derived at 25 stations in 2007.,"Accuracy 2m in 2007. Due to significant tectonic activity in PNG, AGD66 and WGS 84 are separating by approximately 7cm per year.",4013,-8.28,-5.59,142.24,144.75,1,0,9603,-124,-60,154,,,,,0
-211,6905,4202,4326,"Derived at 161 stations. Replaces AGD66 to WGS 84 (1) (code 1108).",For military purposes only. Accuracy 5m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-128,-52,153,,,,,0
-212,6943,4202,4326,"Parameter values taken from AGD66 to PNG94 (3) (code 6938). Approximation at the +/- 5m level assuming that PNG94 is equivalent to WGS 84 within the accuracy of the transformation.",Low accuracy transformation suitable for mapping and navigation purposes only.,4214,-10.76,-2.53,140.85,150.96,1,0,9603,-129,-58,152,,,,,0
-213,6944,4202,4326,"Parameter values taken from AGD66 to PNG94 (5) (code 6940). Approximation at the +/- 4m level assuming that PNG94 is equivalent to WGS 84 within the accuracy of the transformation.",Low accuracy transformation suitable for mapping and navigation purposes only.,4013,-8.28,-5.59,142.24,144.75,1,0,9603,-131.3,-55.3,151.8,,,,,0
-214,6945,4202,4326,"Parameter values taken from AGD66 to PNG94 (7) (code 6942). Approximation at the +/- 4m level assuming that PNG94 is equivalent to WGS 84 within the accuracy of the transformation.",Low accuracy transformation suitable for mapping and navigation purposes only.,4216,-6.6,-5.05,140.89,141.54,1,0,9603,-137.4,-58.9,150.4,,,,,0
-215,15788,4202,4326,"Parameter values from AGD66 to GDA94 (1) (code 1278). Derived at 162 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",5m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-127.8,-52.3,152.9,,,,,0
-216,15980,4202,4326,"Parameter values from AGD66 to GDA94 (12) (code 15979). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Use only offshore: onshore tfms 1665-68 for ACT, NSW/Vic, Tas and NT respectively are more accurate.",3m accuracy.,3559,-47.2,-8.88,109.23,163.2,1,0,9607,-117.808,-51.536,137.784,-0.303,-0.446,-0.234,-0.29,1
-217,1109,4203,4326,"Derived at 90 stations. Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",For military purposes only. Accuracy 2m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-134,-48,149,,,,,1
-218,1236,4203,4326,"""Higgins parameters"". Replaced by AGD84 to GDA94 (2) (code 1280) and AGD84 to WGS 84 (7) (code 1669). Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",Preliminary estimate.,2575,-43.7,-9.86,112.85,153.69,1,0,9607,-116,-50.47,141.69,-0.23,-0.39,-0.344,0.0983,0
-219,1669,4203,4326,"Parameter values from AGD84 to GDA94 (2) (code 1280). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces AGD84 to WGS 84 (2) (code 1236). Note: AGD84 officially adopted only in Qld, SA and WA.",1m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9607,-117.763,-51.51,139.061,-0.292,-0.443,-0.277,-0.191,0
-220,15789,4203,4326,"Parameter values from AGD84 to GDA94 (1) (code 1279). Derived at 327 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the tfm. AGD84 officially adopted only in Queensland, South Australia and Western Australia.",5m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-128.5,-53,153.4,,,,,0
-221,1055,4204,4326,Derived at station K1.,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-145.7,-249.1,1.5,,,,,0
-222,1056,4204,4326,"Derivation is more precise, but no evidence that accuracy is better than Ain el Abd to WGS 84 (3). OGP recommends using Ain el Abd to WGS 84 (3).",1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9607,-85.645,-273.077,-79.708,-2.289,1.421,-2.532,3.194,0
-223,1057,4204,4326,.,1 metre accuracy.,2956,29.1,30.09,46.54,48.42,1,0,9607,-202.234,-168.351,-63.51,-3.545,-0.659,1.945,2.1,0
-224,1058,4204,4326,,1 metre accuracy.,2957,28.53,29.45,46.54,48.48,1,0,9607,-18.944,-379.364,-24.063,-0.04,0.764,-6.431,3.657,0
-225,1110,4204,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,3943,25.53,26.34,50.39,50.85,1,0,9603,-150,-250,-1,,,,,0
-226,1111,4204,4326,Derived at 9 stations.,For military purposes. Accuracy 10m in each axis.,3303,15.61,32.16,34.51,55.67,1,0,9603,-143,-236,7,,,,,1
-227,1107,4205,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3308,-1.71,12.03,40.99,51.47,1,0,9603,-43,-163,45,,,,,1
-228,15846,4706,4326,"Sometime referred to as ""Egypt 1907 to WGS 84"". However, application to WGS 84 coordinates of the reverse of this tfm results in Gulf of Suez S-650 TL, not Egypt 1907, position. Gulf of Suez S-650 TL and Egypt 1907 CRSs differ by some 20 metres.",Used for oil exploration by GUPCO.,2341,27.19,30.01,32.34,34.27,1,0,9603,-146.21,112.63,4.05,,,,,1
-229,1656,4207,4326,"Parameter values from Lisbon to ETRS89 (1) (code 1655). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Lisbon to WGS 84 (4) (code 1988).",For applications to an accuracy of 3 metres.,1294,36.95,42.16,-9.56,-6.19,1,0,9606,-280.9,-89.8,130.2,-1.721,0.355,-0.371,-5.92,0
-230,1944,4207,4326,"Parameter values from Lisbon to ETRS89 (2) (code 1790). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1294,36.95,42.16,-9.56,-6.19,1,1,9606,-282.1,-72.2,120,-1.592,0.145,-0.89,-4.46,0
-231,1984,4207,4326,,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-304.046,-60.576,103.64,,,,,1
-232,1988,4207,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-288.885,-91.744,126.244,1.691,-0.41,0.211,-4.598,0
-233,6898,4207,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-306,-62,105,,,,,0
-234,15877,4720,4326,"Suitable for GIS mapping purposes but not rigorous surveying. Very similar results may be obtained through Fiji 1986 to WGS 84 (1) (tfm code 15876).","Horizontal accuracy 2m, vertical accuracy approximately 40 metres..",3398,-19.22,-16.1,176.81,-179.77,1,0,9607,-35.173,136.571,-36.964,1.37,-0.842,-4.718,-1.537,0
-235,15876,4720,4326,"Approximation at the +/- 2m level assuming that Fiji 1986 is equivalent to WGS 72. Parameter values taken from WGS 72 to WGS 84 (1) (tfm code 1237).",tbc,1094,-20.81,-12.42,176.81,-178.15,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
-236,1113,4209,4326,Derived at 41 stations.,"For military purposes only. Accuracy 20m, 33m and 20m in X, Y and Z axes.",2312,-30.66,-8.19,19.99,35.93,1,0,9603,-143,-90,-294,,,,,1
-237,1114,4209,4326,Derived at 9 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1051,-26.88,-17.78,19.99,29.38,1,0,9603,-138,-105,-289,,,,,0
-238,1115,4209,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.86,1,1,9603,-153,-5,-292,,,,,0
-239,1116,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 3m and 8m in X, Y and Z axes.",1141,-30.66,-28.57,27.01,29.46,1,0,9603,-125,-108,-295,,,,,0
-240,1117,4209,4326,Derived at 6 stations.,"For military purposes. Accuracy 9m, 24m and 8m in X, Y and Z axes.",1150,-17.14,-9.37,32.68,35.93,1,0,9603,-161,-73,-317,,,,,0
-241,1118,4209,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1224,-27.32,-25.72,30.79,32.14,1,0,9603,-134,-105,-295,,,,,0
-242,1119,4209,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1259,-13.46,5.39,11.79,31.31,1,1,9603,-169,-19,-278,,,,,0
-243,1120,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 21m, 21m and 27m in X, Y and Z axes.",1260,-18.08,-8.19,21.99,33.71,1,0,9603,-147,-74,-283,,,,,0
-244,1121,4209,4326,"Derived at 10 stations. Replaced by Arc 1950 to WGS 84 (10), tfm code 6906.","For military purposes. Accuracy 5m, 8m and 11m in X, Y and Z axes.",1261,-22.42,-15.61,25.23,33.08,1,0,9603,-142,-96,-293,,,,,0
-245,6904,4209,4326,"Derived at 7 stations. Info source gives source CRS as Arc 1960. From inspection of parameter values, comparison of those from DMA TR8350.2 transformations and geographic applicability of CRS, OGP believes that this should be Arc 1950.","For military purposes only. Accuracy 13m, 25m and 7m in X, Y and Z axes.",1150,-17.14,-9.37,32.68,35.93,1,0,9603,-179,-81,-314,,,,,0
-246,6906,4209,4326,"Derived at 38 stations. Replaces Arc 1950 to WGS 84 (9), tfm code 1121.","For military purposes. Accuracy 10m in each of X, Y and Z axes.",1261,-22.42,-15.61,25.23,33.08,1,0,9603,-145,-97,-292,,,,,0
-247,1122,4210,4326,Derived at 25 stations.,For military purposes only. Accuracy 20m in each axis.,2311,-11.75,4.63,29.34,41.91,1,0,9603,-160,-6,-302,,,,,1
-248,1284,4210,4326,Derived at 24 stations.,"For military purposes. Accuracy 4m, 3m and 3m in X, Y and Z axes.",3264,-4.72,4.63,33.9,41.91,1,0,9603,-157,-2,-299,,,,,0
-249,1285,4210,4326,Derived at 12 stations.,"For military purposes. Accuracy 6m, 9m and 10m in X, Y and Z axes.",3316,-11.75,-0.99,29.34,40.48,1,0,9603,-175,-23,-303,,,,,0
-250,3998,4210,4326,"Derived at 3 stations. From inspection of parameter values and geographic applicability of CRS, OGP believes that the published source CRS (Arc 1950) has been misidentified by information source. Analysis of TR8350.2 contour charts suggest Arc 1960.",For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.86,1,0,9603,-153,-5,-292,,,,,0
-251,1123,4211,4326,"Note: The area of use cited for this transformation (Sumatra) is not consistent with the area of use (Java) for the Batavia (Genuk) coordinate reference system. Derived at 5 stations.",For military purposes. Accuracy 3m in each axis.,1355,-5.99,5.97,95.16,106.13,1,0,9603,-377,681,-50,,,,,1
-252,1813,4211,4326,Used by ARCO offshore NW Java area.,Oil industry operations.,2577,-6.89,-4.07,105.77,110.01,1,0,9603,-378.873,676.002,-46.255,,,,,0
-253,1814,4211,4326,Used by PT Komaritim for Nippon Steel during East Java Gas Pipeline construction.,Oil industry operations.,2588,-8.46,-6.8,112.8,117.01,1,0,9603,-377.7,675.1,-52.2,,,,,0
-254,15793,4212,4326,"Derived at 2 stations (S40 and M1, St Annes Tower) in 2004.",Accuracy 2.5m.,3218,13,13.39,-59.71,-59.37,1,0,9603,31.95,300.99,419.19,,,,,1
-255,15809,4725,4326,"Derived at 2 satellite stations. Note: NGA online html files carry a different dZ value - OGP believe this is an erroneous transcription from the TR8350.2 line above.","Military and topographic mapping. Accuracy +/- 25m in each axis.",3201,16.67,16.79,-169.59,-169.47,1,0,9603,189,-79,-202,,,,,1
-256,6143,4726,4326,"Parameter values are taken from SIGD59 to CIGD11 (1) (code 6137) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3186,19.63,19.78,-80.14,-79.69,1,0,9607,8.853,-52.644,180.304,0.393,2.323,-2.96,-24.081,1
-257,15814,4726,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",3186,19.63,19.78,-80.14,-79.69,1,0,9603,42,124,147,,,,,0
-258,15829,4726,4326,Determined from 2 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3186,19.63,19.78,-80.14,-79.69,1,0,9603,44.4,109,151.7,,,,,0
-259,6907,4713,4326,"Derived at 2 stations. Replaces Ayabelle Lighthouse to WGS 84 (1) (code 15800).",For military purposes only. Accuracy 10m in each axis.,3238,10.94,12.72,41.75,43.48,1,0,9603,-77,-128,142,,,,,1
-260,15800,4713,4326,"Derived at 1 satellite station. Replaced by Ayabelle Lighthouse to WGS 84 (2) (code 6907).",For military purposes only. Accuracy 25m in each axis.,1081,10.94,12.72,41.75,44.15,1,0,9603,-79,-129,145,,,,,0
-261,1124,4216,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3221,32.21,32.43,-64.89,-64.61,1,0,9603,-73,213,296,,,,,1
-262,15970,4216,4326,"Parameter values from Bermuda 1957 to BDA2000 (1) (code 15969). Assumes BDA2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy +/- 1 metre.",3221,32.21,32.43,-64.89,-64.61,1,0,9607,-292.295,248.758,429.447,-4.9971,-2.99,-6.6906,1.0289,0
-263,15819,4729,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25 m in each axis.",3208,-25.14,-25,-130.16,-130.01,1,0,9603,185,165,42,,,,,1
-264,1125,4218,4326,Derived in 1987 at 7 stations.,"For military purposes. Accuracy 6m, 5m and 6m in X, Y and Z axes.",3686,-4.23,13.68,-79.1,-66.87,1,0,9603,307,304,-318,,,,,1
-265,1597,4218,4326,Derived in 1995 by WGC at first order stations Recreo and Mena via multi-day ties to 4 IGS stations. Residuals under 20cm.,Oil exploration.,2315,4.75,5.68,-73,-72.25,1,0,9603,304.5,306.5,-318.1,,,,,0
-266,15715,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (1) (tfm code 15714).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3082,9.8,12.52,-73,-71.06,1,0,9607,-806.413,-263.5,-622.671,12.414219,-2.9908418,-39.034686,-20.81616,0
-267,15717,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (2) (tfm code 15716).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3083,9.39,11.59,-76.08,-73,1,0,9607,100.783,187.382,-47,-9.2238300,2.4238033,-8.3082783,-13.56561,0
-268,15719,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (3) (tfm code 15718).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3084,8,9.4,-77.48,-74.39,1,0,9607,336.026,348.565,252.978,-17.241289,-6.3064928,1.5620498,-5.771909,0
-269,15721,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (4) (tfm code 15720).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3085,5,9.4,-74.4,-71.99,1,0,9607,963.273,486.386,190.997,-16.485036,-1.6688258,21.692849,-13.89914,0
-270,15723,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (5) (tfm code 15722).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3086,5,8.01,-77.92,-74.39,1,0,9607,-90.29,247.559,-21.989,-8.6968853,-4.1880336,-12.808267,2.181658,0
-271,15725,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (6) (tfm code 15724).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3087,3,5.01,-77.68,-74.39,1,0,9607,-0.562,244.299,-456.938,6.8668710,-8.2526735,-9.2967797,3.74656,0
-272,15727,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (7) (tfm code 15726).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3088,-1.13,3.01,-79.1,-74,1,0,9607,-305.356,222.004,-30.023,-9.6904939,1.0319682,-19.757394,6.325747,0
-273,15729,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (8) (tfm code 15728).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3089,-4.23,7.1,-74.4,-66.87,1,0,9607,221.899,274.136,-397.554,2.8084459,-0.44850859,-2.810172,-2.199943,0
-274,1126,4219,4326,Accuracy estimate not available.,For military purposes.,1287,-3.3,-1.44,105.07,108.35,1,0,9603,-384,664,-48,,,,,1
-275,1318,4220,4326,,Used for oil exploration by Conoco.,2316,-8.59,-7.75,12.58,13.4,1,0,9603,-42.01,-332.21,-229.75,,,,,0
-276,1319,4220,4326,,Used for oil exploration by Texaco.,2317,-7.01,-6.01,12.08,12.84,1,0,9603,-40,-354,-224,,,,,0
-277,1320,4220,4326,"Replaced by Camacupa to WGS 84 (9). Used by Shell prior to 1994.",Oil exploration prior to 1994.,2321,-7.26,-6.03,11.08,12.09,1,0,9606,-37.2,-370.6,-224,0,0,0.554,0.219,0
-278,1321,4220,4326,"Derived as mean of 123 Transit passes at station Cabo Ledo NE base in November 1990. Used by Elf for block 7 up to December 1992 then replaced by Camacupa to WGS 84 (7). Used by Total in block 8, ExxonMobil block 24, Western Geophysical for spec. data.",Oil exploration.,2320,-17.26,-6.01,8.2,13.86,1,0,9603,-41.8,-342.2,-228.2,,,,,0
-279,1322,4220,4326,"Derived at station Djeno during coordination of platform PAL F2 in February 1992. Used by Elf for block 3 up to December 1992 then replaced by Camacupa to WGS 84 (7).",Oil exploration.,2318,-7.34,-6.66,11.74,12.5,1,0,9603,-55.5,-348,-229.2,,,,,0
-280,1323,4220,4326,Derived at Luanda observatory December 1992.,Used for oil exploration by Elf for 1993 block 7 shallow water survey.,2319,-10.09,-9.41,12.66,13.39,1,0,9603,-43,-337,-233,,,,,0
-281,1324,4220,4326,"Derived at platform PAL F2 in December 1992. For use in blocks 3, 7 and 17, replaced by Camacupa to WGS 84 (10) (code 1327).","Used for oil exploration by Elf for blocks 3, 7 and 17 between December 1992 and 1994 then superseded by Camacupa to WGS 84 (10). Used by Exxon for block 15 since 1993.",2322,-10.09,-6.03,10.83,13.39,1,0,9603,-48,-345,-231,,,,,0
-282,1325,4220,4326,"Derived at platform PAL F2 in December 1992. Used by Total for block 2 between December 1992 and 1994 then replaced by Camacupa to WGS 84 (10).",Oil exploration between December 1992 and 1994.,2317,-7.01,-6.01,12.08,12.84,1,0,9603,-48.6,-345.1,-230.8,,,,,0
-283,1326,4220,4326,"Derived by GPS on two Topnav DGPS reference stations at Djeno and Luanda. Replaces Camacupa to WGS 84 (3). In block 18 replaced by BP from 1999 by Camacupa to WGS 84 (10).",Used by Shell since 1994.,2323,-8.34,-6.03,11.08,12.75,1,0,9606,-41.057,-374.564,-226.287,0,0,0.554,0.219,0
-284,1327,4220,4326,Derived at platform PAL F2 in 1994 by Topnav using Doris.,Used for oil exploration by Elf in blocks 3 and 17 since 1994. Used by Total in block 2 since 1994. Adopted by BP-Amoco Elf and Exxon for blocks 18 and 31-33 in 1999.,2324,-8.59,-6.01,10.41,12.84,1,0,9603,-50.9,-347.6,-231,,,,,1
-285,1127,4221,4326,Derived at 20 stations.,For military purposes. Accuracy 5m in each axis.,3843,-54.93,-21.78,-73.59,-53.65,1,0,9603,-148,136,90,,,,,1
-286,1527,4221,4326,"Derived through ties at 2 stations (Cerro Colorado and Chihuido Sur) to 4 IGS stations in February 1995",Oil exploration.,2325,-37.5,-36.14,-70.5,-70.03,1,0,9603,-154.5,150.7,100.4,,,,,0
-287,1128,4222,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 6m and 6m in X, Y and Z axes.",3309,-34.88,-22.13,16.45,32.95,1,0,9603,-136,-108,-292,,,,,1
-288,1129,4222,4326,"Parameter values are from Cape to Hartebeesthoek94 (1) (code 1504) assuming that Hartebeesthoek94 and WGS 84 are equivalent within the accuracy of the transformation. Residuals should not exceed 15 metres.",Accuracy 15m.,3309,-34.88,-22.13,16.45,32.95,1,0,9603,-134.73,-110.92,-292.66,,,,,0
-289,1130,4223,4326,Derived at 5 stations.,"For military purposes. Accuracy 6m, 9m and 8m in X, Y and Z axes.",1236,30.23,38.41,7.49,13.67,1,0,9603,-263,6,431,,,,,1
-290,1538,4223,4326,Derived at station Chaffar January 1995.,Oil exploration.,1489,33.22,38.41,7.81,13.67,1,0,9603,-260.1,5.5,432.2,,,,,0
-291,1131,4224,4326,Derived at 6 stations.,"For military purposes. Accuracy 6m, 9m and 5m in X, Y and Z axes.",3675,-22,-19.29,-62.57,-57.81,1,0,9603,-134,229,-29,,,,,0
-292,3972,4224,4326,"Mandatory for SICAD use until 2005. Replaced by Chua to SIRGAS 2000 (tfm code 4069).","Used by governmental agencies in Distrito Federal until adoption of SIRGAS 2000 by Brazil in 2005. Legally mandated for Cartography System of Distrito Federal (SICAD) until 2005.",3619,-15.94,-15.37,-48.1,-47.1,1,0,9603,-143.87,243.37,-33.52,,,,,1
-293,4834,4224,4326,"Parameter values from Chua to SIRGAS 2000 (1) (tfm code 4069) assuming that within the tfm accuracy SIRGAS 2000 is equivalent to WGS 84.","Cartography System of Distrito Federal (SICAD)",3619,-15.94,-15.37,-48.1,-47.1,1,0,9603,-144.35,242.88,-33.2,,,,,0
-294,1132,4225,4326,Derived at 17 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206,172,-6,,,,,0
-295,6192,4225,4326,"Formed by concatenation of tfms codes 6191 and 1877. Used by Petrobras and ANP until February 2005 when replaced by Corrego Alegre 1970-72 to WGS 84 (4) (tfm code 6194).",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-205.57,168.77,-4.12,,,,,1
-296,6194,4225,4326,"Parameter values from Corrego Alegre to SIRGAS 2000 (2) (tfm code 6193) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras from February 2005, replacing use of tfm code 6192.",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206.05,168.28,-3.82,,,,,0
-297,15842,4739,4326,"Derived at 2 satellite stations. Care: does not use Hong Kong 1963 (code 4838) as the source CRS.","Military mapping. Accuracy +/- 1m.",1118,22.13,22.58,113.76,114.51,1,0,9603,-156,-271,-189,,,,,1
-298,1244,4740,4326,"Mandated for use in Russia by GosStandard of Russia Decree #327 of August 9, 2001. Republished but with one significant figure less precision to parameter values in GOST R 51794-2008 of December 18 2008.",Geodetic applications. Accuracy better than 0.5 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,-1.08,-0.27,-0.9,0,0,-0.16,-0.12,0
-299,15843,4740,4326,"Derived through Glonass and GPS at 30 stations throughout USSR - Former Soviet Union (FSU).",Geodetic applications. Accuracy better than 1.5 metres.,1262,-90,90,-180,180,1,0,9607,0,0,1.5,0,0,-0.076,0,1
-300,1148,4229,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 6m and 8m in X, Y and Z axes.",1086,21.89,33.82,24.7,37.91,1,0,9603,-130,110,-13,,,,,1
-301,1546,4229,4326,,Used for oil exploration by GUPCO.,2341,27.19,30.01,32.34,34.27,1,1,9603,-146.21,112.63,4.05,,,,,0
-302,1075,4230,4326,"Derived in 1987 by Geodetic for TPAO. Used on BP 1991/92 2D seismic surveys in central and eastern Turkish sector of Black Sea. In Turkey, replaced by tfm code 1784. Also adopted for use offshore Israel.",Oil Exploration,2896,31.35,43.45,28.03,41.47,1,0,9603,-89.05,-87.03,-124.56,,,,,0
-303,1087,4230,4326,,Topographic mapping.,1130,29.18,33.38,34.88,39.31,1,0,9603,-112,-110.3,-140.2,,,,,0
-304,1133,4230,4326,Derived at 85 stations. In Germany will be accepted by LBA for minerals management purposes as alternative to tfm 1052 or 1998.,"For military purposes. Accepted for minerals management in Germany. Accuracy 3m, 8m and 5m in X, Y and Z axes.",2420,34.88,71.21,-9.56,31.59,1,0,9603,-87,-98,-121,,,,,1
-305,1134,4230,4326,Derived at 52 stations.,For military purposes only. Accuracy 3m each axis.,2421,42.33,57.8,-4.87,17.17,1,0,9603,-87,-96,-120,,,,,0
-306,1135,4230,4326,Accuracy estimate not available.,For military purposes only.,2345,15.61,37.39,34.17,55.67,1,0,9603,-103,-106,-141,,,,,0
-307,1136,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,1078,32.88,36.21,29.95,35.2,1,0,9603,-104,-101,-140,,,,,0
-308,1137,4230,4326,Derived at 14 stations.,"For military purposes. Accuracy 6m, 8m and 8m in X, Y and Z axes.",2595,25.71,31.68,24.7,30,1,0,9603,-130,-117,-151,,,,,0
-309,1138,4230,4326,Derived at 40 stations.,For military purposes only. Accuracy 3m in each axis.,2343,49.11,60.9,-10.56,1.84,1,0,9603,-86,-96,-120,,,,,0
-310,1139,4230,4326,Derived at 20 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",2344,57.93,71.21,4.68,31.59,1,0,9603,-87,-95,-120,,,,,0
-311,1140,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3254,34.88,41.75,19.57,28.3,1,0,9603,-84,-95,-130,,,,,0
-312,1142,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,2339,38.82,41.31,8.08,9.89,1,0,9603,-97,-103,-120,,,,,0
-313,1143,4230,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2340,36.59,38.35,12.36,15.71,1,0,9603,-97,-88,-135,,,,,0
-314,1144,4230,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3275,35.74,36.05,14.27,14.63,1,0,9603,-107,-88,-149,,,,,0
-315,1145,4230,4326,Derived at 18 stations.,"For military purposes only. Accuracy 5m, 6m and 3m in X, Y and Z axes.",2338,35.26,43.82,-9.56,3.39,1,0,9603,-84,-107,-120,,,,,0
-316,1245,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 25m in each axis.,1236,30.23,38.41,7.49,13.67,1,0,9603,-112,-77,-145,,,,,0
-317,1275,4230,4326,"These same parameter values are used to transform to ETRS89. See ED50 to ETRS89 (10) (code 1650).",For applications to an accuracy of 2 metres.,1096,41.15,51.56,-9.86,10.38,1,0,9603,-84,-97,-117,,,,,0
-318,1311,4230,4326,"Based on ED50 to WGS72 (precise ephemeris) 6-nations agreement of 1981 to which precise to broadcast and broadcast to WGS 84 transformations have been concatenated.",Recommended transformation for UKCS and IrishCS petroleum purposes.,2342,47.42,63.89,-16.1,10.86,1,0,9606,-89.5,-93.8,-123.1,0,0,-0.156,1.2,0
-319,1440,4230,4326,,Used in oil industry.,3254,34.88,41.75,19.57,28.3,1,0,9603,-86,-92.2,-127.5,,,,,0
-320,1612,4230,4326,"Parameter values are taken from ED50 to ETRS89 (1), code 1588. Adopted for ED50 to WGS84 transformations offshore Norway north of 62N from April 2001 when it replaced code 1590. Included in Statens Kartverk programme wsktrans from v4.0.",Oil industry offshore.,2601,62,84.17,-3.7,39.65,1,0,9606,-116.641,-56.931,-110.559,0.893,0.921,-0.917,-3.52,0
-321,1613,4230,4326,"Approximation to 1 metre of concatenated transformation ED50 to WGS 84 (14), code 8653. 8653 remains the transformation promulgated by Statens Kartverk but 1613 recommended by EPSG for practical oil industry usage.",Approximation to 1 metre for oil industry use.,2334,56.08,62,1.37,11.14,1,0,9606,-90.365,-101.13,-123.384,0.333,0.077,0.894,1.994,0
-322,1627,4230,4326,"Parameter values from ED50 to ETRS89 (4) (code 1626). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3237,54.51,57.8,8,15.24,1,0,9606,-81.1,-89.4,-115.8,0.485,0.024,0.413,-0.54,0
-323,1629,4230,4326,"Parameter values from ED50 to ETRS89 (5) (code 1628). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1105,36,36.16,-5.42,-4.89,1,0,9603,-116.8,-106.4,-154.4,,,,,0
-324,1631,4230,4326,"Parameter values from ED50 to ETRS89 (6) (code 1630). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2335,38.59,40.11,1.14,4.39,1,0,9606,-181.5,-90.3,-187.2,0.144,0.492,-0.394,17.57,0
-325,1633,4230,4326,"Parameter values from ED50 to ETRS89 (7) (code 1632). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2336,35.26,43.56,-7.54,3.39,1,0,9606,-131,-100.3,-163.4,-1.244,-0.02,-1.144,9.39,0
-326,1635,4230,4326,"Parameter values from ED50 to ETRS89 (8) (code 1634). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2337,41.5,43.82,-9.37,-4.5,1,0,9606,-178.4,-83.2,-221.3,0.54,-0.532,-0.126,21.2,0
-327,1784,4230,4326,"Parameter values from ED50 to ETRS89 (9) (code 1783). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1237,34.42,43.45,25.62,44.83,1,0,9606,-84.1,-101.8,-129.7,0,0,0.468,1.05,0
-328,1810,4230,4326,Derived via concatenation through WGS72. The ED50 to WGS72 step is the Sepplin 1974 value for all Europe.,Oil industry exploration and production operations.,2595,25.71,31.68,24.7,30,1,0,9606,-84,-103,-122.5,0,0,0.554,0.2263,0
-329,1853,4230,4326,Derived at a single point in Galway docks.,Used by Enterprise for Corrib.,2961,53.75,55.76,-12.5,-9.49,1,0,9603,-82.31,-95.23,-114.96,,,,,0
-330,1961,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.45,55.77,2.53,6.41,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.4428,1.218,0
-331,1985,4230,4326,May be taken as a transformation from ED50 to ETRS89 - see tfm code 5040.,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-87.987,-108.639,-121.593,,,,,0
-332,1989,4230,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-74.292,-135.889,-104.967,0.524,0.136,-0.61,-3.761,0
-333,1998,4230,4326,"Approximation to better than 0.5m of transformation adopted in June 2003 (see ED50 to WGS 84 (35), code 1052). Acceptable to Landesbergamt for Lower Saxony and Bundesanstalt für Seeschifffahrt und Hydrographie.",Recommended transformation for Germany North Sea petroleum purposes.,2879,53.6,55.92,3.34,8.88,1,0,9606,-157.89,-17.16,-78.41,2.118,2.697,-1.434,-5.38,0
-334,1999,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.45,55.77,2.53,6.41,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
-335,3904,4230,4326,"Parameter values from ED87 to WGS 84 (32) (tfm code 3905), assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3-5m. Used by NAM for offshore operations until mid 2004, then replaced by tfm code 1311.","E&P operations in the Dutch sector of the North Sea.",1630,51.45,55.77,2.53,6.41,1,0,9606,-83.11,-97.38,-117.22,0.005693,-0.044698,0.044285,0.1218,0
-336,15964,4230,4326,Developed by the Portuguese Hydrographic Institute and used by the Directorate of Energy and Geology.,Hydrography and minerals management offshore Portugal.,3537,34.91,41.88,-13.87,-7.24,1,0,9603,-86.277,-108.879,-120.181,,,,,0
-337,1146,4231,4326,,"?",2330,51.03,62.01,-5.05,11.14,1,0,9606,-82.981,-99.719,-110.709,-0.10470,0.031002,0.080402,-0.3143,0
-338,1960,4231,4326,,Scientific research.,1297,34.88,71.21,-10.56,31.59,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
-339,3905,4231,4326,"Parameter values taken from ED87 to ETRS89 (1) (tfm code 4078) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation. Used as a tfm between ED50 and WGS 84 - see code 3904.",Scientific research.,1297,34.88,71.21,-10.56,31.59,1,0,9606,-83.11,-97.38,-117.22,0.005693,-0.044698,0.044285,0.1218,1
-340,1256,4232,4326,"Derived at 7 stations. Replaced by Fahud to WGS 84 (3) (code 6908).","For military purposes. Accuracy 3m, 3m and 9m in X, Y and Z axes.",4009,16.59,26.42,51.99,59.91,1,0,9603,-346,-1,224,,,,,0
-341,1438,4232,4326,,Oil exploration.,4009,16.59,26.42,51.99,59.91,1,0,9606,-333.102,-11.02,230.69,0,0,0.554,0.219,1
-342,6908,4232,4326,"Derived at 11 stations. Replaces Fahud to WGS 84 (1) (code 1256).","For military purposes. Accuracy 3m, 3m and 6m in X, Y and Z axes.",4009,16.59,26.42,51.99,59.91,1,0,9603,-345,3,223,,,,,0
-343,1894,4233,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1152,-3.47,8.1,69.29,77.08,1,1,9603,-133,-321,50,,,,,0
-344,7033,4744,4326,Derived by concatenation of parameter values published by IGN Paris from Nahrwan 1934 to WGS 72 at the Nahrwan SE Base station near Baghdad with DMA WGS 72 to WGS 84 parameter values. For more accurate transformation away from origin see codes 7008-7032.,Oil exploration.,3625,29.06,37.39,38.79,48.61,1,0,9603,-242.2,-144.9,370.3,,,,,1
-345,15817,4727,4326,"Derived at 1 satellite station. Information source states ""provided for historical purposes only. These parameter [values] should not be used"". Replaced by Midway 1961 to WGS 84 (2) (tfm code 15818).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.28,-177.45,-177.31,1,0,9603,912,-58,1227,,,,,0
-346,15818,4727,4326,"Derived at 1 satellite station. Replaces Midway 1961 to WGS 84 (1) (tfm code 15817).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.28,-177.45,-177.31,1,0,9603,403,-81,277,,,,,1
-347,1152,4236,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,3315,21.87,25.34,119.25,122.06,1,0,9603,-637,-549,-203,,,,,1
-348,1242,4237,4326,"Parameter value error in info source Hungarian text but correct in English summary. Replaces HD72 to WGS 84 (2) (code 1831).",Accuracy at metre level throughout Hungary.,1119,45.74,48.58,16.11,22.9,1,0,9603,52.17,-71.82,-14.9,,,,,1
-349,1448,4237,4326,"Parameter values taken from HD72 to ETRS89 (2) (code 1449) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces HD72 to WGS 84 (1) (code 1830).","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.74,48.58,16.11,22.9,1,0,9607,52.684,-71.194,-13.975,0.312,0.1063,0.3729,1.0191,0
-350,1677,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1273) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1119,45.74,48.58,16.11,22.9,1,1,9607,56,75.77,15.31,-0.37,-0.2,-0.21,-1.01,0
-351,1830,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1829) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. OGP recommends use of newer MSZ 7222 equivalent (tfm code 1448) in preference to this transformation.","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.74,48.58,16.11,22.9,1,0,9607,56,-75.77,-15.31,0.37,0.2,0.21,1.01,0
-352,1831,4237,4326,"Derived at fundamental point Szolohegy and tested at 99 stations throughout Hungary. OGP recommends use of newer transformation (tfm code 1242) in preference to this transformation.",Accuracy better than 1m in all three dimensions throughout Hungary.,1119,45.74,48.58,16.11,22.9,1,0,9603,57.01,-69.97,-9.29,,,,,0
-353,1248,4238,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,4020,-10.98,5.97,95.16,141.01,1,0,9603,-24,-15,5,,,,,1
-354,1832,4238,4326,"Derived via coordinates of 2 Pulse8 stations. Use of ID74 to WGS 84 (3) (code 1833) is recommended.",For oil industry purposes.,4020,-10.98,5.97,95.16,141.01,1,0,9606,2.691,-14.757,4.724,0,0,0.774,-0.6,0
-355,1833,4238,4326,"Parameter values from ID74 to DGN95 (1) (code 15911) assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.","Standard deviations of translations are 1.3, 1.1 and 3.6m, of rotations 0.11, 0.06 and 0.04 sec and ppm 0.18.",4020,-10.98,5.97,95.16,141.01,1,0,9607,-1.977,-13.06,-9.993,-0.364,-0.254,-0.689,-1.037,0
-356,1153,4239,4326,Derived at 11 stations.,"For military purposes. Accuracy 15m, 6m and 12m in X, Y and Z axes.",3317,5.63,20.46,97.34,105.64,1,0,9603,217,823,299,,,,,1
-357,1154,4240,4326,"Derived at 62 stations. Replaced by Indian 1975 to WGS 84 (2) (code 1304).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.46,97.34,105.64,1,0,9603,209,818,290,,,,,0
-358,1304,4240,4326,"Derived at 62 stations. Replaces Indian 1975 to WGS 84 (1) (code 1154).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.46,97.34,105.64,1,0,9603,210,814,289,,,,,1
-359,1537,4240,4326,Derived in 1995 at point RTSD181.,Oil exploration.,2358,6.74,8.16,102.16,103.05,1,0,9603,204.64,834.74,293.8,,,,,0
-360,1812,4240,4326,,Cadastral survey.,3317,5.63,20.46,97.34,105.64,1,0,9606,293,836,318,0.5,1.6,-2.8,2.1,0
-361,1084,4242,4326,Derived via NAD27 and WGS 72. Preliminary values derived by Survey Department but not officially promulgated.,For applications requiring 5m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9603,70,207,389.5,,,,,1
-362,1085,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 2m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9603,65.334,212.46,387.63,,,,,0
-363,1086,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 1m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,1,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,-8.95,0
-364,15927,4242,4326,"Derived at 4 stations, tested at a further 9. Also used as tfm to JAD69 to JAD2001 (see code 15926).
+186,6964,4191,4326,"Parameter values from Albanian 1987 to ETRS89 (1) (code 6963). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Use only for horizontal coordinates; geoid heights must be calculated with ALBGEO3 software.",3212,39.64,42.67,19.22,21.06,1,1,9607,-44.183,-0.58,-38.489,2.3867,2.7072,-3.5196,-8.2703,0
+187,7834,4191,4326,"Parameter values from Albanian 1987 to ETRS89 (1) (code 7833). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Use only for horizontal coordinates; geoid heights must be calculated with ALBGEO3 software.",3212,39.64,42.67,19.22,21.06,1,0,9607,-44.183,-0.58,-38.489,-2.3867,-2.7072,3.5196,-8.2703,1
+188,15873,4192,4326,Derived at Manoca tower assuming the pyramid on the tower and the centre of the tower reservoir are co-located. This assumption carries a few metres uncertainty.,Oil exploration.,2555,2.16,4.99,8.45,10.4,1,0,9603,-206.1,-174.7,-87.7,,,,,1
+189,1796,4193,4326,"Derived at two points, checked at a third by Stolt Comex Seaway and Geoid for Elf.",Oil industry,2555,2.16,4.99,8.45,10.4,1,0,9603,-70.9,-151.8,-41.4,,,,,1
+190,1797,4194,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",3362,59.74,79,-73.29,-42.52,1,0,9603,164,138,-189,,,,,1
+191,1798,4194,4326,,Topographic mapping.,3362,59.74,79,-73.29,-42.52,1,0,9606,163.511,127.533,-159.789,0,0,0.814,-0.6,0
+192,1799,4195,4326,,Topographic mapping.,2570,68.66,74.58,-29.69,-19.89,1,0,9606,105,326,-102.5,0,0,0.814,-0.6,1
+193,1800,4196,4326,,Topographic mapping.,2571,65.52,65.91,-38.86,-36.81,1,0,9606,-45,417,-3.5,0,0,0.814,-0.6,1
+194,15796,4709,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3200,24.67,24.89,141.2,141.42,1,0,9603,145,75,-272,,,,,1
+195,15798,4710,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,3183,-16.08,-15.85,-5.85,-5.58,1,0,9603,-320,550,-494,,,,,1
+196,7894,4710,4326,"Parameter values from Astro DOS 71 to SHGD2015 (1) (tfm code 7893). Assumes SHGD2015 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications requiring an accuracy of better than 1 metre.,3183,-16.08,-15.85,-5.85,-5.58,1,0,9603,-323.65,551.39,-491.22,,,,,0
+197,15799,4711,4326,Derived at 1 satellite station.,For military purposes only. Accuracy 25m in each axis.,1872,24.22,24.35,153.91,154.05,1,0,9603,124,-234,-25,,,,,1
+198,1281,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90 (1) (tfm code 1257) and PZ-90 to WGS 84 (2) (tfm code 1244). Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5043.",Accuracy 1 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,24.82,-131.21,-82.66,0,0,-0.16,-0.12,0
+199,5043,4200,4326,"Derived through concatenation of Pulkovo 1995 to PZ-90.02 to WGS 84. Replaces Pulkovo 1995 to WGS 84 (1), tfm code 1281.",Accuracy 1 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,24.47,-130.89,-81.56,0,0,-0.13,-0.22,1
+200,1100,4201,4326,Derived at 22 stations.,For military purposes only. Accuracy 5m in each axis.,1271,3.4,22.24,21.82,47.99,1,0,9603,-166,-15,204,,,,,1
+201,1101,4201,4326,"Derived at 1 station connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: the Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Burkino Faso.",For military purposes. Accuracy 25m in each axis.,1057,9.39,15.09,-5.53,2.4,1,0,9603,-118,-14,218,,,,,0
+202,1102,4201,4326,"Derived at 1 station connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: the Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Cameroon.",For military purposes. Accuracy 25m in each axis.,3226,1.65,13.09,8.45,16.21,1,0,9603,-134,-2,210,,,,,0
+203,1103,4201,4326,Derived at 8 stations.,For military purposes. Accuracy 3m in each axis.,1091,3.4,14.89,32.99,47.99,1,0,9603,-165,-11,206,,,,,0
+204,1104,4201,4326,"Derived at 1 station connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: the Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Mali.",For military purposes. Accuracy 25m in each axis.,1153,10.14,25.01,-12.25,4.26,1,0,9603,-123,-20,220,,,,,0
+205,1105,4201,4326,"Derived at 2 stations connected to the Adindan (Blue Nile 1958) network through the 1968-69 12th parallel traverse. Note: The Adindan (Blue Nile 1958) CRS is used in Ethiopia and Sudan, not Senegal.",For military purposes. Accuracy 25m in each axis.,3304,12.29,16.7,-17.59,-11.36,1,0,9603,-128,-18,224,,,,,0
+206,1106,4201,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3311,3.49,22.24,21.82,38.66,1,0,9603,-161,-14,205,,,,,0
+207,1108,4202,4326,"Derived at 105 stations. Replaced by AGD66 to WGS 84 (20) (code 6905).",For military purposes only. Accuracy 3m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-133,-48,148,,,,,0
+208,1665,4202,4326,"Parameter values from AGD66 to GDA94 (2) (code 1458). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in A.C.T. 1m accuracy.,2283,-35.93,-35.12,148.76,149.4,1,0,9607,-129.193,-41.212,130.73,-0.246,-0.374,-0.329,-2.955,0
+209,1666,4202,4326,"Parameter values from AGD66 to GDA94 (4) (code 1460). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in NSW and Victoria. 1m accuracy.,2286,-39.2,-28.15,140.96,153.69,1,0,9607,-119.353,-48.301,139.484,-0.415,-0.26,-0.437,-0.613,0
+210,1667,4202,4326,"Parameter values from AGD66 to GDA94 (8) (code 1594). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Tasmania. 1m accuracy.,1282,-43.7,-39.52,143.77,148.55,1,0,9607,-120.271,-64.543,161.632,-0.217,0.067,0.129,2.499,0
+211,1668,4202,4326,"Parameter values from AGD66 to GDA94 (9) (code 1595). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",Recommended for mid-accuracy use in Northern Territory. 1m accuracy.,2284,-26.01,-10.86,128.99,138,1,0,9607,-124.133,-42.003,137.4,0.008,-0.557,-0.178,-1.854,0
+212,15980,4202,4326,"Parameter values from AGD66 to GDA94 (12) (code 15979). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Use only offshore: onshore tfms 1665-68 for ACT, NSW/Vic, Tas and NT respectively are more accurate.",3m accuracy.,3559,-47.2,-8.88,109.23,163.2,1,0,9607,-117.808,-51.536,137.784,-0.303,-0.446,-0.234,-0.29,1
+213,5841,4202,4326,Derived at 25 stations in 2007.,"Accuracy 2m in 2007. Due to significant tectonic activity in PNG, AGD66 and WGS 84 are separating by approximately 7cm per year.",4013,-8.28,-5.59,142.24,144.75,1,0,9603,-124,-60,154,,,,,0
+214,6905,4202,4326,"Derived at 161 stations. Replaces AGD66 to WGS 84 (1) (code 1108).",For military purposes only. Accuracy 5m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-128,-52,153,,,,,0
+215,6943,4202,4326,"Parameter values taken from AGD66 to PNG94 (3) (code 6938). Approximation at the +/- 5m level assuming that PNG94 is equivalent to WGS 84 within the accuracy of the transformation.",Low accuracy transformation suitable for mapping and navigation purposes only.,4214,-10.76,-2.53,140.85,150.96,1,0,9603,-129,-58,152,,,,,0
+216,6944,4202,4326,"Parameter values taken from AGD66 to PNG94 (5) (code 6940). Approximation at the +/- 4m level assuming that PNG94 is equivalent to WGS 84 within the accuracy of the transformation.",Low accuracy transformation suitable for mapping and navigation purposes only.,4013,-8.28,-5.59,142.24,144.75,1,0,9603,-131.3,-55.3,151.8,,,,,0
+217,6945,4202,4326,"Parameter values taken from AGD66 to PNG94 (7) (code 6942). Approximation at the +/- 4m level assuming that PNG94 is equivalent to WGS 84 within the accuracy of the transformation.",Low accuracy transformation suitable for mapping and navigation purposes only.,4216,-6.6,-5.05,140.89,141.54,1,0,9603,-137.4,-58.9,150.4,,,,,0
+218,15788,4202,4326,"Parameter values from AGD66 to GDA94 (1) (code 1278). Derived at 162 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation.",5m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-127.8,-52.3,152.9,,,,,0
+219,1109,4203,4326,"Derived at 90 stations. Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",For military purposes only. Accuracy 2m in each axis.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-134,-48,149,,,,,1
+220,1236,4203,4326,"""Higgins parameters"". Replaced by AGD84 to GDA94 (2) (code 1280) and AGD84 to WGS 84 (7) (code 1669). Note: AGD84 officially adopted only in Queensland, South Australia and Western Australia.",Preliminary estimate.,2575,-43.7,-9.86,112.85,153.69,1,0,9607,-116,-50.47,141.69,-0.23,-0.39,-0.344,0.0983,0
+221,1669,4203,4326,"Parameter values from AGD84 to GDA94 (2) (code 1280). Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces AGD84 to WGS 84 (2) (code 1236). Note: AGD84 officially adopted only in Qld, SA and WA.",1m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9607,-117.763,-51.51,139.061,-0.292,-0.443,-0.277,-0.191,0
+222,15789,4203,4326,"Parameter values from AGD84 to GDA94 (1) (code 1279). Derived at 327 stations. Assumes GDA94 and WGS 84 can be considered the same to within the accuracy of the tfm. AGD84 officially adopted only in Queensland, South Australia and Western Australia.",5m accuracy.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,-128.5,-53,153.4,,,,,0
+223,1055,4204,4326,Derived at station K1.,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-145.7,-249.1,1.5,,,,,0
+224,1056,4204,4326,"Derivation is more precise, but no evidence that accuracy is better than Ain el Abd to WGS 84 (3). OGP recommends using Ain el Abd to WGS 84 (3).",1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9607,-85.645,-273.077,-79.708,-2.289,1.421,-2.532,3.194,0
+225,1057,4204,4326,.,1 metre accuracy.,2956,29.1,30.09,46.54,48.42,1,0,9607,-202.234,-168.351,-63.51,-3.545,-0.659,1.945,2.1,0
+226,1058,4204,4326,,1 metre accuracy.,2957,28.53,29.45,46.54,48.48,1,0,9607,-18.944,-379.364,-24.063,-0.04,0.764,-6.431,3.657,0
+227,1110,4204,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,3943,25.53,26.34,50.39,50.85,1,0,9603,-150,-250,-1,,,,,0
+228,1111,4204,4326,Derived at 9 stations.,For military purposes. Accuracy 10m in each axis.,3303,15.61,32.16,34.51,55.67,1,0,9603,-143,-236,7,,,,,1
+229,1107,4205,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3308,-1.71,12.03,40.99,51.47,1,0,9603,-43,-163,45,,,,,1
+230,15846,4706,4326,"Sometime referred to as ""Egypt 1907 to WGS 84"". However, application to WGS 84 coordinates of the reverse of this tfm results in Gulf of Suez S-650 TL, not Egypt 1907, position. Gulf of Suez S-650 TL and Egypt 1907 CRSs differ by some 20 metres.",Used for oil exploration by GUPCO.,2341,27.19,30.01,32.34,34.27,1,0,9603,-146.21,112.63,4.05,,,,,1
+231,1656,4207,4326,"Parameter values from Lisbon to ETRS89 (1) (code 1655). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Lisbon to WGS 84 (4) (code 1988).",For applications to an accuracy of 3 metres.,1294,36.95,42.16,-9.56,-6.19,1,0,9606,-280.9,-89.8,130.2,-1.721,0.355,-0.371,-5.92,0
+232,1944,4207,4326,"Parameter values from Lisbon to ETRS89 (2) (code 1790). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1294,36.95,42.16,-9.56,-6.19,1,1,9606,-282.1,-72.2,120,-1.592,0.145,-0.89,-4.46,0
+233,1984,4207,4326,,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-304.046,-60.576,103.64,,,,,1
+234,1988,4207,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-288.885,-91.744,126.244,1.691,-0.41,0.211,-4.598,0
+235,6898,4207,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-306,-62,105,,,,,0
+236,15877,4720,4326,"Suitable for GIS mapping purposes but not rigorous surveying. Very similar results may be obtained through Fiji 1986 to WGS 84 (1) (tfm code 15876).","Horizontal accuracy 2m, vertical accuracy approximately 40 metres..",3398,-19.22,-16.1,176.81,-179.77,1,0,9607,-35.173,136.571,-36.964,1.37,-0.842,-4.718,-1.537,0
+237,15876,4720,4326,"Approximation at the +/- 2m level assuming that Fiji 1986 is equivalent to WGS 72. Parameter values taken from WGS 72 to WGS 84 (1) (tfm code 1237).",tbc,1094,-20.81,-12.42,176.81,-178.15,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
+238,1113,4209,4326,Derived at 41 stations.,"For military purposes only. Accuracy 20m, 33m and 20m in X, Y and Z axes.",2312,-30.66,-8.19,19.99,35.93,1,0,9603,-143,-90,-294,,,,,1
+239,1114,4209,4326,Derived at 9 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1051,-26.88,-17.78,19.99,29.38,1,0,9603,-138,-105,-289,,,,,0
+240,1115,4209,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.86,1,1,9603,-153,-5,-292,,,,,0
+241,1116,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 3m and 8m in X, Y and Z axes.",1141,-30.66,-28.57,27.01,29.46,1,0,9603,-125,-108,-295,,,,,0
+242,1117,4209,4326,Derived at 6 stations.,"For military purposes. Accuracy 9m, 24m and 8m in X, Y and Z axes.",1150,-17.14,-9.37,32.68,35.93,1,0,9603,-161,-73,-317,,,,,0
+243,1118,4209,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1224,-27.32,-25.72,30.79,32.14,1,0,9603,-134,-105,-295,,,,,0
+244,1119,4209,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1259,-13.46,5.39,11.79,31.31,1,1,9603,-169,-19,-278,,,,,0
+245,1120,4209,4326,Derived at 5 stations.,"For military purposes. Accuracy 21m, 21m and 27m in X, Y and Z axes.",1260,-18.08,-8.19,21.99,33.71,1,0,9603,-147,-74,-283,,,,,0
+246,1121,4209,4326,"Derived at 10 stations. Replaced by Arc 1950 to WGS 84 (10), tfm code 6906.","For military purposes. Accuracy 5m, 8m and 11m in X, Y and Z axes.",1261,-22.42,-15.61,25.23,33.08,1,0,9603,-142,-96,-293,,,,,0
+247,6904,4209,4326,"Derived at 7 stations. Info source gives source CRS as Arc 1960. From inspection of parameter values, comparison of those from DMA TR8350.2 transformations and geographic applicability of CRS, OGP believes that this should be Arc 1950.","For military purposes only. Accuracy 13m, 25m and 7m in X, Y and Z axes.",1150,-17.14,-9.37,32.68,35.93,1,0,9603,-179,-81,-314,,,,,0
+248,6906,4209,4326,"Derived at 38 stations. Replaces Arc 1950 to WGS 84 (9), tfm code 1121.","For military purposes. Accuracy 10m in each of X, Y and Z axes.",1261,-22.42,-15.61,25.23,33.08,1,0,9603,-145,-97,-292,,,,,0
+249,1122,4210,4326,Derived at 25 stations.,For military purposes only. Accuracy 20m in each axis.,2311,-11.75,4.63,29.34,41.91,1,0,9603,-160,-6,-302,,,,,1
+250,1284,4210,4326,Derived at 24 stations.,"For military purposes. Accuracy 4m, 3m and 3m in X, Y and Z axes.",3264,-4.72,4.63,33.9,41.91,1,0,9603,-157,-2,-299,,,,,0
+251,1285,4210,4326,Derived at 12 stations.,"For military purposes. Accuracy 6m, 9m and 10m in X, Y and Z axes.",3316,-11.75,-0.99,29.34,40.48,1,0,9603,-175,-23,-303,,,,,0
+252,3998,4210,4326,"Derived at 3 stations. From inspection of parameter values and geographic applicability of CRS, OGP believes that the published source CRS (Arc 1950) has been misidentified by information source. Analysis of TR8350.2 contour charts suggest Arc 1960.",For military purposes. Accuracy 20m in each axis.,1058,-4.45,-2.3,28.98,30.86,1,0,9603,-153,-5,-292,,,,,0
+253,1123,4211,4326,"Note: The area of use cited for this transformation (Sumatra) is not consistent with the area of use (Java) for the Batavia (Genuk) coordinate reference system. Derived at 5 stations.",For military purposes. Accuracy 3m in each axis.,1355,-5.99,5.97,95.16,106.13,1,0,9603,-377,681,-50,,,,,1
+254,1813,4211,4326,Used by ARCO offshore NW Java area.,Oil industry operations.,2577,-6.89,-4.07,105.77,110.01,1,0,9603,-378.873,676.002,-46.255,,,,,0
+255,1814,4211,4326,Used by PT Komaritim for Nippon Steel during East Java Gas Pipeline construction.,Oil industry operations.,2588,-8.46,-6.8,112.8,117.01,1,0,9603,-377.7,675.1,-52.2,,,,,0
+256,15793,4212,4326,"Derived at 2 stations (S40 and M1, St Annes Tower) in 2004.",Accuracy 2.5m.,3218,13,13.39,-59.71,-59.37,1,0,9603,31.95,300.99,419.19,,,,,1
+257,15809,4725,4326,"Derived at 2 satellite stations. Note: NGA online html files carry a different dZ value - OGP believe this is an erroneous transcription from the TR8350.2 line above.","Military and topographic mapping. Accuracy +/- 25m in each axis.",3201,16.67,16.79,-169.59,-169.47,1,0,9603,189,-79,-202,,,,,1
+258,15918,4214,4326,Provided by BGP to TOTAL in June 2006.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,12.646,-155.176,-80.863,,,,,0
+259,15920,4214,4326,"Derived via WGS 72BE. Original transformation derived by GSI in 1980-81. The GSI memo incorrectly gave the parameters as from WGS 72 to Beijing 1954, but it has been determined by the OGP that the memo should have stated from Beijing 1954 to WGS 72BE.",Geophysical exploration in South China Sea.,3470,18.31,22.89,110.13,116.76,1,0,9606,31.4,-144.3,-74.8,0,0,0.814,-0.38,0
+260,15921,4214,4326,Provided by BGP to ELF in 1994.,Geophysical exploration in Tarim basin. Accuracy stated as 1m within basin.,3507,37,41.99,77.45,88,1,0,9603,15.8,-154.4,-82.3,,,,,1
+261,15936,4214,4326,Provided by Sinopec to TOTAL in January 2007.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,11.911,-154.833,-80.079,,,,,0
+262,15935,4214,4326,Concatenated via WGS 72BE. Recomputation by Shelltech in 1981 of SSB 1980 observation.,Geophysical exploration in Bei Bu basin. Accuracy stated as 1m within basin.,3561,17.81,21.69,107.15,110.17,1,0,9606,18,-136.8,-73.7,0,0,0.814,-0.38,0
+263,15919,4214,4326,Derived via WGS 72BE. Original transformation derived in 1979 at 4 stations on Yellow Sea coast.,Geophysical exploration in Yellow Sea.,3469,31.23,37.4,119.23,125.06,1,0,9606,15.53,-113.82,-41.38,0,0,0.814,-0.38,0
+264,6907,4713,4326,"Derived at 2 stations. Replaces Ayabelle Lighthouse to WGS 84 (1) (code 15800).",For military purposes only. Accuracy 10m in each axis.,3238,10.94,12.72,41.75,43.48,1,0,9603,-77,-128,142,,,,,1
+265,15800,4713,4326,"Derived at 1 satellite station. Replaced by Ayabelle Lighthouse to WGS 84 (2) (code 6907).",For military purposes only. Accuracy 25m in each axis.,1081,10.94,12.72,41.75,44.15,1,0,9603,-79,-129,145,,,,,0
+266,1124,4216,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3221,32.21,32.43,-64.89,-64.61,1,0,9603,-73,213,296,,,,,1
+267,15970,4216,4326,"Parameter values from Bermuda 1957 to BDA2000 (1) (code 15969). Assumes BDA2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy +/- 1 metre.",3221,32.21,32.43,-64.89,-64.61,1,0,9607,-292.295,248.758,429.447,-4.9971,-2.99,-6.6906,1.0289,0
+268,15819,4729,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25 m in each axis.",3208,-25.14,-25,-130.16,-130.01,1,0,9603,185,165,42,,,,,1
+269,1125,4218,4326,Derived in 1987 at 7 stations.,"For military purposes. Accuracy 6m, 5m and 6m in X, Y and Z axes.",3686,-4.23,13.68,-79.1,-66.87,1,0,9603,307,304,-318,,,,,1
+270,1597,4218,4326,Derived in 1995 by WGC at first order stations Recreo and Mena via multi-day ties to 4 IGS stations. Residuals under 20cm.,Oil exploration.,2315,4.75,5.68,-73,-72.25,1,0,9603,304.5,306.5,-318.1,,,,,0
+271,15715,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (1) (tfm code 15714).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3082,9.8,12.52,-73,-71.06,1,0,9607,-806.413,-263.5,-622.671,12.414219,-2.9908418,-39.034686,-20.81616,0
+272,15717,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (2) (tfm code 15716).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3083,9.39,11.59,-76.08,-73,1,0,9607,100.783,187.382,-47,-9.2238300,2.4238033,-8.3082783,-13.56561,0
+273,15719,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (3) (tfm code 15718).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3084,8,9.4,-77.48,-74.39,1,0,9607,336.026,348.565,252.978,-17.241289,-6.3064928,1.5620498,-5.771909,0
+274,15721,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (4) (tfm code 15720).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3085,5,9.4,-74.4,-71.99,1,0,9607,963.273,486.386,190.997,-16.485036,-1.6688258,21.692849,-13.89914,0
+275,15723,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (5) (tfm code 15722).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3086,5,8.01,-77.92,-74.39,1,0,9607,-90.29,247.559,-21.989,-8.6968853,-4.1880336,-12.808267,2.181658,0
+276,15725,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (6) (tfm code 15724).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3087,3,5.01,-77.68,-74.39,1,0,9607,-0.562,244.299,-456.938,6.8668710,-8.2526735,-9.2967797,3.74656,0
+277,15727,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (7) (tfm code 15726).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3088,-1.13,3.01,-79.1,-74,1,0,9607,-305.356,222.004,-30.023,-9.6904939,1.0319682,-19.757394,6.325747,0
+278,15729,4218,4326,"Approximation at the +/- 1m level assuming that MAGNA-SIRGAS is equivalent to WGS 84. Parameter values taken from Bogota 1975 to MAGNA-SIRGAS (8) (tfm code 15728).","Accuracy about 1 part in 10^5 of distance between points, depending on relative tectonic motion.",3089,-4.23,7.1,-74.4,-66.87,1,0,9607,221.899,274.136,-397.554,2.8084459,-0.44850859,-2.810172,-2.199943,0
+279,1126,4219,4326,Accuracy estimate not available.,For military purposes.,1287,-3.3,-1.44,105.07,108.35,1,0,9603,-384,664,-48,,,,,1
+280,1318,4220,4326,,Used for oil exploration by Conoco.,2316,-8.59,-7.75,12.58,13.4,1,0,9603,-42.01,-332.21,-229.75,,,,,0
+281,1319,4220,4326,,Used for oil exploration by Texaco.,2317,-7.01,-6.01,12.08,12.84,1,0,9603,-40,-354,-224,,,,,0
+282,1320,4220,4326,"Replaced by Camacupa to WGS 84 (9). Used by Shell prior to 1994.",Oil exploration prior to 1994.,2321,-7.26,-6.03,11.08,12.09,1,0,9606,-37.2,-370.6,-224,0,0,0.554,0.219,0
+283,1321,4220,4326,"Derived as mean of 123 Transit passes at station Cabo Ledo NE base in November 1990. Used by Elf for block 7 up to December 1992 then replaced by Camacupa to WGS 84 (7). Used by Total in block 8, ExxonMobil block 24, Western Geophysical for spec. data.",Oil exploration.,2320,-17.26,-6.01,8.2,13.86,1,0,9603,-41.8,-342.2,-228.2,,,,,0
+284,1322,4220,4326,"Derived at station Djeno during coordination of platform PAL F2 in February 1992. Used by Elf for block 3 up to December 1992 then replaced by Camacupa to WGS 84 (7).",Oil exploration.,2318,-7.34,-6.66,11.74,12.5,1,0,9603,-55.5,-348,-229.2,,,,,0
+285,1323,4220,4326,Derived at Luanda observatory December 1992.,Used for oil exploration by Elf for 1993 block 7 shallow water survey.,2319,-10.09,-9.41,12.66,13.39,1,0,9603,-43,-337,-233,,,,,0
+286,1324,4220,4326,"Derived at platform PAL F2 in December 1992. For use in blocks 3, 7 and 17, replaced by Camacupa to WGS 84 (10) (code 1327).","Used for oil exploration by Elf for blocks 3, 7 and 17 between December 1992 and 1994 then superseded by Camacupa to WGS 84 (10). Used by Exxon for block 15 since 1993.",2322,-10.09,-6.03,10.83,13.39,1,0,9603,-48,-345,-231,,,,,0
+287,1325,4220,4326,"Derived at platform PAL F2 in December 1992. Used by Total for block 2 between December 1992 and 1994 then replaced by Camacupa to WGS 84 (10).",Oil exploration between December 1992 and 1994.,2317,-7.01,-6.01,12.08,12.84,1,0,9603,-48.6,-345.1,-230.8,,,,,0
+288,1326,4220,4326,"Derived by GPS on two Topnav DGPS reference stations at Djeno and Luanda. Replaces Camacupa to WGS 84 (3). In block 18 replaced by BP from 1999 by Camacupa to WGS 84 (10).",Used by Shell since 1994.,2323,-8.34,-6.03,11.08,12.75,1,0,9606,-41.057,-374.564,-226.287,0,0,0.554,0.219,0
+289,1327,4220,4326,Derived at platform PAL F2 in 1994 by Topnav using Doris.,Used for oil exploration by Elf in blocks 3 and 17 since 1994. Used by Total in block 2 since 1994. Adopted by BP-Amoco Elf and Exxon for blocks 18 and 31-33 in 1999.,2324,-8.59,-6.01,10.41,12.84,1,0,9603,-50.9,-347.6,-231,,,,,1
+290,1127,4221,4326,Derived at 20 stations.,For military purposes. Accuracy 5m in each axis.,3843,-54.93,-21.78,-73.59,-53.65,1,0,9603,-148,136,90,,,,,1
+291,1527,4221,4326,"Derived through ties at 2 stations (Cerro Colorado and Chihuido Sur) to 4 IGS stations in February 1995",Oil exploration.,2325,-37.5,-36.14,-70.5,-70.03,1,0,9603,-154.5,150.7,100.4,,,,,0
+292,1128,4222,4326,Derived at 5 stations.,"For military purposes. Accuracy 3m, 6m and 6m in X, Y and Z axes.",3309,-34.88,-22.13,16.45,32.95,1,0,9603,-136,-108,-292,,,,,1
+293,1129,4222,4326,"Parameter values are from Cape to Hartebeesthoek94 (1) (code 1504) assuming that Hartebeesthoek94 and WGS 84 are equivalent within the accuracy of the transformation. Residuals should not exceed 15 metres.",Accuracy 15m.,3309,-34.88,-22.13,16.45,32.95,1,0,9603,-134.73,-110.92,-292.66,,,,,0
+294,1130,4223,4326,Derived at 5 stations.,"For military purposes. Accuracy 6m, 9m and 8m in X, Y and Z axes.",1236,30.23,38.41,7.49,13.67,1,0,9603,-263,6,431,,,,,1
+295,1538,4223,4326,Derived at station Chaffar January 1995.,Oil exploration.,1489,33.22,38.41,7.81,13.67,1,0,9603,-260.1,5.5,432.2,,,,,0
+296,1131,4224,4326,Derived at 6 stations.,"For military purposes. Accuracy 6m, 9m and 5m in X, Y and Z axes.",3675,-22,-19.29,-62.57,-57.81,1,0,9603,-134,229,-29,,,,,0
+297,3972,4224,4326,"Mandatory for SICAD use until 2005. Replaced by Chua to SIRGAS 2000 (tfm code 4069).","Used by governmental agencies in Distrito Federal until adoption of SIRGAS 2000 by Brazil in 2005. Legally mandated for Cartography System of Distrito Federal (SICAD) until 2005.",3619,-15.94,-15.37,-48.1,-47.1,1,0,9603,-143.87,243.37,-33.52,,,,,1
+298,4834,4224,4326,"Parameter values from Chua to SIRGAS 2000 (1) (tfm code 4069) assuming that within the tfm accuracy SIRGAS 2000 is equivalent to WGS 84.","Cartography System of Distrito Federal (SICAD)",3619,-15.94,-15.37,-48.1,-47.1,1,0,9603,-144.35,242.88,-33.2,,,,,0
+299,1132,4225,4326,Derived at 17 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206,172,-6,,,,,0
+300,6192,4225,4326,"Formed by concatenation of tfms codes 6191 and 1877. Used by Petrobras and ANP until February 2005 when replaced by Corrego Alegre 1970-72 to WGS 84 (4) (tfm code 6194).",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-205.57,168.77,-4.12,,,,,1
+301,6194,4225,4326,"Parameter values from Corrego Alegre to SIRGAS 2000 (2) (tfm code 6193) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Used by ANP and Petrobras from February 2005, replacing use of tfm code 6192.",Medium and small scale mapping.,1293,-33.78,-2.68,-58.16,-34.74,1,0,9603,-206.05,168.28,-3.82,,,,,0
+302,15842,4739,4326,"Derived at 2 satellite stations. Care: does not use Hong Kong 1963 (code 4838) as the source CRS.","Military mapping. Accuracy +/- 1m.",1118,22.13,22.58,113.76,114.51,1,0,9603,-156,-271,-189,,,,,1
+303,1244,4740,4326,"Mandated for use in Russia by GosStandard of Russia Decree #327 of August 9, 2001. Republished but with one significant figure less precision to parameter values in GOST R 51794-2008 of December 18 2008.",Geodetic applications. Accuracy better than 0.5 metre.,1198,39.87,85.2,18.92,-168.97,1,0,9607,-1.08,-0.27,-0.9,0,0,-0.16,-0.12,0
+304,15843,4740,4326,"Derived through Glonass and GPS at 30 stations throughout USSR - Former Soviet Union (FSU).",Geodetic applications. Accuracy better than 1.5 metres.,1262,-90,90,-180,180,1,0,9607,0,0,1.5,0,0,-0.076,0,1
+305,1148,4229,4326,Derived at 14 stations.,"For military purposes. Accuracy 3m, 6m and 8m in X, Y and Z axes.",1086,21.89,33.82,24.7,37.91,1,0,9603,-130,110,-13,,,,,1
+306,1546,4229,4326,,Used for oil exploration by GUPCO.,2341,27.19,30.01,32.34,34.27,1,1,9603,-146.21,112.63,4.05,,,,,0
+307,1075,4230,4326,"Derived in 1987 by Geodetic for TPAO. Used on BP 1991/92 2D seismic surveys in central and eastern Turkish sector of Black Sea. In Turkey, replaced by tfm code 1784. Also adopted for use offshore Israel.",Oil Exploration,2896,31.35,43.45,28.03,41.47,1,0,9603,-89.05,-87.03,-124.56,,,,,0
+308,1087,4230,4326,,Topographic mapping.,1130,29.18,33.38,34.88,39.31,1,0,9603,-112,-110.3,-140.2,,,,,0
+309,1133,4230,4326,Derived at 85 stations. In Germany will be accepted by LBA for minerals management purposes as alternative to tfm 1052 or 1998.,"For military purposes. Accepted for minerals management in Germany. Accuracy 3m, 8m and 5m in X, Y and Z axes.",2420,34.88,71.21,-9.56,31.59,1,0,9603,-87,-98,-121,,,,,1
+310,1134,4230,4326,Derived at 52 stations.,For military purposes only. Accuracy 3m each axis.,2421,42.33,57.8,-4.87,17.17,1,0,9603,-87,-96,-120,,,,,0
+311,1135,4230,4326,Accuracy estimate not available.,For military purposes only.,2345,15.61,37.39,34.17,55.67,1,0,9603,-103,-106,-141,,,,,0
+312,1136,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,1078,32.88,36.21,29.95,35.2,1,0,9603,-104,-101,-140,,,,,0
+313,1137,4230,4326,Derived at 14 stations.,"For military purposes. Accuracy 6m, 8m and 8m in X, Y and Z axes.",2595,25.71,31.68,24.7,30,1,0,9603,-130,-117,-151,,,,,0
+314,1138,4230,4326,Derived at 40 stations.,For military purposes only. Accuracy 3m in each axis.,2343,49.11,60.9,-10.56,1.84,1,0,9603,-86,-96,-120,,,,,0
+315,1139,4230,4326,Derived at 20 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",2344,57.93,71.21,4.68,31.59,1,0,9603,-87,-95,-120,,,,,0
+316,1140,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,3254,34.88,41.75,19.57,28.3,1,0,9603,-84,-95,-130,,,,,0
+317,1142,4230,4326,Derived at 2 stations.,For military purposes only. Accuracy 25m in each axis.,2339,38.82,41.31,8.08,9.89,1,0,9603,-97,-103,-120,,,,,0
+318,1143,4230,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2340,36.59,38.35,12.36,15.71,1,0,9603,-97,-88,-135,,,,,0
+319,1144,4230,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3275,35.74,36.05,14.27,14.63,1,0,9603,-107,-88,-149,,,,,0
+320,1145,4230,4326,Derived at 18 stations.,"For military purposes only. Accuracy 5m, 6m and 3m in X, Y and Z axes.",2338,35.26,43.82,-9.56,3.39,1,0,9603,-84,-107,-120,,,,,0
+321,1245,4230,4326,Derived at 4 stations.,For military purposes only. Accuracy 25m in each axis.,1236,30.23,38.41,7.49,13.67,1,0,9603,-112,-77,-145,,,,,0
+322,1275,4230,4326,"These same parameter values are used to transform to ETRS89. See ED50 to ETRS89 (10) (code 1650).",For applications to an accuracy of 2 metres.,1096,41.15,51.56,-9.86,10.38,1,0,9603,-84,-97,-117,,,,,0
+323,1311,4230,4326,"Based on ED50 to WGS72 (precise ephemeris) 6-nations agreement of 1981 to which precise to broadcast and broadcast to WGS 84 transformations have been concatenated.",Recommended transformation for UKCS and IrishCS petroleum purposes.,2342,47.42,63.89,-16.1,10.86,1,0,9606,-89.5,-93.8,-123.1,0,0,-0.156,1.2,0
+324,1440,4230,4326,,Used in oil industry.,3254,34.88,41.75,19.57,28.3,1,0,9603,-86,-92.2,-127.5,,,,,0
+325,1612,4230,4326,"Parameter values are taken from ED50 to ETRS89 (1), code 1588. Adopted for ED50 to WGS84 transformations offshore Norway north of 62N from April 2001 when it replaced code 1590. Included in Statens Kartverk programme wsktrans from v4.0.",Oil industry offshore.,2601,62,84.17,-3.7,39.65,1,0,9606,-116.641,-56.931,-110.559,0.893,0.921,-0.917,-3.52,0
+326,1613,4230,4326,"Approximation to 1 metre of concatenated transformation ED50 to WGS 84 (14), code 8653. 8653 remains the transformation promulgated by Statens Kartverk but 1613 recommended by EPSG for practical oil industry usage.",Approximation to 1 metre for oil industry use.,2334,56.08,62,1.37,11.14,1,0,9606,-90.365,-101.13,-123.384,0.333,0.077,0.894,1.994,0
+327,1627,4230,4326,"Parameter values from ED50 to ETRS89 (4) (code 1626). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3237,54.51,57.8,8,15.24,1,0,9606,-81.1,-89.4,-115.8,0.485,0.024,0.413,-0.54,0
+328,1629,4230,4326,"Parameter values from ED50 to ETRS89 (5) (code 1628). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1105,36,36.16,-5.42,-4.89,1,0,9603,-116.8,-106.4,-154.4,,,,,0
+329,1631,4230,4326,"Parameter values from ED50 to ETRS89 (6) (code 1630). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2335,38.59,40.11,1.14,4.39,1,0,9606,-181.5,-90.3,-187.2,0.144,0.492,-0.394,17.57,0
+330,1633,4230,4326,"Parameter values from ED50 to ETRS89 (7) (code 1632). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2336,35.26,43.56,-7.54,3.39,1,0,9606,-131,-100.3,-163.4,-1.244,-0.02,-1.144,9.39,0
+331,1635,4230,4326,"Parameter values from ED50 to ETRS89 (8) (code 1634). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1.5 metres.,2337,41.5,43.82,-9.37,-4.5,1,0,9606,-178.4,-83.2,-221.3,0.54,-0.532,-0.126,21.2,0
+332,1784,4230,4326,"Parameter values from ED50 to ETRS89 (9) (code 1783). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 2 metres.,1237,34.42,43.45,25.62,44.83,1,0,9606,-84.1,-101.8,-129.7,0,0,0.468,1.05,0
+333,1810,4230,4326,Derived via concatenation through WGS72. The ED50 to WGS72 step is the Sepplin 1974 value for all Europe.,Oil industry exploration and production operations.,2595,25.71,31.68,24.7,30,1,0,9606,-84,-103,-122.5,0,0,0.554,0.2263,0
+334,1853,4230,4326,Derived at a single point in Galway docks.,Used by Enterprise for Corrib.,2961,53.75,55.76,-12.5,-9.49,1,0,9603,-82.31,-95.23,-114.96,,,,,0
+335,1961,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.45,55.77,2.53,6.41,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.4428,1.218,0
+336,1985,4230,4326,May be taken as a transformation from ED50 to ETRS89 - see tfm code 5040.,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-87.987,-108.639,-121.593,,,,,0
+337,1989,4230,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-74.292,-135.889,-104.967,0.524,0.136,-0.61,-3.761,0
+338,1998,4230,4326,"Approximation to better than 0.5m of transformation adopted in June 2003 (see ED50 to WGS 84 (35), code 1052). Acceptable to Landesbergamt for Lower Saxony and Bundesanstalt für Seeschifffahrt und Hydrographie.",Recommended transformation for Germany North Sea petroleum purposes.,2879,53.6,55.92,3.34,8.88,1,0,9606,-157.89,-17.16,-78.41,2.118,2.697,-1.434,-5.38,0
+339,1999,4230,4326,"Parameter values taken from ED87 to WGS 84 (2) (tfm code 1960) assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3m.",Used by NAM for offshore operations.,1630,51.45,55.77,2.53,6.41,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
+340,3904,4230,4326,"Parameter values from ED87 to WGS 84 (32) (tfm code 3905), assuming that ED87 is identical to ED50. Errors caused by this assumption can reach 3-5m. Used by NAM for offshore operations until mid 2004, then replaced by tfm code 1311.","E&P operations in the Dutch sector of the North Sea.",1630,51.45,55.77,2.53,6.41,1,0,9606,-83.11,-97.38,-117.22,0.005693,-0.044698,0.044285,0.1218,0
+341,15964,4230,4326,Developed by the Portuguese Hydrographic Institute and used by the Directorate of Energy and Geology.,Hydrography and minerals management offshore Portugal.,3537,34.91,41.88,-13.87,-7.24,1,0,9603,-86.277,-108.879,-120.181,,,,,0
+342,1146,4231,4326,,"?",2330,51.03,62.01,-5.05,11.14,1,0,9606,-82.981,-99.719,-110.709,-0.10470,0.031002,0.080402,-0.3143,0
+343,1960,4231,4326,,Scientific research.,1297,34.88,71.21,-10.56,31.59,1,1,9606,-83.11,-97.38,-117.22,0.005693,-0.04469,0.04428,1.218,0
+344,3905,4231,4326,"Parameter values taken from ED87 to ETRS89 (1) (tfm code 4078) assuming that ETRS89 is coincident with WGS 84 within the accuracy of the transformation. Used as a tfm between ED50 and WGS 84 - see code 3904.",Scientific research.,1297,34.88,71.21,-10.56,31.59,1,0,9606,-83.11,-97.38,-117.22,0.005693,-0.044698,0.044285,0.1218,1
+345,1256,4232,4326,"Derived at 7 stations. Replaced by Fahud to WGS 84 (3) (code 6908).","For military purposes. Accuracy 3m, 3m and 9m in X, Y and Z axes.",4009,16.59,26.42,51.99,59.91,1,0,9603,-346,-1,224,,,,,0
+346,1438,4232,4326,,Oil exploration.,4009,16.59,26.42,51.99,59.91,1,0,9606,-333.102,-11.02,230.69,0,0,0.554,0.219,1
+347,6908,4232,4326,"Derived at 11 stations. Replaces Fahud to WGS 84 (1) (code 1256).","For military purposes. Accuracy 3m, 3m and 6m in X, Y and Z axes.",4009,16.59,26.42,51.99,59.91,1,0,9603,-345,3,223,,,,,0
+348,1894,4233,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1152,-3.47,8.1,69.29,77.08,1,1,9603,-133,-321,50,,,,,0
+349,7033,4744,4326,Derived by concatenation of parameter values published by IGN Paris from Nahrwan 1934 to WGS 72 at the Nahrwan SE Base station near Baghdad with DMA WGS 72 to WGS 84 parameter values. For more accurate transformation away from origin see codes 7008-7032.,Oil exploration.,3625,29.06,37.39,38.79,48.61,1,0,9603,-242.2,-144.9,370.3,,,,,1
+350,15879,4747,4326,"Approximation at the +/- 1m level assuming that GR96 is equivalent to WGS 84 within the accuracy of the transformation.","For applications with an accuracy of +/- 1m.",1107,56.38,87.03,-75,8.12,1,0,9603,0,0,0,,,,,1
+351,1152,4236,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,3315,21.87,25.34,119.25,122.06,1,0,9603,-637,-549,-203,,,,,1
+352,1242,4237,4326,"Parameter value error in info source Hungarian text but correct in English summary. Replaces HD72 to WGS 84 (2) (code 1831).",Accuracy at metre level throughout Hungary.,1119,45.74,48.58,16.11,22.9,1,0,9603,52.17,-71.82,-14.9,,,,,1
+353,1448,4237,4326,"Parameter values taken from HD72 to ETRS89 (2) (code 1449) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces HD72 to WGS 84 (1) (code 1830).","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.74,48.58,16.11,22.9,1,0,9607,52.684,-71.194,-13.975,0.312,0.1063,0.3729,1.0191,0
+354,1677,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1273) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level.",1119,45.74,48.58,16.11,22.9,1,1,9607,56,75.77,15.31,-0.37,-0.2,-0.21,-1.01,0
+355,1830,4237,4326,"Parameter values taken from HD72 to ETRS89 (1) (code 1829) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. OGP recommends use of newer MSZ 7222 equivalent (tfm code 1448) in preference to this transformation.","Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",1119,45.74,48.58,16.11,22.9,1,0,9607,56,-75.77,-15.31,0.37,0.2,0.21,1.01,0
+356,1831,4237,4326,"Derived at fundamental point Szolohegy and tested at 99 stations throughout Hungary. OGP recommends use of newer transformation (tfm code 1242) in preference to this transformation.",Accuracy better than 1m in all three dimensions throughout Hungary.,1119,45.74,48.58,16.11,22.9,1,0,9603,57.01,-69.97,-9.29,,,,,0
+357,1248,4238,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,4020,-10.98,5.97,95.16,141.01,1,0,9603,-24,-15,5,,,,,1
+358,1832,4238,4326,"Derived via coordinates of 2 Pulse8 stations. Use of ID74 to WGS 84 (3) (code 1833) is recommended.",For oil industry purposes.,4020,-10.98,5.97,95.16,141.01,1,0,9606,2.691,-14.757,4.724,0,0,0.774,-0.6,0
+359,1833,4238,4326,"Parameter values from ID74 to DGN95 (1) (code 15911) assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.","Standard deviations of translations are 1.3, 1.1 and 3.6m, of rotations 0.11, 0.06 and 0.04 sec and ppm 0.18.",4020,-10.98,5.97,95.16,141.01,1,0,9607,-1.977,-13.06,-9.993,-0.364,-0.254,-0.689,-1.037,0
+360,1153,4239,4326,Derived at 11 stations.,"For military purposes. Accuracy 15m, 6m and 12m in X, Y and Z axes.",3317,5.63,20.46,97.34,105.64,1,0,9603,217,823,299,,,,,1
+361,1154,4240,4326,"Derived at 62 stations. Replaced by Indian 1975 to WGS 84 (2) (code 1304).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.46,97.34,105.64,1,0,9603,209,818,290,,,,,0
+362,1304,4240,4326,"Derived at 62 stations. Replaces Indian 1975 to WGS 84 (1) (code 1154).","For military purposes. Accuracy 3m, 2m and 3m in X, Y and Z axes.",3741,5.63,20.46,97.34,105.64,1,0,9603,210,814,289,,,,,1
+363,1537,4240,4326,Derived in 1995 at point RTSD181.,Oil exploration.,2358,6.74,8.16,102.16,103.05,1,0,9603,204.64,834.74,293.8,,,,,0
+364,1812,4240,4326,,Cadastral survey.,3317,5.63,20.46,97.34,105.64,1,0,9606,293,836,318,0.5,1.6,-2.8,2.1,0
+365,1084,4242,4326,Derived via NAD27 and WGS 72. Preliminary values derived by Survey Department but not officially promulgated.,For applications requiring 5m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9603,70,207,389.5,,,,,1
+366,1085,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 2m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9603,65.334,212.46,387.63,,,,,0
+367,1086,4242,4326,"Derived at 4 stations, tested at a further 9.",For applications requiring 1m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,1,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,-8.95,0
+368,15927,4242,4326,"Derived at 4 stations, tested at a further 9. Also used as tfm to JAD69 to JAD2001 (see code 15926).
 Note: Info source paper contains an error in sign of dS, subsequently confirmed by primary author and NLA of Jamaica, and corrected in this record.",For applications requiring 1m accuracy.,3342,17.64,18.58,-78.43,-76.17,1,0,9607,-33.722,153.789,94.959,8.581,4.478,-4.54,8.95,0
-365,1930,4642,4326,,"Accuracy better than +/- 1 metre.",2820,-22.73,-22.49,167.36,167.61,1,1,9606,244.416,85.339,168.114,-8.9353,7.7523,12.5953,14.268,0
-366,15848,4642,4326,,"Accuracy +/- 10 metres.",2820,-22.73,-22.49,167.36,167.61,1,0,9603,-13,-348,292,,,,,1
-367,1157,4244,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3310,5.86,9.88,79.64,81.95,1,0,9603,-97,787,86,,,,,1
-368,1158,4245,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 6m in X, Y and Z axes.",4223,1.13,7.81,99.59,105.82,1,0,9603,-11,851,5,,,,,1
-369,1059,4246,4326,,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-294.7,-200.1,525.5,,,,,1
-370,1516,4247,4326,Also used for PSAD56 to WGS 84 transformations.,"Parameter values estimated accuracy: ± 2.0m; ± 2.7m; ± 1.3m respectively.",2363,3.56,10.8,-67.49,-59.8,1,0,9603,-273.5,110.6,-357.9,,,,,1
-371,1201,4248,4326,Derived at 63 stations. DMA also lists Colombia as area of applicability but PSAD56 is not used in that country.,"For military purposes only. Accuracy 17m, 27m and 27m in X, Y and Z axes.",2399,-45,12.52,-81.41,-56.47,1,0,9603,-288,175,-376,,,,,1
-372,1202,4248,4326,Derived at 5 stations.,"For military purposes only. Accuracy 5m, 11m and 14m in X, Y and Z axes.",1049,-22.91,-9.67,-69.66,-57.52,1,0,9603,-270,188,-388,,,,,0
-373,1203,4248,4326,"Derived at 1 station. Replaced by PSAD56 to WGS 84 (15) (code 6971).",For military purposes. Accuracy 25m in each axis.,2402,-21.51,-17.5,-70.49,-68.18,1,0,9603,-270,183,-390,,,,,0
-374,1204,4248,4326,"Derived at 3 stations. Replaced by PSAD56 to WGS 84 (17) (code 6973).",For military purposes. Accuracy 20m in each axis.,2403,-45,-38.99,-75.22,-71.1,1,0,9603,-305,243,-442,,,,,0
-375,1205,4248,4326,"Derived at 4 stations. Note that although the PSAD56 network included Colombia the CRS is not used there: see Bogota 1975 (CRS code 4218).",For military purposes. Accuracy 15m in each axis.,3229,-4.23,12.52,-79.1,-66.87,1,0,9603,-282,169,-371,,,,,0
-376,1206,4248,4326,Derived at 11 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3241,-5.01,1.45,-81.03,-75.21,1,0,9603,-278,171,-367,,,,,0
-377,1207,4248,4326,Derived at 9 stations.,"For military purposes. Accuracy 6m, 14m and 5m in X, Y and Z axes.",1114,1.18,10.7,-61.39,-55.77,1,0,9603,-298,159,-369,,,,,0
-378,1208,4248,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 12m in X, Y and Z axes.",1189,-21.05,-0.03,-84.68,-68.67,1,0,9603,-279,175,-379,,,,,0
-379,1209,4248,4326,Derived at 24 stations.,"For military purposes only. Accuracy 9m, 14m and 15m in X, Y and Z axes.",1251,0.64,16.75,-73.38,-58.95,1,0,9603,-295,173,-371,,,,,0
-380,1582,4248,4326,Derived May 1995 by Geoid for Total. OSU91A geoid model used.,Oil exploration.,2400,-14.43,-13.56,-68.96,-67.79,1,0,9603,-259.73,173.12,-398.27,,,,,0
-381,1583,4248,4326,Derived July 1997 by Geoid from data recorded by UGA for Total. OSU91A geoid model used.,Oil exploration.,2401,-21.71,-21.09,-63.44,-62.95,1,0,9603,-307.7,265.3,-363.5,,,,,0
-382,1811,4248,4326,Used by Petrobras for shelf operations.,Oil industry exploration.,1754,-1.05,5.6,-51.64,-48,1,0,9603,-291.87,106.37,-364.52,,,,,0
-383,3990,4248,4326,"Parameter values from PSAD56 to SIRGAS 1995 (1) (code 3971). Assumes SIRGAS 1995 and WGS 84 can be considered the same to within the accuracy of the transformation.","Suitable for mapping at 1:25,000 scale and smaller.",3241,-5.01,1.45,-81.03,-75.21,1,0,9607,-60.31,245.935,31.008,-12.324,-3.755,7.37,0.447,0
-384,6971,4248,4326,"Derived at 5 stations. Replaces PSAD56 to WGS 84 (3) (code 1203). Also used as a transformation from PSAD56 to SIRGAS-Chile - see code 6949.",For military purposes. Accuracy 10m in each axis.,4231,-26,-17.5,-70.79,-67,1,0,9603,-302,272,-360,,,,,0
-385,6972,4248,4326,Derived at 7 stations. Also used as a transformation from PSAD56 to SIRGAS-Chile - see code 6950.,For military purposes. Accuracy 10m in each axis.,4222,-36,-26,-72.87,-68.28,1,0,9603,-328,340,-329,,,,,0
-386,6973,4248,4326,"Derived at 6 stations. Replaces PSAD56 to WGS 84 (4) (code 1204). Info source gives S limit as 44°S but Chilean IGM states that PSAD56 limit is 43°30'S. Also used as a transformation from PSAD56 to SIRGAS-Chile - see code 6951.",For military purposes. Accuracy 10m in each axis.,4221,-43.5,-35.99,-74.48,-70.39,1,0,9603,-352,403,-287,,,,,0
-387,15967,4761,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. HTRS96 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1076,41.62,46.54,13,19.43,1,0,9603,0,0,0,,,,,1
-388,1159,4250,4326,Derived at 8 stations.,"For military purposes. Accuracy 2m, 3m and 2m in X, Y and Z axes.",1104,1.4,11.16,-3.79,2.1,1,0,9603,-130,29,364,,,,,1
-389,1160,4251,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,3270,4.29,8.52,-11.52,-7.36,1,0,9603,-90,40,88,,,,,1
-390,1887,4182,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1344,39.3,39.77,-31.34,-31.02,1,0,9603,-425,-169,81,,,,,1
-391,1982,4182,4326,Derived at 2 stations in 1999.,For low resolution applications.,1344,39.3,39.77,-31.34,-31.02,1,0,9603,-422.651,-172.995,84.02,,,,,0
-392,1161,4253,4326,Derived at 6 stations.,"For military purposes. Accuracy 8m, 11m and 9m in X, Y and Z axes.",2364,7.75,19.45,116.89,125.88,1,0,9603,-133,-77,-51,,,,,1
-393,1162,4253,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2365,4.99,10.52,119.76,126.65,1,0,9603,-133,-79,-72,,,,,0
-394,1529,4254,4326,"Derived through ties at 3 stations (RC03, TOTAL11 and MP12) to 3 IGS stations in November 1995",Oil exploration.,2357,-55.11,-52.59,-68.64,-63.73,1,0,9606,18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013,0
-395,1892,4254,4326,Derived at 2 stations. As the source CRS was used for the border survey this transformation is probably also applicable to adjacent areas of Argentina.,Accuracy 25m in each axis.,2805,-55.96,-51.99,-74.83,-66.33,1,0,9603,16,196,93,,,,,1
-396,1246,4255,4326,Accuracy estimate not available.,For military purposes only.,1024,29.4,38.48,60.5,74.92,1,0,9603,-333,-222,114,,,,,1
-397,1164,4256,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2369,-4.86,-4.5,55.3,55.59,1,0,9603,41,-220,-134,,,,,1
-398,1549,4208,4326,,Oil exploration.,2307,-28.41,-17.59,-48.8,-35.18,1,1,9603,-158,315,-148,,,,,0
-399,1550,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2308,-9.8,-8.39,-39.04,-37.09,1,0,9603,-139.62,290.53,-150.29,,,,,0
-400,1551,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2309,-10.61,-9.79,-39.14,-37.99,1,0,9603,-141.15,293.44,-150.56,,,,,0
-401,1552,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2310,-12.27,-10.6,-39.07,-37.98,1,0,9603,-142.48,296.03,-149.74,,,,,0
-402,10089,4208,4326,"Used by ExxonMobil for block BMS1. See WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.41,-22.66,-48.8,-40.2,1,0,9603,-163.466,317.396,-147.538,,,,,0
-403,10090,4208,4326,"Used by ExxonMobil for block BC10. Derived from earlier Shell position vector tfm of dX = -181m, dY = +294m, dZ = -144.5m, rX = rY = 0, rZ = +0.554s, dS = +0.219 ppm. See Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-170,305,-145,,,,,0
-404,10091,4208,4326,"Used by ExxonMobil for block BMES1. See Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-162.904,312.531,-137.109,,,,,0
-405,10092,4208,4326,"Used by ExxonMobil for block BP1. Also used by BG as part of a concatenated tfm to SAD69 for offshore regional studies. See WGS 84 (13) (tfm code 5051) for transformation Petrobras now recommends for the area.",Oil exploration.,2965,-35.71,-28.11,-53.38,-44.71,1,0,9603,-158,309,-151,,,,,0
-406,10093,4208,4326,"Used by ExxonMobil for offshore regional studies. See Aratu to WGS 84 (13) through (21) (tfm codes 5051-67 [odd numbers only]) which Petrobras now recommends for various areas.",Oil exploration.,2966,-34,-18,-53.38,-35.19,1,0,9603,-161,308,-142,,,,,0
-407,10094,4208,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.89,18.25,-16.11,-15.83,1,1,9603,124.5,-63.5,-281,,,,,0
-408,15710,4208,4326,"Replaced by Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-160,315,-142,,,,,0
-409,15711,4208,4326,"Replaced by Aratu to WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.41,-22.66,-48.8,-40.2,1,0,9603,-158,309,-147,,,,,0
-410,15712,4208,4326,"Replaced by Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-161,310,-145,,,,,0
-411,5051,4208,4326,"Parameters from Aratu to SIRGAS 2000 (1) (tfm code 5050) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15711 and 15734.",Oil exploration.,3700,-35.71,-22.66,-53.38,-40.2,1,0,9603,-157.84,308.54,-146.6,,,,,0
-412,5053,4208,4326,"Parameters from Aratu to SIRGAS 2000 (2) (tfm code 5052) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15710 and 15754.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-160.31,314.82,-142.25,,,,,0
-413,5055,4208,4326,"Parameters from Aratu to SIRGAS 2000 (3) (tfm code 5054) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 15712 and 15754.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-161.11,310.25,-144.64,,,,,0
-414,5057,4208,4326,"Parameters from Aratu to SIRGAS 2000 (4) (tfm code 5056) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3699,-17.7,-13.01,-39.22,-34.6,1,0,9603,-160.4,302.29,-144.19,,,,,0
-415,5059,4208,4326,"Parameters from Aratu to SIRGAS 2000 (5) (tfm code 5058) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3692,-13.57,-11.18,-39.09,-35.31,1,0,9603,-153.54,302.33,-152.37,,,,,0
-416,5061,4208,4326,"Parameters from Aratu to SIRGAS 2000 (6) (tfm code 5060) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 1550-1552.",Oil exploration.,3693,-12.27,-8.39,-39.14,-37.09,1,0,9603,-151.5,300.09,-151.15,,,,,0
-417,5063,4208,4326,"Parameters from Aratu to SIRGAS 2000 (7) (tfm code 5062) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3696,-13.58,-8.73,-37.34,-32.01,1,0,9603,-156.8,298.41,-147.41,,,,,0
-418,5065,4208,4326,"Parameters from Aratu to SIRGAS 2000 (8) (tfm code 5064) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation.Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3697,-10.17,-4.6,-35.1,-29.13,1,0,9603,-157.4,295.05,-150.19,,,,,0
-419,5067,4208,4326,"Parameters from Aratu to SIRGAS 2000 (9) (tfm code 5066) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3698,-6.5,4.26,-44.79,-26,1,0,9603,-151.99,287.04,-147.45,,,,,1
-420,15754,4208,4326,"Mean for 3 basins. See Aratu to WGS 84 (10) through (12) (codes 15710-12) for transformations for individual basins. Replaced by Aratu to WGS 84 (13) through (15) (tfm codes 5051, 5053 and 5055) which Petrobras now recommends for the areas.",Oil exploration.,2307,-28.41,-17.59,-48.8,-35.18,1,0,9603,-158,315,-148,,,,,0
-421,1149,4258,4326,,ETRS89 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1298,32.88,84.17,-16.1,39.65,1,0,9603,0,0,0,,,,,1
-422,1571,4258,4326,"Dutch sources also quote an equivalent transformation with parameter values dX=+593.032 dY=+26.000 dZ=+478.741m, rX rY rZ and dS as this tfm. These values belong to a different transformation method and cannot be used with the Coordinate Frame method.",Accuracy 0.5m,1172,50.75,55.77,2.53,7.22,1,1,9607,565.04,49.91,465.84,0.409394,-0.359705,1.86849,4.0772,0
-423,1330,4259,4326,"Derived at Station Y in April 1989 using 572 transit satellite passes. Computed value for dZ was -96.42 but -96.38 has been utilised. Replaced Malongo 1987 to WGS 84 (3) (code 15791) in 1989. Replaced by Malongo 1987 to WGS 84 (2) (code 1557) in 1990.",Offshore oil exploration and production between April 1989 and June 1990.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-252.95,-4.11,-96.38,,,,,0
-424,1557,4259,4326,"Derived at station Y in July 1990 through Transit single point positioning using 187 passes by Geodetic Survey Ltd. Replaces Malongo 1987 to WGS 84 (1) (trf code 1330).",Offshore oil exploration and production from June 1990.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-254.1,-5.36,-100.29,,,,,1
-425,15791,4259,4326,"Derived via WGS 72BE by Geodetic for Chevron in 1987 by single point Transit translocation at 1 station (Malongo Y). Replaced in 1989 by Malongo 1987 to WGS 84 (1) (code 1330).",Oil industry exploration and production between September 1987 and April 1989.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-259.99,-5.28,-97.09,,,,,0
-426,1316,4260,4326,,"?",1060,1.65,13.09,8.32,16.21,1,1,9603,-70.9,-151.8,-41.4,,,,,0
-427,1166,4261,4326,Derived at 9 stations.,"For military purposes. Accuracy 5m, 3m and 3m in X, Y and Z axes.",3280,27.66,35.97,-13.24,-1.01,1,0,9603,31,146,47,,,,,1
-428,1165,4262,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1089,12.36,18.1,36.44,43.31,1,0,9603,639,405,60,,,,,1
-429,1067,4263,4326,"Used by Statoil for deep water blocks 210, 213, 217 and 218. Parameter values interpolated from Racal Survey geocentric translation contour charts for each of these four blocks and then meaned.",Oil industry exploration and production.,3817,3.24,5.54,4.41,6.29,1,0,9603,-92.1,-89.9,114.9,,,,,0
-430,1167,4263,4326,"Derived at 2 stations. Note: Minna is used in Nigeria, not Cameroon.",For military purposes only. Accuracy 25m in each axis.,3226,1.65,13.09,8.45,16.21,1,0,9603,-81,-84,115,,,,,0
-431,1168,4263,4326,Derived at 6 stations.,"For military purposes. Accuracy 3m, 6m and 5m in X, Y and Z axes.",1178,1.92,13.9,2.66,14.65,1,0,9603,-92,-93,122,,,,,1
-432,1534,4263,4326,,Oil exploration.,2371,4.22,6.95,4.35,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-433,1754,4263,4326,"Derived at 8 stations across the Niger delta. Used by Shell SPDC throughout southern Nigeria onshore, delta and shallow offshore from 1994 and by Total in OPL246. Sometimes given with parameter values to greater resolution; values here are adequate.",Oil exploration.,2371,4.22,6.95,4.35,9.45,1,0,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-434,1818,4263,4326,Concatenated via WGS 72BE.,Oil industry operations.,1717,1.92,6.14,2.66,7.82,1,0,9606,-89,-112,125.9,0,0,0.814,-0.38,0
-435,1819,4263,4326,Used by Shell in southern Nigeria and Total in OPL246.,Oil industry operations.,2371,4.22,6.95,4.35,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
-436,1820,4263,4326,Derived by Nortech at station L40 Minna using NNPC 1989 GPS network tied to 4 ADOS stations. Used by Conoco in OPLs 219-220 to cm precision and ExxonMobil in OPL 209 to dm precision..,Oil industry operations.,3813,3.25,5.54,4.01,6.96,1,0,9603,-93.2,-93.31,121.156,,,,,0
-437,1821,4263,4326,"Derived by Elf Petroleum Nigeria in 1994 at 3 stations (M101 onshore, offshore platforms XSW06 and XSV39) and used in OMLs 99-102 and OPLs 222-223.",Oil industry operations.,3814,3.25,4.51,7.16,8.25,1,0,9603,-88.98,-83.23,113.55,,,,,0
-438,1822,4263,4326,"Used by Shell SNEPCO for OPLs 209-213 and 316. Derived during 1990 Niger Delta control survey at 4 stations (XSU27, 30 31 and 35).",Oil industry exploration and production.,3815,4.22,6.31,3.83,5.17,1,0,9603,-92.726,-90.304,115.735,,,,,0
-439,1823,4263,4326,"Used by Shell SNEPCO for OPLs 217-223. Derived during 1990 Niger Delta control survey at 4 stations (XSU38, 41, 44 and 45).",Oil industry exploration and production.,3816,3.24,3.86,5.58,8,1,0,9603,-93.134,-86.647,114.196,,,,,0
-440,1824,4263,4326,Used by Shell SNEPCO for Gongola basin.,Oil industry exploration and production.,3824,8.78,11.63,9.41,12.13,1,0,9603,-93,-94,124,,,,,0
-441,15706,4263,4326,Used by Elf in Blocks OPL 222 and OPL 223 and by Mobil in 1994.,Oil industry exploration.,1717,1.92,6.14,2.66,7.82,1,0,9603,-93.6,-83.7,113.8,,,,,0
-442,15705,4263,4326,"Derived via WGS 72(BE). Minna to WGS 72(BE) transformation derived in 1981 for Mobil E&P Nigeria (MEPCON) by Geodetic Survey through Transit translocation at six stations in southern Nigeria. Used by MEPCON in blocks OPL 215 and 221.",Oil industry exploration.,3819,3.25,4.23,5.02,7.31,1,0,9606,-83.13,-104.95,114.63,0,0,0.554,0,0
-443,6196,4263,4326,Used by Addax for OPL 118 and OML 124. Derived in 1999 at 4 stations during  extension into OPL 118 of control in Chevron block OML 53.,Oil industry exploration and production.,4127,5.56,5.74,6.72,6.97,1,0,9603,-93.179,-87.124,114.338,,,,,0
-444,15493,4263,4326,"Adopted by MPN for all joint venture operations from 1/1/1996.",Oil industry exploration and production.,3590,3.99,5.01,5.99,8.01,1,0,9603,-94.031,-83.317,116.708,,,,,0
-445,15755,4263,4326,Derived in 1995 at unspecified DMA ADOS stations and Racal stations M101 and ZVS3003. Used by Elf in onshore Block OML 58.,Oil industry exploration and production. Accuracy 0.5m.,3113,5.05,5.36,6.53,6.84,1,0,9603,-90.2,-87.32,114.17,,,,,0
-446,1329,4264,4326,"Superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557. Malongo 1987 is an offshore extension of the Mhast cooordinate system.","Used for oil exploration by Chevron until superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557.",1317,-6.04,-5.05,10.53,12.18,1,1,9603,-252.95,-4.11,-96.38,,,,,0
-447,1088,4265,4326,,Oil exploration and production,2882,43.62,45.73,12.22,13.96,1,0,9603,-223.7,-67.38,1.34,,,,,0
-448,1089,4265,4326,,Oil exploration and production,2883,41.95,44.04,13.61,16.14,1,0,9603,-225.4,-67.7,7.85,,,,,0
-449,1090,4265,4326,,Oil exploration and production,2884,40.72,42.28,15.95,18.63,1,0,9603,-227.1,-68.1,14.4,,,,,0
-450,1091,4265,4326,,Marine navigation,2885,39.77,41.03,17.95,18.99,1,0,9603,-231.61,-68.21,13.93,,,,,0
-451,1092,4265,4326,,Marine navigation,2886,37.67,40.47,16.55,18.93,1,0,9603,-225.06,-67.37,14.61,,,,,0
-452,1093,4265,4326,,Marine navigation,2887,35.22,37.48,13,15.16,1,0,9603,-229.08,-65.73,20.21,,,,,0
-453,1094,4265,4326,,Marine navigation,2888,35.28,38.45,10.68,13.01,1,0,9603,-230.47,-56.08,22.43,,,,,0
-454,1169,4265,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2339,38.82,41.31,8.08,9.89,1,0,9603,-225,-65,9,,,,,0
-455,1660,4265,4326,"Parameter values from Monte Mario to ETRS89 (1) (code 1659). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2372,37.86,47.1,6.62,18.58,1,0,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68,1
-456,1662,4265,4326,"Parameter values from Monte Mario to ETRS89 (2) (code 1661). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2339,38.82,41.31,8.08,9.89,1,0,9606,-168.6,-34,38.6,-0.374,-0.679,-1.379,-9.48,0
-457,1664,4265,4326,"Parameter values from Monte Mario to ETRS89 (3) (code 1663). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2340,36.59,38.35,12.36,15.71,1,0,9606,-50.2,-50.4,84.8,-0.69,-2.012,0.459,-28.08,0
-458,1163,4266,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-74,-130,42,,,,,1
-459,1532,4266,4326,Derived as mean of Doris determinations at 3 stations in Port Gentil area in 1994.,Oil exploration.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-80.7,-132.5,41.1,,,,,0
-460,1170,4267,4326,Derived at 15 stations.,"For military purposes. Accuracy 3m, 9m and 12m in X, Y and Z axes.",2418,13,23.25,-85.01,-59.37,1,0,9603,-3,142,183,,,,,0
-461,1171,4267,4326,Derived at 19 stations.,"For military purposes only. Accuracy 8m, 3m and 5m in X, Y and Z axes.",2419,7.98,18.49,-92.29,-82.53,1,0,9603,0,125,194,,,,,0
-462,1172,4267,4326,Derived at 112 stations.,"For military purposes only. Accuracy 15m, 11m and 6m in X, Y and Z axes.",1061,40.04,86.46,-141.01,-47.74,1,0,9603,-10,158,187,,,,,1
-463,1173,4267,4326,Derived at 405 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",1323,24.41,49.38,-124.79,-66.91,1,0,9603,-8,160,176,,,,,0
-464,1174,4267,4326,Derived at 129 stations.,"For military purposes only. Accuracy 5m, 5m and 8m in X, Y and Z axes.",2389,24.41,49.38,-97.22,-66.91,1,0,9603,-9,161,179,,,,,0
-465,1175,4267,4326,Derived at 276 stations.,"For military purposes only. Accuracy 5m, 3m and 3m in X, Y and Z axes.",2390,25.83,49.05,-124.79,-89.64,1,0,9603,-8,159,175,,,,,0
-466,1176,4267,4326,Derived at 47 stations.,"For military purposes only. Accuracy 5m, 9m and 5m in X, Y and Z axes.",2412,54.34,71.4,-168.26,-129.99,1,0,9603,-5,135,172,,,,,0
-467,1177,4267,4326,Derived at 11 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",2413,20.86,27.29,-79.04,-72.68,1,0,9603,-4,154,178,,,,,0
-468,1178,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2414,23.9,24.19,-74.6,-74.37,1,0,9603,1,140,165,,,,,0
-469,1179,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 8m, 8m and 6m in X, Y and Z axes.",2384,48.25,60.01,-139.04,-109.98,1,0,9603,-7,162,188,,,,,0
-470,1180,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",2415,41.67,60.01,-102,-74.35,1,0,9603,-9,157,184,,,,,0
-471,1181,4267,4326,Derived at 37 stations.,"For military purposes only. Accuracy 6m, 6m and 3m in X, Y and Z axes.",2416,43.41,62.62,-79.85,-52.54,1,0,9603,-22,160,190,,,,,0
-472,1182,4267,4326,Derived at 17 stations.,"For military purposes only. Accuracy 5m, 5m and 3m in X, Y and Z axes.",2410,49,83.17,-136.46,-60.72,1,0,9603,4,159,188,,,,,0
-473,1183,4267,4326,Derived at 8 stations.,"For military purposes only. Accuracy 5m, 8m and 3m in X, Y and Z axes.",2417,59.99,69.7,-141.01,-123.91,1,0,9603,-7,139,181,,,,,0
-474,1184,4267,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2385,8.82,9.45,-80.07,-79.46,1,0,9603,0,125,201,,,,,0
-475,1185,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3235,19.77,23.25,-85.01,-74.07,1,0,9603,-9,152,178,,,,,0
-476,1186,4267,4326,"Derived at 2 stations. Note: NAD27 is not used in Greenland.",For military purposes. Accuracy 25m in each axis.,2386,75.86,79.2,-73.29,-60.98,1,0,9603,11,114,195,,,,,0
-477,1187,4267,4326,Derived at 22 stations.,"For military purposes only. Accuracy 8m, 6m and 6m in X, Y and Z axes.",3278,14.51,32.72,-118.47,-86.68,1,0,9603,-12,130,190,,,,,0
-478,1249,4267,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 10m in X, Y and Z axes.",2387,51.54,54.34,-178.3,-164.84,1,0,9603,-2,152,149,,,,,0
-479,1250,4267,4326,Derived at 5 stations.,For military purposes. Accuracy 10m in each axis.,2388,51.3,53.07,172.42,179.86,1,0,9603,2,204,105,,,,,0
-480,1530,4267,4326,,Accuracy 3m.,1077,18.83,25.51,-87.01,-73.57,1,0,9603,-4.2,135.4,181.9,,,,,0
-481,15699,4267,4326,"Developed by John E Chance and Associates at 19°44'N, 92°21'W. Geoid height used =-13.34m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3462,17.85,20.89,-94.79,-89.75,1,0,9603,-2,124.7,196,,,,,0
-482,15852,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3358,23.82,30.25,-87.25,-81.17,1,0,9603,-3,154,177,,,,,0
-483,15853,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3359,25.61,30.23,-95,-87.25,1,0,9603,-7,151,175,,,,,0
-484,15854,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3360,25.97,28.97,-97.22,-95,1,0,9603,-7,151,178,,,,,0
-485,15855,4267,4326,"Developed by John E Chance and Associates at 21°55'N, 97°20'W. Geoid height used =-17m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3361,21.51,22.75,-98.1,-96.89,1,0,9603,-8,125,190,,,,,0
-486,15856,4267,4326,"Developed by EnSoCo Inc. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).",Oil exploration and production. Accuracy 8 metres.,3357,23.82,30.25,-97.22,-81.17,1,0,9603,-7,158,172,,,,,0
-487,15913,4267,4326,"Developed by John E Chance and Associates at 21°33'N, 92°33'W. Geoid height used =-16.7m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3461,20.87,23.01,-94.33,-88.67,1,0,9603,0,125,196,,,,,0
-488,15978,4267,4326,,Accuracy 1m.,1077,18.83,25.51,-87.01,-73.57,1,0,9607,2.478,149.752,197.726,-0.526,-0.498,0.501,0.685,0
-489,1188,4269,4326,Derived at 354 stations.,Accuracy 2m in each axis.,1325,23.81,86.46,-172.54,-47.74,1,0,9603,0,0,0,,,,,1
-490,1251,4269,4326,Derived at 4 stations.,"For military purposes only. Accuracy 5m, 2m and 5m in X, Y and Z axes.",2157,51.3,54.34,172.42,-164.84,1,0,9603,-2,0,4,,,,,0
-491,1252,4269,4326,Derived at 6 stations.,For military purposes only. Accuracy 2m in each axis.,3883,15.56,25.58,-163.74,-151.27,1,0,9603,1,1,-1,,,,,0
-492,1308,4269,4326,"Strictly between NAD83 and ITRF94(1996.0). Superseded by NAD83 to WGS 84 (5) (code 1515).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.91,1,1,9607,-0.9738,1.9453,0.5486,-0.0275508,-0.010049,-0.011359,0,0
-493,1515,4269,4326,"Strictly between NAD83 and ITRF96(1997.0). Supersedes NAD83 to WGS 84 (4) (code 1308).",Geodesy.,1323,24.41,49.38,-124.79,-66.91,1,1,9607,-0.991,1.9072,0.5129,-0.02578991,-0.00965010,-0.0116599,0,0
-494,1189,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2391,20.12,20.74,58.58,59.01,1,0,9603,-247,-148,369,,,,,0
-495,1190,4270,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3968,24.63,28.57,47.95,50.81,1,0,9603,-243,-192,477,,,,,0
-496,1191,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1243,22.63,26.27,51.5,57.13,1,0,9603,-249,-156,381,,,,,1
-497,1531,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at platform AK1 to 4 IGS stations in March 1995.,Oil exploration.,2392,25.33,25.54,53.03,53.4,1,0,9603,-245,-153.9,382.8,,,,,0
-498,1536,4270,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation North Field development. Adopted by QGPC for all offshore Qatar.",Oil exploration.,2406,24.64,27.05,50.55,53.04,1,0,9603,-250.2,-153.09,391.7,,,,,0
-499,15871,4270,4326,Derived by concatenation of parameter values published by IGN Paris from Nahrwan 1967 to WGS 72 at the Nahrwan SE Base trig station near Baghdad with DMA WGS 72 to WGS 84 parameter values.,Oil exploration.,3625,29.06,37.39,38.79,48.61,1,1,9603,-242.2,-144.9,370.3,,,,,0
-500,6998,4270,4326,Derived via WGS 72 but provenance uncertain. In ADMA replaces tfm code 15938. In ADCO replaced by tfm code 6999 from October 2013.,Oil exploration and production.,4226,22.63,25.64,51.5,56.03,1,0,9607,-233.4,-160.7,381.5,0,0,-0.554,0.2263,0
-501,6999,4270,4326,"Derived in October 2013 at four control points of the ADCO CRF and evaluated at four others. Estimated horizontal accuracy of 0.14 m at the 95% confidence level.","Oil exploration and production horizontal coordinate transformation. Although a 3D transformation, should not be used for vertical dimension.",4225,22.63,24.95,51.56,56.03,1,0,9607,-253.4392,-148.452,386.5267,-0.15605,-0.43,0.1013,-0.0424,0
-502,7002,4270,4326,,Abu Dhabi Municipality GIS.,4229,24.24,24.64,54.2,54.71,1,0,9607,-246.1633,-152.9047,382.6047,-0.0989,-0.1382,-0.0768,2.1e-06,0
-503,7003,4270,4326,,Abu Dhabi Municipality GIS.,1850,22.76,24.32,51.56,54.01,1,0,9607,-242.8907,-149.0671,384.416,-0.19044,-0.24987,-0.13925,0.0001746,0
-504,7004,4270,4326,,Abu Dhabi Municipality GIS.,4227,22.63,24.95,53.99,56.03,1,0,9607,-246.734,-153.4345,382.1477,0.116617,0.165167,0.091327,1.94e-05,0
-505,15937,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at station TC58 to 4 IGS stations in March 1995.,Oil exploration.,3509,24,25.64,51.5,54.85,1,0,9603,-245.8,-152.2,382.9,,,,,0
-506,15938,4270,4326,Derived via WGS 72BE from Transit observations at station TC58 in 1976 by BP for ADMA.,Oil exploration.,3509,24,25.64,51.5,54.85,1,0,9606,-225.4,-158.7,380.8,0,0,0.814,-0.38,0
-507,15952,4270,4326,"Used by DPC for Al Fateh field. Applying this transformation gives same result as Nahrwan 1967 to WGS 84 (8) (code 15938).",Oil exploration and production.,3530,24.94,25.8,54.06,55.3,1,0,9603,-244.2,-149.8,379.3,,,,,0
-508,15953,4270,4326,Used by Dubai Municipality before 1994.,Municipal operations.,3531,24.85,25.34,54.84,55.55,1,0,9603,-250.7,-157.9,380.4,,,,,0
-509,1192,4271,4326,"CAUTION: OGP believes that these parameter values include a blunder and that if NIMA transformation parameters are to be used the 1987 version (EPSG code 1307) be used.",For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,1322,11.09,11.4,-60.9,-60.47,1,0,9603,-10,375,165,,,,,1
-510,1307,4271,4326,"(1) See remarks for tfm code 1192. (2) Naparima 1972 is an extension to Tobago of the Napaima 1955 geographic CRS of Trindad. In Trinidad this transformation may also be considered to use Napaima 1955 (code 4158) as its source CRS: see tfm code 1556.",For military purposes only. Accuracy 15m in each axis.,1322,11.09,11.4,-60.9,-60.47,1,0,9603,-2,374,172,,,,,0
-511,1151,4272,4326,Derived at 14 stations.,"For military purposes only. Accuracy 5m, 3m and 5m in X, Y and Z axes.",3285,-47.65,-33.89,165.87,179.27,1,0,9603,84,-22,209,,,,,0
-512,1564,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (2) (code 1701) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the transformation. For improved accuracy use NZGD49 to WGS 84 (4) (code 1670).",Transformation accuracy about 4 metres.,3285,-47.65,-33.89,165.87,179.27,1,0,9607,59.47,-5.04,187.44,-0.47,0.1,-1.024,-4.5993,1
-513,15975,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (1) (code 1566) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the tfm. For better accuracy use NZGD49 to WGS 84 (2) (code 1564) or NZGD49 to WGS 84 (3) (code 1670).",5m accuracy.,3285,-47.65,-33.89,165.87,179.27,1,0,9603,54.4,-20.1,183.1,,,,,0
-514,1654,4273,4326,"Parameter values from NGO 1948 to ETRS89 (1) (code 1653). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 3 metres.,1352,57.93,71.21,4.68,31.22,1,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21,1
-515,1658,4274,4326,"Parameter values from Datum 73 to ETRS89 (1) (code 1657). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Datum 73 to WGS 84 (4) (tfm code 1987).",For applications to an accuracy of 2 metres.,1294,36.95,42.16,-9.56,-6.19,1,0,9606,-238.2,85.2,29.9,0.166,0.046,1.248,2.03,0
-516,1945,4274,4326,"Parameter values from Datum 73 to ETRS89 (2) (code 1792). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1294,36.95,42.16,-9.56,-6.19,1,1,9606,-231,102.6,29.8,0.615,-0.198,0.881,1.79,0
-517,1983,4274,4326,,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-223.237,110.193,36.649,,,,,1
-518,1987,4274,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-239.749,88.181,30.488,-0.263,-0.082,-1.211,2.229,0
-519,1193,4275,4326,"These same parameter values are used to transform to ETRS89. See NTF to ETRS89 (1) (code 1651).",For applications to an accuracy of 2 metres.,3694,41.31,51.14,-4.87,9.63,1,0,9603,-168,-60,320,,,,,1
-520,1195,4277,4326,Derived at 38 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",1264,49.81,60.9,-8.74,1.84,1,0,9603,375,-111,431,,,,,0
-521,1196,4277,4326,Derived at 24 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",2395,49.81,55.85,-6.5,1.84,1,0,9603,371,-112,434,,,,,0
-522,1197,4277,4326,Derived at 25 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",2396,49.81,55.85,-6.5,1.84,1,0,9603,371,-111,434,,,,,0
-523,1198,4277,4326,Derived at 13 stations.,For military purposes only. Accuracy 10m in each axis.,2397,54.57,60.9,-8.74,-0.65,1,0,9603,384,-111,425,,,,,0
-524,1199,4277,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2398,51.28,53.48,-5.34,-2.65,1,0,9603,370,-108,434,,,,,0
-525,1314,4277,4326,"For a more accurate transformation see OSGB 1936 / British National Grid to ETRS89 (2) (code 1039): contact the Ordnance Survey of Great Britain (http://www.gps.gov.uk/gpssurveying.asp) for details.",Oil exploration. Accuracy better than 4m and generally better than 2m.,1264,49.81,60.9,-8.74,1.84,1,0,9606,446.448,-125.157,542.06,0.15,0.247,0.842,-20.489,1
-526,5622,4277,4326,Derived by CGG for 1994 3D seismic survey.,Oil exploration and production.,3893,50.53,50.8,-2.2,-1.68,1,0,9603,370.396,-108.938,435.682,,,,,0
-527,4560,4558,4326,"Approximation at the +/- 1m level assuming that RRAF91 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,0,9603,0,0,0,,,,,1
-528,1074,4281,4326,"Not recognised by Survey of Israel. See Palestine 1923 to WGS 84 (2) (code 8650).","Oil Exploration. Accuracy: 1m to north and 5m to south of east-west line through Beersheba (31°15'N).",2603,29.45,33.28,34.17,35.69,1,0,9606,-275.7224,94.7824,340.8944,-8.001,-4.42,-11.821,1,1
-529,1200,4282,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1072,-6.91,3.72,8.84,18.65,1,0,9603,-148,51,-291,,,,,1
-530,1801,4282,4326,"Derived in 1994 by CGG/Topnav using DORIS system on various stations along the coastline.","?",2574,-6.91,-3.55,8.84,12.34,1,0,9603,-145,52.7,-291.6,,,,,0
-531,1802,4282,4326,Derived by Geoid for Elf in May 1995 using GPS and IGS data by tying 4 geodetic points to ITRF93 epoch 1995.4.,Used by Elf since May 1995 for all offshore Congo operations.,2574,-6.91,-3.55,8.84,12.34,1,0,9606,-178.3,-316.7,-131.5,5.278,6.077,10.979,19.166,0
-532,1150,4283,4326,,GDA94 is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,0,0,0,,,,,1
-533,1254,4284,4326,Accuracy estimate not available.,For military purposes.,1198,39.87,85.2,18.92,-168.97,1,0,9603,28,-130,-95,,,,,0
-534,1267,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (2) (tfm code 1244. Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5044.",Accuracy 4 metres.,1198,39.87,85.2,18.92,-168.97,1,0,9607,23.92,-141.27,-80.9,0,-0.35,-0.82,-0.12,1
-535,1287,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.74,48.58,16.11,22.9,1,1,9603,28,-121,-77,,,,,0
-536,1288,4284,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",1192,49,55.93,14.14,24.15,1,1,9603,23,-124,-82,,,,,0
-537,1289,4284,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,1,9603,26,-121,-78,,,,,0
-538,1290,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1139,55.67,58.09,19.06,28.24,1,0,9603,24,-124,-82,,,,,0
-539,1291,4284,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1131,40.59,55.45,46.49,87.35,1,0,9603,15,-130,-84,,,,,0
-540,1292,4284,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,1025,39.63,42.67,18.46,21.06,1,1,9603,24,-130,-92,,,,,0
-541,1293,4284,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
-542,1303,4284,4326,Mean of 13 stations along entire Kazak coastline.,Residuals under 2 m.,2405,41.15,46.97,48.9,53.15,1,0,9606,43.822,-108.842,-119.585,1.455,-0.761,0.737,0.549,0
-543,1334,4284,4326,,"?",3246,57.52,59.75,21.74,28.2,1,0,9607,21.58719,-97.54127,-60.92546,-1.01378,-0.58117,-0.2348,-4.6121,0
-544,1679,4284,4326,"Parameter values taken from Pulkovo 1942 to LKS94(ETRS89) (1) (code 1274) assuming that LKS94(ETRS89) is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 9m level.",1145,53.89,56.45,19.02,26.82,1,0,9607,-40.595,-18.55,-69.339,-2.508,-1.832,2.611,-4.299,0
-545,1807,4284,4326,"Derived via WGS72 values taken from SOCAR Magnavox 1502 manual. Used by AIOC 1995-1997 then replaced by the AIOC97 values (tfm code 1808).
+369,1930,4642,4326,,"Accuracy better than +/- 1 metre.",2820,-22.73,-22.49,167.36,167.61,1,1,9606,244.416,85.339,168.114,-8.9353,7.7523,12.5953,14.268,0
+370,15848,4642,4326,,"Accuracy +/- 10 metres.",2820,-22.73,-22.49,167.36,167.61,1,0,9603,-13,-348,292,,,,,1
+371,1157,4244,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3310,5.86,9.88,79.64,81.95,1,0,9603,-97,787,86,,,,,1
+372,1158,4245,4326,Derived at 6 stations.,"For military purposes. Accuracy 10m, 8m and 6m in X, Y and Z axes.",4223,1.13,7.81,99.59,105.82,1,0,9603,-11,851,5,,,,,1
+373,1059,4246,4326,,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-294.7,-200.1,525.5,,,,,1
+374,1516,4247,4326,Also used for PSAD56 to WGS 84 transformations.,"Parameter values estimated accuracy: ± 2.0m; ± 2.7m; ± 1.3m respectively.",2363,3.56,10.8,-67.49,-59.8,1,0,9603,-273.5,110.6,-357.9,,,,,1
+375,1201,4248,4326,Derived at 63 stations. DMA also lists Colombia as area of applicability but PSAD56 is not used in that country.,"For military purposes only. Accuracy 17m, 27m and 27m in X, Y and Z axes.",2399,-45,12.52,-81.41,-56.47,1,0,9603,-288,175,-376,,,,,1
+376,1202,4248,4326,Derived at 5 stations.,"For military purposes only. Accuracy 5m, 11m and 14m in X, Y and Z axes.",1049,-22.91,-9.67,-69.66,-57.52,1,0,9603,-270,188,-388,,,,,0
+377,1203,4248,4326,"Derived at 1 station. Replaced by PSAD56 to WGS 84 (15) (code 6971).",For military purposes. Accuracy 25m in each axis.,2402,-21.51,-17.5,-70.49,-68.18,1,0,9603,-270,183,-390,,,,,0
+378,1204,4248,4326,"Derived at 3 stations. Replaced by PSAD56 to WGS 84 (17) (code 6973).",For military purposes. Accuracy 20m in each axis.,2403,-45,-38.99,-75.22,-71.1,1,0,9603,-305,243,-442,,,,,0
+379,1205,4248,4326,"Derived at 4 stations. Note that although the PSAD56 network included Colombia the CRS is not used there: see Bogota 1975 (CRS code 4218).",For military purposes. Accuracy 15m in each axis.,3229,-4.23,12.52,-79.1,-66.87,1,0,9603,-282,169,-371,,,,,0
+380,1206,4248,4326,Derived at 11 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",3241,-5.01,1.45,-81.03,-75.21,1,0,9603,-278,171,-367,,,,,0
+381,1207,4248,4326,Derived at 9 stations.,"For military purposes. Accuracy 6m, 14m and 5m in X, Y and Z axes.",1114,1.18,10.7,-61.39,-55.77,1,0,9603,-298,159,-369,,,,,0
+382,1208,4248,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 12m in X, Y and Z axes.",1189,-21.05,-0.03,-84.68,-68.67,1,0,9603,-279,175,-379,,,,,0
+383,1209,4248,4326,Derived at 24 stations.,"For military purposes only. Accuracy 9m, 14m and 15m in X, Y and Z axes.",1251,0.64,16.75,-73.38,-58.95,1,0,9603,-295,173,-371,,,,,0
+384,1582,4248,4326,Derived May 1995 by Geoid for Total. OSU91A geoid model used.,Oil exploration.,2400,-14.43,-13.56,-68.96,-67.79,1,0,9603,-259.73,173.12,-398.27,,,,,0
+385,1583,4248,4326,Derived July 1997 by Geoid from data recorded by UGA for Total. OSU91A geoid model used.,Oil exploration.,2401,-21.71,-21.09,-63.44,-62.95,1,0,9603,-307.7,265.3,-363.5,,,,,0
+386,1811,4248,4326,Used by Petrobras for shelf operations.,Oil industry exploration.,1754,-1.05,5.6,-51.64,-48,1,0,9603,-291.87,106.37,-364.52,,,,,0
+387,3990,4248,4326,"Parameter values from PSAD56 to SIRGAS 1995 (1) (code 3971). Assumes SIRGAS 1995 and WGS 84 can be considered the same to within the accuracy of the transformation.","Suitable for mapping at 1:25,000 scale and smaller.",3241,-5.01,1.45,-81.03,-75.21,1,0,9607,-60.31,245.935,31.008,-12.324,-3.755,7.37,0.447,0
+388,6971,4248,4326,"Derived at 5 stations. Replaces PSAD56 to WGS 84 (3) (code 1203). Also used as a transformation from PSAD56 to SIRGAS-Chile - see code 6949.",For military purposes. Accuracy 10m in each axis.,4231,-26,-17.5,-70.79,-67,1,0,9603,-302,272,-360,,,,,0
+389,6972,4248,4326,Derived at 7 stations. Also used as a transformation from PSAD56 to SIRGAS-Chile - see code 6950.,For military purposes. Accuracy 10m in each axis.,4222,-36,-26,-72.87,-68.28,1,0,9603,-328,340,-329,,,,,0
+390,6973,4248,4326,"Derived at 6 stations. Replaces PSAD56 to WGS 84 (4) (code 1204). Info source gives S limit as 44°S but Chilean IGM states that PSAD56 limit is 43°30'S. Also used as a transformation from PSAD56 to SIRGAS-Chile - see code 6951.",For military purposes. Accuracy 10m in each axis.,4221,-43.5,-35.99,-74.48,-70.39,1,0,9603,-352,403,-287,,,,,0
+391,15967,4761,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. HTRS96 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1076,41.62,46.54,13,19.43,1,0,9603,0,0,0,,,,,1
+392,1159,4250,4326,Derived at 8 stations.,"For military purposes. Accuracy 2m, 3m and 2m in X, Y and Z axes.",1104,1.4,11.16,-3.79,2.1,1,0,9603,-130,29,364,,,,,1
+393,1160,4251,4326,Derived at 4 stations.,For military purposes only. Accuracy 15m in each axis.,3270,4.29,8.52,-11.52,-7.36,1,0,9603,-90,40,88,,,,,1
+394,1887,4182,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1344,39.3,39.77,-31.34,-31.02,1,0,9603,-425,-169,81,,,,,1
+395,1982,4182,4326,Derived at 2 stations in 1999.,For low resolution applications.,1344,39.3,39.77,-31.34,-31.02,1,0,9603,-422.651,-172.995,84.02,,,,,0
+396,1161,4253,4326,Derived at 6 stations.,"For military purposes. Accuracy 8m, 11m and 9m in X, Y and Z axes.",2364,7.75,19.45,116.89,125.88,1,0,9603,-133,-77,-51,,,,,1
+397,1162,4253,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2365,4.99,10.52,119.76,126.65,1,0,9603,-133,-79,-72,,,,,0
+398,1529,4254,4326,"Derived through ties at 3 stations (RC03, TOTAL11 and MP12) to 3 IGS stations in November 1995",Oil exploration.,2357,-55.11,-52.59,-68.64,-63.73,1,0,9606,18.38,192.45,96.82,0.056,-0.142,-0.2,-0.0013,0
+399,1892,4254,4326,Derived at 2 stations. As the source CRS was used for the border survey this transformation is probably also applicable to adjacent areas of Argentina.,Accuracy 25m in each axis.,2805,-55.96,-51.99,-74.83,-66.33,1,0,9603,16,196,93,,,,,1
+400,1246,4255,4326,Accuracy estimate not available.,For military purposes only.,1024,29.4,38.48,60.5,74.92,1,0,9603,-333,-222,114,,,,,1
+401,1164,4256,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2369,-4.86,-4.5,55.3,55.59,1,0,9603,41,-220,-134,,,,,1
+402,1549,4208,4326,,Oil exploration.,2307,-28.41,-17.59,-48.8,-35.18,1,1,9603,-158,315,-148,,,,,0
+403,1550,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2308,-9.8,-8.39,-39.04,-37.09,1,0,9603,-139.62,290.53,-150.29,,,,,0
+404,1551,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2309,-10.61,-9.79,-39.14,-37.99,1,0,9603,-141.15,293.44,-150.56,,,,,0
+405,1552,4208,4326,"Replaced by Aratu to WGS 84 (18) (tfm code 5061) which Petrobras now recommends for the area.",Oil exploration.,2310,-12.27,-10.6,-39.07,-37.98,1,0,9603,-142.48,296.03,-149.74,,,,,0
+406,10089,4208,4326,"Used by ExxonMobil for block BMS1. See WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.41,-22.66,-48.8,-40.2,1,0,9603,-163.466,317.396,-147.538,,,,,0
+407,10090,4208,4326,"Used by ExxonMobil for block BC10. Derived from earlier Shell position vector tfm of dX = -181m, dY = +294m, dZ = -144.5m, rX = rY = 0, rZ = +0.554s, dS = +0.219 ppm. See Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-170,305,-145,,,,,0
+408,10091,4208,4326,"Used by ExxonMobil for block BMES1. See Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-162.904,312.531,-137.109,,,,,0
+409,10092,4208,4326,"Used by ExxonMobil for block BP1. Also used by BG as part of a concatenated tfm to SAD69 for offshore regional studies. See WGS 84 (13) (tfm code 5051) for transformation Petrobras now recommends for the area.",Oil exploration.,2965,-35.71,-28.11,-53.38,-44.71,1,0,9603,-158,309,-151,,,,,0
+410,10093,4208,4326,"Used by ExxonMobil for offshore regional studies. See Aratu to WGS 84 (13) through (21) (tfm codes 5051-67 [odd numbers only]) which Petrobras now recommends for various areas.",Oil exploration.,2966,-34,-18,-53.38,-35.19,1,0,9603,-161,308,-142,,,,,0
+411,10094,4208,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.89,18.25,-16.11,-15.83,1,1,9603,124.5,-63.5,-281,,,,,0
+412,15710,4208,4326,"Replaced by Aratu to WGS 84 (14) (tfm code 5053) which Petrobras now recommends for the area.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-160,315,-142,,,,,0
+413,15711,4208,4326,"Replaced by Aratu to WGS 84 (13) (tfm code 5051) which Petrobras now recommends for the area.",Oil exploration.,2962,-28.41,-22.66,-48.8,-40.2,1,0,9603,-158,309,-147,,,,,0
+414,15712,4208,4326,"Replaced by Aratu to WGS 84 (15) (tfm code 5055) which Petrobras now recommends for the area.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-161,310,-145,,,,,0
+415,5051,4208,4326,"Parameters from Aratu to SIRGAS 2000 (1) (tfm code 5050) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15711 and 15734.",Oil exploration.,3700,-35.71,-22.66,-53.38,-40.2,1,0,9603,-157.84,308.54,-146.6,,,,,0
+416,5053,4208,4326,"Parameters from Aratu to SIRGAS 2000 (2) (tfm code 5052) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfm codes 15710 and 15754.",Oil exploration.,2963,-25.91,-20.45,-42.04,-37.11,1,0,9603,-160.31,314.82,-142.25,,,,,0
+417,5055,4208,4326,"Parameters from Aratu to SIRGAS 2000 (3) (tfm code 5054) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 15712 and 15754.",Oil exploration.,2964,-22.04,-17.59,-40.37,-35.18,1,0,9603,-161.11,310.25,-144.64,,,,,0
+418,5057,4208,4326,"Parameters from Aratu to SIRGAS 2000 (4) (tfm code 5056) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3699,-17.7,-13.01,-39.22,-34.6,1,0,9603,-160.4,302.29,-144.19,,,,,0
+419,5059,4208,4326,"Parameters from Aratu to SIRGAS 2000 (5) (tfm code 5058) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3692,-13.57,-11.18,-39.09,-35.31,1,0,9603,-153.54,302.33,-152.37,,,,,0
+420,5061,4208,4326,"Parameters from Aratu to SIRGAS 2000 (6) (tfm code 5060) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area. Replaces tfms 1550-1552.",Oil exploration.,3693,-12.27,-8.39,-39.14,-37.09,1,0,9603,-151.5,300.09,-151.15,,,,,0
+421,5063,4208,4326,"Parameters from Aratu to SIRGAS 2000 (7) (tfm code 5062) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3696,-13.58,-8.73,-37.34,-32.01,1,0,9603,-156.8,298.41,-147.41,,,,,0
+422,5065,4208,4326,"Parameters from Aratu to SIRGAS 2000 (8) (tfm code 5064) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation.Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3697,-10.17,-4.6,-35.1,-29.13,1,0,9603,-157.4,295.05,-150.19,,,,,0
+423,5067,4208,4326,"Parameters from Aratu to SIRGAS 2000 (9) (tfm code 5066) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation. Petrobras preferred parameters for all purposes in the area.",Oil exploration.,3698,-6.5,4.26,-44.79,-26,1,0,9603,-151.99,287.04,-147.45,,,,,1
+424,15754,4208,4326,"Mean for 3 basins. See Aratu to WGS 84 (10) through (12) (codes 15710-12) for transformations for individual basins. Replaced by Aratu to WGS 84 (13) through (15) (tfm codes 5051, 5053 and 5055) which Petrobras now recommends for the areas.",Oil exploration.,2307,-28.41,-17.59,-48.8,-35.18,1,0,9603,-158,315,-148,,,,,0
+425,1149,4258,4326,,ETRS89 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1298,32.88,84.17,-16.1,40.18,1,0,9603,0,0,0,,,,,1
+426,1571,4258,4326,"Dutch sources also quote an equivalent transformation with parameter values dX=+593.032 dY=+26.000 dZ=+478.741m, rX rY rZ and dS as this tfm. These values belong to a different transformation method and cannot be used with the Coordinate Frame method.",Accuracy 0.5m,1172,50.75,55.77,2.53,7.22,1,1,9607,565.04,49.91,465.84,0.409394,-0.359705,1.86849,4.0772,0
+427,1330,4259,4326,"Derived at Station Y in April 1989 using 572 transit satellite passes. Computed value for dZ was -96.42 but -96.38 has been utilised. Replaced Malongo 1987 to WGS 84 (3) (code 15791) in 1989. Replaced by Malongo 1987 to WGS 84 (2) (code 1557) in 1990.",Offshore oil exploration and production between April 1989 and June 1990.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-252.95,-4.11,-96.38,,,,,0
+428,1557,4259,4326,"Derived at station Y in July 1990 through Transit single point positioning using 187 passes by Geodetic Survey Ltd. Replaces Malongo 1987 to WGS 84 (1) (trf code 1330).",Offshore oil exploration and production from June 1990.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-254.1,-5.36,-100.29,,,,,1
+429,15791,4259,4326,"Derived via WGS 72BE by Geodetic for Chevron in 1987 by single point Transit translocation at 1 station (Malongo Y). Replaced in 1989 by Malongo 1987 to WGS 84 (1) (code 1330).",Oil industry exploration and production between September 1987 and April 1989.,3180,-6.04,-5.05,10.53,12.37,1,0,9603,-259.99,-5.28,-97.09,,,,,0
+430,1316,4260,4326,,"?",1060,1.65,13.09,8.32,16.21,1,1,9603,-70.9,-151.8,-41.4,,,,,0
+431,1166,4261,4326,Derived at 9 stations.,"For military purposes. Accuracy 5m, 3m and 3m in X, Y and Z axes.",3280,27.66,35.97,-13.24,-1.01,1,0,9603,31,146,47,,,,,1
+432,1165,4262,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1089,12.36,18.1,36.44,43.31,1,0,9603,639,405,60,,,,,1
+433,1067,4263,4326,"Used by Statoil for deep water blocks 210, 213, 217 and 218. Parameter values interpolated from Racal Survey geocentric translation contour charts for each of these four blocks and then meaned.",Oil industry exploration and production.,3817,3.24,5.54,4.41,6.29,1,0,9603,-92.1,-89.9,114.9,,,,,0
+434,1167,4263,4326,"Derived at 2 stations. Note: Minna is used in Nigeria, not Cameroon.",For military purposes only. Accuracy 25m in each axis.,3226,1.65,13.09,8.45,16.21,1,0,9603,-81,-84,115,,,,,0
+435,1168,4263,4326,Derived at 6 stations.,"For military purposes. Accuracy 3m, 6m and 5m in X, Y and Z axes.",1178,1.92,13.9,2.66,14.65,1,0,9603,-92,-93,122,,,,,1
+436,1534,4263,4326,,Oil exploration.,2371,4.22,6.95,4.35,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+437,1754,4263,4326,"Derived at 8 stations across the Niger delta. Used by Shell SPDC throughout southern Nigeria onshore, delta and shallow offshore from 1994 and by Total in OPL246. Sometimes given with parameter values to greater resolution; values here are adequate.",Oil exploration.,2371,4.22,6.95,4.35,9.45,1,0,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+438,1818,4263,4326,Concatenated via WGS 72BE.,Oil industry operations.,1717,1.92,6.14,2.66,7.82,1,0,9606,-89,-112,125.9,0,0,0.814,-0.38,0
+439,1819,4263,4326,Used by Shell in southern Nigeria and Total in OPL246.,Oil industry operations.,2371,4.22,6.95,4.35,9.45,1,1,9606,-111.92,-87.85,114.5,1.875,0.202,0.219,0.032,0
+440,1820,4263,4326,Derived by Nortech at station L40 Minna using NNPC 1989 GPS network tied to 4 ADOS stations. Used by Conoco in OPLs 219-220 to cm precision and ExxonMobil in OPL 209 to dm precision..,Oil industry operations.,3813,3.25,5.54,4.01,6.96,1,0,9603,-93.2,-93.31,121.156,,,,,0
+441,1821,4263,4326,"Derived by Elf Petroleum Nigeria in 1994 at 3 stations (M101 onshore, offshore platforms XSW06 and XSV39) and used in OMLs 99-102 and OPLs 222-223.",Oil industry operations.,3814,3.25,4.51,7.16,8.25,1,0,9603,-88.98,-83.23,113.55,,,,,0
+442,1822,4263,4326,"Used by Shell SNEPCO for OPLs 209-213 and 316. Derived during 1990 Niger Delta control survey at 4 stations (XSU27, 30 31 and 35).",Oil industry exploration and production.,3815,4.22,6.31,3.83,5.17,1,0,9603,-92.726,-90.304,115.735,,,,,0
+443,1823,4263,4326,"Used by Shell SNEPCO for OPLs 217-223. Derived during 1990 Niger Delta control survey at 4 stations (XSU38, 41, 44 and 45).",Oil industry exploration and production.,3816,3.24,3.86,5.58,8,1,0,9603,-93.134,-86.647,114.196,,,,,0
+444,1824,4263,4326,Used by Shell SNEPCO for Gongola basin.,Oil industry exploration and production.,3824,8.78,11.63,9.41,12.13,1,0,9603,-93,-94,124,,,,,0
+445,15706,4263,4326,Used by Elf in Blocks OPL 222 and OPL 223 and by Mobil in 1994.,Oil industry exploration.,1717,1.92,6.14,2.66,7.82,1,0,9603,-93.6,-83.7,113.8,,,,,0
+446,15705,4263,4326,"Derived via WGS 72(BE). Minna to WGS 72(BE) transformation derived in 1981 for Mobil E&P Nigeria (MEPCON) by Geodetic Survey through Transit translocation at six stations in southern Nigeria. Used by MEPCON in blocks OPL 215 and 221.",Oil industry exploration.,3819,3.25,4.23,5.02,7.31,1,0,9606,-83.13,-104.95,114.63,0,0,0.554,0,0
+447,6196,4263,4326,Used by Addax for OPL 118 and OML 124. Derived in 1999 at 4 stations during  extension into OPL 118 of control in Chevron block OML 53.,Oil industry exploration and production.,4127,5.56,5.74,6.72,6.97,1,0,9603,-93.179,-87.124,114.338,,,,,0
+448,15493,4263,4326,"Adopted by MPN for all joint venture operations from 1/1/1996.",Oil industry exploration and production.,3590,3.99,5.01,5.99,8.01,1,0,9603,-94.031,-83.317,116.708,,,,,0
+449,15755,4263,4326,Derived in 1995 at unspecified DMA ADOS stations and Racal stations M101 and ZVS3003. Used by Elf in onshore Block OML 58.,Oil industry exploration and production. Accuracy 0.5m.,3113,5.05,5.36,6.53,6.84,1,0,9603,-90.2,-87.32,114.17,,,,,0
+450,1329,4264,4326,"Superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557. Malongo 1987 is an offshore extension of the Mhast cooordinate system.","Used for oil exploration by Chevron until superseded in 1990 by trf Malongo 1987 to WGS 84 (2), code 1557.",1317,-6.04,-5.05,10.53,12.18,1,1,9603,-252.95,-4.11,-96.38,,,,,0
+451,1088,4265,4326,,Oil exploration and production,2882,43.62,45.73,12.22,13.96,1,0,9603,-223.7,-67.38,1.34,,,,,0
+452,1089,4265,4326,,Oil exploration and production,2883,41.95,44.04,13.61,16.14,1,0,9603,-225.4,-67.7,7.85,,,,,0
+453,1090,4265,4326,,Oil exploration and production,2884,40.72,42.28,15.95,18.63,1,0,9603,-227.1,-68.1,14.4,,,,,0
+454,1091,4265,4326,,Marine navigation,2885,39.77,41.03,17.95,18.99,1,0,9603,-231.61,-68.21,13.93,,,,,0
+455,1092,4265,4326,,Marine navigation,2886,37.67,40.47,16.55,18.93,1,0,9603,-225.06,-67.37,14.61,,,,,0
+456,1093,4265,4326,,Marine navigation,2887,35.22,37.48,13,15.16,1,0,9603,-229.08,-65.73,20.21,,,,,0
+457,1094,4265,4326,,Marine navigation,2888,35.28,38.45,10.68,13.01,1,0,9603,-230.47,-56.08,22.43,,,,,0
+458,1169,4265,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2339,38.82,41.31,8.08,9.89,1,0,9603,-225,-65,9,,,,,0
+459,1660,4265,4326,"Parameter values from Monte Mario to ETRS89 (1) (code 1659). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2372,37.86,47.1,6.62,18.58,1,0,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68,1
+460,1662,4265,4326,"Parameter values from Monte Mario to ETRS89 (2) (code 1661). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2339,38.82,41.31,8.08,9.89,1,0,9606,-168.6,-34,38.6,-0.374,-0.679,-1.379,-9.48,0
+461,1664,4265,4326,"Parameter values from Monte Mario to ETRS89 (3) (code 1663). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.","Accuracy: 4 metres",2340,36.59,38.35,12.36,15.71,1,0,9606,-50.2,-50.4,84.8,-0.69,-2.012,0.459,-28.08,0
+462,1163,4266,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-74,-130,42,,,,,1
+463,1532,4266,4326,Derived as mean of Doris determinations at 3 stations in Port Gentil area in 1994.,Oil exploration.,1100,-6.37,2.32,7.03,14.52,1,0,9603,-80.7,-132.5,41.1,,,,,0
+464,1170,4267,4326,Derived at 15 stations.,"For military purposes. Accuracy 3m, 9m and 12m in X, Y and Z axes.",2418,13,23.25,-85.01,-59.37,1,0,9603,-3,142,183,,,,,0
+465,1171,4267,4326,Derived at 19 stations.,"For military purposes only. Accuracy 8m, 3m and 5m in X, Y and Z axes.",2419,7.98,18.49,-92.29,-82.53,1,0,9603,0,125,194,,,,,0
+466,1172,4267,4326,Derived at 112 stations.,"For military purposes only. Accuracy 15m, 11m and 6m in X, Y and Z axes.",1061,40.04,86.46,-141.01,-47.74,1,0,9603,-10,158,187,,,,,1
+467,1173,4267,4326,Derived at 405 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",1323,24.41,49.38,-124.79,-66.91,1,0,9603,-8,160,176,,,,,0
+468,1174,4267,4326,Derived at 129 stations.,"For military purposes only. Accuracy 5m, 5m and 8m in X, Y and Z axes.",2389,24.41,49.38,-97.22,-66.91,1,0,9603,-9,161,179,,,,,0
+469,1175,4267,4326,Derived at 276 stations.,"For military purposes only. Accuracy 5m, 3m and 3m in X, Y and Z axes.",2390,25.83,49.05,-124.79,-89.64,1,0,9603,-8,159,175,,,,,0
+470,1176,4267,4326,Derived at 47 stations.,"For military purposes only. Accuracy 5m, 9m and 5m in X, Y and Z axes.",2412,54.34,71.4,-168.26,-129.99,1,0,9603,-5,135,172,,,,,0
+471,1177,4267,4326,Derived at 11 stations.,"For military purposes. Accuracy 5m, 3m and 5m in X, Y and Z axes.",2413,20.86,27.29,-79.04,-72.68,1,0,9603,-4,154,178,,,,,0
+472,1178,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2414,23.9,24.19,-74.6,-74.37,1,0,9603,1,140,165,,,,,0
+473,1179,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 8m, 8m and 6m in X, Y and Z axes.",2384,48.25,60.01,-139.04,-109.98,1,0,9603,-7,162,188,,,,,0
+474,1180,4267,4326,Derived at 25 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",2415,41.67,60.01,-102,-74.35,1,0,9603,-9,157,184,,,,,0
+475,1181,4267,4326,Derived at 37 stations.,"For military purposes only. Accuracy 6m, 6m and 3m in X, Y and Z axes.",2416,43.41,62.62,-79.85,-52.54,1,0,9603,-22,160,190,,,,,0
+476,1182,4267,4326,Derived at 17 stations.,"For military purposes only. Accuracy 5m, 5m and 3m in X, Y and Z axes.",2410,49,83.17,-136.46,-60.72,1,0,9603,4,159,188,,,,,0
+477,1183,4267,4326,Derived at 8 stations.,"For military purposes only. Accuracy 5m, 8m and 3m in X, Y and Z axes.",2417,59.99,69.7,-141.01,-123.91,1,0,9603,-7,139,181,,,,,0
+478,1184,4267,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,2385,8.82,9.45,-80.07,-79.46,1,0,9603,0,125,201,,,,,0
+479,1185,4267,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,3235,19.77,23.25,-85.01,-74.07,1,0,9603,-9,152,178,,,,,0
+480,1186,4267,4326,"Derived at 2 stations. Note: NAD27 is not used in Greenland.",For military purposes. Accuracy 25m in each axis.,2386,75.86,79.2,-73.29,-60.98,1,0,9603,11,114,195,,,,,0
+481,1187,4267,4326,Derived at 22 stations.,"For military purposes only. Accuracy 8m, 6m and 6m in X, Y and Z axes.",3278,14.51,32.72,-118.47,-86.68,1,0,9603,-12,130,190,,,,,0
+482,1249,4267,4326,Derived at 6 stations.,"For military purposes only. Accuracy 6m, 8m and 10m in X, Y and Z axes.",2387,51.54,54.34,-178.3,-164.84,1,0,9603,-2,152,149,,,,,0
+483,1250,4267,4326,Derived at 5 stations.,For military purposes. Accuracy 10m in each axis.,2388,51.3,53.07,172.42,179.86,1,0,9603,2,204,105,,,,,0
+484,1530,4267,4326,,Accuracy 3m.,1077,18.83,25.51,-87.01,-73.57,1,0,9603,-4.2,135.4,181.9,,,,,0
+485,15699,4267,4326,"Developed by John E Chance and Associates at 19°44'N, 92°21'W. Geoid height used =-13.34m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3462,17.85,20.89,-94.79,-89.75,1,0,9603,-2,124.7,196,,,,,0
+486,15913,4267,4326,"Developed by John E Chance and Associates at 21°33'N, 92°33'W. Geoid height used =-16.7m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3461,20.87,23.01,-94.33,-88.67,1,0,9603,0,125,196,,,,,0
+487,15852,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3358,23.82,30.25,-87.25,-81.17,1,0,9603,-3,154,177,,,,,0
+488,15853,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3359,25.61,30.23,-95,-87.25,1,0,9603,-7,151,175,,,,,0
+489,15854,4267,4326,"Developed by John E Chance and Associates. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3360,25.97,28.97,-97.22,-95,1,0,9603,-7,151,178,,,,,0
+490,15855,4267,4326,"Developed by John E Chance and Associates at 21°55'N, 97°20'W. Geoid height used =-17m.","Oil exploration and production. Horizontal transformation accuracy (1 sigma) is considered to be at the +/- 5 meter level.",3361,21.51,22.75,-98.1,-96.89,1,0,9603,-8,125,190,,,,,0
+491,15856,4267,4326,"Developed by EnSoCo Inc. Replaced by NAD27 to WGS 84 (79) (tfm code 15851).",Oil exploration and production. Accuracy 8 metres.,3357,23.82,30.25,-97.22,-81.17,1,0,9603,-7,158,172,,,,,0
+492,7698,4267,4326,"Derived at stations in the provinces of Colón, Panamá, Coclé, Veraguas,
+Herrera, Los Santos y Chiriquí. Standard deviation 0.871m in north and 0.531m in east.",Accuracy 1m.,3290,7.15,9.68,-83.04,-77.19,1,0,9607,-32.3841359,180.4090461,120.8442577,2.1545854,0.1498782,-0.5742915,8.1049164,0
+493,15978,4267,4326,,Accuracy 1m.,1077,18.83,25.51,-87.01,-73.57,1,0,9607,2.478,149.752,197.726,-0.526,-0.498,0.501,0.685,0
+494,1188,4269,4326,Derived at 354 stations.,Accuracy 2m in each axis.,1325,23.81,86.46,-172.54,-47.74,1,0,9603,0,0,0,,,,,1
+495,1251,4269,4326,Derived at 4 stations.,"For military purposes only. Accuracy 5m, 2m and 5m in X, Y and Z axes.",2157,51.3,54.34,172.42,-164.84,1,0,9603,-2,0,4,,,,,0
+496,1252,4269,4326,Derived at 6 stations.,For military purposes only. Accuracy 2m in each axis.,3883,15.56,25.58,-163.74,-151.27,1,0,9603,1,1,-1,,,,,0
+497,1308,4269,4326,"Strictly between NAD83 and ITRF94(1996.0). Superseded by NAD83 to WGS 84 (5) (code 1515).",Historical record only - superseded - see remarks.,1323,24.41,49.38,-124.79,-66.91,1,1,9607,-0.9738,1.9453,0.5486,-0.0275508,-0.010049,-0.011359,0,0
+498,1515,4269,4326,"Strictly between NAD83 and ITRF96(1997.0). Supersedes NAD83 to WGS 84 (4) (code 1308).",Geodesy.,1323,24.41,49.38,-124.79,-66.91,1,1,9607,-0.991,1.9072,0.5129,-0.02578991,-0.00965010,-0.0116599,0,0
+499,1189,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,2391,20.12,20.74,58.58,59.01,1,0,9603,-247,-148,369,,,,,0
+500,1190,4270,4326,Derived at 3 stations.,For military purposes. Accuracy 20m in each axis.,3968,24.63,28.57,47.95,50.81,1,0,9603,-243,-192,477,,,,,0
+501,1191,4270,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1243,22.63,26.27,51.5,57.13,1,0,9603,-249,-156,381,,,,,1
+502,1531,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at platform AK1 to 4 IGS stations in March 1995.,Oil exploration.,2392,25.33,25.54,53.03,53.4,1,0,9603,-245,-153.9,382.8,,,,,0
+503,1536,4270,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation North Field development. Adopted by QGPC for all offshore Qatar.",Oil exploration.,2406,24.64,27.05,50.55,53.04,1,0,9603,-250.2,-153.09,391.7,,,,,0
+504,15937,4270,4326,Parameter values adopted by Total are mean of those derived by Oceonics and Geoid through ties at station TC58 to 4 IGS stations in March 1995.,Oil exploration.,3509,24,25.64,51.5,54.85,1,0,9603,-245.8,-152.2,382.9,,,,,0
+505,15938,4270,4326,Derived via WGS 72BE from Transit observations at station TC58 in 1976 by BP for ADMA.,Oil exploration.,3509,24,25.64,51.5,54.85,1,0,9606,-225.4,-158.7,380.8,0,0,0.814,-0.38,0
+506,15871,4270,4326,Derived by concatenation of parameter values published by IGN Paris from Nahrwan 1967 to WGS 72 at the Nahrwan SE Base trig station near Baghdad with DMA WGS 72 to WGS 84 parameter values.,Oil exploration.,3625,29.06,37.39,38.79,48.61,1,1,9603,-242.2,-144.9,370.3,,,,,0
+507,6998,4270,4326,Derived via WGS 72 but provenance uncertain. In ADMA replaces tfm code 15938. In ADCO replaced by tfm code 6999 from October 2013.,Oil exploration and production.,4226,22.63,25.64,51.5,56.03,1,0,9607,-233.4,-160.7,381.5,0,0,-0.554,0.2263,0
+508,6999,4270,4326,"Derived in October 2013 at four control points of the ADCO CRF and evaluated at four others. Estimated horizontal accuracy of 0.14 m at the 95% confidence level.","Oil exploration and production horizontal coordinate transformation. Although a 3D transformation, should not be used for vertical dimension.",4225,22.63,24.95,51.56,56.03,1,0,9607,-253.4392,-148.452,386.5267,-0.15605,-0.43,0.1013,-0.0424,0
+509,7002,4270,4326,,Abu Dhabi Municipality GIS.,4229,24.24,24.64,54.2,54.71,1,0,9607,-246.1633,-152.9047,382.6047,-0.0989,-0.1382,-0.0768,2.1e-06,0
+510,7003,4270,4326,,Abu Dhabi Municipality GIS.,1850,22.76,24.32,51.56,54.01,1,0,9607,-242.8907,-149.0671,384.416,-0.19044,-0.24987,-0.13925,0.0001746,0
+511,7004,4270,4326,,Abu Dhabi Municipality GIS.,4227,22.63,24.95,53.99,56.03,1,0,9607,-246.734,-153.4345,382.1477,0.116617,0.165167,0.091327,1.94e-05,0
+512,15952,4270,4326,"Used by DPC for Al Fateh field. Applying this transformation gives same result as Nahrwan 1967 to WGS 84 (8) (code 15938).",Oil exploration and production.,3530,24.94,25.8,54.06,55.3,1,0,9603,-244.2,-149.8,379.3,,,,,0
+513,15953,4270,4326,Used by Dubai Municipality before 1994.,Municipal operations.,3531,24.85,25.34,54.84,55.55,1,0,9603,-250.7,-157.9,380.4,,,,,0
+514,1192,4271,4326,"CAUTION: OGP believes that these parameter values include a blunder and that if NIMA transformation parameters are to be used the 1987 version (EPSG code 1307) be used.",For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,1322,11.09,11.4,-60.9,-60.47,1,0,9603,-10,375,165,,,,,1
+515,1307,4271,4326,"(1) See remarks for tfm code 1192. (2) Naparima 1972 is an extension to Tobago of the Napaima 1955 geographic CRS of Trindad. In Trinidad this transformation may also be considered to use Napaima 1955 (code 4158) as its source CRS: see tfm code 1556.",For military purposes only. Accuracy 15m in each axis.,1322,11.09,11.4,-60.9,-60.47,1,0,9603,-2,374,172,,,,,0
+516,1151,4272,4326,Derived at 14 stations.,"For military purposes only. Accuracy 5m, 3m and 5m in X, Y and Z axes.",3285,-47.65,-33.89,165.87,179.27,1,0,9603,84,-22,209,,,,,0
+517,1564,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (2) (code 1701) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the transformation. For improved accuracy use NZGD49 to WGS 84 (4) (code 1670).",Transformation accuracy about 4 metres.,3285,-47.65,-33.89,165.87,179.27,1,0,9607,59.47,-5.04,187.44,-0.47,0.1,-1.024,-4.5993,1
+518,15975,4272,4326,"These parameter values are taken from NZGD49 to NZGD2000 (1) (code 1566) and assume that NZGD2000 and WGS 84 are coincident to within the accuracy of the tfm. For better accuracy use NZGD49 to WGS 84 (2) (code 1564) or NZGD49 to WGS 84 (3) (code 1670).",5m accuracy.,3285,-47.65,-33.89,165.87,179.27,1,0,9603,54.4,-20.1,183.1,,,,,0
+519,1654,4273,4326,"Parameter values from NGO 1948 to ETRS89 (1) (code 1653). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 3 metres.,1352,57.93,71.21,4.68,31.22,1,0,9606,278.3,93,474.5,7.889,0.05,-6.61,6.21,1
+520,1658,4274,4326,"Parameter values from Datum 73 to ETRS89 (1) (code 1657). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaced by Datum 73 to WGS 84 (4) (tfm code 1987).",For applications to an accuracy of 2 metres.,1294,36.95,42.16,-9.56,-6.19,1,0,9606,-238.2,85.2,29.9,0.166,0.046,1.248,2.03,0
+521,1945,4274,4326,"Parameter values from Datum 73 to ETRS89 (2) (code 1792). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1294,36.95,42.16,-9.56,-6.19,1,1,9606,-231,102.6,29.8,0.615,-0.198,0.881,1.79,0
+522,1983,4274,4326,,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,-223.237,110.193,36.649,,,,,1
+523,1987,4274,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,-239.749,88.181,30.488,-0.263,-0.082,-1.211,2.229,0
+524,1193,4275,4326,"These same parameter values are used to transform to ETRS89. See NTF to ETRS89 (1) (code 1651).",For applications to an accuracy of 2 metres.,3694,41.31,51.14,-4.87,9.63,1,0,9603,-168,-60,320,,,,,1
+525,1195,4277,4326,Derived at 38 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",1264,49.79,60.94,-8.82,1.92,1,0,9603,375,-111,431,,,,,0
+526,1196,4277,4326,Derived at 24 stations.,"For military purposes only. Accuracy 5m, 5m and 6m in X, Y and Z axes.",2395,49.81,55.85,-6.5,1.84,1,0,9603,371,-112,434,,,,,0
+527,1197,4277,4326,Derived at 25 stations.,"For military purposes only. Accuracy 10m, 10m and 15m in X, Y and Z axes.",2396,49.81,55.85,-6.5,1.84,1,0,9603,371,-111,434,,,,,0
+528,1198,4277,4326,Derived at 13 stations.,For military purposes only. Accuracy 10m in each axis.,2397,54.57,60.9,-8.74,-0.65,1,0,9603,384,-111,425,,,,,0
+529,1199,4277,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,2398,51.28,53.48,-5.34,-2.65,1,0,9603,370,-108,434,,,,,0
+530,1314,4277,4326,"For a more accurate transformation see OSGB 1936 / British National Grid to ETRS89 (2) (code 1039): contact the Ordnance Survey of Great Britain (http://www.gps.gov.uk/gpssurveying.asp) for details.",Oil exploration. Accuracy better than 4m and generally better than 2m.,1264,49.79,60.94,-8.82,1.92,1,0,9606,446.448,-125.157,542.06,0.15,0.247,0.842,-20.489,1
+531,5622,4277,4326,Derived by CGG for 1994 3D seismic survey.,Oil exploration and production.,3893,50.53,50.8,-2.2,-1.68,1,0,9603,370.936,-108.938,435.682,,,,,0
+532,7898,7881,4326,"Parameter values from Tritan St. Helena to SHGD2015 (1) (tfm code 7897). Assumes Tritan St. Helena and SHGD2015 can be considered the same to within the accuracy of the transformation.",For applications requiring an accuracy of better than 1 metre.,3183,-16.08,-15.85,-5.85,-5.58,1,0,9603,-0.077,0.079,0.086,,,,,1
+533,4560,4558,4326,"Approximation at the +/- 1m level assuming that RRAF91 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,0,9603,0,0,0,,,,,1
+534,1074,4281,4326,"Not recognised by Survey of Israel. See Palestine 1923 to WGS 84 (2) (code 8650).","Oil Exploration. Accuracy: 1m to north and 5m to south of east-west line through Beersheba (31°15'N).",2603,29.45,33.28,34.17,35.69,1,0,9606,-275.7224,94.7824,340.8944,-8.001,-4.42,-11.821,1,1
+535,1200,4282,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1072,-6.91,3.72,8.84,18.65,1,0,9603,-148,51,-291,,,,,1
+536,1801,4282,4326,"Derived in 1994 by CGG/Topnav using DORIS system on various stations along the coastline.","?",2574,-6.91,-3.55,8.84,12.34,1,0,9603,-145,52.7,-291.6,,,,,0
+537,1802,4282,4326,Derived by Geoid for Elf in May 1995 using GPS and IGS data by tying 4 geodetic points to ITRF93 epoch 1995.4.,Used by Elf since May 1995 for all offshore Congo operations.,2574,-6.91,-3.55,8.84,12.34,1,0,9606,-178.3,-316.7,-131.5,5.278,6.077,10.979,19.166,0
+538,1150,4283,4326,,GDA94 is a realisation of WGS 84 coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,2575,-43.7,-9.86,112.85,153.69,1,0,9603,0,0,0,,,,,1
+539,1254,4284,4326,Accuracy estimate not available.,For military purposes.,1198,39.87,85.2,18.92,-168.97,1,0,9603,28,-130,-95,,,,,0
+540,1267,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (2) (tfm code 1244. Mandated for use in Russia by GOST R 51794-2001, but this has been superseded by GOST R 51794-2008. Replaced by tfm code 5044.",Accuracy 4 metres.,1198,39.87,85.2,18.92,-168.97,1,0,9607,23.92,-141.27,-80.9,0,-0.35,-0.82,-0.12,1
+541,1287,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1119,45.74,48.58,16.11,22.9,1,1,9603,28,-121,-77,,,,,0
+542,1288,4284,4326,Derived at 11 stations.,"For military purposes only. Accuracy 4m, 2m and 4m in X, Y and Z axes.",1192,49,55.93,14.14,24.15,1,1,9603,23,-124,-82,,,,,0
+543,1289,4284,4326,Derived at 6 stations.,"For military purposes only. Accuracy 3m, 3m and 2m in X, Y and Z axes.",1306,47.73,51.06,12.09,22.56,1,1,9603,26,-121,-78,,,,,0
+544,1290,4284,4326,Derived at 5 stations.,For military purposes. Accuracy 2m in each axis.,1139,55.67,58.09,19.06,28.24,1,0,9603,24,-124,-82,,,,,0
+545,1291,4284,4326,Derived at 2 stations.,For military purposes. Accuracy 25m in each axis.,1131,40.59,55.45,46.49,87.35,1,0,9603,15,-130,-84,,,,,0
+546,1292,4284,4326,Derived at 7 stations.,For military purposes. Accuracy 3m in each axis.,1025,39.63,42.67,18.46,21.06,1,1,9603,24,-130,-92,,,,,0
+547,1293,4284,4326,Derived at 4 stations.,"For military purposes. Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
+548,1303,4284,4326,Mean of 13 stations along entire Kazak coastline.,Residuals under 2 m.,2405,41.15,46.97,48.9,53.15,1,0,9606,43.822,-108.842,-119.585,1.455,-0.761,0.737,0.549,0
+549,1334,4284,4326,,"?",3246,57.52,59.75,21.74,28.2,1,0,9607,21.58719,-97.54127,-60.92546,-1.01378,-0.58117,-0.2348,-4.6121,0
+550,1679,4284,4326,"Parameter values taken from Pulkovo 1942 to LKS94(ETRS89) (1) (code 1274) assuming that LKS94(ETRS89) is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 9m level.",1145,53.89,56.45,19.02,26.82,1,0,9607,-40.595,-18.55,-69.339,-2.508,-1.832,2.611,-4.299,0
+551,1807,4284,4326,"Derived via WGS72 values taken from SOCAR Magnavox 1502 manual. Used by AIOC 1995-1997 then replaced by the AIOC97 values (tfm code 1808).
 Do not confuse with AIOC95 vertical datum as used in southern Caspian Sea and at Sangachal terminal by AIOC.",Oil industry operations by AIOC prior to 1997.,1038,37.89,42.59,44.77,51.73,1,0,9606,27,-135,-84.5,0,0,0.554,0.2263,0
-546,1808,4284,4326,"Mean of 3 stations in western Georgia, 4 stations in eastern Georgia and 4 stations in eastern Azerbaijan. Derived for use on AIOC early oil western export pipeline, but adopted for all AIOC work replacing the 1995 AIOC transformation (code 1807).",Oil industry operations.,2593,37.89,43.59,39.99,51.73,1,0,9606,686.1,-123.5,-574.4,8.045,-23.366,10.791,-2.926,0
-547,1809,4284,4326,Parameter values calculated by Elf Exploration and Production based on geodetic survey carried out by Azerbaijan State Committee for Geodesy and Cartography.,Oil industry operations.,2594,38.31,40.33,48.93,50.4,1,0,9606,926.4,-715.9,-186.4,-10.364,-20.78,26.452,-7.224,0
-548,5044,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90.02 to WGS 84. Replaces Pulkovo 1942 to WGS 84 (17) (code 1267).",Accuracy 3 metres.,1198,39.87,85.2,18.92,-168.97,1,0,9607,23.57,-140.95,-79.8,0,-0.35,-0.79,-0.22,0
-549,15865,4284,4326,"Derived via PZ-90 at 30 stations throughout USSR (Former Soviet Union, FSU) through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (1) (tfm code 15843).",Accuracy 4.5 metres.,2423,35.14,81.91,19.57,-168.97,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,0
-550,6899,4284,4326,Derived at 19 stations.,"For military purposes. Accuracy 2m, 3m and 3m in X, Y and Z axes.",3246,57.52,59.75,21.74,28.2,1,0,9603,22,-126,-85,,,,,0
-551,1561,4285,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1346,24.55,26.2,50.69,51.68,1,0,9603,-128,-283,22,,,,,0
-552,1562,4285,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation.",Oil exploration.,2406,24.64,27.05,50.55,53.04,1,0,9603,-128.16,-282.42,21.93,,,,,1
-553,1563,4285,4326,"Derived by Qatar Centre for GIS. See Qatar 1974 to WGS 84 (2) (code 1562) for transformation used by QGPC for offshore petroleum industry.",Oil exploration.,1346,24.55,26.2,50.69,51.68,1,0,9603,-128.033,-283.697,21.052,,,,,0
-554,1211,4287,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",2407,59.75,72,-55,-40,1,1,9603,164,138,-189,,,,,0
-555,1112,4289,4326,"Replaced by Amersfoort to WGS 84 (2) (code 1672).","?",1275,50.75,53.7,3.2,7.22,1,0,9606,593.16,26.15,478.54,-1.30440,-0.10330,-1.14450,4.0775,0
-556,1672,4289,4326,"Parameter values from Amersfoort to ETRS89 (1) (code 1751) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (1) (code 1112). Replaced by Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.04,49.91,465.84,0.409394,-0.359705,1.86849,4.0772,0
-557,4833,4289,4326,"Parameter values from Amersfoort to ETRS89 (5) (tfm code 4830) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.4171,50.3319,465.5524,0.398957,-0.343988,1.87740,4.0725,1
-558,15934,4289,4326,"Parameter values from Amersfoort to ETRS89 (3) (tfm code 15739) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (2) (code 1672). Replaced by Amersfoort to WGS 84 (4) (tfm code 4833).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.2369,50.0087,465.658,0.406857,-0.350733,1.87035,4.0812,0
-559,1212,4291,4326,Derived at 84 stations.,"For military purposes only. Accuracy 15m, 6m and 9m in X, Y and Z axes.",1341,-56.15,13,-82,-34,1,1,9603,-57,1,-41,,,,,0
-560,1213,4291,4326,Derived at 10 stations.,For military purposes only. Accuracy 5m in each axis.,1033,-58.41,-21.78,-73.59,-52.63,1,1,9603,-62,-1,-37,,,,,0
-561,1214,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1049,-22.91,-9.67,-69.66,-57.52,1,1,9603,-61,2,-48,,,,,0
-562,1215,4291,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",1053,-35.71,7.04,-74.01,-25.28,1,1,9603,-60,-2,-41,,,,,0
-563,1216,4291,4326,Derived at 9 stations.,"For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",1066,-59.87,-17.5,-113.21,-65.72,1,1,9603,-75,-1,-44,,,,,0
-564,1217,4291,4326,Derived at 7 stations.,"For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",1070,-4.23,15.51,-84.77,-66.87,1,1,9603,-44,6,-36,,,,,0
-565,1218,4291,4326,Derived at 11 stations.,For military purposes. Accuracy 3m in each axis.,1085,-5.01,5,-95.35,-75.21,1,1,9603,-48,3,-44,,,,,0
-566,1219,4291,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2356,-1.41,0.18,-91.72,-89.19,1,1,9603,-47,26,-42,,,,,0
-567,1220,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",1114,1.18,10.7,-61.39,-55.77,1,1,9603,-53,3,-47,,,,,0
-568,1221,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1188,-27.59,-19.29,-62.65,-54.24,1,1,9603,-61,2,-33,,,,,0
-569,1222,4291,4326,Derived at 6 stations.,For military purposes. Accuracy 5m in each axis.,1189,-21.05,-0.03,-84.68,-68.67,1,1,9603,-58,0,-44,,,,,0
-570,1223,4291,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1235,9.83,12.34,-62.09,-57.28,1,1,9603,-45,12,-33,,,,,0
-571,1224,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",1251,0.64,16.75,-73.38,-58.95,1,1,9603,-45,8,-33,,,,,0
-572,1548,4291,4326,"Derived by Brazilean Institute of Geography and Statistics (IGBE) in 1989. Used by ANP.",Medium and small scale mapping.,1053,-35.71,7.04,-74.01,-25.28,1,1,9603,-66.87,4.37,-38.52,,,,,0
-573,1225,4292,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,2355,-52.51,-51.16,-59.98,-57.61,1,0,9603,-355,21,72,,,,,1
-574,1226,4293,4326,"Derived at 3 stations. 
+552,1808,4284,4326,"Mean of 3 stations in western Georgia, 4 stations in eastern Georgia and 4 stations in eastern Azerbaijan. Derived for use on AIOC early oil western export pipeline, but adopted for all AIOC work replacing the 1995 AIOC transformation (code 1807).",Oil industry operations.,2593,37.89,43.59,39.99,51.73,1,0,9606,686.1,-123.5,-574.4,8.045,-23.366,10.791,-2.926,0
+553,1809,4284,4326,Parameter values calculated by Elf Exploration and Production based on geodetic survey carried out by Azerbaijan State Committee for Geodesy and Cartography.,Oil industry operations.,2594,38.31,40.33,48.93,50.4,1,0,9606,926.4,-715.9,-186.4,-10.364,-20.78,26.452,-7.224,0
+554,5044,4284,4326,"Derived through concatenation of Pulkovo 1942 to PZ-90.02 to WGS 84. Replaces Pulkovo 1942 to WGS 84 (17) (code 1267).",Accuracy 3 metres.,1198,39.87,85.2,18.92,-168.97,1,0,9607,23.57,-140.95,-79.8,0,-0.35,-0.79,-0.22,0
+555,15865,4284,4326,"Derived via PZ-90 at 30 stations throughout USSR (Former Soviet Union, FSU) through concatenation of Pulkovo 1942 to PZ-90 (1) (tfm code 15844) and PZ-90 to WGS 84 (1) (tfm code 15843).",Accuracy 4.5 metres.,2423,35.14,81.91,19.57,-168.97,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,0
+556,6899,4284,4326,Derived at 19 stations.,"For military purposes. Accuracy 2m, 3m and 3m in X, Y and Z axes.",3246,57.52,59.75,21.74,28.2,1,0,9603,22,-126,-85,,,,,0
+557,1561,4285,4326,Derived at 3 stations.,For military purposes only. Accuracy 20m in each axis.,1346,24.55,26.2,50.69,51.68,1,0,9603,-128,-283,22,,,,,0
+558,1562,4285,4326,"Derived by Brown & Root in 1992 for Qatar General Petroleum Corporation.",Oil exploration.,2406,24.64,27.05,50.55,53.04,1,0,9603,-128.16,-282.42,21.93,,,,,1
+559,1563,4285,4326,"Derived by Qatar Centre for GIS. See Qatar 1974 to WGS 84 (2) (code 1562) for transformation used by QGPC for offshore petroleum industry.",Oil exploration.,1346,24.55,26.2,50.69,51.68,1,0,9603,-128.033,-283.697,21.052,,,,,0
+560,1211,4287,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m, 25m and 32m in X, Y and Z axes.",2407,59.75,72,-55,-40,1,1,9603,164,138,-189,,,,,0
+561,15934,4289,4326,"Parameter values from Amersfoort to ETRS89 (3) (tfm code 15739) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (2) (code 1672). Replaced by Amersfoort to WGS 84 (4) (tfm code 4833).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.2369,50.0087,465.658,0.406857,-0.350733,1.87035,4.0812,1
+562,1112,4289,4326,"Replaced by Amersfoort to WGS 84 (2) (code 1672).","?",1275,50.75,53.7,3.2,7.22,1,0,9606,593.16,26.15,478.54,-1.30440,-0.10330,-1.14450,4.0775,0
+563,1672,4289,4326,"Parameter values from Amersfoort to ETRS89 (1) (code 1751) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (1) (code 1112). Replaced by Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.04,49.91,465.84,0.409394,-0.359705,1.86849,4.0772,0
+564,4833,4289,4326,"Parameter values from Amersfoort to ETRS89 (5) (tfm code 4830) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces Amersfoort to WGS 84 (3) (code 15934).","Approximation at the +/- 1m level.",1275,50.75,53.7,3.2,7.22,1,0,9607,565.4171,50.3319,465.5524,0.398957,-0.343988,1.87740,4.0725,0
+565,1212,4291,4326,Derived at 84 stations.,"For military purposes only. Accuracy 15m, 6m and 9m in X, Y and Z axes.",1341,-56.15,13,-82,-34,1,1,9603,-57,1,-41,,,,,0
+566,1213,4291,4326,Derived at 10 stations.,For military purposes only. Accuracy 5m in each axis.,1033,-58.41,-21.78,-73.59,-52.63,1,1,9603,-62,-1,-37,,,,,0
+567,1214,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1049,-22.91,-9.67,-69.66,-57.52,1,1,9603,-61,2,-48,,,,,0
+568,1215,4291,4326,Derived at 22 stations.,"For military purposes only. Accuracy 3m, 5m and 5m in X, Y and Z axes.",1053,-35.71,7.04,-74.01,-25.28,1,1,9603,-60,-2,-41,,,,,0
+569,1216,4291,4326,Derived at 9 stations.,"For military purposes only. Accuracy 15m, 8m and 11m in X, Y and Z axes.",1066,-59.87,-17.5,-113.21,-65.72,1,1,9603,-75,-1,-44,,,,,0
+570,1217,4291,4326,Derived at 7 stations.,"For military purposes only. Accuracy 6m, 6m and 5m in X, Y and Z axes.",1070,-4.23,15.51,-84.77,-66.87,1,1,9603,-44,6,-36,,,,,0
+571,1218,4291,4326,Derived at 11 stations.,For military purposes. Accuracy 3m in each axis.,1085,-5.01,5,-95.35,-75.21,1,1,9603,-48,3,-44,,,,,0
+572,1219,4291,4326,Derived at 1 station.,For military purposes. Accuracy 25m in each axis.,2356,-1.41,0.18,-91.72,-89.19,1,1,9603,-47,26,-42,,,,,0
+573,1220,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 9m, 5m and 5m in X, Y and Z axes.",1114,1.18,10.7,-61.39,-55.77,1,1,9603,-53,3,-47,,,,,0
+574,1221,4291,4326,Derived at 4 stations.,For military purposes. Accuracy 15m in each axis.,1188,-27.59,-19.29,-62.65,-54.24,1,1,9603,-61,2,-33,,,,,0
+575,1222,4291,4326,Derived at 6 stations.,For military purposes. Accuracy 5m in each axis.,1189,-21.05,-0.03,-84.68,-68.67,1,1,9603,-58,0,-44,,,,,0
+576,1223,4291,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,1235,9.83,12.34,-62.09,-57.28,1,1,9603,-45,12,-33,,,,,0
+577,1224,4291,4326,Derived at 5 stations.,"For military purposes only. Accuracy 3m, 6m and 3m in X, Y and Z axes.",1251,0.64,16.75,-73.38,-58.95,1,1,9603,-45,8,-33,,,,,0
+578,1548,4291,4326,"Derived by Brazilean Institute of Geography and Statistics (IGBE) in 1989. Used by ANP.",Medium and small scale mapping.,1053,-35.71,7.04,-74.01,-25.28,1,1,9603,-66.87,4.37,-38.52,,,,,0
+579,1225,4292,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,2355,-52.51,-51.16,-59.98,-57.61,1,0,9603,-355,21,72,,,,,1
+580,1226,4293,4326,"Derived at 3 stations. 
 Beware!  Source CRS uses German legal metres, transformation parameter values are in (International) metres. See tfm code 1271 for example.",For military purposes only. Accuracy 20m in each axis.,1169,-30.64,-16.95,8.24,25.27,1,0,9603,616,97,-251,,,,,1
-575,1271,4293,4326,"Beware!  Source CRS uses GLM, tfm param in m. Example: Schwarzeck ?=19°35'46.952""S ?=20°41'50.649""E h=1185.99m; X=5623409.386 Y=2124618.003 Z=-2125847.632 GLM; X=5623485.84m Y=2124646.89m Z=-2125876.54m; WGS 84 X=5624101.48m Y=2124748.97m Z=-2126132.35m.","?",1169,-30.64,-16.95,8.24,25.27,1,0,9603,615.64,102.08,-255.81,,,,,0
-576,1286,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.24,4.37,108.79,119.06,1,1,9603,-403,684,41,,,,,0
-577,1834,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.24,4.37,108.79,119.06,1,1,9603,-403,684,41,,,,,0
-578,1835,4294,4326,,Oil exploration.,1360,-4.24,4.29,114.55,119.06,1,1,9603,-387.06,636.53,46.29,,,,,0
-579,1836,4294,4326,,Oil exploration.,2770,-0.07,4.29,116.96,119.06,1,1,9603,-403.4,681.12,46.56,,,,,0
-580,6900,4129,4326,Derived at 3 stations.,For military purposes. Accuracy 10m in each axis.,1329,-26.87,-19.84,31.29,35.65,1,0,9603,-132,-110,-335,,,,,1
-581,1227,4297,4326,Accuracy estimate not available.,For military purposes.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-189,-242,-91,,,,,1
-582,6873,4297,4326,Derived at 9 points throughout Madagascar. Adopted by OMV.,For applications with an accuracy of 3m.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-198.383,-240.517,-107.909,,,,,0
-583,1228,4298,4326,Derived at 8 stations.,"For military purposes. Accuracy 10m, 10m and 12m in X, Y and Z axes.",1362,0.85,7.67,109.31,119.61,1,0,9603,-679,669,-48,,,,,1
-584,1592,4298,4326,"Originally used by BSP offshore only, use extended to onshore in 2010.",Oil exploration and production.,1055,4.01,6.31,112.37,115.37,1,0,9603,-678,670,-48,,,,,0
-585,1615,4298,4326,"CARE! Erroneous GPS data was used in the derivation of these parameters. They produce a coordinate difference of 10m horizontally and 50m vertically compared to Timbalai 1948 to WGS 84 (2) (code 1592).",Topographic and engineering survey onshore.,2349,4.01,5.11,114.09,115.37,1,0,9603,-726.282,703.611,-48.999,,,,,0
-586,1852,4298,4326,"Derived by Racal Survey for SSB at 24 coastal stations (including Timbalai fundamental point and 6 other primary triangulation stations) between in Sabah (Kudat southwards) and Sarawak (Sibu northwards).",Oil exploration.,2780,1.56,7.67,109.31,117.31,1,0,9606,-533.4,669.2,-52.5,0,0,4.28,9.4,0
-587,5248,4298,4326,,Oil exploration.,1055,4.01,6.31,112.37,115.37,1,1,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
-588,5249,4298,4326,"Parameter values taken from Timbalai 1948 to GDBD2009 (1) (code 5878) assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Oil exploration.,1055,4.01,6.31,112.37,115.37,1,0,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
-589,6902,4298,4326,Derived at 9 stations.,"For military purposes. Accuracy 1m, 6m and 2m in X, Y and Z axes.",2349,4.01,5.11,114.09,115.37,1,0,9603,-679,667,-49,,,,,0
-590,1229,4299,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1305,51.39,55.43,-10.56,-5.34,1,1,9603,506,-122,611,,,,,0
-591,1641,4299,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) TM65 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.39,55.43,-10.56,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-592,1954,4300,4326,"Parameter values taken from TM65 to ETRS89 (2) (code 1953). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.39,55.43,-10.56,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
-593,1956,4300,4326,"Derived at 7 stations. TM75 is based on the geodetic datum of 1965 which should not be confused with the mapping adjustment of 1965 (TM65).",For military purposes only. Accuracy 3m in each axis.,1305,51.39,55.43,-10.56,-5.34,1,0,9603,506,-122,611,,,,,0
-594,1230,4301,4326,Derived at 31 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2409,20.37,45.54,122.83,145.87,1,0,9603,-148,507,685,,,,,0
-595,1231,4301,4326,Derived at 16 stations.,"For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3995,30.18,45.54,128.31,145.87,1,0,9603,-148,507,685,,,,,0
-596,1232,4301,4326,"Derived at 29 stations. Replaced by Tokyo to WGS 84 (5) (code 1305).","For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3266,33.14,38.64,124.53,131.01,1,0,9603,-146,507,687,,,,,0
-597,1233,4301,4326,Derived at 3 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2408,23.98,26.91,122.83,131.38,1,0,9603,-158,507,676,,,,,0
-598,1305,4301,4326,"Derived at 29 stations. Replaces Tokyo to WGS 84 (3) (code 1232).",For military purposes. Accuracy 2m in each axis.,3266,33.14,38.64,124.53,131.01,1,0,9603,-147,506,687,,,,,0
-599,15484,4301,4326,"Parameter values from Tokyo to JGD2000 (1) (code 15483). Assumes JGD2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Surveying, mapping and civil engineering purposes. Accuracy on main islands 9m.",3957,20.37,45.54,122.83,154.05,1,0,9603,-146.414,507.337,680.507,,,,,1
-600,1296,4302,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,1339,9.83,11.51,-62.09,-60,1,0,9603,-61.702,284.488,472.052,,,,,1
-601,10085,4302,4326,"Parameter values provided to EOG by Trinidad Ministry of Energy and Energy Industries. Used by EOG offshore Trinidad (including Pelican, Kiskadee and Ibis fields) since 1996.",Oil exploration.,1339,9.83,11.51,-62.09,-60,1,0,9603,-61,285.2,471.6,,,,,0
-602,1932,4644,4326,,"Accuracy better than +/- 1 metre.",2823,-22.37,-22.19,166.35,166.54,1,1,9606,-166.207,-154.777,254.831,-37.5444,7.7011,-10.2025,-30.8598,0
-603,15904,4644,4326,"Parameter values taken from NEA74 Noumea to RGNC91-93 (1) ( code 15886) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2823,-22.37,-22.19,166.35,166.54,1,0,9603,-10.18,-350.43,291.37,,,,,1
-604,1294,4304,4326,Accuracy estimate not available.,For military purposes.,1365,31.99,37.14,-2.95,9.09,1,0,9603,-73,-247,227,,,,,1
-605,15815,4728,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3873,27.58,29.3,-18.22,-13.37,1,0,9603,-307,-92,127,,,,,1
-606,1253,4307,4326,Derived at 3 stations.,For military purposes only. Accuracy 25m in each axis.,3213,18.97,37.14,-8.67,11.99,1,0,9603,-186,-93,310,,,,,0
-607,1255,4307,4326,"CAUTION: Source CRS described by DMA as from Voirol 1960. OGP believes that the data used in the derivation of these parameters contains a blunder. We recommend using transformation North Sahara 1959 to WGS84 (1) (code 1253). Derived at 2 stations.",For military purposes only. Accuracy 25m in each axis.,1365,31.99,37.14,-2.95,9.09,1,0,9603,-123,-206,219,,,,,0
-608,1815,4307,4326,Used by BP in District 3 and In Salah Gas.,Oil industry operations.,2598,25,32,1,3.3,1,0,9606,-152.9,43.8,358.3,2.714,1.386,-2.788,-6.743,0
-609,1816,4307,4326,"Derived at astro station central to concession. Significant and varying differences (>100m) at 4 neighbouring astro stations.",Oil industry operations.,2599,27.5,28.3,8.83,9.92,1,0,9603,-95.7,10.2,158.9,,,,,0
-610,1817,4307,4326,Derived at astro station Guerrara.,Oil industry operations.,2600,31.75,32.42,7.16,8,1,0,9603,-165.914,-70.607,305.009,,,,,0
-611,5630,4307,4326,"Derived at 1 station (L38).",Used by Total in Ahnet licence area.,3917,26.06,27.51,1.26,2.92,1,0,9603,-168.52,-72.05,304.3,,,,,0
-612,5660,4307,4326,Derived in 2006 at 45 points in north and central Algeria.,Accuracy at 75 common points better than 1m..,1026,18.97,38.8,-8.67,11.99,1,0,9606,-209.3622,-87.8162,404.6198,0.0046,3.4784,0.5805,-1.4547,1
-613,7442,4307,4326,"Derived at 1 astro station central to concession. Significant and varying differences (>100m) known to exist in neighbouring astro stations.",Oil industry operations.,4382,27.4,28.1,7.66,8.27,1,0,9603,-181.7,64.7,247.2,,,,,0
-614,15874,4307,4326,"Derived at 11 stations throughout blocks 317b, 319b, 321b and 322b. Network based on station P4 (horizontal) and benchmark RN51 (vertical) using EGM96 geoid height. Used by Statoil in Hassi Mouina.",Oil exploration and production. Accuracy 5m.,3402,29.25,31,0,1.25,1,0,9603,-169.559,-72.34,303.102,,,,,0
-615,1234,4309,4326,Accuracy estimate not available.,For military purposes.,3326,-35,-30.09,-58.49,-53.09,1,0,9603,-155,171,37,,,,,1
-616,5386,4309,4326,Derived at 11 stations during 1998 densification of Uruguay control based on SIRGAS 1995.,"Accuracy at stations used for derivation: 0.13 to 1.17m.",3326,-35,-30.09,-58.49,-53.09,1,0,9606,-124.45,183.74,44.64,-0.4384,0.5446,-0.9706,-2.1365,0
-617,6903,4310,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1207,10.64,16.7,-20.22,-11.36,1,0,9603,-30,190,89,,,,,1
-618,1235,4311,4326,Derived at 5 stations.,"For military purposes. Accuracy 5m, 5m and 8m in X, Y and Z axes.",1222,1.83,9.35,-58.08,-52.66,1,0,9603,-265,120,-358,,,,,1
-619,1194,4312,4326,May be taken as approximate transformation MGI to ETRS89 assuming ETRS89 is equivalent to WGS 84 within the accuracy of the transformation - see tfm code 1024. Information source gives scale as -2.388739 ppm.,Provincial GIS and other applications to an accuracy of 0.5 metres.,1543,46.64,47.84,13.58,16.17,1,0,9607,601.705,84.263,485.227,-4.7354,-1.3145,-5.393,-2.3887,0
-620,1306,4312,4326,Accuracy estimate not available.,For military purposes only.,2370,40.85,46.88,13.38,23.04,1,1,9603,682,-203,480,,,,,0
-621,1471,4312,4326,,For applications to an accuracy of 1.5 metres.,1037,46.4,49.02,9.53,17.17,1,1,9606,-577.326,-90.129,-463.919,-5.136599,-1.474,-5.297044,-2.4232,0
-622,1618,4312,4326,"Same transformation parameters used for MGI to ETRS89 (1) (code 1619).",For applications to an accuracy of 1.5 metres.,1037,46.4,49.02,9.53,17.17,1,0,9606,577.326,90.129,463.919,5.137,1.474,5.297,2.4232,1
-623,1621,4312,4326,"Parameter values from MGI to ETRS89 (2) (code 1620). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1076,41.62,46.54,13,19.43,1,1,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
-624,1786,4312,4326,"Parameter values from MGI to ETRS89 (3) (code 1785). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,1,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
-625,1794,4312,4326,"For more accurate transformation see MGI to WGS 84 (7) (code 1795).",Oil industry,3536,41.79,43.56,18.45,20.38,1,1,9603,695.5,-216.6,491.1,,,,,0
-626,15982,4312,4326,"Parameter values from MGI to Slovenia 1996 (1) (code 15981). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,1,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
-627,1609,4313,4326,"Scale difference is given by information source as 0.999999. Given in this record in ppm to assist application usage. Very similar parameter values (to slightly less precision) used for BD72 to ETRS89: see code 1652.",For applications to an accuracy of 1 metre.,1347,49.5,51.51,2.5,6.4,1,0,9607,-99.059,53.322,-112.486,-0.419,0.83,-1.885,-1,0
-628,1610,4313,4326,,For applications to an accuracy of 5 metres.,1347,49.5,51.51,2.5,6.4,1,0,9603,-125.8,79.9,-100.5,,,,,0
-629,15749,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15748). Scale difference is given by information source as 1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1044,49.5,51.88,2.23,6.4,1,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,1.2747,0
-630,15929,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15928). Scale difference is given by information source as -1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1347,49.5,51.51,2.5,6.4,1,0,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747,1
-631,1673,4314,4326,"Parameter values from DHDN to ETRS89 (1) (code 1309) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by DHDN to WGS 84 (2) (tfm code 1777).",For applications with an accuracy at 5 m level.,2326,47.27,55.09,5.87,13.84,1,0,9607,582,105,414,-1.04,-0.35,3.08,8.3,0
-632,1777,4314,4326,"Parameter values from DHDN to ETRS89 (2) (code 1776) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces DHDN to WGS 84 (1) (tfm code 1673).",For applications with an accuracy at 3 m level,2326,47.27,55.09,5.87,13.84,1,0,9606,598.1,73.7,418.2,0.202,0.045,-2.455,6.7,1
-633,15869,4314,4326,"Parameter values taken from RD/83 to ETRS89 (1) (tfm code 15868) assuming that within the accuracy of the transformation ETRS89 is equivalent to WGS 84 and RD/83 is equivalent to DHDN.",For applications with an accuracy at 2m level,1343,50.2,54.74,9.92,15.04,1,0,9606,612.4,77,440.2,-0.054,0.057,-2.797,2.55,0
-634,1517,4315,4326,,"?",3257,7.19,12.68,-15.13,-7.65,1,0,9603,-23,259,-9,,,,,1
-635,1789,4316,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that","?",1197,43.44,48.27,20.26,31.41,1,1,9603,103.25,-100.4,-307.19,,,,,0
-636,1995,4316,4326,,Oil exploration,3295,43.62,48.27,20.26,29.74,1,0,9603,103.25,-100.4,-307.19,,,,,1
-637,1097,4317,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that Pulkovo 1942 in Romania is equivalent to Dealul Piscului 1970.","Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
-638,1996,4317,4326,,Oil exploration,1197,43.44,48.27,20.26,31.41,1,1,9603,44.107,-116.147,-54.648,,,,,0
-639,1060,4318,4326,,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-3.2,-5.7,2.8,,,,,1
-640,1061,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.45,47.78,48.16,1,0,9603,-20.8,11.3,2.4,,,,,1
-641,1062,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.45,47.78,48.16,1,0,9607,226.702,-193.337,-35.371,2.229,4.391,-9.238,0.9798,0
-642,6910,6881,4326,Derivation not given.,For military purposes. Accuracy not specified.,1340,12.54,19,43.37,53.14,1,0,9603,-24,-203,268,,,,,1
-643,1237,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
-644,1238,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.219,0
-645,6912,6883,4326,Derived at 6 stations.,"For military purposes. Accuracy 5m, 17m and 38m in X, Y and Z axes.",4220,3.14,3.82,8.37,9.02,1,0,9603,-235,-110,393,,,,,1
-646,1240,4324,4326,,Geodesy.,2346,-90,90,-180,180,1,0,9606,0,0,1.9,0,0,0.814,-0.38,1
-647,5521,4646,4326,,For military purposes. Accuracy unknown.,2807,-11.99,-11.31,43.16,43.55,1,0,9603,-963,510,-359,,,,,1
-648,15822,4732,4326,Derived at 10 satellite stations.,"For military and topographic mapping. Accuracy +/-3 m in each axis.",3191,8.66,19.38,162.27,167.82,1,0,9603,102,52,-38,,,,,1
-649,5327,5324,4326,For many purposes ISN2004 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN2004 is equivalent to WGS 84.",1120,59.96,69.59,-30.87,-5.55,1,0,9603,0,0,0,,,,,1
-650,3817,3819,4326,Horizontal coordinates of 66 points of the National Geodetic Network were used to compute this transformation.,GIS and topographic survey.,1119,45.74,48.58,16.11,22.9,1,0,9607,595.48,121.69,515.35,-4.115,2.9383,-0.853,-3.408,1
-651,6914,6892,4326,"Derived by UK DOS at 10 stations in 1998, RMS ±0.314m. Also published by NGA in Standard 0036 v1.0.0 of 2014-07-08 and in GeoTrans v3.4 software with parameter values rounded to integer.",Topographic mapping.,4183,-4.86,-3.66,55.15,56.01,1,0,9603,-43.685,-179.785,-267.721,,,,,1
-652,6926,6892,4326,"Derived by UKHO at 13 stations in 1999, RMS ±0.271m.",Hydrographic survey and charting.,4183,-4.86,-3.66,55.15,56.01,1,0,9606,-76.269,-16.683,68.562,-6.275,10.536,-4.286,-13.686,0
-653,1920,4645,4326,,"Accuracy +/- 1 metre.",1174,-26.45,-14.83,156.25,174.28,1,1,9603,0,0,0,,,,,0
-654,6913,6894,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3250,13.05,13.83,-16.88,-13.79,1,0,9603,-63,176,185,,,,,1
-655,15823,4733,4326,Derived at 2 satellite stations.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3190,19.22,19.38,166.55,166.72,1,0,9603,276,-57,149,,,,,1
-656,3830,3824,4326,"Approximation at the +/- 1m level assuming that TWD97 is equivalent to WGS 84.","Accuracy +/- 1m.",1228,17.36,26.96,114.32,123.61,1,0,9603,0,0,0,,,,,1
-657,7443,7373,4326,"Approximation at the +/- 1m level assuming that ONG14 is equivalent to WGS 84. See transformation code 7377 for authoritative values.",Geodesy.,1183,14.33,26.74,51.99,63.38,1,0,9603,0,0,0,,,,,1
-658,5376,5365,4326,,Accuracy 1m.,1074,2.15,11.77,-90.45,-81.43,1,0,9603,0,0,0,,,,,1
-659,15808,4724,4326,Derived at 2 satellite stations.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3189,-7.49,-7.18,72.3,72.55,1,0,9603,208,-435,-229,,,,,1
-660,5377,5371,4326,,Accuracy 1m.,1186,5,12.51,-84.32,-77.04,1,0,9603,0,0,0,,,,,1
-661,5378,5373,4326,,Accuracy 1m.,1189,-21.05,-0.03,-84.68,-68.67,1,0,9603,0,0,0,,,,,1
-662,15812,4736,4326,,"Scientific mapping. Accuracy +/- 20m in each axis.",3204,-63.08,-62.82,-60.89,-60.35,1,0,9603,260,12,-147,,,,,1
-663,15821,4731,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,1,9603,51,391,-36,,,,,0
-664,15795,4707,4326,Derived at 1 satellite station. Same transformation parameter values related to same datum area given in original 1987 DMA TR8350.2 edition for Sorol Atoll.,For military purposes only. Accuracy 25m in each axis.,3181,23.69,23.93,-166.36,-166.03,1,0,9603,114,-116,-333,,,,,1
-665,5384,5381,4326,,Accuracy 1m.,1247,-37.77,-30.09,-58.49,-50.01,1,0,9603,0,0,0,,,,,1
-666,15813,4722,4326,Determined from 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3529,-54.95,-53.93,-38.08,-35.74,1,0,9603,-794,119,-298,,,,,1
-667,5227,5228,4326,"Parameter values from S-JTSK/05 to ETRS89 (1) (code 5226). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.06,12.09,18.86,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,1
-668,15771,4692,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Maupiti 83 to RGPF (1) (tfm code 15759).","Accuracy +/- 1 metre.",3126,-16.57,-16.34,-152.39,-152.14,1,0,9603,217.037,86.959,23.956,,,,,1
-669,15973,4055,4326,"Executes change of sphere/ellipsoid",Web mapping. Accuracy may be no better than 800 metres.,1262,-90,90,-180,180,1,1,9603,0,0,0,,,,,0
-670,5395,5393,4326,,Accuracy 1m.,1087,9.97,14.44,-91.43,-87.65,1,0,9603,0,0,0,,,,,1
-671,15816,4734,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3184,-40.42,-37,-12.76,-9.8,1,0,9603,-632,438,-609,,,,,1
-672,1585,4227,4326,,"?",1227,32.31,37.3,34.96,42.38,1,1,9603,-177.5,14.1,237.6,,,,,0
-673,1586,4227,4326,"Derived in 1995 by CGG for Al Furat Petroleum Company. Can be approximated using geocentric translations of dX=-174.3m, dY=+14.1m, dZ=+237.6m.",Oil exploration.,2327,35.33,35.9,39.15,40.41,1,0,9606,-175.09,1.218,238.831,-0.047,0.019,0.808,0.1698,0
-674,1587,4227,4326,Derived at four stations by Topnav in 1997.,Oil exploration.,2328,35.79,36.5,40.5,41.39,1,0,9603,-191.77,15.01,235.07,,,,,0
-675,15741,4227,4326,Derived by Elf in 1991 from tfm code 1584 concatenated with a tfm from WGS72BE to WGS84.,Oil exploration. Accuracy 5m.,2329,34.49,35.9,39.3,40.81,1,0,9603,-187.5,14.1,237.6,,,,,0
-676,15742,4227,4326,Derived for 1998 Omar seismic survey and used in 2000 for El Isba seismic survey.,Oil exploration. Accuracy 5m.,3314,32.31,37.3,35.61,42.38,1,0,9603,-190.421,8.532,238.69,,,,,1
-677,15743,4227,4326,"Derived 2005 at 5 triangulation stations and using (EGM96 geoid model +1.15m). Used by Total/DEZPC for Jafra and Mazraa seismic surveys. Can be approximated using geocentric translations of dX=-190.6m, dY=+8.8m, dZ=+239.6m.",Oil exploration. Accuracy 0.5m.,2329,34.49,35.9,39.3,40.81,1,0,9606,-83.58,-397.54,458.78,-17.595,-2.847,4.256,3.225,0
-678,5261,5252,4326,,"Approximation at the +/- 1m level as both TUREF and WGS 84 are realisations of ITRS.",1237,34.42,43.45,25.62,44.83,1,0,9603,0,0,0,,,,,1
-679,1925,4639,4326,,"Accuracy +/- 10 metres.",2815,-13.41,-13.16,-176.25,-176.07,1,1,9603,252,-132,-125,,,,,0
-680,15847,4639,4326,"Replaces information from 2001 (tfm code 1925).","Accuracy +/- 10 metres.",2815,-13.41,-13.16,-176.25,-176.07,1,0,9603,253,-132,-127,,,,,1
-681,15801,4714,4326,Derived at 3 satellite stations.,"Military and topographic mapping; Accuracy +/- 20 m in each axis",3193,-20.31,-17.37,168.09,169.95,1,0,9603,-127,-769,472,,,,,1
-682,15880,4749,4326,,"Accuracy +/- 1 metre.",1174,-26.45,-14.83,156.25,174.28,1,0,9603,0,0,0,,,,,1
-683,15802,4715,4326,No accuracy estimate available.,Military and scientific mapping.,3205,-77.94,-77.17,165.73,167.43,1,0,9603,-104,-129,239,,,,,1
-684,1994,4657,4326,,Low accuracy applications.,3262,63.34,66.59,-24.66,-13.38,1,0,9603,-28,199,5,,,,,1
-685,5351,5340,4326,,Approximation at the sub meter level.,1033,-58.41,-21.78,-73.59,-52.63,1,0,9603,0,0,0,,,,,1
-686,5078,4743,4326,"Parameter values from Karbala 1979 to IGRS (1) (tfm code 5077) assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation. Replaces Karbala 1979 to WGS 84 (1) (tfm code 15872).",Accuracy 1m.,3625,29.06,37.39,38.79,48.61,1,0,9603,70.995,-335.916,262.898,,,,,1
-687,15872,4743,4326,"Derived from shifts in UTM rectangular coordinates for one point in Basra area provided by Iraq National Oil Exploration Company. Replaced by Karbala 1979 to WGS 84 (2) (tfm code 5078).",Oil exploration.,3397,29.87,31.09,46.46,48.61,1,0,9603,84.1,-320.1,218.7,,,,,0
-688,1951,4658,4326,"Derived at 6 stations. Replaced by Hjorsey 1955 to WGS 84 (2) (code 6909).","Accuracy 3m, 3m and 5m in X, Y and Z axes.",3262,63.34,66.59,-24.66,-13.38,1,0,9603,-73,46,-86,,,,,0
-689,6909,4658,4326,"Derived at 16 stations. Replaces Hjorsey 1955 to WGS 84 (1) (code 1951).","Accuracy 3m, 3m and 6m in X, Y and Z axes.",3262,63.34,66.59,-24.66,-13.38,1,0,9603,-73,47,-83,,,,,1
-690,6373,6365,4326,,Accuracy 1m.,1160,12.1,32.72,-122.19,-84.64,1,0,9603,0,0,0,,,,,1
-691,3894,3889,4326,"Approximation at the +/- 1m level assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1124,29.06,37.39,38.79,48.75,1,0,9603,0,0,0,,,,,1
-692,1952,4659,4326,For many purposes ISN93 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN93 is equivalent to WGS 84.",1120,59.96,69.59,-30.87,-5.55,1,0,9603,0,0,0,,,,,1
-693,1957,4660,4326,Derived at 3 stations. Residuals under 1m.,For applications to an accuracy of 1 metre.,2869,70.75,71.24,-9.17,-7.87,1,0,9606,982.6087,552.753,-540.873,6.6816266,-31.6114924,-19.84816,16.805,1
-694,1958,4661,4326,,LKS92 is a realisation of ETRS89 coincident to WGS84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1139,55.67,58.09,19.06,28.24,1,0,9603,0,0,0,,,,,1
-695,15849,4213,4326,"Used by Elf / CGG between December 1991 and March 1992. Probably derived from results of concatenated tfm Beduaram to WGS 84 (1) (code 8634).",Oil exploration.,2771,12.8,16.7,7.81,14.9,1,0,9603,-106,-87,188,,,,,1
-696,15803,4716,4326,Derived at 4 satellite stations.,"Military and topographic mapping. Accuracy +/- 15 m in each axis.",3196,-4.76,-2.68,-174.6,-170.66,1,0,9603,298,-304,-375,,,,,1
-697,3915,3906,4326,"Parameter values from MGI 1901 to ETRS89 (3) (code 3914). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,0,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
-698,3917,3906,4326,"Parameter values from MGI 1901 to Slovenia 1996 (1) (code 3916). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,0,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
-699,3962,3906,4326,Accuracy estimate not available from information source but established empirically by OGP.,For military purposes only.,2370,40.85,46.88,13.38,23.04,1,0,9603,682,-203,480,,,,,1
-700,3964,3906,4326,"Parameter values from MGI 1901 to ETRS89 (2) (code 3963). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3234,42.34,46.54,13.43,19.43,1,0,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
-701,3965,3906,4326,,Oil industry,3536,41.79,43.56,18.45,20.38,1,0,9603,695.5,-216.6,491.1,,,,,0
-702,6206,3906,4326,Derived at 13 stations.,"1m accuracy. Residuals generally less than +/- 1m horizontally and vertically.",1148,40.85,42.36,20.45,23.04,1,0,9607,521.748,229.489,590.921,-4.029,-4.488,15.521,-9.78,0
-703,15879,4747,4326,"Approximation at the +/- 1m level assuming that GR96 is equivalent to WGS 84 within the accuracy of the transformation.","For applications with an accuracy of +/- 1m.",1107,56.38,87.03,-75,8.12,1,0,9603,0,0,0,,,,,1
-704,1962,4662,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15903.,"Accuracy +/- 10 metres.",2822,-22.45,-20.03,163.92,167.09,1,0,9603,-13,-348,292,,,,,0
-705,1963,4662,4326,Withdrawn by information source and replaced by improved information - see tfm code 15903.,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.03,163.92,167.09,1,0,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
-706,15903,4662,4326,"Parameter values taken from IGN72 Grande Terre to RGNC91-93 (1) ( code 15882) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy +/- 2 metres.",2822,-22.45,-20.03,163.92,167.09,1,0,9603,-11.64,-348.6,291.98,,,,,1
-707,15878,4748,4326,"Parameter values taken from Viti Levu 1912 to WGS 84 (1) (tfm code 15897). Approximation at the +/- 50m level assuming that CRS 4748 is equivalent to CRS 4752 within the transformation accuracy. Source CRSs 4748 and 4752 are independent but connected.","For applications with an accuracy of +/-50m.",3401,-17.07,-16.1,178.42,-179.77,1,0,9603,51,391,-36,,,,,1
-708,1966,4663,4326,Derived at Forte de Sao Tiago.,For low resolution applications.,2870,32.58,33.15,-17.31,-16.23,1,0,9603,-502.862,-247.438,312.724,,,,,1
-709,1967,4663,4326,,For medium resolution applications.,2870,32.58,33.15,-17.31,-16.23,1,0,9607,-210.502,-66.902,-48.476,-2.094,15.067,5.817,0.485,0
-710,6911,6882,4326,Derivation not given.,For military purposes. Accuracy not specified.,3269,33.06,34.65,35.04,36.63,1,0,9603,-183,-15,273,,,,,1
-711,15805,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3198,-8.86,-7.52,156.44,158.2,1,0,9603,230,-199,-752,,,,,1
-712,15807,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3197,-9.98,-9.2,159.55,160.88,1,0,9603,252,-209,-751,,,,,0
-713,1968,4664,4326,Calculated in 2001.,For low resolution applications.,2871,37.65,37.96,-25.92,-25.08,1,0,9603,-204.633,140.216,55.199,,,,,0
-714,1969,4664,4326,Calculated in 2001.,For medium resolution applications.,2871,37.65,37.96,-25.92,-25.08,1,0,9607,-211.939,137.626,58.3,0.089,-0.251,-0.079,0.384,0
-715,1970,4664,4326,Mean for all islands in group.,For low resolution applications.,1345,36.87,37.96,-25.92,-24.62,1,0,9603,-204.619,140.176,55.226,,,,,1
-716,1971,4664,4326,Mean for all islands in group.,For medium resolution applications.,1345,36.87,37.96,-25.92,-24.62,1,0,9607,-208.719,129.685,52.092,0.195,0.014,-0.327,0.198,0
-717,15881,4750,4326,"Parameter values taken from ST87 Ouvea to RGNC91-93 (1) ( code 15885) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.44,166.71,1,0,9603,-56.263,16.136,-22.856,,,,,1
-718,1972,4665,4326,,For low resolution applications.,2872,38.57,38.86,-27.44,-26.97,1,0,9603,-106.301,166.27,-37.916,,,,,0
-719,1973,4665,4326,,For medium resolution applications.,2872,38.57,38.86,-27.44,-26.97,1,0,9607,-105.854,165.589,-38.312,0.003,0.026,-0.024,-0.048,0
-720,1974,4665,4326,,For low resolution applications.,2873,38.46,38.7,-28.9,-28.54,1,0,9603,-106.248,166.244,-37.845,,,,,0
-721,1975,4665,4326,,For medium resolution applications.,2873,38.46,38.7,-28.9,-28.54,1,0,9607,-104,162.924,-38.882,0.075,0.071,-0.051,-0.338,0
-722,1976,4665,4326,,For low resolution applications.,2874,38.32,38.61,-28.61,-27.98,1,0,9603,-106.044,166.655,-37.876,,,,,0
-723,1977,4665,4326,,For medium resolution applications.,2874,38.32,38.61,-28.61,-27.98,1,0,9607,-95.323,166.098,-69.942,0.215,1.031,-0.047,1.922,0
-724,1978,4665,4326,,For low resolution applications.,2875,38.48,38.8,-28.37,-27.71,1,0,9603,-106.253,166.239,-37.854,,,,,0
-725,1979,4665,4326,,For medium resolution applications.,2875,38.48,38.8,-28.37,-27.71,1,0,9607,-100.306,161.246,-48.761,0.192,0.385,-0.076,0.131,0
-726,1980,4665,4326,Mean for all islands in group.,For low resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-106.226,166.366,-37.893,,,,,1
-727,1981,4665,4326,Mean for all islands in group.,For medium resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9607,-103.088,162.481,-28.276,-0.167,-0.082,-0.168,-1.504,0
-728,1986,4666,4326,May be taken as a transformation from Lisbon 1890 to ETRS89 - see tfm code 5039.,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,508.088,-191.042,565.223,,,,,1
-729,1990,4666,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,631.392,-66.551,481.442,-1.09,4.445,4.487,-4.43,0
-730,15804,4717,4326,Derived at 19 satellite stations.,"US space and military operations. Accuracy +/- 3 m in each axis.",3206,20.86,30.83,-82.33,-72.68,1,0,9603,-2,151,181,,,,,1
-731,5267,5264,4326,DRUKREF 03 and WGS 84 are both realisations of ITRS.,For applications to an accuracy of 1 metre.,1048,26.7,28.33,88.75,92.12,1,0,9603,0,0,0,,,,,1
-732,1993,4667,4326,For all practical purposes this transformation is exact.,Boundary demarcation.,2876,29.06,30.32,46.36,48.61,1,0,9603,0,0,0,,,,,1
-733,6895,4752,4326,"Derived at 9 stations. Replaces Viti Levu 1912 to WGS 84 (1) (code 15897).","For military and topographic mapping. Accuracy +/-3m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,0,9603,98,390,-22,,,,,1
-734,15897,4752,4326,"Derived at 1 satellite station. Replaced by Viti Levu 1912 to WGS 84 (2) (code 6895).","For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,0,9603,51,391,-36,,,,,0
-735,5470,5451,4326,"Parameter values taken from Ocotepeque to CR05 (1) (tfm code 6890) assuming that CR05 is equivalent to WGS 84 within the accuracy of the transformation.",Topographic mapping.,3232,7.98,11.22,-85.97,-82.53,1,0,9603,213.11,9.37,-74.95,,,,,0
-736,5473,5451,4326,"Rotations in original source given in radians are equivalent to Rx = 2.35"", Ry = -0.06"", Rz = 6.39"".",Topographic mapping.,3232,7.98,11.22,-85.97,-82.53,1,1,9607,213.116,9.358,-74.946,2.351,-0.06147,6.39,-5.22,0
-737,5474,5451,4326,,Topographic mapping.,3876,7.98,17.83,-92.29,-82.53,1,1,9603,205.435,-29.099,292.202,,,,,0
-738,6891,5451,4326,"Concatenation (via NAD27) of transformations 6888 and 1171. Accuracy not given, but accuracy of constituent transformations given as 9m and 10m respectively.",For military purposes.,3876,7.98,17.83,-92.29,-82.53,1,0,9603,205,96,-98,,,,,1
-739,15752,4668,4326,Derived at 22 stations.,For military purposes. Accuracy 3m in each axis.,1297,34.88,71.21,-10.56,31.59,1,0,9603,-86,-98,-119,,,,,1
-740,15810,4735,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3192,5.21,5.43,162.85,163.1,1,0,9603,647,1777,-1124,,,,,1
-741,6701,5246,4326,"Approximation at the +/- 1m level assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1055,4.01,6.31,112.37,115.37,1,0,9603,0,0,0,,,,,1
-742,4477,4463,4326,"Approximation at the +/- 1m level assuming that RGSPM06 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1220,43.41,47.37,-57.1,-55.9,1,0,9603,0,0,0,,,,,1
-743,5501,5489,4326,"Approximation at the +/- 1m level assuming that RGAF09 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,0,9603,0,0,0,,,,,1
-744,15912,4755,4326,"Approximation at the +/- 1m level assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1 metre.,1122,-13.25,7.79,92.01,141.46,1,0,9603,0,0,0,,,,,1
-745,1555,4158,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-0.465,372.095,171.736,,,,,1
-746,1556,4158,4326,Described by NIMA as Naparima to WGS 84. In Trinidad the source CRS is better known as Naparima 1955. EPSG has duplicated the tfm using the alternative source CRSs. See also tfm code 1307.,For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-2,374,172,,,,,0
-747,4476,4470,4326,"Approximation at the +/- 1m level assuming that RGM04 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1159,-14.49,-11.33,43.68,46.7,1,0,9603,0,0,0,,,,,1
-748,5194,4756,4326,Used by Total in Mekong delta.,Academic research not officially adopted.,3770,9.34,11.03,104.25,107.11,1,0,9607,-192.873,-39.382,-111.202,0.00205,0.0005,-0.00335,0.0188,0
-749,6960,4756,4326,,Academic research not officially adopted.,3328,8.5,23.33,102.14,109.52,1,0,9607,-191.90441429,-39.30318279,-111.45032835,-0.00928836,0.01975479,-0.00427372,0.252906278,1
-750,1931,4643,4326,,"Accuracy better than +/- 1 metre.",2821,-19.85,-19.5,163.54,163.75,1,0,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002,1
-751,4290,4475,4326,"Parameter values taken from Cadastre 1997 to RGM04 (1) (transformation code 4478) assuming that RGM04 is coincident with WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",3340,-13.05,-12.61,44.98,45.35,1,0,9603,-381.788,-57.501,-256.673,,,,,1
-752,5374,5354,4326,,Accuracy 1m.,1049,-22.91,-9.67,-69.66,-57.52,1,0,9603,0,0,0,,,,,1
-753,15787,4701,4326,Derived by Topnav in 1991 at station TSH 85.,Oil exploration. Accuracy 5m.,3171,-6.04,-4.28,12.17,16.28,1,0,9603,-79.9,-158,-168.9,,,,,1
-754,4832,4483,4326,,Accuracy 1m.,1160,12.1,32.72,-122.19,-84.64,1,0,9603,0,0,0,,,,,1
-755,1917,4633,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15902.,"Accuracy +/- 10 metres.",2814,-21.24,-20.62,166.98,167.52,1,0,9603,336,223,-231,,,,,0
-756,1927,4633,4326,Withdrawn by information source and replaced by improved information - see tfm code 15902.,"Accuracy better than +/- 1 metre.",2814,-21.24,-20.62,166.98,167.52,1,0,9606,137.092,131.66,91.475,-1.9436,-11.5993,-4.3321,-7.4824,0
-757,15902,4633,4326,"Parameter values taken from IGN56 Lifou to RGNC91-93 (1) ( code 15883) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2814,-21.24,-20.62,166.98,167.52,1,0,9603,335.47,222.58,-230.94,,,,,1
-758,15925,4758,4326,,For all practical purposes JAD2001 can be considered to be coincident with WGS 84.,1128,14.08,19.36,-80.6,-74.51,1,0,9603,0,0,0,,,,,1
-759,6711,6706,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. RDN2008 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1127,34.76,47.1,5.93,18.99,1,0,9603,0,0,0,,,,,1
-760,15845,4161,4326,Transformation parameter precision given to millimetres in information source but due to accuracy rounded to nearest decimetre for EPSG database.,Geodetic surveying within the oil industry. Accuracy 25 m.,1265,-46.7,-45.19,-69.5,-67.1,1,0,9603,27.5,14,186.4,,,,,1
-761,15931,4759,4326,"Approximation at the +/- 1m level assuming that NAD83(NSRS2007) is equivalent to WGS 84 within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1511,14.92,74.71,167.65,-63.88,1,0,9603,0,0,0,,,,,1
-762,1540,4163,4326,,Accuracy better than 1 metre.,1257,8.95,19,41.08,57.96,1,0,9603,0,0,0,,,,,1
-763,4905,5013,4326,,PTRA08 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,3670,29.24,43.07,-35.58,-12.48,1,0,9603,0,0,0,,,,,1
-764,6195,5527,4326,"Parameter values from SAD69(96) to SIRGAS 2000 (2)) (tfm code 5881) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation, based on SAD69 to SIRGAS 2000 (1)) (tfm code 15485). Used by Petrobras and ANP from 1994.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).", [...]
-765,15806,4719,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis",3188,-27.25,-27.01,-109.51,-109.16,1,0,9603,211,147,111,,,,,1
-766,15860,4702,4326,Mauritania 1999 can be considered to be the same as WGS 84 within the accuracy of this transformation.,Minerals management. Accuracy 1m.,1157,14.72,27.3,-20.04,-4.8,1,0,9603,0,0,0,,,,,1
-767,15971,4762,4326,"Approximation at the +/- 1m level assuming that BDA2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1047,28.91,35.73,-68.83,-60.7,1,0,9603,0,0,0,,,,,1
-768,5375,5360,4326,,Accuracy 1m.,1066,-59.87,-17.5,-113.21,-65.72,1,0,9603,0,0,0,,,,,1
-769,15972,4763,4326,"Approximation at the +/- 1m level assuming that Pitcairn 2006 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3208,-25.14,-25,-130.16,-130.01,1,0,9603,0,0,0,,,,,1
-770,1558,4166,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,3266,33.14,38.64,124.53,131.01,1,0,9603,0,0,0,,,,,1
-771,4084,4081,4326,"Approximation at the +/- 1m level assuming that REGCAN95 is equivalent to WGS 84.","Accuracy +/- 1m.",3199,24.6,32.76,-21.93,-11.75,1,0,9603,0,0,0,,,,,1
-772,15974,4764,4326,"Approximation at the +/- 1m level assuming that RSRGD2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3558,-90,-59.99,144.99,-144.99,1,0,9603,0,0,0,,,,,1
-773,5553,5546,4326,"Exact in 1994 but due to significant and variable tectonic activity in PNG, in 2011 PNG94 and WGS 84 differ generally by 2m but in areas of significant tectonic activity differences can exceed 9m.",Approximation at the 2-10m level.,1187,-14.75,2.58,139.2,162.81,1,0,9603,0,0,0,,,,,1
-774,15870,4679,4326,Derived at 5 points in 2002.,Hydrographic survey,2967,19.37,21.34,-17.08,-15.88,1,0,9603,-80.01,253.26,291.19,,,,,1
-775,15976,4765,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1212,45.42,46.88,13.38,16.61,1,0,9603,0,0,0,,,,,1
-776,15820,4730,4326,Derived at 1 satellite station.,For military and topographic mapping. Accuracy 25m in each axis.,3194,-17.32,-14.57,166.47,168.71,1,0,9603,170,42,84,,,,,1
-777,15709,4680,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.89,18.25,-16.11,-15.83,1,0,9603,124.5,-63.5,-281,,,,,1
-778,15908,4754,4326,Derived at 5 stations throughout Libya used to define LGD2006 in May 2006.,For applications to an accuracy of 0.1 metre.,1143,19.5,35.23,9.31,26.21,1,0,9603,-208.4058,-109.8777,-2.5764,,,,,1
-779,5585,4023,4326,"Parameter values from MOLDREF99 to ETRS89 (1) (code 5584). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications with an accuracy of 1m.,1162,45.44,48.47,26.63,30.13,1,0,9603,0,0,0,,,,,1
-780,15831,4737,4326,"Approximation at the +/- 1m level assuming that ITRF2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1135,28.6,40.27,122.71,134.28,1,0,9603,0,0,0,,,,,1
-781,5590,5561,4326,"Derived through concatenation of UCS-2000 to S-42 (1) (tfm code 5586 reversed) [an approximation] and S-42 to WGS 84 (16) (tfm code 15865) [derived for whole FSU rather than Ukraine]. Replaced by UCS-2000 to WGS 84 (2) (tfm code 5840).",Accuracy 5 metres.,1242,43.18,52.38,22.15,40.18,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,1
-782,5823,5561,4326,"Parameter values taken from Ukraine 2000 to ITRF2005 (1) (code 5822) assuming that ITRS2005 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level assuming that ITRS2005 is equivalent to WGS 84.",1242,43.18,52.38,22.15,40.18,1,1,9603,24,-121,-76,,,,,0
-783,5840,5561,4326,"Parameter values taken from UCS-2000 to ITRF2005 (1) (code 5822) assuming that WGS 84 is equivalent to ITRS2005 within the accuracy of the transformation. Replaces UCS-2000 to WGS 84 (1) (tfm code 5590).","Approximation at the +/- 1m level assuming that WGS 84 is equivalent to ITRS2005.",1242,43.18,52.38,22.15,40.18,1,0,9603,24,-121,-76,,,,,0
-784,15700,4682,4326,Derived at origin station in Dhaka.,Oil exploration.,1041,18.56,26.63,88.04,92.67,1,1,9603,283.8,735.9,261.1,,,,,0
-785,15779,4682,4326,Derived at origin station in Dhaka. Source information given to 3 decimal places but rounded by OGP to be commensurate with stated accuracy.,Oil exploration.,1041,18.56,26.63,88.04,92.67,1,0,9603,283.7,735.9,261.1,,,,,1
-786,1919,4635,4326,,"Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.44,166.71,1,1,9606,-122.383,-188.696,103.344,3.5107,-4.9668,-5.7047,4.4798,0
-787,15708,4683,4326,Derived during GPS campaign which established PRS92 coordinates at 330 first order stations.,"Accuracy: 1-10 parts per million.",1190,3,22.18,116.04,129.95,1,0,9607,-127.62,-67.24,-47.04,3.068,-4.903,-1.578,-1.06,1
-788,1837,4257,4326,,Oil exploration.,1316,-6.54,-1.88,118.71,120.78,1,0,9603,-587.8,519.75,145.76,,,,,1
-789,15713,4684,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3274,-0.69,7.08,72.81,73.69,1,0,9603,-133,-321,50,,,,,1
-790,6177,6135,4326,"Approximation at the +/- 1m level assuming that CIGD11 is equivalent to WGS 84.","Accuracy +/- 1m.",1063,17.58,20.68,-83.6,-78.72,1,0,9603,0,0,0,,,,,1
-791,4064,4046,4326,"Approximation at the +/- 1m level assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,3613,-13.46,-3.41,11.79,29.81,1,0,9603,0,0,0,,,,,1
-792,15918,4214,4326,Provided by BGP to TOTAL in June 2006.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,12.646,-155.176,-80.863,,,,,0
-793,15919,4214,4326,Derived via WGS 72BE. Original transformation derived in 1979 at 4 stations on Yellow Sea coast.,Geophysical exploration in Yellow Sea.,3469,31.23,37.4,119.23,125.06,1,0,9606,15.53,-113.82,-41.38,0,0,0.814,-0.38,0
-794,15920,4214,4326,"Derived via WGS 72BE. Original transformation derived by GSI in 1980-81. The GSI memo incorrectly gave the parameters as from WGS 72 to Beijing 1954, but it has been determined by the OGP that the memo should have stated from Beijing 1954 to WGS 72BE.",Geophysical exploration in South China Sea.,3470,18.31,22.89,110.13,116.76,1,0,9606,31.4,-144.3,-74.8,0,0,0.814,-0.38,0
-795,15921,4214,4326,Provided by BGP to ELF in 1994.,Geophysical exploration in Tarim basin. Accuracy stated as 1m within basin.,3507,37,41.99,77.45,88,1,0,9603,15.8,-154.4,-82.3,,,,,1
-796,15935,4214,4326,Concatenated via WGS 72BE. Recomputation by Shelltech in 1981 of SSB 1980 observation.,Geophysical exploration in Bei Bu basin. Accuracy stated as 1m within basin.,3561,17.81,21.69,107.15,110.17,1,0,9606,18,-136.8,-73.7,0,0,0.814,-0.38,0
-797,15936,4214,4326,Provided by Sinopec to TOTAL in January 2007.,Geophysical exploration in Ordos basin. Accuracy stated as 1m within basin.,3466,35,39,107,110.01,1,0,9603,11.911,-154.833,-80.079,,,,,0
-798,15875,4721,4326,Derived at 20 stations. Also published by NGA in GeoTrans v3.4 software with parameter values rounded to integer.,"For military purposes. Accuracy 5m, 3m and 2m in X, Y and Z axes.",3398,-19.22,-16.1,176.81,-179.77,1,0,9603,265.025,384.929,-194.046,,,,,1
-799,7445,6311,4326,"Parameter values from CGRS93 to ETRS89 (1) (code 7444). Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",Small scale hydrographic and aviation  mapping.,3236,34.59,35.74,32.2,34.65,1,0,9606,8.846,-4.394,-1.122,0.00237,0.146528,-0.130428,0.783926,1
-800,5599,5593,4326,,Approximation at the 1m level.,3889,54.33,54.83,10.66,12.01,1,0,9603,0,0,0,,,,,1
-801,15832,4687,4326,"Transformation is to original definition of WGS 84. It is consistent with later WGS 84 realisations G730, G873 and G1150 to no better than 1m.","Accuracy +/- 0.5 metre (to original definition of WGS 84 - see remarks).",1098,-31.24,-4.52,-158.13,-131.97,1,0,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093,1
-802,15833,4687,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84.","Accuracy +/- 1 metre.",1098,-31.24,-4.52,-158.13,-131.97,1,0,9603,0,0,0,,,,,0
-803,1921,4636,4326,,"Accuracy +/- 10 metres.",2817,-66.78,-66.1,139.44,141.5,1,0,9603,365,194,166,,,,,1
-804,15772,4688,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Fatu Iva 72 to RGPF (1) (tfm code 15760).","Accuracy +/- 2 metres.",3133,-10.6,-10.36,-138.75,-138.54,1,0,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074,1
-805,5236,5233,4326,Derived at 58 stations.,Accuracy 14m.,3310,5.86,9.88,79.64,81.95,1,0,9607,-0.293,766.95,87.713,-0.195704,-1.695068,-3.473016,-0.039338,1
-806,4077,4075,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. SREF98 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",3534,41.85,46.19,18.81,23.01,1,0,9603,0,0,0,,,,,1
-807,4835,4690,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahiti 79 to RGPF (1) (tfm code 15756).","Accuracy +/- 1 metre.",3124,-17.93,-17.44,-149.7,-149.09,1,0,9607,221.525,152.948,176.768,2.3847,1.3896,0.877,11.4741,1
-808,1922,4637,4326,,"Accuracy +/- 10 metres.",2818,-67.13,-65.61,136,142,1,0,9603,325,154,172,,,,,1
-809,15797,4712,4326,Derived at 2 satellite stations.,For military purposes only. Accuracy 25m in each axis.,3182,-8.03,-7.83,-14.46,-14.24,1,0,9603,-205,107,53,,,,,1
-810,15769,4691,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Moorea 87 to RGPF (1) (tfm code 15757).","Accuracy +/- 1 metre.",3125,-17.63,-17.41,-150,-149.73,1,0,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773,1
-811,6142,4723,4326,"Parameter values are taken from GCGD59 to CIGD11 (1) (code 6136) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3185,19.21,19.41,-81.46,-81.04,1,0,9607,-179.483,-69.379,-27.584,7.862,-8.163,-6.042,-13.925,1
-812,15830,4723,4326,Determined from 6 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3185,19.21,19.41,-81.46,-81.04,1,0,9603,67.8,106.1,138.8,,,,,0
-813,4066,4695,4326,"Parameter values taken from Katanga 1955 to RGRDC 2005 (1) (code 4065) assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1.5m.,3614,-12.01,-11.13,26.38,27.75,1,0,9603,-103.746,-9.614,-255.95,,,,,1
-814,15746,4693,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11 and Pars LNG plants.,Petroleum Exploration and Production.,3141,27.63,27.81,52.09,52.26,1,0,9603,0,-0.15,0.68,,,,,1
-815,1441,4601,4326,,"?",1273,16.94,17.22,-61.95,-61.61,1,0,9603,-255,-15,71,,,,,1
-816,15811,4601,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",1273,16.94,17.22,-61.95,-61.61,1,0,9603,-270,13,62,,,,,0
-817,1442,4602,4326,,"?",3239,15.14,15.69,-61.55,-61.2,1,0,9603,725,685,536,,,,,1
-818,1443,4603,4326,,"?",3118,11.94,12.29,-61.84,-61.54,1,0,9603,72,213.7,93,,,,,1
-819,1444,4604,4326,Derived at 1 satellite station.,Accuracy 25m in each axis.,3279,16.62,16.87,-62.29,-62.08,1,0,9603,174,359,365,,,,,1
-820,1445,4605,4326,,"?",3297,17.06,17.46,-62.92,-62.5,1,0,9603,9,183,236,,,,,1
-821,15750,4605,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m in each of X, Y and Z axes.",3297,17.06,17.46,-62.92,-62.5,1,0,9603,-7,215,225,,,,,0
-822,1446,4606,4326,,"?",3298,13.66,14.16,-61.13,-60.82,1,0,9603,-149,128,296,,,,,1
-823,6897,4606,4326,Derived at 3 stations.,For military purposes only. Accuracy 1m in each axis.,3298,13.66,14.16,-61.13,-60.82,1,0,9603,-153,153,307,,,,,0
-824,1959,4607,4326,Derived at 4 points.,1m accuracy.,3300,12.54,13.44,-61.52,-61.07,1,0,9603,195.671,332.517,274.607,,,,,1
+581,1271,4293,4326,"Beware!  Source CRS uses GLM, tfm param in m. Example: Schwarzeck ?=19°35'46.952""S ?=20°41'50.649""E h=1185.99m; X=5623409.386 Y=2124618.003 Z=-2125847.632 GLM; X=5623485.84m Y=2124646.89m Z=-2125876.54m; WGS 84 X=5624101.48m Y=2124748.97m Z=-2126132.35m.","?",1169,-30.64,-16.95,8.24,25.27,1,0,9603,615.64,102.08,-255.81,,,,,0
+582,1286,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.24,4.37,108.79,119.06,1,1,9603,-403,684,41,,,,,0
+583,1834,4294,4326,Accuracy estimate not available.,For military purposes.,2354,-4.24,4.37,108.79,119.06,1,1,9603,-403,684,41,,,,,0
+584,1835,4294,4326,,Oil exploration.,1360,-4.24,4.29,114.55,119.06,1,1,9603,-387.06,636.53,46.29,,,,,0
+585,1836,4294,4326,,Oil exploration.,2770,-0.07,4.29,116.96,119.06,1,1,9603,-403.4,681.12,46.56,,,,,0
+586,6900,4129,4326,Derived at 3 stations.,For military purposes. Accuracy 10m in each axis.,1329,-26.87,-19.84,31.29,35.65,1,0,9603,-132,-110,-335,,,,,1
+587,1227,4297,4326,Accuracy estimate not available.,For military purposes.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-189,-242,-91,,,,,1
+588,6873,4297,4326,Derived at 9 points throughout Madagascar. Adopted by OMV.,For applications with an accuracy of 3m.,1149,-26.59,-11.69,42.53,51.03,1,0,9603,-198.383,-240.517,-107.909,,,,,0
+589,1228,4298,4326,Derived at 8 stations.,"For military purposes. Accuracy 10m, 10m and 12m in X, Y and Z axes.",1362,0.85,7.67,109.31,119.61,1,0,9603,-679,669,-48,,,,,1
+590,1592,4298,4326,"Originally used by BSP offshore only, use extended to onshore in 2010.",Oil exploration and production.,1055,4.01,6.31,112.37,115.37,1,0,9603,-678,670,-48,,,,,0
+591,1615,4298,4326,"CARE! Erroneous GPS data was used in the derivation of these parameters. They produce a coordinate difference of 10m horizontally and 50m vertically compared to Timbalai 1948 to WGS 84 (2) (code 1592).",Topographic and engineering survey onshore.,2349,4.01,5.11,114.09,115.37,1,0,9603,-726.282,703.611,-48.999,,,,,0
+592,1852,4298,4326,"Derived by Racal Survey for SSB at 24 coastal stations (including Timbalai fundamental point and 6 other primary triangulation stations) between in Sabah (Kudat southwards) and Sarawak (Sibu northwards).",Oil exploration.,2780,1.56,7.67,109.31,117.31,1,0,9606,-533.4,669.2,-52.5,0,0,4.28,9.4,0
+593,5248,4298,4326,,Oil exploration.,1055,4.01,6.31,112.37,115.37,1,1,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
+594,5249,4298,4326,"Parameter values taken from Timbalai 1948 to GDBD2009 (1) (code 5878) assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Oil exploration.,1055,4.01,6.31,112.37,115.37,1,0,9607,-689.5937,623.84046,-65.93566,0.02331,-1.17094,0.80054,5.88536,0
+595,6902,4298,4326,Derived at 9 stations.,"For military purposes. Accuracy 1m, 6m and 2m in X, Y and Z axes.",2349,4.01,5.11,114.09,115.37,1,0,9603,-679,667,-49,,,,,0
+596,1229,4299,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1305,51.39,55.43,-10.56,-5.34,1,1,9603,506,-122,611,,,,,0
+597,1641,4299,4326,"Parameter values from TM75 to ETRS89 (2) (code 1953). Assumes each pair of (i) TM65 and TM75, and (ii) ETRS89 and WGS 84, can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.39,55.43,-10.56,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+598,1954,4300,4326,"Parameter values taken from TM65 to ETRS89 (2) (code 1953). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1305,51.39,55.43,-10.56,-5.34,1,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15,1
+599,1956,4300,4326,"Derived at 7 stations. TM75 is based on the geodetic datum of 1965 which should not be confused with the mapping adjustment of 1965 (TM65).",For military purposes only. Accuracy 3m in each axis.,1305,51.39,55.43,-10.56,-5.34,1,0,9603,506,-122,611,,,,,0
+600,1230,4301,4326,Derived at 31 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2409,20.37,45.54,122.83,145.87,1,0,9603,-148,507,685,,,,,0
+601,1231,4301,4326,Derived at 16 stations.,"For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3995,30.18,45.54,128.31,145.87,1,0,9603,-148,507,685,,,,,0
+602,1232,4301,4326,"Derived at 29 stations. Replaced by Tokyo to WGS 84 (5) (code 1305).","For military purposes only. Accuracy 8m, 5m and 8m in X, Y and Z axes.",3266,33.14,38.64,124.53,131.01,1,0,9603,-146,507,687,,,,,0
+603,1233,4301,4326,Derived at 3 stations.,"For military purposes only. Accuracy 20m, 5m and 20m in X, Y and Z axes.",2408,23.98,26.91,122.83,131.38,1,0,9603,-158,507,676,,,,,0
+604,1305,4301,4326,"Derived at 29 stations. Replaces Tokyo to WGS 84 (3) (code 1232).",For military purposes. Accuracy 2m in each axis.,3266,33.14,38.64,124.53,131.01,1,0,9603,-147,506,687,,,,,0
+605,15484,4301,4326,"Parameter values from Tokyo to JGD2000 (1) (code 15483). Assumes JGD2000 and WGS 84 can be considered the same to within the accuracy of the transformation.","Surveying, mapping and civil engineering purposes. Accuracy on main islands 9m.",3957,20.37,45.54,122.83,154.05,1,0,9603,-146.414,507.337,680.507,,,,,1
+606,1296,4302,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,1339,9.83,11.51,-62.09,-60,1,0,9603,-61.702,284.488,472.052,,,,,1
+607,10085,4302,4326,"Parameter values provided to EOG by Trinidad Ministry of Energy and Energy Industries. Used by EOG offshore Trinidad (including Pelican, Kiskadee and Ibis fields) since 1996.",Oil exploration.,1339,9.83,11.51,-62.09,-60,1,0,9603,-61,285.2,471.6,,,,,0
+608,1932,4644,4326,,"Accuracy better than +/- 1 metre.",2823,-22.37,-22.19,166.35,166.54,1,1,9606,-166.207,-154.777,254.831,-37.5444,7.7011,-10.2025,-30.8598,0
+609,15904,4644,4326,"Parameter values taken from NEA74 Noumea to RGNC91-93 (1) ( code 15886) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2823,-22.37,-22.19,166.35,166.54,1,0,9603,-10.18,-350.43,291.37,,,,,1
+610,1294,4304,4326,Accuracy estimate not available.,For military purposes.,1365,31.99,37.14,-2.95,9.09,1,0,9603,-73,-247,227,,,,,1
+611,15815,4728,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3873,27.58,29.3,-18.22,-13.37,1,0,9603,-307,-92,127,,,,,1
+612,1253,4307,4326,Derived at 3 stations.,For military purposes only. Accuracy 25m in each axis.,3213,18.97,37.14,-8.67,11.99,1,0,9603,-186,-93,310,,,,,0
+613,1255,4307,4326,"CAUTION: Source CRS described by DMA as from Voirol 1960. OGP believes that the data used in the derivation of these parameters contains a blunder. We recommend using transformation North Sahara 1959 to WGS84 (1) (code 1253). Derived at 2 stations.",For military purposes only. Accuracy 25m in each axis.,1365,31.99,37.14,-2.95,9.09,1,0,9603,-123,-206,219,,,,,0
+614,1815,4307,4326,Used by BP in District 3 and In Salah Gas.,Oil industry operations.,2598,25,32,1,3.3,1,0,9606,-152.9,43.8,358.3,2.714,1.386,-2.788,-6.743,0
+615,1816,4307,4326,"Derived at astro station central to concession. Significant and varying differences (>100m) at 4 neighbouring astro stations.",Oil industry operations.,2599,27.5,28.3,8.83,9.92,1,0,9603,-95.7,10.2,158.9,,,,,0
+616,1817,4307,4326,Derived at astro station Guerrara.,Oil industry operations.,2600,31.75,32.42,7.16,8,1,0,9603,-165.914,-70.607,305.009,,,,,0
+617,5630,4307,4326,"Derived at 1 station (L38).",Used by Total in Ahnet licence area.,3917,26.06,27.51,1.26,2.92,1,0,9603,-168.52,-72.05,304.3,,,,,0
+618,5660,4307,4326,Derived in 2006 at 45 points in north and central Algeria.,Accuracy at 75 common points better than 1m..,1026,18.97,38.8,-8.67,11.99,1,0,9606,-209.3622,-87.8162,404.6198,0.0046,3.4784,0.5805,-1.4547,1
+619,7442,4307,4326,"Derived at 1 astro station central to concession. Significant and varying differences (>100m) known to exist in neighbouring astro stations.",Oil industry operations.,4382,27.4,28.1,7.66,8.27,1,0,9603,-181.7,64.7,247.2,,,,,0
+620,15874,4307,4326,"Derived at 11 stations throughout blocks 317b, 319b, 321b and 322b. Network based on station P4 (horizontal) and benchmark RN51 (vertical) using EGM96 geoid height. Used by Statoil in Hassi Mouina.",Oil exploration and production. Accuracy 5m.,3402,29.25,31,0,1.25,1,0,9603,-169.559,-72.34,303.102,,,,,0
+621,1234,4309,4326,Accuracy estimate not available.,For military purposes.,3326,-35,-30.09,-58.49,-53.09,1,0,9603,-155,171,37,,,,,1
+622,5386,4309,4326,Derived at 11 stations during 1998 densification of Uruguay control based on SIRGAS 1995.,"Accuracy at stations used for derivation: 0.13 to 1.17m.",3326,-35,-30.09,-58.49,-53.09,1,0,9606,-124.45,183.74,44.64,-0.4384,0.5446,-0.9706,-2.1365,0
+623,6903,4310,4326,Derived at 7 stations.,For military purposes only. Accuracy 3m in each axis.,1207,10.64,16.7,-20.22,-11.36,1,0,9603,-30,190,89,,,,,1
+624,1235,4311,4326,Derived at 5 stations.,"For military purposes. Accuracy 5m, 5m and 8m in X, Y and Z axes.",1222,1.83,9.35,-58.08,-52.66,1,0,9603,-265,120,-358,,,,,1
+625,1194,4312,4326,May be taken as approximate transformation MGI to ETRS89 assuming ETRS89 is equivalent to WGS 84 within the accuracy of the transformation - see tfm code 1024. Information source gives scale as -2.388739 ppm.,Provincial GIS and other applications to an accuracy of 0.5 metres.,1543,46.64,47.84,13.58,16.17,1,0,9607,601.705,84.263,485.227,-4.7354,-1.3145,-5.393,-2.3887,0
+626,1306,4312,4326,Accuracy estimate not available.,For military purposes only.,2370,40.85,46.88,13.38,23.04,1,1,9603,682,-203,480,,,,,0
+627,1471,4312,4326,,For applications to an accuracy of 1.5 metres.,1037,46.4,49.02,9.53,17.17,1,1,9606,-577.326,-90.129,-463.919,-5.136599,-1.474,-5.297044,-2.4232,0
+628,1618,4312,4326,"Same transformation parameters used for MGI to ETRS89 (1) (code 1619).",For applications to an accuracy of 1.5 metres.,1037,46.4,49.02,9.53,17.17,1,0,9606,577.326,90.129,463.919,5.137,1.474,5.297,2.4232,1
+629,1621,4312,4326,"Parameter values from MGI to ETRS89 (2) (code 1620). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1076,41.62,46.54,13,19.43,1,1,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
+630,1786,4312,4326,"Parameter values from MGI to ETRS89 (3) (code 1785). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,1,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
+631,1794,4312,4326,"For more accurate transformation see MGI to WGS 84 (7) (code 1795).",Oil industry,3536,41.79,43.56,18.45,20.38,1,1,9603,695.5,-216.6,491.1,,,,,0
+632,15982,4312,4326,"Parameter values from MGI to Slovenia 1996 (1) (code 15981). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,1,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
+633,1609,4313,4326,"Scale difference is given by information source as 0.999999. Given in this record in ppm to assist application usage. Very similar parameter values (to slightly less precision) used for BD72 to ETRS89: see code 1652.",For applications to an accuracy of 1 metre.,1347,49.5,51.51,2.5,6.4,1,0,9607,-99.059,53.322,-112.486,-0.419,0.83,-1.885,-1,0
+634,1610,4313,4326,,For applications to an accuracy of 5 metres.,1347,49.5,51.51,2.5,6.4,1,0,9603,-125.8,79.9,-100.5,,,,,0
+635,15929,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15928). Scale difference is given by information source as -1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1347,49.5,51.51,2.5,6.4,1,0,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747,1
+636,15749,4313,4326,"Parameter values from BD72 to ETRS89 (2) (code 15748). Scale difference is given by information source as 1.0000012747. Given in this record in ppm to assist application usage.",For applications to an accuracy of 0.5 metre.,1044,49.5,51.88,2.23,6.4,1,1,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,1.2747,0
+637,1673,4314,4326,"Parameter values from DHDN to ETRS89 (1) (code 1309) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaced by DHDN to WGS 84 (2) (tfm code 1777).",For applications with an accuracy at 5 m level.,2326,47.27,55.09,5.87,13.84,1,0,9607,582,105,414,-1.04,-0.35,3.08,8.3,0
+638,1777,4314,4326,"Parameter values from DHDN to ETRS89 (2) (code 1776) assuming that ETRS89 is equivalent to WGS 84 within the accuracy of the transformation. Replaces DHDN to WGS 84 (1) (tfm code 1673).",For applications with an accuracy at 3 m level,2326,47.27,55.09,5.87,13.84,1,0,9606,598.1,73.7,418.2,0.202,0.045,-2.455,6.7,1
+639,15869,4314,4326,"Parameter values taken from RD/83 to ETRS89 (1) (tfm code 15868) assuming that within the accuracy of the transformation ETRS89 is equivalent to WGS 84 and RD/83 is equivalent to DHDN.",For applications with an accuracy at 2m level,1343,50.2,54.74,9.92,15.04,1,0,9606,612.4,77,440.2,-0.054,0.057,-2.797,2.55,0
+640,1517,4315,4326,,"?",3257,7.19,12.68,-15.13,-7.65,1,0,9603,-23,259,-9,,,,,1
+641,1789,4316,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that","?",1197,43.44,48.27,20.26,31.41,1,1,9603,103.25,-100.4,-307.19,,,,,0
+642,1995,4316,4326,,Oil exploration,3295,43.62,48.27,20.26,29.74,1,0,9603,103.25,-100.4,-307.19,,,,,1
+643,1097,4317,4326,"Parameter values taken from Pulkovo 1942 to WGS 84 (9) (code 1293) assuming that Pulkovo 1942 in Romania is equivalent to Dealul Piscului 1970.","Accuracy 3m, 5m and 3m in X, Y and Z axes.",1197,43.44,48.27,20.26,31.41,1,1,9603,28,-121,-77,,,,,0
+644,1996,4317,4326,,Oil exploration,1197,43.44,48.27,20.26,31.41,1,1,9603,44.107,-116.147,-54.648,,,,,0
+645,1060,4318,4326,,1 metre accuracy.,3267,28.53,30.09,46.54,48.48,1,0,9603,-3.2,-5.7,2.8,,,,,1
+646,1061,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.45,47.78,48.16,1,0,9603,-20.8,11.3,2.4,,,,,1
+647,1062,4319,4326,,For applications requiring an accuracy of better than 1 metre.,1310,29.17,29.45,47.78,48.16,1,0,9607,226.702,-193.337,-35.371,2.229,4.391,-9.238,0.9798,0
+648,6910,6881,4326,Derivation not given.,For military purposes. Accuracy not specified.,1340,12.54,19,43.37,53.14,1,0,9603,-24,-203,268,,,,,1
+649,1237,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.2263,1
+650,1238,4322,4326,,For scientific purposes.,1262,-90,90,-180,180,1,0,9606,0,0,4.5,0,0,0.554,0.219,0
+651,6912,6883,4326,Derived at 6 stations.,"For military purposes. Accuracy 5m, 17m and 38m in X, Y and Z axes.",4220,3.14,3.82,8.37,9.02,1,0,9603,-235,-110,393,,,,,1
+652,1240,4324,4326,,Geodesy.,2346,-90,90,-180,180,1,0,9606,0,0,1.9,0,0,0.814,-0.38,1
+653,5521,4646,4326,,For military purposes. Accuracy unknown.,2807,-11.99,-11.31,43.16,43.55,1,0,9603,-963,510,-359,,,,,1
+654,15822,4732,4326,Derived at 10 satellite stations.,"For military and topographic mapping. Accuracy +/-3 m in each axis.",3191,8.66,19.38,162.27,167.82,1,0,9603,102,52,-38,,,,,1
+655,5327,5324,4326,For many purposes ISN2004 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN2004 is equivalent to WGS 84.",1120,59.96,69.59,-30.87,-5.55,1,0,9603,0,0,0,,,,,1
+656,3817,3819,4326,Horizontal coordinates of 66 points of the National Geodetic Network were used to compute this transformation.,GIS and topographic survey.,1119,45.74,48.58,16.11,22.9,1,0,9607,595.48,121.69,515.35,-4.115,2.9383,-0.853,-3.408,1
+657,6914,6892,4326,"Derived by UK DOS at 10 stations in 1998, RMS ±0.314m. Also published by NGA in Standard 0036 v1.0.0 of 2014-07-08 and in GeoTrans v3.4 software with parameter values rounded to integer.",Topographic mapping.,4183,-4.86,-3.66,55.15,56.01,1,0,9603,-43.685,-179.785,-267.721,,,,,1
+658,6926,6892,4326,"Derived by UKHO at 13 stations in 1999, RMS ±0.271m.",Hydrographic survey and charting.,4183,-4.86,-3.66,55.15,56.01,1,0,9606,-76.269,-16.683,68.562,-6.275,10.536,-4.286,-13.686,0
+659,1920,4645,4326,,"Accuracy +/- 1 metre.",1174,-26.45,-14.83,156.25,174.28,1,1,9603,0,0,0,,,,,0
+660,6913,6894,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3250,13.05,13.83,-16.88,-13.79,1,0,9603,-63,176,185,,,,,1
+661,15823,4733,4326,Derived at 2 satellite stations.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3190,19.22,19.38,166.55,166.72,1,0,9603,276,-57,149,,,,,1
+662,3830,3824,4326,"Approximation at the +/- 1m level assuming that TWD97 is equivalent to WGS 84.","Accuracy +/- 1m.",1228,17.36,26.96,114.32,123.61,1,0,9603,0,0,0,,,,,1
+663,7443,7373,4326,"Approximation at the +/- 1m level assuming that ONG14 is equivalent to WGS 84. See transformation code 7377 for authoritative values.",Geodesy.,1183,14.33,26.74,51.99,63.38,1,0,9603,0,0,0,,,,,1
+664,5376,5365,4326,,Accuracy 1m.,1074,2.15,11.77,-90.45,-81.43,1,0,9603,0,0,0,,,,,1
+665,15808,4724,4326,Derived at 2 satellite stations.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3189,-7.49,-7.18,72.3,72.55,1,0,9603,208,-435,-229,,,,,1
+666,5377,5371,4326,,Accuracy 1m.,1186,5,12.51,-84.32,-77.04,1,0,9603,0,0,0,,,,,1
+667,5378,5373,4326,,Accuracy 1m.,1189,-21.05,-0.03,-84.68,-68.67,1,0,9603,0,0,0,,,,,1
+668,15812,4736,4326,,"Scientific mapping. Accuracy +/- 20m in each axis.",3204,-63.08,-62.82,-60.89,-60.35,1,0,9603,260,12,-147,,,,,1
+669,15821,4731,4326,Derived at 1 satellite station.,"For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,1,9603,51,391,-36,,,,,0
+670,15795,4707,4326,Derived at 1 satellite station. Same transformation parameter values related to same datum area given in original 1987 DMA TR8350.2 edition for Sorol Atoll.,For military purposes only. Accuracy 25m in each axis.,3181,23.69,23.93,-166.36,-166.03,1,0,9603,114,-116,-333,,,,,1
+671,5384,5381,4326,,Accuracy 1m.,1247,-37.77,-30.09,-58.49,-50.01,1,0,9603,0,0,0,,,,,1
+672,15813,4722,4326,Determined from 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3529,-54.95,-53.93,-38.08,-35.74,1,0,9603,-794,119,-298,,,,,1
+673,5227,5228,4326,"Parameter values from S-JTSK/05 to ETRS89 (1) (code 5226). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation. Replaces tfm code 1622.",For applications to an accuracy of 1 metre.,1079,48.58,51.06,12.09,18.86,1,0,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378,1
+674,15771,4692,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Maupiti 83 to RGPF (1) (tfm code 15759).","Accuracy +/- 1 metre.",3126,-16.57,-16.34,-152.39,-152.14,1,0,9603,217.037,86.959,23.956,,,,,1
+675,15973,4055,4326,"Executes change of sphere/ellipsoid",Web mapping. Accuracy may be no better than 800 metres.,1262,-90,90,-180,180,1,1,9603,0,0,0,,,,,0
+676,5395,5393,4326,,Accuracy 1m.,1087,9.97,14.44,-91.43,-87.65,1,0,9603,0,0,0,,,,,1
+677,15816,4734,4326,Determined at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3184,-40.42,-37,-12.76,-9.8,1,0,9603,-632,438,-609,,,,,1
+678,1585,4227,4326,,"?",1227,32.31,37.3,34.96,42.38,1,1,9603,-177.5,14.1,237.6,,,,,0
+679,1586,4227,4326,"Derived in 1995 by CGG for Al Furat Petroleum Company. Can be approximated using geocentric translations of dX=-174.3m, dY=+14.1m, dZ=+237.6m.",Oil exploration.,2327,35.33,35.9,39.15,40.41,1,0,9606,-175.09,1.218,238.831,-0.047,0.019,0.808,0.1698,0
+680,1587,4227,4326,Derived at four stations by Topnav in 1997.,Oil exploration.,2328,35.79,36.5,40.5,41.39,1,0,9603,-191.77,15.01,235.07,,,,,0
+681,15741,4227,4326,Derived by Elf in 1991 from tfm code 1584 concatenated with a tfm from WGS72BE to WGS84.,Oil exploration. Accuracy 5m.,2329,34.49,35.9,39.3,40.81,1,0,9603,-187.5,14.1,237.6,,,,,0
+682,15742,4227,4326,Derived for 1998 Omar seismic survey and used in 2000 for El Isba seismic survey.,Oil exploration. Accuracy 5m.,3314,32.31,37.3,35.61,42.38,1,0,9603,-190.421,8.532,238.69,,,,,1
+683,15743,4227,4326,"Derived 2005 at 5 triangulation stations and using (EGM96 geoid model +1.15m). Used by Total/DEZPC for Jafra and Mazraa seismic surveys. Can be approximated using geocentric translations of dX=-190.6m, dY=+8.8m, dZ=+239.6m.",Oil exploration. Accuracy 0.5m.,2329,34.49,35.9,39.3,40.81,1,0,9606,-83.58,-397.54,458.78,-17.595,-2.847,4.256,3.225,0
+684,5261,5252,4326,,"Approximation at the +/- 1m level as both TUREF and WGS 84 are realisations of ITRS.",1237,34.42,43.45,25.62,44.83,1,0,9603,0,0,0,,,,,1
+685,1925,4639,4326,,"Accuracy +/- 10 metres.",2815,-13.41,-13.16,-176.25,-176.07,1,1,9603,252,-132,-125,,,,,0
+686,15847,4639,4326,"Replaces information from 2001 (tfm code 1925).","Accuracy +/- 10 metres.",2815,-13.41,-13.16,-176.25,-176.07,1,0,9603,253,-132,-127,,,,,1
+687,15801,4714,4326,Derived at 3 satellite stations.,"Military and topographic mapping; Accuracy +/- 20 m in each axis",3193,-20.31,-17.37,168.09,169.95,1,0,9603,-127,-769,472,,,,,1
+688,7892,7886,4326,"SHGD2015 is realised by ITRF2008 at epoch 2015.0 and can be considered coincident with WGS 84 at epoch 2015.0 Accuracy 3 cm at 1/1/2015 then degrades by 3 cm/yr from 1/1/2015 depending upon epoch of WGS 84 due to motion of the Nubian Plate",For military purposes only. Accuracy 25m in each axis.,3183,-16.08,-15.85,-5.85,-5.58,1,0,9603,0,0,0,,,,,1
+689,15802,4715,4326,No accuracy estimate available.,Military and scientific mapping.,3205,-77.94,-77.17,165.73,167.43,1,0,9603,-104,-129,239,,,,,1
+690,1994,4657,4326,,Low accuracy applications.,3262,63.34,66.59,-24.66,-13.38,1,0,9603,-28,199,5,,,,,1
+691,5351,5340,4326,,Approximation at the sub meter level.,1033,-58.41,-21.78,-73.59,-52.63,1,0,9603,0,0,0,,,,,1
+692,5078,4743,4326,"Parameter values from Karbala 1979 to IGRS (1) (tfm code 5077) assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation. Replaces Karbala 1979 to WGS 84 (1) (tfm code 15872).",Accuracy 1m.,3625,29.06,37.39,38.79,48.61,1,0,9603,70.995,-335.916,262.898,,,,,1
+693,15872,4743,4326,"Derived from shifts in UTM rectangular coordinates for one point in Basra area provided by Iraq National Oil Exploration Company. Replaced by Karbala 1979 to WGS 84 (2) (tfm code 5078).",Oil exploration.,3397,29.87,31.09,46.46,48.61,1,0,9603,84.1,-320.1,218.7,,,,,0
+694,1951,4658,4326,"Derived at 6 stations. Replaced by Hjorsey 1955 to WGS 84 (2) (code 6909).","Accuracy 3m, 3m and 5m in X, Y and Z axes.",3262,63.34,66.59,-24.66,-13.38,1,0,9603,-73,46,-86,,,,,0
+695,6909,4658,4326,"Derived at 16 stations. Replaces Hjorsey 1955 to WGS 84 (1) (code 1951).","Accuracy 3m, 3m and 6m in X, Y and Z axes.",3262,63.34,66.59,-24.66,-13.38,1,0,9603,-73,47,-83,,,,,1
+696,6373,6365,4326,,Accuracy 1m.,1160,12.1,32.72,-122.19,-84.64,1,0,9603,0,0,0,,,,,1
+697,3894,3889,4326,"Approximation at the +/- 1m level assuming that IGRS is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1124,29.06,37.39,38.79,48.75,1,0,9603,0,0,0,,,,,1
+698,1952,4659,4326,For many purposes ISN93 can be considered to be coincident with WGS 84.,"Approximation at the +/- 1m level assuming that ISN93 is equivalent to WGS 84.",1120,59.96,69.59,-30.87,-5.55,1,0,9603,0,0,0,,,,,1
+699,1957,4660,4326,Derived at 3 stations. Residuals under 1m.,For applications to an accuracy of 1 metre.,2869,70.75,71.24,-9.17,-7.87,1,0,9606,982.6087,552.753,-540.873,6.6816266,-31.6114924,-19.84816,16.805,1
+700,1958,4661,4326,,LKS92 is a realisation of ETRS89 coincident to WGS84 within 1 metre. This transformation has an accuracy equal to the coincidence figure.,1139,55.67,58.09,19.06,28.24,1,0,9603,0,0,0,,,,,1
+701,15849,4213,4326,"Used by Elf / CGG between December 1991 and March 1992. Probably derived from results of concatenated tfm Beduaram to WGS 84 (1) (code 8634).",Oil exploration.,2771,12.8,16.7,7.81,14.9,1,0,9603,-106,-87,188,,,,,1
+702,15803,4716,4326,Derived at 4 satellite stations.,"Military and topographic mapping. Accuracy +/- 15 m in each axis.",3196,-4.76,-2.68,-174.6,-170.66,1,0,9603,298,-304,-375,,,,,1
+703,3915,3906,4326,"Parameter values from MGI 1901 to ETRS89 (3) (code 3914). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,0,9606,426.9,142.6,460.1,4.91,4.49,-12.42,17.1,0
+704,3917,3906,4326,"Parameter values from MGI 1901 to Slovenia 1996 (1) (code 3916). Assumes Slovenia 1996 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1212,45.42,46.88,13.38,16.61,1,0,9607,409.545,72.164,486.872,-3.085957,-5.46911,11.020289,17.919665,0
+705,3962,3906,4326,Accuracy estimate not available from information source but established empirically by OGP.,For military purposes only.,2370,40.85,46.88,13.38,23.04,1,0,9603,682,-203,480,,,,,1
+706,3964,3906,4326,"Parameter values from MGI 1901 to ETRS89 (2) (code 3963). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,3234,42.34,46.54,13.43,19.43,1,0,9606,551.7,162.9,467.9,6.04,1.96,-11.38,-4.82,0
+707,3965,3906,4326,,Oil industry,3536,41.79,43.56,18.45,20.38,1,0,9603,695.5,-216.6,491.1,,,,,0
+708,6206,3906,4326,Derived at 13 stations.,"1m accuracy. Residuals generally less than +/- 1m horizontally and vertically.",1148,40.85,42.36,20.45,23.04,1,0,9607,521.748,229.489,590.921,-4.029,-4.488,15.521,-9.78,0
+709,7676,3906,4326,"Parameter values from MGI 1901 to ETRS89 (6) (code 7675). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications with an accuracy of 1m.,3534,41.85,46.19,18.81,23.01,1,0,9607,577.88891,165.22205,391.18289,-4.9145,0.94729,13.05098,7.78664,0
+710,1962,4662,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15903.,"Accuracy +/- 10 metres.",2822,-22.45,-20.03,163.92,167.09,1,0,9603,-13,-348,292,,,,,0
+711,1963,4662,4326,Withdrawn by information source and replaced by improved information - see tfm code 15903.,"Accuracy better than +/- 1 metre.",2822,-22.45,-20.03,163.92,167.09,1,0,9606,97.295,-263.247,310.882,-1.5999,0.8386,3.1409,13.3259,0
+712,15903,4662,4326,"Parameter values taken from IGN72 Grande Terre to RGNC91-93 (1) ( code 15882) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy +/- 2 metres.",2822,-22.45,-20.03,163.92,167.09,1,0,9603,-11.64,-348.6,291.98,,,,,1
+713,15878,4748,4326,"Parameter values taken from Viti Levu 1912 to WGS 84 (1) (tfm code 15897). Approximation at the +/- 50m level assuming that CRS 4748 is equivalent to CRS 4752 within the transformation accuracy. Source CRSs 4748 and 4752 are independent but connected.","For applications with an accuracy of +/-50m.",3401,-17.07,-16.1,178.42,-179.77,1,0,9603,51,391,-36,,,,,1
+714,1966,4663,4326,Derived at Forte de Sao Tiago.,For low resolution applications.,2870,32.58,33.15,-17.31,-16.23,1,0,9603,-502.862,-247.438,312.724,,,,,1
+715,1967,4663,4326,,For medium resolution applications.,2870,32.58,33.15,-17.31,-16.23,1,0,9607,-210.502,-66.902,-48.476,-2.094,15.067,5.817,0.485,0
+716,6911,6882,4326,Derivation not given.,For military purposes. Accuracy not specified.,3269,33.06,34.65,35.04,36.63,1,0,9603,-183,-15,273,,,,,1
+717,15880,4749,4326,,"Accuracy +/- 1 metre.",1174,-26.45,-14.83,156.25,174.28,1,0,9603,0,0,0,,,,,1
+718,1968,4664,4326,Calculated in 2001.,For low resolution applications.,2871,37.65,37.96,-25.92,-25.08,1,0,9603,-204.633,140.216,55.199,,,,,0
+719,1969,4664,4326,Calculated in 2001.,For medium resolution applications.,2871,37.65,37.96,-25.92,-25.08,1,0,9607,-211.939,137.626,58.3,0.089,-0.251,-0.079,0.384,0
+720,1970,4664,4326,Mean for all islands in group.,For low resolution applications.,1345,36.87,37.96,-25.92,-24.62,1,0,9603,-204.619,140.176,55.226,,,,,1
+721,1971,4664,4326,Mean for all islands in group.,For medium resolution applications.,1345,36.87,37.96,-25.92,-24.62,1,0,9607,-208.719,129.685,52.092,0.195,0.014,-0.327,0.198,0
+722,15881,4750,4326,"Parameter values taken from ST87 Ouvea to RGNC91-93 (1) ( code 15885) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.","Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.44,166.71,1,0,9603,-56.263,16.136,-22.856,,,,,1
+723,1972,4665,4326,,For low resolution applications.,2872,38.57,38.86,-27.44,-26.97,1,0,9603,-106.301,166.27,-37.916,,,,,0
+724,1973,4665,4326,,For medium resolution applications.,2872,38.57,38.86,-27.44,-26.97,1,0,9607,-105.854,165.589,-38.312,0.003,0.026,-0.024,-0.048,0
+725,1974,4665,4326,,For low resolution applications.,2873,38.46,38.7,-28.9,-28.54,1,0,9603,-106.248,166.244,-37.845,,,,,0
+726,1975,4665,4326,,For medium resolution applications.,2873,38.46,38.7,-28.9,-28.54,1,0,9607,-104,162.924,-38.882,0.075,0.071,-0.051,-0.338,0
+727,1976,4665,4326,,For low resolution applications.,2874,38.32,38.61,-28.61,-27.98,1,0,9603,-106.044,166.655,-37.876,,,,,0
+728,1977,4665,4326,,For medium resolution applications.,2874,38.32,38.61,-28.61,-27.98,1,0,9607,-95.323,166.098,-69.942,0.215,1.031,-0.047,1.922,0
+729,1978,4665,4326,,For low resolution applications.,2875,38.48,38.8,-28.37,-27.71,1,0,9603,-106.253,166.239,-37.854,,,,,0
+730,1979,4665,4326,,For medium resolution applications.,2875,38.48,38.8,-28.37,-27.71,1,0,9607,-100.306,161.246,-48.761,0.192,0.385,-0.076,0.131,0
+731,1980,4665,4326,Mean for all islands in group.,For low resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9603,-106.226,166.366,-37.893,,,,,1
+732,1981,4665,4326,Mean for all islands in group.,For medium resolution applications.,1301,38.32,39.14,-28.9,-26.97,1,0,9607,-103.088,162.481,-28.276,-0.167,-0.082,-0.168,-1.504,0
+733,1986,4666,4326,May be taken as a transformation from Lisbon 1890 to ETRS89 - see tfm code 5039.,For low resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9603,508.088,-191.042,565.223,,,,,1
+734,1990,4666,4326,,For medium resolution applications.,1294,36.95,42.16,-9.56,-6.19,1,0,9607,631.392,-66.551,481.442,-1.09,4.445,4.487,-4.43,0
+735,15804,4717,4326,Derived at 19 satellite stations.,"US space and military operations. Accuracy +/- 3 m in each axis.",3206,20.86,30.83,-82.33,-72.68,1,0,9603,-2,151,181,,,,,1
+736,5267,5264,4326,DRUKREF 03 and WGS 84 are both realisations of ITRS.,For applications to an accuracy of 1 metre.,1048,26.7,28.33,88.75,92.12,1,0,9603,0,0,0,,,,,1
+737,1993,4667,4326,For all practical purposes this transformation is exact.,Boundary demarcation.,2876,29.06,30.32,46.36,48.61,1,0,9603,0,0,0,,,,,1
+738,6895,4752,4326,"Derived at 9 stations. Replaces Viti Levu 1912 to WGS 84 (1) (code 15897).","For military and topographic mapping. Accuracy +/-3m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,0,9603,98,390,-22,,,,,1
+739,15897,4752,4326,"Derived at 1 satellite station. Replaced by Viti Levu 1912 to WGS 84 (2) (code 6895).","For military and topographic mapping. Accuracy +/-25m in each axis.",3195,-18.32,-17.25,177.19,178.75,1,0,9603,51,391,-36,,,,,0
+740,5470,5451,4326,"Parameter values taken from Ocotepeque to CR05 (1) (tfm code 6890) assuming that CR05 is equivalent to WGS 84 within the accuracy of the transformation.",Topographic mapping.,3232,7.98,11.22,-85.97,-82.53,1,0,9603,213.11,9.37,-74.95,,,,,0
+741,5473,5451,4326,"Rotations in original source given in radians are equivalent to Rx = 2.35"", Ry = -0.06"", Rz = 6.39"".",Topographic mapping.,3232,7.98,11.22,-85.97,-82.53,1,1,9607,213.116,9.358,-74.946,2.351,-0.06147,6.39,-5.22,0
+742,5474,5451,4326,,Topographic mapping.,3876,7.98,17.83,-92.29,-82.53,1,1,9603,205.435,-29.099,292.202,,,,,0
+743,6891,5451,4326,"Concatenation (via NAD27) of transformations 6888 and 1171. Accuracy not given, but accuracy of constituent transformations given as 9m and 10m respectively.",For military purposes.,3876,7.98,17.83,-92.29,-82.53,1,0,9603,205,96,-98,,,,,1
+744,15752,4668,4326,Derived at 22 stations.,For military purposes. Accuracy 3m in each axis.,1297,34.88,71.21,-10.56,31.59,1,0,9603,-86,-98,-119,,,,,1
+745,15810,4735,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3192,5.21,5.43,162.85,163.1,1,0,9603,647,1777,-1124,,,,,1
+746,15908,4754,4326,Derived at 5 stations throughout Libya used to define LGD2006 in May 2006.,For applications to an accuracy of 0.1 metre.,1143,19.5,35.23,9.31,26.21,1,0,9603,-208.4058,-109.8777,-2.5764,,,,,1
+747,4477,4463,4326,"Approximation at the +/- 1m level assuming that RGSPM06 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1220,43.41,47.37,-57.1,-55.9,1,0,9603,0,0,0,,,,,1
+748,5501,5489,4326,"Approximation at the +/- 1m level assuming that RGAF09 is equivalent to WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",2824,14.08,18.54,-63.66,-57.52,1,0,9603,0,0,0,,,,,1
+749,15912,4755,4326,"Approximation at the +/- 1m level assuming that DGN95 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1 metre.,1122,-13.95,7.79,92.01,141.46,1,0,9603,0,0,0,,,,,1
+750,1555,4158,4326,Derived in 1989 by ONI for Amoco.,Oil exploration.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-0.465,372.095,171.736,,,,,1
+751,1556,4158,4326,Described by NIMA as Naparima to WGS 84. In Trinidad the source CRS is better known as Naparima 1955. EPSG has duplicated the tfm using the alternative source CRSs. See also tfm code 1307.,For military purposes only. Accuracy given by NIMA 15m in each axis. EPSG believes there is an 8-10m blunder in dX.,3143,9.99,10.9,-61.97,-60.86,1,0,9603,-2,374,172,,,,,0
+752,4476,4470,4326,"Approximation at the +/- 1m level assuming that RGM04 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1159,-14.49,-11.33,43.68,46.7,1,0,9603,0,0,0,,,,,1
+753,5194,4756,4326,Used by Total in Mekong delta.,Academic research not officially adopted.,3770,9.34,11.03,104.25,107.11,1,0,9607,-192.873,-39.382,-111.202,0.00205,0.0005,-0.00335,0.0188,0
+754,6960,4756,4326,,Academic research not officially adopted.,3328,8.5,23.33,102.14,109.52,1,0,9607,-191.90441429,-39.30318279,-111.45032835,-0.00928836,0.01975479,-0.00427372,0.252906278,1
+755,1931,4643,4326,,"Accuracy better than +/- 1 metre.",2821,-19.85,-19.5,163.54,163.75,1,0,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002,1
+756,4290,4475,4326,"Parameter values taken from Cadastre 1997 to RGM04 (1) (transformation code 4478) assuming that RGM04 is coincident with WGS 84 within the accuracy of the transformation.","Accuracy +/- 1 metre.",3340,-13.05,-12.61,44.98,45.35,1,0,9603,-381.788,-57.501,-256.673,,,,,1
+757,5374,5354,4326,,Accuracy 1m.,1049,-22.91,-9.67,-69.66,-57.52,1,0,9603,0,0,0,,,,,1
+758,15787,4701,4326,Derived by Topnav in 1991 at station TSH 85.,Oil exploration. Accuracy 5m.,3171,-6.04,-4.28,12.17,16.28,1,0,9603,-79.9,-158,-168.9,,,,,1
+759,4832,4483,4326,,Accuracy 1m.,1160,12.1,32.72,-122.19,-84.64,1,0,9603,0,0,0,,,,,1
+760,1917,4633,4326,Withdrawn by information source and replaced by improved information from local authority - see tfm code 15902.,"Accuracy +/- 10 metres.",2814,-21.24,-20.62,166.98,167.52,1,0,9603,336,223,-231,,,,,0
+761,1927,4633,4326,Withdrawn by information source and replaced by improved information - see tfm code 15902.,"Accuracy better than +/- 1 metre.",2814,-21.24,-20.62,166.98,167.52,1,0,9606,137.092,131.66,91.475,-1.9436,-11.5993,-4.3321,-7.4824,0
+762,15902,4633,4326,"Parameter values taken from IGN56 Lifou to RGNC91-93 (1) ( code 15883) assuming that RGNC91-93 is equivalent to WGS 84 to within the accuracy of the transformation.",Accuracy 1 metre.,2814,-21.24,-20.62,166.98,167.52,1,0,9603,335.47,222.58,-230.94,,,,,1
+763,15925,4758,4326,,For all practical purposes JAD2001 can be considered to be coincident with WGS 84.,1128,14.08,19.36,-80.6,-74.51,1,0,9603,0,0,0,,,,,1
+764,6711,6706,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. RDN2008 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",1127,34.76,47.1,5.93,18.99,1,0,9603,0,0,0,,,,,1
+765,15845,4161,4326,Transformation parameter precision given to millimetres in information source but due to accuracy rounded to nearest decimetre for EPSG database.,Geodetic surveying within the oil industry. Accuracy 25 m.,1265,-46.7,-45.19,-69.5,-67.1,1,0,9603,27.5,14,186.4,,,,,1
+766,15931,4759,4326,"Approximation at the +/- 1m level assuming that NAD83(NSRS2007) is equivalent to WGS 84 within the accuracy of the transformation.",For applications to an accuracy of 1 metre.,1511,14.92,74.71,167.65,-63.88,1,0,9603,0,0,0,,,,,1
+767,1540,4163,4326,,Accuracy better than 1 metre.,1257,8.95,19,41.08,57.96,1,0,9603,0,0,0,,,,,1
+768,4905,5013,4326,,PTRA08 and WGS 84 are realisations of ITRS coincident to within 1 metre. This transformation has an accuracy equal to the coincidence figure.,3670,29.24,43.07,-35.58,-12.48,1,0,9603,0,0,0,,,,,1
+769,6195,5527,4326,"Parameter values from SAD69(96) to SIRGAS 2000 (2)) (tfm code 5881) assuming that SIRGAS 2000 and WGS 84 are equal within the accuracy of the transformation, based on SAD69 to SIRGAS 2000 (1)) (tfm code 15485). Used by Petrobras and ANP from 1994.","Accuracy generally better than 1m except in Amazon basin where it degenerates to 5m. Should be used only to transform data obtained independently of the classical geodetic network (GPS observations conducted after 1994).", [...]
+770,15806,4719,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis",3188,-27.25,-27.01,-109.51,-109.16,1,0,9603,211,147,111,,,,,1
+771,15860,4702,4326,Mauritania 1999 can be considered to be the same as WGS 84 within the accuracy of this transformation.,Minerals management. Accuracy 1m.,1157,14.72,27.3,-20.04,-4.8,1,0,9603,0,0,0,,,,,1
+772,15971,4762,4326,"Approximation at the +/- 1m level assuming that BDA2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1047,28.91,35.73,-68.83,-60.7,1,0,9603,0,0,0,,,,,1
+773,5375,5360,4326,,Accuracy 1m.,1066,-59.87,-17.5,-113.21,-65.72,1,0,9603,0,0,0,,,,,1
+774,15972,4763,4326,"Approximation at the +/- 1m level assuming that Pitcairn 2006 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3208,-25.14,-25,-130.16,-130.01,1,0,9603,0,0,0,,,,,1
+775,1558,4166,4326,Derived at 5 stations.,For military purposes. Accuracy 1m in each axis.,3266,33.14,38.64,124.53,131.01,1,0,9603,0,0,0,,,,,1
+776,4084,4081,4326,"Approximation at the +/- 1m level assuming that REGCAN95 is equivalent to WGS 84.","Accuracy +/- 1m.",3199,24.6,32.76,-21.93,-11.75,1,0,9603,0,0,0,,,,,1
+777,15974,4764,4326,"Approximation at the +/- 1m level assuming that RSRGD2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",3558,-90,-59.99,144.99,-144.99,1,0,9603,0,0,0,,,,,1
+778,5553,5546,4326,"Exact in 1994 but due to significant and variable tectonic activity in PNG, in 2011 PNG94 and WGS 84 differ generally by 2m but in areas of significant tectonic activity differences can exceed 9m.",Approximation at the 2-10m level.,1187,-14.75,2.58,139.2,162.81,1,0,9603,0,0,0,,,,,1
+779,15870,4679,4326,Derived at 5 points in 2002.,Hydrographic survey,2967,19.37,21.34,-17.08,-15.88,1,0,9603,-80.01,253.26,291.19,,,,,1
+780,15817,4727,4326,"Derived at 1 satellite station. Information source states ""provided for historical purposes only. These parameter [values] should not be used"". Replaced by Midway 1961 to WGS 84 (2) (tfm code 15818).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.28,-177.45,-177.31,1,0,9603,912,-58,1227,,,,,0
+781,15818,4727,4326,"Derived at 1 satellite station. Replaces Midway 1961 to WGS 84 (1) (tfm code 15817).","Military and topographic mapping. Accuracy +/- 25m in each axis.",3202,28.13,28.28,-177.45,-177.31,1,0,9603,403,-81,277,,,,,1
+782,15976,4765,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1212,45.42,46.88,13.38,16.61,1,0,9603,0,0,0,,,,,1
+783,15820,4730,4326,Derived at 1 satellite station.,For military and topographic mapping. Accuracy 25m in each axis.,3194,-17.32,-14.57,166.47,168.71,1,0,9603,170,42,84,,,,,1
+784,15709,4680,4326,Derived by IGN in 1992 at 7 stations within Nouakchott city.,Oil exploration.,2972,17.89,18.25,-16.11,-15.83,1,0,9603,124.5,-63.5,-281,,,,,1
+785,15805,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3198,-8.86,-7.52,156.44,158.2,1,0,9603,230,-199,-752,,,,,1
+786,15807,4718,4326,Derived at 1 satellite station.,"Military and topographic mapping. Accuracy +/- 25m in each axis.",3197,-9.98,-9.2,159.55,160.88,1,0,9603,252,-209,-751,,,,,0
+787,5585,4023,4326,"Parameter values from MOLDREF99 to ETRS89 (1) (code 5584). Assumes ETRS89 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications with an accuracy of 1m.,1162,45.44,48.47,26.63,30.13,1,0,9603,0,0,0,,,,,1
+788,15831,4737,4326,"Approximation at the +/- 1m level assuming that ITRF2000 is equivalent to WGS 84.","Accuracy +/- 1 metre.",1135,28.6,40.27,122.71,134.28,1,0,9603,0,0,0,,,,,1
+789,5590,5561,4326,"Derived through concatenation of UCS-2000 to S-42 (1) (tfm code 5586 reversed) [an approximation] and S-42 to WGS 84 (16) (tfm code 15865) [derived for whole FSU rather than Ukraine]. Replaced by UCS-2000 to WGS 84 (2) (tfm code 5840).",Accuracy 5 metres.,1242,43.18,52.38,22.15,40.18,1,0,9607,25,-141,-78.5,0,-0.35,-0.736,0,1
+790,5823,5561,4326,"Parameter values taken from Ukraine 2000 to ITRF2005 (1) (code 5822) assuming that ITRS2005 is equivalent to WGS 84 within the accuracy of the transformation.","Approximation at the +/- 1m level assuming that ITRS2005 is equivalent to WGS 84.",1242,43.18,52.38,22.15,40.18,1,1,9603,24,-121,-76,,,,,0
+791,5840,5561,4326,"Rounded parameter values taken from UCS-2000 to ITRF2000 (1) (code 7817) assuming that WGS 84 is equivalent to ITRS2000 within the accuracy of the transformation. Replaces UCS-2000 to WGS 84 (1) (tfm code 5590).","Approximation at the +/- 1m level assuming that WGS 84 is equivalent to ITRS2000.",1242,43.18,52.38,22.15,40.18,1,0,9603,24,-121,-76,,,,,0
+792,6143,4726,4326,"Parameter values are taken from SIGD59 to CIGD11 (1) (code 6137) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3186,19.63,19.78,-80.14,-79.69,1,0,9607,8.853,-52.644,180.304,0.393,2.323,-2.96,-24.081,1
+793,15814,4726,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",3186,19.63,19.78,-80.14,-79.69,1,0,9603,42,124,147,,,,,0
+794,15829,4726,4326,Determined from 2 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3186,19.63,19.78,-80.14,-79.69,1,0,9603,44.4,109,151.7,,,,,0
+795,15700,4682,4326,Derived at origin station in Dhaka.,Oil exploration.,1041,18.56,26.63,88.04,92.67,1,1,9603,283.8,735.9,261.1,,,,,0
+796,15779,4682,4326,Derived at origin station in Dhaka. Source information given to 3 decimal places but rounded by OGP to be commensurate with stated accuracy.,Oil exploration.,1041,18.56,26.63,88.04,92.67,1,0,9603,283.7,735.9,261.1,,,,,1
+797,1919,4635,4326,,"Accuracy better than +/- 1 metre.",2813,-20.77,-20.34,166.44,166.71,1,1,9606,-122.383,-188.696,103.344,3.5107,-4.9668,-5.7047,4.4798,0
+798,15708,4683,4326,Derived during GPS campaign which established PRS92 coordinates at 330 first order stations.,"Accuracy: 1-10 parts per million.",1190,3,22.18,116.04,129.95,1,0,9607,-127.62,-67.24,-47.04,3.068,-4.903,-1.578,-1.06,1
+799,6701,5246,4326,"Approximation at the +/- 1m level assuming that GDBD2009 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,1055,4.01,6.31,112.37,115.37,1,0,9603,0,0,0,,,,,1
+800,1837,4257,4326,,Oil exploration.,1316,-6.54,-1.88,118.71,120.78,1,0,9603,-587.8,519.75,145.76,,,,,1
+801,15713,4684,4326,Derived at 1 station.,For military purposes only. Accuracy 25m in each axis.,3274,-0.69,7.08,72.81,73.69,1,0,9603,-133,-321,50,,,,,1
+802,6177,6135,4326,"Approximation at the +/- 1m level assuming that CIGD11 is equivalent to WGS 84.","Accuracy +/- 1m.",1063,17.58,20.68,-83.6,-78.72,1,0,9603,0,0,0,,,,,1
+803,4064,4046,4326,"Approximation at the +/- 1m level assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1m.,3613,-13.46,-3.41,11.79,29.81,1,0,9603,0,0,0,,,,,1
+804,15875,4721,4326,Derived at 20 stations. Also published by NGA in GeoTrans v3.4 software with parameter values rounded to integer.,"For military purposes. Accuracy 5m, 3m and 2m in X, Y and Z axes.",3398,-19.22,-16.1,176.81,-179.77,1,0,9603,265.025,384.929,-194.046,,,,,1
+805,7445,6311,4326,"Parameter values from CGRS93 to ETRS89 (1) (code 7444). Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",Small scale hydrographic and aviation  mapping.,3236,34.59,35.74,32.2,34.65,1,1,9606,8.846,-4.394,-1.122,0.00237,0.146528,-0.130428,0.783926,0
+806,7721,6311,4326,"Parameter values from CGRS93 to ETRS89 (1) (code 7720). Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84.",Small scale hydrographic and aviation  mapping.,3236,34.59,35.74,32.2,34.65,1,0,9607,8.846,-4.394,-1.122,0.00237,0.146528,-0.130428,0.783926,1
+807,5599,5593,4326,,Approximation at the 1m level.,3889,54.33,54.83,10.66,12.01,1,0,9603,0,0,0,,,,,1
+808,15832,4687,4326,"Transformation is to original definition of WGS 84. It is consistent with later WGS 84 realisations G730, G873 and G1150 to no better than 1m.","Accuracy +/- 0.5 metre (to original definition of WGS 84 - see remarks).",1098,-31.24,-4.52,-158.13,-131.97,1,0,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093,1
+809,15833,4687,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84.","Accuracy +/- 1 metre.",1098,-31.24,-4.52,-158.13,-131.97,1,0,9603,0,0,0,,,,,0
+810,1921,4636,4326,,"Accuracy +/- 10 metres.",2817,-66.78,-66.1,139.44,141.5,1,0,9603,365,194,166,,,,,1
+811,15772,4688,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Fatu Iva 72 to RGPF (1) (tfm code 15760).","Accuracy +/- 2 metres.",3133,-10.6,-10.36,-138.75,-138.54,1,0,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074,1
+812,5236,5233,4326,Derived at 58 stations.,Accuracy 14m.,3310,5.86,9.88,79.64,81.95,1,0,9607,-0.293,766.95,87.713,-0.195704,-1.695068,-3.473016,-0.039338,1
+813,4077,4075,4326,"Approximation at the +/- 1m level assuming that ETRS89 is equivalent to WGS 84. SREF98 is a regional realisation of ETRS89.","Accuracy +/- 1 metre.",3534,41.85,46.19,18.81,23.01,1,0,9603,0,0,0,,,,,1
+814,4835,4690,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Tahiti 79 to RGPF (1) (tfm code 15756).","Accuracy +/- 1 metre.",3124,-17.93,-17.44,-149.7,-149.09,1,0,9607,221.525,152.948,176.768,2.3847,1.3896,0.877,11.4741,1
+815,1922,4637,4326,,"Accuracy +/- 10 metres.",2818,-67.13,-65.61,136,142,1,0,9603,325,154,172,,,,,1
+816,15797,4712,4326,Derived at 2 satellite stations.,For military purposes only. Accuracy 25m in each axis.,3182,-8.03,-7.83,-14.46,-14.24,1,0,9603,-205,107,53,,,,,1
+817,15769,4691,4326,"Approximation at the +/- 1m level assuming that RGPF is equivalent to WGS 84. Parameter values taken from Moorea 87 to RGPF (1) (tfm code 15757).","Accuracy +/- 1 metre.",3125,-17.63,-17.41,-150,-149.73,1,0,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773,1
+818,6142,4723,4326,"Parameter values are taken from GCGD59 to CIGD11 (1) (code 6136) assuming that CIGD11 and WGS 84 can be considered the same to within the accuracy of the transformation.",For applications to an accuracy of 1m.,3185,19.21,19.41,-81.46,-81.04,1,0,9607,-179.483,-69.379,-27.584,7.862,-8.163,-6.042,-13.925,1
+819,15830,4723,4326,Determined from 6 satellite stations.,"Topographic survey. Accuracy +/- 1m.",3185,19.21,19.41,-81.46,-81.04,1,0,9603,67.8,106.1,138.8,,,,,0
+820,4066,4695,4326,"Parameter values taken from Katanga 1955 to RGRDC 2005 (1) (code 4065) assuming that RGRDC 2005 is equivalent to WGS 84 within the accuracy of the transformation.",Accuracy 1.5m.,3614,-12.01,-11.13,26.38,27.75,1,0,9603,-103.746,-9.614,-255.95,,,,,1
+821,15746,4693,4326,Derived in Tombak district in March 2005. Used for South Pars phase 11 and Pars LNG plants.,Petroleum Exploration and Production.,3141,27.63,27.81,52.09,52.26,1,0,9603,0,-0.15,0.68,,,,,1
+822,1441,4601,4326,,"?",1273,16.94,17.22,-61.95,-61.61,1,0,9603,-255,-15,71,,,,,1
+823,15811,4601,4326,Determined from 1 satellite station.,"Military mapping. Accuracy +/- 25m in each axis.",1273,16.94,17.22,-61.95,-61.61,1,0,9603,-270,13,62,,,,,0
+824,1442,4602,4326,,"?",3239,15.14,15.69,-61.55,-61.2,1,0,9603,725,685,536,,,,,1
+825,1443,4603,4326,,"?",3118,11.94,12.29,-61.84,-61.54,1,0,9603,72,213.7,93,,,,,1
+826,1444,4604,4326,Derived at 1 satellite station.,Accuracy 25m in each axis.,3279,16.62,16.87,-62.29,-62.08,1,0,9603,174,359,365,,,,,1
+827,1445,4605,4326,,"?",3297,17.06,17.46,-62.92,-62.5,1,0,9603,9,183,236,,,,,1
+828,15750,4605,4326,Derived at 2 stations.,"For military purposes. Accuracy 25m in each of X, Y and Z axes.",3297,17.06,17.46,-62.92,-62.5,1,0,9603,-7,215,225,,,,,0
+829,1446,4606,4326,,"?",3298,13.66,14.16,-61.13,-60.82,1,0,9603,-149,128,296,,,,,1
+830,6897,4606,4326,Derived at 3 stations.,For military purposes only. Accuracy 1m in each axis.,3298,13.66,14.16,-61.13,-60.82,1,0,9603,-153,153,307,,,,,0
+831,1959,4607,4326,Derived at 4 points.,1m accuracy.,3300,12.54,13.44,-61.52,-61.07,1,0,9603,195.671,332.517,274.607,,,,,1
diff --git a/data/default.rsc b/data/default.rsc
new file mode 100644
index 0000000..2fb03e8
Binary files /dev/null and b/data/default.rsc differ
diff --git a/data/ellipsoid.csv b/data/ellipsoid.csv
index abf56c6..0e0bb9d 100644
--- a/data/ellipsoid.csv
+++ b/data/ellipsoid.csv
@@ -1,5 +1,6 @@
 ellipsoid_code,ellipsoid_name,semi_major_axis,uom_code,inv_flattening,semi_minor_axis,ellipsoid_shape,remarks,information_source,data_source,revision_date,change_id,deprecated
 1024,CGCS2000,6378137,9001,298.257222101,,1,"Defining parameters semi-major axis, flattening and angular velocity are same as for GRS 1980 (ellipsoid code 7019); GM = 3986004.4e8 m*m*m/s/s (from NASA 1986 Lageos determination).",Chinese Academy of Surveying and Mapping.,OGP,2009/11/12,2009.084,0
+1025,GSK-2011,6378136.5,9001,298.2564151,,1,,"Parametry Zemli 1990 Reference Document, Military Topgraphic Department (VTU) of the General Staff of Armed Forces of the Russian Federation.",IOGP,2016/01/25,2015.055,0
 7001,Airy 1830,6377563.396,9001,299.3249646,,1,"Original definition is a=20923713, b=20853810 feet of 1796. 1/f is given to 7 decimal places. For the 1936 retriangulation OSGB defines the relationship of 10 feet of 1796 to the International metre through ([10^0.48401603]/10) exactly = 0.3048007491...",Ordnance Survey of Great Britain.,OGP,2006/11/27,1998.321 1998.340 2006.932,0
 7002,Airy Modified 1849,6377340.189,9001,299.3249646,,1,OSGB Airy 1830 figure (ellipsoid code 7001) rescaled by 0.999965 to best fit the scale of the 19th century primary triangulation of Ireland.,"""The Irish Grid - A Description of the Co-ordinate Reference System"" published by Ordnance Survey of Ireland, Dublin and Ordnance Survey of Northern Ireland, Belfast.",OGP,2003/06/27,1998.321 2002.622,0
 7003,Australian National Spheroid,6378160,9001,298.25,,1,Based on the GRS 1967 figure but with 1/f taken to 2 decimal places exactly.  The dimensions are also used as the GRS 1967 Modified ellipsoid (see code 7050).,"""Australian Map Grid Technical Manual""; National Mapping Council of Australia Special Publication #7; 1972",OGP,2008/08/11,2002.500 2008.017,0
@@ -46,7 +47,7 @@ ellipsoid_code,ellipsoid_name,semi_major_axis,uom_code,inv_flattening,semi_minor
 7051,Danish 1876,6377019.27,9001,300,,1,Semi-major axis originally given as 3271883.25 toise. Uses toise to French metre ratio of 1.94903631 to two decimal place precision. An alternative ratio with the German legal metre of 1.9490622 giving 6377104m has not been used in Danish work.,"Kort og Matrikelstyrelsen (KMS), Copenhagen.",OGP,2003/06/27,,0
 7052,Clarke 1866 Authalic Sphere,6370997,9001,,6370997,0,Authalic sphere derived from Clarke 1866 ellipsoid (code 7008).,OGP,OGP,2004/04/27,,0
 7053,Hough 1960,6378270,9001,297,,1,,DMA / NIMA / NGA TR8350.2,OGP,2006/01/26,,0
-7054,PZ-90,6378136,9001,298.257839303,,1,,"Geodeziya i Katografiya, 1993.",OGP,2006/02/03,,0
+7054,PZ-90,6378136,9001,298.257839303,,1,"Earth's angular velocity ? = 7.292115e-5 rad/sec; gravitational constant GM =  3986004.418e8 m*m*m/s/s.","Parametry Zemli 1990 Reference Document, Military Topgraphic Department (VTU) of the General Staff of Armed Forces of the Russian Federation.",IOGP,2016/12/15,2015.055,0
 7055,Clarke 1880 (international foot),20926202,9002,,20854895,1,Clark'es 1880 definition in feet assumed for the purposes of metric conversion to be international foot. a = 6378306.370…metres. 1/f derived from a and b = 293.4663077… Used in Fiji.,"Department of Lands and Survey, Fiji.",OGP,2006/07/14,,0
 7056,Everest 1830 (RSO 1969),6377295.664,9001,300.8017,,1,Adopted for 1969 metrication of peninsula Malaysia RSO grid.  Uses Sears 1922 yard-metre ratio truncated to 6 significant figures applied to Everest 1830 original definition of a and 1/f but with a taken to be in British rather than Indian feet.,Defence Geographic Centre,OGP,2006/07/24,,0
 7057,International 1924 Authalic Sphere,6371228,9001,,6371228,0,Authalic sphere derived from International 1924 ellipsoid (code 7022).,OGP,OGP,2006/09/22,,0
diff --git a/data/gcs.csv b/data/gcs.csv
index e78f240..4c403b3 100644
--- a/data/gcs.csv
+++ b/data/gcs.csv
@@ -80,7 +80,7 @@
 4146,Kalianpur 1975,6146,Kalianpur 1975,6146,9122,7045,8901,1,0,6422,1156,0,9603,295,736,257,,,,
 4147,Hanoi 1972,6147,Hanoi 1972,6147,9122,7024,8901,1,0,6422,1544,0,9603,-17.51,-108.32,-62.39,,,,
 4148,Hartebeesthoek94,6148,Hartebeesthoek94,6148,9122,7030,8901,1,0,6422,1505,0,9603,0,0,0,,,,
-4149,CH1903,6149,CH1903,6149,9122,7004,8901,1,0,6422,1766,1,9603,674.4,15.1,405.3,,,,
+4149,CH1903,6149,CH1903,6149,9122,7004,8901,1,0,6422,1510,1,9603,674.374,15.056,405.346,,,,
 4150,"CH1903+",6150,"CH1903+",6150,9122,7004,8901,1,0,6422,1676,0,9603,674.374,15.056,405.346,,,,
 4151,CHTRF95,6151,Swiss Terrestrial Reference Frame 1995,6151,9122,7019,8901,1,0,6422,1511,0,9603,0,0,0,,,,
 4152,"NAD83(HARN)",6152,"NAD83 (High Accuracy Reference Network)",6152,9122,7019,8901,1,0,6422,1580,1,9603,0,0,0,,,,
@@ -119,7 +119,7 @@
 4188,OSNI 1952,6188,OSNI 1952,6188,9122,7001,8901,1,0,6422,1955,0,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15
 4189,REGVEN,6189,Red Geodesica Venezolana,6189,9122,7019,8901,1,0,6422,1768,0,9603,0,0,0,,,,
 4190,POSGAR 98,6190,Posiciones Geodesicas Argentinas 1998,6190,9122,7019,8901,1,0,6422,1773,1,9603,0,0,0,,,,
-4191,Albanian 1987,6191,Albanian 1987,6191,9122,7024,8901,1,0,6422,6964,0,9607,-44.183,-0.58,-38.489,2.3867,2.7072,-3.5196,-8.2703
+4191,Albanian 1987,6191,Albanian 1987,6191,9122,7024,8901,1,0,6422,7834,1,9607,-44.183,-0.58,-38.489,-2.3867,-2.7072,3.5196,-8.2703
 4192,Douala 1948,6192,Douala 1948,6192,9122,7022,8901,1,0,6422,15873,0,9603,-206.1,-174.7,-87.7,,,,
 4193,Manoca 1962,6193,Manoca 1962,6193,9122,7011,8901,1,0,6422,1796,0,9603,-70.9,-151.8,-41.4,,,,
 4194,Qornoq 1927,6194,Qornoq 1927,6194,9122,7022,8901,1,0,6422,1797,1,9603,164,138,-189,,,,
@@ -216,7 +216,7 @@
 4286,Qatar 1948,6286,Qatar 1948,6286,9122,7020,8901,1,0,6422,,0,,,,,,,,
 4287,Qornoq,6287,Qornoq,6287,9108,7022,8901,1,1,6402,1211,0,9603,164,138,-189,,,,
 4288,Loma Quintana,6288,Loma Quintana,6288,9122,7022,8901,1,0,6422,,0,,,,,,,,
-4289,Amersfoort,6289,Amersfoort,6289,9122,7004,8901,1,0,6422,4833,1,9607,565.4171,50.3319,465.5524,0.398957,-0.343988,1.87740,4.0725
+4289,Amersfoort,6289,Amersfoort,6289,9122,7004,8901,1,0,6422,15934,1,9607,565.2369,50.0087,465.658,0.406857,-0.350733,1.87035,4.0812
 4291,SAD69,6291,South American Datum 1969,6291,9108,7036,8901,1,1,6402,1212,1,9603,-57,1,-41,,,,
 4292,Sapper Hill 1943,6292,Sapper Hill 1943,6292,9122,7022,8901,1,0,6422,1225,0,9603,-355,21,72,,,,
 4293,Schwarzeck,6293,Schwarzeck,6293,9122,7046,8901,1,0,6422,1226,1,9603,616,97,-251,,,,
@@ -355,7 +355,7 @@
 4707,Tern Island 1961,6707,Tern Island 1961,6707,9122,7022,8901,1,0,6422,15795,0,9603,114,-116,-333,,,,
 4708,Cocos Islands 1965,6708,Cocos Islands 1965,6708,9122,7003,8901,1,0,6422,15794,0,9603,-491,-22,435,,,,
 4709,Iwo Jima 1945,6709,Iwo Jima 1945,6709,9122,7022,8901,1,0,6422,15796,0,9603,145,75,-272,,,,
-4710,St. Helena 1971,6710,St. Helena 1971,6710,9122,7022,8901,1,0,6422,15798,0,9603,-320,550,-494,,,,
+4710,Astro DOS 71,6710,Astro DOS 71,6710,9122,7022,8901,1,0,6422,15798,1,9603,-320,550,-494,,,,
 4711,Marcus Island 1952,6711,Marcus Island 1952,6711,9122,7022,8901,1,0,6422,15799,0,9603,124,-234,-25,,,,
 4712,Ascension Island 1958,6712,Ascension Island 1958,6712,9122,7022,8901,1,0,6422,15797,0,9603,-205,107,53,,,,
 4713,Ayabelle Lighthouse,6713,Ayabelle Lighthouse,6713,9122,7012,8901,1,0,6422,6907,1,9603,-77,-128,142,,,,
@@ -385,7 +385,7 @@
 4737,Korea 2000,6737,Geocentric datum of Korea,6737,9122,7019,8901,1,0,6422,15831,0,9603,0,0,0,,,,
 4738,Hong Kong 1963,6738,Hong Kong 1963,6738,9122,7007,8901,1,0,6422,,0,,,,,,,,
 4739,"Hong Kong 1963(67)",6739,"Hong Kong 1963(67)",6739,9122,7022,8901,1,0,6422,15842,0,9603,-156,-271,-189,,,,
-4740,PZ-90,6740,Parametrop Zemp 1990,6740,9122,7054,8901,1,0,6422,15843,1,9607,0,0,1.5,0,0,-0.076,0
+4740,PZ-90,6740,Parametry Zemli 1990,6740,9122,7054,8901,1,0,6422,15843,1,9607,0,0,1.5,0,0,-0.076,0
 4741,FD54,6741,Faroe Datum 1954,6741,9122,7022,8901,1,0,6422,,0,,,,,,,,
 4742,GDM2000,6742,Geodetic Datum of Malaysia 2000,6742,9122,7019,8901,1,0,6422,,0,,,,,,,,
 4743,Karbala 1979,6743,Karbala 1979,6743,9122,7012,8901,1,0,6422,5078,1,9603,70.995,-335.916,262.898,,,,
@@ -411,7 +411,7 @@
 4763,Pitcairn 2006,6763,Pitcairn 2006,6763,9122,7030,8901,1,0,6422,15972,0,9603,0,0,0,,,,
 4764,RSRGD2000,6764,Ross Sea Region Geodetic Datum 2000,6764,9122,7019,8901,1,0,6422,15974,0,9603,0,0,0,,,,
 4765,Slovenia 1996,6765,Slovenia Geodetic Datum 1996,6765,9122,7019,8901,1,0,6422,15976,0,9603,0,0,0,,,,
-4801,"Bern 1898 (Bern)",6801,"CH1903 (Bern)",6149,9122,7004,8907,1,0,6422,1766,1,9603,674.4,15.1,405.3,,,,
+4801,"Bern 1898 (Bern)",6801,"CH1903 (Bern)",6149,9122,7004,8907,1,0,6422,1510,1,9603,674.374,15.056,405.346,,,,
 4802,"Bogota 1975 (Bogota)",6802,"Bogota 1975 (Bogota)",6218,9122,7022,8904,1,0,6422,1125,1,9603,307,304,-318,,,,
 4803,"Lisbon (Lisbon)",6803,"Lisbon 1937 (Lisbon)",6207,9122,7022,8902,1,0,6422,1984,1,9603,-304.046,-60.576,103.64,,,,
 4804,"Makassar (Jakarta)",6804,"Makassar (Jakarta)",6257,9122,7004,8908,1,0,6422,1837,0,9603,-587.8,519.75,145.76,,,,
@@ -447,7 +447,7 @@
 5264,DRUKREF 03,1058,Bhutan National Geodetic Datum,1058,9122,7019,8901,1,0,6422,5267,0,9603,0,0,0,,,,
 5324,ISN2004,1060,Islands Net 2004,1060,9122,7019,8901,1,0,6422,5327,0,9603,0,0,0,,,,
 5340,POSGAR 2007,1062,Posiciones Geodesicas Argentinas 2007,1062,9122,7019,8901,1,0,6422,5351,0,9603,0,0,0,,,,
-5354,MARGEN,1063,Marco Geodesico Nacional,1063,9122,7019,8901,1,0,6422,5374,0,9603,0,0,0,,,,
+5354,MARGEN,1063,Marco Geodesico Nacional de Bolivia,1063,9122,7019,8901,1,0,6422,5374,0,9603,0,0,0,,,,
 5360,SIRGAS-Chile,1064,SIRGAS-Chile,1064,9122,7019,8901,1,0,6422,5375,0,9603,0,0,0,,,,
 5365,CR05,1065,Costa Rica 2005,1065,9122,7030,8901,1,0,6422,5376,0,9603,0,0,0,,,,
 5371,MACARIO SOLIS,1066,Sistema Geodesico Nacional de Panama MACARIO SOLIS,1066,9122,7019,8901,1,0,6422,5377,0,9603,0,0,0,,,,
@@ -467,7 +467,7 @@
 5886,TGD2005,1095,Tonga Geodetic Datum 2005,1095,9122,7019,8901,1,0,6422,,0,,,,,,,,
 6135,CIGD11,1100,Cayman Islands Geodetic Datum 2011,1100,9122,7019,8901,1,0,6422,6177,0,9603,0,0,0,,,,
 6207,Nepal 1981,1111,Nepal 1981,1111,9122,7015,8901,1,0,6422,6208,0,9603,293.17,726.18,245.36,,,,
-6311,CGRS93,1112,Cyprus Geodetic Reference System 1993,1112,9122,7030,8901,1,0,6422,7445,0,9606,8.846,-4.394,-1.122,0.00237,0.146528,-0.130428,0.783926
+6311,CGRS93,1112,Cyprus Geodetic Reference System 1993,1112,9122,7030,8901,1,0,6422,7721,1,9607,8.846,-4.394,-1.122,0.00237,0.146528,-0.130428,0.783926
 6318,"NAD83(2011)",1116,"NAD83 (National Spatial Reference System 2011)",1116,9122,7019,8901,1,0,6422,,0,,,,,,,,
 6322,"NAD83(PA11)",1117,"NAD83 (National Spatial Reference System PA11)",1117,9122,7019,8901,1,0,6422,,0,,,,,,,,
 6325,"NAD83(MA11)",1118,"NAD83 (National Spatial Reference System MA11)",1118,9122,7019,8901,1,0,6422,,0,,,,,,,,
@@ -496,3 +496,9 @@
 7136,IGD05,1114,Israeli Geodetic Datum 2005,1114,9122,7030,8901,1,0,6422,,0,,,,,,,,
 7139,"IGD05/12",1115,"Israeli Geodetic Datum 2005(2012)",1115,9122,7030,8901,1,0,6422,,0,,,,,,,,
 7373,ONGD14,1147,Oman National Geodetic Datum 2014,1147,9122,7019,8901,1,0,6422,7443,0,9603,0,0,0,,,,
+7683,GSK-2011,1159,Geodezicheskaya Sistema Koordinat 2011,1159,9122,1025,8901,1,0,6422,,0,,,,,,,,
+7686,Kyrg-06,1160,Kyrgyzstan Geodetic Datum 2006,1160,9122,7019,8901,1,0,6422,,0,,,,,,,,
+7798,BGS2005,1167,Bulgaria Geodetic System 2005,1167,9122,7019,8901,1,0,6422,,0,,,,,,,,
+7844,GDA2020,1168,Geocentric Datum of Australia 2020,1168,9122,7019,8901,1,0,6422,,0,,,,,,,,
+7881,St. Helena Tritan,1173,St. Helena Tritan,1173,9122,7030,8901,1,0,6422,7898,0,9603,-0.077,0.079,0.086,,,,
+7886,SHGD2015,1174,St. Helena Geodetic Datum 2015,1174,9122,7019,8901,1,0,6422,7892,0,9603,0,0,0,,,,
diff --git a/data/gdal_datum.csv b/data/gdal_datum.csv
index 0b0310a..1484576 100644
--- a/data/gdal_datum.csv
+++ b/data/gdal_datum.csv
@@ -1,61 +1,61 @@
 "DATUM_CODE","DATUM_NAME","DATUM_TYPE","ORIGIN_DESCRIPTION","REALIZATION_EPOCH","ELLIPSOID_CODE","PRIME_MERIDIAN_CODE","AREA_OF_USE_CODE","DATUM_SCOPE","REMARKS","INFORMATION_SOURCE","DATA_SOURCE","REVISION_DATE","CHANGE_ID","DEPRECATED","ESRI_DATUM_NAME"
-1024,Hungarian Datum 1909,geodetic,"Fundamental point not given in information source, but presumably Szolohegy which is origin of later HD72.",1909,7004,8901,1119,Topographic mapping.,"Replaced earlier HD1863 adjustment also on Bessel ellipsoid. Both HD1863 and HD1909 were originally on Ferro Prime Meridian but subsequently converted to Greenwich. Replaced by HD72 (datum code 6237).","Timár, Molnár and Márta in Geodezia es Kartografia 55(3) pp16-21. www.fomi.hu/internet/magyar/szaklap/g [...]
-1025,Taiwan Datum 1967,geodetic,"Fundamental point: Hu Tzu Shan. Latitude: 23°58'32.34""N, longitude: 120°58'25.975""E (of Greenwich).",1967,7050,8901,3315,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Adopted in 1980. TWD67 uses the GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places.","National Land Surveying and Mapping Center (NLSC), http://www.nlsc.gov.tw",OGP,"2008/08/11",,0,"D_TWD_1967"
-1026,Taiwan Datum 1997,geodetic,ITRF94 at epoch 1997.0,1997,7019,8901,1228,"Geodetic survey, GIS, topographic mapping, engineering survey.",Adopted in 1998.,"National Land Surveying and Mapping Center (NLSC), http://www.nlsc.gov.tw",OGP,"2008/08/11",,0,"D_TWD_1997"
-1027,EGM2008 geoid,vertical,Derived through EGM2008 geoid undulation model consisting of spherical harmonic coefficients to degree 2190 and order 2159 applied to the WGS 84 ellipsoid.,2008,,,1262,Geodesy.,"Replaces EGM96 geoid (datum code 5171). See transformation codes 3858 and 3859 for 2.5x2.5 and 1x1 arc minute geoid undulation grid files derived from the spherical harmonic coefficients.","http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008/egm08_wgs84.html",IOGP,"2015/11/25",200 [...]
-1028,Fao 1979,vertical,"Average sea level at Fao during two-year period in mid/late 1970s.",1979,,,3625,"Topographic mapping, geodetic survey.","Levelling network established by Polservice consortium.  Replaces Fao (datum code 5149) in Iraq.","Survey Division, Ministry of Water Resources (MoWR).",OGP,"2010/03/01",2009.003 2010.014,0,
-1029,Iraqi Geospatial Reference System,geodetic,ITRF2000 at epoch 1997.0,2000,7019,8901,1124,Geodetic survey.,,"Survey Division, Ministry of Water Resources (MoWR).",OGP,"2009/02/03",2009.003,0,"D_Iraqi_Geospatial_Reference_System"
-1030,N2000,vertical,"Height at Metsaahovi (latitude 60.21762°N, longitude 24.39517°E) of 54.4233m related to EVRF2000 origin through Baltic Levelling Ring adjustment at epoch 2000.0.",2000,,,3333,"Topographic mapping, geodetic survey.","Realised through the third precise levelling network. Uses normal heights. Replaces N60 (datum code 5116). To account for isostatic land uplift use NKG2005 model.","National Land Survey of Finland;
+1024,Hungarian Datum 1909,geodetic,"Fundamental point not given in information source, but presumably Szolohegy which is origin of later HD72.",1909-01-01,7004,8901,1119,Topographic mapping.,"Replaced earlier HD1863 adjustment also on Bessel ellipsoid. Both HD1863 and HD1909 were originally on Ferro Prime Meridian but subsequently converted to Greenwich. Replaced by HD72 (datum code 6237).","Timár, Molnár and Márta in Geodezia es Kartografia 55(3) pp16-21. www.fomi.hu/internet/magyar/sza [...]
+1025,Taiwan Datum 1967,geodetic,"Fundamental point: Hu Tzu Shan. Latitude: 23°58'32.34""N, longitude: 120°58'25.975""E (of Greenwich).",1967-01-01,7050,8901,3315,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Adopted in 1980. TWD67 uses the GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places.","National Land Surveying and Mapping Center (NLSC), http://www.nlsc.gov.tw",OGP,"2008/08/11",,0,"D_TWD_1967"
+1026,Taiwan Datum 1997,geodetic,ITRF94 at epoch 1997.0,1997-01-01,7019,8901,1228,"Geodetic survey, GIS, topographic mapping, engineering survey.",Adopted in 1998.,"National Land Surveying and Mapping Center (NLSC), http://www.nlsc.gov.tw",OGP,"2008/08/11",,0,"D_TWD_1997"
+1027,EGM2008 geoid,vertical,Derived through EGM2008 geoid undulation model consisting of spherical harmonic coefficients to degree 2190 and order 2159 applied to the WGS 84 ellipsoid.,2008-01-01,,,1262,Geodesy.,"Replaces EGM96 geoid (datum code 5171). See transformation codes 3858 and 3859 for 2.5x2.5 and 1x1 arc minute geoid undulation grid files derived from the spherical harmonic coefficients.","http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008/egm08_wgs84.html",IOGP,"2015/11/2 [...]
+1028,Fao 1979,vertical,"Average sea level at Fao during two-year period in mid/late 1970s.",1979-01-01,,,3625,"Topographic mapping, geodetic survey.","Levelling network established by Polservice consortium.  Replaces Fao (datum code 5149) in Iraq.","Survey Division, Ministry of Water Resources (MoWR).",OGP,"2010/03/01",2009.003 2010.014,0,
+1029,Iraqi Geospatial Reference System,geodetic,ITRF2000 at epoch 1997.0,1997-01-01,7019,8901,1124,Geodetic survey.,,"Survey Division, Ministry of Water Resources (MoWR).",IOGP,"2016/09/16",2009.003 2016.020,0,"D_Iraqi_Geospatial_Reference_System"
+1030,N2000,vertical,"Height at Metsaahovi (latitude 60.21762°N, longitude 24.39517°E) of 54.4233m related to EVRF2000 origin through Baltic Levelling Ring adjustment at epoch 2000.0.",2000-01-01,,,3333,"Topographic mapping, geodetic survey.","Realised through the third precise levelling network. Uses normal heights. Replaces N60 (datum code 5116). To account for isostatic land uplift use NKG2005 model.","National Land Survey of Finland;
 http://www.maanmittauslaitos.fi",OGP,"2009/02/21",2008.112,0,
-1031,MGI 1901,geodetic,"Fundamental point: Hermannskogel. Latitude: 48°16'15.29""N, longitude: 16°17'55.04""E (of Greenwich).",1901,7004,8901,2370,Geodetic survey.,"The longitude of the datum origin equates to the Albrecht 1902 value for the Ferro meridian of 17°39'46.02"" west of Greenwich. Densified in 1948.","The Ferro prime meridian, Gabor Timar (2007), Geodezia es Kartografia vol 59 issue 12 pages 3-7.",OGP,"2009/05/10",2009.015,0,"D_MGI_1901"
-1032,MOLDREF99,geodetic,Densification of ETRS89.,1999,7019,8901,1162,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"State Agency for Land Relations & Cadastre.",OGP,"2009/05/11",2009.026,0,"D_MOLDREF99"
-1033,Reseau Geodesique de la RDC 2005,geodetic,ITRF2000 at epoch 2005.4.,2005,7019,8901,3613,Geodetic survey.,,"""Revision du Tiers Meridional du Reseau Geodesique de la RDC"", COPIREP Reclus project report, 2005.",OGP,"2009/04/16",2009.011,0,"D_Reseau_Geodesique_de_la_RDC_2005"
-1034,Serbian Reference Network 1998,geodetic,"Densification of ETRS89 in Serbia at epoch 1998.7 based on coordinates of 6 stations in Serbia of Yugoslav Reference Frame (YUREF) 1998 campaign.",1998,7019,8901,3534,Geodesy.,Observed 1998-2003.,"Delcev et al, FIG Working Week May 2009; http://www.gig.net/pub",OGP,"2009/05/11",2009.015,0,"D_Serbian_Reference_Network_1998"
-1035,Red Geodesica de Canarias 1995,geodetic,ITRF93 at epoch 1994.9 at VLBI station Maspalomas on Grand Canary.,1995,7019,8901,3199,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Pico de las Nieves 1984 (PN84).","IGN Madrid. http://www.fomento.es.",OGP,"2009/05/15",2009.033,0,"D_Red_Geodesica_de_Canarias_1995"
-1036,Reseau Geodesique de Mayotte 2004,geodetic,ITRF2000 at epoch 2004.0,2004,7019,8901,1159,"Geodetic survey, topographic mapping, engineering survey.","Replaces Combani 1950 (datum code 6632) except for cadastral purposes. (Cadastre 1997 (datum code 1037) used for cadastral purposes).",IGN Paris.,OGP,"2009/10/02",2009.072,0,"D_Reseau_Geodesique_de_Mayotte_2004"
-1037,Cadastre 1997,geodetic,Coordinates of 1 station of Combani 1950 adjustment held fixed.,1997,7022,8901,3340,Cadastral survey.,Derived by adjustment of GPS-observed network which was constrained to Combani 1950 coordinates of one station.,CERTU.,OGP,"2009/10/02",2009.072,0,"D_Cadastre_1997"
-1038,Reseau Geodesique de Saint Pierre et Miquelon 2006,geodetic,ITRF2000 at epoch 2006.0,2006,7019,8901,1220,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Saint Pierre et Miquelon 1950 (datum code 6638).",IGN Paris.,OGP,"2009/10/02",2009.072,0,"D_Reseau_Geodesique_de_St_Pierre_et_Miquelon_2006"
-1039,New Zealand Vertical Datum 2009,vertical,New Zealand Quasigeoid 2009 which is defined by the application of the NZ geoid 2009 grid to NZGD2000 ellipsoidal heights. See transformation code 4459.,2009,,,1175,"Geodetic survey, topographic mapping, engineering survey.",,"Land Information New Zealand (LINZ) standard S25004.",OGP,"2012/01/21",2009.081 2011.004 2012.007,0,
-1040,Dunedin-Bluff 1960,vertical,Common adjustment of Dunedin 1958 and Bluff 1955 networks.,1960,,,3806,"Geodetic survey, topographic mapping, engineering survey.",,"Land Information New Zealand (LINZ) standard S25004.",OGP,"2011/01/25",2009.081 2011.005,0,
-1041,Autonomous Regions of Portugal 2008,geodetic,"ITRF93 as derived from the 1994 TransAtlantic Network for Geodynamics and Oceanography (TANGO) project.",1994,7019,8901,3670,Geodetic survey.,Replaces older classical datums for Azores and Madeira archipelagos.,"Instituto Geografico Portugues; http://www.igeo.pt",OGP,"2010/03/30",2010.006,0,"D_PTRA08"
-1042,Mexico ITRF92,geodetic,ITRF1992 at epoch 1988.00.,1993,7019,8901,1160,Geodetic survey.,"Realised by a frame of 15 active GPS stations observed and adjusted in the ITRF1992. Includes ties to tide gauges. Replaces NAD27 (datum code 6267). Replaced by Mexico ITRF2008 (datum code 1120) from December 2010.","National Densifications per http://www.sirgas.org. See also www.fig.net/pub/cairo/papers/ts_13/ts13_03_hansen.pdf.",OGP,"2013/08/23",2009.087 2010.090 2013.032,0,"D_Mexican_Datum_of_1993"
-1043,China 2000,geodetic,ITRF97 at epoch 2000.0,2000,1024,8901,1067,"Geodetic survey, topographic and engineering survey.",Combined adjustment of astro-geodetic observations as used for Xian 1980 and GPS control network observed 2000-2003. Adopted July 2008.,Chinese Academy of Surveying and Mapping.,OGP,"2012/01/05",2009.084 2011.103,0,"D_China_2000"
+1031,MGI 1901,geodetic,"Fundamental point: Hermannskogel. Latitude: 48°16'15.29""N, longitude: 16°17'55.04""E (of Greenwich).",1901-01-01,7004,8901,2370,Geodetic survey.,"The longitude of the datum origin equates to the Albrecht 1902 value for the Ferro meridian of 17°39'46.02"" west of Greenwich. Densified in 1948.","The Ferro prime meridian, Gabor Timar (2007), Geodezia es Kartografia vol 59 issue 12 pages 3-7.",OGP,"2009/05/10",2009.015,0,"D_MGI_1901"
+1032,MOLDREF99,geodetic,Densification of ETRS89.,1999-01-01,7019,8901,1162,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"State Agency for Land Relations & Cadastre.",OGP,"2009/05/11",2009.026,0,"D_MOLDREF99"
+1033,Reseau Geodesique de la RDC 2005,geodetic,ITRF2000 at epoch 2005.4.,2005-05-26,7019,8901,3613,Geodetic survey.,,"""Revision du Tiers Meridional du Reseau Geodesique de la RDC"", COPIREP Reclus project report, 2005.",IOGP,"2016/09/16",2009.011 2016.020,0,"D_Reseau_Geodesique_de_la_RDC_2005"
+1034,Serbian Reference Network 1998,geodetic,"Densification of ETRS89 in Serbia at epoch 1998.7 based on coordinates of 6 stations in Serbia of Yugoslav Reference Frame (YUREF) 1998 campaign.",1998-09-13,7019,8901,3534,Geodesy.,Observed 1998-2003.,"Delcev et al, FIG Working Week May 2009; http://www.gig.net/pub",IOGP,"2016/09/16",2009.015 2016.020,0,"D_Serbian_Reference_Network_1998"
+1035,Red Geodesica de Canarias 1995,geodetic,ITRF93 at epoch 1994.9 at VLBI station Maspalomas on Grand Canary.,1994-11-24,7019,8901,3199,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Pico de las Nieves 1984 (PN84).","IGN Madrid. http://www.fomento.es.",IOGP,"2016/09/16",2009.033 2016.020,0,"D_Red_Geodesica_de_Canarias_1995"
+1036,Reseau Geodesique de Mayotte 2004,geodetic,ITRF2000 at epoch 2004.0,2004-01-01,7019,8901,1159,"Geodetic survey, topographic mapping, engineering survey.","Replaces Combani 1950 (datum code 6632) except for cadastral purposes. (Cadastre 1997 (datum code 1037) used for cadastral purposes).",IGN Paris.,OGP,"2009/10/02",2009.072,0,"D_Reseau_Geodesique_de_Mayotte_2004"
+1037,Cadastre 1997,geodetic,Coordinates of 1 station of Combani 1950 adjustment held fixed.,1997-01-01,7022,8901,3340,Cadastral survey.,Derived by adjustment of GPS-observed network which was constrained to Combani 1950 coordinates of one station.,CERTU.,OGP,"2009/10/02",2009.072,0,"D_Cadastre_1997"
+1038,Reseau Geodesique de Saint Pierre et Miquelon 2006,geodetic,ITRF2000 at epoch 2006.0,2006-01-01,7019,8901,1220,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Saint Pierre et Miquelon 1950 (datum code 6638).",IGN Paris.,OGP,"2009/10/02",2009.072,0,"D_Reseau_Geodesique_de_St_Pierre_et_Miquelon_2006"
+1039,New Zealand Vertical Datum 2009,vertical,New Zealand Quasigeoid 2009 which is defined by the application of the NZ geoid 2009 grid to NZGD2000 ellipsoidal heights. See transformation code 4459.,2009-01-01,,,1175,"Geodetic survey, topographic mapping, engineering survey.",,"Land Information New Zealand (LINZ) standard S25004.",OGP,"2012/01/21",2009.081 2011.004 2012.007,0,
+1040,Dunedin-Bluff 1960,vertical,Common adjustment of Dunedin 1958 and Bluff 1955 networks.,1960-01-01,,,3806,"Geodetic survey, topographic mapping, engineering survey.",,"Land Information New Zealand (LINZ) standard S25004.",OGP,"2011/01/25",2009.081 2011.005,0,
+1041,Autonomous Regions of Portugal 2008,geodetic,"ITRF93 as derived from the 1994 TransAtlantic Network for Geodynamics and Oceanography (TANGO) project.",1994-01-01,7019,8901,3670,Geodetic survey.,Replaces older classical datums for Azores and Madeira archipelagos.,"Instituto Geografico Portugues; http://www.igeo.pt",OGP,"2010/03/30",2010.006,0,"D_PTRA08"
+1042,Mexico ITRF92,geodetic,ITRF1992 at epoch 1988.00.,1988-01-01,7019,8901,1160,Geodetic survey.,"Realised by a frame of 15 active GPS stations observed and adjusted in the ITRF1992. Includes ties to tide gauges. Replaces NAD27 (datum code 6267). Replaced by Mexico ITRF2008 (datum code 1120) from December 2010.","National Densifications per http://www.sirgas.org. See also www.fig.net/pub/cairo/papers/ts_13/ts13_03_hansen.pdf.",IOGP,"2016/09/16",2009.087 2010.090 2013.032 2016.020,0,"D_M [...]
+1043,China 2000,geodetic,ITRF97 at epoch 2000.0,2000-01-01,1024,8901,1067,"Geodetic survey, topographic and engineering survey.",Combined adjustment of astro-geodetic observations as used for Xian 1980 and GPS control network observed 2000-2003. Adopted July 2008.,Chinese Academy of Surveying and Mapping.,OGP,"2012/01/05",2009.084 2011.103,0,"D_China_2000"
 1044,Sao Tome,geodetic,"Fundamental point: Fortaleza. Latitude: 0°20'49.02""N, longitude: 6°44'41.85""E (of Greenwich).",,7022,8901,3645,"Topographic mapping, geodetic survey.",,"US Department of State Bureau of Intelligence and Research ""Limits in the Sea"" series #98.",OGP,"2009/11/24",2009.098,0,"D_Sao_Tome"
-1045,New Beijing,geodetic,Derived by conformal transformation of Xian 1980 adjustment onto Krassowsky ellipsoid.,1982,7024,8901,3228,Topographic mapping.,From 1982 replaces Beijing 1954.,"Chinese Science Bulletin, 2009, 54:2714-2721.",OGP,"2010/03/01",2009.092 2010.014,0,"D_New_Beijing"
+1045,New Beijing,geodetic,Derived by conformal transformation of Xian 1980 adjustment onto Krassowsky ellipsoid.,1982-01-01,7024,8901,3228,Topographic mapping.,From 1982 replaces Beijing 1954.,"Chinese Science Bulletin, 2009, 54:2714-2721.",OGP,"2010/03/01",2009.092 2010.014,0,"D_New_Beijing"
 1046,Principe,geodetic,"Fundamental point: Morro do Papagaio. Latitude: 1°36'46.87""N, longitude: 7°23'39.65""E (of Greenwich).",,7022,8901,3646,"Topographic mapping, geodetic survey.",,"US Department of State Bureau of Intelligence and Research ""Limits in the Sea"" series #98.",OGP,"2009/11/24",2009.098,0,"D_Principe"
-1047,Reseau de Reference des Antilles Francaises 1991,geodetic,WGS 84 coordinates of a single station determined during the 1988 Tango mission.,1991,7019,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Fort Marigot and Sainte Anne (datum codes 6621-22) in Guadeloupe and Fort Desaix (datum code 6625) in Martinique. Replaced by Reseau Geodesique des Antilles Francaises 2009 (datum code 1073).",IGN Paris.,OGP,"2011/05/09",2009.073 2011.030,0,"D_RRAF_1991"
-1048,Tokyo 1892,geodetic,"Fundamental point: Nikon-Keido-Genten. Latitude: 35°39'17.5148""N, longitude: 139°44'30.0970""E (of Greenwich). Longitude derived in 1892.",1892,7004,8901,1364,"Cadastre, topographic mapping, engineering survey.","Extended from Japan to Korea in 1898. In Japan replaced by Tokyo 1918 (datum code 6301). In South Korea replaced by Tokyo 1918 (code 6301) only for geodetic purposes; for all other purposes replaced by Korean 1985 (code 6162).",Korean Association of Su [...]
-1049,Incheon,vertical,MSL 1913-1916 at Incheon Bay.,1963,,,3739,"Topographic mapping, geodetic survey.",,"National Geographic Information Institute (NGII).",OGP,"2010/06/30",2010.050,0,
-1050,Trieste,vertical,"Reference point HM1(BV1)-Trieste defined relative to mean sea level at Trieste in 1875.",1875,,,2370,"Geodetic survey, topographic mapping, engineering survey.","Normal-orthometric heights. In Croatia replaced by HVRS71 (datum code 5207).","Eurogeographics, http://www.crs-geo.eu",OGP,"2010/07/12",2010.064,0,
-1051,Genoa,vertical,,1942,,,3736,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://www.crs-geo.eu",OGP,"2010/07/12",2010.064,0,
-1052,"System Jednotne Trigonometricke Site Katastralni/05",geodetic,Constrained to S-JTSK but realised through readjustment in projected CRS domain. Related to ETRS89 R05 realisation through transformation code 5226.,2009,7004,8901,1079,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Land Survey Office (ZU), Prague. www.cuzk.cz/zu",OGP,"2010/10/29",2010.071,0,"D_S_JTSK_05"
-1053,Sri Lanka Datum 1999,geodetic,"Fundamental point: ISM Diyatalawa. Latitude: 6°49'02.687""N, longitude: 80°57'40.880""E.",1999,7015,8901,3310,Topographic mapping.,Introduced in 2000.,"Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/08/07",2010.080,0,"D_Sri_Lanka_Datum_1999"
-1054,Sri Lanka Vertical Datum,vertical,MSL at Colombo 1884-1889.,1932,,,3310,"Geodetic survey, topographic mapping, engineering survey.","Normal-orthometric heights, but often referred to as ""orthometric"".","Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/08/07",2010.080,0,
-1055,"System Jednotne Trigonometricke Site Katastralni/05 (Ferro)",geodetic,Constrained to S-JTSK but realised through readjustment in projected CRS domain.,2009,7004,8909,1079,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Land Survey Office (ZU), Prague. www.cuzk.cz/zu",OGP,"2010/10/29",2010.071,0,"D_S_JTSK_05"
-1056,Geocentric Datum Brunei Darussalam 2009,geodetic,ITRF2005 at epoch 2009.45,2009,7019,8901,1055,Geodetic survey.,Replaces use of Timbalai from July 2009.,"Survey Department, Brunei.",OGP,"2010/09/22",2010.057,0,"D_GDBD2009"
-1057,Turkish National Reference Frame,geodetic,ITRF96 at epoch 2005.0,2005,7019,8901,1237,Geodetic survey.,,"General Command of Mapping via EuroGeographics; http://www.crs-geo.eu/",OGP,"2010/09/06",2010.085,0,"D_Turkish_National_Reference_Frame"
-1058,Bhutan National Geodetic Datum,geodetic,ITRF2000 at epoch 2003.87,2000,7019,8901,1048,Geodetic survey.,,"Department of Survey and Land Records (DSLR), National Land Commission of Bhutan (NLC) via Lantmäteriet Sweden.",OGP,"2010/09/06",2010.086,0,"D_Bhutan_National_Geodetic_Datum"
-1059,Faroe Islands Vertical Reference 2009,vertical,,2009,,,3248,Topographic mapping and engineering survey,Mean Tidal Height System.,"Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2010/10/27",2010.092,0,
-1060,Islands Net 2004,geodetic,ITRF2000 at epoch 2004.6.,2004,7019,8901,1120,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces ISN93 (datum code 6659).","Landmaelingar Islands (National Land Survey of Iceland). http://www.lmi.is",OGP,"2010/11/12",2010.101,0,"D_Islands_Network_2004"
-1061,International Terrestrial Reference Frame 2008,geodetic,Origin at geocentre. The ITRF2008 origin is defined in such a way that there are null translation parameters at epoch 2005.0 and null translation rates between the ITRF2008 and the ILRS SLR time series.,2005,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from 2012. Replaces ITRF2005 (code 6896).","International Earth Rotation Service (IERS) Technical Note No. 37, published in 2012. Also at  [...]
-1062,Posiciones Geodesicas Argentinas 2007,geodetic,"A geodetic network of 211 high accuracy surveyed points (178 passive and 33 continuous operating) based on ITRF2005, Epoch 2006.6, that define the National Geodetic System (Sistema Geodésico Nacional) effective 15 May 2009.",2009,7019,8901,1033,"Topographic mapping, geodetic survey.","POSGAR 07 has been adopted by order of the Director of the National Geographic Institute on May 15, 2009, as the new National Geodetic Reference Frame an [...]
-1063,Marco Geodesico Nacional,geodetic,"ITRF94 at epoch 1995.4.  Densification of SIRGAS95 network in Bolivia, consisting of 125 passive geodetic stations and 8 continuous recording GPS stations.",2007,7019,8901,1049,Geodetic survey.,"Densification of SIRGAS 1995 within Bolivia. Replaces PSAD56 (datum code 6248) in Bolivia.","Sistema de Referencia Geocentrico para las Americas (SIRGAS) Boletin Informativo No 12, Aug 2007 and www.sirgas.org/fileadmin/docs/Boletines/Bol12/09_Actividades_SI [...]
-1064,SIRGAS-Chile,geodetic,"ITRF2000 at epoch 2002.0.  Densification of SIRGAS 2000 network in Chile, consisting of 650 monumented stations.",2007,7019,8901,1066,Geodetic survey.,"Densification of SIRGAS 2000 within Chile. Replaces PSAD56 (datum code 6248) in Chile, replaces HITO XVIII (datum code 6254) in Chilean Tierra del Fuego and replaces Easter Island 1967 (datum code 6719)  in Easter Island.","IGM Chile Report: 31_Parra_Baez_Chilean_part_of_SIRGAS.pdf on sirgas.org website (www.si [...]
-1065,Costa Rica 2005,geodetic,"ITRF2000 at epoch 2005.8.  Network of 34 GPS stations throughout the country, five of which were connected to four Caribbean area ITRF stations.",2005,7030,8901,1074,Geodetic survey.,"Replaces Ocotepeque (datum code 1070) in Costa Rica from March 2007.","Instituto Geografico Nacional Costa Rica report: El Sistema de Referencia CR05 y la Proyeccion Transversal de Mercator para Costa Rica CRTM05. (Report available through www.sirgas.org website in national ne [...]
-1066,Sistema Geodesico Nacional de Panama MACARIO SOLIS,geodetic,"ITRF2000 at epoch 2000.0. Densification of SIRGAS 2000 network in Panama, consisting of 20 GPS stations throughout the country.",,7019,8901,1186,Geodetic survey.,,Details taken from summary on national networks list on www.sirgas.org website.,OGP,"2011/03/20",2011.018,0,"D_SGNP_MARCARIO_SOLIS"
-1067,Peru96,geodetic,"ITRF94 at epoch 1995.4.  Densification of SIRGAS95 network in Peru, consisting of 47 passive geodetic stations and 3 continuous recording GPS stations.",1996,7019,8901,1189,Geodetic survey.,"Densification of SIRGAS 1995 within Peru. Replaces PSAD56 (datum code 6248) in Peru.","Details taken from national realizations page of WWW.SIRGAS.ORG, confirmed by reports from IGN Peru.",OGP,"2011/03/20",2011.018,0,"D_Peru96"
-1068,SIRGAS-ROU98,geodetic,"ITRF94 at epoch 1995.4.  Densification of SIRGAS95 network in Uruguay, consisting of 17 passive geodetic stations and 3 continuous recording GPS stations.",1998,7030,8901,1247,Geodetic survey.,"Densification of SIRGAS 1995 within Uruguay. Replaces Yacare (datum code 6309) in Uruguay. Uruguay documentation clearly states use of WGS 84 reference ellipsoid.","Sistema de Referencia Geocentrico para las Americas: SIRGAS, Boletin Informativo No 12, Aug 2007; www.sir [...]
-1069,"SIRGAS_ES2007.8",geodetic,"ITRF2005 at epoch 2007.8.  Densification of SIRGAS-CON network in El Salvador, consisting of 38 monumented stations.",2007,7019,8901,1087,Geodetic survey.,SIRGAS-ES2007.8 is the national SIRGAS densification.,"Integration of the reference frame of El Salvador into SIRGAS (SIRGAS-ES2007.8) report by GG-IGCN (El Salvador) & DGFI (Germany) available from www.sirgas.org.  (Information also summarised on www.sirgas.org website national networks list).",OGP,"20 [...]
-1070,Ocotepeque 1935,geodetic,"Fundamental point: Base Norte. Latitude: 14°26'20.168""N, longitude: 89°11'33.964""W.",1935,7008,8901,3876,Topographic mapping and engineering survey.,"Replaced in Costa Rica by Costa Rica 2005 (CR05) from March 2007 and replaced in El Salvador by SIRGAS_ES2007 from August 2007.","Clifford Mugnier's PE&RS articles on Belize, Costa Rica, El Salvador, Guatemala, Honduras, Nicaragua, Panama (www.asprs.org/resources/grids/) also substantiated in IGN Costa Rica  [...]
-1071,Sibun Gorge 1922,geodetic,"Latitude: 17º03'40.471""N, longitude: 88º37'54.687""W.",1922,7007,8901,3219,Topographic mapping and engineering survey.,,"Clifford Mugnier's March 2009 PE&RS ""Grids and Datums"" article on Belize (www.asprs.org/resources/grids/).",OGP,"2011/03/26",2011.026,0,"D_Sibun_Gorge_1922"
-1072,Panama-Colon 1911,geodetic,"Fundamental point: Balboa Hill. Latitude: 09°04'57.637""N, longtitude: 79°43'50.313""W.",1911,7008,8901,3290,Topographic mapping and engineering survey.,"Reports of the existence of an Ancon datum are probably erroneous, considering that the origin of the Panamá-Colón Datum of 1911 is at Balboa Hill and the access road up the hill is from the town of Ancon, Canal Zone.","Clifford Mugnier's PE&RS July 1999 Grids and Datums article on The Republic of Panama [...]
-1073,Reseau Geodesique des Antilles Francaises 2009,geodetic,ITRF2005 at epoch 2009.0,2009,7019,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.",Replaces RRAF91 in Martinique and Guadeloupe.,IGN Paris.,OGP,"2011/03/23",2011.030,0,"Reseau_Geodesique_des_Antilles_Francaises_2009"
-1074,Corrego Alegre 1961,geodetic,"Fundamental point: Corrego Alegre. Latitude: 19°50'14.91""S, longitude: 48°57'41.98""W (of Greenwich).",1961,7022,8901,3874,"Topographic mapping, geodetic survey.","Replaced by Corrego Alegre 1970-72 (datum code 6225). NIMA gives coordinates of origin as latitude: 19°50'15.14""S, longitude: 48°57'42.75""W.",IBGE,OGP,"2011/07/10",2011.053,0,"D_Corrego_Alegre_1961"
-1075,"South American Datum 1969(96)",geodetic,"Fundamental point: Chua. Geodetic latitude: 19°45'41.6527""S; geodetic longitude: 48°06'04.0639""W (of Greenwich). (Astronomic coordinates: Latitude 19°45'41.34""S +/- 0.05"", longitude 48°06'07.80""W +/- 0.08"").",1996,7050,8901,1053,Topographic mapping.,"SAD69 uses GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places. Replaces original 1969 adjustment (datum code 6618) in Brazil.",IBGE.,OGP,"2012/11/26",2011.053 2012.070,0,"D_South_ [...]
-1076,Papua New Guinea Geodetic Datum 1994,geodetic,ITRF92 at epoch 1994.0.,1994,7019,8901,1187,"Topographic mapping, geodetic, engineering and cadastral survey.",Adopted 1996. Coincident with WGS 84 in 1994 but rapidly divergent due to significant tectonic motion in PNG.,"Quickclose Geomatics and http://www.aspng.org/techinfopng94.htm",OGP,"2011/07/15",2011.059,0,"D_Papua_New_Guinea_Geodetic_Datum_1994"
-1077,Ukraine 2000,geodetic,Orientation and scale constrained to be same as ITRF2000 at epoch 2005.0. Position is minimised deviation between reference ellipsoid and quasigeoid in territory of Ukraine.,2005,7024,8901,1242,Geodesy.,,"Berlin 2008 GNSS Symposium paper 4-7 (""Creation of ZAKPOS active Network Reference Stations for Transcarpathian Region of Ukraine"") by Savchuk et al.",OGP,"2012/12/17",2011.044 2012.087,0,"D_Ukraine_2000"
-1078,Fehmarnbelt Datum 2010,geodetic,ITRF2005 at epoch 2010.14.,2010,7019,8901,3889,Engineering survey and construction of Fehmarnbelt tunnel.,Defined through coordinates of four permanant GNSS stations.,"Femern A/S.",OGP,"2011/09/23",2011.083,0,"D_Fehmarnbelt_Datum_2010"
-1079,Fehmarnbelt Vertical Reference 2010,vertical,"Realised by precise levelling between tide gauges at Marienleuchte (Germany), Rodbyhavn (Denmark) and four Fehmarnbelt project GNSS stations.",2010,,,3890,Engineering survey and construction of Fehmarnbelt tunnel.,,"Femern A/S",OGP,"2011/09/24",2011.083,0,
+1047,Reseau de Reference des Antilles Francaises 1991,geodetic,WGS 84 coordinates of a single station determined during the 1988 Tango mission.,1991-01-01,7019,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Fort Marigot and Sainte Anne (datum codes 6621-22) in Guadeloupe and Fort Desaix (datum code 6625) in Martinique. Replaced by Reseau Geodesique des Antilles Francaises 2009 (datum code 1073).",IGN Paris.,OGP,"2011/05/09",2009.073 2011.030,0," [...]
+1048,Tokyo 1892,geodetic,"Fundamental point: Nikon-Keido-Genten. Latitude: 35°39'17.5148""N, longitude: 139°44'30.0970""E (of Greenwich). Longitude derived in 1892.",1892-01-01,7004,8901,1364,"Cadastre, topographic mapping, engineering survey.","Extended from Japan to Korea in 1898. In Japan replaced by Tokyo 1918 (datum code 6301). In South Korea replaced by Tokyo 1918 (code 6301) only for geodetic purposes; for all other purposes replaced by Korean 1985 (code 6162).",Korean Association [...]
+1049,Incheon,vertical,MSL 1913-1916 at Incheon Bay.,1963-01-01,,,3739,"Topographic mapping, geodetic survey.",,"National Geographic Information Institute (NGII).",OGP,"2010/06/30",2010.050,0,
+1050,Trieste,vertical,"Reference point HM1(BV1)-Trieste defined relative to mean sea level at Trieste in 1875.",1875-01-01,,,2370,"Geodetic survey, topographic mapping, engineering survey.","Normal-orthometric heights. In Croatia replaced by HVRS71 (datum code 5207).","Eurogeographics, http://www.crs-geo.eu",OGP,"2010/07/12",2010.064,0,
+1051,Genoa,vertical,,1942-01-01,,,3736,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://www.crs-geo.eu",OGP,"2010/07/12",2010.064,0,
+1052,"System Jednotne Trigonometricke Site Katastralni/05",geodetic,Constrained to S-JTSK but realised through readjustment in projected CRS domain. Related to ETRS89 R05 realisation through transformation code 5226.,2009-01-01,7004,8901,1079,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Land Survey Office (ZU), Prague. www.cuzk.cz/zu",OGP,"2010/10/29",2010.071,0,"D_S_JTSK_05"
+1053,Sri Lanka Datum 1999,geodetic,"Fundamental point: ISM Diyatalawa. Latitude: 6°49'02.687""N, longitude: 80°57'40.880""E.",1999-01-01,7015,8901,3310,Topographic mapping.,Introduced in 2000.,"Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/08/07",2010.080,0,"D_Sri_Lanka_Datum_1999"
+1054,Sri Lanka Vertical Datum,vertical,MSL at Colombo 1884-1889.,1932-01-01,,,3310,"Geodetic survey, topographic mapping, engineering survey.","Normal-orthometric heights, but often referred to as ""orthometric"".","Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/08/07",2010.080,0,
+1055,"System Jednotne Trigonometricke Site Katastralni/05 (Ferro)",geodetic,Constrained to S-JTSK but realised through readjustment in projected CRS domain.,2009-01-01,7004,8909,1079,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Land Survey Office (ZU), Prague. www.cuzk.cz/zu",OGP,"2010/10/29",2010.071,0,"D_S_JTSK_05"
+1056,Geocentric Datum Brunei Darussalam 2009,geodetic,ITRF2005 at epoch 2009.45,2009-06-13,7019,8901,1055,Geodetic survey.,Replaces use of Timbalai from July 2009.,"Survey Department, Brunei.",IOGP,"2016/09/16",2010.057 2016.020,0,"D_GDBD2009"
+1057,Turkish National Reference Frame,geodetic,ITRF96 at epoch 2005.0,2005-01-01,7019,8901,1237,Geodetic survey.,,"General Command of Mapping via EuroGeographics; http://www.crs-geo.eu/",OGP,"2010/09/06",2010.085,0,"D_Turkish_National_Reference_Frame"
+1058,Bhutan National Geodetic Datum,geodetic,ITRF2000 at epoch 2003.87,2003-11-14,7019,8901,1048,Geodetic survey.,,"Department of Survey and Land Records (DSLR), National Land Commission of Bhutan (NLC) via Lantmäteriet Sweden.",IOGP,"2016/09/16",2010.086 2016.020,0,"D_Bhutan_National_Geodetic_Datum"
+1059,Faroe Islands Vertical Reference 2009,vertical,,2009-01-01,,,3248,Topographic mapping and engineering survey,Mean Tidal Height System.,"Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2010/10/27",2010.092,0,
+1060,Islands Net 2004,geodetic,ITRF2000 at epoch 2004.6.,2004-08-07,7019,8901,1120,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces ISN93 (datum code 6659).","Landmaelingar Islands (National Land Survey of Iceland). http://www.lmi.is",IOGP,"2016/09/16",2010.101 2016.020,0,"D_Islands_Network_2004"
+1061,International Terrestrial Reference Frame 2008,geodetic,Origin at geocentre. The ITRF2008 origin is defined in such a way that there are null translation parameters at epoch 2005.0 and null translation rates between the ITRF2008 and the ILRS SLR time series.,2005-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from 2012. Replaces ITRF2005 (code 6896).","International Earth Rotation Service (IERS) Technical Note No. 37, published in 2012. Al [...]
+1062,Posiciones Geodesicas Argentinas 2007,geodetic,"A geodetic network of 211 high accuracy surveyed points (178 passive and 33 continuous operating) based on ITRF2005, Epoch 2006.6, that define the National Geodetic System (Sistema Geodésico Nacional) effective 15 May 2009.",2006-08-07,7019,8901,1033,"Topographic mapping, geodetic survey.","POSGAR 07 has been adopted by order of the Director of the National Geographic Institute on May 15, 2009, as the new National Geodetic Reference Fr [...]
+1063,Marco Geodesico Nacional de Bolivia,geodetic,"IGS05 (ITRF2005) at epoch 2010.2.  Densification of SIRGAS95 network in Bolivia, consisting of 125 passive geodetic stations and 8 continuous recording GPS stations.",2010-03-14,7019,8901,1049,Geodetic survey.,"Densification of SIRGAS 1995 within Bolivia. Replaces PSAD56 (datum code 6248) in Bolivia.","Sistema de Referencia Geocentrico para las Americas (SIRGAS) Boletin Informativo No 12, Aug 2007 and www.sirgas.org/fileadmin/docs/Boleti [...]
+1064,SIRGAS-Chile,geodetic,"ITRF2000 at epoch 2002.0.  Densification of SIRGAS 2000 network in Chile, consisting of 650 monumented stations.",2002-01-01,7019,8901,1066,Geodetic survey.,"Densification of SIRGAS 2000 within Chile. Replaces PSAD56 (datum code 6248) in Chile, replaces HITO XVIII (datum code 6254) in Chilean Tierra del Fuego and replaces Easter Island 1967 (datum code 6719)  in Easter Island.","IGM Chile Report: 31_Parra_Baez_Chilean_part_of_SIRGAS.pdf on sirgas.org website ( [...]
+1065,Costa Rica 2005,geodetic,"ITRF2000 at epoch 2005.83.  Network of 34 GPS stations throughout the country, five of which were connected to four Caribbean area ITRF stations.",2005-10-30,7030,8901,1074,Geodetic survey.,"Replaces Ocotepeque (datum code 1070) in Costa Rica from March 2007.","Instituto Geografico Nacional Costa Rica report: El Sistema de Referencia CR05 y la Proyeccion Transversal de Mercator para Costa Rica CRTM05. (Report available through www.sirgas.org website in nati [...]
+1066,Sistema Geodesico Nacional de Panama MACARIO SOLIS,geodetic,"ITRF2000 at epoch 2000.0. Densification of SIRGAS 2000 network in Panama, consisting of 20 GPS stations throughout the country.",2000-01-01,7019,8901,1186,Geodetic survey.,,Details taken from summary on national networks list on www.sirgas.org website.,IOGP,"2016/09/16",2011.018 2016.020,0,"D_SGNP_MARCARIO_SOLIS"
+1067,Peru96,geodetic,"Densification of SIRGAS95 network in Peru, consisting of 47 passive geodetic stations and 3 continuous recording GPS stations. Documented as ITRF94 at epoch 1995.4 but possibly a rounded value as SIRGAS95 is at epoch 1995.42.",1996-06-02,7019,8901,1189,Geodetic survey.,"Densification of SIRGAS 1995 within Peru. Replaces PSAD56 (datum code 6248) in Peru.","Details taken from national realizations page of WWW.SIRGAS.ORG, confirmed by reports from IGN Peru.",IOGP,"2016 [...]
+1068,SIRGAS-ROU98,geodetic,"Densification of SIRGAS95 network in Uruguay, consisting of 17 passive geodetic stations and 3 continuous recording GPS stations. Documented as ITRF94 at epoch 1995.4 but possibly a rounded value as SIRGAS95 is at epoch 1995.42.",1995-06-02,7030,8901,1247,Geodetic survey.,"Densification of SIRGAS 1995 within Uruguay. Replaces Yacare (datum code 6309) in Uruguay. Uruguay documentation clearly states use of WGS 84 reference ellipsoid.","Sistema de Referencia Geo [...]
+1069,"SIRGAS_ES2007.8",geodetic,"ITRF2005 at epoch 2007.85.  Densification of SIRGAS-CON network in El Salvador, consisting of 38 monumented stations.",2007-11-07,7019,8901,1087,Geodetic survey.,SIRGAS-ES2007.8 is the national SIRGAS densification.,"Integration of the reference frame of El Salvador into SIRGAS (SIRGAS-ES2007.8) report by GG-IGCN (El Salvador) & DGFI (Germany) available from www.sirgas.org.  (Information also summarised on www.sirgas.org website national networks list).", [...]
+1070,Ocotepeque 1935,geodetic,"Fundamental point: Base Norte. Latitude: 14°26'20.168""N, longitude: 89°11'33.964""W.",1935-07-01,7008,8901,3876,Topographic mapping and engineering survey.,"Replaced in Costa Rica by Costa Rica 2005 (CR05) from March 2007 and replaced in El Salvador by SIRGAS_ES2007 from August 2007.","Clifford Mugnier's PE&RS articles on Belize, Costa Rica, El Salvador, Guatemala, Honduras, Nicaragua, Panama (www.asprs.org/resources/grids/) also substantiated in IGN Costa [...]
+1071,Sibun Gorge 1922,geodetic,"Latitude: 17º03'40.471""N, longitude: 88º37'54.687""W.",1922-07-01,7007,8901,3219,Topographic mapping and engineering survey.,,"Clifford Mugnier's March 2009 PE&RS ""Grids and Datums"" article on Belize (www.asprs.org/resources/grids/).",OGP,"2011/03/26",2011.026,0,"D_Sibun_Gorge_1922"
+1072,Panama-Colon 1911,geodetic,"Fundamental point: Balboa Hill. Latitude: 09°04'57.637""N, longtitude: 79°43'50.313""W.",1911-07-01,7008,8901,3290,Topographic mapping and engineering survey.,"Reports of the existence of an Ancon datum are probably erroneous, considering that the origin of the Panamá-Colón Datum of 1911 is at Balboa Hill and the access road up the hill is from the town of Ancon, Canal Zone.","Clifford Mugnier's PE&RS July 1999 Grids and Datums article on The Republic of  [...]
+1073,Reseau Geodesique des Antilles Francaises 2009,geodetic,ITRF2005 at epoch 2009.0,2009-01-01,7019,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.",Replaces RRAF91 in Martinique and Guadeloupe.,IGN Paris.,OGP,"2011/03/23",2011.030,0,"Reseau_Geodesique_des_Antilles_Francaises_2009"
+1074,Corrego Alegre 1961,geodetic,"Fundamental point: Corrego Alegre. Latitude: 19°50'14.91""S, longitude: 48°57'41.98""W (of Greenwich).",1961-01-01,7022,8901,3874,"Topographic mapping, geodetic survey.","Replaced by Corrego Alegre 1970-72 (datum code 6225). NIMA gives coordinates of origin as latitude: 19°50'15.14""S, longitude: 48°57'42.75""W.",IBGE,OGP,"2011/07/10",2011.053,0,"D_Corrego_Alegre_1961"
+1075,"South American Datum 1969(96)",geodetic,"Fundamental point: Chua. Geodetic latitude: 19°45'41.6527""S; geodetic longitude: 48°06'04.0639""W (of Greenwich). (Astronomic coordinates: Latitude 19°45'41.34""S +/- 0.05"", longitude 48°06'07.80""W +/- 0.08"").",1996-01-01,7050,8901,1053,Topographic mapping.,"SAD69 uses GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places. Replaces original 1969 adjustment (datum code 6618) in Brazil.",IBGE.,OGP,"2012/11/26",2011.053 2012.070,0,"D_ [...]
+1076,Papua New Guinea Geodetic Datum 1994,geodetic,ITRF92 at epoch 1994.0.,1994-01-01,7019,8901,1187,"Topographic mapping, geodetic, engineering and cadastral survey.",Adopted 1996. Coincident with WGS 84 in 1994 but rapidly divergent due to significant tectonic motion in PNG.,"Quickclose Geomatics and http://www.aspng.org/techinfopng94.htm",OGP,"2011/07/15",2011.059,0,"D_Papua_New_Guinea_Geodetic_Datum_1994"
+1077,Ukraine 2000,geodetic,Orientation and scale constrained to be same as ITRF2000 at epoch 2005.0. Position is minimised deviation between reference ellipsoid and quasigeoid in territory of Ukraine.,2005-01-01,7024,8901,1242,Geodesy.,,"Berlin 2008 GNSS Symposium paper 4-7 (""Creation of ZAKPOS active Network Reference Stations for Transcarpathian Region of Ukraine"") by Savchuk et al.",OGP,"2012/12/17",2011.044 2012.087,0,"D_Ukraine_2000"
+1078,Fehmarnbelt Datum 2010,geodetic,ITRF2005 at epoch 2010.14.,2010-02-21,7019,8901,3889,Engineering survey and construction of Fehmarnbelt tunnel.,Defined through coordinates of four permanant GNSS stations.,"Femern A/S.",IOGP,"2016/09/16",2011.083 2016.020,0,"D_Fehmarnbelt_Datum_2010"
+1079,Fehmarnbelt Vertical Reference 2010,vertical,"Realised by precise levelling between tide gauges at Marienleuchte (Germany), Rodbyhavn (Denmark) and four Fehmarnbelt project GNSS stations.",2010-01-01,,,3890,Engineering survey and construction of Fehmarnbelt tunnel.,,"Femern A/S",OGP,"2011/09/24",2011.083,0,
 1080,Lowest Astronomic Tide,vertical,The lowest tide level which can be predicted to occur under average meterological conditions and under any combination of astronomical conditions.,,,,1262,Hydrography and Nautical Charting.,"Users are advised to not use this generic vertical datum but to define explicit realisations of LAT by specifying location and epoch, for instance ""LAT at xxx during yyyy-yyyy"".","IHO Dictionary, S-32, 5th Edition, 2936.",OGP,"2012/08/10",2011.047,0,
 1081,Deutsche Bahn Reference System,geodetic,"Defined by transformation from ETRS89 (transformation code 5826) to be an average of DHDN across all states of Germany.",,7004,8901,3339,Engineering survey for railway applications.,,"Deutsche Bahn AG via Geo++, www.geopp.de",OGP,"2012/03/25",2011.101 2012.034,0,"D_Deutsche_Bahn_Reference_System"
 1082,Highest Astronomic Tide,vertical,The highest tide level which can be predicted to occur under average meterological conditions and under any combination of astronomical conditions.,,,,1262,Hydrography and Nautical Charting.,"Users are advised to not use this generic vertical datum but to define explicit realisations of HAT by specifying location and epoch, for instance ""HAT at xxx during yyyy-yyyy"".","IHO Dictionary, S-32, 5th Edition, 2244.",OGP,"2012/08/10",2011.047,0,
@@ -71,179 +71,206 @@ http://www.maanmittauslaitos.fi",OGP,"2009/02/21",2008.112,0,
 1092,Mean High Water,vertical,The average height of the high waters at a place over a 19-year period.,,,,1262,Hydrography and Nautical Charting.,"Users are advised to not use this generic vertical datum but to define explicit realisations of MHW by specifying location and epoch, for instance ""MHW at xxx during yyyy-yyyy"".","IHO Dictionary, S-32, 5th Edition, 3141.",OGP,"2012/08/10",2011.047,0,
 1093,Low Water,vertical,"The lowest level reached by the water surface in one tidal cycle. When used in inland (non-tidal) waters it is generally defined as a level which the daily mean water level would fall below less than 5% of the time.",,,,1262,"Hydrography and Nautical Charting, mostly in harbour and river engineering.","On a river it is a sloping surface. Users are advised to not use this generic vertical datum but to define explicit realisations of low water by specifying locatio [...]
 1094,High Water,vertical,"The highest level reached at a place by the water surface in one tidal cycle. When used on inland (non-tidal) waters it is generally defined as a level which the daily mean water level exceeds less than 5% of the time.",,,,1262,"Hydrography and Nautical Charting, mostly in harbour and river engineering.","Users are advised to not use this generic vertical datum but to define explicit realisations of high water by specifying location and epoch, for instance ""Hig [...]
-1095,Tonga Geodetic Datum 2005,geodetic,Based on ITRF2000 at epoch 2005.0,2000,7019,8901,1234,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"World Bank Cyclone Emergency Recovery and Management Project, Report 7, Report of the Development of a Geodetic Datum and Map Grid for the Kingdom of Tonga, prepared for the Ministry of Lands, Survey and Natural Resources, 1st November 2004.",OGP,"2012/10/22",2012.085,0,
-1096,Norway Normal Null 2000,vertical,"Adjustment is referenced to mean high tide at Amsterdams Peil in 1684. To account for land level movements caused by isostatic rebound, heights are reduced to epoch 2000.0 using values computed from the NKG2005LU uplift model.",2000,,,1352,"Topographic mapping, geodetic survey.",Replaces NN54. Uses Normal heights.,Norwegian Mapping Authority.,OGP,"2012/12/17",2012.094,0,
-1097,Grand Cayman Vertical Datum 1954,vertical,,1954,,,3185,"Topographic mapping, geodetic survey.",,"Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
-1098,Little Cayman Vertical Datum 1961,vertical,,1961,,,4121,"Topographic mapping, geodetic survey.",,"Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
-1099,Cayman Brac Vertical Datum 1961,vertical,,1961,,,3207,"Topographic mapping, geodetic survey.",,"Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
-1100,Cayman Islands Geodetic Datum 2011,geodetic,ITRF2005 at epoch 2011.0,2011,7019,8901,1063,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces GCGD59 (datum code 6723) and SIGD61 (datum code 6726).","Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
-1101,Cais da Pontinha - Funchal,vertical,"Mean Sea Level during 1913 at Cais da Pontinha, Funchal.",1913,,,4125,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1102,Cais da Vila - Porto Santo,vertical,"Mean Sea Level during 1936 at Cais da Vila, Porto Santo.",1936,,,3680,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1103,Cais das Velas,vertical,Mean Sea Level during 1937 at Cais das Velas.,1937,,,2875,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1104,Horta,vertical,Mean Sea Level during 1935 at Horta.,1935,,,2873,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1105,Cais da Madalena,vertical,Mean Sea Level during 1937 at Cais da Madalena.,1937,,,2874,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1106,Santa Cruz da Graciosa,vertical,Mean Sea Level during 1938 at Santa Cruz da Graciosa.,1938,,,3681,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1107,Cais da Figueirinha - Angra do Heroismo,vertical,"Mean Sea Level during 1951 at Cais da Figueirinha - Angra do Heroísmo.",1951,,,2872,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2014/09/18",2013.010 2014.064,0,
-1108,Santa Cruz das Flores,vertical,Mean Sea Level during 1965 at Santa Cruz das Flores.,1965,,,1344,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1109,Cais da Vila do Porto,vertical,"Mean Sea Level during 1965 at Cais da Vila, Porto.",1965,,,4126,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1110,Ponta Delgada,vertical,Mean Sea Level during 1991 at Ponta Delgada.,1991,,,2871,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
-1111,Nepal 1981,geodetic,"Fundamental point: Station 12/157 Nagarkot. Latitude: 27°41'31.04""N, longitude: 85°31'20.23""E (of Greenwich).",1981,7015,8901,1171,"Geodetic survey, topographic mapping.",,Nepal Survey Department www.dos.gov.np and Nepalese Journal on Geoinformatics June 2011.,OGP,"2013/06/26",2013.018,0,
-1112,Cyprus Geodetic Reference System 1993,geodetic,"Station Chionistra (Mount Troodos). Network scale and orientation determined by connection of six stations to ITRF91 in Europe at epoch 1993.1.",1993,7030,8901,3236,Geodetic survey.,Replaces 1913 and 1935 datums.,"Cyprus Department of Lands and Surveys (DLS).",IOGP,"2015/09/28",2014.091,0,
-1113,Reseau Geodesique des Terres Australes et Antarctiques Francaises 2007,geodetic,ITRF2005 at epoch 2007.274,2007,7019,8901,4246,"Geodetic survey, topographic mapping, engineering survey.","Replaces IGN 1963-64 on Amsterdam, Saint-Paul 1969 on St Paul, IGN64 on Crozet, MHM 1954 on Europa, IGN 1962 on Kerguelan, and Petrels 1972 and Perroud 1950 in Adelie Land.",IGN Paris.,IOGP,"2015/04/25",2015.027,0,
-1114,Israeli Geodetic Datum 2005,geodetic,"Defined by coordinates of 13 Active Positioning Network (APN) stations in ITRF2000 at epoch 2004.75. A further five APN stations were added in 2006.",2004,7030,8901,1126,Geodetic Survey.,"Replaces Israel 1993 (datum code 6141). Replaced by IGD05/12 (datum code 1115).",Survey of Israel.,IOGP,"2015/06/20",2015.020,0,
-1115,"Israeli Geodetic Datum 2005(2012)",geodetic,Datum updated in 2012 with four APN stations removed from definition. Coordinate epoch remains ITRF2000 at epoch 2004.75.,2004,7030,8901,1126,Geodetic Survey.,"Replaces IGD05 (datum code 1114).",Survey of Israel.,IOGP,"2015/06/20",2015.020,0,
-1116,"NAD83 (National Spatial Reference System 2011)",geodetic,"Coordinates of a nationwide adjustment of 79,546 NGS ""passive"" control stations in CONUS and Alaska, constrained to 1,171 current CORS station coordinates at epoch 2010.0.",2012,7019,8901,1511,Geodetic survey.,"Replaces NAD83(NSRS2007). ITRF2008 is understood to underlay the latest CORS station coordinates.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/07",2013.022,0,
-1117,"NAD83 (National Spatial Reference System PA11)",geodetic,"Coordinates of a nationwide adjustment including 345 NGS ""passive"" control stations constrained to 24 current Pacific CORS station coordinates at epoch 2010.0.",2012,7019,8901,4162,Geodetic survey.,"Replaces NAD83(HARN) in American Samoa and Hawaii. ITRF2008 is understood to underlay the latest CORS station coordinates.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/07",2013.022,0,
-1118,"NAD83 (National Spatial Reference System MA11)",geodetic,"Coordinates of a nationwide adjustment including 171 NGS ""passive"" control stations constrained to 24 current Pacific CORS station coordinates at epoch 2010.0.",2012,7019,8901,4167,Geodetic survey.,"Replaces NAD83(HARN) (GGN93) code 6152 in Guam. ITRF2008 is understood to underlay the latest CORS station coordinates.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/08",2013.022,0,
-1119,Northern Marianas Vertical Datum of 2003,vertical,"Mean sea level at Tanapag harbor, Saipan. Benchmark 1633227 TIDAL UH-2C = 1.657m relative to National Tidal Datum Epoch 1983-2001. Transferred to Rota (East Harbor, BM TIDAL 3 = 1.482m) and Tinian (Harbor BM TIDAL 1 = 2.361m).",2003,,,4171,"Topographic mapping, geodetic survey.",Replaces all earlier vertical datums on these islands.,"National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/18",2013.044,0,
-1120,Mexico ITRF2008,geodetic,ITRF2008 at epoch 2010.00.,2010,7019,8901,1160,Geodetic survey.,"Realised by a frame of 15 active GPS stations observed and adjusted in the ITRF2008. Includes ties to tide gauges. Replaces Mexico ITRF92 (datum code 1042).","INEGI, http://www.inegi.org.mx",OGP,"2013/08/04",2013.032,0,
-1121,Tutuila Vertical Datum of 1962,vertical,"Mean sea level at Pago Pago harbor, Tutuila, over 10 years 1949-1955 and 1957-1959. Benchmark NO 2 1948 = 7.67ftUS.",1962,,,2288,"Topographic mapping, geodetic survey.","Replaced by American Samoa Vertical Datum of 2002 (datum code 1125).","National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
-1122,Guam Vertical Datum of 1963,vertical,"Mean sea level at Apra harbor, Guam, 1949-1962. Benchmark NO 5 1949 = 0.599m.",1963,,,3255,"Topographic mapping, geodetic survey.","Replaced by Guam vertical datum of 2004 (datum code 1126).","National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
-1123,Puerto Rico Vertical Datum of 2002,vertical,"Mean sea level at San Juan. Benchmark 9756371 A TIDAL = 1.334m relative to National Tidal Datum Epoch 1960-1978.",2002,,,3294,"Topographic mapping, geodetic survey.",Replaces all earlier vertical datums for Puerto Rico.,"National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/26",2013.044,0,
-1124,Virgin Islands Vertical Datum of 2009,vertical,"Mean sea level for National Tidal Datum Epoch 1983–2001 at (i) Lime Tree Bay, St. Croix (BM 9751401 M = 3.111m) , (ii) Lameshur Bay, St. John (BM 9751381 TIDAL A = 1.077m) , and (iii) Charlotte Amalie, St. Thomas (BM 9751639 F = 1.552m).",2009,,,3330,"Topographic mapping, geodetic survey.",Replaces all earlier vertical datums on these islands.,"National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
-1125,American Samoa Vertical Datum of 2002,vertical,"Mean sea level at Pago Pago harbor, Tutuila. Benchmark 1770000 S TIDAL = 1.364m relative to National Tidal Datum Epoch 1983-2001.",2002,,,2288,"Topographic mapping, geodetic survey.","Replaces Tutuila vertical datum of 1962 (datum code 1121).","National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
-1126,Guam Vertical Datum of 2004,vertical,"Mean sea level at Apra harbor, Guam. Benchmark 1630000 TIDAL 4 = 2.170m relative to US National Tidal Datum Epoch 1983-2001. MSL is 0.419m above MLLW and the BM is 2.589m above MLLW.",2004,,,3255,"Topographic mapping, geodetic survey.","Replaces Guam Vertical Datum of 1963 (datum code 1122).","National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
-1127,Canadian Geodetic Vertical Datum of 2013,vertical,"Defined by the equipotential surface W0 = 62,636,856.0 m^2s^-2, which by convention represents the coastal mean sea level for North America.",2013,,,1061,"Topographic mapping, geodetic survey.","Replaces CGVD28 (datum code 5114) from November 2013.","Geodetic Survey Division, Natural Resources Canada.",OGP,"2013/12/13",2013.064,0,
-1128,Japanese Geodetic Datum 2011,geodetic,"ITRF94 at epoch 1997.0 except for northern Honshu area impacted by 2011 Tohoku earthquake which is ITRF2008 at epoch 2011.395. Fundamental point: Tokyo-Taisho, latitude: 35°39'29.1572""N, longitude: 139°44'28.8869""E (of Greenwich).",2011,7019,8901,1129,"Geodetic survey, topographic and engineering survey.","Instigated under amendment to the Japanese Surveying Law with effect from 21st October 2011. Replaces JGD2000 (datum code 6612).","Geodeti [...]
-1129,Japanese Standard Levelling Datum 1972,vertical,Mean sea level Oshoro 1963-72.,1972,,,4168,"Topographic mapping, geodetic survey.","Normal-orthometric heights. Replaced by JGD2000 (vertical) (datum code 1130) with effect from April 2002.","Geospatial Information Authority of Japan (GSI) bulletin volume 51 of March 2004.",OGP,"2013/12/16",2013.063,0,
-1130,"Japanese Geodetic Datum 2000 (vertical)",vertical,24.4140 metres above mean sea level Tokyo Bay.,2002,,,3263,"Topographic mapping, geodetic survey.","Orthometric heights. Replaces JSLD69 and JSLD72 with effect from April 2002. Replaced by JGD2011 (vertical) (datum code 1131) with effect from 21st October 2011.","Geospatial Information Authority of Japan (GSI) bulletin volume 51 of March 2004.",OGP,"2013/12/15",2013.063,0,
-1131,"Japanese Geodetic Datum 2011 (vertical)",vertical,24.3900 metres above mean sea level Tokyo Bay.,2011,,,3263,"Topographic mapping, geodetic survey.","Orthometric heights. Replaces JGD2000 (vertical) (datum code 1130) with effect from 21st October 2011.","Geodetic Department, Geospatial Information Authority of Japan (GSI).",OGP,"2013/12/15",2013.063,0,
-1132,Rete Dinamica Nazionale 2008,geodetic,"Italian densification of ETRS89 realised through network of 99 permanent reference stations in ETRF2000 at 2008.0.",2008,7019,8901,3343,"Geodetic survey, topographic mapping.","Adopted as official Italian reference datum 10/11/2011. Replaces IGM95 (datum code 6670).",IGM Italy,OGP,"2014/01/21",2014.002,0,
-1133,"NAD83 (Continuously Operating Reference Station 1996)",geodetic,"Defined by time-dependent transformations from ITRF. The ITRF realisation and tfm used has been changed periodically; ITRF96 in years 1997 through 1999, ITRF97 in 2000 and 2001 and ITRF2000 from 2002 (see tfm codes 6864-6866 respectively).",1997,7019,8901,1511,Geodetic survey.,"Replaced by NAD83(2011) from 2011-09-06.","US National Geodetic Survey, http://geodesy.noaa.gov/CORS.",OGP,"2014/09/18",2014.029 2014.065,0,
-1134,Christmas Island Datum 1985,engineering,"WGS 72 / UTM zone 48S coordinates 570000mE, 8840000mN; local grid orientated parallel to UTM grid at this point.",1985,,,4169,"GIS, topographic survey, cadastre, engineering survey.",Replaced by GDA94 geodetic datum.,"Landgate (Government of Western Australia), Christmas Island Geographic Information System documentation, www.ga.gov.au/christmas.",OGP,"2014/02/08",2014.005,0,
+1095,Tonga Geodetic Datum 2005,geodetic,Based on ITRF2000 at epoch 2005.0,2005-01-01,7019,8901,1234,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"World Bank Cyclone Emergency Recovery and Management Project, Report 7, Report of the Development of a Geodetic Datum and Map Grid for the Kingdom of Tonga, prepared for the Ministry of Lands, Survey and Natural Resources, 1st November 2004.",IOGP,"2016/09/16",2012.085 2016.020,0,
+1096,Norway Normal Null 2000,vertical,"Adjustment is referenced to mean high tide at Amsterdams Peil in 1684. To account for land level movements caused by isostatic rebound, heights are reduced to epoch 2000.0 using values computed from the NKG2005LU uplift model.",2000-01-01,,,1352,"Topographic mapping, geodetic survey.",Replaces NN54. Uses Normal heights.,Norwegian Mapping Authority.,OGP,"2012/12/17",2012.094,0,
+1097,Grand Cayman Vertical Datum 1954,vertical,,1954-01-01,,,3185,"Topographic mapping, geodetic survey.",,"Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
+1098,Little Cayman Vertical Datum 1961,vertical,,1961-01-01,,,4121,"Topographic mapping, geodetic survey.",,"Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
+1099,Cayman Brac Vertical Datum 1961,vertical,,1961-01-01,,,3207,"Topographic mapping, geodetic survey.",,"Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
+1100,Cayman Islands Geodetic Datum 2011,geodetic,ITRF2005 at epoch 2011.0,2011-01-01,7019,8901,1063,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces GCGD59 (datum code 6723) and SIGD61 (datum code 6726).","Lands and Surveys Department, Cayman Islands Government.",OGP,"2012/12/08",2012.095,0,
+1101,Cais da Pontinha - Funchal,vertical,"Mean Sea Level during 1913 at Cais da Pontinha, Funchal.",1913-01-01,,,4125,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1102,Cais da Vila - Porto Santo,vertical,"Mean Sea Level during 1936 at Cais da Vila, Porto Santo.",1936-01-01,,,3680,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1103,Cais das Velas,vertical,Mean Sea Level during 1937 at Cais das Velas.,1937-01-01,,,2875,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1104,Horta,vertical,Mean Sea Level during 1935 at Horta.,1935-01-01,,,2873,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1105,Cais da Madalena,vertical,Mean Sea Level during 1937 at Cais da Madalena.,1937-01-01,,,2874,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1106,Santa Cruz da Graciosa,vertical,Mean Sea Level during 1938 at Santa Cruz da Graciosa.,1938-01-01,,,3681,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1107,Cais da Figueirinha - Angra do Heroismo,vertical,"Mean Sea Level during 1951 at Cais da Figueirinha - Angra do Heroísmo.",1951-01-01,,,2872,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2014/09/18",2013.010 2014.064,0,
+1108,Santa Cruz das Flores,vertical,Mean Sea Level during 1965 at Santa Cruz das Flores.,1965-01-01,,,1344,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1109,Cais da Vila do Porto,vertical,"Mean Sea Level during 1965 at Cais da Vila, Porto.",1965-01-01,,,4126,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1110,Ponta Delgada,vertical,Mean Sea Level during 1991 at Ponta Delgada.,1991-01-01,,,2871,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"General Directorate of Land, http://www.dgterritorio.pt/",OGP,"2013/04/10",2013.010,0,
+1111,Nepal 1981,geodetic,"Fundamental point: Station 12/157 Nagarkot. Latitude: 27°41'31.04""N, longitude: 85°31'20.23""E (of Greenwich).",1981-01-01,7015,8901,1171,"Geodetic survey, topographic mapping.",,Nepal Survey Department www.dos.gov.np and Nepalese Journal on Geoinformatics June 2011.,OGP,"2013/06/26",2013.018,0,
+1112,Cyprus Geodetic Reference System 1993,geodetic,"Station Chionistra (Mount Troodos). Network scale and orientation determined by connection of six stations to ITRF91 in Europe at epoch 1993.1.",1993-02-01,7030,8901,3236,Survey plans and maps produced by DLS after 1993.,,"Cyprus Department of Lands and Surveys (DLS).",IOGP,"2016/02/15",2014.091 2016.008,0,
+1113,Reseau Geodesique des Terres Australes et Antarctiques Francaises 2007,geodetic,ITRF2005 at epoch 2007.274,2007-04-10,7019,8901,4246,"Geodetic survey, topographic mapping, engineering survey.","Replaces IGN 1963-64 on Amsterdam, Saint-Paul 1969 on St Paul, IGN64 on Crozet, MHM 1954 on Europa, IGN 1962 on Kerguelan, and Petrels 1972 and Perroud 1950 in Adelie Land.",IGN Paris.,IOGP,"2015/04/25",2015.027,0,
+1114,Israeli Geodetic Datum 2005,geodetic,"Defined by coordinates of 13 Active Positioning Network (APN) stations in ITRF2000 at epoch 2004.75. A further five APN stations were added in 2006.",2004-10-01,7030,8901,1126,Geodetic Survey.,"Replaces Israel 1993 (datum code 6141). Replaced by IGD05/12 (datum code 1115).",Survey of Israel.,IOGP,"2015/06/20",2015.020,0,
+1115,"Israeli Geodetic Datum 2005(2012)",geodetic,Datum updated in 2012 with four APN stations removed from definition. Coordinate epoch remains ITRF2000 at epoch 2004.75.,2004-10-01,7030,8901,1126,Geodetic Survey.,"Replaces IGD05 (datum code 1114).",Survey of Israel.,IOGP,"2015/06/20",2015.020,0,
+1116,"NAD83 (National Spatial Reference System 2011)",geodetic,"Coordinates of a nationwide adjustment of 79,546 NGS ""passive"" control stations in CONUS and Alaska, constrained to 1,171 current CORS station coordinates at epoch 2010.0.",2012-06-12,7019,8901,1511,Geodetic survey.,"Replaces NAD83(NSRS2007). ITRF2008 is understood to underlay the latest CORS station coordinates.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/07",2013.022,0,
+1117,"NAD83 (National Spatial Reference System PA11)",geodetic,"Coordinates of a nationwide adjustment including 345 NGS ""passive"" control stations constrained to 24 current Pacific CORS station coordinates at epoch 2010.0.",2012-06-12,7019,8901,4162,Geodetic survey.,"Replaces NAD83(HARN) in American Samoa and Hawaii. ITRF2008 is understood to underlay the latest CORS station coordinates.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/07",2013.022,0,
+1118,"NAD83 (National Spatial Reference System MA11)",geodetic,"Coordinates of a nationwide adjustment including 171 NGS ""passive"" control stations constrained to 24 current Pacific CORS station coordinates at epoch 2010.0.",2012-06-12,7019,8901,4167,Geodetic survey.,"Replaces NAD83(HARN) (GGN93) code 6152 in Guam. ITRF2008 is understood to underlay the latest CORS station coordinates.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/08",2013.022,0,
+1119,Northern Marianas Vertical Datum of 2003,vertical,"Mean sea level at Tanapag harbor, Saipan. Benchmark 1633227 TIDAL UH-2C = 1.657m relative to National Tidal Datum Epoch 1983-2001. Transferred to Rota (East Harbor, BM TIDAL 3 = 1.482m) and Tinian (Harbor BM TIDAL 1 = 2.361m).",2003-01-01,,,4171,"Topographic mapping, geodetic survey.",Replaces all earlier vertical datums on these islands.,"National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/18",2013.044,0,
+1120,Mexico ITRF2008,geodetic,ITRF2008 at epoch 2010.00.,2010-01-01,7019,8901,1160,Geodetic survey.,"Realised by a frame of 15 active GPS stations observed and adjusted in the ITRF2008. Includes ties to tide gauges. Replaces Mexico ITRF92 (datum code 1042).","INEGI, http://www.inegi.org.mx",OGP,"2013/08/04",2013.032,0,
+1121,Tutuila Vertical Datum of 1962,vertical,"Mean sea level at Pago Pago harbor, Tutuila, over 10 years 1949-1955 and 1957-1959. Benchmark NO 2 1948 = 7.67ftUS.",1962-01-01,,,2288,"Topographic mapping, geodetic survey.","Replaced by American Samoa Vertical Datum of 2002 (datum code 1125).","National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
+1122,Guam Vertical Datum of 1963,vertical,"Mean sea level at Apra harbor, Guam, 1949-1962. Benchmark NO 5 1949 = 0.599m.",1963-01-01,,,3255,"Topographic mapping, geodetic survey.","Replaced by Guam vertical datum of 2004 (datum code 1126).","National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
+1123,Puerto Rico Vertical Datum of 2002,vertical,"Mean sea level at San Juan. Benchmark 9756371 A TIDAL = 1.334m relative to National Tidal Datum Epoch 1960-1978.",2002-01-01,,,3294,"Topographic mapping, geodetic survey.",Replaces all earlier vertical datums for Puerto Rico.,"National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/26",2013.044,0,
+1124,Virgin Islands Vertical Datum of 2009,vertical,"Mean sea level for National Tidal Datum Epoch 1983–2001 at (i) Lime Tree Bay, St. Croix (BM 9751401 M = 3.111m) , (ii) Lameshur Bay, St. John (BM 9751381 TIDAL A = 1.077m) , and (iii) Charlotte Amalie, St. Thomas (BM 9751639 F = 1.552m).",2009-01-01,,,3330,"Topographic mapping, geodetic survey.",Replaces all earlier vertical datums on these islands.,"National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
+1125,American Samoa Vertical Datum of 2002,vertical,"Mean sea level at Pago Pago harbor, Tutuila. Benchmark 1770000 S TIDAL = 1.364m relative to National Tidal Datum Epoch 1983-2001.",2002-01-01,,,2288,"Topographic mapping, geodetic survey.","Replaces Tutuila vertical datum of 1962 (datum code 1121).","National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
+1126,Guam Vertical Datum of 2004,vertical,"Mean sea level at Apra harbor, Guam. Benchmark 1630000 TIDAL 4 = 2.170m relative to US National Tidal Datum Epoch 1983-2001. MSL is 0.419m above MLLW and the BM is 2.589m above MLLW.",2004-01-01,,,3255,"Topographic mapping, geodetic survey.","Replaces Guam Vertical Datum of 1963 (datum code 1122).","National Geodetic Survey; http://www.ngs.noaa.gov",OGP,"2013/10/25",2013.044,0,
+1127,Canadian Geodetic Vertical Datum of 2013,vertical,"Defined by the equipotential surface W0 = 62,636,856.0 m^2s^-2, which by convention represents the coastal mean sea level for North America.",2013-11-01,,,1061,"Topographic mapping, geodetic survey.","Replaces CGVD28 (datum code 5114) from November 2013.","Geodetic Survey Division, Natural Resources Canada.",OGP,"2013/12/13",2013.064,0,
+1128,Japanese Geodetic Datum 2011,geodetic,"ITRF94 at epoch 1997.0 except for northern Honshu area impacted by 2011 Tohoku earthquake which is ITRF2008 at epoch 2011.395. Fundamental point: Tokyo-Taisho, latitude: 35°39'29.1572""N, longitude: 139°44'28.8869""E (of Greenwich).",2011-05-24,7019,8901,1129,"Geodetic survey, topographic and engineering survey.","Instigated under amendment to the Japanese Surveying Law with effect from 21st October 2011. Replaces JGD2000 (datum code 6612).","G [...]
+1129,Japanese Standard Levelling Datum 1972,vertical,Mean sea level Oshoro 1963-72.,1972-01-01,,,4168,"Topographic mapping, geodetic survey.","Normal-orthometric heights. Replaced by JGD2000 (vertical) (datum code 1130) with effect from April 2002.","Geospatial Information Authority of Japan (GSI) bulletin volume 51 of March 2004.",OGP,"2013/12/16",2013.063,0,
+1130,"Japanese Geodetic Datum 2000 (vertical)",vertical,24.4140 metres above mean sea level Tokyo Bay.,2002-04-01,,,3263,"Topographic mapping, geodetic survey.","Orthometric heights. Replaces JSLD69 and JSLD72 with effect from April 2002. Replaced by JGD2011 (vertical) (datum code 1131) with effect from 21st October 2011.","Geospatial Information Authority of Japan (GSI) bulletin volume 51 of March 2004.",OGP,"2013/12/15",2013.063,0,
+1131,"Japanese Geodetic Datum 2011 (vertical)",vertical,24.3900 metres above mean sea level Tokyo Bay.,2011-10-31,,,3263,"Topographic mapping, geodetic survey.","Orthometric heights. Replaces JGD2000 (vertical) (datum code 1130) with effect from 21st October 2011.","Geodetic Department, Geospatial Information Authority of Japan (GSI).",OGP,"2013/12/15",2013.063,0,
+1132,Rete Dinamica Nazionale 2008,geodetic,"Italian densification of ETRS89 realised through network of 99 permanent reference stations in ETRF2000 at 2008.0.",2008-01-01,7019,8901,3343,"Geodetic survey, topographic mapping.","Adopted as official Italian reference datum 10/11/2011. Replaces IGM95 (datum code 6670).",IGM Italy,OGP,"2014/01/21",2014.002,0,
+1133,"NAD83 (Continuously Operating Reference Station 1996)",geodetic,"Defined by time-dependent transformations from ITRF. The ITRF realisation and tfm used has been changed periodically; ITRF96 in years 1997 through 1999, ITRF97 in 2000 and 2001 and ITRF2000 from 2002 (see tfm codes 6864-6866 respectively).",1997-01-01,7019,8901,1511,Geodetic survey.,"Replaced by NAD83(2011) from 2011-09-06.","US National Geodetic Survey, http://geodesy.noaa.gov/CORS.",OGP,"2014/09/18",2014.029 2014.065,0,
+1134,Christmas Island Datum 1985,engineering,"WGS 72 / UTM zone 48S coordinates 570000mE, 8840000mN; local grid orientated parallel to UTM grid at this point.",1985-01-01,,,4169,"GIS, topographic survey, cadastre, engineering survey.",Replaced by GDA94 geodetic datum.,"Landgate (Government of Western Australia), Christmas Island Geographic Information System documentation, www.ga.gov.au/christmas.",OGP,"2014/02/08",2014.005,0,
 1135,Aden 1925,geodetic,,,7012,8901,1340,Engineering and harbour surveys.,,US NGA GeoTrans software v3.4 and other industry sources.,OGP,"2014/07/30",2014.037,0,
 1136,Bioko,geodetic,,,7022,8901,4220,Topographic survey.,,US NGA GeoTrans software v3.4.,OGP,"2014/07/30",2014.037,0,
 1137,Bekaa Valley 1920,geodetic,,,7012,8901,3269,Topographic survey.,,US NGA GeoTrans software v3.4.,OGP,"2014/07/30",2014.037,0,
-1138,South East Island 1943,geodetic,"Fundamental point: Challenger Astro near Port Victoria lighthouse. Latitude: 4°40'39.460""S, longitude: 55°32'00.166""E (of Greenwich).",1975,7012,8901,4183,Topographic survey.,Network readjusted in 1958-59 and extended to Bird and Denis islands in 1975.,UK Hydrographic Office.,OGP,"2014/07/30",2014.037,0,
+1138,South East Island 1943,geodetic,"Fundamental point: Challenger Astro near Port Victoria lighthouse. Latitude: 4°40'39.460""S, longitude: 55°32'00.166""E (of Greenwich).",1975-01-01,7012,8901,4183,Topographic survey.,Network readjusted in 1958-59 and extended to Bird and Denis islands in 1975.,UK Hydrographic Office.,OGP,"2014/07/30",2014.037,0,
 1139,Gambia,geodetic,,,7012,8901,3250,Topographic survey.,,US NGA GeoTrans software v3.4.,OGP,"2014/07/30",2014.037,0,
-1140,Singapore Height Datum,vertical,Mean sea level determined at Victoria Dock tide gauge 1935-1937.,2009,,,1210,"Engineering, topographic mapping and GIS.",Orthometric heights. Network readjusted in 2009.,"Singapore Land Authority, Lands Department.",OGP,"2014/09/18",2014.045 2014.065,0,
-1141,IGS08,geodetic,Origin at geocentre. Derived from a subset of 232 stable IGS station coordinates at epoch 2005.0. For all practical purposes coincident with ITRF2008.,2005,7019,8901,1262,"Geodesy. GPS satellite ephemerides produced by US NGS and other International GNSS Service (IGS) analysis centres are expressed in this datum.",Realisation of ITRF2008 at epoch 2005.0.,"http://www.ngs.noaa.gov/CORS/",OGP,"2015/02/06",2014.070,0,
-1142,IG05 Intermediate Datum,geodetic,Defined by transformation from IGD05 at epoch 2004.75.,2004,7019,8901,2603,"Used only as an intermediate stage in conversions between IGD05 and Israeli Grid 05 (IG05).",,Survey of Israel.,OGP,"2014/11/19",2014.041,0,
-1143,Israeli Geodetic Datum 2005,geodetic,ITRF2000 at epoch 2004.75.,2004,7019,8901,1126,Geodetic Survey.,"Replaces Israel 1993 (datum code 6141). Replaced by IGD05/12 (datum code 1145).",Survey of Israel.,OGP,"2014/11/07",2014.041 2015.020,1,
-1144,"IG05/12 Intermediate Datum",geodetic,"Defined by transformation from IGD05/12 at epoch 2012.00.",2012,7019,8901,2603,"Used only as an intermediate stage in conversions between IGD05/12 and Israeli Grid 05/12 (IG05/12).",,Survey of Israel.,OGP,"2014/11/19",2014.041,0,
-1145,"Israeli Geodetic Datum 2005(2012)",geodetic,ITRF2000 at epoch 2012.00,2012,7019,8901,1126,Geodetic Survey.,"Replaces IGD05 (datum code 1143).",Survey of Israel.,OGP,"2014/11/07",2014.041 2015.020,1,
-1146,Ras Ghumays,vertical,Mean Sea Level at Ras Ghumays 1978 and 1979.,1979,,,4225,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,ADCO,OGP,"2015/01/26",2012.056,0,
-1147,Oman National Geodetic Datum 2014,geodetic,20 stations of the Oman primary network tied to ITRF2008 at epoch 2013.15.,2013,7019,8901,1183,Geodetic Survey.,"Replaces WGS 84 (G874).","National Survey Authority, Sultanate of Oman.",IOGP,"2015/08/11",2015.035,0,
+1140,Singapore Height Datum,vertical,Mean sea level determined at Victoria Dock tide gauge 1935-1937.,2009-01-01,,,1210,"Engineering, topographic mapping and GIS.",Orthometric heights. Network readjusted in 2009.,"Singapore Land Authority, Lands Department.",OGP,"2014/09/18",2014.045 2014.065,0,
+1141,IGS08,geodetic,Origin at geocentre. Derived from a subset of 232 stable IGS station coordinates at epoch 2005.0. For all practical purposes coincident with ITRF2008.,2005-01-01,7019,8901,1262,"Geodesy. GPS satellite ephemerides produced by US NGS and other International GNSS Service (IGS) analysis centres are expressed in this datum.",Realisation of ITRF2008 at epoch 2005.0.,"http://www.ngs.noaa.gov/CORS/",OGP,"2015/02/06",2014.070,0,
+1142,IG05 Intermediate Datum,geodetic,Defined by transformation from IGD05 at epoch 2004.75.,2004-10-01,7019,8901,2603,"Used only as an intermediate stage in conversions between IGD05 and Israeli Grid 05 (IG05).",,Survey of Israel.,OGP,"2014/11/19",2014.041,0,
+1143,Israeli Geodetic Datum 2005,geodetic,ITRF2000 at epoch 2004.75.,2004-10-01,7019,8901,1126,Geodetic Survey.,"Replaces Israel 1993 (datum code 6141). Replaced by IGD05/12 (datum code 1145).",Survey of Israel.,OGP,"2014/11/07",2014.041 2015.020,1,
+1144,"IG05/12 Intermediate Datum",geodetic,"Defined by transformation from IGD05/12 at epoch 2012.00.",2012-01-01,7019,8901,2603,"Used only as an intermediate stage in conversions between IGD05/12 and Israeli Grid 05/12 (IG05/12).",,Survey of Israel.,OGP,"2014/11/19",2014.041,0,
+1145,"Israeli Geodetic Datum 2005(2012)",geodetic,ITRF2000 at epoch 2012.00,2012-01-01,7019,8901,1126,Geodetic Survey.,"Replaces IGD05 (datum code 1143).",Survey of Israel.,OGP,"2014/11/07",2014.041 2015.020,1,
+1146,Ras Ghumays,vertical,Mean Sea Level at Ras Ghumays 1978 and 1979.,1979-01-01,,,4225,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,ADCO,OGP,"2015/01/26",2012.056,0,
+1147,Oman National Geodetic Datum 2014,geodetic,20 stations of the Oman primary network tied to ITRF2008 at epoch 2013.15.,2013-02-25,7019,8901,1183,Geodetic Survey.,"Replaces WGS 84 (G874).","National Survey Authority, Sultanate of Oman.",IOGP,"2016/09/16",2015.035 2016.020,0,
 1148,Famagusta 1960,vertical,Mean sea level at Famagusta Harbour.,,,,3236,Topographic mapping and engineering survey.,Orthometric heights.,"Cyprus Department of Lands and Surveys (DLS).",IOGP,"2015/11/03",2014.091,0,
-1149,PNG08,vertical,"Mean sea level at 8 tide gauges around PNG, defined through application of PNG08 geoid model (transformation code 7655) to PNG94 (CRS code 5545).",2011,,,4384,Geodetic survey.,,"Quickclose Geomatics on behalf of Geodetic Section, PNG Office of the Surveyor-General.",IOGP,"2015/11/05",2015.052,0,
+1149,PNG08,vertical,"Mean sea level at 8 tide gauges around PNG, defined through application of PNG08 geoid model (transformation code 7655) to PNG94 (CRS code 5545).",2011-10-14,,,4384,Geodetic survey.,,"Quickclose Geomatics on behalf of Geodetic Section, PNG Office of the Surveyor-General.",IOGP,"2015/11/05",2015.052,0,
 1150,Kumul 34,vertical,"Kumul Platform Station 34. Propagated through bilinear interpolation of EGM96 geoid model (transformation code 10084) reduced to Kumul 34 by offset of -0.87m.",,,,4013,Engineering survey.,,Quickclose Geomatics.,IOGP,"2015/11/05",2015.052,0,
 1151,Kiunga,vertical,"PSM 9465 at Kiunga Airport. Propagated through bilinear interpolation of EGM2008 geoid model (transformation code 3858) reduced to PSM 9465 by offset of -3.0m.",,,,4383,Engineering survey.,,Quickclose Geomatics.,IOGP,"2015/11/05",2015.052,0,
+1152,"World Geodetic System 1984 (G730)",geodetic,"Defined through coordinates of 10 GPS tracking stations adjusted to a subset of ITRF92 stations at epoch 1994.0. The reference epoch for ITRF92 is 1988.0; the ITRF92 station coordinates were transformed to 1994.0 using the NNR-NUVEL1 plate motion model.",1994-01-01,7030,8901,1262,"GPS satellite navigation (broadcast ephemeris) from 1994-06-29 to 1997-01-28. (Precise ephemeris from 1994-01-02 to 1996-09-28).","Replaces the original Transi [...]
+1153,"World Geodetic System 1984 (G873)",geodetic,"Defined through coordinates of 15 GPS tracking stations adjusted to a subset of ITRF92 stations at epoch 1997.0. The reference epoch for ITRF92 is 1988.0; the ITRF92 station coordinates were transformed to 1997.0 using the NNR-NUVEL1A plate motion model.",1997-01-01,7030,8901,1262,"GPS satellite navigation (broadcast ephemeris) from 1997-01-29 to 2002-01-19. (Precise ephemeris from 1996-09-29 to 2002-01-19).","Replaces World Geodetic Sys [...]
+1154,"World Geodetic System 1984 (G1150)",geodetic,"Defined through coordinates of 17 GPS tracking stations adjusted to a subset of 49 IGS stations. Observations made in February 2001. The reference epoch for ITRF2000 is 1997.0; station coordinates were transformed to 2001.0 using IERS station velocities.",2001-01-01,7030,8901,1262,"GPS satellite navigation (broadcast ephemeris) from 2002-01-20 to 2012-02-07. (Precise ephemeris from 2002-01-20 to 2012-05-06).","Replaces World Geodetic Sy [...]
+1155,"World Geodetic System 1984 (G1674)",geodetic,Defined through coordinates of 15 GPS tracking stations adjusted to a subset of IGS stations at epoch 2005.0. The IGS station coordinates are considered to be equivalent to ITRF2008.,2005-01-01,7030,8901,1262,"GPS satellite navigation (broadcast ephemeris) from 2012-02-08 to 2013-10-15. (Precise ephemeris from 2012-05-07 to 2013-10-15).","Replaces World Geodetic System 1984 (G1150) from 2012-02-08. Replaced by World Geodetic System 1984  [...]
+http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf. Also NGA.STND.0036_1.0.0_WGS84 of 2014-07-08.",IOGP,"2016/01/23",2015.054,0,
+1156,"World Geodetic System 1984 (G1762)",geodetic,Defined through coordinates of 19 GPS tracking stations adjusted to a subset of IGb08 stations at epoch 2005.0 using observatiions made in May 2013. The IGb08 station coordinates are considered to be equivalent to ITRF2008.,2005-01-01,7030,8901,1262,"GPS satellite navigation (broadcast and precise ephemerides) from 2013-10-16.","Replaces World Geodetic System 1984 (G1674) from 2013-10-16.","NGA STND 0036_1 0 0_WGS84_2014-10-27",IOGP,"201 [...]
+1157,Parametry Zemli 1990.02,geodetic,"Defined through coordinates of 33 stations of the satellite geodetic network (SGN) in Russia and Antarctica adjusted to a subset of 14 IGS stations in Russia at epoch 2002.0. The IGS station coordinates are considered to be equivalent to ITRF2000.",2002-01-01,7054,8901,1262,Glonass satellite navigation from 2007-09-20 to 2014-01-14.,Replaces PZ-90 from 2007-09-20. Replaced by PZ-90.11 from 2014-01-15.,"Parametry Zemli 1990 Reference Document, Milita [...]
+1158,Parametry Zemli 1990.11,geodetic,"Defined through coordinates of 33 stations of the satellite geodetic network (SGN) in Russia and Antarctica adjusted to a subset of 14 IGS stations in Russia at epoch 2010.0. The IGS station coordinates are considered to be equivalent to ITRF2008.",2010-01-01,7054,8901,1262,Glonass satellite navigation from 2014-01-15.,Replaces PZ-90.02 from 2014-01-15.,"Parametry Zemli 1990 Reference Document, Military Topgraphic Department (VTU) of the General Sta [...]
+1159,Geodezicheskaya Sistema Koordinat 2011,geodetic,"Coordinates of the Russian fundamental astronomic-geodetic network (about 50 stations) at epoch 2011.0",2011-01-01,1025,8901,1198,Geodetic survey.,,"Parametry Zemli 1990 Reference Document, Military Topgraphic Department (VTU) of the General Staff of Armed Forces of the Russian Federation.",IOGP,"2016/01/25",2015.055,0,
+1160,Kyrgyzstan Geodetic Datum 2006,geodetic,6 stations of the Kyrgyzstan zero-order network tied to ITRF2005 at epoch 2006.70.,2006-09-13,7019,8901,1137,Geodetic Survey.,"The accuracy in the connection to ITRF2005 is estimated to be 5 mm in horizontal and 10-20 mm in height (95% confidence).",GosCartographia.,IOGP,"2015/12/17",2015.064,0,
+1161,Deutsches Haupthoehennetz 1912,vertical,"Height of reference point ""Normalnullpunkt"" at Berlin Observatory defined as 37.000m above MSL in 1879 (transferred to benchmarks near Hoppegarten in Müncheberg in 1912). Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1912-01-01,,,3339,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal-orthometric heights.,"Landesamt für Digitalisierung, Breitband und Vermessung of Bavaria.",IOGP,"2015/12/20",2015.067,0,
+1162,Latvian Height System 2000,vertical,Latvian realisation of EVRF2007. Observed from 2000-2010 and reduced to epoch 2000.5 using empirical land uplift model of Latvia. EVRF2007 heights of 16 points around Latvia held fixed.,2005-07-01,,,3268,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights.,"Latvian Geospatial Information Agency via Eurogeographics, http://www.crs-geo.eu/",IOGP,"2015/12/20",2015.070,0,
+1163,EPSG example moving platform reference point,engineering,"Description of moving platform [common or vessel] reference point.",,,,1263,Example only.,"Example only. There is no convention for the naming of the reference point (the point of 0,0,0 offset): it is often called common [CRP] or vessel [VRP] .",IOGP,IOGP,"2016/02/09",2016.003,0,
+1164,"Ordnance Datum Newlyn (Offshore)",vertical,Defined by OSGM geoid model.,2016-01-01,,,4391,Geodetic survey.,Extension of Ordnance Datum Newlyn offshore through geoid model. Orthometric heights.,Ordnance Survey of Great Britain.,IOGP,"2016/02/09",2015.069,0,
+1165,International Terrestrial Reference Frame 2014,geodetic,"Origin at geocentre. Origin = ILRS SLR long-term solution at epoch 2010.0. Zero scale and scale rate between ITRF2014 and the average of VLBI and SLR scales/rates. Orientation = ITRF2008@ 2010.0 with zero rotation rates between the ITRF2014 and ITRF2008.",2010-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS). Replaces ITRF2008 (datum code 1061) from January 2016.","International Earth  [...]
+1166,"World Geodetic System 1984 (Transit)",geodetic,"Defined through coordinates of 5 GPS tracking stations in the Transit doppler positioning NSWC 9Z-2 reference frame transformed to be aligned to the BIH Conventional Terrestrial Reference Frame (BTS) at epoch 1984.0.",1984-01-01,7030,8901,1262,"GPS satellite navigation (broadcast ephemeris) from 1987-01-01 to 1994-06-28. (Precise ephemeris from 1987-01-01 to 1994-01-01).","The NSWC 9Z-2 origin shifted by -4.5 m along the Z-axis, scale [...]
+1167,Bulgaria Geodetic System 2005,geodetic,"Densification of ETRS89 realised through network of 112 permanent GNSS reference stations in ETRF2000 at 2005.0.",2005-01-01,7019,8901,1056,"Geodetic survey, topographic mapping, cadastre.",Adopted as official Bulgarian reference datum through decree 153 of 2010-07-29.,"Geodesy, Cartography and Geoinformation Systems Directorate (GCGIS).",IOGP,"2016/04/27",2016.017,0,
+1168,Geocentric Datum of Australia 2020,geodetic,ITRF2014 at epoch 2020.0.,2020-01-01,7019,8901,4177,"Geodetic survey, cadastre, topographic mapping, engineering survey, GIS, navigation, positioning.",,"Geodesy Section, Geoscience Australia.",IOGP,"2016/09/07",2016.023,0,
+1169,New Zealand Vertical Datum 2016,vertical,New Zealand quasigeoid 2016 which is defined by the application of the NZ geoid 2016 grid to NZGD2000 ellipsoidal heights. See transformation code 7840.,2016-06-27,,,1175,"Geodetic survey, topographic mapping, engineering survey.",,"Land Information New Zealand (LINZ) standard S25009.",IOGP,"2016/11/21",2016.031,0,
+1170,Deutsches Haupthoehennetz 2016,vertical,"2006-2012 levelling network adjusted to 72 points of the DHHN92. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1996-01-01,,,3339,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights in the mean tidal system.,"Bundesamt für Kartographie und Geodäsie (BKG) via http://www.crs-geo.eu",IOGP,"2016/09/15",2016.030,0,
+1171,Port Moresby 1996,vertical,"BM198 (adjacent to the Port Moresby tide gauge) height of 3.02 above MSL as determined by CSIRO in 1990. Propagated through bilinear interpolation of EGM96 geoid model (transformation code 10084) reduced by offset of -1.58m.",,,,4425,Engineering survey.,Offset has been determined by static GNSS estimation of ellipsoid height of BM198.,Quickclose Geomatics.,IOGP,"2016/11/04",2016.039,0,
+1172,Port Moresby 2008,vertical,"BM198 (adjacent to the Port Moresby tide gauge) height of 3.02 above MSL as determined by CSIRO in 1990. Propagated through bilinear interpolation of EGM2008 geoid model (transformation code 3858 or 3859) reduced by offset of -0.93m.",,,,4425,Engineering survey.,Offset has been determined by static GNSS estimation of ellipsoid height of BM198 validated to a precision of 10 cm by short period tidal observations at Kerema wharf in 2010.,Quickclose Geomatics [...]
+1173,St. Helena Tritan,geodetic,"WGS 84 at epoch 2011.773. WGS 84 coordinates (15°56'33.1217""S, 5°40'02.4436""W, 453.288m ellipsoid height) of Longwood IGS CORS station STHL on 9th October 2011",2011-10-09,7030,8901,3183,Engineering surveys including Airport and Ruperts Wharf construction.,,"St. Helena Government, Environment and Natural Resources Directorate (ENRD).",IOGP,"2016/11/20",2016.038,0,
+1174,St. Helena Geodetic Datum 2015,geodetic,"ITRF2008 at epoch 2015.0. ITRF2008 coordinates (15°56'33.1198""S, 5°40'02.4412""W, 453.183m ellipsoid height) of Longwood IGS CORS station STHL on 1st January 2015.",2015-01-01,7019,8901,3183,"Geodetic survey, topographic mapping.","Developed by Richard Stanaway, Quickclose Pty Ltd, superseding Astro DOS 71 from 1st January 2016.","St. Helena Government, Environment and Natural Resources Directorate (ENRD).",IOGP,"2016/11/29",2016.038,0,
+1175,Jamestown 1971,vertical,"MSL at Jamestown 1971 defined through elevation of triangulation station Astro DOS 71/4 Ladder Hill Fort being 267.858 metres above MSL.",1971-01-01,,,3183,Topographic mapping 1972 to 2015.,,"St. Helena Government, Environment and Natural Resources Directorate (ENRD).",IOGP,"2016/11/25",2016.038,0,
+1176,St. Helena Tritan Vertical Datum 2011,vertical,MSL defined by Longwood IGS station STHL reference level of 436.215m.,2011-10-09,,,3183,Engineering Surveys.,"Defined by offset of -17.073m applied to St. Helena Tritan ellipsiodal height (CRS code 7880).","St. Helena Government, Environment and Natural Resources Directorate (ENRD).",IOGP,"2016/11/25",2016.038,0,
+1177,St. Helena Vertical Datum 2015,vertical,Longwood IGS station STHL reference level of 436.312m.,2015-01-01,,,3183,"Geodetic survey, topographic Mapping, engineering Surveys.","Defined by SHGEOID15 geoid model (transformation code 7891) applied to SHGD2015 (CRS code 7885).","St. Helena Government, Environment and Natural Resources Directorate (ENRD).",IOGP,"2016/11/25",2016.038,0,
 5100,Mean Sea Level,vertical,"The average height of the surface of the sea at a tide station for all stages of the tide over a 19-year period, usually determined from hourly height readings measured from a fixed predetermined reference level.",,,,1262,Hydrography.,"Approximates geoid. Users are advised to not use this generic vertical datum but to define explicit realisations of MSL by specifying location and epoch, for instance ""MSL at xxx during yyyy-yyyy"".","IHO Dictionary, S-32, 5t [...]
-5101,Ordnance Datum Newlyn,vertical,Mean Sea Level at Newlyn between 1915 and 1921.,,,,2792,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2004/06/16",2004.100,0,"D_Ordnance_Datum_Newlyn"
-5102,National Geodetic Vertical Datum 1929,vertical,26 tide gauges in the US and Canada.,1929,,,1323,"Topographic mapping, geodetic survey.",Normal orthometric heights.,,OGP,"1996/09/12",,0,
-5103,North American Vertical Datum 1988,vertical,"Mean water level 1970-1988 at Pointe-au-Pierre (Father's Point) and Rimouski, Quebec. Benchmark 1250-G = 6.273m.",1988,,,4161,"Topographic mapping, geodetic survey.",Helmert orthometric heights.,,OGP,"2013/09/02",2005.880 2009.108 2011.047 2013.028,0,
-5104,Yellow Sea 1956,vertical,2 years tide readings at Qingdao.,1956,,,3228,"Topographic mapping, geodetic survey.",Replaced by Yellow Sea 1985 datum.,,OGP,"2002/06/22",2002.160,0,
-5105,Baltic Sea,vertical,"Datum: average water level at Kronstadt 1833. Network adjusted in 1977.",1977,,,1284,"Topographic mapping, geodetic survey.",Uses Normal heights.,,OGP,"2005/05/27",2004.100 2005.180,0,
+5101,Ordnance Datum Newlyn,vertical,Mean Sea Level at Newlyn between 1915 and 1921. Initially realised through 1921 and then 1956 levelling network adjustments. From 2002 redefined to be realised through OSGM geoid models.,,,,2792,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain.,IOGP,"2016/07/13",2004.100 2015.069,0,"D_Ordnance_Datum_Newlyn"
+5102,National Geodetic Vertical Datum 1929,vertical,26 tide gauges in the US and Canada.,1929-01-01,,,1323,"Topographic mapping, geodetic survey.",Normal orthometric heights.,,OGP,"1996/09/12",,0,
+5103,North American Vertical Datum 1988,vertical,"Mean water level 1970-1988 at Pointe-au-Pierre (Father's Point) and Rimouski, Quebec. Benchmark 1250-G = 6.273m.",1988-01-01,,,4161,"Topographic mapping, geodetic survey.",Helmert orthometric heights.,,OGP,"2013/09/02",2005.880 2009.108 2011.047 2013.028,0,
+5104,Yellow Sea 1956,vertical,2 years tide readings at Qingdao.,1956-01-01,,,3228,"Topographic mapping, geodetic survey.",Replaced by Yellow Sea 1985 datum.,,OGP,"2002/06/22",2002.160,0,
+5105,Baltic Sea,vertical,"Datum: average water level at Kronstadt 1833. Network adjusted in 1977.",1977-01-01,,,1284,"Topographic mapping, geodetic survey.",Uses Normal heights.,,OGP,"2005/05/27",2004.100 2005.180,0,
 5106,Caspian Sea,vertical,Defined as -28.0m Baltic datum,,,,1291,Hydrography.,,,OGP,"1996/09/12",,0,
 5107,Nivellement general de la France,vertical,Mean sea level at Marseille,,,,1326,"Topographic mapping, geodetic survey.",The CNIG states that NGF is a general term applying to all vertical network readjustments of France and recommends more specific terminology. See codes 5118-5120.,"Conseil National de l'Information Geographique groupe de travail ""Reseaux de Nivellement"" recommendations v5.1 April 1994.",OGP,"1996/09/12",,1,
 5109,Normaal Amsterdams Peil,vertical,Mean high tide at Amsterdams Peil in 1684.,,,,1275,"Topographic mapping, geodetic survey, hydrography.",Orthometric heights.,"Nederlandse Commissie voor Geodesie publication 30; 1993",OGP,"2006/01/16",2004.100 2005.880,0,
-5110,Ostend,vertical,Mean low water at Ostend 1855-78 transferred to benchmark GIKMN at Uccle.,1981,,,1347,"Topographic mapping, geodetic survey.","Realised through the second general levelling (DNG or TAW) 1981-1999.","EuroGeographics, http://www.crs-geo.eu",OGP,"2013/04/25",2005.880 2013.012,0,
-5111,Australian Height Datum,vertical,MSL 1966-68 at 30 gauges around coast.,1968,,,1281,"Topographic mapping, geodetic survey.",,Australian Land Information Group  www.auslig.gov.au,OGP,"2005/09/06",2005.460,0,
-5112,"Australian Height Datum (Tasmania)",vertical,MSL 1972 at Hobart and Burnie.,1972,,,2947,"Topographic mapping, geodetic survey.",,,OGP,"2012/01/21",2012.007,0,
+5110,Ostend,vertical,Mean low water at Ostend 1855-78 transferred to benchmark GIKMN at Uccle.,1981-01-01,,,1347,"Topographic mapping, geodetic survey.","Realised through the second general levelling (DNG or TAW) 1981-1999.","EuroGeographics, http://www.crs-geo.eu",OGP,"2013/04/25",2005.880 2013.012,0,
+5111,Australian Height Datum,vertical,MSL 1966-68 at 30 gauges around coast.,1968-01-01,,,1281,"Topographic mapping, geodetic survey.",,Australian Land Information Group  www.auslig.gov.au,OGP,"2005/09/06",2005.460,0,
+5112,"Australian Height Datum (Tasmania)",vertical,MSL 1972 at Hobart and Burnie.,1972-01-01,,,2947,"Topographic mapping, geodetic survey.",,,OGP,"2012/01/21",2012.007,0,
 5113,Instantaneous Water Level,vertical,Instantaneous water level uncorrected for tide.,,,,1262,Hydrography.,Not specific to any location or epoch.,OGP,OGP,"2012/08/10",2011.047,0,
-5114,Canadian Geodetic Vertical Datum of 1928,vertical,Based on the mean sea level determined from several tidal gauges located in strategic areas of the country.,1928,,,1289,"Topographic mapping, geodetic survey.","From November 2013 replaced by CGVD2013 (datum code 1127).","Geodetic Survey Division, Natural Resources Canada. http://maps.nrcan.gc.ca/asdb/asdb_datum.html and http://www.geod.nrcan.gc.ca/index_e/help_e/acron_e.html",OGP,"2014/01/27",2004.723 2013.064,0,
-5115,Piraeus Harbour 1986,vertical,MSL determined during 1986.,1986,,,3254,"Topographic mapping, geodetic survey.",,"Geodesy Department; Public Pertoleum Corporation of Greece",OGP,"1997/06/16",,0,
-5116,Helsinki 1960,vertical,MSL at Helsinki during 1960.,1960,,,3333,"Topographic mapping, geodetic survey.","Uses orthometric heights. Replaced by N2000 (datum code 1030).","National Land Survey of Finland;
+5114,Canadian Geodetic Vertical Datum of 1928,vertical,Based on the mean sea level determined from several tidal gauges located in strategic areas of the country.,1928-01-01,,,1289,"Topographic mapping, geodetic survey.","From November 2013 replaced by CGVD2013 (datum code 1127).","Geodetic Survey Division, Natural Resources Canada. http://maps.nrcan.gc.ca/asdb/asdb_datum.html and http://www.geod.nrcan.gc.ca/index_e/help_e/acron_e.html",OGP,"2014/01/27",2004.723 2013.064,0,
+5115,Piraeus Harbour 1986,vertical,MSL determined during 1986.,1986-01-01,,,3254,"Topographic mapping, geodetic survey.",,"Geodesy Department; Public Pertoleum Corporation of Greece",OGP,"1997/06/16",,0,
+5116,Helsinki 1960,vertical,MSL at Helsinki during 1960.,1960-01-01,,,3333,"Topographic mapping, geodetic survey.","Uses orthometric heights. Replaced by N2000 (datum code 1030).","National Land Survey of Finland;
 http://www.maanmittauslaitos.fi",OGP,"2010/05/02",2008.112,0,
-5117,Rikets hojdsystem 1970,vertical,"Adjustment is referenced to mean high tide at Amsterdams Peil in 1684. To account for land level movements caused by isostatic rebound, heights are reduced to epoch 1970.0 using uplift values computed from repeated levelling observations.",1970,,,3313,"Topographic mapping, geodetic survey.",Realised through the second precise levelling network of 1951-1967. Uses Normal heights. Replaces RH00. Replaced in 2005 by RH2000.,National Land Survey of Sweden [...]
+5117,Rikets hojdsystem 1970,vertical,"Adjustment is referenced to mean high tide at Amsterdams Peil in 1684. To account for land level movements caused by isostatic rebound, heights are reduced to epoch 1970.0 using uplift values computed from repeated levelling observations.",1970-01-01,,,3313,"Topographic mapping, geodetic survey.",Realised through the second precise levelling network of 1951-1967. Uses Normal heights. Replaces RH00. Replaced in 2005 by RH2000.,National Land Survey of  [...]
 5118,Nivellement General de la France - Lallemand,vertical,"Rivet number M.ac O-VIII on the Marseille tide gauge site, with the height fixed in 1897 at 1.661 metre above mean sea level between February 2nd 1885 and January 1st 1897.",,,,1326,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Conseil National de l'Information Geographique groupe de travail ""Reseaux de Nivellement"" recommendations v5.1 April 1994.",OGP,"1997/11/13",2001.470 2004.060,0,
-5119,Nivellement General de la France - IGN69,vertical,"Rivet number M.ac O-VIII on the Marseille tide gauge site, with the height fixed in 1897 at 1.661 metre above mean sea level between February 2nd 1885 and January 1st 1897.",1969,,,1326,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights.,"Conseil National de l'Information Geographique groupe de travail ""Reseaux de Nivellement"" recommendations v5.1 April 1994.",OGP,"2012/01/21",2001.470 2012.010,0,
-5120,Nivellement General de la France - IGN78,vertical,Marker MM3 situated on the tide gauge site of Ajaccio. Height is 3.640 metre above mean sea level.,1978,,,1327,"Geodetic survey, topographic mapping, engineering survey.","Uses Normal heights. Replaces NGC (datum code 5189).","Conseil National de l'Information Geographique groupe de travail ""Reseaux de Nivellement"" recommendations v5.1 April 1994.",OGP,"2012/01/21",2001.470 2004.060 2004.564 2012.010,0,
+5119,Nivellement General de la France - IGN69,vertical,"Rivet number M.ac O-VIII on the Marseille tide gauge site, with the height fixed in 1897 at 1.661 metre above mean sea level between February 2nd 1885 and January 1st 1897.",1969-01-01,,,1326,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights.,"Conseil National de l'Information Geographique groupe de travail ""Reseaux de Nivellement"" recommendations v5.1 April 1994.",OGP,"2012/01/21",2001.470 2012.010,0,
+5120,Nivellement General de la France - IGN78,vertical,Marker MM3 situated on the tide gauge site of Ajaccio. Height is 3.640 metre above mean sea level.,1978-01-01,,,1327,"Geodetic survey, topographic mapping, engineering survey.","Uses Normal heights. Replaces NGC (datum code 5189).","Conseil National de l'Information Geographique groupe de travail ""Reseaux de Nivellement"" recommendations v5.1 April 1994.",OGP,"2012/01/21",2001.470 2004.060 2004.564 2012.010,0,
 5121,Maputo,vertical,Mean sea level at Maputo.,,,,3281,Topographic mapping.,,"Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"1998/04/16",,0,
-5122,Japanese Standard Levelling Datum 1969,vertical,24.4140 metres above mean sea level Tokyo Bay.,1969,,,4166,"Topographic mapping, geodetic survey.","Normal-orthometric heights. Replaces JSLD49. Replaced by JGD2000 (vertical) (datum code 1130) from April 2002.","Geospatial Information Authority of Japan (GSI) bulletin volume 51 of March 2004.",OGP,"2014/05/01",2002.080 2004.380 2013.063,0,
-5123,PDO Height Datum 1993,vertical,,1993,,,3288,Oil industry mapping.,"Misclosure between Muscat and Salalah less than .5 meters with differences from of up to 5 meters from old Fahud Datum.  The PHD93 adjustment was initially known as the Spine.  Replaces Fahud Vertical Datum (code 5124) from 1993.",Petroleum Development Oman,OGP,"1999/04/22",,0,
+5122,Japanese Standard Levelling Datum 1969,vertical,24.4140 metres above mean sea level Tokyo Bay.,1969-01-01,,,4166,"Topographic mapping, geodetic survey.","Normal-orthometric heights. Replaces JSLD49. Replaced by JGD2000 (vertical) (datum code 1130) from April 2002.","Geospatial Information Authority of Japan (GSI) bulletin volume 51 of March 2004.",OGP,"2014/05/01",2002.080 2004.380 2013.063,0,
+5123,PDO Height Datum 1993,vertical,,1993-01-01,,,3288,Oil industry mapping.,"Misclosure between Muscat and Salalah less than .5 meters with differences from of up to 5 meters from old Fahud Datum.  The PHD93 adjustment was initially known as the Spine.  Replaces Fahud Vertical Datum (code 5124) from 1993.",Petroleum Development Oman,OGP,"1999/04/22",,0,
 5124,Fahud Height Datum,vertical,Single MSL determination at Mina Al Fahal.,,,,4009,Oil industry mapping.,"Based on reciprocal trigonometric heighting. Replaced by PHD93 Datum (code 5123) in 1993.",Petroleum Development Oman,OGP,"2012/02/13",2004.212 2011.042,0,
-5125,Ha Tien 1960,vertical,,1960,,,1302,"Topographic mapping, geodetic survey.",In Vietnam replaced by Hon Dau in 1992.,,OGP,"1999/10/20",,0,
-5126,Hon Dau 1992,vertical,,1992,,,4015,"Topographic mapping, geodetic survey.",Replaces Ha Tien in Vietnam.,,OGP,"2012/05/08",2012.046,0,
-5127,Landesnivellement 1902,vertical,"Origin at Repere Pierre du Niton (RPN) defined as 373.6 metres above msl. This value derived from msl at Marseille in 1897 through the French Lallemand network.",1902,,,1286,"Topographic mapping, cadastral survey.","Levelling observations not corrected for gravity field. For scientific purposes, replaced by LHHN95.","Bundesamt für Landestopographie",OGP,"2004/06/16",2004.100,0,
-5128,Landeshohennetz 1995,vertical,"Origin at Repere Pierre du Niton (RPN) defined as 373.6 metres above msl. This value derived from msl at Marseille in 1897 through the French Lallemand network.",1995,,,1286,Geodetic survey and scientific studies.,"Orthometric heights. For scientific purposes only, replaces LN02.","Bundesamt für Landestopographie",OGP,"2004/06/16",2004.100,0,
-5129,European Vertical Reference Frame 2000,vertical,"Height at Normaal Amsterdams Peil (NAP) is zero, defined through height at UELN bench mark 13600 (52°22'53""N 4°54'34""E) of 0.71599m. Datum at NAP is mean high tide in 1684.",2000,,,1299,Geodesy.,"Realised by geopotential numbers and Normal heights of the United European Levelling Network. Replaced by EVRF2007 (datum code 5215).","European veritical data centre at Bundesamt für Kartographie und Geodäsie (BKG), Leipzig branch. http:// [...]
-5130,Malin Head,vertical,Mean sea level between January 1960 and December 1969.,1970,,,1305,Topographic mapping,Orthometric heights.,Ordnance Survey of Ireland,OGP,"2001/11/06",,0,
-5131,Belfast Lough,vertical,"Mean sea level between 1951 and 1956 at Clarendon Dock, Belfast.",1957,,,2530,"Large scale (1:1,250, 1:2,500 and 1:10,000) topographic mapping.","Orthometric heights. Malin Head (datum code 5130) used for 1:50,000 and smaller mapping.",Ordnance Survey of Northern Ireland,OGP,"2002/09/19",2002.620,0,
+5125,Ha Tien 1960,vertical,,1960-01-01,,,1302,"Topographic mapping, geodetic survey.",In Vietnam replaced by Hon Dau in 1992.,,OGP,"1999/10/20",,0,
+5126,Hon Dau 1992,vertical,,1992-01-01,,,4015,"Topographic mapping, geodetic survey.",Replaces Ha Tien in Vietnam.,,OGP,"2012/05/08",2012.046,0,
+5127,Landesnivellement 1902,vertical,"Origin at Repere Pierre du Niton (RPN) defined as 373.6 metres above msl. This value derived from msl at Marseille in 1897 through the French Lallemand network.",1902-01-01,,,1286,"Topographic mapping, cadastral survey.","Levelling observations not corrected for gravity field. For scientific purposes, replaced by LHHN95.","Bundesamt für Landestopographie",OGP,"2004/06/16",2004.100,0,
+5128,Landeshohennetz 1995,vertical,"Origin at Repere Pierre du Niton (RPN) defined as 373.6 metres above msl. This value derived from msl at Marseille in 1897 through the French Lallemand network.",1995-01-01,,,1286,Geodetic survey and scientific studies.,"Orthometric heights. For scientific purposes only, replaces LN02.","Bundesamt für Landestopographie",OGP,"2004/06/16",2004.100,0,
+5129,European Vertical Reference Frame 2000,vertical,"Height at Normaal Amsterdams Peil (NAP) is zero, defined through height at UELN bench mark 13600 (52°22'53""N 4°54'34""E) of 0.71599m. Datum at NAP is mean high tide in 1684.",2000-01-01,,,1299,Geodesy.,"Realised by geopotential numbers and Normal heights of the United European Levelling Network. Replaced by EVRF2007 (datum code 5215).","European veritical data centre at Bundesamt für Kartographie und Geodäsie (BKG), Leipzig branch. h [...]
+5130,Malin Head,vertical,"Mean sea level between January 1960 and December 1969. Initially realised through levelling network adjustment, from 2002 redefined to be realised through OSGM geoid model.",1970-01-01,,,1305,Topographic mapping,Orthometric heights.,Ordnance Survey of Ireland.,IOGP,"2016/07/13",2015.069,0,
+5131,Belfast Lough,vertical,"Mean sea level between 1951 and 1956 at Clarendon Dock, Belfast. Initially realised through levelling network adjustment, from 2002 redefined to be realised through OSGM geoid model.",1957-01-01,,,2530,"Large scale (1:1,250, 1:2,500 and 1:10,000) topographic mapping.","Orthometric heights. Malin Head (datum code 5130) used for 1:50,000 and smaller mapping.",Ordnance Survey of Northern Ireland.,IOGP,"2016/07/13",2002.620 2015.069,0,
 5132,Dansk Normal Nul,vertical,Mean Sea Level at 10 gauges.,,,,3237,Topographic mapping and engineering survey,Orthometric heights.,"Kort & Matrikelstyrelsen",OGP,"2001/11/06",,0,
-5133,AIOC 1995,vertical,Average level of Caspian Sea at the Oil Rocks tide gauge June-September 1995.,1995,,,2592,Oil industry mapping.,AIOC 1995 datum is 1.7m above Caspian datum and 26.3m below Baltic datum.,BP,OGP,"2002/02/12",,0,
+5133,AIOC 1995,vertical,Average level of Caspian Sea at the Oil Rocks tide gauge June-September 1995.,1995-01-01,,,2592,Oil industry mapping.,AIOC 1995 datum is 1.7m above Caspian datum and 26.3m below Baltic datum.,BP,OGP,"2002/02/12",,0,
 5134,Black Sea,vertical,,,,,3251,Nearshore hydrographic surveying and since break-up of Former Soviet Union also topographic mapping.,Black Sea datum is 0.4m below Baltic datum.,BP,OGP,"2011/07/20",2011.061,0,
-5135,Hong Kong Principal Datum,vertical,"1.23m below the mean of 19 years (1965-83) observations of tide levels at North Point, Victoria Harbour.",1980,,,3334,"Geodetic survey, engineering survey, cadastre.",,"Survey and Mapping Office, Lands Department. Http://www.info.gov.hk/landsd/mapping/tindex.htm",OGP,"2002/06/22",,0,
+5135,Hong Kong Principal Datum,vertical,"1.23m below the mean of 19 years (1965-83) observations of tide levels at North Point, Victoria Harbour.",1980-01-01,,,3334,"Geodetic survey, engineering survey, cadastre.",,"Survey and Mapping Office, Lands Department. Http://www.info.gov.hk/landsd/mapping/tindex.htm",OGP,"2002/06/22",,0,
 5136,Hong Kong Chart Datum,vertical,"Approximates to Lowest Astronomic Tide level (LAT).",,,,3335,Hydrographic survey and charting.,"Chart datum is 0.15 metres below Hong Kong Principal Datum (code 5135) and 1.38m below MSL at Quarry Bay.","Survey and Mapping Office, Lands Department. Http://www.info.gov.hk/landsd/mapping/tindex.htm",OGP,"2009/06/02",2009.022,0,
-5137,Yellow Sea 1985,vertical,20 years tide readings at Qingdao.,1985,,,3228,"Topographic mapping, geodetic survey.",Replaces Yellow Sea 1956 datum.,Guangdong Province Land Resource Information Centre,OGP,"2002/06/22",,0,
-5138,"Ordnance Datum Newlyn (Orkney Isles)",vertical,Connected to Newlyn datum by triangulation from the British mainland.,,,,2793,"Topographic mapping, geodetic survey.",Considered as separate from Newlyn because the accuracy of the trigonometric connection across the Pentland Firth does not meet geodetic levelling specifications. Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2004/06/16",2004.100,0,
+5137,Yellow Sea 1985,vertical,20 years tide readings at Qingdao.,1985-01-01,,,3228,"Topographic mapping, geodetic survey.",Replaces Yellow Sea 1956 datum.,Guangdong Province Land Resource Information Centre,OGP,"2002/06/22",,0,
+5138,"Ordnance Datum Newlyn (Orkney Isles)",vertical,"Connected to Newlyn datum by triangulation from the British mainland. Initially realised through levelling network adjustment, from 2002 redefined to be realised through OSGM geoid model.",,,,2793,"Topographic mapping, geodetic survey.",Considered as separate from Newlyn because the accuracy of the trigonometric connection across the Pentland Firth does not meet geodetic levelling specifications. Orthometric heights.,Ordnance Survey o [...]
 5139,Fair Isle,vertical,,,,,2794,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
-5140,Lerwick,vertical,,,,,2795,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
+5140,Lerwick,vertical,"Mean Sea Level at Lerwick 1979 correlated to pre-1900. Initially realised through levelling network adjustment, from 2002 redefined to be realised through OSGM geoid model.",,,,2795,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain.,IOGP,"2016/07/13",2015.069,0,
 5141,Foula,vertical,,,,,2796,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
 5142,Sule Skerry,vertical,,,,,2797,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
 5143,North Rona,vertical,,,,,2798,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
-5144,Stornoway,vertical,,,,,2799,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
+5144,Stornoway,vertical,"Mean Sea Level at Stornoway 1977 correlated to pre-1900. Initially realised through levelling network adjustment, from 2002 redefined to be realised through OSGM geoid model.",,,,2799,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain.,IOGP,"2016/07/13",2015.069,0,
 5145,St Kilda,vertical,,,,,2800,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
 5146,Flannan Isles,vertical,,,,,2801,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2006/01/16",2005.880,0,
-5147,St Marys,vertical,,,,,2802,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
-5148,Douglas,vertical,,,,,2803,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain,OGP,"2002/09/19",,0,
+5147,St Marys,vertical,"Mean Sea Level at St. Marys 1887. Initially realised through levelling network adjustment, from 2002 redefined to be realised through OSGM geoid model.",,,,2802,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain.,IOGP,"2016/07/13",2015.069,0,
+5148,Douglas,vertical,"Mean Sea Level at Douglas 1865. Initially realised through levelling network adjustment, from 2002 redefined to be realised through OSGM geoid model.",,,,2803,"Topographic mapping, geodetic survey.",Orthometric heights.,Ordnance Survey of Great Britain.,IOGP,"2016/07/13",2015.069,0,
 5149,Fao,vertical,,,,,3390,"Topographic mapping, geodetic survey.","Established by Hunting Surveys for IPC. In Iran replaced by Bandar Abbas (code 5150). At time of record creation NIOC data in Ahwaz area still usually referenced to Fao. In Iraq replaced by Fao 1979 (code 1028).","National Iranian Oil Company (NIOC).",OGP,"2009/06/02",2009.003,0,
-5150,Bandar Abbas,vertical,Average sea level at Bandar Abbas 1995-2001.,2001,,,3336,"Topographic mapping, geodetic survey.","Replaces Fao (datum code 5149) in Iran.",National Cartographic Centre of Iran,OGP,"2010/03/01",2010.014,0,
-5151,Nivellement General de Nouvelle Caledonie,vertical,"Rivet AB01 established by SHOM (Service Hydrographique de la Marine)  in 1937 on the Quai des Volontaires in Noumea. Height i: 1.885 metre above mean sea level.",1969,,,2822,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,Service Topographique de la Nouvelle Caledonie.,OGP,"2004/03/15",2004.060,0,
-5152,Poolbeg,vertical,"Low water mark of the spring tide on the 8 April 1837 at Poolbeg Lighthouse, Dublin.",1837,,,1305,Topographic mapping before 1956 in Northern Ireland and 1970 in the Republic of Ireland.,"Replaced by Belfast Lough and Malin Head (datum codes 5130-31).","""The Irish Grid - A Description of the Co-ordinate Reference System"" published by Ordnance Survey of Ireland, Dublin and Ordnance Survey of Northern Ireland, Belfast.",OGP,"2003/06/27",,0,
-5153,Nivellement General Guyanais 1977,vertical,"Mean sea level 1936 at Cayenne. Origin = marker BM35 on stone on St Francois battery, Cayenne, with defined elevation of 1.64m above msl. NGG1977 height 0.00m is 1.96m above sounding datum defined at Cayenne in 1936 by SHM.",1977,,,3146,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",2008.087,0,
-5154,Martinique 1987,vertical,"Mean sea level 1939 at Fort de France. Origin = marker Nbc2 on rebuilt quay wall with defined elevation of 1.38m above msl. Martinique 1987 height 0.00m is 0.56m above SHOM sounding datum.",1987,,,3276,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaces Martinique 1955 (datum code 5192).",IGN Paris,OGP,"2008/09/19",2004.561 2008.087,0,
-5155,Guadeloupe 1988,vertical,"Mean sea level July 1947 to June 1948 at Pointe-Fouillole (Pointe-à-Pitre harbour). Origin = marker GO-7 (formerly AO'-5) with defined height of 2.67m above msl adopted from 1951 value. Guadeloupe 1988 height 0.00m is 0.46m above 1984 sounding datum.",1988,,,2892,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaces Guadeloupe 1951 (datum code 5193).",IGN Paris,OGP,"2008/09/17",2004.561 2008.087,0,
-5156,Reunion 1989,vertical,"Mean sea level during part of November 1949 at port of Saint-Pierre. Origin = marker AB-100 with defined elevation of 13.808m above msl.",1989,,,3337,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights. Replaces Reunion IGN58. Value of marker AB-100 retains height from 1958 adjustment.,IGN Paris,OGP,"2008/09/17",2004.561 2008.087,0,
-5157,Auckland 1946,vertical,MSL at Auckland harbour 1909-1923.,1946,,,3764,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5158,Bluff 1955,vertical,MSL at Invercargill harbour over 8 years between 1918 and 1934.,1955,,,3801,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5159,Dunedin 1958,vertical,MSL at Dunedin harbour 1918-1937.,1958,,,3803,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5160,Gisborne 1926,vertical,MSL at Gisborne harbour 1926.,1926,,,3771,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5161,Lyttelton 1937,vertical,MSL at Lyttelton harbour over 9 years between 1918 and 1933.,1937,,,3804,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5162,Moturiki 1953,vertical,MSL at Moturiki Island February 1949 to December 1952.,1953,,,3768,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5163,Napier 1962,vertical,MSL at Napier harbour. Period of derivation unknown.,1962,,,3772,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5164,Nelson 1955,vertical,MSL at Nelson harbour 1939-1942.,1955,,,3802,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5165,One Tree Point 1964,vertical,MSL at Whangarei harbour 1960-1963.,1964,,,3762,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5166,Tararu 1952,vertical,MSL at Tararu Point 1922-1923.,1952,,,3818,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5167,Taranaki 1970,vertical,MSL at Taranaki harbour 1918-1921.,1970,,,3769,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5168,Wellington 1953,vertical,MSL at Wellington harbour 1909-1946.,1953,,,3773,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
-5169,"Waitangi (Chatham Island) 1959",vertical,MSL at Waitangi harbour collected in 1959.,1959,,,3894,"Geodetic survey, topographic mapping, engineering survey.",,"Interim Report GEO/T1/19/51 for LINZ by John Hannah, ""An Assessment of New Zealand's Height Systems and Options for a Future Height System"", January 2001.",OGP,"2011/06/20",2008.023 2011.048,0,
-5170,Stewart Island 1977,vertical,MSL at 3-5 high and low tides at two different locations.,1977,,,3338,"Geodetic survey, topographic mapping, engineering survey.",,"Interim Report GEO/T1/19/51 for LINZ by John Hannah, ""An Assessment of New Zealand's Height Systems and Options for a Future Height System"", January 2001.",OGP,"2008/04/04",2008.023,0,
-5171,EGM96 geoid,vertical,Derived through EGM84 geoid undulation model consisting of spherical harmonic coefficients to degree and order 360 applied to the WGS 84 ellipsoid.,1996,,,1262,Geodesy.,"Replaces EGM84 geoid (datum code 5203). Replaced by EGM2008 geoid (datum code 1027).","NASA http://cddis.gsfc.nasa.gov/926/egm96/egm96.html",IOGP,"2015/11/25",2015.056,0,
-5172,Nivellement General du Luxembourg,vertical,"Reference point Wemperhardt defined as 528.030m above Normaal Amsterdams Peil (NAP). Datum at NAP is mean high tide in 1684. Network adjusted in 1995.",1995,,,1146,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Administration du Cadastre et de la Topographie. http://www.etat.lu/ACT",OGP,"2004/03/09",,0,
+5150,Bandar Abbas,vertical,Average sea level at Bandar Abbas 1995-2001.,2001-01-01,,,3336,"Topographic mapping, geodetic survey.","Replaces Fao (datum code 5149) in Iran.",National Cartographic Centre of Iran,OGP,"2010/03/01",2010.014,0,
+5151,Nivellement General de Nouvelle Caledonie,vertical,"Rivet AB01 established by SHOM (Service Hydrographique de la Marine)  in 1937 on the Quai des Volontaires in Noumea. Height i: 1.885 metre above mean sea level.",1969-01-01,,,2822,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,Service Topographique de la Nouvelle Caledonie.,OGP,"2004/03/15",2004.060,0,
+5152,Poolbeg,vertical,"Low water mark of the spring tide on the 8 April 1837 at Poolbeg Lighthouse, Dublin.",1837-01-01,,,1305,Topographic mapping before 1956 in Northern Ireland and 1970 in the Republic of Ireland.,"Replaced by Belfast Lough and Malin Head (datum codes 5130-31).","""The Irish Grid - A Description of the Co-ordinate Reference System"" published by Ordnance Survey of Ireland, Dublin and Ordnance Survey of Northern Ireland, Belfast.",OGP,"2003/06/27",,0,
+5153,Nivellement General Guyanais 1977,vertical,"Mean sea level 1936 at Cayenne. Origin = marker BM35 on stone on St Francois battery, Cayenne, with defined elevation of 1.64m above msl. NGG1977 height 0.00m is 1.96m above sounding datum defined at Cayenne in 1936 by SHM.",1977-01-01,,,3146,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",2008.087,0,
+5154,Martinique 1987,vertical,"Mean sea level 1939 at Fort de France. Origin = marker Nbc2 on rebuilt quay wall with defined elevation of 1.38m above msl. Martinique 1987 height 0.00m is 0.56m above SHOM sounding datum.",1987-01-01,,,3276,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaces Martinique 1955 (datum code 5192).",IGN Paris,OGP,"2008/09/19",2004.561 2008.087,0,
+5155,Guadeloupe 1988,vertical,"Mean sea level July 1947 to June 1948 at Pointe-Fouillole (Pointe-à-Pitre harbour). Origin = marker GO-7 (formerly AO'-5) with defined height of 2.67m above msl adopted from 1951 value. Guadeloupe 1988 height 0.00m is 0.46m above 1984 sounding datum.",1988-01-01,,,2892,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaces Guadeloupe 1951 (datum code 5193).",IGN Paris,OGP,"2008/09/17",2004.561 2008.087,0,
+5156,Reunion 1989,vertical,"Mean sea level during part of November 1949 at port of Saint-Pierre. Origin = marker AB-100 with defined elevation of 13.808m above msl.",1989-01-01,,,3337,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights. Replaces Reunion IGN58. Value of marker AB-100 retains height from 1958 adjustment.,IGN Paris,OGP,"2008/09/17",2004.561 2008.087,0,
+5157,Auckland 1946,vertical,MSL at Auckland harbour 1909-1923.,1946-01-01,,,3764,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5158,Bluff 1955,vertical,MSL at Invercargill harbour over 8 years between 1918 and 1934.,1955-01-01,,,3801,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5159,Dunedin 1958,vertical,MSL at Dunedin harbour 1918-1937.,1958-01-01,,,3803,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5160,Gisborne 1926,vertical,MSL at Gisborne harbour 1926.,1926-01-01,,,3771,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5161,Lyttelton 1937,vertical,MSL at Lyttelton harbour over 9 years between 1918 and 1933.,1937-01-01,,,3804,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5162,Moturiki 1953,vertical,MSL at Moturiki Island February 1949 to December 1952.,1953-01-01,,,3768,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5163,Napier 1962,vertical,MSL at Napier harbour. Period of derivation unknown.,1962-01-01,,,3772,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5164,Nelson 1955,vertical,MSL at Nelson harbour 1939-1942.,1955-01-01,,,3802,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5165,One Tree Point 1964,vertical,MSL at Whangarei harbour 1960-1963.,1964-01-01,,,3762,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5166,Tararu 1952,vertical,MSL at Tararu Point 1922-1923.,1952-01-01,,,3818,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5167,Taranaki 1970,vertical,MSL at Taranaki harbour 1918-1921.,1970-01-01,,,3769,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5168,Wellington 1953,vertical,MSL at Wellington harbour 1909-1946.,1953-01-01,,,3773,"Geodetic survey, topographic mapping, engineering survey.",,"OSG Technical Report #10, February 2001.",OGP,"2011/01/25",2008.023 2011.005,0,
+5169,"Waitangi (Chatham Island) 1959",vertical,MSL at Waitangi harbour collected in 1959.,1959-01-01,,,3894,"Geodetic survey, topographic mapping, engineering survey.",,"Interim Report GEO/T1/19/51 for LINZ by John Hannah, ""An Assessment of New Zealand's Height Systems and Options for a Future Height System"", January 2001.",OGP,"2011/06/20",2008.023 2011.048,0,
+5170,Stewart Island 1977,vertical,MSL at 3-5 high and low tides at two different locations.,1977-01-01,,,3338,"Geodetic survey, topographic mapping, engineering survey.",,"Interim Report GEO/T1/19/51 for LINZ by John Hannah, ""An Assessment of New Zealand's Height Systems and Options for a Future Height System"", January 2001.",OGP,"2008/04/04",2008.023,0,
+5171,EGM96 geoid,vertical,Derived through EGM84 geoid undulation model consisting of spherical harmonic coefficients to degree and order 360 applied to the WGS 84 ellipsoid.,1996-01-01,,,1262,Geodesy.,"Replaces EGM84 geoid (datum code 5203). Replaced by EGM2008 geoid (datum code 1027).","NASA http://cddis.gsfc.nasa.gov/926/egm96/egm96.html",IOGP,"2015/11/25",2015.056,0,
+5172,Nivellement General du Luxembourg,vertical,"Reference point Wemperhardt defined as 528.030m above Normaal Amsterdams Peil (NAP). Datum at NAP is mean high tide in 1684. Network adjusted in 1995.",1995-01-01,,,1146,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Administration du Cadastre et de la Topographie. http://www.etat.lu/ACT",OGP,"2004/03/09",,0,
 5173,Antalya,vertical,Mean sea Level at Antalya 1936-71.,,,,3322,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/11/26",2004.722,0,
-5174,Norway Normal Null 1954,vertical,MSL defined by regression at 7 gauges with between 17 and 67 years observations.,1974,,,1352,"Geodetic survey, topographic mapping, engineering survey.",Includes initial NN1954 system and NNN1957 system. Former name retained. Normal-orthometric heights. Replaced by NN2000.,Statoil,OGP,"2012/12/17",2012.094,0,
+5174,Norway Normal Null 1954,vertical,MSL defined by regression at 7 gauges with between 17 and 67 years observations.,1974-01-01,,,1352,"Geodetic survey, topographic mapping, engineering survey.",Includes initial NN1954 system and NNN1957 system. Former name retained. Normal-orthometric heights. Replaced by NN2000.,Statoil,OGP,"2012/12/17",2012.094,0,
 5175,Durres,vertical,Mean Sea Level at Durres.,,,,3212,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5176,Gebrauchshohen ADRIA,vertical,Reference point Hutbiegl defined relative to mean sea level at Trieste in 1875.,,,,1037,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
-5177,National Vertical Network 1999,vertical,Reference point Ruse defined relative to mean sea level at Trieste in 1875.,1999,,,3307,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
-5178,Cascais,vertical,Mean Sea Level at Cascais 1938.,1938,,,1294,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
+5177,National Vertical Network 1999,vertical,Reference point Ruse defined relative to mean sea level at Trieste in 1875.,1999-01-01,,,3307,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
+5178,Cascais,vertical,Mean Sea Level at Cascais 1938.,1938-01-01,,,1294,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5179,Constanta,vertical,Mean Sea Level at Constanta.,,,,3295,"Geodetic survey, topographic mapping, engineering survey.",Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/evrs/Relations.html",OGP,"2004/03/09",,0,
 5180,Alicante,vertical,Mean Sea Level at Alicante between 1870 and 1882.,,,,4188,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2015/01/28",2014.095,0,
-5181,Deutsches Haupthoehennetz 1992,vertical,"Network adjusted in 1992. Geopotential number at reference point Wallenhorst defined as value from the UELN-73/86 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1992,,,3339,"Geodetic survey, topographic mapping, engineering survey.",Replaces DHHN85 in West Germany and SNN76 in East Germany. Uses Normal heights.,"Bundesamt für Kartographie und Geodäsie (BKG), http://crs.bkg.bund.de/crs-eu/",OGP,"2011/08/03",2011.071,0,
-5182,Deutsches Haupthoehennetz 1985,vertical,"Network adjusted in 1985. Height of reference point Wallenhorst defined as value from 1928 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1985,,,2326,"Geodetic survey, topographic mapping, engineering survey.",Replaced by DHHN92. Uses Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2011/08/03",2011.071,0,
-5183,SNN76,vertical,Network adjusted in 1976. Height at reference point Hoppegarten defined as 1957 value from the UPLN adjustment. Datum at Kronstadt is mean sea level of Baltic in 1833.,1976,,,1343,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights. Replaced by DHHN92.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
-5184,Baltic 1982,vertical,Network adjusted in 1982. Height at reference point Varna defined as 1958 value from the UPLN adjustment. Datum at Kronstadt is mean sea level of Baltic in 1833.,1982,,,3224,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
+5181,Deutsches Haupthoehennetz 1992,vertical,"Network adjusted in 1992. Geopotential number at reference point Wallenhorst defined as value from the UELN-73/86 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1992-01-01,,,3339,"Geodetic survey, topographic mapping, engineering survey.",Replaces DHHN85 in West Germany and SNN76 in East Germany. Uses Normal heights.,"Bundesamt für Kartographie und Geodäsie (BKG), http://crs.bkg.bund.de/crs-eu/",OGP,"2011/08/03 [...]
+5182,Deutsches Haupthoehennetz 1985,vertical,"Network adjusted in 1985. Height of reference point Wallenhorst defined as value from 1928 adjustment. Datum at Normaal Amsterdams Peil (NAP) is mean high tide in 1684.",1985-01-01,,,2326,"Geodetic survey, topographic mapping, engineering survey.",Replaced by DHHN92. Uses Normal-orthometric heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2011/08/03",2011.071,0,
+5183,Staatlichen Nivellementnetzes 1976,vertical,Network adjusted in 1976. Height at reference point Hoppegarten defined as 1957 value from the UPLN adjustment. Datum at Kronstadt is mean sea level of Baltic in 1833.,1976-01-01,,,1343,"Geodetic survey, topographic mapping, engineering survey.",Introduced in 1979. Uses Normal heights. Replaced by DHHN92.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",IOGP,"2015/12/30",2015.067,0,
+5184,Baltic 1982,vertical,Network adjusted in 1982. Height at reference point Varna defined as 1958 value from the UPLN adjustment. Datum at Kronstadt is mean sea level of Baltic in 1833.,1982-01-01,,,3224,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5185,Baltic 1980,vertical,,,,,1119,"Geodetic survey, topographic mapping, engineering survey.",Uses Normal heights.,"Eurogeographics, http://crs.bkg.bund.de/crs-eu/",OGP,"2004/03/09",,0,
 5186,Kuwait PWD,vertical,"Mean Low Low Water (MLLW) at Kuwait City.",,,,3267,Municipality and military purposes.,Approximately 1.03m below MSL.,Kuwait Oil Company.,OGP,"2004/06/16",,0,
-5187,KOC Well Datum,vertical,,1937,,,3267,KOC exploration and field development subsurface work.,Approximately 3.22m above MSL.,Kuwait Oil Company.,OGP,"2004/06/16",,0,
-5188,KOC Construction Datum,vertical,,1952,,,3267,KOC survey control and facilities engineering.,Approximately 1.52m below MSL. Created for the construction of the Mina al Ahmadi refinery.,Kuwait Oil Company.,OGP,"2004/06/16",,0,
-5189,Nivellement General de la Corse 1948,vertical,Mean sea level at Ajaccio between 1912 and 1937.,1948,,,1327,"Geodetic survey, topographic mapping, engineering survey.","Replaced by IGN78 Corsica (datum 5120).",IGN Paris,OGP,"2004/10/14",,0,
-5190,Danger 1950,vertical,Marker near tide gauge at port of Saint Pierre. Height is 1.26 metres above zero of tide gauge.,1950,,,3299,"Geodetic survey, topographic mapping, engineering survey.",,IGN Paris,OGP,"2004/10/14",,0,
-5191,Mayotte 1950,vertical,Marker on Issoufali jetty at Dzaoudzi. Height is 2.18m above zero of tide gauge.,1950,,,3340,"Geodetic survey, topographic mapping, engineering survey.",,IGN Paris,OGP,"2004/10/14",,0,
-5192,Martinique 1955,vertical,Mean sea level at Fort de France 1939. Marker DO-4-II on quay wall with elevation of 1.38m above msl.,1955,,,3276,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaced by Martinique 1987 (datum code 5154).",IGN Paris,OGP,"2008/09/17",2008.087,0,
-5193,Guadeloupe 1951,vertical,"Mean sea level July 1947 to June 1948 at Pointe-Fouillole (Pointe-à-Pitre harbour). Origin = marker AO'-12 with height of 1.917m above msl.",1955,,,2892,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaced by Guadeloupe 1988 (datum code 5155). Guadeloupe 1951 height 0.00m is 0.629m above 1947-48 sounding datum.",IGN Paris,OGP,"2008/09/17",2008.087,0,
-5194,Lagos 1955,vertical,"Mean sea level at Lagos, 1912-1928.",1955,,,3287,"Geodetic survey, topographic mapping, engineering survey.",,"Ebong et al, AVN International, 1991.",OGP,"2004/10/14",,0,
+5187,KOC Well Datum,vertical,,1937-01-01,,,3267,KOC exploration and field development subsurface work.,Approximately 3.22m above MSL.,Kuwait Oil Company.,OGP,"2004/06/16",,0,
+5188,KOC Construction Datum,vertical,,1952-01-01,,,3267,KOC survey control and facilities engineering.,Approximately 1.52m below MSL. Created for the construction of the Mina al Ahmadi refinery.,Kuwait Oil Company.,OGP,"2004/06/16",,0,
+5189,Nivellement General de la Corse 1948,vertical,Mean sea level at Ajaccio between 1912 and 1937.,1948-01-01,,,1327,"Geodetic survey, topographic mapping, engineering survey.","Replaced by IGN78 Corsica (datum 5120).",IGN Paris,OGP,"2004/10/14",,0,
+5190,Danger 1950,vertical,Marker near tide gauge at port of Saint Pierre. Height is 1.26 metres above zero of tide gauge.,1950-01-01,,,3299,"Geodetic survey, topographic mapping, engineering survey.",,IGN Paris,OGP,"2004/10/14",,0,
+5191,Mayotte 1950,vertical,Marker on Issoufali jetty at Dzaoudzi. Height is 2.18m above zero of tide gauge.,1950-01-01,,,3340,"Geodetic survey, topographic mapping, engineering survey.",,IGN Paris,OGP,"2004/10/14",,0,
+5192,Martinique 1955,vertical,Mean sea level at Fort de France 1939. Marker DO-4-II on quay wall with elevation of 1.38m above msl.,1955-01-01,,,3276,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaced by Martinique 1987 (datum code 5154).",IGN Paris,OGP,"2008/09/17",2008.087,0,
+5193,Guadeloupe 1951,vertical,"Mean sea level July 1947 to June 1948 at Pointe-Fouillole (Pointe-à-Pitre harbour). Origin = marker AO'-12 with height of 1.917m above msl.",1955-01-01,,,2892,"Geodetic survey, topographic mapping, engineering survey.","Orthometric heights. Replaced by Guadeloupe 1988 (datum code 5155). Guadeloupe 1951 height 0.00m is 0.629m above 1947-48 sounding datum.",IGN Paris,OGP,"2008/09/17",2008.087,0,
+5194,Lagos 1955,vertical,"Mean sea level at Lagos, 1912-1928.",1955-01-01,,,3287,"Geodetic survey, topographic mapping, engineering survey.",,"Ebong et al, AVN International, 1991.",OGP,"2004/10/14",,0,
 5195,Nivellement General de Polynesie Francaise,vertical,,,,,3134,"Geodetic survey, topographic mapping, engineering survey.",The collection of heterogeneous levelling networks throughout the Society Islands of French Polynesia.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
-5196,IGN 1966,vertical,"Fundamental benchmark: RN501",1966,,,3124,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
-5197,Moorea SAU 1981,vertical,"Fundamental benchmark: RN225",1981,,,3125,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
-5198,Raiatea SAU 2001,vertical,"Fundamental benchmark: RN1",2001,,,3136,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
-5199,Maupiti SAU 2001,vertical,"Fundamental benchmark: RN11",2001,,,3126,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
-5200,Huahine SAU 2001,vertical,"Fundamental benchmark: SHOM B3",2001,,,3135,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
-5201,Tahaa SAU 2001,vertical,"Fundamental benchmark: RN16",2001,,,3138,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
-5202,Bora Bora SAU 2001,vertical,"Fundamental benchmark: Vaitape quay SHOM benchmark B.",2001,,,3137,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
-5203,EGM84 geoid,vertical,Derived through EGM84 geoid undulation model consisting of spherical harmonic coefficients to degree and order 180 applied to the WGS 84 ellipsoid.,1987,,,1262,Geodesy.,"Replaced by EGM96 geoid (datum code 5171).","US National Geospatial-Intelligence Agency (NGA); http://earth-info.nga.mil/GandG/",IOGP,"2015/11/25",2015.056,0,
-5204,International Great Lakes Datum 1955,vertical,"Mean water level 1941-1956 at Pointe-au-Père (Father's Point), Quebec. Benchmark 1248-G = 3.794m.",1955,,,3468,Hydrology.,Dynamic heights. Adopted in 1962. Replaced by IGLD 1985 in January 1992.,Coordinating Committee on Great Lakes Basic Hydraulic and Hydrologic Data,OGP,"2012/08/10",2011.047,0,
-5205,International Great Lakes Datum 1985,vertical,"Mean water level 1970-1983 at Pointe-au-Pierre (Father's Point) and 1984-1988 at Rimouski, Quebec. Benchmark 1250-G = 6.273m.",1985,,,3468,Hydrology.,Dynamic heights. Replaces IGLD 1955 from January 1992.,Coordinating Committee on Great Lakes Basic Hydraulic and Hydrologic Data,OGP,"2012/08/10",2011.047,0,
+5196,IGN 1966,vertical,"Fundamental benchmark: RN501",1966-01-01,,,3124,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
+5197,Moorea SAU 1981,vertical,"Fundamental benchmark: RN225",1981-01-01,,,3125,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
+5198,Raiatea SAU 2001,vertical,"Fundamental benchmark: RN1",2001-01-01,,,3136,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
+5199,Maupiti SAU 2001,vertical,"Fundamental benchmark: RN11",2001-01-01,,,3126,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
+5200,Huahine SAU 2001,vertical,"Fundamental benchmark: SHOM B3",2001-01-01,,,3135,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
+5201,Tahaa SAU 2001,vertical,"Fundamental benchmark: RN16",2001-01-01,,,3138,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
+5202,Bora Bora SAU 2001,vertical,"Fundamental benchmark: Vaitape quay SHOM benchmark B.",2001-01-01,,,3137,"Geodetic survey, topographic mapping, engineering survey.",Included as part of NGPF - see datum code 5195.,"Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,
+5203,EGM84 geoid,vertical,Derived through EGM84 geoid undulation model consisting of spherical harmonic coefficients to degree and order 180 applied to the WGS 84 ellipsoid.,1987-01-01,,,1262,Geodesy.,"Replaced by EGM96 geoid (datum code 5171).","US National Geospatial-Intelligence Agency (NGA); http://earth-info.nga.mil/GandG/",IOGP,"2015/11/25",2015.056,0,
+5204,International Great Lakes Datum 1955,vertical,"Mean water level 1941-1956 at Pointe-au-Père (Father's Point), Quebec. Benchmark 1248-G = 3.794m.",1955-01-01,,,3468,Hydrology.,Dynamic heights. Adopted in 1962. Replaced by IGLD 1985 in January 1992.,Coordinating Committee on Great Lakes Basic Hydraulic and Hydrologic Data,OGP,"2012/08/10",2011.047,0,
+5205,International Great Lakes Datum 1985,vertical,"Mean water level 1970-1983 at Pointe-au-Pierre (Father's Point) and 1984-1988 at Rimouski, Quebec. Benchmark 1250-G = 6.273m.",1985-01-01,,,3468,Hydrology.,Dynamic heights. Replaces IGLD 1955 from January 1992.,Coordinating Committee on Great Lakes Basic Hydraulic and Hydrologic Data,OGP,"2012/08/10",2011.047,0,
 5206,Dansk Vertikal Reference 1990,vertical,"Benchmark at Århus cathedral referenced to mean sea level determined during 1990 at 10 tide gauges: Esbjerg, Fredericia, Frederikshavn, Gedser, Hirtshals, Hornbæk, Korsør, København, Slipshavn and Århus.",,,,3237,Topographic mapping and engineering survey,Normal Orthometric heights.,"Kort & Matrikelstyrelsen",OGP,"2006/12/01",,0,
-5207,Croatian Vertical Reference System 1971,vertical,"Mean sea level at five tide gauges in Dubrovnik, Split, Bakar, Rovinj and Kopar at epoch 1971.5",1971,,,3234,Geodesy.,"Replaces Trieste (datum code 1050).",State Geodetic Administration of the Republic of Croatia.,OGP,"2010/07/13",2008.043 2010.064,0,
-5208,Rikets hojdsystem 2000,vertical,"Adjustment is referenced to mean high tide at Amsterdams Peil in 1684. To account for land level movements caused by isostatic rebound, heights are reduced to epoch 2000.0 using values computed from the RH 2000 LU (=NKG2005LU) uplift model.",2000,,,3313,"Topographic mapping, geodetic survey.","Realised through the third precise levelling network of 1979-2003. Adopted in 2005, replacing RH70. Uses Normal heights.",National Land Survey of Sweden,OGP,"2 [...]
-5209,Rikets hojdsystem 1900,vertical,"Adjustment is referenced to mean sea level at Slussen, Stockholm.",1900,,,3313,"Topographic mapping, engineering survey.",Realised through the first precise levelling network of 1886-1905. Replaced by RH70.,National Land Survey of Sweden,OGP,"2008/03/14",,0,
-5210,IGN 1988 LS,vertical,"Mean sea level 1984 at Terre de Haut. Origin = marker O de -5 with defined height of 1.441m above msl. IGN 1988 LS height 0.00m is 0.46m above 1987 sounding datum; this approximately corresponds with msl at Pointe-à-Pitre (see datum code 5155, CRS 5757).",1988,,,2895,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
-5211,IGN 1988 MG,vertical,"Mean sea level 1987 at Grand-Bourg. Origin = marker M0-I with defined height of 0.832m above msl. IGN 1988 MG height 0.00m is 0.46m above 1987 sounding datum; this approximately corresponds with msl at Pointe-à-Pitre (see datum code 5155, CRS code 5757).",1988,,,2894,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
-5212,IGN 1992 LD,vertical,"Mean sea level at Pointe-à-Pitre. Origin = marker A with defined height of 0.792m above msl. IGN 1992 LD height 0.00m is 0.629m above sounding datum at Pointe-à-Pitre.",1992,,,2893,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
-5213,IGN 1988 SB,vertical,"Mean sea level 1988 at port of Gustavia. Origin = marker A.ef-2 with defined height of 0.621m above msl. IGN 1988 SB height 0.00m deduced to be 0.201m above mean sea level at Pointe-à-Pitre.",1988,,,2891,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
-5214,IGN 1988 SM,vertical,"Mean sea level 1949-1950 deduced at Fort Marigot. Origin = marker AS-13 with defined height of 6.990m above msl. IGN 1988 SM height 0.00m deduced to be 0.41m above sounding datum.",1988,,,2890,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
-5215,European Vertical Reference Frame 2007,vertical,Least squares fit to 13 stations of the EVRF2000 solution.,2007,,,3594,Geodesy.,"Realised by geopotential numbers and Normal heights of the United European Levelling Network. Replaces EVRF2000 (datum code 5129).","European veritical data centre at Bundesamt für Kartographie und Geodäsie (BKG), Leipzig branch. http://crs.bkg.bund.de/evrs/",OGP,"2015/02/12",2015.005,0,
+5207,Croatian Vertical Reference System 1971,vertical,"Mean sea level at five tide gauges in Dubrovnik, Split, Bakar, Rovinj and Kopar at epoch 1971.5",1971-01-01,,,3234,Geodesy.,"Replaces Trieste (datum code 1050).",State Geodetic Administration of the Republic of Croatia.,OGP,"2010/07/13",2008.043 2010.064,0,
+5208,Rikets hojdsystem 2000,vertical,"Adjustment is referenced to mean high tide at Amsterdams Peil in 1684. To account for land level movements caused by isostatic rebound, heights are reduced to epoch 2000.0 using values computed from the RH 2000 LU (=NKG2005LU) uplift model.",2000-01-01,,,3313,"Topographic mapping, geodetic survey.","Realised through the third precise levelling network of 1979-2003. Adopted in 2005, replacing RH70. Uses Normal heights.",National Land Survey of Sweden, [...]
+5209,Rikets hojdsystem 1900,vertical,"Adjustment is referenced to mean sea level at Slussen, Stockholm.",1900-01-01,,,3313,"Topographic mapping, engineering survey.",Realised through the first precise levelling network of 1886-1905. Replaced by RH70.,National Land Survey of Sweden,OGP,"2008/03/14",,0,
+5210,IGN 1988 LS,vertical,"Mean sea level 1984 at Terre de Haut. Origin = marker O de -5 with defined height of 1.441m above msl. IGN 1988 LS height 0.00m is 0.46m above 1987 sounding datum; this approximately corresponds with msl at Pointe-à-Pitre (see datum code 5155, CRS 5757).",1988-01-01,,,2895,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
+5211,IGN 1988 MG,vertical,"Mean sea level 1987 at Grand-Bourg. Origin = marker M0-I with defined height of 0.832m above msl. IGN 1988 MG height 0.00m is 0.46m above 1987 sounding datum; this approximately corresponds with msl at Pointe-à-Pitre (see datum code 5155, CRS code 5757).",1988-01-01,,,2894,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
+5212,IGN 1992 LD,vertical,"Mean sea level at Pointe-à-Pitre. Origin = marker A with defined height of 0.792m above msl. IGN 1992 LD height 0.00m is 0.629m above sounding datum at Pointe-à-Pitre.",1992-01-01,,,2893,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
+5213,IGN 1988 SB,vertical,"Mean sea level 1988 at port of Gustavia. Origin = marker A.ef-2 with defined height of 0.621m above msl. IGN 1988 SB height 0.00m deduced to be 0.201m above mean sea level at Pointe-à-Pitre.",1988-01-01,,,2891,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
+5214,IGN 1988 SM,vertical,"Mean sea level 1949-1950 deduced at Fort Marigot. Origin = marker AS-13 with defined height of 6.990m above msl. IGN 1988 SM height 0.00m deduced to be 0.41m above sounding datum.",1988-01-01,,,2890,"Geodetic survey, topographic mapping, engineering survey.",Orthometric heights.,IGN Paris,OGP,"2008/09/17",,0,
+5215,European Vertical Reference Frame 2007,vertical,Least squares fit to 13 stations of the EVRF2000 solution.,2007-01-01,,,3594,Geodesy.,"Realised by geopotential numbers and Normal heights of the United European Levelling Network. Replaces EVRF2000 (datum code 5129).","European veritical data centre at Bundesamt für Kartographie und Geodäsie (BKG), Leipzig branch. http://crs.bkg.bund.de/evrs/",OGP,"2015/02/12",2015.005,0,
 6001,"Not specified (based on Airy 1830 ellipsoid)",geodetic,,,7001,8901,1263,Not a valid datum.,Included for coordinate reference systems where datum is unknown.,OGP,OGP,"2000/05/03",1996.080 2000.420,0,"D_Airy_1830"
 6002,"Not specified (based on Airy Modified 1849 ellipsoid)",geodetic,,,7002,8901,1263,Not a valid datum.,Included for coordinate reference systems where datum is unknown.,OGP,OGP,"2000/05/03",1996.080 2000.420,0,"D_Airy_Modified"
 6003,"Not specified (based on Australian National Spheroid)",geodetic,,,7003,8901,1263,Not a valid datum.,Included for coordinate reference systems where datum is unknown.,OGP,OGP,"2000/05/03",1996.080 2000.420,0,"D_Australian"
@@ -288,396 +315,396 @@ http://www.maanmittauslaitos.fi",OGP,"2010/05/02",2008.112,0,
 6054,"Not specified (based on Hughes 1980 ellipsoid)",geodetic,,,7058,8901,1263,Not a valid datum.,Included for coordinate reference systems where datum is unknown.,OGP,OGP,"2006/09/22",,0,"D_Hughes_1980"
 6055,Popular Visualisation Datum,geodetic,Not specified in the classical sense of defining a geodetic datum.,,7059,8901,1262,Used by certain popular Web mapping and visualisation applications.,Not recognised by geodetic authorities.,Microsoft.,OGP,"2008/03/13",2008.114,1,
 6120,Greek,geodetic,"Fundamental point: Athens Observatory. Latitude 37°58'20.132""N, longitude 23°42'58.815""E (of Greenwich)",,7004,8901,3254,Topographic mapping.,"See geodetic datum alias 6404.  Used as basis of topographic mapping based on Hatt projection. Replaced by GGRS87 (code 6121).","Topography Department; National Technical University of Athens",OGP,"2011/07/20",2004.183 2008.045 2011.062,0,"D_Greek"
-6121,Greek Geodetic Reference System 1987,geodetic,"Fundamental point: Dionysos. Latitude 38°04'33.8""N, longitude 23°55'51.0""E of Greenwich; geoid height 7.0 m.",1987,7019,8901,3254,Topographic mapping.,"Replaced (old) Greek datum.  Oil industry work based on ED50.","L. Portokalakis; Public Petroleum Corporation of Greece",OGP,"2011/07/20",2008.045 2011.062,0,"D_GGRS_1987"
-6122,Average Terrestrial System 1977,geodetic,,1977,7041,8901,1283,Topographic mapping.,"In use from 1979.  To be phased out in late 1990's.",New Brunswick Geographic Information Corporation land and water information standards manual.,OGP,"1997/07/02",,0,"D_ATS_1977"
-6123,"Kartastokoordinaattijarjestelma (1966)",geodetic,Adjustment with fundamental point SF31 based on ED50 transformed to best fit the older VVJ adjustment.,1966,7022,8901,3333,"Geodetic survey, cadastre, topographic mapping, engineering survey.",Adopted in 1970.,"National Land Survey of Finland;
+6121,Greek Geodetic Reference System 1987,geodetic,"Fundamental point: Dionysos. Latitude 38°04'33.8""N, longitude 23°55'51.0""E of Greenwich; geoid height 7.0 m.",1987-01-01,7019,8901,3254,Topographic mapping.,"Replaced (old) Greek datum.  Oil industry work based on ED50.","L. Portokalakis; Public Petroleum Corporation of Greece",OGP,"2011/07/20",2008.045 2011.062,0,"D_GGRS_1987"
+6122,Average Terrestrial System 1977,geodetic,,1977-01-01,7041,8901,1283,Topographic mapping.,"In use from 1979.  To be phased out in late 1990's.",New Brunswick Geographic Information Corporation land and water information standards manual.,OGP,"1997/07/02",,0,"D_ATS_1977"
+6123,"Kartastokoordinaattijarjestelma (1966)",geodetic,Adjustment with fundamental point SF31 based on ED50 transformed to best fit the older VVJ adjustment.,1966-01-01,7022,8901,3333,"Geodetic survey, cadastre, topographic mapping, engineering survey.",Adopted in 1970.,"National Land Survey of Finland;
 http://www.maanmittauslaitos.fi",OGP,"2011/06/30",2006.270 2011.055,0,"D_KKJ"
-6124,Rikets koordinatsystem 1990,geodetic,,1982,7004,8901,1225,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces RT38 adjustment (datum code 6308)",National Land Survey of Sweden,OGP,"1997/11/13",,0,"D_RT_1990"
+6124,Rikets koordinatsystem 1990,geodetic,,1982-01-01,7004,8901,1225,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces RT38 adjustment (datum code 6308)",National Land Survey of Sweden,OGP,"1997/11/13",,0,"D_RT_1990"
 6125,Samboja,geodetic,Original origin station P2 Exc now destroyed.  Extensions recomputed using Toran station T9 as origin.,,7004,8901,1328,Topographic mapping.,,Total Indonesia.,OGP,"1997/11/13",,1,"D_Samboja"
-6126,"Lithuania 1994 (ETRS89)",geodetic,Constrained to 4 ETRS89 points in Lithuania from the EUREF Baltic 1992 campaign..,1994,7019,8901,1145,"Topographic mapping, geodetic survey.",Densification of ETRS89 during the 1992 Baltic campaign.,HNIT-Baltic GeoInfoServisas,OGP,"1998/03/12",,0,"D_Lithuania_1994"
-6127,Tete,geodetic,"Fundamental point: Tete.",1960,7008,8901,3281,Topographic mapping.,,"Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"2014/11/19",2014.076,0,"D_Tete"
+6126,"Lithuania 1994 (ETRS89)",geodetic,Constrained to 4 ETRS89 points in Lithuania from the EUREF Baltic 1992 campaign.,1992-10-01,7019,8901,1145,"Topographic mapping, geodetic survey.",Densification of ETRS89 during the 1992 Baltic campaign.,HNIT-Baltic GeoInfoServisas,IOGP,"2016/09/16",2016.020,0,"D_Lithuania_1994"
+6127,Tete,geodetic,"Fundamental point: Tete.",1960-01-01,7008,8901,3281,Topographic mapping.,,"Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"2014/11/19",2014.076,0,"D_Tete"
 6128,Madzansua,geodetic,"Fundamental point: Madzansua.",,7008,8901,1315,Topographic mapping.,"Replaced by transformation to Tete datum (datum code 6127).","Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"1998/04/16",,0,"D_Madzansua"
-6129,Observatario,geodetic,"Fundamental point: Campos Rodrigues observatory, Maputo.",1907,7008,8901,1329,Topographic mapping.,"Replaced by transformation to Tete datum (datum code 6127).","Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"2014/11/19",2014.076,0,"D_Observatario"
-6130,"Moznet (ITRF94)",geodetic,ITRF94 at epoch 1996.9,,7030,8901,1167,Topographic mapping.,,"Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"2006/08/18",2006.770,0,"D_Moznet"
+6129,Observatario,geodetic,"Fundamental point: Campos Rodrigues observatory, Maputo.",1907-01-01,7008,8901,1329,Topographic mapping.,"Replaced by transformation to Tete datum (datum code 6127).","Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",OGP,"2014/11/19",2014.076,0,"D_Observatario"
+6130,"Moznet (ITRF94)",geodetic,ITRF94 at epoch 1996.9,1996-11-24,7030,8901,1167,Topographic mapping.,,"Mozambique Direcção Nacional de Geografia e Cadastral (DINAGECA).",IOGP,"2016/09/16",2006.770 2016.020,0,"D_Moznet"
 6131,Indian 1960,geodetic,DMA extension over IndoChina of the Indian 1954 network adjusted  to better fit local geoid.,,7015,8901,4007,Topographic mapping.,"Also known as Indian (DMA Reduced).",,OGP,"2012/03/25",2003.361 2012.032,0,"D_Indian_1960"
 6132,Final Datum 1958,geodetic,"Fundamental point: Maniyur.  Latitude: 31°23'59.19""N, longitude: 48°32'31.38""E (of Greenwich).",,7012,8901,1300,Oil industry mapping.,Network included in Nahrwan 1967 adjustment.,IOEPC records,OGP,"2008/06/24",2008.045,0,"D_FD_1958"
-6133,Estonia 1992,geodetic,Densification from 4 ETRS89 points.,1992,7019,8901,3246,"Topographic mapping, Geodetic survey.","Based on ETRS89 as established during the 1992 Baltic campaign. Replaced by Estonia 1997 adjustment (code 6180).","http://www.geo.ut.ee",OGP,"2011/06/30",2005.460 2011.055,0,"D_Estonia_1992"
-6134,PDO Survey Datum 1993,geodetic,Adjustment best fitted to Fahud network.,1993,7012,8901,3288,Oil industry mapping.,"Replaces Fahud datum (code 6232). Maximum differences to Fahud adjustment are 20 metres.",Petroleum Development Oman,OGP,"1999/04/22",,0,"D_PDO_1993"
+6133,Estonia 1992,geodetic,Densification from 4 ETRS89 points.,1992-10-01,7019,8901,3246,"Topographic mapping, Geodetic survey.","Based on ETRS89 as established during the 1992 Baltic campaign. Replaced by Estonia 1997 adjustment (code 6180).","http://www.geo.ut.ee",IOGP,"2016/09/16",2005.460 2011.055 2016.020,0,"D_Estonia_1992"
+6134,PDO Survey Datum 1993,geodetic,Adjustment best fitted to Fahud network.,1993-01-01,7012,8901,3288,Oil industry mapping.,"Replaces Fahud datum (code 6232). Maximum differences to Fahud adjustment are 20 metres.",Petroleum Development Oman,OGP,"1999/04/22",,0,"D_PDO_1993"
 6135,Old Hawaiian,geodetic,"Fundamental point: Oahu West Base Astro.  Latitude: 21°18'13.89""N, longitude 157°50'55.79""W (of Greenwich)",,7008,8901,1334,Topographic mapping.,"Hawaiian Islands were never on NAD27 but rather on Old Hawaiian Datum.  NADCON conversion program provides transformation from Old Hawaiian Datum to NAD83 (original 1986 realization) but making the transformation appear to user as if from NAD27.","http://www.ngs.noaa.gov/ (NADCON readme file).",OGP,"2008/06/24",200 [...]
 6136,St. Lawrence Island,geodetic,,,7008,8901,1332,Topographic mapping.,"Many Alaskan islands were never on NAD27 but rather on independent datums.  NADCON conversion program provides transformation from St. Lawrence Island Datum to NAD83 (original 1986 realization) - making the transformation appear to user as if from NAD27.","http://www.ngs.noaa.gov/ (NADCON readme file)",OGP,"1999/05/24",,0,"D_St_Lawrence_Island"
 6137,St. Paul Island,geodetic,"Fundamental point latitude: 57°07'16.86""N, longitude: 170°16'24.00""W (of Greenwich).",,7008,8901,1333,Topographic mapping.,"Many Alaskan islands were never on NAD27 but rather on independent datums.  NADCON conversion program provides transformation from St. Paul Island Datum to NAD83 (original 1986 realization) - making the transformation appear to user as if from NAD27.","http://www.ngs.noaa.gov/ (NADCON readme file)",OGP,"2008/06/24",2008.045,0,"D_St_P [...]
 6138,St. George Island,geodetic,"Fundamental point latitude: 56°36'11.31""N, longitude: 169°32'36.00""W (of Greenwich).",,7008,8901,1331,Topographic mapping.,"Many Alaskan islands were never on NAD27 but rather on independent datums.  NADCON conversion program provides transformation from St. George Island Datum to NAD83 (original 1986 realization) - making the transformation appear to user as if from NAD27.","http://www.ngs.noaa.gov/ (NADCON readme file)",OGP,"2008/06/24",2003.362 2008. [...]
-6139,Puerto Rico,geodetic,"Fundamental point: Cardona Island Lighthouse. Latitude:17°57'31.40""N, longitude: 66°38'07.53""W (of Greenwich).",1901,7008,8901,1335,Topographic mapping.,"NADCON conversion program provides transformation from Puerto Rico Datum to NAD83 (original 1986 realization) but making the transformation appear to user as if from NAD27.","Ordnance Survey of Great Britain and http://www.ngs.noaa.gov/ (NADCON readme file).",OGP,"2008/06/24",2003.362 2008.045,0,"D_Puerto_Rico"
-6140,NAD83 Canadian Spatial Reference System,geodetic,,1998,7019,8901,1061,Geodetic survey.,,"Natural Resources of Canada, CSRS website.  http://www.geod.nrcan.gc.ca",OGP,"2007/09/25",2005.880 2006.461 2007.026 2007.092,0,"D_North_American_1983_CSRS"
+6139,Puerto Rico,geodetic,"Fundamental point: Cardona Island Lighthouse. Latitude:17°57'31.40""N, longitude: 66°38'07.53""W (of Greenwich).",1901-01-01,7008,8901,1335,Topographic mapping.,"NADCON conversion program provides transformation from Puerto Rico Datum to NAD83 (original 1986 realization) but making the transformation appear to user as if from NAD27.","Ordnance Survey of Great Britain and http://www.ngs.noaa.gov/ (NADCON readme file).",OGP,"2008/06/24",2003.362 2008.045,0,"D_Pue [...]
+6140,NAD83 Canadian Spatial Reference System,geodetic,,1998-01-01,7019,8901,1061,Geodetic survey.,,"Natural Resources of Canada, CSRS website.  http://www.geod.nrcan.gc.ca",OGP,"2007/09/25",2005.880 2006.461 2007.026 2007.092,0,"D_North_American_1983_CSRS"
 6141,Israel 1993,geodetic,"Fundamental point:  Latitude: 31°44'03.817""N, longitude: 35°12'16.261""E (of Greenwich).",,7019,8901,2603,Topographic mapping.,"Replaces Palestine 1923 (datum code 6281). Replaced by IGD05 (datum code 1143).",Survey of Israel.,OGP,"2014/11/21",2002.340 2004.150 2008.045 2014.041,0,"D_Israel"
-6142,Locodjo 1965,geodetic,"Fundamental point: T5 Banco. Latitude: 5°18'50.5""N, longitude: 4°02'05.1""W (of Greenwich).",1965,7012,8901,1075,Topographic mapping.,,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Locodjo_1965"
-6143,Abidjan 1987,geodetic,"Fundamental point: Abidjan I. Latitude: 5°18'51.01""N, longitude: 4°02'06.04""W (of Greenwich).",1987,7012,8901,1075,Topographic mapping.,,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Abidjan_1987"
-6144,Kalianpur 1937,geodetic,"Fundamental point: Kalianpur. Latitude: 24° 07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1937,7015,8901,1308,Topographic mapping.,Replaces 1880 adjustment except for topographic mapping.  Replaced in Bangladesh and Pakistan by 1962 metrication conversion and in India by 1975 metrication conversion.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,"2008/06/24",2008.045,0,"D_Kalianpur_1937"
-6145,Kalianpur 1962,geodetic,"Fundamental point: Kalianpur. Latitude: 24° 07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1962,7044,8901,3289,Topographic mapping.,"1937 adjustment rescaled by ratio metric conversions of Indian foot (1937) to Indian foot (1962).",,OGP,"2008/06/24",2008.045,0,"D_Kalianpur_1962"
-6146,Kalianpur 1975,geodetic,"Fundamental point: Kalianpur. Latitude: 24° 07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1975,7045,8901,3341,Topographic mapping.,"1937 adjustment rescaled by ratio metric conversions of Indian foot (1937) to Indian foot (1975).",,OGP,"2008/06/24",2008.045,0,"D_Kalianpur_1975"
-6147,Hanoi 1972,geodetic,,1972,7024,8901,3328,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,PetroVietnam,OGP,"1999/10/20",,0,"D_Hanoi_1972"
-6148,Hartebeesthoek94,geodetic,Coincident with ITRF91 at epoch 1994.0 at Hartebeesthoek astronomical observatory near Pretoria.,1994,7030,8901,1215,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Cape datum (code 6222).","Directorate of Surveys and Mapping; http://w3sli.wcape.gov.za/surveys/mapping/wgs84.htm",OGP,"2006/08/18",1999.960 2006.770,0,"D_Hartebeesthoek_1994"
-6149,CH1903,geodetic,"Fundamental point: Old Bern observatory. Latitude: 46°57'08.660""N, longitude: 7°26'22.500""E (of Greenwich).",1903,7004,8901,1286,Topographic mapping.,,"Bundesamt für Landestopographie",OGP,"2008/06/24",2008.045,0,"D_CH1903"
+6142,Locodjo 1965,geodetic,"Fundamental point: T5 Banco. Latitude: 5°18'50.5""N, longitude: 4°02'05.1""W (of Greenwich).",1965-01-01,7012,8901,1075,Topographic mapping.,,IGN Paris.,IOGP,"2016/12/15",2008.045 2016.048,0,"D_Locodjo_1965"
+6143,Abidjan 1987,geodetic,"Fundamental point: Abidjan I. Latitude: 5°18'51.01""N, longitude: 4°02'06.04""W (of Greenwich).",1987-01-01,7012,8901,1075,Topographic mapping.,,IGN Paris.,IOGP,"2016/12/15",2008.045 2016.048,0,"D_Abidjan_1987"
+6144,Kalianpur 1937,geodetic,"Fundamental point: Kalianpur. Latitude: 24° 07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1937-01-01,7015,8901,1308,Topographic mapping.,Replaces 1880 adjustment except for topographic mapping.  Replaced in Bangladesh and Pakistan by 1962 metrication conversion and in India by 1975 metrication conversion.,"G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,"2008/06/24",2008.045,0,"D_Ka [...]
+6145,Kalianpur 1962,geodetic,"Fundamental point: Kalianpur. Latitude: 24° 07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1962-01-01,7044,8901,3289,Topographic mapping.,"1937 adjustment rescaled by ratio metric conversions of Indian foot (1937) to Indian foot (1962).",,OGP,"2008/06/24",2008.045,0,"D_Kalianpur_1962"
+6146,Kalianpur 1975,geodetic,"Fundamental point: Kalianpur. Latitude: 24° 07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1975-01-01,7045,8901,3341,Topographic mapping.,"1937 adjustment rescaled by ratio metric conversions of Indian foot (1937) to Indian foot (1975).",,OGP,"2008/06/24",2008.045,0,"D_Kalianpur_1975"
+6147,Hanoi 1972,geodetic,,1972-01-01,7024,8901,3328,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,PetroVietnam,OGP,"1999/10/20",,0,"D_Hanoi_1972"
+6148,Hartebeesthoek94,geodetic,Coincident with ITRF91 at epoch 1994.0 at Hartebeesthoek astronomical observatory near Pretoria.,1994-01-01,7030,8901,1215,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Cape datum (code 6222).","Directorate of Surveys and Mapping; http://w3sli.wcape.gov.za/surveys/mapping/wgs84.htm",OGP,"2006/08/18",1999.960 2006.770,0,"D_Hartebeesthoek_1994"
+6149,CH1903,geodetic,"Fundamental point: Old Bern observatory. Latitude: 46°57'08.660""N, longitude: 7°26'22.500""E (of Greenwich).",1903-01-01,7004,8901,1286,Topographic mapping.,,"Bundesamt für Landestopographie",OGP,"2008/06/24",2008.045,0,"D_CH1903"
 6150,"CH1903+",geodetic,"Fundamental point: Zimmerwald observatory.",,7004,8901,1286,"Geodetic survey, topographic mapping.",,"Bundesamt für Landestopographie.  Aufbau der Landesvermessung der Schweiz 'LV95' Teil 3: Terrestrische Bezugssysteme und Bezugsrahmen. L+T 1999.",OGP,"2001/11/06",2001.520,0,"D_CH1903+"
-6151,Swiss Terrestrial Reference Frame 1995,geodetic,ETRF89 at epoch 1993.0,1995,7019,8901,1286,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Bundesamt für Landestopographie.  Aufbau der Landesvermessung der Schweiz 'LV95' Teil 3: Terrestrische Bezugssysteme und Bezugsrahmen. L+T 1999.",OGP,"2006/08/18",2006.770,0,"D_Swiss_TRF_1995"
+6151,Swiss Terrestrial Reference Frame 1995,geodetic,ETRF89 at epoch 1993.0,1993-01-01,7019,8901,1286,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Bundesamt für Landestopographie.  Aufbau der Landesvermessung der Schweiz 'LV95' Teil 3: Terrestrische Bezugssysteme und Bezugsrahmen. L+T 1999.",IOGP,"2016/09/16",2006.770 2016.020,0,"D_Swiss_TRF_1995"
 6152,"NAD83 (High Accuracy Reference Network)",geodetic,,,7019,8901,1337,Geodetic survey.,"In CONUS, Puerto Rico and US Virgin Islands replaced by NAD83(NSRS2007). In American Samoa and Hawaii replaced by NAD83(PA11). In Guam replaced by NAD83(MA11).",National Geodetic Survey,OGP,"2013/06/12",2009.044 2010.061 2011.009 2013.022,0,"D_North_American_1983_HARN"
-6153,Rassadiran,geodetic,"Fundamental point: Total1. Latitude: 27°31'07.784""N, longitude: 52°36'12.741""E (of Greenwich).",1998,7022,8901,1338,Oil industry mapping.,,Total-Fina,OGP,"2008/06/24",2008.045,0,"D_Rassadiran"
-6154,"European Datum 1950(1977)",geodetic,Extension of ED50 over Iran.,1977,7022,8901,1123,Topographic mapping.,Sometimes referred to as ED50-ED77.,National Cartographic Centre of Iran,OGP,"1999/11/20",,0,"D_European_1950_ED77"
-6155,Dabola 1981,geodetic,,1981,7011,8901,3257,Topographic mapping.,,IGN Paris,OGP,"1999/12/09",,0,"D_Dabola_1981"
+6153,Rassadiran,geodetic,"Fundamental point: Total1. Latitude: 27°31'07.784""N, longitude: 52°36'12.741""E (of Greenwich).",1998-01-01,7022,8901,1338,Oil industry mapping.,,Total-Fina,OGP,"2008/06/24",2008.045,0,"D_Rassadiran"
+6154,"European Datum 1950(1977)",geodetic,Extension of ED50 over Iran.,1977-01-01,7022,8901,1123,Topographic mapping.,Sometimes referred to as ED50-ED77.,National Cartographic Centre of Iran,OGP,"1999/11/20",,0,"D_European_1950_ED77"
+6155,Dabola 1981,geodetic,,1981-01-01,7011,8901,3257,Topographic mapping.,,IGN Paris,OGP,"1999/12/09",,0,"D_Dabola_1981"
 6156,System Jednotne Trigonometricke Site Katastralni,geodetic,"Modification of Austrian MGI datum, code 6312.",,7004,8901,1306,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Research Institute for Geodesy Topography and Cartography (VUGTK); Prague.",OGP,"2010/11/02",2001.260 2001.510 2010.071,0,"D_S_JTSK"
 6157,Mount Dillon,geodetic,"Fundamental point: Mount Dillon triangulation station. Latitude: 11°15'07.843""N, longitude: 60°41'09.632""W (of Greenwich).",,7007,8901,1322,Topographic mapping.,,University of the West Indies Geodetic Services.,OGP,"2008/06/24",2003.361 2008.045,0,"D_Mount_Dillon"
-6158,Naparima 1955,geodetic,"Fundamental point: Naparima. Latitude: 10°16'44.860""N, longitude: 61°27'34.620""W (of Greenwich).",1955,7022,8901,3143,Topographic mapping.,Naparima 1972 is an extension of the Naparima 1955 network of Trinidad to include Tobago.,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Naparima_1955"
-6159,European Libyan Datum 1979,geodetic,Extension of ED50 over Libya.,1979,7022,8901,1143,Topographic mapping.,,Brown and Root,OGP,"2003/12/31",2003.362,0,"D_European_Libyan_1979"
-6160,Chos Malal 1914,geodetic,Chos Malal police station.,1914,7022,8901,1292,Oil industry mapping.,"Also known as Quini-Huao.  Replaced by Campo Inchauspe (code 6221).",Various oil company records.,OGP,"2000/03/07",,0,"D_Chos_Malal_1914"
+6158,Naparima 1955,geodetic,"Fundamental point: Naparima. Latitude: 10°16'44.860""N, longitude: 61°27'34.620""W (of Greenwich).",1955-01-01,7022,8901,3143,Topographic mapping.,Naparima 1972 is an extension of the Naparima 1955 network of Trinidad to include Tobago.,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Naparima_1955"
+6159,European Libyan Datum 1979,geodetic,Extension of ED50 over Libya.,1979-01-01,7022,8901,1143,Topographic mapping.,,Brown and Root,OGP,"2003/12/31",2003.362,0,"D_European_Libyan_1979"
+6160,Chos Malal 1914,geodetic,Chos Malal police station.,1914-01-01,7022,8901,1292,Oil industry mapping.,"Also known as Quini-Huao.  Replaced by Campo Inchauspe (code 6221).",Various oil company records.,OGP,"2000/03/07",,0,"D_Chos_Malal_1914"
 6161,Pampa del Castillo,geodetic,,,7022,8901,1265,Oil industry mapping.,"Used in Comodoro Rivadavia area.  Replaced by Campo Inchauspe (code 6221).",Various oil company records.,OGP,"2000/03/07",,0,"D_Pampa_del_Castillo"
-6162,Korean Datum 1985,geodetic,"Fundamental point: Suwon. Latitude 37°16'31.9034""N, longitude 127°03'05.1451""E of Greenwich. This is consistent with the Tokyo 1918 datum latitude and longitude.",1985,7004,8901,3266,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Tokyo 1918 (datum code 6301). Replaced by Korea 2000 (datum code 6737).","Clifford J. Mugnier; in Photogrammetric Engineering & Remote Sensing November 1999. http://www.asprs.org/",OGP,"2010/06/ [...]
-6163,Yemen National Geodetic Network 1996,geodetic,"Sana'a IGN reference marker.",1996,7030,8901,1257,Topographic mapping.,,IGN Paris,OGP,"2000/03/07",,0,"D_Yemen_NGN_1996"
+6162,Korean Datum 1985,geodetic,"Fundamental point: Suwon. Latitude 37°16'31.9034""N, longitude 127°03'05.1451""E of Greenwich. This is consistent with the Tokyo 1918 datum latitude and longitude.",1985-01-01,7004,8901,3266,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Tokyo 1918 (datum code 6301). Replaced by Korea 2000 (datum code 6737).","Clifford J. Mugnier; in Photogrammetric Engineering & Remote Sensing November 1999. http://www.asprs.org/",OGP,"20 [...]
+6163,Yemen National Geodetic Network 1996,geodetic,"Sana'a IGN reference marker.",1996-01-01,7030,8901,1257,Topographic mapping.,,IGN Paris,OGP,"2000/03/07",,0,"D_Yemen_NGN_1996"
 6164,South Yemen,geodetic,,,7024,8901,1340,Topographic mapping.,,IGN Paris,OGP,"2000/03/07",,0,"D_South_Yemen"
 6165,Bissau,geodetic,,,7022,8901,3258,Topographic mapping.,,"NIMA TR8350.2  ftp://164.214.2.65/pub/gig/tr8350.2/changes.pdf",OGP,"2005/09/05",2005.460,0,"D_Bissau"
-6166,Korean Datum 1995,geodetic,,1995,7030,8901,3266,Topographic mapping.,,"NIMA TR8350.2  ftp://164.214.2.65/pub/gig/tr8350.2/changes.pdf",OGP,"2005/09/05",2005.460,0,"D_Korean_Datum_1995"
-6167,New Zealand Geodetic Datum 2000,geodetic,Based on ITRF96 at epoch 2000.0,2000,7019,8901,1175,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces New Zealand Geodetic Datum 1949 (code 6272) and Chatham Islands Datum 1979 (code 6673) from March 2000.","Land Information New Zealand. http://www.linz.govt.nz/rcs/linz/pub/web/root/core/SurveySystem/GeodeticInfo/GeodeticDatums/nzgd2000factsheet/index.jsp",OGP,"2007/09/29",2004.110 2007.090,0,"D_NZGD_2000"
+6166,Korean Datum 1995,geodetic,,1995-01-01,7030,8901,3266,Topographic mapping.,,"NIMA TR8350.2  ftp://164.214.2.65/pub/gig/tr8350.2/changes.pdf",OGP,"2005/09/05",2005.460,0,"D_Korean_Datum_1995"
+6167,New Zealand Geodetic Datum 2000,geodetic,Based on ITRF96 at epoch 2000.0,2000-01-01,7019,8901,1175,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces New Zealand Geodetic Datum 1949 (code 6272) and Chatham Islands Datum 1979 (code 6673) from March 2000.","Land Information New Zealand. http://www.linz.govt.nz/rcs/linz/pub/web/root/core/SurveySystem/GeodeticInfo/GeodeticDatums/nzgd2000factsheet/index.jsp",OGP,"2007/09/29",2004.110 2007.090,0,"D_NZGD_2000"
 6168,Accra,geodetic,"Fundamental point: GCS Station 547. Latitude: 5°23'43.3""N, longitude: 0°11'52.3""W (of Greenwich).",,7029,8901,1104,Topographic mapping.,"Replaced in 1978 by Leigon datum (code 6250).",Ordnance Survey International,OGP,"2008/06/24",2008.045,0,"D_Accra"
-6169,American Samoa 1962,geodetic,"Fundamental point: Betty 13 eccentric. Latitude: 14°20'08.34""S, longitude: 170°42'52.25""W (of Greenwich).",1962,7008,8901,3109,Topographic mapping.,,NIMA TR8350.2 revision of January 2000. Oil industry sources for origin description details.,OGP,"2008/06/24",2003.362 2005.230 2008.045,0,"D_American_Samoa_1962"
-6170,Sistema de Referencia Geocentrico para America del Sur 1995,geodetic,ITRF94 at epoch 1995.42.,1995,7019,8901,3448,Geodetic survey.,Realised by a frame of 58 stations observed in 1995 and adjusted in the ITRF94. Replaced by SIRGAS 2000.,"NIMA TR8350.2 revision of January 2000. Also http://www1.ibge.gov.br/",OGP,"2006/08/18",2004.250 2005.460 2006.465 2006.770,0,"D_SIRGAS"
-6171,Reseau Geodesique Francais 1993,geodetic,Coincident with ETRS89 at epoch 1993.0,1993,7019,8901,1096,Geodetic survey.,,"http://www.ign.fr/ via TotalFinaElf",OGP,"2005/09/05",2001.510 2005.460,0,"D_RGF_1993"
-6172,Posiciones Geodesicas Argentinas,geodetic,,1994,7019,8901,1033,"Topographic mapping, geodetic survey.","Una red geodésica de 127 puntos materializados
+6169,American Samoa 1962,geodetic,"Fundamental point: Betty 13 eccentric. Latitude: 14°20'08.34""S, longitude: 170°42'52.25""W (of Greenwich).",1962-01-01,7008,8901,3109,Topographic mapping.,,NIMA TR8350.2 revision of January 2000. Oil industry sources for origin description details.,OGP,"2008/06/24",2003.362 2005.230 2008.045,0,"D_American_Samoa_1962"
+6170,Sistema de Referencia Geocentrico para America del Sur 1995,geodetic,ITRF94 at epoch 1995.42.,1995-06-02,7019,8901,3448,Geodetic survey.,Realised by a frame of 58 stations observed in 1995 and adjusted in the ITRF94. Replaced by SIRGAS 2000.,"NIMA TR8350.2 revision of January 2000. Also http://www1.ibge.gov.br/",IOGP,"2016/09/16",2004.250 2005.460 2006.465 2006.770 2016.020,0,"D_SIRGAS"
+6171,Reseau Geodesique Francais 1993,geodetic,Coincident with ETRS89 at epoch 1993.0,1993-01-01,7019,8901,1096,Geodetic survey.,,"http://www.ign.fr/ via TotalFinaElf",OGP,"2005/09/05",2001.510 2005.460,0,"D_RGF_1993"
+6172,Posiciones Geodesicas Argentinas,geodetic,,1994-01-01,7019,8901,1033,"Topographic mapping, geodetic survey.","Una red geodésica de 127 puntos materializados
 en el terreno que definen el Sistema Geodésico Nacional.  [A geodetic network of 127 points defining the National Geodetic System.] Replaced by POSGAR98 (code 6190).","http://www.igm.gov.ar/posgar.html",OGP,"2000/10/19",,1,"D_POSGAR"
-6173,IRENET95,geodetic,ETRS89 stations in Ireland,1995,7019,8901,1305,Geodetic survey.,Densification of ETRS89,Ordnance Survey of Ireland,OGP,"2012/01/05",2004.220 2011.004 2011.082,0,"D_IRENET95"
-6174,Sierra Leone Colony 1924,geodetic,"Fundamental point: Kortright. Latitude: 8°28'44.4""N, longitude: 13°13'03.81""W (of Greenwich).",1924,7029,8901,1342,"Topographic mapping, engineering survey.",,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Sierra_Leone_1924"
-6175,Sierra Leone 1968,geodetic,"Fundamental point: SLX2 Astro. Latitude: 8°27'17.567""N, longitude: 12°49'40.186""W (of Greenwich).",1968,7012,8901,3306,"Topographic mapping, engineering survey.",Extension and readjustment with additional observations of 1960 network.  Coordinates of 1960 stations change by less than 3 metres.,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Sierra_Leone_1968"
-6176,Australian Antarctic Datum 1998,geodetic,,1998,7019,8901,1278,Topographic mapping.,,Standards Australia,OGP,"2006/01/30",2006.080,0,"D_Australian_Antarctic_1998"
-6178,"Pulkovo 1942(83)",geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'18.550""N, longitude: 30°19'42.090""E (of Greenwich).",1983,7024,8901,3900,"Geodetic survey, cadastre, topographic mapping, engineering survey.",1983 international adjustment of Uniform Astro-Geodetic Network of countries of central and eastern Europe.,"Bundesamt für Kartographie und Geodäsie via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2012/01/05",2008.045 2008.011 2011.082,0,"D_Pulkov [...]
-6179,"Pulkovo 1942(58)",geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'18.550""N, longitude: 30°19'42.090""E (of Greenwich).",1956,7024,8901,3574,"Geodetic survey, cadastre, topographic mapping, engineering survey.",1956 international adjustment of Uniform Astro-Geodetic Network of countries of central and eastern Europe. Locally densified during 1957 and 1958.,"Glowny Urzad Geodezji i Kartografii via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2008/09/24",20 [...]
-6180,Estonia 1997,geodetic,Densification of ETRS89 during EUREF-ESTONIA97 campaign through transformation from ITRF96 at epoch 1997.56.,1997,7019,8901,1090,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Estonia 1992 adjustment (code 6133).","Estonian National Land Board via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2006/08/18",2006.770,0,"D_Estonia_1997"
-6181,Luxembourg 1930,geodetic,"Fundamental point: northern station of Habay-la-Neuve baseline in Belgium. Latitude: 49°43'24.408""N, longitude: 5°38'22.470""E (of Greenwich).",1930,7022,8901,1146,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Administration du Cadastre et de la Topographie via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2008/06/24",2008.045,0,"D_Luxembourg_1930"
-6182,Azores Occidental Islands 1939,geodetic,"Fundamental point: Observatario Meteorologico Flores.",1939,7022,8901,1344,Topographic mapping.,,"Instituto Geografico e Cadastral Lisbon via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2005/12/30",2005.850,0,"D_Azores_Occidental_Islands_1939"
-6183,Azores Central Islands 1948,geodetic,"Fundamental point: Graciosa south west base. Latitude: 39°03'54.934""N, longitude: 28°02'23.882""W (of Greenwich).",1948,7022,8901,1301,Topographic mapping.,"Replaced by 1995 adjustment (datum code 6665).","Instituto Geografico e Cadastral Lisbon via EuroGeographics; http://crs.bkg.bund.de/crs-eu/  Oil industry sources for origin description details.",OGP,"2008/06/24",2002.250 2003.231 2003.362 2008.045,0,"D_Azores_Central_Islands_1948"
-6184,Azores Oriental Islands 1940,geodetic,"Fundamental point: Forte de São Bras.",1940,7022,8901,1345,Topographic mapping.,"Replaced by 1995 adjustment (datum code 6664).","Instituto Geografico e Cadastral Lisbon via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2003/08/14",2003.231,0,"D_Azores_Oriental_Islands_1940"
-6185,Madeira 1936,geodetic,"Fundamental point: Madeira SE Base.",1936,7022,8901,1314,Topographic mapping.,,"Instituto Geografico e Cadastral Lisbon via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2001/06/05",,1,"D_Madeira_1936"
-6188,OSNI 1952,geodetic,Position fixed to the coordinates from the 19th century Principle Triangulation of station Divis. Scale and orientation controlled by position of Principle Triangulation stations Knocklayd and Trostan.,1952,7001,8901,2530,Geodetic survey and topographic mapping.,"Replaced by Geodetic Datum of 1965 alias 1975 Mapping Adjustment or TM75 (datum code 6300).",Ordnance Survey of Northern Ireland.,OGP,"2001/11/06",,0,"D_OSNI_1952"
-6189,Red Geodesica Venezolana,geodetic,Realised by a frame of 67 stations observed in 1995 as a densification of the SIRGAS campaign and adjusted in the ITRF94.,2000,7019,8901,1251,Geodetic survey.,,Servicio Autonomo de Geografia y Cartografia Nacional.,OGP,"2001/06/11",,0,"D_REGVEN"
-6190,Posiciones Geodesicas Argentinas 1998,geodetic,"A geodetic network of 136 high accuracy surveyed points. Densification of SIRGAS 1995; ITRF94 at epoch 1995.42.",1998,7019,8901,1033,Geodetic survey.,"Technically, but not legally, this datum replaced the 1994 POSGAR adjustment (code 6694) until adoption of the 2007 POSGAR adjustment (code 1062) in May 2009.","Instituto Geográfico Militar de la República Argentina, http://www.igm.gov.ar",OGP,"2011/03/28",2003.361 2005.460 2005.480 2006 [...]
-6191,Albanian 1987,geodetic,,1987,7024,8901,3212,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2014/11/21",2011.062 2014.078,0,"D_Albanian_1987"
-6192,Douala 1948,geodetic,"South pillar of Douala base; 4°00'40.64""N, 9°42'30.41""E (of Greenwich).",1948,7022,8901,2555,Topographic mapping.,"Replaced  by Manoca 1962 datum (code 6193).",TotalFinaElf,OGP,"2008/06/24",2005.830 2008.045,0,"D_Douala_1948"
-6193,Manoca 1962,geodetic,"Reservoir centre at the  Manoca tower (""tube Suel""), 3°51'49.896""N, 9°36'49.347""E (of Greenwich).",1962,7011,8901,2555,Topographic mapping.,"The intent of the Bukavu 1953 conference was to adopt the Clarke 1880 (RGS) ellipsoid (code 7012) but in practice this datum has used the IGN version.  Replaces Douala 1948 (code 6192).",TotalFinaElf,OGP,"2008/06/24",2008.045,0,"D_Manoca_1962"
-6194,Qornoq 1927,geodetic,"Fundamental point: Station 7008. Latitude: 64°31'06.27""N, longitude: 51°12'24.86""W (of Greenwich).",1927,7022,8901,3362,Topographic mapping.,,"Kort & Matrikelstyrelsen, Copenhagen. Origin coordinates from NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2006.220 2008.045,0,"D_Qornoq_1927"
-6195,Scoresbysund 1952,geodetic,,1952,7022,8901,2570,Topographic mapping.,,"Kort & Matrikelstyrelsen, Copenhagen.",OGP,"2002/01/18",,0,"D_Scoresbysund_1952"
-6196,Ammassalik 1958,geodetic,,1958,7022,8901,2571,Topographic mapping.,,"Kort & Matrikelstyrelsen, Copenhagen.",OGP,"2002/01/18",,0,"D_Ammassalik_1958"
+6173,IRENET95,geodetic,ETRS89 stations in Ireland,1995-01-01,7019,8901,1305,Geodetic survey.,Densification of ETRS89,Ordnance Survey of Ireland,OGP,"2012/01/05",2004.220 2011.004 2011.082,0,"D_IRENET95"
+6174,Sierra Leone Colony 1924,geodetic,"Fundamental point: Kortright. Latitude: 8°28'44.4""N, longitude: 13°13'03.81""W (of Greenwich).",1924-01-01,7029,8901,1342,"Topographic mapping, engineering survey.",,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Sierra_Leone_1924"
+6175,Sierra Leone 1968,geodetic,"Fundamental point: SLX2 Astro. Latitude: 8°27'17.567""N, longitude: 12°49'40.186""W (of Greenwich).",1968-01-01,7012,8901,3306,"Topographic mapping, engineering survey.",Extension and readjustment with additional observations of 1960 network.  Coordinates of 1960 stations change by less than 3 metres.,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Sierra_Leone_1968"
+6176,Australian Antarctic Datum 1998,geodetic,,1998-01-01,7019,8901,1278,Topographic mapping.,,Standards Australia,OGP,"2006/01/30",2006.080,0,"D_Australian_Antarctic_1998"
+6178,"Pulkovo 1942(83)",geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'18.550""N, longitude: 30°19'42.090""E (of Greenwich).",1983-01-01,7024,8901,3900,"Geodetic survey, cadastre, topographic mapping, engineering survey.",1983 international adjustment of Uniform Astro-Geodetic Network of countries of central and eastern Europe.,"Bundesamt für Kartographie und Geodäsie via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2012/01/05",2008.045 2008.011 2011.082,0,"D_ [...]
+6179,"Pulkovo 1942(58)",geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'18.550""N, longitude: 30°19'42.090""E (of Greenwich).",1956-01-01,7024,8901,3574,"Geodetic survey, cadastre, topographic mapping, engineering survey.",1956 international adjustment of Uniform Astro-Geodetic Network of countries of central and eastern Europe. Locally densified during 1957 and 1958.,"Glowny Urzad Geodezji i Kartografii via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2008/09/ [...]
+6180,Estonia 1997,geodetic,Densification of ETRS89 during EUREF-ESTONIA97 campaign through transformation from ITRF96 at epoch 1997.56.,1997-07-23,7019,8901,1090,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Estonia 1992 adjustment (code 6133).","Estonian National Land Board via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",IOGP,"2016/09/16",2006.770 2016.020,0,"D_Estonia_1997"
+6181,Luxembourg 1930,geodetic,"Fundamental point: northern station of Habay-la-Neuve baseline in Belgium. Latitude: 49°43'24.408""N, longitude: 5°38'22.470""E (of Greenwich).",1930-01-01,7022,8901,1146,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Administration du Cadastre et de la Topographie via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2008/06/24",2008.045,0,"D_Luxembourg_1930"
+6182,Azores Occidental Islands 1939,geodetic,"Fundamental point: Observatario Meteorologico Flores.",1939-01-01,7022,8901,1344,Topographic mapping.,,"Instituto Geografico e Cadastral Lisbon via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2005/12/30",2005.850,0,"D_Azores_Occidental_Islands_1939"
+6183,Azores Central Islands 1948,geodetic,"Fundamental point: Graciosa south west base. Latitude: 39°03'54.934""N, longitude: 28°02'23.882""W (of Greenwich).",1948-01-01,7022,8901,1301,Topographic mapping.,"Replaced by 1995 adjustment (datum code 6665).","Instituto Geografico e Cadastral Lisbon via EuroGeographics; http://crs.bkg.bund.de/crs-eu/  Oil industry sources for origin description details.",OGP,"2008/06/24",2002.250 2003.231 2003.362 2008.045,0,"D_Azores_Central_Islands_1948"
+6184,Azores Oriental Islands 1940,geodetic,"Fundamental point: Forte de São Bras.",1940-01-01,7022,8901,1345,Topographic mapping.,"Replaced by 1995 adjustment (datum code 6664).","Instituto Geografico e Cadastral Lisbon via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2003/08/14",2003.231,0,"D_Azores_Oriental_Islands_1940"
+6185,Madeira 1936,geodetic,"Fundamental point: Madeira SE Base.",1936-01-01,7022,8901,1314,Topographic mapping.,,"Instituto Geografico e Cadastral Lisbon via EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2001/06/05",,1,"D_Madeira_1936"
+6188,OSNI 1952,geodetic,Position fixed to the coordinates from the 19th century Principle Triangulation of station Divis. Scale and orientation controlled by position of Principle Triangulation stations Knocklayd and Trostan.,1952-01-01,7001,8901,2530,Geodetic survey and topographic mapping.,"Replaced by Geodetic Datum of 1965 alias 1975 Mapping Adjustment or TM75 (datum code 6300).",Ordnance Survey of Northern Ireland.,OGP,"2001/11/06",,0,"D_OSNI_1952"
+6189,Red Geodesica Venezolana,geodetic,Realised by a frame of 67 stations observed in 1995 as a densification of the SIRGAS campaign and adjusted in the ITRF94. Documented as ITRF94 at epoch 1995.4 but possibly a rounded value as SIRGAS95 is at epoch 1995.42.,1995-06-02,7019,8901,1251,Geodetic survey.,,Servicio Autonomo de Geografia y Cartografia Nacional.,IOGP,"2016/09/16",2016.020,0,"D_REGVEN"
+6190,Posiciones Geodesicas Argentinas 1998,geodetic,"A geodetic network of 136 high accuracy surveyed points. Densification of SIRGAS 1995; ITRF94 at epoch 1995.42.",1995-06-02,7019,8901,1033,Geodetic survey.,"Technically, but not legally, this datum replaced the 1994 POSGAR adjustment (code 6694) until adoption of the 2007 POSGAR adjustment (code 1062) in May 2009.","Instituto Geográfico Militar de la República Argentina, http://www.igm.gov.ar",IOGP,"2016/09/16",2003.361 2005.460 2005.4 [...]
+6191,Albanian 1987,geodetic,,1987-01-01,7024,8901,3212,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2014/11/21",2011.062 2014.078,0,"D_Albanian_1987"
+6192,Douala 1948,geodetic,"South pillar of Douala base; 4°00'40.64""N, 9°42'30.41""E (of Greenwich).",1948-01-01,7022,8901,2555,Topographic mapping.,"Replaced  by Manoca 1962 datum (code 6193).",TotalFinaElf,OGP,"2008/06/24",2005.830 2008.045,0,"D_Douala_1948"
+6193,Manoca 1962,geodetic,"Reservoir centre at the  Manoca tower (""tube Suel""), 3°51'49.896""N, 9°36'49.347""E (of Greenwich).",1962-01-01,7011,8901,2555,Topographic mapping.,"The intent of the Bukavu 1953 conference was to adopt the Clarke 1880 (RGS) ellipsoid (code 7012) but in practice this datum has used the IGN version.  Replaces Douala 1948 (code 6192).",TotalFinaElf,OGP,"2008/06/24",2008.045,0,"D_Manoca_1962"
+6194,Qornoq 1927,geodetic,"Fundamental point: Station 7008. Latitude: 64°31'06.27""N, longitude: 51°12'24.86""W (of Greenwich).",1927-01-01,7022,8901,3362,Topographic mapping.,,"Kort & Matrikelstyrelsen, Copenhagen. Origin coordinates from NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2006.220 2008.045,0,"D_Qornoq_1927"
+6195,Scoresbysund 1952,geodetic,,1952-01-01,7022,8901,2570,Topographic mapping.,,"Kort & Matrikelstyrelsen, Copenhagen.",OGP,"2002/01/18",,0,"D_Scoresbysund_1952"
+6196,Ammassalik 1958,geodetic,,1958-01-01,7022,8901,2571,Topographic mapping.,,"Kort & Matrikelstyrelsen, Copenhagen.",OGP,"2002/01/18",,0,"D_Ammassalik_1958"
 6197,Garoua,geodetic,"Fundamental point: IGN astronomical station and benchmark no. 16 at Tongo. Latitude 8°55'08.74""N, longitude 13°30'43.19""E (of Greenwich).",,7012,8901,2590,Topographic mapping.,,TotalFinaElf,OGP,"2008/06/24",2008.045,0,"D_Garoua"
 6198,Kousseri,geodetic,"IGN astronomical station Dabanga; 11°55'05.9""N  14°38'40.8""E (of Greenwich).",,7012,8901,2591,Topographic mapping.,,TotalFinaElf,OGP,"2008/06/24",2008.045,0,"D_Kousseri"
-6199,Egypt 1930,geodetic,"Fundamental point: Station F1 (Venus). Latitude: 30°01'42.86""N, longitude: 31°16'37.05""E (of Greenwich).",1930,7022,8901,3242,Used for scientific purposes only.,"Note that Egypt 1930 uses the International 1924 ellipsoid, unlike the Egypt 1907 datum (code 6229) which uses the Helmert ellipsoid. Oil industry references to the Egypt 1930 datum name and the Helmert ellipsoid probably mean Egypt 1907 datum.",,OGP,"2008/06/24",2008.045,0,"D_Egypt_1930"
-6200,Pulkovo 1995,geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'15.359""N, longitude: 30°19'28.318""E (of Greenwich).",1995,7024,8901,1198,Scientific adjustment.,,"""Main Terms of Reference for the State Geodetic Network""; Federal Geodetic Service of Russia; 1994",OGP,"2008/06/24",2008.045,0,"D_Pulkovo_1995"
-6201,Adindan,geodetic,"Fundamental point: Station 15; Adindan. Latitude: 22°10'07.110""N, longitude: 31°29'21.608""E (of Greenwich).",1958,7012,8901,1271,Topographic mapping.,"The 12th parallel traverse of 1966-70 (Point 58 datum, code 6620) is connected to the Blue Nile 1958 network in western Sudan. This has given rise to misconceptions that the Blue Nile network is used in west Africa.","US Coast and Geodetic Survey via Geophysical Reasearch vol 67 #11, October 1962.",IOGP,"2015/04/22 [...]
-6202,Australian Geodetic Datum 1966,geodetic,"Fundamental point: Johnson Memorial Cairn. Latitude: 25°56'54.5515""S, longitude: 133°12'30.0771""E (of Greenwich).",1966,7003,8901,1279,Topographic mapping.,,"Australian Map Grid Technical Manual. National Mapping Council of Australia Technical Publication 7; 1972.",OGP,"2008/06/24",2003.361 2008.045,0,"D_Australian_1966"
-6203,Australian Geodetic Datum 1984,geodetic,"Fundamental point: Johnson Memorial Cairn. Latitude: 25°56'54.5515""S, longitude: 133°12'30.0771""E (of Greenwich).",1984,7003,8901,2576,Topographic mapping.,"Uses all data from 1966 adjustment with additional observations, improved software and a geoid model.","""GDA technical manual v2_2"", Intergovernmental Committee on Surveying and Mapping. www.anzlic.org.au/icsm/gdtm/",OGP,"2008/06/24",2003.290 2003.361 2008.045,0,"D_Australian_1984"
-6204,Ain el Abd 1970,geodetic,"Fundamental point: Ain El Abd.  Latitude: 28°14'06.171""N, longitude: 48°16'20.906""E (of Greenwich).",1970,7022,8901,1272,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Ain_el_Abd_1970"
+6199,Egypt 1930,geodetic,"Fundamental point: Station F1 (Venus). Latitude: 30°01'42.86""N, longitude: 31°16'37.05""E (of Greenwich).",1930-01-01,7022,8901,3242,Used for scientific purposes only.,"Note that Egypt 1930 uses the International 1924 ellipsoid, unlike the Egypt 1907 datum (code 6229) which uses the Helmert ellipsoid. Oil industry references to the Egypt 1930 datum name and the Helmert ellipsoid probably mean Egypt 1907 datum.",,OGP,"2008/06/24",2008.045,0,"D_Egypt_1930"
+6200,Pulkovo 1995,geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'15.359""N, longitude: 30°19'28.318""E (of Greenwich).",1995-01-01,7024,8901,1198,Scientific adjustment.,,"""Main Terms of Reference for the State Geodetic Network""; Federal Geodetic Service of Russia; 1994",OGP,"2008/06/24",2008.045,0,"D_Pulkovo_1995"
+6201,Adindan,geodetic,"Fundamental point: Station 15; Adindan. Latitude: 22°10'07.110""N, longitude: 31°29'21.608""E (of Greenwich).",1958-01-01,7012,8901,1271,Topographic mapping.,"The 12th parallel traverse of 1966-70 (Point 58 datum, code 6620) is connected to the Blue Nile 1958 network in western Sudan. This has given rise to misconceptions that the Blue Nile network is used in west Africa.","US Coast and Geodetic Survey via Geophysical Reasearch vol 67 #11, October 1962.",IOGP,"2015 [...]
+6202,Australian Geodetic Datum 1966,geodetic,"Fundamental point: Johnson Memorial Cairn. Latitude: 25°56'54.5515""S, longitude: 133°12'30.0771""E (of Greenwich).",1966-01-01,7003,8901,1279,Topographic mapping.,,"Australian Map Grid Technical Manual. National Mapping Council of Australia Technical Publication 7; 1972.",OGP,"2008/06/24",2003.361 2008.045,0,"D_Australian_1966"
+6203,Australian Geodetic Datum 1984,geodetic,"Fundamental point: Johnson Memorial Cairn. Latitude: 25°56'54.5515""S, longitude: 133°12'30.0771""E (of Greenwich).",1984-01-01,7003,8901,2576,Topographic mapping.,"Uses all data from 1966 adjustment with additional observations, improved software and a geoid model.","""GDA technical manual v2_2"", Intergovernmental Committee on Surveying and Mapping. www.anzlic.org.au/icsm/gdtm/",OGP,"2008/06/24",2003.290 2003.361 2008.045,0,"D_Australian_1984"
+6204,Ain el Abd 1970,geodetic,"Fundamental point: Ain El Abd.  Latitude: 28°14'06.171""N, longitude: 48°16'20.906""E (of Greenwich).",1970-01-01,7022,8901,1272,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Ain_el_Abd_1970"
 6205,Afgooye,geodetic,,,7024,8901,3308,Topographic mapping.,,,OGP,"2012/01/05",2012.001,0,"D_Afgooye"
 6206,Agadez,geodetic,,,7011,8901,1177,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Agadez"
-6207,Lisbon 1937,geodetic,"Fundamental point: Castelo Sao Jorge, Lisbon. Latitude: 38°42'43.631""N, longitude: 9°07'54.862""W (of Greenwich).",1937,7022,8901,1294,Topographic mapping.,"Replaces Lisbon 1890 adjustment (which used Bessel 1841 ellipsoid).","Instituto Geografico e Cadastral; Lisbon",OGP,"2008/06/24",2001.551 2008.045,0,"D_Lisbon"
+6207,Lisbon 1937,geodetic,"Fundamental point: Castelo Sao Jorge, Lisbon. Latitude: 38°42'43.631""N, longitude: 9°07'54.862""W (of Greenwich).",1937-01-01,7022,8901,1294,Topographic mapping.,"Replaces Lisbon 1890 adjustment (which used Bessel 1841 ellipsoid).","Instituto Geografico e Cadastral; Lisbon",OGP,"2008/06/24",2001.551 2008.045,0,"D_Lisbon"
 6208,Aratu,geodetic,,,7022,8901,1274,Oil industry geodetic purposes.,,,OGP,"1995/06/02",,0,"D_Aratu"
-6209,Arc 1950,geodetic,"Fundamental point: Buffelsfontein. Latitude: 33°59'32.000""S, longitude: 25°30'44.622""E (of Greenwich).",1950,7013,8901,1276,"Topographic mapping, geodetic survey.",,,OGP,"2008/06/24",2008.045,0,"D_Arc_1950"
-6210,Arc 1960,geodetic,"Fundamental point: Buffelsfontein. Latitude: 33°59'32.000""S, longitude: 25°30'44.622""E (of Greenwich).",1960,7012,8901,1277,"Topographic mapping, geodetic survey.",,,OGP,"2008/06/24",2008.045,0,"D_Arc_1960"
+6209,Arc 1950,geodetic,"Fundamental point: Buffelsfontein. Latitude: 33°59'32.000""S, longitude: 25°30'44.622""E (of Greenwich).",1950-01-01,7013,8901,1276,"Topographic mapping, geodetic survey.",,,OGP,"2008/06/24",2008.045,0,"D_Arc_1950"
+6210,Arc 1960,geodetic,"Fundamental point: Buffelsfontein. Latitude: 33°59'32.000""S, longitude: 25°30'44.622""E (of Greenwich).",1960-01-01,7012,8901,1277,"Topographic mapping, geodetic survey.",,,OGP,"2008/06/24",2008.045,0,"D_Arc_1960"
 6211,Batavia,geodetic,"Fundamental point: Longitude at Batavia Astro. Station. Latitude: 6°07'39.522""S, longitude: 106°48'27.790""E (of Greenwich). Latitude and azimuth at Genuk.",,7004,8901,3666,Topographic mapping.,,,OGP,"2010/03/30",2003.361 2008.045 2009.106,0,"D_Batavia"
-6212,Barbados 1938,geodetic,"Fundamental point: HMS Challenger astro station M1, St. Anne's Tower. Latitude 13°04'32.53""N, longitude 59°36'29.34""W (of Greenwich).",1938,7012,8901,3218,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"2011/06/30",1999.170 2006.030 2008.045 2011.051,0,"D_Barbados_1938"
+6212,Barbados 1938,geodetic,"Fundamental point: HMS Challenger astro station M1, St. Anne's Tower. Latitude 13°04'32.53""N, longitude 59°36'29.34""W (of Greenwich).",1938-01-01,7012,8901,3218,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"2011/06/30",1999.170 2006.030 2008.045 2011.051,0,"D_Barbados_1938"
 6213,Beduaram,geodetic,,,7011,8901,2771,Topographic mapping.,,,OGP,"2004/09/01",2004.490,0,"D_Beduaram"
-6214,Beijing 1954,geodetic,"Pulkovo, transferred through Russian triangulation.",1954,7024,8901,3228,Topographic mapping.,Scale determined through three baselines in northeast China. Discontinuities at boundaries of adjustment blocks. From 1982 replaced by Xian 1980 and New Beijing.,"Chinese Science Bulletin, 2009, 54:2714-2721",OGP,"2009/11/24",2009.084,0,"D_Beijing_1954"
-6215,Reseau National Belge 1950,geodetic,"Fundamental point: Lommel (tower). Latitude: 51°13'47.334""N, longitude: 5°18'49.483""E (of Greenwich).",1950,7022,8901,1347,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Belge_1950"
-6216,Bermuda 1957,geodetic,"Fundamental point: Fort George base. Latitude 32°22'44.36""N, longitude 64°40'58.11""W (of Greenwich).",1957,7008,8901,3221,Topographic mapping.,,Various oil industry sources.,OGP,"2011/01/25",2003.362 2008.045 2011.004,0,"D_Bermuda_1957"
-6218,Bogota 1975,geodetic,"Fundamental point: Bogota observatory. Latitude: 4°35'56.570""N, longitude: 74°04'51.300""W (of Greenwich).",1975,7022,8901,3686,Topographic mapping.,"Replaces 1951 adjustment. Replaced by MAGNA-SIRGAS (datum code 6685).","Instituto Geografico Agustin Codazzi (IGAC) special publication no. 1, 4th edition (1975) ""Geodesia: Resultados Definitvos de Parte de las Redes Geodesicas Establecidas en el Pais"".",OGP,"2010/03/30",2000.200 2005.060 2007.060 2008.045 2009 [...]
+6214,Beijing 1954,geodetic,"Pulkovo, transferred through Russian triangulation.",1954-01-01,7024,8901,3228,Topographic mapping.,Scale determined through three baselines in northeast China. Discontinuities at boundaries of adjustment blocks. From 1982 replaced by Xian 1980 and New Beijing.,"Chinese Science Bulletin, 2009, 54:2714-2721",OGP,"2009/11/24",2009.084,0,"D_Beijing_1954"
+6215,Reseau National Belge 1950,geodetic,"Fundamental point: Lommel (tower). Latitude: 51°13'47.334""N, longitude: 5°18'49.483""E (of Greenwich).",1950-01-01,7022,8901,1347,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Belge_1950"
+6216,Bermuda 1957,geodetic,"Fundamental point: Fort George base. Latitude 32°22'44.36""N, longitude 64°40'58.11""W (of Greenwich).",1957-01-01,7008,8901,3221,Topographic mapping.,,Various oil industry sources.,OGP,"2011/01/25",2003.362 2008.045 2011.004,0,"D_Bermuda_1957"
+6218,Bogota 1975,geodetic,"Fundamental point: Bogota observatory. Latitude: 4°35'56.570""N, longitude: 74°04'51.300""W (of Greenwich).",1975-01-01,7022,8901,3686,Topographic mapping.,"Replaces 1951 adjustment. Replaced by MAGNA-SIRGAS (datum code 6685).","Instituto Geografico Agustin Codazzi (IGAC) special publication no. 1, 4th edition (1975) ""Geodesia: Resultados Definitvos de Parte de las Redes Geodesicas Establecidas en el Pais"".",OGP,"2010/03/30",2000.200 2005.060 2007.060 2008.04 [...]
 6219,Bukit Rimpah,geodetic,"2°00'40.16""S, 105°51'39.76""E (of Greenwich).",,7004,8901,1287,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Bukit_Rimpah"
-6220,Camacupa,geodetic,"Fundamental point: Campo de Aviaçao. Latitude: 12°01'09.070""S, Longitude = 17°27'19.800""E (of Greenwich)",1948,7012,8901,1288,Coastal hydrography.,,"Portuguese Hydrographic Institute and Clifford J. Mugnier, PE&RS journal, March 2001.",OGP,"2008/06/24",2003.361 2006.973 2008.045,0,"D_Camacupa"
+6220,Camacupa,geodetic,"Fundamental point: Campo de Aviaçao. Latitude: 12°01'09.070""S, Longitude = 17°27'19.800""E (of Greenwich)",1948-01-01,7012,8901,1288,Coastal hydrography.,,"Portuguese Hydrographic Institute and Clifford J. Mugnier, PE&RS journal, March 2001.",OGP,"2008/06/24",2003.361 2006.973 2008.045,0,"D_Camacupa"
 6221,Campo Inchauspe,geodetic,"Fundamental point: Campo Inchauspe. Latitude: 35°58'16.56""S, longitude: 62°10'12.03""W (of Greenwich).",,7022,8901,3843,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2011/03/28",2003.361 2005.460 2008.045 2011.021,0,"D_Campo_Inchauspe"
 6222,Cape,geodetic,"Fundamental point: Buffelsfontein. Latitude: 33°59'32.000""S, longitude: 25°30'44.622""E (of Greenwich).",,7013,8901,1290,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Private Communication, Directorate of Surveys and Land Information, Cape Town.",OGP,"2008/06/24",1996.250 1999.690 2008.045,0,"D_Cape"
-6223,Carthage,geodetic,"Fundamental point: Carthage. Latitude: 40.9464506g = 36°51'06.50""N, longitude: 8.8724368g E of Paris = 10°19'20.72""E (of Greenwich).",1925,7011,8901,1236,Topographic mapping.,Fundamental point astronomic coordinates determined in 1878.,,OGP,"2008/06/24",2003.362 2003.050 2008.045,0,"D_Carthage"
+6223,Carthage,geodetic,"Fundamental point: Carthage. Latitude: 40.9464506g = 36°51'06.50""N, longitude: 8.8724368g E of Paris = 10°19'20.72""E (of Greenwich).",1925-01-01,7011,8901,1236,Topographic mapping.,Fundamental point astronomic coordinates determined in 1878.,,OGP,"2008/06/24",2003.362 2003.050 2008.045,0,"D_Carthage"
 6224,Chua,geodetic,"Fundamental point: Chua. Latitude: 19°45'41.160""S, longitude: 48°06'07.560""W (of Greenwich).",,7022,8901,3356,Geodetic survey.,The Chua origin and associated network is in Brazil with a connecting traverse through northern Paraguay. It was used in Brazil only as input into the Corrego Allegre adjustment and for government work in Distrito Federal.,"NIMA http://earth-info.nima.mil/",OGP,"2009/06/02",2003.361 2005.460 2005.840 2006.490 2008.045 2009.021,0,"D_Chua"
-6225,Corrego Alegre 1970-72,geodetic,"Fundamental point: Corrego Alegre. Latitude: 19°50'14.91""S, longitude: 48°57'41.98""W (of Greenwich).",1972,7022,8901,1293,"Topographic mapping, geodetic survey. Superseded by SAD69.","Replaces 1961 adjustment (datum code 1074). NIMA gives coordinates of origin as latitude: 19°50'15.14""S, longitude: 48°57'42.75""W; these may refer to 1961 adjustment.",IBGE.,OGP,"2011/07/27",2005.841 2008.045 2011.053,0,"D_Corrego_Alegre"
+6225,Corrego Alegre 1970-72,geodetic,"Fundamental point: Corrego Alegre. Latitude: 19°50'14.91""S, longitude: 48°57'41.98""W (of Greenwich).",1972-01-01,7022,8901,1293,"Topographic mapping, geodetic survey. Superseded by SAD69.","Replaces 1961 adjustment (datum code 1074). NIMA gives coordinates of origin as latitude: 19°50'15.14""S, longitude: 48°57'42.75""W; these may refer to 1961 adjustment.",IBGE.,OGP,"2011/07/27",2005.841 2008.045 2011.053,0,"D_Corrego_Alegre"
 6226,"Cote d'Ivoire",geodetic,,,7011,8901,1075,Topographic mapping.,,,OGP,"1995/06/02",2001.110,1,"D_Cote_d_Ivoire"
 6227,Deir ez Zor,geodetic,"Fundamental point: Trig. 254 Deir. Latitude: 35°21'49.975""N, longitude: 40°05'46.770""E (of Greenwich).",,7011,8901,1623,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Deir_ez_Zor"
 6228,Douala,geodetic,,,7011,8901,1060,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Douala"
-6229,Egypt 1907,geodetic,"Fundamental point: Station F1 (Venus). Latitude: 30°01'42.86""N, longitude: 31°16'33.60""E (of Greenwich).",1907,7020,8901,1086,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,,OGP,"2008/06/24",2008.045,0,"D_Egypt_1907"
-6230,European Datum 1950,geodetic,"Fundamental point: Potsdam (Helmert Tower). Latitude: 52°22'51.4456""N, longitude: 13°03'58.9283""E (of Greenwich).",1950,7022,8901,1296,"Topographic mapping, geodetic survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2008/06/24",2003.361 2008.045,0,"D_European_1950"
-6231,European Datum 1987,geodetic,"Fundamental point: Potsdam (Helmert Tower). Latitude: 52°22'51.4456""N, longitude: 13°03'58.9283""E (of Greenwich).",1987,7022,8901,1297,Scientific network.,,,OGP,"2008/06/24",2003.362 2008.045,0,"D_European_1987"
+6229,Egypt 1907,geodetic,"Fundamental point: Station F1 (Venus). Latitude: 30°01'42.86""N, longitude: 31°16'33.60""E (of Greenwich).",1907-01-01,7020,8901,1086,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,,OGP,"2008/06/24",2008.045,0,"D_Egypt_1907"
+6230,European Datum 1950,geodetic,"Fundamental point: Potsdam (Helmert Tower). Latitude: 52°22'51.4456""N, longitude: 13°03'58.9283""E (of Greenwich).",1950-01-01,7022,8901,1296,"Topographic mapping, geodetic survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2008/06/24",2003.361 2008.045,0,"D_European_1950"
+6231,European Datum 1987,geodetic,"Fundamental point: Potsdam (Helmert Tower). Latitude: 52°22'51.4456""N, longitude: 13°03'58.9283""E (of Greenwich).",1987-01-01,7022,8901,1297,Scientific network.,,,OGP,"2008/06/24",2003.362 2008.045,0,"D_European_1987"
 6232,Fahud,geodetic,"Fundamental point: Station NO68-024 Fahud. Latitude: 22°17'31.182""N, longitude: 56°29'18.820""E (of Greenwich).",,7012,8901,4009,Oil industry mapping.,"Replaced by PSD93 (code 6134).",Petroleum Development Oman.,OGP,"2012/02/13",2008.045 2011.042,0,"D_Fahud"
-6233,Gandajika 1970,geodetic,,1970,7022,8901,1152,Topographic mapping.,,,OGP,"1995/06/02",,1,
+6233,Gandajika 1970,geodetic,,1970-01-01,7022,8901,1152,Topographic mapping.,,,OGP,"1995/06/02",,1,
 6234,Garoua,geodetic,,,7011,8901,1060,Topographic mapping.,"The intent of the Bukavu 1953 conference was to adopt the Clarke 1880 (RGS) ellipsoid (code 7012) but in practice this datum has used the IGN version.",,OGP,"1995/06/02",,1,"D_Garoua"
 6235,Guyane Francaise,geodetic,,,7022,8901,1097,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Guyane_Francaise"
-6236,Hu Tzu Shan 1950,geodetic,"Fundamental point: Hu Tzu Shan. Latitude: 23°58'32.34""N, longitude: 120°58'25.975""E (of Greenwich).",1950,7022,8901,3315,Topographic mapping.,,"NIMA 
+6236,Hu Tzu Shan 1950,geodetic,"Fundamental point: Hu Tzu Shan. Latitude: 23°58'32.34""N, longitude: 120°58'25.975""E (of Greenwich).",1950-01-01,7022,8901,3315,Topographic mapping.,,"NIMA 
 US NGA, http://earth-info.nga.mil/GandG/index.html",OGP,"2008/08/12",2003.362 2005.460 2005.830 2008.017 2008.045,0,"D_Hu_Tzu_Shan"
-6237,Hungarian Datum 1972,geodetic,"Fundamental point: Szolohegy. Latitude: 47°17'32,6156""N, longitude 19°36'09.9865""E (of Greenwich); geoid height 6.56m.",1972,7036,8901,1119,Topographic mapping.,"Replaced Hungarian Datum 1909 (EPSG datum code 1024).","http://lazarus.elte.hu/gb/geodez/geod3.htm",OGP,"2008/08/02",1996.090 2008.045 2008.047,0,"D_Hungarian_1972"
-6238,Indonesian Datum 1974,geodetic,"Fundamental point: Padang. Latitude: 0°56'38.414""S, longitude: 100°22' 8.804""E (of Greenwich). Ellipsoidal height 3.190m, gravity-related height 14.0m above mean sea level.",1974,7021,8901,4020,Topographic mapping.,Replaced by DGN95.,Bakosurtanal 1979 paper by Jacob Rais.,OGP,"2012/03/25",2002.151 2006.810 2008.045 2012.032,0,"D_Indonesian_1974"
-6239,Indian 1954,geodetic,Extension of Kalianpur 1937 over Myanmar and Thailand.,1954,7015,8901,1304,Topographic mapping.,,,OGP,"2003/12/31",2003.361,0,"D_Indian_1954"
-6240,Indian 1975,geodetic,"Fundamental point: Khau Sakaerang.",1975,7015,8901,3741,Topographic mapping.,,,OGP,"2011/01/25",2011.004,0,"D_Indian_1975"
-6241,Jamaica 1875,geodetic,"Fundamental point: Fort Charles Flagstaff. Latitude: 17°55'55.800""N, longitude: 76°56'37.260""W (of Greenwich).",1875,7034,8901,3342,Topographic mapping.,,"Survey Department, Government of Jamaica, 1983.",OGP,"2008/06/24",2004.510 2008.045,0,"D_Jamaica_1875"
-6242,Jamaica 1969,geodetic,"Fundamental point: Fort Charles Flagstaff. Latitude: 17°55'55.800""N, longitude: 76°56'37.260""W (of Greenwich).",1969,7008,8901,3342,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Survey Department, Government of Jamaica, 1983.",OGP,"2008/06/24",2004.510 2008.045,0,"D_Jamaica_1969"
-6243,Kalianpur 1880,geodetic,"Fundamental point: Kalianpur. Latitude: 24°07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1880,7042,8901,1307,Topographic mapping.,"Includes 1916 extension into Burma (Myanmar).  Replaced by 1937 adjustment.","G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,"2008/06/24",1997.231 2004.290 2008.045,0,"D_Kalianpur_1880"
-6244,Kandawala,geodetic,"Fundamental point: Kandawala. Latitude: 7°14'06.838""N, longitude: 79°52'36.670""E.",1930,7015,8901,3310,Topographic mapping.,,"Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/09/24",2010.080,0,"D_Kandawala"
-6245,Kertau 1968,geodetic,"Fundamental point: Kertau. Latitude: 3°27'50.710""N, longitude: 102°37'24.550""E (of Greenwich).",1968,7018,8901,4223,"Geodetic survey, cadastre.","Replaces MRT48 and earlier adjustments. Adopts metric conversion of 39.370113 inches per metre. Not used for 1969 metrication of RSO grid - see Kertau (RSO) (code 6751).",Defence Geographic Centre.,OGP,"2014/11/21",2006.251 2008.045 2014.071,0,"D_Kertau"
-6246,Kuwait Oil Company,geodetic,"Fundamental point: K28.  Latitude: 29°03'42.348""N, longitude: 48°08'42.558""E (of Greenwich).",1952,7012,8901,3267,Oil industry mapping.,,,OGP,"2008/06/24",2004.410 2008.045,0,"D_Kuwait_Oil_Company"
+6237,Hungarian Datum 1972,geodetic,"Fundamental point: Szolohegy. Latitude: 47°17'32,6156""N, longitude 19°36'09.9865""E (of Greenwich); geoid height 6.56m.",1972-01-01,7036,8901,1119,Topographic mapping.,"Replaced Hungarian Datum 1909 (EPSG datum code 1024).","http://lazarus.elte.hu/gb/geodez/geod3.htm",OGP,"2008/08/02",1996.090 2008.045 2008.047,0,"D_Hungarian_1972"
+6238,Indonesian Datum 1974,geodetic,"Fundamental point: Padang. Latitude: 0°56'38.414""S, longitude: 100°22' 8.804""E (of Greenwich). Ellipsoidal height 3.190m, gravity-related height 14.0m above mean sea level.",1974-01-01,7021,8901,4020,Topographic mapping.,Replaced by DGN95.,Bakosurtanal 1979 paper by Jacob Rais.,OGP,"2012/03/25",2002.151 2006.810 2008.045 2012.032,0,"D_Indonesian_1974"
+6239,Indian 1954,geodetic,Extension of Kalianpur 1937 over Myanmar and Thailand.,1954-01-01,7015,8901,1304,Topographic mapping.,,,OGP,"2003/12/31",2003.361,0,"D_Indian_1954"
+6240,Indian 1975,geodetic,"Fundamental point: Khau Sakaerang.",1975-01-01,7015,8901,3741,Topographic mapping.,,,OGP,"2011/01/25",2011.004,0,"D_Indian_1975"
+6241,Jamaica 1875,geodetic,"Fundamental point: Fort Charles Flagstaff. Latitude: 17°55'55.800""N, longitude: 76°56'37.260""W (of Greenwich).",1875-01-01,7034,8901,3342,Topographic mapping.,,"Survey Department, Government of Jamaica, 1983.",OGP,"2008/06/24",2004.510 2008.045,0,"D_Jamaica_1875"
+6242,Jamaica 1969,geodetic,"Fundamental point: Fort Charles Flagstaff. Latitude: 17°55'55.800""N, longitude: 76°56'37.260""W (of Greenwich).",1969-01-01,7008,8901,3342,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Survey Department, Government of Jamaica, 1983.",OGP,"2008/06/24",2004.510 2008.045,0,"D_Jamaica_1969"
+6243,Kalianpur 1880,geodetic,"Fundamental point: Kalianpur. Latitude: 24°07'11.260""N, longitude: 77°39'17.570""E (of Greenwich).",1880-01-01,7042,8901,1307,Topographic mapping.,"Includes 1916 extension into Burma (Myanmar).  Replaced by 1937 adjustment.","G. Bomford; ""The Re-adjustment of the Indian Triangulation""; Survey of India Professional Paper 28; 1939.",OGP,"2008/06/24",1997.231 2004.290 2008.045,0,"D_Kalianpur_1880"
+6244,Kandawala,geodetic,"Fundamental point: Kandawala. Latitude: 7°14'06.838""N, longitude: 79°52'36.670""E.",1930-01-01,7015,8901,3310,Topographic mapping.,,"Abeyratne, Featherstone and Tantrigoda in Survey Review vol. 42 no. 317 (July 2010).",OGP,"2010/09/24",2010.080,0,"D_Kandawala"
+6245,Kertau 1968,geodetic,"Fundamental point: Kertau. Latitude: 3°27'50.710""N, longitude: 102°37'24.550""E (of Greenwich).",1968-01-01,7018,8901,4223,"Geodetic survey, cadastre.","Replaces MRT48 and earlier adjustments. Adopts metric conversion of 39.370113 inches per metre. Not used for 1969 metrication of RSO grid - see Kertau (RSO) (code 6751).",Defence Geographic Centre.,OGP,"2014/11/21",2006.251 2008.045 2014.071,0,"D_Kertau"
+6246,Kuwait Oil Company,geodetic,"Fundamental point: K28.  Latitude: 29°03'42.348""N, longitude: 48°08'42.558""E (of Greenwich).",1952-01-01,7012,8901,3267,Oil industry mapping.,,,OGP,"2008/06/24",2004.410 2008.045,0,"D_Kuwait_Oil_Company"
 6247,La Canoa,geodetic,"Fundamental point: La Canoa. Latitude: 8°34'17.170""N, longitude: 63°51'34.880""W (of Greenwich).",,7022,8901,3327,"Geodetic survey, topographic mapping, engineering survey.","Origin and network incorporated within PSAD56 (datum code 6248).",,OGP,"2011/01/25",2008.045 2011.001,0,"D_La_Canoa"
-6248,Provisional South American Datum 1956,geodetic,"Fundamental point: La Canoa. Latitude: 8°34'17.170""N, longitude: 63°51'34.880""W (of Greenwich).",1956,7022,8901,1348,Topographic mapping.,Same origin as La Canoa datum.,,OGP,"2008/06/24",2008.045,0,"D_Provisional_S_American_1956"
+6248,Provisional South American Datum 1956,geodetic,"Fundamental point: La Canoa. Latitude: 8°34'17.170""N, longitude: 63°51'34.880""W (of Greenwich).",1956-01-01,7022,8901,1348,Topographic mapping.,Same origin as La Canoa datum.,,OGP,"2008/06/24",2008.045,0,"D_Provisional_S_American_1956"
 6249,Lake,geodetic,"Fundamental point: Maracaibo Cathedral. Latitude: 10°38'34.678""N, longitude: 71°36'20.224""W (of Greenwich).",,7022,8901,1312,Oil industry mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Lake"
 6250,Leigon,geodetic,"Fundamental point: GCS Station 121, Leigon. Latitude: 5°38'52.27""N, longitude: 0°11'46.08""W (of Greenwich).",,7012,8901,1104,Topographic mapping.,"Replaced Accra datum (code 6168) from 1978.  Coordinates at Leigon fundamental point defined as Accra datum values for that point.",Ordnance Survey International,OGP,"2008/06/24",2008.045,0,"D_Leigon"
-6251,Liberia 1964,geodetic,"Fundamental point: Robertsfield. Latitude: 6°13'53.02""N, longitude: 10°21'35.44""W (of Greenwich).",1964,7012,8901,3270,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2008.045,0,"D_Liberia_1964"
+6251,Liberia 1964,geodetic,"Fundamental point: Robertsfield. Latitude: 6°13'53.02""N, longitude: 10°21'35.44""W (of Greenwich).",1964-01-01,7012,8901,3270,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2008.045,0,"D_Liberia_1964"
 6252,Lome,geodetic,,,7011,8901,1232,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Lome"
-6253,Luzon 1911,geodetic,"Fundamental point: Balacan. Latitude: 13°33'41.000""N, longitude: 121°52'03.000""E (of Greenwich).",1911,7008,8901,3969,Topographic mapping.,"Replaced by Philippine Reference system of 1992 (datum code 6683).",Coast and Geodetic Survey,OGP,"2012/03/25",2004.730 2008.045 2012.032,0,"D_Luzon_1911"
-6254,Hito XVIII 1963,geodetic,Chile-Argentina boundary survey.,1963,7022,8901,1303,Geodetic survey.,Used in Tierra del Fuego.,Various oil company records.,OGP,"1995/06/02",,0,"D_Hito_XVIII_1963"
+6253,Luzon 1911,geodetic,"Fundamental point: Balacan. Latitude: 13°33'41.000""N, longitude: 121°52'03.000""E (of Greenwich).",1911-01-01,7008,8901,3969,Topographic mapping.,"Replaced by Philippine Reference system of 1992 (datum code 6683).",Coast and Geodetic Survey,OGP,"2012/03/25",2004.730 2008.045 2012.032,0,"D_Luzon_1911"
+6254,Hito XVIII 1963,geodetic,Chile-Argentina boundary survey.,1963-01-01,7022,8901,1303,Geodetic survey.,Used in Tierra del Fuego.,Various oil company records.,OGP,"1995/06/02",,0,"D_Hito_XVIII_1963"
 6255,Herat North,geodetic,"Fundamental point: Herat North. Latitude: 34°23'09.08""N, longitude: 64°10'58.94""E (of Greenwich).",,7022,8901,1024,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.362 2005.460 2008.045,0,"D_Herat_North"
-6256,Mahe 1971,geodetic,"Fundamental point: Station SITE. Latitude: 4°40'14.644""S, longitude: 55°28'44.488""E (of Greenwich).",1971,7012,8901,2369,US military survey.,"South East Island 1943 (datum code 1138) used for topographic mapping, cadastral and hydrographic survey.","Clifford Mugnier's September 2007 PE&RS ""Grids and Datums"" article on Seychelles (www.asprs.org/resources/grids/).",OGP,"2014/09/08",2012.025 2014.037,0,"D_Mahe_1971"
+6256,Mahe 1971,geodetic,"Fundamental point: Station SITE. Latitude: 4°40'14.644""S, longitude: 55°28'44.488""E (of Greenwich).",1971-01-01,7012,8901,2369,US military survey.,"South East Island 1943 (datum code 1138) used for topographic mapping, cadastral and hydrographic survey.","Clifford Mugnier's September 2007 PE&RS ""Grids and Datums"" article on Seychelles (www.asprs.org/resources/grids/).",OGP,"2014/09/08",2012.025 2014.037,0,"D_Mahe_1971"
 6257,Makassar,geodetic,"Fundamental point: station P1, Moncongloe. Latitude: 5°08'41.42""S, long 119°24'14.94""E (of Greenwich).",,7004,8901,1316,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.361 2005.460 2008.045,0,"D_Makassar"
-6258,European Terrestrial Reference System 1989,geodetic,Fixed to the stable part of the Eurasian continental plate and consistent with ITRS at the epoch 1989.0.,1989,7019,8901,1298,Geodetic survey.,"The distinction in usage between ETRF89 and ETRS89 is confused: although in principle conceptually different in practice both are used for the realisation.",,OGP,"2003/08/14",1997.110 1997.550 1999.111 2000.720 2003.260,0,"D_ETRS_1989"
-6259,Malongo 1987,geodetic,"Fundamental point: Station Y at Malongo base camp. Latitude: 5°23'30.810""S, longitude: 12°12'01.590""E (of Greenwich).",1987,7022,8901,3180,Oil industry offshore exploration and production from 1987.,"Replaced Mhast (offshore) (code 6705) in 1987. Origin coordinates constrained to those of Mhast (offshore) but other station coordinates differ. References to ""Mhast"" since 1987 often should have stated ""Malongo 1987"".",Chevron Petroleum Technology.,OGP,"200 [...]
+6258,European Terrestrial Reference System 1989,geodetic,Fixed to the stable part of the Eurasian continental plate and consistent with ITRS at the epoch 1989.0.,1989-01-01,7019,8901,1298,Geodetic survey.,"The distinction in usage between ETRF89 and ETRS89 is confused: although in principle conceptually different in practice both are used for the realisation.",,OGP,"2003/08/14",1997.110 1997.550 1999.111 2000.720 2003.260,0,"D_ETRS_1989"
+6259,Malongo 1987,geodetic,"Fundamental point: Station Y at Malongo base camp. Latitude: 5°23'30.810""S, longitude: 12°12'01.590""E (of Greenwich).",1987-01-01,7022,8901,3180,Oil industry offshore exploration and production from 1987.,"Replaced Mhast (offshore) (code 6705) in 1987. Origin coordinates constrained to those of Mhast (offshore) but other station coordinates differ. References to ""Mhast"" since 1987 often should have stated ""Malongo 1987"".",Chevron Petroleum Technology.,OG [...]
 6260,Manoca,geodetic,,,7012,8901,1060,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Manoca"
-6261,Merchich,geodetic,"Fundamental point: Merchich. Latitude: 33°26'59.672""N, longitude: 7°33'27.295""W (of Greenwich).",1922,7011,8901,3280,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Merchich"
+6261,Merchich,geodetic,"Fundamental point: Merchich. Latitude: 33°26'59.672""N, longitude: 7°33'27.295""W (of Greenwich).",1922-01-01,7011,8901,3280,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Merchich"
 6262,Massawa,geodetic,,,7004,8901,1089,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Massawa"
 6263,Minna,geodetic,"Fundamental point: Minna base station L40. Latitude: 9°38'08.87""N, longitude: 6°30'58.76""E (of Greenwich).",,7012,8901,1178,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2008/06/24",2003.361 2005.460 2008.045,0,"D_Minna"
 6264,Mhast,geodetic,,,7022,8901,1318,Coastal hydrography.,,,OGP,"1995/06/02",,1,
-6265,Monte Mario,geodetic,"Fundamental point: Monte Mario. Latitude: 41°55'25.51""N, longitude: 12°27'08.4""E (of Greenwich).",1940,7022,8901,3343,Topographic mapping.,"Replaced Genova datum, Bessel 1841 ellipsoid, from 1940.",,OGP,"2008/06/24",2003.360 2008.045,0,"D_Monte_Mario"
+6265,Monte Mario,geodetic,"Fundamental point: Monte Mario. Latitude: 41°55'25.51""N, longitude: 12°27'08.4""E (of Greenwich).",1940-01-01,7022,8901,3343,Topographic mapping.,"Replaced Genova datum, Bessel 1841 ellipsoid, from 1940.",,OGP,"2008/06/24",2003.360 2008.045,0,"D_Monte_Mario"
 6266,"M'poraloko",geodetic,,,7011,8901,1100,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Mporaloko"
-6267,North American Datum 1927,geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",1927,7008,8901,1349,Topographic mapping.,"In United States (USA) and Canada, replaced by North American Datum 1983 (NAD83) (code 6269) ; in Mexico, replaced by Mexican Datum of 1993 (code 1042).",,OGP,"2009/11/24",2008.024 2008.045 2009.087,0,"D_North_American_1927"
+6267,North American Datum 1927,geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",1927-01-01,7008,8901,1349,Topographic mapping.,"In United States (USA) and Canada, replaced by North American Datum 1983 (NAD83) (code 6269) ; in Mexico, replaced by Mexican Datum of 1993 (code 1042).",,OGP,"2009/11/24",2008.024 2008.045 2009.087,0,"D_North_American_1927"
 6268,NAD27 Michigan,geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",,7009,8901,1391,Topographic mapping.,Ellipsoid taken to be 800ft above the NAD27 reference ellipsoid.,"USGS Professional Paper #1395.",OGP,"2011/02/25",2008.045 2011.013 2013.020,1,
-6269,North American Datum 1983,geodetic,Origin at geocentre.,1986,7019,8901,1350,Topographic mapping.,"Although the 1986 adjustment included connections to Greenland and Mexico, it has not been adopted there. In Canada and US, replaced NAD27.",,OGP,"2008/04/11",2006.464 2008.024,0,"D_North_American_1983"
-6270,Nahrwan 1967,geodetic,"Fundamental point: Nahrwan south base.  Latitude: 33°19'10.87""N, longitude: 44°43'25.54""E (of Greenwich).",1967,7012,8901,1351,Topographic mapping.,"In Iraq, replaces Nahrwan 1934.",,OGP,"2008/06/24",2006.340 2008.045,0,"D_Nahrwan_1967"
-6271,Naparima 1972,geodetic,"Fundamental point: Naparima. Latitude: 10°16'44.860""N, longitude: 61°27'34.620""W (of Greenwich).",1972,7022,8901,1322,Topographic mapping.,Naparima 1972 is an extension of the Naparima 1955 network of Trinidad to include Tobago.,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Naparima_1972"
-6272,New Zealand Geodetic Datum 1949,geodetic,"Fundamental point: Papatahi. Latitude: 41°19' 8.900""S, longitude: 175°02'51.000""E (of Greenwich).",1949,7022,8901,3285,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by New Zealand Geodetic Datum 2000 (code 6167) from March 2000.","Land Information New Zealand. http://www.linz.govt.nz/rcs/linz/pub/web/root/core/SurveySystem/GeodeticInfo/GeodeticDatums/nzgd2000factsheet/index.jsp",OGP,"2008/06/24",2000.702 2 [...]
-6273,NGO 1948,geodetic,"Fundamental point: Oslo observatory. Latitude: 59°54'43.7""N, longitude: 10°43'22.5""E (of Greenwich).",1948,7005,8901,1352,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2008/06/24",2003.362 2008.045,0,"D_NGO_1948"
-6274,Datum 73,geodetic,"Fundamental point:  TF4, Melrica. Latitude: 39°41'37.30""N, longitude: 8°07'53.31""W (of Greenwich).",1964,7022,8901,1294,Topographic mapping.,,"Instituto Geografico e Cadastral; Lisbon",OGP,"2008/06/24",2008.045,0,"D_Datum_73"
-6275,Nouvelle Triangulation Francaise,geodetic,"Fundamental point: Pantheon. Latitude: 48°50'46.522""N, longitude: 2°20'48.667""E (of Greenwich).",1895,7011,8901,3694,Topographic mapping.,,,OGP,"2010/03/30",2003.361 2008.045 2009.106,0,"D_NTF"
+6269,North American Datum 1983,geodetic,Origin at geocentre.,1986-01-01,7019,8901,1350,Topographic mapping.,"Although the 1986 adjustment included connections to Greenland and Mexico, it has not been adopted there. In Canada and US, replaced NAD27.",,OGP,"2008/04/11",2006.464 2008.024,0,"D_North_American_1983"
+6270,Nahrwan 1967,geodetic,"Fundamental point: Nahrwan south base.  Latitude: 33°19'10.87""N, longitude: 44°43'25.54""E (of Greenwich).",1967-01-01,7012,8901,1351,Topographic mapping.,"In Iraq, replaces Nahrwan 1934.",,OGP,"2008/06/24",2006.340 2008.045,0,"D_Nahrwan_1967"
+6271,Naparima 1972,geodetic,"Fundamental point: Naparima. Latitude: 10°16'44.860""N, longitude: 61°27'34.620""W (of Greenwich).",1972-01-01,7022,8901,1322,Topographic mapping.,Naparima 1972 is an extension of the Naparima 1955 network of Trinidad to include Tobago.,Ordnance Survey International.,OGP,"2008/06/24",2008.045,0,"D_Naparima_1972"
+6272,New Zealand Geodetic Datum 1949,geodetic,"Fundamental point: Papatahi. Latitude: 41°19' 8.900""S, longitude: 175°02'51.000""E (of Greenwich).",1949-01-01,7022,8901,3285,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by New Zealand Geodetic Datum 2000 (code 6167) from March 2000.","Land Information New Zealand. http://www.linz.govt.nz/rcs/linz/pub/web/root/core/SurveySystem/GeodeticInfo/GeodeticDatums/nzgd2000factsheet/index.jsp",OGP,"2008/06/24",2000 [...]
+6273,NGO 1948,geodetic,"Fundamental point: Oslo observatory. Latitude: 59°54'43.7""N, longitude: 10°43'22.5""E (of Greenwich).",1948-01-01,7005,8901,1352,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"EuroGeographics; http://crs.bkg.bund.de/crs-eu/",OGP,"2008/06/24",2003.362 2008.045,0,"D_NGO_1948"
+6274,Datum 73,geodetic,"Fundamental point:  TF4, Melrica. Latitude: 39°41'37.30""N, longitude: 8°07'53.31""W (of Greenwich).",1964-01-01,7022,8901,1294,Topographic mapping.,,"Instituto Geografico e Cadastral; Lisbon",OGP,"2008/06/24",2008.045,0,"D_Datum_73"
+6275,Nouvelle Triangulation Francaise,geodetic,"Fundamental point: Pantheon. Latitude: 48°50'46.522""N, longitude: 2°20'48.667""E (of Greenwich).",1895-01-01,7011,8901,3694,Topographic mapping.,,,OGP,"2010/03/30",2003.361 2008.045 2009.106,0,"D_NTF"
 6276,NSWC 9Z-2,geodetic,,,7025,8901,1262,Satellite navigation.,Transit precise ephemeris before 1991.,,OGP,"1995/06/02",,0,"D_NSWC_9Z_2"
-6277,OSGB 1936,geodetic,"From April 2002 the datum is defined through the application of the OSTN02 transformation (tfm code 1039) to ETRS89. Prior to 2002, fundamental point: Herstmonceux, Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich).",1936,7001,8901,1264,Topographic mapping.,"The average accuracy of OSTN02 compared to the old triangulation network (down to 3rd order) is 0.1m.",Ordnance Survey of Great Britain,OGP,"2011/03/14",2002.620 2008.045 2009.055 2010.106,0 [...]
-6278,"OSGB 1970 (SN)",geodetic,"Fundamental point: Herstmonceux. Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich).",1970,7001,8901,1264,Scientific network.,,,OGP,"2008/06/24",2005.880 2008.045,0,"D_OSGB_1970_SN"
-6279,"OS (SN) 1980",geodetic,"Fundamental point: Herstmonceux. Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich).",1980,7001,8901,1354,Scientific network.,,,OGP,"2008/06/24",2008.045,0,"D_OS_SN_1980"
-6280,Padang 1884,geodetic,"Fundamental point: Padang.",1884,7004,8901,1355,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Padang_1884"
-6281,Palestine 1923,geodetic,"Fundamental point: Point 82'M  Jerusalem. Latitude: 31°44' 2.749""N, longitude: 35°12'43.490""E (of Greenwich).",1923,7010,8901,1356,Topographic mapping.,,,OGP,"2008/06/24",2004.150 2008.045,0,"D_Palestine_1923"
-6282,Congo 1960 Pointe Noire,geodetic,"Fundamental point: Point Noire Astro. Latitude: 4°47'00.10""S, longitude: 11°51'01.55""E (of Greenwich).",1960,7011,8901,1072,Topographic mapping.,,Elf,OGP,"2008/06/24",2002.050 2003.361 2008.045,0,"D_Pointe_Noire"
-6283,Geocentric Datum of Australia 1994,geodetic,ITRF92 at epoch 1994.0.,1994,7019,8901,4177,"Topographic mapping, geodetic survey.",Coincident with WGS84 to within 1 metre.,"Australian Surveying and Land Information Group Internet WWW page. http://www.auslig.gov.au/geodesy/datums/gda.htm#specs",OGP,"2014/02/15",2011.004 2014.005,0,"D_GDA_1994"
-6284,Pulkovo 1942,geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'18.550""N, longitude: 30°19'42.090""E (of Greenwich).",1942,7024,8901,2423,Topographic mapping.,,,OGP,"2008/09/24",2008.011 2008.045,0,"D_Pulkovo_1942"
-6285,Qatar 1974,geodetic,"Fundamental point: Station G3.",1974,7022,8901,1346,Topographic mapping.,,,OGP,"2001/08/28",2001.270,0,"D_Qatar"
-6286,Qatar 1948,geodetic,"Fundamental point: Sokey 0 M. Latitude: 25°22'56.500""N, longitude: 50°45'41.000""E (of Greenwich).",1948,7020,8901,1346,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Qatar_1948"
-6287,Qornoq,geodetic,,1927,7022,8901,1107,Topographic mapping.,,,OGP,"1995/06/02",,1,
+6277,OSGB 1936,geodetic,"Prior to 2002, fundamental point: Herstmonceux, Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich). From April 2002 the datum is defined through the application of the OSTN transformation from ETRS89.",1936-01-01,7001,8901,4390,Topographic mapping.,"The average accuracy of OSTN compared to the old triangulation network (down to 3rd order) is 0.1m. With the introduction of OSTN15, the area for OGSB 1936 has effectively been extended from Britain t [...]
+6278,"OSGB 1970 (SN)",geodetic,"Fundamental point: Herstmonceux. Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich).",1970-01-01,7001,8901,1264,Scientific network.,,,OGP,"2008/06/24",2005.880 2008.045,0,"D_OSGB_1970_SN"
+6279,"OS (SN) 1980",geodetic,"Fundamental point: Herstmonceux. Latitude: 50°51'55.271""N, longitude: 0°20'45.882""E (of Greenwich).",1980-01-01,7001,8901,1354,Scientific network.,,,OGP,"2008/06/24",2008.045,0,"D_OS_SN_1980"
+6280,Padang 1884,geodetic,"Fundamental point: Padang.",1884-01-01,7004,8901,1355,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Padang_1884"
+6281,Palestine 1923,geodetic,"Fundamental point: Point 82'M  Jerusalem. Latitude: 31°44' 2.749""N, longitude: 35°12'43.490""E (of Greenwich).",1923-01-01,7010,8901,1356,Topographic mapping.,,,OGP,"2008/06/24",2004.150 2008.045,0,"D_Palestine_1923"
+6282,Congo 1960 Pointe Noire,geodetic,"Fundamental point: Point Noire Astro. Latitude: 4°47'00.10""S, longitude: 11°51'01.55""E (of Greenwich).",1960-01-01,7011,8901,1072,Topographic mapping.,,Elf,OGP,"2008/06/24",2002.050 2003.361 2008.045,0,"D_Pointe_Noire"
+6283,Geocentric Datum of Australia 1994,geodetic,ITRF92 at epoch 1994.0.,1994-01-01,7019,8901,4177,"Topographic mapping, geodetic survey.",Coincident with WGS84 to within 1 metre.,"Australian Surveying and Land Information Group Internet WWW page. http://www.auslig.gov.au/geodesy/datums/gda.htm#specs",OGP,"2014/02/15",2011.004 2014.005,0,"D_GDA_1994"
+6284,Pulkovo 1942,geodetic,"Fundamental point: Pulkovo observatory. Latitude: 59°46'18.550""N, longitude: 30°19'42.090""E (of Greenwich).",1942-01-01,7024,8901,2423,Topographic mapping.,,,OGP,"2008/09/24",2008.011 2008.045,0,"D_Pulkovo_1942"
+6285,Qatar 1974,geodetic,"Fundamental point: Station G3.",1974-01-01,7022,8901,1346,Topographic mapping.,,,OGP,"2001/08/28",2001.270,0,"D_Qatar"
+6286,Qatar 1948,geodetic,"Fundamental point: Sokey 0 M. Latitude: 25°22'56.500""N, longitude: 50°45'41.000""E (of Greenwich).",1948-01-01,7020,8901,1346,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Qatar_1948"
+6287,Qornoq,geodetic,,1927-01-01,7022,8901,1107,Topographic mapping.,,,OGP,"1995/06/02",,1,
 6288,Loma Quintana,geodetic,"Fundamental point: Loma Quintana.",,7022,8901,1313,Topographic mapping.,"Replaced by La Canoa (code 6247).",,OGP,"1995/06/02",,0,"D_Loma_Quintana"
 6289,Amersfoort,geodetic,"Fundamental point: Amersfoort. Latitude: 52°09'22.178""N, longitude: 5°23'15.478""E (of Greenwich).",,7004,8901,1275,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"http://www.rdnap.nl/",OGP,"2008/06/24",2000.560 2003.361 2005.460 2008.045,0,"D_Amersfoort"
-6291,South American Datum 1969,geodetic,,1969,7036,8901,1358,Topographic mapping.,"SAD69 uses GRS67 ellipsoid with 1/f to exactly 2 decimal places.  Precision of ellipsoid entry increased from 2 to 5 dp with change id 97.252.  Error introduced if not using the truncated precision is 0 to 31mm.",,OGP,"1996/10/18",1996.090 1997.252,1,
-6292,Sapper Hill 1943,geodetic,,1943,7022,8901,3247,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Sapper_Hill_1943"
+6291,South American Datum 1969,geodetic,,1969-01-01,7036,8901,1358,Topographic mapping.,"SAD69 uses GRS67 ellipsoid with 1/f to exactly 2 decimal places.  Precision of ellipsoid entry increased from 2 to 5 dp with change id 97.252.  Error introduced if not using the truncated precision is 0 to 31mm.",,OGP,"1996/10/18",1996.090 1997.252,1,
+6292,Sapper Hill 1943,geodetic,,1943-01-01,7022,8901,3247,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Sapper_Hill_1943"
 6293,Schwarzeck,geodetic,"Fundamental point: Schwarzeck. Latitude: 22°45'35.820""S, longitude: 18°40'34.549""E (of Greenwich). Fixed during German South West Africa-British Bechuanaland boundary survey of 1898-1903.",,7046,8901,1169,Topographic mapping.,,"Private Communication, Directorate of Surveys and Land Information, Cape Town.",OGP,"2008/06/24",2001.150 2003.362 2008.045,0,"D_Schwarzeck"
 6294,Segora,geodetic,,,7004,8901,1359,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Segora"
 6295,Serindung,geodetic,"Fundamental point: Ep A. Latitude: 1°06'10.60""N, longitude: 105°00'59.82""E (of Greenwich).",,7004,8901,4005,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2012/03/25",2003.362 2005.460 2008.045 2012.032,0,"D_Serindung"
 6296,Sudan,geodetic,,,7011,8901,1361,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Sudan"
-6297,Tananarive 1925,geodetic,"Fundamental point: Tananarive observatory. Latitude: 18°55'02.10""S, longitude: 47°33'06.75""E (of Greenwich).",2025,7022,8901,1149,Topographic mapping.,,IGN Paris,OGP,"2010/03/30",2003.361 2008.045 2009.106,0,"D_Tananarive_1925"
-6298,Timbalai 1948,geodetic,"Fundamental point: Station P85 at Timbalai. Latitude: 5°17' 3.548""N, longitude: 115°10'56.409""E (of Greenwich).",1948,7016,8901,1362,Topographic mapping.,"In 1968, the original adjustment was densified in Sarawak and extended to Sabah.",Defence Geographic Centre.,OGP,"2008/06/24",2006.252 2008.045,0,"D_Timbalai_1948"
-6299,TM65,geodetic,Adjusted to best mean fit 12 stations of the OSNI 1952 primary adjustment.,1965,7002,8901,1305,Topographic mapping.,"Differences between OSNI 1952 and TM65 at these stations are RMS 0.25m east, 0.23m north, maximum vector 0.57m. TM65 replaced by and not to be confused with Geodetic Datum of 1965 alias 1975 Mapping Adjustment or TM75 (datum code 6300).","""The Irish Grid - A Description of the Co-ordinate Reference System"" published by Ordnance Survey of Ireland, Dubli [...]
-6300,Geodetic Datum of 1965,geodetic,Adjusted to best mean fit 9 stations of the OSNI 1952 primary adjustment in Northern Ireland plus the 1965 values of 3 stations in the Republic of Ireland.,1975,7002,8901,1305,"Geodetic survey, topographic mapping and engineering survey.","Differences from the 1965 adjustment (datum code 6299) are: average difference in Eastings 0.092m; average difference in Northings 0.108m; maximum vector difference 0.548m.","""The Irish Grid - A Description of the  [...]
-6301,Tokyo,geodetic,"Fundamental point: Nikon-Keido-Genten. Latitude: 35°39'17.5148""N, longitude: 139°44'40.5020""E (of Greenwich). Longitude derived in 1918.",1918,7004,8901,1364,"Geodetic survey, cadastre, topographic mapping, engineering survey.","In Japan, replaces Tokyo 1892 (code 1048) and replaced by Japanese Geodetic Datum 2000 (code 6611). In Korea used only for geodetic applications before being replaced by Korean 1985 (code 6162).","Geographic Survey Institute; Japan; Bulleti [...]
+6297,Tananarive 1925,geodetic,"Fundamental point: Tananarive observatory. Latitude: 18°55'02.10""S, longitude: 47°33'06.75""E (of Greenwich).",1925-01-01,7022,8901,1149,Topographic mapping.,,IGN Paris,IOGP,"2016/09/16",2003.361 2008.045 2009.106 2016.020,0,"D_Tananarive_1925"
+6298,Timbalai 1948,geodetic,"Fundamental point: Station P85 at Timbalai. Latitude: 5°17' 3.548""N, longitude: 115°10'56.409""E (of Greenwich).",1948-01-01,7016,8901,1362,Topographic mapping.,"In 1968, the original adjustment was densified in Sarawak and extended to Sabah.",Defence Geographic Centre.,OGP,"2008/06/24",2006.252 2008.045,0,"D_Timbalai_1948"
+6299,TM65,geodetic,Adjusted to best mean fit 12 stations of the OSNI 1952 primary adjustment.,1965-01-01,7002,8901,1305,Topographic mapping.,"Differences between OSNI 1952 and TM65 at these stations are RMS 0.25m east, 0.23m north, maximum vector 0.57m. TM65 replaced by and not to be confused with Geodetic Datum of 1965 alias 1975 Mapping Adjustment or TM75 (datum code 6300).","""The Irish Grid - A Description of the Co-ordinate Reference System"" published by Ordnance Survey of Ireland, [...]
+6300,Geodetic Datum of 1965,geodetic,Adjusted to best mean fit 9 stations of the OSNI 1952 primary adjustment in Northern Ireland plus the 1965 values of 3 stations in the Republic of Ireland.,1975-01-01,7002,8901,1305,"Geodetic survey, topographic mapping and engineering survey.","Differences from the 1965 adjustment (datum code 6299) are: average difference in Eastings 0.092m; average difference in Northings 0.108m; maximum vector difference 0.548m.","""The Irish Grid - A Description o [...]
+6301,Tokyo,geodetic,"Fundamental point: Nikon-Keido-Genten. Latitude: 35°39'17.5148""N, longitude: 139°44'40.5020""E (of Greenwich). Longitude derived in 1918.",1918-01-01,7004,8901,1364,"Geodetic survey, cadastre, topographic mapping, engineering survey.","In Japan, replaces Tokyo 1892 (code 1048) and replaced by Japanese Geodetic Datum 2000 (code 6611). In Korea used only for geodetic applications before being replaced by Korean 1985 (code 6162).","Geographic Survey Institute; Japan; B [...]
 6302,Trinidad 1903,geodetic,"Station 00, Harbour Master's Flagstaff, Port of Spain. 
-Trinidad 1903 / Trinidad Grid coordinates (Clarke's links): 333604.30 E, 436366.91 N (Latitude: 10°38'39.01""N,  Longitude: 61°30'38.00""W of Greenwich)",1903,7007,8901,1339,Topographic mapping.,,"""Land Surveyor's Handbook"", 1935, published under the direction of JW MacGillivray, Surveyor General, Land & Survey's Department, Trinidad & Tobago.",OGP,"2008/06/24",2003.362 2004.130 2008.045,0,"D_Trinidad_1903"
-6303,Trucial Coast 1948,geodetic,"Fundamental point: TC1. Latitude: 25°23'50.190""N, longitude: 55°26'43.950""E (of Greenwich).",1948,7020,8901,1363,Oil industry mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Trucial_Coast_1948"
-6304,Voirol 1875,geodetic,"Fundamental point: Voirol. Latitude: 36°45'07.927""N, longitude: 3°02'49.435""E of Greenwich. Uses RGS (and old IGN) value of 2°20'13.95""for Greenwich-Paris meridian difference.",1875,7011,8901,1365,Topographic mapping.,"Replaced by Voirol 1879 (code 6671).",IGN Paris,OGP,"2008/06/24",2003.361 2008.045,0,"D_Voirol_1875"
-6306,Bern 1938,geodetic,"Fundamental point: Old Bern observatory. Latitude: 46°57'07.890""N, longitude: 7°26'22.335""E (of Greenwich).",1938,7004,8901,1286,Topographic mapping.,"This redetermination of the coordinates of fundamental point is used for scientific purposes and as the graticule overprinted on topographic maps constructed on the CH1903 / LV03 projected CS (code 21781).","""Die Projektionen der schweizerischen Plan- und Kartenwerke""; J. Bolliger 1967",OGP,"2008/06/24",2008.04 [...]
-6307,Nord Sahara 1959,geodetic,"Coordinates of primary network readjusted on ED50 datum and then transformed conformally to Clarke 1880 (RGS) ellipsoid.",1959,7012,8901,1026,Topographic mapping.,"Adjustment includes Morocco and Tunisia but use only in Algeria. Within Algeria the adjustment is north of 32°N but use has been extended southwards in many disconnected projects, some based on independent astro stations rather than the geodetic network.","""Le System Geodesique Nord-Sahara""; I [...]
-6308,Stockholm 1938,geodetic,"Fundamental point: Stockholm observatory.",1938,7004,8901,3313,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RT90 adjustment (datum code 6124)",,OGP,"1996/04/12",,0,"D_Stockholm_1938"
+Trinidad 1903 / Trinidad Grid coordinates (Clarke's links): 333604.30 E, 436366.91 N (Latitude: 10°38'39.01""N,  Longitude: 61°30'38.00""W of Greenwich)",1903-01-01,7007,8901,1339,Topographic mapping.,,"""Land Surveyor's Handbook"", 1935, published under the direction of JW MacGillivray, Surveyor General, Land & Survey's Department, Trinidad & Tobago.",OGP,"2008/06/24",2003.362 2004.130 2008.045,0,"D_Trinidad_1903"
+6303,Trucial Coast 1948,geodetic,"Fundamental point: TC1. Latitude: 25°23'50.190""N, longitude: 55°26'43.950""E (of Greenwich).",1948-01-01,7020,8901,1363,Oil industry mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Trucial_Coast_1948"
+6304,Voirol 1875,geodetic,"Fundamental point: Voirol. Latitude: 36°45'07.927""N, longitude: 3°02'49.435""E of Greenwich. Uses RGS (and old IGN) value of 2°20'13.95""for Greenwich-Paris meridian difference.",1875-01-01,7011,8901,1365,Topographic mapping.,"Replaced by Voirol 1879 (code 6671).",IGN Paris,OGP,"2008/06/24",2003.361 2008.045,0,"D_Voirol_1875"
+6306,Bern 1938,geodetic,"Fundamental point: Old Bern observatory. Latitude: 46°57'07.890""N, longitude: 7°26'22.335""E (of Greenwich).",1938-01-01,7004,8901,1286,Topographic mapping.,"This redetermination of the coordinates of fundamental point is used for scientific purposes and as the graticule overprinted on topographic maps constructed on the CH1903 / LV03 projected CS (code 21781).","""Die Projektionen der schweizerischen Plan- und Kartenwerke""; J. Bolliger 1967",OGP,"2008/06/24",2 [...]
+6307,Nord Sahara 1959,geodetic,"Coordinates of primary network readjusted on ED50 datum and then transformed conformally to Clarke 1880 (RGS) ellipsoid.",1959-01-01,7012,8901,1026,Topographic mapping.,"Adjustment includes Morocco and Tunisia but use only in Algeria. Within Algeria the adjustment is north of 32°N but use has been extended southwards in many disconnected projects, some based on independent astro stations rather than the geodetic network.","""Le System Geodesique Nord-Sahar [...]
+6308,Stockholm 1938,geodetic,"Fundamental point: Stockholm observatory.",1938-01-01,7004,8901,3313,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RT90 adjustment (datum code 6124)",,OGP,"1996/04/12",,0,"D_Stockholm_1938"
 6309,Yacare,geodetic,"Fundamental point: Yacare. Latitude: 30°35'53.68""S, longitude: 57°25'01.30""W (of Greenwich).",,7022,8901,3326,Topographic mapping.,,"NIMA http://earth-info.nima.mil/",OGP,"2011/03/28",2003.362 2005.460 2008.045 2011.018 2011.021,0,"D_Yacare"
 6310,Yoff,geodetic,"Fundamental point: Yoff. Latitude: 14°44'41.62""N, longitude: 17°29'07.02""W (of Greenwich).",,7011,8901,1207,Topographic mapping.,,,OGP,"2008/06/24",2003.362 2008.045,0,"D_Yoff"
 6311,Zanderij,geodetic,,,7022,8901,1222,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Zanderij"
-6312,Militar-Geographische Institut,geodetic,"Fundamental point: Hermannskogel. Latitude: 48°16'15.29""N, longitude: 16°17'41.06""E (of Greenwich).",1901,7004,8901,1037,Geodetic survey.,"The longitude of the datum origin equates to a value for the Ferro meridian of 17°40' exactly west of Greenwich.","Bundesamt fur Eich- und Vermessungswesen; Wien",OGP,"2009/06/02",2008.045 2009.015,0,"D_MGI"
-6313,Reseau National Belge 1972,geodetic,"Fundamental point: Uccle observatory. Latitude: 50°47'57.704""N, longitude: 4°21'24.983""E (of Greenwich).",1972,7022,8901,1347,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Belge_1972"
+6312,Militar-Geographische Institut,geodetic,"Fundamental point: Hermannskogel. Latitude: 48°16'15.29""N, longitude: 16°17'41.06""E (of Greenwich).",1901-01-01,7004,8901,1037,Geodetic survey.,"The longitude of the datum origin equates to a value for the Ferro meridian of 17°40' exactly west of Greenwich.","Bundesamt fur Eich- und Vermessungswesen; Wien",OGP,"2009/06/02",2008.045 2009.015,0,"D_MGI"
+6313,Reseau National Belge 1972,geodetic,"Fundamental point: Uccle observatory. Latitude: 50°47'57.704""N, longitude: 4°21'24.983""E (of Greenwich).",1972-01-01,7022,8901,1347,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Belge_1972"
 6314,Deutsches Hauptdreiecksnetz,geodetic,"Fundamental point: Rauenberg. Latitude: 52°27'12.021""N, longitude: 13°22'04.928""E (of Greenwich).  This station was destroyed in 1910 and the station at Potsdam substituted as the fundamental point.",,7004,8901,2326,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"BKG via EuroGeographics. http://crs.bkg.bund.de",OGP,"2008/06/24",2001.511 2006.410 2008.045,0,"D_Deutsches_Hauptdreiecksnetz"
-6315,Conakry 1905,geodetic,"Fundamental point: Conakry. Latitude: 10.573766g N, longitude: 17.833682g W (of Paris).",1905,7011,8901,3257,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Conakry_1905"
-6316,Dealul Piscului 1930,geodetic,"Fundamental point: latitude 44°24'33.9606""N, longitude 26°06'44.8772""E (of Greenwich).",1930,7022,8901,3295,Topographic mapping.,"Replaced by Pulkovo 1942(58) (datum code 6179)",Institute for Geodesy Photogrametry and Land Management,OGP,"2008/09/24",2008.011 2008.045,0,"D_Dealul_Piscului_1933"
-6317,Dealul Piscului 1970,geodetic,"Fundamental point: latitude 44°24'23.7709""N, longitude 26°06'44.1265""E (of Greenwich).",1970,7024,8901,1197,Topographic mapping.,"Replaces 1933 adjustment (datum code 6316)",Institute for Geodesy Photogrametry and Land Management,OGP,"2008/06/24",2008.045,1,"D_Dealul_Piscului_1970"
-6318,National Geodetic Network,geodetic,,1993,7030,8901,3267,Geodetic survey.,Replaces 1984 adjustment which used the WGS72 ellipsoid.,,OGP,"2004/06/16",2004.410,0,"D_NGN"
+6315,Conakry 1905,geodetic,"Fundamental point: Conakry. Latitude: 10.573766g N, longitude: 17.833682g W (of Paris).",1905-01-01,7011,8901,3257,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Conakry_1905"
+6316,Dealul Piscului 1930,geodetic,"Fundamental point: latitude 44°24'33.9606""N, longitude 26°06'44.8772""E (of Greenwich).",1930-01-01,7022,8901,3295,Topographic mapping.,"Replaced by Pulkovo 1942(58) (datum code 6179)",Institute for Geodesy Photogrametry and Land Management,OGP,"2008/09/24",2008.011 2008.045,0,"D_Dealul_Piscului_1933"
+6317,Dealul Piscului 1970,geodetic,"Fundamental point: latitude 44°24'23.7709""N, longitude 26°06'44.1265""E (of Greenwich).",1970-01-01,7024,8901,1197,Topographic mapping.,"Replaces 1933 adjustment (datum code 6316)",Institute for Geodesy Photogrametry and Land Management,OGP,"2008/06/24",2008.045,1,"D_Dealul_Piscului_1970"
+6318,National Geodetic Network,geodetic,,1993-01-01,7030,8901,3267,Geodetic survey.,Replaces 1984 adjustment which used the WGS72 ellipsoid.,,OGP,"2004/06/16",2004.410,0,"D_NGN"
 6319,Kuwait Utility,geodetic,,,7019,8901,1310,"Cadastre, engineering survey.",,,OGP,"1996/04/12",,0,"D_Kuwait_Utility"
-6322,World Geodetic System 1972,geodetic,Developed from a worldwide distribution of terrestrial and geodetic satellite observations and defined through a set of station coordinates.,1972,7043,8901,1262,Satellite navigation.,Used by GPS before 1987. For Transit satellite positioning see also WGS 72BE.,"NIMA http://earth-info.nima.mil/",OGP,"2006/08/24",1999.030 2003.362 2005.460 2006.820,0,"D_WGS_1972"
-6324,WGS 72 Transit Broadcast Ephemeris,geodetic,,1972,7043,8901,1262,Satellite navigation.,Alleged datum for use with Transit broadcast ephemeris prior to 1989. Relationship to WGS 72 has changed over time.,,OGP,"2006/08/24",1999.030 2006.820,0,"D_WGS_1972_BE"
+6322,World Geodetic System 1972,geodetic,Developed from a worldwide distribution of terrestrial and geodetic satellite observations and defined through a set of station coordinates.,1972-01-01,7043,8901,1262,Satellite navigation.,Used by GPS before 1987. For Transit satellite positioning see also WGS 72BE.,"NIMA http://earth-info.nima.mil/",OGP,"2006/08/24",1999.030 2003.362 2005.460 2006.820,0,"D_WGS_1972"
+6324,WGS 72 Transit Broadcast Ephemeris,geodetic,,1972-01-01,7043,8901,1262,Satellite navigation.,Alleged datum for use with Transit broadcast ephemeris prior to 1989. Relationship to WGS 72 has changed over time.,,OGP,"2006/08/24",1999.030 2006.820,0,"D_WGS_1972_BE"
 6326,World Geodetic System 1984,geodetic,"Defined through a consistent set of station coordinates. These have changed with time: by 0.7m on 1994-06-29 (G730), a further 0.2m on 1997-01-29 (G873),  0.06m on 2002-01-20 (G1150), 0.2m on 2012-02-08 (G1674) and 0.02m on 2013-10-16 (G1762).",,7030,8901,1262,Satellite navigation.,"EPSG::6326 has been the then current realisation. No distinction is made between the original and subsequent (G730, G873, G1150, G1674 and G1762) WGS 84 frames. Since [...]
 http://gis-lab.info/docs/nima-tr8350.2-addendum.pdf. Also NGA.STND.0036_1.0.0_WGS84 of 2014-07-08.",OGP,"2014/11/21",2002.151 2002.890 2003.270 2005.460 2005.550 2006.810 2012.097 2014.081,0,
-6600,Anguilla 1957,geodetic,"Fundamental point: station A4, Police.",1957,7012,8901,3214,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Anguilla_1957"
-6601,Antigua 1943,geodetic,"Fundamental point: station A14.",1943,7012,8901,1273,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Antigua_1943"
-6602,Dominica 1945,geodetic,"Fundamental point: station M12.",1945,7012,8901,3239,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Dominica_1945"
-6603,Grenada 1953,geodetic,"Fundamental point: station GS8, Sante Marie.",1953,7012,8901,1551,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"2006/02/09",2006.030,0,"D_Grenada_1953"
-6604,Montserrat 1958,geodetic,"Fundamental point: station M36.",1958,7012,8901,3279,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Montserrat_1958"
-6605,St. Kitts 1955,geodetic,"Fundamental point: station K12.",1955,7012,8901,3297,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_St_Kitts_1955"
-6606,St. Lucia 1955,geodetic,"Fundamental point: station DCS3.",1955,7012,8901,3298,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_St_Lucia_1955"
-6607,St. Vincent 1945,geodetic,"Fundamental point: station V1, Fort Charlotte.",1945,7012,8901,3300,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"2006/02/09",2006.030,0,"D_St_Vincent_1945"
-6608,"North American Datum 1927 (1976)",geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",1976,7008,8901,1367,"Geodetic survey, cadastre, topographic mapping, engineering survey.","NAD27(76) used in Ontario for all maps at scale 1/20 000 and larger; elsewhere in Canada for selected purposes.",Geodetic Survey of Canada.,OGP,"2008/06/24",2008.045,0,"D_NAD_1927_Definition_1976"
-6609,"North American Datum 1927 (CGQ77)",geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",1977,7008,8901,1368,"Geodetic survey, cadastre, topographic mapping, engineering survey.","NAD27 (CGQ77) used in Quebec for all maps at scale 1/20 000 and larger; generally for maps issued by the Quebec cartography office whose reference system is CGQ77.","Geodetic Service of Quebec.  Contact alain.bernard at mrn.gouv.qc.ca",OGP,"2008/06 [...]
-6610,Xian 1980,geodetic,Xian observatory.,1980,7049,8901,3228,"Geodetic survey, topographic and engineering survey.",,"Chinese Science Bulletin, 2009, 54:2714-2721.",OGP,"2009/11/24",2009.084,0,"D_Xian_1980"
-6611,Hong Kong 1980,geodetic,"Fundamental point: Trig ""Zero"", 38.4 feet south along the transit circle of the Kowloon Observatory. Latitude 22°18'12.82"", longitude 114°10'18.75""E (of Greenwich).",1980,7022,8901,1118,"Geodetic survey, topgraphic and engineering survey, cadastre.","Replaces Hong Kong 1963 and Hong Kong 1963(67).","Survey and Mapping Office, Lands Department. http://www.info.gov.hk/landsd/mapping/tindex.htm",OGP,"2008/06/24",2005.260 2008.045,0,"D_Hong_Kong_1980"
-6612,Japanese Geodetic Datum 2000,geodetic,"ITRF94 at epoch 1997.0. Fundamental point: Tokyo-Taisho, latitude: 35°39'29.1572""N, longitude: 139°44'28.8759""E (of Greenwich).",2000,7019,8901,1129,"Geodetic survey, topographic and engineering survey.","Instigated under amendment to the Japanese Surveying Law with effect from April 2002. Replaces Tokyo datum (code 6301). Replaced by JGD2011 (datum code 1128) with effect from 21st October 2011.","Japanese Survey Federation and Geographical S [...]
+6600,Anguilla 1957,geodetic,"Fundamental point: station A4, Police.",1957-01-01,7012,8901,3214,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Anguilla_1957"
+6601,Antigua 1943,geodetic,"Fundamental point: station A14.",1943-01-01,7012,8901,1273,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Antigua_1943"
+6602,Dominica 1945,geodetic,"Fundamental point: station M12.",1945-01-01,7012,8901,3239,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Dominica_1945"
+6603,Grenada 1953,geodetic,"Fundamental point: station GS8, Sante Marie.",1953-01-01,7012,8901,1551,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"2006/02/09",2006.030,0,"D_Grenada_1953"
+6604,Montserrat 1958,geodetic,"Fundamental point: station M36.",1958-01-01,7012,8901,3279,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_Montserrat_1958"
+6605,St. Kitts 1955,geodetic,"Fundamental point: station K12.",1955-01-01,7012,8901,3297,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_St_Kitts_1955"
+6606,St. Lucia 1955,geodetic,"Fundamental point: station DCS3.",1955-01-01,7012,8901,3298,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"1999/04/22",,0,"D_St_Lucia_1955"
+6607,St. Vincent 1945,geodetic,"Fundamental point: station V1, Fort Charlotte.",1945-01-01,7012,8901,3300,Topographic mapping.,,Ordnance Survey of Great Britain.,OGP,"2006/02/09",2006.030,0,"D_St_Vincent_1945"
+6608,"North American Datum 1927 (1976)",geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",1976-01-01,7008,8901,1367,"Geodetic survey, cadastre, topographic mapping, engineering survey.","NAD27(76) used in Ontario for all maps at scale 1/20 000 and larger; elsewhere in Canada for selected purposes.",Geodetic Survey of Canada.,OGP,"2008/06/24",2008.045,0,"D_NAD_1927_Definition_1976"
+6609,"North American Datum 1927 (CGQ77)",geodetic,"Fundamental point: Meade's Ranch. Latitude: 39°13'26.686""N, longitude: 98°32'30.506""W (of Greenwich).",1977-01-01,7008,8901,1368,"Geodetic survey, cadastre, topographic mapping, engineering survey.","NAD27 (CGQ77) used in Quebec for all maps at scale 1/20 000 and larger; generally for maps issued by the Quebec cartography office whose reference system is CGQ77.","Geodetic Service of Quebec.  Contact alain.bernard at mrn.gouv.qc.ca",OGP,"2 [...]
+6610,Xian 1980,geodetic,Xian observatory.,1980-01-01,7049,8901,3228,"Geodetic survey, topographic and engineering survey.",,"Chinese Science Bulletin, 2009, 54:2714-2721.",OGP,"2009/11/24",2009.084,0,"D_Xian_1980"
+6611,Hong Kong 1980,geodetic,"Fundamental point: Trig ""Zero"", 38.4 feet south along the transit circle of the Kowloon Observatory. Latitude 22°18'12.82"", longitude 114°10'18.75""E (of Greenwich).",1980-01-01,7022,8901,1118,"Geodetic survey, topgraphic and engineering survey, cadastre.","Replaces Hong Kong 1963 and Hong Kong 1963(67).","Survey and Mapping Office, Lands Department. http://www.info.gov.hk/landsd/mapping/tindex.htm",OGP,"2008/06/24",2005.260 2008.045,0,"D_Hong_Kong_1980"
+6612,Japanese Geodetic Datum 2000,geodetic,"ITRF94 at epoch 1997.0. Fundamental point: Tokyo-Taisho, latitude: 35°39'29.1572""N, longitude: 139°44'28.8759""E (of Greenwich).",1997-01-01,7019,8901,1129,"Geodetic survey, topographic and engineering survey.","Instigated under amendment to the Japanese Surveying Law with effect from April 2002. Replaces Tokyo datum (code 6301). Replaced by JGD2011 (datum code 1128) with effect from 21st October 2011.","Japanese Survey Federation and Geograph [...]
 6613,Gunung Segara,geodetic,"Station P5 (Gunung Segara). Latitude 0°32'12.83""S, longitude 117°08'48.47""E (of Greenwich).",,7004,8901,1360,Topographic mapping.,,TotalFinaElf.,OGP,"2008/06/24",2008.045,0,"D_Gunung_Segara"
-6614,Qatar National Datum 1995,geodetic,Defined by transformation from WGS 84 - see coordinate operation code 1840.,1995,7022,8901,1346,Topographic mapping.,,Qatar Centre for Geographic Information.,OGP,"2002/06/28",,0,"D_QND_1995"
-6615,Porto Santo 1936,geodetic,SE Base on Porto Santo island.,1936,7022,8901,1314,Topographic mapping.,"Replaced by 1995 adjustment (datum code 6663). For Selvagens see Selvagem Grande (code 6616).","Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2003/08/14",2003.231 2003.232,0,"D_Porto_Santo_1936"
+6614,Qatar National Datum 1995,geodetic,Defined by transformation from WGS 84 - see coordinate operation code 1840.,1995-01-01,7022,8901,1346,Topographic mapping.,,Qatar Centre for Geographic Information.,OGP,"2002/06/28",,0,"D_QND_1995"
+6615,Porto Santo 1936,geodetic,SE Base on Porto Santo island.,1936-01-01,7022,8901,1314,Topographic mapping.,"Replaced by 1995 adjustment (datum code 6663). For Selvagens see Selvagem Grande (code 6616).","Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2003/08/14",2003.231 2003.232,0,"D_Porto_Santo_1936"
 6616,Selvagem Grande,geodetic,,,7022,8901,2779,Topographic mapping.,,"Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2003/08/14",2003.232,0,"D_Selvagem_Grande_1938"
-6618,South American Datum 1969,geodetic,"Fundamental point: Chua. Geodetic latitude: 19°45'41.6527""S; geodetic longitude: 48°06'04.0639""W (of Greenwich). (Astronomic coordinates: Latitude 19°45'41.34""S +/- 0.05"", longitude 48°06'07.80""W +/- 0.08"").",1969,7050,8901,1358,Topographic mapping.,"SAD69 uses GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places. In Brazil only, replaced by SAD69(96) (datum code 1075).",DMA 1974.,OGP,"2011/07/27",2003.362 2008.045 2011.053,0,"D_South [...]
-6619,SWEREF99,geodetic,Densification of ETRS89.,1999,7019,8901,1225,"Geodetic survey, cadastre, topographic mapping, engineering survey.","The solution was calculated in ITRF 97 epoch 1999.5, and has subsequently been corrected to ETRS 89 in accordance with guidelines given by EUREF.","National Land Survey of Sweden http://www.lantmateriet.se",OGP,"2010/03/01",2009.024,0,"D_SWEREF99"
-6620,Point 58,geodetic,"Fundamental point: Point 58. Latitude: 12°52'44.045""N, longitude: 3°58'37.040""E (of Greenwich).",1969,7012,8901,2790,Geodetic survey,"Used as the basis for computation of the 12th Parallel traverse conducted 1966-70 from Senegal to Chad and connecting to the Blue Nile 1958 (Adindan) triangulation in Sudan.",IGN Paris.,IOGP,"2015/04/22",2008.045 2011.090 2015.010,0,"D_Point_58"
+6618,South American Datum 1969,geodetic,"Fundamental point: Chua. Geodetic latitude: 19°45'41.6527""S; geodetic longitude: 48°06'04.0639""W (of Greenwich). (Astronomic coordinates: Latitude 19°45'41.34""S +/- 0.05"", longitude 48°06'07.80""W +/- 0.08"").",1969-01-01,7050,8901,1358,Topographic mapping.,"SAD69 uses GRS 1967 ellipsoid but with 1/f to exactly 2 decimal places. In Brazil only, replaced by SAD69(96) (datum code 1075).",DMA 1974.,OGP,"2011/07/27",2003.362 2008.045 2011.053,0,"D [...]
+6619,SWEREF99,geodetic,Densification of ETRS89.,1999-06-01,7019,8901,1225,"Geodetic survey, cadastre, topographic mapping, engineering survey.","The solution was calculated in ITRF 97 epoch 1999.5, and has subsequently been corrected to ETRS 89 in accordance with guidelines given by EUREF.","National Land Survey of Sweden http://www.lantmateriet.se",OGP,"2010/03/01",2009.024,0,"D_SWEREF99"
+6620,Point 58,geodetic,"Fundamental point: Point 58. Latitude: 12°52'44.045""N, longitude: 3°58'37.040""E (of Greenwich).",1969-01-01,7012,8901,2790,Geodetic survey,"Used as the basis for computation of the 12th Parallel traverse conducted 1966-70 from Senegal to Chad and connecting to the Blue Nile 1958 (Adindan) triangulation in Sudan.",IGN Paris.,IOGP,"2015/04/22",2008.045 2011.090 2015.010,0,"D_Point_58"
 6621,Fort Marigot,geodetic,,,7022,8901,2828,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2009.073,0,"D_Fort_Marigot"
-6622,Guadeloupe 1948,geodetic,,1948,7022,8901,2829,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2004.561 2009.073,0,"D_Sainte_Anne"
-6623,Centre Spatial Guyanais 1967,geodetic,"Fundamental point: Kourou-Diane. Latitude: 5°15'53.699""N, longitude: 52°48'09.149""W (of Greenwich).",1967,7022,8901,3105,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGFG95 (code 6624).",IGN Paris.,OGP,"2008/06/24",2004.562 2008.045,0,"D_CSG_1967"
-6624,Reseau Geodesique Francais Guyane 1995,geodetic,ITRF93 at epoch 1995.0,1995,7019,8901,1097,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces CSG67 (datum code 6623).",IGN Paris.,OGP,"2002/11/29",,0,"D_RGFG_1995"
-6625,Martinique 1938,geodetic,"Fundamental point: Fort Desaix. Latitude: 14°36'54.090""N, longitude: 61°04'04.030""W (of Greenwich).",1938,7022,8901,3276,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2004.561 2008.045 2009.073,0,"D_Fort_Desaix"
-6626,Reunion 1947,geodetic,"Fundamental point: Piton des Neiges (Borne). Latitude: 21°05'13.119""S, longitude: 55°29'09.193""E (of Greenwich).",1947,7022,8901,3337,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGR92 (datum code 6627).",IGN Paris.,OGP,"2008/06/24",2004.561 2008.045,0,"D_Reunion_1947"
-6627,Reseau Geodesique de la Reunion 1992,geodetic,ITRF91 at epoch 1993.0,1992,7019,8901,3902,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Piton des Neiges (code 6626).",IGN Paris.,OGP,"2012/01/05",2006.770 2011.109,0,"D_RGR_1992"
-6628,Tahiti 52,geodetic,"Fundamental point: Tahiti North Base. Latitude: 17°38'10.0""S, longitude: 149°36'57.8""W (of Greenwich).",1952,7022,8901,2811,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by Tahiti 79 (datum code 6690) in Tahiti and Moorea 87 (code 6691) in Moorea.","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2005.380 2008.045,0,"D_Tahiti_1952"
-6629,Tahaa 54,geodetic,"Fundamental point: Tahaa East Base. Latitude: 16°33'20.97""S, longitude: 151°29'06.25""W (of Greenwich).",1954,7022,8901,2812,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2005.380 2008.045,0,"D_Tahaa_1954"
-6630,IGN72 Nuku Hiva,geodetic,"Fundamental point: Taiohae. Latitude: 8°55'03.97""S, longitude: 140°05'36.24""W (of Greenwich).",1972,7022,8901,3129,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2005.380 2008.045,0,"D_IGN72_Nuku_Hiva"
-6631,K0 1949,geodetic,,1949,7022,8901,2816,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,IGN Paris.,OGP,"2002/11/29",,1,
-6632,Combani 1950,geodetic,Combani South Base.,1950,7022,8901,3340,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGM04 and Cadastre 1997 (datum codes 1036-37).",IGN Paris.,OGP,"2009/10/29",2009.072,0,"D_Combani_1950"
-6633,IGN56 Lifou,geodetic,South end of the Goume base.,1956,7022,8901,2814,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_IGN56_Lifou"
-6634,IGN72 Grande Terre,geodetic,North end of Gomen base.,1972,7022,8901,2822,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_IGN72_Grande_Terre"
-6635,ST87 Ouvea,geodetic,,1987,7022,8901,2813,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Service Topographique de la Nouvelle Caledonie.,OGP,"2002/11/29",,1,
-6636,Petrels 1972,geodetic,"Fundamental point: Astro station DZ on Ile de Petrels. Latitude: 66°40'00""S, longitude: 140°00'46""E (of Greenwich).",1972,7022,8901,2817,"Geodetic survey,  topographic mapping.",,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Petrels_1972"
-6637,Pointe Geologie Perroud 1950,geodetic,"Fundamental point: Astro station G.0 on Pointe Geologie. Latitude: 66°39'30""S, longitude: 140°01'00""E (of Greenwich).",1950,7022,8901,2818,"Geodetic survey,  topographic mapping.",,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Pointe_Geologie_Perroud_1950"
-6638,Saint Pierre et Miquelon 1950,geodetic,,1950,7008,8901,3299,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGSPM06 (datum code 1038).",IGN Paris.,OGP,"2011/01/25",2006.060 2009.072 2011.004,0,"D_Saint_Pierre_et_Miquelon_1950"
-6639,MOP78,geodetic,,1978,7022,8901,2815,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,IGN Paris.,OGP,"2002/11/29",,0,"D_MOP78"
-6640,Reseau de Reference des Antilles Francaises 1991,geodetic,WGS 84 coordinates of a single station determined during the 1988 Tango mission.,1991,7030,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Fort Marigot and Sainte Anne (datum codes 6621-22) in Guadeloupe and Fort Desaix (datum code 6625) in Martinique.",IGN Paris.,OGP,"2004/03/26",2004.200 2009.073,1,
-6641,IGN53 Mare,geodetic,South-east end of the La Roche base.,1953,7022,8901,2819,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_IGN53_Mare"
-6642,ST84 Ile des Pins,geodetic,"Fundamental point: Pic Nga.",1984,7022,8901,2820,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_ST84_Ile_des_Pins"
-6643,ST71 Belep,geodetic,,1971,7022,8901,2821,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Service Topographique de la Nouvelle Caledonie.,OGP,"2002/11/29",,0,"D_ST71_Belep"
-6644,NEA74 Noumea,geodetic,Noumea old signal station.,1974,7022,8901,2823,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_NEA74_Noumea"
-6645,Reseau Geodesique Nouvelle Caledonie 1991,geodetic,ITRF90 at epoch 1989.0,1989,7022,8901,1174,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Service Topographique de la Nouvelle Caledonie.,OGP,"2002/11/29",,1,"D_RGNC_1991"
+6622,Guadeloupe 1948,geodetic,,1948-01-01,7022,8901,2829,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2004.561 2009.073,0,"D_Sainte_Anne"
+6623,Centre Spatial Guyanais 1967,geodetic,"Fundamental point: Kourou-Diane. Latitude: 5°15'53.699""N, longitude: 52°48'09.149""W (of Greenwich).",1967-01-01,7022,8901,3105,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGFG95 (code 6624).",IGN Paris.,OGP,"2008/06/24",2004.562 2008.045,0,"D_CSG_1967"
+6624,Reseau Geodesique Francais Guyane 1995,geodetic,ITRF93 at epoch 1995.0,1995-01-01,7019,8901,1097,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces CSG67 (datum code 6623).",IGN Paris.,OGP,"2002/11/29",,0,"D_RGFG_1995"
+6625,Martinique 1938,geodetic,"Fundamental point: Fort Desaix. Latitude: 14°36'54.090""N, longitude: 61°04'04.030""W (of Greenwich).",1938-01-01,7022,8901,3276,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RRAF 1991 (datum code 1047).",IGN Paris.,OGP,"2009/11/24",2004.561 2008.045 2009.073,0,"D_Fort_Desaix"
+6626,Reunion 1947,geodetic,"Fundamental point: Piton des Neiges (Borne). Latitude: 21°05'13.119""S, longitude: 55°29'09.193""E (of Greenwich).",1947-01-01,7022,8901,3337,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGR92 (datum code 6627).",IGN Paris.,OGP,"2008/06/24",2004.561 2008.045,0,"D_Reunion_1947"
+6627,Reseau Geodesique de la Reunion 1992,geodetic,ITRF91 at epoch 1993.0,1993-01-01,7019,8901,3902,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Piton des Neiges (code 6626).",IGN Paris.,IOGP,"2016/09/16",2006.770 2011.109 2016.020,0,"D_RGR_1992"
+6628,Tahiti 52,geodetic,"Fundamental point: Tahiti North Base. Latitude: 17°38'10.0""S, longitude: 149°36'57.8""W (of Greenwich).",1952-01-01,7022,8901,2811,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by Tahiti 79 (datum code 6690) in Tahiti and Moorea 87 (code 6691) in Moorea.","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2005.380 2008.045,0,"D_Tahiti_1952"
+6629,Tahaa 54,geodetic,"Fundamental point: Tahaa East Base. Latitude: 16°33'20.97""S, longitude: 151°29'06.25""W (of Greenwich).",1954-01-01,7022,8901,2812,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2005.380 2008.045,0,"D_Tahaa_1954"
+6630,IGN72 Nuku Hiva,geodetic,"Fundamental point: Taiohae. Latitude: 8°55'03.97""S, longitude: 140°05'36.24""W (of Greenwich).",1972-01-01,7022,8901,3129,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2005.380 2008.045,0,"D_IGN72_Nuku_Hiva"
+6631,K0 1949,geodetic,,1949-01-01,7022,8901,2816,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,IGN Paris.,OGP,"2002/11/29",,1,
+6632,Combani 1950,geodetic,Combani South Base.,1950-01-01,7022,8901,3340,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGM04 and Cadastre 1997 (datum codes 1036-37).",IGN Paris.,OGP,"2009/10/29",2009.072,0,"D_Combani_1950"
+6633,IGN56 Lifou,geodetic,South end of the Goume base.,1956-01-01,7022,8901,2814,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_IGN56_Lifou"
+6634,IGN72 Grande Terre,geodetic,North end of Gomen base.,1972-01-01,7022,8901,2822,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_IGN72_Grande_Terre"
+6635,ST87 Ouvea,geodetic,,1987-01-01,7022,8901,2813,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Service Topographique de la Nouvelle Caledonie.,OGP,"2002/11/29",,1,
+6636,Petrels 1972,geodetic,"Fundamental point: Astro station DZ on Ile de Petrels. Latitude: 66°40'00""S, longitude: 140°00'46""E (of Greenwich).",1972-01-01,7022,8901,2817,"Geodetic survey,  topographic mapping.",,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Petrels_1972"
+6637,Pointe Geologie Perroud 1950,geodetic,"Fundamental point: Astro station G.0 on Pointe Geologie. Latitude: 66°39'30""S, longitude: 140°01'00""E (of Greenwich).",1950-01-01,7022,8901,2818,"Geodetic survey,  topographic mapping.",,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Pointe_Geologie_Perroud_1950"
+6638,Saint Pierre et Miquelon 1950,geodetic,,1950-01-01,7008,8901,3299,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RGSPM06 (datum code 1038).",IGN Paris.,OGP,"2011/01/25",2006.060 2009.072 2011.004,0,"D_Saint_Pierre_et_Miquelon_1950"
+6639,MOP78,geodetic,,1978-01-01,7022,8901,2815,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,IGN Paris.,OGP,"2002/11/29",,0,"D_MOP78"
+6640,Reseau de Reference des Antilles Francaises 1991,geodetic,WGS 84 coordinates of a single station determined during the 1988 Tango mission.,1991-01-01,7030,8901,2824,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Fort Marigot and Sainte Anne (datum codes 6621-22) in Guadeloupe and Fort Desaix (datum code 6625) in Martinique.",IGN Paris.,OGP,"2004/03/26",2004.200 2009.073,1,
+6641,IGN53 Mare,geodetic,South-east end of the La Roche base.,1953-01-01,7022,8901,2819,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_IGN53_Mare"
+6642,ST84 Ile des Pins,geodetic,"Fundamental point: Pic Nga.",1984-01-01,7022,8901,2820,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_ST84_Ile_des_Pins"
+6643,ST71 Belep,geodetic,,1971-01-01,7022,8901,2821,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Service Topographique de la Nouvelle Caledonie.,OGP,"2002/11/29",,0,"D_ST71_Belep"
+6644,NEA74 Noumea,geodetic,Noumea old signal station.,1974-01-01,7022,8901,2823,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",2006.620,0,"D_NEA74_Noumea"
+6645,Reseau Geodesique Nouvelle Caledonie 1991,geodetic,ITRF90 at epoch 1989.0,1989-01-01,7022,8901,1174,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Service Topographique de la Nouvelle Caledonie.,OGP,"2002/11/29",,1,"D_RGNC_1991"
 6646,Grand Comoros,geodetic,"Fundamental point: M'Tsaoueni.  Latitude: 11°28'32.200""S, longitude: 43°15'42.315""E (of Greenwich).",,7022,8901,2807,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,IGN Paris.,OGP,"2008/06/24",2008.045,0,"D_Grand_Comoros"
-6647,International Terrestrial Reference Frame 1988,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1988.0. Replaced by ITRF89 (code 6648).","International Earth Rotation Service (IERS) Annual Report for 1988. Also IGN Paris http://lareg.ensg.ign.fr/ITRF",OGP,"2006/10/13",2 [...]
-6648,International Terrestrial Reference Frame 1989,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from April 1991. Replaces ITRF88 (code 6647). Replaced by ITRF90 (code 6649).","International Earth Rotation Service (IERS) Technical Note No. 6, April 1991. Also IGN [...]
-6649,International Terrestrial Reference Frame 1990,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from December 1991. Replaces ITRF89 (code 6648). Replaced by ITRF91 (code 6650).","International Earth Rotation Service (IERS) Technical Note No. 9, December 1991. Al [...]
-6650,International Terrestrial Reference Frame 1991,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from October 1992. Replaces ITRF90 (code 6649). Replaced by ITRF92 (code 6651).","International Earth Rotation Service (IERS) Technical Note No. 12, October 1992. Als [...]
-6651,International Terrestrial Reference Frame 1992,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 287 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from October 1993. Replaces ITRF91 (code 6650). Replaced by ITRF93 (code 6652).","International Earth Rotation Service (IERS) Technical Note No. 15, October 1993. [...]
-6652,International Terrestrial Reference Frame 1993,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1993.0.",1993,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from October 1994. Replaces ITRF92 (code 6651). Replaced by ITRF94 (code 6653).","International Earth Rotation Service (IERS) Technical Note No. 18, October 1994. Als [...]
-6653,International Terrestrial Reference Frame 1994,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1993.0.",1993,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from March 1996. Replaces ITRF93 (code 6652). Replaced by ITRF96 (code 6654).","International Earth Rotation Service (IERS) Technical Note No. 20, March 1996. Also IG [...]
-6654,International Terrestrial Reference Frame 1996,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1997.0.",1997,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from May 1998. Replaces ITRF94 (code 6653). Replaced by ITRF97 (code 6655).","International Earth Rotation Service (IERS) Technical Note No. 24, May 1998. Also IGN Pa [...]
-6655,International Terrestrial Reference Frame 1997,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1997.0.",1997,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from May 1999. Replaces ITRF96 (code 6654). Replaced by ITRF2000 (code 6656).","International Earth Rotation Service (IERS) Technical Note No. 27, May 1999. Also IGN  [...]
-6656,International Terrestrial Reference Frame 2000,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1997.0.",1997,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from 2004. Replaces ITRF97 (code 6655). Replaced by ITRF2005 (code 6896).","International Earth Rotation Service (IERS) Technical Note No. 31, published in 2004. Also [...]
-6657,Reykjavik 1900,geodetic,"Fundamental point:  Latitude: 64°08'31.88""N, longitude: 21°55'51.15""W (of Greenwich).",1900,7051,8901,3262,Medium scale topographic mapping.,,"Landmaelingar Islands (National Survey of Iceland).",OGP,"2008/06/24",2008.045,0,"D_Reykjavik_1900"
-6658,Hjorsey 1955,geodetic,"Fundamental point:  Latitude: 64°31'29.26""N, longitude: 22°22'05.84""W (of Greenwich).",1955,7022,8901,3262,"1/50,000 scale topographic mapping.",,"Landmaelingar Islands (National Survey of Iceland).",OGP,"2008/06/24",2008.045,0,"D_Hjorsey_1955"
-6659,Islands Net 1993,geodetic,ITRF93 at epoch 1993.6.,1996,7019,8901,1120,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by ISN2004 (datum code 1060).","Landmaelingar Islands (National Survey of Iceland).",OGP,"2010/11/12",2006.770 2010.101,0,"D_Islands_Network_1993"
-6660,Helle 1954,geodetic,,1954,7022,8901,2869,"Geodetic survey, topographic mapping..",,Statens kartverk.,OGP,"2003/06/27",,0,"D_Helle_1954"
-6661,Latvia 1992,geodetic,Constrained to 4 ETRS89 points in Latvia from the EUREF Baltic 1992 campaign.,1992,7019,8901,1139,"Topographic mapping, geodetic survey.",Densification of ETRS89 during the 1992 Baltic campaign.,"Latvijas Republikas Valsts zemes dienests (State Land Service of the Republic of Latvia) via EuroGeographics. http://crs.bkg.bund.de/crs-eu/",OGP,"2003/06/27",,0,"D_Latvia_1992"
-6663,Porto Santo 1995,geodetic,SE Base on Porto Santo island. Origin and orientation constrained to those of the 1936 adjustment.,1995,7022,8901,1314,Topographic mapping.,"Classical and GPS observations. Replaces 1936 adjustment (datum code 6615). 
+6647,International Terrestrial Reference Frame 1988,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS).",1988-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) at epoch 1988.0. Replaced by ITRF89 (code 6648).","International Earth Rotation Service (IERS) Annual Report for 1988. Also IGN Paris http://lareg.ensg.ign.fr/ITRF",OGP,"2006/10 [...]
+6648,International Terrestrial Reference Frame 1989,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from April 1991. Replaces ITRF88 (code 6647). Replaced by ITRF90 (code 6649).","International Earth Rotation Service (IERS) Technical Note No. 6, April 1991. Al [...]
+6649,International Terrestrial Reference Frame 1990,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from December 1991. Replaces ITRF89 (code 6648). Replaced by ITRF91 (code 6650).","International Earth Rotation Service (IERS) Technical Note No. 9, December 19 [...]
+6650,International Terrestrial Reference Frame 1991,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from October 1992. Replaces ITRF90 (code 6649). Replaced by ITRF92 (code 6651).","International Earth Rotation Service (IERS) Technical Note No. 12, October 199 [...]
+6651,International Terrestrial Reference Frame 1992,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 287 3-dimensional Cartesian station coordinates (SCS) for epoch 1988.0.",1988-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from October 1993. Replaces ITRF91 (code 6650). Replaced by ITRF93 (code 6652).","International Earth Rotation Service (IERS) Technical Note No. 15, October [...]
+6652,International Terrestrial Reference Frame 1993,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1993.0.",1993-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from October 1994. Replaces ITRF92 (code 6651). Replaced by ITRF94 (code 6653).","International Earth Rotation Service (IERS) Technical Note No. 18, October 199 [...]
+6653,International Terrestrial Reference Frame 1994,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1993.0.",1993-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from March 1996. Replaces ITRF93 (code 6652). Replaced by ITRF96 (code 6654).","International Earth Rotation Service (IERS) Technical Note No. 20, March 1996. A [...]
+6654,International Terrestrial Reference Frame 1996,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1997.0.",1997-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from May 1998. Replaces ITRF94 (code 6653). Replaced by ITRF97 (code 6655).","International Earth Rotation Service (IERS) Technical Note No. 24, May 1998. Also  [...]
+6655,International Terrestrial Reference Frame 1997,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1997.0.",1997-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from May 1999. Replaces ITRF96 (code 6654). Replaced by ITRF2000 (code 6656).","International Earth Rotation Service (IERS) Technical Note No. 27, May 1999. Als [...]
+6656,International Terrestrial Reference Frame 2000,geodetic,"Origin at geocentre, orientated to the BIH Terrestrial System at epoch 1984.0. Datum defined by a set of 3-dimensional Cartesian station coordinates (SCS) for epoch 1997.0.",1997-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from 2004. Replaces ITRF97 (code 6655). Replaced by ITRF2005 (code 6896).","International Earth Rotation Service (IERS) Technical Note No. 31, published in 2004 [...]
+6657,Reykjavik 1900,geodetic,"Fundamental point:  Latitude: 64°08'31.88""N, longitude: 21°55'51.15""W (of Greenwich).",1900-01-01,7051,8901,3262,Medium scale topographic mapping.,,"Landmaelingar Islands (National Survey of Iceland).",OGP,"2008/06/24",2008.045,0,"D_Reykjavik_1900"
+6658,Hjorsey 1955,geodetic,"Fundamental point:  Latitude: 64°31'29.26""N, longitude: 22°22'05.84""W (of Greenwich).",1955-01-01,7022,8901,3262,"1/50,000 scale topographic mapping.",,"Landmaelingar Islands (National Survey of Iceland).",OGP,"2008/06/24",2008.045,0,"D_Hjorsey_1955"
+6659,Islands Net 1993,geodetic,ITRF93 at epoch 1993.6.,1993-08-07,7019,8901,1120,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by ISN2004 (datum code 1060).","Landmaelingar Islands (National Survey of Iceland).",IOGP,"2016/09/16",2006.770 2010.101 2016.020,0,"D_Islands_Network_1993"
+6660,Helle 1954,geodetic,,1954-01-01,7022,8901,2869,"Geodetic survey, topographic mapping..",,Statens kartverk.,OGP,"2003/06/27",,0,"D_Helle_1954"
+6661,Latvia 1992,geodetic,Constrained to 4 ETRS89 points in Latvia from the EUREF Baltic 1992 campaign.,1992-10-01,7019,8901,1139,"Topographic mapping, geodetic survey.",Densification of ETRS89 during the 1992 Baltic campaign.,"Latvijas Republikas Valsts zemes dienests (State Land Service of the Republic of Latvia) via EuroGeographics. http://crs.bkg.bund.de/crs-eu/",IOGP,"2016/09/16",2016.020,0,"D_Latvia_1992"
+6663,Porto Santo 1995,geodetic,SE Base on Porto Santo island. Origin and orientation constrained to those of the 1936 adjustment.,1995-01-01,7022,8901,1314,Topographic mapping.,"Classical and GPS observations. Replaces 1936 adjustment (datum code 6615). 
 For Selvagens see Selvagem Grande (datum code 6616).","Instituto Geografico e Cadastral Lisbon; http://www.igeo.pt/",OGP,"2005/09/06",2005.460,0,"D_Porto_Santo_1995"
-6664,Azores Oriental Islands 1995,geodetic,"Fundamental point: Forte de São Bras. Origin and orientation constrained to those of the 1940 adjustment.",1940,7022,8901,1345,Topographic mapping.,"Classical and GPS observations. Replaces 1940 adjustment (datum code 6184).","Instituto Geografico e Cadastral Lisbon; http://www.igeo.pt/",OGP,"2005/09/06",2005.460,0,"D_Azores_Oriental_Islands_1995"
-6665,Azores Central Islands 1995,geodetic,"Fundamental point: Graciosa south west base. Origin and orientation constrained to those of the 1948 adjustment.",1948,7022,8901,1301,Topographic mapping.,"Classical and GPS observations. Replaces 1948 adjustment (datum code 6183).","Instituto Geografico e Cadastral Lisbon; http://www.igeo.pt/",OGP,"2005/09/06",2005.460,0,"D_Azores_Central_Islands_1995"
-6666,Lisbon 1890,geodetic,"Fundamental point: Castelo Sao Jorge, Lisbon. Latitude: 38°42'43.631""N, longitude: 9°07'54.862""W of Greenwich.",1937,7004,8901,1294,Topographic mapping.,"Replaced by Lisbon 1937 adjustment (which uses International 1924 ellipsoid).","Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2008/06/24",2003.361 2008.045,0,"D_Lisbon_1890"
-6667,Iraq-Kuwait Boundary Datum 1992,geodetic,Four stations established between September and December 1991 determined by GPS and Doppler observations.,1992,7030,8901,2876,International boundary demarcation,,"United Nations Iraq-Kuwait Boundary Demarcation Commission, Final Report, May 1993.",OGP,"2003/09/01",,0,"D_Iraq_Kuwait_Boundary_1992"
-6668,European Datum 1979,geodetic,"Fundamental point: Potsdam (Helmert Tower). Latitude: 52°22'51.4456""N, longitude: 13°03'58.9283""E (of Greenwich).",1979,7022,8901,1297,Scientific network.,Replaced by 1987 adjustment.,,OGP,"2008/06/24",2008.045,0,"D_European_1979"
-6670,Istituto Geografico Militaire 1995,geodetic,Network of 1296 points observed 1992-1995 and adjusted in 1996 constrained to 9 ETRS89 points. Densification of ETRS89 in Italy.,1995,7030,8901,3343,Geodetic survey and scientific study.,"Replaced by RDN2008 (datum code 1132) from 2011-11-10.",ENI,OGP,"2014/01/27",2011.004 2014.002,0,"D_IGM_1995"
-6671,Voirol 1879,geodetic,"Fundamental point: Voirol. Latitude: 36°45'08.199""N, longitude: 3°02'49.435""E (of Greenwich). Uses RGS (and old IGN) value of 2°20'13.95""for Greenwich-Paris meridian difference.",1879,7011,8901,1365,Topographic mapping.,"Replaces Voirol 1875 (code 6304).",IGN Paris,OGP,"2008/06/24",2008.045,0,"D_Voirol_1879"
-6672,Chatham Islands Datum 1971,geodetic,,1971,7022,8901,2889,"Geodetic survey, topographic mapping, engineering survey.","Replaced by Chatham Islands Datum 1979 (code 6673).","Office of Surveyor General (OSG) Technical Report 14, June 2001.",OGP,"2004/02/17",,0,"D_Chatham_Island_1971"
-6673,Chatham Islands Datum 1979,geodetic,"Fundamental point: station Astro. Latitude: 43°57'23.60""S, longitude: 176°34'28.65""W (of Greenwich).",1979,7022,8901,2889,"Geodetic survey, topographic mapping, engineering survey.","Replaces Chatham Islands Datum 1971 (code 6672). Replaced by New Zealand Geodetic Datum 2000 (code 6167) from March 2000.","Office of Surveyor General (OSG) Technical Report 14, June 2001.",OGP,"2008/06/24",2008.045,0,"D_Chatham_Islands_1979"
-6674,Sistema de Referencia Geocentrico para las AmericaS 2000,geodetic,ITRF2000 at epoch 2000.40.,2000,7019,8901,3418,Geodetic survey.,"Realised by a frame of 184 stations observed in 2000 and adjusted in the ITRF2000. Includes ties to tide gauges. Replaces SIRGAS 1995 system for South America; expands SIRGAS to Central America.  Name changed in 2001 for use in all of Latin America.","IBGE Brazil,  http://www1.ibge.gov.br/",OGP,"2011/07/27",2005.460 2005.830 2006.465 2006.770 2009.087 20 [...]
-6675,Guam 1963,geodetic,"Fundamental point: Tagcha. Latitude: 13°22'38.49""N, longitude: 144°45'51.56""E (of Greenwich).",1963,7008,8901,3255,Topographic mapping.,"Replaced by NAD83(HARN)","US National Geospatial Intelligence Agency (NGA). http://earth-info.nga.mil/",OGP,"2008/06/24",2005.460 2008.045,0,"D_Guam_1963"
-6676,Vientiane 1982,geodetic,"Fundamental point: Vientiane (Nongteng) Astro Pillar. Latitude: 18°01'31.6301""N, longitude: 102°30'56.6999""E (of Greenwich).",1982,7024,8901,1138,Topographic mapping.,Replaced by Lao 1993.,National Geographic Department,OGP,"2008/06/24",2008.045,0,"D_Vientiane_1982"
-6677,Lao 1993,geodetic,"Fundamental point: Lao 1982 coordinates of Pakxa pillar. Latitude: 18°23'57.0056""N, longitude: 103°38'41.8020""E (of Greenwich). Orientation parallel with WGS 84.",1993,7024,8901,1138,Topographic mapping.,Replaces Vientiane 1982. Replaced by Lao 1997,National Geographic Department,OGP,"2008/06/24",2008.045,0,"D_Lao_1993"
-6678,Lao National Datum 1997,geodetic,"Fundamental point: Vientiane (Nongteng) Astro Pillar. Latitude: 18°01'31.3480""N, longitude: 102°30'57.1376""E (of Greenwich).",1997,7024,8901,1138,"Cadastre, topographic mapping, engineering survey.",Replaces Lao 1993.,National Geographic Department,OGP,"2008/06/24",2008.045,0,"D_Lao_National_Datum_1997"
-6679,Jouik 1961,geodetic,,1961,7012,8901,2967,Hydrographic charting.,"Replaced by Mauritania 1999 (datum code 6702).",Woodside,OGP,"2006/06/12",2006.440,0,"D_Jouik_1961"
-6680,Nouakchott 1965,geodetic,Nouakchott astronomical point.,1965,7012,8901,2968,Topographic survey.,"Triangulation limited to environs of Nouakchott. Extended in 1982 by satellite translocation from a single station ""Ruines"" to support Syledis chain for offshore operations. Replaced by Mauritania 1999 (datum code 6602).",IGN Paris and various industry sources.,OGP,"2006/06/12",2006.440,0,"D_Nouakchott_1965"
-6681,Mauritania 1999,geodetic,,1999,7012,8901,1157,"Minerals management, topographic mapping.","A network of 36 GPS stations tied to ITRF96, 8 of which are IGN astronomic points.",Woodside,OGP,"2004/10/14",,1,"D_Mauritania_1999"
-6682,Gulshan 303,geodetic,"Gulshan garden, Dhaka.",1995,7015,8901,1041,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Network of more than 140 control points observed and adjusted in 1995 by Japan International Cooperation Agency (JICA).",Survey of Bangladesh via IGN Paris and Tullow Oil.,OGP,"2006/06/22",2006.470,0,"D_Gulshan_303"
-6683,Philippine Reference System 1992,geodetic,"Fundamental point: Balacan. Latitude: 13°33'41.000""N, longitude: 121°52'03.000""E (of Greenwich), geoid-ellipsoid separation 0.34m.",1992,7008,8901,1190,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Luzon 1911 datum (code 6253).","National Mapping and Resource Information Authority, Coast and Geodetic Survey Department.",OGP,"2008/06/24",2008.045,0,"D_Philippine_Reference_System_1992"
-6684,Gan 1970,geodetic,,1970,7022,8901,3274,Topographic mapping.,"In some references incorrectly named ""Gandajika 1970"". See datum code 6685.",Various industry sources.,OGP,"2005/04/14",,0,"D_Gan_1970"
-6685,Gandajika,geodetic,Gandajika base.,1953,7022,8901,1259,Topographic mapping.,In some references incorrectly attributed to the Maldives. See datum code 6684.,Various industry sources.,OGP,"2005/04/14",,1,
-6686,Marco Geocentrico Nacional de Referencia,geodetic,"ITRF94 at epoch 1995.4.  Bogota observatory coordinates: Latitude: 4°35'46.3215""N, longitude: 74°04'39.0285""W (of Greenwich).",2004,7019,8901,1070,Geodetic survey.,"Densification of SIRGAS 1995 within Colombia. Replaces Bogota 1975 (datum code 6218).","Instituto Geografico Agustin Codazzi (IGAC) publication ""Aspectos prácticos de la adopción del Marco Geocéntrico Nacional de Referencia MAGNA-SIRGAS como datum oficial de Colombia" [...]
-6687,Reseau Geodesique de la Polynesie Francaise,geodetic,"ITRF92 at epoch 1993.0. Densification by GPS of the Reference Network of French Polynesia, a coordinate set of 13 stations determined through DORIS observations.",1993,7019,8901,1098,Geodetic survey.,"Replaces Tahaa 54 (datum code 6629), IGN 63 Hiva Oa (6689), IGN 72 Nuku Hiva (6630), Maupiti 83 (6692), MHEFO 55 (6688), Moorea 87 (6691) and Tahiti 79 (6690).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Secti [...]
-6688,Fatu Iva 72,geodetic,"Fundamental point: Latitude: 9°25'58.00""S, longitude: 138°55'06.25""W (of Greenwich).",1972,7022,8901,3133,Hydrographic and topographic survey.,"Recomputed by IGN in 1972 using origin and observations of 1953-1955 Mission Hydrographique des Establissements Francais d'Oceanie (MHEFO 55). Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_Fatu_Iva_1972"
-6689,IGN63 Hiva Oa,geodetic,"Fundamental point: Atuona. Latitude: 9°48'27.20""S, longitude: 139°02'15.45""W (of Greenwich).",1963,7022,8901,3130,Hydrographic and topographic survey.,"Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_IGN63_Hiva_Oa"
-6690,Tahiti 79,geodetic,"Fundamental point: Tahiti North Base. Latitude: 17°38'10.0""S, longitude: 149°36'57.8""W (of Greenwich).",1979,7022,8901,3124,Hydrographic and topographic survey.,"Replaces Tahiti 52 (datum code 6628) in Tahiti. Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_Tahiti_1979"
-6691,Moorea 87,geodetic,Two stations on Tahiti whose coordinates from the Tahiti 1979 adjustment were held fixed.,1987,7022,8901,3125,Hydrographic and topographic survey.,"Replaces Tahiti 52 (datum code 6628) in Moorea. Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,"D_Moorea_1987"
-6692,Maupiti 83,geodetic,"Fundamental point: Pitiahe South Base. Latitude: 16°28'28.942""S, longitude: 152°14'55.059""W (of Greenwich).",1983,7022,8901,3126,Hydrographic and topographic survey.,"Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_Maupiti_1983"
-6693,Nakhl-e Ghanem,geodetic,"Coordinates of two stations determined with respect to ITRF 2000 at epoch 2005.2: BMT1 latitude 27°42'09.8417""N, longitude 52°12'11.0362""E (of Greenwich); Total1 latitude 27°31'03.8896""N, longitude 52°36'13.1312""E (of Greenwich).",2005,7030,8901,2362,Engineering survey for onshore facilities for South Pars phase 11 and Pars LNG.,,Total,OGP,"2008/06/24",2006.770 2008.045,0,"D_Nakhl-e_Ghanem"
-6694,Posiciones Geodesicas Argentinas 1994,geodetic,"A geodetic network of 127 high accuracy surveyed points based on WGS 84 that define the National Geodetic System (Sistema Geodésico Nacional).",1994,7030,8901,1033,"Topographic mapping, geodetic survey.","Technically, but not legally, replaced by POSGAR 98 (code 6190) until May 2009, when POSGAR 2007 was officially accepted and officially replaced POSGAR 94.","Instituto Geográfico Militar de la República Argentina, http://www.igm.gov.a [...]
-6695,Katanga 1955,geodetic,"Fundamental point: Tshinsenda A. Latitude: 12°30'31.568""S, longitude: 28°01'02.971""E (of Greenwich).",1955,7008,8901,3147,"Cadastre, topographic mapping, engineering survey.",Replaces earlier adjustments.,"Clifford J. Mugnier, in Photogrammetric Engineering and Remote Sensing, June 2005.",OGP,"2009/06/02",2008.045 2009.011,0,"D_Katanga_1955"
-6696,Kasai 1953,geodetic,"Two stations of the Katanga triangulation with ellipsoid change applied: Kabila, latitude 6°58'34.023""S, longitude 23°50'24.028""E (of Greenwich); and Gandajika NW base, latitude 6°45'01.057""S, longitude 23°57'03.038""E (of Greenwich).",1955,7012,8901,3148,"Cadastre, topographic mapping, engineering survey.",Replaced by IGC 1962 Arc of the 6th Parallel South.,Institute Geographique du Congo,OGP,"2008/06/24",2008.045,0,"D_Kasai_1953"
-6697,IGC 1962 Arc of the 6th Parallel South,geodetic,"Coordinates of 3 stations determined with respect to Arc 1950: Mulungu 4°47'39.2325""S, 29°59'37.5864""E; Nyakawembe 4°14'57.3618""S, 29°42'52.8032""E; Kavula 4°35'15.8634""S, 29°41'14.2693""E (all longitude w.r.t. Greenwich).",1962,7012,8901,3149,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Institute Geographique du Congo,OGP,"2008/06/24",2006.721 2008.045,0,"D_IGC_1962_Arc_of_the_6th_Parallel_South"
-6698,IGN 1962 Kerguelen,geodetic,K0 1949.,1949,7022,8901,2816,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,IGN Paris.,OGP,"2005/11/23",,0,"D_Kerguelen_Island_1949"
-6699,Le Pouce 1934,geodetic,"Fundamental point: Le Pouce. Latitude: 20°11'42.25""S, longitude: 57°31'18.58""E (of Greenwich).",1934,7012,8901,3209,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Cartography Section, Ministry of Housing and Land.",OGP,"2008/06/24",2008.045,0,"D_Le_Pouce_1934"
-6700,IGN Astro 1960,geodetic,Realised through a set of independent astronomically-positioned points.,1960,7012,8901,3277,Small scale topographic mapping.,"Observed during 1959-1960. Independent points not connected through a network. Relative accuracy estimated at 50-100m. Replaced by Mauritania 1999 (datum code 6702).","Ministry of Works and Transport, Topography and Cartography Directive.",OGP,"2012/01/05",2006.440 2012.001,0,"D_IGN_Astro_1960"
-6701,Institut Geographique du Congo Belge 1955,geodetic,"Fundamental point: Yella east base. Latitude: 6°00'53.139""S, longitude: 12°58'29.287""E (of Greenwich).",1955,7012,8901,3171,"Cadastre, topographic mapping, engineering survey.","Replaced by IGC 1962 Arc of the 6th Parallel South, except for oil industry activities.",Institut Geographique du Congo Belge.,OGP,"2008/06/24",2008.045,0,"D_Institut_Geographique_du_Congo_Belge_1955"
-6702,Mauritania 1999,geodetic,ITRF96 at epoch 1997.0,1999,7019,8901,1157,Geodesy.,"A network of 36 GPS stations tied to ITRF96, 8 of which are IGN 1962 astronomic points.","Ministry of Works and Transport, Topography and Cartography Directive.",OGP,"2006/08/18",2006.770,0,"D_Mauritania_1999"
-6703,Missao Hidrografico Angola y Sao Tome 1951,geodetic,Extension of Camacupa datum into Cabinda.,1951,7012,8901,1318,Coastal hydrography.,"A variation of this datum has been adopted by the oil industry but incorrectly using the International 1924 ellipsoid and not tied to the official Portuguese triangulation - see Mhast (onshore) and Mhast (offshore) (codes 6704 and 6705).",Various industry sources.,OGP,"2006/01/03",,0,"D_Mhast_1951"
+6664,Azores Oriental Islands 1995,geodetic,"Fundamental point: Forte de São Bras. Origin and orientation constrained to those of the 1940 adjustment.",1995-01-01,7022,8901,1345,Topographic mapping.,"Classical and GPS observations. Replaces 1940 adjustment (datum code 6184).","Instituto Geografico e Cadastral Lisbon; http://www.igeo.pt/",IOGP,"2016/09/16",2005.460 2016.020,0,"D_Azores_Oriental_Islands_1995"
+6665,Azores Central Islands 1995,geodetic,"Fundamental point: Graciosa south west base. Origin and orientation constrained to those of the 1948 adjustment.",1995-01-01,7022,8901,1301,Topographic mapping.,"Classical and GPS observations. Replaces 1948 adjustment (datum code 6183).","Instituto Geografico e Cadastral Lisbon; http://www.igeo.pt/",IOGP,"2016/09/16",2005.460 2016.020,0,"D_Azores_Central_Islands_1995"
+6666,Lisbon 1890,geodetic,"Fundamental point: Castelo Sao Jorge, Lisbon. Latitude: 38°42'43.631""N, longitude: 9°07'54.862""W of Greenwich.",1937-01-01,7004,8901,1294,Topographic mapping.,"Replaced by Lisbon 1937 adjustment (which uses International 1924 ellipsoid).","Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2008/06/24",2003.361 2008.045,0,"D_Lisbon_1890"
+6667,Iraq-Kuwait Boundary Datum 1992,geodetic,Four stations established between September and December 1991 determined by GPS and Doppler observations.,1992-01-01,7030,8901,2876,International boundary demarcation,,"United Nations Iraq-Kuwait Boundary Demarcation Commission, Final Report, May 1993.",OGP,"2003/09/01",,0,"D_Iraq_Kuwait_Boundary_1992"
+6668,European Datum 1979,geodetic,"Fundamental point: Potsdam (Helmert Tower). Latitude: 52°22'51.4456""N, longitude: 13°03'58.9283""E (of Greenwich).",1979-01-01,7022,8901,1297,Scientific network.,Replaced by 1987 adjustment.,,OGP,"2008/06/24",2008.045,0,"D_European_1979"
+6670,Istituto Geografico Militaire 1995,geodetic,Network of 1296 points observed 1992-1995 and adjusted in 1996 constrained to 9 ETRS89 points. Densification of ETRS89 in Italy.,1995-01-01,7030,8901,3343,Geodetic survey and scientific study.,"Replaced by RDN2008 (datum code 1132) from 2011-11-10.",ENI,OGP,"2014/01/27",2011.004 2014.002,0,"D_IGM_1995"
+6671,Voirol 1879,geodetic,"Fundamental point: Voirol. Latitude: 36°45'08.199""N, longitude: 3°02'49.435""E (of Greenwich). Uses RGS (and old IGN) value of 2°20'13.95""for Greenwich-Paris meridian difference.",1879-01-01,7011,8901,1365,Topographic mapping.,"Replaces Voirol 1875 (code 6304).",IGN Paris,OGP,"2008/06/24",2008.045,0,"D_Voirol_1879"
+6672,Chatham Islands Datum 1971,geodetic,,1971-01-01,7022,8901,2889,"Geodetic survey, topographic mapping, engineering survey.","Replaced by Chatham Islands Datum 1979 (code 6673).","Office of Surveyor General (OSG) Technical Report 14, June 2001.",OGP,"2004/02/17",,0,"D_Chatham_Island_1971"
+6673,Chatham Islands Datum 1979,geodetic,"Fundamental point: station Astro. Latitude: 43°57'23.60""S, longitude: 176°34'28.65""W (of Greenwich).",1979-01-01,7022,8901,2889,"Geodetic survey, topographic mapping, engineering survey.","Replaces Chatham Islands Datum 1971 (code 6672). Replaced by New Zealand Geodetic Datum 2000 (code 6167) from March 2000.","Office of Surveyor General (OSG) Technical Report 14, June 2001.",OGP,"2008/06/24",2008.045,0,"D_Chatham_Islands_1979"
+6674,Sistema de Referencia Geocentrico para las AmericaS 2000,geodetic,ITRF2000 at epoch 2000.40.,2000-05-26,7019,8901,3418,Geodetic survey.,"Realised by a frame of 184 stations observed in 2000 and adjusted in the ITRF2000. Includes ties to tide gauges. Replaces SIRGAS 1995 system for South America; expands SIRGAS to Central America.  Name changed in 2001 for use in all of Latin America.","IBGE Brazil,  http://www1.ibge.gov.br/",IOGP,"2016/09/16",2005.460 2005.830 2006.465 2006.770 2009 [...]
+6675,Guam 1963,geodetic,"Fundamental point: Tagcha. Latitude: 13°22'38.49""N, longitude: 144°45'51.56""E (of Greenwich).",1963-01-01,7008,8901,3255,Topographic mapping.,"Replaced by NAD83(HARN)","US National Geospatial Intelligence Agency (NGA). http://earth-info.nga.mil/",OGP,"2008/06/24",2005.460 2008.045,0,"D_Guam_1963"
+6676,Vientiane 1982,geodetic,"Fundamental point: Vientiane (Nongteng) Astro Pillar. Latitude: 18°01'31.6301""N, longitude: 102°30'56.6999""E (of Greenwich).",1982-01-01,7024,8901,1138,Topographic mapping.,Replaced by Lao 1993.,National Geographic Department,OGP,"2008/06/24",2008.045,0,"D_Vientiane_1982"
+6677,Lao 1993,geodetic,"Fundamental point: Lao 1982 coordinates of Pakxa pillar. Latitude: 18°23'57.0056""N, longitude: 103°38'41.8020""E (of Greenwich). Orientation parallel with WGS 84.",1993-01-01,7024,8901,1138,Topographic mapping.,Replaces Vientiane 1982. Replaced by Lao 1997,National Geographic Department,OGP,"2008/06/24",2008.045,0,"D_Lao_1993"
+6678,Lao National Datum 1997,geodetic,"Fundamental point: Vientiane (Nongteng) Astro Pillar. Latitude: 18°01'31.3480""N, longitude: 102°30'57.1376""E (of Greenwich).",1997-01-01,7024,8901,1138,"Cadastre, topographic mapping, engineering survey.",Replaces Lao 1993.,National Geographic Department,OGP,"2008/06/24",2008.045,0,"D_Lao_National_Datum_1997"
+6679,Jouik 1961,geodetic,,1961-01-01,7012,8901,2967,Hydrographic charting.,"Replaced by Mauritania 1999 (datum code 6702).",Woodside,OGP,"2006/06/12",2006.440,0,"D_Jouik_1961"
+6680,Nouakchott 1965,geodetic,Nouakchott astronomical point.,1965-01-01,7012,8901,2968,Topographic survey.,"Triangulation limited to environs of Nouakchott. Extended in 1982 by satellite translocation from a single station ""Ruines"" to support Syledis chain for offshore operations. Replaced by Mauritania 1999 (datum code 6602).",IGN Paris and various industry sources.,OGP,"2006/06/12",2006.440,0,"D_Nouakchott_1965"
+6681,Mauritania 1999,geodetic,,1999-01-01,7012,8901,1157,"Minerals management, topographic mapping.","A network of 36 GPS stations tied to ITRF96, 8 of which are IGN astronomic points.",Woodside,OGP,"2004/10/14",,1,"D_Mauritania_1999"
+6682,Gulshan 303,geodetic,"Gulshan garden, Dhaka.",1995-01-01,7015,8901,1041,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Network of more than 140 control points observed and adjusted in 1995 by Japan International Cooperation Agency (JICA).",Survey of Bangladesh via IGN Paris and Tullow Oil.,OGP,"2006/06/22",2006.470,0,"D_Gulshan_303"
+6683,Philippine Reference System 1992,geodetic,"Fundamental point: Balacan. Latitude: 13°33'41.000""N, longitude: 121°52'03.000""E (of Greenwich), geoid-ellipsoid separation 0.34m.",1992-01-01,7008,8901,1190,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Luzon 1911 datum (code 6253).","National Mapping and Resource Information Authority, Coast and Geodetic Survey Department.",OGP,"2008/06/24",2008.045,0,"D_Philippine_Reference_System_1992"
+6684,Gan 1970,geodetic,,1970-01-01,7022,8901,3274,Topographic mapping.,"In some references incorrectly named ""Gandajika 1970"". See datum code 6685.",Various industry sources.,OGP,"2005/04/14",,0,"D_Gan_1970"
+6685,Gandajika,geodetic,Gandajika base.,1953-01-01,7022,8901,1259,Topographic mapping.,In some references incorrectly attributed to the Maldives. See datum code 6684.,Various industry sources.,OGP,"2005/04/14",,1,
+6686,Marco Geocentrico Nacional de Referencia,geodetic,"Documented as ITRF94 at epoch 1995.4 but possibly a rounded value as SIRGAS95 is at epoch 1995.42. Bogota observatory coordinates: Latitude: 4°35'46.3215""N, longitude: 74°04'39.0285""W (of Greenwich).",2004-06-02,7019,8901,1070,Geodetic survey.,"Densification of SIRGAS 1995 within Colombia. Replaces Bogota 1975 (datum code 6218).","Instituto Geografico Agustin Codazzi (IGAC) publication ""Aspectos prácticos de la adopción del Marco [...]
+6687,Reseau Geodesique de la Polynesie Francaise,geodetic,"ITRF92 at epoch 1993.0. Densification by GPS of the Reference Network of French Polynesia, a coordinate set of 13 stations determined through DORIS observations.",1993-01-01,7019,8901,1098,Geodetic survey.,"Replaces Tahaa 54 (datum code 6629), IGN 63 Hiva Oa (6689), IGN 72 Nuku Hiva (6630), Maupiti 83 (6692), MHEFO 55 (6688), Moorea 87 (6691) and Tahiti 79 (6690).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, [...]
+6688,Fatu Iva 72,geodetic,"Fundamental point: Latitude: 9°25'58.00""S, longitude: 138°55'06.25""W (of Greenwich).",1972-01-01,7022,8901,3133,Hydrographic and topographic survey.,"Recomputed by IGN in 1972 using origin and observations of 1953-1955 Mission Hydrographique des Establissements Francais d'Oceanie (MHEFO 55). Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_Fatu_Iva_1972"
+6689,IGN63 Hiva Oa,geodetic,"Fundamental point: Atuona. Latitude: 9°48'27.20""S, longitude: 139°02'15.45""W (of Greenwich).",1963-01-01,7022,8901,3130,Hydrographic and topographic survey.,"Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_IGN63_Hiva_Oa"
+6690,Tahiti 79,geodetic,"Fundamental point: Tahiti North Base. Latitude: 17°38'10.0""S, longitude: 149°36'57.8""W (of Greenwich).",1979-01-01,7022,8901,3124,Hydrographic and topographic survey.,"Replaces Tahiti 52 (datum code 6628) in Tahiti. Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_Tahiti_1979"
+6691,Moorea 87,geodetic,Two stations on Tahiti whose coordinates from the Tahiti 1979 adjustment were held fixed.,1987-01-01,7022,8901,3125,Hydrographic and topographic survey.,"Replaces Tahiti 52 (datum code 6628) in Moorea. Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2005/08/12",,0,"D_Moorea_1987"
+6692,Maupiti 83,geodetic,"Fundamental point: Pitiahe South Base. Latitude: 16°28'28.942""S, longitude: 152°14'55.059""W (of Greenwich).",1983-01-01,7022,8901,3126,Hydrographic and topographic survey.,"Replaced by RGPF (datum code 6687).","Gouvernement de la Polynésie Française, Service  de l'Urbanisme, Section topographie.",OGP,"2008/06/24",2008.045,0,"D_Maupiti_1983"
+6693,Nakhl-e Ghanem,geodetic,"Coordinates of two stations determined with respect to ITRF 2000 at epoch 2005.2: BMT1 latitude 27°42'09.8417""N, longitude 52°12'11.0362""E (of Greenwich); Total1 latitude 27°31'03.8896""N, longitude 52°36'13.1312""E (of Greenwich).",2005-01-01,7030,8901,2362,Engineering survey for onshore facilities for South Pars phase 11 and Pars LNG.,,Total,OGP,"2008/06/24",2006.770 2008.045,0,"D_Nakhl-e_Ghanem"
+6694,Posiciones Geodesicas Argentinas 1994,geodetic,"A geodetic network of 127 high accuracy surveyed points based on WGS 84 that define the National Geodetic System (Sistema Geodésico Nacional).",1994-01-01,7030,8901,1033,"Topographic mapping, geodetic survey.","Technically, but not legally, replaced by POSGAR 98 (code 6190) until May 2009, when POSGAR 2007 was officially accepted and officially replaced POSGAR 94.","Instituto Geográfico Militar de la República Argentina, http://www.igm [...]
+6695,Katanga 1955,geodetic,"Fundamental point: Tshinsenda A. Latitude: 12°30'31.568""S, longitude: 28°01'02.971""E (of Greenwich).",1955-01-01,7008,8901,3147,"Cadastre, topographic mapping, engineering survey.",Replaces earlier adjustments.,"Clifford J. Mugnier, in Photogrammetric Engineering and Remote Sensing, June 2005.",OGP,"2009/06/02",2008.045 2009.011,0,"D_Katanga_1955"
+6696,Kasai 1953,geodetic,"Two stations of the Katanga triangulation with ellipsoid change applied: Kabila, latitude 6°58'34.023""S, longitude 23°50'24.028""E (of Greenwich); and Gandajika NW base, latitude 6°45'01.057""S, longitude 23°57'03.038""E (of Greenwich).",1955-01-01,7012,8901,3148,"Cadastre, topographic mapping, engineering survey.",Replaced by IGC 1962 Arc of the 6th Parallel South.,Institute Geographique du Congo,OGP,"2008/06/24",2008.045,0,"D_Kasai_1953"
+6697,IGC 1962 Arc of the 6th Parallel South,geodetic,"Coordinates of 3 stations determined with respect to Arc 1950: Mulungu 4°47'39.2325""S, 29°59'37.5864""E; Nyakawembe 4°14'57.3618""S, 29°42'52.8032""E; Kavula 4°35'15.8634""S, 29°41'14.2693""E (all longitude w.r.t. Greenwich).",1962-01-01,7012,8901,3149,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,Institute Geographique du Congo,OGP,"2008/06/24",2006.721 2008.045,0,"D_IGC_1962_Arc_of_the_6th_Parallel_South"
+6698,IGN 1962 Kerguelen,geodetic,K0 1949.,1949-01-01,7022,8901,2816,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,IGN Paris.,OGP,"2005/11/23",,0,"D_Kerguelen_Island_1949"
+6699,Le Pouce 1934,geodetic,"Fundamental point: Le Pouce. Latitude: 20°11'42.25""S, longitude: 57°31'18.58""E (of Greenwich).",1934-01-01,7012,8901,3209,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Cartography Section, Ministry of Housing and Land.",OGP,"2008/06/24",2008.045,0,"D_Le_Pouce_1934"
+6700,IGN Astro 1960,geodetic,Realised through a set of independent astronomically-positioned points.,1960-01-01,7012,8901,3277,Small scale topographic mapping.,"Observed during 1959-1960. Independent points not connected through a network. Relative accuracy estimated at 50-100m. Replaced by Mauritania 1999 (datum code 6702).","Ministry of Works and Transport, Topography and Cartography Directive.",OGP,"2012/01/05",2006.440 2012.001,0,"D_IGN_Astro_1960"
+6701,Institut Geographique du Congo Belge 1955,geodetic,"Fundamental point: Yella east base. Latitude: 6°00'53.139""S, longitude: 12°58'29.287""E (of Greenwich).",1955-01-01,7012,8901,3171,"Cadastre, topographic mapping, engineering survey.","Replaced by IGC 1962 Arc of the 6th Parallel South, except for oil industry activities.",Institut Geographique du Congo Belge.,OGP,"2008/06/24",2008.045,0,"D_Institut_Geographique_du_Congo_Belge_1955"
+6702,Mauritania 1999,geodetic,ITRF96 at epoch 1997.0,1997-01-01,7019,8901,1157,Geodesy.,"A network of 36 GPS stations tied to ITRF96, 8 of which are IGN 1962 astronomic points.","Ministry of Works and Transport, Topography and Cartography Directive.",IOGP,"2016/09/16",2006.770 2016.020,0,"D_Mauritania_1999"
+6703,Missao Hidrografico Angola y Sao Tome 1951,geodetic,Extension of Camacupa datum into Cabinda.,1951-01-01,7012,8901,1318,Coastal hydrography.,"A variation of this datum has been adopted by the oil industry but incorrectly using the International 1924 ellipsoid and not tied to the official Portuguese triangulation - see Mhast (onshore) and Mhast (offshore) (codes 6704 and 6705).",Various industry sources.,OGP,"2006/01/03",,0,"D_Mhast_1951"
 6704,"Mhast (onshore)",geodetic,Probably adopted a Mhast 1951 coordinate set but associated an incorrect ellipsoid with it.,,7022,8901,3179,"Oil industry exploration and production. From 1979, offshore use superseded by Mhast (offshore) (code 6705).","Adopted by oil industry with intention of being Mhast 1951 (code 6703) but incorrectly (for Mhast 1951) used the International 1924 ellipsoid. This datum differs by about 400 metres from the Portuguese Mhast 1951 and Camacupa datums.",Chevr [...]
-6705,"Mhast (offshore)",geodetic,"Fundamental point: Station Y at Malongo base camp. Latitude: 5°23'30.810""S, longitude: 12°12'01.590""E (of Greenwich).",1979,7022,8901,3180,Oil industry offshore exploration and production between 1979 and 1987.,"Origin coordinates determined by Transit single point position using 32 passes and transformed from WGS72BE using transformation code 15790. Differs from Mhast (onshore) by approximately 10m. Replaced in 1987 by Malongo 1987 (code 6259).",Chevr [...]
-6706,Egypt Gulf of Suez S-650 TL,geodetic,"Fundamental point: Station S-650 DMX. Adopted coordinates: latitude: 28°19'02.1907""N, longitude: 33°06'36.6344""E (of Greenwich). The proper Egypt 1907 coordinates for S-650 differ from these by about 20m.",1980,7020,8901,2341,Oil industry offshore exploration and production in Gulf of Suez after 1980.,"A coherent set of stations bordering the Gulf of Suez coordinated by Transit translocation (""TL"") between 1980 and 1984. Based on incorrect E [...]
-6707,Tern Island 1961,geodetic,"Fundamental point: station FRIG on tern island, station B4 on Sorol Atoll.",1961,7022,8901,3181,Military and topographic mapping,"Two independent astronomic determinations considered to be consistent through adoption of common transformation to WGS 84 (see tfm code 15795).","DMA / NIMA / NGA TR8350.2 (original 1987 first edition and 3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Tern_Island_1961"
-6708,Cocos Islands 1965,geodetic,"Fundamental point: Anna 1.",1965,7003,8901,1069,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Anna_1_1965"
-6709,Iwo Jima 1945,geodetic,"Fundamental point: Beacon ""E"".",1945,7022,8901,3200,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Beacon_E_1945"
-6710,St. Helena 1971,geodetic,"Fundamental point: DOS 71/4.",1971,7022,8901,3183,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_DOS_71_4"
-6711,Marcus Island 1952,geodetic,Marcus Island Astronomic Station.,1952,7022,8901,1872,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2012/03/25",2012.032,0,"D_Astro_1952"
-6712,Ascension Island 1958,geodetic,,1958,7022,8901,3182,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Ascension_Island_1958"
+6705,"Mhast (offshore)",geodetic,"Fundamental point: Station Y at Malongo base camp. Latitude: 5°23'30.810""S, longitude: 12°12'01.590""E (of Greenwich).",1979-01-01,7022,8901,3180,Oil industry offshore exploration and production between 1979 and 1987.,"Origin coordinates determined by Transit single point position using 32 passes and transformed from WGS72BE using transformation code 15790. Differs from Mhast (onshore) by approximately 10m. Replaced in 1987 by Malongo 1987 (code 6259)." [...]
+6706,Egypt Gulf of Suez S-650 TL,geodetic,"Fundamental point: Station S-650 DMX. Adopted coordinates: latitude: 28°19'02.1907""N, longitude: 33°06'36.6344""E (of Greenwich). The proper Egypt 1907 coordinates for S-650 differ from these by about 20m.",1980-01-01,7020,8901,2341,Oil industry offshore exploration and production in Gulf of Suez after 1980.,"A coherent set of stations bordering the Gulf of Suez coordinated by Transit translocation (""TL"") between 1980 and 1984. Based on incor [...]
+6707,Tern Island 1961,geodetic,"Fundamental point: station FRIG on tern island, station B4 on Sorol Atoll.",1961-01-01,7022,8901,3181,Military and topographic mapping,"Two independent astronomic determinations considered to be consistent through adoption of common transformation to WGS 84 (see tfm code 15795).","DMA / NIMA / NGA TR8350.2 (original 1987 first edition and 3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Tern_Island_1961"
+6708,Cocos Islands 1965,geodetic,"Fundamental point: Anna 1.",1965-01-01,7003,8901,1069,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Anna_1_1965"
+6709,Iwo Jima 1945,geodetic,"Fundamental point: Beacon ""E"".",1945-01-01,7022,8901,3200,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Beacon_E_1945"
+6710,Astro DOS 71,geodetic,"Fundamental point: DOS 71/4, Ladder Hill Fort, latitude: 15°55'30""S, longitude: 5°43'25""W (of Greenwich).",1971-01-01,7022,8901,3183,"Geodetic control, military and topographic mapping.",,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000) and St. Helena Government, Environment and Natural Resources Directorate (ENRD).",IOGP,"2016/12/15",2016.038,0,"D_DOS_71_4"
+6711,Marcus Island 1952,geodetic,Marcus Island Astronomic Station.,1952-01-01,7022,8901,1872,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2012/03/25",2012.032,0,"D_Astro_1952"
+6712,Ascension Island 1958,geodetic,,1958-01-01,7022,8901,3182,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Ascension_Island_1958"
 6713,Ayabelle Lighthouse,geodetic,"Fundamental point: Ayabelle Lighthouse.",,7012,8901,1081,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Ayabelle"
-6714,Bellevue,geodetic,,1960,7022,8901,3193,Military and topographic mapping,"Datum covers all the major islands of Vanuatu in two different adjustment blocks, but practical usage is as given in the area of use.","DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/07/29",2006.510,0,"D_Bellevue_IGN"
+6714,Bellevue,geodetic,,1960-01-01,7022,8901,3193,Military and topographic mapping,"Datum covers all the major islands of Vanuatu in two different adjustment blocks, but practical usage is as given in the area of use.","DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/07/29",2006.510,0,"D_Bellevue_IGN"
 6715,Camp Area Astro,geodetic,,,7022,8901,3205,Geodetic and topographic survey,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Camp_Area"
-6716,Phoenix Islands 1966,geodetic,,1966,7022,8901,3196,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Canton_1966"
-6717,Cape Canaveral,geodetic,"Fundamental point: Central 1950.  Latitude: 28°29'32.36555""N, longitude 80°34'38.77362""W (of Greenwich)",1963,7008,8901,3206,US space and military operations.,,"US NGS and DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2008/06/24",2006.870 2008.045,0,"D_Cape_Canaveral"
-6718,Solomon 1968,geodetic,"Fundamental point: GUX 1.",1968,7022,8901,1213,"Military and topographic mapping, +/- 25 meters in each component",,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Solomon_1968"
-6719,Easter Island 1967,geodetic,,1967,7022,8901,3188,"Military and topographic mapping, +/- 25 meters in each component",,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Easter_Island_1967"
-6720,Fiji Geodetic Datum 1986,geodetic,NWL 9D coordinates of 6 stations on Vitu Levu and Vanua Levu.,1986,7043,8901,1094,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Viti Levu 1912, Vanua Levu 1915 and Fiji 1956.","Survey Review 30,231 (January 1989).",OGP,"2006/07/19",2006.500,0,"D_Fiji_1986"
-6721,Fiji 1956,geodetic,"Latitude origin was obtained astronomically at station Rasusuva = 17°49'03.13""S,  longitude origin was obtained astronomically at station Suva = 178°25'35.835""E (of Greenwich).",1956,7022,8901,3398,Military and topographic mapping,For topographic mapping replaces Viti Levu 1912 and Vanua Levu 1915. Replaced by Fiji Geodetic Datum 1986.,"SOPAC, www.sopac.org, and Clifford J. Mugnier in Photogrammetric Engineering and Remote Sensing, October 2000, www.asprs.org." [...]
-6722,South Georgia 1968,geodetic,"Fundamental point: ISTS 061.",1968,7022,8901,3529,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2012/02/13",2012.023,0,"D_ISTS_061_1968"
-6723,Grand Cayman Geodetic Datum 1959,geodetic,"Fundamental point: GC1. Latitude: 19°17'54.43""N, longitude: 81°22'37.17""W (of Greenwich).",1959,7008,8901,3185,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by CIGD11 (datum code 1100).","Lands and Survey Department, Cayman Islands Government.",OGP,"2013/01/17",2008.045 2012.095,0,"D_Grand_Cayman_1959"
-6724,Diego Garcia 1969,geodetic,"Fundamental point: ISTS 073.",1969,7022,8901,3189,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_ISTS_073_1969"
-6725,Johnston Island 1961,geodetic,,1961,7022,8901,3201,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Johnston_Island_1961"
-6726,Sister Islands Geodetic Datum 1961,geodetic,"Fundamental point: LC5. Latitude: 19°39'46.324""N, longitude: 80°03'47.910""W (of Greenwich).",1961,7008,8901,3186,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by CIGD11 (datum code 1100).","Lands and Survey Department, Cayman Islands Government.",OGP,"2013/01/17",2008.045 2012.095,0,"D_Little_Cayman_1961"
-6727,Midway 1961,geodetic,,1961,7022,8901,3202,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Midway_1961"
+6716,Phoenix Islands 1966,geodetic,,1966-01-01,7022,8901,3196,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Canton_1966"
+6717,Cape Canaveral,geodetic,"Fundamental point: Central 1950.  Latitude: 28°29'32.36555""N, longitude 80°34'38.77362""W (of Greenwich)",1963-01-01,7008,8901,3206,US space and military operations.,,"US NGS and DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2008/06/24",2006.870 2008.045,0,"D_Cape_Canaveral"
+6718,Solomon 1968,geodetic,"Fundamental point: GUX 1.",1968-01-01,7022,8901,1213,"Military and topographic mapping, +/- 25 meters in each component",,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Solomon_1968"
+6719,Easter Island 1967,geodetic,,1967-01-01,7022,8901,3188,"Military and topographic mapping, +/- 25 meters in each component",,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Easter_Island_1967"
+6720,Fiji Geodetic Datum 1986,geodetic,NWL 9D coordinates of 6 stations on Vitu Levu and Vanua Levu.,1986-01-01,7043,8901,1094,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Viti Levu 1912, Vanua Levu 1915 and Fiji 1956.","Survey Review 30,231 (January 1989).",OGP,"2006/07/19",2006.500,0,"D_Fiji_1986"
+6721,Fiji 1956,geodetic,"Latitude origin was obtained astronomically at station Rasusuva = 17°49'03.13""S,  longitude origin was obtained astronomically at station Suva = 178°25'35.835""E (of Greenwich).",1956-01-01,7022,8901,3398,Military and topographic mapping,For topographic mapping replaces Viti Levu 1912 and Vanua Levu 1915. Replaced by Fiji Geodetic Datum 1986.,"SOPAC, www.sopac.org, and Clifford J. Mugnier in Photogrammetric Engineering and Remote Sensing, October 2000, www.asprs [...]
+6722,South Georgia 1968,geodetic,"Fundamental point: ISTS 061.",1968-01-01,7022,8901,3529,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2012/02/13",2012.023,0,"D_ISTS_061_1968"
+6723,Grand Cayman Geodetic Datum 1959,geodetic,"Fundamental point: GC1. Latitude: 19°17'54.43""N, longitude: 81°22'37.17""W (of Greenwich).",1959-01-01,7008,8901,3185,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by CIGD11 (datum code 1100).","Lands and Survey Department, Cayman Islands Government.",OGP,"2013/01/17",2008.045 2012.095,0,"D_Grand_Cayman_1959"
+6724,Diego Garcia 1969,geodetic,"Fundamental point: ISTS 073.",1969-01-01,7022,8901,3189,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_ISTS_073_1969"
+6725,Johnston Island 1961,geodetic,,1961-01-01,7022,8901,3201,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Johnston_Island_1961"
+6726,Sister Islands Geodetic Datum 1961,geodetic,"Fundamental point: LC5. Latitude: 19°39'46.324""N, longitude: 80°03'47.910""W (of Greenwich).",1961-01-01,7008,8901,3186,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by CIGD11 (datum code 1100).","Lands and Survey Department, Cayman Islands Government.",OGP,"2013/01/17",2008.045 2012.095,0,"D_Little_Cayman_1961"
+6727,Midway 1961,geodetic,,1961-01-01,7022,8901,3202,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Midway_1961"
 6728,Pico de las Nieves 1984,geodetic,,,7022,8901,3873,Military and topographic mapping,"Replaces Pico de las Nieves 1968 (PN68). Replaced by REGCAN95.","DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2011/05/09",2009.033 2011.035,0,"D_Pico_de_Las_Nieves"
-6729,Pitcairn 1967,geodetic,"Fundamental point: Pitcairn Astro. Latitude: 25°04'06.87""S, longitude: 130°06'47.83""W (of Greenwich).",1967,7022,8901,3208,Military and topographic mapping,Replaced by Pitcairn 2006.,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2008/06/24",2008.004 2008.045,0,"D_Pitcairn_1967"
-6730,Santo 1965,geodetic,,1965,7022,8901,3194,Military and topographic mapping,"Datum covers all the major islands of Vanuatu in two different adjustment blocks, but practical usage is as given in the area of use.","DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/07/29",2006.510,0,"D_Santo_DOS_1965"
-6731,Viti Levu 1916,geodetic,,1916,7012,8901,3195,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,1,"D_Viti_Levu_1916"
-6732,Marshall Islands 1960,geodetic,,1960,7053,8901,3191,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Wake_Eniwetok_1960"
-6733,Wake Island 1952,geodetic,,1952,7022,8901,3190,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Wake_Island_1952"
-6734,Tristan 1968,geodetic,,1968,7022,8901,3184,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Tristan_1968"
-6735,Kusaie 1951,geodetic,,1951,7022,8901,3192,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Kusaie_1951"
+6729,Pitcairn 1967,geodetic,"Fundamental point: Pitcairn Astro. Latitude: 25°04'06.87""S, longitude: 130°06'47.83""W (of Greenwich).",1967-01-01,7022,8901,3208,Military and topographic mapping,Replaced by Pitcairn 2006.,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2008/06/24",2008.004 2008.045,0,"D_Pitcairn_1967"
+6730,Santo 1965,geodetic,,1965-01-01,7022,8901,3194,Military and topographic mapping,"Datum covers all the major islands of Vanuatu in two different adjustment blocks, but practical usage is as given in the area of use.","DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/07/29",2006.510,0,"D_Santo_DOS_1965"
+6731,Viti Levu 1916,geodetic,,1916-01-01,7012,8901,3195,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,1,"D_Viti_Levu_1916"
+6732,Marshall Islands 1960,geodetic,,1960-01-01,7053,8901,3191,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Wake_Eniwetok_1960"
+6733,Wake Island 1952,geodetic,,1952-01-01,7022,8901,3190,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Wake_Island_1952"
+6734,Tristan 1968,geodetic,,1968-01-01,7022,8901,3184,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Tristan_1968"
+6735,Kusaie 1951,geodetic,,1951-01-01,7022,8901,3192,Military and topographic mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Kusaie_1951"
 6736,Deception Island,geodetic,,,7012,8901,3204,Military and scientific mapping,,"DMA / NIMA / NGA TR8350.2 (3rd edition, Amendment 1, 3 January 2000).",OGP,"2006/01/26",,0,"D_Deception_Island"
-6737,Geocentric datum of Korea,geodetic,ITRF2000 at epoch 2002.0.,2002,7019,8901,1135,Geodetic survey.,,"Permanent Committee for GIS Infrastructure for Asia and the Pacific (PCGIAP), http://www.gsi.go.jp/PCGIAP",OGP,"2006/08/18",2006.770,0,"D_Korea_2000"
-6738,Hong Kong 1963,geodetic,"Fundamental point: Trig ""Zero"", 38.4 feet south along the transit circle of the Kowloon Observatory. Latitude 22°18'12.82""N, longitude 114°10'18.75""E (of Greenwich).",1963,7007,8901,1118,Topographic mapping and hydrographic charting.,"Replaced by Hong Kong 1963(67) for military purposes only in 1967.  Replaced by Hong Kong 1980.","Survey and Mapping Office, Lands Department. http://www.info.gov.hk/landsd/",OGP,"2008/06/24",2008.045,0,"D_Hong_Kong_1963"
-6739,"Hong Kong 1963(67)",geodetic,"Fundamental point: Trig ""Zero"", 38.4 feet south along the transit circle of the Kowloon Observatory. Latitude 22°18'12.82""N, longitude 114°10'18.75""E (of Greenwich).",1967,7022,8901,1118,Military mapping and charting.,Replaces Hong Kong 1963 for military purposes only in 1967.  Replaced by Hong Kong 1980.,UK Hydrographic Office.,OGP,"2008/06/24",2008.045,0,"D_Hong_Kong_1963_67"
-6740,Parametrop Zemp 1990,geodetic,Geocentre.,1990,7054,8901,1262,Geodetic survey.,"Derived through satellite tracking techniques. EPSG's PZ-90 datum has been the then current realisation. No distinction is made between the original PZ-90 frame and the PZ-90.02 improvement which was introduced in 2007.","Geodeziya i Katografiya, 1993.",OGP,"2010/03/30",2010.031,0,"D_Parametrop_Zemp_1990"
-6741,Faroe Datum 1954,geodetic,Astronomical observations at 3 points.,1954,7022,8901,3248,"Geodetic survey, topographic mapping, engineering and cadastral survey.","Replaced by ED50 in late 1970's for all purposes other than cadastre. Replaced by fk89 for cadastre.","Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2006/08/04",2005.472,0,"D_Faroe_Datum_1954"
-6742,Geodetic Datum of Malaysia 2000,geodetic,"ITRF2000, epoch 2000.0.",2000,7019,8901,1151,"Geodetic survey, topographic mapping, engineering and cadastrral survey.",Replaces all older Malaysian datums.,"GDM2000 Technical Manual; Department of Survey and Mapping Malaysia. www.jupem.gov.my",OGP,"2006/03/16",,0,"D_GDM_2000"
-6743,Karbala 1979,geodetic,"Fundamental point: Karbala. Latitude: 32°34'14.4941""N, longitude: 44°00'49.6379""E.",1979,7012,8901,3625,Geodetic survey.,National geodetic network established by Polservice consortium.,Various industry sources.,OGP,"2011/01/25",2009.003 2011.004,0,"D_Karbala_1979_Polservice"
-6744,Nahrwan 1934,geodetic,"Fundamental point: Nahrwan south base.  Latitude: 33°19'10.87""N, longitude: 44°43'25.54""E (of Greenwich).",1934,7012,8901,4238,Oil exploration and production.,"This adjustment later discovered to have a significant orientation error. In Iran replaced by FD58. In Iraq, replaced by Karbala 1979.",Various industry sources.,OGP,"2015/02/12",2008.045 2014.070,0,"D_Nahrwan_1934"
-6745,"Rauenberg Datum/83",geodetic,"Fundamental point: Rauenberg. Latitude: 52°27'12.021""N, longitude: 13°22'04.928""E (of Greenwich). This station was destroyed in 1910 and the station at Potsdam substituted as the fundamental point.",1990,7004,8901,2545,"Geodetic survey, cadastre, topographic mapping, engineering survey.","RD/83 is the realisation of DHDN in Saxony. It is the resultant of applying a transformation derived at 106 points throughout former East Germany to Pulkovo 1942/83 [...]
-6746,"Potsdam Datum/83",geodetic,"Fundamental point: Rauenberg. Latitude: 52°27'12.021""N, longitude: 13°22'04.928""E (of Greenwich). This station was destroyed in 1910 and the station at Potsdam substituted as the fundamental point.",1990,7004,8901,2544,"Geodetic survey, cadastre, topographic mapping, engineering survey.","PD/83 is the realisation of DHDN in Thuringen. It is the resultant of applying a transformation derived at 13 points on the border between East and West Germany to Pu [...]
-6747,Greenland 1996,geodetic,ITRF94 at epoch 1996.62,1996,7019,8901,1107,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Ammassalik 1958, Qornoq 1927 and Scoresbysund 1952.","Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2006/08/18",2006.770,0,"D_Greenland_1996"
-6748,Vanua Levu 1915,geodetic,"Latitude origin was obtained astronomically at station Numuiloa = 16°23'38.36""S, longitude origin was obtained astronomically at station Suva = 178°25'35.835""E.",1915,7055,8901,3401,"Geodetic survey, cadastre, topographic mapping, engineering survey.","For topographic mapping, replaced by Fiji 1956. For other purposes, replaced by Fiji 1986.","Clifford J. Mugnier in Photogrammetric Engineering and Remote Sensing, October 2000, www.asprs.org.",OGP,"2008/06 [...]
-6749,Reseau Geodesique de Nouvelle Caledonie 91-93,geodetic,ITRF90 at epoch 1989.0.,1989,7019,8901,1174,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/08/18",2006.770,0,"D_Reseau_Geodesique_de_Nouvelle_Caledonie_1991-93"
-6750,ST87 Ouvea,geodetic,Ouloup.,1987,7030,8901,2813,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",,0,"D_ST87_Ouvea"
-6751,"Kertau (RSO)",geodetic,,1969,7056,8901,1309,Metrication of RSO grid.,Adopts metric conversion of 0.914398 metres per yard exactly. This is a truncation of the Sears 1922 ratio.,Defence Geographic Centre.,OGP,"2006/07/24",,0,"D_Kertau_RSO"
-6752,Viti Levu 1912,geodetic,"Latitude origin was obtained astronomically at station Monavatu = 17°53'28.285""S, longitude origin was obtained astronomically at station Suva = 178°25'35.835""E.",1912,7055,8901,3195,"Geodetic survey, cadastre, topographic mapping, engineering survey.","For topographic mapping, replaced by Fiji 1956. For other purposes, replaced by Fiji 1986.","Clifford J. Mugnier in Photogrammetric Engineering and Remote Sensing, October 2000, www.asprs.org.",OGP,"2008/06 [...]
-6753,fk89,geodetic,,1989,7022,8901,3248,Cadastre,Replaces FD54 for cadastre.,"Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2006/08/04",,0,"D_fk89"
-6754,Libyan Geodetic Datum 2006,geodetic,5 stations tied to ITRF2000 through 8 days of continuous observations in May 2006.,2006,7022,8901,1143,"Geodetic survey, topographic mapping, engineering survey.",Replaces ELD79.,Survey Department of Libya.,OGP,"2006/08/25",,0,"D_Libyan_Geodetic_Datum_2006"
-6755,Datum Geodesi Nasional 1995,geodetic,ITRF91at epoch 1992.0.,1995,7030,8901,1122,"Geodetic survey, topographic mapping, engineering survey.",Replaces ID74 and all older datums.,Bakosurtanal.,OGP,"2006/08/25",,0,"D_Datum_Geodesi_Nasional_1995"
-6756,Vietnam 2000,geodetic,"Point N00, located in the premises of the Land Administration Research Institute, Hoang Quoc Viet Street, Hanoi.",2000,7030,8901,3328,"Geodetic survey, topographic mapping, engineering survey.",Replaces Hanoi 1972.,General Director of Land Administration.,OGP,"2011/01/25",2011.004,0,"D_Vietnam_2000"
-6757,SVY21,geodetic,"Fundamental point: Base 7 at Pierce Resevoir. Latitude: 1°22'02.9154""N, longitude: 103°49'31.9752""E (of Greenwich).",2004,7030,8901,1210,Cadastre.,Replaces Kertau 1968 for cadastral purposes from August 2004.,Singapore Land Authority,OGP,"2008/06/24",2008.045,0,"D_SVY21"
-6758,Jamaica 2001,geodetic,Aligned to WGS 84.,2001,7030,8901,1128,"Geodetic survey, cadastre, topographic mapping, hydrographic charting, engineering survey.",,National Land Agency.,OGP,"2007/01/19",,0,"D_Jamaica_2001"
-6759,"NAD83 (National Spatial Reference System 2007)",geodetic,"Coordinates of 486 national continually operating reference system (CORS) and 195 collaborative GPS (CGPS) sites constrained to their CORS96 values, ITRF2000 at epoch 2002.0.",2007,7019,8901,1511,Geodetic survey.,"Replaced by NAD83 (National Spatial Reference System 2011), datum code 1116.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/12",2013.022,0,"D_NAD_1983_NSRS2007"
-6760,World Geodetic System 1966,geodetic,Developed from a worldwide distribution of terrestrial and geodetic satellite observations and defined through a set of station coordinates.,1966,7025,8901,1262,Geodesy.,"A worldwide 5° × 5° mean free air gravity anomaly field provided the basic data for producing the WGS 66 gravimetric geoid. Replaced by WGS 72.","US DMA/NIMA/NGA",OGP,"2007/03/25",,0,"D_WGS_1966"
-6761,Croatian Terrestrial Reference System,geodetic,Densification of ETRS89 in Croatia at epoch 1995.55.,1996,7019,8901,1076,Geodesy.,Based on 78 control points with coordinates determined in ETRS89.,State Geodetic Administration of the Republic of Croatia.,OGP,"2007/09/25",,0,"D_Croatian_Terrestrial_Reference_System"
-6762,Bermuda 2000,geodetic,ITRF96 at epoch 2000.0.,2000,7030,8901,1047,"Topographic mapping, cadastral and engineering survey.",,Department of Lands Buildings and Surveys,OGP,"2007/12/12",,0,"D_Bermuda_2000"
-6763,Pitcairn 2006,geodetic,"Fundamental point: Pitcairn Astro. Latitude: 25°04'06.7894""S, longitude: 130°06'46.6816""W (of Greenwich), derived by single point GPS oberservations.",2006,7030,8901,3208,"Cadastre, topographic mapping and engineering survey",Replaces Pitcairn 1967.,Pitcairn Island Government.,OGP,"2008/06/24",2008.045,0,"D_Pitcairn_2006"
-6764,Ross Sea Region Geodetic Datum 2000,geodetic,Based on ITRF96 at epoch 2000.0,2000,7019,8901,3558,"Geodetic survey, topographic mapping.",,"Land Information New Zealand: LINZS25001 Standard for Ross Sea Region Geodetic Datum 2000; 16 November 2007.",OGP,"2008/04/04",,0,"D_Ross_Sea_Region_Geodetic_Datum_2000"
-6765,Slovenia Geodetic Datum 1996,geodetic,"Densification of ETRS89, based on ITRS89 at epoch 1995.55.",1996,7019,8901,1212,"Geodetic survey, topographic mapping.",,Surveying and Mapping Authority of Slovenia,OGP,"2008/04/04",,0,"D_Slovenia_Geodetic_Datum_1996"
-6801,"CH1903 (Bern)",geodetic,"Fundamental point: Old Bern observatory. Latitude: 46°57'08.660""N, longitude: 0°E (of Bern).",1903,7004,8907,1286,Topographic mapping.,,"Bundesamt für Landestopographie",OGP,"2008/06/24",2003.361 2008.045,0,"D_Bern_1898"
-6802,"Bogota 1975 (Bogota)",geodetic,"Fundamental point: Bogota observatory. Latitude: 4°35'56.570""N, longitude: 0°E (of Bogota).",1975,7022,8904,3229,Topographic mapping.,,,OGP,"2008/06/24",2000.200 2003.361 2008.045,0,"D_Bogota"
-6803,"Lisbon 1937 (Lisbon)",geodetic,"Fundamental point: Castelo Sao Jorge, Lisbon. Latitude: 38°42'43.631""N, longitude: 0°E (of Lisbon).",1937,7022,8902,1294,Topographic mapping.,"Replaces Lisbon 1890 adjustment (which used Bessel 1841 ellipsoid).","Instituto Geografico e Cadastral; Lisbon",OGP,"2008/06/24",2001.551 2008.045,0,"D_Lisbon"
+6737,Geocentric datum of Korea,geodetic,ITRF2000 at epoch 2002.0.,2002-01-01,7019,8901,1135,Geodetic survey.,,"Permanent Committee for GIS Infrastructure for Asia and the Pacific (PCGIAP), http://www.gsi.go.jp/PCGIAP",OGP,"2006/08/18",2006.770,0,"D_Korea_2000"
+6738,Hong Kong 1963,geodetic,"Fundamental point: Trig ""Zero"", 38.4 feet south along the transit circle of the Kowloon Observatory. Latitude 22°18'12.82""N, longitude 114°10'18.75""E (of Greenwich).",1963-01-01,7007,8901,1118,Topographic mapping and hydrographic charting.,"Replaced by Hong Kong 1963(67) for military purposes only in 1967.  Replaced by Hong Kong 1980.","Survey and Mapping Office, Lands Department. http://www.info.gov.hk/landsd/",OGP,"2008/06/24",2008.045,0,"D_Hong_Kong_1963"
+6739,"Hong Kong 1963(67)",geodetic,"Fundamental point: Trig ""Zero"", 38.4 feet south along the transit circle of the Kowloon Observatory. Latitude 22°18'12.82""N, longitude 114°10'18.75""E (of Greenwich).",1967-01-01,7022,8901,1118,Military mapping and charting.,Replaces Hong Kong 1963 for military purposes only in 1967.  Replaced by Hong Kong 1980.,UK Hydrographic Office.,OGP,"2008/06/24",2008.045,0,"D_Hong_Kong_1963_67"
+6740,Parametry Zemli 1990,geodetic,"Defined through coordinates of stations of the satellite geodetic network (SGN) in Russia at epoch 1990.0.",1990-01-01,7054,8901,1262,Glonass satellite navigation prior to 2007-09-20.,Replaced by PZ-90.02 from 2007-09-20.,"Geodeziya i Katografiya, 1993, and ""Parametry Zemli Reference Document"", Military Topgraphic Department (VTU) of the General Staff of Armed Forces of the Russian Federation.",IOGP,"2016/12/15",2010.031 2015.055,0,"D_Parametrop_Zemp_1990"
+6741,Faroe Datum 1954,geodetic,Astronomical observations at 3 points.,1954-01-01,7022,8901,3248,"Geodetic survey, topographic mapping, engineering and cadastral survey.","Replaced by ED50 in late 1970's for all purposes other than cadastre. Replaced by fk89 for cadastre.","Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2006/08/04",2005.472,0,"D_Faroe_Datum_1954"
+6742,Geodetic Datum of Malaysia 2000,geodetic,"ITRF2000, epoch 2000.0.",2000-01-01,7019,8901,1151,"Geodetic survey, topographic mapping, engineering and cadastrral survey.",Replaces all older Malaysian datums.,"GDM2000 Technical Manual; Department of Survey and Mapping Malaysia. www.jupem.gov.my",OGP,"2006/03/16",,0,"D_GDM_2000"
+6743,Karbala 1979,geodetic,"Fundamental point: Karbala. Latitude: 32°34'14.4941""N, longitude: 44°00'49.6379""E.",1979-01-01,7012,8901,3625,Geodetic survey.,National geodetic network established by Polservice consortium.,Various industry sources.,OGP,"2011/01/25",2009.003 2011.004,0,"D_Karbala_1979_Polservice"
+6744,Nahrwan 1934,geodetic,"Fundamental point: Nahrwan south base.  Latitude: 33°19'10.87""N, longitude: 44°43'25.54""E (of Greenwich).",1934-01-01,7012,8901,4238,Oil exploration and production.,"This adjustment later discovered to have a significant orientation error. In Iran replaced by FD58. In Iraq, replaced by Karbala 1979.",Various industry sources.,OGP,"2015/02/12",2008.045 2014.070,0,"D_Nahrwan_1934"
+6745,"Rauenberg Datum/83",geodetic,"Fundamental point: Rauenberg. Latitude: 52°27'12.021""N, longitude: 13°22'04.928""E (of Greenwich). This station was destroyed in 1910 and the station at Potsdam substituted as the fundamental point.",1990-01-01,7004,8901,2545,"Geodetic survey, cadastre, topographic mapping, engineering survey.","RD/83 is the realisation of DHDN in Saxony. It is the resultant of applying a transformation derived at 106 points throughout former East Germany to Pulkovo 1 [...]
+6746,"Potsdam Datum/83",geodetic,"Fundamental point: Rauenberg. Latitude: 52°27'12.021""N, longitude: 13°22'04.928""E (of Greenwich). This station was destroyed in 1910 and the station at Potsdam substituted as the fundamental point.",1990-01-01,7004,8901,2544,"Geodetic survey, cadastre, topographic mapping, engineering survey.","PD/83 is the realisation of DHDN in Thuringen. It is the resultant of applying a transformation derived at 13 points on the border between East and West Germany [...]
+6747,Greenland 1996,geodetic,ITRF94 at epoch 1996.62,1996-08-14,7019,8901,1107,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaces Ammassalik 1958, Qornoq 1927 and Scoresbysund 1952.","Kort & Matrikelstyrelsen (KMS), Copenhagen.",IOGP,"2016/09/16",2006.770 2016.020,0,"D_Greenland_1996"
+6748,Vanua Levu 1915,geodetic,"Latitude origin was obtained astronomically at station Numuiloa = 16°23'38.36""S, longitude origin was obtained astronomically at station Suva = 178°25'35.835""E.",1915-01-01,7055,8901,3401,"Geodetic survey, cadastre, topographic mapping, engineering survey.","For topographic mapping, replaced by Fiji 1956. For other purposes, replaced by Fiji 1986.","Clifford J. Mugnier in Photogrammetric Engineering and Remote Sensing, October 2000, www.asprs.org.",OGP,"2 [...]
+6749,Reseau Geodesique de Nouvelle Caledonie 91-93,geodetic,ITRF90 at epoch 1989.0.,1989-01-01,7019,8901,1174,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/08/18",2006.770,0,"D_Reseau_Geodesique_de_Nouvelle_Caledonie_1991-93"
+6750,ST87 Ouvea,geodetic,Ouloup.,1987-01-01,7030,8901,2813,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,"Service Topographique de la Nouvelle Caledonie, Direction des Infrastructures, de la Topografie et des Transports Terrestres. www.dittt.gouv.nc",OGP,"2006/07/21",,0,"D_ST87_Ouvea"
+6751,"Kertau (RSO)",geodetic,,1969-01-01,7056,8901,1309,Metrication of RSO grid.,Adopts metric conversion of 0.914398 metres per yard exactly. This is a truncation of the Sears 1922 ratio.,Defence Geographic Centre.,OGP,"2006/07/24",,0,"D_Kertau_RSO"
+6752,Viti Levu 1912,geodetic,"Latitude origin was obtained astronomically at station Monavatu = 17°53'28.285""S, longitude origin was obtained astronomically at station Suva = 178°25'35.835""E.",1912-01-01,7055,8901,3195,"Geodetic survey, cadastre, topographic mapping, engineering survey.","For topographic mapping, replaced by Fiji 1956. For other purposes, replaced by Fiji 1986.","Clifford J. Mugnier in Photogrammetric Engineering and Remote Sensing, October 2000, www.asprs.org.",OGP,"2 [...]
+6753,fk89,geodetic,,1989-01-01,7022,8901,3248,Cadastre,Replaces FD54 for cadastre.,"Kort & Matrikelstyrelsen (KMS), Copenhagen.",OGP,"2006/08/04",,0,"D_fk89"
+6754,Libyan Geodetic Datum 2006,geodetic,5 stations tied to ITRF2000 through 8 days of continuous observations in May 2006.,2006-05-19,7022,8901,1143,"Geodetic survey, topographic mapping, engineering survey.",Replaces ELD79.,Survey Department of Libya.,IOGP,"2016/09/16",2016.020,0,"D_Libyan_Geodetic_Datum_2006"
+6755,Datum Geodesi Nasional 1995,geodetic,ITRF91at epoch 1992.0.,1995-01-01,7030,8901,1122,"Geodetic survey, topographic mapping, engineering survey.",Replaces ID74 and all older datums.,Bakosurtanal.,OGP,"2006/08/25",,0,"D_Datum_Geodesi_Nasional_1995"
+6756,Vietnam 2000,geodetic,"Point N00, located in the premises of the Land Administration Research Institute, Hoang Quoc Viet Street, Hanoi.",2000-01-01,7030,8901,3328,"Geodetic survey, topographic mapping, engineering survey.",Replaces Hanoi 1972.,General Director of Land Administration.,OGP,"2011/01/25",2011.004,0,"D_Vietnam_2000"
+6757,SVY21,geodetic,"Fundamental point: Base 7 at Pierce Resevoir. Latitude: 1°22'02.9154""N, longitude: 103°49'31.9752""E (of Greenwich).",2004-01-01,7030,8901,1210,Cadastre.,Replaces Kertau 1968 for cadastral purposes from August 2004.,Singapore Land Authority,OGP,"2008/06/24",2008.045,0,"D_SVY21"
+6758,Jamaica 2001,geodetic,Aligned to WGS 84.,2001-01-01,7030,8901,1128,"Geodetic survey, cadastre, topographic mapping, hydrographic charting, engineering survey.",,National Land Agency.,OGP,"2007/01/19",,0,"D_Jamaica_2001"
+6759,"NAD83 (National Spatial Reference System 2007)",geodetic,"Coordinates of 486 national continually operating reference system (CORS) and 195 collaborative GPS (CGPS) sites constrained to their CORS96 values, ITRF2000 at epoch 2002.0.",2007-01-01,7019,8901,1511,Geodetic survey.,"Replaced by NAD83 (National Spatial Reference System 2011), datum code 1116.","U.S. National Geodetic Survey, http://www.ngs.noaa.gov/",OGP,"2013/06/12",2013.022,0,"D_NAD_1983_NSRS2007"
+6760,World Geodetic System 1966,geodetic,Developed from a worldwide distribution of terrestrial and geodetic satellite observations and defined through a set of station coordinates.,1966-01-01,7025,8901,1262,Geodesy.,"A worldwide 5° × 5° mean free air gravity anomaly field provided the basic data for producing the WGS 66 gravimetric geoid. Replaced by WGS 72.","US DMA/NIMA/NGA",OGP,"2007/03/25",,0,"D_WGS_1966"
+6761,Croatian Terrestrial Reference System,geodetic,Densification of ETRS89 in Croatia at epoch 1995.55.,1995-07-20,7019,8901,1076,Geodesy.,Based on 78 control points with coordinates determined in ETRS89.,State Geodetic Administration of the Republic of Croatia.,IOGP,"2016/09/16",2016.020,0,"D_Croatian_Terrestrial_Reference_System"
+6762,Bermuda 2000,geodetic,ITRF96 at epoch 2000.0.,2000-01-01,7030,8901,1047,"Topographic mapping, cadastral and engineering survey.",,Department of Lands Buildings and Surveys,OGP,"2007/12/12",,0,"D_Bermuda_2000"
+6763,Pitcairn 2006,geodetic,"Fundamental point: Pitcairn Astro. Latitude: 25°04'06.7894""S, longitude: 130°06'46.6816""W (of Greenwich), derived by single point GPS oberservations.",2006-01-01,7030,8901,3208,"Cadastre, topographic mapping and engineering survey",Replaces Pitcairn 1967.,Pitcairn Island Government.,OGP,"2008/06/24",2008.045,0,"D_Pitcairn_2006"
+6764,Ross Sea Region Geodetic Datum 2000,geodetic,Based on ITRF96 at epoch 2000.0,2000-01-01,7019,8901,3558,"Geodetic survey, topographic mapping.",,"Land Information New Zealand: LINZS25001 Standard for Ross Sea Region Geodetic Datum 2000; 16 November 2007.",OGP,"2008/04/04",,0,"D_Ross_Sea_Region_Geodetic_Datum_2000"
+6765,Slovenia Geodetic Datum 1996,geodetic,"Densification of ETRS89, based on ITRS89 at epoch 1995.55.",1996-01-01,7019,8901,1212,"Geodetic survey, topographic mapping.",,Surveying and Mapping Authority of Slovenia,OGP,"2008/04/04",,0,"D_Slovenia_Geodetic_Datum_1996"
+6801,"CH1903 (Bern)",geodetic,"Fundamental point: Old Bern observatory. Latitude: 46°57'08.660""N, longitude: 0°E (of Bern).",1903-01-01,7004,8907,1286,Topographic mapping.,,"Bundesamt für Landestopographie",OGP,"2008/06/24",2003.361 2008.045,0,"D_Bern_1898"
+6802,"Bogota 1975 (Bogota)",geodetic,"Fundamental point: Bogota observatory. Latitude: 4°35'56.570""N, longitude: 0°E (of Bogota).",1975-01-01,7022,8904,3229,Topographic mapping.,,,OGP,"2008/06/24",2000.200 2003.361 2008.045,0,"D_Bogota"
+6803,"Lisbon 1937 (Lisbon)",geodetic,"Fundamental point: Castelo Sao Jorge, Lisbon. Latitude: 38°42'43.631""N, longitude: 0°E (of Lisbon).",1937-01-01,7022,8902,1294,Topographic mapping.,"Replaces Lisbon 1890 adjustment (which used Bessel 1841 ellipsoid).","Instituto Geografico e Cadastral; Lisbon",OGP,"2008/06/24",2001.551 2008.045,0,"D_Lisbon"
 6804,"Makassar (Jakarta)",geodetic,"Fundamental point: station P1, Moncongloe. Latitude 5°08'41.42""S, longitude 12°35'47.15""E (of Jakarta).",,7004,8908,1316,Topographic mapping.,,OGP,OGP,"2008/06/24",2003.361 2008.045,0,"D_Makassar"
-6805,"Militar-Geographische Institut (Ferro)",geodetic,"Fundamental point: Hermannskogel. Latitude: 48°16'15.29""N, longitude: 33°57'41.06""E (of Ferro).",1901,7004,8909,1321,Geodetic survey.,Replaced by MGI in Austria and MGI 1901 in former Yugoslavia.,"Bundesamt fur Eich- und Vermessungswesen; Wien",OGP,"2009/06/02",2008.045 2009.015,0,"D_MGI"
+6805,"Militar-Geographische Institut (Ferro)",geodetic,"Fundamental point: Hermannskogel. Latitude: 48°16'15.29""N, longitude: 33°57'41.06""E (of Ferro).",1901-01-01,7004,8909,1321,Geodetic survey.,Replaced by MGI in Austria and MGI 1901 in former Yugoslavia.,"Bundesamt fur Eich- und Vermessungswesen; Wien",OGP,"2009/06/02",2008.045 2009.015,0,"D_MGI"
 6806,"Monte Mario (Rome)",geodetic,"Fundamental point: Monte Mario. Latitude: 41°55'25.51""N, longitude: 0°00' 00.00""E (of Rome).",,7022,8906,3343,Topographic mapping.,"Replaced Genova datum, Bessel 1841 ellipsoid, from 1940.",,OGP,"2008/06/24",2003.360 2008.045,0,"D_Monte_Mario"
-6807,"Nouvelle Triangulation Francaise (Paris)",geodetic,"Fundamental point: Pantheon. Latitude: 54.273618g N, longitude: 0.0106921g E (of Paris).",1895,7011,8903,3694,Topographic mapping.,,,OGP,"2010/03/30",2003.361 2009.106,0,"D_NTF"
-6808,"Padang 1884 (Jakarta)",geodetic,"Fundamental point: Padang",1884,7004,8908,1355,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Padang_1884"
-6809,"Reseau National Belge 1950 (Brussels)",geodetic,"Fundamental point: Lommel (tower). Latitude: 51°13'47.334""N, longitude: 0°56'44.773""E (of Brussels).",1950,7022,8910,1347,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Belge_1950"
-6810,"Tananarive 1925 (Paris)",geodetic,"Fundamental point: Tananarive observatory. Latitude: 21.0191667g S, longitude: 50.23849537g E (of Paris)",1925,7022,8903,3273,Topographic mapping.,,IGN Paris,OGP,"2003/12/31",2003.361,0,"D_Tananarive_1925"
-6811,"Voirol 1875 (Paris)",geodetic,"Fundamental point: Voirol. Latitude: 40.83578 grads N, longitude: 0.78873 grads E (of Paris).",1875,7011,8903,1365,Topographic mapping.,,IGN Paris,OGP,"2004/01/07",2003.361,0,"D_Voirol_1875"
+6807,"Nouvelle Triangulation Francaise (Paris)",geodetic,"Fundamental point: Pantheon. Latitude: 54.273618g N, longitude: 0.0106921g E (of Paris).",1895-01-01,7011,8903,3694,Topographic mapping.,,,OGP,"2010/03/30",2003.361 2009.106,0,"D_NTF"
+6808,"Padang 1884 (Jakarta)",geodetic,"Fundamental point: Padang",1884-01-01,7004,8908,1355,Topographic mapping.,,,OGP,"1995/06/02",,0,"D_Padang_1884"
+6809,"Reseau National Belge 1950 (Brussels)",geodetic,"Fundamental point: Lommel (tower). Latitude: 51°13'47.334""N, longitude: 0°56'44.773""E (of Brussels).",1950-01-01,7022,8910,1347,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Belge_1950"
+6810,"Tananarive 1925 (Paris)",geodetic,"Fundamental point: Tananarive observatory. Latitude: 21.0191667g S, longitude: 50.23849537g E (of Paris)",1925-01-01,7022,8903,3273,Topographic mapping.,,IGN Paris,OGP,"2003/12/31",2003.361,0,"D_Tananarive_1925"
+6811,"Voirol 1875 (Paris)",geodetic,"Fundamental point: Voirol. Latitude: 40.83578 grads N, longitude: 0.78873 grads E (of Paris).",1875-01-01,7011,8903,1365,Topographic mapping.,,IGN Paris,OGP,"2004/01/07",2003.361,0,"D_Voirol_1875"
 6813,"Batavia (Jakarta)",geodetic,"Fundamental point: Longitude at Batavia astronomical station. Latitude: 6°07'39.522""S, longitude: 0°00'00.0""E (of Jakarta). Latitude and azimuth at Genuk.",,7004,8908,1285,Topographic mapping.,,,OGP,"2008/06/24",2003.361 2008.045,0,"D_Batavia"
-6814,"Stockholm 1938 (Stockholm)",geodetic,"Fundamental point: Stockholm observatory",1938,7004,8911,3313,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RT90 adjustment (datum code 6124)",,OGP,"1996/04/12",,0,"D_Stockholm_1938"
+6814,"Stockholm 1938 (Stockholm)",geodetic,"Fundamental point: Stockholm observatory",1938-01-01,7004,8911,3313,"Geodetic survey, cadastre, topographic mapping, engineering survey.","Replaced by RT90 adjustment (datum code 6124)",,OGP,"1996/04/12",,0,"D_Stockholm_1938"
 6815,"Greek (Athens)",geodetic,"Fundamental point: Athens Observatory. Latitude 37°58'20.132""N, longitude 0°E (of Athens).",,7004,8912,3254,Topographic mapping.,See geodetic datum alias 6404.  Used as basis of topographic mapping based on Hatt projection.,"Topography Department; National Technical University of Athens",OGP,"2011/07/20",2008.045 2011.062,0,"D_Greek"
-6816,"Carthage (Paris)",geodetic,"Fundamental point: Carthage. Latitude: 40.9464506g N, longitude: 8.8724368g E (of Paris).",1925,7011,8903,1618,Topographic mapping.,Fundamental point astronomic coordinates determined in 1878.,,OGP,"2004/01/15",2003.362 2003.050,0,"D_Carthage"
-6817,"NGO 1948 (Oslo)",geodetic,"Fundamental point: Oslo observatory. Latitude: 59°54'43.7""N, longitude: 0°00'00.0""E (of Oslo).",1948,7005,8913,1352,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,,OGP,"2008/06/24",2003.362 2008.045,0,"D_NGO_1948"
-6818,"System Jednotne Trigonometricke Site Katastralni (Ferro)",geodetic,"Modification of Austrian MGI (Ferro) datum.",1920,7004,8909,1306,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Research Institute for Geodesy Topography and Cartography (VUGTK); Prague.",OGP,"2010/11/02",2001.260 2010.071,0,"D_S_JTSK"
-6819,"Nord Sahara 1959 (Paris)",geodetic,"Coordinates of primary network readjusted on ED50 datum and then transformed conformally to Clarke 1880 (RGS) ellipsoid.",1959,7012,8903,1366,Topographic mapping.,,"""Le System Geodesique Nord-Sahara""; IGN Paris",OGP,"2000/06/23",,1,"D_Nord_Sahara_1959"
+6816,"Carthage (Paris)",geodetic,"Fundamental point: Carthage. Latitude: 40.9464506g N, longitude: 8.8724368g E (of Paris).",1925-01-01,7011,8903,1618,Topographic mapping.,Fundamental point astronomic coordinates determined in 1878.,,OGP,"2004/01/15",2003.362 2003.050,0,"D_Carthage"
+6817,"NGO 1948 (Oslo)",geodetic,"Fundamental point: Oslo observatory. Latitude: 59°54'43.7""N, longitude: 0°00'00.0""E (of Oslo).",1948-01-01,7005,8913,1352,"Geodetic survey, cadastre, topographic mapping, engineering survey.",,,OGP,"2008/06/24",2003.362 2008.045,0,"D_NGO_1948"
+6818,"System Jednotne Trigonometricke Site Katastralni (Ferro)",geodetic,"Modification of Austrian MGI (Ferro) datum.",1920-01-01,7004,8909,1306,"Geodetic survey, cadastre, topographic mapping, engineering survey.","S-JTSK = System of the Unified Trigonometrical Cadastral Network.","Research Institute for Geodesy Topography and Cartography (VUGTK); Prague.",OGP,"2010/11/02",2001.260 2010.071,0,"D_S_JTSK"
+6819,"Nord Sahara 1959 (Paris)",geodetic,"Coordinates of primary network readjusted on ED50 datum and then transformed conformally to Clarke 1880 (RGS) ellipsoid.",1959-01-01,7012,8903,1366,Topographic mapping.,,"""Le System Geodesique Nord-Sahara""; IGN Paris",OGP,"2000/06/23",,1,"D_Nord_Sahara_1959"
 6820,"Gunung Segara (Jakarta)",geodetic,"Station P5 (Gunung Segara) 0°32'12.83""S, 117°08'48.47""E (of Greenwich). Longitude 8°20'20.68""E (of Jakarta).",,7004,8908,1360,Topographic mapping.,,,OGP,"2008/06/24",2008.045,0,"D_Gunung_Segara"
-6821,"Voirol 1879 (Paris)",geodetic,"Fundamental point: Voirol. Latitude: 40.835864 grads N, longitude: 0.788735 grads E (of Paris).",1879,7011,8903,1365,Topographic mapping.,"Replaces Voirol 1875 (Paris) (code 6811).",IGN Paris,OGP,"2004/01/07",,0,"D_Voirol_1879"
-6896,International Terrestrial Reference Frame 2005,geodetic,"Origin at geocentre, originally orientated to the BIH Terrestrial System at epoch 1984.0 then adjusted to ensure zero net rotation to earth's overall tectonic motion. Defined by time series of Cartesian station coordinates for epoch 2000.0.",2000,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from September 2007. Replaces ITRF2000 (code 6656). Replaced by ITRF2008 (datum code 1061).","Jour [...]
+6821,"Voirol 1879 (Paris)",geodetic,"Fundamental point: Voirol. Latitude: 40.835864 grads N, longitude: 0.788735 grads E (of Paris).",1879-01-01,7011,8903,1365,Topographic mapping.,"Replaces Voirol 1875 (Paris) (code 6811).",IGN Paris,OGP,"2004/01/07",,0,"D_Voirol_1879"
+6896,International Terrestrial Reference Frame 2005,geodetic,"Origin at geocentre, originally orientated to the BIH Terrestrial System at epoch 1984.0 then adjusted to ensure zero net rotation to earth's overall tectonic motion. Defined by time series of Cartesian station coordinates for epoch 2000.0.",2000-01-01,7019,8901,1262,Geodesy.,"Realisation of the IERS Terrestrial Reference System (ITRS) from September 2007. Replaces ITRF2000 (code 6656). Replaced by ITRF2008 (datum code 1061)." [...]
 6901,"Ancienne Triangulation Francaise (Paris)",geodetic,,,7027,8914,1326,Topographic mapping.,"Uses the RGS value for the Paris meridian.  In Alsace, data suspected to be transformation of German network into ATF. Replaced by Nouvelle Triangulation Francaise (Paris) (code 6807) which uses the 1936 IGN value for the Paris meridian.",,OGP,"2007/11/01",2007.083,0,"D_ATF"
 6902,"Nord de Guerre (Paris)",geodetic,,,7027,8903,1369,Topographic mapping.,,,OGP,"1995/06/02",,1,"D_Nord_de_Guerre"
-6903,"Madrid 1870 (Madrid)",geodetic,"Fundamental point: Madrid observatory.",1870,7028,8905,2366,Topographic mapping.,,"Institut de Geomatica; Barcelona",OGP,"1998/11/11",,0,"D_Madrid_1870"
-6904,"Lisbon 1890 (Lisbon)",geodetic,"Fundamental point: Castelo Sao Jorge, Lisbon. Latitude: 38°42'43.631""N, longitude: 0°E (of Lisbon).",1937,7004,8902,1294,Topographic mapping.,"Replaced by Lisbon 1937 adjustment (which uses International 1924 ellipsoid).","Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2008/06/24",2003.232 2008.045,0,"D_Lisbon_1890"
+6903,"Madrid 1870 (Madrid)",geodetic,"Fundamental point: Madrid observatory.",1870-01-01,7028,8905,2366,Topographic mapping.,,"Institut de Geomatica; Barcelona",OGP,"1998/11/11",,0,"D_Madrid_1870"
+6904,"Lisbon 1890 (Lisbon)",geodetic,"Fundamental point: Castelo Sao Jorge, Lisbon. Latitude: 38°42'43.631""N, longitude: 0°E (of Lisbon).",1937-01-01,7004,8902,1294,Topographic mapping.,"Replaced by Lisbon 1937 adjustment (which uses International 1924 ellipsoid).","Instituto Geografico e Cadastral Lisbon http://www.igeo.pt",OGP,"2008/06/24",2003.232 2008.045,0,"D_Lisbon_1890"
 9300,Astra Minas,engineering,"Origin at 45°59'54.79""S, 67°34'38.94""W (of Greenwich).",,,,1265,Oil industry mapping.,,,OGP,"2008/06/24",2008.045,0,
 9301,Barcelona,engineering,"Centre of the gateway of San Cristobal chuch; Plaza Boyaca; Barcelona.",,,,1266,Oil industry mapping.,"Coordinates variously given as 10°08'06""N  64°41'17""W and 10°08'06""N  64°41'07.5""W.  It is not clear whether there should be two local datums.","Ministry of Mines standards manual, 1974.",OGP,"2008/06/24",2008.045,0,
 9302,Maturin,engineering,"Concrete post PR-1 in Plaza Bolivar; Maturin.  9°44'55""N, 63°10'40""W (of Greenwich).",,,,1320,Oil industry mapping.,,"Ministry of Mines standards manual, 1974.",OGP,"2008/06/24",2008.045,0,
diff --git a/data/gdalvrt.xsd b/data/gdalvrt.xsd
index b1f7e80..6b13541 100644
--- a/data/gdalvrt.xsd
+++ b/data/gdalvrt.xsd
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 /******************************************************************************
- * $Id: gdalvrt.xsd 30648 2015-09-22 15:16:23Z rouault $
+ * $Id: gdalvrt.xsd 35479 2016-09-16 20:34:58Z rouault $
  *
  * Project:  GDAL/OGR
  * Purpose:  XML Schema for GDAL VRT files.
@@ -167,6 +167,14 @@
                 <!-- for a VRTDerivedRasterBand -->
                 <xs:element name="PixelFunctionType" type="xs:string"/>
                 <xs:element name="SourceTransferType" type="DataTypeType"/>
+                <xs:element name="PixelFunctionLanguage" type="xs:string"/>
+                <xs:element name="PixelFunctionCode" type="xs:string"/>
+                <xs:element name="PixelFunctionArguments">
+                    <xs:complexType>
+                        <xs:anyAttribute processContents="lax"/>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="BufferRadius" type="xs:nonNegativeInteger"/>
 
                 <!-- for a VRTRawRasterBand -->
                 <xs:element name="SourceFilename" type="SourceFilenameType"/>
diff --git a/data/geoccs.csv b/data/geoccs.csv
index 2fe9ddd..4cba07b 100644
--- a/data/geoccs.csv
+++ b/data/geoccs.csv
@@ -70,7 +70,7 @@
 4918,ITRF97,6655,International Terrestrial Reference Frame 1997,6655,9001,7019,8901,1,0,6500
 4919,ITRF2000,6656,International Terrestrial Reference Frame 2000,6656,9001,7019,8901,1,0,6500
 4920,GDM2000,6742,Geodetic Datum of Malaysia 2000,6742,9001,7019,8901,1,0,6500
-4922,PZ-90,6740,Parametrop Zemp 1990,6740,9001,7054,8901,1,0,6500
+4922,PZ-90,6740,Parametry Zemli 1990,6740,9001,7054,8901,1,0,6500
 4924,Mauritania 1999,6702,Mauritania 1999,6702,9001,7019,8901,1,0,6500
 4926,Korea 2000,6737,Geocentric datum of Korea,6737,9001,7019,8901,1,0,6500
 4928,POSGAR 94,6694,Posiciones Geodesicas Argentinas 1994,6694,9001,7030,8901,1,0,6500
@@ -116,7 +116,7 @@
 5322,ISN2004,1060,Islands Net 2004,1060,9001,7019,8901,1,0,6500
 5332,ITRF2008,1061,International Terrestrial Reference Frame 2008,1061,9001,7019,8901,1,0,6500
 5341,POSGAR 2007,1062,Posiciones Geodesicas Argentinas 2007,1062,9001,7019,8901,1,0,6500
-5352,MARGEN,1063,Marco Geodesico Nacional,1063,9001,7019,8901,1,0,6500
+5352,MARGEN,1063,Marco Geodesico Nacional de Bolivia,1063,9001,7019,8901,1,0,6500
 5358,SIRGAS-Chile,1064,SIRGAS-Chile,1064,9001,7019,8901,1,0,6500
 5363,CR05,1065,Costa Rica 2005,1065,9001,7030,8901,1,0,6500
 5368,MACARIO SOLIS,1066,Sistema Geodesico Nacional de Panama MACARIO SOLIS,1066,9001,7019,8901,1,0,6500
@@ -147,3 +147,18 @@
 7134,IGD05,1114,Israeli Geodetic Datum 2005,1114,9001,7030,8901,1,0,6500
 7137,"IGD05/12",1115,"Israeli Geodetic Datum 2005(2012)",1115,9001,7030,8901,1,0,6500
 7371,ONGD14,1147,Oman National Geodetic Datum 2014,1147,9001,7019,8901,1,0,6500
+7656,"WGS 84 (G730)",1152,"World Geodetic System 1984 (G730)",1152,9001,7030,8901,1,0,6500
+7658,"WGS 84 (G873)",1153,"World Geodetic System 1984 (G873)",1153,9001,7030,8901,1,0,6500
+7660,"WGS 84 (G1150)",1154,"World Geodetic System 1984 (G1150)",1154,9001,7030,8901,1,0,6500
+7662,"WGS 84 (G1674)",1155,"World Geodetic System 1984 (G1674)",1155,9001,7030,8901,1,0,6500
+7664,"WGS 84 (G1762)",1156,"World Geodetic System 1984 (G1762)",1156,9001,7030,8901,1,0,6500
+7677,PZ-90.02,1157,Parametry Zemli 1990.02,1157,9001,7054,8901,1,0,6500
+7679,PZ-90.11,1158,Parametry Zemli 1990.11,1158,9001,7054,8901,1,0,6500
+7681,GSK-2011,1159,Geodezicheskaya Sistema Koordinat 2011,1159,9001,1025,8901,1,0,6500
+7684,Kyrg-06,1160,Kyrgyzstan Geodetic Datum 2006,1160,9001,7019,8901,1,0,6500
+7789,ITRF2014,1165,International Terrestrial Reference Frame 2014,1165,9001,7019,8901,1,0,6500
+7796,BGS2005,1167,Bulgaria Geodetic System 2005,1167,9001,7019,8901,1,0,6500
+7815,"WGS 84 (Transit)",1166,"World Geodetic System 1984 (Transit)",1166,9001,7030,8901,1,0,6500
+7842,GDA2020,1168,Geocentric Datum of Australia 2020,1168,9001,7019,8901,1,0,6500
+7879,St. Helena Tritan,1173,St. Helena Tritan,1173,9001,7030,8901,1,0,6500
+7884,SHGD2015,1174,St. Helena Geodetic Datum 2015,1174,9001,7019,8901,1,0,6500
diff --git a/data/gml_registry.xml b/data/gml_registry.xml
index f4f5a2a..831a32d 100644
--- a/data/gml_registry.xml
+++ b/data/gml_registry.xml
@@ -55,4 +55,63 @@
                      elementValue="ST_UVOH"
                      gfsSchemaLocation="ruian_vf_st_uvoh_v1.gfs" />
     </namespace>
+
+    <!-- Japan FGD GML v4 schema -->
+    <namespace uri="http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema">
+        <featureType elementName="GCP"
+                     gfsSchemaLocation="jpfgdgml_GCP.gfs" />
+        <featureType elementName="ElevPt"
+                     gfsSchemaLocation="jpfgdgml_ElevPt.gfs" />
+        <featureType elementName="Cntr"
+                     gfsSchemaLocation="jpfgdgml_Cntr.gfs" />
+        <featureType elementName="AdmArea"
+                     gfsSchemaLocation="jpfgdgml_AdmArea.gfs" />
+        <featureType elementName="AdmBdry"
+                     gfsSchemaLocation="jpfgdgml_AdmBdry.gfs" />
+        <featureType elementName="CommBdry"
+                     gfsSchemaLocation="jpfgdgml_CommBdry.gfs" />
+        <featureType elementName="AdmPt"
+                     gfsSchemaLocation="jpfgdgml_AdmPt.gfs" />
+        <featureType elementName="CommPt"
+                     gfsSchemaLocation="jpfgdgml_CommPt.gfs" />
+        <featureType elementName="SBArea"
+                     gfsSchemaLocation="jpfgdgml_SBArea.gfs" />
+        <featureType elementName="SBBdry"
+                     gfsSchemaLocation="jpfgdgml_SBBdry.gfs" />
+        <featureType elementName="SBAPt"
+                     gfsSchemaLocation="jpfgdgml_SBAPt.gfs" />
+        <featureType elementName="WA"
+                     gfsSchemaLocation="jpfgdgml_WA.gfs" />
+        <featureType elementName="WL"
+                     gfsSchemaLocation="jpfgdgml_WL.gfs" />
+        <featureType elementName="Cstline"
+                     gfsSchemaLocation="jpfgdgml_Cstline.gfs" />
+        <featureType elementName="WStrL"
+                     gfsSchemaLocation="jpfgdgml_WStrL.gfs" />
+        <featureType elementName="WStrA"
+                     gfsSchemaLocation="jpfgdgml_WStrA.gfs" />
+        <featureType elementName="LeveeEdge"
+                     gfsSchemaLocation="jpfgdgml_LeveeEdge.gfs" />
+        <featureType elementName="RvrMgtBdry"
+                     gfsSchemaLocation="jpfgdgml_RvrMgtBdry.gfs" />
+        <featureType elementName="BldA"
+                     gfsSchemaLocation="jpfgdgml_BldA.gfs" />
+        <featureType elementName="BldL"
+                     gfsSchemaLocation="jpfgdgml_BldL.gfs" />
+        <featureType elementName="RdEdg"
+                     gfsSchemaLocation="jpfgdgml_RdEdg.gfs" />
+        <featureType elementName="RdCompt"
+                     gfsSchemaLocation="jpfgdgml_RdCompt.gfs" />
+        <featureType elementName="RdASL"
+                     gfsSchemaLocation="jpfgdgml_RdASL.gfs" />
+        <featureType elementName="RdArea"
+                     gfsSchemaLocation="jpfgdgml_RdArea.gfs" />
+        <featureType elementName="RdSgmtA"
+                     gfsSchemaLocation="jpfgdgml_RdSgmtA.gfs" />
+        <featureType elementName="RdMgtBdry"
+                     gfsSchemaLocation="jpfgdgml_RdMgtBdry.gfs" />
+        <featureType elementName="RailCL"
+                     gfsSchemaLocation="jpfgdgml_RailCL.gfs" />
+    </namespace>
+
 </gml_registry>
diff --git a/data/gmlasconf.xml b/data/gmlasconf.xml
new file mode 100644
index 0000000..cd8fe47
--- /dev/null
+++ b/data/gmlasconf.xml
@@ -0,0 +1,169 @@
+<!-- This file is under the public domain -->
+
+<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               xsi:noNamespaceSchemaLocation="gmlasconf.xsd">
+
+    <AllowRemoteSchemaDownload>true</AllowRemoteSchemaDownload>
+    <SchemaCache enabled="true">
+        <Directory/> <!-- empty: use $HOME/.gdal/gmlas_xsd_cache by default -->
+    </SchemaCache>
+    <SchemaAnalysisOptions>
+        <SchemaFullChecking>true</SchemaFullChecking>
+        <HandleMultipleImports>false</HandleMultipleImports>
+    </SchemaAnalysisOptions>
+    <Validation enabled="false">
+        <FailIfError>false</FailIfError>
+    </Validation>
+    <ExposeMetadataLayers>false</ExposeMetadataLayers>
+    <LayerBuildingRules>
+        <AlwaysGenerateOGRId>false</AlwaysGenerateOGRId>
+        <RemoveUnusedLayers>false</RemoveUnusedLayers>
+        <RemoveUnusedFields>false</RemoveUnusedFields>
+        <UseArrays>true</UseArrays>
+        <UseNullState>false</UseNullState>
+        <GML>
+            <IncludeGeometryXML>false</IncludeGeometryXML>
+            <InstantiateGMLFeaturesOnly>true</InstantiateGMLFeaturesOnly>
+        </GML>
+        <!-- 60 for PostgreSQL compatiblity. The maximum is 64 but reserve
+             some space so that the spatial index name can be formed -->
+        <IdentifierMaxLength>60</IdentifierMaxLength>
+        <!-- Whether layer and field names should be consider equal in a
+             case insensitive way. This is important for conversion to
+             Postgres when identifiers are laundered in lower case -->
+        <CaseInsensitiveIdentifier>true</CaseInsensitiveIdentifier>
+        <!-- Launder identifiers like the OGR PG driver does.
+             Note: this laundering is safe for other backends as well. -->
+        <PostgreSQLIdentifierLaundering>true</PostgreSQLIdentifierLaundering>
+        <FlatteningRules>
+            <!-- Maximum number of fields allowed for element flattening -->
+            <MaximumNumberOfFields>10</MaximumNumberOfFields>
+
+            <!--
+            <Namespaces>
+                <Namespace prefix="..." uri="..."/>
+            </Namespaces>
+            -->
+            <!-- Exception to MaximumNumberOfFields:
+                force this element(s) to be flattened even if they have more elements -->
+            <!--
+            <ForceFlatteningXPath>...</ForceFlatteningXPath>
+            -->
+            <!-- Exception to MaximumNumberOfFields:
+                prevent this element(s) from being flattened even if they have less elements -->
+            <!--
+            <DisableFlatteningXPath>...</DisableFlatteningXPath>
+            -->
+        </FlatteningRules>
+
+        <SWEProcessing>
+            <Activation>ifSWENamespaceFoundInTopElement</Activation>
+            <ProcessDataArray>true</ProcessDataArray>
+        </SWEProcessing>
+    </LayerBuildingRules>
+
+    <!-- constraints typically expressed as schematrons -->
+    <TypingConstraints>
+        <Namespaces>
+            <Namespace prefix="gwml2w" uri="http://www.opengis.net/gwml-well/2.2"/>
+            <Namespace prefix="om" uri="http://www.opengis.net/om/2.0"/>
+        </Namespaces>
+        <ChildConstraint>
+            <ContainerXPath>gwml2w:GW_GeologyLog/om:result</ContainerXPath>
+            <ChildrenElements>
+                <Element>gwml2w:GW_GeologyLogCoverage</Element>
+            </ChildrenElements>
+        </ChildConstraint>
+    </TypingConstraints>
+
+    <XLinkResolution>
+        <Timeout>10</Timeout> <!-- can be set with GDAL_HTTP_TIMEOUT -->
+        <!-- <MaxGlobalResolutionTime></MaxGlobalResolutionTime> -->
+        <MaxFileSize>1048576</MaxFileSize>
+        <!--
+        <ProxyServerPort>myproxy.com:8080</ProxyServerPort>  Can be set with GDAL_HTTP_PROXY
+        <ProxyUserPassword>user:password<ProxyUserPassword>  Can be set with GDAL_HTTP_PROXYUSERPW
+        <ProxyAuth>Basic or NTLM or Digest or Any</ProxyAuth> Can be set with GDAL_PROXY_AUTH
+        -->
+        <CacheDirectory/> <!-- empty: use $HOME/.gdal/gmlas_xlink_resolution_cache by default -->
+        <DefaultResolution enabled="false">
+            <AllowRemoteDownload>true</AllowRemoteDownload>
+            <ResolutionMode>RawContent</ResolutionMode>
+            <ResolutionDepth>1</ResolutionDepth>
+            <CacheResults>false</CacheResults>
+        </DefaultResolution>
+<!--
+        <URLSpecificResolution>
+            <URLPrefix>http://inspire.ec.europa.eu/codelist</URLPrefix>
+            <HTTPHeader>
+                <Name>Accept</Name>
+                <Value>application/x-iso19135+xml</Value>
+            </HTTPHeader>
+            <HTTPHeader>
+                <Name>Accept-Language</Name>
+                <Value>en</Value>
+            </HTTPHeader>
+            <AllowRemoteDownload>true</AllowRemoteDownload>
+            <ResolutionMode>FieldsFromXPath</ResolutionMode>
+            <ResolutionDepth>1</ResolutionDepth>
+            <CacheResults>true</CacheResults>
+            <Field>
+                <Name>name</Name>
+                <Type>string</Type>
+                <XPath>RE_RegisterItem/name/gco:CharacterString</XPath>
+            </Field>
+            <Field>
+                <Name>definition</Name>
+                <Type>string</Type>
+                <XPath>RE_RegisterItem/definition/gco:CharacterString</XPath>
+            </Field>
+        </URLSpecificResolution>
+-->
+    </XLinkResolution>
+
+    <IgnoredXPaths>
+        <WarnIfIgnoredXPathFoundInDocInstance>true</WarnIfIgnoredXPathFoundInDocInstance>
+        <Namespaces>
+            <Namespace prefix="gml" uri="http://www.opengis.net/gml"/>
+            <Namespace prefix="gml32" uri="http://www.opengis.net/gml/3.2"/>
+            <Namespace prefix="swe" uri="http://www.opengis.net/swe/2.0"/>
+        </Namespaces>
+        <XPath warnIfIgnoredXPathFoundInDocInstance="false">gml:boundedBy</XPath>
+        <XPath warnIfIgnoredXPathFoundInDocInstance="false">gml32:boundedBy</XPath>
+        <XPath>gml:priorityLocation</XPath>
+        <XPath>gml32:priorityLocation</XPath>
+        <XPath>gml32:descriptionReference/@owns</XPath>
+        <XPath>@xlink:show</XPath>
+        <XPath>@xlink:type</XPath>
+        <XPath>@xlink:role</XPath>
+        <XPath>@xlink:arcrole</XPath>
+        <XPath>@xlink:actuate</XPath>
+        <XPath>@gml:remoteSchema</XPath>
+        <XPath>@gml32:remoteSchema</XPath>
+        <XPath>swe:Quantity/swe:extension</XPath>
+        <XPath>swe:Quantity/@referenceFrame</XPath>
+        <XPath>swe:Quantity/@axisID</XPath>
+        <XPath>swe:Quantity/@updatable</XPath>
+        <XPath>swe:Quantity/@optional</XPath>
+        <XPath>swe:Quantity/@id</XPath>
+        <XPath>swe:Quantity/swe:identifier</XPath>
+        <XPath>swe:Quantity/@definition</XPath>
+        <XPath>swe:Quantity/swe:label</XPath>
+        <XPath>swe:Quantity/swe:nilValues</XPath>
+        <XPath>swe:Quantity/swe:constraint</XPath>
+        <XPath>swe:Quantity/swe:quality</XPath>
+        <XPath>swe:Quantity/swe:extension</XPath>
+    </IgnoredXPaths>
+
+    <!-- Section for GMLAS writer config -->
+    <WriterConfig>
+        <IndentationSize>2</IndentationSize>
+        <Comment/>
+        <LineFormat>NATIVE</LineFormat>
+        <SRSNameFormat>OGC_URL</SRSNameFormat>
+        <Wrapping>WFS2_FEATURECOLLECTION</Wrapping>
+        <!-- <Timestamp></Timestamp> -->
+        <WFS20SchemaLocation>http://schemas.opengis.net/wfs/2.0/wfs.xsd</WFS20SchemaLocation>
+    </WriterConfig>
+
+</Configuration>
diff --git a/data/gmlasconf.xsd b/data/gmlasconf.xsd
new file mode 100644
index 0000000..aee082a
--- /dev/null
+++ b/data/gmlasconf.xsd
@@ -0,0 +1,1041 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL/OGR
+ * Purpose:  XML Schema for gmlasconf.xml
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ **********************************************************************
+ * Copyright (c) 2016, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           elementFormDefault="qualified" version="1.0">
+  <xs:element name="Configuration">
+    <xs:annotation>
+        <xs:documentation>
+            Configuration of GMLAS driver.
+        </xs:documentation>
+    </xs:annotation>
+
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="AllowRemoteSchemaDownload" minOccurs="0"
+                    type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>
+                Whether downloading remote schemas is allowed. Default is true.
+            </xs:documentation>
+          </xs:annotation>
+        </xs:element>
+        <xs:element name="SchemaCache" minOccurs="0">
+          <xs:annotation>
+            <xs:documentation>
+                Describe working of schema cache.
+            </xs:documentation>
+          </xs:annotation>
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="Directory" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                  <xs:documentation>
+                    Name of the cache directory. If not specified, this
+                    defaults to $HOME/.gdal/gmlas_xsd_cache.
+                    Ignored if 'enabled' is not true.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+            </xs:sequence>
+            <xs:attribute name="enabled" type="xs:boolean">
+              <xs:annotation>
+                <xs:documentation>
+                        Whether the cache is enabled. Default is true.
+                    </xs:documentation>
+              </xs:annotation>
+            </xs:attribute>
+          </xs:complexType>
+        </xs:element>
+
+        <xs:element name="SchemaAnalysisOptions" minOccurs="0">
+          <xs:annotation>
+            <xs:documentation>
+                Describe option that affect the Xerces schema parser.
+            </xs:documentation>
+          </xs:annotation>
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="SchemaFullChecking" minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether to enable full schema constraint checking, including checking
+                    which may be time-consuming or memory intensive. Currently,
+                    particle unique attribution constraint checking and particle
+                    derivation restriction checking are controlled by this option.
+                    Defaults to true.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+              <xs:element name="HandleMultipleImports" minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether to allow multiple schemas with the same namespace
+                    to be imported.
+                    Defaults to false.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+
+        <xs:element name="Validation" minOccurs="0">
+          <xs:annotation>
+            <xs:documentation>
+                Describe if and how validation of the document against the
+                schema is done.
+            </xs:documentation>
+          </xs:annotation>
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="FailIfError" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether a validation error should prevent dataset
+                    opening.
+                    Ignored if 'enabled' is not true.
+                    Default is false.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+            </xs:sequence>
+            <xs:attribute name="enabled" type="xs:boolean">
+              <xs:annotation>
+                <xs:documentation>
+                  Whether validation is enabled. Default is false.
+                </xs:documentation>
+              </xs:annotation>
+            </xs:attribute>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="ExposeMetadataLayers" minOccurs="0" type="xs:boolean">
+          <xs:annotation>
+            <xs:documentation>
+                Whether the _ogr_layers_metadata, _ogr_fields_metadata and
+                _ogr_layer_relationships layers that show how OGR layers and
+                fields are built from the schemas should be exposed as
+                available layers.
+                Default is false.
+            </xs:documentation>
+          </xs:annotation>
+        </xs:element>
+
+        <xs:element name="LayerBuildingRules" minOccurs="0">
+          <xs:annotation>
+            <xs:documentation>
+                Tunable rules that affect how layers and fields are built from
+                the schema.
+            </xs:documentation>
+          </xs:annotation>
+          <xs:complexType>
+            <xs:sequence>
+
+              <xs:element name="AlwaysGenerateOGRId" minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether a 'ogr_pkid' attribute should always be generated,
+                    even if the underlying XML element has a required attribute
+                    of type ID. Turning it to true can be useful if the
+                    uniqueness of such attributes is not trused.
+                    Default is false.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="RemoveUnusedLayers" minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether to remove any OGR layer without any feature, during the
+                    initial scan pass.
+                    Default is false.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="RemoveUnusedFields" minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether to remove any unused OGR field, during the
+                    initial scan pass.
+                    Default is false.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="UseArrays" minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether OGR array types (StringList, IntegerList,
+                    Integer64List and RealList) can be used to store
+                    repeated values of the corresponding base types.
+                    Default is true.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="UseNullState" minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether xsi:nil="true" should be mapped from/to the OGR
+                    null field state (new in GDAL 2.2). If set to false, then
+                    a XXX_nil field will be added when necessary. If set to true,
+                    then unset and null states are used (but this is not very
+                    convenient when converting to SQL databases where both states
+                    are equivalent).
+                    Default is false.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="GML" minOccurs="0">
+                <xs:annotation>
+                  <xs:documentation>
+                    Settings specific to documents that import the GML namespace.
+                  </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="IncludeGeometryXML" minOccurs="0"
+                                type="xs:boolean">
+                      <xs:annotation>
+                        <xs:documentation>
+                          Whether the XML description of a GML geometry should
+                          be stored in a string attribute (whose name is the
+                          element name suffixed by _xml). This is in addition
+                          to storing the geometry as a OGR geometry.
+                          Default is false.
+                         </xs:documentation>
+                      </xs:annotation>
+                    </xs:element>
+                    <xs:element name="InstantiateGMLFeaturesOnly" minOccurs="0"
+                                type="xs:boolean">
+                      <xs:annotation>
+                        <xs:documentation>
+                          Whether, when dealing with schemas that import the
+                          GML namespace, and that at least one of them has
+                          elements that derive from gml:_Feature or
+                          gml:AbstractFeatureonly, only such elements should be
+                          instantiated as OGR layers, during the first pass that
+                          iterates over top level elements of the imported
+                          schemas.
+                          Note: for technical reasons, other elements may end
+                          up being exposed as OGR layers, but this setting
+                          is a first way of limiting the number of OGR layers.
+                          Default is true.
+                         </xs:documentation>
+                      </xs:annotation>
+                    </xs:element>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+
+              <xs:element name="IdentifierMaxLength" minOccurs="0">
+                <xs:annotation>
+                  <xs:documentation>
+                    Maximum size of layer and field identifiers. If identifiers
+                    are naturally bigger than the limit, a logic truncates
+                    them while ensuring their unicity.
+                    When absent, unlimited size.
+                  </xs:documentation>
+                </xs:annotation>
+                <xs:simpleType>
+                    <xs:restriction base="xs:positiveInteger">
+                        <xs:minInclusive value="10"/>
+                    </xs:restriction>
+                </xs:simpleType>
+              </xs:element>
+
+              <xs:element name="CaseInsensitiveIdentifier" minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether layer and field names should be consider equal in a
+                    case insensitive way. This is important for conversion to
+                    Postgres when identifiers are laundered in lower case
+                    Default is true.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="PostgreSQLIdentifierLaundering" minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Whether layer and field names should be laundered like the
+                    OGR PostgreSQL driver does by default, ie identifiers put
+                    in lower cases and a few special characters( single quote,
+                    dash, sharp) replaced by underscore. This can help to post-
+                    process the _ogr_layer_relationships layers more easily or,
+                    for write support.
+                    Note: this laundering is safe for other backends as well.
+                    Default is true.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="FlatteningRules" minOccurs="0">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="MaximumNumberOfFields" type="xs:int" minOccurs="0">
+                      <xs:annotation>
+                        <xs:documentation>
+                            Maximum number of fields in an element considered
+                            for flattening.
+                            Default is 10.
+                        </xs:documentation>
+                      </xs:annotation>
+                    </xs:element>
+                    <xs:element name="Namespaces" type="namespacesType" minOccurs="0"/>
+                    <xs:element name="ForceFlatteningXPath" type="xs:string" minOccurs="0" maxOccurs="unbounded">
+                      <xs:annotation>
+                        <xs:documentation>
+                            XPath of element that will be considered for flattening
+                            even if it has more than MaximumNumberOfFields fields.
+                            Note: other constraints might make it impossible to
+                            flatten it, for example if it has repeated elements.
+                        </xs:documentation>
+                      </xs:annotation>
+                    </xs:element>
+                    <xs:element name="DisableFlatteningXPath" type="xs:string" minOccurs="0" maxOccurs="unbounded">
+                      <xs:annotation>
+                        <xs:documentation>
+                            XPath of element that will NOT be considered for flattening
+                            even if it has less or MaximumNumberOfFields fields.
+                        </xs:documentation>
+                      </xs:annotation>
+                    </xs:element>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+
+              <xs:element name="SWEProcessing" minOccurs="0">
+                <xs:annotation>
+                    <xs:documentation>
+                        Configuration of special processing for elements in
+                        the http://www.opengis.net/swe/2.0 namespace.
+                    </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="Activation" minOccurs="0">
+                      <xs:annotation>
+                        <xs:documentation>
+                            If and how SWE processing is enabled.
+                            Default is ifSWENamespaceFoundInTopElement.
+                        </xs:documentation>
+                      </xs:annotation>
+                      <xs:simpleType>
+                        <xs:restriction base="xs:string">
+                            <xs:enumeration value="ifSWENamespaceFoundInTopElement">
+                                <xs:annotation>
+                                    <xs:documentation>
+                                        If the http://www.opengis.net/swe/2.0
+                                        namespace is found, SWE special
+                                        processing will be enabled.
+                                    </xs:documentation>
+                                </xs:annotation>
+                            </xs:enumeration>
+                            <xs:enumeration value="true"/>
+                            <xs:enumeration value="false"/>
+                        </xs:restriction>
+                      </xs:simpleType>
+                    </xs:element>
+                    <xs:element name="ProcessDataArray" type="xs:boolean"
+                                minOccurs="0" maxOccurs="unbounded">
+                      <xs:annotation>
+                        <xs:documentation>
+                            If swe:DataArray must be parsed. Default is tru.
+                        </xs:documentation>
+                      </xs:annotation>
+                    </xs:element>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+
+
+        <xs:element name="TypingConstraints" minOccurs="0">
+          <xs:annotation>
+            <xs:documentation>
+                Constraints to specify the types of children of elements of
+                type xs:anyType.
+            </xs:documentation>
+          </xs:annotation>
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="Namespaces" type="namespacesType" minOccurs="0"/>
+
+              <xs:element name="ChildConstraint" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                  <xs:sequence>
+                    <xs:element name="ContainerXPath" type="xs:string"/>
+                    <xs:element name="ChildrenElements" maxOccurs="unbounded">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="Element" type="xs:string" maxOccurs="unbounded"/>
+                        </xs:sequence>
+                    </xs:complexType>
+                    </xs:element>
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+
+        <xs:element name="XLinkResolution" minOccurs="0">
+          <xs:annotation>
+            <xs:documentation>
+                Rules regarding resolution of xlink:href attributes
+            </xs:documentation>
+          </xs:annotation>
+          <xs:complexType>
+            <xs:sequence>
+
+              <xs:element name="Timeout" minOccurs="0" type="xs:positiveInteger">
+                <xs:annotation>
+                  <xs:documentation>
+                    Timeout in seconds for resolving a HTTP resource.
+                    Default: no timeout or value of GDAL_HTTP_TIMEOUT
+                    configuration option.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="MaxGlobalResolutionTime" minOccurs="0"
+                          type="xs:positiveInteger">
+                <xs:annotation>
+                  <xs:documentation>
+                    Maximum allowed time for resolving all XLinks in a single
+                    document.
+                    Default: none
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="MaxFileSize" minOccurs="0">
+                <xs:annotation>
+                  <xs:documentation>
+                    Maximum file size allowed. 
+                    Default: 1 MB.
+                  </xs:documentation>
+                </xs:annotation>
+                <xs:simpleType>
+                    <xs:union memberTypes="xs:positiveInteger unlimitedEnumType"/>
+                </xs:simpleType>
+              </xs:element>
+
+              <xs:element name="ProxyServerPort" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                  <xs:documentation>
+                    Name and port of proxy server (server:port syntax)
+                    Default: none or value of GDAL_HTTP_PROXY
+                    configuration option.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="ProxyUserPassword" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                  <xs:documentation>
+                    User name and password to use for proxy server
+                    (username:password syntax)
+                    Default: none or value of GDAL_HTTP_PROXYUSERPW
+                    configuration option.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="ProxyAuth" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                  <xs:documentation>
+                    Proxy authentification method: one of Basic, NTLM, Digest
+                    or Any.
+                    Default: none or value of GDAL_PROXY_AUTH
+                    configuration option.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="CacheDirectory" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                  <xs:documentation>
+                    Name of the cache directory for resolved documents.
+                    If not specified, this defaults to $HOME/.gdal/gmlas_xlink_resolution_cache.
+                    The cache is only used if enabled in DefaultResolution or
+                    particular URLSpecificResolution rules.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="DefaultResolution" minOccurs="0">
+                <xs:annotation>
+                   <xs:documentation>
+                    Default rules that apply for all URLs that are not referenced
+                    by a dedicated URLSpecificResolution rule.
+                   </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                  <xs:sequence>
+
+                    <xs:element name="AllowRemoteDownload" minOccurs="0"
+                                type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation>
+                            Whether downloading remote resources is allowed.
+                            If false, only locally cached resources will be used.
+                            Default is true.
+                        </xs:documentation>
+                    </xs:annotation>
+                    </xs:element>
+
+                    <xs:element name="ResolutionMode" minOccurs="0">
+                      <xs:annotation>
+                        <xs:documentation>
+                            Resolution mode. Must be XMLRawContent currently
+                        </xs:documentation>
+                      </xs:annotation>
+                      <xs:simpleType>
+                        <xs:restriction base="xs:string">
+                            <xs:enumeration value="RawContent">
+                                <xs:annotation>
+                                    <xs:documentation>
+                                        The content, provided it is of text
+                                        nature, is set in a field suffixed with
+                                        _raw
+                                    </xs:documentation>
+                                </xs:annotation>
+                            </xs:enumeration>
+                        </xs:restriction>
+                      </xs:simpleType>
+                   </xs:element>
+
+                    <xs:element name="ResolutionDepth" minOccurs="0">
+                      <xs:annotation>
+                        <xs:documentation>
+                            Resolution depth. Must be 1 currently.
+                        </xs:documentation>
+                      </xs:annotation>
+                      <xs:simpleType>
+                        <xs:restriction base="xs:nonNegativeInteger">
+                            <xs:minInclusive value="1"/>
+                            <xs:maxInclusive value="1"/>
+                        </xs:restriction>
+                      </xs:simpleType>
+                   </xs:element>
+
+                    <xs:element name="CacheResults" minOccurs="0" type="xs:boolean">
+                      <xs:annotation>
+                        <xs:documentation>
+                            Whether resolved documents should be cached.
+                            Default is false.
+                        </xs:documentation>
+                      </xs:annotation>
+                   </xs:element>
+
+                  </xs:sequence>
+
+                  <xs:attribute name="enabled" type="xs:boolean">
+                    <xs:annotation>
+                      <xs:documentation>
+                        Whether default XLink resolution is enabled.
+                        Default is false.
+                      </xs:documentation>
+                    </xs:annotation>
+                  </xs:attribute>
+
+                </xs:complexType>
+              </xs:element>
+
+              <xs:element name="URLSpecificResolution" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation>
+                   <xs:documentation>
+                    Particular rule that apply for all URLs starting with
+                    a precise prefix. Setting at least one URLSpecificResolution will cause
+                    a compulsory initial scan of the whole file to be done so
+                    as to identify which xlink:href fields use which URL, so as
+                    to create the relevant OGR fields.
+                   </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                  <xs:sequence>
+
+                    <xs:element name="URLPrefix" minOccurs="0" type="xs:anyURI">
+                      <xs:annotation>
+                        <xs:documentation>
+                            URL prefix. All URLs starting with this string will
+                            match this rule.
+                        </xs:documentation>
+                      </xs:annotation>
+                   </xs:element>
+
+                    <xs:element name="HTTPHeader" minOccurs="0" maxOccurs="unbounded">
+                      <xs:annotation>
+                        <xs:documentation>
+                            Custom HTTP header to send in the GET request.
+                        </xs:documentation>
+                      </xs:annotation>
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="Name" type="xs:string">
+                            <xs:annotation>
+                              <xs:documentation>
+                                 HTTP header name
+                              </xs:documentation>
+                            </xs:annotation>
+                          </xs:element>
+                          <xs:element name="Value" type="xs:string">
+                            <xs:annotation>
+                              <xs:documentation>
+                                 HTTP header value
+                              </xs:documentation>
+                            </xs:annotation>
+                          </xs:element>
+                        </xs:sequence>
+                      </xs:complexType>
+                   </xs:element>
+
+                    <xs:element name="AllowRemoteDownload" minOccurs="0"
+                                type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation>
+                            Whether downloading remote resources is allowed.
+                            If false, only locally cached resources will be used.
+                            Default is true.
+                        </xs:documentation>
+                    </xs:annotation>
+                    </xs:element>
+
+                    <xs:element name="ResolutionMode" minOccurs="0">
+                      <xs:annotation>
+                        <xs:documentation>
+                            Resolution mode.
+                            Default is RawContent.
+                        </xs:documentation>
+                      </xs:annotation>
+                      <xs:simpleType>
+                        <xs:restriction base="xs:string">
+                            <xs:enumeration value="RawContent">
+                                <xs:annotation>
+                                    <xs:documentation>
+                                        The content, provided it is of text
+                                        nature, is set in a field suffixed with
+                                        _rawcontent
+                                    </xs:documentation>
+                                </xs:annotation>
+                            </xs:enumeration>
+                            <xs:enumeration value="FieldsFromXPath">
+                                <xs:annotation>
+                                    <xs:documentation>
+                                        The content, assumed to be XML, will be
+                                        parsed and fields specified with Field
+                                        created.
+                                    </xs:documentation>
+                                </xs:annotation>
+                            </xs:enumeration>
+                        </xs:restriction>
+                      </xs:simpleType>
+                   </xs:element>
+
+                    <xs:element name="ResolutionDepth" minOccurs="0">
+                      <xs:annotation>
+                        <xs:documentation>
+                            Resolution depth. Must be 1 currently.
+                        </xs:documentation>
+                      </xs:annotation>
+                      <xs:simpleType>
+                        <xs:restriction base="xs:nonNegativeInteger">
+                            <xs:minInclusive value="1"/>
+                            <xs:maxInclusive value="1"/>
+                        </xs:restriction>
+                      </xs:simpleType>
+                   </xs:element>
+
+                    <xs:element name="CacheResults" minOccurs="0" type="xs:boolean">
+                      <xs:annotation>
+                        <xs:documentation>
+                            Whether resolved documents should be cached.
+                            Default is false.
+                        </xs:documentation>
+                      </xs:annotation>
+                   </xs:element>
+
+                    <xs:element name="Field" minOccurs="0" maxOccurs="unbounded">
+                      <xs:annotation>
+                        <xs:documentation>
+                            Field to create from parsed XML content. Only used
+                            if ResolutionMode = FieldsFromXPath
+                        </xs:documentation>
+                      </xs:annotation>
+                      <xs:complexType>
+                        <xs:sequence>
+                          <xs:element name="Name" type="xs:string">
+                            <xs:annotation>
+                              <xs:documentation>
+                                 Field name
+                              </xs:documentation>
+                            </xs:annotation>
+                          </xs:element>
+                          <xs:element name="Type">
+                            <xs:annotation>
+                              <xs:documentation>
+                                 Field type
+                              </xs:documentation>
+                            </xs:annotation>
+                            <xs:simpleType>
+                                <xs:restriction base="xs:string">
+                                    <xs:enumeration value="string"/>
+                                    <xs:enumeration value="integer"/>
+                                    <xs:enumeration value="long"/>
+                                    <xs:enumeration value="double"/>
+                                    <xs:enumeration value="dateTime"/>
+                                </xs:restriction>
+                            </xs:simpleType>
+                          </xs:element>
+                          <xs:element name="XPath" type="xs:string">
+                            <xs:annotation>
+                              <xs:documentation>
+                                 XPath from the root of the resolved document
+                                 from which to extract the value of the field.
+                                Only a restricted subset of the full XPath 1.0
+                                syntax is supported, namely the abbreviated syntax
+                                with the '//' and '@' axis specifiers.
+                                Valid XPath are for example:
+                                - [ns1:]foo/[ns2:]bar: matches a bar element as a
+                                    direct child of a foo element, foo being at any
+                                    nesting level in the compared XPath.
+                                - [ns1:foo]/@[ns2:]baz: matches a baz attribute of a
+                                    foo element, foo being at any nesting level in
+                                    the compared XPath
+                                - [ns1:]foo//[ns2:]bar: matches a bar element as a
+                                    direct or indirect child of a foo element,
+                                    foo being at any nesting level in the compared
+                                    XPath.
+                                - /[ns1:]foo/[ns2:]bar: matches a bar element as a
+                                    direct child of a foo element, foo being at the
+                                    root level.
+                              </xs:documentation>
+                            </xs:annotation>
+                          </xs:element>
+                        </xs:sequence>
+                      </xs:complexType>
+                   </xs:element>
+
+                  </xs:sequence>
+                </xs:complexType>
+              </xs:element>
+
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+
+        <xs:element name="IgnoredXPaths" minOccurs="0">
+          <xs:annotation>
+            <xs:documentation>
+                Define elements and attributes that will be ignored when
+                building OGR layer and field definitions.
+            </xs:documentation>
+          </xs:annotation>
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="WarnIfIgnoredXPathFoundInDocInstance"
+                          minOccurs="0" type="xs:boolean">
+                <xs:annotation>
+                  <xs:documentation>
+                    Emit a warning each time an element or attribute is
+                    found in the document parsed, but ignored because
+                    of the ignored XPath defined.
+                    Default is true.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+              <xs:element name="Namespaces" type="namespacesType" minOccurs="0"/>
+              <xs:element name="XPath" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation>
+                  <xs:documentation>
+                    A XPath against which elements and attributes found
+                    during schema analysis will be compared. If the
+                    XPath of the element/attribute of the schema
+                    matches this XPath, it will be ignored.
+                    Only a restricted subset of the full XPath 1.0
+                    syntax is supported, namely the abbreviated syntax
+                    with the '//' and '@' axis specifiers.
+                    Valid XPath are for example:
+                    - [ns1:]foo/[ns2:]bar: matches a bar element as a
+                        direct child of a foo element, foo being at any
+                        nesting level in the compared XPath.
+                    - [ns1:foo]/@[ns2:]baz: matches a baz attribute of a
+                        foo element, foo being at any nesting level in
+                        the compared XPath
+                    - [ns1:]foo//[ns2:]bar: matches a bar element as a
+                        direct or indirect child of a foo element,
+                        foo being at any nesting level in the compared
+                        XPath.
+                    - /[ns1:]foo/[ns2:]bar: matches a bar element as a
+                        direct child of a foo element, foo being at the
+                        root level.
+                  </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                  <xs:simpleContent>
+                    <xs:extension base="xs:string">
+                      <xs:attribute name="warnIfIgnoredXPathFoundInDocInstance"
+                                    type="xs:boolean">
+                        <xs:annotation>
+                          <xs:documentation>
+                            Emit a warning each time an element or attribute is
+                            found in the document parsed, but ignored because
+                            of the ignored XPath defined.
+                            Override the global setting of the
+                            WarnIfIgnoredXPathFoundInDocInstance element
+                            Default is true.
+                          </xs:documentation>
+                        </xs:annotation>
+                      </xs:attribute>
+                    </xs:extension>
+                  </xs:simpleContent>
+                </xs:complexType>
+              </xs:element>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+
+        <xs:element name="WriterConfig" minOccurs="0">
+          <xs:annotation>
+            <xs:documentation>Configuration of GMLAS writer
+            </xs:documentation>
+          </xs:annotation>
+          <xs:complexType>
+            <xs:sequence>
+
+              <xs:element name="IndentationSize" minOccurs="0">
+                <xs:annotation>
+                  <xs:documentation>
+                    Number of spaces used to indent each level of nesting in
+                    XML ouput.
+                    Default is 2.
+                  </xs:documentation>
+                </xs:annotation>
+                <xs:simpleType>
+                    <xs:restriction base="xs:nonNegativeInteger">
+                        <xs:maxInclusive value="8"/>
+                    </xs:restriction>
+                </xs:simpleType>
+              </xs:element>
+
+              <xs:element name="Comment" type="xs:string" minOccurs="0">
+                <xs:annotation>
+                  <xs:documentation>
+                    Comment to add at top of output XML file.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="LineFormat" minOccurs="0">
+                <xs:annotation>
+                  <xs:documentation>
+                    Line format.
+                    Default is platform dependant (CR-LF on Windows, LF otherwise)
+                  </xs:documentation>
+                </xs:annotation>
+                <xs:simpleType>
+                    <xs:restriction base="xs:string">
+                        <xs:enumeration value="NATIVE">
+                            <xs:annotation>
+                                <xs:documentation>
+                                    Platform dependant (CR-LF on Windows, LF otherwise)
+                                </xs:documentation>
+                            </xs:annotation>
+                        </xs:enumeration>
+                        <xs:enumeration value="CRLF">
+                            <xs:annotation>
+                                <xs:documentation>
+                                    Windows end-of-line style : CR-LF
+                                </xs:documentation>
+                            </xs:annotation>
+                        </xs:enumeration>
+                        <xs:enumeration value="FieldsFromXPath">
+                            <xs:annotation>
+                                <xs:documentation>
+                                    Unix end-of-line style: LF
+                                </xs:documentation>
+                            </xs:annotation>
+                        </xs:enumeration>
+                    </xs:restriction>
+                </xs:simpleType>
+              </xs:element>
+
+              <xs:element name="SRSNameFormat" minOccurs="0">
+                <xs:annotation>
+                  <xs:documentation>
+                    Format to use for srsName attributes on geometries.
+                    Default is OGC_URL.
+                  </xs:documentation>
+                </xs:annotation>
+                <xs:simpleType>
+                    <xs:restriction base="xs:string">
+                        <xs:enumeration value="SHORT">
+                            <xs:annotation>
+                                <xs:documentation>
+srsName will be in the form AUTHORITY_NAME:AUTHORITY_CODE
+                                </xs:documentation>
+                            </xs:annotation>
+                        </xs:enumeration>
+                        <xs:enumeration value="OGC_URN">
+                            <xs:annotation>
+                                <xs:documentation>
+srsName will be in the form urn:ogc:def:crs:AUTHORITY_NAME::AUTHORITY_CODE
+                                </xs:documentation>
+                            </xs:annotation>
+                        </xs:enumeration>
+                        <xs:enumeration value="OGC_URL">
+                            <xs:annotation>
+                                <xs:documentation>
+ssrsName will be in the form http://www.opengis.net/def/crs/AUTHORITY_NAME/0/AUTHORITY_CODE
+                                </xs:documentation>
+                            </xs:annotation>
+                        </xs:enumeration>
+                    </xs:restriction>
+                </xs:simpleType>
+              </xs:element>
+
+              <xs:element name="Wrapping" minOccurs="0">
+                <xs:annotation>
+                  <xs:documentation>
+                    How to wrap features in a collection.
+                    Default is WFS2_FEATURECOLLECTION
+                  </xs:documentation>
+                </xs:annotation>
+                <xs:simpleType>
+                    <xs:restriction base="xs:string">
+                        <xs:enumeration value="WFS2_FEATURECOLLECTION">
+                            <xs:annotation>
+                                <xs:documentation>
+Use wfs:FeatureCollection / wfs:member wrapping
+                                </xs:documentation>
+                            </xs:annotation>
+                        </xs:enumeration>
+                        <xs:enumeration value="GMLAS_FEATURECOLLECTION">
+                            <xs:annotation>
+                                <xs:documentation>
+Use ogr_gmlas:FeatureCollection / ogr_gmlas:featureMember wrapping
+                                </xs:documentation>
+                            </xs:annotation>
+                        </xs:enumeration>
+                    </xs:restriction>
+                </xs:simpleType>
+              </xs:element>
+
+              <xs:element name="Timestamp" minOccurs="0" type="xs:dateTime">
+                <xs:annotation>
+                  <xs:documentation>
+                    User-specified XML dateTime value for timestamp to use in
+                    wfs:FeatureCollection attribute.
+                    Only valid for WRAPPING=WFS2_FEATURECOLLECTION.
+                    Default is current date-time.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+              <xs:element name="WFS20SchemaLocation" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                  <xs:documentation>
+                    Path or URL to OGC WFS 2.0 schema.
+                    Only valid for WRAPPING=WFS2_FEATURECOLLECTION.
+                    Default is http://schemas.opengis.net/wfs/2.0/wfs.xsd.
+                  </xs:documentation>
+                </xs:annotation>
+              </xs:element>
+
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+
+  <xs:simpleType name="unlimitedEnumType">
+    <xs:restriction base="xs:string">
+        <xs:enumeration value="unlimited"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="namespacesType">
+    <xs:annotation>
+        <xs:documentation>
+        Define optional namespaces prefix/uri tuples with
+        which to interpret the XPath elements defined
+        afterwards.
+        This allows the user to define different rules when
+        different namespaces in different XML instances map
+        to the same prefix. E.g documents referencing
+        different GML versions may use "gml" as
+        a prefix for "http://www.opengis.net/gml" or
+        "http://www.opengis.net/gml/3.2", but it might be
+        desirable to have different exclusion rules.
+        When comparing the XPath exclusion rules and the
+        XPath of the elements/attributes of the parsed
+        documents, and when the namespace of the XPath
+        exclusion rule has been difined, the URI will be
+        used as the unambiguous key. Otherwise prefix
+        matching will be used.
+        </xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+        <xs:element name="Namespace" minOccurs="0" maxOccurs="unbounded">
+            <xs:annotation>
+            <xs:documentation>
+                Define a namespaces prefix/uri tuple with
+                which to interpret the XPath elements
+                defined afterwards.
+            </xs:documentation>
+            </xs:annotation>
+            <xs:complexType>
+            <xs:sequence/>
+            <xs:attribute name="prefix" type="xs:string" use="required">
+                <xs:annotation>
+                <xs:documentation>Namespace prefix.</xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="uri" type="xs:string" use="required">
+                <xs:annotation>
+                <xs:documentation>Namespace URI.</xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            </xs:complexType>
+        </xs:element>
+     </xs:sequence>
+  </xs:complexType>
+
+</xs:schema>
diff --git a/data/jpfgdgml_AdmArea.gfs b/data/jpfgdgml_AdmArea.gfs
new file mode 100644
index 0000000..00ff305
--- /dev/null
+++ b/data/jpfgdgml_AdmArea.gfs
@@ -0,0 +1,59 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>AdmArea</Name>
+    <ElementPath>AdmArea</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>area</GeometryElementPath>
+    <GeometryType>Polygon</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>admCode</Name>
+      <ElementPath>admCode</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_AdmBdry.gfs b/data/jpfgdgml_AdmBdry.gfs
new file mode 100644
index 0000000..fda5918
--- /dev/null
+++ b/data/jpfgdgml_AdmBdry.gfs
@@ -0,0 +1,49 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>AdmBdry</Name>
+    <ElementPath>AdmBdry</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_AdmPt.gfs b/data/jpfgdgml_AdmPt.gfs
new file mode 100644
index 0000000..13717e0
--- /dev/null
+++ b/data/jpfgdgml_AdmPt.gfs
@@ -0,0 +1,59 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>AdmPt</Name>
+    <ElementPath>AdmPt</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>pos</GeometryElementPath>
+    <GeometryType>Point</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>admCode</Name>
+      <ElementPath>admCode</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_BldA.gfs b/data/jpfgdgml_BldA.gfs
new file mode 100644
index 0000000..fac2433
--- /dev/null
+++ b/data/jpfgdgml_BldA.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>BldA</Name>
+    <ElementPath>BldA</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>area</GeometryElementPath>
+    <GeometryType>Polygon</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_BldL.gfs b/data/jpfgdgml_BldL.gfs
new file mode 100644
index 0000000..5b8f9ce
--- /dev/null
+++ b/data/jpfgdgml_BldL.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>BldL</Name>
+    <ElementPath>BldL</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_Cntr.gfs b/data/jpfgdgml_Cntr.gfs
new file mode 100644
index 0000000..a06ee67
--- /dev/null
+++ b/data/jpfgdgml_Cntr.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>Cntr</Name>
+    <ElementPath>Cntr</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>alti</Name>
+      <ElementPath>alti</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_CommBdry.gfs b/data/jpfgdgml_CommBdry.gfs
new file mode 100644
index 0000000..ac865f5
--- /dev/null
+++ b/data/jpfgdgml_CommBdry.gfs
@@ -0,0 +1,49 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>CommBdry</Name>
+    <ElementPath>CommBdry</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_CommPt.gfs b/data/jpfgdgml_CommPt.gfs
new file mode 100644
index 0000000..425b587
--- /dev/null
+++ b/data/jpfgdgml_CommPt.gfs
@@ -0,0 +1,59 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>CommPt</Name>
+    <ElementPath>CommPt</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>pos</GeometryElementPath>
+    <GeometryType>Point</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>admCode</Name>
+      <ElementPath>admCode</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_Cstline.gfs b/data/jpfgdgml_Cstline.gfs
new file mode 100644
index 0000000..4cca3f2
--- /dev/null
+++ b/data/jpfgdgml_Cstline.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>Cstline</Name>
+    <ElementPath>Cstline</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_ElevPt.gfs b/data/jpfgdgml_ElevPt.gfs
new file mode 100644
index 0000000..970fbe6
--- /dev/null
+++ b/data/jpfgdgml_ElevPt.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>ElevPt</Name>
+    <ElementPath>ElevPt</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>pos</GeometryElementPath>
+    <GeometryType>Point</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>alti</Name>
+      <ElementPath>alti</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_GCP.gfs b/data/jpfgdgml_GCP.gfs
new file mode 100644
index 0000000..a3cf4ef
--- /dev/null
+++ b/data/jpfgdgml_GCP.gfs
@@ -0,0 +1,94 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>GCP</Name>
+    <ElementPath>GCP</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>pos</GeometryElementPath>
+    <GeometryType>Point</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>advNo</Name>
+      <ElementPath>advNo</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgName</Name>
+      <ElementPath>orgName</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>gcpClass</Name>
+      <ElementPath>gcpClass</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>gcpCode</Name>
+      <ElementPath>gcpCode</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>B</Name>
+      <ElementPath>B</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>L</Name>
+      <ElementPath>L</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>alti</Name>
+      <ElementPath>alti</ElementPath>
+      <Type>Real</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>altiAcc</Name>
+      <ElementPath>altiAcc</ElementPath>
+      <Type>Integer</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_LeveeEdge.gfs b/data/jpfgdgml_LeveeEdge.gfs
new file mode 100644
index 0000000..7263fa1
--- /dev/null
+++ b/data/jpfgdgml_LeveeEdge.gfs
@@ -0,0 +1,49 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>LeveeEdge</Name>
+    <ElementPath>LeveeEdge</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_RailCL.gfs b/data/jpfgdgml_RailCL.gfs
new file mode 100644
index 0000000..e1ec070
--- /dev/null
+++ b/data/jpfgdgml_RailCL.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>RailCL</Name>
+    <ElementPath>RailCL</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_RdASL.gfs b/data/jpfgdgml_RdASL.gfs
new file mode 100644
index 0000000..1b413d3
--- /dev/null
+++ b/data/jpfgdgml_RdASL.gfs
@@ -0,0 +1,44 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>RdASL</Name>
+    <ElementPath>RdASL</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_RdArea.gfs b/data/jpfgdgml_RdArea.gfs
new file mode 100644
index 0000000..9c242b3
--- /dev/null
+++ b/data/jpfgdgml_RdArea.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>RdArea</Name>
+    <ElementPath>RdArea</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>area</GeometryElementPath>
+    <GeometryType>Polygon</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>admOffice</Name>
+      <ElementPath>admOffice</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_RdCompt.gfs b/data/jpfgdgml_RdCompt.gfs
new file mode 100644
index 0000000..4af814d
--- /dev/null
+++ b/data/jpfgdgml_RdCompt.gfs
@@ -0,0 +1,59 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>RdCompt</Name>
+    <ElementPath>RdCompt</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>admOffice</Name>
+      <ElementPath>admOffice</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_RdEdg.gfs b/data/jpfgdgml_RdEdg.gfs
new file mode 100644
index 0000000..b43a96c
--- /dev/null
+++ b/data/jpfgdgml_RdEdg.gfs
@@ -0,0 +1,59 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>RdEdg</Name>
+    <ElementPath>RdEdg</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>admOffice</Name>
+      <ElementPath>admOffice</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_RdMgtBdry.gfs b/data/jpfgdgml_RdMgtBdry.gfs
new file mode 100644
index 0000000..de5eaf4
--- /dev/null
+++ b/data/jpfgdgml_RdMgtBdry.gfs
@@ -0,0 +1,49 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>RdMgtBdry</Name>
+    <ElementPath>RdMgtBdry</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_RdSgmtA.gfs b/data/jpfgdgml_RdSgmtA.gfs
new file mode 100644
index 0000000..fbde9b9
--- /dev/null
+++ b/data/jpfgdgml_RdSgmtA.gfs
@@ -0,0 +1,59 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>RdSgmtA</Name>
+    <ElementPath>RdSgmtA</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>area</GeometryElementPath>
+    <GeometryType>Polygon</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>admOffice</Name>
+      <ElementPath>admOffice</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_RvrMgtBdry.gfs b/data/jpfgdgml_RvrMgtBdry.gfs
new file mode 100644
index 0000000..1b25ef7
--- /dev/null
+++ b/data/jpfgdgml_RvrMgtBdry.gfs
@@ -0,0 +1,49 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>RvrMgtBdry</Name>
+    <ElementPath>RvrMgtBdry</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_SBAPt.gfs b/data/jpfgdgml_SBAPt.gfs
new file mode 100644
index 0000000..c396300
--- /dev/null
+++ b/data/jpfgdgml_SBAPt.gfs
@@ -0,0 +1,49 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>SBAPt</Name>
+    <ElementPath>SBAPt</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>pos</GeometryElementPath>
+    <GeometryType>Point</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>sbaNo</Name>
+      <ElementPath>sbaNo</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_SBArea.gfs b/data/jpfgdgml_SBArea.gfs
new file mode 100644
index 0000000..5f351f0
--- /dev/null
+++ b/data/jpfgdgml_SBArea.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>SBArea</Name>
+    <ElementPath>SBArea</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>area</GeometryElementPath>
+    <GeometryType>Polygon</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>sbaNo</Name>
+      <ElementPath>sbaNo</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_SBBdry.gfs b/data/jpfgdgml_SBBdry.gfs
new file mode 100644
index 0000000..ba24e53
--- /dev/null
+++ b/data/jpfgdgml_SBBdry.gfs
@@ -0,0 +1,44 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>SBBdry</Name>
+    <ElementPath>SBBdry</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_WA.gfs b/data/jpfgdgml_WA.gfs
new file mode 100644
index 0000000..9c44233
--- /dev/null
+++ b/data/jpfgdgml_WA.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>WA</Name>
+    <ElementPath>WA</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>area</GeometryElementPath>
+    <GeometryType>Polygon</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_WL.gfs b/data/jpfgdgml_WL.gfs
new file mode 100644
index 0000000..f57fa5a
--- /dev/null
+++ b/data/jpfgdgml_WL.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>WL</Name>
+    <ElementPath>WL</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_WStrA.gfs b/data/jpfgdgml_WStrA.gfs
new file mode 100644
index 0000000..9e3ecb2
--- /dev/null
+++ b/data/jpfgdgml_WStrA.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>WStrA</Name>
+    <ElementPath>WStrA</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>area</GeometryElementPath>
+    <GeometryType>Polygon</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/jpfgdgml_WStrL.gfs b/data/jpfgdgml_WStrL.gfs
new file mode 100644
index 0000000..a5c09da
--- /dev/null
+++ b/data/jpfgdgml_WStrL.gfs
@@ -0,0 +1,54 @@
+<GMLFeatureClassList>
+  <GMLFeatureClass>
+    <Name>WStrL</Name>
+    <ElementPath>WStrL</ElementPath>
+    <SRSName>urn:ogc:def:crs:EPSG::6668</SRSName>
+    <GeometryElementPath>loc</GeometryElementPath>
+    <GeometryType>LineString</GeometryType>
+    <PropertyDefn>
+      <Name>fid</Name>
+      <ElementPath>fid</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanFr</Name>
+      <ElementPath>lfSpanFr|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>lfSpanTo</Name>
+      <ElementPath>lfSpanTo|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>devDate</Name>
+      <ElementPath>devDate|timePosition</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgGILvl</Name>
+      <ElementPath>orgGILvl</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>orgMDId</Name>
+      <ElementPath>orgMDId</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>vis</Name>
+      <ElementPath>vis</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>type</Name>
+      <ElementPath>type</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+    <PropertyDefn>
+      <Name>name</Name>
+      <ElementPath>name</ElementPath>
+      <Type>String</Type>
+    </PropertyDefn>
+  </GMLFeatureClass>
+</GMLFeatureClassList>
diff --git a/data/nitf_spec.xml b/data/nitf_spec.xml
index a9cb273..26d9348 100644
--- a/data/nitf_spec.xml
+++ b/data/nitf_spec.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0"?>
 <!--
 /******************************************************************************
- * $Id: nitf_spec.xml 32488 2015-12-27 08:29:13Z rouault $
+ * $Id: nitf_spec.xml 35539 2016-09-29 12:18:43Z rouault $
  *
  * Project:  NITF Library
  * Purpose:  Description of NITF TREs
@@ -119,12 +119,12 @@
         <field name="L_LINES" length="5" type="integer" minval="1" maxval="99999"/>
         <field name="LAYOVER_ANGLE" length="3" type="integer" minval="0" maxval="359" unit="degrees"/>
         <field name="SHADOW_ANGLE" length="3" type="integer" minval="0" maxval="359" unit="degrees"/>
-        <field length="16"/>
+        <field length="16" fixed_value="                "/>
         <field name="FRLC_LOC" length="21"/>
         <field name="LRLC_LOC" length="21"/>
         <field name="LRFC_LOC" length="21"/>
         <field name="FRFC_LOC" length="21"/>
-        <field length="5"/>
+        <field length="5" fixed_value="010.0"/>
     </tre>
 
     <tre name="BNDPLB" minlength="124" maxlength="99964" location="image">
@@ -274,9 +274,9 @@
     <!-- STDI-0002 Appendix E (ASDE 2.1/CN1), Table E-12 -->
     <tre name="EXPLTB" length="101" location="image">
         <field name="ANGLE_TO_NORTH" length="7" type="real" minval="0.0" maxval="359.999"/>
-        <field name="ANGLE_TO_NORTH_ACCY" length="6" type="real" min="0.0" maxval="44.999"/>
-        <field name="SQUINT_ANGLE" length="7" type="real" min="-60.0" maxval="85.0"/>
-        <field name="SQUINT_ANGLE_ACCY" length="6" type="real" min="0.0" maxval="44.999"/>
+        <field name="ANGLE_TO_NORTH_ACCY" length="6" type="real" minval="0.0" maxval="44.999"/>
+        <field name="SQUINT_ANGLE" length="7" type="real" minval="-60.0" maxval="85.0"/>
+        <field name="SQUINT_ANGLE_ACCY" length="6" type="real" minval="0.0" maxval="44.999"/>
         <field name="MODE" length="3" type="string"/>
         <field length="16" fixed_value="                "/>
         <field name="GRAZE_ANG" length="5" type="real" unit="degrees" minval="0.0" maxval="90.00"/>
@@ -449,34 +449,61 @@
         <field name="TOTAL_TILES_ROWS" length="5" type="integer" minval="1" maxval="99999"/>
     </tre>
 
+    <!-- STDI-0002 Appendix E (ASDE 2.1/CN1), Section 3.10 and Table E-19 -->
+    <tre name="MTIRPB" minlength="119" maxlength="42035">
+        <field name="MTI_DP" length="2" type="string"/>
+        <field name="MTI_PACKET_ID" length="3" minval="1" maxval="999" type="integer"/>
+        <field name="PATCH_NO" length="4" minval="1" maxval="999" type="integer"/>
+        <field name="WAMTI_FRAME_NO" length="5" type="string"/>
+        <field name="WAMTI_BAR_NO" length="1" type="string"/>
+        <field name="DATIME" length="14" type="string"/>
+        <field name="ACFT_LOC" length="21" type="string"/>
+        <field name="ACFT_ALT" length="6" minval="0" maxval="999999" type="integer"/>
+        <field name="ACFT_ALT_UNIT" length="1" type="string"/>
+        <field name="ACFT_HEADING" length="3" minval="0" maxval="359" type="integer"/>
+        <field name="MTI_LR" length="1" type="string"/>
+        <field name="SQUINT_ANGLE" length="6" minval="-60.0" maxval="85.00" type="real"/>
+        <field name="COSGRZ" length="7" minval="0" maxval="9.99999" type="real"/>
+        <field name="NO_VALID_TARGETS" length="3" minval="1" maxval="999" type="integer"/>
+        <loop counter="NO_VALID_TARGETS" md_prefix="TGT_%03d_" name="TARGETS">
+            <field name="TGT_LOC" length="23" type="string"/>
+            <field name="TGT_LOC_ACCY" length="6" minval="0" maxval="999.99" type="real"/>
+            <field name="TGT_VEL_R" length="4" minval="-200" maxval="200" type="string"/>
+            <field name="TGT_SPEED" length="3" minval="0" maxval="200" type="string"/>
+            <field name="TGT_HEADING" length="3" minval="0" maxval="359" type="string"/>
+            <field name="TGT_AMPLITUDE" length="2" minval="0" maxval="15" type="string"/>
+            <field name="TGT_CAT" length="1" type="string"/>
+        </loop>
+    </tre>
+
     <!-- STDI-0002 Appendix E (ASDE 2.1/CN1), Table E-21 -->
-    <tre name="PATCHB" size="121" location="image">
+    <tre name="PATCHB" length="121" location="image">
         <field name="PAT_NO" length="4" type="integer" minval="1" maxval="999"/>
         <!-- LAST_PAT_LEVEL is a string because it is <R>, so it may contain only a space -->
         <field name="LAST_PAT_FLAG" length="1" type="integer" minval="0" maxval="1"/>
         <field name="LNSTRT" length="7" type="integer" minval="1" maxval="9999999"/>
         <field name="LNSTOP" length="7" type="integer" minval="20" maxval="9999999"/>
-        <field name="AZL" length="5" type="integer" units="lines" minval="20" maxval="99999"/>
+        <field name="AZL" length="5" type="integer" unit="lines" minval="20" maxval="99999"/>
         <!-- NVL is a string because it is <R> -->
-        <field name="NVL" length="5" type="string" units="lines"/>
+        <field name="NVL" length="5" type="string" unit="lines"/>
         <!-- FVL is a string because it is <R> -->
         <field name="FVL" length="3" type="string" minval="1" maxval="681"/>
-        <field name="NPIXEL" length="5" type="integer" units="pixels" minval="1" maxval="99999"/>
-        <field name="FVPIX" length="5" type="integer" units="pixels" minval="1" maxval="99999"/>
+        <field name="NPIXEL" length="5" type="integer" unit="pixels" minval="1" maxval="99999"/>
+        <field name="FVPIX" length="5" type="integer" unit="pixels" minval="1" maxval="99999"/>
         <!-- FRAME is a string because it is <R> -->
         <field name="FRAME" length="3" type="string" minval="1" maxval="512"/>
-        <field name="UTC" length="8" type="real" units="seconds" minval="0.0" maxval="86399.99"/>
-        <field name="SHEAD" length="7" type="real" units="degrees" minval="0.0" maxval="359.999"/>
+        <field name="UTC" length="8" type="real" unit="seconds" minval="0.0" maxval="86399.99"/>
+        <field name="SHEAD" length="7" type="real" unit="degrees" minval="0.0" maxval="359.999"/>
         <!-- GRAVITY is a string because it is <R> -->
-        <field name="GRAVITY" length="7" type="string" units="feet/sec^2"/>
-        <field name="INS_V_NC" length="5" type="integer" units="feet/sec" minval="-9999" maxval="9999"/>
-        <field name="INS_V_EC" length="5" type="integer" units="feet/sec" minval="-9999" maxval="9999"/>
-        <field name="INS_V_DC" length="5" type="integer" units="feet/sec" minval="-9999" maxval="9999"/>
+        <field name="GRAVITY" length="7" type="string" unit="feet/sec^2"/>
+        <field name="INS_V_NC" length="5" type="integer" unit="feet/sec" minval="-9999" maxval="9999"/>
+        <field name="INS_V_EC" length="5" type="integer" unit="feet/sec" minval="-9999" maxval="9999"/>
+        <field name="INS_V_DC" length="5" type="integer" unit="feet/sec" minval="-9999" maxval="9999"/>
         <!-- OFFLAT and OFFLONG are string because they are <R> -->
-        <field name="OFFLAT" length="8" type="string" units="seconds"/>
-        <field name="OFFLONG" length="8" type="string" units="seconds"/>
-        <field name="TRACK" length="3" type="integer" units="degrees" minval="0" maxval="359"/>
-        <field name="GSWEEP" length="6" type="real" units="degrees" minval="0.0" maxval="120.0"/>
+        <field name="OFFLAT" length="8" type="string" unit="seconds"/>
+        <field name="OFFLONG" length="8" type="string" unit="seconds"/>
+        <field name="TRACK" length="3" type="integer" unit="degrees" minval="0" maxval="359"/>
+        <field name="GSWEEP" length="6" type="real" unit="degrees" minval="0.0" maxval="120.0"/>
         <!-- SHEAR is a string because it is <R> -->
         <field name="SHEAR" length="8" type="string"/>
         <!-- BATCH_NO is a string because it is <R> -->
@@ -667,6 +694,37 @@
         </loop>
     </tre>
 
+    <!-- Table 68 of http://earth-info.nga.mil/publications/specs/printed/89034/89034DPPDB.pdf -->
+    <tre name="IMASDA" length="242" location="image">
+        <field name="LONTR" length="22" type="real" unit="degrees" minval="-180.0" maxval="180.0"/>
+        <field name="LATTR" length="22" type="real" unit="degrees" minval="-90.0" maxval="90.0"/>
+        <field name="ELVTR" length="22" type="real" unit="meters" minval="-1000.0" maxval="10000.0"/>
+        <field name="LONSC" length="22" type="real" minval="0.0" maxval="100.0"/>
+        <field name="LATSC" length="22" type="real" minval="0.0" maxval="100.0"/>
+        <field name="ELVSC" length="22" type="real" minval="0.0" maxval="100.0"/>
+        <field name="XITR" length="22" type="real" unit="pixels" minval="-10000.0" maxval="10000.0"/>
+        <field name="YITR" length="22" type="real" unit="pixels" minval="-10000.0" maxval="10000.0"/>
+        <field name="XISC" length="22" type="real" minval="0.0" maxval="100.0"/>
+        <field name="YISC" length="22" type="real" minval="0.0" maxval="100.0"/>
+        <field name="DELEV" length="22" type="real" unit="meters" minval="-1000.0" maxval="10000.0"/>
+    </tre>
+
+    <!-- Table 69 of http://earth-info.nga.mil/publications/specs/printed/89034/89034DPPDB.pdf -->
+    <tre name="IMRFCA" length="1760" location="image">
+        <loop iterations="20" name="XINC">
+            <field name="" longname="XINC" length="22" type="real"/>
+        </loop>
+        <loop iterations="20" name="XIDC">
+            <field name="" longname="XIDC" length="22" type="real"/>
+        </loop>
+        <loop iterations="20" name="YINC">
+            <field name="" longname="YINC" length="22" type="real"/>
+        </loop>
+        <loop iterations="20" name="YIDC">
+            <field name="" longname="YIDC" length="22" type="real"/>
+        </loop>
+    </tre>
+
     <tre name="RSMAPA" minlength="507" maxlength="1243" location="image">
         <field name="IID" length="80" type="string"/>
         <field name="EDITION" length="40" type="string"/>
diff --git a/data/ogrvrt.xsd b/data/ogrvrt.xsd
index d957a49..879bc5f 100644
--- a/data/ogrvrt.xsd
+++ b/data/ogrvrt.xsd
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 /******************************************************************************
- * $Id: ogrvrt.xsd 34203 2016-05-10 14:06:35Z rouault $
+ * $Id: ogrvrt.xsd 36883 2016-12-15 13:31:12Z rouault $
  *
  * Project:  GDAL/OGR
  * Purpose:  XML Schema for OGR VRT files.
@@ -249,6 +249,20 @@
             <xs:enumeration value="wkbCurveZM"/>
             <xs:enumeration value="wkbSurfaceZM"/>
 
+            <!-- below is new in GDAL 2.2 -->
+            <xs:enumeration value="wkbPolyhedralSurface"/>
+            <xs:enumeration value="wkbTIN"/>
+            <xs:enumeration value="wkbTriangle"/>
+            <xs:enumeration value="wkbPolyhedralSurfaceZ"/>
+            <xs:enumeration value="wkbTINZ"/>
+            <xs:enumeration value="wkbTriangleZ"/>
+            <xs:enumeration value="wkbPolyhedralSurfaceM"/>
+            <xs:enumeration value="wkbTINM"/>
+            <xs:enumeration value="wkbTriangleM"/>
+            <xs:enumeration value="wkbPolyhedralSurfaceZM"/>
+            <xs:enumeration value="wkbTINZM"/>
+            <xs:enumeration value="wkbTriangleZM"/>
+
         </xs:restriction>
     </xs:simpleType>
 
diff --git a/data/osmconf.ini b/data/osmconf.ini
index 1fabcef..0ee63e2 100644
--- a/data/osmconf.ini
+++ b/data/osmconf.ini
@@ -2,9 +2,9 @@
 # Configuration file for OSM import
 #
 
-# put here the name of keys for ways that are assumed to be polygons if they are closed
+# put here the name of keys, or key=value, for ways that are assumed to be polygons if they are closed
 # see http://wiki.openstreetmap.org/wiki/Map_Features
-closed_ways_are_polygons=aeroway,amenity,boundary,building,craft,geological,historic,landuse,leisure,military,natural,office,place,shop,sport,tourism
+closed_ways_are_polygons=aeroway,amenity,boundary,building,craft,geological,historic,landuse,leisure,military,natural,office,place,shop,sport,tourism,highway=platform,public_transport=platform
 
 # comment to avoid laundering of keys ( ':' turned into '_' )
 attribute_name_laundering=yes
diff --git a/data/pcs.csv b/data/pcs.csv
index 6815684..c3633be 100644
--- a/data/pcs.csv
+++ b/data/pcs.csv
@@ -1,4709 +1,4786 @@
-"COORD_REF_SYS_CODE","COORD_REF_SYS_NAME","UOM_CODE","SOURCE_GEOGCRS_CODE","COORD_OP_CODE","COORD_OP_METHOD_CODE","SHOW_CRS","DEPRECATED","COORD_SYS_CODE","PARAMETER_CODE_1","PARAMETER_VALUE_1","PARAMETER_UOM_1","PARAMETER_CODE_2","PARAMETER_VALUE_2","PARAMETER_UOM_2","PARAMETER_CODE_3","PARAMETER_VALUE_3","PARAMETER_UOM_3","PARAMETER_CODE_4","PARAMETER_VALUE_4","PARAMETER_UOM_4","PARAMETER_CODE_5","PARAMETER_VALUE_5","PARAMETER_UOM_5","PARAMETER_CODE_6","PARAMETER_VALUE_6","PARAMETER_UO [...]
-2000,"Anguilla 1957 / British West Indies Grid",9001,4600,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-2001,"Antigua 1943 / British West Indies Grid",9001,4601,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-2002,"Dominica 1945 / British West Indies Grid",9001,4602,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-2003,"Grenada 1953 / British West Indies Grid",9001,4603,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-2004,"Montserrat 1958 / British West Indies Grid",9001,4604,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-2005,"St. Kitts 1955 / British West Indies Grid",9001,4605,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-2006,"St. Lucia 1955 / British West Indies Grid",9001,4606,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-2007,"St. Vincent 45 / British West Indies Grid",9001,4607,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-2008,"NAD27(CGQ77) / SCoPQ zone 2",9001,4609,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2009,"NAD27(CGQ77) / SCoPQ zone 3",9001,4609,17703,9807,1,0,4499,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2010,"NAD27(CGQ77) / SCoPQ zone 4",9001,4609,17704,9807,1,0,4499,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2011,"NAD27(CGQ77) / SCoPQ zone 5",9001,4609,17705,9807,1,0,4499,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2012,"NAD27(CGQ77) / SCoPQ zone 6",9001,4609,17706,9807,1,0,4499,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2013,"NAD27(CGQ77) / SCoPQ zone 7",9001,4609,17707,9807,1,0,4499,8801,0,9110,8802,-70.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2014,"NAD27(CGQ77) / SCoPQ zone 8",9001,4609,17708,9807,1,0,4499,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2015,"NAD27(CGQ77) / SCoPQ zone 9",9001,4609,17709,9807,1,0,4499,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2016,"NAD27(CGQ77) / SCoPQ zone 10",9001,4609,17710,9807,1,0,4499,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2017,"NAD27(76) / MTM zone 8",9001,4608,17708,9807,1,0,4499,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2018,"NAD27(76) / MTM zone 9",9001,4608,17709,9807,1,0,4499,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2019,"NAD27(76) / MTM zone 10",9001,4608,17710,9807,1,0,4499,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2020,"NAD27(76) / MTM zone 11",9001,4608,17711,9807,1,0,4400,8801,0,9110,8802,-82.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2021,"NAD27(76) / MTM zone 12",9001,4608,17712,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2022,"NAD27(76) / MTM zone 13",9001,4608,17713,9807,1,0,4400,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2023,"NAD27(76) / MTM zone 14",9001,4608,17714,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2024,"NAD27(76) / MTM zone 15",9001,4608,17715,9807,1,0,4400,8801,0,9102,8802,-90,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2025,"NAD27(76) / MTM zone 16",9001,4608,17716,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2026,"NAD27(76) / MTM zone 17",9001,4608,17717,9807,1,0,4400,8801,0,9102,8802,-96,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2027,"NAD27(76) / UTM zone 15N",9001,4608,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2028,"NAD27(76) / UTM zone 16N",9001,4608,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2029,"NAD27(76) / UTM zone 17N",9001,4608,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2030,"NAD27(76) / UTM zone 18N",9001,4608,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2031,"NAD27(CGQ77) / UTM zone 17N",9001,4609,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2032,"NAD27(CGQ77) / UTM zone 18N",9001,4609,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2033,"NAD27(CGQ77) / UTM zone 19N",9001,4609,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2034,"NAD27(CGQ77) / UTM zone 20N",9001,4609,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2035,"NAD27(CGQ77) / UTM zone 21N",9001,4609,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2036,"NAD83(CSRS98) / New Brunswick Stereo",9001,4140,19946,9809,1,1,4500,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,2500000,9001,8807,7500000,9001,,,,,,
-2037,"NAD83(CSRS98) / UTM zone 19N",9001,4140,16019,9807,1,1,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2038,"NAD83(CSRS98) / UTM zone 20N",9001,4140,16020,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2039,"Israel 1993 / Israeli TM Grid",9001,4141,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,
-2040,"Locodjo 1965 / UTM zone 30N",9001,4142,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2041,"Abidjan 1987 / UTM zone 30N",9001,4143,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2042,"Locodjo 1965 / UTM zone 29N",9001,4142,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2043,"Abidjan 1987 / UTM zone 29N",9001,4143,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2044,"Hanoi 1972 / Gauss-Kruger zone 18",9001,4147,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,
-2045,"Hanoi 1972 / Gauss-Kruger zone 19",9001,4147,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-2046,"Hartebeesthoek94 / Lo15",9001,4148,17515,9808,1,0,6503,8801,0,9102,8802,15,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2047,"Hartebeesthoek94 / Lo17",9001,4148,17517,9808,1,0,6503,8801,0,9102,8802,17,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2048,"Hartebeesthoek94 / Lo19",9001,4148,17519,9808,1,0,6503,8801,0,9102,8802,19,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2049,"Hartebeesthoek94 / Lo21",9001,4148,17521,9808,1,0,6503,8801,0,9102,8802,21,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2050,"Hartebeesthoek94 / Lo23",9001,4148,17523,9808,1,0,6503,8801,0,9102,8802,23,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2051,"Hartebeesthoek94 / Lo25",9001,4148,17525,9808,1,0,6503,8801,0,9102,8802,25,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2052,"Hartebeesthoek94 / Lo27",9001,4148,17527,9808,1,0,6503,8801,0,9102,8802,27,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2053,"Hartebeesthoek94 / Lo29",9001,4148,17529,9808,1,0,6503,8801,0,9102,8802,29,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2054,"Hartebeesthoek94 / Lo31",9001,4148,17531,9808,1,0,6503,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2055,"Hartebeesthoek94 / Lo33",9001,4148,17533,9808,1,0,6503,8801,0,9102,8802,33,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2056,"CH1903+ / LV95",9001,4150,19950,9815,1,0,4400,8811,46.570866,9110,8812,7.26225,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,2600000,9001,8817,1200000,9001
-2057,"Rassadiran / Nakhl e Taqi",9001,4153,19951,9815,1,0,4400,8811,27.31077837,9110,8812,52.3612741,9110,8813,0.34179803,9110,8814,0.34179803,9110,8815,0.999895934,9201,8816,658377.437,9001,8817,3044969.194,9001
-2058,"ED50(ED77) / UTM zone 38N",9001,4154,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2059,"ED50(ED77) / UTM zone 39N",9001,4154,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2060,"ED50(ED77) / UTM zone 40N",9001,4154,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2061,"ED50(ED77) / UTM zone 41N",9001,4154,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2062,"Madrid 1870 (Madrid) / Spain",9001,4903,19921,9801,1,0,4499,8801,40,9102,8802,0,9102,8805,0.9988085293,9201,8806,600000,9001,8807,600000,9001,,,,,,
-2063,"Dabola 1981 / UTM zone 28N",9001,4315,16028,9807,1,1,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2064,"Dabola 1981 / UTM zone 29N",9001,4315,16029,9807,1,1,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2065,"S-JTSK (Ferro) / Krovak",9001,4818,19952,9819,1,0,6501,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110
-2066,"Mount Dillon / Tobago Grid",9039,4157,19924,9806,1,0,4407,8801,11.1507843,9110,8802,-60.4109632,9110,8806,187500,9039,8807,180000,9039,,,,,,,,,
-2067,"Naparima 1955 / UTM zone 20N",9001,4158,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2068,"ELD79 / Libya zone 5",9001,4159,18240,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2069,"ELD79 / Libya zone 6",9001,4159,18241,9807,1,0,4499,8801,0,9102,8802,11,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2070,"ELD79 / Libya zone 7",9001,4159,18242,9807,1,0,4499,8801,0,9102,8802,13,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2071,"ELD79 / Libya zone 8",9001,4159,18243,9807,1,0,4499,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2072,"ELD79 / Libya zone 9",9001,4159,18244,9807,1,0,4499,8801,0,9102,8802,17,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2073,"ELD79 / Libya zone 10",9001,4159,18245,9807,1,0,4499,8801,0,9102,8802,19,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2074,"ELD79 / Libya zone 11",9001,4159,18246,9807,1,0,4499,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2075,"ELD79 / Libya zone 12",9001,4159,18247,9807,1,0,4499,8801,0,9102,8802,23,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2076,"ELD79 / Libya zone 13",9001,4159,18248,9807,1,0,4499,8801,0,9102,8802,25,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2077,"ELD79 / UTM zone 32N",9001,4159,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2078,"ELD79 / UTM zone 33N",9001,4159,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2079,"ELD79 / UTM zone 34N",9001,4159,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2080,"ELD79 / UTM zone 35N",9001,4159,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2081,"Chos Malal 1914 / Argentina 2",9001,4160,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-2082,"Pampa del Castillo / Argentina 2",9001,4161,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-2083,"Hito XVIII 1963 / Argentina 2",9001,4254,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-2084,"Hito XVIII 1963 / UTM zone 19S",9001,4254,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2085,"NAD27 / Cuba Norte",9001,4267,18061,9801,1,1,4532,8801,22.21,9110,8802,-81,9110,8805,0.99993602,9201,8806,500000,9001,8807,280296.016,9001,,,,,,
-2086,"NAD27 / Cuba Sur",9001,4267,18062,9801,1,1,4532,8801,20.43,9110,8802,-76.5,9110,8805,0.99994848,9201,8806,500000,9001,8807,229126.939,9001,,,,,,
-2087,"ELD79 / TM 12 NE",9001,4159,16412,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2088,"Carthage / TM 11 NE",9001,4223,16411,9807,1,0,4400,8801,0,9102,8802,11,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2089,"Yemen NGN96 / UTM zone 38N",9001,4163,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2090,"Yemen NGN96 / UTM zone 39N",9001,4163,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2091,"South Yemen / Gauss Kruger zone 8",9001,4164,16208,9807,1,1,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-2092,"South Yemen / Gauss Kruger zone 9",9001,4164,16209,9807,1,1,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-2093,"Hanoi 1972 / GK 106 NE",9001,4147,16586,9807,1,0,4530,8801,0,9102,8802,106,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2094,"WGS 72BE / TM 106 NE",9001,4324,16506,9807,1,0,4400,8801,0,9102,8802,106,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2095,"Bissau / UTM zone 28N",9001,4165,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2096,"Korean 1985 / East Belt",9001,4162,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-2097,"Korean 1985 / Central Belt",9001,4162,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-2098,"Korean 1985 / West Belt",9001,4162,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-2099,"Qatar 1948 / Qatar Grid",9001,4286,19953,9806,1,0,4400,8801,25.22565,9110,8802,50.4541,9110,8806,100000,9001,8807,100000,9001,,,,,,,,,
-2100,"GGRS87 / Greek Grid",9001,4121,19930,9807,1,0,4400,8801,0,9102,8802,24,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2101,"Lake / Maracaibo Grid M1",9001,4249,18260,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,0,9001,8807,-52684.972,9001,,,,,,
-2102,"Lake / Maracaibo Grid",9001,4249,18261,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,200000,9001,8807,147315.028,9001,,,,,,
-2103,"Lake / Maracaibo Grid M3",9001,4249,18262,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,500000,9001,8807,447315.028,9001,,,,,,
-2104,"Lake / Maracaibo La Rosa Grid",9001,4249,18263,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,-17044,9001,8807,-23139.97,9001,,,,,,
-2105,"NZGD2000 / Mount Eden 2000",9001,4167,17931,9807,1,0,4500,8801,-36.5247,9110,8802,174.4551,9110,8805,0.9999,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2106,"NZGD2000 / Bay of Plenty 2000",9001,4167,17932,9807,1,0,4500,8801,-37.454,9110,8802,176.2758,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2107,"NZGD2000 / Poverty Bay 2000",9001,4167,17933,9807,1,0,4500,8801,-38.3728,9110,8802,177.5308,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2108,"NZGD2000 / Hawkes Bay 2000",9001,4167,17934,9807,1,0,4500,8801,-39.3903,9110,8802,176.4025,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2109,"NZGD2000 / Taranaki 2000",9001,4167,17935,9807,1,0,4500,8801,-39.0808,9110,8802,174.134,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2110,"NZGD2000 / Tuhirangi 2000",9001,4167,17936,9807,1,0,4500,8801,-39.3044,9110,8802,175.3824,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2111,"NZGD2000 / Wanganui 2000",9001,4167,17937,9807,1,0,4500,8801,-40.1431,9110,8802,175.2917,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2112,"NZGD2000 / Wairarapa 2000",9001,4167,17938,9807,1,0,4500,8801,-40.5531,9110,8802,175.385,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2113,"NZGD2000 / Wellington 2000",9001,4167,17939,9807,1,0,4500,8801,-41.1804,9110,8802,174.4635,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2114,"NZGD2000 / Collingwood 2000",9001,4167,17940,9807,1,0,4500,8801,-40.4253,9110,8802,172.4019,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2115,"NZGD2000 / Nelson 2000",9001,4167,17941,9807,1,0,4500,8801,-41.1628,9110,8802,173.1757,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2116,"NZGD2000 / Karamea 2000",9001,4167,17942,9807,1,0,4500,8801,-41.1723,9110,8802,172.0632,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2117,"NZGD2000 / Buller 2000",9001,4167,17943,9807,1,0,4500,8801,-41.4838,9110,8802,171.3452,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2118,"NZGD2000 / Grey 2000",9001,4167,17944,9807,1,0,4500,8801,-42.2001,9110,8802,171.3259,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2119,"NZGD2000 / Amuri 2000",9001,4167,17945,9807,1,0,4500,8801,-42.412,9110,8802,173.0036,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2120,"NZGD2000 / Marlborough 2000",9001,4167,17946,9807,1,0,4500,8801,-41.324,9110,8802,173.4807,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2121,"NZGD2000 / Hokitika 2000",9001,4167,17947,9807,1,0,4500,8801,-42.531,9110,8802,170.5847,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2122,"NZGD2000 / Okarito 2000",9001,4167,17948,9807,1,0,4500,8801,-43.0636,9110,8802,170.1539,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2123,"NZGD2000 / Jacksons Bay 2000",9001,4167,17949,9807,1,0,4500,8801,-43.584,9110,8802,168.3622,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2124,"NZGD2000 / Mount Pleasant 2000",9001,4167,17950,9807,1,0,4500,8801,-43.3526,9110,8802,172.4337,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2125,"NZGD2000 / Gawler 2000",9001,4167,17951,9807,1,0,4500,8801,-43.4455,9110,8802,171.2138,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2126,"NZGD2000 / Timaru 2000",9001,4167,17952,9807,1,0,4500,8801,-44.2407,9110,8802,171.0326,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2127,"NZGD2000 / Lindis Peak 2000",9001,4167,17953,9807,1,0,4500,8801,-44.4406,9110,8802,169.2803,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2128,"NZGD2000 / Mount Nicholas 2000",9001,4167,17954,9807,1,0,4500,8801,-45.0758,9110,8802,168.2355,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2129,"NZGD2000 / Mount York 2000",9001,4167,17955,9807,1,0,4500,8801,-45.3349,9110,8802,167.4419,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2130,"NZGD2000 / Observation Point 2000",9001,4167,17956,9807,1,0,4500,8801,-45.4858,9110,8802,170.3742,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2131,"NZGD2000 / North Taieri 2000",9001,4167,17957,9807,1,0,4500,8801,-45.5141,9110,8802,170.1657,9110,8805,0.99996,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2132,"NZGD2000 / Bluff 2000",9001,4167,17958,9807,1,0,4500,8801,-46.36,9110,8802,168.2034,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2133,"NZGD2000 / UTM zone 58S",9001,4167,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2134,"NZGD2000 / UTM zone 59S",9001,4167,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2135,"NZGD2000 / UTM zone 60S",9001,4167,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2136,"Accra / Ghana National Grid",9094,4168,19959,9807,1,0,4404,8801,4.4,9110,8802,-1,9110,8805,0.99975,9201,8806,900000,9094,8807,0,9094,,,,,,
-2137,"Accra / TM 1 NW",9001,4168,17001,9807,1,0,4400,8801,0,9102,8802,-1,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2138,"NAD27(CGQ77) / Quebec Lambert",9001,4609,19944,9802,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,
-2139,"NAD83(CSRS98) / SCoPQ zone 2",9001,4140,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2140,"NAD83(CSRS98) / MTM zone 3",9001,4140,17703,9807,1,1,4496,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2141,"NAD83(CSRS98) / MTM zone 4",9001,4140,17704,9807,1,1,4496,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2142,"NAD83(CSRS98) / MTM zone 5",9001,4140,17705,9807,1,1,4496,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2143,"NAD83(CSRS98) / MTM zone 6",9001,4140,17706,9807,1,1,4496,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2144,"NAD83(CSRS98) / MTM zone 7",9001,4140,17707,9807,1,1,4496,8801,0,9110,8802,-70.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2145,"NAD83(CSRS98) / MTM zone 8",9001,4140,17708,9807,1,1,4496,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2146,"NAD83(CSRS98) / MTM zone 9",9001,4140,17709,9807,1,1,4496,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2147,"NAD83(CSRS98) / MTM zone 10",9001,4140,17710,9807,1,1,4496,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2148,"NAD83(CSRS98) / UTM zone 21N",9001,4140,16021,9807,1,1,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2149,"NAD83(CSRS98) / UTM zone 18N",9001,4140,16018,9807,1,1,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2150,"NAD83(CSRS98) / UTM zone 17N",9001,4140,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2151,"NAD83(CSRS98) / UTM zone 13N",9001,4140,16013,9807,1,1,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2152,"NAD83(CSRS98) / UTM zone 12N",9001,4140,16012,9807,1,1,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2153,"NAD83(CSRS98) / UTM zone 11N",9001,4140,16011,9807,1,1,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2154,"RGF93 / Lambert-93",9001,4171,18085,9802,1,0,4499,8821,46.3,9110,8822,3,9110,8823,49,9110,8824,44,9110,8826,700000,9001,8827,6600000,9001,,,
-2155,"American Samoa 1962 / American Samoa Lambert",9003,4169,15300,9801,1,1,4497,8801,-14.16,9110,8802,170,9110,8805,1,9201,8806,500000,9003,8807,0,9003,,,,,,
-2156,"NAD83(HARN) / UTM zone 59S",9001,4152,16159,9807,1,1,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2157,"IRENET95 / Irish Transverse Mercator",9001,4173,19962,9807,1,0,4400,8801,53.3,9110,8802,-8,9110,8805,0.99982,9201,8806,600000,9001,8807,750000,9001,,,,,,
-2158,"IRENET95 / UTM zone 29N",9001,4173,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2159,"Sierra Leone 1924 / New Colony Grid",9094,4174,19963,9807,1,0,4404,8801,6.4,9110,8802,-12,9110,8805,1,9201,8806,500000,9094,8807,0,9094,,,,,,
-2160,"Sierra Leone 1924 / New War Office Grid",9094,4174,19964,9807,1,0,4404,8801,6.4,9110,8802,-12,9110,8805,1,9201,8806,800000,9094,8807,600000,9094,,,,,,
-2161,"Sierra Leone 1968 / UTM zone 28N",9001,4175,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2162,"Sierra Leone 1968 / UTM zone 29N",9001,4175,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2163,US National Atlas Equal Area,9001,4052,3899,1027,1,0,4499,8801,45,9102,8802,-100,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-2164,"Locodjo 1965 / TM 5 NW",9001,4142,17005,9807,1,0,4400,8801,0,9102,8802,-5,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2165,"Abidjan 1987 / TM 5 NW",9001,4143,17005,9807,1,0,4400,8801,0,9102,8802,-5,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2166,"Pulkovo 1942(83) / Gauss Kruger zone 3",9001,4178,16263,9807,1,1,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-2167,"Pulkovo 1942(83) / Gauss Kruger zone 4",9001,4178,16264,9807,1,1,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-2168,"Pulkovo 1942(83) / Gauss Kruger zone 5",9001,4178,16265,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-2169,"Luxembourg 1930 / Gauss",9001,4181,19966,9807,1,0,4530,8801,49.5,9110,8802,6.1,9110,8805,1,9201,8806,80000,9001,8807,100000,9001,,,,,,
-2170,"MGI / Slovenia Grid",9001,4312,19967,9807,1,1,4530,8801,0,9110,8802,15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-2171,"Pulkovo 1942(58) / Poland zone I",9001,4179,18281,9809,1,1,4530,8801,50.373,9110,8802,21.05,9110,8805,0.9998,9201,8806,4637000,9001,8807,5647000,9001,,,,,,
-2172,"Pulkovo 1942(58) / Poland zone II",9001,4179,18282,9809,1,0,4530,8801,53.0007,9110,8802,21.301,9110,8805,0.9998,9201,8806,4603000,9001,8807,5806000,9001,,,,,,
-2173,"Pulkovo 1942(58) / Poland zone III",9001,4179,18283,9809,1,0,4530,8801,53.35,9110,8802,17.003,9110,8805,0.9998,9201,8806,3501000,9001,8807,5999000,9001,,,,,,
-2174,"Pulkovo 1942(58) / Poland zone IV",9001,4179,18284,9809,1,0,4530,8801,51.4015,9110,8802,16.402,9110,8805,0.9998,9201,8806,3703000,9001,8807,5627000,9001,,,,,,
-2175,"Pulkovo 1942(58) / Poland zone V",9001,4179,18285,9807,1,0,4530,8801,0,9110,8802,18.573,9110,8805,0.999983,9201,8806,237000,9001,8807,-4700000,9001,,,,,,
-2176,"ETRS89 / Poland CS2000 zone 5",9001,4258,18305,9807,1,0,4531,8801,0,9102,8802,15,9102,8805,0.999923,9201,8806,5500000,9001,8807,0,9001,,,,,,
-2177,"ETRS89 / Poland CS2000 zone 6",9001,4258,18306,9807,1,0,4531,8801,0,9102,8802,18,9102,8805,0.999923,9201,8806,6500000,9001,8807,0,9001,,,,,,
-2178,"ETRS89 / Poland CS2000 zone 7",9001,4258,18307,9807,1,0,4531,8801,0,9102,8802,21,9102,8805,0.999923,9201,8806,7500000,9001,8807,0,9001,,,,,,
-2179,"ETRS89 / Poland CS2000 zone 8",9001,4258,18308,9807,1,0,4531,8801,0,9102,8802,24,9102,8805,0.999923,9201,8806,8500000,9001,8807,0,9001,,,,,,
-2180,"ETRS89 / Poland CS92",9001,4258,18300,9807,1,0,4531,8801,0,9102,8802,19,9102,8805,0.9993,9201,8806,500000,9001,8807,-5300000,9001,,,,,,
-2188,"Azores Occidental 1939 / UTM zone 25N",9001,4182,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2189,"Azores Central 1948 / UTM zone 26N",9001,4183,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2190,"Azores Oriental 1940 / UTM zone 26N",9001,4184,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2191,"Madeira 1936 / UTM zone 28N",9001,4185,16028,9807,1,1,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2192,"ED50 / France EuroLambert",9001,4230,18086,9801,1,1,4499,8801,46.48,9110,8802,2.2014025,9110,8805,0.99987742,9201,8806,600000,9001,8807,2200000,9001,,,,,,
-2193,"NZGD2000 / New Zealand Transverse Mercator 2000",9001,4167,19971,9807,1,0,4500,8801,0,9102,8802,173,9102,8805,0.9996,9201,8806,1600000,9001,8807,10000000,9001,,,,,,
-2194,"American Samoa 1962 / American Samoa Lambert",9003,4169,15301,9801,1,1,4497,8801,-14.16,9110,8802,-170,9110,8805,1,9201,8806,500000,9003,8807,0,9003,,,,,,
-2195,"NAD83(HARN) / UTM zone 2S",9001,4152,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2196,"ETRS89 / Kp2000 Jutland",9001,4258,18401,9807,1,0,4400,8801,0,9110,8802,9.3,9110,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-2197,"ETRS89 / Kp2000 Zealand",9001,4258,18402,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-2198,"ETRS89 / Kp2000 Bornholm",9001,4258,18403,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,900000,9001,8807,0,9001,,,,,,
-2199,"Albanian 1987 / Gauss Kruger zone 4",9001,4191,16204,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-2200,"ATS77 / New Brunswick Stereographic (ATS77)",9001,4122,19945,9809,1,0,4500,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,300000,9001,8807,800000,9001,,,,,,
-2201,"REGVEN / UTM zone 18N",9001,4189,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2202,"REGVEN / UTM zone 19N",9001,4189,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2203,"REGVEN / UTM zone 20N",9001,4189,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2204,"NAD27 / Tennessee",9003,4267,15302,9802,1,0,4497,8821,34.4,9110,8822,-86,9110,8823,35.15,9110,8824,36.25,9110,8826,2000000,9003,8827,100000,9003,,,
-2205,"NAD83 / Kentucky North",9001,4269,15303,9802,1,0,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,500000,9001,8827,0,9001,,,
-2206,"ED50 / 3-degree Gauss-Kruger zone 9",9001,4230,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-2207,"ED50 / 3-degree Gauss-Kruger zone 10",9001,4230,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
-2208,"ED50 / 3-degree Gauss-Kruger zone 11",9001,4230,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
-2209,"ED50 / 3-degree Gauss-Kruger zone 12",9001,4230,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
-2210,"ED50 / 3-degree Gauss-Kruger zone 13",9001,4230,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-2211,"ED50 / 3-degree Gauss-Kruger zone 14",9001,4230,16274,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-2212,"ED50 / 3-degree Gauss-Kruger zone 15",9001,4230,16275,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-2213,"ETRS89 / TM 30 NE",9001,4258,16430,9807,1,0,4400,8801,0,9102,8802,30,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2214,"Douala 1948 / AOF west",9001,4192,18415,9807,1,1,4400,8801,0,9110,8802,10.3,9110,8805,0.999,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-2215,"Manoca 1962 / UTM zone 32N",9001,4193,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2216,"Qornoq 1927 / UTM zone 22N",9001,4194,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2217,"Qornoq 1927 / UTM zone 23N",9001,4194,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2218,"Scoresbysund 1952 / Greenland zone 5 east",9001,4195,18425,9826,1,0,1031,8801,70.3,9110,8802,-24,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2219,"ATS77 / UTM zone 19N",9001,4122,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2220,"ATS77 / UTM zone 20N",9001,4122,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2221,"Scoresbysund 1952 / Greenland zone 6 east",9001,4195,18426,9826,1,0,1031,8801,67.3,9110,8802,-32,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2222,"NAD83 / Arizona East (ft)",9002,4269,15304,9807,1,0,4495,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,
-2223,"NAD83 / Arizona Central (ft)",9002,4269,15305,9807,1,0,4495,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,
-2224,"NAD83 / Arizona West (ft)",9002,4269,15306,9807,1,0,4495,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,700000,9002,8807,0,9002,,,,,,
-2225,"NAD83 / California zone 1 (ftUS)",9003,4269,15307,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2226,"NAD83 / California zone 2 (ftUS)",9003,4269,15308,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2227,"NAD83 / California zone 3 (ftUS)",9003,4269,15309,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2228,"NAD83 / California zone 4 (ftUS)",9003,4269,15310,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2229,"NAD83 / California zone 5 (ftUS)",9003,4269,15311,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2230,"NAD83 / California zone 6 (ftUS)",9003,4269,15312,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2231,"NAD83 / Colorado North (ftUS)",9003,4269,15313,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,3000000,9003,8827,1000000,9003,,,
-2232,"NAD83 / Colorado Central (ftUS)",9003,4269,15314,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,3000000,9003,8827,1000000,9003,,,
-2233,"NAD83 / Colorado South (ftUS)",9003,4269,15315,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,3000000,9003,8827,1000000,9003,,,
-2234,"NAD83 / Connecticut (ftUS)",9003,4269,15316,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,1000000,9003,8827,500000,9003,,,
-2235,"NAD83 / Delaware (ftUS)",9003,4269,15317,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2236,"NAD83 / Florida East (ftUS)",9003,4269,15318,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2237,"NAD83 / Florida West (ftUS)",9003,4269,15319,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2238,"NAD83 / Florida North (ftUS)",9003,4269,15320,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,1968500,9003,8827,0,9003,,,
-2239,"NAD83 / Georgia East (ftUS)",9003,4269,15321,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2240,"NAD83 / Georgia West (ftUS)",9003,4269,15322,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,2296583.333,9003,8807,0,9003,,,,,,
-2241,"NAD83 / Idaho East (ftUS)",9003,4269,15323,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2242,"NAD83 / Idaho Central (ftUS)",9003,4269,15324,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,1640416.667,9003,8807,0,9003,,,,,,
-2243,"NAD83 / Idaho West (ftUS)",9003,4269,15325,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,2624666.667,9003,8807,0,9003,,,,,,
-2244,"NAD83 / Indiana East (ftUS)",9003,4269,15326,9807,1,1,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,818125,9003,,,,,,
-2245,"NAD83 / Indiana West (ftUS)",9003,4269,15327,9807,1,1,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,818125,9003,,,,,,
-2246,"NAD83 / Kentucky North (ftUS)",9003,4269,15328,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,1640416.667,9003,8827,0,9003,,,
-2247,"NAD83 / Kentucky South (ftUS)",9003,4269,15329,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,1640416.667,9003,8827,1640416.667,9003,,,
-2248,"NAD83 / Maryland (ftUS)",9003,4269,15330,9802,1,0,4497,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,1312333.333,9003,8827,0,9003,,,
-2249,"NAD83 / Massachusetts Mainland (ftUS)",9003,4269,15331,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,656166.667,9003,8827,2460625,9003,,,
-2250,"NAD83 / Massachusetts Island (ftUS)",9003,4269,15332,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,1640416.667,9003,8827,0,9003,,,
-2251,"NAD83 / Michigan North (ft)",9002,4269,15333,9802,1,0,4495,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,26246719.16,9002,8827,0,9002,,,
-2252,"NAD83 / Michigan Central (ft)",9002,4269,15334,9802,1,0,4495,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,19685039.37,9002,8827,0,9002,,,
-2253,"NAD83 / Michigan South (ft)",9002,4269,15335,9802,1,0,4495,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,13123359.58,9002,8827,0,9002,,,
-2254,"NAD83 / Mississippi East (ftUS)",9003,4269,15336,9807,1,0,4497,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,984250,9003,8807,0,9003,,,,,,
-2255,"NAD83 / Mississippi West (ftUS)",9003,4269,15337,9807,1,0,4497,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,2296583.333,9003,8807,0,9003,,,,,,
-2256,"NAD83 / Montana (ft)",9002,4269,15338,9802,1,0,4495,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,1968503.937,9002,8827,0,9002,,,
-2257,"NAD83 / New Mexico East (ftUS)",9003,4269,15339,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,541337.5,9003,8807,0,9003,,,,,,
-2258,"NAD83 / New Mexico Central (ftUS)",9003,4269,15340,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,1640416.667,9003,8807,0,9003,,,,,,
-2259,"NAD83 / New Mexico West (ftUS)",9003,4269,15341,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,2723091.667,9003,8807,0,9003,,,,,,
-2260,"NAD83 / New York East (ftUS)",9003,4269,15342,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,
-2261,"NAD83 / New York Central (ftUS)",9003,4269,15343,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,820208.333,9003,8807,0,9003,,,,,,
-2262,"NAD83 / New York West (ftUS)",9003,4269,15344,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,1148291.667,9003,8807,0,9003,,,,,,
-2263,"NAD83 / New York Long Island (ftUS)",9003,4269,15345,9802,1,0,4497,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,984250,9003,8827,0,9003,,,
-2264,"NAD83 / North Carolina (ftUS)",9003,4269,15346,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,
-2265,"NAD83 / North Dakota North (ft)",9002,4269,15347,9802,1,0,4495,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,1968503.937,9002,8827,0,9002,,,
-2266,"NAD83 / North Dakota South (ft)",9002,4269,15348,9802,1,0,4495,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,1968503.937,9002,8827,0,9002,,,
-2267,"NAD83 / Oklahoma North (ftUS)",9003,4269,15349,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,1968500,9003,8827,0,9003,,,
-2268,"NAD83 / Oklahoma South (ftUS)",9003,4269,15350,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,1968500,9003,8827,0,9003,,,
-2269,"NAD83 / Oregon North (ft)",9002,4269,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,
-2270,"NAD83 / Oregon South (ft)",9002,4269,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,
-2271,"NAD83 / Pennsylvania North (ftUS)",9003,4269,15353,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,1968500,9003,8827,0,9003,,,
-2272,"NAD83 / Pennsylvania South (ftUS)",9003,4269,15354,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,1968500,9003,8827,0,9003,,,
-2273,"NAD83 / South Carolina (ft)",9002,4269,15355,9802,1,0,4495,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,2000000,9002,8827,0,9002,,,
-2274,"NAD83 / Tennessee (ftUS)",9003,4269,15356,9802,1,0,4497,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,1968500,9003,8827,0,9003,,,
-2275,"NAD83 / Texas North (ftUS)",9003,4269,15357,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,656166.667,9003,8827,3280833.333,9003,,,
-2276,"NAD83 / Texas North Central (ftUS)",9003,4269,15358,9802,1,0,4497,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,1968500,9003,8827,6561666.667,9003,,,
-2277,"NAD83 / Texas Central (ftUS)",9003,4269,15359,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,2296583.333,9003,8827,9842500,9003,,,
-2278,"NAD83 / Texas South Central (ftUS)",9003,4269,15360,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,1968500,9003,8827,13123333.333,9003,,,
-2279,"NAD83 / Texas South (ftUS)",9003,4269,15361,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,984250,9003,8827,16404166.667,9003,,,
-2280,"NAD83 / Utah North (ft)",9002,4269,15362,9802,0,0,4495,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640419.948,9002,8827,3280839.895,9002,,,
-2281,"NAD83 / Utah Central (ft)",9002,4269,15363,9802,0,0,4495,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640419.948,9002,8827,6561679.79,9002,,,
-2282,"NAD83 / Utah South (ft)",9002,4269,15364,9802,0,0,4495,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640419.948,9002,8827,9842519.685,9002,,,
-2283,"NAD83 / Virginia North (ftUS)",9003,4269,15365,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,11482916.667,9003,8827,6561666.667,9003,,,
-2284,"NAD83 / Virginia South (ftUS)",9003,4269,15366,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,11482916.667,9003,8827,3280833.333,9003,,,
-2285,"NAD83 / Washington North (ftUS)",9003,4269,15367,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,1640416.667,9003,8827,0,9003,,,
-2286,"NAD83 / Washington South (ftUS)",9003,4269,15368,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,1640416.667,9003,8827,0,9003,,,
-2287,"NAD83 / Wisconsin North (ftUS)",9003,4269,15369,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,1968500,9003,8827,0,9003,,,
-2288,"NAD83 / Wisconsin Central (ftUS)",9003,4269,15370,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,1968500,9003,8827,0,9003,,,
-2289,"NAD83 / Wisconsin South (ftUS)",9003,4269,15371,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,1968500,9003,8827,0,9003,,,
-2290,"ATS77 / Prince Edward Isl. Stereographic (ATS77)",9001,4122,19933,9809,1,0,4496,8801,47.15,9110,8802,-63,9110,8805,0.999912,9201,8806,700000,9001,8807,400000,9001,,,,,,
-2291,"NAD83(CSRS98) / Prince Edward Isl. Stereographic (NAD83)",9001,4122,19960,9809,1,1,4496,8801,47.15,9110,8802,-63,9110,8805,0.999912,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2292,"NAD83(CSRS98) / Prince Edward Isl. Stereographic (NAD83)",9001,4140,19960,9809,1,1,4496,8801,47.15,9110,8802,-63,9110,8805,0.999912,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2294,"ATS77 / MTM Nova Scotia zone 4",9001,4122,17794,9807,1,0,4400,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,4500000,9001,8807,0,9001,,,,,,
-2295,"ATS77 / MTM Nova Scotia zone 5",9001,4122,17795,9807,1,0,4400,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,5500000,9001,8807,0,9001,,,,,,
-2296,"Ammassalik 1958 / Greenland zone 7 east",9001,4196,18427,9826,1,0,1031,8801,64.3,9110,8802,-40,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2297,"Qornoq 1927 / Greenland zone 1 east",9001,4194,18421,9826,1,1,4501,8801,82.3,9110,8802,-40,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2298,"Qornoq 1927 / Greenland zone 2 east",9001,4194,18422,9826,1,1,4501,8801,79.3,9110,8802,-24,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2299,"Qornoq 1927 / Greenland zone 2 west",9001,4194,18432,9826,1,0,1031,8801,79.3,9110,8802,-64,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2300,"Qornoq 1927 / Greenland zone 3 east",9001,4194,18423,9826,1,1,4501,8801,76.3,9110,8802,-20,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2301,"Qornoq 1927 / Greenland zone 3 west",9001,4194,18433,9826,1,0,1031,8801,76.3,9110,8802,-64,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2302,"Qornoq 1927 / Greenland zone 4 east",9001,4194,18424,9826,1,1,4501,8801,73.3,9110,8802,-24,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2303,"Qornoq 1927 / Greenland zone 4 west",9001,4194,18434,9826,1,0,1031,8801,73.3,9110,8802,-52,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2304,"Qornoq 1927 / Greenland zone 5 west",9001,4194,18435,9826,1,0,1031,8801,70.3,9110,8802,-52,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2305,"Qornoq 1927 / Greenland zone 6 west",9001,4194,18436,9826,1,0,1031,8801,67.3,9110,8802,-52,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2306,"Qornoq 1927 / Greenland zone 7 west",9001,4194,18437,9826,1,0,1031,8801,64.3,9110,8802,-52,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2307,"Qornoq 1927 / Greenland zone 8 east",9001,4194,18428,9826,1,0,1031,8801,61.3,9110,8802,-48,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-2308,"Batavia / TM 109 SE",9001,4211,16709,9807,1,0,4400,8801,0,9102,8802,109,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2309,"WGS 84 / TM 116 SE",9001,4326,16716,9807,1,0,4400,8801,0,9102,8802,116,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2310,"WGS 84 / TM 132 SE",9001,4326,16732,9807,1,0,4400,8801,0,9102,8802,132,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2311,"WGS 84 / TM 6 NE",9001,4326,16406,9807,1,0,4400,8801,0,9102,8802,6,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2312,"Garoua / UTM zone 33N",9001,4197,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2313,"Kousseri / UTM zone 33N",9001,4198,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2314,"Trinidad 1903 / Trinidad Grid (ftCla)",9005,4302,19975,9806,1,0,4403,8801,10.263,9110,8802,-61.2,9110,8806,283800,9005,8807,214500,9005,,,,,,,,,
-2315,"Campo Inchauspe / UTM zone 19S",9001,4221,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2316,"Campo Inchauspe / UTM zone 20S",9001,4221,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2317,"PSAD56 / ICN Regional",9001,4248,19976,9802,1,0,4499,8821,6,9102,8822,-66,9102,8823,9,9102,8824,3,9102,8826,1000000,9001,8827,1000000,9001,,,
-2318,"Ain el Abd / Aramco Lambert",9001,4204,19977,9802,1,0,4400,8821,25.0522236,9110,8822,48,9102,8823,17,9102,8824,33,9102,8826,0,9001,8827,0,9001,,,
-2319,"ED50 / TM27",9001,4230,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2320,"ED50 / TM30",9001,4230,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2321,"ED50 / TM33",9001,4230,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2322,"ED50 / TM36",9001,4230,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2323,"ED50 / TM39",9001,4230,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2324,"ED50 / TM42",9001,4230,16374,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2325,"ED50 / TM45",9001,4230,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2326,Hong Kong 1980 Grid System,9001,4611,19978,9807,1,0,4500,8801,22.184368,9110,8802,114.10428,9110,8805,1,9201,8806,836694.05,9001,8807,819069.8,9001,,,,,,
-2327,"Xian 1980 / Gauss-Kruger zone 13",9001,4610,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-2328,"Xian 1980 / Gauss-Kruger zone 14",9001,4610,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-2329,"Xian 1980 / Gauss-Kruger zone 15",9001,4610,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-2330,"Xian 1980 / Gauss-Kruger zone 16",9001,4610,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,
-2331,"Xian 1980 / Gauss-Kruger zone 17",9001,4610,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,
-2332,"Xian 1980 / Gauss-Kruger zone 18",9001,4610,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,
-2333,"Xian 1980 / Gauss-Kruger zone 19",9001,4610,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-2334,"Xian 1980 / Gauss-Kruger zone 20",9001,4610,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
-2335,"Xian 1980 / Gauss-Kruger zone 21",9001,4610,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
-2336,"Xian 1980 / Gauss-Kruger zone 22",9001,4610,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
-2337,"Xian 1980 / Gauss-Kruger zone 23",9001,4610,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
-2338,"Xian 1980 / Gauss-Kruger CM 75E",9001,4610,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2339,"Xian 1980 / Gauss-Kruger CM 81E",9001,4610,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2340,"Xian 1980 / Gauss-Kruger CM 87E",9001,4610,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2341,"Xian 1980 / Gauss-Kruger CM 93E",9001,4610,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2342,"Xian 1980 / Gauss-Kruger CM 99E",9001,4610,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2343,"Xian 1980 / Gauss-Kruger CM 105E",9001,4610,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2344,"Xian 1980 / Gauss-Kruger CM 111E",9001,4610,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2345,"Xian 1980 / Gauss-Kruger CM 117E",9001,4610,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2346,"Xian 1980 / Gauss-Kruger CM 123E",9001,4610,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2347,"Xian 1980 / Gauss-Kruger CM 129E",9001,4610,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2348,"Xian 1980 / Gauss-Kruger CM 135E",9001,4610,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2349,"Xian 1980 / 3-degree Gauss-Kruger zone 25",9001,4610,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
-2350,"Xian 1980 / 3-degree Gauss-Kruger zone 26",9001,4610,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
-2351,"Xian 1980 / 3-degree Gauss-Kruger zone 27",9001,4610,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
-2352,"Xian 1980 / 3-degree Gauss-Kruger zone 28",9001,4610,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
-2353,"Xian 1980 / 3-degree Gauss-Kruger zone 29",9001,4610,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
-2354,"Xian 1980 / 3-degree Gauss-Kruger zone 30",9001,4610,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
-2355,"Xian 1980 / 3-degree Gauss-Kruger zone 31",9001,4610,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
-2356,"Xian 1980 / 3-degree Gauss-Kruger zone 32",9001,4610,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,
-2357,"Xian 1980 / 3-degree Gauss-Kruger zone 33",9001,4610,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,
-2358,"Xian 1980 / 3-degree Gauss-Kruger zone 34",9001,4610,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,
-2359,"Xian 1980 / 3-degree Gauss-Kruger zone 35",9001,4610,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,
-2360,"Xian 1980 / 3-degree Gauss-Kruger zone 36",9001,4610,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,
-2361,"Xian 1980 / 3-degree Gauss-Kruger zone 37",9001,4610,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,
-2362,"Xian 1980 / 3-degree Gauss-Kruger zone 38",9001,4610,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,
-2363,"Xian 1980 / 3-degree Gauss-Kruger zone 39",9001,4610,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,
-2364,"Xian 1980 / 3-degree Gauss-Kruger zone 40",9001,4610,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,
-2365,"Xian 1980 / 3-degree Gauss-Kruger zone 41",9001,4610,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,
-2366,"Xian 1980 / 3-degree Gauss-Kruger zone 42",9001,4610,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,
-2367,"Xian 1980 / 3-degree Gauss-Kruger zone 43",9001,4610,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,
-2368,"Xian 1980 / 3-degree Gauss-Kruger zone 44",9001,4610,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,
-2369,"Xian 1980 / 3-degree Gauss-Kruger zone 45",9001,4610,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,
-2370,"Xian 1980 / 3-degree Gauss-Kruger CM 75E",9001,4610,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2371,"Xian 1980 / 3-degree Gauss-Kruger CM 78E",9001,4610,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2372,"Xian 1980 / 3-degree Gauss-Kruger CM 81E",9001,4610,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2373,"Xian 1980 / 3-degree Gauss-Kruger CM 84E",9001,4610,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2374,"Xian 1980 / 3-degree Gauss-Kruger CM 87E",9001,4610,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2375,"Xian 1980 / 3-degree Gauss-Kruger CM 90E",9001,4610,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2376,"Xian 1980 / 3-degree Gauss-Kruger CM 93E",9001,4610,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2377,"Xian 1980 / 3-degree Gauss-Kruger CM 96E",9001,4610,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2378,"Xian 1980 / 3-degree Gauss-Kruger CM 99E",9001,4610,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2379,"Xian 1980 / 3-degree Gauss-Kruger CM 102E",9001,4610,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2380,"Xian 1980 / 3-degree Gauss-Kruger CM 105E",9001,4610,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2381,"Xian 1980 / 3-degree Gauss-Kruger CM 108E",9001,4610,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2382,"Xian 1980 / 3-degree Gauss-Kruger CM 111E",9001,4610,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2383,"Xian 1980 / 3-degree Gauss-Kruger CM 114E",9001,4610,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2384,"Xian 1980 / 3-degree Gauss-Kruger CM 117E",9001,4610,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2385,"Xian 1980 / 3-degree Gauss-Kruger CM 120E",9001,4610,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2386,"Xian 1980 / 3-degree Gauss-Kruger CM 123E",9001,4610,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2387,"Xian 1980 / 3-degree Gauss-Kruger CM 126E",9001,4610,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2388,"Xian 1980 / 3-degree Gauss-Kruger CM 129E",9001,4610,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2389,"Xian 1980 / 3-degree Gauss-Kruger CM 132E",9001,4610,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2390,"Xian 1980 / 3-degree Gauss-Kruger CM 135E",9001,4610,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2391,"KKJ / Finland zone 1",9001,4123,18191,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-2392,"KKJ / Finland zone 2",9001,4123,18192,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-2393,"KKJ / Finland Uniform Coordinate System",9001,4123,18193,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-2394,"KKJ / Finland zone 4",9001,4123,18194,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-2395,"South Yemen / Gauss-Kruger zone 8",9001,4164,16208,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-2396,"South Yemen / Gauss-Kruger zone 9",9001,4164,16209,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-2397,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 3",9001,4178,16263,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-2398,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 4",9001,4178,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-2399,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 5",9001,4178,16265,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-2400,RT90 2.5 gon W,9001,4124,19929,9807,1,1,4530,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-2401,"Beijing 1954 / 3-degree Gauss-Kruger zone 25",9001,4214,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
-2402,"Beijing 1954 / 3-degree Gauss-Kruger zone 26",9001,4214,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
-2403,"Beijing 1954 / 3-degree Gauss-Kruger zone 27",9001,4214,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
-2404,"Beijing 1954 / 3-degree Gauss-Kruger zone 28",9001,4214,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
-2405,"Beijing 1954 / 3-degree Gauss-Kruger zone 29",9001,4214,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
-2406,"Beijing 1954 / 3-degree Gauss-Kruger zone 30",9001,4214,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
-2407,"Beijing 1954 / 3-degree Gauss-Kruger zone 31",9001,4214,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
-2408,"Beijing 1954 / 3-degree Gauss-Kruger zone 32",9001,4214,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,
-2409,"Beijing 1954 / 3-degree Gauss-Kruger zone 33",9001,4214,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,
-2410,"Beijing 1954 / 3-degree Gauss-Kruger zone 34",9001,4214,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,
-2411,"Beijing 1954 / 3-degree Gauss-Kruger zone 35",9001,4214,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,
-2412,"Beijing 1954 / 3-degree Gauss-Kruger zone 36",9001,4214,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,
-2413,"Beijing 1954 / 3-degree Gauss-Kruger zone 37",9001,4214,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,
-2414,"Beijing 1954 / 3-degree Gauss-Kruger zone 38",9001,4214,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,
-2415,"Beijing 1954 / 3-degree Gauss-Kruger zone 39",9001,4214,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,
-2416,"Beijing 1954 / 3-degree Gauss-Kruger zone 40",9001,4214,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,
-2417,"Beijing 1954 / 3-degree Gauss-Kruger zone 41",9001,4214,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,
-2418,"Beijing 1954 / 3-degree Gauss-Kruger zone 42",9001,4214,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,
-2419,"Beijing 1954 / 3-degree Gauss-Kruger zone 43",9001,4214,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,
-2420,"Beijing 1954 / 3-degree Gauss-Kruger zone 44",9001,4214,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,
-2421,"Beijing 1954 / 3-degree Gauss-Kruger zone 45",9001,4214,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,
-2422,"Beijing 1954 / 3-degree Gauss-Kruger CM 75E",9001,4214,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2423,"Beijing 1954 / 3-degree Gauss-Kruger CM 78E",9001,4214,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2424,"Beijing 1954 / 3-degree Gauss-Kruger CM 81E",9001,4214,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2425,"Beijing 1954 / 3-degree Gauss-Kruger CM 84E",9001,4214,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2426,"Beijing 1954 / 3-degree Gauss-Kruger CM 87E",9001,4214,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2427,"Beijing 1954 / 3-degree Gauss-Kruger CM 90E",9001,4214,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2428,"Beijing 1954 / 3-degree Gauss-Kruger CM 93E",9001,4214,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2429,"Beijing 1954 / 3-degree Gauss-Kruger CM 96E",9001,4214,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2430,"Beijing 1954 / 3-degree Gauss-Kruger CM 99E",9001,4214,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2431,"Beijing 1954 / 3-degree Gauss-Kruger CM 102E",9001,4214,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2432,"Beijing 1954 / 3-degree Gauss-Kruger CM 105E",9001,4214,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2433,"Beijing 1954 / 3-degree Gauss-Kruger CM 108E",9001,4214,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2434,"Beijing 1954 / 3-degree Gauss-Kruger CM 111E",9001,4214,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2435,"Beijing 1954 / 3-degree Gauss-Kruger CM 114E",9001,4214,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2436,"Beijing 1954 / 3-degree Gauss-Kruger CM 117E",9001,4214,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2437,"Beijing 1954 / 3-degree Gauss-Kruger CM 120E",9001,4214,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2438,"Beijing 1954 / 3-degree Gauss-Kruger CM 123E",9001,4214,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2439,"Beijing 1954 / 3-degree Gauss-Kruger CM 126E",9001,4214,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2440,"Beijing 1954 / 3-degree Gauss-Kruger CM 129E",9001,4214,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2441,"Beijing 1954 / 3-degree Gauss-Kruger CM 132E",9001,4214,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2442,"Beijing 1954 / 3-degree Gauss-Kruger CM 135E",9001,4214,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2443,"JGD2000 / Japan Plane Rectangular CS I",9001,4612,17801,9807,1,0,4530,8801,33,9110,8802,129.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2444,"JGD2000 / Japan Plane Rectangular CS II",9001,4612,17802,9807,1,0,4530,8801,33,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2445,"JGD2000 / Japan Plane Rectangular CS III",9001,4612,17803,9807,1,0,4530,8801,36,9110,8802,132.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2446,"JGD2000 / Japan Plane Rectangular CS IV",9001,4612,17804,9807,1,0,4530,8801,33,9110,8802,133.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2447,"JGD2000 / Japan Plane Rectangular CS V",9001,4612,17805,9807,1,0,4530,8801,36,9110,8802,134.2,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2448,"JGD2000 / Japan Plane Rectangular CS VI",9001,4612,17806,9807,1,0,4530,8801,36,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2449,"JGD2000 / Japan Plane Rectangular CS VII",9001,4612,17807,9807,1,0,4530,8801,36,9110,8802,137.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2450,"JGD2000 / Japan Plane Rectangular CS VIII",9001,4612,17808,9807,1,0,4530,8801,36,9110,8802,138.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2451,"JGD2000 / Japan Plane Rectangular CS IX",9001,4612,17809,9807,1,0,4530,8801,36,9110,8802,139.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2452,"JGD2000 / Japan Plane Rectangular CS X",9001,4612,17810,9807,1,0,4530,8801,40,9110,8802,140.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2453,"JGD2000 / Japan Plane Rectangular CS XI",9001,4612,17811,9807,1,0,4530,8801,44,9110,8802,140.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2454,"JGD2000 / Japan Plane Rectangular CS XII",9001,4612,17812,9807,1,0,4530,8801,44,9110,8802,142.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2455,"JGD2000 / Japan Plane Rectangular CS XIII",9001,4612,17813,9807,1,0,4530,8801,44,9110,8802,144.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2456,"JGD2000 / Japan Plane Rectangular CS XIV",9001,4612,17814,9807,1,0,4530,8801,26,9110,8802,142,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2457,"JGD2000 / Japan Plane Rectangular CS XV",9001,4612,17815,9807,1,0,4530,8801,26,9110,8802,127.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2458,"JGD2000 / Japan Plane Rectangular CS XVI",9001,4612,17816,9807,1,0,4530,8801,26,9110,8802,124,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2459,"JGD2000 / Japan Plane Rectangular CS XVII",9001,4612,17817,9807,1,0,4530,8801,26,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2460,"JGD2000 / Japan Plane Rectangular CS XVIII",9001,4612,17818,9807,1,0,4530,8801,20,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2461,"JGD2000 / Japan Plane Rectangular CS XIX",9001,4612,17819,9807,1,0,4530,8801,26,9110,8802,154,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-2462,"Albanian 1987 / Gauss-Kruger zone 4",9001,4191,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-2463,"Pulkovo 1995 / Gauss-Kruger CM 21E",9001,4200,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2464,"Pulkovo 1995 / Gauss-Kruger CM 27E",9001,4200,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2465,"Pulkovo 1995 / Gauss-Kruger CM 33E",9001,4200,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2466,"Pulkovo 1995 / Gauss-Kruger CM 39E",9001,4200,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2467,"Pulkovo 1995 / Gauss-Kruger CM 45E",9001,4200,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2468,"Pulkovo 1995 / Gauss-Kruger CM 51E",9001,4200,16309,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2469,"Pulkovo 1995 / Gauss-Kruger CM 57E",9001,4200,16310,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2470,"Pulkovo 1995 / Gauss-Kruger CM 63E",9001,4200,16311,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2471,"Pulkovo 1995 / Gauss-Kruger CM 69E",9001,4200,16312,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2472,"Pulkovo 1995 / Gauss-Kruger CM 75E",9001,4200,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2473,"Pulkovo 1995 / Gauss-Kruger CM 81E",9001,4200,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2474,"Pulkovo 1995 / Gauss-Kruger CM 87E",9001,4200,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2475,"Pulkovo 1995 / Gauss-Kruger CM 93E",9001,4200,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2476,"Pulkovo 1995 / Gauss-Kruger CM 99E",9001,4200,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2477,"Pulkovo 1995 / Gauss-Kruger CM 105E",9001,4200,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2478,"Pulkovo 1995 / Gauss-Kruger CM 111E",9001,4200,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2479,"Pulkovo 1995 / Gauss-Kruger CM 117E",9001,4200,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2480,"Pulkovo 1995 / Gauss-Kruger CM 123E",9001,4200,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2481,"Pulkovo 1995 / Gauss-Kruger CM 129E",9001,4200,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2482,"Pulkovo 1995 / Gauss-Kruger CM 135E",9001,4200,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2483,"Pulkovo 1995 / Gauss-Kruger CM 141E",9001,4200,16324,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2484,"Pulkovo 1995 / Gauss-Kruger CM 147E",9001,4200,16325,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2485,"Pulkovo 1995 / Gauss-Kruger CM 153E",9001,4200,16326,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2486,"Pulkovo 1995 / Gauss-Kruger CM 159E",9001,4200,16327,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2487,"Pulkovo 1995 / Gauss-Kruger CM 165E",9001,4200,16328,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2488,"Pulkovo 1995 / Gauss-Kruger CM 171E",9001,4200,16329,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2489,"Pulkovo 1995 / Gauss-Kruger CM 177E",9001,4200,16330,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2490,"Pulkovo 1995 / Gauss-Kruger CM 177W",9001,4200,16331,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2491,"Pulkovo 1995 / Gauss-Kruger CM 171W",9001,4200,16332,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2492,"Pulkovo 1942 / Gauss-Kruger CM 9E",9001,4284,16302,9807,1,1,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2493,"Pulkovo 1942 / Gauss-Kruger CM 15E",9001,4284,16303,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2494,"Pulkovo 1942 / Gauss-Kruger CM 21E",9001,4284,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2495,"Pulkovo 1942 / Gauss-Kruger CM 27E",9001,4284,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2496,"Pulkovo 1942 / Gauss-Kruger CM 33E",9001,4284,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2497,"Pulkovo 1942 / Gauss-Kruger CM 39E",9001,4284,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2498,"Pulkovo 1942 / Gauss-Kruger CM 45E",9001,4284,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2499,"Pulkovo 1942 / Gauss-Kruger CM 51E",9001,4284,16309,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2500,"Pulkovo 1942 / Gauss-Kruger CM 57E",9001,4284,16310,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2501,"Pulkovo 1942 / Gauss-Kruger CM 63E",9001,4284,16311,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2502,"Pulkovo 1942 / Gauss-Kruger CM 69E",9001,4284,16312,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2503,"Pulkovo 1942 / Gauss-Kruger CM 75E",9001,4284,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2504,"Pulkovo 1942 / Gauss-Kruger CM 81E",9001,4284,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2505,"Pulkovo 1942 / Gauss-Kruger CM 87E",9001,4284,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2506,"Pulkovo 1942 / Gauss-Kruger CM 93E",9001,4284,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2507,"Pulkovo 1942 / Gauss-Kruger CM 99E",9001,4284,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2508,"Pulkovo 1942 / Gauss-Kruger CM 105E",9001,4284,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2509,"Pulkovo 1942 / Gauss-Kruger CM 111E",9001,4284,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2510,"Pulkovo 1942 / Gauss-Kruger CM 117E",9001,4284,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2511,"Pulkovo 1942 / Gauss-Kruger CM 123E",9001,4284,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2512,"Pulkovo 1942 / Gauss-Kruger CM 129E",9001,4284,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2513,"Pulkovo 1942 / Gauss-Kruger CM 135E",9001,4284,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2514,"Pulkovo 1942 / Gauss-Kruger CM 141E",9001,4284,16324,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2515,"Pulkovo 1942 / Gauss-Kruger CM 147E",9001,4284,16325,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2516,"Pulkovo 1942 / Gauss-Kruger CM 153E",9001,4284,16326,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2517,"Pulkovo 1942 / Gauss-Kruger CM 159E",9001,4284,16327,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2518,"Pulkovo 1942 / Gauss-Kruger CM 165E",9001,4284,16328,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2519,"Pulkovo 1942 / Gauss-Kruger CM 171E",9001,4284,16329,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2520,"Pulkovo 1942 / Gauss-Kruger CM 177E",9001,4284,16330,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2521,"Pulkovo 1942 / Gauss-Kruger CM 177W",9001,4284,16331,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2522,"Pulkovo 1942 / Gauss-Kruger CM 171W",9001,4284,16332,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2523,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 7",9001,4284,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-2524,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 8",9001,4284,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-2525,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 9",9001,4284,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-2526,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 10",9001,4284,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
-2527,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 11",9001,4284,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
-2528,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 12",9001,4284,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
-2529,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 13",9001,4284,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-2530,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 14",9001,4284,16274,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-2531,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 15",9001,4284,16275,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-2532,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 16",9001,4284,16276,9807,1,0,4530,8801,0,9102,8802,48,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,
-2533,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 17",9001,4284,16277,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,
-2534,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 18",9001,4284,16278,9807,1,0,4530,8801,0,9102,8802,54,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,
-2535,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 19",9001,4284,16279,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-2536,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 20",9001,4284,16280,9807,1,0,4530,8801,0,9102,8802,60,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
-2537,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 21",9001,4284,16281,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
-2538,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 22",9001,4284,16282,9807,1,0,4530,8801,0,9102,8802,66,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
-2539,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 23",9001,4284,16283,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
-2540,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 24",9001,4284,16284,9807,1,0,4530,8801,0,9102,8802,72,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,
-2541,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 25",9001,4284,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
-2542,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 26",9001,4284,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
-2543,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 27",9001,4284,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
-2544,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 28",9001,4284,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
-2545,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 29",9001,4284,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
-2546,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 30",9001,4284,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
-2547,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 31",9001,4284,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
-2548,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 32",9001,4284,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,
-2549,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 33",9001,4284,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,
-2550,"Samboja / UTM zone 50S",9001,4125,16150,9807,1,1,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2551,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 34",9001,4284,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,
-2552,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 35",9001,4284,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,
-2553,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 36",9001,4284,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,
-2554,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 37",9001,4284,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,
-2555,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 38",9001,4284,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,
-2556,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 39",9001,4284,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,
-2557,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 40",9001,4284,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,
-2558,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 41",9001,4284,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,
-2559,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 42",9001,4284,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,
-2560,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 43",9001,4284,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,
-2561,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 44",9001,4284,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,
-2562,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 45",9001,4284,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,
-2563,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 46",9001,4284,16076,9807,1,0,4530,8801,0,9102,8802,138,9102,8805,1,9201,8806,46500000,9001,8807,0,9001,,,,,,
-2564,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 47",9001,4284,16077,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,47500000,9001,8807,0,9001,,,,,,
-2565,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 48",9001,4284,16078,9807,1,0,4530,8801,0,9102,8802,144,9102,8805,1,9201,8806,48500000,9001,8807,0,9001,,,,,,
-2566,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 49",9001,4284,16079,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,49500000,9001,8807,0,9001,,,,,,
-2567,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 50",9001,4284,16080,9807,1,0,4530,8801,0,9102,8802,150,9102,8805,1,9201,8806,50500000,9001,8807,0,9001,,,,,,
-2568,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 51",9001,4284,16081,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,51500000,9001,8807,0,9001,,,,,,
-2569,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 52",9001,4284,16082,9807,1,0,4530,8801,0,9102,8802,156,9102,8805,1,9201,8806,52500000,9001,8807,0,9001,,,,,,
-2570,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 53",9001,4284,16083,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,53500000,9001,8807,0,9001,,,,,,
-2571,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 54",9001,4284,16084,9807,1,0,4530,8801,0,9102,8802,162,9102,8805,1,9201,8806,54500000,9001,8807,0,9001,,,,,,
-2572,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 55",9001,4284,16085,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,55500000,9001,8807,0,9001,,,,,,
-2573,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 56",9001,4284,16086,9807,1,0,4530,8801,0,9102,8802,168,9102,8805,1,9201,8806,56500000,9001,8807,0,9001,,,,,,
-2574,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 57",9001,4284,16087,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,57500000,9001,8807,0,9001,,,,,,
-2575,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 58",9001,4284,16088,9807,1,0,4530,8801,0,9102,8802,174,9102,8805,1,9201,8806,58500000,9001,8807,0,9001,,,,,,
-2576,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 59",9001,4284,16089,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,59500000,9001,8807,0,9001,,,,,,
-2577,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 60",9001,4284,16090,9807,1,1,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,60000000,9001,8807,0,9001,,,,,,
-2578,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 61",9001,4284,16091,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,61500000,9001,8807,0,9001,,,,,,
-2579,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 62",9001,4284,16092,9807,1,0,4530,8801,0,9102,8802,-174,9102,8805,1,9201,8806,62500000,9001,8807,0,9001,,,,,,
-2580,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 63",9001,4284,16093,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,63500000,9001,8807,0,9001,,,,,,
-2581,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 64",9001,4284,16094,9807,1,0,4530,8801,0,9102,8802,-168,9102,8805,1,9201,8806,64500000,9001,8807,0,9001,,,,,,
-2582,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 21E",9001,4284,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2583,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 24E",9001,4284,16368,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2584,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 27E",9001,4284,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2585,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 30E",9001,4284,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2586,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 33E",9001,4284,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2587,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 36E",9001,4284,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2588,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 39E",9001,4284,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2589,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 42E",9001,4284,16374,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2590,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 45E",9001,4284,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2591,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 48E",9001,4284,16376,9807,1,0,4530,8801,0,9102,8802,48,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2592,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 51E",9001,4284,16309,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2593,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 54E",9001,4284,16378,9807,1,0,4530,8801,0,9102,8802,54,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2594,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 57E",9001,4284,16310,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2595,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 60E",9001,4284,16380,9807,1,0,4530,8801,0,9102,8802,60,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2596,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 63E",9001,4284,16311,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2597,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 66E",9001,4284,16382,9807,1,0,4530,8801,0,9102,8802,66,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2598,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 69E",9001,4284,16312,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2599,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 72E",9001,4284,16384,9807,1,0,4530,8801,0,9102,8802,72,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2600,Lietuvos Koordinoei Sistema 1994,9001,4669,19934,9807,1,1,4530,8801,0,9102,8802,24,9102,8805,0.9998,9201,8806,500000,9001,8807,0,9001,,,,,,
-2601,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 75E",9001,4284,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2602,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 78E",9001,4284,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2603,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 81E",9001,4284,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2604,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 84E",9001,4284,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2605,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 87E",9001,4284,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2606,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 90E",9001,4284,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2607,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 93E",9001,4284,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2608,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 96E",9001,4284,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2609,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 99E",9001,4284,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2610,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 102E",9001,4284,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2611,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 105E",9001,4284,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2612,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 108E",9001,4284,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2613,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 111E",9001,4284,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2614,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 114E",9001,4284,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2615,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 117E",9001,4284,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2616,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 120E",9001,4284,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2617,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 123E",9001,4284,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2618,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 126E",9001,4284,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2619,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 129E",9001,4284,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2620,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 132E",9001,4284,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2621,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 135E",9001,4284,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2622,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 138E",9001,4284,16176,9807,1,0,4530,8801,0,9102,8802,138,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2623,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 141E",9001,4284,16324,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2624,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 144E",9001,4284,16178,9807,1,0,4530,8801,0,9102,8802,144,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2625,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 147E",9001,4284,16325,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2626,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 150E",9001,4284,16180,9807,1,0,4530,8801,0,9102,8802,150,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2627,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 153E",9001,4284,16326,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2628,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 156E",9001,4284,16182,9807,1,0,4530,8801,0,9102,8802,156,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2629,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 159E",9001,4284,16327,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2630,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 162E",9001,4284,16184,9807,1,0,4530,8801,0,9102,8802,162,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2631,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 165E",9001,4284,16328,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2632,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 168E",9001,4284,16186,9807,1,0,4530,8801,0,9102,8802,168,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2633,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 171E",9001,4284,16329,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2634,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 174E",9001,4284,16188,9807,1,0,4530,8801,0,9102,8802,174,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2635,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 177E",9001,4284,16330,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2636,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 180E",9001,4284,16190,9807,1,0,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2637,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 177W",9001,4284,16331,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2638,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 174W",9001,4284,16192,9807,1,0,4530,8801,0,9102,8802,-174,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2639,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 171W",9001,4284,16332,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2640,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 168W",9001,4284,16194,9807,1,0,4530,8801,0,9102,8802,-168,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2641,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 7",9001,4200,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-2642,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 8",9001,4200,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-2643,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 9",9001,4200,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-2644,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 10",9001,4200,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
-2645,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 11",9001,4200,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
-2646,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 12",9001,4200,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
-2647,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 13",9001,4200,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-2648,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 14",9001,4200,16274,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-2649,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 15",9001,4200,16275,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-2650,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 16",9001,4200,16276,9807,1,0,4530,8801,0,9102,8802,48,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,
-2651,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 17",9001,4200,16277,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,
-2652,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 18",9001,4200,16278,9807,1,0,4530,8801,0,9102,8802,54,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,
-2653,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 19",9001,4200,16279,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-2654,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 20",9001,4200,16280,9807,1,0,4530,8801,0,9102,8802,60,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
-2655,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 21",9001,4200,16281,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
-2656,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 22",9001,4200,16282,9807,1,0,4530,8801,0,9102,8802,66,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
-2657,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 23",9001,4200,16283,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
-2658,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 24",9001,4200,16284,9807,1,0,4530,8801,0,9102,8802,72,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,
-2659,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 25",9001,4200,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
-2660,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 26",9001,4200,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
-2661,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 27",9001,4200,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
-2662,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 28",9001,4200,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
-2663,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 29",9001,4200,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
-2664,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 30",9001,4200,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
-2665,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 31",9001,4200,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
-2666,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 32",9001,4200,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,
-2667,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 33",9001,4200,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,
-2668,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 34",9001,4200,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,
-2669,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 35",9001,4200,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,
-2670,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 36",9001,4200,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,
-2671,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 37",9001,4200,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,
-2672,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 38",9001,4200,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,
-2673,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 39",9001,4200,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,
-2674,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 40",9001,4200,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,
-2675,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 41",9001,4200,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,
-2676,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 42",9001,4200,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,
-2677,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 43",9001,4200,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,
-2678,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 44",9001,4200,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,
-2679,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 45",9001,4200,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,
-2680,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 46",9001,4200,16076,9807,1,0,4530,8801,0,9102,8802,138,9102,8805,1,9201,8806,46500000,9001,8807,0,9001,,,,,,
-2681,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 47",9001,4200,16077,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,47500000,9001,8807,0,9001,,,,,,
-2682,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 48",9001,4200,16078,9807,1,0,4530,8801,0,9102,8802,144,9102,8805,1,9201,8806,48500000,9001,8807,0,9001,,,,,,
-2683,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 49",9001,4200,16079,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,49500000,9001,8807,0,9001,,,,,,
-2684,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 50",9001,4200,16080,9807,1,0,4530,8801,0,9102,8802,150,9102,8805,1,9201,8806,50500000,9001,8807,0,9001,,,,,,
-2685,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 51",9001,4200,16081,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,51500000,9001,8807,0,9001,,,,,,
-2686,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 52",9001,4200,16082,9807,1,0,4530,8801,0,9102,8802,156,9102,8805,1,9201,8806,52500000,9001,8807,0,9001,,,,,,
-2687,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 53",9001,4200,16083,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,53500000,9001,8807,0,9001,,,,,,
-2688,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 54",9001,4200,16084,9807,1,0,4530,8801,0,9102,8802,162,9102,8805,1,9201,8806,54500000,9001,8807,0,9001,,,,,,
-2689,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 55",9001,4200,16085,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,55500000,9001,8807,0,9001,,,,,,
-2690,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 56",9001,4200,16086,9807,1,0,4530,8801,0,9102,8802,168,9102,8805,1,9201,8806,56500000,9001,8807,0,9001,,,,,,
-2691,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 57",9001,4200,16087,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,57500000,9001,8807,0,9001,,,,,,
-2692,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 58",9001,4200,16088,9807,1,0,4530,8801,0,9102,8802,174,9102,8805,1,9201,8806,58500000,9001,8807,0,9001,,,,,,
-2693,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 59",9001,4200,16089,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,59500000,9001,8807,0,9001,,,,,,
-2694,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 60",9001,4200,16090,9807,1,1,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,60000000,9001,8807,0,9001,,,,,,
-2695,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 61",9001,4200,16091,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,61500000,9001,8807,0,9001,,,,,,
-2696,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 62",9001,4200,16092,9807,1,0,4530,8801,0,9102,8802,-174,9102,8805,1,9201,8806,62500000,9001,8807,0,9001,,,,,,
-2697,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 63",9001,4200,16093,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,63500000,9001,8807,0,9001,,,,,,
-2698,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 64",9001,4200,16094,9807,1,0,4530,8801,0,9102,8802,-168,9102,8805,1,9201,8806,64500000,9001,8807,0,9001,,,,,,
-2699,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 21E",9001,4200,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2700,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 24E",9001,4200,16368,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2701,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 27E",9001,4200,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2702,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 30E",9001,4200,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2703,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 33E",9001,4200,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2704,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 36E",9001,4200,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2705,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 39E",9001,4200,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2706,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 42E",9001,4200,16374,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2707,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 45E",9001,4200,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2708,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 48E",9001,4200,16376,9807,1,0,4530,8801,0,9102,8802,48,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2709,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 51E",9001,4200,16309,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2710,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 54E",9001,4200,16378,9807,1,0,4530,8801,0,9102,8802,54,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2711,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 57E",9001,4200,16310,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2712,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 60E",9001,4200,16380,9807,1,0,4530,8801,0,9102,8802,60,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2713,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 63E",9001,4200,16311,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2714,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 66E",9001,4200,16382,9807,1,0,4530,8801,0,9102,8802,66,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2715,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 69E",9001,4200,16312,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2716,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 72E",9001,4200,16384,9807,1,0,4530,8801,0,9102,8802,72,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2717,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 75E",9001,4200,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2718,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 78E",9001,4200,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2719,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 81E",9001,4200,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2720,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 84E",9001,4200,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2721,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 87E",9001,4200,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2722,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 90E",9001,4200,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2723,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 93E",9001,4200,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2724,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 96E",9001,4200,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2725,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 99E",9001,4200,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2726,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 102E",9001,4200,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2727,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 105E",9001,4200,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2728,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 108E",9001,4200,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2729,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 111E",9001,4200,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2730,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 114E",9001,4200,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2731,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 117E",9001,4200,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2732,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 120E",9001,4200,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2733,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 123E",9001,4200,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2734,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 126E",9001,4200,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2735,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 129E",9001,4200,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2736,"Tete / UTM zone 36S",9001,4127,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2737,"Tete / UTM zone 37S",9001,4127,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2738,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 132E",9001,4200,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2739,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 135E",9001,4200,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2740,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 138E",9001,4200,16176,9807,1,0,4530,8801,0,9102,8802,138,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2741,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 141E",9001,4200,16324,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2742,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 144E",9001,4200,16178,9807,1,0,4530,8801,0,9102,8802,144,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2743,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 147E",9001,4200,16325,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2744,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 150E",9001,4200,16180,9807,1,0,4530,8801,0,9102,8802,150,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2745,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 153E",9001,4200,16326,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2746,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 156E",9001,4200,16182,9807,1,0,4530,8801,0,9102,8802,156,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2747,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 159E",9001,4200,16327,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2748,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 162E",9001,4200,16184,9807,1,0,4530,8801,0,9102,8802,162,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2749,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 165E",9001,4200,16328,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2750,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 168E",9001,4200,16186,9807,1,0,4530,8801,0,9102,8802,168,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2751,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 171E",9001,4200,16329,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2752,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 174E",9001,4200,16188,9807,1,0,4530,8801,0,9102,8802,174,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2753,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 177E",9001,4200,16330,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2754,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 180E",9001,4200,16190,9807,1,0,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2755,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 177W",9001,4200,16331,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2756,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 174W",9001,4200,16192,9807,1,0,4530,8801,0,9102,8802,-174,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2757,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 171W",9001,4200,16332,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2758,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 168W",9001,4200,16194,9807,1,0,4530,8801,0,9102,8802,-168,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2759,"NAD83(HARN) / Alabama East",9001,4152,10131,9807,1,0,4499,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,
-2760,"NAD83(HARN) / Alabama West",9001,4152,10132,9807,1,0,4499,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,600000,9001,8807,0,9001,,,,,,
-2761,"NAD83(HARN) / Arizona East",9001,4152,10231,9807,1,0,4499,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,
-2762,"NAD83(HARN) / Arizona Central",9001,4152,10232,9807,1,0,4499,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,
-2763,"NAD83(HARN) / Arizona West",9001,4152,10233,9807,1,0,4499,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,213360,9001,8807,0,9001,,,,,,
-2764,"NAD83(HARN) / Arkansas North",9001,4152,10331,9802,1,0,4499,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,400000,9001,8827,0,9001,,,
-2765,"NAD83(HARN) / Arkansas South",9001,4152,10332,9802,1,0,4499,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,400000,9001,8827,400000,9001,,,
-2766,"NAD83(HARN) / California zone 1",9001,4152,10431,9802,1,0,4499,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9001,8827,500000,9001,,,
-2767,"NAD83(HARN) / California zone 2",9001,4152,10432,9802,1,0,4499,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9001,8827,500000,9001,,,
-2768,"NAD83(HARN) / California zone 3",9001,4152,10433,9802,1,0,4499,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9001,8827,500000,9001,,,
-2769,"NAD83(HARN) / California zone 4",9001,4152,10434,9802,1,0,4499,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9001,8827,500000,9001,,,
-2770,"NAD83(HARN) / California zone 5",9001,4152,10435,9802,1,0,4499,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9001,8827,500000,9001,,,
-2771,"NAD83(HARN) / California zone 6",9001,4152,10436,9802,1,0,4499,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9001,8827,500000,9001,,,
-2772,"NAD83(HARN) / Colorado North",9001,4152,10531,9802,1,0,4499,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-2773,"NAD83(HARN) / Colorado Central",9001,4152,10532,9802,1,0,4499,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-2774,"NAD83(HARN) / Colorado South",9001,4152,10533,9802,1,0,4499,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-2775,"NAD83(HARN) / Connecticut",9001,4152,10630,9802,1,0,4499,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,304800.6096,9001,8827,152400.3048,9001,,,
-2776,"NAD83(HARN) / Delaware",9001,4152,10730,9807,1,0,4499,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,200000,9001,8807,0,9001,,,,,,
-2777,"NAD83(HARN) / Florida East",9001,4152,10931,9807,1,0,4499,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,
-2778,"NAD83(HARN) / Florida West",9001,4152,10932,9807,1,0,4499,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,
-2779,"NAD83(HARN) / Florida North",9001,4152,10933,9802,1,0,4499,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,600000,9001,8827,0,9001,,,
-2780,"NAD83(HARN) / Georgia East",9001,4152,11031,9807,1,0,4499,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-2781,"NAD83(HARN) / Georgia West",9001,4152,11032,9807,1,0,4499,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,700000,9001,8807,0,9001,,,,,,
-2782,"NAD83(HARN) / Hawaii zone 1",9001,4152,15131,9807,1,0,4499,8801,18.5,9110,8802,-155.3,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,
-2783,"NAD83(HARN) / Hawaii zone 2",9001,4152,15132,9807,1,0,4499,8801,20.2,9110,8802,-156.4,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,
-2784,"NAD83(HARN) / Hawaii zone 3",9001,4152,15133,9807,1,0,4499,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,
-2785,"NAD83(HARN) / Hawaii zone 4",9001,4152,15134,9807,1,0,4499,8801,21.5,9110,8802,-159.3,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,
-2786,"NAD83(HARN) / Hawaii zone 5",9001,4152,15135,9807,1,0,4499,8801,21.4,9110,8802,-160.1,9110,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-2787,"NAD83(HARN) / Idaho East",9001,4152,11131,9807,1,0,4499,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,200000,9001,8807,0,9001,,,,,,
-2788,"NAD83(HARN) / Idaho Central",9001,4152,11132,9807,1,0,4499,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9001,8807,0,9001,,,,,,
-2789,"NAD83(HARN) / Idaho West",9001,4152,11133,9807,1,0,4499,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,800000,9001,8807,0,9001,,,,,,
-2790,"NAD83(HARN) / Illinois East",9001,4152,11231,9807,1,0,4499,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,300000,9001,8807,0,9001,,,,,,
-2791,"NAD83(HARN) / Illinois West",9001,4152,11232,9807,1,0,4499,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,700000,9001,8807,0,9001,,,,,,
-2792,"NAD83(HARN) / Indiana East",9001,4152,11331,9807,1,0,4499,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,100000,9001,8807,250000,9001,,,,,,
-2793,"NAD83(HARN) / Indiana West",9001,4152,11332,9807,1,0,4499,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,900000,9001,8807,250000,9001,,,,,,
-2794,"NAD83(HARN) / Iowa North",9001,4152,11431,9802,1,0,4499,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,1500000,9001,8827,1000000,9001,,,
-2795,"NAD83(HARN) / Iowa South",9001,4152,11432,9802,1,0,4499,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,500000,9001,8827,0,9001,,,
-2796,"NAD83(HARN) / Kansas North",9001,4152,11531,9802,1,0,4499,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,400000,9001,8827,0,9001,,,
-2797,"NAD83(HARN) / Kansas South",9001,4152,11532,9802,1,0,4499,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,400000,9001,8827,400000,9001,,,
-2798,"NAD83(HARN) / Kentucky North",9001,4152,15303,9802,1,0,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,500000,9001,8827,0,9001,,,
-2799,"NAD83(HARN) / Kentucky South",9001,4152,11632,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,500000,9001,8827,500000,9001,,,
-2800,"NAD83(HARN) / Louisiana North",9001,4152,11731,9802,1,0,4499,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,1000000,9001,8827,0,9001,,,
-2801,"NAD83(HARN) / Louisiana South",9001,4152,11732,9802,1,0,4499,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,1000000,9001,8827,0,9001,,,
-2802,"NAD83(HARN) / Maine East",9001,4152,11831,9807,1,0,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,300000,9001,8807,0,9001,,,,,,
-2803,"NAD83(HARN) / Maine West",9001,4152,11832,9807,1,0,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,900000,9001,8807,0,9001,,,,,,
-2804,"NAD83(HARN) / Maryland",9001,4152,11930,9802,1,0,4499,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,400000,9001,8827,0,9001,,,
-2805,"NAD83(HARN) / Massachusetts Mainland",9001,4152,12031,9802,1,0,4499,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,200000,9001,8827,750000,9001,,,
-2806,"NAD83(HARN) / Massachusetts Island",9001,4152,12032,9802,1,0,4499,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,500000,9001,8827,0,9001,,,
-2807,"NAD83(HARN) / Michigan North",9001,4152,12141,9802,1,0,4499,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,8000000,9001,8827,0,9001,,,
-2808,"NAD83(HARN) / Michigan Central",9001,4152,12142,9802,1,0,4499,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,6000000,9001,8827,0,9001,,,
-2809,"NAD83(HARN) / Michigan South",9001,4152,12143,9802,1,0,4499,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,4000000,9001,8827,0,9001,,,
-2810,"NAD83(HARN) / Minnesota North",9001,4152,12231,9802,1,0,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,800000,9001,8827,100000,9001,,,
-2811,"NAD83(HARN) / Minnesota Central",9001,4152,12232,9802,1,0,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,800000,9001,8827,100000,9001,,,
-2812,"NAD83(HARN) / Minnesota South",9001,4152,12233,9802,1,0,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,800000,9001,8827,100000,9001,,,
-2813,"NAD83(HARN) / Mississippi East",9001,4152,12331,9807,1,0,4499,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,300000,9001,8807,0,9001,,,,,,
-2814,"NAD83(HARN) / Mississippi West",9001,4152,12332,9807,1,0,4499,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,700000,9001,8807,0,9001,,,,,,
-2815,"NAD83(HARN) / Missouri East",9001,4152,12431,9807,1,0,4499,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,250000,9001,8807,0,9001,,,,,,
-2816,"NAD83(HARN) / Missouri Central",9001,4152,12432,9807,1,0,4499,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9001,8807,0,9001,,,,,,
-2817,"NAD83(HARN) / Missouri West",9001,4152,12433,9807,1,0,4499,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,850000,9001,8807,0,9001,,,,,,
-2818,"NAD83(HARN) / Montana",9001,4152,12530,9802,1,0,4499,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,600000,9001,8827,0,9001,,,
-2819,"NAD83(HARN) / Nebraska",9001,4152,12630,9802,1,0,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,500000,9001,8827,0,9001,,,
-2820,"NAD83(HARN) / Nevada East",9001,4152,12731,9807,1,0,4499,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,200000,9001,8807,8000000,9001,,,,,,
-2821,"NAD83(HARN) / Nevada Central",9001,4152,12732,9807,1,0,4499,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9001,8807,6000000,9001,,,,,,
-2822,"NAD83(HARN) / Nevada West",9001,4152,12733,9807,1,0,4499,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,800000,9001,8807,4000000,9001,,,,,,
-2823,"NAD83(HARN) / New Hampshire",9001,4152,12830,9807,1,0,4499,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,300000,9001,8807,0,9001,,,,,,
-2824,"NAD83(HARN) / New Jersey",9001,4152,12930,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,
-2825,"NAD83(HARN) / New Mexico East",9001,4152,13031,9807,1,0,4499,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,165000,9001,8807,0,9001,,,,,,
-2826,"NAD83(HARN) / New Mexico Central",9001,4152,13032,9807,1,0,4499,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-2827,"NAD83(HARN) / New Mexico West",9001,4152,13033,9807,1,0,4499,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,830000,9001,8807,0,9001,,,,,,
-2828,"NAD83(HARN) / New York East",9001,4152,13131,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,
-2829,"NAD83(HARN) / New York Central",9001,4152,13132,9807,1,0,4499,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,250000,9001,8807,0,9001,,,,,,
-2830,"NAD83(HARN) / New York West",9001,4152,13133,9807,1,0,4499,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,350000,9001,8807,0,9001,,,,,,
-2831,"NAD83(HARN) / New York Long Island",9001,4152,13134,9802,1,0,4499,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,300000,9001,8827,0,9001,,,
-2832,"NAD83(HARN) / North Dakota North",9001,4152,13331,9802,1,0,4499,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,600000,9001,8827,0,9001,,,
-2833,"NAD83(HARN) / North Dakota South",9001,4152,13332,9802,1,0,4499,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,600000,9001,8827,0,9001,,,
-2834,"NAD83(HARN) / Ohio North",9001,4152,13431,9802,1,0,4499,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,600000,9001,8827,0,9001,,,
-2835,"NAD83(HARN) / Ohio South",9001,4152,13432,9802,1,0,4499,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,600000,9001,8827,0,9001,,,
-2836,"NAD83(HARN) / Oklahoma North",9001,4152,13531,9802,1,0,4499,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,600000,9001,8827,0,9001,,,
-2837,"NAD83(HARN) / Oklahoma South",9001,4152,13532,9802,1,0,4499,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,600000,9001,8827,0,9001,,,
-2838,"NAD83(HARN) / Oregon North",9001,4152,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,
-2839,"NAD83(HARN) / Oregon South",9001,4152,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,
-2840,"NAD83(HARN) / Rhode Island",9001,4152,13830,9807,1,0,4499,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,100000,9001,8807,0,9001,,,,,,
-2841,"NAD83(HARN) / South Dakota North",9001,4152,14031,9802,1,0,4499,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,600000,9001,8827,0,9001,,,
-2842,"NAD83(HARN) / South Dakota South",9001,4152,14032,9802,1,0,4499,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,600000,9001,8827,0,9001,,,
-2843,"NAD83(HARN) / Tennessee",9001,4152,14130,9802,1,0,4499,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,600000,9001,8827,0,9001,,,
-2844,"NAD83(HARN) / Texas North",9001,4152,14231,9802,1,0,4499,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,200000,9001,8827,1000000,9001,,,
-2845,"NAD83(HARN) / Texas North Central",9001,4152,14232,9802,1,0,4499,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,600000,9001,8827,2000000,9001,,,
-2846,"NAD83(HARN) / Texas Central",9001,4152,14233,9802,1,0,4499,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,700000,9001,8827,3000000,9001,,,
-2847,"NAD83(HARN) / Texas South Central",9001,4152,14234,9802,1,0,4499,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,600000,9001,8827,4000000,9001,,,
-2848,"NAD83(HARN) / Texas South",9001,4152,14235,9802,1,0,4499,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,300000,9001,8827,5000000,9001,,,
-2849,"NAD83(HARN) / Utah North",9001,4152,14331,9802,1,0,4499,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,500000,9001,8827,1000000,9001,,,
-2850,"NAD83(HARN) / Utah Central",9001,4152,14332,9802,1,0,4499,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,500000,9001,8827,2000000,9001,,,
-2851,"NAD83(HARN) / Utah South",9001,4152,14333,9802,1,0,4499,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,500000,9001,8827,3000000,9001,,,
-2852,"NAD83(HARN) / Vermont",9001,4152,14430,9807,1,0,4499,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9001,8807,0,9001,,,,,,
-2853,"NAD83(HARN) / Virginia North",9001,4152,14531,9802,1,0,4499,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,3500000,9001,8827,2000000,9001,,,
-2854,"NAD83(HARN) / Virginia South",9001,4152,14532,9802,1,0,4499,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,3500000,9001,8827,1000000,9001,,,
-2855,"NAD83(HARN) / Washington North",9001,4152,14631,9802,1,0,4499,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,500000,9001,8827,0,9001,,,
-2856,"NAD83(HARN) / Washington South",9001,4152,14632,9802,1,0,4499,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,500000,9001,8827,0,9001,,,
-2857,"NAD83(HARN) / West Virginia North",9001,4152,14731,9802,1,0,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,600000,9001,8827,0,9001,,,
-2858,"NAD83(HARN) / West Virginia South",9001,4152,14732,9802,1,0,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,600000,9001,8827,0,9001,,,
-2859,"NAD83(HARN) / Wisconsin North",9001,4152,14831,9802,1,0,4499,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,600000,9001,8827,0,9001,,,
-2860,"NAD83(HARN) / Wisconsin Central",9001,4152,14832,9802,1,0,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,
-2861,"NAD83(HARN) / Wisconsin South",9001,4152,14833,9802,1,0,4499,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,600000,9001,8827,0,9001,,,
-2862,"NAD83(HARN) / Wyoming East",9001,4152,14931,9807,1,0,4499,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,200000,9001,8807,0,9001,,,,,,
-2863,"NAD83(HARN) / Wyoming East Central",9001,4152,14932,9807,1,0,4499,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,400000,9001,8807,100000,9001,,,,,,
-2864,"NAD83(HARN) / Wyoming West Central",9001,4152,14933,9807,1,0,4499,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,600000,9001,8807,0,9001,,,,,,
-2865,"NAD83(HARN) / Wyoming West",9001,4152,14934,9807,1,0,4499,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,800000,9001,8807,100000,9001,,,,,,
-2866,"NAD83(HARN) / Puerto Rico and Virgin Is.",9001,4152,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,
-2867,"NAD83(HARN) / Arizona East (ft)",9002,4152,15304,9807,1,0,4495,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,
-2868,"NAD83(HARN) / Arizona Central (ft)",9002,4152,15305,9807,1,0,4495,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,
-2869,"NAD83(HARN) / Arizona West (ft)",9002,4152,15306,9807,1,0,4495,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,700000,9002,8807,0,9002,,,,,,
-2870,"NAD83(HARN) / California zone 1 (ftUS)",9003,4152,15307,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2871,"NAD83(HARN) / California zone 2 (ftUS)",9003,4152,15308,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2872,"NAD83(HARN) / California zone 3 (ftUS)",9003,4152,15309,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2873,"NAD83(HARN) / California zone 4 (ftUS)",9003,4152,15310,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2874,"NAD83(HARN) / California zone 5 (ftUS)",9003,4152,15311,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2875,"NAD83(HARN) / California zone 6 (ftUS)",9003,4152,15312,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-2876,"NAD83(HARN) / Colorado North (ftUS)",9003,4152,15313,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,3000000,9003,8827,1000000,9003,,,
-2877,"NAD83(HARN) / Colorado Central (ftUS)",9003,4152,15314,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,3000000,9003,8827,1000000,9003,,,
-2878,"NAD83(HARN) / Colorado South (ftUS)",9003,4152,15315,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,3000000,9003,8827,1000000,9003,,,
-2879,"NAD83(HARN) / Connecticut (ftUS)",9003,4152,15316,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,1000000,9003,8827,500000,9003,,,
-2880,"NAD83(HARN) / Delaware (ftUS)",9003,4152,15317,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2881,"NAD83(HARN) / Florida East (ftUS)",9003,4152,15318,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2882,"NAD83(HARN) / Florida West (ftUS)",9003,4152,15319,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2883,"NAD83(HARN) / Florida North (ftUS)",9003,4152,15320,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,1968500,9003,8827,0,9003,,,
-2884,"NAD83(HARN) / Georgia East (ftUS)",9003,4152,15321,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2885,"NAD83(HARN) / Georgia West (ftUS)",9003,4152,15322,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,2296583.333,9003,8807,0,9003,,,,,,
-2886,"NAD83(HARN) / Idaho East (ftUS)",9003,4152,15323,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-2887,"NAD83(HARN) / Idaho Central (ftUS)",9003,4152,15324,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,1640416.667,9003,8807,0,9003,,,,,,
-2888,"NAD83(HARN) / Idaho West (ftUS)",9003,4152,15325,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,2624666.667,9003,8807,0,9003,,,,,,
-2889,"NAD83(HARN) / Indiana East (ftUS)",9003,4152,15326,9807,1,1,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,818125,9003,,,,,,
-2890,"NAD83(HARN) / Indiana West (ftUS)",9003,4152,15327,9807,1,1,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,818125,9003,,,,,,
-2891,"NAD83(HARN) / Kentucky North (ftUS)",9003,4152,15328,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,1640416.667,9003,8827,0,9003,,,
-2892,"NAD83(HARN) / Kentucky South (ftUS)",9003,4152,15329,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,1640416.667,9003,8827,1640416.667,9003,,,
-2893,"NAD83(HARN) / Maryland (ftUS)",9003,4152,15330,9802,1,0,4497,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,1312333.333,9003,8827,0,9003,,,
-2894,"NAD83(HARN) / Massachusetts Mainland (ftUS)",9003,4152,15331,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,656166.667,9003,8827,2460625,9003,,,
-2895,"NAD83(HARN) / Massachusetts Island (ftUS)",9003,4152,15332,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,1640416.667,9003,8827,0,9003,,,
-2896,"NAD83(HARN) / Michigan North (ft)",9002,4152,15333,9802,1,0,4495,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,26246719.16,9002,8827,0,9002,,,
-2897,"NAD83(HARN) / Michigan Central (ft)",9002,4152,15334,9802,1,0,4495,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,19685039.37,9002,8827,0,9002,,,
-2898,"NAD83(HARN) / Michigan South (ft)",9002,4152,15335,9802,1,0,4495,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,13123359.58,9002,8827,0,9002,,,
-2899,"NAD83(HARN) / Mississippi East (ftUS)",9003,4152,15336,9807,1,0,4497,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,984250,9003,8807,0,9003,,,,,,
-2900,"NAD83(HARN) / Mississippi West (ftUS)",9003,4152,15337,9807,1,0,4497,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,2296583.333,9003,8807,0,9003,,,,,,
-2901,"NAD83(HARN) / Montana (ft)",9002,4152,15338,9802,1,0,4495,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,1968503.937,9002,8827,0,9002,,,
-2902,"NAD83(HARN) / New Mexico East (ftUS)",9003,4152,15339,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,541337.5,9003,8807,0,9003,,,,,,
-2903,"NAD83(HARN) / New Mexico Central (ftUS)",9003,4152,15340,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,1640416.667,9003,8807,0,9003,,,,,,
-2904,"NAD83(HARN) / New Mexico West (ftUS)",9003,4152,15341,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,2723091.667,9003,8807,0,9003,,,,,,
-2905,"NAD83(HARN) / New York East (ftUS)",9003,4152,15342,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,
-2906,"NAD83(HARN) / New York Central (ftUS)",9003,4152,15343,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,820208.333,9003,8807,0,9003,,,,,,
-2907,"NAD83(HARN) / New York West (ftUS)",9003,4152,15344,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,1148291.667,9003,8807,0,9003,,,,,,
-2908,"NAD83(HARN) / New York Long Island (ftUS)",9003,4152,15345,9802,1,0,4497,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,984250,9003,8827,0,9003,,,
-2909,"NAD83(HARN) / North Dakota North (ft)",9002,4152,15347,9802,1,0,4495,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,1968503.937,9002,8827,0,9002,,,
-2910,"NAD83(HARN) / North Dakota South (ft)",9002,4152,15348,9802,1,0,4495,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,1968503.937,9002,8827,0,9002,,,
-2911,"NAD83(HARN) / Oklahoma North (ftUS)",9003,4152,15349,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,1968500,9003,8827,0,9003,,,
-2912,"NAD83(HARN) / Oklahoma South (ftUS)",9003,4152,15350,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,1968500,9003,8827,0,9003,,,
-2913,"NAD83(HARN) / Oregon North (ft)",9002,4152,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,
-2914,"NAD83(HARN) / Oregon South (ft)",9002,4152,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,
-2915,"NAD83(HARN) / Tennessee (ftUS)",9003,4152,15356,9802,1,0,4497,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,1968500,9003,8827,0,9003,,,
-2916,"NAD83(HARN) / Texas North (ftUS)",9003,4152,15357,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,656166.667,9003,8827,3280833.333,9003,,,
-2917,"NAD83(HARN) / Texas North Central (ftUS)",9003,4152,15358,9802,1,0,4497,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,1968500,9003,8827,6561666.667,9003,,,
-2918,"NAD83(HARN) / Texas Central (ftUS)",9003,4152,15359,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,2296583.333,9003,8827,9842500,9003,,,
-2919,"NAD83(HARN) / Texas South Central (ftUS)",9003,4152,15360,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,1968500,9003,8827,13123333.333,9003,,,
-2920,"NAD83(HARN) / Texas South (ftUS)",9003,4152,15361,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,984250,9003,8827,16404166.667,9003,,,
-2921,"NAD83(HARN) / Utah North (ft)",9002,4152,15362,9802,0,0,4495,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640419.948,9002,8827,3280839.895,9002,,,
-2922,"NAD83(HARN) / Utah Central (ft)",9002,4152,15363,9802,0,0,4495,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640419.948,9002,8827,6561679.79,9002,,,
-2923,"NAD83(HARN) / Utah South (ft)",9002,4152,15364,9802,0,0,4495,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640419.948,9002,8827,9842519.685,9002,,,
-2924,"NAD83(HARN) / Virginia North (ftUS)",9003,4152,15365,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,11482916.667,9003,8827,6561666.667,9003,,,
-2925,"NAD83(HARN) / Virginia South (ftUS)",9003,4152,15366,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,11482916.667,9003,8827,3280833.333,9003,,,
-2926,"NAD83(HARN) / Washington North (ftUS)",9003,4152,15367,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,1640416.667,9003,8827,0,9003,,,
-2927,"NAD83(HARN) / Washington South (ftUS)",9003,4152,15368,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,1640416.667,9003,8827,0,9003,,,
-2928,"NAD83(HARN) / Wisconsin North (ftUS)",9003,4152,15369,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,1968500,9003,8827,0,9003,,,
-2929,"NAD83(HARN) / Wisconsin Central (ftUS)",9003,4152,15370,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,1968500,9003,8827,0,9003,,,
-2930,"NAD83(HARN) / Wisconsin South (ftUS)",9003,4152,15371,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,1968500,9003,8827,0,9003,,,
-2931,"Beduaram / TM 13 NE",9001,4213,16413,9807,1,0,4499,8801,0,9102,8802,13,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2932,"QND95 / Qatar National Grid",9001,4614,19919,9807,1,0,4400,8801,24.27,9110,8802,51.13,9110,8805,0.99999,9201,8806,200000,9001,8807,300000,9001,,,,,,
-2933,"Segara / UTM zone 50S",9001,4613,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2934,"Segara (Jakarta) / NEIEZ",9001,4820,19905,9804,1,1,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
-2935,"Pulkovo 1942 / CS63 zone A1",9001,4284,18441,9807,1,0,4530,8801,0.07,9110,8802,41.32,9110,8805,1,9201,8806,1300000,9001,8807,0,9001,,,,,,
-2936,"Pulkovo 1942 / CS63 zone A2",9001,4284,18442,9807,1,0,4530,8801,0.07,9110,8802,44.32,9110,8805,1,9201,8806,2300000,9001,8807,0,9001,,,,,,
-2937,"Pulkovo 1942 / CS63 zone A3",9001,4284,18443,9807,1,0,4530,8801,0.07,9110,8802,47.32,9110,8805,1,9201,8806,3300000,9001,8807,0,9001,,,,,,
-2938,"Pulkovo 1942 / CS63 zone A4",9001,4284,18444,9807,1,0,4530,8801,0.07,9110,8802,50.32,9110,8805,1,9201,8806,4300000,9001,8807,0,9001,,,,,,
-2939,"Pulkovo 1942 / CS63 zone K2",9001,4284,18446,9807,1,0,4530,8801,0.08,9110,8802,50.46,9110,8805,1,9201,8806,2300000,9001,8807,0,9001,,,,,,
-2940,"Pulkovo 1942 / CS63 zone K3",9001,4284,18447,9807,1,0,4530,8801,0.08,9110,8802,53.46,9110,8805,1,9201,8806,3300000,9001,8807,0,9001,,,,,,
-2941,"Pulkovo 1942 / CS63 zone K4",9001,4284,18448,9807,1,0,4530,8801,0.08,9110,8802,56.46,9110,8805,1,9201,8806,4300000,9001,8807,0,9001,,,,,,
-2942,"Porto Santo / UTM zone 28N",9001,4615,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2943,"Selvagem Grande / UTM zone 28N",9001,4616,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2944,"NAD83(CSRS) / SCoPQ zone 2",9001,4617,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2945,"NAD83(CSRS) / MTM zone 3",9001,4617,17703,9807,1,0,4496,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2946,"NAD83(CSRS) / MTM zone 4",9001,4617,17704,9807,1,0,4496,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2947,"NAD83(CSRS) / MTM zone 5",9001,4617,17705,9807,1,0,4496,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2948,"NAD83(CSRS) / MTM zone 6",9001,4617,17706,9807,1,0,4496,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2949,"NAD83(CSRS) / MTM zone 7",9001,4617,17707,9807,1,0,4496,8801,0,9110,8802,-70.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2950,"NAD83(CSRS) / MTM zone 8",9001,4617,17708,9807,1,0,4496,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2951,"NAD83(CSRS) / MTM zone 9",9001,4617,17709,9807,1,0,4496,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2952,"NAD83(CSRS) / MTM zone 10",9001,4617,17710,9807,1,0,4496,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-2953,"NAD83(CSRS) / New Brunswick Stereographic",9001,4617,19946,9809,1,0,4500,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,2500000,9001,8807,7500000,9001,,,,,,
-2954,"NAD83(CSRS) / Prince Edward Isl. Stereographic (NAD83)",9001,4617,19960,9809,1,0,4496,8801,47.15,9110,8802,-63,9110,8805,0.999912,9201,8806,400000,9001,8807,800000,9001,,,,,,
-2955,"NAD83(CSRS) / UTM zone 11N",9001,4617,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2956,"NAD83(CSRS) / UTM zone 12N",9001,4617,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2957,"NAD83(CSRS) / UTM zone 13N",9001,4617,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2958,"NAD83(CSRS) / UTM zone 17N",9001,4617,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2959,"NAD83(CSRS) / UTM zone 18N",9001,4617,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2960,"NAD83(CSRS) / UTM zone 19N",9001,4617,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2961,"NAD83(CSRS) / UTM zone 20N",9001,4617,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2962,"NAD83(CSRS) / UTM zone 21N",9001,4617,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2963,"Lisbon 1890 (Lisbon) / Portugal Bonne",9001,4904,19979,9828,1,0,6509,8801,39.4,9110,8802,1,9110,8806,0,9001,8807,0,9001,,,,,,,,,
-2964,"NAD27 / Alaska Albers",9003,4267,15020,9822,1,0,4497,8821,50,9102,8822,-154,9102,8823,55,9102,8824,65,9102,8826,0,9003,8827,0,9003,,,
-2965,"NAD83 / Indiana East (ftUS)",9003,4269,15372,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,820208.333,9003,,,,,,
-2966,"NAD83 / Indiana West (ftUS)",9003,4269,15373,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,820208.333,9003,,,,,,
-2967,"NAD83(HARN) / Indiana East (ftUS)",9003,4152,15372,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,820208.333,9003,,,,,,
-2968,"NAD83(HARN) / Indiana West (ftUS)",9003,4152,15373,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,820208.333,9003,,,,,,
-2969,"Fort Marigot / UTM zone 20N",9001,4621,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2970,"Guadeloupe 1948 / UTM zone 20N",9001,4622,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2971,"CSG67 / UTM zone 22N",9001,4623,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2972,"RGFG95 / UTM zone 22N",9001,4624,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2973,"Martinique 1938 / UTM zone 20N",9001,4625,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2975,"RGR92 / UTM zone 40S",9001,4627,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2976,"Tahiti 52 / UTM zone 6S",9001,4628,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2977,"Tahaa 54 / UTM zone 5S",9001,4629,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2978,"IGN72 Nuku Hiva / UTM zone 7S",9001,4630,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2979,"K0 1949 / UTM zone 42S",9001,4631,16142,9807,1,1,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2980,"Combani 1950 / UTM zone 38S",9001,4632,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2981,"IGN56 Lifou / UTM zone 58S",9001,4633,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2982,"IGN72 Grand Terre / UTM zone 58S",9001,4634,16158,9807,1,1,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2983,"ST87 Ouvea / UTM zone 58S",9001,4635,16158,9807,1,1,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2984,"RGNC 1991 / Lambert New Caledonia",9001,4645,19981,9802,1,1,4499,8821,-21.3,9110,8822,166,9110,8823,-20.4,9110,8824,-22.2,9110,8826,400000,9001,8827,300000,9001,,,
-2985,"Petrels 1972 / Terre Adelie Polar Stereographic",9001,4636,19983,9830,1,0,1025,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,
-2986,"Perroud 1950 / Terre Adelie Polar Stereographic",9001,4637,19983,9830,1,0,1025,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,
-2987,"Saint Pierre et Miquelon 1950 / UTM zone 21N",9001,4638,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2988,"MOP78 / UTM zone 1S",9001,4639,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2989,"RRAF 1991 / UTM zone 20N",9001,4640,16020,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-2990,"Reunion 1947 / TM Reunion",9001,4626,19982,9807,1,1,4499,8801,-21.07,9110,8802,55.32,9110,8805,1,9201,8806,50000,9001,8807,160000,9001,,,,,,
-2991,"NAD83 / Oregon LCC (m)",9001,4269,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,
-2992,"NAD83 / Oregon GIC Lambert (ft)",9002,4269,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,
-2993,"NAD83(HARN) / Oregon LCC (m)",9001,4152,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,
-2994,"NAD83(HARN) / Oregon GIC Lambert (ft)",9002,4152,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,
-2995,"IGN53 Mare / UTM zone 58S",9001,4641,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2996,"ST84 Ile des Pins / UTM zone 58S",9001,4642,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2997,"ST71 Belep / UTM zone 58S",9001,4643,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2998,"NEA74 Noumea / UTM zone 58S",9001,4644,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-2999,"Grand Comoros / UTM zone 38S",9001,4646,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3000,"Segara / NEIEZ",9001,4613,19905,9804,1,0,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
-3001,"Batavia / NEIEZ",9001,4211,19905,9804,1,0,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
-3002,"Makassar / NEIEZ",9001,4257,19905,9804,1,0,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
-3003,"Monte Mario / Italy zone 1",9001,4265,18121,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3004,"Monte Mario / Italy zone 2",9001,4265,18122,9807,1,0,4499,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,2520000,9001,8807,0,9001,,,,,,
-3005,"NAD83 / BC Albers",9001,4269,19984,9822,1,0,4400,8821,45,9102,8822,-126,9102,8823,50,9110,8824,58.3,9110,8826,1000000,9001,8827,0,9001,,,
-3006,SWEREF99 TM,9001,4619,17333,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3007,SWEREF99 12 00,9001,4619,17321,9807,1,0,4500,8801,0,9102,8802,12,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3008,SWEREF99 13 30,9001,4619,17322,9807,1,0,4500,8801,0,9110,8802,13.3,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3009,SWEREF99 15 00,9001,4619,17323,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3010,SWEREF99 16 30,9001,4619,17324,9807,1,0,4500,8801,0,9110,8802,16.3,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3011,SWEREF99 18 00,9001,4619,17325,9807,1,0,4500,8801,0,9102,8802,18,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3012,SWEREF99 14 15,9001,4619,17326,9807,1,0,4500,8801,0,9110,8802,14.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3013,SWEREF99 15 45,9001,4619,17327,9807,1,0,4500,8801,0,9110,8802,15.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3014,SWEREF99 17 15,9001,4619,17328,9807,1,0,4500,8801,0,9110,8802,17.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3015,SWEREF99 18 45,9001,4619,17329,9807,1,0,4500,8801,0,9110,8802,18.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3016,SWEREF99 20 15,9001,4619,17330,9807,1,0,4500,8801,0,9110,8802,20.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3017,SWEREF99 21 45,9001,4619,17331,9807,1,0,4500,8801,0,9110,8802,21.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3018,SWEREF99 23 15,9001,4619,17332,9807,1,0,4500,8801,0,9110,8802,23.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-3019,RT90 7.5 gon V,9001,4124,17334,9807,1,0,4530,8801,0,9110,8802,11.18298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3020,RT90 5 gon V,9001,4124,17335,9807,1,0,4530,8801,0,9110,8802,13.33298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3021,RT90 2.5 gon V,9001,4124,19929,9807,1,0,4530,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3022,RT90 0 gon,9001,4124,17336,9807,1,0,4530,8801,0,9110,8802,18.03298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3023,RT90 2.5 gon O,9001,4124,17337,9807,1,0,4530,8801,0,9110,8802,20.18298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3024,RT90 5 gon O,9001,4124,17338,9807,1,0,4530,8801,0,9110,8802,22.33298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3025,RT38 7.5 gon V,9001,4308,17334,9807,1,0,4530,8801,0,9110,8802,11.18298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3026,RT38 5 gon V,9001,4308,17335,9807,1,0,4530,8801,0,9110,8802,13.33298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3027,RT38 2.5 gon V,9001,4308,19929,9807,1,0,4530,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3028,RT38 0 gon,9001,4308,17336,9807,1,0,4530,8801,0,9110,8802,18.03298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3029,RT38 2.5 gon O,9001,4308,17337,9807,1,0,4530,8801,0,9110,8802,20.18298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3030,RT38 5 gon O,9001,4308,17338,9807,1,0,4530,8801,0,9110,8802,22.33298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-3031,"WGS 84 / Antarctic Polar Stereographic",9001,4326,19992,9829,1,0,4490,8806,0,9001,8807,0,9001,8832,-71,9102,8833,0,9102,,,,,,,,,
-3032,"WGS 84 / Australian Antarctic Polar Stereographic",9001,4326,19993,9829,1,0,4489,8806,6000000,9001,8807,6000000,9001,8832,-71,9102,8833,70,9102,,,,,,,,,
-3033,"WGS 84 / Australian Antarctic Lambert",9001,4326,19994,9802,1,0,4400,8821,-50,9110,8822,70,9110,8823,-68.3,9110,8824,-74.3,9110,8826,6000000,9001,8827,6000000,9001,,,
-3034,"ETRS89 / LCC Europe",9001,4258,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,
-3035,"ETRS89 / LAEA Europe",9001,4258,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,
-3036,"Moznet / UTM zone 36S",9001,4130,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3037,"Moznet / UTM zone 37S",9001,4130,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3038,"ETRS89 / TM26",9001,4258,16026,9807,1,1,4500,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3039,"ETRS89 / TM27",9001,4258,16027,9807,1,1,4500,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3040,"ETRS89 / UTM zone 28N (N-E)",9001,4258,16028,9807,1,0,4500,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3041,"ETRS89 / UTM zone 29N (N-E)",9001,4258,16029,9807,1,0,4500,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3042,"ETRS89 / UTM zone 30N (N-E)",9001,4258,16030,9807,1,0,4500,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3043,"ETRS89 / UTM zone 31N (N-E)",9001,4258,16031,9807,1,0,4500,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3044,"ETRS89 / UTM zone 32N (N-E)",9001,4258,16032,9807,1,0,4500,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3045,"ETRS89 / UTM zone 33N (N-E)",9001,4258,16033,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3046,"ETRS89 / UTM zone 34N (N-E)",9001,4258,16034,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3047,"ETRS89 / UTM zone 35N (N-E)",9001,4258,16035,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3048,"ETRS89 / UTM zone 36N (N-E)",9001,4258,16036,9807,1,0,4500,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3049,"ETRS89 / UTM zone 37N (N-E)",9001,4258,16037,9807,1,0,4500,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3050,"ETRS89 / TM38",9001,4258,16038,9807,1,1,4500,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3051,"ETRS89 / TM39",9001,4258,16039,9807,1,1,4500,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3052,"Reykjavik 1900 / Lambert 1900",9001,4657,19987,9826,1,0,4491,8801,65,9110,8802,-19.011965,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-3053,"Hjorsey 1955 / Lambert 1955",9001,4658,19988,9826,1,0,4491,8801,65,9102,8802,-18,9102,8805,1,9201,8806,500000,9001,8807,500000,9001,,,,,,
-3054,"Hjorsey 1955 / UTM zone 26N",9001,4658,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3055,"Hjorsey 1955 / UTM zone 27N",9001,4658,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3056,"Hjorsey 1955 / UTM zone 28N",9001,4658,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3057,"ISN93 / Lambert 1993",9001,4659,19989,9802,1,0,4499,8821,65,9110,8822,-19,9110,8823,64.15,9110,8824,65.45,9110,8826,500000,9001,8827,500000,9001,,,
-3058,"Helle 1954 / Jan Mayen Grid",9001,4660,19991,9807,1,0,4531,8801,0,9110,8802,-8.3,9110,8805,1,9201,8806,50000,9001,8807,-7800000,9001,,,,,,
-3059,"LKS92 / Latvia TM",9001,4661,19990,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,0.9996,9201,8806,500000,9001,8807,-6000000,9001,,,,,,
-3060,"IGN72 Grande Terre / UTM zone 58S",9001,4662,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3061,"Porto Santo 1995 / UTM zone 28N",9001,4663,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3062,"Azores Oriental 1995 / UTM zone 26N",9001,4664,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3063,"Azores Central 1995 / UTM zone 26N",9001,4665,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3064,"IGM95 / UTM zone 32N",9001,4670,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3065,"IGM95 / UTM zone 33N",9001,4670,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3066,"ED50 / Jordan TM",9001,4230,19995,9807,1,0,4400,8801,0,9102,8802,37,9102,8805,0.9998,9201,8806,500000,9001,8807,-3000000,9001,,,,,,
-3067,"ETRS89 / TM35FIN(E,N)",9001,4258,16065,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3068,"DHDN / Soldner Berlin",9001,4314,19996,9806,1,0,4531,8801,52.25071338,9110,8802,13.37379332,9110,8806,40000,9001,8807,10000,9001,,,,,,,,,
-3069,"NAD27 / Wisconsin Transverse Mercator",9001,4267,14811,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,500000,9001,8807,-4500000,9001,,,,,,
-3070,"NAD83 / Wisconsin Transverse Mercator",9001,4269,14841,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,520000,9001,8807,-4480000,9001,,,,,,
-3071,"NAD83(HARN) / Wisconsin Transverse Mercator",9001,4152,14841,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,520000,9001,8807,-4480000,9001,,,,,,
-3072,"NAD83 / Maine CS2000 East",9001,4269,11851,9807,1,0,4499,8801,43.5,9110,8802,-67.523,9110,8805,0.99998,9201,8806,700000,9001,8807,0,9001,,,,,,
-3073,"NAD83 / Maine CS2000 Central",9001,4269,11852,9807,1,1,4499,8801,43,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,
-3074,"NAD83 / Maine CS2000 West",9001,4269,11853,9807,1,0,4499,8801,42.5,9110,8802,-70.223,9110,8805,0.99998,9201,8806,300000,9001,8807,0,9001,,,,,,
-3075,"NAD83(HARN) / Maine CS2000 East",9001,4152,11851,9807,1,0,4499,8801,43.5,9110,8802,-67.523,9110,8805,0.99998,9201,8806,700000,9001,8807,0,9001,,,,,,
-3076,"NAD83(HARN) / Maine CS2000 Central",9001,4152,11852,9807,1,1,4499,8801,43,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,
-3077,"NAD83(HARN) / Maine CS2000 West",9001,4152,11853,9807,1,0,4499,8801,42.5,9110,8802,-70.223,9110,8805,0.99998,9201,8806,300000,9001,8807,0,9001,,,,,,
-3078,"NAD83 / Michigan Oblique Mercator",9001,4269,12150,9812,1,0,4499,8806,2546731.496,9001,8807,-4354009.816,9001,8811,45.1833,9110,8812,-86,9110,8813,337.25556,9102,8814,337.25556,9102,8815,0.9996,9201
-3079,"NAD83(HARN) / Michigan Oblique Mercator",9001,4152,12150,9812,1,0,4499,8806,2546731.496,9001,8807,-4354009.816,9001,8811,45.1833,9110,8812,-86,9110,8813,337.25556,9102,8814,337.25556,9102,8815,0.9996,9201
-3080,"NAD27 / Shackleford",9002,4267,14252,9802,1,0,4495,8821,31.1,9110,8822,-100,9110,8823,27.25,9110,8824,34.55,9110,8826,3000000,9002,8827,3000000,9002,,,
-3081,"NAD83 / Texas State Mapping System",9001,4269,14251,9802,1,0,4499,8821,31.1,9110,8822,-100,9110,8823,27.25,9110,8824,34.55,9110,8826,1000000,9001,8827,1000000,9001,,,
-3082,"NAD83 / Texas Centric Lambert Conformal",9001,4269,14253,9802,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,5000000,9001,,,
-3083,"NAD83 / Texas Centric Albers Equal Area",9001,4269,14254,9822,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,6000000,9001,,,
-3084,"NAD83(HARN) / Texas Centric Lambert Conformal",9001,4152,14253,9802,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,5000000,9001,,,
-3085,"NAD83(HARN) / Texas Centric Albers Equal Area",9001,4152,14254,9822,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,6000000,9001,,,
-3086,"NAD83 / Florida GDL Albers",9001,4269,10934,9822,1,0,4499,8821,24,9110,8822,-84,9110,8823,24,9110,8824,31.3,9110,8826,400000,9001,8827,0,9001,,,
-3087,"NAD83(HARN) / Florida GDL Albers",9001,4152,10934,9822,1,0,4499,8821,24,9110,8822,-84,9110,8823,24,9110,8824,31.3,9110,8826,400000,9001,8827,0,9001,,,
-3088,"NAD83 / Kentucky Single Zone",9001,4269,11630,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,1500000,9001,8827,1000000,9001,,,
-3089,"NAD83 / Kentucky Single Zone (ftUS)",9003,4269,15375,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,4921250,9003,8827,3280833.333,9003,,,
-3090,"NAD83(HARN) / Kentucky Single Zone",9001,4152,11630,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,1500000,9001,8827,1000000,9001,,,
-3091,"NAD83(HARN) / Kentucky Single Zone (ftUS)",9003,4152,15375,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,4921250,9003,8827,3280833.333,9003,,,
-3092,"Tokyo / UTM zone 51N",9001,4301,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3093,"Tokyo / UTM zone 52N",9001,4301,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3094,"Tokyo / UTM zone 53N",9001,4301,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3095,"Tokyo / UTM zone 54N",9001,4301,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3096,"Tokyo / UTM zone 55N",9001,4301,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3097,"JGD2000 / UTM zone 51N",9001,4612,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3098,"JGD2000 / UTM zone 52N",9001,4612,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3099,"JGD2000 / UTM zone 53N",9001,4612,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3100,"JGD2000 / UTM zone 54N",9001,4612,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3101,"JGD2000 / UTM zone 55N",9001,4612,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3102,"American Samoa 1962 / American Samoa Lambert",9003,4169,15376,9801,1,0,4497,8801,-14.16,9110,8802,-170,9110,8805,1,9201,8806,500000,9003,8807,312234.65,9003,,,,,,
-3103,"Mauritania 1999 / UTM zone 28N",9001,4681,16028,9807,1,1,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3104,"Mauritania 1999 / UTM zone 29N",9001,4681,16029,9807,1,1,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3105,"Mauritania 1999 / UTM zone 30N",9001,4681,16030,9807,1,1,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3106,"Gulshan 303 / Bangladesh Transverse Mercator",9001,4682,16490,9807,1,0,4400,8801,0,9102,8802,90,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3107,"GDA94 / SA Lambert",9001,4283,17359,9802,1,0,4400,8821,-32,9102,8822,135,9102,8823,-28,9102,8824,-36,9102,8826,1000000,9001,8827,2000000,9001,,,
-3108,"ETRS89 / Guernsey Grid",9001,4258,19998,9807,1,0,4400,8801,49.3,9110,8802,-2.25,9110,8805,0.999997,9201,8806,47000,9001,8807,50000,9001,,,,,,
-3109,"ETRS89 / Jersey Transverse Mercator",9001,4258,19999,9807,1,0,4400,8801,49.225,9102,8802,-2.135,9102,8805,0.9999999,9201,8806,40000,9001,8807,70000,9001,,,,,,
-3110,"AGD66 / Vicgrid66",9001,4202,17360,9802,1,0,4400,8821,-37,9102,8822,145,9102,8823,-36,9102,8824,-38,9102,8826,2500000,9001,8827,4500000,9001,,,
-3111,"GDA94 / Vicgrid94",9001,4283,17361,9802,1,0,4400,8821,-37,9102,8822,145,9102,8823,-36,9102,8824,-38,9102,8826,2500000,9001,8827,2500000,9001,,,
-3112,"GDA94 / Geoscience Australia Lambert",9001,4283,17362,9802,1,0,4400,8821,0,9102,8822,134,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,
-3113,"GDA94 / BCSG02",9001,4283,17363,9807,1,0,4400,8801,-28,9102,8802,153,9102,8805,0.99999,9201,8806,50000,9001,8807,100000,9001,,,,,,
-3114,"MAGNA-SIRGAS / Colombia Far West zone",9001,4686,18055,9807,1,0,4500,8801,4.35463215,9110,8802,-80.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-3115,"MAGNA-SIRGAS / Colombia West zone",9001,4686,18056,9807,1,0,4500,8801,4.35463215,9110,8802,-77.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-3116,"MAGNA-SIRGAS / Colombia Bogota zone",9001,4686,18057,9807,1,0,4500,8801,4.35463215,9110,8802,-74.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-3117,"MAGNA-SIRGAS / Colombia East Central zone",9001,4686,18058,9807,1,0,4500,8801,4.35463215,9110,8802,-71.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-3118,"MAGNA-SIRGAS / Colombia East zone",9001,4686,18059,9807,1,0,4500,8801,4.35463215,9110,8802,-68.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-3119,"Douala 1948 / AEF west",9001,4192,18415,9807,1,0,4400,8801,0,9110,8802,10.3,9110,8805,0.999,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-3120,"Pulkovo 1942(58) / Poland zone I",9001,4179,18280,9809,1,0,4530,8801,50.373,9110,8802,21.05,9110,8805,0.9998,9201,8806,4637000,9001,8807,5467000,9001,,,,,,
-3121,"PRS92 / Philippines zone 1",9001,4683,18171,9807,1,0,4499,8801,0,9102,8802,117,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-3122,"PRS92 / Philippines zone 2",9001,4683,18172,9807,1,0,4499,8801,0,9102,8802,119,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-3123,"PRS92 / Philippines zone 3",9001,4683,18173,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-3124,"PRS92 / Philippines zone 4",9001,4683,18174,9807,1,0,4499,8801,0,9102,8802,123,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-3125,"PRS92 / Philippines zone 5",9001,4683,18175,9807,1,0,4499,8801,0,9102,8802,125,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-3126,"ETRS89 / ETRS-GK19FIN",9001,4258,18183,9807,1,0,4500,8801,0,9102,8802,19,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3127,"ETRS89 / ETRS-GK20FIN",9001,4258,18184,9807,1,0,4500,8801,0,9102,8802,20,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3128,"ETRS89 / ETRS-GK21FIN",9001,4258,18185,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3129,"ETRS89 / ETRS-GK22FIN",9001,4258,18186,9807,1,0,4500,8801,0,9102,8802,22,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3130,"ETRS89 / ETRS-GK23FIN",9001,4258,18187,9807,1,0,4500,8801,0,9102,8802,23,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3131,"ETRS89 / ETRS-GK24FIN",9001,4258,18188,9807,1,0,4500,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3132,"ETRS89 / ETRS-GK25FIN",9001,4258,18189,9807,1,0,4500,8801,0,9102,8802,25,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3133,"ETRS89 / ETRS-GK26FIN",9001,4258,18190,9807,1,0,4500,8801,0,9102,8802,26,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3134,"ETRS89 / ETRS-GK27FIN",9001,4258,18195,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3135,"ETRS89 / ETRS-GK28FIN",9001,4258,18196,9807,1,0,4500,8801,0,9102,8802,28,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3136,"ETRS89 / ETRS-GK29FIN",9001,4258,18197,9807,1,0,4500,8801,0,9102,8802,29,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3137,"ETRS89 / ETRS-GK30FIN",9001,4258,18198,9807,1,0,4500,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3138,"ETRS89 / ETRS-GK31FIN",9001,4258,18199,9807,1,0,4500,8801,0,9102,8802,31,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3139,"Vanua Levu 1915 / Vanua Levu Grid",9098,4748,19878,9833,1,0,4533,8801,-16.15,9110,8802,179.2,9110,8806,1251331.8,9098,8807,1662888.5,9098,,,,,,,,,
-3140,"Viti Levu 1912 / Viti Levu Grid",9098,4752,19879,9806,1,0,4533,8801,-18,9102,8802,178,9102,8806,544000,9098,8807,704000,9098,,,,,,,,,
-3141,"Fiji 1956 / UTM zone 60S",9001,4721,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3142,"Fiji 1956 / UTM zone 1S",9001,4721,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3143,"Fiji 1986 / Fiji Map Grid",9001,4720,19880,9807,1,1,4400,8801,-17,9110,8802,178.45,9110,8805,0.99985,9001,8806,2000000,9001,8807,4000000,9001,,,,,,
-3144,"FD54 / Faroe Lambert",9001,4741,19870,9826,1,0,1031,8801,62,9102,8802,-9,9102,8805,1,9201,8806,500000,9001,8807,500000,9001,,,,,,
-3145,"ETRS89 / Faroe Lambert",9001,4258,19870,9826,1,0,1031,8801,62,9102,8802,-9,9102,8805,1,9201,8806,500000,9001,8807,500000,9001,,,,,,
-3146,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 6",9001,4284,16266,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-3147,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 18E",9001,4284,16366,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3148,"Indian 1960 / UTM zone 48N",9001,4131,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3149,"Indian 1960 / UTM zone 49N",9001,4131,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3150,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 6",9001,4200,16266,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-3151,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 18E",9001,4200,16366,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3152,ST74,9001,4619,19876,9807,1,0,4531,8801,0,9110,8802,18.0328044,9110,8805,0.99999425,9201,8806,100178.1808,9001,8807,-6500614.7836,9001,,,,,,
-3153,"NAD83(CSRS) / BC Albers",9001,4617,19984,9822,1,0,4400,8821,45,9102,8822,-126,9102,8823,50,9110,8824,58.3,9110,8826,1000000,9001,8827,0,9001,,,
-3154,"NAD83(CSRS) / UTM zone 7N",9001,4617,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3155,"NAD83(CSRS) / UTM zone 8N",9001,4617,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3156,"NAD83(CSRS) / UTM zone 9N",9001,4617,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3157,"NAD83(CSRS) / UTM zone 10N",9001,4617,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3158,"NAD83(CSRS) / UTM zone 14N",9001,4617,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3159,"NAD83(CSRS) / UTM zone 15N",9001,4617,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3160,"NAD83(CSRS) / UTM zone 16N",9001,4617,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3161,"NAD83 / Ontario MNR Lambert",9001,4269,19875,9802,1,0,4400,8821,0,9102,8822,-85,9102,8823,44.5,9102,8824,53.5,9102,8826,930000,9001,8827,6430000,9001,,,
-3162,"NAD83(CSRS) / Ontario MNR Lambert",9001,4617,19875,9802,1,0,4400,8821,0,9102,8822,-85,9102,8823,44.5,9102,8824,53.5,9102,8826,930000,9001,8827,6430000,9001,,,
-3163,"RGNC91-93 / Lambert New Caledonia",9001,4749,19981,9802,1,0,4499,8821,-21.3,9110,8822,166,9110,8823,-20.4,9110,8824,-22.2,9110,8826,400000,9001,8827,300000,9001,,,
-3164,"ST87 Ouvea / UTM zone 58S",9001,4750,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3165,"NEA74 Noumea / Noumea Lambert",9001,4644,19873,9802,1,0,4499,8821,-22.16108903,9110,8822,166.26327327,9110,8823,-22.14408903,9110,8824,-22.17408903,9110,8826,0.66,9001,8827,1.02,9001,,,
-3166,"NEA74 Noumea / Noumea Lambert 2",9001,4644,19874,9802,1,0,4499,8821,-22.1611,9110,8822,166.2633,9110,8823,-22.1441,9110,8824,-22.1741,9110,8826,8.313,9001,8827,-2.354,9001,,,
-3167,"Kertau (RSO) / RSO Malaya (ch)",9301,4751,19871,9812,1,0,4410,8806,40000,9301,8807,0,9301,8811,4,9110,8812,102.15,9110,8813,323.01328458,9110,8814,323.07483685,9110,8815,0.99984,9201
-3168,"Kertau (RSO) / RSO Malaya (m)",9001,4751,19872,9812,1,0,4400,8806,804670.24,9001,8807,0,9001,8811,4,9110,8812,102.15,9110,8813,323.01328458,9110,8814,323.07483685,9110,8815,0.99984,9201
-3169,"RGNC91-93 / UTM zone 57S",9001,4749,16157,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3170,"RGNC91-93 / UTM zone 58S",9001,4749,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3171,"RGNC91-93 / UTM zone 59S",9001,4749,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3172,"IGN53 Mare / UTM zone 59S",9001,4641,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3173,"fk89 / Faroe Lambert FK89",9001,4753,19877,9826,1,0,1031,8801,62,9102,8802,-9,9102,8805,1,9201,8806,700000,9001,8807,700000,9001,,,,,,
-3174,"NAD83 / Great Lakes Albers",9001,4269,15397,9822,1,0,4499,8821,45.568977,9102,8822,-84.455955,9102,8823,42.122774,9102,8824,49.01518,9102,8826,1000000,9001,8827,1000000,9001,,,
-3175,"NAD83 / Great Lakes and St Lawrence Albers",9001,4269,15398,9822,1,0,4499,8821,45.568977,9102,8822,-83.248627,9102,8823,42.122774,9102,8824,49.01518,9102,8826,1000000,9001,8827,1000000,9001,,,
-3176,"Indian 1960 / TM 106 NE",9001,4131,16506,9807,1,0,4400,8801,0,9102,8802,106,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3177,"LGD2006 / Libya TM",9001,4754,18319,9807,1,0,4499,8801,0,9102,8802,17,9102,8805,0.9965,9201,8806,1000000,9001,8807,0,9001,,,,,,
-3178,"GR96 / UTM zone 18N",9001,4747,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3179,"GR96 / UTM zone 19N",9001,4747,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3180,"GR96 / UTM zone 20N",9001,4747,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3181,"GR96 / UTM zone 21N",9001,4747,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3182,"GR96 / UTM zone 22N",9001,4747,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3183,"GR96 / UTM zone 23N",9001,4747,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3184,"GR96 / UTM zone 24N",9001,4747,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3185,"GR96 / UTM zone 25N",9001,4747,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3186,"GR96 / UTM zone 26N",9001,4747,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3187,"GR96 / UTM zone 27N",9001,4747,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3188,"GR96 / UTM zone 28N",9001,4747,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3189,"GR96 / UTM zone 29N",9001,4747,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3190,"LGD2006 / Libya TM zone 5",9001,4754,18310,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3191,"LGD2006 / Libya TM zone 6",9001,4754,18311,9807,1,0,4499,8801,0,9102,8802,11,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3192,"LGD2006 / Libya TM zone 7",9001,4754,18312,9807,1,0,4499,8801,0,9102,8802,13,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3193,"LGD2006 / Libya TM zone 8",9001,4754,18313,9807,1,0,4499,8801,0,9102,8802,15,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3194,"LGD2006 / Libya TM zone 9",9001,4754,18314,9807,1,0,4499,8801,0,9102,8802,17,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3195,"LGD2006 / Libya TM zone 10",9001,4754,18315,9807,1,0,4499,8801,0,9102,8802,19,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3196,"LGD2006 / Libya TM zone 11",9001,4754,18316,9807,1,0,4499,8801,0,9102,8802,21,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3197,"LGD2006 / Libya TM zone 12",9001,4754,18317,9807,1,0,4499,8801,0,9102,8802,23,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3198,"LGD2006 / Libya TM zone 13",9001,4754,18318,9807,1,0,4499,8801,0,9102,8802,25,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3199,"LGD2006 / UTM zone 32N",9001,4754,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3200,"FD58 / Iraq zone",9001,4132,19906,9801,1,0,4400,8801,32.3,9110,8802,45,9110,8805,0.9987864078,9201,8806,1500000,9001,8807,1166200,9001,,,,,,
-3201,"LGD2006 / UTM zone 33N",9001,4754,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3202,"LGD2006 / UTM zone 34N",9001,4754,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3203,"LGD2006 / UTM zone 35N",9001,4754,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3204,"WGS 84 / SCAR IMW SP19-20",9001,4326,17204,9802,1,0,4400,8821,-90,9102,8822,-66,9102,8823,-60.4,9110,8824,-63.2,9110,8826,0,9001,8827,0,9001,,,
-3205,"WGS 84 / SCAR IMW SP21-22",9001,4326,17205,9802,1,0,4400,8821,-90,9102,8822,-54,9102,8823,-60.4,9110,8824,-63.2,9110,8826,0,9001,8827,0,9001,,,
-3206,"WGS 84 / SCAR IMW SP23-24",9001,4326,17206,9802,1,0,4400,8821,-90,9102,8822,-42,9102,8823,-60.4,9110,8824,-63.2,9110,8826,0,9001,8827,0,9001,,,
-3207,"WGS 84 / SCAR IMW SQ01-02",9001,4326,17207,9802,1,0,4400,8821,-90,9102,8822,-174,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3208,"WGS 84 / SCAR IMW SQ19-20",9001,4326,17208,9802,1,0,4400,8821,-90,9102,8822,-66,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3209,"WGS 84 / SCAR IMW SQ21-22",9001,4326,17209,9802,1,0,4400,8821,-90,9102,8822,-54,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3210,"WGS 84 / SCAR IMW SQ37-38",9001,4326,17210,9802,1,0,4400,8821,-90,9102,8822,42,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3211,"WGS 84 / SCAR IMW SQ39-40",9001,4326,17211,9802,1,0,4400,8821,-90,9102,8822,54,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3212,"WGS 84 / SCAR IMW SQ41-42",9001,4326,17212,9802,1,0,4400,8821,-90,9102,8822,66,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3213,"WGS 84 / SCAR IMW SQ43-44",9001,4326,17213,9802,1,0,4400,8821,-90,9102,8822,78,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3214,"WGS 84 / SCAR IMW SQ45-46",9001,4326,17214,9802,1,0,4400,8821,-90,9102,8822,90,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3215,"WGS 84 / SCAR IMW SQ47-48",9001,4326,17215,9802,1,0,4400,8821,-90,9102,8822,102,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3216,"WGS 84 / SCAR IMW SQ49-50",9001,4326,17216,9802,1,0,4400,8821,-90,9102,8822,114,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3217,"WGS 84 / SCAR IMW SQ51-52",9001,4326,17217,9802,1,0,4400,8821,-90,9102,8822,126,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3218,"WGS 84 / SCAR IMW SQ53-54",9001,4326,17218,9802,1,0,4400,8821,-90,9102,8822,138,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3219,"WGS 84 / SCAR IMW SQ55-56",9001,4326,17219,9802,1,0,4400,8821,-90,9102,8822,150,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3220,"WGS 84 / SCAR IMW SQ57-58",9001,4326,17220,9802,1,0,4400,8821,-90,9102,8822,162,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,
-3221,"WGS 84 / SCAR IMW SR13-14",9001,4326,17221,9802,1,0,4400,8821,-90,9102,8822,-102,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3222,"WGS 84 / SCAR IMW SR15-16",9001,4326,17222,9802,1,0,4400,8821,-90,9102,8822,-90,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3223,"WGS 84 / SCAR IMW SR17-18",9001,4326,17223,9802,1,0,4400,8821,-90,9102,8822,-78,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3224,"WGS 84 / SCAR IMW SR19-20",9001,4326,17224,9802,1,0,4400,8821,-90,9102,8822,-66,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3225,"WGS 84 / SCAR IMW SR27-28",9001,4326,17225,9802,1,0,4400,8821,-90,9102,8822,-18,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3226,"WGS 84 / SCAR IMW SR29-30",9001,4326,17226,9802,1,0,4400,8821,-90,9102,8822,-6,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3227,"WGS 84 / SCAR IMW SR31-32",9001,4326,17227,9802,1,0,4400,8821,-90,9102,8822,6,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3228,"WGS 84 / SCAR IMW SR33-34",9001,4326,17228,9802,1,0,4400,8821,-90,9102,8822,18,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3229,"WGS 84 / SCAR IMW SR35-36",9001,4326,17229,9802,1,0,4400,8821,-90,9102,8822,30,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3230,"WGS 84 / SCAR IMW SR37-38",9001,4326,17230,9802,1,0,4400,8821,-90,9102,8822,42,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3231,"WGS 84 / SCAR IMW SR39-40",9001,4326,17231,9802,1,0,4400,8821,-90,9102,8822,54,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3232,"WGS 84 / SCAR IMW SR41-42",9001,4326,17232,9802,1,0,4400,8821,-90,9102,8822,66,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3233,"WGS 84 / SCAR IMW SR43-44",9001,4326,17233,9802,1,0,4400,8821,-90,9102,8822,78,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3234,"WGS 84 / SCAR IMW SR45-46",9001,4326,17234,9802,1,0,4400,8821,-90,9102,8822,90,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3235,"WGS 84 / SCAR IMW SR47-48",9001,4326,17235,9802,1,0,4400,8821,-90,9102,8822,102,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3236,"WGS 84 / SCAR IMW SR49-50",9001,4326,17236,9802,1,0,4400,8821,-90,9102,8822,114,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3237,"WGS 84 / SCAR IMW SR51-52",9001,4326,17237,9802,1,0,4400,8821,-90,9102,8822,126,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3238,"WGS 84 / SCAR IMW SR53-54",9001,4326,17238,9802,1,0,4400,8821,-90,9102,8822,138,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3239,"WGS 84 / SCAR IMW SR55-56",9001,4326,17239,9802,1,0,4400,8821,-90,9102,8822,150,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3240,"WGS 84 / SCAR IMW SR57-58",9001,4326,17240,9802,1,0,4400,8821,-90,9102,8822,162,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3241,"WGS 84 / SCAR IMW SR59-60",9001,4326,17241,9802,1,0,4400,8821,-90,9102,8822,174,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,
-3242,"WGS 84 / SCAR IMW SS04-06",9001,4326,17242,9802,1,0,4400,8821,-90,9102,8822,-153,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3243,"WGS 84 / SCAR IMW SS07-09",9001,4326,17243,9802,1,0,4400,8821,-90,9102,8822,-135,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3244,"WGS 84 / SCAR IMW SS10-12",9001,4326,17244,9802,1,0,4400,8821,-90,9102,8822,-117,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3245,"WGS 84 / SCAR IMW SS13-15",9001,4326,17245,9802,1,0,4400,8821,-90,9102,8822,-99,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3246,"WGS 84 / SCAR IMW SS16-18",9001,4326,17246,9802,1,0,4400,8821,-90,9102,8822,-81,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3247,"WGS 84 / SCAR IMW SS19-21",9001,4326,17247,9802,1,0,4400,8821,-90,9102,8822,-63,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3248,"WGS 84 / SCAR IMW SS25-27",9001,4326,17248,9802,1,0,4400,8821,-90,9102,8822,-27,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3249,"WGS 84 / SCAR IMW SS28-30",9001,4326,17249,9802,1,0,4400,8821,-90,9102,8822,-9,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3250,"WGS 84 / SCAR IMW SS31-33",9001,4326,17250,9802,1,0,4400,8821,-90,9102,8822,9,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3251,"WGS 84 / SCAR IMW SS34-36",9001,4326,17251,9802,1,0,4400,8821,-90,9102,8822,27,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3252,"WGS 84 / SCAR IMW SS37-39",9001,4326,17252,9802,1,0,4400,8821,-90,9102,8822,45,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3253,"WGS 84 / SCAR IMW SS40-42",9001,4326,17253,9802,1,0,4400,8821,-90,9102,8822,63,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3254,"WGS 84 / SCAR IMW SS43-45",9001,4326,17254,9802,1,0,4400,8821,-90,9102,8822,81,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3255,"WGS 84 / SCAR IMW SS46-48",9001,4326,17255,9802,1,0,4400,8821,-90,9102,8822,99,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3256,"WGS 84 / SCAR IMW SS49-51",9001,4326,17256,9802,1,0,4400,8821,-90,9102,8822,117,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3257,"WGS 84 / SCAR IMW SS52-54",9001,4326,17257,9802,1,0,4400,8821,-90,9102,8822,135,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3258,"WGS 84 / SCAR IMW SS55-57",9001,4326,17258,9802,1,0,4400,8821,-90,9102,8822,153,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3259,"WGS 84 / SCAR IMW SS58-60",9001,4326,17259,9802,1,0,4400,8821,-90,9102,8822,171,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,
-3260,"WGS 84 / SCAR IMW ST01-04",9001,4326,17260,9802,1,0,4400,8821,-90,9102,8822,-168,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3261,"WGS 84 / SCAR IMW ST05-08",9001,4326,17261,9802,1,0,4400,8821,-90,9102,8822,-144,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3262,"WGS 84 / SCAR IMW ST09-12",9001,4326,17262,9802,1,0,4400,8821,-90,9102,8822,-120,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3263,"WGS 84 / SCAR IMW ST13-16",9001,4326,17263,9802,1,0,4400,8821,-90,9102,8822,-96,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3264,"WGS 84 / SCAR IMW ST17-20",9001,4326,17264,9802,1,0,4400,8821,-90,9102,8822,-72,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3265,"WGS 84 / SCAR IMW ST21-24",9001,4326,17265,9802,1,0,4400,8821,-90,9102,8822,-48,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3266,"WGS 84 / SCAR IMW ST25-28",9001,4326,17266,9802,1,0,4400,8821,-90,9102,8822,-24,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3267,"WGS 84 / SCAR IMW ST29-32",9001,4326,17267,9802,1,0,4400,8821,-90,9102,8822,0,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3268,"WGS 84 / SCAR IMW ST33-36",9001,4326,17268,9802,1,0,4400,8821,-90,9102,8822,24,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3269,"WGS 84 / SCAR IMW ST37-40",9001,4326,17269,9802,1,0,4400,8821,-90,9102,8822,48,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3270,"WGS 84 / SCAR IMW ST41-44",9001,4326,17270,9802,1,0,4400,8821,-90,9102,8822,72,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3271,"WGS 84 / SCAR IMW ST45-48",9001,4326,17271,9802,1,0,4400,8821,-90,9102,8822,96,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3272,"WGS 84 / SCAR IMW ST49-52",9001,4326,17272,9802,1,0,4400,8821,-90,9102,8822,120,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3273,"WGS 84 / SCAR IMW ST53-56",9001,4326,17273,9802,1,0,4400,8821,-90,9102,8822,144,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3274,"WGS 84 / SCAR IMW ST57-60",9001,4326,17274,9802,1,0,4400,8821,-90,9102,8822,168,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3275,"WGS 84 / SCAR IMW SU01-05",9001,4326,17275,9829,1,0,4471,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-165,9102,,,,,,,,,
-3276,"WGS 84 / SCAR IMW SU06-10",9001,4326,17276,9829,1,0,4473,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-135,9102,,,,,,,,,
-3277,"WGS 84 / SCAR IMW SU11-15",9001,4326,17277,9829,1,0,4474,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-105,9102,,,,,,,,,
-3278,"WGS 84 / SCAR IMW SU16-20",9001,4326,17278,9829,1,0,4476,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-75,9102,,,,,,,,,
-3279,"WGS 84 / SCAR IMW SU21-25",9001,4326,17279,9829,1,0,4477,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-45,9102,,,,,,,,,
-3280,"WGS 84 / SCAR IMW SU26-30",9001,4326,17280,9829,1,0,4479,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-15,9102,,,,,,,,,
-3281,"WGS 84 / SCAR IMW SU31-35",9001,4326,17281,9829,1,0,4480,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,15,9102,,,,,,,,,
-3282,"WGS 84 / SCAR IMW SU36-40",9001,4326,17282,9829,1,0,4482,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,45,9102,,,,,,,,,
-3283,"WGS 84 / SCAR IMW SU41-45",9001,4326,17283,9829,1,0,4483,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,75,9102,,,,,,,,,
-3284,"WGS 84 / SCAR IMW SU46-50",9001,4326,17284,9829,1,0,4485,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,105,9102,,,,,,,,,
-3285,"WGS 84 / SCAR IMW SU51-55",9001,4326,17285,9829,1,0,4486,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,135,9102,,,,,,,,,
-3286,"WGS 84 / SCAR IMW SU56-60",9001,4326,17286,9829,1,0,4488,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,165,9102,,,,,,,,,
-3287,"WGS 84 / SCAR IMW SV01-10",9001,4326,17287,9829,1,0,4472,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-150,9102,,,,,,,,,
-3288,"WGS 84 / SCAR IMW SV11-20",9001,4326,17288,9829,1,0,4475,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-90,9102,,,,,,,,,
-3289,"WGS 84 / SCAR IMW SV21-30",9001,4326,17289,9829,1,0,4478,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-30,9102,,,,,,,,,
-3290,"WGS 84 / SCAR IMW SV31-40",9001,4326,17290,9829,1,0,4481,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,30,9102,,,,,,,,,
-3291,"WGS 84 / SCAR IMW SV41-50",9001,4326,17291,9829,1,0,4484,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,90,9102,,,,,,,,,
-3292,"WGS 84 / SCAR IMW SV51-60",9001,4326,17292,9829,1,0,4487,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,150,9102,,,,,,,,,
-3293,"WGS 84 / SCAR IMW SW01-60",9001,4326,17293,9829,1,0,4490,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,0,9102,,,,,,,,,
-3294,"WGS 84 / USGS Transantarctic Mountains",9001,4326,17294,9802,1,0,4400,8821,-78,9102,8822,162,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,
-3295,"Guam 1963 / Yap Islands",9001,4675,15399,9832,1,0,4499,8801,9.324815,9110,8802,138.100748,9110,8806,40000,9001,8807,60000,9001,,,,,,,,,
-3296,"RGPF / UTM zone 5S",9001,4687,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3297,"RGPF / UTM zone 6S",9001,4687,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3298,"RGPF / UTM zone 7S",9001,4687,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3299,"RGPF / UTM zone 8S",9001,4687,16108,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3300,Estonian Coordinate System of 1992,9001,4133,19938,9802,1,0,4530,8821,57.310319415,9110,8822,24,9110,8823,59.2,9110,8824,58,9110,8826,500000,9001,8827,6375000,9001,,,
-3301,Estonian Coordinate System of 1997,9001,4180,19938,9802,1,0,4530,8821,57.310319415,9110,8822,24,9110,8823,59.2,9110,8824,58,9110,8826,500000,9001,8827,6375000,9001,,,
-3302,"IGN63 Hiva Oa / UTM zone 7S",9001,4689,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3303,"Fatu Iva 72 / UTM zone 7S",9001,4688,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3304,"Tahiti 79 / UTM zone 6S",9001,4690,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3305,"Moorea 87 / UTM zone 6S",9001,4691,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3306,"Maupiti 83 / UTM zone 5S",9001,4692,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3307,"Nakhl-e Ghanem / UTM zone 39N",9001,4693,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3308,"GDA94 / NSW Lambert",9001,4283,17364,9802,1,0,4400,8821,-33.25,9102,8822,147,9102,8823,-30.75,9102,8824,-35.75,9102,8826,9300000,9001,8827,4500000,9001,,,
-3309,"NAD27 / California Albers",9001,4267,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,
-3310,"NAD83 / California Albers",9001,4269,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,
-3311,"NAD83(HARN) / California Albers",9001,4152,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,
-3312,"CSG67 / UTM zone 21N",9001,4623,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3313,"RGFG95 / UTM zone 21N",9001,4624,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3314,"Katanga 1955 / Katanga Lambert",9001,4695,17401,9802,1,1,4400,8821,0,9102,8822,26,9102,8823,-6.5,9102,8824,-11.5,9102,8826,0,9001,8827,0,9001,,,
-3315,"Katanga 1955 / Katanga TM",9001,4695,17402,9807,1,1,4400,8801,-9,9102,8802,26,9102,8805,0.9998,9201,8806,0,9001,8807,0,9001,,,,,,
-3316,"Kasai 1953 / Congo TM zone 22",9001,4696,17422,9807,1,0,4400,8801,0,9102,8802,22,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3317,"Kasai 1953 / Congo TM zone 24",9001,4696,17424,9807,1,0,4400,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3318,"IGC 1962 / Congo TM zone 12",9001,4697,17412,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3319,"IGC 1962 / Congo TM zone 14",9001,4697,17414,9807,1,0,4400,8801,0,9102,8802,14,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3320,"IGC 1962 / Congo TM zone 16",9001,4697,17416,9807,1,0,4400,8801,0,9102,8802,16,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3321,"IGC 1962 / Congo TM zone 18",9001,4697,17418,9807,1,0,4400,8801,0,9102,8802,18,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3322,"IGC 1962 / Congo TM zone 20",9001,4697,17420,9807,1,0,4400,8801,0,9102,8802,20,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3323,"IGC 1962 / Congo TM zone 22",9001,4697,17422,9807,1,0,4400,8801,0,9102,8802,22,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3324,"IGC 1962 / Congo TM zone 24",9001,4697,17424,9807,1,0,4400,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3325,"IGC 1962 / Congo TM zone 26",9001,4697,17426,9807,1,0,4400,8801,0,9102,8802,26,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3326,"IGC 1962 / Congo TM zone 28",9001,4697,17428,9807,1,0,4400,8801,0,9102,8802,28,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3327,"IGC 1962 / Congo TM zone 30",9001,4697,17430,9807,1,0,4400,8801,0,9102,8802,30,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3328,"Pulkovo 1942(58) / GUGiK-80",9001,4179,18286,9809,1,0,4530,8801,52.1,9110,8802,19.1,9110,8805,0.999714,9201,8806,500000,9001,8807,500000,9001,,,,,,
-3329,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 5",9001,4179,16265,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-3330,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 6",9001,4179,16266,9807,1,0,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-3331,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 7",9001,4179,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-3332,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 8",9001,4179,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-3333,"Pulkovo 1942(58) / Gauss-Kruger zone 3",9001,4179,16203,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-3334,"Pulkovo 1942(58) / Gauss-Kruger zone 4",9001,4179,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-3335,"Pulkovo 1942(58) / Gauss-Kruger zone 5",9001,4179,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-3336,"IGN 1962 Kerguelen / UTM zone 42S",9001,4698,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3337,"Le Pouce 1934 / Mauritius Grid",9001,4699,19899,9801,1,0,4400,8801,-20.114225,9110,8802,57.311858,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-3338,"NAD83 / Alaska Albers",9001,4269,15021,9822,1,0,4499,8821,50,9102,8822,-154,9102,8823,55,9102,8824,65,9102,8826,0,9001,8827,0,9001,,,
-3339,"IGCB 1955 / Congo TM zone 12",9001,4701,17412,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3340,"IGCB 1955 / Congo TM zone 14",9001,4701,17414,9807,1,0,4400,8801,0,9102,8802,14,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3341,"IGCB 1955 / Congo TM zone 16",9001,4701,17416,9807,1,0,4400,8801,0,9102,8802,16,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3342,"IGCB 1955 / UTM zone 33S",9001,4701,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3343,"Mauritania 1999 / UTM zone 28N",9001,4702,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3344,"Mauritania 1999 / UTM zone 29N",9001,4702,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3345,"Mauritania 1999 / UTM zone 30N",9001,4702,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3346,"LKS94 / Lithuania TM",9001,4669,19934,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,0.9998,9201,8806,500000,9001,8807,0,9001,,,,,,
-3347,"NAD83 / Statistics Canada Lambert",9001,4269,19897,9802,1,0,4400,8821,63.390675,9102,8822,-91.52,9110,8823,49,9102,8824,77,9102,8826,6200000,9001,8827,3000000,9001,,,
-3348,"NAD83(CSRS) / Statistics Canada Lambert",9001,4617,19897,9802,1,0,4400,8821,63.390675,9102,8822,-91.52,9110,8823,49,9102,8824,77,9102,8826,6200000,9001,8827,3000000,9001,,,
-3349,"WGS 84 / PDC Mercator",9001,4326,19898,9804,1,1,4400,8801,0,9102,8802,-150,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-3350,"Pulkovo 1942 / CS63 zone C0",9001,4284,18450,9807,1,0,4530,8801,0.06,9110,8802,21.57,9110,8805,1,9201,8806,250000,9001,8807,0,9001,,,,,,
-3351,"Pulkovo 1942 / CS63 zone C1",9001,4284,18451,9807,1,0,4530,8801,0.06,9110,8802,24.57,9110,8805,1,9201,8806,1250000,9001,8807,0,9001,,,,,,
-3352,"Pulkovo 1942 / CS63 zone C2",9001,4284,18452,9807,1,0,4530,8801,0.06,9110,8802,27.57,9110,8805,1,9201,8806,2250000,9001,8807,0,9001,,,,,,
-3353,"Mhast (onshore) / UTM zone 32S",9001,4704,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3354,"Mhast (offshore) / UTM zone 32S",9001,4705,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3355,"Egypt Gulf of Suez S-650 TL / Red Belt",9001,4706,18072,9807,1,0,4400,8801,30,9102,8802,31,9102,8805,1,9201,8806,615000,9001,8807,810000,9001,,,,,,
-3356,"Grand Cayman 1959 / UTM zone 17N",9001,4723,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3357,"Little Cayman 1961 / UTM zone 17N",9001,4726,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3358,"NAD83(HARN) / North Carolina",9001,4152,13230,9802,1,0,4499,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,609601.22,9001,8827,0,9001,,,
-3359,"NAD83(HARN) / North Carolina (ftUS)",9002,4152,15346,9802,1,1,4495,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,
-3360,"NAD83(HARN) / South Carolina",9001,4152,13930,9802,1,0,4499,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,609600,9001,8827,0,9001,,,
-3361,"NAD83(HARN) / South Carolina (ft)",9002,4152,15355,9802,1,0,4495,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,2000000,9002,8827,0,9002,,,
-3362,"NAD83(HARN) / Pennsylvania North",9001,4152,13731,9802,1,0,4499,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,600000,9001,8827,0,9001,,,
-3363,"NAD83(HARN) / Pennsylvania North (ftUS)",9003,4152,15353,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,1968500,9003,8827,0,9003,,,
-3364,"NAD83(HARN) / Pennsylvania South",9001,4152,13732,9802,1,0,4499,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,600000,9001,8827,0,9001,,,
-3365,"NAD83(HARN) / Pennsylvania South (ftUS)",9003,4152,15354,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,1968500,9003,8827,0,9003,,,
-3366,Hong Kong 1963 Grid System,9001,4738,19896,9806,1,1,4500,8801,22.184368,9110,8802,114.10428,9110,8806,132033.92,9005,8807,62565.96,9005,,,,,,,,,
-3367,"IGN Astro 1960 / UTM zone 28N",9001,4700,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3368,"IGN Astro 1960 / UTM zone 29N",9001,4700,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3369,"IGN Astro 1960 / UTM zone 30N",9001,4700,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3370,"NAD27 / UTM zone 59N",9001,4267,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3371,"NAD27 / UTM zone 60N",9001,4267,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3372,"NAD83 / UTM zone 59N",9001,4269,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3373,"NAD83 / UTM zone 60N",9001,4269,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3374,"FD54 / UTM zone 29N",9001,4741,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3375,"GDM2000 / Peninsula RSO",9001,4742,19895,9812,1,0,4400,8806,804671,9001,8807,0,9001,8811,4,9110,8812,102.15,9110,8813,323.013286728,9110,8814,323.07483685,9110,8815,0.99984,9201
-3376,"GDM2000 / East Malaysia BRSO",9001,4742,19894,9812,1,0,4400,8806,0,9001,8807,0,9001,8811,4,9110,8812,115,9110,8813,53.185691582,9110,8814,53.07483685,9110,8815,0.99984,9201
-3377,"GDM2000 / Johor Grid",9001,4742,19893,9806,1,0,4400,8801,2.071804708,9110,8802,103.254057045,9110,8806,-14810.562,9001,8807,8758.32,9001,,,,,,,,,
-3378,"GDM2000 / Sembilan and Melaka Grid",9001,4742,19892,9806,1,0,4400,8801,2.405645149,9110,8802,101.582965815,9110,8806,3673.785,9001,8807,-4240.573,9001,,,,,,,,,
-3379,"GDM2000 / Pahang Grid",9001,4742,19891,9806,1,0,4400,8801,3.460979712,9110,8802,102.220587634,9110,8806,-7368.228,9001,8807,6485.858,9001,,,,,,,,,
-3380,"GDM2000 / Selangor Grid",9001,4742,19890,9806,1,0,4400,8801,3.410473658,9110,8802,101.232078849,9110,8806,-34836.161,9001,8807,56464.049,9001,,,,,,,,,
-3381,"GDM2000 / Terengganu Grid",9001,4742,19889,9806,1,0,4400,8801,4.583462672,9110,8802,103.041299225,9110,8806,19594.245,9001,8807,3371.895,9001,,,,,,,,,
-3382,"GDM2000 / Pinang Grid",9001,4742,19888,9806,1,0,4400,8801,5.251746315,9110,8802,100.203975707,9110,8806,-23.414,9001,8807,62.283,9001,,,,,,,,,
-3383,"GDM2000 / Kedah and Perlis Grid",9001,4742,19887,9806,1,0,4400,8801,5.575282177,9110,8802,100.3810936,9110,8806,0,9001,8807,0,9001,,,,,,,,,
-3384,"GDM2000 / Perak Grid",9001,4742,19886,9806,1,0,4400,8801,4.513262688,9110,8802,100.485547811,9110,8806,-1.769,9001,8807,133454.779,9001,,,,,,,,,
-3385,"GDM2000 / Kelantan Grid",9001,4742,19885,9806,1,0,4400,8801,5.582115717,9110,8802,102.174287001,9110,8806,13227.851,9001,8807,8739.894,9001,,,,,,,,,
-3386,"KKJ / Finland zone 0",9001,4123,18180,9807,1,0,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-3387,"KKJ / Finland zone 5",9001,4123,18205,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-3388,"Pulkovo 1942 / Caspian Sea Mercator",9001,4284,19884,9805,1,0,4534,8802,51,9102,8806,0,9001,8807,0,9001,8823,42,9102,,,,,,,,,
-3389,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 60",9001,4284,16099,9807,1,0,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,60500000,9001,8807,0,9001,,,,,,
-3390,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 60",9001,4200,16099,9807,1,0,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,60500000,9001,8807,0,9001,,,,,,
-3391,"Karbala 1979 / UTM zone 37N",9001,4743,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3392,"Karbala 1979 / UTM zone 38N",9001,4743,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3393,"Karbala 1979 / UTM zone 39N",9001,4743,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3394,"Nahrwan 1934 / Iraq zone",9001,4744,19906,9801,1,0,4400,8801,32.3,9110,8802,45,9110,8805,0.9987864078,9201,8806,1500000,9001,8807,1166200,9001,,,,,,
-3395,"WGS 84 / World Mercator",9001,4326,19883,9804,1,0,4400,8801,0,9102,8802,0,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-3396,"PD/83 / 3-degree Gauss-Kruger zone 3",9001,4746,16263,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-3397,"PD/83 / 3-degree Gauss-Kruger zone 4",9001,4746,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-3398,"RD/83 / 3-degree Gauss-Kruger zone 4",9001,4745,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-3399,"RD/83 / 3-degree Gauss-Kruger zone 5",9001,4745,16265,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-3400,"NAD83 / Alberta 10-TM (Forest)",9001,4269,19881,9807,1,0,4400,8801,0,9102,8802,-115,9102,8805,0.9992,9201,8806,500000,9001,8807,0,9001,,,,,,
-3401,"NAD83 / Alberta 10-TM (Resource)",9001,4269,19882,9807,1,0,4400,8801,0,9102,8802,-115,9102,8805,0.9992,9201,8806,0,9001,8807,0,9001,,,,,,
-3402,"NAD83(CSRS) / Alberta 10-TM (Forest)",9001,4617,19881,9807,1,0,4400,8801,0,9102,8802,-115,9102,8805,0.9992,9201,8806,500000,9001,8807,0,9001,,,,,,
-3403,"NAD83(CSRS) / Alberta 10-TM (Resource)",9001,4617,19882,9807,1,0,4400,8801,0,9102,8802,-115,9102,8805,0.9992,9201,8806,0,9001,8807,0,9001,,,,,,
-3404,"NAD83(HARN) / North Carolina (ftUS)",9003,4152,15346,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,
-3405,"VN-2000 / UTM zone 48N",9001,4756,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3406,"VN-2000 / UTM zone 49N",9001,4756,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3407,Hong Kong 1963 Grid System,9005,4738,19896,9806,1,0,4502,8801,22.184368,9110,8802,114.10428,9110,8806,132033.92,9005,8807,62565.96,9005,,,,,,,,,
-3408,NSIDC EASE-Grid North,9001,4053,3897,1027,1,0,4469,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3409,NSIDC EASE-Grid South,9001,4053,3898,1027,1,0,4470,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3410,NSIDC EASE-Grid Global,9001,4053,19869,9834,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,
-3411,NSIDC Sea Ice Polar Stereographic North,9001,4054,19865,9829,1,0,4468,8806,0,9001,8807,0,9001,8832,70,9102,8833,-45,9102,,,,,,,,,
-3412,NSIDC Sea Ice Polar Stereographic South,9001,4054,19866,9829,1,0,4470,8806,0,9001,8807,0,9001,8832,-70,9102,8833,0,9102,,,,,,,,,
-3413,"WGS 84 / NSIDC Sea Ice Polar Stereographic North",9001,4326,19865,9829,1,0,4468,8806,0,9001,8807,0,9001,8832,70,9102,8833,-45,9102,,,,,,,,,
-3414,"SVY21 / Singapore TM",9001,4757,19864,9807,1,0,4500,8801,1.22,9110,8802,103.5,9110,8805,1,9201,8806,28001.642,9001,8807,38744.572,9001,,,,,,
-3415,"WGS 72BE / South China Sea Lambert",9001,4324,19863,9802,1,0,4400,8821,21,9102,8822,114,9102,8823,18,9102,8824,24,9102,8826,500000,9001,8827,500000,9001,,,
-3416,"ETRS89 / Austria Lambert",9001,4258,19947,9802,1,0,4530,8821,47.3,9110,8822,13.2,9110,8823,49,9110,8824,46,9110,8826,400000,9001,8827,400000,9001,,,
-3417,"NAD83 / Iowa North (ftUS)",9003,4269,15377,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,4921250,9003,8827,3280833.3333,9003,,,
-3418,"NAD83 / Iowa South (ftUS)",9003,4269,15378,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,1640416.6667,9003,8827,0,9003,,,
-3419,"NAD83 / Kansas North (ftUS)",9003,4269,15379,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,1312333.3333,9003,8827,0,9003,,,
-3420,"NAD83 / Kansas South (ftUS)",9003,4269,15380,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,
-3421,"NAD83 / Nevada East (ftUS)",9003,4269,15381,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,656166.6667,9003,8807,26246666.6667,9003,,,,,,
-3422,"NAD83 / Nevada Central (ftUS)",9003,4269,15382,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,1640416.6667,9003,8807,19685000,9003,,,,,,
-3423,"NAD83 / Nevada West (ftUS)",9003,4269,15383,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,2624666.6667,9003,8807,13123333.3333,9003,,,,,,
-3424,"NAD83 / New Jersey (ftUS)",9003,4269,15384,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,
-3425,"NAD83(HARN) / Iowa North (ftUS)",9003,4152,15377,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,4921250,9003,8827,3280833.3333,9003,,,
-3426,"NAD83(HARN) / Iowa South (ftUS)",9003,4152,15378,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,1640416.6667,9003,8827,0,9003,,,
-3427,"NAD83(HARN) / Kansas North (ftUS)",9003,4152,15379,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,1312333.3333,9003,8827,0,9003,,,
-3428,"NAD83(HARN) / Kansas South (ftUS)",9003,4152,15380,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,
-3429,"NAD83(HARN) / Nevada East (ftUS)",9003,4152,15381,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,656166.6667,9003,8807,26246666.6667,9003,,,,,,
-3430,"NAD83(HARN) / Nevada Central (ftUS)",9003,4152,15382,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,1640416.6667,9003,8807,19685000,9003,,,,,,
-3431,"NAD83(HARN) / Nevada West (ftUS)",9003,4152,15383,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,2624666.6667,9003,8807,13123333.3333,9003,,,,,,
-3432,"NAD83(HARN) / New Jersey (ftUS)",9003,4152,15384,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,
-3433,"NAD83 / Arkansas North (ftUS)",9003,4269,15385,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,1312333.3333,9003,8827,0,9003,,,
-3434,"NAD83 / Arkansas South (ftUS)",9003,4269,15386,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,
-3435,"NAD83 / Illinois East (ftUS)",9003,4269,15387,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,984250,9003,8807,0,9003,,,,,,
-3436,"NAD83 / Illinois West (ftUS)",9003,4269,15388,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,2296583.3333,9003,8807,0,9003,,,,,,
-3437,"NAD83 / New Hampshire (ftUS)",9003,4269,15389,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,984250,9003,8807,0,9003,,,,,,
-3438,"NAD83 / Rhode Island (ftUS)",9003,4269,15390,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,328083.3333,9003,8807,0,9003,,,,,,
-3439,"PSD93 / UTM zone 39N",9001,4134,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3440,"PSD93 / UTM zone 40N",9001,4134,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3441,"NAD83(HARN) / Arkansas North (ftUS)",9003,4152,15385,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,1312333.3333,9003,8827,0,9003,,,
-3442,"NAD83(HARN) / Arkansas South (ftUS)",9003,4152,15386,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,
-3443,"NAD83(HARN) / Illinois East (ftUS)",9003,4152,15387,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,984250,9003,8807,0,9003,,,,,,
-3444,"NAD83(HARN) / Illinois West (ftUS)",9003,4152,15388,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,2296583.3333,9003,8807,0,9003,,,,,,
-3445,"NAD83(HARN) / New Hampshire (ftUS)",9003,4152,15389,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,984250,9003,8807,0,9003,,,,,,
-3446,"NAD83(HARN) / Rhode Island (ftUS)",9003,4152,15390,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,328083.3333,9003,8807,0,9003,,,,,,
-3447,"ETRS89 / Belgian Lambert 2005",9001,4258,19862,9802,1,0,4499,8821,50.4752134,9110,8822,4.2133177,9110,8823,49.5,9110,8824,51.1,9110,8826,150328,9001,8827,166262,9001,,,
-3448,"JAD2001 / Jamaica Metric Grid",9001,4758,19860,9801,1,0,4400,8801,18,9102,8802,-77,9102,8805,1,9201,8806,750000,9001,8807,650000,9001,,,,,,
-3449,"JAD2001 / UTM zone 17N",9001,4758,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3450,"JAD2001 / UTM zone 18N",9001,4758,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3451,"NAD83 / Louisiana North (ftUS)",9003,4269,15391,9802,1,0,4497,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,3280833.3333,9003,8827,0,9003,,,
-3452,"NAD83 / Louisiana South (ftUS)",9003,4269,15392,9802,1,0,4497,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,3280833.3333,9003,8827,0,9003,,,
-3453,"NAD83 / Louisiana Offshore (ftUS)",9003,4269,15393,9802,1,0,4497,8821,25.3,9110,8822,-91.2,9110,8823,27.5,9110,8824,26.1,9110,8826,3280833.3333,9003,8827,0,9003,,,
-3454,"NAD83 / South Dakota North (ftUS)",9003,4269,15395,9802,1,1,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,
-3455,"NAD83 / South Dakota South (ftUS)",9003,4269,15395,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,
-3456,"NAD83(HARN) / Louisiana North (ftUS)",9003,4152,15391,9802,1,0,4497,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,3280833.3333,9003,8827,0,9003,,,
-3457,"NAD83(HARN) / Louisiana South (ftUS)",9003,4152,15392,9802,1,0,4497,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,3280833.3333,9003,8827,0,9003,,,
-3458,"NAD83(HARN) / South Dakota North (ftUS)",9003,4152,15394,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,1968500,9003,8827,0,9003,,,
-3459,"NAD83(HARN) / South Dakota South (ftUS)",9003,4152,15395,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,
-3460,"Fiji 1986 / Fiji Map Grid",9001,4720,19859,9807,1,0,4400,8801,-17,9110,8802,178.45,9110,8805,0.99985,9201,8806,2000000,9001,8807,4000000,9001,,,,,,
-3461,"Dabola 1981 / UTM zone 28N",9001,4155,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3462,"Dabola 1981 / UTM zone 29N",9001,4155,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3463,"NAD83 / Maine CS2000 Central",9001,4269,11854,9807,1,0,4499,8801,43.3,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,
-3464,"NAD83(HARN) / Maine CS2000 Central",9001,4152,11854,9807,1,0,4499,8801,43.3,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,
-3465,"NAD83(NSRS2007) / Alabama East",9001,4759,10131,9807,1,0,4499,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,
-3466,"NAD83(NSRS2007) / Alabama West",9001,4759,10132,9807,1,0,4499,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,600000,9001,8807,0,9001,,,,,,
-3467,"NAD83(NSRS2007) / Alaska Albers",9001,4759,15021,9822,1,0,4499,8821,50,9102,8822,-154,9102,8823,55,9102,8824,65,9102,8826,0,9001,8827,0,9001,,,
-3468,"NAD83(NSRS2007) / Alaska zone 1",9001,4759,15031,9812,1,0,4499,8806,5000000,9001,8807,-5000000,9001,8811,57,9110,8812,-133.4,9110,8813,323.07483685,9110,8814,323.07483685,9110,8815,0.9999,9201
-3469,"NAD83(NSRS2007) / Alaska zone 2",9001,4759,15032,9807,1,0,4499,8801,54,9102,8802,-142,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3470,"NAD83(NSRS2007) / Alaska zone 3",9001,4759,15033,9807,1,0,4499,8801,54,9102,8802,-146,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3471,"NAD83(NSRS2007) / Alaska zone 4",9001,4759,15034,9807,1,0,4499,8801,54,9102,8802,-150,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3472,"NAD83(NSRS2007) / Alaska zone 5",9001,4759,15035,9807,1,0,4499,8801,54,9102,8802,-154,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3473,"NAD83(NSRS2007) / Alaska zone 6",9001,4759,15036,9807,1,0,4499,8801,54,9102,8802,-158,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3474,"NAD83(NSRS2007) / Alaska zone 7",9001,4759,15037,9807,1,0,4499,8801,54,9102,8802,-162,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3475,"NAD83(NSRS2007) / Alaska zone 8",9001,4759,15038,9807,1,0,4499,8801,54,9102,8802,-166,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3476,"NAD83(NSRS2007) / Alaska zone 9",9001,4759,15039,9807,1,0,4499,8801,54,9102,8802,-170,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3477,"NAD83(NSRS2007) / Alaska zone 10",9001,4759,15040,9802,1,0,4499,8821,51,9110,8822,-176,9110,8823,53.5,9110,8824,51.5,9110,8826,1000000,9001,8827,0,9001,,,
-3478,"NAD83(NSRS2007) / Arizona Central",9001,4759,10232,9807,1,0,4499,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,
-3479,"NAD83(NSRS2007) / Arizona Central (ft)",9002,4759,15305,9807,1,0,4495,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,
-3480,"NAD83(NSRS2007) / Arizona East",9001,4759,10231,9807,1,0,4499,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,
-3481,"NAD83(NSRS2007) / Arizona East (ft)",9002,4759,15304,9807,1,0,4495,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,
-3482,"NAD83(NSRS2007) / Arizona West",9001,4759,10233,9807,1,0,4499,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,213360,9001,8807,0,9001,,,,,,
-3483,"NAD83(NSRS2007) / Arizona West (ft)",9002,4759,15306,9807,1,0,4495,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,700000,9002,8807,0,9002,,,,,,
-3484,"NAD83(NSRS2007) / Arkansas North",9001,4759,10331,9802,1,0,4499,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,400000,9001,8827,0,9001,,,
-3485,"NAD83(NSRS2007) / Arkansas North (ftUS)",9003,4759,15385,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,1312333.3333,9003,8827,0,9003,,,
-3486,"NAD83(NSRS2007) / Arkansas South",9001,4759,10332,9802,1,0,4499,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,400000,9001,8827,400000,9001,,,
-3487,"NAD83(NSRS2007) / Arkansas South (ftUS)",9003,4759,15386,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,
-3488,"NAD83(NSRS2007) / California Albers",9001,4759,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,
-3489,"NAD83(NSRS2007) / California zone 1",9001,4759,10431,9802,1,0,4499,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9001,8827,500000,9001,,,
-3490,"NAD83(NSRS2007) / California zone 1 (ftUS)",9003,4759,15307,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-3491,"NAD83(NSRS2007) / California zone 2",9001,4759,10432,9802,1,0,4499,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9001,8827,500000,9001,,,
-3492,"NAD83(NSRS2007) / California zone 2 (ftUS)",9003,4759,15308,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-3493,"NAD83(NSRS2007) / California zone 3",9001,4759,10433,9802,1,0,4499,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9001,8827,500000,9001,,,
-3494,"NAD83(NSRS2007) / California zone 3 (ftUS)",9003,4759,15309,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-3495,"NAD83(NSRS2007) / California zone 4",9001,4759,10434,9802,1,0,4499,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9001,8827,500000,9001,,,
-3496,"NAD83(NSRS2007) / California zone 4 (ftUS)",9003,4759,15310,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-3497,"NAD83(NSRS2007) / California zone 5",9001,4759,10435,9802,1,0,4499,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9001,8827,500000,9001,,,
-3498,"NAD83(NSRS2007) / California zone 5 (ftUS)",9003,4759,15311,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-3499,"NAD83(NSRS2007) / California zone 6",9001,4759,10436,9802,1,0,4499,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9001,8827,500000,9001,,,
-3500,"NAD83(NSRS2007) / California zone 6 (ftUS)",9003,4759,15312,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-3501,"NAD83(NSRS2007) / Colorado Central",9001,4759,10532,9802,1,0,4499,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-3502,"NAD83(NSRS2007) / Colorado Central (ftUS)",9003,4759,15314,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,3000000,9003,8827,1000000,9003,,,
-3503,"NAD83(NSRS2007) / Colorado North",9001,4759,10531,9802,1,0,4499,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-3504,"NAD83(NSRS2007) / Colorado North (ftUS)",9003,4759,15313,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,3000000,9003,8827,1000000,9003,,,
-3505,"NAD83(NSRS2007) / Colorado South",9001,4759,10533,9802,1,0,4499,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-3506,"NAD83(NSRS2007) / Colorado South (ftUS)",9003,4759,15315,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,3000000,9003,8827,1000000,9003,,,
-3507,"NAD83(NSRS2007) / Connecticut",9001,4759,10630,9802,1,0,4499,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,304800.6096,9001,8827,152400.3048,9001,,,
-3508,"NAD83(NSRS2007) / Connecticut (ftUS)",9003,4759,15316,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,1000000,9003,8827,500000,9003,,,
-3509,"NAD83(NSRS2007) / Delaware",9001,4759,10730,9807,1,0,4499,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,200000,9001,8807,0,9001,,,,,,
-3510,"NAD83(NSRS2007) / Delaware (ftUS)",9003,4759,15317,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-3511,"NAD83(NSRS2007) / Florida East",9001,4759,10931,9807,1,0,4499,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,
-3512,"NAD83(NSRS2007) / Florida East (ftUS)",9003,4759,15318,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-3513,"NAD83(NSRS2007) / Florida GDL Albers",9001,4759,10934,9822,1,0,4499,8821,24,9110,8822,-84,9110,8823,24,9110,8824,31.3,9110,8826,400000,9001,8827,0,9001,,,
-3514,"NAD83(NSRS2007) / Florida North",9001,4759,10933,9802,1,0,4499,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,600000,9001,8827,0,9001,,,
-3515,"NAD83(NSRS2007) / Florida North (ftUS)",9003,4759,15320,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,1968500,9003,8827,0,9003,,,
-3516,"NAD83(NSRS2007) / Florida West",9001,4759,10932,9807,1,0,4499,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,
-3517,"NAD83(NSRS2007) / Florida West (ftUS)",9003,4759,15319,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-3518,"NAD83(NSRS2007) / Georgia East",9001,4759,11031,9807,1,0,4499,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-3519,"NAD83(NSRS2007) / Georgia East (ftUS)",9003,4759,15321,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-3520,"NAD83(NSRS2007) / Georgia West",9001,4759,11032,9807,1,0,4499,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,700000,9001,8807,0,9001,,,,,,
-3521,"NAD83(NSRS2007) / Georgia West (ftUS)",9003,4759,15322,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,2296583.333,9003,8807,0,9003,,,,,,
-3522,"NAD83(NSRS2007) / Idaho Central",9001,4759,11132,9807,1,0,4499,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9001,8807,0,9001,,,,,,
-3523,"NAD83(NSRS2007) / Idaho Central (ftUS)",9003,4759,15324,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,1640416.667,9003,8807,0,9003,,,,,,
-3524,"NAD83(NSRS2007) / Idaho East",9001,4759,11131,9807,1,0,4499,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,200000,9001,8807,0,9001,,,,,,
-3525,"NAD83(NSRS2007) / Idaho East (ftUS)",9003,4759,15323,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-3526,"NAD83(NSRS2007) / Idaho West",9001,4759,11133,9807,1,0,4499,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,800000,9001,8807,0,9001,,,,,,
-3527,"NAD83(NSRS2007) / Idaho West (ftUS)",9003,4759,15325,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,2624666.667,9003,8807,0,9003,,,,,,
-3528,"NAD83(NSRS2007) / Illinois East",9001,4759,11231,9807,1,0,4499,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,300000,9001,8807,0,9001,,,,,,
-3529,"NAD83(NSRS2007) / Illinois East (ftUS)",9003,4759,15387,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,984250,9003,8807,0,9003,,,,,,
-3530,"NAD83(NSRS2007) / Illinois West",9001,4759,11232,9807,1,0,4499,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,700000,9001,8807,0,9001,,,,,,
-3531,"NAD83(NSRS2007) / Illinois West (ftUS)",9003,4759,15388,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,2296583.3333,9003,8807,0,9003,,,,,,
-3532,"NAD83(NSRS2007) / Indiana East",9001,4759,11331,9807,1,0,4499,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,100000,9001,8807,250000,9001,,,,,,
-3533,"NAD83(NSRS2007) / Indiana East (ftUS)",9003,4759,15372,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,820208.333,9003,,,,,,
-3534,"NAD83(NSRS2007) / Indiana West",9001,4759,11332,9807,1,0,4499,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,900000,9001,8807,250000,9001,,,,,,
-3535,"NAD83(NSRS2007) / Indiana West (ftUS)",9003,4759,15373,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,820208.333,9003,,,,,,
-3536,"NAD83(NSRS2007) / Iowa North",9001,4759,11431,9802,1,0,4499,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,1500000,9001,8827,1000000,9001,,,
-3537,"NAD83(NSRS2007) / Iowa North (ftUS)",9003,4759,15377,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,4921250,9003,8827,3280833.3333,9003,,,
-3538,"NAD83(NSRS2007) / Iowa South",9001,4759,11432,9802,1,0,4499,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,500000,9001,8827,0,9001,,,
-3539,"NAD83(NSRS2007) / Iowa South (ftUS)",9003,4759,15378,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,1640416.6667,9003,8827,0,9003,,,
-3540,"NAD83(NSRS2007) / Kansas North",9001,4759,11531,9802,1,0,4499,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,400000,9001,8827,0,9001,,,
-3541,"NAD83(NSRS2007) / Kansas North (ftUS)",9003,4759,15379,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,1312333.3333,9003,8827,0,9003,,,
-3542,"NAD83(NSRS2007) / Kansas South",9001,4759,11532,9802,1,0,4499,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,400000,9001,8827,400000,9001,,,
-3543,"NAD83(NSRS2007) / Kansas South (ftUS)",9003,4759,15380,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,
-3544,"NAD83(NSRS2007) / Kentucky North",9001,4759,15303,9802,1,0,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,500000,9001,8827,0,9001,,,
-3545,"NAD83(NSRS2007) / Kentucky North (ftUS)",9003,4759,15328,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,1640416.667,9003,8827,0,9003,,,
-3546,"NAD83(NSRS2007) / Kentucky Single Zone",9001,4759,11630,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,1500000,9001,8827,1000000,9001,,,
-3547,"NAD83(NSRS2007) / Kentucky Single Zone (ftUS)",9003,4759,15375,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,4921250,9003,8827,3280833.333,9003,,,
-3548,"NAD83(NSRS2007) / Kentucky South",9001,4759,11632,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,500000,9001,8827,500000,9001,,,
-3549,"NAD83(NSRS2007) / Kentucky South (ftUS)",9003,4759,15329,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,1640416.667,9003,8827,1640416.667,9003,,,
-3550,"NAD83(NSRS2007) / Louisiana North",9001,4759,11731,9802,1,0,4499,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,1000000,9001,8827,0,9001,,,
-3551,"NAD83(NSRS2007) / Louisiana North (ftUS)",9003,4759,15391,9802,1,0,4497,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,3280833.3333,9003,8827,0,9003,,,
-3552,"NAD83(NSRS2007) / Louisiana South",9001,4759,11732,9802,1,0,4499,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,1000000,9001,8827,0,9001,,,
-3553,"NAD83(NSRS2007) / Louisiana South (ftUS)",9003,4759,15392,9802,1,0,4497,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,3280833.3333,9003,8827,0,9003,,,
-3554,"NAD83(NSRS2007) / Maine CS2000 Central",9001,4759,11854,9807,1,0,4499,8801,43.3,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,
-3555,"NAD83(NSRS2007) / Maine CS2000 East",9001,4759,11851,9807,1,0,4499,8801,43.5,9110,8802,-67.523,9110,8805,0.99998,9201,8806,700000,9001,8807,0,9001,,,,,,
-3556,"NAD83(NSRS2007) / Maine CS2000 West",9001,4759,11853,9807,1,0,4499,8801,42.5,9110,8802,-70.223,9110,8805,0.99998,9201,8806,300000,9001,8807,0,9001,,,,,,
-3557,"NAD83(NSRS2007) / Maine East",9001,4759,11831,9807,1,0,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,300000,9001,8807,0,9001,,,,,,
-3558,"NAD83(NSRS2007) / Maine West",9001,4759,11832,9807,1,0,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,900000,9001,8807,0,9001,,,,,,
-3559,"NAD83(NSRS2007) / Maryland",9001,4759,11930,9802,1,0,4499,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,400000,9001,8827,0,9001,,,
-3560,"NAD83 / Utah North (ftUS)",9003,4269,15297,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640416.6667,9003,8827,3280833.3333,9003,,,
-3561,"Old Hawaiian / Hawaii zone 1",9003,4135,15101,9807,1,0,4497,8801,18.5,9110,8802,-155.3,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,
-3562,"Old Hawaiian / Hawaii zone 2",9003,4135,15102,9807,1,0,4497,8801,20.2,9110,8802,-156.4,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,
-3563,"Old Hawaiian / Hawaii zone 3",9003,4135,15103,9807,1,0,4497,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,500000,9003,8807,0,9003,,,,,,
-3564,"Old Hawaiian / Hawaii zone 4",9003,4135,15104,9807,1,0,4497,8801,21.5,9110,8802,-159.3,9110,8805,0.99999,9201,8806,500000,9003,8807,0,9003,,,,,,
-3565,"Old Hawaiian / Hawaii zone 5",9003,4135,15105,9807,1,0,4497,8801,21.4,9110,8802,-160.1,9110,8805,1,9201,8806,500000,9003,8807,0,9003,,,,,,
-3566,"NAD83 / Utah Central (ftUS)",9003,4269,15298,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640416.6667,9003,8827,6561666.6667,9003,,,
-3567,"NAD83 / Utah South (ftUS)",9003,4269,15299,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640416.6667,9003,8827,9842500,9003,,,
-3568,"NAD83(HARN) / Utah North (ftUS)",9003,4152,15297,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640416.6667,9003,8827,3280833.3333,9003,,,
-3569,"NAD83(HARN) / Utah Central (ftUS)",9003,4152,15298,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640416.6667,9003,8827,6561666.6667,9003,,,
-3570,"NAD83(HARN) / Utah South (ftUS)",9003,4152,15299,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640416.6667,9003,8827,9842500,9003,,,
-3571,"WGS 84 / North Pole LAEA Bering Sea",9001,4326,17295,9820,1,0,4464,8801,90,9102,8802,180,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3572,"WGS 84 / North Pole LAEA Alaska",9001,4326,17296,9820,1,0,4467,8801,90,9102,8802,-150,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3573,"WGS 84 / North Pole LAEA Canada",9001,4326,17297,9820,1,0,4466,8801,90,9102,8802,-100,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3574,"WGS 84 / North Pole LAEA Atlantic",9001,4326,17298,9820,1,0,4465,8801,90,9102,8802,-40,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3575,"WGS 84 / North Pole LAEA Europe",9001,4326,17299,9820,1,0,4463,8801,90,9102,8802,10,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3576,"WGS 84 / North Pole LAEA Russia",9001,4326,17300,9820,1,0,1035,8801,90,9102,8802,90,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3577,"GDA94 / Australian Albers",9001,4283,17365,9822,1,0,4400,8821,0,9102,8822,132,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,
-3578,"NAD83 / Yukon Albers",9001,4269,19858,9822,1,0,4400,8821,59,9110,8822,-132.3,9110,8823,61.4,9110,8824,68,9110,8826,500000,9001,8827,500000,9001,,,
-3579,"NAD83(CSRS) / Yukon Albers",9001,4617,19858,9822,1,0,4400,8821,59,9110,8822,-132.3,9110,8823,61.4,9110,8824,68,9110,8826,500000,9001,8827,500000,9001,,,
-3580,"NAD83 / NWT Lambert",9001,4269,19857,9802,1,0,4400,8821,0,9102,8822,-112,9102,8823,62,9102,8824,70,9102,8826,0,9001,8827,0,9001,,,
-3581,"NAD83(CSRS) / NWT Lambert",9001,4617,19857,9802,1,0,4400,8821,0,9102,8822,-112,9102,8823,62,9102,8824,70,9102,8826,0,9001,8827,0,9001,,,
-3582,"NAD83(NSRS2007) / Maryland (ftUS)",9003,4759,15330,9802,1,0,4497,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,1312333.333,9003,8827,0,9003,,,
-3583,"NAD83(NSRS2007) / Massachusetts Island",9001,4759,12032,9802,1,0,4499,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,500000,9001,8827,0,9001,,,
-3584,"NAD83(NSRS2007) / Massachusetts Island (ftUS)",9003,4759,15332,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,1640416.667,9003,8827,0,9003,,,
-3585,"NAD83(NSRS2007) / Massachusetts Mainland",9001,4759,12031,9802,1,0,4499,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,200000,9001,8827,750000,9001,,,
-3586,"NAD83(NSRS2007) / Massachusetts Mainland (ftUS)",9003,4759,15331,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,656166.667,9003,8827,2460625,9003,,,
-3587,"NAD83(NSRS2007) / Michigan Central",9001,4759,12142,9802,1,0,4499,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,6000000,9001,8827,0,9001,,,
-3588,"NAD83(NSRS2007) / Michigan Central (ft)",9002,4759,15334,9802,1,0,4495,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,19685039.37,9002,8827,0,9002,,,
-3589,"NAD83(NSRS2007) / Michigan North",9001,4759,12141,9802,1,0,4499,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,8000000,9001,8827,0,9001,,,
-3590,"NAD83(NSRS2007) / Michigan North (ft)",9002,4759,15333,9802,1,0,4495,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,26246719.16,9002,8827,0,9002,,,
-3591,"NAD83(NSRS2007) / Michigan Oblique Mercator",9001,4759,12150,9812,1,0,4499,8806,2546731.496,9001,8807,-4354009.816,9001,8811,45.1833,9110,8812,-86,9110,8813,337.25556,9102,8814,337.25556,9102,8815,0.9996,9201
-3592,"NAD83(NSRS2007) / Michigan South",9001,4759,12143,9802,1,0,4499,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,4000000,9001,8827,0,9001,,,
-3593,"NAD83(NSRS2007) / Michigan South (ft)",9002,4759,15335,9802,1,0,4495,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,13123359.58,9002,8827,0,9002,,,
-3594,"NAD83(NSRS2007) / Minnesota Central",9001,4759,12232,9802,1,0,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,800000,9001,8827,100000,9001,,,
-3595,"NAD83(NSRS2007) / Minnesota North",9001,4759,12231,9802,1,0,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,800000,9001,8827,100000,9001,,,
-3596,"NAD83(NSRS2007) / Minnesota South",9001,4759,12233,9802,1,0,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,800000,9001,8827,100000,9001,,,
-3597,"NAD83(NSRS2007) / Mississippi East",9001,4759,12331,9807,1,0,4499,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,300000,9001,8807,0,9001,,,,,,
-3598,"NAD83(NSRS2007) / Mississippi East (ftUS)",9003,4759,15336,9807,1,0,4497,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,984250,9003,8807,0,9003,,,,,,
-3599,"NAD83(NSRS2007) / Mississippi West",9001,4759,12332,9807,1,0,4499,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,700000,9001,8807,0,9001,,,,,,
-3600,"NAD83(NSRS2007) / Mississippi West (ftUS)",9003,4759,15337,9807,1,0,4497,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,2296583.333,9003,8807,0,9003,,,,,,
-3601,"NAD83(NSRS2007) / Missouri Central",9001,4759,12432,9807,1,0,4499,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9001,8807,0,9001,,,,,,
-3602,"NAD83(NSRS2007) / Missouri East",9001,4759,12431,9807,1,0,4499,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,250000,9001,8807,0,9001,,,,,,
-3603,"NAD83(NSRS2007) / Missouri West",9001,4759,12433,9807,1,0,4499,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,850000,9001,8807,0,9001,,,,,,
-3604,"NAD83(NSRS2007) / Montana",9001,4759,12530,9802,1,0,4499,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,600000,9001,8827,0,9001,,,
-3605,"NAD83(NSRS2007) / Montana (ft)",9002,4759,15338,9802,1,0,4495,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,1968503.937,9002,8827,0,9002,,,
-3606,"NAD83(NSRS2007) / Nebraska",9001,4759,12630,9802,1,0,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,500000,9001,8827,0,9001,,,
-3607,"NAD83(NSRS2007) / Nevada Central",9001,4759,12732,9807,1,0,4499,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9001,8807,6000000,9001,,,,,,
-3608,"NAD83(NSRS2007) / Nevada Central (ftUS)",9003,4759,15382,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,1640416.6667,9003,8807,19685000,9003,,,,,,
-3609,"NAD83(NSRS2007) / Nevada East",9001,4759,12731,9807,1,0,4499,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,200000,9001,8807,8000000,9001,,,,,,
-3610,"NAD83(NSRS2007) / Nevada East (ftUS)",9003,4759,15381,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,656166.6667,9003,8807,26246666.6667,9003,,,,,,
-3611,"NAD83(NSRS2007) / Nevada West",9001,4759,12733,9807,1,0,4499,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,800000,9001,8807,4000000,9001,,,,,,
-3612,"NAD83(NSRS2007) / Nevada West (ftUS)",9003,4759,15383,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,2624666.6667,9003,8807,13123333.3333,9003,,,,,,
-3613,"NAD83(NSRS2007) / New Hampshire",9001,4759,12830,9807,1,0,4499,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,300000,9001,8807,0,9001,,,,,,
-3614,"NAD83(NSRS2007) / New Hampshire (ftUS)",9003,4759,15389,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,984250,9003,8807,0,9003,,,,,,
-3615,"NAD83(NSRS2007) / New Jersey",9001,4759,12930,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,
-3616,"NAD83(NSRS2007) / New Jersey (ftUS)",9003,4759,15384,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,
-3617,"NAD83(NSRS2007) / New Mexico Central",9001,4759,13032,9807,1,0,4499,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3618,"NAD83(NSRS2007) / New Mexico Central (ftUS)",9003,4759,15340,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,1640416.667,9003,8807,0,9003,,,,,,
-3619,"NAD83(NSRS2007) / New Mexico East",9001,4759,13031,9807,1,0,4499,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,165000,9001,8807,0,9001,,,,,,
-3620,"NAD83(NSRS2007) / New Mexico East (ftUS)",9003,4759,15339,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,541337.5,9003,8807,0,9003,,,,,,
-3621,"NAD83(NSRS2007) / New Mexico West",9001,4759,13033,9807,1,0,4499,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,830000,9001,8807,0,9001,,,,,,
-3622,"NAD83(NSRS2007) / New Mexico West (ftUS)",9003,4759,15341,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,2723091.667,9003,8807,0,9003,,,,,,
-3623,"NAD83(NSRS2007) / New York Central",9001,4759,13132,9807,1,0,4499,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,250000,9001,8807,0,9001,,,,,,
-3624,"NAD83(NSRS2007) / New York Central (ftUS)",9003,4759,15343,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,820208.333,9003,8807,0,9003,,,,,,
-3625,"NAD83(NSRS2007) / New York East",9001,4759,13131,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,
-3626,"NAD83(NSRS2007) / New York East (ftUS)",9003,4759,15342,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,
-3627,"NAD83(NSRS2007) / New York Long Island",9001,4759,13134,9802,1,0,4499,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,300000,9001,8827,0,9001,,,
-3628,"NAD83(NSRS2007) / New York Long Island (ftUS)",9003,4759,15345,9802,1,0,4497,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,984250,9003,8827,0,9003,,,
-3629,"NAD83(NSRS2007) / New York West",9001,4759,13133,9807,1,0,4499,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,350000,9001,8807,0,9001,,,,,,
-3630,"NAD83(NSRS2007) / New York West (ftUS)",9003,4759,15344,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,1148291.667,9003,8807,0,9003,,,,,,
-3631,"NAD83(NSRS2007) / North Carolina",9001,4759,13230,9802,1,0,4499,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,609601.22,9001,8827,0,9001,,,
-3632,"NAD83(NSRS2007) / North Carolina (ftUS)",9003,4759,15346,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,
-3633,"NAD83(NSRS2007) / North Dakota North",9001,4759,13331,9802,1,0,4499,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,600000,9001,8827,0,9001,,,
-3634,"NAD83(NSRS2007) / North Dakota North (ft)",9002,4759,15347,9802,1,0,4495,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,1968503.937,9002,8827,0,9002,,,
-3635,"NAD83(NSRS2007) / North Dakota South",9001,4759,13332,9802,1,0,4499,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,600000,9001,8827,0,9001,,,
-3636,"NAD83(NSRS2007) / North Dakota South (ft)",9002,4759,15348,9802,1,0,4495,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,1968503.937,9002,8827,0,9002,,,
-3637,"NAD83(NSRS2007) / Ohio North",9001,4759,13431,9802,1,0,4499,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,600000,9001,8827,0,9001,,,
-3638,"NAD83(NSRS2007) / Ohio South",9001,4759,13432,9802,1,0,4499,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,600000,9001,8827,0,9001,,,
-3639,"NAD83(NSRS2007) / Oklahoma North",9001,4759,13531,9802,1,0,4499,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,600000,9001,8827,0,9001,,,
-3640,"NAD83(NSRS2007) / Oklahoma North (ftUS)",9003,4759,15349,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,1968500,9003,8827,0,9003,,,
-3641,"NAD83(NSRS2007) / Oklahoma South",9001,4759,13532,9802,1,0,4499,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,600000,9001,8827,0,9001,,,
-3642,"NAD83(NSRS2007) / Oklahoma South (ftUS)",9003,4759,15350,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,1968500,9003,8827,0,9003,,,
-3643,"NAD83(NSRS2007) / Oregon LCC (m)",9001,4759,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,
-3644,"NAD83(NSRS2007) / Oregon GIC Lambert (ft)",9002,4759,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,
-3645,"NAD83(NSRS2007) / Oregon North",9001,4759,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,
-3646,"NAD83(NSRS2007) / Oregon North (ft)",9002,4759,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,
-3647,"NAD83(NSRS2007) / Oregon South",9001,4759,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,
-3648,"NAD83(NSRS2007) / Oregon South (ft)",9002,4759,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,
-3649,"NAD83(NSRS2007) / Pennsylvania North",9001,4759,13731,9802,1,0,4499,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,600000,9001,8827,0,9001,,,
-3650,"NAD83(NSRS2007) / Pennsylvania North (ftUS)",9003,4759,15353,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,1968500,9003,8827,0,9003,,,
-3651,"NAD83(NSRS2007) / Pennsylvania South",9001,4759,13732,9802,1,0,4499,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,600000,9001,8827,0,9001,,,
-3652,"NAD83(NSRS2007) / Pennsylvania South (ftUS)",9003,4759,15354,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,1968500,9003,8827,0,9003,,,
-3653,"NAD83(NSRS2007) / Rhode Island",9001,4759,13830,9807,1,0,4499,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,100000,9001,8807,0,9001,,,,,,
-3654,"NAD83(NSRS2007) / Rhode Island (ftUS)",9003,4759,15390,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,328083.3333,9003,8807,0,9003,,,,,,
-3655,"NAD83(NSRS2007) / South Carolina",9001,4759,13930,9802,1,0,4499,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,609600,9001,8827,0,9001,,,
-3656,"NAD83(NSRS2007) / South Carolina (ft)",9002,4759,15355,9802,1,0,4495,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,2000000,9002,8827,0,9002,,,
-3657,"NAD83(NSRS2007) / South Dakota North",9001,4759,14031,9802,1,0,4499,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,600000,9001,8827,0,9001,,,
-3658,"NAD83(NSRS2007) / South Dakota North (ftUS)",9003,4759,15394,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,1968500,9003,8827,0,9003,,,
-3659,"NAD83(NSRS2007) / South Dakota South",9001,4759,14032,9802,1,0,4499,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,600000,9001,8827,0,9001,,,
-3660,"NAD83(NSRS2007) / South Dakota South (ftUS)",9003,4759,15395,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,
-3661,"NAD83(NSRS2007) / Tennessee",9001,4759,14130,9802,1,0,4499,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,600000,9001,8827,0,9001,,,
-3662,"NAD83(NSRS2007) / Tennessee (ftUS)",9003,4759,15356,9802,1,0,4497,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,1968500,9003,8827,0,9003,,,
-3663,"NAD83(NSRS2007) / Texas Central",9001,4759,14233,9802,1,0,4499,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,700000,9001,8827,3000000,9001,,,
-3664,"NAD83(NSRS2007) / Texas Central (ftUS)",9003,4759,15359,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,2296583.333,9003,8827,9842500,9003,,,
-3665,"NAD83(NSRS2007) / Texas Centric Albers Equal Area",9001,4759,14254,9822,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,6000000,9001,,,
-3666,"NAD83(NSRS2007) / Texas Centric Lambert Conformal",9001,4759,14253,9802,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,5000000,9001,,,
-3667,"NAD83(NSRS2007) / Texas North",9001,4759,14231,9802,1,0,4499,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,200000,9001,8827,1000000,9001,,,
-3668,"NAD83(NSRS2007) / Texas North (ftUS)",9003,4759,15357,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,656166.667,9003,8827,3280833.333,9003,,,
-3669,"NAD83(NSRS2007) / Texas North Central",9001,4759,14232,9802,1,0,4499,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,600000,9001,8827,2000000,9001,,,
-3670,"NAD83(NSRS2007) / Texas North Central (ftUS)",9003,4759,15358,9802,1,0,4497,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,1968500,9003,8827,6561666.667,9003,,,
-3671,"NAD83(NSRS2007) / Texas South",9001,4759,14235,9802,1,0,4499,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,300000,9001,8827,5000000,9001,,,
-3672,"NAD83(NSRS2007) / Texas South (ftUS)",9003,4759,15361,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,984250,9003,8827,16404166.667,9003,,,
-3673,"NAD83(NSRS2007) / Texas South Central",9001,4759,14234,9802,1,0,4499,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,600000,9001,8827,4000000,9001,,,
-3674,"NAD83(NSRS2007) / Texas South Central (ftUS)",9003,4759,15360,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,1968500,9003,8827,13123333.333,9003,,,
-3675,"NAD83(NSRS2007) / Utah Central",9001,4759,14332,9802,1,0,4499,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,500000,9001,8827,2000000,9001,,,
-3676,"NAD83(NSRS2007) / Utah Central (ft)",9002,4759,15363,9802,0,0,4495,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640419.948,9002,8827,6561679.79,9002,,,
-3677,"NAD83(NSRS2007) / Utah Central (ftUS)",9003,4759,15298,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640416.6667,9003,8827,6561666.6667,9003,,,
-3678,"NAD83(NSRS2007) / Utah North",9001,4759,14331,9802,1,0,4499,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,500000,9001,8827,1000000,9001,,,
-3679,"NAD83(NSRS2007) / Utah North (ft)",9002,4759,15362,9802,0,0,4495,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640419.948,9002,8827,3280839.895,9002,,,
-3680,"NAD83(NSRS2007) / Utah North (ftUS)",9003,4759,15297,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640416.6667,9003,8827,3280833.3333,9003,,,
-3681,"NAD83(NSRS2007) / Utah South",9001,4759,14333,9802,1,0,4499,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,500000,9001,8827,3000000,9001,,,
-3682,"NAD83(NSRS2007) / Utah South (ft)",9002,4759,15364,9802,0,0,4495,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640419.948,9002,8827,9842519.685,9002,,,
-3683,"NAD83(NSRS2007) / Utah South (ftUS)",9003,4759,15299,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640416.6667,9003,8827,9842500,9003,,,
-3684,"NAD83(NSRS2007) / Vermont",9001,4759,14430,9807,1,0,4499,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9001,8807,0,9001,,,,,,
-3685,"NAD83(NSRS2007) / Virginia North",9001,4759,14531,9802,1,0,4499,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,3500000,9001,8827,2000000,9001,,,
-3686,"NAD83(NSRS2007) / Virginia North (ftUS)",9003,4759,15365,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,11482916.667,9003,8827,6561666.667,9003,,,
-3687,"NAD83(NSRS2007) / Virginia South",9001,4759,14532,9802,1,0,4499,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,3500000,9001,8827,1000000,9001,,,
-3688,"NAD83(NSRS2007) / Virginia South (ftUS)",9003,4759,15366,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,11482916.667,9003,8827,3280833.333,9003,,,
-3689,"NAD83(NSRS2007) / Washington North",9001,4759,14631,9802,1,0,4499,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,500000,9001,8827,0,9001,,,
-3690,"NAD83(NSRS2007) / Washington North (ftUS)",9003,4759,15367,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,1640416.667,9003,8827,0,9003,,,
-3691,"NAD83(NSRS2007) / Washington South",9001,4759,14632,9802,1,0,4499,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,500000,9001,8827,0,9001,,,
-3692,"NAD83(NSRS2007) / Washington South (ftUS)",9003,4759,15368,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,1640416.667,9003,8827,0,9003,,,
-3693,"NAD83(NSRS2007) / West Virginia North",9001,4759,14731,9802,1,0,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,600000,9001,8827,0,9001,,,
-3694,"NAD83(NSRS2007) / West Virginia South",9001,4759,14732,9802,1,0,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,600000,9001,8827,0,9001,,,
-3695,"NAD83(NSRS2007) / Wisconsin Central",9001,4759,14832,9802,1,0,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,
-3696,"NAD83(NSRS2007) / Wisconsin Central (ftUS)",9003,4759,15370,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,1968500,9003,8827,0,9003,,,
-3697,"NAD83(NSRS2007) / Wisconsin North",9001,4759,14831,9802,1,0,4499,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,600000,9001,8827,0,9001,,,
-3698,"NAD83(NSRS2007) / Wisconsin North (ftUS)",9003,4759,15369,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,1968500,9003,8827,0,9003,,,
-3699,"NAD83(NSRS2007) / Wisconsin South",9001,4759,14833,9802,1,0,4499,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,600000,9001,8827,0,9001,,,
-3700,"NAD83(NSRS2007) / Wisconsin South (ftUS)",9003,4759,15371,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,1968500,9003,8827,0,9003,,,
-3701,"NAD83(NSRS2007) / Wisconsin Transverse Mercator",9001,4759,14841,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,520000,9001,8807,-4480000,9001,,,,,,
-3702,"NAD83(NSRS2007) / Wyoming East",9001,4759,14931,9807,1,0,4499,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,200000,9001,8807,0,9001,,,,,,
-3703,"NAD83(NSRS2007) / Wyoming East Central",9001,4759,14932,9807,1,0,4499,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,400000,9001,8807,100000,9001,,,,,,
-3704,"NAD83(NSRS2007) / Wyoming West Central",9001,4759,14933,9807,1,0,4499,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,600000,9001,8807,0,9001,,,,,,
-3705,"NAD83(NSRS2007) / Wyoming West",9001,4759,14934,9807,1,0,4499,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,800000,9001,8807,100000,9001,,,,,,
-3706,"NAD83(NSRS2007) / UTM zone 59N",9001,4759,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3707,"NAD83(NSRS2007) / UTM zone 60N",9001,4759,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3708,"NAD83(NSRS2007) / UTM zone 1N",9001,4759,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3709,"NAD83(NSRS2007) / UTM zone 2N",9001,4759,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3710,"NAD83(NSRS2007) / UTM zone 3N",9001,4759,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3711,"NAD83(NSRS2007) / UTM zone 4N",9001,4759,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3712,"NAD83(NSRS2007) / UTM zone 5N",9001,4759,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3713,"NAD83(NSRS2007) / UTM zone 6N",9001,4759,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3714,"NAD83(NSRS2007) / UTM zone 7N",9001,4759,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3715,"NAD83(NSRS2007) / UTM zone 8N",9001,4759,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3716,"NAD83(NSRS2007) / UTM zone 9N",9001,4759,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3717,"NAD83(NSRS2007) / UTM zone 10N",9001,4759,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3718,"NAD83(NSRS2007) / UTM zone 11N",9001,4759,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3719,"NAD83(NSRS2007) / UTM zone 12N",9001,4759,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3720,"NAD83(NSRS2007) / UTM zone 13N",9001,4759,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3721,"NAD83(NSRS2007) / UTM zone 14N",9001,4759,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3722,"NAD83(NSRS2007) / UTM zone 15N",9001,4759,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3723,"NAD83(NSRS2007) / UTM zone 16N",9001,4759,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3724,"NAD83(NSRS2007) / UTM zone 17N",9001,4759,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3725,"NAD83(NSRS2007) / UTM zone 18N",9001,4759,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3726,"NAD83(NSRS2007) / UTM zone 19N",9001,4759,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3727,"Reunion 1947 / TM Reunion",9001,4626,19856,9807,1,0,4499,8801,-21.07,9110,8802,55.32,9110,8805,1,9201,8806,160000,9001,8807,50000,9001,,,,,,
-3728,"NAD83(NSRS2007) / Ohio North (ftUS)",9003,4759,13433,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,1968500,9003,8827,0,9003,,,
-3729,"NAD83(NSRS2007) / Ohio South (ftUS)",9003,4759,13434,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,1968500,9003,8827,0,9003,,,
-3730,"NAD83(NSRS2007) / Wyoming East (ftUS)",9003,4759,14935,9807,1,0,4497,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,656166.6667,9003,8807,0,9003,,,,,,
-3731,"NAD83(NSRS2007) / Wyoming East Central (ftUS)",9003,4759,14936,9807,1,0,4497,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,1312333.3333,9003,8807,328083.3333,9003,,,,,,
-3732,"NAD83(NSRS2007) / Wyoming West Central (ftUS)",9003,4759,14937,9807,1,0,4497,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,1968500,9003,8807,0,9003,,,,,,
-3733,"NAD83(NSRS2007) / Wyoming West (ftUS)",9003,4759,14938,9807,1,0,4497,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,2624666.6667,9003,8807,328083.3333,9003,,,,,,
-3734,"NAD83 / Ohio North (ftUS)",9003,4269,13433,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,1968500,9003,8827,0,9003,,,
-3735,"NAD83 / Ohio South (ftUS)",9003,4269,13434,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,1968500,9003,8827,0,9003,,,
-3736,"NAD83 / Wyoming East (ftUS)",9003,4269,14935,9807,1,0,4497,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,656166.6667,9003,8807,0,9003,,,,,,
-3737,"NAD83 / Wyoming East Central (ftUS)",9003,4269,14936,9807,1,0,4497,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,1312333.3333,9003,8807,328083.3333,9003,,,,,,
-3738,"NAD83 / Wyoming West Central (ftUS)",9003,4269,14937,9807,1,0,4497,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,1968500,9003,8807,0,9003,,,,,,
-3739,"NAD83 / Wyoming West (ftUS)",9003,4269,14938,9807,1,0,4497,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,2624666.6667,9003,8807,328083.3333,9003,,,,,,
-3740,"NAD83(HARN) / UTM zone 10N",9001,4152,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3741,"NAD83(HARN) / UTM zone 11N",9001,4152,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3742,"NAD83(HARN) / UTM zone 12N",9001,4152,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3743,"NAD83(HARN) / UTM zone 13N",9001,4152,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3744,"NAD83(HARN) / UTM zone 14N",9001,4152,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3745,"NAD83(HARN) / UTM zone 15N",9001,4152,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3746,"NAD83(HARN) / UTM zone 16N",9001,4152,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3747,"NAD83(HARN) / UTM zone 17N",9001,4152,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3748,"NAD83(HARN) / UTM zone 18N",9001,4152,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3749,"NAD83(HARN) / UTM zone 19N",9001,4152,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3750,"NAD83(HARN) / UTM zone 4N",9001,4152,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3751,"NAD83(HARN) / UTM zone 5N",9001,4152,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3752,"WGS 84 / Mercator 41",9001,4326,19855,9804,1,1,4499,8801,-41,9102,8802,100,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-3753,"NAD83(HARN) / Ohio North (ftUS)",9003,4152,13433,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,1968500,9003,8827,0,9003,,,
-3754,"NAD83(HARN) / Ohio South (ftUS)",9003,4152,13434,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,1968500,9003,8827,0,9003,,,
-3755,"NAD83(HARN) / Wyoming East (ftUS)",9003,4152,14935,9807,1,0,4497,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,656166.6667,9003,8807,0,9003,,,,,,
-3756,"NAD83(HARN) / Wyoming East Central (ftUS)",9003,4152,14936,9807,1,0,4497,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,1312333.3333,9003,8807,328083.3333,9003,,,,,,
-3757,"NAD83(HARN) / Wyoming West Central (ftUS)",9003,4152,14937,9807,1,0,4497,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,1968500,9003,8807,0,9003,,,,,,
-3758,"NAD83(HARN) / Wyoming West (ftUS)",9003,4152,14938,9807,1,0,4497,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,2624666.6667,9003,8807,328083.3333,9003,,,,,,
-3759,"NAD83 / Hawaii zone 3 (ftUS)",9003,4269,15138,9807,1,0,4497,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,
-3760,"NAD83(HARN) / Hawaii zone 3 (ftUS)",9003,4152,15138,9807,1,0,4497,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,
-3761,"NAD83(CSRS) / UTM zone 22N",9001,4617,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3762,"WGS 84 / South Georgia Lambert",9001,4326,19854,9802,1,0,4400,8821,-55,9102,8822,-37,9102,8823,-54,9110,8824,-54.45,9110,8826,0,9001,8827,0,9001,,,
-3763,"ETRS89 / Portugal TM06",9001,4258,19853,9807,1,0,4499,8801,39.400573,9110,8802,-8.075919,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-3764,"NZGD2000 / Chatham Island Circuit 2000",9001,4167,17959,9807,1,0,4500,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,
-3765,"HTRS96 / Croatia TM",9001,4761,19851,9807,1,0,4400,8801,0,9102,8802,16.5,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3766,"HTRS96 / Croatia LCC",9001,4761,19852,9802,1,0,4400,8821,0,9102,8822,16.3,9110,8823,45.55,9110,8824,43.05,9110,8826,0,9001,8827,0,9001,,,
-3767,"HTRS96 / UTM zone 33N",9001,4761,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3768,"HTRS96 / UTM zone 34N",9001,4761,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3769,"Bermuda 1957 / UTM zone 20N",9001,4216,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3770,"BDA2000 / Bermuda 2000 National Grid",9001,4762,19849,9807,1,0,4400,8801,32,9110,8802,-64.45,9110,8805,1,9201,8806,550000,9001,8807,100000,9001,,,,,,
-3771,"NAD27 / Alberta 3TM ref merid 111 W",9001,4267,17722,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3772,"NAD27 / Alberta 3TM ref merid 114 W",9001,4267,17723,9807,1,0,4400,8801,0,9102,8802,-114,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3773,"NAD27 / Alberta 3TM ref merid 117 W",9001,4267,17724,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3774,"NAD27 / Alberta 3TM ref merid 120 W",9001,4267,17725,9807,1,1,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9001,8806,0,9001,8807,0,9001,,,,,,
-3775,"NAD83 / Alberta 3TM ref merid 111 W",9001,4269,17722,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3776,"NAD83 / Alberta 3TM ref merid 114 W",9001,4269,17723,9807,1,0,4400,8801,0,9102,8802,-114,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3777,"NAD83 / Alberta 3TM ref merid 117 W",9001,4269,17724,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3778,"NAD83 / Alberta 3TM ref merid 120 W",9001,4269,17725,9807,1,1,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9001,8806,0,9001,8807,0,9001,,,,,,
-3779,"NAD83(CSRS) / Alberta 3TM ref merid 111 W",9001,4617,17722,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3780,"NAD83(CSRS) / Alberta 3TM ref merid 114 W",9001,4617,17723,9807,1,0,4400,8801,0,9102,8802,-114,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3781,"NAD83(CSRS) / Alberta 3TM ref merid 117 W",9001,4617,17724,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3782,"NAD83(CSRS) / Alberta 3TM ref merid 120 W",9001,4617,17725,9807,1,1,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9001,8806,0,9001,8807,0,9001,,,,,,
-3783,"Pitcairn 2006 / Pitcairn TM 2006",9001,4763,19848,9807,1,0,4400,8801,-25.04067894,9110,8802,-130.06466816,9110,8805,1,9201,8806,14200,9001,8807,15500,9001,,,,,,
-3784,"Pitcairn 1967 / UTM zone 9S",9001,4729,16109,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-3785,"Popular Visualisation CRS / Mercator",9001,4055,19847,9841,1,1,4499,8801,0,9102,8802,0,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-3786,"World Equidistant Cylindrical (Sphere)",9001,4047,19968,9823,1,1,4499,8801,0,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3787,"MGI / Slovene National Grid",9001,4312,19845,9807,1,1,4498,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,500000,9001,8807,-5000000,9001,,,,,,
-3788,"NZGD2000 / Auckland Islands TM 2000",9001,4167,17960,9807,1,0,4500,8801,0,9102,8802,166,9102,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,
-3789,"NZGD2000 / Campbell Island TM 2000",9001,4167,17961,9807,1,0,4500,8801,0,9102,8802,169,9102,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,
-3790,"NZGD2000 / Antipodes Islands TM 2000",9001,4167,17962,9807,1,0,4500,8801,0,9102,8802,179,9102,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,
-3791,"NZGD2000 / Raoul Island TM 2000",9001,4167,17963,9807,1,0,4500,8801,0,9102,8802,-178,9102,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,
-3793,"NZGD2000 / Chatham Islands TM 2000",9001,4167,17965,9807,1,0,4500,8801,0,9110,8802,-176.3,9110,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,
-3794,"Slovenia 1996 / Slovene National Grid",9001,4765,19845,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,500000,9001,8807,-5000000,9001,,,,,,
-3795,"NAD27 / Cuba Norte",9001,4267,18063,9802,1,0,4532,8821,22.21,9110,8822,-81,9110,8823,23,9110,8824,21.42,9110,8826,500000,9001,8827,280296.016,9001,,,
-3796,"NAD27 / Cuba Sur",9001,4267,18064,9802,1,0,4532,8821,20.43,9110,8822,-76.5,9110,8823,21.18,9110,8824,20.08,9110,8826,500000,9001,8827,229126.939,9001,,,
-3797,"NAD27 / MTQ Lambert",9001,4267,19844,9802,1,0,4499,8821,44,9102,8822,-70,9102,8823,50,9102,8824,46,9102,8826,800000,9001,8827,0,9001,,,
-3798,"NAD83 / MTQ Lambert",9001,4269,19844,9802,1,0,4499,8821,44,9102,8822,-70,9102,8823,50,9102,8824,46,9102,8826,800000,9001,8827,0,9001,,,
-3799,"NAD83(CSRS) / MTQ Lambert",9001,4617,19844,9802,1,0,4499,8821,44,9102,8822,-70,9102,8823,50,9102,8824,46,9102,8826,800000,9001,8827,0,9001,,,
-3800,"NAD27 / Alberta 3TM ref merid 120 W",9001,4267,17726,9807,1,0,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3801,"NAD83 / Alberta 3TM ref merid 120 W",9001,4269,17726,9807,1,0,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3802,"NAD83(CSRS) / Alberta 3TM ref merid 120 W",9001,4617,17726,9807,1,0,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-3812,"ETRS89 / Belgian Lambert 2008",9001,4258,3811,9802,1,0,4499,8821,50.4752134,9110,8822,4.2133177,9110,8823,49.5,9110,8824,51.1,9110,8826,649328,9001,8827,665262,9001,,,
-3814,"NAD83 / Mississippi TM",9001,4269,3813,9807,1,0,4499,8801,32.3,9110,8802,-89.45,9110,8805,0.9998335,9201,8806,500000,9001,8807,1300000,9001,,,,,,
-3815,"NAD83(HARN) / Mississippi TM",9001,4152,3813,9807,1,0,4499,8801,32.3,9110,8802,-89.45,9110,8805,0.9998335,9201,8806,500000,9001,8807,1300000,9001,,,,,,
-3816,"NAD83(NSRS2007) / Mississippi TM",9001,4759,3813,9807,1,0,4499,8801,32.3,9110,8802,-89.45,9110,8805,0.9998335,9201,8806,500000,9001,8807,1300000,9001,,,,,,
-3825,"TWD97 / TM2 zone 119",9001,3824,3818,9807,1,0,4499,8801,0,9102,8802,119,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,
-3826,"TWD97 / TM2 zone 121",9001,3824,3820,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,
-3827,"TWD67 / TM2 zone 119",9001,3821,3818,9807,1,0,4499,8801,0,9102,8802,119,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,
-3828,"TWD67 / TM2 zone 121",9001,3821,3820,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,
-3829,"Hu Tzu Shan 1950 / UTM zone 51N",9001,4236,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3832,"WGS 84 / PDC Mercator",9001,4326,3831,9804,1,0,4400,8801,0,9102,8802,150,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-3833,"Pulkovo 1942(58) / Gauss-Kruger zone 2",9001,4179,16202,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-3834,"Pulkovo 1942(83) / Gauss-Kruger zone 2",9001,4178,16202,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-3835,"Pulkovo 1942(83) / Gauss-Kruger zone 3",9001,4178,16203,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-3836,"Pulkovo 1942(83) / Gauss-Kruger zone 4",9001,4178,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-3837,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 3",9001,4179,16263,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-3838,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 4",9001,4179,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-3839,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 9",9001,4179,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-3840,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 10",9001,4179,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
-3841,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 6",9001,4178,16266,9807,1,0,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-3842,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 7",9001,4178,16266,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-3843,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 8",9001,4178,16266,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-3844,"Pulkovo 1942(58) / Stereo70",9001,4179,19926,9809,1,0,4530,8801,46,9102,8802,25,9102,8805,0.99975,9201,8806,500000,9001,8807,500000,9001,,,,,,
-3845,"SWEREF99 / RT90 7.5 gon V emulation",9001,4619,17339,9807,1,0,4530,8801,0,9110,8802,11.18225,9110,8805,1.000006,9201,8806,1500025.141,9001,8807,-667.282,9001,,,,,,
-3846,"SWEREF99 / RT90 5 gon V emulation",9001,4619,17340,9807,1,0,4530,8801,0,9110,8802,13.332256,9110,8805,1.0000058,9201,8806,1500044.695,9001,8807,-667.13,9001,,,,,,
-3847,"SWEREF99 / RT90 2.5 gon V emulation",9001,4619,17341,9807,1,0,4530,8801,0,9110,8802,15.4822624306,9110,8805,1.00000561024,9201,8806,1500064.274,9001,8807,-667.711,9001,,,,,,
-3848,"SWEREF99 / RT90 0 gon emulation",9001,4619,17342,9807,1,0,4530,8801,0,9110,8802,18.032268,9110,8805,1.0000054,9201,8806,1500083.521,9001,8807,-668.844,9001,,,,,,
-3849,"SWEREF99 / RT90 2.5 gon O emulation",9001,4619,17343,9807,1,0,4530,8801,0,9110,8802,20.182274,9110,8805,1.0000052,9201,8806,1500102.765,9001,8807,-670.706,9001,,,,,,
-3850,"SWEREF99 / RT90 5 gon O emulation",9001,4619,17344,9807,1,0,4530,8801,0,9110,8802,22.33228,9110,8805,1.0000049,9201,8806,1500121.846,9001,8807,-672.557,9001,,,,,,
-3851,"NZGD2000 / NZCS2000",9001,4167,17964,9802,1,0,4500,8821,-41,9110,8822,173,9110,8823,-37.3,9110,8824,-44.3,9110,8826,3000000,9001,8827,7000000,9001,,,
-3852,"RSRGD2000 / DGLC2000",9001,4764,17966,9802,1,0,4500,8821,-90,9110,8822,157,9110,8823,-76.4,9110,8824,-79.2,9110,8826,500000,9001,8827,0,9001,,,
-3854,County ST74,9001,4619,3853,9807,1,0,4531,8801,0,9110,8802,18.0328332,9110,8805,0.99999506,9201,8806,100182.7406,9001,8807,-6500620.1207,9001,,,,,,
-3857,"WGS 84 / Pseudo-Mercator",9001,4326,3856,1024,1,0,4499,8801,0,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3873,"ETRS89 / GK19FIN",9001,4258,3860,9807,1,0,4500,8801,0,9102,8802,19,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-3874,"ETRS89 / GK20FIN",9001,4258,3861,9807,1,0,4500,8801,0,9102,8802,20,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
-3875,"ETRS89 / GK21FIN",9001,4258,3862,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
-3876,"ETRS89 / GK22FIN",9001,4258,3863,9807,1,0,4500,8801,0,9102,8802,22,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
-3877,"ETRS89 / GK23FIN",9001,4258,3864,9807,1,0,4500,8801,0,9102,8802,23,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
-3878,"ETRS89 / GK24FIN",9001,4258,3865,9807,1,0,4500,8801,0,9102,8802,24,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,
-3879,"ETRS89 / GK25FIN",9001,4258,3866,9807,1,0,4500,8801,0,9102,8802,25,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
-3880,"ETRS89 / GK26FIN",9001,4258,3867,9807,1,0,4500,8801,0,9102,8802,26,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
-3881,"ETRS89 / GK27FIN",9001,4258,3868,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
-3882,"ETRS89 / GK28FIN",9001,4258,3869,9807,1,0,4500,8801,0,9102,8802,28,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
-3883,"ETRS89 / GK29FIN",9001,4258,3870,9807,1,0,4500,8801,0,9102,8802,29,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
-3884,"ETRS89 / GK30FIN",9001,4258,3871,9807,1,0,4500,8801,0,9102,8802,30,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
-3885,"ETRS89 / GK31FIN",9001,4258,3872,9807,1,0,4500,8801,0,9102,8802,31,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
-3890,"IGRS / UTM zone 37N",9001,3889,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3891,"IGRS / UTM zone 38N",9001,3889,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3892,"IGRS / UTM zone 39N",9001,3889,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3893,"ED50 / Iraq National Grid",9001,4230,19907,9807,1,0,4400,8801,29.0134566,9110,8802,46.3,9110,8805,0.9994,9201,8806,800000,9001,8807,0,9001,,,,,,
-3907,"MGI 1901 / Balkans zone 5",9001,3906,18275,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,5500000,9001,8807,0,9001,,,,,,
-3908,"MGI 1901 / Balkans zone 6",9001,3906,18276,9807,1,0,4530,8801,0,9102,8802,18,9102,8805,0.9999,9201,8806,6500000,9001,8807,0,9001,,,,,,
-3909,"MGI 1901 / Balkans zone 7",9001,3906,18277,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,
-3910,"MGI 1901 / Balkans zone 8",9001,3906,18278,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,8500000,9001,8807,0,9001,,,,,,
-3911,"MGI 1901 / Slovenia Grid",9001,3906,19967,9807,1,0,4530,8801,0,9110,8802,15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-3912,"MGI 1901 / Slovene National Grid",9001,3906,19845,9807,1,0,4498,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,500000,9001,8807,-5000000,9001,,,,,,
-3920,"Puerto Rico / UTM zone 20N",9001,4139,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-3942,"RGF93 / CC42",9001,4171,18101,9802,1,0,4499,8821,42,9102,8822,3,9102,8823,41.25,9102,8824,42.75,9102,8826,1700000,9001,8827,1200000,9001,,,
-3943,"RGF93 / CC43",9001,4171,18102,9802,1,0,4499,8821,43,9102,8822,3,9102,8823,42.25,9102,8824,43.75,9102,8826,1700000,9001,8827,2200000,9001,,,
-3944,"RGF93 / CC44",9001,4171,18103,9802,1,0,4499,8821,44,9102,8822,3,9102,8823,43.25,9102,8824,44.75,9102,8826,1700000,9001,8827,3200000,9001,,,
-3945,"RGF93 / CC45",9001,4171,18104,9802,1,0,4499,8821,45,9102,8822,3,9102,8823,44.25,9102,8824,45.75,9102,8826,1700000,9001,8827,4200000,9001,,,
-3946,"RGF93 / CC46",9001,4171,18105,9802,1,0,4499,8821,46,9102,8822,3,9102,8823,45.25,9102,8824,46.75,9102,8826,1700000,9001,8827,5200000,9001,,,
-3947,"RGF93 / CC47",9001,4171,18106,9802,1,0,4499,8821,47,9102,8822,3,9102,8823,46.25,9102,8824,47.75,9102,8826,1700000,9001,8827,6200000,9001,,,
-3948,"RGF93 / CC48",9001,4171,18107,9802,1,0,4499,8821,48,9102,8822,3,9102,8823,47.25,9102,8824,48.75,9102,8826,1700000,9001,8827,7200000,9001,,,
-3949,"RGF93 / CC49",9001,4171,18108,9802,1,0,4499,8821,49,9102,8822,3,9102,8823,48.25,9102,8824,49.75,9102,8826,1700000,9001,8827,8200000,9001,,,
-3950,"RGF93 / CC50",9001,4171,18109,9802,1,0,4499,8821,50,9102,8822,3,9102,8823,49.25,9102,8824,50.75,9102,8826,1700000,9001,8827,9200000,9001,,,
-3968,"NAD83 / Virginia Lambert",9001,4269,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,
-3969,"NAD83(HARN) / Virginia Lambert",9001,4152,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,
-3970,"NAD83(NSRS2007) / Virginia Lambert",9001,4759,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,
-3973,"WGS 84 / NSIDC EASE-Grid North",9001,4326,3897,1027,1,1,4469,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3974,"WGS 84 / NSIDC EASE-Grid South",9001,4326,3898,1027,1,1,4470,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-3975,"WGS 84 / NSIDC EASE-Grid Global",9001,4326,19869,9834,1,1,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,
-3976,"WGS 84 / NSIDC Sea Ice Polar Stereographic South",9001,4326,19866,9829,1,0,4470,8806,0,9001,8807,0,9001,8832,-70,9102,8833,0,9102,,,,,,,,,
-3978,"NAD83 / Canada Atlas Lambert",9001,4269,3977,9802,1,0,4400,8821,49,9102,8822,-95,9102,8823,49,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
-3979,"NAD83(CSRS) / Canada Atlas Lambert",9001,4617,3977,9802,1,0,4400,8821,49,9102,8822,-95,9102,8823,49,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
-3985,"Katanga 1955 / Katanga Lambert",9001,4695,3980,9802,1,1,4499,8821,9,9102,8822,26,9102,8823,-6.5,9102,8824,-11.5,9102,8826,500000,9001,8827,500000,9001,,,
-3986,"Katanga 1955 / Katanga Gauss zone A",9001,4695,3981,9807,1,0,4499,8801,-9,9102,8802,30,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-3987,"Katanga 1955 / Katanga Gauss zone B",9001,4695,3982,9807,1,0,4499,8801,-9,9102,8802,28,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-3988,"Katanga 1955 / Katanga Gauss zone C",9001,4695,3983,9807,1,0,4499,8801,-9,9102,8802,26,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-3989,"Katanga 1955 / Katanga Gauss zone D",9001,4695,3984,9807,1,0,4499,8801,-9,9102,8802,24,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-3991,Puerto Rico State Plane CS of 1927,9003,4139,15201,9802,1,0,4497,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,500000,9003,8827,0,9003,,,
-3992,"Puerto Rico / St. Croix",9003,4139,15202,9802,1,0,4497,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,500000,9003,8827,100000,9003,,,
-3993,"Guam 1963 / Guam SPCS",9001,4675,15400,9831,1,0,4499,8801,13.282087887,9110,8802,144.445550254,9110,8806,50000,9001,8807,50000,9001,,,,,,,,,
-3994,"WGS 84 / Mercator 41",9001,4326,19843,9805,1,0,4499,8802,100,9102,8806,0,9001,8807,0,9001,8823,-41,9102,,,,,,,,,
-3995,"WGS 84 / Arctic Polar Stereographic",9001,4326,19842,9829,1,0,4469,8806,0,9001,8807,0,9001,8832,71,9102,8833,0,9102,,,,,,,,,
-3996,"WGS 84 / IBCAO Polar Stereographic",9001,4326,19840,9829,1,0,4469,8806,0,9001,8807,0,9001,8832,75,9102,8833,0,9102,,,,,,,,,
-3997,"WGS 84 / Dubai Local TM",9001,4326,19839,9807,1,0,4400,8801,0,9110,8802,55.2,9110,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4026,"MOLDREF99 / Moldova TM",9001,4023,3999,9807,1,0,4530,8801,0,9110,8802,28.24,9110,8805,0.99994,9201,8806,200000,9001,8807,-5000000,9001,,,,,,
-4037,"WGS 84 / TMzn35N",9001,4326,16035,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4038,"WGS 84 / TMzn36N",9001,4326,16036,9807,1,0,4500,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4048,"RGRDC 2005 / Congo TM zone 12",9001,4046,17412,9807,1,0,4499,8801,0,9102,8802,12,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4049,"RGRDC 2005 / Congo TM zone 14",9001,4046,17414,9807,1,0,4499,8801,0,9102,8802,14,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4050,"RGRDC 2005 / Congo TM zone 16",9001,4046,17416,9807,1,0,4499,8801,0,9102,8802,16,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4051,"RGRDC 2005 / Congo TM zone 18",9001,4046,17418,9807,1,0,4499,8801,0,9102,8802,18,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4056,"RGRDC 2005 / Congo TM zone 20",9001,4046,17420,9807,1,0,4499,8801,0,9102,8802,20,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4057,"RGRDC 2005 / Congo TM zone 22",9001,4046,17422,9807,1,0,4499,8801,0,9102,8802,22,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4058,"RGRDC 2005 / Congo TM zone 24",9001,4046,17424,9807,1,0,4499,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4059,"RGRDC 2005 / Congo TM zone 26",9001,4046,17426,9807,1,0,4499,8801,0,9102,8802,26,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4060,"RGRDC 2005 / Congo TM zone 28",9001,4046,17428,9807,1,0,4499,8801,0,9102,8802,28,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4061,"RGRDC 2005 / UTM zone 33S",9001,4046,16133,9807,1,0,4499,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4062,"RGRDC 2005 / UTM zone 34S",9001,4046,16134,9807,1,0,4499,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4063,"RGRDC 2005 / UTM zone 35S",9001,4046,16135,9807,1,0,4499,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4071,"Chua / UTM zone 23S",9001,4224,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4082,"REGCAN95 / UTM zone 27N",9001,4081,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4083,"REGCAN95 / UTM zone 28N",9001,4081,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4087,"WGS 84 / World Equidistant Cylindrical",9001,4326,4085,1028,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,0,9102,,,,,,,,,
-4088,"World Equidistant Cylindrical (Sphere)",9001,4047,4086,1029,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,0,9102,,,,,,,,,
-4093,"ETRS89 / DKTM1",9001,4258,4089,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.99998,9201,8806,200000,9001,8807,-5000000,9001,,,,,,
-4094,"ETRS89 / DKTM2",9001,4258,4090,9807,1,0,4400,8801,0,9102,8802,10,9102,8805,0.99998,9201,8806,400000,9001,8807,-5000000,9001,,,,,,
-4095,"ETRS89 / DKTM3",9001,4258,4091,9807,1,0,4400,8801,0,9102,8802,11.75,9102,8805,0.99998,9201,8806,600000,9001,8807,-5000000,9001,,,,,,
-4096,"ETRS89 / DKTM4",9001,4258,4092,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,800000,9001,8807,-5000000,9001,,,,,,
-4217,"NAD83 / BLM 59N (ftUS)",9003,4269,4186,9807,1,0,4497,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4390,"Kertau 1968 / Johor Grid",9001,4245,4114,9806,1,0,4400,8801,2.02333,9110,8802,103.334593,9110,8806,0,9001,8807,0,9001,,,,,,,,,
-4391,"Kertau 1968 / Sembilan and Melaka Grid",9001,4245,4115,9806,1,0,4400,8801,2.424422,9110,8802,101.56282,9110,8806,-242.005,9001,8807,-948.547,9001,,,,,,,,,
-4392,"Kertau 1968 / Pahang Grid",9001,4245,4116,9806,1,0,4400,8801,3.42395,9110,8802,102.261024,9110,8806,0,9001,8807,0,9001,,,,,,,,,
-4393,"Kertau 1968 / Selangor Grid",9001,4245,4117,9806,1,0,4400,8801,3.404924,9110,8802,101.302968,9110,8806,-21759.438,9001,8807,55960.906,9001,,,,,,,,,
-4394,"Kertau 1968 / Terengganu Grid",9001,4245,4177,9806,1,0,4400,8801,4.564611,9110,8802,102.534275,9110,8806,0,9001,8807,0,9001,,,,,,,,,
-4395,"Kertau 1968 / Pinang Grid",9001,4245,4305,9806,1,0,4400,8801,5.251677,9110,8802,100.204513,9110,8806,0,9001,8807,0,9001,,,,,,,,,
-4396,"Kertau 1968 / Kedah and Perlis Grid",9001,4245,4320,9806,1,0,4400,8801,5.575453,9110,8802,100.381534,9110,8806,0,9001,8807,0,9001,,,,,,,,,
-4397,"Kertau 1968 / Perak Revised Grid",9001,4245,4321,9806,1,0,4400,8801,4.513377,9110,8802,100.490036,9110,8806,0,9001,8807,133453.669,9001,,,,,,,,,
-4398,"Kertau 1968 / Kelantan Grid",9001,4245,4323,9806,1,0,4400,8801,5.533812,9110,8802,102.103825,9110,8806,0,9001,8807,0,9001,,,,,,,,,
-4399,"NAD27 / BLM 59N (ftUS)",9003,4267,4186,9807,1,0,4497,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4400,"NAD27 / BLM 60N (ftUS)",9003,4267,4187,9807,1,0,4497,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4401,"NAD27 / BLM 1N (ftUS)",9003,4267,4101,9807,1,0,4497,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4402,"NAD27 / BLM 2N (ftUS)",9003,4267,4102,9807,1,0,4497,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4403,"NAD27 / BLM 3N (ftUS)",9003,4267,4103,9807,1,0,4497,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4404,"NAD27 / BLM 4N (ftUS)",9003,4267,4104,9807,1,0,4497,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4405,"NAD27 / BLM 5N (ftUS)",9003,4267,4105,9807,1,0,4497,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4406,"NAD27 / BLM 6N (ftUS)",9003,4267,4106,9807,1,0,4497,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4407,"NAD27 / BLM 7N (ftUS)",9003,4267,4107,9807,1,0,4497,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4408,"NAD27 / BLM 8N (ftUS)",9003,4267,4108,9807,1,0,4497,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4409,"NAD27 / BLM 9N (ftUS)",9003,4267,4109,9807,1,0,4497,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4410,"NAD27 / BLM 10N (ftUS)",9003,4267,4110,9807,1,0,4497,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4411,"NAD27 / BLM 11N (ftUS)",9003,4267,4111,9807,1,0,4497,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4412,"NAD27 / BLM 12N (ftUS)",9003,4267,4112,9807,1,0,4497,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4413,"NAD27 / BLM 13N (ftUS)",9003,4267,4113,9807,1,0,4497,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4414,"NAD83(HARN) / Guam Map Grid",9001,4152,4325,9807,1,0,4499,8801,13.3,9110,8802,144.45,9110,8805,1,9201,8806,100000,9001,8807,200000,9001,,,,,,
-4415,"Katanga 1955 / Katanga Lambert",9001,4695,4416,9802,1,0,4499,8821,-9,9102,8822,26,9102,8823,-6.5,9102,8824,-11.5,9102,8826,500000,9001,8827,500000,9001,,,
-4417,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 7",9001,4178,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-4418,"NAD27 / BLM 18N (ftUS)",9003,4267,4118,9807,1,0,4497,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4419,"NAD27 / BLM 19N (ftUS)",9003,4267,4119,9807,1,0,4497,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4420,"NAD83 / BLM 60N (ftUS)",9003,4269,4187,9807,1,0,4497,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4421,"NAD83 / BLM 1N (ftUS)",9003,4269,4101,9807,1,0,4497,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4422,"NAD83 / BLM 2N (ftUS)",9003,4269,4102,9807,1,0,4497,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4423,"NAD83 / BLM 3N (ftUS)",9003,4269,4103,9807,1,0,4497,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4424,"NAD83 / BLM 4N (ftUS)",9003,4269,4104,9807,1,0,4497,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4425,"NAD83 / BLM 5N (ftUS)",9003,4269,4105,9807,1,0,4497,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4426,"NAD83 / BLM 6N (ftUS)",9003,4269,4106,9807,1,0,4497,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4427,"NAD83 / BLM 7N (ftUS)",9003,4269,4107,9807,1,0,4497,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4428,"NAD83 / BLM 8N (ftUS)",9003,4269,4108,9807,1,0,4497,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4429,"NAD83 / BLM 9N (ftUS)",9003,4269,4109,9807,1,0,4497,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4430,"NAD83 / BLM 10N (ftUS)",9003,4269,4110,9807,1,0,4497,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4431,"NAD83 / BLM 11N (ftUS)",9003,4269,4111,9807,1,0,4497,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4432,"NAD83 / BLM 12N (ftUS)",9003,4269,4112,9807,1,0,4497,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4433,"NAD83 / BLM 13N (ftUS)",9003,4269,4113,9807,1,0,4497,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4434,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 8",9001,4178,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-4437,"NAD83(NSRS2007) / Puerto Rico and Virgin Is.",9001,4759,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,
-4438,"NAD83 / BLM 18N (ftUS)",9003,4269,4118,9807,1,0,4497,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4439,"NAD83 / BLM 19N (ftUS)",9003,4269,4119,9807,1,0,4497,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-4455,"NAD27 / Pennsylvania South",9003,4267,4436,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,2000000,9003,8827,0,9003,,,
-4456,"NAD27 / New York Long Island",9003,4267,4454,9802,1,0,4497,8821,40.3,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,2000000,9003,8827,100000,9003,,,
-4457,"NAD83 / South Dakota North (ftUS)",9003,4269,15394,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,1968500,9003,8827,0,9003,,,
-4462,"WGS 84 / Australian Centre for Remote Sensing Lambert",9001,4326,4460,9802,1,0,4400,8821,-27,9102,8822,132,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,
-4467,"RGSPM06 / UTM zone 21N",9001,4463,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4471,"RGM04 / UTM zone 38S",9001,4470,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4474,"Cadastre 1997 / UTM zone 38S",9001,4632,16138,9807,1,1,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-4484,"Mexico ITRF92 / UTM zone 11N",9001,4483,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4485,"Mexico ITRF92 / UTM zone 12N",9001,4483,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4486,"Mexico ITRF92 / UTM zone 13N",9001,4483,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4487,"Mexico ITRF92 / UTM zone 14N",9001,4483,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4488,"Mexico ITRF92 / UTM zone 15N",9001,4483,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4489,"Mexico ITRF92 / UTM zone 16N",9001,4483,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4491,"CGCS2000 / Gauss-Kruger zone 13",9001,4490,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-4492,"CGCS2000 / Gauss-Kruger zone 14",9001,4490,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-4493,"CGCS2000 / Gauss-Kruger zone 15",9001,4490,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-4494,"CGCS2000 / Gauss-Kruger zone 16",9001,4490,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,
-4495,"CGCS2000 / Gauss-Kruger zone 17",9001,4490,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,
-4496,"CGCS2000 / Gauss-Kruger zone 18",9001,4490,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,
-4497,"CGCS2000 / Gauss-Kruger zone 19",9001,4490,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-4498,"CGCS2000 / Gauss-Kruger zone 20",9001,4490,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
-4499,"CGCS2000 / Gauss-Kruger zone 21",9001,4490,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
-4500,"CGCS2000 / Gauss-Kruger zone 22",9001,4490,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
-4501,"CGCS2000 / Gauss-Kruger zone 23",9001,4490,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
-4502,"CGCS2000 / Gauss-Kruger CM 75E",9001,4490,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4503,"CGCS2000 / Gauss-Kruger CM 81E",9001,4490,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4504,"CGCS2000 / Gauss-Kruger CM 87E",9001,4490,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4505,"CGCS2000 / Gauss-Kruger CM 93E",9001,4490,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4506,"CGCS2000 / Gauss-Kruger CM 99E",9001,4490,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4507,"CGCS2000 / Gauss-Kruger CM 105E",9001,4490,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4508,"CGCS2000 / Gauss-Kruger CM 111E",9001,4490,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4509,"CGCS2000 / Gauss-Kruger CM 117E",9001,4490,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4510,"CGCS2000 / Gauss-Kruger CM 123E",9001,4490,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4511,"CGCS2000 / Gauss-Kruger CM 129E",9001,4490,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4512,"CGCS2000 / Gauss-Kruger CM 135E",9001,4490,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4513,"CGCS2000 / 3-degree Gauss-Kruger zone 25",9001,4490,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
-4514,"CGCS2000 / 3-degree Gauss-Kruger zone 26",9001,4490,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
-4515,"CGCS2000 / 3-degree Gauss-Kruger zone 27",9001,4490,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
-4516,"CGCS2000 / 3-degree Gauss-Kruger zone 28",9001,4490,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
-4517,"CGCS2000 / 3-degree Gauss-Kruger zone 29",9001,4490,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
-4518,"CGCS2000 / 3-degree Gauss-Kruger zone 30",9001,4490,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
-4519,"CGCS2000 / 3-degree Gauss-Kruger zone 31",9001,4490,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
-4520,"CGCS2000 / 3-degree Gauss-Kruger zone 32",9001,4490,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,
-4521,"CGCS2000 / 3-degree Gauss-Kruger zone 33",9001,4490,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,
-4522,"CGCS2000 / 3-degree Gauss-Kruger zone 34",9001,4490,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,
-4523,"CGCS2000 / 3-degree Gauss-Kruger zone 35",9001,4490,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,
-4524,"CGCS2000 / 3-degree Gauss-Kruger zone 36",9001,4490,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,
-4525,"CGCS2000 / 3-degree Gauss-Kruger zone 37",9001,4490,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,
-4526,"CGCS2000 / 3-degree Gauss-Kruger zone 38",9001,4490,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,
-4527,"CGCS2000 / 3-degree Gauss-Kruger zone 39",9001,4490,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,
-4528,"CGCS2000 / 3-degree Gauss-Kruger zone 40",9001,4490,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,
-4529,"CGCS2000 / 3-degree Gauss-Kruger zone 41",9001,4490,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,
-4530,"CGCS2000 / 3-degree Gauss-Kruger zone 42",9001,4490,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,
-4531,"CGCS2000 / 3-degree Gauss-Kruger zone 43",9001,4490,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,
-4532,"CGCS2000 / 3-degree Gauss-Kruger zone 44",9001,4490,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,
-4533,"CGCS2000 / 3-degree Gauss-Kruger zone 45",9001,4490,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,
-4534,"CGCS2000 / 3-degree Gauss-Kruger CM 75E",9001,4490,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4535,"CGCS2000 / 3-degree Gauss-Kruger CM 78E",9001,4490,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4536,"CGCS2000 / 3-degree Gauss-Kruger CM 81E",9001,4490,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4537,"CGCS2000 / 3-degree Gauss-Kruger CM 84E",9001,4490,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4538,"CGCS2000 / 3-degree Gauss-Kruger CM 87E",9001,4490,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4539,"CGCS2000 / 3-degree Gauss-Kruger CM 90E",9001,4490,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4540,"CGCS2000 / 3-degree Gauss-Kruger CM 93E",9001,4490,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4541,"CGCS2000 / 3-degree Gauss-Kruger CM 96E",9001,4490,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4542,"CGCS2000 / 3-degree Gauss-Kruger CM 99E",9001,4490,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4543,"CGCS2000 / 3-degree Gauss-Kruger CM 102E",9001,4490,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4544,"CGCS2000 / 3-degree Gauss-Kruger CM 105E",9001,4490,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4545,"CGCS2000 / 3-degree Gauss-Kruger CM 108E",9001,4490,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4546,"CGCS2000 / 3-degree Gauss-Kruger CM 111E",9001,4490,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4547,"CGCS2000 / 3-degree Gauss-Kruger CM 114E",9001,4490,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4548,"CGCS2000 / 3-degree Gauss-Kruger CM 117E",9001,4490,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4549,"CGCS2000 / 3-degree Gauss-Kruger CM 120E",9001,4490,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4550,"CGCS2000 / 3-degree Gauss-Kruger CM 123E",9001,4490,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4551,"CGCS2000 / 3-degree Gauss-Kruger CM 126E",9001,4490,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4552,"CGCS2000 / 3-degree Gauss-Kruger CM 129E",9001,4490,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4553,"CGCS2000 / 3-degree Gauss-Kruger CM 132E",9001,4490,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4554,"CGCS2000 / 3-degree Gauss-Kruger CM 135E",9001,4490,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4559,"RRAF 1991 / UTM zone 20N",9001,4558,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-4568,"New Beijing / Gauss-Kruger zone 13",9001,4555,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-4569,"New Beijing / Gauss-Kruger zone 14",9001,4555,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-4570,"New Beijing / Gauss-Kruger zone 15",9001,4555,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-4571,"New Beijing / Gauss-Kruger zone 16",9001,4555,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,
-4572,"New Beijing / Gauss-Kruger zone 17",9001,4555,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,
-4573,"New Beijing / Gauss-Kruger zone 18",9001,4555,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,
-4574,"New Beijing / Gauss-Kruger zone 19",9001,4555,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-4575,"New Beijing / Gauss-Kruger zone 20",9001,4555,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
-4576,"New Beijing / Gauss-Kruger zone 21",9001,4555,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
-4577,"New Beijing / Gauss-Kruger zone 22",9001,4555,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
-4578,"New Beijing / Gauss-Kruger zone 23",9001,4555,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
-4579,"New Beijing / Gauss-Kruger CM 75E",9001,4555,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4580,"New Beijing / Gauss-Kruger CM 81E",9001,4555,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4581,"New Beijing / Gauss-Kruger CM 87E",9001,4555,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4582,"New Beijing / Gauss-Kruger CM 93E",9001,4555,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4583,"New Beijing / Gauss-Kruger CM 99E",9001,4555,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4584,"New Beijing / Gauss-Kruger CM 105E",9001,4555,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4585,"New Beijing / Gauss-Kruger CM 111E",9001,4555,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4586,"New Beijing / Gauss-Kruger CM 117E",9001,4555,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4587,"New Beijing / Gauss-Kruger CM 123E",9001,4555,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4588,"New Beijing / Gauss-Kruger CM 129E",9001,4555,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4589,"New Beijing / Gauss-Kruger CM 135E",9001,4555,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4647,"ETRS89 / UTM zone 32N (zE-N)",9001,4258,4648,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,32500000,9001,8807,0,9001,,,,,,
-4652,"New Beijing / 3-degree Gauss-Kruger zone 25",9001,4555,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
-4653,"New Beijing / 3-degree Gauss-Kruger zone 26",9001,4555,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
-4654,"New Beijing / 3-degree Gauss-Kruger zone 27",9001,4555,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
-4655,"New Beijing / 3-degree Gauss-Kruger zone 28",9001,4555,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
-4656,"New Beijing / 3-degree Gauss-Kruger zone 29",9001,4555,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
-4766,"New Beijing / 3-degree Gauss-Kruger zone 30",9001,4555,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
-4767,"New Beijing / 3-degree Gauss-Kruger zone 31",9001,4555,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
-4768,"New Beijing / 3-degree Gauss-Kruger zone 32",9001,4555,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,
-4769,"New Beijing / 3-degree Gauss-Kruger zone 33",9001,4555,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,
-4770,"New Beijing / 3-degree Gauss-Kruger zone 34",9001,4555,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,
-4771,"New Beijing / 3-degree Gauss-Kruger zone 35",9001,4555,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,
-4772,"New Beijing / 3-degree Gauss-Kruger zone 36",9001,4555,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,
-4773,"New Beijing / 3-degree Gauss-Kruger zone 37",9001,4555,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,
-4774,"New Beijing / 3-degree Gauss-Kruger zone 38",9001,4555,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,
-4775,"New Beijing / 3-degree Gauss-Kruger zone 39",9001,4555,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,
-4776,"New Beijing / 3-degree Gauss-Kruger zone 40",9001,4555,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,
-4777,"New Beijing / 3-degree Gauss-Kruger zone 41",9001,4555,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,
-4778,"New Beijing / 3-degree Gauss-Kruger zone 42",9001,4555,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,
-4779,"New Beijing / 3-degree Gauss-Kruger zone 43",9001,4555,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,
-4780,"New Beijing / 3-degree Gauss-Kruger zone 44",9001,4555,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,
-4781,"New Beijing / 3-degree Gauss-Kruger zone 45",9001,4555,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,
-4782,"New Beijing / 3-degree Gauss-Kruger CM 75E",9001,4555,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4783,"New Beijing / 3-degree Gauss-Kruger CM 78E",9001,4555,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4784,"New Beijing / 3-degree Gauss-Kruger CM 81E",9001,4555,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4785,"New Beijing / 3-degree Gauss-Kruger CM 84E",9001,4555,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4786,"New Beijing / 3-degree Gauss-Kruger CM 87E",9001,4555,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4787,"New Beijing / 3-degree Gauss-Kruger CM 90E",9001,4555,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4788,"New Beijing / 3-degree Gauss-Kruger CM 93E",9001,4555,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4789,"New Beijing / 3-degree Gauss-Kruger CM 96E",9001,4555,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4790,"New Beijing / 3-degree Gauss-Kruger CM 99E",9001,4555,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4791,"New Beijing / 3-degree Gauss-Kruger CM 102E",9001,4555,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4792,"New Beijing / 3-degree Gauss-Kruger CM 105E",9001,4555,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4793,"New Beijing / 3-degree Gauss-Kruger CM 108E",9001,4555,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4794,"New Beijing / 3-degree Gauss-Kruger CM 111E",9001,4555,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4795,"New Beijing / 3-degree Gauss-Kruger CM 114E",9001,4555,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4796,"New Beijing / 3-degree Gauss-Kruger CM 117E",9001,4555,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4797,"New Beijing / 3-degree Gauss-Kruger CM 120E",9001,4555,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4798,"New Beijing / 3-degree Gauss-Kruger CM 123E",9001,4555,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4799,"New Beijing / 3-degree Gauss-Kruger CM 126E",9001,4555,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4800,"New Beijing / 3-degree Gauss-Kruger CM 129E",9001,4555,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4812,"New Beijing / 3-degree Gauss-Kruger CM 132E",9001,4555,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4822,"New Beijing / 3-degree Gauss-Kruger CM 135E",9001,4555,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-4826,"WGS 84 / Cape Verde National",9001,4326,4825,9802,1,0,1024,8821,15.5,9110,8822,-24,9110,8823,15,9110,8824,16.4,9110,8826,161587.83,9001,8827,128511.202,9001,,,
-4839,"ETRS89 / LCC Germany (N-E)",9001,4258,4838,9802,1,0,4500,8821,51,9102,8822,10.3,9110,8823,48.4,9110,8824,53.4,9110,8826,0,9001,8827,0,9001,,,
-4855,"ETRS89 / NTM zone 5",9001,4258,4845,9807,1,1,4500,8801,0,9110,8802,5.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4856,"ETRS89 / NTM zone 6",9001,4258,4846,9807,1,1,4500,8801,0,9110,8802,6.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4857,"ETRS89 / NTM zone 7",9001,4258,4847,9807,1,1,4500,8801,0,9110,8802,7.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4858,"ETRS89 / NTM zone 8",9001,4258,4848,9807,1,1,4500,8801,0,9110,8802,8.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4859,"ETRS89 / NTM zone 9",9001,4258,4849,9807,1,1,4500,8801,0,9110,8802,9.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4860,"ETRS89 / NTM zone 10",9001,4258,4850,9807,1,1,4500,8801,0,9110,8802,10.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4861,"ETRS89 / NTM zone 11",9001,4258,4851,9807,1,1,4500,8801,0,9110,8802,11.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4862,"ETRS89 / NTM zone 12",9001,4258,4852,9807,1,1,4500,8801,0,9110,8802,12.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4863,"ETRS89 / NTM zone 13",9001,4258,4853,9807,1,1,4500,8801,0,9110,8802,13.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4864,"ETRS89 / NTM zone 14",9001,4258,4854,9807,1,1,4500,8801,0,9110,8802,14.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4865,"ETRS89 / NTM zone 15",9001,4258,4841,9807,1,1,4500,8801,0,9110,8802,15.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4866,"ETRS89 / NTM zone 16",9001,4258,4842,9807,1,1,4500,8801,0,9110,8802,16.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4867,"ETRS89 / NTM zone 17",9001,4258,4843,9807,1,1,4500,8801,0,9110,8802,17.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4868,"ETRS89 / NTM zone 18",9001,4258,4844,9807,1,1,4500,8801,0,9110,8802,18.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4869,"ETRS89 / NTM zone 19",9001,4258,4881,9807,1,1,4500,8801,0,9110,8802,19.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4870,"ETRS89 / NTM zone 20",9001,4258,5000,9807,1,1,4500,8801,0,9110,8802,20.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4871,"ETRS89 / NTM zone 21",9001,4258,5001,9807,1,1,4500,8801,0,9110,8802,21.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4872,"ETRS89 / NTM zone 22",9001,4258,5002,9807,1,1,4500,8801,0,9110,8802,22.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4873,"ETRS89 / NTM zone 23",9001,4258,5003,9807,1,1,4500,8801,0,9110,8802,23.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4874,"ETRS89 / NTM zone 24",9001,4258,5004,9807,1,1,4500,8801,0,9110,8802,24.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4875,"ETRS89 / NTM zone 25",9001,4258,5005,9807,1,1,4500,8801,0,9110,8802,25.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4876,"ETRS89 / NTM zone 26",9001,4258,5006,9807,1,1,4500,8801,0,9110,8802,26.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4877,"ETRS89 / NTM zone 27",9001,4258,5007,9807,1,1,4500,8801,0,9110,8802,27.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4878,"ETRS89 / NTM zone 28",9001,4258,5008,9807,1,1,4500,8801,0,9110,8802,28.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4879,"ETRS89 / NTM zone 29",9001,4258,5009,9807,1,1,4500,8801,0,9110,8802,29.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-4880,"ETRS89 / NTM zone 30",9001,4258,5010,9807,1,1,4500,8801,0,9110,8802,30.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5014,"PTRA08 / UTM zone 25N",9001,5013,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5015,"PTRA08 / UTM zone 26N",9001,5013,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5016,"PTRA08 / UTM zone 28N",9001,5013,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5017,"Lisbon 1890 / Portugal Bonne New",9001,4666,5019,9828,1,0,6509,8801,39.4,9110,8802,-8.0754862,9110,8806,0,9001,8807,0,9001,,,,,,,,,
-5018,"Lisbon / Portuguese Grid New",9001,4207,5020,9807,1,0,4499,8801,39.4,9110,8802,-8.0754862,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-5041,"WGS 84 / UPS North (E,N)",9001,4326,16061,9810,1,0,1026,8801,90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
-5042,"WGS 84 / UPS South (E,N)",9001,4326,16161,9810,1,0,1027,8801,-90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
-5048,"ETRS89 / TM35FIN(N,E)",9001,4258,16065,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5069,"NAD27 / Conus Albers",9001,4267,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
-5070,"NAD83 / Conus Albers",9001,4269,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
-5071,"NAD83(HARN) / Conus Albers",9001,4152,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
-5072,"NAD83(NSRS2007) / Conus Albers",9001,4759,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
-5105,"ETRS89 / NTM zone 5",9001,4258,5135,9807,1,0,4500,8801,58,9110,8802,5.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5106,"ETRS89 / NTM zone 6",9001,4258,5136,9807,1,0,4500,8801,58,9110,8802,6.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5107,"ETRS89 / NTM zone 7",9001,4258,5137,9807,1,0,4500,8801,58,9110,8802,7.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5108,"ETRS89 / NTM zone 8",9001,4258,5138,9807,1,0,4500,8801,58,9110,8802,8.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5109,"ETRS89 / NTM zone 9",9001,4258,5139,9807,1,0,4500,8801,58,9110,8802,9.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5110,"ETRS89 / NTM zone 10",9001,4258,5140,9807,1,0,4500,8801,58,9110,8802,10.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5111,"ETRS89 / NTM zone 11",9001,4258,5141,9807,1,0,4500,8801,58,9110,8802,11.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5112,"ETRS89 / NTM zone 12",9001,4258,5142,9807,1,0,4500,8801,58,9110,8802,12.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5113,"ETRS89 / NTM zone 13",9001,4258,5143,9807,1,0,4500,8801,58,9110,8802,13.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5114,"ETRS89 / NTM zone 14",9001,4258,5144,9807,1,0,4500,8801,58,9110,8802,14.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5115,"ETRS89 / NTM zone 15",9001,4258,5145,9807,1,0,4500,8801,58,9110,8802,15.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5116,"ETRS89 / NTM zone 16",9001,4258,5146,9807,1,0,4500,8801,58,9110,8802,16.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5117,"ETRS89 / NTM zone 17",9001,4258,5147,9807,1,0,4500,8801,58,9110,8802,17.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5118,"ETRS89 / NTM zone 18",9001,4258,5148,9807,1,0,4500,8801,58,9110,8802,18.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5119,"ETRS89 / NTM zone 19",9001,4258,5149,9807,1,0,4500,8801,58,9110,8802,19.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5120,"ETRS89 / NTM zone 20",9001,4258,5150,9807,1,0,4500,8801,58,9110,8802,20.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5121,"ETRS89 / NTM zone 21",9001,4258,5151,9807,1,0,4500,8801,58,9110,8802,21.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5122,"ETRS89 / NTM zone 22",9001,4258,5152,9807,1,0,4500,8801,58,9110,8802,22.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5123,"ETRS89 / NTM zone 23",9001,4258,5153,9807,1,0,4500,8801,58,9110,8802,23.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5124,"ETRS89 / NTM zone 24",9001,4258,5154,9807,1,0,4500,8801,58,9110,8802,24.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5125,"ETRS89 / NTM zone 25",9001,4258,5155,9807,1,0,4500,8801,58,9110,8802,25.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5126,"ETRS89 / NTM zone 26",9001,4258,5156,9807,1,0,4500,8801,58,9110,8802,26.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5127,"ETRS89 / NTM zone 27",9001,4258,5157,9807,1,0,4500,8801,58,9110,8802,27.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5128,"ETRS89 / NTM zone 28",9001,4258,5158,9807,1,0,4500,8801,58,9110,8802,28.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5129,"ETRS89 / NTM zone 29",9001,4258,5159,9807,1,0,4500,8801,58,9110,8802,29.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5130,"ETRS89 / NTM zone 30",9001,4258,5160,9807,1,0,4500,8801,58,9110,8802,30.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,
-5167,"Korean 1985 / East Sea Belt",9001,4162,5049,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5168,"Korean 1985 / Central Belt Jeju",9001,4162,5131,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,
-5169,"Tokyo 1892 / Korea West Belt",9001,5132,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5170,"Tokyo 1892 / Korea Central Belt",9001,5132,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5171,"Tokyo 1892 / Korea East Belt",9001,5132,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5172,"Tokyo 1892 / Korea East Sea Belt",9001,5132,5049,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5173,"Korean 1985 / Modified West Belt",9001,4162,5161,9807,1,0,4530,8801,38,9102,8802,125.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5174,"Korean 1985 / Modified Central Belt",9001,4162,5162,9807,1,0,4530,8801,38,9102,8802,127.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5175,"Korean 1985 / Modified Central Belt Jeju",9001,4162,5163,9807,1,0,4530,8801,38,9102,8802,127.0010405,9110,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,
-5176,"Korean 1985 / Modified East Belt",9001,4162,5164,9807,1,0,4530,8801,38,9102,8802,129.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5177,"Korean 1985 / Modified East Sea Belt",9001,4162,5165,9807,1,0,4530,8801,38,9102,8802,131.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5178,"Korean 1985 / Unified CS",9001,4162,5100,9807,1,0,4530,8801,38,9102,8802,127.3,9110,8805,0.9996,9201,8806,1000000,9001,8807,2000000,9001,,,,,,
-5179,"Korea 2000 / Unified CS",9001,4737,5100,9807,1,0,4530,8801,38,9102,8802,127.3,9110,8805,0.9996,9201,8806,1000000,9001,8807,2000000,9001,,,,,,
-5180,"Korea 2000 / West Belt",9001,4737,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5181,"Korea 2000 / Central Belt",9001,4737,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5182,"Korea 2000 / Central Belt Jeju",9001,4737,5131,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,
-5183,"Korea 2000 / East Belt",9001,4737,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5184,"Korea 2000 / East Sea Belt",9001,4737,5049,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,
-5185,"Korea 2000 / West Belt 2010",9001,4737,5101,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
-5186,"Korea 2000 / Central Belt 2010",9001,4737,5102,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
-5187,"Korea 2000 / East Belt 2010",9001,4737,5103,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
-5188,"Korea 2000 / East Sea Belt 2010",9001,4737,5104,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,
-5221,"S-JTSK (Ferro) / Krovak East North",9001,4818,5218,1041,1,0,4499,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110
-5223,"WGS 84 / Gabon TM",9001,4326,5222,9807,1,0,4499,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,500000,9001,,,,,,
-5224,"S-JTSK/05 (Ferro) / Modified Krovak",9001,5229,5219,1042,1,0,6501,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
-5225,"S-JTSK/05 (Ferro) / Modified Krovak East North",9001,5229,5220,1043,1,0,4499,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
-5234,"Kandawala / Sri Lanka Grid",9001,4244,5231,9807,1,0,4400,8801,7.0001729,9110,8802,80.461816,9110,8805,0.9999238418,9201,8806,200000,9001,8807,200000,9001,,,,,,
-5235,"SLD99 / Sri Lanka Grid 1999",9001,5233,5232,9807,1,0,4400,8801,7.00016975,9110,8802,80.46181671,9110,8805,0.9999238418,9201,8806,500000,9001,8807,500000,9001,,,,,,
-5243,"ETRS89 / LCC Germany (E-N)",9001,4258,4838,9802,1,0,4400,8821,51,9102,8822,10.3,9110,8823,48.4,9110,8824,53.4,9110,8826,0,9001,8827,0,9001,,,
-5247,"GDBD2009 / Brunei BRSO",9001,5246,19894,9812,1,0,4400,8806,0,9001,8807,0,9001,8811,4,9110,8812,115,9110,8813,53.185691582,9110,8814,53.07483685,9110,8815,0.99984,9201
-5253,"TUREF / TM27",9001,5252,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5254,"TUREF / TM30",9001,5252,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5255,"TUREF / TM33",9001,5252,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5256,"TUREF / TM36",9001,5252,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5257,"TUREF / TM39",9001,5252,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5258,"TUREF / TM42",9001,5252,16374,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5259,"TUREF / TM45",9001,5252,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5266,"DRUKREF 03 / Bhutan National Grid",9001,5264,5265,9807,1,0,4400,8801,0,9102,8802,90,9102,8805,1,9201,8806,250000,9001,8807,0,9001,,,,,,
-5269,"TUREF / 3-degree Gauss-Kruger zone 9",9001,5252,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-5270,"TUREF / 3-degree Gauss-Kruger zone 10",9001,5252,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
-5271,"TUREF / 3-degree Gauss-Kruger zone 11",9001,5252,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
-5272,"TUREF / 3-degree Gauss-Kruger zone 12",9001,5252,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
-5273,"TUREF / 3-degree Gauss-Kruger zone 13",9001,5252,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-5274,"TUREF / 3-degree Gauss-Kruger zone 14",9001,5252,16274,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-5275,"TUREF / 3-degree Gauss-Kruger zone 15",9001,5252,16275,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-5292,"DRUKREF 03 / Bumthang TM",9001,5264,5268,9807,1,0,4400,8801,0,9110,8802,90.44,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5293,"DRUKREF 03 / Chhukha TM",9001,5264,5276,9807,1,0,4400,8801,0,9110,8802,89.33,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5294,"DRUKREF 03 / Dagana TM",9001,5264,5277,9807,1,0,4400,8801,0,9110,8802,89.51,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5295,"DRUKREF 03 / Gasa TM",9001,5264,5278,9807,1,0,4400,8801,0,9110,8802,90.02,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5296,"DRUKREF 03 / Ha TM",9001,5264,5279,9807,1,0,4400,8801,0,9110,8802,90.09,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5297,"DRUKREF 03 / Lhuentse TM",9001,5264,5280,9807,1,0,4400,8801,0,9110,8802,91.08,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5298,"DRUKREF 03 / Mongar TM",9001,5264,5281,9807,1,0,4400,8801,0,9110,8802,91.14,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5299,"DRUKREF 03 / Paro TM",9001,5264,5282,9807,1,0,4400,8801,0,9110,8802,89.21,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5300,"DRUKREF 03 / Pemagatshel TM",9001,5264,5283,9807,1,0,4400,8801,0,9110,8802,91.21,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5301,"DRUKREF 03 / Punakha TM",9001,5264,5313,9807,1,0,4400,8801,0,9110,8802,89.51,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5302,"DRUKREF 03 / Samdrup Jongkhar TM",9001,5264,5285,9807,1,0,4400,8801,0,9110,8802,91.34,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5303,"DRUKREF 03 / Samtse TM",9001,5264,5286,9807,1,0,4400,8801,0,9110,8802,89.04,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5304,"DRUKREF 03 / Sarpang TM",9001,5264,5287,9807,1,0,4400,8801,0,9110,8802,90.16,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5305,"DRUKREF 03 / Thimphu TM",9001,5264,5312,9807,1,0,4400,8801,0,9110,8802,89.33,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5306,"DRUKREF 03 / Trashigang TM",9001,5264,5289,9807,1,0,4400,8801,0,9110,8802,91.45,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5307,"DRUKREF 03 / Trongsa TM",9001,5264,5290,9807,1,0,4400,8801,0,9110,8802,90.3,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5308,"DRUKREF 03 / Tsirang TM",9001,5264,5284,9807,1,0,4400,8801,0,9110,8802,90.1,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5309,"DRUKREF 03 / Wangdue Phodrang TM",9001,5264,5288,9807,1,0,4400,8801,0,9110,8802,90.07,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5310,"DRUKREF 03 / Yangtse TM",9001,5264,5314,9807,1,0,4400,8801,0,9110,8802,91.34,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5311,"DRUKREF 03 / Zhemgang TM",9001,5264,5291,9807,1,0,4400,8801,0,9110,8802,90.52,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,
-5316,"ETRS89 / Faroe TM",9001,4258,5315,9807,1,0,4400,8801,0,9102,8802,-7,9102,8805,0.999997,9201,8806,200000,9001,8807,-6000000,9001,,,,,,
-5320,"NAD83 / Teranet Ontario Lambert",9001,4269,5319,9802,1,0,4499,8821,0,9102,8822,-84,9102,8823,44.3,9110,8824,54.3,9110,8826,1000000,9001,8827,0,9001,,,
-5321,"NAD83(CSRS) / Teranet Ontario Lambert",9001,4617,5319,9802,1,0,4499,8821,0,9102,8822,-84,9102,8823,44.3,9110,8824,54.3,9110,8826,1000000,9001,8827,0,9001,,,
-5325,"ISN2004 / Lambert 2004",9001,5324,5326,9802,1,0,4499,8821,65,9110,8822,-19,9110,8823,64.15,9110,8824,65.45,9110,8826,1700000,9001,8827,300000,9001,,,
-5329,"Segara (Jakarta) / NEIEZ",9001,4820,5328,9804,1,0,4499,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
-5330,"Batavia (Jakarta) / NEIEZ",9001,4813,5328,9804,1,0,4499,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
-5331,"Makassar (Jakarta) / NEIEZ",9001,4804,5328,9804,1,0,4499,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
-5337,"Aratu / UTM zone 25S",9001,4208,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5343,"POSGAR 2007 / Argentina 1",9001,5340,18031,9807,1,0,4530,8801,-90,9102,8802,-72,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-5344,"POSGAR 2007 / Argentina 2",9001,5340,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-5345,"POSGAR 2007 / Argentina 3",9001,5340,18033,9807,1,0,4530,8801,-90,9102,8802,-66,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-5346,"POSGAR 2007 / Argentina 4",9001,5340,18034,9807,1,0,4530,8801,-90,9102,8802,-63,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-5347,"POSGAR 2007 / Argentina 5",9001,5340,18035,9807,1,0,4530,8801,-90,9102,8802,-60,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-5348,"POSGAR 2007 / Argentina 6",9001,5340,18036,9807,1,0,4530,8801,-90,9102,8802,-57,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-5349,"POSGAR 2007 / Argentina 7",9001,5340,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-5355,"MARGEN / UTM zone 20S",9001,5354,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5356,"MARGEN / UTM zone 19S",9001,5354,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5357,"MARGEN / UTM zone 21S",9001,5354,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5361,"SIRGAS-Chile / UTM zone 19S",9001,5360,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5362,"SIRGAS-Chile / UTM zone 18S",9001,5360,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5367,"CR05 / CRTM05",9001,5365,5366,9807,1,0,4500,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-5382,"SIRGAS-ROU98 / UTM zone 21S",9001,5381,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5383,"SIRGAS-ROU98 / UTM zone 22S",9001,5381,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5387,"Peru96 / UTM zone 18S",9001,5373,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5388,"Peru96 / UTM zone 17S",9001,5373,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5389,"Peru96 / UTM zone 19S",9001,5373,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5396,"SIRGAS 2000 / UTM zone 26S",9001,4674,16126,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5456,"Ocotepeque 1935 / Costa Rica Norte",9001,5451,5390,9801,1,0,4499,8801,10.28,9110,8802,-84.2,9110,8805,0.99995696,9201,8806,500000,9001,8807,271820.522,9001,,,,,,
-5457,"Ocotepeque 1935 / Costa Rica Sur",9001,5451,5394,9801,1,0,4499,8801,9,9110,8802,-83.4,9110,8805,0.99995696,9201,8806,500000,9001,8807,327987.436,9001,,,,,,
-5458,"Ocotepeque 1935 / Guatemala Norte",9001,4267,18211,9801,1,1,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,
-5459,"Ocotepeque 1935 / Guatemala Sur",9001,5451,18212,9801,1,0,4499,8801,14.54,9110,8802,-90.2,9110,8805,0.99989906,9201,8806,500000,9001,8807,325992.681,9001,,,,,,
-5460,"Ocotepeque 1935 / El Salvador Lambert",9001,5451,5399,9801,1,0,4499,8801,13.47,9110,8802,-89,9110,8805,0.99996704,9201,8806,500000,9001,8807,295809.184,9001,,,,,,
-5461,"Ocotepeque 1935 / Nicaragua Norte",9001,5451,5439,9801,1,0,4499,8801,13.52,9110,8802,-85.3,9110,8805,0.99990314,9201,8806,500000,9001,8807,359891.816,9001,,,,,,
-5462,"Ocotepeque 1935 / Nicaragua Sur",9001,5451,5444,9801,1,0,4499,8801,11.44,9110,8802,-85.3,9110,8805,0.99992228,9201,8806,500000,9001,8807,288876.327,9001,,,,,,
-5463,"SAD69 / UTM zone 17N",9001,4618,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5466,"Sibun Gorge 1922 / Colony Grid",9001,5464,5465,9807,1,1,4499,8801,17.0340471,9110,8802,-88.3754687,9110,8805,1,9201,8806,217259.26,9005,8807,445474.83,9005,,,,,,
-5469,"Panama-Colon 1911 / Panama Lambert",9001,5467,5468,9801,1,0,4499,8801,8.25,9110,8802,-80,9110,8805,0.99989909,9201,8806,500000,9001,8807,294865.303,9001,,,,,,
-5472,"Panama-Colon 1911 / Panama Polyconic",9037,5467,5471,9818,1,0,1028,8801,8.15,9110,8802,-81,9110,8806,1000000,9037,8807,1092972.1,9037,,,,,,,,,
-5479,"RSRGD2000 / MSLC2000",9001,4764,5475,9802,1,0,4500,8821,-78,9110,8822,163,9110,8823,-76.4,9110,8824,-79.2,9110,8826,7000000,9001,8827,5000000,9001,,,
-5480,"RSRGD2000 / BCLC2000",9001,4764,5476,9802,1,0,4500,8821,-74.3,9110,8822,165,9110,8823,-73.4,9110,8824,-75.2,9110,8826,5000000,9001,8827,3000000,9001,,,
-5481,"RSRGD2000 / PCLC2000",9001,4764,5477,9802,1,0,4500,8821,-71.3,9110,8822,166,9110,8823,-70.4,9110,8824,-72.2,9110,8826,3000000,9001,8827,1000000,9001,,,
-5482,"RSRGD2000 / RSPS2000",9001,4764,5478,9810,1,0,1044,8801,-90,9102,8802,180,9102,8805,0.994,9201,8806,5000000,9001,8807,1000000,9001,,,,,,
-5490,"RGAF09 / UTM zone 20N",9001,5489,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5513,"S-JTSK / Krovak",9001,4156,5509,9819,1,0,6501,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110
-5514,"S-JTSK / Krovak East North",9001,4156,5510,1041,1,0,4499,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110
-5515,"S-JTSK/05 / Modified Krovak",9001,5228,5511,1042,1,0,6501,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
-5516,"S-JTSK/05 / Modified Krovak East North",9001,5228,5512,1043,1,0,4499,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203
-5518,"CI1971 / Chatham Islands Map Grid",9001,4672,5517,9807,1,0,4500,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,350000,9001,8807,650000,9001,,,,,,
-5519,"CI1979 / Chatham Islands Map Grid",9001,4673,5517,9807,1,0,4500,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,350000,9001,8807,650000,9001,,,,,,
-5520,"DHDN / 3-degree Gauss-Kruger zone 1",9001,4314,16261,9807,1,0,4530,8801,0,9102,8802,3,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-5523,"WGS 84 / Gabon TM 2011",9001,4326,5522,9807,1,0,4499,8801,0,9102,8802,11.3,9110,8805,0.9996,9201,8806,1500000,9001,8807,5500000,9001,,,,,,
-5530,"SAD69(96) / Brazil Polyconic",9001,5527,19941,9818,1,0,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
-5531,"SAD69(96) / UTM zone 21S",9001,5527,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5532,"SAD69(96) / UTM zone 22S",9001,4618,16122,9807,1,1,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5533,"SAD69(96) / UTM zone 23S",9001,5527,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5534,"SAD69(96) / UTM zone 24S",9001,5527,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5535,"SAD69(96) / UTM zone 25S",9001,5527,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5536,"Corrego Alegre 1961 / UTM zone 21S",9001,5524,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5537,"Corrego Alegre 1961 / UTM zone 22S",9001,5524,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5538,"Corrego Alegre 1961 / UTM zone 23S",9001,5524,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5539,"Corrego Alegre 1961 / UTM zone 24S",9001,5524,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5550,"PNG94 / PNGMG94 zone 54",9001,5546,5547,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5551,"PNG94 / PNGMG94 zone 55",9001,5546,5548,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5552,"PNG94 / PNGMG94 zone 56",9001,5546,5549,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5559,"Ocotepeque 1935 / Guatemala Norte",9001,5451,18211,9801,1,0,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,
-5562,"UCS-2000 / Gauss-Kruger zone 4",9001,5561,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-5563,"UCS-2000 / Gauss-Kruger zone 5",9001,5561,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-5564,"UCS-2000 / Gauss-Kruger zone 6",9001,5561,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-5565,"UCS-2000 / Gauss-Kruger zone 7",9001,5561,16207,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-5566,"UCS-2000 / Gauss-Kruger CM 21E",9001,5561,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5567,"UCS-2000 / Gauss-Kruger CM 27E",9001,5561,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5568,"UCS-2000 / Gauss-Kruger CM 33E",9001,5561,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5569,"UCS-2000 / Gauss-Kruger CM 39E",9001,5561,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5570,"UCS-2000 / 3-degree Gauss-Kruger zone 7",9001,5561,16267,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-5571,"UCS-2000 / 3-degree Gauss-Kruger zone 8",9001,5561,16268,9807,1,1,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-5572,"UCS-2000 / 3-degree Gauss-Kruger zone 9",9001,5561,16269,9807,1,1,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-5573,"UCS-2000 / 3-degree Gauss-Kruger zone 10",9001,5561,16270,9807,1,1,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
-5574,"UCS-2000 / 3-degree Gauss-Kruger zone 11",9001,5561,16271,9807,1,1,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
-5575,"UCS-2000 / 3-degree Gauss-Kruger zone 12",9001,5561,16272,9807,1,1,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
-5576,"UCS-2000 / 3-degree Gauss-Kruger zone 13",9001,5561,16273,9807,1,1,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-5577,"UCS-2000 / 3-degree Gauss-Kruger CM 21E",9001,5561,16304,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5578,"UCS-2000 / 3-degree Gauss-Kruger CM 24E",9001,5561,16368,9807,1,1,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5579,"UCS-2000 / 3-degree Gauss-Kruger CM 27E",9001,5561,16305,9807,1,1,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5580,"UCS-2000 / 3-degree Gauss-Kruger CM 30E",9001,5561,16370,9807,1,1,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5581,"UCS-2000 / 3-degree Gauss-Kruger CM 33E",9001,5561,16306,9807,1,1,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5582,"UCS-2000 / 3-degree Gauss-Kruger CM 36E",9001,5561,16372,9807,1,1,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5583,"UCS-2000 / 3-degree Gauss-Kruger CM 39E",9001,5561,16307,9807,1,1,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-5588,"NAD27 / New Brunswick Stereographic (NAD27)",9002,4267,5587,9809,1,0,1029,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,1000000,9002,8807,1000000,9002,,,,,,
-5589,"Sibun Gorge 1922 / Colony Grid",9005,5464,5465,9807,1,0,4403,8801,17.0340471,9110,8802,-88.3754687,9110,8805,1,9201,8806,217259.26,9005,8807,445474.83,9005,,,,,,
-5596,"FEH2010 / Fehmarnbelt TM",9001,5593,5595,9807,1,0,4400,8801,0,9110,8802,11.2,9110,8805,1,9201,8806,1000000,9001,8807,0,9001,,,,,,
-5623,"NAD27 / Michigan East",9003,4267,12101,9807,1,0,4497,8801,41.3,9110,8802,-83.4,9110,8805,0.999942857,9201,8806,500000,9003,8807,0,9003,,,,,,
-5624,"NAD27 / Michigan Old Central",9003,4267,12102,9807,1,0,4497,8801,41.3,9110,8802,-85.45,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,
-5625,"NAD27 / Michigan West",9003,4267,12103,9807,1,0,4497,8801,41.3,9110,8802,-88.45,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,
-5627,"ED50 / TM 6 NE",9001,4230,16406,9807,1,0,4400,8801,0,9102,8802,6,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5629,"Moznet / UTM zone 38S",9001,4130,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5631,"Pulkovo 1942(58) / Gauss-Kruger zone 2 (E-N)",9001,4179,16202,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-5632,"PTRA08 / LCC Europe",9001,5013,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,
-5633,"PTRA08 / LAEA Europe",9001,5013,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,
-5634,"REGCAN95 / LCC Europe",9001,4081,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,
-5635,"REGCAN95 / LAEA Europe",9001,4081,19986,9820,1,0,4500,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,
-5636,"TUREF / LAEA Europe",9001,5252,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,
-5637,"TUREF / LCC Europe",9001,5252,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,
-5638,"ISN2004 / LAEA Europe",9001,5324,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,
-5639,"ISN2004 / LCC Europe",9001,5324,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,
-5641,"SIRGAS 2000 / Brazil Mercator",9001,4674,5640,9805,1,0,4499,8802,-43,9102,8806,5000000,9001,8807,10000000,9001,8823,-2,9102,,,,,,,,,
-5643,"ED50 / SPBA LCC",9001,4230,5642,9802,1,0,4400,8821,48,9102,8822,10,9102,8823,52.4,9110,8824,54.2,9110,8826,815000,9001,8827,0,9001,,,
-5644,"RGR92 / UTM zone 39S",9001,4627,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5646,"NAD83 / Vermont (ftUS)",9003,4269,5645,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,
-5649,"ETRS89 / UTM zone 31N (zE-N)",9001,4258,5647,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,31500000,9001,8807,0,9001,,,,,,
-5650,"ETRS89 / UTM zone 33N (zE-N)",9001,4258,5648,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,33500000,9001,8807,0,9001,,,,,,
-5651,"ETRS89 / UTM zone 31N (N-zE)",9001,4258,5647,9807,1,0,4500,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,31500000,9001,8807,0,9001,,,,,,
-5652,"ETRS89 / UTM zone 32N (N-zE)",9001,4258,4648,9807,1,0,4500,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,32500000,9001,8807,0,9001,,,,,,
-5653,"ETRS89 / UTM zone 33N (N-zE)",9001,4258,5648,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,33500000,9001,8807,0,9001,,,,,,
-5654,"NAD83(HARN) / Vermont (ftUS)",9003,4152,5645,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,
-5655,"NAD83(NSRS2007) / Vermont (ftUS)",9003,4759,5645,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,
-5659,"Monte Mario / TM Emilia-Romagna",9001,4265,5658,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500053,9001,8807,-3999820,9001,,,,,,
-5663,"Pulkovo 1942(58) / Gauss-Kruger zone 3 (E-N)",9001,4179,16203,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-5664,"Pulkovo 1942(83) / Gauss-Kruger zone 2 (E-N)",9001,4178,16202,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-5665,"Pulkovo 1942(83) / Gauss-Kruger zone 3 (E-N)",9001,4178,16203,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-5666,"PD/83 / 3-degree Gauss-Kruger zone 3 (E-N)",9001,4746,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-5667,"PD/83 / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4746,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-5668,"RD/83 / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4745,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-5669,"RD/83 / 3-degree Gauss-Kruger zone 5 (E-N)",9001,4745,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-5670,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 3 (E-N)",9001,4179,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-5671,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4179,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-5672,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 5 (E-N)",9001,4179,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-5673,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 3 (E-N)",9001,4178,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-5674,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4178,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-5675,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 5 (E-N)",9001,4178,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-5676,"DHDN / 3-degree Gauss-Kruger zone 2 (E-N)",9001,4314,16262,9807,1,0,4400,8801,0,9102,8802,6,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-5677,"DHDN / 3-degree Gauss-Kruger zone 3 (E-N)",9001,4314,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-5678,"DHDN / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4314,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-5679,"DHDN / 3-degree Gauss-Kruger zone 5 (E-N)",9001,4314,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-5680,"DHDN / 3-degree Gauss-Kruger zone 1 (E-N)",9001,4314,16261,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-5682,"DB_REF / 3-degree Gauss-Kruger zone 2 (E-N)",9001,5681,16262,9807,1,0,4400,8801,0,9102,8802,6,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-5683,"DB_REF / 3-degree Gauss-Kruger zone 3 (E-N)",9001,5681,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-5684,"DB_REF / 3-degree Gauss-Kruger zone 4 (E-N)",9001,5681,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-5685,"DB_REF / 3-degree Gauss-Kruger zone 5 (E-N)",9001,5681,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-5700,"NZGD2000 / UTM zone 1S",9001,4167,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5819,EPSG topocentric example A,9001,4979,15594,9837,1,0,4461,8834,55,9102,8835,5,9102,8836,0,9001,,,,,,,,,,,,
-5820,EPSG topocentric example B,9001,4978,15595,9836,1,0,4461,8837,3771793.97,9001,8838,140253.34,9001,8839,5124304.35,9001,,,,,,,,,,,,
-5821,EPSG vertical perspective example,9001,5819,19850,9838,1,0,4461,8834,55,9102,8835,5,9102,8836,200,9001,8840,5900,9036,,,,,,,,,
-5825,"AGD66 / ACT Standard Grid",9001,4202,5824,9807,1,0,4400,8801,-35.19038506,9110,8802,149.003346139,9110,8805,1.000086,9201,8806,200000,9001,8807,600000,9001,,,,,,
-5836,"Yemen NGN96 / UTM zone 37N",9001,4163,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5837,"Yemen NGN96 / UTM zone 40N",9001,4163,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-5839,"Peru96 / UTM zone 17S",9001,5373,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5842,"WGS 84 / TM 12 SE",9001,4326,16612,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5844,"RGRDC 2005 / Congo TM zone 30",9001,4046,17430,9807,1,0,4499,8801,0,9102,8802,30,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5858,"SAD69(96) / UTM zone 22S",9001,5527,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5875,"SAD69(96) / UTM zone 18S",9001,5527,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5876,"SAD69(96) / UTM zone 19S",9001,5527,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5877,"SAD69(96) / UTM zone 20S",9001,5527,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5879,"Cadastre 1997 / UTM zone 38S",9001,4475,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-5880,"SIRGAS 2000 / Brazil Polyconic",9001,4674,19941,9818,1,0,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
-5887,"TGD2005 / Tonga Map Grid",9001,5886,5883,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1500000,9001,8807,5000000,9001,,,,,,
-5890,JAXA Snow Depth Polar Stereographic North,9001,4054,5889,9829,1,0,1035,8806,0,9001,8807,0,9001,8832,70,9102,8833,90,9102,,,,,,,,,
-5921,"WGS 84 / EPSG Arctic Regional zone A1",9001,4326,5906,9802,1,0,4400,8821,81.19020136,9110,8822,-111,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
-5922,"WGS 84 / EPSG Arctic Regional zone A2",9001,4326,5907,9802,1,0,4400,8821,81.19020136,9110,8822,-39,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
-5923,"WGS 84 / EPSG Arctic Regional zone A3",9001,4326,5908,9802,1,0,4400,8821,81.19020136,9110,8822,33,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
-5924,"WGS 84 / EPSG Arctic Regional zone A4",9001,4326,5909,9802,1,0,4400,8821,81.19020136,9110,8822,105,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
-5925,"WGS 84 / EPSG Arctic Regional zone A5",9001,4326,5910,9802,1,0,4400,8821,81.19020136,9110,8822,177,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
-5926,"WGS 84 / EPSG Arctic Regional zone B1",9001,4326,5911,9802,1,0,4400,8821,73.09206671,9110,8822,-111,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
-5927,"WGS 84 / EPSG Arctic Regional zone B2",9001,4326,5912,9802,1,0,4400,8821,73.09206671,9110,8822,-39,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
-5928,"WGS 84 / EPSG Arctic Regional zone B3",9001,4326,5913,9802,1,0,4400,8821,73.09206671,9110,8822,33,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
-5929,"WGS 84 / EPSG Arctic Regional zone B4",9001,4326,5914,9802,1,0,4400,8821,73.09206671,9110,8822,105,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
-5930,"WGS 84 / EPSG Arctic Regional zone B5",9001,4326,5915,9802,1,0,4400,8821,73.09206671,9110,8822,177,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,
-5931,"WGS 84 / EPSG Arctic Regional zone C1",9001,4326,5916,9802,1,0,4400,8821,65.06045752,9110,8822,-111,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
-5932,"WGS 84 / EPSG Arctic Regional zone C2",9001,4326,5917,9802,1,0,4400,8821,65.06045752,9110,8822,-39,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
-5933,"WGS 84 / EPSG Arctic Regional zone C3",9001,4326,5918,9802,1,0,4400,8821,65.06045752,9110,8822,33,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
-5934,"WGS 84 / EPSG Arctic Regional zone C4",9001,4326,5919,9802,1,0,4400,8821,65.06045752,9110,8822,105,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
-5935,"WGS 84 / EPSG Arctic Regional zone C5",9001,4326,5920,9802,1,0,4400,8821,65.06045752,9110,8822,177,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,
-5936,"WGS 84 / EPSG Alaska Polar Stereographic",9001,4326,5901,9810,1,0,4467,8801,90,9102,8802,-150,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
-5937,"WGS 84 / EPSG Canada Polar Stereographic",9001,4326,5902,9810,1,0,4466,8801,90,9102,8802,-100,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
-5938,"WGS 84 / EPSG Greenland Polar Stereographic",9001,4326,5903,9810,1,0,1036,8801,90,9102,8802,-33,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
-5939,"WGS 84 / EPSG Norway Polar Stereographic",9001,4326,5904,9810,1,0,1037,8801,90,9102,8802,18,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
-5940,"WGS 84 / EPSG Russia Polar Stereographic",9001,4326,5905,9810,1,0,1038,8801,90,9102,8802,105,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
-6050,"GR96 / EPSG Arctic zone 1-25",9001,4747,5979,9802,1,0,4400,8821,85.2613626,9110,8822,-30,9110,8823,87,9110,8824,83.4,9110,8826,25500000,9001,8827,1500000,9001,,,
-6051,"GR96 / EPSG Arctic zone 2-18",9001,4747,5987,9802,1,0,4400,8821,82.03303296,9110,8822,-52,9110,8823,83.4,9110,8824,80.2,9110,8826,18500000,9001,8827,2500000,9001,,,
-6052,"GR96 / EPSG Arctic zone 2-20",9001,4747,5988,9802,1,0,4400,8821,82.03303296,9110,8822,-12,9110,8823,83.4,9110,8824,80.2,9110,8826,20500000,9001,8827,2500000,9001,,,
-6053,"GR96 / EPSG Arctic zone 3-29",9001,4747,6002,9802,1,0,4400,8821,78.42264151,9110,8822,-69,9110,8823,80.2,9110,8824,77,9110,8826,29500000,9001,8827,3500000,9001,,,
-6054,"GR96 / EPSG Arctic zone 3-31",9001,4747,6003,9802,1,0,4400,8821,78.42264151,9110,8822,-39,9110,8823,80.2,9110,8824,77,9110,8826,31500000,9001,8827,3500000,9001,,,
-6055,"GR96 / EPSG Arctic zone 3-33",9001,4747,6004,9802,1,0,4400,8821,78.42264151,9110,8822,-10,9110,8823,80.2,9110,8824,77,9110,8826,33500000,9001,8827,3500000,9001,,,
-6056,"GR96 / EPSG Arctic zone 4-20",9001,4747,6009,9802,1,0,4400,8821,75.21518519,9110,8822,-64,9110,8823,77,9110,8824,73.4,9110,8826,20500000,9001,8827,4500000,9001,,,
-6057,"GR96 / EPSG Arctic zone 4-22",9001,4747,6010,9802,1,0,4400,8821,75.21518519,9110,8822,-39,9110,8823,77,9110,8824,73.4,9110,8826,22500000,9001,8827,4500000,9001,,,
-6058,"GR96 / EPSG Arctic zone 4-24",9001,4747,6011,9802,1,0,4400,8821,75.21518519,9110,8822,-14,9110,8823,77,9110,8824,73.4,9110,8826,24500000,9001,8827,4500000,9001,,,
-6059,"GR96 / EPSG Arctic zone 5-41",9001,4747,6035,9802,1,0,4400,8821,72.01300331,9110,8822,-62,9110,8823,73.4,9110,8824,70.2,9110,8826,41500000,9001,8827,5500000,9001,,,
-6060,"GR96 / EPSG Arctic zone 5-43",9001,4747,6036,9802,1,0,4400,8821,72.01300331,9110,8822,-42,9110,8823,73.4,9110,8824,70.2,9110,8826,43500000,9001,8827,5500000,9001,,,
-6061,"GR96 / EPSG Arctic zone 5-45",9001,4747,6037,9802,1,0,4400,8821,72.01300331,9110,8822,-22,9110,8823,73.4,9110,8824,70.2,9110,8826,45500000,9001,8827,5500000,9001,,,
-6062,"GR96 / EPSG Arctic zone 6-26",9001,4747,6045,9802,1,0,4400,8821,68.4114912,9110,8822,-56,9110,8823,70.2,9110,8824,67,9110,8826,26500000,9001,8827,6500000,9001,,,
-6063,"GR96 / EPSG Arctic zone 6-28",9001,4747,6046,9802,1,0,4400,8821,68.4114912,9110,8822,-38,9110,8823,70.2,9110,8824,67,9110,8826,28500000,9001,8827,6500000,9001,,,
-6064,"GR96 / EPSG Arctic zone 6-30",9001,4747,6047,9802,1,0,4400,8821,68.4114912,9110,8822,-20,9110,8823,70.2,9110,8824,67,9110,8826,30500000,9001,8827,6500000,9001,,,
-6065,"GR96 / EPSG Arctic zone 7-11",9001,4747,6048,9802,1,0,4400,8821,65.21037415,9110,8822,-51,9110,8823,67,9110,8824,63.4,9110,8826,11500000,9001,8827,7500000,9001,,,
-6066,"GR96 / EPSG Arctic zone 7-13",9001,4747,6049,9802,1,0,4400,8821,65.21037415,9110,8822,-34,9110,8823,67,9110,8824,63.4,9110,8826,13500000,9001,8827,7500000,9001,,,
-6067,"GR96 / EPSG Arctic zone 8-20",9001,4747,5943,9802,1,0,4400,8821,62.00551048,9110,8822,-52,9110,8823,63.4,9110,8824,60.2,9110,8826,20500000,9001,8827,8500000,9001,,,
-6068,"GR96 / EPSG Arctic zone 8-22",9001,4747,5944,9802,1,0,4400,8821,62.00551048,9110,8822,-37,9110,8823,63.4,9110,8824,60.2,9110,8826,22500000,9001,8827,8500000,9001,,,
-6069,"ETRS89 / EPSG Arctic zone 2-22",9001,4258,5989,9802,1,0,4400,8821,82.03303296,9110,8822,16,9110,8823,83.4,9110,8824,80.2,9110,8826,22500000,9001,8827,2500000,9001,,,
-6070,"ETRS89 / EPSG Arctic zone 3-11",9001,4258,5993,9802,1,0,4400,8821,78.42264151,9110,8822,21,9110,8823,80.2,9110,8824,77,9110,8826,11500000,9001,8827,3500000,9001,,,
-6071,"ETRS89 / EPSG Arctic zone 4-26",9001,4258,6012,9802,1,0,4400,8821,75.21518519,9110,8822,10,9110,8823,77,9110,8824,73.4,9110,8826,26500000,9001,8827,4500000,9001,,,
-6072,"ETRS89 / EPSG Arctic zone 4-28",9001,4258,6013,9802,1,0,4400,8821,75.21518519,9110,8822,34,9110,8823,77,9110,8824,73.4,9110,8826,28500000,9001,8827,4500000,9001,,,
-6073,"ETRS89 / EPSG Arctic zone 5-11",9001,4258,6020,9802,1,0,4400,8821,72.01300331,9110,8822,14,9110,8823,73.4,9110,8824,70.2,9110,8826,11500000,9001,8827,5500000,9001,,,
-6074,"ETRS89 / EPSG Arctic zone 5-13",9001,4258,6021,9802,1,0,4400,8821,72.01300331,9110,8822,34,9110,8823,73.4,9110,8824,70.2,9110,8826,13500000,9001,8827,5500000,9001,,,
-6075,"WGS 84 / EPSG Arctic zone 2-24",9001,4326,5990,9802,1,0,4400,8821,82.03303296,9110,8822,53,9110,8823,83.4,9110,8824,80.2,9110,8826,24500000,9001,8827,2500000,9001,,,
-6076,"WGS 84 / EPSG Arctic zone 2-26",9001,4326,5991,9802,1,0,4400,8821,82.03303296,9110,8822,93,9110,8823,83.4,9110,8824,80.2,9110,8826,26500000,9001,8827,2500000,9001,,,
-6077,"WGS 84 / EPSG Arctic zone 3-13",9001,4326,5994,9802,1,0,4400,8821,78.42264151,9110,8822,52,9110,8823,80.2,9110,8824,77,9110,8826,13500000,9001,8827,3500000,9001,,,
-6078,"WGS 84 / EPSG Arctic zone 3-15",9001,4326,5995,9802,1,0,4400,8821,78.42264151,9110,8822,83,9110,8823,80.2,9110,8824,77,9110,8826,15500000,9001,8827,3500000,9001,,,
-6079,"WGS 84 / EPSG Arctic zone 3-17",9001,4326,5996,9802,1,0,4400,8821,78.42264151,9110,8822,114,9110,8823,80.2,9110,8824,77,9110,8826,17500000,9001,8827,3500000,9001,,,
-6080,"WGS 84 / EPSG Arctic zone 3-19",9001,4326,5997,9802,1,0,4400,8821,78.42264151,9110,8822,145,9110,8823,80.2,9110,8824,77,9110,8826,19500000,9001,8827,3500000,9001,,,
-6081,"WGS 84 / EPSG Arctic zone 4-30",9001,4326,6014,9802,1,0,4400,8821,75.21518519,9110,8822,58,9110,8823,77,9110,8824,73.4,9110,8826,30500000,9001,8827,4500000,9001,,,
-6082,"WGS 84 / EPSG Arctic zone 4-32",9001,4326,6015,9802,1,0,4400,8821,75.21518519,9110,8822,82,9110,8823,77,9110,8824,73.4,9110,8826,32500000,9001,8827,4500000,9001,,,
-6083,"WGS 84 / EPSG Arctic zone 4-34",9001,4326,6016,9802,1,0,4400,8821,75.21518519,9110,8822,106,9110,8823,77,9110,8824,73.4,9110,8826,34500000,9001,8827,4500000,9001,,,
-6084,"WGS 84 / EPSG Arctic zone 4-36",9001,4326,6017,9802,1,0,4400,8821,75.21518519,9110,8822,130,9110,8823,77,9110,8824,73.4,9110,8826,36500000,9001,8827,4500000,9001,,,
-6085,"WGS 84 / EPSG Arctic zone 4-38",9001,4326,6018,9802,1,0,4400,8821,75.21518519,9110,8822,154,9110,8823,77,9110,8824,73.4,9110,8826,38500000,9001,8827,4500000,9001,,,
-6086,"WGS 84 / EPSG Arctic zone 4-40",9001,4326,6019,9802,1,0,4400,8821,75.21518519,9110,8822,179,9110,8823,77,9110,8824,73.4,9110,8826,40500000,9001,8827,4500000,9001,,,
-6087,"WGS 84 / EPSG Arctic zone 5-15",9001,4326,6022,9802,1,0,4400,8821,72.01300331,9110,8822,54,9110,8823,73.4,9110,8824,70.2,9110,8826,15500000,9001,8827,5500000,9001,,,
-6088,"WGS 84 / EPSG Arctic zone 5-17",9001,4326,6023,9802,1,0,4400,8821,72.01300331,9110,8822,74,9110,8823,73.4,9110,8824,70.2,9110,8826,17500000,9001,8827,5500000,9001,,,
-6089,"WGS 84 / EPSG Arctic zone 5-19",9001,4326,6024,9802,1,0,4400,8821,72.01300331,9110,8822,95,9110,8823,73.4,9110,8824,70.2,9110,8826,19500000,9001,8827,5500000,9001,,,
-6090,"WGS 84 / EPSG Arctic zone 5-21",9001,4326,6025,9802,1,0,4400,8821,72.01300331,9110,8822,116,9110,8823,73.4,9110,8824,70.2,9110,8826,21500000,9001,8827,5500000,9001,,,
-6091,"WGS 84 / EPSG Arctic zone 5-23",9001,4326,6026,9802,1,0,4400,8821,72.01300331,9110,8822,137,9110,8823,73.4,9110,8824,70.2,9110,8826,23500000,9001,8827,5500000,9001,,,
-6092,"WGS 84 / EPSG Arctic zone 5-25",9001,4326,6027,9802,1,0,4400,8821,72.01300331,9110,8822,158,9110,8823,73.4,9110,8824,70.2,9110,8826,25500000,9001,8827,5500000,9001,,,
-6093,"WGS 84 / EPSG Arctic zone 5-27",9001,4326,6028,9802,1,0,4400,8821,72.01300331,9110,8822,179,9110,8823,73.4,9110,8824,70.2,9110,8826,27500000,9001,8827,5500000,9001,,,
-6094,"NAD83(NSRS2007) / EPSG Arctic zone 5-29",9001,4759,6029,9802,1,0,4400,8821,72.01300331,9110,8822,-163,9110,8823,73.4,9110,8824,70.2,9110,8826,29500000,9001,8827,5500000,9001,,,
-6095,"NAD83(NSRS2007) / EPSG Arctic zone 5-31",9001,4759,6030,9802,1,0,4400,8821,72.01300331,9110,8822,-147,9110,8823,73.4,9110,8824,70.2,9110,8826,31500000,9001,8827,5500000,9001,,,
-6096,"NAD83(NSRS2007) / EPSG Arctic zone 6-14",9001,4759,6039,9802,1,0,4400,8821,68.4114912,9110,8822,-165,9110,8823,70.2,9110,8824,67,9110,8826,14500000,9001,8827,6500000,9001,,,
-6097,"NAD83(NSRS2007) / EPSG Arctic zone 6-16",9001,4759,6040,9802,1,0,4400,8821,68.4114912,9110,8822,-147,9110,8823,70.2,9110,8824,67,9110,8826,16500000,9001,8827,6500000,9001,,,
-6098,"NAD83(CSRS) / EPSG Arctic zone 1-23",9001,4617,5978,9802,1,0,4400,8821,85.2613626,9110,8822,-90,9110,8823,87,9110,8824,83.4,9110,8826,23500000,9001,8827,1500000,9001,,,
-6099,"NAD83(CSRS) / EPSG Arctic zone 2-14",9001,4617,5985,9802,1,0,4400,8821,82.03303296,9110,8822,-115,9110,8823,83.4,9110,8824,80.2,9110,8826,14500000,9001,8827,2500000,9001,,,
-6100,"NAD83(CSRS) / EPSG Arctic zone 2-16",9001,4617,5986,9802,1,0,4400,8821,82.03303296,9110,8822,-75,9110,8823,83.4,9110,8824,80.2,9110,8826,16500000,9001,8827,2500000,9001,,,
-6101,"NAD83(CSRS) / EPSG Arctic zone 3-25",9001,4617,6000,9802,1,0,4400,8821,78.42264151,9110,8822,-129,9110,8823,80.2,9110,8824,77,9110,8826,25500000,9001,8827,3500000,9001,,,
-6102,"NAD83(CSRS) / EPSG Arctic zone 3-27",9001,4617,6001,9802,1,0,4400,8821,78.42264151,9110,8822,-99,9110,8823,80.2,9110,8824,77,9110,8826,27500000,9001,8827,3500000,9001,,,
-6103,"NAD83(CSRS) / EPSG Arctic zone 3-29",9001,4617,6002,9802,1,0,4400,8821,78.42264151,9110,8822,-69,9110,8823,80.2,9110,8824,77,9110,8826,29500000,9001,8827,3500000,9001,,,
-6104,"NAD83(CSRS) / EPSG Arctic zone 4-14",9001,4617,6006,9802,1,0,4400,8821,75.21518519,9110,8822,-129,9110,8823,77,9110,8824,73.4,9110,8826,14500000,9001,8827,4500000,9001,,,
-6105,"NAD83(CSRS) / EPSG Arctic zone 4-16",9001,4617,6007,9802,1,0,4400,8821,75.21518519,9110,8822,-104,9110,8823,77,9110,8824,73.4,9110,8826,16500000,9001,8827,4500000,9001,,,
-6106,"NAD83(CSRS) / EPSG Arctic zone 4-18",9001,4617,6008,9802,1,0,4400,8821,75.21518519,9110,8822,-79,9110,8823,77,9110,8824,73.4,9110,8826,18500000,9001,8827,4500000,9001,,,
-6107,"NAD83(CSRS) / EPSG Arctic zone 5-33",9001,4617,6031,9802,1,0,4400,8821,72.01300331,9110,8822,-131,9110,8823,73.4,9110,8824,70.2,9110,8826,33500000,9001,8827,5500000,9001,,,
-6108,"NAD83(CSRS) / EPSG Arctic zone 5-35",9001,4617,6032,9802,1,0,4400,8821,72.01300331,9110,8822,-111,9110,8823,73.4,9110,8824,70.2,9110,8826,35500000,9001,8827,5500000,9001,,,
-6109,"NAD83(CSRS) / EPSG Arctic zone 5-37",9001,4617,6033,9802,1,0,4400,8821,72.01300331,9110,8822,-91,9110,8823,73.4,9110,8824,70.2,9110,8826,37500000,9001,8827,5500000,9001,,,
-6110,"NAD83(CSRS) / EPSG Arctic zone 5-39",9001,4617,6034,9802,1,0,4400,8821,72.01300331,9110,8822,-71,9110,8823,73.4,9110,8824,70.2,9110,8826,39500000,9001,8827,5500000,9001,,,
-6111,"NAD83(CSRS) / EPSG Arctic zone 6-18",9001,4617,6041,9802,1,0,4400,8821,68.4114912,9110,8822,-132,9110,8823,70.2,9110,8824,67,9110,8826,18500000,9001,8827,6500000,9001,,,
-6112,"NAD83(CSRS) / EPSG Arctic zone 6-20",9001,4617,6042,9802,1,0,4400,8821,68.4114912,9110,8822,-113,9110,8823,70.2,9110,8824,67,9110,8826,20500000,9001,8827,6500000,9001,,,
-6113,"NAD83(CSRS) / EPSG Arctic zone 6-22",9001,4617,6043,9802,1,0,4400,8821,68.4114912,9110,8822,-94,9110,8823,70.2,9110,8824,67,9110,8826,22500000,9001,8827,6500000,9001,,,
-6114,"NAD83(CSRS) / EPSG Arctic zone 6-24",9001,4617,6044,9802,1,0,4400,8821,68.4114912,9110,8822,-75,9110,8823,70.2,9110,8824,67,9110,8826,24500000,9001,8827,6500000,9001,,,
-6115,"WGS 84 / EPSG Arctic zone 1-27",9001,4326,5980,9802,1,0,4400,8821,85.2613626,9110,8822,30,9110,8823,87,9110,8824,83.4,9110,8826,27500000,9001,8827,1500000,9001,,,
-6116,"WGS 84 / EPSG Arctic zone 1-29",9001,4326,5981,9802,1,0,4400,8821,85.2613626,9110,8822,90,9110,8823,87,9110,8824,83.4,9110,8826,29500000,9001,8827,1500000,9001,,,
-6117,"WGS 84 / EPSG Arctic zone 1-31",9001,4326,5982,9802,1,0,4400,8821,85.2613626,9110,8822,150,9110,8823,87,9110,8824,83.4,9110,8826,31500000,9001,8827,1500000,9001,,,
-6118,"WGS 84 / EPSG Arctic zone 1-21",9001,4326,5977,9802,1,0,4400,8821,85.2613626,9110,8822,-150,9110,8823,87,9110,8824,83.4,9110,8826,21500000,9001,8827,1500000,9001,,,
-6119,"WGS 84 / EPSG Arctic zone 2-28",9001,4326,5992,9802,1,0,4400,8821,82.03303296,9110,8822,133,9110,8823,83.4,9110,8824,80.2,9110,8826,28500000,9001,8827,2500000,9001,,,
-6120,"WGS 84 / EPSG Arctic zone 2-10",9001,4326,5983,9802,1,0,4400,8821,82.03303296,9110,8822,166,9110,8823,83.4,9110,8824,80.2,9110,8826,10500000,9001,8827,2500000,9001,,,
-6121,"WGS 84 / EPSG Arctic zone 2-12",9001,4326,5984,9802,1,0,4400,8821,82.03303296,9110,8822,-154,9110,8823,83.4,9110,8824,80.2,9110,8826,12500000,9001,8827,2500000,9001,,,
-6122,"WGS 84 / EPSG Arctic zone 3-21",9001,4326,5998,9802,1,0,4400,8821,78.42264151,9110,8822,176,9110,8823,80.2,9110,8824,77,9110,8826,21500000,9001,8827,3500000,9001,,,
-6123,"WGS 84 / EPSG Arctic zone 3-23",9001,4326,5999,9802,1,0,4400,8821,78.42264151,9110,8822,-153,9110,8823,80.2,9110,8824,77,9110,8826,23500000,9001,8827,3500000,9001,,,
-6124,"WGS 84 / EPSG Arctic zone 4-12",9001,4326,6005,9802,1,0,4400,8821,75.21518519,9110,8822,-155,9110,8823,77,9110,8824,73.4,9110,8826,12500000,9001,8827,4500000,9001,,,
-6125,"ETRS89 / EPSG Arctic zone 5-47",9001,4258,6038,9802,1,0,4400,8821,72.01300331,9110,8822,-5,9110,8823,73.4,9110,8824,70.2,9110,8826,47500000,9001,8827,5500000,9001,,,
-6128,Grand Cayman National Grid 1959,9002,4723,6127,9807,1,0,1039,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640419.9475,9002,8807,0,9002,,,,,,
-6129,Sister Islands National Grid 1961,9002,4726,6127,9807,1,0,1039,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640419.9475,9002,8807,0,9002,,,,,,
-6141,Cayman Islands National Grid 2011,9002,6135,6126,9802,1,1,1039,8821,19.2,9110,8822,80.34,9110,8823,19.2,9110,8824,19.42,9110,8826,2950000,9002,8827,1900000,9002,,,
-6200,"NAD27 / Michigan North",9003,4267,6197,1051,1,1,4497,1038,1.0000382,9201,8821,44.87,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003
-6201,"NAD27 / Michigan Central",9003,4267,6198,1051,1,0,4497,1038,1.0000382,9201,8821,43.19,9110,8822,-84.2,9110,8823,44.11,9110,8824,45.42,9110,8826,2000000,9003,8827,0,9003
-6202,"NAD27 / Michigan South",9003,4267,6199,1051,1,0,4497,1038,1.0000382,9201,8821,41.3,9110,8822,-84.2,9110,8823,42.06,9110,8824,43.4,9110,8826,2000000,9003,8827,0,9003
-6204,Macedonia State Coordinate System,9001,3906,6203,9807,1,0,4498,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6210,"SIRGAS 2000 / UTM zone 23N",9001,4674,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6211,"SIRGAS 2000 / UTM zone 24N",9001,4674,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6244,"MAGNA-SIRGAS / Arauca urban grid",9001,4686,6212,1052,1,0,4500,1039,100,9001,8801,7.051538301,9110,8802,-70.452991476,9110,8806,1035263.443,9001,8807,1275526.621,9001,,,,,,
-6245,"MAGNA-SIRGAS / Armenia urban grid",9001,4686,6213,1052,1,0,4500,1039,1470,9001,8801,4.315637,9110,8802,-75.4024561,9110,8806,1155824.666,9001,8807,993087.465,9001,,,,,,
-6246,"MAGNA-SIRGAS / Barranquilla urban grid",9001,4686,6214,1052,1,0,4500,1039,100,9001,8801,10.55234591,9110,8802,-74.50035928,9110,8806,917264.406,9001,8807,1699839.935,9001,,,,,,
-6247,"MAGNA-SIRGAS / Bogota urban grid",9001,4686,6215,1052,1,0,4500,1039,2550,9001,8801,4.404975,9110,8802,-74.084773,9110,8806,92334.879,9001,8807,109320.965,9001,,,,,,
-6248,"MAGNA-SIRGAS / Bucaramanga urban grid",9001,4686,6216,1052,1,0,4500,1039,931,9001,8801,7.044399371,9110,8802,-73.11504356,9110,8806,1097241.305,9001,8807,1274642.278,9001,,,,,,
-6249,"MAGNA-SIRGAS / Cali urban grid",9001,4686,6217,1052,1,0,4500,1039,1000,9001,8801,3.263078,9110,8802,-76.3114025,9110,8806,1061900.18,9001,8807,872364.63,9001,,,,,,
-6250,"MAGNA-SIRGAS / Cartagena urban grid",9001,4686,6218,1052,1,0,4500,1039,0,9001,8801,10.2349371,9110,8802,-75.3040345,9110,8806,842981.41,9001,8807,1641887.09,9001,,,,,,
-6251,"MAGNA-SIRGAS / Cucuta urban grid",9001,4686,6219,1052,1,0,4500,1039,308,9001,8801,7.532017225,9110,8802,-72.301033542,9110,8806,842805.406,9001,8807,1364404.57,9001,,,,,,
-6252,"MAGNA-SIRGAS / Florencia urban grid",9001,4686,6220,1052,1,0,4500,1039,300,9001,8801,1.371564426,9110,8802,-75.370882337,9110,8806,1162300.348,9001,8807,671068.716,9001,,,,,,
-6253,"MAGNA-SIRGAS / Ibague urban grid",9001,4686,6221,1052,1,0,4500,1039,1100,9001,8801,4.250988618,9110,8802,-75.104773336,9110,8806,877634.33,9001,8807,980541.348,9001,,,,,,
-6254,"MAGNA-SIRGAS / Inirida urban grid",9001,4686,6222,1052,1,0,4500,1039,96,9001,8801,3.504357746,9110,8802,-67.541883552,9110,8806,1019177.687,9001,8807,491791.326,9001,,,,,,
-6255,"MAGNA-SIRGAS / Leticia urban grid",9001,4686,6223,1052,1,0,4500,1039,89.7,9001,8801,-4.115166257,9110,8802,-69.563411981,9110,8806,25978.217,9001,8807,27501.365,9001,,,,,,
-6256,"MAGNA-SIRGAS / Manizales urban grid",9001,4686,6224,1052,1,0,4500,1039,2100,9001,8801,5.0405354,9110,8802,-75.3039941,9110,8806,1173727.04,9001,8807,1052391.13,9001,,,,,,
-6257,"MAGNA-SIRGAS / Medellin urban grid",9001,4686,6225,1052,1,0,4500,1039,1510,9001,8801,6.1345152,9110,8802,-75.3353593,9110,8806,835378.647,9001,8807,1180816.875,9001,,,,,,
-6258,"MAGNA-SIRGAS / Mitu urban grid",9001,4686,6226,1052,1,0,4500,1039,170,9001,8801,1.145988972,9110,8802,-70.140766196,9110,8806,1093717.398,9001,8807,629997.236,9001,,,,,,
-6259,"MAGNA-SIRGAS / Mocoa urban grid",9001,4686,6227,1052,1,0,4500,1039,655.2,9001,8801,1.082408409,9110,8802,-76.390367639,9110,8806,1047467.388,9001,8807,617828.474,9001,,,,,,
-6260,"MAGNA-SIRGAS / Monteria urban grid",9001,4686,6228,1052,1,0,4500,1039,15,9001,8801,8.462310872,9110,8802,-75.524639199,9110,8806,1131814.934,9001,8807,1462131.119,9001,,,,,,
-6261,"MAGNA-SIRGAS / Neiva urban grid",9001,4686,6229,1052,1,0,4500,1039,430,9001,8801,2.56326942,9110,8802,-75.17471722,9110,8806,864476.923,9001,8807,817199.827,9001,,,,,,
-6262,"MAGNA-SIRGAS / Pasto urban grid",9001,4686,6230,1052,1,0,4500,1039,2530,9001,8801,1.120356225,9110,8802,-77.151125228,9110,8806,980469.695,9001,8807,624555.332,9001,,,,,,
-6263,"MAGNA-SIRGAS / Pereira urban grid",9001,4686,6231,1052,1,0,4500,1039,1500,9001,8801,4.4848937,9110,8802,-75.4138225,9110,8806,1153492.012,9001,8807,1024195.255,9001,,,,,,
-6264,"MAGNA-SIRGAS / Popayan urban grid",9001,4686,6232,1052,1,0,4500,1039,1740,9001,8801,2.272217558,9110,8802,-76.362192989,9110,8806,1052430.525,9001,8807,763366.548,9001,,,,,,
-6265,"MAGNA-SIRGAS / Puerto Carreno urban grid",9001,4686,6233,1052,1,0,4500,1039,51.58,9001,8801,6.105059709,9110,8802,-67.300270089,9110,8806,1063834.703,9001,8807,1175257.481,9001,,,,,,
-6266,"MAGNA-SIRGAS / Quibdo urban grid",9001,4686,6234,1052,1,0,4500,1039,44,9001,8801,5.413929158,9110,8802,-76.390271389,9110,8806,1047273.617,9001,8807,1121443.09,9001,,,,,,
-6267,"MAGNA-SIRGAS / Riohacha urban grid",9001,4686,6235,1052,1,0,4500,1039,6,9001,8801,11.321288798,9110,8802,-72.540996793,9110,8806,1128154.73,9001,8807,1767887.914,9001,,,,,,
-6268,"MAGNA-SIRGAS / San Andres urban grid",9001,4686,6236,1052,1,0,4500,1039,6,9001,8801,12.312565957,9110,8802,-81.434575342,9110,8806,820439.298,9001,8807,1877357.828,9001,,,,,,
-6269,"MAGNA-SIRGAS / San Jose del Guaviare urban grid",9001,4686,6237,1052,1,0,4500,1039,185,9001,8801,2.335068419,9110,8802,-72.382411997,9110,8806,1159876.62,9001,8807,775380.342,9001,,,,,,
-6270,"MAGNA-SIRGAS / Santa Marta urban grid",9001,4686,6238,1052,1,0,4500,1039,29,9001,8801,11.1310715,9110,8802,-74.1330019,9110,8806,983892.409,9001,8807,1732533.518,9001,,,,,,
-6271,"MAGNA-SIRGAS / Sucre urban grid",9001,4686,6239,1052,1,0,4500,1039,20,9001,8801,8.483798132,9110,8802,-74.432088057,9110,8806,929043.607,9001,8807,1466125.658,9001,,,,,,
-6272,"MAGNA-SIRGAS / Tunja urban grid",9001,4686,6240,1052,1,0,4500,1039,2800,9001,8801,5.320310106,9110,8802,-73.210698004,9110,8806,1080514.91,9001,8807,1103772.028,9001,,,,,,
-6273,"MAGNA-SIRGAS / Valledupar urban grid",9001,4686,6241,1052,1,0,4500,1039,200,9001,8801,10.265014,9110,8802,-73.1447657,9110,8806,1090979.66,9001,8807,1647208.93,9001,,,,,,
-6274,"MAGNA-SIRGAS / Villavicencio urban grid",9001,4686,6242,1052,1,0,4500,1039,427.19,9001,8801,4.091935036,9110,8802,-73.372814955,9110,8806,1050678.757,9001,8807,950952.124,9001,,,,,,
-6275,"MAGNA-SIRGAS / Yopal urban grid",9001,4686,6243,1052,1,0,4500,1039,300,9001,8801,5.2114138,9110,8802,-72.2512145,9110,8806,851184.177,9001,8807,1083954.137,9001,,,,,,
-6307,"NAD83(CORS96) / Puerto Rico and Virgin Is.",9001,6783,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,
-6312,"CGRS93 / Cyprus Local Transverse Mercator",9001,6311,6308,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.99995,9201,8806,200000,9001,8807,-3500000,9001,,,,,,
-6316,Macedonia State Coordinate System zone 7,9001,3906,18277,9807,1,0,4498,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,
-6328,"NAD83(2011) / UTM zone 59N",9001,6318,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6329,"NAD83(2011) / UTM zone 60N",9001,6318,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6330,"NAD83(2011) / UTM zone 1N",9001,6318,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6331,"NAD83(2011) / UTM zone 2N",9001,6318,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6332,"NAD83(2011) / UTM zone 3N",9001,6318,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6333,"NAD83(2011) / UTM zone 4N",9001,6318,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6334,"NAD83(2011) / UTM zone 5N",9001,6318,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6335,"NAD83(2011) / UTM zone 6N",9001,6318,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6336,"NAD83(2011) / UTM zone 7N",9001,6318,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6337,"NAD83(2011) / UTM zone 8N",9001,6318,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6338,"NAD83(2011) / UTM zone 9N",9001,6318,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6339,"NAD83(2011) / UTM zone 10N",9001,6318,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6340,"NAD83(2011) / UTM zone 11N",9001,6318,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6341,"NAD83(2011) / UTM zone 12N",9001,6318,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6342,"NAD83(2011) / UTM zone 13N",9001,6318,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6343,"NAD83(2011) / UTM zone 14N",9001,6318,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6344,"NAD83(2011) / UTM zone 15N",9001,6318,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6345,"NAD83(2011) / UTM zone 16N",9001,6318,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6346,"NAD83(2011) / UTM zone 17N",9001,6318,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6347,"NAD83(2011) / UTM zone 18N",9001,6318,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6348,"NAD83(2011) / UTM zone 19N",9001,6318,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6350,"NAD83(2011) / Conus Albers",9001,6318,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,
-6351,"NAD83(2011) / EPSG Arctic zone 5-29",9001,6318,6029,9802,1,0,4400,8821,72.01300331,9110,8822,-163,9110,8823,73.4,9110,8824,70.2,9110,8826,29500000,9001,8827,5500000,9001,,,
-6352,"NAD83(2011) / EPSG Arctic zone 5-31",9001,6318,6030,9802,1,0,4400,8821,72.01300331,9110,8822,-147,9110,8823,73.4,9110,8824,70.2,9110,8826,31500000,9001,8827,5500000,9001,,,
-6353,"NAD83(2011) / EPSG Arctic zone 6-14",9001,6318,6039,9802,1,0,4400,8821,68.4114912,9110,8822,-165,9110,8823,70.2,9110,8824,67,9110,8826,14500000,9001,8827,6500000,9001,,,
-6354,"NAD83(2011) / EPSG Arctic zone 6-16",9001,6318,6040,9802,1,0,4400,8821,68.4114912,9110,8822,-147,9110,8823,70.2,9110,8824,67,9110,8826,16500000,9001,8827,6500000,9001,,,
-6355,"NAD83(2011) / Alabama East",9001,6318,10131,9807,1,0,4499,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,
-6356,"NAD83(2011) / Alabama West",9001,6318,10132,9807,1,0,4499,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,600000,9001,8807,0,9001,,,,,,
-6362,"Mexico ITRF92 / LCC",9001,4483,6361,9802,1,0,4500,8821,12,9102,8822,-102,9102,8823,17.5,9102,8824,29.5,9102,8826,2500000,9001,8827,0,9001,,,
-6366,"Mexico ITRF2008 / UTM zone 11N",9001,6365,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6367,"Mexico ITRF2008 / UTM zone 12N",9001,6365,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6368,"Mexico ITRF2008 / UTM zone 13N",9001,6365,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6369,"Mexico ITRF2008 / UTM zone 14N",9001,6365,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6370,"Mexico ITRF2008 / UTM zone 15N",9001,6365,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6371,"Mexico ITRF2008 / UTM zone 16N",9001,6365,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6372,"Mexico ITRF2008 / LCC",9001,6365,6361,9802,1,0,4500,8821,12,9102,8822,-102,9102,8823,17.5,9102,8824,29.5,9102,8826,2500000,9001,8827,0,9001,,,
-6381,"UCS-2000 / Ukraine TM zone 7",9001,5561,6374,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,
-6382,"UCS-2000 / Ukraine TM zone 8",9001,5561,6375,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,
-6383,"UCS-2000 / Ukraine TM zone 9",9001,5561,6376,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,
-6384,"UCS-2000 / Ukraine TM zone 10",9001,5561,6377,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,
-6385,"UCS-2000 / Ukraine TM zone 11",9001,5561,6378,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,
-6386,"UCS-2000 / Ukraine TM zone 12",9001,5561,6379,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,
-6387,"UCS-2000 / Ukraine TM zone 13",9001,5561,6380,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,
-6391,Cayman Islands National Grid 2011,9002,6135,6390,9802,1,0,1039,8821,19.2,9110,8822,-80.34,9110,8823,19.2,9110,8824,19.42,9110,8826,2950000,9002,8827,1900000,9002,,,
-6393,"NAD83(2011) / Alaska Albers",9001,6318,15021,9822,1,0,4499,8821,50,9102,8822,-154,9102,8823,55,9102,8824,65,9102,8826,0,9001,8827,0,9001,,,
-6394,"NAD83(2011) / Alaska zone 1",9001,6318,15031,9812,1,0,4499,8806,5000000,9001,8807,-5000000,9001,8811,57,9110,8812,-133.4,9110,8813,323.07483685,9110,8814,323.07483685,9110,8815,0.9999,9201
-6395,"NAD83(2011) / Alaska zone 2",9001,6318,15032,9807,1,0,4499,8801,54,9102,8802,-142,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6396,"NAD83(2011) / Alaska zone 3",9001,6318,15033,9807,1,0,4499,8801,54,9102,8802,-146,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6397,"NAD83(2011) / Alaska zone 4",9001,6318,15034,9807,1,0,4499,8801,54,9102,8802,-150,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6398,"NAD83(2011) / Alaska zone 5",9001,6318,15035,9807,1,0,4499,8801,54,9102,8802,-154,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6399,"NAD83(2011) / Alaska zone 6",9001,6318,15036,9807,1,0,4499,8801,54,9102,8802,-158,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6400,"NAD83(2011) / Alaska zone 7",9001,6318,15037,9807,1,0,4499,8801,54,9102,8802,-162,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6401,"NAD83(2011) / Alaska zone 8",9001,6318,15038,9807,1,0,4499,8801,54,9102,8802,-166,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6402,"NAD83(2011) / Alaska zone 9",9001,6318,15039,9807,1,0,4499,8801,54,9102,8802,-170,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6403,"NAD83(2011) / Alaska zone 10",9001,6318,15040,9802,1,0,4499,8821,51,9110,8822,-176,9110,8823,53.5,9110,8824,51.5,9110,8826,1000000,9001,8827,0,9001,,,
-6404,"NAD83(2011) / Arizona Central",9001,6318,10232,9807,1,0,4499,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,
-6405,"NAD83(2011) / Arizona Central (ft)",9002,6318,15305,9807,1,0,4495,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,
-6406,"NAD83(2011) / Arizona East",9001,6318,10231,9807,1,0,4499,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,
-6407,"NAD83(2011) / Arizona East (ft)",9002,6318,15304,9807,1,0,4495,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,
-6408,"NAD83(2011) / Arizona West",9001,6318,10233,9807,1,0,4499,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,213360,9001,8807,0,9001,,,,,,
-6409,"NAD83(2011) / Arizona West (ft)",9002,6318,15306,9807,1,0,4495,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,700000,9002,8807,0,9002,,,,,,
-6410,"NAD83(2011) / Arkansas North",9001,6318,10331,9802,1,0,4499,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,400000,9001,8827,0,9001,,,
-6411,"NAD83(2011) / Arkansas North (ftUS)",9003,6318,15385,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,1312333.3333,9003,8827,0,9003,,,
-6412,"NAD83(2011) / Arkansas South",9001,6318,10332,9802,1,0,4499,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,400000,9001,8827,400000,9001,,,
-6413,"NAD83(2011) / Arkansas South (ftUS)",9003,6318,15386,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,
-6414,"NAD83(2011) / California Albers",9001,6318,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,
-6415,"NAD83(2011) / California zone 1",9001,6318,10431,9802,1,0,4499,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9001,8827,500000,9001,,,
-6416,"NAD83(2011) / California zone 1 (ftUS)",9003,6318,15307,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-6417,"NAD83(2011) / California zone 2",9001,6318,10432,9802,1,0,4499,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9001,8827,500000,9001,,,
-6418,"NAD83(2011) / California zone 2 (ftUS)",9003,6318,15308,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-6419,"NAD83(2011) / California zone 3",9001,6318,10433,9802,1,0,4499,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9001,8827,500000,9001,,,
-6420,"NAD83(2011) / California zone 3 (ftUS)",9003,6318,15309,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-6421,"NAD83(2011) / California zone 4",9001,6318,10434,9802,1,0,4499,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9001,8827,500000,9001,,,
-6422,"NAD83(2011) / California zone 4 (ftUS)",9003,6318,15310,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-6423,"NAD83(2011) / California zone 5",9001,6318,10435,9802,1,0,4499,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9001,8827,500000,9001,,,
-6424,"NAD83(2011) / California zone 5 (ftUS)",9003,6318,15311,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-6425,"NAD83(2011) / California zone 6",9001,6318,10436,9802,1,0,4499,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9001,8827,500000,9001,,,
-6426,"NAD83(2011) / California zone 6 (ftUS)",9003,6318,15312,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,
-6427,"NAD83(2011) / Colorado Central",9001,6318,10532,9802,1,0,4499,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-6428,"NAD83(2011) / Colorado Central (ftUS)",9003,6318,15314,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,3000000,9003,8827,1000000,9003,,,
-6429,"NAD83(2011) / Colorado North",9001,6318,10531,9802,1,0,4499,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-6430,"NAD83(2011) / Colorado North (ftUS)",9003,6318,15313,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,3000000,9003,8827,1000000,9003,,,
-6431,"NAD83(2011) / Colorado South",9001,6318,10533,9802,1,0,4499,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-6432,"NAD83(2011) / Colorado South (ftUS)",9003,6318,15315,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,3000000,9003,8827,1000000,9003,,,
-6433,"NAD83(2011) / Connecticut",9001,6318,10630,9802,1,0,4499,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,304800.6096,9001,8827,152400.3048,9001,,,
-6434,"NAD83(2011) / Connecticut (ftUS)",9003,6318,15316,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,1000000,9003,8827,500000,9003,,,
-6435,"NAD83(2011) / Delaware",9001,6318,10730,9807,1,0,4499,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,200000,9001,8807,0,9001,,,,,,
-6436,"NAD83(2011) / Delaware (ftUS)",9003,6318,15317,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-6437,"NAD83(2011) / Florida East",9001,6318,10931,9807,1,0,4499,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,
-6438,"NAD83(2011) / Florida East (ftUS)",9003,6318,15318,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-6439,"NAD83(2011) / Florida GDL Albers",9001,6318,10934,9822,1,0,4499,8821,24,9110,8822,-84,9110,8823,24,9110,8824,31.3,9110,8826,400000,9001,8827,0,9001,,,
-6440,"NAD83(2011) / Florida North",9001,6318,10933,9802,1,0,4499,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,600000,9001,8827,0,9001,,,
-6441,"NAD83(2011) / Florida North (ftUS)",9003,6318,15320,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,1968500,9003,8827,0,9003,,,
-6442,"NAD83(2011) / Florida West",9001,6318,10932,9807,1,0,4499,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,
-6443,"NAD83(2011) / Florida West (ftUS)",9003,6318,15319,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-6444,"NAD83(2011) / Georgia East",9001,6318,11031,9807,1,0,4499,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-6445,"NAD83(2011) / Georgia East (ftUS)",9003,6318,15321,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-6446,"NAD83(2011) / Georgia West",9001,6318,11032,9807,1,0,4499,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,700000,9001,8807,0,9001,,,,,,
-6447,"NAD83(2011) / Georgia West (ftUS)",9003,6318,15322,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,2296583.333,9003,8807,0,9003,,,,,,
-6448,"NAD83(2011) / Idaho Central",9001,6318,11132,9807,1,0,4499,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9001,8807,0,9001,,,,,,
-6449,"NAD83(2011) / Idaho Central (ftUS)",9003,6318,15324,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,1640416.667,9003,8807,0,9003,,,,,,
-6450,"NAD83(2011) / Idaho East",9001,6318,11131,9807,1,0,4499,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,200000,9001,8807,0,9001,,,,,,
-6451,"NAD83(2011) / Idaho East (ftUS)",9003,6318,15323,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,656166.667,9003,8807,0,9003,,,,,,
-6452,"NAD83(2011) / Idaho West",9001,6318,11133,9807,1,0,4499,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,800000,9001,8807,0,9001,,,,,,
-6453,"NAD83(2011) / Idaho West (ftUS)",9003,6318,15325,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,2624666.667,9003,8807,0,9003,,,,,,
-6454,"NAD83(2011) / Illinois East",9001,6318,11231,9807,1,0,4499,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,300000,9001,8807,0,9001,,,,,,
-6455,"NAD83(2011) / Illinois East (ftUS)",9003,6318,15387,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,984250,9003,8807,0,9003,,,,,,
-6456,"NAD83(2011) / Illinois West",9001,6318,11232,9807,1,0,4499,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,700000,9001,8807,0,9001,,,,,,
-6457,"NAD83(2011) / Illinois West (ftUS)",9003,6318,15388,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,2296583.3333,9003,8807,0,9003,,,,,,
-6458,"NAD83(2011) / Indiana East",9001,6318,11331,9807,1,0,4499,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,100000,9001,8807,250000,9001,,,,,,
-6459,"NAD83(2011) / Indiana East (ftUS)",9003,6318,15372,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,820208.333,9003,,,,,,
-6460,"NAD83(2011) / Indiana West",9001,6318,11332,9807,1,0,4499,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,900000,9001,8807,250000,9001,,,,,,
-6461,"NAD83(2011) / Indiana West (ftUS)",9003,6318,15373,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,820208.333,9003,,,,,,
-6462,"NAD83(2011) / Iowa North",9001,6318,11431,9802,1,0,4499,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,1500000,9001,8827,1000000,9001,,,
-6463,"NAD83(2011) / Iowa North (ftUS)",9003,6318,15377,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,4921250,9003,8827,3280833.3333,9003,,,
-6464,"NAD83(2011) / Iowa South",9001,6318,11432,9802,1,0,4499,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,500000,9001,8827,0,9001,,,
-6465,"NAD83(2011) / Iowa South (ftUS)",9003,6318,15378,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,1640416.6667,9003,8827,0,9003,,,
-6466,"NAD83(2011) / Kansas North",9001,6318,11531,9802,1,0,4499,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,400000,9001,8827,0,9001,,,
-6467,"NAD83(2011) / Kansas North (ftUS)",9003,6318,15379,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,1312333.3333,9003,8827,0,9003,,,
-6468,"NAD83(2011) / Kansas South",9001,6318,11532,9802,1,0,4499,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,400000,9001,8827,400000,9001,,,
-6469,"NAD83(2011) / Kansas South (ftUS)",9003,6318,15380,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,
-6470,"NAD83(2011) / Kentucky North",9001,6318,15303,9802,1,0,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,500000,9001,8827,0,9001,,,
-6471,"NAD83(2011) / Kentucky North (ftUS)",9003,6318,15328,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,1640416.667,9003,8827,0,9003,,,
-6472,"NAD83(2011) / Kentucky Single Zone",9001,6318,11630,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,1500000,9001,8827,1000000,9001,,,
-6473,"NAD83(2011) / Kentucky Single Zone (ftUS)",9003,6318,15375,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,4921250,9003,8827,3280833.333,9003,,,
-6474,"NAD83(2011) / Kentucky South",9001,6318,11632,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,500000,9001,8827,500000,9001,,,
-6475,"NAD83(2011) / Kentucky South (ftUS)",9003,6318,15329,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,1640416.667,9003,8827,1640416.667,9003,,,
-6476,"NAD83(2011) / Louisiana North",9001,6318,11731,9802,1,0,4499,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,1000000,9001,8827,0,9001,,,
-6477,"NAD83(2011) / Louisiana North (ftUS)",9003,6318,15391,9802,1,0,4497,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,3280833.3333,9003,8827,0,9003,,,
-6478,"NAD83(2011) / Louisiana South",9001,6318,11732,9802,1,0,4499,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,1000000,9001,8827,0,9001,,,
-6479,"NAD83(2011) / Louisiana South (ftUS)",9003,6318,15392,9802,1,0,4497,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,3280833.3333,9003,8827,0,9003,,,
-6480,"NAD83(2011) / Maine CS2000 Central",9001,6318,11854,9807,1,0,4499,8801,43.3,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,
-6481,"NAD83(2011) / Maine CS2000 East",9001,6318,11851,9807,1,0,4499,8801,43.5,9110,8802,-67.523,9110,8805,0.99998,9201,8806,700000,9001,8807,0,9001,,,,,,
-6482,"NAD83(2011) / Maine CS2000 West",9001,6318,11853,9807,1,0,4499,8801,42.5,9110,8802,-70.223,9110,8805,0.99998,9201,8806,300000,9001,8807,0,9001,,,,,,
-6483,"NAD83(2011) / Maine East",9001,6318,11831,9807,1,0,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,300000,9001,8807,0,9001,,,,,,
-6484,"NAD83(2011) / Maine East (ftUS)",9003,6318,11833,9807,1,0,4497,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,
-6485,"NAD83(2011) / Maine West",9001,6318,11832,9807,1,0,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,900000,9001,8807,0,9001,,,,,,
-6486,"NAD83(2011) / Maine West (ftUS)",9003,6318,11834,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,
-6487,"NAD83(2011) / Maryland",9001,6318,11930,9802,1,0,4499,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,400000,9001,8827,0,9001,,,
-6488,"NAD83(2011) / Maryland (ftUS)",9003,6318,15330,9802,1,0,4497,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,1312333.333,9003,8827,0,9003,,,
-6489,"NAD83(2011) / Massachusetts Island",9001,6318,12032,9802,1,0,4499,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,500000,9001,8827,0,9001,,,
-6490,"NAD83(2011) / Massachusetts Island (ftUS)",9003,6318,15332,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,1640416.667,9003,8827,0,9003,,,
-6491,"NAD83(2011) / Massachusetts Mainland",9001,6318,12031,9802,1,0,4499,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,200000,9001,8827,750000,9001,,,
-6492,"NAD83(2011) / Massachusetts Mainland (ftUS)",9003,6318,15331,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,656166.667,9003,8827,2460625,9003,,,
-6493,"NAD83(2011) / Michigan Central",9001,6318,12142,9802,1,0,4499,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,6000000,9001,8827,0,9001,,,
-6494,"NAD83(2011) / Michigan Central (ft)",9002,6318,15334,9802,1,0,4495,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,19685039.37,9002,8827,0,9002,,,
-6495,"NAD83(2011) / Michigan North",9001,6318,12141,9802,1,0,4499,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,8000000,9001,8827,0,9001,,,
-6496,"NAD83(2011) / Michigan North (ft)",9002,6318,15333,9802,1,0,4495,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,26246719.16,9002,8827,0,9002,,,
-6497,"NAD83(2011) / Michigan Oblique Mercator",9001,6318,12150,9812,1,0,4499,8806,2546731.496,9001,8807,-4354009.816,9001,8811,45.1833,9110,8812,-86,9110,8813,337.25556,9102,8814,337.25556,9102,8815,0.9996,9201
-6498,"NAD83(2011) / Michigan South",9001,6318,12143,9802,1,0,4499,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,4000000,9001,8827,0,9001,,,
-6499,"NAD83(2011) / Michigan South (ft)",9002,6318,15335,9802,1,0,4495,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,13123359.58,9002,8827,0,9002,,,
-6500,"NAD83(2011) / Minnesota Central",9001,6318,12232,9802,1,0,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,800000,9001,8827,100000,9001,,,
-6501,"NAD83(2011) / Minnesota Central (ftUS)",9003,6318,12235,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-6502,"NAD83(2011) / Minnesota North",9001,6318,12231,9802,1,0,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,800000,9001,8827,100000,9001,,,
-6503,"NAD83(2011) / Minnesota North (ftUS)",9003,6318,12234,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-6504,"NAD83(2011) / Minnesota South",9001,6318,12233,9802,1,0,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,800000,9001,8827,100000,9001,,,
-6505,"NAD83(2011) / Minnesota South (ftUS)",9003,6318,12236,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-6506,"NAD83(2011) / Mississippi East",9001,6318,12331,9807,1,0,4499,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,300000,9001,8807,0,9001,,,,,,
-6507,"NAD83(2011) / Mississippi East (ftUS)",9003,6318,15336,9807,1,0,4497,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,984250,9003,8807,0,9003,,,,,,
-6508,"NAD83(2011) / Mississippi TM",9001,6318,3813,9807,1,0,4499,8801,32.3,9110,8802,-89.45,9110,8805,0.9998335,9201,8806,500000,9001,8807,1300000,9001,,,,,,
-6509,"NAD83(2011) / Mississippi West",9001,6318,12332,9807,1,0,4499,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,700000,9001,8807,0,9001,,,,,,
-6510,"NAD83(2011) / Mississippi West (ftUS)",9003,6318,15337,9807,1,0,4497,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,2296583.333,9003,8807,0,9003,,,,,,
-6511,"NAD83(2011) / Missouri Central",9001,6318,12432,9807,1,0,4499,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9001,8807,0,9001,,,,,,
-6512,"NAD83(2011) / Missouri East",9001,6318,12431,9807,1,0,4499,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,250000,9001,8807,0,9001,,,,,,
-6513,"NAD83(2011) / Missouri West",9001,6318,12433,9807,1,0,4499,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,850000,9001,8807,0,9001,,,,,,
-6514,"NAD83(2011) / Montana",9001,6318,12530,9802,1,0,4499,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,600000,9001,8827,0,9001,,,
-6515,"NAD83(2011) / Montana (ft)",9002,6318,15338,9802,1,0,4495,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,1968503.937,9002,8827,0,9002,,,
-6516,"NAD83(2011) / Nebraska",9001,6318,12630,9802,1,0,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,500000,9001,8827,0,9001,,,
-6517,"NAD83(2011) / Nebraska (ftUS)",9003,4759,15396,9802,1,1,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,
-6518,"NAD83(2011) / Nevada Central",9001,6318,12732,9807,1,0,4499,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9001,8807,6000000,9001,,,,,,
-6519,"NAD83(2011) / Nevada Central (ftUS)",9003,6318,15382,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,1640416.6667,9003,8807,19685000,9003,,,,,,
-6520,"NAD83(2011) / Nevada East",9001,6318,12731,9807,1,0,4499,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,200000,9001,8807,8000000,9001,,,,,,
-6521,"NAD83(2011) / Nevada East (ftUS)",9003,6318,15381,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,656166.6667,9003,8807,26246666.6667,9003,,,,,,
-6522,"NAD83(2011) / Nevada West",9001,6318,12733,9807,1,0,4499,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,800000,9001,8807,4000000,9001,,,,,,
-6523,"NAD83(2011) / Nevada West (ftUS)",9003,6318,15383,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,2624666.6667,9003,8807,13123333.3333,9003,,,,,,
-6524,"NAD83(2011) / New Hampshire",9001,6318,12830,9807,1,0,4499,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,300000,9001,8807,0,9001,,,,,,
-6525,"NAD83(2011) / New Hampshire (ftUS)",9003,6318,15389,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,984250,9003,8807,0,9003,,,,,,
-6526,"NAD83(2011) / New Jersey",9001,6318,12930,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,
-6527,"NAD83(2011) / New Jersey (ftUS)",9003,6318,15384,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,
-6528,"NAD83(2011) / New Mexico Central",9001,6318,13032,9807,1,0,4499,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6529,"NAD83(2011) / New Mexico Central (ftUS)",9003,6318,15340,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,1640416.667,9003,8807,0,9003,,,,,,
-6530,"NAD83(2011) / New Mexico East",9001,6318,13031,9807,1,0,4499,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,165000,9001,8807,0,9001,,,,,,
-6531,"NAD83(2011) / New Mexico East (ftUS)",9003,6318,15339,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,541337.5,9003,8807,0,9003,,,,,,
-6532,"NAD83(2011) / New Mexico West",9001,6318,13033,9807,1,0,4499,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,830000,9001,8807,0,9001,,,,,,
-6533,"NAD83(2011) / New Mexico West (ftUS)",9003,6318,15341,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,2723091.667,9003,8807,0,9003,,,,,,
-6534,"NAD83(2011) / New York Central",9001,6318,13132,9807,1,0,4499,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,250000,9001,8807,0,9001,,,,,,
-6535,"NAD83(2011) / New York Central (ftUS)",9003,6318,15343,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,820208.333,9003,8807,0,9003,,,,,,
-6536,"NAD83(2011) / New York East",9001,6318,13131,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,
-6537,"NAD83(2011) / New York East (ftUS)",9003,6318,15342,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,
-6538,"NAD83(2011) / New York Long Island",9001,6318,13134,9802,1,0,4499,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,300000,9001,8827,0,9001,,,
-6539,"NAD83(2011) / New York Long Island (ftUS)",9003,6318,15345,9802,1,0,4497,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,984250,9003,8827,0,9003,,,
-6540,"NAD83(2011) / New York West",9001,6318,13133,9807,1,0,4499,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,350000,9001,8807,0,9001,,,,,,
-6541,"NAD83(2011) / New York West (ftUS)",9003,6318,15344,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,1148291.667,9003,8807,0,9003,,,,,,
-6542,"NAD83(2011) / North Carolina",9001,6318,13230,9802,1,0,4499,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,609601.22,9001,8827,0,9001,,,
-6543,"NAD83(2011) / North Carolina (ftUS)",9003,6318,15346,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,
-6544,"NAD83(2011) / North Dakota North",9001,6318,13331,9802,1,0,4499,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,600000,9001,8827,0,9001,,,
-6545,"NAD83(2011) / North Dakota North (ft)",9002,6318,15347,9802,1,0,4495,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,1968503.937,9002,8827,0,9002,,,
-6546,"NAD83(2011) / North Dakota South",9001,6318,13332,9802,1,0,4499,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,600000,9001,8827,0,9001,,,
-6547,"NAD83(2011) / North Dakota South (ft)",9002,6318,15348,9802,1,0,4495,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,1968503.937,9002,8827,0,9002,,,
-6548,"NAD83(2011) / Ohio North",9001,6318,13431,9802,1,0,4499,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,600000,9001,8827,0,9001,,,
-6549,"NAD83(2011) / Ohio North (ftUS)",9003,6318,13433,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,1968500,9003,8827,0,9003,,,
-6550,"NAD83(2011) / Ohio South",9001,6318,13432,9802,1,0,4499,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,600000,9001,8827,0,9001,,,
-6551,"NAD83(2011) / Ohio South (ftUS)",9003,6318,13434,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,1968500,9003,8827,0,9003,,,
-6552,"NAD83(2011) / Oklahoma North",9001,6318,13531,9802,1,0,4499,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,600000,9001,8827,0,9001,,,
-6553,"NAD83(2011) / Oklahoma North (ftUS)",9003,6318,15349,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,1968500,9003,8827,0,9003,,,
-6554,"NAD83(2011) / Oklahoma South",9001,6318,13532,9802,1,0,4499,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,600000,9001,8827,0,9001,,,
-6555,"NAD83(2011) / Oklahoma South (ftUS)",9003,6318,15350,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,1968500,9003,8827,0,9003,,,
-6556,"NAD83(2011) / Oregon LCC (m)",9001,6318,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,
-6557,"NAD83(2011) / Oregon GIC Lambert (ft)",9002,6318,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,
-6558,"NAD83(2011) / Oregon North",9001,6318,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,
-6559,"NAD83(2011) / Oregon North (ft)",9002,6318,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,
-6560,"NAD83(2011) / Oregon South",9001,6318,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,
-6561,"NAD83(2011) / Oregon South (ft)",9002,6318,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,
-6562,"NAD83(2011) / Pennsylvania North",9001,6318,13731,9802,1,0,4499,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,600000,9001,8827,0,9001,,,
-6563,"NAD83(2011) / Pennsylvania North (ftUS)",9003,6318,15353,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,1968500,9003,8827,0,9003,,,
-6564,"NAD83(2011) / Pennsylvania South",9001,6318,13732,9802,1,0,4499,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,600000,9001,8827,0,9001,,,
-6565,"NAD83(2011) / Pennsylvania South (ftUS)",9003,6318,15354,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,1968500,9003,8827,0,9003,,,
-6566,"NAD83(2011) / Puerto Rico and Virgin Is.",9001,6318,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,
-6567,"NAD83(2011) / Rhode Island",9001,6318,13830,9807,1,0,4499,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,100000,9001,8807,0,9001,,,,,,
-6568,"NAD83(2011) / Rhode Island (ftUS)",9003,6318,15390,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,328083.3333,9003,8807,0,9003,,,,,,
-6569,"NAD83(2011) / South Carolina",9001,6318,13930,9802,1,0,4499,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,609600,9001,8827,0,9001,,,
-6570,"NAD83(2011) / South Carolina (ft)",9002,6318,15355,9802,1,0,4495,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,2000000,9002,8827,0,9002,,,
-6571,"NAD83(2011) / South Dakota North",9001,6318,14031,9802,1,0,4499,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,600000,9001,8827,0,9001,,,
-6572,"NAD83(2011) / South Dakota North (ftUS)",9003,6318,15394,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,1968500,9003,8827,0,9003,,,
-6573,"NAD83(2011) / South Dakota South",9001,6318,14032,9802,1,0,4499,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,600000,9001,8827,0,9001,,,
-6574,"NAD83(2011) / South Dakota South (ftUS)",9003,6318,15395,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,
-6575,"NAD83(2011) / Tennessee",9001,6318,14130,9802,1,0,4499,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,600000,9001,8827,0,9001,,,
-6576,"NAD83(2011) / Tennessee (ftUS)",9003,6318,15356,9802,1,0,4497,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,1968500,9003,8827,0,9003,,,
-6577,"NAD83(2011) / Texas Central",9001,6318,14233,9802,1,0,4499,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,700000,9001,8827,3000000,9001,,,
-6578,"NAD83(2011) / Texas Central (ftUS)",9003,6318,15359,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,2296583.333,9003,8827,9842500,9003,,,
-6579,"NAD83(2011) / Texas Centric Albers Equal Area",9001,6318,14254,9822,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,6000000,9001,,,
-6580,"NAD83(2011) / Texas Centric Lambert Conformal",9001,6318,14253,9802,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,5000000,9001,,,
-6581,"NAD83(2011) / Texas North",9001,6318,14231,9802,1,0,4499,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,200000,9001,8827,1000000,9001,,,
-6582,"NAD83(2011) / Texas North (ftUS)",9003,6318,15357,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,656166.667,9003,8827,3280833.333,9003,,,
-6583,"NAD83(2011) / Texas North Central",9001,6318,14232,9802,1,0,4499,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,600000,9001,8827,2000000,9001,,,
-6584,"NAD83(2011) / Texas North Central (ftUS)",9003,6318,15358,9802,1,0,4497,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,1968500,9003,8827,6561666.667,9003,,,
-6585,"NAD83(2011) / Texas South",9001,6318,14235,9802,1,0,4499,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,300000,9001,8827,5000000,9001,,,
-6586,"NAD83(2011) / Texas South (ftUS)",9003,6318,15361,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,984250,9003,8827,16404166.667,9003,,,
-6587,"NAD83(2011) / Texas South Central",9001,6318,14234,9802,1,0,4499,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,600000,9001,8827,4000000,9001,,,
-6588,"NAD83(2011) / Texas South Central (ftUS)",9003,6318,15360,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,1968500,9003,8827,13123333.333,9003,,,
-6589,"NAD83(2011) / Vermont",9001,6318,14430,9807,1,0,4499,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9001,8807,0,9001,,,,,,
-6590,"NAD83(2011) / Vermont (ftUS)",9003,6318,5645,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,
-6591,"NAD83(2011) / Virginia Lambert",9001,6318,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,
-6592,"NAD83(2011) / Virginia North",9001,6318,14531,9802,1,0,4499,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,3500000,9001,8827,2000000,9001,,,
-6593,"NAD83(2011) / Virginia North (ftUS)",9003,6318,15365,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,11482916.667,9003,8827,6561666.667,9003,,,
-6594,"NAD83(2011) / Virginia South",9001,6318,14532,9802,1,0,4499,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,3500000,9001,8827,1000000,9001,,,
-6595,"NAD83(2011) / Virginia South (ftUS)",9003,6318,15366,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,11482916.667,9003,8827,3280833.333,9003,,,
-6596,"NAD83(2011) / Washington North",9001,6318,14631,9802,1,0,4499,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,500000,9001,8827,0,9001,,,
-6597,"NAD83(2011) / Washington North (ftUS)",9003,6318,15367,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,1640416.667,9003,8827,0,9003,,,
-6598,"NAD83(2011) / Washington South",9001,6318,14632,9802,1,0,4499,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,500000,9001,8827,0,9001,,,
-6599,"NAD83(2011) / Washington South (ftUS)",9003,6318,15368,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,1640416.667,9003,8827,0,9003,,,
-6600,"NAD83(2011) / West Virginia North",9001,6318,14731,9802,1,0,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,600000,9001,8827,0,9001,,,
-6601,"NAD83(2011) / West Virginia North (ftUS)",9003,6318,14735,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9003,8827,0,9003,,,
-6602,"NAD83(2011) / West Virginia South",9001,6318,14732,9802,1,0,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,600000,9001,8827,0,9001,,,
-6603,"NAD83(2011) / West Virginia South (ftUS)",9003,6318,14736,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9003,8827,0,9003,,,
-6604,"NAD83(2011) / Wisconsin Central",9001,4759,14832,9802,1,1,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,
-6605,"NAD83(2011) / Wisconsin Central (ftUS)",9003,6318,15370,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,1968500,9003,8827,0,9003,,,
-6606,"NAD83(2011) / Wisconsin North",9001,6318,14831,9802,1,0,4499,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,600000,9001,8827,0,9001,,,
-6607,"NAD83(2011) / Wisconsin North (ftUS)",9003,6318,15369,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,1968500,9003,8827,0,9003,,,
-6608,"NAD83(2011) / Wisconsin South",9001,6318,14833,9802,1,0,4499,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,600000,9001,8827,0,9001,,,
-6609,"NAD83(2011) / Wisconsin South (ftUS)",9003,6318,15371,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,1968500,9003,8827,0,9003,,,
-6610,"NAD83(2011) / Wisconsin Transverse Mercator",9001,6318,14841,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,520000,9001,8807,-4480000,9001,,,,,,
-6611,"NAD83(2011) / Wyoming East",9001,6318,14931,9807,1,0,4499,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,200000,9001,8807,0,9001,,,,,,
-6612,"NAD83(2011) / Wyoming East (ftUS)",9003,6318,14935,9807,1,0,4497,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,656166.6667,9003,8807,0,9003,,,,,,
-6613,"NAD83(2011) / Wyoming East Central",9001,6318,14932,9807,1,0,4499,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,400000,9001,8807,100000,9001,,,,,,
-6614,"NAD83(2011) / Wyoming East Central (ftUS)",9003,6318,14936,9807,1,0,4497,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,1312333.3333,9003,8807,328083.3333,9003,,,,,,
-6615,"NAD83(2011) / Wyoming West",9001,6318,14934,9807,1,0,4499,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,800000,9001,8807,100000,9001,,,,,,
-6616,"NAD83(2011) / Wyoming West (ftUS)",9003,6318,14938,9807,1,0,4497,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,2624666.6667,9003,8807,328083.3333,9003,,,,,,
-6617,"NAD83(2011) / Wyoming West Central",9001,6318,14933,9807,1,0,4499,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,600000,9001,8807,0,9001,,,,,,
-6618,"NAD83(2011) / Wyoming West Central (ftUS)",9003,6318,14937,9807,1,0,4497,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,1968500,9003,8807,0,9003,,,,,,
-6619,"NAD83(2011) / Utah Central",9001,6318,14332,9802,1,0,4499,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,500000,9001,8827,2000000,9001,,,
-6620,"NAD83(2011) / Utah North",9001,6318,14331,9802,1,0,4499,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,500000,9001,8827,1000000,9001,,,
-6621,"NAD83(2011) / Utah South",9001,6318,14333,9802,1,0,4499,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,500000,9001,8827,3000000,9001,,,
-6622,"NAD83(CSRS) / Quebec Lambert",9001,4617,19944,9802,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,
-6623,"NAD83 / Quebec Albers",9001,4269,6645,9822,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,
-6624,"NAD83(CSRS) / Quebec Albers",9001,4617,6645,9822,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,
-6625,"NAD83(2011) / Utah Central (ftUS)",9003,6318,15298,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640416.6667,9003,8827,6561666.6667,9003,,,
-6626,"NAD83(2011) / Utah North (ftUS)",9003,6318,15297,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640416.6667,9003,8827,3280833.3333,9003,,,
-6627,"NAD83(2011) / Utah South (ftUS)",9003,6318,15299,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640416.6667,9003,8827,9842500,9003,,,
-6628,"NAD83(PA11) / Hawaii zone 1",9001,6322,15131,9807,1,0,4499,8801,18.5,9110,8802,-155.3,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,
-6629,"NAD83(PA11) / Hawaii zone 2",9001,6322,15132,9807,1,0,4499,8801,20.2,9110,8802,-156.4,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,
-6630,"NAD83(PA11) / Hawaii zone 3",9001,6322,15133,9807,1,0,4499,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6631,"NAD83(PA11) / Hawaii zone 4",9001,6322,15134,9807,1,0,4499,8801,21.5,9110,8802,-159.3,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,
-6632,"NAD83(PA11) / Hawaii zone 5",9001,6322,15135,9807,1,0,4499,8801,21.4,9110,8802,-160.1,9110,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-6633,"NAD83(PA11) / Hawaii zone 3 (ftUS)",9003,6322,15138,9807,1,0,4497,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,
-6634,"NAD83(PA11) / UTM zone 4N",9001,6322,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6635,"NAD83(PA11) / UTM zone 5N",9001,6322,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6636,"NAD83(PA11) / UTM zone 2S",9001,6322,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6637,"NAD83(MA11) / Guam Map Grid",9001,6325,4325,9807,1,0,4499,8801,13.3,9110,8802,144.45,9110,8805,1,9201,8806,100000,9001,8807,200000,9001,,,,,,
-6646,"Karbala 1979 / Iraq National Grid",9001,4743,19907,9807,1,0,4400,8801,29.0134566,9110,8802,46.3,9110,8805,0.9994,9201,8806,800000,9001,8807,0,9001,,,,,,
-6669,"JGD2011 / Japan Plane Rectangular CS I",9001,6668,17801,9807,1,0,4530,8801,33,9110,8802,129.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6670,"JGD2011 / Japan Plane Rectangular CS II",9001,6668,17802,9807,1,0,4530,8801,33,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6671,"JGD2011 / Japan Plane Rectangular CS III",9001,6668,17803,9807,1,0,4530,8801,36,9110,8802,132.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6672,"JGD2011 / Japan Plane Rectangular CS IV",9001,6668,17804,9807,1,0,4530,8801,33,9110,8802,133.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6673,"JGD2011 / Japan Plane Rectangular CS V",9001,6668,17805,9807,1,0,4530,8801,36,9110,8802,134.2,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6674,"JGD2011 / Japan Plane Rectangular CS VI",9001,6668,17806,9807,1,0,4530,8801,36,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6675,"JGD2011 / Japan Plane Rectangular CS VII",9001,6668,17807,9807,1,0,4530,8801,36,9110,8802,137.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6676,"JGD2011 / Japan Plane Rectangular CS VIII",9001,6668,17808,9807,1,0,4530,8801,36,9110,8802,138.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6677,"JGD2011 / Japan Plane Rectangular CS IX",9001,6668,17809,9807,1,0,4530,8801,36,9110,8802,139.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6678,"JGD2011 / Japan Plane Rectangular CS X",9001,6668,17810,9807,1,0,4530,8801,40,9110,8802,140.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6679,"JGD2011 / Japan Plane Rectangular CS XI",9001,6668,17811,9807,1,0,4530,8801,44,9110,8802,140.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6680,"JGD2011 / Japan Plane Rectangular CS XII",9001,6668,17812,9807,1,0,4530,8801,44,9110,8802,142.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6681,"JGD2011 / Japan Plane Rectangular CS XIII",9001,6668,17813,9807,1,0,4530,8801,44,9110,8802,144.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6682,"JGD2011 / Japan Plane Rectangular CS XIV",9001,6668,17814,9807,1,0,4530,8801,26,9110,8802,142,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6683,"JGD2011 / Japan Plane Rectangular CS XV",9001,6668,17815,9807,1,0,4530,8801,26,9110,8802,127.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6684,"JGD2011 / Japan Plane Rectangular CS XVI",9001,6668,17816,9807,1,0,4530,8801,26,9110,8802,124,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6685,"JGD2011 / Japan Plane Rectangular CS XVII",9001,6668,17817,9807,1,0,4530,8801,26,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6686,"JGD2011 / Japan Plane Rectangular CS XVIII",9001,6668,17818,9807,1,0,4530,8801,20,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6687,"JGD2011 / Japan Plane Rectangular CS XIX",9001,6668,17819,9807,1,0,4530,8801,26,9110,8802,154,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-6688,"JGD2011 / UTM zone 51N",9001,6668,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6689,"JGD2011 / UTM zone 52N",9001,6668,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6690,"JGD2011 / UTM zone 53N",9001,6668,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6691,"JGD2011 / UTM zone 54N",9001,6668,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6692,"JGD2011 / UTM zone 55N",9001,6668,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6703,"WGS 84 / TM 60 SW",9001,4326,6702,9807,1,0,4400,8801,0,9102,8802,-60,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6707,"RDN2008 / TM32",9001,6706,16032,9807,1,0,4500,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6708,"RDN2008 / TM33",9001,6706,16033,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6709,"RDN2008 / TM34",9001,6706,16034,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6720,"WGS 84 / CIG92",9001,4326,6716,9807,1,0,4400,8801,0,9110,8802,105.373,9110,8805,1.000024,9201,8806,50000,9001,8807,1300000,9001,,,,,,
-6721,"GDA94 / CIG94",9001,4283,6717,9807,1,0,4400,8801,0,9110,8802,105.373,9110,8805,1.00002514,9201,8806,50000,9001,8807,1300000,9001,,,,,,
-6722,"WGS 84 / CKIG92",9001,4326,6718,9807,1,0,4400,8801,0,9110,8802,96.523,9110,8805,1,9201,8806,50000,9001,8807,1400000,9001,,,,,,
-6723,"GDA94 / CKIG94",9001,4283,6719,9807,1,0,4400,8801,0,9110,8802,96.523,9110,8805,0.99999387,9201,8806,50000,9001,8807,1500000,9001,,,,,,
-6732,"GDA94 / MGA zone 41",9001,4283,6725,9807,1,1,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6733,"GDA94 / MGA zone 42",9001,4283,6726,9807,1,1,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6734,"GDA94 / MGA zone 43",9001,4283,6727,9807,1,1,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6735,"GDA94 / MGA zone 44",9001,4283,6728,9807,1,1,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6736,"GDA94 / MGA zone 46",9001,4283,6729,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6737,"GDA94 / MGA zone 47",9001,4283,6730,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6738,"GDA94 / MGA zone 59",9001,4283,6731,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-6784,"NAD83(CORS96) / Oregon Baker zone (m)",9001,6783,6741,9807,1,0,4499,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,40000,9001,8807,0,9001,,,,,,
-6785,"NAD83(CORS96) / Oregon Baker zone (ft)",9002,6783,6742,9807,1,0,4495,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
-6786,"NAD83(2011) / Oregon Baker zone (m)",9001,6318,6741,9807,1,0,4499,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,40000,9001,8807,0,9001,,,,,,
-6787,"NAD83(2011) / Oregon Baker zone (ft)",9002,6318,6742,9807,1,0,4495,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
-6788,"NAD83(CORS96) / Oregon Bend-Klamath Falls zone (m)",9001,6783,6743,9807,1,0,4499,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,80000,9001,8807,0,9001,,,,,,
-6789,"NAD83(CORS96) / Oregon Bend-Klamath Falls zone (ft)",9002,6783,6744,9807,1,0,4495,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
-6790,"NAD83(2011) / Oregon Bend-Klamath Falls zone (m)",9001,6318,6743,9807,1,0,4499,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,80000,9001,8807,0,9001,,,,,,
-6791,"NAD83(2011) / Oregon Bend-Klamath Falls zone (ft)",9002,6318,6744,9807,1,0,4495,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
-6792,"NAD83(CORS96) / Oregon Bend-Redmond-Prineville zone (m)",9001,6783,6745,9801,1,0,4499,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,80000,9001,8807,130000,9001,,,,,,
-6793,"NAD83(CORS96) / Oregon Bend-Redmond-Prineville zone (ft)",9002,6783,6746,9801,1,0,4495,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,262467.1916,9002,8807,426509.1864,9002,,,,,,
-6794,"NAD83(2011) / Oregon Bend-Redmond-Prineville zone (m)",9001,6318,6745,9801,1,0,4499,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,80000,9001,8807,130000,9001,,,,,,
-6795,"NAD83(2011) / Oregon Bend-Redmond-Prineville zone (ft)",9002,6318,6746,9801,1,0,4495,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,262467.1916,9002,8807,426509.1864,9002,,,,,,
-6796,"NAD83(CORS96) / Oregon Bend-Burns zone (m)",9001,6783,6747,9801,1,0,4499,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,120000,9001,8807,60000,9001,,,,,,
-6797,"NAD83(CORS96) / Oregon Bend-Burns zone (ft)",9002,6783,6748,9801,1,0,4495,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,393700.7874,9002,8807,196850.3937,9002,,,,,,
-6798,"NAD83(2011) / Oregon Bend-Burns zone (m)",9001,6318,6747,9801,1,0,4499,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,120000,9001,8807,60000,9001,,,,,,
-6799,"NAD83(2011) / Oregon Bend-Burns zone (ft)",9002,6318,6748,9801,1,0,4495,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,393700.7874,9002,8807,196850.3937,9002,,,,,,
-6800,"NAD83(CORS96) / Oregon Canyonville-Grants Pass zone (m)",9001,6783,6749,9807,1,0,4499,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,40000,9001,8807,0,9001,,,,,,
-6801,"NAD83(CORS96) / Oregon Canyonville-Grants Pass zone (ft)",9002,6783,6750,9807,1,0,4495,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
-6802,"NAD83(2011) / Oregon Canyonville-Grants Pass zone (m)",9001,6318,6749,9807,1,0,4499,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,40000,9001,8807,0,9001,,,,,,
-6803,"NAD83(2011) / Oregon Canyonville-Grants Pass zone (ft)",9002,6318,6750,9807,1,0,4495,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
-6804,"NAD83(CORS96) / Oregon Columbia River East zone (m)",9001,6783,6751,9801,1,0,4499,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,150000,9001,8807,30000,9001,,,,,,
-6805,"NAD83(CORS96) / Oregon Columbia River East zone (ft)",9002,6783,6752,9801,1,0,4495,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,492125.9843,9002,8807,98425.1969,9002,,,,,,
-6806,"NAD83(2011) / Oregon Columbia River East zone (m)",9001,6318,6751,9801,1,0,4499,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,150000,9001,8807,30000,9001,,,,,,
-6807,"NAD83(2011) / Oregon Columbia River East zone (ft)",9002,6318,6752,9801,1,0,4495,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,492125.9843,9002,8807,98425.1969,9002,,,,,,
-6808,"NAD83(CORS96) / Oregon Columbia River West zone (m)",9001,6783,6753,9812,1,0,4499,8806,7000000,9001,8807,-3000000,9001,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
-6809,"NAD83(CORS96) / Oregon Columbia River West zone (ft)",9002,6783,6754,9812,1,0,4495,8806,22965879.2651,9002,8807,-9842519.685,9002,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
-6810,"NAD83(2011) / Oregon Columbia River West zone (m)",9001,6318,6753,9812,1,0,4499,8806,7000000,9001,8807,-3000000,9001,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
-6811,"NAD83(2011) / Oregon Columbia River West zone (ft)",9002,6318,6754,9812,1,0,4495,8806,22965879.2651,9002,8807,-9842519.685,9002,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201
-6812,"NAD83(CORS96) / Oregon Cottage Grove-Canyonville zone (m)",9001,6783,6755,9807,1,0,4499,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,50000,9001,8807,0,9001,,,,,,
-6813,"NAD83(CORS96) / Oregon Cottage Grove-Canyonville zone (ft)",9002,6783,6756,9807,1,0,4495,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
-6814,"NAD83(2011) / Oregon Cottage Grove-Canyonville zone (m)",9001,6318,6755,9807,1,0,4499,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,50000,9001,8807,0,9001,,,,,,
-6815,"NAD83(2011) / Oregon Cottage Grove-Canyonville zone (ft)",9002,6318,6756,9807,1,0,4495,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
-6816,"NAD83(CORS96) / Oregon Dufur-Madras zone (m)",9001,6783,6757,9807,1,0,4499,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,80000,9001,8807,0,9001,,,,,,
-6817,"NAD83(CORS96) / Oregon Dufur-Madras zone (ft)",9002,6783,6758,9807,1,0,4495,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
-6818,"NAD83(2011) / Oregon Dufur-Madras zone (m)",9001,6318,6757,9807,1,0,4499,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,80000,9001,8807,0,9001,,,,,,
-6819,"NAD83(2011) / Oregon Dufur-Madras zone (ft)",9002,6318,6758,9807,1,0,4495,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
-6820,"NAD83(CORS96) / Oregon Eugene zone (m)",9001,6783,6759,9807,1,0,4499,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,50000,9001,8807,0,9001,,,,,,
-6821,"NAD83(CORS96) / Oregon Eugene zone (ft)",9002,6783,6760,9807,1,0,4495,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
-6822,"NAD83(2011) / Oregon Eugene zone (m)",9001,6318,6759,9807,1,0,4499,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,50000,9001,8807,0,9001,,,,,,
-6823,"NAD83(2011) / Oregon Eugene zone (ft)",9002,6318,6760,9807,1,0,4495,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
-6824,"NAD83(CORS96) / Oregon Grants Pass-Ashland zone (m)",9001,6783,6761,9807,1,0,4499,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,50000,9001,8807,0,9001,,,,,,
-6825,"NAD83(CORS96) / Oregon Grants Pass-Ashland zone (ft)",9002,6783,6762,9807,1,0,4495,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
-6826,"NAD83(2011) / Oregon Grants Pass-Ashland zone (m)",9001,6318,6761,9807,1,0,4499,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,50000,9001,8807,0,9001,,,,,,
-6827,"NAD83(2011) / Oregon Grants Pass-Ashland zone (ft)",9002,6318,6762,9807,1,0,4495,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
-6828,"NAD83(CORS96) / Oregon Gresham-Warm Springs zone (m)",9001,6783,6763,9807,1,0,4499,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,10000,9001,8807,0,9001,,,,,,
-6829,"NAD83(CORS96) / Oregon Gresham-Warm Springs zone (ft)",9002,6783,6764,9807,1,0,4495,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,32808.399,9002,8807,0,9002,,,,,,
-6830,"NAD83(2011) / Oregon Gresham-Warm Springs zone (m)",9001,6318,6763,9807,1,0,4499,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,10000,9001,8807,0,9001,,,,,,
-6831,"NAD83(2011) / Oregon Gresham-Warm Springs zone (ft)",9002,6318,6764,9807,1,0,4495,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,32808.399,9002,8807,0,9002,,,,,,
-6832,"NAD83(CORS96) / Oregon La Grande zone (m)",9001,6783,6765,9807,1,0,4499,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,40000,9001,8807,0,9001,,,,,,
-6833,"NAD83(CORS96) / Oregon La Grande zone (ft)",9002,6783,6766,9807,1,0,4495,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
-6834,"NAD83(2011) / Oregon La Grande zone (m)",9001,6318,6765,9807,1,0,4499,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,40000,9001,8807,0,9001,,,,,,
-6835,"NAD83(2011) / Oregon La Grande zone (ft)",9002,6318,6766,9807,1,0,4495,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,131233.5958,9002,8807,0,9002,,,,,,
-6836,"NAD83(CORS96) / Oregon Ontario zone (m)",9001,6783,6767,9807,1,0,4499,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,80000,9001,8807,0,9001,,,,,,
-6837,"NAD83(CORS96) / Oregon Ontario zone (ft)",9002,6783,6768,9807,1,0,4495,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
-6838,"NAD83(2011) / Oregon Ontario zone (m)",9001,6318,6767,9807,1,0,4499,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,80000,9001,8807,0,9001,,,,,,
-6839,"NAD83(2011) / Oregon Ontario zone (ft)",9002,6318,6768,9807,1,0,4495,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,262467.1916,9002,8807,0,9002,,,,,,
-6840,"NAD83(CORS96) / Oregon Coast zone (m)",9001,6783,6769,9812,1,0,4499,8806,-300000,9001,8807,-4600000,9001,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
-6841,"NAD83(CORS96) / Oregon Coast zone (ft)",9002,6783,6770,9812,1,0,4495,8806,-984251.9685,9002,8807,-15091863.5171,9002,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
-6842,"NAD83(2011) / Oregon Coast zone (m)",9001,6318,6769,9812,1,0,4499,8806,-300000,9001,8807,-4600000,9001,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
-6843,"NAD83(2011) / Oregon Coast zone (ft)",9002,6318,6770,9812,1,0,4495,8806,-984251.9685,9002,8807,-15091863.5171,9002,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201
-6844,"NAD83(CORS96) / Oregon Pendleton zone (m)",9001,6783,6771,9807,1,0,4499,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,60000,9001,8807,0,9001,,,,,,
-6845,"NAD83(CORS96) / Oregon Pendleton zone (ft)",9002,6783,6772,9807,1,0,4495,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,196850.3937,9002,8807,0,9002,,,,,,
-6846,"NAD83(2011) / Oregon Pendleton zone (m)",9001,6318,6771,9807,1,0,4499,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,60000,9001,8807,0,9001,,,,,,
-6847,"NAD83(2011) / Oregon Pendleton zone (ft)",9002,6318,6772,9807,1,0,4495,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,196850.3937,9002,8807,0,9002,,,,,,
-6848,"NAD83(CORS96) / Oregon Pendleton-La Grande zone (m)",9001,6783,6773,9807,1,0,4499,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,30000,9001,8807,0,9001,,,,,,
-6849,"NAD83(CORS96) / Oregon Pendleton-La Grande zone (ft)",9002,6783,6774,9807,1,0,4495,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,98425.1969,9002,8807,0,9002,,,,,,
-6850,"NAD83(2011) / Oregon Pendleton-La Grande zone (m)",9001,6318,6773,9807,1,0,4499,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,30000,9001,8807,0,9001,,,,,,
-6851,"NAD83(2011) / Oregon Pendleton-La Grande zone (ft)",9002,6318,6774,9807,1,0,4495,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,98425.1969,9002,8807,0,9002,,,,,,
-6852,"NAD83(CORS96) / Oregon Portland zone (m)",9001,6783,6775,9801,1,0,4499,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,100000,9001,8807,50000,9001,,,,,,
-6853,"NAD83(CORS96) / Oregon Portland zone (ft)",9002,6783,6776,9801,1,0,4495,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,328083.9895,9002,8807,164041.9948,9002,,,,,,
-6854,"NAD83(2011) / Oregon Portland zone (m)",9001,6318,6775,9801,1,0,4499,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,100000,9001,8807,50000,9001,,,,,,
-6855,"NAD83(2011) / Oregon Portland zone (ft)",9002,6318,6776,9801,1,0,4495,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,328083.9895,9002,8807,164041.9948,9002,,,,,,
-6856,"NAD83(CORS96) / Oregon Salem zone (m)",9001,6783,6777,9807,1,0,4499,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,50000,9001,8807,0,9001,,,,,,
-6857,"NAD83(CORS96) / Oregon Salem zone (ft)",9002,6783,6778,9807,1,0,4495,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
-6858,"NAD83(2011) / Oregon Salem zone (m)",9001,6318,6777,9807,1,0,4499,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,50000,9001,8807,0,9001,,,,,,
-6859,"NAD83(2011) / Oregon Salem zone (ft)",9002,6318,6778,9807,1,0,4495,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,164041.9948,9002,8807,0,9002,,,,,,
-6860,"NAD83(CORS96) / Oregon Santiam Pass zone (m)",9001,6783,6779,9807,1,0,4499,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9001,8807,0,9001,,,,,,
-6861,"NAD83(CORS96) / Oregon Santiam Pass zone (ft)",9002,6783,6780,9807,1,0,4495,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9002,8807,0,9002,,,,,,
-6862,"NAD83(2011) / Oregon Santiam Pass zone (m)",9001,6318,6779,9807,1,0,4499,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9001,8807,0,9001,,,,,,
-6863,"NAD83(2011) / Oregon Santiam Pass (ft)",9002,6318,6780,9807,1,0,4495,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9002,8807,0,9002,,,,,,
-6867,"NAD83(CORS96) / Oregon LCC (m)",9001,6783,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,
-6868,"NAD83(CORS96) / Oregon GIC Lambert (ft)",9002,6783,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,
-6870,"ETRS89 / Albania TM 2010",9001,4258,6869,9807,1,0,4530,8801,0,9102,8802,20,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-6875,"RDN2008 / Italy zone",9001,6706,6877,9807,1,0,4500,8801,0,9102,8802,12,9102,8805,0.9985,9201,8806,7000000,9001,8807,0,9001,,,,,,
-6876,"RDN2008 / Zone 12",9001,6706,6878,9807,1,0,4500,8801,0,9102,8802,12,9102,8805,1,9201,8806,3000000,9001,8807,0,9001,,,,,,
-6879,"NAD83(2011) / Wisconsin Central",9001,6318,14832,9802,1,0,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,
-6880,"NAD83(2011) / Nebraska (ftUS)",9003,6318,15396,9802,1,0,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,
-6884,"NAD83(CORS96) / Oregon North",9001,6783,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,
-6885,"NAD83(CORS96) / Oregon North (ft)",9002,6783,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,
-6886,"NAD83(CORS96) / Oregon South",9001,6783,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,
-6887,"NAD83(CORS96) / Oregon South (ft)",9002,6783,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,
-6915,"South East Island 1943 / UTM zone 40N",9001,6892,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-6922,"NAD83 / Kansas LCC",9001,4269,6920,9802,1,0,4499,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,400000,9001,8827,0,9001,,,
-6923,"NAD83 / Kansas LCC (ftUS)",9003,4269,6921,9802,1,0,4497,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,1312333.3333,9003,8827,0,9003,,,
-6924,"NAD83(2011) / Kansas LCC",9001,6318,6920,9802,1,0,4499,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,400000,9001,8827,0,9001,,,
-6925,"NAD83(2011) / Kansas LCC (ftUS)",9003,6318,6921,9802,1,0,4497,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,1312333.3333,9003,8827,0,9003,,,
-6931,"WGS 84 / NSIDC EASE-Grid 2.0 North",9001,4326,6929,9820,1,0,4469,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-6932,"WGS 84 / NSIDC EASE-Grid 2.0 South",9001,4326,6930,9820,1,0,4470,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-6933,"WGS 84 / NSIDC EASE-Grid 2.0 Global",9001,4326,6928,9835,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,
-6956,"VN-2000 / TM-3 zone 481",9001,4756,6952,9807,1,0,4400,8801,0,9102,8802,102,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
-6957,"VN-2000 / TM-3 zone 482",9001,4756,6953,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
-6958,"VN-2000 / TM-3 zone 491",9001,4756,6954,9807,1,0,4400,8801,0,9102,8802,108,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
-6959,"VN-2000 / TM-3 Da Nang zone",9001,4756,6955,9807,1,0,4400,8801,0,9110,8802,107.45,9110,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,
-6962,"ETRS89 / Albania LCC 2010",9001,4258,6961,9802,1,0,4530,8821,41,9102,8822,20,9102,8823,39,9102,8824,43,9102,8826,0,9001,8827,0,9001,,,
-6966,"NAD27 / Michigan North",9003,4267,6965,1051,1,0,4497,1038,1.0000382,9201,8821,44.47,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003
-6984,Israeli Grid 05,9001,6983,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,
-6991,"Israeli Grid 05/12",9001,6990,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,
-6996,"NAD83(2011) / San Francisco CS13",9001,6318,6994,9807,1,1,4499,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9202,8806,48000,9001,8807,24000,9001,,,,,,
-6997,"NAD83(2011) / San Francisco CS13 (ftUS)",9003,6318,6995,9807,1,1,4497,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9202,8806,157480,9003,8807,78740,9003,,,,,,
-7005,"Nahrwan 1934 / UTM zone 37N",9001,4744,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-7006,"Nahrwan 1934 / UTM zone 38N",9001,4744,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-7007,"Nahrwan 1934 / UTM zone 39N",9001,4744,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-7057,"NAD83(2011) / IaRCS zone 1",9003,6318,7043,9801,1,0,4497,8801,43.12,9110,8802,-95.15,9110,8805,1.000052,9201,8806,11500000,9003,8807,9600000,9003,,,,,,
-7058,"NAD83(2011) / IaRCS zone 2",9003,6318,7044,9801,1,0,4497,8801,43.1,9110,8802,-92.45,9110,8805,1.000043,9201,8806,12500000,9003,8807,9800000,9003,,,,,,
-7059,"NAD83(2011) / IaRCS zone 3",9003,6318,7045,9807,1,0,4497,8801,40.15,9110,8802,-91.12,9110,8805,1.000035,9201,8806,13500000,9003,8807,8300000,9003,,,,,,
-7060,"NAD83(2011) / IaRCS zone 4",9003,6318,7046,9801,1,0,4497,8801,42.32,9110,8802,-94.5,9110,8805,1.000045,9201,8806,14500000,9003,8807,8600000,9003,,,,,,
-7061,"NAD83(2011) / IaRCS zone 5",9003,6318,7047,9801,1,0,4497,8801,42.39,9110,8802,-92.15,9110,8805,1.000032,9201,8806,15500000,9003,8807,8900000,9003,,,,,,
-7062,"NAD83(2011) / IaRCS zone 6",9003,6318,7048,9807,1,0,4497,8801,40.15,9110,8802,-95.44,9110,8805,1.000039,9201,8806,16500000,9003,8807,6600000,9003,,,,,,
-7063,"NAD83(2011) / IaRCS zone 7",9003,6318,7049,9807,1,0,4497,8801,40.15,9110,8802,-94.38,9110,8805,1.000045,9201,8806,17500000,9003,8807,6800000,9003,,,,,,
-7064,"NAD83(2011) / IaRCS zone 8",9003,6318,7050,9807,1,0,4497,8801,40.15,9110,8802,-93.43,9110,8805,1.000033,9201,8806,18500000,9003,8807,7000000,9003,,,,,,
-7065,"NAD83(2011) / IaRCS zone 9",9003,6318,7051,9807,1,0,4497,8801,40.15,9110,8802,-92.49,9110,8805,1.000027,9201,8806,19500000,9003,8807,7200000,9003,,,,,,
-7066,"NAD83(2011) / IaRCS zone 10",9003,6318,7052,9801,1,0,4497,8801,41.5,9110,8802,-91.4,9110,8805,1.00002,9201,8806,20500000,9003,8807,8000000,9003,,,,,,
-7067,"NAD83(2011) / IaRCS zone 11",9003,6318,7053,9807,1,0,4497,8801,40.15,9110,8802,-90.32,9110,8805,1.000027,9201,8806,21500000,9003,8807,7600000,9003,,,,,,
-7068,"NAD83(2011) / IaRCS zone 12",9003,6318,7054,9801,1,0,4497,8801,40.55,9110,8802,-93.45,9110,8805,1.000037,9201,8806,22500000,9003,8807,6200000,9003,,,,,,
-7069,"NAD83(2011) / IaRCS zone 13",9003,6318,7055,9807,1,0,4497,8801,40.15,9110,8802,-91.55,9110,8805,1.00002,9201,8806,23500000,9003,8807,6400000,9003,,,,,,
-7070,"NAD83(2011) / IaRCS zone 14",9003,6318,7056,9807,1,0,4497,8801,40.15,9110,8802,-91.15,9110,8805,1.000018,9201,8806,24500000,9003,8807,6200000,9003,,,,,,
-7074,"RGTAAF07 / UTM zone 37S",9001,7073,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-7075,"RGTAAF07 / UTM zone 38S",9001,7073,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-7076,"RGTAAF07 / UTM zone 39S",9001,7073,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-7077,"RGTAAF07 / UTM zone 40S",9001,7073,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-7078,"RGTAAF07 / UTM zone 41S",9001,7073,16141,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-7079,"RGTAAF07 / UTM zone 42S",9001,7073,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-7080,"RGTAAF07 / UTM zone 43S",9001,7073,16143,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-7081,"RGTAAF07 / UTM zone 44S",9001,7073,16144,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-7082,"RGTAAF07 / Terre Adelie Polar Stereographic",9001,7073,19983,9830,1,0,4400,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,
-7109,"NAD83(2011) / RMTCRS St Mary (m)",9001,6318,7089,9807,1,0,4499,8801,48.3,9110,8802,-112.3,9110,8805,1.00016,9201,8806,150000,9001,8807,0,9001,,,,,,
-7110,"NAD83(2011) / RMTCRS Blackfeet (m)",9001,6318,7091,9807,1,0,4499,8801,48,9110,8802,-112.3,9110,8805,1.00019,9201,8806,100000,9001,8807,0,9001,,,,,,
-7111,"NAD83(2011) / RMTCRS Milk River (m)",9001,6318,7093,9801,1,0,4499,8801,48.3,9110,8802,-111,9110,8805,1.000145,9201,8806,150000,9001,8807,200000,9001,,,,,,
-7112,"NAD83(2011) / RMTCRS Fort Belknap (m)",9001,6318,7095,9801,1,0,4499,8801,48.3,9110,8802,-108.3,9110,8805,1.00012,9201,8806,200000,9001,8807,150000,9001,,,,,,
-7113,"NAD83(2011) / RMTCRS Fort Peck Assiniboine (m)",9001,6318,7097,9801,1,0,4499,8801,48.2,9110,8802,-105.3,9110,8805,1.00012,9201,8806,200000,9001,8807,100000,9001,,,,,,
-7114,"NAD83(2011) / RMTCRS Fort Peck Sioux (m)",9001,6318,7099,9801,1,0,4499,8801,48.2,9110,8802,-105.3,9110,8805,1.00009,9201,8806,100000,9001,8807,50000,9001,,,,,,
-7115,"NAD83(2011) / RMTCRS Crow (m)",9001,6318,7101,9807,1,0,4499,8801,44.45,9110,8802,-107.45,9110,8805,1.000148,9201,8806,200000,9001,8807,0,9001,,,,,,
-7116,"NAD83(2011) / RMTCRS Bobcat (m)",9001,6318,7103,9801,1,0,4499,8801,46.15,9110,8802,-111.15,9110,8805,1.000185,9201,8806,100000,9001,8807,100000,9001,,,,,,
-7117,"NAD83(2011) / RMTCRS Billings (m)",9001,6318,7105,9801,1,0,4499,8801,45.47,9110,8802,-108.25,9110,8805,1.0001515,9201,8806,200000,9001,8807,50000,9001,,,,,,
-7118,"NAD83(2011) / RMTCRS Wind River (m)",9001,6318,7107,9807,1,0,4499,8801,42.4,9110,8802,-108.2,9110,8805,1.00024,9201,8806,100000,9001,8807,0,9001,,,,,,
-7119,"NAD83(2011) / RMTCRS St Mary (ft)",9002,6318,7090,9807,1,0,4495,8801,48.3,9110,8802,-112.3,9110,8805,1.00016,9201,8806,492125.9843,9002,8807,0,9002,,,,,,
-7120,"NAD83(2011) / RMTCRS Blackfeet (ft)",9002,6318,7092,9807,1,0,4495,8801,48,9110,8802,-112.3,9110,8805,1.00019,9201,8806,328083.9895,9002,8807,0,9002,,,,,,
-7121,"NAD83(2011) / RMTCRS Milk River (ft)",9002,6318,7094,9801,1,0,4495,8801,48.3,9110,8802,-111,9110,8805,1.000145,9201,8806,492125.9843,9002,8807,656167.979,9002,,,,,,
-7122,"NAD83(2011) / RMTCRS Fort Belknap (ft)",9002,6318,7096,9801,1,0,4495,8801,48.3,9110,8802,-108.3,9110,8805,1.00012,9201,8806,656167.979,9002,8807,492125.9843,9002,,,,,,
-7123,"NAD83(2011) / RMTCRS Fort Peck Assiniboine (ft)",9002,6318,7098,9801,1,0,4495,8801,48.2,9110,8802,-105.3,9110,8805,1.00012,9201,8806,656167.979,9002,8807,328083.9895,9002,,,,,,
-7124,"NAD83(2011) / RMTCRS Fort Peck Sioux (ft)",9002,6318,7100,9801,1,0,4495,8801,48.2,9110,8802,-105.3,9110,8805,1.00009,9201,8806,328083.9895,9002,8807,164041.9938,9002,,,,,,
-7125,"NAD83(2011) / RMTCRS Crow (ft)",9002,6318,7102,9807,1,0,4495,8801,44.45,9110,8802,-107.45,9110,8805,1.000148,9201,8806,656167.979,9002,8807,0,9002,,,,,,
-7126,"NAD83(2011) / RMTCRS Bobcat (ft)",9002,6318,7104,9801,1,0,4495,8801,46.15,9110,8802,-111.15,9110,8805,1.000185,9201,8806,328083.9895,9002,8807,328083.9895,9002,,,,,,
-7127,"NAD83(2011) / RMTCRS Billings (ft)",9002,6318,7106,9801,1,0,4495,8801,45.47,9110,8802,-108.25,9110,8805,1.0001515,9201,8806,656167.979,9002,8807,164041.9948,9002,,,,,,
-7128,"NAD83(2011) / RMTCRS Wind River (ftUS)",9003,6318,7108,9807,1,0,4497,8801,42.4,9110,8802,-108.2,9110,8805,1.00024,9201,8806,328083.3333,9003,8807,0,9003,,,,,,
-7131,"NAD83(2011) / San Francisco CS13",9001,6318,7129,9807,1,0,4499,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9201,8806,48000,9001,8807,24000,9001,,,,,,
-7132,"NAD83(2011) / San Francisco CS13 (ftUS)",9003,6318,7130,9807,1,0,4497,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9201,8806,157480,9003,8807,78740,9003,,,,,,
-7142,"Palestine 1923 / Palestine Grid modified",9001,4281,7141,9807,1,0,4400,8801,31.4402749,9110,8802,35.124349,9110,8805,1,9201,8806,170251.555,9001,8807,126867.909,9001,,,,,,
-7257,"NAD83(2011) / InGCS Adams (m)",9001,6318,7143,9807,1,0,4499,8801,40.33,9110,8802,-84.57,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7258,"NAD83(2011) / InGCS Adams (ftUS)",9003,6318,7144,9807,1,0,4497,8801,40.33,9110,8802,-84.57,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7259,"NAD83(2011) / InGCS Allen (m)",9001,6318,7145,9807,1,0,4499,8801,40.54,9110,8802,-85.03,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7260,"NAD83(2011) / InGCS Allen (ftUS)",9003,6318,7146,9807,1,0,4497,8801,40.54,9110,8802,-85.03,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7261,"NAD83(2011) / InGCS Bartholomew (m)",9001,6318,7147,9807,1,0,4499,8801,39,9110,8802,-85.51,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7262,"NAD83(2011) / InGCS Bartholomew (ftUS)",9003,6318,7148,9807,1,0,4497,8801,39,9110,8802,-85.51,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7263,"NAD83(2011) / InGCS Benton (m)",9001,6318,7149,9807,1,0,4499,8801,40.27,9110,8802,-87.18,9110,8805,1.000029,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7264,"NAD83(2011) / InGCS Benton (ftUS)",9003,6318,7150,9807,1,0,4497,8801,40.27,9110,8802,-87.18,9110,8805,1.000029,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7265,"NAD83(2011) / InGCS Blackford-Delaware (m)",9001,6318,7151,9807,1,0,4499,8801,40.03,9110,8802,-85.24,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7266,"NAD83(2011) / InGCS Blackford-Delaware (ftUS)",9003,6318,7152,9807,1,0,4497,8801,40.03,9110,8802,-85.24,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7267,"NAD83(2011) / InGCS Boone-Hendricks (m)",9001,6318,7153,9807,1,0,4499,8801,39.36,9110,8802,-86.3,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7268,"NAD83(2011) / InGCS Boone-Hendricks (ftUS)",9003,6318,7154,9807,1,0,4497,8801,39.36,9110,8802,-86.3,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7269,"NAD83(2011) / InGCS Brown (m)",9001,6318,7155,9807,1,0,4499,8801,39,9110,8802,-86.18,9110,8805,1.00003,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7270,"NAD83(2011) / InGCS Brown (ftUS)",9003,6318,7156,9807,1,0,4497,8801,39,9110,8802,-86.18,9110,8805,1.00003,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7271,"NAD83(2011) / InGCS Carroll (m)",9001,6318,7157,9807,1,0,4499,8801,40.24,9110,8802,-86.39,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7272,"NAD83(2011) / InGCS Carroll (ftUS)",9003,6318,7158,9807,1,0,4497,8801,40.24,9110,8802,-86.39,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7273,"NAD83(2011) / InGCS Cass (m)",9001,6318,7159,9807,1,0,4499,8801,40.33,9110,8802,-86.24,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7274,"NAD83(2011) / InGCS Cass (ftUS)",9003,6318,7160,9807,1,0,4497,8801,40.33,9110,8802,-86.24,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7275,"NAD83(2011) / InGCS Clark-Floyd-Scott (m)",9001,6318,7161,9807,1,0,4499,8801,38.09,9110,8802,-85.36,9110,8805,1.000021,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7276,"NAD83(2011) / InGCS Clark-Floyd-Scott (ftUS)",9003,6318,7162,9807,1,0,4497,8801,38.09,9110,8802,-85.36,9110,8805,1.000021,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7277,"NAD83(2011) / InGCS Clay (m)",9001,6318,7163,9807,1,0,4499,8801,39.09,9110,8802,-87.09,9110,8805,1.000024,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7278,"NAD83(2011) / InGCS Clay (ftUS)",9003,6318,7164,9807,1,0,4497,8801,39.09,9110,8802,-87.09,9110,8805,1.000024,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7279,"NAD83(2011) / InGCS Clinton (m)",9001,6318,7165,9807,1,0,4499,8801,40.09,9110,8802,-86.36,9110,8805,1.000032,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7280,"NAD83(2011) / InGCS Clinton (ftUS)",9003,6318,7166,9807,1,0,4497,8801,40.09,9110,8802,-86.36,9110,8805,1.000032,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7281,"NAD83(2011) / InGCS Crawford-Lawrence-Orange (m)",9001,6318,7167,9807,1,0,4499,8801,38.06,9110,8802,-86.3,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7282,"NAD83(2011) / InGCS Crawford-Lawrence-Orange (ftUS)",9003,6318,7168,9807,1,0,4497,8801,38.06,9110,8802,-86.3,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7283,"NAD83(2011) / InGCS Daviess-Greene (m)",9001,6318,7169,9807,1,0,4499,8801,38.27,9110,8802,-87.06,9110,8805,1.000018,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7284,"NAD83(2011) / InGCS Daviess-Greene (ftUS)",9003,6318,7170,9807,1,0,4497,8801,38.27,9110,8802,-87.06,9110,8805,1.000018,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7285,"NAD83(2011) / InGCS Dearborn-Ohio-Switzerland (m)",9001,6318,7171,9807,1,0,4499,8801,38.39,9110,8802,-84.54,9110,8805,1.000029,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7286,"NAD83(2011) / InGCS Dearborn-Ohio-Switzerland (ftUS)",9003,6318,7172,9807,1,0,4497,8801,38.39,9110,8802,-84.54,9110,8805,1.000029,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7287,"NAD83(2011) / InGCS Decatur-Rush (m)",9001,6318,7173,9807,1,0,4499,8801,39.06,9110,8802,-85.39,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7288,"NAD83(2011) / InGCS Decatur-Rush (ftUS)",9003,6318,7174,9807,1,0,4497,8801,39.06,9110,8802,-85.39,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7289,"NAD83(2011) / InGCS DeKalb (m)",9001,6318,7175,9807,1,0,4499,8801,41.15,9110,8802,-84.57,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7290,"NAD83(2011) / InGCS DeKalb (ftUS)",9003,6318,7176,9807,1,0,4497,8801,41.15,9110,8802,-84.57,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7291,"NAD83(2011) / InGCS Dubois-Martin (m)",9001,6318,7177,9807,1,0,4499,8801,38.12,9110,8802,-86.57,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7292,"NAD83(2011) / InGCS Dubois-Martin (ftUS)",9003,6318,7178,9807,1,0,4497,8801,38.12,9110,8802,-86.57,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7293,"NAD83(2011) / InGCS Elkhart-Kosciusko-Wabash (m)",9001,6318,7179,9807,1,0,4499,8801,40.39,9110,8802,-85.51,9110,8805,1.000033,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7294,"NAD83(2011) / InGCS Elkhart-Kosciusko-Wabash (ftUS)",9003,6318,7180,9807,1,0,4497,8801,40.39,9110,8802,-85.51,9110,8805,1.000033,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7295,"NAD83(2011) / InGCS Fayette-Franklin-Union (m)",9001,6318,7181,9807,1,0,4499,8801,39.15,9110,8802,-85.03,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7296,"NAD83(2011) / InGCS Fayette-Franklin-Union (ftUS)",9003,6318,7182,9807,1,0,4497,8801,39.15,9110,8802,-85.03,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7297,"NAD83(2011) / InGCS Fountain-Warren (m)",9001,6318,7183,9807,1,0,4499,8801,39.57,9110,8802,-87.18,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7298,"NAD83(2011) / InGCS Fountain-Warren (ftUS)",9003,6318,7184,9807,1,0,4497,8801,39.57,9110,8802,-87.18,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7299,"NAD83(2011) / InGCS Fulton-Marshall-St. Joseph (m)",9001,6318,7185,9807,1,0,4499,8801,40.54,9110,8802,-86.18,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7300,"NAD83(2011) / InGCS Fulton-Marshall-St. Joseph (ftUS)",9003,6318,7186,9807,1,0,4497,8801,40.54,9110,8802,-86.18,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7301,"NAD83(2011) / InGCS Gibson (m)",9001,6318,7187,9807,1,0,4499,8801,38.09,9110,8802,-87.39,9110,8805,1.000013,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7302,"NAD83(2011) / InGCS Gibson (ftUS)",9003,6318,7188,9807,1,0,4497,8801,38.09,9110,8802,-87.39,9110,8805,1.000013,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7303,"NAD83(2011) / InGCS Grant (m)",9001,6318,7189,9807,1,0,4499,8801,40.21,9110,8802,-85.42,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7304,"NAD83(2011) / InGCS Grant (ftUS)",9003,6318,7190,9807,1,0,4497,8801,40.21,9110,8802,-85.42,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7305,"NAD83(2011) / InGCS Hamilton-Tipton (m)",9001,6318,7191,9807,1,0,4499,8801,39.54,9110,8802,-86,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7306,"NAD83(2011) / InGCS Hamilton-Tipton (ftUS)",9003,6318,7192,9807,1,0,4497,8801,39.54,9110,8802,-86,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7307,"NAD83(2011) / InGCS Hancock-Madison (m)",9001,6318,7193,9807,1,0,4499,8801,39.39,9110,8802,-85.48,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7308,"NAD83(2011) / InGCS Hancock-Madison (ftUS)",9003,6318,7194,9807,1,0,4497,8801,39.39,9110,8802,-85.48,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7309,"NAD83(2011) / InGCS Harrison-Washington (m)",9001,6318,7195,9807,1,0,4499,8801,37.57,9110,8802,-86.09,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7310,"NAD83(2011) / InGCS Harrison-Washington (ftUS)",9003,6318,7196,9807,1,0,4497,8801,37.57,9110,8802,-86.09,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7311,"NAD83(2011) / InGCS Henry (m)",9001,6318,7197,9807,1,0,4499,8801,39.45,9110,8802,-85.27,9110,8805,1.000043,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7312,"NAD83(2011) / InGCS Henry (ftUS)",9003,6318,7198,9807,1,0,4497,8801,39.45,9110,8802,-85.27,9110,8805,1.000043,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7313,"NAD83(2011) / InGCS Howard-Miami (m)",9001,6318,7199,9807,1,0,4499,8801,40.21,9110,8802,-86.09,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7314,"NAD83(2011) / InGCS Howard-Miami (ftUS)",9003,6318,7200,9807,1,0,4497,8801,40.21,9110,8802,-86.09,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7315,"NAD83(2011) / InGCS Huntington-Whitley (m)",9001,6318,7201,9807,1,0,4499,8801,40.39,9110,8802,-85.3,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7316,"NAD83(2011) / InGCS Huntington-Whitley (ftUS)",9003,6318,7202,9807,1,0,4497,8801,40.39,9110,8802,-85.3,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7317,"NAD83(2011) / InGCS Jackson (m)",9001,6318,7203,9807,1,0,4499,8801,38.42,9110,8802,-85.57,9110,8805,1.000022,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7318,"NAD83(2011) / InGCS Jackson (ftUS)",9003,6318,7204,9807,1,0,4497,8801,38.42,9110,8802,-85.57,9110,8805,1.000022,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7319,"NAD83(2011) / InGCS Jasper-Porter (m)",9001,6318,7205,9807,1,0,4499,8801,40.42,9110,8802,-87.06,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7320,"NAD83(2011) / InGCS Jasper-Porter (ftUS)",9003,6318,7206,9807,1,0,4497,8801,40.42,9110,8802,-87.06,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7321,"NAD83(2011) / InGCS Jay (m)",9001,6318,7207,9807,1,0,4499,8801,40.18,9110,8802,-85,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7322,"NAD83(2011) / InGCS Jay (ftUS)",9003,6318,7208,9807,1,0,4497,8801,40.18,9110,8802,-85,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7323,"NAD83(2011) / InGCS Jefferson (m)",9001,6318,7209,9807,1,0,4499,8801,38.33,9110,8802,-85.21,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7324,"NAD83(2011) / InGCS Jefferson (ftUS)",9003,6318,7210,9807,1,0,4497,8801,38.33,9110,8802,-85.21,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7325,"NAD83(2011) / InGCS Jennings (m)",9001,6318,7211,9807,1,0,4499,8801,38.48,9110,8802,-85.48,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7326,"NAD83(2011) / InGCS Jennings (ftUS)",9003,6318,7212,9807,1,0,4497,8801,38.48,9110,8802,-85.48,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7327,"NAD83(2011) / InGCS Johnson-Marion (m)",9001,6318,7213,9807,1,0,4499,8801,39.18,9110,8802,-86.09,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7328,"NAD83(2011) / InGCS Johnson-Marion (ftUS)",9003,6318,7214,9807,1,0,4497,8801,39.18,9110,8802,-86.09,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7329,"NAD83(2011) / InGCS Knox (m)",9001,6318,7215,9807,1,0,4499,8801,38.24,9110,8802,-87.27,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7330,"NAD83(2011) / InGCS Knox (ftUS)",9003,6318,7216,9807,1,0,4497,8801,38.24,9110,8802,-87.27,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7331,"NAD83(2011) / InGCS LaGrange-Noble (m)",9001,6318,7217,9807,1,0,4499,8801,41.15,9110,8802,-85.27,9110,8805,1.000037,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7332,"NAD83(2011) / InGCS LaGrange-Noble (ftUS)",9003,6318,7218,9807,1,0,4497,8801,41.15,9110,8802,-85.27,9110,8805,1.000037,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7333,"NAD83(2011) / InGCS Lake-Newton (m)",9001,6318,7219,9807,1,0,4499,8801,40.42,9110,8802,-87.24,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7334,"NAD83(2011) / InGCS Lake-Newton (ftUS)",9003,6318,7220,9807,1,0,4497,8801,40.42,9110,8802,-87.24,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7335,"NAD83(2011) / InGCS LaPorte-Pulaski-Starke (m)",9001,6318,7221,9807,1,0,4499,8801,40.54,9110,8802,-86.45,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7336,"NAD83(2011) / InGCS LaPorte-Pulaski-Starke (ftUS)",9003,6318,7222,9807,1,0,4497,8801,40.54,9110,8802,-86.45,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7337,"NAD83(2011) / InGCS Monroe-Morgan (m)",9001,6318,7223,9807,1,0,4499,8801,38.57,9110,8802,-86.3,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7338,"NAD83(2011) / InGCS Monroe-Morgan (ftUS)",9003,6318,7224,9807,1,0,4497,8801,38.57,9110,8802,-86.3,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7339,"NAD83(2011) / InGCS Montgomery-Putnam (m)",9001,6318,7225,9807,1,0,4499,8801,39.27,9110,8802,-86.57,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7340,"NAD83(2011) / InGCS Montgomery-Putnam (ftUS)",9003,6318,7226,9807,1,0,4497,8801,39.27,9110,8802,-86.57,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7341,"NAD83(2011) / InGCS Owen (m)",9001,6318,7227,9807,1,0,4499,8801,39.09,9110,8802,-86.54,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7342,"NAD83(2011) / InGCS Owen (ftUS)",9003,6318,7228,9807,1,0,4497,8801,39.09,9110,8802,-86.54,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7343,"NAD83(2011) / InGCS Parke-Vermillion (m)",9001,6318,7229,9807,1,0,4499,8801,39.36,9110,8802,-87.21,9110,8805,1.000022,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7344,"NAD83(2011) / InGCS Parke-Vermillion (ftUS)",9003,6318,7230,9807,1,0,4497,8801,39.36,9110,8802,-87.21,9110,8805,1.000022,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7345,"NAD83(2011) / InGCS Perry (m)",9001,6318,7231,9807,1,0,4499,8801,37.48,9110,8802,-86.42,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7346,"NAD83(2011) / InGCS Perry (ftUS)",9003,6318,7232,9807,1,0,4497,8801,37.48,9110,8802,-86.42,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7347,"NAD83(2011) / InGCS Pike-Warrick (m)",9001,6318,7233,9807,1,0,4499,8801,37.51,9110,8802,-87.18,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7348,"NAD83(2011) / InGCS Pike-Warrick (ftUS)",9003,6318,7234,9807,1,0,4497,8801,37.51,9110,8802,-87.18,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7349,"NAD83(2011) / InGCS Posey (m)",9001,6318,7235,9807,1,0,4499,8801,37.45,9110,8802,-87.57,9110,8805,1.000013,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7350,"NAD83(2011) / InGCS Posey (ftUS)",9003,6318,7236,9807,1,0,4497,8801,37.45,9110,8802,-87.57,9110,8805,1.000013,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7351,"NAD83(2011) / InGCS Randolph-Wayne (m)",9001,6318,7237,9807,1,0,4499,8801,39.42,9110,8802,-85.03,9110,8805,1.000044,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7352,"NAD83(2011) / InGCS Randolph-Wayne (ftUS)",9003,6318,7238,9807,1,0,4497,8801,39.42,9110,8802,-85.03,9110,8805,1.000044,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7353,"NAD83(2011) / InGCS Ripley (m)",9001,6318,7239,9807,1,0,4499,8801,38.54,9110,8802,-85.18,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7354,"NAD83(2011) / InGCS Ripley (ftUS)",9003,6318,7240,9807,1,0,4497,8801,38.54,9110,8802,-85.18,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7355,"NAD83(2011) / InGCS Shelby (m)",9001,6318,7241,9807,1,0,4499,8801,39.18,9110,8802,-85.54,9110,8805,1.00003,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7356,"NAD83(2011) / InGCS Shelby (ftUS)",9003,6318,7242,9807,1,0,4497,8801,39.18,9110,8802,-85.54,9110,8805,1.00003,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7357,"NAD83(2011) / InGCS Spencer (m)",9001,6318,7243,9807,1,0,4499,8801,37.45,9110,8802,-87.03,9110,8805,1.000014,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7358,"NAD83(2011) / InGCS Spencer (ftUS)",9003,6318,7244,9807,1,0,4497,8801,37.45,9110,8802,-87.03,9110,8805,1.000014,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7359,"NAD83(2011) / InGCS Steuben (m)",9001,6318,7245,9807,1,0,4499,8801,41.3,9110,8802,-85,9110,8805,1.000041,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7360,"NAD83(2011) / InGCS Steuben (ftUS)",9003,6318,7246,9807,1,0,4497,8801,41.3,9110,8802,-85,9110,8805,1.000041,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7361,"NAD83(2011) / InGCS Sullivan (m)",9001,6318,7247,9807,1,0,4499,8801,38.54,9110,8802,-87.3,9110,8805,1.000017,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7362,"NAD83(2011) / InGCS Sullivan (ftUS)",9003,6318,7248,9807,1,0,4497,8801,38.54,9110,8802,-87.3,9110,8805,1.000017,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7363,"NAD83(2011) / InGCS Tippecanoe-White (m)",9001,6318,7249,9807,1,0,4499,8801,40.12,9110,8802,-86.54,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7364,"NAD83(2011) / InGCS Tippecanoe-White (ftUS)",9003,6318,7250,9807,1,0,4497,8801,40.12,9110,8802,-86.54,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7365,"NAD83(2011) / InGCS Vanderburgh (m)",9001,6318,7251,9807,1,0,4499,8801,37.48,9110,8802,-87.33,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7366,"NAD83(2011) / InGCS Vanderburgh (ftUS)",9003,6318,7252,9807,1,0,4497,8801,37.48,9110,8802,-87.33,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7367,"NAD83(2011) / InGCS Vigo (m)",9001,6318,7253,9807,1,0,4499,8801,39.15,9110,8802,-87.27,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7368,"NAD83(2011) / InGCS Vigo (ftUS)",9003,6318,7254,9807,1,0,4497,8801,39.15,9110,8802,-87.27,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7369,"NAD83(2011) / InGCS Wells (m)",9001,6318,7255,9807,1,0,4499,8801,40.33,9110,8802,-85.15,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,
-7370,"NAD83(2011) / InGCS Wells (ftUS)",9003,6318,7256,9807,1,0,4497,8801,40.33,9110,8802,-85.15,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,
-7374,"ONGD14 / UTM zone 39N",9001,7373,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-7375,"ONGD14 / UTM zone 40N",9001,7373,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-7376,"ONGD14 / UTM zone 41N",9001,7373,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-7528,"NAD83(2011) / WISCRS Adams and Juneau (m)",9001,6318,7484,9807,1,0,4499,8801,43.22,9110,8802,-90,9110,8805,1.0000365285,9201,8806,147218.6942,9001,8807,0.0037,9001,,,,,,
-7529,"NAD83(2011) / WISCRS Ashland (m)",9001,6318,7378,9807,1,0,4499,8801,45.4222,9110,8802,-90.372,9110,8805,1.0000495683,9201,8806,172821.9461,9001,8807,0.0017,9001,,,,,,
-7530,"NAD83(2011) / WISCRS Barron (m)",9001,6318,7426,9807,1,0,4499,8801,45.08,9110,8802,-91.51,9110,8805,1.0000486665,9201,8806,93150,9001,8807,0.0029,9001,,,,,,
-7531,"NAD83(2011) / WISCRS Bayfield (m)",9001,6318,7380,9801,1,0,4499,8801,46.4010734158,9110,8802,-91.091,9110,8805,1.0000331195,9201,8806,228600.4575,9001,8807,148551.4837,9001,,,,,,
-7532,"NAD83(2011) / WISCRS Brown (m)",9001,6318,7428,9807,1,0,4499,8801,43,9102,8802,-88,9102,8805,1.00002,9201,8806,31600,9001,8807,4600,9001,,,,,,
-7533,"NAD83(2011) / WISCRS Buffalo (m)",9001,6318,7430,9807,1,0,4499,8801,43.2853,9110,8802,-91.475,9110,8805,1.0000382778,9201,8806,175260.3502,9001,8807,0.0048,9001,,,,,,
-7534,"NAD83(2011) / WISCRS Burnett (m)",9001,6318,7382,9801,1,0,4499,8801,45.5355373517,9110,8802,-92.2728,9110,8805,1.0000383841,9201,8806,64008.1276,9001,8807,59445.9043,9001,,,,,,
-7535,"NAD83(2011) / WISCRS Calumet, Fond du Lac, Outagamie and Winnebago (m)",9001,6318,7486,9807,1,0,4499,8801,42.431,9110,8802,-88.3,9110,8805,1.0000286569,9201,8806,244754.8893,9001,8807,0.0049,9001,,,,,,
-7536,"NAD83(2011) / WISCRS Chippewa (m)",9001,6318,7432,9801,1,0,4499,8801,44.5840284835,9110,8802,-91.174,9110,8805,1.0000391127,9201,8806,60045.72,9001,8807,44091.4346,9001,,,,,,
-7537,"NAD83(2011) / WISCRS Clark (m)",9001,6318,7434,9807,1,0,4499,8801,43.36,9110,8802,-90.423,9110,8805,1.0000463003,9201,8806,199949.1989,9001,8807,0.0086,9001,,,,,,
-7538,"NAD83(2011) / WISCRS Columbia (m)",9001,6318,7488,9801,1,0,4499,8801,43.2745167925,9110,8802,-89.234,9110,8805,1.00003498,9201,8806,169164.3381,9001,8807,111569.6134,9001,,,,,,
-7539,"NAD83(2011) / WISCRS Crawford (m)",9001,6318,7490,9801,1,0,4499,8801,43.1200200178,9110,8802,-90.562,9110,8805,1.0000349151,9201,8806,113690.6274,9001,8807,53703.1201,9001,,,,,,
-7540,"NAD83(2011) / WISCRS Dane (m)",9001,6318,7492,9801,1,0,4499,8801,43.0410257735,9110,8802,-89.252,9110,8805,1.0000384786,9201,8806,247193.2944,9001,8807,146591.9896,9001,,,,,,
-7541,"NAD83(2011) / WISCRS Dodge and Jefferson (m)",9001,6318,7494,9807,1,0,4499,8801,41.282,9110,8802,-88.463,9110,8805,1.0000346418,9201,8806,263347.7263,9001,8807,0.0076,9001,,,,,,
-7542,"NAD83(2011) / WISCRS Door (m)",9001,6318,7436,9807,1,0,4499,8801,44.24,9110,8802,-87.162,9110,8805,1.0000187521,9201,8806,158801.1176,9001,8807,0.0023,9001,,,,,,
-7543,"NAD83(2011) / WISCRS Douglas (m)",9001,6318,7384,9807,1,0,4499,8801,45.53,9110,8802,-91.55,9110,8805,1.0000385418,9201,8806,59131.3183,9001,8807,0.0041,9001,,,,,,
-7544,"NAD83(2011) / WISCRS Dunn (m)",9001,6318,7438,9807,1,0,4499,8801,44.243,9110,8802,-91.534,9110,8805,1.0000410324,9201,8806,51816.104,9001,8807,0.003,9001,,,,,,
-7545,"NAD83(2011) / WISCRS Eau Claire (m)",9001,6318,7440,9801,1,0,4499,8801,44.5220212055,9110,8802,-91.172,9110,8805,1.000035079,9201,8806,120091.4402,9001,8807,91687.9239,9001,,,,,,
-7546,"NAD83(2011) / WISCRS Florence (m)",9001,6318,7386,9807,1,0,4499,8801,45.262,9110,8802,-88.083,9110,8805,1.0000552095,9201,8806,133502.6683,9001,8807,0.0063,9001,,,,,,
-7547,"NAD83(2011) / WISCRS Forest (m)",9001,6318,7388,9807,1,0,4499,8801,44.002,9110,8802,-88.38,9110,8805,1.0000673004,9201,8806,275844.5533,9001,8807,0.0157,9001,,,,,,
-7548,"NAD83(2011) / WISCRS Grant (m)",9001,6318,7496,9807,1,0,4499,8801,41.244,9110,8802,-90.48,9110,8805,1.0000349452,9201,8806,242316.4841,9001,8807,0.01,9001,,,,,,
-7549,"NAD83(2011) / WISCRS Green and Lafayette (m)",9001,6318,7498,9801,1,0,4499,8801,42.3815224197,9110,8802,-89.502,9110,8805,1.0000390487,9201,8806,170078.7403,9001,8807,45830.2947,9001,,,,,,
-7550,"NAD83(2011) / WISCRS Green Lake and Marquette (m)",9001,6318,7500,9801,1,0,4499,8801,43.4825200424,9110,8802,-89.143,9110,8805,1.0000344057,9201,8806,150876.3018,9001,8807,79170.7795,9001,,,,,,
-7551,"NAD83(2011) / WISCRS Iowa (m)",9001,6318,7502,9807,1,0,4499,8801,42.322,9110,8802,-90.094,9110,8805,1.0000394961,9201,8806,113081.0261,9001,8807,0.0045,9001,,,,,,
-7552,"NAD83(2011) / WISCRS Iron (m)",9001,6318,7390,9807,1,0,4499,8801,45.26,9110,8802,-90.152,9110,8805,1.0000677153,9201,8806,220980.4419,9001,8807,0.0085,9001,,,,,,
-7553,"NAD83(2011) / WISCRS Jackson (m)",9001,6318,7450,9807,1,0,4499,8801,44.151200646,9110,8802,-90.503946747,9110,8805,1.0000353,9201,8806,27000,9001,8807,25000,9001,,,,,,
-7554,"NAD83(2011) / WISCRS Kenosha, Milwaukee, Ozaukee and Racine (m)",9001,6318,7504,9807,1,0,4499,8801,42.13,9110,8802,-87.534,9110,8805,1.0000260649,9201,8806,185928.3728,9001,8807,0.0009,9001,,,,,,
-7555,"NAD83(2011) / WISCRS Kewaunee, Manitowoc and Sheboygan (m)",9001,6318,7506,9807,1,0,4499,8801,43.16,9110,8802,-87.33,9110,8805,1.0000233704,9201,8806,79857.7614,9001,8807,0.0012,9001,,,,,,
-7556,"NAD83(2011) / WISCRS La Crosse (m)",9001,6318,7508,9807,1,0,4499,8801,43.2704,9110,8802,-91.19,9110,8805,1.0000319985,9201,8806,130454.6598,9001,8807,0.0033,9001,,,,,,
-7557,"NAD83(2011) / WISCRS Langlade (m)",9001,6318,7452,9801,1,0,4499,8801,45.0915253579,9110,8802,-89.02,9110,8805,1.0000627024,9201,8806,198425.197,9001,8807,105279.7829,9001,,,,,,
-7558,"NAD83(2011) / WISCRS Lincoln (m)",9001,6318,7454,9807,1,0,4499,8801,44.504,9110,8802,-89.44,9110,8805,1.0000599003,9201,8806,116129.0323,9001,8807,0.0058,9001,,,,,,
-7559,"NAD83(2011) / WISCRS Marathon (m)",9001,6318,7456,9801,1,0,4499,8801,44.5403255925,9110,8802,-89.4612,9110,8805,1.000053289,9201,8806,74676.1493,9001,8807,55049.2669,9001,,,,,,
-7560,"NAD83(2011) / WISCRS Marinette (m)",9001,6318,7458,9807,1,0,4499,8801,44.413,9110,8802,-87.424,9110,8805,1.0000234982,9201,8806,238658.8794,9001,8807,0.0032,9001,,,,,,
-7561,"NAD83(2011) / WISCRS Menominee (m)",9001,6318,7460,9807,1,0,4499,8801,44.43,9110,8802,-88.25,9110,8805,1.0000362499,9201,8806,105461.0121,9001,8807,0.0029,9001,,,,,,
-7562,"NAD83(2011) / WISCRS Monroe (m)",9001,6318,7510,9801,1,0,4499,8801,44.0000266143,9110,8802,-90.383,9110,8805,1.0000434122,9201,8806,204521.209,9001,8807,121923.9861,9001,,,,,,
-7563,"NAD83(2011) / WISCRS Oconto (m)",9001,6318,7462,9807,1,0,4499,8801,44.235,9110,8802,-87.543,9110,8805,1.0000236869,9201,8806,182880.3676,9001,8807,0.0033,9001,,,,,,
-7564,"NAD83(2011) / WISCRS Oneida (m)",9001,6318,7392,9801,1,0,4499,8801,45.4215205573,9110,8802,-89.324,9110,8805,1.0000686968,9201,8806,70104.1401,9001,8807,57588.0346,9001,,,,,,
-7565,"NAD83(2011) / WISCRS Pepin and Pierce (m)",9001,6318,7464,9801,1,0,4499,8801,44.3810135939,9110,8802,-92.134,9110,8805,1.0000362977,9201,8806,167640.3354,9001,8807,86033.0876,9001,,,,,,
-7566,"NAD83(2011) / WISCRS Polk (m)",9001,6318,7466,9807,1,0,4499,8801,44.394,9110,8802,-92.38,9110,8805,1.0000433849,9201,8806,141732.2823,9001,8807,0.0059,9001,,,,,,
-7567,"NAD83(2011) / WISCRS Portage (m)",9001,6318,7468,9801,1,0,4499,8801,44.2500566311,9110,8802,-89.3,9110,8805,1.000039936,9201,8806,56388.1128,9001,8807,50022.1874,9001,,,,,,
-7568,"NAD83(2011) / WISCRS Price (m)",9001,6318,7394,9807,1,0,4499,8801,44.332,9110,8802,-90.292,9110,8805,1.0000649554,9201,8806,227990.8546,9001,8807,0.0109,9001,,,,,,
-7569,"NAD83(2011) / WISCRS Richland (m)",9001,6318,7512,9801,1,0,4499,8801,43.1920326539,9110,8802,-90.255,9110,8805,1.0000375653,9201,8806,202387.6048,9001,8807,134255.4253,9001,,,,,,
-7570,"NAD83(2011) / WISCRS Rock (m)",9001,6318,7514,9807,1,0,4499,8801,41.564,9110,8802,-89.042,9110,8805,1.0000337311,9201,8806,146304.2926,9001,8807,0.0068,9001,,,,,,
-7571,"NAD83(2011) / WISCRS Rusk (m)",9001,6318,7470,9807,1,0,4499,8801,43.551,9110,8802,-91.04,9110,8805,1.0000495976,9201,8806,250546.1013,9001,8807,0.0234,9001,,,,,,
-7572,"NAD83(2011) / WISCRS Sauk (m)",9001,6318,7516,9807,1,0,4499,8801,42.491,9110,8802,-89.54,9110,8805,1.0000373868,9201,8806,185623.5716,9001,8807,0.0051,9001,,,,,,
-7573,"NAD83(2011) / WISCRS Sawyer (m)",9001,6318,7396,9801,1,0,4499,8801,45.5400356873,9110,8802,-91.07,9110,8805,1.0000573461,9201,8806,216713.2336,9001,8807,120734.1631,9001,,,,,,
-7574,"NAD83(2011) / WISCRS Shawano (m)",9001,6318,7472,9807,1,0,4499,8801,44.021,9110,8802,-88.362,9110,8805,1.000032144,9201,8806,262433.3253,9001,8807,0.0096,9001,,,,,,
-7575,"NAD83(2011) / WISCRS St. Croix (m)",9001,6318,7474,9807,1,0,4499,8801,44.021,9110,8802,-92.38,9110,8805,1.0000381803,9201,8806,165506.7302,9001,8807,0.0103,9001,,,,,,
-7576,"NAD83(2011) / WISCRS Taylor (m)",9001,6318,7476,9801,1,0,4499,8801,45.1040159509,9110,8802,-90.29,9110,8805,1.0000597566,9201,8806,187147.5744,9001,8807,107746.7522,9001,,,,,,
-7577,"NAD83(2011) / WISCRS Trempealeau (m)",9001,6318,7478,9807,1,0,4499,8801,43.094,9110,8802,-91.22,9110,8805,1.0000361538,9201,8806,256946.9138,9001,8807,0.0041,9001,,,,,,
-7578,"NAD83(2011) / WISCRS Vernon (m)",9001,6318,7518,9801,1,0,4499,8801,43.3430118583,9110,8802,-90.47,9110,8805,1.0000408158,9201,8806,222504.4451,9001,8807,47532.0602,9001,,,,,,
-7579,"NAD83(2011) / WISCRS Vilas (m)",9001,6318,7398,9801,1,0,4499,8801,46.0440238726,9110,8802,-89.292,9110,8805,1.0000730142,9201,8806,134417.0689,9001,8807,50337.1092,9001,,,,,,
-7580,"NAD83(2011) / WISCRS Walworth (m)",9001,6318,7520,9801,1,0,4499,8801,42.4010063549,9110,8802,-88.323,9110,8805,1.0000367192,9201,8806,232562.8651,9001,8807,111088.2224,9001,,,,,,
-7581,"NAD83(2011) / WISCRS Washburn (m)",9001,6318,7424,9801,1,0,4499,8801,45.57403914,9110,8802,-91.47,9110,8805,1.0000475376,9201,8806,234086.8682,9001,8807,188358.6058,9001,,,,,,
-7582,"NAD83(2011) / WISCRS Washington (m)",9001,6318,7522,9807,1,0,4499,8801,42.5505,9110,8802,-88.035,9110,8805,1.00003738,9201,8806,120091.4415,9001,8807,0.003,9001,,,,,,
-7583,"NAD83(2011) / WISCRS Waukesha (m)",9001,6318,7524,9807,1,0,4499,8801,42.341,9110,8802,-88.133,9110,8805,1.0000346179,9201,8806,208788.418,9001,8807,0.0034,9001,,,,,,
-7584,"NAD83(2011) / WISCRS Waupaca (m)",9001,6318,7480,9807,1,0,4499,8801,43.2513,9110,8802,-88.49,9110,8805,1.0000333645,9201,8806,185013.9709,9001,8807,0.007,9001,,,,,,
-7585,"NAD83(2011) / WISCRS Waushara (m)",9001,6318,7526,9801,1,0,4499,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,120091.4402,9001,8807,45069.7587,9001,,,,,,
-7586,"NAD83(2011) / WISCRS Wood (m)",9001,6318,7482,9801,1,0,4499,8801,44.214534369,9110,8802,-90,9110,8805,1.0000421209,9201,8806,208483.6173,9001,8807,134589.754,9001,,,,,,
-7587,"NAD83(2011) / WISCRS Adams and Juneau (ftUS)",9003,6318,7485,9807,1,0,4497,8801,43.22,9110,8802,-90,9110,8805,1.0000365285,9201,8806,482999.999,9003,8807,0.012,9003,,,,,,
-7588,"NAD83(2011) / WISCRS Ashland (ftUS)",9003,6318,7379,9807,1,0,4497,8801,45.4222,9110,8802,-90.372,9110,8805,1.0000495683,9201,8806,567000.001,9003,8807,0.006,9003,,,,,,
-7589,"NAD83(2011) / WISCRS Barron (ftUS)",9003,6318,7427,9807,1,0,4497,8801,45.08,9110,8802,-91.51,9110,8805,1.0000486665,9201,8806,305609.625,9003,8807,0.01,9003,,,,,,
-7590,"NAD83(2011) / WISCRS Bayfield (ftUS)",9003,6318,7381,9801,1,0,4497,8801,46.4010734158,9110,8802,-91.091,9110,8805,1.0000331195,9201,8806,750000.001,9003,8807,487372.659,9003,,,,,,
-7591,"NAD83(2011) / WISCRS Brown (ftUS)",9003,6318,7429,9807,1,0,4497,8801,43,9110,8802,-88,9110,8805,1.00002,9201,8806,103674.333,9003,8807,15091.833,9003,,,,,,
-7592,"NAD83(2011) / WISCRS Buffalo (ftUS)",9003,6318,7431,9807,1,0,4497,8801,43.2853,9110,8802,-91.475,9110,8805,1.0000382778,9201,8806,574999.999,9003,8807,0.016,9003,,,,,,
-7593,"NAD83(2011) / WISCRS Burnett (ftUS)",9003,6318,7383,9801,1,0,4497,8801,45.5355373517,9110,8802,-92.2728,9110,8805,1.0000383841,9201,8806,209999.999,9003,8807,195032.104,9003,,,,,,
-7594,"NAD83(2011) / WISCRS Calumet, Fond du Lac, Outagamie and Winnebago (ftUS)",9003,6318,7487,9807,1,0,4497,8801,42.431,9110,8802,-88.3,9110,8805,1.0000286569,9201,8806,802999.999,9003,8807,0.016,9003,,,,,,
-7595,"NAD83(2011) / WISCRS Chippewa (ftUS)",9003,6318,7433,9801,1,0,4497,8801,44.5840284835,9110,8802,-91.174,9110,8805,1.0000391127,9201,8806,197000,9003,8807,144656.648,9003,,,,,,
-7596,"NAD83(2011) / WISCRS Clark (ftUS)",9003,6318,7435,9807,1,0,4497,8801,43.36,9110,8802,-90.423,9110,8805,1.0000463003,9201,8806,655999.997,9003,8807,0.028,9003,,,,,,
-7597,"NAD83(2011) / WISCRS Columbia (ftUS)",9003,6318,7489,9801,1,0,4497,8801,43.2745167925,9110,8802,-89.234,9110,8805,1.00003498,9201,8806,554999.999,9003,8807,366041.307,9003,,,,,,
-7598,"NAD83(2011) / WISCRS Crawford (ftUS)",9003,6318,7491,9801,1,0,4497,8801,43.1200200178,9110,8802,-90.562,9110,8805,1.0000349151,9201,8806,373000,9003,8807,176190.987,9003,,,,,,
-7599,"NAD83(2011) / WISCRS Dane (ftUS)",9003,6318,7493,9801,1,0,4497,8801,43.0410257735,9110,8802,-89.252,9110,8805,1.0000384786,9201,8806,811000,9003,8807,480943.886,9003,,,,,,
-7600,"NAD83(2011) / WISCRS Dodge and Jefferson (ftUS)",9003,6318,7495,9807,1,0,4497,8801,41.282,9110,8802,-88.463,9110,8805,1.0000346418,9201,8806,863999.999,9003,8807,0.025,9003,,,,,,
-7601,"NAD83(2011) / WISCRS Door (ftUS)",9003,6318,7437,9807,1,0,4497,8801,44.24,9110,8802,-87.162,9110,8805,1.0000187521,9201,8806,521000,9003,8807,0.008,9003,,,,,,
-7602,"NAD83(2011) / WISCRS Douglas (ftUS)",9003,6318,7385,9807,1,0,4497,8801,45.53,9110,8802,-91.55,9110,8805,1.0000385418,9201,8806,194000,9003,8807,0.013,9003,,,,,,
-7603,"NAD83(2011) / WISCRS Dunn (ftUS)",9003,6318,7439,9807,1,0,4497,8801,44.243,9110,8802,-91.534,9110,8805,1.0000410324,9201,8806,170000.001,9003,8807,0.01,9003,,,,,,
-7604,"NAD83(2011) / WISCRS Eau Claire (ftUS)",9003,6318,7441,9801,1,0,4497,8801,44.5220212055,9110,8802,-91.172,9110,8805,1.000035079,9201,8806,394000,9003,8807,300812.797,9003,,,,,,
-7605,"NAD83(2011) / WISCRS Florence (ftUS)",9003,6318,7387,9807,1,0,4497,8801,45.262,9110,8802,-88.083,9110,8805,1.0000552095,9201,8806,438000.004,9003,8807,0.021,9003,,,,,,
-7606,"NAD83(2011) / WISCRS Forest (ftUS)",9003,6318,7389,9807,1,0,4497,8801,44.002,9110,8802,-88.38,9110,8805,1.0000673004,9201,8806,905000.005,9003,8807,0.052,9003,,,,,,
-7607,"NAD83(2011) / WISCRS Grant (ftUS)",9003,6318,7497,9807,1,0,4497,8801,41.244,9110,8802,-90.48,9110,8805,1.0000349452,9201,8806,794999.998,9003,8807,0.033,9003,,,,,,
-7608,"NAD83(2011) / WISCRS Green and Lafayette (ftUS)",9003,6318,7499,9801,1,0,4497,8801,42.3815224197,9110,8802,-89.502,9110,8805,1.0000390487,9201,8806,558000,9003,8807,150361.559,9003,,,,,,
-7609,"NAD83(2011) / WISCRS Green Lake and Marquette (ftUS)",9003,6318,7501,9801,1,0,4497,8801,43.4825200424,9110,8802,-89.143,9110,8805,1.0000344057,9201,8806,495000,9003,8807,259746.132,9003,,,,,,
-7610,"NAD83(2011) / WISCRS Iowa (ftUS)",9003,6318,7503,9807,1,0,4497,8801,42.322,9110,8802,-90.094,9110,8805,1.0000394961,9201,8806,371000,9003,8807,0.015,9003,,,,,,
-7611,"NAD83(2011) / WISCRS Iron (ftUS)",9003,6318,7391,9807,1,0,4497,8801,45.26,9110,8802,-90.152,9110,8805,1.0000677153,9201,8806,725000,9003,8807,0.028,9003,,,,,,
-7612,"NAD83(2011) / WISCRS Jackson (ftUS)",9003,6318,7451,9807,1,0,4497,8801,44.151200646,9110,8802,-90.503946747,9110,8805,1.0000353,9201,8806,88582.5,9003,8807,82020.833,9003,,,,,,
-7613,"NAD83(2011) / WISCRS Kenosha, Milwaukee, Ozaukee and Racine (ftUS)",9003,6318,7505,9807,1,0,4497,8801,42.13,9110,8802,-87.534,9110,8805,1.0000260649,9201,8806,610000.003,9003,8807,0.003,9003,,,,,,
-7614,"NAD83(2011) / WISCRS Kewaunee, Manitowoc and Sheboygan (ftUS)",9003,6318,7507,9807,1,0,4497,8801,43.16,9110,8802,-87.33,9110,8805,1.0000233704,9201,8806,262000.006,9003,8807,0.004,9003,,,,,,
-7615,"NAD83(2011) / WISCRS La Crosse (ftUS)",9003,6318,7509,9807,1,0,4497,8801,43.2704,9110,8802,-91.19,9110,8805,1.0000319985,9201,8806,427999.996,9003,8807,0.011,9003,,,,,,
-7616,"NAD83(2011) / WISCRS Langlade (ftUS)",9003,6318,7453,9801,1,0,4497,8801,45.0915253579,9110,8802,-89.02,9110,8805,1.0000627024,9201,8806,651000,9003,8807,345405.421,9003,,,,,,
-7617,"NAD83(2011) / WISCRS Lincoln (ftUS)",9003,6318,7455,9807,1,0,4497,8801,44.504,9110,8802,-89.44,9110,8805,1.0000599003,9201,8806,381000,9003,8807,0.019,9003,,,,,,
-7618,"NAD83(2011) / WISCRS Marathon (ftUS)",9003,6318,7457,9801,1,0,4497,8801,44.5403255925,9110,8802,-89.4612,9110,8805,1.000053289,9201,8806,245000,9003,8807,180607.47,9003,,,,,,
-7619,"NAD83(2011) / WISCRS Marinette (ftUS)",9003,6318,7459,9807,1,0,4497,8801,44.413,9110,8802,-87.424,9110,8805,1.0000234982,9201,8806,783000.007,9003,8807,0.01,9003,,,,,,
-7620,"NAD83(2011) / WISCRS Menominee (ftUS)",9003,6318,7461,9807,1,0,4497,8801,44.43,9110,8802,-88.25,9110,8805,1.0000362499,9201,8806,346000.004,9003,8807,0.01,9003,,,,,,
-7621,"NAD83(2011) / WISCRS Monroe (ftUS)",9003,6318,7511,9801,1,0,4497,8801,44.0000266143,9110,8802,-90.383,9110,8805,1.0000434122,9201,8806,671000,9003,8807,400012.278,9003,,,,,,
-7622,"NAD83(2011) / WISCRS Oconto (ftUS)",9003,6318,7463,9807,1,0,4497,8801,44.235,9110,8802,-87.543,9110,8805,1.0000236869,9201,8806,600000.006,9003,8807,0.011,9003,,,,,,
-7623,"NAD83(2011) / WISCRS Oneida (ftUS)",9003,6318,7393,9801,1,0,4497,8801,45.4215205573,9110,8802,-89.324,9110,8805,1.0000686968,9201,8806,230000,9003,8807,188936.744,9003,,,,,,
-7624,"NAD83(2011) / WISCRS Pepin and Pierce (ftUS)",9003,6318,7465,9801,1,0,4497,8801,44.3810135939,9110,8802,-92.134,9110,8805,1.0000362977,9201,8806,550000,9003,8807,282260.222,9003,,,,,,
-7625,"NAD83(2011) / WISCRS Polk (ftUS)",9003,6318,7467,9807,1,0,4497,8801,44.394,9110,8802,-92.38,9110,8805,1.0000433849,9201,8806,464999.996,9003,8807,0.019,9003,,,,,,
-7626,"NAD83(2011) / WISCRS Portage (ftUS)",9003,6318,7469,9801,1,0,4497,8801,44.2500566311,9110,8802,-89.3,9110,8805,1.000039936,9201,8806,185000,9003,8807,164114.46,9003,,,,,,
-7627,"NAD83(2011) / WISCRS Price (ftUS)",9003,6318,7395,9807,1,0,4497,8801,44.332,9110,8802,-90.292,9110,8805,1.0000649554,9201,8806,747999.995,9003,8807,0.036,9003,,,,,,
-7628,"NAD83(2011) / WISCRS Richland (ftUS)",9003,6318,7513,9801,1,0,4497,8801,43.1920326539,9110,8802,-90.255,9110,8805,1.0000375653,9201,8806,664000,9003,8807,440469.675,9003,,,,,,
-7629,"NAD83(2011) / WISCRS Rock (ftUS)",9003,6318,7515,9807,1,0,4497,8801,41.564,9110,8802,-89.042,9110,8805,1.0000337311,9201,8806,480000,9003,8807,0.022,9003,,,,,,
-7630,"NAD83(2011) / WISCRS Rusk (ftUS)",9003,6318,7471,9807,1,0,4497,8801,43.551,9110,8802,-91.04,9110,8805,1.0000495976,9201,8806,822000.001,9003,8807,0.077,9003,,,,,,
-7631,"NAD83(2011) / WISCRS Sauk (ftUS)",9003,6318,7517,9807,1,0,4497,8801,42.491,9110,8802,-89.54,9110,8805,1.0000373868,9201,8806,609000.001,9003,8807,0.017,9003,,,,,,
-7632,"NAD83(2011) / WISCRS Sawyer (ftUS)",9003,6318,7397,9801,1,0,4497,8801,45.5400356873,9110,8802,-91.07,9110,8805,1.0000573461,9201,8806,711000.001,9003,8807,396108.667,9003,,,,,,
-7633,"NAD83(2011) / WISCRS Shawano (ftUS)",9003,6318,7473,9807,1,0,4497,8801,44.021,9110,8802,-88.362,9110,8805,1.000032144,9201,8806,861000.001,9003,8807,0.031,9003,,,,,,
-7634,"NAD83(2011) / WISCRS St. Croix (ftUS)",9003,6318,7475,9807,1,0,4497,8801,44.021,9110,8802,-92.38,9110,8805,1.0000381803,9201,8806,542999.997,9003,8807,0.034,9003,,,,,,
-7635,"NAD83(2011) / WISCRS Taylor (ftUS)",9003,6318,7477,9801,1,0,4497,8801,45.1040159509,9110,8802,-90.29,9110,8805,1.0000597566,9201,8806,614000,9003,8807,353499.136,9003,,,,,,
-7636,"NAD83(2011) / WISCRS Trempealeau (ftUS)",9003,6318,7479,9807,1,0,4497,8801,43.094,9110,8802,-91.22,9110,8805,1.0000361538,9201,8806,843000,9003,8807,0.013,9003,,,,,,
-7637,"NAD83(2011) / WISCRS Vernon (ftUS)",9003,6318,7519,9801,1,0,4497,8801,43.3430118583,9110,8802,-90.47,9110,8805,1.0000408158,9201,8806,730000,9003,8807,155944.768,9003,,,,,,
-7638,"NAD83(2011) / WISCRS Vilas (ftUS)",9003,6318,7399,9801,1,0,4497,8801,46.0440238726,9110,8802,-89.292,9110,8805,1.0000730142,9201,8806,441000,9003,8807,165147.666,9003,,,,,,
-7639,"NAD83(2011) / WISCRS Walworth (ftUS)",9003,6318,7521,9801,1,0,4497,8801,42.4010063549,9110,8802,-88.323,9110,8805,1.0000367192,9201,8806,763000,9003,8807,364461.943,9003,,,,,,
-7640,"NAD83(2011) / WISCRS Washburn (ftUS)",9003,6318,7425,9801,1,0,4497,8801,45.57403914,9110,8802,-91.47,9110,8805,1.0000475376,9201,8806,768000,9003,8807,617973.193,9003,,,,,,
-7641,"NAD83(2011) / WISCRS Washington (ftUS)",9003,6318,7523,9807,1,0,4497,8801,42.5505,9110,8802,-88.035,9110,8805,1.00003738,9201,8806,394000.004,9003,8807,0.01,9003,,,,,,
-7642,"NAD83(2011) / WISCRS Waukesha (ftUS)",9003,6318,7525,9807,1,0,4497,8801,42.341,9110,8802,-88.133,9110,8805,1.0000346179,9201,8806,685000.001,9003,8807,0.011,9003,,,,,,
-7643,"NAD83(2011) / WISCRS Waupaca (ftUS)",9003,6318,7481,9807,1,0,4497,8801,43.2513,9110,8802,-88.49,9110,8805,1.0000333645,9201,8806,607000.003,9003,8807,0.023,9003,,,,,,
-7644,"NAD83(2011) / WISCRS Waushara (ftUS)",9003,6318,7527,9801,1,0,4497,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,394000,9003,8807,147866.367,9003,,,,,,
-7645,"NAD83(2011) / WISCRS Wood (ftUS)",9003,6318,7483,9801,1,0,4497,8801,44.214534369,9110,8802,-90,9110,8805,1.0000421209,9201,8806,684000.001,9003,8807,441566.551,9003,,,,,,
-20004,"Pulkovo 1995 / Gauss-Kruger zone 4",9001,4200,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-20005,"Pulkovo 1995 / Gauss-Kruger zone 5",9001,4200,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-20006,"Pulkovo 1995 / Gauss-Kruger zone 6",9001,4200,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-20007,"Pulkovo 1995 / Gauss-Kruger zone 7",9001,4200,16207,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-20008,"Pulkovo 1995 / Gauss-Kruger zone 8",9001,4200,16208,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-20009,"Pulkovo 1995 / Gauss-Kruger zone 9",9001,4200,16209,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-20010,"Pulkovo 1995 / Gauss-Kruger zone 10",9001,4200,16210,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
-20011,"Pulkovo 1995 / Gauss-Kruger zone 11",9001,4200,16211,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
-20012,"Pulkovo 1995 / Gauss-Kruger zone 12",9001,4200,16212,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
-20013,"Pulkovo 1995 / Gauss-Kruger zone 13",9001,4200,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-20014,"Pulkovo 1995 / Gauss-Kruger zone 14",9001,4200,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-20015,"Pulkovo 1995 / Gauss-Kruger zone 15",9001,4200,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-20016,"Pulkovo 1995 / Gauss-Kruger zone 16",9001,4200,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,
-20017,"Pulkovo 1995 / Gauss-Kruger zone 17",9001,4200,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,
-20018,"Pulkovo 1995 / Gauss-Kruger zone 18",9001,4200,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,
-20019,"Pulkovo 1995 / Gauss-Kruger zone 19",9001,4200,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-20020,"Pulkovo 1995 / Gauss-Kruger zone 20",9001,4200,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
-20021,"Pulkovo 1995 / Gauss-Kruger zone 21",9001,4200,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
-20022,"Pulkovo 1995 / Gauss-Kruger zone 22",9001,4200,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
-20023,"Pulkovo 1995 / Gauss-Kruger zone 23",9001,4200,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
-20024,"Pulkovo 1995 / Gauss-Kruger zone 24",9001,4200,16224,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,
-20025,"Pulkovo 1995 / Gauss-Kruger zone 25",9001,4200,16225,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
-20026,"Pulkovo 1995 / Gauss-Kruger zone 26",9001,4200,16226,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
-20027,"Pulkovo 1995 / Gauss-Kruger zone 27",9001,4200,16227,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
-20028,"Pulkovo 1995 / Gauss-Kruger zone 28",9001,4200,16228,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
-20029,"Pulkovo 1995 / Gauss-Kruger zone 29",9001,4200,16229,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
-20030,"Pulkovo 1995 / Gauss-Kruger zone 30",9001,4200,16230,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
-20031,"Pulkovo 1995 / Gauss-Kruger zone 31",9001,4200,16231,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
-20032,"Pulkovo 1995 / Gauss-Kruger zone 32",9001,4200,16232,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,
-20064,"Pulkovo 1995 / Gauss-Kruger 4N",9001,4200,16304,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20065,"Pulkovo 1995 / Gauss-Kruger 5N",9001,4200,16305,9807,1,1,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20066,"Pulkovo 1995 / Gauss-Kruger 6N",9001,4200,16306,9807,1,1,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20067,"Pulkovo 1995 / Gauss-Kruger 7N",9001,4200,16307,9807,1,1,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20068,"Pulkovo 1995 / Gauss-Kruger 8N",9001,4200,16308,9807,1,1,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20069,"Pulkovo 1995 / Gauss-Kruger 9N",9001,4200,16309,9807,1,1,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20070,"Pulkovo 1995 / Gauss-Kruger 10N",9001,4200,16310,9807,1,1,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20071,"Pulkovo 1995 / Gauss-Kruger 11N",9001,4200,16311,9807,1,1,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20072,"Pulkovo 1995 / Gauss-Kruger 12N",9001,4200,16312,9807,1,1,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20073,"Pulkovo 1995 / Gauss-Kruger 13N",9001,4200,16313,9807,1,1,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20074,"Pulkovo 1995 / Gauss-Kruger 14N",9001,4200,16314,9807,1,1,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20075,"Pulkovo 1995 / Gauss-Kruger 15N",9001,4200,16315,9807,1,1,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20076,"Pulkovo 1995 / Gauss-Kruger 16N",9001,4200,16316,9807,1,1,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20077,"Pulkovo 1995 / Gauss-Kruger 17N",9001,4200,16317,9807,1,1,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20078,"Pulkovo 1995 / Gauss-Kruger 18N",9001,4200,16318,9807,1,1,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20079,"Pulkovo 1995 / Gauss-Kruger 19N",9001,4200,16319,9807,1,1,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20080,"Pulkovo 1995 / Gauss-Kruger 20N",9001,4200,16320,9807,1,1,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20081,"Pulkovo 1995 / Gauss-Kruger 21N",9001,4200,16321,9807,1,1,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20082,"Pulkovo 1995 / Gauss-Kruger 22N",9001,4200,16322,9807,1,1,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20083,"Pulkovo 1995 / Gauss-Kruger 23N",9001,4200,16323,9807,1,1,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20084,"Pulkovo 1995 / Gauss-Kruger 24N",9001,4200,16324,9807,1,1,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20085,"Pulkovo 1995 / Gauss-Kruger 25N",9001,4200,16325,9807,1,1,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20086,"Pulkovo 1995 / Gauss-Kruger 26N",9001,4200,16326,9807,1,1,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20087,"Pulkovo 1995 / Gauss-Kruger 27N",9001,4200,16327,9807,1,1,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20088,"Pulkovo 1995 / Gauss-Kruger 28N",9001,4200,16328,9807,1,1,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20089,"Pulkovo 1995 / Gauss-Kruger 29N",9001,4200,16329,9807,1,1,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20090,"Pulkovo 1995 / Gauss-Kruger 30N",9001,4200,16330,9807,1,1,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20091,"Pulkovo 1995 / Gauss-Kruger 31N",9001,4200,16331,9807,1,1,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20092,"Pulkovo 1995 / Gauss-Kruger 32N",9001,4200,16332,9807,1,1,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-20135,"Adindan / UTM zone 35N",9001,4201,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20136,"Adindan / UTM zone 36N",9001,4201,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20137,"Adindan / UTM zone 37N",9001,4201,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20138,"Adindan / UTM zone 38N",9001,4201,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20248,"AGD66 / AMG zone 48",9001,4202,17448,9807,1,1,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20249,"AGD66 / AMG zone 49",9001,4202,17449,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20250,"AGD66 / AMG zone 50",9001,4202,17450,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20251,"AGD66 / AMG zone 51",9001,4202,17451,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20252,"AGD66 / AMG zone 52",9001,4202,17452,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20253,"AGD66 / AMG zone 53",9001,4202,17453,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20254,"AGD66 / AMG zone 54",9001,4202,17454,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20255,"AGD66 / AMG zone 55",9001,4202,17455,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20256,"AGD66 / AMG zone 56",9001,4202,17456,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20257,"AGD66 / AMG zone 57",9001,4202,17457,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20258,"AGD66 / AMG zone 58",9001,4202,17458,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20348,"AGD84 / AMG zone 48",9001,4203,17448,9807,1,1,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20349,"AGD84 / AMG zone 49",9001,4203,17449,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20350,"AGD84 / AMG zone 50",9001,4203,17450,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20351,"AGD84 / AMG zone 51",9001,4203,17451,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20352,"AGD84 / AMG zone 52",9001,4203,17452,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20353,"AGD84 / AMG zone 53",9001,4203,17453,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20354,"AGD84 / AMG zone 54",9001,4203,17454,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20355,"AGD84 / AMG zone 55",9001,4203,17455,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20356,"AGD84 / AMG zone 56",9001,4203,17456,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20357,"AGD84 / AMG zone 57",9001,4203,17457,9807,1,1,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20358,"AGD84 / AMG zone 58",9001,4203,17458,9807,1,1,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20436,"Ain el Abd / UTM zone 36N",9001,4204,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20437,"Ain el Abd / UTM zone 37N",9001,4204,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20438,"Ain el Abd / UTM zone 38N",9001,4204,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20439,"Ain el Abd / UTM zone 39N",9001,4204,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20440,"Ain el Abd / UTM zone 40N",9001,4204,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20499,"Ain el Abd / Bahrain Grid",9001,4204,19900,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20538,"Afgooye / UTM zone 38N",9001,4205,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20539,"Afgooye / UTM zone 39N",9001,4205,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-20790,"Lisbon (Lisbon) / Portuguese National Grid",9001,4803,19936,9807,1,0,4499,8801,39.4,9110,8802,1,9110,8805,1,9201,8806,200000,9001,8807,300000,9001,,,,,,
-20791,"Lisbon (Lisbon) / Portuguese Grid",9001,4803,19969,9807,1,0,4499,8801,39.4,9110,8802,1,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-20822,"Aratu / UTM zone 22S",9001,4208,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20823,"Aratu / UTM zone 23S",9001,4208,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20824,"Aratu / UTM zone 24S",9001,4208,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20934,"Arc 1950 / UTM zone 34S",9001,4209,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20935,"Arc 1950 / UTM zone 35S",9001,4209,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-20936,"Arc 1950 / UTM zone 36S",9001,4209,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-21035,"Arc 1960 / UTM zone 35S",9001,4210,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-21036,"Arc 1960 / UTM zone 36S",9001,4210,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-21037,"Arc 1960 / UTM zone 37S",9001,4210,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-21095,"Arc 1960 / UTM zone 35N",9001,4210,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-21096,"Arc 1960 / UTM zone 36N",9001,4210,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-21097,"Arc 1960 / UTM zone 37N",9001,4210,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-21100,"Batavia (Jakarta) / NEIEZ",9001,4813,19905,9804,1,1,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
-21148,"Batavia / UTM zone 48S",9001,4211,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-21149,"Batavia / UTM zone 49S",9001,4211,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-21150,"Batavia / UTM zone 50S",9001,4211,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-21291,"Barbados 1938 / British West Indies Grid",9001,4212,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,
-21292,"Barbados 1938 / Barbados National Grid",9001,4212,19943,9807,1,0,4400,8801,13.1035,9110,8802,-59.3335,9110,8805,0.9999986,9201,8806,30000,9001,8807,75000,9001,,,,,,
-21413,"Beijing 1954 / Gauss-Kruger zone 13",9001,4214,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-21414,"Beijing 1954 / Gauss-Kruger zone 14",9001,4214,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-21415,"Beijing 1954 / Gauss-Kruger zone 15",9001,4214,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-21416,"Beijing 1954 / Gauss-Kruger zone 16",9001,4214,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,
-21417,"Beijing 1954 / Gauss-Kruger zone 17",9001,4214,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,
-21418,"Beijing 1954 / Gauss-Kruger zone 18",9001,4214,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,
-21419,"Beijing 1954 / Gauss-Kruger zone 19",9001,4214,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-21420,"Beijing 1954 / Gauss-Kruger zone 20",9001,4214,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
-21421,"Beijing 1954 / Gauss-Kruger zone 21",9001,4214,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
-21422,"Beijing 1954 / Gauss-Kruger zone 22",9001,4214,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
-21423,"Beijing 1954 / Gauss-Kruger zone 23",9001,4214,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
-21453,"Beijing 1954 / Gauss-Kruger CM 75E",9001,4214,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21454,"Beijing 1954 / Gauss-Kruger CM 81E",9001,4214,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21455,"Beijing 1954 / Gauss-Kruger CM 87E",9001,4214,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21456,"Beijing 1954 / Gauss-Kruger CM 93E",9001,4214,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21457,"Beijing 1954 / Gauss-Kruger CM 99E",9001,4214,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21458,"Beijing 1954 / Gauss-Kruger CM 105E",9001,4214,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21459,"Beijing 1954 / Gauss-Kruger CM 111E",9001,4214,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21460,"Beijing 1954 / Gauss-Kruger CM 117E",9001,4214,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21461,"Beijing 1954 / Gauss-Kruger CM 123E",9001,4214,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21462,"Beijing 1954 / Gauss-Kruger CM 129E",9001,4214,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21463,"Beijing 1954 / Gauss-Kruger CM 135E",9001,4214,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21473,"Beijing 1954 / Gauss-Kruger 13N",9001,4214,16313,9807,1,1,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21474,"Beijing 1954 / Gauss-Kruger 14N",9001,4214,16314,9807,1,1,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21475,"Beijing 1954 / Gauss-Kruger 15N",9001,4214,16315,9807,1,1,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21476,"Beijing 1954 / Gauss-Kruger 16N",9001,4214,16316,9807,1,1,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21477,"Beijing 1954 / Gauss-Kruger 17N",9001,4214,16317,9807,1,1,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21478,"Beijing 1954 / Gauss-Kruger 18N",9001,4214,16318,9807,1,1,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21479,"Beijing 1954 / Gauss-Kruger 19N",9001,4214,16319,9807,1,1,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21480,"Beijing 1954 / Gauss-Kruger 20N",9001,4214,16320,9807,1,1,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21481,"Beijing 1954 / Gauss-Kruger 21N",9001,4214,16321,9807,1,1,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21482,"Beijing 1954 / Gauss-Kruger 22N",9001,4214,16322,9807,1,1,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21483,"Beijing 1954 / Gauss-Kruger 23N",9001,4214,16323,9807,1,1,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-21500,"Belge 1950 (Brussels) / Belge Lambert 50",9001,4809,19901,9802,1,0,4499,8821,90,9110,8822,0,9110,8823,49.5,9110,8824,51.1,9110,8826,150000,9001,8827,5400000,9001,,,
-21780,"Bern 1898 (Bern) / LV03C",9001,4801,19923,9815,1,0,4498,8811,46.570866,9110,8812,0,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,0,9001,8817,0,9001
-21781,"CH1903 / LV03",9001,4149,19922,9815,1,0,4498,8811,46.570866,9110,8812,7.26225,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,600000,9001,8817,200000,9001
-21782,"CH1903 / LV03C-G",9001,4149,19841,9815,1,0,4498,8811,46.570866,9110,8812,7.26225,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,0,9001,8817,0,9001
-21817,"Bogota 1975 / UTM zone 17N",9001,4218,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-21818,"Bogota 1975 / UTM zone 18N",9001,4218,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-21891,"Bogota 1975 / Colombia West zone",9001,4218,18051,9807,1,1,4499,8801,4.355657,9110,8802,-77.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-21892,"Bogota 1975 / Colombia Bogota zone",9001,4218,18052,9807,1,1,4499,8801,4.355657,9110,8802,-74.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-21893,"Bogota 1975 / Colombia East Central zone",9001,4218,18053,9807,1,1,4499,8801,4.355657,9110,8802,-71.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-21894,"Bogota 1975 / Colombia East",9001,4218,18054,9807,1,1,4499,8801,4.355657,9110,8802,-68.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-21896,"Bogota 1975 / Colombia West zone",9001,4218,18051,9807,1,0,4530,8801,4.355657,9110,8802,-77.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-21897,"Bogota 1975 / Colombia Bogota zone",9001,4218,18052,9807,1,0,4530,8801,4.355657,9110,8802,-74.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-21898,"Bogota 1975 / Colombia East Central zone",9001,4218,18053,9807,1,0,4530,8801,4.355657,9110,8802,-71.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-21899,"Bogota 1975 / Colombia East",9001,4218,18054,9807,1,0,4530,8801,4.355657,9110,8802,-68.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
-22032,"Camacupa / UTM zone 32S",9001,4220,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22033,"Camacupa / UTM zone 33S",9001,4220,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22091,"Camacupa / TM 11.30 SE",9001,4220,16611,9807,1,0,4400,8801,0,9110,8802,11.3,9110,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22092,"Camacupa / TM 12 SE",9001,4220,16612,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22171,"POSGAR 98 / Argentina 1",9001,4190,18031,9807,1,0,4530,8801,-90,9102,8802,-72,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-22172,"POSGAR 98 / Argentina 2",9001,4190,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-22173,"POSGAR 98 / Argentina 3",9001,4190,18033,9807,1,0,4530,8801,-90,9102,8802,-66,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-22174,"POSGAR 98 / Argentina 4",9001,4190,18034,9807,1,0,4530,8801,-90,9102,8802,-63,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-22175,"POSGAR 98 / Argentina 5",9001,4190,18035,9807,1,0,4530,8801,-90,9102,8802,-60,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-22176,"POSGAR 98 / Argentina 6",9001,4190,18036,9807,1,0,4530,8801,-90,9102,8802,-57,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-22177,"POSGAR 98 / Argentina 7",9001,4190,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-22181,"POSGAR 94 / Argentina 1",9001,4694,18031,9807,1,0,4530,8801,-90,9102,8802,-72,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-22182,"POSGAR 94 / Argentina 2",9001,4694,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-22183,"POSGAR 94 / Argentina 3",9001,4694,18033,9807,1,0,4530,8801,-90,9102,8802,-66,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-22184,"POSGAR 94 / Argentina 4",9001,4694,18034,9807,1,0,4530,8801,-90,9102,8802,-63,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-22185,"POSGAR 94 / Argentina 5",9001,4694,18035,9807,1,0,4530,8801,-90,9102,8802,-60,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-22186,"POSGAR 94 / Argentina 6",9001,4694,18036,9807,1,0,4530,8801,-90,9102,8802,-57,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-22187,"POSGAR 94 / Argentina 7",9001,4694,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-22191,"Campo Inchauspe / Argentina 1",9001,4221,18031,9807,1,0,4530,8801,-90,9102,8802,-72,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-22192,"Campo Inchauspe / Argentina 2",9001,4221,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-22193,"Campo Inchauspe / Argentina 3",9001,4221,18033,9807,1,0,4530,8801,-90,9102,8802,-66,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-22194,"Campo Inchauspe / Argentina 4",9001,4221,18034,9807,1,0,4530,8801,-90,9102,8802,-63,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-22195,"Campo Inchauspe / Argentina 5",9001,4221,18035,9807,1,0,4530,8801,-90,9102,8802,-60,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-22196,"Campo Inchauspe / Argentina 6",9001,4221,18036,9807,1,0,4530,8801,-90,9102,8802,-57,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-22197,"Campo Inchauspe / Argentina 7",9001,4221,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-22234,"Cape / UTM zone 34S",9001,4222,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22235,"Cape / UTM zone 35S",9001,4222,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22236,"Cape / UTM zone 36S",9001,4222,16136,9807,1,1,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22275,"Cape / Lo15",9001,4222,17515,9808,1,0,6503,8801,0,9102,8802,15,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22277,"Cape / Lo17",9001,4222,17517,9808,1,0,6503,8801,0,9102,8802,17,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22279,"Cape / Lo19",9001,4222,17519,9808,1,0,6503,8801,0,9102,8802,19,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22281,"Cape / Lo21",9001,4222,17521,9808,1,0,6503,8801,0,9102,8802,21,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22283,"Cape / Lo23",9001,4222,17523,9808,1,0,6503,8801,0,9102,8802,23,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22285,"Cape / Lo25",9001,4222,17525,9808,1,0,6503,8801,0,9102,8802,25,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22287,"Cape / Lo27",9001,4222,17527,9808,1,0,6503,8801,0,9102,8802,27,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22289,"Cape / Lo29",9001,4222,17529,9808,1,0,6503,8801,0,9102,8802,29,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22291,"Cape / Lo31",9001,4222,17531,9808,1,0,6503,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22293,"Cape / Lo33",9001,4222,17533,9808,1,0,6503,8801,0,9102,8802,33,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-22300,"Carthage (Paris) / Tunisia Mining Grid",9036,4816,19937,9816,1,0,4406,8821,36.5964,9105,8822,7.83445,9105,8826,270,9036,8827,360,9036,,,,,,,,,
-22332,"Carthage / UTM zone 32N",9001,4223,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-22391,"Carthage / Nord Tunisie",9001,4223,18181,9801,1,0,4499,8801,40,9105,8802,11,9105,8805,0.999625544,9201,8806,500000,9001,8807,300000,9001,,,,,,
-22392,"Carthage / Sud Tunisie",9001,4223,18182,9801,1,0,4499,8801,37,9105,8802,11,9105,8805,0.999625769,9201,8806,500000,9001,8807,300000,9001,,,,,,
-22521,"Corrego Alegre 1970-72 / UTM zone 21S",9001,4225,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22522,"Corrego Alegre 1970-72 / UTM zone 22S",9001,4225,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22523,"Corrego Alegre 1970-72 / UTM zone 23S",9001,4225,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22524,"Corrego Alegre 1970-72 / UTM zone 24S",9001,4225,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22525,"Corrego Alegre 1970-72 / UTM zone 25S",9001,4225,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-22700,"Deir ez Zor / Levant Zone",9001,4227,19940,9817,1,0,4499,8801,34.39,9110,8802,37.21,9110,8805,0.9996256,9201,8806,300000,9001,8807,300000,9001,,,,,,
-22770,"Deir ez Zor / Syria Lambert",9001,4227,19948,9801,1,0,4499,8801,34.39,9110,8802,37.21,9110,8805,0.9996256,9201,8806,300000,9001,8807,300000,9001,,,,,,
-22780,"Deir ez Zor / Levant Stereographic",9001,4227,19949,9809,1,0,4499,8801,38,9105,8802,43.5,9105,8805,0.9995341,9201,8806,0,9001,8807,0,9001,,,,,,
-22832,"Douala / UTM zone 32N",9001,4228,16032,9807,1,1,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-22991,"Egypt 1907 / Blue Belt",9001,4229,18071,9807,1,0,4400,8801,30,9102,8802,35,9102,8805,1,9201,8806,300000,9001,8807,1100000,9001,,,,,,
-22992,"Egypt 1907 / Red Belt",9001,4229,18072,9807,1,0,4400,8801,30,9102,8802,31,9102,8805,1,9201,8806,615000,9001,8807,810000,9001,,,,,,
-22993,"Egypt 1907 / Purple Belt",9001,4229,18073,9807,1,0,4400,8801,30,9102,8802,27,9102,8805,1,9201,8806,700000,9001,8807,200000,9001,,,,,,
-22994,"Egypt 1907 / Extended Purple Belt",9001,4229,18074,9807,1,0,4400,8801,30,9102,8802,27,9102,8805,1,9201,8806,700000,9001,8807,1200000,9001,,,,,,
-23028,"ED50 / UTM zone 28N",9001,4230,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23029,"ED50 / UTM zone 29N",9001,4230,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23030,"ED50 / UTM zone 30N",9001,4230,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23031,"ED50 / UTM zone 31N",9001,4230,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23032,"ED50 / UTM zone 32N",9001,4230,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23033,"ED50 / UTM zone 33N",9001,4230,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23034,"ED50 / UTM zone 34N",9001,4230,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23035,"ED50 / UTM zone 35N",9001,4230,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23036,"ED50 / UTM zone 36N",9001,4230,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23037,"ED50 / UTM zone 37N",9001,4230,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23038,"ED50 / UTM zone 38N",9001,4230,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23090,"ED50 / TM 0 N",9001,4230,16400,9807,1,0,4400,8801,0,9102,8802,0,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23095,"ED50 / TM 5 NE",9001,4230,16405,9807,1,0,4400,8801,0,9102,8802,5,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23239,"Fahud / UTM zone 39N",9001,4232,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23240,"Fahud / UTM zone 40N",9001,4232,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23433,"Garoua / UTM zone 33N",9001,4234,16033,9807,1,1,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23700,"HD72 / EOV",9001,4237,19931,9815,1,0,4498,8811,47.08398174,9110,8812,19.02548584,9110,8813,90,9110,8814,90,9110,8815,0.99993,9201,8816,650000,9001,8817,200000,9001
-23830,"DGN95 / Indonesia TM-3 zone 46.2",9001,4755,17432,9807,1,0,4499,8801,0,9102,8802,94.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23831,"DGN95 / Indonesia TM-3 zone 47.1",9001,4755,17433,9807,1,0,4499,8801,0,9102,8802,97.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23832,"DGN95 / Indonesia TM-3 zone 47.2",9001,4755,17434,9807,1,0,4499,8801,0,9102,8802,100.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23833,"DGN95 / Indonesia TM-3 zone 48.1",9001,4755,17435,9807,1,0,4499,8801,0,9102,8802,103.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23834,"DGN95 / Indonesia TM-3 zone 48.2",9001,4755,17436,9807,1,0,4499,8801,0,9102,8802,106.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23835,"DGN95 / Indonesia TM-3 zone 49.1",9001,4755,17437,9807,1,0,4499,8801,0,9102,8802,109.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23836,"DGN95 / Indonesia TM-3 zone 49.2",9001,4755,17438,9807,1,0,4499,8801,0,9102,8802,112.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23837,"DGN95 / Indonesia TM-3 zone 50.1",9001,4755,17439,9807,1,0,4499,8801,0,9102,8802,115.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23838,"DGN95 / Indonesia TM-3 zone 50.2",9001,4755,17440,9807,1,0,4499,8801,0,9102,8802,118.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23839,"DGN95 / Indonesia TM-3 zone 51.1",9001,4755,17441,9807,1,0,4499,8801,0,9102,8802,121.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23840,"DGN95 / Indonesia TM-3 zone 51.2",9001,4755,17442,9807,1,0,4499,8801,0,9102,8802,124.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23841,"DGN95 / Indonesia TM-3 zone 52.1",9001,4755,17443,9807,1,0,4499,8801,0,9102,8802,127.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23842,"DGN95 / Indonesia TM-3 zone 52.2",9001,4755,17444,9807,1,0,4499,8801,0,9102,8802,130.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23843,"DGN95 / Indonesia TM-3 zone 53.1",9001,4755,17445,9807,1,0,4499,8801,0,9102,8802,133.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23844,"DGN95 / Indonesia TM-3 zone 53.2",9001,4755,17446,9807,1,0,4499,8801,0,9102,8802,136.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23845,"DGN95 / Indonesia TM-3 zone 54.1",9001,4755,17447,9807,1,0,4499,8801,0,9102,8802,139.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,
-23846,"ID74 / UTM zone 46N",9001,4238,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23847,"ID74 / UTM zone 47N",9001,4238,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23848,"ID74 / UTM zone 48N",9001,4238,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23849,"ID74 / UTM zone 49N",9001,4238,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23850,"ID74 / UTM zone 50N",9001,4238,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23851,"ID74 / UTM zone 51N",9001,4238,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23852,"ID74 / UTM zone 52N",9001,4238,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23853,"ID74 / UTM zone 53N",9001,4238,16053,9807,1,1,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23866,"DGN95 / UTM zone 46N",9001,4755,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23867,"DGN95 / UTM zone 47N",9001,4755,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23868,"DGN95 / UTM zone 48N",9001,4755,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23869,"DGN95 / UTM zone 49N",9001,4755,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23870,"DGN95 / UTM zone 50N",9001,4755,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23871,"DGN95 / UTM zone 51N",9001,4755,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23872,"DGN95 / UTM zone 52N",9001,4755,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23877,"DGN95 / UTM zone 47S",9001,4755,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23878,"DGN95 / UTM zone 48S",9001,4755,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23879,"DGN95 / UTM zone 49S",9001,4755,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23880,"DGN95 / UTM zone 50S",9001,4755,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23881,"DGN95 / UTM zone 51S",9001,4755,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23882,"DGN95 / UTM zone 52S",9001,4755,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23883,"DGN95 / UTM zone 53S",9001,4755,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23884,"DGN95 / UTM zone 54S",9001,4755,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23886,"ID74 / UTM zone 46S",9001,4238,16146,9807,1,1,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23887,"ID74 / UTM zone 47S",9001,4238,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23888,"ID74 / UTM zone 48S",9001,4238,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23889,"ID74 / UTM zone 49S",9001,4238,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23890,"ID74 / UTM zone 50S",9001,4238,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23891,"ID74 / UTM zone 51S",9001,4238,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23892,"ID74 / UTM zone 52S",9001,4238,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23893,"ID74 / UTM zone 53S",9001,4238,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23894,"ID74 / UTM zone 54S",9001,4238,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-23946,"Indian 1954 / UTM zone 46N",9001,4239,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23947,"Indian 1954 / UTM zone 47N",9001,4239,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-23948,"Indian 1954 / UTM zone 48N",9001,4239,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24047,"Indian 1975 / UTM zone 47N",9001,4240,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24048,"Indian 1975 / UTM zone 48N",9001,4240,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24100,"Jamaica 1875 / Jamaica (Old Grid)",9005,4241,19909,9801,1,0,4403,8801,18,9102,8802,-77,9102,8805,1,9201,8806,550000,9005,8807,400000,9005,,,,,,
-24200,"JAD69 / Jamaica National Grid",9001,4242,19910,9801,1,0,4400,8801,18,9102,8802,-77,9102,8805,1,9201,8806,250000,9001,8807,150000,9001,,,,,,
-24305,"Kalianpur 1937 / UTM zone 45N",9001,4144,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24306,"Kalianpur 1937 / UTM zone 46N",9001,4144,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24311,"Kalianpur 1962 / UTM zone 41N",9001,4145,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24312,"Kalianpur 1962 / UTM zone 42N",9001,4145,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24313,"Kalianpur 1962 / UTM zone 43N",9001,4145,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24342,"Kalianpur 1975 / UTM zone 42N",9001,4146,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24343,"Kalianpur 1975 / UTM zone 43N",9001,4146,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24344,"Kalianpur 1975 / UTM zone 44N",9001,4146,16044,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24345,"Kalianpur 1975 / UTM zone 45N",9001,4146,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24346,"Kalianpur 1975 / UTM zone 46N",9001,4146,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24347,"Kalianpur 1975 / UTM zone 47N",9001,4146,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24370,"Kalianpur 1880 / India zone 0",9084,4243,18110,9801,1,0,4408,8801,39.3,9110,8802,68,9110,8805,0.99846154,9201,8806,2355500,9084,8807,2590000,9084,,,,,,
-24371,"Kalianpur 1880 / India zone I",9084,4243,18111,9801,1,0,4408,8801,32.3,9110,8802,68,9110,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,
-24372,"Kalianpur 1880 / India zone IIa",9084,4243,18112,9801,1,0,4408,8801,26,9102,8802,74,9102,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,
-24373,"Kalianpur 1880 / India zone IIIa",9084,4243,18114,9801,1,0,4408,8801,19,9102,8802,80,9102,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,
-24374,"Kalianpur 1880 / India zone IVa",9084,4243,18116,9801,1,0,4408,8801,12,9102,8802,80,9102,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,
-24375,"Kalianpur 1937 / India zone IIb",9001,4144,18238,9801,1,0,4400,8801,26,9102,8802,90,9102,8805,0.99878641,9201,8806,2743185.69,9001,8807,914395.23,9001,,,,,,
-24376,"Kalianpur 1962 / India zone I",9001,4145,18236,9801,1,0,4400,8801,32.3,9110,8802,68,9110,8805,0.99878641,9201,8806,2743196.4,9001,8807,914398.8,9001,,,,,,
-24377,"Kalianpur 1962 / India zone IIa",9001,4145,18237,9801,1,0,4400,8801,26,9102,8802,74,9102,8805,0.99878641,9201,8806,2743196.4,9001,8807,914398.8,9001,,,,,,
-24378,"Kalianpur 1975 / India zone I",9001,4146,18231,9801,1,0,4400,8801,32.3,9110,8802,68,9110,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,
-24379,"Kalianpur 1975 / India zone IIa",9001,4146,18232,9801,1,0,4400,8801,26,9102,8802,74,9102,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,
-24380,"Kalianpur 1975 / India zone IIb",9001,4146,18235,9801,1,0,4400,8801,26,9102,8802,90,9102,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,
-24381,"Kalianpur 1975 / India zone IIIa",9001,4146,18233,9801,1,0,4400,8801,19,9102,8802,80,9102,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,
-24382,"Kalianpur 1880 / India zone IIb",9084,4243,18113,9801,1,0,4408,8801,26,9102,8802,90,9102,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,
-24383,"Kalianpur 1975 / India zone IVa",9001,4146,18234,9801,1,0,4400,8801,12,9102,8802,80,9102,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,
-24500,"Kertau 1968 / Singapore Grid",9001,4245,19920,9806,1,0,4400,8801,1.1715528,9110,8802,103.5110808,9110,8806,30000,9001,8807,30000,9001,,,,,,,,,
-24547,"Kertau 1968 / UTM zone 47N",9001,4245,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24548,"Kertau 1968 / UTM zone 48N",9001,4245,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24571,"Kertau / R.S.O. Malaya (ch)",9062,4245,19935,9812,1,1,4401,8806,40000,9062,8807,0,9062,8811,4,9110,8812,102.15,9110,8813,323.01328458,9110,8814,323.07483685,9110,8815,0.99984,9201
-24600,KOC Lambert,9001,4246,19906,9801,1,0,4400,8801,32.3,9110,8802,45,9110,8805,0.9987864078,9201,8806,1500000,9001,8807,1166200,9001,,,,,,
-24718,"La Canoa / UTM zone 18N",9001,4247,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24719,"La Canoa / UTM zone 19N",9001,4247,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24720,"La Canoa / UTM zone 20N",9001,4247,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24817,"PSAD56 / UTM zone 17N",9001,4248,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24818,"PSAD56 / UTM zone 18N",9001,4248,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24819,"PSAD56 / UTM zone 19N",9001,4248,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24820,"PSAD56 / UTM zone 20N",9001,4248,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24821,"PSAD56 / UTM zone 21N",9001,4248,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-24877,"PSAD56 / UTM zone 17S",9001,4248,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-24878,"PSAD56 / UTM zone 18S",9001,4248,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-24879,"PSAD56 / UTM zone 19S",9001,4248,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-24880,"PSAD56 / UTM zone 20S",9001,4248,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-24881,"PSAD56 / UTM zone 21S",9001,4248,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-24882,"PSAD56 / UTM zone 22S",9001,4248,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-24891,"PSAD56 / Peru west zone",9001,4248,18161,9807,1,0,4499,8801,-6,9110,8802,-80.3,9110,8805,0.99983008,9201,8806,222000,9001,8807,1426834.743,9001,,,,,,
-24892,"PSAD56 / Peru central zone",9001,4248,18162,9807,1,0,4499,8801,-9.3,9110,8802,-76,9110,8805,0.99932994,9201,8806,720000,9001,8807,1039979.159,9001,,,,,,
-24893,"PSAD56 / Peru east zone",9001,4248,18163,9807,1,0,4499,8801,-9.3,9110,8802,-70.3,9110,8805,0.99952992,9201,8806,1324000,9001,8807,1040084.558,9001,,,,,,
-25000,"Leigon / Ghana Metre Grid",9001,4250,19904,9807,1,0,4400,8801,4.4,9110,8802,-1,9110,8805,0.99975,9201,8806,274319.51,9001,8807,0,9001,,,,,,
-25231,"Lome / UTM zone 31N",9001,4252,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25391,"Luzon 1911 / Philippines zone I",9001,4253,18171,9807,1,0,4499,8801,0,9102,8802,117,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-25392,"Luzon 1911 / Philippines zone II",9001,4253,18172,9807,1,0,4499,8801,0,9102,8802,119,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-25393,"Luzon 1911 / Philippines zone III",9001,4253,18173,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-25394,"Luzon 1911 / Philippines zone IV",9001,4253,18174,9807,1,0,4499,8801,0,9102,8802,123,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-25395,"Luzon 1911 / Philippines zone V",9001,4253,18175,9807,1,0,4499,8801,0,9102,8802,125,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,
-25700,"Makassar (Jakarta) / NEIEZ",9001,4804,19905,9804,1,1,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,
-25828,"ETRS89 / UTM zone 28N",9001,4258,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25829,"ETRS89 / UTM zone 29N",9001,4258,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25830,"ETRS89 / UTM zone 30N",9001,4258,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25831,"ETRS89 / UTM zone 31N",9001,4258,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25832,"ETRS89 / UTM zone 32N",9001,4258,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25833,"ETRS89 / UTM zone 33N",9001,4258,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25834,"ETRS89 / UTM zone 34N",9001,4258,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25835,"ETRS89 / UTM zone 35N",9001,4258,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25836,"ETRS89 / UTM zone 36N",9001,4258,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25837,"ETRS89 / UTM zone 37N",9001,4258,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25838,"ETRS89 / UTM zone 38N",9001,4258,16038,9807,1,1,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25884,"ETRS89 / TM Baltic93",9001,4258,19939,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-25932,"Malongo 1987 / UTM zone 32S",9001,4259,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-26191,"Merchich / Nord Maroc",9001,4261,18131,9801,1,0,4499,8801,37,9105,8802,-6,9105,8805,0.999625769,9201,8806,500000,9001,8807,300000,9001,,,,,,
-26192,"Merchich / Sud Maroc",9001,4261,18132,9801,1,0,4499,8801,33,9105,8802,-6,9105,8805,0.999615596,9201,8806,500000,9001,8807,300000,9001,,,,,,
-26193,"Merchich / Sahara",9001,4261,18133,9801,1,1,4499,8801,29,9105,8802,-6,9105,8805,0.9996,9201,8806,1200000,9001,8807,400000,9001,,,,,,
-26194,"Merchich / Sahara Nord",9001,4261,18134,9801,1,0,4499,8801,29,9105,8802,-6,9105,8805,0.999616304,9201,8806,1200000,9001,8807,400000,9001,,,,,,
-26195,"Merchich / Sahara Sud",9001,4261,18135,9801,1,0,4499,8801,25,9105,8802,-6,9105,8805,0.999616437,9201,8806,1500000,9001,8807,400000,9001,,,,,,
-26237,"Massawa / UTM zone 37N",9001,4262,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26331,"Minna / UTM zone 31N",9001,4263,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26332,"Minna / UTM zone 32N",9001,4263,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26391,"Minna / Nigeria West Belt",9001,4263,18151,9807,1,0,4400,8801,4,9110,8802,4.3,9110,8805,0.99975,9201,8806,230738.26,9001,8807,0,9001,,,,,,
-26392,"Minna / Nigeria Mid Belt",9001,4263,18152,9807,1,0,4400,8801,4,9110,8802,8.3,9110,8805,0.99975,9201,8806,670553.98,9001,8807,0,9001,,,,,,
-26393,"Minna / Nigeria East Belt",9001,4263,18153,9807,1,0,4400,8801,4,9110,8802,12.3,9110,8805,0.99975,9201,8806,1110369.7,9001,8807,0,9001,,,,,,
-26432,"Mhast / UTM zone 32S",9001,4264,16132,9807,1,1,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-26591,"Monte Mario (Rome) / Italy zone 1",9001,4806,18121,9807,1,1,4499,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,1500000,9001,8807,0,9001,,,,,,
-26592,"Monte Mario (Rome) / Italy zone 2",9001,4806,18122,9807,1,1,4499,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,2520000,9001,8807,0,9001,,,,,,
-26632,"M'poraloko / UTM zone 32N",9001,4266,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26692,"M'poraloko / UTM zone 32S",9001,4266,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-26701,"NAD27 / UTM zone 1N",9001,4267,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26702,"NAD27 / UTM zone 2N",9001,4267,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26703,"NAD27 / UTM zone 3N",9001,4267,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26704,"NAD27 / UTM zone 4N",9001,4267,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26705,"NAD27 / UTM zone 5N",9001,4267,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26706,"NAD27 / UTM zone 6N",9001,4267,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26707,"NAD27 / UTM zone 7N",9001,4267,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26708,"NAD27 / UTM zone 8N",9001,4267,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26709,"NAD27 / UTM zone 9N",9001,4267,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26710,"NAD27 / UTM zone 10N",9001,4267,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26711,"NAD27 / UTM zone 11N",9001,4267,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26712,"NAD27 / UTM zone 12N",9001,4267,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26713,"NAD27 / UTM zone 13N",9001,4267,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26714,"NAD27 / UTM zone 14N",9001,4267,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26715,"NAD27 / UTM zone 15N",9001,4267,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26716,"NAD27 / UTM zone 16N",9001,4267,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26717,"NAD27 / UTM zone 17N",9001,4267,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26718,"NAD27 / UTM zone 18N",9001,4267,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26719,"NAD27 / UTM zone 19N",9001,4267,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26720,"NAD27 / UTM zone 20N",9001,4267,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26721,"NAD27 / UTM zone 21N",9001,4267,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26722,"NAD27 / UTM zone 22N",9001,4267,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26729,"NAD27 / Alabama East",9003,4267,10101,9807,1,0,4497,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,500000,9003,8807,0,9003,,,,,,
-26730,"NAD27 / Alabama West",9003,4267,10102,9807,1,0,4497,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,
-26731,"NAD27 / Alaska zone 1",9003,4267,15001,9812,1,0,4497,8806,16404166.67,9003,8807,-16404166.67,9003,8811,57,9110,8812,-133.4,9110,8813,323.07483685,9110,8814,323.07483685,9110,8815,0.9999,9201
-26732,"NAD27 / Alaska zone 2",9003,4267,15002,9807,1,0,4497,8801,54,9102,8802,-142,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26733,"NAD27 / Alaska zone 3",9003,4267,15003,9807,1,0,4497,8801,54,9102,8802,-146,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26734,"NAD27 / Alaska zone 4",9003,4267,15004,9807,1,0,4497,8801,54,9102,8802,-150,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26735,"NAD27 / Alaska zone 5",9003,4267,15005,9807,1,0,4497,8801,54,9102,8802,-154,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26736,"NAD27 / Alaska zone 6",9003,4267,15006,9807,1,0,4497,8801,54,9102,8802,-158,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26737,"NAD27 / Alaska zone 7",9003,4267,15007,9807,1,0,4497,8801,54,9102,8802,-162,9102,8805,0.9999,9201,8806,700000,9003,8807,0,9003,,,,,,
-26738,"NAD27 / Alaska zone 8",9003,4267,15008,9807,1,0,4497,8801,54,9102,8802,-166,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26739,"NAD27 / Alaska zone 9",9003,4267,15009,9807,1,0,4497,8801,54,9102,8802,-170,9102,8805,0.9999,9201,8806,600000,9003,8807,0,9003,,,,,,
-26740,"NAD27 / Alaska zone 10",9003,4267,15010,9802,1,0,4497,8821,51,9110,8822,-176,9110,8823,53.5,9110,8824,51.5,9110,8826,3000000,9003,8827,0,9003,,,
-26741,"NAD27 / California zone I",9003,4267,10401,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9003,8827,0,9003,,,
-26742,"NAD27 / California zone II",9003,4267,10402,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9003,8827,0,9003,,,
-26743,"NAD27 / California zone III",9003,4267,10403,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9003,8827,0,9003,,,
-26744,"NAD27 / California zone IV",9003,4267,10404,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9003,8827,0,9003,,,
-26745,"NAD27 / California zone V",9003,4267,10405,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9003,8827,0,9003,,,
-26746,"NAD27 / California zone VI",9003,4267,10406,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9003,8827,0,9003,,,
-26747,"NAD27 / California zone VII",9003,4267,10407,9802,1,1,4497,8821,34.08,9110,8822,-118.2,9110,8823,34.25,9110,8824,33.52,9110,8826,4186692.58,9003,8827,416926.74,9003,,,
-26748,"NAD27 / Arizona East",9003,4267,10201,9807,1,0,4497,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26749,"NAD27 / Arizona Central",9003,4267,10202,9807,1,0,4497,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26750,"NAD27 / Arizona West",9003,4267,10203,9807,1,0,4497,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,
-26751,"NAD27 / Arkansas North",9003,4267,10301,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,2000000,9003,8827,0,9003,,,
-26752,"NAD27 / Arkansas South",9003,4267,10302,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,2000000,9003,8827,0,9003,,,
-26753,"NAD27 / Colorado North",9003,4267,10501,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,39.43,9110,8824,40.47,9110,8826,2000000,9003,8827,0,9003,,,
-26754,"NAD27 / Colorado Central",9003,4267,10502,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,2000000,9003,8827,0,9003,,,
-26755,"NAD27 / Colorado South",9003,4267,10503,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,2000000,9003,8827,0,9003,,,
-26756,"NAD27 / Connecticut",9003,4267,10600,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,600000,9003,8827,0,9003,,,
-26757,"NAD27 / Delaware",9003,4267,10700,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,500000,9003,8807,0,9003,,,,,,
-26758,"NAD27 / Florida East",9003,4267,10901,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-26759,"NAD27 / Florida West",9003,4267,10902,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-26760,"NAD27 / Florida North",9003,4267,10903,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,2000000,9003,8827,0,9003,,,
-26766,"NAD27 / Georgia East",9003,4267,11001,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26767,"NAD27 / Georgia West",9003,4267,11002,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26768,"NAD27 / Idaho East",9003,4267,11101,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,500000,9003,8807,0,9003,,,,,,
-26769,"NAD27 / Idaho Central",9003,4267,11102,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9003,8807,0,9003,,,,,,
-26770,"NAD27 / Idaho West",9003,4267,11103,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,
-26771,"NAD27 / Illinois East",9003,4267,11201,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,500000,9003,8807,0,9003,,,,,,
-26772,"NAD27 / Illinois West",9003,4267,11202,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-26773,"NAD27 / Indiana East",9003,4267,11301,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,
-26774,"NAD27 / Indiana West",9003,4267,11302,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,
-26775,"NAD27 / Iowa North",9003,4267,11401,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,2000000,9003,8827,0,9003,,,
-26776,"NAD27 / Iowa South",9003,4267,11402,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,2000000,9003,8827,0,9003,,,
-26777,"NAD27 / Kansas North",9003,4267,11501,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,2000000,9003,8827,0,9003,,,
-26778,"NAD27 / Kansas South",9003,4267,11502,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,2000000,9003,8827,0,9003,,,
-26779,"NAD27 / Kentucky North",9003,4267,11601,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,2000000,9003,8827,0,9003,,,
-26780,"NAD27 / Kentucky South",9003,4267,11602,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,36.44,9110,8824,37.56,9110,8826,2000000,9003,8827,0,9003,,,
-26781,"NAD27 / Louisiana North",9003,4267,11701,9802,1,0,4497,8821,30.4,9110,8822,-92.3,9110,8823,31.1,9110,8824,32.4,9110,8826,2000000,9003,8827,0,9003,,,
-26782,"NAD27 / Louisiana South",9003,4267,11702,9802,1,0,4497,8821,28.4,9110,8822,-91.2,9110,8823,29.18,9110,8824,30.42,9110,8826,2000000,9003,8827,0,9003,,,
-26783,"NAD27 / Maine East",9003,4267,11801,9807,1,0,4497,8801,43.5,9110,8802,-68.3,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-26784,"NAD27 / Maine West",9003,4267,11802,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,
-26785,"NAD27 / Maryland",9003,4267,11900,9802,1,0,4497,8821,37.5,9110,8822,-77,9110,8823,38.18,9110,8824,39.27,9110,8826,800000,9003,8827,0,9003,,,
-26786,"NAD27 / Massachusetts Mainland",9003,4267,12001,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,41.43,9110,8824,42.41,9110,8826,600000,9003,8827,0,9003,,,
-26787,"NAD27 / Massachusetts Island",9003,4267,12002,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.17,9110,8824,41.29,9110,8826,200000,9003,8827,0,9003,,,
-26791,"NAD27 / Minnesota North",9003,4267,12201,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,47.02,9110,8824,48.38,9110,8826,2000000,9003,8827,0,9003,,,
-26792,"NAD27 / Minnesota Central",9003,4267,12202,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,45.37,9110,8824,47.03,9110,8826,2000000,9003,8827,0,9003,,,
-26793,"NAD27 / Minnesota South",9003,4267,12203,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,43.47,9110,8824,45.13,9110,8826,2000000,9003,8827,0,9003,,,
-26794,"NAD27 / Mississippi East",9003,4267,12301,9807,1,0,4497,8801,29.4,9110,8802,-88.5,9110,8805,0.99996,9201,8806,500000,9003,8807,0,9003,,,,,,
-26795,"NAD27 / Mississippi West",9003,4267,12302,9807,1,0,4497,8801,30.3,9110,8802,-90.2,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-26796,"NAD27 / Missouri East",9003,4267,12401,9807,1,0,4497,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,
-26797,"NAD27 / Missouri Central",9003,4267,12402,9807,1,0,4497,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,
-26798,"NAD27 / Missouri West",9003,4267,12403,9807,1,0,4497,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-26799,"NAD27 / California zone VII",9003,4267,10408,9802,1,0,4497,8821,34.08,9110,8822,-118.2,9110,8823,34.25,9110,8824,33.52,9110,8826,4186692.58,9003,8827,4160926.74,9003,,,
-26801,"NAD Michigan / Michigan East",9003,4268,12101,9807,1,1,4497,8801,41.3,9110,8802,-83.4,9110,8805,0.999942857,9201,8806,500000,9003,8807,0,9003,,,,,,
-26802,"NAD Michigan / Michigan Old Central",9003,4268,12102,9807,1,1,4497,8801,41.3,9110,8802,-85.45,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,
-26803,"NAD Michigan / Michigan West",9003,4268,12103,9807,1,1,4497,8801,41.3,9110,8802,-88.45,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,
-26811,"NAD Michigan / Michigan North",9003,4268,12111,9802,1,1,4497,8821,44.47,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003,,,
-26812,"NAD Michigan / Michigan Central",9003,4268,12112,9802,1,1,4497,8821,43.19,9110,8822,-84.2,9110,8823,44.11,9110,8824,45.42,9110,8826,2000000,9003,8827,0,9003,,,
-26813,"NAD Michigan / Michigan South",9003,4268,12113,9802,1,1,4497,8821,41.3,9110,8822,-84.2,9110,8823,42.06,9110,8824,43.4,9110,8826,2000000,9003,8827,0,9003,,,
-26814,"NAD83 / Maine East (ftUS)",9001,4269,11833,9807,1,1,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,
-26815,"NAD83 / Maine West (ftUS)",9001,4269,11834,9807,1,1,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,
-26819,"NAD83 / Minnesota North (ftUS)",9001,4269,12234,9802,1,1,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26820,"NAD83 / Minnesota Central (ftUS)",9001,4269,12235,9802,1,1,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26821,"NAD83 / Minnesota South (ftUS)",9001,4269,12236,9802,1,1,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26822,"NAD83 / Nebraska (ftUS)",9001,4269,15396,9802,1,1,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,
-26823,"NAD83 / West Virginia North (ftUS)",9001,4269,14733,9802,1,1,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9001,8827,0,9001,,,
-26824,"NAD83 / West Virginia South (ftUS)",9001,4269,14734,9802,1,1,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9001,8827,0,9001,,,
-26825,"NAD83(HARN) / Maine East (ftUS)",9001,4152,11833,9807,1,1,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,
-26826,"NAD83(HARN) / Maine West (ftUS)",9001,4152,11834,9807,1,1,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,
-26830,"NAD83(HARN) / Minnesota North (ftUS)",9001,4152,12234,9802,1,1,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26831,"NAD83(HARN) / Minnesota Central (ftUS)",9001,4152,12235,9802,1,1,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26832,"NAD83(HARN) / Minnesota South (ftUS)",9001,4152,12236,9802,1,1,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26833,"NAD83(HARN) / Nebraska (ftUS)",9001,4152,15396,9802,1,1,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,
-26834,"NAD83(HARN) / West Virginia North (ftUS)",9001,4152,14733,9802,1,1,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9001,8827,0,9001,,,
-26835,"NAD83(HARN) / West Virginia South (ftUS)",9001,4152,14734,9802,1,1,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9001,8827,0,9001,,,
-26836,"NAD83(NSRS2007) / Maine East (ftUS)",9001,4759,11833,9807,1,1,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,
-26837,"NAD83(NSRS2007) / Maine West (ftUS)",9001,4759,11834,9807,1,1,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,
-26841,"NAD83(NSRS2007) / Minnesota North (ftUS)",9001,4759,12234,9802,1,1,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26842,"NAD83(NSRS2007) / Minnesota Central (ftUS)",9001,4759,12235,9802,1,1,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26843,"NAD83(NSRS2007) / Minnesota South (ftUS)",9001,4759,12236,9802,1,1,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26844,"NAD83(NSRS2007) / Nebraska (ftUS)",9001,4759,15396,9802,1,1,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,
-26845,"NAD83(NSRS2007) / West Virginia North (ftUS)",9001,4759,14733,9802,1,1,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9001,8827,0,9001,,,
-26846,"NAD83(NSRS2007) / West Virginia South (ftUS)",9001,4759,14734,9802,1,1,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9001,8827,0,9001,,,
-26847,"NAD83 / Maine East (ftUS)",9003,4269,11833,9807,1,0,4497,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,
-26848,"NAD83 / Maine West (ftUS)",9003,4269,11834,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,
-26849,"NAD83 / Minnesota North (ftUS)",9003,4269,12234,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26850,"NAD83 / Minnesota Central (ftUS)",9003,4269,12235,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26851,"NAD83 / Minnesota South (ftUS)",9003,4269,12236,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26852,"NAD83 / Nebraska (ftUS)",9003,4269,15396,9802,1,0,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,
-26853,"NAD83 / West Virginia North (ftUS)",9003,4269,14735,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9003,8827,0,9003,,,
-26854,"NAD83 / West Virginia South (ftUS)",9003,4269,14736,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9003,8827,0,9003,,,
-26855,"NAD83(HARN) / Maine East (ftUS)",9003,4152,11833,9807,1,0,4497,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,
-26856,"NAD83(HARN) / Maine West (ftUS)",9003,4152,11834,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,
-26857,"NAD83(HARN) / Minnesota North (ftUS)",9003,4152,12234,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26858,"NAD83(HARN) / Minnesota Central (ftUS)",9003,4152,12235,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26859,"NAD83(HARN) / Minnesota South (ftUS)",9003,4152,12236,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26860,"NAD83(HARN) / Nebraska (ftUS)",9003,4152,15396,9802,1,0,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,
-26861,"NAD83(HARN) / West Virginia North (ftUS)",9003,4152,14735,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9003,8827,0,9003,,,
-26862,"NAD83(HARN) / West Virginia South (ftUS)",9003,4152,14736,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9003,8827,0,9003,,,
-26863,"NAD83(NSRS2007) / Maine East (ftUS)",9003,4759,11833,9807,1,0,4497,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,
-26864,"NAD83(NSRS2007) / Maine West (ftUS)",9003,4759,11834,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,
-26865,"NAD83(NSRS2007) / Minnesota North (ftUS)",9003,4759,12234,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26866,"NAD83(NSRS2007) / Minnesota Central (ftUS)",9003,4759,12235,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26867,"NAD83(NSRS2007) / Minnesota South (ftUS)",9003,4759,12236,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,
-26868,"NAD83(NSRS2007) / Nebraska (ftUS)",9003,4759,15396,9802,1,0,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,
-26869,"NAD83(NSRS2007) / West Virginia North (ftUS)",9003,4759,14735,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9003,8827,0,9003,,,
-26870,"NAD83(NSRS2007) / West Virginia South (ftUS)",9003,4759,14736,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9003,8827,0,9003,,,
-26891,"NAD83(CSRS) / MTM zone 11",9001,4617,17711,9807,1,0,4400,8801,0,9110,8802,-82.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-26892,"NAD83(CSRS) / MTM zone 12",9001,4617,17712,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-26893,"NAD83(CSRS) / MTM zone 13",9001,4617,17713,9807,1,0,4400,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-26894,"NAD83(CSRS) / MTM zone 14",9001,4617,17714,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-26895,"NAD83(CSRS) / MTM zone 15",9001,4617,17715,9807,1,0,4400,8801,0,9102,8802,-90,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-26896,"NAD83(CSRS) / MTM zone 16",9001,4617,17716,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-26897,"NAD83(CSRS) / MTM zone 17",9001,4617,17717,9807,1,0,4400,8801,0,9102,8802,-96,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-26898,"NAD83(CSRS) / MTM zone 1",9001,4617,17701,9807,1,0,4496,8801,0,9102,8802,-53,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-26899,"NAD83(CSRS) / MTM zone 2",9001,4617,17702,9807,1,0,4496,8801,0,9102,8802,-56,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-26901,"NAD83 / UTM zone 1N",9001,4269,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26902,"NAD83 / UTM zone 2N",9001,4269,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26903,"NAD83 / UTM zone 3N",9001,4269,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26904,"NAD83 / UTM zone 4N",9001,4269,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26905,"NAD83 / UTM zone 5N",9001,4269,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26906,"NAD83 / UTM zone 6N",9001,4269,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26907,"NAD83 / UTM zone 7N",9001,4269,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26908,"NAD83 / UTM zone 8N",9001,4269,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26909,"NAD83 / UTM zone 9N",9001,4269,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26910,"NAD83 / UTM zone 10N",9001,4269,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26911,"NAD83 / UTM zone 11N",9001,4269,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26912,"NAD83 / UTM zone 12N",9001,4269,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26913,"NAD83 / UTM zone 13N",9001,4269,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26914,"NAD83 / UTM zone 14N",9001,4269,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26915,"NAD83 / UTM zone 15N",9001,4269,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26916,"NAD83 / UTM zone 16N",9001,4269,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26917,"NAD83 / UTM zone 17N",9001,4269,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26918,"NAD83 / UTM zone 18N",9001,4269,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26919,"NAD83 / UTM zone 19N",9001,4269,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26920,"NAD83 / UTM zone 20N",9001,4269,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26921,"NAD83 / UTM zone 21N",9001,4269,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26922,"NAD83 / UTM zone 22N",9001,4269,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26923,"NAD83 / UTM zone 23N",9001,4269,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-26929,"NAD83 / Alabama East",9001,4269,10131,9807,1,0,4499,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,
-26930,"NAD83 / Alabama West",9001,4269,10132,9807,1,0,4499,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,600000,9001,8807,0,9001,,,,,,
-26931,"NAD83 / Alaska zone 1",9001,4269,15031,9812,1,0,4499,8806,5000000,9001,8807,-5000000,9001,8811,57,9110,8812,-133.4,9110,8813,323.07483685,9110,8814,323.07483685,9110,8815,0.9999,9201
-26932,"NAD83 / Alaska zone 2",9001,4269,15032,9807,1,0,4499,8801,54,9102,8802,-142,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26933,"NAD83 / Alaska zone 3",9001,4269,15033,9807,1,0,4499,8801,54,9102,8802,-146,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26934,"NAD83 / Alaska zone 4",9001,4269,15034,9807,1,0,4499,8801,54,9102,8802,-150,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26935,"NAD83 / Alaska zone 5",9001,4269,15035,9807,1,0,4499,8801,54,9102,8802,-154,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26936,"NAD83 / Alaska zone 6",9001,4269,15036,9807,1,0,4499,8801,54,9102,8802,-158,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26937,"NAD83 / Alaska zone 7",9001,4269,15037,9807,1,0,4499,8801,54,9102,8802,-162,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26938,"NAD83 / Alaska zone 8",9001,4269,15038,9807,1,0,4499,8801,54,9102,8802,-166,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26939,"NAD83 / Alaska zone 9",9001,4269,15039,9807,1,0,4499,8801,54,9102,8802,-170,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26940,"NAD83 / Alaska zone 10",9001,4269,15040,9802,1,0,4499,8821,51,9110,8822,-176,9110,8823,53.5,9110,8824,51.5,9110,8826,1000000,9001,8827,0,9001,,,
-26941,"NAD83 / California zone 1",9001,4269,10431,9802,1,0,4499,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9001,8827,500000,9001,,,
-26942,"NAD83 / California zone 2",9001,4269,10432,9802,1,0,4499,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9001,8827,500000,9001,,,
-26943,"NAD83 / California zone 3",9001,4269,10433,9802,1,0,4499,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9001,8827,500000,9001,,,
-26944,"NAD83 / California zone 4",9001,4269,10434,9802,1,0,4499,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9001,8827,500000,9001,,,
-26945,"NAD83 / California zone 5",9001,4269,10435,9802,1,0,4499,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9001,8827,500000,9001,,,
-26946,"NAD83 / California zone 6",9001,4269,10436,9802,1,0,4499,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9001,8827,500000,9001,,,
-26948,"NAD83 / Arizona East",9001,4269,10231,9807,1,0,4499,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,
-26949,"NAD83 / Arizona Central",9001,4269,10232,9807,1,0,4499,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,
-26950,"NAD83 / Arizona West",9001,4269,10233,9807,1,0,4499,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,213360,9001,8807,0,9001,,,,,,
-26951,"NAD83 / Arkansas North",9001,4269,10331,9802,1,0,4499,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,400000,9001,8827,0,9001,,,
-26952,"NAD83 / Arkansas South",9001,4269,10332,9802,1,0,4499,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,400000,9001,8827,400000,9001,,,
-26953,"NAD83 / Colorado North",9001,4269,10531,9802,1,0,4499,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-26954,"NAD83 / Colorado Central",9001,4269,10532,9802,1,0,4499,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-26955,"NAD83 / Colorado South",9001,4269,10533,9802,1,0,4499,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,
-26956,"NAD83 / Connecticut",9001,4269,10630,9802,1,0,4499,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,304800.6096,9001,8827,152400.3048,9001,,,
-26957,"NAD83 / Delaware",9001,4269,10730,9807,1,0,4499,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,200000,9001,8807,0,9001,,,,,,
-26958,"NAD83 / Florida East",9001,4269,10931,9807,1,0,4499,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,
-26959,"NAD83 / Florida West",9001,4269,10932,9807,1,0,4499,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,
-26960,"NAD83 / Florida North",9001,4269,10933,9802,1,0,4499,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,600000,9001,8827,0,9001,,,
-26961,"NAD83 / Hawaii zone 1",9001,4269,15131,9807,1,0,4499,8801,18.5,9110,8802,-155.3,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,
-26962,"NAD83 / Hawaii zone 2",9001,4269,15132,9807,1,0,4499,8801,20.2,9110,8802,-156.4,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,
-26963,"NAD83 / Hawaii zone 3",9001,4269,15133,9807,1,0,4499,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26964,"NAD83 / Hawaii zone 4",9001,4269,15134,9807,1,0,4499,8801,21.5,9110,8802,-159.3,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,
-26965,"NAD83 / Hawaii zone 5",9001,4269,15135,9807,1,0,4499,8801,21.4,9110,8802,-160.1,9110,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-26966,"NAD83 / Georgia East",9001,4269,11031,9807,1,0,4499,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,
-26967,"NAD83 / Georgia West",9001,4269,11032,9807,1,0,4499,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,700000,9001,8807,0,9001,,,,,,
-26968,"NAD83 / Idaho East",9001,4269,11131,9807,1,0,4499,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,200000,9001,8807,0,9001,,,,,,
-26969,"NAD83 / Idaho Central",9001,4269,11132,9807,1,0,4499,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9001,8807,0,9001,,,,,,
-26970,"NAD83 / Idaho West",9001,4269,11133,9807,1,0,4499,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,800000,9001,8807,0,9001,,,,,,
-26971,"NAD83 / Illinois East",9001,4269,11231,9807,1,0,4499,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,300000,9001,8807,0,9001,,,,,,
-26972,"NAD83 / Illinois West",9001,4269,11232,9807,1,0,4499,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,700000,9001,8807,0,9001,,,,,,
-26973,"NAD83 / Indiana East",9001,4269,11331,9807,1,0,4499,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,100000,9001,8807,250000,9001,,,,,,
-26974,"NAD83 / Indiana West",9001,4269,11332,9807,1,0,4499,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,900000,9001,8807,250000,9001,,,,,,
-26975,"NAD83 / Iowa North",9001,4269,11431,9802,1,0,4499,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,1500000,9001,8827,1000000,9001,,,
-26976,"NAD83 / Iowa South",9001,4269,11432,9802,1,0,4499,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,500000,9001,8827,0,9001,,,
-26977,"NAD83 / Kansas North",9001,4269,11531,9802,1,0,4499,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,400000,9001,8827,0,9001,,,
-26978,"NAD83 / Kansas South",9001,4269,11532,9802,1,0,4499,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,400000,9001,8827,400000,9001,,,
-26979,"NAD83 / Kentucky North",9001,4269,11631,9802,1,1,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,37.58,9110,8826,500000,9001,8827,0,9001,,,
-26980,"NAD83 / Kentucky South",9001,4269,11632,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,500000,9001,8827,500000,9001,,,
-26981,"NAD83 / Louisiana North",9001,4269,11731,9802,1,0,4499,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,1000000,9001,8827,0,9001,,,
-26982,"NAD83 / Louisiana South",9001,4269,11732,9802,1,0,4499,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,1000000,9001,8827,0,9001,,,
-26983,"NAD83 / Maine East",9001,4269,11831,9807,1,0,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,300000,9001,8807,0,9001,,,,,,
-26984,"NAD83 / Maine West",9001,4269,11832,9807,1,0,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,900000,9001,8807,0,9001,,,,,,
-26985,"NAD83 / Maryland",9001,4269,11930,9802,1,0,4499,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,400000,9001,8827,0,9001,,,
-26986,"NAD83 / Massachusetts Mainland",9001,4269,12031,9802,1,0,4499,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,200000,9001,8827,750000,9001,,,
-26987,"NAD83 / Massachusetts Island",9001,4269,12032,9802,1,0,4499,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,500000,9001,8827,0,9001,,,
-26988,"NAD83 / Michigan North",9001,4269,12141,9802,1,0,4499,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,8000000,9001,8827,0,9001,,,
-26989,"NAD83 / Michigan Central",9001,4269,12142,9802,1,0,4499,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,6000000,9001,8827,0,9001,,,
-26990,"NAD83 / Michigan South",9001,4269,12143,9802,1,0,4499,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,4000000,9001,8827,0,9001,,,
-26991,"NAD83 / Minnesota North",9001,4269,12231,9802,1,0,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,800000,9001,8827,100000,9001,,,
-26992,"NAD83 / Minnesota Central",9001,4269,12232,9802,1,0,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,800000,9001,8827,100000,9001,,,
-26993,"NAD83 / Minnesota South",9001,4269,12233,9802,1,0,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,800000,9001,8827,100000,9001,,,
-26994,"NAD83 / Mississippi East",9001,4269,12331,9807,1,0,4499,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,300000,9001,8807,0,9001,,,,,,
-26995,"NAD83 / Mississippi West",9001,4269,12332,9807,1,0,4499,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,700000,9001,8807,0,9001,,,,,,
-26996,"NAD83 / Missouri East",9001,4269,12431,9807,1,0,4499,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,250000,9001,8807,0,9001,,,,,,
-26997,"NAD83 / Missouri Central",9001,4269,12432,9807,1,0,4499,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9001,8807,0,9001,,,,,,
-26998,"NAD83 / Missouri West",9001,4269,12433,9807,1,0,4499,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,850000,9001,8807,0,9001,,,,,,
-27037,"Nahrwan 1967 / UTM zone 37N",9001,4270,16037,9807,1,1,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-27038,"Nahrwan 1967 / UTM zone 38N",9001,4270,16038,9807,1,1,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-27039,"Nahrwan 1967 / UTM zone 39N",9001,4270,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-27040,"Nahrwan 1967 / UTM zone 40N",9001,4270,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-27120,"Naparima 1972 / UTM zone 20N",9001,4271,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-27200,"NZGD49 / New Zealand Map Grid",9001,4272,19917,9811,1,0,4400,8801,-41,9102,8802,173,9102,8806,2510000,9001,8807,6023150,9001,,,,,,,,,
-27205,"NZGD49 / Mount Eden Circuit",9001,4272,17901,9807,1,0,4500,8801,-36.5247515,9110,8802,174.45516217,9110,8805,0.9999,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27206,"NZGD49 / Bay of Plenty Circuit",9001,4272,17902,9807,1,0,4500,8801,-37.45404993,9110,8802,176.27583101,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27207,"NZGD49 / Poverty Bay Circuit",9001,4272,17903,9807,1,0,4500,8801,-38.372893,9110,8802,177.53082906,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27208,"NZGD49 / Hawkes Bay Circuit",9001,4272,17904,9807,1,0,4500,8801,-39.39033455,9110,8802,176.40252499,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27209,"NZGD49 / Taranaki Circuit",9001,4272,17905,9807,1,0,4500,8801,-39.08087299,9110,8802,174.13408423,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27210,"NZGD49 / Tuhirangi Circuit",9001,4272,17906,9807,1,0,4500,8801,-39.30448934,9110,8802,175.38241325,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27211,"NZGD49 / Wanganui Circuit",9001,4272,17907,9807,1,0,4500,8801,-40.14310097,9110,8802,175.29171586,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27212,"NZGD49 / Wairarapa Circuit",9001,4272,17908,9807,1,0,4500,8801,-40.55319175,9110,8802,175.38504588,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27213,"NZGD49 / Wellington Circuit",9001,4272,17909,9807,1,0,4500,8801,-41.18047507,9110,8802,174.46358432,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27214,"NZGD49 / Collingwood Circuit",9001,4272,17910,9807,1,0,4500,8801,-40.42531326,9110,8802,172.40193674,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27215,"NZGD49 / Nelson Circuit",9001,4272,17911,9807,1,0,4500,8801,-41.1628361,9110,8802,173.17575405,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27216,"NZGD49 / Karamea Circuit",9001,4272,17912,9807,1,0,4500,8801,-41.17236815,9110,8802,172.06325015,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27217,"NZGD49 / Buller Circuit",9001,4272,17913,9807,1,0,4500,8801,-41.48388903,9110,8802,171.34525362,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27218,"NZGD49 / Grey Circuit",9001,4272,17914,9807,1,0,4500,8801,-42.20012994,9110,8802,171.32591767,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27219,"NZGD49 / Amuri Circuit",9001,4272,17915,9807,1,0,4500,8801,-42.41208197,9110,8802,173.00364802,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27220,"NZGD49 / Marlborough Circuit",9001,4272,17916,9807,1,0,4500,8801,-41.3240152,9110,8802,173.48074668,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27221,"NZGD49 / Hokitika Circuit",9001,4272,17917,9807,1,0,4500,8801,-42.53107605,9110,8802,170.58479766,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27222,"NZGD49 / Okarito Circuit",9001,4272,17918,9807,1,0,4500,8801,-43.06364613,9110,8802,170.1539333,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27223,"NZGD49 / Jacksons Bay Circuit",9001,4272,17919,9807,1,0,4500,8801,-43.58400904,9110,8802,168.36225612,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27224,"NZGD49 / Mount Pleasant Circuit",9001,4272,17920,9807,1,0,4500,8801,-43.35262953,9110,8802,172.43378969,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27225,"NZGD49 / Gawler Circuit",9001,4272,17921,9807,1,0,4500,8801,-43.44553616,9110,8802,171.21386945,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27226,"NZGD49 / Timaru Circuit",9001,4272,17922,9807,1,0,4500,8801,-44.24079933,9110,8802,171.0326103,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27227,"NZGD49 / Lindis Peak Circuit",9001,4272,17923,9807,1,0,4500,8801,-44.44069647,9110,8802,169.28039183,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27228,"NZGD49 / Mount Nicholas Circuit",9001,4272,17924,9807,1,0,4500,8801,-45.07584493,9110,8802,168.23551083,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27229,"NZGD49 / Mount York Circuit",9001,4272,17925,9807,1,0,4500,8801,-45.33494142,9110,8802,167.44199024,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27230,"NZGD49 / Observation Point Circuit",9001,4272,17926,9807,1,0,4500,8801,-45.48583078,9110,8802,170.37429426,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27231,"NZGD49 / North Taieri Circuit",9001,4272,17927,9807,1,0,4500,8801,-45.51414481,9110,8802,170.16573208,9110,8805,0.99996,9201,8806,300000,9001,8807,700000,9001,,,,,,
-27232,"NZGD49 / Bluff Circuit",9001,4272,17928,9807,1,0,4500,8801,-46.36000346,9110,8802,168.20343392,9110,8805,1,9201,8806,300002.66,9001,8807,699999.58,9001,,,,,,
-27258,"NZGD49 / UTM zone 58S",9001,4272,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-27259,"NZGD49 / UTM zone 59S",9001,4272,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-27260,"NZGD49 / UTM zone 60S",9001,4272,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-27291,"NZGD49 / North Island Grid",9040,4272,18141,9807,1,0,4409,8801,-39,9110,8802,175.3,9110,8805,1,9201,8806,300000,9040,8807,400000,9040,,,,,,
-27292,"NZGD49 / South Island Grid",9040,4272,18142,9807,1,0,4409,8801,-44,9110,8802,171.3,9110,8805,1,9201,8806,500000,9040,8807,500000,9040,,,,,,
-27391,"NGO 1948 (Oslo) / NGO zone I",9001,4817,18221,9807,1,0,4531,8801,58,9110,8802,-4.4,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-27392,"NGO 1948 (Oslo) / NGO zone II",9001,4817,18222,9807,1,0,4531,8801,58,9110,8802,-2.2,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-27393,"NGO 1948 (Oslo) / NGO zone III",9001,4817,18223,9807,1,0,4531,8801,58,9110,8802,0,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-27394,"NGO 1948 (Oslo) / NGO zone IV",9001,4817,18224,9807,1,0,4531,8801,58,9110,8802,2.3,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-27395,"NGO 1948 (Oslo) / NGO zone V",9001,4817,18225,9807,1,0,4531,8801,58,9110,8802,6.1,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-27396,"NGO 1948 (Oslo) / NGO zone VI",9001,4817,18226,9807,1,0,4531,8801,58,9110,8802,10.1,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-27397,"NGO 1948 (Oslo) / NGO zone VII",9001,4817,18227,9807,1,0,4531,8801,58,9110,8802,14.1,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-27398,"NGO 1948 (Oslo) / NGO zone VIII",9001,4817,18228,9807,1,0,4531,8801,58,9110,8802,18.2,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-27429,"Datum 73 / UTM zone 29N",9001,4274,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-27492,"Datum 73 / Modified Portuguese Grid",9001,4274,19974,9807,1,1,4530,8801,39.4,9110,8802,-8.0754862,9110,8805,1,9201,8806,180.598,9001,8807,-86.99,9001,,,,,,
-27493,"Datum 73 / Modified Portuguese Grid",9001,4274,19974,9807,1,0,4499,8801,39.4,9110,8802,-8.0754862,9110,8805,1,9201,8806,180.598,9001,8807,-86.99,9001,,,,,,
-27500,"ATF (Paris) / Nord de Guerre",9001,4901,19903,9801,1,0,4499,8801,55,9105,8802,6,9105,8805,0.99950908,9201,8806,500000,9001,8807,300000,9001,,,,,,
-27561,"NTF (Paris) / Lambert Nord France",9001,4807,18091,9801,1,0,4499,8801,55,9105,8802,0,9105,8805,0.999877341,9201,8806,600000,9001,8807,200000,9001,,,,,,
-27562,"NTF (Paris) / Lambert Centre France",9001,4807,18092,9801,1,0,4499,8801,52,9105,8802,0,9105,8805,0.99987742,9201,8806,600000,9001,8807,200000,9001,,,,,,
-27563,"NTF (Paris) / Lambert Sud France",9001,4807,18093,9801,1,0,4499,8801,49,9105,8802,0,9105,8805,0.999877499,9201,8806,600000,9001,8807,200000,9001,,,,,,
-27564,"NTF (Paris) / Lambert Corse",9001,4807,18094,9801,1,0,4499,8801,46.85,9105,8802,0,9105,8805,0.99994471,9201,8806,234.358,9001,8807,185861.369,9001,,,,,,
-27571,"NTF (Paris) / Lambert zone I",9001,4807,18081,9801,1,0,4499,8801,55,9105,8802,0,9105,8805,0.999877341,9201,8806,600000,9001,8807,1200000,9001,,,,,,
-27572,"NTF (Paris) / Lambert zone II",9001,4807,18082,9801,1,0,4499,8801,52,9105,8802,0,9105,8805,0.99987742,9201,8806,600000,9001,8807,2200000,9001,,,,,,
-27573,"NTF (Paris) / Lambert zone III",9001,4807,18083,9801,1,0,4499,8801,49,9105,8802,0,9105,8805,0.999877499,9201,8806,600000,9001,8807,3200000,9001,,,,,,
-27574,"NTF (Paris) / Lambert zone IV",9001,4807,18084,9801,1,0,4499,8801,46.85,9105,8802,0,9105,8805,0.99994471,9201,8806,234.358,9001,8807,4185861.369,9001,,,,,,
-27581,"NTF (Paris) / France I",9001,4807,18081,9801,1,1,4499,8801,55,9105,8802,0,9105,8805,0.999877341,9201,8806,600000,9001,8807,1200000,9001,,,,,,
-27582,"NTF (Paris) / France II",9001,4807,18082,9801,1,1,4499,8801,52,9105,8802,0,9105,8805,0.99987742,9201,8806,600000,9001,8807,2200000,9001,,,,,,
-27583,"NTF (Paris) / France III",9001,4807,18083,9801,1,1,4499,8801,49,9105,8802,0,9105,8805,0.999877499,9201,8806,600000,9001,8807,3200000,9001,,,,,,
-27584,"NTF (Paris) / France IV",9001,4807,18084,9801,1,1,4499,8801,46.85,9105,8802,0,9105,8805,0.99994471,9201,8806,234.358,9001,8807,4185861.369,9001,,,,,,
-27591,"NTF (Paris) / Nord France",9001,4807,18091,9801,1,1,4499,8801,55,9105,8802,0,9105,8805,0.999877341,9201,8806,600000,9001,8807,200000,9001,,,,,,
-27592,"NTF (Paris) / Centre France",9001,4807,18092,9801,1,1,4499,8801,52,9105,8802,0,9105,8805,0.99987742,9201,8806,600000,9001,8807,200000,9001,,,,,,
-27593,"NTF (Paris) / Sud France",9001,4807,18093,9801,1,1,4499,8801,49,9105,8802,0,9105,8805,0.999877499,9201,8806,600000,9001,8807,200000,9001,,,,,,
-27594,"NTF (Paris) / Corse",9001,4807,18094,9801,1,1,4499,8801,46.85,9105,8802,0,9105,8805,0.99994471,9201,8806,234.358,9001,8807,185861.369,9001,,,,,,
-27700,"OSGB 1936 / British National Grid",9001,4277,19916,9807,1,0,4400,8801,49,9102,8802,-2,9102,8805,0.9996012717,9201,8806,400000,9001,8807,-100000,9001,,,,,,
-28191,"Palestine 1923 / Palestine Grid",9001,4281,18201,9806,1,0,4400,8801,31.4402749,9110,8802,35.124349,9110,8806,170251.555,9001,8807,126867.909,9001,,,,,,,,,
-28192,"Palestine 1923 / Palestine Belt",9001,4281,18202,9807,1,0,4400,8801,31.4402749,9110,8802,35.124349,9110,8805,1,9201,8806,170251.555,9001,8807,1126867.909,9001,,,,,,
-28193,"Palestine 1923 / Israeli CS Grid",9001,4281,18203,9806,1,0,4400,8801,31.4402749,9110,8802,35.124349,9110,8806,170251.555,9001,8807,1126867.909,9001,,,,,,,,,
-28232,"Pointe Noire / UTM zone 32S",9001,4282,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28348,"GDA94 / MGA zone 48",9001,4283,17348,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28349,"GDA94 / MGA zone 49",9001,4283,17349,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28350,"GDA94 / MGA zone 50",9001,4283,17350,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28351,"GDA94 / MGA zone 51",9001,4283,17351,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28352,"GDA94 / MGA zone 52",9001,4283,17352,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28353,"GDA94 / MGA zone 53",9001,4283,17353,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28354,"GDA94 / MGA zone 54",9001,4283,17354,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28355,"GDA94 / MGA zone 55",9001,4283,17355,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28356,"GDA94 / MGA zone 56",9001,4283,17356,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28357,"GDA94 / MGA zone 57",9001,4283,17357,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28358,"GDA94 / MGA zone 58",9001,4283,17358,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-28402,"Pulkovo 1942 / Gauss-Kruger zone 2",9001,4284,16202,9807,1,1,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-28403,"Pulkovo 1942 / Gauss-Kruger zone 3",9001,4284,16203,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-28404,"Pulkovo 1942 / Gauss-Kruger zone 4",9001,4284,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-28405,"Pulkovo 1942 / Gauss-Kruger zone 5",9001,4284,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-28406,"Pulkovo 1942 / Gauss-Kruger zone 6",9001,4284,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-28407,"Pulkovo 1942 / Gauss-Kruger zone 7",9001,4284,16207,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-28408,"Pulkovo 1942 / Gauss-Kruger zone 8",9001,4284,16208,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-28409,"Pulkovo 1942 / Gauss-Kruger zone 9",9001,4284,16209,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,
-28410,"Pulkovo 1942 / Gauss-Kruger zone 10",9001,4284,16210,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,
-28411,"Pulkovo 1942 / Gauss-Kruger zone 11",9001,4284,16211,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,
-28412,"Pulkovo 1942 / Gauss-Kruger zone 12",9001,4284,16212,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,
-28413,"Pulkovo 1942 / Gauss-Kruger zone 13",9001,4284,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,
-28414,"Pulkovo 1942 / Gauss-Kruger zone 14",9001,4284,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,
-28415,"Pulkovo 1942 / Gauss-Kruger zone 15",9001,4284,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,
-28416,"Pulkovo 1942 / Gauss-Kruger zone 16",9001,4284,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,
-28417,"Pulkovo 1942 / Gauss-Kruger zone 17",9001,4284,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,
-28418,"Pulkovo 1942 / Gauss-Kruger zone 18",9001,4284,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,
-28419,"Pulkovo 1942 / Gauss-Kruger zone 19",9001,4284,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,
-28420,"Pulkovo 1942 / Gauss-Kruger zone 20",9001,4284,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,
-28421,"Pulkovo 1942 / Gauss-Kruger zone 21",9001,4284,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,
-28422,"Pulkovo 1942 / Gauss-Kruger zone 22",9001,4284,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,
-28423,"Pulkovo 1942 / Gauss-Kruger zone 23",9001,4284,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,
-28424,"Pulkovo 1942 / Gauss-Kruger zone 24",9001,4284,16224,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,
-28425,"Pulkovo 1942 / Gauss-Kruger zone 25",9001,4284,16225,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,
-28426,"Pulkovo 1942 / Gauss-Kruger zone 26",9001,4284,16226,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,
-28427,"Pulkovo 1942 / Gauss-Kruger zone 27",9001,4284,16227,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,
-28428,"Pulkovo 1942 / Gauss-Kruger zone 28",9001,4284,16228,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,
-28429,"Pulkovo 1942 / Gauss-Kruger zone 29",9001,4284,16229,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,
-28430,"Pulkovo 1942 / Gauss-Kruger zone 30",9001,4284,16230,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,
-28431,"Pulkovo 1942 / Gauss-Kruger zone 31",9001,4284,16231,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,
-28432,"Pulkovo 1942 / Gauss-Kruger zone 32",9001,4284,16232,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,
-28462,"Pulkovo 1942 / Gauss-Kruger 2N",9001,4284,16302,9807,1,1,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28463,"Pulkovo 1942 / Gauss-Kruger 3N",9001,4284,16303,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28464,"Pulkovo 1942 / Gauss-Kruger 4N",9001,4284,16304,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28465,"Pulkovo 1942 / Gauss-Kruger 5N",9001,4284,16305,9807,1,1,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28466,"Pulkovo 1942 / Gauss-Kruger 6N",9001,4284,16306,9807,1,1,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28467,"Pulkovo 1942 / Gauss-Kruger 7N",9001,4284,16307,9807,1,1,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28468,"Pulkovo 1942 / Gauss-Kruger 8N",9001,4284,16308,9807,1,1,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28469,"Pulkovo 1942 / Gauss-Kruger 9N",9001,4284,16309,9807,1,1,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28470,"Pulkovo 1942 / Gauss-Kruger 10N",9001,4284,16310,9807,1,1,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28471,"Pulkovo 1942 / Gauss-Kruger 11N",9001,4284,16311,9807,1,1,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28472,"Pulkovo 1942 / Gauss-Kruger 12N",9001,4284,16312,9807,1,1,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28473,"Pulkovo 1942 / Gauss-Kruger 13N",9001,4284,16313,9807,1,1,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28474,"Pulkovo 1942 / Gauss-Kruger 14N",9001,4284,16314,9807,1,1,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28475,"Pulkovo 1942 / Gauss-Kruger 15N",9001,4284,16315,9807,1,1,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28476,"Pulkovo 1942 / Gauss-Kruger 16N",9001,4284,16316,9807,1,1,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28477,"Pulkovo 1942 / Gauss-Kruger 17N",9001,4284,16317,9807,1,1,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28478,"Pulkovo 1942 / Gauss-Kruger 18N",9001,4284,16318,9807,1,1,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28479,"Pulkovo 1942 / Gauss-Kruger 19N",9001,4284,16319,9807,1,1,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28480,"Pulkovo 1942 / Gauss-Kruger 20N",9001,4284,16320,9807,1,1,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28481,"Pulkovo 1942 / Gauss-Kruger 21N",9001,4284,16321,9807,1,1,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28482,"Pulkovo 1942 / Gauss-Kruger 22N",9001,4284,16322,9807,1,1,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28483,"Pulkovo 1942 / Gauss-Kruger 23N",9001,4284,16323,9807,1,1,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28484,"Pulkovo 1942 / Gauss-Kruger 24N",9001,4284,16324,9807,1,1,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28485,"Pulkovo 1942 / Gauss-Kruger 25N",9001,4284,16325,9807,1,1,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28486,"Pulkovo 1942 / Gauss-Kruger 26N",9001,4284,16326,9807,1,1,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28487,"Pulkovo 1942 / Gauss-Kruger 27N",9001,4284,16327,9807,1,1,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28488,"Pulkovo 1942 / Gauss-Kruger 28N",9001,4284,16328,9807,1,1,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28489,"Pulkovo 1942 / Gauss-Kruger 29N",9001,4284,16329,9807,1,1,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28490,"Pulkovo 1942 / Gauss-Kruger 30N",9001,4284,16330,9807,1,1,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28491,"Pulkovo 1942 / Gauss-Kruger 31N",9001,4284,16331,9807,1,1,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28492,"Pulkovo 1942 / Gauss-Kruger 32N",9001,4284,16332,9807,1,1,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-28600,"Qatar 1974 / Qatar National Grid",9001,4285,19919,9807,1,0,4400,8801,24.27,9110,8802,51.13,9110,8805,0.99999,9201,8806,200000,9001,8807,300000,9001,,,,,,
-28991,"Amersfoort / RD Old",9001,4289,19913,9809,1,0,4499,8801,52.0922178,9110,8802,5.23155,9110,8805,0.9999079,9201,8806,0,9001,8807,0,9001,,,,,,
-28992,"Amersfoort / RD New",9001,4289,19914,9809,1,0,4499,8801,52.0922178,9110,8802,5.23155,9110,8805,0.9999079,9201,8806,155000,9001,8807,463000,9001,,,,,,
-29100,"SAD69 / Brazil Polyconic",9001,4291,19941,9818,1,1,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
-29101,"SAD69 / Brazil Polyconic",9001,4618,19941,9818,1,0,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
-29118,"SAD69 / UTM zone 18N",9001,4291,16018,9807,1,1,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29119,"SAD69 / UTM zone 19N",9001,4291,16019,9807,1,1,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29120,"SAD69 / UTM zone 20N",9001,4291,16020,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29121,"SAD69 / UTM zone 21N",9001,4291,16021,9807,1,1,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29122,"SAD69 / UTM zone 22N",9001,4291,16022,9807,1,1,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29168,"SAD69 / UTM zone 18N",9001,4618,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29169,"SAD69 / UTM zone 19N",9001,4618,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29170,"SAD69 / UTM zone 20N",9001,4618,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29171,"SAD69 / UTM zone 21N",9001,4618,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29172,"SAD69 / UTM zone 22N",9001,4618,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29177,"SAD69 / UTM zone 17S",9001,4291,16117,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29178,"SAD69 / UTM zone 18S",9001,4291,16118,9807,1,1,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29179,"SAD69 / UTM zone 19S",9001,4291,16119,9807,1,1,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29180,"SAD69 / UTM zone 20S",9001,4291,16120,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29181,"SAD69 / UTM zone 21S",9001,4291,16121,9807,1,1,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29182,"SAD69 / UTM zone 22S",9001,4291,16122,9807,1,1,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29183,"SAD69 / UTM zone 23S",9001,4291,16123,9807,1,1,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29184,"SAD69 / UTM zone 24S",9001,4291,16124,9807,1,1,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29185,"SAD69 / UTM zone 25S",9001,4291,16125,9807,1,1,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29187,"SAD69 / UTM zone 17S",9001,4618,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29188,"SAD69 / UTM zone 18S",9001,4618,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29189,"SAD69 / UTM zone 19S",9001,4618,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29190,"SAD69 / UTM zone 20S",9001,4618,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29191,"SAD69 / UTM zone 21S",9001,4618,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29192,"SAD69 / UTM zone 22S",9001,4618,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29193,"SAD69 / UTM zone 23S",9001,4618,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29194,"SAD69 / UTM zone 24S",9001,4618,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29195,"SAD69 / UTM zone 25S",9001,4618,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29220,"Sapper Hill 1943 / UTM zone 20S",9001,4292,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29221,"Sapper Hill 1943 / UTM zone 21S",9001,4292,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29333,"Schwarzeck / UTM zone 33S",9001,4293,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29371,"Schwarzeck / Lo22/11",9031,4293,17611,9808,1,0,6502,8801,-22,9102,8802,11,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,
-29373,"Schwarzeck / Lo22/13",9031,4293,17613,9808,1,0,6502,8801,-22,9102,8802,13,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,
-29375,"Schwarzeck / Lo22/15",9031,4293,17615,9808,1,0,6502,8801,-22,9102,8802,15,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,
-29377,"Schwarzeck / Lo22/17",9031,4293,17617,9808,1,0,6502,8801,-22,9102,8802,17,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,
-29379,"Schwarzeck / Lo22/19",9031,4293,17619,9808,1,0,6502,8801,-22,9102,8802,19,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,
-29381,"Schwarzeck / Lo22/21",9031,4293,17621,9808,1,0,6502,8801,-22,9102,8802,21,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,
-29383,"Schwarzeck / Lo22/23",9031,4293,17623,9808,1,0,6502,8801,-22,9102,8802,23,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,
-29385,"Schwarzeck / Lo22/25",9031,4293,17625,9808,1,0,6502,8801,-22,9102,8802,25,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,
-29635,"Sudan / UTM zone 35N",9001,4296,16035,9807,1,1,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29636,"Sudan / UTM zone 36N",9001,4296,16036,9807,1,1,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29700,"Tananarive (Paris) / Laborde Grid",9001,4810,19911,9815,1,1,4499,8811,-21,9105,8812,49,9105,8813,21,9105,8814,21,9105,8815,0.9995,9201,8816,400000,9001,8817,800000,9001
-29701,"Tananarive (Paris) / Laborde Grid",9001,4810,19861,9813,1,0,4530,8806,400000,9001,8807,800000,9001,8811,-21,9105,8812,49,9105,8813,21,9105,8815,0.9995,9201,,,
-29702,"Tananarive (Paris) / Laborde Grid approximation",9001,4810,19911,9815,1,0,4530,8811,-21,9105,8812,49,9105,8813,21,9105,8814,21,9105,8815,0.9995,9201,8816,400000,9001,8817,800000,9001
-29738,"Tananarive / UTM zone 38S",9001,4297,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29739,"Tananarive / UTM zone 39S",9001,4297,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-29849,"Timbalai 1948 / UTM zone 49N",9001,4298,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29850,"Timbalai 1948 / UTM zone 50N",9001,4298,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-29871,"Timbalai 1948 / RSO Borneo (ch)",9042,4298,19956,9815,1,0,4402,8811,4,9110,8812,115,9110,8813,53.18569537,9110,8814,53.07483685,9110,8815,0.99984,9201,8816,29352.4763,9042,8817,22014.3572,9042
-29872,"Timbalai 1948 / RSO Borneo (ft)",9041,4298,19957,9815,1,0,4405,8811,4,9110,8812,115,9110,8813,53.18569537,9110,8814,53.07483685,9110,8815,0.99984,9201,8816,1937263.44,9041,8817,1452947.58,9041
-29873,"Timbalai 1948 / RSO Borneo (m)",9001,4298,19958,9815,1,0,4400,8811,4,9110,8812,115,9110,8813,53.18569537,9110,8814,53.07483685,9110,8815,0.99984,9201,8816,590476.87,9001,8817,442857.65,9001
-29900,"TM65 / Irish National Grid",9001,4299,19908,9807,1,1,4400,8801,53.3,9110,8802,-8,9110,8805,1.000035,9201,8806,200000,9001,8807,250000,9001,,,,,,
-29901,"OSNI 1952 / Irish National Grid",9001,4188,19973,9807,1,0,4400,8801,53.3,9110,8802,-8,9110,8805,1,9201,8806,200000,9001,8807,250000,9001,,,,,,
-29902,"TM65 / Irish Grid",9001,4299,19972,9807,1,0,4400,8801,53.3,9110,8802,-8,9110,8805,1.000035,9201,8806,200000,9001,8807,250000,9001,,,,,,
-29903,"TM75 / Irish Grid",9001,4300,19972,9807,1,0,4400,8801,53.3,9110,8802,-8,9110,8805,1.000035,9201,8806,200000,9001,8807,250000,9001,,,,,,
-30161,"Tokyo / Japan Plane Rectangular CS I",9001,4301,17801,9807,1,0,4530,8801,33,9110,8802,129.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30162,"Tokyo / Japan Plane Rectangular CS II",9001,4301,17802,9807,1,0,4530,8801,33,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30163,"Tokyo / Japan Plane Rectangular CS III",9001,4301,17803,9807,1,0,4530,8801,36,9110,8802,132.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30164,"Tokyo / Japan Plane Rectangular CS IV",9001,4301,17804,9807,1,0,4530,8801,33,9110,8802,133.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30165,"Tokyo / Japan Plane Rectangular CS V",9001,4301,17805,9807,1,0,4530,8801,36,9110,8802,134.2,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30166,"Tokyo / Japan Plane Rectangular CS VI",9001,4301,17806,9807,1,0,4530,8801,36,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30167,"Tokyo / Japan Plane Rectangular CS VII",9001,4301,17807,9807,1,0,4530,8801,36,9110,8802,137.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30168,"Tokyo / Japan Plane Rectangular CS VIII",9001,4301,17808,9807,1,0,4530,8801,36,9110,8802,138.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30169,"Tokyo / Japan Plane Rectangular CS IX",9001,4301,17809,9807,1,0,4530,8801,36,9110,8802,139.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30170,"Tokyo / Japan Plane Rectangular CS X",9001,4301,17810,9807,1,0,4530,8801,40,9110,8802,140.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30171,"Tokyo / Japan Plane Rectangular CS XI",9001,4301,17811,9807,1,0,4530,8801,44,9110,8802,140.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30172,"Tokyo / Japan Plane Rectangular CS XII",9001,4301,17812,9807,1,0,4530,8801,44,9110,8802,142.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30173,"Tokyo / Japan Plane Rectangular CS XIII",9001,4301,17813,9807,1,0,4530,8801,44,9110,8802,144.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30174,"Tokyo / Japan Plane Rectangular CS XIV",9001,4301,17814,9807,1,0,4530,8801,26,9110,8802,142,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30175,"Tokyo / Japan Plane Rectangular CS XV",9001,4301,17815,9807,1,0,4530,8801,26,9110,8802,127.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30176,"Tokyo / Japan Plane Rectangular CS XVI",9001,4301,17816,9807,1,0,4530,8801,26,9110,8802,124,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30177,"Tokyo / Japan Plane Rectangular CS XVII",9001,4301,17817,9807,1,0,4530,8801,26,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30178,"Tokyo / Japan Plane Rectangular CS XVIII",9001,4301,17818,9807,1,0,4530,8801,20,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30179,"Tokyo / Japan Plane Rectangular CS XIX",9001,4301,17819,9807,1,0,4530,8801,26,9110,8802,154,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,
-30200,"Trinidad 1903 / Trinidad Grid",9039,4302,19925,9806,1,0,4407,8801,10.263,9110,8802,-61.2,9110,8806,430000,9039,8807,325000,9039,,,,,,,,,
-30339,"TC(1948) / UTM zone 39N",9001,4303,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-30340,"TC(1948) / UTM zone 40N",9001,4303,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-30491,"Voirol 1875 / Nord Algerie (ancienne)",9001,4304,18011,9801,1,0,4499,8801,40,9105,8802,3,9105,8805,0.999625544,9201,8806,500000,9001,8807,300000,9001,,,,,,
-30492,"Voirol 1875 / Sud Algerie (ancienne)",9001,4304,18012,9801,1,0,4499,8801,37,9105,8802,3,9105,8805,0.999625769,9201,8806,500000,9001,8807,300000,9001,,,,,,
-30493,"Voirol 1879 / Nord Algerie (ancienne)",9001,4671,18011,9801,1,0,4499,8801,40,9105,8802,3,9105,8805,0.999625544,9201,8806,500000,9001,8807,300000,9001,,,,,,
-30494,"Voirol 1879 / Sud Algerie (ancienne)",9001,4671,18012,9801,1,0,4499,8801,37,9105,8802,3,9105,8805,0.999625769,9201,8806,500000,9001,8807,300000,9001,,,,,,
-30729,"Nord Sahara 1959 / UTM zone 29N",9001,4307,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-30730,"Nord Sahara 1959 / UTM zone 30N",9001,4307,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-30731,"Nord Sahara 1959 / UTM zone 31N",9001,4307,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-30732,"Nord Sahara 1959 / UTM zone 32N",9001,4307,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-30791,"Nord Sahara 1959 / Nord Algerie",9001,4307,18021,9801,1,0,4499,8801,40,9105,8802,3,9105,8805,0.999625544,9201,8806,500135,9001,8807,300090,9001,,,,,,
-30792,"Nord Sahara 1959 / Sud Algerie",9001,4307,18022,9801,1,0,4499,8801,37,9105,8802,3,9105,8805,0.999625769,9201,8806,500135,9001,8807,300090,9001,,,,,,
-30800,RT38 2.5 gon W,9001,4308,19929,9807,1,1,4530,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-31028,"Yoff / UTM zone 28N",9001,4310,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31121,"Zanderij / UTM zone 21N",9001,4311,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31154,"Zanderij / TM 54 NW",9001,4311,17054,9807,1,0,4400,8801,0,9102,8802,-54,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31170,"Zanderij / Suriname Old TM",9001,4311,19954,9807,1,0,4400,8801,0,9110,8802,-55.41,9110,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31171,"Zanderij / Suriname TM",9001,4311,19955,9807,1,0,4400,8801,0,9110,8802,-55.41,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-31251,"MGI (Ferro) / Austria GK West Zone",9001,4805,18001,9807,1,0,4530,8801,0,9102,8802,28,9102,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,
-31252,"MGI (Ferro) / Austria GK Central Zone",9001,4805,18002,9807,1,0,4530,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,
-31253,"MGI (Ferro) / Austria GK East Zone",9001,4805,18003,9807,1,0,4530,8801,0,9102,8802,34,9102,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,
-31254,"MGI / Austria GK West",9001,4312,18004,9807,1,0,4530,8801,0,9110,8802,10.2,9110,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,
-31255,"MGI / Austria GK Central",9001,4312,18005,9807,1,0,4530,8801,0,9110,8802,13.2,9110,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,
-31256,"MGI / Austria GK East",9001,4312,18006,9807,1,0,4530,8801,0,9110,8802,16.2,9110,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,
-31257,"MGI / Austria GK M28",9001,4312,18007,9807,1,0,4530,8801,0,9110,8802,10.2,9110,8805,1,9201,8806,150000,9001,8807,-5000000,9001,,,,,,
-31258,"MGI / Austria GK M31",9001,4312,18008,9807,1,0,4530,8801,0,9110,8802,13.2,9110,8805,1,9201,8806,450000,9001,8807,-5000000,9001,,,,,,
-31259,"MGI / Austria GK M34",9001,4312,18009,9807,1,0,4530,8801,0,9110,8802,16.2,9110,8805,1,9201,8806,750000,9001,8807,-5000000,9001,,,,,,
-31265,"MGI / 3-degree Gauss zone 5",9001,4312,16265,9807,1,1,4499,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-31266,"MGI / 3-degree Gauss zone 6",9001,4312,16266,9807,1,1,4499,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,
-31267,"MGI / 3-degree Gauss zone 7",9001,4312,16267,9807,1,1,4499,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,
-31268,"MGI / 3-degree Gauss zone 8",9001,4312,16268,9807,1,1,4499,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,
-31275,"MGI / Balkans zone 5",9001,4312,18275,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,5500000,9001,8807,0,9001,,,,,,
-31276,"MGI / Balkans zone 6",9001,4312,18276,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,0.9999,9201,8806,6500000,9001,8807,0,9001,,,,,,
-31277,"MGI / Balkans zone 7",9001,4312,18277,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,
-31278,"MGI / Balkans zone 8",9001,4312,18277,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,
-31279,"MGI / Balkans zone 8",9001,4312,18278,9807,1,1,4530,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,8500000,9001,8807,0,9001,,,,,,
-31281,"MGI (Ferro) / Austria West Zone",9001,4805,18041,9807,1,0,4530,8801,0,9102,8802,28,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-31282,"MGI (Ferro) / Austria Central Zone",9001,4805,18042,9807,1,0,4530,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-31283,"MGI (Ferro) / Austria East Zone",9001,4805,18043,9807,1,0,4530,8801,0,9102,8802,34,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-31284,"MGI / Austria M28",9001,4312,18044,9807,1,0,4530,8801,0,9110,8802,10.2,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-31285,"MGI / Austria M31",9001,4312,18045,9807,1,0,4530,8801,0,9110,8802,13.2,9110,8805,1,9201,8806,450000,9001,8807,0,9001,,,,,,
-31286,"MGI / Austria M34",9001,4312,18046,9807,1,0,4530,8801,0,9110,8802,16.2,9110,8805,1,9201,8806,750000,9001,8807,0,9001,,,,,,
-31287,"MGI / Austria Lambert",9001,4312,19947,9802,1,0,4530,8821,47.3,9110,8822,13.2,9110,8823,49,9110,8824,46,9110,8826,400000,9001,8827,400000,9001,,,
-31288,"MGI (Ferro) / M28",9001,4805,18047,9807,1,0,4530,8801,0,9102,8802,28,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-31289,"MGI (Ferro) / M31",9001,4805,18048,9807,1,0,4530,8801,0,9102,8802,31,9102,8805,1,9201,8806,450000,9001,8807,0,9001,,,,,,
-31290,"MGI (Ferro) / M34",9001,4805,18049,9807,1,0,4530,8801,0,9102,8802,34,9102,8805,1,9201,8806,750000,9001,8807,0,9001,,,,,,
-31291,"MGI (Ferro) / Austria West Zone",9001,4805,18041,9807,1,1,4499,8801,0,9102,8802,28,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-31292,"MGI (Ferro) / Austria Central Zone",9001,4805,18042,9807,1,1,4499,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-31293,"MGI (Ferro) / Austria East Zone",9001,4805,18043,9807,1,1,4499,8801,0,9102,8802,34,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,
-31294,"MGI / M28",9001,4312,18044,9807,1,1,4499,8801,0,9110,8802,10.2,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,
-31295,"MGI / M31",9001,4312,18045,9807,1,1,4499,8801,0,9110,8802,13.2,9110,8805,1,9201,8806,450000,9001,8807,0,9001,,,,,,
-31296,"MGI / M34",9001,4312,18046,9807,1,1,4499,8801,0,9110,8802,16.2,9110,8805,1,9201,8806,750000,9001,8807,0,9001,,,,,,
-31297,"MGI / Austria Lambert",9001,4312,19947,9802,1,1,4499,8821,47.3,9110,8822,13.2,9110,8823,49,9110,8824,46,9110,8826,400000,9001,8827,400000,9001,,,
-31300,"Belge 1972 / Belge Lambert 72",9001,4313,19902,9803,1,0,4499,8821,90,9110,8822,4.2124983,9110,8823,49.5,9110,8824,51.1,9110,8826,150000.01256,9001,8827,5400088.4378,9001,,,
-31370,"Belge 1972 / Belgian Lambert 72",9001,4313,19961,9802,1,0,4499,8821,90,9110,8822,4.2202952,9110,8823,51.100000204,9110,8824,49.500000204,9110,8826,150000.013,9001,8827,5400088.438,9001,,,
-31461,"DHDN / 3-degree Gauss zone 1",9001,4314,16261,9807,1,1,4499,8801,0,9102,8802,3,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
-31462,"DHDN / 3-degree Gauss zone 2",9001,4314,16262,9807,1,1,4499,8801,0,9102,8802,6,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-31463,"DHDN / 3-degree Gauss zone 3",9001,4314,16263,9807,1,1,4499,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-31464,"DHDN / 3-degree Gauss zone 4",9001,4314,16264,9807,1,1,4499,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-31465,"DHDN / 3-degree Gauss zone 5",9001,4314,16265,9807,1,1,4499,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-31466,"DHDN / 3-degree Gauss-Kruger zone 2",9001,4314,16262,9807,1,0,4530,8801,0,9102,8802,6,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,
-31467,"DHDN / 3-degree Gauss-Kruger zone 3",9001,4314,16263,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,
-31468,"DHDN / 3-degree Gauss-Kruger zone 4",9001,4314,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,
-31469,"DHDN / 3-degree Gauss-Kruger zone 5",9001,4314,16265,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,
-31528,"Conakry 1905 / UTM zone 28N",9001,4315,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31529,"Conakry 1905 / UTM zone 29N",9001,4315,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31600,"Dealul Piscului 1930 / Stereo 33",9001,4316,19927,9809,1,0,4499,8801,45.54,9110,8802,25.23328772,9110,8805,0.9996667,9201,8806,500000,9001,8807,500000,9001,,,,,,
-31700,"Dealul Piscului 1970/ Stereo 70",9001,4317,19926,9809,1,1,4530,8801,46,9102,8802,25,9102,8805,0.99975,9201,8806,500000,9001,8807,500000,9001,,,,,,
-31838,"NGN / UTM zone 38N",9001,4318,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31839,"NGN / UTM zone 39N",9001,4318,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31900,"KUDAMS / KTM",9001,4319,19928,9807,1,1,4400,8801,0,9102,8802,48,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31901,"KUDAMS / KTM",9001,4319,19997,9807,1,0,4400,8801,0,9102,8802,48,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,
-31965,"SIRGAS 2000 / UTM zone 11N",9001,4674,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31966,"SIRGAS 2000 / UTM zone 12N",9001,4674,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31967,"SIRGAS 2000 / UTM zone 13N",9001,4674,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31968,"SIRGAS 2000 / UTM zone 14N",9001,4674,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31969,"SIRGAS 2000 / UTM zone 15N",9001,4674,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31970,"SIRGAS 2000 / UTM zone 16N",9001,4674,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31971,"SIRGAS 2000 / UTM zone 17N",9001,4674,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31972,"SIRGAS 2000 / UTM zone 18N",9001,4674,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31973,"SIRGAS 2000 / UTM zone 19N",9001,4674,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31974,"SIRGAS 2000 / UTM zone 20N",9001,4674,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31975,"SIRGAS 2000 / UTM zone 21N",9001,4674,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31976,"SIRGAS 2000 / UTM zone 22N",9001,4674,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31977,"SIRGAS 2000 / UTM zone 17S",9001,4674,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31978,"SIRGAS 2000 / UTM zone 18S",9001,4674,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31979,"SIRGAS 2000 / UTM zone 19S",9001,4674,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31980,"SIRGAS 2000 / UTM zone 20S",9001,4674,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31981,"SIRGAS 2000 / UTM zone 21S",9001,4674,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31982,"SIRGAS 2000 / UTM zone 22S",9001,4674,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31983,"SIRGAS 2000 / UTM zone 23S",9001,4674,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31984,"SIRGAS 2000 / UTM zone 24S",9001,4674,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31985,"SIRGAS 2000 / UTM zone 25S",9001,4674,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31986,"SIRGAS 1995 / UTM zone 17N",9001,4170,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31987,"SIRGAS 1995 / UTM zone 18N",9001,4170,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31988,"SIRGAS 1995 / UTM zone 19N",9001,4170,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31989,"SIRGAS 1995 / UTM zone 20N",9001,4170,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31990,"SIRGAS 1995 / UTM zone 21N",9001,4170,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31991,"SIRGAS 1995 / UTM zone 22N",9001,4170,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-31992,"SIRGAS 1995 / UTM zone 17S",9001,4170,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31993,"SIRGAS 1995 / UTM zone 18S",9001,4170,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31994,"SIRGAS 1995 / UTM zone 19S",9001,4170,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31995,"SIRGAS 1995 / UTM zone 20S",9001,4170,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31996,"SIRGAS 1995 / UTM zone 21S",9001,4170,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31997,"SIRGAS 1995 / UTM zone 22S",9001,4170,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31998,"SIRGAS 1995 / UTM zone 23S",9001,4170,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-31999,"SIRGAS 1995 / UTM zone 24S",9001,4170,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32000,"SIRGAS 1995 / UTM zone 25S",9001,4170,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32001,"NAD27 / Montana North",9003,4267,12501,9802,1,0,4497,8821,47,9110,8822,-109.3,9110,8823,48.43,9110,8824,47.51,9110,8826,2000000,9003,8827,0,9003,,,
-32002,"NAD27 / Montana Central",9003,4267,12502,9802,1,0,4497,8821,45.5,9110,8822,-109.3,9110,8823,47.53,9110,8824,46.27,9110,8826,2000000,9003,8827,0,9003,,,
-32003,"NAD27 / Montana South",9003,4267,12503,9802,1,0,4497,8821,44,9110,8822,-109.3,9110,8823,46.24,9110,8824,44.52,9110,8826,2000000,9003,8827,0,9003,,,
-32005,"NAD27 / Nebraska North",9003,4267,12601,9802,1,0,4497,8821,41.2,9110,8822,-100,9110,8823,41.51,9110,8824,42.49,9110,8826,2000000,9003,8827,0,9003,,,
-32006,"NAD27 / Nebraska South",9003,4267,12602,9802,1,0,4497,8821,39.4,9110,8822,-99.3,9110,8823,40.17,9110,8824,41.43,9110,8826,2000000,9003,8827,0,9003,,,
-32007,"NAD27 / Nevada East",9003,4267,12701,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-32008,"NAD27 / Nevada Central",9003,4267,12702,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-32009,"NAD27 / Nevada West",9003,4267,12703,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-32010,"NAD27 / New Hampshire",9003,4267,12800,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,
-32011,"NAD27 / New Jersey",9003,4267,12900,9807,1,0,4497,8801,38.5,9110,8802,-74.4,9110,8805,0.999975,9201,8806,2000000,9003,8807,0,9003,,,,,,
-32012,"NAD27 / New Mexico East",9003,4267,13001,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,
-32013,"NAD27 / New Mexico Central",9003,4267,13002,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,
-32014,"NAD27 / New Mexico West",9003,4267,13003,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,500000,9003,8807,0,9003,,,,,,
-32015,"NAD27 / New York East",9003,4267,13101,9807,1,0,4497,8801,40,9110,8802,-74.2,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,
-32016,"NAD27 / New York Central",9003,4267,13102,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,500000,9003,8807,0,9003,,,,,,
-32017,"NAD27 / New York West",9003,4267,13103,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,500000,9003,8807,0,9003,,,,,,
-32018,"NAD27 / New York Long Island",9003,4267,13104,9802,1,1,4497,8821,40.3,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,1000000,9003,8827,0,9003,,,
-32019,"NAD27 / North Carolina",9003,4267,13200,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,34.2,9110,8824,36.1,9110,8826,2000000,9003,8827,0,9003,,,
-32020,"NAD27 / North Dakota North",9003,4267,13301,9802,1,0,4497,8821,47,9110,8822,-100.3,9110,8823,47.26,9110,8824,48.44,9110,8826,2000000,9003,8827,0,9003,,,
-32021,"NAD27 / North Dakota South",9003,4267,13302,9802,1,0,4497,8821,45.4,9110,8822,-100.3,9110,8823,46.11,9110,8824,47.29,9110,8826,2000000,9003,8827,0,9003,,,
-32022,"NAD27 / Ohio North",9003,4267,13401,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,40.26,9110,8824,41.42,9110,8826,2000000,9003,8827,0,9003,,,
-32023,"NAD27 / Ohio South",9003,4267,13402,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,38.44,9110,8824,40.02,9110,8826,2000000,9003,8827,0,9003,,,
-32024,"NAD27 / Oklahoma North",9003,4267,13501,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,35.34,9110,8824,36.46,9110,8826,2000000,9003,8827,0,9003,,,
-32025,"NAD27 / Oklahoma South",9003,4267,13502,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,33.56,9110,8824,35.14,9110,8826,2000000,9003,8827,0,9003,,,
-32026,"NAD27 / Oregon North",9003,4267,13601,9802,1,0,4497,8821,43.4,9110,8822,-120.3,9110,8823,44.2,9110,8824,46,9110,8826,2000000,9003,8827,0,9003,,,
-32027,"NAD27 / Oregon South",9003,4267,13602,9802,1,0,4497,8821,41.4,9110,8822,-120.3,9110,8823,42.2,9110,8824,44,9110,8826,2000000,9003,8827,0,9003,,,
-32028,"NAD27 / Pennsylvania North",9003,4267,13701,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,40.53,9110,8824,41.57,9110,8826,2000000,9003,8827,0,9003,,,
-32029,"NAD27 / Pennsylvania South",9003,4267,13702,9802,1,1,4497,8821,39.2,9110,8822,-77.45,9110,8823,39.56,9110,8824,40.48,9110,8826,2000000,9003,8827,0,9003,,,
-32030,"NAD27 / Rhode Island",9003,4267,13800,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.9999938,9201,8806,500000,9003,8807,0,9003,,,,,,
-32031,"NAD27 / South Carolina North",9003,4267,13901,9802,1,0,4497,8821,33,9110,8822,-81,9110,8823,33.46,9110,8824,34.58,9110,8826,2000000,9003,8827,0,9003,,,
-32033,"NAD27 / South Carolina South",9003,4267,13902,9802,1,0,4497,8821,31.5,9110,8822,-81,9110,8823,32.2,9110,8824,33.4,9110,8826,2000000,9003,8827,0,9003,,,
-32034,"NAD27 / South Dakota North",9003,4267,14001,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,44.25,9110,8824,45.41,9110,8826,2000000,9003,8827,0,9003,,,
-32035,"NAD27 / South Dakota South",9003,4267,14002,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,42.5,9110,8824,44.24,9110,8826,2000000,9003,8827,0,9003,,,
-32036,"NAD27 / Tennessee",9003,4267,14100,9802,1,1,4497,8821,34.4,9110,8822,-86,9110,8823,35.15,9110,8824,36.25,9110,8826,100000,9003,8827,0,9003,,,
-32037,"NAD27 / Texas North",9003,4267,14201,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,34.39,9110,8824,36.11,9110,8826,2000000,9003,8827,0,9003,,,
-32038,"NAD27 / Texas North Central",9003,4267,14202,9802,1,0,4497,8821,31.4,9110,8822,-97.3,9110,8823,32.08,9110,8824,33.58,9110,8826,2000000,9003,8827,0,9003,,,
-32039,"NAD27 / Texas Central",9003,4267,14203,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,30.07,9110,8824,31.53,9110,8826,2000000,9003,8827,0,9003,,,
-32040,"NAD27 / Texas South Central",9003,4267,14204,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,28.23,9110,8824,30.17,9110,8826,2000000,9003,8827,0,9003,,,
-32041,"NAD27 / Texas South",9003,4267,14205,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,26.1,9110,8824,27.5,9110,8826,2000000,9003,8827,0,9003,,,
-32042,"NAD27 / Utah North",9003,4267,14301,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,40.43,9110,8824,41.47,9110,8826,2000000,9003,8827,0,9003,,,
-32043,"NAD27 / Utah Central",9003,4267,14302,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,39.01,9110,8824,40.39,9110,8826,2000000,9003,8827,0,9003,,,
-32044,"NAD27 / Utah South",9003,4267,14303,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,37.13,9110,8824,38.21,9110,8826,2000000,9003,8827,0,9003,,,
-32045,"NAD27 / Vermont",9003,4267,14400,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9003,8807,0,9003,,,,,,
-32046,"NAD27 / Virginia North",9003,4267,14501,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,38.02,9110,8824,39.12,9110,8826,2000000,9003,8827,0,9003,,,
-32047,"NAD27 / Virginia South",9003,4267,14502,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,36.46,9110,8824,37.58,9110,8826,2000000,9003,8827,0,9003,,,
-32048,"NAD27 / Washington North",9003,4267,14601,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,47.3,9110,8824,48.44,9110,8826,2000000,9003,8827,0,9003,,,
-32049,"NAD27 / Washington South",9003,4267,14602,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,45.5,9110,8824,47.2,9110,8826,2000000,9003,8827,0,9003,,,
-32050,"NAD27 / West Virginia North",9003,4267,14701,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,39,9110,8824,40.15,9110,8826,2000000,9003,8827,0,9003,,,
-32051,"NAD27 / West Virginia South",9003,4267,14702,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,37.29,9110,8824,38.53,9110,8826,2000000,9003,8827,0,9003,,,
-32052,"NAD27 / Wisconsin North",9003,4267,14801,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,45.34,9110,8824,46.46,9110,8826,2000000,9003,8827,0,9003,,,
-32053,"NAD27 / Wisconsin Central",9003,4267,14802,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,44.15,9110,8824,45.3,9110,8826,2000000,9003,8827,0,9003,,,
-32054,"NAD27 / Wisconsin South",9003,4267,14803,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,42.44,9110,8824,44.04,9110,8826,2000000,9003,8827,0,9003,,,
-32055,"NAD27 / Wyoming East",9003,4267,14901,9807,1,0,4497,8801,40.4,9110,8802,-105.1,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-32056,"NAD27 / Wyoming East Central",9003,4267,14902,9807,1,0,4497,8801,40.4,9110,8802,-107.2,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-32057,"NAD27 / Wyoming West Central",9003,4267,14903,9807,1,0,4497,8801,40.4,9110,8802,-108.45,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-32058,"NAD27 / Wyoming West",9003,4267,14904,9807,1,0,4497,8801,40.4,9110,8802,-110.05,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,
-32061,"NAD27 / Guatemala Norte",9001,4267,18211,9801,1,1,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,
-32062,"NAD27 / Guatemala Sur",9001,4267,18212,9801,1,1,4499,8801,14.54,9110,8802,-90.2,9110,8805,0.99989906,9201,8806,500000,9001,8807,325992.681,9001,,,,,,
-32064,"NAD27 / BLM 14N (ftUS)",9003,4267,15914,9807,1,0,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32065,"NAD27 / BLM 15N (ftUS)",9003,4267,15915,9807,1,0,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32066,"NAD27 / BLM 16N (ftUS)",9003,4267,15916,9807,1,0,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32067,"NAD27 / BLM 17N (ftUS)",9003,4267,15917,9807,1,0,4497,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32074,"NAD27 / BLM 14N (feet)",9003,4267,15914,9807,1,1,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32075,"NAD27 / BLM 15N (feet)",9003,4267,15915,9807,1,1,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32076,"NAD27 / BLM 16N (feet)",9003,4267,15916,9807,1,1,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32077,"NAD27 / BLM 17N (feet)",9003,4267,15917,9807,1,1,4497,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32081,"NAD27 / MTM zone 1",9001,4267,17701,9807,1,0,4400,8801,0,9102,8802,-53,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32082,"NAD27 / MTM zone 2",9001,4267,17702,9807,1,0,4400,8801,0,9102,8802,-56,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32083,"NAD27 / MTM zone 3",9001,4267,17703,9807,1,0,4400,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32084,"NAD27 / MTM zone 4",9001,4267,17704,9807,1,0,4400,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32085,"NAD27 / MTM zone 5",9001,4267,17705,9807,1,0,4400,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32086,"NAD27 / MTM zone 6",9001,4267,17706,9807,1,0,4400,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32098,"NAD27 / Quebec Lambert",9001,4267,19944,9802,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,
-32099,"NAD27 / Louisiana Offshore",9003,4267,11703,9802,1,0,4497,8821,25.4,9110,8822,-91.2,9110,8823,27.5,9110,8824,26.1,9110,8826,2000000,9003,8827,0,9003,,,
-32100,"NAD83 / Montana",9001,4269,12530,9802,1,0,4499,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,600000,9001,8827,0,9001,,,
-32104,"NAD83 / Nebraska",9001,4269,12630,9802,1,0,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,500000,9001,8827,0,9001,,,
-32107,"NAD83 / Nevada East",9001,4269,12731,9807,1,0,4499,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,200000,9001,8807,8000000,9001,,,,,,
-32108,"NAD83 / Nevada Central",9001,4269,12732,9807,1,0,4499,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9001,8807,6000000,9001,,,,,,
-32109,"NAD83 / Nevada West",9001,4269,12733,9807,1,0,4499,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,800000,9001,8807,4000000,9001,,,,,,
-32110,"NAD83 / New Hampshire",9001,4269,12830,9807,1,0,4499,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,300000,9001,8807,0,9001,,,,,,
-32111,"NAD83 / New Jersey",9001,4269,12930,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,
-32112,"NAD83 / New Mexico East",9001,4269,13031,9807,1,0,4499,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,165000,9001,8807,0,9001,,,,,,
-32113,"NAD83 / New Mexico Central",9001,4269,13032,9807,1,0,4499,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,
-32114,"NAD83 / New Mexico West",9001,4269,13033,9807,1,0,4499,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,830000,9001,8807,0,9001,,,,,,
-32115,"NAD83 / New York East",9001,4269,13131,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,
-32116,"NAD83 / New York Central",9001,4269,13132,9807,1,0,4499,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,250000,9001,8807,0,9001,,,,,,
-32117,"NAD83 / New York West",9001,4269,13133,9807,1,0,4499,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,350000,9001,8807,0,9001,,,,,,
-32118,"NAD83 / New York Long Island",9001,4269,13134,9802,1,0,4499,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,300000,9001,8827,0,9001,,,
-32119,"NAD83 / North Carolina",9001,4269,13230,9802,1,0,4499,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,609601.22,9001,8827,0,9001,,,
-32120,"NAD83 / North Dakota North",9001,4269,13331,9802,1,0,4499,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,600000,9001,8827,0,9001,,,
-32121,"NAD83 / North Dakota South",9001,4269,13332,9802,1,0,4499,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,600000,9001,8827,0,9001,,,
-32122,"NAD83 / Ohio North",9001,4269,13431,9802,1,0,4499,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,600000,9001,8827,0,9001,,,
-32123,"NAD83 / Ohio South",9001,4269,13432,9802,1,0,4499,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,600000,9001,8827,0,9001,,,
-32124,"NAD83 / Oklahoma North",9001,4269,13531,9802,1,0,4499,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,600000,9001,8827,0,9001,,,
-32125,"NAD83 / Oklahoma South",9001,4269,13532,9802,1,0,4499,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,600000,9001,8827,0,9001,,,
-32126,"NAD83 / Oregon North",9001,4269,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,
-32127,"NAD83 / Oregon South",9001,4269,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,
-32128,"NAD83 / Pennsylvania North",9001,4269,13731,9802,1,0,4499,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,600000,9001,8827,0,9001,,,
-32129,"NAD83 / Pennsylvania South",9001,4269,13732,9802,1,0,4499,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,600000,9001,8827,0,9001,,,
-32130,"NAD83 / Rhode Island",9001,4269,13830,9807,1,0,4499,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,100000,9001,8807,0,9001,,,,,,
-32133,"NAD83 / South Carolina",9001,4269,13930,9802,1,0,4499,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,609600,9001,8827,0,9001,,,
-32134,"NAD83 / South Dakota North",9001,4269,14031,9802,1,0,4499,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,600000,9001,8827,0,9001,,,
-32135,"NAD83 / South Dakota South",9001,4269,14032,9802,1,0,4499,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,600000,9001,8827,0,9001,,,
-32136,"NAD83 / Tennessee",9001,4269,14130,9802,1,0,4499,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,600000,9001,8827,0,9001,,,
-32137,"NAD83 / Texas North",9001,4269,14231,9802,1,0,4499,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,200000,9001,8827,1000000,9001,,,
-32138,"NAD83 / Texas North Central",9001,4269,14232,9802,1,0,4499,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,600000,9001,8827,2000000,9001,,,
-32139,"NAD83 / Texas Central",9001,4269,14233,9802,1,0,4499,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,700000,9001,8827,3000000,9001,,,
-32140,"NAD83 / Texas South Central",9001,4269,14234,9802,1,0,4499,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,600000,9001,8827,4000000,9001,,,
-32141,"NAD83 / Texas South",9001,4269,14235,9802,1,0,4499,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,300000,9001,8827,5000000,9001,,,
-32142,"NAD83 / Utah North",9001,4269,14331,9802,1,0,4499,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,500000,9001,8827,1000000,9001,,,
-32143,"NAD83 / Utah Central",9001,4269,14332,9802,1,0,4499,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,500000,9001,8827,2000000,9001,,,
-32144,"NAD83 / Utah South",9001,4269,14333,9802,1,0,4499,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,500000,9001,8827,3000000,9001,,,
-32145,"NAD83 / Vermont",9001,4269,14430,9807,1,0,4499,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9001,8807,0,9001,,,,,,
-32146,"NAD83 / Virginia North",9001,4269,14531,9802,1,0,4499,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,3500000,9001,8827,2000000,9001,,,
-32147,"NAD83 / Virginia South",9001,4269,14532,9802,1,0,4499,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,3500000,9001,8827,1000000,9001,,,
-32148,"NAD83 / Washington North",9001,4269,14631,9802,1,0,4499,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,500000,9001,8827,0,9001,,,
-32149,"NAD83 / Washington South",9001,4269,14632,9802,1,0,4499,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,500000,9001,8827,0,9001,,,
-32150,"NAD83 / West Virginia North",9001,4269,14731,9802,1,0,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,600000,9001,8827,0,9001,,,
-32151,"NAD83 / West Virginia South",9001,4269,14732,9802,1,0,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,600000,9001,8827,0,9001,,,
-32152,"NAD83 / Wisconsin North",9001,4269,14831,9802,1,0,4499,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,600000,9001,8827,0,9001,,,
-32153,"NAD83 / Wisconsin Central",9001,4269,14832,9802,1,0,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,
-32154,"NAD83 / Wisconsin South",9001,4269,14833,9802,1,0,4499,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,600000,9001,8827,0,9001,,,
-32155,"NAD83 / Wyoming East",9001,4269,14931,9807,1,0,4499,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,200000,9001,8807,0,9001,,,,,,
-32156,"NAD83 / Wyoming East Central",9001,4269,14932,9807,1,0,4499,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,400000,9001,8807,100000,9001,,,,,,
-32157,"NAD83 / Wyoming West Central",9001,4269,14933,9807,1,0,4499,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,600000,9001,8807,0,9001,,,,,,
-32158,"NAD83 / Wyoming West",9001,4269,14934,9807,1,0,4499,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,800000,9001,8807,100000,9001,,,,,,
-32161,"NAD83 / Puerto Rico & Virgin Is.",9001,4269,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,
-32164,"NAD83 / BLM 14N (ftUS)",9003,4269,15914,9807,1,0,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32165,"NAD83 / BLM 15N (ftUS)",9003,4269,15915,9807,1,0,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32166,"NAD83 / BLM 16N (ftUS)",9003,4269,15916,9807,1,0,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32167,"NAD83 / BLM 17N (ftUS)",9003,4269,15917,9807,1,0,4497,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32180,"NAD83 / SCoPQ zone 2",9001,4269,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32181,"NAD83 / MTM zone 1",9001,4269,17701,9807,1,0,4496,8801,0,9102,8802,-53,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32182,"NAD83 / MTM zone 2",9001,4269,17702,9807,1,0,4496,8801,0,9102,8802,-56,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32183,"NAD83 / MTM zone 3",9001,4269,17703,9807,1,0,4496,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32184,"NAD83 / MTM zone 4",9001,4269,17704,9807,1,0,4496,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32185,"NAD83 / MTM zone 5",9001,4269,17705,9807,1,0,4496,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32186,"NAD83 / MTM zone 6",9001,4269,17706,9807,1,0,4496,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32187,"NAD83 / MTM zone 7",9001,4269,17707,9807,1,0,4496,8801,0,9110,8802,-70.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32188,"NAD83 / MTM zone 8",9001,4269,17708,9807,1,0,4496,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32189,"NAD83 / MTM zone 9",9001,4269,17709,9807,1,0,4496,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32190,"NAD83 / MTM zone 10",9001,4269,17710,9807,1,0,4496,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32191,"NAD83 / MTM zone 11",9001,4269,17711,9807,1,0,4400,8801,0,9110,8802,-82.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32192,"NAD83 / MTM zone 12",9001,4269,17712,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32193,"NAD83 / MTM zone 13",9001,4269,17713,9807,1,0,4400,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32194,"NAD83 / MTM zone 14",9001,4269,17714,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32195,"NAD83 / MTM zone 15",9001,4269,17715,9807,1,0,4400,8801,0,9102,8802,-90,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32196,"NAD83 / MTM zone 16",9001,4269,17716,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32197,"NAD83 / MTM zone 17",9001,4269,17717,9807,1,0,4400,8801,0,9102,8802,-96,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,
-32198,"NAD83 / Quebec Lambert",9001,4269,19944,9802,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,
-32199,"NAD83 / Louisiana Offshore",9001,4269,11733,9802,1,0,4499,8821,25.3,9110,8822,-91.2,9110,8823,27.5,9110,8824,26.1,9110,8826,1000000,9001,8827,0,9001,,,
-32201,"WGS 72 / UTM zone 1N",9001,4322,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32202,"WGS 72 / UTM zone 2N",9001,4322,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32203,"WGS 72 / UTM zone 3N",9001,4322,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32204,"WGS 72 / UTM zone 4N",9001,4322,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32205,"WGS 72 / UTM zone 5N",9001,4322,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32206,"WGS 72 / UTM zone 6N",9001,4322,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32207,"WGS 72 / UTM zone 7N",9001,4322,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32208,"WGS 72 / UTM zone 8N",9001,4322,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32209,"WGS 72 / UTM zone 9N",9001,4322,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32210,"WGS 72 / UTM zone 10N",9001,4322,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32211,"WGS 72 / UTM zone 11N",9001,4322,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32212,"WGS 72 / UTM zone 12N",9001,4322,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32213,"WGS 72 / UTM zone 13N",9001,4322,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32214,"WGS 72 / UTM zone 14N",9001,4322,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32215,"WGS 72 / UTM zone 15N",9001,4322,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32216,"WGS 72 / UTM zone 16N",9001,4322,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32217,"WGS 72 / UTM zone 17N",9001,4322,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32218,"WGS 72 / UTM zone 18N",9001,4322,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32219,"WGS 72 / UTM zone 19N",9001,4322,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32220,"WGS 72 / UTM zone 20N",9001,4322,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32221,"WGS 72 / UTM zone 21N",9001,4322,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32222,"WGS 72 / UTM zone 22N",9001,4322,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32223,"WGS 72 / UTM zone 23N",9001,4322,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32224,"WGS 72 / UTM zone 24N",9001,4322,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32225,"WGS 72 / UTM zone 25N",9001,4322,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32226,"WGS 72 / UTM zone 26N",9001,4322,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32227,"WGS 72 / UTM zone 27N",9001,4322,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32228,"WGS 72 / UTM zone 28N",9001,4322,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32229,"WGS 72 / UTM zone 29N",9001,4322,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32230,"WGS 72 / UTM zone 30N",9001,4322,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32231,"WGS 72 / UTM zone 31N",9001,4322,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32232,"WGS 72 / UTM zone 32N",9001,4322,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32233,"WGS 72 / UTM zone 33N",9001,4322,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32234,"WGS 72 / UTM zone 34N",9001,4322,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32235,"WGS 72 / UTM zone 35N",9001,4322,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32236,"WGS 72 / UTM zone 36N",9001,4322,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32237,"WGS 72 / UTM zone 37N",9001,4322,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32238,"WGS 72 / UTM zone 38N",9001,4322,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32239,"WGS 72 / UTM zone 39N",9001,4322,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32240,"WGS 72 / UTM zone 40N",9001,4322,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32241,"WGS 72 / UTM zone 41N",9001,4322,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32242,"WGS 72 / UTM zone 42N",9001,4322,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32243,"WGS 72 / UTM zone 43N",9001,4322,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32244,"WGS 72 / UTM zone 44N",9001,4322,16044,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32245,"WGS 72 / UTM zone 45N",9001,4322,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32246,"WGS 72 / UTM zone 46N",9001,4322,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32247,"WGS 72 / UTM zone 47N",9001,4322,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32248,"WGS 72 / UTM zone 48N",9001,4322,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32249,"WGS 72 / UTM zone 49N",9001,4322,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32250,"WGS 72 / UTM zone 50N",9001,4322,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32251,"WGS 72 / UTM zone 51N",9001,4322,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32252,"WGS 72 / UTM zone 52N",9001,4322,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32253,"WGS 72 / UTM zone 53N",9001,4322,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32254,"WGS 72 / UTM zone 54N",9001,4322,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32255,"WGS 72 / UTM zone 55N",9001,4322,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32256,"WGS 72 / UTM zone 56N",9001,4322,16056,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32257,"WGS 72 / UTM zone 57N",9001,4322,16057,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32258,"WGS 72 / UTM zone 58N",9001,4322,16058,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32259,"WGS 72 / UTM zone 59N",9001,4322,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32260,"WGS 72 / UTM zone 60N",9001,4322,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32301,"WGS 72 / UTM zone 1S",9001,4322,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32302,"WGS 72 / UTM zone 2S",9001,4322,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32303,"WGS 72 / UTM zone 3S",9001,4322,16103,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32304,"WGS 72 / UTM zone 4S",9001,4322,16104,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32305,"WGS 72 / UTM zone 5S",9001,4322,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32306,"WGS 72 / UTM zone 6S",9001,4322,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32307,"WGS 72 / UTM zone 7S",9001,4322,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32308,"WGS 72 / UTM zone 8S",9001,4322,16108,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32309,"WGS 72 / UTM zone 9S",9001,4322,16109,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32310,"WGS 72 / UTM zone 10S",9001,4322,16110,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32311,"WGS 72 / UTM zone 11S",9001,4322,16111,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32312,"WGS 72 / UTM zone 12S",9001,4322,16112,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32313,"WGS 72 / UTM zone 13S",9001,4322,16113,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32314,"WGS 72 / UTM zone 14S",9001,4322,16114,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32315,"WGS 72 / UTM zone 15S",9001,4322,16115,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32316,"WGS 72 / UTM zone 16S",9001,4322,16116,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32317,"WGS 72 / UTM zone 17S",9001,4322,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32318,"WGS 72 / UTM zone 18S",9001,4322,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32319,"WGS 72 / UTM zone 19S",9001,4322,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32320,"WGS 72 / UTM zone 20S",9001,4322,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32321,"WGS 72 / UTM zone 21S",9001,4322,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32322,"WGS 72 / UTM zone 22S",9001,4322,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32323,"WGS 72 / UTM zone 23S",9001,4322,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32324,"WGS 72 / UTM zone 24S",9001,4322,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32325,"WGS 72 / UTM zone 25S",9001,4322,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32326,"WGS 72 / UTM zone 26S",9001,4322,16126,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32327,"WGS 72 / UTM zone 27S",9001,4322,16127,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32328,"WGS 72 / UTM zone 28S",9001,4322,16128,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32329,"WGS 72 / UTM zone 29S",9001,4322,16129,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32330,"WGS 72 / UTM zone 30S",9001,4322,16130,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32331,"WGS 72 / UTM zone 31S",9001,4322,16131,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32332,"WGS 72 / UTM zone 32S",9001,4322,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32333,"WGS 72 / UTM zone 33S",9001,4322,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32334,"WGS 72 / UTM zone 34S",9001,4322,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32335,"WGS 72 / UTM zone 35S",9001,4322,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32336,"WGS 72 / UTM zone 36S",9001,4322,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32337,"WGS 72 / UTM zone 37S",9001,4322,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32338,"WGS 72 / UTM zone 38S",9001,4322,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32339,"WGS 72 / UTM zone 39S",9001,4322,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32340,"WGS 72 / UTM zone 40S",9001,4322,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32341,"WGS 72 / UTM zone 41S",9001,4322,16141,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32342,"WGS 72 / UTM zone 42S",9001,4322,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32343,"WGS 72 / UTM zone 43S",9001,4322,16143,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32344,"WGS 72 / UTM zone 44S",9001,4322,16144,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32345,"WGS 72 / UTM zone 45S",9001,4322,16145,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32346,"WGS 72 / UTM zone 46S",9001,4322,16146,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32347,"WGS 72 / UTM zone 47S",9001,4322,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32348,"WGS 72 / UTM zone 48S",9001,4322,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32349,"WGS 72 / UTM zone 49S",9001,4322,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32350,"WGS 72 / UTM zone 50S",9001,4322,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32351,"WGS 72 / UTM zone 51S",9001,4322,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32352,"WGS 72 / UTM zone 52S",9001,4322,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32353,"WGS 72 / UTM zone 53S",9001,4322,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32354,"WGS 72 / UTM zone 54S",9001,4322,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32355,"WGS 72 / UTM zone 55S",9001,4322,16155,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32356,"WGS 72 / UTM zone 56S",9001,4322,16156,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32357,"WGS 72 / UTM zone 57S",9001,4322,16157,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32358,"WGS 72 / UTM zone 58S",9001,4322,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32359,"WGS 72 / UTM zone 59S",9001,4322,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32360,"WGS 72 / UTM zone 60S",9001,4322,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32401,"WGS 72BE / UTM zone 1N",9001,4324,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32402,"WGS 72BE / UTM zone 2N",9001,4324,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32403,"WGS 72BE / UTM zone 3N",9001,4324,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32404,"WGS 72BE / UTM zone 4N",9001,4324,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32405,"WGS 72BE / UTM zone 5N",9001,4324,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32406,"WGS 72BE / UTM zone 6N",9001,4324,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32407,"WGS 72BE / UTM zone 7N",9001,4324,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32408,"WGS 72BE / UTM zone 8N",9001,4324,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32409,"WGS 72BE / UTM zone 9N",9001,4324,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32410,"WGS 72BE / UTM zone 10N",9001,4324,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32411,"WGS 72BE / UTM zone 11N",9001,4324,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32412,"WGS 72BE / UTM zone 12N",9001,4324,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32413,"WGS 72BE / UTM zone 13N",9001,4324,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32414,"WGS 72BE / UTM zone 14N",9001,4324,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32415,"WGS 72BE / UTM zone 15N",9001,4324,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32416,"WGS 72BE / UTM zone 16N",9001,4324,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32417,"WGS 72BE / UTM zone 17N",9001,4324,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32418,"WGS 72BE / UTM zone 18N",9001,4324,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32419,"WGS 72BE / UTM zone 19N",9001,4324,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32420,"WGS 72BE / UTM zone 20N",9001,4324,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32421,"WGS 72BE / UTM zone 21N",9001,4324,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32422,"WGS 72BE / UTM zone 22N",9001,4324,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32423,"WGS 72BE / UTM zone 23N",9001,4324,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32424,"WGS 72BE / UTM zone 24N",9001,4324,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32425,"WGS 72BE / UTM zone 25N",9001,4324,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32426,"WGS 72BE / UTM zone 26N",9001,4324,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32427,"WGS 72BE / UTM zone 27N",9001,4324,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32428,"WGS 72BE / UTM zone 28N",9001,4324,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32429,"WGS 72BE / UTM zone 29N",9001,4324,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32430,"WGS 72BE / UTM zone 30N",9001,4324,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32431,"WGS 72BE / UTM zone 31N",9001,4324,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32432,"WGS 72BE / UTM zone 32N",9001,4324,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32433,"WGS 72BE / UTM zone 33N",9001,4324,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32434,"WGS 72BE / UTM zone 34N",9001,4324,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32435,"WGS 72BE / UTM zone 35N",9001,4324,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32436,"WGS 72BE / UTM zone 36N",9001,4324,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32437,"WGS 72BE / UTM zone 37N",9001,4324,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32438,"WGS 72BE / UTM zone 38N",9001,4324,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32439,"WGS 72BE / UTM zone 39N",9001,4324,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32440,"WGS 72BE / UTM zone 40N",9001,4324,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32441,"WGS 72BE / UTM zone 41N",9001,4324,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32442,"WGS 72BE / UTM zone 42N",9001,4324,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32443,"WGS 72BE / UTM zone 43N",9001,4324,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32444,"WGS 72BE / UTM zone 44N",9001,4324,16044,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32445,"WGS 72BE / UTM zone 45N",9001,4324,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32446,"WGS 72BE / UTM zone 46N",9001,4324,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32447,"WGS 72BE / UTM zone 47N",9001,4324,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32448,"WGS 72BE / UTM zone 48N",9001,4324,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32449,"WGS 72BE / UTM zone 49N",9001,4324,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32450,"WGS 72BE / UTM zone 50N",9001,4324,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32451,"WGS 72BE / UTM zone 51N",9001,4324,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32452,"WGS 72BE / UTM zone 52N",9001,4324,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32453,"WGS 72BE / UTM zone 53N",9001,4324,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32454,"WGS 72BE / UTM zone 54N",9001,4324,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32455,"WGS 72BE / UTM zone 55N",9001,4324,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32456,"WGS 72BE / UTM zone 56N",9001,4324,16056,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32457,"WGS 72BE / UTM zone 57N",9001,4324,16057,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32458,"WGS 72BE / UTM zone 58N",9001,4324,16058,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32459,"WGS 72BE / UTM zone 59N",9001,4324,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32460,"WGS 72BE / UTM zone 60N",9001,4324,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32501,"WGS 72BE / UTM zone 1S",9001,4324,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32502,"WGS 72BE / UTM zone 2S",9001,4324,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32503,"WGS 72BE / UTM zone 3S",9001,4324,16103,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32504,"WGS 72BE / UTM zone 4S",9001,4324,16104,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32505,"WGS 72BE / UTM zone 5S",9001,4324,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32506,"WGS 72BE / UTM zone 6S",9001,4324,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32507,"WGS 72BE / UTM zone 7S",9001,4324,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32508,"WGS 72BE / UTM zone 8S",9001,4324,16108,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32509,"WGS 72BE / UTM zone 9S",9001,4324,16109,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32510,"WGS 72BE / UTM zone 10S",9001,4324,16110,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32511,"WGS 72BE / UTM zone 11S",9001,4324,16111,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32512,"WGS 72BE / UTM zone 12S",9001,4324,16112,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32513,"WGS 72BE / UTM zone 13S",9001,4324,16113,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32514,"WGS 72BE / UTM zone 14S",9001,4324,16114,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32515,"WGS 72BE / UTM zone 15S",9001,4324,16115,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32516,"WGS 72BE / UTM zone 16S",9001,4324,16116,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32517,"WGS 72BE / UTM zone 17S",9001,4324,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32518,"WGS 72BE / UTM zone 18S",9001,4324,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32519,"WGS 72BE / UTM zone 19S",9001,4324,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32520,"WGS 72BE / UTM zone 20S",9001,4324,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32521,"WGS 72BE / UTM zone 21S",9001,4324,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32522,"WGS 72BE / UTM zone 22S",9001,4324,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32523,"WGS 72BE / UTM zone 23S",9001,4324,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32524,"WGS 72BE / UTM zone 24S",9001,4324,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32525,"WGS 72BE / UTM zone 25S",9001,4324,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32526,"WGS 72BE / UTM zone 26S",9001,4324,16126,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32527,"WGS 72BE / UTM zone 27S",9001,4324,16127,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32528,"WGS 72BE / UTM zone 28S",9001,4324,16128,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32529,"WGS 72BE / UTM zone 29S",9001,4324,16129,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32530,"WGS 72BE / UTM zone 30S",9001,4324,16130,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32531,"WGS 72BE / UTM zone 31S",9001,4324,16131,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32532,"WGS 72BE / UTM zone 32S",9001,4324,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32533,"WGS 72BE / UTM zone 33S",9001,4324,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32534,"WGS 72BE / UTM zone 34S",9001,4324,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32535,"WGS 72BE / UTM zone 35S",9001,4324,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32536,"WGS 72BE / UTM zone 36S",9001,4324,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32537,"WGS 72BE / UTM zone 37S",9001,4324,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32538,"WGS 72BE / UTM zone 38S",9001,4324,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32539,"WGS 72BE / UTM zone 39S",9001,4324,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32540,"WGS 72BE / UTM zone 40S",9001,4324,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32541,"WGS 72BE / UTM zone 41S",9001,4324,16141,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32542,"WGS 72BE / UTM zone 42S",9001,4324,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32543,"WGS 72BE / UTM zone 43S",9001,4324,16143,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32544,"WGS 72BE / UTM zone 44S",9001,4324,16144,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32545,"WGS 72BE / UTM zone 45S",9001,4324,16145,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32546,"WGS 72BE / UTM zone 46S",9001,4324,16146,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32547,"WGS 72BE / UTM zone 47S",9001,4324,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32548,"WGS 72BE / UTM zone 48S",9001,4324,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32549,"WGS 72BE / UTM zone 49S",9001,4324,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32550,"WGS 72BE / UTM zone 50S",9001,4324,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32551,"WGS 72BE / UTM zone 51S",9001,4324,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32552,"WGS 72BE / UTM zone 52S",9001,4324,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32553,"WGS 72BE / UTM zone 53S",9001,4324,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32554,"WGS 72BE / UTM zone 54S",9001,4324,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32555,"WGS 72BE / UTM zone 55S",9001,4324,16155,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32556,"WGS 72BE / UTM zone 56S",9001,4324,16156,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32557,"WGS 72BE / UTM zone 57S",9001,4324,16157,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32558,"WGS 72BE / UTM zone 58S",9001,4324,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32559,"WGS 72BE / UTM zone 59S",9001,4324,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32560,"WGS 72BE / UTM zone 60S",9001,4324,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32600,"WGS 84 / UTM grid system (northern hemisphere)",9001,4326,16000,9824,1,0,4400,8801,0,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,8830,-180,9102,8831,6,9102,,,
-32601,"WGS 84 / UTM zone 1N",9001,4326,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32602,"WGS 84 / UTM zone 2N",9001,4326,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32603,"WGS 84 / UTM zone 3N",9001,4326,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32604,"WGS 84 / UTM zone 4N",9001,4326,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32605,"WGS 84 / UTM zone 5N",9001,4326,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32606,"WGS 84 / UTM zone 6N",9001,4326,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32607,"WGS 84 / UTM zone 7N",9001,4326,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32608,"WGS 84 / UTM zone 8N",9001,4326,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32609,"WGS 84 / UTM zone 9N",9001,4326,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32610,"WGS 84 / UTM zone 10N",9001,4326,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32611,"WGS 84 / UTM zone 11N",9001,4326,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32612,"WGS 84 / UTM zone 12N",9001,4326,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32613,"WGS 84 / UTM zone 13N",9001,4326,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32614,"WGS 84 / UTM zone 14N",9001,4326,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32615,"WGS 84 / UTM zone 15N",9001,4326,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32616,"WGS 84 / UTM zone 16N",9001,4326,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32617,"WGS 84 / UTM zone 17N",9001,4326,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32618,"WGS 84 / UTM zone 18N",9001,4326,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32619,"WGS 84 / UTM zone 19N",9001,4326,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32620,"WGS 84 / UTM zone 20N",9001,4326,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32621,"WGS 84 / UTM zone 21N",9001,4326,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32622,"WGS 84 / UTM zone 22N",9001,4326,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32623,"WGS 84 / UTM zone 23N",9001,4326,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32624,"WGS 84 / UTM zone 24N",9001,4326,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32625,"WGS 84 / UTM zone 25N",9001,4326,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32626,"WGS 84 / UTM zone 26N",9001,4326,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32627,"WGS 84 / UTM zone 27N",9001,4326,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32628,"WGS 84 / UTM zone 28N",9001,4326,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32629,"WGS 84 / UTM zone 29N",9001,4326,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32630,"WGS 84 / UTM zone 30N",9001,4326,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32631,"WGS 84 / UTM zone 31N",9001,4326,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32632,"WGS 84 / UTM zone 32N",9001,4326,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32633,"WGS 84 / UTM zone 33N",9001,4326,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32634,"WGS 84 / UTM zone 34N",9001,4326,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32635,"WGS 84 / UTM zone 35N",9001,4326,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32636,"WGS 84 / UTM zone 36N",9001,4326,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32637,"WGS 84 / UTM zone 37N",9001,4326,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32638,"WGS 84 / UTM zone 38N",9001,4326,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32639,"WGS 84 / UTM zone 39N",9001,4326,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32640,"WGS 84 / UTM zone 40N",9001,4326,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32641,"WGS 84 / UTM zone 41N",9001,4326,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32642,"WGS 84 / UTM zone 42N",9001,4326,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32643,"WGS 84 / UTM zone 43N",9001,4326,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32644,"WGS 84 / UTM zone 44N",9001,4326,16044,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32645,"WGS 84 / UTM zone 45N",9001,4326,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32646,"WGS 84 / UTM zone 46N",9001,4326,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32647,"WGS 84 / UTM zone 47N",9001,4326,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32648,"WGS 84 / UTM zone 48N",9001,4326,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32649,"WGS 84 / UTM zone 49N",9001,4326,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32650,"WGS 84 / UTM zone 50N",9001,4326,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32651,"WGS 84 / UTM zone 51N",9001,4326,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32652,"WGS 84 / UTM zone 52N",9001,4326,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32653,"WGS 84 / UTM zone 53N",9001,4326,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32654,"WGS 84 / UTM zone 54N",9001,4326,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32655,"WGS 84 / UTM zone 55N",9001,4326,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32656,"WGS 84 / UTM zone 56N",9001,4326,16056,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32657,"WGS 84 / UTM zone 57N",9001,4326,16057,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32658,"WGS 84 / UTM zone 58N",9001,4326,16058,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32659,"WGS 84 / UTM zone 59N",9001,4326,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32660,"WGS 84 / UTM zone 60N",9001,4326,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
-32661,"WGS 84 / UPS North (N,E)",9001,4326,16061,9810,1,0,4493,8801,90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
-32662,"WGS 84 / Plate Carree",9001,4326,19968,9823,1,1,4499,8801,0,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,
-32663,"WGS 84 / World Equidistant Cylindrical",9001,4326,19846,9842,1,1,4499,8801,0,9102,8806,0,9001,8807,0,9001,8822,0,9102,,,,,,,,,
-32664,"WGS 84 / BLM 14N (ftUS)",9003,4326,15914,9807,1,0,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32665,"WGS 84 / BLM 15N (ftUS)",9003,4326,15915,9807,1,0,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32666,"WGS 84 / BLM 16N (ftUS)",9003,4326,15916,9807,1,0,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32667,"WGS 84 / BLM 17N (ftUS)",9003,4326,15917,9807,1,0,4497,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,
-32700,"WGS 84 / UTM grid system (southern hemisphere)",9001,4326,16100,9824,1,0,4400,8801,0,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,8830,-180,9102,8831,6,9102,,,
-32701,"WGS 84 / UTM zone 1S",9001,4326,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32702,"WGS 84 / UTM zone 2S",9001,4326,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32703,"WGS 84 / UTM zone 3S",9001,4326,16103,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32704,"WGS 84 / UTM zone 4S",9001,4326,16104,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32705,"WGS 84 / UTM zone 5S",9001,4326,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32706,"WGS 84 / UTM zone 6S",9001,4326,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32707,"WGS 84 / UTM zone 7S",9001,4326,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32708,"WGS 84 / UTM zone 8S",9001,4326,16108,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32709,"WGS 84 / UTM zone 9S",9001,4326,16109,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32710,"WGS 84 / UTM zone 10S",9001,4326,16110,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32711,"WGS 84 / UTM zone 11S",9001,4326,16111,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32712,"WGS 84 / UTM zone 12S",9001,4326,16112,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32713,"WGS 84 / UTM zone 13S",9001,4326,16113,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32714,"WGS 84 / UTM zone 14S",9001,4326,16114,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32715,"WGS 84 / UTM zone 15S",9001,4326,16115,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32716,"WGS 84 / UTM zone 16S",9001,4326,16116,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32717,"WGS 84 / UTM zone 17S",9001,4326,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32718,"WGS 84 / UTM zone 18S",9001,4326,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32719,"WGS 84 / UTM zone 19S",9001,4326,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32720,"WGS 84 / UTM zone 20S",9001,4326,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32721,"WGS 84 / UTM zone 21S",9001,4326,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32722,"WGS 84 / UTM zone 22S",9001,4326,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32723,"WGS 84 / UTM zone 23S",9001,4326,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32724,"WGS 84 / UTM zone 24S",9001,4326,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32725,"WGS 84 / UTM zone 25S",9001,4326,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32726,"WGS 84 / UTM zone 26S",9001,4326,16126,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32727,"WGS 84 / UTM zone 27S",9001,4326,16127,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32728,"WGS 84 / UTM zone 28S",9001,4326,16128,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32729,"WGS 84 / UTM zone 29S",9001,4326,16129,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32730,"WGS 84 / UTM zone 30S",9001,4326,16130,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32731,"WGS 84 / UTM zone 31S",9001,4326,16131,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32732,"WGS 84 / UTM zone 32S",9001,4326,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32733,"WGS 84 / UTM zone 33S",9001,4326,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32734,"WGS 84 / UTM zone 34S",9001,4326,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32735,"WGS 84 / UTM zone 35S",9001,4326,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32736,"WGS 84 / UTM zone 36S",9001,4326,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32737,"WGS 84 / UTM zone 37S",9001,4326,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32738,"WGS 84 / UTM zone 38S",9001,4326,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32739,"WGS 84 / UTM zone 39S",9001,4326,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32740,"WGS 84 / UTM zone 40S",9001,4326,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32741,"WGS 84 / UTM zone 41S",9001,4326,16141,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32742,"WGS 84 / UTM zone 42S",9001,4326,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32743,"WGS 84 / UTM zone 43S",9001,4326,16143,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32744,"WGS 84 / UTM zone 44S",9001,4326,16144,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32745,"WGS 84 / UTM zone 45S",9001,4326,16145,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32746,"WGS 84 / UTM zone 46S",9001,4326,16146,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32747,"WGS 84 / UTM zone 47S",9001,4326,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32748,"WGS 84 / UTM zone 48S",9001,4326,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32749,"WGS 84 / UTM zone 49S",9001,4326,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32750,"WGS 84 / UTM zone 50S",9001,4326,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32751,"WGS 84 / UTM zone 51S",9001,4326,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32752,"WGS 84 / UTM zone 52S",9001,4326,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32753,"WGS 84 / UTM zone 53S",9001,4326,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32754,"WGS 84 / UTM zone 54S",9001,4326,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32755,"WGS 84 / UTM zone 55S",9001,4326,16155,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32756,"WGS 84 / UTM zone 56S",9001,4326,16156,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32757,"WGS 84 / UTM zone 57S",9001,4326,16157,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32758,"WGS 84 / UTM zone 58S",9001,4326,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32759,"WGS 84 / UTM zone 59S",9001,4326,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32760,"WGS 84 / UTM zone 60S",9001,4326,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
-32761,"WGS 84 / UPS South (N,E)",9001,4326,16161,9810,1,0,4494,8801,-90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,
-32766,"WGS 84 / TM 36 SE",9001,4326,16636,9807,1,0,4400,8801,0,9102,8802,36,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
+"COORD_REF_SYS_CODE","COORD_REF_SYS_NAME","UOM_CODE","SOURCE_GEOGCRS_CODE","COORD_OP_CODE","COORD_OP_METHOD_CODE","SHOW_CRS","DEPRECATED","COORD_SYS_CODE","PARAMETER_CODE_1","PARAMETER_VALUE_1","PARAMETER_UOM_1","PARAMETER_CODE_2","PARAMETER_VALUE_2","PARAMETER_UOM_2","PARAMETER_CODE_3","PARAMETER_VALUE_3","PARAMETER_UOM_3","PARAMETER_CODE_4","PARAMETER_VALUE_4","PARAMETER_UOM_4","PARAMETER_CODE_5","PARAMETER_VALUE_5","PARAMETER_UOM_5","PARAMETER_CODE_6","PARAMETER_VALUE_6","PARAMETER_UO [...]
+2000,"Anguilla 1957 / British West Indies Grid",9001,4600,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,,,,,,,,
+2001,"Antigua 1943 / British West Indies Grid",9001,4601,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,,,,,,,,
+2002,"Dominica 1945 / British West Indies Grid",9001,4602,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,,,,,,,,
+2003,"Grenada 1953 / British West Indies Grid",9001,4603,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,,,,,,,,
+2004,"Montserrat 1958 / British West Indies Grid",9001,4604,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,,,,,,,,
+2005,"St. Kitts 1955 / British West Indies Grid",9001,4605,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,,,,,,,,
+2006,"St. Lucia 1955 / British West Indies Grid",9001,4606,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,,,,,,,,
+2007,"St. Vincent 45 / British West Indies Grid",9001,4607,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,,,,,,,,
+2008,"NAD27(CGQ77) / SCoPQ zone 2",9001,4609,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2009,"NAD27(CGQ77) / SCoPQ zone 3",9001,4609,17703,9807,1,0,4499,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2010,"NAD27(CGQ77) / SCoPQ zone 4",9001,4609,17704,9807,1,0,4499,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2011,"NAD27(CGQ77) / SCoPQ zone 5",9001,4609,17705,9807,1,0,4499,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2012,"NAD27(CGQ77) / SCoPQ zone 6",9001,4609,17706,9807,1,0,4499,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2013,"NAD27(CGQ77) / SCoPQ zone 7",9001,4609,17707,9807,1,0,4499,8801,0,9110,8802,-70.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2014,"NAD27(CGQ77) / SCoPQ zone 8",9001,4609,17708,9807,1,0,4499,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2015,"NAD27(CGQ77) / SCoPQ zone 9",9001,4609,17709,9807,1,0,4499,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2016,"NAD27(CGQ77) / SCoPQ zone 10",9001,4609,17710,9807,1,0,4499,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2017,"NAD27(76) / MTM zone 8",9001,4608,17708,9807,1,0,4499,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2018,"NAD27(76) / MTM zone 9",9001,4608,17709,9807,1,0,4499,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2019,"NAD27(76) / MTM zone 10",9001,4608,17710,9807,1,0,4499,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2020,"NAD27(76) / MTM zone 11",9001,4608,17711,9807,1,0,4400,8801,0,9110,8802,-82.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2021,"NAD27(76) / MTM zone 12",9001,4608,17712,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2022,"NAD27(76) / MTM zone 13",9001,4608,17713,9807,1,0,4400,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2023,"NAD27(76) / MTM zone 14",9001,4608,17714,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2024,"NAD27(76) / MTM zone 15",9001,4608,17715,9807,1,0,4400,8801,0,9102,8802,-90,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2025,"NAD27(76) / MTM zone 16",9001,4608,17716,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2026,"NAD27(76) / MTM zone 17",9001,4608,17717,9807,1,0,4400,8801,0,9102,8802,-96,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2027,"NAD27(76) / UTM zone 15N",9001,4608,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2028,"NAD27(76) / UTM zone 16N",9001,4608,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2029,"NAD27(76) / UTM zone 17N",9001,4608,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2030,"NAD27(76) / UTM zone 18N",9001,4608,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2031,"NAD27(CGQ77) / UTM zone 17N",9001,4609,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2032,"NAD27(CGQ77) / UTM zone 18N",9001,4609,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2033,"NAD27(CGQ77) / UTM zone 19N",9001,4609,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2034,"NAD27(CGQ77) / UTM zone 20N",9001,4609,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2035,"NAD27(CGQ77) / UTM zone 21N",9001,4609,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2036,"NAD83(CSRS98) / New Brunswick Stereo",9001,4140,19946,9809,1,1,4500,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,2500000,9001,8807,7500000,9001,,,,,,,,,,,,,
+2037,"NAD83(CSRS98) / UTM zone 19N",9001,4140,16019,9807,1,1,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2038,"NAD83(CSRS98) / UTM zone 20N",9001,4140,16020,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2039,"Israel 1993 / Israeli TM Grid",9001,4141,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,,,,,,,,
+2040,"Locodjo 1965 / UTM zone 30N",9001,4142,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2041,"Abidjan 1987 / UTM zone 30N",9001,4143,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2042,"Locodjo 1965 / UTM zone 29N",9001,4142,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2043,"Abidjan 1987 / UTM zone 29N",9001,4143,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2044,"Hanoi 1972 / Gauss-Kruger zone 18",9001,4147,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,,,,,,,,
+2045,"Hanoi 1972 / Gauss-Kruger zone 19",9001,4147,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+2046,"Hartebeesthoek94 / Lo15",9001,4148,17515,9808,1,0,6503,8801,0,9102,8802,15,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2047,"Hartebeesthoek94 / Lo17",9001,4148,17517,9808,1,0,6503,8801,0,9102,8802,17,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2048,"Hartebeesthoek94 / Lo19",9001,4148,17519,9808,1,0,6503,8801,0,9102,8802,19,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2049,"Hartebeesthoek94 / Lo21",9001,4148,17521,9808,1,0,6503,8801,0,9102,8802,21,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2050,"Hartebeesthoek94 / Lo23",9001,4148,17523,9808,1,0,6503,8801,0,9102,8802,23,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2051,"Hartebeesthoek94 / Lo25",9001,4148,17525,9808,1,0,6503,8801,0,9102,8802,25,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2052,"Hartebeesthoek94 / Lo27",9001,4148,17527,9808,1,0,6503,8801,0,9102,8802,27,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2053,"Hartebeesthoek94 / Lo29",9001,4148,17529,9808,1,0,6503,8801,0,9102,8802,29,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2054,"Hartebeesthoek94 / Lo31",9001,4148,17531,9808,1,0,6503,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2055,"Hartebeesthoek94 / Lo33",9001,4148,17533,9808,1,0,6503,8801,0,9102,8802,33,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2056,"CH1903+ / LV95",9001,4150,19950,9815,1,0,4400,8811,46.570866,9110,8812,7.26225,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,2600000,9001,8817,1200000,9001,,,,,,,
+2057,"Rassadiran / Nakhl e Taqi",9001,4153,19951,9815,1,0,4400,8811,27.31077837,9110,8812,52.3612741,9110,8813,0.34179803,9110,8814,0.34179803,9110,8815,0.999895934,9201,8816,658377.437,9001,8817,3044969.194,9001,,,,,,,
+2058,"ED50(ED77) / UTM zone 38N",9001,4154,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2059,"ED50(ED77) / UTM zone 39N",9001,4154,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2060,"ED50(ED77) / UTM zone 40N",9001,4154,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2061,"ED50(ED77) / UTM zone 41N",9001,4154,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2062,"Madrid 1870 (Madrid) / Spain",9001,4903,19921,9801,1,0,4499,8801,40,9102,8802,0,9102,8805,0.9988085293,9201,8806,600000,9001,8807,600000,9001,,,,,,,,,,,,,
+2063,"Dabola 1981 / UTM zone 28N",9001,4315,16028,9807,1,1,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2064,"Dabola 1981 / UTM zone 29N",9001,4315,16029,9807,1,1,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2065,"S-JTSK (Ferro) / Krovak",9001,4818,19952,9819,1,0,6501,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110,570.8,85.7,462.8,4.998,1.587,5.261,3.56
+2066,"Mount Dillon / Tobago Grid",9039,4157,19924,9806,1,0,4407,8801,11.1507843,9110,8802,-60.4109632,9110,8806,187500,9039,8807,180000,9039,,,,,,,,,,,,,,,,
+2067,"Naparima 1955 / UTM zone 20N",9001,4158,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2068,"ELD79 / Libya zone 5",9001,4159,18240,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2069,"ELD79 / Libya zone 6",9001,4159,18241,9807,1,0,4499,8801,0,9102,8802,11,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2070,"ELD79 / Libya zone 7",9001,4159,18242,9807,1,0,4499,8801,0,9102,8802,13,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2071,"ELD79 / Libya zone 8",9001,4159,18243,9807,1,0,4499,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2072,"ELD79 / Libya zone 9",9001,4159,18244,9807,1,0,4499,8801,0,9102,8802,17,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2073,"ELD79 / Libya zone 10",9001,4159,18245,9807,1,0,4499,8801,0,9102,8802,19,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2074,"ELD79 / Libya zone 11",9001,4159,18246,9807,1,0,4499,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2075,"ELD79 / Libya zone 12",9001,4159,18247,9807,1,0,4499,8801,0,9102,8802,23,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2076,"ELD79 / Libya zone 13",9001,4159,18248,9807,1,0,4499,8801,0,9102,8802,25,9102,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2077,"ELD79 / UTM zone 32N",9001,4159,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2078,"ELD79 / UTM zone 33N",9001,4159,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2079,"ELD79 / UTM zone 34N",9001,4159,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2080,"ELD79 / UTM zone 35N",9001,4159,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2081,"Chos Malal 1914 / Argentina 2",9001,4160,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+2082,"Pampa del Castillo / Argentina 2",9001,4161,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+2083,"Hito XVIII 1963 / Argentina 2",9001,4254,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+2084,"Hito XVIII 1963 / UTM zone 19S",9001,4254,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2085,"NAD27 / Cuba Norte",9001,4267,18061,9801,1,1,4532,8801,22.21,9110,8802,-81,9110,8805,0.99993602,9201,8806,500000,9001,8807,280296.016,9001,,,,,,,,,,,,,
+2086,"NAD27 / Cuba Sur",9001,4267,18062,9801,1,1,4532,8801,20.43,9110,8802,-76.5,9110,8805,0.99994848,9201,8806,500000,9001,8807,229126.939,9001,,,,,,,,,,,,,
+2087,"ELD79 / TM 12 NE",9001,4159,16412,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2088,"Carthage / TM 11 NE",9001,4223,16411,9807,1,0,4400,8801,0,9102,8802,11,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2089,"Yemen NGN96 / UTM zone 38N",9001,4163,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2090,"Yemen NGN96 / UTM zone 39N",9001,4163,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2091,"South Yemen / Gauss Kruger zone 8",9001,4164,16208,9807,1,1,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+2092,"South Yemen / Gauss Kruger zone 9",9001,4164,16209,9807,1,1,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+2093,"Hanoi 1972 / GK 106 NE",9001,4147,16586,9807,1,0,4530,8801,0,9102,8802,106,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2094,"WGS 72BE / TM 106 NE",9001,4324,16506,9807,1,0,4400,8801,0,9102,8802,106,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2095,"Bissau / UTM zone 28N",9001,4165,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2096,"Korean 1985 / East Belt",9001,4162,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+2097,"Korean 1985 / Central Belt",9001,4162,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+2098,"Korean 1985 / West Belt",9001,4162,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+2099,"Qatar 1948 / Qatar Grid",9001,4286,19953,9806,1,0,4400,8801,25.22565,9110,8802,50.4541,9110,8806,100000,9001,8807,100000,9001,,,,,,,,,,,,,,,,
+2100,"GGRS87 / Greek Grid",9001,4121,19930,9807,1,0,4400,8801,0,9102,8802,24,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2101,"Lake / Maracaibo Grid M1",9001,4249,18260,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,0,9001,8807,-52684.972,9001,,,,,,,,,,,,,
+2102,"Lake / Maracaibo Grid",9001,4249,18261,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,200000,9001,8807,147315.028,9001,,,,,,,,,,,,,
+2103,"Lake / Maracaibo Grid M3",9001,4249,18262,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,500000,9001,8807,447315.028,9001,,,,,,,,,,,,,
+2104,"Lake / Maracaibo La Rosa Grid",9001,4249,18263,9801,1,0,4499,8801,10.1,9110,8802,-71.3620224,9110,8805,1,9201,8806,-17044,9001,8807,-23139.97,9001,,,,,,,,,,,,,
+2105,"NZGD2000 / Mount Eden 2000",9001,4167,17931,9807,1,0,4500,8801,-36.5247,9110,8802,174.4551,9110,8805,0.9999,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2106,"NZGD2000 / Bay of Plenty 2000",9001,4167,17932,9807,1,0,4500,8801,-37.454,9110,8802,176.2758,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2107,"NZGD2000 / Poverty Bay 2000",9001,4167,17933,9807,1,0,4500,8801,-38.3728,9110,8802,177.5308,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2108,"NZGD2000 / Hawkes Bay 2000",9001,4167,17934,9807,1,0,4500,8801,-39.3903,9110,8802,176.4025,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2109,"NZGD2000 / Taranaki 2000",9001,4167,17935,9807,1,0,4500,8801,-39.0808,9110,8802,174.134,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2110,"NZGD2000 / Tuhirangi 2000",9001,4167,17936,9807,1,0,4500,8801,-39.3044,9110,8802,175.3824,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2111,"NZGD2000 / Wanganui 2000",9001,4167,17937,9807,1,0,4500,8801,-40.1431,9110,8802,175.2917,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2112,"NZGD2000 / Wairarapa 2000",9001,4167,17938,9807,1,0,4500,8801,-40.5531,9110,8802,175.385,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2113,"NZGD2000 / Wellington 2000",9001,4167,17939,9807,1,0,4500,8801,-41.1804,9110,8802,174.4635,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2114,"NZGD2000 / Collingwood 2000",9001,4167,17940,9807,1,0,4500,8801,-40.4253,9110,8802,172.4019,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2115,"NZGD2000 / Nelson 2000",9001,4167,17941,9807,1,0,4500,8801,-41.1628,9110,8802,173.1757,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2116,"NZGD2000 / Karamea 2000",9001,4167,17942,9807,1,0,4500,8801,-41.1723,9110,8802,172.0632,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2117,"NZGD2000 / Buller 2000",9001,4167,17943,9807,1,0,4500,8801,-41.4838,9110,8802,171.3452,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2118,"NZGD2000 / Grey 2000",9001,4167,17944,9807,1,0,4500,8801,-42.2001,9110,8802,171.3259,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2119,"NZGD2000 / Amuri 2000",9001,4167,17945,9807,1,0,4500,8801,-42.412,9110,8802,173.0036,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2120,"NZGD2000 / Marlborough 2000",9001,4167,17946,9807,1,0,4500,8801,-41.324,9110,8802,173.4807,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2121,"NZGD2000 / Hokitika 2000",9001,4167,17947,9807,1,0,4500,8801,-42.531,9110,8802,170.5847,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2122,"NZGD2000 / Okarito 2000",9001,4167,17948,9807,1,0,4500,8801,-43.0636,9110,8802,170.1539,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2123,"NZGD2000 / Jacksons Bay 2000",9001,4167,17949,9807,1,0,4500,8801,-43.584,9110,8802,168.3622,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2124,"NZGD2000 / Mount Pleasant 2000",9001,4167,17950,9807,1,0,4500,8801,-43.3526,9110,8802,172.4337,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2125,"NZGD2000 / Gawler 2000",9001,4167,17951,9807,1,0,4500,8801,-43.4455,9110,8802,171.2138,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2126,"NZGD2000 / Timaru 2000",9001,4167,17952,9807,1,0,4500,8801,-44.2407,9110,8802,171.0326,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2127,"NZGD2000 / Lindis Peak 2000",9001,4167,17953,9807,1,0,4500,8801,-44.4406,9110,8802,169.2803,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2128,"NZGD2000 / Mount Nicholas 2000",9001,4167,17954,9807,1,0,4500,8801,-45.0758,9110,8802,168.2355,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2129,"NZGD2000 / Mount York 2000",9001,4167,17955,9807,1,0,4500,8801,-45.3349,9110,8802,167.4419,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2130,"NZGD2000 / Observation Point 2000",9001,4167,17956,9807,1,0,4500,8801,-45.4858,9110,8802,170.3742,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2131,"NZGD2000 / North Taieri 2000",9001,4167,17957,9807,1,0,4500,8801,-45.5141,9110,8802,170.1657,9110,8805,0.99996,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2132,"NZGD2000 / Bluff 2000",9001,4167,17958,9807,1,0,4500,8801,-46.36,9110,8802,168.2034,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2133,"NZGD2000 / UTM zone 58S",9001,4167,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2134,"NZGD2000 / UTM zone 59S",9001,4167,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2135,"NZGD2000 / UTM zone 60S",9001,4167,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2136,"Accra / Ghana National Grid",9094,4168,19959,9807,1,0,4404,8801,4.4,9110,8802,-1,9110,8805,0.99975,9201,8806,900000,9094,8807,0,9094,,,,,,,,,,,,,
+2137,"Accra / TM 1 NW",9001,4168,17001,9807,1,0,4400,8801,0,9102,8802,-1,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2138,"NAD27(CGQ77) / Quebec Lambert",9001,4609,19944,9802,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+2139,"NAD83(CSRS98) / SCoPQ zone 2",9001,4140,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2140,"NAD83(CSRS98) / MTM zone 3",9001,4140,17703,9807,1,1,4496,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2141,"NAD83(CSRS98) / MTM zone 4",9001,4140,17704,9807,1,1,4496,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2142,"NAD83(CSRS98) / MTM zone 5",9001,4140,17705,9807,1,1,4496,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2143,"NAD83(CSRS98) / MTM zone 6",9001,4140,17706,9807,1,1,4496,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2144,"NAD83(CSRS98) / MTM zone 7",9001,4140,17707,9807,1,1,4496,8801,0,9110,8802,-70.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2145,"NAD83(CSRS98) / MTM zone 8",9001,4140,17708,9807,1,1,4496,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2146,"NAD83(CSRS98) / MTM zone 9",9001,4140,17709,9807,1,1,4496,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2147,"NAD83(CSRS98) / MTM zone 10",9001,4140,17710,9807,1,1,4496,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2148,"NAD83(CSRS98) / UTM zone 21N",9001,4140,16021,9807,1,1,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2149,"NAD83(CSRS98) / UTM zone 18N",9001,4140,16018,9807,1,1,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2150,"NAD83(CSRS98) / UTM zone 17N",9001,4140,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2151,"NAD83(CSRS98) / UTM zone 13N",9001,4140,16013,9807,1,1,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2152,"NAD83(CSRS98) / UTM zone 12N",9001,4140,16012,9807,1,1,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2153,"NAD83(CSRS98) / UTM zone 11N",9001,4140,16011,9807,1,1,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2154,"RGF93 / Lambert-93",9001,4171,18085,9802,1,0,4499,8821,46.3,9110,8822,3,9110,8823,49,9110,8824,44,9110,8826,700000,9001,8827,6600000,9001,,,,,,,,,,
+2155,"American Samoa 1962 / American Samoa Lambert",9003,4169,15300,9801,1,1,4497,8801,-14.16,9110,8802,170,9110,8805,1,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+2156,"NAD83(HARN) / UTM zone 59S",9001,4152,16159,9807,1,1,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2157,"IRENET95 / Irish Transverse Mercator",9001,4173,19962,9807,1,0,4400,8801,53.3,9110,8802,-8,9110,8805,0.99982,9201,8806,600000,9001,8807,750000,9001,,,,,,,,,,,,,
+2158,"IRENET95 / UTM zone 29N",9001,4173,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2159,"Sierra Leone 1924 / New Colony Grid",9094,4174,19963,9807,1,0,4404,8801,6.4,9110,8802,-12,9110,8805,1,9201,8806,500000,9094,8807,0,9094,,,,,,,,,,,,,
+2160,"Sierra Leone 1924 / New War Office Grid",9094,4174,19964,9807,1,0,4404,8801,6.4,9110,8802,-12,9110,8805,1,9201,8806,800000,9094,8807,600000,9094,,,,,,,,,,,,,
+2161,"Sierra Leone 1968 / UTM zone 28N",9001,4175,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2162,"Sierra Leone 1968 / UTM zone 29N",9001,4175,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2163,US National Atlas Equal Area,9001,4052,3899,1027,1,0,4499,8801,45,9102,8802,-100,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+2164,"Locodjo 1965 / TM 5 NW",9001,4142,17005,9807,1,0,4400,8801,0,9102,8802,-5,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2165,"Abidjan 1987 / TM 5 NW",9001,4143,17005,9807,1,0,4400,8801,0,9102,8802,-5,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2166,"Pulkovo 1942(83) / Gauss Kruger zone 3",9001,4178,16263,9807,1,1,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+2167,"Pulkovo 1942(83) / Gauss Kruger zone 4",9001,4178,16264,9807,1,1,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+2168,"Pulkovo 1942(83) / Gauss Kruger zone 5",9001,4178,16265,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+2169,"Luxembourg 1930 / Gauss",9001,4181,19966,9807,1,0,4530,8801,49.5,9110,8802,6.1,9110,8805,1,9201,8806,80000,9001,8807,100000,9001,,,,,,,,,,,,,
+2170,"MGI / Slovenia Grid",9001,4312,19967,9807,1,1,4530,8801,0,9110,8802,15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2171,"Pulkovo 1942(58) / Poland zone I",9001,4179,18281,9809,1,1,4530,8801,50.373,9110,8802,21.05,9110,8805,0.9998,9201,8806,4637000,9001,8807,5647000,9001,,,,,,,,,,,,,
+2172,"Pulkovo 1942(58) / Poland zone II",9001,4179,18282,9809,1,0,4530,8801,53.0007,9110,8802,21.301,9110,8805,0.9998,9201,8806,4603000,9001,8807,5806000,9001,,,,,,,,,,,,,
+2173,"Pulkovo 1942(58) / Poland zone III",9001,4179,18283,9809,1,0,4530,8801,53.35,9110,8802,17.003,9110,8805,0.9998,9201,8806,3501000,9001,8807,5999000,9001,,,,,,,,,,,,,
+2174,"Pulkovo 1942(58) / Poland zone IV",9001,4179,18284,9809,1,0,4530,8801,51.4015,9110,8802,16.402,9110,8805,0.9998,9201,8806,3703000,9001,8807,5627000,9001,,,,,,,,,,,,,
+2175,"Pulkovo 1942(58) / Poland zone V",9001,4179,18285,9807,1,0,4530,8801,0,9110,8802,18.573,9110,8805,0.999983,9201,8806,237000,9001,8807,-4700000,9001,,,,,,,,,,,,,
+2176,"ETRS89 / Poland CS2000 zone 5",9001,4258,18305,9807,1,0,4531,8801,0,9102,8802,15,9102,8805,0.999923,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+2177,"ETRS89 / Poland CS2000 zone 6",9001,4258,18306,9807,1,0,4531,8801,0,9102,8802,18,9102,8805,0.999923,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+2178,"ETRS89 / Poland CS2000 zone 7",9001,4258,18307,9807,1,0,4531,8801,0,9102,8802,21,9102,8805,0.999923,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+2179,"ETRS89 / Poland CS2000 zone 8",9001,4258,18308,9807,1,0,4531,8801,0,9102,8802,24,9102,8805,0.999923,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+2180,"ETRS89 / Poland CS92",9001,4258,18300,9807,1,0,4531,8801,0,9102,8802,19,9102,8805,0.9993,9201,8806,500000,9001,8807,-5300000,9001,,,,,,,,,,,,,
+2188,"Azores Occidental 1939 / UTM zone 25N",9001,4182,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2189,"Azores Central 1948 / UTM zone 26N",9001,4183,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2190,"Azores Oriental 1940 / UTM zone 26N",9001,4184,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2191,"Madeira 1936 / UTM zone 28N",9001,4185,16028,9807,1,1,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2192,"ED50 / France EuroLambert",9001,4230,18086,9801,1,1,4499,8801,46.48,9110,8802,2.2014025,9110,8805,0.99987742,9201,8806,600000,9001,8807,2200000,9001,,,,,,,,,,,,,
+2193,"NZGD2000 / New Zealand Transverse Mercator 2000",9001,4167,19971,9807,1,0,4500,8801,0,9102,8802,173,9102,8805,0.9996,9201,8806,1600000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2194,"American Samoa 1962 / American Samoa Lambert",9003,4169,15301,9801,1,1,4497,8801,-14.16,9110,8802,-170,9110,8805,1,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+2195,"NAD83(HARN) / UTM zone 2S",9001,4152,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2196,"ETRS89 / Kp2000 Jutland",9001,4258,18401,9807,1,0,4400,8801,0,9110,8802,9.3,9110,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2197,"ETRS89 / Kp2000 Zealand",9001,4258,18402,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2198,"ETRS89 / Kp2000 Bornholm",9001,4258,18403,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,900000,9001,8807,0,9001,,,,,,,,,,,,,
+2199,"Albanian 1987 / Gauss Kruger zone 4",9001,4191,16204,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+2200,"ATS77 / New Brunswick Stereographic (ATS77)",9001,4122,19945,9809,1,0,4500,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,300000,9001,8807,800000,9001,,,,,,,,,,,,,
+2201,"REGVEN / UTM zone 18N",9001,4189,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2202,"REGVEN / UTM zone 19N",9001,4189,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2203,"REGVEN / UTM zone 20N",9001,4189,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2204,"NAD27 / Tennessee",9003,4267,15302,9802,1,0,4497,8821,34.4,9110,8822,-86,9110,8823,35.15,9110,8824,36.25,9110,8826,2000000,9003,8827,100000,9003,,,,,,,,,,
+2205,"NAD83 / Kentucky North",9001,4269,15303,9802,1,0,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+2206,"ED50 / 3-degree Gauss-Kruger zone 9",9001,4230,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+2207,"ED50 / 3-degree Gauss-Kruger zone 10",9001,4230,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,,,,,,,,
+2208,"ED50 / 3-degree Gauss-Kruger zone 11",9001,4230,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,,,,,,,,
+2209,"ED50 / 3-degree Gauss-Kruger zone 12",9001,4230,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,,,,,,,,
+2210,"ED50 / 3-degree Gauss-Kruger zone 13",9001,4230,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+2211,"ED50 / 3-degree Gauss-Kruger zone 14",9001,4230,16274,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+2212,"ED50 / 3-degree Gauss-Kruger zone 15",9001,4230,16275,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+2213,"ETRS89 / TM 30 NE",9001,4258,16430,9807,1,0,4400,8801,0,9102,8802,30,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2214,"Douala 1948 / AOF west",9001,4192,18415,9807,1,1,4400,8801,0,9110,8802,10.3,9110,8805,0.999,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+2215,"Manoca 1962 / UTM zone 32N",9001,4193,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2216,"Qornoq 1927 / UTM zone 22N",9001,4194,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2217,"Qornoq 1927 / UTM zone 23N",9001,4194,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2218,"Scoresbysund 1952 / Greenland zone 5 east",9001,4195,18425,9826,1,0,1031,8801,70.3,9110,8802,-24,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2219,"ATS77 / UTM zone 19N",9001,4122,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2220,"ATS77 / UTM zone 20N",9001,4122,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2221,"Scoresbysund 1952 / Greenland zone 6 east",9001,4195,18426,9826,1,0,1031,8801,67.3,9110,8802,-32,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2222,"NAD83 / Arizona East (ft)",9002,4269,15304,9807,1,0,4495,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+2223,"NAD83 / Arizona Central (ft)",9002,4269,15305,9807,1,0,4495,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+2224,"NAD83 / Arizona West (ft)",9002,4269,15306,9807,1,0,4495,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+2225,"NAD83 / California zone 1 (ftUS)",9003,4269,15307,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2226,"NAD83 / California zone 2 (ftUS)",9003,4269,15308,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2227,"NAD83 / California zone 3 (ftUS)",9003,4269,15309,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2228,"NAD83 / California zone 4 (ftUS)",9003,4269,15310,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2229,"NAD83 / California zone 5 (ftUS)",9003,4269,15311,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2230,"NAD83 / California zone 6 (ftUS)",9003,4269,15312,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2231,"NAD83 / Colorado North (ftUS)",9003,4269,15313,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+2232,"NAD83 / Colorado Central (ftUS)",9003,4269,15314,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+2233,"NAD83 / Colorado South (ftUS)",9003,4269,15315,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+2234,"NAD83 / Connecticut (ftUS)",9003,4269,15316,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,1000000,9003,8827,500000,9003,,,,,,,,,,
+2235,"NAD83 / Delaware (ftUS)",9003,4269,15317,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2236,"NAD83 / Florida East (ftUS)",9003,4269,15318,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2237,"NAD83 / Florida West (ftUS)",9003,4269,15319,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2238,"NAD83 / Florida North (ftUS)",9003,4269,15320,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2239,"NAD83 / Georgia East (ftUS)",9003,4269,15321,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2240,"NAD83 / Georgia West (ftUS)",9003,4269,15322,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,2296583.333,9003,8807,0,9003,,,,,,,,,,,,,
+2241,"NAD83 / Idaho East (ftUS)",9003,4269,15323,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2242,"NAD83 / Idaho Central (ftUS)",9003,4269,15324,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,1640416.667,9003,8807,0,9003,,,,,,,,,,,,,
+2243,"NAD83 / Idaho West (ftUS)",9003,4269,15325,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,2624666.667,9003,8807,0,9003,,,,,,,,,,,,,
+2244,"NAD83 / Indiana East (ftUS)",9003,4269,15326,9807,1,1,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,818125,9003,,,,,,,,,,,,,
+2245,"NAD83 / Indiana West (ftUS)",9003,4269,15327,9807,1,1,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,818125,9003,,,,,,,,,,,,,
+2246,"NAD83 / Kentucky North (ftUS)",9003,4269,15328,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+2247,"NAD83 / Kentucky South (ftUS)",9003,4269,15329,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,1640416.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2248,"NAD83 / Maryland (ftUS)",9003,4269,15330,9802,1,0,4497,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,1312333.333,9003,8827,0,9003,,,,,,,,,,
+2249,"NAD83 / Massachusetts Mainland (ftUS)",9003,4269,15331,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,656166.667,9003,8827,2460625,9003,,,,,,,,,,
+2250,"NAD83 / Massachusetts Island (ftUS)",9003,4269,15332,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+2251,"NAD83 / Michigan North (ft)",9002,4269,15333,9802,1,0,4495,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,26246719.16,9002,8827,0,9002,,,,,,,,,,
+2252,"NAD83 / Michigan Central (ft)",9002,4269,15334,9802,1,0,4495,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,19685039.37,9002,8827,0,9002,,,,,,,,,,
+2253,"NAD83 / Michigan South (ft)",9002,4269,15335,9802,1,0,4495,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,13123359.58,9002,8827,0,9002,,,,,,,,,,
+2254,"NAD83 / Mississippi East (ftUS)",9003,4269,15336,9807,1,0,4497,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+2255,"NAD83 / Mississippi West (ftUS)",9003,4269,15337,9807,1,0,4497,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,2296583.333,9003,8807,0,9003,,,,,,,,,,,,,
+2256,"NAD83 / Montana (ft)",9002,4269,15338,9802,1,0,4495,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+2257,"NAD83 / New Mexico East (ftUS)",9003,4269,15339,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,541337.5,9003,8807,0,9003,,,,,,,,,,,,,
+2258,"NAD83 / New Mexico Central (ftUS)",9003,4269,15340,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,1640416.667,9003,8807,0,9003,,,,,,,,,,,,,
+2259,"NAD83 / New Mexico West (ftUS)",9003,4269,15341,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,2723091.667,9003,8807,0,9003,,,,,,,,,,,,,
+2260,"NAD83 / New York East (ftUS)",9003,4269,15342,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,,,,,,,,
+2261,"NAD83 / New York Central (ftUS)",9003,4269,15343,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,820208.333,9003,8807,0,9003,,,,,,,,,,,,,
+2262,"NAD83 / New York West (ftUS)",9003,4269,15344,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,1148291.667,9003,8807,0,9003,,,,,,,,,,,,,
+2263,"NAD83 / New York Long Island (ftUS)",9003,4269,15345,9802,1,0,4497,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,984250,9003,8827,0,9003,,,,,,,,,,
+2264,"NAD83 / North Carolina (ftUS)",9003,4269,15346,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+2265,"NAD83 / North Dakota North (ft)",9002,4269,15347,9802,1,0,4495,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+2266,"NAD83 / North Dakota South (ft)",9002,4269,15348,9802,1,0,4495,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+2267,"NAD83 / Oklahoma North (ftUS)",9003,4269,15349,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2268,"NAD83 / Oklahoma South (ftUS)",9003,4269,15350,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2269,"NAD83 / Oregon North (ft)",9002,4269,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,,,,,,,,
+2270,"NAD83 / Oregon South (ft)",9002,4269,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,,,,,,,,
+2271,"NAD83 / Pennsylvania North (ftUS)",9003,4269,15353,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2272,"NAD83 / Pennsylvania South (ftUS)",9003,4269,15354,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2273,"NAD83 / South Carolina (ft)",9002,4269,15355,9802,1,0,4495,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,2000000,9002,8827,0,9002,,,,,,,,,,
+2274,"NAD83 / Tennessee (ftUS)",9003,4269,15356,9802,1,0,4497,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2275,"NAD83 / Texas North (ftUS)",9003,4269,15357,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,656166.667,9003,8827,3280833.333,9003,,,,,,,,,,
+2276,"NAD83 / Texas North Central (ftUS)",9003,4269,15358,9802,1,0,4497,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,1968500,9003,8827,6561666.667,9003,,,,,,,,,,
+2277,"NAD83 / Texas Central (ftUS)",9003,4269,15359,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,2296583.333,9003,8827,9842500,9003,,,,,,,,,,
+2278,"NAD83 / Texas South Central (ftUS)",9003,4269,15360,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,1968500,9003,8827,13123333.333,9003,,,,,,,,,,
+2279,"NAD83 / Texas South (ftUS)",9003,4269,15361,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,984250,9003,8827,16404166.667,9003,,,,,,,,,,
+2280,"NAD83 / Utah North (ft)",9002,4269,15362,9802,0,0,4495,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640419.948,9002,8827,3280839.895,9002,,,,,,,,,,
+2281,"NAD83 / Utah Central (ft)",9002,4269,15363,9802,0,0,4495,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640419.948,9002,8827,6561679.79,9002,,,,,,,,,,
+2282,"NAD83 / Utah South (ft)",9002,4269,15364,9802,0,0,4495,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640419.948,9002,8827,9842519.685,9002,,,,,,,,,,
+2283,"NAD83 / Virginia North (ftUS)",9003,4269,15365,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,11482916.667,9003,8827,6561666.667,9003,,,,,,,,,,
+2284,"NAD83 / Virginia South (ftUS)",9003,4269,15366,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,11482916.667,9003,8827,3280833.333,9003,,,,,,,,,,
+2285,"NAD83 / Washington North (ftUS)",9003,4269,15367,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+2286,"NAD83 / Washington South (ftUS)",9003,4269,15368,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+2287,"NAD83 / Wisconsin North (ftUS)",9003,4269,15369,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2288,"NAD83 / Wisconsin Central (ftUS)",9003,4269,15370,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2289,"NAD83 / Wisconsin South (ftUS)",9003,4269,15371,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2290,"ATS77 / Prince Edward Isl. Stereographic (ATS77)",9001,4122,19933,9809,1,0,4496,8801,47.15,9110,8802,-63,9110,8805,0.999912,9201,8806,700000,9001,8807,400000,9001,,,,,,,,,,,,,
+2291,"NAD83(CSRS98) / Prince Edward Isl. Stereographic (NAD83)",9001,4122,19960,9809,1,1,4496,8801,47.15,9110,8802,-63,9110,8805,0.999912,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2292,"NAD83(CSRS98) / Prince Edward Isl. Stereographic (NAD83)",9001,4140,19960,9809,1,1,4496,8801,47.15,9110,8802,-63,9110,8805,0.999912,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2294,"ATS77 / MTM Nova Scotia zone 4",9001,4122,17794,9807,1,0,4400,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+2295,"ATS77 / MTM Nova Scotia zone 5",9001,4122,17795,9807,1,0,4400,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+2296,"Ammassalik 1958 / Greenland zone 7 east",9001,4196,18427,9826,1,0,1031,8801,64.3,9110,8802,-40,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2297,"Qornoq 1927 / Greenland zone 1 east",9001,4194,18421,9826,1,1,4501,8801,82.3,9110,8802,-40,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2298,"Qornoq 1927 / Greenland zone 2 east",9001,4194,18422,9826,1,1,4501,8801,79.3,9110,8802,-24,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2299,"Qornoq 1927 / Greenland zone 2 west",9001,4194,18432,9826,1,0,1031,8801,79.3,9110,8802,-64,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2300,"Qornoq 1927 / Greenland zone 3 east",9001,4194,18423,9826,1,1,4501,8801,76.3,9110,8802,-20,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2301,"Qornoq 1927 / Greenland zone 3 west",9001,4194,18433,9826,1,0,1031,8801,76.3,9110,8802,-64,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2302,"Qornoq 1927 / Greenland zone 4 east",9001,4194,18424,9826,1,1,4501,8801,73.3,9110,8802,-24,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2303,"Qornoq 1927 / Greenland zone 4 west",9001,4194,18434,9826,1,0,1031,8801,73.3,9110,8802,-52,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2304,"Qornoq 1927 / Greenland zone 5 west",9001,4194,18435,9826,1,0,1031,8801,70.3,9110,8802,-52,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2305,"Qornoq 1927 / Greenland zone 6 west",9001,4194,18436,9826,1,0,1031,8801,67.3,9110,8802,-52,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2306,"Qornoq 1927 / Greenland zone 7 west",9001,4194,18437,9826,1,0,1031,8801,64.3,9110,8802,-52,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2307,"Qornoq 1927 / Greenland zone 8 east",9001,4194,18428,9826,1,0,1031,8801,61.3,9110,8802,-48,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2308,"Batavia / TM 109 SE",9001,4211,16709,9807,1,0,4400,8801,0,9102,8802,109,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2309,"WGS 84 / TM 116 SE",9001,4326,16716,9807,1,0,4400,8801,0,9102,8802,116,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2310,"WGS 84 / TM 132 SE",9001,4326,16732,9807,1,0,4400,8801,0,9102,8802,132,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2311,"WGS 84 / TM 6 NE",9001,4326,16406,9807,1,0,4400,8801,0,9102,8802,6,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2312,"Garoua / UTM zone 33N",9001,4197,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2313,"Kousseri / UTM zone 33N",9001,4198,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2314,"Trinidad 1903 / Trinidad Grid (ftCla)",9005,4302,19975,9806,1,0,4403,8801,10.263,9110,8802,-61.2,9110,8806,283800,9005,8807,214500,9005,,,,,,,,,,,,,,,,
+2315,"Campo Inchauspe / UTM zone 19S",9001,4221,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2316,"Campo Inchauspe / UTM zone 20S",9001,4221,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2317,"PSAD56 / ICN Regional",9001,4248,19976,9802,1,0,4499,8821,6,9102,8822,-66,9102,8823,9,9102,8824,3,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+2318,"Ain el Abd / Aramco Lambert",9001,4204,19977,9802,1,0,4400,8821,25.0522236,9110,8822,48,9102,8823,17,9102,8824,33,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+2319,"ED50 / TM27",9001,4230,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2320,"ED50 / TM30",9001,4230,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2321,"ED50 / TM33",9001,4230,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2322,"ED50 / TM36",9001,4230,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2323,"ED50 / TM39",9001,4230,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2324,"ED50 / TM42",9001,4230,16374,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2325,"ED50 / TM45",9001,4230,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2326,Hong Kong 1980 Grid System,9001,4611,19978,9807,1,0,4500,8801,22.184368,9110,8802,114.10428,9110,8805,1,9201,8806,836694.05,9001,8807,819069.8,9001,,,,,,,,,,,,,
+2327,"Xian 1980 / Gauss-Kruger zone 13",9001,4610,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+2328,"Xian 1980 / Gauss-Kruger zone 14",9001,4610,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+2329,"Xian 1980 / Gauss-Kruger zone 15",9001,4610,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+2330,"Xian 1980 / Gauss-Kruger zone 16",9001,4610,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,,,,,,,,
+2331,"Xian 1980 / Gauss-Kruger zone 17",9001,4610,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,,,,,,,,
+2332,"Xian 1980 / Gauss-Kruger zone 18",9001,4610,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,,,,,,,,
+2333,"Xian 1980 / Gauss-Kruger zone 19",9001,4610,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+2334,"Xian 1980 / Gauss-Kruger zone 20",9001,4610,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,,,,,,,,
+2335,"Xian 1980 / Gauss-Kruger zone 21",9001,4610,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,,,,,,,,
+2336,"Xian 1980 / Gauss-Kruger zone 22",9001,4610,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,,,,,,,,
+2337,"Xian 1980 / Gauss-Kruger zone 23",9001,4610,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,,,,,,,,
+2338,"Xian 1980 / Gauss-Kruger CM 75E",9001,4610,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2339,"Xian 1980 / Gauss-Kruger CM 81E",9001,4610,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2340,"Xian 1980 / Gauss-Kruger CM 87E",9001,4610,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2341,"Xian 1980 / Gauss-Kruger CM 93E",9001,4610,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2342,"Xian 1980 / Gauss-Kruger CM 99E",9001,4610,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2343,"Xian 1980 / Gauss-Kruger CM 105E",9001,4610,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2344,"Xian 1980 / Gauss-Kruger CM 111E",9001,4610,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2345,"Xian 1980 / Gauss-Kruger CM 117E",9001,4610,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2346,"Xian 1980 / Gauss-Kruger CM 123E",9001,4610,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2347,"Xian 1980 / Gauss-Kruger CM 129E",9001,4610,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2348,"Xian 1980 / Gauss-Kruger CM 135E",9001,4610,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2349,"Xian 1980 / 3-degree Gauss-Kruger zone 25",9001,4610,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,,,,,,,,
+2350,"Xian 1980 / 3-degree Gauss-Kruger zone 26",9001,4610,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,,,,,,,,
+2351,"Xian 1980 / 3-degree Gauss-Kruger zone 27",9001,4610,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,,,,,,,,
+2352,"Xian 1980 / 3-degree Gauss-Kruger zone 28",9001,4610,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,,,,,,,,
+2353,"Xian 1980 / 3-degree Gauss-Kruger zone 29",9001,4610,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,,,,,,,,
+2354,"Xian 1980 / 3-degree Gauss-Kruger zone 30",9001,4610,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,,,,,,,,
+2355,"Xian 1980 / 3-degree Gauss-Kruger zone 31",9001,4610,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+2356,"Xian 1980 / 3-degree Gauss-Kruger zone 32",9001,4610,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+2357,"Xian 1980 / 3-degree Gauss-Kruger zone 33",9001,4610,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,,,,,,,,
+2358,"Xian 1980 / 3-degree Gauss-Kruger zone 34",9001,4610,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,,,,,,,,
+2359,"Xian 1980 / 3-degree Gauss-Kruger zone 35",9001,4610,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,,,,,,,,
+2360,"Xian 1980 / 3-degree Gauss-Kruger zone 36",9001,4610,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,,,,,,,,
+2361,"Xian 1980 / 3-degree Gauss-Kruger zone 37",9001,4610,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,,,,,,,,
+2362,"Xian 1980 / 3-degree Gauss-Kruger zone 38",9001,4610,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,,,,,,,,
+2363,"Xian 1980 / 3-degree Gauss-Kruger zone 39",9001,4610,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,,,,,,,,
+2364,"Xian 1980 / 3-degree Gauss-Kruger zone 40",9001,4610,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,,,,,,,,
+2365,"Xian 1980 / 3-degree Gauss-Kruger zone 41",9001,4610,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,,,,,,,,
+2366,"Xian 1980 / 3-degree Gauss-Kruger zone 42",9001,4610,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,,,,,,,,
+2367,"Xian 1980 / 3-degree Gauss-Kruger zone 43",9001,4610,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,,,,,,,,
+2368,"Xian 1980 / 3-degree Gauss-Kruger zone 44",9001,4610,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,,,,,,,,
+2369,"Xian 1980 / 3-degree Gauss-Kruger zone 45",9001,4610,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,,,,,,,,
+2370,"Xian 1980 / 3-degree Gauss-Kruger CM 75E",9001,4610,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2371,"Xian 1980 / 3-degree Gauss-Kruger CM 78E",9001,4610,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2372,"Xian 1980 / 3-degree Gauss-Kruger CM 81E",9001,4610,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2373,"Xian 1980 / 3-degree Gauss-Kruger CM 84E",9001,4610,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2374,"Xian 1980 / 3-degree Gauss-Kruger CM 87E",9001,4610,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2375,"Xian 1980 / 3-degree Gauss-Kruger CM 90E",9001,4610,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2376,"Xian 1980 / 3-degree Gauss-Kruger CM 93E",9001,4610,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2377,"Xian 1980 / 3-degree Gauss-Kruger CM 96E",9001,4610,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2378,"Xian 1980 / 3-degree Gauss-Kruger CM 99E",9001,4610,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2379,"Xian 1980 / 3-degree Gauss-Kruger CM 102E",9001,4610,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2380,"Xian 1980 / 3-degree Gauss-Kruger CM 105E",9001,4610,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2381,"Xian 1980 / 3-degree Gauss-Kruger CM 108E",9001,4610,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2382,"Xian 1980 / 3-degree Gauss-Kruger CM 111E",9001,4610,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2383,"Xian 1980 / 3-degree Gauss-Kruger CM 114E",9001,4610,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2384,"Xian 1980 / 3-degree Gauss-Kruger CM 117E",9001,4610,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2385,"Xian 1980 / 3-degree Gauss-Kruger CM 120E",9001,4610,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2386,"Xian 1980 / 3-degree Gauss-Kruger CM 123E",9001,4610,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2387,"Xian 1980 / 3-degree Gauss-Kruger CM 126E",9001,4610,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2388,"Xian 1980 / 3-degree Gauss-Kruger CM 129E",9001,4610,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2389,"Xian 1980 / 3-degree Gauss-Kruger CM 132E",9001,4610,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2390,"Xian 1980 / 3-degree Gauss-Kruger CM 135E",9001,4610,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2391,"KKJ / Finland zone 1",9001,4123,18191,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+2392,"KKJ / Finland zone 2",9001,4123,18192,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+2393,"KKJ / Finland Uniform Coordinate System",9001,4123,18193,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+2394,"KKJ / Finland zone 4",9001,4123,18194,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+2395,"South Yemen / Gauss-Kruger zone 8",9001,4164,16208,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+2396,"South Yemen / Gauss-Kruger zone 9",9001,4164,16209,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+2397,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 3",9001,4178,16263,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,24.9,-126.4,-93.2,-0.063,-0.247,-0.041,1.01
+2398,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 4",9001,4178,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,24.9,-126.4,-93.2,-0.063,-0.247,-0.041,1.01
+2399,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 5",9001,4178,16265,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,24.9,-126.4,-93.2,-0.063,-0.247,-0.041,1.01
+2400,RT90 2.5 gon W,9001,4124,19929,9807,1,1,4530,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+2401,"Beijing 1954 / 3-degree Gauss-Kruger zone 25",9001,4214,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,,,,,,,,
+2402,"Beijing 1954 / 3-degree Gauss-Kruger zone 26",9001,4214,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,,,,,,,,
+2403,"Beijing 1954 / 3-degree Gauss-Kruger zone 27",9001,4214,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,,,,,,,,
+2404,"Beijing 1954 / 3-degree Gauss-Kruger zone 28",9001,4214,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,,,,,,,,
+2405,"Beijing 1954 / 3-degree Gauss-Kruger zone 29",9001,4214,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,,,,,,,,
+2406,"Beijing 1954 / 3-degree Gauss-Kruger zone 30",9001,4214,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,,,,,,,,
+2407,"Beijing 1954 / 3-degree Gauss-Kruger zone 31",9001,4214,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+2408,"Beijing 1954 / 3-degree Gauss-Kruger zone 32",9001,4214,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+2409,"Beijing 1954 / 3-degree Gauss-Kruger zone 33",9001,4214,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,,,,,,,,
+2410,"Beijing 1954 / 3-degree Gauss-Kruger zone 34",9001,4214,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,,,,,,,,
+2411,"Beijing 1954 / 3-degree Gauss-Kruger zone 35",9001,4214,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,,,,,,,,
+2412,"Beijing 1954 / 3-degree Gauss-Kruger zone 36",9001,4214,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,,,,,,,,
+2413,"Beijing 1954 / 3-degree Gauss-Kruger zone 37",9001,4214,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,,,,,,,,
+2414,"Beijing 1954 / 3-degree Gauss-Kruger zone 38",9001,4214,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,,,,,,,,
+2415,"Beijing 1954 / 3-degree Gauss-Kruger zone 39",9001,4214,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,,,,,,,,
+2416,"Beijing 1954 / 3-degree Gauss-Kruger zone 40",9001,4214,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,,,,,,,,
+2417,"Beijing 1954 / 3-degree Gauss-Kruger zone 41",9001,4214,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,,,,,,,,
+2418,"Beijing 1954 / 3-degree Gauss-Kruger zone 42",9001,4214,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,,,,,,,,
+2419,"Beijing 1954 / 3-degree Gauss-Kruger zone 43",9001,4214,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,,,,,,,,
+2420,"Beijing 1954 / 3-degree Gauss-Kruger zone 44",9001,4214,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,,,,,,,,
+2421,"Beijing 1954 / 3-degree Gauss-Kruger zone 45",9001,4214,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,,,,,,,,
+2422,"Beijing 1954 / 3-degree Gauss-Kruger CM 75E",9001,4214,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2423,"Beijing 1954 / 3-degree Gauss-Kruger CM 78E",9001,4214,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2424,"Beijing 1954 / 3-degree Gauss-Kruger CM 81E",9001,4214,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2425,"Beijing 1954 / 3-degree Gauss-Kruger CM 84E",9001,4214,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2426,"Beijing 1954 / 3-degree Gauss-Kruger CM 87E",9001,4214,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2427,"Beijing 1954 / 3-degree Gauss-Kruger CM 90E",9001,4214,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2428,"Beijing 1954 / 3-degree Gauss-Kruger CM 93E",9001,4214,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2429,"Beijing 1954 / 3-degree Gauss-Kruger CM 96E",9001,4214,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2430,"Beijing 1954 / 3-degree Gauss-Kruger CM 99E",9001,4214,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2431,"Beijing 1954 / 3-degree Gauss-Kruger CM 102E",9001,4214,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2432,"Beijing 1954 / 3-degree Gauss-Kruger CM 105E",9001,4214,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2433,"Beijing 1954 / 3-degree Gauss-Kruger CM 108E",9001,4214,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2434,"Beijing 1954 / 3-degree Gauss-Kruger CM 111E",9001,4214,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2435,"Beijing 1954 / 3-degree Gauss-Kruger CM 114E",9001,4214,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2436,"Beijing 1954 / 3-degree Gauss-Kruger CM 117E",9001,4214,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2437,"Beijing 1954 / 3-degree Gauss-Kruger CM 120E",9001,4214,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2438,"Beijing 1954 / 3-degree Gauss-Kruger CM 123E",9001,4214,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2439,"Beijing 1954 / 3-degree Gauss-Kruger CM 126E",9001,4214,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2440,"Beijing 1954 / 3-degree Gauss-Kruger CM 129E",9001,4214,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2441,"Beijing 1954 / 3-degree Gauss-Kruger CM 132E",9001,4214,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2442,"Beijing 1954 / 3-degree Gauss-Kruger CM 135E",9001,4214,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2443,"JGD2000 / Japan Plane Rectangular CS I",9001,4612,17801,9807,1,0,4530,8801,33,9110,8802,129.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2444,"JGD2000 / Japan Plane Rectangular CS II",9001,4612,17802,9807,1,0,4530,8801,33,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2445,"JGD2000 / Japan Plane Rectangular CS III",9001,4612,17803,9807,1,0,4530,8801,36,9110,8802,132.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2446,"JGD2000 / Japan Plane Rectangular CS IV",9001,4612,17804,9807,1,0,4530,8801,33,9110,8802,133.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2447,"JGD2000 / Japan Plane Rectangular CS V",9001,4612,17805,9807,1,0,4530,8801,36,9110,8802,134.2,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2448,"JGD2000 / Japan Plane Rectangular CS VI",9001,4612,17806,9807,1,0,4530,8801,36,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2449,"JGD2000 / Japan Plane Rectangular CS VII",9001,4612,17807,9807,1,0,4530,8801,36,9110,8802,137.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2450,"JGD2000 / Japan Plane Rectangular CS VIII",9001,4612,17808,9807,1,0,4530,8801,36,9110,8802,138.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2451,"JGD2000 / Japan Plane Rectangular CS IX",9001,4612,17809,9807,1,0,4530,8801,36,9110,8802,139.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2452,"JGD2000 / Japan Plane Rectangular CS X",9001,4612,17810,9807,1,0,4530,8801,40,9110,8802,140.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2453,"JGD2000 / Japan Plane Rectangular CS XI",9001,4612,17811,9807,1,0,4530,8801,44,9110,8802,140.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2454,"JGD2000 / Japan Plane Rectangular CS XII",9001,4612,17812,9807,1,0,4530,8801,44,9110,8802,142.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2455,"JGD2000 / Japan Plane Rectangular CS XIII",9001,4612,17813,9807,1,0,4530,8801,44,9110,8802,144.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2456,"JGD2000 / Japan Plane Rectangular CS XIV",9001,4612,17814,9807,1,0,4530,8801,26,9110,8802,142,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2457,"JGD2000 / Japan Plane Rectangular CS XV",9001,4612,17815,9807,1,0,4530,8801,26,9110,8802,127.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2458,"JGD2000 / Japan Plane Rectangular CS XVI",9001,4612,17816,9807,1,0,4530,8801,26,9110,8802,124,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2459,"JGD2000 / Japan Plane Rectangular CS XVII",9001,4612,17817,9807,1,0,4530,8801,26,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2460,"JGD2000 / Japan Plane Rectangular CS XVIII",9001,4612,17818,9807,1,0,4530,8801,20,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2461,"JGD2000 / Japan Plane Rectangular CS XIX",9001,4612,17819,9807,1,0,4530,8801,26,9110,8802,154,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+2462,"Albanian 1987 / Gauss-Kruger zone 4",9001,4191,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+2463,"Pulkovo 1995 / Gauss-Kruger CM 21E",9001,4200,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2464,"Pulkovo 1995 / Gauss-Kruger CM 27E",9001,4200,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2465,"Pulkovo 1995 / Gauss-Kruger CM 33E",9001,4200,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2466,"Pulkovo 1995 / Gauss-Kruger CM 39E",9001,4200,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2467,"Pulkovo 1995 / Gauss-Kruger CM 45E",9001,4200,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2468,"Pulkovo 1995 / Gauss-Kruger CM 51E",9001,4200,16309,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2469,"Pulkovo 1995 / Gauss-Kruger CM 57E",9001,4200,16310,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2470,"Pulkovo 1995 / Gauss-Kruger CM 63E",9001,4200,16311,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2471,"Pulkovo 1995 / Gauss-Kruger CM 69E",9001,4200,16312,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2472,"Pulkovo 1995 / Gauss-Kruger CM 75E",9001,4200,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2473,"Pulkovo 1995 / Gauss-Kruger CM 81E",9001,4200,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2474,"Pulkovo 1995 / Gauss-Kruger CM 87E",9001,4200,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2475,"Pulkovo 1995 / Gauss-Kruger CM 93E",9001,4200,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2476,"Pulkovo 1995 / Gauss-Kruger CM 99E",9001,4200,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2477,"Pulkovo 1995 / Gauss-Kruger CM 105E",9001,4200,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2478,"Pulkovo 1995 / Gauss-Kruger CM 111E",9001,4200,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2479,"Pulkovo 1995 / Gauss-Kruger CM 117E",9001,4200,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2480,"Pulkovo 1995 / Gauss-Kruger CM 123E",9001,4200,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2481,"Pulkovo 1995 / Gauss-Kruger CM 129E",9001,4200,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2482,"Pulkovo 1995 / Gauss-Kruger CM 135E",9001,4200,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2483,"Pulkovo 1995 / Gauss-Kruger CM 141E",9001,4200,16324,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2484,"Pulkovo 1995 / Gauss-Kruger CM 147E",9001,4200,16325,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2485,"Pulkovo 1995 / Gauss-Kruger CM 153E",9001,4200,16326,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2486,"Pulkovo 1995 / Gauss-Kruger CM 159E",9001,4200,16327,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2487,"Pulkovo 1995 / Gauss-Kruger CM 165E",9001,4200,16328,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2488,"Pulkovo 1995 / Gauss-Kruger CM 171E",9001,4200,16329,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2489,"Pulkovo 1995 / Gauss-Kruger CM 177E",9001,4200,16330,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2490,"Pulkovo 1995 / Gauss-Kruger CM 177W",9001,4200,16331,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2491,"Pulkovo 1995 / Gauss-Kruger CM 171W",9001,4200,16332,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2492,"Pulkovo 1942 / Gauss-Kruger CM 9E",9001,4284,16302,9807,1,1,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2493,"Pulkovo 1942 / Gauss-Kruger CM 15E",9001,4284,16303,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2494,"Pulkovo 1942 / Gauss-Kruger CM 21E",9001,4284,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2495,"Pulkovo 1942 / Gauss-Kruger CM 27E",9001,4284,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2496,"Pulkovo 1942 / Gauss-Kruger CM 33E",9001,4284,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2497,"Pulkovo 1942 / Gauss-Kruger CM 39E",9001,4284,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2498,"Pulkovo 1942 / Gauss-Kruger CM 45E",9001,4284,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2499,"Pulkovo 1942 / Gauss-Kruger CM 51E",9001,4284,16309,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2500,"Pulkovo 1942 / Gauss-Kruger CM 57E",9001,4284,16310,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2501,"Pulkovo 1942 / Gauss-Kruger CM 63E",9001,4284,16311,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2502,"Pulkovo 1942 / Gauss-Kruger CM 69E",9001,4284,16312,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2503,"Pulkovo 1942 / Gauss-Kruger CM 75E",9001,4284,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2504,"Pulkovo 1942 / Gauss-Kruger CM 81E",9001,4284,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2505,"Pulkovo 1942 / Gauss-Kruger CM 87E",9001,4284,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2506,"Pulkovo 1942 / Gauss-Kruger CM 93E",9001,4284,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2507,"Pulkovo 1942 / Gauss-Kruger CM 99E",9001,4284,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2508,"Pulkovo 1942 / Gauss-Kruger CM 105E",9001,4284,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2509,"Pulkovo 1942 / Gauss-Kruger CM 111E",9001,4284,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2510,"Pulkovo 1942 / Gauss-Kruger CM 117E",9001,4284,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2511,"Pulkovo 1942 / Gauss-Kruger CM 123E",9001,4284,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2512,"Pulkovo 1942 / Gauss-Kruger CM 129E",9001,4284,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2513,"Pulkovo 1942 / Gauss-Kruger CM 135E",9001,4284,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2514,"Pulkovo 1942 / Gauss-Kruger CM 141E",9001,4284,16324,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2515,"Pulkovo 1942 / Gauss-Kruger CM 147E",9001,4284,16325,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2516,"Pulkovo 1942 / Gauss-Kruger CM 153E",9001,4284,16326,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2517,"Pulkovo 1942 / Gauss-Kruger CM 159E",9001,4284,16327,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2518,"Pulkovo 1942 / Gauss-Kruger CM 165E",9001,4284,16328,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2519,"Pulkovo 1942 / Gauss-Kruger CM 171E",9001,4284,16329,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2520,"Pulkovo 1942 / Gauss-Kruger CM 177E",9001,4284,16330,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2521,"Pulkovo 1942 / Gauss-Kruger CM 177W",9001,4284,16331,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2522,"Pulkovo 1942 / Gauss-Kruger CM 171W",9001,4284,16332,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2523,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 7",9001,4284,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+2524,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 8",9001,4284,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+2525,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 9",9001,4284,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+2526,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 10",9001,4284,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,,,,,,,,
+2527,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 11",9001,4284,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,,,,,,,,
+2528,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 12",9001,4284,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,,,,,,,,
+2529,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 13",9001,4284,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+2530,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 14",9001,4284,16274,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+2531,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 15",9001,4284,16275,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+2532,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 16",9001,4284,16276,9807,1,0,4530,8801,0,9102,8802,48,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,,,,,,,,
+2533,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 17",9001,4284,16277,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,,,,,,,,
+2534,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 18",9001,4284,16278,9807,1,0,4530,8801,0,9102,8802,54,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,,,,,,,,
+2535,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 19",9001,4284,16279,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+2536,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 20",9001,4284,16280,9807,1,0,4530,8801,0,9102,8802,60,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,,,,,,,,
+2537,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 21",9001,4284,16281,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,,,,,,,,
+2538,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 22",9001,4284,16282,9807,1,0,4530,8801,0,9102,8802,66,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,,,,,,,,
+2539,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 23",9001,4284,16283,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,,,,,,,,
+2540,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 24",9001,4284,16284,9807,1,0,4530,8801,0,9102,8802,72,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,,,,,,,,
+2541,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 25",9001,4284,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,,,,,,,,
+2542,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 26",9001,4284,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,,,,,,,,
+2543,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 27",9001,4284,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,,,,,,,,
+2544,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 28",9001,4284,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,,,,,,,,
+2545,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 29",9001,4284,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,,,,,,,,
+2546,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 30",9001,4284,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,,,,,,,,
+2547,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 31",9001,4284,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+2548,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 32",9001,4284,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+2549,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 33",9001,4284,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,,,,,,,,
+2550,"Samboja / UTM zone 50S",9001,4125,16150,9807,1,1,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2551,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 34",9001,4284,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,,,,,,,,
+2552,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 35",9001,4284,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,,,,,,,,
+2553,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 36",9001,4284,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,,,,,,,,
+2554,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 37",9001,4284,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,,,,,,,,
+2555,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 38",9001,4284,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,,,,,,,,
+2556,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 39",9001,4284,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,,,,,,,,
+2557,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 40",9001,4284,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,,,,,,,,
+2558,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 41",9001,4284,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,,,,,,,,
+2559,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 42",9001,4284,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,,,,,,,,
+2560,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 43",9001,4284,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,,,,,,,,
+2561,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 44",9001,4284,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,,,,,,,,
+2562,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 45",9001,4284,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,,,,,,,,
+2563,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 46",9001,4284,16076,9807,1,0,4530,8801,0,9102,8802,138,9102,8805,1,9201,8806,46500000,9001,8807,0,9001,,,,,,,,,,,,,
+2564,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 47",9001,4284,16077,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,47500000,9001,8807,0,9001,,,,,,,,,,,,,
+2565,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 48",9001,4284,16078,9807,1,0,4530,8801,0,9102,8802,144,9102,8805,1,9201,8806,48500000,9001,8807,0,9001,,,,,,,,,,,,,
+2566,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 49",9001,4284,16079,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,49500000,9001,8807,0,9001,,,,,,,,,,,,,
+2567,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 50",9001,4284,16080,9807,1,0,4530,8801,0,9102,8802,150,9102,8805,1,9201,8806,50500000,9001,8807,0,9001,,,,,,,,,,,,,
+2568,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 51",9001,4284,16081,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,51500000,9001,8807,0,9001,,,,,,,,,,,,,
+2569,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 52",9001,4284,16082,9807,1,0,4530,8801,0,9102,8802,156,9102,8805,1,9201,8806,52500000,9001,8807,0,9001,,,,,,,,,,,,,
+2570,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 53",9001,4284,16083,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,53500000,9001,8807,0,9001,,,,,,,,,,,,,
+2571,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 54",9001,4284,16084,9807,1,0,4530,8801,0,9102,8802,162,9102,8805,1,9201,8806,54500000,9001,8807,0,9001,,,,,,,,,,,,,
+2572,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 55",9001,4284,16085,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,55500000,9001,8807,0,9001,,,,,,,,,,,,,
+2573,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 56",9001,4284,16086,9807,1,0,4530,8801,0,9102,8802,168,9102,8805,1,9201,8806,56500000,9001,8807,0,9001,,,,,,,,,,,,,
+2574,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 57",9001,4284,16087,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,57500000,9001,8807,0,9001,,,,,,,,,,,,,
+2575,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 58",9001,4284,16088,9807,1,0,4530,8801,0,9102,8802,174,9102,8805,1,9201,8806,58500000,9001,8807,0,9001,,,,,,,,,,,,,
+2576,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 59",9001,4284,16089,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,59500000,9001,8807,0,9001,,,,,,,,,,,,,
+2577,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 60",9001,4284,16090,9807,1,1,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,60000000,9001,8807,0,9001,,,,,,,,,,,,,
+2578,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 61",9001,4284,16091,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,61500000,9001,8807,0,9001,,,,,,,,,,,,,
+2579,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 62",9001,4284,16092,9807,1,0,4530,8801,0,9102,8802,-174,9102,8805,1,9201,8806,62500000,9001,8807,0,9001,,,,,,,,,,,,,
+2580,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 63",9001,4284,16093,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,63500000,9001,8807,0,9001,,,,,,,,,,,,,
+2581,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 64",9001,4284,16094,9807,1,0,4530,8801,0,9102,8802,-168,9102,8805,1,9201,8806,64500000,9001,8807,0,9001,,,,,,,,,,,,,
+2582,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 21E",9001,4284,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2583,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 24E",9001,4284,16368,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2584,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 27E",9001,4284,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2585,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 30E",9001,4284,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2586,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 33E",9001,4284,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2587,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 36E",9001,4284,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2588,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 39E",9001,4284,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2589,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 42E",9001,4284,16374,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2590,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 45E",9001,4284,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2591,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 48E",9001,4284,16376,9807,1,0,4530,8801,0,9102,8802,48,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2592,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 51E",9001,4284,16309,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2593,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 54E",9001,4284,16378,9807,1,0,4530,8801,0,9102,8802,54,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2594,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 57E",9001,4284,16310,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2595,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 60E",9001,4284,16380,9807,1,0,4530,8801,0,9102,8802,60,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2596,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 63E",9001,4284,16311,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2597,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 66E",9001,4284,16382,9807,1,0,4530,8801,0,9102,8802,66,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2598,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 69E",9001,4284,16312,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2599,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 72E",9001,4284,16384,9807,1,0,4530,8801,0,9102,8802,72,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2600,Lietuvos Koordinoei Sistema 1994,9001,4669,19934,9807,1,1,4530,8801,0,9102,8802,24,9102,8805,0.9998,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2601,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 75E",9001,4284,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2602,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 78E",9001,4284,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2603,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 81E",9001,4284,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2604,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 84E",9001,4284,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2605,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 87E",9001,4284,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2606,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 90E",9001,4284,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2607,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 93E",9001,4284,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2608,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 96E",9001,4284,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2609,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 99E",9001,4284,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2610,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 102E",9001,4284,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2611,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 105E",9001,4284,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2612,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 108E",9001,4284,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2613,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 111E",9001,4284,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2614,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 114E",9001,4284,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2615,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 117E",9001,4284,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2616,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 120E",9001,4284,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2617,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 123E",9001,4284,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2618,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 126E",9001,4284,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2619,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 129E",9001,4284,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2620,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 132E",9001,4284,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2621,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 135E",9001,4284,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2622,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 138E",9001,4284,16176,9807,1,0,4530,8801,0,9102,8802,138,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2623,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 141E",9001,4284,16324,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2624,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 144E",9001,4284,16178,9807,1,0,4530,8801,0,9102,8802,144,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2625,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 147E",9001,4284,16325,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2626,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 150E",9001,4284,16180,9807,1,0,4530,8801,0,9102,8802,150,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2627,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 153E",9001,4284,16326,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2628,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 156E",9001,4284,16182,9807,1,0,4530,8801,0,9102,8802,156,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2629,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 159E",9001,4284,16327,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2630,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 162E",9001,4284,16184,9807,1,0,4530,8801,0,9102,8802,162,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2631,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 165E",9001,4284,16328,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2632,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 168E",9001,4284,16186,9807,1,0,4530,8801,0,9102,8802,168,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2633,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 171E",9001,4284,16329,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2634,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 174E",9001,4284,16188,9807,1,0,4530,8801,0,9102,8802,174,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2635,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 177E",9001,4284,16330,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2636,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 180E",9001,4284,16190,9807,1,0,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2637,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 177W",9001,4284,16331,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2638,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 174W",9001,4284,16192,9807,1,0,4530,8801,0,9102,8802,-174,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2639,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 171W",9001,4284,16332,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2640,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 168W",9001,4284,16194,9807,1,0,4530,8801,0,9102,8802,-168,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2641,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 7",9001,4200,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+2642,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 8",9001,4200,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+2643,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 9",9001,4200,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+2644,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 10",9001,4200,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,,,,,,,,
+2645,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 11",9001,4200,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,,,,,,,,
+2646,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 12",9001,4200,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,,,,,,,,
+2647,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 13",9001,4200,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+2648,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 14",9001,4200,16274,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+2649,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 15",9001,4200,16275,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+2650,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 16",9001,4200,16276,9807,1,0,4530,8801,0,9102,8802,48,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,,,,,,,,
+2651,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 17",9001,4200,16277,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,,,,,,,,
+2652,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 18",9001,4200,16278,9807,1,0,4530,8801,0,9102,8802,54,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,,,,,,,,
+2653,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 19",9001,4200,16279,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+2654,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 20",9001,4200,16280,9807,1,0,4530,8801,0,9102,8802,60,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,,,,,,,,
+2655,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 21",9001,4200,16281,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,,,,,,,,
+2656,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 22",9001,4200,16282,9807,1,0,4530,8801,0,9102,8802,66,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,,,,,,,,
+2657,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 23",9001,4200,16283,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,,,,,,,,
+2658,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 24",9001,4200,16284,9807,1,0,4530,8801,0,9102,8802,72,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,,,,,,,,
+2659,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 25",9001,4200,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,,,,,,,,
+2660,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 26",9001,4200,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,,,,,,,,
+2661,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 27",9001,4200,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,,,,,,,,
+2662,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 28",9001,4200,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,,,,,,,,
+2663,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 29",9001,4200,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,,,,,,,,
+2664,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 30",9001,4200,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,,,,,,,,
+2665,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 31",9001,4200,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+2666,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 32",9001,4200,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+2667,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 33",9001,4200,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,,,,,,,,
+2668,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 34",9001,4200,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,,,,,,,,
+2669,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 35",9001,4200,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,,,,,,,,
+2670,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 36",9001,4200,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,,,,,,,,
+2671,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 37",9001,4200,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,,,,,,,,
+2672,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 38",9001,4200,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,,,,,,,,
+2673,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 39",9001,4200,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,,,,,,,,
+2674,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 40",9001,4200,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,,,,,,,,
+2675,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 41",9001,4200,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,,,,,,,,
+2676,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 42",9001,4200,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,,,,,,,,
+2677,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 43",9001,4200,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,,,,,,,,
+2678,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 44",9001,4200,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,,,,,,,,
+2679,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 45",9001,4200,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,,,,,,,,
+2680,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 46",9001,4200,16076,9807,1,0,4530,8801,0,9102,8802,138,9102,8805,1,9201,8806,46500000,9001,8807,0,9001,,,,,,,,,,,,,
+2681,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 47",9001,4200,16077,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,47500000,9001,8807,0,9001,,,,,,,,,,,,,
+2682,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 48",9001,4200,16078,9807,1,0,4530,8801,0,9102,8802,144,9102,8805,1,9201,8806,48500000,9001,8807,0,9001,,,,,,,,,,,,,
+2683,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 49",9001,4200,16079,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,49500000,9001,8807,0,9001,,,,,,,,,,,,,
+2684,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 50",9001,4200,16080,9807,1,0,4530,8801,0,9102,8802,150,9102,8805,1,9201,8806,50500000,9001,8807,0,9001,,,,,,,,,,,,,
+2685,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 51",9001,4200,16081,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,51500000,9001,8807,0,9001,,,,,,,,,,,,,
+2686,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 52",9001,4200,16082,9807,1,0,4530,8801,0,9102,8802,156,9102,8805,1,9201,8806,52500000,9001,8807,0,9001,,,,,,,,,,,,,
+2687,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 53",9001,4200,16083,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,53500000,9001,8807,0,9001,,,,,,,,,,,,,
+2688,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 54",9001,4200,16084,9807,1,0,4530,8801,0,9102,8802,162,9102,8805,1,9201,8806,54500000,9001,8807,0,9001,,,,,,,,,,,,,
+2689,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 55",9001,4200,16085,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,55500000,9001,8807,0,9001,,,,,,,,,,,,,
+2690,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 56",9001,4200,16086,9807,1,0,4530,8801,0,9102,8802,168,9102,8805,1,9201,8806,56500000,9001,8807,0,9001,,,,,,,,,,,,,
+2691,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 57",9001,4200,16087,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,57500000,9001,8807,0,9001,,,,,,,,,,,,,
+2692,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 58",9001,4200,16088,9807,1,0,4530,8801,0,9102,8802,174,9102,8805,1,9201,8806,58500000,9001,8807,0,9001,,,,,,,,,,,,,
+2693,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 59",9001,4200,16089,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,59500000,9001,8807,0,9001,,,,,,,,,,,,,
+2694,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 60",9001,4200,16090,9807,1,1,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,60000000,9001,8807,0,9001,,,,,,,,,,,,,
+2695,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 61",9001,4200,16091,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,61500000,9001,8807,0,9001,,,,,,,,,,,,,
+2696,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 62",9001,4200,16092,9807,1,0,4530,8801,0,9102,8802,-174,9102,8805,1,9201,8806,62500000,9001,8807,0,9001,,,,,,,,,,,,,
+2697,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 63",9001,4200,16093,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,63500000,9001,8807,0,9001,,,,,,,,,,,,,
+2698,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 64",9001,4200,16094,9807,1,0,4530,8801,0,9102,8802,-168,9102,8805,1,9201,8806,64500000,9001,8807,0,9001,,,,,,,,,,,,,
+2699,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 21E",9001,4200,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2700,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 24E",9001,4200,16368,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2701,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 27E",9001,4200,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2702,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 30E",9001,4200,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2703,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 33E",9001,4200,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2704,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 36E",9001,4200,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2705,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 39E",9001,4200,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2706,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 42E",9001,4200,16374,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2707,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 45E",9001,4200,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2708,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 48E",9001,4200,16376,9807,1,0,4530,8801,0,9102,8802,48,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2709,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 51E",9001,4200,16309,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2710,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 54E",9001,4200,16378,9807,1,0,4530,8801,0,9102,8802,54,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2711,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 57E",9001,4200,16310,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2712,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 60E",9001,4200,16380,9807,1,0,4530,8801,0,9102,8802,60,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2713,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 63E",9001,4200,16311,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2714,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 66E",9001,4200,16382,9807,1,0,4530,8801,0,9102,8802,66,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2715,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 69E",9001,4200,16312,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2716,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 72E",9001,4200,16384,9807,1,0,4530,8801,0,9102,8802,72,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2717,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 75E",9001,4200,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2718,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 78E",9001,4200,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2719,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 81E",9001,4200,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2720,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 84E",9001,4200,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2721,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 87E",9001,4200,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2722,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 90E",9001,4200,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2723,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 93E",9001,4200,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2724,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 96E",9001,4200,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2725,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 99E",9001,4200,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2726,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 102E",9001,4200,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2727,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 105E",9001,4200,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2728,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 108E",9001,4200,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2729,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 111E",9001,4200,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2730,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 114E",9001,4200,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2731,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 117E",9001,4200,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2732,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 120E",9001,4200,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2733,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 123E",9001,4200,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2734,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 126E",9001,4200,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2735,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 129E",9001,4200,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2736,"Tete / UTM zone 36S",9001,4127,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2737,"Tete / UTM zone 37S",9001,4127,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2738,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 132E",9001,4200,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2739,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 135E",9001,4200,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2740,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 138E",9001,4200,16176,9807,1,0,4530,8801,0,9102,8802,138,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2741,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 141E",9001,4200,16324,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2742,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 144E",9001,4200,16178,9807,1,0,4530,8801,0,9102,8802,144,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2743,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 147E",9001,4200,16325,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2744,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 150E",9001,4200,16180,9807,1,0,4530,8801,0,9102,8802,150,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2745,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 153E",9001,4200,16326,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2746,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 156E",9001,4200,16182,9807,1,0,4530,8801,0,9102,8802,156,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2747,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 159E",9001,4200,16327,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2748,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 162E",9001,4200,16184,9807,1,0,4530,8801,0,9102,8802,162,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2749,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 165E",9001,4200,16328,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2750,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 168E",9001,4200,16186,9807,1,0,4530,8801,0,9102,8802,168,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2751,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 171E",9001,4200,16329,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2752,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 174E",9001,4200,16188,9807,1,0,4530,8801,0,9102,8802,174,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2753,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 177E",9001,4200,16330,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2754,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 180E",9001,4200,16190,9807,1,0,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2755,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 177W",9001,4200,16331,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2756,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 174W",9001,4200,16192,9807,1,0,4530,8801,0,9102,8802,-174,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2757,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 171W",9001,4200,16332,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2758,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 168W",9001,4200,16194,9807,1,0,4530,8801,0,9102,8802,-168,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2759,"NAD83(HARN) / Alabama East",9001,4152,10131,9807,1,0,4499,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2760,"NAD83(HARN) / Alabama West",9001,4152,10132,9807,1,0,4499,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,600000,9001,8807,0,9001,,,,,,,,,,,,,
+2761,"NAD83(HARN) / Arizona East",9001,4152,10231,9807,1,0,4499,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+2762,"NAD83(HARN) / Arizona Central",9001,4152,10232,9807,1,0,4499,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+2763,"NAD83(HARN) / Arizona West",9001,4152,10233,9807,1,0,4499,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+2764,"NAD83(HARN) / Arkansas North",9001,4152,10331,9802,1,0,4499,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+2765,"NAD83(HARN) / Arkansas South",9001,4152,10332,9802,1,0,4499,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+2766,"NAD83(HARN) / California zone 1",9001,4152,10431,9802,1,0,4499,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+2767,"NAD83(HARN) / California zone 2",9001,4152,10432,9802,1,0,4499,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+2768,"NAD83(HARN) / California zone 3",9001,4152,10433,9802,1,0,4499,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+2769,"NAD83(HARN) / California zone 4",9001,4152,10434,9802,1,0,4499,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+2770,"NAD83(HARN) / California zone 5",9001,4152,10435,9802,1,0,4499,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+2771,"NAD83(HARN) / California zone 6",9001,4152,10436,9802,1,0,4499,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+2772,"NAD83(HARN) / Colorado North",9001,4152,10531,9802,1,0,4499,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+2773,"NAD83(HARN) / Colorado Central",9001,4152,10532,9802,1,0,4499,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+2774,"NAD83(HARN) / Colorado South",9001,4152,10533,9802,1,0,4499,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+2775,"NAD83(HARN) / Connecticut",9001,4152,10630,9802,1,0,4499,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,304800.6096,9001,8827,152400.3048,9001,,,,,,,,,,
+2776,"NAD83(HARN) / Delaware",9001,4152,10730,9807,1,0,4499,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2777,"NAD83(HARN) / Florida East",9001,4152,10931,9807,1,0,4499,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2778,"NAD83(HARN) / Florida West",9001,4152,10932,9807,1,0,4499,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2779,"NAD83(HARN) / Florida North",9001,4152,10933,9802,1,0,4499,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2780,"NAD83(HARN) / Georgia East",9001,4152,11031,9807,1,0,4499,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2781,"NAD83(HARN) / Georgia West",9001,4152,11032,9807,1,0,4499,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+2782,"NAD83(HARN) / Hawaii zone 1",9001,4152,15131,9807,1,0,4499,8801,18.5,9110,8802,-155.3,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2783,"NAD83(HARN) / Hawaii zone 2",9001,4152,15132,9807,1,0,4499,8801,20.2,9110,8802,-156.4,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2784,"NAD83(HARN) / Hawaii zone 3",9001,4152,15133,9807,1,0,4499,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2785,"NAD83(HARN) / Hawaii zone 4",9001,4152,15134,9807,1,0,4499,8801,21.5,9110,8802,-159.3,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2786,"NAD83(HARN) / Hawaii zone 5",9001,4152,15135,9807,1,0,4499,8801,21.4,9110,8802,-160.1,9110,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2787,"NAD83(HARN) / Idaho East",9001,4152,11131,9807,1,0,4499,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2788,"NAD83(HARN) / Idaho Central",9001,4152,11132,9807,1,0,4499,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2789,"NAD83(HARN) / Idaho West",9001,4152,11133,9807,1,0,4499,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,800000,9001,8807,0,9001,,,,,,,,,,,,,
+2790,"NAD83(HARN) / Illinois East",9001,4152,11231,9807,1,0,4499,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+2791,"NAD83(HARN) / Illinois West",9001,4152,11232,9807,1,0,4499,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+2792,"NAD83(HARN) / Indiana East",9001,4152,11331,9807,1,0,4499,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,100000,9001,8807,250000,9001,,,,,,,,,,,,,
+2793,"NAD83(HARN) / Indiana West",9001,4152,11332,9807,1,0,4499,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,900000,9001,8807,250000,9001,,,,,,,,,,,,,
+2794,"NAD83(HARN) / Iowa North",9001,4152,11431,9802,1,0,4499,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,1500000,9001,8827,1000000,9001,,,,,,,,,,
+2795,"NAD83(HARN) / Iowa South",9001,4152,11432,9802,1,0,4499,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+2796,"NAD83(HARN) / Kansas North",9001,4152,11531,9802,1,0,4499,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+2797,"NAD83(HARN) / Kansas South",9001,4152,11532,9802,1,0,4499,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+2798,"NAD83(HARN) / Kentucky North",9001,4152,15303,9802,1,0,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+2799,"NAD83(HARN) / Kentucky South",9001,4152,11632,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+2800,"NAD83(HARN) / Louisiana North",9001,4152,11731,9802,1,0,4499,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+2801,"NAD83(HARN) / Louisiana South",9001,4152,11732,9802,1,0,4499,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+2802,"NAD83(HARN) / Maine East",9001,4152,11831,9807,1,0,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+2803,"NAD83(HARN) / Maine West",9001,4152,11832,9807,1,0,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,900000,9001,8807,0,9001,,,,,,,,,,,,,
+2804,"NAD83(HARN) / Maryland",9001,4152,11930,9802,1,0,4499,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+2805,"NAD83(HARN) / Massachusetts Mainland",9001,4152,12031,9802,1,0,4499,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,200000,9001,8827,750000,9001,,,,,,,,,,
+2806,"NAD83(HARN) / Massachusetts Island",9001,4152,12032,9802,1,0,4499,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+2807,"NAD83(HARN) / Michigan North",9001,4152,12141,9802,1,0,4499,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,8000000,9001,8827,0,9001,,,,,,,,,,
+2808,"NAD83(HARN) / Michigan Central",9001,4152,12142,9802,1,0,4499,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,6000000,9001,8827,0,9001,,,,,,,,,,
+2809,"NAD83(HARN) / Michigan South",9001,4152,12143,9802,1,0,4499,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,4000000,9001,8827,0,9001,,,,,,,,,,
+2810,"NAD83(HARN) / Minnesota North",9001,4152,12231,9802,1,0,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+2811,"NAD83(HARN) / Minnesota Central",9001,4152,12232,9802,1,0,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+2812,"NAD83(HARN) / Minnesota South",9001,4152,12233,9802,1,0,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+2813,"NAD83(HARN) / Mississippi East",9001,4152,12331,9807,1,0,4499,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+2814,"NAD83(HARN) / Mississippi West",9001,4152,12332,9807,1,0,4499,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+2815,"NAD83(HARN) / Missouri East",9001,4152,12431,9807,1,0,4499,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+2816,"NAD83(HARN) / Missouri Central",9001,4152,12432,9807,1,0,4499,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2817,"NAD83(HARN) / Missouri West",9001,4152,12433,9807,1,0,4499,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,850000,9001,8807,0,9001,,,,,,,,,,,,,
+2818,"NAD83(HARN) / Montana",9001,4152,12530,9802,1,0,4499,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2819,"NAD83(HARN) / Nebraska",9001,4152,12630,9802,1,0,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+2820,"NAD83(HARN) / Nevada East",9001,4152,12731,9807,1,0,4499,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,200000,9001,8807,8000000,9001,,,,,,,,,,,,,
+2821,"NAD83(HARN) / Nevada Central",9001,4152,12732,9807,1,0,4499,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9001,8807,6000000,9001,,,,,,,,,,,,,
+2822,"NAD83(HARN) / Nevada West",9001,4152,12733,9807,1,0,4499,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,800000,9001,8807,4000000,9001,,,,,,,,,,,,,
+2823,"NAD83(HARN) / New Hampshire",9001,4152,12830,9807,1,0,4499,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+2824,"NAD83(HARN) / New Jersey",9001,4152,12930,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+2825,"NAD83(HARN) / New Mexico East",9001,4152,13031,9807,1,0,4499,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,165000,9001,8807,0,9001,,,,,,,,,,,,,
+2826,"NAD83(HARN) / New Mexico Central",9001,4152,13032,9807,1,0,4499,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2827,"NAD83(HARN) / New Mexico West",9001,4152,13033,9807,1,0,4499,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,830000,9001,8807,0,9001,,,,,,,,,,,,,
+2828,"NAD83(HARN) / New York East",9001,4152,13131,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+2829,"NAD83(HARN) / New York Central",9001,4152,13132,9807,1,0,4499,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+2830,"NAD83(HARN) / New York West",9001,4152,13133,9807,1,0,4499,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,350000,9001,8807,0,9001,,,,,,,,,,,,,
+2831,"NAD83(HARN) / New York Long Island",9001,4152,13134,9802,1,0,4499,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,300000,9001,8827,0,9001,,,,,,,,,,
+2832,"NAD83(HARN) / North Dakota North",9001,4152,13331,9802,1,0,4499,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2833,"NAD83(HARN) / North Dakota South",9001,4152,13332,9802,1,0,4499,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2834,"NAD83(HARN) / Ohio North",9001,4152,13431,9802,1,0,4499,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2835,"NAD83(HARN) / Ohio South",9001,4152,13432,9802,1,0,4499,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2836,"NAD83(HARN) / Oklahoma North",9001,4152,13531,9802,1,0,4499,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2837,"NAD83(HARN) / Oklahoma South",9001,4152,13532,9802,1,0,4499,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2838,"NAD83(HARN) / Oregon North",9001,4152,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,,,,,,,,
+2839,"NAD83(HARN) / Oregon South",9001,4152,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,,,,,,,,
+2840,"NAD83(HARN) / Rhode Island",9001,4152,13830,9807,1,0,4499,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,100000,9001,8807,0,9001,,,,,,,,,,,,,
+2841,"NAD83(HARN) / South Dakota North",9001,4152,14031,9802,1,0,4499,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2842,"NAD83(HARN) / South Dakota South",9001,4152,14032,9802,1,0,4499,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2843,"NAD83(HARN) / Tennessee",9001,4152,14130,9802,1,0,4499,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2844,"NAD83(HARN) / Texas North",9001,4152,14231,9802,1,0,4499,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,200000,9001,8827,1000000,9001,,,,,,,,,,
+2845,"NAD83(HARN) / Texas North Central",9001,4152,14232,9802,1,0,4499,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,600000,9001,8827,2000000,9001,,,,,,,,,,
+2846,"NAD83(HARN) / Texas Central",9001,4152,14233,9802,1,0,4499,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,700000,9001,8827,3000000,9001,,,,,,,,,,
+2847,"NAD83(HARN) / Texas South Central",9001,4152,14234,9802,1,0,4499,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,600000,9001,8827,4000000,9001,,,,,,,,,,
+2848,"NAD83(HARN) / Texas South",9001,4152,14235,9802,1,0,4499,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,300000,9001,8827,5000000,9001,,,,,,,,,,
+2849,"NAD83(HARN) / Utah North",9001,4152,14331,9802,1,0,4499,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,500000,9001,8827,1000000,9001,,,,,,,,,,
+2850,"NAD83(HARN) / Utah Central",9001,4152,14332,9802,1,0,4499,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,500000,9001,8827,2000000,9001,,,,,,,,,,
+2851,"NAD83(HARN) / Utah South",9001,4152,14333,9802,1,0,4499,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,500000,9001,8827,3000000,9001,,,,,,,,,,
+2852,"NAD83(HARN) / Vermont",9001,4152,14430,9807,1,0,4499,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2853,"NAD83(HARN) / Virginia North",9001,4152,14531,9802,1,0,4499,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,3500000,9001,8827,2000000,9001,,,,,,,,,,
+2854,"NAD83(HARN) / Virginia South",9001,4152,14532,9802,1,0,4499,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,3500000,9001,8827,1000000,9001,,,,,,,,,,
+2855,"NAD83(HARN) / Washington North",9001,4152,14631,9802,1,0,4499,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+2856,"NAD83(HARN) / Washington South",9001,4152,14632,9802,1,0,4499,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+2857,"NAD83(HARN) / West Virginia North",9001,4152,14731,9802,1,0,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2858,"NAD83(HARN) / West Virginia South",9001,4152,14732,9802,1,0,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2859,"NAD83(HARN) / Wisconsin North",9001,4152,14831,9802,1,0,4499,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2860,"NAD83(HARN) / Wisconsin Central",9001,4152,14832,9802,1,0,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2861,"NAD83(HARN) / Wisconsin South",9001,4152,14833,9802,1,0,4499,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+2862,"NAD83(HARN) / Wyoming East",9001,4152,14931,9807,1,0,4499,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+2863,"NAD83(HARN) / Wyoming East Central",9001,4152,14932,9807,1,0,4499,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,400000,9001,8807,100000,9001,,,,,,,,,,,,,
+2864,"NAD83(HARN) / Wyoming West Central",9001,4152,14933,9807,1,0,4499,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,600000,9001,8807,0,9001,,,,,,,,,,,,,
+2865,"NAD83(HARN) / Wyoming West",9001,4152,14934,9807,1,0,4499,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,800000,9001,8807,100000,9001,,,,,,,,,,,,,
+2866,"NAD83(HARN) / Puerto Rico and Virgin Is.",9001,4152,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,,,,,,,,
+2867,"NAD83(HARN) / Arizona East (ft)",9002,4152,15304,9807,1,0,4495,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+2868,"NAD83(HARN) / Arizona Central (ft)",9002,4152,15305,9807,1,0,4495,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+2869,"NAD83(HARN) / Arizona West (ft)",9002,4152,15306,9807,1,0,4495,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+2870,"NAD83(HARN) / California zone 1 (ftUS)",9003,4152,15307,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2871,"NAD83(HARN) / California zone 2 (ftUS)",9003,4152,15308,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2872,"NAD83(HARN) / California zone 3 (ftUS)",9003,4152,15309,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2873,"NAD83(HARN) / California zone 4 (ftUS)",9003,4152,15310,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2874,"NAD83(HARN) / California zone 5 (ftUS)",9003,4152,15311,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2875,"NAD83(HARN) / California zone 6 (ftUS)",9003,4152,15312,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2876,"NAD83(HARN) / Colorado North (ftUS)",9003,4152,15313,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+2877,"NAD83(HARN) / Colorado Central (ftUS)",9003,4152,15314,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+2878,"NAD83(HARN) / Colorado South (ftUS)",9003,4152,15315,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+2879,"NAD83(HARN) / Connecticut (ftUS)",9003,4152,15316,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,1000000,9003,8827,500000,9003,,,,,,,,,,
+2880,"NAD83(HARN) / Delaware (ftUS)",9003,4152,15317,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2881,"NAD83(HARN) / Florida East (ftUS)",9003,4152,15318,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2882,"NAD83(HARN) / Florida West (ftUS)",9003,4152,15319,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2883,"NAD83(HARN) / Florida North (ftUS)",9003,4152,15320,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2884,"NAD83(HARN) / Georgia East (ftUS)",9003,4152,15321,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2885,"NAD83(HARN) / Georgia West (ftUS)",9003,4152,15322,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,2296583.333,9003,8807,0,9003,,,,,,,,,,,,,
+2886,"NAD83(HARN) / Idaho East (ftUS)",9003,4152,15323,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+2887,"NAD83(HARN) / Idaho Central (ftUS)",9003,4152,15324,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,1640416.667,9003,8807,0,9003,,,,,,,,,,,,,
+2888,"NAD83(HARN) / Idaho West (ftUS)",9003,4152,15325,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,2624666.667,9003,8807,0,9003,,,,,,,,,,,,,
+2889,"NAD83(HARN) / Indiana East (ftUS)",9003,4152,15326,9807,1,1,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,818125,9003,,,,,,,,,,,,,
+2890,"NAD83(HARN) / Indiana West (ftUS)",9003,4152,15327,9807,1,1,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,818125,9003,,,,,,,,,,,,,
+2891,"NAD83(HARN) / Kentucky North (ftUS)",9003,4152,15328,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+2892,"NAD83(HARN) / Kentucky South (ftUS)",9003,4152,15329,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,1640416.667,9003,8827,1640416.667,9003,,,,,,,,,,
+2893,"NAD83(HARN) / Maryland (ftUS)",9003,4152,15330,9802,1,0,4497,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,1312333.333,9003,8827,0,9003,,,,,,,,,,
+2894,"NAD83(HARN) / Massachusetts Mainland (ftUS)",9003,4152,15331,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,656166.667,9003,8827,2460625,9003,,,,,,,,,,
+2895,"NAD83(HARN) / Massachusetts Island (ftUS)",9003,4152,15332,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+2896,"NAD83(HARN) / Michigan North (ft)",9002,4152,15333,9802,1,0,4495,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,26246719.16,9002,8827,0,9002,,,,,,,,,,
+2897,"NAD83(HARN) / Michigan Central (ft)",9002,4152,15334,9802,1,0,4495,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,19685039.37,9002,8827,0,9002,,,,,,,,,,
+2898,"NAD83(HARN) / Michigan South (ft)",9002,4152,15335,9802,1,0,4495,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,13123359.58,9002,8827,0,9002,,,,,,,,,,
+2899,"NAD83(HARN) / Mississippi East (ftUS)",9003,4152,15336,9807,1,0,4497,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+2900,"NAD83(HARN) / Mississippi West (ftUS)",9003,4152,15337,9807,1,0,4497,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,2296583.333,9003,8807,0,9003,,,,,,,,,,,,,
+2901,"NAD83(HARN) / Montana (ft)",9002,4152,15338,9802,1,0,4495,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+2902,"NAD83(HARN) / New Mexico East (ftUS)",9003,4152,15339,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,541337.5,9003,8807,0,9003,,,,,,,,,,,,,
+2903,"NAD83(HARN) / New Mexico Central (ftUS)",9003,4152,15340,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,1640416.667,9003,8807,0,9003,,,,,,,,,,,,,
+2904,"NAD83(HARN) / New Mexico West (ftUS)",9003,4152,15341,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,2723091.667,9003,8807,0,9003,,,,,,,,,,,,,
+2905,"NAD83(HARN) / New York East (ftUS)",9003,4152,15342,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,,,,,,,,
+2906,"NAD83(HARN) / New York Central (ftUS)",9003,4152,15343,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,820208.333,9003,8807,0,9003,,,,,,,,,,,,,
+2907,"NAD83(HARN) / New York West (ftUS)",9003,4152,15344,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,1148291.667,9003,8807,0,9003,,,,,,,,,,,,,
+2908,"NAD83(HARN) / New York Long Island (ftUS)",9003,4152,15345,9802,1,0,4497,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,984250,9003,8827,0,9003,,,,,,,,,,
+2909,"NAD83(HARN) / North Dakota North (ft)",9002,4152,15347,9802,1,0,4495,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+2910,"NAD83(HARN) / North Dakota South (ft)",9002,4152,15348,9802,1,0,4495,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+2911,"NAD83(HARN) / Oklahoma North (ftUS)",9003,4152,15349,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2912,"NAD83(HARN) / Oklahoma South (ftUS)",9003,4152,15350,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2913,"NAD83(HARN) / Oregon North (ft)",9002,4152,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,,,,,,,,
+2914,"NAD83(HARN) / Oregon South (ft)",9002,4152,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,,,,,,,,
+2915,"NAD83(HARN) / Tennessee (ftUS)",9003,4152,15356,9802,1,0,4497,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2916,"NAD83(HARN) / Texas North (ftUS)",9003,4152,15357,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,656166.667,9003,8827,3280833.333,9003,,,,,,,,,,
+2917,"NAD83(HARN) / Texas North Central (ftUS)",9003,4152,15358,9802,1,0,4497,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,1968500,9003,8827,6561666.667,9003,,,,,,,,,,
+2918,"NAD83(HARN) / Texas Central (ftUS)",9003,4152,15359,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,2296583.333,9003,8827,9842500,9003,,,,,,,,,,
+2919,"NAD83(HARN) / Texas South Central (ftUS)",9003,4152,15360,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,1968500,9003,8827,13123333.333,9003,,,,,,,,,,
+2920,"NAD83(HARN) / Texas South (ftUS)",9003,4152,15361,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,984250,9003,8827,16404166.667,9003,,,,,,,,,,
+2921,"NAD83(HARN) / Utah North (ft)",9002,4152,15362,9802,0,0,4495,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640419.948,9002,8827,3280839.895,9002,,,,,,,,,,
+2922,"NAD83(HARN) / Utah Central (ft)",9002,4152,15363,9802,0,0,4495,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640419.948,9002,8827,6561679.79,9002,,,,,,,,,,
+2923,"NAD83(HARN) / Utah South (ft)",9002,4152,15364,9802,0,0,4495,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640419.948,9002,8827,9842519.685,9002,,,,,,,,,,
+2924,"NAD83(HARN) / Virginia North (ftUS)",9003,4152,15365,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,11482916.667,9003,8827,6561666.667,9003,,,,,,,,,,
+2925,"NAD83(HARN) / Virginia South (ftUS)",9003,4152,15366,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,11482916.667,9003,8827,3280833.333,9003,,,,,,,,,,
+2926,"NAD83(HARN) / Washington North (ftUS)",9003,4152,15367,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+2927,"NAD83(HARN) / Washington South (ftUS)",9003,4152,15368,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+2928,"NAD83(HARN) / Wisconsin North (ftUS)",9003,4152,15369,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2929,"NAD83(HARN) / Wisconsin Central (ftUS)",9003,4152,15370,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2930,"NAD83(HARN) / Wisconsin South (ftUS)",9003,4152,15371,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+2931,"Beduaram / TM 13 NE",9001,4213,16413,9807,1,0,4499,8801,0,9102,8802,13,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2932,"QND95 / Qatar National Grid",9001,4614,19919,9807,1,0,4400,8801,24.27,9110,8802,51.13,9110,8805,0.99999,9201,8806,200000,9001,8807,300000,9001,,,,,,,,,,,,,
+2933,"Segara / UTM zone 50S",9001,4613,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2934,"Segara (Jakarta) / NEIEZ",9001,4820,19905,9804,1,1,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,,,,,,,,
+2935,"Pulkovo 1942 / CS63 zone A1",9001,4284,18441,9807,1,0,4530,8801,0.07,9110,8802,41.32,9110,8805,1,9201,8806,1300000,9001,8807,0,9001,,,,,,,,,,,,,
+2936,"Pulkovo 1942 / CS63 zone A2",9001,4284,18442,9807,1,0,4530,8801,0.07,9110,8802,44.32,9110,8805,1,9201,8806,2300000,9001,8807,0,9001,,,,,,,,,,,,,
+2937,"Pulkovo 1942 / CS63 zone A3",9001,4284,18443,9807,1,0,4530,8801,0.07,9110,8802,47.32,9110,8805,1,9201,8806,3300000,9001,8807,0,9001,,,,,,,,,,,,,
+2938,"Pulkovo 1942 / CS63 zone A4",9001,4284,18444,9807,1,0,4530,8801,0.07,9110,8802,50.32,9110,8805,1,9201,8806,4300000,9001,8807,0,9001,,,,,,,,,,,,,
+2939,"Pulkovo 1942 / CS63 zone K2",9001,4284,18446,9807,1,0,4530,8801,0.08,9110,8802,50.46,9110,8805,1,9201,8806,2300000,9001,8807,0,9001,,,,,,,,,,,,,
+2940,"Pulkovo 1942 / CS63 zone K3",9001,4284,18447,9807,1,0,4530,8801,0.08,9110,8802,53.46,9110,8805,1,9201,8806,3300000,9001,8807,0,9001,,,,,,,,,,,,,
+2941,"Pulkovo 1942 / CS63 zone K4",9001,4284,18448,9807,1,0,4530,8801,0.08,9110,8802,56.46,9110,8805,1,9201,8806,4300000,9001,8807,0,9001,,,,,,,,,,,,,
+2942,"Porto Santo / UTM zone 28N",9001,4615,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2943,"Selvagem Grande / UTM zone 28N",9001,4616,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2944,"NAD83(CSRS) / SCoPQ zone 2",9001,4617,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2945,"NAD83(CSRS) / MTM zone 3",9001,4617,17703,9807,1,0,4496,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2946,"NAD83(CSRS) / MTM zone 4",9001,4617,17704,9807,1,0,4496,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2947,"NAD83(CSRS) / MTM zone 5",9001,4617,17705,9807,1,0,4496,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2948,"NAD83(CSRS) / MTM zone 6",9001,4617,17706,9807,1,0,4496,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2949,"NAD83(CSRS) / MTM zone 7",9001,4617,17707,9807,1,0,4496,8801,0,9110,8802,-70.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2950,"NAD83(CSRS) / MTM zone 8",9001,4617,17708,9807,1,0,4496,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2951,"NAD83(CSRS) / MTM zone 9",9001,4617,17709,9807,1,0,4496,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2952,"NAD83(CSRS) / MTM zone 10",9001,4617,17710,9807,1,0,4496,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+2953,"NAD83(CSRS) / New Brunswick Stereographic",9001,4617,19946,9809,1,0,4500,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,2500000,9001,8807,7500000,9001,,,,,,,,,,,,,
+2954,"NAD83(CSRS) / Prince Edward Isl. Stereographic (NAD83)",9001,4617,19960,9809,1,0,4496,8801,47.15,9110,8802,-63,9110,8805,0.999912,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+2955,"NAD83(CSRS) / UTM zone 11N",9001,4617,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2956,"NAD83(CSRS) / UTM zone 12N",9001,4617,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2957,"NAD83(CSRS) / UTM zone 13N",9001,4617,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2958,"NAD83(CSRS) / UTM zone 17N",9001,4617,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2959,"NAD83(CSRS) / UTM zone 18N",9001,4617,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2960,"NAD83(CSRS) / UTM zone 19N",9001,4617,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2961,"NAD83(CSRS) / UTM zone 20N",9001,4617,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2962,"NAD83(CSRS) / UTM zone 21N",9001,4617,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2963,"Lisbon 1890 (Lisbon) / Portugal Bonne",9001,4904,19979,9828,1,0,6509,8801,39.4,9110,8802,1,9110,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+2964,"NAD27 / Alaska Albers",9003,4267,15020,9822,1,0,4497,8821,50,9102,8822,-154,9102,8823,55,9102,8824,65,9102,8826,0,9003,8827,0,9003,,,,,,,,,,
+2965,"NAD83 / Indiana East (ftUS)",9003,4269,15372,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,820208.333,9003,,,,,,,,,,,,,
+2966,"NAD83 / Indiana West (ftUS)",9003,4269,15373,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,820208.333,9003,,,,,,,,,,,,,
+2967,"NAD83(HARN) / Indiana East (ftUS)",9003,4152,15372,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,820208.333,9003,,,,,,,,,,,,,
+2968,"NAD83(HARN) / Indiana West (ftUS)",9003,4152,15373,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,820208.333,9003,,,,,,,,,,,,,
+2969,"Fort Marigot / UTM zone 20N",9001,4621,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2970,"Guadeloupe 1948 / UTM zone 20N",9001,4622,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2971,"CSG67 / UTM zone 22N",9001,4623,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2972,"RGFG95 / UTM zone 22N",9001,4624,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2973,"Martinique 1938 / UTM zone 20N",9001,4625,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2975,"RGR92 / UTM zone 40S",9001,4627,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2976,"Tahiti 52 / UTM zone 6S",9001,4628,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2977,"Tahaa 54 / UTM zone 5S",9001,4629,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2978,"IGN72 Nuku Hiva / UTM zone 7S",9001,4630,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2979,"K0 1949 / UTM zone 42S",9001,4631,16142,9807,1,1,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2980,"Combani 1950 / UTM zone 38S",9001,4632,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2981,"IGN56 Lifou / UTM zone 58S",9001,4633,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2982,"IGN72 Grand Terre / UTM zone 58S",9001,4634,16158,9807,1,1,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2983,"ST87 Ouvea / UTM zone 58S",9001,4635,16158,9807,1,1,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2984,"RGNC 1991 / Lambert New Caledonia",9001,4645,19981,9802,1,1,4499,8821,-21.3,9110,8822,166,9110,8823,-20.4,9110,8824,-22.2,9110,8826,400000,9001,8827,300000,9001,,,,,,,,,,
+2985,"Petrels 1972 / Terre Adelie Polar Stereographic",9001,4636,19983,9830,1,0,1025,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,,,,,,,,
+2986,"Perroud 1950 / Terre Adelie Polar Stereographic",9001,4637,19983,9830,1,0,1025,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,,,,,,,,
+2987,"Saint Pierre et Miquelon 1950 / UTM zone 21N",9001,4638,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2988,"MOP78 / UTM zone 1S",9001,4639,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2989,"RRAF 1991 / UTM zone 20N",9001,4640,16020,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+2990,"Reunion 1947 / TM Reunion",9001,4626,19982,9807,1,1,4499,8801,-21.07,9110,8802,55.32,9110,8805,1,9201,8806,50000,9001,8807,160000,9001,,,,,,,,,,,,,
+2991,"NAD83 / Oregon LCC (m)",9001,4269,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+2992,"NAD83 / Oregon GIC Lambert (ft)",9002,4269,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,,,,,,,,
+2993,"NAD83(HARN) / Oregon LCC (m)",9001,4152,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+2994,"NAD83(HARN) / Oregon GIC Lambert (ft)",9002,4152,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,,,,,,,,
+2995,"IGN53 Mare / UTM zone 58S",9001,4641,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2996,"ST84 Ile des Pins / UTM zone 58S",9001,4642,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2997,"ST71 Belep / UTM zone 58S",9001,4643,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2998,"NEA74 Noumea / UTM zone 58S",9001,4644,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+2999,"Grand Comoros / UTM zone 38S",9001,4646,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3000,"Segara / NEIEZ",9001,4613,19905,9804,1,0,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,,,,,,,,
+3001,"Batavia / NEIEZ",9001,4211,19905,9804,1,0,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,,,,,,,,
+3002,"Makassar / NEIEZ",9001,4257,19905,9804,1,0,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,,,,,,,,
+3003,"Monte Mario / Italy zone 1",9001,4265,18121,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3004,"Monte Mario / Italy zone 2",9001,4265,18122,9807,1,0,4499,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,2520000,9001,8807,0,9001,,,,,,,,,,,,,
+3005,"NAD83 / BC Albers",9001,4269,19984,9822,1,0,4400,8821,45,9102,8822,-126,9102,8823,50,9110,8824,58.3,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+3006,SWEREF99 TM,9001,4619,17333,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3007,SWEREF99 12 00,9001,4619,17321,9807,1,0,4500,8801,0,9102,8802,12,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3008,SWEREF99 13 30,9001,4619,17322,9807,1,0,4500,8801,0,9110,8802,13.3,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3009,SWEREF99 15 00,9001,4619,17323,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3010,SWEREF99 16 30,9001,4619,17324,9807,1,0,4500,8801,0,9110,8802,16.3,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3011,SWEREF99 18 00,9001,4619,17325,9807,1,0,4500,8801,0,9102,8802,18,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3012,SWEREF99 14 15,9001,4619,17326,9807,1,0,4500,8801,0,9110,8802,14.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3013,SWEREF99 15 45,9001,4619,17327,9807,1,0,4500,8801,0,9110,8802,15.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3014,SWEREF99 17 15,9001,4619,17328,9807,1,0,4500,8801,0,9110,8802,17.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3015,SWEREF99 18 45,9001,4619,17329,9807,1,0,4500,8801,0,9110,8802,18.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3016,SWEREF99 20 15,9001,4619,17330,9807,1,0,4500,8801,0,9110,8802,20.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3017,SWEREF99 21 45,9001,4619,17331,9807,1,0,4500,8801,0,9110,8802,21.45,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3018,SWEREF99 23 15,9001,4619,17332,9807,1,0,4500,8801,0,9110,8802,23.15,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3019,RT90 7.5 gon V,9001,4124,17334,9807,1,0,4530,8801,0,9110,8802,11.18298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3020,RT90 5 gon V,9001,4124,17335,9807,1,0,4530,8801,0,9110,8802,13.33298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3021,RT90 2.5 gon V,9001,4124,19929,9807,1,0,4530,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3022,RT90 0 gon,9001,4124,17336,9807,1,0,4530,8801,0,9110,8802,18.03298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3023,RT90 2.5 gon O,9001,4124,17337,9807,1,0,4530,8801,0,9110,8802,20.18298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3024,RT90 5 gon O,9001,4124,17338,9807,1,0,4530,8801,0,9110,8802,22.33298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3025,RT38 7.5 gon V,9001,4308,17334,9807,1,0,4530,8801,0,9110,8802,11.18298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3026,RT38 5 gon V,9001,4308,17335,9807,1,0,4530,8801,0,9110,8802,13.33298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3027,RT38 2.5 gon V,9001,4308,19929,9807,1,0,4530,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3028,RT38 0 gon,9001,4308,17336,9807,1,0,4530,8801,0,9110,8802,18.03298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3029,RT38 2.5 gon O,9001,4308,17337,9807,1,0,4530,8801,0,9110,8802,20.18298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3030,RT38 5 gon O,9001,4308,17338,9807,1,0,4530,8801,0,9110,8802,22.33298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+3031,"WGS 84 / Antarctic Polar Stereographic",9001,4326,19992,9829,1,0,4490,8806,0,9001,8807,0,9001,8832,-71,9102,8833,0,9102,,,,,,,,,,,,,,,,
+3032,"WGS 84 / Australian Antarctic Polar Stereographic",9001,4326,19993,9829,1,0,4489,8806,6000000,9001,8807,6000000,9001,8832,-71,9102,8833,70,9102,,,,,,,,,,,,,,,,
+3033,"WGS 84 / Australian Antarctic Lambert",9001,4326,19994,9802,1,0,4400,8821,-50,9110,8822,70,9110,8823,-68.3,9110,8824,-74.3,9110,8826,6000000,9001,8827,6000000,9001,,,,,,,,,,
+3034,"ETRS89 / LCC Europe",9001,4258,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,,,,,,,,
+3035,"ETRS89 / LAEA Europe",9001,4258,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,,,,,,,,
+3036,"Moznet / UTM zone 36S",9001,4130,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3037,"Moznet / UTM zone 37S",9001,4130,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3038,"ETRS89 / TM26",9001,4258,16026,9807,1,1,4500,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3039,"ETRS89 / TM27",9001,4258,16027,9807,1,1,4500,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3040,"ETRS89 / UTM zone 28N (N-E)",9001,4258,16028,9807,1,0,4500,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3041,"ETRS89 / UTM zone 29N (N-E)",9001,4258,16029,9807,1,0,4500,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3042,"ETRS89 / UTM zone 30N (N-E)",9001,4258,16030,9807,1,0,4500,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3043,"ETRS89 / UTM zone 31N (N-E)",9001,4258,16031,9807,1,0,4500,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3044,"ETRS89 / UTM zone 32N (N-E)",9001,4258,16032,9807,1,0,4500,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3045,"ETRS89 / UTM zone 33N (N-E)",9001,4258,16033,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3046,"ETRS89 / UTM zone 34N (N-E)",9001,4258,16034,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3047,"ETRS89 / UTM zone 35N (N-E)",9001,4258,16035,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3048,"ETRS89 / UTM zone 36N (N-E)",9001,4258,16036,9807,1,0,4500,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3049,"ETRS89 / UTM zone 37N (N-E)",9001,4258,16037,9807,1,0,4500,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3050,"ETRS89 / TM38",9001,4258,16038,9807,1,1,4500,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3051,"ETRS89 / TM39",9001,4258,16039,9807,1,1,4500,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3052,"Reykjavik 1900 / Lambert 1900",9001,4657,19987,9826,1,0,4491,8801,65,9110,8802,-19.011965,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3053,"Hjorsey 1955 / Lambert 1955",9001,4658,19988,9826,1,0,4491,8801,65,9102,8802,-18,9102,8805,1,9201,8806,500000,9001,8807,500000,9001,,,,,,,,,,,,,
+3054,"Hjorsey 1955 / UTM zone 26N",9001,4658,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3055,"Hjorsey 1955 / UTM zone 27N",9001,4658,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3056,"Hjorsey 1955 / UTM zone 28N",9001,4658,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3057,"ISN93 / Lambert 1993",9001,4659,19989,9802,1,0,4499,8821,65,9110,8822,-19,9110,8823,64.15,9110,8824,65.45,9110,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+3058,"Helle 1954 / Jan Mayen Grid",9001,4660,19991,9807,1,0,4531,8801,0,9110,8802,-8.3,9110,8805,1,9201,8806,50000,9001,8807,-7800000,9001,,,,,,,,,,,,,
+3059,"LKS92 / Latvia TM",9001,4661,19990,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,0.9996,9201,8806,500000,9001,8807,-6000000,9001,,,,,,,,,,,,,
+3060,"IGN72 Grande Terre / UTM zone 58S",9001,4662,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3061,"Porto Santo 1995 / UTM zone 28N",9001,4663,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3062,"Azores Oriental 1995 / UTM zone 26N",9001,4664,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3063,"Azores Central 1995 / UTM zone 26N",9001,4665,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3064,"IGM95 / UTM zone 32N",9001,4670,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3065,"IGM95 / UTM zone 33N",9001,4670,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3066,"ED50 / Jordan TM",9001,4230,19995,9807,1,0,4400,8801,0,9102,8802,37,9102,8805,0.9998,9201,8806,500000,9001,8807,-3000000,9001,,,,,,,,,,,,,
+3067,"ETRS89 / TM35FIN(E,N)",9001,4258,16065,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3068,"DHDN / Soldner Berlin",9001,4314,19996,9806,1,0,4531,8801,52.25071338,9110,8802,13.37379332,9110,8806,40000,9001,8807,10000,9001,,,,,,,,,,,,,,,,
+3069,"NAD27 / Wisconsin Transverse Mercator",9001,4267,14811,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,500000,9001,8807,-4500000,9001,,,,,,,,,,,,,
+3070,"NAD83 / Wisconsin Transverse Mercator",9001,4269,14841,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,520000,9001,8807,-4480000,9001,,,,,,,,,,,,,
+3071,"NAD83(HARN) / Wisconsin Transverse Mercator",9001,4152,14841,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,520000,9001,8807,-4480000,9001,,,,,,,,,,,,,
+3072,"NAD83 / Maine CS2000 East",9001,4269,11851,9807,1,0,4499,8801,43.5,9110,8802,-67.523,9110,8805,0.99998,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+3073,"NAD83 / Maine CS2000 Central",9001,4269,11852,9807,1,1,4499,8801,43,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3074,"NAD83 / Maine CS2000 West",9001,4269,11853,9807,1,0,4499,8801,42.5,9110,8802,-70.223,9110,8805,0.99998,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+3075,"NAD83(HARN) / Maine CS2000 East",9001,4152,11851,9807,1,0,4499,8801,43.5,9110,8802,-67.523,9110,8805,0.99998,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+3076,"NAD83(HARN) / Maine CS2000 Central",9001,4152,11852,9807,1,1,4499,8801,43,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3077,"NAD83(HARN) / Maine CS2000 West",9001,4152,11853,9807,1,0,4499,8801,42.5,9110,8802,-70.223,9110,8805,0.99998,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+3078,"NAD83 / Michigan Oblique Mercator",9001,4269,12150,9812,1,0,4499,8806,2546731.496,9001,8807,-4354009.816,9001,8811,45.1833,9110,8812,-86,9110,8813,337.25556,9102,8814,337.25556,9102,8815,0.9996,9201,,,,,,,
+3079,"NAD83(HARN) / Michigan Oblique Mercator",9001,4152,12150,9812,1,0,4499,8806,2546731.496,9001,8807,-4354009.816,9001,8811,45.1833,9110,8812,-86,9110,8813,337.25556,9102,8814,337.25556,9102,8815,0.9996,9201,,,,,,,
+3080,"NAD27 / Shackleford",9002,4267,14252,9802,1,0,4495,8821,31.1,9110,8822,-100,9110,8823,27.25,9110,8824,34.55,9110,8826,3000000,9002,8827,3000000,9002,,,,,,,,,,
+3081,"NAD83 / Texas State Mapping System",9001,4269,14251,9802,1,0,4499,8821,31.1,9110,8822,-100,9110,8823,27.25,9110,8824,34.55,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+3082,"NAD83 / Texas Centric Lambert Conformal",9001,4269,14253,9802,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,5000000,9001,,,,,,,,,,
+3083,"NAD83 / Texas Centric Albers Equal Area",9001,4269,14254,9822,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,6000000,9001,,,,,,,,,,
+3084,"NAD83(HARN) / Texas Centric Lambert Conformal",9001,4152,14253,9802,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,5000000,9001,,,,,,,,,,
+3085,"NAD83(HARN) / Texas Centric Albers Equal Area",9001,4152,14254,9822,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,6000000,9001,,,,,,,,,,
+3086,"NAD83 / Florida GDL Albers",9001,4269,10934,9822,1,0,4499,8821,24,9110,8822,-84,9110,8823,24,9110,8824,31.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+3087,"NAD83(HARN) / Florida GDL Albers",9001,4152,10934,9822,1,0,4499,8821,24,9110,8822,-84,9110,8823,24,9110,8824,31.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+3088,"NAD83 / Kentucky Single Zone",9001,4269,11630,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,1500000,9001,8827,1000000,9001,,,,,,,,,,
+3089,"NAD83 / Kentucky Single Zone (ftUS)",9003,4269,15375,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,4921250,9003,8827,3280833.333,9003,,,,,,,,,,
+3090,"NAD83(HARN) / Kentucky Single Zone",9001,4152,11630,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,1500000,9001,8827,1000000,9001,,,,,,,,,,
+3091,"NAD83(HARN) / Kentucky Single Zone (ftUS)",9003,4152,15375,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,4921250,9003,8827,3280833.333,9003,,,,,,,,,,
+3092,"Tokyo / UTM zone 51N",9001,4301,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3093,"Tokyo / UTM zone 52N",9001,4301,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3094,"Tokyo / UTM zone 53N",9001,4301,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3095,"Tokyo / UTM zone 54N",9001,4301,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3096,"Tokyo / UTM zone 55N",9001,4301,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3097,"JGD2000 / UTM zone 51N",9001,4612,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3098,"JGD2000 / UTM zone 52N",9001,4612,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3099,"JGD2000 / UTM zone 53N",9001,4612,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3100,"JGD2000 / UTM zone 54N",9001,4612,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3101,"JGD2000 / UTM zone 55N",9001,4612,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3102,"American Samoa 1962 / American Samoa Lambert",9003,4169,15376,9801,1,0,4497,8801,-14.16,9110,8802,-170,9110,8805,1,9201,8806,500000,9003,8807,312234.65,9003,,,,,,,,,,,,,
+3103,"Mauritania 1999 / UTM zone 28N",9001,4681,16028,9807,1,1,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3104,"Mauritania 1999 / UTM zone 29N",9001,4681,16029,9807,1,1,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3105,"Mauritania 1999 / UTM zone 30N",9001,4681,16030,9807,1,1,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3106,"Gulshan 303 / Bangladesh Transverse Mercator",9001,4682,16490,9807,1,0,4400,8801,0,9102,8802,90,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3107,"GDA94 / SA Lambert",9001,4283,17359,9802,1,0,4400,8821,-32,9102,8822,135,9102,8823,-28,9102,8824,-36,9102,8826,1000000,9001,8827,2000000,9001,,,,,,,,,,
+3108,"ETRS89 / Guernsey Grid",9001,4258,19998,9807,1,0,4400,8801,49.3,9110,8802,-2.25,9110,8805,0.999997,9201,8806,47000,9001,8807,50000,9001,,,,,,,,,,,,,
+3109,"ETRS89 / Jersey Transverse Mercator",9001,4258,19999,9807,1,0,4400,8801,49.225,9102,8802,-2.135,9102,8805,0.9999999,9201,8806,40000,9001,8807,70000,9001,,,,,,,,,,,,,
+3110,"AGD66 / Vicgrid66",9001,4202,17360,9802,1,0,4400,8821,-37,9102,8822,145,9102,8823,-36,9102,8824,-38,9102,8826,2500000,9001,8827,4500000,9001,,,,,,,,,,
+3111,"GDA94 / Vicgrid",9001,4283,17361,9802,1,0,4400,8821,-37,9102,8822,145,9102,8823,-36,9102,8824,-38,9102,8826,2500000,9001,8827,2500000,9001,,,,,,,,,,
+3112,"GDA94 / Geoscience Australia Lambert",9001,4283,17362,9802,1,0,4400,8821,0,9102,8822,134,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3113,"GDA94 / BCSG02",9001,4283,17363,9807,1,0,4400,8801,-28,9102,8802,153,9102,8805,0.99999,9201,8806,50000,9001,8807,100000,9001,,,,,,,,,,,,,
+3114,"MAGNA-SIRGAS / Colombia Far West zone",9001,4686,18055,9807,1,0,4500,8801,4.35463215,9110,8802,-80.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+3115,"MAGNA-SIRGAS / Colombia West zone",9001,4686,18056,9807,1,0,4500,8801,4.35463215,9110,8802,-77.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+3116,"MAGNA-SIRGAS / Colombia Bogota zone",9001,4686,18057,9807,1,0,4500,8801,4.35463215,9110,8802,-74.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+3117,"MAGNA-SIRGAS / Colombia East Central zone",9001,4686,18058,9807,1,0,4500,8801,4.35463215,9110,8802,-71.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+3118,"MAGNA-SIRGAS / Colombia East zone",9001,4686,18059,9807,1,0,4500,8801,4.35463215,9110,8802,-68.04390285,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+3119,"Douala 1948 / AEF west",9001,4192,18415,9807,1,0,4400,8801,0,9110,8802,10.3,9110,8805,0.999,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+3120,"Pulkovo 1942(58) / Poland zone I",9001,4179,18280,9809,1,0,4530,8801,50.373,9110,8802,21.05,9110,8805,0.9998,9201,8806,4637000,9001,8807,5467000,9001,,,,,,,,,,,,,
+3121,"PRS92 / Philippines zone 1",9001,4683,18171,9807,1,0,4499,8801,0,9102,8802,117,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3122,"PRS92 / Philippines zone 2",9001,4683,18172,9807,1,0,4499,8801,0,9102,8802,119,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3123,"PRS92 / Philippines zone 3",9001,4683,18173,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3124,"PRS92 / Philippines zone 4",9001,4683,18174,9807,1,0,4499,8801,0,9102,8802,123,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3125,"PRS92 / Philippines zone 5",9001,4683,18175,9807,1,0,4499,8801,0,9102,8802,125,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3126,"ETRS89 / ETRS-GK19FIN",9001,4258,18183,9807,1,0,4500,8801,0,9102,8802,19,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3127,"ETRS89 / ETRS-GK20FIN",9001,4258,18184,9807,1,0,4500,8801,0,9102,8802,20,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3128,"ETRS89 / ETRS-GK21FIN",9001,4258,18185,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3129,"ETRS89 / ETRS-GK22FIN",9001,4258,18186,9807,1,0,4500,8801,0,9102,8802,22,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3130,"ETRS89 / ETRS-GK23FIN",9001,4258,18187,9807,1,0,4500,8801,0,9102,8802,23,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3131,"ETRS89 / ETRS-GK24FIN",9001,4258,18188,9807,1,0,4500,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3132,"ETRS89 / ETRS-GK25FIN",9001,4258,18189,9807,1,0,4500,8801,0,9102,8802,25,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3133,"ETRS89 / ETRS-GK26FIN",9001,4258,18190,9807,1,0,4500,8801,0,9102,8802,26,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3134,"ETRS89 / ETRS-GK27FIN",9001,4258,18195,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3135,"ETRS89 / ETRS-GK28FIN",9001,4258,18196,9807,1,0,4500,8801,0,9102,8802,28,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3136,"ETRS89 / ETRS-GK29FIN",9001,4258,18197,9807,1,0,4500,8801,0,9102,8802,29,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3137,"ETRS89 / ETRS-GK30FIN",9001,4258,18198,9807,1,0,4500,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3138,"ETRS89 / ETRS-GK31FIN",9001,4258,18199,9807,1,0,4500,8801,0,9102,8802,31,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3139,"Vanua Levu 1915 / Vanua Levu Grid",9098,4748,19878,9833,1,0,4533,8801,-16.15,9110,8802,179.2,9110,8806,1251331.8,9098,8807,1662888.5,9098,,,,,,,,,,,,,,,,
+3140,"Viti Levu 1912 / Viti Levu Grid",9098,4752,19879,9806,1,0,4533,8801,-18,9102,8802,178,9102,8806,544000,9098,8807,704000,9098,,,,,,,,,,,,,,,,
+3141,"Fiji 1956 / UTM zone 60S",9001,4721,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3142,"Fiji 1956 / UTM zone 1S",9001,4721,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3143,"Fiji 1986 / Fiji Map Grid",9001,4720,19880,9807,1,1,4400,8801,-17,9110,8802,178.45,9110,8805,0.99985,9001,8806,2000000,9001,8807,4000000,9001,,,,,,,,,,,,,
+3144,"FD54 / Faroe Lambert",9001,4741,19870,9826,1,0,1031,8801,62,9102,8802,-9,9102,8805,1,9201,8806,500000,9001,8807,500000,9001,,,,,,,,,,,,,
+3145,"ETRS89 / Faroe Lambert",9001,4258,19870,9826,1,0,1031,8801,62,9102,8802,-9,9102,8805,1,9201,8806,500000,9001,8807,500000,9001,,,,,,,,,,,,,
+3146,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 6",9001,4284,16266,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+3147,"Pulkovo 1942 / 3-degree Gauss-Kruger CM 18E",9001,4284,16366,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3148,"Indian 1960 / UTM zone 48N",9001,4131,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3149,"Indian 1960 / UTM zone 49N",9001,4131,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3150,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 6",9001,4200,16266,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+3151,"Pulkovo 1995 / 3-degree Gauss-Kruger CM 18E",9001,4200,16366,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3152,ST74,9001,4619,19876,9807,1,0,4531,8801,0,9110,8802,18.0328044,9110,8805,0.99999425,9201,8806,100178.1808,9001,8807,-6500614.7836,9001,,,,,,,,,,,,,
+3153,"NAD83(CSRS) / BC Albers",9001,4617,19984,9822,1,0,4400,8821,45,9102,8822,-126,9102,8823,50,9110,8824,58.3,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+3154,"NAD83(CSRS) / UTM zone 7N",9001,4617,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3155,"NAD83(CSRS) / UTM zone 8N",9001,4617,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3156,"NAD83(CSRS) / UTM zone 9N",9001,4617,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3157,"NAD83(CSRS) / UTM zone 10N",9001,4617,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3158,"NAD83(CSRS) / UTM zone 14N",9001,4617,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3159,"NAD83(CSRS) / UTM zone 15N",9001,4617,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3160,"NAD83(CSRS) / UTM zone 16N",9001,4617,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3161,"NAD83 / Ontario MNR Lambert",9001,4269,19875,9802,1,0,4400,8821,0,9102,8822,-85,9102,8823,44.5,9102,8824,53.5,9102,8826,930000,9001,8827,6430000,9001,,,,,,,,,,
+3162,"NAD83(CSRS) / Ontario MNR Lambert",9001,4617,19875,9802,1,0,4400,8821,0,9102,8822,-85,9102,8823,44.5,9102,8824,53.5,9102,8826,930000,9001,8827,6430000,9001,,,,,,,,,,
+3163,"RGNC91-93 / Lambert New Caledonia",9001,4749,19981,9802,1,0,4499,8821,-21.3,9110,8822,166,9110,8823,-20.4,9110,8824,-22.2,9110,8826,400000,9001,8827,300000,9001,,,,,,,,,,
+3164,"ST87 Ouvea / UTM zone 58S",9001,4750,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3165,"NEA74 Noumea / Noumea Lambert",9001,4644,19873,9802,1,0,4499,8821,-22.16108903,9110,8822,166.26327327,9110,8823,-22.14408903,9110,8824,-22.17408903,9110,8826,0.66,9001,8827,1.02,9001,,,,,,,,,,
+3166,"NEA74 Noumea / Noumea Lambert 2",9001,4644,19874,9802,1,0,4499,8821,-22.1611,9110,8822,166.2633,9110,8823,-22.1441,9110,8824,-22.1741,9110,8826,8.313,9001,8827,-2.354,9001,,,,,,,,,,
+3167,"Kertau (RSO) / RSO Malaya (ch)",9301,4751,19871,9812,1,0,4410,8806,40000,9301,8807,0,9301,8811,4,9110,8812,102.15,9110,8813,323.01328458,9110,8814,323.07483685,9110,8815,0.99984,9201,,,,,,,
+3168,"Kertau (RSO) / RSO Malaya (m)",9001,4751,19872,9812,1,0,4400,8806,804670.24,9001,8807,0,9001,8811,4,9110,8812,102.15,9110,8813,323.01328458,9110,8814,323.07483685,9110,8815,0.99984,9201,,,,,,,
+3169,"RGNC91-93 / UTM zone 57S",9001,4749,16157,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3170,"RGNC91-93 / UTM zone 58S",9001,4749,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3171,"RGNC91-93 / UTM zone 59S",9001,4749,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3172,"IGN53 Mare / UTM zone 59S",9001,4641,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3173,"fk89 / Faroe Lambert FK89",9001,4753,19877,9826,1,0,1031,8801,62,9102,8802,-9,9102,8805,1,9201,8806,700000,9001,8807,700000,9001,,,,,,,,,,,,,
+3174,"NAD83 / Great Lakes Albers",9001,4269,15397,9822,1,0,4499,8821,45.568977,9102,8822,-84.455955,9102,8823,42.122774,9102,8824,49.01518,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+3175,"NAD83 / Great Lakes and St Lawrence Albers",9001,4269,15398,9822,1,0,4499,8821,45.568977,9102,8822,-83.248627,9102,8823,42.122774,9102,8824,49.01518,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+3176,"Indian 1960 / TM 106 NE",9001,4131,16506,9807,1,0,4400,8801,0,9102,8802,106,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3177,"LGD2006 / Libya TM",9001,4754,18319,9807,1,0,4499,8801,0,9102,8802,17,9102,8805,0.9965,9201,8806,1000000,9001,8807,0,9001,,,,,,,,,,,,,
+3178,"GR96 / UTM zone 18N",9001,4747,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3179,"GR96 / UTM zone 19N",9001,4747,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3180,"GR96 / UTM zone 20N",9001,4747,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3181,"GR96 / UTM zone 21N",9001,4747,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3182,"GR96 / UTM zone 22N",9001,4747,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3183,"GR96 / UTM zone 23N",9001,4747,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3184,"GR96 / UTM zone 24N",9001,4747,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3185,"GR96 / UTM zone 25N",9001,4747,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3186,"GR96 / UTM zone 26N",9001,4747,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3187,"GR96 / UTM zone 27N",9001,4747,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3188,"GR96 / UTM zone 28N",9001,4747,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3189,"GR96 / UTM zone 29N",9001,4747,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3190,"LGD2006 / Libya TM zone 5",9001,4754,18310,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3191,"LGD2006 / Libya TM zone 6",9001,4754,18311,9807,1,0,4499,8801,0,9102,8802,11,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3192,"LGD2006 / Libya TM zone 7",9001,4754,18312,9807,1,0,4499,8801,0,9102,8802,13,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3193,"LGD2006 / Libya TM zone 8",9001,4754,18313,9807,1,0,4499,8801,0,9102,8802,15,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3194,"LGD2006 / Libya TM zone 9",9001,4754,18314,9807,1,0,4499,8801,0,9102,8802,17,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3195,"LGD2006 / Libya TM zone 10",9001,4754,18315,9807,1,0,4499,8801,0,9102,8802,19,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3196,"LGD2006 / Libya TM zone 11",9001,4754,18316,9807,1,0,4499,8801,0,9102,8802,21,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3197,"LGD2006 / Libya TM zone 12",9001,4754,18317,9807,1,0,4499,8801,0,9102,8802,23,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3198,"LGD2006 / Libya TM zone 13",9001,4754,18318,9807,1,0,4499,8801,0,9102,8802,25,9102,8805,0.99995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3199,"LGD2006 / UTM zone 32N",9001,4754,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3200,"FD58 / Iraq zone",9001,4132,19906,9801,1,0,4400,8801,32.3,9110,8802,45,9110,8805,0.9987864078,9201,8806,1500000,9001,8807,1166200,9001,,,,,,,,,,,,,
+3201,"LGD2006 / UTM zone 33N",9001,4754,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3202,"LGD2006 / UTM zone 34N",9001,4754,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3203,"LGD2006 / UTM zone 35N",9001,4754,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3204,"WGS 84 / SCAR IMW SP19-20",9001,4326,17204,9802,1,0,4400,8821,-90,9102,8822,-66,9102,8823,-60.4,9110,8824,-63.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3205,"WGS 84 / SCAR IMW SP21-22",9001,4326,17205,9802,1,0,4400,8821,-90,9102,8822,-54,9102,8823,-60.4,9110,8824,-63.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3206,"WGS 84 / SCAR IMW SP23-24",9001,4326,17206,9802,1,0,4400,8821,-90,9102,8822,-42,9102,8823,-60.4,9110,8824,-63.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3207,"WGS 84 / SCAR IMW SQ01-02",9001,4326,17207,9802,1,0,4400,8821,-90,9102,8822,-174,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3208,"WGS 84 / SCAR IMW SQ19-20",9001,4326,17208,9802,1,0,4400,8821,-90,9102,8822,-66,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3209,"WGS 84 / SCAR IMW SQ21-22",9001,4326,17209,9802,1,0,4400,8821,-90,9102,8822,-54,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3210,"WGS 84 / SCAR IMW SQ37-38",9001,4326,17210,9802,1,0,4400,8821,-90,9102,8822,42,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3211,"WGS 84 / SCAR IMW SQ39-40",9001,4326,17211,9802,1,0,4400,8821,-90,9102,8822,54,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3212,"WGS 84 / SCAR IMW SQ41-42",9001,4326,17212,9802,1,0,4400,8821,-90,9102,8822,66,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3213,"WGS 84 / SCAR IMW SQ43-44",9001,4326,17213,9802,1,0,4400,8821,-90,9102,8822,78,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3214,"WGS 84 / SCAR IMW SQ45-46",9001,4326,17214,9802,1,0,4400,8821,-90,9102,8822,90,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3215,"WGS 84 / SCAR IMW SQ47-48",9001,4326,17215,9802,1,0,4400,8821,-90,9102,8822,102,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3216,"WGS 84 / SCAR IMW SQ49-50",9001,4326,17216,9802,1,0,4400,8821,-90,9102,8822,114,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3217,"WGS 84 / SCAR IMW SQ51-52",9001,4326,17217,9802,1,0,4400,8821,-90,9102,8822,126,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3218,"WGS 84 / SCAR IMW SQ53-54",9001,4326,17218,9802,1,0,4400,8821,-90,9102,8822,138,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3219,"WGS 84 / SCAR IMW SQ55-56",9001,4326,17219,9802,1,0,4400,8821,-90,9102,8822,150,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3220,"WGS 84 / SCAR IMW SQ57-58",9001,4326,17220,9802,1,0,4400,8821,-90,9102,8822,162,9102,8823,-64.4,9110,8824,-67.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3221,"WGS 84 / SCAR IMW SR13-14",9001,4326,17221,9802,1,0,4400,8821,-90,9102,8822,-102,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3222,"WGS 84 / SCAR IMW SR15-16",9001,4326,17222,9802,1,0,4400,8821,-90,9102,8822,-90,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3223,"WGS 84 / SCAR IMW SR17-18",9001,4326,17223,9802,1,0,4400,8821,-90,9102,8822,-78,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3224,"WGS 84 / SCAR IMW SR19-20",9001,4326,17224,9802,1,0,4400,8821,-90,9102,8822,-66,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3225,"WGS 84 / SCAR IMW SR27-28",9001,4326,17225,9802,1,0,4400,8821,-90,9102,8822,-18,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3226,"WGS 84 / SCAR IMW SR29-30",9001,4326,17226,9802,1,0,4400,8821,-90,9102,8822,-6,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3227,"WGS 84 / SCAR IMW SR31-32",9001,4326,17227,9802,1,0,4400,8821,-90,9102,8822,6,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3228,"WGS 84 / SCAR IMW SR33-34",9001,4326,17228,9802,1,0,4400,8821,-90,9102,8822,18,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3229,"WGS 84 / SCAR IMW SR35-36",9001,4326,17229,9802,1,0,4400,8821,-90,9102,8822,30,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3230,"WGS 84 / SCAR IMW SR37-38",9001,4326,17230,9802,1,0,4400,8821,-90,9102,8822,42,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3231,"WGS 84 / SCAR IMW SR39-40",9001,4326,17231,9802,1,0,4400,8821,-90,9102,8822,54,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3232,"WGS 84 / SCAR IMW SR41-42",9001,4326,17232,9802,1,0,4400,8821,-90,9102,8822,66,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3233,"WGS 84 / SCAR IMW SR43-44",9001,4326,17233,9802,1,0,4400,8821,-90,9102,8822,78,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3234,"WGS 84 / SCAR IMW SR45-46",9001,4326,17234,9802,1,0,4400,8821,-90,9102,8822,90,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3235,"WGS 84 / SCAR IMW SR47-48",9001,4326,17235,9802,1,0,4400,8821,-90,9102,8822,102,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3236,"WGS 84 / SCAR IMW SR49-50",9001,4326,17236,9802,1,0,4400,8821,-90,9102,8822,114,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3237,"WGS 84 / SCAR IMW SR51-52",9001,4326,17237,9802,1,0,4400,8821,-90,9102,8822,126,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3238,"WGS 84 / SCAR IMW SR53-54",9001,4326,17238,9802,1,0,4400,8821,-90,9102,8822,138,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3239,"WGS 84 / SCAR IMW SR55-56",9001,4326,17239,9802,1,0,4400,8821,-90,9102,8822,150,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3240,"WGS 84 / SCAR IMW SR57-58",9001,4326,17240,9802,1,0,4400,8821,-90,9102,8822,162,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3241,"WGS 84 / SCAR IMW SR59-60",9001,4326,17241,9802,1,0,4400,8821,-90,9102,8822,174,9102,8823,-68.4,9110,8824,-71.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3242,"WGS 84 / SCAR IMW SS04-06",9001,4326,17242,9802,1,0,4400,8821,-90,9102,8822,-153,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3243,"WGS 84 / SCAR IMW SS07-09",9001,4326,17243,9802,1,0,4400,8821,-90,9102,8822,-135,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3244,"WGS 84 / SCAR IMW SS10-12",9001,4326,17244,9802,1,0,4400,8821,-90,9102,8822,-117,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3245,"WGS 84 / SCAR IMW SS13-15",9001,4326,17245,9802,1,0,4400,8821,-90,9102,8822,-99,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3246,"WGS 84 / SCAR IMW SS16-18",9001,4326,17246,9802,1,0,4400,8821,-90,9102,8822,-81,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3247,"WGS 84 / SCAR IMW SS19-21",9001,4326,17247,9802,1,0,4400,8821,-90,9102,8822,-63,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3248,"WGS 84 / SCAR IMW SS25-27",9001,4326,17248,9802,1,0,4400,8821,-90,9102,8822,-27,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3249,"WGS 84 / SCAR IMW SS28-30",9001,4326,17249,9802,1,0,4400,8821,-90,9102,8822,-9,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3250,"WGS 84 / SCAR IMW SS31-33",9001,4326,17250,9802,1,0,4400,8821,-90,9102,8822,9,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3251,"WGS 84 / SCAR IMW SS34-36",9001,4326,17251,9802,1,0,4400,8821,-90,9102,8822,27,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3252,"WGS 84 / SCAR IMW SS37-39",9001,4326,17252,9802,1,0,4400,8821,-90,9102,8822,45,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3253,"WGS 84 / SCAR IMW SS40-42",9001,4326,17253,9802,1,0,4400,8821,-90,9102,8822,63,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3254,"WGS 84 / SCAR IMW SS43-45",9001,4326,17254,9802,1,0,4400,8821,-90,9102,8822,81,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3255,"WGS 84 / SCAR IMW SS46-48",9001,4326,17255,9802,1,0,4400,8821,-90,9102,8822,99,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3256,"WGS 84 / SCAR IMW SS49-51",9001,4326,17256,9802,1,0,4400,8821,-90,9102,8822,117,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3257,"WGS 84 / SCAR IMW SS52-54",9001,4326,17257,9802,1,0,4400,8821,-90,9102,8822,135,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3258,"WGS 84 / SCAR IMW SS55-57",9001,4326,17258,9802,1,0,4400,8821,-90,9102,8822,153,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3259,"WGS 84 / SCAR IMW SS58-60",9001,4326,17259,9802,1,0,4400,8821,-90,9102,8822,171,9102,8823,-72.4,9110,8824,-75.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3260,"WGS 84 / SCAR IMW ST01-04",9001,4326,17260,9802,1,0,4400,8821,-90,9102,8822,-168,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3261,"WGS 84 / SCAR IMW ST05-08",9001,4326,17261,9802,1,0,4400,8821,-90,9102,8822,-144,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3262,"WGS 84 / SCAR IMW ST09-12",9001,4326,17262,9802,1,0,4400,8821,-90,9102,8822,-120,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3263,"WGS 84 / SCAR IMW ST13-16",9001,4326,17263,9802,1,0,4400,8821,-90,9102,8822,-96,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3264,"WGS 84 / SCAR IMW ST17-20",9001,4326,17264,9802,1,0,4400,8821,-90,9102,8822,-72,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3265,"WGS 84 / SCAR IMW ST21-24",9001,4326,17265,9802,1,0,4400,8821,-90,9102,8822,-48,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3266,"WGS 84 / SCAR IMW ST25-28",9001,4326,17266,9802,1,0,4400,8821,-90,9102,8822,-24,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3267,"WGS 84 / SCAR IMW ST29-32",9001,4326,17267,9802,1,0,4400,8821,-90,9102,8822,0,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3268,"WGS 84 / SCAR IMW ST33-36",9001,4326,17268,9802,1,0,4400,8821,-90,9102,8822,24,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3269,"WGS 84 / SCAR IMW ST37-40",9001,4326,17269,9802,1,0,4400,8821,-90,9102,8822,48,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3270,"WGS 84 / SCAR IMW ST41-44",9001,4326,17270,9802,1,0,4400,8821,-90,9102,8822,72,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3271,"WGS 84 / SCAR IMW ST45-48",9001,4326,17271,9802,1,0,4400,8821,-90,9102,8822,96,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3272,"WGS 84 / SCAR IMW ST49-52",9001,4326,17272,9802,1,0,4400,8821,-90,9102,8822,120,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3273,"WGS 84 / SCAR IMW ST53-56",9001,4326,17273,9802,1,0,4400,8821,-90,9102,8822,144,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3274,"WGS 84 / SCAR IMW ST57-60",9001,4326,17274,9802,1,0,4400,8821,-90,9102,8822,168,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3275,"WGS 84 / SCAR IMW SU01-05",9001,4326,17275,9829,1,0,4471,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-165,9102,,,,,,,,,,,,,,,,
+3276,"WGS 84 / SCAR IMW SU06-10",9001,4326,17276,9829,1,0,4473,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-135,9102,,,,,,,,,,,,,,,,
+3277,"WGS 84 / SCAR IMW SU11-15",9001,4326,17277,9829,1,0,4474,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-105,9102,,,,,,,,,,,,,,,,
+3278,"WGS 84 / SCAR IMW SU16-20",9001,4326,17278,9829,1,0,4476,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-75,9102,,,,,,,,,,,,,,,,
+3279,"WGS 84 / SCAR IMW SU21-25",9001,4326,17279,9829,1,0,4477,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-45,9102,,,,,,,,,,,,,,,,
+3280,"WGS 84 / SCAR IMW SU26-30",9001,4326,17280,9829,1,0,4479,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-15,9102,,,,,,,,,,,,,,,,
+3281,"WGS 84 / SCAR IMW SU31-35",9001,4326,17281,9829,1,0,4480,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,15,9102,,,,,,,,,,,,,,,,
+3282,"WGS 84 / SCAR IMW SU36-40",9001,4326,17282,9829,1,0,4482,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,45,9102,,,,,,,,,,,,,,,,
+3283,"WGS 84 / SCAR IMW SU41-45",9001,4326,17283,9829,1,0,4483,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,75,9102,,,,,,,,,,,,,,,,
+3284,"WGS 84 / SCAR IMW SU46-50",9001,4326,17284,9829,1,0,4485,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,105,9102,,,,,,,,,,,,,,,,
+3285,"WGS 84 / SCAR IMW SU51-55",9001,4326,17285,9829,1,0,4486,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,135,9102,,,,,,,,,,,,,,,,
+3286,"WGS 84 / SCAR IMW SU56-60",9001,4326,17286,9829,1,0,4488,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,165,9102,,,,,,,,,,,,,,,,
+3287,"WGS 84 / SCAR IMW SV01-10",9001,4326,17287,9829,1,0,4472,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-150,9102,,,,,,,,,,,,,,,,
+3288,"WGS 84 / SCAR IMW SV11-20",9001,4326,17288,9829,1,0,4475,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-90,9102,,,,,,,,,,,,,,,,
+3289,"WGS 84 / SCAR IMW SV21-30",9001,4326,17289,9829,1,0,4478,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,-30,9102,,,,,,,,,,,,,,,,
+3290,"WGS 84 / SCAR IMW SV31-40",9001,4326,17290,9829,1,0,4481,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,30,9102,,,,,,,,,,,,,,,,
+3291,"WGS 84 / SCAR IMW SV41-50",9001,4326,17291,9829,1,0,4484,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,90,9102,,,,,,,,,,,,,,,,
+3292,"WGS 84 / SCAR IMW SV51-60",9001,4326,17292,9829,1,0,4487,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,150,9102,,,,,,,,,,,,,,,,
+3293,"WGS 84 / SCAR IMW SW01-60",9001,4326,17293,9829,1,0,4490,8806,0,9001,8807,0,9001,8832,-80.1419,9110,8833,0,9102,,,,,,,,,,,,,,,,
+3294,"WGS 84 / USGS Transantarctic Mountains",9001,4326,17294,9802,1,0,4400,8821,-78,9102,8822,162,9102,8823,-76.4,9110,8824,-79.2,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3295,"Guam 1963 / Yap Islands",9001,4675,15399,9832,1,0,4499,8801,9.324815,9110,8802,138.100748,9110,8806,40000,9001,8807,60000,9001,,,,,,,,,,,,,,,,
+3296,"RGPF / UTM zone 5S",9001,4687,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3297,"RGPF / UTM zone 6S",9001,4687,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3298,"RGPF / UTM zone 7S",9001,4687,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3299,"RGPF / UTM zone 8S",9001,4687,16108,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3300,Estonian Coordinate System of 1992,9001,4133,19938,9802,1,0,4530,8821,57.310319415,9110,8822,24,9110,8823,59.2,9110,8824,58,9110,8826,500000,9001,8827,6375000,9001,,,,,,,,,,
+3301,Estonian Coordinate System of 1997,9001,4180,19938,9802,1,0,4530,8821,57.310319415,9110,8822,24,9110,8823,59.2,9110,8824,58,9110,8826,500000,9001,8827,6375000,9001,,,,,,,,,,
+3302,"IGN63 Hiva Oa / UTM zone 7S",9001,4689,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3303,"Fatu Iva 72 / UTM zone 7S",9001,4688,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3304,"Tahiti 79 / UTM zone 6S",9001,4690,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3305,"Moorea 87 / UTM zone 6S",9001,4691,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3306,"Maupiti 83 / UTM zone 5S",9001,4692,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3307,"Nakhl-e Ghanem / UTM zone 39N",9001,4693,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3308,"GDA94 / NSW Lambert",9001,4283,17364,9802,1,0,4400,8821,-33.25,9102,8822,147,9102,8823,-30.75,9102,8824,-35.75,9102,8826,9300000,9001,8827,4500000,9001,,,,,,,,,,
+3309,"NAD27 / California Albers",9001,4267,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,,,,,,,,
+3310,"NAD83 / California Albers",9001,4269,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,,,,,,,,
+3311,"NAD83(HARN) / California Albers",9001,4152,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,,,,,,,,
+3312,"CSG67 / UTM zone 21N",9001,4623,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3313,"RGFG95 / UTM zone 21N",9001,4624,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3314,"Katanga 1955 / Katanga Lambert",9001,4695,17401,9802,1,1,4400,8821,0,9102,8822,26,9102,8823,-6.5,9102,8824,-11.5,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3315,"Katanga 1955 / Katanga TM",9001,4695,17402,9807,1,1,4400,8801,-9,9102,8802,26,9102,8805,0.9998,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3316,"Kasai 1953 / Congo TM zone 22",9001,4696,17422,9807,1,0,4400,8801,0,9102,8802,22,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3317,"Kasai 1953 / Congo TM zone 24",9001,4696,17424,9807,1,0,4400,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3318,"IGC 1962 / Congo TM zone 12",9001,4697,17412,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3319,"IGC 1962 / Congo TM zone 14",9001,4697,17414,9807,1,0,4400,8801,0,9102,8802,14,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3320,"IGC 1962 / Congo TM zone 16",9001,4697,17416,9807,1,0,4400,8801,0,9102,8802,16,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3321,"IGC 1962 / Congo TM zone 18",9001,4697,17418,9807,1,0,4400,8801,0,9102,8802,18,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3322,"IGC 1962 / Congo TM zone 20",9001,4697,17420,9807,1,0,4400,8801,0,9102,8802,20,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3323,"IGC 1962 / Congo TM zone 22",9001,4697,17422,9807,1,0,4400,8801,0,9102,8802,22,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3324,"IGC 1962 / Congo TM zone 24",9001,4697,17424,9807,1,0,4400,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3325,"IGC 1962 / Congo TM zone 26",9001,4697,17426,9807,1,0,4400,8801,0,9102,8802,26,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3326,"IGC 1962 / Congo TM zone 28",9001,4697,17428,9807,1,0,4400,8801,0,9102,8802,28,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3327,"IGC 1962 / Congo TM zone 30",9001,4697,17430,9807,1,0,4400,8801,0,9102,8802,30,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3328,"Pulkovo 1942(58) / GUGiK-80",9001,4179,18286,9809,1,0,4530,8801,52.1,9110,8802,19.1,9110,8805,0.999714,9201,8806,500000,9001,8807,500000,9001,,,,,,,,,,,,,
+3329,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 5",9001,4179,16265,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+3330,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 6",9001,4179,16266,9807,1,0,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+3331,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 7",9001,4179,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+3332,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 8",9001,4179,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+3333,"Pulkovo 1942(58) / Gauss-Kruger zone 3",9001,4179,16203,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+3334,"Pulkovo 1942(58) / Gauss-Kruger zone 4",9001,4179,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+3335,"Pulkovo 1942(58) / Gauss-Kruger zone 5",9001,4179,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+3336,"IGN 1962 Kerguelen / UTM zone 42S",9001,4698,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3337,"Le Pouce 1934 / Mauritius Grid",9001,4699,19899,9801,1,0,4400,8801,-20.114225,9110,8802,57.311858,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+3338,"NAD83 / Alaska Albers",9001,4269,15021,9822,1,0,4499,8821,50,9102,8822,-154,9102,8823,55,9102,8824,65,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3339,"IGCB 1955 / Congo TM zone 12",9001,4701,17412,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3340,"IGCB 1955 / Congo TM zone 14",9001,4701,17414,9807,1,0,4400,8801,0,9102,8802,14,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3341,"IGCB 1955 / Congo TM zone 16",9001,4701,17416,9807,1,0,4400,8801,0,9102,8802,16,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3342,"IGCB 1955 / UTM zone 33S",9001,4701,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3343,"Mauritania 1999 / UTM zone 28N",9001,4702,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3344,"Mauritania 1999 / UTM zone 29N",9001,4702,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3345,"Mauritania 1999 / UTM zone 30N",9001,4702,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3346,"LKS94 / Lithuania TM",9001,4669,19934,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,0.9998,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3347,"NAD83 / Statistics Canada Lambert",9001,4269,19897,9802,1,0,4400,8821,63.390675,9102,8822,-91.52,9110,8823,49,9102,8824,77,9102,8826,6200000,9001,8827,3000000,9001,,,,,,,,,,
+3348,"NAD83(CSRS) / Statistics Canada Lambert",9001,4617,19897,9802,1,0,4400,8821,63.390675,9102,8822,-91.52,9110,8823,49,9102,8824,77,9102,8826,6200000,9001,8827,3000000,9001,,,,,,,,,,
+3349,"WGS 84 / PDC Mercator",9001,4326,19898,9804,1,1,4400,8801,0,9102,8802,-150,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3350,"Pulkovo 1942 / CS63 zone C0",9001,4284,18450,9807,1,0,4530,8801,0.06,9110,8802,21.57,9110,8805,1,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+3351,"Pulkovo 1942 / CS63 zone C1",9001,4284,18451,9807,1,0,4530,8801,0.06,9110,8802,24.57,9110,8805,1,9201,8806,1250000,9001,8807,0,9001,,,,,,,,,,,,,
+3352,"Pulkovo 1942 / CS63 zone C2",9001,4284,18452,9807,1,0,4530,8801,0.06,9110,8802,27.57,9110,8805,1,9201,8806,2250000,9001,8807,0,9001,,,,,,,,,,,,,
+3353,"Mhast (onshore) / UTM zone 32S",9001,4704,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3354,"Mhast (offshore) / UTM zone 32S",9001,4705,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3355,"Egypt Gulf of Suez S-650 TL / Red Belt",9001,4706,18072,9807,1,0,4400,8801,30,9102,8802,31,9102,8805,1,9201,8806,615000,9001,8807,810000,9001,,,,,,,,,,,,,
+3356,"Grand Cayman 1959 / UTM zone 17N",9001,4723,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3357,"Little Cayman 1961 / UTM zone 17N",9001,4726,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3358,"NAD83(HARN) / North Carolina",9001,4152,13230,9802,1,0,4499,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,609601.22,9001,8827,0,9001,,,,,,,,,,
+3359,"NAD83(HARN) / North Carolina (ftUS)",9002,4152,15346,9802,1,1,4495,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+3360,"NAD83(HARN) / South Carolina",9001,4152,13930,9802,1,0,4499,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,609600,9001,8827,0,9001,,,,,,,,,,
+3361,"NAD83(HARN) / South Carolina (ft)",9002,4152,15355,9802,1,0,4495,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,2000000,9002,8827,0,9002,,,,,,,,,,
+3362,"NAD83(HARN) / Pennsylvania North",9001,4152,13731,9802,1,0,4499,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3363,"NAD83(HARN) / Pennsylvania North (ftUS)",9003,4152,15353,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3364,"NAD83(HARN) / Pennsylvania South",9001,4152,13732,9802,1,0,4499,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3365,"NAD83(HARN) / Pennsylvania South (ftUS)",9003,4152,15354,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3366,Hong Kong 1963 Grid System,9001,4738,19896,9806,1,1,4500,8801,22.184368,9110,8802,114.10428,9110,8806,132033.92,9005,8807,62565.96,9005,,,,,,,,,,,,,,,,
+3367,"IGN Astro 1960 / UTM zone 28N",9001,4700,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3368,"IGN Astro 1960 / UTM zone 29N",9001,4700,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3369,"IGN Astro 1960 / UTM zone 30N",9001,4700,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3370,"NAD27 / UTM zone 59N",9001,4267,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3371,"NAD27 / UTM zone 60N",9001,4267,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3372,"NAD83 / UTM zone 59N",9001,4269,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3373,"NAD83 / UTM zone 60N",9001,4269,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3374,"FD54 / UTM zone 29N",9001,4741,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3375,"GDM2000 / Peninsula RSO",9001,4742,19895,9812,1,0,4400,8806,804671,9001,8807,0,9001,8811,4,9110,8812,102.15,9110,8813,323.013286728,9110,8814,323.07483685,9110,8815,0.99984,9201,,,,,,,
+3376,"GDM2000 / East Malaysia BRSO",9001,4742,19894,9812,1,0,4400,8806,0,9001,8807,0,9001,8811,4,9110,8812,115,9110,8813,53.185691582,9110,8814,53.07483685,9110,8815,0.99984,9201,,,,,,,
+3377,"GDM2000 / Johor Grid",9001,4742,19893,9806,1,0,4400,8801,2.071804708,9110,8802,103.254057045,9110,8806,-14810.562,9001,8807,8758.32,9001,,,,,,,,,,,,,,,,
+3378,"GDM2000 / Sembilan and Melaka Grid",9001,4742,19892,9806,1,0,4400,8801,2.405645149,9110,8802,101.582965815,9110,8806,3673.785,9001,8807,-4240.573,9001,,,,,,,,,,,,,,,,
+3379,"GDM2000 / Pahang Grid",9001,4742,19891,9806,1,0,4400,8801,3.460979712,9110,8802,102.220587634,9110,8806,-7368.228,9001,8807,6485.858,9001,,,,,,,,,,,,,,,,
+3380,"GDM2000 / Selangor Grid",9001,4742,19890,9806,1,0,4400,8801,3.410473658,9110,8802,101.232078849,9110,8806,-34836.161,9001,8807,56464.049,9001,,,,,,,,,,,,,,,,
+3381,"GDM2000 / Terengganu Grid",9001,4742,19889,9806,1,0,4400,8801,4.583462672,9110,8802,103.041299225,9110,8806,19594.245,9001,8807,3371.895,9001,,,,,,,,,,,,,,,,
+3382,"GDM2000 / Pinang Grid",9001,4742,19888,9806,1,0,4400,8801,5.251746315,9110,8802,100.203975707,9110,8806,-23.414,9001,8807,62.283,9001,,,,,,,,,,,,,,,,
+3383,"GDM2000 / Kedah and Perlis Grid",9001,4742,19887,9806,1,0,4400,8801,5.575282177,9110,8802,100.3810936,9110,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3384,"GDM2000 / Perak Grid",9001,4742,19886,9806,1,0,4400,8801,4.513262688,9110,8802,100.485547811,9110,8806,-1.769,9001,8807,133454.779,9001,,,,,,,,,,,,,,,,
+3385,"GDM2000 / Kelantan Grid",9001,4742,19885,9806,1,0,4400,8801,5.582115717,9110,8802,102.174287001,9110,8806,13227.851,9001,8807,8739.894,9001,,,,,,,,,,,,,,,,
+3386,"KKJ / Finland zone 0",9001,4123,18180,9807,1,0,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3387,"KKJ / Finland zone 5",9001,4123,18205,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+3388,"Pulkovo 1942 / Caspian Sea Mercator",9001,4284,19884,9805,1,0,4534,8802,51,9102,8806,0,9001,8807,0,9001,8823,42,9102,,,,,,,,,,,,,,,,
+3389,"Pulkovo 1942 / 3-degree Gauss-Kruger zone 60",9001,4284,16099,9807,1,0,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,60500000,9001,8807,0,9001,,,,,,,,,,,,,
+3390,"Pulkovo 1995 / 3-degree Gauss-Kruger zone 60",9001,4200,16099,9807,1,0,4530,8801,0,9102,8802,180,9102,8805,1,9201,8806,60500000,9001,8807,0,9001,,,,,,,,,,,,,
+3391,"Karbala 1979 / UTM zone 37N",9001,4743,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3392,"Karbala 1979 / UTM zone 38N",9001,4743,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3393,"Karbala 1979 / UTM zone 39N",9001,4743,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3394,"Nahrwan 1934 / Iraq zone",9001,4744,19906,9801,1,0,4400,8801,32.3,9110,8802,45,9110,8805,0.9987864078,9201,8806,1500000,9001,8807,1166200,9001,,,,,,,,,,,,,
+3395,"WGS 84 / World Mercator",9001,4326,19883,9804,1,0,4400,8801,0,9102,8802,0,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3396,"PD/83 / 3-degree Gauss-Kruger zone 3",9001,4746,16263,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+3397,"PD/83 / 3-degree Gauss-Kruger zone 4",9001,4746,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+3398,"RD/83 / 3-degree Gauss-Kruger zone 4",9001,4745,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+3399,"RD/83 / 3-degree Gauss-Kruger zone 5",9001,4745,16265,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+3400,"NAD83 / Alberta 10-TM (Forest)",9001,4269,19881,9807,1,0,4400,8801,0,9102,8802,-115,9102,8805,0.9992,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3401,"NAD83 / Alberta 10-TM (Resource)",9001,4269,19882,9807,1,0,4400,8801,0,9102,8802,-115,9102,8805,0.9992,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3402,"NAD83(CSRS) / Alberta 10-TM (Forest)",9001,4617,19881,9807,1,0,4400,8801,0,9102,8802,-115,9102,8805,0.9992,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3403,"NAD83(CSRS) / Alberta 10-TM (Resource)",9001,4617,19882,9807,1,0,4400,8801,0,9102,8802,-115,9102,8805,0.9992,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3404,"NAD83(HARN) / North Carolina (ftUS)",9003,4152,15346,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+3405,"VN-2000 / UTM zone 48N",9001,4756,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3406,"VN-2000 / UTM zone 49N",9001,4756,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3407,Hong Kong 1963 Grid System,9005,4738,19896,9806,1,0,4502,8801,22.184368,9110,8802,114.10428,9110,8806,132033.92,9005,8807,62565.96,9005,,,,,,,,,,,,,,,,
+3408,NSIDC EASE-Grid North,9001,4053,3897,1027,1,0,4469,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3409,NSIDC EASE-Grid South,9001,4053,3898,1027,1,0,4470,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3410,NSIDC EASE-Grid Global,9001,4053,19869,9834,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,,,,,,,,
+3411,NSIDC Sea Ice Polar Stereographic North,9001,4054,19865,9829,1,0,4468,8806,0,9001,8807,0,9001,8832,70,9102,8833,-45,9102,,,,,,,,,,,,,,,,
+3412,NSIDC Sea Ice Polar Stereographic South,9001,4054,19866,9829,1,0,4470,8806,0,9001,8807,0,9001,8832,-70,9102,8833,0,9102,,,,,,,,,,,,,,,,
+3413,"WGS 84 / NSIDC Sea Ice Polar Stereographic North",9001,4326,19865,9829,1,0,4468,8806,0,9001,8807,0,9001,8832,70,9102,8833,-45,9102,,,,,,,,,,,,,,,,
+3414,"SVY21 / Singapore TM",9001,4757,19864,9807,1,0,4500,8801,1.22,9110,8802,103.5,9110,8805,1,9201,8806,28001.642,9001,8807,38744.572,9001,,,,,,,,,,,,,
+3415,"WGS 72BE / South China Sea Lambert",9001,4324,19863,9802,1,0,4400,8821,21,9102,8822,114,9102,8823,18,9102,8824,24,9102,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+3416,"ETRS89 / Austria Lambert",9001,4258,19947,9802,1,0,4530,8821,47.3,9110,8822,13.2,9110,8823,49,9110,8824,46,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+3417,"NAD83 / Iowa North (ftUS)",9003,4269,15377,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,4921250,9003,8827,3280833.3333,9003,,,,,,,,,,
+3418,"NAD83 / Iowa South (ftUS)",9003,4269,15378,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+3419,"NAD83 / Kansas North (ftUS)",9003,4269,15379,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+3420,"NAD83 / Kansas South (ftUS)",9003,4269,15380,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,,,,,,,,
+3421,"NAD83 / Nevada East (ftUS)",9003,4269,15381,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,656166.6667,9003,8807,26246666.6667,9003,,,,,,,,,,,,,
+3422,"NAD83 / Nevada Central (ftUS)",9003,4269,15382,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,1640416.6667,9003,8807,19685000,9003,,,,,,,,,,,,,
+3423,"NAD83 / Nevada West (ftUS)",9003,4269,15383,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,2624666.6667,9003,8807,13123333.3333,9003,,,,,,,,,,,,,
+3424,"NAD83 / New Jersey (ftUS)",9003,4269,15384,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,,,,,,,,
+3425,"NAD83(HARN) / Iowa North (ftUS)",9003,4152,15377,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,4921250,9003,8827,3280833.3333,9003,,,,,,,,,,
+3426,"NAD83(HARN) / Iowa South (ftUS)",9003,4152,15378,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+3427,"NAD83(HARN) / Kansas North (ftUS)",9003,4152,15379,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+3428,"NAD83(HARN) / Kansas South (ftUS)",9003,4152,15380,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,,,,,,,,
+3429,"NAD83(HARN) / Nevada East (ftUS)",9003,4152,15381,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,656166.6667,9003,8807,26246666.6667,9003,,,,,,,,,,,,,
+3430,"NAD83(HARN) / Nevada Central (ftUS)",9003,4152,15382,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,1640416.6667,9003,8807,19685000,9003,,,,,,,,,,,,,
+3431,"NAD83(HARN) / Nevada West (ftUS)",9003,4152,15383,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,2624666.6667,9003,8807,13123333.3333,9003,,,,,,,,,,,,,
+3432,"NAD83(HARN) / New Jersey (ftUS)",9003,4152,15384,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,,,,,,,,
+3433,"NAD83 / Arkansas North (ftUS)",9003,4269,15385,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+3434,"NAD83 / Arkansas South (ftUS)",9003,4269,15386,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,,,,,,,,
+3435,"NAD83 / Illinois East (ftUS)",9003,4269,15387,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+3436,"NAD83 / Illinois West (ftUS)",9003,4269,15388,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,2296583.3333,9003,8807,0,9003,,,,,,,,,,,,,
+3437,"NAD83 / New Hampshire (ftUS)",9003,4269,15389,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+3438,"NAD83 / Rhode Island (ftUS)",9003,4269,15390,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,328083.3333,9003,8807,0,9003,,,,,,,,,,,,,
+3439,"PSD93 / UTM zone 39N",9001,4134,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3440,"PSD93 / UTM zone 40N",9001,4134,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3441,"NAD83(HARN) / Arkansas North (ftUS)",9003,4152,15385,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+3442,"NAD83(HARN) / Arkansas South (ftUS)",9003,4152,15386,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,,,,,,,,
+3443,"NAD83(HARN) / Illinois East (ftUS)",9003,4152,15387,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+3444,"NAD83(HARN) / Illinois West (ftUS)",9003,4152,15388,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,2296583.3333,9003,8807,0,9003,,,,,,,,,,,,,
+3445,"NAD83(HARN) / New Hampshire (ftUS)",9003,4152,15389,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+3446,"NAD83(HARN) / Rhode Island (ftUS)",9003,4152,15390,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,328083.3333,9003,8807,0,9003,,,,,,,,,,,,,
+3447,"ETRS89 / Belgian Lambert 2005",9001,4258,19862,9802,1,0,4499,8821,50.4752134,9110,8822,4.2133177,9110,8823,49.5,9110,8824,51.1,9110,8826,150328,9001,8827,166262,9001,,,,,,,,,,
+3448,"JAD2001 / Jamaica Metric Grid",9001,4758,19860,9801,1,0,4400,8801,18,9102,8802,-77,9102,8805,1,9201,8806,750000,9001,8807,650000,9001,,,,,,,,,,,,,
+3449,"JAD2001 / UTM zone 17N",9001,4758,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3450,"JAD2001 / UTM zone 18N",9001,4758,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3451,"NAD83 / Louisiana North (ftUS)",9003,4269,15391,9802,1,0,4497,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,3280833.3333,9003,8827,0,9003,,,,,,,,,,
+3452,"NAD83 / Louisiana South (ftUS)",9003,4269,15392,9802,1,0,4497,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,3280833.3333,9003,8827,0,9003,,,,,,,,,,
+3453,"NAD83 / Louisiana Offshore (ftUS)",9003,4269,15393,9802,1,0,4497,8821,25.3,9110,8822,-91.2,9110,8823,27.5,9110,8824,26.1,9110,8826,3280833.3333,9003,8827,0,9003,,,,,,,,,,
+3454,"NAD83 / South Dakota North (ftUS)",9003,4269,15395,9802,1,1,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3455,"NAD83 / South Dakota South (ftUS)",9003,4269,15395,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3456,"NAD83(HARN) / Louisiana North (ftUS)",9003,4152,15391,9802,1,0,4497,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,3280833.3333,9003,8827,0,9003,,,,,,,,,,
+3457,"NAD83(HARN) / Louisiana South (ftUS)",9003,4152,15392,9802,1,0,4497,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,3280833.3333,9003,8827,0,9003,,,,,,,,,,
+3458,"NAD83(HARN) / South Dakota North (ftUS)",9003,4152,15394,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3459,"NAD83(HARN) / South Dakota South (ftUS)",9003,4152,15395,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3460,"Fiji 1986 / Fiji Map Grid",9001,4720,19859,9807,1,0,4400,8801,-17,9110,8802,178.45,9110,8805,0.99985,9201,8806,2000000,9001,8807,4000000,9001,,,,,,,,,,,,,
+3461,"Dabola 1981 / UTM zone 28N",9001,4155,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3462,"Dabola 1981 / UTM zone 29N",9001,4155,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3463,"NAD83 / Maine CS2000 Central",9001,4269,11854,9807,1,0,4499,8801,43.3,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3464,"NAD83(HARN) / Maine CS2000 Central",9001,4152,11854,9807,1,0,4499,8801,43.3,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3465,"NAD83(NSRS2007) / Alabama East",9001,4759,10131,9807,1,0,4499,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3466,"NAD83(NSRS2007) / Alabama West",9001,4759,10132,9807,1,0,4499,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,600000,9001,8807,0,9001,,,,,,,,,,,,,
+3467,"NAD83(NSRS2007) / Alaska Albers",9001,4759,15021,9822,1,0,4499,8821,50,9102,8822,-154,9102,8823,55,9102,8824,65,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3468,"NAD83(NSRS2007) / Alaska zone 1",9001,4759,15031,9812,1,0,4499,8806,5000000,9001,8807,-5000000,9001,8811,57,9110,8812,-133.4,9110,8813,323.07483685,9110,8814,323.07483685,9110,8815,0.9999,9201,,,,,,,
+3469,"NAD83(NSRS2007) / Alaska zone 2",9001,4759,15032,9807,1,0,4499,8801,54,9102,8802,-142,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3470,"NAD83(NSRS2007) / Alaska zone 3",9001,4759,15033,9807,1,0,4499,8801,54,9102,8802,-146,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3471,"NAD83(NSRS2007) / Alaska zone 4",9001,4759,15034,9807,1,0,4499,8801,54,9102,8802,-150,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3472,"NAD83(NSRS2007) / Alaska zone 5",9001,4759,15035,9807,1,0,4499,8801,54,9102,8802,-154,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3473,"NAD83(NSRS2007) / Alaska zone 6",9001,4759,15036,9807,1,0,4499,8801,54,9102,8802,-158,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3474,"NAD83(NSRS2007) / Alaska zone 7",9001,4759,15037,9807,1,0,4499,8801,54,9102,8802,-162,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3475,"NAD83(NSRS2007) / Alaska zone 8",9001,4759,15038,9807,1,0,4499,8801,54,9102,8802,-166,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3476,"NAD83(NSRS2007) / Alaska zone 9",9001,4759,15039,9807,1,0,4499,8801,54,9102,8802,-170,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3477,"NAD83(NSRS2007) / Alaska zone 10",9001,4759,15040,9802,1,0,4499,8821,51,9110,8822,-176,9110,8823,53.5,9110,8824,51.5,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+3478,"NAD83(NSRS2007) / Arizona Central",9001,4759,10232,9807,1,0,4499,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+3479,"NAD83(NSRS2007) / Arizona Central (ft)",9002,4759,15305,9807,1,0,4495,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+3480,"NAD83(NSRS2007) / Arizona East",9001,4759,10231,9807,1,0,4499,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+3481,"NAD83(NSRS2007) / Arizona East (ft)",9002,4759,15304,9807,1,0,4495,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+3482,"NAD83(NSRS2007) / Arizona West",9001,4759,10233,9807,1,0,4499,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+3483,"NAD83(NSRS2007) / Arizona West (ft)",9002,4759,15306,9807,1,0,4495,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+3484,"NAD83(NSRS2007) / Arkansas North",9001,4759,10331,9802,1,0,4499,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+3485,"NAD83(NSRS2007) / Arkansas North (ftUS)",9003,4759,15385,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+3486,"NAD83(NSRS2007) / Arkansas South",9001,4759,10332,9802,1,0,4499,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+3487,"NAD83(NSRS2007) / Arkansas South (ftUS)",9003,4759,15386,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,,,,,,,,
+3488,"NAD83(NSRS2007) / California Albers",9001,4759,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,,,,,,,,
+3489,"NAD83(NSRS2007) / California zone 1",9001,4759,10431,9802,1,0,4499,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+3490,"NAD83(NSRS2007) / California zone 1 (ftUS)",9003,4759,15307,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+3491,"NAD83(NSRS2007) / California zone 2",9001,4759,10432,9802,1,0,4499,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+3492,"NAD83(NSRS2007) / California zone 2 (ftUS)",9003,4759,15308,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+3493,"NAD83(NSRS2007) / California zone 3",9001,4759,10433,9802,1,0,4499,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+3494,"NAD83(NSRS2007) / California zone 3 (ftUS)",9003,4759,15309,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+3495,"NAD83(NSRS2007) / California zone 4",9001,4759,10434,9802,1,0,4499,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+3496,"NAD83(NSRS2007) / California zone 4 (ftUS)",9003,4759,15310,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+3497,"NAD83(NSRS2007) / California zone 5",9001,4759,10435,9802,1,0,4499,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+3498,"NAD83(NSRS2007) / California zone 5 (ftUS)",9003,4759,15311,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+3499,"NAD83(NSRS2007) / California zone 6",9001,4759,10436,9802,1,0,4499,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+3500,"NAD83(NSRS2007) / California zone 6 (ftUS)",9003,4759,15312,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+3501,"NAD83(NSRS2007) / Colorado Central",9001,4759,10532,9802,1,0,4499,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+3502,"NAD83(NSRS2007) / Colorado Central (ftUS)",9003,4759,15314,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+3503,"NAD83(NSRS2007) / Colorado North",9001,4759,10531,9802,1,0,4499,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+3504,"NAD83(NSRS2007) / Colorado North (ftUS)",9003,4759,15313,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+3505,"NAD83(NSRS2007) / Colorado South",9001,4759,10533,9802,1,0,4499,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+3506,"NAD83(NSRS2007) / Colorado South (ftUS)",9003,4759,15315,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+3507,"NAD83(NSRS2007) / Connecticut",9001,4759,10630,9802,1,0,4499,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,304800.6096,9001,8827,152400.3048,9001,,,,,,,,,,
+3508,"NAD83(NSRS2007) / Connecticut (ftUS)",9003,4759,15316,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,1000000,9003,8827,500000,9003,,,,,,,,,,
+3509,"NAD83(NSRS2007) / Delaware",9001,4759,10730,9807,1,0,4499,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3510,"NAD83(NSRS2007) / Delaware (ftUS)",9003,4759,15317,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+3511,"NAD83(NSRS2007) / Florida East",9001,4759,10931,9807,1,0,4499,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3512,"NAD83(NSRS2007) / Florida East (ftUS)",9003,4759,15318,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+3513,"NAD83(NSRS2007) / Florida GDL Albers",9001,4759,10934,9822,1,0,4499,8821,24,9110,8822,-84,9110,8823,24,9110,8824,31.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+3514,"NAD83(NSRS2007) / Florida North",9001,4759,10933,9802,1,0,4499,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3515,"NAD83(NSRS2007) / Florida North (ftUS)",9003,4759,15320,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3516,"NAD83(NSRS2007) / Florida West",9001,4759,10932,9807,1,0,4499,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3517,"NAD83(NSRS2007) / Florida West (ftUS)",9003,4759,15319,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+3518,"NAD83(NSRS2007) / Georgia East",9001,4759,11031,9807,1,0,4499,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3519,"NAD83(NSRS2007) / Georgia East (ftUS)",9003,4759,15321,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+3520,"NAD83(NSRS2007) / Georgia West",9001,4759,11032,9807,1,0,4499,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+3521,"NAD83(NSRS2007) / Georgia West (ftUS)",9003,4759,15322,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,2296583.333,9003,8807,0,9003,,,,,,,,,,,,,
+3522,"NAD83(NSRS2007) / Idaho Central",9001,4759,11132,9807,1,0,4499,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3523,"NAD83(NSRS2007) / Idaho Central (ftUS)",9003,4759,15324,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,1640416.667,9003,8807,0,9003,,,,,,,,,,,,,
+3524,"NAD83(NSRS2007) / Idaho East",9001,4759,11131,9807,1,0,4499,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3525,"NAD83(NSRS2007) / Idaho East (ftUS)",9003,4759,15323,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+3526,"NAD83(NSRS2007) / Idaho West",9001,4759,11133,9807,1,0,4499,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,800000,9001,8807,0,9001,,,,,,,,,,,,,
+3527,"NAD83(NSRS2007) / Idaho West (ftUS)",9003,4759,15325,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,2624666.667,9003,8807,0,9003,,,,,,,,,,,,,
+3528,"NAD83(NSRS2007) / Illinois East",9001,4759,11231,9807,1,0,4499,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+3529,"NAD83(NSRS2007) / Illinois East (ftUS)",9003,4759,15387,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+3530,"NAD83(NSRS2007) / Illinois West",9001,4759,11232,9807,1,0,4499,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+3531,"NAD83(NSRS2007) / Illinois West (ftUS)",9003,4759,15388,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,2296583.3333,9003,8807,0,9003,,,,,,,,,,,,,
+3532,"NAD83(NSRS2007) / Indiana East",9001,4759,11331,9807,1,0,4499,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,100000,9001,8807,250000,9001,,,,,,,,,,,,,
+3533,"NAD83(NSRS2007) / Indiana East (ftUS)",9003,4759,15372,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,820208.333,9003,,,,,,,,,,,,,
+3534,"NAD83(NSRS2007) / Indiana West",9001,4759,11332,9807,1,0,4499,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,900000,9001,8807,250000,9001,,,,,,,,,,,,,
+3535,"NAD83(NSRS2007) / Indiana West (ftUS)",9003,4759,15373,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,820208.333,9003,,,,,,,,,,,,,
+3536,"NAD83(NSRS2007) / Iowa North",9001,4759,11431,9802,1,0,4499,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,1500000,9001,8827,1000000,9001,,,,,,,,,,
+3537,"NAD83(NSRS2007) / Iowa North (ftUS)",9003,4759,15377,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,4921250,9003,8827,3280833.3333,9003,,,,,,,,,,
+3538,"NAD83(NSRS2007) / Iowa South",9001,4759,11432,9802,1,0,4499,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+3539,"NAD83(NSRS2007) / Iowa South (ftUS)",9003,4759,15378,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+3540,"NAD83(NSRS2007) / Kansas North",9001,4759,11531,9802,1,0,4499,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+3541,"NAD83(NSRS2007) / Kansas North (ftUS)",9003,4759,15379,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+3542,"NAD83(NSRS2007) / Kansas South",9001,4759,11532,9802,1,0,4499,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+3543,"NAD83(NSRS2007) / Kansas South (ftUS)",9003,4759,15380,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,,,,,,,,
+3544,"NAD83(NSRS2007) / Kentucky North",9001,4759,15303,9802,1,0,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+3545,"NAD83(NSRS2007) / Kentucky North (ftUS)",9003,4759,15328,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+3546,"NAD83(NSRS2007) / Kentucky Single Zone",9001,4759,11630,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,1500000,9001,8827,1000000,9001,,,,,,,,,,
+3547,"NAD83(NSRS2007) / Kentucky Single Zone (ftUS)",9003,4759,15375,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,4921250,9003,8827,3280833.333,9003,,,,,,,,,,
+3548,"NAD83(NSRS2007) / Kentucky South",9001,4759,11632,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+3549,"NAD83(NSRS2007) / Kentucky South (ftUS)",9003,4759,15329,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,1640416.667,9003,8827,1640416.667,9003,,,,,,,,,,
+3550,"NAD83(NSRS2007) / Louisiana North",9001,4759,11731,9802,1,0,4499,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+3551,"NAD83(NSRS2007) / Louisiana North (ftUS)",9003,4759,15391,9802,1,0,4497,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,3280833.3333,9003,8827,0,9003,,,,,,,,,,
+3552,"NAD83(NSRS2007) / Louisiana South",9001,4759,11732,9802,1,0,4499,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+3553,"NAD83(NSRS2007) / Louisiana South (ftUS)",9003,4759,15392,9802,1,0,4497,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,3280833.3333,9003,8827,0,9003,,,,,,,,,,
+3554,"NAD83(NSRS2007) / Maine CS2000 Central",9001,4759,11854,9807,1,0,4499,8801,43.3,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3555,"NAD83(NSRS2007) / Maine CS2000 East",9001,4759,11851,9807,1,0,4499,8801,43.5,9110,8802,-67.523,9110,8805,0.99998,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+3556,"NAD83(NSRS2007) / Maine CS2000 West",9001,4759,11853,9807,1,0,4499,8801,42.5,9110,8802,-70.223,9110,8805,0.99998,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+3557,"NAD83(NSRS2007) / Maine East",9001,4759,11831,9807,1,0,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+3558,"NAD83(NSRS2007) / Maine West",9001,4759,11832,9807,1,0,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,900000,9001,8807,0,9001,,,,,,,,,,,,,
+3559,"NAD83(NSRS2007) / Maryland",9001,4759,11930,9802,1,0,4499,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+3560,"NAD83 / Utah North (ftUS)",9003,4269,15297,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640416.6667,9003,8827,3280833.3333,9003,,,,,,,,,,
+3561,"Old Hawaiian / Hawaii zone 1",9003,4135,15101,9807,1,0,4497,8801,18.5,9110,8802,-155.3,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+3562,"Old Hawaiian / Hawaii zone 2",9003,4135,15102,9807,1,0,4497,8801,20.2,9110,8802,-156.4,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+3563,"Old Hawaiian / Hawaii zone 3",9003,4135,15103,9807,1,0,4497,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+3564,"Old Hawaiian / Hawaii zone 4",9003,4135,15104,9807,1,0,4497,8801,21.5,9110,8802,-159.3,9110,8805,0.99999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+3565,"Old Hawaiian / Hawaii zone 5",9003,4135,15105,9807,1,0,4497,8801,21.4,9110,8802,-160.1,9110,8805,1,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+3566,"NAD83 / Utah Central (ftUS)",9003,4269,15298,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640416.6667,9003,8827,6561666.6667,9003,,,,,,,,,,
+3567,"NAD83 / Utah South (ftUS)",9003,4269,15299,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640416.6667,9003,8827,9842500,9003,,,,,,,,,,
+3568,"NAD83(HARN) / Utah North (ftUS)",9003,4152,15297,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640416.6667,9003,8827,3280833.3333,9003,,,,,,,,,,
+3569,"NAD83(HARN) / Utah Central (ftUS)",9003,4152,15298,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640416.6667,9003,8827,6561666.6667,9003,,,,,,,,,,
+3570,"NAD83(HARN) / Utah South (ftUS)",9003,4152,15299,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640416.6667,9003,8827,9842500,9003,,,,,,,,,,
+3571,"WGS 84 / North Pole LAEA Bering Sea",9001,4326,17295,9820,1,0,4464,8801,90,9102,8802,180,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3572,"WGS 84 / North Pole LAEA Alaska",9001,4326,17296,9820,1,0,4467,8801,90,9102,8802,-150,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3573,"WGS 84 / North Pole LAEA Canada",9001,4326,17297,9820,1,0,4466,8801,90,9102,8802,-100,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3574,"WGS 84 / North Pole LAEA Atlantic",9001,4326,17298,9820,1,0,4465,8801,90,9102,8802,-40,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3575,"WGS 84 / North Pole LAEA Europe",9001,4326,17299,9820,1,0,4463,8801,90,9102,8802,10,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3576,"WGS 84 / North Pole LAEA Russia",9001,4326,17300,9820,1,0,1035,8801,90,9102,8802,90,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3577,"GDA94 / Australian Albers",9001,4283,17365,9822,1,0,4400,8821,0,9102,8822,132,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3578,"NAD83 / Yukon Albers",9001,4269,19858,9822,1,0,4400,8821,59,9110,8822,-132.3,9110,8823,61.4,9110,8824,68,9110,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+3579,"NAD83(CSRS) / Yukon Albers",9001,4617,19858,9822,1,0,4400,8821,59,9110,8822,-132.3,9110,8823,61.4,9110,8824,68,9110,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+3580,"NAD83 / NWT Lambert",9001,4269,19857,9802,1,0,4400,8821,0,9102,8822,-112,9102,8823,62,9102,8824,70,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3581,"NAD83(CSRS) / NWT Lambert",9001,4617,19857,9802,1,0,4400,8821,0,9102,8822,-112,9102,8823,62,9102,8824,70,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3582,"NAD83(NSRS2007) / Maryland (ftUS)",9003,4759,15330,9802,1,0,4497,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,1312333.333,9003,8827,0,9003,,,,,,,,,,
+3583,"NAD83(NSRS2007) / Massachusetts Island",9001,4759,12032,9802,1,0,4499,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+3584,"NAD83(NSRS2007) / Massachusetts Island (ftUS)",9003,4759,15332,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+3585,"NAD83(NSRS2007) / Massachusetts Mainland",9001,4759,12031,9802,1,0,4499,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,200000,9001,8827,750000,9001,,,,,,,,,,
+3586,"NAD83(NSRS2007) / Massachusetts Mainland (ftUS)",9003,4759,15331,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,656166.667,9003,8827,2460625,9003,,,,,,,,,,
+3587,"NAD83(NSRS2007) / Michigan Central",9001,4759,12142,9802,1,0,4499,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,6000000,9001,8827,0,9001,,,,,,,,,,
+3588,"NAD83(NSRS2007) / Michigan Central (ft)",9002,4759,15334,9802,1,0,4495,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,19685039.37,9002,8827,0,9002,,,,,,,,,,
+3589,"NAD83(NSRS2007) / Michigan North",9001,4759,12141,9802,1,0,4499,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,8000000,9001,8827,0,9001,,,,,,,,,,
+3590,"NAD83(NSRS2007) / Michigan North (ft)",9002,4759,15333,9802,1,0,4495,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,26246719.16,9002,8827,0,9002,,,,,,,,,,
+3591,"NAD83(NSRS2007) / Michigan Oblique Mercator",9001,4759,12150,9812,1,0,4499,8806,2546731.496,9001,8807,-4354009.816,9001,8811,45.1833,9110,8812,-86,9110,8813,337.25556,9102,8814,337.25556,9102,8815,0.9996,9201,,,,,,,
+3592,"NAD83(NSRS2007) / Michigan South",9001,4759,12143,9802,1,0,4499,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,4000000,9001,8827,0,9001,,,,,,,,,,
+3593,"NAD83(NSRS2007) / Michigan South (ft)",9002,4759,15335,9802,1,0,4495,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,13123359.58,9002,8827,0,9002,,,,,,,,,,
+3594,"NAD83(NSRS2007) / Minnesota Central",9001,4759,12232,9802,1,0,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+3595,"NAD83(NSRS2007) / Minnesota North",9001,4759,12231,9802,1,0,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+3596,"NAD83(NSRS2007) / Minnesota South",9001,4759,12233,9802,1,0,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+3597,"NAD83(NSRS2007) / Mississippi East",9001,4759,12331,9807,1,0,4499,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+3598,"NAD83(NSRS2007) / Mississippi East (ftUS)",9003,4759,15336,9807,1,0,4497,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+3599,"NAD83(NSRS2007) / Mississippi West",9001,4759,12332,9807,1,0,4499,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+3600,"NAD83(NSRS2007) / Mississippi West (ftUS)",9003,4759,15337,9807,1,0,4497,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,2296583.333,9003,8807,0,9003,,,,,,,,,,,,,
+3601,"NAD83(NSRS2007) / Missouri Central",9001,4759,12432,9807,1,0,4499,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3602,"NAD83(NSRS2007) / Missouri East",9001,4759,12431,9807,1,0,4499,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+3603,"NAD83(NSRS2007) / Missouri West",9001,4759,12433,9807,1,0,4499,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,850000,9001,8807,0,9001,,,,,,,,,,,,,
+3604,"NAD83(NSRS2007) / Montana",9001,4759,12530,9802,1,0,4499,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3605,"NAD83(NSRS2007) / Montana (ft)",9002,4759,15338,9802,1,0,4495,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+3606,"NAD83(NSRS2007) / Nebraska",9001,4759,12630,9802,1,0,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+3607,"NAD83(NSRS2007) / Nevada Central",9001,4759,12732,9807,1,0,4499,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9001,8807,6000000,9001,,,,,,,,,,,,,
+3608,"NAD83(NSRS2007) / Nevada Central (ftUS)",9003,4759,15382,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,1640416.6667,9003,8807,19685000,9003,,,,,,,,,,,,,
+3609,"NAD83(NSRS2007) / Nevada East",9001,4759,12731,9807,1,0,4499,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,200000,9001,8807,8000000,9001,,,,,,,,,,,,,
+3610,"NAD83(NSRS2007) / Nevada East (ftUS)",9003,4759,15381,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,656166.6667,9003,8807,26246666.6667,9003,,,,,,,,,,,,,
+3611,"NAD83(NSRS2007) / Nevada West",9001,4759,12733,9807,1,0,4499,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,800000,9001,8807,4000000,9001,,,,,,,,,,,,,
+3612,"NAD83(NSRS2007) / Nevada West (ftUS)",9003,4759,15383,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,2624666.6667,9003,8807,13123333.3333,9003,,,,,,,,,,,,,
+3613,"NAD83(NSRS2007) / New Hampshire",9001,4759,12830,9807,1,0,4499,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+3614,"NAD83(NSRS2007) / New Hampshire (ftUS)",9003,4759,15389,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+3615,"NAD83(NSRS2007) / New Jersey",9001,4759,12930,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3616,"NAD83(NSRS2007) / New Jersey (ftUS)",9003,4759,15384,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,,,,,,,,
+3617,"NAD83(NSRS2007) / New Mexico Central",9001,4759,13032,9807,1,0,4499,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3618,"NAD83(NSRS2007) / New Mexico Central (ftUS)",9003,4759,15340,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,1640416.667,9003,8807,0,9003,,,,,,,,,,,,,
+3619,"NAD83(NSRS2007) / New Mexico East",9001,4759,13031,9807,1,0,4499,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,165000,9001,8807,0,9001,,,,,,,,,,,,,
+3620,"NAD83(NSRS2007) / New Mexico East (ftUS)",9003,4759,15339,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,541337.5,9003,8807,0,9003,,,,,,,,,,,,,
+3621,"NAD83(NSRS2007) / New Mexico West",9001,4759,13033,9807,1,0,4499,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,830000,9001,8807,0,9001,,,,,,,,,,,,,
+3622,"NAD83(NSRS2007) / New Mexico West (ftUS)",9003,4759,15341,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,2723091.667,9003,8807,0,9003,,,,,,,,,,,,,
+3623,"NAD83(NSRS2007) / New York Central",9001,4759,13132,9807,1,0,4499,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+3624,"NAD83(NSRS2007) / New York Central (ftUS)",9003,4759,15343,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,820208.333,9003,8807,0,9003,,,,,,,,,,,,,
+3625,"NAD83(NSRS2007) / New York East",9001,4759,13131,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+3626,"NAD83(NSRS2007) / New York East (ftUS)",9003,4759,15342,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,,,,,,,,
+3627,"NAD83(NSRS2007) / New York Long Island",9001,4759,13134,9802,1,0,4499,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,300000,9001,8827,0,9001,,,,,,,,,,
+3628,"NAD83(NSRS2007) / New York Long Island (ftUS)",9003,4759,15345,9802,1,0,4497,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,984250,9003,8827,0,9003,,,,,,,,,,
+3629,"NAD83(NSRS2007) / New York West",9001,4759,13133,9807,1,0,4499,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,350000,9001,8807,0,9001,,,,,,,,,,,,,
+3630,"NAD83(NSRS2007) / New York West (ftUS)",9003,4759,15344,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,1148291.667,9003,8807,0,9003,,,,,,,,,,,,,
+3631,"NAD83(NSRS2007) / North Carolina",9001,4759,13230,9802,1,0,4499,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,609601.22,9001,8827,0,9001,,,,,,,,,,
+3632,"NAD83(NSRS2007) / North Carolina (ftUS)",9003,4759,15346,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+3633,"NAD83(NSRS2007) / North Dakota North",9001,4759,13331,9802,1,0,4499,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3634,"NAD83(NSRS2007) / North Dakota North (ft)",9002,4759,15347,9802,1,0,4495,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+3635,"NAD83(NSRS2007) / North Dakota South",9001,4759,13332,9802,1,0,4499,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3636,"NAD83(NSRS2007) / North Dakota South (ft)",9002,4759,15348,9802,1,0,4495,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+3637,"NAD83(NSRS2007) / Ohio North",9001,4759,13431,9802,1,0,4499,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3638,"NAD83(NSRS2007) / Ohio South",9001,4759,13432,9802,1,0,4499,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3639,"NAD83(NSRS2007) / Oklahoma North",9001,4759,13531,9802,1,0,4499,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3640,"NAD83(NSRS2007) / Oklahoma North (ftUS)",9003,4759,15349,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3641,"NAD83(NSRS2007) / Oklahoma South",9001,4759,13532,9802,1,0,4499,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3642,"NAD83(NSRS2007) / Oklahoma South (ftUS)",9003,4759,15350,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3643,"NAD83(NSRS2007) / Oregon LCC (m)",9001,4759,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+3644,"NAD83(NSRS2007) / Oregon GIC Lambert (ft)",9002,4759,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,,,,,,,,
+3645,"NAD83(NSRS2007) / Oregon North",9001,4759,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,,,,,,,,
+3646,"NAD83(NSRS2007) / Oregon North (ft)",9002,4759,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,,,,,,,,
+3647,"NAD83(NSRS2007) / Oregon South",9001,4759,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,,,,,,,,
+3648,"NAD83(NSRS2007) / Oregon South (ft)",9002,4759,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,,,,,,,,
+3649,"NAD83(NSRS2007) / Pennsylvania North",9001,4759,13731,9802,1,0,4499,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3650,"NAD83(NSRS2007) / Pennsylvania North (ftUS)",9003,4759,15353,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3651,"NAD83(NSRS2007) / Pennsylvania South",9001,4759,13732,9802,1,0,4499,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3652,"NAD83(NSRS2007) / Pennsylvania South (ftUS)",9003,4759,15354,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3653,"NAD83(NSRS2007) / Rhode Island",9001,4759,13830,9807,1,0,4499,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,100000,9001,8807,0,9001,,,,,,,,,,,,,
+3654,"NAD83(NSRS2007) / Rhode Island (ftUS)",9003,4759,15390,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,328083.3333,9003,8807,0,9003,,,,,,,,,,,,,
+3655,"NAD83(NSRS2007) / South Carolina",9001,4759,13930,9802,1,0,4499,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,609600,9001,8827,0,9001,,,,,,,,,,
+3656,"NAD83(NSRS2007) / South Carolina (ft)",9002,4759,15355,9802,1,0,4495,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,2000000,9002,8827,0,9002,,,,,,,,,,
+3657,"NAD83(NSRS2007) / South Dakota North",9001,4759,14031,9802,1,0,4499,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3658,"NAD83(NSRS2007) / South Dakota North (ftUS)",9003,4759,15394,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3659,"NAD83(NSRS2007) / South Dakota South",9001,4759,14032,9802,1,0,4499,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3660,"NAD83(NSRS2007) / South Dakota South (ftUS)",9003,4759,15395,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3661,"NAD83(NSRS2007) / Tennessee",9001,4759,14130,9802,1,0,4499,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3662,"NAD83(NSRS2007) / Tennessee (ftUS)",9003,4759,15356,9802,1,0,4497,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3663,"NAD83(NSRS2007) / Texas Central",9001,4759,14233,9802,1,0,4499,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,700000,9001,8827,3000000,9001,,,,,,,,,,
+3664,"NAD83(NSRS2007) / Texas Central (ftUS)",9003,4759,15359,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,2296583.333,9003,8827,9842500,9003,,,,,,,,,,
+3665,"NAD83(NSRS2007) / Texas Centric Albers Equal Area",9001,4759,14254,9822,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,6000000,9001,,,,,,,,,,
+3666,"NAD83(NSRS2007) / Texas Centric Lambert Conformal",9001,4759,14253,9802,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,5000000,9001,,,,,,,,,,
+3667,"NAD83(NSRS2007) / Texas North",9001,4759,14231,9802,1,0,4499,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,200000,9001,8827,1000000,9001,,,,,,,,,,
+3668,"NAD83(NSRS2007) / Texas North (ftUS)",9003,4759,15357,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,656166.667,9003,8827,3280833.333,9003,,,,,,,,,,
+3669,"NAD83(NSRS2007) / Texas North Central",9001,4759,14232,9802,1,0,4499,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,600000,9001,8827,2000000,9001,,,,,,,,,,
+3670,"NAD83(NSRS2007) / Texas North Central (ftUS)",9003,4759,15358,9802,1,0,4497,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,1968500,9003,8827,6561666.667,9003,,,,,,,,,,
+3671,"NAD83(NSRS2007) / Texas South",9001,4759,14235,9802,1,0,4499,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,300000,9001,8827,5000000,9001,,,,,,,,,,
+3672,"NAD83(NSRS2007) / Texas South (ftUS)",9003,4759,15361,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,984250,9003,8827,16404166.667,9003,,,,,,,,,,
+3673,"NAD83(NSRS2007) / Texas South Central",9001,4759,14234,9802,1,0,4499,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,600000,9001,8827,4000000,9001,,,,,,,,,,
+3674,"NAD83(NSRS2007) / Texas South Central (ftUS)",9003,4759,15360,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,1968500,9003,8827,13123333.333,9003,,,,,,,,,,
+3675,"NAD83(NSRS2007) / Utah Central",9001,4759,14332,9802,1,0,4499,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,500000,9001,8827,2000000,9001,,,,,,,,,,
+3676,"NAD83(NSRS2007) / Utah Central (ft)",9002,4759,15363,9802,0,0,4495,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640419.948,9002,8827,6561679.79,9002,,,,,,,,,,
+3677,"NAD83(NSRS2007) / Utah Central (ftUS)",9003,4759,15298,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640416.6667,9003,8827,6561666.6667,9003,,,,,,,,,,
+3678,"NAD83(NSRS2007) / Utah North",9001,4759,14331,9802,1,0,4499,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,500000,9001,8827,1000000,9001,,,,,,,,,,
+3679,"NAD83(NSRS2007) / Utah North (ft)",9002,4759,15362,9802,0,0,4495,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640419.948,9002,8827,3280839.895,9002,,,,,,,,,,
+3680,"NAD83(NSRS2007) / Utah North (ftUS)",9003,4759,15297,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640416.6667,9003,8827,3280833.3333,9003,,,,,,,,,,
+3681,"NAD83(NSRS2007) / Utah South",9001,4759,14333,9802,1,0,4499,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,500000,9001,8827,3000000,9001,,,,,,,,,,
+3682,"NAD83(NSRS2007) / Utah South (ft)",9002,4759,15364,9802,0,0,4495,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640419.948,9002,8827,9842519.685,9002,,,,,,,,,,
+3683,"NAD83(NSRS2007) / Utah South (ftUS)",9003,4759,15299,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640416.6667,9003,8827,9842500,9003,,,,,,,,,,
+3684,"NAD83(NSRS2007) / Vermont",9001,4759,14430,9807,1,0,4499,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3685,"NAD83(NSRS2007) / Virginia North",9001,4759,14531,9802,1,0,4499,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,3500000,9001,8827,2000000,9001,,,,,,,,,,
+3686,"NAD83(NSRS2007) / Virginia North (ftUS)",9003,4759,15365,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,11482916.667,9003,8827,6561666.667,9003,,,,,,,,,,
+3687,"NAD83(NSRS2007) / Virginia South",9001,4759,14532,9802,1,0,4499,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,3500000,9001,8827,1000000,9001,,,,,,,,,,
+3688,"NAD83(NSRS2007) / Virginia South (ftUS)",9003,4759,15366,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,11482916.667,9003,8827,3280833.333,9003,,,,,,,,,,
+3689,"NAD83(NSRS2007) / Washington North",9001,4759,14631,9802,1,0,4499,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+3690,"NAD83(NSRS2007) / Washington North (ftUS)",9003,4759,15367,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+3691,"NAD83(NSRS2007) / Washington South",9001,4759,14632,9802,1,0,4499,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+3692,"NAD83(NSRS2007) / Washington South (ftUS)",9003,4759,15368,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+3693,"NAD83(NSRS2007) / West Virginia North",9001,4759,14731,9802,1,0,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3694,"NAD83(NSRS2007) / West Virginia South",9001,4759,14732,9802,1,0,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3695,"NAD83(NSRS2007) / Wisconsin Central",9001,4759,14832,9802,1,0,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3696,"NAD83(NSRS2007) / Wisconsin Central (ftUS)",9003,4759,15370,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3697,"NAD83(NSRS2007) / Wisconsin North",9001,4759,14831,9802,1,0,4499,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3698,"NAD83(NSRS2007) / Wisconsin North (ftUS)",9003,4759,15369,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3699,"NAD83(NSRS2007) / Wisconsin South",9001,4759,14833,9802,1,0,4499,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+3700,"NAD83(NSRS2007) / Wisconsin South (ftUS)",9003,4759,15371,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3701,"NAD83(NSRS2007) / Wisconsin Transverse Mercator",9001,4759,14841,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,520000,9001,8807,-4480000,9001,,,,,,,,,,,,,
+3702,"NAD83(NSRS2007) / Wyoming East",9001,4759,14931,9807,1,0,4499,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+3703,"NAD83(NSRS2007) / Wyoming East Central",9001,4759,14932,9807,1,0,4499,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,400000,9001,8807,100000,9001,,,,,,,,,,,,,
+3704,"NAD83(NSRS2007) / Wyoming West Central",9001,4759,14933,9807,1,0,4499,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,600000,9001,8807,0,9001,,,,,,,,,,,,,
+3705,"NAD83(NSRS2007) / Wyoming West",9001,4759,14934,9807,1,0,4499,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,800000,9001,8807,100000,9001,,,,,,,,,,,,,
+3706,"NAD83(NSRS2007) / UTM zone 59N",9001,4759,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3707,"NAD83(NSRS2007) / UTM zone 60N",9001,4759,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3708,"NAD83(NSRS2007) / UTM zone 1N",9001,4759,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3709,"NAD83(NSRS2007) / UTM zone 2N",9001,4759,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3710,"NAD83(NSRS2007) / UTM zone 3N",9001,4759,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3711,"NAD83(NSRS2007) / UTM zone 4N",9001,4759,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3712,"NAD83(NSRS2007) / UTM zone 5N",9001,4759,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3713,"NAD83(NSRS2007) / UTM zone 6N",9001,4759,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3714,"NAD83(NSRS2007) / UTM zone 7N",9001,4759,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3715,"NAD83(NSRS2007) / UTM zone 8N",9001,4759,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3716,"NAD83(NSRS2007) / UTM zone 9N",9001,4759,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3717,"NAD83(NSRS2007) / UTM zone 10N",9001,4759,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3718,"NAD83(NSRS2007) / UTM zone 11N",9001,4759,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3719,"NAD83(NSRS2007) / UTM zone 12N",9001,4759,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3720,"NAD83(NSRS2007) / UTM zone 13N",9001,4759,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3721,"NAD83(NSRS2007) / UTM zone 14N",9001,4759,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3722,"NAD83(NSRS2007) / UTM zone 15N",9001,4759,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3723,"NAD83(NSRS2007) / UTM zone 16N",9001,4759,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3724,"NAD83(NSRS2007) / UTM zone 17N",9001,4759,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3725,"NAD83(NSRS2007) / UTM zone 18N",9001,4759,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3726,"NAD83(NSRS2007) / UTM zone 19N",9001,4759,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3727,"Reunion 1947 / TM Reunion",9001,4626,19856,9807,1,0,4499,8801,-21.07,9110,8802,55.32,9110,8805,1,9201,8806,160000,9001,8807,50000,9001,,,,,,,,,,,,,
+3728,"NAD83(NSRS2007) / Ohio North (ftUS)",9003,4759,13433,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3729,"NAD83(NSRS2007) / Ohio South (ftUS)",9003,4759,13434,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3730,"NAD83(NSRS2007) / Wyoming East (ftUS)",9003,4759,14935,9807,1,0,4497,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,656166.6667,9003,8807,0,9003,,,,,,,,,,,,,
+3731,"NAD83(NSRS2007) / Wyoming East Central (ftUS)",9003,4759,14936,9807,1,0,4497,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,1312333.3333,9003,8807,328083.3333,9003,,,,,,,,,,,,,
+3732,"NAD83(NSRS2007) / Wyoming West Central (ftUS)",9003,4759,14937,9807,1,0,4497,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,1968500,9003,8807,0,9003,,,,,,,,,,,,,
+3733,"NAD83(NSRS2007) / Wyoming West (ftUS)",9003,4759,14938,9807,1,0,4497,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,2624666.6667,9003,8807,328083.3333,9003,,,,,,,,,,,,,
+3734,"NAD83 / Ohio North (ftUS)",9003,4269,13433,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3735,"NAD83 / Ohio South (ftUS)",9003,4269,13434,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3736,"NAD83 / Wyoming East (ftUS)",9003,4269,14935,9807,1,0,4497,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,656166.6667,9003,8807,0,9003,,,,,,,,,,,,,
+3737,"NAD83 / Wyoming East Central (ftUS)",9003,4269,14936,9807,1,0,4497,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,1312333.3333,9003,8807,328083.3333,9003,,,,,,,,,,,,,
+3738,"NAD83 / Wyoming West Central (ftUS)",9003,4269,14937,9807,1,0,4497,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,1968500,9003,8807,0,9003,,,,,,,,,,,,,
+3739,"NAD83 / Wyoming West (ftUS)",9003,4269,14938,9807,1,0,4497,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,2624666.6667,9003,8807,328083.3333,9003,,,,,,,,,,,,,
+3740,"NAD83(HARN) / UTM zone 10N",9001,4152,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3741,"NAD83(HARN) / UTM zone 11N",9001,4152,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3742,"NAD83(HARN) / UTM zone 12N",9001,4152,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3743,"NAD83(HARN) / UTM zone 13N",9001,4152,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3744,"NAD83(HARN) / UTM zone 14N",9001,4152,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3745,"NAD83(HARN) / UTM zone 15N",9001,4152,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3746,"NAD83(HARN) / UTM zone 16N",9001,4152,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3747,"NAD83(HARN) / UTM zone 17N",9001,4152,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3748,"NAD83(HARN) / UTM zone 18N",9001,4152,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3749,"NAD83(HARN) / UTM zone 19N",9001,4152,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3750,"NAD83(HARN) / UTM zone 4N",9001,4152,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3751,"NAD83(HARN) / UTM zone 5N",9001,4152,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3752,"WGS 84 / Mercator 41",9001,4326,19855,9804,1,1,4499,8801,-41,9102,8802,100,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3753,"NAD83(HARN) / Ohio North (ftUS)",9003,4152,13433,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3754,"NAD83(HARN) / Ohio South (ftUS)",9003,4152,13434,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+3755,"NAD83(HARN) / Wyoming East (ftUS)",9003,4152,14935,9807,1,0,4497,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,656166.6667,9003,8807,0,9003,,,,,,,,,,,,,
+3756,"NAD83(HARN) / Wyoming East Central (ftUS)",9003,4152,14936,9807,1,0,4497,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,1312333.3333,9003,8807,328083.3333,9003,,,,,,,,,,,,,
+3757,"NAD83(HARN) / Wyoming West Central (ftUS)",9003,4152,14937,9807,1,0,4497,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,1968500,9003,8807,0,9003,,,,,,,,,,,,,
+3758,"NAD83(HARN) / Wyoming West (ftUS)",9003,4152,14938,9807,1,0,4497,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,2624666.6667,9003,8807,328083.3333,9003,,,,,,,,,,,,,
+3759,"NAD83 / Hawaii zone 3 (ftUS)",9003,4269,15138,9807,1,0,4497,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,,,,,,,,
+3760,"NAD83(HARN) / Hawaii zone 3 (ftUS)",9003,4152,15138,9807,1,0,4497,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,,,,,,,,
+3761,"NAD83(CSRS) / UTM zone 22N",9001,4617,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3762,"WGS 84 / South Georgia Lambert",9001,4326,19854,9802,1,0,4400,8821,-55,9102,8822,-37,9102,8823,-54,9110,8824,-54.45,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3763,"ETRS89 / Portugal TM06",9001,4258,19853,9807,1,0,4499,8801,39.400573,9110,8802,-8.075919,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3764,"NZGD2000 / Chatham Island Circuit 2000",9001,4167,17959,9807,1,0,4500,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,400000,9001,8807,800000,9001,,,,,,,,,,,,,
+3765,"HTRS96 / Croatia TM",9001,4761,19851,9807,1,0,4400,8801,0,9102,8802,16.5,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3766,"HTRS96 / Croatia LCC",9001,4761,19852,9802,1,0,4400,8821,0,9102,8822,16.3,9110,8823,45.55,9110,8824,43.05,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+3767,"HTRS96 / UTM zone 33N",9001,4761,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3768,"HTRS96 / UTM zone 34N",9001,4761,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3769,"Bermuda 1957 / UTM zone 20N",9001,4216,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3770,"BDA2000 / Bermuda 2000 National Grid",9001,4762,19849,9807,1,0,4400,8801,32,9110,8802,-64.45,9110,8805,1,9201,8806,550000,9001,8807,100000,9001,,,,,,,,,,,,,
+3771,"NAD27 / Alberta 3TM ref merid 111 W",9001,4267,17722,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3772,"NAD27 / Alberta 3TM ref merid 114 W",9001,4267,17723,9807,1,0,4400,8801,0,9102,8802,-114,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3773,"NAD27 / Alberta 3TM ref merid 117 W",9001,4267,17724,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3774,"NAD27 / Alberta 3TM ref merid 120 W",9001,4267,17725,9807,1,1,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9001,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3775,"NAD83 / Alberta 3TM ref merid 111 W",9001,4269,17722,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3776,"NAD83 / Alberta 3TM ref merid 114 W",9001,4269,17723,9807,1,0,4400,8801,0,9102,8802,-114,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3777,"NAD83 / Alberta 3TM ref merid 117 W",9001,4269,17724,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3778,"NAD83 / Alberta 3TM ref merid 120 W",9001,4269,17725,9807,1,1,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9001,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3779,"NAD83(CSRS) / Alberta 3TM ref merid 111 W",9001,4617,17722,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3780,"NAD83(CSRS) / Alberta 3TM ref merid 114 W",9001,4617,17723,9807,1,0,4400,8801,0,9102,8802,-114,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3781,"NAD83(CSRS) / Alberta 3TM ref merid 117 W",9001,4617,17724,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3782,"NAD83(CSRS) / Alberta 3TM ref merid 120 W",9001,4617,17725,9807,1,1,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9001,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3783,"Pitcairn 2006 / Pitcairn TM 2006",9001,4763,19848,9807,1,0,4400,8801,-25.04067894,9110,8802,-130.06466816,9110,8805,1,9201,8806,14200,9001,8807,15500,9001,,,,,,,,,,,,,
+3784,"Pitcairn 1967 / UTM zone 9S",9001,4729,16109,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3785,"Popular Visualisation CRS / Mercator",9001,4055,19847,9841,1,1,4499,8801,0,9102,8802,0,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3786,"World Equidistant Cylindrical (Sphere)",9001,4047,19968,9823,1,1,4499,8801,0,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3787,"MGI / Slovene National Grid",9001,4312,19845,9807,1,1,4498,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,500000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+3788,"NZGD2000 / Auckland Islands TM 2000",9001,4167,17960,9807,1,0,4500,8801,0,9102,8802,166,9102,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3789,"NZGD2000 / Campbell Island TM 2000",9001,4167,17961,9807,1,0,4500,8801,0,9102,8802,169,9102,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3790,"NZGD2000 / Antipodes Islands TM 2000",9001,4167,17962,9807,1,0,4500,8801,0,9102,8802,179,9102,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3791,"NZGD2000 / Raoul Island TM 2000",9001,4167,17963,9807,1,0,4500,8801,0,9102,8802,-178,9102,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3793,"NZGD2000 / Chatham Islands TM 2000",9001,4167,17965,9807,1,0,4500,8801,0,9110,8802,-176.3,9110,8805,1,9201,8806,3500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+3794,"Slovenia 1996 / Slovene National Grid",9001,4765,19845,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,500000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+3795,"NAD27 / Cuba Norte",9001,4267,18063,9802,1,0,4532,8821,22.21,9110,8822,-81,9110,8823,23,9110,8824,21.42,9110,8826,500000,9001,8827,280296.016,9001,,,,,,,,,,
+3796,"NAD27 / Cuba Sur",9001,4267,18064,9802,1,0,4532,8821,20.43,9110,8822,-76.5,9110,8823,21.18,9110,8824,20.08,9110,8826,500000,9001,8827,229126.939,9001,,,,,,,,,,
+3797,"NAD27 / MTQ Lambert",9001,4267,19844,9802,1,0,4499,8821,44,9102,8822,-70,9102,8823,50,9102,8824,46,9102,8826,800000,9001,8827,0,9001,,,,,,,,,,
+3798,"NAD83 / MTQ Lambert",9001,4269,19844,9802,1,0,4499,8821,44,9102,8822,-70,9102,8823,50,9102,8824,46,9102,8826,800000,9001,8827,0,9001,,,,,,,,,,
+3799,"NAD83(CSRS) / MTQ Lambert",9001,4617,19844,9802,1,0,4499,8821,44,9102,8822,-70,9102,8823,50,9102,8824,46,9102,8826,800000,9001,8827,0,9001,,,,,,,,,,
+3800,"NAD27 / Alberta 3TM ref merid 120 W",9001,4267,17726,9807,1,0,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3801,"NAD83 / Alberta 3TM ref merid 120 W",9001,4269,17726,9807,1,0,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3802,"NAD83(CSRS) / Alberta 3TM ref merid 120 W",9001,4617,17726,9807,1,0,4400,8801,0,9102,8802,-120,9102,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3812,"ETRS89 / Belgian Lambert 2008",9001,4258,3811,9802,1,0,4499,8821,50.4752134,9110,8822,4.2133177,9110,8823,49.5,9110,8824,51.1,9110,8826,649328,9001,8827,665262,9001,,,,,,,,,,
+3814,"NAD83 / Mississippi TM",9001,4269,3813,9807,1,0,4499,8801,32.3,9110,8802,-89.45,9110,8805,0.9998335,9201,8806,500000,9001,8807,1300000,9001,,,,,,,,,,,,,
+3815,"NAD83(HARN) / Mississippi TM",9001,4152,3813,9807,1,0,4499,8801,32.3,9110,8802,-89.45,9110,8805,0.9998335,9201,8806,500000,9001,8807,1300000,9001,,,,,,,,,,,,,
+3816,"NAD83(NSRS2007) / Mississippi TM",9001,4759,3813,9807,1,0,4499,8801,32.3,9110,8802,-89.45,9110,8805,0.9998335,9201,8806,500000,9001,8807,1300000,9001,,,,,,,,,,,,,
+3825,"TWD97 / TM2 zone 119",9001,3824,3818,9807,1,0,4499,8801,0,9102,8802,119,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+3826,"TWD97 / TM2 zone 121",9001,3824,3820,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+3827,"TWD67 / TM2 zone 119",9001,3821,3818,9807,1,0,4499,8801,0,9102,8802,119,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+3828,"TWD67 / TM2 zone 121",9001,3821,3820,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.9999,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+3829,"Hu Tzu Shan 1950 / UTM zone 51N",9001,4236,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3832,"WGS 84 / PDC Mercator",9001,4326,3831,9804,1,0,4400,8801,0,9102,8802,150,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+3833,"Pulkovo 1942(58) / Gauss-Kruger zone 2",9001,4179,16202,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+3834,"Pulkovo 1942(83) / Gauss-Kruger zone 2",9001,4178,16202,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+3835,"Pulkovo 1942(83) / Gauss-Kruger zone 3",9001,4178,16203,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+3836,"Pulkovo 1942(83) / Gauss-Kruger zone 4",9001,4178,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+3837,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 3",9001,4179,16263,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+3838,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 4",9001,4179,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+3839,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 9",9001,4179,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+3840,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 10",9001,4179,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,,,,,,,,
+3841,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 6",9001,4178,16266,9807,1,0,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+3842,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 7",9001,4178,16266,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+3843,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 8",9001,4178,16266,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+3844,"Pulkovo 1942(58) / Stereo70",9001,4179,19926,9809,1,0,4530,8801,46,9102,8802,25,9102,8805,0.99975,9201,8806,500000,9001,8807,500000,9001,,,,,,,2.329,-147.042,-92.08,0.309,-0.325,-0.497,5.69
+3845,"SWEREF99 / RT90 7.5 gon V emulation",9001,4619,17339,9807,1,0,4530,8801,0,9110,8802,11.18225,9110,8805,1.000006,9201,8806,1500025.141,9001,8807,-667.282,9001,,,,,,,,,,,,,
+3846,"SWEREF99 / RT90 5 gon V emulation",9001,4619,17340,9807,1,0,4530,8801,0,9110,8802,13.332256,9110,8805,1.0000058,9201,8806,1500044.695,9001,8807,-667.13,9001,,,,,,,,,,,,,
+3847,"SWEREF99 / RT90 2.5 gon V emulation",9001,4619,17341,9807,1,0,4530,8801,0,9110,8802,15.4822624306,9110,8805,1.00000561024,9201,8806,1500064.274,9001,8807,-667.711,9001,,,,,,,,,,,,,
+3848,"SWEREF99 / RT90 0 gon emulation",9001,4619,17342,9807,1,0,4530,8801,0,9110,8802,18.032268,9110,8805,1.0000054,9201,8806,1500083.521,9001,8807,-668.844,9001,,,,,,,,,,,,,
+3849,"SWEREF99 / RT90 2.5 gon O emulation",9001,4619,17343,9807,1,0,4530,8801,0,9110,8802,20.182274,9110,8805,1.0000052,9201,8806,1500102.765,9001,8807,-670.706,9001,,,,,,,,,,,,,
+3850,"SWEREF99 / RT90 5 gon O emulation",9001,4619,17344,9807,1,0,4530,8801,0,9110,8802,22.33228,9110,8805,1.0000049,9201,8806,1500121.846,9001,8807,-672.557,9001,,,,,,,,,,,,,
+3851,"NZGD2000 / NZCS2000",9001,4167,17964,9802,1,0,4500,8821,-41,9110,8822,173,9110,8823,-37.3,9110,8824,-44.3,9110,8826,3000000,9001,8827,7000000,9001,,,,,,,,,,
+3852,"RSRGD2000 / DGLC2000",9001,4764,17966,9802,1,0,4500,8821,-90,9110,8822,157,9110,8823,-76.4,9110,8824,-79.2,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+3854,County ST74,9001,4619,3853,9807,1,0,4531,8801,0,9110,8802,18.0328332,9110,8805,0.99999506,9201,8806,100182.7406,9001,8807,-6500620.1207,9001,,,,,,,,,,,,,
+3857,"WGS 84 / Pseudo-Mercator",9001,4326,3856,1024,1,0,4499,8801,0,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3873,"ETRS89 / GK19FIN",9001,4258,3860,9807,1,0,4500,8801,0,9102,8802,19,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+3874,"ETRS89 / GK20FIN",9001,4258,3861,9807,1,0,4500,8801,0,9102,8802,20,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,,,,,,,,
+3875,"ETRS89 / GK21FIN",9001,4258,3862,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,,,,,,,,
+3876,"ETRS89 / GK22FIN",9001,4258,3863,9807,1,0,4500,8801,0,9102,8802,22,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,,,,,,,,
+3877,"ETRS89 / GK23FIN",9001,4258,3864,9807,1,0,4500,8801,0,9102,8802,23,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,,,,,,,,
+3878,"ETRS89 / GK24FIN",9001,4258,3865,9807,1,0,4500,8801,0,9102,8802,24,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,,,,,,,,
+3879,"ETRS89 / GK25FIN",9001,4258,3866,9807,1,0,4500,8801,0,9102,8802,25,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,,,,,,,,
+3880,"ETRS89 / GK26FIN",9001,4258,3867,9807,1,0,4500,8801,0,9102,8802,26,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,,,,,,,,
+3881,"ETRS89 / GK27FIN",9001,4258,3868,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,,,,,,,,
+3882,"ETRS89 / GK28FIN",9001,4258,3869,9807,1,0,4500,8801,0,9102,8802,28,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,,,,,,,,
+3883,"ETRS89 / GK29FIN",9001,4258,3870,9807,1,0,4500,8801,0,9102,8802,29,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,,,,,,,,
+3884,"ETRS89 / GK30FIN",9001,4258,3871,9807,1,0,4500,8801,0,9102,8802,30,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,,,,,,,,
+3885,"ETRS89 / GK31FIN",9001,4258,3872,9807,1,0,4500,8801,0,9102,8802,31,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+3890,"IGRS / UTM zone 37N",9001,3889,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3891,"IGRS / UTM zone 38N",9001,3889,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3892,"IGRS / UTM zone 39N",9001,3889,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3893,"ED50 / Iraq National Grid",9001,4230,19907,9807,1,0,4400,8801,29.0134566,9110,8802,46.3,9110,8805,0.9994,9201,8806,800000,9001,8807,0,9001,,,,,,,,,,,,,
+3907,"MGI 1901 / Balkans zone 5",9001,3906,18275,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+3908,"MGI 1901 / Balkans zone 6",9001,3906,18276,9807,1,0,4530,8801,0,9102,8802,18,9102,8805,0.9999,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+3909,"MGI 1901 / Balkans zone 7",9001,3906,18277,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+3910,"MGI 1901 / Balkans zone 8",9001,3906,18278,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+3911,"MGI 1901 / Slovenia Grid",9001,3906,19967,9807,1,0,4530,8801,0,9110,8802,15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3912,"MGI 1901 / Slovene National Grid",9001,3906,19845,9807,1,0,4498,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,500000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+3920,"Puerto Rico / UTM zone 20N",9001,4139,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+3942,"RGF93 / CC42",9001,4171,18101,9802,1,0,4499,8821,42,9102,8822,3,9102,8823,41.25,9102,8824,42.75,9102,8826,1700000,9001,8827,1200000,9001,,,,,,,,,,
+3943,"RGF93 / CC43",9001,4171,18102,9802,1,0,4499,8821,43,9102,8822,3,9102,8823,42.25,9102,8824,43.75,9102,8826,1700000,9001,8827,2200000,9001,,,,,,,,,,
+3944,"RGF93 / CC44",9001,4171,18103,9802,1,0,4499,8821,44,9102,8822,3,9102,8823,43.25,9102,8824,44.75,9102,8826,1700000,9001,8827,3200000,9001,,,,,,,,,,
+3945,"RGF93 / CC45",9001,4171,18104,9802,1,0,4499,8821,45,9102,8822,3,9102,8823,44.25,9102,8824,45.75,9102,8826,1700000,9001,8827,4200000,9001,,,,,,,,,,
+3946,"RGF93 / CC46",9001,4171,18105,9802,1,0,4499,8821,46,9102,8822,3,9102,8823,45.25,9102,8824,46.75,9102,8826,1700000,9001,8827,5200000,9001,,,,,,,,,,
+3947,"RGF93 / CC47",9001,4171,18106,9802,1,0,4499,8821,47,9102,8822,3,9102,8823,46.25,9102,8824,47.75,9102,8826,1700000,9001,8827,6200000,9001,,,,,,,,,,
+3948,"RGF93 / CC48",9001,4171,18107,9802,1,0,4499,8821,48,9102,8822,3,9102,8823,47.25,9102,8824,48.75,9102,8826,1700000,9001,8827,7200000,9001,,,,,,,,,,
+3949,"RGF93 / CC49",9001,4171,18108,9802,1,0,4499,8821,49,9102,8822,3,9102,8823,48.25,9102,8824,49.75,9102,8826,1700000,9001,8827,8200000,9001,,,,,,,,,,
+3950,"RGF93 / CC50",9001,4171,18109,9802,1,0,4499,8821,50,9102,8822,3,9102,8823,49.25,9102,8824,50.75,9102,8826,1700000,9001,8827,9200000,9001,,,,,,,,,,
+3968,"NAD83 / Virginia Lambert",9001,4269,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3969,"NAD83(HARN) / Virginia Lambert",9001,4152,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3970,"NAD83(NSRS2007) / Virginia Lambert",9001,4759,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3973,"WGS 84 / NSIDC EASE-Grid North",9001,4326,3897,1027,1,1,4469,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3974,"WGS 84 / NSIDC EASE-Grid South",9001,4326,3898,1027,1,1,4470,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+3975,"WGS 84 / NSIDC EASE-Grid Global",9001,4326,19869,9834,1,1,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,,,,,,,,
+3976,"WGS 84 / NSIDC Sea Ice Polar Stereographic South",9001,4326,19866,9829,1,0,4470,8806,0,9001,8807,0,9001,8832,-70,9102,8833,0,9102,,,,,,,,,,,,,,,,
+3978,"NAD83 / Canada Atlas Lambert",9001,4269,3977,9802,1,0,4400,8821,49,9102,8822,-95,9102,8823,49,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3979,"NAD83(CSRS) / Canada Atlas Lambert",9001,4617,3977,9802,1,0,4400,8821,49,9102,8822,-95,9102,8823,49,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+3985,"Katanga 1955 / Katanga Lambert",9001,4695,3980,9802,1,1,4499,8821,9,9102,8822,26,9102,8823,-6.5,9102,8824,-11.5,9102,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+3986,"Katanga 1955 / Katanga Gauss zone A",9001,4695,3981,9807,1,0,4499,8801,-9,9102,8802,30,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+3987,"Katanga 1955 / Katanga Gauss zone B",9001,4695,3982,9807,1,0,4499,8801,-9,9102,8802,28,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+3988,"Katanga 1955 / Katanga Gauss zone C",9001,4695,3983,9807,1,0,4499,8801,-9,9102,8802,26,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+3989,"Katanga 1955 / Katanga Gauss zone D",9001,4695,3984,9807,1,0,4499,8801,-9,9102,8802,24,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+3991,Puerto Rico State Plane CS of 1927,9003,4139,15201,9802,1,0,4497,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,500000,9003,8827,0,9003,,,,,,,,,,
+3992,"Puerto Rico / St. Croix",9003,4139,15202,9802,1,0,4497,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,500000,9003,8827,100000,9003,,,,,,,,,,
+3993,"Guam 1963 / Guam SPCS",9001,4675,15400,9831,1,0,4499,8801,13.282087887,9110,8802,144.445550254,9110,8806,50000,9001,8807,50000,9001,,,,,,,,,,,,,,,,
+3994,"WGS 84 / Mercator 41",9001,4326,19843,9805,1,0,4499,8802,100,9102,8806,0,9001,8807,0,9001,8823,-41,9102,,,,,,,,,,,,,,,,
+3995,"WGS 84 / Arctic Polar Stereographic",9001,4326,19842,9829,1,0,4469,8806,0,9001,8807,0,9001,8832,71,9102,8833,0,9102,,,,,,,,,,,,,,,,
+3996,"WGS 84 / IBCAO Polar Stereographic",9001,4326,19840,9829,1,0,4469,8806,0,9001,8807,0,9001,8832,75,9102,8833,0,9102,,,,,,,,,,,,,,,,
+3997,"WGS 84 / Dubai Local TM",9001,4326,19839,9807,1,0,4400,8801,0,9110,8802,55.2,9110,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4026,"MOLDREF99 / Moldova TM",9001,4023,3999,9807,1,0,4530,8801,0,9110,8802,28.24,9110,8805,0.99994,9201,8806,200000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+4037,"WGS 84 / TMzn35N",9001,4326,16035,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4038,"WGS 84 / TMzn36N",9001,4326,16036,9807,1,0,4500,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4048,"RGRDC 2005 / Congo TM zone 12",9001,4046,17412,9807,1,0,4499,8801,0,9102,8802,12,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4049,"RGRDC 2005 / Congo TM zone 14",9001,4046,17414,9807,1,0,4499,8801,0,9102,8802,14,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4050,"RGRDC 2005 / Congo TM zone 16",9001,4046,17416,9807,1,0,4499,8801,0,9102,8802,16,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4051,"RGRDC 2005 / Congo TM zone 18",9001,4046,17418,9807,1,0,4499,8801,0,9102,8802,18,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4056,"RGRDC 2005 / Congo TM zone 20",9001,4046,17420,9807,1,0,4499,8801,0,9102,8802,20,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4057,"RGRDC 2005 / Congo TM zone 22",9001,4046,17422,9807,1,0,4499,8801,0,9102,8802,22,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4058,"RGRDC 2005 / Congo TM zone 24",9001,4046,17424,9807,1,0,4499,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4059,"RGRDC 2005 / Congo TM zone 26",9001,4046,17426,9807,1,0,4499,8801,0,9102,8802,26,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4060,"RGRDC 2005 / Congo TM zone 28",9001,4046,17428,9807,1,0,4499,8801,0,9102,8802,28,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4061,"RGRDC 2005 / UTM zone 33S",9001,4046,16133,9807,1,0,4499,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4062,"RGRDC 2005 / UTM zone 34S",9001,4046,16134,9807,1,0,4499,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4063,"RGRDC 2005 / UTM zone 35S",9001,4046,16135,9807,1,0,4499,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4071,"Chua / UTM zone 23S",9001,4224,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4082,"REGCAN95 / UTM zone 27N",9001,4081,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4083,"REGCAN95 / UTM zone 28N",9001,4081,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4087,"WGS 84 / World Equidistant Cylindrical",9001,4326,4085,1028,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,0,9102,,,,,,,,,,,,,,,,
+4088,"World Equidistant Cylindrical (Sphere)",9001,4047,4086,1029,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,0,9102,,,,,,,,,,,,,,,,
+4093,"ETRS89 / DKTM1",9001,4258,4089,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.99998,9201,8806,200000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+4094,"ETRS89 / DKTM2",9001,4258,4090,9807,1,0,4400,8801,0,9102,8802,10,9102,8805,0.99998,9201,8806,400000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+4095,"ETRS89 / DKTM3",9001,4258,4091,9807,1,0,4400,8801,0,9102,8802,11.75,9102,8805,0.99998,9201,8806,600000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+4096,"ETRS89 / DKTM4",9001,4258,4092,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,800000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+4217,"NAD83 / BLM 59N (ftUS)",9003,4269,4186,9807,1,0,4497,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4390,"Kertau 1968 / Johor Grid",9001,4245,4114,9806,1,0,4400,8801,2.02333,9110,8802,103.334593,9110,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+4391,"Kertau 1968 / Sembilan and Melaka Grid",9001,4245,4115,9806,1,0,4400,8801,2.424422,9110,8802,101.56282,9110,8806,-242.005,9001,8807,-948.547,9001,,,,,,,,,,,,,,,,
+4392,"Kertau 1968 / Pahang Grid",9001,4245,4116,9806,1,0,4400,8801,3.42395,9110,8802,102.261024,9110,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+4393,"Kertau 1968 / Selangor Grid",9001,4245,4117,9806,1,0,4400,8801,3.404924,9110,8802,101.302968,9110,8806,-21759.438,9001,8807,55960.906,9001,,,,,,,,,,,,,,,,
+4394,"Kertau 1968 / Terengganu Grid",9001,4245,4177,9806,1,0,4400,8801,4.564611,9110,8802,102.534275,9110,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+4395,"Kertau 1968 / Pinang Grid",9001,4245,4305,9806,1,0,4400,8801,5.251677,9110,8802,100.204513,9110,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+4396,"Kertau 1968 / Kedah and Perlis Grid",9001,4245,4320,9806,1,0,4400,8801,5.575453,9110,8802,100.381534,9110,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+4397,"Kertau 1968 / Perak Revised Grid",9001,4245,4321,9806,1,0,4400,8801,4.513377,9110,8802,100.490036,9110,8806,0,9001,8807,133453.669,9001,,,,,,,,,,,,,,,,
+4398,"Kertau 1968 / Kelantan Grid",9001,4245,4323,9806,1,0,4400,8801,5.533812,9110,8802,102.103825,9110,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+4399,"NAD27 / BLM 59N (ftUS)",9003,4267,4186,9807,1,0,4497,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4400,"NAD27 / BLM 60N (ftUS)",9003,4267,4187,9807,1,0,4497,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4401,"NAD27 / BLM 1N (ftUS)",9003,4267,4101,9807,1,0,4497,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4402,"NAD27 / BLM 2N (ftUS)",9003,4267,4102,9807,1,0,4497,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4403,"NAD27 / BLM 3N (ftUS)",9003,4267,4103,9807,1,0,4497,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4404,"NAD27 / BLM 4N (ftUS)",9003,4267,4104,9807,1,0,4497,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4405,"NAD27 / BLM 5N (ftUS)",9003,4267,4105,9807,1,0,4497,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4406,"NAD27 / BLM 6N (ftUS)",9003,4267,4106,9807,1,0,4497,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4407,"NAD27 / BLM 7N (ftUS)",9003,4267,4107,9807,1,0,4497,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4408,"NAD27 / BLM 8N (ftUS)",9003,4267,4108,9807,1,0,4497,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4409,"NAD27 / BLM 9N (ftUS)",9003,4267,4109,9807,1,0,4497,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4410,"NAD27 / BLM 10N (ftUS)",9003,4267,4110,9807,1,0,4497,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4411,"NAD27 / BLM 11N (ftUS)",9003,4267,4111,9807,1,0,4497,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4412,"NAD27 / BLM 12N (ftUS)",9003,4267,4112,9807,1,0,4497,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4413,"NAD27 / BLM 13N (ftUS)",9003,4267,4113,9807,1,0,4497,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4414,"NAD83(HARN) / Guam Map Grid",9001,4152,4325,9807,1,0,4499,8801,13.3,9110,8802,144.45,9110,8805,1,9201,8806,100000,9001,8807,200000,9001,,,,,,,,,,,,,
+4415,"Katanga 1955 / Katanga Lambert",9001,4695,4416,9802,1,0,4499,8821,-9,9102,8822,26,9102,8823,-6.5,9102,8824,-11.5,9102,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+4417,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 7",9001,4178,16267,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+4418,"NAD27 / BLM 18N (ftUS)",9003,4267,4118,9807,1,0,4497,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4419,"NAD27 / BLM 19N (ftUS)",9003,4267,4119,9807,1,0,4497,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4420,"NAD83 / BLM 60N (ftUS)",9003,4269,4187,9807,1,0,4497,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4421,"NAD83 / BLM 1N (ftUS)",9003,4269,4101,9807,1,0,4497,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4422,"NAD83 / BLM 2N (ftUS)",9003,4269,4102,9807,1,0,4497,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4423,"NAD83 / BLM 3N (ftUS)",9003,4269,4103,9807,1,0,4497,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4424,"NAD83 / BLM 4N (ftUS)",9003,4269,4104,9807,1,0,4497,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4425,"NAD83 / BLM 5N (ftUS)",9003,4269,4105,9807,1,0,4497,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4426,"NAD83 / BLM 6N (ftUS)",9003,4269,4106,9807,1,0,4497,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4427,"NAD83 / BLM 7N (ftUS)",9003,4269,4107,9807,1,0,4497,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4428,"NAD83 / BLM 8N (ftUS)",9003,4269,4108,9807,1,0,4497,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4429,"NAD83 / BLM 9N (ftUS)",9003,4269,4109,9807,1,0,4497,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4430,"NAD83 / BLM 10N (ftUS)",9003,4269,4110,9807,1,0,4497,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4431,"NAD83 / BLM 11N (ftUS)",9003,4269,4111,9807,1,0,4497,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4432,"NAD83 / BLM 12N (ftUS)",9003,4269,4112,9807,1,0,4497,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4433,"NAD83 / BLM 13N (ftUS)",9003,4269,4113,9807,1,0,4497,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4434,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 8",9001,4178,16268,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+4437,"NAD83(NSRS2007) / Puerto Rico and Virgin Is.",9001,4759,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,,,,,,,,
+4438,"NAD83 / BLM 18N (ftUS)",9003,4269,4118,9807,1,0,4497,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4439,"NAD83 / BLM 19N (ftUS)",9003,4269,4119,9807,1,0,4497,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+4455,"NAD27 / Pennsylvania South",9003,4267,4436,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+4456,"NAD27 / New York Long Island",9003,4267,4454,9802,1,0,4497,8821,40.3,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,2000000,9003,8827,100000,9003,,,,,,,,,,
+4457,"NAD83 / South Dakota North (ftUS)",9003,4269,15394,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+4462,"WGS 84 / Australian Centre for Remote Sensing Lambert",9001,4326,4460,9802,1,0,4400,8821,-27,9102,8822,132,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+4467,"RGSPM06 / UTM zone 21N",9001,4463,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4471,"RGM04 / UTM zone 38S",9001,4470,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4474,"Cadastre 1997 / UTM zone 38S",9001,4632,16138,9807,1,1,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+4484,"Mexico ITRF92 / UTM zone 11N",9001,4483,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4485,"Mexico ITRF92 / UTM zone 12N",9001,4483,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4486,"Mexico ITRF92 / UTM zone 13N",9001,4483,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4487,"Mexico ITRF92 / UTM zone 14N",9001,4483,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4488,"Mexico ITRF92 / UTM zone 15N",9001,4483,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4489,"Mexico ITRF92 / UTM zone 16N",9001,4483,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4491,"CGCS2000 / Gauss-Kruger zone 13",9001,4490,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+4492,"CGCS2000 / Gauss-Kruger zone 14",9001,4490,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+4493,"CGCS2000 / Gauss-Kruger zone 15",9001,4490,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+4494,"CGCS2000 / Gauss-Kruger zone 16",9001,4490,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,,,,,,,,
+4495,"CGCS2000 / Gauss-Kruger zone 17",9001,4490,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,,,,,,,,
+4496,"CGCS2000 / Gauss-Kruger zone 18",9001,4490,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,,,,,,,,
+4497,"CGCS2000 / Gauss-Kruger zone 19",9001,4490,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+4498,"CGCS2000 / Gauss-Kruger zone 20",9001,4490,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,,,,,,,,
+4499,"CGCS2000 / Gauss-Kruger zone 21",9001,4490,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,,,,,,,,
+4500,"CGCS2000 / Gauss-Kruger zone 22",9001,4490,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,,,,,,,,
+4501,"CGCS2000 / Gauss-Kruger zone 23",9001,4490,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,,,,,,,,
+4502,"CGCS2000 / Gauss-Kruger CM 75E",9001,4490,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4503,"CGCS2000 / Gauss-Kruger CM 81E",9001,4490,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4504,"CGCS2000 / Gauss-Kruger CM 87E",9001,4490,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4505,"CGCS2000 / Gauss-Kruger CM 93E",9001,4490,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4506,"CGCS2000 / Gauss-Kruger CM 99E",9001,4490,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4507,"CGCS2000 / Gauss-Kruger CM 105E",9001,4490,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4508,"CGCS2000 / Gauss-Kruger CM 111E",9001,4490,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4509,"CGCS2000 / Gauss-Kruger CM 117E",9001,4490,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4510,"CGCS2000 / Gauss-Kruger CM 123E",9001,4490,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4511,"CGCS2000 / Gauss-Kruger CM 129E",9001,4490,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4512,"CGCS2000 / Gauss-Kruger CM 135E",9001,4490,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4513,"CGCS2000 / 3-degree Gauss-Kruger zone 25",9001,4490,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,,,,,,,,
+4514,"CGCS2000 / 3-degree Gauss-Kruger zone 26",9001,4490,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,,,,,,,,
+4515,"CGCS2000 / 3-degree Gauss-Kruger zone 27",9001,4490,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,,,,,,,,
+4516,"CGCS2000 / 3-degree Gauss-Kruger zone 28",9001,4490,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,,,,,,,,
+4517,"CGCS2000 / 3-degree Gauss-Kruger zone 29",9001,4490,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,,,,,,,,
+4518,"CGCS2000 / 3-degree Gauss-Kruger zone 30",9001,4490,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,,,,,,,,
+4519,"CGCS2000 / 3-degree Gauss-Kruger zone 31",9001,4490,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+4520,"CGCS2000 / 3-degree Gauss-Kruger zone 32",9001,4490,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+4521,"CGCS2000 / 3-degree Gauss-Kruger zone 33",9001,4490,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,,,,,,,,
+4522,"CGCS2000 / 3-degree Gauss-Kruger zone 34",9001,4490,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,,,,,,,,
+4523,"CGCS2000 / 3-degree Gauss-Kruger zone 35",9001,4490,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,,,,,,,,
+4524,"CGCS2000 / 3-degree Gauss-Kruger zone 36",9001,4490,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,,,,,,,,
+4525,"CGCS2000 / 3-degree Gauss-Kruger zone 37",9001,4490,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,,,,,,,,
+4526,"CGCS2000 / 3-degree Gauss-Kruger zone 38",9001,4490,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,,,,,,,,
+4527,"CGCS2000 / 3-degree Gauss-Kruger zone 39",9001,4490,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,,,,,,,,
+4528,"CGCS2000 / 3-degree Gauss-Kruger zone 40",9001,4490,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,,,,,,,,
+4529,"CGCS2000 / 3-degree Gauss-Kruger zone 41",9001,4490,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,,,,,,,,
+4530,"CGCS2000 / 3-degree Gauss-Kruger zone 42",9001,4490,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,,,,,,,,
+4531,"CGCS2000 / 3-degree Gauss-Kruger zone 43",9001,4490,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,,,,,,,,
+4532,"CGCS2000 / 3-degree Gauss-Kruger zone 44",9001,4490,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,,,,,,,,
+4533,"CGCS2000 / 3-degree Gauss-Kruger zone 45",9001,4490,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,,,,,,,,
+4534,"CGCS2000 / 3-degree Gauss-Kruger CM 75E",9001,4490,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4535,"CGCS2000 / 3-degree Gauss-Kruger CM 78E",9001,4490,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4536,"CGCS2000 / 3-degree Gauss-Kruger CM 81E",9001,4490,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4537,"CGCS2000 / 3-degree Gauss-Kruger CM 84E",9001,4490,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4538,"CGCS2000 / 3-degree Gauss-Kruger CM 87E",9001,4490,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4539,"CGCS2000 / 3-degree Gauss-Kruger CM 90E",9001,4490,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4540,"CGCS2000 / 3-degree Gauss-Kruger CM 93E",9001,4490,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4541,"CGCS2000 / 3-degree Gauss-Kruger CM 96E",9001,4490,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4542,"CGCS2000 / 3-degree Gauss-Kruger CM 99E",9001,4490,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4543,"CGCS2000 / 3-degree Gauss-Kruger CM 102E",9001,4490,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4544,"CGCS2000 / 3-degree Gauss-Kruger CM 105E",9001,4490,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4545,"CGCS2000 / 3-degree Gauss-Kruger CM 108E",9001,4490,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4546,"CGCS2000 / 3-degree Gauss-Kruger CM 111E",9001,4490,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4547,"CGCS2000 / 3-degree Gauss-Kruger CM 114E",9001,4490,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4548,"CGCS2000 / 3-degree Gauss-Kruger CM 117E",9001,4490,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4549,"CGCS2000 / 3-degree Gauss-Kruger CM 120E",9001,4490,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4550,"CGCS2000 / 3-degree Gauss-Kruger CM 123E",9001,4490,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4551,"CGCS2000 / 3-degree Gauss-Kruger CM 126E",9001,4490,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4552,"CGCS2000 / 3-degree Gauss-Kruger CM 129E",9001,4490,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4553,"CGCS2000 / 3-degree Gauss-Kruger CM 132E",9001,4490,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4554,"CGCS2000 / 3-degree Gauss-Kruger CM 135E",9001,4490,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4559,"RRAF 1991 / UTM zone 20N",9001,4558,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4568,"New Beijing / Gauss-Kruger zone 13",9001,4555,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+4569,"New Beijing / Gauss-Kruger zone 14",9001,4555,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+4570,"New Beijing / Gauss-Kruger zone 15",9001,4555,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+4571,"New Beijing / Gauss-Kruger zone 16",9001,4555,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,,,,,,,,
+4572,"New Beijing / Gauss-Kruger zone 17",9001,4555,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,,,,,,,,
+4573,"New Beijing / Gauss-Kruger zone 18",9001,4555,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,,,,,,,,
+4574,"New Beijing / Gauss-Kruger zone 19",9001,4555,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+4575,"New Beijing / Gauss-Kruger zone 20",9001,4555,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,,,,,,,,
+4576,"New Beijing / Gauss-Kruger zone 21",9001,4555,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,,,,,,,,
+4577,"New Beijing / Gauss-Kruger zone 22",9001,4555,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,,,,,,,,
+4578,"New Beijing / Gauss-Kruger zone 23",9001,4555,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,,,,,,,,
+4579,"New Beijing / Gauss-Kruger CM 75E",9001,4555,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4580,"New Beijing / Gauss-Kruger CM 81E",9001,4555,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4581,"New Beijing / Gauss-Kruger CM 87E",9001,4555,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4582,"New Beijing / Gauss-Kruger CM 93E",9001,4555,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4583,"New Beijing / Gauss-Kruger CM 99E",9001,4555,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4584,"New Beijing / Gauss-Kruger CM 105E",9001,4555,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4585,"New Beijing / Gauss-Kruger CM 111E",9001,4555,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4586,"New Beijing / Gauss-Kruger CM 117E",9001,4555,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4587,"New Beijing / Gauss-Kruger CM 123E",9001,4555,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4588,"New Beijing / Gauss-Kruger CM 129E",9001,4555,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4589,"New Beijing / Gauss-Kruger CM 135E",9001,4555,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4647,"ETRS89 / UTM zone 32N (zE-N)",9001,4258,4648,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+4652,"New Beijing / 3-degree Gauss-Kruger zone 25",9001,4555,16285,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,,,,,,,,
+4653,"New Beijing / 3-degree Gauss-Kruger zone 26",9001,4555,16286,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,,,,,,,,
+4654,"New Beijing / 3-degree Gauss-Kruger zone 27",9001,4555,16287,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,,,,,,,,
+4655,"New Beijing / 3-degree Gauss-Kruger zone 28",9001,4555,16288,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,,,,,,,,
+4656,"New Beijing / 3-degree Gauss-Kruger zone 29",9001,4555,16289,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,,,,,,,,
+4766,"New Beijing / 3-degree Gauss-Kruger zone 30",9001,4555,16290,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,,,,,,,,
+4767,"New Beijing / 3-degree Gauss-Kruger zone 31",9001,4555,16291,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+4768,"New Beijing / 3-degree Gauss-Kruger zone 32",9001,4555,16292,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+4769,"New Beijing / 3-degree Gauss-Kruger zone 33",9001,4555,16293,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,33500000,9001,8807,0,9001,,,,,,,,,,,,,
+4770,"New Beijing / 3-degree Gauss-Kruger zone 34",9001,4555,16294,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,34500000,9001,8807,0,9001,,,,,,,,,,,,,
+4771,"New Beijing / 3-degree Gauss-Kruger zone 35",9001,4555,16295,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,35500000,9001,8807,0,9001,,,,,,,,,,,,,
+4772,"New Beijing / 3-degree Gauss-Kruger zone 36",9001,4555,16296,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,36500000,9001,8807,0,9001,,,,,,,,,,,,,
+4773,"New Beijing / 3-degree Gauss-Kruger zone 37",9001,4555,16297,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,37500000,9001,8807,0,9001,,,,,,,,,,,,,
+4774,"New Beijing / 3-degree Gauss-Kruger zone 38",9001,4555,16298,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,38500000,9001,8807,0,9001,,,,,,,,,,,,,
+4775,"New Beijing / 3-degree Gauss-Kruger zone 39",9001,4555,16299,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,39500000,9001,8807,0,9001,,,,,,,,,,,,,
+4776,"New Beijing / 3-degree Gauss-Kruger zone 40",9001,4555,16070,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,40500000,9001,8807,0,9001,,,,,,,,,,,,,
+4777,"New Beijing / 3-degree Gauss-Kruger zone 41",9001,4555,16071,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,41500000,9001,8807,0,9001,,,,,,,,,,,,,
+4778,"New Beijing / 3-degree Gauss-Kruger zone 42",9001,4555,16072,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,42500000,9001,8807,0,9001,,,,,,,,,,,,,
+4779,"New Beijing / 3-degree Gauss-Kruger zone 43",9001,4555,16073,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,43500000,9001,8807,0,9001,,,,,,,,,,,,,
+4780,"New Beijing / 3-degree Gauss-Kruger zone 44",9001,4555,16074,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,44500000,9001,8807,0,9001,,,,,,,,,,,,,
+4781,"New Beijing / 3-degree Gauss-Kruger zone 45",9001,4555,16075,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,45500000,9001,8807,0,9001,,,,,,,,,,,,,
+4782,"New Beijing / 3-degree Gauss-Kruger CM 75E",9001,4555,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4783,"New Beijing / 3-degree Gauss-Kruger CM 78E",9001,4555,16386,9807,1,0,4530,8801,0,9102,8802,78,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4784,"New Beijing / 3-degree Gauss-Kruger CM 81E",9001,4555,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4785,"New Beijing / 3-degree Gauss-Kruger CM 84E",9001,4555,16388,9807,1,0,4530,8801,0,9102,8802,84,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4786,"New Beijing / 3-degree Gauss-Kruger CM 87E",9001,4555,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4787,"New Beijing / 3-degree Gauss-Kruger CM 90E",9001,4555,16390,9807,1,0,4530,8801,0,9102,8802,90,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4788,"New Beijing / 3-degree Gauss-Kruger CM 93E",9001,4555,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4789,"New Beijing / 3-degree Gauss-Kruger CM 96E",9001,4555,16392,9807,1,0,4530,8801,0,9102,8802,96,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4790,"New Beijing / 3-degree Gauss-Kruger CM 99E",9001,4555,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4791,"New Beijing / 3-degree Gauss-Kruger CM 102E",9001,4555,16394,9807,1,0,4530,8801,0,9102,8802,102,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4792,"New Beijing / 3-degree Gauss-Kruger CM 105E",9001,4555,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4793,"New Beijing / 3-degree Gauss-Kruger CM 108E",9001,4555,16396,9807,1,0,4530,8801,0,9102,8802,108,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4794,"New Beijing / 3-degree Gauss-Kruger CM 111E",9001,4555,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4795,"New Beijing / 3-degree Gauss-Kruger CM 114E",9001,4555,16398,9807,1,0,4530,8801,0,9102,8802,114,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4796,"New Beijing / 3-degree Gauss-Kruger CM 117E",9001,4555,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4797,"New Beijing / 3-degree Gauss-Kruger CM 120E",9001,4555,16170,9807,1,0,4530,8801,0,9102,8802,120,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4798,"New Beijing / 3-degree Gauss-Kruger CM 123E",9001,4555,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4799,"New Beijing / 3-degree Gauss-Kruger CM 126E",9001,4555,16172,9807,1,0,4530,8801,0,9102,8802,126,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4800,"New Beijing / 3-degree Gauss-Kruger CM 129E",9001,4555,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4812,"New Beijing / 3-degree Gauss-Kruger CM 132E",9001,4555,16174,9807,1,0,4530,8801,0,9102,8802,132,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4822,"New Beijing / 3-degree Gauss-Kruger CM 135E",9001,4555,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+4826,"WGS 84 / Cape Verde National",9001,4326,4825,9802,1,0,1024,8821,15.5,9110,8822,-24,9110,8823,15,9110,8824,16.4,9110,8826,161587.83,9001,8827,128511.202,9001,,,,,,,,,,
+4839,"ETRS89 / LCC Germany (N-E)",9001,4258,4838,9802,1,0,4500,8821,51,9102,8822,10.3,9110,8823,48.4,9110,8824,53.4,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+4855,"ETRS89 / NTM zone 5",9001,4258,4845,9807,1,1,4500,8801,0,9110,8802,5.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4856,"ETRS89 / NTM zone 6",9001,4258,4846,9807,1,1,4500,8801,0,9110,8802,6.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4857,"ETRS89 / NTM zone 7",9001,4258,4847,9807,1,1,4500,8801,0,9110,8802,7.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4858,"ETRS89 / NTM zone 8",9001,4258,4848,9807,1,1,4500,8801,0,9110,8802,8.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4859,"ETRS89 / NTM zone 9",9001,4258,4849,9807,1,1,4500,8801,0,9110,8802,9.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4860,"ETRS89 / NTM zone 10",9001,4258,4850,9807,1,1,4500,8801,0,9110,8802,10.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4861,"ETRS89 / NTM zone 11",9001,4258,4851,9807,1,1,4500,8801,0,9110,8802,11.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4862,"ETRS89 / NTM zone 12",9001,4258,4852,9807,1,1,4500,8801,0,9110,8802,12.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4863,"ETRS89 / NTM zone 13",9001,4258,4853,9807,1,1,4500,8801,0,9110,8802,13.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4864,"ETRS89 / NTM zone 14",9001,4258,4854,9807,1,1,4500,8801,0,9110,8802,14.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4865,"ETRS89 / NTM zone 15",9001,4258,4841,9807,1,1,4500,8801,0,9110,8802,15.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4866,"ETRS89 / NTM zone 16",9001,4258,4842,9807,1,1,4500,8801,0,9110,8802,16.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4867,"ETRS89 / NTM zone 17",9001,4258,4843,9807,1,1,4500,8801,0,9110,8802,17.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4868,"ETRS89 / NTM zone 18",9001,4258,4844,9807,1,1,4500,8801,0,9110,8802,18.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4869,"ETRS89 / NTM zone 19",9001,4258,4881,9807,1,1,4500,8801,0,9110,8802,19.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4870,"ETRS89 / NTM zone 20",9001,4258,5000,9807,1,1,4500,8801,0,9110,8802,20.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4871,"ETRS89 / NTM zone 21",9001,4258,5001,9807,1,1,4500,8801,0,9110,8802,21.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4872,"ETRS89 / NTM zone 22",9001,4258,5002,9807,1,1,4500,8801,0,9110,8802,22.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4873,"ETRS89 / NTM zone 23",9001,4258,5003,9807,1,1,4500,8801,0,9110,8802,23.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4874,"ETRS89 / NTM zone 24",9001,4258,5004,9807,1,1,4500,8801,0,9110,8802,24.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4875,"ETRS89 / NTM zone 25",9001,4258,5005,9807,1,1,4500,8801,0,9110,8802,25.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4876,"ETRS89 / NTM zone 26",9001,4258,5006,9807,1,1,4500,8801,0,9110,8802,26.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4877,"ETRS89 / NTM zone 27",9001,4258,5007,9807,1,1,4500,8801,0,9110,8802,27.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4878,"ETRS89 / NTM zone 28",9001,4258,5008,9807,1,1,4500,8801,0,9110,8802,28.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4879,"ETRS89 / NTM zone 29",9001,4258,5009,9807,1,1,4500,8801,0,9110,8802,29.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+4880,"ETRS89 / NTM zone 30",9001,4258,5010,9807,1,1,4500,8801,0,9110,8802,30.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5014,"PTRA08 / UTM zone 25N",9001,5013,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5015,"PTRA08 / UTM zone 26N",9001,5013,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5016,"PTRA08 / UTM zone 28N",9001,5013,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5017,"Lisbon 1890 / Portugal Bonne New",9001,4666,5019,9828,1,0,6509,8801,39.4,9110,8802,-8.0754862,9110,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+5018,"Lisbon / Portuguese Grid New",9001,4207,5020,9807,1,0,4499,8801,39.4,9110,8802,-8.0754862,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+5041,"WGS 84 / UPS North (E,N)",9001,4326,16061,9810,1,0,1026,8801,90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+5042,"WGS 84 / UPS South (E,N)",9001,4326,16161,9810,1,0,1027,8801,-90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+5048,"ETRS89 / TM35FIN(N,E)",9001,4258,16065,9807,1,0,4500,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5069,"NAD27 / Conus Albers",9001,4267,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+5070,"NAD83 / Conus Albers",9001,4269,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+5071,"NAD83(HARN) / Conus Albers",9001,4152,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+5072,"NAD83(NSRS2007) / Conus Albers",9001,4759,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+5105,"ETRS89 / NTM zone 5",9001,4258,5135,9807,1,0,4500,8801,58,9110,8802,5.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5106,"ETRS89 / NTM zone 6",9001,4258,5136,9807,1,0,4500,8801,58,9110,8802,6.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5107,"ETRS89 / NTM zone 7",9001,4258,5137,9807,1,0,4500,8801,58,9110,8802,7.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5108,"ETRS89 / NTM zone 8",9001,4258,5138,9807,1,0,4500,8801,58,9110,8802,8.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5109,"ETRS89 / NTM zone 9",9001,4258,5139,9807,1,0,4500,8801,58,9110,8802,9.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5110,"ETRS89 / NTM zone 10",9001,4258,5140,9807,1,0,4500,8801,58,9110,8802,10.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5111,"ETRS89 / NTM zone 11",9001,4258,5141,9807,1,0,4500,8801,58,9110,8802,11.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5112,"ETRS89 / NTM zone 12",9001,4258,5142,9807,1,0,4500,8801,58,9110,8802,12.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5113,"ETRS89 / NTM zone 13",9001,4258,5143,9807,1,0,4500,8801,58,9110,8802,13.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5114,"ETRS89 / NTM zone 14",9001,4258,5144,9807,1,0,4500,8801,58,9110,8802,14.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5115,"ETRS89 / NTM zone 15",9001,4258,5145,9807,1,0,4500,8801,58,9110,8802,15.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5116,"ETRS89 / NTM zone 16",9001,4258,5146,9807,1,0,4500,8801,58,9110,8802,16.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5117,"ETRS89 / NTM zone 17",9001,4258,5147,9807,1,0,4500,8801,58,9110,8802,17.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5118,"ETRS89 / NTM zone 18",9001,4258,5148,9807,1,0,4500,8801,58,9110,8802,18.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5119,"ETRS89 / NTM zone 19",9001,4258,5149,9807,1,0,4500,8801,58,9110,8802,19.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5120,"ETRS89 / NTM zone 20",9001,4258,5150,9807,1,0,4500,8801,58,9110,8802,20.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5121,"ETRS89 / NTM zone 21",9001,4258,5151,9807,1,0,4500,8801,58,9110,8802,21.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5122,"ETRS89 / NTM zone 22",9001,4258,5152,9807,1,0,4500,8801,58,9110,8802,22.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5123,"ETRS89 / NTM zone 23",9001,4258,5153,9807,1,0,4500,8801,58,9110,8802,23.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5124,"ETRS89 / NTM zone 24",9001,4258,5154,9807,1,0,4500,8801,58,9110,8802,24.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5125,"ETRS89 / NTM zone 25",9001,4258,5155,9807,1,0,4500,8801,58,9110,8802,25.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5126,"ETRS89 / NTM zone 26",9001,4258,5156,9807,1,0,4500,8801,58,9110,8802,26.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5127,"ETRS89 / NTM zone 27",9001,4258,5157,9807,1,0,4500,8801,58,9110,8802,27.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5128,"ETRS89 / NTM zone 28",9001,4258,5158,9807,1,0,4500,8801,58,9110,8802,28.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5129,"ETRS89 / NTM zone 29",9001,4258,5159,9807,1,0,4500,8801,58,9110,8802,29.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5130,"ETRS89 / NTM zone 30",9001,4258,5160,9807,1,0,4500,8801,58,9110,8802,30.3,9110,8805,1,9201,8806,100000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5167,"Korean 1985 / East Sea Belt",9001,4162,5049,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5168,"Korean 1985 / Central Belt Jeju",9001,4162,5131,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,,,,,,,,
+5169,"Tokyo 1892 / Korea West Belt",9001,5132,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5170,"Tokyo 1892 / Korea Central Belt",9001,5132,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5171,"Tokyo 1892 / Korea East Belt",9001,5132,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5172,"Tokyo 1892 / Korea East Sea Belt",9001,5132,5049,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5173,"Korean 1985 / Modified West Belt",9001,4162,5161,9807,1,0,4530,8801,38,9102,8802,125.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5174,"Korean 1985 / Modified Central Belt",9001,4162,5162,9807,1,0,4530,8801,38,9102,8802,127.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5175,"Korean 1985 / Modified Central Belt Jeju",9001,4162,5163,9807,1,0,4530,8801,38,9102,8802,127.0010405,9110,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,,,,,,,,
+5176,"Korean 1985 / Modified East Belt",9001,4162,5164,9807,1,0,4530,8801,38,9102,8802,129.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5177,"Korean 1985 / Modified East Sea Belt",9001,4162,5165,9807,1,0,4530,8801,38,9102,8802,131.0010405,9110,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5178,"Korean 1985 / Unified CS",9001,4162,5100,9807,1,0,4530,8801,38,9102,8802,127.3,9110,8805,0.9996,9201,8806,1000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+5179,"Korea 2000 / Unified CS",9001,4737,5100,9807,1,0,4530,8801,38,9102,8802,127.3,9110,8805,0.9996,9201,8806,1000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+5180,"Korea 2000 / West Belt",9001,4737,18253,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5181,"Korea 2000 / Central Belt",9001,4737,18252,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5182,"Korea 2000 / Central Belt Jeju",9001,4737,5131,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,550000,9001,,,,,,,,,,,,,
+5183,"Korea 2000 / East Belt",9001,4737,18251,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5184,"Korea 2000 / East Sea Belt",9001,4737,5049,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,500000,9001,,,,,,,,,,,,,
+5185,"Korea 2000 / West Belt 2010",9001,4737,5101,9807,1,0,4530,8801,38,9102,8802,125,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,,,,,,,,
+5186,"Korea 2000 / Central Belt 2010",9001,4737,5102,9807,1,0,4530,8801,38,9102,8802,127,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,,,,,,,,
+5187,"Korea 2000 / East Belt 2010",9001,4737,5103,9807,1,0,4530,8801,38,9102,8802,129,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,,,,,,,,
+5188,"Korea 2000 / East Sea Belt 2010",9001,4737,5104,9807,1,0,4530,8801,38,9102,8802,131,9102,8805,1,9201,8806,200000,9001,8807,600000,9001,,,,,,,,,,,,,
+5221,"S-JTSK (Ferro) / Krovak East North",9001,4818,5218,1041,1,0,4499,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,42.3,9110,,,,,,,
+5223,"WGS 84 / Gabon TM",9001,4326,5222,9807,1,0,4499,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,500000,9001,,,,,,,,,,,,,
+5224,"S-JTSK/05 (Ferro) / Modified Krovak",9001,5229,5219,1042,1,0,6501,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203,,,,,,,
+5225,"S-JTSK/05 (Ferro) / Modified Krovak East North",9001,5229,5220,1043,1,0,4499,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203,,,,,,,
+5234,"Kandawala / Sri Lanka Grid",9001,4244,5231,9807,1,0,4400,8801,7.0001729,9110,8802,80.461816,9110,8805,0.9999238418,9201,8806,200000,9001,8807,200000,9001,,,,,,,,,,,,,
+5235,"SLD99 / Sri Lanka Grid 1999",9001,5233,5232,9807,1,0,4400,8801,7.00016975,9110,8802,80.46181671,9110,8805,0.9999238418,9201,8806,500000,9001,8807,500000,9001,,,,,,,,,,,,,
+5243,"ETRS89 / LCC Germany (E-N)",9001,4258,4838,9802,1,0,4400,8821,51,9102,8822,10.3,9110,8823,48.4,9110,8824,53.4,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+5247,"GDBD2009 / Brunei BRSO",9001,5246,19894,9812,1,0,4400,8806,0,9001,8807,0,9001,8811,4,9110,8812,115,9110,8813,53.185691582,9110,8814,53.07483685,9110,8815,0.99984,9201,,,,,,,
+5253,"TUREF / TM27",9001,5252,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5254,"TUREF / TM30",9001,5252,16370,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5255,"TUREF / TM33",9001,5252,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5256,"TUREF / TM36",9001,5252,16372,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5257,"TUREF / TM39",9001,5252,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5258,"TUREF / TM42",9001,5252,16374,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5259,"TUREF / TM45",9001,5252,16308,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5266,"DRUKREF 03 / Bhutan National Grid",9001,5264,5265,9807,1,0,4400,8801,0,9102,8802,90,9102,8805,1,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+5269,"TUREF / 3-degree Gauss-Kruger zone 9",9001,5252,16269,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+5270,"TUREF / 3-degree Gauss-Kruger zone 10",9001,5252,16270,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,,,,,,,,
+5271,"TUREF / 3-degree Gauss-Kruger zone 11",9001,5252,16271,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,,,,,,,,
+5272,"TUREF / 3-degree Gauss-Kruger zone 12",9001,5252,16272,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,,,,,,,,
+5273,"TUREF / 3-degree Gauss-Kruger zone 13",9001,5252,16273,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+5274,"TUREF / 3-degree Gauss-Kruger zone 14",9001,5252,16274,9807,1,0,4530,8801,0,9102,8802,42,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+5275,"TUREF / 3-degree Gauss-Kruger zone 15",9001,5252,16275,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+5292,"DRUKREF 03 / Bumthang TM",9001,5264,5268,9807,1,0,4400,8801,0,9110,8802,90.44,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5293,"DRUKREF 03 / Chhukha TM",9001,5264,5276,9807,1,0,4400,8801,0,9110,8802,89.33,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5294,"DRUKREF 03 / Dagana TM",9001,5264,5277,9807,1,0,4400,8801,0,9110,8802,89.51,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5295,"DRUKREF 03 / Gasa TM",9001,5264,5278,9807,1,0,4400,8801,0,9110,8802,90.02,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5296,"DRUKREF 03 / Ha TM",9001,5264,5279,9807,1,0,4400,8801,0,9110,8802,90.09,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5297,"DRUKREF 03 / Lhuentse TM",9001,5264,5280,9807,1,0,4400,8801,0,9110,8802,91.08,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5298,"DRUKREF 03 / Mongar TM",9001,5264,5281,9807,1,0,4400,8801,0,9110,8802,91.14,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5299,"DRUKREF 03 / Paro TM",9001,5264,5282,9807,1,0,4400,8801,0,9110,8802,89.21,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5300,"DRUKREF 03 / Pemagatshel TM",9001,5264,5283,9807,1,0,4400,8801,0,9110,8802,91.21,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5301,"DRUKREF 03 / Punakha TM",9001,5264,5313,9807,1,0,4400,8801,0,9110,8802,89.51,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5302,"DRUKREF 03 / Samdrup Jongkhar TM",9001,5264,5285,9807,1,0,4400,8801,0,9110,8802,91.34,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5303,"DRUKREF 03 / Samtse TM",9001,5264,5286,9807,1,0,4400,8801,0,9110,8802,89.04,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5304,"DRUKREF 03 / Sarpang TM",9001,5264,5287,9807,1,0,4400,8801,0,9110,8802,90.16,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5305,"DRUKREF 03 / Thimphu TM",9001,5264,5312,9807,1,0,4400,8801,0,9110,8802,89.33,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5306,"DRUKREF 03 / Trashigang TM",9001,5264,5289,9807,1,0,4400,8801,0,9110,8802,91.45,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5307,"DRUKREF 03 / Trongsa TM",9001,5264,5290,9807,1,0,4400,8801,0,9110,8802,90.3,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5308,"DRUKREF 03 / Tsirang TM",9001,5264,5284,9807,1,0,4400,8801,0,9110,8802,90.1,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5309,"DRUKREF 03 / Wangdue Phodrang TM",9001,5264,5288,9807,1,0,4400,8801,0,9110,8802,90.07,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5310,"DRUKREF 03 / Yangtse TM",9001,5264,5314,9807,1,0,4400,8801,0,9110,8802,91.34,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5311,"DRUKREF 03 / Zhemgang TM",9001,5264,5291,9807,1,0,4400,8801,0,9110,8802,90.52,9110,8805,1,9201,8806,250000,9001,8807,-2500000,9001,,,,,,,,,,,,,
+5316,"ETRS89 / Faroe TM",9001,4258,5315,9807,1,0,4400,8801,0,9102,8802,-7,9102,8805,0.999997,9201,8806,200000,9001,8807,-6000000,9001,,,,,,,,,,,,,
+5320,"NAD83 / Teranet Ontario Lambert",9001,4269,5319,9802,1,0,4499,8821,0,9102,8822,-84,9102,8823,44.3,9110,8824,54.3,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+5321,"NAD83(CSRS) / Teranet Ontario Lambert",9001,4617,5319,9802,1,0,4499,8821,0,9102,8822,-84,9102,8823,44.3,9110,8824,54.3,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+5325,"ISN2004 / Lambert 2004",9001,5324,5326,9802,1,0,4499,8821,65,9110,8822,-19,9110,8823,64.15,9110,8824,65.45,9110,8826,1700000,9001,8827,300000,9001,,,,,,,,,,
+5329,"Segara (Jakarta) / NEIEZ",9001,4820,5328,9804,1,0,4499,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,,,,,,,,
+5330,"Batavia (Jakarta) / NEIEZ",9001,4813,5328,9804,1,0,4499,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,,,,,,,,
+5331,"Makassar (Jakarta) / NEIEZ",9001,4804,5328,9804,1,0,4499,8801,0,9102,8802,3.113221,9110,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,,,,,,,,
+5337,"Aratu / UTM zone 25S",9001,4208,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5343,"POSGAR 2007 / Argentina 1",9001,5340,18031,9807,1,0,4530,8801,-90,9102,8802,-72,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+5344,"POSGAR 2007 / Argentina 2",9001,5340,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+5345,"POSGAR 2007 / Argentina 3",9001,5340,18033,9807,1,0,4530,8801,-90,9102,8802,-66,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+5346,"POSGAR 2007 / Argentina 4",9001,5340,18034,9807,1,0,4530,8801,-90,9102,8802,-63,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+5347,"POSGAR 2007 / Argentina 5",9001,5340,18035,9807,1,0,4530,8801,-90,9102,8802,-60,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+5348,"POSGAR 2007 / Argentina 6",9001,5340,18036,9807,1,0,4530,8801,-90,9102,8802,-57,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+5349,"POSGAR 2007 / Argentina 7",9001,5340,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+5355,"MARGEN / UTM zone 20S",9001,5354,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5356,"MARGEN / UTM zone 19S",9001,5354,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5357,"MARGEN / UTM zone 21S",9001,5354,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5361,"SIRGAS-Chile / UTM zone 19S",9001,5360,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5362,"SIRGAS-Chile / UTM zone 18S",9001,5360,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5367,"CR05 / CRTM05",9001,5365,5366,9807,1,0,4500,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5382,"SIRGAS-ROU98 / UTM zone 21S",9001,5381,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5383,"SIRGAS-ROU98 / UTM zone 22S",9001,5381,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5387,"Peru96 / UTM zone 18S",9001,5373,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5388,"Peru96 / UTM zone 17S",9001,5373,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5389,"Peru96 / UTM zone 19S",9001,5373,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5396,"SIRGAS 2000 / UTM zone 26S",9001,4674,16126,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5456,"Ocotepeque 1935 / Costa Rica Norte",9001,5451,5390,9801,1,0,4499,8801,10.28,9110,8802,-84.2,9110,8805,0.99995696,9201,8806,500000,9001,8807,271820.522,9001,,,,,,,,,,,,,
+5457,"Ocotepeque 1935 / Costa Rica Sur",9001,5451,5394,9801,1,0,4499,8801,9,9110,8802,-83.4,9110,8805,0.99995696,9201,8806,500000,9001,8807,327987.436,9001,,,,,,,,,,,,,
+5458,"Ocotepeque 1935 / Guatemala Norte",9001,4267,18211,9801,1,1,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,,,,,,,,
+5459,"Ocotepeque 1935 / Guatemala Sur",9001,5451,18212,9801,1,0,4499,8801,14.54,9110,8802,-90.2,9110,8805,0.99989906,9201,8806,500000,9001,8807,325992.681,9001,,,,,,,,,,,,,
+5460,"Ocotepeque 1935 / El Salvador Lambert",9001,5451,5399,9801,1,0,4499,8801,13.47,9110,8802,-89,9110,8805,0.99996704,9201,8806,500000,9001,8807,295809.184,9001,,,,,,,,,,,,,
+5461,"Ocotepeque 1935 / Nicaragua Norte",9001,5451,5439,9801,1,0,4499,8801,13.52,9110,8802,-85.3,9110,8805,0.99990314,9201,8806,500000,9001,8807,359891.816,9001,,,,,,,,,,,,,
+5462,"Ocotepeque 1935 / Nicaragua Sur",9001,5451,5444,9801,1,0,4499,8801,11.44,9110,8802,-85.3,9110,8805,0.99992228,9201,8806,500000,9001,8807,288876.327,9001,,,,,,,,,,,,,
+5463,"SAD69 / UTM zone 17N",9001,4618,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5466,"Sibun Gorge 1922 / Colony Grid",9001,5464,5465,9807,1,1,4499,8801,17.0340471,9110,8802,-88.3754687,9110,8805,1,9201,8806,217259.26,9005,8807,445474.83,9005,,,,,,,,,,,,,
+5469,"Panama-Colon 1911 / Panama Lambert",9001,5467,5468,9801,1,0,4499,8801,8.25,9110,8802,-80,9110,8805,0.99989909,9201,8806,500000,9001,8807,294865.303,9001,,,,,,,,,,,,,
+5472,"Panama-Colon 1911 / Panama Polyconic",9037,5467,5471,9818,1,0,1028,8801,8.15,9110,8802,-81,9110,8806,1000000,9037,8807,1092972.1,9037,,,,,,,,,,,,,,,,
+5479,"RSRGD2000 / MSLC2000",9001,4764,5475,9802,1,0,4500,8821,-78,9110,8822,163,9110,8823,-76.4,9110,8824,-79.2,9110,8826,7000000,9001,8827,5000000,9001,,,,,,,,,,
+5480,"RSRGD2000 / BCLC2000",9001,4764,5476,9802,1,0,4500,8821,-74.3,9110,8822,165,9110,8823,-73.4,9110,8824,-75.2,9110,8826,5000000,9001,8827,3000000,9001,,,,,,,,,,
+5481,"RSRGD2000 / PCLC2000",9001,4764,5477,9802,1,0,4500,8821,-71.3,9110,8822,166,9110,8823,-70.4,9110,8824,-72.2,9110,8826,3000000,9001,8827,1000000,9001,,,,,,,,,,
+5482,"RSRGD2000 / RSPS2000",9001,4764,5478,9810,1,0,1044,8801,-90,9102,8802,180,9102,8805,0.994,9201,8806,5000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+5490,"RGAF09 / UTM zone 20N",9001,5489,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5513,"S-JTSK / Krovak",9001,4156,5509,9819,1,0,6501,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110,,,,,,,
+5514,"S-JTSK / Krovak East North",9001,4156,5510,1041,1,0,4499,1036,30.1717303,9110,8806,0,9001,8807,0,9001,8811,49.3,9110,8818,78.3,9110,8819,0.9999,9201,8833,24.5,9110,,,,,,,
+5515,"S-JTSK/05 / Modified Krovak",9001,5228,5511,1042,1,0,6501,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203,,,,,,,
+5516,"S-JTSK/05 / Modified Krovak East North",9001,5228,5512,1043,1,0,4499,1026,0.02946529277,9203,1027,0.02515965696,9203,1028,1.193845912e-07,9203,1029,-4.668270147e-07,9203,1030,9.233980362e-12,9203,1031,1.523735715e-12,9203,1032,1.696780024e-18,9203,,,,,,,
+5518,"CI1971 / Chatham Islands Map Grid",9001,4672,5517,9807,1,0,4500,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,350000,9001,8807,650000,9001,,,,,,,,,,,,,
+5519,"CI1979 / Chatham Islands Map Grid",9001,4673,5517,9807,1,0,4500,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,350000,9001,8807,650000,9001,,,,,,,,,,,,,
+5520,"DHDN / 3-degree Gauss-Kruger zone 1",9001,4314,16261,9807,1,0,4530,8801,0,9102,8802,3,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+5523,"WGS 84 / Gabon TM 2011",9001,4326,5522,9807,1,0,4499,8801,0,9102,8802,11.3,9110,8805,0.9996,9201,8806,1500000,9001,8807,5500000,9001,,,,,,,,,,,,,
+5530,"SAD69(96) / Brazil Polyconic",9001,5527,19941,9818,1,0,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,,,,,,,,
+5531,"SAD69(96) / UTM zone 21S",9001,5527,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5532,"SAD69(96) / UTM zone 22S",9001,4618,16122,9807,1,1,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5533,"SAD69(96) / UTM zone 23S",9001,5527,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5534,"SAD69(96) / UTM zone 24S",9001,5527,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5535,"SAD69(96) / UTM zone 25S",9001,5527,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5536,"Corrego Alegre 1961 / UTM zone 21S",9001,5524,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5537,"Corrego Alegre 1961 / UTM zone 22S",9001,5524,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5538,"Corrego Alegre 1961 / UTM zone 23S",9001,5524,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5539,"Corrego Alegre 1961 / UTM zone 24S",9001,5524,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5550,"PNG94 / PNGMG94 zone 54",9001,5546,5547,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5551,"PNG94 / PNGMG94 zone 55",9001,5546,5548,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5552,"PNG94 / PNGMG94 zone 56",9001,5546,5549,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5559,"Ocotepeque 1935 / Guatemala Norte",9001,5451,18211,9801,1,0,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,,,,,,,,
+5562,"UCS-2000 / Gauss-Kruger zone 4",9001,5561,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+5563,"UCS-2000 / Gauss-Kruger zone 5",9001,5561,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+5564,"UCS-2000 / Gauss-Kruger zone 6",9001,5561,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+5565,"UCS-2000 / Gauss-Kruger zone 7",9001,5561,16207,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+5566,"UCS-2000 / Gauss-Kruger CM 21E",9001,5561,16304,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5567,"UCS-2000 / Gauss-Kruger CM 27E",9001,5561,16305,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5568,"UCS-2000 / Gauss-Kruger CM 33E",9001,5561,16306,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5569,"UCS-2000 / Gauss-Kruger CM 39E",9001,5561,16307,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5570,"UCS-2000 / 3-degree Gauss-Kruger zone 7",9001,5561,16267,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+5571,"UCS-2000 / 3-degree Gauss-Kruger zone 8",9001,5561,16268,9807,1,1,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+5572,"UCS-2000 / 3-degree Gauss-Kruger zone 9",9001,5561,16269,9807,1,1,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+5573,"UCS-2000 / 3-degree Gauss-Kruger zone 10",9001,5561,16270,9807,1,1,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,,,,,,,,
+5574,"UCS-2000 / 3-degree Gauss-Kruger zone 11",9001,5561,16271,9807,1,1,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,,,,,,,,
+5575,"UCS-2000 / 3-degree Gauss-Kruger zone 12",9001,5561,16272,9807,1,1,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,,,,,,,,
+5576,"UCS-2000 / 3-degree Gauss-Kruger zone 13",9001,5561,16273,9807,1,1,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+5577,"UCS-2000 / 3-degree Gauss-Kruger CM 21E",9001,5561,16304,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5578,"UCS-2000 / 3-degree Gauss-Kruger CM 24E",9001,5561,16368,9807,1,1,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5579,"UCS-2000 / 3-degree Gauss-Kruger CM 27E",9001,5561,16305,9807,1,1,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5580,"UCS-2000 / 3-degree Gauss-Kruger CM 30E",9001,5561,16370,9807,1,1,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5581,"UCS-2000 / 3-degree Gauss-Kruger CM 33E",9001,5561,16306,9807,1,1,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5582,"UCS-2000 / 3-degree Gauss-Kruger CM 36E",9001,5561,16372,9807,1,1,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5583,"UCS-2000 / 3-degree Gauss-Kruger CM 39E",9001,5561,16307,9807,1,1,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5588,"NAD27 / New Brunswick Stereographic (NAD27)",9002,4267,5587,9809,1,0,1029,8801,46.3,9110,8802,-66.3,9110,8805,0.999912,9201,8806,1000000,9002,8807,1000000,9002,,,,,,,,,,,,,
+5589,"Sibun Gorge 1922 / Colony Grid",9005,5464,5465,9807,1,0,4403,8801,17.0340471,9110,8802,-88.3754687,9110,8805,1,9201,8806,217259.26,9005,8807,445474.83,9005,,,,,,,,,,,,,
+5596,"FEH2010 / Fehmarnbelt TM",9001,5593,5595,9807,1,0,4400,8801,0,9110,8802,11.2,9110,8805,1,9201,8806,1000000,9001,8807,0,9001,,,,,,,,,,,,,
+5623,"NAD27 / Michigan East",9003,4267,12101,9807,1,0,4497,8801,41.3,9110,8802,-83.4,9110,8805,0.999942857,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+5624,"NAD27 / Michigan Old Central",9003,4267,12102,9807,1,0,4497,8801,41.3,9110,8802,-85.45,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+5625,"NAD27 / Michigan West",9003,4267,12103,9807,1,0,4497,8801,41.3,9110,8802,-88.45,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+5627,"ED50 / TM 6 NE",9001,4230,16406,9807,1,0,4400,8801,0,9102,8802,6,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5629,"Moznet / UTM zone 38S",9001,4130,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5631,"Pulkovo 1942(58) / Gauss-Kruger zone 2 (E-N)",9001,4179,16202,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+5632,"PTRA08 / LCC Europe",9001,5013,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,,,,,,,,
+5633,"PTRA08 / LAEA Europe",9001,5013,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,,,,,,,,
+5634,"REGCAN95 / LCC Europe",9001,4081,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,,,,,,,,
+5635,"REGCAN95 / LAEA Europe",9001,4081,19986,9820,1,0,4500,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,,,,,,,,
+5636,"TUREF / LAEA Europe",9001,5252,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,,,,,,,,
+5637,"TUREF / LCC Europe",9001,5252,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,,,,,,,,
+5638,"ISN2004 / LAEA Europe",9001,5324,19986,9820,1,0,4532,8801,52,9102,8802,10,9102,8806,4321000,9001,8807,3210000,9001,,,,,,,,,,,,,,,,
+5639,"ISN2004 / LCC Europe",9001,5324,19985,9802,1,0,4500,8821,52,9102,8822,10,9102,8823,35,9102,8824,65,9102,8826,4000000,9001,8827,2800000,9001,,,,,,,,,,
+5641,"SIRGAS 2000 / Brazil Mercator",9001,4674,5640,9805,1,0,4499,8802,-43,9102,8806,5000000,9001,8807,10000000,9001,8823,-2,9102,,,,,,,,,,,,,,,,
+5643,"ED50 / SPBA LCC",9001,4230,5642,9802,1,0,4400,8821,48,9102,8822,10,9102,8823,52.4,9110,8824,54.2,9110,8826,815000,9001,8827,0,9001,,,,,,,,,,
+5644,"RGR92 / UTM zone 39S",9001,4627,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5646,"NAD83 / Vermont (ftUS)",9003,4269,5645,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,,,,,,,,
+5649,"ETRS89 / UTM zone 31N (zE-N)",9001,4258,5647,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+5650,"ETRS89 / UTM zone 33N (zE-N)",9001,4258,5648,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,33500000,9001,8807,0,9001,,,,,,,,,,,,,
+5651,"ETRS89 / UTM zone 31N (N-zE)",9001,4258,5647,9807,1,0,4500,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+5652,"ETRS89 / UTM zone 32N (N-zE)",9001,4258,4648,9807,1,0,4500,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+5653,"ETRS89 / UTM zone 33N (N-zE)",9001,4258,5648,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,33500000,9001,8807,0,9001,,,,,,,,,,,,,
+5654,"NAD83(HARN) / Vermont (ftUS)",9003,4152,5645,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,,,,,,,,
+5655,"NAD83(NSRS2007) / Vermont (ftUS)",9003,4759,5645,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,,,,,,,,
+5659,"Monte Mario / TM Emilia-Romagna",9001,4265,5658,9807,1,0,4499,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500053,9001,8807,-3999820,9001,,,,,,,,,,,,,
+5663,"Pulkovo 1942(58) / Gauss-Kruger zone 3 (E-N)",9001,4179,16203,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+5664,"Pulkovo 1942(83) / Gauss-Kruger zone 2 (E-N)",9001,4178,16202,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+5665,"Pulkovo 1942(83) / Gauss-Kruger zone 3 (E-N)",9001,4178,16203,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+5666,"PD/83 / 3-degree Gauss-Kruger zone 3 (E-N)",9001,4746,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+5667,"PD/83 / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4746,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+5668,"RD/83 / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4745,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+5669,"RD/83 / 3-degree Gauss-Kruger zone 5 (E-N)",9001,4745,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+5670,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 3 (E-N)",9001,4179,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+5671,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4179,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+5672,"Pulkovo 1942(58) / 3-degree Gauss-Kruger zone 5 (E-N)",9001,4179,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+5673,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 3 (E-N)",9001,4178,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+5674,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4178,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+5675,"Pulkovo 1942(83) / 3-degree Gauss-Kruger zone 5 (E-N)",9001,4178,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+5676,"DHDN / 3-degree Gauss-Kruger zone 2 (E-N)",9001,4314,16262,9807,1,0,4400,8801,0,9102,8802,6,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+5677,"DHDN / 3-degree Gauss-Kruger zone 3 (E-N)",9001,4314,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+5678,"DHDN / 3-degree Gauss-Kruger zone 4 (E-N)",9001,4314,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+5679,"DHDN / 3-degree Gauss-Kruger zone 5 (E-N)",9001,4314,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+5680,"DHDN / 3-degree Gauss-Kruger zone 1 (E-N)",9001,4314,16261,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+5682,"DB_REF / 3-degree Gauss-Kruger zone 2 (E-N)",9001,5681,16262,9807,1,0,4400,8801,0,9102,8802,6,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+5683,"DB_REF / 3-degree Gauss-Kruger zone 3 (E-N)",9001,5681,16263,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+5684,"DB_REF / 3-degree Gauss-Kruger zone 4 (E-N)",9001,5681,16264,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+5685,"DB_REF / 3-degree Gauss-Kruger zone 5 (E-N)",9001,5681,16265,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+5700,"NZGD2000 / UTM zone 1S",9001,4167,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5819,EPSG topocentric example A,9001,4979,15594,9837,1,0,4461,8834,55,9102,8835,5,9102,8836,0,9001,,,,,,,,,,,,,,,,,,,
+5820,EPSG topocentric example B,9001,4978,15595,9836,1,0,4461,8837,3771793.97,9001,8838,140253.34,9001,8839,5124304.35,9001,,,,,,,,,,,,,,,,,,,
+5821,EPSG vertical perspective example,9001,5819,19850,9838,1,0,4461,8834,55,9102,8835,5,9102,8836,200,9001,8840,5900,9036,,,,,,,,,,,,,,,,
+5825,"AGD66 / ACT Standard Grid",9001,4202,5824,9807,1,0,4400,8801,-35.19038506,9110,8802,149.003346139,9110,8805,1.000086,9201,8806,200000,9001,8807,600000,9001,,,,,,,,,,,,,
+5836,"Yemen NGN96 / UTM zone 37N",9001,4163,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5837,"Yemen NGN96 / UTM zone 40N",9001,4163,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+5839,"Peru96 / UTM zone 17S",9001,5373,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5842,"WGS 84 / TM 12 SE",9001,4326,16612,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5844,"RGRDC 2005 / Congo TM zone 30",9001,4046,17430,9807,1,0,4499,8801,0,9102,8802,30,9102,8805,0.9999,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5858,"SAD69(96) / UTM zone 22S",9001,5527,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5875,"SAD69(96) / UTM zone 18S",9001,5527,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5876,"SAD69(96) / UTM zone 19S",9001,5527,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5877,"SAD69(96) / UTM zone 20S",9001,5527,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5879,"Cadastre 1997 / UTM zone 38S",9001,4475,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+5880,"SIRGAS 2000 / Brazil Polyconic",9001,4674,19941,9818,1,0,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,,,,,,,,
+5887,"TGD2005 / Tonga Map Grid",9001,5886,5883,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,1500000,9001,8807,5000000,9001,,,,,,,,,,,,,
+5890,JAXA Snow Depth Polar Stereographic North,9001,4054,5889,9829,1,0,1035,8806,0,9001,8807,0,9001,8832,70,9102,8833,90,9102,,,,,,,,,,,,,,,,
+5921,"WGS 84 / EPSG Arctic Regional zone A1",9001,4326,5906,9802,1,0,4400,8821,81.19020136,9110,8822,-111,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5922,"WGS 84 / EPSG Arctic Regional zone A2",9001,4326,5907,9802,1,0,4400,8821,81.19020136,9110,8822,-39,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5923,"WGS 84 / EPSG Arctic Regional zone A3",9001,4326,5908,9802,1,0,4400,8821,81.19020136,9110,8822,33,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5924,"WGS 84 / EPSG Arctic Regional zone A4",9001,4326,5909,9802,1,0,4400,8821,81.19020136,9110,8822,105,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5925,"WGS 84 / EPSG Arctic Regional zone A5",9001,4326,5910,9802,1,0,4400,8821,81.19020136,9110,8822,177,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5926,"WGS 84 / EPSG Arctic Regional zone B1",9001,4326,5911,9802,1,0,4400,8821,73.09206671,9110,8822,-111,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5927,"WGS 84 / EPSG Arctic Regional zone B2",9001,4326,5912,9802,1,0,4400,8821,73.09206671,9110,8822,-39,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5928,"WGS 84 / EPSG Arctic Regional zone B3",9001,4326,5913,9802,1,0,4400,8821,73.09206671,9110,8822,33,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5929,"WGS 84 / EPSG Arctic Regional zone B4",9001,4326,5914,9802,1,0,4400,8821,73.09206671,9110,8822,105,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5930,"WGS 84 / EPSG Arctic Regional zone B5",9001,4326,5915,9802,1,0,4400,8821,73.09206671,9110,8822,177,9102,8823,77,9102,8824,69,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5931,"WGS 84 / EPSG Arctic Regional zone C1",9001,4326,5916,9802,1,0,4400,8821,65.06045752,9110,8822,-111,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5932,"WGS 84 / EPSG Arctic Regional zone C2",9001,4326,5917,9802,1,0,4400,8821,65.06045752,9110,8822,-39,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5933,"WGS 84 / EPSG Arctic Regional zone C3",9001,4326,5918,9802,1,0,4400,8821,65.06045752,9110,8822,33,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5934,"WGS 84 / EPSG Arctic Regional zone C4",9001,4326,5919,9802,1,0,4400,8821,65.06045752,9110,8822,105,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5935,"WGS 84 / EPSG Arctic Regional zone C5",9001,4326,5920,9802,1,0,4400,8821,65.06045752,9110,8822,177,9102,8823,69,9102,8824,61,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+5936,"WGS 84 / EPSG Alaska Polar Stereographic",9001,4326,5901,9810,1,0,4467,8801,90,9102,8802,-150,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+5937,"WGS 84 / EPSG Canada Polar Stereographic",9001,4326,5902,9810,1,0,4466,8801,90,9102,8802,-100,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+5938,"WGS 84 / EPSG Greenland Polar Stereographic",9001,4326,5903,9810,1,0,1036,8801,90,9102,8802,-33,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+5939,"WGS 84 / EPSG Norway Polar Stereographic",9001,4326,5904,9810,1,0,1037,8801,90,9102,8802,18,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+5940,"WGS 84 / EPSG Russia Polar Stereographic",9001,4326,5905,9810,1,0,1038,8801,90,9102,8802,105,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+6050,"GR96 / EPSG Arctic zone 1-25",9001,4747,5979,9802,1,0,4400,8821,85.2613626,9110,8822,-30,9110,8823,87,9110,8824,83.4,9110,8826,25500000,9001,8827,1500000,9001,,,,,,,,,,
+6051,"GR96 / EPSG Arctic zone 2-18",9001,4747,5987,9802,1,0,4400,8821,82.03303296,9110,8822,-52,9110,8823,83.4,9110,8824,80.2,9110,8826,18500000,9001,8827,2500000,9001,,,,,,,,,,
+6052,"GR96 / EPSG Arctic zone 2-20",9001,4747,5988,9802,1,0,4400,8821,82.03303296,9110,8822,-12,9110,8823,83.4,9110,8824,80.2,9110,8826,20500000,9001,8827,2500000,9001,,,,,,,,,,
+6053,"GR96 / EPSG Arctic zone 3-29",9001,4747,6002,9802,1,0,4400,8821,78.42264151,9110,8822,-69,9110,8823,80.2,9110,8824,77,9110,8826,29500000,9001,8827,3500000,9001,,,,,,,,,,
+6054,"GR96 / EPSG Arctic zone 3-31",9001,4747,6003,9802,1,0,4400,8821,78.42264151,9110,8822,-39,9110,8823,80.2,9110,8824,77,9110,8826,31500000,9001,8827,3500000,9001,,,,,,,,,,
+6055,"GR96 / EPSG Arctic zone 3-33",9001,4747,6004,9802,1,0,4400,8821,78.42264151,9110,8822,-10,9110,8823,80.2,9110,8824,77,9110,8826,33500000,9001,8827,3500000,9001,,,,,,,,,,
+6056,"GR96 / EPSG Arctic zone 4-20",9001,4747,6009,9802,1,0,4400,8821,75.21518519,9110,8822,-64,9110,8823,77,9110,8824,73.4,9110,8826,20500000,9001,8827,4500000,9001,,,,,,,,,,
+6057,"GR96 / EPSG Arctic zone 4-22",9001,4747,6010,9802,1,0,4400,8821,75.21518519,9110,8822,-39,9110,8823,77,9110,8824,73.4,9110,8826,22500000,9001,8827,4500000,9001,,,,,,,,,,
+6058,"GR96 / EPSG Arctic zone 4-24",9001,4747,6011,9802,1,0,4400,8821,75.21518519,9110,8822,-14,9110,8823,77,9110,8824,73.4,9110,8826,24500000,9001,8827,4500000,9001,,,,,,,,,,
+6059,"GR96 / EPSG Arctic zone 5-41",9001,4747,6035,9802,1,0,4400,8821,72.01300331,9110,8822,-62,9110,8823,73.4,9110,8824,70.2,9110,8826,41500000,9001,8827,5500000,9001,,,,,,,,,,
+6060,"GR96 / EPSG Arctic zone 5-43",9001,4747,6036,9802,1,0,4400,8821,72.01300331,9110,8822,-42,9110,8823,73.4,9110,8824,70.2,9110,8826,43500000,9001,8827,5500000,9001,,,,,,,,,,
+6061,"GR96 / EPSG Arctic zone 5-45",9001,4747,6037,9802,1,0,4400,8821,72.01300331,9110,8822,-22,9110,8823,73.4,9110,8824,70.2,9110,8826,45500000,9001,8827,5500000,9001,,,,,,,,,,
+6062,"GR96 / EPSG Arctic zone 6-26",9001,4747,6045,9802,1,0,4400,8821,68.4114912,9110,8822,-56,9110,8823,70.2,9110,8824,67,9110,8826,26500000,9001,8827,6500000,9001,,,,,,,,,,
+6063,"GR96 / EPSG Arctic zone 6-28",9001,4747,6046,9802,1,0,4400,8821,68.4114912,9110,8822,-38,9110,8823,70.2,9110,8824,67,9110,8826,28500000,9001,8827,6500000,9001,,,,,,,,,,
+6064,"GR96 / EPSG Arctic zone 6-30",9001,4747,6047,9802,1,0,4400,8821,68.4114912,9110,8822,-20,9110,8823,70.2,9110,8824,67,9110,8826,30500000,9001,8827,6500000,9001,,,,,,,,,,
+6065,"GR96 / EPSG Arctic zone 7-11",9001,4747,6048,9802,1,0,4400,8821,65.21037415,9110,8822,-51,9110,8823,67,9110,8824,63.4,9110,8826,11500000,9001,8827,7500000,9001,,,,,,,,,,
+6066,"GR96 / EPSG Arctic zone 7-13",9001,4747,6049,9802,1,0,4400,8821,65.21037415,9110,8822,-34,9110,8823,67,9110,8824,63.4,9110,8826,13500000,9001,8827,7500000,9001,,,,,,,,,,
+6067,"GR96 / EPSG Arctic zone 8-20",9001,4747,5943,9802,1,0,4400,8821,62.00551048,9110,8822,-52,9110,8823,63.4,9110,8824,60.2,9110,8826,20500000,9001,8827,8500000,9001,,,,,,,,,,
+6068,"GR96 / EPSG Arctic zone 8-22",9001,4747,5944,9802,1,0,4400,8821,62.00551048,9110,8822,-37,9110,8823,63.4,9110,8824,60.2,9110,8826,22500000,9001,8827,8500000,9001,,,,,,,,,,
+6069,"ETRS89 / EPSG Arctic zone 2-22",9001,4258,5989,9802,1,0,4400,8821,82.03303296,9110,8822,16,9110,8823,83.4,9110,8824,80.2,9110,8826,22500000,9001,8827,2500000,9001,,,,,,,,,,
+6070,"ETRS89 / EPSG Arctic zone 3-11",9001,4258,5993,9802,1,0,4400,8821,78.42264151,9110,8822,21,9110,8823,80.2,9110,8824,77,9110,8826,11500000,9001,8827,3500000,9001,,,,,,,,,,
+6071,"ETRS89 / EPSG Arctic zone 4-26",9001,4258,6012,9802,1,0,4400,8821,75.21518519,9110,8822,10,9110,8823,77,9110,8824,73.4,9110,8826,26500000,9001,8827,4500000,9001,,,,,,,,,,
+6072,"ETRS89 / EPSG Arctic zone 4-28",9001,4258,6013,9802,1,0,4400,8821,75.21518519,9110,8822,34,9110,8823,77,9110,8824,73.4,9110,8826,28500000,9001,8827,4500000,9001,,,,,,,,,,
+6073,"ETRS89 / EPSG Arctic zone 5-11",9001,4258,6020,9802,1,0,4400,8821,72.01300331,9110,8822,14,9110,8823,73.4,9110,8824,70.2,9110,8826,11500000,9001,8827,5500000,9001,,,,,,,,,,
+6074,"ETRS89 / EPSG Arctic zone 5-13",9001,4258,6021,9802,1,0,4400,8821,72.01300331,9110,8822,34,9110,8823,73.4,9110,8824,70.2,9110,8826,13500000,9001,8827,5500000,9001,,,,,,,,,,
+6075,"WGS 84 / EPSG Arctic zone 2-24",9001,4326,5990,9802,1,0,4400,8821,82.03303296,9110,8822,53,9110,8823,83.4,9110,8824,80.2,9110,8826,24500000,9001,8827,2500000,9001,,,,,,,,,,
+6076,"WGS 84 / EPSG Arctic zone 2-26",9001,4326,5991,9802,1,0,4400,8821,82.03303296,9110,8822,93,9110,8823,83.4,9110,8824,80.2,9110,8826,26500000,9001,8827,2500000,9001,,,,,,,,,,
+6077,"WGS 84 / EPSG Arctic zone 3-13",9001,4326,5994,9802,1,0,4400,8821,78.42264151,9110,8822,52,9110,8823,80.2,9110,8824,77,9110,8826,13500000,9001,8827,3500000,9001,,,,,,,,,,
+6078,"WGS 84 / EPSG Arctic zone 3-15",9001,4326,5995,9802,1,0,4400,8821,78.42264151,9110,8822,83,9110,8823,80.2,9110,8824,77,9110,8826,15500000,9001,8827,3500000,9001,,,,,,,,,,
+6079,"WGS 84 / EPSG Arctic zone 3-17",9001,4326,5996,9802,1,0,4400,8821,78.42264151,9110,8822,114,9110,8823,80.2,9110,8824,77,9110,8826,17500000,9001,8827,3500000,9001,,,,,,,,,,
+6080,"WGS 84 / EPSG Arctic zone 3-19",9001,4326,5997,9802,1,0,4400,8821,78.42264151,9110,8822,145,9110,8823,80.2,9110,8824,77,9110,8826,19500000,9001,8827,3500000,9001,,,,,,,,,,
+6081,"WGS 84 / EPSG Arctic zone 4-30",9001,4326,6014,9802,1,0,4400,8821,75.21518519,9110,8822,58,9110,8823,77,9110,8824,73.4,9110,8826,30500000,9001,8827,4500000,9001,,,,,,,,,,
+6082,"WGS 84 / EPSG Arctic zone 4-32",9001,4326,6015,9802,1,0,4400,8821,75.21518519,9110,8822,82,9110,8823,77,9110,8824,73.4,9110,8826,32500000,9001,8827,4500000,9001,,,,,,,,,,
+6083,"WGS 84 / EPSG Arctic zone 4-34",9001,4326,6016,9802,1,0,4400,8821,75.21518519,9110,8822,106,9110,8823,77,9110,8824,73.4,9110,8826,34500000,9001,8827,4500000,9001,,,,,,,,,,
+6084,"WGS 84 / EPSG Arctic zone 4-36",9001,4326,6017,9802,1,0,4400,8821,75.21518519,9110,8822,130,9110,8823,77,9110,8824,73.4,9110,8826,36500000,9001,8827,4500000,9001,,,,,,,,,,
+6085,"WGS 84 / EPSG Arctic zone 4-38",9001,4326,6018,9802,1,0,4400,8821,75.21518519,9110,8822,154,9110,8823,77,9110,8824,73.4,9110,8826,38500000,9001,8827,4500000,9001,,,,,,,,,,
+6086,"WGS 84 / EPSG Arctic zone 4-40",9001,4326,6019,9802,1,0,4400,8821,75.21518519,9110,8822,179,9110,8823,77,9110,8824,73.4,9110,8826,40500000,9001,8827,4500000,9001,,,,,,,,,,
+6087,"WGS 84 / EPSG Arctic zone 5-15",9001,4326,6022,9802,1,0,4400,8821,72.01300331,9110,8822,54,9110,8823,73.4,9110,8824,70.2,9110,8826,15500000,9001,8827,5500000,9001,,,,,,,,,,
+6088,"WGS 84 / EPSG Arctic zone 5-17",9001,4326,6023,9802,1,0,4400,8821,72.01300331,9110,8822,74,9110,8823,73.4,9110,8824,70.2,9110,8826,17500000,9001,8827,5500000,9001,,,,,,,,,,
+6089,"WGS 84 / EPSG Arctic zone 5-19",9001,4326,6024,9802,1,0,4400,8821,72.01300331,9110,8822,95,9110,8823,73.4,9110,8824,70.2,9110,8826,19500000,9001,8827,5500000,9001,,,,,,,,,,
+6090,"WGS 84 / EPSG Arctic zone 5-21",9001,4326,6025,9802,1,0,4400,8821,72.01300331,9110,8822,116,9110,8823,73.4,9110,8824,70.2,9110,8826,21500000,9001,8827,5500000,9001,,,,,,,,,,
+6091,"WGS 84 / EPSG Arctic zone 5-23",9001,4326,6026,9802,1,0,4400,8821,72.01300331,9110,8822,137,9110,8823,73.4,9110,8824,70.2,9110,8826,23500000,9001,8827,5500000,9001,,,,,,,,,,
+6092,"WGS 84 / EPSG Arctic zone 5-25",9001,4326,6027,9802,1,0,4400,8821,72.01300331,9110,8822,158,9110,8823,73.4,9110,8824,70.2,9110,8826,25500000,9001,8827,5500000,9001,,,,,,,,,,
+6093,"WGS 84 / EPSG Arctic zone 5-27",9001,4326,6028,9802,1,0,4400,8821,72.01300331,9110,8822,179,9110,8823,73.4,9110,8824,70.2,9110,8826,27500000,9001,8827,5500000,9001,,,,,,,,,,
+6094,"NAD83(NSRS2007) / EPSG Arctic zone 5-29",9001,4759,6029,9802,1,0,4400,8821,72.01300331,9110,8822,-163,9110,8823,73.4,9110,8824,70.2,9110,8826,29500000,9001,8827,5500000,9001,,,,,,,,,,
+6095,"NAD83(NSRS2007) / EPSG Arctic zone 5-31",9001,4759,6030,9802,1,0,4400,8821,72.01300331,9110,8822,-147,9110,8823,73.4,9110,8824,70.2,9110,8826,31500000,9001,8827,5500000,9001,,,,,,,,,,
+6096,"NAD83(NSRS2007) / EPSG Arctic zone 6-14",9001,4759,6039,9802,1,0,4400,8821,68.4114912,9110,8822,-165,9110,8823,70.2,9110,8824,67,9110,8826,14500000,9001,8827,6500000,9001,,,,,,,,,,
+6097,"NAD83(NSRS2007) / EPSG Arctic zone 6-16",9001,4759,6040,9802,1,0,4400,8821,68.4114912,9110,8822,-147,9110,8823,70.2,9110,8824,67,9110,8826,16500000,9001,8827,6500000,9001,,,,,,,,,,
+6098,"NAD83(CSRS) / EPSG Arctic zone 1-23",9001,4617,5978,9802,1,0,4400,8821,85.2613626,9110,8822,-90,9110,8823,87,9110,8824,83.4,9110,8826,23500000,9001,8827,1500000,9001,,,,,,,,,,
+6099,"NAD83(CSRS) / EPSG Arctic zone 2-14",9001,4617,5985,9802,1,0,4400,8821,82.03303296,9110,8822,-115,9110,8823,83.4,9110,8824,80.2,9110,8826,14500000,9001,8827,2500000,9001,,,,,,,,,,
+6100,"NAD83(CSRS) / EPSG Arctic zone 2-16",9001,4617,5986,9802,1,0,4400,8821,82.03303296,9110,8822,-75,9110,8823,83.4,9110,8824,80.2,9110,8826,16500000,9001,8827,2500000,9001,,,,,,,,,,
+6101,"NAD83(CSRS) / EPSG Arctic zone 3-25",9001,4617,6000,9802,1,0,4400,8821,78.42264151,9110,8822,-129,9110,8823,80.2,9110,8824,77,9110,8826,25500000,9001,8827,3500000,9001,,,,,,,,,,
+6102,"NAD83(CSRS) / EPSG Arctic zone 3-27",9001,4617,6001,9802,1,0,4400,8821,78.42264151,9110,8822,-99,9110,8823,80.2,9110,8824,77,9110,8826,27500000,9001,8827,3500000,9001,,,,,,,,,,
+6103,"NAD83(CSRS) / EPSG Arctic zone 3-29",9001,4617,6002,9802,1,0,4400,8821,78.42264151,9110,8822,-69,9110,8823,80.2,9110,8824,77,9110,8826,29500000,9001,8827,3500000,9001,,,,,,,,,,
+6104,"NAD83(CSRS) / EPSG Arctic zone 4-14",9001,4617,6006,9802,1,0,4400,8821,75.21518519,9110,8822,-129,9110,8823,77,9110,8824,73.4,9110,8826,14500000,9001,8827,4500000,9001,,,,,,,,,,
+6105,"NAD83(CSRS) / EPSG Arctic zone 4-16",9001,4617,6007,9802,1,0,4400,8821,75.21518519,9110,8822,-104,9110,8823,77,9110,8824,73.4,9110,8826,16500000,9001,8827,4500000,9001,,,,,,,,,,
+6106,"NAD83(CSRS) / EPSG Arctic zone 4-18",9001,4617,6008,9802,1,0,4400,8821,75.21518519,9110,8822,-79,9110,8823,77,9110,8824,73.4,9110,8826,18500000,9001,8827,4500000,9001,,,,,,,,,,
+6107,"NAD83(CSRS) / EPSG Arctic zone 5-33",9001,4617,6031,9802,1,0,4400,8821,72.01300331,9110,8822,-131,9110,8823,73.4,9110,8824,70.2,9110,8826,33500000,9001,8827,5500000,9001,,,,,,,,,,
+6108,"NAD83(CSRS) / EPSG Arctic zone 5-35",9001,4617,6032,9802,1,0,4400,8821,72.01300331,9110,8822,-111,9110,8823,73.4,9110,8824,70.2,9110,8826,35500000,9001,8827,5500000,9001,,,,,,,,,,
+6109,"NAD83(CSRS) / EPSG Arctic zone 5-37",9001,4617,6033,9802,1,0,4400,8821,72.01300331,9110,8822,-91,9110,8823,73.4,9110,8824,70.2,9110,8826,37500000,9001,8827,5500000,9001,,,,,,,,,,
+6110,"NAD83(CSRS) / EPSG Arctic zone 5-39",9001,4617,6034,9802,1,0,4400,8821,72.01300331,9110,8822,-71,9110,8823,73.4,9110,8824,70.2,9110,8826,39500000,9001,8827,5500000,9001,,,,,,,,,,
+6111,"NAD83(CSRS) / EPSG Arctic zone 6-18",9001,4617,6041,9802,1,0,4400,8821,68.4114912,9110,8822,-132,9110,8823,70.2,9110,8824,67,9110,8826,18500000,9001,8827,6500000,9001,,,,,,,,,,
+6112,"NAD83(CSRS) / EPSG Arctic zone 6-20",9001,4617,6042,9802,1,0,4400,8821,68.4114912,9110,8822,-113,9110,8823,70.2,9110,8824,67,9110,8826,20500000,9001,8827,6500000,9001,,,,,,,,,,
+6113,"NAD83(CSRS) / EPSG Arctic zone 6-22",9001,4617,6043,9802,1,0,4400,8821,68.4114912,9110,8822,-94,9110,8823,70.2,9110,8824,67,9110,8826,22500000,9001,8827,6500000,9001,,,,,,,,,,
+6114,"NAD83(CSRS) / EPSG Arctic zone 6-24",9001,4617,6044,9802,1,0,4400,8821,68.4114912,9110,8822,-75,9110,8823,70.2,9110,8824,67,9110,8826,24500000,9001,8827,6500000,9001,,,,,,,,,,
+6115,"WGS 84 / EPSG Arctic zone 1-27",9001,4326,5980,9802,1,0,4400,8821,85.2613626,9110,8822,30,9110,8823,87,9110,8824,83.4,9110,8826,27500000,9001,8827,1500000,9001,,,,,,,,,,
+6116,"WGS 84 / EPSG Arctic zone 1-29",9001,4326,5981,9802,1,0,4400,8821,85.2613626,9110,8822,90,9110,8823,87,9110,8824,83.4,9110,8826,29500000,9001,8827,1500000,9001,,,,,,,,,,
+6117,"WGS 84 / EPSG Arctic zone 1-31",9001,4326,5982,9802,1,0,4400,8821,85.2613626,9110,8822,150,9110,8823,87,9110,8824,83.4,9110,8826,31500000,9001,8827,1500000,9001,,,,,,,,,,
+6118,"WGS 84 / EPSG Arctic zone 1-21",9001,4326,5977,9802,1,0,4400,8821,85.2613626,9110,8822,-150,9110,8823,87,9110,8824,83.4,9110,8826,21500000,9001,8827,1500000,9001,,,,,,,,,,
+6119,"WGS 84 / EPSG Arctic zone 2-28",9001,4326,5992,9802,1,0,4400,8821,82.03303296,9110,8822,133,9110,8823,83.4,9110,8824,80.2,9110,8826,28500000,9001,8827,2500000,9001,,,,,,,,,,
+6120,"WGS 84 / EPSG Arctic zone 2-10",9001,4326,5983,9802,1,0,4400,8821,82.03303296,9110,8822,166,9110,8823,83.4,9110,8824,80.2,9110,8826,10500000,9001,8827,2500000,9001,,,,,,,,,,
+6121,"WGS 84 / EPSG Arctic zone 2-12",9001,4326,5984,9802,1,0,4400,8821,82.03303296,9110,8822,-154,9110,8823,83.4,9110,8824,80.2,9110,8826,12500000,9001,8827,2500000,9001,,,,,,,,,,
+6122,"WGS 84 / EPSG Arctic zone 3-21",9001,4326,5998,9802,1,0,4400,8821,78.42264151,9110,8822,176,9110,8823,80.2,9110,8824,77,9110,8826,21500000,9001,8827,3500000,9001,,,,,,,,,,
+6123,"WGS 84 / EPSG Arctic zone 3-23",9001,4326,5999,9802,1,0,4400,8821,78.42264151,9110,8822,-153,9110,8823,80.2,9110,8824,77,9110,8826,23500000,9001,8827,3500000,9001,,,,,,,,,,
+6124,"WGS 84 / EPSG Arctic zone 4-12",9001,4326,6005,9802,1,0,4400,8821,75.21518519,9110,8822,-155,9110,8823,77,9110,8824,73.4,9110,8826,12500000,9001,8827,4500000,9001,,,,,,,,,,
+6125,"ETRS89 / EPSG Arctic zone 5-47",9001,4258,6038,9802,1,0,4400,8821,72.01300331,9110,8822,-5,9110,8823,73.4,9110,8824,70.2,9110,8826,47500000,9001,8827,5500000,9001,,,,,,,,,,
+6128,Grand Cayman National Grid 1959,9002,4723,6127,9807,1,0,1039,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640419.9475,9002,8807,0,9002,,,,,,,,,,,,,
+6129,Sister Islands National Grid 1961,9002,4726,6127,9807,1,0,1039,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640419.9475,9002,8807,0,9002,,,,,,,,,,,,,
+6141,Cayman Islands National Grid 2011,9002,6135,6126,9802,1,1,1039,8821,19.2,9110,8822,80.34,9110,8823,19.2,9110,8824,19.42,9110,8826,2950000,9002,8827,1900000,9002,,,,,,,,,,
+6200,"NAD27 / Michigan North",9003,4267,6197,1051,1,1,4497,1038,1.0000382,9201,8821,44.87,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003,,,,,,,
+6201,"NAD27 / Michigan Central",9003,4267,6198,1051,1,0,4497,1038,1.0000382,9201,8821,43.19,9110,8822,-84.2,9110,8823,44.11,9110,8824,45.42,9110,8826,2000000,9003,8827,0,9003,,,,,,,
+6202,"NAD27 / Michigan South",9003,4267,6199,1051,1,0,4497,1038,1.0000382,9201,8821,41.3,9110,8822,-84.2,9110,8823,42.06,9110,8824,43.4,9110,8826,2000000,9003,8827,0,9003,,,,,,,
+6204,Macedonia State Coordinate System,9001,3906,6203,9807,1,0,4498,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6210,"SIRGAS 2000 / UTM zone 23N",9001,4674,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6211,"SIRGAS 2000 / UTM zone 24N",9001,4674,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6244,"MAGNA-SIRGAS / Arauca urban grid",9001,4686,6212,1052,1,0,4500,1039,100,9001,8801,7.051538301,9110,8802,-70.452991476,9110,8806,1035263.443,9001,8807,1275526.621,9001,,,,,,,,,,,,,
+6245,"MAGNA-SIRGAS / Armenia urban grid",9001,4686,6213,1052,1,0,4500,1039,1470,9001,8801,4.315637,9110,8802,-75.4024561,9110,8806,1155824.666,9001,8807,993087.465,9001,,,,,,,,,,,,,
+6246,"MAGNA-SIRGAS / Barranquilla urban grid",9001,4686,6214,1052,1,0,4500,1039,100,9001,8801,10.55234591,9110,8802,-74.50035928,9110,8806,917264.406,9001,8807,1699839.935,9001,,,,,,,,,,,,,
+6247,"MAGNA-SIRGAS / Bogota urban grid",9001,4686,6215,1052,1,0,4500,1039,2550,9001,8801,4.404975,9110,8802,-74.084773,9110,8806,92334.879,9001,8807,109320.965,9001,,,,,,,,,,,,,
+6248,"MAGNA-SIRGAS / Bucaramanga urban grid",9001,4686,6216,1052,1,0,4500,1039,931,9001,8801,7.044399371,9110,8802,-73.11504356,9110,8806,1097241.305,9001,8807,1274642.278,9001,,,,,,,,,,,,,
+6249,"MAGNA-SIRGAS / Cali urban grid",9001,4686,6217,1052,1,0,4500,1039,1000,9001,8801,3.263078,9110,8802,-76.3114025,9110,8806,1061900.18,9001,8807,872364.63,9001,,,,,,,,,,,,,
+6250,"MAGNA-SIRGAS / Cartagena urban grid",9001,4686,6218,1052,1,0,4500,1039,0,9001,8801,10.2349371,9110,8802,-75.3040345,9110,8806,842981.41,9001,8807,1641887.09,9001,,,,,,,,,,,,,
+6251,"MAGNA-SIRGAS / Cucuta urban grid",9001,4686,6219,1052,1,0,4500,1039,308,9001,8801,7.532017225,9110,8802,-72.301033542,9110,8806,842805.406,9001,8807,1364404.57,9001,,,,,,,,,,,,,
+6252,"MAGNA-SIRGAS / Florencia urban grid",9001,4686,6220,1052,1,0,4500,1039,300,9001,8801,1.371564426,9110,8802,-75.370882337,9110,8806,1162300.348,9001,8807,671068.716,9001,,,,,,,,,,,,,
+6253,"MAGNA-SIRGAS / Ibague urban grid",9001,4686,6221,1052,1,0,4500,1039,1100,9001,8801,4.250988618,9110,8802,-75.104773336,9110,8806,877634.33,9001,8807,980541.348,9001,,,,,,,,,,,,,
+6254,"MAGNA-SIRGAS / Inirida urban grid",9001,4686,6222,1052,1,0,4500,1039,96,9001,8801,3.504357746,9110,8802,-67.541883552,9110,8806,1019177.687,9001,8807,491791.326,9001,,,,,,,,,,,,,
+6255,"MAGNA-SIRGAS / Leticia urban grid",9001,4686,6223,1052,1,0,4500,1039,89.7,9001,8801,-4.115166257,9110,8802,-69.563411981,9110,8806,25978.217,9001,8807,27501.365,9001,,,,,,,,,,,,,
+6256,"MAGNA-SIRGAS / Manizales urban grid",9001,4686,6224,1052,1,0,4500,1039,2100,9001,8801,5.0405354,9110,8802,-75.3039941,9110,8806,1173727.04,9001,8807,1052391.13,9001,,,,,,,,,,,,,
+6257,"MAGNA-SIRGAS / Medellin urban grid",9001,4686,6225,1052,1,0,4500,1039,1510,9001,8801,6.1345152,9110,8802,-75.3353593,9110,8806,835378.647,9001,8807,1180816.875,9001,,,,,,,,,,,,,
+6258,"MAGNA-SIRGAS / Mitu urban grid",9001,4686,6226,1052,1,0,4500,1039,170,9001,8801,1.145988972,9110,8802,-70.140766196,9110,8806,1093717.398,9001,8807,629997.236,9001,,,,,,,,,,,,,
+6259,"MAGNA-SIRGAS / Mocoa urban grid",9001,4686,6227,1052,1,0,4500,1039,655.2,9001,8801,1.082408409,9110,8802,-76.390367639,9110,8806,1047467.388,9001,8807,617828.474,9001,,,,,,,,,,,,,
+6260,"MAGNA-SIRGAS / Monteria urban grid",9001,4686,6228,1052,1,0,4500,1039,15,9001,8801,8.462310872,9110,8802,-75.524639199,9110,8806,1131814.934,9001,8807,1462131.119,9001,,,,,,,,,,,,,
+6261,"MAGNA-SIRGAS / Neiva urban grid",9001,4686,6229,1052,1,0,4500,1039,430,9001,8801,2.56326942,9110,8802,-75.17471722,9110,8806,864476.923,9001,8807,817199.827,9001,,,,,,,,,,,,,
+6262,"MAGNA-SIRGAS / Pasto urban grid",9001,4686,6230,1052,1,0,4500,1039,2530,9001,8801,1.120356225,9110,8802,-77.151125228,9110,8806,980469.695,9001,8807,624555.332,9001,,,,,,,,,,,,,
+6263,"MAGNA-SIRGAS / Pereira urban grid",9001,4686,6231,1052,1,0,4500,1039,1500,9001,8801,4.4848937,9110,8802,-75.4138225,9110,8806,1153492.012,9001,8807,1024195.255,9001,,,,,,,,,,,,,
+6264,"MAGNA-SIRGAS / Popayan urban grid",9001,4686,6232,1052,1,0,4500,1039,1740,9001,8801,2.272217558,9110,8802,-76.362192989,9110,8806,1052430.525,9001,8807,763366.548,9001,,,,,,,,,,,,,
+6265,"MAGNA-SIRGAS / Puerto Carreno urban grid",9001,4686,6233,1052,1,0,4500,1039,51.58,9001,8801,6.105059709,9110,8802,-67.300270089,9110,8806,1063834.703,9001,8807,1175257.481,9001,,,,,,,,,,,,,
+6266,"MAGNA-SIRGAS / Quibdo urban grid",9001,4686,6234,1052,1,0,4500,1039,44,9001,8801,5.413929158,9110,8802,-76.390271389,9110,8806,1047273.617,9001,8807,1121443.09,9001,,,,,,,,,,,,,
+6267,"MAGNA-SIRGAS / Riohacha urban grid",9001,4686,6235,1052,1,0,4500,1039,6,9001,8801,11.321288798,9110,8802,-72.540996793,9110,8806,1128154.73,9001,8807,1767887.914,9001,,,,,,,,,,,,,
+6268,"MAGNA-SIRGAS / San Andres urban grid",9001,4686,6236,1052,1,0,4500,1039,6,9001,8801,12.312565957,9110,8802,-81.434575342,9110,8806,820439.298,9001,8807,1877357.828,9001,,,,,,,,,,,,,
+6269,"MAGNA-SIRGAS / San Jose del Guaviare urban grid",9001,4686,6237,1052,1,0,4500,1039,185,9001,8801,2.335068419,9110,8802,-72.382411997,9110,8806,1159876.62,9001,8807,775380.342,9001,,,,,,,,,,,,,
+6270,"MAGNA-SIRGAS / Santa Marta urban grid",9001,4686,6238,1052,1,0,4500,1039,29,9001,8801,11.1310715,9110,8802,-74.1330019,9110,8806,983892.409,9001,8807,1732533.518,9001,,,,,,,,,,,,,
+6271,"MAGNA-SIRGAS / Sucre urban grid",9001,4686,6239,1052,1,0,4500,1039,20,9001,8801,8.483798132,9110,8802,-74.432088057,9110,8806,929043.607,9001,8807,1466125.658,9001,,,,,,,,,,,,,
+6272,"MAGNA-SIRGAS / Tunja urban grid",9001,4686,6240,1052,1,0,4500,1039,2800,9001,8801,5.320310106,9110,8802,-73.210698004,9110,8806,1080514.91,9001,8807,1103772.028,9001,,,,,,,,,,,,,
+6273,"MAGNA-SIRGAS / Valledupar urban grid",9001,4686,6241,1052,1,0,4500,1039,200,9001,8801,10.265014,9110,8802,-73.1447657,9110,8806,1090979.66,9001,8807,1647208.93,9001,,,,,,,,,,,,,
+6274,"MAGNA-SIRGAS / Villavicencio urban grid",9001,4686,6242,1052,1,0,4500,1039,427.19,9001,8801,4.091935036,9110,8802,-73.372814955,9110,8806,1050678.757,9001,8807,950952.124,9001,,,,,,,,,,,,,
+6275,"MAGNA-SIRGAS / Yopal urban grid",9001,4686,6243,1052,1,0,4500,1039,300,9001,8801,5.2114138,9110,8802,-72.2512145,9110,8806,851184.177,9001,8807,1083954.137,9001,,,,,,,,,,,,,
+6307,"NAD83(CORS96) / Puerto Rico and Virgin Is.",9001,6783,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,,,,,,,,
+6312,"CGRS93 / Cyprus Local Transverse Mercator",9001,6311,6308,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.99995,9201,8806,200000,9001,8807,-3500000,9001,,,,,,,,,,,,,
+6316,Macedonia State Coordinate System zone 7,9001,3906,18277,9807,1,0,4498,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+6328,"NAD83(2011) / UTM zone 59N",9001,6318,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6329,"NAD83(2011) / UTM zone 60N",9001,6318,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6330,"NAD83(2011) / UTM zone 1N",9001,6318,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6331,"NAD83(2011) / UTM zone 2N",9001,6318,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6332,"NAD83(2011) / UTM zone 3N",9001,6318,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6333,"NAD83(2011) / UTM zone 4N",9001,6318,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6334,"NAD83(2011) / UTM zone 5N",9001,6318,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6335,"NAD83(2011) / UTM zone 6N",9001,6318,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6336,"NAD83(2011) / UTM zone 7N",9001,6318,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6337,"NAD83(2011) / UTM zone 8N",9001,6318,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6338,"NAD83(2011) / UTM zone 9N",9001,6318,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6339,"NAD83(2011) / UTM zone 10N",9001,6318,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6340,"NAD83(2011) / UTM zone 11N",9001,6318,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6341,"NAD83(2011) / UTM zone 12N",9001,6318,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6342,"NAD83(2011) / UTM zone 13N",9001,6318,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6343,"NAD83(2011) / UTM zone 14N",9001,6318,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6344,"NAD83(2011) / UTM zone 15N",9001,6318,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6345,"NAD83(2011) / UTM zone 16N",9001,6318,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6346,"NAD83(2011) / UTM zone 17N",9001,6318,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6347,"NAD83(2011) / UTM zone 18N",9001,6318,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6348,"NAD83(2011) / UTM zone 19N",9001,6318,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6350,"NAD83(2011) / Conus Albers",9001,6318,5068,9822,1,0,4499,8821,23,9102,8822,-96,9102,8823,29.3,9110,8824,45.3,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+6351,"NAD83(2011) / EPSG Arctic zone 5-29",9001,6318,6029,9802,1,0,4400,8821,72.01300331,9110,8822,-163,9110,8823,73.4,9110,8824,70.2,9110,8826,29500000,9001,8827,5500000,9001,,,,,,,,,,
+6352,"NAD83(2011) / EPSG Arctic zone 5-31",9001,6318,6030,9802,1,0,4400,8821,72.01300331,9110,8822,-147,9110,8823,73.4,9110,8824,70.2,9110,8826,31500000,9001,8827,5500000,9001,,,,,,,,,,
+6353,"NAD83(2011) / EPSG Arctic zone 6-14",9001,6318,6039,9802,1,0,4400,8821,68.4114912,9110,8822,-165,9110,8823,70.2,9110,8824,67,9110,8826,14500000,9001,8827,6500000,9001,,,,,,,,,,
+6354,"NAD83(2011) / EPSG Arctic zone 6-16",9001,6318,6040,9802,1,0,4400,8821,68.4114912,9110,8822,-147,9110,8823,70.2,9110,8824,67,9110,8826,16500000,9001,8827,6500000,9001,,,,,,,,,,
+6355,"NAD83(2011) / Alabama East",9001,6318,10131,9807,1,0,4499,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+6356,"NAD83(2011) / Alabama West",9001,6318,10132,9807,1,0,4499,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,600000,9001,8807,0,9001,,,,,,,,,,,,,
+6362,"Mexico ITRF92 / LCC",9001,4483,6361,9802,1,0,4500,8821,12,9102,8822,-102,9102,8823,17.5,9102,8824,29.5,9102,8826,2500000,9001,8827,0,9001,,,,,,,,,,
+6366,"Mexico ITRF2008 / UTM zone 11N",9001,6365,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6367,"Mexico ITRF2008 / UTM zone 12N",9001,6365,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6368,"Mexico ITRF2008 / UTM zone 13N",9001,6365,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6369,"Mexico ITRF2008 / UTM zone 14N",9001,6365,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6370,"Mexico ITRF2008 / UTM zone 15N",9001,6365,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6371,"Mexico ITRF2008 / UTM zone 16N",9001,6365,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6372,"Mexico ITRF2008 / LCC",9001,6365,6361,9802,1,0,4500,8821,12,9102,8822,-102,9102,8823,17.5,9102,8824,29.5,9102,8826,2500000,9001,8827,0,9001,,,,,,,,,,
+6381,"UCS-2000 / Ukraine TM zone 7",9001,5561,6374,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6382,"UCS-2000 / Ukraine TM zone 8",9001,5561,6375,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6383,"UCS-2000 / Ukraine TM zone 9",9001,5561,6376,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6384,"UCS-2000 / Ukraine TM zone 10",9001,5561,6377,9807,1,0,4530,8801,0,9102,8802,30,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6385,"UCS-2000 / Ukraine TM zone 11",9001,5561,6378,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6386,"UCS-2000 / Ukraine TM zone 12",9001,5561,6379,9807,1,0,4530,8801,0,9102,8802,36,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6387,"UCS-2000 / Ukraine TM zone 13",9001,5561,6380,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6391,Cayman Islands National Grid 2011,9002,6135,6390,9802,1,0,1039,8821,19.2,9110,8822,-80.34,9110,8823,19.2,9110,8824,19.42,9110,8826,2950000,9002,8827,1900000,9002,,,,,,,,,,
+6393,"NAD83(2011) / Alaska Albers",9001,6318,15021,9822,1,0,4499,8821,50,9102,8822,-154,9102,8823,55,9102,8824,65,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+6394,"NAD83(2011) / Alaska zone 1",9001,6318,15031,9812,1,0,4499,8806,5000000,9001,8807,-5000000,9001,8811,57,9110,8812,-133.4,9110,8813,323.07483685,9110,8814,323.07483685,9110,8815,0.9999,9201,,,,,,,
+6395,"NAD83(2011) / Alaska zone 2",9001,6318,15032,9807,1,0,4499,8801,54,9102,8802,-142,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6396,"NAD83(2011) / Alaska zone 3",9001,6318,15033,9807,1,0,4499,8801,54,9102,8802,-146,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6397,"NAD83(2011) / Alaska zone 4",9001,6318,15034,9807,1,0,4499,8801,54,9102,8802,-150,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6398,"NAD83(2011) / Alaska zone 5",9001,6318,15035,9807,1,0,4499,8801,54,9102,8802,-154,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6399,"NAD83(2011) / Alaska zone 6",9001,6318,15036,9807,1,0,4499,8801,54,9102,8802,-158,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6400,"NAD83(2011) / Alaska zone 7",9001,6318,15037,9807,1,0,4499,8801,54,9102,8802,-162,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6401,"NAD83(2011) / Alaska zone 8",9001,6318,15038,9807,1,0,4499,8801,54,9102,8802,-166,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6402,"NAD83(2011) / Alaska zone 9",9001,6318,15039,9807,1,0,4499,8801,54,9102,8802,-170,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6403,"NAD83(2011) / Alaska zone 10",9001,6318,15040,9802,1,0,4499,8821,51,9110,8822,-176,9110,8823,53.5,9110,8824,51.5,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+6404,"NAD83(2011) / Arizona Central",9001,6318,10232,9807,1,0,4499,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+6405,"NAD83(2011) / Arizona Central (ft)",9002,6318,15305,9807,1,0,4495,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+6406,"NAD83(2011) / Arizona East",9001,6318,10231,9807,1,0,4499,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+6407,"NAD83(2011) / Arizona East (ft)",9002,6318,15304,9807,1,0,4495,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+6408,"NAD83(2011) / Arizona West",9001,6318,10233,9807,1,0,4499,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+6409,"NAD83(2011) / Arizona West (ft)",9002,6318,15306,9807,1,0,4495,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,700000,9002,8807,0,9002,,,,,,,,,,,,,
+6410,"NAD83(2011) / Arkansas North",9001,6318,10331,9802,1,0,4499,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+6411,"NAD83(2011) / Arkansas North (ftUS)",9003,6318,15385,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+6412,"NAD83(2011) / Arkansas South",9001,6318,10332,9802,1,0,4499,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+6413,"NAD83(2011) / Arkansas South (ftUS)",9003,6318,15386,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,,,,,,,,
+6414,"NAD83(2011) / California Albers",9001,6318,10420,9822,1,0,4499,8821,0,9102,8822,-120,9102,8823,34,9102,8824,40.5,9102,8826,0,9001,8827,-4000000,9001,,,,,,,,,,
+6415,"NAD83(2011) / California zone 1",9001,6318,10431,9802,1,0,4499,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+6416,"NAD83(2011) / California zone 1 (ftUS)",9003,6318,15307,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+6417,"NAD83(2011) / California zone 2",9001,6318,10432,9802,1,0,4499,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+6418,"NAD83(2011) / California zone 2 (ftUS)",9003,6318,15308,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+6419,"NAD83(2011) / California zone 3",9001,6318,10433,9802,1,0,4499,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+6420,"NAD83(2011) / California zone 3 (ftUS)",9003,6318,15309,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+6421,"NAD83(2011) / California zone 4",9001,6318,10434,9802,1,0,4499,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+6422,"NAD83(2011) / California zone 4 (ftUS)",9003,6318,15310,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+6423,"NAD83(2011) / California zone 5",9001,6318,10435,9802,1,0,4499,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+6424,"NAD83(2011) / California zone 5 (ftUS)",9003,6318,15311,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+6425,"NAD83(2011) / California zone 6",9001,6318,10436,9802,1,0,4499,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+6426,"NAD83(2011) / California zone 6 (ftUS)",9003,6318,15312,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,6561666.667,9003,8827,1640416.667,9003,,,,,,,,,,
+6427,"NAD83(2011) / Colorado Central",9001,6318,10532,9802,1,0,4499,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+6428,"NAD83(2011) / Colorado Central (ftUS)",9003,6318,15314,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+6429,"NAD83(2011) / Colorado North",9001,6318,10531,9802,1,0,4499,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+6430,"NAD83(2011) / Colorado North (ftUS)",9003,6318,15313,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+6431,"NAD83(2011) / Colorado South",9001,6318,10533,9802,1,0,4499,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+6432,"NAD83(2011) / Colorado South (ftUS)",9003,6318,15315,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,3000000,9003,8827,1000000,9003,,,,,,,,,,
+6433,"NAD83(2011) / Connecticut",9001,6318,10630,9802,1,0,4499,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,304800.6096,9001,8827,152400.3048,9001,,,,,,,,,,
+6434,"NAD83(2011) / Connecticut (ftUS)",9003,6318,15316,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,1000000,9003,8827,500000,9003,,,,,,,,,,
+6435,"NAD83(2011) / Delaware",9001,6318,10730,9807,1,0,4499,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+6436,"NAD83(2011) / Delaware (ftUS)",9003,6318,15317,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+6437,"NAD83(2011) / Florida East",9001,6318,10931,9807,1,0,4499,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+6438,"NAD83(2011) / Florida East (ftUS)",9003,6318,15318,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+6439,"NAD83(2011) / Florida GDL Albers",9001,6318,10934,9822,1,0,4499,8821,24,9110,8822,-84,9110,8823,24,9110,8824,31.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+6440,"NAD83(2011) / Florida North",9001,6318,10933,9802,1,0,4499,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6441,"NAD83(2011) / Florida North (ftUS)",9003,6318,15320,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6442,"NAD83(2011) / Florida West",9001,6318,10932,9807,1,0,4499,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+6443,"NAD83(2011) / Florida West (ftUS)",9003,6318,15319,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+6444,"NAD83(2011) / Georgia East",9001,6318,11031,9807,1,0,4499,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+6445,"NAD83(2011) / Georgia East (ftUS)",9003,6318,15321,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+6446,"NAD83(2011) / Georgia West",9001,6318,11032,9807,1,0,4499,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+6447,"NAD83(2011) / Georgia West (ftUS)",9003,6318,15322,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,2296583.333,9003,8807,0,9003,,,,,,,,,,,,,
+6448,"NAD83(2011) / Idaho Central",9001,6318,11132,9807,1,0,4499,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6449,"NAD83(2011) / Idaho Central (ftUS)",9003,6318,15324,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,1640416.667,9003,8807,0,9003,,,,,,,,,,,,,
+6450,"NAD83(2011) / Idaho East",9001,6318,11131,9807,1,0,4499,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+6451,"NAD83(2011) / Idaho East (ftUS)",9003,6318,15323,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,656166.667,9003,8807,0,9003,,,,,,,,,,,,,
+6452,"NAD83(2011) / Idaho West",9001,6318,11133,9807,1,0,4499,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,800000,9001,8807,0,9001,,,,,,,,,,,,,
+6453,"NAD83(2011) / Idaho West (ftUS)",9003,6318,15325,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,2624666.667,9003,8807,0,9003,,,,,,,,,,,,,
+6454,"NAD83(2011) / Illinois East",9001,6318,11231,9807,1,0,4499,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6455,"NAD83(2011) / Illinois East (ftUS)",9003,6318,15387,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+6456,"NAD83(2011) / Illinois West",9001,6318,11232,9807,1,0,4499,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+6457,"NAD83(2011) / Illinois West (ftUS)",9003,6318,15388,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,2296583.3333,9003,8807,0,9003,,,,,,,,,,,,,
+6458,"NAD83(2011) / Indiana East",9001,6318,11331,9807,1,0,4499,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,100000,9001,8807,250000,9001,,,,,,,,,,,,,
+6459,"NAD83(2011) / Indiana East (ftUS)",9003,6318,15372,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,328083.333,9003,8807,820208.333,9003,,,,,,,,,,,,,
+6460,"NAD83(2011) / Indiana West",9001,6318,11332,9807,1,0,4499,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,900000,9001,8807,250000,9001,,,,,,,,,,,,,
+6461,"NAD83(2011) / Indiana West (ftUS)",9003,6318,15373,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,2952750,9003,8807,820208.333,9003,,,,,,,,,,,,,
+6462,"NAD83(2011) / Iowa North",9001,6318,11431,9802,1,0,4499,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,1500000,9001,8827,1000000,9001,,,,,,,,,,
+6463,"NAD83(2011) / Iowa North (ftUS)",9003,6318,15377,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,4921250,9003,8827,3280833.3333,9003,,,,,,,,,,
+6464,"NAD83(2011) / Iowa South",9001,6318,11432,9802,1,0,4499,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+6465,"NAD83(2011) / Iowa South (ftUS)",9003,6318,15378,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+6466,"NAD83(2011) / Kansas North",9001,6318,11531,9802,1,0,4499,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+6467,"NAD83(2011) / Kansas North (ftUS)",9003,6318,15379,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+6468,"NAD83(2011) / Kansas South",9001,6318,11532,9802,1,0,4499,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+6469,"NAD83(2011) / Kansas South (ftUS)",9003,6318,15380,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,1312333.3333,9003,8827,1312333.3333,9003,,,,,,,,,,
+6470,"NAD83(2011) / Kentucky North",9001,6318,15303,9802,1,0,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+6471,"NAD83(2011) / Kentucky North (ftUS)",9003,6318,15328,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+6472,"NAD83(2011) / Kentucky Single Zone",9001,6318,11630,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,1500000,9001,8827,1000000,9001,,,,,,,,,,
+6473,"NAD83(2011) / Kentucky Single Zone (ftUS)",9003,6318,15375,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.05,9110,8824,38.4,9110,8826,4921250,9003,8827,3280833.333,9003,,,,,,,,,,
+6474,"NAD83(2011) / Kentucky South",9001,6318,11632,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+6475,"NAD83(2011) / Kentucky South (ftUS)",9003,6318,15329,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,1640416.667,9003,8827,1640416.667,9003,,,,,,,,,,
+6476,"NAD83(2011) / Louisiana North",9001,6318,11731,9802,1,0,4499,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+6477,"NAD83(2011) / Louisiana North (ftUS)",9003,6318,15391,9802,1,0,4497,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,3280833.3333,9003,8827,0,9003,,,,,,,,,,
+6478,"NAD83(2011) / Louisiana South",9001,6318,11732,9802,1,0,4499,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+6479,"NAD83(2011) / Louisiana South (ftUS)",9003,6318,15392,9802,1,0,4497,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,3280833.3333,9003,8827,0,9003,,,,,,,,,,
+6480,"NAD83(2011) / Maine CS2000 Central",9001,6318,11854,9807,1,0,4499,8801,43.3,9110,8802,-69.073,9110,8805,0.99998,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6481,"NAD83(2011) / Maine CS2000 East",9001,6318,11851,9807,1,0,4499,8801,43.5,9110,8802,-67.523,9110,8805,0.99998,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+6482,"NAD83(2011) / Maine CS2000 West",9001,6318,11853,9807,1,0,4499,8801,42.5,9110,8802,-70.223,9110,8805,0.99998,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6483,"NAD83(2011) / Maine East",9001,6318,11831,9807,1,0,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6484,"NAD83(2011) / Maine East (ftUS)",9003,6318,11833,9807,1,0,4497,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+6485,"NAD83(2011) / Maine West",9001,6318,11832,9807,1,0,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,900000,9001,8807,0,9001,,,,,,,,,,,,,
+6486,"NAD83(2011) / Maine West (ftUS)",9003,6318,11834,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,,,,,,,,
+6487,"NAD83(2011) / Maryland",9001,6318,11930,9802,1,0,4499,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+6488,"NAD83(2011) / Maryland (ftUS)",9003,6318,15330,9802,1,0,4497,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,1312333.333,9003,8827,0,9003,,,,,,,,,,
+6489,"NAD83(2011) / Massachusetts Island",9001,6318,12032,9802,1,0,4499,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+6490,"NAD83(2011) / Massachusetts Island (ftUS)",9003,6318,15332,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+6491,"NAD83(2011) / Massachusetts Mainland",9001,6318,12031,9802,1,0,4499,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,200000,9001,8827,750000,9001,,,,,,,,,,
+6492,"NAD83(2011) / Massachusetts Mainland (ftUS)",9003,6318,15331,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,656166.667,9003,8827,2460625,9003,,,,,,,,,,
+6493,"NAD83(2011) / Michigan Central",9001,6318,12142,9802,1,0,4499,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,6000000,9001,8827,0,9001,,,,,,,,,,
+6494,"NAD83(2011) / Michigan Central (ft)",9002,6318,15334,9802,1,0,4495,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,19685039.37,9002,8827,0,9002,,,,,,,,,,
+6495,"NAD83(2011) / Michigan North",9001,6318,12141,9802,1,0,4499,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,8000000,9001,8827,0,9001,,,,,,,,,,
+6496,"NAD83(2011) / Michigan North (ft)",9002,6318,15333,9802,1,0,4495,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,26246719.16,9002,8827,0,9002,,,,,,,,,,
+6497,"NAD83(2011) / Michigan Oblique Mercator",9001,6318,12150,9812,1,0,4499,8806,2546731.496,9001,8807,-4354009.816,9001,8811,45.1833,9110,8812,-86,9110,8813,337.25556,9102,8814,337.25556,9102,8815,0.9996,9201,,,,,,,
+6498,"NAD83(2011) / Michigan South",9001,6318,12143,9802,1,0,4499,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,4000000,9001,8827,0,9001,,,,,,,,,,
+6499,"NAD83(2011) / Michigan South (ft)",9002,6318,15335,9802,1,0,4495,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,13123359.58,9002,8827,0,9002,,,,,,,,,,
+6500,"NAD83(2011) / Minnesota Central",9001,6318,12232,9802,1,0,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+6501,"NAD83(2011) / Minnesota Central (ftUS)",9003,6318,12235,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+6502,"NAD83(2011) / Minnesota North",9001,6318,12231,9802,1,0,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+6503,"NAD83(2011) / Minnesota North (ftUS)",9003,6318,12234,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+6504,"NAD83(2011) / Minnesota South",9001,6318,12233,9802,1,0,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+6505,"NAD83(2011) / Minnesota South (ftUS)",9003,6318,12236,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+6506,"NAD83(2011) / Mississippi East",9001,6318,12331,9807,1,0,4499,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6507,"NAD83(2011) / Mississippi East (ftUS)",9003,6318,15336,9807,1,0,4497,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+6508,"NAD83(2011) / Mississippi TM",9001,6318,3813,9807,1,0,4499,8801,32.3,9110,8802,-89.45,9110,8805,0.9998335,9201,8806,500000,9001,8807,1300000,9001,,,,,,,,,,,,,
+6509,"NAD83(2011) / Mississippi West",9001,6318,12332,9807,1,0,4499,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+6510,"NAD83(2011) / Mississippi West (ftUS)",9003,6318,15337,9807,1,0,4497,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,2296583.333,9003,8807,0,9003,,,,,,,,,,,,,
+6511,"NAD83(2011) / Missouri Central",9001,6318,12432,9807,1,0,4499,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6512,"NAD83(2011) / Missouri East",9001,6318,12431,9807,1,0,4499,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+6513,"NAD83(2011) / Missouri West",9001,6318,12433,9807,1,0,4499,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,850000,9001,8807,0,9001,,,,,,,,,,,,,
+6514,"NAD83(2011) / Montana",9001,6318,12530,9802,1,0,4499,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6515,"NAD83(2011) / Montana (ft)",9002,6318,15338,9802,1,0,4495,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+6516,"NAD83(2011) / Nebraska",9001,6318,12630,9802,1,0,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+6517,"NAD83(2011) / Nebraska (ftUS)",9003,4759,15396,9802,1,1,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+6518,"NAD83(2011) / Nevada Central",9001,6318,12732,9807,1,0,4499,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9001,8807,6000000,9001,,,,,,,,,,,,,
+6519,"NAD83(2011) / Nevada Central (ftUS)",9003,6318,15382,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,1640416.6667,9003,8807,19685000,9003,,,,,,,,,,,,,
+6520,"NAD83(2011) / Nevada East",9001,6318,12731,9807,1,0,4499,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,200000,9001,8807,8000000,9001,,,,,,,,,,,,,
+6521,"NAD83(2011) / Nevada East (ftUS)",9003,6318,15381,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,656166.6667,9003,8807,26246666.6667,9003,,,,,,,,,,,,,
+6522,"NAD83(2011) / Nevada West",9001,6318,12733,9807,1,0,4499,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,800000,9001,8807,4000000,9001,,,,,,,,,,,,,
+6523,"NAD83(2011) / Nevada West (ftUS)",9003,6318,15383,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,2624666.6667,9003,8807,13123333.3333,9003,,,,,,,,,,,,,
+6524,"NAD83(2011) / New Hampshire",9001,6318,12830,9807,1,0,4499,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+6525,"NAD83(2011) / New Hampshire (ftUS)",9003,6318,15389,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+6526,"NAD83(2011) / New Jersey",9001,6318,12930,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+6527,"NAD83(2011) / New Jersey (ftUS)",9003,6318,15384,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,,,,,,,,
+6528,"NAD83(2011) / New Mexico Central",9001,6318,13032,9807,1,0,4499,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6529,"NAD83(2011) / New Mexico Central (ftUS)",9003,6318,15340,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,1640416.667,9003,8807,0,9003,,,,,,,,,,,,,
+6530,"NAD83(2011) / New Mexico East",9001,6318,13031,9807,1,0,4499,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,165000,9001,8807,0,9001,,,,,,,,,,,,,
+6531,"NAD83(2011) / New Mexico East (ftUS)",9003,6318,15339,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,541337.5,9003,8807,0,9003,,,,,,,,,,,,,
+6532,"NAD83(2011) / New Mexico West",9001,6318,13033,9807,1,0,4499,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,830000,9001,8807,0,9001,,,,,,,,,,,,,
+6533,"NAD83(2011) / New Mexico West (ftUS)",9003,6318,15341,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,2723091.667,9003,8807,0,9003,,,,,,,,,,,,,
+6534,"NAD83(2011) / New York Central",9001,6318,13132,9807,1,0,4499,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+6535,"NAD83(2011) / New York Central (ftUS)",9003,6318,15343,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,820208.333,9003,8807,0,9003,,,,,,,,,,,,,
+6536,"NAD83(2011) / New York East",9001,6318,13131,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+6537,"NAD83(2011) / New York East (ftUS)",9003,6318,15342,9807,1,0,4497,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,492125,9003,8807,0,9003,,,,,,,,,,,,,
+6538,"NAD83(2011) / New York Long Island",9001,6318,13134,9802,1,0,4499,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,300000,9001,8827,0,9001,,,,,,,,,,
+6539,"NAD83(2011) / New York Long Island (ftUS)",9003,6318,15345,9802,1,0,4497,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,984250,9003,8827,0,9003,,,,,,,,,,
+6540,"NAD83(2011) / New York West",9001,6318,13133,9807,1,0,4499,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,350000,9001,8807,0,9001,,,,,,,,,,,,,
+6541,"NAD83(2011) / New York West (ftUS)",9003,6318,15344,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,1148291.667,9003,8807,0,9003,,,,,,,,,,,,,
+6542,"NAD83(2011) / North Carolina",9001,6318,13230,9802,1,0,4499,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,609601.22,9001,8827,0,9001,,,,,,,,,,
+6543,"NAD83(2011) / North Carolina (ftUS)",9003,6318,15346,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+6544,"NAD83(2011) / North Dakota North",9001,6318,13331,9802,1,0,4499,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6545,"NAD83(2011) / North Dakota North (ft)",9002,6318,15347,9802,1,0,4495,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+6546,"NAD83(2011) / North Dakota South",9001,6318,13332,9802,1,0,4499,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6547,"NAD83(2011) / North Dakota South (ft)",9002,6318,15348,9802,1,0,4495,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,1968503.937,9002,8827,0,9002,,,,,,,,,,
+6548,"NAD83(2011) / Ohio North",9001,6318,13431,9802,1,0,4499,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6549,"NAD83(2011) / Ohio North (ftUS)",9003,6318,13433,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6550,"NAD83(2011) / Ohio South",9001,6318,13432,9802,1,0,4499,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6551,"NAD83(2011) / Ohio South (ftUS)",9003,6318,13434,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6552,"NAD83(2011) / Oklahoma North",9001,6318,13531,9802,1,0,4499,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6553,"NAD83(2011) / Oklahoma North (ftUS)",9003,6318,15349,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6554,"NAD83(2011) / Oklahoma South",9001,6318,13532,9802,1,0,4499,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6555,"NAD83(2011) / Oklahoma South (ftUS)",9003,6318,15350,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6556,"NAD83(2011) / Oregon LCC (m)",9001,6318,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+6557,"NAD83(2011) / Oregon GIC Lambert (ft)",9002,6318,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,,,,,,,,
+6558,"NAD83(2011) / Oregon North",9001,6318,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,,,,,,,,
+6559,"NAD83(2011) / Oregon North (ft)",9002,6318,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,,,,,,,,
+6560,"NAD83(2011) / Oregon South",9001,6318,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,,,,,,,,
+6561,"NAD83(2011) / Oregon South (ft)",9002,6318,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,,,,,,,,
+6562,"NAD83(2011) / Pennsylvania North",9001,6318,13731,9802,1,0,4499,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6563,"NAD83(2011) / Pennsylvania North (ftUS)",9003,6318,15353,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6564,"NAD83(2011) / Pennsylvania South",9001,6318,13732,9802,1,0,4499,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6565,"NAD83(2011) / Pennsylvania South (ftUS)",9003,6318,15354,9802,1,0,4497,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6566,"NAD83(2011) / Puerto Rico and Virgin Is.",9001,6318,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,,,,,,,,
+6567,"NAD83(2011) / Rhode Island",9001,6318,13830,9807,1,0,4499,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,100000,9001,8807,0,9001,,,,,,,,,,,,,
+6568,"NAD83(2011) / Rhode Island (ftUS)",9003,6318,15390,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,328083.3333,9003,8807,0,9003,,,,,,,,,,,,,
+6569,"NAD83(2011) / South Carolina",9001,6318,13930,9802,1,0,4499,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,609600,9001,8827,0,9001,,,,,,,,,,
+6570,"NAD83(2011) / South Carolina (ft)",9002,6318,15355,9802,1,0,4495,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,2000000,9002,8827,0,9002,,,,,,,,,,
+6571,"NAD83(2011) / South Dakota North",9001,6318,14031,9802,1,0,4499,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6572,"NAD83(2011) / South Dakota North (ftUS)",9003,6318,15394,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6573,"NAD83(2011) / South Dakota South",9001,6318,14032,9802,1,0,4499,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6574,"NAD83(2011) / South Dakota South (ftUS)",9003,6318,15395,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6575,"NAD83(2011) / Tennessee",9001,6318,14130,9802,1,0,4499,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6576,"NAD83(2011) / Tennessee (ftUS)",9003,6318,15356,9802,1,0,4497,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6577,"NAD83(2011) / Texas Central",9001,6318,14233,9802,1,0,4499,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,700000,9001,8827,3000000,9001,,,,,,,,,,
+6578,"NAD83(2011) / Texas Central (ftUS)",9003,6318,15359,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,2296583.333,9003,8827,9842500,9003,,,,,,,,,,
+6579,"NAD83(2011) / Texas Centric Albers Equal Area",9001,6318,14254,9822,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,6000000,9001,,,,,,,,,,
+6580,"NAD83(2011) / Texas Centric Lambert Conformal",9001,6318,14253,9802,1,0,4499,8821,18,9110,8822,-100,9110,8823,27.3,9110,8824,35,9110,8826,1500000,9001,8827,5000000,9001,,,,,,,,,,
+6581,"NAD83(2011) / Texas North",9001,6318,14231,9802,1,0,4499,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,200000,9001,8827,1000000,9001,,,,,,,,,,
+6582,"NAD83(2011) / Texas North (ftUS)",9003,6318,15357,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,656166.667,9003,8827,3280833.333,9003,,,,,,,,,,
+6583,"NAD83(2011) / Texas North Central",9001,6318,14232,9802,1,0,4499,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,600000,9001,8827,2000000,9001,,,,,,,,,,
+6584,"NAD83(2011) / Texas North Central (ftUS)",9003,6318,15358,9802,1,0,4497,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,1968500,9003,8827,6561666.667,9003,,,,,,,,,,
+6585,"NAD83(2011) / Texas South",9001,6318,14235,9802,1,0,4499,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,300000,9001,8827,5000000,9001,,,,,,,,,,
+6586,"NAD83(2011) / Texas South (ftUS)",9003,6318,15361,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,984250,9003,8827,16404166.667,9003,,,,,,,,,,
+6587,"NAD83(2011) / Texas South Central",9001,6318,14234,9802,1,0,4499,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,600000,9001,8827,4000000,9001,,,,,,,,,,
+6588,"NAD83(2011) / Texas South Central (ftUS)",9003,6318,15360,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,1968500,9003,8827,13123333.333,9003,,,,,,,,,,
+6589,"NAD83(2011) / Vermont",9001,6318,14430,9807,1,0,4499,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6590,"NAD83(2011) / Vermont (ftUS)",9003,6318,5645,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,,,,,,,,
+6591,"NAD83(2011) / Virginia Lambert",9001,6318,3967,9802,1,0,4499,8821,36,9102,8822,-79.5,9102,8823,37,9102,8824,39.5,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+6592,"NAD83(2011) / Virginia North",9001,6318,14531,9802,1,0,4499,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,3500000,9001,8827,2000000,9001,,,,,,,,,,
+6593,"NAD83(2011) / Virginia North (ftUS)",9003,6318,15365,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,11482916.667,9003,8827,6561666.667,9003,,,,,,,,,,
+6594,"NAD83(2011) / Virginia South",9001,6318,14532,9802,1,0,4499,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,3500000,9001,8827,1000000,9001,,,,,,,,,,
+6595,"NAD83(2011) / Virginia South (ftUS)",9003,6318,15366,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,11482916.667,9003,8827,3280833.333,9003,,,,,,,,,,
+6596,"NAD83(2011) / Washington North",9001,6318,14631,9802,1,0,4499,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+6597,"NAD83(2011) / Washington North (ftUS)",9003,6318,15367,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+6598,"NAD83(2011) / Washington South",9001,6318,14632,9802,1,0,4499,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+6599,"NAD83(2011) / Washington South (ftUS)",9003,6318,15368,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,1640416.667,9003,8827,0,9003,,,,,,,,,,
+6600,"NAD83(2011) / West Virginia North",9001,6318,14731,9802,1,0,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6601,"NAD83(2011) / West Virginia North (ftUS)",9003,6318,14735,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6602,"NAD83(2011) / West Virginia South",9001,6318,14732,9802,1,0,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6603,"NAD83(2011) / West Virginia South (ftUS)",9003,6318,14736,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6604,"NAD83(2011) / Wisconsin Central",9001,4759,14832,9802,1,1,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6605,"NAD83(2011) / Wisconsin Central (ftUS)",9003,6318,15370,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6606,"NAD83(2011) / Wisconsin North",9001,6318,14831,9802,1,0,4499,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6607,"NAD83(2011) / Wisconsin North (ftUS)",9003,6318,15369,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6608,"NAD83(2011) / Wisconsin South",9001,6318,14833,9802,1,0,4499,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6609,"NAD83(2011) / Wisconsin South (ftUS)",9003,6318,15371,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+6610,"NAD83(2011) / Wisconsin Transverse Mercator",9001,6318,14841,9807,1,0,4499,8801,0,9102,8802,-90,9102,8805,0.9996,9201,8806,520000,9001,8807,-4480000,9001,,,,,,,,,,,,,
+6611,"NAD83(2011) / Wyoming East",9001,6318,14931,9807,1,0,4499,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+6612,"NAD83(2011) / Wyoming East (ftUS)",9003,6318,14935,9807,1,0,4497,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,656166.6667,9003,8807,0,9003,,,,,,,,,,,,,
+6613,"NAD83(2011) / Wyoming East Central",9001,6318,14932,9807,1,0,4499,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,400000,9001,8807,100000,9001,,,,,,,,,,,,,
+6614,"NAD83(2011) / Wyoming East Central (ftUS)",9003,6318,14936,9807,1,0,4497,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,1312333.3333,9003,8807,328083.3333,9003,,,,,,,,,,,,,
+6615,"NAD83(2011) / Wyoming West",9001,6318,14934,9807,1,0,4499,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,800000,9001,8807,100000,9001,,,,,,,,,,,,,
+6616,"NAD83(2011) / Wyoming West (ftUS)",9003,6318,14938,9807,1,0,4497,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,2624666.6667,9003,8807,328083.3333,9003,,,,,,,,,,,,,
+6617,"NAD83(2011) / Wyoming West Central",9001,6318,14933,9807,1,0,4499,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,600000,9001,8807,0,9001,,,,,,,,,,,,,
+6618,"NAD83(2011) / Wyoming West Central (ftUS)",9003,6318,14937,9807,1,0,4497,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,1968500,9003,8807,0,9003,,,,,,,,,,,,,
+6619,"NAD83(2011) / Utah Central",9001,6318,14332,9802,1,0,4499,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,500000,9001,8827,2000000,9001,,,,,,,,,,
+6620,"NAD83(2011) / Utah North",9001,6318,14331,9802,1,0,4499,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,500000,9001,8827,1000000,9001,,,,,,,,,,
+6621,"NAD83(2011) / Utah South",9001,6318,14333,9802,1,0,4499,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,500000,9001,8827,3000000,9001,,,,,,,,,,
+6622,"NAD83(CSRS) / Quebec Lambert",9001,4617,19944,9802,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+6623,"NAD83 / Quebec Albers",9001,4269,6645,9822,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+6624,"NAD83(CSRS) / Quebec Albers",9001,4617,6645,9822,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+6625,"NAD83(2011) / Utah Central (ftUS)",9003,6318,15298,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,1640416.6667,9003,8827,6561666.6667,9003,,,,,,,,,,
+6626,"NAD83(2011) / Utah North (ftUS)",9003,6318,15297,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,1640416.6667,9003,8827,3280833.3333,9003,,,,,,,,,,
+6627,"NAD83(2011) / Utah South (ftUS)",9003,6318,15299,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,1640416.6667,9003,8827,9842500,9003,,,,,,,,,,
+6628,"NAD83(PA11) / Hawaii zone 1",9001,6322,15131,9807,1,0,4499,8801,18.5,9110,8802,-155.3,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6629,"NAD83(PA11) / Hawaii zone 2",9001,6322,15132,9807,1,0,4499,8801,20.2,9110,8802,-156.4,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6630,"NAD83(PA11) / Hawaii zone 3",9001,6322,15133,9807,1,0,4499,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6631,"NAD83(PA11) / Hawaii zone 4",9001,6322,15134,9807,1,0,4499,8801,21.5,9110,8802,-159.3,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6632,"NAD83(PA11) / Hawaii zone 5",9001,6322,15135,9807,1,0,4499,8801,21.4,9110,8802,-160.1,9110,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6633,"NAD83(PA11) / Hawaii zone 3 (ftUS)",9003,6322,15138,9807,1,0,4497,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,1640416.6667,9003,8807,0,9003,,,,,,,,,,,,,
+6634,"NAD83(PA11) / UTM zone 4N",9001,6322,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6635,"NAD83(PA11) / UTM zone 5N",9001,6322,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6636,"NAD83(PA11) / UTM zone 2S",9001,6322,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+6637,"NAD83(MA11) / Guam Map Grid",9001,6325,4325,9807,1,0,4499,8801,13.3,9110,8802,144.45,9110,8805,1,9201,8806,100000,9001,8807,200000,9001,,,,,,,,,,,,,
+6646,"Karbala 1979 / Iraq National Grid",9001,4743,19907,9807,1,0,4400,8801,29.0134566,9110,8802,46.3,9110,8805,0.9994,9201,8806,800000,9001,8807,0,9001,,,,,,,,,,,,,
+6669,"JGD2011 / Japan Plane Rectangular CS I",9001,6668,17801,9807,1,0,4530,8801,33,9110,8802,129.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6670,"JGD2011 / Japan Plane Rectangular CS II",9001,6668,17802,9807,1,0,4530,8801,33,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6671,"JGD2011 / Japan Plane Rectangular CS III",9001,6668,17803,9807,1,0,4530,8801,36,9110,8802,132.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6672,"JGD2011 / Japan Plane Rectangular CS IV",9001,6668,17804,9807,1,0,4530,8801,33,9110,8802,133.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6673,"JGD2011 / Japan Plane Rectangular CS V",9001,6668,17805,9807,1,0,4530,8801,36,9110,8802,134.2,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6674,"JGD2011 / Japan Plane Rectangular CS VI",9001,6668,17806,9807,1,0,4530,8801,36,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6675,"JGD2011 / Japan Plane Rectangular CS VII",9001,6668,17807,9807,1,0,4530,8801,36,9110,8802,137.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6676,"JGD2011 / Japan Plane Rectangular CS VIII",9001,6668,17808,9807,1,0,4530,8801,36,9110,8802,138.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6677,"JGD2011 / Japan Plane Rectangular CS IX",9001,6668,17809,9807,1,0,4530,8801,36,9110,8802,139.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6678,"JGD2011 / Japan Plane Rectangular CS X",9001,6668,17810,9807,1,0,4530,8801,40,9110,8802,140.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6679,"JGD2011 / Japan Plane Rectangular CS XI",9001,6668,17811,9807,1,0,4530,8801,44,9110,8802,140.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6680,"JGD2011 / Japan Plane Rectangular CS XII",9001,6668,17812,9807,1,0,4530,8801,44,9110,8802,142.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6681,"JGD2011 / Japan Plane Rectangular CS XIII",9001,6668,17813,9807,1,0,4530,8801,44,9110,8802,144.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6682,"JGD2011 / Japan Plane Rectangular CS XIV",9001,6668,17814,9807,1,0,4530,8801,26,9110,8802,142,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6683,"JGD2011 / Japan Plane Rectangular CS XV",9001,6668,17815,9807,1,0,4530,8801,26,9110,8802,127.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6684,"JGD2011 / Japan Plane Rectangular CS XVI",9001,6668,17816,9807,1,0,4530,8801,26,9110,8802,124,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6685,"JGD2011 / Japan Plane Rectangular CS XVII",9001,6668,17817,9807,1,0,4530,8801,26,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6686,"JGD2011 / Japan Plane Rectangular CS XVIII",9001,6668,17818,9807,1,0,4530,8801,20,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6687,"JGD2011 / Japan Plane Rectangular CS XIX",9001,6668,17819,9807,1,0,4530,8801,26,9110,8802,154,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6688,"JGD2011 / UTM zone 51N",9001,6668,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6689,"JGD2011 / UTM zone 52N",9001,6668,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6690,"JGD2011 / UTM zone 53N",9001,6668,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6691,"JGD2011 / UTM zone 54N",9001,6668,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6692,"JGD2011 / UTM zone 55N",9001,6668,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6703,"WGS 84 / TM 60 SW",9001,4326,6702,9807,1,0,4400,8801,0,9102,8802,-60,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+6707,"RDN2008 / UTM zone 32N (N-E)",9001,6706,16032,9807,1,0,4500,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6708,"RDN2008 / UTM zone 33N (N-E)",9001,6706,16033,9807,1,0,4500,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6709,"RDN2008 / UTM zone 34N (N-E)",9001,6706,16034,9807,1,0,4500,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6720,"WGS 84 / CIG92",9001,4326,6716,9807,1,0,4400,8801,0,9110,8802,105.373,9110,8805,1.000024,9201,8806,50000,9001,8807,1300000,9001,,,,,,,,,,,,,
+6721,"GDA94 / CIG94",9001,4283,6717,9807,1,0,4400,8801,0,9110,8802,105.373,9110,8805,1.00002514,9201,8806,50000,9001,8807,1300000,9001,,,,,,,,,,,,,
+6722,"WGS 84 / CKIG92",9001,4326,6718,9807,1,0,4400,8801,0,9110,8802,96.523,9110,8805,1,9201,8806,50000,9001,8807,1400000,9001,,,,,,,,,,,,,
+6723,"GDA94 / CKIG94",9001,4283,6719,9807,1,0,4400,8801,0,9110,8802,96.523,9110,8805,0.99999387,9201,8806,50000,9001,8807,1500000,9001,,,,,,,,,,,,,
+6732,"GDA94 / MGA zone 41",9001,4283,6725,9807,1,1,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+6733,"GDA94 / MGA zone 42",9001,4283,6726,9807,1,1,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+6734,"GDA94 / MGA zone 43",9001,4283,6727,9807,1,1,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+6735,"GDA94 / MGA zone 44",9001,4283,6728,9807,1,1,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+6736,"GDA94 / MGA zone 46",9001,4283,6729,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+6737,"GDA94 / MGA zone 47",9001,4283,6730,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+6738,"GDA94 / MGA zone 59",9001,4283,6731,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+6784,"NAD83(CORS96) / Oregon Baker zone (m)",9001,6783,6741,9807,1,0,4499,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,40000,9001,8807,0,9001,,,,,,,,,,,,,
+6785,"NAD83(CORS96) / Oregon Baker zone (ft)",9002,6783,6742,9807,1,0,4495,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,131233.5958,9002,8807,0,9002,,,,,,,,,,,,,
+6786,"NAD83(2011) / Oregon Baker zone (m)",9001,6318,6741,9807,1,0,4499,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,40000,9001,8807,0,9001,,,,,,,,,,,,,
+6787,"NAD83(2011) / Oregon Baker zone (ft)",9002,6318,6742,9807,1,0,4495,8801,44.3,9110,8802,-117.5,9110,8805,1.00016,9201,8806,131233.5958,9002,8807,0,9002,,,,,,,,,,,,,
+6788,"NAD83(CORS96) / Oregon Bend-Klamath Falls zone (m)",9001,6783,6743,9807,1,0,4499,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,80000,9001,8807,0,9001,,,,,,,,,,,,,
+6789,"NAD83(CORS96) / Oregon Bend-Klamath Falls zone (ft)",9002,6783,6744,9807,1,0,4495,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,262467.1916,9002,8807,0,9002,,,,,,,,,,,,,
+6790,"NAD83(2011) / Oregon Bend-Klamath Falls zone (m)",9001,6318,6743,9807,1,0,4499,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,80000,9001,8807,0,9001,,,,,,,,,,,,,
+6791,"NAD83(2011) / Oregon Bend-Klamath Falls zone (ft)",9002,6318,6744,9807,1,0,4495,8801,41.45,9110,8802,-121.45,9110,8805,1.0002,9201,8806,262467.1916,9002,8807,0,9002,,,,,,,,,,,,,
+6792,"NAD83(CORS96) / Oregon Bend-Redmond-Prineville zone (m)",9001,6783,6745,9801,1,0,4499,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,80000,9001,8807,130000,9001,,,,,,,,,,,,,
+6793,"NAD83(CORS96) / Oregon Bend-Redmond-Prineville zone (ft)",9002,6783,6746,9801,1,0,4495,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,262467.1916,9002,8807,426509.1864,9002,,,,,,,,,,,,,
+6794,"NAD83(2011) / Oregon Bend-Redmond-Prineville zone (m)",9001,6318,6745,9801,1,0,4499,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,80000,9001,8807,130000,9001,,,,,,,,,,,,,
+6795,"NAD83(2011) / Oregon Bend-Redmond-Prineville zone (ft)",9002,6318,6746,9801,1,0,4495,8801,44.4,9110,8802,-121.15,9110,8805,1.00012,9201,8806,262467.1916,9002,8807,426509.1864,9002,,,,,,,,,,,,,
+6796,"NAD83(CORS96) / Oregon Bend-Burns zone (m)",9001,6783,6747,9801,1,0,4499,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,120000,9001,8807,60000,9001,,,,,,,,,,,,,
+6797,"NAD83(CORS96) / Oregon Bend-Burns zone (ft)",9002,6783,6748,9801,1,0,4495,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,393700.7874,9002,8807,196850.3937,9002,,,,,,,,,,,,,
+6798,"NAD83(2011) / Oregon Bend-Burns zone (m)",9001,6318,6747,9801,1,0,4499,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,120000,9001,8807,60000,9001,,,,,,,,,,,,,
+6799,"NAD83(2011) / Oregon Bend-Burns zone (ft)",9002,6318,6748,9801,1,0,4495,8801,43.4,9110,8802,-119.45,9110,8805,1.0002,9201,8806,393700.7874,9002,8807,196850.3937,9002,,,,,,,,,,,,,
+6800,"NAD83(CORS96) / Oregon Canyonville-Grants Pass zone (m)",9001,6783,6749,9807,1,0,4499,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,40000,9001,8807,0,9001,,,,,,,,,,,,,
+6801,"NAD83(CORS96) / Oregon Canyonville-Grants Pass zone (ft)",9002,6783,6750,9807,1,0,4495,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,131233.5958,9002,8807,0,9002,,,,,,,,,,,,,
+6802,"NAD83(2011) / Oregon Canyonville-Grants Pass zone (m)",9001,6318,6749,9807,1,0,4499,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,40000,9001,8807,0,9001,,,,,,,,,,,,,
+6803,"NAD83(2011) / Oregon Canyonville-Grants Pass zone (ft)",9002,6318,6750,9807,1,0,4495,8801,42.3,9110,8802,-123.2,9110,8805,1.00007,9201,8806,131233.5958,9002,8807,0,9002,,,,,,,,,,,,,
+6804,"NAD83(CORS96) / Oregon Columbia River East zone (m)",9001,6783,6751,9801,1,0,4499,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,150000,9001,8807,30000,9001,,,,,,,,,,,,,
+6805,"NAD83(CORS96) / Oregon Columbia River East zone (ft)",9002,6783,6752,9801,1,0,4495,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,492125.9843,9002,8807,98425.1969,9002,,,,,,,,,,,,,
+6806,"NAD83(2011) / Oregon Columbia River East zone (m)",9001,6318,6751,9801,1,0,4499,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,150000,9001,8807,30000,9001,,,,,,,,,,,,,
+6807,"NAD83(2011) / Oregon Columbia River East zone (ft)",9002,6318,6752,9801,1,0,4495,8801,45.4,9110,8802,-120.3,9110,8805,1.000008,9201,8806,492125.9843,9002,8807,98425.1969,9002,,,,,,,,,,,,,
+6808,"NAD83(CORS96) / Oregon Columbia River West zone (m)",9001,6783,6753,9812,1,0,4499,8806,7000000,9001,8807,-3000000,9001,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201,,,,,,,
+6809,"NAD83(CORS96) / Oregon Columbia River West zone (ft)",9002,6783,6754,9812,1,0,4495,8806,22965879.2651,9002,8807,-9842519.685,9002,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201,,,,,,,
+6810,"NAD83(2011) / Oregon Columbia River West zone (m)",9001,6318,6753,9812,1,0,4499,8806,7000000,9001,8807,-3000000,9001,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201,,,,,,,
+6811,"NAD83(2011) / Oregon Columbia River West zone (ft)",9002,6318,6754,9812,1,0,4495,8806,22965879.2651,9002,8807,-9842519.685,9002,8811,45.55,9110,8812,-123,9110,8813,295,9102,8814,295,9102,8815,1,9201,,,,,,,
+6812,"NAD83(CORS96) / Oregon Cottage Grove-Canyonville zone (m)",9001,6783,6755,9807,1,0,4499,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,50000,9001,8807,0,9001,,,,,,,,,,,,,
+6813,"NAD83(CORS96) / Oregon Cottage Grove-Canyonville zone (ft)",9002,6783,6756,9807,1,0,4495,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,164041.9948,9002,8807,0,9002,,,,,,,,,,,,,
+6814,"NAD83(2011) / Oregon Cottage Grove-Canyonville zone (m)",9001,6318,6755,9807,1,0,4499,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,50000,9001,8807,0,9001,,,,,,,,,,,,,
+6815,"NAD83(2011) / Oregon Cottage Grove-Canyonville zone (ft)",9002,6318,6756,9807,1,0,4495,8801,42.5,9110,8802,-123.2,9110,8805,1.000023,9201,8806,164041.9948,9002,8807,0,9002,,,,,,,,,,,,,
+6816,"NAD83(CORS96) / Oregon Dufur-Madras zone (m)",9001,6783,6757,9807,1,0,4499,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,80000,9001,8807,0,9001,,,,,,,,,,,,,
+6817,"NAD83(CORS96) / Oregon Dufur-Madras zone (ft)",9002,6783,6758,9807,1,0,4495,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,262467.1916,9002,8807,0,9002,,,,,,,,,,,,,
+6818,"NAD83(2011) / Oregon Dufur-Madras zone (m)",9001,6318,6757,9807,1,0,4499,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,80000,9001,8807,0,9001,,,,,,,,,,,,,
+6819,"NAD83(2011) / Oregon Dufur-Madras zone (ft)",9002,6318,6758,9807,1,0,4495,8801,44.3,9110,8802,-121,9110,8805,1.00011,9201,8806,262467.1916,9002,8807,0,9002,,,,,,,,,,,,,
+6820,"NAD83(CORS96) / Oregon Eugene zone (m)",9001,6783,6759,9807,1,0,4499,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,50000,9001,8807,0,9001,,,,,,,,,,,,,
+6821,"NAD83(CORS96) / Oregon Eugene zone (ft)",9002,6783,6760,9807,1,0,4495,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,164041.9948,9002,8807,0,9002,,,,,,,,,,,,,
+6822,"NAD83(2011) / Oregon Eugene zone (m)",9001,6318,6759,9807,1,0,4499,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,50000,9001,8807,0,9001,,,,,,,,,,,,,
+6823,"NAD83(2011) / Oregon Eugene zone (ft)",9002,6318,6760,9807,1,0,4495,8801,43.45,9110,8802,-123.1,9110,8805,1.000015,9201,8806,164041.9948,9002,8807,0,9002,,,,,,,,,,,,,
+6824,"NAD83(CORS96) / Oregon Grants Pass-Ashland zone (m)",9001,6783,6761,9807,1,0,4499,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,50000,9001,8807,0,9001,,,,,,,,,,,,,
+6825,"NAD83(CORS96) / Oregon Grants Pass-Ashland zone (ft)",9002,6783,6762,9807,1,0,4495,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,164041.9948,9002,8807,0,9002,,,,,,,,,,,,,
+6826,"NAD83(2011) / Oregon Grants Pass-Ashland zone (m)",9001,6318,6761,9807,1,0,4499,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,50000,9001,8807,0,9001,,,,,,,,,,,,,
+6827,"NAD83(2011) / Oregon Grants Pass-Ashland zone (ft)",9002,6318,6762,9807,1,0,4495,8801,41.45,9110,8802,-123.2,9110,8805,1.000043,9201,8806,164041.9948,9002,8807,0,9002,,,,,,,,,,,,,
+6828,"NAD83(CORS96) / Oregon Gresham-Warm Springs zone (m)",9001,6783,6763,9807,1,0,4499,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,10000,9001,8807,0,9001,,,,,,,,,,,,,
+6829,"NAD83(CORS96) / Oregon Gresham-Warm Springs zone (ft)",9002,6783,6764,9807,1,0,4495,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,32808.399,9002,8807,0,9002,,,,,,,,,,,,,
+6830,"NAD83(2011) / Oregon Gresham-Warm Springs zone (m)",9001,6318,6763,9807,1,0,4499,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,10000,9001,8807,0,9001,,,,,,,,,,,,,
+6831,"NAD83(2011) / Oregon Gresham-Warm Springs zone (ft)",9002,6318,6764,9807,1,0,4495,8801,45,9110,8802,-122.2,9110,8805,1.00005,9201,8806,32808.399,9002,8807,0,9002,,,,,,,,,,,,,
+6832,"NAD83(CORS96) / Oregon La Grande zone (m)",9001,6783,6765,9807,1,0,4499,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,40000,9001,8807,0,9001,,,,,,,,,,,,,
+6833,"NAD83(CORS96) / Oregon La Grande zone (ft)",9002,6783,6766,9807,1,0,4495,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,131233.5958,9002,8807,0,9002,,,,,,,,,,,,,
+6834,"NAD83(2011) / Oregon La Grande zone (m)",9001,6318,6765,9807,1,0,4499,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,40000,9001,8807,0,9001,,,,,,,,,,,,,
+6835,"NAD83(2011) / Oregon La Grande zone (ft)",9002,6318,6766,9807,1,0,4495,8801,45,9102,8802,-118,9102,8805,1.00013,9201,8806,131233.5958,9002,8807,0,9002,,,,,,,,,,,,,
+6836,"NAD83(CORS96) / Oregon Ontario zone (m)",9001,6783,6767,9807,1,0,4499,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,80000,9001,8807,0,9001,,,,,,,,,,,,,
+6837,"NAD83(CORS96) / Oregon Ontario zone (ft)",9002,6783,6768,9807,1,0,4495,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,262467.1916,9002,8807,0,9002,,,,,,,,,,,,,
+6838,"NAD83(2011) / Oregon Ontario zone (m)",9001,6318,6767,9807,1,0,4499,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,80000,9001,8807,0,9001,,,,,,,,,,,,,
+6839,"NAD83(2011) / Oregon Ontario zone (ft)",9002,6318,6768,9807,1,0,4495,8801,43.15,9110,8802,-117,9110,8805,1.0001,9201,8806,262467.1916,9002,8807,0,9002,,,,,,,,,,,,,
+6840,"NAD83(CORS96) / Oregon Coast zone (m)",9001,6783,6769,9812,1,0,4499,8806,-300000,9001,8807,-4600000,9001,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201,,,,,,,
+6841,"NAD83(CORS96) / Oregon Coast zone (ft)",9002,6783,6770,9812,1,0,4495,8806,-984251.9685,9002,8807,-15091863.5171,9002,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201,,,,,,,
+6842,"NAD83(2011) / Oregon Coast zone (m)",9001,6318,6769,9812,1,0,4499,8806,-300000,9001,8807,-4600000,9001,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201,,,,,,,
+6843,"NAD83(2011) / Oregon Coast zone (ft)",9002,6318,6770,9812,1,0,4495,8806,-984251.9685,9002,8807,-15091863.5171,9002,8811,44.45,9110,8812,-124.03,9110,8813,5,9102,8814,5,9102,8815,1,9201,,,,,,,
+6844,"NAD83(CORS96) / Oregon Pendleton zone (m)",9001,6783,6771,9807,1,0,4499,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,60000,9001,8807,0,9001,,,,,,,,,,,,,
+6845,"NAD83(CORS96) / Oregon Pendleton zone (ft)",9002,6783,6772,9807,1,0,4495,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,196850.3937,9002,8807,0,9002,,,,,,,,,,,,,
+6846,"NAD83(2011) / Oregon Pendleton zone (m)",9001,6318,6771,9807,1,0,4499,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,60000,9001,8807,0,9001,,,,,,,,,,,,,
+6847,"NAD83(2011) / Oregon Pendleton zone (ft)",9002,6318,6772,9807,1,0,4495,8801,45.15,9110,8802,-119.1,9110,8805,1.000045,9201,8806,196850.3937,9002,8807,0,9002,,,,,,,,,,,,,
+6848,"NAD83(CORS96) / Oregon Pendleton-La Grande zone (m)",9001,6783,6773,9807,1,0,4499,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,30000,9001,8807,0,9001,,,,,,,,,,,,,
+6849,"NAD83(CORS96) / Oregon Pendleton-La Grande zone (ft)",9002,6783,6774,9807,1,0,4495,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,98425.1969,9002,8807,0,9002,,,,,,,,,,,,,
+6850,"NAD83(2011) / Oregon Pendleton-La Grande zone (m)",9001,6318,6773,9807,1,0,4499,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,30000,9001,8807,0,9001,,,,,,,,,,,,,
+6851,"NAD83(2011) / Oregon Pendleton-La Grande zone (ft)",9002,6318,6774,9807,1,0,4495,8801,45.05,9110,8802,-118.2,9110,8805,1.000175,9201,8806,98425.1969,9002,8807,0,9002,,,,,,,,,,,,,
+6852,"NAD83(CORS96) / Oregon Portland zone (m)",9001,6783,6775,9801,1,0,4499,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,100000,9001,8807,50000,9001,,,,,,,,,,,,,
+6853,"NAD83(CORS96) / Oregon Portland zone (ft)",9002,6783,6776,9801,1,0,4495,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,328083.9895,9002,8807,164041.9948,9002,,,,,,,,,,,,,
+6854,"NAD83(2011) / Oregon Portland zone (m)",9001,6318,6775,9801,1,0,4499,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,100000,9001,8807,50000,9001,,,,,,,,,,,,,
+6855,"NAD83(2011) / Oregon Portland zone (ft)",9002,6318,6776,9801,1,0,4495,8801,45.3,9110,8802,-122.45,9110,8805,1.000002,9201,8806,328083.9895,9002,8807,164041.9948,9002,,,,,,,,,,,,,
+6856,"NAD83(CORS96) / Oregon Salem zone (m)",9001,6783,6777,9807,1,0,4499,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,50000,9001,8807,0,9001,,,,,,,,,,,,,
+6857,"NAD83(CORS96) / Oregon Salem zone (ft)",9002,6783,6778,9807,1,0,4495,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,164041.9948,9002,8807,0,9002,,,,,,,,,,,,,
+6858,"NAD83(2011) / Oregon Salem zone (m)",9001,6318,6777,9807,1,0,4499,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,50000,9001,8807,0,9001,,,,,,,,,,,,,
+6859,"NAD83(2011) / Oregon Salem zone (ft)",9002,6318,6778,9807,1,0,4495,8801,44.2,9110,8802,-123.05,9110,8805,1.00001,9201,8806,164041.9948,9002,8807,0,9002,,,,,,,,,,,,,
+6860,"NAD83(CORS96) / Oregon Santiam Pass zone (m)",9001,6783,6779,9807,1,0,4499,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6861,"NAD83(CORS96) / Oregon Santiam Pass zone (ft)",9002,6783,6780,9807,1,0,4495,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9002,8807,0,9002,,,,,,,,,,,,,
+6862,"NAD83(2011) / Oregon Santiam Pass zone (m)",9001,6318,6779,9807,1,0,4499,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+6863,"NAD83(2011) / Oregon Santiam Pass (ft)",9002,6318,6780,9807,1,0,4495,8801,44.05,9110,8802,-122.3,9110,8805,1.000155,9201,8806,0,9002,8807,0,9002,,,,,,,,,,,,,
+6867,"NAD83(CORS96) / Oregon LCC (m)",9001,6783,13633,9802,1,0,4499,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+6868,"NAD83(CORS96) / Oregon GIC Lambert (ft)",9002,6783,15374,9802,1,0,4495,8821,41.45,9110,8822,-120.3,9110,8823,43,9110,8824,45.3,9110,8826,1312335.958,9002,8827,0,9002,,,,,,,,,,
+6870,"ETRS89 / Albania TM 2010",9001,4258,6869,9807,1,0,4530,8801,0,9102,8802,20,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6875,"RDN2008 / Italy zone (N-E)",9001,6706,6877,9807,1,0,4500,8801,0,9102,8802,12,9102,8805,0.9985,9201,8806,7000000,9001,8807,0,9001,,,,,,,,,,,,,
+6876,"RDN2008 / Zone 12 (N-E)",9001,6706,6878,9807,1,0,4500,8801,0,9102,8802,12,9102,8805,1,9201,8806,3000000,9001,8807,0,9001,,,,,,,,,,,,,
+6879,"NAD83(2011) / Wisconsin Central",9001,6318,14832,9802,1,0,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+6880,"NAD83(2011) / Nebraska (ftUS)",9003,6318,15396,9802,1,0,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+6884,"NAD83(CORS96) / Oregon North",9001,6783,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,,,,,,,,
+6885,"NAD83(CORS96) / Oregon North (ft)",9002,6783,15351,9802,1,0,4495,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,8202099.738,9002,8827,0,9002,,,,,,,,,,
+6886,"NAD83(CORS96) / Oregon South",9001,6783,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,,,,,,,,
+6887,"NAD83(CORS96) / Oregon South (ft)",9002,6783,15352,9802,1,0,4495,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,4921259.843,9002,8827,0,9002,,,,,,,,,,
+6915,"South East Island 1943 / UTM zone 40N",9001,6892,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+6922,"NAD83 / Kansas LCC",9001,4269,6920,9802,1,0,4499,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+6923,"NAD83 / Kansas LCC (ftUS)",9003,4269,6921,9802,1,0,4497,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+6924,"NAD83(2011) / Kansas LCC",9001,6318,6920,9802,1,0,4499,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+6925,"NAD83(2011) / Kansas LCC (ftUS)",9003,6318,6921,9802,1,0,4497,8821,36,9110,8822,-98.15,9110,8823,39.3,9110,8824,37.3,9110,8826,1312333.3333,9003,8827,0,9003,,,,,,,,,,
+6931,"WGS 84 / NSIDC EASE-Grid 2.0 North",9001,4326,6929,9820,1,0,4469,8801,90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+6932,"WGS 84 / NSIDC EASE-Grid 2.0 South",9001,4326,6930,9820,1,0,4470,8801,-90,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+6933,"WGS 84 / NSIDC EASE-Grid 2.0 Global",9001,4326,6928,9835,1,0,4499,8802,0,9102,8806,0,9001,8807,0,9001,8823,30,9102,,,,,,,,,,,,,,,,
+6956,"VN-2000 / TM-3 zone 481",9001,4756,6952,9807,1,0,4400,8801,0,9102,8802,102,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,,,,,,,,
+6957,"VN-2000 / TM-3 zone 482",9001,4756,6953,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,,,,,,,,
+6958,"VN-2000 / TM-3 zone 491",9001,4756,6954,9807,1,0,4400,8801,0,9102,8802,108,9102,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,,,,,,,,
+6959,"VN-2000 / TM-3 Da Nang zone",9001,4756,6955,9807,1,0,4400,8801,0,9110,8802,107.45,9110,8805,0.9999,9201,8806,0,9001,8807,500000,9001,,,,,,,,,,,,,
+6962,"ETRS89 / Albania LCC 2010",9001,4258,6961,9802,1,0,4530,8821,41,9102,8822,20,9102,8823,39,9102,8824,43,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+6966,"NAD27 / Michigan North",9003,4267,6965,1051,1,0,4497,1038,1.0000382,9201,8821,44.47,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003,,,,,,,
+6984,Israeli Grid 05,9001,6983,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,,,,,,,,
+6991,"Israeli Grid 05/12",9001,6990,18204,9807,1,0,4400,8801,31.4403817,9110,8802,35.1216261,9110,8805,1.0000067,9201,8806,219529.584,9001,8807,626907.39,9001,,,,,,,,,,,,,
+6996,"NAD83(2011) / San Francisco CS13",9001,6318,6994,9807,1,1,4499,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9202,8806,48000,9001,8807,24000,9001,,,,,,,,,,,,,
+6997,"NAD83(2011) / San Francisco CS13 (ftUS)",9003,6318,6995,9807,1,1,4497,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9202,8806,157480,9003,8807,78740,9003,,,,,,,,,,,,,
+7005,"Nahrwan 1934 / UTM zone 37N",9001,4744,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7006,"Nahrwan 1934 / UTM zone 38N",9001,4744,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7007,"Nahrwan 1934 / UTM zone 39N",9001,4744,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7057,"NAD83(2011) / IaRCS zone 1",9003,6318,7043,9801,1,0,4497,8801,43.12,9110,8802,-95.15,9110,8805,1.000052,9201,8806,11500000,9003,8807,9600000,9003,,,,,,,,,,,,,
+7058,"NAD83(2011) / IaRCS zone 2",9003,6318,7044,9801,1,0,4497,8801,43.1,9110,8802,-92.45,9110,8805,1.000043,9201,8806,12500000,9003,8807,9800000,9003,,,,,,,,,,,,,
+7059,"NAD83(2011) / IaRCS zone 3",9003,6318,7045,9807,1,0,4497,8801,40.15,9110,8802,-91.12,9110,8805,1.000035,9201,8806,13500000,9003,8807,8300000,9003,,,,,,,,,,,,,
+7060,"NAD83(2011) / IaRCS zone 4",9003,6318,7046,9801,1,0,4497,8801,42.32,9110,8802,-94.5,9110,8805,1.000045,9201,8806,14500000,9003,8807,8600000,9003,,,,,,,,,,,,,
+7061,"NAD83(2011) / IaRCS zone 5",9003,6318,7047,9801,1,0,4497,8801,42.39,9110,8802,-92.15,9110,8805,1.000032,9201,8806,15500000,9003,8807,8900000,9003,,,,,,,,,,,,,
+7062,"NAD83(2011) / IaRCS zone 6",9003,6318,7048,9807,1,0,4497,8801,40.15,9110,8802,-95.44,9110,8805,1.000039,9201,8806,16500000,9003,8807,6600000,9003,,,,,,,,,,,,,
+7063,"NAD83(2011) / IaRCS zone 7",9003,6318,7049,9807,1,0,4497,8801,40.15,9110,8802,-94.38,9110,8805,1.000045,9201,8806,17500000,9003,8807,6800000,9003,,,,,,,,,,,,,
+7064,"NAD83(2011) / IaRCS zone 8",9003,6318,7050,9807,1,0,4497,8801,40.15,9110,8802,-93.43,9110,8805,1.000033,9201,8806,18500000,9003,8807,7000000,9003,,,,,,,,,,,,,
+7065,"NAD83(2011) / IaRCS zone 9",9003,6318,7051,9807,1,0,4497,8801,40.15,9110,8802,-92.49,9110,8805,1.000027,9201,8806,19500000,9003,8807,7200000,9003,,,,,,,,,,,,,
+7066,"NAD83(2011) / IaRCS zone 10",9003,6318,7052,9801,1,0,4497,8801,41.5,9110,8802,-91.4,9110,8805,1.00002,9201,8806,20500000,9003,8807,8000000,9003,,,,,,,,,,,,,
+7067,"NAD83(2011) / IaRCS zone 11",9003,6318,7053,9807,1,0,4497,8801,40.15,9110,8802,-90.32,9110,8805,1.000027,9201,8806,21500000,9003,8807,7600000,9003,,,,,,,,,,,,,
+7068,"NAD83(2011) / IaRCS zone 12",9003,6318,7054,9801,1,0,4497,8801,40.55,9110,8802,-93.45,9110,8805,1.000037,9201,8806,22500000,9003,8807,6200000,9003,,,,,,,,,,,,,
+7069,"NAD83(2011) / IaRCS zone 13",9003,6318,7055,9807,1,0,4497,8801,40.15,9110,8802,-91.55,9110,8805,1.00002,9201,8806,23500000,9003,8807,6400000,9003,,,,,,,,,,,,,
+7070,"NAD83(2011) / IaRCS zone 14",9003,6318,7056,9807,1,0,4497,8801,40.15,9110,8802,-91.15,9110,8805,1.000018,9201,8806,24500000,9003,8807,6200000,9003,,,,,,,,,,,,,
+7074,"RGTAAF07 / UTM zone 37S",9001,7073,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7075,"RGTAAF07 / UTM zone 38S",9001,7073,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7076,"RGTAAF07 / UTM zone 39S",9001,7073,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7077,"RGTAAF07 / UTM zone 40S",9001,7073,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7078,"RGTAAF07 / UTM zone 41S",9001,7073,16141,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7079,"RGTAAF07 / UTM zone 42S",9001,7073,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7080,"RGTAAF07 / UTM zone 43S",9001,7073,16143,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7081,"RGTAAF07 / UTM zone 44S",9001,7073,16144,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7082,"RGTAAF07 / Terre Adelie Polar Stereographic",9001,7073,19983,9830,1,0,4400,8826,300000,9001,8827,200000,9001,8832,-67,9102,8833,140,9102,,,,,,,,,,,,,,,,
+7109,"NAD83(2011) / RMTCRS St Mary (m)",9001,6318,7089,9807,1,0,4499,8801,48.3,9110,8802,-112.3,9110,8805,1.00016,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+7110,"NAD83(2011) / RMTCRS Blackfeet (m)",9001,6318,7091,9807,1,0,4499,8801,48,9110,8802,-112.3,9110,8805,1.00019,9201,8806,100000,9001,8807,0,9001,,,,,,,,,,,,,
+7111,"NAD83(2011) / RMTCRS Milk River (m)",9001,6318,7093,9801,1,0,4499,8801,48.3,9110,8802,-111,9110,8805,1.000145,9201,8806,150000,9001,8807,200000,9001,,,,,,,,,,,,,
+7112,"NAD83(2011) / RMTCRS Fort Belknap (m)",9001,6318,7095,9801,1,0,4499,8801,48.3,9110,8802,-108.3,9110,8805,1.00012,9201,8806,200000,9001,8807,150000,9001,,,,,,,,,,,,,
+7113,"NAD83(2011) / RMTCRS Fort Peck Assiniboine (m)",9001,6318,7097,9801,1,0,4499,8801,48.2,9110,8802,-105.3,9110,8805,1.00012,9201,8806,200000,9001,8807,100000,9001,,,,,,,,,,,,,
+7114,"NAD83(2011) / RMTCRS Fort Peck Sioux (m)",9001,6318,7099,9801,1,0,4499,8801,48.2,9110,8802,-105.3,9110,8805,1.00009,9201,8806,100000,9001,8807,50000,9001,,,,,,,,,,,,,
+7115,"NAD83(2011) / RMTCRS Crow (m)",9001,6318,7101,9807,1,0,4499,8801,44.45,9110,8802,-107.45,9110,8805,1.000148,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+7116,"NAD83(2011) / RMTCRS Bobcat (m)",9001,6318,7103,9801,1,0,4499,8801,46.15,9110,8802,-111.15,9110,8805,1.000185,9201,8806,100000,9001,8807,100000,9001,,,,,,,,,,,,,
+7117,"NAD83(2011) / RMTCRS Billings (m)",9001,6318,7105,9801,1,0,4499,8801,45.47,9110,8802,-108.25,9110,8805,1.0001515,9201,8806,200000,9001,8807,50000,9001,,,,,,,,,,,,,
+7118,"NAD83(2011) / RMTCRS Wind River (m)",9001,6318,7107,9807,1,0,4499,8801,42.4,9110,8802,-108.2,9110,8805,1.00024,9201,8806,100000,9001,8807,0,9001,,,,,,,,,,,,,
+7119,"NAD83(2011) / RMTCRS St Mary (ft)",9002,6318,7090,9807,1,0,4495,8801,48.3,9110,8802,-112.3,9110,8805,1.00016,9201,8806,492125.9843,9002,8807,0,9002,,,,,,,,,,,,,
+7120,"NAD83(2011) / RMTCRS Blackfeet (ft)",9002,6318,7092,9807,1,0,4495,8801,48,9110,8802,-112.3,9110,8805,1.00019,9201,8806,328083.9895,9002,8807,0,9002,,,,,,,,,,,,,
+7121,"NAD83(2011) / RMTCRS Milk River (ft)",9002,6318,7094,9801,1,0,4495,8801,48.3,9110,8802,-111,9110,8805,1.000145,9201,8806,492125.9843,9002,8807,656167.979,9002,,,,,,,,,,,,,
+7122,"NAD83(2011) / RMTCRS Fort Belknap (ft)",9002,6318,7096,9801,1,0,4495,8801,48.3,9110,8802,-108.3,9110,8805,1.00012,9201,8806,656167.979,9002,8807,492125.9843,9002,,,,,,,,,,,,,
+7123,"NAD83(2011) / RMTCRS Fort Peck Assiniboine (ft)",9002,6318,7098,9801,1,0,4495,8801,48.2,9110,8802,-105.3,9110,8805,1.00012,9201,8806,656167.979,9002,8807,328083.9895,9002,,,,,,,,,,,,,
+7124,"NAD83(2011) / RMTCRS Fort Peck Sioux (ft)",9002,6318,7100,9801,1,0,4495,8801,48.2,9110,8802,-105.3,9110,8805,1.00009,9201,8806,328083.9895,9002,8807,164041.9938,9002,,,,,,,,,,,,,
+7125,"NAD83(2011) / RMTCRS Crow (ft)",9002,6318,7102,9807,1,0,4495,8801,44.45,9110,8802,-107.45,9110,8805,1.000148,9201,8806,656167.979,9002,8807,0,9002,,,,,,,,,,,,,
+7126,"NAD83(2011) / RMTCRS Bobcat (ft)",9002,6318,7104,9801,1,0,4495,8801,46.15,9110,8802,-111.15,9110,8805,1.000185,9201,8806,328083.9895,9002,8807,328083.9895,9002,,,,,,,,,,,,,
+7127,"NAD83(2011) / RMTCRS Billings (ft)",9002,6318,7106,9801,1,0,4495,8801,45.47,9110,8802,-108.25,9110,8805,1.0001515,9201,8806,656167.979,9002,8807,164041.9948,9002,,,,,,,,,,,,,
+7128,"NAD83(2011) / RMTCRS Wind River (ftUS)",9003,6318,7108,9807,1,0,4497,8801,42.4,9110,8802,-108.2,9110,8805,1.00024,9201,8806,328083.3333,9003,8807,0,9003,,,,,,,,,,,,,
+7131,"NAD83(2011) / San Francisco CS13",9001,6318,7129,9807,1,0,4499,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9201,8806,48000,9001,8807,24000,9001,,,,,,,,,,,,,
+7132,"NAD83(2011) / San Francisco CS13 (ftUS)",9003,6318,7130,9807,1,0,4497,8801,37.75,9102,8802,-122.45,9102,8805,1.000007,9201,8806,157480,9003,8807,78740,9003,,,,,,,,,,,,,
+7142,"Palestine 1923 / Palestine Grid modified",9001,4281,7141,9807,1,0,4400,8801,31.4402749,9110,8802,35.124349,9110,8805,1,9201,8806,170251.555,9001,8807,126867.909,9001,,,,,,,,,,,,,
+7257,"NAD83(2011) / InGCS Adams (m)",9001,6318,7143,9807,1,0,4499,8801,40.33,9110,8802,-84.57,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7258,"NAD83(2011) / InGCS Adams (ftUS)",9003,6318,7144,9807,1,0,4497,8801,40.33,9110,8802,-84.57,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7259,"NAD83(2011) / InGCS Allen (m)",9001,6318,7145,9807,1,0,4499,8801,40.54,9110,8802,-85.03,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7260,"NAD83(2011) / InGCS Allen (ftUS)",9003,6318,7146,9807,1,0,4497,8801,40.54,9110,8802,-85.03,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7261,"NAD83(2011) / InGCS Bartholomew (m)",9001,6318,7147,9807,1,0,4499,8801,39,9110,8802,-85.51,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7262,"NAD83(2011) / InGCS Bartholomew (ftUS)",9003,6318,7148,9807,1,0,4497,8801,39,9110,8802,-85.51,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7263,"NAD83(2011) / InGCS Benton (m)",9001,6318,7149,9807,1,0,4499,8801,40.27,9110,8802,-87.18,9110,8805,1.000029,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7264,"NAD83(2011) / InGCS Benton (ftUS)",9003,6318,7150,9807,1,0,4497,8801,40.27,9110,8802,-87.18,9110,8805,1.000029,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7265,"NAD83(2011) / InGCS Blackford-Delaware (m)",9001,6318,7151,9807,1,0,4499,8801,40.03,9110,8802,-85.24,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7266,"NAD83(2011) / InGCS Blackford-Delaware (ftUS)",9003,6318,7152,9807,1,0,4497,8801,40.03,9110,8802,-85.24,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7267,"NAD83(2011) / InGCS Boone-Hendricks (m)",9001,6318,7153,9807,1,0,4499,8801,39.36,9110,8802,-86.3,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7268,"NAD83(2011) / InGCS Boone-Hendricks (ftUS)",9003,6318,7154,9807,1,0,4497,8801,39.36,9110,8802,-86.3,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7269,"NAD83(2011) / InGCS Brown (m)",9001,6318,7155,9807,1,0,4499,8801,39,9110,8802,-86.18,9110,8805,1.00003,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7270,"NAD83(2011) / InGCS Brown (ftUS)",9003,6318,7156,9807,1,0,4497,8801,39,9110,8802,-86.18,9110,8805,1.00003,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7271,"NAD83(2011) / InGCS Carroll (m)",9001,6318,7157,9807,1,0,4499,8801,40.24,9110,8802,-86.39,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7272,"NAD83(2011) / InGCS Carroll (ftUS)",9003,6318,7158,9807,1,0,4497,8801,40.24,9110,8802,-86.39,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7273,"NAD83(2011) / InGCS Cass (m)",9001,6318,7159,9807,1,0,4499,8801,40.33,9110,8802,-86.24,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7274,"NAD83(2011) / InGCS Cass (ftUS)",9003,6318,7160,9807,1,0,4497,8801,40.33,9110,8802,-86.24,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7275,"NAD83(2011) / InGCS Clark-Floyd-Scott (m)",9001,6318,7161,9807,1,0,4499,8801,38.09,9110,8802,-85.36,9110,8805,1.000021,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7276,"NAD83(2011) / InGCS Clark-Floyd-Scott (ftUS)",9003,6318,7162,9807,1,0,4497,8801,38.09,9110,8802,-85.36,9110,8805,1.000021,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7277,"NAD83(2011) / InGCS Clay (m)",9001,6318,7163,9807,1,0,4499,8801,39.09,9110,8802,-87.09,9110,8805,1.000024,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7278,"NAD83(2011) / InGCS Clay (ftUS)",9003,6318,7164,9807,1,0,4497,8801,39.09,9110,8802,-87.09,9110,8805,1.000024,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7279,"NAD83(2011) / InGCS Clinton (m)",9001,6318,7165,9807,1,0,4499,8801,40.09,9110,8802,-86.36,9110,8805,1.000032,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7280,"NAD83(2011) / InGCS Clinton (ftUS)",9003,6318,7166,9807,1,0,4497,8801,40.09,9110,8802,-86.36,9110,8805,1.000032,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7281,"NAD83(2011) / InGCS Crawford-Lawrence-Orange (m)",9001,6318,7167,9807,1,0,4499,8801,38.06,9110,8802,-86.3,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7282,"NAD83(2011) / InGCS Crawford-Lawrence-Orange (ftUS)",9003,6318,7168,9807,1,0,4497,8801,38.06,9110,8802,-86.3,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7283,"NAD83(2011) / InGCS Daviess-Greene (m)",9001,6318,7169,9807,1,0,4499,8801,38.27,9110,8802,-87.06,9110,8805,1.000018,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7284,"NAD83(2011) / InGCS Daviess-Greene (ftUS)",9003,6318,7170,9807,1,0,4497,8801,38.27,9110,8802,-87.06,9110,8805,1.000018,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7285,"NAD83(2011) / InGCS Dearborn-Ohio-Switzerland (m)",9001,6318,7171,9807,1,0,4499,8801,38.39,9110,8802,-84.54,9110,8805,1.000029,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7286,"NAD83(2011) / InGCS Dearborn-Ohio-Switzerland (ftUS)",9003,6318,7172,9807,1,0,4497,8801,38.39,9110,8802,-84.54,9110,8805,1.000029,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7287,"NAD83(2011) / InGCS Decatur-Rush (m)",9001,6318,7173,9807,1,0,4499,8801,39.06,9110,8802,-85.39,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7288,"NAD83(2011) / InGCS Decatur-Rush (ftUS)",9003,6318,7174,9807,1,0,4497,8801,39.06,9110,8802,-85.39,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7289,"NAD83(2011) / InGCS DeKalb (m)",9001,6318,7175,9807,1,0,4499,8801,41.15,9110,8802,-84.57,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7290,"NAD83(2011) / InGCS DeKalb (ftUS)",9003,6318,7176,9807,1,0,4497,8801,41.15,9110,8802,-84.57,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7291,"NAD83(2011) / InGCS Dubois-Martin (m)",9001,6318,7177,9807,1,0,4499,8801,38.12,9110,8802,-86.57,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7292,"NAD83(2011) / InGCS Dubois-Martin (ftUS)",9003,6318,7178,9807,1,0,4497,8801,38.12,9110,8802,-86.57,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7293,"NAD83(2011) / InGCS Elkhart-Kosciusko-Wabash (m)",9001,6318,7179,9807,1,0,4499,8801,40.39,9110,8802,-85.51,9110,8805,1.000033,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7294,"NAD83(2011) / InGCS Elkhart-Kosciusko-Wabash (ftUS)",9003,6318,7180,9807,1,0,4497,8801,40.39,9110,8802,-85.51,9110,8805,1.000033,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7295,"NAD83(2011) / InGCS Fayette-Franklin-Union (m)",9001,6318,7181,9807,1,0,4499,8801,39.15,9110,8802,-85.03,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7296,"NAD83(2011) / InGCS Fayette-Franklin-Union (ftUS)",9003,6318,7182,9807,1,0,4497,8801,39.15,9110,8802,-85.03,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7297,"NAD83(2011) / InGCS Fountain-Warren (m)",9001,6318,7183,9807,1,0,4499,8801,39.57,9110,8802,-87.18,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7298,"NAD83(2011) / InGCS Fountain-Warren (ftUS)",9003,6318,7184,9807,1,0,4497,8801,39.57,9110,8802,-87.18,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7299,"NAD83(2011) / InGCS Fulton-Marshall-St. Joseph (m)",9001,6318,7185,9807,1,0,4499,8801,40.54,9110,8802,-86.18,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7300,"NAD83(2011) / InGCS Fulton-Marshall-St. Joseph (ftUS)",9003,6318,7186,9807,1,0,4497,8801,40.54,9110,8802,-86.18,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7301,"NAD83(2011) / InGCS Gibson (m)",9001,6318,7187,9807,1,0,4499,8801,38.09,9110,8802,-87.39,9110,8805,1.000013,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7302,"NAD83(2011) / InGCS Gibson (ftUS)",9003,6318,7188,9807,1,0,4497,8801,38.09,9110,8802,-87.39,9110,8805,1.000013,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7303,"NAD83(2011) / InGCS Grant (m)",9001,6318,7189,9807,1,0,4499,8801,40.21,9110,8802,-85.42,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7304,"NAD83(2011) / InGCS Grant (ftUS)",9003,6318,7190,9807,1,0,4497,8801,40.21,9110,8802,-85.42,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7305,"NAD83(2011) / InGCS Hamilton-Tipton (m)",9001,6318,7191,9807,1,0,4499,8801,39.54,9110,8802,-86,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7306,"NAD83(2011) / InGCS Hamilton-Tipton (ftUS)",9003,6318,7192,9807,1,0,4497,8801,39.54,9110,8802,-86,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7307,"NAD83(2011) / InGCS Hancock-Madison (m)",9001,6318,7193,9807,1,0,4499,8801,39.39,9110,8802,-85.48,9110,8805,1.000036,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7308,"NAD83(2011) / InGCS Hancock-Madison (ftUS)",9003,6318,7194,9807,1,0,4497,8801,39.39,9110,8802,-85.48,9110,8805,1.000036,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7309,"NAD83(2011) / InGCS Harrison-Washington (m)",9001,6318,7195,9807,1,0,4499,8801,37.57,9110,8802,-86.09,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7310,"NAD83(2011) / InGCS Harrison-Washington (ftUS)",9003,6318,7196,9807,1,0,4497,8801,37.57,9110,8802,-86.09,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7311,"NAD83(2011) / InGCS Henry (m)",9001,6318,7197,9807,1,0,4499,8801,39.45,9110,8802,-85.27,9110,8805,1.000043,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7312,"NAD83(2011) / InGCS Henry (ftUS)",9003,6318,7198,9807,1,0,4497,8801,39.45,9110,8802,-85.27,9110,8805,1.000043,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7313,"NAD83(2011) / InGCS Howard-Miami (m)",9001,6318,7199,9807,1,0,4499,8801,40.21,9110,8802,-86.09,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7314,"NAD83(2011) / InGCS Howard-Miami (ftUS)",9003,6318,7200,9807,1,0,4497,8801,40.21,9110,8802,-86.09,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7315,"NAD83(2011) / InGCS Huntington-Whitley (m)",9001,6318,7201,9807,1,0,4499,8801,40.39,9110,8802,-85.3,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7316,"NAD83(2011) / InGCS Huntington-Whitley (ftUS)",9003,6318,7202,9807,1,0,4497,8801,40.39,9110,8802,-85.3,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7317,"NAD83(2011) / InGCS Jackson (m)",9001,6318,7203,9807,1,0,4499,8801,38.42,9110,8802,-85.57,9110,8805,1.000022,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7318,"NAD83(2011) / InGCS Jackson (ftUS)",9003,6318,7204,9807,1,0,4497,8801,38.42,9110,8802,-85.57,9110,8805,1.000022,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7319,"NAD83(2011) / InGCS Jasper-Porter (m)",9001,6318,7205,9807,1,0,4499,8801,40.42,9110,8802,-87.06,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7320,"NAD83(2011) / InGCS Jasper-Porter (ftUS)",9003,6318,7206,9807,1,0,4497,8801,40.42,9110,8802,-87.06,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7321,"NAD83(2011) / InGCS Jay (m)",9001,6318,7207,9807,1,0,4499,8801,40.18,9110,8802,-85,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7322,"NAD83(2011) / InGCS Jay (ftUS)",9003,6318,7208,9807,1,0,4497,8801,40.18,9110,8802,-85,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7323,"NAD83(2011) / InGCS Jefferson (m)",9001,6318,7209,9807,1,0,4499,8801,38.33,9110,8802,-85.21,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7324,"NAD83(2011) / InGCS Jefferson (ftUS)",9003,6318,7210,9807,1,0,4497,8801,38.33,9110,8802,-85.21,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7325,"NAD83(2011) / InGCS Jennings (m)",9001,6318,7211,9807,1,0,4499,8801,38.48,9110,8802,-85.48,9110,8805,1.000025,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7326,"NAD83(2011) / InGCS Jennings (ftUS)",9003,6318,7212,9807,1,0,4497,8801,38.48,9110,8802,-85.48,9110,8805,1.000025,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7327,"NAD83(2011) / InGCS Johnson-Marion (m)",9001,6318,7213,9807,1,0,4499,8801,39.18,9110,8802,-86.09,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7328,"NAD83(2011) / InGCS Johnson-Marion (ftUS)",9003,6318,7214,9807,1,0,4497,8801,39.18,9110,8802,-86.09,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7329,"NAD83(2011) / InGCS Knox (m)",9001,6318,7215,9807,1,0,4499,8801,38.24,9110,8802,-87.27,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7330,"NAD83(2011) / InGCS Knox (ftUS)",9003,6318,7216,9807,1,0,4497,8801,38.24,9110,8802,-87.27,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7331,"NAD83(2011) / InGCS LaGrange-Noble (m)",9001,6318,7217,9807,1,0,4499,8801,41.15,9110,8802,-85.27,9110,8805,1.000037,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7332,"NAD83(2011) / InGCS LaGrange-Noble (ftUS)",9003,6318,7218,9807,1,0,4497,8801,41.15,9110,8802,-85.27,9110,8805,1.000037,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7333,"NAD83(2011) / InGCS Lake-Newton (m)",9001,6318,7219,9807,1,0,4499,8801,40.42,9110,8802,-87.24,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7334,"NAD83(2011) / InGCS Lake-Newton (ftUS)",9003,6318,7220,9807,1,0,4497,8801,40.42,9110,8802,-87.24,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7335,"NAD83(2011) / InGCS LaPorte-Pulaski-Starke (m)",9001,6318,7221,9807,1,0,4499,8801,40.54,9110,8802,-86.45,9110,8805,1.000027,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7336,"NAD83(2011) / InGCS LaPorte-Pulaski-Starke (ftUS)",9003,6318,7222,9807,1,0,4497,8801,40.54,9110,8802,-86.45,9110,8805,1.000027,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7337,"NAD83(2011) / InGCS Monroe-Morgan (m)",9001,6318,7223,9807,1,0,4499,8801,38.57,9110,8802,-86.3,9110,8805,1.000028,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7338,"NAD83(2011) / InGCS Monroe-Morgan (ftUS)",9003,6318,7224,9807,1,0,4497,8801,38.57,9110,8802,-86.3,9110,8805,1.000028,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7339,"NAD83(2011) / InGCS Montgomery-Putnam (m)",9001,6318,7225,9807,1,0,4499,8801,39.27,9110,8802,-86.57,9110,8805,1.000031,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7340,"NAD83(2011) / InGCS Montgomery-Putnam (ftUS)",9003,6318,7226,9807,1,0,4497,8801,39.27,9110,8802,-86.57,9110,8805,1.000031,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7341,"NAD83(2011) / InGCS Owen (m)",9001,6318,7227,9807,1,0,4499,8801,39.09,9110,8802,-86.54,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7342,"NAD83(2011) / InGCS Owen (ftUS)",9003,6318,7228,9807,1,0,4497,8801,39.09,9110,8802,-86.54,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7343,"NAD83(2011) / InGCS Parke-Vermillion (m)",9001,6318,7229,9807,1,0,4499,8801,39.36,9110,8802,-87.21,9110,8805,1.000022,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7344,"NAD83(2011) / InGCS Parke-Vermillion (ftUS)",9003,6318,7230,9807,1,0,4497,8801,39.36,9110,8802,-87.21,9110,8805,1.000022,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7345,"NAD83(2011) / InGCS Perry (m)",9001,6318,7231,9807,1,0,4499,8801,37.48,9110,8802,-86.42,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7346,"NAD83(2011) / InGCS Perry (ftUS)",9003,6318,7232,9807,1,0,4497,8801,37.48,9110,8802,-86.42,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7347,"NAD83(2011) / InGCS Pike-Warrick (m)",9001,6318,7233,9807,1,0,4499,8801,37.51,9110,8802,-87.18,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7348,"NAD83(2011) / InGCS Pike-Warrick (ftUS)",9003,6318,7234,9807,1,0,4497,8801,37.51,9110,8802,-87.18,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7349,"NAD83(2011) / InGCS Posey (m)",9001,6318,7235,9807,1,0,4499,8801,37.45,9110,8802,-87.57,9110,8805,1.000013,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7350,"NAD83(2011) / InGCS Posey (ftUS)",9003,6318,7236,9807,1,0,4497,8801,37.45,9110,8802,-87.57,9110,8805,1.000013,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7351,"NAD83(2011) / InGCS Randolph-Wayne (m)",9001,6318,7237,9807,1,0,4499,8801,39.42,9110,8802,-85.03,9110,8805,1.000044,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7352,"NAD83(2011) / InGCS Randolph-Wayne (ftUS)",9003,6318,7238,9807,1,0,4497,8801,39.42,9110,8802,-85.03,9110,8805,1.000044,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7353,"NAD83(2011) / InGCS Ripley (m)",9001,6318,7239,9807,1,0,4499,8801,38.54,9110,8802,-85.18,9110,8805,1.000038,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7354,"NAD83(2011) / InGCS Ripley (ftUS)",9003,6318,7240,9807,1,0,4497,8801,38.54,9110,8802,-85.18,9110,8805,1.000038,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7355,"NAD83(2011) / InGCS Shelby (m)",9001,6318,7241,9807,1,0,4499,8801,39.18,9110,8802,-85.54,9110,8805,1.00003,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7356,"NAD83(2011) / InGCS Shelby (ftUS)",9003,6318,7242,9807,1,0,4497,8801,39.18,9110,8802,-85.54,9110,8805,1.00003,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7357,"NAD83(2011) / InGCS Spencer (m)",9001,6318,7243,9807,1,0,4499,8801,37.45,9110,8802,-87.03,9110,8805,1.000014,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7358,"NAD83(2011) / InGCS Spencer (ftUS)",9003,6318,7244,9807,1,0,4497,8801,37.45,9110,8802,-87.03,9110,8805,1.000014,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7359,"NAD83(2011) / InGCS Steuben (m)",9001,6318,7245,9807,1,0,4499,8801,41.3,9110,8802,-85,9110,8805,1.000041,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7360,"NAD83(2011) / InGCS Steuben (ftUS)",9003,6318,7246,9807,1,0,4497,8801,41.3,9110,8802,-85,9110,8805,1.000041,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7361,"NAD83(2011) / InGCS Sullivan (m)",9001,6318,7247,9807,1,0,4499,8801,38.54,9110,8802,-87.3,9110,8805,1.000017,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7362,"NAD83(2011) / InGCS Sullivan (ftUS)",9003,6318,7248,9807,1,0,4497,8801,38.54,9110,8802,-87.3,9110,8805,1.000017,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7363,"NAD83(2011) / InGCS Tippecanoe-White (m)",9001,6318,7249,9807,1,0,4499,8801,40.12,9110,8802,-86.54,9110,8805,1.000026,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7364,"NAD83(2011) / InGCS Tippecanoe-White (ftUS)",9003,6318,7250,9807,1,0,4497,8801,40.12,9110,8802,-86.54,9110,8805,1.000026,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7365,"NAD83(2011) / InGCS Vanderburgh (m)",9001,6318,7251,9807,1,0,4499,8801,37.48,9110,8802,-87.33,9110,8805,1.000015,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7366,"NAD83(2011) / InGCS Vanderburgh (ftUS)",9003,6318,7252,9807,1,0,4497,8801,37.48,9110,8802,-87.33,9110,8805,1.000015,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7367,"NAD83(2011) / InGCS Vigo (m)",9001,6318,7253,9807,1,0,4499,8801,39.15,9110,8802,-87.27,9110,8805,1.00002,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7368,"NAD83(2011) / InGCS Vigo (ftUS)",9003,6318,7254,9807,1,0,4497,8801,39.15,9110,8802,-87.27,9110,8805,1.00002,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7369,"NAD83(2011) / InGCS Wells (m)",9001,6318,7255,9807,1,0,4499,8801,40.33,9110,8802,-85.15,9110,8805,1.000034,9201,8806,240000,9001,8807,36000,9001,,,,,,,,,,,,,
+7370,"NAD83(2011) / InGCS Wells (ftUS)",9003,6318,7256,9807,1,0,4497,8801,40.33,9110,8802,-85.15,9110,8805,1.000034,9201,8806,787400,9003,8807,118110,9003,,,,,,,,,,,,,
+7374,"ONGD14 / UTM zone 39N",9001,7373,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7375,"ONGD14 / UTM zone 40N",9001,7373,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7376,"ONGD14 / UTM zone 41N",9001,7373,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7528,"NAD83(2011) / WISCRS Adams and Juneau (m)",9001,6318,7484,9807,1,0,4499,8801,43.22,9110,8802,-90,9110,8805,1.0000365285,9201,8806,147218.6942,9001,8807,0.0037,9001,,,,,,,,,,,,,
+7529,"NAD83(2011) / WISCRS Ashland (m)",9001,6318,7378,9807,1,0,4499,8801,45.4222,9110,8802,-90.372,9110,8805,1.0000495683,9201,8806,172821.9461,9001,8807,0.0017,9001,,,,,,,,,,,,,
+7530,"NAD83(2011) / WISCRS Barron (m)",9001,6318,7426,9807,1,0,4499,8801,45.08,9110,8802,-91.51,9110,8805,1.0000486665,9201,8806,93150,9001,8807,0.0029,9001,,,,,,,,,,,,,
+7531,"NAD83(2011) / WISCRS Bayfield (m)",9001,6318,7380,9801,1,0,4499,8801,46.4010734158,9110,8802,-91.091,9110,8805,1.0000331195,9201,8806,228600.4575,9001,8807,148551.4837,9001,,,,,,,,,,,,,
+7532,"NAD83(2011) / WISCRS Brown (m)",9001,6318,7428,9807,1,0,4499,8801,43,9102,8802,-88,9102,8805,1.00002,9201,8806,31600,9001,8807,4600,9001,,,,,,,,,,,,,
+7533,"NAD83(2011) / WISCRS Buffalo (m)",9001,6318,7430,9807,1,0,4499,8801,43.2853,9110,8802,-91.475,9110,8805,1.0000382778,9201,8806,175260.3502,9001,8807,0.0048,9001,,,,,,,,,,,,,
+7534,"NAD83(2011) / WISCRS Burnett (m)",9001,6318,7382,9801,1,0,4499,8801,45.5355373517,9110,8802,-92.2728,9110,8805,1.0000383841,9201,8806,64008.1276,9001,8807,59445.9043,9001,,,,,,,,,,,,,
+7535,"NAD83(2011) / WISCRS Calumet, Fond du Lac, Outagamie and Winnebago (m)",9001,6318,7486,9807,1,0,4499,8801,42.431,9110,8802,-88.3,9110,8805,1.0000286569,9201,8806,244754.8893,9001,8807,0.0049,9001,,,,,,,,,,,,,
+7536,"NAD83(2011) / WISCRS Chippewa (m)",9001,6318,7432,9801,1,0,4499,8801,44.5840284835,9110,8802,-91.174,9110,8805,1.0000391127,9201,8806,60045.72,9001,8807,44091.4346,9001,,,,,,,,,,,,,
+7537,"NAD83(2011) / WISCRS Clark (m)",9001,6318,7434,9807,1,0,4499,8801,43.36,9110,8802,-90.423,9110,8805,1.0000463003,9201,8806,199949.1989,9001,8807,0.0086,9001,,,,,,,,,,,,,
+7538,"NAD83(2011) / WISCRS Columbia (m)",9001,6318,7488,9801,1,0,4499,8801,43.2745167925,9110,8802,-89.234,9110,8805,1.00003498,9201,8806,169164.3381,9001,8807,111569.6134,9001,,,,,,,,,,,,,
+7539,"NAD83(2011) / WISCRS Crawford (m)",9001,6318,7490,9801,1,0,4499,8801,43.1200200178,9110,8802,-90.562,9110,8805,1.0000349151,9201,8806,113690.6274,9001,8807,53703.1201,9001,,,,,,,,,,,,,
+7540,"NAD83(2011) / WISCRS Dane (m)",9001,6318,7492,9801,1,0,4499,8801,43.0410257735,9110,8802,-89.252,9110,8805,1.0000384786,9201,8806,247193.2944,9001,8807,146591.9896,9001,,,,,,,,,,,,,
+7541,"NAD83(2011) / WISCRS Dodge and Jefferson (m)",9001,6318,7494,9807,1,0,4499,8801,41.282,9110,8802,-88.463,9110,8805,1.0000346418,9201,8806,263347.7263,9001,8807,0.0076,9001,,,,,,,,,,,,,
+7542,"NAD83(2011) / WISCRS Door (m)",9001,6318,7436,9807,1,0,4499,8801,44.24,9110,8802,-87.162,9110,8805,1.0000187521,9201,8806,158801.1176,9001,8807,0.0023,9001,,,,,,,,,,,,,
+7543,"NAD83(2011) / WISCRS Douglas (m)",9001,6318,7384,9807,1,0,4499,8801,45.53,9110,8802,-91.55,9110,8805,1.0000385418,9201,8806,59131.3183,9001,8807,0.0041,9001,,,,,,,,,,,,,
+7544,"NAD83(2011) / WISCRS Dunn (m)",9001,6318,7438,9807,1,0,4499,8801,44.243,9110,8802,-91.534,9110,8805,1.0000410324,9201,8806,51816.104,9001,8807,0.003,9001,,,,,,,,,,,,,
+7545,"NAD83(2011) / WISCRS Eau Claire (m)",9001,6318,7440,9801,1,0,4499,8801,44.5220212055,9110,8802,-91.172,9110,8805,1.000035079,9201,8806,120091.4402,9001,8807,91687.9239,9001,,,,,,,,,,,,,
+7546,"NAD83(2011) / WISCRS Florence (m)",9001,6318,7386,9807,1,0,4499,8801,45.262,9110,8802,-88.083,9110,8805,1.0000552095,9201,8806,133502.6683,9001,8807,0.0063,9001,,,,,,,,,,,,,
+7547,"NAD83(2011) / WISCRS Forest (m)",9001,6318,7388,9807,1,0,4499,8801,44.002,9110,8802,-88.38,9110,8805,1.0000673004,9201,8806,275844.5533,9001,8807,0.0157,9001,,,,,,,,,,,,,
+7548,"NAD83(2011) / WISCRS Grant (m)",9001,6318,7496,9807,1,0,4499,8801,41.244,9110,8802,-90.48,9110,8805,1.0000349452,9201,8806,242316.4841,9001,8807,0.01,9001,,,,,,,,,,,,,
+7549,"NAD83(2011) / WISCRS Green and Lafayette (m)",9001,6318,7498,9801,1,0,4499,8801,42.3815224197,9110,8802,-89.502,9110,8805,1.0000390487,9201,8806,170078.7403,9001,8807,45830.2947,9001,,,,,,,,,,,,,
+7550,"NAD83(2011) / WISCRS Green Lake and Marquette (m)",9001,6318,7500,9801,1,0,4499,8801,43.4825200424,9110,8802,-89.143,9110,8805,1.0000344057,9201,8806,150876.3018,9001,8807,79170.7795,9001,,,,,,,,,,,,,
+7551,"NAD83(2011) / WISCRS Iowa (m)",9001,6318,7502,9807,1,0,4499,8801,42.322,9110,8802,-90.094,9110,8805,1.0000394961,9201,8806,113081.0261,9001,8807,0.0045,9001,,,,,,,,,,,,,
+7552,"NAD83(2011) / WISCRS Iron (m)",9001,6318,7390,9807,1,0,4499,8801,45.26,9110,8802,-90.152,9110,8805,1.0000677153,9201,8806,220980.4419,9001,8807,0.0085,9001,,,,,,,,,,,,,
+7553,"NAD83(2011) / WISCRS Jackson (m)",9001,6318,7450,9807,1,0,4499,8801,44.151200646,9110,8802,-90.503946747,9110,8805,1.0000353,9201,8806,27000,9001,8807,25000,9001,,,,,,,,,,,,,
+7554,"NAD83(2011) / WISCRS Kenosha, Milwaukee, Ozaukee and Racine (m)",9001,6318,7504,9807,1,0,4499,8801,42.13,9110,8802,-87.534,9110,8805,1.0000260649,9201,8806,185928.3728,9001,8807,0.0009,9001,,,,,,,,,,,,,
+7555,"NAD83(2011) / WISCRS Kewaunee, Manitowoc and Sheboygan (m)",9001,6318,7506,9807,1,0,4499,8801,43.16,9110,8802,-87.33,9110,8805,1.0000233704,9201,8806,79857.7614,9001,8807,0.0012,9001,,,,,,,,,,,,,
+7556,"NAD83(2011) / WISCRS La Crosse (m)",9001,6318,7508,9807,1,0,4499,8801,43.2704,9110,8802,-91.19,9110,8805,1.0000319985,9201,8806,130454.6598,9001,8807,0.0033,9001,,,,,,,,,,,,,
+7557,"NAD83(2011) / WISCRS Langlade (m)",9001,6318,7452,9801,1,0,4499,8801,45.0915253579,9110,8802,-89.02,9110,8805,1.0000627024,9201,8806,198425.197,9001,8807,105279.7829,9001,,,,,,,,,,,,,
+7558,"NAD83(2011) / WISCRS Lincoln (m)",9001,6318,7454,9807,1,0,4499,8801,44.504,9110,8802,-89.44,9110,8805,1.0000599003,9201,8806,116129.0323,9001,8807,0.0058,9001,,,,,,,,,,,,,
+7559,"NAD83(2011) / WISCRS Marathon (m)",9001,6318,7456,9801,1,0,4499,8801,44.5403255925,9110,8802,-89.4612,9110,8805,1.000053289,9201,8806,74676.1493,9001,8807,55049.2669,9001,,,,,,,,,,,,,
+7560,"NAD83(2011) / WISCRS Marinette (m)",9001,6318,7458,9807,1,0,4499,8801,44.413,9110,8802,-87.424,9110,8805,1.0000234982,9201,8806,238658.8794,9001,8807,0.0032,9001,,,,,,,,,,,,,
+7561,"NAD83(2011) / WISCRS Menominee (m)",9001,6318,7460,9807,1,0,4499,8801,44.43,9110,8802,-88.25,9110,8805,1.0000362499,9201,8806,105461.0121,9001,8807,0.0029,9001,,,,,,,,,,,,,
+7562,"NAD83(2011) / WISCRS Monroe (m)",9001,6318,7510,9801,1,0,4499,8801,44.0000266143,9110,8802,-90.383,9110,8805,1.0000434122,9201,8806,204521.209,9001,8807,121923.9861,9001,,,,,,,,,,,,,
+7563,"NAD83(2011) / WISCRS Oconto (m)",9001,6318,7462,9807,1,0,4499,8801,44.235,9110,8802,-87.543,9110,8805,1.0000236869,9201,8806,182880.3676,9001,8807,0.0033,9001,,,,,,,,,,,,,
+7564,"NAD83(2011) / WISCRS Oneida (m)",9001,6318,7392,9801,1,0,4499,8801,45.4215205573,9110,8802,-89.324,9110,8805,1.0000686968,9201,8806,70104.1401,9001,8807,57588.0346,9001,,,,,,,,,,,,,
+7565,"NAD83(2011) / WISCRS Pepin and Pierce (m)",9001,6318,7464,9801,1,0,4499,8801,44.3810135939,9110,8802,-92.134,9110,8805,1.0000362977,9201,8806,167640.3354,9001,8807,86033.0876,9001,,,,,,,,,,,,,
+7566,"NAD83(2011) / WISCRS Polk (m)",9001,6318,7466,9807,1,0,4499,8801,44.394,9110,8802,-92.38,9110,8805,1.0000433849,9201,8806,141732.2823,9001,8807,0.0059,9001,,,,,,,,,,,,,
+7567,"NAD83(2011) / WISCRS Portage (m)",9001,6318,7468,9801,1,0,4499,8801,44.2500566311,9110,8802,-89.3,9110,8805,1.000039936,9201,8806,56388.1128,9001,8807,50022.1874,9001,,,,,,,,,,,,,
+7568,"NAD83(2011) / WISCRS Price (m)",9001,6318,7394,9807,1,0,4499,8801,44.332,9110,8802,-90.292,9110,8805,1.0000649554,9201,8806,227990.8546,9001,8807,0.0109,9001,,,,,,,,,,,,,
+7569,"NAD83(2011) / WISCRS Richland (m)",9001,6318,7512,9801,1,0,4499,8801,43.1920326539,9110,8802,-90.255,9110,8805,1.0000375653,9201,8806,202387.6048,9001,8807,134255.4253,9001,,,,,,,,,,,,,
+7570,"NAD83(2011) / WISCRS Rock (m)",9001,6318,7514,9807,1,0,4499,8801,41.564,9110,8802,-89.042,9110,8805,1.0000337311,9201,8806,146304.2926,9001,8807,0.0068,9001,,,,,,,,,,,,,
+7571,"NAD83(2011) / WISCRS Rusk (m)",9001,6318,7470,9807,1,0,4499,8801,43.551,9110,8802,-91.04,9110,8805,1.0000495976,9201,8806,250546.1013,9001,8807,0.0234,9001,,,,,,,,,,,,,
+7572,"NAD83(2011) / WISCRS Sauk (m)",9001,6318,7516,9807,1,0,4499,8801,42.491,9110,8802,-89.54,9110,8805,1.0000373868,9201,8806,185623.5716,9001,8807,0.0051,9001,,,,,,,,,,,,,
+7573,"NAD83(2011) / WISCRS Sawyer (m)",9001,6318,7396,9801,1,0,4499,8801,45.5400356873,9110,8802,-91.07,9110,8805,1.0000573461,9201,8806,216713.2336,9001,8807,120734.1631,9001,,,,,,,,,,,,,
+7574,"NAD83(2011) / WISCRS Shawano (m)",9001,6318,7472,9807,1,0,4499,8801,44.021,9110,8802,-88.362,9110,8805,1.000032144,9201,8806,262433.3253,9001,8807,0.0096,9001,,,,,,,,,,,,,
+7575,"NAD83(2011) / WISCRS St. Croix (m)",9001,6318,7474,9807,1,0,4499,8801,44.021,9110,8802,-92.38,9110,8805,1.0000381803,9201,8806,165506.7302,9001,8807,0.0103,9001,,,,,,,,,,,,,
+7576,"NAD83(2011) / WISCRS Taylor (m)",9001,6318,7476,9801,1,0,4499,8801,45.1040159509,9110,8802,-90.29,9110,8805,1.0000597566,9201,8806,187147.5744,9001,8807,107746.7522,9001,,,,,,,,,,,,,
+7577,"NAD83(2011) / WISCRS Trempealeau (m)",9001,6318,7478,9807,1,0,4499,8801,43.094,9110,8802,-91.22,9110,8805,1.0000361538,9201,8806,256946.9138,9001,8807,0.0041,9001,,,,,,,,,,,,,
+7578,"NAD83(2011) / WISCRS Vernon (m)",9001,6318,7518,9801,1,0,4499,8801,43.3430118583,9110,8802,-90.47,9110,8805,1.0000408158,9201,8806,222504.4451,9001,8807,47532.0602,9001,,,,,,,,,,,,,
+7579,"NAD83(2011) / WISCRS Vilas (m)",9001,6318,7398,9801,1,0,4499,8801,46.0440238726,9110,8802,-89.292,9110,8805,1.0000730142,9201,8806,134417.0689,9001,8807,50337.1092,9001,,,,,,,,,,,,,
+7580,"NAD83(2011) / WISCRS Walworth (m)",9001,6318,7520,9801,1,0,4499,8801,42.4010063549,9110,8802,-88.323,9110,8805,1.0000367192,9201,8806,232562.8651,9001,8807,111088.2224,9001,,,,,,,,,,,,,
+7581,"NAD83(2011) / WISCRS Washburn (m)",9001,6318,7424,9801,1,0,4499,8801,45.57403914,9110,8802,-91.47,9110,8805,1.0000475376,9201,8806,234086.8682,9001,8807,188358.6058,9001,,,,,,,,,,,,,
+7582,"NAD83(2011) / WISCRS Washington (m)",9001,6318,7522,9807,1,0,4499,8801,42.5505,9110,8802,-88.035,9110,8805,1.00003738,9201,8806,120091.4415,9001,8807,0.003,9001,,,,,,,,,,,,,
+7583,"NAD83(2011) / WISCRS Waukesha (m)",9001,6318,7524,9807,1,0,4499,8801,42.341,9110,8802,-88.133,9110,8805,1.0000346179,9201,8806,208788.418,9001,8807,0.0034,9001,,,,,,,,,,,,,
+7584,"NAD83(2011) / WISCRS Waupaca (m)",9001,6318,7480,9807,1,0,4499,8801,43.2513,9110,8802,-88.49,9110,8805,1.0000333645,9201,8806,185013.9709,9001,8807,0.007,9001,,,,,,,,,,,,,
+7585,"NAD83(2011) / WISCRS Waushara (m)",9001,6318,7526,9801,1,0,4499,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,120091.4402,9001,8807,45069.7587,9001,,,,,,,,,,,,,
+7586,"NAD83(2011) / WISCRS Wood (m)",9001,6318,7482,9801,1,0,4499,8801,44.214534369,9110,8802,-90,9110,8805,1.0000421209,9201,8806,208483.6173,9001,8807,134589.754,9001,,,,,,,,,,,,,
+7587,"NAD83(2011) / WISCRS Adams and Juneau (ftUS)",9003,6318,7485,9807,1,0,4497,8801,43.22,9110,8802,-90,9110,8805,1.0000365285,9201,8806,482999.999,9003,8807,0.012,9003,,,,,,,,,,,,,
+7588,"NAD83(2011) / WISCRS Ashland (ftUS)",9003,6318,7379,9807,1,0,4497,8801,45.4222,9110,8802,-90.372,9110,8805,1.0000495683,9201,8806,567000.001,9003,8807,0.006,9003,,,,,,,,,,,,,
+7589,"NAD83(2011) / WISCRS Barron (ftUS)",9003,6318,7427,9807,1,0,4497,8801,45.08,9110,8802,-91.51,9110,8805,1.0000486665,9201,8806,305609.625,9003,8807,0.01,9003,,,,,,,,,,,,,
+7590,"NAD83(2011) / WISCRS Bayfield (ftUS)",9003,6318,7381,9801,1,0,4497,8801,46.4010734158,9110,8802,-91.091,9110,8805,1.0000331195,9201,8806,750000.001,9003,8807,487372.659,9003,,,,,,,,,,,,,
+7591,"NAD83(2011) / WISCRS Brown (ftUS)",9003,6318,7429,9807,1,0,4497,8801,43,9110,8802,-88,9110,8805,1.00002,9201,8806,103674.333,9003,8807,15091.833,9003,,,,,,,,,,,,,
+7592,"NAD83(2011) / WISCRS Buffalo (ftUS)",9003,6318,7431,9807,1,0,4497,8801,43.2853,9110,8802,-91.475,9110,8805,1.0000382778,9201,8806,574999.999,9003,8807,0.016,9003,,,,,,,,,,,,,
+7593,"NAD83(2011) / WISCRS Burnett (ftUS)",9003,6318,7383,9801,1,0,4497,8801,45.5355373517,9110,8802,-92.2728,9110,8805,1.0000383841,9201,8806,209999.999,9003,8807,195032.104,9003,,,,,,,,,,,,,
+7594,"NAD83(2011) / WISCRS Calumet, Fond du Lac, Outagamie and Winnebago (ftUS)",9003,6318,7487,9807,1,0,4497,8801,42.431,9110,8802,-88.3,9110,8805,1.0000286569,9201,8806,802999.999,9003,8807,0.016,9003,,,,,,,,,,,,,
+7595,"NAD83(2011) / WISCRS Chippewa (ftUS)",9003,6318,7433,9801,1,0,4497,8801,44.5840284835,9110,8802,-91.174,9110,8805,1.0000391127,9201,8806,197000,9003,8807,144656.648,9003,,,,,,,,,,,,,
+7596,"NAD83(2011) / WISCRS Clark (ftUS)",9003,6318,7435,9807,1,0,4497,8801,43.36,9110,8802,-90.423,9110,8805,1.0000463003,9201,8806,655999.997,9003,8807,0.028,9003,,,,,,,,,,,,,
+7597,"NAD83(2011) / WISCRS Columbia (ftUS)",9003,6318,7489,9801,1,0,4497,8801,43.2745167925,9110,8802,-89.234,9110,8805,1.00003498,9201,8806,554999.999,9003,8807,366041.307,9003,,,,,,,,,,,,,
+7598,"NAD83(2011) / WISCRS Crawford (ftUS)",9003,6318,7491,9801,1,0,4497,8801,43.1200200178,9110,8802,-90.562,9110,8805,1.0000349151,9201,8806,373000,9003,8807,176190.987,9003,,,,,,,,,,,,,
+7599,"NAD83(2011) / WISCRS Dane (ftUS)",9003,6318,7493,9801,1,0,4497,8801,43.0410257735,9110,8802,-89.252,9110,8805,1.0000384786,9201,8806,811000,9003,8807,480943.886,9003,,,,,,,,,,,,,
+7600,"NAD83(2011) / WISCRS Dodge and Jefferson (ftUS)",9003,6318,7495,9807,1,0,4497,8801,41.282,9110,8802,-88.463,9110,8805,1.0000346418,9201,8806,863999.999,9003,8807,0.025,9003,,,,,,,,,,,,,
+7601,"NAD83(2011) / WISCRS Door (ftUS)",9003,6318,7437,9807,1,0,4497,8801,44.24,9110,8802,-87.162,9110,8805,1.0000187521,9201,8806,521000,9003,8807,0.008,9003,,,,,,,,,,,,,
+7602,"NAD83(2011) / WISCRS Douglas (ftUS)",9003,6318,7385,9807,1,0,4497,8801,45.53,9110,8802,-91.55,9110,8805,1.0000385418,9201,8806,194000,9003,8807,0.013,9003,,,,,,,,,,,,,
+7603,"NAD83(2011) / WISCRS Dunn (ftUS)",9003,6318,7439,9807,1,0,4497,8801,44.243,9110,8802,-91.534,9110,8805,1.0000410324,9201,8806,170000.001,9003,8807,0.01,9003,,,,,,,,,,,,,
+7604,"NAD83(2011) / WISCRS Eau Claire (ftUS)",9003,6318,7441,9801,1,0,4497,8801,44.5220212055,9110,8802,-91.172,9110,8805,1.000035079,9201,8806,394000,9003,8807,300812.797,9003,,,,,,,,,,,,,
+7605,"NAD83(2011) / WISCRS Florence (ftUS)",9003,6318,7387,9807,1,0,4497,8801,45.262,9110,8802,-88.083,9110,8805,1.0000552095,9201,8806,438000.004,9003,8807,0.021,9003,,,,,,,,,,,,,
+7606,"NAD83(2011) / WISCRS Forest (ftUS)",9003,6318,7389,9807,1,0,4497,8801,44.002,9110,8802,-88.38,9110,8805,1.0000673004,9201,8806,905000.005,9003,8807,0.052,9003,,,,,,,,,,,,,
+7607,"NAD83(2011) / WISCRS Grant (ftUS)",9003,6318,7497,9807,1,0,4497,8801,41.244,9110,8802,-90.48,9110,8805,1.0000349452,9201,8806,794999.998,9003,8807,0.033,9003,,,,,,,,,,,,,
+7608,"NAD83(2011) / WISCRS Green and Lafayette (ftUS)",9003,6318,7499,9801,1,0,4497,8801,42.3815224197,9110,8802,-89.502,9110,8805,1.0000390487,9201,8806,558000,9003,8807,150361.559,9003,,,,,,,,,,,,,
+7609,"NAD83(2011) / WISCRS Green Lake and Marquette (ftUS)",9003,6318,7501,9801,1,0,4497,8801,43.4825200424,9110,8802,-89.143,9110,8805,1.0000344057,9201,8806,495000,9003,8807,259746.132,9003,,,,,,,,,,,,,
+7610,"NAD83(2011) / WISCRS Iowa (ftUS)",9003,6318,7503,9807,1,0,4497,8801,42.322,9110,8802,-90.094,9110,8805,1.0000394961,9201,8806,371000,9003,8807,0.015,9003,,,,,,,,,,,,,
+7611,"NAD83(2011) / WISCRS Iron (ftUS)",9003,6318,7391,9807,1,0,4497,8801,45.26,9110,8802,-90.152,9110,8805,1.0000677153,9201,8806,725000,9003,8807,0.028,9003,,,,,,,,,,,,,
+7612,"NAD83(2011) / WISCRS Jackson (ftUS)",9003,6318,7451,9807,1,0,4497,8801,44.151200646,9110,8802,-90.503946747,9110,8805,1.0000353,9201,8806,88582.5,9003,8807,82020.833,9003,,,,,,,,,,,,,
+7613,"NAD83(2011) / WISCRS Kenosha, Milwaukee, Ozaukee and Racine (ftUS)",9003,6318,7505,9807,1,0,4497,8801,42.13,9110,8802,-87.534,9110,8805,1.0000260649,9201,8806,610000.003,9003,8807,0.003,9003,,,,,,,,,,,,,
+7614,"NAD83(2011) / WISCRS Kewaunee, Manitowoc and Sheboygan (ftUS)",9003,6318,7507,9807,1,0,4497,8801,43.16,9110,8802,-87.33,9110,8805,1.0000233704,9201,8806,262000.006,9003,8807,0.004,9003,,,,,,,,,,,,,
+7615,"NAD83(2011) / WISCRS La Crosse (ftUS)",9003,6318,7509,9807,1,0,4497,8801,43.2704,9110,8802,-91.19,9110,8805,1.0000319985,9201,8806,427999.996,9003,8807,0.011,9003,,,,,,,,,,,,,
+7616,"NAD83(2011) / WISCRS Langlade (ftUS)",9003,6318,7453,9801,1,0,4497,8801,45.0915253579,9110,8802,-89.02,9110,8805,1.0000627024,9201,8806,651000,9003,8807,345405.421,9003,,,,,,,,,,,,,
+7617,"NAD83(2011) / WISCRS Lincoln (ftUS)",9003,6318,7455,9807,1,0,4497,8801,44.504,9110,8802,-89.44,9110,8805,1.0000599003,9201,8806,381000,9003,8807,0.019,9003,,,,,,,,,,,,,
+7618,"NAD83(2011) / WISCRS Marathon (ftUS)",9003,6318,7457,9801,1,0,4497,8801,44.5403255925,9110,8802,-89.4612,9110,8805,1.000053289,9201,8806,245000,9003,8807,180607.47,9003,,,,,,,,,,,,,
+7619,"NAD83(2011) / WISCRS Marinette (ftUS)",9003,6318,7459,9807,1,0,4497,8801,44.413,9110,8802,-87.424,9110,8805,1.0000234982,9201,8806,783000.007,9003,8807,0.01,9003,,,,,,,,,,,,,
+7620,"NAD83(2011) / WISCRS Menominee (ftUS)",9003,6318,7461,9807,1,0,4497,8801,44.43,9110,8802,-88.25,9110,8805,1.0000362499,9201,8806,346000.004,9003,8807,0.01,9003,,,,,,,,,,,,,
+7621,"NAD83(2011) / WISCRS Monroe (ftUS)",9003,6318,7511,9801,1,0,4497,8801,44.0000266143,9110,8802,-90.383,9110,8805,1.0000434122,9201,8806,671000,9003,8807,400012.278,9003,,,,,,,,,,,,,
+7622,"NAD83(2011) / WISCRS Oconto (ftUS)",9003,6318,7463,9807,1,0,4497,8801,44.235,9110,8802,-87.543,9110,8805,1.0000236869,9201,8806,600000.006,9003,8807,0.011,9003,,,,,,,,,,,,,
+7623,"NAD83(2011) / WISCRS Oneida (ftUS)",9003,6318,7393,9801,1,0,4497,8801,45.4215205573,9110,8802,-89.324,9110,8805,1.0000686968,9201,8806,230000,9003,8807,188936.744,9003,,,,,,,,,,,,,
+7624,"NAD83(2011) / WISCRS Pepin and Pierce (ftUS)",9003,6318,7465,9801,1,0,4497,8801,44.3810135939,9110,8802,-92.134,9110,8805,1.0000362977,9201,8806,550000,9003,8807,282260.222,9003,,,,,,,,,,,,,
+7625,"NAD83(2011) / WISCRS Polk (ftUS)",9003,6318,7467,9807,1,0,4497,8801,44.394,9110,8802,-92.38,9110,8805,1.0000433849,9201,8806,464999.996,9003,8807,0.019,9003,,,,,,,,,,,,,
+7626,"NAD83(2011) / WISCRS Portage (ftUS)",9003,6318,7469,9801,1,0,4497,8801,44.2500566311,9110,8802,-89.3,9110,8805,1.000039936,9201,8806,185000,9003,8807,164114.46,9003,,,,,,,,,,,,,
+7627,"NAD83(2011) / WISCRS Price (ftUS)",9003,6318,7395,9807,1,0,4497,8801,44.332,9110,8802,-90.292,9110,8805,1.0000649554,9201,8806,747999.995,9003,8807,0.036,9003,,,,,,,,,,,,,
+7628,"NAD83(2011) / WISCRS Richland (ftUS)",9003,6318,7513,9801,1,0,4497,8801,43.1920326539,9110,8802,-90.255,9110,8805,1.0000375653,9201,8806,664000,9003,8807,440469.675,9003,,,,,,,,,,,,,
+7629,"NAD83(2011) / WISCRS Rock (ftUS)",9003,6318,7515,9807,1,0,4497,8801,41.564,9110,8802,-89.042,9110,8805,1.0000337311,9201,8806,480000,9003,8807,0.022,9003,,,,,,,,,,,,,
+7630,"NAD83(2011) / WISCRS Rusk (ftUS)",9003,6318,7471,9807,1,0,4497,8801,43.551,9110,8802,-91.04,9110,8805,1.0000495976,9201,8806,822000.001,9003,8807,0.077,9003,,,,,,,,,,,,,
+7631,"NAD83(2011) / WISCRS Sauk (ftUS)",9003,6318,7517,9807,1,0,4497,8801,42.491,9110,8802,-89.54,9110,8805,1.0000373868,9201,8806,609000.001,9003,8807,0.017,9003,,,,,,,,,,,,,
+7632,"NAD83(2011) / WISCRS Sawyer (ftUS)",9003,6318,7397,9801,1,0,4497,8801,45.5400356873,9110,8802,-91.07,9110,8805,1.0000573461,9201,8806,711000.001,9003,8807,396108.667,9003,,,,,,,,,,,,,
+7633,"NAD83(2011) / WISCRS Shawano (ftUS)",9003,6318,7473,9807,1,0,4497,8801,44.021,9110,8802,-88.362,9110,8805,1.000032144,9201,8806,861000.001,9003,8807,0.031,9003,,,,,,,,,,,,,
+7634,"NAD83(2011) / WISCRS St. Croix (ftUS)",9003,6318,7475,9807,1,0,4497,8801,44.021,9110,8802,-92.38,9110,8805,1.0000381803,9201,8806,542999.997,9003,8807,0.034,9003,,,,,,,,,,,,,
+7635,"NAD83(2011) / WISCRS Taylor (ftUS)",9003,6318,7477,9801,1,0,4497,8801,45.1040159509,9110,8802,-90.29,9110,8805,1.0000597566,9201,8806,614000,9003,8807,353499.136,9003,,,,,,,,,,,,,
+7636,"NAD83(2011) / WISCRS Trempealeau (ftUS)",9003,6318,7479,9807,1,0,4497,8801,43.094,9110,8802,-91.22,9110,8805,1.0000361538,9201,8806,843000,9003,8807,0.013,9003,,,,,,,,,,,,,
+7637,"NAD83(2011) / WISCRS Vernon (ftUS)",9003,6318,7519,9801,1,0,4497,8801,43.3430118583,9110,8802,-90.47,9110,8805,1.0000408158,9201,8806,730000,9003,8807,155944.768,9003,,,,,,,,,,,,,
+7638,"NAD83(2011) / WISCRS Vilas (ftUS)",9003,6318,7399,9801,1,0,4497,8801,46.0440238726,9110,8802,-89.292,9110,8805,1.0000730142,9201,8806,441000,9003,8807,165147.666,9003,,,,,,,,,,,,,
+7639,"NAD83(2011) / WISCRS Walworth (ftUS)",9003,6318,7521,9801,1,0,4497,8801,42.4010063549,9110,8802,-88.323,9110,8805,1.0000367192,9201,8806,763000,9003,8807,364461.943,9003,,,,,,,,,,,,,
+7640,"NAD83(2011) / WISCRS Washburn (ftUS)",9003,6318,7425,9801,1,0,4497,8801,45.57403914,9110,8802,-91.47,9110,8805,1.0000475376,9201,8806,768000,9003,8807,617973.193,9003,,,,,,,,,,,,,
+7641,"NAD83(2011) / WISCRS Washington (ftUS)",9003,6318,7523,9807,1,0,4497,8801,42.5505,9110,8802,-88.035,9110,8805,1.00003738,9201,8806,394000.004,9003,8807,0.01,9003,,,,,,,,,,,,,
+7642,"NAD83(2011) / WISCRS Waukesha (ftUS)",9003,6318,7525,9807,1,0,4497,8801,42.341,9110,8802,-88.133,9110,8805,1.0000346179,9201,8806,685000.001,9003,8807,0.011,9003,,,,,,,,,,,,,
+7643,"NAD83(2011) / WISCRS Waupaca (ftUS)",9003,6318,7481,9807,1,0,4497,8801,43.2513,9110,8802,-88.49,9110,8805,1.0000333645,9201,8806,607000.003,9003,8807,0.023,9003,,,,,,,,,,,,,
+7644,"NAD83(2011) / WISCRS Waushara (ftUS)",9003,6318,7527,9801,1,0,4497,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,394000,9003,8807,147866.367,9003,,,,,,,,,,,,,
+7645,"NAD83(2011) / WISCRS Wood (ftUS)",9003,6318,7483,9801,1,0,4497,8801,44.214534369,9110,8802,-90,9110,8805,1.0000421209,9201,8806,684000.001,9003,8807,441566.551,9003,,,,,,,,,,,,,
+7692,"Kyrg-06 / zone 1",9001,7686,7687,9807,1,0,4400,8801,0,9110,8802,68.31,9110,8805,1,9201,8806,1300000,9001,8807,14743.5,9001,,,,,,,,,,,,,
+7693,"Kyrg-06 / zone 2",9001,7686,7688,9807,1,0,4400,8801,0,9110,8802,71.31,9110,8805,1,9201,8806,2300000,9001,8807,14743.5,9001,,,,,,,,,,,,,
+7694,"Kyrg-06 / zone 3",9001,7686,7689,9807,1,0,4400,8801,0,9110,8802,74.31,9110,8805,1,9201,8806,3300000,9001,8807,14743.5,9001,,,,,,,,,,,,,
+7695,"Kyrg-06 / zone 4",9001,7686,7690,9807,1,0,4400,8801,0,9110,8802,77.31,9110,8805,1,9201,8806,4300000,9001,8807,14743.5,9001,,,,,,,,,,,,,
+7696,"Kyrg-06 / zone 5",9001,7686,7691,9807,1,0,4400,8801,0,9110,8802,80.31,9110,8805,1,9201,8806,5300000,9001,8807,14743.5,9001,,,,,,,,,,,,,
+7755,"WGS 84 / India NSF LCC",9001,4326,7722,9802,1,0,4499,8821,24,9102,8822,80,9102,8823,12.2822638,9110,8824,35.1022096,9110,8826,4000000,9001,8827,4000000,9001,,,,,,,,,,
+7756,"WGS 84 / Andhra Pradesh",9001,4326,7723,9802,1,0,4499,8821,16.25543298,9102,8822,80.875,9102,8823,13.75,9102,8824,18.75,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7757,"WGS 84 / Arunachal Pradesh",9001,4326,7724,9802,1,0,4499,8821,28.00157897,9102,8822,94.5,9102,8823,27,9102,8824,29,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7758,"WGS 84 / Assam",9001,4326,7725,9802,1,0,4499,8821,26.00257703,9102,8822,92.75,9102,8823,24.4,9110,8824,27.2,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7759,"WGS 84 / Bihar",9001,4326,7726,9802,1,0,4499,8821,25.87725247,9102,8822,85.875,9102,8823,24.625,9102,8824,27.125,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7760,"WGS 84 / Delhi",9001,4326,7727,9802,1,0,4499,8821,28.62510126,9102,8822,77,9102,8823,28.223,9110,8824,28.523,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7761,"WGS 84 / Gujarat",9001,4326,7728,9802,1,0,4499,8821,22.37807121,9102,8822,71.375,9102,8823,20.473,9110,8824,23.573,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7762,"WGS 84 / Haryana",9001,4326,7729,9802,1,0,4499,8821,29.25226266,9102,8822,76,9102,8823,28.05,9110,8824,30.25,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7763,"WGS 84 / Himachal Pradesh",9001,4326,7730,9802,1,0,4499,8821,31.75183497,9102,8822,77.375,9102,8823,30.75,9102,8824,32.75,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7764,"WGS 84 / Jammu and Kashmir",9001,4326,7731,9802,1,0,4499,8821,34.75570874,9102,8822,76.5,9102,8823,33.05,9110,8824,36.25,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7765,"WGS 84 / Jharkhand",9001,4326,7732,9802,1,0,4499,8821,23.62652682,9102,8822,85.625,9102,8823,22.323,9110,8824,24.423,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7766,"WGS 84 / Madhya Pradesh",9001,4326,7733,9802,1,0,4499,8821,24.00529821,9102,8822,78.375,9102,8823,22,9102,8824,26,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7767,"WGS 84 / Maharashtra",9001,4326,7734,9802,1,0,4499,8821,18.88015774,9102,8822,76.75,9102,8823,16.373,9110,8824,21.073,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7768,"WGS 84 / Manipur",9001,4326,7735,9802,1,0,4499,8821,24.75060911,9102,8822,94,9102,8823,24.05,9110,8824,25.25,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7769,"WGS 84 / Meghalaya",9001,4326,7736,9802,1,0,4499,8821,25.62524747,9102,8822,91.375,9102,8823,25.123,9110,8824,26.023,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7770,"WGS 84 / Nagaland",9001,4326,7737,9802,1,0,4499,8821,26.12581974,9102,8822,94.375,9102,8823,25.223,9110,8824,26.523,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7771,"WGS 84 / India Northeast",9001,4326,7738,9802,1,0,4499,8821,25.63452135,9102,8822,93.5,9102,8823,23.023,9110,8824,28.123,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7772,"WGS 84 / Orissa",9001,4326,7739,9802,1,0,4499,8821,20.25305174,9102,8822,84.375,9102,8823,18.35,9110,8824,21.55,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7773,"WGS 84 / Punjab",9001,4326,7740,9802,1,0,4499,8821,31.00178226,9102,8822,75.375,9102,8823,30,9102,8824,32,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7774,"WGS 84 / Rajasthan",9001,4326,7741,9802,1,0,4499,8821,26.88505546,9102,8822,73.875,9102,8823,24.173,9110,8824,29.273,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7775,"WGS 84 / Uttar Pradesh",9001,4326,7742,9802,1,0,4499,8821,27.13270823,9102,8822,80.875,9102,8823,24.523,9110,8824,29.223,9110,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7776,"WGS 84 / Uttaranchal",9001,4326,7743,9802,1,0,4499,8821,30.0017132,9102,8822,79.375,9102,8823,29,9102,8824,31,9102,8826,1000000,9001,8827,1000000,9001,,,,,,,,,,
+7777,"WGS 84 / Andaman and Nicobar",9001,4326,7744,9807,1,0,4499,8801,10.25,9102,8802,93.25,9102,8805,0.9999428,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7778,"WGS 84 / Chhattisgarh",9001,4326,7745,9807,1,0,4499,8801,21,9102,8802,82.25,9102,8805,0.9998332,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7779,"WGS 84 / Goa",9001,4326,7746,9807,1,0,4499,8801,15.375,9102,8802,74,9102,8805,0.9999913,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7780,"WGS 84 / Karnataka",9001,4326,7747,9807,1,0,4499,8801,15.125,9102,8802,76.375,9102,8805,0.9998012,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7781,"WGS 84 / Kerala",9001,4326,7748,9807,1,0,4499,8801,10.5,9102,8802,76,9102,8805,0.9999177,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7782,"WGS 84 / Lakshadweep",9001,4326,7749,9807,1,0,4499,8801,10,9102,8802,73.125,9102,8805,0.9999536,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7783,"WGS 84 / Mizoram",9001,4326,7750,9807,1,0,4499,8801,23.125,9102,8802,92.75,9102,8805,0.9999821,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7784,"WGS 84 / Sikkim",9001,4326,7751,9807,1,0,4499,8801,27.625,9102,8802,88.5,9102,8805,0.9999926,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7785,"WGS 84 / Tamil Nadu",9001,4326,7752,9807,1,0,4499,8801,10.875,9102,8802,78.375,9102,8805,0.9997942,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7786,"WGS 84 / Tripura",9001,4326,7753,9807,1,0,4499,8801,23.75,9102,8802,91.75,9102,8805,0.9999822,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7787,"WGS 84 / West Bengal",9001,4326,7754,9807,1,0,4499,8801,24.375,9102,8802,87.875,9102,8805,0.9998584,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+7791,"RDN2008 / UTM zone 32N",9001,6706,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7792,"RDN2008 / UTM zone 33N",9001,6706,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7793,"RDN2008 / UTM zone 34N",9001,6706,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7794,"RDN2008 / Italy zone (E-N)",9001,6706,6877,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9985,9201,8806,7000000,9001,8807,0,9001,,,,,,,,,,,,,
+7795,"RDN2008 / Zone 12 (E-N)",9001,6706,6878,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,1,9201,8806,3000000,9001,8807,0,9001,,,,,,,,,,,,,
+7799,"BGS2005 / UTM zone 34N (N-E)",9001,7798,16034,9807,1,0,4531,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7800,"BGS2005 / UTM zone 35N (N-E)",9001,7798,16035,9807,1,0,4531,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7801,"BGS2005 / CCS2005",9001,7798,7802,9802,1,0,4531,8821,42.400435246,9110,8822,25.3,9110,8823,42,9110,8824,43.2,9110,8826,500000,9001,8827,4725824.3591,9001,,,,,,,,,,
+7803,"BGS2005 / UTM zone 34N",9001,7798,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7804,"BGS2005 / UTM zone 35N",9001,7798,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7805,"BGS2005 / UTM zone 36N",9001,7798,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+7825,"Pulkovo 1942 / CS63 zone X1",9001,4284,7818,9807,1,0,4530,8801,0.05,9110,8802,23.3,9110,8805,1,9201,8806,1300000,9001,8807,0,9001,,,,,,,,,,,,,
+7826,"Pulkovo 1942 / CS63 zone X2",9001,4284,7819,9807,1,0,4530,8801,0.05,9110,8802,26.3,9110,8805,1,9201,8806,2300000,9001,8807,0,9001,,,,,,,,,,,,,
+7827,"Pulkovo 1942 / CS63 zone X3",9001,4284,7820,9807,1,0,4530,8801,0.05,9110,8802,29.3,9110,8805,1,9201,8806,3300000,9001,8807,0,9001,,,,,,,,,,,,,
+7828,"Pulkovo 1942 / CS63 zone X4",9001,4284,7821,9807,1,0,4530,8801,0.05,9110,8802,32.3,9110,8805,1,9201,8806,4300000,9001,8807,0,9001,,,,,,,,,,,,,
+7829,"Pulkovo 1942 / CS63 zone X5",9001,4284,7822,9807,1,0,4530,8801,0.05,9110,8802,35.3,9110,8805,1,9201,8806,5300000,9001,8807,0,9001,,,,,,,,,,,,,
+7830,"Pulkovo 1942 / CS63 zone X6",9001,4284,7823,9807,1,0,4530,8801,0.05,9110,8802,38.3,9110,8805,1,9201,8806,6300000,9001,8807,0,9001,,,,,,,,,,,,,
+7831,"Pulkovo 1942 / CS63 zone X7",9001,4284,7824,9807,1,0,4530,8801,0.05,9110,8802,41.3,9110,8805,1,9201,8806,7300000,9001,8807,0,9001,,,,,,,,,,,,,
+7845,"GDA2020 / GA LCC",9001,7844,17362,9802,1,0,4400,8821,0,9102,8822,134,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,,,,,,,,
+7846,"GDA2020 / MGA zone 46",9001,7844,6729,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7847,"GDA2020 / MGA zone 47",9001,7844,6730,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7848,"GDA2020 / MGA zone 48",9001,7844,17348,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7849,"GDA2020 / MGA zone 49",9001,7844,17349,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7850,"GDA2020 / MGA zone 50",9001,7844,17350,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7851,"GDA2020 / MGA zone 51",9001,7844,17351,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7852,"GDA2020 / MGA zone 52",9001,7844,17352,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7853,"GDA2020 / MGA zone 53",9001,7844,17353,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7854,"GDA2020 / MGA zone 54",9001,7844,17354,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7855,"GDA2020 / MGA zone 55",9001,7844,17355,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7856,"GDA2020 / MGA zone 56",9001,7844,17356,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7857,"GDA2020 / MGA zone 57",9001,7844,17357,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7858,"GDA2020 / MGA zone 58",9001,7844,17358,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7859,"GDA2020 / MGA zone 59",9001,7844,6731,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7877,"Astro DOS 71 / SHLG71",9001,4710,7875,9807,1,0,4400,8801,-15.58,9110,8802,-5.43,9110,8805,1,9201,8806,300000,9001,8807,2000000,9001,,,,,,,,,,,,,
+7878,"Astro DOS 71 / UTM zone 30S",9001,4710,16130,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7882,"St. Helena Tritan / SHLG(Tritan)",9001,7881,7876,9807,1,0,4400,8801,-15.58,9110,8802,-5.43,9110,8805,1,9201,8806,299483.737,9001,8807,2000527.879,9001,,,,,,,,,,,,,
+7883,"St. Helena Tritan / UTM zone 30S",9001,7881,16130,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7887,SHMG2015,9001,7886,16130,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+7899,"GDA2020 / Vicgrid",9001,7844,17361,9802,1,0,4400,8821,-37,9102,8822,145,9102,8823,-36,9102,8824,-38,9102,8826,2500000,9001,8827,2500000,9001,,,,,,,,,,
+20004,"Pulkovo 1995 / Gauss-Kruger zone 4",9001,4200,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+20005,"Pulkovo 1995 / Gauss-Kruger zone 5",9001,4200,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+20006,"Pulkovo 1995 / Gauss-Kruger zone 6",9001,4200,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+20007,"Pulkovo 1995 / Gauss-Kruger zone 7",9001,4200,16207,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+20008,"Pulkovo 1995 / Gauss-Kruger zone 8",9001,4200,16208,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+20009,"Pulkovo 1995 / Gauss-Kruger zone 9",9001,4200,16209,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+20010,"Pulkovo 1995 / Gauss-Kruger zone 10",9001,4200,16210,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,,,,,,,,
+20011,"Pulkovo 1995 / Gauss-Kruger zone 11",9001,4200,16211,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,,,,,,,,
+20012,"Pulkovo 1995 / Gauss-Kruger zone 12",9001,4200,16212,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,,,,,,,,
+20013,"Pulkovo 1995 / Gauss-Kruger zone 13",9001,4200,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+20014,"Pulkovo 1995 / Gauss-Kruger zone 14",9001,4200,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+20015,"Pulkovo 1995 / Gauss-Kruger zone 15",9001,4200,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+20016,"Pulkovo 1995 / Gauss-Kruger zone 16",9001,4200,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,,,,,,,,
+20017,"Pulkovo 1995 / Gauss-Kruger zone 17",9001,4200,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,,,,,,,,
+20018,"Pulkovo 1995 / Gauss-Kruger zone 18",9001,4200,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,,,,,,,,
+20019,"Pulkovo 1995 / Gauss-Kruger zone 19",9001,4200,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+20020,"Pulkovo 1995 / Gauss-Kruger zone 20",9001,4200,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,,,,,,,,
+20021,"Pulkovo 1995 / Gauss-Kruger zone 21",9001,4200,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,,,,,,,,
+20022,"Pulkovo 1995 / Gauss-Kruger zone 22",9001,4200,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,,,,,,,,
+20023,"Pulkovo 1995 / Gauss-Kruger zone 23",9001,4200,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,,,,,,,,
+20024,"Pulkovo 1995 / Gauss-Kruger zone 24",9001,4200,16224,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,,,,,,,,
+20025,"Pulkovo 1995 / Gauss-Kruger zone 25",9001,4200,16225,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,,,,,,,,
+20026,"Pulkovo 1995 / Gauss-Kruger zone 26",9001,4200,16226,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,,,,,,,,
+20027,"Pulkovo 1995 / Gauss-Kruger zone 27",9001,4200,16227,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,,,,,,,,
+20028,"Pulkovo 1995 / Gauss-Kruger zone 28",9001,4200,16228,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,,,,,,,,
+20029,"Pulkovo 1995 / Gauss-Kruger zone 29",9001,4200,16229,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,,,,,,,,
+20030,"Pulkovo 1995 / Gauss-Kruger zone 30",9001,4200,16230,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,,,,,,,,
+20031,"Pulkovo 1995 / Gauss-Kruger zone 31",9001,4200,16231,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+20032,"Pulkovo 1995 / Gauss-Kruger zone 32",9001,4200,16232,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+20064,"Pulkovo 1995 / Gauss-Kruger 4N",9001,4200,16304,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20065,"Pulkovo 1995 / Gauss-Kruger 5N",9001,4200,16305,9807,1,1,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20066,"Pulkovo 1995 / Gauss-Kruger 6N",9001,4200,16306,9807,1,1,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20067,"Pulkovo 1995 / Gauss-Kruger 7N",9001,4200,16307,9807,1,1,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20068,"Pulkovo 1995 / Gauss-Kruger 8N",9001,4200,16308,9807,1,1,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20069,"Pulkovo 1995 / Gauss-Kruger 9N",9001,4200,16309,9807,1,1,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20070,"Pulkovo 1995 / Gauss-Kruger 10N",9001,4200,16310,9807,1,1,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20071,"Pulkovo 1995 / Gauss-Kruger 11N",9001,4200,16311,9807,1,1,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20072,"Pulkovo 1995 / Gauss-Kruger 12N",9001,4200,16312,9807,1,1,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20073,"Pulkovo 1995 / Gauss-Kruger 13N",9001,4200,16313,9807,1,1,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20074,"Pulkovo 1995 / Gauss-Kruger 14N",9001,4200,16314,9807,1,1,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20075,"Pulkovo 1995 / Gauss-Kruger 15N",9001,4200,16315,9807,1,1,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20076,"Pulkovo 1995 / Gauss-Kruger 16N",9001,4200,16316,9807,1,1,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20077,"Pulkovo 1995 / Gauss-Kruger 17N",9001,4200,16317,9807,1,1,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20078,"Pulkovo 1995 / Gauss-Kruger 18N",9001,4200,16318,9807,1,1,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20079,"Pulkovo 1995 / Gauss-Kruger 19N",9001,4200,16319,9807,1,1,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20080,"Pulkovo 1995 / Gauss-Kruger 20N",9001,4200,16320,9807,1,1,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20081,"Pulkovo 1995 / Gauss-Kruger 21N",9001,4200,16321,9807,1,1,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20082,"Pulkovo 1995 / Gauss-Kruger 22N",9001,4200,16322,9807,1,1,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20083,"Pulkovo 1995 / Gauss-Kruger 23N",9001,4200,16323,9807,1,1,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20084,"Pulkovo 1995 / Gauss-Kruger 24N",9001,4200,16324,9807,1,1,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20085,"Pulkovo 1995 / Gauss-Kruger 25N",9001,4200,16325,9807,1,1,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20086,"Pulkovo 1995 / Gauss-Kruger 26N",9001,4200,16326,9807,1,1,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20087,"Pulkovo 1995 / Gauss-Kruger 27N",9001,4200,16327,9807,1,1,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20088,"Pulkovo 1995 / Gauss-Kruger 28N",9001,4200,16328,9807,1,1,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20089,"Pulkovo 1995 / Gauss-Kruger 29N",9001,4200,16329,9807,1,1,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20090,"Pulkovo 1995 / Gauss-Kruger 30N",9001,4200,16330,9807,1,1,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20091,"Pulkovo 1995 / Gauss-Kruger 31N",9001,4200,16331,9807,1,1,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20092,"Pulkovo 1995 / Gauss-Kruger 32N",9001,4200,16332,9807,1,1,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20135,"Adindan / UTM zone 35N",9001,4201,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20136,"Adindan / UTM zone 36N",9001,4201,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20137,"Adindan / UTM zone 37N",9001,4201,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20138,"Adindan / UTM zone 38N",9001,4201,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20248,"AGD66 / AMG zone 48",9001,4202,17448,9807,1,1,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20249,"AGD66 / AMG zone 49",9001,4202,17449,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20250,"AGD66 / AMG zone 50",9001,4202,17450,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20251,"AGD66 / AMG zone 51",9001,4202,17451,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20252,"AGD66 / AMG zone 52",9001,4202,17452,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20253,"AGD66 / AMG zone 53",9001,4202,17453,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20254,"AGD66 / AMG zone 54",9001,4202,17454,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20255,"AGD66 / AMG zone 55",9001,4202,17455,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20256,"AGD66 / AMG zone 56",9001,4202,17456,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20257,"AGD66 / AMG zone 57",9001,4202,17457,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20258,"AGD66 / AMG zone 58",9001,4202,17458,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20348,"AGD84 / AMG zone 48",9001,4203,17448,9807,1,1,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20349,"AGD84 / AMG zone 49",9001,4203,17449,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20350,"AGD84 / AMG zone 50",9001,4203,17450,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20351,"AGD84 / AMG zone 51",9001,4203,17451,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20352,"AGD84 / AMG zone 52",9001,4203,17452,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20353,"AGD84 / AMG zone 53",9001,4203,17453,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20354,"AGD84 / AMG zone 54",9001,4203,17454,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20355,"AGD84 / AMG zone 55",9001,4203,17455,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20356,"AGD84 / AMG zone 56",9001,4203,17456,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20357,"AGD84 / AMG zone 57",9001,4203,17457,9807,1,1,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20358,"AGD84 / AMG zone 58",9001,4203,17458,9807,1,1,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20436,"Ain el Abd / UTM zone 36N",9001,4204,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20437,"Ain el Abd / UTM zone 37N",9001,4204,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20438,"Ain el Abd / UTM zone 38N",9001,4204,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20439,"Ain el Abd / UTM zone 39N",9001,4204,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20440,"Ain el Abd / UTM zone 40N",9001,4204,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20499,"Ain el Abd / Bahrain Grid",9001,4204,19900,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20538,"Afgooye / UTM zone 38N",9001,4205,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20539,"Afgooye / UTM zone 39N",9001,4205,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+20790,"Lisbon (Lisbon) / Portuguese National Grid",9001,4803,19936,9807,1,0,4499,8801,39.4,9110,8802,1,9110,8805,1,9201,8806,200000,9001,8807,300000,9001,,,,,,,,,,,,,
+20791,"Lisbon (Lisbon) / Portuguese Grid",9001,4803,19969,9807,1,0,4499,8801,39.4,9110,8802,1,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+20822,"Aratu / UTM zone 22S",9001,4208,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20823,"Aratu / UTM zone 23S",9001,4208,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20824,"Aratu / UTM zone 24S",9001,4208,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20934,"Arc 1950 / UTM zone 34S",9001,4209,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20935,"Arc 1950 / UTM zone 35S",9001,4209,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+20936,"Arc 1950 / UTM zone 36S",9001,4209,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+21035,"Arc 1960 / UTM zone 35S",9001,4210,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+21036,"Arc 1960 / UTM zone 36S",9001,4210,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+21037,"Arc 1960 / UTM zone 37S",9001,4210,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+21095,"Arc 1960 / UTM zone 35N",9001,4210,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21096,"Arc 1960 / UTM zone 36N",9001,4210,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21097,"Arc 1960 / UTM zone 37N",9001,4210,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21100,"Batavia (Jakarta) / NEIEZ",9001,4813,19905,9804,1,1,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,,,,,,,,
+21148,"Batavia / UTM zone 48S",9001,4211,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+21149,"Batavia / UTM zone 49S",9001,4211,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+21150,"Batavia / UTM zone 50S",9001,4211,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+21291,"Barbados 1938 / British West Indies Grid",9001,4212,19942,9807,1,0,4400,8801,0,9102,8802,-62,9102,8805,0.9995,9201,8806,400000,9001,8807,0,9001,,,,,,,,,,,,,
+21292,"Barbados 1938 / Barbados National Grid",9001,4212,19943,9807,1,0,4400,8801,13.1035,9110,8802,-59.3335,9110,8805,0.9999986,9201,8806,30000,9001,8807,75000,9001,,,,,,,,,,,,,
+21413,"Beijing 1954 / Gauss-Kruger zone 13",9001,4214,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+21414,"Beijing 1954 / Gauss-Kruger zone 14",9001,4214,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+21415,"Beijing 1954 / Gauss-Kruger zone 15",9001,4214,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+21416,"Beijing 1954 / Gauss-Kruger zone 16",9001,4214,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,,,,,,,,
+21417,"Beijing 1954 / Gauss-Kruger zone 17",9001,4214,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,,,,,,,,
+21418,"Beijing 1954 / Gauss-Kruger zone 18",9001,4214,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,,,,,,,,
+21419,"Beijing 1954 / Gauss-Kruger zone 19",9001,4214,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+21420,"Beijing 1954 / Gauss-Kruger zone 20",9001,4214,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,,,,,,,,
+21421,"Beijing 1954 / Gauss-Kruger zone 21",9001,4214,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,,,,,,,,
+21422,"Beijing 1954 / Gauss-Kruger zone 22",9001,4214,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,,,,,,,,
+21423,"Beijing 1954 / Gauss-Kruger zone 23",9001,4214,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,,,,,,,,
+21453,"Beijing 1954 / Gauss-Kruger CM 75E",9001,4214,16313,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21454,"Beijing 1954 / Gauss-Kruger CM 81E",9001,4214,16314,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21455,"Beijing 1954 / Gauss-Kruger CM 87E",9001,4214,16315,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21456,"Beijing 1954 / Gauss-Kruger CM 93E",9001,4214,16316,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21457,"Beijing 1954 / Gauss-Kruger CM 99E",9001,4214,16317,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21458,"Beijing 1954 / Gauss-Kruger CM 105E",9001,4214,16318,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21459,"Beijing 1954 / Gauss-Kruger CM 111E",9001,4214,16319,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21460,"Beijing 1954 / Gauss-Kruger CM 117E",9001,4214,16320,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21461,"Beijing 1954 / Gauss-Kruger CM 123E",9001,4214,16321,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21462,"Beijing 1954 / Gauss-Kruger CM 129E",9001,4214,16322,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21463,"Beijing 1954 / Gauss-Kruger CM 135E",9001,4214,16323,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21473,"Beijing 1954 / Gauss-Kruger 13N",9001,4214,16313,9807,1,1,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21474,"Beijing 1954 / Gauss-Kruger 14N",9001,4214,16314,9807,1,1,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21475,"Beijing 1954 / Gauss-Kruger 15N",9001,4214,16315,9807,1,1,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21476,"Beijing 1954 / Gauss-Kruger 16N",9001,4214,16316,9807,1,1,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21477,"Beijing 1954 / Gauss-Kruger 17N",9001,4214,16317,9807,1,1,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21478,"Beijing 1954 / Gauss-Kruger 18N",9001,4214,16318,9807,1,1,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21479,"Beijing 1954 / Gauss-Kruger 19N",9001,4214,16319,9807,1,1,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21480,"Beijing 1954 / Gauss-Kruger 20N",9001,4214,16320,9807,1,1,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21481,"Beijing 1954 / Gauss-Kruger 21N",9001,4214,16321,9807,1,1,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21482,"Beijing 1954 / Gauss-Kruger 22N",9001,4214,16322,9807,1,1,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21483,"Beijing 1954 / Gauss-Kruger 23N",9001,4214,16323,9807,1,1,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21500,"Belge 1950 (Brussels) / Belge Lambert 50",9001,4809,19901,9802,1,0,4499,8821,90,9110,8822,0,9110,8823,49.5,9110,8824,51.1,9110,8826,150000,9001,8827,5400000,9001,,,,,,,,,,
+21780,"Bern 1898 (Bern) / LV03C",9001,4801,19923,9815,1,0,4498,8811,46.570866,9110,8812,0,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,0,9001,8817,0,9001,,,,,,,
+21781,"CH1903 / LV03",9001,4149,19922,9815,1,0,4498,8811,46.570866,9110,8812,7.26225,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,600000,9001,8817,200000,9001,,,,,,,
+21782,"CH1903 / LV03C-G",9001,4149,19841,9815,1,0,4498,8811,46.570866,9110,8812,7.26225,9110,8813,90,9110,8814,90,9110,8815,1,9201,8816,0,9001,8817,0,9001,,,,,,,
+21817,"Bogota 1975 / UTM zone 17N",9001,4218,16017,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21818,"Bogota 1975 / UTM zone 18N",9001,4218,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+21891,"Bogota 1975 / Colombia West zone",9001,4218,18051,9807,1,1,4499,8801,4.355657,9110,8802,-77.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+21892,"Bogota 1975 / Colombia Bogota zone",9001,4218,18052,9807,1,1,4499,8801,4.355657,9110,8802,-74.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+21893,"Bogota 1975 / Colombia East Central zone",9001,4218,18053,9807,1,1,4499,8801,4.355657,9110,8802,-71.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+21894,"Bogota 1975 / Colombia East",9001,4218,18054,9807,1,1,4499,8801,4.355657,9110,8802,-68.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+21896,"Bogota 1975 / Colombia West zone",9001,4218,18051,9807,1,0,4530,8801,4.355657,9110,8802,-77.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+21897,"Bogota 1975 / Colombia Bogota zone",9001,4218,18052,9807,1,0,4530,8801,4.355657,9110,8802,-74.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+21898,"Bogota 1975 / Colombia East Central zone",9001,4218,18053,9807,1,0,4530,8801,4.355657,9110,8802,-71.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+21899,"Bogota 1975 / Colombia East",9001,4218,18054,9807,1,0,4530,8801,4.355657,9110,8802,-68.04513,9110,8805,1,9201,8806,1000000,9001,8807,1000000,9001,,,,,,,,,,,,,
+22032,"Camacupa / UTM zone 32S",9001,4220,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22033,"Camacupa / UTM zone 33S",9001,4220,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22091,"Camacupa / TM 11.30 SE",9001,4220,16611,9807,1,0,4400,8801,0,9110,8802,11.3,9110,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22092,"Camacupa / TM 12 SE",9001,4220,16612,9807,1,0,4400,8801,0,9102,8802,12,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22171,"POSGAR 98 / Argentina 1",9001,4190,18031,9807,1,0,4530,8801,-90,9102,8802,-72,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+22172,"POSGAR 98 / Argentina 2",9001,4190,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+22173,"POSGAR 98 / Argentina 3",9001,4190,18033,9807,1,0,4530,8801,-90,9102,8802,-66,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+22174,"POSGAR 98 / Argentina 4",9001,4190,18034,9807,1,0,4530,8801,-90,9102,8802,-63,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+22175,"POSGAR 98 / Argentina 5",9001,4190,18035,9807,1,0,4530,8801,-90,9102,8802,-60,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+22176,"POSGAR 98 / Argentina 6",9001,4190,18036,9807,1,0,4530,8801,-90,9102,8802,-57,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+22177,"POSGAR 98 / Argentina 7",9001,4190,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+22181,"POSGAR 94 / Argentina 1",9001,4694,18031,9807,1,0,4530,8801,-90,9102,8802,-72,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+22182,"POSGAR 94 / Argentina 2",9001,4694,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+22183,"POSGAR 94 / Argentina 3",9001,4694,18033,9807,1,0,4530,8801,-90,9102,8802,-66,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+22184,"POSGAR 94 / Argentina 4",9001,4694,18034,9807,1,0,4530,8801,-90,9102,8802,-63,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+22185,"POSGAR 94 / Argentina 5",9001,4694,18035,9807,1,0,4530,8801,-90,9102,8802,-60,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+22186,"POSGAR 94 / Argentina 6",9001,4694,18036,9807,1,0,4530,8801,-90,9102,8802,-57,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+22187,"POSGAR 94 / Argentina 7",9001,4694,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+22191,"Campo Inchauspe / Argentina 1",9001,4221,18031,9807,1,0,4530,8801,-90,9102,8802,-72,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+22192,"Campo Inchauspe / Argentina 2",9001,4221,18032,9807,1,0,4530,8801,-90,9102,8802,-69,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+22193,"Campo Inchauspe / Argentina 3",9001,4221,18033,9807,1,0,4530,8801,-90,9102,8802,-66,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+22194,"Campo Inchauspe / Argentina 4",9001,4221,18034,9807,1,0,4530,8801,-90,9102,8802,-63,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+22195,"Campo Inchauspe / Argentina 5",9001,4221,18035,9807,1,0,4530,8801,-90,9102,8802,-60,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+22196,"Campo Inchauspe / Argentina 6",9001,4221,18036,9807,1,0,4530,8801,-90,9102,8802,-57,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+22197,"Campo Inchauspe / Argentina 7",9001,4221,18037,9807,1,0,4530,8801,-90,9102,8802,-54,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+22234,"Cape / UTM zone 34S",9001,4222,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22235,"Cape / UTM zone 35S",9001,4222,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22236,"Cape / UTM zone 36S",9001,4222,16136,9807,1,1,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22275,"Cape / Lo15",9001,4222,17515,9808,1,0,6503,8801,0,9102,8802,15,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22277,"Cape / Lo17",9001,4222,17517,9808,1,0,6503,8801,0,9102,8802,17,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22279,"Cape / Lo19",9001,4222,17519,9808,1,0,6503,8801,0,9102,8802,19,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22281,"Cape / Lo21",9001,4222,17521,9808,1,0,6503,8801,0,9102,8802,21,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22283,"Cape / Lo23",9001,4222,17523,9808,1,0,6503,8801,0,9102,8802,23,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22285,"Cape / Lo25",9001,4222,17525,9808,1,0,6503,8801,0,9102,8802,25,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22287,"Cape / Lo27",9001,4222,17527,9808,1,0,6503,8801,0,9102,8802,27,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22289,"Cape / Lo29",9001,4222,17529,9808,1,0,6503,8801,0,9102,8802,29,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22291,"Cape / Lo31",9001,4222,17531,9808,1,0,6503,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22293,"Cape / Lo33",9001,4222,17533,9808,1,0,6503,8801,0,9102,8802,33,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22300,"Carthage (Paris) / Tunisia Mining Grid",9036,4816,19937,9816,1,0,4406,8821,36.5964,9105,8822,7.83445,9105,8826,270,9036,8827,360,9036,,,,,,,,,,,,,,,,
+22332,"Carthage / UTM zone 32N",9001,4223,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+22391,"Carthage / Nord Tunisie",9001,4223,18181,9801,1,0,4499,8801,40,9105,8802,11,9105,8805,0.999625544,9201,8806,500000,9001,8807,300000,9001,,,,,,,,,,,,,
+22392,"Carthage / Sud Tunisie",9001,4223,18182,9801,1,0,4499,8801,37,9105,8802,11,9105,8805,0.999625769,9201,8806,500000,9001,8807,300000,9001,,,,,,,,,,,,,
+22521,"Corrego Alegre 1970-72 / UTM zone 21S",9001,4225,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22522,"Corrego Alegre 1970-72 / UTM zone 22S",9001,4225,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22523,"Corrego Alegre 1970-72 / UTM zone 23S",9001,4225,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22524,"Corrego Alegre 1970-72 / UTM zone 24S",9001,4225,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22525,"Corrego Alegre 1970-72 / UTM zone 25S",9001,4225,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+22700,"Deir ez Zor / Levant Zone",9001,4227,19940,9817,1,0,4499,8801,34.39,9110,8802,37.21,9110,8805,0.9996256,9201,8806,300000,9001,8807,300000,9001,,,,,,,,,,,,,
+22770,"Deir ez Zor / Syria Lambert",9001,4227,19948,9801,1,0,4499,8801,34.39,9110,8802,37.21,9110,8805,0.9996256,9201,8806,300000,9001,8807,300000,9001,,,,,,,,,,,,,
+22780,"Deir ez Zor / Levant Stereographic",9001,4227,19949,9809,1,0,4499,8801,38,9105,8802,43.5,9105,8805,0.9995341,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+22832,"Douala / UTM zone 32N",9001,4228,16032,9807,1,1,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+22991,"Egypt 1907 / Blue Belt",9001,4229,18071,9807,1,0,4400,8801,30,9102,8802,35,9102,8805,1,9201,8806,300000,9001,8807,1100000,9001,,,,,,,,,,,,,
+22992,"Egypt 1907 / Red Belt",9001,4229,18072,9807,1,0,4400,8801,30,9102,8802,31,9102,8805,1,9201,8806,615000,9001,8807,810000,9001,,,,,,,,,,,,,
+22993,"Egypt 1907 / Purple Belt",9001,4229,18073,9807,1,0,4400,8801,30,9102,8802,27,9102,8805,1,9201,8806,700000,9001,8807,200000,9001,,,,,,,,,,,,,
+22994,"Egypt 1907 / Extended Purple Belt",9001,4229,18074,9807,1,0,4400,8801,30,9102,8802,27,9102,8805,1,9201,8806,700000,9001,8807,1200000,9001,,,,,,,,,,,,,
+23028,"ED50 / UTM zone 28N",9001,4230,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23029,"ED50 / UTM zone 29N",9001,4230,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23030,"ED50 / UTM zone 30N",9001,4230,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23031,"ED50 / UTM zone 31N",9001,4230,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23032,"ED50 / UTM zone 32N",9001,4230,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23033,"ED50 / UTM zone 33N",9001,4230,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23034,"ED50 / UTM zone 34N",9001,4230,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23035,"ED50 / UTM zone 35N",9001,4230,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23036,"ED50 / UTM zone 36N",9001,4230,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23037,"ED50 / UTM zone 37N",9001,4230,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23038,"ED50 / UTM zone 38N",9001,4230,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23090,"ED50 / TM 0 N",9001,4230,16400,9807,1,0,4400,8801,0,9102,8802,0,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23095,"ED50 / TM 5 NE",9001,4230,16405,9807,1,0,4400,8801,0,9102,8802,5,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23239,"Fahud / UTM zone 39N",9001,4232,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23240,"Fahud / UTM zone 40N",9001,4232,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23433,"Garoua / UTM zone 33N",9001,4234,16033,9807,1,1,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23700,"HD72 / EOV",9001,4237,19931,9815,1,0,4498,8811,47.08398174,9110,8812,19.02548584,9110,8813,90,9110,8814,90,9110,8815,0.99993,9201,8816,650000,9001,8817,200000,9001,,,,,,,
+23830,"DGN95 / Indonesia TM-3 zone 46.2",9001,4755,17432,9807,1,0,4499,8801,0,9102,8802,94.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23831,"DGN95 / Indonesia TM-3 zone 47.1",9001,4755,17433,9807,1,0,4499,8801,0,9102,8802,97.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23832,"DGN95 / Indonesia TM-3 zone 47.2",9001,4755,17434,9807,1,0,4499,8801,0,9102,8802,100.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23833,"DGN95 / Indonesia TM-3 zone 48.1",9001,4755,17435,9807,1,0,4499,8801,0,9102,8802,103.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23834,"DGN95 / Indonesia TM-3 zone 48.2",9001,4755,17436,9807,1,0,4499,8801,0,9102,8802,106.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23835,"DGN95 / Indonesia TM-3 zone 49.1",9001,4755,17437,9807,1,0,4499,8801,0,9102,8802,109.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23836,"DGN95 / Indonesia TM-3 zone 49.2",9001,4755,17438,9807,1,0,4499,8801,0,9102,8802,112.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23837,"DGN95 / Indonesia TM-3 zone 50.1",9001,4755,17439,9807,1,0,4499,8801,0,9102,8802,115.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23838,"DGN95 / Indonesia TM-3 zone 50.2",9001,4755,17440,9807,1,0,4499,8801,0,9102,8802,118.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23839,"DGN95 / Indonesia TM-3 zone 51.1",9001,4755,17441,9807,1,0,4499,8801,0,9102,8802,121.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23840,"DGN95 / Indonesia TM-3 zone 51.2",9001,4755,17442,9807,1,0,4499,8801,0,9102,8802,124.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23841,"DGN95 / Indonesia TM-3 zone 52.1",9001,4755,17443,9807,1,0,4499,8801,0,9102,8802,127.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23842,"DGN95 / Indonesia TM-3 zone 52.2",9001,4755,17444,9807,1,0,4499,8801,0,9102,8802,130.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23843,"DGN95 / Indonesia TM-3 zone 53.1",9001,4755,17445,9807,1,0,4499,8801,0,9102,8802,133.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23844,"DGN95 / Indonesia TM-3 zone 53.2",9001,4755,17446,9807,1,0,4499,8801,0,9102,8802,136.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23845,"DGN95 / Indonesia TM-3 zone 54.1",9001,4755,17447,9807,1,0,4499,8801,0,9102,8802,139.5,9102,8805,0.9999,9201,8806,200000,9001,8807,1500000,9001,,,,,,,,,,,,,
+23846,"ID74 / UTM zone 46N",9001,4238,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23847,"ID74 / UTM zone 47N",9001,4238,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23848,"ID74 / UTM zone 48N",9001,4238,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23849,"ID74 / UTM zone 49N",9001,4238,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23850,"ID74 / UTM zone 50N",9001,4238,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23851,"ID74 / UTM zone 51N",9001,4238,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23852,"ID74 / UTM zone 52N",9001,4238,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23853,"ID74 / UTM zone 53N",9001,4238,16053,9807,1,1,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23866,"DGN95 / UTM zone 46N",9001,4755,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23867,"DGN95 / UTM zone 47N",9001,4755,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23868,"DGN95 / UTM zone 48N",9001,4755,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23869,"DGN95 / UTM zone 49N",9001,4755,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23870,"DGN95 / UTM zone 50N",9001,4755,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23871,"DGN95 / UTM zone 51N",9001,4755,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23872,"DGN95 / UTM zone 52N",9001,4755,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23877,"DGN95 / UTM zone 47S",9001,4755,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23878,"DGN95 / UTM zone 48S",9001,4755,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23879,"DGN95 / UTM zone 49S",9001,4755,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23880,"DGN95 / UTM zone 50S",9001,4755,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23881,"DGN95 / UTM zone 51S",9001,4755,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23882,"DGN95 / UTM zone 52S",9001,4755,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23883,"DGN95 / UTM zone 53S",9001,4755,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23884,"DGN95 / UTM zone 54S",9001,4755,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23886,"ID74 / UTM zone 46S",9001,4238,16146,9807,1,1,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23887,"ID74 / UTM zone 47S",9001,4238,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23888,"ID74 / UTM zone 48S",9001,4238,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23889,"ID74 / UTM zone 49S",9001,4238,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23890,"ID74 / UTM zone 50S",9001,4238,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23891,"ID74 / UTM zone 51S",9001,4238,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23892,"ID74 / UTM zone 52S",9001,4238,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23893,"ID74 / UTM zone 53S",9001,4238,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23894,"ID74 / UTM zone 54S",9001,4238,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+23946,"Indian 1954 / UTM zone 46N",9001,4239,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23947,"Indian 1954 / UTM zone 47N",9001,4239,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+23948,"Indian 1954 / UTM zone 48N",9001,4239,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24047,"Indian 1975 / UTM zone 47N",9001,4240,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24048,"Indian 1975 / UTM zone 48N",9001,4240,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24100,"Jamaica 1875 / Jamaica (Old Grid)",9005,4241,19909,9801,1,0,4403,8801,18,9102,8802,-77,9102,8805,1,9201,8806,550000,9005,8807,400000,9005,,,,,,,,,,,,,
+24200,"JAD69 / Jamaica National Grid",9001,4242,19910,9801,1,0,4400,8801,18,9102,8802,-77,9102,8805,1,9201,8806,250000,9001,8807,150000,9001,,,,,,,,,,,,,
+24305,"Kalianpur 1937 / UTM zone 45N",9001,4144,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24306,"Kalianpur 1937 / UTM zone 46N",9001,4144,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24311,"Kalianpur 1962 / UTM zone 41N",9001,4145,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24312,"Kalianpur 1962 / UTM zone 42N",9001,4145,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24313,"Kalianpur 1962 / UTM zone 43N",9001,4145,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24342,"Kalianpur 1975 / UTM zone 42N",9001,4146,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24343,"Kalianpur 1975 / UTM zone 43N",9001,4146,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24344,"Kalianpur 1975 / UTM zone 44N",9001,4146,16044,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24345,"Kalianpur 1975 / UTM zone 45N",9001,4146,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24346,"Kalianpur 1975 / UTM zone 46N",9001,4146,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24347,"Kalianpur 1975 / UTM zone 47N",9001,4146,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24370,"Kalianpur 1880 / India zone 0",9084,4243,18110,9801,1,0,4408,8801,39.3,9110,8802,68,9110,8805,0.99846154,9201,8806,2355500,9084,8807,2590000,9084,,,,,,,,,,,,,
+24371,"Kalianpur 1880 / India zone I",9084,4243,18111,9801,1,0,4408,8801,32.3,9110,8802,68,9110,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,,,,,,,,
+24372,"Kalianpur 1880 / India zone IIa",9084,4243,18112,9801,1,0,4408,8801,26,9102,8802,74,9102,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,,,,,,,,
+24373,"Kalianpur 1880 / India zone IIIa",9084,4243,18114,9801,1,0,4408,8801,19,9102,8802,80,9102,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,,,,,,,,
+24374,"Kalianpur 1880 / India zone IVa",9084,4243,18116,9801,1,0,4408,8801,12,9102,8802,80,9102,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,,,,,,,,
+24375,"Kalianpur 1937 / India zone IIb",9001,4144,18238,9801,1,0,4400,8801,26,9102,8802,90,9102,8805,0.99878641,9201,8806,2743185.69,9001,8807,914395.23,9001,,,,,,,,,,,,,
+24376,"Kalianpur 1962 / India zone I",9001,4145,18236,9801,1,0,4400,8801,32.3,9110,8802,68,9110,8805,0.99878641,9201,8806,2743196.4,9001,8807,914398.8,9001,,,,,,,,,,,,,
+24377,"Kalianpur 1962 / India zone IIa",9001,4145,18237,9801,1,0,4400,8801,26,9102,8802,74,9102,8805,0.99878641,9201,8806,2743196.4,9001,8807,914398.8,9001,,,,,,,,,,,,,
+24378,"Kalianpur 1975 / India zone I",9001,4146,18231,9801,1,0,4400,8801,32.3,9110,8802,68,9110,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,,,,,,,,
+24379,"Kalianpur 1975 / India zone IIa",9001,4146,18232,9801,1,0,4400,8801,26,9102,8802,74,9102,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,,,,,,,,
+24380,"Kalianpur 1975 / India zone IIb",9001,4146,18235,9801,1,0,4400,8801,26,9102,8802,90,9102,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,,,,,,,,
+24381,"Kalianpur 1975 / India zone IIIa",9001,4146,18233,9801,1,0,4400,8801,19,9102,8802,80,9102,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,,,,,,,,
+24382,"Kalianpur 1880 / India zone IIb",9084,4243,18113,9801,1,0,4408,8801,26,9102,8802,90,9102,8805,0.99878641,9201,8806,3000000,9084,8807,1000000,9084,,,,,,,,,,,,,
+24383,"Kalianpur 1975 / India zone IVa",9001,4146,18234,9801,1,0,4400,8801,12,9102,8802,80,9102,8805,0.99878641,9201,8806,2743195.5,9001,8807,914398.5,9001,,,,,,,,,,,,,
+24500,"Kertau 1968 / Singapore Grid",9001,4245,19920,9806,1,0,4400,8801,1.1715528,9110,8802,103.5110808,9110,8806,30000,9001,8807,30000,9001,,,,,,,,,,,,,,,,
+24547,"Kertau 1968 / UTM zone 47N",9001,4245,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24548,"Kertau 1968 / UTM zone 48N",9001,4245,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24571,"Kertau / R.S.O. Malaya (ch)",9062,4245,19935,9812,1,1,4401,8806,40000,9062,8807,0,9062,8811,4,9110,8812,102.15,9110,8813,323.01328458,9110,8814,323.07483685,9110,8815,0.99984,9201,,,,,,,
+24600,KOC Lambert,9001,4246,19906,9801,1,0,4400,8801,32.3,9110,8802,45,9110,8805,0.9987864078,9201,8806,1500000,9001,8807,1166200,9001,,,,,,,,,,,,,
+24718,"La Canoa / UTM zone 18N",9001,4247,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24719,"La Canoa / UTM zone 19N",9001,4247,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24720,"La Canoa / UTM zone 20N",9001,4247,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24817,"PSAD56 / UTM zone 17N",9001,4248,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24818,"PSAD56 / UTM zone 18N",9001,4248,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24819,"PSAD56 / UTM zone 19N",9001,4248,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24820,"PSAD56 / UTM zone 20N",9001,4248,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24821,"PSAD56 / UTM zone 21N",9001,4248,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+24877,"PSAD56 / UTM zone 17S",9001,4248,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+24878,"PSAD56 / UTM zone 18S",9001,4248,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+24879,"PSAD56 / UTM zone 19S",9001,4248,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+24880,"PSAD56 / UTM zone 20S",9001,4248,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+24881,"PSAD56 / UTM zone 21S",9001,4248,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+24882,"PSAD56 / UTM zone 22S",9001,4248,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+24891,"PSAD56 / Peru west zone",9001,4248,18161,9807,1,0,4499,8801,-6,9110,8802,-80.3,9110,8805,0.99983008,9201,8806,222000,9001,8807,1426834.743,9001,,,,,,,,,,,,,
+24892,"PSAD56 / Peru central zone",9001,4248,18162,9807,1,0,4499,8801,-9.3,9110,8802,-76,9110,8805,0.99932994,9201,8806,720000,9001,8807,1039979.159,9001,,,,,,,,,,,,,
+24893,"PSAD56 / Peru east zone",9001,4248,18163,9807,1,0,4499,8801,-9.3,9110,8802,-70.3,9110,8805,0.99952992,9201,8806,1324000,9001,8807,1040084.558,9001,,,,,,,,,,,,,
+25000,"Leigon / Ghana Metre Grid",9001,4250,19904,9807,1,0,4400,8801,4.4,9110,8802,-1,9110,8805,0.99975,9201,8806,274319.51,9001,8807,0,9001,,,,,,,,,,,,,
+25231,"Lome / UTM zone 31N",9001,4252,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25391,"Luzon 1911 / Philippines zone I",9001,4253,18171,9807,1,0,4499,8801,0,9102,8802,117,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25392,"Luzon 1911 / Philippines zone II",9001,4253,18172,9807,1,0,4499,8801,0,9102,8802,119,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25393,"Luzon 1911 / Philippines zone III",9001,4253,18173,9807,1,0,4499,8801,0,9102,8802,121,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25394,"Luzon 1911 / Philippines zone IV",9001,4253,18174,9807,1,0,4499,8801,0,9102,8802,123,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25395,"Luzon 1911 / Philippines zone V",9001,4253,18175,9807,1,0,4499,8801,0,9102,8802,125,9102,8805,0.99995,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25700,"Makassar (Jakarta) / NEIEZ",9001,4804,19905,9804,1,1,4499,8801,0,9102,8802,110,9102,8805,0.997,9201,8806,3900000,9001,8807,900000,9001,,,,,,,,,,,,,
+25828,"ETRS89 / UTM zone 28N",9001,4258,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25829,"ETRS89 / UTM zone 29N",9001,4258,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25830,"ETRS89 / UTM zone 30N",9001,4258,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25831,"ETRS89 / UTM zone 31N",9001,4258,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25832,"ETRS89 / UTM zone 32N",9001,4258,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25833,"ETRS89 / UTM zone 33N",9001,4258,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25834,"ETRS89 / UTM zone 34N",9001,4258,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25835,"ETRS89 / UTM zone 35N",9001,4258,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25836,"ETRS89 / UTM zone 36N",9001,4258,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25837,"ETRS89 / UTM zone 37N",9001,4258,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25838,"ETRS89 / UTM zone 38N",9001,4258,16038,9807,1,1,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25884,"ETRS89 / TM Baltic93",9001,4258,19939,9807,1,0,4530,8801,0,9102,8802,24,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+25932,"Malongo 1987 / UTM zone 32S",9001,4259,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+26191,"Merchich / Nord Maroc",9001,4261,18131,9801,1,0,4499,8801,37,9105,8802,-6,9105,8805,0.999625769,9201,8806,500000,9001,8807,300000,9001,,,,,,,,,,,,,
+26192,"Merchich / Sud Maroc",9001,4261,18132,9801,1,0,4499,8801,33,9105,8802,-6,9105,8805,0.999615596,9201,8806,500000,9001,8807,300000,9001,,,,,,,,,,,,,
+26193,"Merchich / Sahara",9001,4261,18133,9801,1,1,4499,8801,29,9105,8802,-6,9105,8805,0.9996,9201,8806,1200000,9001,8807,400000,9001,,,,,,,,,,,,,
+26194,"Merchich / Sahara Nord",9001,4261,18134,9801,1,0,4499,8801,29,9105,8802,-6,9105,8805,0.999616304,9201,8806,1200000,9001,8807,400000,9001,,,,,,,,,,,,,
+26195,"Merchich / Sahara Sud",9001,4261,18135,9801,1,0,4499,8801,25,9105,8802,-6,9105,8805,0.999616437,9201,8806,1500000,9001,8807,400000,9001,,,,,,,,,,,,,
+26237,"Massawa / UTM zone 37N",9001,4262,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26331,"Minna / UTM zone 31N",9001,4263,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26332,"Minna / UTM zone 32N",9001,4263,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26391,"Minna / Nigeria West Belt",9001,4263,18151,9807,1,0,4400,8801,4,9110,8802,4.3,9110,8805,0.99975,9201,8806,230738.26,9001,8807,0,9001,,,,,,,,,,,,,
+26392,"Minna / Nigeria Mid Belt",9001,4263,18152,9807,1,0,4400,8801,4,9110,8802,8.3,9110,8805,0.99975,9201,8806,670553.98,9001,8807,0,9001,,,,,,,,,,,,,
+26393,"Minna / Nigeria East Belt",9001,4263,18153,9807,1,0,4400,8801,4,9110,8802,12.3,9110,8805,0.99975,9201,8806,1110369.7,9001,8807,0,9001,,,,,,,,,,,,,
+26432,"Mhast / UTM zone 32S",9001,4264,16132,9807,1,1,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+26591,"Monte Mario (Rome) / Italy zone 1",9001,4806,18121,9807,1,1,4499,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+26592,"Monte Mario (Rome) / Italy zone 2",9001,4806,18122,9807,1,1,4499,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,2520000,9001,8807,0,9001,,,,,,,,,,,,,
+26632,"M'poraloko / UTM zone 32N",9001,4266,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26692,"M'poraloko / UTM zone 32S",9001,4266,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+26701,"NAD27 / UTM zone 1N",9001,4267,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26702,"NAD27 / UTM zone 2N",9001,4267,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26703,"NAD27 / UTM zone 3N",9001,4267,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26704,"NAD27 / UTM zone 4N",9001,4267,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26705,"NAD27 / UTM zone 5N",9001,4267,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26706,"NAD27 / UTM zone 6N",9001,4267,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26707,"NAD27 / UTM zone 7N",9001,4267,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26708,"NAD27 / UTM zone 8N",9001,4267,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26709,"NAD27 / UTM zone 9N",9001,4267,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26710,"NAD27 / UTM zone 10N",9001,4267,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26711,"NAD27 / UTM zone 11N",9001,4267,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26712,"NAD27 / UTM zone 12N",9001,4267,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26713,"NAD27 / UTM zone 13N",9001,4267,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26714,"NAD27 / UTM zone 14N",9001,4267,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26715,"NAD27 / UTM zone 15N",9001,4267,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26716,"NAD27 / UTM zone 16N",9001,4267,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26717,"NAD27 / UTM zone 17N",9001,4267,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26718,"NAD27 / UTM zone 18N",9001,4267,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26719,"NAD27 / UTM zone 19N",9001,4267,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26720,"NAD27 / UTM zone 20N",9001,4267,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26721,"NAD27 / UTM zone 21N",9001,4267,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26722,"NAD27 / UTM zone 22N",9001,4267,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26729,"NAD27 / Alabama East",9003,4267,10101,9807,1,0,4497,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26730,"NAD27 / Alabama West",9003,4267,10102,9807,1,0,4497,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26731,"NAD27 / Alaska zone 1",9003,4267,15001,9812,1,0,4497,8806,16404166.67,9003,8807,-16404166.67,9003,8811,57,9110,8812,-133.4,9110,8813,323.07483685,9110,8814,323.07483685,9110,8815,0.9999,9201,,,,,,,
+26732,"NAD27 / Alaska zone 2",9003,4267,15002,9807,1,0,4497,8801,54,9102,8802,-142,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26733,"NAD27 / Alaska zone 3",9003,4267,15003,9807,1,0,4497,8801,54,9102,8802,-146,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26734,"NAD27 / Alaska zone 4",9003,4267,15004,9807,1,0,4497,8801,54,9102,8802,-150,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26735,"NAD27 / Alaska zone 5",9003,4267,15005,9807,1,0,4497,8801,54,9102,8802,-154,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26736,"NAD27 / Alaska zone 6",9003,4267,15006,9807,1,0,4497,8801,54,9102,8802,-158,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26737,"NAD27 / Alaska zone 7",9003,4267,15007,9807,1,0,4497,8801,54,9102,8802,-162,9102,8805,0.9999,9201,8806,700000,9003,8807,0,9003,,,,,,,,,,,,,
+26738,"NAD27 / Alaska zone 8",9003,4267,15008,9807,1,0,4497,8801,54,9102,8802,-166,9102,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26739,"NAD27 / Alaska zone 9",9003,4267,15009,9807,1,0,4497,8801,54,9102,8802,-170,9102,8805,0.9999,9201,8806,600000,9003,8807,0,9003,,,,,,,,,,,,,
+26740,"NAD27 / Alaska zone 10",9003,4267,15010,9802,1,0,4497,8821,51,9110,8822,-176,9110,8823,53.5,9110,8824,51.5,9110,8826,3000000,9003,8827,0,9003,,,,,,,,,,
+26741,"NAD27 / California zone I",9003,4267,10401,9802,1,0,4497,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26742,"NAD27 / California zone II",9003,4267,10402,9802,1,0,4497,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26743,"NAD27 / California zone III",9003,4267,10403,9802,1,0,4497,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26744,"NAD27 / California zone IV",9003,4267,10404,9802,1,0,4497,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26745,"NAD27 / California zone V",9003,4267,10405,9802,1,0,4497,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26746,"NAD27 / California zone VI",9003,4267,10406,9802,1,0,4497,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26747,"NAD27 / California zone VII",9003,4267,10407,9802,1,1,4497,8821,34.08,9110,8822,-118.2,9110,8823,34.25,9110,8824,33.52,9110,8826,4186692.58,9003,8827,416926.74,9003,,,,,,,,,,
+26748,"NAD27 / Arizona East",9003,4267,10201,9807,1,0,4497,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26749,"NAD27 / Arizona Central",9003,4267,10202,9807,1,0,4497,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26750,"NAD27 / Arizona West",9003,4267,10203,9807,1,0,4497,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26751,"NAD27 / Arkansas North",9003,4267,10301,9802,1,0,4497,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26752,"NAD27 / Arkansas South",9003,4267,10302,9802,1,0,4497,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26753,"NAD27 / Colorado North",9003,4267,10501,9802,1,0,4497,8821,39.2,9110,8822,-105.3,9110,8823,39.43,9110,8824,40.47,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26754,"NAD27 / Colorado Central",9003,4267,10502,9802,1,0,4497,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26755,"NAD27 / Colorado South",9003,4267,10503,9802,1,0,4497,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26756,"NAD27 / Connecticut",9003,4267,10600,9802,1,0,4497,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,600000,9003,8827,0,9003,,,,,,,,,,
+26757,"NAD27 / Delaware",9003,4267,10700,9807,1,0,4497,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26758,"NAD27 / Florida East",9003,4267,10901,9807,1,0,4497,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26759,"NAD27 / Florida West",9003,4267,10902,9807,1,0,4497,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26760,"NAD27 / Florida North",9003,4267,10903,9802,1,0,4497,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26766,"NAD27 / Georgia East",9003,4267,11001,9807,1,0,4497,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26767,"NAD27 / Georgia West",9003,4267,11002,9807,1,0,4497,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26768,"NAD27 / Idaho East",9003,4267,11101,9807,1,0,4497,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26769,"NAD27 / Idaho Central",9003,4267,11102,9807,1,0,4497,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26770,"NAD27 / Idaho West",9003,4267,11103,9807,1,0,4497,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26771,"NAD27 / Illinois East",9003,4267,11201,9807,1,0,4497,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26772,"NAD27 / Illinois West",9003,4267,11202,9807,1,0,4497,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26773,"NAD27 / Indiana East",9003,4267,11301,9807,1,0,4497,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26774,"NAD27 / Indiana West",9003,4267,11302,9807,1,0,4497,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26775,"NAD27 / Iowa North",9003,4267,11401,9802,1,0,4497,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26776,"NAD27 / Iowa South",9003,4267,11402,9802,1,0,4497,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26777,"NAD27 / Kansas North",9003,4267,11501,9802,1,0,4497,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26778,"NAD27 / Kansas South",9003,4267,11502,9802,1,0,4497,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26779,"NAD27 / Kentucky North",9003,4267,11601,9802,1,0,4497,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,38.58,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26780,"NAD27 / Kentucky South",9003,4267,11602,9802,1,0,4497,8821,36.2,9110,8822,-85.45,9110,8823,36.44,9110,8824,37.56,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26781,"NAD27 / Louisiana North",9003,4267,11701,9802,1,0,4497,8821,30.4,9110,8822,-92.3,9110,8823,31.1,9110,8824,32.4,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26782,"NAD27 / Louisiana South",9003,4267,11702,9802,1,0,4497,8821,28.4,9110,8822,-91.2,9110,8823,29.18,9110,8824,30.42,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26783,"NAD27 / Maine East",9003,4267,11801,9807,1,0,4497,8801,43.5,9110,8802,-68.3,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26784,"NAD27 / Maine West",9003,4267,11802,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26785,"NAD27 / Maryland",9003,4267,11900,9802,1,0,4497,8821,37.5,9110,8822,-77,9110,8823,38.18,9110,8824,39.27,9110,8826,800000,9003,8827,0,9003,,,,,,,,,,
+26786,"NAD27 / Massachusetts Mainland",9003,4267,12001,9802,1,0,4497,8821,41,9110,8822,-71.3,9110,8823,41.43,9110,8824,42.41,9110,8826,600000,9003,8827,0,9003,,,,,,,,,,
+26787,"NAD27 / Massachusetts Island",9003,4267,12002,9802,1,0,4497,8821,41,9110,8822,-70.3,9110,8823,41.17,9110,8824,41.29,9110,8826,200000,9003,8827,0,9003,,,,,,,,,,
+26791,"NAD27 / Minnesota North",9003,4267,12201,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,47.02,9110,8824,48.38,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26792,"NAD27 / Minnesota Central",9003,4267,12202,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,45.37,9110,8824,47.03,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26793,"NAD27 / Minnesota South",9003,4267,12203,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,43.47,9110,8824,45.13,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26794,"NAD27 / Mississippi East",9003,4267,12301,9807,1,0,4497,8801,29.4,9110,8802,-88.5,9110,8805,0.99996,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26795,"NAD27 / Mississippi West",9003,4267,12302,9807,1,0,4497,8801,30.3,9110,8802,-90.2,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26796,"NAD27 / Missouri East",9003,4267,12401,9807,1,0,4497,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26797,"NAD27 / Missouri Central",9003,4267,12402,9807,1,0,4497,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26798,"NAD27 / Missouri West",9003,4267,12403,9807,1,0,4497,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26799,"NAD27 / California zone VII",9003,4267,10408,9802,1,0,4497,8821,34.08,9110,8822,-118.2,9110,8823,34.25,9110,8824,33.52,9110,8826,4186692.58,9003,8827,4160926.74,9003,,,,,,,,,,
+26801,"NAD Michigan / Michigan East",9003,4268,12101,9807,1,1,4497,8801,41.3,9110,8802,-83.4,9110,8805,0.999942857,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26802,"NAD Michigan / Michigan Old Central",9003,4268,12102,9807,1,1,4497,8801,41.3,9110,8802,-85.45,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26803,"NAD Michigan / Michigan West",9003,4268,12103,9807,1,1,4497,8801,41.3,9110,8802,-88.45,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+26811,"NAD Michigan / Michigan North",9003,4268,12111,9802,1,1,4497,8821,44.47,9110,8822,-87,9110,8823,45.29,9110,8824,47.05,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26812,"NAD Michigan / Michigan Central",9003,4268,12112,9802,1,1,4497,8821,43.19,9110,8822,-84.2,9110,8823,44.11,9110,8824,45.42,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26813,"NAD Michigan / Michigan South",9003,4268,12113,9802,1,1,4497,8821,41.3,9110,8822,-84.2,9110,8823,42.06,9110,8824,43.4,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+26814,"NAD83 / Maine East (ftUS)",9001,4269,11833,9807,1,1,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+26815,"NAD83 / Maine West (ftUS)",9001,4269,11834,9807,1,1,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,,,,,,,,
+26819,"NAD83 / Minnesota North (ftUS)",9001,4269,12234,9802,1,1,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26820,"NAD83 / Minnesota Central (ftUS)",9001,4269,12235,9802,1,1,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26821,"NAD83 / Minnesota South (ftUS)",9001,4269,12236,9802,1,1,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26822,"NAD83 / Nebraska (ftUS)",9001,4269,15396,9802,1,1,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+26823,"NAD83 / West Virginia North (ftUS)",9001,4269,14733,9802,1,1,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9001,8827,0,9001,,,,,,,,,,
+26824,"NAD83 / West Virginia South (ftUS)",9001,4269,14734,9802,1,1,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9001,8827,0,9001,,,,,,,,,,
+26825,"NAD83(HARN) / Maine East (ftUS)",9001,4152,11833,9807,1,1,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+26826,"NAD83(HARN) / Maine West (ftUS)",9001,4152,11834,9807,1,1,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,,,,,,,,
+26830,"NAD83(HARN) / Minnesota North (ftUS)",9001,4152,12234,9802,1,1,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26831,"NAD83(HARN) / Minnesota Central (ftUS)",9001,4152,12235,9802,1,1,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26832,"NAD83(HARN) / Minnesota South (ftUS)",9001,4152,12236,9802,1,1,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26833,"NAD83(HARN) / Nebraska (ftUS)",9001,4152,15396,9802,1,1,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+26834,"NAD83(HARN) / West Virginia North (ftUS)",9001,4152,14733,9802,1,1,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9001,8827,0,9001,,,,,,,,,,
+26835,"NAD83(HARN) / West Virginia South (ftUS)",9001,4152,14734,9802,1,1,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9001,8827,0,9001,,,,,,,,,,
+26836,"NAD83(NSRS2007) / Maine East (ftUS)",9001,4759,11833,9807,1,1,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+26837,"NAD83(NSRS2007) / Maine West (ftUS)",9001,4759,11834,9807,1,1,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,,,,,,,,
+26841,"NAD83(NSRS2007) / Minnesota North (ftUS)",9001,4759,12234,9802,1,1,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26842,"NAD83(NSRS2007) / Minnesota Central (ftUS)",9001,4759,12235,9802,1,1,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26843,"NAD83(NSRS2007) / Minnesota South (ftUS)",9001,4759,12236,9802,1,1,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26844,"NAD83(NSRS2007) / Nebraska (ftUS)",9001,4759,15396,9802,1,1,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+26845,"NAD83(NSRS2007) / West Virginia North (ftUS)",9001,4759,14733,9802,1,1,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9001,8827,0,9001,,,,,,,,,,
+26846,"NAD83(NSRS2007) / West Virginia South (ftUS)",9001,4759,14734,9802,1,1,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9001,8827,0,9001,,,,,,,,,,
+26847,"NAD83 / Maine East (ftUS)",9003,4269,11833,9807,1,0,4497,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+26848,"NAD83 / Maine West (ftUS)",9003,4269,11834,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,,,,,,,,
+26849,"NAD83 / Minnesota North (ftUS)",9003,4269,12234,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26850,"NAD83 / Minnesota Central (ftUS)",9003,4269,12235,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26851,"NAD83 / Minnesota South (ftUS)",9003,4269,12236,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26852,"NAD83 / Nebraska (ftUS)",9003,4269,15396,9802,1,0,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+26853,"NAD83 / West Virginia North (ftUS)",9003,4269,14735,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+26854,"NAD83 / West Virginia South (ftUS)",9003,4269,14736,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+26855,"NAD83(HARN) / Maine East (ftUS)",9003,4152,11833,9807,1,0,4497,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+26856,"NAD83(HARN) / Maine West (ftUS)",9003,4152,11834,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,,,,,,,,
+26857,"NAD83(HARN) / Minnesota North (ftUS)",9003,4152,12234,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26858,"NAD83(HARN) / Minnesota Central (ftUS)",9003,4152,12235,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26859,"NAD83(HARN) / Minnesota South (ftUS)",9003,4152,12236,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26860,"NAD83(HARN) / Nebraska (ftUS)",9003,4152,15396,9802,1,0,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+26861,"NAD83(HARN) / West Virginia North (ftUS)",9003,4152,14735,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+26862,"NAD83(HARN) / West Virginia South (ftUS)",9003,4152,14736,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+26863,"NAD83(NSRS2007) / Maine East (ftUS)",9003,4759,11833,9807,1,0,4497,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,984250,9003,8807,0,9003,,,,,,,,,,,,,
+26864,"NAD83(NSRS2007) / Maine West (ftUS)",9003,4759,11834,9807,1,0,4497,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,2952750,9003,8807,0,9003,,,,,,,,,,,,,
+26865,"NAD83(NSRS2007) / Minnesota North (ftUS)",9003,4759,12234,9802,1,0,4497,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26866,"NAD83(NSRS2007) / Minnesota Central (ftUS)",9003,4759,12235,9802,1,0,4497,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26867,"NAD83(NSRS2007) / Minnesota South (ftUS)",9003,4759,12236,9802,1,0,4497,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,2624666.6667,9003,8827,328083.3333,9003,,,,,,,,,,
+26868,"NAD83(NSRS2007) / Nebraska (ftUS)",9003,4759,15396,9802,1,0,4497,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,1640416.6667,9003,8827,0,9003,,,,,,,,,,
+26869,"NAD83(NSRS2007) / West Virginia North (ftUS)",9003,4759,14735,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+26870,"NAD83(NSRS2007) / West Virginia South (ftUS)",9003,4759,14736,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,1968500,9003,8827,0,9003,,,,,,,,,,
+26891,"NAD83(CSRS) / MTM zone 11",9001,4617,17711,9807,1,0,4400,8801,0,9110,8802,-82.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+26892,"NAD83(CSRS) / MTM zone 12",9001,4617,17712,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+26893,"NAD83(CSRS) / MTM zone 13",9001,4617,17713,9807,1,0,4400,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+26894,"NAD83(CSRS) / MTM zone 14",9001,4617,17714,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+26895,"NAD83(CSRS) / MTM zone 15",9001,4617,17715,9807,1,0,4400,8801,0,9102,8802,-90,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+26896,"NAD83(CSRS) / MTM zone 16",9001,4617,17716,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+26897,"NAD83(CSRS) / MTM zone 17",9001,4617,17717,9807,1,0,4400,8801,0,9102,8802,-96,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+26898,"NAD83(CSRS) / MTM zone 1",9001,4617,17701,9807,1,0,4496,8801,0,9102,8802,-53,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+26899,"NAD83(CSRS) / MTM zone 2",9001,4617,17702,9807,1,0,4496,8801,0,9102,8802,-56,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+26901,"NAD83 / UTM zone 1N",9001,4269,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26902,"NAD83 / UTM zone 2N",9001,4269,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26903,"NAD83 / UTM zone 3N",9001,4269,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26904,"NAD83 / UTM zone 4N",9001,4269,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26905,"NAD83 / UTM zone 5N",9001,4269,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26906,"NAD83 / UTM zone 6N",9001,4269,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26907,"NAD83 / UTM zone 7N",9001,4269,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26908,"NAD83 / UTM zone 8N",9001,4269,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26909,"NAD83 / UTM zone 9N",9001,4269,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26910,"NAD83 / UTM zone 10N",9001,4269,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26911,"NAD83 / UTM zone 11N",9001,4269,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26912,"NAD83 / UTM zone 12N",9001,4269,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26913,"NAD83 / UTM zone 13N",9001,4269,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26914,"NAD83 / UTM zone 14N",9001,4269,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26915,"NAD83 / UTM zone 15N",9001,4269,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26916,"NAD83 / UTM zone 16N",9001,4269,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26917,"NAD83 / UTM zone 17N",9001,4269,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26918,"NAD83 / UTM zone 18N",9001,4269,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26919,"NAD83 / UTM zone 19N",9001,4269,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26920,"NAD83 / UTM zone 20N",9001,4269,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26921,"NAD83 / UTM zone 21N",9001,4269,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26922,"NAD83 / UTM zone 22N",9001,4269,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26923,"NAD83 / UTM zone 23N",9001,4269,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26929,"NAD83 / Alabama East",9001,4269,10131,9807,1,0,4499,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+26930,"NAD83 / Alabama West",9001,4269,10132,9807,1,0,4499,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,600000,9001,8807,0,9001,,,,,,,,,,,,,
+26931,"NAD83 / Alaska zone 1",9001,4269,15031,9812,1,0,4499,8806,5000000,9001,8807,-5000000,9001,8811,57,9110,8812,-133.4,9110,8813,323.07483685,9110,8814,323.07483685,9110,8815,0.9999,9201,,,,,,,
+26932,"NAD83 / Alaska zone 2",9001,4269,15032,9807,1,0,4499,8801,54,9102,8802,-142,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26933,"NAD83 / Alaska zone 3",9001,4269,15033,9807,1,0,4499,8801,54,9102,8802,-146,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26934,"NAD83 / Alaska zone 4",9001,4269,15034,9807,1,0,4499,8801,54,9102,8802,-150,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26935,"NAD83 / Alaska zone 5",9001,4269,15035,9807,1,0,4499,8801,54,9102,8802,-154,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26936,"NAD83 / Alaska zone 6",9001,4269,15036,9807,1,0,4499,8801,54,9102,8802,-158,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26937,"NAD83 / Alaska zone 7",9001,4269,15037,9807,1,0,4499,8801,54,9102,8802,-162,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26938,"NAD83 / Alaska zone 8",9001,4269,15038,9807,1,0,4499,8801,54,9102,8802,-166,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26939,"NAD83 / Alaska zone 9",9001,4269,15039,9807,1,0,4499,8801,54,9102,8802,-170,9102,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26940,"NAD83 / Alaska zone 10",9001,4269,15040,9802,1,0,4499,8821,51,9110,8822,-176,9110,8823,53.5,9110,8824,51.5,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+26941,"NAD83 / California zone 1",9001,4269,10431,9802,1,0,4499,8821,39.2,9110,8822,-122,9110,8823,41.4,9110,8824,40,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+26942,"NAD83 / California zone 2",9001,4269,10432,9802,1,0,4499,8821,37.4,9110,8822,-122,9110,8823,39.5,9110,8824,38.2,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+26943,"NAD83 / California zone 3",9001,4269,10433,9802,1,0,4499,8821,36.3,9110,8822,-120.3,9110,8823,38.26,9110,8824,37.04,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+26944,"NAD83 / California zone 4",9001,4269,10434,9802,1,0,4499,8821,35.2,9110,8822,-119,9110,8823,37.15,9110,8824,36,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+26945,"NAD83 / California zone 5",9001,4269,10435,9802,1,0,4499,8821,33.3,9110,8822,-118,9110,8823,35.28,9110,8824,34.02,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+26946,"NAD83 / California zone 6",9001,4269,10436,9802,1,0,4499,8821,32.1,9110,8822,-116.15,9110,8823,33.53,9110,8824,32.47,9110,8826,2000000,9001,8827,500000,9001,,,,,,,,,,
+26948,"NAD83 / Arizona East",9001,4269,10231,9807,1,0,4499,8801,31,9110,8802,-110.1,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+26949,"NAD83 / Arizona Central",9001,4269,10232,9807,1,0,4499,8801,31,9110,8802,-111.55,9110,8805,0.9999,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+26950,"NAD83 / Arizona West",9001,4269,10233,9807,1,0,4499,8801,31,9110,8802,-113.45,9110,8805,0.999933333,9201,8806,213360,9001,8807,0,9001,,,,,,,,,,,,,
+26951,"NAD83 / Arkansas North",9001,4269,10331,9802,1,0,4499,8821,34.2,9110,8822,-92,9110,8823,36.14,9110,8824,34.56,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+26952,"NAD83 / Arkansas South",9001,4269,10332,9802,1,0,4499,8821,32.4,9110,8822,-92,9110,8823,34.46,9110,8824,33.18,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+26953,"NAD83 / Colorado North",9001,4269,10531,9802,1,0,4499,8821,39.2,9110,8822,-105.3,9110,8823,40.47,9110,8824,39.43,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+26954,"NAD83 / Colorado Central",9001,4269,10532,9802,1,0,4499,8821,37.5,9110,8822,-105.3,9110,8823,39.45,9110,8824,38.27,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+26955,"NAD83 / Colorado South",9001,4269,10533,9802,1,0,4499,8821,36.4,9110,8822,-105.3,9110,8823,38.26,9110,8824,37.14,9110,8826,914401.8289,9001,8827,304800.6096,9001,,,,,,,,,,
+26956,"NAD83 / Connecticut",9001,4269,10630,9802,1,0,4499,8821,40.5,9110,8822,-72.45,9110,8823,41.52,9110,8824,41.12,9110,8826,304800.6096,9001,8827,152400.3048,9001,,,,,,,,,,
+26957,"NAD83 / Delaware",9001,4269,10730,9807,1,0,4499,8801,38,9110,8802,-75.25,9110,8805,0.999995,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+26958,"NAD83 / Florida East",9001,4269,10931,9807,1,0,4499,8801,24.2,9110,8802,-81,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+26959,"NAD83 / Florida West",9001,4269,10932,9807,1,0,4499,8801,24.2,9110,8802,-82,9110,8805,0.999941177,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+26960,"NAD83 / Florida North",9001,4269,10933,9802,1,0,4499,8821,29,9110,8822,-84.3,9110,8823,30.45,9110,8824,29.35,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+26961,"NAD83 / Hawaii zone 1",9001,4269,15131,9807,1,0,4499,8801,18.5,9110,8802,-155.3,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26962,"NAD83 / Hawaii zone 2",9001,4269,15132,9807,1,0,4499,8801,20.2,9110,8802,-156.4,9110,8805,0.999966667,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26963,"NAD83 / Hawaii zone 3",9001,4269,15133,9807,1,0,4499,8801,21.1,9110,8802,-158,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26964,"NAD83 / Hawaii zone 4",9001,4269,15134,9807,1,0,4499,8801,21.5,9110,8802,-159.3,9110,8805,0.99999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26965,"NAD83 / Hawaii zone 5",9001,4269,15135,9807,1,0,4499,8801,21.4,9110,8802,-160.1,9110,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26966,"NAD83 / Georgia East",9001,4269,11031,9807,1,0,4499,8801,30,9110,8802,-82.1,9110,8805,0.9999,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+26967,"NAD83 / Georgia West",9001,4269,11032,9807,1,0,4499,8801,30,9110,8802,-84.1,9110,8805,0.9999,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+26968,"NAD83 / Idaho East",9001,4269,11131,9807,1,0,4499,8801,41.4,9110,8802,-112.1,9110,8805,0.999947368,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+26969,"NAD83 / Idaho Central",9001,4269,11132,9807,1,0,4499,8801,41.4,9110,8802,-114,9110,8805,0.999947368,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26970,"NAD83 / Idaho West",9001,4269,11133,9807,1,0,4499,8801,41.4,9110,8802,-115.45,9110,8805,0.999933333,9201,8806,800000,9001,8807,0,9001,,,,,,,,,,,,,
+26971,"NAD83 / Illinois East",9001,4269,11231,9807,1,0,4499,8801,36.4,9110,8802,-88.2,9110,8805,0.999975,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+26972,"NAD83 / Illinois West",9001,4269,11232,9807,1,0,4499,8801,36.4,9110,8802,-90.1,9110,8805,0.999941177,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+26973,"NAD83 / Indiana East",9001,4269,11331,9807,1,0,4499,8801,37.3,9110,8802,-85.4,9110,8805,0.999966667,9201,8806,100000,9001,8807,250000,9001,,,,,,,,,,,,,
+26974,"NAD83 / Indiana West",9001,4269,11332,9807,1,0,4499,8801,37.3,9110,8802,-87.05,9110,8805,0.999966667,9201,8806,900000,9001,8807,250000,9001,,,,,,,,,,,,,
+26975,"NAD83 / Iowa North",9001,4269,11431,9802,1,0,4499,8821,41.3,9110,8822,-93.3,9110,8823,43.16,9110,8824,42.04,9110,8826,1500000,9001,8827,1000000,9001,,,,,,,,,,
+26976,"NAD83 / Iowa South",9001,4269,11432,9802,1,0,4499,8821,40,9110,8822,-93.3,9110,8823,41.47,9110,8824,40.37,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+26977,"NAD83 / Kansas North",9001,4269,11531,9802,1,0,4499,8821,38.2,9110,8822,-98,9110,8823,39.47,9110,8824,38.43,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+26978,"NAD83 / Kansas South",9001,4269,11532,9802,1,0,4499,8821,36.4,9110,8822,-98.3,9110,8823,38.34,9110,8824,37.16,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+26979,"NAD83 / Kentucky North",9001,4269,11631,9802,1,1,4499,8821,37.3,9110,8822,-84.15,9110,8823,37.58,9110,8824,37.58,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+26980,"NAD83 / Kentucky South",9001,4269,11632,9802,1,0,4499,8821,36.2,9110,8822,-85.45,9110,8823,37.56,9110,8824,36.44,9110,8826,500000,9001,8827,500000,9001,,,,,,,,,,
+26981,"NAD83 / Louisiana North",9001,4269,11731,9802,1,0,4499,8821,30.3,9110,8822,-92.3,9110,8823,32.4,9110,8824,31.1,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+26982,"NAD83 / Louisiana South",9001,4269,11732,9802,1,0,4499,8821,28.3,9110,8822,-91.2,9110,8823,30.42,9110,8824,29.18,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+26983,"NAD83 / Maine East",9001,4269,11831,9807,1,0,4499,8801,43.4,9110,8802,-68.3,9110,8805,0.9999,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+26984,"NAD83 / Maine West",9001,4269,11832,9807,1,0,4499,8801,42.5,9110,8802,-70.1,9110,8805,0.999966667,9201,8806,900000,9001,8807,0,9001,,,,,,,,,,,,,
+26985,"NAD83 / Maryland",9001,4269,11930,9802,1,0,4499,8821,37.4,9110,8822,-77,9110,8823,39.27,9110,8824,38.18,9110,8826,400000,9001,8827,0,9001,,,,,,,,,,
+26986,"NAD83 / Massachusetts Mainland",9001,4269,12031,9802,1,0,4499,8821,41,9110,8822,-71.3,9110,8823,42.41,9110,8824,41.43,9110,8826,200000,9001,8827,750000,9001,,,,,,,,,,
+26987,"NAD83 / Massachusetts Island",9001,4269,12032,9802,1,0,4499,8821,41,9110,8822,-70.3,9110,8823,41.29,9110,8824,41.17,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+26988,"NAD83 / Michigan North",9001,4269,12141,9802,1,0,4499,8821,44.47,9110,8822,-87,9110,8823,47.05,9110,8824,45.29,9110,8826,8000000,9001,8827,0,9001,,,,,,,,,,
+26989,"NAD83 / Michigan Central",9001,4269,12142,9802,1,0,4499,8821,43.19,9110,8822,-84.22,9110,8823,45.42,9110,8824,44.11,9110,8826,6000000,9001,8827,0,9001,,,,,,,,,,
+26990,"NAD83 / Michigan South",9001,4269,12143,9802,1,0,4499,8821,41.3,9110,8822,-84.22,9110,8823,43.4,9110,8824,42.06,9110,8826,4000000,9001,8827,0,9001,,,,,,,,,,
+26991,"NAD83 / Minnesota North",9001,4269,12231,9802,1,0,4499,8821,46.3,9110,8822,-93.06,9110,8823,48.38,9110,8824,47.02,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+26992,"NAD83 / Minnesota Central",9001,4269,12232,9802,1,0,4499,8821,45,9110,8822,-94.15,9110,8823,47.03,9110,8824,45.37,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+26993,"NAD83 / Minnesota South",9001,4269,12233,9802,1,0,4499,8821,43,9110,8822,-94,9110,8823,45.13,9110,8824,43.47,9110,8826,800000,9001,8827,100000,9001,,,,,,,,,,
+26994,"NAD83 / Mississippi East",9001,4269,12331,9807,1,0,4499,8801,29.3,9110,8802,-88.5,9110,8805,0.99995,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+26995,"NAD83 / Mississippi West",9001,4269,12332,9807,1,0,4499,8801,29.3,9110,8802,-90.2,9110,8805,0.99995,9201,8806,700000,9001,8807,0,9001,,,,,,,,,,,,,
+26996,"NAD83 / Missouri East",9001,4269,12431,9807,1,0,4499,8801,35.5,9110,8802,-90.3,9110,8805,0.999933333,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+26997,"NAD83 / Missouri Central",9001,4269,12432,9807,1,0,4499,8801,35.5,9110,8802,-92.3,9110,8805,0.999933333,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+26998,"NAD83 / Missouri West",9001,4269,12433,9807,1,0,4499,8801,36.1,9110,8802,-94.3,9110,8805,0.999941177,9201,8806,850000,9001,8807,0,9001,,,,,,,,,,,,,
+27037,"Nahrwan 1967 / UTM zone 37N",9001,4270,16037,9807,1,1,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+27038,"Nahrwan 1967 / UTM zone 38N",9001,4270,16038,9807,1,1,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+27039,"Nahrwan 1967 / UTM zone 39N",9001,4270,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+27040,"Nahrwan 1967 / UTM zone 40N",9001,4270,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+27120,"Naparima 1972 / UTM zone 20N",9001,4271,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+27200,"NZGD49 / New Zealand Map Grid",9001,4272,19917,9811,1,0,4400,8801,-41,9102,8802,173,9102,8806,2510000,9001,8807,6023150,9001,,,,,,,,,,,,,,,,
+27205,"NZGD49 / Mount Eden Circuit",9001,4272,17901,9807,1,0,4500,8801,-36.5247515,9110,8802,174.45516217,9110,8805,0.9999,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27206,"NZGD49 / Bay of Plenty Circuit",9001,4272,17902,9807,1,0,4500,8801,-37.45404993,9110,8802,176.27583101,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27207,"NZGD49 / Poverty Bay Circuit",9001,4272,17903,9807,1,0,4500,8801,-38.372893,9110,8802,177.53082906,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27208,"NZGD49 / Hawkes Bay Circuit",9001,4272,17904,9807,1,0,4500,8801,-39.39033455,9110,8802,176.40252499,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27209,"NZGD49 / Taranaki Circuit",9001,4272,17905,9807,1,0,4500,8801,-39.08087299,9110,8802,174.13408423,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27210,"NZGD49 / Tuhirangi Circuit",9001,4272,17906,9807,1,0,4500,8801,-39.30448934,9110,8802,175.38241325,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27211,"NZGD49 / Wanganui Circuit",9001,4272,17907,9807,1,0,4500,8801,-40.14310097,9110,8802,175.29171586,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27212,"NZGD49 / Wairarapa Circuit",9001,4272,17908,9807,1,0,4500,8801,-40.55319175,9110,8802,175.38504588,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27213,"NZGD49 / Wellington Circuit",9001,4272,17909,9807,1,0,4500,8801,-41.18047507,9110,8802,174.46358432,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27214,"NZGD49 / Collingwood Circuit",9001,4272,17910,9807,1,0,4500,8801,-40.42531326,9110,8802,172.40193674,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27215,"NZGD49 / Nelson Circuit",9001,4272,17911,9807,1,0,4500,8801,-41.1628361,9110,8802,173.17575405,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27216,"NZGD49 / Karamea Circuit",9001,4272,17912,9807,1,0,4500,8801,-41.17236815,9110,8802,172.06325015,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27217,"NZGD49 / Buller Circuit",9001,4272,17913,9807,1,0,4500,8801,-41.48388903,9110,8802,171.34525362,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27218,"NZGD49 / Grey Circuit",9001,4272,17914,9807,1,0,4500,8801,-42.20012994,9110,8802,171.32591767,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27219,"NZGD49 / Amuri Circuit",9001,4272,17915,9807,1,0,4500,8801,-42.41208197,9110,8802,173.00364802,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27220,"NZGD49 / Marlborough Circuit",9001,4272,17916,9807,1,0,4500,8801,-41.3240152,9110,8802,173.48074668,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27221,"NZGD49 / Hokitika Circuit",9001,4272,17917,9807,1,0,4500,8801,-42.53107605,9110,8802,170.58479766,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27222,"NZGD49 / Okarito Circuit",9001,4272,17918,9807,1,0,4500,8801,-43.06364613,9110,8802,170.1539333,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27223,"NZGD49 / Jacksons Bay Circuit",9001,4272,17919,9807,1,0,4500,8801,-43.58400904,9110,8802,168.36225612,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27224,"NZGD49 / Mount Pleasant Circuit",9001,4272,17920,9807,1,0,4500,8801,-43.35262953,9110,8802,172.43378969,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27225,"NZGD49 / Gawler Circuit",9001,4272,17921,9807,1,0,4500,8801,-43.44553616,9110,8802,171.21386945,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27226,"NZGD49 / Timaru Circuit",9001,4272,17922,9807,1,0,4500,8801,-44.24079933,9110,8802,171.0326103,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27227,"NZGD49 / Lindis Peak Circuit",9001,4272,17923,9807,1,0,4500,8801,-44.44069647,9110,8802,169.28039183,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27228,"NZGD49 / Mount Nicholas Circuit",9001,4272,17924,9807,1,0,4500,8801,-45.07584493,9110,8802,168.23551083,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27229,"NZGD49 / Mount York Circuit",9001,4272,17925,9807,1,0,4500,8801,-45.33494142,9110,8802,167.44199024,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27230,"NZGD49 / Observation Point Circuit",9001,4272,17926,9807,1,0,4500,8801,-45.48583078,9110,8802,170.37429426,9110,8805,1,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27231,"NZGD49 / North Taieri Circuit",9001,4272,17927,9807,1,0,4500,8801,-45.51414481,9110,8802,170.16573208,9110,8805,0.99996,9201,8806,300000,9001,8807,700000,9001,,,,,,,,,,,,,
+27232,"NZGD49 / Bluff Circuit",9001,4272,17928,9807,1,0,4500,8801,-46.36000346,9110,8802,168.20343392,9110,8805,1,9201,8806,300002.66,9001,8807,699999.58,9001,,,,,,,,,,,,,
+27258,"NZGD49 / UTM zone 58S",9001,4272,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+27259,"NZGD49 / UTM zone 59S",9001,4272,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+27260,"NZGD49 / UTM zone 60S",9001,4272,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+27291,"NZGD49 / North Island Grid",9040,4272,18141,9807,1,0,4409,8801,-39,9110,8802,175.3,9110,8805,1,9201,8806,300000,9040,8807,400000,9040,,,,,,,,,,,,,
+27292,"NZGD49 / South Island Grid",9040,4272,18142,9807,1,0,4409,8801,-44,9110,8802,171.3,9110,8805,1,9201,8806,500000,9040,8807,500000,9040,,,,,,,,,,,,,
+27391,"NGO 1948 (Oslo) / NGO zone I",9001,4817,18221,9807,1,0,4531,8801,58,9110,8802,-4.4,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+27392,"NGO 1948 (Oslo) / NGO zone II",9001,4817,18222,9807,1,0,4531,8801,58,9110,8802,-2.2,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+27393,"NGO 1948 (Oslo) / NGO zone III",9001,4817,18223,9807,1,0,4531,8801,58,9110,8802,0,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+27394,"NGO 1948 (Oslo) / NGO zone IV",9001,4817,18224,9807,1,0,4531,8801,58,9110,8802,2.3,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+27395,"NGO 1948 (Oslo) / NGO zone V",9001,4817,18225,9807,1,0,4531,8801,58,9110,8802,6.1,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+27396,"NGO 1948 (Oslo) / NGO zone VI",9001,4817,18226,9807,1,0,4531,8801,58,9110,8802,10.1,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+27397,"NGO 1948 (Oslo) / NGO zone VII",9001,4817,18227,9807,1,0,4531,8801,58,9110,8802,14.1,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+27398,"NGO 1948 (Oslo) / NGO zone VIII",9001,4817,18228,9807,1,0,4531,8801,58,9110,8802,18.2,9110,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+27429,"Datum 73 / UTM zone 29N",9001,4274,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+27492,"Datum 73 / Modified Portuguese Grid",9001,4274,19974,9807,1,1,4530,8801,39.4,9110,8802,-8.0754862,9110,8805,1,9201,8806,180.598,9001,8807,-86.99,9001,,,,,,,,,,,,,
+27493,"Datum 73 / Modified Portuguese Grid",9001,4274,19974,9807,1,0,4499,8801,39.4,9110,8802,-8.0754862,9110,8805,1,9201,8806,180.598,9001,8807,-86.99,9001,,,,,,,,,,,,,
+27500,"ATF (Paris) / Nord de Guerre",9001,4901,19903,9801,1,0,4499,8801,55,9105,8802,6,9105,8805,0.99950908,9201,8806,500000,9001,8807,300000,9001,,,,,,,,,,,,,
+27561,"NTF (Paris) / Lambert Nord France",9001,4807,18091,9801,1,0,4499,8801,55,9105,8802,0,9105,8805,0.999877341,9201,8806,600000,9001,8807,200000,9001,,,,,,,,,,,,,
+27562,"NTF (Paris) / Lambert Centre France",9001,4807,18092,9801,1,0,4499,8801,52,9105,8802,0,9105,8805,0.99987742,9201,8806,600000,9001,8807,200000,9001,,,,,,,,,,,,,
+27563,"NTF (Paris) / Lambert Sud France",9001,4807,18093,9801,1,0,4499,8801,49,9105,8802,0,9105,8805,0.999877499,9201,8806,600000,9001,8807,200000,9001,,,,,,,,,,,,,
+27564,"NTF (Paris) / Lambert Corse",9001,4807,18094,9801,1,0,4499,8801,46.85,9105,8802,0,9105,8805,0.99994471,9201,8806,234.358,9001,8807,185861.369,9001,,,,,,,,,,,,,
+27571,"NTF (Paris) / Lambert zone I",9001,4807,18081,9801,1,0,4499,8801,55,9105,8802,0,9105,8805,0.999877341,9201,8806,600000,9001,8807,1200000,9001,,,,,,,,,,,,,
+27572,"NTF (Paris) / Lambert zone II",9001,4807,18082,9801,1,0,4499,8801,52,9105,8802,0,9105,8805,0.99987742,9201,8806,600000,9001,8807,2200000,9001,,,,,,,,,,,,,
+27573,"NTF (Paris) / Lambert zone III",9001,4807,18083,9801,1,0,4499,8801,49,9105,8802,0,9105,8805,0.999877499,9201,8806,600000,9001,8807,3200000,9001,,,,,,,,,,,,,
+27574,"NTF (Paris) / Lambert zone IV",9001,4807,18084,9801,1,0,4499,8801,46.85,9105,8802,0,9105,8805,0.99994471,9201,8806,234.358,9001,8807,4185861.369,9001,,,,,,,,,,,,,
+27581,"NTF (Paris) / France I",9001,4807,18081,9801,1,1,4499,8801,55,9105,8802,0,9105,8805,0.999877341,9201,8806,600000,9001,8807,1200000,9001,,,,,,,,,,,,,
+27582,"NTF (Paris) / France II",9001,4807,18082,9801,1,1,4499,8801,52,9105,8802,0,9105,8805,0.99987742,9201,8806,600000,9001,8807,2200000,9001,,,,,,,,,,,,,
+27583,"NTF (Paris) / France III",9001,4807,18083,9801,1,1,4499,8801,49,9105,8802,0,9105,8805,0.999877499,9201,8806,600000,9001,8807,3200000,9001,,,,,,,,,,,,,
+27584,"NTF (Paris) / France IV",9001,4807,18084,9801,1,1,4499,8801,46.85,9105,8802,0,9105,8805,0.99994471,9201,8806,234.358,9001,8807,4185861.369,9001,,,,,,,,,,,,,
+27591,"NTF (Paris) / Nord France",9001,4807,18091,9801,1,1,4499,8801,55,9105,8802,0,9105,8805,0.999877341,9201,8806,600000,9001,8807,200000,9001,,,,,,,,,,,,,
+27592,"NTF (Paris) / Centre France",9001,4807,18092,9801,1,1,4499,8801,52,9105,8802,0,9105,8805,0.99987742,9201,8806,600000,9001,8807,200000,9001,,,,,,,,,,,,,
+27593,"NTF (Paris) / Sud France",9001,4807,18093,9801,1,1,4499,8801,49,9105,8802,0,9105,8805,0.999877499,9201,8806,600000,9001,8807,200000,9001,,,,,,,,,,,,,
+27594,"NTF (Paris) / Corse",9001,4807,18094,9801,1,1,4499,8801,46.85,9105,8802,0,9105,8805,0.99994471,9201,8806,234.358,9001,8807,185861.369,9001,,,,,,,,,,,,,
+27700,"OSGB 1936 / British National Grid",9001,4277,19916,9807,1,0,4400,8801,49,9102,8802,-2,9102,8805,0.9996012717,9201,8806,400000,9001,8807,-100000,9001,,,,,,,,,,,,,
+28191,"Palestine 1923 / Palestine Grid",9001,4281,18201,9806,1,0,4400,8801,31.4402749,9110,8802,35.124349,9110,8806,170251.555,9001,8807,126867.909,9001,,,,,,,,,,,,,,,,
+28192,"Palestine 1923 / Palestine Belt",9001,4281,18202,9807,1,0,4400,8801,31.4402749,9110,8802,35.124349,9110,8805,1,9201,8806,170251.555,9001,8807,1126867.909,9001,,,,,,,,,,,,,
+28193,"Palestine 1923 / Israeli CS Grid",9001,4281,18203,9806,1,0,4400,8801,31.4402749,9110,8802,35.124349,9110,8806,170251.555,9001,8807,1126867.909,9001,,,,,,,,,,,,,,,,
+28232,"Pointe Noire / UTM zone 32S",9001,4282,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28348,"GDA94 / MGA zone 48",9001,4283,17348,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28349,"GDA94 / MGA zone 49",9001,4283,17349,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28350,"GDA94 / MGA zone 50",9001,4283,17350,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28351,"GDA94 / MGA zone 51",9001,4283,17351,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28352,"GDA94 / MGA zone 52",9001,4283,17352,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28353,"GDA94 / MGA zone 53",9001,4283,17353,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28354,"GDA94 / MGA zone 54",9001,4283,17354,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28355,"GDA94 / MGA zone 55",9001,4283,17355,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28356,"GDA94 / MGA zone 56",9001,4283,17356,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28357,"GDA94 / MGA zone 57",9001,4283,17357,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28358,"GDA94 / MGA zone 58",9001,4283,17358,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+28402,"Pulkovo 1942 / Gauss-Kruger zone 2",9001,4284,16202,9807,1,1,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+28403,"Pulkovo 1942 / Gauss-Kruger zone 3",9001,4284,16203,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+28404,"Pulkovo 1942 / Gauss-Kruger zone 4",9001,4284,16204,9807,1,0,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+28405,"Pulkovo 1942 / Gauss-Kruger zone 5",9001,4284,16205,9807,1,0,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+28406,"Pulkovo 1942 / Gauss-Kruger zone 6",9001,4284,16206,9807,1,0,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+28407,"Pulkovo 1942 / Gauss-Kruger zone 7",9001,4284,16207,9807,1,0,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+28408,"Pulkovo 1942 / Gauss-Kruger zone 8",9001,4284,16208,9807,1,0,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+28409,"Pulkovo 1942 / Gauss-Kruger zone 9",9001,4284,16209,9807,1,0,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,9500000,9001,8807,0,9001,,,,,,,,,,,,,
+28410,"Pulkovo 1942 / Gauss-Kruger zone 10",9001,4284,16210,9807,1,0,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,10500000,9001,8807,0,9001,,,,,,,,,,,,,
+28411,"Pulkovo 1942 / Gauss-Kruger zone 11",9001,4284,16211,9807,1,0,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,11500000,9001,8807,0,9001,,,,,,,,,,,,,
+28412,"Pulkovo 1942 / Gauss-Kruger zone 12",9001,4284,16212,9807,1,0,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,12500000,9001,8807,0,9001,,,,,,,,,,,,,
+28413,"Pulkovo 1942 / Gauss-Kruger zone 13",9001,4284,16213,9807,1,0,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,13500000,9001,8807,0,9001,,,,,,,,,,,,,
+28414,"Pulkovo 1942 / Gauss-Kruger zone 14",9001,4284,16214,9807,1,0,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,14500000,9001,8807,0,9001,,,,,,,,,,,,,
+28415,"Pulkovo 1942 / Gauss-Kruger zone 15",9001,4284,16215,9807,1,0,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,15500000,9001,8807,0,9001,,,,,,,,,,,,,
+28416,"Pulkovo 1942 / Gauss-Kruger zone 16",9001,4284,16216,9807,1,0,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,16500000,9001,8807,0,9001,,,,,,,,,,,,,
+28417,"Pulkovo 1942 / Gauss-Kruger zone 17",9001,4284,16217,9807,1,0,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,17500000,9001,8807,0,9001,,,,,,,,,,,,,
+28418,"Pulkovo 1942 / Gauss-Kruger zone 18",9001,4284,16218,9807,1,0,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,18500000,9001,8807,0,9001,,,,,,,,,,,,,
+28419,"Pulkovo 1942 / Gauss-Kruger zone 19",9001,4284,16219,9807,1,0,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,19500000,9001,8807,0,9001,,,,,,,,,,,,,
+28420,"Pulkovo 1942 / Gauss-Kruger zone 20",9001,4284,16220,9807,1,0,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,20500000,9001,8807,0,9001,,,,,,,,,,,,,
+28421,"Pulkovo 1942 / Gauss-Kruger zone 21",9001,4284,16221,9807,1,0,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,21500000,9001,8807,0,9001,,,,,,,,,,,,,
+28422,"Pulkovo 1942 / Gauss-Kruger zone 22",9001,4284,16222,9807,1,0,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,22500000,9001,8807,0,9001,,,,,,,,,,,,,
+28423,"Pulkovo 1942 / Gauss-Kruger zone 23",9001,4284,16223,9807,1,0,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,23500000,9001,8807,0,9001,,,,,,,,,,,,,
+28424,"Pulkovo 1942 / Gauss-Kruger zone 24",9001,4284,16224,9807,1,0,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,24500000,9001,8807,0,9001,,,,,,,,,,,,,
+28425,"Pulkovo 1942 / Gauss-Kruger zone 25",9001,4284,16225,9807,1,0,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,25500000,9001,8807,0,9001,,,,,,,,,,,,,
+28426,"Pulkovo 1942 / Gauss-Kruger zone 26",9001,4284,16226,9807,1,0,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,26500000,9001,8807,0,9001,,,,,,,,,,,,,
+28427,"Pulkovo 1942 / Gauss-Kruger zone 27",9001,4284,16227,9807,1,0,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,27500000,9001,8807,0,9001,,,,,,,,,,,,,
+28428,"Pulkovo 1942 / Gauss-Kruger zone 28",9001,4284,16228,9807,1,0,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,28500000,9001,8807,0,9001,,,,,,,,,,,,,
+28429,"Pulkovo 1942 / Gauss-Kruger zone 29",9001,4284,16229,9807,1,0,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,29500000,9001,8807,0,9001,,,,,,,,,,,,,
+28430,"Pulkovo 1942 / Gauss-Kruger zone 30",9001,4284,16230,9807,1,0,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,30500000,9001,8807,0,9001,,,,,,,,,,,,,
+28431,"Pulkovo 1942 / Gauss-Kruger zone 31",9001,4284,16231,9807,1,0,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,31500000,9001,8807,0,9001,,,,,,,,,,,,,
+28432,"Pulkovo 1942 / Gauss-Kruger zone 32",9001,4284,16232,9807,1,0,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,32500000,9001,8807,0,9001,,,,,,,,,,,,,
+28462,"Pulkovo 1942 / Gauss-Kruger 2N",9001,4284,16302,9807,1,1,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28463,"Pulkovo 1942 / Gauss-Kruger 3N",9001,4284,16303,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28464,"Pulkovo 1942 / Gauss-Kruger 4N",9001,4284,16304,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28465,"Pulkovo 1942 / Gauss-Kruger 5N",9001,4284,16305,9807,1,1,4530,8801,0,9102,8802,27,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28466,"Pulkovo 1942 / Gauss-Kruger 6N",9001,4284,16306,9807,1,1,4530,8801,0,9102,8802,33,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28467,"Pulkovo 1942 / Gauss-Kruger 7N",9001,4284,16307,9807,1,1,4530,8801,0,9102,8802,39,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28468,"Pulkovo 1942 / Gauss-Kruger 8N",9001,4284,16308,9807,1,1,4530,8801,0,9102,8802,45,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28469,"Pulkovo 1942 / Gauss-Kruger 9N",9001,4284,16309,9807,1,1,4530,8801,0,9102,8802,51,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28470,"Pulkovo 1942 / Gauss-Kruger 10N",9001,4284,16310,9807,1,1,4530,8801,0,9102,8802,57,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28471,"Pulkovo 1942 / Gauss-Kruger 11N",9001,4284,16311,9807,1,1,4530,8801,0,9102,8802,63,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28472,"Pulkovo 1942 / Gauss-Kruger 12N",9001,4284,16312,9807,1,1,4530,8801,0,9102,8802,69,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28473,"Pulkovo 1942 / Gauss-Kruger 13N",9001,4284,16313,9807,1,1,4530,8801,0,9102,8802,75,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28474,"Pulkovo 1942 / Gauss-Kruger 14N",9001,4284,16314,9807,1,1,4530,8801,0,9102,8802,81,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28475,"Pulkovo 1942 / Gauss-Kruger 15N",9001,4284,16315,9807,1,1,4530,8801,0,9102,8802,87,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28476,"Pulkovo 1942 / Gauss-Kruger 16N",9001,4284,16316,9807,1,1,4530,8801,0,9102,8802,93,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28477,"Pulkovo 1942 / Gauss-Kruger 17N",9001,4284,16317,9807,1,1,4530,8801,0,9102,8802,99,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28478,"Pulkovo 1942 / Gauss-Kruger 18N",9001,4284,16318,9807,1,1,4530,8801,0,9102,8802,105,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28479,"Pulkovo 1942 / Gauss-Kruger 19N",9001,4284,16319,9807,1,1,4530,8801,0,9102,8802,111,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28480,"Pulkovo 1942 / Gauss-Kruger 20N",9001,4284,16320,9807,1,1,4530,8801,0,9102,8802,117,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28481,"Pulkovo 1942 / Gauss-Kruger 21N",9001,4284,16321,9807,1,1,4530,8801,0,9102,8802,123,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28482,"Pulkovo 1942 / Gauss-Kruger 22N",9001,4284,16322,9807,1,1,4530,8801,0,9102,8802,129,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28483,"Pulkovo 1942 / Gauss-Kruger 23N",9001,4284,16323,9807,1,1,4530,8801,0,9102,8802,135,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28484,"Pulkovo 1942 / Gauss-Kruger 24N",9001,4284,16324,9807,1,1,4530,8801,0,9102,8802,141,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28485,"Pulkovo 1942 / Gauss-Kruger 25N",9001,4284,16325,9807,1,1,4530,8801,0,9102,8802,147,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28486,"Pulkovo 1942 / Gauss-Kruger 26N",9001,4284,16326,9807,1,1,4530,8801,0,9102,8802,153,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28487,"Pulkovo 1942 / Gauss-Kruger 27N",9001,4284,16327,9807,1,1,4530,8801,0,9102,8802,159,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28488,"Pulkovo 1942 / Gauss-Kruger 28N",9001,4284,16328,9807,1,1,4530,8801,0,9102,8802,165,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28489,"Pulkovo 1942 / Gauss-Kruger 29N",9001,4284,16329,9807,1,1,4530,8801,0,9102,8802,171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28490,"Pulkovo 1942 / Gauss-Kruger 30N",9001,4284,16330,9807,1,1,4530,8801,0,9102,8802,177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28491,"Pulkovo 1942 / Gauss-Kruger 31N",9001,4284,16331,9807,1,1,4530,8801,0,9102,8802,-177,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28492,"Pulkovo 1942 / Gauss-Kruger 32N",9001,4284,16332,9807,1,1,4530,8801,0,9102,8802,-171,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+28600,"Qatar 1974 / Qatar National Grid",9001,4285,19919,9807,1,0,4400,8801,24.27,9110,8802,51.13,9110,8805,0.99999,9201,8806,200000,9001,8807,300000,9001,,,,,,,,,,,,,
+28991,"Amersfoort / RD Old",9001,4289,19913,9809,1,0,4499,8801,52.0922178,9110,8802,5.23155,9110,8805,0.9999079,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+28992,"Amersfoort / RD New",9001,4289,19914,9809,1,0,4499,8801,52.0922178,9110,8802,5.23155,9110,8805,0.9999079,9201,8806,155000,9001,8807,463000,9001,,,,,,,,,,,,,
+29100,"SAD69 / Brazil Polyconic",9001,4291,19941,9818,1,1,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,,,,,,,,
+29101,"SAD69 / Brazil Polyconic",9001,4618,19941,9818,1,0,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,,,,,,,,
+29118,"SAD69 / UTM zone 18N",9001,4291,16018,9807,1,1,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29119,"SAD69 / UTM zone 19N",9001,4291,16019,9807,1,1,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29120,"SAD69 / UTM zone 20N",9001,4291,16020,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29121,"SAD69 / UTM zone 21N",9001,4291,16021,9807,1,1,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29122,"SAD69 / UTM zone 22N",9001,4291,16022,9807,1,1,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29168,"SAD69 / UTM zone 18N",9001,4618,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29169,"SAD69 / UTM zone 19N",9001,4618,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29170,"SAD69 / UTM zone 20N",9001,4618,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29171,"SAD69 / UTM zone 21N",9001,4618,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29172,"SAD69 / UTM zone 22N",9001,4618,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29177,"SAD69 / UTM zone 17S",9001,4291,16117,9807,1,1,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29178,"SAD69 / UTM zone 18S",9001,4291,16118,9807,1,1,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29179,"SAD69 / UTM zone 19S",9001,4291,16119,9807,1,1,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29180,"SAD69 / UTM zone 20S",9001,4291,16120,9807,1,1,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29181,"SAD69 / UTM zone 21S",9001,4291,16121,9807,1,1,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29182,"SAD69 / UTM zone 22S",9001,4291,16122,9807,1,1,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29183,"SAD69 / UTM zone 23S",9001,4291,16123,9807,1,1,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29184,"SAD69 / UTM zone 24S",9001,4291,16124,9807,1,1,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29185,"SAD69 / UTM zone 25S",9001,4291,16125,9807,1,1,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29187,"SAD69 / UTM zone 17S",9001,4618,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29188,"SAD69 / UTM zone 18S",9001,4618,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29189,"SAD69 / UTM zone 19S",9001,4618,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29190,"SAD69 / UTM zone 20S",9001,4618,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29191,"SAD69 / UTM zone 21S",9001,4618,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29192,"SAD69 / UTM zone 22S",9001,4618,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29193,"SAD69 / UTM zone 23S",9001,4618,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29194,"SAD69 / UTM zone 24S",9001,4618,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29195,"SAD69 / UTM zone 25S",9001,4618,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29220,"Sapper Hill 1943 / UTM zone 20S",9001,4292,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29221,"Sapper Hill 1943 / UTM zone 21S",9001,4292,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29333,"Schwarzeck / UTM zone 33S",9001,4293,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29371,"Schwarzeck / Lo22/11",9031,4293,17611,9808,1,0,6502,8801,-22,9102,8802,11,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,,,,,,,,
+29373,"Schwarzeck / Lo22/13",9031,4293,17613,9808,1,0,6502,8801,-22,9102,8802,13,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,,,,,,,,
+29375,"Schwarzeck / Lo22/15",9031,4293,17615,9808,1,0,6502,8801,-22,9102,8802,15,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,,,,,,,,
+29377,"Schwarzeck / Lo22/17",9031,4293,17617,9808,1,0,6502,8801,-22,9102,8802,17,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,,,,,,,,
+29379,"Schwarzeck / Lo22/19",9031,4293,17619,9808,1,0,6502,8801,-22,9102,8802,19,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,,,,,,,,
+29381,"Schwarzeck / Lo22/21",9031,4293,17621,9808,1,0,6502,8801,-22,9102,8802,21,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,,,,,,,,
+29383,"Schwarzeck / Lo22/23",9031,4293,17623,9808,1,0,6502,8801,-22,9102,8802,23,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,,,,,,,,
+29385,"Schwarzeck / Lo22/25",9031,4293,17625,9808,1,0,6502,8801,-22,9102,8802,25,9102,8805,1,9201,8806,0,9031,8807,0,9031,,,,,,,,,,,,,
+29635,"Sudan / UTM zone 35N",9001,4296,16035,9807,1,1,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29636,"Sudan / UTM zone 36N",9001,4296,16036,9807,1,1,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29700,"Tananarive (Paris) / Laborde Grid",9001,4810,19911,9815,1,1,4499,8811,-21,9105,8812,49,9105,8813,21,9105,8814,21,9105,8815,0.9995,9201,8816,400000,9001,8817,800000,9001,,,,,,,
+29701,"Tananarive (Paris) / Laborde Grid",9001,4810,19861,9813,1,0,4530,8806,400000,9001,8807,800000,9001,8811,-21,9105,8812,49,9105,8813,21,9105,8815,0.9995,9201,,,,,,,,,,
+29702,"Tananarive (Paris) / Laborde Grid approximation",9001,4810,19911,9815,1,0,4530,8811,-21,9105,8812,49,9105,8813,21,9105,8814,21,9105,8815,0.9995,9201,8816,400000,9001,8817,800000,9001,,,,,,,
+29738,"Tananarive / UTM zone 38S",9001,4297,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29739,"Tananarive / UTM zone 39S",9001,4297,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+29849,"Timbalai 1948 / UTM zone 49N",9001,4298,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29850,"Timbalai 1948 / UTM zone 50N",9001,4298,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+29871,"Timbalai 1948 / RSO Borneo (ch)",9042,4298,19956,9815,1,0,4402,8811,4,9110,8812,115,9110,8813,53.18569537,9110,8814,53.07483685,9110,8815,0.99984,9201,8816,29352.4763,9042,8817,22014.3572,9042,,,,,,,
+29872,"Timbalai 1948 / RSO Borneo (ftSe)",9041,4298,19957,9815,1,0,4405,8811,4,9110,8812,115,9110,8813,53.18569537,9110,8814,53.07483685,9110,8815,0.99984,9201,8816,1937263.44,9041,8817,1452947.58,9041,,,,,,,
+29873,"Timbalai 1948 / RSO Borneo (m)",9001,4298,19958,9815,1,0,4400,8811,4,9110,8812,115,9110,8813,53.18569537,9110,8814,53.07483685,9110,8815,0.99984,9201,8816,590476.87,9001,8817,442857.65,9001,,,,,,,
+29900,"TM65 / Irish National Grid",9001,4299,19908,9807,1,1,4400,8801,53.3,9110,8802,-8,9110,8805,1.000035,9201,8806,200000,9001,8807,250000,9001,,,,,,,,,,,,,
+29901,"OSNI 1952 / Irish National Grid",9001,4188,19973,9807,1,0,4400,8801,53.3,9110,8802,-8,9110,8805,1,9201,8806,200000,9001,8807,250000,9001,,,,,,,,,,,,,
+29902,"TM65 / Irish Grid",9001,4299,19972,9807,1,0,4400,8801,53.3,9110,8802,-8,9110,8805,1.000035,9201,8806,200000,9001,8807,250000,9001,,,,,,,,,,,,,
+29903,"TM75 / Irish Grid",9001,4300,19972,9807,1,0,4400,8801,53.3,9110,8802,-8,9110,8805,1.000035,9201,8806,200000,9001,8807,250000,9001,,,,,,,,,,,,,
+30161,"Tokyo / Japan Plane Rectangular CS I",9001,4301,17801,9807,1,0,4530,8801,33,9110,8802,129.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30162,"Tokyo / Japan Plane Rectangular CS II",9001,4301,17802,9807,1,0,4530,8801,33,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30163,"Tokyo / Japan Plane Rectangular CS III",9001,4301,17803,9807,1,0,4530,8801,36,9110,8802,132.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30164,"Tokyo / Japan Plane Rectangular CS IV",9001,4301,17804,9807,1,0,4530,8801,33,9110,8802,133.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30165,"Tokyo / Japan Plane Rectangular CS V",9001,4301,17805,9807,1,0,4530,8801,36,9110,8802,134.2,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30166,"Tokyo / Japan Plane Rectangular CS VI",9001,4301,17806,9807,1,0,4530,8801,36,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30167,"Tokyo / Japan Plane Rectangular CS VII",9001,4301,17807,9807,1,0,4530,8801,36,9110,8802,137.1,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30168,"Tokyo / Japan Plane Rectangular CS VIII",9001,4301,17808,9807,1,0,4530,8801,36,9110,8802,138.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30169,"Tokyo / Japan Plane Rectangular CS IX",9001,4301,17809,9807,1,0,4530,8801,36,9110,8802,139.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30170,"Tokyo / Japan Plane Rectangular CS X",9001,4301,17810,9807,1,0,4530,8801,40,9110,8802,140.5,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30171,"Tokyo / Japan Plane Rectangular CS XI",9001,4301,17811,9807,1,0,4530,8801,44,9110,8802,140.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30172,"Tokyo / Japan Plane Rectangular CS XII",9001,4301,17812,9807,1,0,4530,8801,44,9110,8802,142.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30173,"Tokyo / Japan Plane Rectangular CS XIII",9001,4301,17813,9807,1,0,4530,8801,44,9110,8802,144.15,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30174,"Tokyo / Japan Plane Rectangular CS XIV",9001,4301,17814,9807,1,0,4530,8801,26,9110,8802,142,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30175,"Tokyo / Japan Plane Rectangular CS XV",9001,4301,17815,9807,1,0,4530,8801,26,9110,8802,127.3,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30176,"Tokyo / Japan Plane Rectangular CS XVI",9001,4301,17816,9807,1,0,4530,8801,26,9110,8802,124,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30177,"Tokyo / Japan Plane Rectangular CS XVII",9001,4301,17817,9807,1,0,4530,8801,26,9110,8802,131,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30178,"Tokyo / Japan Plane Rectangular CS XVIII",9001,4301,17818,9807,1,0,4530,8801,20,9110,8802,136,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30179,"Tokyo / Japan Plane Rectangular CS XIX",9001,4301,17819,9807,1,0,4530,8801,26,9110,8802,154,9110,8805,0.9999,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+30200,"Trinidad 1903 / Trinidad Grid",9039,4302,19925,9806,1,0,4407,8801,10.263,9110,8802,-61.2,9110,8806,430000,9039,8807,325000,9039,,,,,,,,,,,,,,,,
+30339,"TC(1948) / UTM zone 39N",9001,4303,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+30340,"TC(1948) / UTM zone 40N",9001,4303,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+30491,"Voirol 1875 / Nord Algerie (ancienne)",9001,4304,18011,9801,1,0,4499,8801,40,9105,8802,3,9105,8805,0.999625544,9201,8806,500000,9001,8807,300000,9001,,,,,,,,,,,,,
+30492,"Voirol 1875 / Sud Algerie (ancienne)",9001,4304,18012,9801,1,0,4499,8801,37,9105,8802,3,9105,8805,0.999625769,9201,8806,500000,9001,8807,300000,9001,,,,,,,,,,,,,
+30493,"Voirol 1879 / Nord Algerie (ancienne)",9001,4671,18011,9801,1,0,4499,8801,40,9105,8802,3,9105,8805,0.999625544,9201,8806,500000,9001,8807,300000,9001,,,,,,,,,,,,,
+30494,"Voirol 1879 / Sud Algerie (ancienne)",9001,4671,18012,9801,1,0,4499,8801,37,9105,8802,3,9105,8805,0.999625769,9201,8806,500000,9001,8807,300000,9001,,,,,,,,,,,,,
+30729,"Nord Sahara 1959 / UTM zone 29N",9001,4307,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+30730,"Nord Sahara 1959 / UTM zone 30N",9001,4307,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+30731,"Nord Sahara 1959 / UTM zone 31N",9001,4307,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+30732,"Nord Sahara 1959 / UTM zone 32N",9001,4307,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+30791,"Nord Sahara 1959 / Nord Algerie",9001,4307,18021,9801,1,0,4499,8801,40,9105,8802,3,9105,8805,0.999625544,9201,8806,500135,9001,8807,300090,9001,,,,,,,,,,,,,
+30792,"Nord Sahara 1959 / Sud Algerie",9001,4307,18022,9801,1,0,4499,8801,37,9105,8802,3,9105,8805,0.999625769,9201,8806,500135,9001,8807,300090,9001,,,,,,,,,,,,,
+30800,RT38 2.5 gon W,9001,4308,19929,9807,1,1,4530,8801,0,9110,8802,15.48298,9110,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+31028,"Yoff / UTM zone 28N",9001,4310,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31121,"Zanderij / UTM zone 21N",9001,4311,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31154,"Zanderij / TM 54 NW",9001,4311,17054,9807,1,0,4400,8801,0,9102,8802,-54,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31170,"Zanderij / Suriname Old TM",9001,4311,19954,9807,1,0,4400,8801,0,9110,8802,-55.41,9110,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31171,"Zanderij / Suriname TM",9001,4311,19955,9807,1,0,4400,8801,0,9110,8802,-55.41,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31251,"MGI (Ferro) / Austria GK West Zone",9001,4805,18001,9807,1,0,4530,8801,0,9102,8802,28,9102,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,,577.326,90.129,463.919,5.137,1.474,5.297,2.4232
+31252,"MGI (Ferro) / Austria GK Central Zone",9001,4805,18002,9807,1,0,4530,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,,577.326,90.129,463.919,5.137,1.474,5.297,2.4232
+31253,"MGI (Ferro) / Austria GK East Zone",9001,4805,18003,9807,1,0,4530,8801,0,9102,8802,34,9102,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,,577.326,90.129,463.919,5.137,1.474,5.297,2.4232
+31254,"MGI / Austria GK West",9001,4312,18004,9807,1,0,4530,8801,0,9110,8802,10.2,9110,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,,,,,,,,
+31255,"MGI / Austria GK Central",9001,4312,18005,9807,1,0,4530,8801,0,9110,8802,13.2,9110,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,,,,,,,,
+31256,"MGI / Austria GK East",9001,4312,18006,9807,1,0,4530,8801,0,9110,8802,16.2,9110,8805,1,9201,8806,0,9001,8807,-5000000,9001,,,,,,,,,,,,,
+31257,"MGI / Austria GK M28",9001,4312,18007,9807,1,0,4530,8801,0,9110,8802,10.2,9110,8805,1,9201,8806,150000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+31258,"MGI / Austria GK M31",9001,4312,18008,9807,1,0,4530,8801,0,9110,8802,13.2,9110,8805,1,9201,8806,450000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+31259,"MGI / Austria GK M34",9001,4312,18009,9807,1,0,4530,8801,0,9110,8802,16.2,9110,8805,1,9201,8806,750000,9001,8807,-5000000,9001,,,,,,,,,,,,,
+31265,"MGI / 3-degree Gauss zone 5",9001,4312,16265,9807,1,1,4499,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+31266,"MGI / 3-degree Gauss zone 6",9001,4312,16266,9807,1,1,4499,8801,0,9102,8802,18,9102,8805,1,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+31267,"MGI / 3-degree Gauss zone 7",9001,4312,16267,9807,1,1,4499,8801,0,9102,8802,21,9102,8805,1,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+31268,"MGI / 3-degree Gauss zone 8",9001,4312,16268,9807,1,1,4499,8801,0,9102,8802,24,9102,8805,1,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+31275,"MGI / Balkans zone 5",9001,4312,18275,9807,1,1,4530,8801,0,9102,8802,15,9102,8805,0.9999,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+31276,"MGI / Balkans zone 6",9001,4312,18276,9807,1,1,4530,8801,0,9102,8802,18,9102,8805,0.9999,9201,8806,6500000,9001,8807,0,9001,,,,,,,,,,,,,
+31277,"MGI / Balkans zone 7",9001,4312,18277,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+31278,"MGI / Balkans zone 8",9001,4312,18277,9807,1,1,4530,8801,0,9102,8802,21,9102,8805,0.9999,9201,8806,7500000,9001,8807,0,9001,,,,,,,,,,,,,
+31279,"MGI / Balkans zone 8",9001,4312,18278,9807,1,1,4530,8801,0,9102,8802,24,9102,8805,0.9999,9201,8806,8500000,9001,8807,0,9001,,,,,,,,,,,,,
+31281,"MGI (Ferro) / Austria West Zone",9001,4805,18041,9807,1,0,4530,8801,0,9102,8802,28,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+31282,"MGI (Ferro) / Austria Central Zone",9001,4805,18042,9807,1,0,4530,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+31283,"MGI (Ferro) / Austria East Zone",9001,4805,18043,9807,1,0,4530,8801,0,9102,8802,34,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+31284,"MGI / Austria M28",9001,4312,18044,9807,1,0,4530,8801,0,9110,8802,10.2,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+31285,"MGI / Austria M31",9001,4312,18045,9807,1,0,4530,8801,0,9110,8802,13.2,9110,8805,1,9201,8806,450000,9001,8807,0,9001,,,,,,,,,,,,,
+31286,"MGI / Austria M34",9001,4312,18046,9807,1,0,4530,8801,0,9110,8802,16.2,9110,8805,1,9201,8806,750000,9001,8807,0,9001,,,,,,,,,,,,,
+31287,"MGI / Austria Lambert",9001,4312,19947,9802,1,0,4530,8821,47.3,9110,8822,13.2,9110,8823,49,9110,8824,46,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+31288,"MGI (Ferro) / M28",9001,4805,18047,9807,1,0,4530,8801,0,9102,8802,28,9102,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+31289,"MGI (Ferro) / M31",9001,4805,18048,9807,1,0,4530,8801,0,9102,8802,31,9102,8805,1,9201,8806,450000,9001,8807,0,9001,,,,,,,,,,,,,
+31290,"MGI (Ferro) / M34",9001,4805,18049,9807,1,0,4530,8801,0,9102,8802,34,9102,8805,1,9201,8806,750000,9001,8807,0,9001,,,,,,,,,,,,,
+31291,"MGI (Ferro) / Austria West Zone",9001,4805,18041,9807,1,1,4499,8801,0,9102,8802,28,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+31292,"MGI (Ferro) / Austria Central Zone",9001,4805,18042,9807,1,1,4499,8801,0,9102,8802,31,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+31293,"MGI (Ferro) / Austria East Zone",9001,4805,18043,9807,1,1,4499,8801,0,9102,8802,34,9102,8805,1,9201,8806,0,9001,8807,0,9001,,,,,,,,,,,,,
+31294,"MGI / M28",9001,4312,18044,9807,1,1,4499,8801,0,9110,8802,10.2,9110,8805,1,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+31295,"MGI / M31",9001,4312,18045,9807,1,1,4499,8801,0,9110,8802,13.2,9110,8805,1,9201,8806,450000,9001,8807,0,9001,,,,,,,,,,,,,
+31296,"MGI / M34",9001,4312,18046,9807,1,1,4499,8801,0,9110,8802,16.2,9110,8805,1,9201,8806,750000,9001,8807,0,9001,,,,,,,,,,,,,
+31297,"MGI / Austria Lambert",9001,4312,19947,9802,1,1,4499,8821,47.3,9110,8822,13.2,9110,8823,49,9110,8824,46,9110,8826,400000,9001,8827,400000,9001,,,,,,,,,,
+31300,"Belge 1972 / Belge Lambert 72",9001,4313,19902,9803,1,0,4499,8821,90,9110,8822,4.2124983,9110,8823,49.5,9110,8824,51.1,9110,8826,150000.01256,9001,8827,5400088.4378,9001,,,,,,,,,,
+31370,"Belge 1972 / Belgian Lambert 72",9001,4313,19961,9802,1,0,4499,8821,90,9110,8822,4.2202952,9110,8823,51.100000204,9110,8824,49.500000204,9110,8826,150000.013,9001,8827,5400088.438,9001,,,,,,,,,,
+31461,"DHDN / 3-degree Gauss zone 1",9001,4314,16261,9807,1,1,4499,8801,0,9102,8802,3,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+31462,"DHDN / 3-degree Gauss zone 2",9001,4314,16262,9807,1,1,4499,8801,0,9102,8802,6,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+31463,"DHDN / 3-degree Gauss zone 3",9001,4314,16263,9807,1,1,4499,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+31464,"DHDN / 3-degree Gauss zone 4",9001,4314,16264,9807,1,1,4499,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+31465,"DHDN / 3-degree Gauss zone 5",9001,4314,16265,9807,1,1,4499,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+31466,"DHDN / 3-degree Gauss-Kruger zone 2",9001,4314,16262,9807,1,0,4530,8801,0,9102,8802,6,9102,8805,1,9201,8806,2500000,9001,8807,0,9001,,,,,,,,,,,,,
+31467,"DHDN / 3-degree Gauss-Kruger zone 3",9001,4314,16263,9807,1,0,4530,8801,0,9102,8802,9,9102,8805,1,9201,8806,3500000,9001,8807,0,9001,,,,,,,,,,,,,
+31468,"DHDN / 3-degree Gauss-Kruger zone 4",9001,4314,16264,9807,1,0,4530,8801,0,9102,8802,12,9102,8805,1,9201,8806,4500000,9001,8807,0,9001,,,,,,,,,,,,,
+31469,"DHDN / 3-degree Gauss-Kruger zone 5",9001,4314,16265,9807,1,0,4530,8801,0,9102,8802,15,9102,8805,1,9201,8806,5500000,9001,8807,0,9001,,,,,,,,,,,,,
+31528,"Conakry 1905 / UTM zone 28N",9001,4315,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31529,"Conakry 1905 / UTM zone 29N",9001,4315,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31600,"Dealul Piscului 1930 / Stereo 33",9001,4316,19927,9809,1,0,4499,8801,45.54,9110,8802,25.23328772,9110,8805,0.9996667,9201,8806,500000,9001,8807,500000,9001,,,,,,,,,,,,,
+31700,"Dealul Piscului 1970/ Stereo 70",9001,4317,19926,9809,1,1,4530,8801,46,9102,8802,25,9102,8805,0.99975,9201,8806,500000,9001,8807,500000,9001,,,,,,,,,,,,,
+31838,"NGN / UTM zone 38N",9001,4318,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31839,"NGN / UTM zone 39N",9001,4318,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31900,"KUDAMS / KTM",9001,4319,19928,9807,1,1,4400,8801,0,9102,8802,48,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31901,"KUDAMS / KTM",9001,4319,19997,9807,1,0,4400,8801,0,9102,8802,48,9102,8805,1,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31965,"SIRGAS 2000 / UTM zone 11N",9001,4674,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31966,"SIRGAS 2000 / UTM zone 12N",9001,4674,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31967,"SIRGAS 2000 / UTM zone 13N",9001,4674,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31968,"SIRGAS 2000 / UTM zone 14N",9001,4674,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31969,"SIRGAS 2000 / UTM zone 15N",9001,4674,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31970,"SIRGAS 2000 / UTM zone 16N",9001,4674,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31971,"SIRGAS 2000 / UTM zone 17N",9001,4674,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31972,"SIRGAS 2000 / UTM zone 18N",9001,4674,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31973,"SIRGAS 2000 / UTM zone 19N",9001,4674,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31974,"SIRGAS 2000 / UTM zone 20N",9001,4674,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31975,"SIRGAS 2000 / UTM zone 21N",9001,4674,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31976,"SIRGAS 2000 / UTM zone 22N",9001,4674,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31977,"SIRGAS 2000 / UTM zone 17S",9001,4674,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31978,"SIRGAS 2000 / UTM zone 18S",9001,4674,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31979,"SIRGAS 2000 / UTM zone 19S",9001,4674,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31980,"SIRGAS 2000 / UTM zone 20S",9001,4674,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31981,"SIRGAS 2000 / UTM zone 21S",9001,4674,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31982,"SIRGAS 2000 / UTM zone 22S",9001,4674,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31983,"SIRGAS 2000 / UTM zone 23S",9001,4674,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31984,"SIRGAS 2000 / UTM zone 24S",9001,4674,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31985,"SIRGAS 2000 / UTM zone 25S",9001,4674,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31986,"SIRGAS 1995 / UTM zone 17N",9001,4170,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31987,"SIRGAS 1995 / UTM zone 18N",9001,4170,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31988,"SIRGAS 1995 / UTM zone 19N",9001,4170,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31989,"SIRGAS 1995 / UTM zone 20N",9001,4170,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31990,"SIRGAS 1995 / UTM zone 21N",9001,4170,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31991,"SIRGAS 1995 / UTM zone 22N",9001,4170,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+31992,"SIRGAS 1995 / UTM zone 17S",9001,4170,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31993,"SIRGAS 1995 / UTM zone 18S",9001,4170,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31994,"SIRGAS 1995 / UTM zone 19S",9001,4170,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31995,"SIRGAS 1995 / UTM zone 20S",9001,4170,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31996,"SIRGAS 1995 / UTM zone 21S",9001,4170,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31997,"SIRGAS 1995 / UTM zone 22S",9001,4170,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31998,"SIRGAS 1995 / UTM zone 23S",9001,4170,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+31999,"SIRGAS 1995 / UTM zone 24S",9001,4170,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32000,"SIRGAS 1995 / UTM zone 25S",9001,4170,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32001,"NAD27 / Montana North",9003,4267,12501,9802,1,0,4497,8821,47,9110,8822,-109.3,9110,8823,48.43,9110,8824,47.51,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32002,"NAD27 / Montana Central",9003,4267,12502,9802,1,0,4497,8821,45.5,9110,8822,-109.3,9110,8823,47.53,9110,8824,46.27,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32003,"NAD27 / Montana South",9003,4267,12503,9802,1,0,4497,8821,44,9110,8822,-109.3,9110,8823,46.24,9110,8824,44.52,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32005,"NAD27 / Nebraska North",9003,4267,12601,9802,1,0,4497,8821,41.2,9110,8822,-100,9110,8823,41.51,9110,8824,42.49,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32006,"NAD27 / Nebraska South",9003,4267,12602,9802,1,0,4497,8821,39.4,9110,8822,-99.3,9110,8823,40.17,9110,8824,41.43,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32007,"NAD27 / Nevada East",9003,4267,12701,9807,1,0,4497,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32008,"NAD27 / Nevada Central",9003,4267,12702,9807,1,0,4497,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32009,"NAD27 / Nevada West",9003,4267,12703,9807,1,0,4497,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32010,"NAD27 / New Hampshire",9003,4267,12800,9807,1,0,4497,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32011,"NAD27 / New Jersey",9003,4267,12900,9807,1,0,4497,8801,38.5,9110,8802,-74.4,9110,8805,0.999975,9201,8806,2000000,9003,8807,0,9003,,,,,,,,,,,,,
+32012,"NAD27 / New Mexico East",9003,4267,13001,9807,1,0,4497,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32013,"NAD27 / New Mexico Central",9003,4267,13002,9807,1,0,4497,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32014,"NAD27 / New Mexico West",9003,4267,13003,9807,1,0,4497,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32015,"NAD27 / New York East",9003,4267,13101,9807,1,0,4497,8801,40,9110,8802,-74.2,9110,8805,0.999966667,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32016,"NAD27 / New York Central",9003,4267,13102,9807,1,0,4497,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32017,"NAD27 / New York West",9003,4267,13103,9807,1,0,4497,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32018,"NAD27 / New York Long Island",9003,4267,13104,9802,1,1,4497,8821,40.3,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,1000000,9003,8827,0,9003,,,,,,,,,,
+32019,"NAD27 / North Carolina",9003,4267,13200,9802,1,0,4497,8821,33.45,9110,8822,-79,9110,8823,34.2,9110,8824,36.1,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32020,"NAD27 / North Dakota North",9003,4267,13301,9802,1,0,4497,8821,47,9110,8822,-100.3,9110,8823,47.26,9110,8824,48.44,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32021,"NAD27 / North Dakota South",9003,4267,13302,9802,1,0,4497,8821,45.4,9110,8822,-100.3,9110,8823,46.11,9110,8824,47.29,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32022,"NAD27 / Ohio North",9003,4267,13401,9802,1,0,4497,8821,39.4,9110,8822,-82.3,9110,8823,40.26,9110,8824,41.42,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32023,"NAD27 / Ohio South",9003,4267,13402,9802,1,0,4497,8821,38,9110,8822,-82.3,9110,8823,38.44,9110,8824,40.02,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32024,"NAD27 / Oklahoma North",9003,4267,13501,9802,1,0,4497,8821,35,9110,8822,-98,9110,8823,35.34,9110,8824,36.46,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32025,"NAD27 / Oklahoma South",9003,4267,13502,9802,1,0,4497,8821,33.2,9110,8822,-98,9110,8823,33.56,9110,8824,35.14,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32026,"NAD27 / Oregon North",9003,4267,13601,9802,1,0,4497,8821,43.4,9110,8822,-120.3,9110,8823,44.2,9110,8824,46,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32027,"NAD27 / Oregon South",9003,4267,13602,9802,1,0,4497,8821,41.4,9110,8822,-120.3,9110,8823,42.2,9110,8824,44,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32028,"NAD27 / Pennsylvania North",9003,4267,13701,9802,1,0,4497,8821,40.1,9110,8822,-77.45,9110,8823,40.53,9110,8824,41.57,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32029,"NAD27 / Pennsylvania South",9003,4267,13702,9802,1,1,4497,8821,39.2,9110,8822,-77.45,9110,8823,39.56,9110,8824,40.48,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32030,"NAD27 / Rhode Island",9003,4267,13800,9807,1,0,4497,8801,41.05,9110,8802,-71.3,9110,8805,0.9999938,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32031,"NAD27 / South Carolina North",9003,4267,13901,9802,1,0,4497,8821,33,9110,8822,-81,9110,8823,33.46,9110,8824,34.58,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32033,"NAD27 / South Carolina South",9003,4267,13902,9802,1,0,4497,8821,31.5,9110,8822,-81,9110,8823,32.2,9110,8824,33.4,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32034,"NAD27 / South Dakota North",9003,4267,14001,9802,1,0,4497,8821,43.5,9110,8822,-100,9110,8823,44.25,9110,8824,45.41,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32035,"NAD27 / South Dakota South",9003,4267,14002,9802,1,0,4497,8821,42.2,9110,8822,-100.2,9110,8823,42.5,9110,8824,44.24,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32036,"NAD27 / Tennessee",9003,4267,14100,9802,1,1,4497,8821,34.4,9110,8822,-86,9110,8823,35.15,9110,8824,36.25,9110,8826,100000,9003,8827,0,9003,,,,,,,,,,
+32037,"NAD27 / Texas North",9003,4267,14201,9802,1,0,4497,8821,34,9110,8822,-101.3,9110,8823,34.39,9110,8824,36.11,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32038,"NAD27 / Texas North Central",9003,4267,14202,9802,1,0,4497,8821,31.4,9110,8822,-97.3,9110,8823,32.08,9110,8824,33.58,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32039,"NAD27 / Texas Central",9003,4267,14203,9802,1,0,4497,8821,29.4,9110,8822,-100.2,9110,8823,30.07,9110,8824,31.53,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32040,"NAD27 / Texas South Central",9003,4267,14204,9802,1,0,4497,8821,27.5,9110,8822,-99,9110,8823,28.23,9110,8824,30.17,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32041,"NAD27 / Texas South",9003,4267,14205,9802,1,0,4497,8821,25.4,9110,8822,-98.3,9110,8823,26.1,9110,8824,27.5,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32042,"NAD27 / Utah North",9003,4267,14301,9802,1,0,4497,8821,40.2,9110,8822,-111.3,9110,8823,40.43,9110,8824,41.47,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32043,"NAD27 / Utah Central",9003,4267,14302,9802,1,0,4497,8821,38.2,9110,8822,-111.3,9110,8823,39.01,9110,8824,40.39,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32044,"NAD27 / Utah South",9003,4267,14303,9802,1,0,4497,8821,36.4,9110,8822,-111.3,9110,8823,37.13,9110,8824,38.21,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32045,"NAD27 / Vermont",9003,4267,14400,9807,1,0,4497,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32046,"NAD27 / Virginia North",9003,4267,14501,9802,1,0,4497,8821,37.4,9110,8822,-78.3,9110,8823,38.02,9110,8824,39.12,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32047,"NAD27 / Virginia South",9003,4267,14502,9802,1,0,4497,8821,36.2,9110,8822,-78.3,9110,8823,36.46,9110,8824,37.58,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32048,"NAD27 / Washington North",9003,4267,14601,9802,1,0,4497,8821,47,9110,8822,-120.5,9110,8823,47.3,9110,8824,48.44,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32049,"NAD27 / Washington South",9003,4267,14602,9802,1,0,4497,8821,45.2,9110,8822,-120.3,9110,8823,45.5,9110,8824,47.2,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32050,"NAD27 / West Virginia North",9003,4267,14701,9802,1,0,4497,8821,38.3,9110,8822,-79.3,9110,8823,39,9110,8824,40.15,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32051,"NAD27 / West Virginia South",9003,4267,14702,9802,1,0,4497,8821,37,9110,8822,-81,9110,8823,37.29,9110,8824,38.53,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32052,"NAD27 / Wisconsin North",9003,4267,14801,9802,1,0,4497,8821,45.1,9110,8822,-90,9110,8823,45.34,9110,8824,46.46,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32053,"NAD27 / Wisconsin Central",9003,4267,14802,9802,1,0,4497,8821,43.5,9110,8822,-90,9110,8823,44.15,9110,8824,45.3,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32054,"NAD27 / Wisconsin South",9003,4267,14803,9802,1,0,4497,8821,42,9110,8822,-90,9110,8823,42.44,9110,8824,44.04,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32055,"NAD27 / Wyoming East",9003,4267,14901,9807,1,0,4497,8801,40.4,9110,8802,-105.1,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32056,"NAD27 / Wyoming East Central",9003,4267,14902,9807,1,0,4497,8801,40.4,9110,8802,-107.2,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32057,"NAD27 / Wyoming West Central",9003,4267,14903,9807,1,0,4497,8801,40.4,9110,8802,-108.45,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32058,"NAD27 / Wyoming West",9003,4267,14904,9807,1,0,4497,8801,40.4,9110,8802,-110.05,9110,8805,0.999941177,9201,8806,500000,9003,8807,0,9003,,,,,,,,,,,,,
+32061,"NAD27 / Guatemala Norte",9001,4267,18211,9801,1,1,4499,8801,16.49,9110,8802,-90.2,9110,8805,0.99992226,9201,8806,500000,9001,8807,292209.579,9001,,,,,,,,,,,,,
+32062,"NAD27 / Guatemala Sur",9001,4267,18212,9801,1,1,4499,8801,14.54,9110,8802,-90.2,9110,8805,0.99989906,9201,8806,500000,9001,8807,325992.681,9001,,,,,,,,,,,,,
+32064,"NAD27 / BLM 14N (ftUS)",9003,4267,15914,9807,1,0,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32065,"NAD27 / BLM 15N (ftUS)",9003,4267,15915,9807,1,0,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32066,"NAD27 / BLM 16N (ftUS)",9003,4267,15916,9807,1,0,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32067,"NAD27 / BLM 17N (ftUS)",9003,4267,15917,9807,1,0,4497,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32074,"NAD27 / BLM 14N (feet)",9003,4267,15914,9807,1,1,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32075,"NAD27 / BLM 15N (feet)",9003,4267,15915,9807,1,1,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32076,"NAD27 / BLM 16N (feet)",9003,4267,15916,9807,1,1,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32077,"NAD27 / BLM 17N (feet)",9003,4267,15917,9807,1,1,4497,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32081,"NAD27 / MTM zone 1",9001,4267,17701,9807,1,0,4400,8801,0,9102,8802,-53,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32082,"NAD27 / MTM zone 2",9001,4267,17702,9807,1,0,4400,8801,0,9102,8802,-56,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32083,"NAD27 / MTM zone 3",9001,4267,17703,9807,1,0,4400,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32084,"NAD27 / MTM zone 4",9001,4267,17704,9807,1,0,4400,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32085,"NAD27 / MTM zone 5",9001,4267,17705,9807,1,0,4400,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32086,"NAD27 / MTM zone 6",9001,4267,17706,9807,1,0,4400,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32098,"NAD27 / Quebec Lambert",9001,4267,19944,9802,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+32099,"NAD27 / Louisiana Offshore",9003,4267,11703,9802,1,0,4497,8821,25.4,9110,8822,-91.2,9110,8823,27.5,9110,8824,26.1,9110,8826,2000000,9003,8827,0,9003,,,,,,,,,,
+32100,"NAD83 / Montana",9001,4269,12530,9802,1,0,4499,8821,44.15,9110,8822,-109.3,9110,8823,49,9110,8824,45,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32104,"NAD83 / Nebraska",9001,4269,12630,9802,1,0,4499,8821,39.5,9110,8822,-100,9110,8823,43,9110,8824,40,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+32107,"NAD83 / Nevada East",9001,4269,12731,9807,1,0,4499,8801,34.45,9110,8802,-115.35,9110,8805,0.9999,9201,8806,200000,9001,8807,8000000,9001,,,,,,,,,,,,,
+32108,"NAD83 / Nevada Central",9001,4269,12732,9807,1,0,4499,8801,34.45,9110,8802,-116.4,9110,8805,0.9999,9201,8806,500000,9001,8807,6000000,9001,,,,,,,,,,,,,
+32109,"NAD83 / Nevada West",9001,4269,12733,9807,1,0,4499,8801,34.45,9110,8802,-118.35,9110,8805,0.9999,9201,8806,800000,9001,8807,4000000,9001,,,,,,,,,,,,,
+32110,"NAD83 / New Hampshire",9001,4269,12830,9807,1,0,4499,8801,42.3,9110,8802,-71.4,9110,8805,0.999966667,9201,8806,300000,9001,8807,0,9001,,,,,,,,,,,,,
+32111,"NAD83 / New Jersey",9001,4269,12930,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+32112,"NAD83 / New Mexico East",9001,4269,13031,9807,1,0,4499,8801,31,9110,8802,-104.2,9110,8805,0.999909091,9201,8806,165000,9001,8807,0,9001,,,,,,,,,,,,,
+32113,"NAD83 / New Mexico Central",9001,4269,13032,9807,1,0,4499,8801,31,9110,8802,-106.15,9110,8805,0.9999,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32114,"NAD83 / New Mexico West",9001,4269,13033,9807,1,0,4499,8801,31,9110,8802,-107.5,9110,8805,0.999916667,9201,8806,830000,9001,8807,0,9001,,,,,,,,,,,,,
+32115,"NAD83 / New York East",9001,4269,13131,9807,1,0,4499,8801,38.5,9110,8802,-74.3,9110,8805,0.9999,9201,8806,150000,9001,8807,0,9001,,,,,,,,,,,,,
+32116,"NAD83 / New York Central",9001,4269,13132,9807,1,0,4499,8801,40,9110,8802,-76.35,9110,8805,0.9999375,9201,8806,250000,9001,8807,0,9001,,,,,,,,,,,,,
+32117,"NAD83 / New York West",9001,4269,13133,9807,1,0,4499,8801,40,9110,8802,-78.35,9110,8805,0.9999375,9201,8806,350000,9001,8807,0,9001,,,,,,,,,,,,,
+32118,"NAD83 / New York Long Island",9001,4269,13134,9802,1,0,4499,8821,40.1,9110,8822,-74,9110,8823,41.02,9110,8824,40.4,9110,8826,300000,9001,8827,0,9001,,,,,,,,,,
+32119,"NAD83 / North Carolina",9001,4269,13230,9802,1,0,4499,8821,33.45,9110,8822,-79,9110,8823,36.1,9110,8824,34.2,9110,8826,609601.22,9001,8827,0,9001,,,,,,,,,,
+32120,"NAD83 / North Dakota North",9001,4269,13331,9802,1,0,4499,8821,47,9110,8822,-100.3,9110,8823,48.44,9110,8824,47.26,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32121,"NAD83 / North Dakota South",9001,4269,13332,9802,1,0,4499,8821,45.4,9110,8822,-100.3,9110,8823,47.29,9110,8824,46.11,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32122,"NAD83 / Ohio North",9001,4269,13431,9802,1,0,4499,8821,39.4,9110,8822,-82.3,9110,8823,41.42,9110,8824,40.26,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32123,"NAD83 / Ohio South",9001,4269,13432,9802,1,0,4499,8821,38,9110,8822,-82.3,9110,8823,40.02,9110,8824,38.44,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32124,"NAD83 / Oklahoma North",9001,4269,13531,9802,1,0,4499,8821,35,9110,8822,-98,9110,8823,36.46,9110,8824,35.34,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32125,"NAD83 / Oklahoma South",9001,4269,13532,9802,1,0,4499,8821,33.2,9110,8822,-98,9110,8823,35.14,9110,8824,33.56,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32126,"NAD83 / Oregon North",9001,4269,13631,9802,1,0,4499,8821,43.4,9110,8822,-120.3,9110,8823,46,9110,8824,44.2,9110,8826,2500000,9001,8827,0,9001,,,,,,,,,,
+32127,"NAD83 / Oregon South",9001,4269,13632,9802,1,0,4499,8821,41.4,9110,8822,-120.3,9110,8823,44,9110,8824,42.2,9110,8826,1500000,9001,8827,0,9001,,,,,,,,,,
+32128,"NAD83 / Pennsylvania North",9001,4269,13731,9802,1,0,4499,8821,40.1,9110,8822,-77.45,9110,8823,41.57,9110,8824,40.53,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32129,"NAD83 / Pennsylvania South",9001,4269,13732,9802,1,0,4499,8821,39.2,9110,8822,-77.45,9110,8823,40.58,9110,8824,39.56,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32130,"NAD83 / Rhode Island",9001,4269,13830,9807,1,0,4499,8801,41.05,9110,8802,-71.3,9110,8805,0.99999375,9201,8806,100000,9001,8807,0,9001,,,,,,,,,,,,,
+32133,"NAD83 / South Carolina",9001,4269,13930,9802,1,0,4499,8821,31.5,9110,8822,-81,9110,8823,34.5,9110,8824,32.3,9110,8826,609600,9001,8827,0,9001,,,,,,,,,,
+32134,"NAD83 / South Dakota North",9001,4269,14031,9802,1,0,4499,8821,43.5,9110,8822,-100,9110,8823,45.41,9110,8824,44.25,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32135,"NAD83 / South Dakota South",9001,4269,14032,9802,1,0,4499,8821,42.2,9110,8822,-100.2,9110,8823,44.24,9110,8824,42.5,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32136,"NAD83 / Tennessee",9001,4269,14130,9802,1,0,4499,8821,34.2,9110,8822,-86,9110,8823,36.25,9110,8824,35.15,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32137,"NAD83 / Texas North",9001,4269,14231,9802,1,0,4499,8821,34,9110,8822,-101.3,9110,8823,36.11,9110,8824,34.39,9110,8826,200000,9001,8827,1000000,9001,,,,,,,,,,
+32138,"NAD83 / Texas North Central",9001,4269,14232,9802,1,0,4499,8821,31.4,9110,8822,-98.3,9110,8823,33.58,9110,8824,32.08,9110,8826,600000,9001,8827,2000000,9001,,,,,,,,,,
+32139,"NAD83 / Texas Central",9001,4269,14233,9802,1,0,4499,8821,29.4,9110,8822,-100.2,9110,8823,31.53,9110,8824,30.07,9110,8826,700000,9001,8827,3000000,9001,,,,,,,,,,
+32140,"NAD83 / Texas South Central",9001,4269,14234,9802,1,0,4499,8821,27.5,9110,8822,-99,9110,8823,30.17,9110,8824,28.23,9110,8826,600000,9001,8827,4000000,9001,,,,,,,,,,
+32141,"NAD83 / Texas South",9001,4269,14235,9802,1,0,4499,8821,25.4,9110,8822,-98.3,9110,8823,27.5,9110,8824,26.1,9110,8826,300000,9001,8827,5000000,9001,,,,,,,,,,
+32142,"NAD83 / Utah North",9001,4269,14331,9802,1,0,4499,8821,40.2,9110,8822,-111.3,9110,8823,41.47,9110,8824,40.43,9110,8826,500000,9001,8827,1000000,9001,,,,,,,,,,
+32143,"NAD83 / Utah Central",9001,4269,14332,9802,1,0,4499,8821,38.2,9110,8822,-111.3,9110,8823,40.39,9110,8824,39.01,9110,8826,500000,9001,8827,2000000,9001,,,,,,,,,,
+32144,"NAD83 / Utah South",9001,4269,14333,9802,1,0,4499,8821,36.4,9110,8822,-111.3,9110,8823,38.21,9110,8824,37.13,9110,8826,500000,9001,8827,3000000,9001,,,,,,,,,,
+32145,"NAD83 / Vermont",9001,4269,14430,9807,1,0,4499,8801,42.3,9110,8802,-72.3,9110,8805,0.999964286,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32146,"NAD83 / Virginia North",9001,4269,14531,9802,1,0,4499,8821,37.4,9110,8822,-78.3,9110,8823,39.12,9110,8824,38.02,9110,8826,3500000,9001,8827,2000000,9001,,,,,,,,,,
+32147,"NAD83 / Virginia South",9001,4269,14532,9802,1,0,4499,8821,36.2,9110,8822,-78.3,9110,8823,37.58,9110,8824,36.46,9110,8826,3500000,9001,8827,1000000,9001,,,,,,,,,,
+32148,"NAD83 / Washington North",9001,4269,14631,9802,1,0,4499,8821,47,9110,8822,-120.5,9110,8823,48.44,9110,8824,47.3,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+32149,"NAD83 / Washington South",9001,4269,14632,9802,1,0,4499,8821,45.2,9110,8822,-120.3,9110,8823,47.2,9110,8824,45.5,9110,8826,500000,9001,8827,0,9001,,,,,,,,,,
+32150,"NAD83 / West Virginia North",9001,4269,14731,9802,1,0,4499,8821,38.3,9110,8822,-79.3,9110,8823,40.15,9110,8824,39,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32151,"NAD83 / West Virginia South",9001,4269,14732,9802,1,0,4499,8821,37,9110,8822,-81,9110,8823,38.53,9110,8824,37.29,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32152,"NAD83 / Wisconsin North",9001,4269,14831,9802,1,0,4499,8821,45.1,9110,8822,-90,9110,8823,46.46,9110,8824,45.34,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32153,"NAD83 / Wisconsin Central",9001,4269,14832,9802,1,0,4499,8821,43.5,9110,8822,-90,9110,8823,45.3,9110,8824,44.15,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32154,"NAD83 / Wisconsin South",9001,4269,14833,9802,1,0,4499,8821,42,9110,8822,-90,9110,8823,44.04,9110,8824,42.44,9110,8826,600000,9001,8827,0,9001,,,,,,,,,,
+32155,"NAD83 / Wyoming East",9001,4269,14931,9807,1,0,4499,8801,40.3,9110,8802,-105.1,9110,8805,0.9999375,9201,8806,200000,9001,8807,0,9001,,,,,,,,,,,,,
+32156,"NAD83 / Wyoming East Central",9001,4269,14932,9807,1,0,4499,8801,40.3,9110,8802,-107.2,9110,8805,0.9999375,9201,8806,400000,9001,8807,100000,9001,,,,,,,,,,,,,
+32157,"NAD83 / Wyoming West Central",9001,4269,14933,9807,1,0,4499,8801,40.3,9110,8802,-108.45,9110,8805,0.9999375,9201,8806,600000,9001,8807,0,9001,,,,,,,,,,,,,
+32158,"NAD83 / Wyoming West",9001,4269,14934,9807,1,0,4499,8801,40.3,9110,8802,-110.05,9110,8805,0.9999375,9201,8806,800000,9001,8807,100000,9001,,,,,,,,,,,,,
+32161,"NAD83 / Puerto Rico & Virgin Is.",9001,4269,15230,9802,1,0,4499,8821,17.5,9110,8822,-66.26,9110,8823,18.26,9110,8824,18.02,9110,8826,200000,9001,8827,200000,9001,,,,,,,,,,
+32164,"NAD83 / BLM 14N (ftUS)",9003,4269,15914,9807,1,0,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32165,"NAD83 / BLM 15N (ftUS)",9003,4269,15915,9807,1,0,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32166,"NAD83 / BLM 16N (ftUS)",9003,4269,15916,9807,1,0,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32167,"NAD83 / BLM 17N (ftUS)",9003,4269,15917,9807,1,0,4497,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32180,"NAD83 / SCoPQ zone 2",9001,4269,17700,9807,1,1,4499,8801,0,9110,8802,-55.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32181,"NAD83 / MTM zone 1",9001,4269,17701,9807,1,0,4496,8801,0,9102,8802,-53,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32182,"NAD83 / MTM zone 2",9001,4269,17702,9807,1,0,4496,8801,0,9102,8802,-56,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32183,"NAD83 / MTM zone 3",9001,4269,17703,9807,1,0,4496,8801,0,9110,8802,-58.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32184,"NAD83 / MTM zone 4",9001,4269,17704,9807,1,0,4496,8801,0,9110,8802,-61.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32185,"NAD83 / MTM zone 5",9001,4269,17705,9807,1,0,4496,8801,0,9110,8802,-64.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32186,"NAD83 / MTM zone 6",9001,4269,17706,9807,1,0,4496,8801,0,9110,8802,-67.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32187,"NAD83 / MTM zone 7",9001,4269,17707,9807,1,0,4496,8801,0,9110,8802,-70.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32188,"NAD83 / MTM zone 8",9001,4269,17708,9807,1,0,4496,8801,0,9110,8802,-73.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32189,"NAD83 / MTM zone 9",9001,4269,17709,9807,1,0,4496,8801,0,9110,8802,-76.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32190,"NAD83 / MTM zone 10",9001,4269,17710,9807,1,0,4496,8801,0,9110,8802,-79.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32191,"NAD83 / MTM zone 11",9001,4269,17711,9807,1,0,4400,8801,0,9110,8802,-82.3,9110,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32192,"NAD83 / MTM zone 12",9001,4269,17712,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32193,"NAD83 / MTM zone 13",9001,4269,17713,9807,1,0,4400,8801,0,9102,8802,-84,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32194,"NAD83 / MTM zone 14",9001,4269,17714,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32195,"NAD83 / MTM zone 15",9001,4269,17715,9807,1,0,4400,8801,0,9102,8802,-90,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32196,"NAD83 / MTM zone 16",9001,4269,17716,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32197,"NAD83 / MTM zone 17",9001,4269,17717,9807,1,0,4400,8801,0,9102,8802,-96,9102,8805,0.9999,9201,8806,304800,9001,8807,0,9001,,,,,,,,,,,,,
+32198,"NAD83 / Quebec Lambert",9001,4269,19944,9802,1,0,4499,8821,44,9110,8822,-68.3,9110,8823,60,9110,8824,46,9110,8826,0,9001,8827,0,9001,,,,,,,,,,
+32199,"NAD83 / Louisiana Offshore",9001,4269,11733,9802,1,0,4499,8821,25.3,9110,8822,-91.2,9110,8823,27.5,9110,8824,26.1,9110,8826,1000000,9001,8827,0,9001,,,,,,,,,,
+32201,"WGS 72 / UTM zone 1N",9001,4322,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32202,"WGS 72 / UTM zone 2N",9001,4322,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32203,"WGS 72 / UTM zone 3N",9001,4322,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32204,"WGS 72 / UTM zone 4N",9001,4322,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32205,"WGS 72 / UTM zone 5N",9001,4322,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32206,"WGS 72 / UTM zone 6N",9001,4322,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32207,"WGS 72 / UTM zone 7N",9001,4322,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32208,"WGS 72 / UTM zone 8N",9001,4322,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32209,"WGS 72 / UTM zone 9N",9001,4322,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32210,"WGS 72 / UTM zone 10N",9001,4322,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32211,"WGS 72 / UTM zone 11N",9001,4322,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32212,"WGS 72 / UTM zone 12N",9001,4322,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32213,"WGS 72 / UTM zone 13N",9001,4322,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32214,"WGS 72 / UTM zone 14N",9001,4322,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32215,"WGS 72 / UTM zone 15N",9001,4322,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32216,"WGS 72 / UTM zone 16N",9001,4322,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32217,"WGS 72 / UTM zone 17N",9001,4322,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32218,"WGS 72 / UTM zone 18N",9001,4322,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32219,"WGS 72 / UTM zone 19N",9001,4322,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32220,"WGS 72 / UTM zone 20N",9001,4322,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32221,"WGS 72 / UTM zone 21N",9001,4322,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32222,"WGS 72 / UTM zone 22N",9001,4322,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32223,"WGS 72 / UTM zone 23N",9001,4322,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32224,"WGS 72 / UTM zone 24N",9001,4322,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32225,"WGS 72 / UTM zone 25N",9001,4322,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32226,"WGS 72 / UTM zone 26N",9001,4322,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32227,"WGS 72 / UTM zone 27N",9001,4322,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32228,"WGS 72 / UTM zone 28N",9001,4322,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32229,"WGS 72 / UTM zone 29N",9001,4322,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32230,"WGS 72 / UTM zone 30N",9001,4322,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32231,"WGS 72 / UTM zone 31N",9001,4322,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32232,"WGS 72 / UTM zone 32N",9001,4322,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32233,"WGS 72 / UTM zone 33N",9001,4322,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32234,"WGS 72 / UTM zone 34N",9001,4322,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32235,"WGS 72 / UTM zone 35N",9001,4322,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32236,"WGS 72 / UTM zone 36N",9001,4322,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32237,"WGS 72 / UTM zone 37N",9001,4322,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32238,"WGS 72 / UTM zone 38N",9001,4322,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32239,"WGS 72 / UTM zone 39N",9001,4322,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32240,"WGS 72 / UTM zone 40N",9001,4322,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32241,"WGS 72 / UTM zone 41N",9001,4322,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32242,"WGS 72 / UTM zone 42N",9001,4322,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32243,"WGS 72 / UTM zone 43N",9001,4322,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32244,"WGS 72 / UTM zone 44N",9001,4322,16044,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32245,"WGS 72 / UTM zone 45N",9001,4322,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32246,"WGS 72 / UTM zone 46N",9001,4322,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32247,"WGS 72 / UTM zone 47N",9001,4322,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32248,"WGS 72 / UTM zone 48N",9001,4322,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32249,"WGS 72 / UTM zone 49N",9001,4322,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32250,"WGS 72 / UTM zone 50N",9001,4322,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32251,"WGS 72 / UTM zone 51N",9001,4322,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32252,"WGS 72 / UTM zone 52N",9001,4322,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32253,"WGS 72 / UTM zone 53N",9001,4322,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32254,"WGS 72 / UTM zone 54N",9001,4322,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32255,"WGS 72 / UTM zone 55N",9001,4322,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32256,"WGS 72 / UTM zone 56N",9001,4322,16056,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32257,"WGS 72 / UTM zone 57N",9001,4322,16057,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32258,"WGS 72 / UTM zone 58N",9001,4322,16058,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32259,"WGS 72 / UTM zone 59N",9001,4322,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32260,"WGS 72 / UTM zone 60N",9001,4322,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32301,"WGS 72 / UTM zone 1S",9001,4322,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32302,"WGS 72 / UTM zone 2S",9001,4322,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32303,"WGS 72 / UTM zone 3S",9001,4322,16103,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32304,"WGS 72 / UTM zone 4S",9001,4322,16104,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32305,"WGS 72 / UTM zone 5S",9001,4322,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32306,"WGS 72 / UTM zone 6S",9001,4322,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32307,"WGS 72 / UTM zone 7S",9001,4322,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32308,"WGS 72 / UTM zone 8S",9001,4322,16108,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32309,"WGS 72 / UTM zone 9S",9001,4322,16109,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32310,"WGS 72 / UTM zone 10S",9001,4322,16110,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32311,"WGS 72 / UTM zone 11S",9001,4322,16111,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32312,"WGS 72 / UTM zone 12S",9001,4322,16112,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32313,"WGS 72 / UTM zone 13S",9001,4322,16113,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32314,"WGS 72 / UTM zone 14S",9001,4322,16114,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32315,"WGS 72 / UTM zone 15S",9001,4322,16115,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32316,"WGS 72 / UTM zone 16S",9001,4322,16116,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32317,"WGS 72 / UTM zone 17S",9001,4322,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32318,"WGS 72 / UTM zone 18S",9001,4322,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32319,"WGS 72 / UTM zone 19S",9001,4322,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32320,"WGS 72 / UTM zone 20S",9001,4322,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32321,"WGS 72 / UTM zone 21S",9001,4322,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32322,"WGS 72 / UTM zone 22S",9001,4322,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32323,"WGS 72 / UTM zone 23S",9001,4322,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32324,"WGS 72 / UTM zone 24S",9001,4322,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32325,"WGS 72 / UTM zone 25S",9001,4322,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32326,"WGS 72 / UTM zone 26S",9001,4322,16126,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32327,"WGS 72 / UTM zone 27S",9001,4322,16127,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32328,"WGS 72 / UTM zone 28S",9001,4322,16128,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32329,"WGS 72 / UTM zone 29S",9001,4322,16129,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32330,"WGS 72 / UTM zone 30S",9001,4322,16130,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32331,"WGS 72 / UTM zone 31S",9001,4322,16131,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32332,"WGS 72 / UTM zone 32S",9001,4322,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32333,"WGS 72 / UTM zone 33S",9001,4322,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32334,"WGS 72 / UTM zone 34S",9001,4322,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32335,"WGS 72 / UTM zone 35S",9001,4322,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32336,"WGS 72 / UTM zone 36S",9001,4322,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32337,"WGS 72 / UTM zone 37S",9001,4322,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32338,"WGS 72 / UTM zone 38S",9001,4322,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32339,"WGS 72 / UTM zone 39S",9001,4322,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32340,"WGS 72 / UTM zone 40S",9001,4322,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32341,"WGS 72 / UTM zone 41S",9001,4322,16141,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32342,"WGS 72 / UTM zone 42S",9001,4322,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32343,"WGS 72 / UTM zone 43S",9001,4322,16143,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32344,"WGS 72 / UTM zone 44S",9001,4322,16144,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32345,"WGS 72 / UTM zone 45S",9001,4322,16145,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32346,"WGS 72 / UTM zone 46S",9001,4322,16146,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32347,"WGS 72 / UTM zone 47S",9001,4322,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32348,"WGS 72 / UTM zone 48S",9001,4322,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32349,"WGS 72 / UTM zone 49S",9001,4322,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32350,"WGS 72 / UTM zone 50S",9001,4322,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32351,"WGS 72 / UTM zone 51S",9001,4322,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32352,"WGS 72 / UTM zone 52S",9001,4322,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32353,"WGS 72 / UTM zone 53S",9001,4322,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32354,"WGS 72 / UTM zone 54S",9001,4322,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32355,"WGS 72 / UTM zone 55S",9001,4322,16155,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32356,"WGS 72 / UTM zone 56S",9001,4322,16156,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32357,"WGS 72 / UTM zone 57S",9001,4322,16157,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32358,"WGS 72 / UTM zone 58S",9001,4322,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32359,"WGS 72 / UTM zone 59S",9001,4322,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32360,"WGS 72 / UTM zone 60S",9001,4322,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32401,"WGS 72BE / UTM zone 1N",9001,4324,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32402,"WGS 72BE / UTM zone 2N",9001,4324,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32403,"WGS 72BE / UTM zone 3N",9001,4324,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32404,"WGS 72BE / UTM zone 4N",9001,4324,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32405,"WGS 72BE / UTM zone 5N",9001,4324,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32406,"WGS 72BE / UTM zone 6N",9001,4324,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32407,"WGS 72BE / UTM zone 7N",9001,4324,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32408,"WGS 72BE / UTM zone 8N",9001,4324,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32409,"WGS 72BE / UTM zone 9N",9001,4324,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32410,"WGS 72BE / UTM zone 10N",9001,4324,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32411,"WGS 72BE / UTM zone 11N",9001,4324,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32412,"WGS 72BE / UTM zone 12N",9001,4324,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32413,"WGS 72BE / UTM zone 13N",9001,4324,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32414,"WGS 72BE / UTM zone 14N",9001,4324,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32415,"WGS 72BE / UTM zone 15N",9001,4324,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32416,"WGS 72BE / UTM zone 16N",9001,4324,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32417,"WGS 72BE / UTM zone 17N",9001,4324,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32418,"WGS 72BE / UTM zone 18N",9001,4324,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32419,"WGS 72BE / UTM zone 19N",9001,4324,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32420,"WGS 72BE / UTM zone 20N",9001,4324,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32421,"WGS 72BE / UTM zone 21N",9001,4324,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32422,"WGS 72BE / UTM zone 22N",9001,4324,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32423,"WGS 72BE / UTM zone 23N",9001,4324,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32424,"WGS 72BE / UTM zone 24N",9001,4324,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32425,"WGS 72BE / UTM zone 25N",9001,4324,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32426,"WGS 72BE / UTM zone 26N",9001,4324,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32427,"WGS 72BE / UTM zone 27N",9001,4324,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32428,"WGS 72BE / UTM zone 28N",9001,4324,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32429,"WGS 72BE / UTM zone 29N",9001,4324,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32430,"WGS 72BE / UTM zone 30N",9001,4324,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32431,"WGS 72BE / UTM zone 31N",9001,4324,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32432,"WGS 72BE / UTM zone 32N",9001,4324,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32433,"WGS 72BE / UTM zone 33N",9001,4324,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32434,"WGS 72BE / UTM zone 34N",9001,4324,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32435,"WGS 72BE / UTM zone 35N",9001,4324,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32436,"WGS 72BE / UTM zone 36N",9001,4324,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32437,"WGS 72BE / UTM zone 37N",9001,4324,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32438,"WGS 72BE / UTM zone 38N",9001,4324,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32439,"WGS 72BE / UTM zone 39N",9001,4324,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32440,"WGS 72BE / UTM zone 40N",9001,4324,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32441,"WGS 72BE / UTM zone 41N",9001,4324,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32442,"WGS 72BE / UTM zone 42N",9001,4324,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32443,"WGS 72BE / UTM zone 43N",9001,4324,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32444,"WGS 72BE / UTM zone 44N",9001,4324,16044,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32445,"WGS 72BE / UTM zone 45N",9001,4324,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32446,"WGS 72BE / UTM zone 46N",9001,4324,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32447,"WGS 72BE / UTM zone 47N",9001,4324,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32448,"WGS 72BE / UTM zone 48N",9001,4324,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32449,"WGS 72BE / UTM zone 49N",9001,4324,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32450,"WGS 72BE / UTM zone 50N",9001,4324,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32451,"WGS 72BE / UTM zone 51N",9001,4324,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32452,"WGS 72BE / UTM zone 52N",9001,4324,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32453,"WGS 72BE / UTM zone 53N",9001,4324,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32454,"WGS 72BE / UTM zone 54N",9001,4324,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32455,"WGS 72BE / UTM zone 55N",9001,4324,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32456,"WGS 72BE / UTM zone 56N",9001,4324,16056,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32457,"WGS 72BE / UTM zone 57N",9001,4324,16057,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32458,"WGS 72BE / UTM zone 58N",9001,4324,16058,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32459,"WGS 72BE / UTM zone 59N",9001,4324,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32460,"WGS 72BE / UTM zone 60N",9001,4324,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32501,"WGS 72BE / UTM zone 1S",9001,4324,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32502,"WGS 72BE / UTM zone 2S",9001,4324,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32503,"WGS 72BE / UTM zone 3S",9001,4324,16103,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32504,"WGS 72BE / UTM zone 4S",9001,4324,16104,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32505,"WGS 72BE / UTM zone 5S",9001,4324,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32506,"WGS 72BE / UTM zone 6S",9001,4324,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32507,"WGS 72BE / UTM zone 7S",9001,4324,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32508,"WGS 72BE / UTM zone 8S",9001,4324,16108,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32509,"WGS 72BE / UTM zone 9S",9001,4324,16109,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32510,"WGS 72BE / UTM zone 10S",9001,4324,16110,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32511,"WGS 72BE / UTM zone 11S",9001,4324,16111,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32512,"WGS 72BE / UTM zone 12S",9001,4324,16112,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32513,"WGS 72BE / UTM zone 13S",9001,4324,16113,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32514,"WGS 72BE / UTM zone 14S",9001,4324,16114,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32515,"WGS 72BE / UTM zone 15S",9001,4324,16115,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32516,"WGS 72BE / UTM zone 16S",9001,4324,16116,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32517,"WGS 72BE / UTM zone 17S",9001,4324,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32518,"WGS 72BE / UTM zone 18S",9001,4324,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32519,"WGS 72BE / UTM zone 19S",9001,4324,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32520,"WGS 72BE / UTM zone 20S",9001,4324,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32521,"WGS 72BE / UTM zone 21S",9001,4324,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32522,"WGS 72BE / UTM zone 22S",9001,4324,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32523,"WGS 72BE / UTM zone 23S",9001,4324,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32524,"WGS 72BE / UTM zone 24S",9001,4324,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32525,"WGS 72BE / UTM zone 25S",9001,4324,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32526,"WGS 72BE / UTM zone 26S",9001,4324,16126,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32527,"WGS 72BE / UTM zone 27S",9001,4324,16127,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32528,"WGS 72BE / UTM zone 28S",9001,4324,16128,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32529,"WGS 72BE / UTM zone 29S",9001,4324,16129,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32530,"WGS 72BE / UTM zone 30S",9001,4324,16130,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32531,"WGS 72BE / UTM zone 31S",9001,4324,16131,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32532,"WGS 72BE / UTM zone 32S",9001,4324,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32533,"WGS 72BE / UTM zone 33S",9001,4324,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32534,"WGS 72BE / UTM zone 34S",9001,4324,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32535,"WGS 72BE / UTM zone 35S",9001,4324,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32536,"WGS 72BE / UTM zone 36S",9001,4324,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32537,"WGS 72BE / UTM zone 37S",9001,4324,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32538,"WGS 72BE / UTM zone 38S",9001,4324,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32539,"WGS 72BE / UTM zone 39S",9001,4324,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32540,"WGS 72BE / UTM zone 40S",9001,4324,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32541,"WGS 72BE / UTM zone 41S",9001,4324,16141,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32542,"WGS 72BE / UTM zone 42S",9001,4324,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32543,"WGS 72BE / UTM zone 43S",9001,4324,16143,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32544,"WGS 72BE / UTM zone 44S",9001,4324,16144,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32545,"WGS 72BE / UTM zone 45S",9001,4324,16145,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32546,"WGS 72BE / UTM zone 46S",9001,4324,16146,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32547,"WGS 72BE / UTM zone 47S",9001,4324,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32548,"WGS 72BE / UTM zone 48S",9001,4324,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32549,"WGS 72BE / UTM zone 49S",9001,4324,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32550,"WGS 72BE / UTM zone 50S",9001,4324,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32551,"WGS 72BE / UTM zone 51S",9001,4324,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32552,"WGS 72BE / UTM zone 52S",9001,4324,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32553,"WGS 72BE / UTM zone 53S",9001,4324,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32554,"WGS 72BE / UTM zone 54S",9001,4324,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32555,"WGS 72BE / UTM zone 55S",9001,4324,16155,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32556,"WGS 72BE / UTM zone 56S",9001,4324,16156,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32557,"WGS 72BE / UTM zone 57S",9001,4324,16157,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32558,"WGS 72BE / UTM zone 58S",9001,4324,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32559,"WGS 72BE / UTM zone 59S",9001,4324,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32560,"WGS 72BE / UTM zone 60S",9001,4324,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32600,"WGS 84 / UTM grid system (northern hemisphere)",9001,4326,16000,9824,1,0,4400,8801,0,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,8830,-180,9102,8831,6,9102,,,,,,,,,,
+32601,"WGS 84 / UTM zone 1N",9001,4326,16001,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32602,"WGS 84 / UTM zone 2N",9001,4326,16002,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32603,"WGS 84 / UTM zone 3N",9001,4326,16003,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32604,"WGS 84 / UTM zone 4N",9001,4326,16004,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32605,"WGS 84 / UTM zone 5N",9001,4326,16005,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32606,"WGS 84 / UTM zone 6N",9001,4326,16006,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32607,"WGS 84 / UTM zone 7N",9001,4326,16007,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32608,"WGS 84 / UTM zone 8N",9001,4326,16008,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32609,"WGS 84 / UTM zone 9N",9001,4326,16009,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32610,"WGS 84 / UTM zone 10N",9001,4326,16010,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32611,"WGS 84 / UTM zone 11N",9001,4326,16011,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32612,"WGS 84 / UTM zone 12N",9001,4326,16012,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32613,"WGS 84 / UTM zone 13N",9001,4326,16013,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32614,"WGS 84 / UTM zone 14N",9001,4326,16014,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32615,"WGS 84 / UTM zone 15N",9001,4326,16015,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32616,"WGS 84 / UTM zone 16N",9001,4326,16016,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32617,"WGS 84 / UTM zone 17N",9001,4326,16017,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32618,"WGS 84 / UTM zone 18N",9001,4326,16018,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32619,"WGS 84 / UTM zone 19N",9001,4326,16019,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32620,"WGS 84 / UTM zone 20N",9001,4326,16020,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32621,"WGS 84 / UTM zone 21N",9001,4326,16021,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32622,"WGS 84 / UTM zone 22N",9001,4326,16022,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32623,"WGS 84 / UTM zone 23N",9001,4326,16023,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32624,"WGS 84 / UTM zone 24N",9001,4326,16024,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32625,"WGS 84 / UTM zone 25N",9001,4326,16025,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32626,"WGS 84 / UTM zone 26N",9001,4326,16026,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32627,"WGS 84 / UTM zone 27N",9001,4326,16027,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32628,"WGS 84 / UTM zone 28N",9001,4326,16028,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32629,"WGS 84 / UTM zone 29N",9001,4326,16029,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32630,"WGS 84 / UTM zone 30N",9001,4326,16030,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32631,"WGS 84 / UTM zone 31N",9001,4326,16031,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32632,"WGS 84 / UTM zone 32N",9001,4326,16032,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32633,"WGS 84 / UTM zone 33N",9001,4326,16033,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32634,"WGS 84 / UTM zone 34N",9001,4326,16034,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32635,"WGS 84 / UTM zone 35N",9001,4326,16035,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32636,"WGS 84 / UTM zone 36N",9001,4326,16036,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32637,"WGS 84 / UTM zone 37N",9001,4326,16037,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32638,"WGS 84 / UTM zone 38N",9001,4326,16038,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32639,"WGS 84 / UTM zone 39N",9001,4326,16039,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32640,"WGS 84 / UTM zone 40N",9001,4326,16040,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32641,"WGS 84 / UTM zone 41N",9001,4326,16041,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32642,"WGS 84 / UTM zone 42N",9001,4326,16042,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32643,"WGS 84 / UTM zone 43N",9001,4326,16043,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32644,"WGS 84 / UTM zone 44N",9001,4326,16044,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32645,"WGS 84 / UTM zone 45N",9001,4326,16045,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32646,"WGS 84 / UTM zone 46N",9001,4326,16046,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32647,"WGS 84 / UTM zone 47N",9001,4326,16047,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32648,"WGS 84 / UTM zone 48N",9001,4326,16048,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32649,"WGS 84 / UTM zone 49N",9001,4326,16049,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32650,"WGS 84 / UTM zone 50N",9001,4326,16050,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32651,"WGS 84 / UTM zone 51N",9001,4326,16051,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32652,"WGS 84 / UTM zone 52N",9001,4326,16052,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32653,"WGS 84 / UTM zone 53N",9001,4326,16053,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32654,"WGS 84 / UTM zone 54N",9001,4326,16054,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32655,"WGS 84 / UTM zone 55N",9001,4326,16055,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32656,"WGS 84 / UTM zone 56N",9001,4326,16056,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32657,"WGS 84 / UTM zone 57N",9001,4326,16057,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32658,"WGS 84 / UTM zone 58N",9001,4326,16058,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32659,"WGS 84 / UTM zone 59N",9001,4326,16059,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32660,"WGS 84 / UTM zone 60N",9001,4326,16060,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,,,,,,,,
+32661,"WGS 84 / UPS North (N,E)",9001,4326,16061,9810,1,0,4493,8801,90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+32662,"WGS 84 / Plate Carree",9001,4326,19968,9823,1,1,4499,8801,0,9102,8802,0,9102,8806,0,9001,8807,0,9001,,,,,,,,,,,,,,,,
+32663,"WGS 84 / World Equidistant Cylindrical",9001,4326,19846,9842,1,1,4499,8801,0,9102,8806,0,9001,8807,0,9001,8822,0,9102,,,,,,,,,,,,,,,,
+32664,"WGS 84 / BLM 14N (ftUS)",9003,4326,15914,9807,1,0,4497,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32665,"WGS 84 / BLM 15N (ftUS)",9003,4326,15915,9807,1,0,4497,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32666,"WGS 84 / BLM 16N (ftUS)",9003,4326,15916,9807,1,0,4497,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32667,"WGS 84 / BLM 17N (ftUS)",9003,4326,15917,9807,1,0,4497,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,1640416.67,9003,8807,0,9003,,,,,,,,,,,,,
+32700,"WGS 84 / UTM grid system (southern hemisphere)",9001,4326,16100,9824,1,0,4400,8801,0,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,8830,-180,9102,8831,6,9102,,,,,,,,,,
+32701,"WGS 84 / UTM zone 1S",9001,4326,16101,9807,1,0,4400,8801,0,9102,8802,-177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32702,"WGS 84 / UTM zone 2S",9001,4326,16102,9807,1,0,4400,8801,0,9102,8802,-171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32703,"WGS 84 / UTM zone 3S",9001,4326,16103,9807,1,0,4400,8801,0,9102,8802,-165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32704,"WGS 84 / UTM zone 4S",9001,4326,16104,9807,1,0,4400,8801,0,9102,8802,-159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32705,"WGS 84 / UTM zone 5S",9001,4326,16105,9807,1,0,4400,8801,0,9102,8802,-153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32706,"WGS 84 / UTM zone 6S",9001,4326,16106,9807,1,0,4400,8801,0,9102,8802,-147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32707,"WGS 84 / UTM zone 7S",9001,4326,16107,9807,1,0,4400,8801,0,9102,8802,-141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32708,"WGS 84 / UTM zone 8S",9001,4326,16108,9807,1,0,4400,8801,0,9102,8802,-135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32709,"WGS 84 / UTM zone 9S",9001,4326,16109,9807,1,0,4400,8801,0,9102,8802,-129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32710,"WGS 84 / UTM zone 10S",9001,4326,16110,9807,1,0,4400,8801,0,9102,8802,-123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32711,"WGS 84 / UTM zone 11S",9001,4326,16111,9807,1,0,4400,8801,0,9102,8802,-117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32712,"WGS 84 / UTM zone 12S",9001,4326,16112,9807,1,0,4400,8801,0,9102,8802,-111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32713,"WGS 84 / UTM zone 13S",9001,4326,16113,9807,1,0,4400,8801,0,9102,8802,-105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32714,"WGS 84 / UTM zone 14S",9001,4326,16114,9807,1,0,4400,8801,0,9102,8802,-99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32715,"WGS 84 / UTM zone 15S",9001,4326,16115,9807,1,0,4400,8801,0,9102,8802,-93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32716,"WGS 84 / UTM zone 16S",9001,4326,16116,9807,1,0,4400,8801,0,9102,8802,-87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32717,"WGS 84 / UTM zone 17S",9001,4326,16117,9807,1,0,4400,8801,0,9102,8802,-81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32718,"WGS 84 / UTM zone 18S",9001,4326,16118,9807,1,0,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32719,"WGS 84 / UTM zone 19S",9001,4326,16119,9807,1,0,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32720,"WGS 84 / UTM zone 20S",9001,4326,16120,9807,1,0,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32721,"WGS 84 / UTM zone 21S",9001,4326,16121,9807,1,0,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32722,"WGS 84 / UTM zone 22S",9001,4326,16122,9807,1,0,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32723,"WGS 84 / UTM zone 23S",9001,4326,16123,9807,1,0,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32724,"WGS 84 / UTM zone 24S",9001,4326,16124,9807,1,0,4400,8801,0,9102,8802,-39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32725,"WGS 84 / UTM zone 25S",9001,4326,16125,9807,1,0,4400,8801,0,9102,8802,-33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32726,"WGS 84 / UTM zone 26S",9001,4326,16126,9807,1,0,4400,8801,0,9102,8802,-27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32727,"WGS 84 / UTM zone 27S",9001,4326,16127,9807,1,0,4400,8801,0,9102,8802,-21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32728,"WGS 84 / UTM zone 28S",9001,4326,16128,9807,1,0,4400,8801,0,9102,8802,-15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32729,"WGS 84 / UTM zone 29S",9001,4326,16129,9807,1,0,4400,8801,0,9102,8802,-9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32730,"WGS 84 / UTM zone 30S",9001,4326,16130,9807,1,0,4400,8801,0,9102,8802,-3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32731,"WGS 84 / UTM zone 31S",9001,4326,16131,9807,1,0,4400,8801,0,9102,8802,3,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32732,"WGS 84 / UTM zone 32S",9001,4326,16132,9807,1,0,4400,8801,0,9102,8802,9,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32733,"WGS 84 / UTM zone 33S",9001,4326,16133,9807,1,0,4400,8801,0,9102,8802,15,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32734,"WGS 84 / UTM zone 34S",9001,4326,16134,9807,1,0,4400,8801,0,9102,8802,21,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32735,"WGS 84 / UTM zone 35S",9001,4326,16135,9807,1,0,4400,8801,0,9102,8802,27,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32736,"WGS 84 / UTM zone 36S",9001,4326,16136,9807,1,0,4400,8801,0,9102,8802,33,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32737,"WGS 84 / UTM zone 37S",9001,4326,16137,9807,1,0,4400,8801,0,9102,8802,39,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32738,"WGS 84 / UTM zone 38S",9001,4326,16138,9807,1,0,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32739,"WGS 84 / UTM zone 39S",9001,4326,16139,9807,1,0,4400,8801,0,9102,8802,51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32740,"WGS 84 / UTM zone 40S",9001,4326,16140,9807,1,0,4400,8801,0,9102,8802,57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32741,"WGS 84 / UTM zone 41S",9001,4326,16141,9807,1,0,4400,8801,0,9102,8802,63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32742,"WGS 84 / UTM zone 42S",9001,4326,16142,9807,1,0,4400,8801,0,9102,8802,69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32743,"WGS 84 / UTM zone 43S",9001,4326,16143,9807,1,0,4400,8801,0,9102,8802,75,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32744,"WGS 84 / UTM zone 44S",9001,4326,16144,9807,1,0,4400,8801,0,9102,8802,81,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32745,"WGS 84 / UTM zone 45S",9001,4326,16145,9807,1,0,4400,8801,0,9102,8802,87,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32746,"WGS 84 / UTM zone 46S",9001,4326,16146,9807,1,0,4400,8801,0,9102,8802,93,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32747,"WGS 84 / UTM zone 47S",9001,4326,16147,9807,1,0,4400,8801,0,9102,8802,99,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32748,"WGS 84 / UTM zone 48S",9001,4326,16148,9807,1,0,4400,8801,0,9102,8802,105,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32749,"WGS 84 / UTM zone 49S",9001,4326,16149,9807,1,0,4400,8801,0,9102,8802,111,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32750,"WGS 84 / UTM zone 50S",9001,4326,16150,9807,1,0,4400,8801,0,9102,8802,117,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32751,"WGS 84 / UTM zone 51S",9001,4326,16151,9807,1,0,4400,8801,0,9102,8802,123,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32752,"WGS 84 / UTM zone 52S",9001,4326,16152,9807,1,0,4400,8801,0,9102,8802,129,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32753,"WGS 84 / UTM zone 53S",9001,4326,16153,9807,1,0,4400,8801,0,9102,8802,135,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32754,"WGS 84 / UTM zone 54S",9001,4326,16154,9807,1,0,4400,8801,0,9102,8802,141,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32755,"WGS 84 / UTM zone 55S",9001,4326,16155,9807,1,0,4400,8801,0,9102,8802,147,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32756,"WGS 84 / UTM zone 56S",9001,4326,16156,9807,1,0,4400,8801,0,9102,8802,153,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32757,"WGS 84 / UTM zone 57S",9001,4326,16157,9807,1,0,4400,8801,0,9102,8802,159,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32758,"WGS 84 / UTM zone 58S",9001,4326,16158,9807,1,0,4400,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32759,"WGS 84 / UTM zone 59S",9001,4326,16159,9807,1,0,4400,8801,0,9102,8802,171,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32760,"WGS 84 / UTM zone 60S",9001,4326,16160,9807,1,0,4400,8801,0,9102,8802,177,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
+32761,"WGS 84 / UPS South (N,E)",9001,4326,16161,9810,1,0,4494,8801,-90,9102,8802,0,9102,8805,0.994,9201,8806,2000000,9001,8807,2000000,9001,,,,,,,,,,,,,
+32766,"WGS 84 / TM 36 SE",9001,4326,16636,9807,1,0,4400,8801,0,9102,8802,36,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,,,,,,,,
diff --git a/data/pcs.override.csv b/data/pcs.override.csv
index 5e694fd..b8cd3cb 100644
--- a/data/pcs.override.csv
+++ b/data/pcs.override.csv
@@ -1,4 +1,4 @@
-"COORD_REF_SYS_CODE","COORD_REF_SYS_NAME","UOM_CODE","SOURCE_GEOGCRS_CODE","COORD_OP_CODE","COORD_OP_METHOD_CODE","SHOW_CRS","DEPRECATED","COORD_SYS_CODE","PARAMETER_CODE_1","PARAMETER_VALUE_1","PARAMETER_UOM_1","PARAMETER_CODE_2","PARAMETER_VALUE_2","PARAMETER_UOM_2","PARAMETER_CODE_3","PARAMETER_VALUE_3","PARAMETER_UOM_3","PARAMETER_CODE_4","PARAMETER_VALUE_4","PARAMETER_UOM_4","PARAMETER_CODE_5","PARAMETER_VALUE_5","PARAMETER_UOM_5","PARAMETER_CODE_6","PARAMETER_VALUE_6","PARAMETER_UO [...]
+"COORD_REF_SYS_CODE","COORD_REF_SYS_NAME","UOM_CODE","SOURCE_GEOGCRS_CODE","COORD_OP_CODE","COORD_OP_METHOD_CODE","SHOW_CRS","DEPRECATED","COORD_SYS_CODE","PARAMETER_CODE_1","PARAMETER_VALUE_1","PARAMETER_UOM_1","PARAMETER_CODE_2","PARAMETER_VALUE_2","PARAMETER_UOM_2","PARAMETER_CODE_3","PARAMETER_VALUE_3","PARAMETER_UOM_3","PARAMETER_CODE_4","PARAMETER_VALUE_4","PARAMETER_UOM_4","PARAMETER_CODE_5","PARAMETER_VALUE_5","PARAMETER_UOM_5","PARAMETER_CODE_6","PARAMETER_VALUE_6","PARAMETER_UO [...]
 #
 # NOTICE: The master version of this file is in the libgeotiff subversion at:
 #
@@ -10,10 +10,10 @@
 #
 # Adjust central meridian to be relative to prime meridian. 
 #
-26591,"Monte Mario (Rome) / Italy zone 1",9001,4806,18121,9807,1,1,4499,8801,0,9102,8802,-3.45233333333333,9102,8805,0.9996,9201,8806,1500000,9001,8807,0,9001,,,,,,
-26592,"Monte Mario (Rome) / Italy zone 2",9001,4806,18122,9807,1,1,4499,8801,0,9102,8802,2.54766666666666,9102,8805,0.9996,9201,8806,2520000,9001,8807,0,9001,,,,,,
+26591,"Monte Mario (Rome) / Italy zone 1",9001,4806,18121,9807,1,1,4499,8801,0,9102,8802,-3.45233333333333,9102,8805,0.9996,9201,8806,1500000,9001,8807,0,9001,,,,,,,,,,,,,
+26592,"Monte Mario (Rome) / Italy zone 2",9001,4806,18122,9807,1,1,4499,8801,0,9102,8802,2.54766666666666,9102,8805,0.9996,9201,8806,2520000,9001,8807,0,9001,,,,,,,,,,,,,
 #
 # 26799 is deprecated, because of the error in the false northing.  However,
 # we "fix" the original to reduce problems folks would otherwise encounter.
 #
-26799,"NAD27 / California zone VII",9003,4267,10408,9802,1,0,4497,8821,34.08,9110,8822,-118.2,9110,8823,34.25,9110,8824,33.52,9110,8826,4186692.58,9003,8827,4160926.74,9003,,,
+26799,"NAD27 / California zone VII",9003,4267,10408,9802,1,0,4497,8821,34.08,9110,8822,-118.2,9110,8823,34.25,9110,8824,33.52,9110,8826,4186692.58,9003,8827,4160926.74,9003,,,,,,,,,,
diff --git a/data/plscenesconf.json b/data/plscenesconf.json
new file mode 100644
index 0000000..af5881e
--- /dev/null
+++ b/data/plscenesconf.json
@@ -0,0 +1,296 @@
+{
+    "v1_data": {
+        "PSOrthoTile" : {
+            "fields": [
+                { "name": "acquired", "type": "datetime" },
+                { "name": "anomalous_pixels", "type": "double" },
+                { "name": "black_fill", "type": "double" },
+                { "name": "cloud_cover", "type": "double" },
+                { "name": "columns", "type": "int" },
+                { "name": "epsg_code", "type": "int" },
+                { "name": "grid_cell", "type": "string" },
+                { "name": "gsd", "type": "double" },
+                { "name": "item_type", "type": "string" },
+                { "name": "origin_x", "type": "double" },
+                { "name": "origin_y", "type": "double" },
+                { "name": "pixel_resolution", "type": "double" },
+                { "name": "provider", "type": "string" },
+                { "name": "published", "type": "datetime" },
+                { "name": "rows", "type": "int" },
+                { "name": "satellite_id", "type": "string" },
+                { "name": "sun_azimuth", "type": "double" },
+                { "name": "sun_elevation", "type": "double" },
+                { "name": "updated", "type": "datetime" },
+                { "name": "usable_data", "type": "double" },
+                { "name": "view_angle", "type": "double" }
+            ],
+            "assets": [
+                "analytic",
+                "analytic_dn",
+                "analytic_dn_xml",
+                "analytic_xml",
+                "udm",
+                "visual",
+                "visual_xml"
+            ]
+        },
+        "REOrthoTile" : {
+            "fields" : [
+                { "name": "acquired", "type": "datetime" },
+                { "name": "anomalous_pixels", "type": "double" },
+                { "name": "black_fill", "type": "double" },
+                { "name": "catalog_id", "type": "string" },
+                { "name": "cloud_cover", "type": "double" },
+                { "name": "columns", "type": "int" },
+                { "name": "epsg_code", "type": "int" },
+                { "name": "grid_cell", "type": "string" },
+                { "name": "gsd", "type": "double" },
+                { "name": "item_type", "type": "string" },
+                { "name": "origin_x", "type": "double" },
+                { "name": "origin_y", "type": "double" },
+                { "name": "pixel_resolution", "type": "double" },
+                { "name": "provider", "type": "string" },
+                { "name": "published", "type": "datetime" },
+                { "name": "rows", "type": "int" },
+                { "name": "satellite_id", "type": "string" },
+                { "name": "strip_id", "type": "string" },
+                { "name": "sun_azimuth", "type": "double" },
+                { "name": "sun_elevation", "type": "double" },
+                { "name": "updated", "type": "datetime" },
+                { "name": "usable_data", "type": "double" },
+                { "name": "view_angle", "type": "double" }
+             ],
+            "assets": [
+                "analytic",
+                "analytic_xml",
+                "udm",
+                "visual",
+                "visual_xml"
+            ]
+        },
+        "PSScene3Band" : {
+            "fields": [
+                { "name": "acquired", "type": "datetime" },
+                { "name": "anomalous_pixels", "type": "double" },
+                { "name": "cloud_cover", "type": "double" },
+                { "name": "columns", "type": "int" },
+                { "name": "epsg_code", "type": "int" },
+                { "name": "gsd", "type": "double" },
+                { "name": "instrument", "type": "string" },
+                { "name": "item_type", "type": "string" },
+                { "name": "origin_x", "type": "double" },
+                { "name": "origin_y", "type": "double" },
+                { "name": "pixel_resolution", "type": "double" },
+                { "name": "provider", "type": "string" },
+                { "name": "published", "type": "datetime" },
+                { "name": "quality_category", "type": "string" },
+                { "name": "rows", "type": "int" },
+                { "name": "satellite_id", "type": "string" },
+                { "name": "strip_id", "type": "string" },
+                { "name": "sun_azimuth", "type": "double" },
+                { "name": "sun_elevation", "type": "double" },
+                { "name": "updated", "type": "datetime" },
+                { "name": "usable_data", "type": "double" },
+                { "name": "view_angle", "type": "double" }
+            ],
+            "assets": [
+                "analytic",
+                "analytic_dn",
+                "analytic_dn_xml",
+                "analytic_xml",
+                "basic_analytic",
+                "basic_analytic_dn",
+                "basic_analytic_dn_rpc",
+                "basic_analytic_dn_xml",
+                "basic_analytic_rpc",
+                "basic_analytic_xml",
+                "basic_udm",
+                "udm",
+                "visual",
+                "visual_xml"
+            ]
+        },
+        "PSScene4Band" : {
+            "fields": [
+                { "name": "acquired", "type": "datetime" },
+                { "name": "anomalous_pixels", "type": "double" },
+                { "name": "cloud_cover", "type": "double" },
+                { "name": "columns", "type": "int" },
+                { "name": "epsg_code", "type": "int" },
+                { "name": "gsd", "type": "double" },
+                { "name": "instrument", "type": "string" },
+                { "name": "item_type", "type": "string" },
+                { "name": "origin_x", "type": "double" },
+                { "name": "origin_y", "type": "double" },
+                { "name": "pixel_resolution", "type": "double" },
+                { "name": "provider", "type": "string" },
+                { "name": "published", "type": "datetime" },
+                { "name": "quality_category", "type": "string" },
+                { "name": "rows", "type": "int" },
+                { "name": "satellite_id", "type": "string" },
+                { "name": "strip_id", "type": "string" },
+                { "name": "sun_azimuth", "type": "double" },
+                { "name": "sun_elevation", "type": "double" },
+                { "name": "updated", "type": "datetime" },
+                { "name": "usable_data", "type": "double" },
+                { "name": "view_angle", "type": "double" }
+            ],
+            "assets": [
+                "analytic",
+                "analytic_dn",
+                "analytic_dn_xml",
+                "analytic_xml",
+                "basic_analytic",
+                "basic_analytic_dn",
+                "basic_analytic_dn_nitf",
+                "basic_analytic_dn_rpc",
+                "basic_analytic_dn_rpc_nitf",
+                "basic_analytic_dn_xml",
+                "basic_analytic_dn_xml_nitf",
+                "basic_analytic_nitf",
+                "basic_analytic_rpc",
+                "basic_analytic_rpc_nitf",
+                "basic_analytic_xml",
+                "basic_analytic_xml_nitf",
+                "basic_udm",
+                "udm"
+            ]
+        },
+        "REScene" : {
+            "fields":  [
+                { "name": "acquired", "type": "datetime" },
+                { "name": "anomalous_pixels", "type": "double" },
+                { "name": "black_fill", "type": "double" },
+                { "name": "catalog_id", "type": "string" },
+                { "name": "cloud_cover", "type": "double" },
+                { "name": "columns", "type": "int" },
+                { "name": "gsd", "type": "double" },
+                { "name": "item_type", "type": "string" },
+                { "name": "provider", "type": "string" },
+                { "name": "published", "type": "datetime" },
+                { "name": "rows", "type": "int" },
+                { "name": "satellite_id", "type": "string" },
+                { "name": "strip_id", "type": "string" },
+                { "name": "sun_azimuth", "type": "double" },
+                { "name": "sun_elevation", "type": "double" },
+                { "name": "updated", "type": "datetime" },
+                { "name": "usable_data", "type": "double" },
+                { "name": "view_angle", "type": "double" }
+            ],
+            "assets": [
+                "basic_analytic_b1",
+                "basic_analytic_b1_nitf",
+                "basic_analytic_b2",
+                "basic_analytic_b2_nitf",
+                "basic_analytic_b3",
+                "basic_analytic_b3_nitf",
+                "basic_analytic_b4",
+                "basic_analytic_b4_nitf",
+                "basic_analytic_b5",
+                "basic_analytic_b5_nitf",
+                "basic_analytic_rpc",
+                "basic_analytic_sci",
+                "basic_analytic_xml",
+                "basic_analytic_xml_nitf",
+                "basic_udm",
+                "browse"
+            ]
+        },
+        "Landsat8L1G" : {
+            "fields": [
+                { "name": "acquired", "type": "datetime" },
+                { "name": "anomalous_pixels", "type": "double" },
+                { "name": "cloud_cover", "type": "double" },
+                { "name": "columns", "type": "int" },
+                { "name": "data_type", "type": "string" },
+                { "name": "epsg_code", "type": "int" },
+                { "name": "gsd", "type": "double" },
+                { "name": "instrument", "type": "string" },
+                { "name": "item_type", "type": "string" },
+                { "name": "origin_x", "type": "double" },
+                { "name": "origin_y", "type": "double" },
+                { "name": "pixel_resolution", "type": "double" },
+                { "name": "provider", "type": "string" },
+                { "name": "published", "type": "datetime" },
+                { "name": "quality_category", "type": "string" },
+                { "name": "rows", "type": "int" },
+                { "name": "satellite_id", "type": "string" },
+                { "name": "sun_azimuth", "type": "double" },
+                { "name": "sun_elevation", "type": "double" },
+                { "name": "updated", "type": "datetime" },
+                { "name": "usable_data", "type": "double" },
+                { "name": "view_angle", "type": "double" },
+                { "name": "wrs_path", "type": "int" },
+                { "name": "wrs_row", "type": "int" }
+            ],
+            "assets": [
+                "analytic_b1",
+                "analytic_b2",
+                "analytic_b3",
+                "analytic_b4",
+                "analytic_b5",
+                "analytic_b6",
+                "analytic_b7",
+                "analytic_b8",
+                "analytic_b9",
+                "analytic_b10",
+                "analytic_b11",
+                "analytic_bqa",
+                "metadata_txt",
+                "visual"
+            ]
+        },
+        "Sentinel2L1C" :  {
+            "fields": [
+                { "name": "abs_orbit_number", "type": "int" },
+                { "name": "acquired", "type": "datetime" },
+                { "name": "anomalous_pixels", "type": "double" },
+                { "name": "black_fill", "type": "double" },
+                { "name": "cloud_cover", "type": "double" },
+                { "name": "columns", "type": "int" },
+                { "name": "data_type", "type": "string" },
+                { "name": "datatake_id", "type": "string" },
+                { "name": "epsg_code", "type": "int" },
+                { "name": "granule_id", "type": "string" },
+                { "name": "gsd", "type": "double" },
+                { "name": "instrument", "type": "string" },
+                { "name": "item_type", "type": "string" },
+                { "name": "mgrs_grid_id", "type": "string" },
+                { "name": "origin_x", "type": "double" },
+                { "name": "origin_y", "type": "double" },
+                { "name": "pixel_resolution", "type": "double" },
+                { "name": "product_generation_time", "type": "datetime" },
+                { "name": "product_id", "type": "string" },
+                { "name": "provider", "type": "string" },
+                { "name": "published", "type": "datetime" },
+                { "name": "quality_category", "type": "string" },
+                { "name": "rel_orbit_number", "type": "int" },
+                { "name": "rows", "type": "int" },
+                { "name": "s2_processor_version", "type": "string" },
+                { "name": "satellite_id", "type": "string" },
+                { "name": "sun_azimuth", "type": "double" },
+                { "name": "sun_elevation", "type": "double" },
+                { "name": "updated", "type": "datetime" },
+                { "name": "usable_data", "type": "double" },
+                { "name": "view_angle", "type": "double" }
+            ],
+            "assets": [
+                "analytic_b1",
+                "analytic_b2",
+                "analytic_b3",
+                "analytic_b4",
+                "analytic_b5",
+                "analytic_b6",
+                "analytic_b7",
+                "analytic_b8",
+                "analytic_b8a",
+                "analytic_b9",
+                "analytic_b10",
+                "analytic_b11",
+                "analytic_b12",
+                "metadata_aux"
+            ]
+        }
+    }
+}
+
diff --git a/data/prime_meridian.csv b/data/prime_meridian.csv
index dbcc804..fa79cac 100644
--- a/data/prime_meridian.csv
+++ b/data/prime_meridian.csv
@@ -1,5 +1,5 @@
 prime_meridian_code,prime_meridian_name,greenwich_longitude,uom_code,remarks,information_source,data_source,revision_date,change_id,deprecated
-8901,Greenwich,0,9102,,,OGP,1995/06/02,1996.290,0
+8901,Greenwich,0,9102,The international reference meridian as defined first by the 1884 International Meridian Conference and later by the Bureau International de l'Heure (BIH) and then the International Earth Rotation Service (IERS).,OGP,IOGP,2016/12/15,1996.290 2016.045,0
 8902,Lisbon,-9.0754862,9110,,"Instituto Geografico e Cadastral; Lisbon",OGP,2014/06/27,1996.290 2014.040,0
 8903,Paris,2.5969213,9105,"Value adopted by IGN (Paris) in 1936. Equivalent to 2°20'14.025"". Preferred by EPSG to earlier value of 2°20'13.95"" (2.596898 grads) used by RGS London.","Institut Geographique National (IGN); Paris",OGP,2008/06/24,2008.045,0
 8904,Bogota,-74.04513,9110,,"Instituto Geografico ""Augustin Cadazzi"" (IGAC); Bogota",OGP,2014/06/27,1996.290 2014.040,0
diff --git a/data/projop_wparm.csv b/data/projop_wparm.csv
index a687198..c28202b 100644
--- a/data/projop_wparm.csv
+++ b/data/projop_wparm.csv
@@ -692,6 +692,54 @@
 7525,"WISCRS Waukesha County (ftUS)",9807,8801,42.341,9110,8802,-88.133,9110,8805,1.0000346179,9201,8806,685000.001,9003,8807,0.011,9003,,,,,,
 7526,"WISCRS Waushara County (m)",9801,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,120091.4402,9001,8807,45069.7587,9001,,,,,,
 7527,"WISCRS Waushara County (ftUS)",9801,8801,44.0650198565,9110,8802,-89.143,9110,8805,1.0000392096,9201,8806,394000,9003,8807,147866.367,9003,,,,,,
+7687,Kyrgyzstan zone 1,9807,8801,0,9110,8802,68.31,9110,8805,1,9201,8806,1300000,9001,8807,14743.5,9001,,,,,,
+7688,Kyrgyzstan zone 2,9807,8801,0,9110,8802,71.31,9110,8805,1,9201,8806,2300000,9001,8807,14743.5,9001,,,,,,
+7689,Kyrgyzstan zone 3,9807,8801,0,9110,8802,74.31,9110,8805,1,9201,8806,3300000,9001,8807,14743.5,9001,,,,,,
+7690,Kyrgyzstan zone 4,9807,8801,0,9110,8802,77.31,9110,8805,1,9201,8806,4300000,9001,8807,14743.5,9001,,,,,,
+7691,Kyrgyzstan zone 5,9807,8801,0,9110,8802,80.31,9110,8805,1,9201,8806,5300000,9001,8807,14743.5,9001,,,,,,
+7722,Survey of India Lambert,9802,8821,24,9102,8822,80,9102,8823,12.2822638,9110,8824,35.1022096,9110,8826,4000000,9001,8827,4000000,9001,,,
+7723,Andhra Pradesh NSF LCC,9802,8821,16.25543298,9102,8822,80.875,9102,8823,13.75,9102,8824,18.75,9102,8826,1000000,9001,8827,1000000,9001,,,
+7724,Arunachal Pradesh NSF LCC,9802,8821,28.00157897,9102,8822,94.5,9102,8823,27,9102,8824,29,9102,8826,1000000,9001,8827,1000000,9001,,,
+7725,Assam NSF LCC,9802,8821,26.00257703,9102,8822,92.75,9102,8823,24.4,9110,8824,27.2,9110,8826,1000000,9001,8827,1000000,9001,,,
+7726,Bihar NSF LCC,9802,8821,25.87725247,9102,8822,85.875,9102,8823,24.625,9102,8824,27.125,9102,8826,1000000,9001,8827,1000000,9001,,,
+7727,Delhi NSF LCC,9802,8821,28.62510126,9102,8822,77,9102,8823,28.223,9110,8824,28.523,9110,8826,1000000,9001,8827,1000000,9001,,,
+7728,Gujarat NSF LCC,9802,8821,22.37807121,9102,8822,71.375,9102,8823,20.473,9110,8824,23.573,9110,8826,1000000,9001,8827,1000000,9001,,,
+7729,Haryana NSF LCC,9802,8821,29.25226266,9102,8822,76,9102,8823,28.05,9110,8824,30.25,9110,8826,1000000,9001,8827,1000000,9001,,,
+7730,Himachal Pradesh NSF LCC,9802,8821,31.75183497,9102,8822,77.375,9102,8823,30.75,9102,8824,32.75,9102,8826,1000000,9001,8827,1000000,9001,,,
+7731,Jammu and Kashmir NSF LCC,9802,8821,34.75570874,9102,8822,76.5,9102,8823,33.05,9110,8824,36.25,9110,8826,1000000,9001,8827,1000000,9001,,,
+7732,Jharkhand NSF LCC,9802,8821,23.62652682,9102,8822,85.625,9102,8823,22.323,9110,8824,24.423,9110,8826,1000000,9001,8827,1000000,9001,,,
+7733,Madhya Pradesh NSF LCC,9802,8821,24.00529821,9102,8822,78.375,9102,8823,22,9102,8824,26,9102,8826,1000000,9001,8827,1000000,9001,,,
+7734,Maharashtra NSF LCC,9802,8821,18.88015774,9102,8822,76.75,9102,8823,16.373,9110,8824,21.073,9110,8826,1000000,9001,8827,1000000,9001,,,
+7735,Manipur NSF LCC,9802,8821,24.75060911,9102,8822,94,9102,8823,24.05,9110,8824,25.25,9110,8826,1000000,9001,8827,1000000,9001,,,
+7736,Meghalaya NSF LCC,9802,8821,25.62524747,9102,8822,91.375,9102,8823,25.123,9110,8824,26.023,9110,8826,1000000,9001,8827,1000000,9001,,,
+7737,Nagaland NSF LCC,9802,8821,26.12581974,9102,8822,94.375,9102,8823,25.223,9110,8824,26.523,9110,8826,1000000,9001,8827,1000000,9001,,,
+7738,Northeast India NSF LCC,9802,8821,25.63452135,9102,8822,93.5,9102,8823,23.023,9110,8824,28.123,9110,8826,1000000,9001,8827,1000000,9001,,,
+7739,Orissa NSF LCC,9802,8821,20.25305174,9102,8822,84.375,9102,8823,18.35,9110,8824,21.55,9110,8826,1000000,9001,8827,1000000,9001,,,
+7740,Punjab NSF LCC,9802,8821,31.00178226,9102,8822,75.375,9102,8823,30,9102,8824,32,9102,8826,1000000,9001,8827,1000000,9001,,,
+7741,Rajasthan NSF LCC,9802,8821,26.88505546,9102,8822,73.875,9102,8823,24.173,9110,8824,29.273,9110,8826,1000000,9001,8827,1000000,9001,,,
+7742,Uttar Pradesh NSF LCC,9802,8821,27.13270823,9102,8822,80.875,9102,8823,24.523,9110,8824,29.223,9110,8826,1000000,9001,8827,1000000,9001,,,
+7743,Uttaranchal NSF LCC,9802,8821,30.0017132,9102,8822,79.375,9102,8823,29,9102,8824,31,9102,8826,1000000,9001,8827,1000000,9001,,,
+7744,Andaman and Nicobar NSF TM,9807,8801,10.25,9102,8802,93.25,9102,8805,0.9999428,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7745,Chhattisgarh NSF TM,9807,8801,21,9102,8802,82.25,9102,8805,0.9998332,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7746,Goa NSF TM,9807,8801,15.375,9102,8802,74,9102,8805,0.9999913,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7747,Karnataka NSF TM,9807,8801,15.125,9102,8802,76.375,9102,8805,0.9998012,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7748,Kerala NSF TM,9807,8801,10.5,9102,8802,76,9102,8805,0.9999177,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7749,Lakshadweep NSF TM,9807,8801,10,9102,8802,73.125,9102,8805,0.9999536,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7750,Mizoram NSF TM,9807,8801,23.125,9102,8802,92.75,9102,8805,0.9999821,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7751,Sikkim NSF TM,9807,8801,27.625,9102,8802,88.5,9102,8805,0.9999926,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7752,Tamil Nadu NSF TM,9807,8801,10.875,9102,8802,78.375,9102,8805,0.9997942,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7753,Tripura NSF TM,9807,8801,23.75,9102,8802,91.75,9102,8805,0.9999822,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7754,West Bengal NSF TM,9807,8801,24.375,9102,8802,87.875,9102,8805,0.9998584,9201,8806,1000000,9001,8807,1000000,9001,,,,,,
+7802,Cadastral Coordinate System 2005,9802,8821,42.400435246,9110,8822,25.3,9110,8823,42,9110,8824,43.2,9110,8826,500000,9001,8827,4725824.3591,9001,,,
+7818,CS63 zone X1,9807,8801,0.05,9110,8802,23.3,9110,8805,1,9201,8806,1300000,9001,8807,0,9001,,,,,,
+7819,CS63 zone X2,9807,8801,0.05,9110,8802,26.3,9110,8805,1,9201,8806,2300000,9001,8807,0,9001,,,,,,
+7820,CS63 zone X3,9807,8801,0.05,9110,8802,29.3,9110,8805,1,9201,8806,3300000,9001,8807,0,9001,,,,,,
+7821,CS63 zone X4,9807,8801,0.05,9110,8802,32.3,9110,8805,1,9201,8806,4300000,9001,8807,0,9001,,,,,,
+7822,CS63 zone X5,9807,8801,0.05,9110,8802,35.3,9110,8805,1,9201,8806,5300000,9001,8807,0,9001,,,,,,
+7823,CS63 zone X6,9807,8801,0.05,9110,8802,38.3,9110,8805,1,9201,8806,6300000,9001,8807,0,9001,,,,,,
+7824,CS63 zone X7,9807,8801,0.05,9110,8802,41.3,9110,8805,1,9201,8806,7300000,9001,8807,0,9001,,,,,,
+7875,St. Helena Local Grid 1971,9807,8801,-15.58,9110,8802,-5.43,9110,8805,1,9201,8806,300000,9001,8807,2000000,9001,,,,,,
+7876,"St. Helena Local Grid (Tritan)",9807,8801,-15.58,9110,8802,-5.43,9110,8805,1,9201,8806,299483.737,9001,8807,2000527.879,9001,,,,,,
 10101,Alabama CS27 East zone,9807,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,500000,9003,8807,0,9003,,,,,,
 10102,Alabama CS27 West zone,9807,8801,30,9110,8802,-87.3,9110,8805,0.999933333,9201,8806,500000,9003,8807,0,9003,,,,,,
 10131,"SPCS83 Alabama East zone (meters)",9807,8801,30.3,9110,8802,-85.5,9110,8805,0.99996,9201,8806,200000,9001,8807,0,9001,,,,,,
@@ -1714,7 +1762,7 @@
 17358,Map Grid of Australia zone 58,9807,8801,0,9102,8802,165,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
 17359,SA Lambert,9802,8821,-32,9102,8822,135,9102,8823,-28,9102,8824,-36,9102,8826,1000000,9001,8827,2000000,9001,,,
 17360,Vicgrid66,9802,8821,-37,9102,8822,145,9102,8823,-36,9102,8824,-38,9102,8826,2500000,9001,8827,4500000,9001,,,
-17361,Vicgrid94,9802,8821,-37,9102,8822,145,9102,8823,-36,9102,8824,-38,9102,8826,2500000,9001,8827,2500000,9001,,,
+17361,Vicgrid,9802,8821,-37,9102,8822,145,9102,8823,-36,9102,8824,-38,9102,8826,2500000,9001,8827,2500000,9001,,,
 17362,Geoscience Australia Standard National Scale Lambert Projection,9802,8821,0,9102,8822,134,9102,8823,-18,9102,8824,-36,9102,8826,0,9001,8827,0,9001,,,
 17363,Brisbane City Survey Grid 02,9807,8801,-28,9102,8802,153,9102,8805,0.99999,9201,8806,50000,9001,8807,100000,9001,,,,,,
 17364,New South Wales Lambert,9802,8821,-33.25,9102,8822,147,9102,8823,-30.75,9102,8824,-35.75,9102,8826,9300000,9001,8827,4500000,9001,,,
diff --git a/data/s57attributes.csv b/data/s57attributes.csv
index 6e44456..3b2c04e 100644
--- a/data/s57attributes.csv
+++ b/data/s57attributes.csv
@@ -22,15 +22,15 @@
 21,Category of distance mark,CATDIS,E,F
 22,Category of dock,CATDOC,E,F
 23,Category of dumping ground,CATDPG,L,F
-24,Category of  fence/wall,CATFNC,E,F
+24,Category of fence/wall,CATFNC,E,F
 25,Category of ferry,CATFRY,E,F
-26,Category of  fishing  facility,CATFIF,E,F
-27,Category of  fog signal,CATFOG,E,F
-28,Category of  fortified structure,CATFOR,E,F
+26,Category of fishing  facility,CATFIF,E,F
+27,Category of fog signal,CATFOG,E,F
+28,Category of fortified structure,CATFOR,E,F
 29,Category of gate,CATGAT,E,F
 30,Category of harbour facility,CATHAF,L,F
 31,Category of hulk,CATHLK,L,F
-32,Category of  ice,CATICE,E,F
+32,Category of ice,CATICE,E,F
 33,Category of installation buoy,CATINB,E,F
 34,Category of land region,CATLND,L,F
 35,Category of landmark,CATLMK,L,F
@@ -188,6 +188,9 @@
 187,Water level effect,WATLEV,E,F
 188,Category of Tidal stream,CAT_TS,E,F
 189,Positional accuracy units,PUNITS,E,F
+190,Object class definition,CLSDEF,S,F
+191,Object class name,CLSNAM,S,F
+192,Symbol instruction,SYMINS,S,F
 300,Information in national language,NINFOM,S,N
 301,Object name in national language,NOBJNM,S,N
 302,Pilot district in national language,NPLDST,S,N
@@ -196,3 +199,286 @@
 400,Horizontal datum,HORDAT,E,S
 401,Positional Accuracy,POSACC,F,S
 402,Quality of position,QUAPOS,E,S
+0,"###Codes in the 17xxx range come from past s57attributes_iw.csv (Inland Waterways)",###,S,F
+17000,Category of Anchorage area,catach,L,F
+17001,Category of distance mark,catdis,E,F
+17002,Category of signal station trafficcatsit,catsit,L,F
+17003,Category of signal station warning,catsiw,L,F
+17004,Restriction,restrn,L,F
+17005,Vertical datum,verdat,E,F
+17006,Category of bridge,catbrg,L,F
+17007,Category of ferry,catfry,L,F
+17008,Category of harbour facilities,cathaf,L,F
+17009,"Marks navigational – System of",marsys,E,F
+17050,Additional mark,addmrk,L,F
+17051,Category of bank,catbnk,E,F
+17052,Category of notice mark,catnmk,E,F
+17055,Class of dangerous cargo,clsdng,E,F
+17056,Direction of impact,dirimp,L,F
+17057,Distance from bank,disbk1,F,F
+17058,Distance from bank,disbk2,F,F
+17059,"Distance of impact, upstream",disipu,F,F
+17060,"Distance of impact, downstream",disipd,F,F
+17061,Elevation 1,eleva1,F,F
+17062,Elevation 2,eleva2,F,F
+17063,Function of notice mark,fnctnm,E,F
+17064,Waterway distance,wtwdis,F,F
+17065,Bunker vessel,bunves,E,F
+17066,Category of berth,catbrt,L,F
+17067,Category of bunker,catbun,L,F
+17068,Category of CEMT class,catccl,L,F
+17069,Category of communication,catcom,L,F
+17070,Category of harbour area,cathbr,L,F
+17071,Category of refuse dump,catrfd,L,F
+17072,Category of terminal,cattml,L,F
+17073,Communication,comctn,S,F
+17074,"Horizontal clearance, length",horcll,F,F
+17075,"Horizontal clearance, width",horclw,F,F
+17076,Transshipping goods,trshgd,L,F
+17077,UN Location Code,unlocd,S,F
+17112,Category of waterway mark,catwwm,E,F
+0,"###Codes in the 20xxx and 22xxx range come from past s57attributes_aml.csv (Additional_Military_Layers)",###,S,F
+20484,"Abandonment Date","databa","A","?"
+20485,"Attenuation","attutn","F","?"
+20486,"Beam of Vessel","vesbem","F","?"
+20487,"Bearing","bearng","F","?"
+20488,"Blind Zone","blndzn","A","?"
+20489,"Breaker Type","brktyp","E","?"
+20490,"Density","bulkdn","F","?"
+20491,"Burial Mechanism","brmchm","E","?"
+20492,"Burial Percentage","brpctg","I","?"
+20493,"Burial Period","brperd","I","?"
+20494,"Burial Probability","brprob","E","?"
+20495,"Cardinal Point Orientation","orcard","E","?"
+20496,"Category of administration area","catadm","E","?"
+20497,"Category of airspace restriction","catasr","E","?"
+20498,"Category of bedrock","N/A","N/A","?"
+20499,"Bottom Feature Classification","catbot","E","?"
+20500,"Category of coastguard station","catcgs","E","?"
+20501,"Category of controlled airspace","catcas","E","?"
+20502,"Fishing Activity","catfsh","E","?"
+20503,"Type of Imagery","catimg","L","?"
+20504,"Category of marine management area","catmma","E","?"
+20505,"Category of maritime safety information","catmsi","E","?"
+20506,"Category of military exercise airspace ","catmea","E","?"
+20507,"Category of patrol area","catpat","E","?"
+20508,"Category of reporting/radio calling-in point","catrep","E","?"
+20509,"Category of regulated airspace","N/A","N/A","?"
+20510,"Category of territorial sea baseline","catsbl","E","?"
+20511,"Trafficability","cattrf","E","?"
+20512,"Command System","comsys","S","?"
+20515,"Controlled airspace class designation","caircd","E","?"
+20516,"Controlling authority","authty","S","?"
+20517,"Current Scour Dimensions","scrdim","A","?"
+20518,"Dangerous Marine and Land Life","dgmrlf","L","?"
+20519,"Date Sunk","datsnk","A","?"
+20520,"Debris Field","debfld","A","?"
+20521,"Depth of Activity","depact","F","?"
+20522,"Depth of Layer","deplyr","F","?"
+20523,"Distance from Small Bottom Object","discon","F","?"
+20524,"Diver’s Thrust Test Depth","dttdep","E","?"
+20525,"Diver’s Thrust Test Number","dttnum","I","?"
+20526,"Diving Activity","divact","E","?"
+20527,"Draught of Vessel","vesdgh","F","?"
+20528,"Exit Usability","exitus","E","?"
+20529,"Field Name","fldnam","S","?"
+20530,"First Detection Year","datfir","A","?"
+20531,"First Sensor","senfir","E","?"
+20532,"First Source","sorfir","E","?"
+20533,"Foliar Index","folinx","F","?"
+20534,"Gas Content","gascon","I","?"
+20535,"General Water Depth","gendep","I","?"
+20536,"Gradient","gradnt","E","?"
+20537,"Grain Size","grnsiz","F","?"
+20538,"Inclination","incltn","F","?"
+20539,"Internal Data Record Identification Number","N/A","N/A","?"
+20540,"Last Detection Year","datlst","A","?"
+20541,"Last Sensor","senlst","E","?"
+20542,"Last Source","sorlst","E","?"
+20543,"Lay Platform","layptm","E","?"
+20544,"Lay Reference Number","layrfn","S","?"
+20545,"Lay Time","laytim","A","?"
+20546,"Layer Number","laynum","I","?"
+20547,"Legal Status","legsta","S","?"
+20548,"Length of Vessel","veslen","F","?"
+20549,"Magnetic Anomaly Detector (MAD) Signature","madsig","E","?"
+20550,"Magnetic Intensity","magint","I","?"
+20551,"Mean Shear Strength","msstrg","F","?"
+20552,"Migration Direction","migdir","I","?"
+20553,"Migration Speed","migspd","F","?"
+20554,"Milec Density","milden","E","?"
+20555,"Mine Index Mine Case","mnimnc","E","?"
+20556,"Mine Index Mine Type","mnimnt","L","?"
+20557,"Mine Reference Number","minern","S","?"
+20558,"Mine-Hunting Classification","mhclas","E","?"
+20559,"Minehunting System","mnhsys","S","?"
+20560,"Minesweeping System","mnssys","S","?"
+20561,"Mission Classification","miscls","E","?"
+20562,"Mission Comments","miscom","S","?"
+20563,"Mission Date","misdat","A","?"
+20564,"Mission Name","misnme","S","?"
+20565,"MWDC Reference Number","mwdcrn","S","?"
+20566,"Nature of Geological Layer","natsed","E","?"
+20567,"Navigation System","navsys","S","?"
+20568,"NOMBO Density","nomden","E","?"
+20569,"Not Found","notfnd","S","?"
+20570,"Number of Previous Observations","nmprob","I","?"
+20571,"Operator","oprtor","S","?"
+20572,"Orientation of Best Observation","orbobn","F","?"
+20573,"Origin of Data","orgdat","E","?"
+20574,"Originator","orgntr","S","?"
+20575,"Porosity","porsty","I","?"
+20576,"Quality of Beach Data","quabch","A","?"
+20577,"Re-entered Date","datren","A","?"
+20578,"Re-suspended Date","datres","A","?"
+20579,"Reverberation","revebn","E","?"
+20580,"Safety Zone","N/A","N/A","?"
+20581,"Sample Retained","samret","S","?"
+20582,"Seabed Coverage","sbdcov","I","?"
+20583,"Ships Speed","shpspd","F","?"
+20584,"Sonar Frequency","snrfrq","E","?"
+20585,"Sonar Range Scale","snrrsc","F","?"
+20586,"Sonar Reflectivity","snrflc","E","?"
+20587,"Sonar Signal Strength","sonsig","E","?"
+20588,"Sound Velocity","sndvel","F","?"
+20589,"Sounding Datum","soudat","E","?"
+20590,"Spudded Date","datspd","A","?"
+20592,"Steepest Face Orientation","stfotn","F","?"
+20593,"Strength According to Richter Scale","ricsca","I","?"
+20594,"Strength of Magnetic Anomaly","magany","E","?"
+20595,"Suitability for ACV Use","stbacv","E","?"
+20596,"Surf Height","srfhgt","F","?"
+20597,"Surf Zone","srfzne","I","?"
+20598,"Survey Date and Time","surdat","A","?"
+20599,"Suspension Date","datsus","A","?"
+20600,"Swell Height","swlhgt","F","?"
+20601,"Tidal Range","tdlrng","F","?"
+20602,"Time of Year","timeyr","L","?"
+20603,"Tonnage","tonage","I","?"
+20604,"Towed Body Depth","twdbdp","F","?"
+20605,"Type of military activity","milact","L","?"
+20606,"Type of Tonnage","typton","E","?"
+20607,"Type of Wreck","typewk","E","?"
+20608,"Underwater Reference Mark","unwrfm","E","?"
+20609,"Unique ID from a Navigational Product","N/A","N/A","?"
+20610,"Water Clarity","watclr","F","?"
+20611,"Wavelength","wavlen","F","?"
+20612,"Weight Bearing Capability","wbrcap","I","?"
+20613,"Width (left)","lftwid","F","?"
+20614,"Width (right)","rgtwid","F","?"
+20615,"Contour Type","hypcat","E","?"
+20616,"Sounding Velocity","souvel","E","?"
+20617,"Access Restriction","accres","S","?"
+20618,"Approach","apprch","S","?"
+20619,"Category of Beach","catbch","E","?"
+20620,"Clearance Percentage","clperc","I","?"
+20621,"Communications","commns","L","?"
+20622,"Confidence Level","conlev","F","?"
+20624,"Exit Description","extdes","S","?"
+20625,"Industry","indtry","S","?"
+20626,"Landing Conditions","lndcon","S","?"
+20627,"Leisure Activity","lsract","S","?"
+20628,"Logistics","logtcs","L","?"
+20629,"Manoeuvring","manvrg","S","?"
+20630,"Mine Threat Density","mntden","I","?"
+20631,"Multiple Contacts","mulcon","I","?"
+20632,"Navigational Description","navdes","S","?"
+20633,"Navigational Difficulty","navdif","E","?"
+20634,"Number of Remaining Mines","numrmn","I","?"
+20635,"Pier Contact Details","pierod","S","?"
+20636,"Pier Description","pierdn","S","?"
+20637,"Prairies Density","prsden","I","?"
+20638,"Probability for Remaining Mines","prbrmn","F","?"
+20639,"Remaining Mines Likely, Maximum Number","rmnlmn","I","?"
+20640,"Self Protection (Air)","sfptna","E","?"
+20641,"Self Protection (Near Defence)","sptnnd","E","?"
+20642,"Self Protection (Surface)","sfptns","E","?"
+20643,"Sensor Coverage","sencov","S","?"
+20644,"Simple Initial Threat","sminth","F","?"
+20645,"Target Reference Weight","tgrfwt","E","?"
+20646,"Tidal Type","tdltyp","E","?"
+20647,"Type of Resource Location","typres","E","?"
+20648,"Undetectable Mines Ratio","undmnr","F","?"
+20649,"Undetectable Mines Ratio with Burial","umnrwb","F","?"
+20650,"Undetectable Mines Ratio without Burial","umrwob","F","?"
+20651,"Weapon Coverage","wpncov","S","?"
+20652,"On Sonar","onsonr","E","?"
+20653,"HF Bottom Loss","hfbmls","F","?"
+20654,"LF Bottom Loss","lfbmls","F","?"
+20655,"Detection Probability","dtprob","F","?"
+20656,"Disposal Probability","dsprob","F","?"
+20657,"Classification Probability","clprob","F","?"
+20658,"Characteristic Detection Width (A)","cswidt","I","?"
+20659,"Characteristic Detection Probability (B)","csprob","F","?"
+20660,"Zone Colour","znecol","E","?"
+20661,"Reverberation Frequency","revfqy","F","?"
+20662,"Reverberation Grazing Angle","revgan","F","?"
+20663,"International Defence Organisation (IDO) status","secido","E","?"
+20664,"Protective Marking","secpmk","E","?"
+20665,"Owner Authority","secown","S","?"
+20666,"Caveat ","seccvt","S","?"
+20667,"Species","spcies","S","?"
+20668,"Swept date","swpdat","A","?"
+20669,"Runway length","rwylen","I","?"
+20670,"Active period","actper","S","?"
+20671,"Maximum altitude","maxalt","I","?"
+20672,"Minimum altitude","minalt","I","?"
+20673,"Maximum Flight Level","maxftl","I","?"
+20674,"Minimum Flight Level","minftl","I","?"
+20675,"Bottom Vertical Safety Separation","bverss","I","?"
+20676,"Minimum Safe Depth","mindep","I","?"
+20677,"Interpolated line characteristic","linech","E","?"
+20678,"Identification","identy","S","?"
+20679,"Route Classification","rclass","E","?"
+20680,"Population","popltn","I","?"
+20681,"Surface Threat","surtht","E","?"
+20682,"Heading-Up Bearing","upbear","F","?"
+20683,"Heading-Down Bearing","dnbear","F","?"
+20684,"Ice Concentration","icencn","I","?"
+20685,"Danger height","dgrhgt","I","?"
+20686,"Depth Restriction","depres","S","?"
+20687,"Area Category","arecat","E","?"
+20688,"Existence of Restricted Area","exzres","E","?"
+20689,"Target Strength","tarstg","I","?"
+20690,"Qualification of Radar Coverage","quarad","I","?"
+20691,"Contact Details","condet","S","?"
+20692,"Limit of Anchors and Chains","limanc","F","?"
+20693,"CCM Index","ccmidx","I","?"
+20694,"Military Load Classification","mlclas","E","?"
+20695,"MGS Type","mgstyp","E","?"
+20696,"Ice Attribute Concentration Total","iceact","E","?"
+20697,"Ice Stage of Development","icesod","E","?"
+20698,"Ice Advisory Code","iceadc","S","?"
+20699,"Number of Icebergs in Area","icebnm","I","?"
+20700,"Ice Line Category","icelnc","E","?"
+20701,"Ice Polynya Type","icepty","E","?"
+20702,"Ice Polynya Status","icepst","E","?"
+20703,"Ice Lead Type","icelty","E","?"
+20704,"Ice Lead Status","icelst","E","?"
+20705,"Iceberg Size","icebsz","E","?"
+20706,"Iceberg Shape","icebsh","E","?"
+20707,"Icedrift or Iceberg Direction","icebdr","E","?"
+20708,"Icedrift or Iceberg Speed","icebsp","F","?"
+20709,"Maximum Ice Thickness","icemax","F","?"
+20710,"Minimum Ice Thickness","icemin","F","?"
+20711,"Ice Ridge Development","icerdv","E","?"
+20712,"Land Ice","icelnd","E","?"
+20713,"Sea Direction","seadir","E","?"
+20714,"Traffic density","traden","S","?"
+20715,"Type of shipping","typshp","L","?"
+20716,"Ice Coverage Type","icecvt","E","?"
+20718,"Status of Small Bottom Object","staobj","L","?"
+20719,"ICAO code","icaocd","S","?"
+20720,"textual description","txtdes","S","?"
+20721,"Object Reference Number","objtrn","S","?"
+20722,"Object Shape","objshp","S","?"
+22484,"Category of completeness","catcnf","E","?"
+22485,"Error Ellipse","errell","A","?"
+22486,"Object classes","N/A","N/A","?"
+22487,"Security classification","N/A","N/A","?"
+22488,"Vertical Datum Shift Parameter","vershf","F","?"
+22489,"Absolute Vertical Accuracy","elvacc","F","?"
+22490,"Reflection Coefficient","reflco","F","?"
+22491,"Copyright statement","cpyrit","S","?"
+0,"###40000 comes from past s57attributes_iw.csv (Inland Waterways)",###,S,F
+40000,Update message,updmsg,S,F
diff --git a/data/s57attributes_aml.csv b/data/s57attributes_aml.csv
deleted file mode 100644
index 4aeba80..0000000
--- a/data/s57attributes_aml.csv
+++ /dev/null
@@ -1,440 +0,0 @@
-"Code","Attribute","Acronym","Attributetype","Class"
-1,Agency responsible for production,AGENCY,A,F
-2,Beacon shape,BCNSHP,E,F
-3,Building shape,BUISHP,E,F
-4,Buoy shape,BOYSHP,E,F
-5,Buried depth,BURDEP,F,F
-6,Call sign,CALSGN,S,F
-7,Category of airport/airfield,CATAIR,L,F
-8,Category of anchorage,CATACH,L,F
-9,Category of bridge,CATBRG,L,F
-10,Category of built-up area,CATBUA,E,F
-11,Category of cable,CATCBL,E,F
-12,Category of canal,CATCAN,E,F
-13,Category of cardinal mark,CATCAM,E,F
-14,Category of checkpoint,CATCHP,E,F
-15,Category of coastline,CATCOA,E,F
-16,Category of control point,CATCTR,E,F
-17,Category of conveyor,CATCON,E,F
-18,Category of coverage,CATCOV,E,F
-19,Category of crane,CATCRN,E,F
-20,Category of dam,CATDAM,E,F
-21,Category of distance mark,CATDIS,E,F
-22,Category of dock,CATDOC,E,F
-23,Category of dumping ground,CATDPG,L,F
-24,Category of  fence/wall,CATFNC,E,F
-25,Category of ferry,CATFRY,E,F
-26,Category of  fishing  facility,CATFIF,E,F
-27,Category of  fog signal,CATFOG,E,F
-28,Category of  fortified structure,CATFOR,E,F
-29,Category of gate,CATGAT,E,F
-30,Category of harbour facility,CATHAF,L,F
-31,Category of hulk,CATHLK,L,F
-32,Category of  ice,CATICE,E,F
-33,Category of installation buoy,CATINB,E,F
-34,Category of land region,CATLND,L,F
-35,Category of landmark,CATLMK,L,F
-36,Category of lateral mark,CATLAM,E,F
-37,Category of light,CATLIT,L,F
-38,Category of marine farm/culture,CATMFA,E,F
-39,Category of military practice area,CATMPA,L,F
-40,Category of mooring/warping facility,CATMOR,E,F
-41,Category of navigation line,CATNAV,E,F
-42,Category of obstruction,CATOBS,E,F
-43,Category of offshore platform,CATOFP,L,F
-44,Category of oil barrier,CATOLB,E,F
-45,Category of pile,CATPLE,E,F
-46,Category of pilot boarding place,CATPIL,E,F
-47,Category of pipeline / pipe,CATPIP,L,F
-48,Category of production area,CATPRA,E,F
-49,Category of pylon,CATPYL,E,F
-50,Category of quality of data,CATQUA,E,F
-51,Category of radar station,CATRAS,E,F
-52,Category of radar transponder beacon,CATRTB,E,F
-53,Category of radio station,CATROS,L,F
-54,Category of recommended track,CATTRK,E,F
-55,Category of rescue station,CATRSC,L,F
-56,Category of restricted area,CATREA,L,F
-57,Category of road,CATROD,E,F
-58,Category of runway,CATRUN,E,F
-59,Category of sea area,CATSEA,E,F
-60,Category of shoreline construction,CATSLC,E,F
-61,"Category of signal station, traffic",CATSIT,L,F
-62,"Category of signal station, warning",CATSIW,L,F
-63,Category of silo/tank,CATSIL,E,F
-64,Category of slope,CATSLO,E,F
-65,Category of small craft facility,CATSCF,L,F
-66,Category of special purpose mark,CATSPM,L,F
-67,Category of Traffic Separation Scheme,CATTSS,E,F
-68,Category of vegetation,CATVEG,L,F
-69,Category of water turbulence,CATWAT,E,F
-70,Category of weed/kelp,CATWED,E,F
-71,Category of wreck,CATWRK,E,F
-72,Category of zone of confidence data,CATZOC,E,F
-73,Character spacing,$SPACE,E,$
-74,Character specification,$CHARS,A,$
-75,Colour,COLOUR,L,F
-76,Colour pattern,COLPAT,L,F
-77,Communication channel,COMCHA,A,F
-78,Compass size,$CSIZE,F,$
-79,Compilation date,CPDATE,A,F
-80,Compilation scale,CSCALE,I,F
-81,Condition,CONDTN,E,F
-82,"Conspicuous, Radar",CONRAD,E,F
-83,"Conspicuous, visual",CONVIS,E,F
-84,Current velocity,CURVEL,F,F
-85,Date end,DATEND,A,F
-86,Date start,DATSTA,A,F
-87,Depth range value 1,DRVAL1,F,F
-88,Depth range value 2,DRVAL2,F,F
-89,Depth units,DUNITS,E,F
-90,Elevation,ELEVAT,F,F
-91,Estimated range of transmission,ESTRNG,F,F
-92,Exhibition condition of light,EXCLIT,E,F
-93,Exposition of sounding,EXPSOU,E,F
-94,Function,FUNCTN,L,F
-95,Height,HEIGHT,F,F
-96,Height/length units,HUNITS,E,F
-97,Horizontal accuracy,HORACC,F,F
-98,Horizontal clearance,HORCLR,F,F
-99,Horizontal length,HORLEN,F,F
-100,Horizontal width,HORWID,F,F
-101,Ice factor,ICEFAC,F,F
-102,Information,INFORM,S,F
-103,Jurisdiction,JRSDTN,E,F
-104,Justification - horizontal,$JUSTH,E,$
-105,Justification - vertical,$JUSTV,E,$
-106,Lifting capacity,LIFCAP,F,F
-107,Light characteristic,LITCHR,E,F
-108,Light visibility,LITVIS,L,F
-109,Marks navigational - System of,MARSYS,E,F
-110,Multiplicity of lights,MLTYLT,I,F
-111,Nationality,NATION,A,F
-112,Nature of construction,NATCON,L,F
-113,Nature of surface,NATSUR,L,F
-114,Nature of surface - qualifying terms,NATQUA,L,F
-115,Notice to Mariners date,NMDATE,A,F
-116,Object name,OBJNAM,S,F
-117,Orientation,ORIENT,F,F
-118,Periodic date end,PEREND,A,F
-119,Periodic date start,PERSTA,A,F
-120,Pictorial representation,PICREP,S,F
-121,Pilot district,PILDST,S,F
-122,Producing country,PRCTRY,A,F
-123,Product,PRODCT,L,F
-124,Publication reference,PUBREF,S,F
-125,Quality of sounding measurement,QUASOU,L,F
-126,Radar wave length,RADWAL,A,F
-127,Radius,RADIUS,F,F
-128,Recording date,RECDAT,A,F
-129,Recording indication,RECIND,A,F
-130,Reference year for magnetic variation,RYRMGV,A,F
-131,Restriction,RESTRN,L,F
-132,Scale maximum,SCAMAX,I,F
-133,Scale minimum,SCAMIN,I,F
-134,Scale value one,SCVAL1,I,F
-135,Scale value two,SCVAL2,I,F
-136,Sector limit one,SECTR1,F,F
-137,Sector limit two,SECTR2,F,F
-138,Shift parameters,SHIPAM,A,F
-139,Signal frequency,SIGFRQ,I,F
-140,Signal generation,SIGGEN,E,F
-141,Signal group,SIGGRP,A,F
-142,Signal period,SIGPER,F,F
-143,Signal sequence,SIGSEQ,A,F
-144,Sounding accuracy,SOUACC,F,F
-145,Sounding distance - maximum,SDISMX,I,F
-146,Sounding distance - minimum,SDISMN,I,F
-147,Source date,SORDAT,A,F
-148,Source indication,SORIND,A,F
-149,Status,STATUS,L,F
-150,Survey authority,SURATH,S,F
-151,Survey date - end,SUREND,A,F
-152,Survey date - start,SURSTA,A,F
-153,Survey type,SURTYP,L,F
-154,Symbol scaling factor,$SCALE,F,$
-155,Symbolization code,$SCODE,A,$
-156,Technique of sounding measurement,TECSOU,L,F
-157,Text string,$TXSTR,S,$
-158,Textual description,TXTDSC,S,F
-159,Tidal stream - panel values,TS_TSP,A,F
-160,"Tidal stream, current - time series values",TS_TSV,A,F
-161,Tide - accuracy of water level,T_ACWL,E,F
-162,Tide - high and low water values,T_HWLW,A,F
-163,Tide - method of tidal prediction,T_MTOD,E,F
-164,Tide - time and height differences,T_THDF,A,F
-165,"Tide, current - time interval of values",T_TINT,I,F
-166,Tide - time series values,T_TSVL,A,F
-167,Tide - value of harmonic constituents,T_VAHC,A,F
-168,Time end,TIMEND,A,F
-169,Time start,TIMSTA,A,F
-170,Tint,$TINTS,E,$
-171,Topmark/daymark shape,TOPSHP,E,F
-172,Traffic flow,TRAFIC,E,F
-173,Value of annual change in magnetic variation,VALACM,F,F
-174,Value of depth contour,VALDCO,F,F
-175,Value of local magnetic anomaly,VALLMA,F,F
-176,Value of magnetic variation,VALMAG,F,F
-177,Value of maximum range,VALMXR,F,F
-178,Value of nominal range,VALNMR,F,F
-179,Value of sounding,VALSOU,F,F
-180,Vertical accuracy,VERACC,F,F
-181,Vertical clearance,VERCLR,F,F
-182,"Vertical clearance, closed",VERCCL,F,F
-183,"Vertical clearance, open",VERCOP,F,F
-184,"Vertical clearance, safe",VERCSA,F,F
-185,Vertical datum,VERDAT,E,F
-186,Vertical length,VERLEN,F,F
-187,Water level effect,WATLEV,E,F
-188,Category of Tidal stream,CAT_TS,E,F
-189,Positional accuracy units,PUNITS,E,F
-300,Information in national language,NINFOM,S,N
-301,Object name in national language,NOBJNM,S,N
-302,Pilot district in national language,NPLDST,S,N
-303,Text string in national language,$NTXST,S,N
-304,Textual description in national language,NTXTDS,S,N
-400,Horizontal datum,HORDAT,E,S
-401,Positional Accuracy,POSACC,F,S
-402,Quality of position,QUAPOS,E,S
-20484,"Abandonment Date","databa","A","?"
-20485,"Attenuation","attutn","F","?"
-20486,"Beam of Vessel","vesbem","F","?"
-20487,"Bearing","bearng","F","?"
-20488,"Blind Zone","blndzn","A","?"
-20489,"Breaker Type","brktyp","E","?"
-20490,"Density","bulkdn","F","?"
-20491,"Burial Mechanism","brmchm","E","?"
-20492,"Burial Percentage","brpctg","I","?"
-20493,"Burial Period","brperd","I","?"
-20494,"Burial Probability","brprob","E","?"
-20495,"Cardinal Point Orientation","orcard","E","?"
-20496,"Category of administration area","catadm","E","?"
-20497,"Category of airspace restriction","catasr","E","?"
-20498,"Category of bedrock","N/A","N/A","?"
-20499,"Bottom Feature Classification","catbot","E","?"
-20500,"Category of coastguard station","catcgs","E","?"
-20501,"Category of controlled airspace","catcas","E","?"
-20502,"Fishing Activity","catfsh","E","?"
-20503,"Type of Imagery","catimg","L","?"
-20504,"Category of marine management area","catmma","E","?"
-20505,"Category of maritime safety information","catmsi","E","?"
-20506,"Category of military exercise airspace ","catmea","E","?"
-20507,"Category of patrol area","catpat","E","?"
-20508,"Category of reporting/radio calling-in point","catrep","E","?"
-20509,"Category of regulated airspace","N/A","N/A","?"
-20510,"Category of territorial sea baseline","catsbl","E","?"
-20511,"Trafficability","cattrf","E","?"
-20512,"Command System","comsys","S","?"
-20515,"Controlled airspace class designation","caircd","E","?"
-20516,"Controlling authority","authty","S","?"
-20517,"Current Scour Dimensions","scrdim","A","?"
-20518,"Dangerous Marine and Land Life","dgmrlf","L","?"
-20519,"Date Sunk","datsnk","A","?"
-20520,"Debris Field","debfld","A","?"
-20521,"Depth of Activity","depact","F","?"
-20522,"Depth of Layer","deplyr","F","?"
-20523,"Distance from Small Bottom Object","discon","F","?"
-20524,"Diver’s Thrust Test Depth","dttdep","E","?"
-20525,"Diver’s Thrust Test Number","dttnum","I","?"
-20526,"Diving Activity","divact","E","?"
-20527,"Draught of Vessel","vesdgh","F","?"
-20528,"Exit Usability","exitus","E","?"
-20529,"Field Name","fldnam","S","?"
-20530,"First Detection Year","datfir","A","?"
-20531,"First Sensor","senfir","E","?"
-20532,"First Source","sorfir","E","?"
-20533,"Foliar Index","folinx","F","?"
-20534,"Gas Content","gascon","I","?"
-20535,"General Water Depth","gendep","I","?"
-20536,"Gradient","gradnt","E","?"
-20537,"Grain Size","grnsiz","F","?"
-20538,"Inclination","incltn","F","?"
-20539,"Internal Data Record Identification Number","N/A","N/A","?"
-20540,"Last Detection Year","datlst","A","?"
-20541,"Last Sensor","senlst","E","?"
-20542,"Last Source","sorlst","E","?"
-20543,"Lay Platform","layptm","E","?"
-20544,"Lay Reference Number","layrfn","S","?"
-20545,"Lay Time","laytim","A","?"
-20546,"Layer Number","laynum","I","?"
-20547,"Legal Status","legsta","S","?"
-20548,"Length of Vessel","veslen","F","?"
-20549,"Magnetic Anomaly Detector (MAD) Signature","madsig","E","?"
-20550,"Magnetic Intensity","magint","I","?"
-20551,"Mean Shear Strength","msstrg","F","?"
-20552,"Migration Direction","migdir","I","?"
-20553,"Migration Speed","migspd","F","?"
-20554,"Milec Density","milden","E","?"
-20555,"Mine Index Mine Case","mnimnc","E","?"
-20556,"Mine Index Mine Type","mnimnt","L","?"
-20557,"Mine Reference Number","minern","S","?"
-20558,"Mine-Hunting Classification","mhclas","E","?"
-20559,"Minehunting System","mnhsys","S","?"
-20560,"Minesweeping System","mnssys","S","?"
-20561,"Mission Classification","miscls","E","?"
-20562,"Mission Comments","miscom","S","?"
-20563,"Mission Date","misdat","A","?"
-20564,"Mission Name","misnme","S","?"
-20565,"MWDC Reference Number","mwdcrn","S","?"
-20566,"Nature of Geological Layer","natsed","E","?"
-20567,"Navigation System","navsys","S","?"
-20568,"NOMBO Density","nomden","E","?"
-20569,"Not Found","notfnd","S","?"
-20570,"Number of Previous Observations","nmprob","I","?"
-20571,"Operator","oprtor","S","?"
-20572,"Orientation of Best Observation","orbobn","F","?"
-20573,"Origin of Data","orgdat","E","?"
-20574,"Originator","orgntr","S","?"
-20575,"Porosity","porsty","I","?"
-20576,"Quality of Beach Data","quabch","A","?"
-20577,"Re-entered Date","datren","A","?"
-20578,"Re-suspended Date","datres","A","?"
-20579,"Reverberation","revebn","E","?"
-20580,"Safety Zone","N/A","N/A","?"
-20581,"Sample Retained","samret","S","?"
-20582,"Seabed Coverage","sbdcov","I","?"
-20583,"Ships Speed","shpspd","F","?"
-20584,"Sonar Frequency","snrfrq","E","?"
-20585,"Sonar Range Scale","snrrsc","F","?"
-20586,"Sonar Reflectivity","snrflc","E","?"
-20587,"Sonar Signal Strength","sonsig","E","?"
-20588,"Sound Velocity","sndvel","F","?"
-20589,"Sounding Datum","soudat","E","?"
-20590,"Spudded Date","datspd","A","?"
-20592,"Steepest Face Orientation","stfotn","F","?"
-20593,"Strength According to Richter Scale","ricsca","I","?"
-20594,"Strength of Magnetic Anomaly","magany","E","?"
-20595,"Suitability for ACV Use","stbacv","E","?"
-20596,"Surf Height","srfhgt","F","?"
-20597,"Surf Zone","srfzne","I","?"
-20598,"Survey Date and Time","surdat","A","?"
-20599,"Suspension Date","datsus","A","?"
-20600,"Swell Height","swlhgt","F","?"
-20601,"Tidal Range","tdlrng","F","?"
-20602,"Time of Year","timeyr","L","?"
-20603,"Tonnage","tonage","I","?"
-20604,"Towed Body Depth","twdbdp","F","?"
-20605,"Type of military activity","milact","L","?"
-20606,"Type of Tonnage","typton","E","?"
-20607,"Type of Wreck","typewk","E","?"
-20608,"Underwater Reference Mark","unwrfm","E","?"
-20609,"Unique ID from a Navigational Product","N/A","N/A","?"
-20610,"Water Clarity","watclr","F","?"
-20611,"Wavelength","wavlen","F","?"
-20612,"Weight Bearing Capability","wbrcap","I","?"
-20613,"Width (left)","lftwid","F","?"
-20614,"Width (right)","rgtwid","F","?"
-20615,"Contour Type","hypcat","E","?"
-20616,"Sounding Velocity","souvel","E","?"
-20617,"Access Restriction","accres","S","?"
-20618,"Approach","apprch","S","?"
-20619,"Category of Beach","catbch","E","?"
-20620,"Clearance Percentage","clperc","I","?"
-20621,"Communications","commns","L","?"
-20622,"Confidence Level","conlev","F","?"
-20624,"Exit Description","extdes","S","?"
-20625,"Industry","indtry","S","?"
-20626,"Landing Conditions","lndcon","S","?"
-20627,"Leisure Activity","lsract","S","?"
-20628,"Logistics","logtcs","L","?"
-20629,"Manoeuvring","manvrg","S","?"
-20630,"Mine Threat Density","mntden","I","?"
-20631,"Multiple Contacts","mulcon","I","?"
-20632,"Navigational Description","navdes","S","?"
-20633,"Navigational Difficulty","navdif","E","?"
-20634,"Number of Remaining Mines","numrmn","I","?"
-20635,"Pier Contact Details","pierod","S","?"
-20636,"Pier Description","pierdn","S","?"
-20637,"Prairies Density","prsden","I","?"
-20638,"Probability for Remaining Mines","prbrmn","F","?"
-20639,"Remaining Mines Likely, Maximum Number","rmnlmn","I","?"
-20640,"Self Protection (Air)","sfptna","E","?"
-20641,"Self Protection (Near Defence)","sptnnd","E","?"
-20642,"Self Protection (Surface)","sfptns","E","?"
-20643,"Sensor Coverage","sencov","S","?"
-20644,"Simple Initial Threat","sminth","F","?"
-20645,"Target Reference Weight","tgrfwt","E","?"
-20646,"Tidal Type","tdltyp","E","?"
-20647,"Type of Resource Location","typres","E","?"
-20648,"Undetectable Mines Ratio","undmnr","F","?"
-20649,"Undetectable Mines Ratio with Burial","umnrwb","F","?"
-20650,"Undetectable Mines Ratio without Burial","umrwob","F","?"
-20651,"Weapon Coverage","wpncov","S","?"
-20652,"On Sonar","onsonr","E","?"
-20653,"HF Bottom Loss","hfbmls","F","?"
-20654,"LF Bottom Loss","lfbmls","F","?"
-20655,"Detection Probability","dtprob","F","?"
-20656,"Disposal Probability","dsprob","F","?"
-20657,"Classification Probability","clprob","F","?"
-20658,"Characteristic Detection Width (A)","cswidt","I","?"
-20659,"Characteristic Detection Probability (B)","csprob","F","?"
-20660,"Zone Colour","znecol","E","?"
-20661,"Reverberation Frequency","revfqy","F","?"
-20662,"Reverberation Grazing Angle","revgan","F","?"
-20663,"International Defence Organisation (IDO) status","secido","E","?"
-20664,"Protective Marking","secpmk","E","?"
-20665,"Owner Authority","secown","S","?"
-20666,"Caveat ","seccvt","S","?"
-20667,"Species","spcies","S","?"
-20668,"Swept date","swpdat","A","?"
-20669,"Runway length","rwylen","I","?"
-20670,"Active period","actper","S","?"
-20671,"Maximum altitude","maxalt","I","?"
-20672,"Minimum altitude","minalt","I","?"
-20673,"Maximum Flight Level","maxftl","I","?"
-20674,"Minimum Flight Level","minftl","I","?"
-20675,"Bottom Vertical Safety Separation","bverss","I","?"
-20676,"Minimum Safe Depth","mindep","I","?"
-20677,"Interpolated line characteristic","linech","E","?"
-20678,"Identification","identy","S","?"
-20679,"Route Classification","rclass","E","?"
-20680,"Population","popltn","I","?"
-20681,"Surface Threat","surtht","E","?"
-20682,"Heading-Up Bearing","upbear","F","?"
-20683,"Heading-Down Bearing","dnbear","F","?"
-20684,"Ice Concentration","icencn","I","?"
-20685,"Danger height","dgrhgt","I","?"
-20686,"Depth Restriction","depres","S","?"
-20687,"Area Category","arecat","E","?"
-20688,"Existence of Restricted Area","exzres","E","?"
-20689,"Target Strength","tarstg","I","?"
-20690,"Qualification of Radar Coverage","quarad","I","?"
-20691,"Contact Details","condet","S","?"
-20692,"Limit of Anchors and Chains","limanc","F","?"
-20693,"CCM Index","ccmidx","I","?"
-20694,"Military Load Classification","mlclas","E","?"
-20695,"MGS Type","mgstyp","E","?"
-20696,"Ice Attribute Concentration Total","iceact","E","?"
-20697,"Ice Stage of Development","icesod","E","?"
-20698,"Ice Advisory Code","iceadc","S","?"
-20699,"Number of Icebergs in Area","icebnm","I","?"
-20700,"Ice Line Category","icelnc","E","?"
-20701,"Ice Polynya Type","icepty","E","?"
-20702,"Ice Polynya Status","icepst","E","?"
-20703,"Ice Lead Type","icelty","E","?"
-20704,"Ice Lead Status","icelst","E","?"
-20705,"Iceberg Size","icebsz","E","?"
-20706,"Iceberg Shape","icebsh","E","?"
-20707,"Icedrift or Iceberg Direction","icebdr","E","?"
-20708,"Icedrift or Iceberg Speed","icebsp","F","?"
-20709,"Maximum Ice Thickness","icemax","F","?"
-20710,"Minimum Ice Thickness","icemin","F","?"
-20711,"Ice Ridge Development","icerdv","E","?"
-20712,"Land Ice","icelnd","E","?"
-20713,"Sea Direction","seadir","E","?"
-20714,"Traffic density","traden","S","?"
-20715,"Type of shipping","typshp","L","?"
-20716,"Ice Coverage Type","icecvt","E","?"
-20718,"Status of Small Bottom Object","staobj","L","?"
-20719,"ICAO code","icaocd","S","?"
-20720,"textual description","txtdes","S","?"
-20721,"Object Reference Number","objtrn","S","?"
-20722,"Object Shape","objshp","S","?"
-22484,"Category of completeness","catcnf","E","?"
-22485,"Error Ellipse","errell","A","?"
-22486,"Object classes","N/A","N/A","?"
-22487,"Security classification","N/A","N/A","?"
-22488,"Vertical Datum Shift Parameter","vershf","F","?"
-22489,"Absolute Vertical Accuracy","elvacc","F","?"
-22490,"Reflection Coefficient","reflco","F","?"
-22491,"Copyright statement","cpyrit","S","?"
diff --git a/data/s57attributes_iw.csv b/data/s57attributes_iw.csv
deleted file mode 100644
index d696ce3..0000000
--- a/data/s57attributes_iw.csv
+++ /dev/null
@@ -1,236 +0,0 @@
-"Code","Attribute","Acronym","Attributetype","Class"
-1,Agency responsible for production,AGENCY,A,F
-2,Beacon shape,BCNSHP,E,F
-3,Building shape,BUISHP,E,F
-4,Buoy shape,BOYSHP,E,F
-5,Buried depth,BURDEP,F,F
-6,Call sign,CALSGN,S,F
-7,Category of airport/airfield,CATAIR,L,F
-8,Category of anchorage,CATACH,L,F
-9,Category of bridge,CATBRG,L,F
-10,Category of built-up area,CATBUA,E,F
-11,Category of cable,CATCBL,E,F
-12,Category of canal,CATCAN,E,F
-13,Category of cardinal mark,CATCAM,E,F
-14,Category of checkpoint,CATCHP,E,F
-15,Category of coastline,CATCOA,E,F
-16,Category of control point,CATCTR,E,F
-17,Category of conveyor,CATCON,E,F
-18,Category of coverage,CATCOV,E,F
-19,Category of crane,CATCRN,E,F
-20,Category of dam,CATDAM,E,F
-21,Category of distance mark,CATDIS,E,F
-22,Category of dock,CATDOC,E,F
-23,Category of dumping ground,CATDPG,L,F
-24,Category of fence/wall,CATFNC,E,F
-25,Category of ferry,CATFRY,E,F
-26,Category of fishing  facility,CATFIF,E,F
-27,Category of fog signal,CATFOG,E,F
-28,Category of fortified structure,CATFOR,E,F
-29,Category of gate,CATGAT,E,F
-30,Category of harbour facility,CATHAF,L,F
-31,Category of hulk,CATHLK,L,F
-32,Category of ice,CATICE,E,F
-33,Category of installation buoy,CATINB,E,F
-34,Category of land region,CATLND,L,F
-35,Category of landmark,CATLMK,L,F
-36,Category of lateral mark,CATLAM,E,F
-37,Category of light,CATLIT,L,F
-38,Category of marine farm/culture,CATMFA,E,F
-39,Category of military practice area,CATMPA,L,F
-40,Category of mooring/warping facility,CATMOR,E,F
-41,Category of navigation line,CATNAV,E,F
-42,Category of obstruction,CATOBS,E,F
-43,Category of offshore platform,CATOFP,L,F
-44,Category of oil barrier,CATOLB,E,F
-45,Category of pile,CATPLE,E,F
-46,Category of pilot boarding place,CATPIL,E,F
-47,Category of pipeline / pipe,CATPIP,L,F
-48,Category of production area,CATPRA,E,F
-49,Category of pylon,CATPYL,E,F
-50,Category of quality of data,CATQUA,E,F
-51,Category of radar station,CATRAS,E,F
-52,Category of radar transponder beacon,CATRTB,E,F
-53,Category of radio station,CATROS,L,F
-54,Category of recommended track,CATTRK,E,F
-55,Category of rescue station,CATRSC,L,F
-56,Category of restricted area,CATREA,L,F
-57,Category of road,CATROD,E,F
-58,Category of runway,CATRUN,E,F
-59,Category of sea area,CATSEA,E,F
-60,Category of shoreline construction,CATSLC,E,F
-61,"Category of signal station, traffic",CATSIT,L,F
-62,"Category of signal station, warning",CATSIW,L,F
-63,Category of silo/tank,CATSIL,E,F
-64,Category of slope,CATSLO,E,F
-65,Category of small craft facility,CATSCF,L,F
-66,Category of special purpose mark,CATSPM,L,F
-67,Category of Traffic Separation Scheme,CATTSS,E,F
-68,Category of vegetation,CATVEG,L,F
-69,Category of water turbulence,CATWAT,E,F
-70,Category of weed/kelp,CATWED,E,F
-71,Category of wreck,CATWRK,E,F
-72,Category of zone of confidence data,CATZOC,E,F
-73,Character spacing,$SPACE,E,$
-74,Character specification,$CHARS,A,$
-75,Colour,COLOUR,L,F
-76,Colour pattern,COLPAT,L,F
-77,Communication channel,COMCHA,A,F
-78,Compass size,$CSIZE,F,$
-79,Compilation date,CPDATE,A,F
-80,Compilation scale,CSCALE,I,F
-81,Condition,CONDTN,E,F
-82,"Conspicuous, Radar",CONRAD,E,F
-83,"Conspicuous, visual",CONVIS,E,F
-84,Current velocity,CURVEL,F,F
-85,Date end,DATEND,A,F
-86,Date start,DATSTA,A,F
-87,Depth range value 1,DRVAL1,F,F
-88,Depth range value 2,DRVAL2,F,F
-89,Depth units,DUNITS,E,F
-90,Elevation,ELEVAT,F,F
-91,Estimated range of transmission,ESTRNG,F,F
-92,Exhibition condition of light,EXCLIT,E,F
-93,Exposition of sounding,EXPSOU,E,F
-94,Function,FUNCTN,L,F
-95,Height,HEIGHT,F,F
-96,Height/length units,HUNITS,E,F
-97,Horizontal accuracy,HORACC,F,F
-98,Horizontal clearance,HORCLR,F,F
-99,Horizontal length,HORLEN,F,F
-100,Horizontal width,HORWID,F,F
-101,Ice factor,ICEFAC,F,F
-102,Information,INFORM,S,F
-103,Jurisdiction,JRSDTN,E,F
-104,Justification - horizontal,$JUSTH,E,$
-105,Justification - vertical,$JUSTV,E,$
-106,Lifting capacity,LIFCAP,F,F
-107,Light characteristic,LITCHR,E,F
-108,Light visibility,LITVIS,L,F
-109,Marks navigational - System of,MARSYS,E,F
-110,Multiplicity of lights,MLTYLT,I,F
-111,Nationality,NATION,A,F
-112,Nature of construction,NATCON,L,F
-113,Nature of surface,NATSUR,L,F
-114,Nature of surface - qualifying terms,NATQUA,L,F
-115,Notice to Mariners date,NMDATE,A,F
-116,Object name,OBJNAM,S,F
-117,Orientation,ORIENT,F,F
-118,Periodic date end,PEREND,A,F
-119,Periodic date start,PERSTA,A,F
-120,Pictorial representation,PICREP,S,F
-121,Pilot district,PILDST,S,F
-122,Producing country,PRCTRY,A,F
-123,Product,PRODCT,L,F
-124,Publication reference,PUBREF,S,F
-125,Quality of sounding measurement,QUASOU,L,F
-126,Radar wave length,RADWAL,A,F
-127,Radius,RADIUS,F,F
-128,Recording date,RECDAT,A,F
-129,Recording indication,RECIND,A,F
-130,Reference year for magnetic variation,RYRMGV,A,F
-131,Restriction,RESTRN,L,F
-132,Scale maximum,SCAMAX,I,F
-133,Scale minimum,SCAMIN,I,F
-134,Scale value one,SCVAL1,I,F
-135,Scale value two,SCVAL2,I,F
-136,Sector limit one,SECTR1,F,F
-137,Sector limit two,SECTR2,F,F
-138,Shift parameters,SHIPAM,A,F
-139,Signal frequency,SIGFRQ,I,F
-140,Signal generation,SIGGEN,E,F
-141,Signal group,SIGGRP,A,F
-142,Signal period,SIGPER,F,F
-143,Signal sequence,SIGSEQ,A,F
-144,Sounding accuracy,SOUACC,F,F
-145,Sounding distance - maximum,SDISMX,I,F
-146,Sounding distance - minimum,SDISMN,I,F
-147,Source date,SORDAT,A,F
-148,Source indication,SORIND,A,F
-149,Status,STATUS,L,F
-150,Survey authority,SURATH,S,F
-151,Survey date - end,SUREND,A,F
-152,Survey date - start,SURSTA,A,F
-153,Survey type,SURTYP,L,F
-154,Symbol scaling factor,$SCALE,F,$
-155,Symbolization code,$SCODE,A,$
-156,Technique of sounding measurement,TECSOU,L,F
-157,Text string,$TXSTR,S,$
-158,Textual description,TXTDSC,S,F
-159,Tidal stream - panel values,TS_TSP,A,F
-160,"Tidal stream, current - time series values",TS_TSV,A,F
-161,Tide - accuracy of water level,T_ACWL,E,F
-162,Tide - high and low water values,T_HWLW,A,F
-163,Tide - method of tidal prediction,T_MTOD,E,F
-164,Tide - time and height differences,T_THDF,A,F
-165,"Tide, current - time interval of values",T_TINT,I,F
-166,Tide - time series values,T_TSVL,A,F
-167,Tide - value of harmonic constituents,T_VAHC,A,F
-168,Time end,TIMEND,A,F
-169,Time start,TIMSTA,A,F
-170,Tint,$TINTS,E,$
-171,Topmark/daymark shape,TOPSHP,E,F
-172,Traffic flow,TRAFIC,E,F
-173,Value of annual change in magnetic variation,VALACM,F,F
-174,Value of depth contour,VALDCO,F,F
-175,Value of local magnetic anomaly,VALLMA,F,F
-176,Value of magnetic variation,VALMAG,F,F
-177,Value of maximum range,VALMXR,F,F
-178,Value of nominal range,VALNMR,F,F
-179,Value of sounding,VALSOU,F,F
-180,Vertical accuracy,VERACC,F,F
-181,Vertical clearance,VERCLR,F,F
-182,"Vertical clearance, closed",VERCCL,F,F
-183,"Vertical clearance, open",VERCOP,F,F
-184,"Vertical clearance, safe",VERCSA,F,F
-185,Vertical datum,VERDAT,E,F
-186,Vertical length,VERLEN,F,F
-187,Water level effect,WATLEV,E,F
-188,Category of Tidal stream,CAT_TS,E,F
-189,Positional accuracy units,PUNITS,E,F
-300,Information in national language,NINFOM,S,N
-301,Object name in national language,NOBJNM,S,N
-302,Pilot district in national language,NPLDST,S,N
-303,Text string in national language,$NTXST,S,N
-304,Textual description in national language,NTXTDS,S,N
-400,Horizontal datum,HORDAT,E,S
-401,Positional Accuracy,POSACC,F,S
-402,Quality of position,QUAPOS,E,S
-17000,Category of Anchorage area,catach,L,F
-17001,Category of distance mark,catdis,E,F
-17002,Category of signal station trafficcatsit,catsit,L,F
-17003,Category of signal station warning,catsiw,L,F
-17004,Restriction,restrn,L,F
-17005,Vertical datum,verdat,E,F
-17006,Category of bridge,catbrg,L,F
-17007,Category of ferry,catfry,L,F
-17008,Category of harbour facilities,cathaf,L,F
-17009,"Marks navigational � System of",marsys,E,F
-17050,Additional mark,addmrk,L,F
-17051,Category of bank,catbnk,E,F
-17052,Category of notice mark,catnmk,E,F
-17055,Class of dangerous cargo,clsdng,E,F
-17056,Direction of impact,dirimp,L,F
-17057,Distance from bank,disbk1,F,F
-17058,Distance from bank,disbk2,F,F
-17059,"Distance of impact, upstream",disipu,F,F
-17060,"Distance of impact, downstream",disipd,F,F
-17061,Elevation 1,eleva1,F,F
-17062,Elevation 2,eleva2,F,F
-17063,Function of notice mark,fnctnm,E,F
-17064,Waterway distance,wtwdis,F,F
-17065,Bunker vessel,bunves,E,F
-17066,Category of berth,catbrt,L,F
-17067,Category of bunker,catbun,L,F
-17068,Category of CEMT class,catccl,L,F
-17069,Category of communication,catcom,L,F
-17070,Category of harbour area,cathbr,L,F
-17071,Category of refuse dump,catrfd,L,F
-17072,Category of terminal,cattml,L,F
-17073,Communication,comctn,S,F
-17074,"Horizontal clearance, length",horcll,F,F
-17075,"Horizontal clearance, width",horclw,F,F
-17076,Transshipping goods,trshgd,L,F
-17077,UN Location Code,unlocd,S,F
-17112,Category of waterway mark,catwwm,E,F
-40000,Update message,updmsg,S,F
diff --git a/data/s57objectclasses.csv b/data/s57objectclasses.csv
index 24b5e43..7e38654 100644
--- a/data/s57objectclasses.csv
+++ b/data/s57objectclasses.csv
@@ -8,7 +8,7 @@
 7,"Beacon, lateral",BCNLAT,BCNSHP;CATLAM;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
 8,"Beacon, safe water",BCNSAW,BCNSHP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
 9,"Beacon, special purpose/general",BCNSPP,BCNSHP;CATSPM;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-10,Berth,BERTHS,DATEND;DATSTA;DRVAL1;NOBJNM;OBJNAM;PEREND;PERSTA;QUASOU;SOUACC;STATUS;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
+10,Berth,BERTHS,DATEND;DATSTA;DRVAL1;NOBJNM;OBJNAM;PEREND;PERSTA;QUASOU;SOUACC;STATUS;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
 11,Bridge,BRIDGE,CATBRG;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HORACC;HORCLR;NATCON;NOBJNM;OBJNAM;VERACC;VERCCL;VERCLR;VERCOP;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
 12,"Building, single",BUISGL,BUISHP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;FUNCTN;HEIGHT;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
 13,Built-up area,BUAARE,CATBUA;CONDTN;CONRAD;CONVIS;HEIGHT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
@@ -23,7 +23,7 @@
 22,"Cable, submarine",CBLSUB,BURDEP;CATCBL;CONDTN;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;STATUS;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
 23,Canal,CANALS,CATCAN;CONDTN;DATEND;DATSTA;HORACC;HORCLR;HORWID;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
 24,Canal bank,CANBNK,CONDTN;DATEND;DATSTA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-25,Cargo transshipment area,CTSARE,DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
+25,Cargo transshipment area,CTSARE,DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
 26,Causeway,CAUSWY,CONDTN;NATCON;NOBJNM;OBJNAM;STATUS;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
 27,Caution area,CTNARE,DATEND;DATSTA;PEREND;PERSTA;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
 28,Checkpoint,CHKPNT,CATCHP;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
@@ -41,7 +41,7 @@
 40,Deep water route centerline,DWRTCL,CATTRK;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
 41,Deep water route part,DWRTPT,DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;RESTRN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
 42,Depth area,DEPARE,DRVAL1;DRVAL2;QUASOU;SOUACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-43,Depth contour,DEPCNT,VALDCO;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
+43,Depth contour,DEPCNT,VALDCO;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;hypcat;,G,Line;
 44,Distance mark,DISMAR,CATDIS;DATEND;DATSTA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
 45,Dock area,DOCARE,CATDOC;CONDTN;DATEND;DATSTA;HORACC;HORCLR;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
 46,Dredged area,DRGARE,DRVAL1;DRVAL2;NOBJNM;OBJNAM;QUASOU;RESTRN;SOUACC;TECSOU;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
@@ -50,7 +50,7 @@
 49,Dyke,DYKCON,CONDTN;CONRAD;DATEND;DATSTA;HEIGHT;NATCON;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
 50,Exclusive Economic Zone,EXEZNE,NATION;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
 51,Fairway,FAIRWY,DATEND;DATSTA;DRVAL1;NOBJNM;OBJNAM;ORIENT;QUASOU;RESTRN;SOUACC;STATUS;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-52,Fence/wall,FNCLNE,CATFNC;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;HEIGHT;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
+52,Fence/wall,FNCLNE,CATFNC;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;HEIGHT;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
 53,Ferry route,FERYRT,CATFRY;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
 54,Fishery zone,FSHZNE,NATION;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
 55,Fishing facility,FSHFAC,CATFIF;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
@@ -118,7 +118,7 @@
 117,Runway,RUNWAY,CATRUN;CONDTN;CONVIS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
 118,Sand waves,SNDWAV,VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
 119,Sea area / named water area,SEAARE,CATSEA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-120,Sea-plane landing area,SPLARE,NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;VALDCO;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
+120,Sea-plane landing area,SPLARE,NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
 121,Seabed area,SBDARE,COLOUR;NATQUA;NATSUR;WATLEV;OBJNAM;NOBJNM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
 122,Shoreline Construction,SLCONS,CATSLC;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;HORACC;HORCLR;HORLEN;HORWID;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
 123,"Signal station, traffic",SISTAT,CATSIT;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
@@ -159,6 +159,9 @@
 158,Weed/Kelp,WEDKLP,CATWED;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
 159,Wreck,WRECKS,CATWRK;CONRAD;CONVIS;EXPSOU;HEIGHT;NOBJNM;OBJNAM;QUASOU;SOUACC;STATUS;TECSOU;VALSOU;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
 160,Tidal stream - flood/ebb,TS_FEB,CAT_TS;CURVEL;DATEND;DATSTA;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
+161,Archipelagix Sea Lane,ARCSLN,DATEND;DATSTA;NATION;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
+162,Archipelagix Sea Lane axis,ASLXIS,DATEND;DATSTA;NATION;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
+163,New object,NEWOBJ,CLSDEF;CLSNAM;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;NATION;NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;WATLEV;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;SYMINS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;Point;
 300,Accuracy of data,M_ACCY,HORACC;POSACC;SOUACC;VERACC;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
 301,Compilation scale of data,M_CSCL,CSCALE;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
 302,Coverage,M_COVR,CATCOV;,INFORM;NINFOM;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
@@ -180,3 +183,105 @@
 502,Cartographic symbol,$CSYMB,ORIENT;$SCALE;$SCODE;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
 503,Compass,$COMPS,$CSIZE;RYRMGV;VALACM;VALMAG;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
 504,Text,$TEXTS,$CHARS;COLOUR;$JUSTH;$JUSTV;$NTXST;$SPACE;$TXSTR;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
+0,"###Codes in the 17xxx range come from past s57objectclasses_iw.csv (Inland Waterways)",,,,,
+17000,Anchor berth,achbrt,catach;clsdng;comctn;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RADIUS;restrn;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
+17001,Anchorage area,achare,catach;clsdng;comctn;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;restrn;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
+17002,Canal bank,canbnk,catbnk;CONRAD;DATEND;DATSTA;NATSUR;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;
+17003,Depth area,depare,DRVAL1;DRVAL2;eleva1;eleva2;wtwdis;QUASOU;SOUACC;verdat;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;Area;
+17004,Distance mark,dismar,catdis;DATEND;DATSTA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17005,Restricted area,resare,CATREA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;restrn;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17006,River bank,rivbnk,catbnk;CONRAD;NATSUR;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;
+17007,Signal station traffic,sistat,catsit;COMCHA;DATEND;DATSTA;dirimp;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17008,Signal station warning,sistaw,catsiw;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17009,Top Mark,topmar,COLOUR;COLPAT;HEIGHT;marsys;STATUS;TOPSHP;VERACC;verdat;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17010,Berth berths,berths,catbrt;clsdng;comctn;DATEND;DATSTA;DRVAL1;NOBJNM;OBJNAM;PEREND;PERSTA;QUASOU;SOUACC;STATUS;trshgd;verdat;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Line;Area;
+17011,"Bridge","bridge",catbrg;comctn;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HORACC;HORCLR;NATCON;NOBJNM;OBJNAM;TIMEND;TIMSTA;VERACC;VERCCL;VERCLR;VERCOP;verdat;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Line;Area;
+17012,Cable overhead,cblohd,CATCBL;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ICEFAC;NOBJNM;OBJNAM;STATUS;VERACC;VERCLR;VERCSA;verdat;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;RECDAT;RECIND;,SORDAT;SORIND;,G,Line;
+17013,Ferry route,feryrt,catfry;comctn;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;Area;
+17014,Harbour Area,hrbare,cathbr;comctn;NOBJNM;OBJNAM;STATUS;unlocd;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17015,Harbour Facilities,hrbfac,cathaf;CONDTN;DATEND;DATSTA;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
+17016,Lock Basin,lokbsn,HORACC;horcll;horclw;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17017,Radio calling-in point,rdocal,catcom;comctn;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;STATUS;TRAFIC;dirimp;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Line;
+17018,Navigational system of marks,m_nsys,marsys;ORIENT;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17050,Notice mark,notmrk,catnmk;fnctnm;dirimp;disipd;disipu;disbk1;disbk2;addmrk;marsys;ORIENT;CONDTN;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17051,Waterway axis,wtwaxs,catccl;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;
+17052,Waterway profile,wtwprf,wtwdis;HEIGHT;verdat;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Line;
+17053,Bridge area,brgare,comctn;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17054,Bunker station,bunsta,bunves;catbun;comctn;NOBJNM;OBJNAM;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17055,Communication Area,comare,catcom;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;STATUS;TIMEND;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17056,Harbour Basin,hrbbsn,HORACC;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17057,Lock area,lokare,comctn;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17058,Lock basin part,lkbspt,HORACC;horcll;horclw;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17059,Port Area,prtare,comctn;NOBJNM;OBJNAM;STATUS;unlocd;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
+17060,Beacon water-way,bcnwtw,BCNSHP;catwwm;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;dirimp;ELEVAT;HEIGHT;marsys;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;verdat;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17061,Buoy water-way,boywtw,BOYSHP;catwwm;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;marsys;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17062,Refuse dump,refdmp,catrfd;comctn;NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17063,Route planning point,rtplpt,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
+17064,Terminal,termnl,cattml;comctn;NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;trshgd;unlocd;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
+17065,Turning basin,trnbsn,HORCLR;NOBJNM;STATUS;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
+0,"###Codes in the 20xxx and 21xxx range come from past s57objectclasses_aml.csv (Additional_Military_Layers)",,,,,
+20484,"ATS Route Centreline","atsctl","authty;linech;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
+20485,"Airspace Restriction","airres + catasr","authty;catasr;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20486,"Area of Imagery Coverage","imgare","bearng;catimg;ELEVAT;HUNITS;orgntr;SUREND;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20487,"Beach Exit","bchext","ccmidx;exitus;gradnt;HORCLR;HORLEN;HORWID;HUNITS;VERCSA;wbrcap","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L"
+20488,"Beach Profile","bchprf","bearng;gradnt;SUREND","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
+20489,"Beach Survey","bchare","accres;brktyp;ccmidx;dgmrlf;HORLEN;HORWID;HUNITS;quabch;orgntr;srfhgt;srfzne;stbacv;SUREND;SURSTA;swlhgt;tdlrng;tdltyp","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P   A   "
+20490,"Bedrock area","bedare","N/A","N/A",,"G","A"
+20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
+20492,"Centre Line","centre","N/A","N/A",,"G","L"
+20494,"Contact History","histob","orgntr;surdat;SUREND","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
+20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
+20496,"Diving Location","divloc","depact;divact;DUNITS;OBJNAM;NOBJNM;timeyr;watclr","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
+20497,"Drinking Water Location","watloc","N/A","N/A",,"G","P"
+20498,"Drop Zone","drpzne","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
+20499,"Environmentally Sensitive Area","envare","authty;legsta;OBJNAM;NOBJNM;PEREND;PERSTA","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A;P"
+20500,"Fishing Activity Area","fshare","catfsh;STATUS;timeyr","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20501,"Impact Scour","iscour","datfir;datlst;depwat;DUNITS;gendep;HORLEN;HORWID;HUNITS;NATQUA;NATSUR;NOBJNM;OBJNAM;orcard;ORIENT;QUASOU;senfir;senlst;sonsig;sorfir;sorlst;SOUACC;soudat;STATUS;TECSOU;VALSOU;VERLEN;WATLEV","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
+20502,"Landing Area","lngare","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20503,"Landing Place","lndplc","gradnt;STATUS;wbrcap","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
+20504,"Landing Point","lndpnt","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
+20505,"Landing Site","lndste","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20506,"Landing Strip","lndstp","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20507,"Landing Zone","lndzne","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20508,"Marine management area","marman + catmma","actper;authty;catmma;identy;linech;NOBJNM;OBJNAM;NATION;spcies;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20509,"Maritime Safety Information area","msiare","catmsi;condet;NATION;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20510,"MCM Area","mcmare","mhclas;milden;nomden","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20513,"Patrol area","patare + catpat","authty;catpat;identy;linech;NOBJNM;OBJNAM;NATION;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20514,"Q-Route Leg","qroute","actper;dnbear;lftwid;NATION;NOBJNM;OBJNAM;rclass;rgtwid;STATUS;TRAFIC;HUNITS;upbear","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
+20515,"Radio broadcast area","rdoare","NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20516,"Regulated airspace","regasp","N/A","N/A",,"G","A"
+20517,"Geological Layer","sedlay","attutn;bulkdn;COLOUR;deplyr;dttdep;dttnum;DUNITS;gascon;grnsiz;hfbmls;laynum;lfbmls;mgstyp;reflco;migspd;migdir;msstrg;natsed;NATQUA;porsty;revebn;revfqy;revgan;samret;sndvel;snrflc;soudat;WATLEV;wbrcap","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
+20518,"Seismic Activity Area","seiare","bearng;ricsca","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20519,"Sensor Anomaly","senanm","datfir;datlst;DUNITS;gendep;HUNITS;madsig;magany;magint;NOBJNM;OBJNAM;orcard;ORIENT;QUASOU;scrdim;senfir;senlst;sonsig;sorfir;sorlst;soudat;SOUACC;STATUS;TECSOU;VALSOU;WATLEV","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
+20520,"Shelter Location","shlloc","OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
+20521,"Superficial Sediment Deposits","seddep","N/A","N/A",,"G","A"
+20522,"Trafficability Area","trfare","cattrf","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20523,"Trawl Scours","twlscr","HUNITS;HORWID;ORIENT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
+20524,"Turning point","turnpt","NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
+20525,"Viewpoint","viewpt","bearng;discon;DUNITS;shpspd;snrfrq;snrrsc;twdbdp","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
+20526,"Bottom Tactical Data Area","btdare","mntden;undmnr;umnrwb;umrwob","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20527,"Burial Probability Area","bprare","brmchm;brperd;brprob;tgrfwt","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20528,"Leisure Activity Area","lsrare","lsract;timeyr","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20529,"Performance Data Area","pfdare","clperc;clprob;csprob;cswidt;dsprob;dtprob","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20530,"Resource Location","resloc","typres;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
+20531,"Risk Data Area","rkdare","conlev;numrmn;prbrmn;rmnlmn;sminth;znecol","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
+20533,"Internal Waters Area ","intwtr","linech;NATION;RESTRN;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20534,"Sea Ice","seaice","iceact;icecvt;icesod;icemax;icemin;icerdv;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20535,"Ice Advisory Area","iceadv","iceadc;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20536,"Iceberg Area","brgare","icebnm;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20537,"Land Ice","lndice","icelnd;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20538,"Ice Line","icelin","icelnc;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
+20539,"Ice Route","icerte","NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
+20540,"Ice Polynya","icepol","icepst;icepty;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
+20541,"Ice Lead","icelea","icelty;icelst;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
+20542,"Iceberg","icebrg","icebsz;icebsh;icebdr;icebsp;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
+20543,"Ice Movement","icemov","icebsp;icebdr;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
+20544,"Traffic route","tfcrte","linech;NOBJNM;OBJNAM;PEREND;PERSTA;traden;TRAFIC;typshp","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
+20717,"User Defined","u_defd","txtdes","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
+20718,"Small Bottom Object","smalbo","blndzn;brmchm;brpctg;COLOUR;comsys;datfir;datlst;depwat;DUNITS;gendep;HORLEN;HORWID;HUNITS;incltn;layptm;layrfn;laytim;madsig;magany;magint;minern;miscls;miscom;misdat;misnme;mnhsys;mnimnc;mnimnt;mnssys;mulcon;mwdcrn;NATCON;navsys;notfnd;nmprob;objtrn;objshp onsonr;orbobn;orgdat;orgntr;ORIENT;QUASOU;scrdim;senfir;senlst;snrflc;soudat;stacon;surdat;SUREND;tarstg;TECSOU;unwrfm;VERLEN","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSA [...]
+21484,"Completeness for the product specification","m_conf + catcnf","catcnf","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"M","A"
+21485,"Security Classification Information","m_clas","","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"M","A"
+21486,"Vertical Datum Shift Area","m_vers","vershf","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"M","P;A"
+21487,"Defined Straight Lines","m_line","linech","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"M","N/A"
diff --git a/data/s57objectclasses_aml.csv b/data/s57objectclasses_aml.csv
deleted file mode 100644
index 8999336..0000000
--- a/data/s57objectclasses_aml.csv
+++ /dev/null
@@ -1,305 +0,0 @@
-"Code","ObjectClass","Acronym","Attribute_A","Attribute_B","Attribute_C","Class","Primitives"
-1,Administration area (Named),ADMARE,JRSDTN;NATION;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-2,Airport / airfield,AIRARE,CATAIR;CONDTN;CONVIS;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-3,Anchor berth,ACHBRT,CATACH;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RADIUS;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-4,Anchorage area,ACHARE,CATACH;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-5,"Beacon, cardinal",BCNCAR,BCNSHP;CATCAM;COLOUR;COLPAT;CONDTN;CONVIS;CONRAD;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-6,"Beacon, isolated danger",BCNISD,BCNSHP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-7,"Beacon, lateral",BCNLAT,BCNSHP;CATLAM;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-8,"Beacon, safe water",BCNSAW,BCNSHP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-9,"Beacon, special purpose/general",BCNSPP,BCNSHP;CATSPM;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-10,Berth,BERTHS,DATEND;DATSTA;DRVAL1;NOBJNM;OBJNAM;PEREND;PERSTA;QUASOU;SOUACC;STATUS;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-11,Bridge,BRIDGE,CATBRG;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HORACC;HORCLR;NATCON;NOBJNM;OBJNAM;VERACC;VERCCL;VERCLR;VERCOP;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-12,"Building, single",BUISGL,BUISHP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;FUNCTN;HEIGHT;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-13,Built-up area,BUAARE,CATBUA;CONDTN;CONRAD;CONVIS;HEIGHT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-14,"Buoy, cardinal",BOYCAR,BOYSHP;CATCAM;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-15,"Buoy, installation",BOYINB,BOYSHP;CATINB;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;PRODCT;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-16,"Buoy, isolated danger",BOYISD,BOYSHP;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-17,"Buoy, lateral",BOYLAT,BOYSHP;CATLAM;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-18,"Buoy, safe water",BOYSAW,BOYSHP;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-19,"Buoy, special purpose/general",BOYSPP,BOYSHP;CATSPM;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-20,Cable area,CBLARE,CATCBL;DATEND;DATSTA;NOBJNM;OBJNAM;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-21,"Cable, overhead",CBLOHD,CATCBL;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ICEFAC;NOBJNM;OBJNAM;STATUS;VERACC;VERCLR;VERCSA;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-22,"Cable, submarine",CBLSUB,BURDEP;CATCBL;CONDTN;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;STATUS;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-23,Canal,CANALS,CATCAN;CONDTN;DATEND;DATSTA;HORACC;HORCLR;HORWID;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-24,Canal bank,CANBNK,CONDTN;DATEND;DATSTA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-25,Cargo transshipment area,CTSARE,DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-26,Causeway,CAUSWY,CONDTN;NATCON;NOBJNM;OBJNAM;STATUS;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-27,Caution area,CTNARE,DATEND;DATSTA;PEREND;PERSTA;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-28,Checkpoint,CHKPNT,CATCHP;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-29,Coastguard station,CGUSTA,DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-30,Coastline,COALNE,CATCOA;COLOUR;CONRAD;CONVIS;ELEVAT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-31,Contiguous zone,CONZNE,DATEND;DATSTA;NATION;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-32,Continental shelf area,COSARE,NATION;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-33,Control point,CTRPNT,CATCTR;DATEND;DATSTA;ELEVAT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-34,Conveyor,CONVYR,CATCON;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;LIFCAP;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERCLR;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-35,Crane,CRANES,CATCRN;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;HEIGHT;LIFCAP;NOBJNM;OBJNAM;ORIENT;RADIUS;STATUS;VERACC;VERCLR;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-36,Current - non - gravitational,CURENT,CURVEL;DATEND;DATSTA;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;,INFORM;NINFOM;SCAMAX;SCAMIN;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-37,Custom zone,CUSZNE,NATION;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-38,Dam,DAMCON,CATDAM;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NATCON;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-39,Daymark,DAYMAR,CATSPM;COLOUR;COLPAT;DATEND;DATSTA;ELEVAT;HEIGHT;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;TOPSHP;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-40,Deep water route centerline,DWRTCL,CATTRK;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-41,Deep water route part,DWRTPT,DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;RESTRN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-42,Depth area,DEPARE,DRVAL1;DRVAL2;QUASOU;SOUACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-43,Depth contour,DEPCNT,VALDCO;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;hypcat;,G,Line;
-44,Distance mark,DISMAR,CATDIS;DATEND;DATSTA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-45,Dock area,DOCARE,CATDOC;CONDTN;DATEND;DATSTA;HORACC;HORCLR;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-46,Dredged area,DRGARE,DRVAL1;DRVAL2;NOBJNM;OBJNAM;QUASOU;RESTRN;SOUACC;TECSOU;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-47,Dry dock,DRYDOC,CONDTN;HORACC;HORCLR;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;DRVAL1;QUASOU;SOUACC;VERDAT;,INFORM;NINFOM;SCAMAX;SCAMIN;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-48,Dumping ground,DMPGRD,CATDPG;NOBJNM;OBJNAM;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-49,Dyke,DYKCON,CONDTN;CONRAD;DATEND;DATSTA;HEIGHT;NATCON;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-50,Exclusive Economic Zone,EXEZNE,NATION;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-51,Fairway,FAIRWY,DATEND;DATSTA;DRVAL1;NOBJNM;OBJNAM;ORIENT;QUASOU;RESTRN;SOUACC;STATUS;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-52,Fence/wall,FNCLNE,CATFNC;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;HEIGHT;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-53,Ferry route,FERYRT,CATFRY;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-54,Fishery zone,FSHZNE,NATION;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-55,Fishing facility,FSHFAC,CATFIF;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-56,Fishing ground,FSHGRD,NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-57,Floating dock,FLODOC,COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;DRVAL1;HORACC;HORCLR;HORLEN;HORWID;LIFCAP;NOBJNM;OBJNAM;STATUS;VERACC;VERLEN;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-58,Fog signal,FOGSIG,CATFOG;DATEND;DATSTA;NOBJNM;OBJNAM;SIGFRQ;SIGGEN;SIGGRP;SIGPER;SIGSEQ;STATUS;VALMXR;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-59,Fortified structure,FORSTC,CATFOR;CONDTN;CONRAD;CONVIS;HEIGHT;NATCON;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-60,Free port area,FRPARE,NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-61,Gate,GATCON,CATGAT;CONDTN;DRVAL1;HORACC;HORCLR;NATCON;NOBJNM;OBJNAM;QUASOU;SOUACC;STATUS;VERACC;VERCLR;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-62,Gridiron,GRIDRN,HORACC;HORLEN;HORWID;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-63,Harbour area (administrative),HRBARE,NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-64,Harbour facility,HRBFAC,CATHAF;CONDTN;DATEND;DATSTA;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-65,Hulk,HULKES,CATHLK;COLOUR;COLPAT;CONRAD;CONVIS;HORACC;HORLEN;HORWID;NOBJNM;OBJNAM;VERACC;VERLEN;CONDTN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-66,Ice area,ICEARE,CATICE;CONVIS;ELEVAT;HEIGHT;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-67,Incineration area,ICNARE,NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-68,Inshore traffic zone,ISTZNE,CATTSS;DATEND;DATSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-69,Lake,LAKARE,ELEVAT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-70,Lake shore,LAKSHR,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-71,Land area,LNDARE,CONDTN;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-72,Land elevation,LNDELV,CONVIS;ELEVAT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;
-73,Land region,LNDRGN,CATLND;NATQUA;NATSUR;NOBJNM;OBJNAM;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-74,Landmark,LNDMRK,CATLMK;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;FUNCTN;HEIGHT;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-75,Light,LIGHTS,CATLIT;COLOUR;DATEND;DATSTA;EXCLIT;HEIGHT;LITCHR;LITVIS;MARSYS;MLTYLT;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;SECTR1;SECTR2;SIGGRP;SIGPER;SIGSEQ;STATUS;VERACC;VALNMR;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-76,Light float,LITFLT,COLOUR;COLPAT;CONRAD;CONVIS;DATEND;DATSTA;HORACC;HORLEN;HORWID;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-77,Light vessel,LITVES,COLOUR;COLPAT;CONRAD;CONVIS;DATEND;DATSTA;HORACC;HORLEN;HORWID;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-78,Local magnetic anomaly,LOCMAG,NOBJNM;OBJNAM;VALLMA;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-79,Lock basin,LOKBSN,DATEND;DATSTA;HORACC;HORCLR;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-80,Log pond,LOGPON,NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-81,Magnetic variation,MAGVAR,DATEND;DATSTA;RYRMGV;VALACM;VALMAG;,INFORM;NINFOM;SCAMAX;SCAMIN;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-82,Marine farm/culture,MARCUL,CATMFA;DATEND;DATSTA;EXPSOU;NOBJNM;OBJNAM;PEREND;PERSTA;QUASOU;RESTRN;SOUACC;STATUS;VALSOU;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-83,Military practice area,MIPARE,CATMPA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-84,Mooring/warping facility,MORFAC,BOYSHP;CATMOR;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-85,Navigation line,NAVLNE,CATNAV;DATEND;DATSTA;ORIENT;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-86,Obstruction,OBSTRN,CATOBS;CONDTN;EXPSOU;HEIGHT;NATCON;NATQUA;NOBJNM;OBJNAM;PRODCT;QUASOU;SOUACC;STATUS;TECSOU;VALSOU;VERACC;VERDAT;VERLEN;WATLEV;NATSUR;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-87,Offshore platform,OFSPLF,CATOFP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NATCON;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-88,Offshore production area,OSPARE,CATPRA;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NOBJNM;OBJNAM;PRODCT;RESTRN;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-89,Oil barrier,OILBAR,CATOLB;CONDTN;DATEND;DATSTA;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-90,Pile,PILPNT,CATPLE;COLOUR;COLPAT;CONDTN;CONVIS;DATEND;DATSTA;HEIGHT;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-91,Pilot boarding place,PILBOP,CATPIL;COMCHA;DATEND;DATSTA;NOBJNM;NPLDST;OBJNAM;PEREND;PERSTA;PILDST;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-92,Pipeline area,PIPARE,CONDTN;DATEND;DATSTA;NOBJNM;OBJNAM;PRODCT;RESTRN;STATUS;CATPIP;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-93,"Pipeline, overhead",PIPOHD,CATPIP;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERCLR;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-94,"Pipeline, submarine/on land",PIPSOL,BURDEP;CATPIP;CONDTN;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERLEN;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;
-95,Pontoon,PONTON,CONDTN;CONRAD;CONVIS;DATEND;DATSTA;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-96,Precautionary area,PRCARE,DATEND;DATSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-97,Production / storage area,PRDARE,CATPRA;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-98,Pylon/bridge support,PYLONS,CATPYL;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NATCON;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-99,Radar line,RADLNE,NOBJNM;OBJNAM;ORIENT;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-100,Radar range,RADRNG,COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-101,Radar reflector,RADRFL,HEIGHT;STATUS;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-102,Radar station,RADSTA,CATRAS;DATEND;DATSTA;HEIGHT;NOBJNM;OBJNAM;STATUS;VERACC;VALMXR;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-103,Radar transponder beacon,RTPBCN,CATRTB;DATEND;DATSTA;NOBJNM;OBJNAM;RADWAL;SECTR1;SECTR2;SIGGRP;SIGSEQ;STATUS;VALMXR;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-104,Radio calling-in point,RDOCAL,COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;STATUS;TRAFIC;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;
-105,Radio station,RDOSTA,CALSGN;CATROS;COMCHA;DATEND;DATSTA;ESTRNG;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;SIGFRQ;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-106,Railway,RAILWY,CONDTN;HEIGHT;NOBJNM;OBJNAM;STATUS;VERACC;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-107,Rapids,RAPIDS,NOBJNM;OBJNAM;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-108,Recommended route centerline,RCRTCL,CATTRK;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-109,Recommended track,RECTRC,CATTRK;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-110,Recommended Traffic Lane Part,RCTLPT,DATEND;DATSTA;ORIENT;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-111,Rescue station,RSCSTA,CATRSC;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;SCAMAX;SCAMIN;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-112,Restricted area,RESARE,CATREA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-113,Retro-reflector,RETRFL,COLOUR;COLPAT;HEIGHT;MARSYS;STATUS;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-114,River,RIVERS,NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-115,River bank,RIVBNK,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-116,Road,ROADWY,CATROD;CONDTN;NATCON;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-117,Runway,RUNWAY,CATRUN;CONDTN;CONVIS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-118,Sand waves,SNDWAV,VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-119,Sea area / named water area,SEAARE,CATSEA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-120,Sea-plane landing area,SPLARE,NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;VALDCO;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-121,Seabed area,SBDARE,COLOUR;NATQUA;NATSUR;WATLEV;OBJNAM;NOBJNM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-122,Shoreline Construction,SLCONS,CATSLC;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;HORACC;HORCLR;HORLEN;HORWID;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-123,"Signal station, traffic",SISTAT,CATSIT;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-124,"Signal station, warning",SISTAW,CATSIW;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-125,Silo / tank,SILTNK,BUISHP;CATSIL;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;HEIGHT;NATCON;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-126,Slope topline,SLOTOP,CATSLO;COLOUR;CONRAD;CONVIS;ELEVAT;NATCON;NATQUA;NATSUR;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-127,Sloping ground,SLOGRD,CATSLO;COLOUR;CONRAD;CONVIS;NATCON;NATQUA;NATSUR;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-128,Small craft facility,SMCFAC,CATSCF;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-129,Sounding,SOUNDG,EXPSOU;NOBJNM;OBJNAM;QUASOU;SOUACC;TECSOU;VERDAT;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-130,Spring,SPRING,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-131,Square,SQUARE,CONDTN;NATCON;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-132,Straight territorial sea baseline,STSLNE,NATION;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-133,Submarine transit lane,SUBTLN,NOBJNM;OBJNAM;RESTRN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-134,Swept Area,SWPARE,DRVAL1;QUASOU;SOUACC;TECSOU;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-135,Territorial sea area,TESARE,NATION;RESTRN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-136,Tidal stream - harmonic prediction,TS_PRH,NOBJNM;OBJNAM;T_MTOD;T_VAHC;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-137,Tidal stream - non-harmonic prediction,TS_PNH,NOBJNM;OBJNAM;T_MTOD;T_THDF;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-138,Tidal stream panel data,TS_PAD,NOBJNM;OBJNAM;TS_TSP;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-139,Tidal stream - time series,TS_TIS,NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;T_TINT;TS_TSV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-140,Tide - harmonic prediction,T_HMON,NOBJNM;OBJNAM;T_ACWL;T_MTOD;T_VAHC;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-141,Tide - non-harmonic prediction,T_NHMN,NOBJNM;OBJNAM;T_ACWL;T_MTOD;T_THDF;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-142,Tidal stream - time series,T_TIMS,NOBJNM;OBJNAM;T_HWLW;T_TINT;T_TSVL;TIMEND;TIMSTA;STATUS;T_ACWL;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-143,Tideway,TIDEWY,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-144,Top mark,TOPMAR,COLOUR;COLPAT;HEIGHT;MARSYS;STATUS;TOPSHP;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-145,Traffic Separation Line,TSELNE,CATTSS;DATEND;DATSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-146,Traffic Separation Scheme  Boundary,TSSBND,CATTSS;DATEND;DATSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-147,Traffic Separation Scheme Crossing,TSSCRS,CATTSS;DATEND;DATSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-148,Traffic Separation Scheme  Lane part,TSSLPT,CATTSS;DATEND;DATSTA;ORIENT;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-149,Traffic Separation Scheme  Roundabout,TSSRON,CATTSS;DATEND;DATSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-150,Traffic Separation Zone,TSEZNE,CATTSS;DATEND;DATSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-151,Tunnel,TUNNEL,BURDEP;CONDTN;HORACC;HORCLR;NOBJNM;OBJNAM;STATUS;VERACC;VERCLR;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-152,Two-way route  part,TWRTPT,CATTRK;DATEND;DATSTA;DRVAL1;DRVAL2;ORIENT;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-153,Underwater rock / awash rock,UWTROC,EXPSOU;NATSUR;NATQUA;NOBJNM;OBJNAM;QUASOU;SOUACC;STATUS;TECSOU;VALSOU;VERDAT;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-154,Unsurveyed area,UNSARE,,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-155,Vegetation,VEGATN,CATVEG;CONVIS;ELEVAT;HEIGHT;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-156,Water turbulence,WATTUR,CATWAT;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-157,Waterfall,WATFAL,CONVIS;NOBJNM;OBJNAM;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;
-158,Weed/Kelp,WEDKLP,CATWED;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-159,Wreck,WRECKS,CATWRK;CONRAD;CONVIS;EXPSOU;HEIGHT;NOBJNM;OBJNAM;QUASOU;SOUACC;STATUS;TECSOU;VALSOU;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-160,Tidal stream - flood/ebb,TS_FEB,CAT_TS;CURVEL;DATEND;DATSTA;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-300,Accuracy of data,M_ACCY,HORACC;POSACC;SOUACC;VERACC;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-301,Compilation scale of data,M_CSCL,CSCALE;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-302,Coverage,M_COVR,CATCOV;,INFORM;NINFOM;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-303,Horizontal datum of data,M_HDAT,HORDAT;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-304,Horizontal datum shift parameters,M_HOPA,HORDAT;SHIPAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-305,Nautical publication information,M_NPUB,,INFORM;NINFOM;NTXTDS;PICREP;PUBREF;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-306,Navigational system of marks,M_NSYS,MARSYS;ORIENT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-307,Production information,M_PROD,AGENCY;CPDATE;NATION;NMDATE;PRCTRY;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-308,Quality of data,M_QUAL,CATQUA;CATZOC;DRVAL1;DRVAL2;POSACC;SOUACC;SUREND;SURSTA;TECSOU;VERDAT;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-309,Sounding datum,M_SDAT,VERDAT;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-310,Survey reliability,M_SREL,QUAPOS;QUASOU;SCVAL1;SCVAL2;SDISMN;SDISMX;SURATH;SUREND;SURSTA;SURTYP;TECSOU;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-311,Units of measurement of data,M_UNIT,DUNITS;HUNITS;PUNITS;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-312,Vertical datum of data,M_VDAT,VERDAT;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-400,Aggregation,C_AGGR,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,C,
-401,Association,C_ASSO,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,C,
-402,Stacked on/stacked under,C_STAC,,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,C,
-500,Cartographic area,$AREAS,COLOUR;ORIENT;$SCODE;$TINTS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-501,Cartographic line,$LINES,$SCODE;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-502,Cartographic symbol,$CSYMB,ORIENT;$SCALE;$SCODE;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-503,Compass,$COMPS,$CSIZE;RYRMGV;VALACM;VALMAG;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-504,Text,$TEXTS,$CHARS;COLOUR;$JUSTH;$JUSTV;$NTXST;$SPACE;$TXSTR;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-20484,"ATS Route Centreline","atsctl","authty;linech;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
-20485,"Airspace Restriction","airres + catasr","authty;catasr;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20485,"Airspace Restriction","airres + catasr","authty;catasr;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20485,"Airspace Restriction","airres + catasr","authty;catasr;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20485,"Airspace Restriction","airres + catasr","authty;catasr;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20485,"Airspace Restriction","airres + catasr","authty;catasr;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20485,"Airspace Restriction","airres + catasr","authty;catasr;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20485,"Airspace Restriction","airres + catasr","authty;catasr;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20486,"Area of Imagery Coverage","imgare","bearng;catimg;ELEVAT;HUNITS;orgntr;SUREND;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20487,"Beach Exit","bchext","ccmidx;exitus;gradnt;HORCLR;HORLEN;HORWID;HUNITS;VERCSA;wbrcap","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L"
-20488,"Beach Profile","bchprf","bearng;gradnt;SUREND","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
-20489,"Beach Survey","bchare","accres;brktyp;ccmidx;dgmrlf;HORLEN;HORWID;HUNITS;quabch;orgntr;srfhgt;srfzne;stbacv;SUREND;SURSTA;swlhgt;tdlrng;tdltyp","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P   A   "
-20490,"Bedrock area","bedare","N/A","N/A",,"G","A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20491,"Bottom Feature","botmft + catbot","catbot;DUNITS;gradnt;HORLEN;HORWID;HUNITS;migspd;migdir;NOBJNM;OBJNAM;ORIENT;soudat;stfotn;VALSOU;VERLEN;WATLEV;wavlen","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20492,"Centre Line","centre","N/A","N/A",,"G","L"
-20494,"Contact History","histob","orgntr;surdat;SUREND","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20495,"Controlled airspace","ctlasp + catcas","authty;catcas;caircd;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20496,"Diving Location","divloc","depact;divact;DUNITS;OBJNAM;NOBJNM;timeyr;watclr","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
-20497,"Drinking Water Location","watloc","N/A","N/A",,"G","P"
-20498,"Drop Zone","drpzne","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
-20499,"Environmentally Sensitive Area","envare","authty;legsta;OBJNAM;NOBJNM;PEREND;PERSTA","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A;P"
-20500,"Fishing Activity Area","fshare","catfsh;STATUS;timeyr","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20501,"Impact Scour","iscour","datfir;datlst;depwat;DUNITS;gendep;HORLEN;HORWID;HUNITS;NATQUA;NATSUR;NOBJNM;OBJNAM;orcard;ORIENT;QUASOU;senfir;senlst;sonsig;sorfir;sorlst;SOUACC;soudat;STATUS;TECSOU;VALSOU;VERLEN;WATLEV","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20502,"Landing Area","lngare","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20503,"Landing Place","lndplc","gradnt;STATUS;wbrcap","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20504,"Landing Point","lndpnt","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20505,"Landing Site","lndste","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20506,"Landing Strip","lndstp","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20507,"Landing Zone","lndzne","apprch;extdes;lndcon;OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20508,"Marine management area","marman + catmma","actper;authty;catmma;identy;linech;NOBJNM;OBJNAM;NATION;spcies;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20508,"Marine management area","marman + catmma","actper;authty;catmma;identy;linech;NOBJNM;OBJNAM;NATION;spcies;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20508,"Marine management area","marman + catmma","actper;authty;catmma;identy;linech;NOBJNM;OBJNAM;NATION;spcies;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20508,"Marine management area","marman + catmma","actper;authty;catmma;identy;linech;NOBJNM;OBJNAM;NATION;spcies;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20508,"Marine management area","marman + catmma","actper;authty;catmma;identy;linech;NOBJNM;OBJNAM;NATION;spcies;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20509,"Maritime Safety Information area","msiare","catmsi;condet;NATION;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20510,"MCM Area","mcmare","mhclas;milden;nomden","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20511,"Military exercise airspace","mexasp + catmea","actper;authty;catmea;linech;maxalt;maxftl;minalt;minftl;NOBJNM;OBJNAM;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20513,"Patrol area","patare + catpat","authty;catpat;identy;linech;NOBJNM;OBJNAM;NATION;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20513,"Patrol area","patare + catpat","authty;catpat;identy;linech;NOBJNM;OBJNAM;NATION;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20514,"Q-Route Leg","qroute","actper;dnbear;lftwid;NATION;NOBJNM;OBJNAM;rclass;rgtwid;STATUS;TRAFIC;HUNITS;upbear","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
-20515,"Radio broadcast area","rdoare","NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20516,"Regulated airspace","regasp","N/A","N/A",,"G","A"
-20517,"Geological Layer","sedlay","attutn;bulkdn;COLOUR;deplyr;dttdep;dttnum;DUNITS;gascon;grnsiz;hfbmls;laynum;lfbmls;mgstyp;reflco;migspd;migdir;msstrg;natsed;NATQUA;porsty;revebn;revfqy;revgan;samret;sndvel;snrflc;soudat;WATLEV;wbrcap","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
-20518,"Seismic Activity Area","seiare","bearng;ricsca","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20519,"Sensor Anomaly","senanm","datfir;datlst;DUNITS;gendep;HUNITS;madsig;magany;magint;NOBJNM;OBJNAM;orcard;ORIENT;QUASOU;scrdim;senfir;senlst;sonsig;sorfir;sorlst;soudat;SOUACC;STATUS;TECSOU;VALSOU;WATLEV","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20520,"Shelter Location","shlloc","OBJNAM;NOBJNM;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20521,"Superficial Sediment Deposits","seddep","N/A","N/A",,"G","A"
-20522,"Trafficability Area","trfare","cattrf","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20523,"Trawl Scours","twlscr","HUNITS;HORWID;ORIENT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20524,"Turning point","turnpt","NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20525,"Viewpoint","viewpt","bearng;discon;DUNITS;shpspd;snrfrq;snrrsc;twdbdp","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20525,"Viewpoint","viewpt","bearng;catimg;ELEVAT;HUNITS;VERDAT","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20526,"Bottom Tactical Data Area","btdare","mntden;undmnr;umnrwb;umrwob","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20527,"Burial Probability Area","bprare","brmchm;brperd;brprob;tgrfwt","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20528,"Leisure Activity Area","lsrare","lsract;timeyr","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20529,"Performance Data Area","pfdare","clperc;clprob;csprob;cswidt;dsprob;dtprob","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20530,"Resource Location","resloc","typres;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
-20531,"Risk Data Area","rkdare","conlev;numrmn;prbrmn;rmnlmn;sminth;znecol","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20532,"Navigation system (NAVAID)","navaid + CATROS","actper;CALSGN;CATROS;COMCHA;NOBJNM;OBJNAM;SIGFRQ","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P"
-20533,"Internal Waters Area ","intwtr","linech;NATION;RESTRN;STATUS","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20534,"Sea Ice","seaice","iceact;icecvt;icesod;icemax;icemin;icerdv;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20535,"Ice Advisory Area","iceadv","iceadc;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20536,"Iceberg Area","brgare","icebnm;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20537,"Land Ice","lndice","icelnd;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20538,"Ice Line","icelin","icelnc;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
-20539,"Ice Route","icerte","NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
-20540,"Ice Polynya","icepol","icepst;icepty;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","A"
-20541,"Ice Lead","icelea","icelty;icelst;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L;A"
-20542,"Iceberg","icebrg","icebsz;icebsh;icebdr;icebsp;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
-20543,"Ice Movement","icemov","icebsp;icebdr;NOBJNM;OBJNAM","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;A"
-20544,"Traffic route","tfcrte","linech;NOBJNM;OBJNAM;PEREND;PERSTA;traden;TRAFIC;typshp","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","L"
-20717,"User Defined","u_defd","txtdes","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"G","P;L;A"
-20718,"Small Bottom Object","smalbo","blndzn;brmchm;brpctg;COLOUR;comsys;datfir;datlst;depwat;DUNITS;gendep;HORLEN;HORWID;HUNITS;incltn;layptm;layrfn;laytim;madsig;magany;magint;minern;miscls;miscom;misdat;misnme;mnhsys;mnimnc;mnimnt;mnssys;mulcon;mwdcrn;NATCON;navsys;notfnd;nmprob;objtrn;objshp onsonr;orbobn;orgdat;orgntr;ORIENT;QUASOU;scrdim;senfir;senlst;snrflc;soudat;stacon;surdat;SUREND;tarstg;TECSOU;unwrfm;VERLEN","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSA [...]
-21484,"Completeness for the product specification","m_conf + catcnf","catcnf","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"M","A"
-21485,"Security Classification Information","m_clas","","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"M","A"
-21486,"Vertical Datum Shift Area","m_vers","vershf","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"M","P;A"
-21487,"Defined Straight Lines","m_line","linech","AGENCY;CSCALE;elvacc;errell;HORACC;INFORM;NINFOM;NTXTDS;PICREP;POSACC;PRCTRY;PUBREF;RECDAT;QUAPOS;seccvt;secido;secown;secpmk;SORDAT;SORIND;TXTDSC;VERACC",,"M","N/A"
diff --git a/data/s57objectclasses_iw.csv b/data/s57objectclasses_iw.csv
deleted file mode 100644
index c1b4691..0000000
--- a/data/s57objectclasses_iw.csv
+++ /dev/null
@@ -1,217 +0,0 @@
-"Code","ObjectClass","Acronym","Attribute_A","Attribute_B","Attribute_C","Class","Primitives"
-1,Administration area (Named),ADMARE,JRSDTN;NATION;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-2,Airport / airfield,AIRARE,CATAIR;CONDTN;CONVIS;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-3,Anchor berth,ACHBRT,CATACH;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RADIUS;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-4,Anchorage area,ACHARE,CATACH;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-5,"Beacon, cardinal",BCNCAR,BCNSHP;CATCAM;COLOUR;COLPAT;CONDTN;CONVIS;CONRAD;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-6,"Beacon, isolated danger",BCNISD,BCNSHP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-7,"Beacon, lateral",BCNLAT,BCNSHP;CATLAM;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-8,"Beacon, safe water",BCNSAW,BCNSHP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-9,"Beacon, special purpose/general",BCNSPP,BCNSHP;CATSPM;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-10,Berth,BERTHS,DATEND;DATSTA;DRVAL1;NOBJNM;OBJNAM;PEREND;PERSTA;QUASOU;SOUACC;STATUS;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-11,Bridge,BRIDGE,CATBRG;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HORACC;HORCLR;NATCON;NOBJNM;OBJNAM;VERACC;VERCCL;VERCLR;VERCOP;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-12,"Building, single",BUISGL,BUISHP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;FUNCTN;HEIGHT;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-13,Built-up area,BUAARE,CATBUA;CONDTN;CONRAD;CONVIS;HEIGHT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-14,"Buoy, cardinal",BOYCAR,BOYSHP;CATCAM;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-15,"Buoy, installation",BOYINB,BOYSHP;CATINB;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;PRODCT;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-16,"Buoy, isolated danger",BOYISD,BOYSHP;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-17,"Buoy, lateral",BOYLAT,BOYSHP;CATLAM;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-18,"Buoy, safe water",BOYSAW,BOYSHP;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-19,"Buoy, special purpose/general",BOYSPP,BOYSHP;CATSPM;COLOUR;COLPAT;CONRAD;DATEND;DATSTA;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-20,Cable area,CBLARE,CATCBL;DATEND;DATSTA;NOBJNM;OBJNAM;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-21,"Cable, overhead",CBLOHD,CATCBL;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ICEFAC;NOBJNM;OBJNAM;STATUS;VERACC;VERCLR;VERCSA;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-22,"Cable, submarine",CBLSUB,BURDEP;CATCBL;CONDTN;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;STATUS;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-23,Canal,CANALS,CATCAN;CONDTN;DATEND;DATSTA;HORACC;HORCLR;HORWID;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-24,Canal bank,CANBNK,CONDTN;DATEND;DATSTA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-25,Cargo transshipment area,CTSARE,DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-26,Causeway,CAUSWY,CONDTN;NATCON;NOBJNM;OBJNAM;STATUS;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-27,Caution area,CTNARE,DATEND;DATSTA;PEREND;PERSTA;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-28,Checkpoint,CHKPNT,CATCHP;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-29,Coastguard station,CGUSTA,DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-30,Coastline,COALNE,CATCOA;COLOUR;CONRAD;CONVIS;ELEVAT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-31,Contiguous zone,CONZNE,DATEND;DATSTA;NATION;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-32,Continental shelf area,COSARE,NATION;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-33,Control point,CTRPNT,CATCTR;DATEND;DATSTA;ELEVAT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-34,Conveyor,CONVYR,CATCON;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;LIFCAP;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERCLR;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-35,Crane,CRANES,CATCRN;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;HEIGHT;LIFCAP;NOBJNM;OBJNAM;ORIENT;RADIUS;STATUS;VERACC;VERCLR;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-36,Current - non - gravitational,CURENT,CURVEL;DATEND;DATSTA;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;,INFORM;NINFOM;SCAMAX;SCAMIN;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-37,Custom zone,CUSZNE,NATION;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-38,Dam,DAMCON,CATDAM;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NATCON;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-39,Daymark,DAYMAR,CATSPM;COLOUR;COLPAT;DATEND;DATSTA;ELEVAT;HEIGHT;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;TOPSHP;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-40,Deep water route centerline,DWRTCL,CATTRK;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-41,Deep water route part,DWRTPT,DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;RESTRN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-42,Depth area,DEPARE,DRVAL1;DRVAL2;QUASOU;SOUACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-43,Depth contour,DEPCNT,VALDCO;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-44,Distance mark,DISMAR,CATDIS;DATEND;DATSTA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-45,Dock area,DOCARE,CATDOC;CONDTN;DATEND;DATSTA;HORACC;HORCLR;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-46,Dredged area,DRGARE,DRVAL1;DRVAL2;NOBJNM;OBJNAM;QUASOU;RESTRN;SOUACC;TECSOU;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-47,Dry dock,DRYDOC,CONDTN;HORACC;HORCLR;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;DRVAL1;QUASOU;SOUACC;VERDAT;,INFORM;NINFOM;SCAMAX;SCAMIN;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-48,Dumping ground,DMPGRD,CATDPG;NOBJNM;OBJNAM;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-49,Dyke,DYKCON,CONDTN;CONRAD;DATEND;DATSTA;HEIGHT;NATCON;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-50,Exclusive Economic Zone,EXEZNE,NATION;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-51,Fairway,FAIRWY,DATEND;DATSTA;DRVAL1;NOBJNM;OBJNAM;ORIENT;QUASOU;RESTRN;SOUACC;STATUS;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-52,Fence/wall,FNCLNE,CATFNC;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;HEIGHT;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-53,Ferry route,FERYRT,CATFRY;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-54,Fishery zone,FSHZNE,NATION;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-55,Fishing facility,FSHFAC,CATFIF;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-56,Fishing ground,FSHGRD,NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-57,Floating dock,FLODOC,COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;DRVAL1;HORACC;HORCLR;HORLEN;HORWID;LIFCAP;NOBJNM;OBJNAM;STATUS;VERACC;VERLEN;VERDAT;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-58,Fog signal,FOGSIG,CATFOG;DATEND;DATSTA;NOBJNM;OBJNAM;SIGFRQ;SIGGEN;SIGGRP;SIGPER;SIGSEQ;STATUS;VALMXR;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-59,Fortified structure,FORSTC,CATFOR;CONDTN;CONRAD;CONVIS;HEIGHT;NATCON;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-60,Free port area,FRPARE,NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-61,Gate,GATCON,CATGAT;CONDTN;DRVAL1;HORACC;HORCLR;NATCON;NOBJNM;OBJNAM;QUASOU;SOUACC;STATUS;VERACC;VERCLR;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-62,Gridiron,GRIDRN,HORACC;HORLEN;HORWID;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-63,Harbour area (administrative),HRBARE,NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-64,Harbour facility,HRBFAC,CATHAF;CONDTN;DATEND;DATSTA;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-65,Hulk,HULKES,CATHLK;COLOUR;COLPAT;CONRAD;CONVIS;HORACC;HORLEN;HORWID;NOBJNM;OBJNAM;VERACC;VERLEN;CONDTN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-66,Ice area,ICEARE,CATICE;CONVIS;ELEVAT;HEIGHT;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-67,Incineration area,ICNARE,NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-68,Inshore traffic zone,ISTZNE,CATTSS;DATEND;DATSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-69,Lake,LAKARE,ELEVAT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-70,Lake shore,LAKSHR,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-71,Land area,LNDARE,CONDTN;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-72,Land elevation,LNDELV,CONVIS;ELEVAT;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;
-73,Land region,LNDRGN,CATLND;NATQUA;NATSUR;NOBJNM;OBJNAM;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-74,Landmark,LNDMRK,CATLMK;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;FUNCTN;HEIGHT;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-75,Light,LIGHTS,CATLIT;COLOUR;DATEND;DATSTA;EXCLIT;HEIGHT;LITCHR;LITVIS;MARSYS;MLTYLT;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;SECTR1;SECTR2;SIGGRP;SIGPER;SIGSEQ;STATUS;VERACC;VALNMR;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-76,Light float,LITFLT,COLOUR;COLPAT;CONRAD;CONVIS;DATEND;DATSTA;HORACC;HORLEN;HORWID;MARSYS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-77,Light vessel,LITVES,COLOUR;COLPAT;CONRAD;CONVIS;DATEND;DATSTA;HORACC;HORLEN;HORWID;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-78,Local magnetic anomaly,LOCMAG,NOBJNM;OBJNAM;VALLMA;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-79,Lock basin,LOKBSN,DATEND;DATSTA;HORACC;HORCLR;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-80,Log pond,LOGPON,NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-81,Magnetic variation,MAGVAR,DATEND;DATSTA;RYRMGV;VALACM;VALMAG;,INFORM;NINFOM;SCAMAX;SCAMIN;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-82,Marine farm/culture,MARCUL,CATMFA;DATEND;DATSTA;EXPSOU;NOBJNM;OBJNAM;PEREND;PERSTA;QUASOU;RESTRN;SOUACC;STATUS;VALSOU;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-83,Military practice area,MIPARE,CATMPA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-84,Mooring/warping facility,MORFAC,BOYSHP;CATMOR;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-85,Navigation line,NAVLNE,CATNAV;DATEND;DATSTA;ORIENT;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-86,Obstruction,OBSTRN,CATOBS;CONDTN;EXPSOU;HEIGHT;NATCON;NATQUA;NOBJNM;OBJNAM;PRODCT;QUASOU;SOUACC;STATUS;TECSOU;VALSOU;VERACC;VERDAT;VERLEN;WATLEV;NATSUR;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-87,Offshore platform,OFSPLF,CATOFP;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NATCON;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-88,Offshore production area,OSPARE,CATPRA;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NOBJNM;OBJNAM;PRODCT;RESTRN;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-89,Oil barrier,OILBAR,CATOLB;CONDTN;DATEND;DATSTA;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-90,Pile,PILPNT,CATPLE;COLOUR;COLPAT;CONDTN;CONVIS;DATEND;DATSTA;HEIGHT;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-91,Pilot boarding place,PILBOP,CATPIL;COMCHA;DATEND;DATSTA;NOBJNM;NPLDST;OBJNAM;PEREND;PERSTA;PILDST;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-92,Pipeline area,PIPARE,CONDTN;DATEND;DATSTA;NOBJNM;OBJNAM;PRODCT;RESTRN;STATUS;CATPIP;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-93,"Pipeline, overhead",PIPOHD,CATPIP;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERCLR;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-94,"Pipeline, submarine/on land",PIPSOL,BURDEP;CATPIP;CONDTN;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERLEN;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;
-95,Pontoon,PONTON,CONDTN;CONRAD;CONVIS;DATEND;DATSTA;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-96,Precautionary area,PRCARE,DATEND;DATSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-97,Production / storage area,PRDARE,CATPRA;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ELEVAT;HEIGHT;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-98,Pylon/bridge support,PYLONS,CATPYL;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;NATCON;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-99,Radar line,RADLNE,NOBJNM;OBJNAM;ORIENT;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-100,Radar range,RADRNG,COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-101,Radar reflector,RADRFL,HEIGHT;STATUS;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-102,Radar station,RADSTA,CATRAS;DATEND;DATSTA;HEIGHT;NOBJNM;OBJNAM;STATUS;VERACC;VALMXR;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-103,Radar transponder beacon,RTPBCN,CATRTB;DATEND;DATSTA;NOBJNM;OBJNAM;RADWAL;SECTR1;SECTR2;SIGGRP;SIGSEQ;STATUS;VALMXR;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-104,Radio calling-in point,RDOCAL,COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;STATUS;TRAFIC;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;
-105,Radio station,RDOSTA,CALSGN;CATROS;COMCHA;DATEND;DATSTA;ESTRNG;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;SIGFRQ;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-106,Railway,RAILWY,CONDTN;HEIGHT;NOBJNM;OBJNAM;STATUS;VERACC;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-107,Rapids,RAPIDS,NOBJNM;OBJNAM;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-108,Recommended route centerline,RCRTCL,CATTRK;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-109,Recommended track,RECTRC,CATTRK;DATEND;DATSTA;DRVAL1;DRVAL2;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-110,Recommended Traffic Lane Part,RCTLPT,DATEND;DATSTA;ORIENT;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-111,Rescue station,RSCSTA,CATRSC;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;SCAMAX;SCAMIN;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-112,Restricted area,RESARE,CATREA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-113,Retro-reflector,RETRFL,COLOUR;COLPAT;HEIGHT;MARSYS;STATUS;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-114,River,RIVERS,NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-115,River bank,RIVBNK,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-116,Road,ROADWY,CATROD;CONDTN;NATCON;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-117,Runway,RUNWAY,CATRUN;CONDTN;CONVIS;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-118,Sand waves,SNDWAV,VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-119,Sea area / named water area,SEAARE,CATSEA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-120,Sea-plane landing area,SPLARE,NOBJNM;OBJNAM;PEREND;PERSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;VALDCO;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-121,Seabed area,SBDARE,COLOUR;NATQUA;NATSUR;WATLEV;OBJNAM;NOBJNM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-122,Shoreline Construction,SLCONS,CATSLC;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HEIGHT;HORACC;HORCLR;HORLEN;HORWID;NATCON;NOBJNM;OBJNAM;STATUS;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-123,"Signal station, traffic",SISTAT,CATSIT;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-124,"Signal station, warning",SISTAW,CATSIW;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-125,Silo / tank,SILTNK,BUISHP;CATSIL;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;ELEVAT;HEIGHT;NATCON;NOBJNM;OBJNAM;PRODCT;STATUS;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-126,Slope topline,SLOTOP,CATSLO;COLOUR;CONRAD;CONVIS;ELEVAT;NATCON;NATQUA;NATSUR;NOBJNM;OBJNAM;VERACC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-127,Sloping ground,SLOGRD,CATSLO;COLOUR;CONRAD;CONVIS;NATCON;NATQUA;NATSUR;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-128,Small craft facility,SMCFAC,CATSCF;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-129,Sounding,SOUNDG,EXPSOU;NOBJNM;OBJNAM;QUASOU;SOUACC;TECSOU;VERDAT;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-130,Spring,SPRING,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-131,Square,SQUARE,CONDTN;NATCON;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-132,Straight territorial sea baseline,STSLNE,NATION;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-133,Submarine transit lane,SUBTLN,NOBJNM;OBJNAM;RESTRN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-134,Swept Area,SWPARE,DRVAL1;QUASOU;SOUACC;TECSOU;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-135,Territorial sea area,TESARE,NATION;RESTRN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-136,Tidal stream - harmonic prediction,TS_PRH,NOBJNM;OBJNAM;T_MTOD;T_VAHC;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-137,Tidal stream - non-harmonic prediction,TS_PNH,NOBJNM;OBJNAM;T_MTOD;T_THDF;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-138,Tidal stream panel data,TS_PAD,NOBJNM;OBJNAM;TS_TSP;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-139,Tidal stream - time series,TS_TIS,NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;T_TINT;TS_TSV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-140,Tide - harmonic prediction,T_HMON,NOBJNM;OBJNAM;T_ACWL;T_MTOD;T_VAHC;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-141,Tide - non-harmonic prediction,T_NHMN,NOBJNM;OBJNAM;T_ACWL;T_MTOD;T_THDF;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-142,Tidal stream - time series,T_TIMS,NOBJNM;OBJNAM;T_HWLW;T_TINT;T_TSVL;TIMEND;TIMSTA;STATUS;T_ACWL;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-143,Tideway,TIDEWY,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;Area;
-144,Top mark,TOPMAR,COLOUR;COLPAT;HEIGHT;MARSYS;STATUS;TOPSHP;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-145,Traffic Separation Line,TSELNE,CATTSS;DATEND;DATSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-146,Traffic Separation Scheme  Boundary,TSSBND,CATTSS;DATEND;DATSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Line;
-147,Traffic Separation Scheme Crossing,TSSCRS,CATTSS;DATEND;DATSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-148,Traffic Separation Scheme  Lane part,TSSLPT,CATTSS;DATEND;DATSTA;ORIENT;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-149,Traffic Separation Scheme  Roundabout,TSSRON,CATTSS;DATEND;DATSTA;RESTRN;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-150,Traffic Separation Zone,TSEZNE,CATTSS;DATEND;DATSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-151,Tunnel,TUNNEL,BURDEP;CONDTN;HORACC;HORCLR;NOBJNM;OBJNAM;STATUS;VERACC;VERCLR;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-152,Two-way route  part,TWRTPT,CATTRK;DATEND;DATSTA;DRVAL1;DRVAL2;ORIENT;QUASOU;SOUACC;STATUS;TECSOU;TRAFIC;VERDAT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-153,Underwater rock / awash rock,UWTROC,EXPSOU;NATSUR;NATQUA;NOBJNM;OBJNAM;QUASOU;SOUACC;STATUS;TECSOU;VALSOU;VERDAT;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;
-154,Unsurveyed area,UNSARE,,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Area;
-155,Vegetation,VEGATN,CATVEG;CONVIS;ELEVAT;HEIGHT;NOBJNM;OBJNAM;VERACC;VERDAT;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-156,Water turbulence,WATTUR,CATWAT;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;Area;
-157,Waterfall,WATFAL,CONVIS;NOBJNM;OBJNAM;VERACC;VERLEN;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Line;
-158,Weed/Kelp,WEDKLP,CATWED;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-159,Wreck,WRECKS,CATWRK;CONRAD;CONVIS;EXPSOU;HEIGHT;NOBJNM;OBJNAM;QUASOU;SOUACC;STATUS;TECSOU;VALSOU;VERACC;VERDAT;VERLEN;WATLEV;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-160,Tidal stream - flood/ebb,TS_FEB,CAT_TS;CURVEL;DATEND;DATSTA;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,G,Point;Area;
-300,Accuracy of data,M_ACCY,HORACC;POSACC;SOUACC;VERACC;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-301,Compilation scale of data,M_CSCL,CSCALE;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-302,Coverage,M_COVR,CATCOV;,INFORM;NINFOM;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-303,Horizontal datum of data,M_HDAT,HORDAT;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-304,Horizontal datum shift parameters,M_HOPA,HORDAT;SHIPAM;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-305,Nautical publication information,M_NPUB,,INFORM;NINFOM;NTXTDS;PICREP;PUBREF;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-306,Navigational system of marks,M_NSYS,MARSYS;ORIENT;,INFORM;NINFOM;NTXTDS;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-307,Production information,M_PROD,AGENCY;CPDATE;NATION;NMDATE;PRCTRY;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-308,Quality of data,M_QUAL,CATQUA;CATZOC;DRVAL1;DRVAL2;POSACC;SOUACC;SUREND;SURSTA;TECSOU;VERDAT;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-309,Sounding datum,M_SDAT,VERDAT;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-310,Survey reliability,M_SREL,QUAPOS;QUASOU;SCVAL1;SCVAL2;SDISMN;SDISMX;SURATH;SUREND;SURSTA;SURTYP;TECSOU;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-311,Units of measurement of data,M_UNIT,DUNITS;HUNITS;PUNITS;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-312,Vertical datum of data,M_VDAT,VERDAT;,INFORM;NINFOM;NTXTDS;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,M,Area;
-400,Aggregation,C_AGGR,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,C,
-401,Association,C_ASSO,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,C,
-402,Stacked on/stacked under,C_STAC,,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,C,
-500,Cartographic area,$AREAS,COLOUR;ORIENT;$SCODE;$TINTS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-501,Cartographic line,$LINES,$SCODE;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-502,Cartographic symbol,$CSYMB,ORIENT;$SCALE;$SCODE;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-503,Compass,$COMPS,$CSIZE;RYRMGV;VALACM;VALMAG;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-504,Text,$TEXTS,$CHARS;COLOUR;$JUSTH;$JUSTV;$NTXST;$SPACE;$TXSTR;,INFORM;NINFOM;NTXTDS;PICREP;SCAMAX;SCAMIN;TXTDSC;,RECDAT;RECIND;SORDAT;SORIND;,$,
-17000,Anchor berth,achbrt,catach;clsdng;comctn;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;RADIUS;restrn;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
-17001,Anchorage area,achare,catach;clsdng;comctn;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;restrn;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
-17002,Canal bank,canbnk,catbnk;CONRAD;DATEND;DATSTA;NATSUR;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;
-17003,Depth area,depare,DRVAL1;DRVAL2;eleva1;eleva2;wtwdis;QUASOU;SOUACC;verdat;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;Area;
-17004,Distance mark,dismar,catdis;DATEND;DATSTA;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17005,Restricted area,resare,CATREA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;restrn;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17006,River bank,rivbnk,catbnk;CONRAD;NATSUR;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;
-17007,Signal station traffic,sistat,catsit;COMCHA;DATEND;DATSTA;dirimp;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17008,Signal station warning,sistaw,catsiw;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17009,Top Mark,topmar,COLOUR;COLPAT;HEIGHT;marsys;STATUS;TOPSHP;VERACC;verdat;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17010,Berth berths,berths,catbrt;clsdng;comctn;DATEND;DATSTA;DRVAL1;NOBJNM;OBJNAM;PEREND;PERSTA;QUASOU;SOUACC;STATUS;trshgd;verdat;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Line;Area;
-17011,"Bridge","bridge",catbrg;comctn;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;HORACC;HORCLR;NATCON;NOBJNM;OBJNAM;TIMEND;TIMSTA;VERACC;VERCCL;VERCLR;VERCOP;verdat;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Line;Area;
-17012,Cable overhead,cblohd,CATCBL;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;ICEFAC;NOBJNM;OBJNAM;STATUS;VERACC;VERCLR;VERCSA;verdat;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;RECDAT;RECIND;,SORDAT;SORIND;,G,Line;
-17013,Ferry route,feryrt,catfry;comctn;DATEND;DATSTA;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;Area;
-17014,Harbour Area,hrbare,cathbr;comctn;NOBJNM;OBJNAM;STATUS;unlocd;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17015,Harbour Facilities,hrbfac,cathaf;CONDTN;DATEND;DATSTA;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
-17016,Lock Basin,lokbsn,HORACC;horcll;horclw;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17017,Radio calling-in point,rdocal,catcom;comctn;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;ORIENT;PEREND;PERSTA;STATUS;TRAFIC;dirimp;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Line;
-17018,Navigational system of marks,m_nsys,marsys;ORIENT;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17050,Notice mark,notmrk,catnmk;fnctnm;dirimp;disipd;disipu;disbk1;disbk2;addmrk;marsys;ORIENT;CONDTN;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17051,Waterway axis,wtwaxs,catccl;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Line;
-17052,Waterway profile,wtwprf,wtwdis;HEIGHT;verdat;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Line;
-17053,Bridge area,brgare,comctn;NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17054,Bunker station,bunsta,bunves;catbun;comctn;NOBJNM;OBJNAM;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17055,Communication Area,comare,catcom;COMCHA;DATEND;DATSTA;NOBJNM;OBJNAM;STATUS;TIMEND;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17056,Harbour Basin,hrbbsn,HORACC;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17057,Lock area,lokare,comctn;NOBJNM;OBJNAM;STATUS;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17058,Lock basin part,lkbspt,HORACC;horcll;horclw;HORLEN;HORWID;NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17059,Port Area,prtare,comctn;NOBJNM;OBJNAM;STATUS;unlocd;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Area;
-17060,Beacon water-way,bcnwtw,BCNSHP;catwwm;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;dirimp;ELEVAT;HEIGHT;marsys;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERACC;verdat;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17061,Buoy water-way,boywtw,BOYSHP;catwwm;COLOUR;COLPAT;CONDTN;CONRAD;CONVIS;DATEND;DATSTA;marsys;NATCON;NOBJNM;OBJNAM;PEREND;PERSTA;STATUS;VERLEN;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17062,Refuse dump,refdmp,catrfd;comctn;NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17063,Route planning point,rtplpt,NOBJNM;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;
-17064,Terminal,termnl,cattml;comctn;NOBJNM;OBJNAM;STATUS;TIMEND;TIMSTA;trshgd;unlocd;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
-17065,Turning basin,trnbsn,HORCLR;NOBJNM;STATUS;OBJNAM;,INFORM;NINFOM;NTXTDS;PICREP;SCAMIN;TXTDSC;updmsg;,SORDAT;SORIND;,G,Point;Area;
diff --git a/data/unit_of_measure.csv b/data/unit_of_measure.csv
index 951bdc1..28c41b7 100644
--- a/data/unit_of_measure.csv
+++ b/data/unit_of_measure.csv
@@ -4,7 +4,10 @@ uom_code,unit_of_meas_name,unit_of_meas_type,target_uom_code,factor_b,factor_c,r
 1026,metres per second,length,1026,1,1,Length rate.,OGP,IOGP,2015/11/25,2013.021 2015.062,0
 1027,millimetres per year,length,1026,1,31556925445,"Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",ISO 1000.,OGP,2013/09/02,2013.021 2013.042,0
 1028,parts per billion,scale,9201,1,1000000000,"Billion is internationally ambiguous, in different languages being 1E+9 and 1E+12. One billion taken here to be 1E+9.",OGP,OGP,2013/05/29,2013.021,0
+1029,year,time,1040,31556925.445,1,,"International Union of Geological Sciences (IUGS) and International Union of Pure and Applied Chemistry (IUPAC). Pure Appl. Chem., Vol. 83, No. 5, pp. 1159–1162, 2011.",OGP,2013/05/28,2013.021,0
+1030,parts per billion per year,scale,1036,1,3.1556925445e+16,"Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029. Billion is internationally ambiguous, in different languages being 1E+9 and 1E+12. One billion taken here to be 1E+9.",ISO 1000.,IOGP,2015/06/24,2013.021 2013.042 2013.067 2015.036,0
 1031,milliarc-second,angle,9101,3.14159265358979,648000000,= ((pi/180) / 3600 / 1000) radians,,IOGP,2015/11/25,2013.021 2015.062,0
+1032,milliarc-seconds per year,angle,1035,3.14159265358979,2.044888768836e+16,"= ((pi/180) / 3600 / 1000) radians per year. Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",,OGP,2013/09/02,2013.021 2013.042,0
 1033,centimetre,length,9001,1,100,,ISO 1000.,IOGP,2015/11/25,2013.021 2015.062,0
 1034,centimetres per year,length,1026,1,3155692544.5,"Year taken to be IUGS definition of 31556925.445 seconds; see UoM code 1029.",ISO 1000.,OGP,2013/09/02,2013.021 2013.042,0
 1035,radians per second,angle,1035,1,1,Angle rate.,OGP,IOGP,2015/11/25,2013.021 2015.062,0
@@ -65,8 +68,8 @@ uom_code,unit_of_meas_name,unit_of_meas_type,target_uom_code,factor_b,factor_c,r
 9107,degree minute second,angle,9102,,,"Degree representation. Format: signed degrees (integer) - arc-minutes (integer) - arc-seconds (real, any precision). Different symbol sets are in use as field separators, for example º ' "". Convert to degrees using algorithm.",OGP,IOGP,2015/11/25,1996.190 2002.070 2002.780 2015.062,0
 9108,degree minute second hemisphere,angle,9102,,,"Degree representation. Format: degrees (integer) - arc-minutes (integer) - arc-seconds (real) - hemisphere abbreviation (single character N S E or W). Different symbol sets are in use as field separators for example º ' "". Convert to deg using algorithm.",OGP,IOGP,2015/11/25,1996.190 2002.070 2002.780 2015.062,0
 9109,microradian,angle,9101,1,1000000,rad * 10E-6,ISO 1000.,OGP,1996/10/18,1999.050,0
-9110,sexagesimal DMS,angle,9102,,,Pseudo unit. Format: signed degrees - period - minutes (2 digits) - integer seconds (2 digits) - fraction of seconds (any precision). Must include leading zero in minutes and seconds and exclude decimal point for seconds. Convert to degree using formula.,OGP,IOGP,2015/11/25,2002.270 2002.780 2008.020 2015.062,0
-9111,sexagesimal DM,angle,9102,,,Pseudo unit. Format: sign - degrees - decimal point - integer minutes (two digits) - fraction of minutes (any precision).  Must include leading zero in integer minutes.  Must exclude decimal point for minutes.  Convert to deg using algorithm.,OGP,IOGP,2015/11/25,2002.070 2002.780 2015.062,0
+9110,sexagesimal DMS,angle,9102,,,Pseudo unit. Format: signed degrees - period - minutes (2 digits) - integer seconds (2 digits) - fraction of seconds (any precision). Must include leading zero in minutes and seconds and exclude decimal point for seconds. Convert to deg using algorithm.,OGP,IOGP,2016/12/15,2002.270 2002.780 2008.020 2015.062 2016.047,0
+9111,sexagesimal DM,angle,9102,,,Pseudo unit. Format: signed degrees - period - integer minutes (2 digits) - fraction of minutes (any precision). Must include leading zero in minutes and exclude decimal point for minutes. Convert to degree using algorithm.,OGP,IOGP,2016/12/15,2002.070 2002.780 2015.062 2016.047,0
 9112,centesimal minute,angle,9101,3.14159265358979,20000,1/100 of a grad and gon = ((pi/200) / 100) radians,http://www.geodesy.matav.hu/,IOGP,2015/11/25,1998.480 1999.510 2002.860 2005.460 2015.062,0
 9113,centesimal second,angle,9101,3.14159265358979,2000000,"1/100 of a centesimal minute or 1/10,000th of a grad and gon = ((pi/200) / 10000) radians",http://www.geodesy.matav.hu/,IOGP,2015/11/25,1999.510 2002.860 2005.460 2015.062,0
 9114,mil_6400,angle,9101,3.14159265358979,3200,Angle subtended by 1/6400 part of a circle.  Approximates to 1/1000th radian.  Note that other approximations (notably 1/6300 circle and 1/6000 circle) also exist.,http://www.geodesy.matav.hu/,IOGP,2015/11/25,1999.510 2005.460 2015.062,0
@@ -76,7 +79,7 @@ uom_code,unit_of_meas_name,unit_of_meas_type,target_uom_code,factor_b,factor_c,r
 9118,degree minute hemisphere,angle,9102,,,"Degree representation. Format: degrees (integer) - arc-minutes (real, any precision) - hemisphere abbreviation (single character N S E or W). Different symbol sets are in use as field separators, for example º '. Convert to degrees using algorithm.",OGP,IOGP,2015/11/25,2015.062,0
 9119,hemisphere degree minute,angle,9102,,,"Degree representation. Format:  hemisphere abbreviation (single character N S E or W) - degrees (integer) - arc-minutes (real, any precision). Different symbol sets are in use as field separators, for example º '. Convert to degrees using algorithm.",OGP,IOGP,2015/11/25,2015.062,0
 9120,hemisphere degree minute second,angle,9102,,,"Degree representation. Format: hemisphere abbreviation (single character N S E or W) - degrees (integer) - arc-minutes (integer) - arc-seconds (real). Different symbol sets are in use as field separators for example º ' "". Convert to deg using algorithm.",OGP,IOGP,2015/11/25,2015.062,0
-9121,sexagesimal DMS.s,angle,9102,,,"Pseudo unit. Format: signed degrees - minutes (two digits) - seconds (real, any precision). Must include leading zero in minutes and seconds where value is under 10 and include decimal separator for seconds. Convert to degree using algorithm.",ISO 6709:1983.,IOGP,2015/11/25,2015.062,0
+9121,sexagesimal DMS.s,angle,9104,,,Pseudo unit. Format: signed degrees - minutes (2 digits) - integer seconds (2 digits) - period - fraction of seconds (any precision). Must include leading zero in minutes and seconds and include decimal point for seconds. Convert to deg using algorithm.,ISO 6709:1983.,IOGP,2016/12/15,2015.062 2016.047,0
 9122,degree (supplier to define representation),angle,9101,3.14159265358979,180,"= pi/180 radians. The degree representation (e.g. decimal, DMSH, etc.) must be clarified by suppliers of data associated with this code.",OGP,IOGP,2015/11/25,2015.062,0
 9201,unity,scale,9201,1,1,,,IOGP,2015/11/25,2015.062,0
 9202,parts per million,scale,9201,1,1000000,,,IOGP,2015/11/25,2013.021 2013.037 2015.062,0
diff --git a/data/vertcs.csv b/data/vertcs.csv
index 7af97c8..9fdc763 100644
--- a/data/vertcs.csv
+++ b/data/vertcs.csv
@@ -115,7 +115,7 @@
 5782,Alicante height,5180,Alicante,9001,1,0,6499,,
 5783,DHHN92 height,5181,Deutsches Haupthoehennetz 1992,9001,1,0,6499,,
 5784,DHHN85 height,5182,Deutsches Haupthoehennetz 1985,9001,1,0,6499,,
-5785,SNN76 height,5183,SNN76,9001,1,0,6499,,
+5785,SNN76 height,5183,Staatlichen Nivellementnetzes 1976,9001,1,0,6499,,
 5786,Baltic 1982 height,5184,Baltic 1982,9001,1,0,6499,,
 5787,EOMA 1980 height,5185,Baltic 1980,9001,1,0,6499,,
 5788,Kuwait PWD height,5186,Kuwait PWD,9001,1,0,6499,,
@@ -181,3 +181,13 @@
 7447,PNG08 height,1149,PNG08,9001,1,0,6499,,
 7651,Kumul 34 height,1150,Kumul 34,9001,1,0,6499,,
 7652,Kiunga height,1151,Kiunga,9001,1,0,6499,,
+7699,DHHN12 height,1161,Deutsches Haupthoehennetz 1912,9001,1,0,6499,,
+7700,Latvia 2000 height,1162,Latvian Height System 2000,9001,1,0,6499,,
+7707,"ODN (Offshore) height",1164,"Ordnance Datum Newlyn (Offshore)",9001,1,0,6499,,
+7832,POM96 height,1171,Port Moresby 1996,9001,1,0,6499,,
+7837,DHHN2016 height,1170,Deutsches Haupthoehennetz 2016,9001,1,0,6499,,
+7839,NZVD2016 height,1169,New Zealand Vertical Datum 2016,9001,1,0,6499,,
+7841,POM08 height,1172,Port Moresby 2008,9001,1,0,6499,,
+7888,Jamestown 1971 height,1175,Jamestown 1971,9001,1,0,6499,,
+7889,St. Helena Tritan 2011 height,1176,St. Helena Tritan Vertical Datum 2011,9001,1,0,6499,,
+7890,SHVD2015 height,1177,St. Helena Vertical Datum 2015,9001,1,0,6499,,
diff --git a/doc/api.dox b/doc/api.dox
index fd24c34..0d0c87c 100644
--- a/doc/api.dox
+++ b/doc/api.dox
@@ -7,17 +7,17 @@
 GDALProcessFunc is a typedef defining the signature of functions to be
 used with GDAL as callbacks to report the progress of long running processes.
 Typically these are functions that would update a GUI progress bar showing how
-much of a process is done. 
+much of a process is done.
 
 A number of GDAL functions and methods accept GDALProcessFunc arguments along
-with an opaque application supplied data item (pProgressArg) which are then 
+with an opaque application supplied data item (pProgressArg) which are then
 used to implement progress reporting.  The GDALDataset::BuildOverviews(), and
 GDALDriver::CreateCopy() methods are examples of two methods that utilize
 the progress semantics.
 
 \code
-  int (*GDALProgressFunc)(double dfComplete, const char *pszMessage, 
-		          void *pProgressArg);
+  int (*GDALProgressFunc)(double dfComplete, const char *pszMessage,
+                          void *pProgressArg);
 \endcode
 
 @param dfComplete The ratio of completeness of the process from 0.0 for just
@@ -25,8 +25,8 @@ started to 1.0 for completed.
 
 @param pszMessage An optional message string to display.  This is usually NULL.
 
- at param pProgressArg Application supplied opaque data normally used by the 
-callback to display the result. 
+ at param pProgressArg Application supplied opaque data normally used by the
+callback to display the result.
 
 @return TRUE if the operation should continue or FALSE if the user has
 requested a cancel.
@@ -44,7 +44,7 @@ text progress reporting mechanism, using pData to pass a default message:
                  (char) pData );
      else
          printf( "%d%% complete.\n", (int) (dfComplete*100) );
-     
+
      return TRUE;
  }
 \endcode
@@ -55,22 +55,22 @@ this:
 \code
       int       anOverviewList[3] = {2, 4, 8};
 
-      poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, NULL, 
+      poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, NULL,
                                  MyTextProgress, "building overviews" );
 \endcode
 
 In addition to reporting progress to the user, the GDALProcessFunc mechanism
 also provides a mechanism for a user interface to return a request from the
 user to cancel the operation to the algorithm via the return value.  If FALSE
-is returned, the algorithm should terminate the operation and return as 
+is returned, the algorithm should terminate the operation and return as
 quickly as possible.
- 
-More often that implementing custom progress functions, applications 
-will just use existing progress functions like GDALDummyProgress(), 
-GDALTermProgress() and GDALScaledProgress().  Python scripts also can pass 
+
+More often that implementing custom progress functions, applications
+will just use existing progress functions like GDALDummyProgress(),
+GDALTermProgress() and GDALScaledProgress().  Python scripts also can pass
 progress functions.
 
-Application code implementing GDALProgressFunc semantics should remember 
+Application code implementing GDALProgressFunc semantics should remember
 a few things:
 <ol>
 <li> Be wary of NULL progress functions being passed in.  The pfnProgress
@@ -80,7 +80,7 @@ argument can be set to GDALDummyProgress() in this case for simplicity.
 operation should be terminated.
 
 <li> The ratio of completeness should vary from 0.0 to 1.0.  Please ensure the
-exact value 1.0 is always returned at the end of the algorithm as some 
-GUI display mechanisms use this as a clue to pop down the progress monitor. 
+exact value 1.0 is always returned at the end of the algorithm as some
+GUI display mechanisms use this as a clue to pop down the progress monitor.
 
 */
diff --git a/doc/br/Doxyfile b/doc/br/Doxyfile
index ba6edc8..4bbffb6 100644
--- a/doc/br/Doxyfile
+++ b/doc/br/Doxyfile
@@ -1,1138 +1,1136 @@
-# Doxyfile 1.4.2
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
-# by quotes) that should identify the project.
-
-PROJECT_NAME           = BR
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
-# This could be handy for archiving the generated documentation or 
-# if some version control system is used.
-
-PROJECT_NUMBER         = 
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY       = 
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
-# documentation generated by doxygen is written. Doxygen will use this 
-# information to generate all constant output in the proper language. 
-# The default language is English, other supported languages are: 
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
-# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
-# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
-# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
-# Swedish, and Ukrainian.
-
-OUTPUT_LANGUAGE        = Brazilian
-
-# This tag can be used to specify the encoding used in the generated output. 
-# The encoding is not always determined by the language that is chosen, 
-# but also whether or not the output is meant for Windows or non-Windows users. 
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
-# forces the Windows encoding (this is the default for the Windows binary), 
-# whereas setting the tag to NO uses a Unix-style encoding (the default for 
-# all platforms other than Windows).
-
-USE_WINDOWS_ENCODING   = NO
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
-# include brief member descriptions after the members that are listed in 
-# the file and class documentation (similar to JavaDoc). 
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
-# the brief description of a member or function before the detailed description. 
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF           = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator 
-# that is used to form the text in various listings. Each string 
-# in this list, if found as the leading text of the brief description, will be 
-# stripped from the text and the result after processing the whole list, is 
-# used as the annotated text. Otherwise, the brief description is used as-is. 
-# If left blank, the following values are used ("$name" is automatically 
-# replaced with the name of the entity): "The $name class" "The $name widget" 
-# "The $name file" "is" "provides" "specifies" "contains" 
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF       = 
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
-# Doxygen will generate a detailed section even if there is only a brief 
-# description.
-
-ALWAYS_DETAILED_SEC    = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
-# inherited members of a class in the documentation of that class as if those 
-# members were ordinary class members. Constructors, destructors and assignment 
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB  = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
-# path before files name in the file list and in the header files. If set 
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES        = NO
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
-# the path mentioned in the documentation of a class, which tells 
-# the reader which header file to include in order to use a class. 
-# If left blank only the name of the header file containing the class 
-# definition is used. Otherwise one should specify the include paths that 
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH    = 
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
-# (but less readable) file names. This can be useful is your file systems 
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES            = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
-# will interpret the first line (until the first dot) of a JavaDoc-style 
-# comment as the brief description. If set to NO, the JavaDoc 
-# comments will behave just like the Qt-style comments (thus requiring an 
-# explicit @brief command for a brief description.
-
-JAVADOC_AUTOBRIEF      = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
-# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
-# comments) as a brief description. This used to be the default behaviour. 
-# The new default is to treat a multi-line C++ comment block as a detailed 
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member 
-# documentation.
-
-DETAILS_AT_TOP         = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
-# member inherits the documentation from any documented member that it 
-# re-implements.
-
-INHERIT_DOCS           = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE               = 8
-
-# This tag can be used to specify a number of aliases that acts 
-# as commands in the documentation. An alias has the form "name=value". 
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
-# put the command \sideeffect (or @sideeffect) in the documentation, which 
-# will result in a user-defined paragraph with heading "Side Effects:". 
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES                = 
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
-# sources only. Doxygen will then generate output that is more tailored for C. 
-# For instance, some of the names that are used will be different. The list 
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C  = NO
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
-# only. Doxygen will then generate output that is more tailored for Java. 
-# For instance, namespaces will be presented as packages, qualified scopes 
-# will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA   = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
-# the same type (for instance a group of public functions) to be put as a 
-# subgroup of that type (e.g. under the Public Functions section). Set it to 
-# NO to prevent subgrouping. Alternatively, this can be done per class using 
-# the \nosubgrouping command.
-
-SUBGROUPING            = YES
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
-# documentation are documented, even if no documentation was available. 
-# Private class members and static file members will be hidden unless 
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL            = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
-# will be included in the documentation.
-
-EXTRACT_PRIVATE        = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file 
-# will be included in the documentation.
-
-EXTRACT_STATIC         = NO
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
-# defined locally in source files will be included in the documentation. 
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES  = YES
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
-# undocumented members of documented classes, files or namespaces. 
-# If set to NO (the default) these members will be included in the 
-# various overviews, but no documentation section is generated. 
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS     = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
-# undocumented classes that are normally visible in the class hierarchy. 
-# If set to NO (the default) these classes will be included in the various 
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES     = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
-# friend (class|struct|union) declarations. 
-# If set to NO (the default) these declarations will be included in the 
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS  = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
-# documentation blocks found inside the body of a function. 
-# If set to NO (the default) these blocks will be appended to the 
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS      = NO
-
-# The INTERNAL_DOCS tag determines if documentation 
-# that is typed after a \internal command is included. If the tag is set 
-# to NO (the default) then the documentation will be excluded. 
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS          = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
-# file names in lower-case letters. If set to YES upper-case letters are also 
-# allowed. This is useful if you have classes or files whose names only differ 
-# in case and if your file system supports case sensitive file names. Windows 
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES       = YES
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
-# will show members with their full class and namespace scopes in the 
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
-# will put a list of the files that are included by a file in the documentation 
-# of that file.
-
-SHOW_INCLUDE_FILES     = YES
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
-# is inserted in the documentation for inline members.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
-# will sort the (detailed) documentation of file and class members 
-# alphabetically by member name. If set to NO the members will appear in 
-# declaration order.
-
-SORT_MEMBER_DOCS       = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
-# brief documentation of file, namespace and class members alphabetically 
-# by member name. If set to NO (the default) the members will appear in 
-# declaration order.
-
-SORT_BRIEF_DOCS        = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
-# sorted by fully-qualified names, including namespaces. If set to 
-# NO (the default), the class list will be sorted only by class name, 
-# not including the namespace part. 
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the 
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME     = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or 
-# disable (NO) the todo list. This list is created by putting \todo 
-# commands in the documentation.
-
-GENERATE_TODOLIST      = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or 
-# disable (NO) the test list. This list is created by putting \test 
-# commands in the documentation.
-
-GENERATE_TESTLIST      = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or 
-# disable (NO) the bug list. This list is created by putting \bug 
-# commands in the documentation.
-
-GENERATE_BUGLIST       = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
-# disable (NO) the deprecated list. This list is created by putting 
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional 
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS       = 
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
-# the initial value of a variable or define consists of for it to appear in 
-# the documentation. If the initializer consists of more lines than specified 
-# here it will be hidden. Use a value of 0 to hide initializers completely. 
-# The appearance of the initializer of individual variables and defines in the 
-# documentation can be controlled using \showinitializer or \hideinitializer 
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES  = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
-# at the bottom of the documentation of classes and structs. If set to YES the 
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES        = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated 
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET                  = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are 
-# generated by doxygen. Possible values are YES and NO. If left blank 
-# NO is used.
-
-WARNINGS               = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED   = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
-# potential errors in the documentation, such as not documenting some 
-# parameters in a documented function, or documenting parameters that 
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR      = YES
-
-# The WARN_FORMAT tag determines the format of the warning messages that 
-# doxygen can produce. The string should contain the $file, $line, and $text 
-# tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text. Optionally the format may contain 
-# $version, which will be replaced by the version of the file (if it could 
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT            = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning 
-# and error messages should be written. If left blank the output is written 
-# to stderr.
-
-WARN_LOGFILE           = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
-# with spaces.
-
-INPUT                  = .
-
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank the following patterns are tested: 
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
-
-FILE_PATTERNS          = *.h \
-                         *.cpp \
-                         *.c \
-                         *.dox
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
-# should be searched for input files as well. Possible values are YES and NO. 
-# If left blank NO is used.
-
-RECURSIVE              = NO
-
-# The EXCLUDE tag can be used to specify files and/or directories that should 
-# excluded from the INPUT source files. This way you can easily exclude a 
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE                = 
-
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
-# directories that are symbolic links (a Unix filesystem feature) are excluded 
-# from the input.
-
-EXCLUDE_SYMLINKS       = NO
-
-# If the value of the INPUT tag contains directories, you can use the 
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
-# certain files from those directories.
-
-EXCLUDE_PATTERNS       = 
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
-# the \include command).
-
-EXAMPLE_PATH           = apps \
-                         frmts \
-                         frmts/jdem 
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included.
-
-EXAMPLE_PATTERNS       = 
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
-# searched for input files to be used with the \include or \dontinclude 
-# commands irrespective of the value of the RECURSIVE tag. 
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE      = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or 
-# directories that contain image that are included in the documentation (see 
-# the \image command).
-
-IMAGE_PATH             = 
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should 
-# invoke to filter for each input file. Doxygen will invoke the filter program 
-# by executing (via popen()) the command <filter> <input-file>, where <filter> 
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
-# input file. Doxygen will then use the output that the filter program writes 
-# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
-# ignored.
-
-INPUT_FILTER           = 
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
-# INPUT_FILTER) will be used to filter the input files when producing source 
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES    = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-# Note: To get rid of all source code in the generated output, make sure also 
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER         = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body 
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES         = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
-# doxygen to hide any special comment blocks from generated source code 
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS    = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
-# then for each documented function all documented 
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = YES
-
-# If the REFERENCES_RELATION tag is set to YES (the default) 
-# then for each documented function all documented entities 
-# called/used by that function will be listed.
-
-REFERENCES_RELATION    = YES
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
-# will generate a verbatim copy of the header file for each class for 
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS       = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
-# of all compounds will be generated. Enable this if the project 
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX     = NO
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX    = 5
-
-# In case all classes in a project start with a common prefix, all 
-# classes will be put under the same header in the alphabetical index. 
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX          = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
-# generate HTML output.
-
-GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT            = 
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION    = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard header.
-
-HTML_HEADER            = 
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard footer.
-
-HTML_FOOTER            = ../gdal_footer.html
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
-# style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet. Note that doxygen will try to copy 
-# the style sheet file to the HTML output directory, so don't put your own 
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET        = 
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS     = YES
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
-# will be generated that can be used as input for tools like the 
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP      = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
-# be used to specify the file name of the resulting .chm file. You 
-# can add a path in front of the file if the result should not be 
-# written to the html output directory.
-
-CHM_FILE               = 
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
-# be used to specify the location (absolute path including file name) of 
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION           = 
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
-# controls if a separate .chi index file is generated (YES) or that 
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI           = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
-# controls whether a binary table of contents is generated (YES) or a 
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members 
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND             = NO
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
-# the value YES disables it.
-
-DISABLE_INDEX          = NO
-
-# This tag can be used to set the number of enum values (range [1..20]) 
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that 
-# is generated for HTML Help). For this to work a browser that supports 
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
-# probably better off using the HTML help feature.
-
-GENERATE_TREEVIEW      = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
-# used to set the initial width (in pixels) of the frame in which the tree 
-# is shown.
-
-TREEVIEW_WIDTH         = 250
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
-# generate Latex output.
-
-GENERATE_LATEX         = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT           = 
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
-# invoked. If left blank `latex' will be used as the default command name.
-
-LATEX_CMD_NAME         = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
-# generate index for LaTeX. If left blank `makeindex' will be used as the 
-# default command name.
-
-MAKEINDEX_CMD_NAME     = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
-# LaTeX documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_LATEX          = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used 
-# by the printer. Possible values are: a4, a4wide, letter, legal and 
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE             = a4wide
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES         = 
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
-# the generated latex document. The header should contain everything until 
-# the first chapter. If it is left blank doxygen will generate a 
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER           = 
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
-# contain links (just like the HTML output) instead of page references 
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS         = NO
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
-# plain latex in the generated Makefile. Set this option to YES to get a 
-# higher quality PDF documentation.
-
-USE_PDFLATEX           = NO
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
-# command to the generated LaTeX files. This will instruct LaTeX to keep 
-# running if errors occur, instead of asking the user for help. 
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE        = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
-# include the index chapters (such as File Index, Compound Index, etc.) 
-# in the output.
-
-LATEX_HIDE_INDICES     = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
-# The RTF output is optimized for Word 97 and may not look very pretty with 
-# other RTF readers or editors.
-
-GENERATE_RTF           = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT             = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
-# RTF documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_RTF            = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
-# will contain hyperlink fields. The RTF file will 
-# contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using WORD or other 
-# programs which support those fields. 
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS         = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
-# config file, i.e. a series of assignments. You only have to provide 
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE    = 
-
-# Set optional variables used in the generation of an rtf document. 
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE    = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
-# generate man pages
-
-GENERATE_MAN           = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT             = man
-
-# The MAN_EXTENSION tag determines the extension that is added to 
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION          = .1
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
-# then it will generate one additional man file for each entity 
-# documented in the real man page(s). These additional files 
-# only source the real man page, but without them the man command 
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS              = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will 
-# generate an XML file that captures the structure of 
-# the code including all documentation.
-
-GENERATE_XML           = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT             = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_SCHEMA             = 
-
-# The XML_DTD tag can be used to specify an XML DTD, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_DTD                = 
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
-# dump the program listings (including syntax highlighting 
-# and cross-referencing information) to the XML output. Note that 
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING     = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
-# generate an AutoGen Definitions (see autogen.sf.net) file 
-# that captures the structure of the code including all 
-# documentation. Note that this feature is still experimental 
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF   = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
-# generate a Perl module file that captures the structure of 
-# the code including all documentation. Note that this 
-# feature is still experimental and incomplete at the 
-# moment.
-
-GENERATE_PERLMOD       = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX          = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
-# nicely formatted so it can be parsed by a human reader.  This is useful 
-# if you want to understand what is going on.  On the other hand, if this 
-# tag is set to NO the size of the Perl module output will be much smaller 
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY         = YES
-
-# The names of the make variables in the generated doxyrules.make file 
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
-# This is useful so different doxyrules.make files included by the same 
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
-# evaluate all C-preprocessor directives found in the sources and include 
-# files.
-
-ENABLE_PREPROCESSING   = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
-# names in the source code. If set to NO (the default) only conditional 
-# compilation will be performed. Macro expansion can be done in a controlled 
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION        = YES
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
-# then the macro expansion is limited to the macros specified with the 
-# PREDEFINED and EXPAND_AS_PREDEFINED tags.
-
-EXPAND_ONLY_PREDEF     = YES
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES        = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that 
-# contain include files that are not input files but should be processed by 
-# the preprocessor.
-
-INCLUDE_PATH           = 
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
-# patterns (like *.h and *.hpp) to filter out the header-files in the 
-# directories. If left blank, the patterns specified with FILE_PATTERNS will 
-# be used.
-
-INCLUDE_FILE_PATTERNS  = 
-
-# The PREDEFINED tag can be used to specify one or more macro names that 
-# are defined before the preprocessor is started (similar to the -D option of 
-# gcc). The argument of the tag is a list of macros of the form: name 
-# or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed. To prevent a macro definition from being 
-# undefined via #undef or recursively expanded use the := operator 
-# instead of the = operator.
-
-PREDEFINED             = HAVE_DLFCN_H \
-                         CPL_DLL \
-                         CPL_STDCALL \
-                         CPL_C_START \
-                         CPL_C_END \
-                         __cplusplus \
-                         DOXYGEN_SKIP
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
-# this tag can be used to specify a list of macro names that should be expanded. 
-# The macro definition that is found in the sources will be used. 
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED      = 
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
-# doxygen's preprocessor will remove all function-like macros that are alone 
-# on a line, have an all uppercase name, and do not end with a semicolon. Such 
-# function macros are typically used for boiler-plate code, and will confuse 
-# the parser if not removed.
-
-SKIP_FUNCTION_MACROS   = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references   
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles. 
-# Optionally an initial location of the external documentation 
-# can be added for each tagfile. The format of a tag file without 
-# this location is as follows: 
-#   TAGFILES = file1 file2 ... 
-# Adding location for the tag files is done as follows: 
-#   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool 
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen 
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES               = 
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE       = 
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
-# in the class index. If set to NO only the inherited external classes 
-# will be listed.
-
-ALLEXTERNALS           = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
-# in the modules index. If set to NO, only the current project's groups will 
-# be listed.
-
-EXTERNAL_GROUPS        = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script 
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH              = /usr/local/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
-# or super classes. Setting the tag to NO turns the diagrams off. Note that 
-# this option is superseded by the HAVE_DOT option below. This is only a 
-# fallback. It is recommended to install and use dot, since it yields more 
-# powerful graphs.
-
-CLASS_DIAGRAMS         = YES
-
-# If set to YES, the inheritance and collaboration graphs will hide 
-# inheritance and usage relations if the target is undocumented 
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS   = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
-# available from the path. This tool is part of Graphviz, a graph visualization 
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT               = NO
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect inheritance relations. Setting this tag to YES will force the 
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH            = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect implementation dependencies (inheritance, containment, and 
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH    = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
-# collaboration diagrams in a style similar to the OMG's Unified Modeling 
-# Language.
-
-UML_LOOK               = NO
-
-# If set to YES, the inheritance and collaboration graphs will show the 
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS     = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
-# tags are set to YES then doxygen will generate a graph for each documented 
-# file showing the direct and indirect include dependencies of the file with 
-# other documented files.
-
-INCLUDE_GRAPH          = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
-# documented header file showing the documented files that directly or 
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH      = YES
-
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
-# generate a call dependency graph for every global function or class method. 
-# Note that enabling this option will significantly increase the time of a run. 
-# So in most cases it will be better to enable call graphs for selected 
-# functions only using the \callgraph command.
-
-CALL_GRAPH             = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY    = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
-
-DOT_IMAGE_FORMAT       = png
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be 
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH               = 
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that 
-# contain dot files that are included in the documentation (see the 
-# \dotfile command).
-
-DOTFILE_DIRS           = 
-
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_WIDTH    = 1024
-
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_HEIGHT   = 1024
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
-# graphs generated by dot. A depth value of 3 means that only nodes reachable 
-# from the root by following a path via at most 3 edges will be shown. Nodes 
-# that lay further from the root node will be omitted. Note that setting this 
-# option to 1 or 2 may greatly reduce the computation time needed for large 
-# code bases. Also note that a graph may be further truncated if the graph's 
-# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
-# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
-# the graph is not depth-constrained.
-
-MAX_DOT_GRAPH_DEPTH    = 0
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
-# generate a legend page explaining the meaning of the various boxes and 
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND        = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
-# remove the intermediate dot files that are used to generate 
-# the various graphs.
-
-DOT_CLEANUP            = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE           = NO
+# Doxyfile 1.4.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = BR
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = Brazilian
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+#USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+#DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = .
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = *.h \
+                         *.cpp \
+                         *.c \
+                         *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            =
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            = ../gdal_footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+#HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           =
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .1
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             = HAVE_DLFCN_H \
+                         CPL_DLL \
+                         CPL_STDCALL \
+                         CPL_C_START \
+                         CPL_C_END \
+                         __cplusplus \
+                         DOXYGEN_SKIP
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/local/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+#MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+#MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/doc/br/gdal_building_br.dox b/doc/br/gdal_building_br.dox
index 2cec01f..3305452 100644
--- a/doc/br/gdal_building_br.dox
+++ b/doc/br/gdal_building_br.dox
@@ -1,9 +1,9 @@
-#ifndef DOXYGEN_SKIP
-/* $Id: gdal_building_br.dox $ */
-#endif /* DOXYGEN_SKIP */
-
-/*! \page gdal_building_br Como compilar GDAL
-
-Este tópico mudo-se para o endereço wiki: http://trac.osgeo.org/gdal/wiki/BuildHints
-
-*/
+#ifndef DOXYGEN_SKIP
+/* $Id: gdal_building_br.dox $ */
+#endif /* DOXYGEN_SKIP */
+
+/*! \page gdal_building_br Como compilar GDAL
+
+Este tópico mudo-se para o endereço wiki: http://trac.osgeo.org/gdal/wiki/BuildHints
+
+*/
diff --git a/doc/br/gdal_datamodel_br.dox b/doc/br/gdal_datamodel_br.dox
index d25286e..374b038 100644
--- a/doc/br/gdal_datamodel_br.dox
+++ b/doc/br/gdal_datamodel_br.dox
@@ -1,310 +1,310 @@
-/* $Id: gdal_datamodel_br.dox $ */
-
-/*! \page gdal_datamodel_br Modelo de Dados de GDAL
-
-Este documento descreve o Modelo de Dados implementado pela bilbioteca GDAL, 
-os tipos de informação que GDAL pode conter e a sua semântica.<p>
-
-\section gdal_datamodel_dataset Dataset
-
-Um dataset (representado pela classe GDALDataset) é um agrupamento de bandas 
-"raster" e um conjunto de informação comum a estas bandas. 
-Em particular, um dataset possui o conceito de tamanho (em pixels e em linhas)
-que se aplica à todas as bandas. 
-O Dataset também é reponsável pelas definições de referência geográficas e
-sistema de coordenadas comum a todas as bandas.
-O Dataset também pode possuir metadado, representado por uma lista de strings no formato de pares nome=valor.
-
-Note que o GDALDataet e o modelo de bandas "raster" em GDAL são ligeiramente baseados na 
-especificação do "Grid Coverage" do OpenGIS (OGC).
-
-\subsection gdal_datamodel_dataset_cs Sistema de Coordenadas
-
-O sistema de coordenadas de um dataset é representado por uma string no 
-formato "Well Kown Text" que contém:
-
-<ul>
-<li> Nome geral para o sistema de coordenadas.
-<li> Nome do sistema de coordenadas geográficas.
-<li> Nome do datum.
-<li> Nome da Elipsóide, semi-eixo maior e o inverso do achatamento.
-<li> Nome do meridiano de origem e sua distância de Greenwich. 
-<li> Nome da projeção (ex. Transverse Mercator). 
-<li> Lista de parâmetros de projeção (ex. central_meridian). 
-<li> Nome das unidades e fator de conversão para metros ou radianos.
-<li> Nome e order dos eixos.
-<li> Códigos para relacionar a maioria dos items acima com tabelas de autoridades tais como EPSG. 
-</ul>
-
-Para maiores informações sobre o sistema de coordenadas OpenGIS WKT, e seu o mecanismo 
-de manipulação, refira-se ao documento <a href="ogr/osr_tutorial.html">
-osr_tutorial</a> e/ou a documentação da classe OGRSpatialReference.
-
-O sistema de coordenadas retornado pelo método GDALDataset::GetProjectionRef()
-descreve as coordenadas geo-referenciadas que devem ser usadas na transformação afim
-retornada pelo método GDALDataset::GetGeoTransform().
-O sistema de coordenadas retornado pelo métido GDALDataset::GetGCPProjection()
-descreve as coordenadas geo-referenciadas dos GCPs (Ground Control Points ou ponto de controle
-na superficíe) retornados pelo
-método GDALDataset::GetGCPs().
-
-Note que a string do sistema de coordenada retornado for "" isto
-indica que nada se sabe sobre o sistema de coordenadas do referido dataset.
-
-\subsection gdal_datamodel_dataset_gtm Transformacao afim
-
-GDAL datasets tem duas formas de descrever o relationamento entre
-poisição em raster (coordenadas de pixel) e coordenadas geográficas.
-O primeiro e mais usado é a transformação afim (o outro usa os GCPs).
-
-A transformação afim consiste em seis coeficiente retornados por
-GDALDataset::GetGeoTransform() que mapeiam coordenadas de pixel/linhas 
-em coordenadas referenciadas spacialmente usango o seguinte relacionamento:
-
-<pre>
-    Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
-    Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
-</pre>
-
-No caso de imagens orientadas em direção ao norte, os coeficientes GT(2) e GT(4) são igual a zero, 
-o GT(1) é a largura en pixels, e GT(5) é a altura en pixels. A posição (GT(0), GT(3))
-é o canto superior esquerdo do pixel no canto superior esquerdo da imagem.
-
-Note que a coordenada pixel/linha neste formato se extendem de (0.0, 0.0) no pixel do canto superior esquerdo
-localizado no canto superior esquerdo da imagem até o canto inferior direito do pixel localizado no canto
-inferior direito da imagem. Consequentement, a coordenada do pixel no canto superior esquerdo é (0.5, 0.5).
-
-\subsection gdal_datamodel_dataset_gcp GCPs
-
-Um dataset pode possuir um conjunto de pontos de controle relacionando uma ou mais posições
-no raster com coordenadas geo-referenciadas. Todos os GCPs compartilham o mesmo sistema
-de coordanadas (retornado pelo GDALDataset::GetGCPProjection()). Cada GCP (representado 
-pelo classe GDAL_GCP) contén as seguintes estrutura:
-
-<pre>
-typedef struct
-{
-    char	*pszId; 
-    char	*pszInfo;
-    double 	dfGCPPixel;
-    double	dfGCPLine;
-    double	dfGCPX;
-    double	dfGCPY;
-    double	dfGCPZ;
-} GDAL_GCP;
-</pre>
-
-A string pszId deve conter um único (e geralmente, mas nem sempre, numérico)
-identificador para cada GCP dentro do conjunto de GCPs do dataset.
-A string pszInfo é usualmente vazia mas pode conter qualquer texto associado ao
-GCP que o usuário defina. Potencialmente pszInfo poderá conter informação, 
-decodificável automaticamente, sobre o estado do GCP. O que no entando ainda não
-tem sido feito até o momento.
-
-Os campos (Pixel, Line) contém a localização do GCP no raster. Os
-campos (X,Y,Z) estão associados com a localixação geo-referenciada sendo 
-que Z é normalmente zero.
-
-O modelo de dados de GDAL nao impõe nenhum mecanismo de transformação para que
-deve ser generado a partir dos GCPs... Isto é deixado para o applicação. No
-entanto polinomios de primeiro a quinto grau são comument utilizados.
-
-Normalmente um dataset ira conter transformações afins (geotransform), GCPs
-or nenhum dos dois. É incomum encontrar os dois e neste caso não existe uma definição
-de qual deve ter precedência.
-
-\subsection gdal_datamodel_dataset_metadata Metadados
-
-O metado do GDAL é um formato auxiliar de dado textual específico 
-para cada aplicação que contém uma lista de pares nome=valor. É requerido
-que os nomes sejam chaves facilmente distintas (sem espaço e caracteres especiais).
-O valor pode ser de qualquer tamanho e pode conter qualquer coisa, exceto um caracter núlo (zero ASCII).
-
-O sistema de manipulação de metadas não é apropriado para suportar grandes volume de metados. 
-Mais de 100K bytes de metada para um dataset provavelmente causará degradação na performance.
-
-Com o tempo espera-se que nomes bem conhecidos sejam identificados e bem estabelicidos semanticamente,
-no entanto isto ainda não tem ocorrido até o momento.
-
-Alguns formatos suportam metados genéricos (definidos pelo usuário), enquanto outros 
-formatos supportam nomes specificos. Por exemplo o TIFF driver retorna algumas de suas
-"tags" na forma de metadas tais como data e hora:
-
-<pre>
-TIFFTAG_DATETIME=1999:05:11 11:29:56
-</pre>
-
-O matado é dividido em grupos chamados domínios (domains). O domínio default
-tem o nome em branco (NULL ou ""). Existem alguns domínios specificos para
-propósitos especiais. Note que correntement não existe uma forma de enumerar
-todos os domínios disponíveis para um dado objeto mas as aplicações podem testar
-a existência de domínios conhecidos.
-
-\subsubsection gdal_datamodel_subdatasets Dominio de SUBDATASETS
-
-Os domínios SUBDATASETS podem listar uma hierarquia de datasets filhos.
-Normalmente isto é usado para prover endereços para várias imagens (ou datasets)
-internas à um único arquivo de images (como HDF ou NITF). Por exemplo, um arquivo
-NITF com quatro imagens pode ter a seguinte lista de subdataset:
-
-<pre>
-  SUBDATASET_1_NAME=NITF_IM:0:multi_1b.ntf
-  SUBDATASET_1_DESC=Image 1 of multi_1b.ntf
-  SUBDATASET_2_NAME=NITF_IM:1:multi_1b.ntf
-  SUBDATASET_2_DESC=Image 2 of multi_1b.ntf
-  SUBDATASET_3_NAME=NITF_IM:2:multi_1b.ntf
-  SUBDATASET_3_DESC=Image 3 of multi_1b.ntf
-  SUBDATASET_4_NAME=NITF_IM:3:multi_1b.ntf
-  SUBDATASET_4_DESC=Image 4 of multi_1b.ntf
-  SUBDATASET_5_NAME=NITF_IM:4:multi_1b.ntf
-  SUBDATASET_5_DESC=Image 5 of multi_1b.ntf
-</pre>
-
-O valor de _NAME é a string que pode ser usada em uma chamada à GDALOpen()
-para acessar o arquivo. O valor de _DESC tem a intensão de apresentar uma
-descrição ao usuário no caso da seleção de subdataset.
-
-\subsubsection gdal_datamodel_image_structure Dominio IMAGE_STRUCTURE 
-
-O domínio defult do metadata ("") está relacionado à image e não particularmente
-a forma como a image é organizada no arquivo.
-Isto significa que este domínio é apropriado para se copiar junto com o dataset
-quanto a image é copida para um novo format.
-Alguma informações pertence somente a um particular format de arquivo e sua forma
-de armazenamento.
-Para que esta informação não seja copiada inadvertidamente este tipo de informação
-é colocado num domínio especial chamado IMAGE_STRUCTURE que não normalmente não deve ser
-copiado de um formato para outro.
-
-Um item que aparece no domínio IMAGE_STRUCTURE é o esquema de compressão usado
-pelo formato. O nome deste item no metada é COMPRESSION mas o valor dele pode
-ser específico para cada formato.
-
-\subsubsection gdal_datamodel_xml Dominio xml:
-
-Qualquer domínio cujo o prefix do nome é "xml:" não é um item de metada normal mas sim
-um único documento XML armazenado numa string longa.
-
-\section gdal_datamodel_rasterband Banda de Imagem Raster
-
-Uma banda de image raster é representada em GDAL pela classe GDALRaseterBand.
-Ela representa uma única banda, canal ou camada. Em GDAL, uma banda não representa 
-necessáriamente uma imagem inteira. Uma imagem 24bit RGB, por exemplo, é normalmente 
-representada por um dataset com três bandas, uma para vermelho, uma pra verde e outra para azul.
-
-Um banda raster tem as seguintes propriedades:
-
-<ul>
-
-<li> Altura e largura em número de pixels e linhas. Pode ser o mesmo valor definido para o
-dataset, caso seje uma banda de resolução total.
-
-<li> Um tipo de dato. Podendo ser Byte, UInt16, Int16, UInt32, Int32, 
-Float32, Float64, and the complex types CInt16, CInt32, CFloat32, and CFloat64.
-
-<li> Um tamanho de bloco, que seria o valor preferido (eficiente) para se acessar 
-um pedaço do arquivo. Para imagens dividida em "tiles" este seria o tamanho de um bloco.
-Para image organizadas por linha de varredura (scanLine), tamalho de bloco seria normalmente 
-uma "scanline".
-
-<li> Lista de pares nome/valor do metada, no mesmo formato que o dataset mas com 
-informações que sejam potencialmente especificas da banda.
-
-<li> Um string com uma descrição opcional
-
-<li> Uma lista de nomes de categorias (efetivamente, nome de classe numa imagem temática)
-
-<li> Opcionalmente, mínimos e máximos valores de pixel.
-
-<li> Opcionalmente, o valor do deslocamento e da escala para transformar os valores de
-banda raster em valores significativoes (ex. para traduzir altura para metros).
-
-<li> Opcionalmente, o nome da unidade do raster. Indicando, por exemplo, a unidade linear 
-para um dado de elevação.
-
-<li> A tipo de interpretação das cores da banda, que pode ser:
-
-  <ul> 
-  <li> GCI_Undefined: O default, Nada ou desconhecido
-  <li> GCI_GrayIndex: Image em toms de cinza independente
-  <li> GCI_PaletteIndex: A banda representa índice para tabela de cores
-  <li> GCI_RedBand: A banda representa a proção vermelha de uma image RGB ou RGBA
-  <li> GCI_GreenBand: A banda representa a proção verde de uma image RGB ou RGBA
-  <li> GCI_BlueBand: A banda representa a proção azul de uma image RGB ou RGBA
-  <li> GCI_AlphaBand: A banda representa a proção alpha de uma image RGBA
-  <li> GCI_HueBand: A banda representa a proção intensidade de uma image HLS
-  <li> GCI_SaturationBand: A banda representa a proção saturação de uma image HLS
-  <li> GCI_LightnessBand: A banda representa a proção luz de uma image HLS
-  <li> GCI_CyanBand: A banda representa a proção ciano de uma image CMY ou CMYK
-  <li> GCI_MagentaBand: A banda representa a proção magenta de uma image CMY ou CMYK
-  <li> GCI_YellowBand: A banda representa a proção amarelo de uma image CMY ou CMYK
-  <li> GCI_BlackBand: A banda representa a proção preto de uma image CMYK
-  </ul>
-
-<li> Uma tabela de cores. A ser detalhada porteriormente.
-
-<li> Indicação da existência de versões reduzida de banda (piramides).
-
-</ul>
-
-\section gdal_datamodel_rasterband_ct Tabela de cores
-
-A tabela de cores consiste de zero ou mais items decritos em C na seguinte estrucura:
-
-<pre>
-typedef struct
-{
-    /- gray, red, cyan or hue -/
-    short      c1;      
-
-    /- green, magenta, or lightness -/    
-    short      c2;      
-
-    /- blue, yellow, or saturation -/
-    short      c3;      
-
-    /- alpha or blackband -/
-    short      c4;      
-} GDALColorEntry;
-</pre>
-
-A tabela de cores também possiu um valor de interpretação (GDALPaletteInterp)
-com um dos seguintes valores, que indica como os valores de c1/c2/c3/c4 dos 
-item da tabela devem ser interpretados. 
-
-<ul>
-<li> GPI_Gray: Usa c1 como valor de tom de cinza.
-<li> GPI_RGB: Usa c1 como vermelho, c2 como verde, c3 como azul e c4 como alpha.
-<li> GPI_CMYK: Usa c1 como ciano, c2 como magenta, c3 como amarelo e c4 como preto.
-<li> GPI_HLS: Usa c1 como intensidade, c2 como saturação, c3 como luminosidade.
-</ul>
-
-Para associar a cor com o pixel, o valor de pixel deve ser usado como um
-&iacute&ndice dentro da tabela de cores. Isto significa que as cores devem ser 
-sempre aplicadas começando do zero em diante. Não existe provisão para
-macanismo de calcular escala antes de se buscar valores na tabela de cores.
-
-\section gdal_datamodel_rasterband_overviews Overviews
-
-Uma banda pode ter zero ou mais overviews. Cada overview é representada
-por um banda GDALRasterBand independente. O tamanho (em pixels e linhas) de
-um overview é diferente do raster que ela representa, mas a região geográfica
-covertida pela overview é a mesma da image de resolução total.
-
-As overviews são usadas para mostrar uma image de resolução reduzida de forma mais 
-rápida do que se acessar todos os dados da resolução total da imagem e depois 
-reduzir-la por amostragem.
-
-Bandas podem também a propriedadde HasArbitraryOverviews que indica se, caso
-seja verdadeira, o raster pode ser lido a qualquer resolução mas sem nenhuma
-distinção de overviews. Isto se aplica a algumas images codificadas tipo FFT, ou
-imagens capturadas via servidores (como OGDI) onde a amostragem pode ser executada
-mais eficentemente do que na máquina remota.
-
-\htmlonly
-<p>
-$Id: gdal_datamodel_br.dox $
-</p>
-\endhtmlonly
-
-*/
+/* $Id: gdal_datamodel_br.dox $ */
+
+/*! \page gdal_datamodel_br Modelo de Dados de GDAL
+
+Este documento descreve o Modelo de Dados implementado pela bilbioteca GDAL,
+os tipos de informação que GDAL pode conter e a sua semântica.<p>
+
+\section gdal_datamodel_dataset Dataset
+
+Um dataset (representado pela classe GDALDataset) é um agrupamento de bandas
+"raster" e um conjunto de informação comum a estas bandas.
+Em particular, um dataset possui o conceito de tamanho (em pixels e em linhas)
+que se aplica à todas as bandas.
+O Dataset também é reponsável pelas definições de referência geográficas e
+sistema de coordenadas comum a todas as bandas.
+O Dataset também pode possuir metadado, representado por uma lista de strings no formato de pares nome=valor.
+
+Note que o GDALDataet e o modelo de bandas "raster" em GDAL são ligeiramente baseados na
+especificação do "Grid Coverage" do OpenGIS (OGC).
+
+\subsection gdal_datamodel_dataset_cs Sistema de Coordenadas
+
+O sistema de coordenadas de um dataset é representado por uma string no
+formato "Well Kown Text" que contém:
+
+<ul>
+<li> Nome geral para o sistema de coordenadas.
+<li> Nome do sistema de coordenadas geográficas.
+<li> Nome do datum.
+<li> Nome da Elipsóide, semi-eixo maior e o inverso do achatamento.
+<li> Nome do meridiano de origem e sua distância de Greenwich.
+<li> Nome da projeção (ex. Transverse Mercator).
+<li> Lista de parâmetros de projeção (ex. central_meridian).
+<li> Nome das unidades e fator de conversão para metros ou radianos.
+<li> Nome e order dos eixos.
+<li> Códigos para relacionar a maioria dos items acima com tabelas de autoridades tais como EPSG.
+</ul>
+
+Para maiores informações sobre o sistema de coordenadas OpenGIS WKT, e seu o mecanismo
+de manipulação, refira-se ao documento <a href="ogr/osr_tutorial.html">
+osr_tutorial</a> e/ou a documentação da classe OGRSpatialReference.
+
+O sistema de coordenadas retornado pelo método GDALDataset::GetProjectionRef()
+descreve as coordenadas geo-referenciadas que devem ser usadas na transformação afim
+retornada pelo método GDALDataset::GetGeoTransform().
+O sistema de coordenadas retornado pelo métido GDALDataset::GetGCPProjection()
+descreve as coordenadas geo-referenciadas dos GCPs (Ground Control Points ou ponto de controle
+na superficíe) retornados pelo
+método GDALDataset::GetGCPs().
+
+Note que a string do sistema de coordenada retornado for "" isto
+indica que nada se sabe sobre o sistema de coordenadas do referido dataset.
+
+\subsection gdal_datamodel_dataset_gtm Transformacao afim
+
+GDAL datasets tem duas formas de descrever o relationamento entre
+poisição em raster (coordenadas de pixel) e coordenadas geográficas.
+O primeiro e mais usado é a transformação afim (o outro usa os GCPs).
+
+A transformação afim consiste em seis coeficiente retornados por
+GDALDataset::GetGeoTransform() que mapeiam coordenadas de pixel/linhas
+em coordenadas referenciadas spacialmente usango o seguinte relacionamento:
+
+<pre>
+    Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
+    Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
+</pre>
+
+No caso de imagens orientadas em direção ao norte, os coeficientes GT(2) e GT(4) são igual a zero,
+o GT(1) é a largura en pixels, e GT(5) é a altura en pixels. A posição (GT(0), GT(3))
+é o canto superior esquerdo do pixel no canto superior esquerdo da imagem.
+
+Note que a coordenada pixel/linha neste formato se extendem de (0.0, 0.0) no pixel do canto superior esquerdo
+localizado no canto superior esquerdo da imagem até o canto inferior direito do pixel localizado no canto
+inferior direito da imagem. Consequentement, a coordenada do pixel no canto superior esquerdo é (0.5, 0.5).
+
+\subsection gdal_datamodel_dataset_gcp GCPs
+
+Um dataset pode possuir um conjunto de pontos de controle relacionando uma ou mais posições
+no raster com coordenadas geo-referenciadas. Todos os GCPs compartilham o mesmo sistema
+de coordanadas (retornado pelo GDALDataset::GetGCPProjection()). Cada GCP (representado
+pelo classe GDAL_GCP) contén as seguintes estrutura:
+
+<pre>
+typedef struct
+{
+    char   *pszId;
+    char   *pszInfo;
+    double dfGCPPixel;
+    double dfGCPLine;
+    double dfGCPX;
+    double dfGCPY;
+    double dfGCPZ;
+} GDAL_GCP;
+</pre>
+
+A string pszId deve conter um único (e geralmente, mas nem sempre, numérico)
+identificador para cada GCP dentro do conjunto de GCPs do dataset.
+A string pszInfo é usualmente vazia mas pode conter qualquer texto associado ao
+GCP que o usuário defina. Potencialmente pszInfo poderá conter informação,
+decodificável automaticamente, sobre o estado do GCP. O que no entando ainda não
+tem sido feito até o momento.
+
+Os campos (Pixel, Line) contém a localização do GCP no raster. Os
+campos (X,Y,Z) estão associados com a localixação geo-referenciada sendo
+que Z é normalmente zero.
+
+O modelo de dados de GDAL nao impõe nenhum mecanismo de transformação para que
+deve ser generado a partir dos GCPs... Isto é deixado para o applicação. No
+entanto polinomios de primeiro a quinto grau são comument utilizados.
+
+Normalmente um dataset ira conter transformações afins (geotransform), GCPs
+or nenhum dos dois. É incomum encontrar os dois e neste caso não existe uma definição
+de qual deve ter precedência.
+
+\subsection gdal_datamodel_dataset_metadata Metadados
+
+O metado do GDAL é um formato auxiliar de dado textual específico
+para cada aplicação que contém uma lista de pares nome=valor. É requerido
+que os nomes sejam chaves facilmente distintas (sem espaço e caracteres especiais).
+O valor pode ser de qualquer tamanho e pode conter qualquer coisa, exceto um caracter núlo (zero ASCII).
+
+O sistema de manipulação de metadas não é apropriado para suportar grandes volume de metados.
+Mais de 100K bytes de metada para um dataset provavelmente causará degradação na performance.
+
+Com o tempo espera-se que nomes bem conhecidos sejam identificados e bem estabelicidos semanticamente,
+no entanto isto ainda não tem ocorrido até o momento.
+
+Alguns formatos suportam metados genéricos (definidos pelo usuário), enquanto outros
+formatos supportam nomes specificos. Por exemplo o TIFF driver retorna algumas de suas
+"tags" na forma de metadas tais como data e hora:
+
+<pre>
+TIFFTAG_DATETIME=1999:05:11 11:29:56
+</pre>
+
+O matado é dividido em grupos chamados domínios (domains). O domínio default
+tem o nome em branco (NULL ou ""). Existem alguns domínios specificos para
+propósitos especiais. Note que correntement não existe uma forma de enumerar
+todos os domínios disponíveis para um dado objeto mas as aplicações podem testar
+a existência de domínios conhecidos.
+
+\subsubsection gdal_datamodel_subdatasets Dominio de SUBDATASETS
+
+Os domínios SUBDATASETS podem listar uma hierarquia de datasets filhos.
+Normalmente isto é usado para prover endereços para várias imagens (ou datasets)
+internas à um único arquivo de images (como HDF ou NITF). Por exemplo, um arquivo
+NITF com quatro imagens pode ter a seguinte lista de subdataset:
+
+<pre>
+  SUBDATASET_1_NAME=NITF_IM:0:multi_1b.ntf
+  SUBDATASET_1_DESC=Image 1 of multi_1b.ntf
+  SUBDATASET_2_NAME=NITF_IM:1:multi_1b.ntf
+  SUBDATASET_2_DESC=Image 2 of multi_1b.ntf
+  SUBDATASET_3_NAME=NITF_IM:2:multi_1b.ntf
+  SUBDATASET_3_DESC=Image 3 of multi_1b.ntf
+  SUBDATASET_4_NAME=NITF_IM:3:multi_1b.ntf
+  SUBDATASET_4_DESC=Image 4 of multi_1b.ntf
+  SUBDATASET_5_NAME=NITF_IM:4:multi_1b.ntf
+  SUBDATASET_5_DESC=Image 5 of multi_1b.ntf
+</pre>
+
+O valor de _NAME é a string que pode ser usada em uma chamada à GDALOpen()
+para acessar o arquivo. O valor de _DESC tem a intensão de apresentar uma
+descrição ao usuário no caso da seleção de subdataset.
+
+\subsubsection gdal_datamodel_image_structure Dominio IMAGE_STRUCTURE
+
+O domínio defult do metadata ("") está relacionado à image e não particularmente
+a forma como a image é organizada no arquivo.
+Isto significa que este domínio é apropriado para se copiar junto com o dataset
+quanto a image é copida para um novo format.
+Alguma informações pertence somente a um particular format de arquivo e sua forma
+de armazenamento.
+Para que esta informação não seja copiada inadvertidamente este tipo de informação
+é colocado num domínio especial chamado IMAGE_STRUCTURE que não normalmente não deve ser
+copiado de um formato para outro.
+
+Um item que aparece no domínio IMAGE_STRUCTURE é o esquema de compressão usado
+pelo formato. O nome deste item no metada é COMPRESSION mas o valor dele pode
+ser específico para cada formato.
+
+\subsubsection gdal_datamodel_xml Dominio xml:
+
+Qualquer domínio cujo o prefix do nome é "xml:" não é um item de metada normal mas sim
+um único documento XML armazenado numa string longa.
+
+\section gdal_datamodel_rasterband Banda de Imagem Raster
+
+Uma banda de image raster é representada em GDAL pela classe GDALRaseterBand.
+Ela representa uma única banda, canal ou camada. Em GDAL, uma banda não representa
+necessáriamente uma imagem inteira. Uma imagem 24bit RGB, por exemplo, é normalmente
+representada por um dataset com três bandas, uma para vermelho, uma pra verde e outra para azul.
+
+Um banda raster tem as seguintes propriedades:
+
+<ul>
+
+<li> Altura e largura em número de pixels e linhas. Pode ser o mesmo valor definido para o
+dataset, caso seje uma banda de resolução total.
+
+<li> Um tipo de dato. Podendo ser Byte, UInt16, Int16, UInt32, Int32,
+Float32, Float64, and the complex types CInt16, CInt32, CFloat32, and CFloat64.
+
+<li> Um tamanho de bloco, que seria o valor preferido (eficiente) para se acessar
+um pedaço do arquivo. Para imagens dividida em "tiles" este seria o tamanho de um bloco.
+Para image organizadas por linha de varredura (scanLine), tamalho de bloco seria normalmente
+uma "scanline".
+
+<li> Lista de pares nome/valor do metada, no mesmo formato que o dataset mas com
+informações que sejam potencialmente especificas da banda.
+
+<li> Um string com uma descrição opcional
+
+<li> Uma lista de nomes de categorias (efetivamente, nome de classe numa imagem temática)
+
+<li> Opcionalmente, mínimos e máximos valores de pixel.
+
+<li> Opcionalmente, o valor do deslocamento e da escala para transformar os valores de
+banda raster em valores significativoes (ex. para traduzir altura para metros).
+
+<li> Opcionalmente, o nome da unidade do raster. Indicando, por exemplo, a unidade linear
+para um dado de elevação.
+
+<li> A tipo de interpretação das cores da banda, que pode ser:
+
+  <ul>
+  <li> GCI_Undefined: O default, Nada ou desconhecido
+  <li> GCI_GrayIndex: Image em toms de cinza independente
+  <li> GCI_PaletteIndex: A banda representa índice para tabela de cores
+  <li> GCI_RedBand: A banda representa a proção vermelha de uma image RGB ou RGBA
+  <li> GCI_GreenBand: A banda representa a proção verde de uma image RGB ou RGBA
+  <li> GCI_BlueBand: A banda representa a proção azul de uma image RGB ou RGBA
+  <li> GCI_AlphaBand: A banda representa a proção alpha de uma image RGBA
+  <li> GCI_HueBand: A banda representa a proção intensidade de uma image HLS
+  <li> GCI_SaturationBand: A banda representa a proção saturação de uma image HLS
+  <li> GCI_LightnessBand: A banda representa a proção luz de uma image HLS
+  <li> GCI_CyanBand: A banda representa a proção ciano de uma image CMY ou CMYK
+  <li> GCI_MagentaBand: A banda representa a proção magenta de uma image CMY ou CMYK
+  <li> GCI_YellowBand: A banda representa a proção amarelo de uma image CMY ou CMYK
+  <li> GCI_BlackBand: A banda representa a proção preto de uma image CMYK
+  </ul>
+
+<li> Uma tabela de cores. A ser detalhada porteriormente.
+
+<li> Indicação da existência de versões reduzida de banda (piramides).
+
+</ul>
+
+\section gdal_datamodel_rasterband_ct Tabela de cores
+
+A tabela de cores consiste de zero ou mais items decritos em C na seguinte estrucura:
+
+<pre>
+typedef struct
+{
+    /- gray, red, cyan or hue -/
+    short      c1;
+
+    /- green, magenta, or lightness -/
+    short      c2;
+
+    /- blue, yellow, or saturation -/
+    short      c3;
+
+    /- alpha or blackband -/
+    short      c4;
+} GDALColorEntry;
+</pre>
+
+A tabela de cores também possiu um valor de interpretação (GDALPaletteInterp)
+com um dos seguintes valores, que indica como os valores de c1/c2/c3/c4 dos
+item da tabela devem ser interpretados.
+
+<ul>
+<li> GPI_Gray: Usa c1 como valor de tom de cinza.
+<li> GPI_RGB: Usa c1 como vermelho, c2 como verde, c3 como azul e c4 como alpha.
+<li> GPI_CMYK: Usa c1 como ciano, c2 como magenta, c3 como amarelo e c4 como preto.
+<li> GPI_HLS: Usa c1 como intensidade, c2 como saturação, c3 como luminosidade.
+</ul>
+
+Para associar a cor com o pixel, o valor de pixel deve ser usado como um
+&iacute&ndice dentro da tabela de cores. Isto significa que as cores devem ser
+sempre aplicadas começando do zero em diante. Não existe provisão para
+macanismo de calcular escala antes de se buscar valores na tabela de cores.
+
+\section gdal_datamodel_rasterband_overviews Overviews
+
+Uma banda pode ter zero ou mais overviews. Cada overview é representada
+por um banda GDALRasterBand independente. O tamanho (em pixels e linhas) de
+um overview é diferente do raster que ela representa, mas a região geográfica
+covertida pela overview é a mesma da image de resolução total.
+
+As overviews são usadas para mostrar uma image de resolução reduzida de forma mais
+rápida do que se acessar todos os dados da resolução total da imagem e depois
+reduzir-la por amostragem.
+
+Bandas podem também a propriedadde HasArbitraryOverviews que indica se, caso
+seja verdadeira, o raster pode ser lido a qualquer resolução mas sem nenhuma
+distinção de overviews. Isto se aplica a algumas images codificadas tipo FFT, ou
+imagens capturadas via servidores (como OGDI) onde a amostragem pode ser executada
+mais eficentemente do que na máquina remota.
+
+\htmlonly
+<p>
+$Id: gdal_datamodel_br.dox $
+</p>
+\endhtmlonly
+
+*/
diff --git a/doc/br/gdal_tutorial_br.dox b/doc/br/gdal_tutorial_br.dox
index e121877..e6aa59f 100644
--- a/doc/br/gdal_tutorial_br.dox
+++ b/doc/br/gdal_tutorial_br.dox
@@ -1,617 +1,617 @@
-/* $Id: gdal_tutorial_br.dox $ */
-
-/*! \page gdal_tutorial_br Tutorial da API do GDAL
-
-\section gdal_tutorial_open Abrindo um Arquivo
-
-Antes de abrir um dataset raster suportado por GDAL é necessário 
-registar os drivers, existe um driver para cada formato suportado e o registro
-dos driver é realizado normalmente com a função GDALAllRegister().  GDALAllRegister() 
-registar todos os drivers conhecidos including os "plug-in", que são bilioteca dinâmicas,  
-carregadas pelo método GDALDriverManager::AutoLoadDrivers(). 
-Se por algum motivo uma aplicações necessetita limitar o conjunto de drivers seria 
-útil verificar o código de <a href="gdalallregister.cpp.html">gdalallregister.cpp</a>.
-
-Uma vez que os drivers são registados, a aplicação deve chamar a 
-função GDALOpen() para abrir dataset, passando o nome do dataset e a forma de 
-acesso (GA_ReadOnly ou GA_Update).
-
-Em C++:
-\code
-#include "gdal_priv.h"
-
-int main()
-{
-    GDALDataset  *poDataset;
-
-    GDALAllRegister();
-
-    poDataset = (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
-    if( poDataset == NULL )
-    {
-	...;
-    }
-\endcode
-
-Em C:
-\code
-#include "gdal.h"
-
-int main()
-{
-    GDALDatasetH  hDataset;
-
-    GDALAllRegister();
-
-    hDataset = GDALOpen( pszFilename, GA_ReadOnly );
-    if( hDataset == NULL )
-    {
-	...;
-    }
-\endcode
-
-Em Python:
-\code
-    import gdal
-    from gdalconst import *
-
-    dataset = gdal.Open( filename, GA_ReadOnly )
-    if dataset is None:
-        ...
-\endcode
-
-Note que se GDALOpen() retornar NULL significa que ocorreu uma falhada, e 
-que as mensagens de erro deverão ter sido emitidas através de CPLError(). 
-Se você quiser controlar como os erros estão relatados revise a  
-a documentação do usuário de função CPLError(). 
-Em geral, todo o GDAL usa CPLError() para o relatório de erro. 
-Note também que o pszFilename não necessita 
-realmente ser o nome de uma arquivo físico (no entando geralmente é). 
-A interpretação é dependente do driver, e pôde ser um URL, 
-um nome de arquivo com os parâmetros adicionais adicionados na 
-string para controlar a abertura do arquivo ou qualquer outra coisa. 
-Tente por favor não limitar diálogos da seleção da arquivo de 
-GDAL somente a selecionar arquivos físicos.
-
-\section gdal_tutorial_dataset Extraindo Informacoes do Arquivo
-
-Como descrita em <a href="gdal_datamodel.html">GDAL Data Model</a>, um 
-GDALDataset contem uma lista de bandas raster, todas pertencendo 
-à uma mesma área, e tendo a mesma definição. Possui também um metadata, um sistema 
-coordenado, uma transformação geográfica, tamanho do raster e várias outras informações.
-
-\code
-    adfGeoTransform[0] /* top left x */
-    adfGeoTransform[1] /* w-e pixel resolution */
-    adfGeoTransform[2] /* rotation, 0 if image is "north up" */
-    adfGeoTransform[3] /* top left y */
-    adfGeoTransform[4] /* rotation, 0 if image is "north up" */
-    adfGeoTransform[5] /* n-s pixel resolution */
-\endcode
-
-Se nós quiséssemos imprimir alguma informação geral sobre a série 
-de dados nós pudemos fazer o seguinte:
-
-Em C++:
-\code
-    double        adfGeoTransform[6];
-
-    printf( "Driver: %s/%s\n",
-            poDataset->GetDriver()->GetDescription(), 
-            poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );
-
-    printf( "Size is %dx%dx%d\n", 
-            poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
-            poDataset->GetRasterCount() );
-
-    if( poDataset->GetProjectionRef()  != NULL )
-        printf( "Projection is `%s'\n", poDataset->GetProjectionRef() );
-
-    if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
-    {
-        printf( "Origin = (%.6f,%.6f)\n",
-                adfGeoTransform[0], adfGeoTransform[3] );
-
-        printf( "Pixel Size = (%.6f,%.6f)\n",
-                adfGeoTransform[1], adfGeoTransform[5] );
-    }
-\endcode
-
-Em C:
-\code
-    GDALDriverH   hDriver;
-    double        adfGeoTransform[6];
-
-    hDriver = GDALGetDatasetDriver( hDataset );
-    printf( "Driver: %s/%s\n",
-            GDALGetDriverShortName( hDriver ),
-            GDALGetDriverLongName( hDriver ) );
-
-    printf( "Size is %dx%dx%d\n",
-	    GDALGetRasterXSize( hDataset ), 
-            GDALGetRasterYSize( hDataset ),
-            GDALGetRasterCount( hDataset ) );
-
-    if( GDALGetProjectionRef( hDataset ) != NULL )
-        printf( "Projection is `%s'\n", GDALGetProjectionRef( hDataset ) );
-
-    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
-    {
-        printf( "Origin = (%.6f,%.6f)\n",
-                adfGeoTransform[0], adfGeoTransform[3] );
-
-        printf( "Pixel Size = (%.6f,%.6f)\n",
-                adfGeoTransform[1], adfGeoTransform[5] );
-    }
-\endcode
-
-Em Python:
-\code
-    print 'Driver: ', dataset.GetDriver().ShortName,'/', \
-          dataset.GetDriver().LongName
-    print 'Size is ',dataset.RasterXSize,'x',dataset.RasterYSize, \
-          'x',dataset.RasterCount
-    print 'Projection is ',dataset.GetProjection()
-    
-    geotransform = dataset.GetGeoTransform()
-    if not geotransform is None:
-	print 'Origin = (',geotransform[0], ',',geotransform[3],')'
-	print 'Pixel Size = (',geotransform[1], ',',geotransform[5],')'
-\endcode
-
-\section gdal_tutorial_band Extraindo uma Banda Raster
-
-Neste ponto o acesso aos dados da raster através de GDAL pode ser feito 
-uma banda de cada vez. A Band também possui metadata, tamanho de block, tabelas da cor, 
-e vário a outra informação disponível na classe GDALRasterBand. 
-Os seguintes códigos buscam um objeto de GDALRasterBand da série de dados 
-(numerada a partir de 1 em GetRasterCount()) e a exposições de algums 
-informações sobre ela.
-
-Em C++:
-\code
-	GDALRasterBand  *poBand;
-        int             nBlockXSize, nBlockYSize;
-        int             bGotMin, bGotMax;
-        double          adfMinMax[2];
-	
-        poBand = poDataset->GetRasterBand( 1 );
-	poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
-        printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
-                nBlockXSize, nBlockYSize,
-                GDALGetDataTypeName(poBand->GetRasterDataType()),
-                GDALGetColorInterpretationName(
-                    poBand->GetColorInterpretation()) );
-
-        adfMinMax[0] = poBand->GetMinimum( &bGotMin );
-        adfMinMax[1] = poBand->GetMaximum( &bGotMax );
-        if( ! (bGotMin && bGotMax) )
-            GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
-
-        printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
-        
-        if( poBand->GetOverviewCount() > 0 )
-            printf( "Band has %d overviews.\n", poBand->GetOverviewCount() );
-
-        if( poBand->GetColorTable() != NULL )
-            printf( "Band has a color table with %d entries.\n", 
-                     poBand->GetColorTable()->GetColorEntryCount() );
-\endcode
-
-Em C:
-\code
-	GDALRasterBandH hBand;
-        int             nBlockXSize, nBlockYSize;
-        int             bGotMin, bGotMax;
-        double          adfMinMax[2];
-	
-        hBand = GDALGetRasterBand( hDataset, 1 );
-        GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
-        printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
-                nBlockXSize, nBlockYSize,
-                GDALGetDataTypeName(GDALGetRasterDataType(hBand)),
-                GDALGetColorInterpretationName(
-                    GDALGetRasterColorInterpretation(hBand)) );
-
-        adfMinMax[0] = GDALGetRasterMinimum( hBand, &bGotMin );
-        adfMinMax[1] = GDALGetRasterMaximum( hBand, &bGotMax );
-        if( ! (bGotMin && bGotMax) )
-            GDALComputeRasterMinMax( hBand, TRUE, adfMinMax );
-
-        printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
-        
-        if( GDALGetOverviewCount(hBand) > 0 )
-            printf( "Band has %d overviews.\n", GDALGetOverviewCount(hBand));
-
-        if( GDALGetRasterColorTable( hBand ) != NULL )
-            printf( "Band has a color table with %d entries.\n", 
-                     GDALGetColorEntryCount(
-                         GDALGetRasterColorTable( hBand ) ) );
-\endcode
-
-In Python (note several bindings are missing):
-\code
-	band = dataset.GetRasterBand(1)
-
-	print 'Band Type=',gdal.GetDataTypeName(band.DataType)
-
-	min = band.GetMinimum()
-	max = band.GetMaximum()
-	if min is not None and max is not None:
-	    (min,max) = ComputeRasterMinMax(1)
-	print 'Min=%.3f, Max=%.3f' % (min,max)
-
-	if band.GetOverviewCount() > 0:
-	    print 'Band has ', band.GetOverviewCount(), ' overviews.'
-
-        if not band.GetRasterColorTable() is None:
-	    print 'Band has a color table with ', \
-	    band.GetRasterColorTable().GetCount(), ' entries.'
-\endcode
-
-\section gdal_tutorial_read Lendo dato Raster
-
-Há algumas maneiras diferentes de ler dados da raster, mas o mais comum é 
-através do Método GDALRasterBand::RasterIO(). Este método tomará 
-automaticamente cuidado da conversão do tipo de dados, amostragem e janela
-de dados requerida. O seguinte código lerá o primeiro scanline dos dados em um 
-buffer em tamanho similar à quantidade lida, convertendo os valores para ponto 
-flutuando como parte da operação:
-
-Em C++:
-\code
-        float *pafScanline;
-        int   nXSize = poBand->GetXSize();
-
-        pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
-        poBand->RasterIO( GF_Read, 0, 0, nXSize, 1, 
-                          pafScanline, nXSize, 1, GDT_Float32, 
-                          0, 0 );
-\endcode
-
-Em C:
-\code
-        float *pafScanline;
-        int   nXSize = GDALGetRasterBandXSize( hBand );
-
-        pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
-	    GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1, 
-                      pafScanline, nXSize, 1, GDT_Float32, 
-                      0, 0 );
-\endcode
-
-Em Python:
- 
-\code
-  	scanline = band.ReadRaster( 0, 0, band.XSize, 1, \
-                                     band.XSize, 1, GDT_Float32 )
-\endcode
- 
-Note que o scanline retornado é do tipo char*, e contem os 
-bytes xsize*4 de dados binários brutos de ponto flutuando. Isto 
-pode ser convertido em Python usando o módulo do <b>struct</b> 
-da biblioteca padrão:
-
-\code
-	import struct
-
-	tuple_of_floats = struct.unpack('f' * b2.XSize, scanline)
-\endcode
-
-A chamada de RasterIO espera os seguintes argumentos.
-\code
-CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
-                                 int nXOff, int nYOff, int nXSize, int nYSize,
-                                 void * pData, int nBufXSize, int nBufYSize,
-                                 GDALDataType eBufType,
-                                 int nPixelSpace,
-                                 int nLineSpace )
-\endcode
-
-Note que a mesma chamada de RasterIO() poderá ler, ou gravar dependendo do valor
-de eRWFlag (GF_Read ou GF_Write). Os argumentos nXOff, nYOff, nXSize, nYSize 
-descreve a janela de dados da raster para ler (ou para gravar). 
-Não necessita ser coincidente com os limites da image embora o acesso pode ser mais eficiente se for.
-
-O pData é o buffer de memória para os dados que serão lidos ou gravados. 
-O verdadeiro tipo de dado &eacute aquele passado por eBufType, tal como GDT_Float32, 
-ou GDT_Byte. A chamada de RasterIO() cuidará de converter entre o tipo 
-de dados do buffer e o tipo de dados da banda. Anotar que ao converter dados do 
-ponto flutuando para o inteiro RasterIO arredonda para baixo, e ao converter de 
-para fora dos limites de valores válidos para o tipo de saída, será escolhido o mais
-próximo valor possível. 
-Isto implica, por exemplo, que os dados 16bit lidos em um buffer de GDT_Byte 
-converterão todos os valores maiores de 255 para 255, os <b>dados não estão escalados!</b>
-
-Os valores nBufXSize e nBufYSize descrevem o tamanho do buffer. Ao carregar dados na 
-resolução completa os valores seria o mesmo que o tamanho da janela. Entretanto, para carregar 
-uma vista de solução reduzida (overview) os valores podiam ser ajustado para menos do que a janela 
-no arquivo. Neste caso o RasterIO() utilizará overview para fazer 
-mais eficientemente o IO se as overview forem apropriadas.
-
-O nPixelSpace, e o nLineSpace são normalmente zero indicando que os valores default
-devem ser usados. Entretanto, podem ser usados controlar o acesso à dados da memória, 
-permitindo a leitura em um buffer que contem dados intercalados (interleave) pixel por exemplo.  
-
-\section gdal_tutorial_close Fechando o Dataset
-
-Por favor tenha em mente que os objetos de GDALRasterBand estão possuídos por sua 
-dataset, e nunca devem ser destruídos com o operador delete de C++. 
-GDALDataset podem ser fechado chamando GDALClose() ou usando o operador delete 
-no GDALDataset. Um ou outro resultado na finalização apropriada, e resolver 
-gravações pendentes.
-
-\section gdal_tutorial_creation Tecnicas para criar arquivos
-
-As arquivos em formatos suportados GDAL podem ser criadas se o driver do formato 
-suportar a criação. Há duas técnicas gerais para criar arquivos, usando CreateCopy() e Create(). 
-O método de CreateCopy chama o método CreateCopy() do driver do formato, e 
-passar como parâmetro dataset que será copiado. O método criar chama o 
-método Create() do driver, e então explicitamente grava todos os metadata, e dados 
-da raster com as chamadas separadas. Todos os drivers que suportam criar arquivos 
-novos suportam o método de CreateCopy(), mas somente algum sustentação o método Create().
-
-Para determinar se o driver de um formato suporta Create ou CreateCopy é necessário verificar o 
-DCAP_CREATE e os metadata de DCAP_CREATECOPY no driver do formato 
-objetam. Assegurar-se de que GDALAllRegister() tenha sido chamado antes de chamar GetDriverByName(). 
-
-Em C++:
-\code
-#include "cpl_string.h"
-...
-    const char *pszFormat = "GTiff";
-    GDALDriver *poDriver;
-    char **papszMetadata;
-
-    poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
-
-    if( poDriver == NULL )
-        exit( 1 );
-
-    papszMetadata = poDriver->GetMetadata();
-    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
-        printf( "Driver %s supports Create() method.\n", pszFormat );
-    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
-        printf( "Driver %s supports CreateCopy() method.\n", pszFormat );
-\endcode
-
-Em C:
-\code
-#include "cpl_string.h"
-...
-    const char *pszFormat = "GTiff";
-    GDALDriver hDriver = GDALGetDriverByName( pszFormat );
-    char **papszMetadata;
-
-    if( hDriver == NULL )
-        exit( 1 );
-
-    papszMetadata = GDALGetMetadata( hDriver, NULL );
-    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
-        printf( "Driver %s supports Create() method.\n", pszFormat );
-    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
-        printf( "Driver %s supports CreateCopy() method.\n", pszFormat );
-\endcode
-
-Em Python:
-
-\code
-    format = "GTiff"
-    driver = gdal.GetDriverByName( format )
-    metadata = driver.GetMetadata()
-    if metadata.has_key(gdal.DCAP_CREATE) \
-       and metadata[gdal.DCAP_CREATE] == 'YES':
-        print 'Driver %s supports Create() method.' % format
-    if metadata.has_key(gdal.DCAP_CREATECOPY) \
-       and metadata[gdal.DCAP_CREATECOPY] == 'YES':
-        print 'Driver %s supports CreateCopy() method.' % format
-\endcode
-
-Note que um número de drivers são de leitura apenas e não suportarão 
-Create() ou CreateCopy ().
-
-\section gdal_tutorial_createcopy Usando CreateCopy()
-
-O GDALDriver:: O método de CreateCopy() pode ser usado razoavelmente 
-simples enquanto a maioria de informação é coletada do dataset de entrada.
-Entretanto, inclui opções para passar a formato opções 
-específicas da criação, e para relatar o progresso ao usuário enquanto 
-uma cópia longa da série de dados ocorre. Uma cópia simples de uma arquivo 
-nomeou o pszSrcFilename, a uma arquivo nova nomeada pszDstFilename usando 
-opções de defeito em um formato cujo o driver fosse buscado previamente 
-pudesse olhar como este:
-
-Em C++:
-\code
-    GDALDataset *poSrcDS = 
-       (GDALDataset *) GDALOpen( pszSrcFilename, GA_ReadOnly );
-    GDALDataset *poDstDS;
-
-    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE, 
-                                    NULL, NULL, NULL );
-    if( poDstDS != NULL )
-        delete poDstDS;
-\endcode
-
-Em C:
-\code
-    GDALDatasetH hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
-    GDALDatasetH hDstDS;
-
-    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE, 
-                             NULL, NULL, NULL );
-    if( hDstDS != NULL )
-        GDALClose( hDstDS );
-\endcode
-
-Em Python:
-
-\code
-    src_ds = gdal.Open( src_filename )
-    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0 )
-\endcode
-
-Note que o método de CreateCopy() retorna um dataset writeable, 
-e que deve ser fechado corretamente à escrita completa e a nivelar a série 
-de dados ao disco. No Python encaixotar isto ocorre automaticamente quando 
-os "dst_ds" saem do espaço. O valor FALSO (ou 0) usado para a opção do 
-bStrict imediatamente depois que o nome de arquivo do destino na chamada 
-de CreateCopy() indica que a chamada de CreateCopy() deve proseguir sem
-um erro fatal mesmo se a série de dados do destino não puder ser criada 
-para combinar exatamente a série de dados da entrada. Isto pôde ser porque 
-o formato da saída não suporta o datatype do pixel do dataset de entrada, 
-ou porque o destino não pode suportar a escrita que georeferencing 
-por exemplo.
-
-Casos mais complexo pôdem envolver passar opções da criação, e usar
-um monitor predefinido do progresso como este:
-
-Em C++:
-\code
-#include "cpl_string.h"
-...
-    char **papszOptions = NULL;
-    
-    papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
-    papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
-    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE, 
-                                    papszOptions, GDALTermProgress, NULL );
-    if( poDstDS != NULL )
-        delete poDstDS;
-    CSLDestroy( papszOptions );
-\endcode
-
-Em C:
-\code
-#include "cpl_string.h"
-...
-    char **papszOptions = NULL;
-    
-    papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
-    papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
-    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE, 
-                             papszOptions, GDALTermProgres, NULL );
-    if( hDstDS != NULL )
-        GDALClose( hDstDS );
-    CSLDestroy( papszOptions );
-\endcode
-
-Em Python:
-
-\code
-    src_ds = gdal.Open( src_filename )
-    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0, 
-                                [ 'TILED=YES', 'COMPRESS=PACKBITS' ] )
-\endcode
-
-\section gdal_tutorial_create Usando Create()
-
-Em situações em que não se quer somente exportar um arquivo existente 
-para uma arquivo novo, geralmente usa-se o método GDALDriver::Create() (embora algumas 
-opções interessantes são possíveis 
-com o uso de arquivos virtuais ou de arquivos da em-memória). 
-O método Create() examina uma lista de opções bem como o CreateCopy(), mas 
-o tamanho da imagem, número das bandas e o tipo da banda deve ser fornecido explicitamente.
-<p>
-
-Em C++:
-\code
-    GDALDataset *poDstDS;	
-    char **papszOptions = NULL;
-
-    poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte, 
-                                papszOptions );
-\endcode
-
-Em C:
-\code
-    GDALDatasetH hDstDS;	
-    char **papszOptions = NULL;
-
-    hDstDS = GDALCreate( hDriver, pszDstFilename, 512, 512, 1, GDT_Byte, 
-                         papszOptions );
-\endcode
-
-Em Python:
-
-\code
-    dst_ds = driver.Create( dst_filename, 512, 512, 1, gdal.GDT_Byte )
-\endcode
-
-Uma vez que o dataset é criado com sucesso, todos os metadata apropriados devem 
-ser gravados no arquivo. O que variará de acordo com o uso, 
-mas um caso simples com projeção, do geotransform e da raster é 
-mostrado a seguir:<p>
-
-Em C++:
-\code
-    double adfGeoTransform[6] = { 444720, 30, 0, 3751320, 0, -30 };
-    OGRSpatialReference oSRS;
-    char *pszSRS_WKT = NULL;
-    GDALRasterBand *poBand;
-    GByte abyRaster[512*512];
-
-    poDstDS->SetGeoTransform( adfGeoTransform );
-    
-    oSRS.SetUTM( 11, TRUE );
-    oSRS.SetWellKnownGeogCS( "NAD27" );
-    oSRS.exportToWkt( &pszSRS_WKT );
-    poDstDS->SetProjection( pszSRS_WKT );
-    CPLFree( pszSRS_WKT );
-
-    poBand = poDstDS->GetRasterBand(1);
-    poBand->RasterIO( GF_Write, 0, 0, 512, 512, 
-                      abyRaster, 512, 512, GDT_Byte, 0, 0 );    
-
-    delete poDstDS;
-\endcode
-
-Em C:
-\code
-    double adfGeoTransform[6] = { 444720, 30, 0, 3751320, 0, -30 };
-    OGRSpatialReferenceH hSRS;
-    char *pszSRS_WKT = NULL;
-    GDALRasterBandH hBand;
-    GByte abyRaster[512*512];
-
-    GDALSetGeoTransform( hDstDS, adfGeoTransform );
-
-    hSRS = OSRNewSpatialReference( NULL );
-    OSRSetUTM( hSRS, 11, TRUE );
-    OSRSetWellKnownGeogCS( hSRS, "NAD27" );			
-    OSRExportToWkt( hSRS, &pszSRS_WKT );
-    OSRDestroySpatialReference( hSRS );
-
-    GDALSetProjection( hDstDS, pszSRS_WKT );
-    CPLFree( pszSRS_WKT );
-
-    hBand = GDALGetRasterBand( hDstDS, 1 );
-    GDALRasterIO( hBand, GF_Write, 0, 0, 512, 512, 
-                  abyRaster, 512, 512, GDT_Byte, 0, 0 );    
-
-    GDALClose( hDstDS );
-\endcode
-
-Em Python:
-
-\code
-    import Numeric, osr
-
-    dst_ds.SetGeoTransform( [ 444720, 30, 0, 3751320, 0, -30 ] )
-    
-    srs = osr.SpatialReference()
-    srs.SetUTM( 11, 1 )
-    srs.SetWellKnownGeogCS( 'NAD27' )
-    dst_ds.SetProjection( srs.ExportToWkt() )
-
-    raster = Numeric.zeros( (512, 512) )    
-    dst_ds.GetRasterBand(1).WriteArray( raster )
-\endcode
-
-\htmlonly
-<p>
-$Id: gdal_tutorial_br.dox $
-</p>
-\endhtmlonly
-
-*/
+/* $Id: gdal_tutorial_br.dox $ */
+
+/*! \page gdal_tutorial_br Tutorial da API do GDAL
+
+\section gdal_tutorial_open Abrindo um Arquivo
+
+Antes de abrir um dataset raster suportado por GDAL é necessário
+registar os drivers, existe um driver para cada formato suportado e o registro
+dos driver é realizado normalmente com a função GDALAllRegister().  GDALAllRegister()
+registar todos os drivers conhecidos including os "plug-in", que são bilioteca dinâmicas,
+carregadas pelo método GDALDriverManager::AutoLoadDrivers().
+Se por algum motivo uma aplicações necessetita limitar o conjunto de drivers seria
+útil verificar o código de <a href="gdalallregister.cpp.html">gdalallregister.cpp</a>.
+
+Uma vez que os drivers são registados, a aplicação deve chamar a
+função GDALOpen() para abrir dataset, passando o nome do dataset e a forma de
+acesso (GA_ReadOnly ou GA_Update).
+
+Em C++:
+\code
+#include "gdal_priv.h"
+
+int main()
+{
+    GDALDataset  *poDataset;
+
+    GDALAllRegister();
+
+    poDataset = (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+    if( poDataset == NULL )
+    {
+        ...;
+    }
+\endcode
+
+Em C:
+\code
+#include "gdal.h"
+
+int main()
+{
+    GDALDatasetH  hDataset;
+
+    GDALAllRegister();
+
+    hDataset = GDALOpen( pszFilename, GA_ReadOnly );
+    if( hDataset == NULL )
+    {
+        ...;
+    }
+\endcode
+
+Em Python:
+\code
+    import gdal
+    from gdalconst import *
+
+    dataset = gdal.Open( filename, GA_ReadOnly )
+    if dataset is None:
+        ...
+\endcode
+
+Note que se GDALOpen() retornar NULL significa que ocorreu uma falhada, e
+que as mensagens de erro deverão ter sido emitidas através de CPLError().
+Se você quiser controlar como os erros estão relatados revise a
+a documentação do usuário de função CPLError().
+Em geral, todo o GDAL usa CPLError() para o relatório de erro.
+Note também que o pszFilename não necessita
+realmente ser o nome de uma arquivo físico (no entando geralmente é).
+A interpretação é dependente do driver, e pôde ser um URL,
+um nome de arquivo com os parâmetros adicionais adicionados na
+string para controlar a abertura do arquivo ou qualquer outra coisa.
+Tente por favor não limitar diálogos da seleção da arquivo de
+GDAL somente a selecionar arquivos físicos.
+
+\section gdal_tutorial_dataset Extraindo Informacoes do Arquivo
+
+Como descrita em <a href="gdal_datamodel.html">GDAL Data Model</a>, um
+GDALDataset contem uma lista de bandas raster, todas pertencendo
+à uma mesma área, e tendo a mesma definição. Possui também um metadata, um sistema
+coordenado, uma transformação geográfica, tamanho do raster e várias outras informações.
+
+\code
+    adfGeoTransform[0] /* top left x */
+    adfGeoTransform[1] /* w-e pixel resolution */
+    adfGeoTransform[2] /* rotation, 0 if image is "north up" */
+    adfGeoTransform[3] /* top left y */
+    adfGeoTransform[4] /* rotation, 0 if image is "north up" */
+    adfGeoTransform[5] /* n-s pixel resolution */
+\endcode
+
+Se nós quiséssemos imprimir alguma informação geral sobre a série
+de dados nós pudemos fazer o seguinte:
+
+Em C++:
+\code
+    double        adfGeoTransform[6];
+
+    printf( "Driver: %s/%s\n",
+            poDataset->GetDriver()->GetDescription(),
+            poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );
+
+    printf( "Size is %dx%dx%d\n",
+            poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
+            poDataset->GetRasterCount() );
+
+    if( poDataset->GetProjectionRef()  != NULL )
+        printf( "Projection is `%s'\n", poDataset->GetProjectionRef() );
+
+    if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
+    {
+        printf( "Origin = (%.6f,%.6f)\n",
+                adfGeoTransform[0], adfGeoTransform[3] );
+
+        printf( "Pixel Size = (%.6f,%.6f)\n",
+                adfGeoTransform[1], adfGeoTransform[5] );
+    }
+\endcode
+
+Em C:
+\code
+    GDALDriverH   hDriver;
+    double        adfGeoTransform[6];
+
+    hDriver = GDALGetDatasetDriver( hDataset );
+    printf( "Driver: %s/%s\n",
+            GDALGetDriverShortName( hDriver ),
+            GDALGetDriverLongName( hDriver ) );
+
+    printf( "Size is %dx%dx%d\n",
+            GDALGetRasterXSize( hDataset ),
+            GDALGetRasterYSize( hDataset ),
+            GDALGetRasterCount( hDataset ) );
+
+    if( GDALGetProjectionRef( hDataset ) != NULL )
+        printf( "Projection is `%s'\n", GDALGetProjectionRef( hDataset ) );
+
+    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
+    {
+        printf( "Origin = (%.6f,%.6f)\n",
+                adfGeoTransform[0], adfGeoTransform[3] );
+
+        printf( "Pixel Size = (%.6f,%.6f)\n",
+                adfGeoTransform[1], adfGeoTransform[5] );
+    }
+\endcode
+
+Em Python:
+\code
+    print 'Driver: ', dataset.GetDriver().ShortName,'/', \
+          dataset.GetDriver().LongName
+    print 'Size is ',dataset.RasterXSize,'x',dataset.RasterYSize, \
+          'x',dataset.RasterCount
+    print 'Projection is ',dataset.GetProjection()
+
+    geotransform = dataset.GetGeoTransform()
+    if not geotransform is None:
+        print 'Origin = (',geotransform[0], ',',geotransform[3],')'
+        print 'Pixel Size = (',geotransform[1], ',',geotransform[5],')'
+\endcode
+
+\section gdal_tutorial_band Extraindo uma Banda Raster
+
+Neste ponto o acesso aos dados da raster através de GDAL pode ser feito
+uma banda de cada vez. A Band também possui metadata, tamanho de block, tabelas da cor,
+e vário a outra informação disponível na classe GDALRasterBand.
+Os seguintes códigos buscam um objeto de GDALRasterBand da série de dados
+(numerada a partir de 1 em GetRasterCount()) e a exposições de algums
+informações sobre ela.
+
+Em C++:
+\code
+        GDALRasterBand  *poBand;
+        int             nBlockXSize, nBlockYSize;
+        int             bGotMin, bGotMax;
+        double          adfMinMax[2];
+
+        poBand = poDataset->GetRasterBand( 1 );
+        poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
+        printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
+                nBlockXSize, nBlockYSize,
+                GDALGetDataTypeName(poBand->GetRasterDataType()),
+                GDALGetColorInterpretationName(
+                    poBand->GetColorInterpretation()) );
+
+        adfMinMax[0] = poBand->GetMinimum( &bGotMin );
+        adfMinMax[1] = poBand->GetMaximum( &bGotMax );
+        if( ! (bGotMin && bGotMax) )
+            GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
+
+        printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
+
+        if( poBand->GetOverviewCount() > 0 )
+            printf( "Band has %d overviews.\n", poBand->GetOverviewCount() );
+
+        if( poBand->GetColorTable() != NULL )
+            printf( "Band has a color table with %d entries.\n",
+                     poBand->GetColorTable()->GetColorEntryCount() );
+\endcode
+
+Em C:
+\code
+    GDALRasterBandH hBand;
+    int             nBlockXSize, nBlockYSize;
+    int             bGotMin, bGotMax;
+    double          adfMinMax[2];
+
+    hBand = GDALGetRasterBand( hDataset, 1 );
+    GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
+    printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
+            nBlockXSize, nBlockYSize,
+            GDALGetDataTypeName(GDALGetRasterDataType(hBand)),
+            GDALGetColorInterpretationName(
+                GDALGetRasterColorInterpretation(hBand)) );
+
+    adfMinMax[0] = GDALGetRasterMinimum( hBand, &bGotMin );
+    adfMinMax[1] = GDALGetRasterMaximum( hBand, &bGotMax );
+    if( ! (bGotMin && bGotMax) )
+        GDALComputeRasterMinMax( hBand, TRUE, adfMinMax );
+
+    printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
+
+    if( GDALGetOverviewCount(hBand) > 0 )
+        printf( "Band has %d overviews.\n", GDALGetOverviewCount(hBand));
+
+    if( GDALGetRasterColorTable( hBand ) != NULL )
+        printf( "Band has a color table with %d entries.\n",
+                 GDALGetColorEntryCount(
+                     GDALGetRasterColorTable( hBand ) ) );
+\endcode
+
+In Python (note several bindings are missing):
+\code
+    band = dataset.GetRasterBand(1)
+
+    print 'Band Type=',gdal.GetDataTypeName(band.DataType)
+
+    min = band.GetMinimum()
+    max = band.GetMaximum()
+    if min is not None and max is not None:
+        (min,max) = ComputeRasterMinMax(1)
+    print 'Min=%.3f, Max=%.3f' % (min,max)
+
+    if band.GetOverviewCount() > 0:
+        print 'Band has ', band.GetOverviewCount(), ' overviews.'
+
+    if not band.GetRasterColorTable() is None:
+        print 'Band has a color table with ', \
+          band.GetRasterColorTable().GetCount(), ' entries.'
+\endcode
+
+\section gdal_tutorial_read Lendo dato Raster
+
+Há algumas maneiras diferentes de ler dados da raster, mas o mais comum é
+através do Método GDALRasterBand::RasterIO(). Este método tomará
+automaticamente cuidado da conversão do tipo de dados, amostragem e janela
+de dados requerida. O seguinte código lerá o primeiro scanline dos dados em um
+buffer em tamanho similar à quantidade lida, convertendo os valores para ponto
+flutuando como parte da operação:
+
+Em C++:
+\code
+        float *pafScanline;
+        int   nXSize = poBand->GetXSize();
+
+        pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
+        poBand->RasterIO( GF_Read, 0, 0, nXSize, 1,
+                          pafScanline, nXSize, 1, GDT_Float32,
+                          0, 0 );
+\endcode
+
+Em C:
+\code
+        float *pafScanline;
+        int   nXSize = GDALGetRasterBandXSize( hBand );
+
+        pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
+        GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1,
+                      pafScanline, nXSize, 1, GDT_Float32,
+                      0, 0 );
+\endcode
+
+Em Python:
+
+\code
+        scanline = band.ReadRaster( 0, 0, band.XSize, 1, \
+                                    band.XSize, 1, GDT_Float32 )
+\endcode
+
+Note que o scanline retornado é do tipo char*, e contem os
+bytes xsize*4 de dados binários brutos de ponto flutuando. Isto
+pode ser convertido em Python usando o módulo do <b>struct</b>
+da biblioteca padrão:
+
+\code
+        import struct
+
+        tuple_of_floats = struct.unpack('f' * b2.XSize, scanline)
+\endcode
+
+A chamada de RasterIO espera os seguintes argumentos.
+\code
+CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
+                                 int nXOff, int nYOff, int nXSize, int nYSize,
+                                 void * pData, int nBufXSize, int nBufYSize,
+                                 GDALDataType eBufType,
+                                 int nPixelSpace,
+                                 int nLineSpace )
+\endcode
+
+Note que a mesma chamada de RasterIO() poderá ler, ou gravar dependendo do valor
+de eRWFlag (GF_Read ou GF_Write). Os argumentos nXOff, nYOff, nXSize, nYSize
+descreve a janela de dados da raster para ler (ou para gravar).
+Não necessita ser coincidente com os limites da image embora o acesso pode ser mais eficiente se for.
+
+O pData é o buffer de memória para os dados que serão lidos ou gravados.
+O verdadeiro tipo de dado &eacute aquele passado por eBufType, tal como GDT_Float32,
+ou GDT_Byte. A chamada de RasterIO() cuidará de converter entre o tipo
+de dados do buffer e o tipo de dados da banda. Anotar que ao converter dados do
+ponto flutuando para o inteiro RasterIO arredonda para baixo, e ao converter de
+para fora dos limites de valores válidos para o tipo de saída, será escolhido o mais
+próximo valor possível.
+Isto implica, por exemplo, que os dados 16bit lidos em um buffer de GDT_Byte
+converterão todos os valores maiores de 255 para 255, os <b>dados não estão escalados!</b>
+
+Os valores nBufXSize e nBufYSize descrevem o tamanho do buffer. Ao carregar dados na
+resolução completa os valores seria o mesmo que o tamanho da janela. Entretanto, para carregar
+uma vista de solução reduzida (overview) os valores podiam ser ajustado para menos do que a janela
+no arquivo. Neste caso o RasterIO() utilizará overview para fazer
+mais eficientemente o IO se as overview forem apropriadas.
+
+O nPixelSpace, e o nLineSpace são normalmente zero indicando que os valores default
+devem ser usados. Entretanto, podem ser usados controlar o acesso à dados da memória,
+permitindo a leitura em um buffer que contem dados intercalados (interleave) pixel por exemplo.
+
+\section gdal_tutorial_close Fechando o Dataset
+
+Por favor tenha em mente que os objetos de GDALRasterBand estão possuídos por sua
+dataset, e nunca devem ser destruídos com o operador delete de C++.
+GDALDataset podem ser fechado chamando GDALClose() ou usando o operador delete
+no GDALDataset. Um ou outro resultado na finalização apropriada, e resolver
+gravações pendentes.
+
+\section gdal_tutorial_creation Tecnicas para criar arquivos
+
+As arquivos em formatos suportados GDAL podem ser criadas se o driver do formato
+suportar a criação. Há duas técnicas gerais para criar arquivos, usando CreateCopy() e Create().
+O método de CreateCopy chama o método CreateCopy() do driver do formato, e
+passar como parâmetro dataset que será copiado. O método criar chama o
+método Create() do driver, e então explicitamente grava todos os metadata, e dados
+da raster com as chamadas separadas. Todos os drivers que suportam criar arquivos
+novos suportam o método de CreateCopy(), mas somente algum sustentação o método Create().
+
+Para determinar se o driver de um formato suporta Create ou CreateCopy é necessário verificar o
+DCAP_CREATE e os metadata de DCAP_CREATECOPY no driver do formato
+objetam. Assegurar-se de que GDALAllRegister() tenha sido chamado antes de chamar GetDriverByName().
+
+Em C++:
+\code
+#include "cpl_string.h"
+...
+    const char *pszFormat = "GTiff";
+    GDALDriver *poDriver;
+    char **papszMetadata;
+
+    poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
+
+    if( poDriver == NULL )
+        exit( 1 );
+
+    papszMetadata = poDriver->GetMetadata();
+    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
+        printf( "Driver %s supports Create() method.\n", pszFormat );
+    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
+        printf( "Driver %s supports CreateCopy() method.\n", pszFormat );
+\endcode
+
+Em C:
+\code
+#include "cpl_string.h"
+...
+    const char *pszFormat = "GTiff";
+    GDALDriver hDriver = GDALGetDriverByName( pszFormat );
+    char **papszMetadata;
+
+    if( hDriver == NULL )
+        exit( 1 );
+
+    papszMetadata = GDALGetMetadata( hDriver, NULL );
+    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
+        printf( "Driver %s supports Create() method.\n", pszFormat );
+    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
+        printf( "Driver %s supports CreateCopy() method.\n", pszFormat );
+\endcode
+
+Em Python:
+
+\code
+    format = "GTiff"
+    driver = gdal.GetDriverByName( format )
+    metadata = driver.GetMetadata()
+    if metadata.has_key(gdal.DCAP_CREATE) \
+       and metadata[gdal.DCAP_CREATE] == 'YES':
+        print 'Driver %s supports Create() method.' % format
+    if metadata.has_key(gdal.DCAP_CREATECOPY) \
+       and metadata[gdal.DCAP_CREATECOPY] == 'YES':
+        print 'Driver %s supports CreateCopy() method.' % format
+\endcode
+
+Note que um número de drivers são de leitura apenas e não suportarão
+Create() ou CreateCopy ().
+
+\section gdal_tutorial_createcopy Usando CreateCopy()
+
+O GDALDriver:: O método de CreateCopy() pode ser usado razoavelmente
+simples enquanto a maioria de informação é coletada do dataset de entrada.
+Entretanto, inclui opções para passar a formato opções
+específicas da criação, e para relatar o progresso ao usuário enquanto
+uma cópia longa da série de dados ocorre. Uma cópia simples de uma arquivo
+nomeou o pszSrcFilename, a uma arquivo nova nomeada pszDstFilename usando
+opções de defeito em um formato cujo o driver fosse buscado previamente
+pudesse olhar como este:
+
+Em C++:
+\code
+    GDALDataset *poSrcDS =
+       (GDALDataset *) GDALOpen( pszSrcFilename, GA_ReadOnly );
+    GDALDataset *poDstDS;
+
+    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
+                                    NULL, NULL, NULL );
+    if( poDstDS != NULL )
+        delete poDstDS;
+\endcode
+
+Em C:
+\code
+    GDALDatasetH hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
+    GDALDatasetH hDstDS;
+
+    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE,
+                             NULL, NULL, NULL );
+    if( hDstDS != NULL )
+        GDALClose( hDstDS );
+\endcode
+
+Em Python:
+
+\code
+    src_ds = gdal.Open( src_filename )
+    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0 )
+\endcode
+
+Note que o método de CreateCopy() retorna um dataset writeable,
+e que deve ser fechado corretamente à escrita completa e a nivelar a série
+de dados ao disco. No Python encaixotar isto ocorre automaticamente quando
+os "dst_ds" saem do espaço. O valor FALSO (ou 0) usado para a opção do
+bStrict imediatamente depois que o nome de arquivo do destino na chamada
+de CreateCopy() indica que a chamada de CreateCopy() deve proseguir sem
+um erro fatal mesmo se a série de dados do destino não puder ser criada
+para combinar exatamente a série de dados da entrada. Isto pôde ser porque
+o formato da saída não suporta o datatype do pixel do dataset de entrada,
+ou porque o destino não pode suportar a escrita que georeferencing
+por exemplo.
+
+Casos mais complexo pôdem envolver passar opções da criação, e usar
+um monitor predefinido do progresso como este:
+
+Em C++:
+\code
+#include "cpl_string.h"
+...
+    char **papszOptions = NULL;
+
+    papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
+    papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
+    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
+                                    papszOptions, GDALTermProgress, NULL );
+    if( poDstDS != NULL )
+        delete poDstDS;
+    CSLDestroy( papszOptions );
+\endcode
+
+Em C:
+\code
+#include "cpl_string.h"
+...
+    char **papszOptions = NULL;
+
+    papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
+    papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
+    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE,
+                             papszOptions, GDALTermProgres, NULL );
+    if( hDstDS != NULL )
+        GDALClose( hDstDS );
+    CSLDestroy( papszOptions );
+\endcode
+
+Em Python:
+
+\code
+    src_ds = gdal.Open( src_filename )
+    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0,
+                                [ 'TILED=YES', 'COMPRESS=PACKBITS' ] )
+\endcode
+
+\section gdal_tutorial_create Usando Create()
+
+Em situações em que não se quer somente exportar um arquivo existente
+para uma arquivo novo, geralmente usa-se o método GDALDriver::Create() (embora algumas
+opções interessantes são possíveis
+com o uso de arquivos virtuais ou de arquivos da em-memória).
+O método Create() examina uma lista de opções bem como o CreateCopy(), mas
+o tamanho da imagem, número das bandas e o tipo da banda deve ser fornecido explicitamente.
+<p>
+
+Em C++:
+\code
+    GDALDataset *poDstDS;
+    char **papszOptions = NULL;
+
+    poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte,
+                                papszOptions );
+\endcode
+
+Em C:
+\code
+    GDALDatasetH hDstDS;
+    char **papszOptions = NULL;
+
+    hDstDS = GDALCreate( hDriver, pszDstFilename, 512, 512, 1, GDT_Byte,
+                         papszOptions );
+\endcode
+
+Em Python:
+
+\code
+    dst_ds = driver.Create( dst_filename, 512, 512, 1, gdal.GDT_Byte )
+\endcode
+
+Uma vez que o dataset é criado com sucesso, todos os metadata apropriados devem
+ser gravados no arquivo. O que variará de acordo com o uso,
+mas um caso simples com projeção, do geotransform e da raster é
+mostrado a seguir:<p>
+
+Em C++:
+\code
+    double adfGeoTransform[6] = { 444720, 30, 0, 3751320, 0, -30 };
+    OGRSpatialReference oSRS;
+    char *pszSRS_WKT = NULL;
+    GDALRasterBand *poBand;
+    GByte abyRaster[512*512];
+
+    poDstDS->SetGeoTransform( adfGeoTransform );
+
+    oSRS.SetUTM( 11, TRUE );
+    oSRS.SetWellKnownGeogCS( "NAD27" );
+    oSRS.exportToWkt( &pszSRS_WKT );
+    poDstDS->SetProjection( pszSRS_WKT );
+    CPLFree( pszSRS_WKT );
+
+    poBand = poDstDS->GetRasterBand(1);
+    poBand->RasterIO( GF_Write, 0, 0, 512, 512,
+                      abyRaster, 512, 512, GDT_Byte, 0, 0 );
+
+    delete poDstDS;
+\endcode
+
+Em C:
+\code
+    double adfGeoTransform[6] = { 444720, 30, 0, 3751320, 0, -30 };
+    OGRSpatialReferenceH hSRS;
+    char *pszSRS_WKT = NULL;
+    GDALRasterBandH hBand;
+    GByte abyRaster[512*512];
+
+    GDALSetGeoTransform( hDstDS, adfGeoTransform );
+
+    hSRS = OSRNewSpatialReference( NULL );
+    OSRSetUTM( hSRS, 11, TRUE );
+    OSRSetWellKnownGeogCS( hSRS, "NAD27" );
+    OSRExportToWkt( hSRS, &pszSRS_WKT );
+    OSRDestroySpatialReference( hSRS );
+
+    GDALSetProjection( hDstDS, pszSRS_WKT );
+    CPLFree( pszSRS_WKT );
+
+    hBand = GDALGetRasterBand( hDstDS, 1 );
+    GDALRasterIO( hBand, GF_Write, 0, 0, 512, 512,
+                  abyRaster, 512, 512, GDT_Byte, 0, 0 );
+
+    GDALClose( hDstDS );
+\endcode
+
+Em Python:
+
+\code
+    import Numeric, osr
+
+    dst_ds.SetGeoTransform( [ 444720, 30, 0, 3751320, 0, -30 ] )
+
+    srs = osr.SpatialReference()
+    srs.SetUTM( 11, 1 )
+    srs.SetWellKnownGeogCS( 'NAD27' )
+    dst_ds.SetProjection( srs.ExportToWkt() )
+
+    raster = Numeric.zeros( (512, 512) )
+    dst_ds.GetRasterBand(1).WriteArray( raster )
+\endcode
+
+\htmlonly
+<p>
+$Id: gdal_tutorial_br.dox $
+</p>
+\endhtmlonly
+
+*/
diff --git a/doc/br/index_br.dox b/doc/br/index_br.dox
index 3fedf6b..1820a1c 100644
--- a/doc/br/index_br.dox
+++ b/doc/br/index_br.dox
@@ -1,142 +1,162 @@
-#ifndef DOXYGEN_SKIP
-/* $Id: index_br.dox $ */
-Translation corresponds to index.dox "11836 2007-08-02 21:24:45Z warmerdam"
-Translator Ivan Lucena <ivan dot lucena at oracle dot com>
-#endif /* DOXYGEN_SKIP */
-
-/*! \page index_br GDAL - Biblioteca de Abstrações de Dados Geo-Espaciais
-
-<center>
-<b>Selecione o idioma</b>:
-<a href="index.html">[English] </a>
-<a href="index_ru.html">[Russian] </a>
-[Portuguese]
-<a href="http://softlibre.gloobe.org/doku.php?id=gdal_ogr:couteau_suisse:start">[Frances]</a>
-</center>
-
-\htmlonly<img src="gdalicon.png" alt="GDAL">\endhtmlonly \latexonly GDAL \endlatexonly
-é uma bibliotéca para tradução de formatos de dados geográficos distribuída pela
-<a href="http://www.osgeo.org/">Open Source Geospatial Foundation</a> sob a licença
-<a href="http://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse">X/MIT</a> estilo
-<a href="http://www.opensource.org/"> Open Source</a>.
-As aplicações que à utilizam acessam todos os formats
-supportados pela biblioteca através de
-\link gdal_datamodel_br.html um único modelo de dados abstrato\endlink.
-A bilioteca GDAL também conta com uma variadade de programas
-<a class="el" href="gdal_utilities.html"> utilitários de linha de comando</a>
-para a tradução de formatos bem como uma série de outras funções.
-A página
-<a href="http://trac.osgeo.org/gdal/wiki/Release/2.0.0-News">novidades</a> descreve o
-lançamento em Junho de 2015 da release 2.0.0 da biblioteca GDAL/OGR.
-
-Tradicionalmente a bilioteca GDAL referia-se a dados Raster enquanto que OGR 
-referia-se a dados Vetorias (Simple Features). Mas a partir da verção 2.0 as duas partes 
-estão mais integradas. Voce ainda pode se referir a 
-<a href="http://gdal.org/1.11/index.html">documentação da GDAL 1.X</a> se necessário.
-
-
-Página Principal: http://www.gdal.org<br>
-Download:
- <a href="ftp://ftp.remotesensing.org/gdal">ftp at remotesensing.org</a>,
- <a href="http://download.osgeo.org/gdal">http at download.osgeo.org</a>
-
-\section index_userdocs Documentação para usuário
-
-<ul>
-<li> <a href="http://trac.osgeo.org/gdal/">Wiki</a> - Documentação e dicas mantidas por vários desenvolvedores e contribuidores
-<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">Downloads</a> - <Programas executáveis prontos para usar
-<li> <a href="formats_list.html">Formatos raster suportados</a> (142 drivers): <a href="frmt_gtiff.html">GeoTIFF</a>, <a href="frmt_hfa.html">Erdas Imagine</a>, <a href="frmt_ecw.html">ECW</a>, <a href="frmt_mrsid.html">MrSID</a>, <a href="frmt_jp2openjpeg.html">JPEG2000</a>, <a href="frmt_dted.html">DTED</a>, <a href="frmt_nitf.html">NITF</a>, <a href="drv_geopackage_raster.html">GeoPackage</a>, ...
-<li> <a href="ogr_formats.html">Formatos vectorais suportados</a> (84 drivers): <a href="drv_shapefile.html">ESRI Shapefile</a>, <a href="drv_sde.html">ESRI ArcSDE</a>, <a href="drv_openfilegdb.html">ESRI FileGDB</a>, <a href="drv_mitab.html">MapInfo (tab and mid/mif)</a>, <a href="drv_gml.html">GML</a>, <a href="drv_libkml.html">KML</a>, <a href="drv_pg.html">PostGIS</a>, <a href="drv_oci.html">Oracle Spatial</a>, <a href="drv_geopackage.html">GeoPackage</a>, ...
-<li> <a href="gdal_utilities.html">Programas utilitários para raster</a>: <a href="gdalinfo.html">gdalinfo</a>, <a href="gdal_translate.html">gdal_translate</a>, <a href="gdaladdo.html">gdaladdo</a>, <a href="gdalwarp.html">gdalwarp</a>, ...
-<li> <a href="ogr_utilities.html">Programas utilitários para vector</a>: <a href="ogrinfo.html">ogrinfo</a>, <a href="ogr2ogr.html">ogr2ogr</a>, <a href="ogrtindex.html">ogrtindex</a>, ...
-<li> <a href="http://trac.osgeo.org/gdal/wiki/FAQ">Perguntas Mais Frequentes</a>
-<li> <a href="gdal_datamodel_br.html">Modelo de dados raster </a> <b>(em português)</b> e <a href="ogr_arch.html">vectorial</a> em Inglès.
-<li> <a href="http://trac.osgeo.org/gdal/wiki/GovernanceAndCommunity">Governança e participação comunitária</a>
-<li> <a href="http://www.osgeo.org/search_profile?SET=1&MUL_TECH[0]=00013">Lista de provedores de serviço GDAL</a> (lista de provedores não vetados)
-<li> <a href="credits.html">Patrocinadores, Agradecimentos e Créditos</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/SoftwareUsingGdal">Software que usam GDAL</a>
-</ul>
-
-\section index_devdocs Documentação para desenvolvedor
-
-<ul>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/BuildHints">Como compilar GDAL</a>
-<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">Downloads</a> - código fonte
-<li> <a href="wince.html">GDAL para Windows CE (sem manutenção)</a>
-</ul>
-
-\section index_devdocs_tutorial Tutoriais
-
-<ul>
-<li> Raster topics:
-  <ul>
-    <li> <a href="gdal_tutorial_br.html">Tutorial da API raster</a>
-    <li> <a href="gdal_drivertut.html">Implementação de driver raster</a>
-    <li> <a href="gdal_vrttut.html">Formato virtual raster (VRT)</a>
-    <li> <a href="warptut.html">Tutorial de Reprojeção em raster
-  </ul>
-</li>
-<li> Vector topics:
-  <ul>
-    <li> <a href="ogr_apitut.html">Tutorial da API vetorial</a>
-    <li> <a href="ogr_drivertut.html">Implementação de driver vetorial</a>
-    <li> <a href="drv_vrt.html">Formato virtual vetorial (VRT)</a>
-    <li> <a href="ogr_feature_style.html">Especificação de estilo vetorial</a>
-   </ul>
-</li>
-<li> <a href="osr_tutorial.html"> Tutorial de Referência Espacial</a> (OSR - OGRSpatialReference)
-</ul>
-
-\subsection index_devdocs_api Documentação da API
-
-<ul>
-<li> <a href="hierarchy.html">Documentação de referencia da API</a>
-<li> <a href="gdal_8h.html">API raster para C</a>
-<li> <a href="ogr_api_8h.html">API vector para C</a>
-<li> <a href="classGDALDataset.html">GDALDataset para C++</a>
-<li> <a href="classGDALRasterBand.html">GDALRasterBand para C++</a>
-<li> <a href="classOGRLayer.html">OGRLayer para C++</a>
-<li> Dialeto <a href="ogr_sql.html">OGR SQL</a> e dialeto <a href="ogr_sql_sqlite.html">SQLITE SQL</a>
-</ul>
-
-<!--
-\subsection index_devdocs_specs Specifications
-
-<ul>
-<li> <a href="http://home.gdal.org/projects/opengis/twohalfdsf.html">Adam's 2.5 D Simple Features Proposal (OGC 99-402r2)</a>
-<li> Adam's SRS WKT Clarification Proposal in <a href="http://home.gdal.org/projects/opengis/wkt_prop.html">html</a>
-or <a href="http://home.gdal.org/projects/opengis/wkt_prop.doc">doc</a> format.
-</ul>
--->
-
-\section index_maillist Lista de discussão por correio eletrònico
-
-A lista <a href="http://lists.osgeo.org/mailman/listinfo/gdal-announce">gdal-announce</a>
-é uma lista de pequeno volume de mensagens usada somente para anunciar lançamento de
-versões e desenvolvimentos significativos.
-
-A lista <a href="mailto:gdal-dev at lists.maptools.org">gdal-dev at lists.maptools.org</a>
-pode ser usada para a discussão sobre o desenvolvimento e uso da GDAL e tecnologias relaciadas.
-A inscrição e o acesso aos arquivo da lista podem ser feitos
-<a href="http://lists.maptools.org/mailman/listinfo/gdal-dev/"> nesta página</a>.
-Os arquivos da lista também estão disponíveis (somente para leitura) através do
-<a href="news://news.gmane.org/gmane.comp.gis.gdal.devel">news://news.gmane.org/gmane.comp.gis.gdal.devel</a>
-ou na página
-<a href="http://news.gmane.org/gmane.comp.gis.gdal.devel">http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.<p>
-
-Usuários e desenvolvedores da GDAL/OGR podem constantemente ser achados no canal IRC
-<a href="irc://irc.freenode.net/#gdal">#gdal</a> do irc.freenode.net.<p>
-
-\section index_bugs Como Reportar Problemas (Bugs)
-
-Bugs em GDAL podem ser
-<a href="http://trac.osgeo.org/gdal/newticket">reportados</a> e também
-<a href="http://trac.osgeo.org/gdal/report/1?sort=ticket&asc=0">listados</a> através do software Trac.<p>
-
-\section index_bindings GDAL em outras linguagens
-
-Lista de linguagens de programção supportadas por GDAL:
-<a href="http://trac.osgeo.org/gdal/#GDALOGRInOtherLanguages">GDAL
-wiki</a>.
-
-*/
+#ifndef DOXYGEN_SKIP
+/* $Id: index_br.dox $ */
+Translation corresponds to index.dox "11836 2007-08-02 21:24:45Z warmerdam"
+Translator Ivan Lucena <ivan dot lucena at oracle dot com>
+#endif /* DOXYGEN_SKIP */
+
+/*! \page index_br GDAL - Biblioteca de Abstrações de Dados Geo-Espaciais
+
+<center>
+<b>Selecione o idioma</b>:
+<a href="index.html">[English] </a>
+<a href="index_ru.html">[Russian] </a>
+[Portuguese]
+<a href="http://softlibre.gloobe.org/doku.php?id=gdal_ogr:couteau_suisse:start">[Frances]</a>
+</center>
+
+\htmlonly<img src="gdalicon.png" alt="GDAL">\endhtmlonly \latexonly GDAL \endlatexonly
+é uma bibliotéca para tradução de formatos de dados geográficos distribuída pela
+<a href="http://www.osgeo.org/">Open Source Geospatial Foundation</a> sob a licença
+<a href="http://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse">X/MIT</a> estilo
+<a href="http://www.opensource.org/"> Open Source</a>.
+As aplicações que à utilizam acessam todos os formats
+supportados pela biblioteca através de
+\link gdal_datamodel_br.html um único modelo de dados abstrato\endlink.
+A bilioteca GDAL também conta com uma variadade de programas
+<a class="el" href="gdal_utilities.html"> utilitários de linha de comando</a>
+para a tradução de formatos bem como uma série de outras funções.
+A página
+<a href="http://trac.osgeo.org/gdal/wiki/Release/2.0.0-News">novidades</a> descreve o
+lançamento em Outubro de 2016 da release 2.1.2 da biblioteca GDAL/OGR.
+
+Tradicionalmente a bilioteca GDAL referia-se a dados Raster enquanto que OGR
+referia-se a dados Vetorias (Simple Features). Mas a partir da verção 2.0 as duas partes
+estão mais integradas. Voce ainda pode se referir a
+<a href="http://gdal.org/1.11/index.html">documentação da GDAL 1.X</a> se necessário.
+
+
+Página Principal: http://www.gdal.org<br>
+Download:
+ <a href="ftp://ftp.remotesensing.org/gdal">ftp at remotesensing.org</a>,
+ <a href="http://download.osgeo.org/gdal">http at download.osgeo.org</a>
+
+\section index_userdocs Documentação para usuário
+
+<ul>
+<li> <a href="http://trac.osgeo.org/gdal/">Wiki</a> - Documentação e dicas mantidas por vários desenvolvedores e contribuidores
+<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">Downloads</a> - Programas executáveis prontos para usar
+<li> <a href="formats_list.html">Formatos raster suportados</a> (142 drivers): <a href="frmt_gtiff.html">GeoTIFF</a>, <a href="frmt_hfa.html">Erdas Imagine</a>, <a href="frmt_ecw.html">ECW</a>, <a href="frmt_mrsid.html">MrSID</a>, <a href="frmt_jp2openjpeg.html">JPEG2000</a>, <a href="frmt_dted.html">DTED</a>, <a href="frmt_nitf.html">NITF</a>, <a href="drv_geopackage_raster.html">GeoPackage</a>, ...
+<li> <a href="ogr_formats.html">Formatos vectorais suportados</a> (84 drivers): <a href="drv_shapefile.html">ESRI Shapefile</a>, <a href="drv_sde.html">ESRI ArcSDE</a>, <a href="drv_openfilegdb.html">ESRI FileGDB</a>, <a href="drv_mitab.html">MapInfo (tab and mid/mif)</a>, <a href="drv_gml.html">GML</a>, <a href="drv_libkml.html">KML</a>, <a href="drv_pg.html">PostGIS</a>, <a href="drv_oci.html">Oracle Spatial</a>, <a href="drv_geopackage.html">GeoPackage</a>, ...
+<li> <a href="gdal_utilities.html">Programas utilitários para raster</a>: <a href="gdalinfo.html">gdalinfo</a>, <a href="gdal_translate.html">gdal_translate</a>, <a href="gdaladdo.html">gdaladdo</a>, <a href="gdalwarp.html">gdalwarp</a>, ...
+<li> <a href="ogr_utilities.html">Programas utilitários para vector</a>: <a href="ogrinfo.html">ogrinfo</a>, <a href="ogr2ogr.html">ogr2ogr</a>, <a href="ogrtindex.html">ogrtindex</a>, ...
+<li> <a href="http://trac.osgeo.org/gdal/wiki/FAQ">Perguntas Mais Frequentes</a>
+<li> <a href="gdal_datamodel_br.html">Modelo de dados raster </a> <b>(em português)</b> e <a href="ogr_arch.html">vectorial</a> em Inglès.
+<li> <a href="http://trac.osgeo.org/gdal/wiki/GovernanceAndCommunity">Governança e participação comunitária</a>
+<li> <a href="http://www.osgeo.org/search_profile?SET=1&MUL_TECH[0]=00013">Lista de provedores de serviço GDAL</a> (lista de provedores não vetados)
+<li> <a href="credits.html">Patrocinadores, Agradecimentos e Créditos</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/SoftwareUsingGdal">Software que usam GDAL</a>
+</ul>
+
+\section index_devdocs Documentação para desenvolvedor
+
+<ul>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/BuildHints">Como compilar GDAL</a>
+<li> <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">Downloads</a> - código fonte
+<li> <a href="wince.html">GDAL para Windows CE (sem manutenção)</a>
+</ul>
+
+\section index_devdocs_tutorial Tutoriais
+
+<ul>
+<li> Raster topics:
+  <ul>
+    <li> <a href="gdal_tutorial_br.html">Tutorial da API raster</a></li>
+    <li> <a href="gdal_drivertut.html">Implementação de driver raster</a></li>
+    <li> <a href="gdal_vrttut.html">Formato virtual raster (VRT)</a></li>
+    <li> <a href="warptut.html">Tutorial de Reprojeção em raster</a></li>
+  </ul>
+</li>
+<li> Vector topics:
+  <ul>
+    <li> <a href="ogr_apitut.html">Tutorial da API vetorial</a></li>
+    <li> <a href="ogr_drivertut.html">Implementação de driver vetorial</a></li>
+    <li> <a href="drv_vrt.html">Formato virtual vetorial (VRT)</a></li>
+    <li> <a href="ogr_feature_style.html">Especificação de estilo vetorial</a></li>
+   </ul>
+</li>
+<li> <a href="osr_tutorial.html"> Tutorial de Referência Espacial</a> (OSR - OGRSpatialReference)
+</ul>
+
+\subsection index_devdocs_api Documentação da API
+
+<ul>
+<li> <a href="hierarchy.html">Documentação de referencia da API</a></li>
+<li> <a href="gdal_8h.html">API raster para C</a></li>
+<li> <a href="ogr_api_8h.html">API vector para C</a></li>
+<li> <a href="classGDALDataset.html">GDALDataset para C++</a></li>
+<li> <a href="classGDALRasterBand.html">GDALRasterBand para C++</a></li>
+<li> <a href="classOGRLayer.html">OGRLayer para C++</a></li>
+<li> Dialeto <a href="ogr_sql.html">OGR SQL</a> e dialeto <a href="ogr_sql_sqlite.html">SQLITE SQL</a></li>
+</ul>
+
+<!--
+\subsection index_devdocs_specs Specifications
+
+<ul>
+<li> <a href="http://home.gdal.org/projects/opengis/twohalfdsf.html">Adam's 2.5 D Simple Features Proposal (OGC 99-402r2)</a>
+<li> Adam's SRS WKT Clarification Proposal in <a href="http://home.gdal.org/projects/opengis/wkt_prop.html">html</a>
+or <a href="http://home.gdal.org/projects/opengis/wkt_prop.doc">doc</a> format.
+</ul>
+-->
+
+\section foss4g Conference
+
+\htmlonly
+<table border="0" cellspacing="4" cellpadding="4">
+
+<tr><td><a href="http://2017.foss4g.org/">
+<img src="foss4g2017.png" alt="FOSS4G 2017" border="0">
+</a></td>
+
+<td><a href="http://2017.foss4g.org">FOSS4G 2017</a> 
+
+É a principal conferência anual de software geoespacial livre e de código aberto.
+Ele incluirá apresentações relacionadas ao GDAL/OGR, e alguns dos membros da comunidade 
+de desenvolvimento da GDAL/OGR estarão participando. É o evento para aqueles interessados em GDAL/OGR,
+outras tecnologias geoespaciais FOSS e da comunidade em torno deles.
+A conferência será realizada em Boston, EUA, de <strong>14 a 18 de agosto de 2017.</strong>.</td>
+</table>
+
+\endhtmlonly
+
+\section index_maillist Lista de discussão por correio eletrônico
+
+A lista <a href="http://lists.osgeo.org/mailman/listinfo/gdal-announce">gdal-announce</a>
+é uma lista de pequeno volume de mensagens usada somente para anunciar lançamento de
+versões e desenvolvimentos significativos.
+
+A lista <a href="mailto:gdal-dev at lists.maptools.org">gdal-dev at lists.maptools.org</a>
+pode ser usada para a discussão sobre o desenvolvimento e uso da GDAL e tecnologias relaciadas.
+A inscrição e o acesso aos arquivo da lista podem ser feitos
+<a href="http://lists.maptools.org/mailman/listinfo/gdal-dev/"> nesta página</a>.
+Os arquivos da lista também estão disponíveis (somente para leitura) através do
+<a href="news://news.gmane.org/gmane.comp.gis.gdal.devel">news://news.gmane.org/gmane.comp.gis.gdal.devel</a>
+ou na página
+<a href="http://news.gmane.org/gmane.comp.gis.gdal.devel">http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.<p>
+
+Usuários e desenvolvedores da GDAL/OGR podem constantemente ser achados no canal IRC
+<a href="irc://irc.freenode.net/#gdal">\#gdal</a> do irc.freenode.net.<p>
+
+\section index_bugs Como Reportar Problemas (Bugs)
+
+Bugs em GDAL podem ser
+<a href="http://trac.osgeo.org/gdal/newticket">reportados</a> e também
+<a href="http://trac.osgeo.org/gdal/report/1?sort=ticket&asc=0">listados</a> através do software Trac.<p>
+
+\section index_bindings GDAL em outras linguagens
+
+Lista de linguagens de programção supportadas por GDAL:
+<a href="http://trac.osgeo.org/gdal/#GDALOGRInOtherLanguages">GDAL
+wiki</a>.
+
+*/
diff --git a/doc/credits.dox b/doc/credits.dox
index 97e12c7..1e9fc60 100644
--- a/doc/credits.dox
+++ b/doc/credits.dox
@@ -1,15 +1,15 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: credits.dox 33134 2016-01-23 23:10:03Z rouault $ */
+/* $Id: credits.dox 35221 2016-08-27 23:28:41Z goatbar $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
 \page credits Acknowledgements and Credits
 
-There are too many people who have helped since GDAL/OGR was launched in 
-late 1998 for me to thank them all.  I have received moral support, 
+There are too many people who have helped since GDAL/OGR was launched in
+late 1998 for me to thank them all.  I have received moral support,
 financial support, code contributions, sample datasets, and bug reports
 from literally hundreds of people.  However, below I would like to single
-out a few people and organizations who have supported GDAL over the 
+out a few people and organizations who have supported GDAL over the
 years.  Forgive me for all those I left out.<p>
 
 <i>Frank Warmerdam</i><p>
@@ -21,13 +21,13 @@ years.  Forgive me for all those I left out.<p>
 He is primarily responsible for the HDF, MrSID, L1B, and PCIDSK drivers.
 He has also relieved me of most libtiff maintenance work.  <p>
 
-<li> <b>Daniel Morissette</b>: for his key contributions to CPL library, and 
+<li> <b>Daniel Morissette</b>: for his key contributions to CPL library, and
 development of the Mapinfo TAB translator.<p>
 
 <li> <b>Howard Butler</b>: for substantial improvements to the python
 bindings.<p>
 
-<li> <b>Ken Shih</b>: for the bulk of the implementation of the OLE DB 
+<li> <b>Ken Shih</b>: for the bulk of the implementation of the OLE DB
 provider.<p>
 
 <li> <b>Markus Neteler</b>: for various contributions to GDAL documentation
@@ -36,32 +36,32 @@ and general supportiveness.<p>
 <li> <b>Silke Reimer</b>: for work on Debian, and RPM packaging as well
 as the GDAL man pages.<p>
 
-<li> <b>Alessandro Amici</b>: for work on configuration and build system, 
+<li> <b>Alessandro Amici</b>: for work on configuration and build system,
 and for the initial Debian packaging.<p>
 
-<li> <b>Stephane Villeneuve</b>: for development of the Mapinfo MIF 
+<li> <b>Stephane Villeneuve</b>: for development of the Mapinfo MIF
 translator.<p>
 
-<li> <b>Marin Byrne</b>: for producing the current GDAL icon set (based on 
+<li> <b>Marin Byrne</b>: for producing the current GDAL icon set (based on
 the earlier version by Martin Daly).<p>
 
-<li> <b><a href="http://www.darek.info.pl/">Darek Krawczyk</a></b>: for producing design of the GDAL Team Member t-shirt (based on Marin's and Martin's graphics).<p>  
+<li> <b><a href="http://www.darek.info.pl/">Darek Krawczyk</a></b>: for producing design of the GDAL Team Member t-shirt (based on Marin's and Martin's graphics).<p>
 
 </ul>
 
 \section credits_cooperate Corporate
 
-<ul> 
+<ul>
 
-<li> <b><a href="http://www.actgate.com/">Applied Coherent 
-Technologies</a></b>: Supported implementation of the GDAL contour generator, 
+<li> <b><a href="http://www.actgate.com/">Applied Coherent
+Technologies</a></b>: Supported implementation of the GDAL contour generator,
 as well as various improvements to HDF drivers. Has been a Silver sponsor
 of GDAL.
 <p>
 
-<li> <b><a href="http://www.atlantis-scientific.com/">Atlantis 
-Scientific</a></b>: Supported the development of the CEOS, 
-and a variety of other radar oriented format drivers as well as 
+<li> <b><a href="http://www.atlantis-scientific.com/">Atlantis
+Scientific</a></b>: Supported the development of the CEOS,
+and a variety of other radar oriented format drivers as well as
 development of OpenEV, my day-to-day GDAL image viewer.<p>
 
 <li> <b><a href="http://www.augsignals.com">A.U.G. Signals</a></b>:
@@ -74,45 +74,45 @@ the basis of OGR dgn support, as well as preliminary work on image warping
 in GDAL.
 <p>
 
-<li> <b><a href="http://www.cadcorp.com">Cadcorp</a></b>: Supported 
+<li> <b><a href="http://www.cadcorp.com">Cadcorp</a></b>: Supported
 development of the Virtual Warped Raster capability. Has been a silver sponsor
 of GDAL.
 <p>
 
 <li> <b><a href="http://www.dmsolutions.ca/">DM Solutions Group</a></b>:
-Supported the development of the DGN driver, the OGR Arc/Info Binary 
-Coverage driver, OGR WCTS (Web Coordinate Transformation Server), 
+Supported the development of the DGN driver, the OGR Arc/Info Binary
+Coverage driver, OGR WCTS (Web Coordinate Transformation Server),
 OGR VRT driver, ODBC driver, MySQL driver, SQLite driver, OGR JOIN and
 OGR C API.
 <p>
 
 <li> <b><a href="http://www.ermapper.com">ERMapper</a></b>: provided
-primary sponsorship for GDAL from February 2005 to November 2006 to support 
+primary sponsorship for GDAL from February 2005 to November 2006 to support
 work on GDAL improvement efforts not focused on any particular client project.
 <p>
 
-<li> <b><a href="http://gsc.nrcan.gc.ca">Geological Survey of Canada</a></b>, 
+<li> <b><a href="http://gsc.nrcan.gc.ca">Geological Survey of Canada</a></b>,
 Natural Resources Canada: Supported the initial development of the ArcSDE raster
 driver. <p>
 
-<li> <b><a href="http://www.osgis.nl/">OSGIS</a></b> and the 
+<li> <b><a href="http://www.osgis.nl/">OSGIS</a></b> and the
 Geo-Information and ICT Department of the Ministry of Transport, Public
 Works and Water Management:
 Funded the DWG/DXF writing driver in OGR.<p>
 
-<li> <b><a href="http://www.geosoft.com/">Geosoft</a></b>: Supported 
-improvements to libtiff (RGBA Strip/Tile access), and the Arc/Info Binary Grid 
+<li> <b><a href="http://www.geosoft.com/">Geosoft</a></b>: Supported
+improvements to libtiff (RGBA Strip/Tile access), and the Arc/Info Binary Grid
 driver.
 <p>
 
-<li> <b><a href="http://www.geospaceinc.com/">Geospace Inc</a></b>, 
+<li> <b><a href="http://www.geospaceinc.com/">Geospace Inc</a></b>,
 Supported the development of write functionality for the OGR ArcSDE driver. <p>
 
-<li> <b><a href="http://www.geotango.com/">GeoTango</a></b>: Supported 
+<li> <b><a href="http://www.geotango.com/">GeoTango</a></b>: Supported
 OGR Memory driver, Virtual Raster Filtering, and NITF RPC capabilities.
 <p>
 
-<li> <b><a href="http://www.i3.com">i-cubed</a></b>: Supported the MrSID 
+<li> <b><a href="http://www.i3.com">i-cubed</a></b>: Supported the MrSID
 driver. Has been a Silver sponsor of GDAL.
 <p>
 
@@ -150,8 +150,8 @@ read support.
 <li> <b><a href="http://www.fao.org/">UN FAO</a></b>: Supported development
 of the IDA (WinDisp) driver, and GDAL VB6 bindings.<p>
 
-<li> <b><a href="http://www.softmaptech.com">SoftMap</a></b>: Supported 
-initial development of OGR as well as the OGR MapInfo integration. 
+<li> <b><a href="http://www.softmaptech.com">SoftMap</a></b>: Supported
+initial development of OGR as well as the OGR MapInfo integration.
 <p>
 
 <li> <b><a href="http://www.extendthereach.com/">SRC</a></b>: Supported
@@ -160,19 +160,19 @@ of GDAL.
 <p>
 
 <li> <b><a href="http://www.safe.com/">Safe Software</a></b>: Supported
-development of the OGR OLE DB provider, TIGER/Line driver, S-57 driver, 
+development of the OGR OLE DB provider, TIGER/Line driver, S-57 driver,
 DTED driver, FMEObjects driver, SDTS driver and NTF driver.  Has been a
 Silver sponsor of GDAL.
 <p>
 
 <li> <b><a href="http://www.environmentyukon.gov.yk.ca/">
-Yukon Department of the Environment</a></b>: Supported development of 
+Yukon Department of the Environment</a></b>: Supported development of
 CDED / USGS DEM Writer.
 <p>
 
 <li> <b><a href="http://www.waypointinfo.com/">Waypoint</a></b>:
-Panorama(TM) mapping platform delivers powerful on-line mapping 
-services for business and government organizations, including spatial 
+Panorama(TM) mapping platform delivers powerful on-line mapping
+services for business and government organizations, including spatial
 analysis, mobile asset tracking, web publishing, and Web Mapping Services. Has
 been a Silver sponsor of GDAL.
 </td></tr>
@@ -181,7 +181,7 @@ been a Silver sponsor of GDAL.
 
 \htmlonly
 <p>
-$Id: credits.dox 33134 2016-01-23 23:10:03Z rouault $
+$Id: credits.dox 35221 2016-08-27 23:28:41Z goatbar $
 </p>
 \endhtmlonly
 
diff --git a/doc/download.dox b/doc/download.dox
index f7cc59a..c267d63 100644
--- a/doc/download.dox
+++ b/doc/download.dox
@@ -1,10 +1,10 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: download.dox 33134 2016-01-23 23:10:03Z rouault $ */
+/* $Id: download.dox 35221 2016-08-27 23:28:41Z goatbar $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
 \page download GDAL Downloads
 
 This page has been moved to the Wiki with a topic on downloading <a href="http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries">binaries (pre-built executables</a> and a topic on downloading <a href="http://trac.osgeo.org/gdal/wiki/DownloadSource">source</a>.
- 
+
 */
diff --git a/doc/examples.dox b/doc/examples.dox
index 74c3a03..c00f4c1 100644
--- a/doc/examples.dox
+++ b/doc/examples.dox
@@ -1,11 +1,11 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: examples.dox 8730 2005-10-27 15:12:49Z dron $ */
+/* $Id: examples.dox 34931 2016-08-05 17:13:05Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
-\page gdalinfo.c Simple C Example: gdalinfo.c
+\page gdalinfo_lib.cpp Simple C Example: gdalinfo_lib.cpp
 
-\include gdalinfo.c
+\include gdalinfo_lib.cpp
 */
 
 /*!
@@ -19,10 +19,3 @@
 
 \include jdemdataset.cpp
 */
-
-/*!
-\page NEWS NEWS
-
-\include NEWS
-*/
-
diff --git a/doc/gdal_datamodel.dox b/doc/gdal_datamodel.dox
index 073e207..e07ef73 100644
--- a/doc/gdal_datamodel.dox
+++ b/doc/gdal_datamodel.dox
@@ -1,24 +1,24 @@
-/* $Id: gdal_datamodel.dox 33134 2016-01-23 23:10:03Z rouault $ */
+/* $Id: gdal_datamodel.dox 36955 2016-12-19 12:34:05Z rouault $ */
 
 /*!
 \page gdal_datamodel GDAL Data Model
 
 This document attempts to describe the GDAL data model.  That is the
-types of information that a GDAL data store can contain, and their 
+types of information that a GDAL data store can contain, and their
 semantics.<p>
 
 \section gdal_datamodel_dataset Dataset
 
-A dataset (represented by the GDALDataset class) is an assembly of 
+A dataset (represented by the GDALDataset class) is an assembly of
 related raster bands and some information common to them all.  In particular
 the dataset has a concept of the raster size (in pixels and lines) that
-applies to all the bands.  The dataset is also responsible for the 
+applies to all the bands.  The dataset is also responsible for the
 georeferencing transform and coordinate system definition of all bands.  The
 dataset itself can also have associated metadata, a list of name/value
-pairs in string form. 
+pairs in string form.
 
-Note that the GDAL dataset, and raster band data model is loosely 
-based on the OpenGIS Grid Coverages specification. 
+Note that the GDAL dataset, and raster band data model is loosely
+based on the OpenGIS Grid Coverages specification.
 
 \subsection gdal_datamodel_dataset_cs Coordinate System
 
@@ -26,41 +26,41 @@ Dataset coordinate systems are represented as OpenGIS Well Known Text
 strings.  This can contain:
 
 <ul>
-<li> An overall coordinate system name. 
-<li> A geographic coordinate system name. 
-<li> A datum identifier. 
-<li> An ellipsoid name, semi-major axis, and inverse flattening. 
-<li> A prime meridian name and offset from Greenwich. 
-<li> A projection method type (i.e. Transverse Mercator). 
-<li> A list of projection parameters (i.e. central_meridian). 
-<li> A units name, and conversion factor to meters or radians. 
-<li> Names and ordering for the axes. 
+<li> An overall coordinate system name.
+<li> A geographic coordinate system name.
+<li> A datum identifier.
+<li> An ellipsoid name, semi-major axis, and inverse flattening.
+<li> A prime meridian name and offset from Greenwich.
+<li> A projection method type (i.e. Transverse Mercator).
+<li> A list of projection parameters (i.e. central_meridian).
+<li> A units name, and conversion factor to meters or radians.
+<li> Names and ordering for the axes.
 <li> Codes for most of the above in terms of predefined coordinate systems
-from authorities such as EPSG. 
+from authorities such as EPSG.
 </ul>
 
-For more information on OpenGIS WKT coordinate system definitions, and 
+For more information on OpenGIS WKT coordinate system definitions, and
 mechanisms to manipulate them, refer to the <a href="ogr/osr_tutorial.html">
 osr_tutorial</a> document and/or the OGRSpatialReference class documentation.
 
-The coordinate system returned by GDALDataset::GetProjectionRef() 
+The coordinate system returned by GDALDataset::GetProjectionRef()
 describes the georeferenced coordinates implied by the affine georeferencing
 transform returned by GDALDataset::GetGeoTransform().  The coordinate
-system returned by GDALDataset::GetGCPProjection() describes the 
+system returned by GDALDataset::GetGCPProjection() describes the
 georeferenced coordinates of the GCPs returned by GDALDataset::GetGCPs().
 
 Note that a returned coordinate system strings of "" indicates nothing
-is known about the georeferencing coordinate system.  
+is known about the georeferencing coordinate system.
 
 \subsection gdal_datamodel_dataset_gtm Affine GeoTransform
 
 GDAL datasets have two ways of describing the relationship between
 raster positions (in pixel/line coordinates) and georeferenced coordinates.
 The first, and most commonly used is the affine transform (the other is
-GCPs).  
+GCPs).
 
-The affine transform consists of six coefficients returned by 
-GDALDataset::GetGeoTransform() which map pixel/line coordinates into 
+The affine transform consists of six coefficients returned by
+GDALDataset::GetGeoTransform() which map pixel/line coordinates into
 georeferenced space using the following relationship:
 
 <pre>
@@ -75,7 +75,7 @@ position is the top left corner of the top left pixel of the raster.
 Note that the pixel/line coordinates in the above are from (0.0,0.0) at the
 top left corner of the top left pixel to (width_in_pixels,height_in_pixels)
 at the bottom right corner of the bottom right pixel.  The pixel/line location
-of the center of the top left pixel would therefore be (0.5,0.5). 
+of the center of the top left pixel would therefore be (0.5,0.5).
 
 \subsection gdal_datamodel_dataset_gcp GCPs
 
@@ -87,7 +87,7 @@ coordinate system (returned by GDALDataset::GetGCPProjection()).  Each GCP
 <pre>
 typedef struct
 {
-    char	*pszId; 
+    char	*pszId;
     char	*pszInfo;
     double 	dfGCPPixel;
     double	dfGCPLine;
@@ -100,31 +100,31 @@ typedef struct
 The pszId string is intended to be a unique (and often, but not always
 numerical) identifier for the GCP within the set of GCPs on this dataset.
 The pszInfo is usually an empty string, but can contain any user defined
-text associated with the GCP.  Potentially this can also contain machine 
+text associated with the GCP.  Potentially this can also contain machine
 parsable information on GCP status though that isn't done at this time.
 
 The (Pixel,Line) position is the GCP location on the raster.  The (X,Y,Z)
 position is the associated georeferenced location with the Z often being
-zero. 
+zero.
 
 The GDAL data model does not imply a transformation mechanism that must
 be generated from the GCPs ... this is left to the application.  However
-1st to 5th order polynomials are common. 
+1st to 5th order polynomials are common.
 
 Normally a dataset will contain either an affine geotransform, GCPs or
-neither.  It is uncommon to have both, and it is undefined which is 
+neither.  It is uncommon to have both, and it is undefined which is
 authoritative.
 
 \subsection gdal_datamodel_dataset_metadata Metadata
 
 GDAL metadata is auxiliary format and application specific textual data
-kept as a list of name/value pairs.  The names are required to be well 
+kept as a list of name/value pairs.  The names are required to be well
 behaved tokens (no spaces, or odd characters).  The values can be of
-any length, and contain anything except an embedded null (ASCII zero).  
+any length, and contain anything except an embedded null (ASCII zero).
 
 The metadata handling system is not well tuned to handling very large bodies
 of metadata.  Handling of more than 100K of metadata for a dataset is likely
-to lead to performance degradation. 
+to lead to performance degradation.
 
 Some formats will support generic (user defined) metadata, while other
 format drivers will map specific format fields to metadata names.  For
@@ -136,7 +136,7 @@ TIFFTAG_DATETIME=1999:05:11 11:29:56
 </pre>
 
 Metadata is split into named groups called domains, with the default
-domain having no name (NULL or "").  Some specific domains exist for 
+domain having no name (NULL or "").  Some specific domains exist for
 special purposes.  Note that currently there is no way to enumerate all
 the domains available for a given object, but applications can "test" for
 any domains they know how to interpret.
@@ -145,17 +145,17 @@ The following metadata items have well defined semantics in the default
 domain:
 
 <ul>
-<li> AREA_OR_POINT: May be either "Area" (the default) or "Point".  Indicates 
-whether a pixel value should be assumed to represent a sampling over the 
-region of the pixel or a point sample at the center of the pixel.  This is not 
-intended to influence interpretation of georeferencing which remains area 
+<li> AREA_OR_POINT: May be either "Area" (the default) or "Point".  Indicates
+whether a pixel value should be assumed to represent a sampling over the
+region of the pixel or a point sample at the center of the pixel.  This is not
+intended to influence interpretation of georeferencing which remains area
 oriented.
 <li> NODATA_VALUES: The value is a list of space separated pixel values matching
 the number of bands in the dataset that can be collectively used to identify
 pixels that are nodata in the dataset.  With this style of nodata a pixel
-is considered nodata in all bands if and only if all bands match the 
+is considered nodata in all bands if and only if all bands match the
 corresponding value in the NODATA_VALUES tuple.  This metadata is not widely
-honoured by GDAL drivers, algorithms or utilities at this time. 
+honoured by GDAL drivers, algorithms or utilities at this time.
 <li> MATRIX_REPRESENTATION: This value, used for Polarimetric SAR datasets, contains the matrix representation that this data is provided in. The following are acceptable values:
     <ul>
     <li>SCATTERING
@@ -183,7 +183,7 @@ honoured by GDAL drivers, algorithms or utilities at this time.
 
 The SUBDATASETS domain holds a list of child datasets.  Normally this is
 used to provide pointers to a list of images stored within a single multi
-image file. 
+image file.
 
 For example, an NITF with two images might have the following subdataset list.
 
@@ -194,34 +194,34 @@ For example, an NITF with two images might have the following subdataset list.
   SUBDATASET_2_DESC=Image 2 of multi_1b.ntf
 </pre>
 
-The value of the _NAME is the string that can be passed to GDALOpen() to 
+The value of the _NAME is the string that can be passed to GDALOpen() to
 access the file.  The _DESC value is intended to be a more user friendly
-string that can be displayed to the user in a selector. 
+string that can be displayed to the user in a selector.
 
-Drivers which support subdatasets advertize the DMD_SUBDATASETS capability. 
-This information is reported when the \-\-format and \-\-formats options are 
+Drivers which support subdatasets advertize the DMD_SUBDATASETS capability.
+This information is reported when the \-\-format and \-\-formats options are
 passed to the command line utilities.
 
-Currently, drivers which support subdatasets are: 
-ADRG, ECRGTOC, GEORASTER, GTiff, HDF4, HDF5, netCDF, NITF, NTv2, OGDI, PDF, 
+Currently, drivers which support subdatasets are:
+ADRG, ECRGTOC, GEORASTER, GTiff, HDF4, HDF5, netCDF, NITF, NTv2, OGDI, PDF,
 PostGISRaster, Rasterlite, RPFTOC, RS2, WCS, and WMS.
- 
+
 \subsubsection gdal_datamodel_image_structure IMAGE_STRUCTURE Domain
 
-Metadata in the default domain is intended to be related to the 
+Metadata in the default domain is intended to be related to the
 image, and not particularly related to the way the image is stored on
 disk.  That is, it is suitable for copying with the dataset when it is
 copied to a new format.  Some information of interest is closely tied
 to a particular file format and storage mechanism.  In order to prevent
 this getting copied along with datasets it is placed in a special domain
-called IMAGE_STRUCTURE that should not normally be copied to new formats. 
+called IMAGE_STRUCTURE that should not normally be copied to new formats.
 
-Currently the following items are defined by 
-<a href="http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure">RFC 14</a> 
-as having specific semantics in the IMAGE_STRUCTURE domain. 
+Currently the following items are defined by
+<a href="http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure">RFC 14</a>
+as having specific semantics in the IMAGE_STRUCTURE domain.
 
 <ul>
-<li> COMPRESSION:     The compression type used for this dataset or band. There is no fixed catalog of compression type names, but where a given format includes a COMPRESSION creation option, the same list of values should be used here as there. 
+<li> COMPRESSION:     The compression type used for this dataset or band. There is no fixed catalog of compression type names, but where a given format includes a COMPRESSION creation option, the same list of values should be used here as there.
 <li> NBITS: The actual number of bits used for this band, or the bands of this dataset. Normally only present when the number of bits is non-standard for the datatype, such as when a 1 bit TIFF is represented through GDAL as GDT_Byte.
 <li> INTERLEAVE: This only applies on datasets, and the value should be one of PIXEL, LINE or BAND. It can be used as a data access hint.
 <li> PIXELTYPE: This may appear on a GDT_Byte band (or the corresponding dataset) and have the value SIGNEDBYTE to indicate the unsigned byte values between 128 and 255 should be interpreted as being values between -128 and -1 for applications that recognise the SIGNEDBYTE type.
@@ -260,69 +260,69 @@ The line and pixel offset expressed with LINE_OFF and SAMP_OFF are with respect
 \subsubsection gdal_datamodel_imagery IMAGERY Domain (remote sensing)
 
 For satellite or aerial imagery the IMAGERY Domain may be present. It depends on exist special metadata files near the image file. The files at the same directory with image file tested by the set of metadata readers, if files can be processed by the metadata reader, it fill the IMAGERY Domain with the following items:
-   
+
 <ul>
 <li>  SATELLITEID: A satellite or scanner name
 <li>  CLOUDCOVER: Cloud coverage. The value between 0 - 100 or 999 if not available
 <li>  ACQUISITIONDATETIME: The image acquisition date time in UTC
-</ul>  
+</ul>
 
 
 \subsubsection gdal_datamodel_xml xml: Domains
 
-Any domain name prefixed with "xml:" is not normal name/value metadata. 
-It is a single XML document stored in one big string. 
+Any domain name prefixed with "xml:" is not normal name/value metadata.
+It is a single XML document stored in one big string.
 
 
 \section gdal_datamodel_rasterband Raster Band
 
-A raster band is represented in GDAL with the GDALRasterBand class.  It 
+A raster band is represented in GDAL with the GDALRasterBand class.  It
 represents a single raster band/channel/layer.  It does not necessarily
 represent a whole image.  For instance, a 24bit RGB image would normally
 be represented as a dataset with three bands, one for red, one for green
-and one for blue. 
+and one for blue.
 
 A raster band has the following properties:
 
 <ul>
 
-<li> A width and height in pixels and lines.  This is the same as that 
-defined for the dataset, if this is a full resolution band. 
+<li> A width and height in pixels and lines.  This is the same as that
+defined for the dataset, if this is a full resolution band.
 
-<li> A datatype (GDALDataType).  One of Byte, UInt16, Int16, UInt32, Int32, 
+<li> A datatype (GDALDataType).  One of Byte, UInt16, Int16, UInt32, Int32,
 Float32, Float64, and the complex types CInt16, CInt32, CFloat32, and CFloat64.
 
-<li> A block size.  This is a preferred (efficient) access chunk size.  For 
-tiled images this will be one tile.  For scanline oriented images this will 
-normally be one scanline. 
+<li> A block size.  This is a preferred (efficient) access chunk size.  For
+tiled images this will be one tile.  For scanline oriented images this will
+normally be one scanline.
 
 <li> A list of name/value pair metadata in the same format as the dataset,
 but of information that is potentially specific to this band.
 
-<li> An optional description string. 
+<li> An optional description string.
 
-<li> An optional single nodata pixel value (see also NODATA_VALUES metadata on 
+<li> An optional single nodata pixel value (see also NODATA_VALUES metadata on
 the dataset for multi-band style nodata values).
 
-<li> An optional nodata mask band marking pixels as nodata or in some cases 
-transparency as discussed in <a 
-href="http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask">RFC 15: Band 
-Masks</a>.
+<li> An optional nodata mask band marking pixels as nodata or in some cases
+transparency as discussed in <a
+href="http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask">RFC 15: Band
+Masks</a> and documented in \ref GDALRasterBand::GetMaskBand().
 
-<li> An optional list of category names (effectively class names in a 
-thematic image).  
+<li> An optional list of category names (effectively class names in a
+thematic image).
 
-<li> An optional minimum and maximum value. 
+<li> An optional minimum and maximum value.
 
 <li> An optional offset and scale for transforming raster values into meaning
 full values (i.e. translate height to meters).
 
-<li> An optional raster unit name.  For instance, this might indicate linear 
+<li> An optional raster unit name.  For instance, this might indicate linear
 units for elevation data.
 
 <li> A color interpretation for the band.  This is one of:
 
-  <ul> 
+  <ul>
   <li> GCI_Undefined: the default, nothing is known.
   <li> GCI_GrayIndex: this is an independent gray-scale image
   <li> GCI_PaletteIndex: this raster acts as an index into a color table
@@ -336,12 +336,12 @@ units for elevation data.
   <li> GCI_CyanBand: this band is the cyan portion of a CMY or CMYK image
   <li> GCI_MagentaBand: this band is the magenta portion of a CMY or CMYK image
   <li> GCI_YellowBand: this band is the yellow portion of a CMY or CMYK image
-  <li> GCI_BlackBand: this band is the black portion of a CMYK image. 
+  <li> GCI_BlackBand: this band is the black portion of a CMYK image.
   </ul>
 
-<li> A color table, described in more detail later. 
+<li> A color table, described in more detail later.
 
-<li> Knowledge of reduced resolution overviews (pyramids) if available. 
+<li> Knowledge of reduced resolution overviews (pyramids) if available.
 
 </ul>
 
@@ -354,49 +354,49 @@ following structure:
 typedef struct
 {
     /- gray, red, cyan or hue -/
-    short      c1;      
+    short      c1;
 
-    /- green, magenta, or lightness -/    
-    short      c2;      
+    /- green, magenta, or lightness -/
+    short      c2;
 
     /- blue, yellow, or saturation -/
-    short      c3;      
+    short      c3;
 
     /- alpha or black band -/
-    short      c4;      
+    short      c4;
 } GDALColorEntry;
 </pre>
 
 The color table also has a palette interpretation value (GDALPaletteInterp)
 which is one of the following values, and indicates how the c1/c2/c3/c4 values
-of a color entry should be interpreted. 
+of a color entry should be interpreted.
 
 <ul>
-<li> GPI_Gray: Use c1 as gray scale value. 
+<li> GPI_Gray: Use c1 as gray scale value.
 <li> GPI_RGB: Use c1 as red, c2 as green, c3 as blue and c4 as alpha.
-<li> GPI_CMYK: Use c1 as cyan, c2 as magenta, c3 as yellow and c4 as black. 
-<li> GPI_HLS: Use c1 as hue, c2 as lightness, and c3 as saturation. 
+<li> GPI_CMYK: Use c1 as cyan, c2 as magenta, c3 as yellow and c4 as black.
+<li> GPI_HLS: Use c1 as hue, c2 as lightness, and c3 as saturation.
 </ul>
 
 To associate a color with a raster pixel, the pixel value is used as a
 subscript into the color table.  That means that the colors are always
 applied starting at zero and ascending.  There is no provision for indicating
-a pre-scaling mechanism before looking up in the color table. 
+a pre-scaling mechanism before looking up in the color table.
 
 \section gdal_datamodel_rasterband_overviews Overviews
 
 A band may have zero or more overviews.  Each overview is represented as
-a "free standing" GDALRasterBand.  The size (in pixels and lines) of the 
+a "free standing" GDALRasterBand.  The size (in pixels and lines) of the
 overview will be different than the underlying raster, but the geographic
-region covered by overviews is the same as the full resolution band.  
+region covered by overviews is the same as the full resolution band.
 
 The overviews are used to display reduced resolution overviews more quickly
-than could be done by reading all the full resolution data and downsampling. 
+than could be done by reading all the full resolution data and downsampling.
 
 Bands also have a HasArbitraryOverviews property which is TRUE if the
 raster can be read at any resolution efficiently but with no distinct
 overview levels.  This applies to some FFT encoded images, or images pulled
 through gateways (like OGDI) where downsampling can be done efficiently
-at the remote point. 
+at the remote point.
 
 */
diff --git a/doc/gdal_drivertut.dox b/doc/gdal_drivertut.dox
index 1611b1b..e253d8c 100644
--- a/doc/gdal_drivertut.dox
+++ b/doc/gdal_drivertut.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_drivertut.dox 33134 2016-01-23 23:10:03Z rouault $ */
+/* $Id: gdal_drivertut.dox 37555 2017-03-02 13:02:20Z goatbar $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -9,13 +9,13 @@
 
 In general new formats are added to GDAL by implementing format specific
 drivers as subclasses of GDALDataset, and band accessors as subclasses
-of GDALRasterBand.  As well, a GDALDriver instance is created for the 
+of GDALRasterBand.  As well, a GDALDriver instance is created for the
 format, and registered with the GDALDriverManager, to ensure that the system
 <i>knows</i> about the format.
 
 This tutorial will start with implementing a simple read-only driver
 (based on the JDEM driver), and then proceed to utilizing the RawRasterBand
-helper class, implementing creatable and updatable formats, and some 
+helper class, implementing creatable and updatable formats, and some
 esoteric issues.
 
 It is strongly advised that the <a href="gdal_datamodel.html">GDAL Data Model
@@ -39,7 +39,7 @@ GDAL driver.
 \section gdal_drivertut_dataset Implementing the Dataset
 
 We will start showing minimal implementation of a read-only driver for
-the Japanese DEM format (<a href="jdemdataset.cpp.html">jdemdataset.cpp</a>).  
+the Japanese DEM format (<a href="jdemdataset.cpp.html">jdemdataset.cpp</a>).
 First we declare a format
 specific dataset class, JDEMDataset in this case.
 
@@ -48,16 +48,16 @@ class JDEMDataset : public GDALPamDataset
 {
     friend class JDEMRasterBand;
 
-    FILE	*fp;
-    GByte	abyHeader[1012];
+    FILE        *fp;
+    GByte       abyHeader[1012];
 
   public:
-		~JDEMDataset();
-    
+                ~JDEMDataset();
+
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
 
-    CPLErr 	GetGeoTransform( double * padfTransform );
+    CPLErr      GetGeoTransform( double * padfTransform );
     const char *GetProjectionRef();
 };
 \endcode
@@ -65,93 +65,80 @@ class JDEMDataset : public GDALPamDataset
 In general we provide capabilities for a driver, by overriding the various
 virtual methods on the GDALDataset base class.  However, the Open() method
 is special.  This is not a virtual method on the base class, and we will
-need a freestanding function for this operation, so we declare it static. 
+need a freestanding function for this operation, so we declare it static.
 Implementing it as a method in the JDEMDataset class is convenient because
-we have privileged access to modify the contents of the database object. 
+we have privileged access to modify the contents of the database object.
 
 The open method itself may look something like this:
 
-\verbatim
-GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
+\code
+GDALDataset *JDEMDataset::Open( GDALOpenInfo *poOpenInfo )
 
 {
-// -------------------------------------------------------------------- //
-//      Confirm that the header is compatible with a JDEM dataset.      //
-// -------------------------------------------------------------------- //
-    if (!Identify(poOpenInfo))
+    // Confirm that the header is compatible with a JDEM dataset.
+    if( !Identify(poOpenInfo) )
         return NULL;
-    
-// -------------------------------------------------------------------- //
-//      Confirm the requested access is supported.                      //
-// -------------------------------------------------------------------- //
+
+    // Confirm the requested access is supported.
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "The JDEM driver does not support update access to existing"
-                  " datasets.\n" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The JDEM driver does not support update access to existing "
+                 "datasets.");
         return NULL;
     }
 
-    /* Check that the file pointer from GDALOpenInfo* is available */
+    // Check that the file pointer from GDALOpenInfo* is available
     if( poOpenInfo->fpL == NULL )
     {
         return NULL;
     }
-// -------------------------------------------------------------------- //
-//      Create a corresponding GDALDataset.                             //
-// -------------------------------------------------------------------- //
-    JDEMDataset 	*poDS;
 
-    poDS = new JDEMDataset();
+    // Create a corresponding GDALDataset.
+    JDEMDataset *poDS = new JDEMDataset();
 
-    /* Borrow the file pointer from GDALOpenInfo* */
+    // Borrow the file pointer from GDALOpenInfo*.
     poDS->fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
-    
-// -------------------------------------------------------------------- //
-//      Read the header.                                                //
-// -------------------------------------------------------------------- //
-    VSIFReadL( poDS->abyHeader, 1, 1012, poDS->fp );
-
-    poDS->nRasterXSize = JDEMGetField( (char *) poDS->abyHeader + 23, 3 );
-    poDS->nRasterYSize = JDEMGetField( (char *) poDS->abyHeader + 26, 3 );
-    if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
+
+    // Read the header.
+    VSIFReadL(poDS->abyHeader, 1, 1012, poDS->fp);
+
+    poDS->nRasterXSize =
+        JDEMGetField(reinterpret_cast<char *>(poDS->abyHeader) + 23, 3);
+    poDS->nRasterYSize =
+        JDEMGetField(reinterpret_cast<char *>(poDS->abyHeader) + 26, 3);
+    if( poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Invalid dimensions : %d x %d", 
-                  poDS->nRasterXSize, poDS->nRasterYSize); 
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid dimensions : %d x %d",
+                 poDS->nRasterXSize, poDS->nRasterYSize);
         delete poDS;
         return NULL;
     }
 
-// -------------------------------------------------------------------- //
-//      Create band information objects.                                //
-// -------------------------------------------------------------------- //
-    poDS->SetBand( 1, new JDEMRasterBand( poDS, 1 ));
+    // Create band information objects.
+    poDS->SetBand(1, new JDEMRasterBand(poDS, 1));
 
-// -------------------------------------------------------------------- //
-//      Initialize any PAM information.                                 //
-// -------------------------------------------------------------------- //
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    // Initialize any PAM information.
+    poDS->SetDescription(poOpenInfo->pszFilename);
     poDS->TryLoadXML();
 
-// -------------------------------------------------------------------- //
-//      Initialize default overviews.                                   //
-// -------------------------------------------------------------------- //
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
-    return( poDS );
+    // Initialize default overviews.
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
+    return poDS;
 }
-\endverbatim
+\code
 
 The first step in any database Open function is to verify that the file
 being passed is in fact of the type this driver is for.  It is important
 to realize that each driver's Open function is called in turn till one
 succeeds.  Drivers must quietly return NULL if the passed file is not of
 their format.  They should only produce an error if the file does appear to
-be of their supported format, but is for some reason unsupported or corrupt. 
+be of their supported format, but is for some reason unsupported or corrupt.
 
 The information on the file to be opened is passed in contained in a
-GDALOpenInfo object.  The GDALOpenInfo includes the following public 
+GDALOpenInfo object.  The GDALOpenInfo includes the following public
 data members:
 
 \code
@@ -171,8 +158,8 @@ data members:
 \endcode
 
 The driver can inspect these to establish if the file is supported.  If the
-pszFilename refers to an object in the file system, the <b>bStatOK</b> flag 
-will be set to TRUE.  As well, if the file was successfully opened, the first 
+pszFilename refers to an object in the file system, the <b>bStatOK</b> flag
+will be set to TRUE.  As well, if the file was successfully opened, the first
 kilobyte or so is read in, and put in <b>pabyHeader</b>, with the exact size in
 <b>nHeaderBytes</b>.
 
@@ -182,11 +169,11 @@ and that various parts of the header are as expected for this format.  In
 this case, there are no <i>magic</i> numbers for JDEM format so we check
 various date fields to ensure they have reasonable century values.  If the
 test fails, we quietly return NULL indicating this file isn't of our supported
-format. 
+format.
 
 The identification is in fact delegated to a Identify() static function :
 
-\verbatim
+\code
 /************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
@@ -194,27 +181,26 @@ The identification is in fact delegated to a Identify() static function :
 int JDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Confirm that the header has what appears to be dates in the     */
-/*      expected locations.  Sadly this is a relatively weak test.      */
-/* -------------------------------------------------------------------- */
+    // Confirm that the header has what appears to be dates in the
+    // expected locations.  Sadly this is a relatively weak test.
     if( poOpenInfo->nHeaderBytes < 50 )
         return FALSE;
 
-    /* check if century values seem reasonable */
-    if( (!EQUALN((char *)poOpenInfo->pabyHeader+11,"19",2)
-          && !EQUALN((char *)poOpenInfo->pabyHeader+11,"20",2))
-        || (!EQUALN((char *)poOpenInfo->pabyHeader+15,"19",2)
-             && !EQUALN((char *)poOpenInfo->pabyHeader+15,"20",2))
-        || (!EQUALN((char *)poOpenInfo->pabyHeader+19,"19",2)
-             && !EQUALN((char *)poOpenInfo->pabyHeader+19,"20",2)) )
+    // Check if century values seem reasonable.
+    const char *psHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
+    if( (!EQUALN(psHeader + 11, "19", 2) &&
+         !EQUALN(psHeader + 11, "20", 2)) ||
+        (!EQUALN(psHeader + 15, "19", 2) &&
+         !EQUALN(psHeader + 15, "20", 2)) ||
+        (!EQUALN(psHeader + 19, "19", 2) &&
+         !EQUALN(psHeader + 19, "20", 2)) )
     {
         return FALSE;
     }
 
     return TRUE;
 }
-\endverbatim
+\code
 
 It is important to make the <i>is this my format</i> test as stringent as
 possible.  In this particular case the test is weak, and a file that happened
@@ -223,92 +209,89 @@ JDEM format, causing it to not be handled properly.
 
 Once we are satisfied that the file is of our format, we can do any other
 tests that are necessary to validate the file is usable, and in particular
-that we can provide the level of access desired.  Since the JDEM driver 
+that we can provide the level of access desired.  Since the JDEM driver does
+not provide update support, error out in that case.
 
 \code
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "The JDEM driver does not support update access to existing"
-                  " datasets.\n" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The JDEM driver does not support update access to existing "
+                 "datasets.");
         return NULL;
     }
 \endcode
 
-Next we need to create an instance of the database class in which we will 
+Next we need to create an instance of the database class in which we will
 set various information of interest.
 
 \code
-    /* Check that the file pointer from GDALOpenInfo* is available */
+    // Check that the file pointer from GDALOpenInfo* is available.
     if( poOpenInfo->fpL == NULL )
     {
         return NULL;
     }
 
-    JDEMDataset 	*poDS;
-
-    poDS = new JDEMDataset();
+    JDEMDataset *poDS = new JDEMDataset();
 
-    /* Borrow the file pointer from GDALOpenInfo* */
+    // Borrow the file pointer from GDALOpenInfo*.
     poDS->fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
 \endcode
 
 At this point we "borrow" the file handle that was held by GDALOpenInfo*.
 This file pointer uses the VSI*L GDAL API to
-access files on disk.  This virtualized POSIX-style API allows some 
-special capabilities like supporting large files, in-memory files 
-and zipped files. 
+access files on disk.  This virtualized POSIX-style API allows some
+special capabilities like supporting large files, in-memory files
+and zipped files.
 
 Next the X and Y size are extracted from the header. The nRasterXSize and
 nRasterYSize are data fields inherited from the GDALDataset base class, and
 must be set by the Open() method.
 
 \code
-    VSIFReadL( poDS->abyHeader, 1, 1012, poDS->fp );
+    VSIFReadL(poDS->abyHeader, 1, 1012, poDS->fp);
 
-    poDS->nRasterXSize = JDEMGetField( (char *) poDS->abyHeader + 23, 3 );
-    poDS->nRasterYSize = JDEMGetField( (char *) poDS->abyHeader + 26, 3 );
+    poDS->nRasterXSize =
+        JDEMGetField(reinterpret_cast<char *>(poDS->abyHeader) + 23, 3);
+    poDS->nRasterYSize =
+        JDEMGetField(reinterpret_cast<char *>(poDS->abyHeader) + 26, 3);
 
     if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Invalid dimensions : %d x %d", 
-                  poDS->nRasterXSize, poDS->nRasterYSize); 
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid dimensions : %d x %d",
+                 poDS->nRasterXSize, poDS->nRasterYSize);
         delete poDS;
         return NULL;
     }
 \endcode
 
 All the bands related to this dataset must be created and attached using
-the SetBand() method.  We will explore the JDEMRasterBand() class shortly. 
+the SetBand() method.  We will explore the JDEMRasterBand() class shortly.
 
 \code
-// -------------------------------------------------------------------- //
-//      Create band information objects.                                //
-// -------------------------------------------------------------------- //
-    poDS->SetBand( 1, new JDEMRasterBand( poDS, 1 ));
+    // Create band information objects.
+    poDS->SetBand(1, new JDEMRasterBand(poDS, 1));
 \endcode
 
 Finally we assign a name to the dataset object, and call the GDALPamDataset
-TryLoadXML() method which can initialize auxiliary information from an 
+TryLoadXML() method which can initialize auxiliary information from an
 .aux.xml file if available.  For more details on these services review
 the GDALPamDataset and related classes.
 
 \code
-// -------------------------------------------------------------------- //
-//      Initialize any PAM information.                                 //
-// -------------------------------------------------------------------- //
+    // Initialize any PAM information.
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
-    return( poDS );
+    return poDS;
 }
 \endcode
 
 \section gdal_drivertut_rasterband Implementing the RasterBand
 
-Similar to the customized JDEMDataset class subclassed from GDALDataset, 
+Similar to the customized JDEMDataset class subclassed from GDALDataset,
 we also need to declare and implement a customized JDEMRasterBand derived
 from GDALRasterBand for access to the band(s) of the JDEM file.  For
 JDEMRasterBand the declaration looks like this:
@@ -317,24 +300,24 @@ JDEMRasterBand the declaration looks like this:
 class JDEMRasterBand : public GDALPamRasterBand
 {
   public:
-    		JDEMRasterBand( JDEMDataset *, int );
+    JDEMRasterBand( JDEMDataset *, int );
     virtual CPLErr IReadBlock( int, int, void * );
 };
 \endcode
 
 The constructor may have any signature, and is only called from the Open()
-method.  Other virtual methods, such as IReadBlock() must be exactly 
-matched to the method signature in gdal_priv.h.  
+method.  Other virtual methods, such as IReadBlock() must be exactly
+matched to the method signature in gdal_priv.h.
 
 The constructor implementation looks like this:
 
 \code
-JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDS, int nBand )
+JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
-    
+    poDS = poDSIn;
+    nBand = nBandIn;
+
     eDataType = GDT_Float32;
 
     nBlockXSize = poDS->GetRasterXSize();
@@ -343,62 +326,60 @@ JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDS, int nBand )
 \endcode
 
 The following data members are inherited from GDALRasterBand, and should
-generally be set in the band constructor. 
+generally be set in the band constructor.
 
 <ul>
-<li> <b>poDS</b>: Pointer to the parent GDALDataset. 
-<li> <b>nBand</b>: The band number within the dataset. 
-<li> <b>eDataType</b>: The data type of pixels in this band. 
-<li> <b>nBlockXSize</b>: The width of one block in this band. 
-<li> <b>nBlockYSize</b>: The height of one block in this band. 
+<li> <b>poDS</b>: Pointer to the parent GDALDataset.
+<li> <b>nBand</b>: The band number within the dataset.
+<li> <b>eDataType</b>: The data type of pixels in this band.
+<li> <b>nBlockXSize</b>: The width of one block in this band.
+<li> <b>nBlockYSize</b>: The height of one block in this band.
 </ul>
 
-The full set of possible GDALDataType values are declared in gdal.h, and 
-include GDT_Byte, GDT_UInt16, GDT_Int16, and GDT_Float32.  The block size is 
+The full set of possible GDALDataType values are declared in gdal.h, and
+include GDT_Byte, GDT_UInt16, GDT_Int16, and GDT_Float32.  The block size is
 used to establish a <i>natural</i> or efficient block size to access the data
-with.  For tiled datasets this will be the size of a tile, while for most 
-other datasets it will be one scanline, as in this case. 
+with.  For tiled datasets this will be the size of a tile, while for most
+other datasets it will be one scanline, as in this case.
 
 Next we see the implementation of the code that actually reads the image
-data, IReadBlock(). 
+data, IReadBlock().
 
 \code
 CPLErr JDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    JDEMDataset *poGDS = (JDEMDataset *) poDS;
-    char	*pszRecord;
-    int		nRecordSize = nBlockXSize*5 + 9 + 2;
-    int		i;
+    JDEMDataset *poGDS = static_cast<JDEMDataset *>(poDS);
+    int nRecordSize = nBlockXSize * 5 + 9 + 2;
 
-    VSIFSeekL( poGDS->fp, 1011 + nRecordSize*nBlockYOff, SEEK_SET );
+    VSIFSeekL(poGDS->fp, 1011 + nRecordSize*nBlockYOff, SEEK_SET);
 
-    pszRecord = (char *) CPLMalloc(nRecordSize);
-    VSIFReadL( pszRecord, 1, nRecordSize, poGDS->fp );
+    char *pszRecord = static_cast<char *>(CPLMalloc(nRecordSize));
+    VSIFReadL(pszRecord, 1, nRecordSize, poGDS->fp);
 
-    if( !EQUALN((char *) poGDS->abyHeader,pszRecord,6) )
+    if( !EQUALN(reinterpret_cast<char *>(poGDS->abyHeader), pszRecord, 6) )
     {
-        CPLFree( pszRecord );
+        CPLFree(pszRecord);
 
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "JDEM Scanline corrupt.  Perhaps file was not transferred\n"
-                  "in binary mode?" );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "JDEM Scanline corrupt.  Perhaps file was not transferred "
+                 "in binary mode?");
         return CE_Failure;
     }
-    
-    if( JDEMGetField( pszRecord + 6, 3 ) != nBlockYOff + 1 )
+
+    if( JDEMGetField(pszRecord + 6, 3) != nBlockYOff + 1 )
     {
-        CPLFree( pszRecord );
+        CPLFree(pszRecord);
 
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "JDEM scanline out of order, JDEM driver does not\n"
-                  "currently support partial datasets." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "JDEM scanline out of order, JDEM driver does not "
+                 "currently support partial datasets.");
         return CE_Failure;
     }
 
-    for( i = 0; i < nBlockXSize; i++ )
-        ((float *) pImage)[i] = JDEMGetField( pszRecord + 9 + 5 * i, 5) * 0.1;
+    for( int i = 0; i < nBlockXSize; i++ )
+        ((float *) pImage)[i] = JDEMGetField(pszRecord + 9 + 5 * i, 5) * 0.1;
 
     return CE_None;
 }
@@ -407,21 +388,21 @@ CPLErr JDEMRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 Key items to note are:
 
 <ul>
-<li> It is typical to cast the GDALRasterBand::poDS member to the derived 
+<li> It is typical to cast the GDALRasterBand::poDS member to the derived
 type of the owning dataset.  If your RasterBand class will need privileged
 access to the owning dataset object, ensure it is declared as a friend (omitted
-above for brevity). 
+above for brevity).
 
-<li> If an error occurs, report it with CPLError(), and return CE_Failure. 
-Otherwise return CE_None.  
+<li> If an error occurs, report it with CPLError(), and return CE_Failure.
+Otherwise return CE_None.
 
 <li> The pImage buffer should be filled with one block of data.  The block
 is the size declared in nBlockXSize and nBlockYSize for the raster band.  The
-type of the data within pImage should match the type declared in 
-eDataType in the raster band object. 
+type of the data within pImage should match the type declared in
+eDataType in the raster band object.
 
-<li> The nBlockXOff and nBlockYOff are block offsets, so with 128x128 tiled 
-datasets values of 1 and 1 would indicate the block going from (128,128) to 
+<li> The nBlockXOff and nBlockYOff are block offsets, so with 128x128 tiled
+datasets values of 1 and 1 would indicate the block going from (128,128) to
 (255,255) should be loaded.
 
 </ul>
@@ -431,41 +412,40 @@ datasets values of 1 and 1 would indicate the block going from (128,128) to
 While the JDEMDataset and JDEMRasterBand are now ready to use to read image
 data, it still isn't clear how the GDAL system knows about the new driver.
 This is accomplished via the GDALDriverManager.  To register our format we
-implement a registration function:
+implement a registration function.  The declaration goes in gcore/gdal_frmts.h:
+
 
 \code
-CPL_C_START
 void CPL_DLL GDALRegister_JDEM(void);
-CPL_C_END
+\endcode
 
-...
+The definition in the driver file is:
 
+\code
 void GDALRegister_JDEM()
 
 {
-    GDALDriver	*poDriver;
+    if( !GDAL_CHECK_VERSION("JDEM") )
+        return;
 
-    if (! GDAL_CHECK_VERSION("JDEM"))
+    if( GDALGetDriverByName("JDEM") != NULL )
         return;
 
-    if( GDALGetDriverByName( "JDEM" ) == NULL )
-    {
-        poDriver = new GDALDriver();
-        
-        poDriver->SetDescription( "JDEM" );
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
-                                   "Japanese DEM (.mem)" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
-                                   "frmt_various.html#JDEM" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mem" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-        poDriver->pfnOpen = JDEMDataset::Open;
-        poDriver->pfnIdentify = JDEMDataset::Identify;
-
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription("JDEM");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
+                              "Japanese DEM (.mem)");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
+                              "frmt_various.html#JDEM");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "mem");
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
+
+    poDriver->pfnOpen = JDEMDataset::Open;
+    poDriver->pfnIdentify = JDEMDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
 \endcode
 
@@ -479,13 +459,13 @@ with which the driver was compiled and the version against which it is running a
 
 The registration function will create an instance of a GDALDriver object
 when first called, and register it with the GDALDriverManager.  The
-following fields can be set in the driver before 
+following fields can be set in the driver before
 registering it with the GDALDriverManager().
 
 <ul>
-<li> The description is the short name for the format.  This is a unique 
-name for this format, often used to identity the driver in scripts and 
-command line programs.  Normally 3-5 characters in length, and matching the 
+<li> The description is the short name for the format.  This is a unique
+name for this format, often used to identity the driver in scripts and
+command line programs.  Normally 3-5 characters in length, and matching the
 prefix of the format classes. (mandatory)
 
 <li> GDAL_DCAP_RASTER: set to YES to indicate that this driver handles
@@ -494,8 +474,8 @@ raster data. (mandatory)
 <li> GDAL_DMD_LONGNAME: A longer descriptive name for the file format,
 but still no longer than 50-60 characters. (mandatory)
 
-<li> GDAL_DMD_HELPTOPIC: The name of a help topic to display for this driver, 
-if any.  In this case JDEM format is contained within the various format 
+<li> GDAL_DMD_HELPTOPIC: The name of a help topic to display for this driver,
+if any.  In this case JDEM format is contained within the various format
 web page held in gdal/html.  (optional)
 
 <li> GDAL_DMD_EXTENSION: The extension used for files of this type.  If more
@@ -521,14 +501,14 @@ example value might be "Byte Int16 UInt16". (required - if creation supported)
 with files opened with the VSI*L GDAL API. Otherwise this metadata item should
 not be defined. (optional)
 
-<li> pfnOpen: The function to call to try opening files of this format. 
-(optional) 
+<li> pfnOpen: The function to call to try opening files of this format.
+(optional)
 
 <li> pfnIdentify: The function to call to try identifying files of this format.
 A driver should return 1 if it recognizes the file as being of its format,
 0 if it recognizes the file as being NOT of its format, or -1 if it cannot
 reach to a firm conclusion by just examining the header bytes.
-(optional) 
+(optional)
 
 <li> pfnCreate: The function to call to create new updatable datasets of this
 format. (optional)
@@ -555,38 +535,38 @@ when writing new drivers is to:
 as the short name.
 
 <li> Add a GNUmakefile and makefile.vc in that directory modeled on those
-from other similar directories (i.e. the jdem directory). 
+from other similar directories (i.e. the jdem directory).
 
-<li> Add the module with the dataset, and rasterband implementation.  
-Generally this is called <short_name>dataset.cpp, with all the GDAL specific
+<li> Add the module with the dataset, and rasterband implementation.
+Generally this is called <short_name>dataset.cpp, with all the GDAL specific
 code in one file, though that is not required.
 
 <li> Add the registration entry point declaration (i.e. GDALRegister_JDEM()) to
 gdal/gcore/gdal_frmts.h.
 
 <li> Add a call to the registration function to frmts/gdalallregister.cpp,
-protected by an appropriate #ifdef.  
+protected by an appropriate \#ifdef.
 
-<li> Add the format short name to the GDAL_FORMATS macro in 
-GDALmake.opt.in (and to GDALmake.opt). 
+<li> Add the format short name to the GDAL_FORMATS macro in
+GDALmake.opt.in (and to GDALmake.opt).
 
-<li> Add a format specific item to the EXTRAFLAGS macro in frmts/makefile.vc. 
+<li> Add a format specific item to the EXTRAFLAGS macro in frmts/makefile.vc.
 </ol>
 
 Once this is all done, it should be possible to rebuild GDAL, and have
 the new format available in all the utilities.  The gdalinfo utility can be
 used to test that opening and reporting on the format is working, and the
-gdal_translate utility can be used to test image reading. 
+gdal_translate utility can be used to test image reading.
 
 \section gdal_drivertut_georef Adding Georeferencing
 
-Now we will take the example a step forward, adding georeferencing support. 
+Now we will take the example a step forward, adding georeferencing support.
 We add the following two virtual method overrides to JDEMDataset, taking
 care to exactly match the signature of the method on the GDALRasterDataset
 base class.
 
 \code
-    CPLErr 	GetGeoTransform( double * padfTransform );
+    CPLErr      GetGeoTransform( double * padfTransform );
     const char *GetProjectionRef();
 \endcode
 
@@ -594,7 +574,7 @@ The implementation of GetGeoTransform() just copies the usual geotransform
 matrix into the supplied buffer.  Note that GetGeoTransform() may be called
 a lot, so it isn't generally wise to do a lot of computation in it.  In many
 cases the Open() will collect the geotransform, and this method will just
-copy it over.  Also note that the geotransform return is based on an 
+copy it over.  Also note that the geotransform return is based on an
 anchor point at the top left corner of the top left pixel, not the center
 of pixel approach used in some packages.
 
@@ -602,18 +582,18 @@ of pixel approach used in some packages.
 CPLErr JDEMDataset::GetGeoTransform( double * padfTransform )
 
 {
-    double	dfLLLat, dfLLLong, dfURLat, dfURLong;
+    const char *psHeader = reinterpret_cast<char *>(abyHeader);
+
+    const double dfLLLat = JDEMGetAngle(psHeader + 29);
+    const double dfLLLong = JDEMGetAngle(psHeader + 36);
+    const double dfURLat = JDEMGetAngle(psHeader + 43);
+    const double dfURLong = JDEMGetAngle(psHeader + 50);
 
-    dfLLLat = JDEMGetAngle( (char *) abyHeader + 29 );
-    dfLLLong = JDEMGetAngle( (char *) abyHeader + 36 );
-    dfURLat = JDEMGetAngle( (char *) abyHeader + 43 );
-    dfURLong = JDEMGetAngle( (char *) abyHeader + 50 );
-    
     padfTransform[0] = dfLLLong;
     padfTransform[3] = dfURLat;
     padfTransform[1] = (dfURLong - dfLLLong) / GetRasterXSize();
     padfTransform[2] = 0.0;
-        
+
     padfTransform[4] = 0.0;
     padfTransform[5] = -1 * (dfURLat - dfLLLat) / GetRasterYSize();
 
@@ -622,7 +602,7 @@ CPLErr JDEMDataset::GetGeoTransform( double * padfTransform )
 }
 \endcode
 
-The GetProjectionRef() method returns a pointer to an internal string 
+The GetProjectionRef() method returns a pointer to an internal string
 containing a coordinate system definition in OGC WKT format.  In this case
 the coordinate system is fixed for all files of this format, but in more
 complex cases a definition may need to be composed on the fly, in which case
@@ -633,46 +613,47 @@ definition.
 const char *JDEMDataset::GetProjectionRef()
 
 {
-    return( "GEOGCS[\"Tokyo\",DATUM[\"Tokyo\",SPHEROID[\"Bessel 1841\","
-	"6377397.155,299.1528128,AUTHORITY[\"EPSG\",7004]],TOWGS84[-148,"
-	"507,685,0,0,0,0],AUTHORITY[\"EPSG\",6301]],PRIMEM[\"Greenwich\","
-	"0,AUTHORITY[\"EPSG\",8901]],UNIT[\"DMSH\",0.0174532925199433,"
-	"AUTHORITY[\"EPSG\",9108]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST],"
-	"AUTHORITY[\"EPSG\",4301]]" );
+    return
+        "GEOGCS[\"Tokyo\",DATUM[\"Tokyo\",SPHEROID[\"Bessel 1841\","
+        "6377397.155,299.1528128,AUTHORITY[\"EPSG\",7004]],TOWGS84[-148,"
+        "507,685,0,0,0,0],AUTHORITY[\"EPSG\",6301]],PRIMEM[\"Greenwich\","
+        "0,AUTHORITY[\"EPSG\",8901]],UNIT[\"DMSH\",0.0174532925199433,"
+        "AUTHORITY[\"EPSG\",9108]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST],"
+        "AUTHORITY[\"EPSG\",4301]]";
 }
 \endcode
 
 This completes explanation of the features of the JDEM driver.  The full
-source for <a href="jdemdataset.cpp.html">jdemdataset.cpp</a> can be reviewed 
+source for <a href="jdemdataset.cpp.html">jdemdataset.cpp</a> can be reviewed
 as needed.
 
 \section gdal_drivertut_overviews Overviews
 
 GDAL allows file formats to make pre-built overviews available to applications
-via the GDALRasterBand::GetOverview() and related methods.  However, 
-implementing this is pretty involved, and goes beyond the scope of this 
+via the GDALRasterBand::GetOverview() and related methods.  However,
+implementing this is pretty involved, and goes beyond the scope of this
 document for now.  The GeoTIFF driver (gdal/frmts/gtiff/geotiff.cpp) and
 related source can be reviewed for an example of a file format implementing
-overview reporting and creation support. 
+overview reporting and creation support.
 
 Formats can also report that they have arbitrary overviews, by overriding
-the HasArbitraryOverviews() method on the GDALRasterBand, returning TRUE. 
+the HasArbitraryOverviews() method on the GDALRasterBand, returning TRUE.
 In this case the raster band object is expected to override the RasterIO()
-method itself, to implement efficient access to imagery with resampling. 
+method itself, to implement efficient access to imagery with resampling.
 This is also involved, and there are a lot of requirements for correct
 implementation of the RasterIO() method.  An example of this can be found
-in the OGDI and ECW formats. 
+in the OGDI and ECW formats.
 
-However, by far the most common approach to implementing overviews is to 
+However, by far the most common approach to implementing overviews is to
 use the default support in GDAL for external overviews stored in TIFF files
-with the same name as the dataset, but the extension .ovr appended.  In 
+with the same name as the dataset, but the extension .ovr appended.  In
 order to enable reading and creation of this style of overviews it is necessary
 for the GDALDataset to initialize the oOvManager object within itself.  This
 is typically accomplished with a call like the following near the end of the
 Open() method (after the PAM TryLoadXML()).
 
 \code
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
 \endcode
 
 This will enable default implementations for reading and creating overviews for
@@ -686,33 +667,33 @@ CreateCopy() method, and involves implementing a function that can write a
 file in the output format, pulling all imagery and other information needed
 from a source GDALDataset.  The second method, the dynamic creation method,
 involves implementing a Create method to create the shell of the file, and
-then the application writes various information by calls to set methods. 
+then the application writes various information by calls to set methods.
 
 The benefits of the first method are that that all the information is available
 at the point the output file is being created.  This can be especially
-important when implementing file formats using external libraries which 
+important when implementing file formats using external libraries which
 require information like color maps, and georeferencing information at the
 point the file is created.  The other advantage of this method is that the
-CreateCopy() method can read some kinds of information, such as min/max, 
+CreateCopy() method can read some kinds of information, such as min/max,
 scaling, description and GCPs for which there are no equivalent set methods.
 
 The benefits of the second method are that applications can create an
 empty new file, and write results to it as they become available.  A complete
-image of the desired data does not have to be available in advance.  
+image of the desired data does not have to be available in advance.
 
-For very important formats both methods may be implemented, otherwise do 
-whichever is simpler, or provides the required capabilities. 
+For very important formats both methods may be implemented, otherwise do
+whichever is simpler, or provides the required capabilities.
 
 \subsection gdal_drivertut_creation_createcopy CreateCopy
 
-The GDALDriver::CreateCopy() method call is passed through directly, so 
-that method should be consulted for details of arguments.  However, some 
+The GDALDriver::CreateCopy() method call is passed through directly, so
+that method should be consulted for details of arguments.  However, some
 things to keep in mind are:
 
 <ul>
 <li> If the bStrict flag is FALSE the driver should try to do something
 reasonable when it cannot exactly represent the source dataset, transforming
-data types on the fly, dropping georeferencing and so forth. 
+data types on the fly, dropping georeferencing and so forth.
 
 <li> Implementing progress reporting correctly is somewhat involved.  The
 return result of the progress function needs always to be checked for
@@ -722,97 +703,88 @@ JPEGCreateCopy() method demonstrates good handling of the progress function.
 <li> Special creation options should be documented in the on-line help.
 If the options take the format "NAME=VALUE" the papszOptions list can be
 manipulated with CPLFetchNameValue() as demonstrated in the handling of
-the QUALITY and PROGRESSIVE flags for JPEGCreateCopy(). 
+the QUALITY and PROGRESSIVE flags for JPEGCreateCopy().
 
-<li> The returned GDALDataset handle can be in ReadOnly or Update mode.  
-Return it in Update mode if practical, otherwise in ReadOnly mode is fine. 
+<li> The returned GDALDataset handle can be in ReadOnly or Update mode.
+Return it in Update mode if practical, otherwise in ReadOnly mode is fine.
 
 </ul>
 
 The full implementation of the CreateCopy function for JPEG (which is
 assigned to pfnCreateCopy in the GDALDriver object) is here.
 
-\verbatim
+\code
 static GDALDataset *
-JPEGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                int bStrict, char ** papszOptions, 
+JPEGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                int bStrict, char ** papszOptions,
                 GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
-    int  nQuality = 75;
-    int  bProgressive = FALSE;
-
-// -------------------------------------------------------------------- 
-//      Some some rudimentary checks                                    
-// -------------------------------------------------------------------- 
+    const int nBands = poSrcDS->GetRasterCount();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+
+    // Some some rudimentary checks
     if( nBands != 1 && nBands != 3 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "JPEG driver doesn't support %d bands.  Must be 1 (grey) "
-                  "or 3 (RGB) bands.\n", nBands );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "JPEG driver doesn't support %d bands.  Must be 1 (grey) "
+                 "or 3 (RGB) bands.", nBands);
 
         return NULL;
     }
 
     if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte && bStrict )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
-                  "JPEG driver doesn't support data type %s. "
-                  "Only eight bit byte bands supported.\n", 
-                  GDALGetDataTypeName( 
-                      poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "JPEG driver doesn't support data type %s. "
+                 "Only eight bit byte bands supported.",
+                 GDALGetDataTypeName(
+                     poSrcDS->GetRasterBand(1)->GetRasterDataType()));
 
         return NULL;
     }
 
-// -------------------------------------------------------------------- 
-//      What options has the user selected?                             
-// -------------------------------------------------------------------- 
-    if( CSLFetchNameValue(papszOptions,"QUALITY") != NULL )
+    // What options has the user selected?
+
+    int nQuality = 75;
+    if( CSLFetchNameValue(papszOptions, "QUALITY") != NULL )
     {
-        nQuality = atoi(CSLFetchNameValue(papszOptions,"QUALITY"));
+        nQuality = atoi(CSLFetchNameValue(papszOptions, "QUALITY"));
         if( nQuality < 10 || nQuality > 100 )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg,
-                      "QUALITY=%s is not a legal value in the range 10-100.",
-                      CSLFetchNameValue(papszOptions,"QUALITY") );
+            CPLError(CE_Failure, CPLE_IllegalArg,
+                     "QUALITY=%s is not a legal value in the range 10 - 100.",
+                     CSLFetchNameValue(papszOptions, "QUALITY"));
             return NULL;
         }
     }
 
-    if( CSLFetchNameValue(papszOptions,"PROGRESSIVE") != NULL )
+    bool bProgressive = false;
+    if( CSLFetchNameValue(papszOptions, "PROGRESSIVE") != NULL )
     {
-        bProgressive = TRUE;
+        bProgressive = true;
     }
 
-// -------------------------------------------------------------------- 
-//      Create the dataset.                                             
-// -------------------------------------------------------------------- 
-    VSILFILE	*fpImage;
-
-    fpImage = VSIFOpenL( pszFilename, "wb" );
+    // Create the dataset.
+    VSILFILE *fpImage = VSIFOpenL(pszFilename, "wb");
     if( fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Unable to create jpeg file %s.\n", 
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Unable to create jpeg file %s.",
+                 pszFilename);
         return NULL;
     }
 
-// -------------------------------------------------------------------- 
-//      Initialize JPG access to the file.                              
-// -------------------------------------------------------------------- 
+    // Initialize JPG access to the file.
     struct jpeg_compress_struct sCInfo;
     struct jpeg_error_mgr sJErr;
-    
-    sCInfo.err = jpeg_std_error( &sJErr );
-    jpeg_create_compress( &sCInfo );
-    
-    jpeg_stdio_dest( &sCInfo, fpImage );
-    
+
+    sCInfo.err = jpeg_std_error(&sJErr);
+    jpeg_create_compress(&sCInfo);
+
+    jpeg_stdio_dest(&sCInfo, fpImage);
+
     sCInfo.image_width = nXSize;
     sCInfo.image_height = nYSize;
     sCInfo.input_components = nBands;
@@ -826,115 +798,99 @@ JPEGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         sCInfo.in_color_space = JCS_RGB;
     }
 
-    jpeg_set_defaults( &sCInfo );
-    
-    jpeg_set_quality( &sCInfo, nQuality, TRUE );
+    jpeg_set_defaults(&sCInfo);
 
-    if( bProgressive )
-        jpeg_simple_progression( &sCInfo );
+    jpeg_set_quality(&sCInfo, nQuality, TRUE);
 
-    jpeg_start_compress( &sCInfo, TRUE );
+    if( bProgressive )
+        jpeg_simple_progression(&sCInfo);
 
-// -------------------------------------------------------------------- 
-//      Loop over image, copying image data.                            
-// -------------------------------------------------------------------- 
-    GByte 	*pabyScanline;
-    CPLErr      eErr;
+    jpeg_start_compress(&sCInfo, TRUE);
 
-    pabyScanline = (GByte *) CPLMalloc( nBands * nXSize );
+    // Loop over image, copying image data.
+    GByte *pabyScanline = static_cast<GByte *>(CPLMalloc(nBands * nXSize));
 
     for( int iLine = 0; iLine < nYSize; iLine++ )
     {
-        JSAMPLE      *ppSamples;
-
         for( int iBand = 0; iBand < nBands; iBand++ )
         {
-            GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 );
-            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
-                                     pabyScanline + iBand, nXSize, 1, GDT_Byte,
-                                     nBands, nBands * nXSize );
+            GDALRasterBand * poBand = poSrcDS->GetRasterBand(iBand + 1);
+            const CPLErr eErr =
+                poBand->RasterIO(GF_Read, 0, iLine, nXSize, 1,
+                                 pabyScanline + iBand, nXSize, 1, GDT_Byte,
+                                 nBands, nBands * nXSize);
+            // TODO: Handle error.
         }
 
-        ppSamples = pabyScanline;
-        jpeg_write_scanlines( &sCInfo, &ppSamples, 1 );
+        JSAMPLE *ppSamples = pabyScanline;
+        jpeg_write_scanlines(&sCInfo, &ppSamples, 1);
     }
 
-    CPLFree( pabyScanline );
+    CPLFree(pabyScanline);
 
-    jpeg_finish_compress( &sCInfo );
-    jpeg_destroy_compress( &sCInfo );
+    jpeg_finish_compress(&sCInfo);
+    jpeg_destroy_compress(&sCInfo);
 
-    VSIFCloseL( fpImage );
+    VSIFCloseL(fpImage);
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+    return static_cast<GDALDataset *>(GDALOpen(pszFilename, GA_ReadOnly));
 }
-\endverbatim
+\endcode
 
 \subsection gdal_drivertut_creation_create Dynamic Creation
 
 In the case of dynamic creation, there is no source dataset.  Instead the
 size, number of bands, and pixel data type of the desired file is provided
 but other information (such as georeferencing, and imagery data) would be
-supplied later via other method calls on the resulting GDALDataset.  
+supplied later via other method calls on the resulting GDALDataset.
 
 The following sample implement PCI .aux labeled raw raster creation.  It
 follows a common approach of creating a blank, but valid file using non-GDAL
 calls, and then calling GDALOpen(,GA_Update) at the end to return a writable
 file handle.  This avoids having to duplicate the various setup actions in
-the Open() function. 
+the Open() function.
 
-\verbatim
+\code
 GDALDataset *PAuxDataset::Create( const char * pszFilename,
                                   int nXSize, int nYSize, int nBands,
                                   GDALDataType eType,
-                                  char ** // papszParmList  )
+                                  char ** /* papszParmList */ )
 
 {
-    char	*pszAuxFilename;
-
-// -------------------------------------------------------------------- 
-//      Verify input options.                                           
-// -------------------------------------------------------------------- 
-    if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16
-        && eType != GDT_Int16 )
+    // Verify input options.
+    if( eType != GDT_Byte && eType != GDT_Float32 &&
+        eType != GDT_UInt16 && eType != GDT_Int16 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create PCI .Aux labeled dataset with an illegal\n"
-              "data type (%s).\n",
-              GDALGetDataTypeName(eType) );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Attempt to create PCI .Aux labeled dataset with an illegal "
+            "data type (%s).",
+            GDALGetDataTypeName(eType));
 
         return NULL;
     }
 
-// -------------------------------------------------------------------- 
-//      Try to create the file.                                         
-// -------------------------------------------------------------------- 
-    FILE	*fp;
-
-    fp = VSIFOpen( pszFilename, "w" );
+    // Try to create the file.
+    FILE *fp = VSIFOpen(pszFilename, "w");
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Attempt to create file `%s' failed.",
+                 pszFilename);
         return NULL;
     }
 
-// -------------------------------------------------------------------- 
-//      Just write out a couple of bytes to establish the binary        
-//      file, and then close it.                                        
-// -------------------------------------------------------------------- 
-    VSIFWrite( (void *) "\0\0", 2, 1, fp );
-    VSIFClose( fp );
+    // Just write out a couple of bytes to establish the binary
+    // file, and then close it.
+    VSIFWrite("\0\0", 2, 1, fp);
+    VSIFClose(fp);
 
-// -------------------------------------------------------------------- 
-//      Create the aux filename.                                        
-// -------------------------------------------------------------------- 
-    pszAuxFilename = (char *) CPLMalloc(strlen(pszFilename)+5);
-    strcpy( pszAuxFilename, pszFilename );;
+    // Create the aux filename.
+    char *pszAuxFilename = static_cast<char *>(CPLMalloc(strlen(pszFilename) + 5));
+    strcpy(pszAuxFilename, pszFilename);;
 
-    for( int i = strlen(pszAuxFilename)-1; i > 0; i-- )
+    for( int i = strlen(pszAuxFilename) - 1; i > 0; i-- )
     {
         if( pszAuxFilename[i] == '.' )
         {
@@ -943,55 +899,42 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
         }
     }
 
-    strcat( pszAuxFilename, ".aux" );
+    strcat(pszAuxFilename, ".aux");
 
-// -------------------------------------------------------------------- 
-//      Open the file.                                                  
-// -------------------------------------------------------------------- 
-    fp = VSIFOpen( pszAuxFilename, "wt" );
+    // Open the file.
+    fp = VSIFOpen(pszAuxFilename, "wt");
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
-                  pszAuxFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Attempt to create file `%s' failed.",
+                 pszAuxFilename);
         return NULL;
     }
-    
-// -------------------------------------------------------------------- 
-//      We need to write out the original filename but without any      
-//      path components in the AuxiliaryTarget line.  Do so now.         
-// -------------------------------------------------------------------- 
-    int		iStart;
-
-    iStart = strlen(pszFilename)-1;
-    while( iStart > 0 && pszFilename[iStart-1] != '/'
-           && pszFilename[iStart-1] != '\\' )
+
+    // We need to write out the original filename but without any
+    // path components in the AuxiliaryTarget line.  Do so now.
+    int iStart = strlen(pszFilename) - 1;
+    while( iStart > 0 && pszFilename[iStart - 1] != '/' &&
+           pszFilename[iStart - 1] != '\\' )
         iStart--;
 
-    VSIFPrintf( fp, "AuxilaryTarget: %s\n", pszFilename + iStart );
-
-// -------------------------------------------------------------------- 
-//      Write out the raw definition for the dataset as a whole.        
-// -------------------------------------------------------------------- 
-    VSIFPrintf( fp, "RawDefinition: %d %d %d\n",
-                nXSize, nYSize, nBands );
-
-// -------------------------------------------------------------------- 
-//      Write out a definition for each band.  We always write band     
-//      sequential files for now as these are pretty efficiently        
-//      handled by GDAL.                                                
-// -------------------------------------------------------------------- 
-    int		nImgOffset = 0;
-    
+    VSIFPrintf(fp, "AuxilaryTarget: %s\n", pszFilename + iStart);
+
+    // Write out the raw definition for the dataset as a whole.
+    VSIFPrintf(fp, "RawDefinition: %d %d %d\n",
+               nXSize, nYSize, nBands);
+
+    // Write out a definition for each band.  We always write band
+    // sequential files for now as these are pretty efficiently
+    // handled by GDAL.
+    int nImgOffset = 0;
+
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        const char * pszTypeName;
-        int	     nPixelOffset;
-        int	     nLineOffset;
-
-        nPixelOffset = GDALGetDataTypeSize(eType)/8;
-        nLineOffset = nXSize * nPixelOffset;
+        const int nPixelOffset = GDALGetDataTypeSize(eType)/8;
+        const int nLineOffset = nXSize * nPixelOffset;
 
+        const char *pszTypeName = NULL;
         if( eType == GDT_Float32 )
             pszTypeName = "32R";
         else if( eType == GDT_Int16 )
@@ -1002,7 +945,7 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
             pszTypeName = "8U";
 
         VSIFPrintf( fp, "ChanDefinition-%d: %s %d %d %d %s\n",
-                    iBand+1, pszTypeName,
+                    iBand + 1, pszTypeName,
                     nImgOffset, nPixelOffset, nLineOffset,
 #ifdef CPL_LSB
                     "Swapped"
@@ -1014,34 +957,32 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
         nImgOffset += nYSize * nLineOffset;
     }
 
-// -------------------------------------------------------------------- 
-//      Cleanup                                                         
-// -------------------------------------------------------------------- 
-    VSIFClose( fp );
+    // Cleanup.
+    VSIFClose(fp);
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    return static_cast<GDALDataset *>(GDALOpen(pszFilename, GA_Update));
 }
-\endverbatim
+\endcode
 
 File formats supporting dynamic creation, or even just update-in-place
 access also need to implement an IWriteBlock() method
-on the raster band class.  It has semantics similar to IReadBlock().  
+on the raster band class.  It has semantics similar to IReadBlock().
 As well, for various esoteric reasons, it is critical that a FlushCache()
 method be implemented in the raster band destructor.  This is to ensure that
 any write cache blocks for the band be flushed out before the destructor
-is called.  
+is called.
 
 \section gdal_drivertut_raw RawDataset/RawRasterBand Helper Classes
 
 Many file formats have the actual imagery data stored in a regular,
-binary, scanline oriented format.  Rather than re-implement the access 
+binary, scanline oriented format.  Rather than re-implement the access
 semantics for this for each formats, there are provided RawDataset and
 RawRasterBand classes declared in gdal/frmts/raw that can be utilized to
 implement efficient and convenient access.
 
 In these cases the format specific band class may not be required, or if
 required it can be derived from RawRasterBand.  The dataset class should
-be derived from RawDataset. 
+be derived from RawDataset.
 
 The Open() method for the dataset then instantiates raster bands passing
 all the layout information to the constructor.  For instance, the PNM driver
@@ -1050,37 +991,37 @@ uses the following calls to create it's raster bands.
 \code
     if( poOpenInfo->pabyHeader[1] == '5' )
     {
-        poDS->SetBand( 
-            1, new RawRasterBand( poDS, 1, poDS->fpImage,
-                                  iIn, 1, nWidth, GDT_Byte, TRUE ));
+        poDS->SetBand(
+            1, new RawRasterBand(poDS, 1, poDS->fpImage,
+                                 iIn, 1, nWidth, GDT_Byte, TRUE));
     }
-    else 
+    else
     {
-        poDS->SetBand( 
-            1, new RawRasterBand( poDS, 1, poDS->fpImage,
-                                  iIn, 3, nWidth*3, GDT_Byte, TRUE ));
-        poDS->SetBand( 
-            2, new RawRasterBand( poDS, 2, poDS->fpImage,
-                                  iIn+1, 3, nWidth*3, GDT_Byte, TRUE ));
-        poDS->SetBand( 
-            3, new RawRasterBand( poDS, 3, poDS->fpImage,
-                                  iIn+2, 3, nWidth*3, GDT_Byte, TRUE ));
+        poDS->SetBand(
+            1, new RawRasterBand(poDS, 1, poDS->fpImage,
+                                 iIn, 3, nWidth*3, GDT_Byte, TRUE));
+        poDS->SetBand(
+            2, new RawRasterBand(poDS, 2, poDS->fpImage,
+                                 iIn+1, 3, nWidth*3, GDT_Byte, TRUE));
+        poDS->SetBand(
+            3, new RawRasterBand(poDS, 3, poDS->fpImage,
+                                 iIn+2, 3, nWidth*3, GDT_Byte, TRUE));
     }
 \endcode
 
-The RawRasterBand takes the following arguments. 
+The RawRasterBand takes the following arguments.
 
 <ul>
 <li> <b>poDS</b>: The GDALDataset this band will be a child of.   This
-dataset must be of a class derived from RawRasterDataset. 
-<li> <b>nBand</b>: The band it is on that dataset, 1 based. 
+dataset must be of a class derived from RawRasterDataset.
+<li> <b>nBand</b>: The band it is on that dataset, 1 based.
 <li> <b>fpRaw</b>: The FILE * handle to the file containing the raster data.
-<li> <b>nImgOffset</b>: The byte offset to the first pixel of raster data for 
-the first scanline. 
-<li> <b>nPixelOffset</b>: The byte offset from the start of one pixel to the 
-start of the next within the scanline. 
+<li> <b>nImgOffset</b>: The byte offset to the first pixel of raster data for
+the first scanline.
+<li> <b>nPixelOffset</b>: The byte offset from the start of one pixel to the
+start of the next within the scanline.
 <li> <b>nLineOffset</b>: The byte offset from the start of one scanline to
-the start of the next. 
+the start of the next.
 <li> <b>eDataType</b>: The GDALDataType code for the type of the data on disk.
 <li> <b>bNativeOrder</b>: FALSE if the data is not in the same endianness as
 the machine GDAL is running on.  The data will be automatically byte swapped.
@@ -1092,26 +1033,26 @@ of format implementation.<p>
 
 \section gdal_drivertut_metadata Metadata, and Other Exotic Extensions
 
-There are various other items in the GDAL data model, for which virtual 
+There are various other items in the GDAL data model, for which virtual
 methods exist on the GDALDataset and GDALRasterBand.  They include:
 
 <ul>
 <li> <b>Metadata</b>: Name/value text values about a dataset or band.  The
 GDALMajorObject (base class for GDALRasterBand and GDALDataset) has built-in
 support for holding metadata, so for read access it only needs to be
-set with calls to SetMetadataItem() during the Open().  The SAR_CEOS 
+set with calls to SetMetadataItem() during the Open().  The SAR_CEOS
 (frmts/ceos2/sar_ceosdataset.cpp) and GeoTIFF drivers are examples of drivers
 implementing readable metadata.
 
 <li> <b>ColorTables</b>: GDT_Byte raster bands can have color tables associated
 with them.  The frmts/png/pngdataset.cpp driver contains an example of a
-format that supports colortables. 
+format that supports colortables.
 
 <li> <b>ColorInterpretation</b>: The PNG driver contains an example of a
 driver that returns an indication of whether a band should be treated as
-a Red, Green, Blue, Alpha or Greyscale band. 
+a Red, Green, Blue, Alpha or Greyscale band.
 
-<li> <b>GCPs</b>: GDALDatasets can have a set of ground control points 
+<li> <b>GCPs</b>: GDALDatasets can have a set of ground control points
 associated with them (as opposed to an explicit affine transform returned by
 GetGeotransform()) relating the raster to georeferenced coordinates.  The
 MFF2 (gdal/frmts/raw/hkvdataset.cpp) format is a simple example of a format
@@ -1119,17 +1060,17 @@ supporting GCPs.
 
 <li> <b>NoDataValue</b>: Bands with known "nodata" values can implement
 the GetNoDataValue() method.  See the PAux (frmts/raw/pauxdataset.cpp) for
-an example of this. 
+an example of this.
 
 <li> <b>Category Names</b>: Classified images with names for each class can
 return them using the GetCategoryNames() method though no formats currently
 implement this.
 
-</ul> 
+</ul>
 
 \htmlonly
 <p>
-$Id: gdal_drivertut.dox 33134 2016-01-23 23:10:03Z rouault $
+$Id: gdal_drivertut.dox 37555 2017-03-02 13:02:20Z goatbar $
 </p>
 \endhtmlonly
 
diff --git a/doc/gdal_tutorial.dox b/doc/gdal_tutorial.dox
index c0fc37a..0ab5f62 100644
--- a/doc/gdal_tutorial.dox
+++ b/doc/gdal_tutorial.dox
@@ -1,23 +1,23 @@
-/* $Id: gdal_tutorial.dox 33134 2016-01-23 23:10:03Z rouault $ */
+/* $Id: gdal_tutorial.dox 35222 2016-08-28 06:06:11Z goatbar $ */
 
 /*!
 \page gdal_tutorial GDAL API Tutorial
 
 \section gdal_tutorial_open Opening the File
 
-Before opening a GDAL supported raster datastore it is necessary to 
+Before opening a GDAL supported raster datastore it is necessary to
 register drivers.  There is a driver for each supported format.  Normally
 this is accomplished with the GDALAllRegister() function which attempts
 to register all known drivers, including those auto-loaded from .so files
 using GDALDriverManager::AutoLoadDrivers().  If for some applications it
 is necessary to limit the set of drivers it may be helpful to review
 the code from <a href="gdalallregister.cpp.html">gdalallregister.cpp</a>.
-Python automatically calls GDALAllRegister() when the gdal module is 
+Python automatically calls GDALAllRegister() when the gdal module is
 imported.
 
 Once the drivers are registered, the application should call the free
 standing GDALOpen() function to open a dataset, passing the name of the
-dataset and the access desired (GA_ReadOnly or GA_Update). 
+dataset and the access desired (GA_ReadOnly or GA_Update).
 
 In C++:
 \code
@@ -67,7 +67,7 @@ In Python:
 
 Note that if GDALOpen() returns NULL it means the open failed, and that
 an error messages will already have been emitted via CPLError().  If you want
-to control how errors are reported to the user review the CPLError() 
+to control how errors are reported to the user review the CPLError()
 documentation.  Generally speaking all of GDAL uses CPLError() for error
 reporting.  Also, note that pszFilename need not actually be the name
 of a physical file (though it usually is).  It's interpretation is driver
@@ -80,8 +80,8 @@ to limit GDAL file selection dialogs to only selecting physical files.
 As described in the <a href="gdal_datamodel.html">GDAL Data Model</a>, a
 GDALDataset contains a list of raster bands, all pertaining to the same
 area, and having the same resolution.  It also has metadata, a coordinate
-system, a georeferencing transform, size of raster and various other 
-information.  
+system, a georeferencing transform, size of raster and various other
+information.
 
 In the particular, but common, case of a "north up" image without any rotation
 or shearing, the georeferencing transform takes the following form :
@@ -97,7 +97,7 @@ or shearing, the georeferencing transform takes the following form :
 
 In the general case, this is an affine transform.
 
-If we wanted to print some general information about the 
+If we wanted to print some general information about the
 dataset we might do the following:
 
 In C++:
@@ -105,10 +105,10 @@ In C++:
     double        adfGeoTransform[6];
 
     printf( "Driver: %s/%s\n",
-            poDataset->GetDriver()->GetDescription(), 
+            poDataset->GetDriver()->GetDescription(),
             poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );
 
-    printf( "Size is %dx%dx%d\n", 
+    printf( "Size is %dx%dx%d\n",
             poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
             poDataset->GetRasterCount() );
 
@@ -136,7 +136,7 @@ In C:
             GDALGetDriverLongName( hDriver ) );
 
     printf( "Size is %dx%dx%d\n",
-	    GDALGetRasterXSize( hDataset ), 
+	    GDALGetRasterXSize( hDataset ),
             GDALGetRasterYSize( hDataset ),
             GDALGetRasterCount( hDataset ) );
 
@@ -160,7 +160,7 @@ In Python:
     print 'Size is ',dataset.RasterXSize,'x',dataset.RasterYSize, \
           'x',dataset.RasterCount
     print 'Projection is ',dataset.GetProjection()
-    
+
     geotransform = dataset.GetGeoTransform()
     if not geotransform is None:
 	print 'Origin = (',geotransform[0], ',',geotransform[3],')'
@@ -170,7 +170,7 @@ In Python:
 \section gdal_tutorial_band Fetching a Raster Band
 
 At this time access to raster data via GDAL is done one band at a time.
-Also, there is metadata, block sizes, color tables, and various other 
+Also, there is metadata, block sizes, color tables, and various other
 information available on a band by band basis.  The following codes fetches
 a GDALRasterBand object from the dataset (numbered 1 through GetRasterCount())
 and displays a little information about it.
@@ -181,7 +181,7 @@ In C++:
         int             nBlockXSize, nBlockYSize;
         int             bGotMin, bGotMax;
         double          adfMinMax[2];
-	
+
         poBand = poDataset->GetRasterBand( 1 );
 	poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
         printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
@@ -196,12 +196,12 @@ In C++:
             GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
 
         printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
-        
+
         if( poBand->GetOverviewCount() > 0 )
             printf( "Band has %d overviews.\n", poBand->GetOverviewCount() );
 
         if( poBand->GetColorTable() != NULL )
-            printf( "Band has a color table with %d entries.\n", 
+            printf( "Band has a color table with %d entries.\n",
                      poBand->GetColorTable()->GetColorEntryCount() );
 \endcode
 
@@ -211,7 +211,7 @@ In C:
         int             nBlockXSize, nBlockYSize;
         int             bGotMin, bGotMax;
         double          adfMinMax[2];
-	
+
         hBand = GDALGetRasterBand( hDataset, 1 );
         GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
         printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
@@ -226,12 +226,12 @@ In C:
             GDALComputeRasterMinMax( hBand, TRUE, adfMinMax );
 
         printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
-        
+
         if( GDALGetOverviewCount(hBand) > 0 )
             printf( "Band has %d overviews.\n", GDALGetOverviewCount(hBand));
 
         if( GDALGetRasterColorTable( hBand ) != NULL )
-            printf( "Band has a color table with %d entries.\n", 
+            printf( "Band has a color table with %d entries.\n",
                      GDALGetColorEntryCount(
                          GDALGetRasterColorTable( hBand ) ) );
 \endcode
@@ -259,8 +259,8 @@ In Python (note several bindings are missing):
 \section gdal_tutorial_read Reading Raster Data
 
 There are a few ways to read raster data, but the most common is via
-the GDALRasterBand::RasterIO() method.  This method will automatically take 
-care of data type conversion, up/down sampling and windowing.  The following 
+the GDALRasterBand::RasterIO() method.  This method will automatically take
+care of data type conversion, up/down sampling and windowing.  The following
 code will read the first scanline of data into a similarly sized buffer,
 converting it to floating point as part of the operation.
 
@@ -270,8 +270,8 @@ In C++:
         int   nXSize = poBand->GetXSize();
 
         pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
-        poBand->RasterIO( GF_Read, 0, 0, nXSize, 1, 
-                          pafScanline, nXSize, 1, GDT_Float32, 
+        poBand->RasterIO( GF_Read, 0, 0, nXSize, 1,
+                          pafScanline, nXSize, 1, GDT_Float32,
                           0, 0 );
 \endcode
 
@@ -283,20 +283,20 @@ In C:
         int   nXSize = GDALGetRasterBandXSize( hBand );
 
         pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
-	GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1, 
-                      pafScanline, nXSize, 1, GDT_Float32, 
+	GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1,
+                      pafScanline, nXSize, 1, GDT_Float32,
                       0, 0 );
 \endcode
 
 The pafScanline buffer should be freed with CPLFree() when it is no longer used.
 
 In Python:
- 
+
 \code
   	scanline = band.ReadRaster( 0, 0, band.XSize, 1, \
                                      band.XSize, 1, GDT_Float32 )
 \endcode
- 
+
 Note that the returned scanline is of type string, and contains
 xsize*4 bytes of raw binary floating point data. This can be converted
 to Python values using the <b>struct</b> module from the standard
@@ -308,7 +308,7 @@ library:
 	tuple_of_floats = struct.unpack('f' * b2.XSize, scanline)
 \endcode
 
-The RasterIO call takes the following arguments. 
+The RasterIO call takes the following arguments.
 \code
 CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
                                  int nXOff, int nYOff, int nXSize, int nYSize,
@@ -318,38 +318,38 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
                                  int nLineSpace )
 \endcode
 
-Note that the same RasterIO() call is used to read, or write based on 
-the setting of eRWFlag (either GF_Read or GF_Write).  The nXOff, nYOff, 
-nXSize, nYSize argument describe the window of raster data on disk to 
+Note that the same RasterIO() call is used to read, or write based on
+the setting of eRWFlag (either GF_Read or GF_Write).  The nXOff, nYOff,
+nXSize, nYSize argument describe the window of raster data on disk to
 read (or write).  It doesn't have to fall on tile boundaries though access
-may be more efficient if it does.  
+may be more efficient if it does.
 
 The pData is the memory buffer the data is read into, or written from.  It's
 real type must be whatever is passed as eBufType, such as GDT_Float32, or
-GDT_Byte.  The RasterIO() call will take care of converting between the 
+GDT_Byte.  The RasterIO() call will take care of converting between the
 buffer's data type and the data type of the band.  Note that when converting
 floating point data to integer RasterIO() rounds down, and when converting
 source values outside the legal range of the output the nearest legal value
 is used.  This implies, for instance, that 16bit data read into a GDT_Byte
-buffer will map all values greater than 255 to 255, <b>the data is not 
+buffer will map all values greater than 255 to 255, <b>the data is not
 scaled!</b>
 
 The nBufXSize and nBufYSize
 values describe the size of the buffer.  When loading data at full resolution
-this would be the same as the window size.  However, to load a reduced 
+this would be the same as the window size.  However, to load a reduced
 resolution overview this could be set to smaller than the window on disk.  In
 this case the RasterIO() will utilize overviews to do the IO more efficiently
-if the overviews are suitable. 
+if the overviews are suitable.
 
 The nPixelSpace, and nLineSpace are normally zero indicating that default
-values should be used.  However, they can be used to control access to 
+values should be used.  However, they can be used to control access to
 the memory data buffer, allowing reading into a buffer containing other
-pixel interleaved data for instance.  
+pixel interleaved data for instance.
 
 \section gdal_tutorial_close Closing the Dataset
 
 Please keep in mind that GDALRasterBand objects are <i>owned</i> by their
-dataset, and they should never be destroyed with the C++ delete operator. 
+dataset, and they should never be destroyed with the C++ delete operator.
 GDALDataset's can be closed by calling GDALClose() (it is NOT recommended
 to use the delete operator on a GDALDataset for Windows users because of known
 issues when allocating and freeing memory across module boundaries. See the relevant
@@ -363,14 +363,14 @@ like GTiff will likely result in being unable to open it afterwards.
 New files in GDAL supported formats may be created if the format driver
 supports creation.  There are two general techniques for creating files,
 using CreateCopy() and Create().
-The CreateCopy method involves calling the CreateCopy() method on the 
+The CreateCopy method involves calling the CreateCopy() method on the
 format driver, and passing in a source dataset that should be copied.  The
 Create method involves calling the Create() method on the driver, and then
-explicitly writing all the metadata, and raster data with separate calls. 
-All drivers that support creating new files support the CreateCopy() method, 
+explicitly writing all the metadata, and raster data with separate calls.
+All drivers that support creating new files support the CreateCopy() method,
 but only a few support the Create() method.
 
-To determine if a particular format supports Create or CreateCopy 
+To determine if a particular format supports Create or CreateCopy
 it is possible to check the DCAP_CREATE  and DCAP_CREATECOPY metadata on the
 format driver object.  Ensure that GDALAllRegister() has been called before
 calling GetDriverByName().  In this example we fetch a driver, and determine
@@ -433,8 +433,8 @@ or CreateCopy().
 
 \section gdal_tutorial_createcopy Using CreateCopy()
 
-The GDALDriver::CreateCopy() method can be used fairly simply as most 
-information is collected from the source dataset.  However, it includes 
+The GDALDriver::CreateCopy() method can be used fairly simply as most
+information is collected from the source dataset.  However, it includes
 options for passing format specific creation options, and for reporting
 progress to the user as a long dataset copy takes place.  A simple copy
 from the a file named pszSrcFilename, to a new file named pszDstFilename
@@ -443,11 +443,11 @@ look like this:
 
 In C++:
 \code
-    GDALDataset *poSrcDS = 
+    GDALDataset *poSrcDS =
        (GDALDataset *) GDALOpen( pszSrcFilename, GA_ReadOnly );
     GDALDataset *poDstDS;
 
-    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE, 
+    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
                                     NULL, NULL, NULL );
 
     /* Once we're done, close properly the dataset */
@@ -461,7 +461,7 @@ In C:
     GDALDatasetH hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
     GDALDatasetH hDstDS;
 
-    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE, 
+    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE,
                              NULL, NULL, NULL );
 
     /* Once we're done, close properly the dataset */
@@ -483,15 +483,15 @@ In Python:
 
 Note that the CreateCopy() method returns a writable dataset, and that it
 must be closed properly to complete writing and flushing the dataset to disk.
-In the Python case this occurs automatically when "dst_ds" goes out of scope. 
+In the Python case this occurs automatically when "dst_ds" goes out of scope.
 The FALSE (or 0) value used for the bStrict option just after the destination
-filename in the CreateCopy() call indicates that the CreateCopy() call 
+filename in the CreateCopy() call indicates that the CreateCopy() call
 should proceed without a fatal error even if the destination dataset cannot
 be created to exactly match the input dataset.  This might be because the
 output format does not support the pixel datatype of the input dataset, or
 because the destination cannot support writing georeferencing for instance.
 
-A more complex case might involve passing creation options, and using a 
+A more complex case might involve passing creation options, and using a
 predefined progress monitor like this:
 
 In C++:
@@ -499,10 +499,10 @@ In C++:
 #include "cpl_string.h"
 ...
     char **papszOptions = NULL;
-    
+
     papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
     papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
-    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE, 
+    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
                                     papszOptions, GDALTermProgress, NULL );
 
     /* Once we're done, close properly the dataset */
@@ -516,10 +516,10 @@ In C:
 #include "cpl_string.h"
 ...
     char **papszOptions = NULL;
-    
+
     papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
     papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
-    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE, 
+    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE,
                              papszOptions, GDALTermProgres, NULL );
 
     /* Once we're done, close properly the dataset */
@@ -532,7 +532,7 @@ In Python:
 
 \code
     src_ds = gdal.Open( src_filename )
-    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0, 
+    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0,
                                 [ 'TILED=YES', 'COMPRESS=PACKBITS' ] )
 
     # Once we're done, close properly the dataset
@@ -543,27 +543,27 @@ In Python:
 \section gdal_tutorial_create Using Create()
 
 For situations in which you are not just exporting an existing file to a new
-file, it is generally necessary to use the GDALDriver::Create() method (though 
+file, it is generally necessary to use the GDALDriver::Create() method (though
 some interesting options are possible through use of virtual files or in-memory
-files).  The Create() method takes an options list much like CreateCopy(), 
+files).  The Create() method takes an options list much like CreateCopy(),
 but the image size, number of bands and band type must be provided explicitly.
 <p>
 
 In C++:
 \code
-    GDALDataset *poDstDS;	
+    GDALDataset *poDstDS;
     char **papszOptions = NULL;
 
-    poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte, 
+    poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte,
                                 papszOptions );
 \endcode
 
 In C:
 \code
-    GDALDatasetH hDstDS;	
+    GDALDatasetH hDstDS;
     char **papszOptions = NULL;
 
-    hDstDS = GDALCreate( hDriver, pszDstFilename, 512, 512, 1, GDT_Byte, 
+    hDstDS = GDALCreate( hDriver, pszDstFilename, 512, 512, 1, GDT_Byte,
                          papszOptions );
 \endcode
 
@@ -587,7 +587,7 @@ In C++:
     GByte abyRaster[512*512];
 
     poDstDS->SetGeoTransform( adfGeoTransform );
-    
+
     oSRS.SetUTM( 11, TRUE );
     oSRS.SetWellKnownGeogCS( "NAD27" );
     oSRS.exportToWkt( &pszSRS_WKT );
@@ -595,8 +595,8 @@ In C++:
     CPLFree( pszSRS_WKT );
 
     poBand = poDstDS->GetRasterBand(1);
-    poBand->RasterIO( GF_Write, 0, 0, 512, 512, 
-                      abyRaster, 512, 512, GDT_Byte, 0, 0 );    
+    poBand->RasterIO( GF_Write, 0, 0, 512, 512,
+                      abyRaster, 512, 512, GDT_Byte, 0, 0 );
 
     /* Once we're done, close properly the dataset */
     GDALClose( (GDALDatasetH) poDstDS );
@@ -614,7 +614,7 @@ In C:
 
     hSRS = OSRNewSpatialReference( NULL );
     OSRSetUTM( hSRS, 11, TRUE );
-    OSRSetWellKnownGeogCS( hSRS, "NAD27" );			
+    OSRSetWellKnownGeogCS( hSRS, "NAD27" );
     OSRExportToWkt( hSRS, &pszSRS_WKT );
     OSRDestroySpatialReference( hSRS );
 
@@ -622,8 +622,8 @@ In C:
     CPLFree( pszSRS_WKT );
 
     hBand = GDALGetRasterBand( hDstDS, 1 );
-    GDALRasterIO( hBand, GF_Write, 0, 0, 512, 512, 
-                  abyRaster, 512, 512, GDT_Byte, 0, 0 );    
+    GDALRasterIO( hBand, GF_Write, 0, 0, 512, 512,
+                  abyRaster, 512, 512, GDT_Byte, 0, 0 );
 
     /* Once we're done, close properly the dataset */
     GDALClose( hDstDS );
@@ -636,13 +636,13 @@ In Python:
     import numpy
 
     dst_ds.SetGeoTransform( [ 444720, 30, 0, 3751320, 0, -30 ] )
-    
+
     srs = osr.SpatialReference()
     srs.SetUTM( 11, 1 )
     srs.SetWellKnownGeogCS( 'NAD27' )
     dst_ds.SetProjection( srs.ExportToWkt() )
 
-    raster = numpy.zeros( (512, 512), dtype=numpy.uint8 )    
+    raster = numpy.zeros( (512, 512), dtype=numpy.uint8 )
     dst_ds.GetRasterBand(1).WriteArray( raster )
 
     # Once we're done, close properly the dataset
@@ -651,7 +651,7 @@ In Python:
 
 \htmlonly
 <p>
-$Id: gdal_tutorial.dox 33134 2016-01-23 23:10:03Z rouault $
+$Id: gdal_tutorial.dox 35222 2016-08-28 06:06:11Z goatbar $
 </p>
 \endhtmlonly
 
diff --git a/doc/grid_tutorial.dox b/doc/grid_tutorial.dox
index 5ae47ba..c8c04bd 100644
--- a/doc/grid_tutorial.dox
+++ b/doc/grid_tutorial.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: grid_tutorial.dox 14579 2008-05-30 15:41:30Z dron $ */
+/* $Id: grid_tutorial.dox 35222 2016-08-28 06:06:11Z goatbar $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -19,7 +19,7 @@ This problem can be solved using data interpolation or approximation
 algorithms. But you are not limited by interpolation here. Sometimes you don't
 need to interpolate your data but rather compute some statistics or data
 metrics over the region. Statistics is valuable itself or could be used for
-better choosing the interpolation algorithm and parameters. 
+better choosing the interpolation algorithm and parameters.
 
 That is what GDAL Grid API is about. It helps you to interpolate your data
 (see \ref grid_tutorial_interpolation) or compute data metrics (see \ref
@@ -47,7 +47,7 @@ formula:
      Z=\frac{\sum_{i=1}^n{\frac{Z_i}{r_i^p}}}{\sum_{i=1}^n{\frac{1}{r_i^p}}}
 \f]
 
-where 
+where
 <ul>
     <li> \f$Z_i\f$ is a known value at point \f$i\f$,
     <li> \f$r\f$ is a distance from the grid node to point \f$i\f$,
@@ -82,7 +82,7 @@ Mathematically it can be expressed with the formula:
      Z=\frac{\sum_{i=1}^n{Z_i}}{n}
 \f]
 
-where 
+where
 <ul>
     <li> \f$Z\f$ is a resulting value at the grid node,
     <li> \f$Z_i\f$ is a known value at point \f$i\f$,
@@ -118,7 +118,7 @@ If there are no points found, the specified NODATA value will be returned.
      Z=\min{(Z_1,Z_2,\ldots,Z_n)}
 \f]
 
-where 
+where
 <ul>
     <li> \f$Z\f$ is a resulting value at the grid node,
     <li> \f$Z_i\f$ is a known value at point \f$i\f$,
@@ -135,7 +135,7 @@ If there are no points found, the specified NODATA value will be returned.
      Z=\max{(Z_1,Z_2,\ldots,Z_n)}
 \f]
 
-where 
+where
 <ul>
     <li> \f$Z\f$ is a resulting value at the grid node,
     <li> \f$Z_i\f$ is a known value at point \f$i\f$,
@@ -153,7 +153,7 @@ specified NODATA value will be returned.
      Z=\max{(Z_1,Z_2,\ldots,Z_n)}-\min{(Z_1,Z_2,\ldots,Z_n)}
 \f]
 
-where 
+where
 <ul>
     <li> \f$Z\f$ is a resulting value at the grid node,
     <li> \f$Z_i\f$ is a known value at point \f$i\f$,
@@ -182,7 +182,7 @@ be used for computation.
 
 \htmlonly
 <p>
-$Id: grid_tutorial.dox 14579 2008-05-30 15:41:30Z dron $
+$Id: grid_tutorial.dox 35222 2016-08-28 06:06:11Z goatbar $
 </p>
 \endhtmlonly
 
diff --git a/doc/images/OSGeo_project.png b/doc/images/OSGeo_project.png
new file mode 100644
index 0000000..48f9b1d
Binary files /dev/null and b/doc/images/OSGeo_project.png differ
diff --git a/doc/images/foss4g2017.png b/doc/images/foss4g2017.png
new file mode 100644
index 0000000..fea550f
Binary files /dev/null and b/doc/images/foss4g2017.png differ
diff --git a/doc/index.dox b/doc/index.dox
index 70b51d9..1ef08c3 100644
--- a/doc/index.dox
+++ b/doc/index.dox
@@ -1,24 +1,34 @@
-#ifndef DOXYGEN_SKIP                                                            
-/* $Id: index.dox 33196 2016-01-29 10:56:46Z rouault $ */               
-#endif /* DOXYGEN_SKIP */                                                       
+#ifndef DOXYGEN_SKIP
+/* $Id: index.dox 37219 2017-01-27 11:03:40Z rouault $ */
+#endif /* DOXYGEN_SKIP */
 
 /*! \mainpage GDAL - Geospatial Data Abstraction Library
 
 <center><b>Select language</b>: [English]<a href="index_ru.html">[Russian]</a><a href="index_br.html">[Portuguese]</a><a href="http://gdal.gloobe.org/">[French/Francais]</a></center>
 
+<table border="0" cellspacing="4" cellpadding="4">
+
+<tr><td>
 \htmlonly<img src="gdalicon.png" alt="GDAL">\endhtmlonly \latexonly GDAL/OGR \endlatexonly
 is a translator library for raster and vector geospatial data formats
-that is released under an <a href="http://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse">X/MIT</a> style 
+that is released under an <a href="http://trac.osgeo.org/gdal/wiki/FAQGeneral#WhatlicensedoesGDALOGRuse">X/MIT</a> style
 <a href="http://www.opensource.org/">
 Open Source</a> license by the <a href="http://www.osgeo.org/">Open Source
 Geospatial Foundation</a>.  As a library, it presents a
 \link gdal_datamodel.html single raster abstract data model\endlink and
-\link ogr_arch.html vector abstract data model\endlink  
+\link ogr_arch.html single vector abstract data model\endlink
 to the calling application for all supported formats.  It also comes with a variety
 of useful command line utilities
-for data translation and processing.  The 
-<a href="http://trac.osgeo.org/gdal/wiki/Release/2.0.2-News">NEWS</a>
-page describes the January 2016 GDAL/OGR 2.0.2 release.
+for data translation and processing.  The
+<a href="http://trac.osgeo.org/gdal/wiki/Release/2.1.3-News">NEWS</a>
+page describes the January 2017 GDAL/OGR 2.1.3 release.
+</td>
+
+<td>
+\htmlonly<a href="http://www.osgeo.org"><img src="OSGeo_project.png" alt="OSGeo project" border="0"></a>\endhtmlonly
+</td>
+</tr>
+</table>
 
 Traditionally GDAL used to design the raster part of the library, and OGR the
 vector part for Simple Features. Starting with GDAL 2.0, both sides have been
@@ -26,9 +36,7 @@ more tightly integrated. You can still refer to the <a href="http://gdal.org/1.1
 if needed.
 
 Master: http://www.gdal.org<br>
-Download: 
- <a href="ftp://ftp.remotesensing.org/gdal">ftp at remotesensing.org</a>,
- <a href="http://download.osgeo.org/gdal">http at download.osgeo.org</a>
+Download: <a href="http://download.osgeo.org/gdal">http at download.osgeo.org</a>
 
 \section index_userdocs User Oriented Documentation
 
@@ -90,6 +98,7 @@ Download:
 <li> <a href="gdal_8h.html">gdal.h: Raster C API</a>
 <li> <a href="ogr__api_8h.html">ogr_api.h: Vector C API</a>
 <li> <a href="gdal__alg_8h.html">gdal_alg.h: GDAL Algorithms C API</a>
+<li> <a href="ogr__srs__api_8h.html">ogr_srs_api.h: Spatial Reference System C API</a>
 <li> <a href="gdal__utils_8h.html">gdal_utils.h: GDAL Utilities C API</a>
 <li> <a href="classGDALDataset.html">GDALDataset C++ API</a>
 <li> <a href="classGDALRasterBand.html">GDALRasterBand C++ API</a>
@@ -107,22 +116,22 @@ or <a href="http://home.gdal.org/projects/opengis/wkt_prop.doc">doc</a> format.
 </ul>
 -->
 
-\section foss4g Conference 
- 
-\htmlonly 
-<table border="0" cellspacing="4" cellpadding="4"> 
-
-<tr><td><a href="http://2016.foss4g.org/"> 
-<img src="http://wiki.osgeo.org/images/f/ff/Foss4g2016_logo_squared.png" alt="FOSS4G 2016" border="0"> 
-</a></td> 
- 
-<td><a href="http://2016.foss4g.org">FOSS4G 2016</a> is the leading annual  
-conference for free and open source geospatial software.  It will include  
-presentations related to GDAL/OGR, and some of the GDAL/OGR  
-development community will be attending.  It is <i>the</i> event for those  
-interested in GDAL/OGR, other FOSS geospatial technologies and the community  
-around them. The conference will be held in Bonn, Germany, <strong>August 24th - 26th, 2016</strong>.</td>
-</table> 
+\section foss4g Conference
+
+\htmlonly
+<table border="0" cellspacing="4" cellpadding="4">
+
+<tr><td><a href="http://2017.foss4g.org/">
+<img src="foss4g2017.png" alt="FOSS4G 2017" border="0">
+</a></td>
+
+<td><a href="http://2017.foss4g.org">FOSS4G 2017</a> is the leading annual
+conference for free and open source geospatial software.  It will include
+presentations related to GDAL/OGR, and some of the GDAL/OGR
+development community will be attending.  It is <i>the</i> event for those
+interested in GDAL/OGR, other FOSS geospatial technologies and the community
+around them. The conference will be held in Boston, USA, <strong>August 14th - 18th, 2017</strong>.</td>
+</table>
 \endhtmlonly
 
 \section index_maillist Mailing List
@@ -132,22 +141,21 @@ developments with the GDAL/OGR project.
 
 The <a href="mailto:gdal-dev at lists.osgeo.org">gdal-dev at lists.osgeo.org</a>
 mailing list can be used for discussion of development and user issues related
-to GDAL and related technologies.  Subscriptions can be done, and archives 
-reviewed <a href="http://lists.osgeo.org/mailman/listinfo/gdal-dev/">on 
+to GDAL and related technologies.  Subscriptions can be done, and archives
+reviewed <a href="http://lists.osgeo.org/mailman/listinfo/gdal-dev/">on
 the web</a>.  The mailing list is also available in read-only format by NNTP at
-<a href="news://news.gmane.org/gmane.comp.gis.gdal.devel">news://news.gmane.org/gmane.comp.gis.gdal.devel</a>
-and by HTTP at
-<a href="http://news.gmane.org/gmane.comp.gis.gdal.devel">http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.
+<a href="news://news.gmane.org/gmane.comp.gis.gdal.devel">news://news.gmane.org/gmane.comp.gis.gdal.devel</a>.
+
 Archives since 2005 are searchable on <a href="http://osgeo-org.1560.n6.nabble.com/GDAL-Dev-f3742093.html">Nabble</a>.<p>
 
-Some GDAL/OGR users and developers can also often be found in the 
-<a href="irc://irc.freenode.net/#gdal">#gdal</a> IRC channel on irc.freenode.net.<p>
+Some GDAL/OGR users and developers can also often be found in the
+<a href="irc://irc.freenode.net/#gdal">\#gdal</a> IRC channel on irc.freenode.net.<p>
 
 \section index_bugs Bug Reporting
 
-GDAL bugs 
-<a href="http://trac.osgeo.org/gdal">can be reported</a>, and 
-<a href="http://trac.osgeo.org/gdal/report/1?sort=ticket&asc=0">can be 
+GDAL bugs
+<a href="http://trac.osgeo.org/gdal">can be reported</a>, and
+<a href="http://trac.osgeo.org/gdal/report/1?sort=ticket&asc=0">can be
 listed</a> using Trac.<p>
 
 \section index_bindings GDAL In Other Languages
diff --git a/doc/ru/Doxyfile b/doc/ru/Doxyfile
index 2223f14..2c77c0a 100644
--- a/doc/ru/Doxyfile
+++ b/doc/ru/Doxyfile
@@ -1,1138 +1,1136 @@
-# Doxyfile 1.4.2
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
-# by quotes) that should identify the project.
-
-PROJECT_NAME           = RU
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
-# This could be handy for archiving the generated documentation or 
-# if some version control system is used.
-
-PROJECT_NUMBER         = 
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY       = 
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
-# documentation generated by doxygen is written. Doxygen will use this 
-# information to generate all constant output in the proper language. 
-# The default language is English, other supported languages are: 
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
-# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
-# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
-# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
-# Swedish, and Ukrainian.
-
-OUTPUT_LANGUAGE        = Russian
-
-# This tag can be used to specify the encoding used in the generated output. 
-# The encoding is not always determined by the language that is chosen, 
-# but also whether or not the output is meant for Windows or non-Windows users. 
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
-# forces the Windows encoding (this is the default for the Windows binary), 
-# whereas setting the tag to NO uses a Unix-style encoding (the default for 
-# all platforms other than Windows).
-
-USE_WINDOWS_ENCODING   = NO
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
-# include brief member descriptions after the members that are listed in 
-# the file and class documentation (similar to JavaDoc). 
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
-# the brief description of a member or function before the detailed description. 
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF           = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator 
-# that is used to form the text in various listings. Each string 
-# in this list, if found as the leading text of the brief description, will be 
-# stripped from the text and the result after processing the whole list, is 
-# used as the annotated text. Otherwise, the brief description is used as-is. 
-# If left blank, the following values are used ("$name" is automatically 
-# replaced with the name of the entity): "The $name class" "The $name widget" 
-# "The $name file" "is" "provides" "specifies" "contains" 
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF       = 
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
-# Doxygen will generate a detailed section even if there is only a brief 
-# description.
-
-ALWAYS_DETAILED_SEC    = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
-# inherited members of a class in the documentation of that class as if those 
-# members were ordinary class members. Constructors, destructors and assignment 
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB  = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
-# path before files name in the file list and in the header files. If set 
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES        = NO
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
-# the path mentioned in the documentation of a class, which tells 
-# the reader which header file to include in order to use a class. 
-# If left blank only the name of the header file containing the class 
-# definition is used. Otherwise one should specify the include paths that 
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH    = 
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
-# (but less readable) file names. This can be useful is your file systems 
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES            = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
-# will interpret the first line (until the first dot) of a JavaDoc-style 
-# comment as the brief description. If set to NO, the JavaDoc 
-# comments will behave just like the Qt-style comments (thus requiring an 
-# explicit @brief command for a brief description.
-
-JAVADOC_AUTOBRIEF      = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
-# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
-# comments) as a brief description. This used to be the default behaviour. 
-# The new default is to treat a multi-line C++ comment block as a detailed 
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member 
-# documentation.
-
-DETAILS_AT_TOP         = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
-# member inherits the documentation from any documented member that it 
-# re-implements.
-
-INHERIT_DOCS           = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE               = 8
-
-# This tag can be used to specify a number of aliases that acts 
-# as commands in the documentation. An alias has the form "name=value". 
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
-# put the command \sideeffect (or @sideeffect) in the documentation, which 
-# will result in a user-defined paragraph with heading "Side Effects:". 
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES                = 
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
-# sources only. Doxygen will then generate output that is more tailored for C. 
-# For instance, some of the names that are used will be different. The list 
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C  = NO
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
-# only. Doxygen will then generate output that is more tailored for Java. 
-# For instance, namespaces will be presented as packages, qualified scopes 
-# will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA   = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
-# the same type (for instance a group of public functions) to be put as a 
-# subgroup of that type (e.g. under the Public Functions section). Set it to 
-# NO to prevent subgrouping. Alternatively, this can be done per class using 
-# the \nosubgrouping command.
-
-SUBGROUPING            = YES
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
-# documentation are documented, even if no documentation was available. 
-# Private class members and static file members will be hidden unless 
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL            = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
-# will be included in the documentation.
-
-EXTRACT_PRIVATE        = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file 
-# will be included in the documentation.
-
-EXTRACT_STATIC         = NO
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
-# defined locally in source files will be included in the documentation. 
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES  = YES
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
-# undocumented members of documented classes, files or namespaces. 
-# If set to NO (the default) these members will be included in the 
-# various overviews, but no documentation section is generated. 
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS     = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
-# undocumented classes that are normally visible in the class hierarchy. 
-# If set to NO (the default) these classes will be included in the various 
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES     = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
-# friend (class|struct|union) declarations. 
-# If set to NO (the default) these declarations will be included in the 
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS  = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
-# documentation blocks found inside the body of a function. 
-# If set to NO (the default) these blocks will be appended to the 
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS      = NO
-
-# The INTERNAL_DOCS tag determines if documentation 
-# that is typed after a \internal command is included. If the tag is set 
-# to NO (the default) then the documentation will be excluded. 
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS          = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
-# file names in lower-case letters. If set to YES upper-case letters are also 
-# allowed. This is useful if you have classes or files whose names only differ 
-# in case and if your file system supports case sensitive file names. Windows 
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES       = YES
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
-# will show members with their full class and namespace scopes in the 
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
-# will put a list of the files that are included by a file in the documentation 
-# of that file.
-
-SHOW_INCLUDE_FILES     = YES
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
-# is inserted in the documentation for inline members.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
-# will sort the (detailed) documentation of file and class members 
-# alphabetically by member name. If set to NO the members will appear in 
-# declaration order.
-
-SORT_MEMBER_DOCS       = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
-# brief documentation of file, namespace and class members alphabetically 
-# by member name. If set to NO (the default) the members will appear in 
-# declaration order.
-
-SORT_BRIEF_DOCS        = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
-# sorted by fully-qualified names, including namespaces. If set to 
-# NO (the default), the class list will be sorted only by class name, 
-# not including the namespace part. 
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the 
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME     = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or 
-# disable (NO) the todo list. This list is created by putting \todo 
-# commands in the documentation.
-
-GENERATE_TODOLIST      = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or 
-# disable (NO) the test list. This list is created by putting \test 
-# commands in the documentation.
-
-GENERATE_TESTLIST      = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or 
-# disable (NO) the bug list. This list is created by putting \bug 
-# commands in the documentation.
-
-GENERATE_BUGLIST       = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
-# disable (NO) the deprecated list. This list is created by putting 
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional 
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS       = 
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
-# the initial value of a variable or define consists of for it to appear in 
-# the documentation. If the initializer consists of more lines than specified 
-# here it will be hidden. Use a value of 0 to hide initializers completely. 
-# The appearance of the initializer of individual variables and defines in the 
-# documentation can be controlled using \showinitializer or \hideinitializer 
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES  = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
-# at the bottom of the documentation of classes and structs. If set to YES the 
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES        = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated 
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET                  = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are 
-# generated by doxygen. Possible values are YES and NO. If left blank 
-# NO is used.
-
-WARNINGS               = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED   = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
-# potential errors in the documentation, such as not documenting some 
-# parameters in a documented function, or documenting parameters that 
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR      = YES
-
-# The WARN_FORMAT tag determines the format of the warning messages that 
-# doxygen can produce. The string should contain the $file, $line, and $text 
-# tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text. Optionally the format may contain 
-# $version, which will be replaced by the version of the file (if it could 
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT            = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning 
-# and error messages should be written. If left blank the output is written 
-# to stderr.
-
-WARN_LOGFILE           = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
-# with spaces.
-
-INPUT                  = .
-
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank the following patterns are tested: 
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
-
-FILE_PATTERNS          = *.h \
-                         *.cpp \
-                         *.c \
-                         *.dox
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
-# should be searched for input files as well. Possible values are YES and NO. 
-# If left blank NO is used.
-
-RECURSIVE              = NO
-
-# The EXCLUDE tag can be used to specify files and/or directories that should 
-# excluded from the INPUT source files. This way you can easily exclude a 
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE                = 
-
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
-# directories that are symbolic links (a Unix filesystem feature) are excluded 
-# from the input.
-
-EXCLUDE_SYMLINKS       = NO
-
-# If the value of the INPUT tag contains directories, you can use the 
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
-# certain files from those directories.
-
-EXCLUDE_PATTERNS       = 
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
-# the \include command).
-
-EXAMPLE_PATH           = apps \
-                         frmts \
-                         frmts/jdem 
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included.
-
-EXAMPLE_PATTERNS       = 
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
-# searched for input files to be used with the \include or \dontinclude 
-# commands irrespective of the value of the RECURSIVE tag. 
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE      = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or 
-# directories that contain image that are included in the documentation (see 
-# the \image command).
-
-IMAGE_PATH             = 
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should 
-# invoke to filter for each input file. Doxygen will invoke the filter program 
-# by executing (via popen()) the command <filter> <input-file>, where <filter> 
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
-# input file. Doxygen will then use the output that the filter program writes 
-# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
-# ignored.
-
-INPUT_FILTER           = 
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
-# INPUT_FILTER) will be used to filter the input files when producing source 
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES    = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-# Note: To get rid of all source code in the generated output, make sure also 
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER         = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body 
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES         = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
-# doxygen to hide any special comment blocks from generated source code 
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS    = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
-# then for each documented function all documented 
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = YES
-
-# If the REFERENCES_RELATION tag is set to YES (the default) 
-# then for each documented function all documented entities 
-# called/used by that function will be listed.
-
-REFERENCES_RELATION    = YES
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
-# will generate a verbatim copy of the header file for each class for 
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS       = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
-# of all compounds will be generated. Enable this if the project 
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX     = NO
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX    = 5
-
-# In case all classes in a project start with a common prefix, all 
-# classes will be put under the same header in the alphabetical index. 
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX          = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
-# generate HTML output.
-
-GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT            = 
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION    = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard header.
-
-HTML_HEADER            = 
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard footer.
-
-HTML_FOOTER            = ../gdal_footer.html
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
-# style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet. Note that doxygen will try to copy 
-# the style sheet file to the HTML output directory, so don't put your own 
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET        = 
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS     = YES
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
-# will be generated that can be used as input for tools like the 
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP      = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
-# be used to specify the file name of the resulting .chm file. You 
-# can add a path in front of the file if the result should not be 
-# written to the html output directory.
-
-CHM_FILE               = 
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
-# be used to specify the location (absolute path including file name) of 
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION           = 
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
-# controls if a separate .chi index file is generated (YES) or that 
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI           = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
-# controls whether a binary table of contents is generated (YES) or a 
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members 
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND             = NO
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
-# the value YES disables it.
-
-DISABLE_INDEX          = NO
-
-# This tag can be used to set the number of enum values (range [1..20]) 
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that 
-# is generated for HTML Help). For this to work a browser that supports 
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
-# probably better off using the HTML help feature.
-
-GENERATE_TREEVIEW      = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
-# used to set the initial width (in pixels) of the frame in which the tree 
-# is shown.
-
-TREEVIEW_WIDTH         = 250
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
-# generate Latex output.
-
-GENERATE_LATEX         = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT           = 
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
-# invoked. If left blank `latex' will be used as the default command name.
-
-LATEX_CMD_NAME         = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
-# generate index for LaTeX. If left blank `makeindex' will be used as the 
-# default command name.
-
-MAKEINDEX_CMD_NAME     = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
-# LaTeX documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_LATEX          = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used 
-# by the printer. Possible values are: a4, a4wide, letter, legal and 
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE             = a4wide
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES         = 
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
-# the generated latex document. The header should contain everything until 
-# the first chapter. If it is left blank doxygen will generate a 
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER           = 
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
-# contain links (just like the HTML output) instead of page references 
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS         = NO
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
-# plain latex in the generated Makefile. Set this option to YES to get a 
-# higher quality PDF documentation.
-
-USE_PDFLATEX           = NO
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
-# command to the generated LaTeX files. This will instruct LaTeX to keep 
-# running if errors occur, instead of asking the user for help. 
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE        = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
-# include the index chapters (such as File Index, Compound Index, etc.) 
-# in the output.
-
-LATEX_HIDE_INDICES     = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
-# The RTF output is optimized for Word 97 and may not look very pretty with 
-# other RTF readers or editors.
-
-GENERATE_RTF           = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT             = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
-# RTF documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_RTF            = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
-# will contain hyperlink fields. The RTF file will 
-# contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using WORD or other 
-# programs which support those fields. 
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS         = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
-# config file, i.e. a series of assignments. You only have to provide 
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE    = 
-
-# Set optional variables used in the generation of an rtf document. 
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE    = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
-# generate man pages
-
-GENERATE_MAN           = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT             = man
-
-# The MAN_EXTENSION tag determines the extension that is added to 
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION          = .1
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
-# then it will generate one additional man file for each entity 
-# documented in the real man page(s). These additional files 
-# only source the real man page, but without them the man command 
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS              = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will 
-# generate an XML file that captures the structure of 
-# the code including all documentation.
-
-GENERATE_XML           = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT             = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_SCHEMA             = 
-
-# The XML_DTD tag can be used to specify an XML DTD, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_DTD                = 
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
-# dump the program listings (including syntax highlighting 
-# and cross-referencing information) to the XML output. Note that 
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING     = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
-# generate an AutoGen Definitions (see autogen.sf.net) file 
-# that captures the structure of the code including all 
-# documentation. Note that this feature is still experimental 
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF   = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
-# generate a Perl module file that captures the structure of 
-# the code including all documentation. Note that this 
-# feature is still experimental and incomplete at the 
-# moment.
-
-GENERATE_PERLMOD       = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX          = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
-# nicely formatted so it can be parsed by a human reader.  This is useful 
-# if you want to understand what is going on.  On the other hand, if this 
-# tag is set to NO the size of the Perl module output will be much smaller 
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY         = YES
-
-# The names of the make variables in the generated doxyrules.make file 
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
-# This is useful so different doxyrules.make files included by the same 
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
-# evaluate all C-preprocessor directives found in the sources and include 
-# files.
-
-ENABLE_PREPROCESSING   = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
-# names in the source code. If set to NO (the default) only conditional 
-# compilation will be performed. Macro expansion can be done in a controlled 
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION        = YES
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
-# then the macro expansion is limited to the macros specified with the 
-# PREDEFINED and EXPAND_AS_PREDEFINED tags.
-
-EXPAND_ONLY_PREDEF     = YES
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES        = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that 
-# contain include files that are not input files but should be processed by 
-# the preprocessor.
-
-INCLUDE_PATH           = 
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
-# patterns (like *.h and *.hpp) to filter out the header-files in the 
-# directories. If left blank, the patterns specified with FILE_PATTERNS will 
-# be used.
-
-INCLUDE_FILE_PATTERNS  = 
-
-# The PREDEFINED tag can be used to specify one or more macro names that 
-# are defined before the preprocessor is started (similar to the -D option of 
-# gcc). The argument of the tag is a list of macros of the form: name 
-# or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed. To prevent a macro definition from being 
-# undefined via #undef or recursively expanded use the := operator 
-# instead of the = operator.
-
-PREDEFINED             = HAVE_DLFCN_H \
-                         CPL_DLL \
-                         CPL_STDCALL \
-                         CPL_C_START \
-                         CPL_C_END \
-                         __cplusplus \
-                         DOXYGEN_SKIP
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
-# this tag can be used to specify a list of macro names that should be expanded. 
-# The macro definition that is found in the sources will be used. 
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED      = 
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
-# doxygen's preprocessor will remove all function-like macros that are alone 
-# on a line, have an all uppercase name, and do not end with a semicolon. Such 
-# function macros are typically used for boiler-plate code, and will confuse 
-# the parser if not removed.
-
-SKIP_FUNCTION_MACROS   = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references   
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles. 
-# Optionally an initial location of the external documentation 
-# can be added for each tagfile. The format of a tag file without 
-# this location is as follows: 
-#   TAGFILES = file1 file2 ... 
-# Adding location for the tag files is done as follows: 
-#   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen 
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES               = 
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE       = 
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
-# in the class index. If set to NO only the inherited external classes 
-# will be listed.
-
-ALLEXTERNALS           = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
-# in the modules index. If set to NO, only the current project's groups will 
-# be listed.
-
-EXTERNAL_GROUPS        = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script 
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH              = /usr/local/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
-# or super classes. Setting the tag to NO turns the diagrams off. Note that 
-# this option is superseded by the HAVE_DOT option below. This is only a 
-# fallback. It is recommended to install and use dot, since it yields more 
-# powerful graphs.
-
-CLASS_DIAGRAMS         = YES
-
-# If set to YES, the inheritance and collaboration graphs will hide 
-# inheritance and usage relations if the target is undocumented 
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS   = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
-# available from the path. This tool is part of Graphviz, a graph visualization 
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT               = NO
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect inheritance relations. Setting this tag to YES will force the 
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH            = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect implementation dependencies (inheritance, containment, and 
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH    = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
-# collaboration diagrams in a style similar to the OMG's Unified Modeling 
-# Language.
-
-UML_LOOK               = NO
-
-# If set to YES, the inheritance and collaboration graphs will show the 
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS     = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
-# tags are set to YES then doxygen will generate a graph for each documented 
-# file showing the direct and indirect include dependencies of the file with 
-# other documented files.
-
-INCLUDE_GRAPH          = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
-# documented header file showing the documented files that directly or 
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH      = YES
-
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
-# generate a call dependency graph for every global function or class method. 
-# Note that enabling this option will significantly increase the time of a run. 
-# So in most cases it will be better to enable call graphs for selected 
-# functions only using the \callgraph command.
-
-CALL_GRAPH             = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY    = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
-
-DOT_IMAGE_FORMAT       = png
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be 
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH               = 
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that 
-# contain dot files that are included in the documentation (see the 
-# \dotfile command).
-
-DOTFILE_DIRS           = 
-
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_WIDTH    = 1024
-
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_HEIGHT   = 1024
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
-# graphs generated by dot. A depth value of 3 means that only nodes reachable 
-# from the root by following a path via at most 3 edges will be shown. Nodes 
-# that lay further from the root node will be omitted. Note that setting this 
-# option to 1 or 2 may greatly reduce the computation time needed for large 
-# code bases. Also note that a graph may be further truncated if the graph's 
-# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
-# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
-# the graph is not depth-constrained.
-
-MAX_DOT_GRAPH_DEPTH    = 0
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
-# generate a legend page explaining the meaning of the various boxes and 
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND        = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
-# remove the intermediate dot files that are used to generate 
-# the various graphs.
-
-DOT_CLEANUP            = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE           = NO
+# Doxyfile 1.4.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = RU
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = Russian
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+#USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+#DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = .
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS          = *.h \
+                         *.cpp \
+                         *.c \
+                         *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            =
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            = ../gdal_footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+#HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           =
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .1
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             = HAVE_DLFCN_H \
+                         CPL_DLL \
+                         CPL_STDCALL \
+                         CPL_C_START \
+                         CPL_C_END \
+                         __cplusplus \
+                         DOXYGEN_SKIP
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/local/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+#MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+#MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/doc/ru/gdal_datamodel_ru.dox b/doc/ru/gdal_datamodel_ru.dox
index 08186e7..147cb62 100644
--- a/doc/ru/gdal_datamodel_ru.dox
+++ b/doc/ru/gdal_datamodel_ru.dox
@@ -1,6 +1,6 @@
 #ifndef DOXYGEN_SKIP
 /*
-$Id: gdal_datamodel_ru.dox 30822 2015-10-03 22:38:55Z bishop $
+$Id: gdal_datamodel_ru.dox 35221 2016-08-27 23:28:41Z goatbar $
 Translation corresponds to gdal_datamodel.dox 14550 2008-05-28 10:55:15Z
 Translator Andrey Kiselev <dron at remotesensing.org>
 Translator Dmitry Baryshnikov <polimax at mail.ru>
@@ -25,7 +25,7 @@ Translator Dmitry Baryshnikov <polimax at mail.ru>
 ключ/значение в текстовом виде.
 
 Заметим, что набор данных GDAL и модель растровых каналов изначально
-базируется на спецификации регулярных покрытий консорциума OpenGIS. 
+базируется на спецификации регулярных покрытий консорциума OpenGIS.
 
 \subsection gdal_datamodel_ru_dataset_cs Система координат
 
@@ -33,17 +33,17 @@ Translator Dmitry Baryshnikov <polimax at mail.ru>
 (Well Known Text). Такая строка может содержать:
 
 <ul>
-<li> Общее название координатной системы. 
-<li> Название географической координатной системы. 
-<li> Идентификатор системы координат. 
-<li> Название эллипсоида, большая полуось, сжатие. 
-<li> Название начального меридиана и его смещение относительно Гринвичского. 
+<li> Общее название координатной системы.
+<li> Название географической координатной системы.
+<li> Идентификатор системы координат.
+<li> Название эллипсоида, большая полуось, сжатие.
+<li> Название начального меридиана и его смещение относительно Гринвичского.
 <li> Название проекции (например, Transverse Mercator).
-<li> Список параметров проекции (например, положение осевого меридиана). 
-<li> Название единиц измерения и множитель для перехода к метрам или радианам. 
-<li> Названия и порядок следования координатных осей. 
+<li> Список параметров проекции (например, положение осевого меридиана).
+<li> Название единиц измерения и множитель для перехода к метрам или радианам.
+<li> Названия и порядок следования координатных осей.
 <li> Коды для вышеперечисленных параметров по предопределённым таблицам,
-таким, как таблицы EPSG. 
+таким, как таблицы EPSG.
 </ul>
 
 Дополнительные сведения об определениях координатных систем с помощью строк
@@ -58,14 +58,14 @@ OpenGIS WKT и способах работы с ними можно найти 
 описывает геодезические координаты наземных контрольных точек, список которых
 даёт метод GDALDataset::GetGCPs().
 
-Заметим, что пустая строка (""), возвращаемая в качестве определения координатной системы, означает отсутствие информации о координатной системе.  
+Заметим, что пустая строка (""), возвращаемая в качестве определения координатной системы, означает отсутствие информации о координатной системе.
 
 \subsection gdal_datamodel_ru_dataset_gtm Аффинное преобразование геодезических координат
 
 Существует два способа задать связь между точками растра (в терминах
 строка/столбец) и геодезическими координатами. Первый и наиболее часто
 используемый --- это аффинное преобразование. Второй предполагает
-использование наземных контрольных точек.  
+использование наземных контрольных точек.
 
 Матрица аффинного преобразования состоит из шести коэффициентов, возвращаемых методом GDALDataset::GetGeoTransform(), которая отображает строку/столбец в пространство геодезических координат по следующему соотношению:
 
@@ -79,7 +79,7 @@ OpenGIS WKT и способах работы с ними можно найти 
 его высоте. Координаты (GT(0),GT(3)) задают положение верхнего левого угла
 верхнего левого пиксела растра.
 
-Заметим, что координаты строка/столбец могут принимать значения от (0.0,0.0) в верхнем левом углу верхнего левого пиксела до (ширина_в пикселах,высота_в_пикселах) в правом нижнем углу правого нижнего пиксела. Положение центра верхнего левого пиксела в терминах строка/столбец будет, таким образом, (0.5,0.5). 
+Заметим, что координаты строка/столбец могут принимать значения от (0.0,0.0) в верхнем левом углу верхнего левого пиксела до (ширина_в пикселах,высота_в_пикселах) в правом нижнем углу правого нижнего пиксела. Положение центра верхнего левого пиксела в терминах строка/столбец будет, таким образом, (0.5,0.5).
 
 \subsection gdal_datamodel_ru_dataset_gcp Наземные контрольные точки (Ground Control Points, GCPs)
 
@@ -92,7 +92,7 @@ GDAL_GCP) содержит следующее:
 <pre>
 typedef struct
 {
-    char	*pszId; 
+    char	*pszId;
     char	*pszInfo;
     double 	dfGCPPixel;
     double	dfGCPLine;
@@ -111,11 +111,11 @@ typedef struct
 
 Координаты (dfGCPPixel, dfGCPLine) задают положение точки на растре.
 Координаты (dfGCPX, dfGCPY, dfGCPZ) задают соответствующую привязку точки к
-геодезическим координатам (координата Z часто бывает нулём). 
+геодезическим координатам (координата Z часто бывает нулём).
 
 Модель данных GDAL не содержит механизма преобразования, получаемого из
 контрольных точек, --- это оставлено для приложений более высокого уровня.
-Обычно для этого применяются полиномы от 1-го до 5-го порядка. 
+Обычно для этого применяются полиномы от 1-го до 5-го порядка.
 
 Обычно набор данных содержит либо аффинное преобразование, либо контрольные точки, либо ничего. В редких случаях может присутствовать и то, и другое, тогда не определено, какой из способов имеет преимущество.
 
@@ -125,11 +125,11 @@ typedef struct
 Их состав определяется форматом хранения данных и приложением. Ключи должны
 быть "правильными" лексемами (без пробельных и специальных символов). Значения
 могут иметь любую длину и содержать любые символы, за исключением нулевого
-символа ASCII.  
+символа ASCII.
 
 Механизм управления метаданными плохо оптимизирован для работы с очень
 большими блоками данных. Однако работа с метаданными, превышающими в размере
-100KiB скорее всего приведёт к снижению производительности. 
+100KiB скорее всего приведёт к снижению производительности.
 
 Некоторые форматы данных содержат собственную базу метаданных, драйверы других
 форматов могут отображать поля, специфичные для данного формата, в записи базы
@@ -162,7 +162,7 @@ TIFFTAG_DATETIME=1999:05:11 11:29:56
 наборе данных. При таком способе указания отсутствия данных пиксель считается
 пустым тогда итолько тогда, когда если во всех каналах его значение совпадает
 соответствующему полю в списке NODATA_VALUES. Эта запись пока не очень широко
-используется драйверами, алгоритмами и вспомогательными программами GDAL. 
+используется драйверами, алгоритмами и вспомогательными программами GDAL.
 <li> MATRIX_REPRESENTATION: Показывает, в каком виде представлены матричные
 данные. Используется для наборов данных поляризационных радиолокаторов с
 синтезированной апертурой (Polarimetric SAR). Может принимать следующие
@@ -204,7 +204,7 @@ Covariance_13, Covariance_23 (поскольку сама матрица Эрм
 Домен SUBDATASETS содержит список дочерних наборов данных. Обычно он
 используется для получения указателей на изображения, хранящиеся все вместе в
 едином файле (таком, как HDF или NITF). Например, файл формата NITF с двумя
-изображениями может иметь следующий список вложенных наборов данных: 
+изображениями может иметь следующий список вложенных наборов данных:
 
 <pre>
   SUBDATASET_1_NAME=NITF_IM:0:multi_1b.ntf
@@ -219,11 +219,11 @@ GDALOpen() для получения доступа к изображению. 
 показана пользователю для облегчения выбора.
 
 Драйверы, которые поддерживают дочерние наборы данных сообщают об этом через значение
-DMD_SUBDATASETS. Данные выводятся при передаче ключей \-\-format and \-\-formats  
+DMD_SUBDATASETS. Данные выводятся при передаче ключей \-\-format and \-\-formats
 в утилиты командной строки.
 
-На текущий момент дочерние наборы поддерживают следующие драйверы: 
-ADRG, ECRGTOC, GEORASTER, GTiff, HDF4, HDF5, netCDF, NITF, NTv2, OGDI, PDF, 
+На текущий момент дочерние наборы поддерживают следующие драйверы:
+ADRG, ECRGTOC, GEORASTER, GTiff, HDF4, HDF5, netCDF, NITF, NTv2, OGDI, PDF,
 PostGISRaster, Rasterlite, RPFTOC, RS2, WCS, и WMS.
 
 \subsubsection gdal_datamodel_ru_image_structure Домен структуры изображения (IMAGE_STRUCTURE)
@@ -237,15 +237,15 @@ PostGISRaster, Rasterlite, RPFTOC, RS2, WCS, и WMS.
 домен, называемый IMAGE_STRUCTURE, который не должен слепо копироваться в
 другие форматы.
 
-В настоящий момент спецификацией 
-<a href="http://trac.osgeo.org/gdal/rfc14_imagestructure">RFC 14</a> 
+В настоящий момент спецификацией
+<a href="http://trac.osgeo.org/gdal/rfc14_imagestructure">RFC 14</a>
 определены следующие специальные записи в домене IMAGE_STRUCTURE.
 
 <ul>
 <li> COMPRESSION: Алгоритм сжатия, используемый для данного набора данных или
 канала. Не существует определённого каталога имён алгоритмов сжатия, однако
 если данный формат поддерживает параметр создания COMPRESSION, точно такой же
-список возможных значений должен быть использован и здесь. 
+список возможных значений должен быть использован и здесь.
 <li> NBITS: Число бит на значение пиксела в канале или во всех каналах данного
 набора данных. Обычно присутствует только в случаях нестандартного числа бит
 для этого типа данных, например, если 1-битовый файл TIFF представлен в GDAL в
@@ -297,17 +297,17 @@ Coefficient). Эта геометрическая модель может быт
 
 \subsubsection gdal_datamodel_ru_imagery Домен метаданных ДДЗ (IMAGERY)
 
-Для материалов воздушной или космической съемки может быть задан домен IMAGERY. 
+Для материалов воздушной или космической съемки может быть задан домен IMAGERY.
 Наличие такого домена зависит от специальных файлов метаданных, которые обычно
-размещаются рядом с файлом изображения. Файлы метаданных передаются в классы 
+размещаются рядом с файлом изображения. Файлы метаданных передаются в классы
 чтения метаданных, которые, если поддерживают переданные формат, заполняют домен
 следующими величинами:
-   
+
 <ul>
 <li>  SATELLITEID: Название КА или аппаратуры наблюдения
 <li>  CLOUDCOVER: Облачность. Значение между 0 - 100 или 999 при отсутствии
 <li>  ACQUISITIONDATETIME: Дата и время съемки в UTC
-</ul>  
+</ul>
 
 \subsubsection gdal_datamodel_ru_xml Домены "xml:"
 
@@ -320,23 +320,23 @@ Coefficient). Эта геометрическая модель может быт
 Растровый канал описывается в GDAL с помощью класса GDALRasterBand. Он не
 обязательно должен представлять всё изображение. Например, 24-битное
 RGB-изображение должно быть представлено как набор данных с тремя каналами, по
-одному для красной, зелёной и синей компоненты. 
+одному для красной, зелёной и синей компоненты.
 
 Растровый канал имеет следующие свойства:
 
 <ul>
 
-<li> Ширина и высота в пикселах и строках. Они будут теми же самыми, что и для всего набора данных, если это канал в полном разрешении. 
+<li> Ширина и высота в пикселах и строках. Они будут теми же самыми, что и для всего набора данных, если это канал в полном разрешении.
 
 <li> Тип данных (GDALDataType). Один из вещественных (Byte, UInt16, Int16,
 UInt32, Int32, Float32, Float64), или комплексных типов CInt16, CInt32,
 CFloat32, and CFloat64.
 
-<li> Размер блока. Предпочтительный (наиболее эффективный) размер блока данных для считывания. Для изображений, хранящихся построчно, это в большинстве случаев будет одна строка. 
+<li> Размер блока. Предпочтительный (наиболее эффективный) размер блока данных для считывания. Для изображений, хранящихся построчно, это в большинстве случаев будет одна строка.
 
 <li> Список метаданных в виде пар ключ/значение в том же формате, что и для всего набора данных, но содержащих информацию, специфичную для данного канала.
 
-<li> Необязательная строка описания. 
+<li> Необязательная строка описания.
 
 <li> Необязательный маркер отсутсвия данных (см. также запись метаданных
 NODATA_VALUES для набора данных, содержащий маркеры отсутствия данных для
@@ -344,23 +344,23 @@ NODATA_VALUES для набора данных, содержащий марке
 
 <li> Необязательный канал маски, маркирующий пикселы, в которых данные
 отсутствуют или прозрачны. См. обсуждение
-<a href="http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask">RFC 15: Band 
+<a href="http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask">RFC 15: Band
 Masks</a>.
 
 <li> Необязательный список категорий (например, названий классов на
-тематической карте).  
+тематической карте).
 
-<li> Необязательные минимальное и максимальное значение. 
+<li> Необязательные минимальное и максимальное значение.
 
 <li> Необязательные калибровочные коэффициенты для пересчёта значений растра в
-физические величины (например, перевод отсчётов высоты в метры). 
+физические величины (например, перевод отсчётов высоты в метры).
 
 <li> Необязательное название единиц измерения. Например, это поле может
 содержать единицы измерения высоты для модели рельефа.
 
 <li> Цветовая интерпретация канала. Одна из:
 
-  <ul> 
+  <ul>
   <li> GCI_Undefined: по умолчанию, не определено.
   <li> GCI_GrayIndex: одиночное изображение в оттенках серого.
   <li> GCI_PaletteIndex: изображение с цветовой палитрой.
@@ -377,9 +377,9 @@ Masks</a>.
   <li> GCI_BlackBand: чёрная компонента CMY- или CMYK-изображения.
   </ul>
 
-<li> Таблица цветов (палитра), которая будет подробно описана ниже. 
+<li> Таблица цветов (палитра), которая будет подробно описана ниже.
 
-<li> Информация об уменьшенных обзорных изображениях (пирамидах). 
+<li> Информация об уменьшенных обзорных изображениях (пирамидах).
 
 </ul>
 
@@ -392,32 +392,32 @@ Masks</a>.
 typedef struct
 {
     /- серый, красный, голубой или цвет -/
-    short      c1;      
+    short      c1;
 
-    /- зелёный, пурпурный или яркость -/    
-    short      c2;      
+    /- зелёный, пурпурный или яркость -/
+    short      c2;
 
     /- синий, жёлтый или насыщенность -/
-    short      c3;      
+    short      c3;
 
     /- альфа-канал или чёрный -/
-    short      c4;      
+    short      c4;
 } GDALColorEntry;
 </pre>
 
 Таблица цветов также имеет индикатор интерпретации (GDALPaletteInterp),
 который указывает на то, как параметры c1/c2/c3/c4 должны быть
 проинтерпретированы приложением. Этот индикатор может принимать следующие
-значения: 
+значения:
 
 <ul>
 <li> GPI_Gray: Считать c1 значением в градациях серого.
 <li> GPI_RGB: Считать c1 красным, c2 зелёным, c3 синим, а c4 --- альфа-каналом.
-<li> GPI_CMYK: Считать c1 голубым, c2 пурпурным, c3 жёлтым, c4 чёрным. 
-<li> GPI_HLS: Считать c1 цветом, c2 яркостью, c3 насыщенностью. 
+<li> GPI_CMYK: Считать c1 голубым, c2 пурпурным, c3 жёлтым, c4 чёрным.
+<li> GPI_HLS: Считать c1 цветом, c2 яркостью, c3 насыщенностью.
 </ul>
 
-Для связывания цвета с пикселем значение этого пиксела используется в качестве индекса в таблице цветов. Это значит, что цвета всегда располагаются в таблице начиная с нулевого индекса и далее по возрастанию. Не существует механизма для предварительного масштабирования значений, прежде, чем будет применена таблица цветов. 
+Для связывания цвета с пикселем значение этого пиксела используется в качестве индекса в таблице цветов. Это значит, что цвета всегда располагаются в таблице начиная с нулевого индекса и далее по возрастанию. Не существует механизма для предварительного масштабирования значений, прежде, чем будет применена таблица цветов.
 
 \section gdal_datamodel_ru_rasterband_overviews Обзорные изображения
 
@@ -425,13 +425,13 @@ typedef struct
 представлено в виде отдельного канала GDALRasterBand. Размер обзорного
 изображения (в терминах строк и столбцов) будет отличаться от базового
 полноразмерного растра, однако географически они будут покрывать один и тот же
-регион.  
+регион.
 
 Обзорные изображения применяются для быстрого отображения уменьшенных копий
 растра, вместо того, чтобы читать полноразмерное изображение с последующим
-масштабированием. 
+масштабированием.
 
-Канал также обладает свойством HasArbitraryOverviews, которое равно TRUE, если растр может быть эффективно прочитан в любом разрешении, но не имеет чётких пирамидальных слоёв. Такими свойствами обладают некоторые алгоритмы кодирования изображений с помощью БПФ и вейвлетов, а также изображения, получаемые из внешних источников (таких, как OGDI), когда масштабирование производится на удалённой стороне. 
+Канал также обладает свойством HasArbitraryOverviews, которое равно TRUE, если растр может быть эффективно прочитан в любом разрешении, но не имеет чётких пирамидальных слоёв. Такими свойствами обладают некоторые алгоритмы кодирования изображений с помощью БПФ и вейвлетов, а также изображения, получаемые из внешних источников (таких, как OGDI), когда масштабирование производится на удалённой стороне.
 
 */
 
diff --git a/doc/ru/gdal_tutorial_ru.dox b/doc/ru/gdal_tutorial_ru.dox
index 104e02d..26ef11f 100644
--- a/doc/ru/gdal_tutorial_ru.dox
+++ b/doc/ru/gdal_tutorial_ru.dox
@@ -1,5 +1,5 @@
 /*
-$Id: gdal_tutorial_ru.dox 30780 2015-10-01 10:42:39Z bishop $
+$Id: gdal_tutorial_ru.dox 35222 2016-08-28 06:06:11Z goatbar $
 Translation corresponds to gdal_tutorial.dox 14528 2008-05-26 03:07:21Z
 Translator Andrey Kiselev <dron at remotesensing.org>
 Translator Dmitry Baryshnikov <polimax at mail.ru>
@@ -105,10 +105,10 @@ GDAL</a>, набор данных GDALDataset содержит список ра
     double        adfGeoTransform[6];
 
     printf( "Драйвер: %s/%s\n",
-            poDataset->GetDriver()->GetDescription(), 
+            poDataset->GetDriver()->GetDescription(),
             poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );
 
-    printf( "Размер %dx%dx%d\n", 
+    printf( "Размер %dx%dx%d\n",
             poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
             poDataset->GetRasterCount() );
 
@@ -136,7 +136,7 @@ GDAL</a>, набор данных GDALDataset содержит список ра
             GDALGetDriverLongName( hDriver ) );
 
     printf( "Размер %dx%dx%d\n",
-	    GDALGetRasterXSize( hDataset ), 
+	    GDALGetRasterXSize( hDataset ),
             GDALGetRasterYSize( hDataset ),
             GDALGetRasterCount( hDataset ) );
 
@@ -160,7 +160,7 @@ GDAL</a>, набор данных GDALDataset содержит список ра
     print 'Размер ',dataset.RasterXSize,'x',dataset.RasterYSize, \
           'x',dataset.RasterCount
     print 'Проекция ',dataset.GetProjection()
-    
+
     geotransform = dataset.GetGeoTransform()
     if not geotransform is None:
 	print 'Начало координат (',geotransform[0], ',',geotransform[3],')'
@@ -181,7 +181,7 @@ GDAL</a>, набор данных GDALDataset содержит список ра
         int             nBlockXSize, nBlockYSize;
         int             bGotMin, bGotMax;
         double          adfMinMax[2];
-	
+
         poBand = poDataset->GetRasterBand( 1 );
 	poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
         printf( "Размер блока %dx%d, тип данных %s, ColorInterp=%s\n",
@@ -196,13 +196,13 @@ GDAL</a>, набор данных GDALDataset содержит список ра
             GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
 
         printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
-        
+
         if( poBand->GetOverviewCount() > 0 )
             printf( "Канал содержит %d обзорных изображений.\n",
 	            poBand->GetOverviewCount() );
 
         if( poBand->GetColorTable() != NULL )
-            printf( "Канал содержит таблицу цветов с %d записями.\n", 
+            printf( "Канал содержит таблицу цветов с %d записями.\n",
                      poBand->GetColorTable()->GetColorEntryCount() );
 \endcode
 
@@ -212,7 +212,7 @@ In C:
         int             nBlockXSize, nBlockYSize;
         int             bGotMin, bGotMax;
         double          adfMinMax[2];
-	
+
         hBand = GDALGetRasterBand( hDataset, 1 );
         GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
         printf( "Размер блока %dx%d, тип данных %s, ColorInterp=%s\n",
@@ -227,13 +227,13 @@ In C:
             GDALComputeRasterMinMax( hBand, TRUE, adfMinMax );
 
         printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
-        
+
         if( GDALGetOverviewCount(hBand) > 0 )
             printf( "Канал содержит %d обзорных изображений.\n",
 	            GDALGetOverviewCount(hBand));
 
         if( GDALGetRasterColorTable( hBand ) != NULL )
-            printf( "Канал содержит таблицу цветов с %d записями.\n", 
+            printf( "Канал содержит таблицу цветов с %d записями.\n",
                      GDALGetColorEntryCount(
                          GDALGetRasterColorTable( hBand ) ) );
 \endcode
@@ -269,8 +269,8 @@ In C:
         int   nXSize = poBand->GetXSize();
 
         pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
-        poBand->RasterIO( GF_Read, 0, 0, nXSize, 1, 
-                          pafScanline, nXSize, 1, GDT_Float32, 
+        poBand->RasterIO( GF_Read, 0, 0, nXSize, 1,
+                          pafScanline, nXSize, 1, GDT_Float32,
                           0, 0 );
 \endcode
 
@@ -282,20 +282,20 @@ In C:
         int   nXSize = GDALGetRasterBandXSize( hBand );
 
         pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
-	GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1, 
-                      pafScanline, nXSize, 1, GDT_Float32, 
+	GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1,
+                      pafScanline, nXSize, 1, GDT_Float32,
                       0, 0 );
 \endcode
 
 Буффер pafScanline должен быть освобожден при помощи CPLFree() после его использования.
 
 На языке Python:
- 
+
 \code
   	scanline = band.ReadRaster( 0, 0, band.XSize, 1, \
                                      band.XSize, 1, GDT_Float32 )
 \endcode
- 
+
 Здесь возвращаемая строка имеет тип string, и содержит xsize*4 байт
 вещественных данных. Эта строка может быть преобразована в базовые типы языка
 Python с помощью модуля <b>struct</b> из стандартной библиотеки:
@@ -306,7 +306,7 @@ Python с помощью модуля <b>struct</b> из стандартной
 	tuple_of_floats = struct.unpack('f' * b2.XSize, scanline)
 \endcode
 
-Вызов функции The RasterIO производится со следующими аргументами: 
+Вызов функции The RasterIO производится со следующими аргументами:
 \code
 CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
                                  int nXOff, int nYOff, int nXSize, int nYSize,
@@ -320,7 +320,7 @@ CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
 для записи, в зависимости от значения флага eRWFlag (GF_Read или GF_Write).
 Аргументы nXOff, nYOff, nXSize, nYSize описывают окно растра для чтения (или
 записи). Это окно необязательно должно совпадать с границами смежных блоков,
-однако считывание может быть более эффективным, если границы совпадают.  
+однако считывание может быть более эффективным, если границы совпадают.
 
 pData --- это указатель на буфер в памяти, куда должны быть прочитаны (или
 откуда записаны) данные. Фактический тип этого буфера должен совпадать с
@@ -351,7 +351,7 @@ pData --- это указатель на буфер в памяти, куда д
 delete языка C++. Наборы данных GDALDataset могут быть закрыты либо с помощью
 вызова функции GDALClose() (настоятельно НЕ рекомендуется использовать оператор
 delete для освобождения GDALDataset для пользователей Windows из-за извесной ошибки
-получения и освобождения памяти через границы модуля. Подробнее см. 
+получения и освобождения памяти через границы модуля. Подробнее см.
 <a href="http://trac.osgeo.org/gdal/wiki/FAQMiscellaneous#HowshouldIdeallocateresourcesacquaintedfromGDALonWindows">раздел</a> в FAQ).
 Вызов GDALClose приведет к правильной очистке и выполнении всех ожидающих операций
 записи.
@@ -446,11 +446,11 @@ CreateCopy(), однако не все поддерживают метод Creat
 
 На языке C++:
 \code
-    GDALDataset *poSrcDS = 
+    GDALDataset *poSrcDS =
        (GDALDataset *) GDALOpen( pszSrcFilename, GA_ReadOnly );
     GDALDataset *poDstDS;
 
-    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE, 
+    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
                                     NULL, NULL, NULL );
     if( poDstDS != NULL )
         delete poDstDS;
@@ -461,7 +461,7 @@ CreateCopy(), однако не все поддерживают метод Creat
     GDALDatasetH hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
     GDALDatasetH hDstDS;
 
-    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE, 
+    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE,
                              NULL, NULL, NULL );
     if( hDstDS != NULL )
         GDALClose( hDstDS );
@@ -493,12 +493,12 @@ CreateCopy(), показывает, что CreateCopy() должен завер
 #include "cpl_string.h"
 ...
     char **papszOptions = NULL;
-    
+
     papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
     papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
-    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE, 
+    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
                                     papszOptions, GDALTermProgress, NULL );
-    
+
     /* Once we're done, close properly the dataset */
     if( poDstDS != NULL )
         delete poDstDS;
@@ -510,12 +510,12 @@ CreateCopy(), показывает, что CreateCopy() должен завер
 #include "cpl_string.h"
 ...
     char **papszOptions = NULL;
-    
+
     papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
     papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
-    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE, 
+    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE,
                              papszOptions, GDALTermProgres, NULL );
-    /* Once we're done, close properly the dataset */                         
+    /* Once we're done, close properly the dataset */
     if( hDstDS != NULL )
         GDALClose( hDstDS );
     CSLDestroy( papszOptions );
@@ -525,11 +525,11 @@ CreateCopy(), показывает, что CreateCopy() должен завер
 
 \code
     src_ds = gdal.Open( src_filename )
-    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0, 
+    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0,
                                 [ 'TILED=YES', 'COMPRESS=PACKBITS' ] )
     # Once we're done, close properly the dataset
     dst_ds = None
-    src_ds = None                                
+    src_ds = None
 \endcode
 
 \section gdal_tutorial_ru_create Использование метода Create()
@@ -543,19 +543,19 @@ CreateCopy(), показывает, что CreateCopy() должен завер
 
 На языке C++:
 \code
-    GDALDataset *poDstDS;	
+    GDALDataset *poDstDS;
     char **papszOptions = NULL;
 
-    poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte, 
+    poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte,
                                 papszOptions );
 \endcode
 
 На языке C:
 \code
-    GDALDatasetH hDstDS;	
+    GDALDatasetH hDstDS;
     char **papszOptions = NULL;
 
-    hDstDS = GDALCreate( hDriver, pszDstFilename, 512, 512, 1, GDT_Byte, 
+    hDstDS = GDALCreate( hDriver, pszDstFilename, 512, 512, 1, GDT_Byte,
                          papszOptions );
 \endcode
 
@@ -576,7 +576,7 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     GByte abyRaster[512*512];
 
     poDstDS->SetGeoTransform( adfGeoTransform );
-    
+
     oSRS.SetUTM( 11, TRUE );
     oSRS.SetWellKnownGeogCS( "NAD27" );
     oSRS.exportToWkt( &pszSRS_WKT );
@@ -584,8 +584,8 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     CPLFree( pszSRS_WKT );
 
     poBand = poDstDS->GetRasterBand(1);
-    poBand->RasterIO( GF_Write, 0, 0, 512, 512, 
-                      abyRaster, 512, 512, GDT_Byte, 0, 0 );    
+    poBand->RasterIO( GF_Write, 0, 0, 512, 512,
+                      abyRaster, 512, 512, GDT_Byte, 0, 0 );
 
     /* Once we're done, close properly the dataset */
     GDALClose( (GDALDatasetH) poDstDS );
@@ -603,7 +603,7 @@ CreateCopy(), показывает, что CreateCopy() должен завер
 
     hSRS = OSRNewSpatialReference( NULL );
     OSRSetUTM( hSRS, 11, TRUE );
-    OSRSetWellKnownGeogCS( hSRS, "NAD27" );			
+    OSRSetWellKnownGeogCS( hSRS, "NAD27" );
     OSRExportToWkt( hSRS, &pszSRS_WKT );
     OSRDestroySpatialReference( hSRS );
 
@@ -611,8 +611,8 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     CPLFree( pszSRS_WKT );
 
     hBand = GDALGetRasterBand( hDstDS, 1 );
-    GDALRasterIO( hBand, GF_Write, 0, 0, 512, 512, 
-                  abyRaster, 512, 512, GDT_Byte, 0, 0 );    
+    GDALRasterIO( hBand, GF_Write, 0, 0, 512, 512,
+                  abyRaster, 512, 512, GDT_Byte, 0, 0 );
 
     /* Once we're done, close properly the dataset */
     GDALClose( hDstDS );
@@ -625,13 +625,13 @@ CreateCopy(), показывает, что CreateCopy() должен завер
     import numpy
 
     dst_ds.SetGeoTransform( [ 444720, 30, 0, 3751320, 0, -30 ] )
-    
+
     srs = osr.SpatialReference()
     srs.SetUTM( 11, 1 )
     srs.SetWellKnownGeogCS( 'NAD27' )
     dst_ds.SetProjection( srs.ExportToWkt() )
 
-    raster = numpy.zeros( (512, 512), dtype=numpy.uint8 )    
+    raster = numpy.zeros( (512, 512), dtype=numpy.uint8 )
     dst_ds.GetRasterBand(1).WriteArray( raster )
 
     # Once we're done, close properly the dataset
@@ -640,7 +640,7 @@ CreateCopy(), показывает, что CreateCopy() должен завер
 
 \htmlonly
 <p>
-$Id: gdal_tutorial_ru.dox 30780 2015-10-01 10:42:39Z bishop $
+$Id: gdal_tutorial_ru.dox 35222 2016-08-28 06:06:11Z goatbar $
 </p>
 \endhtmlonly
 
diff --git a/doc/ru/index_ru.dox b/doc/ru/index_ru.dox
index c33cad9..c648668 100644
--- a/doc/ru/index_ru.dox
+++ b/doc/ru/index_ru.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: index_ru.dox 32998 2016-01-15 14:46:13Z bishop $ */
+/* $Id: index_ru.dox 35222 2016-08-28 06:06:11Z goatbar $ */
 Translation corresponds to index.dox 14537 2008-05-27 17:12:02Z
 Translator Andrey Kiselev <dron at ak4719.spb.edu>
 Translator Dmitry Baryshnikov <polimax at mail.ru>
@@ -122,9 +122,9 @@ or <a href="http://home.gdal.org/projects/opengis/wkt_prop.doc">doc</a> format.
 \htmlonly
 <table border="0" cellspacing="4" cellpadding="4">
 
-<tr><td><a href="http://2016.foss4g.org/"> 
-<img src="http://wiki.osgeo.org/images/f/ff/Foss4g2016_logo_squared.png" alt="FOSS4G 2016" border="0"> 
-</a></td> 
+<tr><td><a href="http://2016.foss4g.org/">
+<img src="http://wiki.osgeo.org/images/f/ff/Foss4g2016_logo_squared.png" alt="FOSS4G 2016" border="0">
+</a></td>
 
 <td><a href="http://2016.foss4g.org">FOSS4G 2016</a> основная ежегодная
 конференция разработчиков открытого и свободного географического программного
@@ -158,7 +158,7 @@ http://news.gmane.org/gmane.comp.gis.gdal.devel</a>.
 Архив начиная с 2005 года доступен на <a href="http://osgeo-org.1560.n6.nabble.com/GDAL-Dev-f3742093.html">Nabble</a>.<p>
 
 Многих пользователей и разработчиков GDAL/OGR часто можно найти на IRC канале
-<a href="irc:irc.freenode.net/#gdal">#gdal</a> сервера irc.freenode.net.<p>
+<a href="irc:irc.freenode.net/#gdal">\#gdal</a> сервера irc.freenode.net.<p>
 
 \section index_bugs_ru Отчёты об ошибках
 
diff --git a/doc/sponsorship.dox b/doc/sponsorship.dox
index 0465ddc..379bc0c 100644
--- a/doc/sponsorship.dox
+++ b/doc/sponsorship.dox
@@ -1,26 +1,26 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: sponsorship.dox 32092 2015-12-08 14:54:56Z goatbar $ */
+/* $Id: sponsorship.dox 35221 2016-08-27 23:28:41Z goatbar $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
 \page sponsorship Sponsoring GDAL/OGR
 
-Development and maintenance of GDAL/OGR is supported by organizations 
-contracting developers, organizations contributing improvements, users 
+Development and maintenance of GDAL/OGR is supported by organizations
+contracting developers, organizations contributing improvements, users
 contributing improvements, and volunteers.  Generally speaking this works
 well, and GDAL/OGR has improved substantially over the years.
 
 However, there are still many tasks which do not receive the attention they
-should.  Processing bug reports, writing documentation, writing test scripts, 
-evaluating test script failures and user support often receive less 
+should.  Processing bug reports, writing documentation, writing test scripts,
+evaluating test script failures and user support often receive less
 attention than would be desired.  Some new features of broad interest are
 not implemented because they aren't important enough to any one person or
 organization.
 
 In order to provide sustained funding to support the maintenance, improvement
-and promotion of the GDAL/OGR project, the project seeks project sponsors to 
-provide financial support.  Sponsorship would be accomplished via the 
-<a href="http://wiki.osgeo.org/index.php/Project_Sponsorship">OSGeo 
+and promotion of the GDAL/OGR project, the project seeks project sponsors to
+provide financial support.  Sponsorship would be accomplished via the
+<a href="http://wiki.osgeo.org/index.php/Project_Sponsorship">OSGeo
 Project Sponsorship</a> program.  Funds are held by OSGeo for disposition
 on behalf of the project, and dispersed at the discretion of the GDAL/OGR
 Project Steering Committee.
@@ -32,16 +32,16 @@ on a contract basis.  The responsibilities would include:
 
 <ul>
 <li> Addressing bug reports - reproducing then fixing or passing on to another developer.
-<li> Extending, and running the test suite. 
+<li> Extending, and running the test suite.
 <li> Improving documentation.
-<li> Other improvements to the software. 
-<li> General user support on the mailing list. 
+<li> Other improvements to the software.
+<li> General user support on the mailing list.
 </ul>
 
-Sponsorship funds may also be used to contract for specific improvements to 
-GDAL, provision of resources such as web hosting, funding code sprints, 
+Sponsorship funds may also be used to contract for specific improvements to
+GDAL, provision of resources such as web hosting, funding code sprints,
 or funding project promotion.  Decisions on spending of sponsorship funds
-will be made by the GDAL/OGR Project Steering Committee. 
+will be made by the GDAL/OGR Project Steering Committee.
 
 \section ss_benefits Sponsorship Benefits
 
@@ -50,28 +50,28 @@ Sponsoring GDAL/OGR provides the following benefits:
 <ol>
 <li> Ensures the sustainability and health of the GDAL/OGR project.
 <li> All sponsors will be listed on the project <a href="credits.html">
-Credits</a> page, ordered by contribution class (Platinum, Gold, Silver) 
-with a link back to the sponsor.  Silver sponsors and above may include a 
+Credits</a> page, ordered by contribution class (Platinum, Gold, Silver)
+with a link back to the sponsor.  Silver sponsors and above may include a
 logo.  Platinum sponsors may also have a logo appearing on the OSGeo main
-page. 
-<li> Sponsors will be permitted to indicate they are project sponsors 
-in web and other promotional materials, and use the GDAL/OGR logo. 
+page.
+<li> Sponsors will be permitted to indicate they are project sponsors
+in web and other promotional materials, and use the GDAL/OGR logo.
 <li> Sponsor input on project focus and direction will be solicited via a
 survey.
-<li> Sponsors will received a degree of priority in processing of 
+<li> Sponsors will received a degree of priority in processing of
 bug reports by any maintainer hired with sponsorship funds.
 <li> Sponsors will receive a detailed report annually on the use of
-sponsorship funds. 
+sponsorship funds.
 </ol>
 
 \section ss_levels Sponsorship Process
 
-Sponsors can sponsor GDAL for any amount of money of at least $500 USD.  
+Sponsors can sponsor GDAL for any amount of money of at least $500 USD.
 At or above the following levels a sponsor will be designated as being one
 of the following class:
 
 <ol>
-<li> $27000+ USD: Platinum Sponsor				
+<li> $27000+ USD: Platinum Sponsor
 <li> $9000+ USD: Gold Sponsor
 <li> $3000+ USD: Silver Sponsor
 </ol>
@@ -82,12 +82,12 @@ and sponsorships will be eligible as a charitable contribution for US
 taxpayers.  Appropriate receipts can be issued when needed.
 
 Organizations or individuals interested in sponsoring the GDAL/OGR project
-should contact Frank Warmerdam (warmerdam at pobox.com, +1 650 701-7823) with 
-questions, or to make arrangements.  
+should contact Frank Warmerdam (warmerdam at pobox.com, +1 650 701-7823) with
+questions, or to make arrangements.
 
 \htmlonly
 <p>
-$Id: sponsorship.dox 32092 2015-12-08 14:54:56Z goatbar $
+$Id: sponsorship.dox 35221 2016-08-27 23:28:41Z goatbar $
 </p>
 \endhtmlonly
 
diff --git a/doc/vb6_tutorial.dox b/doc/vb6_tutorial.dox
deleted file mode 100644
index d8e9ad0..0000000
--- a/doc/vb6_tutorial.dox
+++ /dev/null
@@ -1,528 +0,0 @@
-#ifndef DOXYGEN_SKIP
-/* $Id: vb6_tutorial.dox 13528 2008-01-14 19:37:42Z warmerdam $ */
-#endif /* DOXYGEN_SKIP */
-
-/*!
-\page vb6_tutorial GDAL VB6 Bindings Tutorial
-
-\section Intro Introduction
-
-A partial set of Visual Basic 6 bindings have been build for GDAL.  Internally 
-these bindings use Declare based calls into the GDAL DLL C API but a set of
-shadow classes are also provided to provide object oriented access to 
-GDAL services in VB6 similar to those provided in C++. 
-
-Note that the VB6 bindings are nowhere near comprehensive, nor are they 
-documented.  However, in combination with the corresponding C++ class
-documentation, and the following docs, it should be possible to use GDAL 
-to accomplish a variety of operations.  It is not believed that the VB6
-bindings will be of any utility with earlier version of VB nor with VB.Net. 
-
-The classes for which access has been implemented includes 
-GDALDriver, GDALDataset, GDALRasterBand, GDALColorTable, OGRSpatialReference
-and OGRCoordinateTransformation.
-
-A mailing list specifically on VB6 GDAL topics has been setup at
-http://groups.yahoo.com/group/gdal-vb6-appdev .
-
-\section UsingVB6 Using GDAL VB6 Classes
-
-To use VB6 GDAL bindings it is necessary to ensure that GDAL has been
-built with appropriate C entry points exported using the "stdcall" calling
-convention.  This is the current default, but was not as recently as GDAL
-1.2.6.  So ensure you get a version more recent than 1.2.6.  
-
-Then add the GDAL VB6 class and module files to your VB6 project.  These
-come from the <a href="http://svn.osgeo.org/gdal/trunk/gdal/vb6">gdal/vb6 directory</a>
-and include the following key files:
-
-<ul>
-<li> GDAL.bas - The main user visible module. 
-<li> GDALCore.bas - This module is for internal use. 
-<li> GDALDriver.cls - The GDALDriver class. 
-<li> GDALDataset.cls - The GDALDataset class.
-<li> GDALRasterBand.cls - The GDALRasterBand class. 
-<li> GDALColorTable.cls - The GDALColorTable class.
-<li> OGRSpatialReference.cls - The OGRSpatialReference class. 
-<li> OGRCoordinateTransformation.cls - The OGRCoordinateTransformation class.
-</ul>
-
-You may need to edit GDALCore.bas, and change occurrences of gdal12.dll 
-to match what your GDAL DLL is called.  You can include a full path to the
-DLL if it can't be guaranteed to be in the current working directory of the
-application (or the windows system32 directory).  
-
-You should also be able to load the "test" project from the gdal\\vb6\\test
-directory.  The test project has test menu items roughly corresponding to
-the tasks in the following tutorial topics.  
-
-\section TutorialRead Tutorial - Read Dataset
-
-This brief tutorial will demonstrate open a GDAL file, and fetching out
-some information, about the dataset, and the individual bands.  The
-results are printed to the default from in the following example for 
-simplicity. 
-
-Before opening the file we need to register the GDAL format drivers.
-Normally we will just register all the drivers with GDALAllRegister().
-
-\code
-  Call GDAL.AllRegister()
-\endcode
-
-Then we need to try and open the dataset.  The GDAL.OpenDS() function
-returns a GDALDataset object, so we dimension an appropriate object for
-this.  GDAL.OpenDS() is the VB6 equivalent of the GDALDataset::GDALOpen() 
-function.
-
-\code
-  Dim ds As GDALDataset
-
-  Set ds = GDAL.OpenDS( "utm.tif", GDAL.GA_ReadOnly )
-\endcode
-  
-Then we need to check if the open succeeded, and if not report an error. 
-
-\code
-  If not ds.IsValid() Then
-    Call MsgBox( "Open failed: " & GDAL.GetLastErrorMsg() )
-    Exit Sub
-  End If
-\endcode
-
-If things succeeded, we query width of the image in pixels (XSize),
-Height of the image in pixels (YSize) and number of bands (BandCount)
-from the dataset properties.
-
-\code
-  Print "Size: " & ds.XSize & "x" & ds.YSize & "x" & ds.BandCount
-\endcode
-
-Next we read metadata from the dataset using the VB6 equivalent of the
-GDALMajorObject::GetMetadata() method, and report it to the user.  Metadata
-is returned as an array of strings of "name=value" items.  Array indices 
-start at zero in the returned array.  The domain argument should normally
-be vbNullString though in specialized circumstances other domains might
-apply.
-
-\code
-  Dim MD As Variant
-  MD = ds.GetMetadata(vbNullString)
-  If (UBound(MD) > 0) Then
-    Print "Metadata:"
-    For i = 1 To UBound(MD)
-      Print "  " & MD(i)
-    Next i
-  End If
-\endcode
-
-Parsing the "name=value" strings from GetMetadata() can be a bit of a bother,
-so if we were looking for specific values we could use GetMetadataItem()
-and provide a specific item we want to extract.  This would extract just
-the value if it is found, or an empty string otherwise.  The GetMetadataItem()
-is an analog of the C++ GDALMajorObject::GetMetadataItem() method. 
-
-\code
-  Dim MDValue As String
-
-  MDValue = ds.GetMetadataItem( "TIFF_DATETIME", vbNullString )
-  if MDValue <> "" Then
-    Print "Creation Date: " & MDValue
-  End If
-\endcode  
-
-The GDALDataset::GetGeoTransform() method is used to get fetch the affine
-transformation used to relate pixel/line locations on the image to 
-georeferenced locations in the current coordinate system.  In the most common
-case (image is not rotated or sheared) you can just report the origin 
-(upper left corner) and pixel size from these values.   The method returns
-0 on success or an error class if it fails, so we only use the return result
-(placed into the Geotransform array) on success.
-
-\code
-  Dim Geotransform(6) As Double
-
-  If ds.GetGeoTransform( Geotransform ) = 0 Then 
-    If Geotransform(2) = 0 and Geotransform(4) = 0 Then
-      Print "Origin: " & Geotransform(0) & "," & Geotransform(3)
-      Print "Pixel Size: " & Geotransform(1) & "x" & (-1 * Geotransform(5))
-    End If
-  End If
-\endcode
-
-The coordinate system can be fetched using the GDALDataset::GetProjectionRef()
-analog, GDALDataset.GetProjection().  The returned string is in OpenGIS
-Well Known Text format.   A later example will show how to use an 
-OGRSpatialReference object to reformat the WKT into more readable format
-and make other use of it. 
-
-\code
-  Dim WKT As String
-
-  WKT = ds.GetProjection()
-  If Len(WKT) > 0 Then
-    Print "Projection: " & WKT
-  End If
-\endcode
-
-GDALDataset objects have one or more raster bands associated with them.
-GDALRasterBand objects can have metadata (accessed the same as on the
-GDALDataset) as well as an array of pixel values, and various specialized
-metadata items like data type, color interpretation, offset/scale.   Here
-we report a few of the items.  
-
-First we loop over all the bands, fetching a band object for each band
-and report the band number, and block size. 
-
-\code
-  For i = 1 To ds.BandCount
-    Dim band As GDALRasterBand
-           
-    Set band = ds.GetRasterBand(i)
-    Print "Band " & i & " BlockSize: " & band.BlockXSize & "x" & band.BlockYSize
-\endcode
-
-The GDALRasterBand has a DataType property which has the value returned
-by the C++ method GDALRasterBand::GetRasterDataType().  The returned value
-is an integer, but may be compared to the predefined constants GDAL.GDT_Byte, 
-GDAL.GDT_UInt16, GDAL.GDT_Int16, GDAL.GDT_UInt32, GDAL.GDT_Int32, 
-GDAL.GDT_Float32, GDAL.GDT_Float64, GDAL.GDT_CInt16, GDAL.GDT_CInt32,
-GDAL.GDT_CFloat32 and GDAL.GDT_CFloat64.   In this case we use the 
-GDAL.GetDataTypeName() method to convert the data type into a name we
-can show the user. 
-
-\code
-    Print "     DataType=" & GDAL.GetDataTypeName(band.DataType) _
-\endcode
-
-We also report the offset, scale, minimum and maximum for the band. 
-
-\code
-    Print " Offset=" & band.GetOffset() & " Scale=" & band.GetScale() _
-        & " Min=" & band.GetMinimum() & " Max=" & band.GetMaximum()
-\endcode
-
-GDALRasterBands can also have GDALColorTable objects associated with them.  
-They are read with the GDALRasterBand::GetColorTable() analog in VB6.  
-Individual RGBA entries should be read into a 4 Integer array.
-
-\code
-    Dim ct As GDALColorTable
-    Set ct = band.GetColorTable()
-    If ct.IsValid() Then
-      Dim CEntry(4) As Integer
-      Print "    Has Color Table, " & ct.EntryCount & " entries"
-      For iColor = 0 To ct.EntryCount - 1
-        Call ct.GetColorEntryAsRGB(iColor, CEntry)
-        Print "      " & iColor & ": " & CEntry(0) & "," & CEntry(1) & "," & CEntry(2) & "," & CEntry(3)
-      Next iColor
-    End If
-\endcode
-
-But of course, the most important contents of a GDAL file is the raster
-pixel values themselves.  The C++ GDALRasterBand::RasterIO() method is
-provided in a somewhat simplified form.  A predimensioned 1D or 2D 
-array of type Byte, Int, Long, Float or Double is passed to the RasterIO()
-method along with the band and window to be read.  Internally the "buffer
-size" and datatype is extracted from the dimensions of the passed in buffer.
-
-This example dimensions the RawData array to be the size of one scanline
-of data (XSize x 1) and reads the first whole scanline of data from the
-file, but only prints out the second and tenth values (since the buffer
-indexes are zero based). 
-
-\code
-    Dim err As Long
-    Dim RawData() As Double
-    ReDim RawData(ds.XSize) As Double
-
-    err = band.RasterIO(GDAL.GF_Read, 0, 0, ds.XSize, 1, RawData)
-    if err = 0 Then
-      Print "    Data: " & RawData(1) & " " & RawData(9)
-    End If
-\endcode
-
-Finally, when done accessing a GDALDataset we can explicitly close
-it using the CloseDS() method, or just let it fall out of scope in which
-case it will be closed automatically. 
-
-\code
-    Call ds.CloseDS()
-\endcode
-
-\section TutorialCreate Tutorial - Creating Files
-
-Next we address creating a new file from an existing file.  To create a
-new file, you have to select a GDALDriver to do the creating.  The GDALDriver
-is essentially an object representing a file format.   We fetch it with the
-GetDriverByName() call from the GDAL module using the driver name.  
-
-\code
-    Dim Drv As GDALDriver
-
-    Call GDAL.AllRegister
-    Drv = GDALCore.GetDriverByName( "GTiff" )
-    If Not Drv.IsValid() Then
-        Call MsgBox( "GTiff driver not found " )
-	Exit Sub
-    End If
-\endcode
-
-You could get a list of registered drivers, and identify which support
-creation something like this:
-
-\code
-    drvCount = GDAL.GetDriverCount
-    For drvIndex = 0 To drvCount - 1
-        Set Drv = GDAL.GetDriver(drvIndex)
-        If Drv.GetMetadataItem(GDAL.DCAP_CREATE, "") = "YES" _
-            Or Drv.GetMetadataItem(GDAL.DCAP_CREATECOPY, "") = "YES" Then
-            xMsg = " (Read/Write)"
-        Else
-            xMsg = " (ReadOnly)"
-        End If
-              
-        Print Drv.GetShortName() & ": " & Drv.GetMetadataItem(GDAL.DMD_LONGNAME, "") & xMsg
-    Next drvIndex
-\endcode
-
-Once we have the driver object, the simplest way of creating a new file
-is to use CreateCopy().  This tries to create a copy of the input file
-in the new format.  A complete segment (without any error checking)
-would look like the following.  The CreateCopy() method corresponds to the
-C++ method GDALDriver::CreateCopy().  The VB6 implementation does not 
-support the use of progress callbacks. 
-
-\code
-    Dim Drv As GDALDriver
-    Dim SrcDS As GDALDataset, DstDS As GDALDataset
-
-    Call GDAL.AllRegister
-    Set Drv = GDALCore.GetDriverByName( "GTiff" )
-
-    Set SrcDS = GDAL.Open( "in.tif", GDAL.GA_ReadOnly )
-    Set DstDS = Drv.CreateCopy( "out.tif", SrcDS, True, Nothing )
-\endcode
-
-This is nice and simple, but sometimes we need to create a file with more
-detailed control.  So, next we show how to create a file and then copy 
-pieces of data to it "manually".   The GDALDriver::Create() analog is 
-Create().  
-
-\code
-    Set DstDS = Drv.Create("out.tif", SrcDS.XSize, SrcDS.YSize, _
-                           SrcDS.BandCount, GDAL.GDT_Byte, Nothing)
-\endcode
-
-In some cases we may want to provide some creation options,
-which is demonstrated here.  Creation options (like metadata set through the
-SetMetadata() method) are arrays of Strings.  
-
-\code
-    Dim CreateOptions(1) As String
-
-    CreateOptions(1) = "PHOTOMETRIC=MINISWHITE"
-    Set DstDS = Drv.Create("out.tif", SrcDS.XSize, SrcDS.YSize, _
-                           SrcDS.BandCount, GDAL.GDT_Byte, CreateOptions)
-\endcode
-
-When copying the GeoTransform, we take care to check that reading the
-geotransform actually worked.  Most methods which return CPLErr in C++
-also return it in VB6.  A return value of 0 will indicate success, and non-zero
-is failure. 
-
-\code
-    Dim err As Long
-    Dim gt(6) As Double
-
-    err = SrcDS.GetGeoTransform(gt)
-    If err = 0 Then
-        Call DstDS.SetGeoTransform(gt)
-    End If
-\endcode
-
-Copy the projection.  Even if GetProjection() fails we get an empty string
-which is safe enough to set on the target.   Similarly for metadata. 
-
-\code
-    Call DstDS.SetProjection(SrcDS.GetProjection())
-    Call DstDS.SetMetadata(SrcDS.GetMetadata(""), "")
-\endcode
-    
-Next we loop, processing bands, and copy some common data items.
-
-\code
-    For iBand = 1 To SrcDS.BandCount
-        Dim SrcBand As GDALRasterBand, DstBand As GDALRasterBand
-        
-        Set SrcBand = SrcDS.GetRasterBand(iBand)
-        Set DstBand = DstDS.GetRasterBand(iBand)
-        
-        Call DstBand.SetMetadata(SrcBand.GetMetadata(""), "")
-        Call DstBand.SetOffset(SrcBand.GetOffset())
-        Call DstBand.SetScale(SrcBand.GetScale())
-
-        Dim NoDataValue As Double, Success As Long
-        
-        NoDataValue = SrcBand.GetNoDataValue(Success)
-        If Success <> 0 Then
-            Call DstBand.SetNoDataValue(NoDataValue)
-        End If
-\endcode
-
-Then, if one is available, we copy the palette.
-
-\code
-        Dim ct As GDALColorTable
-        Set ct = SrcBand.GetColorTable()
-        If ct.IsValid() Then
-            err = DstBand.SetColorTable(ct)
-        End If
-\endcode        
-
-Finally, the meat and potatoes.  We copy the image data.  We do this one
-scanline at a time so that we can support very large images without require
-large amounts of RAM.   Here we use a Double buffer for the scanline, but
-if we knew in advance the type of the image, we could dimension a buffer
-of the appropriate type.  The RasterIO() method internally knows how to
-convert pixel data types, so using Double ensures all data types (except
-for complex) are properly preserved, though at the cost of some extra data
-conversion internally.
-
-\code
-        Dim Scanline() As Double, iLine As Long
-        ReDim Scanline(SrcDS.XSize) As Double
-
-        ' Copy band raster data.
-        For iLine = 0 To SrcDS.YSize - 1
-            Call SrcBand.RasterIO(GDAL.GF_Read, 0, iLine, SrcDS.XSize, 1, _
-				  Scanline)
-            Call DstBand.RasterIO(GDAL.GF_Write, 0, iLine, SrcDS.XSize, 1, _
-				  Scanline)
-        Next iLine
-\endcode
-
-\section OSRTut Tutorial - Coordinate Systems and Reprojection
-
-The GDAL VB6 bindings also include limited support for use of the
-OGRSpatialReference and OGRCoordinateTransformation classes.  The 
-OGRSpatialReference represents a coordinate system and can be used to 
-parse, manipulate and form WKT strings, such as those returned by the
-GDALDataset.GetProjection() method.   The OGRCoordinateTransformation 
-class provides a way of reprojecting between two coordinate systems. 
-
-The following example shows how to report the corners of an image in
-georeferenced and geographic (lat/long) coordinates.   First, we open
-the file, and read the geotransform. 
-
-\code
-    Dim ds As GDALDataset
-    
-    Call GDALCore.GDALAllRegister
-    Set ds = GDAL.OpenDS(FileDlg.Filename, GDAL.GA_ReadOnly)
-    
-    If ds.IsValid() Then
-        Dim Geotransform(6) As Double
-        
-        Call ds.GetGeoTransform(Geotransform)
-\endcode
-
-Next, we fetch the coordinate system, and if it is non-empty we try to 
-instantiate an OGRSpatialReference from it. 
-
-\code        
-        ' report projection in pretty format.
-        Dim WKT As String
-        Dim srs As New OGRSpatialReference
-        Dim latlong_srs As OGRSpatialReference
-        Dim ct As New OGRCoordinateTransformation
-
-        WKT = ds.GetProjection()
-        If Len(WKT) > 0 Then
-            Print "Projection: "
-            Call srs.SetFromUserInput(WKT)
-
-\endcode
-
-If the coordinate system is projected it will have a PROJECTION node.  In
-that case we build a new coordinate system which is the corresponding 
-geographic coordinate system.  So for instance if the "srs" was UTM 11 WGS84
-then it's corresponding geographic coordinate system would just be WGS84.
-Once we have these two coordinate systems, we build a transformer to convert
-between them. 
-
-\code
-            If srs.GetAttrValue("PROJECTION", 0) <> "" Then
-                Set latlong_srs = srs.CloneGeogCS()
-                Set ct = GDAL.CreateCoordinateTransformation(srs, latlong_srs)
-            End If
-        End If
-\endcode
-
-Next we call a helper function to report each corner, and the center. 
-We pass in the name of the corner, the pixel/line location at the corner,
-and the geotransform and transformer object.
-
-\code
-        Call ReportCorner("Top Left      ", 0, 0, _
-                          Geotransform, ct)
-        Call ReportCorner("Top Right     ", ds.XSize, 0, _
-                          Geotransform, ct)
-        Call ReportCorner("Bottom Left   ", 0, ds.YSize, _
-                          Geotransform, ct)
-        Call ReportCorner("Bottom Right  ", ds.XSize, ds.YSize, _
-                          Geotransform, ct)
-        Call ReportCorner("Center        ", ds.XSize / 2#, ds.YSize / 2#, _
-                          Geotransform, ct)
-\endcode
-
-The ReportCorner subroutine starts by computing the corresponding 
-georeferenced x and y location using the pixel/line coordinates and the
-geotransform. 
-
-\code
-Private Sub ReportCorner(CornerName As String, pixel As Double, line As Double, _
-                         gt() As Double, ct As OGRCoordinateTransformation)
-                             
-    Dim geox As Double, geoy As Double
-    
-    geox = gt(0) + pixel * gt(1) + line * gt(2)
-    geoy = gt(3) + pixel * gt(4) + line * gt(5)
-\endcode
-
-Next, if we have a transformer, we use it to compute a corresponding 
-latitude and longitude.
-
-\code
-    Dim longitude As Double, latitude As Double, Z As Double
-    Dim latlong_valid As Boolean
-
-    latlong_valid = False
-    
-    If ct.IsValid() Then
-        Z = 0
-        longitude = geox
-        latitude = geoy
-        latlong_valid = ct.TransformOne(longitude, latitude, Z)
-    End If
-\endcode
-
-Then we report the corner location in georeferenced, and if we have it
-geographic coordinates.  
-
-\code                         
-    If latlong_valid Then
-        Print CornerName & geox & "," & geoy & "    " & longitude & "," & latitude
-    Else
-        Print CornerName & geox & "," & geoy
-    End If
-End Sub
-\endcode
-
-\htmlonly
-<p>
-$Id: vb6_tutorial.dox 13528 2008-01-14 19:37:42Z warmerdam $
-</p>
-\endhtmlonly
-
-*/
diff --git a/doc/warptut.dox b/doc/warptut.dox
index 04e9e74..3a7942a 100644
--- a/doc/warptut.dox
+++ b/doc/warptut.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: warptut.dox 33134 2016-01-23 23:10:03Z rouault $ */
+/* $Id: warptut.dox 35221 2016-08-27 23:28:41Z goatbar $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -9,18 +9,18 @@
 
 The GDAL Warp API (declared in gdalwarper.h) provides services for high
 performance image warping using application provided geometric transformation
-functions (GDALTransformerFunc), a variety of resampling kernels, and 
+functions (GDALTransformerFunc), a variety of resampling kernels, and
 various masking options.  Files much larger than can be held in memory can
 be warped.
 
 This tutorial demonstrates how to implement an application using the Warp API.
 It assumes implementation in C++ as C and Python bindings are incomplete for
-the Warp API.  It also assumes familiarity with the 
+the Warp API.  It also assumes familiarity with the
 <a href="gdal_datamodel.html">GDAL Data Model</a>, and the general GDAL API.
 
-Applications normally perform a warp by initializing a GDALWarpOptions 
+Applications normally perform a warp by initializing a GDALWarpOptions
 structure with the options to be utilized, instantiating a GDALWarpOperation
-based on these options, and then invoking the 
+based on these options, and then invoking the
 GDALWarpOperation::ChunkAndWarpImage() method to perform the warp options
 internally using the GDALWarpKernel class.
 
@@ -37,47 +37,47 @@ int main()
 {
     GDALDatasetH  hSrcDS, hDstDS;
 
-    // Open input and output files. 
+    // Open input and output files.
 
     GDALAllRegister();
 
     hSrcDS = GDALOpen( "in.tif", GA_ReadOnly );
     hDstDS = GDALOpen( "out.tif", GA_Update );
 
-    // Setup warp options. 
-    
+    // Setup warp options.
+
     GDALWarpOptions *psWarpOptions = GDALCreateWarpOptions();
 
     psWarpOptions->hSrcDS = hSrcDS;
     psWarpOptions->hDstDS = hDstDS;
 
     psWarpOptions->nBandCount = 1;
-    psWarpOptions->panSrcBands = 
+    psWarpOptions->panSrcBands =
 	(int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount );
     psWarpOptions->panSrcBands[0] = 1;
-    psWarpOptions->panDstBands = 
+    psWarpOptions->panDstBands =
 	(int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount );
     psWarpOptions->panDstBands[0] = 1;
 
-    psWarpOptions->pfnProgress = GDALTermProgress;   
+    psWarpOptions->pfnProgress = GDALTermProgress;
 
-    // Establish reprojection transformer. 
+    // Establish reprojection transformer.
 
-    psWarpOptions->pTransformerArg = 
-        GDALCreateGenImgProjTransformer( hSrcDS, 
-                                         GDALGetProjectionRef(hSrcDS), 
+    psWarpOptions->pTransformerArg =
+        GDALCreateGenImgProjTransformer( hSrcDS,
+                                         GDALGetProjectionRef(hSrcDS),
                                          hDstDS,
-                                         GDALGetProjectionRef(hDstDS), 
+                                         GDALGetProjectionRef(hDstDS),
                                          FALSE, 0.0, 1 );
     psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
 
-    // Initialize and execute the warp operation. 
+    // Initialize and execute the warp operation.
 
     GDALWarpOperation oOperation;
 
     oOperation.Initialize( psWarpOptions );
-    oOperation.ChunkAndWarpImage( 0, 0, 
-		                  GDALGetRasterXSize( hDstDS ), 
+    oOperation.ChunkAndWarpImage( 0, 0,
+		                  GDALGetRasterXSize( hDstDS ),
 			          GDALGetRasterYSize( hDstDS ) );
 
     GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
@@ -98,17 +98,17 @@ panDstBands lists are dynamically allocated here and will be free automatically
 by GDALDestroyWarpOptions().  The simple terminal output progress monitor
 (GDALTermProgress) is installed for reporting completion progress to the user.
 
-GDALCreateGenImgProjTransformer() is used to initialize the reprojection 
+GDALCreateGenImgProjTransformer() is used to initialize the reprojection
 transformation between the source and destination images.  We assume that
 they already have reasonable bounds and coordinate systems set.  Use of
-GCPs is disabled. 
+GCPs is disabled.
 
 Once the options structure is ready, a GDALWarpOperation is instantiated using
-them, and the warp actually performed with 
+them, and the warp actually performed with
 GDALWarpOperation::ChunkAndWarpImage().  Then the transformer, warp options
-and datasets are cleaned up. 
+and datasets are cleaned up.
 
-Normally error check would be needed after opening files, setting up the 
+Normally error check would be needed after opening files, setting up the
 reprojection transformer (returns NULL on failure), and initializing the
 warp.
 
@@ -119,9 +119,9 @@ to control warping behavior.  A few of particular interest are:
 
 <ol>
 
-<li> GDALWarpOptions::dfWarpMemoryLimit - Set the maximum amount of memory to 
+<li> GDALWarpOptions::dfWarpMemoryLimit - Set the maximum amount of memory to
 be used by the GDALWarpOperation when selecting a size of image chunk to
-operate on.  The value is in bytes, and the default is likely to be 
+operate on.  The value is in bytes, and the default is likely to be
 conservative (small).  Increasing the chunk size can help substantially in
 some situations but care should be taken to ensure that this size, plus the
 GDAL cache size plus the working set of GDAL, your application and the
@@ -133,29 +133,29 @@ caching.
 
 <li> GDALWarpOpations::eResampleAlg - One of GRA_NearestNeighbour (the default,
 and fastest), GRA_Bilinear (2x2 bilinear resampling) or GRA_Cubic.  The
-GRA_NearestNeighbour type should generally be used for thematic or color mapped 
-images.  The other resampling types may give better results for thematic 
-images, especially when substantially changing resolution. 
+GRA_NearestNeighbour type should generally be used for thematic or color mapped
+images.  The other resampling types may give better results for thematic
+images, especially when substantially changing resolution.
 
 <li> GDALWarpOptions::padfSrcNoDataReal - This array (one entry per band
 being processed) may be setup with a "nodata" value for each band if you wish
 to avoid having pixels of some background value copied to the destination
-image. 
+image.
 
 <li><a name="#warpoptions"></a> GDALWarpOptions::papszWarpOptions - This is
-a string list of NAME=VALUE options passed to the warper.  See the 
-GDALWarpOptions::papszWarpOptions docs for all options.  Supported values 
+a string list of NAME=VALUE options passed to the warper.  See the
+GDALWarpOptions::papszWarpOptions docs for all options.  Supported values
 include:
 
 <ul>
-<li> INIT_DEST=[value] or INIT_DEST=NO_DATA: This option forces the 
+<li> INIT_DEST=[value] or INIT_DEST=NO_DATA: This option forces the
  destination image to be initialized to the indicated value (for all bands)
  or indicates that it should be initialized to the NO_DATA value in
  padfDstNoDataReal/padfDstNoDataImag.  If this value isn't set the
  destination image will be read and the source warp overlaid on it.
 
 <li> WRITE_FLUSH=YES/NO: This option forces a flush to disk of data after
- each chunk is processed.  In some cases this helps ensure a serial 
+ each chunk is processed.  In some cases this helps ensure a serial
  writing of the output data otherwise a block of data may be written to disk
  each time a block of data is read for the input buffer resulting in a lot
  of extra seeking around the disk, and reduced IO throughput.  The default
@@ -166,7 +166,7 @@ include:
 
 \section warptut_output Creating the Output File
 
-In the previous case an appropriate output file was already assumed to 
+In the previous case an appropriate output file was already assumed to
 exist.  Now we will go through a case where a new file with appropriate
 bounds in a new coordinate system is created.  This operation doesn't
 relate specifically to the warp API.  It is just using the transformation API.
@@ -182,12 +182,12 @@ relate specifically to the warp API.  It is just using the transformation API.
     GDALDatasetH hDstDS;
     GDALDatasetH hSrcDS;
 
-    // Open the source file. 
+    // Open the source file.
 
     hSrcDS = GDALOpen( "in.tif", GA_ReadOnly );
     CPLAssert( hSrcDS != NULL );
-    
-    // Create output with same datatype as first input band. 
+
+    // Create output with same datatype as first input band.
 
     eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1));
 
@@ -196,14 +196,14 @@ relate specifically to the warp API.  It is just using the transformation API.
     hDriver = GDALGetDriverByName( "GTiff" );
     CPLAssert( hDriver != NULL );
 
-    // Get Source coordinate system. 
+    // Get Source coordinate system.
 
     const char *pszSrcWKT, *pszDstWKT = NULL;
 
     pszSrcWKT = GDALGetProjectionRef( hSrcDS );
     CPLAssert( pszSrcWKT != NULL && strlen(pszSrcWKT) > 0 );
 
-    // Setup output coordinate system that is UTM 11 WGS84. 
+    // Setup output coordinate system that is UTM 11 WGS84.
 
     OGRSpatialReference oSRS;
 
@@ -213,38 +213,38 @@ relate specifically to the warp API.  It is just using the transformation API.
     oSRS.exportToWkt( &pszDstWKT );
 
     // Create a transformer that maps from source pixel/line coordinates
-    // to destination georeferenced coordinates (not destination 
+    // to destination georeferenced coordinates (not destination
     // pixel line).  We do that by omitting the destination dataset
-    // handle (setting it to NULL). 
+    // handle (setting it to NULL).
 
     void *hTransformArg;
 
-    hTransformArg = 
-        GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT, 
+    hTransformArg =
+        GDALCreateGenImgProjTransformer( hSrcDS, pszSrcWKT, NULL, pszDstWKT,
                                          FALSE, 0, 1 );
     CPLAssert( hTransformArg != NULL );
 
-    // Get approximate output georeferenced bounds and resolution for file. 
+    // Get approximate output georeferenced bounds and resolution for file.
 
     double adfDstGeoTransform[6];
     int nPixels=0, nLines=0;
     CPLErr eErr;
 
-    eErr = GDALSuggestedWarpOutput( hSrcDS, 
-				    GDALGenImgProjTransform, hTransformArg, 
+    eErr = GDALSuggestedWarpOutput( hSrcDS,
+				    GDALGenImgProjTransform, hTransformArg,
                                     adfDstGeoTransform, &nPixels, &nLines );
     CPLAssert( eErr == CE_None );
 
     GDALDestroyGenImgProjTransformer( hTransformArg );
 
-    // Create the output file.  
+    // Create the output file.
 
-    hDstDS = GDALCreate( hDriver, "out.tif", nPixels, nLines, 
+    hDstDS = GDALCreate( hDriver, "out.tif", nPixels, nLines,
                          GDALGetRasterCount(hSrcDS), eDT, NULL );
-    
+
     CPLAssert( hDstDS != NULL );
 
-    // Write out the projection definition. 
+    // Write out the projection definition.
 
     GDALSetProjection( hDstDS, pszDstWKT );
     GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
@@ -267,23 +267,23 @@ Some notes on this logic:
 <li> We need to create the transformer to output coordinates such that the
 output of the transformer is georeferenced, not pixel line coordinates since
 we use the transformer to map pixels around the source image into destination
-georeferenced coordinates.  
+georeferenced coordinates.
 
 <li> The GDALSuggestedWarpOutput() function will return an adfDstGeoTransform,
-nPixels and nLines that describes an output image size and georeferenced 
+nPixels and nLines that describes an output image size and georeferenced
 extents that should hold all pixels from the source image.  The resolution
 is intended to be comparable to the source, but the output pixels are always
-square regardless of the shape of input pixels. 
+square regardless of the shape of input pixels.
 
 <li> The warper requires an output file in a format that can be "randomly"
 written to.  This generally limits things to uncompressed formats that
-have an implementation of the Create() method (as opposed to CreateCopy()). 
+have an implementation of the Create() method (as opposed to CreateCopy()).
 To warp to compressed formats, or CreateCopy() style formats it is necessary
 to produce a full temporary copy of the image in a better behaved format, and
-then CreateCopy() it to the desired final format. 
+then CreateCopy() it to the desired final format.
 
 <li> The Warp API copies only pixels.  All color maps, georeferencing and
-other metadata must be copied to the destination by the application.  
+other metadata must be copied to the destination by the application.
 
 </ul>
 
@@ -295,28 +295,28 @@ of the warp API.
 <ol>
 
 <li> Increase the amount of memory available for the Warp API chunking so that
-larger chunks can be operated on at a time.  This is the 
+larger chunks can be operated on at a time.  This is the
 GDALWarpOptions::dfWarpMemoryLimit parameter.  In theory the larger the chunk
 size operated on the more efficient the I/O strategy, and the more efficient
-the approximated transformation will be.   However, the sum of the warp 
+the approximated transformation will be.   However, the sum of the warp
 memory and the GDAL cache should be less than RAM size, likely around 2/3
 of RAM size.
 
-<li> Increase the amount of memory for GDAL caching.  This is especially 
-important when working with very large input and output images that are 
+<li> Increase the amount of memory for GDAL caching.  This is especially
+important when working with very large input and output images that are
 scanline oriented.  If all the input or output scanlines have to be re-read
-for each chunk they intersect performance may degrade greatly.  Use 
+for each chunk they intersect performance may degrade greatly.  Use
 GDALSetCacheMax() to control the amount of memory available for caching
-within GDAL. 
+within GDAL.
 
 <li> Use an approximated transformation instead of exact reprojection for
 each pixel to be transformed.  This code illustrates how an approximated
 transformation could be created based on a reprojection transformation, but
-with a given error threshold (dfErrorThreshold in output pixels). 
+with a given error threshold (dfErrorThreshold in output pixels).
 
 \code
-        hTransformArg = 
-            GDALCreateApproxTransformer( GDALGenImgProjTransform, 
+        hTransformArg =
+            GDALCreateApproxTransformer( GDALGenImgProjTransform,
                                          hGenImgProjArg, dfErrorThreshold );
         pfnTransformer = GDALApproxTransform;
 \endcode
@@ -324,15 +324,15 @@ with a given error threshold (dfErrorThreshold in output pixels).
 <li> When writing to a blank output file, use the INIT_DEST option in the
 GDALWarpOptions::papszWarpOptions to cause the output chunks to be
 initialized to a fixed value, instead of being read from the output.  This
-can substantially reduce unnecessary IO work. 
+can substantially reduce unnecessary IO work.
 
 <li> Use tiled input and output formats.  Tiled formats allow a given
-chunk of source and destination imagery to be accessed without having to 
-touch a great deal of extra image data.  Large scanline oriented files 
+chunk of source and destination imagery to be accessed without having to
+touch a great deal of extra image data.  Large scanline oriented files
 can result in a great deal of wasted extra IO.
 
-<li> Process all bands in one call.  This ensures the transformation 
-calculations don't have to be performed for each band. 
+<li> Process all bands in one call.  This ensures the transformation
+calculations don't have to be performed for each band.
 
 <li> Use the GDALWarpOperation::ChunkAndWarpMulti() method instead of
 GDALWarpOperation::ChunkAndWarpImage().  It uses a separate thread for the
@@ -343,10 +343,10 @@ for previous versions --with-threads was required in configure).
 
 <li> The resampling kernels vary is work required from nearest neighbour
 being least, then bilinear then cubic.  Don't use a more complex resampling
-kernel than needed. 
+kernel than needed.
 
-<li> Avoid use of esoteric masking options so that special simplified 
-logic case be used for common special cases.  For instance, nearest 
+<li> Avoid use of esoteric masking options so that special simplified
+logic case be used for common special cases.  For instance, nearest
 neighbour resampling with no masking on 8bit data is highly optimized
 compared to the general case.
 
@@ -358,11 +358,11 @@ The GDALWarpOptions include a bunch of esoteric masking capabilities, for
 validity masks, and density masks on input and output.  Some of these are
 not yet implemented and others are implemented but poorly tested.  Other
 than per-band validity masks it is advised that these features be used with
-caution at this time. 
+caution at this time.
 
 \htmlonly
 <p>
-$Id: warptut.dox 33134 2016-01-23 23:10:03Z rouault $
+$Id: warptut.dox 35221 2016-08-27 23:28:41Z goatbar $
 </p>
 \endhtmlonly
 
diff --git a/frmts/aaigrid/aaigriddataset.cpp b/frmts/aaigrid/aaigriddataset.cpp
index 7bb8414..08164db 100644
--- a/frmts/aaigrid/aaigriddataset.cpp
+++ b/frmts/aaigrid/aaigriddataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: aaigriddataset.cpp 33809 2016-03-29 21:41:38Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements Arc/Info ASCII Grid Format.
@@ -32,124 +31,40 @@
 // We need cpl_port as first include to avoid VSIStatBufL being not
 // defined on i586-mingw32msvc.
 #include "cpl_port.h"
+#include "aaigriddataset.h"
+#include "gdal_frmts.h"
 
-#include <ctype.h>
+#include <cctype>
 #include <climits>
-
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
+#include <limits>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_pam.h"
-#include "gdal_frmts.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: aaigriddataset.cpp 33809 2016-03-29 21:41:38Z goatbar $");
+CPL_CVSID("$Id: aaigriddataset.cpp 37613 2017-03-05 02:51:32Z goatbar $");
 
-static CPLString OSR_GDS( char **papszNV, const char * pszField,
+static CPLString OSR_GDS( char **papszNV, const char *pszField,
                           const char *pszDefaultValue );
 
-typedef enum
-{
-    FORMAT_AAIG,
-    FORMAT_GRASSASCII
-} GridFormat;
-
-/************************************************************************/
-/* ==================================================================== */
-/*                              AAIGDataset                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class AAIGRasterBand;
-
-class CPL_DLL AAIGDataset : public GDALPamDataset
-{
-    friend class AAIGRasterBand;
-
-    VSILFILE   *fp;
-
-    char        **papszPrj;
-    CPLString   osPrjFilename;
-    char        *pszProjection;
-
-    unsigned char achReadBuf[256];
-    GUIntBig    nBufferOffset;
-    int         nOffsetInBuffer;
-
-    char        Getc();
-    GUIntBig    Tell();
-    int         Seek( GUIntBig nOffset );
-
-  protected:
-    GDALDataType eDataType;
-    double      adfGeoTransform[6];
-    int         bNoDataSet;
-    double      dfNoDataValue;
-
-
-    virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
-
-  public:
-                AAIGDataset();
-       virtual ~AAIGDataset();
-
-    virtual char **GetFileList(void);
-
-    static GDALDataset *CommonOpen( GDALOpenInfo * poOpenInfo,
-                                    GridFormat eFormat );
-
-    static GDALDataset *Open( GDALOpenInfo * );
-    static int          Identify( GDALOpenInfo * );
-    static CPLErr       Delete( const char *pszFilename );
-    static CPLErr       Remove( const char *pszFilename, int bRepError );
-    static GDALDataset *CreateCopy( const char * pszFilename,
-                                    GDALDataset *poSrcDS,
-                                    int bStrict, char ** papszOptions,
-                                    GDALProgressFunc pfnProgress,
-                                    void * pProgressData );
-
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char *GetProjectionRef(void);
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                        GRASSASCIIDataset                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class GRASSASCIIDataset : public AAIGDataset
-{
-    virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
-
-  public:
-                GRASSASCIIDataset() : AAIGDataset() {}
-       virtual ~GRASSASCIIDataset() {}
-
-    static GDALDataset *Open( GDALOpenInfo * );
-    static int          Identify( GDALOpenInfo * );
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            AAIGRasterBand                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class AAIGRasterBand : public GDALPamRasterBand
-{
-    friend class AAIGDataset;
-
-    GUIntBig      *panLineOffset;
-
-  public:
-
-                   AAIGRasterBand( AAIGDataset *, int );
-    virtual       ~AAIGRasterBand();
-
-    virtual double GetNoDataValue( int * );
-    virtual CPLErr SetNoDataValue( double );
-    virtual CPLErr IReadBlock( int, int, void * );
-};
-
 /************************************************************************/
 /*                           AAIGRasterBand()                            */
 /************************************************************************/
@@ -165,9 +80,8 @@ AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDSIn, int nDataStart ) :
     nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 
-    panLineOffset =
-        static_cast<GUIntBig *>(
-            VSI_CALLOC_VERBOSE( poDSIn->nRasterYSize, sizeof(GUIntBig) ) );
+    panLineOffset = static_cast<GUIntBig *>(
+        VSI_CALLOC_VERBOSE(poDSIn->nRasterYSize, sizeof(GUIntBig)));
     if (panLineOffset == NULL)
     {
         return;
@@ -179,62 +93,56 @@ AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDSIn, int nDataStart ) :
 /*                          ~AAIGRasterBand()                           */
 /************************************************************************/
 
-AAIGRasterBand::~AAIGRasterBand()
-
-{
-    CPLFree( panLineOffset );
-}
+AAIGRasterBand::~AAIGRasterBand() { CPLFree(panLineOffset); }
 
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
 CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                  void * pImage )
+                                   void *pImage )
 
 {
-    AAIGDataset *poODS = reinterpret_cast<AAIGDataset *>( poDS );
+    AAIGDataset *poODS = static_cast<AAIGDataset *>(poDS);
 
-    if( nBlockYOff < 0 || nBlockYOff > poODS->nRasterYSize - 1
-        || nBlockXOff != 0 || panLineOffset == NULL || poODS->fp == NULL )
+    if( nBlockYOff < 0 || nBlockYOff > poODS->nRasterYSize - 1 ||
+        nBlockXOff != 0 || panLineOffset == NULL || poODS->fp == NULL )
         return CE_Failure;
 
     if( panLineOffset[nBlockYOff] == 0 )
     {
         for( int iPrevLine = 1; iPrevLine <= nBlockYOff; iPrevLine++ )
             if( panLineOffset[iPrevLine] == 0 )
-                IReadBlock( nBlockXOff, iPrevLine-1, NULL );
+                IReadBlock(nBlockXOff, iPrevLine - 1, NULL);
     }
 
     if( panLineOffset[nBlockYOff] == 0 )
         return CE_Failure;
 
-
-    if( poODS->Seek( panLineOffset[nBlockYOff] ) != 0 )
+    if( poODS->Seek(panLineOffset[nBlockYOff]) != 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Can't seek to offset %lu in input file to read data.",
-                  static_cast<long unsigned int>(panLineOffset[nBlockYOff] ) );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Can't seek to offset %lu in input file to read data.",
+                 static_cast<long unsigned int>(panLineOffset[nBlockYOff]));
         return CE_Failure;
     }
 
     for( int iPixel = 0; iPixel < poODS->nRasterXSize; )
     {
         // Suck up any pre-white space.
-        char chNext;
+        char chNext = '\0';
         do {
             chNext = poODS->Getc();
-        } while( isspace( static_cast<unsigned char>(chNext) ) );
+        } while( isspace(static_cast<unsigned char>(chNext)) );
 
         char szToken[500] = { '\0' };
-        int  iTokenChar = 0;
-        while( chNext != '\0' && !isspace((unsigned char)chNext)  )
+        int iTokenChar = 0;
+        while( chNext != '\0' && !isspace((unsigned char)chNext) )
         {
-            if( iTokenChar == sizeof(szToken)-2 )
+            if( iTokenChar == sizeof(szToken) - 2 )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Token too long at scanline %d.",
-                          nBlockYOff );
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Token too long at scanline %d.", nBlockYOff);
                 return CE_Failure;
             }
 
@@ -246,9 +154,8 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             (iPixel != poODS->nRasterXSize - 1 ||
             nBlockYOff != poODS->nRasterYSize - 1) )
         {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "File short, can't read line %d.",
-                      nBlockYOff );
+            CPLError(CE_Failure, CPLE_FileIO, "File short, can't read line %d.",
+                     nBlockYOff);
             return CE_Failure;
         }
 
@@ -260,10 +167,10 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 reinterpret_cast<double *>(pImage)[iPixel] = CPLAtofM(szToken);
             else if( eDataType == GDT_Float32 )
                 reinterpret_cast<float *>(pImage)[iPixel] =
-                    static_cast<float>( CPLAtofM(szToken) );
+                    static_cast<float>(CPLAtofM(szToken));
             else
                 reinterpret_cast<GInt32 *>(pImage)[iPixel] =
-                    static_cast<GInt32>( atoi(szToken) );
+                    static_cast<GInt32>(atoi(szToken));
         }
 
         iPixel++;
@@ -279,10 +186,10 @@ CPLErr AAIGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                           GetNoDataValue()                           */
 /************************************************************************/
 
-double AAIGRasterBand::GetNoDataValue( int * pbSuccess )
+double AAIGRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
-    AAIGDataset *poODS = reinterpret_cast<AAIGDataset *>( poDS );
+    AAIGDataset *poODS = static_cast<AAIGDataset *>(poDS);
 
     if( pbSuccess )
         *pbSuccess = poODS->bNoDataSet;
@@ -290,7 +197,6 @@ double AAIGRasterBand::GetNoDataValue( int * pbSuccess )
     return poODS->dfNoDataValue;
 }
 
-
 /************************************************************************/
 /*                           SetNoDataValue()                           */
 /************************************************************************/
@@ -298,9 +204,9 @@ double AAIGRasterBand::GetNoDataValue( int * pbSuccess )
 CPLErr AAIGRasterBand::SetNoDataValue( double dfNoData )
 
 {
-    AAIGDataset *poODS = reinterpret_cast<AAIGDataset *>( poDS );
+    AAIGDataset *poODS = static_cast<AAIGDataset *>(poDS);
 
-    poODS->bNoDataSet = TRUE;
+    poODS->bNoDataSet = true;
     poODS->dfNoDataValue = dfNoData;
 
     return CE_None;
@@ -323,7 +229,7 @@ AAIGDataset::AAIGDataset() :
     nBufferOffset(0),
     nOffsetInBuffer(256),
     eDataType(GDT_Int32),
-    bNoDataSet(FALSE),
+    bNoDataSet(false),
     dfNoDataValue(-9999.0)
 {
     adfGeoTransform[0] = 0.0;
@@ -332,6 +238,7 @@ AAIGDataset::AAIGDataset() :
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+    memset(achReadBuf, 0, sizeof(achReadBuf));
 }
 
 /************************************************************************/
@@ -345,25 +252,21 @@ AAIGDataset::~AAIGDataset()
 
     if( fp != NULL )
     {
-        if( VSIFCloseL( fp ) != 0 )
+        if( VSIFCloseL(fp) != 0 )
         {
             CPLError(CE_Failure, CPLE_FileIO, "I/O error");
         }
     }
 
-    CPLFree( pszProjection );
-    CSLDestroy( papszPrj );
+    CPLFree(pszProjection);
+    CSLDestroy(papszPrj);
 }
 
 /************************************************************************/
 /*                                Tell()                                */
 /************************************************************************/
 
-GUIntBig AAIGDataset::Tell()
-
-{
-    return nBufferOffset + nOffsetInBuffer;
-}
+GUIntBig AAIGDataset::Tell() { return nBufferOffset + nOffsetInBuffer; }
 
 /************************************************************************/
 /*                                Seek()                                */
@@ -373,7 +276,7 @@ int AAIGDataset::Seek( GUIntBig nNewOffset )
 
 {
     nOffsetInBuffer = sizeof(achReadBuf);
-    return VSIFSeekL( fp, nNewOffset, SEEK_SET );
+    return VSIFSeekL(fp, nNewOffset, SEEK_SET);
 }
 
 /************************************************************************/
@@ -386,13 +289,13 @@ int AAIGDataset::Seek( GUIntBig nNewOffset )
 char AAIGDataset::Getc()
 
 {
-    if( nOffsetInBuffer < (int) sizeof(achReadBuf) )
+    if( nOffsetInBuffer < static_cast<int>(sizeof(achReadBuf)) )
         return achReadBuf[nOffsetInBuffer++];
 
-    nBufferOffset = VSIFTellL( fp );
+    nBufferOffset = VSIFTellL(fp);
     const int nRead =
-        static_cast<int>(VSIFReadL( achReadBuf, 1, sizeof(achReadBuf), fp ));
-    for( unsigned int i=nRead; i < sizeof(achReadBuf); i++ )
+        static_cast<int>(VSIFReadL(achReadBuf, 1, sizeof(achReadBuf), fp));
+    for( unsigned int i = nRead; i < sizeof(achReadBuf); i++ )
         achReadBuf[i] = '\0';
 
     nOffsetInBuffer = 0;
@@ -410,7 +313,7 @@ char **AAIGDataset::GetFileList()
     char **papszFileList = GDALPamDataset::GetFileList();
 
     if( papszPrj != NULL )
-        papszFileList = CSLAddString( papszFileList, osPrjFilename );
+        papszFileList = CSLAddString(papszFileList, osPrjFilename);
 
     return papszFileList;
 }
@@ -419,22 +322,20 @@ char **AAIGDataset::GetFileList()
 /*                            Identify()                                */
 /************************************************************************/
 
-int AAIGDataset::Identify( GDALOpenInfo * poOpenInfo )
+int AAIGDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Does this look like an AI grid file?                            */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 40
-        || !( STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "ncols") ||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "nrows") ||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "xllcorner")||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "yllcorner")||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "xllcenter")||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "yllcenter")||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "dx")||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "dy")||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "cellsize")) )
+    // Does this look like an AI grid file?
+    if( poOpenInfo->nHeaderBytes < 40 ||
+        !(STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "ncols") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "nrows") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "xllcorner") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "yllcorner") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "xllcenter") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "yllcenter") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "dx") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "dy") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "cellsize")) )
         return FALSE;
 
     return TRUE;
@@ -444,19 +345,17 @@ int AAIGDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                            Identify()                                */
 /************************************************************************/
 
-int GRASSASCIIDataset::Identify( GDALOpenInfo * poOpenInfo )
+int GRASSASCIIDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Does this look like a GRASS ASCII grid file?                    */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 40
-        || !( STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "north:") ||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "south:") ||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "east:")||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "west:")||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "rows:")||
-              STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "cols:") ) )
+    // Does this look like a GRASS ASCII grid file?
+    if( poOpenInfo->nHeaderBytes < 40 ||
+        !(STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "north:") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "south:") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "east:") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "west:") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "rows:") ||
+          STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "cols:")) )
         return FALSE;
 
     return TRUE;
@@ -468,8 +367,11 @@ int GRASSASCIIDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
 {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    // During fuzzing, do not use Identify to reject crazy content.
     if (!Identify(poOpenInfo))
         return NULL;
+#endif
 
     return CommonOpen(poOpenInfo, FORMAT_AAIG);
 }
@@ -478,67 +380,67 @@ GDALDataset *AAIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                          ParseHeader()                               */
 /************************************************************************/
 
-int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
+int AAIGDataset::ParseHeader(const char *pszHeader, const char *pszDataType)
 {
-    char** papszTokens =
-        CSLTokenizeString2( pszHeader,  " \n\r\t" , 0 );
+    char **papszTokens = CSLTokenizeString2(pszHeader, " \n\r\t", 0);
     const int nTokens = CSLCount(papszTokens);
 
     int i = 0;
-    if ( (i = CSLFindString( papszTokens, "ncols" )) < 0 ||
+    if ( (i = CSLFindString(papszTokens, "ncols")) < 0 ||
          i + 1 >= nTokens)
     {
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
         return FALSE;
     }
     nRasterXSize = atoi(papszTokens[i + 1]);
-    if ( (i = CSLFindString( papszTokens, "nrows" )) < 0 ||
+    if ( (i = CSLFindString(papszTokens, "nrows")) < 0 ||
          i + 1 >= nTokens)
     {
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
         return FALSE;
     }
     nRasterYSize = atoi(papszTokens[i + 1]);
 
     if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
     {
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
         return FALSE;
     }
 
     double dfCellDX = 0.0;
     double dfCellDY = 0.0;
-    if ( (i = CSLFindString( papszTokens, "cellsize" )) < 0 )
+    if ( (i = CSLFindString(papszTokens, "cellsize")) < 0 )
     {
         int iDX, iDY;
-        if( (iDX = CSLFindString(papszTokens,"dx")) < 0
-            || (iDY = CSLFindString(papszTokens,"dy")) < 0
-            || iDX+1 >= nTokens
-            || iDY+1 >= nTokens)
+        if( (iDX = CSLFindString(papszTokens, "dx")) < 0 ||
+            (iDY = CSLFindString(papszTokens, "dy")) < 0 ||
+            iDX + 1 >= nTokens ||
+            iDY + 1 >= nTokens )
         {
-            CSLDestroy( papszTokens );
+            CSLDestroy(papszTokens);
             return FALSE;
         }
 
-        dfCellDX = CPLAtofM( papszTokens[iDX+1] );
-        dfCellDY = CPLAtofM( papszTokens[iDY+1] );
+        dfCellDX = CPLAtofM(papszTokens[iDX + 1]);
+        dfCellDY = CPLAtofM(papszTokens[iDY + 1]);
     }
     else
     {
         if (i + 1 >= nTokens)
         {
-            CSLDestroy( papszTokens );
+            CSLDestroy(papszTokens);
             return FALSE;
         }
-        dfCellDX = dfCellDY = CPLAtofM( papszTokens[i + 1] );
+        dfCellDY = CPLAtofM(papszTokens[i + 1]);
+        dfCellDX = dfCellDY;
     }
 
     int j = 0;
-    if ((i = CSLFindString( papszTokens, "xllcorner" )) >= 0 &&
-        (j = CSLFindString( papszTokens, "yllcorner" )) >= 0 &&
+    if ((i = CSLFindString(papszTokens, "xllcorner")) >= 0 &&
+        (j = CSLFindString(papszTokens, "yllcorner")) >= 0 &&
         i + 1 < nTokens && j + 1 < nTokens)
     {
-        adfGeoTransform[0] = CPLAtofM( papszTokens[i + 1] );
+        adfGeoTransform[0] = CPLAtofM(papszTokens[i + 1]);
 
         // Small hack to compensate from insufficient precision in cellsize
         // parameter in datasets of
@@ -548,30 +450,30 @@ int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
             dfCellDX == dfCellDY &&
             fabs(dfCellDX - (360.0 / nRasterXSize)) < 1e-9)
         {
-            dfCellDX = dfCellDY = 360.0 / nRasterXSize;
+            dfCellDY = 360.0 / nRasterXSize;
+            dfCellDX = dfCellDY;
         }
 
         adfGeoTransform[1] = dfCellDX;
         adfGeoTransform[2] = 0.0;
-        adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
-            + nRasterYSize * dfCellDY;
+        adfGeoTransform[3] =
+            CPLAtofM(papszTokens[j + 1]) + nRasterYSize * dfCellDY;
         adfGeoTransform[4] = 0.0;
-        adfGeoTransform[5] = - dfCellDY;
+        adfGeoTransform[5] = -dfCellDY;
     }
-    else if ((i = CSLFindString( papszTokens, "xllcenter" )) >= 0 &&
-             (j = CSLFindString( papszTokens, "yllcenter" )) >= 0  &&
+    else if ((i = CSLFindString(papszTokens, "xllcenter")) >= 0 &&
+             (j = CSLFindString(papszTokens, "yllcenter")) >= 0 &&
              i + 1 < nTokens && j + 1 < nTokens)
     {
-        SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
+        SetMetadataItem(GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT);
 
         adfGeoTransform[0] = CPLAtofM(papszTokens[i + 1]) - 0.5 * dfCellDX;
         adfGeoTransform[1] = dfCellDX;
         adfGeoTransform[2] = 0.0;
-        adfGeoTransform[3] = CPLAtofM( papszTokens[j + 1] )
-            - 0.5 * dfCellDY
-            + nRasterYSize * dfCellDY;
+        adfGeoTransform[3] = CPLAtofM(papszTokens[j + 1]) - 0.5 * dfCellDY +
+                             nRasterYSize * dfCellDY;
         adfGeoTransform[4] = 0.0;
-        adfGeoTransform[5] = - dfCellDY;
+        adfGeoTransform[5] = -dfCellDY;
     }
     else
     {
@@ -580,30 +482,37 @@ int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
         adfGeoTransform[2] = 0.0;
         adfGeoTransform[3] = 0.0;
         adfGeoTransform[4] = 0.0;
-        adfGeoTransform[5] = - dfCellDY;
+        adfGeoTransform[5] = -dfCellDY;
     }
 
     if( (i = CSLFindString( papszTokens, "NODATA_value" )) >= 0 &&
         i + 1 < nTokens)
     {
-        const char* pszNoData = papszTokens[i + 1];
+        const char *pszNoData = papszTokens[i + 1];
 
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
         dfNoDataValue = CPLAtofM(pszNoData);
         if( pszDataType == NULL &&
-            (strchr( pszNoData, '.' ) != NULL ||
-             strchr( pszNoData, ',' ) != NULL ||
+            (strchr(pszNoData, '.') != NULL ||
+             strchr(pszNoData, ',') != NULL ||
              INT_MIN > dfNoDataValue || dfNoDataValue > INT_MAX) )
         {
             eDataType = GDT_Float32;
+            if( !CPLIsInf(dfNoDataValue) &&
+                (fabs(dfNoDataValue) < std::numeric_limits<float>::min() ||
+                 fabs(dfNoDataValue) > std::numeric_limits<float>::max()) )
+            {
+                eDataType = GDT_Float64;
+            }
         }
         if( eDataType == GDT_Float32 )
         {
-            dfNoDataValue = (double) (float) dfNoDataValue;
+            dfNoDataValue =
+                static_cast<double>(static_cast<float>(dfNoDataValue));
         }
     }
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
 
     return TRUE;
 }
@@ -612,62 +521,65 @@ int AAIGDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *GRASSASCIIDataset::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *GRASSASCIIDataset::Open( GDALOpenInfo *poOpenInfo )
 {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    // During fuzzing, do not use Identify to reject crazy content.
     if (!Identify(poOpenInfo))
         return NULL;
+#endif
 
     return CommonOpen(poOpenInfo, FORMAT_GRASSASCII);
 }
 
-
 /************************************************************************/
 /*                          ParseHeader()                               */
 /************************************************************************/
 
-int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataType)
+int GRASSASCIIDataset::ParseHeader(const char *pszHeader,
+                                   const char *pszDataType)
 {
-    char** papszTokens =
-        CSLTokenizeString2( pszHeader,  " \n\r\t:" , 0 );
+    char **papszTokens = CSLTokenizeString2(pszHeader, " \n\r\t:", 0);
     const int nTokens = CSLCount(papszTokens);
     int i = 0;
-    if ( (i = CSLFindString( papszTokens, "cols" )) < 0 ||
+    if ( (i = CSLFindString(papszTokens, "cols")) < 0 ||
          i + 1 >= nTokens)
     {
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
         return FALSE;
     }
     nRasterXSize = atoi(papszTokens[i + 1]);
     if ( (i = CSLFindString( papszTokens, "rows" )) < 0 ||
          i + 1 >= nTokens)
     {
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
         return FALSE;
     }
     nRasterYSize = atoi(papszTokens[i + 1]);
 
     if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
     {
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
         return FALSE;
     }
 
-    const int iNorth = CSLFindString( papszTokens, "north" );
-    const int iSouth = CSLFindString( papszTokens, "south" );
-    const int iEast = CSLFindString( papszTokens, "east" );
-    const int iWest = CSLFindString( papszTokens, "west" );
+    const int iNorth = CSLFindString(papszTokens, "north");
+    const int iSouth = CSLFindString(papszTokens, "south");
+    const int iEast = CSLFindString(papszTokens, "east");
+    const int iWest = CSLFindString(papszTokens, "west");
 
     if (iNorth == -1 || iSouth == -1 || iEast == -1 || iWest == -1 ||
-        MAX(MAX(iNorth, iSouth), MAX(iEast, iWest)) + 1 >= nTokens)
+        std::max(std::max(iNorth, iSouth),
+                 std::max(iEast, iWest)) + 1 >= nTokens)
     {
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
         return FALSE;
     }
 
-    const double dfNorth = CPLAtofM( papszTokens[iNorth + 1] );
-    const double dfSouth = CPLAtofM( papszTokens[iSouth + 1] );
-    const double dfEast = CPLAtofM( papszTokens[iEast + 1] );
-    const double dfWest = CPLAtofM( papszTokens[iWest + 1] );
+    const double dfNorth = CPLAtofM(papszTokens[iNorth + 1]);
+    const double dfSouth = CPLAtofM(papszTokens[iSouth + 1]);
+    const double dfEast = CPLAtofM(papszTokens[iEast + 1]);
+    const double dfWest = CPLAtofM(papszTokens[iWest + 1]);
     const double dfPixelXSize = (dfEast - dfWest) / nRasterXSize;
     const double dfPixelYSize = (dfNorth - dfSouth) / nRasterYSize;
 
@@ -676,18 +588,18 @@ int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataTyp
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = dfNorth;
     adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = - dfPixelYSize;
+    adfGeoTransform[5] = -dfPixelYSize;
 
-    if( (i = CSLFindString( papszTokens, "null" )) >= 0 &&
+    if( (i = CSLFindString(papszTokens, "null")) >= 0 &&
         i + 1 < nTokens)
     {
-        const char* pszNoData = papszTokens[i + 1];
+        const char *pszNoData = papszTokens[i + 1];
 
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
         dfNoDataValue = CPLAtofM(pszNoData);
         if( pszDataType == NULL &&
-            (strchr( pszNoData, '.' ) != NULL ||
-             strchr( pszNoData, ',' ) != NULL ||
+            (strchr(pszNoData, '.') != NULL ||
+             strchr(pszNoData, ',') != NULL ||
              INT_MIN > dfNoDataValue || dfNoDataValue > INT_MAX) )
         {
             eDataType = GDT_Float32;
@@ -696,14 +608,14 @@ int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataTyp
         {
             // TODO(schwehr): Is this really what we want?
             dfNoDataValue =
-                static_cast<double>( static_cast<float>( dfNoDataValue ) );
+                static_cast<double>(static_cast<float>(dfNoDataValue));
         }
     }
 
-    if( (i = CSLFindString( papszTokens, "type" )) >= 0 &&
+    if( (i = CSLFindString(papszTokens, "type")) >= 0 &&
         i + 1 < nTokens)
     {
-        const char* pszType = papszTokens[i + 1];
+        const char *pszType = papszTokens[i + 1];
         if (EQUAL(pszType, "int"))
             eDataType = GDT_Int32;
         else if (EQUAL(pszType, "float"))
@@ -712,8 +624,8 @@ int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataTyp
             eDataType = GDT_Float64;
         else
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Invalid value for type parameter : %s", pszType);
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Invalid value for type parameter : %s", pszType);
         }
     }
 
@@ -726,12 +638,10 @@ int GRASSASCIIDataset::ParseHeader(const char* pszHeader, const char* pszDataTyp
 /*                           CommonOpen()                               */
 /************************************************************************/
 
-GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
-                                            GridFormat eFormat )
+GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo *poOpenInfo,
+                                      GridFormat eFormat )
 {
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
+    // Create a corresponding GDALDataset.
     AAIGDataset *poDS = NULL;
 
     if (eFormat == FORMAT_AAIG)
@@ -739,74 +649,67 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
     else
         poDS = new GRASSASCIIDataset();
 
-    const char* pszDataTypeOption =
-        (eFormat == FORMAT_AAIG) ?
+    const char *pszDataTypeOption =
+        eFormat == FORMAT_AAIG ?
         "AAIGRID_DATATYPE" : "GRASSASCIIGRID_DATATYPE";
 
-    const char* pszDataType = CPLGetConfigOption(pszDataTypeOption, NULL);
+    const char *pszDataType = CPLGetConfigOption(pszDataTypeOption, NULL);
     if( pszDataType == NULL )
         pszDataType =
-            CSLFetchNameValue( poOpenInfo->papszOpenOptions, "DATATYPE" );
+            CSLFetchNameValue(poOpenInfo->papszOpenOptions, "DATATYPE");
     if (pszDataType != NULL)
     {
         poDS->eDataType = GDALGetDataTypeByName(pszDataType);
         if (!(poDS->eDataType == GDT_Int32 || poDS->eDataType == GDT_Float32 ||
               poDS->eDataType == GDT_Float64))
         {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                      "Unsupported value for %s : %s",
-                      pszDataTypeOption, pszDataType );
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "Unsupported value for %s : %s",
+                     pszDataTypeOption, pszDataType);
             poDS->eDataType = GDT_Int32;
             pszDataType = NULL;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Parse the header.                                               */
-/* -------------------------------------------------------------------- */
-    if (!poDS->ParseHeader((const char *) poOpenInfo->pabyHeader, pszDataType))
+    // Parse the header.
+    if (!poDS->ParseHeader((const char *)poOpenInfo->pabyHeader, pszDataType))
     {
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Open file with large file API.                                  */
-/* -------------------------------------------------------------------- */
-
-    poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
+    // Open file with large file API.
+    poDS->fp = VSIFOpenL(poOpenInfo->pszFilename, "r");
     if( poDS->fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "VSIFOpenL(%s) failed unexpectedly.",
-                  poOpenInfo->pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "VSIFOpenL(%s) failed unexpectedly.",
+                 poOpenInfo->pszFilename);
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Find the start of real data.                                    */
-/* -------------------------------------------------------------------- */
+    // Find the start of real data.
     int nStartOfData = 0;
 
-    for( int i = 2; true ; i++ )
+    for( int i = 2; true; i++ )
     {
         if( poOpenInfo->pabyHeader[i] == '\0' )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Couldn't find data values in ASCII Grid file.\n" );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Couldn't find data values in ASCII Grid file.");
             delete poDS;
             return NULL;
         }
 
-        if( poOpenInfo->pabyHeader[i-1] == '\n'
-            || poOpenInfo->pabyHeader[i-2] == '\n'
-            || poOpenInfo->pabyHeader[i-1] == '\r'
-            || poOpenInfo->pabyHeader[i-2] == '\r' )
+        if( poOpenInfo->pabyHeader[i - 1] == '\n' ||
+            poOpenInfo->pabyHeader[i - 2] == '\n' ||
+            poOpenInfo->pabyHeader[i - 1] == '\r' ||
+            poOpenInfo->pabyHeader[i - 2] == '\r' )
         {
-            if( !isalpha(poOpenInfo->pabyHeader[i])
-                && poOpenInfo->pabyHeader[i] != '\n'
-                && poOpenInfo->pabyHeader[i] != '\r')
+            if( !isalpha(poOpenInfo->pabyHeader[i]) &&
+                poOpenInfo->pabyHeader[i] != '\n' &&
+                poOpenInfo->pabyHeader[i] != '\r')
             {
                 nStartOfData = i;
 
@@ -816,17 +719,16 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Recognize the type of data.                                     */
-/* -------------------------------------------------------------------- */
-    CPLAssert( NULL != poDS->fp );
+    // Recognize the type of data.
+    CPLAssert(NULL != poDS->fp);
 
-    if( pszDataType == NULL && poDS->eDataType != GDT_Float32)
+    if( pszDataType == NULL &&
+        poDS->eDataType != GDT_Float32 && poDS->eDataType != GDT_Float64)
     {
-        /* Allocate 100K chunk + 1 extra byte for NULL character. */
+        // Allocate 100K chunk + 1 extra byte for NULL character.
         const size_t nChunkSize = 1024 * 100;
-        GByte* pabyChunk = static_cast<GByte *>(
-            VSI_CALLOC_VERBOSE( nChunkSize + 1, sizeof(GByte) ) );
+        GByte *pabyChunk = static_cast<GByte *>(
+            VSI_CALLOC_VERBOSE(nChunkSize + 1, sizeof(GByte)));
         if (pabyChunk == NULL)
         {
             delete poDS;
@@ -834,17 +736,17 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
         }
         pabyChunk[nChunkSize] = '\0';
 
-        if( VSIFSeekL( poDS->fp, nStartOfData, SEEK_SET ) < 0 )
+        if( VSIFSeekL(poDS->fp, nStartOfData, SEEK_SET) < 0 )
         {
             delete poDS;
-            VSIFree( pabyChunk );
+            VSIFree(pabyChunk);
             return NULL;
         }
 
-        /* Scan for dot in subsequent chunks of data. */
-        while( !VSIFEofL( poDS->fp) )
+        // Scan for dot in subsequent chunks of data.
+        while( !VSIFEofL(poDS->fp) )
         {
-            CPL_IGNORE_RET_VAL(VSIFReadL( pabyChunk, nChunkSize, 1, poDS->fp ));
+            CPL_IGNORE_RET_VAL(VSIFReadL(pabyChunk, nChunkSize, 1, poDS->fp));
 
             for( int i = 0; i < static_cast<int>(nChunkSize); i++)
             {
@@ -857,57 +759,51 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
             }
         }
 
-        /* Deallocate chunk. */
-        VSIFree( pabyChunk );
+        // Deallocate chunk.
+        VSIFree(pabyChunk);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
-    AAIGRasterBand* band = new AAIGRasterBand( poDS, nStartOfData );
-    poDS->SetBand( 1, band );
+    // Create band information objects.
+    AAIGRasterBand *band = new AAIGRasterBand(poDS, nStartOfData);
+    poDS->SetBand(1, band);
     if (band->panLineOffset == NULL)
     {
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try to read projection file.                                    */
-/* -------------------------------------------------------------------- */
-
-    char * const pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-    char * const pszBasename =
+    // Try to read projection file.
+    char *const pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
+    char *const pszBasename =
         CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
 
-    poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "prj" );
+    poDS->osPrjFilename = CPLFormFilename(pszDirname, pszBasename, "prj");
     int nRet = 0;
     {
         VSIStatBufL sStatBuf;
-        nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
+        nRet = VSIStatL(poDS->osPrjFilename, &sStatBuf);
     }
     if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename) )
     {
-        poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "PRJ" );
+        poDS->osPrjFilename = CPLFormFilename(pszDirname, pszBasename, "PRJ");
 
         VSIStatBufL sStatBuf;
-        nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
+        nRet = VSIStatL(poDS->osPrjFilename, &sStatBuf);
     }
 
     if( nRet == 0 )
     {
-        poDS->papszPrj = CSLLoad( poDS->osPrjFilename );
+        poDS->papszPrj = CSLLoad(poDS->osPrjFilename);
 
-        CPLDebug( "AAIGrid", "Loaded SRS from %s",
-                  poDS->osPrjFilename.c_str() );
+        CPLDebug("AAIGrid", "Loaded SRS from %s", poDS->osPrjFilename.c_str());
 
         OGRSpatialReference oSRS;
-        if( oSRS.importFromESRI( poDS->papszPrj ) == OGRERR_NONE )
+        if( oSRS.importFromESRI(poDS->papszPrj) == OGRERR_NONE )
         {
             // If geographic values are in seconds, we must transform.
             // Is there a code for minutes too?
-            if( oSRS.IsGeographic()
-                && EQUAL(OSR_GDS( poDS->papszPrj, "Units", ""), "DS") )
+            if( oSRS.IsGeographic() &&
+                EQUAL(OSR_GDS(poDS->papszPrj, "Units", ""), "DS") )
             {
                 poDS->adfGeoTransform[0] /= 3600.0;
                 poDS->adfGeoTransform[1] /= 3600.0;
@@ -917,25 +813,21 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
                 poDS->adfGeoTransform[5] /= 3600.0;
             }
 
-            CPLFree( poDS->pszProjection );
-            oSRS.exportToWkt( &(poDS->pszProjection) );
+            CPLFree(poDS->pszProjection);
+            oSRS.exportToWkt(&(poDS->pszProjection));
         }
     }
 
-    CPLFree( pszDirname );
-    CPLFree( pszBasename );
+    CPLFree(pszDirname);
+    CPLFree(pszBasename);
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    // Initialize any PAM information.
+    poDS->SetDescription(poOpenInfo->pszFilename);
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Check for external overviews.                                   */
-/* -------------------------------------------------------------------- */
+    // Check for external overviews.
     poDS->oOvManager.Initialize(
-        poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
+        poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles());
 
     return poDS;
 }
@@ -944,10 +836,10 @@ GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo * poOpenInfo,
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr AAIGDataset::GetGeoTransform( double * padfTransform )
+CPLErr AAIGDataset::GetGeoTransform( double *padfTransform )
 
 {
-    memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
+    memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
     return CE_None;
 }
 
@@ -955,182 +847,171 @@ CPLErr AAIGDataset::GetGeoTransform( double * padfTransform )
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char *AAIGDataset::GetProjectionRef()
-
-{
-    return pszProjection;
-}
+const char *AAIGDataset::GetProjectionRef() { return pszProjection; }
 
 /************************************************************************/
 /*                          CreateCopy()                                */
 /************************************************************************/
 
 GDALDataset * AAIGDataset::CreateCopy(
-    const char * pszFilename, GDALDataset *poSrcDS,
+    const char *pszFilename, GDALDataset *poSrcDS,
     int /* bStrict */,
-    char ** papszOptions,
-    GDALProgressFunc pfnProgress, void * pProgressData )
+    char **papszOptions,
+    GDALProgressFunc pfnProgress, void *pProgressData )
 {
     const int nBands = poSrcDS->GetRasterCount();
     const int nXSize = poSrcDS->GetRasterXSize();
     const int nYSize = poSrcDS->GetRasterYSize();
 
-/* -------------------------------------------------------------------- */
-/*      Some rudimentary checks                                         */
-/* -------------------------------------------------------------------- */
+    // Some rudimentary checks.
     if( nBands != 1 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "AAIG driver doesn't support %d bands.  Must be 1 band.\n",
-                  nBands );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "AAIG driver doesn't support %d bands.  Must be 1 band.",
+                 nBands);
 
         return NULL;
     }
 
-    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    if( !pfnProgress(0.0, NULL, pProgressData) )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Create the dataset.                                             */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fpImage = VSIFOpenL( pszFilename, "wt" );
+    // Create the dataset.
+    VSILFILE *fpImage = VSIFOpenL(pszFilename, "wt");
     if( fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unable to create file %s.\n",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Unable to create file %s.",
+                 pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write ASCII Grid file header                                    */
-/* -------------------------------------------------------------------- */
-    double      adfGeoTransform[6];
-    char        szHeader[2000];
+    // Write ASCII Grid file header.
+    double adfGeoTransform[6] = {};
+    char szHeader[2000] = {};
     const char *pszForceCellsize =
-        CSLFetchNameValue( papszOptions, "FORCE_CELLSIZE" );
-
-    poSrcDS->GetGeoTransform( adfGeoTransform );
-
-    if( ABS(adfGeoTransform[1]+adfGeoTransform[5]) < 0.0000001
-        || ABS(adfGeoTransform[1]-adfGeoTransform[5]) < 0.0000001
-        || (pszForceCellsize && CPLTestBool(pszForceCellsize)) )
-        CPLsnprintf( szHeader, sizeof(szHeader),
-                 "ncols        %d\n"
-                 "nrows        %d\n"
-                 "xllcorner    %.12f\n"
-                 "yllcorner    %.12f\n"
-                 "cellsize     %.12f\n",
-                 nXSize, nYSize,
-                 adfGeoTransform[0],
-                 adfGeoTransform[3] - nYSize * adfGeoTransform[1],
-                 adfGeoTransform[1] );
+        CSLFetchNameValue(papszOptions, "FORCE_CELLSIZE");
+
+    poSrcDS->GetGeoTransform(adfGeoTransform);
+
+    if( std::abs(adfGeoTransform[1] + adfGeoTransform[5]) < 0.0000001 ||
+        std::abs(adfGeoTransform[1]-adfGeoTransform[5]) < 0.0000001 ||
+        (pszForceCellsize && CPLTestBool(pszForceCellsize)) )
+    {
+        CPLsnprintf(
+            szHeader, sizeof(szHeader),
+            "ncols        %d\n"
+            "nrows        %d\n"
+            "xllcorner    %.12f\n"
+            "yllcorner    %.12f\n"
+            "cellsize     %.12f\n",
+            nXSize, nYSize,
+            adfGeoTransform[0],
+            adfGeoTransform[3] - nYSize * adfGeoTransform[1],
+            adfGeoTransform[1]);
+    }
     else
     {
         if( pszForceCellsize == NULL )
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Producing a Golden Surfer style file with DX and DY "
-                      "instead of CELLSIZE since the input pixels are "
-                      "non-square.  Use the FORCE_CELLSIZE=TRUE creation "
-                      "option to force use of DX for even though this will "
-                      "be distorted.  Most ASCII Grid readers (ArcGIS "
-                      "included) do not support the DX and DY parameters." );
-        CPLsnprintf( szHeader, sizeof(szHeader),
-                 "ncols        %d\n"
-                 "nrows        %d\n"
-                 "xllcorner    %.12f\n"
-                 "yllcorner    %.12f\n"
-                 "dx           %.12f\n"
-                 "dy           %.12f\n",
-                 nXSize, nYSize,
-                 adfGeoTransform[0],
-                 adfGeoTransform[3] + nYSize * adfGeoTransform[5],
-                 adfGeoTransform[1],
-                 fabs(adfGeoTransform[5]) );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Producing a Golden Surfer style file with DX and DY "
+                     "instead of CELLSIZE since the input pixels are "
+                     "non-square.  Use the FORCE_CELLSIZE=TRUE creation "
+                     "option to force use of DX for even though this will "
+                     "be distorted.  Most ASCII Grid readers (ArcGIS "
+                     "included) do not support the DX and DY parameters.");
+        CPLsnprintf(
+            szHeader, sizeof(szHeader),
+            "ncols        %d\n"
+            "nrows        %d\n"
+            "xllcorner    %.12f\n"
+            "yllcorner    %.12f\n"
+            "dx           %.12f\n"
+            "dy           %.12f\n",
+            nXSize, nYSize,
+            adfGeoTransform[0],
+            adfGeoTransform[3] + nYSize * adfGeoTransform[5],
+            adfGeoTransform[1],
+            fabs(adfGeoTransform[5]));
     }
 
-/* -------------------------------------------------------------------- */
-/*     Builds the format string used for printing float values.         */
-/* -------------------------------------------------------------------- */
+    // Builds the format string used for printing float values.
     char szFormatFloat[32] = { '\0' };
     strcpy(szFormatFloat, " %.20g");
     const char *pszDecimalPrecision =
-        CSLFetchNameValue( papszOptions, "DECIMAL_PRECISION" );
+        CSLFetchNameValue(papszOptions, "DECIMAL_PRECISION");
     const char *pszSignificantDigits =
-        CSLFetchNameValue( papszOptions, "SIGNIFICANT_DIGITS" );
+        CSLFetchNameValue(papszOptions, "SIGNIFICANT_DIGITS");
     bool bIgnoreSigDigits = false;
     if( pszDecimalPrecision && pszSignificantDigits )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Conflicting precision arguments, using DECIMAL_PRECISION" );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Conflicting precision arguments, using DECIMAL_PRECISION");
         bIgnoreSigDigits = true;
     }
     int nPrecision;
     if ( pszSignificantDigits && !bIgnoreSigDigits )
     {
-        nPrecision = atoi( pszSignificantDigits );
+        nPrecision = atoi(pszSignificantDigits);
         if (nPrecision >= 0)
-            snprintf( szFormatFloat, sizeof(szFormatFloat),
-                      " %%.%dg", nPrecision );
-        CPLDebug( "AAIGrid", "Setting precision format: %s", szFormatFloat );
+            snprintf(szFormatFloat, sizeof(szFormatFloat), " %%.%dg",
+                     nPrecision);
+        CPLDebug("AAIGrid", "Setting precision format: %s", szFormatFloat);
     }
     else if( pszDecimalPrecision )
     {
-        nPrecision = atoi( pszDecimalPrecision );
+        nPrecision = atoi(pszDecimalPrecision);
         if ( nPrecision >= 0 )
-            snprintf( szFormatFloat, sizeof(szFormatFloat),
-                      " %%.%df", nPrecision );
-        CPLDebug( "AAIGrid", "Setting precision format: %s", szFormatFloat );
+            snprintf(szFormatFloat, sizeof(szFormatFloat), " %%.%df",
+                     nPrecision);
+        CPLDebug("AAIGrid", "Setting precision format: %s", szFormatFloat);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Handle nodata (optionally).                                     */
-/* -------------------------------------------------------------------- */
-    GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
+    // Handle nodata (optionally).
+    GDALRasterBand *poBand = poSrcDS->GetRasterBand(1);
     const bool bReadAsInt =
-        poBand->GetRasterDataType() == GDT_Byte
-        || poBand->GetRasterDataType() == GDT_Int16
-        || poBand->GetRasterDataType() == GDT_UInt16
-        || poBand->GetRasterDataType() == GDT_Int32;
+        poBand->GetRasterDataType() == GDT_Byte ||
+        poBand->GetRasterDataType() == GDT_Int16 ||
+        poBand->GetRasterDataType() == GDT_UInt16 ||
+        poBand->GetRasterDataType() == GDT_Int32;
 
     // Write `nodata' value to header if it is exists in source dataset
     int bSuccess = FALSE;
-    const double dfNoData = poBand->GetNoDataValue( &bSuccess );
+    const double dfNoData = poBand->GetNoDataValue(&bSuccess);
     if ( bSuccess )
     {
-        snprintf( szHeader+strlen( szHeader ),
-                  sizeof(szHeader) - strlen(szHeader), "%s", "NODATA_value " );
+        snprintf(szHeader + strlen(szHeader),
+                 sizeof(szHeader) - strlen(szHeader), "%s", "NODATA_value ");
         if( bReadAsInt )
-            snprintf( szHeader+strlen( szHeader ),
-                      sizeof(szHeader) - strlen(szHeader), "%d",
-                      static_cast<int>(dfNoData) );
+            snprintf(szHeader + strlen(szHeader),
+                     sizeof(szHeader) - strlen(szHeader), "%d",
+                     static_cast<int>(dfNoData));
         else
-            CPLsnprintf( szHeader+strlen( szHeader ),
-                         sizeof(szHeader) - strlen(szHeader),
-                         szFormatFloat, dfNoData );
-        snprintf( szHeader+strlen( szHeader ),
-                  sizeof(szHeader) - strlen(szHeader), "%s", "\n" );
+            CPLsnprintf(szHeader + strlen(szHeader),
+                        sizeof(szHeader) - strlen(szHeader),
+                        szFormatFloat, dfNoData);
+        snprintf(szHeader + strlen(szHeader),
+                 sizeof(szHeader) - strlen(szHeader), "%s", "\n");
     }
 
-    if( VSIFWriteL( szHeader, strlen(szHeader), 1, fpImage ) != 1)
+    if( VSIFWriteL(szHeader, strlen(szHeader), 1, fpImage) != 1)
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpImage));
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Loop over image, copying image data.                            */
-/* -------------------------------------------------------------------- */
-    int *panScanline = NULL;
-    double *padfScanline = NULL;
+    // Loop over image, copying image data.
 
     // Write scanlines to output file
-    if (bReadAsInt)
-        panScanline = static_cast<int *>(
-            CPLMalloc( nXSize * GDALGetDataTypeSize(GDT_Int32) / 8 ) );
-    else
-        padfScanline = static_cast<double *>(
-            CPLMalloc( nXSize * GDALGetDataTypeSize(GDT_Float64) / 8 ) );
+    int *panScanline = bReadAsInt
+                           ? static_cast<int *>(CPLMalloc(
+                                 nXSize * GDALGetDataTypeSizeBytes(GDT_Int32)))
+                           : NULL;
+
+    double *padfScanline =
+        bReadAsInt ? NULL
+                   : static_cast<double *>(CPLMalloc(
+                         nXSize * GDALGetDataTypeSizeBytes(GDT_Float64)));
 
     CPLErr eErr = CE_None;
 
@@ -1143,23 +1024,23 @@ GDALDataset * AAIGDataset::CreateCopy(
             bReadAsInt ? reinterpret_cast<void *>(panScanline) :
             reinterpret_cast<void *>(padfScanline),
             nXSize, 1, bReadAsInt ? GDT_Int32 : GDT_Float64,
-            0, 0, NULL );
+            0, 0, NULL);
 
         if( bReadAsInt )
         {
             for ( int iPixel = 0; iPixel < nXSize; iPixel++ )
             {
-                snprintf( szHeader, sizeof(szHeader),
-                          " %d", panScanline[iPixel] );
+                snprintf(szHeader, sizeof(szHeader),
+                         " %d", panScanline[iPixel]);
                 osBuf += szHeader;
                 if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 )
                 {
-                    if ( VSIFWriteL( osBuf, static_cast<int>(osBuf.size()), 1,
-                                     fpImage ) != 1 )
+                    if ( VSIFWriteL(osBuf, static_cast<int>(osBuf.size()), 1,
+                                    fpImage) != 1 )
                     {
                         eErr = CE_Failure;
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Write failed, disk full?\n" );
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Write failed, disk full?");
                         break;
                     }
                     osBuf = "";
@@ -1170,8 +1051,8 @@ GDALDataset * AAIGDataset::CreateCopy(
         {
             for ( int iPixel = 0; iPixel < nXSize; iPixel++ )
             {
-                CPLsnprintf( szHeader, sizeof(szHeader),
-                             szFormatFloat, padfScanline[iPixel] );
+                CPLsnprintf(szHeader, sizeof(szHeader),
+                            szFormatFloat, padfScanline[iPixel]);
 
                 // Make sure that as least one value has a decimal point (#6060)
                 if( !bHasOutputDecimalDot )
@@ -1192,97 +1073,93 @@ GDALDataset * AAIGDataset::CreateCopy(
                 osBuf += szHeader;
                 if( (iPixel & 1023) == 0 || iPixel == nXSize - 1 )
                 {
-                    if ( VSIFWriteL( osBuf, (int)osBuf.size(), 1,
-                                     fpImage ) != 1 )
+                  if ( VSIFWriteL(osBuf, static_cast<int>(osBuf.size()), 1,
+                                  fpImage) != 1 )
                     {
                         eErr = CE_Failure;
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Write failed, disk full?\n" );
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Write failed, disk full?");
                         break;
                     }
                     osBuf = "";
                 }
             }
         }
-        if( VSIFWriteL( (void *) "\n", 1, 1, fpImage ) != 1 )
+        if( VSIFWriteL("\n", 1, 1, fpImage) != 1 )
             eErr = CE_Failure;
 
         if( eErr == CE_None &&
-            !pfnProgress( (iLine + 1) / static_cast<double>(nYSize), NULL,
-                          pProgressData) )
+            !pfnProgress((iLine + 1) / static_cast<double>(nYSize), NULL,
+                         pProgressData) )
         {
             eErr = CE_Failure;
-            CPLError( CE_Failure, CPLE_UserInterrupt,
-                      "User terminated CreateCopy()" );
+            CPLError(CE_Failure, CPLE_UserInterrupt,
+                     "User terminated CreateCopy()");
         }
     }
 
-    CPLFree( panScanline );
-    CPLFree( padfScanline );
-    if( VSIFCloseL( fpImage ) != 0 )
+    CPLFree(panScanline);
+    CPLFree(padfScanline);
+    if( VSIFCloseL(fpImage) != 0 )
         eErr = CE_Failure;
 
     if( eErr != CE_None )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Try to write projection file.                                   */
-/* -------------------------------------------------------------------- */
+    // Try to write projection file.
     const char *pszOriginalProjection = poSrcDS->GetProjectionRef();
-    if( !EQUAL( pszOriginalProjection, "" ) )
+    if( !EQUAL(pszOriginalProjection, "") )
     {
-        char *pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
-        char *pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
-        char *pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
-        VSILFILE *fp = VSIFOpenL( pszPrjFilename, "wt" );
+        char *pszDirname = CPLStrdup(CPLGetPath(pszFilename));
+        char *pszBasename = CPLStrdup(CPLGetBasename(pszFilename));
+        char *pszPrjFilename =
+            CPLStrdup(CPLFormFilename(pszDirname, pszBasename, "prj"));
+        VSILFILE *fp = VSIFOpenL(pszPrjFilename, "wt");
         if (fp != NULL)
         {
             OGRSpatialReference oSRS;
             // TODO(schwehr): importFromWkt should be const for the args.
-            oSRS.importFromWkt( const_cast<char **>( &pszOriginalProjection ) );
+            oSRS.importFromWkt(const_cast<char **>(&pszOriginalProjection));
             oSRS.morphToESRI();
             char *pszESRIProjection = NULL;
-            oSRS.exportToWkt( &pszESRIProjection );
-            CPL_IGNORE_RET_VAL(
-                VSIFWriteL( pszESRIProjection, 1,
-                            strlen(pszESRIProjection), fp ) );
+            oSRS.exportToWkt(&pszESRIProjection);
+            CPL_IGNORE_RET_VAL(VSIFWriteL(pszESRIProjection, 1,
+                                          strlen(pszESRIProjection), fp));
 
-            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
-            CPLFree( pszESRIProjection );
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+            CPLFree(pszESRIProjection);
         }
         else
         {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Unable to create file %s.\n", pszPrjFilename );
+            CPLError(CE_Failure, CPLE_FileIO, "Unable to create file %s.",
+                     pszPrjFilename);
         }
-        CPLFree( pszDirname );
-        CPLFree( pszBasename );
-        CPLFree( pszPrjFilename );
+        CPLFree(pszDirname);
+        CPLFree(pszBasename);
+        CPLFree(pszPrjFilename);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Re-open dataset, and copy any auxiliary pam information.         */
-/* -------------------------------------------------------------------- */
+    // Re-open dataset, and copy any auxiliary pam information.
 
-    /* If writing to stdout, we can't reopen it, so return */
-    /* a fake dataset to make the caller happy */
+    // If writing to stdout, we can't reopen it, so return
+    // a fake dataset to make the caller happy.
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    GDALPamDataset* poDS =
-        reinterpret_cast<GDALPamDataset *>( GDALOpen(pszFilename, GA_ReadOnly) );
+    GDALPamDataset *poDS =
+        reinterpret_cast<GDALPamDataset *>(GDALOpen(pszFilename, GA_ReadOnly));
     CPLPopErrorHandler();
     if (poDS)
     {
-        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+        poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT);
         return poDS;
     }
 
     CPLErrorReset();
 
-    AAIGDataset* poAAIG_DS = new AAIGDataset();
+    AAIGDataset *poAAIG_DS = new AAIGDataset();
     poAAIG_DS->nRasterXSize = nXSize;
     poAAIG_DS->nRasterYSize = nYSize;
     poAAIG_DS->nBands = 1;
-    poAAIG_DS->SetBand( 1, new AAIGRasterBand( poAAIG_DS, 1 ) );
+    poAAIG_DS->SetBand(1, new AAIGRasterBand(poAAIG_DS, 1));
     return poAAIG_DS;
 }
 
@@ -1290,7 +1167,7 @@ GDALDataset * AAIGDataset::CreateCopy(
 /*                              OSR_GDS()                               */
 /************************************************************************/
 
-static CPLString OSR_GDS( char **papszNV, const char * pszField,
+static CPLString OSR_GDS( char **papszNV, const char *pszField,
                           const char *pszDefaultValue )
 
 {
@@ -1315,7 +1192,7 @@ static CPLString OSR_GDS( char **papszNV, const char * pszField,
         else
             osResult = pszDefaultValue;
 
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
         return osResult;
     }
 }
@@ -1327,41 +1204,40 @@ static CPLString OSR_GDS( char **papszNV, const char * pszField,
 void GDALRegister_AAIGrid()
 
 {
-    if( GDALGetDriverByName( "AAIGrid" ) != NULL )
+    if( GDALGetDriverByName("AAIGrid") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "AAIGrid" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Arc/Info ASCII Grid" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                               "frmt_various.html#AAIGrid" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "asc" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                               "Byte UInt16 Int16 Int32 Float32" );
-
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetDescription("AAIGrid");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Arc/Info ASCII Grid");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#AAIGrid");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "asc");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
+                              "Byte UInt16 Int16 Int32 Float32");
+
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>\n"
 "   <Option name='FORCE_CELLSIZE' type='boolean' description='Force use of CELLSIZE, default is FALSE.'/>\n"
 "   <Option name='DECIMAL_PRECISION' type='int' description='Number of decimal when writing floating-point numbers(%f).'/>\n"
 "   <Option name='SIGNIFICANT_DIGITS' type='int' description='Number of significant digits when writing floating-point numbers(%g).'/>\n"
-"</CreationOptionList>\n" );
-    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"</CreationOptionList>\n");
+    poDriver->SetMetadataItem(GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionLists>\n"
 "   <Option name='DATATYPE' type='string-select' description='Data type to be used.'>\n"
 "       <Value>Int32</Value>\n"
 "       <Value>Float32</Value>\n"
 "       <Value>Float64</Value>\n"
 "   </Option>\n"
-"</OpenOptionLists>\n" );
+"</OpenOptionLists>\n");
 
     poDriver->pfnOpen = AAIGDataset::Open;
     poDriver->pfnIdentify = AAIGDataset::Identify;
     poDriver->pfnCreateCopy = AAIGDataset::CreateCopy;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
 
 /************************************************************************/
@@ -1371,21 +1247,21 @@ void GDALRegister_AAIGrid()
 void GDALRegister_GRASSASCIIGrid()
 
 {
-    if( GDALGetDriverByName( "GRASSASCIIGrid" ) != NULL )
+    if( GDALGetDriverByName("GRASSASCIIGrid") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "GRASSASCIIGrid" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GRASS ASCII Grid" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                               "frmt_various.html#GRASSASCIIGrid" );
+    poDriver->SetDescription("GRASSASCIIGrid");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "GRASS ASCII Grid");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
+                              "frmt_various.html#GRASSASCIIGrid");
 
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
 
     poDriver->pfnOpen = GRASSASCIIDataset::Open;
     poDriver->pfnIdentify = GRASSASCIIDataset::Identify;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/aaigrid/aaigriddataset.h b/frmts/aaigrid/aaigriddataset.h
new file mode 100644
index 0000000..7eaf058
--- /dev/null
+++ b/frmts/aaigrid/aaigriddataset.h
@@ -0,0 +1,169 @@
+/******************************************************************************
+ * $Id: aaigriddataset.h 37591 2017-03-04 15:02:53Z goatbar $
+ *
+ * Project:  GDAL
+ * Purpose:  Implements Arc/Info ASCII Grid Format.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2001, Frank Warmerdam (warmerdam at pobox.com)
+ * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2014, Kyle Shannon <kyle at pobox dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDAL_FRMTS_AAIGRID_AAIGRIDDATASET_H_INCLUDED
+#define GDAL_FRMTS_AAIGRID_AAIGRIDDATASET_H_INCLUDED
+
+// We need cpl_port as first include to avoid VSIStatBufL being not
+// defined on i586-mingw32msvc.
+#include "cpl_port.h"
+#include "gdal_frmts.h"
+
+#include <cctype>
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
+#include <limits>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
+#include "ogr_spatialref.h"
+
+typedef enum
+{
+    FORMAT_AAIG,
+    FORMAT_GRASSASCII
+} GridFormat;
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              AAIGDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class AAIGRasterBand;
+
+class CPL_DLL AAIGDataset : public GDALPamDataset
+{
+    friend class AAIGRasterBand;
+
+    VSILFILE   *fp;
+
+    char        **papszPrj;
+    CPLString   osPrjFilename;
+    char        *pszProjection;
+
+    unsigned char achReadBuf[256];
+    GUIntBig    nBufferOffset;
+    int         nOffsetInBuffer;
+
+    char        Getc();
+    GUIntBig    Tell();
+    int         Seek( GUIntBig nOffset );
+
+  protected:
+    GDALDataType eDataType;
+    double      adfGeoTransform[6];
+    bool        bNoDataSet;
+    double      dfNoDataValue;
+
+    virtual int ParseHeader(const char* pszHeader, const char* pszDataType);
+
+  public:
+                AAIGDataset();
+       virtual ~AAIGDataset();
+
+    virtual char **GetFileList(void) override;
+
+    static GDALDataset *CommonOpen( GDALOpenInfo * poOpenInfo,
+                                    GridFormat eFormat );
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+    static CPLErr       Delete( const char *pszFilename );
+    static CPLErr       Remove( const char *pszFilename, int bRepError );
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
+
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char *GetProjectionRef(void) override;
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                        GRASSASCIIDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class GRASSASCIIDataset : public AAIGDataset
+{
+    virtual int ParseHeader(const char* pszHeader, const char* pszDataType) override;
+
+  public:
+                GRASSASCIIDataset() : AAIGDataset() {}
+       virtual ~GRASSASCIIDataset() {}
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            AAIGRasterBand                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class AAIGRasterBand : public GDALPamRasterBand
+{
+    friend class AAIGDataset;
+
+    GUIntBig      *panLineOffset;
+
+  public:
+
+                   AAIGRasterBand( AAIGDataset *, int );
+    virtual       ~AAIGRasterBand();
+
+    virtual double GetNoDataValue( int * ) override;
+    virtual CPLErr SetNoDataValue( double ) override;
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+};
+
+#endif  // GDAL_FRMTS_AAIGRID_AAIGRIDDATASET_H_INCLUDED
diff --git a/frmts/adrg/adrgdataset.cpp b/frmts/adrg/adrgdataset.cpp
index 79e989b..65318ea 100644
--- a/frmts/adrg/adrgdataset.cpp
+++ b/frmts/adrg/adrgdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: adrgdataset.cpp 37158 2017-01-16 18:05:41Z rouault $
  *
  * Purpose:  ADRG reader
  * Author:   Even Rouault, even.rouault at mines-paris.org
@@ -32,7 +31,7 @@
 #include "iso8211.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: adrgdataset.cpp 37158 2017-01-16 18:05:41Z rouault $");
+CPL_CVSID("$Id: adrgdataset.cpp 37157 2017-01-16 18:04:24Z rouault $");
 
 #define N_ELEMENTS(x)  (sizeof(x)/sizeof(x[0]))
 
@@ -77,14 +76,14 @@ class ADRGDataset : public GDALPamDataset
                  ADRGDataset();
     virtual     ~ADRGDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * padfGeoTransform );
-    virtual CPLErr SetGeoTransform( double * padfGeoTransform );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * padfGeoTransform ) override;
+    virtual CPLErr SetGeoTransform( double * padfGeoTransform ) override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
 
-    virtual char      **GetFileList();
+    virtual char      **GetFileList() override;
 
     void                AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName );
 
@@ -112,17 +111,16 @@ class ADRGRasterBand : public GDALPamRasterBand
   public:
                             ADRGRasterBand( ADRGDataset *, int );
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual CPLErr          IWriteBlock( int, int, void * );
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual CPLErr          IWriteBlock( int, int, void * ) override;
 
-    virtual double          GetNoDataValue( int *pbSuccess = NULL );
+    virtual double          GetNoDataValue( int *pbSuccess = NULL ) override;
 
 //    virtual int             GetOverviewCount();
 //    virtual GDALRasterBand* GetOverview(int i);
 };
 
-
 /************************************************************************/
 /*                           ADRGRasterBand()                            */
 /************************************************************************/
@@ -130,8 +128,8 @@ class ADRGRasterBand : public GDALPamRasterBand
 ADRGRasterBand::ADRGRasterBand( ADRGDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Byte;
 
@@ -185,7 +183,7 @@ GDALRasterBand *ADRGRasterBand::GetOverview( int i )
 
 double ADRGRasterBand::GetNoDataValue( int *pbSuccess )
 {
-    if (pbSuccess)
+    if( pbSuccess )
         *pbSuccess = TRUE;
 
     return 0.0;
@@ -212,23 +210,24 @@ GDALColorInterp ADRGRasterBand::GetColorInterpretation()
 /************************************************************************/
 
 CPLErr ADRGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                  void * pImage )
+                                   void * pImage )
 
 {
     ADRGDataset* l_poDS = (ADRGDataset*)this->poDS;
     int nBlock = nBlockYOff * l_poDS->NFC + nBlockXOff;
-    if (nBlockXOff >= l_poDS->NFC || nBlockYOff >= l_poDS->NFL)
+    if( nBlockXOff >= l_poDS->NFC || nBlockYOff >= l_poDS->NFL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
                  nBlockXOff, l_poDS->NFC, nBlockYOff, l_poDS->NFL);
         return CE_Failure;
     }
     CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
 
     int offset;
-    if (l_poDS->TILEINDEX)
+    if( l_poDS->TILEINDEX )
     {
-        if (l_poDS->TILEINDEX[nBlock] == 0)
+        if( l_poDS->TILEINDEX[nBlock] == 0 )
         {
             memset(pImage, 0, 128 * 128);
             return CE_None;
@@ -238,12 +237,12 @@ CPLErr ADRGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     else
         offset = l_poDS->offsetInIMG + nBlock * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
 
-    if (VSIFSeekL(l_poDS->fdIMG, offset, SEEK_SET) != 0)
+    if( VSIFSeekL(l_poDS->fdIMG, offset, SEEK_SET) != 0 )
     {
         CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
         return CE_Failure;
     }
-    if (VSIFReadL(pImage, 1, 128 * 128, l_poDS->fdIMG) != 128 * 128)
+    if( VSIFReadL(pImage, 1, 128 * 128, l_poDS->fdIMG) != 128 * 128 )
     {
         CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
         return CE_Failure;
@@ -257,16 +256,16 @@ CPLErr ADRGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-                                  void * pImage )
+                                    void * pImage )
 
 {
     ADRGDataset* l_poDS = (ADRGDataset*)this->poDS;
     int nBlock = nBlockYOff * l_poDS->NFC + nBlockXOff;
-    if (l_poDS->eAccess != GA_Update)
+    if( l_poDS->eAccess != GA_Update )
     {
         return CE_Failure;
     }
-    if (nBlockXOff >= l_poDS->NFC || nBlockYOff >= l_poDS->NFL)
+    if( nBlockXOff >= l_poDS->NFC || nBlockYOff >= l_poDS->NFL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "nBlockXOff=%d, NFC=%d, nBlockYOff=%d, NFL=%d",
                  nBlockXOff, l_poDS->NFC, nBlockYOff, l_poDS->NFL);
@@ -274,16 +273,16 @@ CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     }
     CPLDebug("ADRG", "(%d,%d) -> nBlock = %d", nBlockXOff, nBlockYOff, nBlock);
 
-    if (l_poDS->TILEINDEX[nBlock] == 0)
+    if( l_poDS->TILEINDEX[nBlock] == 0 )
     {
         unsigned int i;
         int* pi = (int*)pImage;
         for(i=0;i<128*128 / sizeof(int);i++)
         {
-            if (pi[i])
+            if( pi[i] )
                 break;
         }
-        if (i == 128*128 / sizeof(int))
+        if( i == 128*128 / sizeof(int) )
         {
             return CE_None;
         }
@@ -291,15 +290,17 @@ CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         l_poDS->TILEINDEX[nBlock] = l_poDS->nNextAvailableBlock ++;
     }
 
-    int offset
-        = l_poDS->offsetInIMG + (l_poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 + (nBand - 1) * 128 * 128;
+    const int offset =
+        l_poDS->offsetInIMG +
+        (l_poDS->TILEINDEX[nBlock] - 1) * 128 * 128 * 3 +
+        (nBand - 1) * 128 * 128;
 
-    if (VSIFSeekL(l_poDS->fdIMG, offset, SEEK_SET) != 0)
+    if( VSIFSeekL(l_poDS->fdIMG, offset, SEEK_SET) != 0 )
     {
         CPLError(CE_Failure, CPLE_FileIO, "Cannot seek to offset %d", offset);
         return CE_Failure;
     }
-    if (VSIFWriteL(pImage, 1, 128 * 128, l_poDS->fdIMG) != 128 * 128)
+    if( VSIFWriteL(pImage, 1, 128 * 128, l_poDS->fdIMG) != 128 * 128 )
     {
         CPLError(CE_Failure, CPLE_FileIO, "Cannot read data at offset %d", offset);
         return CE_Failure;
@@ -308,11 +309,12 @@ CPLErr ADRGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     return CE_None;
 }
 
-static unsigned int WriteSubFieldStr(VSILFILE* fd, const char* pszStr, unsigned int size)
+static unsigned int WriteSubFieldStr( VSILFILE* fd, const char* pszStr,
+                                      unsigned int size )
 {
     char* str = (char*)CPLMalloc(size+1);
     memset(str, ' ', size);
-    if (strlen(pszStr) > size)
+    if( strlen(pszStr) > size )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "strlen(pszStr) > size");
         CPLFree(str);
@@ -329,7 +331,7 @@ static unsigned int WriteSubFieldInt(VSILFILE* fd, int val, unsigned int size)
 {
     char* str = (char*)CPLMalloc(size+1);
     char formatStr[32];
-    snprintf( formatStr, sizeof(formatStr), "%%0%dd", size);
+    snprintf( formatStr, sizeof(formatStr), "%%0%ud", size);
     snprintf( str, size+1, formatStr, val);
     VSIFWriteL(str, 1, size, fd);
     CPLFree(str);
@@ -353,11 +355,11 @@ static unsigned int WriteUnitTerminator(VSILFILE* fd)
 static unsigned int WriteLongitude(VSILFILE* fd, double val)
 {
     char str[11+1];
-    char sign = (val >= 0) ? '+' : '-';
-    if (val < 0) val = -val;
-    int ddd = (int)val;
-    int mm = (int)((val - ddd) * 60);
-    double ssdotss = ((val - ddd) * 60 - mm) * 60;
+    const char sign = (val >= 0) ? '+' : '-';
+    if( val < 0 ) val = -val;
+    const int ddd = (int)val;
+    const int mm = (int)((val - ddd) * 60);
+    const double ssdotss = ((val - ddd) * 60 - mm) * 60;
     snprintf(str, sizeof(str), "%c%03d%02d%05.2f", sign, ddd, mm, ssdotss);
     CPLAssert((int)strlen(str) == 11);
     VSIFWriteL(str, 1, 11, fd);
@@ -367,11 +369,11 @@ static unsigned int WriteLongitude(VSILFILE* fd, double val)
 static unsigned int WriteLatitude(VSILFILE* fd, double val)
 {
     char str[10+1];
-    char sign = (val >= 0) ? '+' : '-';
-    if (val < 0) val = -val;
-    int dd = (int)val;
-    int mm = (int)((val - dd) * 60);
-    double ssdotss = ((val - dd) * 60 - mm) * 60;
+    const char sign = (val >= 0) ? '+' : '-';
+    if( val < 0 ) val = -val;
+    const int dd = (int)val;
+    const int mm = (int)((val - dd) * 60);
+    const double ssdotss = ((val - dd) * 60 - mm) * 60;
     snprintf(str, sizeof(str), "%c%02d%02d%05.2f", sign, dd, mm, ssdotss);
     CPLAssert((int)strlen(str) == 10);
     VSIFWriteL(str, 1, 10, fd);
@@ -386,10 +388,12 @@ static int BeginLeader(VSILFILE* fd, int sizeFieldLength, int sizeFieldPos, int
     return pos;
 }
 
-static void FinishWriteLeader(VSILFILE* fd, int beginPos, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
-                             int nFields, int* sizeOfFields, const char** nameOfFields)
+static void FinishWriteLeader( VSILFILE* fd, int beginPos, int sizeFieldLength,
+                               int sizeFieldPos, int sizeFieldTag,
+                               int nFields, int* sizeOfFields,
+                               const char** nameOfFields )
 {
-    int endPos = (int)VSIFTellL(fd);
+    const int endPos = (int)VSIFTellL(fd);
     VSIFSeekL(fd, beginPos, SEEK_SET);
 
     int nLeaderSize = 24;
@@ -398,12 +402,14 @@ static void FinishWriteLeader(VSILFILE* fd, int beginPos, int sizeFieldLength, i
 
     int nDataSize = 0;
     int nFieldOffset = 0;
-    for(int i=0;i<nFields;i++)
+    for( int i = 0; i < nFields; i++ )
         nDataSize += sizeOfFields[i];
-    nFieldOffset = (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
+    nFieldOffset =
+        (sizeFieldLength + sizeFieldPos + sizeFieldTag) * nFields + 1;
     nDataSize += nFieldOffset;
 
-    snprintf( szLeader+0, sizeof(szLeader)-0, "%05d", (int) (nDataSize + nLeaderSize) );
+    snprintf( szLeader+0, sizeof(szLeader)-0,
+              "%05d", (int) (nDataSize + nLeaderSize) );
     szLeader[5] = ' ';
     szLeader[6] = 'D';
 
@@ -430,7 +436,6 @@ static void FinishWriteLeader(VSILFILE* fd, int beginPos, int sizeFieldLength, i
     VSIFSeekL(fd, endPos, SEEK_SET);
 }
 
-
 static int BeginHeader(VSILFILE* fd, int sizeFieldLength, int sizeFieldPos, int sizeFieldTag,
                        int nFields)
 {
@@ -490,7 +495,7 @@ static int WriteFieldDecl(VSILFILE* fd, char _data_struct_code , char _data_type
 {
     VSIFWriteL(&_data_struct_code, 1, 1, fd);
     VSIFWriteL(&_data_type_code, 1, 1, fd);
-    if (_data_struct_code == ' ')
+    if( _data_struct_code == ' ' )
     {
         VSIFWriteL("    ", 1 , 4, fd);
     }
@@ -501,7 +506,7 @@ static int WriteFieldDecl(VSILFILE* fd, char _data_struct_code , char _data_type
     int len = 6;
     VSIFWriteL(_fieldName, 1, strlen(_fieldName), fd);
     len += static_cast<int>(strlen(_fieldName));
-    if (_arrayDescr[0])
+    if( _arrayDescr[0] )
     {
         len += WriteUnitTerminator(fd);
         VSIFWriteL(_arrayDescr, 1, strlen(_arrayDescr), fd);
@@ -515,22 +520,29 @@ static int WriteFieldDecl(VSILFILE* fd, char _data_struct_code , char _data_type
     return len;
 }
 
-
 /************************************************************************/
 /*                          ADRGDataset()                               */
 /************************************************************************/
 
 ADRGDataset::ADRGDataset() :
-    offsetInIMG(0), NFC(0), NFL(0), LSO(0.0), PSO(0.0), ARV(0), BRV(0),
-    bGeoTransformValid(0), nNextAvailableBlock(0)
+    fdIMG(NULL),
+    TILEINDEX(NULL),
+    offsetInIMG(0),
+    NFC(0),
+    NFL(0),
+    LSO(0.0),
+    PSO(0.0),
+    ARV(0),
+    BRV(0),
+    papszSubDatasets(NULL),
+    poOverviewDS(NULL),
+    bCreation(FALSE),
+    fdGEN(NULL),
+    fdTHF(NULL),
+    bGeoTransformValid(0),
+    nNextAvailableBlock(0)
 {
-    bCreation = FALSE;
-    poOverviewDS = NULL;
-    fdIMG = NULL;
-    fdGEN = NULL;
-    fdTHF = NULL;
-    TILEINDEX = NULL;
-    papszSubDatasets = NULL;
+    memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
 }
 
 /************************************************************************/
@@ -539,14 +551,14 @@ ADRGDataset::ADRGDataset() :
 
 ADRGDataset::~ADRGDataset()
 {
-    if (poOverviewDS)
+    if( poOverviewDS )
     {
         delete poOverviewDS;
     }
 
     CSLDestroy(papszSubDatasets);
 
-    if (bCreation)
+    if( bCreation )
     {
         GDALPamDataset::FlushCache();
 
@@ -614,21 +626,21 @@ ADRGDataset::~ADRGDataset()
         WriteTHFFile();
     }
 
-    if (fdIMG)
+    if( fdIMG )
     {
         VSIFCloseL(fdIMG);
     }
 
-    if (fdGEN)
+    if( fdGEN )
     {
         VSIFCloseL(fdGEN);
     }
-    if (fdTHF)
+    if( fdTHF )
     {
         VSIFCloseL(fdTHF);
     }
 
-    if (TILEINDEX)
+    if( TILEINDEX )
     {
         delete [] TILEINDEX;
     }
@@ -642,17 +654,17 @@ char ** ADRGDataset::GetFileList()
 {
     char** papszFileList = GDALPamDataset::GetFileList();
 
-    if (osGENFileName.size() > 0 && osIMGFileName.size() > 0)
+    if( !osGENFileName.empty() && !osIMGFileName.empty() )
     {
         CPLString osMainFilename = GetDescription();
-        VSIStatBufL  sStat;
+        VSIStatBufL sStat;
 
         const bool bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
-        if (bMainFileReal)
+        if( bMainFileReal )
         {
             CPLString osShortMainFilename = CPLGetFilename(osMainFilename);
             CPLString osShortGENFileName = CPLGetFilename(osGENFileName);
-            if ( !EQUAL(osShortMainFilename.c_str(), osShortGENFileName.c_str()) )
+            if( !EQUAL(osShortMainFilename.c_str(), osShortGENFileName.c_str()) )
                 papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
         }
         else
@@ -727,7 +739,7 @@ const char* ADRGDataset::GetProjectionRef()
 
 CPLErr ADRGDataset::GetGeoTransform( double * padfGeoTransform)
 {
-    if (papszSubDatasets != NULL)
+    if( papszSubDatasets != NULL )
         return CE_Failure;
 
     memcpy( padfGeoTransform, adfGeoTransform, sizeof(double)*6 );
@@ -794,7 +806,7 @@ DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
                                               const char* pszIMGFileName)
 {
     /* Finds the GEN file corresponding to the IMG file */
-    if (!module.Open(pszGENFileName, TRUE))
+    if( !module.Open(pszGENFileName, TRUE) )
         return NULL;
 
     CPLString osShortIMGFilename = CPLGetFilename(pszIMGFileName);
@@ -806,15 +818,15 @@ DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
         DDFRecord* record = module.ReadRecord();
         CPLPopErrorHandler();
         CPLErrorReset();
-        if (record == NULL)
+        if( record == NULL )
           return NULL;
 
-        if (record->GetFieldCount() >= 5)
+        if( record->GetFieldCount() >= 5 )
         {
             DDFField *field = record->GetField(0);
             DDFFieldDefn *fieldDefn = field->GetFieldDefn();
-            if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
-                fieldDefn->GetSubfieldCount() == 2))
+            if( !(strcmp(fieldDefn->GetName(), "001") == 0 &&
+                fieldDefn->GetSubfieldCount() == 2) )
             {
                 continue;
             }
@@ -823,17 +835,17 @@ DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
             if( RTY == NULL )
                 continue;
             /* Ignore overviews */
-            if ( strcmp(RTY, "OVV") == 0 )
+            if( strcmp(RTY, "OVV") == 0 )
                 continue;
 
-            if ( strcmp(RTY, "GIN") != 0 )
+            if( strcmp(RTY, "GIN") != 0 )
                 continue;
 
             field = record->GetField(3);
             fieldDefn = field->GetFieldDefn();
 
-            if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
-                    fieldDefn->GetSubfieldCount() == 15))
+            if( !(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
+                  fieldDefn->GetSubfieldCount() == 15) )
             {
                 continue;
             }
@@ -844,11 +856,11 @@ DDFRecord* ADRGDataset::FindRecordInGENForIMG(DDFModule& module,
             CPLString osBAD = pszBAD;
             {
                 char* c = (char*) strchr(osBAD.c_str(), ' ');
-                if (c)
+                if( c )
                     *c = 0;
             }
 
-            if (EQUAL(osShortIMGFilename.c_str(), osBAD.c_str()))
+            if( EQUAL(osShortIMGFilename.c_str(), osBAD.c_str()) )
             {
                 return record;
             }
@@ -878,24 +890,20 @@ ADRGDataset* ADRGDataset::OpenDataset(
     int TIF;
     int* TILEINDEX = NULL;
 
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
-    DDFSubfieldDefn* subfieldDefn;
-
-    if (record == NULL)
+    if( record == NULL )
     {
         record = FindRecordInGENForIMG(module, pszGENFileName, pszIMGFileName);
-        if (record == NULL)
+        if( record == NULL )
             return NULL;
     }
 
-    field = record->GetField(1);
+    DDFField* field = record->GetField(1);
     if( field == NULL )
         return NULL;
-    fieldDefn = field->GetFieldDefn();
+    DDFFieldDefn *fieldDefn = field->GetFieldDefn();
 
-    if (!(strcmp(fieldDefn->GetName(), "DSI") == 0 &&
-          fieldDefn->GetSubfieldCount() == 2))
+    if( !(strcmp(fieldDefn->GetName(), "DSI") == 0 &&
+          fieldDefn->GetSubfieldCount() == 2) )
     {
         return NULL;
     }
@@ -916,10 +924,10 @@ ADRGDataset* ADRGDataset::OpenDataset(
 
     // TODO: Support on GIN things.  And what is GIN?
     // GIN might mean general information and might be a typo of GEN.
-    // if (isGIN)
+    // if( isGIN )
     {
-        if (!(strcmp(fieldDefn->GetName(), "GEN") == 0 &&
-                fieldDefn->GetSubfieldCount() == 21))
+        if( !(strcmp(fieldDefn->GetName(), "GEN") == 0 &&
+              fieldDefn->GetSubfieldCount() == 21) )
         {
             return NULL;
         }
@@ -957,8 +965,8 @@ ADRGDataset* ADRGDataset::OpenDataset(
 #if 0
     else
     {
-        if (!(strcmp(fieldDefn->GetName(), "OVI") == 0 &&
-                fieldDefn->GetSubfieldCount() == 5))
+        if( !(strcmp(fieldDefn->GetName(), "OVI") == 0 &&
+                fieldDefn->GetSubfieldCount() == 5) )
         {
             return NULL;
         }
@@ -991,8 +999,8 @@ ADRGDataset* ADRGDataset::OpenDataset(
         return NULL;
     fieldDefn = field->GetFieldDefn();
 
-    if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
-            fieldDefn->GetSubfieldCount() == 15))
+    if( !(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
+          fieldDefn->GetSubfieldCount() == 15))
     {
         return NULL;
     }
@@ -1014,14 +1022,14 @@ ADRGDataset* ADRGDataset::OpenDataset(
 
     int PNC = record->GetIntSubfield("SPR", 0, "PNC", 0);
     CPLDebug("ADRG", "PNC=%d", PNC);
-    if (PNC != 128)
+    if( PNC != 128 )
     {
         return NULL;
     }
 
     int PNL = record->GetIntSubfield("SPR", 0, "PNL", 0);
     CPLDebug("ADRG", "PNL=%d", PNL);
-    if (PNL != 128)
+    if( PNL != 128 )
     {
         return NULL;
     }
@@ -1032,14 +1040,14 @@ ADRGDataset* ADRGDataset::OpenDataset(
     osBAD = pszBAD;
     {
         char* c = (char*) strchr(osBAD.c_str(), ' ');
-        if (c)
+        if( c )
             *c = 0;
     }
     CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
 
-    subfieldDefn = fieldDefn->GetSubfield(14);
-    if (!(strcmp(subfieldDefn->GetName(), "TIF") == 0 &&
-            (subfieldDefn->GetFormat())[0] == 'A'))
+    DDFSubfieldDefn* subfieldDefn = fieldDefn->GetSubfield(14);
+    if( !(strcmp(subfieldDefn->GetName(), "TIF") == 0 &&
+          (subfieldDefn->GetFormat())[0] == 'A') )
     {
         return NULL;
     }
@@ -1050,9 +1058,9 @@ ADRGDataset* ADRGDataset::OpenDataset(
     TIF = pszTIF[0] == 'Y';
     CPLDebug("ADRG", "TIF=%d", TIF);
 
-    if (TIF)
+    if( TIF )
     {
-        if (record->GetFieldCount() != 6)
+        if( record->GetFieldCount() != 6 )
         {
             return NULL;
         }
@@ -1062,12 +1070,12 @@ ADRGDataset* ADRGDataset::OpenDataset(
             return NULL;
         fieldDefn = field->GetFieldDefn();
 
-        if (!(strcmp(fieldDefn->GetName(), "TIM") == 0))
+        if( !(strcmp(fieldDefn->GetName(), "TIM") == 0) )
         {
             return NULL;
         }
 
-        if (field->GetDataSize() != 5 * NFL * NFC + 1)
+        if( field->GetDataSize() != 5 * NFL * NFC + 1 )
         {
             return NULL;
         }
@@ -1092,7 +1100,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
     }
 
     VSILFILE* fdIMG = VSIFOpenL(pszIMGFileName, "rb");
-    if (fdIMG == NULL)
+    if( fdIMG == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s\n", pszIMGFileName);
         delete[] TILEINDEX;
@@ -1103,7 +1111,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
     int offsetInIMG = 0;
     char c;
     char recordName[3];
-    if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
+    if( VSIFReadL(&c, 1, 1, fdIMG) != 1 )
     {
         VSIFCloseL(fdIMG);
         delete[] TILEINDEX;
@@ -1111,20 +1119,20 @@ ADRGDataset* ADRGDataset::OpenDataset(
     }
     while (!VSIFEofL(fdIMG))
     {
-        if (c == 30)
+        if( c == 30 )
         {
-            if (VSIFReadL(recordName, 1, 3, fdIMG) != 3)
+            if( VSIFReadL(recordName, 1, 3, fdIMG) != 3 )
             {
                 VSIFCloseL(fdIMG);
                 delete[] TILEINDEX;
                 return NULL;
             }
             offsetInIMG += 3;
-            if (STARTS_WITH(recordName, "IMG"))
+            if( STARTS_WITH(recordName, "IMG") )
             {
                 offsetInIMG += 4;
-                if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0 ||
-                    VSIFReadL(&c, 1, 1, fdIMG) != 1)
+                if( VSIFSeekL(fdIMG,3,SEEK_CUR) != 0 ||
+                    VSIFReadL(&c, 1, 1, fdIMG) != 1 )
                 {
                     VSIFCloseL(fdIMG);
                     delete[] TILEINDEX;
@@ -1133,7 +1141,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
                 while(c ==' ')
                 {
                     offsetInIMG ++;
-                    if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
+                    if( VSIFReadL(&c, 1, 1, fdIMG) != 1 )
                     {
                         VSIFCloseL(fdIMG);
                         delete[] TILEINDEX;
@@ -1145,8 +1153,8 @@ ADRGDataset* ADRGDataset::OpenDataset(
             }
         }
 
-        offsetInIMG ++;
-        if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
+        offsetInIMG++;
+        if( VSIFReadL(&c, 1, 1, fdIMG) != 1 )
         {
             VSIFCloseL(fdIMG);
             delete[] TILEINDEX;
@@ -1154,7 +1162,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
         }
     }
 
-    if (VSIFEofL(fdIMG))
+    if( VSIFEofL(fdIMG) )
     {
         VSIFCloseL(fdIMG);
         delete[] TILEINDEX;
@@ -1228,7 +1236,7 @@ ADRGDataset* ADRGDataset::OpenDataset(
         poDS->osSRS = SRS_WKT_WGS84;
     }
 
-    // if (isGIN)
+    // if( isGIN )
     {
         char szValue[32];
         snprintf( szValue, sizeof(szValue), "%d", SCA);
@@ -1253,11 +1261,11 @@ ADRGDataset* ADRGDataset::OpenDataset(
 char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
 {
     DDFModule module;
-    DDFRecord * record;
+    DDFRecord *record = NULL;
     int nFilenames = 0;
     char** papszFileNames = NULL;
 
-    if (!module.Open(pszFileName, TRUE))
+    if( !module.Open(pszFileName, TRUE) )
         return papszFileNames;
 
     while (true)
@@ -1266,21 +1274,21 @@ char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
         record = module.ReadRecord();
         CPLPopErrorHandler();
         CPLErrorReset();
-        if (record == NULL)
+        if( record == NULL )
           break;
 
-        if (record->GetFieldCount() >= 2)
+        if( record->GetFieldCount() >= 2 )
         {
             DDFField *field = record->GetField(0);
             DDFFieldDefn *fieldDefn = field->GetFieldDefn();
-            if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
-                fieldDefn->GetSubfieldCount() == 2))
+            if( !(strcmp(fieldDefn->GetName(), "001") == 0 &&
+                fieldDefn->GetSubfieldCount() == 2) )
             {
                 continue;
             }
 
             const char* RTY = record->GetStringSubfield("001", 0, "RTY", 0);
-            if ( RTY == NULL || !( strcmp(RTY, "TFN") == 0 ))
+            if( RTY == NULL || !( strcmp(RTY, "TFN") == 0 ) )
             {
                 continue;
             }
@@ -1291,8 +1299,8 @@ char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
                 field = record->GetField(i);
                 fieldDefn = field->GetFieldDefn();
 
-                if (!(strcmp(fieldDefn->GetName(), "VFF") == 0 &&
-                      fieldDefn->GetSubfieldCount() == 1))
+                if( !(strcmp(fieldDefn->GetName(), "VFF") == 0 &&
+                      fieldDefn->GetSubfieldCount() == 1) )
                 {
                     continue;
                 }
@@ -1302,25 +1310,25 @@ char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
                     continue;
                 CPLString osSubFileName(pszVFF);
                 char* c = (char*) strchr(osSubFileName.c_str(), ' ');
-                if (c)
+                if( c )
                     *c = 0;
-                if (EQUAL(CPLGetExtension(osSubFileName.c_str()), "GEN"))
+                if( EQUAL(CPLGetExtension(osSubFileName.c_str()), "GEN") )
                 {
                     CPLDebug("ADRG", "Found GEN file in THF : %s", osSubFileName.c_str());
                     CPLString osGENFileName(CPLGetDirname(pszFileName));
                     char** tokens = CSLTokenizeString2( osSubFileName.c_str(), "/\"", 0);
                     char** ptr = tokens;
-                    if (ptr == NULL)
+                    if( ptr == NULL )
                         continue;
                     while(*ptr)
                     {
                         char** papszDirContent = VSIReadDir(osGENFileName.c_str());
                         char** ptrDir = papszDirContent;
-                        if (ptrDir)
+                        if( ptrDir )
                         {
-                            while(*ptrDir)
+                            while( *ptrDir )
                             {
-                                if (EQUAL(*ptrDir, *ptr))
+                                if( EQUAL(*ptrDir, *ptr) )
                                 {
                                     osGENFileName = CPLFormFilename(osGENFileName.c_str(), *ptrDir, NULL);
                                     CPLDebug("ADRG", "Building GEN full file name : %s", osGENFileName.c_str());
@@ -1329,14 +1337,14 @@ char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
                                 ptrDir ++;
                             }
                         }
-                        if (ptrDir == NULL)
+                        if( ptrDir == NULL )
                             break;
                         CSLDestroy(papszDirContent);
                         ptr++;
                     }
                     int isNameValid = *ptr == NULL;
                     CSLDestroy(tokens);
-                    if (isNameValid)
+                    if( isNameValid )
                     {
                         papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
                         papszFileNames[nFilenames] = CPLStrdup(osGENFileName.c_str());
@@ -1357,16 +1365,16 @@ char** ADRGDataset::GetGENListFromTHF(const char* pszFileName)
 char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
                                       int *pnRecordIndex)
 {
-    DDFRecord * record;
+    DDFRecord *record = NULL;
     int nFilenames = 0;
     char** papszFileNames = NULL;
     int nRecordIndex = -1;
 
-    if (pnRecordIndex)
+    if( pnRecordIndex )
         *pnRecordIndex = -1;
 
     DDFModule module;
-    if (!module.Open(pszFileName, TRUE))
+    if( !module.Open(pszFileName, TRUE) )
         return NULL;
 
     while (true)
@@ -1377,15 +1385,15 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
         record = module.ReadRecord();
         CPLPopErrorHandler();
         CPLErrorReset();
-        if (record == NULL)
+        if( record == NULL )
           break;
 
-        if (record->GetFieldCount() >= 5)
+        if( record->GetFieldCount() >= 5 )
         {
             DDFField *field = record->GetField(0);
             DDFFieldDefn *fieldDefn = field->GetFieldDefn();
-            if (!(strcmp(fieldDefn->GetName(), "001") == 0 &&
-                fieldDefn->GetSubfieldCount() == 2))
+            if( !(strcmp(fieldDefn->GetName(), "001") == 0 &&
+                  fieldDefn->GetSubfieldCount() == 2) )
             {
                 continue;
             }
@@ -1394,11 +1402,11 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
             if( RTY == NULL )
                 continue;
             /* Ignore overviews */
-            if ( strcmp(RTY, "OVV") == 0 )
+            if( strcmp(RTY, "OVV") == 0 )
                 continue;
 
             // TODO: Fix the non-GIN section or remove it.
-            if ( strcmp(RTY, "GIN") != 0 )
+            if( strcmp(RTY, "GIN") != 0 )
                 continue;
 
             field = record->GetField(3);
@@ -1406,8 +1414,8 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
                 continue;
             fieldDefn = field->GetFieldDefn();
 
-            if (!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
-                    fieldDefn->GetSubfieldCount() == 15))
+            if(!(strcmp(fieldDefn->GetName(), "SPR") == 0 &&
+                 fieldDefn->GetSubfieldCount() == 15) )
             {
                 continue;
             }
@@ -1418,7 +1426,7 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
             CPLString osBAD = pszBAD;
             {
                 char* c = (char*) strchr(osBAD.c_str(), ' ');
-                if (c)
+                if( c )
                     *c = 0;
             }
             CPLDebug("ADRG", "BAD=%s", osBAD.c_str());
@@ -1435,8 +1443,8 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
             }
             else
             {
-                char** papszDirContent;
-                if (strcmp(osGENDir.c_str(), "/vsimem") == 0)
+                char** papszDirContent = NULL;
+                if( strcmp(osGENDir.c_str(), "/vsimem") == 0 )
                 {
                     CPLString osTmp = osGENDir + "/";
                     papszDirContent = VSIReadDir(osTmp);
@@ -1446,7 +1454,7 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
                 char** ptrDir = papszDirContent;
                 while(ptrDir && *ptrDir)
                 {
-                    if (EQUAL(*ptrDir, osBAD.c_str()))
+                    if( EQUAL(*ptrDir, osBAD.c_str()) )
                     {
                         osBAD = CPLFormFilename(osGENDir.c_str(), *ptrDir, NULL);
                         CPLDebug("ADRG", "Building IMG full file name : %s", osBAD.c_str());
@@ -1457,7 +1465,7 @@ char** ADRGDataset::GetIMGListFromGEN(const char* pszFileName,
                 CSLDestroy(papszDirContent);
             }
 
-            if (nFilenames == 0 && pnRecordIndex)
+            if( nFilenames == 0 && pnRecordIndex )
                 *pnRecordIndex = nRecordIndex;
 
             papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
@@ -1484,7 +1492,7 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( STARTS_WITH_CI(poOpenInfo->pszFilename, "ADRG:") )
     {
         char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename + 5, ",", 0);
-        if (CSLCount(papszTokens) == 2)
+        if( CSLCount(papszTokens) == 2 )
         {
             osGENFileName = papszTokens[0];
             osIMGFileName = papszTokens[1];
@@ -1498,12 +1506,12 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
 
         CPLString osFileName(poOpenInfo->pszFilename);
-        if (EQUAL(CPLGetExtension(osFileName.c_str()), "THF"))
+        if( EQUAL(CPLGetExtension(osFileName.c_str()), "THF") )
         {
             char** papszFileNames = GetGENListFromTHF(osFileName.c_str());
-            if (papszFileNames == NULL)
+            if( papszFileNames == NULL )
                 return NULL;
-            if (papszFileNames[1] == NULL)
+            if( papszFileNames[1] == NULL )
             {
                 osFileName = papszFileNames[0];
                 CSLDestroy(papszFileNames);
@@ -1530,14 +1538,15 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
             }
         }
 
-        if (EQUAL(CPLGetExtension(osFileName.c_str()), "GEN"))
+        if( EQUAL(CPLGetExtension(osFileName.c_str()), "GEN") )
         {
             osGENFileName = osFileName;
 
-            char** papszFileNames = GetIMGListFromGEN(osFileName.c_str(), &nRecordIndex);
-            if (papszFileNames == NULL)
+            char** papszFileNames =
+                GetIMGListFromGEN(osFileName.c_str(), &nRecordIndex);
+            if( papszFileNames == NULL )
                 return NULL;
-            if (papszFileNames[1] == NULL)
+            if( papszFileNames[1] == NULL )
             {
                 osIMGFileName = papszFileNames[0];
                 CSLDestroy(papszFileNames);
@@ -1546,7 +1555,7 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
             {
                 char** ptr = papszFileNames;
                 ADRGDataset* poDS = new ADRGDataset();
-                while(*ptr)
+                while( *ptr )
                 {
                     poDS->AddSubDataset(osFileName.c_str(), *ptr);
                     ptr ++;
@@ -1557,46 +1566,47 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-    if (osGENFileName.size() > 0 &&
-        osIMGFileName.size() > 0)
+    if( !osGENFileName.empty() &&
+        !osIMGFileName.empty() )
     {
         if( poOpenInfo->eAccess == GA_Update )
         {
             CPLError( CE_Failure, CPLE_NotSupported,
-                      "The ADRG driver does not support update access to existing"
-                      " datasets.\n" );
+                      "The ADRG driver does not support update access to "
+                      "existing datasets." );
             return NULL;
         }
 
         DDFModule module;
         DDFRecord* record = NULL;
-        if (nRecordIndex >= 0 &&
-            module.Open(osGENFileName.c_str(), TRUE))
+        if( nRecordIndex >= 0 &&
+            module.Open(osGENFileName.c_str(), TRUE) )
         {
-            for(int i=0;i<=nRecordIndex;i++)
+            for( int i = 0; i <= nRecordIndex; i++ )
             {
                 CPLPushErrorHandler( CPLQuietErrorHandler );
                 record = module.ReadRecord();
                 CPLPopErrorHandler();
                 CPLErrorReset();
-                if (record == NULL)
+                if( record == NULL )
                   break;
             }
         }
 
-        ADRGDataset* poDS = OpenDataset(osGENFileName.c_str(), osIMGFileName.c_str(), record);
+        ADRGDataset* poDS =
+            OpenDataset(osGENFileName.c_str(), osIMGFileName.c_str(), record);
 
-        if (poDS)
+        if( poDS )
         {
-            /* -------------------------------------------------------------------- */
-            /*      Initialize any PAM information.                                 */
-            /* -------------------------------------------------------------------- */
+            /* -------------------------------------------------------------- */
+            /*      Initialize any PAM information.                           */
+            /* -------------------------------------------------------------- */
             poDS->SetDescription( poOpenInfo->pszFilename );
             poDS->TryLoadXML();
 
-            /* -------------------------------------------------------------------- */
-            /*      Check for external overviews.                                   */
-            /* -------------------------------------------------------------------- */
+            /* -------------------------------------------------------------- */
+            /*      Check for external overviews.                             */
+            /* -------------------------------------------------------------- */
             if( bFromSubdataset )
                 poDS->oOvManager.Initialize( poDS, osIMGFileName.c_str() );
             else
@@ -1613,18 +1623,18 @@ GDALDataset *ADRGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                               Create()                               */
 /************************************************************************/
 
-GDALDataset *ADRGDataset::Create(const char* pszFilename,
-                                 int nXSize,
-                                 int nYSize,
-                                 int nBands,
-                                 GDALDataType eType,
-                                 CPL_UNUSED char **papszOptions)
+GDALDataset *ADRGDataset::Create( const char* pszFilename,
+                                  int nXSize,
+                                  int nYSize,
+                                  int nBands,
+                                  GDALDataType eType,
+                                  CPL_UNUSED char **papszOptions )
 {
     if( eType != GDT_Byte)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create ADRG dataset with an illegal\n"
-              "data type (%s), only Byte supported by the format.\n",
+              "Attempt to create ADRG dataset with an illegal "
+              "data type (%s), only Byte supported by the format.",
               GDALGetDataTypeName(eType) );
 
         return NULL;
@@ -1633,7 +1643,8 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
     if( nBands != 3 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "ADRG driver doesn't support %d bands. Must be 3 (rgb) bands.\n",
+                  "ADRG driver doesn't support %d bands. "
+                  "Must be 3 (rgb) bands.",
                   nBands );
         return NULL;
     }
@@ -1641,37 +1652,41 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
     if(nXSize < 1 || nYSize < 1)
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                "Specified pixel dimensions (% d x %d) are bad.\n",
+                "Specified pixel dimensions (% d x %d) are bad.",
                 nXSize, nYSize );
     }
 
-    if (!EQUAL(CPLGetExtension(pszFilename), "gen"))
+    if( !EQUAL(CPLGetExtension(pszFilename), "gen") )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                "Invalid filename. Must be ABCDEF01.GEN\n");
+                  "Invalid filename. Must be ABCDEF01.GEN");
         return NULL;
     }
 
     CPLString osBaseFileName(CPLGetBasename(pszFilename));
-    if (strlen(osBaseFileName) != 8 || osBaseFileName[6] != '0' || osBaseFileName[7] != '1')
+    if( osBaseFileName.size() != 8 ||
+        osBaseFileName[6] != '0' ||
+        osBaseFileName[7] != '1' )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                "Invalid filename. Must be xxxxxx01.GEN where x is between A and Z\n");
+                  "Invalid filename. "
+                  "Must be xxxxxx01.GEN where x is between A and Z" );
         return NULL;
     }
 
     for(int i=0;i<6;i++)
     {
-        if (!(osBaseFileName[i] >= 'A' && osBaseFileName[i] <= 'Z'))
+        if( !(osBaseFileName[i] >= 'A' && osBaseFileName[i] <= 'Z') )
         {
             CPLError( CE_Failure, CPLE_NotSupported,
-                "Invalid filename. Must be xxxxxx01.GEN where x is between A and Z\n");
+                      "Invalid filename. "
+                      "Must be xxxxxx01.GEN where x is between A and Z" );
             return NULL;
         }
     }
 
     VSILFILE* fdGEN = VSIFOpenL(pszFilename, "wb");
-    if (fdGEN == NULL)
+    if( fdGEN == NULL )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                 "Cannot create GEN file : %s.\n", pszFilename);
@@ -1679,9 +1694,10 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
     }
 
     CPLString osDirname(CPLGetDirname(pszFilename));
-    CPLString osTransh01THF(CPLFormFilename(osDirname.c_str(), "TRANSH01.THF", NULL));
+    CPLString osTransh01THF(
+        CPLFormFilename(osDirname.c_str(), "TRANSH01.THF", NULL));
     VSILFILE* fdTHF = VSIFOpenL(osTransh01THF.c_str(), "wb");
-    if (fdTHF == NULL)
+    if( fdTHF == NULL )
     {
         VSIFCloseL(fdGEN);
         CPLError( CE_Failure, CPLE_FileIO,
@@ -1691,7 +1707,7 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
 
     CPLString osImgFilename = CPLResetExtension(pszFilename, "IMG");
     VSILFILE* fdIMG = VSIFOpenL(osImgFilename.c_str(), "w+b");
-    if (fdIMG == NULL)
+    if( fdIMG == NULL )
     {
         VSIFCloseL(fdGEN);
         VSIFCloseL(fdTHF);
@@ -1732,12 +1748,12 @@ GDALDataset *ADRGDataset::Create(const char* pszFilename,
 /*                  WriteGENFile_Header()                               */
 /************************************************************************/
 
-static void WriteGENFile_Header(VSILFILE* fd)
+static void WriteGENFile_Header( VSILFILE* fd )
 {
     int nFields = 0;
     int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, };
     const char* nameOfFields[] = { "000", "001", "DRF", "DSI", "OVI", "GEN", "SPR", "BDF", "TIM" };
-    int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
+    const int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
 
     sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "GENERAL_INFORMATION_FILE", "", ""); /* 000 */
     sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
@@ -1765,7 +1781,8 @@ static void WriteGENFile_Header(VSILFILE* fd)
                                                 "*TSI",
                                                 "(I(5))");
 
-    FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
+    FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields),
+                      sizeOfFields, nameOfFields);
 }
 
 /************************************************************************/
@@ -1778,7 +1795,7 @@ static void WriteGENFile_DataSetDescriptionRecord(VSILFILE* fd)
     int nFields = 0;
     int sizeOfFields[] = {0, 0};
     const char* nameOfFields[] = { "001", "DRF" };
-    int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
+    const int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
 
     /* Field 001 */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "DSS", 3); /* RTY */
@@ -1792,9 +1809,10 @@ static void WriteGENFile_DataSetDescriptionRecord(VSILFILE* fd)
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOZ */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* NOS */
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
-    nFields++;
+    /* nFields++; */
 
-    FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
+    FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields),
+                      sizeOfFields, nameOfFields);
 }
 
 /************************************************************************/
@@ -1802,13 +1820,15 @@ static void WriteGENFile_DataSetDescriptionRecord(VSILFILE* fd)
 /************************************************************************/
 
 /* Write OVERVIEW_RECORD */
-static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName, int ARV, int BRV, double LSO, double PSO,
-                                        int nOvSizeX, int nOvSizeY, int NFL, int NFC, int* TILEINDEX)
+static void WriteGENFile_OverviewRecord(
+    VSILFILE* fd, CPLString& osBaseFileName,
+    int ARV, int BRV, double LSO, double PSO,
+    int nOvSizeX, int nOvSizeY, int NFL, int NFC, int* TILEINDEX )
 {
     int nFields = 0;
     int sizeOfFields[] = {0, 0, 0, 0, 0, 0};
     const char* nameOfFields[] = { "001", "DSI", "OVI", "SPR", "BDF", "TIM" };
-    int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
+    const int pos = BeginLeader(fd, 9, 9, 3, N_ELEMENTS(sizeOfFields));
 
     /* Field 001 */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "OVV", 3); /* RTY */
@@ -1824,8 +1844,8 @@ static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName,
 
     /* Field OVI */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
-    sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8); /* ARV */   /* FIXME */
-    sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8); /* BRV */   /* FIXME */
+    sizeOfFields[nFields] += WriteSubFieldInt(fd, ARV, 8);  // ARV - FIXME
+    sizeOfFields[nFields] += WriteSubFieldInt(fd, BRV, 8);  // BRV - FIXME
     sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* LSO */   /* FIXME */
     sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* PSO */    /* FIXME */
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
@@ -1836,8 +1856,10 @@ static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName,
     sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeX-1, 6); /* NUS */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, nOvSizeY-1, 6); /* NLL */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
-    sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeY + 127) / 128, 3); /* NFL */
-    sizeOfFields[nFields] += WriteSubFieldInt(fd, (nOvSizeX + 127) / 128, 3); /* NFC */
+    sizeOfFields[nFields] +=
+        WriteSubFieldInt(fd, (nOvSizeY + 127) / 128, 3); /* NFL */
+    sizeOfFields[nFields] +=
+        WriteSubFieldInt(fd, (nOvSizeX + 127) / 128, 3); /* NFC */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
@@ -1866,14 +1888,15 @@ static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName,
     nFields++;
 
     /* Field TIM */
-    for(int i=0;i<NFL*NFC;i++)
+    for( int i = 0; i < NFL * NFC; i++ )
     {
-        sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
+        sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5);  // TSI
     }
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
-    nFields++;
+    /* nFields++; */
 
-    FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
+    FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields),
+                      sizeOfFields, nameOfFields);
 }
 
 /************************************************************************/
@@ -1881,11 +1904,12 @@ static void WriteGENFile_OverviewRecord(VSILFILE* fd, CPLString& osBaseFileName,
 /************************************************************************/
 
 /* Write GENERAL_INFORMATION_RECORD */
-static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM, CPLString& osBAD,
-                                                  int ARV, int BRV, double LSO, double PSO,
-                                                  double* adfGeoTransform, int SCA,
-                                                  int nRasterXSize, int nRasterYSize,
-                                                  int NFL, int NFC, int* TILEINDEX)
+static void WriteGENFile_GeneralInformationRecord(
+    VSILFILE* fd, CPLString& osNAM, CPLString& osBAD,
+    int ARV, int BRV, double LSO, double PSO,
+    double* adfGeoTransform, int SCA,
+    int nRasterXSize, int nRasterYSize,
+    int NFL, int NFC, int* TILEINDEX )
 
 {
     int nFields = 0;
@@ -1907,17 +1931,21 @@ static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM
 
     /* Field `GEN */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
-    sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LOD */   /* FIXME */
-    sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6); /* LAD */   /* FIXME */
-    sizeOfFields[nFields] += WriteSubFieldInt(fd, 16, 3); /* UNIloa */   /* FIXME */
+    sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6);  // LOD - FIXME
+    sizeOfFields[nFields] += WriteSubFieldStr(fd, "0099.9", 6);  // LAD - FIXME
+    sizeOfFields[nFields] += WriteSubFieldInt(fd, 16, 3);  // UNIloa - FIXME
     sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
-    sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
+    sizeOfFields[nFields] +=
+        WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
     sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* NWO */
     sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NWA */
-    sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
+    sizeOfFields[nFields] +=
+        WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
     sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
-    sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* SEO */
-    sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SEA */
+    sizeOfFields[nFields] +=
+        WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* SEO */
+    sizeOfFields[nFields] +=
+        WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SEA */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, SCA, 9); /* SCA */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 2); /* ZNA */  /* FIXME */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, "100.0", 5); /* PSP */
@@ -1935,8 +1963,10 @@ static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM
     sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterXSize-1, 6); /* NUS */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, nRasterYSize-1, 6); /* NLL */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
-    sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterYSize + 127) / 128, 3); /* NFL */
-    sizeOfFields[nFields] += WriteSubFieldInt(fd, (nRasterXSize + 127) / 128, 3); /* NFC */
+    sizeOfFields[nFields] +=
+        WriteSubFieldInt(fd, (nRasterYSize + 127) / 128, 3); /* NFL */
+    sizeOfFields[nFields] +=
+        WriteSubFieldInt(fd, (nRasterXSize + 127) / 128, 3); /* NFC */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
     sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
@@ -1963,14 +1993,15 @@ static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM
     nFields++;
 
     /* Field TIM */
-    for(int i=0;i<NFL*NFC;i++)
+    for( int i = 0; i < NFL*NFC; i++ )
     {
-        sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5); /* TSI */
+        sizeOfFields[nFields] += WriteSubFieldInt(fd, TILEINDEX[i], 5);  // TSI
     }
     sizeOfFields[nFields] += WriteFieldTerminator(fd);
-    nFields++;
+    /* nFields++; */
 
-    FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
+    FinishWriteLeader(fd, pos, 9, 9, 3, N_ELEMENTS(sizeOfFields),
+                      sizeOfFields, nameOfFields);
 }
 
 /************************************************************************/
@@ -1979,7 +2010,7 @@ static void WriteGENFile_GeneralInformationRecord(VSILFILE* fd, CPLString& osNAM
 
 void ADRGDataset::WriteGENFile()
 {
-    if (!bGeoTransformValid)
+    if( !bGeoTransformValid )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "No geo transform available !");
         adfGeoTransform[0] = 0;
@@ -1996,10 +2027,10 @@ void ADRGDataset::WriteGENFile()
     /*ARV = ((ARV + 255) / 512) * 512;
     BRV = ((BRV + 255) / 512) * 512;*/
 
-    int SCA = (int)floor(1000000. * 400384 / BRV + 0.5);
+    const int SCA = (int)floor(1000000. * 400384 / BRV + 0.5);
 
-    int nOvSizeX = nRasterXSize; // FIXME
-    int nOvSizeY = nRasterYSize; // FIXME
+    const int nOvSizeX = nRasterXSize; // FIXME
+    const int nOvSizeY = nRasterYSize; // FIXME
 
     /* Write header */
     WriteGENFile_Header(fdGEN);
@@ -2013,13 +2044,14 @@ void ADRGDataset::WriteGENFile()
 
     /* Write GENERAL_INFORMATION_RECORD */
     CPLString osNAM = osBaseFileName;
-    char tmp[12+1];
+    char tmp[12+1] = {};
     snprintf(tmp, sizeof(tmp), "%s.IMG", osNAM.c_str());
     CPLString osBAD = tmp;
-    WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
-                                          adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
+    WriteGENFile_GeneralInformationRecord(
+        fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
+        adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
 
-    if (CPLTestBool(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF")))
+    if( CPLTestBool(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF")) )
     {
         strncpy(tmp, osBaseFileName.c_str(), 6);
         tmp[6] = '\0';
@@ -2027,8 +2059,10 @@ void ADRGDataset::WriteGENFile()
         osNAM = tmp;
         snprintf(tmp, sizeof(tmp), "%s.IMG", osNAM.c_str());
         osBAD = tmp;
-        WriteGENFile_GeneralInformationRecord(fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
-                                              adfGeoTransform, SCA, nRasterXSize, nRasterYSize, NFL, NFC, TILEINDEX);
+        WriteGENFile_GeneralInformationRecord(
+            fdGEN, osNAM, osBAD, ARV, BRV, LSO, PSO,
+            adfGeoTransform, SCA, nRasterXSize, nRasterYSize,
+            NFL, NFC, TILEINDEX);
     }
 }
 
@@ -2045,7 +2079,7 @@ void ADRGDataset::WriteTHFFile()
         int nFields = 0;
         int sizeOfFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
         const char* nameOfFields[] = { "000", "001", "VDR", "FDR", "QSR", "QUV", "CPS", "CPT", "SPR", "BDF", "VFF"};
-        int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
+        const int pos = BeginHeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
 
         sizeOfFields[nFields++] += WriteFieldDecl(fd, ' ', ' ', "TRANSMITTAL_HEADER_FILE", "", ""); /* 000 */
         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "RECORD_ID_FIELD", /* 001 */
@@ -2069,17 +2103,22 @@ void ADRGDataset::WriteTHFFile()
         sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "TEST_PATCH_INFORMATION_FIELD", /* CPT */
                                                   "STR!SCR",
                                                   "(I(1),A(100))");
-        sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */
-                                                  "NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF",
-                                                  "(I(6),I(6),I(6),I(6),I(3),I(3),I(6),I(6),I(1),I(1),I(1),I(1),I(1),A(12),A(1))");
-        sizeOfFields[nFields++] += WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */
-                                                  "*BID!WS1!WS2",
-                                                  "(A(5),I(5),I(5))");
-        sizeOfFields[nFields++] += WriteFieldDecl(fd, '1', '0', "TRANSMITTAL_FILENAMES_FIELD", /* VFF */
-                                                  "VFF",
-                                                  "(A(51))");
-
-        FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
+        sizeOfFields[nFields++] +=
+            WriteFieldDecl(
+                fd, '1', '6', "DATA_SET_PARAMETERS_FIELD", /* SPR */
+                "NUL!NUS!NLL!NLS!NFL!NFC!PNC!PNL!COD!ROD!POR!PCB!PVB!BAD!TIF",
+                "(I(6),I(6),I(6),I(6),I(3),I(3),I(6),I(6),I(1),I(1),I(1),I(1),"
+                "I(1),A(12),A(1))");
+        sizeOfFields[nFields++] +=
+            WriteFieldDecl(fd, '2', '6', "BAND_ID_FIELD", /* BDF */
+                           "*BID!WS1!WS2",
+                           "(A(5),I(5),I(5))");
+        sizeOfFields[nFields++] +=
+            WriteFieldDecl(fd, '1', '0', "TRANSMITTAL_FILENAMES_FIELD",
+                           "VFF", "(A(51))");
+
+        FinishWriteHeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields),
+                          sizeOfFields, nameOfFields);
     }
 
     /* Write TRANSMITTAL_DESCRIPTION_RECORD */
@@ -2097,29 +2136,35 @@ void ADRGDataset::WriteTHFFile()
 
         /* Field VDR */
         sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* MSD */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200); /* VOO */ /* Title and address of originator */
+        // VOO - Title and address of originator
+        sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 200);
         sizeOfFields[nFields] += WriteSubFieldStr(fd, " ", 1); /* ADR */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* NOV */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 1); /* SQN */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* NOF */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 16); /* URF */ /* DMA stock number for this CDROM */
+        // URF - DMA stock number for this CDROM
+        sizeOfFields[nFields] += WriteSubFieldStr(fd, "", 16);
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 1, 3); /* EDN */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, "017,19940101", 12); /* DAT */  /* Publication date */
+        sizeOfFields[nFields] +=
+            WriteSubFieldStr(fd, "017,19940101", 12); // DAT - Publication date
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
         nFields++;
 
         /* Field FDR */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
+        sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); // NAM
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 3, 1); /* STR */
         sizeOfFields[nFields] += WriteSubFieldStr(fd, "ADRG", 4); /* PRT */
         sizeOfFields[nFields] += WriteLongitude(fd, LSO); /* SWO */
-        sizeOfFields[nFields] += WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]); /* SWA */
-        sizeOfFields[nFields] += WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]); /* NEO */
+        sizeOfFields[nFields] +=
+            WriteLatitude(fd, PSO + nRasterYSize * adfGeoTransform[5]);  // SWA
+        sizeOfFields[nFields] +=
+            WriteLongitude(fd, LSO + nRasterXSize * adfGeoTransform[1]);  // NEO
         sizeOfFields[nFields] += WriteLatitude(fd, PSO); /* NEA */
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
-        nFields++;
+        /* nFields++; */
 
-        FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
+        FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields),
+                          sizeOfFields, nameOfFields);
     }
 
     /* Write SECURITY_AND_UPDATE_RECORD */
@@ -2144,13 +2189,20 @@ void ADRGDataset::WriteTHFFile()
         nFields++;
 
         /* Field FDR */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, "MILITARY SPECIFICATION ARC DIGITIZED RASTER GRAPHICS (ADRG)", 100); /* SRC */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, "022,19900222", 12); /* DAT */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, "MIL-A-89007", 20); /* SPA */
+        sizeOfFields[nFields] +=
+            WriteSubFieldStr(
+                fd,
+                "MILITARY SPECIFICATION ARC DIGITIZED RASTER GRAPHICS (ADRG)",
+                100); /* SRC */
+        sizeOfFields[nFields] +=
+            WriteSubFieldStr(fd, "022,19900222", 12); /* DAT */
+        sizeOfFields[nFields] +=
+            WriteSubFieldStr(fd, "MIL-A-89007", 20); /* SPA */
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
-        nFields++;
+        /* nFields++; */
 
-        FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
+        FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields),
+                          sizeOfFields, nameOfFields);
     }
 
     /* Write TEST_PATCH_DATA_RECORD */
@@ -2158,7 +2210,7 @@ void ADRGDataset::WriteTHFFile()
         int nFields = 0;
         int sizeOfFields[] = {0, 0, 0, 0, 0};
         const char* nameOfFields[] = { "001", "CPS", "CPT", "SPR", "BDF" };
-        int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
+        const int pos = BeginLeader(fd, 3, 4, 3, N_ELEMENTS(sizeOfFields));
 
         /* Field 001 */
         sizeOfFields[nFields] += WriteSubFieldStr(fd, "TPA", 3); /* RTY */
@@ -2183,16 +2235,20 @@ void ADRGDataset::WriteTHFFile()
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
         nFields++;
 
-        int nPatchXSize = 512;
-        int nPatchYSize = 512;
+        const int nPatchXSize = 512;
+        const int nPatchYSize = 512;
 
         /* Field SPR */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NUL */
-        sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchXSize-1, 6); /* NUS */
-        sizeOfFields[nFields] += WriteSubFieldInt(fd, nPatchYSize-1, 6); /* NLL */
+        sizeOfFields[nFields] +=
+            WriteSubFieldInt(fd, nPatchXSize-1, 6); /* NUS */
+        sizeOfFields[nFields] +=
+            WriteSubFieldInt(fd, nPatchYSize-1, 6); /* NLL */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 6); /* NLS */
-        sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchYSize + 127) / 128, 3); /* NFL */
-        sizeOfFields[nFields] += WriteSubFieldInt(fd, (nPatchXSize + 127) / 128, 3); /* NFC */
+        sizeOfFields[nFields] +=
+            WriteSubFieldInt(fd, (nPatchYSize + 127) / 128, 3); /* NFL */
+        sizeOfFields[nFields] +=
+            WriteSubFieldInt(fd, (nPatchXSize + 127) / 128, 3); /* NFC */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNC */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 128, 6); /* PNL */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* COD */
@@ -2200,7 +2256,8 @@ void ADRGDataset::WriteTHFFile()
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* POR */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 1); /* PCB */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 8, 1); /* PVB */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 12); /* BAD */
+        // BAD
+        sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 12);
         sizeOfFields[nFields] += WriteSubFieldStr(fd, "N", 1); /* TIF */
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
         nFields++;
@@ -2216,23 +2273,25 @@ void ADRGDataset::WriteTHFFile()
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS1 */
         sizeOfFields[nFields] += WriteSubFieldInt(fd, 0, 5); /* WS2 */
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
-        nFields++;
+        /* nFields++; */
 
-        FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields), sizeOfFields, nameOfFields);
+        FinishWriteLeader(fd, pos, 3, 4, 3, N_ELEMENTS(sizeOfFields),
+                          sizeOfFields, nameOfFields);
     }
 
     /* Write TRANSMITTAL_FILENAMES_RECORD */
     {
-        char tmp[12+1];
-
         int nFields = 0;
         int sizeOfFields[] = {0, 0, 0, 0, 0, 0, 0};
 
         /* Debug option to simulate ADRG datasets made of several images */
-        int nTotalFields = (CPLTestBool(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF"))) ? 6 : 5;
+        int nTotalFields =
+            CPLTestBool(CPLGetConfigOption("ADRG_SIMULATE_MULTI_IMG", "OFF"))
+            ? 6 : 5;
 
-        const char* nameOfFields[] = { "001", "VFF", "VFF", "VFF", "VFF", "VFF", "VFF" };
-        int pos = BeginLeader(fd, 9, 9, 3, nTotalFields);
+        const char* nameOfFields[] = {
+            "001", "VFF", "VFF", "VFF", "VFF", "VFF", "VFF" };
+        const int pos = BeginLeader(fd, 9, 9, 3, nTotalFields);
 
         /* Field 001 */
         sizeOfFields[nFields] += WriteSubFieldStr(fd, "TFN", 3); /* RTY */
@@ -2241,16 +2300,17 @@ void ADRGDataset::WriteTHFFile()
         nFields++;
 
         /* Field VFF */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, "TRANSH01.THF", 51); /* VFF */
+        sizeOfFields[nFields] += WriteSubFieldStr(fd, "TRANSH01.THF", 51);
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
         nFields++;
 
         /* Field VFF */
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 51); /* VFF */
+        sizeOfFields[nFields] += WriteSubFieldStr(fd, "TESTPA01.CPH", 51);
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
         nFields++;
 
         /* Field VFF */
+        char tmp[12+1] = {};
         snprintf(tmp, sizeof(tmp), "%s.GEN", osBaseFileName.c_str());
         sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
@@ -2262,7 +2322,7 @@ void ADRGDataset::WriteTHFFile()
         sizeOfFields[nFields] += WriteFieldTerminator(fd);
         nFields++;
 
-        if (nTotalFields == 6)
+        if( nTotalFields == 6 )
         {
             /* Field VFF */
             strncpy(tmp, osBaseFileName.c_str(), 6);
@@ -2270,10 +2330,11 @@ void ADRGDataset::WriteTHFFile()
             strcat(tmp, "02.IMG");
             sizeOfFields[nFields] += WriteSubFieldStr(fd, tmp, 51); /* VFF */
             sizeOfFields[nFields] += WriteFieldTerminator(fd);
-            nFields++;
+            /* nFields++; */
         }
 
-        FinishWriteLeader(fd, pos, 9, 9, 3, nTotalFields, sizeOfFields, nameOfFields);
+        FinishWriteLeader(fd, pos, 9, 9, 3, nTotalFields,
+                          sizeOfFields, nameOfFields);
     }
 }
 
diff --git a/frmts/adrg/srpdataset.cpp b/frmts/adrg/srpdataset.cpp
index 3803676..1fe0a7f 100644
--- a/frmts/adrg/srpdataset.cpp
+++ b/frmts/adrg/srpdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: srpdataset.cpp 34458 2016-06-28 08:37:28Z rouault $
  * Purpose:  ASRP/USRP Reader
  * Author:   Frank Warmerdam (warmerdam at pobox.com)
  *
@@ -33,12 +32,14 @@
 #include "gdal_frmts.h"
 #include "iso8211.h"
 #include "ogr_spatialref.h"
+
+#include <cstdlib>
 #include <algorithm>
 
 // Uncomment to recognize also .gen files in addition to .img files
 // #define OPEN_GEN
 
-CPL_CVSID("$Id: srpdataset.cpp 34458 2016-06-28 08:37:28Z rouault $");
+CPL_CVSID("$Id: srpdataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 class SRPDataset : public GDALPamDataset
 {
@@ -66,12 +67,10 @@ class SRPDataset : public GDALPamDataset
     int          PCB;
     int          PVB;
 
-
     char**       papszSubDatasets;
 
     GDALColorTable oCT;
 
-
     static char** GetGENListFromTHF(const char* pszFileName);
     static char** GetIMGListFromGEN(const char* pszFileName, int* pnRecordIndex = NULL);
     static SRPDataset* OpenDataset(const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record = NULL);
@@ -82,15 +81,15 @@ public:
     SRPDataset();
     virtual     ~SRPDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * padfGeoTransform );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * padfGeoTransform ) override;
 
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
 
-    virtual char **GetFileList();
+    virtual char **GetFileList() override;
 
-    int                 GetFromRecord( const char* pszFileName,
-                                       DDFRecord * record);
+    bool                GetFromRecord( const char* pszFileName,
+                                       DDFRecord * record );
     void                AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName );
     void  AddMetadatafromFromTHF(const char* pszFileName);
 
@@ -110,15 +109,14 @@ class SRPRasterBand : public GDALPamRasterBand
   public:
                             SRPRasterBand( SRPDataset *, int );
 
-    virtual CPLErr          IReadBlock( int, int, void * );
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
 
-    virtual double          GetNoDataValue( int *pbSuccess = NULL );
+    virtual double          GetNoDataValue( int *pbSuccess = NULL ) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
 };
 
-
 /************************************************************************/
 /*                           SRPRasterBand()                            */
 /************************************************************************/
@@ -126,8 +124,8 @@ class SRPRasterBand : public GDALPamRasterBand
 SRPRasterBand::SRPRasterBand( SRPDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Byte;
 
@@ -244,24 +242,26 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      If this is compressed data, we read a goodly chunk of data      */
 /*      and then decode it.                                             */
 /* -------------------------------------------------------------------- */
-    else if( l_poDS->PCB != 0 )
+    else
     {
-        int    nBufSize = 128*128*2;
-        int    nBytesRead, iPixel, iSrc, bHalfByteUsed = FALSE;
+        const int nBufSize = 128*128*2;
         GByte *pabyCData = (GByte *) CPLCalloc(nBufSize,1);
 
-        nBytesRead = static_cast<int>(VSIFReadL(pabyCData, 1, nBufSize, l_poDS->fdIMG));
+        const int nBytesRead =
+            static_cast<int>(VSIFReadL(pabyCData, 1, nBufSize, l_poDS->fdIMG));
         if( nBytesRead == 0 )
         {
             CPLError(CE_Failure, CPLE_FileIO,
                      "Cannot read data at offset %d", offset);
+            CPLFree(pabyCData);
             return CE_Failure;
         }
 
         CPLAssert( l_poDS->PVB == 8 );
         CPLAssert( l_poDS->PCB == 4 || l_poDS->PCB == 8 );
 
-        for( iSrc = 0, iPixel = 0; iPixel < 128 * 128; )
+        bool bHalfByteUsed = false;
+        for( int iSrc = 0, iPixel = 0; iPixel < 128 * 128; )
         {
             if( iSrc + 2 > nBytesRead )
             {
@@ -285,21 +285,21 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 if( (iPixel % 128) == 0 && bHalfByteUsed )
                 {
                     iSrc++;
-                    bHalfByteUsed = FALSE;
+                    bHalfByteUsed = false;
                 }
 
                 if( bHalfByteUsed )
                 {
                     nCount = pabyCData[iSrc++] & 0xf;
                     nValue = pabyCData[iSrc++];
-                    bHalfByteUsed = FALSE;
+                    bHalfByteUsed = false;
                 }
                 else
                 {
                     nCount = pabyCData[iSrc] >> 4;
                     nValue = ((pabyCData[iSrc] & 0xf) << 4)
                         + (pabyCData[iSrc+1] >> 4);
-                    bHalfByteUsed = TRUE;
+                    bHalfByteUsed = true;
                     iSrc++;
                 }
             }
@@ -330,14 +330,22 @@ CPLErr SRPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 SRPDataset::SRPDataset() :
-    NFC(0), NFL(0), ZNA(0), LSO(0.0), PSO(0.0), LOD(0.0), LAD(0.0), ARV(0),
-    BRV(0), PCB(0), PVB(0)
-{
-    fdIMG = NULL;
-    TILEINDEX = NULL;
-    offsetInIMG = 0;
-    papszSubDatasets = NULL;
-}
+    fdIMG(NULL),
+    TILEINDEX(NULL),
+    offsetInIMG(0),
+    NFC(0),
+    NFL(0),
+    ZNA(0),
+    LSO(0.0),
+    PSO(0.0),
+    LOD(0.0),
+    LAD(0.0),
+    ARV(0),
+    BRV(0),
+    PCB(0),
+    PVB(0),
+    papszSubDatasets(NULL)
+{}
 
 /************************************************************************/
 /*                          ~SRPDataset()                              */
@@ -345,15 +353,14 @@ SRPDataset::SRPDataset() :
 
 SRPDataset::~SRPDataset()
 {
-
     CSLDestroy(papszSubDatasets);
 
-    if (fdIMG)
+    if( fdIMG )
     {
         VSIFCloseL(fdIMG);
     }
 
-    if (TILEINDEX)
+    if( TILEINDEX )
     {
         delete [] TILEINDEX;
     }
@@ -441,34 +448,28 @@ CPLErr SRPDataset::GetGeoTransform( double * padfGeoTransform)
 /*                           GetFromRecord()                            */
 /************************************************************************/
 
-int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
+bool SRPDataset::GetFromRecord( const char* pszFileName, DDFRecord * record )
 {
-    CPLString osBAD;
-    int i;
-
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
     int bSuccess;
-    int nSTR;
 
 /* -------------------------------------------------------------------- */
 /*      Read a variety of header fields of interest from the .GEN       */
 /*      file.                                                           */
 /* -------------------------------------------------------------------- */
-    nSTR = record->GetIntSubfield( "GEN", 0, "STR", 0, &bSuccess );
+    const int nSTR = record->GetIntSubfield( "GEN", 0, "STR", 0, &bSuccess );
     if( !bSuccess || nSTR != 4 )
     {
         CPLDebug( "SRP", "Failed to extract STR, or not 4." );
-        return FALSE;
+        return false;
     }
 
-    int SCA = record->GetIntSubfield( "GEN", 0, "SCA", 0, &bSuccess );
+    const int SCA = record->GetIntSubfield( "GEN", 0, "SCA", 0, &bSuccess );
     CPLDebug("SRP", "SCA=%d", SCA);
 
     ZNA = record->GetIntSubfield( "GEN", 0, "ZNA", 0, &bSuccess );
     CPLDebug("SRP", "ZNA=%d", ZNA);
 
-    double PSP = record->GetFloatSubfield( "GEN", 0, "PSP", 0, &bSuccess );
+    const double PSP = record->GetFloatSubfield( "GEN", 0, "PSP", 0, &bSuccess );
     CPLDebug("SRP", "PSP=%f", PSP);
 
     ARV = record->GetIntSubfield( "GEN", 0, "ARV", 0, &bSuccess );
@@ -498,19 +499,19 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
         NFL > INT_MAX / NFC )
     {
         CPLError( CE_Failure, CPLE_AppDefined,"Invalid NFL / NFC values");
-        return FALSE;
+        return false;
     }
 
-    int PNC = record->GetIntSubfield( "SPR", 0, "PNC", 0, &bSuccess );
+    const int PNC = record->GetIntSubfield( "SPR", 0, "PNC", 0, &bSuccess );
     CPLDebug("SRP", "PNC=%d", PNC);
 
-    int PNL = record->GetIntSubfield( "SPR", 0, "PNL", 0, &bSuccess );
+    const int PNL = record->GetIntSubfield( "SPR", 0, "PNL", 0, &bSuccess );
     CPLDebug("SRP", "PNL=%d", PNL);
 
     if( PNL != 128 || PNC != 128 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,"Unsupported PNL or PNC value.");
-        return FALSE;
+        return false;
     }
 
     PCB = record->GetIntSubfield( "SPR", 0, "PCB", 0 );
@@ -519,13 +520,14 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "PCB(%d) or PVB(%d) value unsupported.", PCB, PVB );
-        return FALSE;
+        return false;
     }
 
-    const char* pszBAD = record->GetStringSubfield( "SPR", 0, "BAD", 0, &bSuccess );
+    const char* pszBAD =
+        record->GetStringSubfield( "SPR", 0, "BAD", 0, &bSuccess );
     if( pszBAD == NULL )
-        return FALSE;
-    osBAD = pszBAD;
+        return false;
+    const CPLString osBAD = pszBAD;
     {
         char* c = (char*) strchr(osBAD, ' ');
         if (c)
@@ -537,28 +539,28 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
 /*      Read the tile map if available.                                 */
 /* -------------------------------------------------------------------- */
     const char* pszTIF = record->GetStringSubfield( "SPR", 0, "TIF", 0 );
-    int TIF = pszTIF != NULL && EQUAL(pszTIF,"Y");
-    CPLDebug("SRP", "TIF=%d", TIF);
+    const bool TIF = pszTIF != NULL && EQUAL(pszTIF,"Y");
+    CPLDebug("SRP", "TIF=%s", TIF ? "true": "false");
 
-    if (TIF)
+    if( TIF )
     {
-        field = record->FindField( "TIM" );
+        DDFField* field = record->FindField( "TIM" );
         if( field == NULL )
-            return FALSE;
+            return false;
 
-        fieldDefn = field->GetFieldDefn();
+        DDFFieldDefn *fieldDefn = field->GetFieldDefn();
         DDFSubfieldDefn *subfieldDefn = fieldDefn->FindSubfieldDefn( "TSI" );
         if( subfieldDefn == NULL )
-            return FALSE;
+            return false;
 
-        int nIndexValueWidth = subfieldDefn->GetWidth();
+        const int nIndexValueWidth = subfieldDefn->GetWidth();
 
         /* Should be strict comparison, but apparently a few datasets */
         /* have GetDataSize() greater than the required minimum (#3862) */
         if (nIndexValueWidth > (INT_MAX - 1) / (NFL * NFC) ||
             field->GetDataSize() < nIndexValueWidth * NFL * NFC + 1)
         {
-            return FALSE;
+            return false;
         }
 
         try
@@ -567,18 +569,18 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
         }
         catch( const std::bad_alloc& )
         {
-            return FALSE;
+            return false;
         }
         const char* ptr = field->GetData();
-        char offset[30]={0};
+        char offset[30] = {0};
         offset[nIndexValueWidth] = '\0';
 
-        for(i=0;i<NFL*NFC;i++)
+        for( int i = 0; i < NFL * NFC; i++ )
         {
             strncpy(offset, ptr, nIndexValueWidth);
             ptr += nIndexValueWidth;
             TILEINDEX[i] = atoi(offset);
-            //CPLDebug("SRP", "TSI[%d]=%d", i, TILEINDEX[i]);
+            // CPLDebug("SRP", "TSI[%d]=%d", i, TILEINDEX[i]);
         }
     }
 
@@ -586,14 +588,15 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
 /*      Open the .IMG file.  Try to recover gracefully if the case      */
 /*      of the filename is wrong.                                       */
 /* -------------------------------------------------------------------- */
-    CPLString osDirname = CPLGetDirname(pszFileName);
-    CPLString osImgName = CPLFormCIFilename(osDirname, osBAD, NULL);
+    const CPLString osDirname = CPLGetDirname(pszFileName);
+    const CPLString osImgName = CPLFormCIFilename(osDirname, osBAD, NULL);
 
     fdIMG = VSIFOpenL(osImgName, "rb");
     if (fdIMG == NULL)
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "Cannot find %s", osImgName.c_str());
-        return FALSE;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Cannot find %s", osImgName.c_str() );
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -603,18 +606,18 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
 /*      This code is awfully fragile!                                   */
 /* -------------------------------------------------------------------- */
     char c;
-    char recordName[3];
     if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
     {
-        return FALSE;
+        return false;
     }
     while (!VSIFEofL(fdIMG))
     {
         if (c == 30)
         {
+            char recordName[3] = {};
             if (VSIFReadL(recordName, 1, 3, fdIMG) != 3)
             {
-                return FALSE;
+                return false;
             }
             offsetInIMG += 3;
             if (STARTS_WITH(recordName, "IMG"))
@@ -622,18 +625,18 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
                 offsetInIMG += 4;
                 if (VSIFSeekL(fdIMG,3,SEEK_CUR) != 0)
                 {
-                    return FALSE;
+                    return false;
                 }
                 if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
                 {
-                    return FALSE;
+                    return false;
                 }
                 while( c != 30 )
                 {
                     offsetInIMG ++;
                     if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
                     {
-                        return FALSE;
+                        return false;
                     }
                 }
                 offsetInIMG ++;
@@ -644,13 +647,13 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
         offsetInIMG ++;
         if (VSIFReadL(&c, 1, 1, fdIMG) != 1)
         {
-            return FALSE;
+            return false;
         }
     }
 
     if (VSIFEofL(fdIMG))
     {
-        return FALSE;
+        return false;
     }
 
     CPLDebug("SRP", "Img offset data = %d", offsetInIMG);
@@ -661,18 +664,18 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
     nRasterXSize = NFC * 128;
     nRasterYSize = NFL * 128;
 
-    char szValue[32];
+    char szValue[32] = {};
     snprintf(szValue, sizeof(szValue), "%d", SCA);
     SetMetadataItem( "SRP_SCA", szValue );
 
     nBands = 1;
-    for( i = 0; i < nBands; i++ )
+    for( int i = 0; i < nBands; i++ )
         SetBand( i+1, new SRPRasterBand( this, i+1 ) );
 
 /* -------------------------------------------------------------------- */
 /*      Try to collect a color map from the .QAL file.                  */
 /* -------------------------------------------------------------------- */
-    CPLString osBasename = CPLGetBasename(pszFileName);
+    const CPLString osBasename = CPLGetBasename(pszFileName);
     osQALFileName = CPLFormCIFilename(osDirname, osBasename, "QAL");
 
     DDFModule oQALModule;
@@ -683,28 +686,27 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
         {
             if( record->FindField( "COL" ) != NULL )
             {
-                int            iColor;
-                int            nColorCount = std::min(256,
-                    record->FindField("COL")->GetRepeatCount());
+                const int nColorCount =
+                    std::min(256, record->FindField("COL")->GetRepeatCount());
 
-                for( iColor = 0; iColor < nColorCount; iColor++ )
+                for( int iColor = 0; iColor < nColorCount; iColor++ )
                 {
-                    int nCCD, nNSR, nNSG, nNSB;
-                    GDALColorEntry sEntry;
-
-                    nCCD = record->GetIntSubfield( "COL", 0, "CCD", iColor,
-                        &bSuccess );
+                    const int nCCD =
+                        record->GetIntSubfield( "COL", 0, "CCD", iColor,
+                                                &bSuccess );
                     if( !bSuccess || nCCD < 0 || nCCD > 255 )
                         break;
 
-                    nNSR = record->GetIntSubfield( "COL", 0, "NSR", iColor );
-                    nNSG = record->GetIntSubfield( "COL", 0, "NSG", iColor );
-                    nNSB = record->GetIntSubfield( "COL", 0, "NSB", iColor );
+                    int nNSR = record->GetIntSubfield("COL", 0, "NSR", iColor);
+                    int nNSG = record->GetIntSubfield("COL", 0, "NSG", iColor);
+                    int nNSB = record->GetIntSubfield("COL", 0, "NSB", iColor);
 
-                    sEntry.c1 = (short) nNSR;
-                    sEntry.c2 = (short) nNSG;
-                    sEntry.c3 = (short) nNSB;
-                    sEntry.c4 = 255;
+                    GDALColorEntry sEntry = {
+                        static_cast<short>(nNSR),
+                        static_cast<short>(nNSG),
+                        static_cast<short>(nNSB),
+                        255
+                    };
 
                     oCT.SetColorEntry( nCCD, &sEntry );
                 }
@@ -714,10 +716,11 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
             {
                 // TODO: Translate to English or state why this should not be in
                 // English.
-                //Date de production du produit : QAL.QUV.DAT1
-                //Num�ro d'�dition  du produit : QAL.QUV.EDN
+                // Date de production du produit : QAL.QUV.DAT1
+                // Num�ro d'�dition  du produit : QAL.QUV.EDN
 
-                int EDN = record->GetIntSubfield( "QUV", 0, "EDN", 0, &bSuccess );
+                const int EDN =
+                    record->GetIntSubfield( "QUV", 0, "EDN", 0, &bSuccess );
                 if (bSuccess)
                 {
                     CPLDebug("SRP", "EDN=%d", EDN);
@@ -725,29 +728,34 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
                     SetMetadataItem( "SRP_EDN", szValue );
                 }
 
-
-                const char* pszCDV07 = record->GetStringSubfield( "QUV", 0, "CDV07", 0 );
+                const char* pszCDV07 =
+                    record->GetStringSubfield( "QUV", 0, "CDV07", 0 );
                 if (pszCDV07!=NULL)
                     SetMetadataItem( "SRP_CREATIONDATE", pszCDV07 );
                 else
                 { /*USRP1.2*/
-                    const char* pszDAT = record->GetStringSubfield("QUV", 0, "DAT1", 0);
+                    const char* pszDAT =
+                        record->GetStringSubfield("QUV", 0, "DAT1", 0);
                     if( pszDAT != NULL )
                     {
                         char dat[9];
-                        strncpy(dat,pszDAT+4,8);
+                        strncpy(dat, pszDAT+4, 8);
                         dat[8]='\0';
                         CPLDebug("SRP", "Record DAT %s",dat);
                         SetMetadataItem( "SRP_CREATIONDATE", dat );
                     }
                 }
 
-                const char* pszCDV24 = record->GetStringSubfield( "QUV", 0, "CDV24", 0 );
+                const char* pszCDV24 =
+                    record->GetStringSubfield( "QUV", 0, "CDV24", 0 );
                 if (pszCDV24!=NULL)
+                {
                     SetMetadataItem( "SRP_REVISIONDATE", pszCDV24 );
+                }
                 else
                 { /*USRP1.2*/
-                    const char* pszDAT = record->GetStringSubfield("QUV", 0, "DAT2", 0);
+                    const char* pszDAT =
+                        record->GetStringSubfield("QUV", 0, "DAT2", 0);
                     if( pszDAT != NULL )
                     {
                         char dat[9];
@@ -758,7 +766,8 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
                     }
                 }
 
-                const char* pszQSS = record->GetStringSubfield( "QSR", 0, "QSS", 0 );
+                const char* pszQSS =
+                    record->GetStringSubfield( "QSR", 0, "QSS", 0 );
                 if (pszQSS!=NULL)
                     SetMetadataItem( "SRP_CLASSIFICATION", pszQSS );
             }
@@ -780,21 +789,37 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
 
         if( ZNA == 9 )
         {
-            osSRS = "PROJCS[\"ARC_System_Zone_09\",GEOGCS[\"GCS_Sphere\",DATUM[\"D_Sphere\",SPHEROID[\"Sphere\",6378137.0,0.0]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Azimuthal_Equidistant\"],PARAMETER[\"latitude_of_center\",90],PARAMETER[\"longitude_of_center\",0],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]";
+            osSRS =
+                "PROJCS[\"ARC_System_Zone_09\",GEOGCS[\"GCS_Sphere\","
+                "DATUM[\"D_Sphere\",SPHEROID[\"Sphere\",6378137.0,0.0]],"
+                "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],"
+                "PROJECTION[\"Azimuthal_Equidistant\"],"
+                "PARAMETER[\"latitude_of_center\",90],"
+                "PARAMETER[\"longitude_of_center\",0],"
+                "PARAMETER[\"false_easting\",0],"
+                "PARAMETER[\"false_northing\",0]]";
         }
 
         if (ZNA == 18)
         {
-            osSRS = "PROJCS[\"ARC_System_Zone_18\",GEOGCS[\"GCS_Sphere\",DATUM[\"D_Sphere\",SPHEROID[\"Sphere\",6378137.0,0.0]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Azimuthal_Equidistant\"],PARAMETER[\"latitude_of_center\",-90],PARAMETER[\"longitude_of_center\",0],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]";
+            osSRS =
+                "PROJCS[\"ARC_System_Zone_18\",GEOGCS[\"GCS_Sphere\","
+                "DATUM[\"D_Sphere\",SPHEROID[\"Sphere\",6378137.0,0.0]],"
+                "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],"
+                "PROJECTION[\"Azimuthal_Equidistant\"],"
+                "PARAMETER[\"latitude_of_center\",-90],"
+                "PARAMETER[\"longitude_of_center\",0],"
+                "PARAMETER[\"false_easting\",0],"
+                "PARAMETER[\"false_northing\",0]]";
         }
     }
     else
     {
         OGRSpatialReference oSRS;
 
-        if( ABS(ZNA) >= 1 && ABS(ZNA) <= 60 )
+        if( std::abs(ZNA) >= 1 && std::abs(ZNA) <= 60 )
         {
-            oSRS.SetUTM( ABS(ZNA), ZNA > 0 );
+            oSRS.SetUTM(std::abs(ZNA), ZNA > 0);
             oSRS.SetWellKnownGeogCS( "WGS84" );
         }
         else if( ZNA == 61 )
@@ -815,7 +840,7 @@ int SRPDataset::GetFromRecord(const char* pszFileName, DDFRecord * record)
     snprintf(szValue, sizeof(szValue), "%d", ZNA);
     SetMetadataItem( "SRP_ZNA", szValue );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -826,27 +851,29 @@ char **SRPDataset::GetFileList()
 
 {
     char **papszFileList = GDALPamDataset::GetFileList();
-    if (osGENFileName.size() > 0 && osIMGFileName.size() > 0)
+    if (!osGENFileName.empty() && !osIMGFileName.empty())
     {
         CPLString osMainFilename = GetDescription();
-        int bMainFileReal;
         VSIStatBufL  sStat;
 
-        bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
+        const bool bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
         if (bMainFileReal)
         {
             CPLString osShortMainFilename = CPLGetFilename(osMainFilename);
             CPLString osShortGENFileName = CPLGetFilename(osGENFileName);
-            if ( !EQUAL(osShortMainFilename.c_str(), osShortGENFileName.c_str()) )
-                papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
+            if( !EQUAL(osShortMainFilename.c_str(),
+                       osShortGENFileName.c_str()) )
+                papszFileList =
+                    CSLAddString(papszFileList, osGENFileName.c_str());
         }
         else
+        {
             papszFileList = CSLAddString(papszFileList, osGENFileName.c_str());
+        }
 
         papszFileList = CSLAddString(papszFileList, osIMGFileName.c_str());
 
-
-        if( strlen(osQALFileName) > 0 )
+        if( !osQALFileName.empty() )
             papszFileList = CSLAddString( papszFileList, osQALFileName );
     }
     return papszFileList;
@@ -856,17 +883,17 @@ char **SRPDataset::GetFileList()
 /*                           AddSubDataset()                            */
 /************************************************************************/
 
-void SRPDataset::AddSubDataset( const char* pszGENFileName, const char* pszIMGFileName )
+void SRPDataset::AddSubDataset( const char* pszGENFileName,
+                                const char* pszIMGFileName )
 {
-    char szName[80];
-    int nCount = CSLCount(papszSubDatasets ) / 2;
+    const int nCount = CSLCount(papszSubDatasets ) / 2;
 
-    CPLString osSubDatasetName;
-    osSubDatasetName = "SRP:";
+    CPLString osSubDatasetName = "SRP:";
     osSubDatasetName += pszGENFileName;
     osSubDatasetName += ",";
     osSubDatasetName += pszIMGFileName;
 
+    char szName[80];
     snprintf(szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
     papszSubDatasets =
         CSLSetNameValue( papszSubDatasets, szName, osSubDatasetName);
@@ -893,21 +920,20 @@ char **SRPDataset::GetMetadata( const char *pszDomain )
 /*                      FindRecordInGENForIMG()                         */
 /************************************************************************/
 
-DDFRecord* SRPDataset::FindRecordInGENForIMG(DDFModule& module,
-                                            const char* pszGENFileName,
-                                            const char* pszIMGFileName)
+DDFRecord* SRPDataset::FindRecordInGENForIMG( DDFModule& module,
+                                              const char* pszGENFileName,
+                                              const char* pszIMGFileName )
 {
     /* Finds the GEN file corresponding to the IMG file */
     if (!module.Open(pszGENFileName, TRUE))
         return NULL;
 
-
     CPLString osShortIMGFilename = CPLGetFilename(pszIMGFileName);
 
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
+    DDFField* field = NULL;
+    DDFFieldDefn *fieldDefn = NULL;
 
-    /* Now finds the record */
+    // Now finds the record.
     while( true )
     {
         CPLPushErrorHandler( CPLQuietErrorHandler );
@@ -949,7 +975,7 @@ DDFRecord* SRPDataset::FindRecordInGENForIMG(DDFModule& module,
             const char* pszBAD = record->GetStringSubfield("SPR", 0, "BAD", 0);
             if( pszBAD == NULL || strlen(pszBAD) != 12 )
                 continue;
-            CPLString osBAD = pszBAD;
+            const CPLString osBAD = pszBAD;
             {
                 char* c = (char*) strchr(osBAD.c_str(), ' ');
                 if (c)
@@ -970,9 +996,7 @@ DDFRecord* SRPDataset::FindRecordInGENForIMG(DDFModule& module,
 SRPDataset* SRPDataset::OpenDataset(
     const char* pszGENFileName, const char* pszIMGFileName, DDFRecord* record)
 {
-    DDFModule module;
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
+    DDFModule module; // Don't move this line as it holds ownership of record.
 
     if (record == NULL)
     {
@@ -981,10 +1005,10 @@ SRPDataset* SRPDataset::OpenDataset(
             return NULL;
     }
 
-    field = record->GetField(1);
+    DDFField* field = record->GetField(1);
     if( field == NULL )
         return NULL;
-    fieldDefn = field->GetFieldDefn();
+    DDFFieldDefn *fieldDefn = field->GetFieldDefn();
 
     if (!(strcmp(fieldDefn->GetName(), "DSI") == 0 &&
         fieldDefn->GetSubfieldCount() == 2))
@@ -1006,8 +1030,7 @@ SRPDataset* SRPDataset::OpenDataset(
     if( pszNAM == NULL  )
         return NULL;
 
-
-    CPLString osNAM = pszNAM;
+    const CPLString osNAM = pszNAM;
     CPLDebug("SRP", "osNAM=%s", osNAM.c_str());
     if ( strlen(pszNAM) != 8 )
     {
@@ -1023,7 +1046,6 @@ SRPDataset* SRPDataset::OpenDataset(
     poDS->SetMetadataItem( "SRP_NAM", osNAM );
     poDS->SetMetadataItem( "SRP_PRODUCT", osPRT );
 
-
     if (!poDS->GetFromRecord( pszGENFileName, record ) )
     {
         delete poDS;
@@ -1033,7 +1055,6 @@ SRPDataset* SRPDataset::OpenDataset(
     return poDS;
 }
 
-
 /************************************************************************/
 /*                          GetGENListFromTHF()                         */
 /************************************************************************/
@@ -1041,10 +1062,9 @@ SRPDataset* SRPDataset::OpenDataset(
 char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
 {
     DDFModule module;
-    DDFRecord * record;
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
-    int i;
+    DDFRecord * record = NULL;
+    DDFField* field = NULL;
+    DDFFieldDefn *fieldDefn = NULL;
     int nFilenames = 0;
 
     char** papszFileNames = NULL;
@@ -1088,7 +1108,7 @@ char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
                 }
 
                 int iFDRFieldInstance = 0;
-                for (i = 2; i < record->GetFieldCount() ; i++)
+                for( int i = 2; i < record->GetFieldCount() ; i++ )
                 {
                     field = record->GetField(i);
                     fieldDefn = field->GetFieldDefn();
@@ -1104,7 +1124,6 @@ char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
                     if( pszNAM == NULL)
                         continue;
 
-
                     CPLString osName = CPLString(pszNAM);
 
                     /* Define a subdirectory from Dataset but with only 6 characters */
@@ -1114,9 +1133,8 @@ char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
 
                     CPLString osGENFileName="";
 
-
                     int bFound=0;
-                    if (bFound ==0)
+
                     {
                         char** papszDirContent = VSIReadDir(osDatasetDir.c_str());
                         char** ptrDir = papszDirContent;
@@ -1135,8 +1153,8 @@ char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
                             }
                             CSLDestroy(papszDirContent);
                         }
-
                     }
+
                     /* If not found in sub directory then search in the same directory of the THF file */
                     if (bFound ==0)
                     {
@@ -1157,10 +1175,8 @@ char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
                             }
                             CSLDestroy(papszDirContent);
                         }
-
                     }
 
-
                     if (bFound ==1)
                     {
                         papszFileNames = (char**)CPLRealloc(papszFileNames, sizeof(char*) * (nFilenames + 2));
@@ -1168,16 +1184,13 @@ char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
                         papszFileNames[nFilenames + 1] = NULL;
                         nFilenames ++;
                     }
-
                 }
             }
-
         }
     }
     return papszFileNames;
 }
 
-
 /************************************************************************/
 /*                          AddMetadatafromFromTHF()                         */
 /************************************************************************/
@@ -1185,9 +1198,9 @@ char** SRPDataset::GetGENListFromTHF(const char* pszFileName)
 void SRPDataset::AddMetadatafromFromTHF(const char* pszFileName)
 {
     DDFModule module;
-    DDFRecord * record;
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
+    DDFRecord * record = NULL;
+    DDFField* field = NULL;
+    DDFFieldDefn *fieldDefn = NULL;
 
     int bSuccess=0;
     if (!module.Open(pszFileName, TRUE))
@@ -1226,7 +1239,6 @@ void SRPDataset::AddMetadatafromFromTHF(const char* pszFileName)
                     SetMetadataItem( "SRP_VOO", pszVOO );
                 }
 
-
                 int EDN = record->GetIntSubfield( "VDR", 0, "EDN", 0, &bSuccess );
                 if (bSuccess)
                 {
@@ -1236,7 +1248,6 @@ void SRPDataset::AddMetadatafromFromTHF(const char* pszFileName)
                     SetMetadataItem( "SRP_EDN", szValue );
                 }
 
-
                 const char* pszCDV07 = record->GetStringSubfield("VDR", 0, "CDV07", 0);
                 if( pszCDV07 != NULL )
                 {
@@ -1255,7 +1266,6 @@ void SRPDataset::AddMetadatafromFromTHF(const char* pszFileName)
                         SetMetadataItem( "SRP_CREATIONDATE", dat );
                     }
                 }
-
             }
         } /* End of THF part */
 
@@ -1295,7 +1305,6 @@ void SRPDataset::AddMetadatafromFromTHF(const char* pszFileName)
                 }
             }
         }  /* End of LCF part */
-
     }
 }
 
@@ -1306,9 +1315,9 @@ void SRPDataset::AddMetadatafromFromTHF(const char* pszFileName)
 char** SRPDataset::GetIMGListFromGEN(const char* pszFileName,
                                     int *pnRecordIndex)
 {
-    DDFRecord * record;
-    DDFField* field;
-    DDFFieldDefn *fieldDefn;
+    DDFRecord * record = NULL;
+    DDFField* field = NULL;
+    DDFFieldDefn *fieldDefn = NULL;
     int nFilenames = 0;
     char** papszFileNames = NULL;
     int nRecordIndex = -1;
@@ -1385,7 +1394,7 @@ char** SRPDataset::GetIMGListFromGEN(const char* pszFileName,
             }
             else
             {
-                char** papszDirContent;
+                char** papszDirContent = NULL;
                 if (strcmp(osGENDir.c_str(), "/vsimem") == 0)
                 {
                     CPLString osTmp = osGENDir + "/";
@@ -1522,10 +1531,10 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
 
             osIMGFileName = osFileName;
 
-            static const size_t nLeaderSize = 24;
-            int         i;
+            static const int nLeaderSize = 24;
 
-            for( i = 0; i < (int)nLeaderSize; i++ )
+            int i = 0;  // Used after for.
+            for( ; i < nLeaderSize; i++ )
             {
                 if( poOpenInfo->pabyHeader[i] < 32
                     || poOpenInfo->pabyHeader[i] > 126 )
@@ -1572,11 +1581,10 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-    if (osGENFileName.size() > 0 &&
-        osIMGFileName.size() > 0)
+    if (!osGENFileName.empty() &&
+        !osIMGFileName.empty())
     {
 
-
         if( poOpenInfo->eAccess == GA_Update )
         {
             CPLError( CE_Failure, CPLE_NotSupported,
@@ -1590,8 +1598,7 @@ GDALDataset *SRPDataset::Open( GDALOpenInfo * poOpenInfo )
         if (nRecordIndex >= 0 &&
             module.Open(osGENFileName.c_str(), TRUE))
         {
-            int i;
-            for(i=0;i<nRecordIndex;i++)
+            for( int i = 0; i < nRecordIndex; i++ )
             {
                 CPLPushErrorHandler( CPLQuietErrorHandler );
                 record = module.ReadRecord();
diff --git a/frmts/aigrid/aigccitt.c b/frmts/aigrid/aigccitt.c
index 603accf..5270b4f 100644
--- a/frmts/aigrid/aigccitt.c
+++ b/frmts/aigrid/aigccitt.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigccitt.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: aigccitt.c 36763 2016-12-09 22:10:55Z rouault $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Code for decoding CCITT RLE (G1) compressed data.
@@ -1311,7 +1311,7 @@ static const char* StateNames[] = {
     int t;								\
     NeedBits8(wid,eoflab);						\
     TabEnt = tab + GetBits(wid);					\
-    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,		\
+    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,/*ok*/ 	\
 	   StateNames[TabEnt->State], TabEnt->Param);			\
     for (t = 0; t < TabEnt->Width; t++)					\
 	DEBUG_SHOW;							\
@@ -1323,7 +1323,7 @@ static const char* StateNames[] = {
     int t;								\
     NeedBits16(wid,eoflab);						\
     TabEnt = tab + GetBits(wid);					\
-    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,		\
+    printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail,/*ok*/ 	\
 	   StateNames[TabEnt->State], TabEnt->Param);			\
     for (t = 0; t < TabEnt->Width; t++)					\
 	DEBUG_SHOW;							\
@@ -1334,7 +1334,7 @@ static const char* StateNames[] = {
 
 #define SETVAL(x) do {							\
     *pa++ = RunLength + (x);						\
-    printf("SETVAL: %d\t%d\n", RunLength + (x), a0);			\
+    printf("SETVAL: %d\t%d\n", RunLength + (x), a0);	/*ok*/     	\
     a0 += x;								\
     RunLength = 0;							\
 } while (0)
@@ -1584,6 +1584,12 @@ Fax3PrematureEOF()
  * this is <8 bytes.  We optimize the code here to reflect the
  * machine characteristics.
  */
+
+#if __GNUC__ >= 7
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#endif
+
 #if SIZEOF_UNSIGNED_LONG == 8
 #define FILL(n, cp)							    \
     switch (n) {							    \
@@ -1658,13 +1664,13 @@ aig_TIFFFax3fillruns(unsigned char* buf, GUInt32* runs, GUInt32* erun,
 			     */
 			    for (; n && !isAligned(cp, long); n--)
 				    *cp++ = 0x00;
-			    lp = (long*) cp;
+			    lp = (long*) (void*) cp;
 			    nw = (GInt32)(n / sizeof (long));
 			    n -= nw * sizeof (long);
 			    do {
 				    *lp++ = 0L;
 			    } while (--nw);
-			    cp = (unsigned char*) lp;
+			    cp = (unsigned char*) (void*) lp;
 			}
 			ZERO(n, cp);
 			run &= 7;
@@ -1693,13 +1699,13 @@ aig_TIFFFax3fillruns(unsigned char* buf, GUInt32* runs, GUInt32* erun,
 			     */
 			    for (; n && !isAligned(cp, long); n--)
 				*cp++ = 0xff;
-			    lp = (long*) cp;
+			    lp = (long*) (void*) cp;
 			    nw = (GInt32)(n / sizeof (long));
 			    n -= nw * sizeof (long);
 			    do {
 				*lp++ = -1L;
 			    } while (--nw);
-			    cp = (unsigned char*) lp;
+			    cp = (unsigned char*) (void*) lp;
 			}
 			FILL(n, cp);
 			run &= 7;
@@ -1716,6 +1722,10 @@ aig_TIFFFax3fillruns(unsigned char* buf, GUInt32* runs, GUInt32* erun,
 #undef	ZERO
 #undef	FILL
 
+#if __GNUC__ >= 7
+#pragma GCC diagnostic pop
+#endif
+
 /************************************************************************/
 /*                           Fax3DecodeRLE()                            */
 /*                                                                      */
@@ -1741,8 +1751,8 @@ Fax3DecodeRLE(Fax3BaseState* tif, unsigned char *buf, int occ,
         RunLength = 0;
         pa = thisrun;
 #ifdef FAX3_DEBUG
-        printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail);
-        printf("-------------------- \n");
+        printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail);/*ok*/
+        printf("-------------------- \n");/*ok*/
         fflush(stdout);
 #endif
 
diff --git a/frmts/aigrid/aigdataset.cpp b/frmts/aigrid/aigdataset.cpp
index db5856b..2bdbe4d 100644
--- a/frmts/aigrid/aigdataset.cpp
+++ b/frmts/aigrid/aigdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: aigdataset.cpp 33901 2016-04-06 16:31:31Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Driver
  * Purpose:  Implements GDAL interface to underlying library.
@@ -38,11 +37,10 @@
 
 #include <vector>
 
-CPL_CVSID("$Id: aigdataset.cpp 33901 2016-04-06 16:31:31Z goatbar $");
+CPL_CVSID("$Id: aigdataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 static CPLString OSR_GDS( char **papszNV, const char * pszField,
-                           const char *pszDefaultValue );
-
+                          const char *pszDefaultValue );
 
 /************************************************************************/
 /* ==================================================================== */
@@ -62,7 +60,7 @@ class CPL_DLL AIGDataset : public GDALPamDataset
     char        *pszProjection;
 
     GDALColorTable *poCT;
-    int         bHasReadRat;
+    bool        bHasReadRat;
 
     void        TranslateColorTable( const char * );
 
@@ -71,13 +69,13 @@ class CPL_DLL AIGDataset : public GDALPamDataset
 
   public:
                 AIGDataset();
-                ~AIGDataset();
+    virtual ~AIGDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char *GetProjectionRef(void);
-    virtual char **GetFileList(void);
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char *GetProjectionRef(void) override;
+    virtual char **GetFileList(void) override;
 };
 
 /************************************************************************/
@@ -95,14 +93,14 @@ class AIGRasterBand : public GDALPamRasterBand
 
                    AIGRasterBand( AIGDataset *, int );
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual double GetMinimum( int *pbSuccess );
-    virtual double GetMaximum( int *pbSuccess );
-    virtual double GetNoDataValue( int *pbSuccess );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual double GetMinimum( int *pbSuccess ) override;
+    virtual double GetMaximum( int *pbSuccess ) override;
+    virtual double GetNoDataValue( int *pbSuccess ) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual GDALRasterAttributeTable *GetDefaultRAT();
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual GDALRasterAttributeTable *GetDefaultRAT() override;
 };
 
 /************************************************************************/
@@ -112,8 +110,8 @@ class AIGRasterBand : public GDALPamRasterBand
 AIGRasterBand::AIGRasterBand( AIGDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     nBlockXSize = poDSIn->psInfo->nBlockXSize;
     nBlockYSize = poDSIn->psInfo->nBlockYSize;
@@ -212,7 +210,7 @@ GDALRasterAttributeTable *AIGRasterBand::GetDefaultRAT()
     if (!poODS->bHasReadRat)
     {
         poODS->ReadRAT();
-        poODS->bHasReadRat = TRUE;
+        poODS->bHasReadRat = true;
     }
 
     if( poODS->poRAT )
@@ -309,7 +307,6 @@ GDALColorTable *AIGRasterBand::GetColorTable()
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            AIGDataset()                            */
 /************************************************************************/
@@ -317,12 +314,11 @@ GDALColorTable *AIGRasterBand::GetColorTable()
 AIGDataset::AIGDataset() :
     psInfo(NULL),
     papszPrj(NULL),
+    pszProjection(CPLStrdup("")),
     poCT(NULL),
-    bHasReadRat(FALSE),
+    bHasReadRat(false),
     poRAT(NULL)
-{
-    pszProjection = CPLStrdup("");
-}
+{}
 
 /************************************************************************/
 /*                           ~AIGDataset()                            */
@@ -487,7 +483,7 @@ void AIGDataset::ReadRAT()
 /* -------------------------------------------------------------------- */
 /*      Process all records into RAT.                                   */
 /* -------------------------------------------------------------------- */
-    AVCField *pasFields;
+    AVCField *pasFields = NULL;
     int iRecord = 0;
 
     while( (pasFields = AVCBinReadNextTableRec(psFile)) != NULL )
@@ -549,8 +545,6 @@ void AIGDataset::ReadRAT()
 GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    AIGInfo_t *psInfo;
-
 /* -------------------------------------------------------------------- */
 /*      If the pass name ends in .adf assume a file within the          */
 /*      coverage has been selected, and strip that off the coverage     */
@@ -617,7 +611,7 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
                 bGotOne = true;
                 break;
             }
-        } while(0);
+        } while( false );
     }
 
     for( int iFile = 0;
@@ -650,7 +644,7 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    psInfo = AIGOpen( osCoverName.c_str(), "r" );
+    AIGInfo_t *psInfo = AIGOpen( osCoverName.c_str(), "r" );
 
     if( psInfo == NULL )
     {
@@ -698,7 +692,7 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
     CSLDestroy( papszFiles );
 
     // Look in parent if we don't find a .clr in the coverage dir.
-    if( strlen(osClrFilename) == 0 )
+    if( osClrFilename.empty() )
     {
         osTestName.Printf( "%s/../%s.clr",
                            psInfo->pszCoverName,
@@ -717,7 +711,7 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
             osClrFilename = osTestName;
     }
 
-    if( strlen(osClrFilename) > 0 )
+    if( !osClrFilename.empty() )
         poDS->TranslateColorTable( osClrFilename );
 
 /* -------------------------------------------------------------------- */
@@ -772,7 +766,7 @@ GDALDataset *AIGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, psInfo->pszCoverName );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -790,7 +784,7 @@ CPLErr AIGDataset::GetGeoTransform( double * padfTransform )
     padfTransform[4] = 0;
     padfTransform[5] = -psInfo->dfCellSizeY;
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -933,13 +927,13 @@ static CPLErr AIGRename( const char *pszNewName, const char *pszOldName )
     {
         CPLString osNewFilename;
 
-        if( !EQUALN(papszFileList[i],osOldPath,strlen(osOldPath)) )
+        if( !EQUALN(papszFileList[i],osOldPath,osOldPath.size()) )
         {
-            CPLAssert( FALSE );
+            CPLAssert( false );
             return CE_Failure;
         }
 
-        osNewFilename = osNewPath + (papszFileList[i] + strlen(osOldPath));
+        osNewFilename = osNewPath + (papszFileList[i] + osOldPath.size());
 
         papszNewFileList = CSLAddString( papszNewFileList, osNewFilename );
     }
diff --git a/frmts/aigrid/aigopen.c b/frmts/aigrid/aigopen.c
index 8b3bd8c..33f070a 100644
--- a/frmts/aigrid/aigopen.c
+++ b/frmts/aigrid/aigopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigopen.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: aigopen.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file access cover API for non-GDAL use.
@@ -30,7 +30,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: aigopen.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: aigopen.c 34521 2016-07-02 21:26:43Z goatbar $");
 
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
diff --git a/frmts/aigrid/aigrid.h b/frmts/aigrid/aigrid.h
index 4c1fa1b..f73b24f 100644
--- a/frmts/aigrid/aigrid.h
+++ b/frmts/aigrid/aigrid.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aigrid.h 33901 2016-04-06 16:31:31Z goatbar $
+ * $Id: aigrid.h 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file access include file.
diff --git a/frmts/aigrid/aigrid_format.html b/frmts/aigrid/aigrid_format.html
index e414e81..0ca8cd7 100755
--- a/frmts/aigrid/aigrid_format.html
+++ b/frmts/aigrid/aigrid_format.html
@@ -33,7 +33,7 @@ describing the data layout a binary raster file containing raster data.<p>
 <h2>Version</h2>
 
 I am not sure yet how the versions work for grid files.  I have been
-working primarily with grid files generated by ArcView 3.x, and it's associated
+working primarily with grid files generated by ArcView 3.x, and its associated
 gridio API.  The hdr.adf files I have examined start with the string
 <b>GRID1.2</b> for what that's worth.  Certainly the file naming conventions
 seem to follow the Arc/Info 7.x conventions rather than that of earlier
@@ -44,7 +44,7 @@ versions.<p>
 <h2>File Set</h2>
 
 A grid coverage actually consists of a number of files.  A grid normally
-lives in it's own directory named after the grid.  For instance, the
+lives in its own directory named after the grid.  For instance, the
 grid <b>nwgrd1</b> lives in the directory <b>nwgrd1</b>, and has the following
 component files:<p>
 
diff --git a/frmts/aigrid/aitest.c b/frmts/aigrid/aitest.c
index cd26995..4ef15e3 100644
--- a/frmts/aigrid/aitest.c
+++ b/frmts/aigrid/aitest.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: aitest.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: aitest.c 36393 2016-11-21 14:25:42Z rouault $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Test mainline for examining AIGrid files.
@@ -29,7 +29,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: aitest.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: aitest.c 36393 2016-11-21 14:25:42Z rouault $");
 
 /************************************************************************/
 /*                             DumpMagic()                              */
@@ -96,7 +96,7 @@ static void DumpMagic( AIGInfo_t * psInfo, int bVerbose )
 
         if( bReport )
         {
-            printf( " %02x %5d %5d @ %d %s\n", byMagic, i,
+            printf( " %02x %5d %5d @ %u %s\n", byMagic, i,
                     psTInfo->panBlockSize[i],
                     psTInfo->panBlockOffset[i],
                     pszMessage );
@@ -188,7 +188,7 @@ int main( int argc, char ** argv )
         DumpMagic( psInfo, bMagic );
 
 /* -------------------------------------------------------------------- */
-/*      Read a block, and report it's contents.                         */
+/*      Read a block, and report its contents.                          */
 /* -------------------------------------------------------------------- */
     panRaster = (GInt32 *)
         CPLMalloc(psInfo->nBlockXSize * psInfo->nBlockYSize * 4);
diff --git a/frmts/aigrid/gridlib.c b/frmts/aigrid/gridlib.c
index 0b624c1..02296e2 100644
--- a/frmts/aigrid/gridlib.c
+++ b/frmts/aigrid/gridlib.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gridlib.c 35241 2016-08-29 08:49:57Z rouault $
+ * $Id: gridlib.c 35251 2016-08-30 04:28:53Z goatbar $
  *
  * Project:  Arc/Info Binary Grid Translator
  * Purpose:  Grid file reading code.
@@ -30,7 +30,7 @@
 
 #include "aigrid.h"
 
-CPL_CVSID("$Id: gridlib.c 35241 2016-08-29 08:49:57Z rouault $");
+CPL_CVSID("$Id: gridlib.c 35251 2016-08-30 04:28:53Z goatbar $");
 
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
@@ -1147,8 +1147,6 @@ CPLErr AIGReadStatistics( const char * pszCoverName, AIGInfo_t * psInfo )
         return( CE_Failure );
     }
 
-    CPLFree( pszHDRFilename );
-
 /* -------------------------------------------------------------------- */
 /*      Get the contents - 3 or 4 doubles.                              */
 /* -------------------------------------------------------------------- */
@@ -1186,8 +1184,10 @@ CPLErr AIGReadStatistics( const char * pszCoverName, AIGInfo_t * psInfo )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Wrong content for %s",
                   pszHDRFilename );
+        CPLFree( pszHDRFilename );
         return CE_Failure;
     }
 
-    return( CE_None );
+    CPLFree( pszHDRFilename );
+    return CE_None;
 }
diff --git a/frmts/airsar/airsardataset.cpp b/frmts/airsar/airsardataset.cpp
index e2ce1a1..2c52ac3 100644
--- a/frmts/airsar/airsardataset.cpp
+++ b/frmts/airsar/airsardataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: airsardataset.cpp 33901 2016-04-06 16:31:31Z goatbar $
  *
  * Project:  AirSAR Reader
  * Purpose:  Implements read support for AirSAR Polarimetric data.
@@ -34,7 +33,7 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: airsardataset.cpp 33901 2016-04-06 16:31:31Z goatbar $");
+CPL_CVSID("$Id: airsardataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -81,7 +80,7 @@ class AirSARRasterBand : public GDALPamRasterBand
                 AirSARRasterBand( AirSARDataset *, int );
     virtual     ~AirSARRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /* locations of stokes matrix values within padfMatrix ... same order as they
@@ -106,8 +105,8 @@ AirSARRasterBand::AirSARRasterBand( AirSARDataset *poDSIn,
                                     int nBandIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
@@ -273,7 +272,7 @@ AirSARDataset::AirSARDataset() :
     padfMatrix(NULL),
     nDataStart(0),
     nRecordLength(0)
-{ }
+{}
 
 /************************************************************************/
 /*                           ~AirSARDataset()                           */
@@ -492,13 +491,11 @@ char ** AirSARDataset::ReadHeader( VSILFILE * fp, int nFileOffset,
 
         papszHeadInfo =
             CSLSetNameValue( papszHeadInfo, szPrefixedKeyName, szLine+iValue );
-
     }
 
     return papszHeadInfo;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -625,7 +622,7 @@ GDALDataset *AirSARDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/arg/GNUmakefile b/frmts/arg/GNUmakefile
index 1e22ece..d1e44e9 100644
--- a/frmts/arg/GNUmakefile
+++ b/frmts/arg/GNUmakefile
@@ -4,7 +4,7 @@ include ../../GDALmake.opt
 
 OBJ	=	argdataset.o
 
-CPPFLAGS :=	$(JSON_INCLUDE) -I../raw  $(CPPFLAGS)
+CPPFLAGS :=	-I../../ogr/ogrsf_frmts/geojson $(JSON_INCLUDE) -I../raw  $(CPPFLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/arg/argdataset.cpp b/frmts/arg/argdataset.cpp
index b26e943..de8a1ac 100644
--- a/frmts/arg/argdataset.cpp
+++ b/frmts/arg/argdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: argdataset.cpp 32205 2015-12-17 21:57:20Z goatbar $
  *
  * Project:  Azavea Raster Grid format driver.
  * Purpose:  Implements support for reading and writing Azavea Raster Grid
@@ -34,10 +33,10 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-#include <json.h>
+#include "ogrgeojsonreader.h"
 #include <limits>
 
-CPL_CVSID("$Id: argdataset.cpp 32205 2015-12-17 21:57:20Z goatbar $");
+CPL_CVSID("$Id: argdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -53,15 +52,15 @@ class ARGDataset : public RawDataset
 
     public:
         ARGDataset();
-        ~ARGDataset();
+        virtual ~ARGDataset();
 
-        CPLErr GetGeoTransform( double * padfTransform );
+        CPLErr GetGeoTransform( double * padfTransform ) override;
 
         static int Identify( GDALOpenInfo * );
         static GDALDataset *Open( GDALOpenInfo * );
         static GDALDataset *CreateCopy( const char *, GDALDataset *, int,
             char **, GDALProgressFunc, void *);
-        virtual char **GetFileList(void);
+        virtual char **GetFileList(void) override;
 };
 
 /************************************************************************/
@@ -111,7 +110,8 @@ CPLErr ARGDataset::GetGeoTransform( double * padfTransform )
 /************************************************************************/
 static CPLString GetJsonFilename(CPLString pszFilename)
 {
-    return CPLSPrintf( "%s/%s.json", CPLGetDirname(pszFilename), CPLGetBasename(pszFilename) );
+    return CPLSPrintf( "%s/%s.json", CPLGetDirname(pszFilename),
+                       CPLGetBasename(pszFilename) );
 }
 
 /************************************************************************/
@@ -121,8 +121,8 @@ static json_object * GetJsonObject(CPLString pszFilename)
 {
     CPLString osJSONFilename = GetJsonFilename(pszFilename);
 
-    json_object *pJSONObject
-        = json_object_from_file(const_cast<char *>(osJSONFilename.c_str()));
+    json_object *pJSONObject =
+        json_object_from_file(const_cast<char *>(osJSONFilename.c_str()));
     if (pJSONObject == NULL) {
         CPLDebug("ARGDataset", "GetJsonObject(): Could not parse JSON file.");
         return NULL;
@@ -134,12 +134,15 @@ static json_object * GetJsonObject(CPLString pszFilename)
 /************************************************************************/
 /*                          GetJsonValueStr()                           */
 /************************************************************************/
-static const char *GetJsonValueStr(json_object * pJSONObject, CPLString pszKey)
+static const char *GetJsonValueStr( json_object * pJSONObject,
+                                    CPLString pszKey )
 {
-    json_object *pJSONItem = json_object_object_get(pJSONObject, pszKey.c_str());
-    if (pJSONItem == NULL) {
+    json_object *pJSONItem =
+        CPL_json_object_object_get(pJSONObject, pszKey.c_str());
+    if( pJSONItem == NULL )
+    {
         CPLDebug("ARGDataset", "GetJsonValueStr(): "
-            "Could not find '%s' in JSON.", pszKey.c_str());
+                 "Could not find '%s' in JSON.", pszKey.c_str());
         return NULL;
     }
 
@@ -149,7 +152,7 @@ static const char *GetJsonValueStr(json_object * pJSONObject, CPLString pszKey)
 /************************************************************************/
 /*                          GetJsonValueDbl()                           */
 /************************************************************************/
-static double GetJsonValueDbl(json_object * pJSONObject, CPLString pszKey)
+static double GetJsonValueDbl( json_object * pJSONObject, CPLString pszKey )
 {
     const char *pszJSONStr = GetJsonValueStr(pJSONObject, pszKey.c_str());
     if (pszJSONStr == NULL) {
@@ -159,7 +162,8 @@ static double GetJsonValueDbl(json_object * pJSONObject, CPLString pszKey)
     double dfTmp = CPLStrtod(pszJSONStr, &pszTmp);
     if (pszTmp == pszJSONStr) {
         CPLDebug("ARGDataset", "GetJsonValueDbl(): "
-            "Key value is not a numeric value: %s:%s", pszKey.c_str(), pszTmp);
+                 "Key value is not a numeric value: %s:%s",
+                 pszKey.c_str(), pszTmp);
         return std::numeric_limits<double>::quiet_NaN();
     }
 
@@ -169,9 +173,9 @@ static double GetJsonValueDbl(json_object * pJSONObject, CPLString pszKey)
 /************************************************************************/
 /*                           GetJsonValueInt()                          */
 /************************************************************************/
-static int GetJsonValueInt(json_object *pJSONObject, CPLString pszKey)
+static int GetJsonValueInt( json_object *pJSONObject, CPLString pszKey )
 {
-    double dfTmp = GetJsonValueDbl(pJSONObject, pszKey.c_str());
+    const double dfTmp = GetJsonValueDbl(pJSONObject, pszKey.c_str());
     if (CPLIsNan(dfTmp)) {
         return -1;
     }
@@ -424,7 +428,8 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo *poOpenInfo )
 
         if (nErr == OGRERR_NONE) {
             CPLDebug("ARGDataset", "Open(): "
-                "The EPSG provided did not import cleanly. Defaulting to EPSG:3857");
+                     "The EPSG provided did not import cleanly. "
+                     "Defaulting to EPSG:3857");
         }
         else {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -507,9 +512,9 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo *poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
 #ifdef CPL_LSB
-    int bNative = FALSE;
+    bool bNative = false;
 #else
-    int bNative = TRUE;
+    bool bNative = true;
 #endif
 
     RawRasterBand *poBand
@@ -531,7 +536,7 @@ GDALDataset *ARGDataset::Open( GDALOpenInfo *poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -706,13 +711,14 @@ GDALDataset *ARGDataset::CreateCopy( const char *pszFilename,
     GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
 
 #ifdef CPL_LSB
-    int bNative = FALSE;
+    bool bNative = false;
 #else
-    int bNative = TRUE;
+    bool bNative = true;
 #endif
 
     RawRasterBand *poDstBand = new RawRasterBand( fpImage, 0, nPixelOffset,
-                                                  nPixelOffset * nXSize, eType, bNative,
+                                                  nPixelOffset * nXSize, eType,
+                                                  bNative,
                                                   nXSize, nYSize, TRUE, FALSE);
 
     int nXBlockSize, nYBlockSize;
@@ -723,7 +729,8 @@ GDALDataset *ARGDataset::CreateCopy( const char *pszFilename,
     // convert any blocks into scanlines
     for (int nYBlock = 0; nYBlock * nYBlockSize < nYSize; nYBlock++) {
         for (int nYScanline = 0; nYScanline < nYBlockSize; nYScanline++) {
-            if ((nYScanline+1) + nYBlock * nYBlockSize > poSrcBand->GetYSize() ) {
+            if ((nYScanline+1) + nYBlock * nYBlockSize > poSrcBand->GetYSize() )
+            {
                 continue;
             }
 
diff --git a/frmts/blx/blx.c b/frmts/blx/blx.c
index fd7c5d1..2ff9659 100644
--- a/frmts/blx/blx.c
+++ b/frmts/blx/blx.c
@@ -343,7 +343,7 @@ typedef union
 
 static int get_short_le(unsigned char **data) {
     /* We assume two's complement representation for this to work */
-    unionshort result;
+    unionshort result = { 0 };
     result.u = (unsigned short)(*(*data) | (*(*data+1)<<8));
     *data+=2;
     return result.s;
@@ -351,7 +351,7 @@ static int get_short_le(unsigned char **data) {
 
 static int get_short_be(unsigned char **data) {
     /* We assume two's complement representation for this to work */
-    unionshort result;
+    unionshort result = { 0 };
     result.u = (unsigned short)(*(*data+1) | (*(*data)<<8));
     *data+=2;
     return result.s;
@@ -359,7 +359,7 @@ static int get_short_be(unsigned char **data) {
 
 static void put_short_le(short data, unsigned char **bufptr) {
     /* We assume two's complement representation for this to work */
-    unionshort us;
+    unionshort us = { 0 };
     us.s = data;
     *(*bufptr)++ = (unsigned char)(us.u & 0xff);
     *(*bufptr)++ = (unsigned char)((us.u>>8) & 0xff);
@@ -367,7 +367,7 @@ static void put_short_le(short data, unsigned char **bufptr) {
 
 static void put_short_be(short data, unsigned char **bufptr) {
     /* We assume two's complement representation for this to work */
-    unionshort us;
+    unionshort us = { 0 };
     us.s = data;
     *(*bufptr)++ = (unsigned char)((us.u>>8) & 0xff);
     *(*bufptr)++ = (unsigned char)(us.u & 0xff);
@@ -438,7 +438,7 @@ typedef union
 
 static int get_int32(blxcontext_t *ctx, unsigned char **data) {
     /* We assume two's complement representation for this to work */
-    unionint result;
+    unionint result = { 0 };
 
     if(ctx->endian == LITTLEENDIAN)
 	result.u = *(*data) | (*(*data+1)<<8) | (*(*data+2)<<16) | (*(*data+3)<<24);
@@ -450,7 +450,7 @@ static int get_int32(blxcontext_t *ctx, unsigned char **data) {
 
 static void put_int32(blxcontext_t *ctx, int data, unsigned char **bufptr) {
     /* We assume two's complement representation for this to work */
-    unionint ui;
+    unionint ui = { 0 };
     ui.i = data;
     if(ctx->endian == LITTLEENDIAN) {
 	*(*bufptr)++ = (unsigned char)(ui.u & 0xff);
@@ -485,22 +485,8 @@ static int is_big_endian(void)
 }
 static double doubleSWAP(double df)
 {
-	union
-	{
-		double df;
-		unsigned char b[8];
-	} dat1, dat2;
-
-	dat1.df = df;
-	dat2.b[0] = dat1.b[7];
-	dat2.b[1] = dat1.b[6];
-	dat2.b[2] = dat1.b[5];
-	dat2.b[3] = dat1.b[4];
-	dat2.b[4] = dat1.b[3];
-	dat2.b[5] = dat1.b[2];
-	dat2.b[6] = dat1.b[1];
-	dat2.b[7] = dat1.b[0];
-	return dat2.df;
+        CPL_SWAP64PTR(&df);
+        return df;
 }
 
 static double get_double(blxcontext_t *ctx, unsigned char **data) {
@@ -561,13 +547,14 @@ int blx_encode_celldata(blxcontext_t *ctx,
                         CPL_UNUSED int outbufsize) {
     unsigned char *p=outbuf, *tmpdata, *coutstart, *cout=NULL;
     int level, cn, coutsize, zeros;
-    blxdata *vdec=NULL, *vdiff=NULL, *c[4], *tc1, *clut, *indata_scaled;
+    blxdata *vdec=NULL, *vdiff=NULL, *c[4] = { NULL }, *tc1, *clut, *indata_scaled;
 
     struct lutentry_s lut[256];
     int lutsize=0;
 
     int i, j;
 
+    memset( &lut, 0, sizeof(lut) );
     lut[0].value = 0;
 
     *p++ = (unsigned char)(side/32-4); /* Resolution */
@@ -583,9 +570,10 @@ int blx_encode_celldata(blxcontext_t *ctx,
 
     /* Scale indata and process undefined values*/
     for(i=0; i<side*side; i++) {
-	if((indata[i] == BLX_UNDEF) && ctx->fillundef)
+        if((indata[i] == BLX_UNDEF) && ctx->fillundef)
         indata[i] = (blxdata)ctx->fillundefval;
-	    indata_scaled[i] = (blxdata)(indata[i] / ctx->zscale);
+        /* cppcheck-suppress uninitdata */
+        indata_scaled[i] = (blxdata)(indata[i] / ctx->zscale);
     }
 
     indata = indata_scaled;
@@ -702,7 +690,7 @@ int blx_encode_celldata(blxcontext_t *ctx,
 STATIC blxdata *decode_celldata(blxcontext_t *ctx, unsigned char *inbuf, int len, int *side, blxdata *outbuf, int outbufsize, int overviewlevel) {
     unsigned char *inptr=inbuf;
     int resolution,l_div,level,c,n,i,j,dpos,v,tmp,a,value,l_index,step,cellsize;
-    int baseside[12];
+    int baseside[12] = { 0 };
     blxdata *base, *diff;
     struct component_s linfo[MAXLEVELS][MAXCOMPONENTS];
 
@@ -1122,7 +1110,7 @@ int blx_writecell(blxcontext_t *ctx, blxdata *cell, int cellrow, int cellcol) {
 
 int blxopen(blxcontext_t *ctx, const char *filename, const char *rw) {
     unsigned char header[102],*hptr;
-    int signature[2];
+    int signature[2] = { 0 };
     int i,j;
     struct cellindex_s *ci;
 
diff --git a/frmts/blx/blxdataset.cpp b/frmts/blx/blxdataset.cpp
index bd8bc82..17bdf41 100644
--- a/frmts/blx/blxdataset.cpp
+++ b/frmts/blx/blxdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: blxdataset.cpp 33901 2016-04-06 16:31:31Z goatbar $
  *
  * Project:  BLX Driver
  * Purpose:  GDAL BLX support.
@@ -38,19 +37,19 @@ CPL_C_START
 #include <blx.h>
 CPL_C_END
 
-CPL_CVSID("$Id: blxdataset.cpp 33901 2016-04-06 16:31:31Z goatbar $");
+CPL_CVSID("$Id: blxdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 class BLXDataset : public GDALPamDataset
 {
     friend class BLXRasterBand;
 
-    CPLErr      GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
+    const char *GetProjectionRef() override;
 
     blxcontext_t *blxcontext;
 
     int nOverviewCount;
-    int bIsOverview;
+    bool bIsOverview;
     BLXDataset *papoOverviewDS[BLX_OVERVIEWLEVELS];
 
   public:
@@ -67,12 +66,12 @@ class BLXRasterBand : public GDALPamRasterBand
   public:
     BLXRasterBand( BLXDataset *, int, int overviewLevel=0 );
 
-    virtual double  GetNoDataValue( int *pbSuccess = NULL );
-    virtual GDALColorInterp GetColorInterpretation(void);
-    virtual int GetOverviewCount();
-    virtual GDALRasterBand *GetOverview( int );
+    virtual double  GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual GDALColorInterp GetColorInterpretation(void) override;
+    virtual int GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview( int ) override;
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
@@ -129,7 +128,7 @@ GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
     for(int i=0; i < poDS->nOverviewCount; i++) {
         poDS->papoOverviewDS[i] = new BLXDataset();
         poDS->papoOverviewDS[i]->blxcontext = poDS->blxcontext;
-        poDS->papoOverviewDS[i]->bIsOverview = TRUE;
+        poDS->papoOverviewDS[i]->bIsOverview = true;
         poDS->papoOverviewDS[i]->nRasterXSize = poDS->nRasterXSize >> (i+1);
         poDS->papoOverviewDS[i]->nRasterYSize = poDS->nRasterYSize >> (i+1);
         poDS->nBands = 1;
@@ -154,20 +153,22 @@ GDALDataset *BLXDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML();
 
-    return( poDS );
+    return poDS;
 }
 
 BLXDataset::BLXDataset() :
     blxcontext(NULL),
     nOverviewCount(0),
-    bIsOverview(FALSE)
+    bIsOverview(false)
 {
-    for(int i=0; i < BLX_OVERVIEWLEVELS; i++)
-        papoOverviewDS[i]=NULL;
+    for( int i = 0; i < BLX_OVERVIEWLEVELS; i++ )
+        papoOverviewDS[i] = NULL;
 }
 
-BLXDataset::~BLXDataset() {
-    if(!bIsOverview) {
+BLXDataset::~BLXDataset()
+{
+    if( !bIsOverview )
+    {
         if(blxcontext) {
             blxclose(blxcontext);
             blx_free_context(blxcontext);
@@ -200,14 +201,14 @@ const char *BLXDataset::GetProjectionRef()
         "AUTHORITY[\"EPSG\",\"4326\"]]";
 }
 
-BLXRasterBand::BLXRasterBand( BLXDataset *poDSIn, int nBandIn, int overviewLevelIn )
-
+BLXRasterBand::BLXRasterBand( BLXDataset *poDSIn, int nBandIn,
+                              int overviewLevelIn ) :
+    overviewLevel(overviewLevelIn)
 {
     BLXDataset *poGDS = poDSIn;
 
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->overviewLevel = overviewLevelIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Int16;
 
@@ -375,7 +376,6 @@ BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     for(int i=0; (i < ctx->cell_rows) && (eErr == CE_None); i++)
         for(int j=0; j < ctx->cell_cols; j++) {
-            blxdata *celldata;
             GDALRasterBand * poBand = poSrcDS->GetRasterBand( 1 );
             eErr = poBand->RasterIO( GF_Read, j*ctx->cell_xsize, i*ctx->cell_ysize,
                                      ctx->cell_xsize, ctx->cell_ysize,
@@ -383,7 +383,7 @@ BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                                      0, 0, NULL );
             if(eErr >= CE_Failure)
                  break;
-            celldata = pabyTile;
+            blxdata *celldata = pabyTile;
             if (blx_writecell(ctx, celldata, i, j) != 0)
             {
                 eErr = CE_Failure;
@@ -419,7 +419,6 @@ BLXCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     return NULL;
 }
 
-
 void GDALRegister_BLX()
 
 {
diff --git a/frmts/bmp/bmpdataset.cpp b/frmts/bmp/bmpdataset.cpp
index a5c358f..80b239d 100644
--- a/frmts/bmp/bmpdataset.cpp
+++ b/frmts/bmp/bmpdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: bmpdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Microsoft Windows Bitmap
  * Purpose:  Read/write MS Windows Device Independent Bitmap (DIB) files
@@ -33,7 +32,7 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: bmpdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: bmpdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 // Enable if you want to see lots of BMP debugging output.
 // #define BMP_DEBUG
@@ -88,8 +87,11 @@ enum BMPLCSType                 // Type of logical color space.
 
 typedef struct
 {
+    // cppcheck-suppress unusedStructMember
     GInt32      iCIEX;
+    // cppcheck-suppress unusedStructMember
     GInt32      iCIEY;
+    // cppcheck-suppress unusedStructMember
     GInt32      iCIEZ;
 } BMPCIEXYZ;
 
@@ -146,16 +148,21 @@ typedef struct
                                 // is set to BI_BITFIELDS.
     GUInt32     iGreenMask;     // The same for green component
     GUInt32     iBlueMask;      // The same for blue component
+    // cppcheck-suppress unusedStructMember
     GUInt32     iAlphaMask;     // Colour mask that specifies the alpha
                                 // component of each pixel.
+    // cppcheck-suppress unusedStructMember
     BMPLCSType  iCSType;        // Colour space of the DIB.
     BMPCIEXYZTriple sEndpoints; // This member is ignored unless the iCSType member
                                 // specifies BMPLT_CALIBRATED_RGB.
+    // cppcheck-suppress unusedStructMember
     GUInt32     iGammaRed;      // Toned response curve for red. This member
                                 // is ignored unless color values are calibrated
                                 // RGB values and iCSType is set to
                                 // BMPLT_CALIBRATED_RGB. Specified in 16^16 format.
+    // cppcheck-suppress unusedStructMember
     GUInt32     iGammaGreen;    // Toned response curve for green.
+    // cppcheck-suppress unusedStructMember
     GUInt32     iGammaBlue;     // Toned response curve for blue.
 } BMPInfoHeader;
 
@@ -171,37 +178,39 @@ const unsigned int  BIH_OS22SIZE = 64; // for BMPT_OS22
 // provided for reference
 typedef struct
 {
+    // cppcheck-suppress unusedStructMember
     GByte       bBlue;
+    // cppcheck-suppress unusedStructMember
     GByte       bGreen;
+    // cppcheck-suppress unusedStructMember
     GByte       bRed;
+    // cppcheck-suppress unusedStructMember
     GByte       bReserved;      // Must be 0
 } BMPColorEntry;
 
 /*****************************************************************/
 
-static int countonbits(GUInt32 dw)
+static int countonbits( GUInt32 dw )
 {
     int r = 0;
-    for(int x = 0; x < 32; x++)
+    for( int x = 0; x < 32; x++ )
     {
-        if((dw & (1 << x)) != 0)
+        if( (dw & (1U << x)) != 0 )
             r++;
     }
     return r;
 }
 
-
-static int findfirstonbit(GUInt32 n)
+static int findfirstonbit( GUInt32 n )
 {
-    for(int x = 0; x < 32; x++)
+    for( int x = 0; x < 32; x++ )
     {
-        if((n & (1 << x)) != 0)
+        if( (n & (1U << x)) != 0 )
             return x;
     }
     return -1;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                              BMPDataset                              */
@@ -230,11 +239,11 @@ class BMPDataset : public GDALPamDataset
                                    int, int *,
                                    GSpacing nPixelSpace, GSpacing nLineSpace,
                                    GSpacing nBandSpace,
-                                   GDALRasterIOExtraArg* psExtraArg );
+                                   GDALRasterIOExtraArg* psExtraArg ) override;
 
   public:
                 BMPDataset();
-                ~BMPDataset();
+    virtual ~BMPDataset();
 
     static int           Identify( GDALOpenInfo * );
     static GDALDataset  *Open( GDALOpenInfo * );
@@ -242,8 +251,8 @@ class BMPDataset : public GDALPamDataset
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
 
-    CPLErr              GetGeoTransform( double * padfTransform );
-    virtual CPLErr      SetGeoTransform( double * );
+    CPLErr              GetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr      SetGeoTransform( double * ) override;
 };
 
 /************************************************************************/
@@ -265,13 +274,13 @@ class BMPRasterBand : public GDALPamRasterBand
   public:
 
                 BMPRasterBand( BMPDataset *, int );
-                ~BMPRasterBand();
+    virtual    ~BMPRasterBand();
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual CPLErr          IWriteBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable  *GetColorTable();
-    CPLErr                  SetColorTable( GDALColorTable * );
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual CPLErr          IWriteBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable  *GetColorTable() override;
+    CPLErr                  SetColorTable( GDALColorTable * ) override;
 };
 
 /************************************************************************/
@@ -279,12 +288,13 @@ class BMPRasterBand : public GDALPamRasterBand
 /************************************************************************/
 
 BMPRasterBand::BMPRasterBand( BMPDataset *poDSIn, int nBandIn ) :
-    nScanSize(0)
+    nScanSize(0),
+    iBytesPerPixel(poDSIn->sInfoHeader.iBitCount / 8),
+    pabyScan(NULL)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     eDataType = GDT_Byte;
-    iBytesPerPixel = poDSIn->sInfoHeader.iBitCount / 8;
 
     // We will read one scanline per time. Scanlines in BMP aligned at 4-byte
     // boundary
@@ -292,11 +302,14 @@ BMPRasterBand::BMPRasterBand( BMPDataset *poDSIn, int nBandIn ) :
     nBlockYSize = 1;
 
     if (nBlockXSize < (INT_MAX - 31) / poDSIn->sInfoHeader.iBitCount)
+    {
         nScanSize =
-            ((poDS->GetRasterXSize() * poDSIn->sInfoHeader.iBitCount + 31) & ~31) / 8;
+            ((poDS->GetRasterXSize() *
+              poDSIn->sInfoHeader.iBitCount + 31) & ~31) / 8;
+    }
     else
     {
-        pabyScan = NULL;
+        // pabyScan = NULL;
         return;
     }
 
@@ -306,7 +319,7 @@ BMPRasterBand::BMPRasterBand( BMPDataset *poDSIn, int nBandIn ) :
               nBand, nBlockXSize, nBlockYSize, nScanSize );
 #endif
 
-    pabyScan = (GByte *) VSIMalloc( nScanSize );
+    pabyScan = static_cast<GByte *>(VSIMalloc( nScanSize ));
 }
 
 /************************************************************************/
@@ -322,12 +335,12 @@ BMPRasterBand::~BMPRasterBand()
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+CPLErr BMPRasterBand::IReadBlock( int /* nBlockXOff */,
                                   int nBlockYOff,
                                   void * pImage )
 {
     BMPDataset  *poGDS = (BMPDataset *) poDS;
-    GUInt32     iScanOffset;
+    GUInt32 iScanOffset = 0;
 
     if ( poGDS->sInfoHeader.iHeight > 0 )
         iScanOffset = poGDS->sFileHeader.iOffBits +
@@ -338,7 +351,7 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     if ( VSIFSeekL( poGDS->fp, iScanOffset, SEEK_SET ) < 0 )
     {
         // XXX: We will not report error here, because file just may be
-    // in update state and data for this block will be available later
+        // in update state and data for this block will be available later.
         if( poGDS->eAccess == GA_Update )
         {
             memset( pImage, 0, nBlockXSize );
@@ -348,7 +361,7 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         {
             CPLError( CE_Failure, CPLE_FileIO,
                       "Can't seek to offset %ld in input file to read data.",
-                      (long) iScanOffset );
+                      static_cast<long>(iScanOffset) );
             return CE_Failure;
         }
     }
@@ -364,7 +377,7 @@ CPLErr BMPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         {
             CPLError( CE_Failure, CPLE_FileIO,
                       "Can't read from offset %ld in input file.",
-                      (long) iScanOffset );
+                      static_cast<long>(iScanOffset) );
             return CE_Failure;
         }
     }
@@ -674,11 +687,10 @@ class BMPComprRasterBand : public BMPRasterBand
     GByte           *pabyUncomprBuf;
 
   public:
-
                 BMPComprRasterBand( BMPDataset *, int );
-                ~BMPComprRasterBand();
+    virtual    ~BMPComprRasterBand();
 
-    virtual CPLErr          IReadBlock( int, int, void * );
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
 //    virtual CPLErr        IWriteBlock( int, int, void * );
 };
 
@@ -686,8 +698,10 @@ class BMPComprRasterBand : public BMPRasterBand
 /*                           BMPComprRasterBand()                       */
 /************************************************************************/
 
-BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDSIn, int nBandIn )
-    : BMPRasterBand( poDSIn, nBandIn )
+BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDSIn, int nBandIn ) :
+    BMPRasterBand( poDSIn, nBandIn ),
+    pabyComprBuf(NULL),
+    pabyUncomprBuf(NULL)
 {
     /* TODO: it might be interesting to avoid uncompressing the whole data */
     /* in a single pass, especially if nXSize * nYSize is big */
@@ -696,8 +710,6 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDSIn, int nBandIn )
     {
         CPLError(CE_Failure, CPLE_NotSupported, "Too big dimensions : %d x %d",
                  poDS->GetRasterXSize(), poDS->GetRasterYSize());
-        pabyComprBuf = NULL;
-        pabyUncomprBuf = NULL;
         return;
     }
 
@@ -705,8 +717,6 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDSIn, int nBandIn )
         poDSIn->sFileHeader.iSize - poDSIn->sFileHeader.iOffBits > INT_MAX )
     {
         CPLError(CE_Failure, CPLE_NotSupported, "Invalid header");
-        pabyComprBuf = NULL;
-        pabyUncomprBuf = NULL;
         return;
     }
 
@@ -744,7 +754,8 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDSIn, int nBandIn )
         pabyUncomprBuf = NULL;
         return;
     }
-    unsigned int k, iLength = 0;
+    unsigned int k = 0;
+    unsigned int iLength = 0;
     unsigned int i = 0;
     unsigned int j = 0;
     if ( poDSIn->sInfoHeader.iBitCount == 8 )         // RLE8
@@ -885,7 +896,6 @@ BMPComprRasterBand::BMPComprRasterBand( BMPDataset *poDSIn, int nBandIn )
     // rcg, release compressed buffer here.
     CPLFree( pabyComprBuf );
     pabyComprBuf = NULL;
-
 }
 
 /************************************************************************/
@@ -918,8 +928,12 @@ CPLErr BMPComprRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /************************************************************************/
 
 BMPDataset::BMPDataset() :
-    nColorElems(0), pabyColorTable(NULL),
-    poColorTable(NULL), bGeoTransformValid(FALSE), pszFilename(NULL), fp(NULL)
+    nColorElems(0),
+    pabyColorTable(NULL),
+    poColorTable(NULL),
+    bGeoTransformValid(FALSE),
+    pszFilename(NULL),
+    fp(NULL)
 {
     nBands = 0;
 
@@ -1353,7 +1367,7 @@ GDALDataset *BMPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1556,7 +1570,7 @@ GDALDataset *BMPDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Do we need a world file?                                        */
 /* -------------------------------------------------------------------- */
-    if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
+    if( CPLFetchBool( papszOptions, "WORLDFILE", false ) )
         poDS->bGeoTransformValid = TRUE;
 
     return (GDALDataset *) poDS;
diff --git a/frmts/bmp/frmt_bmp.html b/frmts/bmp/frmt_bmp.html
index 77a9aff..67611e5 100644
--- a/frmts/bmp/frmt_bmp.html
+++ b/frmts/bmp/frmt_bmp.html
@@ -34,8 +34,7 @@ used to establish the geotransform for the image.<p>
 <ul>
 <li> Implemented as <tt>gdal/frmts/bmp/bmpdataset.cpp</tt>.<p>
 
-<li> <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_9qg5.asp">
-MSDN Bitmap Reference
+<li> <a href="https://en.wikipedia.org/wiki/BMP_file_format">Wikipedia BMP file format
 </a><p>
 
 </ul>
diff --git a/frmts/bpg/bpgdataset.cpp b/frmts/bpg/bpgdataset.cpp
index a0a5aaf..2e1f3da 100644
--- a/frmts/bpg/bpgdataset.cpp
+++ b/frmts/bpg/bpgdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL BPG Driver
  * Purpose:  Implement GDAL BPG Support based on libbpg
@@ -38,10 +37,11 @@
 // g++ -fPIC -g -Wall -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -I/home/even/libbpg-0.9.4 frmts/bpg/bpgdataset.cpp -shared -o gdal_BPG.so -L. -lgdal -L/home/even/libbpg-0.9.4/ -lbpg
 
 CPL_C_START
+void CPL_DLL GDALRegister_BPG();
 #include "libbpg.h"
 CPL_C_END
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: bpgdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -83,21 +83,21 @@ class BPGRasterBand : public GDALPamRasterBand
 
                    BPGRasterBand( BPGDataset *, int nbits );
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
 /************************************************************************/
 /*                          BPGRasterBand()                            */
 /************************************************************************/
 
-BPGRasterBand::BPGRasterBand( BPGDataset *poDS, int nbits )
+BPGRasterBand::BPGRasterBand( BPGDataset *poDSIn, int nbits )
 {
-    this->poDS = poDS;
+    poDS = poDSIn;
 
-    eDataType = (nbits > 8) ? GDT_UInt16 : GDT_Byte;
+    eDataType = nbits > 8 ? GDT_UInt16 : GDT_Byte;
 
-    nBlockXSize = poDS->nRasterXSize;
+    nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 }
 
@@ -157,19 +157,16 @@ GDALColorInterp BPGRasterBand::GetColorInterpretation()
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            BPGDataset()                              */
 /************************************************************************/
 
-BPGDataset::BPGDataset()
-
-{
-    fpImage = NULL;
-    pabyUncompressed = NULL;
-    bHasBeenUncompressed = FALSE;
-    eUncompressErrRet = CE_None;
-}
+BPGDataset::BPGDataset() :
+    fpImage(NULL),
+    pabyUncompressed(NULL),
+    bHasBeenUncompressed(FALSE),
+    eUncompressErrRet(CE_None)
+{}
 
 /************************************************************************/
 /*                           ~BPGDataset()                              */
@@ -179,7 +176,7 @@ BPGDataset::~BPGDataset()
 
 {
     FlushCache();
-    if (fpImage)
+    if( fpImage )
         VSIFCloseL(fpImage);
     VSIFree(pabyUncompressed);
 }
@@ -293,9 +290,7 @@ GDALDataset *BPGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    BPGDataset  *poDS;
-
-    poDS = new BPGDataset();
+    BPGDataset *poDS = new BPGDataset();
     poDS->nRasterXSize = imageInfo.width;
     poDS->nRasterYSize = imageInfo.height;
     poDS->fpImage = poOpenInfo->fpL;
diff --git a/frmts/bsb/GNUmakefile b/frmts/bsb/GNUmakefile
index 971e9ce..6eae96a 100644
--- a/frmts/bsb/GNUmakefile
+++ b/frmts/bsb/GNUmakefile
@@ -21,7 +21,7 @@ bsb2raw$(EXE):	bsb2raw.$(OBJ_EXT)
 
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
 
-dist:	
+dist:
 	rm -rf $(DISTDIR)
 	mkdir $(DISTDIR)
 	cp *.cpp *.c *.h $(DISTDIR)
diff --git a/frmts/bsb/README.dist b/frmts/bsb/README.dist
index c230232..df0292b 100644
--- a/frmts/bsb/README.dist
+++ b/frmts/bsb/README.dist
@@ -16,7 +16,7 @@ Files
  Makefile: Simple Unix style makefile for building bsb2raw program.
 
 NOTE: It may be necessary to fool with the cpl_config.h include file for
-different platforms. In particular, change the #undef WORDS_BIGENDIAN to 
+different platforms. In particular, change the #undef WORDS_BIGENDIAN to
 a #define WORDS_BIGENDIAN for big endian systems (Sparc, SGI, etc).  Some
 changes may be needed in cpl_config.h for Windows.
 
@@ -24,7 +24,7 @@ changes may be needed in cpl_config.h for Windows.
 License
 -------
 
-MIT/X license ... see header of bsb_read.c. 
+MIT/X license ... see header of bsb_read.c.
 
 On the Web
 ----------
@@ -34,7 +34,7 @@ http://gdal.velocet.ca/projects/bsb/
 GDAL
 ----
 
-Note that this BSB code is normally incorporated into the larger GDAL 
+Note that this BSB code is normally incorporated into the larger GDAL
 library.  To convert BSB to other common formats like GeoTIFF, PNG, etc
 consider using the GDAL utilities at:
 
diff --git a/frmts/bsb/bsb2raw.c b/frmts/bsb/bsb2raw.c
index 2d6ff41..a426e97 100644
--- a/frmts/bsb/bsb2raw.c
+++ b/frmts/bsb/bsb2raw.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bsb2raw.c 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: bsb2raw.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  BSB Reader
  * Purpose:  Test program for dumping BSB to PPM raster format.
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "bsb_read.h"
 
-CPL_CVSID("$Id: bsb2raw.c 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: bsb2raw.c 34521 2016-07-02 21:26:43Z goatbar $");
 
 /************************************************************************/
 /*                                main()                                */
diff --git a/frmts/bsb/bsb_read.c b/frmts/bsb/bsb_read.c
index ff1d2aa..02cb303 100644
--- a/frmts/bsb/bsb_read.c
+++ b/frmts/bsb/bsb_read.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bsb_read.c 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: bsb_read.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  BSB Reader
  * Purpose:  Low level BSB Access API Implementation (non-GDAL).
@@ -37,7 +37,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: bsb_read.c 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: bsb_read.c 34521 2016-07-02 21:26:43Z goatbar $");
 
 static int BSBReadHeaderLine( BSBInfo *psInfo, char* pszLine, int nLineMaxLen, int bNO1 );
 static int BSBSeekAndCheckScanlineNumber ( BSBInfo *psInfo, int nScanline,
diff --git a/frmts/bsb/bsb_read.h b/frmts/bsb/bsb_read.h
index 9d1134a..24f55bb 100644
--- a/frmts/bsb/bsb_read.h
+++ b/frmts/bsb/bsb_read.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: bsb_read.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: bsb_read.h 35885 2016-10-24 06:23:09Z goatbar $
  *
  * Project:  BSB Reader
  * Purpose:  non-GDAL BSB API Declarations
@@ -38,14 +38,13 @@ CPL_C_START
 typedef struct {
     VSILFILE   *fp;
 
-
     GByte       *pabyBuffer;
     int         nBufferOffset;
     int         nBufferSize;
     int         nBufferAllocation;
     int         nSavedCharacter;
 
-    int		nXSize;
+    int         nXSize;
     int         nYSize;
 
     int         nPCTSize;
@@ -53,11 +52,11 @@ typedef struct {
 
     char        **papszHeader;
 
-    int		*panLineOffset;
+    int         *panLineOffset;
 
     int         nColorSize;
 
-    int		nVersion; /* times 100 */
+    int         nVersion; /* times 100 */
 
     int         bNO1;
 
diff --git a/frmts/bsb/bsbdataset.cpp b/frmts/bsb/bsbdataset.cpp
index dc20307..3e3d028 100644
--- a/frmts/bsb/bsbdataset.cpp
+++ b/frmts/bsb/bsbdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: bsbdataset.cpp 33936 2016-04-10 13:51:04Z rouault $
  *
  * Project:  BSB Reader
  * Purpose:  BSBDataset implementation for BSB format.
@@ -34,14 +33,17 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: bsbdataset.cpp 33936 2016-04-10 13:51:04Z rouault $");
+#include <cstdlib>
+#include <algorithm>
+
+CPL_CVSID("$Id: bsbdataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 //Disabled as people may worry about the BSB patent
 //#define BSB_CREATE
 
 /************************************************************************/
 /* ==================================================================== */
-/*				BSBDataset				*/
+/*                              BSBDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -64,19 +66,19 @@ class BSBDataset : public GDALPamDataset
 
   public:
                 BSBDataset();
-		~BSBDataset();
+    virtual ~BSBDataset();
 
     BSBInfo     *psInfo;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
-    CPLErr 	GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
 /************************************************************************/
@@ -87,17 +89,16 @@ class BSBDataset : public GDALPamDataset
 
 class BSBRasterBand : public GDALPamRasterBand
 {
-    GDALColorTable	oCT;
+    GDALColorTable      oCT;
 
   public:
-    		BSBRasterBand( BSBDataset * );
+    explicit    BSBRasterBand( BSBDataset * );
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorTable *GetColorTable();
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
-
 /************************************************************************/
 /*                           BSBRasterBand()                            */
 /************************************************************************/
@@ -105,8 +106,8 @@ class BSBRasterBand : public GDALPamRasterBand
 BSBRasterBand::BSBRasterBand( BSBDataset *poDSIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = 1;
+    poDS = poDSIn;
+    nBand = 1;
 
     eDataType = GDT_Byte;
 
@@ -117,12 +118,12 @@ BSBRasterBand::BSBRasterBand( BSBDataset *poDSIn )
     // shifted down.
     for( int i = 0; i < poDSIn->psInfo->nPCTSize-1; i++ )
     {
-        GDALColorEntry  oColor;
-
-        oColor.c1 = poDSIn->psInfo->pabyPCT[i*3+0+3];
-        oColor.c2 = poDSIn->psInfo->pabyPCT[i*3+1+3];
-        oColor.c3 = poDSIn->psInfo->pabyPCT[i*3+2+3];
-        oColor.c4 = 255;
+        GDALColorEntry oColor = {
+            poDSIn->psInfo->pabyPCT[i*3+0+3],
+            poDSIn->psInfo->pabyPCT[i*3+1+3],
+            poDSIn->psInfo->pabyPCT[i*3+2+3],
+            255
+        };
 
         oCT.SetColorEntry( i, &oColor );
     }
@@ -178,7 +179,7 @@ GDALColorInterp BSBRasterBand::GetColorInterpretation()
 
 /************************************************************************/
 /* ==================================================================== */
-/*				BSBDataset				*/
+/*                              BSBDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -189,21 +190,22 @@ GDALColorInterp BSBRasterBand::GetColorInterpretation()
 BSBDataset::BSBDataset() :
     nGCPCount(0),
     pasGCPList(NULL),
-    bGeoTransformSet(FALSE)
+    osGCPProjection(
+        "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\","
+        "SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",7030]],"
+        "TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",6326]],"
+        "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],"
+        "UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],"
+        "AUTHORITY[\"EPSG\",4326]]"),
+    bGeoTransformSet(FALSE),
+    psInfo(NULL)
 {
-    psInfo = NULL;
-
-
-    osGCPProjection =
-        "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",7030]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",6326]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4326]]";
-
     adfGeoTransform[0] = 0.0;     /* X Origin (top left corner) */
     adfGeoTransform[1] = 1.0;     /* X Pixel size */
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;     /* Y Origin (top left corner) */
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;     /* Y Pixel Size */
-
 }
 
 /************************************************************************/
@@ -222,7 +224,6 @@ BSBDataset::~BSBDataset()
         BSBClose( psInfo );
 }
 
-
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
@@ -268,7 +269,10 @@ GDALHeuristicDatelineWrap( int nPointCount, double *padfX )
 /*      (0 to 360).                                                     */
 /* -------------------------------------------------------------------- */
     /* Following inits are useless but keep GCC happy */
-    double dfX_PM_Min = 0, dfX_PM_Max = 0, dfX_Dateline_Min = 0, dfX_Dateline_Max = 0;
+    double dfX_PM_Min = 0.0;
+    double dfX_PM_Max = 0.0;
+    double dfX_Dateline_Min = 0.0;
+    double dfX_Dateline_Max = 0.0;
 
     for( int i = 0; i < nPointCount; i++ )
     {
@@ -282,15 +286,17 @@ GDALHeuristicDatelineWrap( int nPointCount, double *padfX )
 
         if( i == 0 )
         {
-            dfX_PM_Min = dfX_PM_Max = dfX_PM;
-            dfX_Dateline_Min = dfX_Dateline_Max = dfX_Dateline;
+            dfX_PM_Min = dfX_PM;
+            dfX_PM_Max = dfX_PM;
+            dfX_Dateline_Min = dfX_Dateline;
+            dfX_Dateline_Max = dfX_Dateline;
         }
         else
         {
-            dfX_PM_Min = MIN(dfX_PM_Min,dfX_PM);
-            dfX_PM_Max = MAX(dfX_PM_Max,dfX_PM);
-            dfX_Dateline_Min = MIN(dfX_Dateline_Min,dfX_Dateline);
-            dfX_Dateline_Max = MAX(dfX_Dateline_Max,dfX_Dateline);
+            dfX_PM_Min = std::min(dfX_PM_Min, dfX_PM);
+            dfX_PM_Max = std::max(dfX_PM_Max, dfX_PM);
+            dfX_Dateline_Min = std::min(dfX_Dateline_Min, dfX_Dateline);
+            dfX_Dateline_Max = std::max(dfX_Dateline_Max, dfX_Dateline);
         }
     }
 
@@ -321,7 +327,6 @@ GDALHeuristicDatelineWrap( int nPointCount, double *padfX )
     else
         bUsePMWrap = true;
 
-
 /* -------------------------------------------------------------------- */
 /*      Apply rewrapping.                                               */
 /* -------------------------------------------------------------------- */
@@ -388,7 +393,8 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Collect coordinate system related parameters from header.       */
 /* -------------------------------------------------------------------- */
-    const char *pszKNP=NULL, *pszKNQ=NULL;
+    const char *pszKNP=NULL;
+    const char *pszKNQ=NULL;
 
     for( int i = 0; psInfo->papszHeader[i] != NULL; i++ )
     {
@@ -414,14 +420,12 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
     {
         const char *pszPR = strstr(pszKNP,"PR=");
         const char *pszGD = strstr(pszKNP,"GD=");
-        const char *pszValue, *pszEnd = NULL;
         const char *pszGEOGCS = "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4326\"]]";
         CPLString osPP;
 
         // Capture the PP string.
-        pszValue = strstr(pszKNP,"PP=");
-        if( pszValue )
-            pszEnd = strstr(pszValue,",");
+        const char *pszValue = strstr(pszKNP,"PP=");
+        const char *pszEnd = pszValue ? strstr(pszValue,",") : NULL;
         if( pszValue && pszEnd )
             osPP.assign(pszValue+3,pszEnd-pszValue-3);
 
@@ -451,7 +455,7 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
         }
 
         else if( STARTS_WITH_CI(pszPR, "PR=TRANSVERSE MERCATOR")
-                 && osPP.size() > 0 )
+                 && !osPP.empty() )
         {
 
             osUnderlyingSRS.Printf(
@@ -460,7 +464,7 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
         }
 
         else if( STARTS_WITH_CI(pszPR, "PR=UNIVERSAL TRANSVERSE MERCATOR")
-                 && osPP.size() > 0 )
+                 && !osPP.empty() )
         {
             // This is not *really* UTM unless the central meridian
             // matches a zone which it does not in some (most?) maps.
@@ -469,7 +473,7 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
                 pszGEOGCS, osPP.c_str() );
         }
 
-        else if( STARTS_WITH_CI(pszPR, "PR=POLYCONIC") && osPP.size() > 0 )
+        else if( STARTS_WITH_CI(pszPR, "PR=POLYCONIC") && !osPP.empty() )
         {
             osUnderlyingSRS.Printf(
                 "PROJCS[\"unnamed\",%s,PROJECTION[\"Polyconic\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0],PARAMETER[\"false_northing\",0]]",
@@ -477,7 +481,7 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
         }
 
         else if( STARTS_WITH_CI(pszPR, "PR=LAMBERT CONFORMAL CONIC")
-                 && osPP.size() > 0 && pszKNQ != NULL )
+                 && !osPP.empty() && pszKNQ != NULL )
         {
             CPLString osP2, osP3;
 
@@ -500,11 +504,10 @@ void BSBDataset::ScanForGCPs( bool isNos, const char *pszFilename )
                     osP3.assign(pszValue+3);
             }
 
-            if( osP2.size() > 0 && osP3.size() > 0 )
+            if( !osP2.empty() && !osP3.empty() )
                 osUnderlyingSRS.Printf(
                     "PROJCS[\"unnamed\",%s,PROJECTION[\"Lambert_Conformal_Conic_2SP\"],PARAMETER[\"standard_parallel_1\",%s],PARAMETER[\"standard_parallel_2\",%s],PARAMETER[\"latitude_of_origin\",0.0],PARAMETER[\"central_meridian\",%s],PARAMETER[\"false_easting\",0.0],PARAMETER[\"false_northing\",0.0]]",
                     pszGEOGCS, osP2.c_str(), osP3.c_str(), osPP.c_str() );
-
         }
     }
 
@@ -566,7 +569,7 @@ void BSBDataset::ScanForGCPsNos( const char *pszFilename )
     const char *extension = CPLGetExtension(pszFilename);
 
     // pseudointelligently try and guess whether we want a .geo or a .GEO
-    const char *geofile;
+    const char *geofile = NULL;
     if (extension[1] == 'O')
     {
         geofile = CPLResetExtension( pszFilename, "GEO");
@@ -612,7 +615,7 @@ void BSBDataset::ScanForGCPsNos( const char *pszFilename )
                 pasGCPList[nGCPCount].dfGCPLine = CPLAtof(Tokens[3]);
 
                 CPLFree( pasGCPList[nGCPCount].pszId );
-                char	szName[50];
+                char szName[50];
                 snprintf( szName, sizeof(szName), "GCP_%d", nGCPCount+1 );
                 pasGCPList[nGCPCount].pszId = CPLStrdup( szName );
 
@@ -626,7 +629,6 @@ void BSBDataset::ScanForGCPsNos( const char *pszFilename )
     VSIFClose(gfp);
 }
 
-
 /************************************************************************/
 /*                            ScanForGCPsBSB()                          */
 /************************************************************************/
@@ -636,7 +638,7 @@ void BSBDataset::ScanForGCPsBSB()
 /* -------------------------------------------------------------------- */
 /*      Collect standalone GCPs.  They look like:                       */
 /*                                                                      */
-/*      REF/1,115,2727,32.346666666667,-60.881666666667			*/
+/*      REF/1,115,2727,32.346666666667,-60.881666666667                 */
 /*      REF/n,pixel,line,lat,long                                       */
 /* -------------------------------------------------------------------- */
     int fileGCPCount=0;
@@ -655,7 +657,7 @@ void BSBDataset::ScanForGCPsBSB()
         if( !STARTS_WITH_CI(psInfo->papszHeader[i], "REF/") )
             continue;
 
-        char	**papszTokens
+        char **papszTokens
             = CSLTokenizeStringComplex( psInfo->papszHeader[i]+4, ",",
                                         FALSE, FALSE );
 
@@ -800,7 +802,7 @@ GDALDataset *BSBDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -914,7 +916,7 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Prepare initial color table.colortable.                         */
 /* -------------------------------------------------------------------- */
-    GDALRasterBand	*poBand = poSrcDS->GetRasterBand(1);
+    GDALRasterBand      *poBand = poSrcDS->GetRasterBand(1);
     unsigned char       abyPCT[771];
     int                 nPCTSize;
     int                 anRemap[256];
@@ -939,14 +941,14 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
     else
     {
-        GDALColorTable	*poCT = poBand->GetColorTable();
+        GDALColorTable *poCT = poBand->GetColorTable();
         int nColorTableSize = poCT->GetColorEntryCount();
         if (nColorTableSize > 255)
             nColorTableSize = 255;
 
         for( int iColor = 0; iColor < nColorTableSize; iColor++ )
         {
-            GDALColorEntry	sEntry;
+            GDALColorEntry sEntry;
 
             poCT->GetColorEntryAsRGB( iColor, &sEntry );
 
@@ -1007,7 +1009,8 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     while( nPCTSize > 128 )
     {
         int nBestRange = 768;
-        int iBestMatch1=-1, iBestMatch2=-1;
+        int iBestMatch1 = -1;
+        int iBestMatch2 = -1;
 
         // Find the closest pair of color table entries.
 
@@ -1015,9 +1018,9 @@ BSBCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         {
             for( int j = i+1; j < nPCTSize; j++ )
             {
-                int nRange = ABS(abyPCT[i*3+0] - abyPCT[j*3+0])
-                    + ABS(abyPCT[i*3+1] - abyPCT[j*3+1])
-                    + ABS(abyPCT[i*3+2] - abyPCT[j*3+2]);
+                int nRange = std::abs(abyPCT[i*3+0] - abyPCT[j*3+0])
+                    + std::abs(abyPCT[i*3+1] - abyPCT[j*3+1])
+                    + std::abs(abyPCT[i*3+2] - abyPCT[j*3+2]);
 
                 if( nRange < nBestRange )
                 {
diff --git a/frmts/cals/calsdataset.cpp b/frmts/cals/calsdataset.cpp
index b4321a6..852efe6 100644
--- a/frmts/cals/calsdataset.cpp
+++ b/frmts/cals/calsdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: calsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  CALS driver
  * Purpose:  CALS driver
@@ -33,7 +32,7 @@
 
 #include "tiff.h"
 
-CPL_CVSID("$Id: calsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: calsdataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -49,23 +48,23 @@ class CALSDataset : public GDALPamDataset
     CPLString    osSparseFilename;
     GDALDataset* poUnderlyingDS;
 
-    static void WriteLEInt16(VSILFILE* fp, GInt16 nVal);
-    static void WriteLEInt32(VSILFILE* fp, GInt32 nVal);
-    static void WriteTIFFTAG(VSILFILE* fp, GInt16 nTagName, GInt16 nTagType,
-                             GInt32 nTagValue);
+    static void WriteLEInt16( VSILFILE* fp, GInt16 nVal );
+    static void WriteLEInt32( VSILFILE* fp, GInt32 nVal );
+    static void WriteTIFFTAG( VSILFILE* fp, GInt16 nTagName, GInt16 nTagType,
+                              GInt32 nTagValue );
 
   public:
-                CALSDataset();
+                 CALSDataset() : poUnderlyingDS(NULL) {}
                 ~CALSDataset();
 
     static int          Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *CreateCopy( const char *pszFilename,
-                                           GDALDataset *poSrcDS,
-                                           int bStrict,
-                                           char **papszOptions,
-                                           GDALProgressFunc pfnProgress,
-                                           void *pProgressData );
+                                    GDALDataset *poSrcDS,
+                                    int bStrict,
+                                    char **papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void *pProgressData );
 };
 
 /************************************************************************/
@@ -79,50 +78,50 @@ class CALSRasterBand: public GDALPamRasterBand
     GDALRasterBand* poUnderlyingBand;
 
   public:
-    CALSRasterBand(CALSDataset* poDSIn)
+    explicit CALSRasterBand( CALSDataset* poDSIn )
     {
-        this->poDS = poDSIn;
+        poDS = poDSIn;
         poUnderlyingBand = poDSIn->poUnderlyingDS->GetRasterBand(1);
         poUnderlyingBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
         nBand = 1;
         eDataType = GDT_Byte;
     }
 
-    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void * pData )
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void * pData ) override
     {
         return poUnderlyingBand->ReadBlock(nBlockXOff, nBlockYOff, pData);
     }
 
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
-                                int nXOff, int nYOff, int nXSize, int nYSize,
-                                void * pData, int nBufXSize, int nBufYSize,
-                                GDALDataType eBufType,
-                                GSpacing nPixelSpace,
-                                GSpacing nLineSpace,
-                                GDALRasterIOExtraArg* psExtraArg )
+                              int nXOff, int nYOff, int nXSize, int nYSize,
+                              void * pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
+                              GSpacing nPixelSpace,
+                              GSpacing nLineSpace,
+                              GDALRasterIOExtraArg* psExtraArg ) override
     {
         return poUnderlyingBand->RasterIO(
-                    eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                    pData, nBufXSize, nBufYSize, eBufType,
-                    nPixelSpace, nLineSpace, psExtraArg ) ;
+            eRWFlag, nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize, eBufType,
+            nPixelSpace, nLineSpace, psExtraArg ) ;
     }
 
-    virtual GDALColorTable* GetColorTable()
+    virtual GDALColorTable* GetColorTable() override
     {
         return poUnderlyingBand->GetColorTable();
     }
 
-    virtual GDALColorInterp GetColorInterpretation()
+    virtual GDALColorInterp GetColorInterpretation() override
     {
         return GCI_PaletteIndex;
     }
 
-    virtual char** GetMetadata(const char* pszDomain)
+    virtual char** GetMetadata(const char* pszDomain) override
     {
         return poUnderlyingBand->GetMetadata(pszDomain);
     }
 
-    virtual const char* GetMetadataItem(const char* pszKey, const char* pszDomain)
+    virtual const char* GetMetadataItem(const char* pszKey, const char* pszDomain) override
     {
         return poUnderlyingBand->GetMetadataItem(pszKey, pszDomain);
     }
@@ -137,61 +136,66 @@ class CALSRasterBand: public GDALPamRasterBand
 class CALSWrapperSrcBand: public GDALPamRasterBand
 {
         GDALDataset* poSrcDS;
-        int bInvertValues;
+        bool bInvertValues;
 
     public:
-        CALSWrapperSrcBand(GDALDataset* poSrcDSIn)
+        explicit CALSWrapperSrcBand( GDALDataset* poSrcDSIn )
         {
-            this->poSrcDS = poSrcDSIn;
+            poSrcDS = poSrcDSIn;
             SetMetadataItem("NBITS", "1", "IMAGE_STRUCTURE");
             poSrcDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
             eDataType = GDT_Byte;
-            bInvertValues = TRUE;
+            bInvertValues = true;
             GDALColorTable* poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
             if( poCT != NULL && poCT->GetColorEntryCount() >= 2 )
             {
                 const GDALColorEntry* psEntry1 = poCT->GetColorEntry(0);
                 const GDALColorEntry* psEntry2 = poCT->GetColorEntry(1);
-                if( psEntry1->c1 == 255 && psEntry1->c2 == 255 && psEntry1->c3 == 255 &&
-                    psEntry2->c1 == 0 && psEntry2->c2 == 0 && psEntry2->c3 == 0 )
+                if( psEntry1->c1 == 255 &&
+                    psEntry1->c2 == 255 &&
+                    psEntry1->c3 == 255 &&
+                    psEntry2->c1 == 0 &&
+                    psEntry2->c2 == 0 &&
+                    psEntry2->c3 == 0 )
                 {
-                    bInvertValues = FALSE;
+                    bInvertValues = false;
                 }
             }
         }
 
-        virtual CPLErr IReadBlock( CPL_UNUSED int nBlockXOff,
-                                   CPL_UNUSED int nBlockYOff,
-                                   CPL_UNUSED void * pData )
+        virtual CPLErr IReadBlock( int /* nBlockXOff */,
+                                   int /* nBlockYOff */,
+                                   void * /* pData */ ) override
         {
-            // Should not be called
+            // Should not be called.
             return CE_Failure;
         }
 
         virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
-                                    int nXOff, int nYOff, int nXSize, int nYSize,
-                                    void * pData, int nBufXSize, int nBufYSize,
-                                    GDALDataType eBufType,
-                                    GSpacing nPixelSpace,
-                                    GSpacing nLineSpace,
-                                    GDALRasterIOExtraArg* psExtraArg )
+                                  int nXOff, int nYOff, int nXSize, int nYSize,
+                                  void * pData, int nBufXSize, int nBufYSize,
+                                  GDALDataType eBufType,
+                                  GSpacing nPixelSpace,
+                                  GSpacing nLineSpace,
+                                  GDALRasterIOExtraArg* psExtraArg ) override
         {
-            CPLErr eErr = poSrcDS->GetRasterBand(1)->RasterIO(
-                        eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                        pData, nBufXSize, nBufYSize, eBufType,
-                        nPixelSpace, nLineSpace, psExtraArg ) ;
+            const CPLErr eErr =
+                poSrcDS->GetRasterBand(1)->RasterIO(
+                    eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                    pData, nBufXSize, nBufYSize, eBufType,
+                    nPixelSpace, nLineSpace, psExtraArg ) ;
             if( bInvertValues )
             {
-                for(int j=0;j<nBufYSize;j++)
+                for( int j = 0; j < nBufYSize; j++ )
                 {
-                    for(int i=0;i<nBufXSize;i++)
+                    for( int i = 0; i < nBufXSize; i++ )
                         ((GByte*)pData)[j * nLineSpace + i * nPixelSpace] =
-                            1 - ((GByte*)pData)[j * nLineSpace + i * nPixelSpace];
+                            1 - ((GByte*)pData)[j * nLineSpace +
+                                                i * nPixelSpace];
                 }
             }
             return eErr;
         }
-
 };
 
 /************************************************************************/
@@ -203,7 +207,7 @@ class CALSWrapperSrcBand: public GDALPamRasterBand
 class CALSWrapperSrcDataset: public GDALPamDataset
 {
     public:
-        CALSWrapperSrcDataset(GDALDataset* poSrcDS, const char* pszPadding)
+        CALSWrapperSrcDataset( GDALDataset* poSrcDS, const char* pszPadding )
         {
             nRasterXSize = poSrcDS->GetRasterXSize();
             nRasterYSize = poSrcDS->GetRasterYSize();
@@ -212,7 +216,6 @@ class CALSWrapperSrcDataset: public GDALPamDataset
         }
 };
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                            CALSDataset                               */
@@ -220,15 +223,6 @@ class CALSWrapperSrcDataset: public GDALPamDataset
 /************************************************************************/
 
 /************************************************************************/
-/*                           CALSDataset()                              */
-/************************************************************************/
-
-CALSDataset::CALSDataset()
-{
-    poUnderlyingDS = NULL;
-}
-
-/************************************************************************/
 /*                            ~CALSDataset()                            */
 /************************************************************************/
 
@@ -236,9 +230,9 @@ CALSDataset::~CALSDataset()
 
 {
     delete poUnderlyingDS;
-    if( osTIFFHeaderFilename.size() )
+    if( !osTIFFHeaderFilename.empty() )
         VSIUnlink(osTIFFHeaderFilename);
-    if( osSparseFilename.size() )
+    if( !osSparseFilename.empty() )
         VSIUnlink(osSparseFilename);
 }
 
@@ -269,9 +263,9 @@ int CALSDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                           WriteLEInt16()                             */
 /************************************************************************/
 
-void CALSDataset::WriteLEInt16(VSILFILE* fp, GInt16 nVal)
+void CALSDataset::WriteLEInt16( VSILFILE* fp, GInt16 nVal )
 {
-    nVal = CPL_LSBWORD16(nVal);
+    CPL_LSBPTR16(&nVal);
     VSIFWriteL(&nVal, 1, 2, fp);
 }
 
@@ -279,9 +273,9 @@ void CALSDataset::WriteLEInt16(VSILFILE* fp, GInt16 nVal)
 /*                            WriteLEInt32()                            */
 /************************************************************************/
 
-void CALSDataset::WriteLEInt32(VSILFILE* fp, GInt32 nVal)
+void CALSDataset::WriteLEInt32( VSILFILE* fp, GInt32 nVal )
 {
-    nVal = CPL_LSBWORD32(nVal);
+    CPL_LSBPTR32(&nVal);
     VSIFWriteL(&nVal, 1, 4, fp);
 }
 
@@ -289,8 +283,8 @@ void CALSDataset::WriteLEInt32(VSILFILE* fp, GInt32 nVal)
 /*                            WriteTIFFTAG()                            */
 /************************************************************************/
 
-void CALSDataset::WriteTIFFTAG(VSILFILE* fp, GInt16 nTagName, GInt16 nTagType,
-                               GInt32 nTagValue)
+void CALSDataset::WriteTIFFTAG( VSILFILE* fp, GInt16 nTagName, GInt16 nTagType,
+                                GInt32 nTagValue )
 {
     WriteLEInt16(fp, nTagName);
     WriteLEInt16(fp, nTagType);
@@ -308,24 +302,28 @@ GDALDataset *CALSDataset::Open( GDALOpenInfo * poOpenInfo )
     if (!Identify(poOpenInfo) || poOpenInfo->fpL == NULL )
         return NULL;
 
-    const char* pszRPelCnt = strstr((const char*) poOpenInfo->pabyHeader, "rpelcnt:");
-    int nXSize, nYSize;
+    const char* pszRPelCnt =
+        strstr((const char*) poOpenInfo->pabyHeader, "rpelcnt:");
+    int nXSize = 0;
+    int nYSize = 0;
     if( sscanf(pszRPelCnt+strlen("rpelcnt:"),"%d,%d",&nXSize,&nYSize) != 2 ||
         nXSize <= 0 || nYSize <= 0 )
         return NULL;
 
-    const char* pszOrient = strstr((const char*) poOpenInfo->pabyHeader, "rorient:");
+    const char* pszOrient =
+        strstr((const char*) poOpenInfo->pabyHeader, "rorient:");
     int nAngle1, nAngle2;
     if( sscanf(pszOrient+strlen("rorient:"),"%d,%d",&nAngle1,&nAngle2) != 2 )
         return NULL;
 
-    const char* pszDensity = strstr((const char*) poOpenInfo->pabyHeader, "rdensty:");
+    const char* pszDensity =
+        strstr((const char*) poOpenInfo->pabyHeader, "rdensty:");
     int nDensity = 0;
     if( pszDensity )
         sscanf(pszDensity+strlen("rdensty:"), "%d", &nDensity);
 
     VSIFSeekL(poOpenInfo->fpL, 0, SEEK_END);
-    int nFAX4BlobSize = (int)VSIFTellL(poOpenInfo->fpL) - 2048;
+    int nFAX4BlobSize = static_cast<int>(VSIFTellL(poOpenInfo->fpL)) - 2048;
     if( nFAX4BlobSize < 0 )
         return NULL;
 
@@ -333,17 +331,17 @@ GDALDataset *CALSDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
 
-    // Create a TIFF header for a single-strip CCITTFAX4 file
+    // Create a TIFF header for a single-strip CCITTFAX4 file.
     poDS->osTIFFHeaderFilename = CPLSPrintf("/vsimem/cals/header_%p.tiff", poDS);
     VSILFILE* fp = VSIFOpenL(poDS->osTIFFHeaderFilename, "wb");
     const int nTagCount = 10;
     const int nHeaderSize = 4 + 4 + 2 + nTagCount * 12 + 4;
-    WriteLEInt16(fp, TIFF_LITTLEENDIAN); /* TIFF little-endian signature */
-    WriteLEInt16(fp, 42); // TIFF classic
+    WriteLEInt16(fp, TIFF_LITTLEENDIAN);  // TIFF little-endian signature.
+    WriteLEInt16(fp, 42);  // TIFF classic.
 
-    WriteLEInt32(fp, 8);  /* Offset of IFD0 */
+    WriteLEInt32(fp, 8);  // Offset of IFD0.
 
-    WriteLEInt16(fp, nTagCount); /* Number of entries */
+    WriteLEInt16(fp, nTagCount);  // Number of entries.
 
     WriteTIFFTAG(fp, TIFFTAG_IMAGEWIDTH, TIFF_LONG, nXSize);
     WriteTIFFTAG(fp, TIFFTAG_IMAGELENGTH, TIFF_LONG, nYSize);
@@ -356,12 +354,12 @@ GDALDataset *CALSDataset::Open( GDALOpenInfo * poOpenInfo )
     WriteTIFFTAG(fp, TIFFTAG_STRIPBYTECOUNTS, TIFF_LONG, nFAX4BlobSize);
     WriteTIFFTAG(fp, TIFFTAG_PLANARCONFIG, TIFF_SHORT, PLANARCONFIG_CONTIG);
 
-    WriteLEInt32(fp, 0);  /* Offset of next IFD */
+    WriteLEInt32(fp, 0);  // Offset of next IFD.
 
     VSIFCloseL(fp);
 
     // Create a /vsisparse/ description file assembling the TIFF header
-    // with the FAX4 codestream that starts at offset 2048 of the CALS file
+    // with the FAX4 codestream that starts at offset 2048 of the CALS file.
     poDS->osSparseFilename = CPLSPrintf("/vsimem/cals/sparse_%p.xml", poDS);
     fp = VSIFOpenL(poDS->osSparseFilename, "wb");
     CPLAssert(fp);
@@ -425,7 +423,7 @@ GDALDataset *CALSDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
                                  poOpenInfo->GetSiblingFiles() );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -446,10 +444,12 @@ GDALDataset *CALSDataset::CreateCopy( const char *pszFilename,
                   "CALS driver only supports single band raster.");
         return NULL;
     }
-    if( poSrcDS->GetRasterBand(1)->GetMetadataItem("NBITS", "IMAGE_STRUCTURE") == NULL ||
-        !EQUAL(poSrcDS->GetRasterBand(1)->GetMetadataItem("NBITS", "IMAGE_STRUCTURE"), "1") )
+    if( poSrcDS->GetRasterBand(1)->
+            GetMetadataItem("NBITS", "IMAGE_STRUCTURE") == NULL ||
+        !EQUAL(poSrcDS->GetRasterBand(1)->
+                   GetMetadataItem("NBITS", "IMAGE_STRUCTURE"), "1") )
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
+        CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_NotSupported,
                   "CALS driver only supports 1-bit.");
         if( bStrict )
             return NULL;
@@ -458,21 +458,23 @@ GDALDataset *CALSDataset::CreateCopy( const char *pszFilename,
     if( poSrcDS->GetRasterXSize() > 999999 ||
         poSrcDS->GetRasterYSize() > 999999 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "CALS driver only supports datasets with dimension <= 999999.");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "CALS driver only supports datasets with dimension <= 999999.");
         return NULL;
     }
 
-    GDALDriver* poGTiffDrv = (GDALDriver*)GDALGetDriverByName("GTiff");
+    GDALDriver* poGTiffDrv =
+        static_cast<GDALDriver *>(GDALGetDriverByName("GTiff"));
     if( poGTiffDrv == NULL )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "CALS driver needs GTiff driver.");
+                  "CALS driver needs GTiff driver." );
         return NULL;
     }
 
-    /* Write a in-memory TIFF with just the TIFF header to figure out */
-    /* how large it will be */
+    // Write a in-memory TIFF with just the TIFF header to figure out
+    // how large it will be.
     CPLString osTmpFilename(CPLSPrintf("/vsimem/cals/tmp_%p", poSrcDS));
     char** papszOptions = NULL;
     papszOptions = CSLSetNameValue(papszOptions, "COMPRESS", "CCITTFAX4");
@@ -487,29 +489,28 @@ GDALDataset *CALSDataset::CreateCopy( const char *pszFilename,
                                            papszOptions);
     if( poDS == NULL )
     {
-        // Should not happen normally (except if CCITTFAX4 not available)
+        // Should not happen normally (except if CCITTFAX4 not available).
         CSLDestroy(papszOptions);
         return NULL;
     }
     const char INITIAL_PADDING[] = "12345";
-    poDS->SetMetadataItem("TIFFTAG_DOCUMENTNAME", INITIAL_PADDING); // to adjust padding
+     // To adjust padding.
+    poDS->SetMetadataItem("TIFFTAG_DOCUMENTNAME", INITIAL_PADDING);
     GDALClose(poDS);
     VSIStatBufL sStat;
     if( VSIStatL(osTmpFilename, &sStat) != 0 )
     {
-        // Shoudln't happen really... Just to make Coverity happy
+        // Shoudln't happen really. Just to make Coverity happy.
         CSLDestroy(papszOptions);
         return NULL;
     }
     int nTIFFHeaderSize = static_cast<int>(sStat.st_size);
     VSIUnlink(osTmpFilename);
 
-
-    /* Redo the same thing, but this time write it to the output file */
-    /* and use a variable TIFF tag (TIFFTAG_DOCUMENTNAME) to enlarge the */
-    /* header + the variable TIFF tag so that they are 2048 bytes large */
-    char szBuffer[2048+1];
-    szBuffer[2048] = 0;
+    // Redo the same thing, but this time write it to the output file
+    // and use a variable TIFF tag (TIFFTAG_DOCUMENTNAME) to enlarge the
+    // header + the variable TIFF tag so that they are 2048 bytes large.
+    char szBuffer[2048+1] = {};
     memset(szBuffer, 'X', 2048 - nTIFFHeaderSize + strlen(INITIAL_PADDING));
     szBuffer[2048 - nTIFFHeaderSize + strlen(INITIAL_PADDING)] = 0;
     GDALDataset* poTmpDS = new CALSWrapperSrcDataset(poSrcDS, szBuffer);
@@ -521,13 +522,14 @@ GDALDataset *CALSDataset::CreateCopy( const char *pszFilename,
         return NULL;
     delete poDS;
 
-    // Now replace the TIFF header by the CALS header !
+    // Now replace the TIFF header by the CALS header.
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb+");
     if( fp == NULL )
-        return NULL; // Shoudln't happen normally
+        return NULL; // Shoudln't happen normally.
     memset(szBuffer, ' ', 2048);
     CPLString osField;
     osField = "srcdocid: NONE";
+    // cppcheck-suppress redundantCopy
     memcpy(szBuffer, osField, osField.size());
 
     osField = "dstdocid: NONE";
@@ -548,7 +550,8 @@ GDALDataset *CALSDataset::CreateCopy( const char *pszFilename,
     osField = "rtype: 1";
     memcpy(szBuffer + 128*6, osField, osField.size());
 
-    int nAngle1 = 0, nAngle2 = 270;
+    int nAngle1 = 0;
+    int nAngle2 = 270;
     const char* pszPixelPath = poSrcDS->GetMetadataItem("PIXEL_PATH");
     const char* pszLineProgression = poSrcDS->GetMetadataItem("LINE_PROGRESSION");
     if( pszPixelPath && pszLineProgression )
diff --git a/frmts/ceos/ceosdataset.cpp b/frmts/ceos/ceosdataset.cpp
index 5dffe76..e4fcdb9 100644
--- a/frmts/ceos/ceosdataset.cpp
+++ b/frmts/ceos/ceosdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ceosdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  CEOS Translator
  * Purpose:  GDALDataset driver for CEOS translator.
@@ -32,11 +31,11 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: ceosdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: ceosdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*				CEOSDataset				*/
+/*                              CEOSDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -46,7 +45,7 @@ class CEOSDataset : public GDALPamDataset
 {
     friend class CEOSRasterBand;
 
-    CEOSImage	*psCEOS;
+    CEOSImage   *psCEOS;
 
   public:
                  CEOSDataset();
@@ -66,12 +65,11 @@ class CEOSRasterBand : public GDALPamRasterBand
 
   public:
 
-    		CEOSRasterBand( CEOSDataset *, int );
+                CEOSRasterBand( CEOSDataset *, int );
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                           CEOSRasterBand()                            */
 /************************************************************************/
@@ -79,8 +77,8 @@ class CEOSRasterBand : public GDALPamRasterBand
 CEOSRasterBand::CEOSRasterBand( CEOSDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Byte;
 
@@ -96,11 +94,11 @@ CPLErr CEOSRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                    int nBlockYOff,
                                    void * pImage )
 {
-    CEOSDataset	*poCEOS_DS = (CEOSDataset *) poDS;
+    CEOSDataset *poCEOS_DS = (CEOSDataset *) poDS;
 
     CPLAssert( nBlockXOff == 0 );
 
-    return( CEOSReadScanline(poCEOS_DS->psCEOS, nBand, nBlockYOff+1, pImage) );
+    return CEOSReadScanline(poCEOS_DS->psCEOS, nBand, nBlockYOff+1, pImage);
 }
 
 /************************************************************************/
@@ -113,11 +111,9 @@ CPLErr CEOSRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                            CEOSDataset()                             */
 /************************************************************************/
 
-CEOSDataset::CEOSDataset()
-
-{
-    psCEOS = NULL;
-}
+CEOSDataset::CEOSDataset() :
+    psCEOS(NULL)
+{}
 
 /************************************************************************/
 /*                            ~CEOSDataset()                            */
@@ -156,7 +152,7 @@ GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     CEOSImage *psCEOS = CEOSOpen( poOpenInfo->pszFilename, "rb" );
     if( psCEOS == NULL )
-        return( NULL );
+        return NULL;
 
     if( psCEOS->nBitsPerPixel != 8 )
     {
@@ -201,7 +197,7 @@ GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    poDS->nBands = psCEOS->nBands;;
+    poDS->nBands = psCEOS->nBands;
 
     for( int i = 0; i < poDS->nBands; i++ )
         poDS->SetBand( i+1, new CEOSRasterBand( poDS, i+1 ) );
@@ -217,7 +213,7 @@ GDALDataset *CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/ceos/ceosopen.c b/frmts/ceos/ceosopen.c
index e5d4135..7e6670b 100644
--- a/frmts/ceos/ceosopen.c
+++ b/frmts/ceos/ceosopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosopen.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: ceosopen.c 36380 2016-11-21 10:21:20Z rouault $
  *
  * Project:  CEOS Translator
  * Purpose:  Implementation of non-GDAL dependent CEOS support.
@@ -30,7 +30,7 @@
 
 #include "ceosopen.h"
 
-CPL_CVSID("$Id: ceosopen.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: ceosopen.c 36380 2016-11-21 10:21:20Z rouault $");
 
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
@@ -44,7 +44,7 @@ CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 static int CEOSScanInt( const char * pszString, int nMaxChars )
 
 {
-    char	szWorking[33];
+    char	szWorking[33] = { 0 };
     int		i;
 
     if( nMaxChars > 32 || nMaxChars == 0 )
diff --git a/frmts/ceos/ceosopen.h b/frmts/ceos/ceosopen.h
index 0aacce3..7b340e3 100644
--- a/frmts/ceos/ceosopen.h
+++ b/frmts/ceos/ceosopen.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosopen.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ceosopen.h 35885 2016-10-24 06:23:09Z goatbar $
  *
  * Project:  CEOS Translator
  * Purpose:  Public (C callable) interface for CEOS and related formats such
@@ -44,17 +44,16 @@
 CPL_C_START
 
 typedef struct {
-    int		nRecordNum;
-    GUInt32	nRecordType;
-    int		nLength;
+    int         nRecordNum;
+    GUInt32     nRecordType;
+    int         nLength;
 
-    char	*pachData;
+    char        *pachData;
 }CEOSRecord;
 
 /* well known record types */
-#define CRT_IMAGE_FDR	0x3FC01212
-#define CRT_IMAGE_DATA	0xEDED1212
-
+#define CRT_IMAGE_FDR   0x3FC01212
+#define CRT_IMAGE_DATA  0xEDED1212
 
 /* -------------------------------------------------------------------- */
 /*      Main CEOS info structure.                                       */
@@ -63,25 +62,25 @@ typedef struct {
 typedef struct {
 
     /* public information */
-    int		nPixels;
-    int		nLines;
-    int		nBands;
+    int         nPixels;
+    int         nLines;
+    int         nBands;
 
-    int		nBitsPerPixel;
+    int         nBitsPerPixel;
 
     /* private information */
-    VSILFILE	*fpImage;
+    VSILFILE    *fpImage;
 
     int         bLittleEndian;
 
-    int		nImageRecCount;
-    int		nImageRecLength;
+    int         nImageRecCount;
+    int         nImageRecLength;
 
-    int		nPrefixBytes;
-    int		nSuffixBytes;
+    int         nPrefixBytes;
+    int         nSuffixBytes;
 
-    int		*panDataStart;
-    int		nLineOffset;
+    int         *panDataStart;
+    int         nLineOffset;
 
 } CEOSImage;
 
@@ -90,7 +89,7 @@ typedef struct {
 /* -------------------------------------------------------------------- */
 
 CEOSImage CPL_ODLL *CEOSOpen( const char *, const char * );
-void CPL_ODLL 	    CEOSClose( CEOSImage * );
+void CPL_ODLL       CEOSClose( CEOSImage * );
 CPLErr CPL_ODLL     CEOSReadScanline( CEOSImage *psImage, int nBand,
                                       int nScanline, void * pData );
 
@@ -98,11 +97,9 @@ CPLErr CPL_ODLL     CEOSReadScanline( CEOSImage *psImage, int nBand,
 /*      Internal prototypes.                                            */
 /* -------------------------------------------------------------------- */
 CEOSRecord CPL_ODLL *CEOSReadRecord( CEOSImage * );
-void CPL_ODLL	     CEOSDestroyRecord( CEOSRecord * );
+void CPL_ODLL        CEOSDestroyRecord( CEOSRecord * );
 
 CPL_C_END
 
 #endif /* ndef CEOSOPEN_H_INCLUDED */
 
-
-
diff --git a/frmts/ceos/ceostest.c b/frmts/ceos/ceostest.c
index fb0d644..fce7d29 100644
--- a/frmts/ceos/ceostest.c
+++ b/frmts/ceos/ceostest.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceostest.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: ceostest.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  CEOS Translator
  * Purpose:  Test mainline.
diff --git a/frmts/ceos2/ceos.c b/frmts/ceos2/ceos.c
index a6179c8..dc375f4 100644
--- a/frmts/ceos2/ceos.c
+++ b/frmts/ceos2/ceos.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceos.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: ceos.c 37040 2016-12-30 15:31:43Z rouault $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  Core CEOS functions.
@@ -29,7 +29,7 @@
 
 #include "ceos.h"
 
-CPL_CVSID("$Id: ceos.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: ceos.c 37040 2016-12-30 15:31:43Z rouault $");
 
 /* Function implementations of functions described in ceos.h */
 
@@ -48,7 +48,7 @@ void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence, CeosTypeCode_t ty
 
 	/* Setup values inside the CeosRecord_t header */
 	record->Sequence = sequence;
-	record->Flavour = 0;
+	record->Flavor = 0;
 	record->FileId = 0;
 	record->TypeCode = typecode;
 	record->Subsequence = 0;
@@ -227,7 +227,7 @@ void SetCeosField(CeosRecord_t *record, int32 start_byte, char *format, void *va
 {
     int field_size;
     char * temp_buf = NULL;
-    char printf_format[ 20 ];
+    char szPrintfFormat[ 20 ];
 
     field_size = 0;
     sscanf(&format[1], "%d", &field_size);
@@ -263,22 +263,22 @@ void SetCeosField(CeosRecord_t *record, int32 start_byte, char *format, void *va
     case 'i':
     case 'I':
 	/* Integer data type */
-	snprintf( printf_format, sizeof(printf_format), "%%%s%c",format+1, 'd');
-	snprintf( temp_buf, field_size+1, printf_format, *(int *) value);
+	snprintf( szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c",format+1, 'd');
+	snprintf( temp_buf, field_size+1, szPrintfFormat, *(int *) value);
 	break;
 
     case 'f':
     case 'F':
 	/* Double precision floating point data type */
-	snprintf( printf_format, sizeof(printf_format), "%%%s%c", format+1, 'g');
-	snprintf( temp_buf, field_size+1, printf_format, *(double *)value);
+	snprintf( szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c", format+1, 'g');
+	snprintf( temp_buf, field_size+1, szPrintfFormat, *(double *)value);
 	break;
 
     case 'e':
     case 'E':
 	/* Double precision floating point data type (forced exponent) */
-	snprintf( printf_format, sizeof(printf_format), "%%%s%c", format+1, 'e');
-	snprintf( temp_buf, field_size+1, printf_format, *(double *)value);
+	snprintf( szPrintfFormat, sizeof(szPrintfFormat), "%%%s%c", format+1, 'e');
+	snprintf( temp_buf, field_size+1, szPrintfFormat, *(double *)value);
 	break;
 
     case 'a':
@@ -307,7 +307,7 @@ void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length, int32
     SetCeosField(record,start_byte,total_len,&integer_value);
 }
 
-CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode, int32 fileid, int32 flavour, int32 subsequence)
+CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode, int32 fileid, int32 flavor, int32 subsequence)
 {
     Link_t *Link;
     CeosRecord_t *record;
@@ -318,7 +318,7 @@ CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode, int32
 
 	if( (record->TypeCode.Int32Code == typecode.Int32Code)
 	    && ( ( fileid == -1 ) || ( record->FileId == fileid  ) )
-	    && ( ( flavour == -1 ) || ( record->Flavour == flavour ) )
+	    && ( ( flavor == -1 ) || ( record->Flavor == flavor ) )
 	    && ( ( subsequence == -1 ) || ( record->Subsequence == subsequence ) ) )
 	    return record;
     }
diff --git a/frmts/ceos2/ceos.h b/frmts/ceos2/ceos.h
index 66f3ec8..a3aefeb 100644
--- a/frmts/ceos2/ceos.h
+++ b/frmts/ceos2/ceos.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceos.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: ceos.h 37040 2016-12-30 15:31:43Z rouault $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  CEOS library prototypes
@@ -27,7 +27,6 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
 #ifndef CEOS_H
 #define CEOS_H
 
@@ -41,8 +40,8 @@ CPL_C_START
 
 typedef struct Link_t_struct
 {
-  struct Link_t_struct	*next;
-  void		*object;
+  struct Link_t_struct *next;
+  void          *object;
 } Link_t;
 
 #define HMalloc CPLMalloc
@@ -142,7 +141,6 @@ Link_t *AddLink( Link_t *psList, Link_t *psLink );
 #define CEOS_RADAR_FLIP_DATE 19980101
 #define CEOS_RADAR_FACILITY "CDPF-RSAT"
 
-
 typedef union
 {
     int32          Int32Code;
@@ -160,7 +158,7 @@ typedef struct
     int32          Sequence;
     CeosTypeCode_t TypeCode;
     int32          Length;
-    int32          Flavour;
+    int32          Flavor;
     int32          Subsequence;
     int32          FileId;
     uchar *        Buffer;
@@ -192,7 +190,7 @@ struct CeosSARImageDesc
 
 typedef struct
 {
-    int32          Flavour;
+    int32          Flavor;
     int32          Sensor;
     int32          ProductType;
     int32          FileNamingConvention;
@@ -222,13 +220,11 @@ typedef struct
     int            Type;
 } CeosRecipeType_t;
 
-
 typedef struct
 {
     CeosRecipeType_t *Recipe;
 } CeosSARImageDescRecipe_t;
 
-
 typedef struct
 {
     int32     ValidFields;
@@ -256,7 +252,6 @@ typedef struct
     TBool PossiblyFlipped;
 } CeosRadarCalibration_t;
 
-
 /* Function prototypes */
 
 void InitEmptyCeosRecord(CeosRecord_t *record, int32 sequence, CeosTypeCode_t typecode, int32 length);
@@ -279,7 +274,7 @@ void SetCeosField(CeosRecord_t *record, int32 start_byte, char *format, void *va
 
 void SetIntCeosField(CeosRecord_t *record, int32 start_byte, int32 length, int32 value);
 
-CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode, int32 fileid, int32 flavour, int32 subsequence);
+CeosRecord_t *FindCeosRecord(Link_t *record_list, CeosTypeCode_t typecode, int32 fileid, int32 flavor, int32 subsequence);
 
 void SerializeCeosRecordsToFile(Link_t *record_list, VSILFILE *fp);
 
@@ -305,7 +300,7 @@ void RegisterRecipes(void);
 void FreeRecipes(void);
 
 void AddRecipe( int ( *function )( CeosSARVolume_t *volume, const void *token ),
-		const void *token, const char *name );
+                const void *token, const char *name );
 
 int CeosDefaultRecipe( CeosSARVolume_t *volume, const void *token );
 int ScanSARRecipeFCN( CeosSARVolume_t *volume, const void *token );
diff --git a/frmts/ceos2/ceosrecipe.c b/frmts/ceos2/ceosrecipe.c
index 2d49eaa..9fd231e 100644
--- a/frmts/ceos2/ceosrecipe.c
+++ b/frmts/ceos2/ceosrecipe.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceosrecipe.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: ceosrecipe.c 36380 2016-11-21 10:21:20Z rouault $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  CEOS field layout recipes.
@@ -29,7 +29,7 @@
 
 #include "ceos.h"
 
-CPL_CVSID("$Id: ceosrecipe.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: ceosrecipe.c 36380 2016-11-21 10:21:20Z rouault $");
 
 /* Array of Datatypes and their names/values */
 
@@ -307,7 +307,7 @@ int CeosDefaultRecipe( CeosSARVolume_t *volume, const void *token )
 {
     const CeosRecipeType_t *recipe;
     CeosRecord_t *record;
-    CeosTypeCode_t TypeCode;
+    CeosTypeCode_t TypeCode = { 0 };
     struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
     char temp_str[1024];
     int i /*, temp_int */;
@@ -521,7 +521,7 @@ int ScanSARRecipeFCN( CeosSARVolume_t *volume, const void *token )
 static int SIRCRecipeFCN( CeosSARVolume_t *volume, const void *token )
 {
     struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
-    CeosTypeCode_t TypeCode;
+    CeosTypeCode_t TypeCode = { 0 };
     CeosRecord_t *record;
     char szSARDataFormat[29];
 
@@ -588,7 +588,7 @@ static int SIRCRecipeFCN( CeosSARVolume_t *volume, const void *token )
 static int PALSARRecipeFCN( CeosSARVolume_t *volume, const void *token )
 {
     struct CeosSARImageDesc *ImageDesc = &(volume->ImageDesc);
-    CeosTypeCode_t TypeCode;
+    CeosTypeCode_t TypeCode = { 0 };
     CeosRecord_t *record;
     char szSARDataFormat[29], szProduct[32];
 
diff --git a/frmts/ceos2/ceossar.c b/frmts/ceos2/ceossar.c
index c6d9529..d38ed3f 100644
--- a/frmts/ceos2/ceossar.c
+++ b/frmts/ceos2/ceossar.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ceossar.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: ceossar.c 37040 2016-12-30 15:31:43Z rouault $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  Functions related to CeosSARVolume_t.
@@ -29,13 +29,13 @@
 
 #include "ceos.h"
 
-CPL_CVSID("$Id: ceossar.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: ceossar.c 37040 2016-12-30 15:31:43Z rouault $");
 
 extern Link_t *RecipeFunctions;
 
 void InitCeosSARVolume(CeosSARVolume_t *volume, int32 file_name_convention)
 {
-    volume->Flavour = \
+    volume->Flavor = \
 	volume->Sensor = \
 	volume->ProductType = 0;
 
diff --git a/frmts/ceos2/link.c b/frmts/ceos2/link.c
index 0013566..2025278 100644
--- a/frmts/ceos2/link.c
+++ b/frmts/ceos2/link.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: link.c 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: link.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  Link list function replacements.
@@ -29,7 +29,7 @@
 
 #include "ceos.h"
 
-CPL_CVSID("$Id: link.c 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: link.c 34521 2016-07-02 21:26:43Z goatbar $");
 
 
 /************************************************************************/
diff --git a/frmts/ceos2/sar_ceosdataset.cpp b/frmts/ceos2/sar_ceosdataset.cpp
index 7530496..7932757 100644
--- a/frmts/ceos2/sar_ceosdataset.cpp
+++ b/frmts/ceos2/sar_ceosdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sar_ceosdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ASI CEOS Translator
  * Purpose:  GDALDataset driver for CEOS translator.
@@ -35,7 +34,7 @@
 #include "rawdataset.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: sar_ceosdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: sar_ceosdataset.cpp 37040 2016-12-30 15:31:43Z rouault $");
 
 static GInt16 CastToGInt16(float val)
 {
@@ -60,7 +59,6 @@ static const char * const CeosExtension[][6] = {
 /* Jers from Japan- not sure if this is generalized as much as it could be */
 { "VOLD", "Sarl_01", "Imop_%02d", "Sart_01", "NULL", "base" },
 
-
 /* Radarsat: basename, not extension */
 { "vdf_dat", "lea_%02d", "dat_%02d", "tra_%02d", "nul_vdf", "base" },
 
@@ -84,7 +82,6 @@ static int
 ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
              vsi_l_offset max_bytes );
 
-
 static CeosTypeCode_t QuadToTC( int a, int b, int c, int d )
 {
     CeosTypeCode_t   abcd;
@@ -114,12 +111,11 @@ static CeosTypeCode_t QuadToTC( int a, int b, int c, int d )
 #define ERS_GENERAL_FACILITY_DATA_TC  QuadToTC( 10, 200, 31, 50 )
 #define ERS_GENERAL_FACILITY_DATA_ALT_TC QuadToTC( 10, 216, 31, 50 )
 
-
 #define RSAT_PROC_PARAM_TC QuadToTC( 18, 120, 18, 20 )
 
 /************************************************************************/
 /* ==================================================================== */
-/*				SAR_CEOSDataset				*/
+/*                              SAR_CEOSDataset                         */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -135,7 +131,7 @@ class SAR_CEOSDataset : public GDALPamDataset
 
     CeosSARVolume_t sVolume;
 
-    VSILFILE	*fpImage;
+    VSILFILE    *fpImage;
 
     char        **papszTempMD;
 
@@ -148,14 +144,14 @@ class SAR_CEOSDataset : public GDALPamDataset
 
   public:
                 SAR_CEOSDataset();
-                ~SAR_CEOSDataset();
+    virtual ~SAR_CEOSDataset();
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char **GetMetadata( const char * pszDomain );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char **GetMetadata( const char * pszDomain ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -173,7 +169,7 @@ class CCPRasterBand : public GDALPamRasterBand
   public:
                    CCPRasterBand( SAR_CEOSDataset *, int, GDALDataType );
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -189,7 +185,7 @@ class PALSARRasterBand : public GDALPamRasterBand
   public:
                    PALSARRasterBand( SAR_CEOSDataset *, int );
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -205,7 +201,7 @@ class SAR_CEOSRasterBand : public GDALPamRasterBand
   public:
                    SAR_CEOSRasterBand( SAR_CEOSDataset *, int, GDALDataType );
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -216,8 +212,8 @@ SAR_CEOSRasterBand::SAR_CEOSRasterBand( SAR_CEOSDataset *poGDSIn, int nBandIn,
                                         GDALDataType eType )
 
 {
-    this->poDS = poGDSIn;
-    this->nBand = nBandIn;
+    poDS = poGDSIn;
+    nBand = nBandIn;
 
     eDataType = eType;
 
@@ -237,7 +233,7 @@ CPLErr SAR_CEOSRasterBand::IReadBlock( int /* nBlockXOff */,
 
     struct CeosSARImageDesc *ImageDesc = &(poGDS->sVolume.ImageDesc);
 
-    int	offset;
+    int offset;
     CalcCeosSARImageFilePosition( &(poGDS->sVolume), nBand,
                                   nBlockYOff + 1, NULL, &offset );
 
@@ -254,7 +250,7 @@ CPLErr SAR_CEOSRasterBand::IReadBlock( int /* nBlockXOff */,
 
     for( int iRecord = 0; iRecord < ImageDesc->RecordsPerLine; iRecord++ )
     {
-        int	nPixelsToRead;
+        int nPixelsToRead;
 
         if( nPixelsRead + ImageDesc->PixelsPerRecord > nBlockXSize )
             nPixelsToRead = nBlockXSize - nPixelsRead;
@@ -306,7 +302,7 @@ CPLErr SAR_CEOSRasterBand::IReadBlock( int /* nBlockXOff */,
 
 /************************************************************************/
 /* ==================================================================== */
-/*				CCPRasterBand				*/
+/*                              CCPRasterBand                           */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -318,8 +314,8 @@ CCPRasterBand::CCPRasterBand( SAR_CEOSDataset *poGDSIn, int nBandIn,
                               GDALDataType eType )
 
 {
-    this->poDS = poGDSIn;
-    this->nBand = nBandIn;
+    poDS = poGDSIn;
+    nBand = nBandIn;
 
     eDataType = eType;
 
@@ -464,7 +460,7 @@ CPLErr CCPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
 /************************************************************************/
 /* ==================================================================== */
-/*			      PALSARRasterBand				*/
+/*                            PALSARRasterBand                          */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -475,8 +471,8 @@ CPLErr CCPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 PALSARRasterBand::PALSARRasterBand( SAR_CEOSDataset *poGDSIn, int nBandIn )
 
 {
-    this->poDS = poGDSIn;
-    this->nBand = nBandIn;
+    poDS = poGDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_CInt16;
 
@@ -620,7 +616,7 @@ CPLErr PALSARRasterBand::IReadBlock( int /* nBlockXOff */,
 
 /************************************************************************/
 /* ==================================================================== */
-/*				SAR_CEOSDataset				*/
+/*                              SAR_CEOSDataset                         */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -634,7 +630,7 @@ SAR_CEOSDataset::SAR_CEOSDataset() :
     nGCPCount(0),
     pasGCPList(NULL)
 {
-    sVolume.Flavour = 0;
+    sVolume.Flavor = 0;
     sVolume.Sensor = 0;
     sVolume.ProductType = 0;
     sVolume.FileNamingConvention = 0;
@@ -739,7 +735,6 @@ const GDAL_GCP *SAR_CEOSDataset::GetGCPs()
     return pasGCPList;
 }
 
-
 /************************************************************************/
 /*                      GetMetadataDomainList()                         */
 /************************************************************************/
@@ -823,10 +818,9 @@ char **SAR_CEOSDataset::GetMetadata( const char * pszDomain )
 /* -------------------------------------------------------------------- */
 /*      Try to fetch the record.                                        */
 /* -------------------------------------------------------------------- */
-    CeosRecord_t *record;
-
-    record = FindCeosRecord( sVolume.RecordList, sTypeCode, nFileId,
-                             -1, nRecordIndex );
+    CeosRecord_t *record =
+        FindCeosRecord( sVolume.RecordList, sTypeCode, nFileId,
+                        -1, nRecordIndex );
 
     if( record == NULL )
         return NULL;
@@ -848,7 +842,6 @@ char **SAR_CEOSDataset::GetMetadata( const char * pszDomain )
     papszTempMD = CSLSetNameValue( NULL, "EscapedRecord", pszSafeCopy );
     CPLFree( pszSafeCopy );
 
-
     // Copy with '\0' replaced by spaces.
 
     pszSafeCopy = (char *) CPLCalloc(1,record->Length+1);
@@ -1059,7 +1052,6 @@ void SAR_CEOSDataset::ScanForMetadata()
         if( !STARTS_WITH_CI(szField, "                                ") )
             SetMetadataItem( "CEOS_SENSOR_ID", szField );
 
-
 /* -------------------------------------------------------------------- */
 /*      ORBIT NUMBER                                                    */
 /* -------------------------------------------------------------------- */
@@ -1069,7 +1061,6 @@ void SAR_CEOSDataset::ScanForMetadata()
         if( !STARTS_WITH_CI(szField, "        ") )
             SetMetadataItem( "CEOS_ORBIT_NUMBER", szField );
 
-
 /* -------------------------------------------------------------------- */
 /*      Platform latitude                                               */
 /* -------------------------------------------------------------------- */
@@ -1140,7 +1131,6 @@ void SAR_CEOSDataset::ScanForMetadata()
 
         if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_PIXEL_SPACING_METERS", szField );
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -1229,10 +1219,9 @@ void SAR_CEOSDataset::ScanForMetadata()
 
         if( !STARTS_WITH_CI(szField, "                    ") )
             SetMetadataItem( "CEOS_GROUND_TO_SLANT_C3", szField );
-
     }
 /* -------------------------------------------------------------------- */
-/*	Detailed Processing Parameters (Radarsat)                       */
+/*      Detailed Processing Parameters (Radarsat)                       */
 /* -------------------------------------------------------------------- */
     record = FindCeosRecord( sVolume.RecordList, RSAT_PROC_PARAM_TC,
                              CEOS_LEADER_FILE, -1, -1 );
@@ -1344,11 +1333,10 @@ void SAR_CEOSDataset::ScanForMetadata()
 
         if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_INC_ANGLE_LAST_RANGE", szField );
-
     }
 /* -------------------------------------------------------------------- */
-/*	Get process-to-raw data coordinate translation values.  These	*/
-/*	are likely specific to Atlantis APP products.			*/
+/*      Get process-to-raw data coordinate translation values.  These   */
+/*      are likely specific to Atlantis APP products.                   */
 /* -------------------------------------------------------------------- */
     record = FindCeosRecord( sVolume.RecordList,
                              IMAGE_HEADER_RECORD_TC,
@@ -1362,62 +1350,53 @@ void SAR_CEOSDataset::ScanForMetadata()
         if( !STARTS_WITH_CI(szField, "    ") )
             SetMetadataItem( "CEOS_DM_CORNER", szField );
 
-
         GetCeosField( record, 453, "A4", szField );
         szField[4] = '\0';
 
         if( !STARTS_WITH_CI(szField, "    ") )
             SetMetadataItem( "CEOS_DM_TRANSPOSE", szField );
 
-
         GetCeosField( record, 457, "A4", szField );
         szField[4] = '\0';
 
         if( !STARTS_WITH_CI(szField, "    ") )
             SetMetadataItem( "CEOS_DM_START_SAMPLE", szField );
 
-
         GetCeosField( record, 461, "A5", szField );
         szField[5] = '\0';
 
         if( !STARTS_WITH_CI(szField, "     ") )
             SetMetadataItem( "CEOS_DM_START_PULSE", szField );
 
-
         GetCeosField( record, 466, "A16", szField );
         szField[16] = '\0';
 
         if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_FAST_ALPHA", szField );
 
-
         GetCeosField( record, 482, "A16", szField );
         szField[16] = '\0';
 
         if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_FAST_BETA", szField );
 
-
         GetCeosField( record, 498, "A16", szField );
         szField[16] = '\0';
 
         if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_SLOW_ALPHA", szField );
 
-
         GetCeosField( record, 514, "A16", szField );
         szField[16] = '\0';
 
         if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_SLOW_BETA", szField );
 
-
         GetCeosField( record, 530, "A16", szField );
         szField[16] = '\0';
 
         if( !STARTS_WITH_CI(szField, "                ") )
             SetMetadataItem( "CEOS_DM_FAST_ALPHA_2", szField );
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -1467,7 +1446,7 @@ void SAR_CEOSDataset::ScanForMetadata()
 
 /* -------------------------------------------------------------------- */
 /*      For ERS Standard Format Landsat scenes we pick up the           */
-/*      gain setting from the Scene Header Record.			*/
+/*      gain setting from the Scene Header Record.                      */
 /* -------------------------------------------------------------------- */
     record = FindCeosRecord( sVolume.RecordList,
                              QuadToTC( 0x12, 0x12, 0x12, 0x09 ),
@@ -1978,7 +1957,7 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
         int StartData;
         CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &StartData );
 
-        StartData += psImageDesc->ImageDataStart;
+        /*StartData += psImageDesc->ImageDataStart; */
 
         int nLineSize, nLineSize2;
         CalcCeosSARImageFilePosition( psVolume, 1, 1, NULL, &nLineSize );
@@ -2021,7 +2000,7 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
             }
             else
             {
-                CPLAssert( FALSE );
+                CPLAssert( false );
                 return NULL;
             }
 
@@ -2059,7 +2038,7 @@ GDALDataset *SAR_CEOSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -2076,8 +2055,6 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
     int                CurrentBodyLength = 0;
     int                CurrentType = 0;
     int                CurrentSequence = 0;
-    Link_t             *TheLink;
-    CeosRecord_t       *record;
     int                iThisRecord = 0;
 
     while(max_records != 0 && max_bytes != 0)
@@ -2093,7 +2070,8 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
             CPLFree(temp_body);
             return CE_Failure;
         }
-        record = (CeosRecord_t *) CPLMalloc( sizeof( CeosRecord_t ) );
+        CeosRecord_t *record =
+            (CeosRecord_t *) CPLMalloc( sizeof( CeosRecord_t ) );
         record->Length = DetermineCeosRecordBodyLength( temp_buffer );
 
         CeosToNative( &(record->Sequence), temp_buffer, 4, 4 );
@@ -2168,12 +2146,13 @@ ProcessData( VSILFILE *fp, int fileid, CeosSARVolume_t *sar, int max_records,
             record->Subsequence = ++CurrentSequence;
         else {
             CurrentType = record->TypeCode.Int32Code;
-            record->Subsequence = CurrentSequence = 0;
+            record->Subsequence = 0;
+            CurrentSequence = 0;
         }
 
         record->FileId = fileid;
 
-        TheLink = ceos2CreateLink( record );
+        Link_t *TheLink = ceos2CreateLink( record );
 
         if( sar->RecordList == NULL )
             sar->RecordList = TheLink;
diff --git a/frmts/coasp/GNUmakefile b/frmts/coasp/GNUmakefile
index 44655c2..14b6b0e 100644
--- a/frmts/coasp/GNUmakefile
+++ b/frmts/coasp/GNUmakefile
@@ -3,7 +3,7 @@ include ../../GDALmake.opt
 
 OBJ	=	coasp_dataset.o
 
-CPPFLAGS	:=	 $(CPPFLAGS) 
+CPPFLAGS	:=	 $(CPPFLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/coasp/coasp_dataset.cpp b/frmts/coasp/coasp_dataset.cpp
index 8bf342d..30bb4f5 100644
--- a/frmts/coasp/coasp_dataset.cpp
+++ b/frmts/coasp/coasp_dataset.cpp
@@ -1,14 +1,13 @@
 /******************************************************************************
- * $Id: coasp_dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  DRDC Configurable Airborne SAR Processor (COASP) data reader
  * Purpose:  Support in GDAL for the DRDC COASP format data, both Metadata
- *	     and complex imagery.
+ *           and complex imagery.
  * Author:   Philippe Vachon <philippe at cowpig.ca>
  * Notes:    I have seen a grand total of 2 COASP scenes (3 sets of headers).
- *	     This is based on my best observations, some educated guesses and
- *	     such. So if you have a scene that doesn't work, send it to me
- *	     please and I will make it work... with violence.
+ *           This is based on my best observations, some educated guesses and
+ *           such. So if you have a scene that doesn't work, send it to me
+ *           please and I will make it work... with violence.
  *
  ******************************************************************************
  * Copyright (c) 2007, Philippe Vachon
@@ -40,16 +39,16 @@
 #include "gdal_frmts.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: coasp_dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: coasp_dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 static const int TYPE_GENERIC = 0;
 static const int TYPE_GEOREF = 1;
 
 enum ePolarization {
-	hh = 0,
-	hv,
-	vh,
-	vv
+    hh = 0,
+    hv,
+    vh,
+    vv
 };
 
 /*******************************************************************
@@ -60,18 +59,18 @@ class COASPMetadataItem;
 
 class COASPMetadataReader
 {
-	VSILFILE *fp;
-	char **papszMetadata;
-	int nMetadataCount;
-	int nCurrentItem;
+        VSILFILE *fp;
+        char **papszMetadata;
+        int nMetadataCount;
+        int nCurrentItem;
 public:
-	COASPMetadataReader(char *pszFname);
+        explicit COASPMetadataReader(char *pszFname);
         ~COASPMetadataReader();
-	COASPMetadataItem *GetNextItem();
-	COASPMetadataItem *GetItem(int nItem);
-	int GotoMetadataItem(int nItemNumber);
-	int GotoMetadataItem(const char *pszName);
-	int GetCurrentItem() { return nCurrentItem; }
+        COASPMetadataItem *GetNextItem();
+        COASPMetadataItem *GetItem(int nItem);
+        int GotoMetadataItem(int nItemNumber);
+        int GotoMetadataItem(const char *pszName);
+        int GetCurrentItem() { return nCurrentItem; }
 };
 
 /* Your average metadata item */
@@ -88,7 +87,7 @@ public:
 
     char *GetItemName();
     char *GetItemValue();
-    int GetType() { return TYPE_GENERIC; }
+    static int GetType() { return TYPE_GENERIC; }
 };
 
 /* Same as MetadataItem class except parses GCP properly and returns
@@ -96,18 +95,20 @@ public:
  */
 class COASPMetadataGeorefGridItem : public COASPMetadataItem
 {
-	int nId;
-	int nPixels;
-	int nLines;
-	double ndLat;
-	double ndLong;
+#ifdef unused
+        int nId;
+        int nPixels;
+        int nLines;
+        double ndLat;
+        double ndLong;
+#endif
 
 public:
-	COASPMetadataGeorefGridItem(int nId, int nPixels, int nLines,
-		double ndLat, double ndLong);
-	const char *GetItemName() { return "georef_grid"; }
-	GDAL_GCP *GetItemValue();
-	int GetType() { return TYPE_GEOREF; }
+        COASPMetadataGeorefGridItem( int nId, int nPixels, int nLines,
+                                     double ndLat, double ndLong );
+        static const char *GetItemName() { return "georef_grid"; }
+        GDAL_GCP *GetItemValue();
+        static int GetType() { return TYPE_GEOREF; }
 };
 
 /********************************************************************
@@ -116,11 +117,10 @@ public:
  * ================================================================ *
  ********************************************************************/
 
-COASPMetadataItem::COASPMetadataItem(char *pszItemName_, char *pszItemValue_)
-{
-    pszItemName = VSIStrdup(pszItemName_);
-    pszItemValue = VSIStrdup(pszItemValue_);
-}
+COASPMetadataItem::COASPMetadataItem(char *pszItemName_, char *pszItemValue_) :
+    pszItemName(VSIStrdup(pszItemName_)),
+    pszItemValue(VSIStrdup(pszItemValue_))
+{}
 
 COASPMetadataItem::~COASPMetadataItem()
 {
@@ -130,28 +130,32 @@ COASPMetadataItem::~COASPMetadataItem()
 
 char *COASPMetadataItem::GetItemName()
 {
-	return VSIStrdup(pszItemName);
+        return VSIStrdup(pszItemName);
 }
 
 char *COASPMetadataItem::GetItemValue()
 {
-	return VSIStrdup(pszItemValue);
+        return VSIStrdup(pszItemValue);
 }
 
-COASPMetadataGeorefGridItem::COASPMetadataGeorefGridItem(int nIdIn, int nPixelsIn,
-	int nLinesIn, double ndLatIn, double ndLongIn)
+COASPMetadataGeorefGridItem::COASPMetadataGeorefGridItem(
+    int /*nIdIn*/, int /*nPixelsIn*/,
+    int /*nLinesIn*/, double /*ndLatIn*/, double /*ndLongIn*/ )
+#ifdef unused
+:
+    nId(nIdIn),
+    nPixels(nPixelsIn),
+    nLines(nLinesIn),
+    ndLat(ndLatIn),
+    ndLong(ndLongIn)
+#endif
 {
-	this->nId = nIdIn;
-	this->nPixels = nPixelsIn;
-	this->nLines = nLinesIn;
-	this->ndLat = ndLatIn;
-	this->ndLong = ndLongIn;
-        pszItemName = VSIStrdup("georef_grid");
+    pszItemName = VSIStrdup("georef_grid");
 }
 
 GDAL_GCP *COASPMetadataGeorefGridItem::GetItemValue()
 {
-	return NULL;
+    return NULL;
 }
 
 /********************************************************************
@@ -161,9 +165,11 @@ GDAL_GCP *COASPMetadataGeorefGridItem::GetItemValue()
  ********************************************************************/
 
 COASPMetadataReader::COASPMetadataReader(char *pszFname) :
-    fp(NULL), papszMetadata(NULL), nMetadataCount(0), nCurrentItem(0)
+    fp(NULL),
+    papszMetadata(CSLLoad(pszFname)),
+    nMetadataCount(0),
+    nCurrentItem(0)
 {
-    papszMetadata = CSLLoad(pszFname);
     nMetadataCount = CSLCount(papszMetadata);
 }
 
@@ -176,69 +182,70 @@ COASPMetadataReader::~COASPMetadataReader()
 
 COASPMetadataItem *COASPMetadataReader::GetNextItem()
 {
-	if (nCurrentItem >= nMetadataCount)
-		return NULL;
+        if (nCurrentItem >= nMetadataCount)
+            return NULL;
 
-        COASPMetadataItem *poMetadata;
+        COASPMetadataItem *poMetadata = NULL;
 
         char **papszMDTokens
             = CSLTokenizeString2(papszMetadata[nCurrentItem], " ",
                                  CSLT_HONOURSTRINGS );
         char *pszItemName = papszMDTokens[0];
-	if (STARTS_WITH_CI(pszItemName, "georef_grid")) {
-		// georef_grid ( pixels lines ) ( lat long )
-		// 0           1 2      3     4 5 6   7    8
-                int nPixels = atoi(papszMDTokens[2]);
-                int nLines = atoi(papszMDTokens[3]);
-                double dfLat = CPLAtof(papszMDTokens[6]);
-                double dfLong = CPLAtof(papszMDTokens[7]);
-                poMetadata = new COASPMetadataGeorefGridItem(
-                    nCurrentItem, nPixels, nLines, dfLat, dfLong);
-	}
-	else {
-		int nCount = CSLCount(papszMDTokens);
-                char *pszItemValue = CPLStrdup(papszMDTokens[1]);
-		for (int i = 2; i < nCount; i++) {
-			const size_t nSize = strlen(pszItemValue) + 1 + strlen(papszMDTokens[i]);
-			pszItemValue = (char *)CPLRealloc(pszItemValue, nSize);
-			snprintf(pszItemValue + strlen(pszItemValue),
-                                 nSize - strlen(pszItemValue), " %s",
-				papszMDTokens[i]);
-		}
-
-		poMetadata = new COASPMetadataItem(pszItemName,
-			pszItemValue);
-
-		CPLFree(pszItemValue);
-	}
-	CSLDestroy(papszMDTokens);
-	nCurrentItem++;
-	return poMetadata;
+        if (STARTS_WITH_CI(pszItemName, "georef_grid"))
+        {
+            // georef_grid ( pixels lines ) ( lat long )
+            // 0           1 2      3     4 5 6   7    8
+            int nPixels = atoi(papszMDTokens[2]);
+            int nLines = atoi(papszMDTokens[3]);
+            double dfLat = CPLAtof(papszMDTokens[6]);
+            double dfLong = CPLAtof(papszMDTokens[7]);
+            poMetadata = new COASPMetadataGeorefGridItem(
+                nCurrentItem, nPixels, nLines, dfLat, dfLong);
+        }
+        else
+        {
+            int nCount = CSLCount(papszMDTokens);
+            char *pszItemValue = CPLStrdup(papszMDTokens[1]);
+            for (int i = 2; i < nCount; i++)
+            {
+                const size_t nSize = strlen(pszItemValue) + 1 + strlen(papszMDTokens[i]);
+                pszItemValue = (char *)CPLRealloc(pszItemValue, nSize);
+                snprintf(pszItemValue + strlen(pszItemValue),
+                         nSize - strlen(pszItemValue), " %s",
+                         papszMDTokens[i]);
+            }
+
+            poMetadata = new COASPMetadataItem(pszItemName, pszItemValue);
+
+            CPLFree(pszItemValue);
+        }
+        CSLDestroy(papszMDTokens);
+        nCurrentItem++;
+        return poMetadata;
 }
 
 /* Goto a particular metadata item, listed by number */
 int COASPMetadataReader::GotoMetadataItem(int nItemNumber)
 {
-	if (nItemNumber >= nMetadataCount || nItemNumber < 0) {
+        if (nItemNumber >= nMetadataCount || nItemNumber < 0) {
             nCurrentItem = 0;
-	}
-	else
+        }
+        else
             nCurrentItem = nItemNumber;
-	return nCurrentItem;
+        return nCurrentItem;
 }
 
 /* Goto the first metadata item with a particular name */
 int COASPMetadataReader::GotoMetadataItem(const char *pszName)
 {
-	nCurrentItem = CSLPartialFindString(papszMetadata, pszName);
-	return nCurrentItem;
+        nCurrentItem = CSLPartialFindString(papszMetadata, pszName);
+        return nCurrentItem;
 }
 
 /*******************************************************************
  * Declaration of the COASPDataset class                           *
  *******************************************************************/
 
-
 class COASPRasterBand;
 
 /* A couple of observations based on the data I have available to me:
@@ -253,22 +260,32 @@ class COASPRasterBand;
 
 class COASPDataset : public GDALDataset
 {
-	friend class COASPRasterBand;
-	VSILFILE *fpHdr; /* File pointer for the header file */
-	VSILFILE *fpBinHH; /* File pointer for the binary matrix */
-	VSILFILE *fpBinHV;
-	VSILFILE *fpBinVH;
-	VSILFILE *fpBinVV;
+        friend class COASPRasterBand;
+        VSILFILE *fpHdr; /* File pointer for the header file */
+        VSILFILE *fpBinHH; /* File pointer for the binary matrix */
+        VSILFILE *fpBinHV;
+        VSILFILE *fpBinVH;
+        VSILFILE *fpBinVV;
 
-	char *pszFileName; /* line and mission ID, mostly, i.e. l27p7 */
+        char *pszFileName; /* line and mission ID, mostly, i.e. l27p7 */
 
-	int nGCPCount;
-	GDAL_GCP *pasGCP;
+        int nGCPCount;
+        GDAL_GCP *pasGCP;
 public:
-	static GDALDataset *Open( GDALOpenInfo * );
-	static int Identify( GDALOpenInfo * poOpenInfo );
-	int GetGCPCount();
-	const GDAL_GCP *GetGCPs();
+        COASPDataset():
+            fpHdr(NULL),
+            fpBinHH(NULL),
+            fpBinHV(NULL),
+            fpBinVH(NULL),
+            fpBinVV(NULL),
+            pszFileName(NULL),
+            nGCPCount(0),
+            pasGCP(NULL) {}
+
+        static GDALDataset *Open( GDALOpenInfo * );
+        static int Identify( GDALOpenInfo * poOpenInfo );
+        int GetGCPCount() override;
+        const GDAL_GCP *GetGCPs() override;
 };
 
 /********************************************************************
@@ -278,21 +295,23 @@ public:
  ********************************************************************/
 
 class COASPRasterBand : public GDALRasterBand {
-	VSILFILE *fp;
-	int ePol;
+        VSILFILE *fp;
+        /*int ePol;*/
 public:
-	COASPRasterBand( COASPDataset *poDS, GDALDataType eDataType, int ePol, VSILFILE *fp );
-	virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff,
-		void *pImage);
+        COASPRasterBand( COASPDataset *poDS, GDALDataType eDataType,
+                         int ePol, VSILFILE *fp );
+        virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff,
+                                   void *pImage) override;
 };
 
-COASPRasterBand::COASPRasterBand( COASPDataset *poDSIn, GDALDataType eDataTypeIn,
-	int ePolIn, VSILFILE *fpIn)
+COASPRasterBand::COASPRasterBand( COASPDataset *poDSIn,
+                                  GDALDataType eDataTypeIn,
+                                  int /*ePolIn*/, VSILFILE *fpIn ) :
+        fp(fpIn)/*,
+        ePol(ePolIn)*/
 {
-	this->fp = fpIn;
-	this->ePol = ePolIn;
-	this->poDS = poDSIn;
-	this->eDataType = eDataTypeIn;
+        poDS = poDSIn;
+        eDataType = eDataTypeIn;
         nBlockXSize = poDS->GetRasterXSize();
         nBlockYSize = 1;
 }
@@ -301,26 +320,26 @@ CPLErr COASPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                     int nBlockYOff,
                                     void *pImage )
 {
-	if (this->fp == NULL) {
-		CPLError(CE_Fatal, CPLE_AppDefined, "file pointer freed unexpectedly\n");
-		return CE_Fatal;
-	}
+        if (this->fp == NULL)
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "File pointer freed unexpectedly");
+            return CE_Fatal;
+        }
 
-	/* 8 bytes per pixel: 4 bytes I, 4 bytes Q */
-	unsigned long nByteNum = poDS->GetRasterXSize() * 8 * nBlockYOff;
+        /* 8 bytes per pixel: 4 bytes I, 4 bytes Q */
+        unsigned long nByteNum = poDS->GetRasterXSize() * 8 * nBlockYOff;
 
-	VSIFSeekL(this->fp, nByteNum, SEEK_SET);
-	int nReadSize = (GDALGetDataTypeSize(eDataType)/8) * poDS->GetRasterXSize();
-	VSIFReadL((char *)pImage, 1, nReadSize,
-		this->fp);
+        VSIFSeekL(this->fp, nByteNum, SEEK_SET);
+        int nReadSize = (GDALGetDataTypeSize(eDataType)/8) * poDS->GetRasterXSize();
+        VSIFReadL((char *)pImage, 1, nReadSize, this->fp);
 
 #ifdef CPL_LSB
-	GDALSwapWords( pImage, 4, nBlockXSize * 2, 4 );
+        GDALSwapWords( pImage, 4, nBlockXSize * 2, 4 );
 #endif
-	return CE_None;
+        return CE_None;
 }
 
-
 /********************************************************************
  * ================================================================ *
  * Implementation of the COASPDataset Class                         *
@@ -333,7 +352,7 @@ CPLErr COASPRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
 int COASPDataset::GetGCPCount()
 {
-	return nGCPCount;
+        return nGCPCount;
 }
 
 /************************************************************************/
@@ -342,7 +361,7 @@ int COASPDataset::GetGCPCount()
 
 const GDAL_GCP *COASPDataset::GetGCPs()
 {
-	return pasGCP;
+        return pasGCP;
 }
 
 /************************************************************************/
@@ -351,16 +370,15 @@ const GDAL_GCP *COASPDataset::GetGCPs()
 
 int COASPDataset::Identify( GDALOpenInfo *poOpenInfo )
 {
-	if(poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 256)
-		return 0;
+    if(poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 256)
+        return 0;
+
+    // With a COASP .hdr file, the first line or so is: time_first_datarec
 
-	/* With a COASP .hdr file, the first line or so is:
- 	 * time_first_datarec
- 	 */
-	if(STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "time_first_datarec"))
-		return 1;
+    if(STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "time_first_datarec"))
+        return 1;
 
-	return 0;
+    return 0;
 }
 
 /************************************************************************/
@@ -369,8 +387,8 @@ int COASPDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
 {
-	if (!COASPDataset::Identify(poOpenInfo))
-		return NULL;
+    if (!COASPDataset::Identify(poOpenInfo))
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
@@ -386,52 +404,57 @@ GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
     /* Create a fresh dataset for us to work with */
     COASPDataset *poDS = new COASPDataset();
 
-	if (poDS == NULL)
-		return NULL;
-
-	/* Steal the file pointer for the header */
-	poDS->fpHdr = poOpenInfo->fpL;
-	poOpenInfo->fpL = NULL;
-
-	/* Set the binary matrix file pointers to NULL, for now */
-	poDS->fpBinHH = NULL;
-	poDS->fpBinHV = NULL;
-	poDS->fpBinVH = NULL;
-	poDS->fpBinVV = NULL;
-        poDS->nGCPCount = 0;
-        poDS->pasGCP = NULL;
-
-	poDS->pszFileName = VSIStrdup(poOpenInfo->pszFilename);
-
-	/* determine the file name prefix */
-	char *pszBaseName = VSIStrdup(CPLGetBasename(poDS->pszFileName));
-	char *pszDir = VSIStrdup(CPLGetPath(poDS->pszFileName));
-	const char *pszExt = "rc";
-	int nNull = static_cast<int>(strlen(pszBaseName)) - 1;
-	char *pszBase = (char *)CPLMalloc(nNull);
-	strncpy(pszBase, pszBaseName, nNull);
-	pszBase[nNull - 1] = '\0';
-	free(pszBaseName);
-
-	char *psChan = strstr(pszBase,"hh");;
-	if (psChan == NULL) {
-		psChan = strstr(pszBase, "hv");
-	}
-	if (psChan == NULL) {
-		psChan = strstr(pszBase, "vh");
-	}
-	if (psChan == NULL) {
-		psChan = strstr(pszBase, "vv");
-	}
-
-	if (psChan == NULL) {
-		CPLError(CE_Fatal, CPLE_AppDefined, "unable to recognize file as COASP.\n");
-		free(poDS->pszFileName);
-		free(pszBase);
-		free(pszDir);
-		delete poDS;
-		return NULL;
-	}
+    if (poDS == NULL)
+        return NULL;
+
+    /* Steal the file pointer for the header */
+    poDS->fpHdr = poOpenInfo->fpL;
+    poOpenInfo->fpL = NULL;
+
+    /* Set the binary matrix file pointers to NULL, for now */
+    poDS->fpBinHH = NULL;
+    poDS->fpBinHV = NULL;
+    poDS->fpBinVH = NULL;
+    poDS->fpBinVV = NULL;
+    poDS->nGCPCount = 0;
+    poDS->pasGCP = NULL;
+
+    poDS->pszFileName = VSIStrdup(poOpenInfo->pszFilename);
+
+    /* determine the file name prefix */
+    char *pszBaseName = VSIStrdup(CPLGetBasename(poDS->pszFileName));
+    char *pszDir = VSIStrdup(CPLGetPath(poDS->pszFileName));
+    const char *pszExt = "rc";
+    int nNull = static_cast<int>(strlen(pszBaseName)) - 1;
+    char *pszBase = (char *)CPLMalloc(nNull);
+    strncpy(pszBase, pszBaseName, nNull);
+    pszBase[nNull - 1] = '\0';
+    free(pszBaseName);
+
+    char *psChan = strstr(pszBase,"hh");
+    if( psChan == NULL )
+    {
+        psChan = strstr(pszBase, "hv");
+    }
+    if (psChan == NULL)
+    {
+        psChan = strstr(pszBase, "vh");
+    }
+    if (psChan == NULL)
+    {
+        psChan = strstr(pszBase, "vv");
+    }
+
+    if (psChan == NULL)
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "Unable to recognize file as COASP.");
+        free(poDS->pszFileName);
+        free(pszBase);
+        free(pszDir);
+        delete poDS;
+        return NULL;
+    }
 
     /* Read Metadata, set GCPs as is appropriate */
     COASPMetadataReader *poReader = new COASPMetadataReader(
@@ -451,82 +474,84 @@ GDALDataset *COASPDataset::Open( GDALOpenInfo *poOpenInfo )
     poDS->nRasterXSize = atoi(nValue);
     free(nValue);
 
+    /* Horizontal transmit, horizontal receive */
+    psChan[0] = 'h';
+    psChan[1] = 'h';
+    const char *pszFilename = CPLFormFilename(pszDir, pszBase, pszExt);
 
-	/* Horizontal transmit, horizontal receive */
-	psChan[0] = 'h';
-	psChan[1] = 'h';
-     const char *pszFilename = CPLFormFilename(pszDir, pszBase, pszExt);
-
-	poDS->fpBinHH = VSIFOpenL(pszFilename, "r");
+    poDS->fpBinHH = VSIFOpenL(pszFilename, "r");
 
-	if (poDS->fpBinHH != NULL) {
-		/* Set raster band */
-		poDS->SetBand(1, new COASPRasterBand(poDS, GDT_CFloat32,
-			hh , poDS->fpBinHH));
-	}
+    if (poDS->fpBinHH != NULL)
+    {
+        /* Set raster band */
+        poDS->SetBand(1, new COASPRasterBand(poDS, GDT_CFloat32,
+                                             hh , poDS->fpBinHH));
+    }
 
-	/* Horizontal transmit, vertical receive */
+    /* Horizontal transmit, vertical receive */
     psChan[0] = 'h';
     psChan[1] = 'v';
     pszFilename = CPLFormFilename(pszDir, pszBase, pszExt);
 
-	poDS->fpBinHV = VSIFOpenL(pszFilename, "r");
+    poDS->fpBinHV = VSIFOpenL(pszFilename, "r");
 
-	if (poDS->fpBinHV != NULL) {
-		poDS->SetBand(2, new COASPRasterBand(poDS, GDT_CFloat32,
-			hv, poDS->fpBinHV));
-	}
+    if (poDS->fpBinHV != NULL)
+    {
+        poDS->SetBand(2, new COASPRasterBand(poDS, GDT_CFloat32,
+                                             hv, poDS->fpBinHV));
+    }
 
-	/* Vertical transmit, horizontal receive */
+    /* Vertical transmit, horizontal receive */
     psChan[0] = 'v';
     psChan[1] = 'h';
     pszFilename = CPLFormFilename(pszDir, pszBase, pszExt);
 
-	poDS->fpBinVH = VSIFOpenL(pszFilename, "r");
+    poDS->fpBinVH = VSIFOpenL(pszFilename, "r");
 
-	if (poDS->fpBinVH != NULL) {
-    	poDS->SetBand(3, new COASPRasterBand(poDS, GDT_CFloat32,
-			vh, poDS->fpBinVH));
-	}
+    if (poDS->fpBinVH != NULL)
+    {
+        poDS->SetBand(3, new COASPRasterBand(poDS, GDT_CFloat32,
+                                             vh, poDS->fpBinVH));
+    }
 
-	/* Vertical transmit, vertical receive */
+    /* Vertical transmit, vertical receive */
     psChan[0] = 'v';
     psChan[1] = 'v';
     pszFilename = CPLFormFilename(pszDir, pszBase, pszExt);
 
-	poDS->fpBinVV = VSIFOpenL(pszFilename, "r");
+    poDS->fpBinVV = VSIFOpenL(pszFilename, "r");
 
-	if (poDS->fpBinVV != NULL) {
-		poDS->SetBand(4, new COASPRasterBand(poDS, GDT_CFloat32,
-			vv, poDS->fpBinVV));
-	}
-
-
-	/* Oops, missing all the data? */
+    if (poDS->fpBinVV != NULL)
+    {
+        poDS->SetBand(4, new COASPRasterBand(poDS, GDT_CFloat32,
+                                             vv, poDS->fpBinVV));
+    }
 
-	if (poDS->fpBinHH == NULL && poDS->fpBinHV == NULL
-		&& poDS->fpBinVH == NULL && poDS->fpBinVV == NULL)
-	{
-		CPLError(CE_Fatal,CPLE_AppDefined,"Unable to find any data! Aborting.");
-		free(pszBase);
-		free(pszDir);
-		delete poDS;
-                delete poItem;
-                delete poReader;
-		return NULL;
-	}
+    /* Oops, missing all the data? */
+    if (poDS->fpBinHH == NULL && poDS->fpBinHV == NULL
+        && poDS->fpBinVH == NULL && poDS->fpBinVV == NULL)
+    {
+        CPLError(CE_Fatal,CPLE_AppDefined,"Unable to find any data! Aborting.");
+        free(pszBase);
+        free(pszDir);
+        delete poDS;
+        delete poItem;
+        delete poReader;
+        return NULL;
+    }
 
-    if ( poDS->GetRasterCount() == 4 ) {
+    if( poDS->GetRasterCount() == 4 )
+    {
         poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
     }
 
-	free(pszBase);
-	free(pszDir);
+    free(pszBase);
+    free(pszDir);
 
-	delete poItem;
-	delete poReader;
+    delete poItem;
+    delete poReader;
 
-	return poDS;
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/cosar/cosar_dataset.cpp b/frmts/cosar/cosar_dataset.cpp
index 5c58639..7d8e6fc 100644
--- a/frmts/cosar/cosar_dataset.cpp
+++ b/frmts/cosar/cosar_dataset.cpp
@@ -29,6 +29,8 @@
 
 #include <string.h>
 
+CPL_CVSID("$Id: cosar_dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+
 /* Various offsets, in bytes */
 // Commented out the unused defines.
 // #define BIB_OFFSET   0  /* Bytes in burst, valid only for ScanSAR */
@@ -37,7 +39,7 @@ const static int RS_OFFSET = 8;  /* Range Samples, the length of a range line */
 // #define AS_OFFSET    12 /* Azimuth Samples, the length of an azimuth column */
 // #define BI_OFFSET    16 /* Burst Index, the index number of the burst */
 const static int RTNB_OFFSET = 20;  /* Rangeline total number of bytes, incl. annot. */
-// #define TNL_OFFSET	24 /* Total Number of Lines */
+// #define TNL_OFFSET   24 /* Total Number of Lines */
 const static int MAGIC1_OFFSET = 28; /* Magic number 1: 0x43534152 */
 // #define MAGIC2_OFFSET 32 /* Magic number 2: Version number */
 
@@ -48,31 +50,30 @@ class COSARDataset : public GDALDataset
 {
 public:
         COSARDataset() : fp(NULL) { }
-	VSILFILE *fp;
+        VSILFILE *fp;
 
-	static GDALDataset *Open( GDALOpenInfo * );
+        static GDALDataset *Open( GDALOpenInfo * );
 };
 
 class COSARRasterBand : public GDALRasterBand
 {
     unsigned long nRTNB;
-    // int nBurstNumber;
+
 public:
-	COSARRasterBand(COSARDataset *, unsigned long nRTNB);
-	virtual CPLErr IReadBlock(int, int, void *);
+        COSARRasterBand(COSARDataset *, unsigned long nRTNB);
+        virtual CPLErr IReadBlock(int, int, void *) override;
 };
 
 /*****************************************************************************
  * COSARRasterBand Implementation
  *****************************************************************************/
 
-COSARRasterBand::COSARRasterBand(COSARDataset *pDS, unsigned long nRTNBIn)  // :
-    // nBurstNumber(1)
+COSARRasterBand::COSARRasterBand( COSARDataset *pDS, unsigned long nRTNBIn ) :
+    nRTNB(nRTNBIn)
 {
-	this->nRTNB = nRTNBIn;
-	nBlockXSize = pDS->GetRasterXSize();
-	nBlockYSize = 1;
-	eDataType = GDT_CInt16;
+        nBlockXSize = pDS->GetRasterXSize();
+        nBlockYSize = 1;
+        eDataType = GDT_CInt16;
 }
 
 CPLErr COSARRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
@@ -135,7 +136,6 @@ CPLErr COSARRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
     return CE_None;
 }
 
-
 /*****************************************************************************
  * COSARDataset Implementation
  *****************************************************************************/
@@ -189,7 +189,6 @@ GDALDataset *COSARDataset::Open( GDALOpenInfo * pOpenInfo ) {
     return pDS;
 }
 
-
 /* register the driver with GDAL */
 void GDALRegister_COSAR()
 
diff --git a/frmts/ctg/ctgdataset.cpp b/frmts/ctg/ctgdataset.cpp
index 77f63bf..8c21115 100644
--- a/frmts/ctg/ctgdataset.cpp
+++ b/frmts/ctg/ctgdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ctgdataset.cpp 32205 2015-12-17 21:57:20Z goatbar $
  *
  * Project:  CTG driver
  * Purpose:  GDALDataset driver for CTG dataset.
@@ -31,7 +30,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ctgdataset.cpp 32205 2015-12-17 21:57:20Z goatbar $");
+CPL_CVSID("$Id: ctgdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 static const int HEADER_LINE_COUNT = 5;
 
@@ -130,8 +129,8 @@ class CTGDataset : public GDALPamDataset
                  CTGDataset();
     virtual     ~CTGDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char* GetProjectionRef();
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char* GetProjectionRef() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -152,14 +151,13 @@ class CTGRasterBand : public GDALPamRasterBand
   public:
 
                 CTGRasterBand( CTGDataset *, int );
-               ~CTGRasterBand();
+    virtual ~CTGRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual char **GetCategoryNames();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual char **GetCategoryNames() override;
 };
 
-
 /************************************************************************/
 /*                           CTGRasterBand()                            */
 /************************************************************************/
@@ -167,8 +165,8 @@ class CTGRasterBand : public GDALPamRasterBand
 CTGRasterBand::CTGRasterBand( CTGDataset *poDSIn, int nBandIn ) :
     papszCategories(NULL)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Int32;
 
@@ -257,7 +255,7 @@ CTGDataset::CTGDataset() :
     pszProjection(NULL),
     bHasReadImagery(FALSE),
     pabyImage(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                            ~CTGDataset()                            */
@@ -268,7 +266,7 @@ CTGDataset::~CTGDataset()
 {
     CPLFree(pszProjection);
     CPLFree(pabyImage);
-    if (fp != NULL)
+    if( fp != NULL )
         VSIFCloseL(fp);
 }
 
@@ -411,7 +409,6 @@ int CTGDataset::Identify( GDALOpenInfo * poOpenInfo )
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
diff --git a/frmts/dds/ddsdataset.cpp b/frmts/dds/ddsdataset.cpp
index bae2e4b..6e232a0 100644
--- a/frmts/dds/ddsdataset.cpp
+++ b/frmts/dds/ddsdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: $
  *
  * Project:  DDS Driver
  * Purpose:  Implement GDAL DDS Support
@@ -39,17 +38,18 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ddsdataset.cpp 35986 2016-10-28 05:11:34Z goatbar $");
 
 using namespace crnlib;
 
 enum { DDS_COLOR_TYPE_RGB,
        DDS_COLOR_TYPE_RGB_ALPHA };
 
-
 /************************************************************************/
 /* ==================================================================== */
-/*				DDSDataset				*/
+/*                              DDSDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -63,7 +63,6 @@ public:
                                    void * pProgressData);
 };
 
-
 /************************************************************************/
 /*                             CreateCopy()                             */
 /************************************************************************/
@@ -149,7 +148,7 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
             fmt = cCRNFmtDXT3;
         else if (EQUAL(pszFormat, "dxt5"))
             fmt = cCRNFmtDXT5;
-	else if (EQUAL(pszFormat, "etc1"))
+        else if (EQUAL(pszFormat, "etc1"))
             fmt = cCRNFmtETC1;
         else
         {
@@ -284,10 +283,11 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
             crn_uint32 *pDst_pixels = pixels;
             for (uint y = 0; y < cDXTBlockSize; y++)
             {
-                const uint actual_y = MIN(cDXTBlockSize - 1U, y);
+                const uint actual_y = std::min(cDXTBlockSize - 1U, y);
                 for (uint x = 0; x < cDXTBlockSize; x++)
                 {
-                    const uint actual_x = MIN(nXSize - 1U, (block_x * cDXTBlockSize) + x);
+                    const uint actual_x =
+                        std::min(nXSize - 1U, (block_x * cDXTBlockSize) + x);
                     *pDst_pixels++ = pSrc_image[actual_x + actual_y * nXSize];
                 }
             }
@@ -307,7 +307,6 @@ DDSDataset::CreateCopy(const char * pszFilename, GDALDataset *poSrcDS,
             CPLError(CE_Failure, CPLE_UserInterrupt,
                       "User terminated CreateCopy()");
         }
-
     }
 
     CPLFree(src_image);
diff --git a/frmts/derived/GNUmakefile b/frmts/derived/GNUmakefile
new file mode 100644
index 0000000..179f487
--- /dev/null
+++ b/frmts/derived/GNUmakefile
@@ -0,0 +1,11 @@
+
+include ../../GDALmake.opt
+
+OBJ	=	deriveddataset.o derivedlist.o
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/derived/deriveddataset.cpp b/frmts/derived/deriveddataset.cpp
new file mode 100644
index 0000000..5cea7f0
--- /dev/null
+++ b/frmts/derived/deriveddataset.cpp
@@ -0,0 +1,223 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Implementation of derived subdatasets
+ * Author:   Julien Michel <julien dot michel at cnes dot fr>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016 Julien Michel <julien dot michel at cnes dot fr>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+#include "../vrt/vrtdataset.h"
+#include "gdal_pam.h"
+#include "gdal_proxy.h"
+#include "derivedlist.h"
+
+CPL_CVSID("$Id: deriveddataset.cpp 35885 2016-10-24 06:23:09Z goatbar $");
+
+class DerivedDataset : public VRTDataset
+{
+    public:
+        DerivedDataset( int nXSize, int nYSize );
+       ~DerivedDataset() {};
+
+        static int Identify( GDALOpenInfo * );
+        static GDALDataset *Open( GDALOpenInfo * );
+};
+
+DerivedDataset::DerivedDataset(int nXSize, int nYSize) :
+    VRTDataset(nXSize, nYSize)
+{
+    poDriver = NULL;
+    SetWritable(FALSE);
+}
+
+int DerivedDataset::Identify(GDALOpenInfo * poOpenInfo)
+{
+    /* Try to open original dataset */
+    CPLString filename(poOpenInfo->pszFilename);
+
+    /* DERIVED_SUBDATASET should be first domain */
+    const size_t dsds_pos = filename.find("DERIVED_SUBDATASET:");
+
+    if (dsds_pos != 0)
+    {
+        /* Unable to Open in this case */
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+GDALDataset * DerivedDataset::Open( GDALOpenInfo * poOpenInfo )
+{
+    /* Try to open original dataset */
+    CPLString filename(poOpenInfo->pszFilename);
+
+    /* DERIVED_SUBDATASET should be first domain */
+    const size_t dsds_pos = filename.find("DERIVED_SUBDATASET:");
+    const size_t nPrefixLen = strlen("DERIVED_SUBDATASET:");
+
+    if (dsds_pos != 0)
+    {
+        /* Unable to Open in this case */
+        return NULL;
+    }
+
+    /* Next, we need to now which derived dataset to compute */
+    const size_t alg_pos = filename.find(":",nPrefixLen+1);
+    if (alg_pos == std::string::npos)
+    {
+        /* Unable to Open if we do not find the name of the derived dataset */
+        return NULL;
+    }
+
+    CPLString odDerivedName = filename.substr(nPrefixLen,alg_pos-nPrefixLen);
+
+    CPLDebug("DerivedDataset::Open","Derived dataset requested: %s",odDerivedName.c_str());
+
+    CPLString pixelFunctionName = "";
+    bool datasetFound = false;
+
+    unsigned int nbSupportedDerivedDS(0);
+    GDALDataType type  = GDT_Float64;
+
+    const DerivedDatasetDescription * poDDSDesc = GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
+
+    for(unsigned int derivedId = 0; derivedId<nbSupportedDerivedDS;++derivedId)
+    {
+        if(odDerivedName == poDDSDesc[derivedId].pszDatasetName)
+        {
+            datasetFound = true;
+            pixelFunctionName = poDDSDesc[derivedId].pszPixelFunction;
+            type = GDALGetDataTypeByName(poDDSDesc[derivedId].pszOutputPixelType);
+        }
+    }
+
+    if(!datasetFound)
+    {
+        return NULL;
+    }
+
+    CPLString odFilename = filename.substr(alg_pos+1,filename.size() - alg_pos);
+
+    GDALDataset * poTmpDS = (GDALDataset*)GDALOpen(odFilename, GA_ReadOnly);
+
+    if( poTmpDS == NULL )
+        return NULL;
+
+    int nbBands = poTmpDS->GetRasterCount();
+
+    if(nbBands == 0)
+    {
+        GDALClose(poTmpDS);
+        return NULL;
+    }
+
+    int nRows = poTmpDS->GetRasterYSize();
+    int nCols = poTmpDS->GetRasterXSize();
+
+    DerivedDataset * poDS = new DerivedDataset(nCols,nRows);
+
+    // Transfer metadata
+    poDS->SetMetadata(poTmpDS->GetMetadata());
+
+    // Transfer projection
+    poDS->SetProjection(poTmpDS->GetProjectionRef());
+
+    // Transfer geotransform
+    double padfTransform[6];
+    CPLErr transformOk = poTmpDS->GetGeoTransform(padfTransform);
+
+    if(transformOk == CE_None)
+    {
+        poDS->SetGeoTransform(padfTransform);
+    }
+
+    // Transfer GCPs
+    const char * gcpProjection = poTmpDS->GetGCPProjection();
+    int nbGcps = poTmpDS->GetGCPCount();
+    poDS->SetGCPs(nbGcps,poTmpDS->GetGCPs(),gcpProjection);
+
+    // Map bands
+    for(int nBand = 1; nBand <= nbBands; ++nBand)
+    {
+        VRTDerivedRasterBand *poBand =
+            new VRTDerivedRasterBand(poDS,nBand,type,nCols,nRows);
+        poDS->SetBand(nBand,poBand);
+
+        poBand->SetPixelFunctionName(pixelFunctionName);
+        poBand->SetSourceTransferType(poTmpDS->GetRasterBand(nBand)->GetRasterDataType());
+
+        GDALProxyPoolDataset* proxyDS =
+            new GDALProxyPoolDataset(
+                odFilename,
+                poDS->nRasterXSize,
+                poDS->nRasterYSize,
+                GA_ReadOnly,
+                TRUE);
+        for(int j=0;j<nbBands;++j)
+        {
+            int blockXSize, blockYSize;
+            poTmpDS->GetRasterBand(nBand)->GetBlockSize(&blockXSize,&blockYSize);
+            proxyDS->AddSrcBandDescription(poTmpDS->GetRasterBand(nBand)->GetRasterDataType(), blockXSize, blockYSize);
+        }
+
+        poBand->AddComplexSource(proxyDS->GetRasterBand(nBand),0,0,nCols,nRows,0,0,nCols,nRows);
+
+        proxyDS->Dereference();
+    }
+
+    GDALClose(poTmpDS);
+
+    // If dataset is a real file, initialize overview manager
+    VSIStatBufL  sStat;
+    if( VSIStatL( odFilename, &sStat ) == 0 )
+    {
+        CPLString path = CPLGetPath(odFilename);
+        CPLString ovrFileName = "DERIVED_DATASET_"+odDerivedName+"_"+CPLGetFilename(odFilename);
+        CPLString ovrFilePath = CPLFormFilename(path,ovrFileName,NULL);
+
+        poDS->oOvManager.Initialize( poDS, ovrFilePath );
+    }
+
+    return poDS;
+}
+
+void GDALRegister_Derived()
+{
+    if( GDALGetDriverByName( "DERIVED" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "DERIVED" );
+#ifdef GDAL_DCAP_RASTER
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+#endif
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Derived datasets using VRT pixel functions" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_derived.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "NO" );
+
+    poDriver->pfnOpen = DerivedDataset::Open;
+    poDriver->pfnIdentify = DerivedDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/derived/derivedlist.c b/frmts/derived/derivedlist.c
new file mode 100644
index 0000000..cb6eb4a
--- /dev/null
+++ b/frmts/derived/derivedlist.c
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Implementation of derived subdatasets
+ * Author:   Julien Michel <julien dot michel at cnes dot fr>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016 Julien Michel <julien dot michel at cnes dot fr>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+#include "derivedlist.h"
+#include "gdal.h"
+
+CPL_C_START
+
+static const DerivedDatasetDescription asDDSDesc [] =
+{
+  { "AMPLITUDE", "Amplitude of input bands", "mod", "complex","Float64"},
+  { "PHASE", "Phase of input bands", "phase", "complex","Float64"},
+  { "REAL", "Real part of input bands", "real", "complex","Float64"},
+  { "IMAG", "Imaginary part of input bands", "imag", "complex","Float64"},
+  { "CONJ", "Conjugate of input bands", "conj", "complex","CFloat64"},
+  { "INTENSITY", "Intensity (squared amplitude) of input bands", "intensity", "complex","Float64"},
+  { "LOGAMPLITUDE", "log10 of amplitude of input bands", "log10", "all","Float64"}
+};
+
+#define NB_DERIVED_DATASETS (sizeof(asDDSDesc)/sizeof(asDDSDesc[0]))
+
+const DerivedDatasetDescription* CPL_STDCALL GDALGetDerivedDatasetDescriptions(unsigned int * pnDescriptionCount)
+{
+  *pnDescriptionCount = (unsigned int)NB_DERIVED_DATASETS;
+  return asDDSDesc;
+}
+
+CPL_C_END
diff --git a/frmts/derived/derivedlist.h b/frmts/derived/derivedlist.h
new file mode 100644
index 0000000..ef8afad
--- /dev/null
+++ b/frmts/derived/derivedlist.h
@@ -0,0 +1,48 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Implementation of derived subdatasets
+ * Author:   Julien Michel <julien dot michel at cnes dot fr>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016 Julien Michel <julien dot michel at cnes dot fr>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+#ifndef DERIVEDLIST_H_INCLUDED
+#define DERIVEDLIST_H_INCLUDED
+
+#include "cpl_port.h"
+
+CPL_C_START
+
+typedef struct
+{
+  const char * pszDatasetName;
+  const char * pszDatasetDescription;
+  const char * pszPixelFunction;
+  const char * pszInputPixelType;
+  const char * pszOutputPixelType;
+} DerivedDatasetDescription;
+
+const DerivedDatasetDescription CPL_DLL * CPL_STDCALL GDALGetDerivedDatasetDescriptions(unsigned int * pnDescriptionCount);
+
+CPL_C_END
+
+#endif
diff --git a/frmts/derived/frmt_derived.html b/frmts/derived/frmt_derived.html
new file mode 100644
index 0000000..0f5f77e
--- /dev/null
+++ b/frmts/derived/frmt_derived.html
@@ -0,0 +1,236 @@
+<html>
+<head>
+<title>DERIVED -- Derived subdatasets driver</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>DERIVED -- Derived subdatasets driver</h1>
+
+<p> This driver allows to access to subdatasets derived from a given
+dataset. Those derived datasets have the same projection reference,
+geo-transform and metadata than the original dataset, but derives new
+pixel values using gdal pixel functions.</p>
+
+<h2> Available functions</h2>
+
+<p>Available derived datasets are:
+  <ul>
+    <li>AMPLITUDE: Amplitude of pixels from input bands</li>
+    <li>PHASE: Phase of pixels from input bands</li>
+    <li>REAL: Real part of pixels from input bands</li>
+    <li>IMAG: Imaginary part of pixels from input bands</li>
+    <li>CONJ: Conjugate of pixels from input bands</li>
+    <li>INTENSITY: Intensity (squared amplitude) of pixels from input bands</li>
+    <li>LOGAMPLITUDE: Log10 of amplitude of pixels from input bands</li>
+  </ul>
+  </p>
+
+<p> A typical use is to directly access amplitude, phase or log-amplitude of any complex dataset.</p>
+
+<h2> Accessing derived subdatasets </h2>
+
+<p> Derived subdatasets are stored in the DERIVED_SUBDATASETS metadata domain, and can be accessed using the following syntax:
+</p>
+
+<pre>
+  DERIVED_SUBDATASET:FUNCTION:dataset_name
+</pre>
+
+<p> where function is one of AMPLITUDE, PHASE, REAL, IMAG, CONJ, INTENSITY, LOGAMPLITUDE. So as to ensure numerical precision, all derived subdatasets bands will have Float64 or CFloat64 precision (depending on the function used).</p>
+
+<p> For instance: <p>
+<pre>
+  $ gdalinfo cint_sar.tif
+</pre>
+
+<pre>
+Driver: GTiff/GeoTIFF
+Files: cint_sar.tif
+Size is 5, 6
+Coordinate System is `'
+GCP Projection =
+GEOGCS["WGS 84",
+    DATUM["WGS_1984",
+        SPHEROID["WGS 84",6378137,298.257223563,
+            AUTHORITY["EPSG","7030"]],
+        AUTHORITY["EPSG","6326"]],
+    PRIMEM["Greenwich",0],
+    UNIT["degree",0.0174532925199433],
+    AUTHORITY["EPSG","4326"]]
+GCP[  0]: Id=1, Info=
+          (-1910.5,-7430.5) -> (297.507,16.368,0)
+GCP[  1]: Id=2, Info=
+          (588.5,-7430.5) -> (297.938,16.455,0)
+GCP[  2]: Id=3, Info=
+          (588.5,7363.5) -> (297.824,16.977,0)
+GCP[  3]: Id=4, Info=
+          (-1910.5,7363.5) -> (297.393,16.89,0)
+Metadata:
+  AREA_OR_POINT=Area
+  CEOS_ACQUISITION_TIME=19970718024119087
+  CEOS_ELLIPSOID=GEM6
+  CEOS_INC_ANGLE=24.824
+  CEOS_LINE_SPACING_METERS=3.9900000
+  CEOS_LOGICAL_VOLUME_ID=0001667400297672
+  CEOS_PIXEL_SPACING_METERS=7.9040000
+  CEOS_PIXEL_TIME_DIR=INCREASE
+  CEOS_PLATFORM_HEADING=347.339
+  CEOS_PLATFORM_LATITUDE=16.213
+  CEOS_PLATFORM_LONGITUDE=-65.311
+  CEOS_PROCESSING_AGENCY=ESA
+  CEOS_PROCESSING_COUNTRY=ITALY
+  CEOS_PROCESSING_FACILITY=ES
+  CEOS_SEMI_MAJOR=6378.1440000
+  CEOS_SEMI_MINOR=6356.7590000
+  CEOS_SENSOR_CLOCK_ANGLE=90.000
+  CEOS_SOFTWARE_ID=ERS2-SLC-6.1
+  CEOS_TRUE_HEADING=345.5885834
+Image Structure Metadata:
+  INTERLEAVE=BAND
+Corner Coordinates:
+Upper Left  (    0.0,    0.0)
+Lower Left  (    0.0,    6.0)
+Upper Right (    5.0,    0.0)
+Lower Right (    5.0,    6.0)
+Center      (    2.5,    3.0)
+Band 1 Block=5x6 Type=CInt16, ColorInterp=Gray
+</pre>
+
+<pre>
+  $ gdalinfo DERIVED_SUBDATASET:LOGAMPLITUDE:cint_sar.tif</pre>
+<pre>
+Driver: DERIVED/Derived datasets using VRT pixel functions
+Files: cint_sar.tif
+Size is 5, 6
+Coordinate System is `'
+GCP Projection =
+GEOGCS["WGS 84",
+    DATUM["WGS_1984",
+        SPHEROID["WGS 84",6378137,298.257223563,
+            AUTHORITY["EPSG","7030"]],
+        AUTHORITY["EPSG","6326"]],
+    PRIMEM["Greenwich",0],
+    UNIT["degree",0.0174532925199433],
+    AUTHORITY["EPSG","4326"]]
+GCP[  0]: Id=1, Info=
+          (-1910.5,-7430.5) -> (297.507,16.368,0)
+GCP[  1]: Id=2, Info=
+          (588.5,-7430.5) -> (297.938,16.455,0)
+GCP[  2]: Id=3, Info=
+          (588.5,7363.5) -> (297.824,16.977,0)
+GCP[  3]: Id=4, Info=
+          (-1910.5,7363.5) -> (297.393,16.89,0)
+Metadata:
+  AREA_OR_POINT=Area
+  CEOS_ACQUISITION_TIME=19970718024119087
+  CEOS_ELLIPSOID=GEM6
+  CEOS_INC_ANGLE=24.824
+  CEOS_LINE_SPACING_METERS=3.9900000
+  CEOS_LOGICAL_VOLUME_ID=0001667400297672
+  CEOS_PIXEL_SPACING_METERS=7.9040000
+  CEOS_PIXEL_TIME_DIR=INCREASE
+  CEOS_PLATFORM_HEADING=347.339
+  CEOS_PLATFORM_LATITUDE=16.213
+  CEOS_PLATFORM_LONGITUDE=-65.311
+  CEOS_PROCESSING_AGENCY=ESA
+  CEOS_PROCESSING_COUNTRY=ITALY
+  CEOS_PROCESSING_FACILITY=ES
+  CEOS_SEMI_MAJOR=6378.1440000
+  CEOS_SEMI_MINOR=6356.7590000
+  CEOS_SENSOR_CLOCK_ANGLE=90.000
+  CEOS_SOFTWARE_ID=ERS2-SLC-6.1
+  CEOS_TRUE_HEADING=345.5885834
+Corner Coordinates:
+Upper Left  (    0.0,    0.0)
+Lower Left  (    0.0,    6.0)
+Upper Right (    5.0,    0.0)
+Lower Right (    5.0,    6.0)
+Center      (    2.5,    3.0)
+Band 1 Block=5x6 Type=Float64, ColorInterp=Undefined
+</pre>
+
+<h2> Listing available subdatasets </h2>
+
+<p> Available subdatasets are reported in the DERIVED_SUBDATASETS metadata domain. Only functions that make sense will be reported for a given dataset, which means that AMPLITUDE, PHASE, REAL, IMAG, CONJ and INTENSITY will only be reported if the dataset has at least one complex band. Nevertheless, even if not reported, those derived datasets are still reachable with the syntax presented above.
+
+  <pre>
+    $ gdalinfo -mdd DERIVED_SUBDATASETS cint_sar.tif
+  </pre>
+
+<pre>Driver: GTiff/GeoTIFF
+Files: cint_sar.tif
+Size is 5, 6
+Coordinate System is `'
+GCP Projection =
+GEOGCS["WGS 84",
+    DATUM["WGS_1984",
+        SPHEROID["WGS 84",6378137,298.257223563,
+            AUTHORITY["EPSG","7030"]],
+        AUTHORITY["EPSG","6326"]],
+    PRIMEM["Greenwich",0],
+    UNIT["degree",0.0174532925199433],
+    AUTHORITY["EPSG","4326"]]
+GCP[  0]: Id=1, Info=
+          (-1910.5,-7430.5) -> (297.507,16.368,0)
+GCP[  1]: Id=2, Info=
+          (588.5,-7430.5) -> (297.938,16.455,0)
+GCP[  2]: Id=3, Info=
+          (588.5,7363.5) -> (297.824,16.977,0)
+GCP[  3]: Id=4, Info=
+          (-1910.5,7363.5) -> (297.393,16.89,0)
+Metadata:
+  AREA_OR_POINT=Area
+  CEOS_ACQUISITION_TIME=19970718024119087
+  CEOS_ELLIPSOID=GEM6
+  CEOS_INC_ANGLE=24.824
+  CEOS_LINE_SPACING_METERS=3.9900000
+  CEOS_LOGICAL_VOLUME_ID=0001667400297672
+  CEOS_PIXEL_SPACING_METERS=7.9040000
+  CEOS_PIXEL_TIME_DIR=INCREASE
+  CEOS_PLATFORM_HEADING=347.339
+  CEOS_PLATFORM_LATITUDE=16.213
+  CEOS_PLATFORM_LONGITUDE=-65.311
+  CEOS_PROCESSING_AGENCY=ESA
+  CEOS_PROCESSING_COUNTRY=ITALY
+  CEOS_PROCESSING_FACILITY=ES
+  CEOS_SEMI_MAJOR=6378.1440000
+  CEOS_SEMI_MINOR=6356.7590000
+  CEOS_SENSOR_CLOCK_ANGLE=90.000
+  CEOS_SOFTWARE_ID=ERS2-SLC-6.1
+  CEOS_TRUE_HEADING=345.5885834
+Metadata (DERIVED_SUBDATASETS):
+  DERIVED_SUBDATASET_0_NAME=DERIVED_SUBDATASET:AMPLITUDE:cint_sar.tif
+  DERIVED_SUBDATASET_0_DESC=Amplitude of input bands from cint_sar.tif
+  DERIVED_SUBDATASET_1_NAME=DERIVED_SUBDATASET:PHASE:cint_sar.tif
+  DERIVED_SUBDATASET_1_DESC=Phase of input bands from cint_sar.tif
+  DERIVED_SUBDATASET_2_NAME=DERIVED_SUBDATASET:REAL:cint_sar.tif
+  DERIVED_SUBDATASET_2_DESC=Real part of input bands from cint_sar.tif
+  DERIVED_SUBDATASET_3_NAME=DERIVED_SUBDATASET:IMAG:cint_sar.tif
+  DERIVED_SUBDATASET_3_DESC=Imaginary part of input bands from cint_sar.tif
+  DERIVED_SUBDATASET_4_NAME=DERIVED_SUBDATASET:CONJ:cint_sar.tif
+  DERIVED_SUBDATASET_4_DESC=Conjugate of input bands from cint_sar.tif
+  DERIVED_SUBDATASET_5_NAME=DERIVED_SUBDATASET:INTENSITY:cint_sar.tif
+  DERIVED_SUBDATASET_5_DESC=Intensity (squared amplitude) of input bands from cint_sar.tif
+  DERIVED_SUBDATASET_6_NAME=DERIVED_SUBDATASET:LOGAMPLITUDE:cint_sar.tif
+  DERIVED_SUBDATASET_6_DESC=log10 of amplitude of input bands from cint_sar.tif
+Image Structure Metadata:
+  INTERLEAVE=BAND
+Corner Coordinates:
+Upper Left  (    0.0,    0.0)
+Lower Left  (    0.0,    6.0)
+Upper Right (    5.0,    0.0)
+Lower Right (    5.0,    6.0)
+Center      (    2.5,    3.0)
+Band 1 Block=5x6 Type=CInt16, ColorInterp=Gray
+</pre>
+
+<h2>See Also:</h2>
+
+<ul>
+    <li><a href="http://gdal.org/gdal_vrttut.html#gdal_vrttut_creation">Using Derived Bands part of the GDAL VRT tutorial</a></li>
+</ul>
+
+
+</body>
+</html>
diff --git a/frmts/derived/makefile.vc b/frmts/derived/makefile.vc
new file mode 100644
index 0000000..9a2d14a
--- /dev/null
+++ b/frmts/derived/makefile.vc
@@ -0,0 +1,13 @@
+
+OBJ = deriveddataset.obj derivedlist.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/dimap/GNUmakefile b/frmts/dimap/GNUmakefile
index 80bfbfe..8216f4f 100644
--- a/frmts/dimap/GNUmakefile
+++ b/frmts/dimap/GNUmakefile
@@ -2,10 +2,12 @@ include ../../GDALmake.opt
 
 OBJ	=	dimapdataset.o
 
-
+CPPFLAGS        :=      -I../vrt  $(CPPFLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
+$(OBJ) $(O_OBJ):	 ../vrt/vrtdataset.h
+
 clean:
 	rm -f *.o $(O_OBJ)
 
diff --git a/frmts/dimap/dimapdataset.cpp b/frmts/dimap/dimapdataset.cpp
index a923f20..5e53d21 100644
--- a/frmts/dimap/dimapdataset.cpp
+++ b/frmts/dimap/dimapdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id $
  *
  * Project:  SPOT Dimap Driver
  * Purpose:  Implementation of SPOT Dimap driver.
@@ -35,8 +34,11 @@
 #include "gdal_pam.h"
 #include "gdal_proxy.h"
 #include "ogr_spatialref.h"
+#include "mdreader/reader_pleiades.h"
+#include "vrtdataset.h"
+#include <map>
 
-CPL_CVSID("$Id: dimapdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: dimapdataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -48,10 +50,11 @@ class DIMAPDataset : public GDALPamDataset
 {
     CPLXMLNode *psProduct;
 
-    CPLXMLNode *psProductDim; /* DIMAP2, DIM_<product_id>.XML */
-    CPLXMLNode *psProductStrip; /* DIMAP2, STRIP_<product_id>.XML */
+    CPLXMLNode *psProductDim;  // DIMAP2, DIM_<product_id>.XML
+    CPLXMLNode *psProductStrip;  // DIMAP2, STRIP_<product_id>.XML
+    CPLString   osRPCFilename;  // DIMAP2, RPC_<product_id>.XML
 
-    GDALDataset   *poImageDS;
+    VRTDataset    *poVRTDS;
 
     int           nGCPCount;
     GDAL_GCP      *pasGCPList;
@@ -70,24 +73,26 @@ class DIMAPDataset : public GDALPamDataset
     char          **papszXMLDimapMetadata;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
     int ReadImageInformation();
-    int ReadImageInformation2(); /* DIMAP 2 */
+    int ReadImageInformation2();  // DIMAP 2.
+
+    void SetMetadataFromXML( CPLXMLNode *psProduct,
+                             const char * const apszMetadataTranslation[] );
 
-    void SetMetadataFromXML(CPLXMLNode *psProduct, const char * const apszMetadataTranslation[]);
   public:
             DIMAPDataset();
-            ~DIMAPDataset();
+    virtual ~DIMAPDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-    virtual char      **GetMetadataDomainList();
-    virtual char **GetMetadata( const char *pszDomain );
-    virtual char **GetFileList(void);
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
+    virtual char      **GetMetadataDomainList() override;
+    virtual char **GetMetadata( const char *pszDomain ) override;
+    virtual char **GetFileList(void) override;
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
@@ -97,27 +102,6 @@ class DIMAPDataset : public GDALPamDataset
 
 /************************************************************************/
 /* ==================================================================== */
-/*                        DIMAPWrapperRasterBand                        */
-/* ==================================================================== */
-/************************************************************************/
-class DIMAPWrapperRasterBand : public GDALProxyRasterBand
-{
-  GDALRasterBand* poBaseBand;
-
-  protected:
-    virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
-
-  public:
-    DIMAPWrapperRasterBand( GDALRasterBand* poBaseBandIn )
-        {
-            this->poBaseBand = poBaseBandIn;
-            eDataType = poBaseBand->GetRasterDataType();
-            poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
-        }
-    ~DIMAPWrapperRasterBand() {}
-};
-/************************************************************************/
-/* ==================================================================== */
 /*                              DIMAPDataset                            */
 /* ==================================================================== */
 /************************************************************************/
@@ -130,14 +114,20 @@ DIMAPDataset::DIMAPDataset() :
     psProduct(NULL),
     psProductDim(NULL),
     psProductStrip(NULL),
-    poImageDS(NULL),
+    poVRTDS(NULL),
     nGCPCount(0),
     pasGCPList(NULL),
+    pszGCPProjection(CPLStrdup("")),
     bHaveGeoTransform(FALSE),
     nProductVersion(1),
     papszXMLDimapMetadata(NULL)
 {
-    pszGCPProjection = CPLStrdup("");
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 0.0;
 }
 
 /************************************************************************/
@@ -155,7 +145,6 @@ DIMAPDataset::~DIMAPDataset()
         CPLDestroyXMLNode( psProductDim );
     if( psProductStrip != NULL )
         CPLDestroyXMLNode( psProductStrip );
-
     CPLFree( pszGCPProjection );
     if( nGCPCount > 0 )
     {
@@ -168,7 +157,6 @@ DIMAPDataset::~DIMAPDataset()
     CloseDependentDatasets();
 }
 
-
 /************************************************************************/
 /*                        CloseDependentDatasets()                      */
 /************************************************************************/
@@ -177,21 +165,13 @@ int DIMAPDataset::CloseDependentDatasets()
 {
     int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
 
-    if( poImageDS != NULL )
+    if( poVRTDS != NULL )
     {
-        delete poImageDS;
-        poImageDS = NULL;
+        delete poVRTDS;
+        poVRTDS = NULL;
         bHasDroppedRef = TRUE;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Disconnect the bands so our destructor doesn't try and          */
-/*      delete them since they really belonged to poImageDS.            */
-/* -------------------------------------------------------------------- */
-    for( int iBand = 0; iBand < nBands; iBand++ )
-        delete papoBands[iBand];
-    nBands = 0;
-
     return bHasDroppedRef;
 }
 
@@ -218,9 +198,10 @@ char **DIMAPDataset::GetMetadata( const char *pszDomain )
 {
     if( pszDomain && EQUAL(pszDomain,"xml:dimap") )
     {
-        if (papszXMLDimapMetadata == NULL)
+        if( papszXMLDimapMetadata == NULL )
         {
-            papszXMLDimapMetadata = (char **) CPLCalloc(sizeof(char*),2);
+            papszXMLDimapMetadata = reinterpret_cast<char **>(
+                CPLCalloc(sizeof(char*), 2) );
             papszXMLDimapMetadata[0] = CPLSerializeXMLTree( psProduct );
         }
         return papszXMLDimapMetadata;
@@ -236,7 +217,7 @@ char **DIMAPDataset::GetMetadata( const char *pszDomain )
 const char *DIMAPDataset::GetProjectionRef()
 
 {
-    if( strlen(osProjection) > 0 )
+    if( !osProjection.empty() )
         return osProjection;
 
     return GDALPamDataset::GetProjectionRef();
@@ -266,7 +247,7 @@ char **DIMAPDataset::GetFileList()
 
 {
     char **papszFileList = GDALPamDataset::GetFileList();
-    char **papszImageFiles = poImageDS->GetFileList();
+    char **papszImageFiles = poVRTDS->GetFileList();
 
     papszFileList = CSLInsertStrings( papszFileList, -1, papszImageFiles );
 
@@ -276,6 +257,173 @@ char **DIMAPDataset::GetFileList()
 }
 
 /************************************************************************/
+/* ==================================================================== */
+/*                            DIMAPRasterBand                           */
+/* ==================================================================== */
+/************************************************************************/
+
+class DIMAPRasterBand : public GDALPamRasterBand
+{
+    friend class DIMAPDataset;
+
+    VRTSourcedRasterBand *poVRTBand;
+
+  public:
+                   DIMAPRasterBand( DIMAPDataset *, int, VRTSourcedRasterBand * );
+    virtual       ~DIMAPRasterBand() {};
+
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GDALRasterIOExtraArg* psExtraArg ) override;
+    virtual int GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview( int ) override;
+    virtual CPLErr ComputeRasterMinMax( int bApproxOK,
+                                        double adfMinMax[2] ) override;
+    virtual CPLErr ComputeStatistics( int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
+                                      double *pdfMean, double *pdfStdDev,
+                                      GDALProgressFunc, void *pProgressData ) override;
+
+    virtual CPLErr  GetHistogram( double dfMin, double dfMax,
+                                  int nBuckets, GUIntBig * panHistogram,
+                                  int bIncludeOutOfRange, int bApproxOK,
+                                  GDALProgressFunc, void *pProgressData ) override;
+};
+
+/************************************************************************/
+/*                          DIMAPRasterBand()                           */
+/************************************************************************/
+
+DIMAPRasterBand::DIMAPRasterBand( DIMAPDataset *poDIMAPDS, int nBandIn,
+                                  VRTSourcedRasterBand *poVRTBandIn ) :
+    poVRTBand(poVRTBandIn)
+{
+    poDS = poDIMAPDS;
+    nBand = nBandIn;
+    eDataType = poVRTBandIn->GetRasterDataType();
+
+    poVRTBandIn->GetBlockSize( &nBlockXSize, &nBlockYSize );
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr DIMAPRasterBand::IReadBlock( int iBlockX, int iBlockY, void *pBuffer )
+
+{
+    return poVRTBand->ReadBlock( iBlockX, iBlockY, pBuffer );
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr DIMAPRasterBand::IRasterIO( GDALRWFlag eRWFlag,
+                                   int nXOff, int nYOff, int nXSize, int nYSize,
+                                   void * pData, int nBufXSize, int nBufYSize,
+                                   GDALDataType eBufType,
+                                   GSpacing nPixelSpace, GSpacing nLineSpace,
+                                   GDALRasterIOExtraArg* psExtraArg )
+
+{
+    if( GDALPamRasterBand::GetOverviewCount() > 0 )
+    {
+        return GDALPamRasterBand::IRasterIO(
+            eRWFlag, nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize, eBufType,
+            nPixelSpace, nLineSpace, psExtraArg );
+    }
+
+    // If not exist DIMAP overviews, try to use band source overviews.
+    return poVRTBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                 pData, nBufXSize, nBufYSize, eBufType,
+                                 nPixelSpace, nLineSpace, psExtraArg );
+}
+
+/************************************************************************/
+/*                          GetOverviewCount()                          */
+/************************************************************************/
+
+int DIMAPRasterBand::GetOverviewCount()
+{
+    if( GDALPamRasterBand::GetOverviewCount() > 0 )
+    {
+        return GDALPamRasterBand::GetOverviewCount();
+    }
+    return poVRTBand->GetOverviewCount();
+}
+
+/************************************************************************/
+/*                             GetOverview()                            */
+/************************************************************************/
+
+GDALRasterBand *DIMAPRasterBand::GetOverview( int iOvr )
+{
+    if( GDALPamRasterBand::GetOverviewCount() > 0 )
+    {
+        return GDALPamRasterBand::GetOverview(iOvr);
+    }
+    return poVRTBand->GetOverview(iOvr);
+}
+
+/************************************************************************/
+/*                         ComputeRasterMinMax()                        */
+/************************************************************************/
+
+CPLErr DIMAPRasterBand::ComputeRasterMinMax( int bApproxOK,
+                                            double adfMinMax[2] )
+{
+    if( GDALPamRasterBand::GetOverviewCount() > 0 )
+    {
+        return GDALPamRasterBand::ComputeRasterMinMax(bApproxOK, adfMinMax);
+    }
+    return poVRTBand->ComputeRasterMinMax(bApproxOK, adfMinMax);
+}
+
+/************************************************************************/
+/*                          ComputeStatistics()                         */
+/************************************************************************/
+
+CPLErr DIMAPRasterBand::ComputeStatistics( int bApproxOK,
+                                           double *pdfMin, double *pdfMax,
+                                           double *pdfMean, double *pdfStdDev,
+                                           GDALProgressFunc pfnProgress,
+                                           void *pProgressData )
+{
+    if( GDALPamRasterBand::GetOverviewCount() > 0 )
+    {
+        return GDALPamRasterBand::ComputeStatistics(
+            bApproxOK, pdfMin, pdfMax, pdfMean, pdfStdDev,
+            pfnProgress, pProgressData);
+    }
+    return poVRTBand->ComputeStatistics(bApproxOK, pdfMin, pdfMax, pdfMean,
+                                        pdfStdDev, pfnProgress, pProgressData);
+}
+
+/************************************************************************/
+/*                            GetHistogram()                            */
+/************************************************************************/
+
+CPLErr DIMAPRasterBand::GetHistogram( double dfMin, double dfMax,
+                                      int nBuckets, GUIntBig *panHistogram,
+                                      int bIncludeOutOfRange, int bApproxOK,
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData )
+{
+    if( GDALPamRasterBand::GetOverviewCount() > 0 )
+    {
+        return GDALPamRasterBand::GetHistogram(
+            dfMin, dfMax, nBuckets, panHistogram, bIncludeOutOfRange,
+            bApproxOK, pfnProgress, pProgressData);
+    }
+    return poVRTBand->GetHistogram(dfMin, dfMax, nBuckets, panHistogram,
+            bIncludeOutOfRange, bApproxOK, pfnProgress, pProgressData);
+}
+
+/************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
 
@@ -284,28 +432,28 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
 {
     if( poOpenInfo->nHeaderBytes >= 100 )
     {
-      if( ( strstr((const char *) poOpenInfo->pabyHeader,
-                   "<Dimap_Document" ) == NULL ) &&
-          ( strstr((const char *) poOpenInfo->pabyHeader,
-                   "<PHR_DIMAP_Document" ) == NULL ) )
+        if( ( strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
+                     "<Dimap_Document" ) == NULL ) &&
+            ( strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
+                     "<PHR_DIMAP_Document" ) == NULL ) )
             return FALSE;
-        else
-            return TRUE;
+
+        return TRUE;
     }
     else if( poOpenInfo->bIsDirectory )
     {
-        /* DIMAP file */
+        // DIMAP file.
         CPLString osMDFilename =
             CPLFormCIFilename( poOpenInfo->pszFilename, "METADATA.DIM", NULL );
 
         VSIStatBufL sStat;
         if( VSIStatL( osMDFilename, &sStat ) == 0 )
         {
-            /* Make sure this is really a Dimap format */
+            // Make sure this is really a Dimap format.
             GDALOpenInfo  oOpenInfo( osMDFilename, GA_ReadOnly, NULL );
             if( oOpenInfo.nHeaderBytes >= 100 )
             {
-                if( strstr((const char *) oOpenInfo.pabyHeader,
+                if( strstr(reinterpret_cast<char *>(oOpenInfo.pabyHeader),
                            "<Dimap_Document" ) == NULL )
                     return FALSE;
 
@@ -314,9 +462,10 @@ int DIMAPDataset::Identify( GDALOpenInfo * poOpenInfo )
         }
         else
         {
-            /* DIMAP 2 file */
+            // DIMAP 2 file.
             osMDFilename =
-                    CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
+                CPLFormCIFilename( poOpenInfo->pszFilename,
+                                   "VOL_PHR.XML", NULL );
 
             if( VSIStatL( osMDFilename, &sStat ) == 0 )
                     return TRUE;
@@ -344,14 +493,14 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->eAccess == GA_Update )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "The DIMAP driver does not support update access to existing"
-                  " datasets.\n" );
+                  "The DIMAP driver does not support update access to existing "
+                  " datasets." );
         return NULL;
     }
 /* -------------------------------------------------------------------- */
 /*      Get the metadata filename.                                      */
 /* -------------------------------------------------------------------- */
-    CPLString osMDFilename, osImageDSFilename, osDIMAPFilename;
+    CPLString osMDFilename;
 
     if( poOpenInfo->bIsDirectory )
     {
@@ -366,13 +515,13 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
                 CPLFormCIFilename( poOpenInfo->pszFilename, "VOL_PHR.XML", NULL );
     }
     else
+    {
         osMDFilename = poOpenInfo->pszFilename;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Ingest the xml file.                                            */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psProductDim = NULL, *psProductStrip = NULL;
-
     CPLXMLNode *psProduct = CPLParseXMLFile( osMDFilename );
     if( psProduct == NULL )
         return NULL;
@@ -381,68 +530,71 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
     if( !psDoc )
         psDoc = CPLGetXMLNode( psProduct, "=PHR_DIMAP_Document" );
 
-    /* We check the for the tag Metadata_Identification.METADATA_FORMAT.
-    *  The metadata will be set to 2.0 for DIMAP2 */
-    int nProductVersion = 1;
-
-    double dfMetadataFormatVersion
-        = CPLAtof( CPLGetXMLValue(
+    // We check the for the tag Metadata_Identification.METADATA_FORMAT.
+    // The metadata will be set to 2.0 for DIMAP2.
+    double dfMetadataFormatVersion =
+        CPLAtof( CPLGetXMLValue(
             CPLGetXMLNode(psDoc, "Metadata_Identification.METADATA_FORMAT"),
             "version", "1") );
 
-    if( dfMetadataFormatVersion >= 2.0 )
-    {
-        nProductVersion = 2;
-    }
+    const int nProductVersion = dfMetadataFormatVersion >= 2.0 ? 2 : 1;
 
-    /* Check needed information for the DIMAP format */
-    if (nProductVersion == 1)
+    CPLString osImageDSFilename;
+    CPLString osDIMAPFilename;
+    CPLString osRPCFilename;
+    CPLXMLNode *psProductDim = NULL;
+    CPLXMLNode *psProductStrip = NULL;
+
+    // Check needed information for the DIMAP format.
+    if( nProductVersion == 1 )
     {
-        CPLXMLNode *psImageAttributes
-            = CPLGetXMLNode( psDoc, "Raster_Dimensions" );
+        CPLXMLNode *psImageAttributes =
+            CPLGetXMLNode( psDoc, "Raster_Dimensions" );
         if( psImageAttributes == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                "Failed to find <Raster_Dimensions> in document." );
+                      "Failed to find <Raster_Dimensions> in document." );
             CPLDestroyXMLNode(psProduct);
             return NULL;
         }
     }
-    else /* DIMAP2 */
+    else  // DIMAP2.
     {
-        /* Verify the presence of the DIMAP product file */
-        CPLXMLNode *psDatasetComponents = CPLGetXMLNode(psDoc, "Dataset_Content.Dataset_Components");
+        // Verify the presence of the DIMAP product file.
+        CPLXMLNode *psDatasetComponents =
+            CPLGetXMLNode(psDoc, "Dataset_Content.Dataset_Components");
 
         if( psDatasetComponents == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                "Failed to find <Dataset_Components> in document." );
+                      "Failed to find <Dataset_Components> in document." );
             CPLDestroyXMLNode(psProduct);
             return NULL;
         }
 
-        CPLXMLNode *psDatasetComponent = psDatasetComponents->psChild;
-
         if( CPLGetXMLNode(psDoc, "Raster_Data") )
         {
             osDIMAPFilename = osMDFilename;
         }
 
-        for( ; osDIMAPFilename.size() == 0 && psDatasetComponent != NULL;
-                psDatasetComponent = psDatasetComponent->psNext )
+        for( CPLXMLNode *psDatasetComponent = psDatasetComponents->psChild;
+             osDIMAPFilename.empty() && psDatasetComponent != NULL;
+             psDatasetComponent = psDatasetComponent->psNext )
         {
-            const char* pszComponentType = CPLGetXMLValue(psDatasetComponent, "COMPONENT_TYPE","");
+            const char* pszComponentType =
+                CPLGetXMLValue(psDatasetComponent, "COMPONENT_TYPE","");
             if( strcmp(pszComponentType, "DIMAP") == 0 )
             {
                 const char *pszHref = CPLGetXMLValue(
                         psDatasetComponent, "COMPONENT_PATH.href", "" );
 
-                if( strlen(pszHref) > 0 ) /* DIMAP product found*/
+                if( strlen(pszHref) > 0 )  // DIMAP product found.
                 {
                     if( poOpenInfo->bIsDirectory )
                     {
                         osDIMAPFilename =
-                            CPLFormCIFilename( poOpenInfo->pszFilename, pszHref, NULL );
+                            CPLFormCIFilename( poOpenInfo->pszFilename,
+                                               pszHref, NULL );
                     }
                     else
                     {
@@ -451,9 +603,11 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
                             CPLFormFilename( osPath, pszHref, NULL );
                     }
 
-                    /* Data file might be specified there */
+                    // Data file might be specified there.
                     const char *pszDataFileHref = CPLGetXMLValue(
-                        psDatasetComponent, "Data_Files.Data_File.DATA_FILE_PATH.href", "" );
+                        psDatasetComponent,
+                        "Data_Files.Data_File.DATA_FILE_PATH.href",
+                        "" );
 
                     if( strlen(pszDataFileHref) > 0 )
                     {
@@ -474,26 +628,30 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
         }
 
-        /* We need the STRIP_<product_id>.XML file for a few metadata */
+        // We need the {STRIP|RPC}_<product_id>.XML file for a few metadata.
         CPLXMLNode *psDocDim = CPLGetXMLNode( psProductDim, "=Dimap_Document" );
         if( !psDocDim )
             psDocDim = CPLGetXMLNode( psProductDim, "=PHR_DIMAP_Document" );
 
-        CPLXMLNode *psDatasetSources = CPLGetXMLNode(psDocDim, "Dataset_Sources");
+        CPLXMLNode *psDatasetSources =
+            CPLGetXMLNode(psDocDim, "Dataset_Sources");
         if( psDatasetSources != NULL )
         {
             CPLString osSTRIPFilename;
-            CPLXMLNode *psDatasetSource = psDatasetSources->psChild;
 
-            for( ; psDatasetSource != NULL; psDatasetSource = psDatasetSource->psNext )
+            for( CPLXMLNode *psDatasetSource = psDatasetSources->psChild;
+                 psDatasetSource != NULL;
+                 psDatasetSource = psDatasetSource->psNext )
             {
-                const char* pszSourceType = CPLGetXMLValue(psDatasetSource, "SOURCE_TYPE","");
+                const char* pszSourceType =
+                    CPLGetXMLValue(psDatasetSource, "SOURCE_TYPE","");
                 if( strcmp(pszSourceType, "Strip_Source") == 0 )
                 {
                     const char *pszHref = CPLGetXMLValue(
-                        psDatasetSource, "Component.COMPONENT_PATH.href", "" );
+                        psDatasetSource, "Component.COMPONENT_PATH.href",
+                        "" );
 
-                    if( strlen(pszHref) > 0 ) /* STRIP product found*/
+                    if( strlen(pszHref) > 0 )  // STRIP product found.
                     {
                         CPLString osPath = CPLGetPath(osDIMAPFilename);
                         osSTRIPFilename =
@@ -506,6 +664,36 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
             psProductStrip = CPLParseXMLFile( osSTRIPFilename );
         }
+
+        CPLXMLNode *psDatasetRFMComponents =
+            CPLGetXMLNode(
+                psDocDim,
+                "Geoposition.Geoposition_Models.Rational_Function_Model");
+        if( psDatasetRFMComponents != NULL )
+        {
+           for( CPLXMLNode *psDatasetRFMComponent =
+                    psDatasetRFMComponents->psChild;
+                psDatasetRFMComponent != NULL;
+                psDatasetRFMComponent = psDatasetRFMComponent->psNext )
+           {
+              const char* pszComponentTitle =
+                  CPLGetXMLValue(psDatasetRFMComponent, "COMPONENT_TITLE", "");
+              if( strcmp(pszComponentTitle, "RPC Model") == 0 )
+              {
+                 const char *pszHref = CPLGetXMLValue(
+                     psDatasetRFMComponent, "COMPONENT_PATH.href", "");
+
+                 if( strlen(pszHref) > 0 )  // RPC product found.
+                 {
+                    CPLString osPath = CPLGetPath(osDIMAPFilename);
+                    osRPCFilename =
+                       CPLFormCIFilename(osPath, pszHref, NULL);
+
+                    break;
+                 }
+              }
+           }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -516,16 +704,15 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->psProduct = psProduct;
     poDS->psProductDim = psProductDim;
     poDS->psProductStrip = psProductStrip;
+    poDS->osRPCFilename = osRPCFilename;
     poDS->nProductVersion = nProductVersion;
     poDS->osMDFilename = osMDFilename;
     poDS->osImageDSFilename = osImageDSFilename;
     poDS->osDIMAPFilename = osDIMAPFilename;
 
-    int res = TRUE;
-    if( nProductVersion == 2 )
-        res = poDS->ReadImageInformation2();
-    else
-        res = poDS->ReadImageInformation();
+    const int res = (nProductVersion == 2) ?
+        poDS->ReadImageInformation2() :
+        poDS->ReadImageInformation();
 
     if( res == FALSE )
     {
@@ -533,10 +720,9 @@ GDALDataset *DIMAPDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    return( poDS );
+    return poDS;
 }
 
-
 /************************************************************************/
 /*               ReadImageInformation() DIMAP Version 1                 */
 /************************************************************************/
@@ -547,20 +733,11 @@ int DIMAPDataset::ReadImageInformation()
     if( !psDoc )
         psDoc = CPLGetXMLNode( psProduct, "=PHR_DIMAP_Document" );
 
-    CPLXMLNode *psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Dimensions" );
-
 /* -------------------------------------------------------------------- */
 /*      Get overall image information.                                  */
 /* -------------------------------------------------------------------- */
-#ifdef DEBUG
-    int l_nBands =
-        atoi(CPLGetXMLValue( psImageAttributes, "NBANDS", "-1" ));
-#endif
 
-    nRasterXSize =
-        atoi(CPLGetXMLValue( psImageAttributes, "NCOLS", "-1" ));
-    nRasterYSize =
-        atoi(CPLGetXMLValue( psImageAttributes, "NROWS", "-1" ));
+    // TODO: DIMAP 1 probably handle mosaics? Like DIMAP 2?
 
 /* -------------------------------------------------------------------- */
 /*      Get the name of the underlying file.                            */
@@ -576,19 +753,66 @@ int DIMAPDataset::ReadImageInformation()
 /*      Try and open the file.                                          */
 /* -------------------------------------------------------------------- */
 
-    poImageDS = (GDALDataset *) GDALOpen( osImageFilename, GA_ReadOnly );
+    GDALDataset* poImageDS =
+        static_cast<GDALDataset *>( GDALOpen( osImageFilename, GA_ReadOnly ) );
     if( poImageDS == NULL )
     {
         return FALSE;
     }
+    nRasterXSize = poImageDS->GetRasterXSize();
+    nRasterYSize = poImageDS->GetRasterYSize();
 
 /* -------------------------------------------------------------------- */
-/*      Attach the bands.                                               */
+/*      Create and initialize the corresponding VRT dataset used to     */
+/*      manage the tiled data access.                                   */
 /* -------------------------------------------------------------------- */
-    CPLAssert( l_nBands == poImageDS->GetRasterCount() );
+    poVRTDS = new VRTDataset(nRasterXSize,nRasterYSize);
+
+    // Don't try to write a VRT file.
+    poVRTDS->SetWritable(FALSE);
 
-    for( int iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
-        SetBand( iBand, new DIMAPWrapperRasterBand(poImageDS->GetRasterBand( iBand )) );
+    GDALDataset *poTileDS =
+          new GDALProxyPoolDataset( osImageFilename, nRasterXSize, nRasterYSize,
+                                    GA_ReadOnly, TRUE );
+
+    for( int iBand = 0; iBand < poImageDS->GetRasterCount(); iBand++ )
+    {
+        poVRTDS->AddBand(
+            poImageDS->GetRasterBand(iBand+1)->GetRasterDataType(), NULL );
+
+        reinterpret_cast<GDALProxyPoolDataset *>( poTileDS )->
+            AddSrcBandDescription(
+                poImageDS->GetRasterBand(iBand+1)->GetRasterDataType(),
+                nRasterXSize, 1 );
+
+        GDALRasterBand *poSrcBand = poTileDS->GetRasterBand(iBand+1);
+
+        VRTSourcedRasterBand *poVRTBand =
+            reinterpret_cast<VRTSourcedRasterBand *>(
+                poVRTDS->GetRasterBand(iBand+1) );
+
+        poVRTBand->AddSimpleSource( poSrcBand,
+                                    0, 0,
+                                    nRasterXSize, nRasterYSize,
+                                    0, 0,
+                                    nRasterXSize, nRasterYSize );
+    }
+
+    poTileDS->Dereference();
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 1; iBand <= poVRTDS->GetRasterCount(); iBand++ )
+    {
+        SetBand(
+            iBand,
+            new DIMAPRasterBand(
+                this,
+                iBand,
+                static_cast<VRTSourcedRasterBand*>(
+                    poVRTDS->GetRasterBand(iBand)) ) );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Try to collect simple insertion point.                          */
@@ -599,17 +823,17 @@ int DIMAPDataset::ReadImageInformation()
     if( psGeoLoc != NULL )
     {
         bHaveGeoTransform = TRUE;
-        adfGeoTransform[0] = CPLAtof(CPLGetXMLValue(psGeoLoc,"ULXMAP","0"));
-        adfGeoTransform[1] = CPLAtof(CPLGetXMLValue(psGeoLoc,"XDIM","0"));
+        adfGeoTransform[0] = CPLAtof(CPLGetXMLValue(psGeoLoc, "ULXMAP", "0"));
+        adfGeoTransform[1] = CPLAtof(CPLGetXMLValue(psGeoLoc, "XDIM", "0"));
         adfGeoTransform[2] = 0.0;
-        adfGeoTransform[3] = CPLAtof(CPLGetXMLValue(psGeoLoc,"ULYMAP","0"));
+        adfGeoTransform[3] = CPLAtof(CPLGetXMLValue(psGeoLoc, "ULYMAP", "0"));
         adfGeoTransform[4] = 0.0;
-        adfGeoTransform[5] = -CPLAtof(CPLGetXMLValue(psGeoLoc,"YDIM","0"));
+        adfGeoTransform[5] = -CPLAtof(CPLGetXMLValue(psGeoLoc, "YDIM", "0"));
     }
     else
     {
         // Try to get geotransform from underlying raster.
-        if ( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None )
+        if( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None )
             bHaveGeoTransform = TRUE;
     }
 
@@ -620,46 +844,46 @@ int DIMAPDataset::ReadImageInformation()
 
     if( psGeoLoc != NULL )
     {
-        CPLXMLNode *psNode;
-
-        // count gcps.
+        // Count gcps.
         nGCPCount = 0;
-        for( psNode = psGeoLoc->psChild; psNode != NULL;
+        for( CPLXMLNode *psNode = psGeoLoc->psChild;
+             psNode != NULL;
              psNode = psNode->psNext )
         {
             if( EQUAL(psNode->pszValue,"Tie_Point") )
                 nGCPCount++ ;
         }
 
-        pasGCPList = (GDAL_GCP *)
-            CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
+        pasGCPList = static_cast<GDAL_GCP *>(
+            CPLCalloc(sizeof(GDAL_GCP),nGCPCount) );
 
         nGCPCount = 0;
 
-        for( psNode = psGeoLoc->psChild; psNode != NULL;
+        for( CPLXMLNode *psNode = psGeoLoc->psChild;
+             psNode != NULL;
              psNode = psNode->psNext )
         {
-            char    szID[32];
-            GDAL_GCP   *psGCP = pasGCPList + nGCPCount;
+            GDAL_GCP *psGCP = pasGCPList + nGCPCount;
 
             if( !EQUAL(psNode->pszValue,"Tie_Point") )
                 continue;
 
-            nGCPCount++ ;
+            nGCPCount++;
 
+            char szID[32] = {};
             snprintf( szID, sizeof(szID), "%d", nGCPCount );
             psGCP->pszId = CPLStrdup( szID );
             psGCP->pszInfo = CPLStrdup("");
             psGCP->dfGCPPixel =
-                CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_DATA_X","0"))-0.5;
+                CPLAtof(CPLGetXMLValue(psNode, "TIE_POINT_DATA_X", "0")) - 0.5;
             psGCP->dfGCPLine =
-                CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_DATA_Y","0"))-0.5;
+                CPLAtof(CPLGetXMLValue(psNode, "TIE_POINT_DATA_Y", "0")) - 0.5;
             psGCP->dfGCPX =
-                CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_CRS_X",""));
+                CPLAtof(CPLGetXMLValue(psNode, "TIE_POINT_CRS_X", ""));
             psGCP->dfGCPY =
-                CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_CRS_Y",""));
+                CPLAtof(CPLGetXMLValue(psNode, "TIE_POINT_CRS_Y", ""));
             psGCP->dfGCPZ =
-                CPLAtof(CPLGetXMLValue(psNode,"TIE_POINT_CRS_Z",""));
+                CPLAtof(CPLGetXMLValue(psNode, "TIE_POINT_CRS_Z", ""));
         }
     }
 
@@ -695,7 +919,7 @@ int DIMAPDataset::ReadImageInformation()
         // Check underlying raster for SRS. We have cases where
         // HORIZONTAL_CS_CODE is empty and the underlying raster
         // is georeferenced (rprinceley).
-        if ( poImageDS->GetProjectionRef() )
+        if( poImageDS->GetProjectionRef() )
         {
             osProjection = poImageDS->GetProjectionRef();
         }
@@ -722,33 +946,36 @@ int DIMAPDataset::ReadImageInformation()
 
     CPLXMLNode *psImageInterpretationNode =
         CPLGetXMLNode( psDoc, "Image_Interpretation" );
-    if (psImageInterpretationNode != NULL)
+    if( psImageInterpretationNode != NULL )
     {
         CPLXMLNode *psSpectralBandInfoNode = psImageInterpretationNode->psChild;
-        while (psSpectralBandInfoNode != NULL)
+        while( psSpectralBandInfoNode != NULL )
         {
-            if (psSpectralBandInfoNode->eType == CXT_Element &&
-                EQUAL(psSpectralBandInfoNode->pszValue, "Spectral_Band_Info"))
+            if( psSpectralBandInfoNode->eType == CXT_Element &&
+                EQUAL(psSpectralBandInfoNode->pszValue, "Spectral_Band_Info") )
             {
                 CPLXMLNode *psTag = psSpectralBandInfoNode->psChild;
                 int nBandIndex = 0;
-                while(psTag != NULL)
+                while( psTag != NULL )
                 {
-                    if (psTag->eType == CXT_Element && psTag->psChild != NULL &&
-                        psTag->psChild->eType == CXT_Text && psTag->pszValue != NULL)
+                    if( psTag->eType == CXT_Element && psTag->psChild != NULL &&
+                        psTag->psChild->eType ==
+                        CXT_Text && psTag->pszValue != NULL)
                     {
-                        if (EQUAL(psTag->pszValue, "BAND_INDEX"))
+                        if( EQUAL(psTag->pszValue, "BAND_INDEX") )
                         {
                             nBandIndex = atoi(psTag->psChild->pszValue);
-                            if (nBandIndex <= 0 ||
-                                nBandIndex > poImageDS->GetRasterCount())
+                            if( nBandIndex <= 0 ||
+                                nBandIndex > poImageDS->GetRasterCount() )
                             {
-                                CPLError(CE_Warning, CPLE_AppDefined,
-                                         "Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
+                                CPLError(
+                                    CE_Warning, CPLE_AppDefined,
+                                    "Bad BAND_INDEX value : %s",
+                                    psTag->psChild->pszValue);
                                 nBandIndex = 0;
                             }
                         }
-                        else if (nBandIndex >= 1)
+                        else if( nBandIndex >= 1 )
                         {
                             GetRasterBand(nBandIndex)->SetMetadataItem(
                                 psTag->pszValue, psTag->psChild->pszValue);
@@ -761,6 +988,8 @@ int DIMAPDataset::ReadImageInformation()
         }
     }
 
+    GDALClose(poImageDS);
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -772,10 +1001,11 @@ int DIMAPDataset::ReadImageInformation()
 /* -------------------------------------------------------------------- */
     oOvManager.Initialize( this, osMDFilename );
 
+    // CID 163546 - poTileDS dereferenced above.
+    // coverity[leaked_storage]
     return TRUE;
 }
 
-
 /************************************************************************/
 /*               ReadImageInformation() DIMAP Version 2                 */
 /************************************************************************/
@@ -786,68 +1016,254 @@ int DIMAPDataset::ReadImageInformation2()
     if( !psDoc )
         psDoc = CPLGetXMLNode( psProductDim, "=PHR_DIMAP_Document" );
 
-    CPLXMLNode *psImageAttributes = CPLGetXMLNode( psDoc, "Raster_Data.Raster_Dimensions" );
+    CPLXMLNode *psImageAttributes =
+        CPLGetXMLNode( psDoc, "Raster_Data.Raster_Dimensions" );
     if( psImageAttributes == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-            "Failed to find <Raster_Dimensions> in document." );
+                  "Failed to find <Raster_Dimensions> in document." );
         return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Get overall image information.                                  */
 /* -------------------------------------------------------------------- */
-#ifdef DEBUG
-    int l_nBands =
-        atoi(CPLGetXMLValue( psImageAttributes, "NBANDS", "-1" ));
-#endif
 
+  /*
+      <Raster_Dimensions>
+         <NROWS>30</NROWS>
+         <NCOLS>20</NCOLS>
+         <NBANDS>4</NBANDS>
+         <Tile_Set>
+            <NTILES>2</NTILES>
+            <Regular_Tiling>
+               <NTILES_SIZE nrows="20" ncols="20"/>
+               <NTILES_COUNT ntiles_R="2" ntiles_C="1"/>
+               <OVERLAP_ROW>0</OVERLAP_ROW>
+               <OVERLAP_COL>0</OVERLAP_COL>
+            </Regular_Tiling>
+         </Tile_Set>
+      </Raster_Dimensions>
+    */
+
+    const int l_nBands =
+        atoi(CPLGetXMLValue( psImageAttributes, "NBANDS", "-1" ));
     nRasterXSize =
         atoi(CPLGetXMLValue( psImageAttributes, "NCOLS", "-1" ));
     nRasterYSize =
         atoi(CPLGetXMLValue( psImageAttributes, "NROWS", "-1" ));
+    int nTileWidth = atoi( CPLGetXMLValue( psImageAttributes,
+                           "Tile_Set.Regular_Tiling.NTILES_SIZE.ncols", "-1" ));
+    int nTileHeight = atoi( CPLGetXMLValue( psImageAttributes,
+                            "Tile_Set.Regular_Tiling.NTILES_SIZE.nrows", "-1" ));
+    int nOverlapRow = atoi( CPLGetXMLValue( psImageAttributes,
+                            "Tile_Set.Regular_Tiling.OVERLAP_ROW", "-1" ));
+    int nOverlapCol = atoi( CPLGetXMLValue( psImageAttributes,
+                            "Tile_Set.Regular_Tiling.OVERLAP_COL", "-1" ));
+    const int nBits = atoi(
+        CPLGetXMLValue( psDoc, "Raster_Data.Raster_Encoding.NBITS", "-1") );
+    CPLString osDataFormat =
+        CPLGetXMLValue( psDoc, "Raster_Data.Data_Access.DATA_FILE_FORMAT", "" );
+    if( osDataFormat == "image/jp2" )
+    {
+        SetMetadataItem( "COMPRESSION", "JPEG2000", "IMAGE_STRUCTURE" );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Get the name of the underlying file.                            */
 /* -------------------------------------------------------------------- */
 
-    /* If the data file was not in the product file, it should be here */
-    if ( osImageDSFilename.size() == 0 )
+    CPLXMLNode *psDataFiles =
+        CPLGetXMLNode(psDoc, "Raster_Data.Data_Access.Data_Files" );
+    /*  <Data_Files>
+            <Data_File tile_R="1" tile_C="1">
+               <DATA_FILE_PATH href="IMG_foo_R1C1.TIF"/>
+            </Data_File>
+            <Data_File tile_R="2" tile_C="1">
+               <DATA_FILE_PATH href="IMG_foo_R2C1.TIF"/>
+            </Data_File>
+         </Data_Files>
+    */
+    std::map< std::pair<int,int>, CPLString > oMapRowColumnToName;
+    if( psDataFiles )
     {
-        const char *pszHref = CPLGetXMLValue(
-                            psDoc, "Raster_Data.Data_Access.Data_Files.Data_File.DATA_FILE_PATH.href", "" );
-        if( strlen(pszHref) > 0 )
+        int nRows = 1;
+        int nCols = 1;
+        CPLString osPath = CPLGetPath( osDIMAPFilename );
+        for( CPLXMLNode* psDataFile = psDataFiles->psChild;
+                         psDataFile; psDataFile = psDataFile->psNext )
         {
-            CPLString osPath = CPLGetPath( osDIMAPFilename );
-            osImageDSFilename =
-                CPLFormCIFilename( osPath, pszHref, NULL );
+            if( psDataFile->eType == CXT_Element &&
+                strcmp( psDataFile->pszValue, "Data_File") == 0 )
+            {
+                const char* pszR = CPLGetXMLValue( psDataFile, "tile_R", NULL );
+                const char* pszC = CPLGetXMLValue( psDataFile, "tile_C", NULL );
+                const char* pszHref =
+                    CPLGetXMLValue(psDataFile, "DATA_FILE_PATH.href", NULL );
+                if( pszR && pszC && pszHref )
+                {
+                    int nRow = atoi(pszR);
+                    int nCol = atoi(pszC);
+                    if( nRow == 1 && nCol == 1 )
+                        osImageDSFilename =
+                            CPLFormCIFilename( osPath, pszHref, NULL );
+                    if( nRow > nRows ) nRows = nRow;
+                    if( nCol > nCols ) nCols = nCol;
+                    oMapRowColumnToName[ std::pair<int,int>(nRow, nCol) ] =
+                          CPLFormCIFilename( osPath, pszHref, NULL );
+                }
+            }
         }
-        else
+        if( nOverlapRow > 0 || nOverlapCol > 0 )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                "Failed to find <DATA_FILE_PATH> in document." );
-            return FALSE;
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Overlap between tiles is not handled currently. "
+                     "Only taking into account top left tile");
+            oMapRowColumnToName.clear();
+            oMapRowColumnToName[ std::pair<int,int>(1,1) ] = osImageDSFilename;
         }
     }
+    else
+    {
+        oMapRowColumnToName[ std::pair<int,int>(1,1) ] = osImageDSFilename;
+    }
 
+    if( osImageDSFilename.empty() )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to find <DATA_FILE_PATH> in document." );
+        return FALSE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Try and open the file.                                          */
 /* -------------------------------------------------------------------- */
-    poImageDS = (GDALDataset *) GDALOpen( osImageDSFilename, GA_ReadOnly );
+    GDALDataset* poImageDS = static_cast<GDALDataset *>(
+        GDALOpen( osImageDSFilename, GA_ReadOnly ) );
     if( poImageDS == NULL )
     {
         return FALSE;
     }
+    if( poImageDS->GetRasterCount() != l_nBands )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Inconsistent band count");
+        GDALClose(poImageDS);
+        return FALSE;
+    }
 
+    if( oMapRowColumnToName.size() == 1 )
+    {
+        nTileWidth = poImageDS->GetRasterXSize();
+        nTileHeight = poImageDS->GetRasterYSize();
+    }
 
 /* -------------------------------------------------------------------- */
-/*      Attach the bands.                                               */
+/*      Create and initialize the corresponding VRT dataset used to     */
+/*      manage the tiled data access.                                   */
 /* -------------------------------------------------------------------- */
-    CPLAssert( l_nBands == poImageDS->GetRasterCount() );
+    poVRTDS = new VRTDataset(nRasterXSize, nRasterYSize);
+
+    // Don't try to write a VRT file.
+    poVRTDS->SetWritable(FALSE);
+
+    std::map< std::pair<int,int>, GDALDataset* > oMapRowColumnToProxyPoolDataset;
+    std::map< std::pair<int,int>, CPLString>::iterator oIterRCN =
+        oMapRowColumnToName.begin();
+    for( ; oIterRCN != oMapRowColumnToName.end(); ++oIterRCN )
+    {
+        const int nRow = oIterRCN->first.first;
+        const int nCol = oIterRCN->first.second;
+        if( (nRow - 1) * nTileHeight < nRasterYSize &&
+            (nCol - 1) * nTileWidth < nRasterXSize )
+        {
+            int nHeight = nTileHeight;
+            if( nRow * nTileHeight > nRasterYSize )
+            {
+                nHeight = nRasterYSize - (nRow - 1) * nTileHeight;
+            }
+            int nWidth = nTileWidth;
+            if( nCol * nTileWidth > nRasterXSize )
+            {
+                nWidth = nRasterXSize - (nCol - 1) * nTileWidth;
+            }
+            GDALProxyPoolDataset* poPPDs = new GDALProxyPoolDataset(
+                oIterRCN->second, nWidth, nHeight, GA_ReadOnly, TRUE );
+            oMapRowColumnToProxyPoolDataset[ oIterRCN->first ] = poPPDs;
+
+            for( int iBand = 0; iBand < poImageDS->GetRasterCount(); iBand++ )
+            {
+                poPPDs->AddSrcBandDescription(
+                    poImageDS->GetRasterBand(iBand+1)->GetRasterDataType(),
+                    nRasterXSize, 1 );
+            }
+        }
+    }
+
+    for( int iBand = 0; iBand < poImageDS->GetRasterCount(); iBand++ )
+    {
+        poVRTDS->AddBand(
+            poImageDS->GetRasterBand(iBand+1)->GetRasterDataType(), NULL );
+
+        VRTSourcedRasterBand *poVRTBand =
+            reinterpret_cast<VRTSourcedRasterBand *>(
+                poVRTDS->GetRasterBand(iBand+1) );
+        if( nBits > 0 && nBits != 8 && nBits != 16 )
+        {
+            poVRTBand->SetMetadataItem(
+                "NBITS", CPLSPrintf("%d", nBits), "IMAGE_STRUCTURE" );
+        }
 
-    for( int iBand = 1; iBand <= poImageDS->GetRasterCount(); iBand++ )
-        SetBand( iBand, new DIMAPWrapperRasterBand(poImageDS->GetRasterBand( iBand )) );
+        std::map< std::pair<int,int>, GDALDataset*>::iterator oIterRCP =
+            oMapRowColumnToProxyPoolDataset.begin();
+        for( ; oIterRCP != oMapRowColumnToProxyPoolDataset.end(); ++oIterRCP )
+        {
+            GDALRasterBand *poSrcBand =
+                oIterRCP->second->GetRasterBand(iBand+1);
+
+            const int nRow = oIterRCP->first.first;
+            const int nCol = oIterRCP->first.second;
+            int nHeight = nTileHeight;
+            if( nRow * nTileHeight > nRasterYSize )
+            {
+                nHeight = nRasterYSize - (nRow - 1) * nTileHeight;
+            }
+            int nWidth = nTileWidth;
+            if( nCol * nTileWidth > nRasterXSize )
+            {
+                nWidth = nRasterXSize - (nCol - 1) * nTileWidth;
+            }
+
+            poVRTBand->AddSimpleSource( poSrcBand,
+                                        0, 0,
+                                        nWidth, nHeight,
+                                        (nCol - 1) * nTileWidth,
+                                        (nRow - 1) * nTileHeight,
+                                        nWidth, nHeight );
+        }
+    }
+
+    std::map< std::pair<int,int>, GDALDataset*>::iterator oIterRCP =
+        oMapRowColumnToProxyPoolDataset.begin();
+    for( ; oIterRCP != oMapRowColumnToProxyPoolDataset.end(); ++oIterRCP )
+    {
+        oIterRCP->second->Dereference();
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+    for( int iBand = 1; iBand <= poVRTDS->GetRasterCount(); iBand++ )
+    {
+        GDALRasterBand* poBand = new DIMAPRasterBand(
+            this, iBand,
+            static_cast<VRTSourcedRasterBand*>(poVRTDS->GetRasterBand(iBand)) );
+        if( nBits > 0 && nBits != 8 && nBits != 16 )
+        {
+            poBand->SetMetadataItem(
+                "NBITS", CPLSPrintf("%d", nBits), "IMAGE_STRUCTURE" );
+        }
+        SetBand(iBand, poBand);
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Try to collect simple insertion point.                          */
@@ -858,18 +1274,23 @@ int DIMAPDataset::ReadImageInformation2()
     if( psGeoLoc != NULL )
     {
         bHaveGeoTransform = TRUE;
-        adfGeoTransform[0] = CPLAtof(CPLGetXMLValue(psGeoLoc,"ULXMAP","0"));
-        adfGeoTransform[1] = CPLAtof(CPLGetXMLValue(psGeoLoc,"XDIM","0"));
+        adfGeoTransform[0] = CPLAtof(CPLGetXMLValue(psGeoLoc, "ULXMAP", "0"));
+        adfGeoTransform[1] = CPLAtof(CPLGetXMLValue(psGeoLoc, "XDIM", "0"));
         adfGeoTransform[2] = 0.0;
-        adfGeoTransform[3] = CPLAtof(CPLGetXMLValue(psGeoLoc,"ULYMAP","0"));
+        adfGeoTransform[3] = CPLAtof(CPLGetXMLValue(psGeoLoc, "ULYMAP", "0"));
         adfGeoTransform[4] = 0.0;
-        adfGeoTransform[5] = -CPLAtof(CPLGetXMLValue(psGeoLoc,"YDIM","0"));
+        adfGeoTransform[5] = -CPLAtof(CPLGetXMLValue(psGeoLoc, "YDIM", "0"));
     }
     else
     {
-        // Try to get geotransform from underlying raster.
-        if ( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None )
+        // Try to get geotransform from underlying raster,
+        // but make sure it is a real geotransform.
+        if( poImageDS->GetGeoTransform(adfGeoTransform) == CE_None &&
+            !(adfGeoTransform[0] == 0.5 && adfGeoTransform[3] == 1.5 &&
+              adfGeoTransform[1] == 1.0 && adfGeoTransform[5] == -1.0) )
+        {
             bHaveGeoTransform = TRUE;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -909,7 +1330,7 @@ int DIMAPDataset::ReadImageInformation2()
         // Check underlying raster for SRS. We have cases where
         // HORIZONTAL_CS_CODE is empty and the underlying raster
         // is georeferenced (rprinceley).
-        if ( poImageDS->GetProjectionRef() )
+        if( poImageDS->GetProjectionRef() )
         {
             osProjection = poImageDS->GetProjectionRef();
         }
@@ -922,13 +1343,13 @@ int DIMAPDataset::ReadImageInformation2()
     static const char * const apszMetadataTranslationDim[] =
     {
         "Product_Information.Delivery_Identification", "DATASET_",
-            "Product_Information.Producer_Information", "DATASET_",
+        "Product_Information.Producer_Information", "DATASET_",
         "Dataset_Sources.Source_Identification.Strip_Source", "",
         "Processing_Information.Production_Facility", "FACILITY_",
         "Processing_Information.Product_Settings", "",
         "Processing_Information.Product_Settings.Geometric_Settings", "GEOMETRIC_",
         "Quality_Assessment.Imaging_Quality_Measurement", "CLOUDCOVER_",
-            NULL, NULL
+        NULL, NULL
     };
 
     SetMetadataFromXML(psProductDim, apszMetadataTranslationDim);
@@ -939,73 +1360,100 @@ int DIMAPDataset::ReadImageInformation2()
 
     static const char * const apszMetadataTranslationStrip[] =
     {
-        "Catalog.Full_Strip.Notations.Cloud_And_Quality_Notation.Data_Strip_Notation", "CLOUDCOVER_",
-        "Acquisition_Configuration.Platform_Configuration.Ephemeris_Configuration", "EPHEMERIS_",
-            NULL, NULL
+        "Catalog.Full_Strip.Notations.Cloud_And_Quality_Notation."
+        "Data_Strip_Notation", "CLOUDCOVER_",
+        "Acquisition_Configuration.Platform_Configuration."
+        "Ephemeris_Configuration", "EPHEMERIS_",
+        NULL, NULL
     };
 
     if( psProductStrip != NULL )
         SetMetadataFromXML(psProductStrip, apszMetadataTranslationStrip);
 
+    if( !osRPCFilename.empty() )
+    {
+        GDALMDReaderPleiades* poReader =
+            GDALMDReaderPleiades::CreateReaderForRPC(osRPCFilename);
+        char** papszRPC = poReader->LoadRPCXmlFile();
+        delete poReader;
+        if( papszRPC )
+            SetMetadata(papszRPC, "RPC");
+        CSLDestroy(papszRPC);
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Set Band metadata from the <Band_Radiance> and                  */
 /*                                <Band_Spectral_Range> content         */
 /* -------------------------------------------------------------------- */
 
     CPLXMLNode *psImageInterpretationNode =
-        CPLGetXMLNode( psDoc,
-                    "Radiometric_Data.Radiometric_Calibration.Instrument_Calibration.Band_Measurement_List" );
-    if (psImageInterpretationNode != NULL)
+        CPLGetXMLNode(
+            psDoc,
+            "Radiometric_Data.Radiometric_Calibration.Instrument_Calibration."
+            "Band_Measurement_List" );
+    if( psImageInterpretationNode != NULL )
     {
         CPLXMLNode *psSpectralBandInfoNode = psImageInterpretationNode->psChild;
-        while (psSpectralBandInfoNode != NULL)
+        while( psSpectralBandInfoNode != NULL )
         {
-            if (psSpectralBandInfoNode->eType == CXT_Element &&
-                (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance") ||
-                 EQUAL(psSpectralBandInfoNode->pszValue, "Band_Spectral_Range") ||
-                 EQUAL(psSpectralBandInfoNode->pszValue, "Band_Solar_Irradiance")))
+            if( psSpectralBandInfoNode->eType == CXT_Element &&
+                (EQUAL(psSpectralBandInfoNode->pszValue,
+                       "Band_Radiance") ||
+                 EQUAL(psSpectralBandInfoNode->pszValue,
+                       "Band_Spectral_Range") ||
+                 EQUAL(psSpectralBandInfoNode->pszValue,
+                       "Band_Solar_Irradiance")) )
             {
                 CPLString osName;
 
-                if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance"))
+                if( EQUAL(psSpectralBandInfoNode->pszValue, "Band_Radiance") )
                     osName = "RADIANCE_";
-                else if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Spectral_Range"))
+                else if( EQUAL(psSpectralBandInfoNode->pszValue,
+                               "Band_Spectral_Range"))
                     osName = "SPECTRAL_RANGE_";
-                else if (EQUAL(psSpectralBandInfoNode->pszValue, "Band_Solar_Irradiance"))
+                else if( EQUAL(psSpectralBandInfoNode->pszValue,
+                               "Band_Solar_Irradiance") )
                     osName = "SOLAR_IRRADIANCE_";
 
                 CPLXMLNode *psTag = psSpectralBandInfoNode->psChild;
                 int nBandIndex = 0;
-                while(psTag != NULL)
+                while( psTag != NULL )
                 {
-                    if (psTag->eType == CXT_Element && psTag->psChild != NULL &&
-                        psTag->psChild->eType == CXT_Text && psTag->pszValue != NULL)
+                    if( psTag->eType == CXT_Element && psTag->psChild != NULL &&
+                        psTag->psChild->eType == CXT_Text &&
+                        psTag->pszValue != NULL )
                     {
-                        if (EQUAL(psTag->pszValue, "BAND_ID"))
+                        if( EQUAL(psTag->pszValue, "BAND_ID") )
                         {
-                            /* BAND_ID is: B0, B1, .... P */
-                            if (!EQUAL(psTag->psChild->pszValue, "P"))
+                            // BAND_ID is: B0, B1, .... P
+                            if( !EQUAL(psTag->psChild->pszValue, "P") )
                             {
-                                if (strlen(psTag->psChild->pszValue) < 2) /* should not happen */
+                                if( strlen(psTag->psChild->pszValue) < 2)
                                 {
-                                    CPLError(CE_Warning, CPLE_AppDefined,
-                                        "Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
+                                    // Should not happen.
+                                    CPLError(
+                                        CE_Warning, CPLE_AppDefined,
+                                        "Bad BAND_INDEX value : %s",
+                                        psTag->psChild->pszValue);
                                     nBandIndex = 0;
                                 }
                                 else
                                 {
-                                    nBandIndex = atoi(&psTag->psChild->pszValue[1]) + 1;
-                                    if (nBandIndex <= 0 ||
-                                    nBandIndex > poImageDS->GetRasterCount())
+                                    nBandIndex =
+                                        atoi(&psTag->psChild->pszValue[1]) + 1;
+                                    if( nBandIndex <= 0 ||
+                                    nBandIndex > poImageDS->GetRasterCount() )
                                     {
-                                    CPLError(CE_Warning, CPLE_AppDefined,
-                                        "Bad BAND_INDEX value : %s", psTag->psChild->pszValue);
-                                    nBandIndex = 0;
+                                        CPLError(
+                                            CE_Warning, CPLE_AppDefined,
+                                            "Bad BAND_INDEX value : %s",
+                                            psTag->psChild->pszValue);
+                                        nBandIndex = 0;
                                     }
                                 }
                             }
                         }
-                        else if (nBandIndex >= 1)
+                        else if( nBandIndex >= 1 )
                         {
                             CPLString osMDName = osName;
                             osMDName += psTag->pszValue;
@@ -1013,7 +1461,6 @@ int DIMAPDataset::ReadImageInformation2()
                             GetRasterBand(nBandIndex)->SetMetadataItem(
                                 osMDName, psTag->psChild->pszValue);
                         }
-
                     }
                     psTag = psTag->psNext;
                 }
@@ -1022,6 +1469,8 @@ int DIMAPDataset::ReadImageInformation2()
         }
     }
 
+    GDALClose(poImageDS);
+
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -1040,15 +1489,18 @@ int DIMAPDataset::ReadImageInformation2()
 /*                          SetMetadataFromXML()                        */
 /************************************************************************/
 
-void DIMAPDataset::SetMetadataFromXML(CPLXMLNode *psProductIn, const char * const apszMetadataTranslation[])
+void DIMAPDataset::SetMetadataFromXML(
+    CPLXMLNode *psProductIn, const char * const apszMetadataTranslation[] )
 {
     CPLXMLNode *psDoc = CPLGetXMLNode( psProductIn, "=Dimap_Document" );
     if( psDoc == NULL )
     {
-      psDoc = CPLGetXMLNode( psProductIn, "=PHR_DIMAP_Document" );
+        psDoc = CPLGetXMLNode( psProductIn, "=PHR_DIMAP_Document" );
     }
 
-    for( int iTrItem = 0; apszMetadataTranslation[iTrItem] != NULL; iTrItem += 2 )
+    for( int iTrItem = 0;
+         apszMetadataTranslation[iTrItem] != NULL;
+         iTrItem += 2 )
     {
         CPLXMLNode *psParent =
             CPLGetXMLNode( psDoc, apszMetadataTranslation[iTrItem] );
@@ -1059,7 +1511,7 @@ void DIMAPDataset::SetMetadataFromXML(CPLXMLNode *psProductIn, const char * cons
         // Hackey logic to support directly access a name/value entry
         // or a parent element with many name/values.
 
-        CPLXMLNode *psTarget;
+        CPLXMLNode *psTarget = NULL;
         if( psParent->psChild != NULL
             && psParent->psChild->eType == CXT_Text )
             psTarget = psParent;
@@ -1074,20 +1526,21 @@ void DIMAPDataset::SetMetadataFromXML(CPLXMLNode *psProductIn, const char * cons
             {
                 CPLString osName = apszMetadataTranslation[iTrItem+1];
 
-                if (psTarget->psChild->eType == CXT_Text)
+                if( psTarget->psChild->eType == CXT_Text )
                 {
                     osName += psTarget->pszValue;
                     SetMetadataItem( osName, psTarget->psChild->pszValue );
                 }
-                else if (psTarget->psChild->eType == CXT_Attribute)
+                else if( psTarget->psChild->eType == CXT_Attribute )
                 {
-                    /* find the tag value, at the end of the attributes */
-                    CPLXMLNode *psNode = psTarget->psChild;
-                    for( ; psNode != NULL;  psNode = psNode->psNext )
+                    // find the tag value, at the end of the attributes.
+                    for( CPLXMLNode *psNode = psTarget->psChild;
+                         psNode != NULL;
+                         psNode = psNode->psNext )
                     {
-                        if (psNode->eType == CXT_Attribute)
+                        if( psNode->eType == CXT_Attribute )
                             continue;
-                        else if (psNode->eType == CXT_Text)
+                        else if( psNode->eType == CXT_Text )
                         {
                             osName += psTarget->pszValue;
                             SetMetadataItem( osName, psNode->pszValue );
diff --git a/frmts/dimap/makefile.vc b/frmts/dimap/makefile.vc
index 2a5fb07..c0da576 100644
--- a/frmts/dimap/makefile.vc
+++ b/frmts/dimap/makefile.vc
@@ -3,6 +3,8 @@ OBJ	=	dimapdataset.obj
 
 GDAL_ROOT	=	..\..
 
+EXTRAFLAGS 	=	-I..\vrt
+
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
 default:	$(OBJ)
diff --git a/frmts/dods/GNUmakefile b/frmts/dods/GNUmakefile
index af987c1..fc1f209 100644
--- a/frmts/dods/GNUmakefile
+++ b/frmts/dods/GNUmakefile
@@ -2,7 +2,7 @@
 
 include ../../GDALmake.opt
 
-OBJ	=	dodsdataset2.o 
+OBJ	=	dodsdataset2.o
 
 CPPFLAGS	:=	 $(CPPFLAGS) $(DODS_INC)
 
@@ -17,7 +17,7 @@ using_dods: using_dods.$(OBJ_EXT) dodsdataset.$(OBJ_EXT)
 
 # There's a note in GDALmake.opt that local programs should link against
 # CONFIG_LIBS, but that doesn't work here, maybe because dodsdataset_test
-# links statically (which it needs to do to run in a debugger). 10/31/03 jhrg 
+# links statically (which it needs to do to run in a debugger). 10/31/03 jhrg
 dodsdataset_test: dodsdataset_test.$(OBJ_EXT) dodsdataset.$(OBJ_EXT)
 	$(LD) $(LNK_FLAGS) -static -g3 $^ $(XTRAOBJ) $(LIBS) $(LIBGDAL) \
 		-lcppunit -lxml2 -o $@$(EXE)
diff --git a/frmts/dods/dodsdataset2.cpp b/frmts/dods/dodsdataset2.cpp
index 7147a41..9086555 100644
--- a/frmts/dods/dodsdataset2.cpp
+++ b/frmts/dods/dodsdataset2.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dodsdataset2.cpp 36175 2016-11-09 09:31:39Z rouault $
  *
  * Project:  OPeNDAP Raster Driver
  * Purpose:  Implements DODSDataset and DODSRasterBand classes.
@@ -36,34 +35,7 @@
 
 #include <debug.h>
 
-#include <BaseType.h>		// DODS
-#include <Byte.h>
-#include <Int16.h>
-#include <UInt16.h>
-#include <Int32.h>
-#include <UInt32.h>
-#include <Float32.h>
-#include <Float64.h>
-#include <Str.h>
-#include <Url.h>
-#include <Array.h>
-#include <Structure.h>
-#include <Sequence.h>
-#include <Grid.h>
-
-#ifdef LIBDAP_310
-/* AISConnect.h/AISConnect class was renamed to Connect.h/Connect in libdap 3.10 */
-#include <Connect.h>
-#define AISConnect Connect
-#else
-#include <AISConnect.h>
-#endif
-
-#include <DDS.h>
-#include <DAS.h>
-#include <BaseTypeFactory.h>
-#include <Error.h>
-#include <escaping.h>
+#include "libdap_headers.h"
 
 #include "cpl_string.h"
 #include "gdal_frmts.h"
@@ -72,7 +44,7 @@
 
 using namespace libdap;
 
-CPL_CVSID("$Id: dodsdataset2.cpp 36175 2016-11-09 09:31:39Z rouault $");
+CPL_CVSID("$Id: dodsdataset2.cpp 36663 2016-12-03 21:34:45Z rouault $");
 
 /** Attribute names used to encode geo-referencing information. Note that
     these are not C++ objects to avoid problems with static global
@@ -86,8 +58,8 @@ const char *nlat = "Northernmost_Latitude"; ///<
 const char *slat = "Southernmost_Latitude"; ///<
 const char *wlon = "Westernmost_Longitude"; ///<
 const char *elon = "Easternmost_Longitude"; ///<
-const char *gcs = "GeographicCS";	    ///<
-const char *pcs = "ProjectionCS";	    ///<
+const char *gcs = "GeographicCS";           ///<
+const char *pcs = "ProjectionCS";           ///<
 const char *norm_proj_param = "Norm_Proj_Param"; ///<
 const char *spatial_ref = "spatial_ref";    ///<
 //@}
@@ -117,13 +89,13 @@ get_variable(DDS &dds, const string &n)
 {
     BaseType *poBT = dds.var(www2id(n));
     if (!poBT) {
-	try {
-	    string leaf = n.substr(n.find_last_of('.')+1);
-	    poBT = dds.var(www2id(leaf));
-	}
-	catch (const std::exception &e) {
-	    poBT = 0;
-	}
+        try {
+            string leaf = n.substr(n.find_last_of('.')+1);
+            poBT = dds.var(www2id(leaf));
+        }
+        catch (const std::exception &e) {
+            poBT = 0;
+        }
     }
 
     return poBT;
@@ -139,15 +111,14 @@ get_variable(DDS &dds, const string &n)
 static string StripQuotes( string oInput )
 
 {
-    char *pszResult;
-
     if( oInput.length() < 2 )
         return oInput;
 
     oInput = oInput.substr(1,oInput.length()-2);
 
-    pszResult = CPLUnescapeString( oInput.c_str(), NULL,
-                                   CPLES_BackslashQuotable );
+    char *pszResult =
+        CPLUnescapeString( oInput.c_str(), NULL,
+                           CPLES_BackslashQuotable );
 
     oInput = pszResult;
 
@@ -208,12 +179,12 @@ static int GetDimension( string oCE, const char *pszDimName,
 class DODSDataset : public GDALDataset
 {
 private:
-    AISConnect *poConnect; 	//< Virtual connection to the data source
+    AISConnect *poConnect;      // Virtual connection to the data source
 
-    string oURL;		//< data source URL
+    string oURL;                // data source URL
     double adfGeoTransform[6];
     int    bGotGeoTransform;
-    string oWKT;		//< Constructed WKT string
+    string oWKT;                // Constructed WKT string
 
     DAS    oDAS;
     DDS   *poDDS;
@@ -240,8 +211,8 @@ public:
     virtual        ~DODSDataset();
 
     // Overridden GDALDataset methods
-    CPLErr GetGeoTransform(double *padfTransform);
-    const char *GetProjectionRef();
+    CPLErr GetGeoTransform(double *padfTransform) override;
+    const char *GetProjectionRef() override;
 
     /// Open is not a method in GDALDataset; it's the driver.
     static GDALDataset *Open(GDALOpenInfo *);
@@ -265,14 +236,14 @@ class DODSRasterBand : public GDALRasterBand
 {
 private:
     string oVarName;
-    string oCE;		        // Holds the CE (with [x] and [y] still there
+    string oCE;                 // Holds the CE (with [x] and [y] still there
 
     friend class DODSDataset;
 
     GDALColorInterp eColorInterp;
     GDALColorTable  *poCT;
 
-    int		   nOverviewCount;
+    int    nOverviewCount;
     DODSRasterBand **papoOverviewBand;
 
     int    nOverviewFactor;     // 1 for base, or 2/4/8 for overviews.
@@ -289,13 +260,13 @@ public:
                     int nOverviewFactor );
     virtual ~DODSRasterBand();
 
-    virtual int    GetOverviewCount();
-    virtual GDALRasterBand *GetOverview( int );
-    virtual CPLErr IReadBlock(int, int, void *);
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-		virtual CPLErr          SetNoDataValue( double );
-    virtual double          GetNoDataValue( int * );
+    virtual int    GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview( int ) override;
+    virtual CPLErr IReadBlock(int, int, void *) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual CPLErr          SetNoDataValue( double ) override;
+    virtual double          GetNoDataValue( int * ) override;
 };
 
 /************************************************************************/
@@ -308,8 +279,10 @@ public:
 /*                            DODSDataset()                             */
 /************************************************************************/
 
-DODSDataset::DODSDataset()
-
+DODSDataset::DODSDataset() :
+    poConnect(NULL),
+    bGotGeoTransform(FALSE),
+    poBaseTypeFactory(new BaseTypeFactory())
 {
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -317,10 +290,7 @@ DODSDataset::DODSDataset()
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    bGotGeoTransform = FALSE;
-
-    poConnect = NULL;
-    poBaseTypeFactory = new BaseTypeFactory();
+    // Need to be done after poBaseTypeFactory initialization
     poDDS = new DDS( poBaseTypeFactory );
 }
 
@@ -349,8 +319,8 @@ DODSDataset::connect_to_server() throw(Error)
 {
     // does the string start with 'http?'
     if (oURL.find("http://") == string::npos
-	&& oURL.find("https://") == string::npos)
-	throw Error(
+        && oURL.find("https://") == string::npos)
+        throw Error(
             "The URL does not start with 'http' or 'https,' I won't try connecting.");
 
 /* -------------------------------------------------------------------- */
@@ -369,7 +339,7 @@ DODSDataset::connect_to_server() throw(Error)
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we have a overridding AIS file location, apply it now.       */
+/*      If we have a overriding AIS file location, apply it now.       */
 /* -------------------------------------------------------------------- */
     if( CPLGetConfigOption( "DODS_AIS_FILE", NULL ) != NULL )
     {
@@ -404,7 +374,10 @@ string DODSDataset::SubConstraint( string raw_constraint,
                                    string y_constraint )
 
 {
-    string::size_type x_off, y_off, x_len=3, y_len=3;
+    string::size_type x_off;
+    string::size_type y_off;
+    string::size_type x_len = 3;
+    string::size_type y_len = 3;
     string final_constraint;
 
     x_off = raw_constraint.find( "[x]" );
@@ -488,7 +461,7 @@ char **DODSDataset::CollectBandsFromDDSVar( string oVarName,
                                             char **papszResultList )
 
 {
-    Array *poArray;
+    Array *poArray = NULL;
     Grid *poGrid = NULL;
 
 /* -------------------------------------------------------------------- */
@@ -515,7 +488,7 @@ char **DODSDataset::CollectBandsFromDDSVar( string oVarName,
 /*      Eventually we will want to support arrays with more than two    */
 /*      dimensions ... but not quite yet.                               */
 /* -------------------------------------------------------------------- */
-    if( poArray->dimensions() != 2 )
+    if( poArray == NULL || poArray->dimensions() != 2 )
         return papszResultList;
 
 /* -------------------------------------------------------------------- */
@@ -535,14 +508,15 @@ char **DODSDataset::CollectBandsFromDDSVar( string oVarName,
 /* -------------------------------------------------------------------- */
     string dim1_name = poArray->dimension_name( dim1 );
     string dim2_name = poArray->dimension_name( dim2 );
-    int iXDim=-1, iYDim=-1;
+    int iXDim = -1;
+    int iYDim = -1;
 
     if( dim1_name == "easting" && dim2_name == "northing" )
     {
         iXDim = 0;
         iYDim = 1;
     }
-    else if( dim1_name == "easting" && dim2_name == "northing" )
+    else if( dim1_name == "northing" && dim2_name == "easting" )
     {
         iXDim = 1;
         iYDim = 0;
@@ -709,16 +683,16 @@ void DODSDataset::HarvestDAS()
     {
         poFileInfo = oDAS.get_table( "NC_GLOBAL" );
 
-	if( poFileInfo == NULL )
-	{
-	    poFileInfo = oDAS.get_table( "HDF_GLOBAL" );
+        if( poFileInfo == NULL )
+        {
+            poFileInfo = oDAS.get_table( "HDF_GLOBAL" );
 
-	    if( poFileInfo == NULL )
-	    {
-	        CPLDebug( "DODS", "No GLOBAL DAS info." );
-	        return;
-	    }
-	}
+            if( poFileInfo == NULL )
+            {
+                CPLDebug( "DODS", "No GLOBAL DAS info." );
+                return;
+            }
+        }
     }
 #else
     AttrTable *poFileInfo = oDAS.find_container( "GLOBAL" );
@@ -727,16 +701,16 @@ void DODSDataset::HarvestDAS()
     {
         poFileInfo = oDAS.find_container( "NC_GLOBAL" );
 
-	if( poFileInfo == NULL )
-	{
-	    poFileInfo = oDAS.find_container( "HDF_GLOBAL" );
+        if( poFileInfo == NULL )
+        {
+            poFileInfo = oDAS.find_container( "HDF_GLOBAL" );
 
-	    if( poFileInfo == NULL )
-	    {
-	        CPLDebug( "DODS", "No GLOBAL DAS info." );
-	        return;
-	    }
-	}
+            if( poFileInfo == NULL )
+            {
+                CPLDebug( "DODS", "No GLOBAL DAS info." );
+                return;
+            }
+        }
     }
 #endif
 
@@ -851,7 +825,8 @@ void DODSDataset::HarvestMaps( string oVarName, string oCE )
 /* -------------------------------------------------------------------- */
 /*      Get the map arrays for x and y.                                 */
 /* -------------------------------------------------------------------- */
-    Array *poXMap = NULL, *poYMap = NULL;
+    Array *poXMap = NULL;
+    Array *poYMap = NULL;
     int iXDim = GetDimension( oCE, "x", NULL );
     int iYDim = GetDimension( oCE, "y", NULL );
     int iMap;
@@ -975,7 +950,6 @@ DODSDataset::Open(GDALOpenInfo *poOpenInfo)
         && !STARTS_WITH_CI(poOpenInfo->pszFilename, "https://") )
         return NULL;
 
-
     DODSDataset *poDS = new DODSDataset();
     char **papszVarConstraintList = NULL;
 
@@ -1006,9 +980,9 @@ DODSDataset::Open(GDALOpenInfo *poOpenInfo)
 /*      Get the AISConnect instance and the DAS and DDS for this        */
 /*      server.                                                         */
 /* -------------------------------------------------------------------- */
-	poDS->poConnect = poDS->connect_to_server();
-	poDS->poConnect->request_das(poDS->oDAS);
-	poDS->poConnect->request_dds(*(poDS->poDDS));
+        poDS->poConnect = poDS->connect_to_server();
+        poDS->poConnect->request_das(poDS->oDAS);
+        poDS->poConnect->request_dds(*(poDS->poDDS));
 
 /* -------------------------------------------------------------------- */
 /*      If we are given a constraint/projection list, then parse it     */
@@ -1044,7 +1018,7 @@ DODSDataset::Open(GDALOpenInfo *poOpenInfo)
         poDS->nRasterXSize = poBaseBand->GetXSize();
         poDS->nRasterYSize = poBaseBand->GetYSize();
 
-	poDS->SetBand(1, poBaseBand );
+        poDS->SetBand(1, poBaseBand );
 
         for( int iBand = 1; papszVarConstraintList[iBand*2] != NULL; iBand++ )
         {
@@ -1130,24 +1104,23 @@ DODSDataset::GetProjectionRef()
 /*                           DODSRasterBand()                           */
 /************************************************************************/
 
-DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
-                               string oCEIn, int nOverviewFactorIn )
+DODSRasterBand::DODSRasterBand( DODSDataset *poDSIn, string oVarNameIn,
+                                string oCEIn, int nOverviewFactorIn ) :
+    oVarName(oVarNameIn),
+    oCE(oCEIn),
+    eColorInterp(GCI_Undefined),
+    poCT(NULL),
+    nOverviewCount(0),
+    papoOverviewBand(NULL),
+    nOverviewFactor(nOverviewFactorIn),
+    bTranspose(FALSE),
+    bFlipX(FALSE),
+    bFlipY(FALSE),
+    bNoDataSet(FALSE),
+    dfNoDataValue(0.0)
 {
     poDS = poDSIn;
 
-    bTranspose = FALSE;
-    bFlipX = FALSE;
-    bFlipY = FALSE;
-
-    oVarName = oVarNameIn;
-    oCE = oCEIn;
-    nOverviewFactor = nOverviewFactorIn;
-    eColorInterp = GCI_Undefined;
-    poCT = NULL;
-
-    nOverviewCount = 0;
-    papoOverviewBand = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Fetch the DDS definition, and isolate the Array.                */
 /* -------------------------------------------------------------------- */
@@ -1157,6 +1130,7 @@ DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
         throw InternalErr(
             CPLSPrintf( "Could not find DDS definition for variable %s.",
                         oVarNameIn.c_str() ) );
+        // cppcheck-suppress duplicateBreak
         return;
     }
 
@@ -1193,7 +1167,7 @@ DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
       case dods_float32_c: eDataType = GDT_Float32; break;
       case dods_float64_c: eDataType = GDT_Float64; break;
       default:
-	throw Error("The DODS GDAL driver supports only numeric data types.");
+        throw Error("The DODS GDAL driver supports only numeric data types.");
     }
 
 /* -------------------------------------------------------------------- */
@@ -1205,7 +1179,8 @@ DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
         throw Error("Variable does not have even 2 dimensions.  For now this is required." );
     }
 
-    int nXDir = 1, nYDir = 1;
+    int nXDir = 1;
+    int nYDir = 1;
     int iXDim = GetDimension( oCE, "x", &nXDir );
     int iYDim = GetDimension( oCE, "y", &nYDir );
 
@@ -1236,22 +1211,22 @@ DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
     if( nBytesPerPixel == 1 )
     {
         nBlockXSize = 1024;
-        nBlockYSize= 256;
+        nBlockYSize = 256;
     }
     else if( nBytesPerPixel == 2 )
     {
         nBlockXSize = 512;
-        nBlockYSize= 256;
+        nBlockYSize = 256;
     }
     else if( nBytesPerPixel == 4 )
     {
         nBlockXSize = 512;
-        nBlockYSize= 128;
+        nBlockYSize = 128;
     }
     else
     {
         nBlockXSize = 256;
-        nBlockYSize= 128;
+        nBlockYSize = 128;
     }
 
     if( nRasterXSize < nBlockXSize * 2 )
@@ -1271,15 +1246,13 @@ DODSRasterBand::DODSRasterBand(DODSDataset *poDSIn, string oVarNameIn,
 /* -------------------------------------------------------------------- */
     if( nOverviewFactorIn == 1 )
     {
-        int iOverview;
-
         nOverviewCount = 0;
         papoOverviewBand = (DODSRasterBand **)
             CPLCalloc( sizeof(void*), 8 );
 
-        for( iOverview = 1; iOverview < 8; iOverview++ )
+        for( int iOverview = 1; iOverview < 8; iOverview++ )
         {
-            int nThisFactor = 1 << iOverview;
+            const int nThisFactor = 1 << iOverview;
 
             if( nRasterXSize / nThisFactor < 128
                 && nRasterYSize / nThisFactor < 128 )
@@ -1318,6 +1291,8 @@ void DODSRasterBand::HarvestDAS()
 
 {
     DODSDataset *poDODS = dynamic_cast<DODSDataset *>(poDS);
+    if( poDODS == NULL )
+        return;
 
 /* -------------------------------------------------------------------- */
 /*      Try and fetch the corresponding DAS subtree if it exists.       */
@@ -1372,14 +1347,12 @@ void DODSRasterBand::HarvestDAS()
 /* -------------------------------------------------------------------- */
 /* Try _FillValue                                                       */
 /* -------------------------------------------------------------------- */
-	oValue = poBandInfo->get_attr( "_FillValue" );
-	if( oValue != "" ) {
-	    SetNoDataValue( CPLAtof(oValue.c_str()) );
-	}
+        oValue = poBandInfo->get_attr( "_FillValue" );
+        if( oValue != "" ) {
+            SetNoDataValue( CPLAtof(oValue.c_str()) );
+        }
     }
 
-
-
 /* -------------------------------------------------------------------- */
 /*      Collect color table                                             */
 /* -------------------------------------------------------------------- */
@@ -1500,11 +1473,12 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
 /* -------------------------------------------------------------------- */
         BaseType *poBt = get_variable(data, oVarName );
         if (!poBt)
-            throw Error(string("I could not read the variable '")
-		    + oVarName		    + string("' from the data source at:\n")
-		    + poDODS->GetUrl() );
+            throw Error(
+                string("I could not read the variable '")
+                + oVarName + string("' from the data source at:\n")
+                + poDODS->GetUrl() );
 
-        Array *poA;
+        Array *poA = NULL;
         switch (poBt->type()) {
           case dods_grid_c:
             poA = dynamic_cast<Array*>(dynamic_cast<Grid*>(poBt)->array_var());
@@ -1530,7 +1504,7 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
 /*      Dump the contents of the Array data into our output image buffer.*/
 /*                                                                      */
 /* -------------------------------------------------------------------- */
-        poA->buf2val(&pImage);	// !Suck the data out of the Array!
+        poA->buf2val(&pImage);  // !Suck the data out of the Array!
 
 /* -------------------------------------------------------------------- */
 /*      If the [x] dimension comes before [y], we need to transpose     */
@@ -1538,13 +1512,12 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
 /* -------------------------------------------------------------------- */
         if( bTranspose )
         {
-            GByte *pabyDataCopy;
             int iY;
 
             CPLDebug( "DODS", "Applying transposition" );
 
             // make a copy of the original
-            pabyDataCopy = (GByte *)
+            GByte *pabyDataCopy = (GByte *)
                 CPLMalloc(nBytesPerPixel * nXSize * nYSize);
             memcpy( pabyDataCopy, pImage, nBytesPerPixel * nXSize * nYSize );
             memset( pImage, 0, nBytesPerPixel * nXSize * nYSize );
@@ -1566,13 +1539,12 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
 /* -------------------------------------------------------------------- */
         if( bFlipX )
         {
-            GByte *pabyDataCopy;
             int iY;
 
             CPLDebug( "DODS", "Applying X flip." );
 
             // make a copy of the original
-            pabyDataCopy = (GByte *)
+            GByte *pabyDataCopy = (GByte *)
                 CPLMalloc(nBytesPerPixel * nXSize * nYSize);
             memcpy( pabyDataCopy, pImage, nBytesPerPixel * nXSize * nYSize );
             memset( pImage, 0, nBytesPerPixel * nXSize * nYSize );
@@ -1594,13 +1566,12 @@ DODSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
 /* -------------------------------------------------------------------- */
         if( bFlipY )
         {
-            GByte *pabyDataCopy;
             int iY;
 
             CPLDebug( "DODS", "Applying Y flip." );
 
             // make a copy of the original
-            pabyDataCopy = (GByte *)
+            GByte *pabyDataCopy = (GByte *)
                 CPLMalloc(nBytesPerPixel * nXSize * nYSize);
             memcpy( pabyDataCopy, pImage, nBytesPerPixel * nXSize * nYSize );
 
diff --git a/frmts/dods/libdap_headers.h b/frmts/dods/libdap_headers.h
new file mode 100644
index 0000000..85ca0b2
--- /dev/null
+++ b/frmts/dods/libdap_headers.h
@@ -0,0 +1,67 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes libdap headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef LIBDAP_HEADERS_H
+#define LIBDAP_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#include <BaseType.h>  // DODS
+#include <Byte.h>
+#include <Int16.h>
+#include <UInt16.h>
+#include <Int32.h>
+#include <UInt32.h>
+#include <Float32.h>
+#include <Float64.h>
+#include <Str.h>
+#include <Url.h>
+#include <Array.h>
+#include <Structure.h>
+#include <Sequence.h>
+#include <Grid.h>
+
+#ifdef LIBDAP_310
+/* AISConnect.h/AISConnect class was renamed to Connect.h/Connect in libdap 3.10 */
+#include <Connect.h>
+#define AISConnect Connect
+#else
+#include <AISConnect.h>
+#endif
+
+#include <DDS.h>
+#include <DAS.h>
+#include <BaseTypeFactory.h>
+#include <Error.h>
+#include <escaping.h>
+
+#endif
diff --git a/frmts/dted/dted_api.c b/frmts/dted/dted_api.c
index 09c3f39..fe8ac67 100644
--- a/frmts/dted/dted_api.c
+++ b/frmts/dted/dted_api.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_api.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: dted_api.c 36422 2016-11-22 00:10:35Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  Implementation of DTED/CDED access functions.
@@ -31,7 +31,7 @@
 #include "dted_api.h"
 
 #ifndef AVOID_CPL
-CPL_CVSID("$Id: dted_api.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: dted_api.c 36422 2016-11-22 00:10:35Z rouault $");
 #endif
 
 static int bWarnedTwoComplement = FALSE;
@@ -1034,6 +1034,7 @@ int DTEDSetMetadata( DTEDInfo *psDInfo, DTEDMetaDataCode eCode,
 /*      Update it, padding with spaces.                                 */
 /* -------------------------------------------------------------------- */
     memset( pszFieldSrc, ' ', nFieldLen );
+    /* cppcheck-suppress redundantCopy */
     strncpy( pszFieldSrc, pszNewValue,
              MIN((size_t)nFieldLen,strlen(pszNewValue)) );
 
diff --git a/frmts/dted/dted_api.h b/frmts/dted/dted_api.h
index 328b7fe..991b989 100644
--- a/frmts/dted/dted_api.h
+++ b/frmts/dted/dted_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_api.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: dted_api.h 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  DTED Translator
  * Purpose:  Public (C callable) interface for DTED/CDED reading.
diff --git a/frmts/dted/dted_create.c b/frmts/dted/dted_create.c
index 72d081e..d77d709 100644
--- a/frmts/dted/dted_create.c
+++ b/frmts/dted/dted_create.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_create.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: dted_create.c 36380 2016-11-21 10:21:20Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  Implementation of DTEDCreate() portion of DTED API.
@@ -30,7 +30,7 @@
 #include "dted_api.h"
 #include <assert.h>
 
-CPL_CVSID("$Id: dted_create.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: dted_create.c 36380 2016-11-21 10:21:20Z rouault $");
 
 #define DTED_ABS_VERT_ACC "NA  "
 #define DTED_SECURITY     "U"
@@ -40,12 +40,14 @@ CPL_CVSID("$Id: dted_create.c 33720 2016-03-15 00:39:53Z goatbar $");
 /*                           DTEDFormatDMS()                            */
 /************************************************************************/
 
-static void DTEDFormatDMS( unsigned char *achField, double dfAngle,
+static void DTEDFormatDMS( unsigned char *achField,
+                           size_t nTargetLenSize,
+                           size_t nOffset,
+                           double dfAngle,
                            const char *pszLatLong, const char *pszFormat )
 
 {
     char        chHemisphere;
-    char        szWork[128];
     int         nDegrees, nMinutes, nSeconds;
     double      dfRemainder;
 
@@ -77,31 +79,33 @@ static void DTEDFormatDMS( unsigned char *achField, double dfAngle,
     dfRemainder = dfRemainder - nMinutes / 60.0;
     nSeconds = (int) floor(dfRemainder * 3600.0 + 0.5);
 
-    snprintf( szWork, sizeof(szWork),pszFormat,
-             nDegrees, nMinutes, nSeconds, chHemisphere );
-
-    strncpy( (char *) achField, szWork, strlen(szWork) );
+    snprintf( (char*)achField + nOffset, nTargetLenSize - nOffset,
+              pszFormat,
+              nDegrees, nMinutes, nSeconds, chHemisphere );
 }
 
 /************************************************************************/
 /*                             DTEDFormat()                             */
 /************************************************************************/
 
-static void DTEDFormat( unsigned char *pszTarget, const char *pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (2, 3);
+static void DTEDFormat( unsigned char *pszTarget,
+                        size_t nTargetLenSize,
+                        size_t nOffset,
+                        const char *pszFormat, ... )
+                                                CPL_PRINT_FUNC_FORMAT (4, 5);
 
-static void DTEDFormat( unsigned char *pszTarget, const char *pszFormat, ... )
+static void DTEDFormat( unsigned char *pszTarget,
+                        size_t nTargetLenSize,
+                        size_t nOffset,
+                        const char *pszFormat, ... )
 
 {
     va_list args;
-    char    szWork[512];
-    // Quiet coverity by staring off nul terminated.
-    szWork[0] = '\0';
 
     va_start(args, pszFormat);
-    CPLvsnprintf( szWork, sizeof(szWork), pszFormat, args );
+    CPLvsnprintf( (char*)pszTarget + nOffset, nTargetLenSize - nOffset,
+                  pszFormat, args );
     va_end(args);
-
-    strncpy( (char *) pszTarget, szWork, strlen(szWork) );
 }
 
 /************************************************************************/
@@ -115,7 +119,6 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
     VSILFILE     *fp;
     unsigned char achRecord[3601*2 + 12];
     int         nXSize, nYSize, iProfile;
-    static char szError[512];
 
 /* -------------------------------------------------------------------- */
 /*      Establish resolution.                                           */
@@ -137,9 +140,8 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
     }
     else
     {
-        snprintf( szError, sizeof(szError), "Illegal DTED Level value %d, only 0-2 allowed.",
+        return CPLSPrintf( "Illegal DTED Level value %d, only 0-2 allowed.",
                  nLevel );
-        return szError;
     }
 
     if( ABS(nLLOriginLat) >= 80 )
@@ -158,8 +160,7 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
 
     if( fp == NULL )
     {
-        snprintf( szError, sizeof(szError), "Unable to create file `%s'.", pszFilename );
-        return szError;
+        return CPLSPrintf( "Unable to create file `%s'.", pszFilename );
     }
 
 /* -------------------------------------------------------------------- */
@@ -167,19 +168,21 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
 /* -------------------------------------------------------------------- */
     memset( achRecord, ' ', DTED_UHL_SIZE );
 
-    DTEDFormat( achRecord + 0, "UHL1" );
+    DTEDFormat( achRecord, sizeof(achRecord), 0, "UHL1" );
 
-    DTEDFormatDMS( achRecord + 4, nLLOriginLong, "LONG", NULL );
-    DTEDFormatDMS( achRecord + 12, nLLOriginLat, "LAT", NULL );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 4, nLLOriginLong, "LONG", NULL );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 12, nLLOriginLat, "LAT", NULL );
 
-    DTEDFormat( achRecord + 20, "%04d", (3600 / (nXSize-1)) * 10 );
-    DTEDFormat( achRecord + 24, "%04d", (3600 / (nYSize-1)) * 10 );
+    DTEDFormat( achRecord, sizeof(achRecord), 20,
+                "%04d", (3600 / (nXSize-1)) * 10 );
+    DTEDFormat( achRecord, sizeof(achRecord), 24,
+                "%04d", (3600 / (nYSize-1)) * 10 );
 
-    DTEDFormat( achRecord + 28, "%4s", DTED_ABS_VERT_ACC );
-    DTEDFormat( achRecord + 32, "%-3s", DTED_SECURITY );
-    DTEDFormat( achRecord + 47, "%04d", nXSize );
-    DTEDFormat( achRecord + 51, "%04d", nYSize );
-    DTEDFormat( achRecord + 55, "%c", '0' );
+    DTEDFormat( achRecord, sizeof(achRecord), 28, "%4s", DTED_ABS_VERT_ACC );
+    DTEDFormat( achRecord, sizeof(achRecord), 32, "%-3s", DTED_SECURITY );
+    DTEDFormat( achRecord, sizeof(achRecord), 47, "%04d", nXSize );
+    DTEDFormat( achRecord, sizeof(achRecord), 51, "%04d", nYSize );
+    DTEDFormat( achRecord, sizeof(achRecord), 55, "%c", '0' );
 
     if( VSIFWriteL( achRecord, DTED_UHL_SIZE, 1, fp ) != 1 )
         return "UHL record write failed.";
@@ -189,53 +192,63 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
 /* -------------------------------------------------------------------- */
     memset( achRecord, ' ', DTED_DSI_SIZE );
 
-    DTEDFormat( achRecord + 0, "DSI" );
-    DTEDFormat( achRecord + 3, "%1s", DTED_SECURITY );
-
-    DTEDFormat( achRecord + 59, "DTED%d", nLevel );
-    DTEDFormat( achRecord + 64, "%015d", 0 );
-    DTEDFormat( achRecord + 87, "%02d", DTED_EDITION );
-    DTEDFormat( achRecord + 89, "%c", 'A' );
-    DTEDFormat( achRecord + 90, "%04d", 0 );
-    DTEDFormat( achRecord + 94, "%04d", 0 );
-    DTEDFormat( achRecord + 98, "%04d", 0 );
-    DTEDFormat( achRecord + 126, "PRF89020B");
-    DTEDFormat( achRecord + 135, "00");
-    DTEDFormat( achRecord + 137, "0005");
-    DTEDFormat( achRecord + 141, "MSL" );
-    DTEDFormat( achRecord + 144, "WGS84" );
+    DTEDFormat( achRecord, sizeof(achRecord), 0, "DSI" );
+    DTEDFormat( achRecord, sizeof(achRecord), 3, "%1s", DTED_SECURITY );
+
+    DTEDFormat( achRecord, sizeof(achRecord), 59, "DTED%d", nLevel );
+    DTEDFormat( achRecord, sizeof(achRecord), 64, "%015d", 0 );
+    DTEDFormat( achRecord, sizeof(achRecord), 87, "%02d", DTED_EDITION );
+    DTEDFormat( achRecord, sizeof(achRecord), 89, "%c", 'A' );
+    DTEDFormat( achRecord, sizeof(achRecord), 90, "%04d", 0 );
+    DTEDFormat( achRecord, sizeof(achRecord), 94, "%04d", 0 );
+    DTEDFormat( achRecord, sizeof(achRecord), 98, "%04d", 0 );
+    DTEDFormat( achRecord, sizeof(achRecord), 126, "PRF89020B");
+    DTEDFormat( achRecord, sizeof(achRecord), 135, "00");
+    DTEDFormat( achRecord, sizeof(achRecord), 137, "0005");
+    DTEDFormat( achRecord, sizeof(achRecord), 141, "MSL" );
+    DTEDFormat( achRecord, sizeof(achRecord), 144, "WGS84" );
 
     /* origin */
-    DTEDFormatDMS( achRecord + 185, nLLOriginLat, "LAT",
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 185, nLLOriginLat, "LAT",
                    "%02d%02d%02d.0%c" );
-    DTEDFormatDMS( achRecord + 194, nLLOriginLong, "LONG",
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 194, nLLOriginLong, "LONG",
                    "%03d%02d%02d.0%c" );
 
     /* SW */
-    DTEDFormatDMS( achRecord + 204, nLLOriginLat, "LAT", "%02d%02d%02d%c" );
-    DTEDFormatDMS( achRecord + 211, nLLOriginLong, "LONG", NULL );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 204,
+                   nLLOriginLat, "LAT", "%02d%02d%02d%c" );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 211,
+                   nLLOriginLong, "LONG", NULL );
 
     /* NW */
-    DTEDFormatDMS( achRecord + 219, nLLOriginLat+1, "LAT", "%02d%02d%02d%c" );
-    DTEDFormatDMS( achRecord + 226, nLLOriginLong, "LONG", NULL );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 219,
+                   nLLOriginLat+1, "LAT", "%02d%02d%02d%c" );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 226,
+                   nLLOriginLong, "LONG", NULL );
 
     /* NE */
-    DTEDFormatDMS( achRecord + 234, nLLOriginLat+1, "LAT", "%02d%02d%02d%c" );
-    DTEDFormatDMS( achRecord + 241, nLLOriginLong+1, "LONG", NULL );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 234,
+                   nLLOriginLat+1, "LAT", "%02d%02d%02d%c" );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 241,
+                   nLLOriginLong+1, "LONG", NULL );
 
     /* SE */
-    DTEDFormatDMS( achRecord + 249, nLLOriginLat, "LAT", "%02d%02d%02d%c" );
-    DTEDFormatDMS( achRecord + 256, nLLOriginLong+1, "LONG", NULL );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 249,
+                   nLLOriginLat, "LAT", "%02d%02d%02d%c" );
+    DTEDFormatDMS( achRecord, sizeof(achRecord), 256,
+                   nLLOriginLong+1, "LONG", NULL );
 
-    DTEDFormat( achRecord + 264, "0000000.0" );
-    DTEDFormat( achRecord + 264, "0000000.0" );
+    DTEDFormat( achRecord, sizeof(achRecord), 264, "0000000.0" );
+    DTEDFormat( achRecord, sizeof(achRecord), 264, "0000000.0" );
 
-    DTEDFormat( achRecord + 273, "%04d", (3600 / (nYSize-1)) * 10 );
-    DTEDFormat( achRecord + 277, "%04d", (3600 / (nXSize-1)) * 10 );
+    DTEDFormat( achRecord, sizeof(achRecord), 273,
+                "%04d", (3600 / (nYSize-1)) * 10 );
+    DTEDFormat( achRecord, sizeof(achRecord), 277,
+                "%04d", (3600 / (nXSize-1)) * 10 );
 
-    DTEDFormat( achRecord + 281, "%04d", nYSize );
-    DTEDFormat( achRecord + 285, "%04d", nXSize );
-    DTEDFormat( achRecord + 289, "%02d", 0 );
+    DTEDFormat( achRecord, sizeof(achRecord), 281, "%04d", nYSize );
+    DTEDFormat( achRecord, sizeof(achRecord), 285, "%04d", nXSize );
+    DTEDFormat( achRecord, sizeof(achRecord), 289, "%02d", 0 );
 
     if( VSIFWriteL( achRecord, DTED_DSI_SIZE, 1, fp ) != 1 )
         return "DSI record write failed.";
@@ -245,14 +258,14 @@ const char *DTEDCreate( const char *pszFilename, int nLevel,
 /* -------------------------------------------------------------------- */
     memset( achRecord, ' ', DTED_ACC_SIZE );
 
-    DTEDFormat( achRecord + 0, "ACC" );
+    DTEDFormat( achRecord, sizeof(achRecord), 0, "ACC" );
 
-    DTEDFormat( achRecord + 3, "NA" );
-    DTEDFormat( achRecord + 7, "NA" );
-    DTEDFormat( achRecord + 11, "NA" );
-    DTEDFormat( achRecord + 15, "NA" );
+    DTEDFormat( achRecord, sizeof(achRecord), 3, "NA" );
+    DTEDFormat( achRecord, sizeof(achRecord), 7, "NA" );
+    DTEDFormat( achRecord, sizeof(achRecord), 11, "NA" );
+    DTEDFormat( achRecord, sizeof(achRecord), 15, "NA" );
 
-    DTEDFormat( achRecord + 55, "00" );
+    DTEDFormat( achRecord, sizeof(achRecord), 55, "00" );
 
     if( VSIFWriteL( achRecord, DTED_ACC_SIZE, 1, fp ) != 1 )
         return "ACC record write failed.";
diff --git a/frmts/dted/dted_ptstream.c b/frmts/dted/dted_ptstream.c
index ba3961d..3cb1478 100644
--- a/frmts/dted/dted_ptstream.c
+++ b/frmts/dted/dted_ptstream.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_ptstream.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: dted_ptstream.c 35839 2016-10-20 21:17:17Z rouault $
  *
  * Project:  DTED Translator
  * Purpose:  DTED Point Stream Writer.
@@ -29,7 +29,7 @@
 
 #include "dted_api.h"
 
-CPL_CVSID("$Id: dted_ptstream.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: dted_ptstream.c 35839 2016-10-20 21:17:17Z rouault $");
 
 typedef struct {
     char     *pszFilename;
@@ -101,9 +101,7 @@ void *DTEDCreatePtStream( const char *pszPath, int nLevel )
         psStream->dfPixelSize = 1.0 / 120.0;
     else if( nLevel == 1 )
         psStream->dfPixelSize = 1.0 / 1200.0;
-    else if( nLevel == 2 )
-        psStream->dfPixelSize = 1.0 / 3600.0;
-    else
+    else /* if( nLevel == 2 ) */
         psStream->dfPixelSize = 1.0 / 3600.0;
 
     return (void *) psStream;
diff --git a/frmts/dted/dted_test.c b/frmts/dted/dted_test.c
index 43a129f..3fa45c4 100644
--- a/frmts/dted/dted_test.c
+++ b/frmts/dted/dted_test.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dted_test.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: dted_test.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  DTED Translator
  * Purpose:  Test mainline for DTED writer.
diff --git a/frmts/dted/dteddataset.cpp b/frmts/dted/dteddataset.cpp
index eac7816..b8ba463 100644
--- a/frmts/dted/dteddataset.cpp
+++ b/frmts/dted/dteddataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dteddataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  DTED Translator
  * Purpose:  GDALDataset driver for DTED translator.
@@ -33,9 +32,10 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
+#include <cstdlib>
 #include <algorithm>
 
-CPL_CVSID("$Id: dteddataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: dteddataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -58,8 +58,8 @@ class DTEDDataset : public GDALPamDataset
                  DTEDDataset();
     virtual     ~DTEDDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     const char* GetFileName() { return pszFilename; }
     void SetFileName(const char* pszFilename);
@@ -78,36 +78,34 @@ class DTEDRasterBand : public GDALPamRasterBand
 {
     friend class DTEDDataset;
 
-    int 	bNoDataSet;
-    double	dfNoDataValue;
+    int         bNoDataSet;
+    double      dfNoDataValue;
 
   public:
 
                 DTEDRasterBand( DTEDDataset *, int );
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 
-    virtual double  GetNoDataValue( int *pbSuccess = NULL );
+    virtual double  GetNoDataValue( int *pbSuccess = NULL ) override;
 
-    virtual const char* GetUnitType() { return "m"; }
+    virtual const char* GetUnitType() override { return "m"; }
 };
 
-
 /************************************************************************/
 /*                           DTEDRasterBand()                            */
 /************************************************************************/
 
 DTEDRasterBand::DTEDRasterBand( DTEDDataset *poDSIn, int nBandIn ) :
-    bNoDataSet(TRUE)
+    bNoDataSet(TRUE),
+    dfNoDataValue(static_cast<double>(DTED_NODATA_VALUE))
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Int16;
 
-    dfNoDataValue = (double) DTED_NODATA_VALUE;
-
     /* For some applications, it may be valuable to consider the whole DTED */
     /* file as single block, as the column orientation doesn't fit very well */
     /* with some scanline oriented algorithms */
@@ -201,11 +199,9 @@ CPLErr DTEDRasterBand::IWriteBlock( int nBlockXOff,
     {
         panData = (GInt16 *) pImage;
         GInt16* panBuffer = (GInt16*) CPLMalloc(sizeof(GInt16) * nBlockYSize);
-        int i;
-        for(i=0;i<nBlockXSize;i++)
+        for( int i = 0; i < nBlockXSize; i++ )
         {
-            int j;
-            for(j=0;j<nBlockYSize;j++)
+            for( int j = 0; j < nBlockYSize; j++ )
             {
                 panBuffer[j] = panData[j * nBlockXSize + i];
             }
@@ -244,12 +240,13 @@ double DTEDRasterBand::GetNoDataValue( int * pbSuccess )
 /*                            ~DTEDDataset()                            */
 /************************************************************************/
 
-DTEDDataset::DTEDDataset() : psDTED(NULL)
-{
-    pszFilename = CPLStrdup("unknown");
-    pszProjection = CPLStrdup("");
-    bVerifyChecksum = CPLTestBool(CPLGetConfigOption("DTED_VERIFY_CHECKSUM", "NO"));
-}
+DTEDDataset::DTEDDataset() :
+    pszFilename(CPLStrdup("unknown")),
+    psDTED(NULL),
+    bVerifyChecksum(CPLTestBool(
+        CPLGetConfigOption("DTED_VERIFY_CHECKSUM", "NO"))),
+    pszProjection(CPLStrdup(""))
+{}
 
 /************************************************************************/
 /*                            ~DTEDDataset()                            */
@@ -331,7 +328,7 @@ GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
                          (poOpenInfo->eAccess == GA_Update) ? "rb+" : "rb", TRUE );
 
     if( psDTED == NULL )
-        return( NULL );
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
@@ -365,9 +362,8 @@ GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Collect any metadata available.                                 */
 /* -------------------------------------------------------------------- */
-    char *pszValue;
-
-    pszValue = DTEDGetMetadata( psDTED, DTEDMD_VERTACCURACY_UHL );
+    char *pszValue =
+        DTEDGetMetadata( psDTED, DTEDMD_VERTACCURACY_UHL );
     poDS->SetMetadataItem( "DTED_VerticalAccuracy_UHL", pszValue );
     CPLFree( pszValue );
 
@@ -498,7 +494,7 @@ GDALDataset *DTEDDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
                                  poOpenInfo->GetSiblingFiles() );
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -515,7 +511,7 @@ CPLErr DTEDDataset::GetGeoTransform( double * padfTransform )
     padfTransform[4] = 0.0;
     padfTransform[5] = psDTED->dfPixelSizeY * -1;
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -536,7 +532,11 @@ const char *DTEDDataset::GetProjectionRef()
     pszPrj = GetMetadataItem( "DTED_HorizontalDatum");
     if (EQUAL(pszPrj, "WGS84"))
     {
-        return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
+        return
+            "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\","
+            "SPHEROID[\"WGS 84\",6378137,298.257223563]],"
+            "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],"
+            "AUTHORITY[\"EPSG\",\"4326\"]]";
     }
     else if (EQUAL(pszPrj, "WGS72"))
     {
@@ -565,7 +565,11 @@ const char *DTEDDataset::GetProjectionRef()
                       "The DTED driver is going to consider it as WGS84.\n"
                       "No more warnings will be issued in this session about this operation.", GetFileName(), pszPrj );
         }
-        return( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]]" );
+        return
+            "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\","
+            "SPHEROID[\"WGS 84\",6378137,298.257223563]],"
+            "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],"
+            "AUTHORITY[\"EPSG\",\"4326\"]]";
     }
 }
 
@@ -664,13 +668,13 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*     Check horizontal source size.                                    */
 /* -------------------------------------------------------------------- */
     int expectedXSize;
-    if( ABS(nLLOriginLat) >= 80 )
+    if( std::abs(nLLOriginLat) >= 80 )
         expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 6 + 1;
-    else if( ABS(nLLOriginLat) >= 75 )
+    else if( std::abs(nLLOriginLat) >= 75 )
         expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 4 + 1;
-    else if( ABS(nLLOriginLat) >= 70 )
+    else if( std::abs(nLLOriginLat) >= 70 )
         expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 3 + 1;
-    else if( ABS(nLLOriginLat) >= 50 )
+    else if( std::abs(nLLOriginLat) >= 50 )
         expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 2 + 1;
     else
         expectedXSize = poSrcDS->GetRasterYSize();
@@ -789,7 +793,8 @@ DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         if (iPartialCell < 1)
            iPartialCell=1;
     }
-    snprintf( szPartialCell, sizeof(szPartialCell), "%02d",iPartialCell);
+
+    CPLsnprintf( szPartialCell, sizeof(szPartialCell), "%02d",iPartialCell);
     DTEDSetMetadata(psDTED, DTEDMD_PARTIALCELL_DSI, szPartialCell);
 
 /* -------------------------------------------------------------------- */
diff --git a/frmts/e00grid/e00compr.h b/frmts/e00grid/e00compr.h
index 73eba07..2fa6b5b 100644
--- a/frmts/e00grid/e00compr.h
+++ b/frmts/e00grid/e00compr.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: e00compr.h,v 1.10 2009-02-24 20:03:50 aboudreault Exp $
+ * $Id: e00compr.h 35885 2016-10-24 06:23:09Z goatbar $
  *
  * Name:     e00compr.h
  * Project:  Compressed E00 Read/Write library
@@ -60,7 +60,6 @@
 #ifndef E00COMPR_H_INCLUDED_
 #define E00COMPR_H_INCLUDED_
 
-
 #include <stdio.h>
 
 #include "cpl_port.h"
@@ -152,7 +151,6 @@ struct _E00WriteInfo
 
 typedef struct _E00WriteInfo *E00WritePtr;
 
-
 /*=====================================================================
                         Function prototypes
  =====================================================================*/
@@ -173,7 +171,6 @@ E00WritePtr E00WriteCallbackOpen(void *pRefData,
 void        E00WriteClose(E00WritePtr psInfo);
 int         E00WriteNextLine(E00WritePtr psInfo, const char *pszLine);
 
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/frmts/e00grid/e00griddataset.cpp b/frmts/e00grid/e00griddataset.cpp
index 9a9cd8a..6ef06c0 100644
--- a/frmts/e00grid/e00griddataset.cpp
+++ b/frmts/e00grid/e00griddataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: e00griddataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  E00 grid driver
  * Purpose:  GDALDataset driver for E00 grid dataset.
@@ -47,7 +46,7 @@ static const int E00_FLOAT_SIZE = 14;
 static const int E00_DOUBLE_SIZE = 21;
 static const int VALS_PER_LINE = 5;
 
-CPL_CVSID("$Id: e00griddataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: e00griddataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /* g++ -fPIC -Wall -g frmts/e00grid/e00griddataset.cpp -shared -o gdal_E00GRID.so -Iport -Igcore -Iogr -L. -lgdal */
 
@@ -107,8 +106,8 @@ class E00GRIDDataset : public GDALPamDataset
                  E00GRIDDataset();
     virtual     ~E00GRIDDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char* GetProjectionRef();
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char* GetProjectionRef() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -125,21 +124,19 @@ class E00GRIDRasterBand : public GDALPamRasterBand
     friend class E00GRIDDataset;
 
   public:
-
                 E00GRIDRasterBand( E00GRIDDataset *, int, GDALDataType );
 
-    virtual CPLErr      IReadBlock( int, int, void * );
+    virtual CPLErr      IReadBlock( int, int, void * ) override;
 
-    virtual double      GetNoDataValue( int *pbSuccess = NULL );
-    virtual const char *GetUnitType();
-    virtual double      GetMinimum( int *pbSuccess = NULL );
-    virtual double      GetMaximum( int *pbSuccess = NULL );
+    virtual double      GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual const char *GetUnitType() override;
+    virtual double      GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double      GetMaximum( int *pbSuccess = NULL ) override;
     virtual CPLErr      GetStatistics( int bApproxOK, int bForce,
                                        double *pdfMin, double *pdfMax,
-                                       double *pdfMean, double *padfStdDev );
+                                       double *pdfMean, double *padfStdDev ) override;
 };
 
-
 /************************************************************************/
 /*                         E00GRIDRasterBand()                          */
 /************************************************************************/
@@ -148,8 +145,8 @@ E00GRIDRasterBand::E00GRIDRasterBand( E00GRIDDataset *poDSIn, int nBandIn,
                                       GDALDataType eDT )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = eDT;
 
@@ -670,7 +667,7 @@ GDALDataset *E00GRIDDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Support overviews.                                              */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -682,10 +679,9 @@ CPLErr E00GRIDDataset::GetGeoTransform( double * padfTransform )
 {
     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
 
-    return( CE_None );
+    return CE_None;
 }
 
-
 /************************************************************************/
 /*                             ReadLine()                               */
 /************************************************************************/
@@ -816,7 +812,7 @@ void E00GRIDDataset::ReadMetadata()
             return;
     }
 
-    const char* pszLine;
+    const char* pszLine = NULL;
     bool bPRJFound = false;
     bool bStatsFound = false;
     while((pszLine = ReadLine()) != NULL)
diff --git a/frmts/e00grid/e00read.c b/frmts/e00grid/e00read.c
index 1952b02..3f1d3ce 100644
--- a/frmts/e00grid/e00read.c
+++ b/frmts/e00grid/e00read.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: e00read.c,v 1.10 2009-02-24 20:03:50 aboudreault Exp $
+ * $Id: e00read.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Name:     e00read.c
  * Project:  Compressed E00 Read/Write library
diff --git a/frmts/ecw/ecwasyncreader.cpp b/frmts/ecw/ecwasyncreader.cpp
index ccfee05..5a482bc 100644
--- a/frmts/ecw/ecwasyncreader.cpp
+++ b/frmts/ecw/ecwasyncreader.cpp
@@ -1,444 +1,446 @@
-/******************************************************************************
- * $Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $
- *
- * Project:  GDAL 
- * Purpose:  ECWAsyncReader implementation
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2011, Frank Warmerdam <warmerdam at pobox.com>
- * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "gdal_ecw.h"
-
-CPL_CVSID("$Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $");
-
-#if defined(FRMT_ecw) && (ECWSDK_VERSION >= 40)
-
-/************************************************************************/
-/*                          BeginAsyncReader()                          */
-/************************************************************************/
-
-GDALAsyncReader* 
-ECWDataset::BeginAsyncReader( int nXOff, int nYOff, int nXSize, int nYSize, 
-                              void *pBuf, int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType,
-                              int nBandCount, int* panBandMap,
-                              int nPixelSpace, int nLineSpace, int nBandSpace,
-                              char **papszOptions)
-
-{
-    int   i;
-
-/* -------------------------------------------------------------------- */
-/*      Provide default packing if needed.                              */
-/* -------------------------------------------------------------------- */
-    if( nPixelSpace == 0 )
-        nPixelSpace = GDALGetDataTypeSize(eBufType) / 8;
-    if( nLineSpace == 0 )
-        nLineSpace = nPixelSpace * nBufXSize;
-    if( nBandSpace == 0 )
-        nBandSpace = nLineSpace * nBufYSize;
-    
-/* -------------------------------------------------------------------- */
-/*      Do a bit of validation.                                         */
-/* -------------------------------------------------------------------- */
-    if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
-    {
-        CPLDebug( "GDAL", 
-                  "BeginAsyncReader() skipped for odd window or buffer size.\n"
-                  "  Window = (%d,%d)x%dx%d\n"
-                  "  Buffer = %dx%d\n",
-                  nXOff, nYOff, nXSize, nYSize, 
-                  nBufXSize, nBufYSize );
-        return NULL;
-    }
-
-    if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
-        || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
-    {
-        ReportError( CE_Failure, CPLE_IllegalArg,
-                  "Access window out of range in RasterIO().  Requested\n"
-                  "(%d,%d) of size %dx%d on raster of %dx%d.",
-                  nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
-        return NULL;
-    }
-
-    if( nBandCount <= 0 || nBandCount > nBands )
-    {
-        ReportError( CE_Failure, CPLE_IllegalArg, "Invalid band count" );
-        return NULL;
-    }
-
-    if( panBandMap != NULL )
-    {
-        for( i = 0; i < nBandCount; i++ )
-        {
-            if( panBandMap[i] < 1 || panBandMap[i] > nBands )
-            {
-                ReportError( CE_Failure, CPLE_IllegalArg,
-                      "panBandMap[%d] = %d, this band does not exist on dataset.",
-                      i, panBandMap[i] );
-                return NULL;
-            }
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create the corresponding async reader.                          */
-/* -------------------------------------------------------------------- */
-    ECWAsyncReader *poReader = new ECWAsyncReader();
-
-    poReader->poDS = this;
-
-    poReader->nXOff = nXOff;
-    poReader->nYOff = nYOff;
-    poReader->nXSize = nXSize;
-    poReader->nYSize = nYSize;
-
-    poReader->pBuf = pBuf;
-    poReader->nBufXSize = nBufXSize;
-    poReader->nBufYSize = nBufYSize;
-    poReader->eBufType = eBufType;
-    poReader->nBandCount = nBandCount;
-    poReader->panBandMap = (int *) CPLCalloc(sizeof(int),nBandCount);
-    if( panBandMap != NULL )
-    {
-        memcpy( poReader->panBandMap, panBandMap, sizeof(int) * nBandCount );
-    }
-    else
-    {
-        for( i = 0; i < nBandCount; i++ )
-            poReader->panBandMap[i] = i + 1;
-    }
-
-    poReader->nPixelSpace = nPixelSpace;
-    poReader->nLineSpace = nLineSpace;
-    poReader->nBandSpace = nBandSpace;
-
-/* -------------------------------------------------------------------- */
-/*      Create a new view for this request.                             */
-/* -------------------------------------------------------------------- */
-    poReader->poFileView = OpenFileView( GetDescription(), true, 
-                                         poReader->bUsingCustomStream );
-
-    if( poReader->poFileView == NULL )
-    {
-        delete poReader;
-        return NULL;
-    }
-
-    poReader->poFileView->SetClientData( poReader );
-    poReader->poFileView->SetRefreshCallback( ECWAsyncReader::RefreshCB );
-
-/* -------------------------------------------------------------------- */
-/*      Issue a corresponding SetView command.                          */
-/* -------------------------------------------------------------------- */
-    std::vector<UINT32> anBandIndices;
-    NCSError     eNCSErr;
-    CNCSError    oErr;
-    
-    for( i = 0; i < nBandCount; i++ )
-        anBandIndices.push_back( panBandMap[i] - 1 );
-
-    oErr = poReader->poFileView->SetView( nBandCount, &(anBandIndices[0]),
-                                          nXOff, nYOff, 
-                                          nXOff + nXSize - 1, 
-                                          nYOff + nYSize - 1,
-                                          nBufXSize, nBufYSize );
-    eNCSErr = oErr.GetErrorNumber();
-    
-    if( eNCSErr != NCS_SUCCESS )
-    {
-        delete poReader;
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "%s", NCSGetErrorText(eNCSErr) );
-        
-        return NULL;
-    }
-
-    return poReader;
-}
-
-/************************************************************************/
-/*                           EndAsyncReader()                           */
-/************************************************************************/
-void ECWDataset::EndAsyncReader(GDALAsyncReader *poReader)
-
-{
-    delete poReader;
-}
-
-/************************************************************************/
-/*                           ECWAsyncReader()                           */
-/************************************************************************/
-
-ECWAsyncReader::ECWAsyncReader()
-
-{
-    hMutex = CPLCreateMutex();
-    CPLReleaseMutex( hMutex );
-
-    poFileView = NULL;
-    bUpdateReady = FALSE;
-    bComplete = FALSE;
-    panBandMap = NULL;
-}
-
-/************************************************************************/
-/*                          ~ECWAsyncReader()                           */
-/************************************************************************/
-
-ECWAsyncReader::~ECWAsyncReader()
-
-{
-    {
-        CPLMutexHolderD( &hMutex );
-
-        // cancel? 
-
-        delete poFileView;
-        // we should also consider cleaning up the io stream if needed.
-    }
-
-    CPLFree(panBandMap);
-    panBandMap = NULL;
-
-    CPLDestroyMutex( hMutex );
-    hMutex = NULL;
-}
-
-/************************************************************************/
-/*                             RefreshCB()                              */
-/*                                                                      */
-/*      This static method is called by the ECW SDK to notify us        */
-/*      that there is new data ready to refresh from.  We just mark     */
-/*      the async reader as ready for an update.  We fetch the data     */
-/*      and push into into the buffer the application uses.  We lock    */
-/*      this async reader's mutex for this whole operation to avoid     */
-/*      a conflict with the main application.                           */
-/************************************************************************/
-
-NCSEcwReadStatus ECWAsyncReader::RefreshCB( NCSFileView *pFileView )
-
-{
-    NCSFileViewSetInfo *psVSI = NULL;
-
-    NCScbmGetViewInfo( pFileView, &psVSI );
-    if( psVSI != NULL )
-    {
-        CPLDebug( "ECW", "RefreshCB(): BlockCounts=%d/%d/%d/%d", 
-                  psVSI->nBlocksAvailableAtSetView,
-                  psVSI->nBlocksAvailable,
-                  psVSI->nMissedBlocksDuringRead,
-                  psVSI->nBlocksInView );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Identify the reader we are responding on behalf of.             */
-/* -------------------------------------------------------------------- */
-    CNCSJP2FileView *poFileView = (CNCSJP2FileView *) pFileView;
-    ECWAsyncReader *poReader = (ECWAsyncReader *)poFileView->GetClientData();
-    
-/* -------------------------------------------------------------------- */
-/*      Acquire the async reader mutex.  Currently we make no           */
-/*      arrangements for failure to acquire it.                         */
-/* -------------------------------------------------------------------- */
-    {
-        CPLMutexHolderD( &(poReader->hMutex) );
-
-/* -------------------------------------------------------------------- */
-/*      Mark the buffer as updated unless we are already complete.      */
-/*      It seems the Update callback keeps getting called even when     */
-/*      no new data has arrived after completion so we don't want to    */
-/*      trigger new work elsewhere in that case.                        */
-/*                                                                      */
-/*      Also record whether we are now complete.                        */
-/* -------------------------------------------------------------------- */
-        if( !poReader->bComplete )
-            poReader->bUpdateReady = TRUE;
-
-        if( psVSI->nBlocksAvailable == psVSI->nBlocksInView )
-            poReader->bComplete = TRUE;
-    }
-
-    /* Call CPLCleanupTLS explicitly since this thread isn't managed */
-    /* by CPL. This will free the resources taken by the above CPLDebug */
-    if( poReader->bComplete )
-        CPLCleanupTLS();
-
-    return NCSECW_READ_OK;
-}
-
-/************************************************************************/
-/*                            ReadToBuffer()                            */
-/************************************************************************/
-NCSEcwReadStatus ECWAsyncReader::ReadToBuffer()
-{
-/* -------------------------------------------------------------------- */
-/*      Setup working scanline, and the pointers into it.               */
-/*                                                                      */
-/*      Should we try and optimize some cases that we could read        */
-/*      directly into the application buffer?  Perhaps in the           */
-/*      future.                                                         */
-/* -------------------------------------------------------------------- */
-    ECWDataset *poECWDS = (ECWDataset *) poDS;
-    int i;
-    int nDataTypeSize = (GDALGetDataTypeSize(poECWDS->eRasterDataType) / 8);
-    GByte *pabyBILScanline = (GByte *) 
-        CPLMalloc(nBufXSize * nDataTypeSize * nBandCount);
-    GByte **papabyBIL = (GByte**)CPLMalloc(nBandCount*sizeof(void*));
-
-    for( i = 0; i < nBandCount; i++ )
-        papabyBIL[i] = pabyBILScanline 
-            + i * nBufXSize * nDataTypeSize;
-
-/* -------------------------------------------------------------------- */
-/*      Read back the imagery into the buffer.                          */
-/* -------------------------------------------------------------------- */ 
-    for( int iScanline = 0; iScanline < nBufYSize; iScanline++ )
-    {
-        NCSEcwReadStatus  eRStatus;
-
-        eRStatus = 
-            poFileView->ReadLineBIL( poECWDS->eNCSRequestDataType, 
-                                               (UINT16) nBandCount,
-                                               (void **) papabyBIL );
-        if( eRStatus != NCSECW_READ_OK )
-        {
-            CPLFree( papabyBIL );
-            CPLFree( pabyBILScanline );
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "NCScbmReadViewLineBIL failed." );
-            return eRStatus;
-        }
-
-        for( i = 0; i < nBandCount; i++ )
-        {
-            GDALCopyWords( 
-                pabyBILScanline + i * nDataTypeSize * nBufXSize,
-                poECWDS->eRasterDataType, nDataTypeSize, 
-                ((GByte *) pBuf) 
-                + nLineSpace * iScanline 
-                + nBandSpace * i, 
-                eBufType, 
-                nPixelSpace, 
-                nBufXSize );
-        }
-    }
-
-    CPLFree( pabyBILScanline );
-    CPLFree( papabyBIL );
-
-    return NCSECW_READ_OK;
-}
-
-/************************************************************************/
-/*                        GetNextUpdatedRegion()                        */
-/************************************************************************/
-
-GDALAsyncStatusType 
-ECWAsyncReader::GetNextUpdatedRegion( double dfTimeout,
-                                      int* pnXBufOff, int* pnYBufOff,
-                                      int* pnXBufSize, int* pnYBufSize )
-
-{
-    CPLDebug( "ECW", "GetNextUpdatedRegion()" );
-
-/* -------------------------------------------------------------------- */
-/*      We always mark the whole raster as updated since the ECW SDK    */
-/*      does not have a concept of partial update notifications.        */
-/* -------------------------------------------------------------------- */
-    *pnXBufOff = 0;
-    *pnYBufOff = 0;
-    *pnXBufSize = nBufXSize;
-    *pnYBufSize = nBufYSize;
-
-    if( bComplete && !bUpdateReady )
-    {
-        CPLDebug( "ECW", "return GARIO_COMPLETE" );
-        return GARIO_COMPLETE;
-    }
-        
-/* -------------------------------------------------------------------- */
-/*      Wait till our timeout, or until we are notified there is        */
-/*      data ready.  We are trusting the CPLSleep() to be pretty        */
-/*      accurate instead of keeping track of time elapsed ourselves     */
-/*      - this is not necessarily a good approach.                      */
-/* -------------------------------------------------------------------- */
-    if( dfTimeout < 0.0 )
-        dfTimeout = 100000.0;
-    
-    while( !bUpdateReady && dfTimeout > 0.0 )
-    {
-        CPLSleep( MIN(0.1, dfTimeout) );
-        dfTimeout -= 0.1;
-        CPLDebug( "ECW", "wait..." );
-    }
-
-    if( !bUpdateReady )
-    {
-        CPLDebug( "ECW", "return GARIO_PENDING" );
-        return GARIO_PENDING;
-    }
-
-    bUpdateReady = FALSE;
-
-/* -------------------------------------------------------------------- */
-/*      Acquire Mutex                                                   */
-/* -------------------------------------------------------------------- */
-    if( !CPLAcquireMutex( hMutex, dfTimeout ) )
-    {
-        CPLDebug( "ECW", "return GARIO_PENDING" );
-        return GARIO_PENDING;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Actually decode the imagery into our buffer.                    */
-/* -------------------------------------------------------------------- */
-    NCSEcwReadStatus  eRStatus = ReadToBuffer();
-
-    if( eRStatus != NCSECW_READ_OK )
-    {
-        CPLReleaseMutex( hMutex );
-        return GARIO_ERROR;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Return indication of complete or just buffer updateded.         */
-/* -------------------------------------------------------------------- */
-
-    if( bComplete && !bUpdateReady )
-    {
-        CPLReleaseMutex( hMutex );
-        CPLDebug( "ECW", "return GARIO_COMPLETE" );
-        return GARIO_COMPLETE;
-    }
-    else
-    {
-        CPLReleaseMutex( hMutex );
-        CPLDebug( "ECW", "return GARIO_UPDATE" );
-        return GARIO_UPDATE;
-    }
-}
-
-#endif /* def FRMT_ecw */
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  ECWAsyncReader implementation
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// ncsjpcbuffer.h needs the min and max macros.
+#undef NOMINMAX
+
+#include "gdal_ecw.h"
+
+CPL_CVSID("$Id: ecwasyncreader.cpp 36008 2016-10-28 22:07:44Z goatbar $");
+
+#if defined(FRMT_ecw) && (ECWSDK_VERSION >= 40)
+
+/************************************************************************/
+/*                          BeginAsyncReader()                          */
+/************************************************************************/
+
+GDALAsyncReader*
+ECWDataset::BeginAsyncReader( int nXOff, int nYOff, int nXSize, int nYSize,
+                              void *pBuf, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
+                              int nBandCount, int* panBandMap,
+                              int nPixelSpace, int nLineSpace, int nBandSpace,
+                              char **papszOptions)
+
+{
+    int   i;
+
+/* -------------------------------------------------------------------- */
+/*      Provide default packing if needed.                              */
+/* -------------------------------------------------------------------- */
+    if( nPixelSpace == 0 )
+        nPixelSpace = GDALGetDataTypeSize(eBufType) / 8;
+    if( nLineSpace == 0 )
+        nLineSpace = nPixelSpace * nBufXSize;
+    if( nBandSpace == 0 )
+        nBandSpace = nLineSpace * nBufYSize;
+
+/* -------------------------------------------------------------------- */
+/*      Do a bit of validation.                                         */
+/* -------------------------------------------------------------------- */
+    if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
+    {
+        CPLDebug( "GDAL",
+                  "BeginAsyncReader() skipped for odd window or buffer size.\n"
+                  "  Window = (%d,%d)x%dx%d\n"
+                  "  Buffer = %dx%d\n",
+                  nXOff, nYOff, nXSize, nYSize,
+                  nBufXSize, nBufYSize );
+        return NULL;
+    }
+
+    if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
+        || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
+    {
+        ReportError( CE_Failure, CPLE_IllegalArg,
+                  "Access window out of range in RasterIO().  Requested\n"
+                  "(%d,%d) of size %dx%d on raster of %dx%d.",
+                  nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
+        return NULL;
+    }
+
+    if( nBandCount <= 0 || nBandCount > nBands )
+    {
+        ReportError( CE_Failure, CPLE_IllegalArg, "Invalid band count" );
+        return NULL;
+    }
+
+    if( panBandMap != NULL )
+    {
+        for( i = 0; i < nBandCount; i++ )
+        {
+            if( panBandMap[i] < 1 || panBandMap[i] > nBands )
+            {
+                ReportError( CE_Failure, CPLE_IllegalArg,
+                      "panBandMap[%d] = %d, this band does not exist on dataset.",
+                      i, panBandMap[i] );
+                return NULL;
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create the corresponding async reader.                          */
+/* -------------------------------------------------------------------- */
+    ECWAsyncReader *poReader = new ECWAsyncReader();
+
+    poReader->poDS = this;
+
+    poReader->nXOff = nXOff;
+    poReader->nYOff = nYOff;
+    poReader->nXSize = nXSize;
+    poReader->nYSize = nYSize;
+
+    poReader->pBuf = pBuf;
+    poReader->nBufXSize = nBufXSize;
+    poReader->nBufYSize = nBufYSize;
+    poReader->eBufType = eBufType;
+    poReader->nBandCount = nBandCount;
+    poReader->panBandMap = (int *) CPLCalloc(sizeof(int),nBandCount);
+    if( panBandMap != NULL )
+    {
+        memcpy( poReader->panBandMap, panBandMap, sizeof(int) * nBandCount );
+    }
+    else
+    {
+        for( i = 0; i < nBandCount; i++ )
+            poReader->panBandMap[i] = i + 1;
+    }
+
+    poReader->nPixelSpace = nPixelSpace;
+    poReader->nLineSpace = nLineSpace;
+    poReader->nBandSpace = nBandSpace;
+
+/* -------------------------------------------------------------------- */
+/*      Create a new view for this request.                             */
+/* -------------------------------------------------------------------- */
+    poReader->poFileView = OpenFileView( GetDescription(), true,
+                                         poReader->bUsingCustomStream );
+
+    if( poReader->poFileView == NULL )
+    {
+        delete poReader;
+        return NULL;
+    }
+
+    poReader->poFileView->SetClientData( poReader );
+    poReader->poFileView->SetRefreshCallback( ECWAsyncReader::RefreshCB );
+
+/* -------------------------------------------------------------------- */
+/*      Issue a corresponding SetView command.                          */
+/* -------------------------------------------------------------------- */
+    std::vector<UINT32> anBandIndices;
+    NCSError     eNCSErr;
+    CNCSError    oErr;
+
+    for( i = 0; i < nBandCount; i++ )
+        anBandIndices.push_back( panBandMap[i] - 1 );
+
+    oErr = poReader->poFileView->SetView( nBandCount, &(anBandIndices[0]),
+                                          nXOff, nYOff,
+                                          nXOff + nXSize - 1,
+                                          nYOff + nYSize - 1,
+                                          nBufXSize, nBufYSize );
+    eNCSErr = oErr.GetErrorNumber();
+
+    if( eNCSErr != NCS_SUCCESS )
+    {
+        delete poReader;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s", NCSGetErrorText(eNCSErr) );
+
+        return NULL;
+    }
+
+    return poReader;
+}
+
+/************************************************************************/
+/*                           EndAsyncReader()                           */
+/************************************************************************/
+void ECWDataset::EndAsyncReader(GDALAsyncReader *poReader)
+
+{
+    delete poReader;
+}
+
+/************************************************************************/
+/*                           ECWAsyncReader()                           */
+/************************************************************************/
+
+ECWAsyncReader::ECWAsyncReader()
+
+{
+    hMutex = CPLCreateMutex();
+    CPLReleaseMutex( hMutex );
+
+    poFileView = NULL;
+    bUpdateReady = FALSE;
+    bComplete = FALSE;
+    panBandMap = NULL;
+}
+
+/************************************************************************/
+/*                          ~ECWAsyncReader()                           */
+/************************************************************************/
+
+ECWAsyncReader::~ECWAsyncReader()
+
+{
+    {
+        CPLMutexHolderD( &hMutex );
+
+        // cancel?
+
+        delete poFileView;
+        // we should also consider cleaning up the io stream if needed.
+    }
+
+    CPLFree(panBandMap);
+    panBandMap = NULL;
+
+    CPLDestroyMutex( hMutex );
+    hMutex = NULL;
+}
+
+/************************************************************************/
+/*                             RefreshCB()                              */
+/*                                                                      */
+/*      This static method is called by the ECW SDK to notify us        */
+/*      that there is new data ready to refresh from.  We just mark     */
+/*      the async reader as ready for an update.  We fetch the data     */
+/*      and push into into the buffer the application uses.  We lock    */
+/*      this async reader's mutex for this whole operation to avoid     */
+/*      a conflict with the main application.                           */
+/************************************************************************/
+
+NCSEcwReadStatus ECWAsyncReader::RefreshCB( NCSFileView *pFileView )
+
+{
+    NCSFileViewSetInfo *psVSI = NULL;
+
+    NCScbmGetViewInfo( pFileView, &psVSI );
+    if( psVSI != NULL )
+    {
+        CPLDebug( "ECW", "RefreshCB(): BlockCounts=%d/%d/%d/%d",
+                  psVSI->nBlocksAvailableAtSetView,
+                  psVSI->nBlocksAvailable,
+                  psVSI->nMissedBlocksDuringRead,
+                  psVSI->nBlocksInView );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Identify the reader we are responding on behalf of.             */
+/* -------------------------------------------------------------------- */
+    CNCSJP2FileView *poFileView = (CNCSJP2FileView *) pFileView;
+    ECWAsyncReader *poReader = (ECWAsyncReader *)poFileView->GetClientData();
+
+/* -------------------------------------------------------------------- */
+/*      Acquire the async reader mutex.  Currently we make no           */
+/*      arrangements for failure to acquire it.                         */
+/* -------------------------------------------------------------------- */
+    {
+        CPLMutexHolderD( &(poReader->hMutex) );
+
+/* -------------------------------------------------------------------- */
+/*      Mark the buffer as updated unless we are already complete.      */
+/*      It seems the Update callback keeps getting called even when     */
+/*      no new data has arrived after completion so we don't want to    */
+/*      trigger new work elsewhere in that case.                        */
+/*                                                                      */
+/*      Also record whether we are now complete.                        */
+/* -------------------------------------------------------------------- */
+        if( !poReader->bComplete )
+            poReader->bUpdateReady = TRUE;
+
+        if( psVSI->nBlocksAvailable == psVSI->nBlocksInView )
+            poReader->bComplete = TRUE;
+    }
+
+    /* Call CPLCleanupTLS explicitly since this thread isn't managed */
+    /* by CPL. This will free the resources taken by the above CPLDebug */
+    if( poReader->bComplete )
+        CPLCleanupTLS();
+
+    return NCSECW_READ_OK;
+}
+
+/************************************************************************/
+/*                            ReadToBuffer()                            */
+/************************************************************************/
+NCSEcwReadStatus ECWAsyncReader::ReadToBuffer()
+{
+/* -------------------------------------------------------------------- */
+/*      Setup working scanline, and the pointers into it.               */
+/*                                                                      */
+/*      Should we try and optimize some cases that we could read        */
+/*      directly into the application buffer?  Perhaps in the           */
+/*      future.                                                         */
+/* -------------------------------------------------------------------- */
+    ECWDataset *poECWDS = (ECWDataset *) poDS;
+    int i;
+    int nDataTypeSize = (GDALGetDataTypeSize(poECWDS->eRasterDataType) / 8);
+    GByte *pabyBILScanline = (GByte *)
+        CPLMalloc(nBufXSize * nDataTypeSize * nBandCount);
+    GByte **papabyBIL = (GByte**)CPLMalloc(nBandCount*sizeof(void*));
+
+    for( i = 0; i < nBandCount; i++ )
+        papabyBIL[i] = pabyBILScanline
+            + i * nBufXSize * nDataTypeSize;
+
+/* -------------------------------------------------------------------- */
+/*      Read back the imagery into the buffer.                          */
+/* -------------------------------------------------------------------- */
+    for( int iScanline = 0; iScanline < nBufYSize; iScanline++ )
+    {
+        NCSEcwReadStatus  eRStatus;
+
+        eRStatus =
+            poFileView->ReadLineBIL( poECWDS->eNCSRequestDataType,
+                                               (UINT16) nBandCount,
+                                               (void **) papabyBIL );
+        if( eRStatus != NCSECW_READ_OK )
+        {
+            CPLFree( papabyBIL );
+            CPLFree( pabyBILScanline );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "NCScbmReadViewLineBIL failed." );
+            return eRStatus;
+        }
+
+        for( i = 0; i < nBandCount; i++ )
+        {
+            GDALCopyWords(
+                pabyBILScanline + i * nDataTypeSize * nBufXSize,
+                poECWDS->eRasterDataType, nDataTypeSize,
+                ((GByte *) pBuf)
+                + nLineSpace * iScanline
+                + nBandSpace * i,
+                eBufType,
+                nPixelSpace,
+                nBufXSize );
+        }
+    }
+
+    CPLFree( pabyBILScanline );
+    CPLFree( papabyBIL );
+
+    return NCSECW_READ_OK;
+}
+
+/************************************************************************/
+/*                        GetNextUpdatedRegion()                        */
+/************************************************************************/
+
+GDALAsyncStatusType
+ECWAsyncReader::GetNextUpdatedRegion( double dfTimeout,
+                                      int* pnXBufOff, int* pnYBufOff,
+                                      int* pnXBufSize, int* pnYBufSize )
+
+{
+    CPLDebug( "ECW", "GetNextUpdatedRegion()" );
+
+/* -------------------------------------------------------------------- */
+/*      We always mark the whole raster as updated since the ECW SDK    */
+/*      does not have a concept of partial update notifications.        */
+/* -------------------------------------------------------------------- */
+    *pnXBufOff = 0;
+    *pnYBufOff = 0;
+    *pnXBufSize = nBufXSize;
+    *pnYBufSize = nBufYSize;
+
+    if( bComplete && !bUpdateReady )
+    {
+        CPLDebug( "ECW", "return GARIO_COMPLETE" );
+        return GARIO_COMPLETE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Wait till our timeout, or until we are notified there is        */
+/*      data ready.  We are trusting the CPLSleep() to be pretty        */
+/*      accurate instead of keeping track of time elapsed ourselves     */
+/*      - this is not necessarily a good approach.                      */
+/* -------------------------------------------------------------------- */
+    if( dfTimeout < 0.0 )
+        dfTimeout = 100000.0;
+
+    while( !bUpdateReady && dfTimeout > 0.0 )
+    {
+        CPLSleep( MIN(0.1, dfTimeout) );
+        dfTimeout -= 0.1;
+        CPLDebug( "ECW", "wait..." );
+    }
+
+    if( !bUpdateReady )
+    {
+        CPLDebug( "ECW", "return GARIO_PENDING" );
+        return GARIO_PENDING;
+    }
+
+    bUpdateReady = FALSE;
+
+/* -------------------------------------------------------------------- */
+/*      Acquire Mutex                                                   */
+/* -------------------------------------------------------------------- */
+    if( !CPLAcquireMutex( hMutex, dfTimeout ) )
+    {
+        CPLDebug( "ECW", "return GARIO_PENDING" );
+        return GARIO_PENDING;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Actually decode the imagery into our buffer.                    */
+/* -------------------------------------------------------------------- */
+    NCSEcwReadStatus  eRStatus = ReadToBuffer();
+
+    if( eRStatus != NCSECW_READ_OK )
+    {
+        CPLReleaseMutex( hMutex );
+        return GARIO_ERROR;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Return indication of complete or just buffer updateded.         */
+/* -------------------------------------------------------------------- */
+
+    if( bComplete && !bUpdateReady )
+    {
+        CPLReleaseMutex( hMutex );
+        CPLDebug( "ECW", "return GARIO_COMPLETE" );
+        return GARIO_COMPLETE;
+    }
+    else
+    {
+        CPLReleaseMutex( hMutex );
+        CPLDebug( "ECW", "return GARIO_UPDATE" );
+        return GARIO_UPDATE;
+    }
+}
+
+#endif /* def FRMT_ecw */
diff --git a/frmts/ecw/ecwcreatecopy.cpp b/frmts/ecw/ecwcreatecopy.cpp
index 7dbda11..0d1a3bc 100644
--- a/frmts/ecw/ecwcreatecopy.cpp
+++ b/frmts/ecw/ecwcreatecopy.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ecwcreatecopy.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GDAL ECW Driver
  * Purpose:  ECW CreateCopy method implementation.
@@ -28,6 +27,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+// ncsjpcbuffer.h needs the min and max macros.
+#undef NOMINMAX
+
 #include "gdal_ecw.h"
 #include "gdaljp2metadata.h"
 #include "ogr_spatialref.h"
@@ -37,7 +39,7 @@
 #include "NCSUtil.h"
 #endif
 
-CPL_CVSID("$Id: ecwcreatecopy.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: ecwcreatecopy.cpp 36740 2016-12-07 15:29:01Z rouault $");
 
 #if defined(FRMT_ecw) && defined(HAVE_COMPRESS)
 
@@ -83,14 +85,14 @@ class GDALECWCompressor : public CNCSFile {
 public:
     GDALECWCompressor();
     virtual ~GDALECWCompressor();
-    virtual CNCSError WriteReadLine(UINT32 nNextLine, void **ppInputArray);
+    virtual CNCSError WriteReadLine(UINT32 nNextLine, void **ppInputArray) override;
 #if ECWSDK_VERSION>=50
-    virtual void WriteStatus(IEEE4 fPercentComplete, const NCS::CString &sStatusText, const CompressionCounters &Counters);
+    virtual void WriteStatus(IEEE4 fPercentComplete, const NCS::CString &sStatusText, const CompressionCounters &Counters) override;
 #else
-    virtual void WriteStatus(UINT32 nCurrentLine);
+    virtual void WriteStatus(UINT32 nCurrentLine) override;
 #endif
 
-    virtual bool WriteCancel();
+    virtual bool WriteCancel() override;
 
     CPLErr  Initialize( const char *pszFilename, char **papszOptions,
                         int nXSize, int nYSize, int nBands, const char * const * papszBandDescriptions, int bRGBColorSpace,
@@ -105,9 +107,11 @@ public:
     CPLErr  WriteJP2Box( GDALJP2Box * );
     void    WriteXMLBoxes();
     CPLErr  ourWriteLineBIL(UINT16 nBands, void **ppOutputLine, UINT32 *pLineSteps = NULL);
-    virtual NCSEcwCellType WriteReadLineGetCellType() {
+#if ECWSDK_VERSION>=50
+    virtual NCSEcwCellType WriteReadLineGetCellType() override {
         return sFileInfo.eCellType;
     }
+#endif
 #ifdef ECW_FW
     CNCSJP2File::CNCSJPXAssocBox  m_oGMLAssoc;
 #endif
@@ -202,7 +206,6 @@ CNCSError GDALECWCompressor::WriteReadLine( UINT32 nNextLine,
 {
     int    iBand, *panBandMap;
     CPLErr eErr;
-    GByte *pabyLineBuf;
     int nWordSize = GDALGetDataTypeSize( eWorkDT ) / 8;
 
 #ifdef DEBUG_VERBOSE
@@ -213,8 +216,9 @@ CNCSError GDALECWCompressor::WriteReadLine( UINT32 nNextLine,
     for( iBand = 0; iBand < sFileInfo.nBands; iBand++ )
         panBandMap[iBand] = iBand+1;
 
-    pabyLineBuf = (GByte *) CPLMalloc( sFileInfo.nSizeX * sFileInfo.nBands
-                                       * nWordSize );
+    GByte *pabyLineBuf =
+        (GByte *) CPLMalloc( sFileInfo.nSizeX * sFileInfo.nBands
+                             * nWordSize );
 
     eErr = m_poSrcDS->RasterIO( GF_Read, 0, nNextLine, sFileInfo.nSizeX, 1,
                                 pabyLineBuf, sFileInfo.nSizeX, 1,
@@ -549,7 +553,6 @@ CPLErr GDALECWCompressor::Initialize(
     GDALDataset* poSrcDS )
 
 {
-     const char *pszOption;
 /* -------------------------------------------------------------------- */
 /*      For 4.x and beyond you need a license key to compress data.     */
 /*      Check for it as a configuration option or a creation option.    */
@@ -626,6 +629,7 @@ CPLErr GDALECWCompressor::Initialize(
 /*      Create and initialize compressor.                               */
 /* -------------------------------------------------------------------- */
     NCSFileViewFileInfoEx    *psClient = &(sFileInfo);
+    const char *pszOption = NULL;
 #if ECWSDK_VERSION >= 50
     if( bIsJPEG2000 == FALSE )
     {
@@ -719,11 +723,13 @@ CPLErr GDALECWCompressor::Initialize(
             bSigned = TRUE;
             break;
 
+#if ECWSDK_VERSION >= 40
         case GDT_Float64:
             psClient->eCellType = NCSCT_IEEE8;
             nBits = 64;
             bSigned = TRUE;
             break;
+#endif
 
         default:
             // We treat complex types as float.
@@ -953,16 +959,19 @@ CPLErr GDALECWCompressor::Initialize(
         oJP2MD.SetRPCMD( papszRPCMD );
 
         if (bIsJPEG2000) {
-            if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
+            if( CPLFetchBool(papszOptions, "WRITE_METADATA", false) )
             {
-                if( !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
+                if( !CPLFetchBool(papszOptions, "MAIN_MD_DOMAIN_ONLY", false) )
                 {
                     WriteXMLBoxes();
                 }
-                WriteJP2Box(GDALJP2Metadata::CreateGDALMultiDomainMetadataXMLBox(
-                        m_poSrcDS, CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE)));
+                WriteJP2Box(
+                    GDALJP2Metadata::CreateGDALMultiDomainMetadataXMLBox(
+                        m_poSrcDS,
+                        CPLFetchBool(papszOptions, "MAIN_MD_DOMAIN_ONLY",
+                                     false)));
             }
-            if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
+            if( CPLFetchBool( papszOptions, "GMLJP2", true ) )
             {
                 const char* pszGMLJP2V2Def = CSLFetchNameValue( papszOptions, "GMLJP2V2_DEF" );
                 if( pszGMLJP2V2Def != NULL )
@@ -970,10 +979,10 @@ CPLErr GDALECWCompressor::Initialize(
                 else
                     WriteJP2Box( oJP2MD.CreateGMLJP2(nXSize,nYSize) );
             }
-            if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) )
+            if( CPLFetchBool( papszOptions, "GeoJP2", true ) )
                 WriteJP2Box( oJP2MD.CreateJP2GeoTIFF() );
-            if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) &&
-                !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
+            if( CPLFetchBool(papszOptions, "WRITE_METADATA", false) &&
+                !CPLFetchBool(papszOptions, "MAIN_MD_DOMAIN_ONLY", false) )
             {
                 WriteJP2Box(GDALJP2Metadata::CreateXMPBox(m_poSrcDS));
             }
@@ -1000,7 +1009,7 @@ CPLErr GDALECWCompressor::Initialize(
         }
 
         m_OStream.Access( fpVSIL, TRUE, (BOOLEAN) bSeekable, pszFilename,
-			  0, -1 );
+                          0, -1 );
     }
     else
     {
@@ -1069,7 +1078,7 @@ CPLErr GDALECWCompressor::Initialize(
             psClient->pFileMetaData->sCompany = NCSStrDupT(NCS::CString(pszECWCompany).c_str());
         }
         CPLString osCompressionSoftware = GetCompressionSoftwareName();
-        if ( osCompressionSoftware.size() > 0 ) {
+        if ( !osCompressionSoftware.empty() ) {
             psClient->pFileMetaData->sCompressionSoftware = NCSStrDupT(NCS::CString(osCompressionSoftware.c_str()).c_str());
         }
         if (m_poSrcDS && m_poSrcDS->GetMetadataItem("FILE_METADATA_COPYRIGHT")!=NULL){
@@ -1317,7 +1326,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Re-open dataset, and copy any auxiliary pam information.         */
 /* -------------------------------------------------------------------- */
     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
-    GDALPamDataset *poDS;
+    GDALPamDataset *poDS = NULL;
 
     if (bIsJPEG2000)
         poDS = (GDALPamDataset*) ECWDatasetOpenJPEG2000(&oOpenInfo);
@@ -1334,7 +1343,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             }
             double dHistMin, dHistMax;
             int nBuckets;
-            GUIntBig *pHistogram;
+            GUIntBig *pHistogram = NULL;
             if (poSrcDS->GetRasterBand(i)->GetDefaultHistogram(&dHistMin, &dHistMax,&nBuckets,&pHistogram, FALSE, NULL, NULL) == CE_None){
                 poDS->GetRasterBand(i)->SetDefaultHistogram(dHistMin, dHistMax, nBuckets, pHistogram);
                 VSIFree(pHistogram);
@@ -1345,7 +1354,7 @@ ECWCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         ((ECWDataset *)poDS)->SetPreventCopyingSomeMetadata(TRUE);
         int nFlags = GCIF_PAM_DEFAULT;
         if( bIsJPEG2000 &&
-            !CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
+            !CPLFetchBool(papszOptions, "WRITE_METADATA", false) )
             nFlags &= ~GCIF_METADATA;
         poDS->CloneInfo( poSrcDS, nFlags );
         ((ECWDataset *)poDS)->SetPreventCopyingSomeMetadata(FALSE);
@@ -1478,7 +1487,9 @@ ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS,
         && eDataType != GDT_Int32
         && eDataType != GDT_UInt32
         && eDataType != GDT_Float32
+#if ECWSDK_VERSION >= 40
         && eDataType != GDT_Float64
+#endif
         && bStrict )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -1524,7 +1535,7 @@ ECWCreateCopyJPEG2000( const char * pszFilename, GDALDataset *poSrcDS,
 
 /************************************************************************/
 /* ==================================================================== */
-/*				ECWWriteDataset				*/
+/*                              ECWWriteDataset                         */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -1606,12 +1617,12 @@ class ECWWriteDataset : public GDALDataset
                                  int );
             ~ECWWriteDataset();
 
-    virtual void   FlushCache( void );
+    virtual void   FlushCache( void ) override;
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char* GetProjectionRef();
-    virtual CPLErr SetGeoTransform( double * );
-    virtual CPLErr SetProjection( const char *pszWKT );
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char* GetProjectionRef() override;
+    virtual CPLErr SetGeoTransform( double * ) override;
+    virtual CPLErr SetProjection( const char *pszWKT ) override;
 
 #ifdef OPTIMIZED_FOR_GDALWARP
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
@@ -1621,7 +1632,7 @@ class ECWWriteDataset : public GDALDataset
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 #endif
 };
 
@@ -1649,17 +1660,17 @@ class ECWWriteRasterBand : public GDALRasterBand
                    ECWWriteRasterBand( ECWWriteDataset *, int );
                   ~ECWWriteRasterBand();
 
-    virtual CPLErr SetColorInterpretation( GDALColorInterp eInterpIn )
+    virtual CPLErr SetColorInterpretation( GDALColorInterp eInterpIn ) override
         { eInterp = eInterpIn;
           if( strlen(GetDescription()) == 0 )
               SetDescription(ECWGetColorInterpretationName(eInterp, nBand-1));
           return CE_None;
         }
-    virtual GDALColorInterp GetColorInterpretation()
+    virtual GDALColorInterp GetColorInterpretation() override
         { return eInterp; }
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 
 #ifdef OPTIMIZED_FOR_GDALWARP
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
@@ -1667,7 +1678,7 @@ class ECWWriteRasterBand : public GDALRasterBand
                               void * pData, int nBufXSize, int nBufYSize,
                               GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 #endif
 };
 
@@ -1797,7 +1808,6 @@ CPLErr ECWWriteDataset::SetProjection( const char *pszWKT )
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                             Crystalize()                             */
 /************************************************************************/
@@ -1864,14 +1874,11 @@ CPLErr ECWWriteDataset::FlushLine()
     if( nLoadedLine != -1 )
     {
 
-        void **papOutputLine;
-
-        papOutputLine = (void **) CPLMalloc(sizeof(void*) * nBands);
+        void **papOutputLine = (void **) CPLMalloc(sizeof(void*) * nBands);
         for( int i = 0; i < nBands; i++ )
             papOutputLine[i] =
                 (void *) (pabyBILBuffer + i * nWordSize * nRasterXSize);
 
-
         eErr =  oCompressor.ourWriteLineBIL( (UINT16) nBands, papOutputLine );
         CPLFree( papOutputLine );
         if (eErr!=CE_None){
diff --git a/frmts/ecw/ecwdataset.cpp b/frmts/ecw/ecwdataset.cpp
index 1936de7..ff3ab97 100644
--- a/frmts/ecw/ecwdataset.cpp
+++ b/frmts/ecw/ecwdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ecwdataset.cpp 34287 2016-05-24 15:49:52Z mloskot $
  *
  * Project:  GDAL
  * Purpose:  ECW (ERDAS Wavelet Compression Format) Driver
@@ -28,6 +27,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+// ncsjpcbuffer.h needs the min and max macros.
+#undef NOMINMAX
+
 #include "cpl_minixml.h"
 #include "gdal_ecw.h"
 #include "gdal_frmts.h"
@@ -37,7 +39,7 @@
 
 #include "../mem/memdataset.h"
 
-CPL_CVSID("$Id: ecwdataset.cpp 34287 2016-05-24 15:49:52Z mloskot $");
+CPL_CVSID("$Id: ecwdataset.cpp 36740 2016-12-07 15:29:01Z rouault $");
 
 #undef NOISY_DEBUG
 
@@ -184,8 +186,10 @@ ECWRasterBand::ECWRasterBand( ECWDataset *poDSIn, int nBandIn, int iOverviewIn,
         poDSIn->psFileInfo->pBands[2].nBits == 8 &&
         poDSIn->psFileInfo->pBands[3].nBits == 1 &&
         eBandInterp == GCI_AlphaBand &&
-        CSLFetchBoolean(papszOpenOptions, "1BIT_ALPHA_PROMOTION",
-            CPLTestBool(CPLGetConfigOption("GDAL_ECW_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES")));
+        CPLFetchBool(papszOpenOptions, "1BIT_ALPHA_PROMOTION",
+            CPLTestBool(
+                CPLGetConfigOption("GDAL_ECW_PROMOTE_1BIT_ALPHA_AS_8BIT",
+                                   "YES")));
     if( bPromoteTo8Bit )
         CPLDebug("ECW", "Fourth (alpha) band is promoted from 1 bit to 8 bit");
 
@@ -206,7 +210,7 @@ ECWRasterBand::~ECWRasterBand()
 {
     FlushCache();
 
-    while( apoOverviews.size() > 0 )
+    while( !apoOverviews.empty() )
     {
         delete apoOverviews.back();
         apoOverviews.pop_back();
@@ -345,12 +349,16 @@ CPLErr ECWRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
                 //Something went wrong during histogram computation.
                 return pamError;
             }
-        }else{
-            //No histogram, no forced computation.
+        }
+        else
+        {
+            // No histogram, no forced computation.
             return CE_Warning;
         }
-    }else {
-        //Statistics were already there and were used.
+    }
+    else
+    {
+        // Statistics were already there and were used.
         return CE_None;
     }
 }
@@ -360,7 +368,8 @@ CPLErr ECWRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
 /************************************************************************/
 
 CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
-                                           int nBuckets, GUIntBig *panHistogram )
+                                           int nBuckets,
+                                           GUIntBig *panHistogram )
 {
     //Only version 3 supports saving statistics.
     if (poGDS->psFileInfo->nFormatVersion < 3 || eBandInterp == GCI_AlphaBand){
@@ -370,13 +379,17 @@ CPLErr ECWRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
     //determine if there are statistics in PAM file.
     double dummy;
     int dummy_i;
-    GUIntBig *dummy_histogram;
-    bool hasPAMDefaultHistogram = GDALPamRasterBand::GetDefaultHistogram(&dummy, &dummy, &dummy_i, &dummy_histogram, FALSE, NULL, NULL) == CE_None;
-    if (hasPAMDefaultHistogram){
+    GUIntBig *dummy_histogram = NULL;
+    bool hasPAMDefaultHistogram =
+        GDALPamRasterBand::GetDefaultHistogram(
+            &dummy, &dummy, &dummy_i, &dummy_histogram,
+            FALSE, NULL, NULL) == CE_None;
+    if( hasPAMDefaultHistogram ) {
         VSIFree(dummy_histogram);
     }
 
-    //ECW SDK ignores statistics for opacity bands. So we need to compute number of bands without opacity.
+    // ECW SDK ignores statistics for opacity bands. So we need to compute
+    // number of bands without opacity.
     GetBandIndexAndCountForStatistics(nStatsBandIndex, nStatsBandCount);
     UINT32 bucketCounts[256];
     std::fill_n(bucketCounts, nStatsBandCount, 0);
@@ -706,7 +719,8 @@ CPLErr ECWRasterBand::OldIRasterIO( GDALRWFlag eRWFlag,
 /*      The ECW SDK doesn't supersample, so adjust for this case.       */
 /* -------------------------------------------------------------------- */
 
-    int          nNewXSize = nBufXSize, nNewYSize = nBufYSize;
+    int nNewXSize = nBufXSize;
+    int nNewYSize = nBufYSize;
 
     if ( nXSize < nBufXSize )
         nNewXSize = nXSize;
@@ -925,7 +939,6 @@ CPLErr ECWRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            ECWDataset()                              */
 /************************************************************************/
@@ -1125,7 +1138,6 @@ NCS::CError ECWDataset::StatisticsWrite()
     bStatisticsDirty = FALSE;
 
     return error;
-
 }
 
 /************************************************************************/
@@ -1394,7 +1406,7 @@ CPLErr ECWDataset::SetMetadata( char ** papszMetadata,
                 osNewMetadata.AddString(*papszIter);
             papszIter ++;
         }
-        if (osNewMetadata.size() != 0)
+        if (!osNewMetadata.empty())
             return GDALPamDataset::SetMetadata(osNewMetadata.List(), pszDomain);
         else
             return CE_None;
@@ -2567,9 +2579,7 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    ECWDataset  *poDS;
-
-    poDS = new ECWDataset(bIsJPEG2000);
+    ECWDataset  *poDS = new ECWDataset(bIsJPEG2000);
     poDS->poFileView = poFileView;
     poDS->eAccess = poOpenInfo->eAccess;
 
@@ -2834,7 +2844,8 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
     if( bIsJPEG2000 && poOpenInfo->nOpenFlags & GDAL_OF_VECTOR )
     {
         poDS->LoadVectorLayers(
-            CSLFetchBoolean(poOpenInfo->papszOpenOptions, "OPEN_REMOTE_GML", FALSE));
+            CPLFetchBool(poOpenInfo->papszOpenOptions, "OPEN_REMOTE_GML",
+                         false));
 
         // If file opened in vector-only mode and there's no vector,
         // return
@@ -2846,7 +2857,7 @@ GDALDataset *ECWDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJPEG2000 )
         }
     }
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -2903,9 +2914,9 @@ char **ECWDataset::GetMetadata( const char *pszDomain )
 /************************************************************************/
 /*                   ReadFileMetaDataFromFile()                         */
 /*                                                                      */
-/* Gets relevant information from NCSFileMetadata and populates			*/
-/* GDAL metadata														*/
-/*																		*/
+/* Gets relevant information from NCSFileMetadata and populates         */
+/* GDAL metadata.                                                       */
+/*                                                                      */
 /************************************************************************/
 #if ECWSDK_VERSION >= 50
 void ECWDataset::ReadFileMetaDataFromFile()
@@ -2913,7 +2924,7 @@ void ECWDataset::ReadFileMetaDataFromFile()
     if (psFileInfo->pFileMetaData == NULL) return;
 
     if (psFileInfo->pFileMetaData->sClassification != NULL )
-        GDALDataset::SetMetadataItem("FILE_METADATA_CLASSIFICATION", NCS::CString(psFileInfo->pFileMetaData->sClassification).a_str());
+        GDALDataset::SetMetadataItem("FILE_METADATA_CLASSIFICATION", NCS::CString(psFileInfo->pFileMetaData->sClassification));
     if (psFileInfo->pFileMetaData->sAcquisitionDate != NULL )
         GDALDataset::SetMetadataItem("FILE_METADATA_ACQUISITION_DATE", NCS::CString(psFileInfo->pFileMetaData->sAcquisitionDate));
     if (psFileInfo->pFileMetaData->sAcquisitionSensorName != NULL )
@@ -3138,7 +3149,6 @@ int ECWTranslateFromWKT( const char *pszWKT,
 
         NCSFree( pszEPSGProj );
         NCSFree( pszEPSGDatum );
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -3199,7 +3209,7 @@ GDALColorInterp ECWGetColorInterpretationByName(const char *pszName)
 
 const char* ECWGetColorInterpretationName(GDALColorInterp eColorInterpretation, int nBandNumber)
 {
-    const char *pszResult;
+    const char *pszResult = NULL;
     switch (eColorInterpretation){
     case GCI_AlphaBand:
         pszResult = NCS_BANDDESC_AllOpacity;
@@ -3304,7 +3314,8 @@ void ECWInitialize()
     if( !CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB","YES") ) )
         NCSecwSetConfig(NCSCFG_JP2_MANAGE_ICC, FALSE);
 #if ECWSDK_VERSION>= 50
-	NCSecwSetConfig(NCSCFG_ECWP_CLIENT_HTTP_USER_AGENT, "ECW GDAL Driver/" NCS_ECWJP2_FULL_VERSION_STRING_DOT_DEL);
+    NCSecwSetConfig(NCSCFG_ECWP_CLIENT_HTTP_USER_AGENT,
+                    "ECW GDAL Driver/" NCS_ECWJP2_FULL_VERSION_STRING_DOT_DEL);
 #endif
 /* -------------------------------------------------------------------- */
 /*      Initialize cache memory limit.  Default is apparently 1/4 RAM.  */
@@ -3318,10 +3329,10 @@ void ECWInitialize()
         NCSecwSetConfig(NCSCFG_CACHE_MAXMEM, (UINT32) atoi(pszEcwCacheSize) );
 
     /* -------------------------------------------------------------------- */
-    /*      Version 3.x and 4.x of the ECWJP2 SDK did not resolve datum and         */
-    /*      projection to EPSG code using internal mapping.					*/
-    /*		Version 5.x do so we provide means to achieve old		*/
-    /*		behaviour.														*/
+    /*      Version 3.x and 4.x of the ECWJP2 SDK did not resolve datum and */
+    /*      projection to EPSG code using internal mapping.                 */
+    /*      Version 5.x do so we provide means to achieve old               */
+    /*      behaviour.                                                      */
     /* -------------------------------------------------------------------- */
     #if ECWSDK_VERSION >= 50
     if( CPLTestBool( CPLGetConfigOption("ECW_DO_NOT_RESOLVE_DATUM_PROJECTION","NO") ) == TRUE)
@@ -3331,7 +3342,7 @@ void ECWInitialize()
 /*      Allow configuration of a local cache based on configuration     */
 /*      options.  Setting the location turns things on.                 */
 /* -------------------------------------------------------------------- */
-    const char *pszOpt;
+    const char *pszOpt = NULL;
 
 #if ECWSDK_VERSION >= 40
     pszOpt = CPLGetConfigOption( "ECWP_CACHE_SIZE_MB", NULL );
@@ -3366,7 +3377,6 @@ void ECWInitialize()
         NCSecwSetConfig( NCSCFG_TEXTURE_DITHER,
                          (BOOLEAN) CPLTestBool( pszOpt ) );
 
-
     pszOpt = CPLGetConfigOption( "ECW_FORCE_FILE_REOPEN", NULL );
     if( pszOpt )
         NCSecwSetConfig( NCSCFG_FORCE_FILE_REOPEN,
@@ -3387,7 +3397,6 @@ void ECWInitialize()
         NCSecwSetConfig( NCSCFG_OPTIMIZE_USE_NEAREST_NEIGHBOUR,
                          (BOOLEAN) CPLTestBool( pszOpt ) );
 
-
     pszOpt = CPLGetConfigOption( "ECW_RESILIENT_DECODING", NULL );
     if( pszOpt )
         NCSecwSetConfig( NCSCFG_RESILIENT_DECODING,
@@ -3437,15 +3446,13 @@ void GDALRegister_ECW()
 
 {
 #ifdef FRMT_ecw
-    GDALDriver *poDriver;
-
     if( !GDAL_CHECK_VERSION( "ECW driver" ) )
         return;
 
     if( GDALGetDriverByName( "ECW" ) != NULL )
         return;
 
-    poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
     poDriver->SetDescription( "ECW" );
     poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
@@ -3568,6 +3575,7 @@ void GDALRegister_JP2ECW()
 "<OpenOptionList>"
 "   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description='Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
 "   <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether to load remote vector layers referenced by a link in a GMLJP2 v2 box' default='NO'/>"
+"   <Option name='GEOREF_SOURCES' type='string' description='Comma separated list made with values INTERNAL/GMLJP2/GEOJP2/WORLDFILE/PAM/NONE that describe the priority order for georeferencing' default='PAM,GEOJP2,GMLJP2,WORLDFILE'/>"
 "</OpenOptionList>" );
 
 #ifdef HAVE_COMPRESS
@@ -3575,7 +3583,12 @@ void GDALRegister_JP2ECW()
     poDriver->pfnCreateCopy = ECWCreateCopyJPEG2000;
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
                                "Byte UInt16 Int16 UInt32 Int32 "
-                               "Float32 Float64" );
+                               "Float32 "
+#if ECWSDK_VERSION >= 40
+    // Crashes for sure with 3.3. Didn't try other versions
+                               "Float64"
+#endif
+                              );
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='TARGET' type='float' description='Compression Percentage' />"
diff --git a/frmts/ecw/ecwsdk_headers.h b/frmts/ecw/ecwsdk_headers.h
index c8c4a13..6d5abc1 100644
--- a/frmts/ecw/ecwsdk_headers.h
+++ b/frmts/ecw/ecwsdk_headers.h
@@ -35,7 +35,6 @@
 #pragma GCC system_header
 #endif
 
-
 // The following is needed on 4.x+ to enable rw support.
 #if defined(HAVE_COMPRESS)
 # ifndef ECW_COMPRESS_RW_SDK_VERSION
diff --git a/frmts/ecw/frmt_ecw.html b/frmts/ecw/frmt_ecw.html
index 0f3c5bb..44c456f 100644
--- a/frmts/ecw/frmt_ecw.html
+++ b/frmts/ecw/frmt_ecw.html
@@ -173,6 +173,16 @@ and SetProjection() methods. If the projection is set with SetProjection() and
 the PROJ, DATUM or UNITS with SetMetadataItem(), the later values will override the values
 built from the projection string.<p>
 
+All those can for example be modified with the -a_ullr, -a_srs or -mo switches
+of the <a href="gdal_edit.html">gdal_edit.py</a> utility.<p>
+
+For example:
+<pre>
+gdal_edit.py -mo DATUM=WGS84 -mo PROJ=GEODETIC -a_ullr 7 47 8 46 test.ecw
+
+gdal_edit.py -a_srs EPSG:3068 -a_ullr 20800 22000 24000 19600 test.ecw
+</pre>
+
 <h3>File Metadata Keys: </h3>
 
 <ul>
@@ -190,7 +200,12 @@ built from the projection string.<p>
 <li>COLORSPACE
 <li>COMPRESSION_DATE
 <li>COMPRESSION_RATE_ACTUAL
-<li>COMPRESSION_RATE_TARGET
+<li>COMPRESSION_RATE_TARGET. This is the percentage of the target compressed
+file size divided by the uncompressed file size. This is equal to
+100 / (100 - TARGET) where TARGET is the value of the TARGET
+creation option used at file creation, so a COMPRESSION_RATE_TARGET=1 is
+equivalent to a TARGET=0 (ie no compression), COMPRESSION_RATE_TARGET=5 is
+equivalent to TARGET=80 (ie dividing uncompressed file size by 5), etc...
 <li>VERSION
 </ul>
 
diff --git a/frmts/ecw/frmt_jp2ecw.html b/frmts/ecw/frmt_jp2ecw.html
index 4f08342..9f4d512 100644
--- a/frmts/ecw/frmt_jp2ecw.html
+++ b/frmts/ecw/frmt_jp2ecw.html
@@ -30,6 +30,30 @@ unlimited sized files on Mobile platforms a license must be purchased from Hexag
 <li>v5.x - Active development, 2013 - current</li>
 </ul>
 
+<h2><a name="georeferencing">Georeferencing</a></h2>
+
+<p>
+Georeferencing information can come from different sources : internal (GeoJP2
+or GMLJP2 boxes), worldfile .j2w/.wld sidecar files, or PAM (Persitant Auxiliary metadata)
+.aux.xml sidecar files.
+By default, information is fetched in following order (first listed is the most
+prioritary): PAM, GeoJP2, GMLJP2, WORLDFILE.
+</p>
+<p>Starting with GDAL 2.2, the allowed sources
+and their priority order can be changed with the GDAL_GEOREF_SOURCES
+configuration option (or GEOREF_SOURCES open option) whose value is a
+comma-separated list of the following keywords :
+PAM, GEOJP2, GMLJP2, INTERNAL (shortcut for GEOJP2,GMLJP2), WORLDFILE, NONE.
+First mentioned sources are the most prioritary over the next ones. A non mentioned
+source will be ignored.
+</p>
+<p>
+For example setting it to "WORLDFILE,PAM,INTERNAL" will make a geotransformation
+matrix from a potential worldfile prioritary over PAM or internal JP2 boxes.
+Setting it to "PAM,WORLDFILE,GEOJP2" will use the mentioned sources and
+ignore GMLJP2 boxes.
+</p>
+
 <h2>Option Options</h2>
 
 (GDAL >= 2.0 )
@@ -38,6 +62,8 @@ The following open option is available:
 <ul>
 <li><p><b>1BIT_ALPHA_PROMOTION=YES/NO</b>: Whether a 1-bit alpha channel should be promoted to 8-bit.
 Defaults to YES.</li>
+<li><p><b>GEOREF_SOURCES=string</b>: (GDAL > 2.2) Define which georeferencing sources are
+allowed and their priority order. See <a href="#georeferencing"><i>Georeferencing</i></a> paragraph.</li>
 </ul>
 
 <h2>Creation Options:</h2>
diff --git a/frmts/ecw/gdal_ecw.h b/frmts/ecw/gdal_ecw.h
index 103faf9..d20894b 100644
--- a/frmts/ecw/gdal_ecw.h
+++ b/frmts/ecw/gdal_ecw.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ecwdataset.cpp 21486 2011-01-13 17:38:17Z warmerdam $
+ * $Id: gdal_ecw.h 36740 2016-12-07 15:29:01Z rouault $
  *
  * Project:  GDAL
  * Purpose:  ECW (ERDAS Wavelet Compression Format) Driver Definitions
@@ -91,16 +91,16 @@ public:
 
 #if ECWSDK_VERSION >= 40
     virtual CNCSError Parse(NCS::SDK::CFileBase &JP2File,
-                             NCS::CIOStream &Stream);
+                             NCS::CIOStream &Stream) override;
     virtual CNCSError UnParse(NCS::SDK::CFileBase &JP2File,
-                                NCS::CIOStream &Stream);
+                                NCS::CIOStream &Stream) override;
 #else
     virtual CNCSError Parse(class CNCSJP2File &JP2File,
-                            CNCSJPCIOStream &Stream);
+                            CNCSJPCIOStream &Stream) override;
     virtual CNCSError UnParse(class CNCSJP2File &JP2File,
-                              CNCSJPCIOStream &Stream);
+                              CNCSJPCIOStream &Stream) override;
 #endif
-    virtual void UpdateXLBox(void);
+    virtual void UpdateXLBox() override;
 
     void    SetData( int nDataLength, const unsigned char *pabyDataIn );
 
@@ -158,7 +158,7 @@ class VSIIOStream : public CNCSJPCIOStream
         }
     }
 
-    virtual CNCSError Close() {
+    virtual CNCSError Close() override {
         CNCSError oErr = CNCSJPCIOStream::Close();
         if( fpVSIL != NULL )
         {
@@ -169,7 +169,7 @@ class VSIIOStream : public CNCSJPCIOStream
     }
 
 #if ECWSDK_VERSION >= 40
-    virtual VSIIOStream *Clone() {
+    virtual VSIIOStream *Clone() override {
         CPLDebug( "ECW", "VSIIOStream::Clone()" );
         VSILFILE *fpNewVSIL = VSIFOpenL( m_Filename, "rb" );
         if (fpNewVSIL == NULL)
@@ -229,11 +229,11 @@ class VSIIOStream : public CNCSJPCIOStream
         }
     }
 
-    virtual bool NCS_FASTCALL Seek() {
+    virtual bool NCS_FASTCALL Seek() override {
         return bSeekable;
     }
 
-    virtual bool NCS_FASTCALL Seek(INT64 offset, Origin origin = CURRENT) {
+    virtual bool NCS_FASTCALL Seek(INT64 offset, Origin origin = CURRENT) override {
 #ifdef DEBUG_VERBOSE
         CPLDebug( "ECW", "VSIIOStream::Seek(" CPL_FRMT_GIB ",%d)",
                   static_cast<GIntBig>(offset), (int) origin );
@@ -258,11 +258,11 @@ class VSIIOStream : public CNCSJPCIOStream
         return(success);
     }
 
-    virtual INT64 NCS_FASTCALL Tell() {
+    virtual INT64 NCS_FASTCALL Tell() override {
         return VSIFTellL( fpVSIL ) - startOfJPData;
     }
 
-    virtual INT64 NCS_FASTCALL Size() {
+    virtual INT64 NCS_FASTCALL Size() override {
         if( lengthOfJPData != -1 )
             return lengthOfJPData;
         else
@@ -281,7 +281,7 @@ class VSIIOStream : public CNCSJPCIOStream
 
 #if ECWSDK_VERSION >= 40
     /* New, and needed, in ECW SDK 4 */
-    virtual bool Read(INT64 offset, void* buffer, UINT32 count)
+    virtual bool Read(INT64 offset, void* buffer, UINT32 count) override
     {
 #ifdef DEBUG_VERBOSE
       CPLDebug( "ECW", "VSIIOStream::Read(" CPL_FRMT_GIB ",%u)", static_cast<GIntBig>(offset), count );
@@ -296,7 +296,7 @@ class VSIIOStream : public CNCSJPCIOStream
     }
 #endif
 
-    virtual bool NCS_FASTCALL Read(void* buffer, UINT32 count) {
+    virtual bool NCS_FASTCALL Read(void* buffer, UINT32 count) override {
 #ifdef DEBUG_VERBOSE
         CPLDebug( "ECW", "VSIIOStream::Read(%u)", count );
 #endif
@@ -316,7 +316,7 @@ class VSIIOStream : public CNCSJPCIOStream
         return true;
     }
 
-    virtual bool NCS_FASTCALL Write(void* buffer, UINT32 count) {
+    virtual bool NCS_FASTCALL Write(void* buffer, UINT32 count) override {
         if( count == 0 )
             return true;
 
@@ -356,7 +356,7 @@ class VSIIOStream : public CNCSJPCIOStream
             else
             {
                 GByte prevBuffer[] =
-		  { (GByte)(nCOMLength >> 8), (GByte) (nCOMLength & 0xff) };
+                  { (GByte)(nCOMLength >> 8), (GByte) (nCOMLength & 0xff) };
                 VSIFWriteL(prevBuffer, 2, 1, fpVSIL);
                 nCOMState = 0;
             }
@@ -415,7 +415,7 @@ public:
                                                      int* pnXBufOff,
                                                      int* pnYBufOff,
                                                      int* pnXBufSize,
-                                                     int* pnYBufSize);
+                                                     int* pnYBufSize) override;
 
     friend class ECWDataset;
 };
@@ -423,7 +423,7 @@ public:
 
 /************************************************************************/
 /* ==================================================================== */
-/*				ECWDataset				*/
+/*                              ECWDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -491,7 +491,7 @@ class CPL_DLL ECWDataset : public GDALJP2AbstractDataset
     NCS::CError StatisticsEnsureInitialized();
     NCS::CError StatisticsWrite();
     void CleanupStatistics();
-	void ReadFileMetaDataFromFile();
+    void ReadFileMetaDataFromFile();
 
     int bFileMetaDataDirty;
     void WriteFileMetaData(NCSFileMetaData* pFileMetaDataCopy);
@@ -548,26 +548,26 @@ class CPL_DLL ECWDataset : public GDALJP2AbstractDataset
                               int, int *,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 
-    virtual char      **GetMetadataDomainList();
+    virtual char      **GetMetadataDomainList() override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                     const char * pszDomain = "" );
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) override;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
 
-    virtual CPLErr SetGeoTransform( double * padfGeoTransform );
-    virtual CPLErr SetProjection( const char* pszProjection );
+    virtual CPLErr SetGeoTransform( double * padfGeoTransform ) override;
+    virtual CPLErr SetProjection( const char* pszProjection ) override;
     virtual CPLErr SetMetadataItem( const char * pszName,
                                  const char * pszValue,
-                                 const char * pszDomain = "" );
+                                 const char * pszDomain = "" ) override;
     virtual CPLErr SetMetadata( char ** papszMetadata,
-                             const char * pszDomain = "" );
+                             const char * pszDomain = "" ) override;
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                int nBufXSize, int nBufYSize,
                                GDALDataType eDT,
                                int nBandCount, int *panBandList,
-                               char **papszOptions );
+                               char **papszOptions ) override;
 
     // progressive methods
 #if ECWSDK_VERSION >= 40
@@ -579,9 +579,9 @@ class CPL_DLL ECWDataset : public GDALJP2AbstractDataset
                                                int nBandCount, int* panBandMap,
                                                int nPixelSpace, int nLineSpace,
                                                int nBandSpace,
-                                               char **papszOptions);
+                                               char **papszOptions) override;
 
-    virtual void EndAsyncReader(GDALAsyncReader *);
+    virtual void EndAsyncReader(GDALAsyncReader *) override;
 #endif /* ECWSDK_VERSION > 40 */
 #if ECWSDK_VERSION >=50
     int GetFormatVersion() const {
@@ -628,39 +628,39 @@ class ECWRasterBand : public GDALPamRasterBand
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 
   public:
 
                    ECWRasterBand( ECWDataset *, int, int iOverview, char** papszOpenOptions );
                    ~ECWRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual int    HasArbitraryOverviews() { return apoOverviews.size() == 0; }
-    virtual int    GetOverviewCount() { return (int)apoOverviews.size(); }
-    virtual GDALRasterBand *GetOverview(int);
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual int    HasArbitraryOverviews() override { return apoOverviews.empty(); }
+    virtual int    GetOverviewCount() override { return (int)apoOverviews.size(); }
+    virtual GDALRasterBand *GetOverview(int) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) override;
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                int nBufXSize, int nBufYSize,
-                               GDALDataType eDT, char **papszOptions );
+                               GDALDataType eDT, char **papszOptions ) override;
 #if ECWSDK_VERSION >= 50
     void GetBandIndexAndCountForStatistics(int &bandIndex, int &bandCount);
     virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                     int *pnBuckets, GUIntBig ** ppanHistogram,
                                     int bForce,
-                                    GDALProgressFunc, void *pProgressData);
+                                    GDALProgressFunc, void *pProgressData) override;
     virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
-                                        int nBuckets, GUIntBig *panHistogram );
-    virtual double GetMinimum( int* pbSuccess );
-    virtual double GetMaximum( int* pbSuccess );
+                                        int nBuckets, GUIntBig *panHistogram ) override;
+    virtual double GetMinimum( int* pbSuccess ) override;
+    virtual double GetMaximum( int* pbSuccess ) override;
     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
                                   double *pdfMin, double *pdfMax,
-                                  double *pdfMean, double *padfStdDev );
+                                  double *pdfMean, double *padfStdDev ) override;
     virtual CPLErr SetStatistics( double dfMin, double dfMax,
-                                  double dfMean, double dfStdDev );
+                                  double dfMean, double dfStdDev ) override;
 #endif
 
 };
diff --git a/frmts/ecw/jp2userbox.cpp b/frmts/ecw/jp2userbox.cpp
index cfe9e95..6f4d460 100644
--- a/frmts/ecw/jp2userbox.cpp
+++ b/frmts/ecw/jp2userbox.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: jp2userbox.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GDAL ECW Driver
  * Purpose:  JP2UserBox implementation - arbitrary box read/write.
@@ -27,9 +26,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+// ncsjpcbuffer.h needs the min and max macros.
+#undef NOMINMAX
+
 #include "gdal_ecw.h"
 
-CPL_CVSID("$Id: jp2userbox.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: jp2userbox.cpp 36012 2016-10-29 01:50:11Z goatbar $");
 
 #if defined(HAVE_COMPRESS)
 
diff --git a/frmts/ecw/lookup.py b/frmts/ecw/lookup.py
index 69f6c5b..e067398 100644
--- a/frmts/ecw/lookup.py
+++ b/frmts/ecw/lookup.py
@@ -1,5 +1,5 @@
 #******************************************************************************
-#  $Id: lookup.py 27632 2014-09-04 17:56:16Z goatbar $
+#  $Id: lookup.py 35222 2016-08-28 06:06:11Z goatbar $
 #
 #  Project:  GDAL ECW Driver
 #  Purpose:  Script to lookup ECW (GDT) coordinate systems and translate
@@ -78,7 +78,7 @@ for line in pfile.readlines():
         tokens = string.split(string.strip(line),',')
         if len(tokens) < 3:
             continue
-        
+
 	for i in range(len(tokens)):
 	    tokens[i] = string.strip(tokens[i])
 
@@ -119,14 +119,14 @@ for line in pfile.readlines():
                            float(dline[3]), fe, fn )
 
 	elif type == 'lamcon2':
-	    srs.SetLCC( r2d(dline[7]), r2d(dline[8]), 
+	    srs.SetLCC( r2d(dline[7]), r2d(dline[8]),
 		        r2d(dline[9]), r2d(dline[6]), fe, fn )
 
 #	elif type == 'lambert2':
 #	    false_en = '+y_0=%.2f +x_0=%.2f' \
 #		% (float(dline[12])*lsize, float(dline[13])*lsize)
 #	    result = '+proj=lcc %s +lat_0=%s +lon_0=%s +lat_1=%s +lat_2=%s' \
-#               % (false_en, r2d(dline[3]), r2d(dline[4]), 
+#               % (false_en, r2d(dline[3]), r2d(dline[4]),
 #			r2d(dline[7]), r2d(dline[8]))
 
 	elif type == 'albersea':
@@ -153,7 +153,7 @@ for line in pfile.readlines():
 	    print '%s,%s' % (id, srs.ExportToWkt())
         else:
             print '%s,LOCAL_CS["%s - (unsupported)"]' % (id,id)
-		
+
     except KeyError:
         print '%s,LOCAL_CS["%s - (unsupported)"]' % (id,id)
 
@@ -179,9 +179,9 @@ for line in pfile.readlines():
 
     if id == 'WGS84':
         srs.SetWellKnownGeogCS( 'WGS84' )
-    elif id == 'NAD27': 
+    elif id == 'NAD27':
         srs.SetWellKnownGeogCS( 'NAD27' )
-    elif id == 'NAD83': 
+    elif id == 'NAD83':
         srs.SetWellKnownGeogCS( 'NAD83' )
     else:
         srs.SetGeogCS( tokens[1], id, sp_name, float(dline[2]), float(dline[4]) )
diff --git a/frmts/elas/elasdataset.cpp b/frmts/elas/elasdataset.cpp
index 0df1720..ce9c66a 100644
--- a/frmts/elas/elasdataset.cpp
+++ b/frmts/elas/elasdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: elasdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ELAS Translator
  * Purpose:  Complete implementation of ELAS translator module for GDAL.
@@ -31,45 +30,46 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
+#include <cmath>
 #include <algorithm>
 
 using std::fill;
 
-CPL_CVSID("$Id: elasdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: elasdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 typedef struct ELASHeader {
     ELASHeader();
 
     GInt32      NBIH;   /* bytes in header, normally 1024 */
-    GInt32      NBPR;	/* bytes per data record (all bands of scanline) */
-    GInt32	IL;	/* initial line - normally 1 */
-    GInt32	LL;	/* last line */
+    GInt32      NBPR;   /* bytes per data record (all bands of scanline) */
+    GInt32      IL;     /* initial line - normally 1 */
+    GInt32      LL;     /* last line */
     GInt32      IE;     /* initial element (pixel), normally 1 */
-    GInt32	LE;	/* last element (pixel) */
-    GInt32	NC;	/* number of channels (bands) */
-    GInt32	H4321;	/* header record identifier - always 4321. */
-    char	YLabel[4]; /* Should be "NOR" for UTM */
+    GInt32      LE;     /* last element (pixel) */
+    GInt32      NC;     /* number of channels (bands) */
+    GUInt32     H4321;  /* header record identifier - always 4321. */
+    char        YLabel[4]; /* Should be "NOR" for UTM */
     GInt32      YOffset;/* topleft pixel center northing */
-    char	XLabel[4]; /* Should be "EAS" for UTM */
+    char        XLabel[4]; /* Should be "EAS" for UTM */
     GInt32      XOffset;/* topleft pixel center easting */
-    float	YPixSize;/* height of pixel in georef units */
-    float	XPixSize;/* width of pixel in georef units */
-    float	Matrix[4]; /* 2x2 transformation matrix.  Should be
+    float       YPixSize;/* height of pixel in georef units */
+    float       XPixSize;/* width of pixel in georef units */
+    float       Matrix[4]; /* 2x2 transformation matrix.  Should be
                               1,0,0,1 for pixel/line, or
                               1,0,0,-1 for UTM */
-    GByte	IH19[4];/* data type, and size flags */
-    GInt32	IH20;	/* number of secondary headers */
-    char	unused1[8];
-    GInt32	LABL;	/* used by LABL module */
-    char	HEAD;	/* used by HEAD module */
-    char	Comment1[64];
-    char	Comment2[64];
-    char	Comment3[64];
-    char	Comment4[64];
-    char	Comment5[64];
-    char	Comment6[64];
-    GUInt16	ColorTable[256];  /* RGB packed with 4 bits each */
-    char	unused2[32];
+    GByte       IH19[4];  /* data type, and size flags */
+    GInt32      IH20;   /* number of secondary headers */
+    char        unused1[8];
+    GInt32      LABL;   /* used by LABL module */
+    char        HEAD;   /* used by HEAD module */
+    char        Comment1[64];
+    char        Comment2[64];
+    char        Comment3[64];
+    char        Comment4[64];
+    char        Comment5[64];
+    char        Comment6[64];
+    GUInt16     ColorTable[256];  /* RGB packed with 4 bits each */
+    char        unused2[32];
 } _ELASHeader;
 
 ELASHeader::ELASHeader() :
@@ -106,7 +106,7 @@ ELASHeader::ELASHeader() :
 
 /************************************************************************/
 /* ==================================================================== */
-/*				ELASDataset				*/
+/*                              ELASDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -116,24 +116,24 @@ class ELASDataset : public GDALPamDataset
 {
     friend class ELASRasterBand;
 
-    VSILFILE	*fp;
+    VSILFILE    *fp;
 
     ELASHeader  sHeader;
-    int		bHeaderModified;
+    int         bHeaderModified;
 
     GDALDataType eRasterDataType;
 
-    int		nLineOffset;
-    int		nBandOffset;     // within a line.
+    int         nLineOffset;
+    int         nBandOffset;  // Within a line.
 
-    double	adfGeoTransform[6];
+    double      adfGeoTransform[6];
 
   public:
                  ELASDataset();
-                 ~ELASDataset();
+    virtual ~ELASDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -141,7 +141,7 @@ class ELASDataset : public GDALPamDataset
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
 
-    virtual void FlushCache( void );
+    virtual void FlushCache( void ) override;
 };
 
 /************************************************************************/
@@ -160,11 +160,10 @@ class ELASRasterBand : public GDALPamRasterBand
 
     // should override RasterIO eventually.
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                           ELASRasterBand()                            */
 /************************************************************************/
@@ -172,10 +171,10 @@ class ELASRasterBand : public GDALPamRasterBand
 ELASRasterBand::ELASRasterBand( ELASDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
-    this->eAccess = poDSIn->eAccess;
+    eAccess = poDSIn->eAccess;
 
     eDataType = poDSIn->eRasterDataType;
 
@@ -193,7 +192,7 @@ CPLErr ELASRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 {
     CPLAssert( nBlockXOff == 0 );
 
-    ELASDataset	*poGDS = (ELASDataset *) poDS;
+    ELASDataset *poGDS = (ELASDataset *) poDS;
 
     int nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
     long nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
@@ -226,7 +225,7 @@ CPLErr ELASRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
     CPLAssert( nBlockXOff == 0 );
     CPLAssert( eAccess == GA_Update );
 
-    ELASDataset	*poGDS = (ELASDataset *) poDS;
+    ELASDataset *poGDS = (ELASDataset *) poDS;
 
     int nDataSize = GDALGetDataTypeSize(eDataType) * poGDS->GetRasterXSize() / 8;
     long nOffset = poGDS->nLineOffset * nBlockYOff + 1024 + (nBand-1) * nDataSize;
@@ -249,7 +248,6 @@ CPLErr ELASRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            ELASDataset()                             */
 /************************************************************************/
@@ -339,12 +337,7 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    const char *pszAccess;
-
-    if( poOpenInfo->eAccess == GA_Update )
-        pszAccess = "r+b";
-    else
-        pszAccess = "rb";
+    const char *pszAccess = poOpenInfo->eAccess == GA_Update ? "r+b" : "rb";
 
     ELASDataset *poDS = new ELASDataset();
 
@@ -416,8 +409,8 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
 /* -------------------------------------------------------------------- */
-/*	Band offsets are always multiples of 256 within a multi-band	*/
-/*	scanline of data.						*/
+/*      Band offsets are always multiples of 256 within a multi-band    */
+/*      scanline of data.                                               */
 /* -------------------------------------------------------------------- */
     poDS->nBandOffset =
         (poDS->nRasterXSize * GDALGetDataTypeSize(poDS->eRasterDataType)/8);
@@ -438,7 +431,7 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
 /* -------------------------------------------------------------------- */
-/*	Extract the projection coordinates, if present.			*/
+/*      Extract the projection coordinates, if present.                 */
 /* -------------------------------------------------------------------- */
     if( poDS->sHeader.XOffset != 0 )
     {
@@ -452,7 +445,7 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[3] =
             (GInt32) CPL_MSBWORD32(poDS->sHeader.YOffset);
         poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = -1.0 * ABS(poDS->sHeader.YPixSize);
+        poDS->adfGeoTransform[5] = -1.0 * std::abs(poDS->sHeader.YPixSize);
 
         CPL_MSBPTR32(&(poDS->sHeader.XPixSize));
         CPL_MSBPTR32(&(poDS->sHeader.YPixSize));
@@ -481,7 +474,7 @@ GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -530,7 +523,7 @@ GDALDataset *ELASDataset::Create( const char * pszFilename,
     }
 
 /* -------------------------------------------------------------------- */
-/*	How long will each band of a scanline be?			*/
+/*      How long will each band of a scanline be?                       */
 /* -------------------------------------------------------------------- */
     int nBandOffset = nXSize * GDALGetDataTypeSize(eType)/8;
 
@@ -545,7 +538,7 @@ GDALDataset *ELASDataset::Create( const char * pszFilename,
 /*      Note that CPL_MSBWORD32() will swap little endian words to      */
 /*      big endian on little endian platforms.                          */
 /* -------------------------------------------------------------------- */
-    ELASHeader	sHeader;
+    ELASHeader sHeader;
 
     memset( &sHeader, 0, 1024 );
 
@@ -616,7 +609,7 @@ CPLErr ELASDataset::GetGeoTransform( double * padfTransform )
 {
     memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -653,8 +646,8 @@ CPLErr ELASDataset::SetGeoTransform( double * padfTransform )
     sHeader.XOffset = CPL_MSBWORD32(nXOff);
     sHeader.YOffset = CPL_MSBWORD32(nYOff);
 
-    sHeader.XPixSize = (float) ABS(adfGeoTransform[1]);
-    sHeader.YPixSize = (float) ABS(adfGeoTransform[5]);
+    sHeader.XPixSize = static_cast<float>(std::abs(adfGeoTransform[1]));
+    sHeader.YPixSize = static_cast<float>(std::abs(adfGeoTransform[5]));
 
     CPL_MSBPTR32(&(sHeader.XPixSize));
     CPL_MSBPTR32(&(sHeader.YPixSize));
@@ -672,10 +665,9 @@ CPLErr ELASDataset::SetGeoTransform( double * padfTransform )
     CPL_MSBPTR32(&(sHeader.Matrix[2]));
     CPL_MSBPTR32(&(sHeader.Matrix[3]));
 
-    return( CE_None );
+    return CE_None;
 }
 
-
 /************************************************************************/
 /*                          GDALRegister_ELAS()                         */
 /************************************************************************/
diff --git a/frmts/envisat/EnvisatFile.c b/frmts/envisat/EnvisatFile.c
index 0232ef5..b9943ba 100644
--- a/frmts/envisat/EnvisatFile.c
+++ b/frmts/envisat/EnvisatFile.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: EnvisatFile.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: EnvisatFile.c 36380 2016-11-21 10:21:20Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -35,7 +35,7 @@
 #  include "cpl_conv.h"
 #  include "EnvisatFile.h"
 
-CPL_CVSID("$Id: EnvisatFile.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: EnvisatFile.c 36380 2016-11-21 10:21:20Z rouault $");
 
 #else
 #  include "APP/app.h"
@@ -1234,7 +1234,7 @@ int EnvisatFile_GetDatasetIndex( EnvisatFile *self, const char *ds_name )
 
     /*
      * Padd the name.  While the normal product spec says the DS_NAME will
-     * be 28 characters, I try to pad more than this incase the specification
+     * be 28 characters, I try to pad more than this in case the specification
      * is changed.
      */
     strncpy( padded_ds_name, ds_name, sizeof(padded_ds_name) );
@@ -1752,6 +1752,8 @@ int S_NameValueList_Parse( const char *text, int text_offset,
         int     src_char = 0;
         int     line_offset = 0;
         EnvisatNameValue *entry = NULL;
+        /* workaround cppcheck false positive by using a pointer */
+        char* pszLine = line;
 
         /*
          * Extract one line of text into the "line" buffer, and remove the
@@ -1771,10 +1773,10 @@ int S_NameValueList_Parse( const char *text, int text_offset,
                 return FAILURE;
             }
 
-            line[line_len++] = *(next_text++);
+            pszLine[line_len++] = *(next_text++);
         }
 
-        line[line_len] = '\0';
+        pszLine[line_len] = '\0';
         if( *next_text == '\n' )
             next_text++;
 
diff --git a/frmts/envisat/EnvisatFile.h b/frmts/envisat/EnvisatFile.h
index b808727..51c8b99 100644
--- a/frmts/envisat/EnvisatFile.h
+++ b/frmts/envisat/EnvisatFile.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: EnvisatFile.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: EnvisatFile.h 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
diff --git a/frmts/envisat/adsrange.cpp b/frmts/envisat/adsrange.cpp
index 20cac71..11f3c78 100644
--- a/frmts/envisat/adsrange.cpp
+++ b/frmts/envisat/adsrange.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: adsrange.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Detect range of ADS records matching the MDS records.
@@ -39,6 +38,8 @@ CPL_C_END
 
 #include <cmath>
 
+CPL_CVSID("$Id: adsrange.cpp 35751 2016-10-16 08:52:06Z rouault $");
+
 /* -------------------------------------------------------------------- */
 /*
  * data-set descriptor (private helper class)
@@ -74,7 +75,7 @@ class DataSet
     }
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(DataSet);
+    CPL_DISALLOW_COPY_ASSIGN(DataSet)
 } ;
 
 /* -------------------------------------------------------------------- */
@@ -83,8 +84,10 @@ class DataSet
  *
  */
 
-ADSRangeLastAfter::ADSRangeLastAfter( EnvisatFile & envfile,
-    int  ads_idx , int mds_idx, const TimeDelta & line_interval )
+ADSRangeLastAfter::ADSRangeLastAfter(
+      EnvisatFile & envfile,
+      int  ads_idx , int mds_idx,
+      const TimeDelta & line_interval )
 {
     /* abs.time tolerance */
     TimeDelta atol = line_interval * 0.5 ;
diff --git a/frmts/envisat/adsrange.hpp b/frmts/envisat/adsrange.hpp
index e0849b6..4428028 100644
--- a/frmts/envisat/adsrange.hpp
+++ b/frmts/envisat/adsrange.hpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: adsrange.hpp 31977 2015-12-03 11:42:22Z rouault $
+ * $Id: adsrange.hpp 35218 2016-08-27 22:20:36Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Detect range of ADS records matching the MDS records
- * Author:   Martin Paces, martin.paces at eox.at 
+ * Author:   Martin Paces, martin.paces at eox.at
  *
  ******************************************************************************
- * Copyright (c) 2013, EOX IT Services, GmbH 
+ * Copyright (c) 2013, EOX IT Services, GmbH
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -41,16 +41,15 @@ CPL_C_END
 
 /* -------------------------------------------------------------------- */
 /*
- * class ADSRange 
+ * class ADSRange
  *
- * Range of ADS record matching the range of the MDS records. 
+ * Range of ADS record matching the range of the MDS records.
  *
  */
 
-class ADSRange 
-{ 
-
-  protected: 
+class ADSRange
+{
+  protected:
 
     int idx_first ; /* index of the first matched ADSR */
     int idx_last ;  /* index of the last matched ADSR */
@@ -62,80 +61,77 @@ class ADSRange
     TimeDelta mjd_m_first ;  /* MDJ time of the first MDS record */
     TimeDelta mjd_m_last ;   /* MDJ time of the last MDS record */
 
-  public: 
-
-    /* CONSTRUCTOR */ 
+  public:
+    /* CONSTRUCTOR */
     ADSRange() :
         idx_first(0), idx_last(0), off_first(0), off_last(0),
-        mjd_first(0), mjd_last(0), mjd_m_first(0), mjd_m_last(0) 
-    { 
-    } 
+        mjd_first(0), mjd_last(0), mjd_m_first(0), mjd_m_last(0)
+    {}
 
-    ADSRange( const int idx_firstIn, const int idx_lastIn, 
-        const int off_firstIn, const int off_lastIn, 
-        const TimeDelta &mjd_firstIn, const TimeDelta &mjd_lastIn, 
+    ADSRange( const int idx_firstIn, const int idx_lastIn,
+        const int off_firstIn, const int off_lastIn,
+        const TimeDelta &mjd_firstIn, const TimeDelta &mjd_lastIn,
         const TimeDelta &mjd_m_firstIn, const TimeDelta &mjd_m_lastIn ) :
         idx_first(idx_firstIn), idx_last(idx_lastIn), off_first(off_firstIn),
         off_last(off_lastIn), mjd_first(mjd_firstIn), mjd_last(mjd_lastIn),
-        mjd_m_first(mjd_m_firstIn), mjd_m_last(mjd_m_lastIn) 
-    { 
-    } 
+        mjd_m_first(mjd_m_firstIn), mjd_m_last(mjd_m_lastIn)
+    {}
 
     /* get count of matched records */
-    inline int getDSRCount( void ) const 
-    { 
-        return ( idx_last - idx_first + 1 ) ; 
-    } 
+    inline int getDSRCount( void ) const
+    {
+        return ( idx_last - idx_first + 1 ) ;
+    }
 
-    /* GETTERS */ 
+    /* GETTERS */
 
     /* get index of the first matched ADS record */
-    inline int getFirstIndex( void ) 
-    { 
-        return this->idx_first ; 
-    } 
+    inline int getFirstIndex( void )
+    {
+        return this->idx_first ;
+    }
 
     /* get index of the last matched ADS record */
-    inline int getLastIndex( void ) 
-    { 
-        return this->idx_last ; 
-    } 
+    inline int getLastIndex( void )
+    {
+        return this->idx_last ;
+    }
 
     /* get offset of the first matched ADS record */
-    inline int getFirstOffset( void ) 
-    { 
-        return this->off_first ; 
-    } 
+    inline int getFirstOffset( void )
+    {
+        return this->off_first ;
+    }
 
     /* get offset of the last matched ADS record */
-    inline int getLastOffset( void ) 
-    { 
-        return this->off_last ; 
-    } 
+    inline int getLastOffset( void )
+    {
+        return this->off_last ;
+    }
 
     /* get MJD time of the first matched ADS record */
-    inline TimeDelta getFirstTime( void ) 
-    { 
-        return this->mjd_first ; 
-    } 
+    inline TimeDelta getFirstTime( void )
+    {
+        return this->mjd_first ;
+    }
 
     /* get MJD time of the last matched ADS record */
-    inline TimeDelta getLastTime( void ) 
-    { 
-        return this->mjd_last ; 
-    } 
+    inline TimeDelta getLastTime( void )
+    {
+        return this->mjd_last ;
+    }
 
     /* get MJD time of the first MDS record */
-    inline TimeDelta getMDSRFirstTime( void ) 
-    { 
-        return this->mjd_m_first ; 
-    } 
+    inline TimeDelta getMDSRFirstTime( void )
+    {
+        return this->mjd_m_first ;
+    }
 
     /* get MJD time of the last MDS record */
-    inline TimeDelta getMDSRLastTime( void ) 
-    { 
-        return this->mjd_m_last ; 
-    } 
+    inline TimeDelta getMDSRLastTime( void )
+    {
+        return this->mjd_m_last ;
+    }
 };
 
 
@@ -161,9 +157,9 @@ class ADSRangeLastAfter: public ADSRange
 
   public:
 
-    /* CONSTRUCTOR */ 
+    /* CONSTRUCTOR */
     ADSRangeLastAfter( EnvisatFile & envfile, int  ads_idx , int mds_idx,
-            const TimeDelta & line_interval ) ; 
+            const TimeDelta & line_interval ) ;
 };
 
 
diff --git a/frmts/envisat/dumpgeo.c b/frmts/envisat/dumpgeo.c
index fb1265f..ea4a866 100644
--- a/frmts/envisat/dumpgeo.c
+++ b/frmts/envisat/dumpgeo.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dumpgeo.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: dumpgeo.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Test mainline for dumping ENVISAT format files.
diff --git a/frmts/envisat/envisat_dump.c b/frmts/envisat/envisat_dump.c
index 795000e..0117f4f 100644
--- a/frmts/envisat/envisat_dump.c
+++ b/frmts/envisat/envisat_dump.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: envisat_dump.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: envisat_dump.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Test mainline for dumping ENVISAT format files.
diff --git a/frmts/envisat/envisatdataset.cpp b/frmts/envisat/envisatdataset.cpp
index d3d6d6a..3ed5dcb 100644
--- a/frmts/envisat/envisatdataset.cpp
+++ b/frmts/envisat/envisatdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: envisatdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Reader for ENVISAT format image data.
@@ -35,7 +34,7 @@
 #include "ogr_srs_api.h"
 #include "timedelta.hpp"
 
-CPL_CVSID("$Id: envisatdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: envisatdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 CPL_C_START
 #include "EnvisatFile.h"
@@ -52,7 +51,7 @@ class MerisL2FlagBand : public GDALPamRasterBand
   public:
     MerisL2FlagBand( GDALDataset *, int, VSILFILE*, vsi_l_offset, int );
     virtual ~MerisL2FlagBand();
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 
   private:
     vsi_l_offset nImgOffset;
@@ -68,29 +67,27 @@ class MerisL2FlagBand : public GDALPamRasterBand
 /*                        MerisL2FlagBand()                       */
 /************************************************************************/
 MerisL2FlagBand::MerisL2FlagBand( GDALDataset *poDSIn, int nBandIn,
-                                  VSILFILE* fpImageIn, vsi_l_offset nImgOffsetIn,
+                                  VSILFILE* fpImageIn,
+                                  vsi_l_offset nImgOffsetIn,
                                   int nPrefixBytesIn ) :
-    nBytePerPixel(3)
+    nImgOffset(nImgOffsetIn),
+    nPrefixBytes(nPrefixBytesIn),
+    nBytePerPixel(3),
+    nRecordSize(nPrefixBytesIn + nBlockXSize * nBytePerPixel),
+    nDataSize(nBlockXSize * nBytePerPixel),
+    pReadBuf(static_cast<GByte *>(CPLMalloc(nRecordSize)))
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
-    this->fpImage = fpImageIn;
-    this->nImgOffset = nImgOffsetIn;
-    this->nPrefixBytes = nPrefixBytesIn;
+    fpImage = fpImageIn;
 
     eDataType = GDT_UInt32;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
-
-    nDataSize = nBlockXSize * nBytePerPixel;
-    nRecordSize = nPrefixBytes + nDataSize;
-
-    pReadBuf = (GByte *) CPLMalloc( nRecordSize );
 }
 
-
 /************************************************************************/
 /*                        ~MerisL2FlagBand()                       */
 /************************************************************************/
@@ -128,9 +125,10 @@ CPLErr MerisL2FlagBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         return CE_Failure;
     }
 
+    const unsigned int nUInt32Size = 4;
     for( unsigned iImg = 0, iBuf = 0;
-         iImg < nBlockXSize * (unsigned)sizeof(GDT_UInt32);
-         iImg += (unsigned)sizeof(GDT_UInt32), iBuf += (unsigned)nBytePerPixel )
+         iImg < nBlockXSize * nUInt32Size;
+         iImg += nUInt32Size, iBuf += (unsigned)nBytePerPixel )
     {
 #ifdef CPL_LSB
         ((GByte*) pImage)[iImg] = pReadBuf[iBuf + 2];
@@ -148,17 +146,16 @@ CPLErr MerisL2FlagBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     return CE_None;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
-/*				EnvisatDataset				*/
+/*                              EnvisatDataset                          */
 /* ==================================================================== */
 /************************************************************************/
 
 class EnvisatDataset : public RawDataset
 {
     EnvisatFile *hEnvisatFile;
-    VSILFILE	*fpImage;
+    VSILFILE    *fpImage;
 
     int         nGCPCount;
     GDAL_GCP    *pasGCPList;
@@ -170,32 +167,31 @@ class EnvisatDataset : public RawDataset
 
     void        UnwrapGCPs();
 
-    void	CollectMetadata( EnvisatFile_HeaderFlag );
+    void        CollectMetadata( EnvisatFile_HeaderFlag );
     void        CollectDSDMetadata();
     void        CollectADSMetadata();
 
   public:
-    		EnvisatDataset();
-    	        ~EnvisatDataset();
-
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-    virtual char      **GetMetadataDomainList();
-    virtual char **GetMetadata( const char * pszDomain );
+                EnvisatDataset();
+    virtual ~EnvisatDataset();
 
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
+    virtual char      **GetMetadataDomainList() override;
+    virtual char **GetMetadata( const char * pszDomain ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
 /************************************************************************/
 /* ==================================================================== */
-/*				EnvisatDataset				*/
+/*                              EnvisatDataset                          */
 /* ==================================================================== */
 /************************************************************************/
 
 /************************************************************************/
-/*                            EnvisatDataset()                             */
+/*                            EnvisatDataset()                          */
 /************************************************************************/
 
 EnvisatDataset::EnvisatDataset() :
@@ -204,11 +200,10 @@ EnvisatDataset::EnvisatDataset() :
     nGCPCount(0),
     pasGCPList(NULL),
     papszTempMD(NULL)
-{
-}
+{}
 
 /************************************************************************/
-/*                            ~EnvisatDataset()                            */
+/*                            ~EnvisatDataset()                         */
 /************************************************************************/
 
 EnvisatDataset::~EnvisatDataset()
@@ -301,11 +296,12 @@ void EnvisatDataset::ScanForGCPs_ASAR()
         return;
 
 /* -------------------------------------------------------------------- */
-/*      Collect the first GCP set from each record.			*/
+/*      Collect the first GCP set from each record.                     */
 /* -------------------------------------------------------------------- */
-    GByte	abyRecord[521];
-    int  	nRange=0, nRangeOffset=0;
-    GUInt32 	unValue;
+    GByte abyRecord[521];
+    int nRange = 0;
+    int nRangeOffset = 0;
+    GUInt32 unValue;
 
     nGCPCount = 0;
     pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),(nNumDSR+1) * 11);
@@ -441,7 +437,7 @@ void EnvisatDataset::ScanForGCPs_MERIS()
 
     for( ; true; nMDSIndex++ )
     {
-        char *pszDSType;
+        char *pszDSType = NULL;
         if( EnvisatFile_GetDatasetInfo( hEnvisatFile, nMDSIndex,
             NULL, &pszDSType, NULL, NULL, NULL, NULL, NULL ) == FAILURE )
         {
@@ -453,7 +449,7 @@ void EnvisatDataset::ScanForGCPs_MERIS()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Get subset of TP ADS records matching the MDS records	*/
+/*      Get subset of TP ADS records matching the MDS records           */
 /* -------------------------------------------------------------------- */
 
     /* get the MDS line sampling time interval */
@@ -511,10 +507,10 @@ void EnvisatDataset::ScanForGCPs_MERIS()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Collect the first GCP set from each record.			*/
+/*      Collect the first GCP set from each record.                     */
 /* -------------------------------------------------------------------- */
 
-    GByte	*pabyRecord = (GByte *) CPLMalloc(nDSRSize-13);
+    GByte *pabyRecord = (GByte *) CPLMalloc(nDSRSize-13);
 
     GUInt32 *tpLat = ((GUInt32*)pabyRecord) + nTPPerLine*0 ; /* latitude */
     GUInt32 *tpLon = ((GUInt32*)pabyRecord) + nTPPerLine*1 ; /* longitude */
@@ -667,7 +663,7 @@ char **EnvisatDataset::GetMetadata( const char * pszDomain )
 void EnvisatDataset::CollectDSDMetadata()
 
 {
-    char	*pszDSName, *pszFilename;
+    char *pszDSName, *pszFilename;
 
     for( int iDSD = 0;
          EnvisatFile_GetDatasetInfo( hEnvisatFile, iDSD, &pszDSName, NULL,
@@ -853,7 +849,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    EnvisatFile	*hEnvisatFile;
+    EnvisatFile *hEnvisatFile = NULL;
     if( EnvisatFile_Open( &hEnvisatFile, poOpenInfo->pszFilename, "r" )
         == FAILURE )
         return NULL;
@@ -863,7 +859,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      raster band.                                                    */
 /* -------------------------------------------------------------------- */
     int         dsr_size, num_dsr, ds_offset;
-    char        *pszDSType;
+    char        *pszDSType = NULL;
 
     int ds_index = 0;
     for( ; true; ds_index++ )
@@ -996,7 +992,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Scan for all datasets matching the reference dataset.           */
 /* -------------------------------------------------------------------- */
     int num_dsr2, dsr_size2, iBand = 0;
-    const char *pszDSName;
+    const char *pszDSName = NULL;
     char szBandName[128];
     bool bMiltiChannel;
 
@@ -1138,7 +1134,7 @@ GDALDataset *EnvisatDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/envisat/records.c b/frmts/envisat/records.c
index 43a0c45..39330a1 100644
--- a/frmts/envisat/records.c
+++ b/frmts/envisat/records.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: records.c 32100 2015-12-09 07:07:26Z goatbar $
+ * $Id: records.c 36393 2016-11-21 14:25:42Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -30,7 +30,7 @@
 #include "cpl_string.h"
 #include "records.h"
 
-CPL_CVSID("$Id: records.c 32100 2015-12-09 07:07:26Z goatbar $");
+CPL_CVSID("$Id: records.c 36393 2016-11-21 14:25:42Z rouault $");
 
 /* --- ASAR record descriptors --------------------------------------------- */
 static const EnvisatFieldDescr ASAR_ANTENNA_ELEV_PATT_ADSR[] = {
@@ -1399,7 +1399,7 @@ CPLErr EnvisatFile_GetFieldAsString(const void *pRecord, int nRecLen,
                 seconds = CPL_MSBWORD32(((const GUInt32*)pData)[1]);
                 microseconds = CPL_MSBWORD32(((const GUInt32*)pData)[2]);
 
-                snprintf(szBuf, nBufLen, "%d, %d, %d", days, seconds, microseconds);
+                snprintf(szBuf, nBufLen, "%d, %u, %u", days, seconds, microseconds);
             }
             break;
         default:
diff --git a/frmts/envisat/records.h b/frmts/envisat/records.h
index c5242e2..1dfe733 100644
--- a/frmts/envisat/records.h
+++ b/frmts/envisat/records.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: records.h 32078 2015-12-08 09:09:45Z rouault $
+ * $Id: records.h 35885 2016-10-24 06:23:09Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  Low Level Envisat file access (read/write) API.
@@ -37,7 +37,6 @@ extern "C"
 {
 #endif
 
-
 #define MJD_FIELD_SIZE 12
 
 /*! Field data types */
@@ -77,7 +76,6 @@ const EnvisatRecordDescr* EnvisatFile_GetRecordDescriptor(const char* pszProduct
 
 CPLErr EnvisatFile_GetFieldAsString(const void*, int, const EnvisatFieldDescr*, char*, size_t);
 
-
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
diff --git a/frmts/envisat/timedelta.hpp b/frmts/envisat/timedelta.hpp
index 312e576..73dfe6d 100644
--- a/frmts/envisat/timedelta.hpp
+++ b/frmts/envisat/timedelta.hpp
@@ -1,12 +1,12 @@
 /******************************************************************************
- * $Id: timedelta.hpp 33123 2016-01-23 18:59:28Z rouault $
+ * $Id: timedelta.hpp 36411 2016-11-21 22:03:48Z rouault $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  time difference class for handling of Envisat MJD time
- * Author:   Martin Paces, martin.paces at eox.at 
+ * Author:   Martin Paces, martin.paces at eox.at
  *
  ******************************************************************************
- * Copyright (c) 2013, EOX IT Services, GmbH 
+ * Copyright (c) 2013, EOX IT Services, GmbH
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,133 +30,133 @@
 #ifndef timedelta_hpp
 #define timedelta_hpp
 /*
- * TimeDelta class represents the time difference. It is used to 
- * hold the Envisat MJD (Modified Julian Date - which is time 
- * since 2000-01-01T00:00:00.000000Z) 
+ * TimeDelta class represents the time difference. It is used to
+ * hold the Envisat MJD (Modified Julian Date - which is time
+ * since 2000-01-01T00:00:00.000000Z)
  */
 
-class TimeDelta  
+class TimeDelta
 {
 
   private:
 
     int days ;     /* number of days */
-    int secs ;     /* number of seconds since day start */ 
+    int secs ;     /* number of seconds since day start */
     int usecs ;    /* number of micro sec. since second start */
 
     /* SETTERS */
 
     /* set object using number of days, seconds and micro-seconds */
-    inline void set( int daysIn , int secsIn , int usecsIn ) 
-    { 
-        int tmp0 , tmp1 ; 
-        /* overflow check with proper handling of negative values */ 
-        /* note that division and modulo for negative values is impl.dependent */ 
+    inline void set( int daysIn , int secsIn , int usecsIn )
+    {
+        int tmp0 , tmp1 ;
+        /* overflow check with proper handling of negative values */
+        /* note that division and modulo for negative values is impl.dependent */
 
-        secsIn += ( tmp0 = usecsIn>=0 ? usecsIn/1000000 : -1-((-usecsIn)/1000000) ) ;  
+        secsIn += ( tmp0 = usecsIn>=0 ? usecsIn/1000000 : -1-((-usecsIn)/1000000) ) ;
         daysIn += ( tmp1 = secsIn>=0 ? secsIn/86400 : -1-((-secsIn)/86400) ) ;
 
         this->usecs = usecsIn - 1000000*tmp0 ;
-        this->secs  = secsIn - 86400*tmp1 ; 
+        this->secs  = secsIn - 86400*tmp1 ;
         this->days  = daysIn ;
-    } 
+    }
 
     /* set object from floating point number of seconds */
-    inline void fromSeconds( double secsIn ) 
-    { 
+    inline void fromSeconds( double secsIn )
+    {
         int _days = (int)( secsIn / 86400 ) ;
         int _secs = (int)( secsIn - 86400*_days ) ;
-        int _uscs = (int)(( secsIn - ((int)secsIn) )*1e6) ; 
+        int _uscs = (int)(( secsIn - ((int)secsIn) )*1e6) ;
 
         this->set( _days , _secs , _uscs ) ;
-    } 
+    }
 
   public:
 
     /* CONSTRUCTORS */
-    TimeDelta( void ) : days(0), secs(0), usecs(0) {} 
+    TimeDelta( void ) : days(0), secs(0), usecs(0) {}
 
     /* construct object using number of days, seconds and micro-seconds */
-    TimeDelta( int daysIn , int secsIn , int usecsIn ) 
-    { 
+    TimeDelta( int daysIn , int secsIn , int usecsIn )
+    {
         this->set( daysIn, secsIn, usecsIn ) ;
-    } 
+    }
 
     /* construct object from floating point number of seconds */
-    TimeDelta( double secsIn ) 
-    { 
+    explicit TimeDelta( double secsIn )
+    {
         this->fromSeconds( secsIn ) ;
     }
 
     /* GETTERS */
 
-    inline int getDays( void ) const 
-    { 
-        return this->days ; 
-    } 
+    inline int getDays( void ) const
+    {
+        return this->days ;
+    }
 
     inline int getSeconds( void ) const
-    { 
-        return this->secs ; 
-    } 
+    {
+        return this->secs ;
+    }
 
-    inline int getMicroseconds( void ) const 
-    { 
-        return this->usecs ; 
-    } 
+    inline int getMicroseconds( void ) const
+    {
+        return this->usecs ;
+    }
 
     /* convert to seconds - can handle safely at least 250 years dif. */
     /*  ... before losing the microsecond precision */
-    inline operator double( void ) const  
-    { 
+    inline operator double( void ) const
+    {
         return (this->days*86400.0) + this->secs + (this->usecs*1e-6) ;
-    } 
+    }
 
     /* OPERATORS */
 
     /* difference */
-    inline TimeDelta operator -( const TimeDelta & that ) const 
-    { 
-        return TimeDelta( this->days - that.days, this->secs - that.secs, 
-                                this->usecs - that.usecs ) ; 
+    inline TimeDelta operator -( const TimeDelta & that ) const
+    {
+        return TimeDelta( this->days - that.days, this->secs - that.secs,
+                                this->usecs - that.usecs ) ;
     }
 
     /* addition */
-    inline TimeDelta operator +( const TimeDelta & that ) const 
-    { 
-        return TimeDelta( this->days + that.days, this->secs + that.secs, 
-                                this->usecs + that.usecs ) ; 
+    inline TimeDelta operator +( const TimeDelta & that ) const
+    {
+        return TimeDelta( this->days + that.days, this->secs + that.secs,
+                                this->usecs + that.usecs ) ;
     }
 
     /* division */
-    inline double operator /( const TimeDelta & that ) const 
-    { 
+    inline double operator /( const TimeDelta & that ) const
+    {
         return ( (double)*this / (double)that ) ;
     }
 
     /* integer multiplication */
-    inline TimeDelta operator *( const int i ) const 
-    { 
+    inline TimeDelta operator *( const int i ) const
+    {
         return TimeDelta( i*this->days, i*this->secs, i*this->usecs ) ;
     }
 
     /* float multiplication */
-    inline TimeDelta operator *( const double f ) const 
-    { 
+    inline TimeDelta operator *( const double f ) const
+    {
         return TimeDelta( f * (double)*this ) ;
     }
 
     /* comparisons operators */
 
-    inline bool operator ==( const TimeDelta & that ) const 
-    { 
+    inline bool operator ==( const TimeDelta & that ) const
+    {
         return ( (this->usecs == that.usecs)&&(this->secs == that.secs)&&
-                 (this->days == that.days) )  ;  
-    } 
+                 (this->days == that.days) )  ;
+    }
 
 
-    inline bool operator >( const TimeDelta & that ) const 
-    { 
+    inline bool operator >( const TimeDelta & that ) const
+    {
         return  (this->days > that.days)
                 ||(
                     (this->days == that.days)
@@ -168,10 +168,10 @@ class TimeDelta
                         )
                     )
                 ) ;
-    } 
+    }
 
-    inline bool operator <( const TimeDelta & that ) const 
-    { 
+    inline bool operator <( const TimeDelta & that ) const
+    {
         return  (this->days < that.days)
                 ||(
                     (this->days == that.days)
@@ -183,34 +183,34 @@ class TimeDelta
                         )
                     )
                 ) ;
-    } 
+    }
 
-    inline bool operator !=( const TimeDelta & that ) const 
-    { 
+    inline bool operator !=( const TimeDelta & that ) const
+    {
         return !( *this == that ) ;
-    } 
+    }
 
-    inline bool operator >=( const TimeDelta & that ) const 
-    { 
+    inline bool operator >=( const TimeDelta & that ) const
+    {
         return !( *this < that ) ;
-    } 
+    }
 
-    inline bool operator <=( const TimeDelta & that ) const 
-    { 
+    inline bool operator <=( const TimeDelta & that ) const
+    {
         return !( *this > that ) ;
-    } 
+    }
 
 };
 
 /*
 #include <iostream>
 
-std::ostream & operator<<( std::ostream & out, const TimeDelta & td ) 
+std::ostream & operator<<( std::ostream & out, const TimeDelta & td )
 {
 
-    out << "TimeDelta(" << td.getDays() 
-        << "," << td.getSeconds() 
-        << "," << td.getMicroseconds() << ")" ; 
+    out << "TimeDelta(" << td.getDays()
+        << "," << td.getSeconds()
+        << "," << td.getMicroseconds() << ")" ;
 
     return out ;
 }
diff --git a/frmts/envisat/unwrapgcps.cpp b/frmts/envisat/unwrapgcps.cpp
index 397a36f..6b82be9 100644
--- a/frmts/envisat/unwrapgcps.cpp
+++ b/frmts/envisat/unwrapgcps.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: unwrapgcps.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  APP ENVISAT Support
  * Purpose:  GCPs Unwrapping for products crossing the WGS84 date-line
@@ -31,6 +30,8 @@
 #include <cmath>
 #include <cstdio>
 
+CPL_CVSID("$Id: unwrapgcps.cpp 35885 2016-10-24 06:23:09Z goatbar $");
+
 // number of histogram bins (36 a 10dg)
 static const int NBIN = 36;
 // number of empty bins to guess the flip-point
@@ -78,9 +79,11 @@ static double _suggest_flip_point( const int cnt, GDAL_GCP *gcp )
         hist[idx] += 1 ;
     }
 
-    // find a middle of at least NEMPTY consecutive empty bins and get its middle
-    int i0 = -1 , i1 = -1 , last_is_empty = 0 ;
-    for( int i = 0 ; i < (2*NBIN-1) ; i++ )
+    // Find middle of at least NEMPTY consecutive empty bins and get its middle.
+    int i0 = -1;
+    int i1 = -1;
+    int last_is_empty = 0;
+    for( int i = 0; i < (2*NBIN-1); i++ )
     {
         if ( 0 == hist[i%NBIN] ) // empty
         {
@@ -110,10 +113,9 @@ static double _suggest_flip_point( const int cnt, GDAL_GCP *gcp )
 
     double tmp = ((i1-i0)*0.5+i0)/((float)NBIN) ;
 
-    return (tmp-floor(tmp))*XDIF + XMIN ;
+    return (tmp-floor(tmp))*XDIF + XMIN;
 }
 
-
 void EnvisatUnwrapGCPs( int cnt, GDAL_GCP *gcp )
 {
     if ( cnt < 1 ) return ;
@@ -127,13 +129,18 @@ void EnvisatUnwrapGCPs( int cnt, GDAL_GCP *gcp )
     double x0_dif , x1_dif ;
 
     {
-        double x0_min, x0_max, x1_min, x1_max ;
+        double x0_min;
+        double x0_max;
+        double x1_min;
+        double x1_max;
 
         {
-            double x0 = gcp[0].dfGCPX ;
+            double x0 = gcp[0].dfGCPX;
             int  flip = (x0>x_flip) ;
-            x0_min = x0_max = x0 ;
-            x1_min = x1_max = x0 - flip*XDIF ;
+            x0_min = x0;
+            x0_max = x0;
+            x1_min = x0 - flip*XDIF;
+            x1_max = x1_min;
             cnt_flip += flip ; // count the flipped values
         }
 
diff --git a/frmts/epsilon/epsilondataset.cpp b/frmts/epsilon/epsilondataset.cpp
index 51ca9c0..0e58a14 100644
--- a/frmts/epsilon/epsilondataset.cpp
+++ b/frmts/epsilon/epsilondataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: epsilondataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL Epsilon driver
  * Purpose:  Implement GDAL Epsilon support using Epsilon library
@@ -30,9 +29,17 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
 #include "epsilon.h"
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
 
-CPL_CVSID("$Id: epsilondataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: epsilondataset.cpp 36758 2016-12-09 16:14:08Z goatbar $");
 
 #define RASTERLITE_WAVELET_HEADER "StartWaveletsImage$$"
 #define RASTERLITE_WAVELET_FOOTER "$$EndWaveletsImage"
@@ -114,38 +121,32 @@ class EpsilonRasterBand : public GDALPamRasterBand
   public:
                             EpsilonRasterBand(EpsilonDataset* poDS, int nBand);
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
 /************************************************************************/
 /*                         EpsilonDataset()                             */
 /************************************************************************/
 
-EpsilonDataset::EpsilonDataset()
-{
-    fp = NULL;
-    nFileOff = 0;
-
-    pabyFileBuf = NULL;
-    nFileBufMaxSize = 0;
-    nFileBufCurSize = 0;
-    nFileBufOffset = 0;
-    bEOF = FALSE;
-    bError = FALSE;
-
-    pabyBlockData = NULL;
-    nBlockDataSize = 0;
-    nStartBlockFileOff = 0;
-
-    bRegularTiling = FALSE;
-
-    nBlocks = 0;
-    pasBlocks = NULL;
-
-    nBufferedBlock = -1;
-    pabyRGBData = NULL;
-}
+EpsilonDataset::EpsilonDataset() :
+    fp(NULL),
+    nFileOff(0),
+    pabyFileBuf(NULL),
+    nFileBufMaxSize(0),
+    nFileBufCurSize(0),
+    nFileBufOffset(0),
+    bEOF(FALSE),
+    bError(FALSE),
+    pabyBlockData(NULL),
+    nBlockDataSize(0),
+    nStartBlockFileOff(0),
+    bRegularTiling(FALSE),
+    nBlocks(0),
+    pasBlocks(NULL),
+    nBufferedBlock(-1),
+    pabyRGBData(NULL)
+{}
 
 /************************************************************************/
 /*                         ~EpsilonDataset()                            */
@@ -153,7 +154,7 @@ EpsilonDataset::EpsilonDataset()
 
 EpsilonDataset::~EpsilonDataset()
 {
-    if (fp)
+    if( fp )
         VSIFCloseL(fp);
     VSIFree(pabyFileBuf);
     VSIFree(pasBlocks);
@@ -164,13 +165,13 @@ EpsilonDataset::~EpsilonDataset()
 /*                       EpsilonRasterBand()                            */
 /************************************************************************/
 
-EpsilonRasterBand::EpsilonRasterBand(EpsilonDataset* poDSIn, int nBandIn)
+EpsilonRasterBand::EpsilonRasterBand( EpsilonDataset* poDSIn, int nBandIn )
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->eDataType = GDT_Byte;
-    this->nBlockXSize = poDSIn->pasBlocks[0].w;
-    this->nBlockYSize = poDSIn->pasBlocks[0].h;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eDataType = GDT_Byte;
+    nBlockXSize = poDSIn->pasBlocks[0].w;
+    nBlockYSize = poDSIn->pasBlocks[0].h;
 }
 
 /************************************************************************/
@@ -326,9 +327,7 @@ CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
             int iOtherBand;
             for(iOtherBand=2;iOtherBand<=3;iOtherBand++)
             {
-                GDALRasterBlock *poBlock;
-
-                poBlock = poGDS->GetRasterBand(iOtherBand)->
+                GDALRasterBlock *poBlock = poGDS->GetRasterBand(iOtherBand)->
                     GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
                 if (poBlock == NULL)
                     break;
@@ -684,7 +683,6 @@ GDALDataset* EpsilonDataset::Open(GDALOpenInfo* poOpenInfo)
     return poDS;
 }
 
-
 /************************************************************************/
 /*                  EpsilonDatasetCreateCopy ()                         */
 /************************************************************************/
@@ -865,16 +863,19 @@ EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Iterate over blocks                                             */
 /* -------------------------------------------------------------------- */
 
-    int nBlockXOff, nBlockYOff;
+    int nBlockXOff;
+    int nBlockYOff;
     CPLErr eErr = CE_None;
-    for(nBlockYOff = 0;
-        eErr == CE_None && nBlockYOff < nYBlocks; nBlockYOff ++)
+    for( nBlockYOff = 0;
+         eErr == CE_None && nBlockYOff < nYBlocks;
+         nBlockYOff++ )
     {
         for(nBlockXOff = 0;
             eErr == CE_None && nBlockXOff < nXBlocks; nBlockXOff ++)
         {
             int bMustMemset = FALSE;
-            int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
+            int nReqXSize = nBlockXSize;
+            int nReqYSize = nBlockYSize;
             if ((nBlockXOff+1) * nBlockXSize > nXSize)
             {
                 bMustMemset = TRUE;
diff --git a/frmts/ers/ersdataset.cpp b/frmts/ers/ersdataset.cpp
index dbcc251..8e375e2 100644
--- a/frmts/ers/ersdataset.cpp
+++ b/frmts/ers/ersdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ersdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ERMapper .ers Driver
  * Purpose:  Implementation of .ers driver.
@@ -34,7 +33,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: ersdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: ersdataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -48,7 +47,7 @@ class ERSDataset : public RawDataset
 {
     friend class ERSRasterBand;
 
-    VSILFILE	*fpImage;	// image data file.
+    VSILFILE    *fpImage;  // Image data file.
     GDALDataset *poDepFile;
 
     int         bGotTransform;
@@ -81,29 +80,29 @@ class ERSDataset : public RawDataset
     CPLStringList oERSMetadataList;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
   public:
-    		ERSDataset();
-	       ~ERSDataset();
-
-    virtual void FlushCache(void);
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual CPLErr SetGeoTransform( double *padfTransform );
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual char **GetFileList(void);
-
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+                ERSDataset();
+    virtual    ~ERSDataset();
+
+    virtual void FlushCache(void) override;
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr SetGeoTransform( double *padfTransform ) override;
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual char **GetFileList(void) override;
+
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) override;
 
-    virtual char      **GetMetadataDomainList();
+    virtual char      **GetMetadataDomainList() override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                     const char * pszDomain = "" );
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) override;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
@@ -120,22 +119,21 @@ ERSDataset::ERSDataset() :
     fpImage(NULL),
     poDepFile(NULL),
     bGotTransform(FALSE),
+    pszProjection(CPLStrdup("")),
     bHDRDirty(FALSE),
     poHeader(NULL),
     nGCPCount(0),
     pasGCPList(NULL),
+    pszGCPProjection(CPLStrdup("")),
     bHasNoDataValue(FALSE),
     dfNoDataValue(0.0)
 {
-    pszProjection = CPLStrdup("");
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-
-    pszGCPProjection = CPLStrdup("");
 }
 
 /************************************************************************/
@@ -258,11 +256,11 @@ char **ERSDataset::GetMetadata( const char *pszDomain )
     if( pszDomain != NULL && EQUAL(pszDomain, "ERS") )
     {
         oERSMetadataList.Clear();
-        if (osProj.size())
+        if (!osProj.empty() )
             oERSMetadataList.AddString(CPLSPrintf("%s=%s", "PROJ", osProj.c_str()));
-        if (osDatum.size())
+        if (!osDatum.empty() )
             oERSMetadataList.AddString(CPLSPrintf("%s=%s", "DATUM", osDatum.c_str()));
-        if (osUnits.size())
+        if (!osUnits.empty() )
             oERSMetadataList.AddString(CPLSPrintf("%s=%s", "UNITS", osUnits.c_str()));
         return oERSMetadataList.List();
     }
@@ -377,7 +375,7 @@ CPLErr ERSDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
         CPLString osLine;
 
         CPLString osId = pasGCPList[iGCP].pszId;
-        if( strlen(osId) == 0 )
+        if( osId.empty() )
             osId.Printf( "%d", iGCP + 1 );
 
         osLine.Printf( "\t\t\t\t\"%s\"\tYes\tYes\t%.6f\t%.6f\t%.15g\t%.15g\t%.15g\n",
@@ -434,15 +432,15 @@ CPLErr ERSDataset::SetProjection( const char *pszSRS )
 
     /* Write the above computed values, unless they have been overridden by */
     /* the creation options PROJ, DATUM or UNITS */
-    if( osProjForced.size() )
+    if( !osProjForced.empty() )
         osProj = osProjForced;
     else
         osProj = szERSProj;
-    if( osDatumForced.size() )
+    if( !osDatumForced.empty() )
         osDatum = osDatumForced;
     else
         osDatum = szERSDatum;
-    if( osUnitsForced.size() )
+    if( !osUnitsForced.empty() )
         osUnits = osUnitsForced;
     else
         osUnits = szERSUnits;
@@ -610,10 +608,10 @@ char **ERSDataset::GetFileList()
     char **papszFileList = GDALPamDataset::GetFileList();
 
     // Add raw data file if we have one.
-    if( strlen(osRawFilename) > 0 )
+    if( !osRawFilename.empty() )
         papszFileList = CSLAddString( papszFileList, osRawFilename );
 
-    // If we have a dependent file, merge it's list of files in.
+    // If we have a dependent file, merge its list of files in.
     if( poDepFile )
     {
         char **papszDepFiles = poDepFile->GetFileList();
@@ -708,9 +706,9 @@ void ERSDataset::ReadGCPs()
     osDatum = poHeader->Find( "RasterInfo.WarpControl.CoordinateSpace.Datum", "" );
     osUnits = poHeader->Find( "RasterInfo.WarpControl.CoordinateSpace.Units", "" );
 
-    oSRS.importFromERM( osProj.size() ? osProj.c_str() : "RAW",
-                        osDatum.size() ? osDatum.c_str() : "WGS84",
-                        osUnits.size() ? osUnits.c_str() : "METERS" );
+    oSRS.importFromERM( !osProj.empty() ? osProj.c_str() : "RAW",
+                        !osDatum.empty() ? osDatum.c_str() : "WGS84",
+                        !osUnits.empty() ? osUnits.c_str() : "METERS" );
 
     CPLFree( pszGCPProjection );
     oSRS.exportToWkt( &pszGCPProjection );
@@ -732,8 +730,8 @@ class ERSRasterBand : public RawRasterBand
                                 GDALDataType eDataType, int bNativeOrder,
                                 int bIsVSIL = FALSE, int bOwnsFP = FALSE );
 
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr SetNoDataValue( double );
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual CPLErr SetNoDataValue( double ) override;
 };
 
 /************************************************************************/
@@ -741,14 +739,14 @@ class ERSRasterBand : public RawRasterBand
 /************************************************************************/
 
 ERSRasterBand::ERSRasterBand( GDALDataset *poDSIn, int nBandIn, void * fpRawIn,
-                                vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
-                                int nLineOffsetIn,
-                                GDALDataType eDataTypeIn, int bNativeOrderIn,
-                                int bIsVSILIn, int bOwnsFPIn ) :
+                              vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
+                              int nLineOffsetIn,
+                              GDALDataType eDataTypeIn, int bNativeOrderIn,
+                              int bIsVSILIn, int bOwnsFPIn ) :
     RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
-                  nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn, bOwnsFPIn)
-{
-}
+                  nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn,
+                  bOwnsFPIn)
+{}
 
 /************************************************************************/
 /*                           GetNoDataValue()                           */
@@ -1056,9 +1054,9 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->osDatum = poHeader->Find( "CoordinateSpace.Datum", "" );
     poDS->osUnits = poHeader->Find( "CoordinateSpace.Units", "" );
 
-    oSRS.importFromERM( poDS->osProj.size() ? poDS->osProj.c_str() : "RAW",
-                        poDS->osDatum.size() ? poDS->osDatum.c_str() : "WGS84",
-                        poDS->osUnits.size() ? poDS->osUnits.c_str() : "METERS" );
+    oSRS.importFromERM( !poDS->osProj.empty() ? poDS->osProj.c_str() : "RAW",
+                        !poDS->osDatum.empty() ? poDS->osDatum.c_str() : "WGS84",
+                        !poDS->osUnits.empty() ? poDS->osUnits.c_str() : "METERS" );
 
     CPLFree( poDS->pszProjection );
     oSRS.exportToWkt( &(poDS->pszProjection) );
@@ -1196,7 +1194,6 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
         }
 
         CPLPopErrorHandler();
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -1234,7 +1231,7 @@ GDALDataset *ERSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1304,7 +1301,7 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
         pszCellType = "IEEE8ByteReal";
     else
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1343,7 +1340,6 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
     }
     VSIFCloseL( fpBin );
 
-
 /* -------------------------------------------------------------------- */
 /*      Try writing header file.                                        */
 /* -------------------------------------------------------------------- */
@@ -1397,14 +1393,23 @@ GDALDataset *ERSDataset::Create( const char * pszFilename,
 /*      Fetch DATUM, PROJ and UNITS creation option                     */
 /* -------------------------------------------------------------------- */
     const char *pszDatum = CSLFetchNameValue( papszOptions, "DATUM" );
-    if (pszDatum)
-        poDS->osDatumForced = poDS->osDatum = pszDatum;
+    if( pszDatum )
+    {
+        poDS->osDatumForced = pszDatum;
+        poDS->osDatum = pszDatum;
+    }
     const char *pszProj = CSLFetchNameValue( papszOptions, "PROJ" );
-    if (pszProj)
-        poDS->osProjForced = poDS->osProj = pszProj;
+    if( pszProj )
+    {
+        poDS->osProjForced = pszProj;
+        poDS->osProj = pszProj;
+    }
     const char *pszUnits = CSLFetchNameValue( papszOptions, "UNITS" );
-    if (pszUnits)
-        poDS->osUnitsForced = poDS->osUnits = pszUnits;
+    if( pszUnits )
+    {
+        poDS->osUnitsForced = pszUnits;
+        poDS->osUnits = pszUnits;
+    }
 
     if (pszDatum || pszProj || pszUnits)
     {
diff --git a/frmts/ers/ershdrnode.cpp b/frmts/ers/ershdrnode.cpp
index 09ab448..0135ea6 100644
--- a/frmts/ers/ershdrnode.cpp
+++ b/frmts/ers/ershdrnode.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ershdrnode.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ERMapper .ers Driver
  * Purpose:  Implementation of ERSHdrNode class for parsing/accessing .ers hdr.
@@ -31,8 +30,7 @@
 #include "cpl_string.h"
 #include "ershdrnode.h"
 
-CPL_CVSID("$Id: ershdrnode.cpp 33717 2016-03-14 06:29:14Z goatbar $");
-
+CPL_CVSID("$Id: ershdrnode.cpp 35885 2016-10-24 06:23:09Z goatbar $");
 
 /************************************************************************/
 /*                             ERSHdrNode()                             */
@@ -44,7 +42,7 @@ ERSHdrNode::ERSHdrNode() :
     papszItemName(NULL),
     papszItemValue(NULL),
     papoItemChild(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                            ~ERSHdrNode()                             */
diff --git a/frmts/ers/ershdrnode.h b/frmts/ers/ershdrnode.h
index 8bd31f8..92f10b5 100644
--- a/frmts/ers/ershdrnode.h
+++ b/frmts/ers/ershdrnode.h
@@ -28,5 +28,5 @@ public:
     void   Set( const char *pszPath, const char *pszValue );
 
 private:
-    int    ReadLine( VSILFILE *, CPLString & );
+    static int    ReadLine( VSILFILE *, CPLString & );
 };
diff --git a/frmts/fit/fit.cpp b/frmts/fit/fit.cpp
index c5ef483..770863f 100644
--- a/frmts/fit/fit.cpp
+++ b/frmts/fit/fit.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: fit.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -30,19 +29,19 @@
 #include <limits.h>
 #include "fit.h"
 
-CPL_CVSID("$Id: fit.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: fit.cpp 36776 2016-12-10 11:17:47Z rouault $");
 
 GDALDataType fitDataType(int dtype) {
     switch (dtype) {
     case 1: // iflBit   /* single-bit */
-        fprintf(stderr,
-                "GDAL unsupported data type (single-bit) in fitDataType\n");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "GDAL unsupported data type (single-bit) in fitDataType");
         return GDT_Unknown;
     case 2: // iflUChar    /* unsigned character (byte) */
         return GDT_Byte;
     case 4: // iflChar     /* signed character (byte) */
-        fprintf(stderr,
-                "GDAL unsupported data type (signed char) in fitDataType\n");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "GDAL unsupported data type (signed char) in fitDataType");
         return GDT_Unknown;
 //         return Byte;
     case 8: // iflUShort   /* unsigned short integer (nominally 16 bits) */
@@ -98,7 +97,6 @@ int fitGetDataType(GDALDataType eDataType) {
                      GDALGetColorInterpretationName(colorInterp), nBands); \
             return 0
 
-
 int fitGetColorModel(GDALColorInterp colorInterp, int nBands) {
     // XXX - Should check colorInterp for all bands, not just first one.
 
diff --git a/frmts/fit/fit.h b/frmts/fit/fit.h
index 1675c0c..e0c898b 100644
--- a/frmts/fit/fit.h
+++ b/frmts/fit/fit.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fit.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: fit.h 35885 2016-10-24 06:23:09Z goatbar $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -33,70 +33,69 @@
 #include "gdal.h"
 
 struct FITinfo {
-    unsigned short magic;	// file ident
-    unsigned short version;	// file version
-    unsigned int xSize;		// image size
+    unsigned short magic;       // file ident
+    unsigned short version;     // file version
+    unsigned int xSize;         // image size
     unsigned int ySize;
     unsigned int zSize;
     unsigned int cSize;
-    int dtype;			// data type
-    int order;			// RGBRGB.. or RR..GG..BB..
-    int space;			// coordinate space
-    int cm;			// color model
-    unsigned int xPageSize;	// page size
+    int dtype;                  // data type
+    int order;                  // RGBRGB.. or RR..GG..BB..
+    int space;                  // coordinate space
+    int cm;                     // color model
+    unsigned int xPageSize;     // page size
     unsigned int yPageSize;
     unsigned int zPageSize;
     unsigned int cPageSize;
-				// NOTE: a word of padding is inserted here
-				//       due to struct alignment rules
-    double minValue;		// min/max pixel values
+                                // NOTE: a word of padding is inserted here
+                                //       due to struct alignment rules
+    double minValue;            // min/max pixel values
     double maxValue;
-    unsigned int dataOffset;	// offset to first page of data
+    unsigned int dataOffset;    // offset to first page of data
 
     // non-header values
-    unsigned int userOffset;	// offset to area of user data
+    unsigned int userOffset;    // offset to area of user data
 };
 
-struct FIThead02 {		// file header for version 02
-    unsigned short magic;	// file ident
-    unsigned short version;	// file version
-    unsigned int xSize;		// image size
+struct FIThead02 {              // file header for version 02
+    unsigned short magic;       // file ident
+    unsigned short version;     // file version
+    unsigned int xSize;         // image size
     unsigned int ySize;
     unsigned int zSize;
     unsigned int cSize;
-    int dtype;			// data type
-    int order;			// RGBRGB.. or RR..GG..BB..
-    int space;			// coordinate space
-    int cm;			// color model
-    unsigned int xPageSize;	// page size
+    int dtype;                  // data type
+    int order;                  // RGBRGB.. or RR..GG..BB..
+    int space;                  // coordinate space
+    int cm;                     // color model
+    unsigned int xPageSize;     // page size
     unsigned int yPageSize;
     unsigned int zPageSize;
     unsigned int cPageSize;
-    short _padding;		// NOTE: a word of padding is inserted here
-				//       due to struct alignment rules
-    double minValue;		// min/max pixel values
+    short _padding;             // NOTE: a word of padding is inserted here
+                                //       due to struct alignment rules
+    double minValue;            // min/max pixel values
     double maxValue;
-    unsigned int dataOffset;	// offset to first page of data
+    unsigned int dataOffset;    // offset to first page of data
     // user extensible area...
 };
 
-
-struct FIThead01 {		// file header for version 01
-    unsigned short magic;	// file ident
-    unsigned short version;	// file version
-    unsigned int xSize;		// image size
+struct FIThead01 {              // file header for version 01
+    unsigned short magic;       // file ident
+    unsigned short version;     // file version
+    unsigned int xSize;         // image size
     unsigned int ySize;
     unsigned int zSize;
     unsigned int cSize;
-    int dtype;			// data type
-    int order;			// RGBRGB.. or RR..GG..BB..
-    int space;			// coordinate space
-    int cm;			// color model
-    unsigned int xPageSize;	// page size
+    int dtype;                  // data type
+    int order;                  // RGBRGB.. or RR..GG..BB..
+    int space;                  // coordinate space
+    int cm;                     // color model
+    unsigned int xPageSize;     // page size
     unsigned int yPageSize;
     unsigned int zPageSize;
     unsigned int cPageSize;
-    unsigned int dataOffset;	// offset to first page of data
+    unsigned int dataOffset;   // offset to first page of data
     // user extensible area...
 };
 
diff --git a/frmts/fit/fitdataset.cpp b/frmts/fit/fitdataset.cpp
index 91d9564..9886423 100644
--- a/frmts/fit/fitdataset.cpp
+++ b/frmts/fit/fitdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: fitdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -34,17 +33,17 @@
 #include "gdal_pam.h"
 #include "gstEndian.h"
 
-CPL_CVSID("$Id: fitdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <algorithm>
 
-#define FIT_WRITE
+CPL_CVSID("$Id: fitdataset.cpp 36763 2016-12-09 22:10:55Z rouault $");
 
-#define FIT_PAGE_SIZE 128
+static const size_t FIT_PAGE_SIZE = 128;
 
 using namespace gstEndian;
 
 /************************************************************************/
 /* ==================================================================== */
-/*				FITDataset				*/
+/*                              FITDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -54,8 +53,8 @@ class FITDataset : public GDALPamDataset
 {
     friend class FITRasterBand;
 
-    VSILFILE	*fp;
-    FITinfo	*info;
+    VSILFILE    *fp;
+    FITinfo     *info;
     double      adfGeoTransform[6];
 
   public:
@@ -65,13 +64,11 @@ class FITDataset : public GDALPamDataset
 //     virtual CPLErr GetGeoTransform( double * );
 };
 
-#ifdef FIT_WRITE
 static GDALDataset *FITCreateCopy(const char * pszFilename,
                                   GDALDataset *poSrcDS,
                                   int bStrict, char ** papszOptions,
                                   GDALProgressFunc pfnProgress,
                                   void * pProgressData );
-#endif // FIT_WRITE
 
 /************************************************************************/
 /* ==================================================================== */
@@ -93,33 +90,31 @@ class FITRasterBand : public GDALPamRasterBand
 public:
 
     FITRasterBand( FITDataset *, int nBandIn, int nBandsIn );
-    ~FITRasterBand();
+    virtual ~FITRasterBand();
 
     // should override RasterIO eventually.
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 //     virtual CPLErr WriteBlock( int, int, void * );
-    virtual double GetMinimum( int *pbSuccess );
-    virtual double GetMaximum( int *pbSuccess );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual double GetMinimum( int *pbSuccess ) override;
+    virtual double GetMaximum( int *pbSuccess ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
-
 /************************************************************************/
 /*                           FITRasterBand()                            */
 /************************************************************************/
 
 FITRasterBand::FITRasterBand( FITDataset *poDSIn, int nBandIn, int nBandsIn ) :
-        recordSize(0),
-        numXBlocks(0),
-        numYBlocks(0),
-        bytesPerComponent(0),
-        bytesPerPixel(0),
-        tmpImage( NULL )
-
+    recordSize(0),
+    numXBlocks(0),
+    numYBlocks(0),
+    bytesPerComponent(0),
+    bytesPerPixel(0),
+    tmpImage( NULL )
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
 /* -------------------------------------------------------------------- */
 /*      Get the GDAL data type.                                         */
@@ -133,9 +128,9 @@ FITRasterBand::FITRasterBand( FITDataset *poDSIn, int nBandIn, int nBandsIn ) :
     nBlockYSize = poDSIn->info->yPageSize;
 
 /* -------------------------------------------------------------------- */
-/*      Caculate the values for record offset calculations.             */
+/*      Calculate the values for record offset calculations.             */
 /* -------------------------------------------------------------------- */
-    bytesPerComponent = (GDALGetDataTypeSize(eDataType) / 8);
+    bytesPerComponent = GDALGetDataTypeSizeBytes(eDataType);
     if( bytesPerComponent == 0 )
         return;
     bytesPerPixel = nBandsIn * bytesPerComponent;
@@ -158,13 +153,11 @@ FITRasterBand::FITRasterBand( FITDataset *poDSIn, int nBandIn, int nBandsIn ) :
     /* ... */
 }
 
-
 FITRasterBand::~FITRasterBand()
 {
     VSIFree ( tmpImage );
 }
 
-
 /************************************************************************/
 /*                            IReadBlock()                              */
 /************************************************************************/
@@ -181,7 +174,6 @@ FITRasterBand::~FITRasterBand()
                     } \
     }
 
-
 #define COPY_YFIRST(t) { \
                 t *dstp = (t *) pImage; \
                 t *srcp = (t *) tmpImage; \
@@ -198,7 +190,7 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 
 {
-    FITDataset	*poFIT_DS = (FITDataset *) poDS;
+    FITDataset *poFIT_DS = (FITDataset *) poDS;
 
     uint64 tilenum = 0;
 
@@ -260,18 +252,18 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if ( VSIFSeekL( poFIT_DS->fp, offset, SEEK_SET ) == -1 ) {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "FIT - 64bit file seek failure, handle=%p", poFIT_DS->fp );
-	    return CE_Failure;
+            return CE_Failure;
     }
 
     // XXX - should handle status
     // fast path is single component (ll?) - no copy needed
-    char *p;
     int fastpath = FALSE;
 
     if ((poFIT_DS->nBands == 1) && (poFIT_DS->info->space == 1)) // upper left
         fastpath = TRUE;
 
-    size_t nRead;
+    size_t nRead = 0;
+    char *p = NULL;
     if (! fastpath) {
         nRead = VSIFReadL( tmpImage, recordSize, 1, poFIT_DS->fp );
         // offset to correct component to swap
@@ -287,7 +279,6 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         return CE_Failure;
     }
 
-
 #ifdef swapping
     unsigned long i = 0;
 
@@ -354,7 +345,6 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 yinc = 1;
             } // switch
 
-
             if (xinc == 1) {
                 xstart = 0;
                 xstop = nBlockXSize;
@@ -395,12 +385,12 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                          "FITRasterBand::IReadBlock unsupported "
                          "bytesPerComponent %lu", bytesPerComponent);
             } // switch
-
-        } // scan left/right first
-        else {
-            // scan up/down first
-
-            switch (poFIT_DS->info->space) {
+        } // Scan left/right first.
+        else
+        {
+            // Scan up/down first.
+            switch (poFIT_DS->info->space)
+            {
             case 5:
                 // iflLeftUpperOrigin -* from upper left corner
                 // scan down then right
@@ -473,10 +463,8 @@ CPLErr FITRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                          "FITRasterBand::IReadBlock unsupported "
                          "bytesPerComponent %lu", bytesPerComponent);
             } // switch
-
-        } // scan up/down first
-
-    } // ! fastpath
+        } // Scan up/down first.
+    } // !fastpath
     return CE_None;
 }
 
@@ -489,7 +477,7 @@ CPLErr FITRasterBand::ReadBlock( int nBlockXOff, int nBlockYOff,
                                  void * pImage )
 
 {
-    FITDataset	*poFIT_DS = (FITDataset *) poDS;
+    FITDataset *poFIT_DS = (FITDataset *) poDS;
 
     return CE_None;
 }
@@ -502,7 +490,7 @@ CPLErr FITRasterBand::WriteBlock( int nBlockXOff, int nBlockYOff,
                                  void * pImage )
 
 {
-    FITDataset	*poFIT_DS = (FITDataset *) poDS;
+    FITDataset *poFIT_DS = (FITDataset *) poDS;
 
     return CE_None;
 }
@@ -557,7 +545,7 @@ double FITRasterBand::GetMaximum( int *pbSuccess )
 
 GDALColorInterp FITRasterBand::GetColorInterpretation()
 {
-    FITDataset	*poFIT_DS = (FITDataset *) poDS;
+    FITDataset *poFIT_DS = (FITDataset *) poDS;
 
     if ((! poFIT_DS) || (! poFIT_DS->info))
         return GCI_Undefined;
@@ -777,12 +765,13 @@ GDALColorInterp FITRasterBand::GetColorInterpretation()
 /*                             FITDataset()                             */
 /************************************************************************/
 
-FITDataset::FITDataset() : fp( NULL ), info( NULL )
+FITDataset::FITDataset() :
+    fp( NULL ),
+    info( NULL )
 {
     adfGeoTransform[0] = 0.0; // x origin (top left corner)
     adfGeoTransform[1] = 1.0; // x pixel size
     adfGeoTransform[2] = 0.0;
-
     adfGeoTransform[3] = 0.0; // y origin (top left corner)
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0; // y pixel size
@@ -795,9 +784,9 @@ FITDataset::FITDataset() : fp( NULL ), info( NULL )
 FITDataset::~FITDataset()
 {
     FlushCache();
-    if (info)
+    if( info )
         delete(info);
-    if(fp)
+    if( fp )
     {
         if( VSIFCloseL(fp) != 0 )
         {
@@ -812,22 +801,22 @@ template< class T >
 class DeleteGuard
 {
 public:
-    DeleteGuard( T *p ) : _ptr( p ) { }
+    explicit DeleteGuard( T *p ) : _ptr( p ) { }
     ~DeleteGuard()
     {
-	    delete _ptr;
+        delete _ptr;
     }
 
     T *take()
     {
         T *tmp = _ptr;
-	    _ptr = NULL;
-	    return tmp;
+        _ptr = NULL;
+        return tmp;
     }
 
 private:
     T *_ptr;
-	// prevent default copy constructor and assignment operator
+    // prevent default copy constructor and assignment operator
     DeleteGuard( const DeleteGuard & );
     DeleteGuard &operator=( const DeleteGuard & );
 };
@@ -838,23 +827,23 @@ template< class T >
 class FreeGuard
 {
 public:
-    FreeGuard( T *p ) : _ptr( p ) { }
+    explicit FreeGuard( T *p ) : _ptr( p ) { }
     ~FreeGuard()
     {
-	    if ( _ptr )
-			free( _ptr );
+        if ( _ptr )
+            free( _ptr );
     }
 
     T *take()
     {
         T *tmp = _ptr;
-	    _ptr = NULL;
-	    return tmp;
+        _ptr = NULL;
+        return tmp;
     }
 
 private:
     T *_ptr;
-	// prevent default copy constructor and assignment operator
+    // prevent default copy constructor and assignment operator
     FreeGuard( const FreeGuard & );
     FreeGuard &operator=( const FreeGuard & );
 };
@@ -866,14 +855,13 @@ private:
 GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 {
 /* -------------------------------------------------------------------- */
-/*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/
+/*      First we check to see if the file has the expected header       */
+/*      bytes.                                                          */
 /* -------------------------------------------------------------------- */
 
     if( poOpenInfo->nHeaderBytes < 5 )
         return NULL;
 
-
     if( !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "IT01") &&
         !STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "IT02") )
         return NULL;
@@ -889,24 +877,24 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    FITDataset 	*poDS = new FITDataset();
+    FITDataset *poDS = new FITDataset();
     DeleteGuard<FITDataset> guard( poDS );
 
-	// re-open file for large file (64bit) access
+    // Re-open file for large file (64bit) access.
     if ( poOpenInfo->eAccess == GA_ReadOnly )
-	poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     else
-	poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
+        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
 
-    if ( !poDS->fp ) {
-	    CPLError( CE_Failure, CPLE_OpenFailed,
-		"Failed to re-open %s with FIT driver.\n",
-		poOpenInfo->pszFilename );
-	    return NULL;
+    if ( !poDS->fp )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Failed to re-open %s with FIT driver.\n",
+                  poOpenInfo->pszFilename );
+        return NULL;
     }
     poDS->eAccess = poOpenInfo->eAccess;
 
-
     poDS->info = new FITinfo;
     FITinfo *info = poDS->info;
 
@@ -924,11 +912,11 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLDebug("FIT", "Loading file with header version 02");
 
         gst_swapb(head->minValue);
-	info->minValue = head->minValue;
+        info->minValue = head->minValue;
         gst_swapb(head->maxValue);
-	info->maxValue = head->maxValue;
+        info->maxValue = head->maxValue;
         gst_swapb(head->dataOffset);
-	info->dataOffset = head->dataOffset;
+        info->dataOffset = head->dataOffset;
 
         info->userOffset = sizeof(FIThead02);
     }
@@ -940,9 +928,9 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLDebug("FIT", "Loading file with header version 01");
 
         // map old style header into new header structure
-	FIThead01* head01 = (FIThead01*)head;
+        FIThead01* head01 = (FIThead01*)head;
         gst_swapb(head->dataOffset);
-	info->dataOffset = head01->dataOffset;
+        info->dataOffset = head01->dataOffset;
 
         info->userOffset = sizeof(FIThead01);
     }
@@ -1008,7 +996,7 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check if 64 bit seek is needed.                                 */
 /* -------------------------------------------------------------------- */
     uint64 bytesPerComponent =
-        (GDALGetDataTypeSize(fitDataType(poDS->info->dtype)) / 8);
+        GDALGetDataTypeSize(fitDataType(poDS->info->dtype)) / 8;
     uint64 bytesPerPixel = head->cSize * bytesPerComponent;
     uint64 recordSize = bytesPerPixel * head->xPageSize *
         head->yPageSize;
@@ -1091,7 +1079,6 @@ GDALDataset *FITDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                           FITCreateCopy()                            */
 /************************************************************************/
 
-#ifdef FIT_WRITE
 static GDALDataset *FITCreateCopy(const char * pszFilename,
                                   GDALDataset *poSrcDS,
                                   int bStrict, char ** papszOptions,
@@ -1130,7 +1117,8 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
 /*      Generate header.                                                */
 /* -------------------------------------------------------------------- */
     // XXX - should FIT_PAGE_SIZE be based on file page size ??
-    int size = MAX(sizeof(FIThead02), FIT_PAGE_SIZE);
+
+    const size_t size = std::max(sizeof(FIThead02), FIT_PAGE_SIZE);
     FIThead02 *head = (FIThead02 *) malloc(size);
     FreeGuard<FIThead02> guardHead( head );
 
@@ -1215,7 +1203,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
     // XXX - need to check all bands
     head->maxValue = firstBand->GetMaximum();
     gst_swapb(head->maxValue);
-    head->dataOffset = size;
+    head->dataOffset = static_cast<unsigned int>(size);
     gst_swapb(head->dataOffset);
 
     CPL_IGNORE_RET_VAL(VSIFWriteL(head, size, 1, fpImage));
@@ -1312,7 +1300,6 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
             CPL_IGNORE_RET_VAL(VSIFWriteL(output, pageBytes, 1, fpImage));
 
             double perc = ((double) (y * maxx + x)) / (maxx * maxy);
-//             printf("progress %f\n", perc);
             if( !pfnProgress( perc, NULL, pProgressData ) )
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -1340,7 +1327,6 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
 
     return poDS;
 }
-#endif // FIT_WRITE
 
 /************************************************************************/
 /*                           GetGeoTransform()                          */
@@ -1350,7 +1336,7 @@ static GDALDataset *FITCreateCopy(const char * pszFilename,
 // {
 //     CPLDebug("FIT", "FITDataset::GetGeoTransform");
 //     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
-//     return( CE_None );
+//     return CE_None;
 // }
 
 /************************************************************************/
@@ -1373,12 +1359,10 @@ void GDALRegister_FIT()
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
     poDriver->pfnOpen = FITDataset::Open;
-#ifdef FIT_WRITE
     poDriver->pfnCreateCopy = FITCreateCopy;
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
                                "Byte UInt16 Int16 UInt32 Int32 "
                                "Float32 Float64" );
-#endif // FIT_WRITE
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/fit/gstEndian.h b/frmts/fit/gstEndian.h
index 866666f..fd784ff 100644
--- a/frmts/fit/gstEndian.h
+++ b/frmts/fit/gstEndian.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gstEndian.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: gstEndian.h 35335 2016-09-05 20:18:57Z goatbar $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -54,33 +54,33 @@ static inline void gst_swap64(void * value)
 {
     // 0x1122334455667788 --> 0x8877665544332211
 
-	*(uint64 *)(value) =
-		   ( ((*(uint64 *)(value) & 0x00000000000000ff) << 56) |
-        	 ((*(uint64 *)(value) & 0x000000000000ff00) << 40)  |
-        	 ((*(uint64 *)(value) & 0x0000000000ff0000) << 24)  |
-        	 ((*(uint64 *)(value) & 0x00000000ff000000) << 8)  |
-        	 ((*(uint64 *)(value) >> 8) & 0x00000000ff000000)  |
-        	 ((*(uint64 *)(value) >> 24) & 0x0000000000ff0000)  |
-        	 ((*(uint64 *)(value) >> 40) & 0x000000000000ff00)  |
-        	 ((*(uint64 *)(value) >> 56) & 0x00000000000000ff) );
+    *(uint64 *)(value) =
+        ( ((*(uint64 *)(value) & 0x00000000000000ff) << 56) |
+          ((*(uint64 *)(value) & 0x000000000000ff00) << 40)  |
+          ((*(uint64 *)(value) & 0x0000000000ff0000) << 24)  |
+          ((*(uint64 *)(value) & 0x00000000ff000000) << 8)  |
+          ((*(uint64 *)(value) >> 8) & 0x00000000ff000000)  |
+          ((*(uint64 *)(value) >> 24) & 0x0000000000ff0000)  |
+          ((*(uint64 *)(value) >> 40) & 0x000000000000ff00)  |
+          ((*(uint64 *)(value) >> 56) & 0x00000000000000ff) );
 }
 
 static inline void gst_swap32(void * value)
 {
     // 0x12 34 56 78 --> 0x78 56 34 12
 
-	*(uint32 *)(value) =
-	       ( ((*(uint32 *)(value) & 0x000000ff) << 24) |
-        	 ((*(uint32 *)(value) & 0x0000ff00) << 8)  |
-        	 ((*(uint32 *)(value) >> 8) & 0x0000ff00)  |
-        	 ((*(uint32 *)(value) >> 24) & 0x000000ff) );
+    *(uint32 *)(value) =
+        ( ((*(uint32 *)(value) & 0x000000ff) << 24) |
+          ((*(uint32 *)(value) & 0x0000ff00) << 8)  |
+          ((*(uint32 *)(value) >> 8) & 0x0000ff00)  |
+          ((*(uint32 *)(value) >> 24) & 0x000000ff) );
 }
 
 static inline void gst_swap16(void * value)
 {
     *(uint16 *)(value) =
-		   ( ((*(uint16 *)(value) & 0x00ff) << 8) |
-             ((*(uint16 *)(value) >> 8) & 0x00ff) );
+      ( ((*(uint16 *)(value) & 0x00ff) << 8) |
+        ((*(uint16 *)(value) >> 8) & 0x00ff) );
 }
 
 static inline void gst_swapbytes(void * value, int size)
@@ -110,9 +110,9 @@ static inline void gst_swapbytes(void * value, int size)
 #else // swapping
 
 #define swapped_fread(ptr, size, nitems, stream) \
-	fread(ptr, size, nitems, stream)
+        fread(ptr, size, nitems, stream)
 #define swapped_fwrite(ptr, size, nitems, stream) \
-	fwrite(ptr, size, nitems, stream)
+        fwrite(ptr, size, nitems, stream)
 
 #define gst_swap64( value )
 #define gst_swap32( value )
diff --git a/frmts/fit/gstTypes.h b/frmts/fit/gstTypes.h
index ec1bfb2..4088761 100644
--- a/frmts/fit/gstTypes.h
+++ b/frmts/fit/gstTypes.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gstTypes.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: gstTypes.h 35335 2016-09-05 20:18:57Z goatbar $
  *
  * Project:  FIT Driver
  * Purpose:  Implement FIT Support - not using the SGI iflFIT library.
@@ -35,12 +35,12 @@
 
 typedef int (*gstItemGetFunc)(void *data, int tag, ...);
 
-typedef GUInt16				uint16;
-typedef GInt16				int16;
-typedef GUInt32				uint32;
-typedef GInt32				int32;
-typedef GUIntBig			uint64;
-typedef GIntBig				int64;
+typedef GUInt16                         uint16;
+typedef GInt16                          int16;
+typedef GUInt32                         uint32;
+typedef GInt32                          int32;
+typedef GUIntBig                        uint64;
+typedef GIntBig                         int64;
 
 typedef unsigned char                   uchar;
 
diff --git a/frmts/fits/GNUmakefile b/frmts/fits/GNUmakefile
index d14fce7..58588ae 100644
--- a/frmts/fits/GNUmakefile
+++ b/frmts/fits/GNUmakefile
@@ -3,7 +3,7 @@ include ../../GDALmake.opt
 
 OBJ	=	fitsdataset.o
 
-FITS_OPTS	=	
+FITS_OPTS	=
 
 CPPFLAGS	:=	 $(FITS_OPTS) $(CPPFLAGS)
 
diff --git a/frmts/fits/fitsdataset.cpp b/frmts/fits/fitsdataset.cpp
index 35857b1..8e6db7e 100644
--- a/frmts/fits/fitsdataset.cpp
+++ b/frmts/fits/fitsdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: fitsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  FITS Driver
  * Purpose:  Implement FITS raster read/write support
@@ -28,19 +27,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
-
 #include "cpl_string.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include <string.h>
 #include <fitsio.h>
 
-CPL_CVSID("$Id: fitsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: fitsdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*				FITSDataset				*/
+/*                              FITSDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -65,12 +62,11 @@ class FITSDataset : public GDALPamDataset {
 public:
   ~FITSDataset();
 
-  static GDALDataset* Open(GDALOpenInfo* );
-  static GDALDataset* Create(const char* pszFilename,
-			     int nXSize, int nYSize, int nBands,
-			     GDALDataType eType,
-			     char** papszParmList);
-
+  static GDALDataset* Open( GDALOpenInfo* );
+  static GDALDataset* Create( const char* pszFilename,
+                              int nXSize, int nYSize, int nBands,
+                              GDALDataType eType,
+                              char** papszParmList );
 };
 
 /************************************************************************/
@@ -81,28 +77,27 @@ public:
 
 class FITSRasterBand : public GDALPamRasterBand {
 
-  friend class	FITSDataset;
+  friend class  FITSDataset;
 
 public:
 
   FITSRasterBand(FITSDataset*, int);
-  ~FITSRasterBand();
+  virtual ~FITSRasterBand();
 
-  virtual CPLErr IReadBlock( int, int, void * );
-  virtual CPLErr IWriteBlock( int, int, void * );
+  virtual CPLErr IReadBlock( int, int, void * ) override;
+  virtual CPLErr IWriteBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                          FITSRasterBand()                           */
 /************************************************************************/
 
-FITSRasterBand::FITSRasterBand(FITSDataset *poDSIn, int nBandIn) {
-
-  this->poDS = poDSIn;
-  this->nBand = nBandIn;
+FITSRasterBand::FITSRasterBand( FITSDataset *poDSIn, int nBandIn )
+{
+  poDS = poDSIn;
+  nBand = nBandIn;
   eDataType = poDSIn->gdalDataType;
-  nBlockXSize = poDSIn->nRasterXSize;;
+  nBlockXSize = poDSIn->nRasterXSize;
   nBlockYSize = 1;
 }
 
@@ -110,7 +105,8 @@ FITSRasterBand::FITSRasterBand(FITSDataset *poDSIn, int nBandIn) {
 /*                          ~FITSRasterBand()                           */
 /************************************************************************/
 
-FITSRasterBand::~FITSRasterBand() {
+FITSRasterBand::~FITSRasterBand()
+{
     FlushCache();
 }
 
@@ -141,16 +137,16 @@ CPLErr FITSRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
   // to read causes an error, so in this case, just return zeros.
   if (!dataset->isExistingFile && offset > dataset->highestOffsetWritten) {
     memset(pImage, 0, nBlockXSize * nBlockYSize
-	   * GDALGetDataTypeSize(eDataType) / 8);
+           * GDALGetDataTypeSize(eDataType) / 8);
     return CE_None;
   }
 
   // Otherwise read in the image data
   fits_read_img(hFITS, dataset->fitsDataType, offset, nElements,
-		NULL, pImage, NULL, &status);
+                NULL, pImage, NULL, &status);
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Couldn't read image data from FITS file (%d).", status);
+             "Couldn't read image data from FITS file (%d).", status);
     return CE_Failure;
   }
 
@@ -162,8 +158,9 @@ CPLErr FITSRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
 /*                                                                      */
 /************************************************************************/
 
-CPLErr FITSRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
-				   void* pImage) {
+CPLErr FITSRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
+                                    void* pImage )
+{
   FITSDataset* dataset = (FITSDataset*) poDS;
   fitsfile* hFITS = dataset->hFITS;
   int status = 0;
@@ -178,7 +175,7 @@ CPLErr FITSRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
     nBlockYOff * nRasterXSize + 1;
   long nElements = nRasterXSize;
   fits_write_img(hFITS, dataset->fitsDataType, offset, nElements,
-		 pImage, &status);
+                 pImage, &status);
 
   // Capture special case of non-zero status due to data range
   // overflow Standard GDAL policy is to silently truncate, which is
@@ -190,7 +187,7 @@ CPLErr FITSRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
   // Check for other errors
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Error writing image data to FITS file (%d).", status);
+             "Error writing image data to FITS file (%d).", status);
     return CE_Failure;
   }
 
@@ -225,14 +222,13 @@ static bool isIgnorableFITSHeader(const char* name) {
   return false;
 }
 
-
 /************************************************************************/
 /*                            FITSDataset()                            */
 /************************************************************************/
 
-FITSDataset::FITSDataset() {
-  hFITS = NULL;
-}
+FITSDataset::FITSDataset():
+    hFITS(NULL)
+{}
 
 /************************************************************************/
 /*                           ~FITSDataset()                            */
@@ -241,57 +237,63 @@ FITSDataset::FITSDataset() {
 FITSDataset::~FITSDataset() {
 
   int status;
-  if (hFITS) {
-    if(eAccess == GA_Update) {   // Only do this if we've successfully opened the file and  update capability
-      // Write any meta data to the file that's compatible with FITS
+  if( hFITS )
+  {
+    if(eAccess == GA_Update)
+    {
+      // Only do this if we've successfully opened the file and update
+      // capability.  Write any meta data to the file that's compatible with
+      // FITS.
       status = 0;
       fits_movabs_hdu(hFITS, 1, NULL, &status);
       fits_write_key_longwarn(hFITS, &status);
       if (status) {
         CPLError(CE_Warning, CPLE_AppDefined,
-	         "Couldn't move to first HDU in FITS file %s (%d).\n",
-	         GetDescription(), status);
+                 "Couldn't move to first HDU in FITS file %s (%d).\n",
+                 GetDescription(), status);
       }
       char** metaData = GetMetadata();
       int count = CSLCount(metaData);
       for (int i = 0; i < count; ++i) {
         const char* field = CSLGetField(metaData, i);
         if (strlen(field) == 0)
-	  continue;
+            continue;
         else {
-	  char* key = NULL;
-	  const char* value = CPLParseNameValue(field, &key);
-	  // FITS keys must be less than 8 chars
-	  if (key != NULL && strlen(key) <= 8 && !isIgnorableFITSHeader(key)) {
-	    // Although FITS provides support for different value
-	    // types, the GDAL Metadata mechanism works only with
-	    // string values. Prior to about 2003-05-02, this driver
-	    // would attempt to guess the value type from the metadata
-	    // value string amd then would use the appropriate
-	    // type-specific FITS keyword update routine. This was
-	    // found to be troublesome (e.g. a numeric version string
-	    // with leading zeros would be interpreted as a number
-	    // and might get those leading zeros stripped), and so now
-	    // the driver writes every value as a string. In practice
-	    // this is not a problem since most FITS reading routines
-	    // will convert from strings to numbers automatically, but
-	    // if you want finer control, use the underlying FITS
-	    // handle. Note: to avoid a compiler warning we copy the
-	    // const value string to a non const one...
-            char* valueCpy = CPLStrdup(value);
-	    fits_update_key_longstr(hFITS, key, valueCpy, NULL, &status);
-	    CPLFree(valueCpy);
-
-	    // Check for errors
-	    if (status) {
-	      CPLError(CE_Warning, CPLE_AppDefined,
-		       "Couldn't update key %s in FITS file %s (%d).",
-		       key, GetDescription(), status);
-	      return;
-	    }
-	  }
-	  // Must free up key
-	  CPLFree(key);
+            char* key = NULL;
+            const char* value = CPLParseNameValue(field, &key);
+            // FITS keys must be less than 8 chars
+            if (key != NULL && strlen(key) <= 8 && !isIgnorableFITSHeader(key))
+            {
+                // Although FITS provides support for different value
+                // types, the GDAL Metadata mechanism works only with
+                // string values. Prior to about 2003-05-02, this driver
+                // would attempt to guess the value type from the metadata
+                // value string amd then would use the appropriate
+                // type-specific FITS keyword update routine. This was
+                // found to be troublesome (e.g. a numeric version string
+                // with leading zeros would be interpreted as a number
+                // and might get those leading zeros stripped), and so now
+                // the driver writes every value as a string. In practice
+                // this is not a problem since most FITS reading routines
+                // will convert from strings to numbers automatically, but
+                // if you want finer control, use the underlying FITS
+                // handle. Note: to avoid a compiler warning we copy the
+                // const value string to a non const one.
+                char* valueCpy = CPLStrdup(value);
+                fits_update_key_longstr(hFITS, key, valueCpy, NULL, &status);
+                CPLFree(valueCpy);
+
+                // Check for errors.
+                if (status)
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Couldn't update key %s in FITS file %s (%d).",
+                             key, GetDescription(), status);
+                    return;
+                }
+            }
+            // Must free up key
+            CPLFree(key);
         }
       }
 
@@ -302,11 +304,9 @@ FITSDataset::~FITSDataset() {
     // Close the FITS handle - ignore the error status
     status = 0;
     fits_close_file(hFITS, &status);
-
   }
 }
 
-
 /************************************************************************/
 /*                           Init()                                     */
 /************************************************************************/
@@ -322,8 +322,8 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   fits_movabs_hdu(hFITS, 1, NULL, &status);
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Couldn't move to first HDU in FITS file %s (%d).\n",
-	     GetDescription(), status);
+             "Couldn't move to first HDU in FITS file %s (%d).\n",
+             GetDescription(), status);
     return CE_Failure;
   }
 
@@ -342,8 +342,8 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   fits_get_img_param(hFITS, maxdim, &bitpix, &naxis, naxes, &status);
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Couldn't determine image parameters of FITS file %s (%d).",
-	     GetDescription(), status);
+             "Couldn't determine image parameters of FITS file %s (%d).",
+             GetDescription(), status);
     return CE_Failure;
   }
 
@@ -370,8 +370,8 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   }
   else {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "FITS file %s has unknown data type: %d.", GetDescription(),
-	     bitpix);
+             "FITS file %s has unknown data type: %d.", GetDescription(),
+             bitpix);
     return CE_Failure;
   }
 
@@ -388,8 +388,8 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   }
   else {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "FITS file %s does not have 2 or 3 dimensions.",
-	     GetDescription());
+             "FITS file %s does not have 2 or 3 dimensions.",
+             GetDescription());
     return CE_Failure;
   }
 
@@ -405,15 +405,16 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   char key[100];
   char value[100];
 
-  int nKeys = 0, nMoreKeys = 0;
+  int nKeys = 0;
+  int nMoreKeys = 0;
   fits_get_hdrspace(hFITS, &nKeys, &nMoreKeys, &status);
   for(keyNum = 1; keyNum <= nKeys; keyNum++)
   {
     fits_read_keyn(hFITS, keyNum, key, value, NULL, &status);
     if (status) {
       CPLError(CE_Failure, CPLE_AppDefined,
-	       "Error while reading key %d from FITS file %s (%d)",
-	       keyNum, GetDescription(), status);
+               "Error while reading key %d from FITS file %s (%d)",
+               keyNum, GetDescription(), status);
       return CE_Failure;
     }
     if (strcmp(key, "END") == 0) {
@@ -427,27 +428,31 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
     else {   // Going to store something, but check for long strings etc
       // Strip off leading and trailing quote if present
       char* newValue = value;
-      if (value[0] == '\'' && value[strlen(value) - 1] == '\'') {
-	newValue = value + 1;
-	value[strlen(value) - 1] = '\0';
+      if (value[0] == '\'' && value[strlen(value) - 1] == '\'')
+      {
+          newValue = value + 1;
+          value[strlen(value) - 1] = '\0';
       }
       // Check for long string
-      if (strrchr(newValue, '&') == newValue + strlen(newValue) - 1) {
-	// Value string ends in "&", so use long string conventions
-	char* longString = NULL;
-	fits_read_key_longstr(hFITS, key, &longString, NULL, &status);
-        // Note that read_key_longstr already strips quotes
-	if (status) {
-	  CPLError(CE_Failure, CPLE_AppDefined,
-		   "Error while reading long string for key %s from "
-		   "FITS file %s (%d)", key, GetDescription(), status);
-	  return CE_Failure;
-	}
-	SetMetadataItem(key, longString);
-	free(longString);
+      if (strrchr(newValue, '&') == newValue + strlen(newValue) - 1)
+      {
+          // Value string ends in "&", so use long string conventions
+          char* longString = NULL;
+          fits_read_key_longstr(hFITS, key, &longString, NULL, &status);
+          // Note that read_key_longstr already strips quotes
+          if( status )
+          {
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Error while reading long string for key %s from "
+                       "FITS file %s (%d)", key, GetDescription(), status);
+              return CE_Failure;
+          }
+          SetMetadataItem(key, longString);
+          free(longString);
       }
-      else {  // Normal keyword
-	SetMetadataItem(key, newValue);
+      else
+      {  // Normal keyword
+          SetMetadataItem(key, newValue);
       }
     }
   }
@@ -455,8 +460,6 @@ CPLErr FITSDataset::Init(fitsfile* hFITS_, bool isExistingFile_) {
   return CE_None;
 }
 
-
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -480,8 +483,8 @@ GDALDataset* FITSDataset::Open(GDALOpenInfo* poOpenInfo) {
     fits_open_file(&hFITS, poOpenInfo->pszFilename, READWRITE, &status);
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Error while opening FITS file %s (%d).\n",
-	     poOpenInfo->pszFilename, status);
+             "Error while opening FITS file %s (%d).\n",
+             poOpenInfo->pszFilename, status);
     fits_close_file(hFITS, &status);
     return NULL;
   }
@@ -513,19 +516,17 @@ GDALDataset* FITSDataset::Open(GDALOpenInfo* poOpenInfo) {
   }
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /*                                                                      */
 /*      Create a new FITS file.                                         */
 /************************************************************************/
 
-GDALDataset *FITSDataset::Create(const char* pszFilename,
-				 int nXSize, int nYSize,
-				 int nBands, GDALDataType eType,
-				 CPL_UNUSED char** papszParmList) {
-  FITSDataset* dataset;
-  fitsfile* hFITS;
+GDALDataset *FITSDataset::Create( const char* pszFilename,
+                                  int nXSize, int nYSize,
+                                  int nBands, GDALDataType eType,
+                                  CPL_UNUSED char** papszParmList )
+{
   int status = 0;
 
   // No creation options are defined. The BSCALE/BZERO options were
@@ -536,11 +537,12 @@ GDALDataset *FITSDataset::Create(const char* pszFilename,
   // Create the file - to force creation, we prepend the name with '!'
   char* extFilename = new char[strlen(pszFilename) + 10];  // 10 for margin!
   snprintf(extFilename, strlen(pszFilename) + 10, "!%s", pszFilename);
+  fitsfile* hFITS = NULL;
   fits_create_file(&hFITS, extFilename, &status);
   delete[] extFilename;
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Couldn't create FITS file %s (%d).\n", pszFilename, status);
+             "Couldn't create FITS file %s (%d).\n", pszFilename, status);
     return NULL;
   }
 
@@ -558,7 +560,7 @@ GDALDataset *FITSDataset::Create(const char* pszFilename,
     bitpix = DOUBLE_IMG;
   else {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "GDALDataType (%d) unsupported for FITS", eType);
+             "GDALDataType (%d) unsupported for FITS", eType);
     fits_close_file(hFITS, &status);
     return NULL;
   }
@@ -571,13 +573,13 @@ GDALDataset *FITSDataset::Create(const char* pszFilename,
   // Check the status
   if (status) {
     CPLError(CE_Failure, CPLE_AppDefined,
-	     "Couldn't create image within FITS file %s (%d).",
-	     pszFilename, status);
+             "Couldn't create image within FITS file %s (%d).",
+             pszFilename, status);
     fits_close_file(hFITS, &status);
     return NULL;
   }
 
-  dataset = new FITSDataset();
+  FITSDataset* dataset = new FITSDataset();
   dataset->nRasterXSize = nXSize;
   dataset->nRasterYSize = nYSize;
   dataset->eAccess = GA_Update;
@@ -593,7 +595,6 @@ GDALDataset *FITSDataset::Create(const char* pszFilename,
   }
 }
 
-
 /************************************************************************/
 /*                          GDALRegister_FITS()                         */
 /************************************************************************/
diff --git a/frmts/formats_list.html b/frmts/formats_list.html
index cff415c..ff8ba75 100644
--- a/frmts/formats_list.html
+++ b/frmts/formats_list.html
@@ -115,6 +115,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_various.html#CAD">AutoCAD DWG Raster layer</a>
+</td><td> CAD
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> Yes (internal libopencad provided)
+</td></tr>
+
 <tr><td> <a href="frmt_cals.html">CALS Type I</a>
 </td><td> CALS
 </td><td> Yes
@@ -179,6 +187,14 @@
 </td><td> No, needs Crunch Lib
 </td></tr>
 
+<tr><td> <a href="frmt_derived.html">Derived</a>
+</td><td> DERIVED
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_various.html#DIMAP">Spot DIMAP (metadata.dim)</a>
 </td><td> DIMAP
 </td><td> No
@@ -359,7 +375,7 @@
 </td><td> GEORASTER
 </td><td> Yes
 </td><td> Yes
-</td><td> --
+</td><td> No limits
 </td><td> No, needs Oracle client libraries
 </td></tr>
 
@@ -539,7 +555,7 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> <a href="frmt_isce.html">ISCE raster</a>
+<tr><td> <a href="frmt_various.html#ISCE">ISCE raster</a>
 </td><td> ISCE
 </td><td> Yes
 </td><td> No
@@ -619,6 +635,14 @@
 </td><td> No, needs Kakadu library
 </td></tr>
 
+<tr><td> <a href="frmt_jp2lura.html">JPEG2000 (.jp2, .j2k)</a>
+</td><td> JP2Lura
+</td><td> Yes
+</td><td> Yes
+</td><td>
+</td><td> No, needs Lurawave library
+</td></tr>
+
 <tr><td> <a href="frmt_jp2mrsid.html">JPEG2000 (.jp2, .j2k)</a>
 </td><td> JP2MrSID
 </td><td> Yes
@@ -827,7 +851,7 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> Northwood/VerticalMapper Classified Grid Format .grc/.tab
+<tr><td> <a href="frmt_nwtgrd.html">Northwood/VerticalMapper Classified Grid Format .grc/.tab</a>
 </td><td> NWT_GRC
 </td><td> No
 </td><td> Yes
@@ -835,7 +859,7 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> Northwood/VerticalMapper Numeric Grid Format .grd/.tab
+<tr><td> <a href="frmt_nwtgrd.html">Northwood/VerticalMapper Numeric Grid Format .grd/.tab</a>
 </td><td> NWT_GRD
 </td><td> No
 </td><td> Yes
@@ -931,6 +955,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_prf.html">PHOTOMOD raster file (.prf,.x-dem)</a>
+</td><td> PRF
+</td><td> No
+</td><td> Yes
+</td><td> No limits
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_r.html">R Object Data Store</a>
 </td><td> R
 </td><td> Yes
@@ -955,6 +987,14 @@
 </td><td> No (needs OGR SQLite driver)
 </td></tr>
 
+<tr><td> <a href="frmt_rasterlite2.html">Rasterlite2 - Rasters in SQLite DB</a>
+</td><td> SQLite
+</td><td> No
+</td><td> Yes
+</td><td> --
+</td><td> No (needs libsqlite3, librasterlite2, libspatialite)
+</td></tr>
+
 <tr><td> <a href="frmt_rik.html">Swedish Grid RIK (.rik)</a>
 </td><td> RIK
 </td><td> No
@@ -995,6 +1035,14 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="frmt_various.html#RRASTER">R Raster (.grd)</a>
+</td><td> RRASTER
+</td><td> No
+</td><td> Yes
+</td><td> -
+</td><td> Yes
+</td></tr>
+
 <tr><td> <a href="frmt_Idrisi.html">Idrisi Raster</a>
 </td><td> RST
 </td><td> Yes
@@ -1203,7 +1251,7 @@
 </p>
 
 <p>
-$Id: formats_list.html 33822 2016-03-31 12:35:35Z rouault $
+$Id: formats_list.html 37018 2016-12-28 11:36:44Z rouault $
 </p>
 
 </body>
diff --git a/frmts/frmt_various.html b/frmts/frmt_various.html
index 4b84816..e6ca2f0 100644
--- a/frmts/frmt_various.html
+++ b/frmts/frmt_various.html
@@ -327,7 +327,7 @@ USGS DOQ Standards</a></p>
 
 <h2><a name="EHdr">EHdr -- ESRI .hdr Labelled</a></h2>
 
-<p>GDAL supports reading and writing the ESRI .hdr labelling format,
+<p>GDAL supports reading and writing the ESRI .hdr labeling format,
 often referred to as ESRI BIL format.  Eight, sixteen
 and thirty-two bit integer raster data types are supported as well as 32
 bit floating point.  Coordinate systems (from a .prj file), and georeferencing
@@ -821,7 +821,7 @@ GMT.</p>
 
 <p>NOTE: Implemented as <tt>gdal/frmts/netcdf/gmtdataset.cpp</tt>.</p>
 
-<p>See Also: <a href="http://www.unidata.ucar.edu/packages/netcdf/">Unidata NetCDF Page</a></p>
+<p>See Also: <a href="http://www.unidata.ucar.edu/software/netcdf/">Unidata NetCDF Page</a></p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
@@ -1117,6 +1117,26 @@ as the list of the NITF tiles of the subdataset.</p>
 
 <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
+<h2><a name="RRASTER">RRASTER -- R Raster</a></h2>
+
+<p>(GDAL >= 2.2)</p>
+
+<p>
+This is a read-only reader for the datasets handled by the
+<a href="https://cran.r-project.org/web/packages/raster/index.html">R Raster package</a>.
+Those datasets are made of a .grd file, which is a text header file, and a .gri
+binary file containing the raster data itself. The .grd is the file opened by
+GDAL.
+</p>
+
+<p>See Also:</p>
+
+<ul>
+<li>Description of the <a href="https://cran.r-project.org/web/packages/raster/vignettes/rasterfile.pdf">"rasterfile" format</a></li>
+</ul>
+
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
 <h2><a name="SAR_CEOS">SAR_CEOS -- CEOS SAR Image</a></h2>
 
 <p>This is a read-only reader for CEOS SAR image files.  To use, select
@@ -1280,7 +1300,14 @@ GDAL will report the images it is composed of as subdatasets. If the THF referen
 
 <h2><a name="SRTMHGT">SRTMHGT - SRTM HGT Format</a></h2>
 
-<p>The SRTM HGT driver currently supports the reading of SRTM-3 and SRTM-1 V2 (HGT) files.</p>
+<p>The SRTM HGT driver currently supports the reading of SRTM-3 and SRTM-1 V2 (HGT) files.
+The files must be named like NXXEYYY.hgt, or starting with GDAL 2.1.2,
+NXXEYYY[.something].hgt</p>
+
+<p>Starting with GDAL 2.2, the driver can directly read .hgt.zip files provided
+that they are named like NXXEYYY[.something].hgt.zip and contain a NXXEYYY.hgt
+file. For previous versions, use /vsizip//path/to/NXXEYYY[.something].hgt.zip/NXXEYYY.hgt
+syntax</p>
 
 <p>The driver does support creating new files, but the input data
 must be exactly formatted as a SRTM-3 or SRTM-1 cell.  That is the size,
@@ -1385,13 +1412,30 @@ left of the values that appear in the file).</p>
 
 <p>NOTE: Implemented as <tt>gdal/frmts/zmap/zmapdataset.cpp</tt>.</p>
 
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+<h2><a name="CAD">CAD -- AutoCAD DWG raster layer</a></h2>
+
+<p>(GDAL >= 2.2.0)</p>
+
+<p>
+OGR DWG support is based on libopencad, so the list of supported DWG (DXF)
+versions can be seen in libopencad documentation. All drawing entities are
+separated into layers as they are in DWG file. The rasters are usually a separate
+georeferenced files (GeoTiff, Jpeg, Png etc.) which exist in DWG file as separate
+layers. The driver try to get spatial reference and other methadata from DWG
+Image description and set it to GDALDataset.
+</p>
+
+<p>NOTE: Implemented as <tt>ogr/ogrsf_frmts/cad/gdalcaddataset.cpp</tt>.</p>
+
 <hr>
 <p>
 <a href="formats_list.html">Full list of GDAL Raster Formats</a>
 </p>
 
 <p>
-$Id: frmt_various.html 33795 2016-03-27 03:34:36Z goatbar $
+$Id: frmt_various.html 37097 2017-01-11 03:40:22Z warmerdam $
 </p>
 
 </body>
diff --git a/frmts/gdalallregister.cpp b/frmts/gdalallregister.cpp
index 848a53d..dd33673 100644
--- a/frmts/gdalallregister.cpp
+++ b/frmts/gdalallregister.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalallregister.cpp 33546 2016-02-24 21:02:52Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALAllRegister(), primary format registration.
@@ -36,7 +35,7 @@
    #include "gnm_frmts.h"
 #endif
 
-CPL_CVSID("$Id: gdalallregister.cpp 33546 2016-02-24 21:02:52Z goatbar $");
+CPL_CVSID("$Id: gdalallregister.cpp 36731 2016-12-07 11:08:07Z rouault $");
 
 #ifdef notdef
 // we may have a use for this some day
@@ -68,6 +67,7 @@ void CPL_STDCALL GDALAllRegister()
 
 #ifdef FRMT_vrt
     GDALRegister_VRT();
+    GDALRegister_Derived();
 #endif
 
 #ifdef FRMT_gtiff
@@ -249,22 +249,27 @@ void CPL_STDCALL GDALAllRegister()
 #endif
 
 #ifdef FRMT_jp2kak
-// JPEG2000 support using Kakadu toolkit
+    // JPEG2000 support using Kakadu toolkit
     GDALRegister_JP2KAK();
 #endif
 
 #ifdef FRMT_jpipkak
-// JPEG2000 support using Kakadu toolkit
+    // JPEG2000 support using Kakadu toolkit
     GDALRegister_JPIPKAK();
 #endif
 
+#ifdef FRMT_jp2lura
+    // JPEG2000 support using Lurawave library
+    GDALRegister_JP2Lura();
+#endif
+
 #ifdef FRMT_ecw
     GDALRegister_ECW();
     GDALRegister_JP2ECW();
 #endif
 
 #ifdef FRMT_openjpeg
-// JPEG2000 support using OpenJPEG library
+    // JPEG2000 support using OpenJPEG library
     GDALRegister_JP2OpenJPEG();
 #endif
 
@@ -285,9 +290,9 @@ void CPL_STDCALL GDALAllRegister()
 #endif
 
 #ifdef FRMT_jpeg2000
-// JPEG2000 support using JasPer toolkit
-// This one should always be placed after other JasPer supported formats,
-// such as BMP or PNM. In other case we will get bad side effects.
+    // JPEG2000 support using JasPer toolkit
+    // This one should always be placed after other JasPer supported formats,
+    // such as BMP or PNM. In other case we will get bad side effects.
     GDALRegister_JPEG2000();
 #endif
 
@@ -431,6 +436,7 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_SNODAS();
     GDALRegister_KRO();
     GDALRegister_ROIPAC();
+    GDALRegister_RRASTER();
 
     // Those ones need to look for side car files so put them at end
     GDALRegister_ENVI();
@@ -544,6 +550,10 @@ void CPL_STDCALL GDALAllRegister()
     GDALRegister_IRIS();
 #endif
 
+#ifdef FRMT_prf
+    GDALRegister_PRF();
+#endif
+
 #ifdef GNM_ENABLED
     GNMRegisterAllInternal();
 #endif
diff --git a/frmts/georaster/frmt_georaster.html b/frmts/georaster/frmt_georaster.html
index f227a9a..3dc9327 100644
--- a/frmts/georaster/frmt_georaster.html
+++ b/frmts/georaster/frmt_georaster.html
@@ -18,7 +18,7 @@ optionally built as a GDAL plugin, but it requires Oracle client
 libraries.
 </p>
 <p>
-When opening a GeoRaster, it's name should be specified in the form:
+When opening a GeoRaster, its name should be specified in the form:
 </p>
 <p style="font-family: Courier New,Courier,monospace; margin-left: 40px;">
 georaster:<user>{,/}<pwd>{,@}[db],[schema.][table],[column],[where]<br>
diff --git a/frmts/georaster/georaster_dataset.cpp b/frmts/georaster/georaster_dataset.cpp
index bec6437..884ee31 100644
--- a/frmts/georaster/georaster_dataset.cpp
+++ b/frmts/georaster/georaster_dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: $
  *
  * Name:     georaster_dataset.cpp
  * Project:  Oracle Spatial GeoRaster Driver
@@ -38,6 +37,8 @@
 
 #include "georaster_priv.h"
 
+CPL_CVSID("$Id: georaster_dataset.cpp 36763 2016-12-09 22:10:55Z rouault $");
+
 //  ---------------------------------------------------------------------------
 //                                                           GeoRasterDataset()
 //  ---------------------------------------------------------------------------
@@ -148,10 +149,7 @@ GDALDataset* GeoRasterDataset::Open( GDALOpenInfo* poOpenInfo )
     //  Create a corresponding GDALDataset
     //  -------------------------------------------------------------------
 
-    GeoRasterDataset *poGRD;
-
-    poGRD = new GeoRasterDataset();
-
+    GeoRasterDataset *poGRD = new GeoRasterDataset();
     if( ! poGRD )
     {
         return NULL;
@@ -688,19 +686,19 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         }
     }
 
-    poGRD->poGeoRaster->bCreateObjectTable = CPL_TO_BOOL(
-        CSLFetchBoolean( papszOptions, "OBJECTTABLE", FALSE ));
+    poGRD->poGeoRaster->bCreateObjectTable =
+        CPLFetchBool( papszOptions, "OBJECTTABLE", false );
 
     //  -------------------------------------------------------------------
     //  Create a SDO_GEORASTER object on the server
     //  -------------------------------------------------------------------
 
-    bool bSucced = poGRW->Create( pszDescription, pszInsert, poGRW->bUniqueFound );
+    const bool bSuccess = poGRW->Create( pszDescription, pszInsert, poGRW->bUniqueFound );
 
     CPLFree( pszInsert );
     CPLFree( pszDescription );
 
-    if( ! bSucced )
+    if( ! bSuccess )
     {
         delete poGRD;
         return NULL;
@@ -747,8 +745,8 @@ GDALDataset *GeoRasterDataset::Create( const char *pszFilename,
         poGRD->poGeoRaster->SetGeoReference( atoi( pszFetched ) );
     }
 
-    poGRD->poGeoRaster->bGenSpatialIndex = CPL_TO_BOOL(
-        CSLFetchBoolean( papszOptions, "SPATIALEXTENT", TRUE ));
+    poGRD->poGeoRaster->bGenSpatialIndex =
+        CPLFetchBool( papszOptions, "SPATIALEXTENT", TRUE );
 
     pszFetched = CSLFetchNameValue( papszOptions, "EXTENTSRID" );
 
@@ -842,13 +840,13 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
     //  Create a GeoRaster on the server or select one to overwrite
     //  -----------------------------------------------------------
 
-    GeoRasterDataset *poDstDS;
-
-    poDstDS = (GeoRasterDataset *) GeoRasterDataset::Create( pszFilename,
-        poSrcDS->GetRasterXSize(),
-        poSrcDS->GetRasterYSize(),
-        poSrcDS->GetRasterCount(),
-        eType, papszOptions );
+    GeoRasterDataset *poDstDS =
+        (GeoRasterDataset *) GeoRasterDataset::Create(
+            pszFilename,
+            poSrcDS->GetRasterXSize(),
+            poSrcDS->GetRasterYSize(),
+            poSrcDS->GetRasterCount(),
+            eType, papszOptions );
 
     if( poDstDS == NULL )
     {
@@ -897,8 +895,12 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
 
     int    bHasNoDataValue = FALSE;
     double dfNoDataValue = 0.0;
-    double dfMin = 0.0, dfMax = 0.0, dfStdDev = 0.0, dfMean = 0.0;
-    double dfMedian = 0.0, dfMode = 0.0;
+    double dfMin = 0.0;
+    double dfMax = 0.0;
+    double dfStdDev = 0.0;
+    double dfMean = 0.0;
+    double dfMedian = 0.0;
+    double dfMode = 0.0;
     int    iBand = 0;
 
     for( iBand = 1; iBand <= poSrcDS->GetRasterCount(); iBand++ )
@@ -1130,7 +1132,6 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
                         return NULL;
                     }
                 }
-
             }
 
             if( ( eErr == CE_None ) && ( ! pfnProgress(
@@ -1154,7 +1155,7 @@ GDALDataset *GeoRasterDataset::CreateCopy( const char* pszFilename,
 
     if( pfnProgress )
     {
-        printf( "Output dataset: (georaster:%s/%s@%s,%s,%d) on %s%s,%s\n",
+        CPLDebug("GEOR", "Output dataset: (georaster:%s/%s@%s,%s,%d) on %s%s,%s",
             poDstDS->poGeoRaster->poConnection->GetUser(),
             poDstDS->poGeoRaster->poConnection->GetPassword(),
             poDstDS->poGeoRaster->poConnection->GetServer(),
@@ -1453,7 +1454,8 @@ CPLErr GeoRasterDataset::SetProjection( const char *pszProjString )
     // Try to extract EPGS authority code
     // --------------------------------------------------------------------
 
-    const char *pszAuthName = NULL, *pszAuthCode = NULL;
+    const char *pszAuthName = NULL;
+    const char *pszAuthCode = NULL;
 
     if( oSRS.IsGeographic() )
     {
diff --git a/frmts/georaster/georaster_priv.h b/frmts/georaster/georaster_priv.h
index 5fc4a03..5dfca52 100644
--- a/frmts/georaster/georaster_priv.h
+++ b/frmts/georaster/georaster_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: georaster_priv.h 34879 2016-08-03 14:05:32Z ilucena $
+ * $Id: georaster_priv.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Name:     georaster_priv.h
  * Project:  Oracle Spatial GeoRaster Driver
@@ -165,13 +165,13 @@ public:
                             char** papszOptions,
                             GDALProgressFunc pfnProgress,
                             void* pProgressData );
-    virtual CPLErr      GetGeoTransform( double* padfTransform );
-    virtual CPLErr      SetGeoTransform( double* padfTransform );
-    virtual const char* GetProjectionRef( void );
-    virtual CPLErr      SetProjection( const char* pszProjString );
-    virtual char      **GetMetadataDomainList();
-    virtual char**      GetMetadata( const char* pszDomain );
-    virtual void        FlushCache( void );
+    virtual CPLErr      GetGeoTransform( double* padfTransform ) override;
+    virtual CPLErr      SetGeoTransform( double* padfTransform ) override;
+    virtual const char* GetProjectionRef() override;
+    virtual CPLErr      SetProjection( const char* pszProjString ) override;
+    virtual char      **GetMetadataDomainList() override;
+    virtual char**      GetMetadata( const char* pszDomain ) override;
+    virtual void        FlushCache() override;
     virtual CPLErr      IRasterIO( GDALRWFlag eRWFlag,
                             int nXOff, int nYOff, int nXSize, int nYSize,
                             void *pData, int nBufXSize, int nBufYSize,
@@ -179,15 +179,15 @@ public:
                             int nBandCount, int *panBandMap,
                             GSpacing nPixelSpace, GSpacing nLineSpace,
                             GSpacing nBandSpace,
-                            GDALRasterIOExtraArg* psExtraArg );
-    virtual int         GetGCPCount() { return nGCPCount; }
-    virtual const char* GetGCPProjection();
+                            GDALRasterIOExtraArg* psExtraArg ) override;
+    virtual int         GetGCPCount() override { return nGCPCount; }
+    virtual const char* GetGCPProjection() override;
     virtual const GDAL_GCP*
-                        GetGCPs() { return pasGCPList; }
+                        GetGCPs() override { return pasGCPList; }
     virtual CPLErr      SetGCPs(
                             int nGCPCount,
                             const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) override;
     virtual CPLErr      IBuildOverviews(
                             const char* pszResampling,
                             int nOverviews,
@@ -195,11 +195,11 @@ public:
                             int nListBandsover,
                             int* panBandList,
                             GDALProgressFunc pfnProgress,
-                            void* pProgresoversData );
-    virtual CPLErr      CreateMaskBand( int nFlags );
-    virtual OGRErr      StartTransaction(int /* bForce */ =FALSE) {return CE_None;};
-    virtual OGRErr      CommitTransaction() {return CE_None;};
-    virtual OGRErr      RollbackTransaction() {return CE_None;};
+                            void* pProgresoversData ) override;
+    virtual CPLErr      CreateMaskBand( int nFlags ) override;
+    virtual OGRErr      StartTransaction(int /* bForce */ =FALSE) override {return CE_None;};
+    virtual OGRErr      CommitTransaction() override {return CE_None;};
+    virtual OGRErr      RollbackTransaction() override {return CE_None;};
 
     void                AssignGeoRaster( GeoRasterWrapper* poGRW );
 };
@@ -244,33 +244,33 @@ private:
 
 public:
 
-    virtual double      GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr      SetNoDataValue( double dfNoDataValue );
-    virtual double      GetMinimum( int* pbSuccess = NULL );
-    virtual double      GetMaximum( int* pbSuccess = NULL );
+    virtual double      GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual CPLErr      SetNoDataValue( double dfNoDataValue ) override;
+    virtual double      GetMinimum( int* pbSuccess = NULL ) override;
+    virtual double      GetMaximum( int* pbSuccess = NULL ) override;
     virtual GDALColorTable*
-                        GetColorTable();
-    virtual CPLErr      SetColorTable( GDALColorTable *poInColorTable );
+                        GetColorTable() override;
+    virtual CPLErr      SetColorTable( GDALColorTable *poInColorTable ) override;
     virtual GDALColorInterp
-                        GetColorInterpretation();
+                        GetColorInterpretation() override;
     virtual CPLErr      IReadBlock( int nBlockXOff, int nBlockYOff,
-                            void *pImage );
+                            void *pImage ) override;
     virtual CPLErr      IWriteBlock( int nBlockXOff, int nBlockYOff,
-                            void *pImage );
+                            void *pImage ) override;
     virtual CPLErr      SetStatistics( double dfMin, double dfMax,
-                            double dfMean, double dfStdDev );
+                            double dfMean, double dfStdDev ) override;
     virtual CPLErr      GetStatistics( int bApproxOK, int bForce,
                             double* pdfMin, double* pdfMax,
-                            double* pdfMean, double* pdfStdDev );
-    virtual             GDALRasterAttributeTable *GetDefaultRAT();
-    virtual CPLErr      SetDefaultRAT( const GDALRasterAttributeTable *poRAT );
-    virtual int         GetOverviewCount();
+                            double* pdfMean, double* pdfStdDev ) override;
+    virtual             GDALRasterAttributeTable *GetDefaultRAT() override;
+    virtual CPLErr      SetDefaultRAT( const GDALRasterAttributeTable *poRAT ) override;
+    virtual int         GetOverviewCount() override;
     virtual GDALRasterBand*
-                        GetOverview( int );
-    virtual CPLErr      CreateMaskBand( int nFlags );
+                        GetOverview( int ) override;
+    virtual CPLErr      CreateMaskBand( int nFlags ) override;
     virtual GDALRasterBand*
-                        GetMaskBand();
-    virtual int         GetMaskFlags();
+                        GetMaskBand() override;
+    virtual int         GetMaskFlags() override;
 };
 
 //  ---------------------------------------------------------------------------
@@ -313,24 +313,24 @@ private:
     bool                bInitializeIO;
     bool                bFlushMetadata;
 
-    void                InitializeLayersNode( void );
-    bool                InitializeIO( void );
+    void                InitializeLayersNode();
+    bool                InitializeIO();
     void                InitializeLevel( int nLevel );
-    bool                FlushMetadata( void );
+    bool                FlushMetadata();
 
-    void                LoadNoDataValues( void );
+    void                LoadNoDataValues();
 
     void                UnpackNBits( GByte* pabyData );
     void                PackNBits( GByte* pabyData );
-    unsigned long       CompressJpeg( void );
-    unsigned long       CompressDeflate( void );
+    unsigned long       CompressJpeg();
+    unsigned long       CompressDeflate();
     void                UncompressJpeg( unsigned long nBufferSize );
     bool                UncompressDeflate( unsigned long nBufferSize );
 
     struct jpeg_decompress_struct sDInfo;
     struct jpeg_compress_struct sCInfo;
     struct jpeg_error_mgr sJErr;
-    
+
     void                GetSpatialReference();
 
 public:
@@ -344,8 +344,8 @@ public:
                             char* pszDescription,
                             char* pszInsert,
                             bool bUpdate );
-    bool                Delete( void );
-    void                GetRasterInfo( void );
+    bool                Delete();
+    void                GetRasterInfo();
     bool                GetStatistics( int nBand,
                                        char* pszMin,
                                        char* pszMax,
@@ -398,7 +398,7 @@ public:
                             const char* pszResampling,
                             bool bInternal = false );
     bool                DeletePyramid();
-    void                PrepareToOverwrite( void );
+    void                PrepareToOverwrite();
     bool                InitializeMask( int nLevel,
                                                 int nBlockColumns,
                                                 int nBlockRows,
diff --git a/frmts/georaster/georaster_rasterband.cpp b/frmts/georaster/georaster_rasterband.cpp
index 4a921db..349c0bf 100644
--- a/frmts/georaster/georaster_rasterband.cpp
+++ b/frmts/georaster/georaster_rasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: $
  *
  * Name:     georaster_rasterband.cpp
  * Project:  Oracle Spatial GeoRaster Driver
@@ -36,6 +35,8 @@
 #include "cpl_vsi.h"
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: georaster_rasterband.cpp 34811 2016-07-28 15:15:05Z goatbar $");
+
 //  ---------------------------------------------------------------------------
 //                                                        GeoRasterRasterBand()
 //  ---------------------------------------------------------------------------
diff --git a/frmts/georaster/georaster_wrapper.cpp b/frmts/georaster/georaster_wrapper.cpp
index 2898230..6c66e5e 100644
--- a/frmts/georaster/georaster_wrapper.cpp
+++ b/frmts/georaster/georaster_wrapper.cpp
@@ -34,13 +34,16 @@
 #include "cpl_string.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: georaster_wrapper.cpp 34811 2016-07-28 15:15:05Z goatbar $");
+CPL_CVSID("$Id: georaster_wrapper.cpp 36367 2016-11-21 01:25:12Z rouault $");
 
 //  ---------------------------------------------------------------------------
 //                                                           GeoRasterWrapper()
 //  ---------------------------------------------------------------------------
 
-GeoRasterWrapper::GeoRasterWrapper()
+GeoRasterWrapper::GeoRasterWrapper() :
+    sPyramidResampling  ( "NN" ),
+    sCompressionType    ( "NONE" ),
+    sInterleaving       ( "BSQ" )
 {
     nRasterId           = -1;
     phMetadata          = NULL;
@@ -61,11 +64,9 @@ GeoRasterWrapper::GeoRasterWrapper()
     dfYCoefficient[0]   = 0.0;
     dfYCoefficient[1]   = 1.0;
     dfYCoefficient[2]   = 0.0;
-    sCompressionType    = "NONE";
     nCompressQuality    = 75;
     bGenPyramid         = false;
     nPyramidLevels      = 0;
-    sPyramidResampling  = "NN";
     pahLocator          = NULL;
     pabyBlockBuf        = NULL;
     pabyCompressBuf     = NULL;
@@ -75,7 +76,6 @@ GeoRasterWrapper::GeoRasterWrapper()
     nCurrentLevel       = -1;
     pahLevels           = NULL;
     nLevelOffset        = 0L;
-    sInterleaving       = "BSQ";
     bUpdate             = false;
     bInitializeIO       = false;
     bFlushMetadata      = false;
@@ -93,13 +93,19 @@ GeoRasterWrapper::GeoRasterWrapper()
     bFlushBlock         = false;
     nFlushBlockSize     = 0L;
     bUniqueFound        = false;
-    sValueAttributeTab  = "";
     psNoDataList        = NULL;
     bWriteOnly          = false;
     bBlocking           = true;
     bAutoBlocking       = false;
     eModelCoordLocation = MCL_DEFAULT;
     phRPC               = NULL;
+    poConnection        = NULL;
+    iDefaultRedBand     = 0;
+    iDefaultGreenBand   = 0;
+    iDefaultBlueBand    = 0;
+    anULTCoordinate[0]  = 0;
+    anULTCoordinate[1]  = 0;
+    anULTCoordinate[2]  = 0;
 }
 
 //  ---------------------------------------------------------------------------
@@ -196,7 +202,6 @@ char** GeoRasterWrapper::ParseIdentificator( const char* pszStringID )
     }
 
     return papszParam;
-
 }
 
 //  ---------------------------------------------------------------------------
@@ -600,9 +605,7 @@ bool GeoRasterWrapper::Create( char* pszDescription,
             int nBlockYSize = nRowBlockSize;
             int nBlockBSize = nBandBlockSize;
 
-            OWStatement* poStmt;
-
-            poStmt = poConnection->CreateStatement(
+            OWStatement* poStmt = poConnection->CreateStatement(
                 "DECLARE\n"
                 "  dimensionSize    sdo_number_array;\n"
                 "  blockSize        sdo_number_array;\n"
@@ -735,7 +738,7 @@ bool GeoRasterWrapper::Create( char* pszDescription,
     //  Create Georaster Table if needed
     //  -------------------------------------------------------------------
 
-    OWStatement* poStmt;
+    OWStatement* poStmt = NULL;
 
     if( ! bUpdateIn )
     {
@@ -928,7 +931,6 @@ bool GeoRasterWrapper::Create( char* pszDescription,
 
         OCIDescriptorFree( phLocator, OCI_DTYPE_LOB );
 
-
         delete poStmt;
 
         return true;
@@ -1440,11 +1442,9 @@ bool GeoRasterWrapper::SetStatistics( int nBand,
 
 bool GeoRasterWrapper::HasColorMap( int nBand )
 {
-    CPLXMLNode *psLayers;
-
     int n = 1;
 
-    psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
+    CPLXMLNode *psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
 
     for( ; psLayers; psLayers = psLayers->psNext, n++ )
     {
@@ -1497,11 +1497,9 @@ void GeoRasterWrapper::GetColorMap( int nBand, GDALColorTable* poCT )
 {
     GDALColorEntry oEntry;
 
-    CPLXMLNode* psLayers;
-
     int n = 1;
 
-    psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
+    CPLXMLNode* psLayers = CPLGetXMLNode( phMetadata, "layerInfo.subLayer" );
 
     for( ; psLayers; psLayers = psLayers->psNext, n++ )
     {
@@ -1593,7 +1591,6 @@ void GeoRasterWrapper::SetColorMap( int nBand, GDALColorTable* poCT )
                 nCount = poCT->GetColorEntryCount();
         }
 
-
         for( iColor = 0; iColor < nCount; iColor++ )
         {
             poCT->GetColorEntryAsRGB( iColor, &oEntry );
@@ -2244,15 +2241,15 @@ void GeoRasterWrapper::GetSpatialReference()
     int i;
 
     CPLXMLNode* phSRSInfo = CPLGetXMLNode( phMetadata, "spatialReferenceInfo" );
-    
+
     if( phSRSInfo == NULL )
     {
         return;
     }
-    
-    const char* pszMCL = CPLGetXMLValue( phSRSInfo, "modelCoordinateLocation", 
+
+    const char* pszMCL = CPLGetXMLValue( phSRSInfo, "modelCoordinateLocation",
                                                     "CENTER" );
-    
+
     if( EQUAL( pszMCL, "CENTER" ) )
     {
       eModelCoordLocation = MCL_CENTER;
@@ -2263,7 +2260,7 @@ void GeoRasterWrapper::GetSpatialReference()
     }
 
     const char* pszModelType = CPLGetXMLValue( phSRSInfo, "modelType", "None" );
-    
+
     if( EQUAL( pszModelType, "FunctionalFitting" ) == false )
     {
         return;
@@ -2285,21 +2282,21 @@ void GeoRasterWrapper::GetSpatialReference()
 
     int nNumCoeff = atoi( CPLGetXMLValue( phPolynomial, "nCoefficients", "0" ));
 
-    if ( nNumCoeff != 3 ) 
+    if ( nNumCoeff != 3 )
     {
         return;
     }
 
-    const char* pszPolyCoeff = CPLGetXMLValue( phPolynomial, 
-                                             "polynomialCoefficients", "None" );
+    const char* pszPolyCoeff = CPLGetXMLValue(phPolynomial,
+                                              "polynomialCoefficients", "None");
 
     if ( EQUAL( pszPolyCoeff, "None" ) )
     {
         return;
     }
 
-    char** papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ", 
-                                           CSLT_STRIPLEADSPACES );
+    char** papszCeoff = CSLTokenizeString2( pszPolyCoeff, " ",
+                                            CSLT_STRIPLEADSPACES );
 
     if( CSLCount( papszCeoff ) < 3 )
     {
@@ -2307,7 +2304,7 @@ void GeoRasterWrapper::GetSpatialReference()
     }
 
     double adfPCoef[3];
-    
+
     for( i = 0; i < 3; i++ )
     {
         adfPCoef[i] = CPLAtof( papszCeoff[i] );
@@ -2333,7 +2330,7 @@ void GeoRasterWrapper::GetSpatialReference()
     {
         return;
     }
-    
+
     double adfRCoef[3];
 
     for( i = 0; i < 3; i++ )
@@ -2348,7 +2345,7 @@ void GeoRasterWrapper::GetSpatialReference()
     double adfVal[6] = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
 
     double dfDet = adfRCoef[1] * adfPCoef[2] - adfRCoef[2] * adfPCoef[1];
-   
+
     if( CPLIsEqual( dfDet, 0.0 ) )
     {
         dfDet = 0.0000000001; // to avoid divide by zero
@@ -2365,26 +2362,26 @@ void GeoRasterWrapper::GetSpatialReference()
     //  -------------------------------------------------------------------
     //  Adjust Model Coordinate Location
     //  -------------------------------------------------------------------
-    
+
     if ( eModelCoordLocation == MCL_CENTER )
     {
         adfVal[2] -= adfVal[0] / 2.0;
         adfVal[5] -= adfVal[4] / 2.0;
     }
 /*
-    CPLDebug("GEOR", "m = [%g, %g, %g, %g, %g, %g]", adfRCoef[1], adfRCoef[2], 
+    CPLDebug("GEOR", "m = [%g, %g, %g, %g, %g, %g]", adfRCoef[1], adfRCoef[2],
              adfRCoef[0], adfPCoef[1], adfPCoef[2], adfPCoef[0]);
-    
-    CPLDebug("GEOR", "i = [%g, %g, %g, %g, %g, %g]", adfVal[0], adfVal[1], 
+
+    CPLDebug("GEOR", "i = [%g, %g, %g, %g, %g, %g]", adfVal[0], adfVal[1],
              adfVal[2], adfVal[3], adfVal[4], adfVal[5]);
-*/    
+*/
     dfXCoefficient[0] = adfVal[0];
     dfXCoefficient[1] = adfVal[1];
     dfXCoefficient[2] = adfVal[2];
     dfYCoefficient[0] = adfVal[3];
     dfYCoefficient[1] = adfVal[4];
     dfYCoefficient[2] = adfVal[5];
-    
+
     //  -------------------------------------------------------------------
     //  Apply ULTCoordinate
     //  -------------------------------------------------------------------
@@ -3816,7 +3813,6 @@ void GeoRasterWrapper::UncompressJpeg( unsigned long nInSize )
                              sDInfo.dc_huff_tbl_ptrs[n],
                              nCompressQuality );
         }
-
     }
 
     jpeg_vsiio_src( &sDInfo, fpImage );
diff --git a/frmts/georaster/makefile.vc b/frmts/georaster/makefile.vc
index 4a99317..3694b84 100644
--- a/frmts/georaster/makefile.vc
+++ b/frmts/georaster/makefile.vc
@@ -18,7 +18,14 @@ JPEG_LIB   = ..\jpeg\libjpeg\libjpeg.lib
 !ENDIF
 !ENDIF
 
-EXTRAFLAGS = $(OCI_INCLUDE) -I..\zlib $(JPEG_FLAGS)
+!IFDEF ZLIB_EXTERNAL_LIB
+ZLIB_FLAGS = $(ZLIB_INC)
+!ELSE
+ZLIB_FLAGS = -I..\zlib
+ZLIB_LIB = ..\zlib\*.obj
+!ENDIF
+
+EXTRAFLAGS = $(OCI_INCLUDE) $(ZLIB_FLAGS) $(JPEG_FLAGS)
 
 default: $(OBJ)
 	xcopy /D  /Y *.obj ..\o
@@ -37,7 +44,7 @@ clean:
 plugin:	$(PLUGIN_DLL)
 
 $(PLUGIN_DLL): $(OBJ)
-	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(OCI_LIB) ..\zlib\*.obj \
+	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(OCI_LIB) $(ZLIB_LIB) \
 	..\jpeg\vsidataio.obj $(JPEG_LIB)
 	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
 
diff --git a/frmts/georaster/oci_wrapper.cpp b/frmts/georaster/oci_wrapper.cpp
index aaf7312..9f64ff8 100644
--- a/frmts/georaster/oci_wrapper.cpp
+++ b/frmts/georaster/oci_wrapper.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: $
  *
  * Name:     oci_wrapper.cpp
  * Project:  Oracle Spatial GeoRaster Driver
@@ -30,6 +29,8 @@
 
 #include "oci_wrapper.h"
 
+CPL_CVSID("$Id: oci_wrapper.cpp 36347 2016-11-20 20:43:39Z rouault $");
+
 static const OW_CellDepth ahOW_CellDepth[] = {
     {"8BIT_U",          GDT_Byte},
     {"16BIT_U",         GDT_UInt16},
@@ -91,12 +92,12 @@ OWConnection::OWConnection( const char* pszUserIn,
     //  Initialize Environment handler
     // ------------------------------------------------------
 
-    if( OCIEnvCreate( &hEnv,
+    if( CheckError( OCIEnvCreate( &hEnv,
         (ub4) ( OCI_DEFAULT | OCI_OBJECT | OCI_THREADED ),
         (dvoid *) 0, (dvoid * (*)(dvoid *, size_t)) 0,
         (dvoid * (*)(dvoid *, dvoid *, size_t)) 0,
         (void (*)(dvoid *, dvoid *)) 0, (size_t) 0,
-        (dvoid **) 0), NULL )
+        (dvoid **) 0), NULL ) )
     {
         return;
     }
@@ -482,7 +483,6 @@ bool OWConnection::GetNextField( OCIParam* phTable,
     *pnScale     = (signed short) nOCIScale;
 
     return true;
-
 }
 
 bool OWConnection::StartTransaction()
@@ -517,12 +517,13 @@ OWStatement::OWStatement( OWConnection* pConnect, const char* pszStatement )
     nNextCol        = 0;
     nNextBnd        = 0;
     hError          = poConnection->hError;
+    nFetchCount     = 0;
 
     //  -----------------------------------------------------------
     //  Create Statement handler
     //  -----------------------------------------------------------
 
-    OCIStmt* hStatement;
+    OCIStmt* hStatement = NULL;
 
     CheckError( OCIHandleAlloc( (dvoid*) poConnection->hEnv,
         (dvoid**) (dvoid*) &hStatement,
@@ -589,7 +590,6 @@ bool OWStatement::Execute( int nRows )
         return false;
     }
 
-
     if( nStatus == OCI_SUCCESS_WITH_INFO || nStatus == OCI_NO_DATA )
     {
         return false;
@@ -746,7 +746,6 @@ void OWStatement::Bind( sdo_geometry** pphData )
     (dvoid**) 0,
         (ub4*) 0),
         hError );
-
 }
 
 void OWStatement::Bind( OCILobLocator** pphLocator )
@@ -803,7 +802,6 @@ void OWStatement::Bind( OCIArray** pphData, OCIType* type )
         (dvoid **)0,
         (ub4 *)0 ),
         hError);
-
 }
 
 void OWStatement::Bind( char* pszData, int nSize )
@@ -1168,7 +1166,7 @@ void OWStatement::Free( OCILobLocator** pphLocator, int nCount )
 int OWStatement::GetElement( OCIArray** ppoData, int nIndex, int* pnResult )
 {
     boolean        exists;
-    OCINumber      *oci_number;
+    OCINumber      *oci_number = NULL;
     ub4            element_type;
 
     *pnResult = 0;
@@ -1204,7 +1202,7 @@ double OWStatement::GetElement( OCIArray** ppoData,
                                int nIndex, double* pdfResult )
 {
     boolean        exists;
-    OCINumber      *oci_number;
+    OCINumber      *oci_number = NULL;
     double         element_type;
 
     *pdfResult = 0.0;
@@ -1318,7 +1316,7 @@ bool OWStatement::WriteBlob( OCILobLocator* phLocator,
         return false;
     }
 
-    return ( nAmont == (ub4) nSize );
+    return nAmont == (ub4) nSize;
 }
 
 char* OWStatement::ReadCLob( OCILobLocator* phLocator )
@@ -1750,7 +1748,6 @@ bool CheckError( sword nStatus, OCIError* hError )
             CPLError( CE_Failure, CPLE_AppDefined, "%.*s",
                 static_cast<int>(sizeof(szMsg)), szMsg );
             break;
-
     }
 
     return true;
diff --git a/frmts/georaster/oci_wrapper.h b/frmts/georaster/oci_wrapper.h
index 5f4b4fc..c62002b 100644
--- a/frmts/georaster/oci_wrapper.h
+++ b/frmts/georaster/oci_wrapper.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: $
+ * $Id: oci_wrapper.h 35929 2016-10-25 16:09:00Z goatbar $
  *
  * Name:     oci_wrapper.h
  * Project:  Oracle Spatial GeoRaster Driver
@@ -329,7 +329,6 @@ public:
     bool                Commit(); // OCITransCommit()
     bool                StartTransaction(); //  //OCITransStart()
     bool                EndTransaction() {return Commit(); }
-
 };
 
 /***************************************************************************/
diff --git a/frmts/gff/gff_dataset.cpp b/frmts/gff/gff_dataset.cpp
index acfd800..d771693 100644
--- a/frmts/gff/gff_dataset.cpp
+++ b/frmts/gff/gff_dataset.cpp
@@ -1,9 +1,8 @@
 /******************************************************************************
- * $Id: gff_dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Ground-based SAR Applitcations Testbed File Format driver
  * Purpose:  Support in GDAL for Sandia National Laboratory's GFF format
- * 	     blame Tisham for putting me up to this
+ *           blame Tisham for putting me up to this
  * Author:   Philippe Vachon <philippe at cowpig.ca>
  *
  ******************************************************************************
@@ -37,7 +36,7 @@
 #include "gdal_pam.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gff_dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gff_dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /*******************************************************************
  * Declaration of the GFFDataset class                             *
@@ -80,15 +79,23 @@ public:
 };
 
 GFFDataset::GFFDataset() :
-    fp(NULL), eDataType(GDT_Unknown), nEndianness(0), nVersionMajor(0),
-    nVersionMinor(0), nLength(0), nBPP(0), nFrameCnt(0), nImageType(0),
-    nRowMajor(0), nRgCnt(0), nAzCnt(0)
-{
-}
+    fp(NULL),
+    eDataType(GDT_Unknown),
+    nEndianness(0),
+    nVersionMajor(0),
+    nVersionMinor(0),
+    nLength(0),
+    nBPP(0),
+    nFrameCnt(0),
+    nImageType(0),
+    nRowMajor(0),
+    nRgCnt(0),
+    nAzCnt(0)
+{}
 
 GFFDataset::~GFFDataset()
 {
-    if (fp != NULL)
+    if( fp != NULL )
         VSIFCloseL(fp);
 }
 
@@ -101,25 +108,13 @@ class GFFRasterBand : public GDALPamRasterBand {
     int nSampleSize;
 public:
     GFFRasterBand( GFFDataset *, int, GDALDataType );
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
-/************************************************************************/
-/*                           GFFRasterBand()                            */
-/************************************************************************/
-GFFRasterBand::GFFRasterBand( GFFDataset *poDSIn, int nBandIn,
-	GDALDataType eDataTypeIn )
+static unsigned long GFFSampleSize( GDALDataType eDataType )
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-
-    this->eDataType = eDataTypeIn;
-
-    nBlockXSize = poDS->GetRasterXSize();
-    nBlockYSize = 1;
-
-    /* Determine the number of bytes per sample */
-    unsigned long nBytes;
+    // Determine the number of bytes per sample.
+    unsigned long nBytes = 1;
     switch (eDataType) {
       case GDT_CInt16:
         nBytes = 4;
@@ -132,8 +127,24 @@ GFFRasterBand::GFFRasterBand( GFFDataset *poDSIn, int nBandIn,
         nBytes = 1;
     }
 
-    nRasterBandMemory = nBytes * poDS->GetRasterXSize();
-    nSampleSize = static_cast<int>(nBytes);
+    return nBytes;
+}
+
+/************************************************************************/
+/*                           GFFRasterBand()                            */
+/************************************************************************/
+GFFRasterBand::GFFRasterBand( GFFDataset *poDSIn, int nBandIn,
+                              GDALDataType eDataTypeIn ) :
+    nRasterBandMemory(GFFSampleSize(eDataTypeIn) * poDSIn->GetRasterXSize()),
+    nSampleSize(static_cast<int>(GFFSampleSize(eDataTypeIn)))
+{
+    poDS = poDSIn;
+    nBand = nBandIn;
+
+    eDataType = eDataTypeIn;
+
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
 }
 
 /************************************************************************/
diff --git a/frmts/gif/biggifdataset.cpp b/frmts/gif/biggifdataset.cpp
index 11a1207..75ed779 100644
--- a/frmts/gif/biggifdataset.cpp
+++ b/frmts/gif/biggifdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: biggifdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  BIGGIF Driver
  * Purpose:  Implement GDAL support for reading large GIF files in a
@@ -35,7 +34,7 @@
 #include "gdal_pam.h"
 #include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: biggifdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: biggifdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -56,11 +55,11 @@ class BIGGIFDataset : public GIFAbstractDataset
     CPLErr       ReOpen();
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
   public:
                  BIGGIFDataset();
-                 ~BIGGIFDataset();
+    virtual ~BIGGIFDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -76,10 +75,9 @@ class BIGGifRasterBand : public GIFAbstractRasterBand
     friend class BIGGIFDataset;
 
   public:
-
                    BIGGifRasterBand( BIGGIFDataset *, int );
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -87,10 +85,10 @@ class BIGGifRasterBand : public GIFAbstractRasterBand
 /************************************************************************/
 
 BIGGifRasterBand::BIGGifRasterBand( BIGGIFDataset *poDSIn, int nBackground ) :
-    GIFAbstractRasterBand(poDSIn, 1, poDSIn->hGifFile->SavedImages, nBackground, TRUE)
+    GIFAbstractRasterBand(poDSIn, 1, poDSIn->hGifFile->SavedImages,
+                          nBackground, TRUE)
 
-{
-}
+{}
 
 /************************************************************************/
 /*                             IReadBlock()                             */
@@ -161,7 +159,6 @@ CPLErr BIGGifRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            BIGGIFDataset()                            */
 /************************************************************************/
@@ -169,8 +166,7 @@ CPLErr BIGGifRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 BIGGIFDataset::BIGGIFDataset() :
     nLastLineRead(-1),
     poWorkDS(NULL)
-{
-}
+{}
 
 /************************************************************************/
 /*                           ~BIGGIFDataset()                            */
@@ -295,7 +291,6 @@ CPLErr BIGGIFDataset::ReOpen()
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
diff --git a/frmts/gif/gifabstractdataset.cpp b/frmts/gif/gifabstractdataset.cpp
index e37cad4..c8b75cc 100644
--- a/frmts/gif/gifabstractdataset.cpp
+++ b/frmts/gif/gifabstractdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gifabstractdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GIF Driver
  * Purpose:  GIF Abstract Dataset
@@ -29,7 +28,7 @@
 
 #include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: gifabstractdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: gifabstractdataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 static const int InterlacedOffset[] = { 0, 4, 2, 1 };
 static const int InterlacedJumps[] = { 8, 8, 4, 2 };
@@ -40,7 +39,6 @@ static const int InterlacedJumps[] = { 8, 8, 4, 2 };
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                         GIFAbstractDataset()                         */
 /************************************************************************/
@@ -191,7 +189,7 @@ void GIFAbstractDataset::CollectXMPMetadata()
         return;
 
     CPLString osXMP = GIFCollectXMPMetadata(fp);
-    if (osXMP.size())
+    if (!osXMP.empty() )
     {
         /* Avoid setting the PAM dirty bit just for that */
         int nOldPamFlags = nPamFlags;
@@ -326,7 +324,7 @@ char **GIFAbstractDataset::GetFileList()
 {
     char **papszFileList = GDALPamDataset::GetFileList();
 
-    if (osWldFilename.size() != 0 &&
+    if (!osWldFilename.empty() &&
         CSLFindString(papszFileList, osWldFilename) == -1)
     {
         papszFileList = CSLAddString( papszFileList, osWldFilename );
@@ -434,7 +432,7 @@ GifRecordType GIFAbstractDataset::FindFirstImage( GifFileType* hGifFile )
         if (RecordType == EXTENSION_RECORD_TYPE)
         {
             int nFunction;
-            GifByteType *pExtData;
+            GifByteType *pExtData = NULL;
             if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR)
                 break;
             while (pExtData != NULL)
@@ -453,24 +451,23 @@ GifRecordType GIFAbstractDataset::FindFirstImage( GifFileType* hGifFile )
 /************************************************************************/
 
 GIFAbstractRasterBand::GIFAbstractRasterBand(
-                              GIFAbstractDataset *poDSIn, int nBandIn,
-                              SavedImage *psSavedImage, int nBackground,
-                              int bAdvertizeInterlacedMDI ) :
+    GIFAbstractDataset *poDSIn, int nBandIn,
+    SavedImage *psSavedImage, int nBackground,
+    int bAdvertizeInterlacedMDI ) :
+    psImage(psSavedImage),
     panInterlaceMap(NULL),
     poColorTable(NULL),
     nTransparentColor(0)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Byte;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 
-    psImage = psSavedImage;
-
-    if (psImage == NULL)
+    if( psImage == NULL )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -495,7 +492,9 @@ GIFAbstractRasterBand::GIFAbstractRasterBand(
         }
     }
     else if( bAdvertizeInterlacedMDI )
+    {
         poDS->SetMetadataItem( "INTERLACED", "NO", "IMAGE_STRUCTURE" );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Check for transparency.  We just take the first graphic         */
@@ -504,13 +503,12 @@ GIFAbstractRasterBand::GIFAbstractRasterBand(
     nTransparentColor = -1;
     for( int iExtBlock = 0; iExtBlock < psImage->ExtensionBlockCount; iExtBlock++ )
     {
-        unsigned char *pExtData;
-
         if( psImage->ExtensionBlocks[iExtBlock].Function != 0xf9 ||
             psImage->ExtensionBlocks[iExtBlock].ByteCount < 4 )
             continue;
 
-        pExtData = (unsigned char *) psImage->ExtensionBlocks[iExtBlock].Bytes;
+        unsigned char *pExtData = reinterpret_cast<unsigned char *>(
+            psImage->ExtensionBlocks[iExtBlock].Bytes);
 
         /* check if transparent color flag is set */
         if( !(pExtData[0] & 0x1) )
@@ -522,7 +520,7 @@ GIFAbstractRasterBand::GIFAbstractRasterBand(
 /* -------------------------------------------------------------------- */
 /*      Setup colormap.                                                 */
 /* -------------------------------------------------------------------- */
-    ColorMapObject      *psGifCT = psImage->ImageDesc.ColorMap;
+    ColorMapObject  *psGifCT = psImage->ImageDesc.ColorMap;
     if( psGifCT == NULL )
         psGifCT = poDSIn->hGifFile->SColorMap;
 
diff --git a/frmts/gif/gifabstractdataset.h b/frmts/gif/gifabstractdataset.h
index fd2cf88..bb74df6 100644
--- a/frmts/gif/gifabstractdataset.h
+++ b/frmts/gif/gifabstractdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gifabstractdataset.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: gifabstractdataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GIF Driver
  * Purpose:  GIF Abstract Dataset
@@ -67,18 +67,18 @@ class GIFAbstractDataset : public GDALPamDataset
 
   public:
                  GIFAbstractDataset();
-                 ~GIFAbstractDataset();
+    virtual      ~GIFAbstractDataset();
 
-    virtual const char *GetProjectionRef();
-    virtual CPLErr GetGeoTransform( double * );
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char  **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char  **GetMetadata( const char * pszDomain = "" ) override;
 
-    virtual char **GetFileList(void);
+    virtual char **GetFileList() override;
 
     static int          Identify( GDALOpenInfo * );
 
@@ -114,10 +114,9 @@ class GIFAbstractRasterBand : public GDALPamRasterBand
                                          int bAdvertizeInterlacedMDI );
     virtual       ~GIFAbstractRasterBand();
 
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
 };
 
-
 #endif
diff --git a/frmts/gif/gifdataset.cpp b/frmts/gif/gifdataset.cpp
index 79668da..580931d 100644
--- a/frmts/gif/gifdataset.cpp
+++ b/frmts/gif/gifdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gifdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GIF Driver
  * Purpose:  Implement GDAL GIF Support using libungif code.
@@ -28,12 +27,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gifabstractdataset.h"
+
 #include "cpl_string.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
-#include "gifabstractdataset.h"
 
-CPL_CVSID("$Id: gifdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: gifdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 CPL_C_START
 #if !(defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5)
@@ -52,11 +52,42 @@ CPL_C_END
 static const int InterlacedOffset[] = { 0, 4, 2, 1 };
 static const int InterlacedJumps[] = { 8, 8, 4, 2 };
 
-static int VSIGIFWriteFunc( GifFileType *, const GifByteType *, int );
+/************************************************************************/
+/*                          VSIGIFWriteFunc()                           */
+/*                                                                      */
+/*      Proxy write function.                                           */
+/************************************************************************/
+
+static int VSIGIFWriteFunc( GifFileType *psGFile,
+                            const GifByteType *pabyBuffer, int nBytesToWrite )
+
+{
+    VSILFILE* fp = static_cast<VSILFILE *>(psGFile->UserData);
+    if( VSIFTellL(fp) == 0 && nBytesToWrite >= 6 &&
+        memcmp(pabyBuffer, "GIF87a", 6) == 0 )
+    {
+        // This is a hack to write a GIF89a instead of GIF87a (we have to, since
+        // we are using graphical extension block).  EGifSpew would write GIF89a
+        // when it detects an extension block if we were using it As we don't,
+        // we could have used EGifSetGifVersion instead, but the version of
+        // libungif in GDAL has a bug: it writes on read-only memory!
+        // This is a well-known problem. Just google for "EGifSetGifVersion
+        // segfault".
+        // Most readers don't even care if it is GIF87a or GIF89a, but it is
+        // better to write the right version.
+
+        size_t nRet = VSIFWriteL("GIF89a", 1, 6, fp);
+        nRet += VSIFWriteL( reinterpret_cast<const char *>(pabyBuffer) + 6,
+                            1, nBytesToWrite - 6, fp );
+        return static_cast<int>(nRet);
+    }
+
+    return static_cast<int>(VSIFWriteL( pabyBuffer, 1, nBytesToWrite, fp ));
+}
 
 /************************************************************************/
 /* ==================================================================== */
-/*	                            GIFDataset                              */
+/*                                  GIFDataset                          */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -89,7 +120,7 @@ class GIFRasterBand : public GIFAbstractRasterBand
   public:
 
                    GIFRasterBand( GIFDataset *, int, SavedImage *, int );
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -98,10 +129,8 @@ class GIFRasterBand : public GIFAbstractRasterBand
 
 GIFRasterBand::GIFRasterBand( GIFDataset *poDSIn, int nBandIn,
                               SavedImage *psSavedImage, int nBackground ) :
-                GIFAbstractRasterBand(poDSIn, nBandIn, psSavedImage, nBackground, FALSE)
-
-{
-}
+    GIFAbstractRasterBand(poDSIn, nBandIn, psSavedImage, nBackground, FALSE)
+{}
 
 /************************************************************************/
 /*                             IReadBlock()                             */
@@ -113,7 +142,7 @@ CPLErr GIFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 {
     CPLAssert( nBlockXOff == 0 );
 
-    if (psImage == NULL)
+    if( psImage == NULL )
     {
         memset(pImage, 0, nBlockXSize);
         return CE_None;
@@ -134,14 +163,11 @@ CPLErr GIFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            GIFDataset()                            */
 /************************************************************************/
 
-GIFDataset::GIFDataset()
-{
-}
+GIFDataset::GIFDataset() {}
 
 /************************************************************************/
 /*                                Open()                                */
@@ -157,7 +183,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "The GIF driver does not support update access to existing"
-                  " files.\n" );
+                  " files." );
         return NULL;
     }
 
@@ -173,15 +199,15 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         VSIFCloseL( fp );
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "DGifOpen() failed for %s.\n"
-                  "Perhaps the gif file is corrupt?\n",
+                  "DGifOpen() failed for %s.  "
+                  "Perhaps the gif file is corrupt?",
                   poOpenInfo->pszFilename );
 
         return NULL;
     }
 
-    /* The following code enables us to detect GIF datasets eligible */
-    /* for BIGGIF driver even with an unpatched giflib  */
+    // The following code enables us to detect GIF datasets eligible
+    // for BIGGIF driver even with an unpatched giflib.
 
     /* -------------------------------------------------------------------- */
     /*      Find the first image record.                                    */
@@ -190,15 +216,16 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
     if( RecordType == IMAGE_DESC_RECORD_TYPE  &&
         DGifGetImageDesc(hGifFile) != GIF_ERROR)
     {
-        int width = hGifFile->SavedImages[0].ImageDesc.Width;
-        int height = hGifFile->SavedImages[0].ImageDesc.Height;
-        if ((double) width * (double) height > 100000000.0 )
+        const int width = hGifFile->SavedImages[0].ImageDesc.Width;
+        const int height = hGifFile->SavedImages[0].ImageDesc.Height;
+        if( static_cast<double>(width) * height > 100000000.0 )
         {
             CPLDebug( "GIF",
-                      "Due to limitations of the GDAL GIF driver we deliberately avoid\n"
-                      "opening large GIF files (larger than 100 megapixels).");
+                      "Due to limitations of the GDAL GIF driver we "
+                      "deliberately avoid opening large GIF files "
+                      "(larger than 100 megapixels).");
             GIFAbstractDataset::myDGifCloseFile( hGifFile );
-            /* Reset poOpenInfo->fpL since BIGGIF may need it */
+            // Reset poOpenInfo->fpL since BIGGIF may need it.
             poOpenInfo->fpL = fp;
             VSIFSeekL(fp, 0, SEEK_SET);
             return NULL;
@@ -209,19 +236,20 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     VSIFSeekL( fp, 0, SEEK_SET);
 
-    hGifFile = GIFAbstractDataset::myDGifOpen( fp, GIFAbstractDataset::ReadFunc );
+    hGifFile =
+        GIFAbstractDataset::myDGifOpen( fp, GIFAbstractDataset::ReadFunc );
     if( hGifFile == NULL )
     {
         VSIFCloseL( fp );
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "DGifOpen() failed for %s.\n"
-                  "Perhaps the gif file is corrupt?\n",
+                  "DGifOpen() failed for %s.  "
+                  "Perhaps the gif file is corrupt?",
                   poOpenInfo->pszFilename );
 
         return NULL;
     }
 
-    int nGifErr = DGifSlurp( hGifFile );
+    const int nGifErr = DGifSlurp( hGifFile );
 
     if( nGifErr != GIF_OK || hGifFile->SavedImages == NULL )
     {
@@ -231,17 +259,18 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
         if( nGifErr == D_GIF_ERR_DATA_TOO_BIG )
         {
              CPLDebug( "GIF",
-                       "DGifSlurp() failed for %s because it was too large.\n"
-                       "Due to limitations of the GDAL GIF driver we deliberately avoid\n"
-                       "opening large GIF files (larger than 100 megapixels).",
+                       "DGifSlurp() failed for %s because it was too large.  "
+                       "Due to limitations of the GDAL GIF driver we "
+                       "deliberately avoid opening large GIF files "
+                       "(larger than 100 megapixels).",
                        poOpenInfo->pszFilename );
             return NULL;
-         }
-         else
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                        "DGifSlurp() failed for %s.\n"
-                        "Perhaps the gif file is corrupt?\n",
-                        poOpenInfo->pszFilename );
+        }
+
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "DGifSlurp() failed for %s.  "
+                  "Perhaps the gif file is corrupt?",
+                  poOpenInfo->pszFilename );
 
         return NULL;
     }
@@ -266,7 +295,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     for( int iImage = 0; iImage < hGifFile->ImageCount; iImage++ )
     {
-        SavedImage	*psImage = hGifFile->SavedImages + iImage;
+        SavedImage *psImage = hGifFile->SavedImages + iImage;
 
         if( psImage->ImageDesc.Width != poDS->nRasterXSize
             || psImage->ImageDesc.Height != poDS->nRasterYSize )
@@ -279,7 +308,7 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
             continue;
         }
 #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
-        /* Since giflib 5, de-interlacing is done by DGifSlurp() */
+        // Since giflib 5, de-interlacing is done by DGifSlurp().
         psImage->ImageDesc.Interlace = 0;
 #endif
         poDS->SetBand( poDS->nBands+1,
@@ -316,20 +345,22 @@ GDALDataset *GIFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                        GDALPrintGifError()                           */
 /************************************************************************/
 
-static void GDALPrintGifError(CPL_UNUSED GifFileType *hGifFile, const char* pszMsg)
+static void GDALPrintGifError( CPL_UNUSED GifFileType *hGifFile,
+                               const char* pszMsg )
 {
-/* GIFLIB_MAJOR is only defined in libgif >= 4.2.0 */
-/* libgif 4.2.0 has retired PrintGifError() and added GifErrorString() */
+    // GIFLIB_MAJOR is only defined in libgif >= 4.2.0.
+    // libgif 4.2.0 has retired PrintGifError() and added GifErrorString().
 #if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) && \
         ((GIFLIB_MAJOR == 4 && GIFLIB_MINOR >= 2) || GIFLIB_MAJOR > 4)
-    /* Static string actually, hence the const char* cast */
+    // Static string actually, hence the const char* cast.
 
 #if GIFLIB_MAJOR >= 5
-    const char* pszGIFLIBError = (const char*) GifErrorString(hGifFile->Error);
+    const char* pszGIFLIBError = GifErrorString(hGifFile->Error);
 #else
+    // TODO(schwehr): Can we remove the cast for older libgif?
     const char* pszGIFLIBError = (const char*) GifErrorString();
 #endif
-    if (pszGIFLIBError == NULL)
+    if( pszGIFLIBError == NULL )
         pszGIFLIBError = "Unknown error";
     CPLError( CE_Failure, CPLE_AppDefined,
               "%s. GIFLib Error : %s", pszMsg, pszGIFLIBError );
@@ -344,15 +375,17 @@ static void GDALPrintGifError(CPL_UNUSED GifFileType *hGifFile, const char* pszM
 /************************************************************************/
 
 GDALDataset *
-GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
-               int bStrict, char ** papszOptions,
-               GDALProgressFunc pfnProgress, void * pProgressData )
+GIFDataset::CreateCopy(
+    const char * pszFilename, GDALDataset *poSrcDS,
+    int bStrict, char ** papszOptions,
+    GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Check for interlaced option.                                    */
 /* -------------------------------------------------------------------- */
-    int bInterlace = CSLFetchBoolean(papszOptions, "INTERLACING", FALSE);
+    const bool bInterlace =
+        CPLFetchBool(papszOptions, "INTERLACING", false);
 
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
@@ -361,17 +394,17 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( nBands != 1 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "GIF driver only supports one band images.\n" );
+                  "GIF driver only supports one band images." );
 
         return NULL;
     }
 
     const int nXSize = poSrcDS->GetRasterXSize();
     const int nYSize = poSrcDS->GetRasterYSize();
-    if (nXSize > 65535 || nYSize > 65535)
+    if( nXSize > 65535 || nYSize > 65535 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "GIF driver only supports datasets up to 65535x65535 size.\n" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "GIF driver only supports datasets up to 65535x65535 size.");
 
         return NULL;
     }
@@ -381,7 +414,7 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "GIF driver doesn't support data type %s. "
-                  "Only eight bit bands supported.\n",
+                  "Only eight bit bands supported.",
                   GDALGetDataTypeName(
                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
 
@@ -391,7 +424,7 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Open the output file.                                           */
 /* -------------------------------------------------------------------- */
-    VSILFILE *fp  = VSIFOpenL( pszFilename, "wb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -400,12 +433,11 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-    GifFileType *hGifFile;
 #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
-    int nError;
-    hGifFile = EGifOpen( fp, VSIGIFWriteFunc, &nError );
+    int nError = 0;
+    GifFileType *hGifFile = EGifOpen( fp, VSIGIFWriteFunc, &nError );
 #else
-    hGifFile = EGifOpen( fp, VSIGIFWriteFunc );
+    GifFileType *hGifFile = EGifOpen( fp, VSIGIFWriteFunc );
 #endif
     if( hGifFile == NULL )
     {
@@ -420,8 +452,8 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Prepare colortable.                                             */
 /* -------------------------------------------------------------------- */
-    GDALRasterBand	*poBand = poSrcDS->GetRasterBand(1);
-    ColorMapObject	*psGifCT;
+    GDALRasterBand *poBand = poSrcDS->GetRasterBand(1);
+    ColorMapObject *psGifCT = NULL;
 
     if( poBand->GetColorTable() == NULL )
     {
@@ -436,14 +468,14 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
         for( int iColor = 0; iColor < 256; iColor++ )
         {
-            psGifCT->Colors[iColor].Red = (GifByteType) iColor;
-            psGifCT->Colors[iColor].Green = (GifByteType) iColor;
-            psGifCT->Colors[iColor].Blue = (GifByteType) iColor;
+            psGifCT->Colors[iColor].Red = static_cast<GifByteType>(iColor);
+            psGifCT->Colors[iColor].Green = static_cast<GifByteType>(iColor);
+            psGifCT->Colors[iColor].Blue = static_cast<GifByteType>(iColor);
         }
     }
     else
     {
-        GDALColorTable	*poCT = poBand->GetColorTable();
+        GDALColorTable *poCT = poBand->GetColorTable();
         int nFullCount = 2;
 
         while( nFullCount < poCT->GetColorEntryCount() )
@@ -461,12 +493,12 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         int iColor = 0;
         for( ; iColor < poCT->GetColorEntryCount(); iColor++ )
         {
-            GDALColorEntry	sEntry;
+            GDALColorEntry sEntry;
 
             poCT->GetColorEntryAsRGB( iColor, &sEntry );
-            psGifCT->Colors[iColor].Red = (GifByteType) sEntry.c1;
-            psGifCT->Colors[iColor].Green = (GifByteType) sEntry.c2;
-            psGifCT->Colors[iColor].Blue = (GifByteType) sEntry.c3;
+            psGifCT->Colors[iColor].Red = static_cast<GifByteType>(sEntry.c1);
+            psGifCT->Colors[iColor].Green = static_cast<GifByteType>(sEntry.c2);
+            psGifCT->Colors[iColor].Blue = static_cast<GifByteType>(sEntry.c3);
         }
         for( ; iColor < nFullCount; iColor++ )
         {
@@ -479,10 +511,10 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Setup parameters.                                               */
 /* -------------------------------------------------------------------- */
-    if (EGifPutScreenDesc(hGifFile, nXSize, nYSize,
+    if( EGifPutScreenDesc(hGifFile, nXSize, nYSize,
                           8, /* ColorRes */
                           255, /* Background */
-                          psGifCT) == GIF_ERROR)
+                          psGifCT) == GIF_ERROR )
     {
         GifFreeMapObject(psGifCT);
         GDALPrintGifError(hGifFile, "Error writing gif file.");
@@ -494,20 +526,21 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     GifFreeMapObject(psGifCT);
     psGifCT = NULL;
 
-    /* Support for transparency */
-    int bNoDataValue;
+    // Support for transparency.
+    int bNoDataValue = 0;
     double noDataValue = poBand->GetNoDataValue(&bNoDataValue);
-    if (bNoDataValue && noDataValue >= 0 && noDataValue <= 255)
+    if( bNoDataValue && noDataValue >= 0 && noDataValue <= 255 )
     {
-        unsigned char extensionData[4];
-        extensionData[0] = 1; /*  Transparent Color Flag */
-        extensionData[1] = 0;
-        extensionData[2] = 0;
-        extensionData[3] = (unsigned char)noDataValue;
+      unsigned char extensionData[4] = {
+        1,  // Transparent Color Flag.
+        0,
+        0,
+        static_cast<unsigned char>(noDataValue) };
         EGifPutExtension(hGifFile, 0xf9, 4, extensionData);
     }
 
-    if (EGifPutImageDesc(hGifFile, 0, 0, nXSize, nYSize, bInterlace, NULL) == GIF_ERROR )
+    if( EGifPutImageDesc(hGifFile, 0, 0, nXSize, nYSize,
+                         bInterlace, NULL) == GIF_ERROR )
     {
         GDALPrintGifError(hGifFile, "Error writing gif file.");
         GIFAbstractDataset::myEGifCloseFile(hGifFile);
@@ -519,7 +552,7 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Loop over image, copying image data.                            */
 /* -------------------------------------------------------------------- */
     GDALPamDataset *poDS = NULL;
-    GByte *pabyScanline = (GByte *) CPLMalloc( nXSize );
+    GByte *pabyScanline = static_cast<GByte *>(CPLMalloc( nXSize ));
 
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     {
@@ -531,54 +564,63 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         for( int iLine = 0; iLine < nYSize; iLine++ )
         {
-            const CPLErr eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
-                                                  pabyScanline, nXSize, 1, GDT_Byte,
-                                                  nBands, nBands * nXSize, NULL );
+            const CPLErr eErr =
+                poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
+                                  pabyScanline, nXSize, 1, GDT_Byte,
+                                  nBands, nBands * nXSize, NULL );
 
-            if( eErr != CE_None || EGifPutLine( hGifFile, pabyScanline, nXSize ) == GIF_ERROR )
+            if( eErr != CE_None ||
+                EGifPutLine( hGifFile, pabyScanline, nXSize ) == GIF_ERROR )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Error writing gif file." );
                 goto error;
             }
 
-            if( !pfnProgress( (iLine + 1) * 1.0 / nYSize, NULL, pProgressData ) )
+            if( !pfnProgress( (iLine + 1) * 1.0 / nYSize,
+                              NULL, pProgressData ) )
             {
                 goto error;
             }
-
         }
     }
     else
     {
         int nLinesToRead = 0;
-        for ( int i = 0; i < 4; i++)
+        for( int i = 0; i < 4; i++)
         {
-            for ( int j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i] )
+            for( int j = InterlacedOffset[i];
+                 j < nYSize;
+                 j += InterlacedJumps[i] )
             {
-                nLinesToRead ++;
+                nLinesToRead++;
             }
         }
 
         int nLinesRead = 0;
-        /* Need to perform 4 passes on the images: */
-        for ( int i = 0; i < 4; i++)
+        // Need to perform 4 passes on the images:
+        for( int i = 0; i < 4; i++)
         {
-            for ( int j = InterlacedOffset[i]; j < nYSize; j += InterlacedJumps[i] )
+            for( int j = InterlacedOffset[i];
+                 j < nYSize;
+                 j += InterlacedJumps[i] )
             {
-                const CPLErr eErr= poBand->RasterIO( GF_Read, 0, j, nXSize, 1,
-                                        pabyScanline, nXSize, 1, GDT_Byte,
-                                        1, nXSize, NULL );
+                const CPLErr eErr =
+                    poBand->RasterIO( GF_Read, 0, j, nXSize, 1,
+                                      pabyScanline, nXSize, 1, GDT_Byte,
+                                      1, nXSize, NULL );
 
-                if (eErr != CE_None || EGifPutLine(hGifFile, pabyScanline, nXSize) == GIF_ERROR)
+                if( eErr != CE_None ||
+                    EGifPutLine(hGifFile, pabyScanline, nXSize) == GIF_ERROR )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
                             "Error writing gif file." );
                     goto error;
                 }
 
-                nLinesRead ++;
-                if( !pfnProgress( nLinesRead * 1.0 / nYSize, NULL, pProgressData ) )
+                nLinesRead++;
+                if( !pfnProgress( nLinesRead * 1.0 / nYSize,
+                                  NULL, pProgressData ) )
                 {
                     goto error;
                 }
@@ -592,10 +634,9 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    if (GIFAbstractDataset::myEGifCloseFile(hGifFile) == GIF_ERROR)
+    if( GIFAbstractDataset::myEGifCloseFile(hGifFile) == GIF_ERROR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "EGifCloseFile() failed.\n" );
+        CPLError( CE_Failure, CPLE_AppDefined, "EGifCloseFile() failed." );
         hGifFile = NULL;
         goto error;
     }
@@ -605,11 +646,11 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     fp = NULL;
 
 /* -------------------------------------------------------------------- */
-/*      Do we need a world file?                                          */
+/*      Do we need a world file?                                        */
 /* -------------------------------------------------------------------- */
-    if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
+    if( CPLFetchBool( papszOptions, "WORLDFILE", false ) )
     {
-        double      adfGeoTransform[6];
+        double adfGeoTransform[6] = {};
 
         if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
             GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
@@ -619,12 +660,12 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Re-open dataset, and copy any auxiliary pam information.         */
 /* -------------------------------------------------------------------- */
 
-    /* If writing to stdout, we can't reopen it, so return */
-    /* a fake dataset to make the caller happy */
+    // If writing to stdout, we can't reopen it, so return
+    // a fake dataset to make the caller happy.
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly);
+    poDS = static_cast<GDALPamDataset *>(GDALOpen(pszFilename, GA_ReadOnly));
     CPLPopErrorHandler();
-    if (poDS)
+    if( poDS )
     {
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
         return poDS;
@@ -636,53 +677,23 @@ GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         GIFDataset* poGIF_DS = new GIFDataset();
         poGIF_DS->nRasterXSize = nXSize;
         poGIF_DS->nRasterYSize = nYSize;
-        for(int i=0;i<nBands;i++)
-            poGIF_DS->SetBand( i+1, new GIFRasterBand( poGIF_DS, i+1, NULL, 0 ) );
+        for( int i = 0; i < nBands; i++ )
+            poGIF_DS->SetBand( i+1,
+                               new GIFRasterBand( poGIF_DS, i+1, NULL, 0 ) );
         return poGIF_DS;
     }
 
 error:
-    if (hGifFile)
+    if( hGifFile )
         GIFAbstractDataset::myEGifCloseFile(hGifFile);
-    if (fp)
+    if( fp )
         VSIFCloseL( fp );
-    if (pabyScanline)
+    if( pabyScanline )
         CPLFree( pabyScanline );
     return NULL;
 }
 
 /************************************************************************/
-/*                          VSIGIFWriteFunc()                           */
-/*                                                                      */
-/*      Proxy write function.                                           */
-/************************************************************************/
-
-static int VSIGIFWriteFunc( GifFileType *psGFile,
-                            const GifByteType *pabyBuffer, int nBytesToWrite )
-
-{
-    VSILFILE* fp = (VSILFILE *) psGFile->UserData;
-    if ( VSIFTellL(fp) == 0 && nBytesToWrite >= 6 &&
-         memcmp(pabyBuffer, "GIF87a", 6) == 0 )
-    {
-        /* This is a hack to write a GIF89a instead of GIF87a */
-        /* (we have to, since we are using graphical extension block) */
-        /* EGifSpew would write GIF89a when it detects an extension block if we were using it */
-        /* As we don't, we could have used EGifSetGifVersion instead, but the version of libungif */
-        /* in GDAL has a bug : it writes on read-only memory ! */
-        /* (this is a well-known problem. Just google for "EGifSetGifVersion segfault") */
-        /* Most readers don't even care if it is GIF87a or GIF89a, but it is */
-        /* better to write the right version */
-
-        size_t nRet = VSIFWriteL("GIF89a", 1, 6, fp);
-        nRet += VSIFWriteL( (char *) pabyBuffer + 6, 1, nBytesToWrite - 6, fp );
-        return static_cast<int>(nRet);
-    }
-    else
-        return static_cast<int>(VSIFWriteL( (void *) pabyBuffer, 1, nBytesToWrite, fp ));
-}
-
-/************************************************************************/
 /*                          GDALRegister_GIF()                          */
 /************************************************************************/
 
@@ -703,11 +714,12 @@ void GDALRegister_GIF()
     poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/gif" );
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-"<CreationOptionList>\n"
-"   <Option name='INTERLACING' type='boolean'/>\n"
-"   <Option name='WORLDFILE' type='boolean'/>\n"
-"</CreationOptionList>\n" );
+    poDriver->SetMetadataItem(
+        GDAL_DMD_CREATIONOPTIONLIST,
+        "<CreationOptionList>\n"
+        "   <Option name='INTERLACING' type='boolean'/>\n"
+        "   <Option name='WORLDFILE' type='boolean'/>\n"
+        "</CreationOptionList>\n" );
 
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
diff --git a/frmts/gif/giflib/dgif_lib.c b/frmts/gif/giflib/dgif_lib.c
index 7e591b9..af933d7 100644
--- a/frmts/gif/giflib/dgif_lib.c
+++ b/frmts/gif/giflib/dgif_lib.c
@@ -10,6 +10,12 @@
 *  3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
 ******************************************************************************/
 
+#if defined(__sun__) && __STDC_VERSION__ >= 201112L && _XOPEN_SOURCE < 600
+#ifdef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE
+#endif
+#define _XOPEN_SOURCE 600
+#endif
 
 #if (defined(_MSC_VER) || defined(__MSDOS__)) && !defined(__DJGPP__) && !defined(__GNUC__)
 #  include <io.h>
@@ -23,7 +29,7 @@
 #  include <sys/stat.h>
 #endif /* _MSC_VER || __MSDOS__ */
 
-#ifdef unix
+#if defined(unix) || defined(__unix__) || defined(__sun__) || defined(__APPLE__)
 #include <unistd.h>
 #endif
 
diff --git a/frmts/gif/giflib/egif_lib.c b/frmts/gif/giflib/egif_lib.c
index f2b79c9..408b75a 100644
--- a/frmts/gif/giflib/egif_lib.c
+++ b/frmts/gif/giflib/egif_lib.c
@@ -11,6 +11,13 @@
  * 26 Jun 96 - Version 3.0 by Eric S. Raymond (Full GIF89 support)
  *****************************************************************************/
 
+#if defined(__sun__) && __STDC_VERSION__ >= 201112L && _XOPEN_SOURCE < 600
+#ifdef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE
+#endif
+#define _XOPEN_SOURCE 600
+#endif
+
 #if defined(_MSC_VER) || defined(__MSDOS__)
 #  include <io.h>
 #  include <sys\stat.h>
@@ -25,7 +32,7 @@
 #  endif
 #endif /* _MSC_VER || __MSDOS__ */
 
-#ifdef unix
+#if defined(unix) || defined(__unix__) || defined(__sun__) || defined(__APPLE__)
 #include <unistd.h>
 #endif
 
diff --git a/frmts/gif/giflib/gif_hash.h b/frmts/gif/giflib/gif_hash.h
index 545146c..bffad23 100644
--- a/frmts/gif/giflib/gif_hash.h
+++ b/frmts/gif/giflib/gif_hash.h
@@ -1,10 +1,10 @@
 /******************************************************************************
-* Declarations, global to other of the GIF-HASH.C module.		      *
-*									      *
-*					Written by Gershon Elber,  Jun 1989   *
+* Declarations, global to other of the GIF-HASH.C module.                     *
+*                                                                             *
+*                                       Written by Gershon Elber,  Jun 1989   *
 *******************************************************************************
-* History:								      *
-* 14 Jun 89 - Version 1.0 by Gershon Elber.				      *
+* History:                                                                    *
+* 14 Jun 89 - Version 1.0 by Gershon Elber.                                   *
 ******************************************************************************/
 
 #ifndef GIF_HASH_H_
@@ -32,20 +32,20 @@
 #include <basetsd.h>
 #endif
 
-#define HT_SIZE			8192	   /* 12bits = 4096 or twice as big! */
-#define HT_KEY_MASK		0x1FFF			      /* 13bits keys */
-#define HT_KEY_NUM_BITS		13			      /* 13bits keys */
-#define HT_MAX_KEY		8191	/* 13bits - 1, maximal code possible */
-#define HT_MAX_CODE		4095	/* Biggest code possible in 12 bits. */
+#define HT_SIZE                 8192       /* 12bits = 4096 or twice as big! */
+#define HT_KEY_MASK             0x1FFF                        /* 13bits keys */
+#define HT_KEY_NUM_BITS         13                            /* 13bits keys */
+#define HT_MAX_KEY              8191    /* 13bits - 1, maximal code possible */
+#define HT_MAX_CODE             4095    /* Biggest code possible in 12 bits. */
 
 /* The 32 bits of the long are divided into two parts for the key & code:   */
 /* 1. The code is 12 bits as our compression algorithm is limited to 12bits */
-/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits.	    */
+/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits.           */
 /* The key is the upper 20 bits.  The code is the lower 12. */
-#define HT_GET_KEY(l)	(l >> 12)
-#define HT_GET_CODE(l)	(l & 0x0FFF)
-#define HT_PUT_KEY(l)	(l << 12)
-#define HT_PUT_CODE(l)	(l & 0x0FFF)
+#define HT_GET_KEY(l)   (l >> 12)
+#define HT_GET_CODE(l)  (l & 0x0FFF)
+#define HT_PUT_KEY(l)   (l << 12)
+#define HT_PUT_CODE(l)  (l & 0x0FFF)
 
 /* GDAL added */
 typedef unsigned int UINT32;
diff --git a/frmts/gif/giflib/gifalloc.c b/frmts/gif/giflib/gifalloc.c
index d68809a..6b67642 100644
--- a/frmts/gif/giflib/gifalloc.c
+++ b/frmts/gif/giflib/gifalloc.c
@@ -63,7 +63,8 @@ MakeMapObject(int ColorCount,
     }
 
     Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
-    if (Object->Colors == (GifColorType *) NULL) {
+    if (Object->Colors == NULL) {
+        free(Object->Colors); /* useless but make cppcheck happy */
         free(Object);
         return ((ColorMapObject *) NULL);
     }
diff --git a/frmts/grass/grass57dataset.cpp b/frmts/grass/grass57dataset.cpp
index f7442d4..fc9e926 100644
--- a/frmts/grass/grass57dataset.cpp
+++ b/frmts/grass/grass57dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: grass57dataset.cpp 33893 2016-04-04 14:08:28Z rouault $
  *
  * Project:  GRASS Driver
  * Purpose:  Implement GRASS raster read/write support
@@ -52,22 +51,24 @@ extern "C" {
 #include <grass/gis.h>
 
 #if GRASS_VERSION_MAJOR  >= 7
-char *GPJ_grass_to_wkt(const struct Key_Value *,
-		       const struct Key_Value *,
-		       int, int);
+char *GPJ_grass_to_wkt( const struct Key_Value *,
+                        const struct Key_Value *,
+                        int, int );
 #else
-char *GPJ_grass_to_wkt(struct Key_Value *,
-		       struct Key_Value *,
-		       int, int);
+char *GPJ_grass_to_wkt( struct Key_Value *,
+                        struct Key_Value *,
+                        int, int );
 #endif
 }
 
 #define GRASS_MAX_COLORS 100000  // what is the right value
 
-CPL_CVSID("$Id: grass57dataset.cpp 33893 2016-04-04 14:08:28Z rouault $");
+CPL_CVSID("$Id: grass57dataset.cpp 37964 2017-04-11 18:04:50Z rouault $");
 
 #if GRASS_VERSION_MAJOR  >= 7
 #define G_get_cellhd             Rast_get_cellhd
+#define G_get_window             Rast_get_window
+#define G_set_window             Rast_set_window
 #define G_raster_map_type        Rast_map_type
 #define G_read_fp_range          Rast_read_fp_range
 #define G_get_fp_range_min_max   Rast_get_fp_range_min_max
@@ -96,7 +97,7 @@ CPL_CVSID("$Id: grass57dataset.cpp 33893 2016-04-04 14:08:28Z rouault $");
 /*                         Grass2CPLErrorHook()                         */
 /************************************************************************/
 
-int Grass2CPLErrorHook( char * pszMessage, int bFatal )
+static int Grass2CPLErrorHook( char * pszMessage, int bFatal )
 
 {
     if( !bFatal )
@@ -110,7 +111,7 @@ int Grass2CPLErrorHook( char * pszMessage, int bFatal )
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GRASSDataset				*/
+/*                              GRASSDataset                            */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -120,22 +121,22 @@ class GRASSDataset : public GDALDataset
 {
     friend class GRASSRasterBand;
 
-    char	*pszGisdbase;
-    char	*pszLocation;  /* LOCATION_NAME */
-    char	*pszElement;   /* cellhd or group */
+    char        *pszGisdbase;
+    char        *pszLocation;  /* LOCATION_NAME */
+    char        *pszElement;   /* cellhd or group */
 
     struct Cell_head sCellInfo; /* raster region */
 
-    char	*pszProjection;
+    char        *pszProjection;
 
-    double	adfGeoTransform[6];
+    double      adfGeoTransform[6];
 
   public:
                  GRASSDataset();
                  ~GRASSDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 
@@ -155,7 +156,7 @@ class GRASSRasterBand : public GDALRasterBand
 
     char        *pszCellName;
     char        *pszMapset;
-    int		hCell;
+    int         hCell;
     int         nGRSType; // GRASS raster type: CELL_TYPE, FCELL_TYPE, DCELL_TYPE
     bool        nativeNulls; // use GRASS native NULL values
 
@@ -164,11 +165,11 @@ class GRASSRasterBand : public GDALRasterBand
 
     struct Cell_head sOpenWindow; /* the region when the raster was opened */
 
-    int		bHaveMinMax;
-    double	dfCellMin;
-    double	dfCellMax;
+    int         bHaveMinMax;
+    double      dfCellMin;
+    double      dfCellMax;
 
-    double	dfNoData;
+    double      dfNoData;
 
     bool        valid;
 
@@ -178,42 +179,40 @@ class GRASSRasterBand : public GDALRasterBand
                                     const char *, const char * );
     virtual        ~GRASSRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
     virtual CPLErr IRasterIO ( GDALRWFlag, int, int, int, int, void *, int, int, GDALDataType,
                                GSpacing nPixelSpace,
                                GSpacing nLineSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum( int *pbSuccess = NULL );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
+                               GDALRasterIOExtraArg* psExtraArg) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum( int *pbSuccess = NULL ) override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 
   private:
     CPLErr ResetReading( struct Cell_head * );
-
 };
 
-
 /************************************************************************/
 /*                          GRASSRasterBand()                           */
 /************************************************************************/
 
-GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
-                                  const char * pszMapset,
-                                  const char * pszCellName )
+GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDSIn, int nBandIn,
+                                  const char * pszMapsetIn,
+                                  const char * pszCellNameIn )
 
 {
-    struct Cell_head	sCellInfo;
+    struct Cell_head sCellInfo;
 
     // Note: GISDBASE, LOCATION_NAME ans MAPSET was set in GRASSDataset::Open
 
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
     this->valid = false;
 
-    this->pszCellName = G_store ( (char *) pszCellName );
-    this->pszMapset = G_store ( (char *) pszMapset );
+    this->pszCellName = G_store ( (char *) pszCellNameIn );
+    this->pszMapset = G_store ( (char *) pszMapsetIn );
 
     G_get_cellhd( (char *) pszCellName, (char *) pszMapset, &sCellInfo );
     nGRSType = G_raster_map_type( (char *) pszCellName, (char *) pszMapset );
@@ -244,66 +243,66 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
     // full raster values range is used -> no checks if shorter type could be used
 
     if( nGRSType == CELL_TYPE ) {
-	if ( sCellInfo.format == 0 ) {  // 1 byte / cell -> possible range 0,255
-	    if ( bHaveMinMax && dfCellMin > 0 ) {
+        if ( sCellInfo.format == 0 ) {  // 1 byte / cell -> possible range 0,255
+            if ( bHaveMinMax && dfCellMin > 0 ) {
                 this->eDataType = GDT_Byte;
-		dfNoData = 0.0;
-	    } else if ( bHaveMinMax && dfCellMax < 255 ) {
+                dfNoData = 0.0;
+            } else if ( bHaveMinMax && dfCellMax < 255 ) {
                 this->eDataType = GDT_Byte;
-		dfNoData = 255.0;
-	    } else { // maximum is not known or full range is used
-		this->eDataType = GDT_UInt16;
-		dfNoData = 256.0;
-	    }
-	    nativeNulls = false;
-	} else if ( sCellInfo.format == 1 ) {  // 2 bytes / cell -> possible range 0,65535
-	    if ( bHaveMinMax && dfCellMin > 0 ) {
-		this->eDataType = GDT_UInt16;
-		dfNoData = 0.0;
-	    } else if ( bHaveMinMax && dfCellMax < 65535 ) {
+                dfNoData = 255.0;
+            } else { // maximum is not known or full range is used
+                this->eDataType = GDT_UInt16;
+                dfNoData = 256.0;
+            }
+            nativeNulls = false;
+        } else if ( sCellInfo.format == 1 ) {  // 2 bytes / cell -> possible range 0,65535
+            if ( bHaveMinMax && dfCellMin > 0 ) {
+                this->eDataType = GDT_UInt16;
+                dfNoData = 0.0;
+            } else if ( bHaveMinMax && dfCellMax < 65535 ) {
                 this->eDataType = GDT_UInt16;
-		dfNoData = 65535;
-	    } else { // maximum is not known or full range is used
-		CELL cval;
-		this->eDataType = GDT_Int32;
-		G_set_c_null_value ( &cval, 1);
-		dfNoData = (double) cval;
-		nativeNulls = true;
-	    }
-	    nativeNulls = false;
-	} else {  // 3-4 bytes
-	    CELL cval;
-	    this->eDataType = GDT_Int32;
-	    G_set_c_null_value ( &cval, 1);
-	    dfNoData = (double) cval;
-	    nativeNulls = true;
-	}
+                dfNoData = 65535;
+            } else { // maximum is not known or full range is used
+                CELL cval;
+                this->eDataType = GDT_Int32;
+                G_set_c_null_value ( &cval, 1);
+                dfNoData = (double) cval;
+                nativeNulls = true;
+            }
+            nativeNulls = false;
+        } else {  // 3-4 bytes
+            CELL cval;
+            this->eDataType = GDT_Int32;
+            G_set_c_null_value ( &cval, 1);
+            dfNoData = (double) cval;
+            nativeNulls = true;
+        }
     }
     else if( nGRSType == FCELL_TYPE ) {
-	FCELL fval;
+        FCELL fval;
         this->eDataType = GDT_Float32;
-	G_set_f_null_value ( &fval, 1);
-	dfNoData = (double) fval;
-	nativeNulls = true;
+        G_set_f_null_value ( &fval, 1);
+        dfNoData = (double) fval;
+        nativeNulls = true;
     }
     else if( nGRSType == DCELL_TYPE )
     {
-	DCELL dval;
+        DCELL dval;
         this->eDataType = GDT_Float64;
-	G_set_d_null_value ( &dval, 1);
-	dfNoData = (double) dval;
-	nativeNulls = true;
+        G_set_d_null_value ( &dval, 1);
+        dfNoData = (double) dval;
+        nativeNulls = true;
     }
 
-    nBlockXSize = poDS->nRasterXSize;;
+    nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 
-    G_set_window( &(((GRASSDataset *)poDS)->sCellInfo) );
+    G_set_window( &(poDSIn->sCellInfo) );
     if ( (hCell = G_open_cell_old((char *) pszCellName, (char *) pszMapset)) < 0 ) {
-	CPLError( CE_Warning, CPLE_AppDefined, "GRASS: Cannot open raster '%s'", pszCellName );
-	return;
+        CPLError( CE_Warning, CPLE_AppDefined, "GRASS: Cannot open raster '%s'", pszCellName );
+        return;
     }
-    G_copy((void *) &sOpenWindow, (void *) &(((GRASSDataset *)poDS)->sCellInfo), sizeof(struct Cell_head));
+    G_copy((void *) &sOpenWindow, (void *) &(poDSIn->sCellInfo), sizeof(struct Cell_head));
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a color table?                                       */
@@ -311,34 +310,34 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
     poCT = NULL;
     if( G_read_colors( (char *) pszCellName, (char *) pszMapset, &sGrassColors ) == 1 )
     {
-	int maxcolor;
-	CELL min, max;
+        int maxcolor;
+        CELL min, max;
 
-	G_get_color_range ( &min, &max, &sGrassColors);
+        G_get_color_range ( &min, &max, &sGrassColors);
 
         if ( bHaveMinMax ) {
-	    if ( max < dfCellMax ) {
-	       maxcolor = max;
+            if ( max < dfCellMax ) {
+               maxcolor = max;
             } else {
-	       maxcolor = (int) ceil ( dfCellMax );
-	    }
-	    if ( maxcolor > GRASS_MAX_COLORS ) {
-		maxcolor = GRASS_MAX_COLORS;
+               maxcolor = (int) ceil ( dfCellMax );
+            }
+            if ( maxcolor > GRASS_MAX_COLORS ) {
+                maxcolor = GRASS_MAX_COLORS;
                 CPLDebug( "GRASS", "Too many values, color table cut to %d entries.", maxcolor );
-	    }
-	} else {
-	    if ( max < GRASS_MAX_COLORS ) {
-	       maxcolor = max;
+            }
+        } else {
+            if ( max < GRASS_MAX_COLORS ) {
+               maxcolor = max;
             } else {
-	       maxcolor = GRASS_MAX_COLORS;
+               maxcolor = GRASS_MAX_COLORS;
                CPLDebug( "GRASS", "Too many values, color table set to %d entries.", maxcolor );
-	    }
+            }
         }
 
         poCT = new GDALColorTable();
         for( int iColor = 0; iColor <= maxcolor; iColor++ )
         {
-            int	nRed, nGreen, nBlue;
+            int nRed, nGreen, nBlue;
             GDALColorEntry    sColor;
 
 #if GRASS_VERSION_MAJOR  >= 7
@@ -424,33 +423,32 @@ CPLErr GRASSRasterBand::ResetReading ( struct Cell_head *sNewWindow )
 
     /* Check if the window has changed */
     if ( sNewWindow->north  != sOpenWindow.north  || sNewWindow->south  != sOpenWindow.south ||
-	 sNewWindow->east   != sOpenWindow.east   || sNewWindow->west   != sOpenWindow.west ||
-	 sNewWindow->ew_res != sOpenWindow.ew_res || sNewWindow->ns_res != sOpenWindow.ns_res ||
-	 sNewWindow->rows   != sOpenWindow.rows   || sNewWindow->cols   != sOpenWindow.cols )
+         sNewWindow->east   != sOpenWindow.east   || sNewWindow->west   != sOpenWindow.west ||
+         sNewWindow->ew_res != sOpenWindow.ew_res || sNewWindow->ns_res != sOpenWindow.ns_res ||
+         sNewWindow->rows   != sOpenWindow.rows   || sNewWindow->cols   != sOpenWindow.cols )
     {
-	if( hCell >= 0 ) {
+        if( hCell >= 0 ) {
             G_close_cell( hCell );
-	    hCell = -1;
-	}
+            hCell = -1;
+        }
 
-	/* Set window */
-	G_set_window( sNewWindow );
+        /* Set window */
+        G_set_window( sNewWindow );
 
-	/* Open raster */
-	G__setenv( "GISDBASE", ((GRASSDataset *)poDS)->pszGisdbase );
-	G__setenv( "LOCATION_NAME", ((GRASSDataset *)poDS)->pszLocation );
-	G__setenv( "MAPSET", pszMapset);
-	G_reset_mapsets();
-	G_add_mapset_to_search_path ( pszMapset );
+        /* Open raster */
+        G__setenv( "GISDBASE", ((GRASSDataset *)poDS)->pszGisdbase );
+        G__setenv( "LOCATION_NAME", ((GRASSDataset *)poDS)->pszLocation );
+        G__setenv( "MAPSET", pszMapset);
+        G_reset_mapsets();
+        G_add_mapset_to_search_path ( pszMapset );
 
-	if ( (hCell = G_open_cell_old( pszCellName, pszMapset)) < 0 ) {
-	    CPLError( CE_Warning, CPLE_AppDefined, "GRASS: Cannot open raster '%s'", pszCellName );
+        if ( (hCell = G_open_cell_old( pszCellName, pszMapset)) < 0 ) {
+            CPLError( CE_Warning, CPLE_AppDefined, "GRASS: Cannot open raster '%s'", pszCellName );
             this->valid = false;
-	    return CE_Failure;
-	}
-
-	G_copy((void *) &sOpenWindow, (void *) sNewWindow, sizeof(struct Cell_head));
+            return CE_Failure;
+        }
 
+        G_copy((void *) &sOpenWindow, (void *) sNewWindow, sizeof(struct Cell_head));
     }
     else
     {
@@ -470,7 +468,6 @@ CPLErr GRASSRasterBand::ResetReading ( struct Cell_head *sNewWindow )
         }
     }
 
-
     return CE_None;
 }
 
@@ -479,7 +476,7 @@ CPLErr GRASSRasterBand::ResetReading ( struct Cell_head *sNewWindow )
 /*                                                                      */
 /************************************************************************/
 
-CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+CPLErr GRASSRasterBand::IReadBlock( int /*nBlockXOff*/, int nBlockYOff,
                                     void *pImage )
 
 {
@@ -491,29 +488,32 @@ CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     }
 
     if ( eDataType == GDT_Byte || eDataType == GDT_UInt16 ) {
-        CELL  *cbuf;
-
-	cbuf = G_allocate_c_raster_buf();
-	G_get_c_raster_row ( hCell, cbuf, nBlockYOff );
-
-	/* Reset NULLs */
-	for ( int col = 0; col < nBlockXSize; col++ ) {
-	    if ( G_is_c_null_value(&(cbuf[col])) )
-		cbuf[col] = (CELL) dfNoData;
-	}
+        CELL *cbuf = G_allocate_c_raster_buf();
+        G_get_c_raster_row ( hCell, cbuf, nBlockYOff );
 
-	GDALCopyWords ( (void *) cbuf, GDT_Int32, sizeof(CELL),
-	                pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
-			nBlockXSize );
+        /* Reset NULLs */
+        for ( int col = 0; col < nBlockXSize; col++ ) {
+            if ( G_is_c_null_value(&(cbuf[col])) )
+                cbuf[col] = (CELL) dfNoData;
+        }
 
-	G_free ( cbuf );
+        GDALCopyWords ( (void *) cbuf, GDT_Int32, sizeof(CELL),
+                        pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
+                        nBlockXSize );
 
-    } else if ( eDataType == GDT_Int32 ) {
-	G_get_c_raster_row ( hCell, (CELL *) pImage, nBlockYOff );
-    } else if ( eDataType == GDT_Float32 ) {
-	G_get_f_raster_row ( hCell, (FCELL *) pImage, nBlockYOff );
-    } else if ( eDataType == GDT_Float64 ) {
-	G_get_d_raster_row ( hCell, (DCELL *) pImage, nBlockYOff );
+        G_free ( cbuf );
+    }
+    else if ( eDataType == GDT_Int32 )
+    {
+        G_get_c_raster_row ( hCell, (CELL *) pImage, nBlockYOff );
+    }
+    else if ( eDataType == GDT_Float32 )
+    {
+        G_get_f_raster_row ( hCell, (FCELL *) pImage, nBlockYOff );
+    }
+    else if ( eDataType == GDT_Float64 )
+    {
+        G_get_d_raster_row ( hCell, (DCELL *) pImage, nBlockYOff );
     }
 
     return CE_None;
@@ -525,12 +525,12 @@ CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr GRASSRasterBand::IRasterIO ( GDALRWFlag eRWFlag,
-	                           int nXOff, int nYOff, int nXSize, int nYSize,
-				   void * pData, int nBufXSize, int nBufYSize,
-				   GDALDataType eBufType,
-				   GSpacing nPixelSpace,
-                   GSpacing nLineSpace,
-                   GDALRasterIOExtraArg* psExtraArg )
+                                   int nXOff, int nYOff, int nXSize, int nYSize,
+                                   void * pData, int nBufXSize, int nBufYSize,
+                                   GDALDataType eBufType,
+                                   GSpacing nPixelSpace,
+                                    GSpacing nLineSpace,
+                                    GDALRasterIOExtraArg* /*psExtraArg*/ )
 {
     /* GRASS library does that, we have only calculate and reset the region in map units
      * and if the region has changed, reopen the raster */
@@ -539,6 +539,7 @@ CPLErr GRASSRasterBand::IRasterIO ( GDALRWFlag eRWFlag,
     struct Cell_head sWindow;
     struct Cell_head *psDsWindow;
 
+    if( eRWFlag != GF_Read ) return CE_Failure;
     if ( ! this->valid ) return CE_Failure;
 
     psDsWindow = &(((GRASSDataset *)poDS)->sCellInfo);
@@ -569,63 +570,63 @@ CPLErr GRASSRasterBand::IRasterIO ( GDALRWFlag eRWFlag,
 
     /* Reset space if default (0) */
     if ( nPixelSpace == 0 )
-	nPixelSpace = GDALGetDataTypeSize ( eBufType ) / 8;
+        nPixelSpace = GDALGetDataTypeSize ( eBufType ) / 8;
 
     if ( nLineSpace == 0 )
-	nLineSpace = nBufXSize * nPixelSpace;
+        nLineSpace = nBufXSize * nPixelSpace;
 
     if ( nGRSType == CELL_TYPE && ( !nativeNulls || eBufType != GDT_Int32 || sizeof(CELL) != 4 ||
-		                    nPixelSpace != sizeof(CELL) )  )
+                                    nPixelSpace != sizeof(CELL) )  )
     {
-	cbuf = G_allocate_c_raster_buf();
+        cbuf = G_allocate_c_raster_buf();
     } else if( nGRSType == FCELL_TYPE && ( eBufType != GDT_Float32 || nPixelSpace != sizeof(FCELL) ) ) {
-	fbuf = G_allocate_f_raster_buf();
+        fbuf = G_allocate_f_raster_buf();
     } else if( nGRSType == DCELL_TYPE && ( eBufType != GDT_Float64 || nPixelSpace != sizeof(DCELL) ) ) {
-	dbuf = G_allocate_d_raster_buf();
+        dbuf = G_allocate_d_raster_buf();
     } else {
-	direct = true;
+        direct = true;
     }
 
     for ( int row = 0; row < nBufYSize; row++ ) {
         char *pnt = (char *)pData + row * nLineSpace;
 
-	if ( nGRSType == CELL_TYPE ) {
-	    if ( direct ) {
-		G_get_c_raster_row ( hCell, (CELL *) pnt, row );
-	    } else {
-		G_get_c_raster_row ( hCell, cbuf, row );
-
-		/* Reset NULLs */
-		for ( int col = 0; col < nBufXSize; col++ ) {
-		    if ( G_is_c_null_value(&(cbuf[col])) )
-			cbuf[col] = (CELL) dfNoData;
-		}
-
-		GDALCopyWords ( (void *) cbuf, GDT_Int32, sizeof(CELL),
-			        (void *)  pnt,  eBufType, nPixelSpace,
-				nBufXSize );
-	    }
-	} else if( nGRSType == FCELL_TYPE ) {
-	    if ( direct ) {
-		G_get_f_raster_row ( hCell, (FCELL *) pnt, row );
-	    } else {
-		G_get_f_raster_row ( hCell, fbuf, row );
-
-		GDALCopyWords ( (void *) fbuf, GDT_Float32, sizeof(FCELL),
-			        (void *)  pnt,  eBufType, nPixelSpace,
-				nBufXSize );
-	    }
-	} else if( nGRSType == DCELL_TYPE ) {
-	    if ( direct ) {
-		G_get_d_raster_row ( hCell, (DCELL *) pnt, row );
-	    } else {
-		G_get_d_raster_row ( hCell, dbuf, row );
-
-		GDALCopyWords ( (void *) dbuf, GDT_Float64, sizeof(DCELL),
-			        (void *)  pnt,  eBufType, nPixelSpace,
-				nBufXSize );
-	    }
-	}
+        if ( nGRSType == CELL_TYPE ) {
+            if ( direct ) {
+                G_get_c_raster_row ( hCell, (CELL *) pnt, row );
+            } else {
+                G_get_c_raster_row ( hCell, cbuf, row );
+
+                /* Reset NULLs */
+                for ( int col = 0; col < nBufXSize; col++ ) {
+                    if ( G_is_c_null_value(&(cbuf[col])) )
+                        cbuf[col] = (CELL) dfNoData;
+                }
+
+                GDALCopyWords ( (void *) cbuf, GDT_Int32, sizeof(CELL),
+                                (void *)  pnt,  eBufType, nPixelSpace,
+                                nBufXSize );
+            }
+        } else if( nGRSType == FCELL_TYPE ) {
+            if ( direct ) {
+                G_get_f_raster_row ( hCell, (FCELL *) pnt, row );
+            } else {
+                G_get_f_raster_row ( hCell, fbuf, row );
+
+                GDALCopyWords ( (void *) fbuf, GDT_Float32, sizeof(FCELL),
+                                (void *)  pnt,  eBufType, nPixelSpace,
+                                nBufXSize );
+            }
+        } else if( nGRSType == DCELL_TYPE ) {
+            if ( direct ) {
+                G_get_d_raster_row ( hCell, (DCELL *) pnt, row );
+            } else {
+                G_get_d_raster_row ( hCell, dbuf, row );
+
+                GDALCopyWords ( (void *) dbuf, GDT_Float64, sizeof(DCELL),
+                                (void *)  pnt,  eBufType, nPixelSpace,
+                                nBufXSize );
+            }
+        }
     }
 
     if ( cbuf ) G_free ( cbuf );
@@ -719,7 +720,6 @@ double GRASSRasterBand::GetNoDataValue( int *pbSuccess )
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            GRASSDataset()                            */
 /************************************************************************/
@@ -734,6 +734,9 @@ GRASSDataset::GRASSDataset()
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+    pszGisdbase = NULL;
+    pszLocation = NULL;
+    pszElement = NULL;
 }
 
 /************************************************************************/
@@ -744,13 +747,13 @@ GRASSDataset::~GRASSDataset()
 {
 
     if ( pszGisdbase )
-	G_free ( pszGisdbase );
+        G_free ( pszGisdbase );
 
     if ( pszLocation )
         G_free ( pszLocation );
 
     if ( pszElement )
-	G_free ( pszElement );
+        G_free ( pszElement );
 
     G_free( pszProjection );
 }
@@ -788,31 +791,37 @@ CPLErr GRASSDataset::GetGeoTransform( double * padfGeoTransform )
 /*          false - failed                                              */
 /************************************************************************/
 bool GRASSDataset::SplitPath( char *path, char **gisdbase, char **location,
-	                      char **mapset, char **element, char **name )
+                              char **mapset, char **element, char **name )
 {
-    char *p, *ptr[5], *tmp;
-    int  i = 0;
+    char *p;
+    char *ptr[5];
+    char *tmp;
+    int i = 0;
 
-    *gisdbase = *location = *mapset = *element = *name = NULL;
+    *gisdbase = NULL;
+    *location = NULL;
+    *mapset = NULL;
+    *element = NULL;
+    *name = NULL;
 
     if ( !path || strlen(path) == 0 )
-	return false;
+        return false;
 
     tmp = G_store ( path );
 
     while ( (p = strrchr(tmp,'/')) != NULL  && i < 4 ) {
-	*p = '\0';
+        *p = '\0';
 
-	if ( strlen(p+1) == 0 ) /* repeated '/' */
-	    continue;
+        if ( strlen(p+1) == 0 ) /* repeated '/' */
+            continue;
 
-	ptr[i++] = p+1;
+        ptr[i++] = p+1;
     }
 
     /* Note: empty GISDBASE == 0 is not accepted (relative path) */
     if ( i != 4 ) {
         G_free ( tmp );
-	return false;
+        return false;
     }
 
     *gisdbase = G_store ( tmp );
@@ -838,8 +847,8 @@ typedef int (*GrassErrorHandler)(char *, int);
 GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    char	*pszGisdb = NULL, *pszLoc = NULL;
-    char	*pszMapset = NULL, *pszElem = NULL, *pszName = NULL;
+    char        *pszGisdb = NULL, *pszLoc = NULL;
+    char        *pszMapset = NULL, *pszElem = NULL, *pszName = NULL;
     char        **papszCells = NULL;
     char        **papszMapsets = NULL;
 
@@ -862,7 +871,6 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
     // Set error function
     G_set_error_routine ( (GrassErrorHandler) Grass2CPLErrorHook );
 
-
     // GISBASE is path to the directory where GRASS is installed,
     if ( !getenv( "GISBASE" ) ) {
         static char* gisbaseEnv = NULL;
@@ -880,19 +888,19 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if ( !SplitPath( poOpenInfo->pszFilename, &pszGisdb, &pszLoc, &pszMapset,
                      &pszElem, &pszName) ) {
-	return NULL;
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Check element name                                              */
 /* -------------------------------------------------------------------- */
     if ( strcmp(pszElem,"cellhd") != 0 && strcmp(pszElem,"group") != 0 ) {
-	G_free(pszGisdb);
+        G_free(pszGisdb);
         G_free(pszLoc);
         G_free(pszMapset);
         G_free(pszElem);
         G_free(pszName);
-	return NULL;
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -911,12 +919,12 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
     if ( strcmp(pszElem,"cellhd") == 0 ) {
 
         if ( G_find_file2("cell", pszName, pszMapset) == NULL ) {
-	    G_free(pszGisdb); G_free(pszLoc); G_free(pszMapset); G_free(pszElem); G_free(pszName);
-	    return NULL;
-	}
+            G_free(pszGisdb); G_free(pszLoc); G_free(pszMapset); G_free(pszElem); G_free(pszName);
+            return NULL;
+        }
 
-	papszMapsets = CSLAddString( papszMapsets, pszMapset );
-	papszCells = CSLAddString( papszCells, pszName );
+        papszMapsets = CSLAddString( papszMapsets, pszMapset );
+        papszCells = CSLAddString( papszCells, pszName );
     }
 /* -------------------------------------------------------------------- */
 /*      Check if this is a valid GRASS imagery group.                   */
@@ -926,12 +934,12 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 
         I_init_group_ref( &ref );
         if ( I_get_group_ref( pszName, &ref ) == 0 ) {
-	    G_free(pszGisdb); G_free(pszLoc); G_free(pszMapset); G_free(pszElem); G_free(pszName);
-	    return NULL;
-	}
+            G_free(pszGisdb); G_free(pszLoc); G_free(pszMapset); G_free(pszElem); G_free(pszName);
+            return NULL;
+        }
 
         for( int iRef = 0; iRef < ref.nfiles; iRef++ )
-	{
+        {
             papszCells = CSLAddString( papszCells, ref.file[iRef].name );
             papszMapsets = CSLAddString( papszMapsets, ref.file[iRef].mapset );
             G_add_mapset_to_search_path ( ref.file[iRef].mapset );
@@ -946,9 +954,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GRASSDataset 	*poDS;
-
-    poDS = new GRASSDataset();
+    GRASSDataset*poDS = new GRASSDataset();
 
     /* notdef: should only allow read access to an existing cell, right? */
     poDS->eAccess = poOpenInfo->eAccess;
@@ -997,14 +1003,14 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     for( int iBand = 0; papszCells[iBand] != NULL; iBand++ )
     {
-	GRASSRasterBand *rb = new GRASSRasterBand( poDS, iBand+1, papszMapsets[iBand],
+        GRASSRasterBand *rb = new GRASSRasterBand( poDS, iBand+1, papszMapsets[iBand],
                                                                   papszCells[iBand] );
 
-	if ( !rb->valid ) {
-	    CPLError( CE_Warning, CPLE_AppDefined, "GRASS: Cannot open raster band %d", iBand);
-	    delete rb;
-	    delete poDS;
-	    return NULL;
+        if ( !rb->valid ) {
+            CPLError( CE_Warning, CPLE_AppDefined, "GRASS: Cannot open raster band %d", iBand);
+            delete rb;
+            delete poDS;
+            return NULL;
         }
 
         poDS->SetBand( iBand+1, rb );
diff --git a/frmts/grass/grassdataset.cpp b/frmts/grass/grassdataset.cpp
index 6503f3e..b7b3441 100644
--- a/frmts/grass/grassdataset.cpp
+++ b/frmts/grass/grassdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: grassdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GRASS Driver
  * Purpose:  Implement GRASS raster read/write support
@@ -35,7 +34,7 @@
 #include "gdal_priv.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: grassdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: grassdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /*                         Grass2CPLErrorHook()                         */
@@ -54,7 +53,7 @@ int Grass2CPLErrorHook( char * pszMessage, int bFatal )
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GRASSDataset				*/
+/*                              GRASSDataset                            */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -64,16 +63,16 @@ class GRASSDataset : public GDALDataset
 {
     friend class GRASSRasterBand;
 
-    char	*pszProjection;
+    char        *pszProjection;
 
-    double	adfGeoTransform[6];
+    double      adfGeoTransform[6];
 
   public:
                  GRASSDataset();
                  ~GRASSDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -88,16 +87,16 @@ class GRASSRasterBand : public GDALRasterBand
 {
     friend class GRASSDataset;
 
-    int		hCell;
+    int         hCell;
     int         nGRSType;
 
     GDALColorTable *poCT;
 
-    int		bHaveMinMax;
-    double	dfCellMin;
-    double	dfCellMax;
+    int         bHaveMinMax;
+    double      dfCellMin;
+    double      dfCellMax;
 
-    double	dfNoData;
+    double      dfNoData;
 
   public:
 
@@ -105,15 +104,14 @@ class GRASSRasterBand : public GDALRasterBand
                                     const char *, const char * );
     virtual        ~GRASSRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum( int *pbSuccess = NULL );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum( int *pbSuccess = NULL ) override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 };
 
-
 /************************************************************************/
 /*                          GRASSRasterBand()                           */
 /************************************************************************/
@@ -123,7 +121,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
                                   const char * pszCellName )
 
 {
-    struct Cell_head	sCellInfo;
+    struct Cell_head sCellInfo;
 
     this->poDS = poDS;
     this->nBand = nBand;
@@ -188,7 +186,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
         dfNoData = -12345.0;
     }
 
-    nBlockXSize = poDS->nRasterXSize;;
+    nBlockXSize = poDS->nRasterXSize;
     nBlockYSize = 1;
 
     hCell = G_open_cell_old((char *) pszCellName, (char *) pszMapset);
@@ -205,7 +203,7 @@ GRASSRasterBand::GRASSRasterBand( GRASSDataset *poDS, int nBand,
         poCT = new GDALColorTable();
         for( int iColor = 0; iColor < 256; iColor++ )
         {
-            int	nRed, nGreen, nBlue;
+            int nRed, nGreen, nBlue;
             GDALColorEntry    sColor;
 
             if( G_get_color( iColor, &nRed, &nGreen, &nBlue, &sGrassColors ) )
@@ -246,7 +244,6 @@ GRASSRasterBand::~GRASSRasterBand()
         G_close_cell( hCell );
 }
 
-
 /************************************************************************/
 /*                             IReadBlock()                             */
 /*                                                                      */
@@ -256,12 +253,10 @@ GRASSRasterBand::~GRASSRasterBand()
 /************************************************************************/
 
 CPLErr GRASSRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                  void * pImage )
+                                    void * pImage )
 
 {
-    char *pachNullBuf;
-
-    pachNullBuf = (char *) CPLMalloc(nBlockXSize);
+    char *pachNullBuf = (char *) CPLMalloc(nBlockXSize);
     G_get_null_value_row( hCell, pachNullBuf, nBlockYOff );
 
     if( eDataType == GDT_Float32 || eDataType == GDT_Float64
@@ -390,7 +385,6 @@ double GRASSRasterBand::GetNoDataValue( int *pbSuccess )
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            GRASSDataset()                            */
 /************************************************************************/
@@ -450,8 +444,8 @@ typedef int (*GrassErrorHandler)();
 GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    static int	bDoneGISInit = FALSE;
-    char	*pszMapset = NULL, *pszCell = NULL;
+    static int  bDoneGISInit = FALSE;
+    char        *pszMapset = NULL, *pszCell = NULL;
     char        **papszCells = NULL;
     char        **papszMapsets = NULL;
 
@@ -501,9 +495,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GRASSDataset 	*poDS;
-
-    poDS = new GRASSDataset();
+    GRASSDataset *poDS = new GRASSDataset();
 
     /* notdef: should only allow read access to an existing cell, right? */
     poDS->eAccess = poOpenInfo->eAccess;
@@ -511,7 +503,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
-    struct Cell_head	sCellInfo;
+    struct Cell_head sCellInfo;
 
     if( G_get_cellhd( papszCells[0], papszMapsets[0], &sCellInfo ) != 0 )
     {
@@ -534,9 +526,7 @@ GDALDataset *GRASSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try to get a projection definition.                             */
 /* -------------------------------------------------------------------- */
-    char	*pszProj4;
-
-    pszProj4 = G_get_cell_as_proj4( papszCells[0], papszMapsets[0] );
+    char *pszProj4 = G_get_cell_as_proj4( papszCells[0], papszMapsets[0] );
     if( pszProj4 != NULL )
     {
         OGRSpatialReference   oSRS;
diff --git a/frmts/grass/pkg/README b/frmts/grass/pkg/README
index cd545cd..dfd9f44 100644
--- a/frmts/grass/pkg/README
+++ b/frmts/grass/pkg/README
@@ -2,11 +2,11 @@ Standalone GRASS Drivers for GDAL and OGR
 =========================================
 
 This package contains standalone drivers for GRASS raster and vector
-files that can be built after GDAL has been built and installed as an 
-"autoload" driver.  
+files that can be built after GDAL has been built and installed as an
+"autoload" driver.
 
 This is particularly useful in resolving problems with GRASS depending
-on GDAL, but GDAL with GRASS support depending on GRASS.  With this 
+on GDAL, but GDAL with GRASS support depending on GRASS.  With this
 package you can configure and install GDAL normally (--without-grass), then
 build and install GRASS normally and finally build and install this driver.
 
@@ -52,12 +52,12 @@ libraries not found?
 
 Answer:
 
-Your problem is likely to be solved by editing /etc/ld.so.conf to 
-include the locations of proj, gdal, grass, and geos. Specifically, 
-the full path to both gdal-config and geos-config, and the full paths 
+Your problem is likely to be solved by editing /etc/ld.so.conf to
+include the locations of proj, gdal, grass, and geos. Specifically,
+the full path to both gdal-config and geos-config, and the full paths
 to the library locations of proj (often /usr/local/lib) and grass (/
-usr/local/grass-6.0.1/lib). After editing ld.so.conf, run ldconfig, 
+usr/local/grass-6.0.1/lib). After editing ld.so.conf, run ldconfig,
 and you should be good to go.
 
-I ran into this problem this weekend (and posted for help to this 
-list), so it seems to be a pretty common issue. 
+I ran into this problem this weekend (and posted for help to this
+list), so it seems to be a pretty common issue.
diff --git a/frmts/grass/pkg/aclocal.m4 b/frmts/grass/pkg/aclocal.m4
index 7bffcf4..ec692bd 100644
--- a/frmts/grass/pkg/aclocal.m4
+++ b/frmts/grass/pkg/aclocal.m4
@@ -6,14 +6,14 @@ AC_DEFUN(AC_COMPILER_LOCALHACK,
   echo 'int main() { int i = 1; if( *((unsigned char *) &i) == 0 ) printf( "BIGENDIAN"); return 0; }' >> conftest.c
   ${CC} $CPPFLAGS $EXTRA_INCLUDES -o conftest conftest.c 2> comp.out
   COMP_CHECK=`grep "system directory" comp.out | grep /usr/local/include`
-  if test -z "$COMP_CHECK" ; then 
+  if test -z "$COMP_CHECK" ; then
      AC_MSG_RESULT([no, everything is ok])
   else
      AC_MSG_RESULT([yes, stripping extras])
      CXXFLAGS=`echo "$CXXFLAGS " | sed "s/-I\/usr\/local\/include //"`
      CFLAGS=`echo "$CFLAGS " | sed "s/-I\/usr\/local\/include //"`
      EXTRA_INCLUDES=`echo "$EXTRA_INCLUDES " | sed "s/-I\/usr\/local\/include //"`
-  fi 
+  fi
   rm -f comp.out
 ])
 
@@ -61,7 +61,7 @@ AC_DEFUN(AC_COMPILER_PIC,
 dnl
 dnl Try to find something to link shared libraries with.  Use "c++ -shared"
 dnl in preference to "ld -shared" because it will link in required c++
-dnl run time support for us. 
+dnl run time support for us.
 dnl
 AC_DEFUN(AC_LD_SHARED,
 [
@@ -84,9 +84,9 @@ AC_DEFUN(AC_LD_SHARED,
 
   if test "$with_ld_shared" != "" ; then
     if test "$with_ld_shared" = "no" ; then
-      echo "user disabled shared library support."	
+      echo "user disabled shared library support."
     else
-      echo "using user supplied .so link command ... $with_ld_shared"	
+      echo "using user supplied .so link command ... $with_ld_shared"
     fi
     LD_SHARED="$with_ld_shared"
   fi
@@ -113,7 +113,7 @@ AC_DEFUN(AC_LD_SHARED,
     fi
   fi
 
-  dnl Test special MacOS (Darwin) case. 
+  dnl Test special MacOS (Darwin) case.
 
   if test ! -z "`uname | grep Darwin`" \
           -a "$LD_SHARED" = "/bin/true" \
@@ -157,7 +157,7 @@ AC_DEFUN(AC_LD_SHARED,
     else
       echo "checking for ${CXX} -shared ... no(2)"
     fi
-  else 
+  else
     if test "$LD_SHARED" = "/bin/true" ; then
       echo "checking for ${CXX} -shared ... no(1)"
     fi
@@ -195,7 +195,7 @@ AC_DEFUN(AC_LD_SHARED,
     fi
   fi
 
-  rm -f conftest* libconftest* 
+  rm -f conftest* libconftest*
 
   AC_SUBST(LD_SHARED,$LD_SHARED)
   AC_SUBST(SO_EXT,$SO_EXT)
diff --git a/frmts/grass/pkg/configure.in b/frmts/grass/pkg/configure.in
index ff96173..c9bf951 100644
--- a/frmts/grass/pkg/configure.in
+++ b/frmts/grass/pkg/configure.in
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: configure.in 37161 2017-01-17 07:34:30Z rouault $
+dnl $Id: configure.in 37160 2017-01-17 07:34:22Z rouault $
 dnl
 dnl Project:  GDAL GRASS Plugin
 dnl Purpose:  Configure source file.
diff --git a/frmts/grib/GNUmakefile b/frmts/grib/GNUmakefile
index 65fec6a..cd0b260 100644
--- a/frmts/grib/GNUmakefile
+++ b/frmts/grib/GNUmakefile
@@ -10,8 +10,17 @@ OBJ	=	gribdataset.o \
                 degrib2.o inventory.o metaname.o myerror.o tdlpack.o filedatasource.o memorydatasource.o grib1tab.o myutil.o metaparse.o weather.o metaprint.o engribapi.o grib2api.o myassert.o scan.o memendian.o fileendian.o gridtemplates.o drstemplates.o pdstemplates.o gbits.o g2_free.o g2_unpack1.o g2_unpack2.o g2_unpack3.o g2_unpack4.o g2_unpack5.o g2_unpack6.o g2_unpack7.o g2_info.o g2_getfld.o simunpack.o comunpack.o pack_gp.o reduce.o specpack.o specunpack.o rdieee.o mkieee.o int_p [...]
 		dec_jpeg2000.o jpcunpack.o jpcpack.o enc_jpeg2000.o
 
-ifeq ($(HAVE_JASPER),yes)
-EXTRAFLAGS	:= 	$(EXTRAFLAGS) -DHAVE_JASPER
+ifeq ($(PNG_SETTING),internal)
+EXTRAFLAGS      :=      $(EXTRAFLAGS) -I../png/libpng -DUSE_PNG
+ifeq ($(LIBZ_SETTING),internal)
+EXTRAFLAGS      :=      $(EXTRAFLAGS) -I../zlib
+endif
+OBJ     :=      $(OBJ) pngpack.o pngunpack.o enc_png.o dec_png.o
+endif
+
+ifeq ($(PNG_SETTING),external)
+EXTRAFLAGS      :=      $(EXTRAFLAGS) -DUSE_PNG
+OBJ     :=      $(OBJ) pngpack.o pngunpack.o enc_png.o dec_png.o
 endif
 
 CPPFLAGS	:=	 $(CPPFLAGS) $(EXTRAFLAGS)
diff --git a/frmts/grib/degrib18/degrib/clock.c b/frmts/grib/degrib18/degrib/clock.c
index 880348d..3786ae2 100644
--- a/frmts/grib/degrib18/degrib/clock.c
+++ b/frmts/grib/degrib18/degrib/clock.c
@@ -652,7 +652,7 @@ static void Clock_FormatParse (char buffer[SIZEOF_BUFFER], sInt4 sec, float floa
          strcat (buffer, temp);
          return;
 
-         /* If the current day is a federal holiday, then return a pointer to 
+         /* If the current day is a federal holiday, then return a pointer to
           * the appropriate holiday string (e.g., "Martin Luther King Day") */
       case 'v':
          /* Clock_FormatParse 'd' */
@@ -967,7 +967,7 @@ void Clock_Print (char *buffer, int n, double l_clock, const char *format,
             j++;
             buffer[j] = '\0';
          } else {
-            Clock_FormatParse (locBuff, sec, floatSec, totDay, year, month,
+            Clock_FormatParse (locBuff, sec, (float)floatSec, totDay, year, month,
                                day, format[i]);
             buffer[j] = '\0';
             strncat (buffer, locBuff, n - j);
@@ -1053,7 +1053,7 @@ void Clock_Print2 (char *buffer, int n, double l_clock, char *format,
             j++;
             buffer[j] = '\0';
          } else {
-            Clock_FormatParse (locBuff, sec, floatSec, totDay, year, month,
+            Clock_FormatParse (locBuff, sec, (float)floatSec, totDay, year, month,
                                day, format[i]);
             buffer[j] = '\0';
             strncat (buffer, locBuff, n - j);
@@ -1455,6 +1455,8 @@ void Clock_PrintMonth (int mon, char *buffer, CPL_UNUSED int buffLen)
  * NOTES
  *****************************************************************************
  */
+
+#if 0  // Unused with GDAL.
 static int Clock_ScanWeekday (char *ptr)
 {
    switch (*ptr) {
@@ -1487,6 +1489,7 @@ static int Clock_ScanWeekday (char *ptr)
    }
    return -1;
 }
+#endif
 
 /*****************************************************************************
  * Clock_ScanColon() --
@@ -1511,6 +1514,8 @@ static int Clock_ScanWeekday (char *ptr)
  * NOTES
  *****************************************************************************
  */
+
+#if 0  // Unused with GDAL.
 static double Clock_ScanColon (char *ptr)
 {
    sInt4 hour, min;
@@ -1535,6 +1540,7 @@ static double Clock_ScanColon (char *ptr)
    }
    return (sec + 60 * min + 3600 * hour);
 }
+#endif
 
 /*****************************************************************************
  * Clock_ScanSlash() --
@@ -1563,6 +1569,8 @@ static double Clock_ScanColon (char *ptr)
  * NOTES
  *****************************************************************************
  */
+
+#if 0  // Unused with GDAL.
 static int Clock_ScanSlash (char *word, int *mon, int *day, sInt4 *year,
                             char *f_year)
 {
@@ -1593,6 +1601,7 @@ static int Clock_ScanSlash (char *word, int *mon, int *day, sInt4 *year,
    }
    return 0;
 }
+#endif
 
 /* http://www.w3.org/TR/NOTE-datetime
    Year and month:
@@ -1612,6 +1621,8 @@ Example:
    US Eastern Standard Time.
 1994-11-05T13:15:30Z corresponds to the same instant.
 */
+
+#if 0  // Unused with GDAL.
 static int Clock_ScanDash (char *word, int *mon, int *day, sInt4 *year,
                            double *ptime, char *f_time)
 {
@@ -1711,6 +1722,7 @@ static int Clock_ScanDash (char *word, int *mon, int *day, sInt4 *year,
    *ptime = sec + min * 60 + hour * 3600 - offset;
    return 0;
 }
+#endif
 
 /*****************************************************************************
  * Clock_ScanDate() --
@@ -1898,6 +1910,8 @@ enum {
  * non-',' non-'.' character.  Move End to first space, ',' or '.' after
  * new Start location.  Copy up to 30 characters (in caps) into word. */
 /* return -1 if no next word, 0 otherwise */
+
+#if 0  // Unused with GDAL.
 static int Clock_GetWord (char **Start, char **End, char word[30],
                           int *wordType)
 {
@@ -1959,7 +1973,9 @@ static int Clock_GetWord (char **Start, char **End, char word[30],
    }
    return 0;
 }
+#endif
 
+#if 0  // Unused with gdal.
 typedef struct {
    sInt4 val;
    int len;             /* read from len char string? */
@@ -1970,6 +1986,7 @@ typedef struct {
    int f_negate;
    int amount;
 } relType;
+#endif
 
 /*****************************************************************************
  * Clock_Scan() --
@@ -1993,6 +2010,8 @@ typedef struct {
 
  *****************************************************************************
  */
+
+#if 0  // Unused with GDAL.
 int Clock_Scan (double *l_clock, char *buffer, char f_gmt)
 {
    char *ptr, *ptr2;
@@ -2013,13 +2032,13 @@ int Clock_Scan (double *l_clock, char *buffer, char f_gmt)
    relType *Rel = NULL;
    int lenRel = 0;
    int lenStack = 0;
-   static char *PreRel[] = { "LAST", "THIS", "NEXT", NULL };
-   static char *RelUnit[] = {
+   static const char * const PreRel[] = { "LAST", "THIS", "NEXT", NULL };
+   static const char * const RelUnit[] = {
       "YEAR", "YEARS", "MONTH", "MONTHS", "FORTNIGHT", "FORTNIGHTS", "WEEK",
       "WEEKS", "DAY", "DAYS", "HOUR", "HOURS", "MIN", "MINS", "MINUTE",
       "MINUTES", "SEC", "SECS", "SECOND", "SECONDS", NULL
    };
-   static char *AdjDay[] = { "YESTERDAY", "TODAY", "TOMORROW", NULL };
+   static const char * const AdjDay[] = { "YESTERDAY", "TODAY", "TOMORROW", NULL };
    sChar f_ampm = -1;
    char f_timeZone = 0;
    char f_time = 0;
@@ -2434,6 +2453,7 @@ int Clock_Scan (double *l_clock, char *buffer, char f_gmt)
    free (Rel);
    return -1;
 }
+#endif  // Unused with GDAL.
 
 #ifdef CLOCK_PROGRAM
 /* See l_clockstart.c */
diff --git a/frmts/grib/degrib18/degrib/clock.h b/frmts/grib/degrib18/degrib/clock.h
index 3b4f15b..5668243 100644
--- a/frmts/grib/degrib18/degrib/clock.h
+++ b/frmts/grib/degrib18/degrib/clock.h
@@ -33,8 +33,11 @@ void Clock_PrintMonth (int mon, char *buffer, int buffLen);
 void Clock_ScanDate (double *clock, sInt4 year, int mon, int day);
 int Clock_ScanDateNumber (double *clock, char *buffer);
 void Clock_PrintDateNumber (double clock, char buffer[15]);
-int Clock_Scan (double *clock, char *buffer, char f_gmt);
 
+#if 0  // Unused with GDAL.
+int Clock_Scan (double *clock, char *buffer, char f_gmt);
+#endif
+  
 #ifdef __cplusplus
 }
 #endif  /* __cplusplus */
diff --git a/frmts/grib/degrib18/degrib/datasource.h b/frmts/grib/degrib18/degrib/datasource.h
index 0eceb07..e768190 100644
--- a/frmts/grib/degrib18/degrib/datasource.h
+++ b/frmts/grib/degrib18/degrib/datasource.h
@@ -7,12 +7,12 @@ class DataSource
 {
 public:
         virtual ~DataSource() {}
-	virtual size_t DataSourceFread(void* lpBuf, size_t size, size_t count) = 0;
-	virtual int DataSourceFgetc() = 0;
-	virtual int DataSourceUngetc(int c) = 0;
-	virtual int DataSourceFseek(long offset, int origin) = 0;
-	virtual int DataSourceFeof() = 0;
-	virtual long DataSourceFtell() = 0;
+        virtual size_t DataSourceFread(void* lpBuf, size_t size, size_t count) = 0;
+        virtual int DataSourceFgetc() = 0;
+        virtual int DataSourceUngetc(int c) = 0;
+        virtual int DataSourceFseek(long offset, int origin) = 0;
+        virtual int DataSourceFeof() = 0;
+        virtual long DataSourceFtell() = 0;
 };
 
 #endif /* DATASOURCE_H */
diff --git a/frmts/grib/degrib18/degrib/degrib1.cpp b/frmts/grib/degrib18/degrib/degrib1.cpp
index 2c2138d..8c8eb03 100644
--- a/frmts/grib/degrib18/degrib/degrib1.cpp
+++ b/frmts/grib/degrib18/degrib/degrib1.cpp
@@ -448,13 +448,13 @@ static int ReadGrib1Sect1 (uChar *pds, uInt4 gribLen, uInt4 *curLoc,
       pdsMeta->P1 = pdsMeta->refTime + P1_DeltaTime;
    } else {
       pdsMeta->P1 = pdsMeta->refTime;
-      printf ("Warning! : Can't figure out time unit of %d\n", *pds);
+      printf ("Warning! : Can't figure out time unit of %u\n", *pds);
    }
    if (ParseSect4Time2secV1 (pds[2], *pds, &P2_DeltaTime) == 0) {
       pdsMeta->P2 = pdsMeta->refTime + P2_DeltaTime;
    } else {
       pdsMeta->P2 = pdsMeta->refTime;
-      printf ("Warning! : Can't figure out time unit of %d\n", *pds);
+      printf ("Warning! : Can't figure out time unit of %u\n", *pds);
    }
    /* The following is based on Table 5. */
    /* Note: For ensemble forecasts, 119 has meaning. */
@@ -487,7 +487,7 @@ static int ReadGrib1Sect1 (uChar *pds, uInt4 gribLen, uInt4 *curLoc,
             pdsMeta->P2 = pdsMeta->P1 = pdsMeta->refTime + P1_DeltaTime;
          } else {
             pdsMeta->P2 = pdsMeta->P1 = pdsMeta->refTime;
-            printf ("Warning! : Can't figure out time unit of %d\n", *pds);
+            printf ("Warning! : Can't figure out time unit of %u\n", *pds);
          }
          pdsMeta->validTime = pdsMeta->P1;
          break;
@@ -594,8 +594,8 @@ static int ReadGrib1Sect1 (uChar *pds, uInt4 gribLen, uInt4 *curLoc,
               sectLen);
       */
    } else {
-      printf ("Un-handled possible ensemble section center %d "
-              "subcenter %d\n", *center, *subcenter);
+      printf ("Un-handled possible ensemble section center %u "
+              "subcenter %u\n", *center, *subcenter);
    }
    return 0;
 }
@@ -831,7 +831,7 @@ static int ReadGrib1Sect2 (uChar *gds, uInt4 gribLen, uInt4 *curLoc,
 #ifdef DEBUG
    if (gds[1] != 255) {
       printf ("\n\tCaution: GRIB1 GDS: FOR ALL NWS products, PV should be "
-              "255 rather than %d\n", gds[1]);
+              "255 rather than %u\n", gds[1]);
    }
 #endif
    if ((gds[1] != 255) && (gds[1] > 6)) {
@@ -1248,7 +1248,7 @@ static int UnpackCmplx (uChar *bds, CPL_UNUSED uInt4 gribLen, CPL_UNUSED uInt4 *
    P1 = GRIB_UNSIGN_INT2 (bds[5], bds[6]);
    P2 = GRIB_UNSIGN_INT2 (bds[7], bds[8]);
    printf ("N1 N2 P1 P2 : %d %d %d %d\n", N1, N2, P1, P2);
-   printf ("Reserved %d\n", bds[9]);
+   printf ("Reserved %u\n", bds[9]);
    bds += 10;
    secLen += 10;
 
@@ -1256,7 +1256,7 @@ static int UnpackCmplx (uChar *bds, CPL_UNUSED uInt4 gribLen, CPL_UNUSED uInt4 *
 
    for (i = 0; i < P1; i++) {
       width[i] = *bds;
-      printf ("(Width %d %d)\n", i, width[i]);
+      printf ("(Width %d %u)\n", i, width[i]);
       bds++;
       secLen++;
    }
@@ -1264,7 +1264,7 @@ static int UnpackCmplx (uChar *bds, CPL_UNUSED uInt4 gribLen, CPL_UNUSED uInt4 *
       bufLoc = 8;
       for (i = 0; i < P2; i++) {
          memBitRead (&uli_temp, sizeof (sInt4), bds, 1, &bufLoc, &numUsed);
-         printf ("(%d %d) ", i, uli_temp);
+         printf ("(%d %u) ", i, uli_temp);
          if (numUsed != 0) {
             printf ("\n");
             bds += numUsed;
@@ -1275,7 +1275,7 @@ static int UnpackCmplx (uChar *bds, CPL_UNUSED uInt4 gribLen, CPL_UNUSED uInt4 *
          bds++;
          secLen++;
       }
-      printf ("Observed Sec Len %d\n", secLen);
+      printf ("Observed Sec Len %u\n", secLen);
    } else {
       /* Jump over widths and secondary bitmap */
       bds += (N1 - 21);
@@ -1285,7 +1285,7 @@ static int UnpackCmplx (uChar *bds, CPL_UNUSED uInt4 gribLen, CPL_UNUSED uInt4 *
    bufLoc = 8;
    for (i = 0; i < P1; i++) {
       memBitRead (&uli_temp, sizeof (sInt4), bds, numBits, &bufLoc, &numUsed);
-      printf ("(%d %d) (numUsed %ld numBits %d)", i, uli_temp, 
+      printf ("(%d %u) (numUsed %ld numBits %d)", i, uli_temp,
               (long) numUsed, numBits);
       if (numUsed != 0) {
          printf ("\n");
@@ -1294,11 +1294,12 @@ static int UnpackCmplx (uChar *bds, CPL_UNUSED uInt4 gribLen, CPL_UNUSED uInt4 *
       }
    }
    if (bufLoc != 8) {
+      // cppcheck-suppress uselessAssignmentPtrArg
       bds++;
       secLen++;
    }
 
-   printf ("Observed Sec Len %d\n", secLen);
+   printf ("Observed Sec Len %u\n", secLen);
    printf ("N2 = %d\n", N2);
 
    errSprintf ("Don't know how to handle Complex GRIB1 packing yet.\n");
@@ -1489,7 +1490,7 @@ static int ReadGrib1Sect4 (uChar *bds, uInt4 gribLen, uInt4 *curLoc,
    meta->gridAttrib.max = meta->gridAttrib.min;
    meta->gridAttrib.f_maxmin = 1;
    meta->gridAttrib.numMiss = 0;
-   meta->gridAttrib.refVal = refVal;
+   meta->gridAttrib.refVal = (float)refVal;
    meta->gridAttrib.ESF = ESF;
    meta->gridAttrib.DSF = DSF;
    bufLoc = 8;
@@ -1517,6 +1518,7 @@ static int ReadGrib1Sect4 (uChar *bds, uInt4 gribLen, uInt4 *curLoc,
             newIndex = i;
          }
          /* A 0 in bitmap means no data. A 1 in bitmap means data. */
+         // cppcheck-suppress nullPointer
          if (!bitmap[i]) {
             meta->gridAttrib.numMiss++;
             data[newIndex] = UNDEFINED;
@@ -1566,6 +1568,7 @@ static int ReadGrib1Sect4 (uChar *bds, uInt4 gribLen, uInt4 *curLoc,
             } else {
                newIndex = i;
             }
+            // cppcheck-suppress nullPointer
             if (!bitmap[i]) {
                data[newIndex] = resetPrim;
             }
diff --git a/frmts/grib/degrib18/degrib/degrib1.h b/frmts/grib/degrib18/degrib/degrib1.h
index 62be482..a23e652 100644
--- a/frmts/grib/degrib18/degrib/degrib1.h
+++ b/frmts/grib/degrib18/degrib/degrib1.h
@@ -60,7 +60,6 @@ extern const GRIB1ParmTable parm_table_undefined[256];
 
 extern const GRIB1SurfTable GRIB1Surface[256];
 
-
 int GRIB1_Inventory (DataSource &fp, uInt4 gribLen, inventoryType * inv);
 
 int GRIB1_RefTime (DataSource &fp, uInt4 gribLen, double *refTime);
diff --git a/frmts/grib/degrib18/degrib/degrib2.cpp b/frmts/grib/degrib18/degrib/degrib2.cpp
index faa643b..0cbeb47 100644
--- a/frmts/grib/degrib18/degrib/degrib2.cpp
+++ b/frmts/grib/degrib18/degrib/degrib2.cpp
@@ -123,10 +123,10 @@ int ReadSECT0 (DataSource &fp, char **buff, uInt4 *buffLen, sInt4 limit,
    wordType word;       /* Used to check that the edition is correct. */
    uInt4 curLen;        /* Where we currently are in buff. */
    uInt4 i;             /* Used to loop over the first few char's */
-   uInt4 stillNeed;     /* Number of bytes still needed to get 1st 8 bytes of 
+   uInt4 stillNeed;     /* Number of bytes still needed to get 1st 8 bytes of
                          * message into memory. */
 
-   /* Get first 8 bytes.  If GRIB we don't care.  If TDLP, this is the length 
+   /* Get first 8 bytes.  If GRIB we don't care.  If TDLP, this is the length
     * of record.  Read at least 1 record (length + 2 * 8) + 8 (next record
     * length) + 8 bytes before giving up. */
    curLen = 8;
@@ -263,7 +263,7 @@ int ReadSECT0 (DataSource &fp, char **buff, uInt4 *buffLen, sInt4 limit,
  *  msgNum = Which message to look for. (Input)
  *  offset = Where in the file the message starts (this is before the
  *           wmo ASCII part if there is one.) (Output)
- *  curMsg = The current # of messages we have looked through. (In/Out) 
+ *  curMsg = The current # of messages we have looked through. (In/Out)
  *
  * FILES/DATABASES:
  *   An already opened "GRIB2" File
@@ -286,7 +286,7 @@ int ReadSECT0 (DataSource &fp, char **buff, uInt4 *buffLen, sInt4 limit,
 int FindGRIBMsg (DataSource &fp, int msgNum, sInt4 *offset, int *curMsg)
 {
    int cnt;             /* The current message we are looking at. */
-   char *buff;          /* Holds the info between records. */
+   char *buff = NULL;   /* Holds the info between records. */
    uInt4 buffLen;       /* Length of info between records. */
    sInt4 sect0[SECT0LEN_WORD]; /* Holds the current Section 0. */
    uInt4 gribLen;       /* Length of the current GRIB message. */
@@ -821,13 +821,14 @@ int ReadGrib2Record (DataSource &fp, sChar f_unit, double **Grib_Data,
    sInt4 l3264b;        /* Number of bits in a sInt4.  Needed by FORTRAN
                          * unpack library to determine if system has a 4
                          * byte_ sInt4 or an 8 byte sInt4. */
-   char *buff;          /* Holds the info between records. */
+   char *buff = NULL;   /* Holds the info between records. */
    uInt4 buffLen;       /* Length of info between records. */
    sInt4 sect0[SECT0LEN_WORD]; /* Holds the current Section 0. */
    uInt4 gribLen;       /* Length of the current GRIB message. */
    sInt4 nd5;           /* Size of grib message rounded up to the nearest
                          * sInt4. */
-   char *c_ipack;       /* A char ptr to the message stored in IS->ipack */
+   /* A char ptr to the message stored in IS->ipack */
+   char *c_ipack = NULL;
    sInt4 local_ns[8];   /* Local copy of section lengths. */
    sInt4 nd2x3;         /* Total number of grid points. */
    short int table50;   /* Type of packing used. (See code table 5.0)
@@ -874,7 +875,6 @@ int ReadGrib2Record (DataSource &fp, sChar f_unit, double **Grib_Data,
     * don't want to throw it out, nor have to re-read ipack from disk.
     */
    l3264b = sizeof (sInt4) * 8;
-   buff = NULL;
    buffLen = 0;
    if (*f_endMsg == 1) {
       if (ReadSECT0 (fp, &buff, &buffLen, -1, sect0, &gribLen, &version) < 0) {
diff --git a/frmts/grib/degrib18/degrib/engribapi.c b/frmts/grib/degrib18/degrib/engribapi.c
index 6576d21..9f64e8b 100644
--- a/frmts/grib/degrib18/degrib/engribapi.c
+++ b/frmts/grib/degrib18/degrib/engribapi.c
@@ -13,7 +13,7 @@
  */
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h> 
+#include <string.h>
 #include <math.h>
 
 #include "grib2api.h"
@@ -577,7 +577,7 @@ int fillSect3 (enGribMeta *en, uShort2 tmplNum, double majEarth,
  * NOTES
  *****************************************************************************
  */
-static int getCodedTime (uChar timeCode, double time, sInt4 *ans)
+static int getCodedTime (uChar timeCode, double l_time, sInt4 *ans)
 {
    /* Following is a lookup table for unit conversion (see code table 4.4). */
    static const sInt4 unit2sec[] = {
@@ -588,7 +588,7 @@ static int getCodedTime (uChar timeCode, double time, sInt4 *ans)
 
    if (timeCode < 14) {
       if (unit2sec[timeCode] != 0) {
-         *ans = NearestInt (time / unit2sec[timeCode]);
+         *ans = NearestInt (l_time / unit2sec[timeCode]);
          return 0;
       }
    }
@@ -1350,7 +1350,7 @@ int fillSect5 (enGribMeta *en, uShort2 tmplNum, sShort2 BSF, sShort2 DSF,
  *    > 0 (max length of sect 6 and sect 7).
  *    -1 Can't handle this kind of bitmap (pre-defined).
  *    -2 No missing value when trying to create the bmap.
- *    -3 Can't handle Nx * Ny != lenData. 
+ *    -3 Can't handle Nx * Ny != lenData.
  *
  *  4/2006 Arthur Taylor (MDL): Created.
  *
diff --git a/frmts/grib/degrib18/degrib/engribapi.h b/frmts/grib/degrib18/degrib/engribapi.h
index 2283507..2b66ea0 100644
--- a/frmts/grib/degrib18/degrib/engribapi.h
+++ b/frmts/grib/degrib18/degrib/engribapi.h
@@ -75,7 +75,6 @@ int fillSect3 (enGribMeta *en, uShort2 tmplNum, double majEarth,
                double meshLat, double orientLon, double scaleLat1,
                double scaleLat2, double southLat, double southLon);
 
-
 int fillSect4_0 (enGribMeta *en, uShort2 tmplNum, uChar cat, uChar subCat,
                  uChar genProcess, uChar bgGenID, uChar genID,
                  uChar f_valCutOff, sInt4 cutOff, uChar timeCode,
diff --git a/frmts/grib/degrib18/degrib/filedatasource.cpp b/frmts/grib/degrib18/degrib/filedatasource.cpp
index e06b0be..ecbd659 100644
--- a/frmts/grib/degrib18/degrib/filedatasource.cpp
+++ b/frmts/grib/degrib18/degrib/filedatasource.cpp
@@ -37,7 +37,7 @@ int FileDataSource::DataSourceFgetc()
 int FileDataSource::DataSourceUngetc(int c)
 {
     DataSourceFseek(-1, SEEK_CUR );
-    
+
     return c;
 }
 
diff --git a/frmts/grib/degrib18/degrib/filedatasource.h b/frmts/grib/degrib18/degrib/filedatasource.h
index aae3afa..1eaaef0 100644
--- a/frmts/grib/degrib18/degrib/filedatasource.h
+++ b/frmts/grib/degrib18/degrib/filedatasource.h
@@ -7,18 +7,18 @@
 class FileDataSource : public DataSource
 {
 public:
-	FileDataSource(const char * fileName);
-	FileDataSource(VSILFILE* fp);
-	virtual ~FileDataSource();
-	virtual size_t DataSourceFread(void* lpBuf, size_t size, size_t count);
-	virtual int DataSourceFgetc();
-	virtual int DataSourceUngetc(int c);
-	virtual int DataSourceFseek(long offset, int origin);
-	virtual int DataSourceFeof();
-	virtual long DataSourceFtell();
+        explicit FileDataSource(const char * fileName);
+        explicit FileDataSource(VSILFILE* fp);
+        virtual ~FileDataSource();
+        virtual size_t DataSourceFread(void* lpBuf, size_t size, size_t count) override;
+        virtual int DataSourceFgetc() override;
+        virtual int DataSourceUngetc(int c) override;
+        virtual int DataSourceFseek(long offset, int origin) override;
+        virtual int DataSourceFeof() override;
+        virtual long DataSourceFtell() override;
 private:
-	VSILFILE * fp;
-	bool closeFile;
+        VSILFILE * fp;
+        bool closeFile;
 };
 
 #endif /* FILEDATASOURCE_H */
diff --git a/frmts/grib/degrib18/degrib/grib2api.c b/frmts/grib/degrib18/degrib/grib2api.c
index 7c53dd9..78e8c50 100644
--- a/frmts/grib/degrib18/degrib/grib2api.c
+++ b/frmts/grib/degrib18/degrib/grib2api.c
@@ -143,7 +143,7 @@ static int mdl_LocalUnpack (unsigned char *local, sInt4 locallen,
       MEMCPY_BIG (&numVal, local, sizeof (sInt4));
       MEMCPY_BIG (&refVal, local + 4, sizeof (float));
       scale = GRIB_UNSIGN_INT2 (local[8], local[9]);
-      recScale10 = 1 / pow (10.0, scale);
+      recScale10 = (sInt4)(1 / pow (10.0, scale));
       numBits = local[10];
       if (numBits >= 32) {
 #ifdef DEBUG
@@ -207,7 +207,7 @@ static int mdl_LocalUnpack (unsigned char *local, sInt4 locallen,
                         &bufLoc, &numUsed);
             local += numUsed;
             BytesUsed += (int) numUsed;
-            idat[curIndex] = (refVal + uli_temp) * recScale10;
+            idat[curIndex] = (sInt4)((refVal + uli_temp) * recScale10);
             curIndex++;
          }
          idat[curIndex] = 0;
@@ -378,14 +378,14 @@ static int TransferInt (float * fld, sInt4 ngrdpts, sInt4 ibitmap,
             ib[i] = bmap[i];
             /* Check if we are supposed to insert xmissp into the field */
             if ((iclean != 0) && (ib[i] == 0)) {
-               iain[i] = xmissp;
+               iain[i] = (sInt4)xmissp;
             } else {
-               iain[i] = fld[i];
+               iain[i] = (sInt4)fld[i];
             }
          }
       } else {
          for (i = 0; i < ngrdpts; i++) {
-            iain[i] = fld[i];
+            iain[i] = (sInt4)fld[i];
          }
       }
    } else {
@@ -404,9 +404,9 @@ static int TransferInt (float * fld, sInt4 ngrdpts, sInt4 ibitmap,
             ib[curIndex] = bmap[i];
             /* Check if we are supposed to insert xmissp into the field */
             if ((iclean != 0) && (ib[curIndex] == 0)) {
-               iain[i] = xmissp;
+               iain[i] = (sInt4)xmissp;
             } else {
-               iain[curIndex] = fld[i];
+               iain[curIndex] = (sInt4)fld[i];
             }
          }
       } else {
@@ -415,7 +415,7 @@ static int TransferInt (float * fld, sInt4 ngrdpts, sInt4 ibitmap,
             /* ScanIndex returns value as if scan was 0100(0000) */
             curIndex = (x - 1) + (y - 1) * nx;
             myAssert (curIndex < nd2x3);
-            iain[curIndex] = fld[i];
+            iain[curIndex] = (sInt4)fld[i];
          }
       }
       *scan = 64 + (*scan & 0x0f);
@@ -1999,7 +1999,7 @@ void pk_grib2 (CPL_UNUSED sInt4 * kfildo, CPL_UNUSED float * ain,
                CPL_UNUSED sInt4 * nidat, CPL_UNUSED float * rdat,
                CPL_UNUSED sInt4 * nrdat, CPL_UNUSED sInt4 * is0,
                CPL_UNUSED sInt4 * ns0, CPL_UNUSED sInt4 * is1,
-               CPL_UNUSED sInt4 * ns1, CPL_UNUSED sInt4 * is3, 
+               CPL_UNUSED sInt4 * ns1, CPL_UNUSED sInt4 * is3,
                CPL_UNUSED sInt4 * ns3, CPL_UNUSED sInt4 * is4,
                CPL_UNUSED sInt4 * ns4, CPL_UNUSED sInt4 * is5,
                CPL_UNUSED sInt4 * ns5, CPL_UNUSED sInt4 * is6,
@@ -2014,7 +2014,7 @@ void pk_grib2 (CPL_UNUSED sInt4 * kfildo, CPL_UNUSED float * ain,
                CPL_UNUSED sInt4 * ndjer, CPL_UNUSED sInt4 * kjer)
 {
 #ifndef _FORTRAN
-   
+
    printf ("Can not pack things unless using FORTRAN!\n");
    return;
 
diff --git a/frmts/grib/degrib18/degrib/inventory.cpp b/frmts/grib/degrib18/degrib/inventory.cpp
index 841ee36..b6754a0 100644
--- a/frmts/grib/degrib18/degrib/inventory.cpp
+++ b/frmts/grib/degrib18/degrib/inventory.cpp
@@ -121,13 +121,13 @@ void GRIB2InventoryPrint (inventoryType *Inv, uInt4 LenInv)
       delta = (Inv[i].validTime - Inv[i].refTime) / 3600.;
       delta = myRound (delta, 2);
       if (Inv[i].comment == NULL) {
-         printf ("%d.%d, %d, %d, %s, %s, %s, %s, %.2f\n",
+         printf ("%u.%u, %d, %d, %s, %s, %s, %s, %.2f\n",
                  Inv[i].msgNum, Inv[i].subgNum, Inv[i].start,
                  Inv[i].GribVersion, Inv[i].element, Inv[i].shortFstLevel,
                  refTime, validTime, delta);
          fflush (stdout);
       } else {
-         printf ("%d.%d, %d, %d, %s=\"%s\", %s, %s, %s, %.2f\n",
+         printf ("%u.%u, %d, %d, %s=\"%s\", %s, %s, %s, %.2f\n",
                  Inv[i].msgNum, Inv[i].subgNum, Inv[i].start,
                  Inv[i].GribVersion, Inv[i].element, Inv[i].comment,
                  Inv[i].shortFstLevel, refTime, validTime, delta);
@@ -243,7 +243,7 @@ static int InventoryParseTime (char *is, double *AnsTime)
  *****************************************************************************
  */
 static int GRIB2SectToBuffer (DataSource &fp,
-                              CPL_UNUSED uInt4 gribLen,
+                              uInt4 gribLen,
                               sChar *sect,
                               uInt4 *secLen, uInt4 *buffLen, char **buff)
 {
@@ -257,7 +257,7 @@ static int GRIB2SectToBuffer (DataSource &fp,
       }
       return -1;
    }
-   if( *secLen < sizeof(sInt4) )
+   if( *secLen < sizeof(sInt4) || *secLen > gribLen )
    {
        errSprintf ("ERROR: Wrong secLen in GRIB2SectToBuffer\n");
        return -1;
@@ -427,6 +427,8 @@ static int GRIB2Inventory2to7 (sChar sectNum, DataSource &fp, sInt4 gribLen,
    uChar cat;           /* General category of Meteo Product. */
    unsigned short int templat; /* The section 4 template number. */
    uChar subcat;        /* Specific subcategory of Product. */
+   uChar genProcess;    /* What type of generate process (Analysis,
+                           Forecast, Probability Forecast, etc). */
    uChar fstSurfType;   /* Type of the first fixed surface. */
    double fstSurfValue; /* Value of first fixed surface. */
    sInt4 value;         /* The scaled value from GRIB2 file. */
@@ -435,6 +437,7 @@ static int GRIB2Inventory2to7 (sChar sectNum, DataSource &fp, sInt4 gribLen,
    uChar sndSurfType;   /* Type of the second fixed surface. */
    double sndSurfValue; /* Value of second fixed surface. */
    sChar f_sndValue;    /* flag if SndValue is valid. */
+   sChar f_fstValue;    /* flag if FstValue is valid. */
    uChar timeRangeUnit;
    sInt4 lenTime;       /* Used by parseTime to tell difference between 8hr
                          * average and 1hr average ozone. */
@@ -486,14 +489,16 @@ enum { GS4_ANALYSIS, GS4_ENSEMBLE, GS4_DERIVED, GS4_PROBABIL_PNT = 5,
        && (templat != GS4_PROBABIL_PNT) && (templat != GS4_STATISTIC)
        && (templat != GS4_PROBABIL_TIME) && (templat != GS4_PERCENTILE)
        && (templat != GS4_ENSEMBLE_STAT)
+       && (templat != GS4_STATISTIC_SPATIAL_AREA)
        && (templat != GS4_RADAR) && (templat != GS4_SATELLITE)
        && (templat != GS4_DERIVED_INTERVAL)) {
       errSprintf ("This was only designed for templates 0, 1, 2, 5, 8, 9, "
-                  "10, 11, 12, 20, 30\n");
+                  "10, 11, 12, 15, 20, 30. Template found = %d\n", templat);
       return -8;
    }
    cat = (*buffer)[10 - 5];
    subcat = (*buffer)[11 - 5];
+   genProcess = (*buffer)[12 - 5];
    genID = 0;
    probType = 0;
    lowerProb = 0;
@@ -510,7 +515,7 @@ enum { GS4_ANALYSIS, GS4_ENSEMBLE, GS4_DERIVED, GS4_PROBABIL_PNT = 5,
       /* Compute forecast time. */
       foreTimeUnit = (*buffer)[18 - 5];
       MEMCPY_BIG (&foreTime, *buffer + 19 - 5, sizeof (sInt4));
-      if (ParseSect4Time2sec (foreTime, foreTimeUnit, &(inv->foreSec)) != 0) {
+      if (ParseSect4Time2sec (/*inv->refTime, */foreTime, foreTimeUnit, &(inv->foreSec)) != 0) {
          errSprintf ("unable to convert TimeUnit: %d \n", foreTimeUnit);
          return -8;
       }
@@ -639,23 +644,23 @@ enum { GS4_ANALYSIS, GS4_ENSEMBLE, GS4_DERIVED, GS4_PROBABIL_PNT = 5,
    /* Try to convert lenTime to hourly. */
    if (timeRangeUnit == 0) {
       lenTime = (sInt4) (lenTime / 60.);
-      /*timeRangeUnit = 1;*/
+      timeRangeUnit = 1;
    } else if (timeRangeUnit == 1) {
    } else if (timeRangeUnit == 2) {
       lenTime = lenTime * 24;
-      /*timeRangeUnit = 1;*/
+      timeRangeUnit = 1;
    } else if (timeRangeUnit == 10) {
       lenTime = lenTime * 3;
-      /*timeRangeUnit = 1;*/
+      timeRangeUnit = 1;
    } else if (timeRangeUnit == 11) {
       lenTime = lenTime * 6;
-      /*timeRangeUnit = 1;*/
+      timeRangeUnit = 1;
    } else if (timeRangeUnit == 12) {
       lenTime = lenTime * 12;
-      /*timeRangeUnit = 1;*/
+      timeRangeUnit = 1;
    } else if (timeRangeUnit == 13) {
       lenTime = (sInt4) (lenTime / 3600.);
-      /*timeRangeUnit = 1;*/
+      timeRangeUnit = 1;
    } else {
       printf ("Can't handle this timeRangeUnit\n");
       //myAssert (timeRangeUnit == 1);
@@ -664,64 +669,26 @@ enum { GS4_ANALYSIS, GS4_ENSEMBLE, GS4_DERIVED, GS4_PROBABIL_PNT = 5,
    if (lenTime == GRIB2MISSING_s4) {
       lenTime = 0;
    }
-   /* Find out what the name of this variable is. */
-   ParseElemName (center, subcenter, prodType, templat, cat, subcat,
-                  lenTime, timeIncrType, genID, probType, lowerProb,
-                  upperProb, &(inv->element), &(inv->comment),
-                  &(inv->unitName), &convert, percentile);
-/*
-   if (strcmp (element, "") == 0) {
-      mallocSprintf (&(inv->element), "unknown");
-      mallocSprintf (&(inv->unitName), "[%s]", unitName);
-      if (strcmp (comment, "unknown") == 0) {
-         mallocSprintf (&(inv->comment), "(prodType %d, cat %d, subcat %d)"
-                        " [%s]", prodType, cat, subcat, unitName);
-      } else {
-         mallocSprintf (&(inv->comment), "%s [%s]", comment, unitName);
-      }
-   } else {
-      if (IsData_MOS (center, subcenter)) {
-         * See : http://www.nco.ncep.noaa.gov/pmb/docs/on388/tablea.html *
-         if (genID == 96) {
-            inv->element = (char *) malloc ((1 + 7 + strlen (element))
-                                            * sizeof (char));
-            sprintf (inv->element, "MOSGFS-%s", element);
-         } else {
-            inv->element = (char *) malloc ((1 + 4 + strlen (element))
-                                            * sizeof (char));
-            sprintf (inv->element, "MOS-%s", element);
-         }
-      } else {
-         inv->element = (char *) malloc ((1 + strlen (element))
-                                         * sizeof (char));
-         strcpy (inv->element, element);
-      }
-      mallocSprintf (&(inv->unitName), "[%s]", unitName);
-      mallocSprintf (&(inv->comment), "%s [%s]", comment, unitName);
-*
-      inv->unitName = (char *) malloc ((1 + 2 + strlen (unitName))
-                                       * sizeof (char));
-      sprintf (inv->unitName, "[%s]", unitName);
-      inv->comment = (char *) malloc ((1 + 3 + strlen (unitName) + strlen (comment))
-                                      * sizeof (char));
-      sprintf (inv->comment, "%s [%s]", comment, unitName);
-*
-   }
-*/
 
    if ((templat == GS4_RADAR) || (templat == GS4_SATELLITE)
        || (templat == 254) || (templat == 1000) || (templat == 1001)
        || (templat == 1002)) {
-      reallocSprintf (&(inv->shortFstLevel), "0 undefined");
-      reallocSprintf (&(inv->longFstLevel), "0.000[-] undefined ()");
+      fstSurfValue = 0;
+      f_fstValue = 0;
+      fstSurfType = 0;
+      sndSurfValue = 0;
+      f_sndValue = 0;
    } else {
       fstSurfType = (*buffer)[23 - 5];
       scale = (*buffer)[24 - 5];
       MEMCPY_BIG (&value, *buffer + 25 - 5, sizeof (sInt4));
-      if ((value == GRIB2MISSING_s4) || (scale == GRIB2MISSING_s1)) {
+      if ((value == GRIB2MISSING_s4) || (scale == GRIB2MISSING_s1) ||
+          (fstSurfType == GRIB2MISSING_u1)) {
          fstSurfValue = 0;
+         f_fstValue = 1;
       } else {
          fstSurfValue = value * pow (10.0, (int) (-1 * scale));
+         f_fstValue = 1;
       }
       sndSurfType = (*buffer)[29 - 5];
       scale = (*buffer)[30 - 5];
@@ -734,7 +701,19 @@ enum { GS4_ANALYSIS, GS4_ENSEMBLE, GS4_DERIVED, GS4_PROBABIL_PNT = 5,
          sndSurfValue = value * pow (10.0, -1 * scale);
          f_sndValue = 1;
       }
+   }
 
+   /* Find out what the name of this variable is. */
+   ParseElemName (center, subcenter, prodType, templat, cat, subcat,
+                  lenTime, timeRangeUnit, timeIncrType, genID, probType, lowerProb,
+                  upperProb, &(inv->element), &(inv->comment),
+                  &(inv->unitName), &convert, percentile, genProcess,
+                  f_fstValue, fstSurfValue, f_sndValue, sndSurfValue);
+
+   if (! f_fstValue) {
+      reallocSprintf (&(inv->shortFstLevel), "0 undefined");
+      reallocSprintf (&(inv->longFstLevel), "0.000[-] undefined ()");
+   } else {
       ParseLevelName (center, subcenter, fstSurfType, fstSurfValue,
                       f_sndValue, sndSurfValue, &(inv->shortFstLevel),
                       &(inv->longFstLevel));
@@ -843,9 +822,9 @@ int GRIB2Inventory (DataSource &fp, inventoryType **Inv, uInt4 *LenInv,
    char *msg;           /* Used to pop messages off the error Stack. */
    int version;         /* Which version of GRIB is in this message. */
    uChar prodType;      /* Which GRIB2 type of product, 0 is meteo, 1 is
-                         * hydro, 2 is land, 3 is space, 10 is oceanographic. 
+                         * hydro, 2 is land, 3 is space, 10 is oceanographic.
                          */
-   int grib_limit;      /* How many bytes to look for before the first "GRIB" 
+   int grib_limit;      /* How many bytes to look for before the first "GRIB"
                          * in the file.  If not found, is not a GRIB file. */
    int c;               /* Determine if end of the file without fileLen. */
    sInt4 fileLen;       /* Length of the GRIB2 file. */
@@ -1088,9 +1067,9 @@ int GRIB2RefTime (char *filename, double *refTime)
    char *msg;           /* Used to pop messages off the error Stack. */
    int version;         /* Which version of GRIB is in this message. */
    /* uChar prodType; */      /* Which GRIB2 type of product, 0 is meteo, 1 is
-                         * hydro, 2 is land, 3 is space, 10 is oceanographic. 
+                         * hydro, 2 is land, 3 is space, 10 is oceanographic.
                          */
-   int grib_limit;      /* How many bytes to look for before the first "GRIB" 
+   int grib_limit;      /* How many bytes to look for before the first "GRIB"
                          * in the file.  If not found, is not a GRIB file. */
    int c;               /* Determine if end of the file without fileLen. */
    sInt4 fileLen;       /* Length of the GRIB2 file. */
diff --git a/frmts/grib/degrib18/degrib/inventory.h b/frmts/grib/degrib18/degrib/inventory.h
index 35652a3..55a3a3d 100644
--- a/frmts/grib/degrib18/degrib/inventory.h
+++ b/frmts/grib/degrib18/degrib/inventory.h
@@ -24,7 +24,6 @@ extern "C" {
 
 #include "datasource.h"
 
-
 typedef struct {
    sChar GribVersion;        /* 1 if GRIB1, 2 if GRIB2, -1 if it is TDLP */
    sInt4 start;           /* Where this message starts in file. */
@@ -39,7 +38,7 @@ typedef struct {
                               * for the others it is refTime + foreSec. */
    char *element;            /* Character look up of variable type. */
    char *comment;            /* A more descriptive look up of variable type. */
-   char *unitName;           /* The unit of this element. */ 
+   char *unitName;           /* The unit of this element. */
    double foreSec;           /* Forecast element in seconds. */
    char *shortFstLevel;      /* Short description of the level of this data
                                 (above ground) (500 mb), etc */
diff --git a/frmts/grib/degrib18/degrib/memorydatasource.cpp b/frmts/grib/degrib18/degrib/memorydatasource.cpp
index b3f5668..232aa3c 100644
--- a/frmts/grib/degrib18/degrib/memorydatasource.cpp
+++ b/frmts/grib/degrib18/degrib/memorydatasource.cpp
@@ -43,7 +43,7 @@ int MemoryDataSource::DataSourceFgetc()
 		returnVal = (int)c;
 		eof = false;
 	}
-	return returnVal;		
+	return returnVal;
 }
 
 int MemoryDataSource::DataSourceUngetc(int c)
@@ -82,7 +82,7 @@ int MemoryDataSource::DataSourceFseek(long offset, int origin)
 
 int MemoryDataSource::DataSourceFeof()
 {
-	return eof;	
+	return eof;
 }
 
 long MemoryDataSource::DataSourceFtell()
diff --git a/frmts/grib/degrib18/degrib/memorydatasource.h b/frmts/grib/degrib18/degrib/memorydatasource.h
index 324d2ee..71b633c 100644
--- a/frmts/grib/degrib18/degrib/memorydatasource.h
+++ b/frmts/grib/degrib18/degrib/memorydatasource.h
@@ -4,22 +4,27 @@
 #include "datasource.h"
 #include <stdio.h>
 
+// Compatibility hack for non-C++11 compilers
+#if !(__cplusplus >= 201103L || _MSC_VER >= 1500)
+#define override
+#endif
+
 class MemoryDataSource : public DataSource
 {
 public:
-	MemoryDataSource(unsigned char * block, long length);
-	virtual ~MemoryDataSource();
-	virtual size_t DataSourceFread(void* lpBuf, size_t size, size_t count);
-	virtual int DataSourceFgetc();
-	virtual int DataSourceUngetc(int c);
-	virtual int DataSourceFseek(long offset, int origin);
-	virtual int DataSourceFeof();
-	virtual long DataSourceFtell();
+        MemoryDataSource(unsigned char * block, long length);
+        virtual ~MemoryDataSource();
+        virtual size_t DataSourceFread(void* lpBuf, size_t size, size_t count) override;
+        virtual int DataSourceFgetc() override;
+        virtual int DataSourceUngetc(int c) override;
+        virtual int DataSourceFseek(long offset, int origin) override;
+        virtual int DataSourceFeof() override;
+        virtual long DataSourceFtell() override;
 private:
-	long seekPos;
-	long blockLength;
-	bool eof;
-	unsigned char * memoryBlock;
+        long seekPos;
+        long blockLength;
+        bool eof;
+        unsigned char * memoryBlock;
 };
 
 #endif /* MEMORYDATASOURCE_H */
diff --git a/frmts/grib/degrib18/degrib/meta.h b/frmts/grib/degrib18/degrib/meta.h
index d49cb7b..d3b992e 100644
--- a/frmts/grib/degrib18/degrib/meta.h
+++ b/frmts/grib/degrib18/degrib/meta.h
@@ -37,7 +37,7 @@ enum {GRIB2BIT_1=128, GRIB2BIT_2=64, GRIB2BIT_3=32, GRIB2BIT_4=16,
 #ifndef UNITCONVERT_ENUM
 #define UNITCONVERT_ENUM
 typedef enum { UC_NONE, UC_K2F, UC_InchWater, UC_M2Feet, UC_M2Inch,
-   UC_MS2Knots, UC_LOG10
+   UC_MS2Knots, UC_LOG10, UC_UVIndex, UC_M2StatuteMile
 } unit_convert;
 #endif
 
@@ -50,15 +50,54 @@ typedef enum { UC_NONE, UC_K2F, UC_InchWater, UC_M2Feet, UC_M2Inch,
 #ifndef NDFD_ENUM
 #define NDFD_ENUM
 /*
-enum { NDFD_MAX, NDFD_MIN, NDFD_POP, NDFD_TEMP, NDFD_WD, NDFD_WS,
-       NDFD_TD, NDFD_SKY, NDFD_QPF, NDFD_SNOW, NDFD_WX, NDFD_WH,
-       NDFD_AT, NDFD_RH, NDFD_WG, NDFD_INC34, NDFD_INC50, NDFD_INC64,
-       NDFD_CUM34, NDFD_CUM50, NDFD_CUM64, NDFD_UNDEF, NDFD_MATCHALL
+enum { NDFD_MAX=0, NDFD_MIN=1, NDFD_POP=2, NDFD_TEMP=3, NDFD_WD=4,
+       NDFD_WS=5, NDFD_TD=6, NDFD_SKY=7, NDFD_QPF=8, NDFD_SNOW=9,
+       NDFD_ICEACC=10, NDFD_WX=11, NDFD_WH=12, NDFD_AT=13, NDFD_RH=14,
+       NDFD_WG=15, NDFD_WWA=16, NDFD_INC34=17, NDFD_INC50=18, NDFD_INC64=19,
+       NDFD_CUM34=20, NDFD_CUM50=21, NDFD_CUM64=22, NDFD_FWXWINDRH=23,
+       NDFD_FWXTSTORM=24, NDFD_CONHAZ=25,
+       NDFD_PTORN=26, NDFD_PHAIL=27, NDFD_PTSTMWIND=28, NDFD_PXTORN=29,
+       NDFD_PXHAIL=30, NDFD_PXTSTMWIND=31, NDFD_PSTORM=32, NDFD_PXSTORM=33,
+       NDFD_TMPABV14D=34, NDFD_TMPBLW14D=35, NDFD_PRCPABV14D=36,
+       NDFD_PRCPBLW14D=37, NDFD_TMPABV30D=38, NDFD_TMPBLW30D=39,
+       NDFD_PRCPABV30D=40, NDFD_PRCPBLW30D=41, NDFD_TMPABV90D=42,
+       NDFD_TMPBLW90D=43, NDFD_PRCPABV90D=44, NDFD_PRCPBLW90D=45, NDFD_MAXRH=46,
+       NDFD_MINRH=47, LAMP_TSTMPRB=48, RTMA_PRECIPA=49, RTMA_SKY=50, RTMA_TD=51,
+       RTMA_TEMP=52, RTMA_UTD=53, RTMA_UTEMP=54, RTMA_UWDIR=55,
+       RTMA_UWSPD=56, RTMA_WDIR=57, RTMA_WSPD=58, NDFD_CANL=59
+#ifdef GFSEKD
+       GFSEKDMOS_MAXT=60, GFSEKDMOS_MINT=61,
+       GFSEKDMOS_TEMP=62, GFSEKDMOS_TD=63, GFSEKDMOS_QPF=64,
+#endif
+        NDFD_UNDEF, NDFD_MATCHALL
 };
 */
 enum { NDFD_MAX, NDFD_MIN, NDFD_POP, NDFD_TEMP, NDFD_WD, NDFD_WS,
-       NDFD_TD, NDFD_SKY, NDFD_QPF, NDFD_SNOW, NDFD_WX, NDFD_WH,
-       NDFD_AT, NDFD_RH, NDFD_UNDEF, NDFD_MATCHALL
+       NDFD_TD, NDFD_SKY, NDFD_QPF, NDFD_SNOW, NDFD_ICEACC, NDFD_WX, NDFD_WH,
+       NDFD_AT, NDFD_RH, NDFD_WG, NDFD_WWA, NDFD_INC34, NDFD_INC50,
+       NDFD_INC64, NDFD_CUM34, NDFD_CUM50, NDFD_CUM64, NDFD_FWXWINDRH,
+       NDFD_FWXTSTORM, NDFD_CONHAZ, NDFD_PTORN, NDFD_PHAIL, NDFD_PTSTMWIND,
+       NDFD_PXTORN, NDFD_PXHAIL, NDFD_PXTSTMWIND, NDFD_PSTORM, NDFD_PXSTORM,
+       NDFD_TMPABV14D, NDFD_TMPBLW14D, NDFD_PRCPABV14D, NDFD_PRCPBLW14D,
+       NDFD_TMPABV30D, NDFD_TMPBLW30D, NDFD_PRCPABV30D, NDFD_PRCPBLW30D,
+       NDFD_TMPABV90D, NDFD_TMPBLW90D, NDFD_PRCPABV90D, NDFD_PRCPBLW90D,
+       NDFD_MAXRH, NDFD_MINRH, LAMP_TSTMPRB, RTMA_PRECIPA, RTMA_SKY, RTMA_TD,
+       RTMA_TEMP, RTMA_UTD, RTMA_UTEMP, RTMA_UWDIR, RTMA_UWSPD, RTMA_WDIR,
+       RTMA_WSPD, NDFD_CANL,
+#ifdef GFSEKD
+       GFSEKDMOS_MAXT, GFSEKDMOS_MINT,
+       GFSEKDMOS_TEMP, GFSEKDMOS_TD, GFSEKDMOS_QPF,
+#endif
+        NDFD_UNDEF, NDFD_MATCHALL
+};
+#endif
+
+#ifndef NDFD_OCONUS_SECTOR_ENUM
+#define NDFD_OCONUS_SECTOR_ENUM
+/* Assumed the same order as in "sector.c" NdfdDefSect[] */
+enum { NDFD_OCONUS_5CONUS, NDFD_OCONUS_2_5CONUS, NDFD_OCONUS_PR,
+       NDFD_OCONUS_HI, NDFD_OCONUS_GU, NDFD_OCONUS_AK, NDFD_OCONUS_NHEMI,
+       NDFD_OCONUS_NPACIFIC, NDFD_OCONUS_UNDEF
 };
 #endif
 
@@ -107,7 +146,7 @@ typedef struct {
    sInt4 HazCode[NUM_UGLY_WORD]; /* A code to represent all the attributes. */
    int SimpleCode;         /* Simple weather code for this ugly string. */
    char *errors;           /* if STORE_ERRORS, then it contains any error
-                            * messages found while parsing this string. */ 
+                            * messages found while parsing this string. */
 } UglyStringType;
 
 typedef struct {
@@ -200,8 +239,12 @@ typedef struct {  /* See Template 4.30. */
 } sect4_BandType;
 
 enum { GS4_ANALYSIS, GS4_ENSEMBLE, GS4_DERIVED, GS4_PROBABIL_PNT = 5,
-   GS4_STATISTIC = 8, GS4_PROBABIL_TIME = 9, GS4_PERCENTILE = 10,
-   GS4_ENSEMBLE_STAT = 11, GS4_DERIVED_INTERVAL = 12, GS4_RADAR = 20,
+   GS4_PERCENT_PNT = 6, GS4_STATISTIC = 8, GS4_PROBABIL_TIME = 9,
+   GS4_PERCENTILE = 10, // FIXME: name in old degrib
+   GS4_PERCENT_TIME = 10, // FIXME: name in recent degrib
+   GS4_ENSEMBLE_STAT = 11, GS4_DERIVED_INTERVAL = 12,
+   GS4_STATISTIC_SPATIAL_AREA = 15, // TODO; partially supported. Should fetch specific fields in metaparse.cpp
+   GS4_RADAR = 20,
    GS4_SATELLITE = 30
 };
 
@@ -487,7 +530,13 @@ typedef enum {
    Prt_F, Prt_FS, Prt_E, Prt_ES, Prt_G, Prt_GS, Prt_SS, Prt_NULL
 } Prt_TYPE;
 
-char *Print(const char *label, const char *varName, Prt_TYPE fmt, ...);
+/* Note that fmt was Prt_TYPE, but there is no way to tell C89/C++03 to
+   use an integer sized enum, so it must be an int to avoid undefined
+   behavior.
+
+   http://stackoverflow.com/questions/9853633/how-to-change-the-integer-type-used-by-an-enum-c
+ */
+char *Print(const char *label, const char *varName, int fmt, ...);
 
 void MetaInit (grib_MetaData *meta);
 
@@ -519,12 +568,14 @@ void ParseGrid (gridAttribType * attrib, double **Grib_Data,
 void FreqPrint (char **ans, double *Data, sInt4 DataLen, sInt4 Nx,
                 sInt4 Ny, sChar decimal, char *comment);
 
+#if 0  // Unused with GDAL
 /* Possible error messages left in errSprintf() */
 int MetaPrintGDS (gdsType * gds, int version, char **ans);
 
 /* Possible error messages left in errSprintf() */
 int MetaPrint (grib_MetaData *meta, char **ans, sChar decimal, sChar f_unit);
-
+#endif  // Unused with GDAL.
+  
 #ifdef __cplusplus
 }
 #endif  /* __cplusplus */
diff --git a/frmts/grib/degrib18/degrib/metaname.cpp b/frmts/grib/degrib18/degrib/metaname.cpp
index 2b7ce0f..4d7bd09 100644
--- a/frmts/grib/degrib18/degrib/metaname.cpp
+++ b/frmts/grib/degrib18/degrib/metaname.cpp
@@ -15,6 +15,7 @@
  */
 #include <string.h>
 #include <stdlib.h>
+#include <limits>
 #include "meta.h"
 #include "metaname.h"
 #include "myerror.h"
@@ -29,7 +30,7 @@ const char *centerLookup (unsigned short int center)
     * http://www.wmo.ch/web/www/WMOCodes/Operational/CommonTables/BUFRCommon-2005feb.pdf
     * http://www.wmo.int/web/www/WMOCodes/Operational/CommonTables/BUFRCommon-2005nov.pdf
     * also see:
-    * http://www.nco.ncep.noaa.gov/pmb/docs/on388/table0.html 
+    * http://www.nco.ncep.noaa.gov/pmb/docs/on388/table0.html
     * I typed this in on 11/2/2006 */
 /* *INDENT-OFF* */
    static const struct {
@@ -433,7 +434,10 @@ const char *processLookup (unsigned short int center, unsigned char process)
       {7, 3, "NCEP/ARL Transport and Dispersion Model"},
       {7, 4, "NCEP/ARL Smoke Model"},
       {7, 5, "Satellite Derived Precipitation and temperatures, from IR"},
+      {7, 6, "NCEP/ARL Dust Model"},
       {7, 10, "Global Wind-Wave Forecast Model"},
+      {7, 11, "Global Multi-Grid Wave Model (Static Grids)"},
+      {7, 12, "Probabilistic Storm Surge"},
       {7, 19, "Limited-area Fine Mesh (LFM) analysis"},
       {7, 25, "Snow Cover Analysis"},
       {7, 30, "Forecaster generated field"},
@@ -461,8 +465,8 @@ const char *processLookup (unsigned short int center, unsigned char process)
       {7, 78, "126 wave triangular, 28 layer Spectral model from 'Medium Range Forecast' run"},
       {7, 79, "Backup from the previous run"},
       {7, 80, "62 wave triangular, 28 layer Spectral model from 'Medium Range Forecast' run"},
-      {7, 81, "Spectral Statistical Interpolation (SSI) analysis from GFS model"},
-      {7, 82, "Spectral Statistical Interpolation (SSI) analysis from 'Final' run."},
+      {7, 81, "Analysis from GFS (Global Forecast System)"},
+      {7, 82, "Analysis from GDAS (Global Data Assimilation System)"},
       {7, 84, "MESO ETA Model (currently 12 km)"},
       {7, 86, "RUC Model from FSL (isentropic; scale: 60km at 40N)"},
       {7, 87, "CAC Ensemble Forecasts from Spectral (ENSMB)"},
@@ -479,11 +483,15 @@ const char *processLookup (unsigned short int center, unsigned char process)
       {7, 100, "RUC Surface Analysis (scale: 60km at 40N)"},
       {7, 101, "RUC Surface Analysis (scale: 40km at 40N)"},
       {7, 105, "RUC Model from FSL (isentropic; scale: 20km at 40N)"},
-      {7, 110, "ETA Model - 15km version"},
-      {7, 111, "Eta model, generic resolution"},
+      {7, 107, "Global Ensemble Forecast System (GEFS)"},
+      {7, 108, "LAMP"},
+      {7, 109, "RTMA (Real Time Mesoscale Analysis)"},
+      {7, 110, "NAM Model - 15km version"},
+      {7, 111, "NAM model, generic resolution"},
       {7, 112, "WRF-NMM (Nondydrostatic Mesoscale Model) model, generic resolution"},
       {7, 113, "Products from NCEP SREF processing"},
-      {7, 115, "Downscaled GFS from Eta eXtension"},
+      {7, 114, "NAEFS Products from joined NCEP, CMC global ensembles"},
+      {7, 115, "Downscaled GFS from NAM eXtension"},
       {7, 116, "WRF-EM (Eulerian Mass-core) model, generic resolution "},
       {7, 120, "Ice Concentration Analysis"},
       {7, 121, "Western North Atlantic Regional Wave Model"},
@@ -495,7 +503,7 @@ const char *processLookup (unsigned short int center, unsigned char process)
       {7, 127, "Lake Ice Forecast Model"},
       {7, 128, "Global Ocean Forecast Model"},
       {7, 129, "Global Ocean Data Analysis System (GODAS)"},
-      {7, 130, "Merge of fields from the RUC, Eta, and Spectral Model"},
+      {7, 130, "Merge of fields from the RUC, NAM, and Spectral Model"},
       {7, 131, "Great Lakes Wave Model"},
       {7, 140, "North American Regional Reanalysis (NARR)"},
       {7, 141, "Land Data Assimilation and Forecast System"},
@@ -507,6 +515,7 @@ const char *processLookup (unsigned short int center, unsigned char process)
       {7, 181, "River Forecast Center Quantitative Precipitation Forecast mosaic"},
       {7, 182, "River Forecast Center Quantitative Precipitation estimate mosaic"},
       {7, 183, "NDFD product generated by NCEP/HPC"},
+      {7, 184, "Climatological Calibrated Precipiation Analysis - CCPA"},
       {7, 190, "National Convective Weather Diagnostic"},
       {7, 191, "Current Icing Potential automated product"},
       {7, 192, "Analysis product from NCEP/AWC"},
@@ -515,10 +524,12 @@ const char *processLookup (unsigned short int center, unsigned char process)
       {7, 196, "Climate Data Assimilation System 2 (CDAS2)"},
       {7, 197, "Climate Data Assimilation System (CDAS)"},
       {7, 198, "Climate Data Assimilation System (CDAS)"},
+      {7, 199, "Climate Forecast System Reanalysis (CFSR)"},
       {7, 200, "CPC Manual Forecast Product"},
       {7, 201, "CPC Automated Product"},
       {7, 210, "EPA Air Quality Forecast"},
       {7, 211, "EPA Air Quality Forecast"},
+      {7, 215, "SPC Manual Forecast Product"},
       {7, 220, "NCEP/OPC automated product"}
    };
 /* *INDENT-ON* */
@@ -551,7 +562,7 @@ typedef struct {
 /* *INDENT-OFF* */
 /* Updated based on:
  * http://www.wmo.ch/web/www/WMOCodes/Operational/GRIB2/FM92-GRIB2-2005nov.pdf
- * 1/3/2006
+ * 7/22/2008
  */
 /* GRIB2 Code table 4.2 : 0.0 */
 static const GRIB2ParmTable MeteoTemp[] = {
@@ -559,8 +570,8 @@ static const GRIB2ParmTable MeteoTemp[] = {
    /* 1 */ {"VTMP", "Virtual temperature", "K", UC_K2F},
    /* 2 */ {"POT", "Potential temperature", "K", UC_K2F},
    /* 3 */ {"EPOT", "Pseudo-adiabatic potential temperature", "K", UC_K2F},
-   /* 4 */ {"TMAX", "Maximum Temperature", "K", UC_K2F}, /* Need NDFD override MaxT */
-   /* 5 */ {"TMIN", "Minimum Temperature", "K", UC_K2F}, /* Need NDFD override MinT */
+   /* 4 */ {"TMAX", "Maximum temperature", "K", UC_K2F}, /* Need NDFD override MaxT */
+   /* 5 */ {"TMIN", "Minimum temperature", "K", UC_K2F}, /* Need NDFD override MinT */
    /* 6 */ {"DPT", "Dew point temperature", "K", UC_K2F}, /* Need NDFD override Td */
    /* 7 */ {"DEPR", "Dew point depression", "K", UC_K2F},
    /* 8 */ {"LAPR", "Lapse rate", "K/m", UC_NONE},
@@ -568,22 +579,23 @@ static const GRIB2ParmTable MeteoTemp[] = {
    /* 10 */ {"LHTFL", "Latent heat net flux", "W/(m^2)", UC_NONE},
    /* 11 */ {"SHTFL", "Sensible heat net flux", "W/(m^2)", UC_NONE},
             /* NDFD */
-   /* 12 */ {"HeatIndex", "Heat index", "K", UC_K2F},
+   /* 12 */ {"HEATX", "Heat index", "K", UC_K2F},
             /* NDFD */
-   /* 13 */ {"WCI", "Wind chill factor", "K", UC_K2F},
-   /* 14 */ {"", "Minimum dew point depression", "K", UC_K2F},
+   /* 13 */ {"WCF", "Wind chill factor", "K", UC_K2F},
+   /* 14 */ {"MINDPD", "Minimum dew point depression", "K", UC_K2F},
    /* 15 */ {"VPTMP", "Virtual potential temperature", "K", UC_K2F},
-/* 16 */    {"SNOHF", "Snow phase change heat flux", "W/m^2", UC_NONE},
+   /* 16 */ {"SNOHF", "Snow phase change heat flux", "W/m^2", UC_NONE},
+   /* 17 */ {"SKINT", "Skin temperature", "K", UC_K2F},
 };
 
 /* GRIB2 Code table 4.2 : 0.1 */
 /* NCEP added "Water" to items 22, 24, 25 */
 static const GRIB2ParmTable MeteoMoist[] = {
    /* 0 */ {"SPFH", "Specific humidity", "kg/kg", UC_NONE},
-   /* 1 */ {"RH", "Relative Humidity", "%", UC_NONE},
+   /* 1 */ {"RH", "Relative humidity", "%", UC_NONE},
    /* 2 */ {"MIXR", "Humidity mixing ratio", "kg/kg", UC_NONE},
    /* 3 */ {"PWAT", "Precipitable water", "kg/(m^2)", UC_NONE},
-   /* 4 */ {"VAPP", "Vapor Pressure", "Pa", UC_NONE},
+   /* 4 */ {"VAPP", "Vapor pressure", "Pa", UC_NONE},
    /* 5 */ {"SATD", "Saturation deficit", "Pa", UC_NONE},
    /* 6 */ {"EVP", "Evaporation", "kg/(m^2)", UC_NONE},
    /* 7 */ {"PRATE", "Precipitation rate", "kg/(m^2 s)", UC_NONE},
@@ -598,38 +610,60 @@ static const GRIB2ParmTable MeteoMoist[] = {
    /* 15 */ {"SNOL", "Large scale snow", "kg/(m^2)", UC_NONE},
    /* 16 */ {"SNOM", "Snow melt", "kg/(m^2)", UC_NONE},
    /* 17 */ {"SNOAG", "Snow age", "day", UC_NONE},
-   /* 18 */ {"", "Absolute humidity", "kg/(m^3)", UC_NONE},
-   /* 19 */ {"", "Precipitation type", "(1 Rain, 2 Thunderstorm, "
-             "3 Freezing Rain, 4 Mixed/ice, 5 snow, 255 missing)", UC_NONE},
-   /* 20 */ {"", "Integrated liquid water", "kg/(m^2)", UC_NONE},
+   /* 18 */ {"ABSH", "Absolute humidity", "kg/(m^3)", UC_NONE},
+   /* 19 */ {"PTYPE", "Precipitation type", "1=Rain; 2=Thunderstorm; "
+             "3=Freezing Rain; 4=Mixed/ice; 5=snow; 255=missing", UC_NONE},
+   /* 20 */ {"ILIQW", "Integrated liquid water", "kg/(m^2)", UC_NONE},
    /* 21 */ {"TCOND", "Condensate", "kg/kg", UC_NONE},
 /* CLWMR Did not make it to tables yet should be "-" */
-   /* 22 */ {"CLWMR", "Cloud Water Mixing Ratio", "kg/kg", UC_NONE},
+   /* 22 */ {"CLWMR", "Cloud mixing ratio", "kg/kg", UC_NONE},
    /* 23 */ {"ICMR", "Ice water mixing ratio", "kg/kg", UC_NONE},   /* ICMR? */
-   /* 24 */ {"RWMR", "Rain Water Mixing Ratio", "kg/kg", UC_NONE},
-   /* 25 */ {"SNMR", "Snow Water Mixing Ratio", "kg/kg", UC_NONE},
+   /* 24 */ {"RWMR", "Rain mixing ratio", "kg/kg", UC_NONE},
+   /* 25 */ {"SNMR", "Snow mixing ratio", "kg/kg", UC_NONE},
    /* 26 */ {"MCONV", "Horizontal moisture convergence", "kg/(kg s)", UC_NONE},
-   /* 27 */ {"", "Maximum relative humidity", "%", UC_NONE},
-   /* 28 */ {"", "Maximum absolute humidity", "kg/(m^3)", UC_NONE},
+   /* 27 */ {"MAXRH", "Maximum relative humidity", "%", UC_NONE},
+   /* 28 */ {"MAXAH", "Maximum absolute humidity", "kg/(m^3)", UC_NONE},
             /* NDFD */
    /* 29 */ {"ASNOW", "Total snowfall", "m", UC_M2Inch},
-   /* 30 */ {"", "Precipitable water category", "(undefined)", UC_NONE},
-   /* 31 */ {"", "Hail", "m", UC_NONE},
-   /* 32 */ {"", "Graupel (snow pellets)", "kg/kg", UC_NONE},
-/* 33 */    {"CRAIN", "Categorical rain", "0=no, 1=yes", UC_NONE},
-/* 34 */    {"CFRZR", "Categorical freezing rain", "0=no, 1=yes", UC_NONE},
-/* 35 */    {"CICEP", "Categorical ice pellets", "0=no, 1=yes", UC_NONE},
-/* 36 */    {"CSNOW", "Categorical snow", "0=no, 1=yes", UC_NONE},
+   /* 30 */ {"PWCAT", "Precipitable water category", "undefined", UC_NONE},
+   /* 31 */ {"HAIL", "Hail", "m", UC_NONE},
+   /* 32 */ {"GRLE", "Graupel (snow pellets)", "kg/kg", UC_NONE},
+/* 33 */    {"CRAIN", "Categorical rain", "0=no; 1=yes", UC_NONE},
+/* 34 */    {"CFRZR", "Categorical freezing rain", "0=no; 1=yes", UC_NONE},
+/* 35 */    {"CICEP", "Categorical ice pellets", "0=no; 1=yes", UC_NONE},
+/* 36 */    {"CSNOW", "Categorical snow", "0=no; 1=yes", UC_NONE},
 /* 37 */    {"CPRAT", "Convective precipitation rate", "kg/(m^2*s)", UC_NONE},
 /* 38 */    {"MCONV", "Horizontal moisture divergence", "kg/(kg*s)", UC_NONE},
 /* 39 */    {"CPOFP", "Percent frozen precipitation", "%", UC_NONE},
 /* 40 */    {"PEVAP", "Potential evaporation", "kg/m^2", UC_NONE},
 /* 41 */    {"PEVPR", "Potential evaporation rate", "W/m^2", UC_NONE},
-/* 42 */    {"SNOWC", "Snow Cover", "%", UC_NONE},
+/* 42 */    {"SNOWC", "Snow cover", "%", UC_NONE},
 /* 43 */    {"FRAIN", "Rain fraction of total cloud water", "-", UC_NONE},
 /* 44 */    {"RIME", "Rime factor", "-", UC_NONE},
 /* 45 */    {"TCOLR", "Total column integrated rain", "kg/m^2", UC_NONE},
 /* 46 */    {"TCOLS", "Total column integrated snow", "kg/m^2", UC_NONE},
+/* 47 */    {"LSWP", "Large scale water precipitation", "kg/m^2", UC_NONE},
+/* 48 */    {"CWP", "Convective water precipitation", "kg/m^2", UC_NONE},
+/* 49 */    {"TWATP", "Total water precipitation", "kg/m^2", UC_NONE},
+/* 50 */    {"TSNOWP", "Total snow precipitation", "kg/m^2", UC_NONE},
+/* 51 */    {"TCWAT", "Total column water", "kg/m^2", UC_NONE},
+/* 52 */    {"TPRATE", "Total precipitation rate", "kg/(m^2*s)", UC_NONE},
+/* 53 */    {"TSRWE", "Total snowfall rate water equivalent", "kg/(m^2*s)", UC_NONE},
+/* 54 */    {"LSPRATE", "Large scale precipitation rate", "kg/(m^2*s)", UC_NONE},
+/* 55 */    {"CSRWE", "Convective snowfall rate water equivalent", "kg/(m^2*s)", UC_NONE},
+/* 56 */    {"LSSRWE", "Large scale snowfall rate water equivalent", "kg/(m^2*s)", UC_NONE},
+/* 57 */    {"TSRATE", "Total snowfall rate", "m/s", UC_NONE},
+/* 58 */    {"CSRATE", "Convective snowfall rate", "m/s", UC_NONE},
+/* 59 */    {"LSSRWE", "Large scale snowfall rate", "m/s", UC_NONE},
+/* 60 */    {"SDWE", "Snow depth water equivalent", "kg/m^2", UC_NONE},
+/* 61 */    {"SDEN", "Snow density", "kg/m^3", UC_NONE},
+/* 62 */    {"SEVAP", "Snow evaporation", "kg/m^2", UC_NONE},
+/* 63 */    {"", "Reserved", "-", UC_NONE},
+/* 64 */    {"TCIWV", "Total column integrated water vapour", "kg/m^2", UC_NONE},
+/* 65 */    {"RPRATE", "Rain precipitation rate", "kg/(m^2*s)", UC_NONE},
+/* 66 */    {"SPRATE", "Snow precipitation rate", "kg/(m^2*s)", UC_NONE},
+/* 67 */    {"FPRATE", "Freezing rain precipitation rate", "kg/(m^2*s)", UC_NONE},
+/* 68 */    {"IPRATE", "Ice pellets precipitation rate", "kg/(m^2*s)", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.2 */
@@ -649,17 +683,17 @@ static const GRIB2ParmTable MeteoMoment[] = {
    /* 11 */ {"ABSD", "Absolute divergence", "1/s", UC_NONE},
    /* 12 */ {"RELV", "Relative vorticity", "1/s", UC_NONE},
    /* 13 */ {"RELD", "Relative divergence", "1/s", UC_NONE},
-   /* 14 */ {"PV", "Potential vorticity", "K(m^2)/(kg s)", UC_NONE},
+   /* 14 */ {"PVORT", "Potential vorticity", "K(m^2)/(kg s)", UC_NONE},
    /* 15 */ {"VUCSH", "Vertical u-component shear", "1/s", UC_NONE},
    /* 16 */ {"VVCSH", "Vertical v-component shear", "1/s", UC_NONE},
    /* 17 */ {"UFLX", "Momentum flux; u component", "N/(m^2)", UC_NONE},
    /* 18 */ {"VFLX", "Momentum flux; v component", "N/(m^2)", UC_NONE},
    /* 19 */ {"WMIXE", "Wind mixing energy", "J", UC_NONE},
    /* 20 */ {"BLYDP", "Boundary layer dissipation", "W/(m^2)", UC_NONE},
-   /* 21 */ {"", "Maximum wind speed", "m/s", UC_NONE},
+   /* 21 */ {"MAXGUST", "Maximum wind speed", "m/s", UC_NONE},
    /* 22 */ {"GUST", "Wind speed (gust)", "m/s", UC_MS2Knots},  /* GUST? */
-   /* 23 */ {"", "u-component of wind (gust)", "m/s", UC_NONE},
-   /* 24 */ {"", "v-component of wind (gust)", "m/s", UC_NONE},
+   /* 23 */ {"UGUST", "u-component of wind (gust)", "m/s", UC_NONE},
+   /* 24 */ {"VGUST", "v-component of wind (gust)", "m/s", UC_NONE},
 /* 25 */    {"VWSH", "Vertical speed shear", "1/s", UC_NONE},
 /* 26 */    {"MFLX", "Horizontal momentum flux", "N/(m^2)", UC_NONE},
 /* 27 */    {"USTM", "U-component storm motion", "m/s", UC_NONE},
@@ -676,20 +710,25 @@ static const GRIB2ParmTable MeteoMass[] = {
    /* 3 */ {"ICAHT", "ICAO Standard Atmosphere Reference Height", "m", UC_NONE},
    /* 4 */ {"GP", "Geopotential", "(m^2)/(s^2)", UC_NONE},
    /* 5 */ {"HGT", "Geopotential height", "gpm", UC_NONE},
-   /* 6 */ {"DIST", "Geometric Height", "m", UC_NONE},
+   /* 6 */ {"DIST", "Geometric height", "m", UC_NONE},
    /* 7 */ {"HSTDV", "Standard deviation of height", "m", UC_NONE},
    /* 8 */ {"PRESA", "Pressure anomaly", "Pa", UC_NONE},
    /* 9 */ {"GPA", "Geopotential height anomaly", "gpm", UC_NONE},
    /* 10 */ {"DEN", "Density", "kg/(m^3)", UC_NONE},
-   /* 11 */ {"", "Altimeter setting", "Pa", UC_NONE},
-   /* 12 */ {"", "Thickness", "m", UC_NONE},
-   /* 13 */ {"", "Pressure altitude", "m", UC_NONE},
-   /* 14 */ {"", "Density altitude", "m", UC_NONE},
+   /* 11 */ {"ALTS", "Altimeter setting", "Pa", UC_NONE},
+   /* 12 */ {"THICK", "Thickness", "m", UC_NONE},
+   /* 13 */ {"PRESALT", "Pressure altitude", "m", UC_NONE},
+   /* 14 */ {"DENALT", "Density altitude", "m", UC_NONE},
 /* 15 */    {"5WAVH", "5-wave geopotential height", "gpm", UC_NONE},
 /* 16 */    {"U-GWD", "Zonal flux of gravity wave stress", "N/(m^2)", UC_NONE},
 /* 17 */    {"V-GWD", "Meridional flux of gravity wave stress", "N/(m^2)", UC_NONE},
 /* 18 */    {"HPBL", "Planetary boundary layer height", "m", UC_NONE},
-/* 19 */    {"5WAVA", "5-Wave geopotential height anomaly", "gpm", UC_NONE},
+/* 19 */    {"5WAVA", "5-wave geopotential height anomaly", "gpm", UC_NONE},
+/* 20 */    {"SDSGSO", "Standard deviation of sub-grid scale orography", "m", UC_NONE},
+/* 21 */    {"AOSGSO", "Angle of sub-gridscale orography", "rad", UC_NONE},
+/* 22 */    {"SSGSO", "Slope of sub-gridscale orography", "Numeric", UC_NONE},
+/* 23 */    {"GSGSO", "Gravity wave dissipation", "W/m^2", UC_NONE},
+/* 24 */    {"ASGSO", "Anisotrophy of sub-gridscale orography", "Numeric", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.4 */
@@ -704,6 +743,49 @@ static const GRIB2ParmTable MeteoShortRadiate[] = {
    /* 6 */ {"SWRAD", "Radiance (with respect to wave length)", "W/(m^3 sr)", UC_NONE},
 /* 7 */    {"DSWRF", "Downward short-wave radiation flux", "W/(m^2)", UC_NONE},
 /* 8 */    {"USWRF", "Upward short-wave radiation flux", "W/(m^2)", UC_NONE},
+/* 9 */    {"NSWRF", "Net short wave radiation flux", "W/(m^2)", UC_NONE},
+/* 10 */   {"PHOTAR", "Photosynthetically active radiation", "W/(m^2)", UC_NONE},
+/* 11 */   {"NSWRFCS", "Net short-wave radiation flux; clear sky", "W/(m^2)", UC_NONE},
+/* 12 */   {"DWUVR", "Downward UV radiation", "W/(m^2)", UC_NONE},
+/* 13 */   {"", "Reserved", "-", UC_NONE},
+/* 14 */   {"", "Reserved", "-", UC_NONE},
+/* 15 */   {"", "Reserved", "-", UC_NONE},
+/* 16 */   {"", "Reserved", "-", UC_NONE},
+/* 17 */   {"", "Reserved", "-", UC_NONE},
+/* 18 */   {"", "Reserved", "-", UC_NONE},
+/* 19 */   {"", "Reserved", "-", UC_NONE},
+/* 20 */   {"", "Reserved", "-", UC_NONE},
+/* 21 */   {"", "Reserved", "-", UC_NONE},
+/* 22 */   {"", "Reserved", "-", UC_NONE},
+/* 23 */   {"", "Reserved", "-", UC_NONE},
+/* 24 */   {"", "Reserved", "-", UC_NONE},
+/* 25 */   {"", "Reserved", "-", UC_NONE},
+/* 26 */   {"", "Reserved", "-", UC_NONE},
+/* 27 */   {"", "Reserved", "-", UC_NONE},
+/* 28 */   {"", "Reserved", "-", UC_NONE},
+/* 29 */   {"", "Reserved", "-", UC_NONE},
+/* 30 */   {"", "Reserved", "-", UC_NONE},
+/* 31 */   {"", "Reserved", "-", UC_NONE},
+/* 32 */   {"", "Reserved", "-", UC_NONE},
+/* 33 */   {"", "Reserved", "-", UC_NONE},
+/* 34 */   {"", "Reserved", "-", UC_NONE},
+/* 35 */   {"", "Reserved", "-", UC_NONE},
+/* 36 */   {"", "Reserved", "-", UC_NONE},
+/* 37 */   {"", "Reserved", "-", UC_NONE},
+/* 38 */   {"", "Reserved", "-", UC_NONE},
+/* 39 */   {"", "Reserved", "-", UC_NONE},
+/* 40 */   {"", "Reserved", "-", UC_NONE},
+/* 41 */   {"", "Reserved", "-", UC_NONE},
+/* 42 */   {"", "Reserved", "-", UC_NONE},
+/* 43 */   {"", "Reserved", "-", UC_NONE},
+/* 44 */   {"", "Reserved", "-", UC_NONE},
+/* 45 */   {"", "Reserved", "-", UC_NONE},
+/* 46 */   {"", "Reserved", "-", UC_NONE},
+/* 47 */   {"", "Reserved", "-", UC_NONE},
+/* 48 */   {"", "Reserved", "-", UC_NONE},
+/* 49 */   {"", "Reserved", "-", UC_NONE},
+/* 50 */   {"UVIUCS", "UV index (under clear sky)", "Numeric", UC_NONE},
+/* 51 */   {"UVI", "UV index", "W/(m^2)", UC_UVIndex},
 };
 
 /* GRIB2 Code table 4.2 : 0.5 */
@@ -712,8 +794,10 @@ static const GRIB2ParmTable MeteoLongRadiate[] = {
    /* 1 */ {"NLWRT", "Net long wave radiation flux (top of atmosphere)",
             "W/(m^2)", UC_NONE},
    /* 2 */ {"LWAVR", "Long wave radiation flux", "W/(m^2)", UC_NONE},
-/* 3 */    {"DLWRF", "Downward Long-Wave Rad. Flux", "W/(m^2)", UC_NONE},
-/* 4 */    {"ULWRF", "Upward Long-Wave Rad. Flux", "W/(m^2)", UC_NONE},
+/* 3 */    {"DLWRF", "Downward long-wave radiation flux", "W/(m^2)", UC_NONE},
+/* 4 */    {"ULWRF", "Upward long-wave radiation flux", "W/(m^2)", UC_NONE},
+/* 5 */    {"NLWRF", "Net long wave radiation flux", "W/(m^2)", UC_NONE},
+/* 6 */    {"NLWRCS", "Net long-wave radiation flux; clear sky", "W/(m^2)", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.6 */
@@ -725,22 +809,22 @@ static const GRIB2ParmTable MeteoCloud[] = {
    /* 4 */ {"MCDC", "Medium cloud cover", "%", UC_NONE},
    /* 5 */ {"HCDC", "High cloud cover", "%", UC_NONE},
    /* 6 */ {"CWAT", "Cloud water", "kg/(m^2)", UC_NONE},
-   /* 7 */ {"", "Cloud amount", "%", UC_NONE},
-   /* 8 */ {"", "Cloud type", "(0 clear, 1 Cumulonimbus, 2 Stratus, "
-            "3 Stratocumulus, 4 Cumulus, 5 Altostratus, 6 Nimbostratus, "
-            "7 Altocumulus, 8 Cirrostratus, 9 Cirrocumulus, 10 Cirrus, "
-            "11 Cumulonimbus (fog), 12 Stratus (fog), 13 Stratocumulus (fog),"
-            " 14 Cumulus (fog), 15 Altostratus (fog), 16 Nimbostratus (fog), "
-            "17 Altocumulus (fog), 18 Cirrostratus (fog), "
-            "19 Cirrocumulus (fog), 20 Cirrus (fog), 191 unknown, "
-            "255 missing)", UC_NONE},
-   /* 9 */ {"", "Thunderstorm maximum tops", "m", UC_NONE},
-   /* 10 */ {"", "Thunderstorm coverage", "(0 none, 1 isolated (1%-2%), "
-             "2 few (3%-15%), 3 scattered (16%-45%), 4 numerous (> 45%), "
-             "255 missing)", UC_NONE},
-   /* 11 */ {"", "Cloud base", "m", UC_NONE},
-   /* 12 */ {"", "Cloud top", "m", UC_NONE},
-   /* 13 */ {"", "Ceiling", "m", UC_NONE},
+   /* 7 */ {"CDCA", "Cloud amount", "%", UC_NONE},
+   /* 8 */ {"CDCT", "Cloud type", "0=clear; 1=Cumulonimbus; 2=Stratus; "
+            "3=Stratocumulus; 4=Cumulus; 5=Altostratus; 6=Nimbostratus; "
+            "7=Altocumulus; 8=Cirrostratus; 9=Cirrocumulus; 10=Cirrus; "
+            "11=Cumulonimbus (fog); 12=Stratus (fog); 13=Stratocumulus (fog);"
+            " 14=Cumulus (fog); 15=Altostratus (fog); 16=Nimbostratus (fog); "
+            "17=Altocumulus (fog); 18=Cirrostratus (fog); "
+            "19=Cirrocumulus (fog); 20=Cirrus (fog); 191=unknown; "
+            "255=missing", UC_NONE},
+   /* 9 */ {"TMAXT", "Thunderstorm maximum tops", "m", UC_NONE},
+   /* 10 */ {"THUNC", "Thunderstorm coverage", "0=none; 1=isolated (1%-2%); "
+             "2=few (3%-15%); 3=scattered (16%-45%); 4=numerous (> 45%); "
+             "255=missing", UC_NONE},
+   /* 11 */ {"CDCB", "Cloud base", "m", UC_M2Feet},
+   /* 12 */ {"CDCT", "Cloud top", "m", UC_M2Feet},
+   /* 13 */ {"CEIL", "Ceiling", "m", UC_M2Feet},
 /* 14 */    {"CDLYR", "Non-convective cloud cover", "%", UC_NONE},
 /* 15 */    {"CWORK", "Cloud work function", "J/kg", UC_NONE},
 /* 16 */    {"CUEFI", "Convective cloud efficiency", "-", UC_NONE},
@@ -749,103 +833,279 @@ static const GRIB2ParmTable MeteoCloud[] = {
 /* 19 */    {"TCOLI", "Total column-integrated cloud ice", "kg/(m^2)", UC_NONE},
 /* 20 */    {"TCOLC", "Total column-integrated condensate", "kg/(m^2)", UC_NONE},
 /* 21 */    {"FICE", "Ice fraction of total condensate", "-", UC_NONE},
+/* 22 */    {"CDCC", "Cloud cover", "%", UC_NONE},
+/* 23 */    {"CDCIMR", "Cloud ice mixing ratio", "kg/kg", UC_NONE},
+/* 24 */    {"SUNS", "Sunshine", "Numeric", UC_NONE},
+/* 25 */    {"CBHE", "Horizontal extent of cumulonimbus (CB)", "%", UC_NONE},
+/* 26 */   {"", "Reserved", "-", UC_NONE},
+/* 27 */   {"", "Reserved", "-", UC_NONE},
+/* 28 */   {"", "Reserved", "-", UC_NONE},
+/* 29 */   {"", "Reserved", "-", UC_NONE},
+/* 30 */   {"", "Reserved", "-", UC_NONE},
+/* 31 */   {"", "Reserved", "-", UC_NONE},
+/* 32 */   {"", "Reserved", "-", UC_NONE},
+/* 33 */    {"SUNSD", "SunShine Duration", "s", UC_NONE},
+
 };
 
 /* GRIB2 Code table 4.2 : 0.7 */
-/* NCEP capitalized items 6, 7, 8 */
 static const GRIB2ParmTable MeteoStability[] = {
    /* 0 */ {"PLI", "Parcel lifted index (to 500 hPa)", "K", UC_NONE},
    /* 1 */ {"BLI", "Best lifted index (to 500 hPa)", "K", UC_NONE},
    /* 2 */ {"KX", "K index", "K", UC_NONE},
-   /* 3 */ {"", "KO index", "K", UC_NONE},
-   /* 4 */ {"", "Total totals index", "K", UC_NONE},
+   /* 3 */ {"KOX", "KO index", "K", UC_NONE},
+   /* 4 */ {"TOTALX", "Total totals index", "K", UC_NONE},
    /* 5 */ {"SX", "Sweat index", "numeric", UC_NONE},
    /* 6 */ {"CAPE", "Convective available potential energy", "J/kg", UC_NONE},
    /* 7 */ {"CIN", "Convective inhibition", "J/kg", UC_NONE},
    /* 8 */ {"HLCY", "Storm relative helicity", "J/kg", UC_NONE},
-   /* 9 */ {"", "Energy helicity index", "numeric", UC_NONE},
-// TODO: Spelling fifted.
-/* 10 */   {"LFTX", "Surface fifted index", "K", UC_NONE},
+   /* 9 */ {"EHLX", "Energy helicity index", "numeric", UC_NONE},
+/* 10 */   {"LFTX", "Surface lifted index", "K", UC_NONE},
 /* 11 */   {"4LFTX", "Best (4-layer) lifted index", "K", UC_NONE},
 /* 12 */   {"RI", "Richardson number", "-", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.13 */
 static const GRIB2ParmTable MeteoAerosols[] = {
-   /* 0 */ {"", "Aerosol type", "(0 Aerosol not present, 1 Aerosol present, "
-            "255 missing)", UC_NONE},
+   /* 0 */ {"AEROT", "Aerosol type", "0=Aerosol not present; 1=Aerosol present; "
+            "255=missing", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.14 */
 static const GRIB2ParmTable MeteoGases[] = {
    /* 0 */ {"TOZNE", "Total ozone", "Dobson", UC_NONE},
-/* 1 */    {"O3MR", "Ozone Mixing Ratio", "kg/kg", UC_NONE},
+/* 1 */    {"O3MR", "Ozone mixing ratio", "kg/kg", UC_NONE},
+/* 2 */    {"TCIOZ", "Total column integrated ozone", "Dobson", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.15 */
 static const GRIB2ParmTable MeteoRadar[] = {
-   /* 0 */ {"", "Base spectrum width", "m/s", UC_NONE},
-   /* 1 */ {"", "Base reflectivity", "dB", UC_NONE},
-   /* 2 */ {"", "Base radial velocity", "m/s", UC_NONE},
-   /* 3 */ {"", "Vertically-integrated liquid", "kg/m", UC_NONE},
-   /* 4 */ {"", "Layer-maximum base reflectivity", "dB", UC_NONE},
-   /* 5 */ {"", "Precipitation", "kg/(m^2)", UC_NONE},
+   /* 0 */ {"BSWID", "Base spectrum width", "m/s", UC_NONE},
+   /* 1 */ {"BREF", "Base reflectivity", "dB", UC_NONE},
+   /* 2 */ {"BRVEL", "Base radial velocity", "m/s", UC_NONE},
+   /* 3 */ {"VERIL", "Vertically-integrated liquid", "kg/m", UC_NONE},
+   /* 4 */ {"LMAXBR", "Layer maximum base reflectivity", "dB", UC_NONE},
+   /* 5 */ {"PREC", "Precipitation", "kg/(m^2)", UC_NONE},
    /* 6 */ {"RDSP1", "Radar spectra (1)", "-", UC_NONE},
    /* 7 */ {"RDSP2", "Radar spectra (2)", "-", UC_NONE},
    /* 8 */ {"RDSP3", "Radar spectra (3)", "-", UC_NONE},
 };
 
+/* GRIB2 Code table 4.2 : 0.16 */
+static const GRIB2ParmTable MeteoRadarImagery[] = {
+   /* 0 */ {"REFZR", "Equivalent radar reflectivity for rain", "mm^6/m^3", UC_NONE},
+   /* 1 */ {"REFZI", "Equivalent radar reflectivity for snow", "mm^6/m^3", UC_NONE},
+   /* 2 */ {"REFZC", "Equivalent radar reflectivity for parameterized convection", "mm^6/m^3", UC_NONE},
+   /* 3 */ {"RETOP", "Echo Top", "m", UC_NONE},
+   /* 4 */ {"REFD", "Reflectivity", "dB", UC_NONE},
+   /* 5 */ {"REFC", "Composity reflectivity", "dB", UC_NONE},
+};
+
 /* GRIB2 Code table 4.2 : 0.18 */
 static const GRIB2ParmTable MeteoNuclear[] = {
-   /* 0 */ {"", "Air concentration of Caesium 137", "Bq/(m^3)", UC_NONE},
-   /* 1 */ {"", "Air concentration of Iodine 131", "Bq/(m^3)", UC_NONE},
-   /* 2 */ {"", "Air concentration of radioactive pollutant", "Bq/(m^3)", UC_NONE},
-   /* 3 */ {"", "Ground deposition of Caesium 137", "Bq/(m^2)", UC_NONE},
-   /* 4 */ {"", "Ground deposition of Iodine 131", "Bq/(m^2)", UC_NONE},
-   /* 5 */ {"", "Ground deposition of radioactive pollutant", "Bq/(m^2)", UC_NONE},
-   /* 6 */ {"", "Time-integrated air concentration of caesium pollutant",
+   /* 0 */ {"ACCES", "Air concentration of Caesium 137", "Bq/(m^3)", UC_NONE},
+   /* 1 */ {"ACIOD", "Air concentration of Iodine 131", "Bq/(m^3)", UC_NONE},
+   /* 2 */ {"ACRADP", "Air concentration of radioactive pollutant", "Bq/(m^3)", UC_NONE},
+   /* 3 */ {"GDCES", "Ground deposition of Caesium 137", "Bq/(m^2)", UC_NONE},
+   /* 4 */ {"GDIOD", "Ground deposition of Iodine 131", "Bq/(m^2)", UC_NONE},
+   /* 5 */ {"GDRADP", "Ground deposition of radioactive pollutant", "Bq/(m^2)", UC_NONE},
+   /* 6 */ {"TIACCP", "Time-integrated air concentration of caesium pollutant",
             "(Bq s)/(m^3)", UC_NONE},
-   /* 7 */ {"", "Time-integrated air concentration of iodine pollutant",
+   /* 7 */ {"TIACIP", "Time-integrated air concentration of iodine pollutant",
             "(Bq s)/(m^3)", UC_NONE},
-   /* 8 */ {"", "Time-integrated air concentration of radioactive pollutant",
+   /* 8 */ {"TIACRP", "Time-integrated air concentration of radioactive pollutant",
             "(Bq s)/(m^3)", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 0.19 */
 /* NCEP capitalized items 11 */
 static const GRIB2ParmTable MeteoAtmos[] = {
-   /* 0 */ {"VIS", "Visibility", "m", UC_NONE},
+   /* 0 */ {"VIS", "Visibility", "m", UC_M2StatuteMile},
    /* 1 */ {"ALBDO", "Albedo", "%", UC_NONE},
    /* 2 */ {"TSTM", "Thunderstorm probability", "%", UC_NONE},
-   /* 3 */ {"MIXHT", "mixed layer depth", "m", UC_NONE},
-   /* 4 */ {"", "Volcanic ash", "(0 not present, 1 present, 255 missing)", UC_NONE},
-   /* 5 */ {"", "Icing top", "m", UC_NONE},
-   /* 6 */ {"", "Icing base", "m", UC_NONE},
-   /* 7 */ {"", "Icing", "(0 None, 1 Light, 2 Moderate, 3 Severe, "
-            "255 missing)", UC_NONE},
-   /* 8 */ {"", "Turbulance top", "m", UC_NONE},
-   /* 9 */ {"", "Turbulence base", "m", UC_NONE},
-   /* 10 */ {"", "Turbulance", "(0 None(smooth), 1 Light, 2 Moderate, "
-             "3 Severe, 4 Extreme, 255 missing)", UC_NONE},
-   /* 11 */ {"TKE", "Turbulent Kinetic Energy", "J/kg", UC_NONE},
-   /* 12 */ {"", "Planetary boundary layer regime", "(0 Reserved, 1 Stable, "
-             "2 Mechanically driven turbulence, 3 Forced convection, "
-             "4 Free convection, 255 missing)", UC_NONE},
-   /* 13 */ {"", "Contrail intensity", "(0 Contrail not present, "
-             "1 Contrail present, 255 missing)", UC_NONE},
-   /* 14 */ {"", "Contrail engine type", "(0 Low bypass, 1 High bypass, "
-             "2 Non bypass, 255 missing)", UC_NONE},
-   /* 15 */ {"", "Contrail top", "m", UC_NONE},
-   /* 16 */ {"", "Contrail base", "m", UC_NONE},
+   /* 3 */ {"MIXHT", "Mixed layer depth", "m", UC_NONE},
+   /* 4 */ {"VOLASH", "Volcanic ash", "0=not present; 1=present; 255=missing", UC_NONE},
+   /* 5 */ {"ICIT", "Icing top", "m", UC_NONE},
+   /* 6 */ {"ICIB", "Icing base", "m", UC_NONE},
+   /* 7 */ {"ICI", "Icing", "0=None; 1=Light; 2=Moderate; 3=Severe; "
+            "255=missing", UC_NONE},
+   /* 8 */ {"TURBT", "Turbulance top", "m", UC_NONE},
+   /* 9 */ {"TURBB", "Turbulence base", "m", UC_NONE},
+   /* 10 */ {"TURB", "Turbulance", "0=None(smooth); 1=Light; 2=Moderate; "
+             "3=Severe; 4=Extreme; 255=missing", UC_NONE},
+   /* 11 */ {"TKE", "Turbulent kinetic energy", "J/kg", UC_NONE},
+   /* 12 */ {"PBLREG", "Planetary boundary layer regime", "0=Reserved; 1=Stable; "
+             "2=Mechanically driven turbulence; 3=Forced convection; "
+             "4=Free convection; 255=missing", UC_NONE},
+   /* 13 */ {"CONTI", "Contrail intensity", "0=Contrail not present; "
+             "1=Contrail present; 255=missing", UC_NONE},
+   /* 14 */ {"CONTET", "Contrail engine type", "0=Low bypass; 1=High bypass; "
+             "2=Non bypass; 255=missing", UC_NONE},
+   /* 15 */ {"CONTT", "Contrail top", "m", UC_NONE},
+   /* 16 */ {"CONTB", "Contrail base", "m", UC_NONE},
 /* 17 */    {"MXSALB", "Maximum snow albedo", "%", UC_NONE},
 /* 18 */    {"SNFALB", "Snow free albedo", "%", UC_NONE},
+/* 19 */    {"SALBD", "Snow albedo", "%", UC_NONE},
+            {"ICIP", "Icing", "%", UC_NONE},
+            {"CTP", "In-Cloud Turbulence", "%", UC_NONE},
+            {"CAT", "Clear Air Turbulence", "%", UC_NONE},
+            {"SLDP", "Supercooled Large Droplet Probability", "%", UC_NONE},
+/* Mike added 3/2012 */
+/* 24 */    {"CONTKE", "Convective Turbulent Kinetic Energy", "J/kg", UC_NONE},
+/* 25 */    {"WIWW", "Weather Interpretation ww (WMO)", " ", UC_NONE},
+/* 26 */    {"CONVO", "Convective Outlook",  "0=No Risk Area; 1=Reserved; "
+             "2=General Thunderstorm Risk Area; 3=Reserved; 4=Slight Risk Area; "
+             "5=Reserved; 6=Moderate Risk Area;  7=Reserved; 8=High Risk Area; "
+             "9-10=Reserved; 11=Dry Thunderstorm (Dry Lightning) Risk Area; "
+             "12-13=Reserved; 14=Critical Risk Area; 15-17=Reserved"
+             "18=Extremely Critical Risk Area; 255=missing", UC_NONE},
+};
+
+/* GRIB2 Code table 4.2 : 0.20 */
+static const GRIB2ParmTable MeteoAtmoChem[] = {
+   /* 0 */  {"MASSDEN", "Mass Density (Concentration)", "kg/(m^3)", UC_NONE},
+   /* 1 */  {"COLMD", "Column-Integrated Mass Density", "kg/(m^2)", UC_NONE},
+   /* 2 */  {"MASSMR", "Mass Mixing Ratio (Mass Fraction in Air)", "kg/kg", UC_NONE},
+   /* 3 */  {"AEMFLX", "Atmosphere Emission Mass Flux", "kg/(m^2*s)", UC_NONE},
+   /* 4 */  {"ANPMFLX", "Atmosphere Net Production Mass Flux", "kg/(m^2*s)", UC_NONE},
+   /* 5 */  {"ANPEMFLX", "Atmosphere Net Production and Emission Mass Flux", "kg/(m^2*s)", UC_NONE},
+   /* 6 */  {"SDDMFLX", "Surface Dry Deposition Mass Flux", "kg/(m^2*s)", UC_NONE},
+   /* 7 */  {"SWDMFLX", "Surface Wet Deposition Mass Flux", "kg/(m^2*s)", UC_NONE},
+   /* 8 */  {"AREMFLX", "Atmosphere Re-Emission Mass Flux", "kg/(m^2*s)", UC_NONE},
+   /* 9 */  {"", "Reserved", "-", UC_NONE},
+  /* 10 */  {"", "Reserved", "-", UC_NONE},
+  /* 11 */  {"", "Reserved", "-", UC_NONE},
+  /* 12 */  {"", "Reserved", "-", UC_NONE},
+  /* 13 */  {"", "Reserved", "-", UC_NONE},
+  /* 14 */  {"", "Reserved", "-", UC_NONE},
+  /* 15 */  {"", "Reserved", "-", UC_NONE},
+  /* 16 */  {"", "Reserved", "-", UC_NONE},
+  /* 17 */  {"", "Reserved", "-", UC_NONE},
+  /* 18 */  {"", "Reserved", "-", UC_NONE},
+  /* 19 */  {"", "Reserved", "-", UC_NONE},
+  /* 20 */  {"", "Reserved", "-", UC_NONE},
+  /* 21 */  {"", "Reserved", "-", UC_NONE},
+  /* 22 */  {"", "Reserved", "-", UC_NONE},
+  /* 23 */  {"", "Reserved", "-", UC_NONE},
+  /* 24 */  {"", "Reserved", "-", UC_NONE},
+  /* 25 */  {"", "Reserved", "-", UC_NONE},
+  /* 26 */  {"", "Reserved", "-", UC_NONE},
+  /* 27 */  {"", "Reserved", "-", UC_NONE},
+  /* 28 */  {"", "Reserved", "-", UC_NONE},
+  /* 29 */  {"", "Reserved", "-", UC_NONE},
+  /* 30 */  {"", "Reserved", "-", UC_NONE},
+  /* 31 */  {"", "Reserved", "-", UC_NONE},
+  /* 32 */  {"", "Reserved", "-", UC_NONE},
+  /* 33 */  {"", "Reserved", "-", UC_NONE},
+  /* 34 */  {"", "Reserved", "-", UC_NONE},
+  /* 35 */  {"", "Reserved", "-", UC_NONE},
+  /* 36 */  {"", "Reserved", "-", UC_NONE},
+  /* 37 */  {"", "Reserved", "-", UC_NONE},
+  /* 38 */  {"", "Reserved", "-", UC_NONE},
+  /* 39 */  {"", "Reserved", "-", UC_NONE},
+  /* 40 */  {"", "Reserved", "-", UC_NONE},
+  /* 41 */  {"", "Reserved", "-", UC_NONE},
+  /* 42 */  {"", "Reserved", "-", UC_NONE},
+  /* 43 */  {"", "Reserved", "-", UC_NONE},
+  /* 44 */  {"", "Reserved", "-", UC_NONE},
+  /* 45 */  {"", "Reserved", "-", UC_NONE},
+  /* 46 */  {"", "Reserved", "-", UC_NONE},
+  /* 47 */  {"", "Reserved", "-", UC_NONE},
+  /* 48 */  {"", "Reserved", "-", UC_NONE},
+  /* 49 */  {"", "Reserved", "-", UC_NONE},
+  /* 50 */  {"AIA", "Amount in Atmosphere", "mol", UC_NONE},
+  /* 51 */  {"CONAIR", "Concentration in Air", "mol/(m^3)", UC_NONE},
+  /* 52 */  {"VMXR", "Volume Mixing Ratio (Fraction in Air)", "mol/mol", UC_NONE},
+  /* 53 */  {"CGPRC", "Chemical Gross Production Rate of Concentration", "mol/(m^3*s)", UC_NONE},
+  /* 54 */  {"CGDRC", "Chemical Gross Destruction Rate of Concentration", "mol/(m^3*s)", UC_NONE},
+  /* 55 */  {"SFLUX", "Surface Flux", "mol/(m^2*s)", UC_NONE},
+  /* 56 */  {"COAIA", "Changes of Amount in Atmosphere", "mol/s", UC_NONE},
+  /* 57 */  {"TYABA", "Total Yearly Average Burden of the Atmosphere", "mol", UC_NONE},
+  /* 58 */  {"TYAAL", "Total Yearly Average Atmospheric Loss", "mol/s", UC_NONE},
+  /* 59 */  {"", "Reserved", "-", UC_NONE},
+  /* 60 */  {"", "Reserved", "-", UC_NONE},
+  /* 61 */  {"", "Reserved", "-", UC_NONE},
+  /* 62 */  {"", "Reserved", "-", UC_NONE},
+  /* 63 */  {"", "Reserved", "-", UC_NONE},
+  /* 64 */  {"", "Reserved", "-", UC_NONE},
+  /* 65 */  {"", "Reserved", "-", UC_NONE},
+  /* 66 */  {"", "Reserved", "-", UC_NONE},
+  /* 67 */  {"", "Reserved", "-", UC_NONE},
+  /* 68 */  {"", "Reserved", "-", UC_NONE},
+  /* 69 */  {"", "Reserved", "-", UC_NONE},
+  /* 70 */  {"", "Reserved", "-", UC_NONE},
+  /* 71 */  {"", "Reserved", "-", UC_NONE},
+  /* 72 */  {"", "Reserved", "-", UC_NONE},
+  /* 73 */  {"", "Reserved", "-", UC_NONE},
+  /* 74 */  {"", "Reserved", "-", UC_NONE},
+  /* 75 */  {"", "Reserved", "-", UC_NONE},
+  /* 76 */  {"", "Reserved", "-", UC_NONE},
+  /* 77 */  {"", "Reserved", "-", UC_NONE},
+  /* 78 */  {"", "Reserved", "-", UC_NONE},
+  /* 79 */  {"", "Reserved", "-", UC_NONE},
+  /* 80 */  {"", "Reserved", "-", UC_NONE},
+  /* 81 */  {"", "Reserved", "-", UC_NONE},
+  /* 82 */  {"", "Reserved", "-", UC_NONE},
+  /* 83 */  {"", "Reserved", "-", UC_NONE},
+  /* 84 */  {"", "Reserved", "-", UC_NONE},
+  /* 85 */  {"", "Reserved", "-", UC_NONE},
+  /* 86 */  {"", "Reserved", "-", UC_NONE},
+  /* 87 */  {"", "Reserved", "-", UC_NONE},
+  /* 88 */  {"", "Reserved", "-", UC_NONE},
+  /* 89 */  {"", "Reserved", "-", UC_NONE},
+  /* 90 */  {"", "Reserved", "-", UC_NONE},
+  /* 91 */  {"", "Reserved", "-", UC_NONE},
+  /* 92 */  {"", "Reserved", "-", UC_NONE},
+  /* 93 */  {"", "Reserved", "-", UC_NONE},
+  /* 94 */  {"", "Reserved", "-", UC_NONE},
+  /* 95 */  {"", "Reserved", "-", UC_NONE},
+  /* 96 */  {"", "Reserved", "-", UC_NONE},
+  /* 97 */  {"", "Reserved", "-", UC_NONE},
+  /* 98 */  {"", "Reserved", "-", UC_NONE},
+  /* 99 */  {"", "Reserved", "-", UC_NONE},
+ /* 100 */  {"SADEN", "Surface Area Density (Aerosol)", "1/m", UC_NONE},
+ /* 101 */  {"AOTK", "Atmosphere Optical Thickness", "m", UC_NONE},
+ /* 102 */  {"", "Reserved", "-", UC_NONE},
+ /* 103 */  {"", "Reserved", "-", UC_NONE},
+ /* 104 */  {"", "Reserved", "-", UC_NONE},
+ /* 105 */  {"", "Reserved", "-", UC_NONE},
+ /* 106 */  {"", "Reserved", "-", UC_NONE},
+ /* 107 */  {"", "Reserved", "-", UC_NONE},
+ /* 108 */  {"", "Reserved", "-", UC_NONE},
+ /* 109 */  {"", "Reserved", "-", UC_NONE},
+ /* 110 */  {"", "Reserved", "-", UC_NONE},
+ /* 111 */  {"", "Reserved", "-", UC_NONE},
+ /* 112 */  {"", "Reserved", "-", UC_NONE},
+ /* 113 */  {"", "Reserved", "-", UC_NONE},
+ /* 114 */  {"", "Reserved", "-", UC_NONE},
+ /* 115 */  {"", "Reserved", "-", UC_NONE},
+ /* 116 */  {"", "Reserved", "-", UC_NONE},
+ /* 117 */  {"", "Reserved", "-", UC_NONE},
+ /* 118 */  {"", "Reserved", "-", UC_NONE},
+ /* 119 */  {"", "Reserved", "-", UC_NONE},
+ /* 120 */  {"", "Reserved", "-", UC_NONE},
+ /* 121 */  {"", "Reserved", "-", UC_NONE},
+ /* 122 */  {"", "Reserved", "-", UC_NONE},
+ /* 123 */  {"", "Reserved", "-", UC_NONE},
+ /* 124 */  {"", "Reserved", "-", UC_NONE},
+ /* 125 */  {"", "Reserved", "-", UC_NONE},
+ /* 126 */  {"", "Reserved", "-", UC_NONE},
+ /* 127 */  {"", "Reserved", "-", UC_NONE},
+ /* 128 */  {"", "Reserved", "-", UC_NONE},
+ /* 129 */  {"", "Reserved", "-", UC_NONE},
+ /* 130 */  {"", "Reserved", "-", UC_NONE},
+ /* 131 */  {"NO2TROP", "Nitrogen Dioxide (NO2) Tropospheric Column", "mol/(cm^2)", UC_NONE},
+ /* 132 */  {"NO2VCD", "Nitrogen Dioxide (NO2) Vertical Column Density", "mol/(cm^2)", UC_NONE},
+ /* 133 */  {"BROVCD", "Bromine Monoxide (BrO) Vertical Column Density", "mol/(cm^2)", UC_NONE},
+ /* 134 */  {"HCHOVCD", "Formaldehyde (HCHO) Vertical Column Density", "mol/(cm^2)", UC_NONE},
 };
 
-/* GRIB2 Code table 4.2 : 0.253 or 0.190 (Document is inconsistent.) */
+/* GRIB2 Code table 4.2 : 0.190 */
 static const GRIB2ParmTable MeteoText[] = {
    /* 0 */ {"", "Arbitrary text string", "CCITTIA5", UC_NONE},
 };
 
+/* GRIB2 Code table 4.2 : 0.191 */
 static const GRIB2ParmTable MeteoMisc[] = {
    /* 0 */ {"TSEC", "Seconds prior to initial reference time (defined in Section"
             " 1)", "s", UC_NONE},
@@ -853,22 +1113,22 @@ static const GRIB2ParmTable MeteoMisc[] = {
 
 /* GRIB2 Code table 4.2 : 1.0 */
 static const GRIB2ParmTable HydroBasic[] = {
-   /* 0 */ {"", "Flash flood guidance", "kg/(m^2)", UC_NONE},
-   /* 1 */ {"", "Flash flood runoff", "kg/(m^2)", UC_NONE},
-   /* 2 */ {"", "Remotely sensed snow cover", "(50 no-snow/no-cloud, "
-            "100 Clouds, 250 Snow, 255 missing)", UC_NONE},
-   /* 3 */ {"", "Elevation of snow covered terrain", "(0-90 elevation in "
-            "increments of 100m, 254 clouds, 255 missing)", UC_NONE},
-   /* 4 */ {"", "Snow water equivalent percent of normal", "%", UC_NONE},
+   /* 0 */ {"FFLDG", "Flash flood guidance", "kg/(m^2)", UC_NONE},
+   /* 1 */ {"FFLDRO", "Flash flood runoff", "kg/(m^2)", UC_NONE},
+   /* 2 */ {"RSSC", "Remotely sensed snow cover", "50=no-snow/no-cloud; "
+            "100=Clouds; 250=Snow; 255=missing", UC_NONE},
+   /* 3 */ {"ESCT", "Elevation of snow covered terrain", "0-90=elevation in "
+            "increments of 100m; 254=clouds; 255=missing", UC_NONE},
+   /* 4 */ {"SWEPON", "Snow water equivalent percent of normal", "%", UC_NONE},
 /* 5 */    {"BGRUN", "Baseflow-groundwater runoff", "kg/(m^2)", UC_NONE},
 /* 6 */    {"SSRUN", "Storm surface runoff", "kg/(m^2)", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 1.1 */
 static const GRIB2ParmTable HydroProb[] = {
-   /* 0 */ {"", "Conditional percent precipitation amount fractile for an "
+   /* 0 */ {"CPPOP", "Conditional percent precipitation amount fractile for an "
             "overall period", "kg/(m^2)", UC_NONE},
-   /* 1 */ {"", "Percent precipitation in a sub-period of an overall period",
+   /* 1 */ {"PPOSP", "Percent precipitation in a sub-period of an overall period",
             "%", UC_NONE},
    /* 2 */ {"PoP", "Probability of 0.01 inch of precipitation", "%", UC_NONE},
 };
@@ -881,13 +1141,13 @@ static const GRIB2ParmTable LandVeg[] = {
    /* 3 */ {"SOILM", "Soil moisture content", "kg/(m^2)", UC_NONE},
    /* 4 */ {"VEG", "Vegetation", "%", UC_NONE},
    /* 5 */ {"WATR", "Water runoff", "kg/(m^2)", UC_NONE},
-   /* 6 */ {"", "Evapotranspiration", "1/(kg^2 s)", UC_NONE},
-   /* 7 */ {"", "Model terrain height", "m", UC_NONE},
-   /* 8 */ {"", "Land use", "(1 Urban land, 2 agriculture, 3 Range Land, "
-            "4 Deciduous forest, 5 Coniferous forest, 6 Forest/wetland, "
-            "7 Water, 8 Wetlands, 9 Desert, 10 Tundra, 11 Ice, "
-            "12 Tropical forest, 13 Savannah)", UC_NONE},
-/* 9 */    {"SOILW", "Volumetric soil moisture content", "fraction", UC_NONE},
+   /* 6 */ {"EVAPT", "Evapotranspiration", "1/(kg^2 s)", UC_NONE},
+   /* 7 */ {"MTERH", "Model terrain height", "m", UC_NONE},
+   /* 8 */ {"LANDU", "Land use", "1=Urban land; 2=agriculture; 3=Range Land; "
+            "4=Deciduous forest; 5=Coniferous forest; 6=Forest/wetland; "
+            "7=Water; 8=Wetlands; 9=Desert; 10=Tundra; 11=Ice; "
+            "12=Tropical forest; 13=Savannah", UC_NONE},
+/* 9 */    {"SOILW", "Volumetric soil moisture content", "Proportion", UC_NONE},
 /* 10 */   {"GFLUX", "Ground heat flux", "W/(m^2)", UC_NONE},
 /* 11 */   {"MSTAV", "Moisture availability", "%", UC_NONE},
 /* 12 */   {"SFEXC", "Exchange coefficient", "(kg/(m^3))(m/s)", UC_NONE},
@@ -895,63 +1155,87 @@ static const GRIB2ParmTable LandVeg[] = {
 /* 14 */   {"BMIXL", "Blackadar's mixing length scale", "m", UC_NONE},
 /* 15 */   {"CCOND", "Canopy conductance", "m/s", UC_NONE},
 /* 16 */   {"RSMIN", "Minimal stomatal resistance", "s/m", UC_NONE},
-/* 17 */   {"WILT", "Wilting point", "fraction", UC_NONE},
-/* 18 */   {"RCS", "Solar parameter in canopy conductance", "fraction", UC_NONE},
-/* 19 */   {"RCT", "Temperature parameter in canopy conductance", "fraction", UC_NONE},
-/* 20 */   {"RCSOL", "Soil moisture parameter in canopy conductance", "fraction", UC_NONE},
-/* 21 */   {"RCQ", "Humidity parameter in canopy conductance", "fraction", UC_NONE},
+/* 17 */   {"WILT", "Wilting point", "Proportion", UC_NONE},
+/* 18 */   {"RCS", "Solar parameter in canopy conductance", "Proportion", UC_NONE},
+/* 19 */   {"RCT", "Temperature parameter in canopy conductance", "Proportion", UC_NONE},
+/* 20 */   {"RCSOL", "Soil moisture parameter in canopy conductance", "Proportion", UC_NONE},
+/* 21 */   {"RCQ", "Humidity parameter in canopy conductance", "Proportion", UC_NONE},
+/* 22 */   {"SOILM", "Soil moisture", "kg/m^3", UC_NONE},
+/* 23 */   {"CISOILW", "Column-integrated soil water", "kg/m^2", UC_NONE},
+/* 24 */   {"HFLUX", "Heat flux", "W/m^2", UC_NONE},
+/* 25 */   {"VSOILM", "Volumetric soil moisture", "m^3/m^3", UC_NONE},
+/* 26 */   {"WILT", "Wilting point", "kg/m^3", UC_NONE},
+/* 27 */   {"VWILTM", "Volumetric wilting moisture", "m^3/m^3", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 2.3 */
 /* NCEP changed 0 to be "Soil type (as in Zobler)" I ignored them */
 static const GRIB2ParmTable LandSoil[] = {
-   /* 0 */ {"SOTYP", "Soil type", "(1 Sand, 2 Loamy sand, 3 Sandy loam, "
-            "4 Silt loam, 5 Organic (redefined), 6 Sandy clay loam, "
-            "7 Silt clay loam, 8 Clay loam, 9 Sandy clay, 10 Silty clay, "
-            "11 Clay)", UC_NONE},
-   /* 1 */ {"", "Upper layer soil temperature", "K", UC_NONE},
-   /* 2 */ {"", "Upper layer soil moisture", "kg/(m^3)", UC_NONE},
-   /* 3 */ {"", "Lower layer soil moisture", "kg/(m^3)", UC_NONE},
-   /* 4 */ {"", "Bottom layer soil temperature", "K", UC_NONE},
-/* 5 */ {"SOILL", "Liquid volumetric soil moisture (non-frozen)", "fraction", UC_NONE},
-/* 6 */ {"RLYRS", "Number of soil layers in root zone", "-", UC_NONE},
-/* 7 */ {"SMREF", "Transpiration stress-onset (soil moisture)", "fraction", UC_NONE},
-/* 8 */ {"SMDRY", "Direct evaporation cease (soil moisture)", "fraction", UC_NONE},
-/* 9 */ {"POROS", "Soil porosity", "fraction", UC_NONE},
+   /* 0 */ {"SOTYP", "Soil type", "1=Sand; 2=Loamy sand; 3=Sandy loam; "
+            "4=Silt loam; 5=Organic (redefined); 6=Sandy clay loam; "
+            "7=Silt clay loam; 8=Clay loam; 9=Sandy clay; 10=Silty clay; "
+            "11=Clay", UC_NONE},
+   /* 1 */ {"UPLST", "Upper layer soil temperature", "K", UC_NONE},
+   /* 2 */ {"UPLSM", "Upper layer soil moisture", "kg/(m^3)", UC_NONE},
+   /* 3 */ {"LOWLSM", "Lower layer soil moisture", "kg/(m^3)", UC_NONE},
+   /* 4 */ {"BOTLST", "Bottom layer soil temperature", "K", UC_NONE},
+/* 5 */ {"SOILL", "Liquid volumetric soil moisture (non-frozen)", "Proportion", UC_NONE},
+/* 6 */ {"RLYRS", "Number of soil layers in root zone", "Numeric", UC_NONE},
+/* 7 */ {"SMREF", "Transpiration stress-onset (soil moisture)", "Proportion", UC_NONE},
+/* 8 */ {"SMDRY", "Direct evaporation cease (soil moisture)", "Proportion", UC_NONE},
+/* 9 */ {"POROS", "Soil porosity", "Proportion", UC_NONE},
+/* 10 */ {"LIQVSM", "Liquid volumetric soil moisture (non-frozen)", "m^3/m^3", UC_NONE},
+/* 11 */ {"VOLTSO", "Volumetric transpiration stress-onset (soil moisture)", "m^3/m^3", UC_NONE},
+/* 12 */ {"TRANSO", "Transpiration stress-onset (soil moisture)", "kg/m^3", UC_NONE},
+/* 13 */ {"VOLDEC", "Volumetric direct evaporation cease (soil moisture)", "m^3/m^3", UC_NONE},
+/* 14 */ {"DIREC", "Direct evaporation cease (soil moisture)", "kg/m^3", UC_NONE},
+/* 15 */ {"SOILP", "Soil porosity", "m^3/m^3", UC_NONE},
+/* 16 */ {"VSOSM", "Volumetric saturation of soil moisture", "m^3/m^3", UC_NONE},
+/* 17 */ {"SATOSM", "Saturation of soil moisture", "kg/m^3", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 3.0 */
 static const GRIB2ParmTable SpaceImage[] = {
-   /* 0 */ {"", "Scaled radiance", "numeric", UC_NONE},
-   /* 1 */ {"", "Scaled albedo", "numeric", UC_NONE},
-   /* 2 */ {"", "Scaled brightness temperature", "numeric", UC_NONE},
-   /* 3 */ {"", "Scaled precipitable water", "numeric", UC_NONE},
-   /* 4 */ {"", "Scaled lifted index", "numeric", UC_NONE},
-   /* 5 */ {"", "Scaled cloud top pressure", "numeric", UC_NONE},
-   /* 6 */ {"", "Scaled skin temperature", "numeric", UC_NONE},
-   /* 7 */ {"", "Cloud mask", "(0 clear over water, 1 clear over land, "
-            "2 cloud)", UC_NONE},
-/* 8 */ {"", "Pixel scene type", "(0 No scene, 1 needle, 2 broad-leafed, "
-         "3 Deciduous needle, 4 Deciduous broad-leafed, 5 Deciduous mixed, "
-         "6 Closed shrub, 7 Open shrub, 8 Woody savannah, 9 Savannah, "
-         "10 Grassland, 11 wetland, 12 Cropland, 13 Urban, 14 crops, "
-         "15 snow, 16 Desert, 17 Water, 18 Tundra, 97 Snow on land, "
-         "98 Snow on water, 99 Sun-glint, 100 General cloud, "
-         "101 (fog, Stratus), 102 Stratocumulus, 103 Low cloud, "
-         "104 Nimbotratus, 105 Altostratus, 106 Medium cloud, 107 Cumulus, "
-         "108 Cirrus, 109 High cloud, 110 Unknown cloud)", UC_NONE},
+   /* 0 */ {"SRAD", "Scaled radiance", "Numeric", UC_NONE},
+   /* 1 */ {"SALBEDO", "Scaled albedo", "Numeric", UC_NONE},
+   /* 2 */ {"SBTMP", "Scaled brightness temperature", "Numeric", UC_NONE},
+   /* 3 */ {"SPWAT", "Scaled precipitable water", "Numeric", UC_NONE},
+   /* 4 */ {"SLFTI", "Scaled lifted index", "Numeric", UC_NONE},
+   /* 5 */ {"SCTPRES", "Scaled cloud top pressure", "Numeric", UC_NONE},
+   /* 6 */ {"SSTMP", "Scaled skin temperature", "Numeric", UC_NONE},
+   /* 7 */ {"CLOUDM", "Cloud mask", "0=clear over water; 1=clear over land; "
+            "2=cloud", UC_NONE},
+/* 8 */ {"PIXST", "Pixel scene type", "0=No scene; 1=needle; 2=broad-leafed; "
+         "3=Deciduous needle; 4=Deciduous broad-leafed; 5=Deciduous mixed; "
+         "6=Closed shrub; 7=Open shrub; 8=Woody savannah; 9=Savannah; "
+         "10=Grassland; 11=wetland; 12=Cropland; 13=Urban; 14=crops; "
+         "15=snow; 16=Desert; 17=Water; 18=Tundra; 97=Snow on land; "
+         "98=Snow on water; 99=Sun-glint; 100=General cloud; "
+         "101=fog Stratus; 102=Stratocumulus; 103=Low cloud; "
+         "104=Nimbotratus; 105=Altostratus; 106=Medium cloud; 107=Cumulus; "
+         "108=Cirrus; 109=High cloud; 110=Unknown cloud", UC_NONE},
+/* 9 */ {"FIREDI", "Fire detection indicator", "0=No fire detected; "
+         "1=Possible fire detected; 2=Probable fire detected", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 3.1 */
 static const GRIB2ParmTable SpaceQuantitative[] = {
-   /* 0 */ {"", "Estimated precipitation", "kg/(m^2)", UC_NONE},
-/* 1 */ {"", "Instantaneous rain rate", "kg/(m^2*s)", UC_NONE},
-/* 2 */ {"", "Cloud top height", "kg/(m^2*s)", UC_NONE},
-/* 3 */ {"", "Cloud top height quality indicator", "(0 Nominal cloud top "
-         "height quality, 1 Fog in segment, 2 Poor quality height estimation "
-         "3 Fog in segment and poor quality height estimation)", UC_NONE},
-/* 4 */ {"", "Estimated u component of wind", "m/s", UC_NONE},
-/* 5 */ {"", "Estimated v component of wind", "m/s", UC_NONE},
+   /* 0 */ {"ESTP", "Estimated precipitation", "kg/(m^2)", UC_NONE},
+/* 1 */ {"IRRATE", "Instantaneous rain rate", "kg/(m^2*s)", UC_NONE},
+/* 2 */ {"CTOPH", "Cloud top height", "kg/(m^2*s)", UC_NONE},
+/* 3 */ {"CTOPHQI", "Cloud top height quality indicator", "0=Nominal cloud top "
+         "height quality; 1=Fog in segment; 2=Poor quality height estimation; "
+         "3=Fog in segment and poor quality height estimation", UC_NONE},
+/* 4 */ {"ESTUGRD", "Estimated u component of wind", "m/s", UC_NONE},
+/* 5 */ {"ESTVGRD", "Estimated v component of wind", "m/s", UC_NONE},
+/* 6 */ {"NPIXU", "Number of pixels used", "Numeric", UC_NONE},
+/* 7 */ {"SOLZA", "Solar zenith angle", "Degree", UC_NONE},
+/* 8 */ {"RAZA", "Relative azimuth angle", "Degree", UC_NONE},
+/* 9 */ {"RFL06", "Reflectance in 0.6 micron channel", "%", UC_NONE},
+/* 10 */ {"RFL08", "Reflectance in 0.8 micron channel", "%", UC_NONE},
+/* 11 */ {"RFL16", "Reflectance in 1.6 micron channel", "%", UC_NONE},
+/* 12 */ {"RFL39", "Reflectance in 3.9 micron channel", "%", UC_NONE},
+/* 13 */ {"ATMDIV", "Atmospheric divergence", "1/s", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 10.0 */
@@ -990,6 +1274,7 @@ static const GRIB2ParmTable OceanIce[] = {
    /* 5 */ {"VICE", "v-component of ice drift", "m/s", UC_NONE},
    /* 6 */ {"ICEG", "Ice growth rate", "m/s", UC_NONE},
    /* 7 */ {"ICED", "Ice divergence", "1/s", UC_NONE},
+   /* 8 */ {"ICET", "Ice temperature", "K", UC_NONE},
 };
 
 /* GRIB2 Code table 4.2 : 10.3 */
@@ -1008,6 +1293,13 @@ static const GRIB2ParmTable OceanSubSurface[] = {
 };
 #endif
 
+/* GRIB2 Code table 4.2 : 10.191 */
+static const GRIB2ParmTable OceanMisc[] = {
+   /* 0 */ {"TSEC", "Seconds prior to initial reference time (defined in Section"
+            " 1)", "s", UC_NONE},
+   /* 1 */ {"MOSF", "Meridonal Overturning Stream Function", "m^3/s", UC_NONE},
+};
+
 /* *INDENT-ON* */
 
 /*****************************************************************************
@@ -1043,14 +1335,14 @@ static const GRIB2ParmTable *Choose_GRIB2ParmTable (int prodType, int cat,
       METEO_MOISTURE_PROB = 10, METEO_MOMENT_PROB = 11, METEO_MASS_PROB = 12,
       METEO_AEROSOL = 13, METEO_GAS = 14, METEO_RADAR = 15,
       METEO_RADAR_IMAGERY = 16, METEO_ELECTRO = 17, METEO_NUCLEAR = 18,
-      METEO_ATMOS = 19, METEO_CCITT = 190, METEO_MISC = 191,
+      METEO_ATMOS = 19, METEO_ATMO_CHEM = 20, METEO_CCITT = 190, METEO_MISC = 191,
       METEO_CCITT2 = 253
    };
    enum { HYDRO_BASIC = 0, HYDRO_PROB = 1 };
    enum { LAND_VEG = 0, LAND_SOIL = 3 };
    enum { SPACE_IMAGE = 0, SPACE_QUANTIT = 1 };
    enum { OCEAN_WAVES = 0, OCEAN_CURRENTS = 1, OCEAN_ICE = 2, OCEAN_SURF = 3,
-      OCEAN_SUBSURF = 4
+      OCEAN_SUBSURF = 4, OCEAN_MISC = 191
    };
 
    switch (prodType) {
@@ -1099,6 +1391,8 @@ static const GRIB2ParmTable *Choose_GRIB2ParmTable (int prodType, int cat,
                *tableLen = sizeof (MeteoRadar) / sizeof (GRIB2ParmTable);
                return &MeteoRadar[0];
             case METEO_RADAR_IMAGERY:
+               *tableLen = sizeof (MeteoRadarImagery) / sizeof (GRIB2ParmTable);
+               return &MeteoRadarImagery[0];
             case METEO_ELECTRO:
                *tableLen = 0;
                return NULL;
@@ -1108,6 +1402,9 @@ static const GRIB2ParmTable *Choose_GRIB2ParmTable (int prodType, int cat,
             case METEO_ATMOS:
                *tableLen = sizeof (MeteoAtmos) / sizeof (GRIB2ParmTable);
                return &MeteoAtmos[0];
+            case METEO_ATMO_CHEM:
+               *tableLen = sizeof (MeteoAtmoChem) / sizeof (GRIB2ParmTable);
+               return &MeteoAtmoChem[0];
             case METEO_CCITT:
             case METEO_CCITT2:
                *tableLen = sizeof (MeteoText) / sizeof (GRIB2ParmTable);
@@ -1170,6 +1467,9 @@ static const GRIB2ParmTable *Choose_GRIB2ParmTable (int prodType, int cat,
             case OCEAN_SURF:
                *tableLen = sizeof (OceanSurface) / sizeof (GRIB2ParmTable);
                return &OceanSurface[0];
+            case OCEAN_MISC:
+               *tableLen = sizeof (OceanMisc) / sizeof (GRIB2ParmTable);
+               return &OceanMisc[0];
             default:
                *tableLen = 0;
                return NULL;
@@ -1195,22 +1495,47 @@ static const NDFD_AbrevOverideTable NDFD_Overide[] = {
    /*  9 */ {"WVHGT", "WaveHeight"},
    /* 10 */ {"ASNOW", "SnowAmt"},
    /* 11 */ {"GUST", "WindGust"},
+   /* 12 */ {"MAXRH", "MaxRH"},                /* Mike added 201202 */
 };
 
 static const GRIB2LocalTable NDFD_LclTable[] = {
-   /* 0 */ {0, 1, 192, "Wx", "Weather string", "-", UC_NONE},
-   /* 1 */ {0, 0, 193, "ApparentT", "Apparent Temperature", "K", UC_K2F},
-   /* 2 */ {0, 14, 192, "O3MR", "Ozone Mixing Ratio", "kg/kg", UC_NONE},
-   /* 3 */ {0, 14, 193, "OZCON", "Ozone Concentration", "PPB", UC_NONE},
+   /* 0 */ {0, 0, 193, "ApparentT", "Apparent Temperature", "K", UC_K2F},
+   /* 1 */ {0, 1, 192, "Wx", "Weather string", "-", UC_NONE},
+           {0, 1, 227, "IceAccum", "Ice Accumulation", "kg/m^2", UC_InchWater},
    /* grandfather'ed in a NDFD choice for POP. */
-   /* 4 */ {0, 10, 8, "PoP12", "Prob of 0.01 In. of Precip", "%", UC_NONE},
+   /* 2 */ {0, 10, 8, "PoP12", "Prob of 0.01 In. of Precip", "%", UC_NONE},
            {0, 13, 194, "smokes", "Surface level smoke from fires",
-            "log10(\xB5" "g/m^3)", UC_LOG10},
+            "log10(µg/m^3)", UC_LOG10},
            {0, 13, 195, "smokec", "Average vertical column smoke from fires",
-            "log10(\xB5" "g/m^3)", UC_LOG10},
+            "log10(µg/m^3)", UC_LOG10},
+   /* 3 */ {0, 14, 192, "O3MR", "Ozone Mixing Ratio", "kg/kg", UC_NONE},
+   /* 4 */ {0, 14, 193, "OZCON", "Ozone Concentration", "PPB", UC_NONE},
+   /* Arthur adopted NCEP ozone values from NCEP local table to NDFD local tables. (11/14/2009) */
+           {0, 14, 200, "OZMAX1", "Ozone Daily Max from 1-hour Average", "ppbV", UC_NONE},
+           {0, 14, 201, "OZMAX8", "Ozone Daily Max from 8-hour Average", "ppbV", UC_NONE},
+   /* Added 1/23/2007 in preparation for SPC NDFD Grids */
+           {0, 19, 194, "ConvOutlook", "Convective Hazard Outlook", "0=none; 2=tstm; 4=slight; 6=moderate; 8=high", UC_NONE},
+           {0, 19, 197, "TornadoProb", "Tornado Probability", "%", UC_NONE},
+           {0, 19, 198, "HailProb", "Hail Probability", "%", UC_NONE},
+           {0, 19, 199, "WindProb", "Damaging Thunderstorm Wind Probability", "%", UC_NONE},
+           {0, 19, 200, "XtrmTornProb", "Extreme Tornado Probability", "%", UC_NONE},
+           {0, 19, 201, "XtrmHailProb", "Extreme Hail Probability", "%", UC_NONE},
+           {0, 19, 202, "XtrmWindProb", "Extreme Thunderstorm Wind Probability", "%", UC_NONE},
+           {0, 19, 215, "TotalSvrProb", "Total Probability of Severe Thunderstorms", "%", UC_NONE},
+           {0, 19, 216, "TotalXtrmProb", "Total Probability of Extreme Severe Thunderstorms", "%", UC_NONE},
+           {0, 19, 217, "WWA", "Watch Warning Advisory", "-", UC_NONE},
+/* Leaving next two lines in for grandfathering sake. 9/19/2007... Probably can remove in future. */
+           {0, 19, 203, "TotalSvrProb", "Total Probability of Severe Thunderstorms", "%", UC_NONE},
+           {0, 19, 204, "TotalXtrmProb", "Total Probability of Extreme Severe Thunderstorms", "%", UC_NONE},
+           {0, 192, 192, "FireWx", "Critical Fire Weather", "%", UC_NONE},
+           {0, 192, 194, "DryLightning", "Dry Lightning", "%", UC_NONE},
+   /* Mike added 1/13 */
+           {2, 1, 192, "CANL", "Cold Advisory for Newborn Livestock", "0=none; 2=slight; 4=mild; 6=moderate; 8=severe; 10=extreme", UC_NONE},
    /* Arthur Added this to both NDFD and NCEP local tables. (5/1/2006) */
            {10, 3, 192, "Surge", "Hurricane Storm Surge", "m", UC_M2Feet},
            {10, 3, 193, "ETSurge", "Extra Tropical Storm Surge", "m", UC_M2Feet},
+   /* Mike added 2/2012 */
+           {0, 1, 198, "MinRH", "Minimum Relative Humidity", "%", UC_NONE}
 };
 
 static const GRIB2LocalTable HPC_LclTable[] = {
@@ -1228,19 +1553,30 @@ http://www.nco.ncep.noaa.gov/pmb/docs/on388/table2.html
 
 Updated again on 2/14/2006
 Updated again on 3/15/2006
+Updated again on 3/26/2008
 */
 static const GRIB2LocalTable NCEP_LclTable[] = {
    /*  0 */ {0, 0, 192, "SNOHF", "Snow Phase Change Heat Flux", "W/(m^2)", UC_NONE},
             {0, 0, 193, "TTRAD", "Temperature tendency by all radiation", "K/s", UC_NONE},
-
-   /*  1 */ {0, 1, 192, "CRAIN", "Categorical Rain", "(0 no; 1 yes)", UC_NONE},
-   /*  2 */ {0, 1, 193, "CFRZR", "Categorical Freezing Rain", "(0 no; 1 yes)", UC_NONE},
-   /*  3 */ {0, 1, 194, "CICEP", "Categorical Ice Pellets", "(0 no; 1 yes)", UC_NONE},
-   /*  4 */ {0, 1, 195, "CSNOW", "Categorical Snow", "(0 no; 1 yes)", UC_NONE},
+            {0, 0, 194, "REV", "Relative Error Variance", "-", UC_NONE},
+            {0, 0, 195, "LRGHR", "Large Scale Condensate Heating rate", "K/s", UC_NONE},
+            {0, 0, 196, "CNVHR", "Deep Convective Heating rate", "K/s", UC_NONE},
+            {0, 0, 197, "THFLX", "Total Downward Heat Flux at Surface", "W/(m^2)", UC_NONE},
+            {0, 0, 198, "TTDIA", "Temperature Tendency By All Physics", "K/s", UC_NONE},
+            {0, 0, 199, "TTPHY", "Temperature Tendency By Non-radiation Physics", "K/s", UC_NONE},
+            {0, 0, 200, "TSD1D", "Standard Dev. of IR Temp. over 1x1 deg. area", "K", UC_NONE},
+            {0, 0, 201, "SHAHR", "Shallow Cnvective Heating rate", "K/s", UC_NONE},
+            {0, 0, 202, "VDFHR", "Vertical Diffusion Heating rate", "K/s", UC_NONE},
+            {0, 0, 203, "THZ0", "Potential temperature at top of viscus sublayer", "K", UC_NONE},
+            {0, 0, 204, "TCHP", "Tropical Cyclone Heat Potential", "J/(m^2*K)", UC_NONE},
+
+   /*  1 */ {0, 1, 192, "CRAIN", "Categorical Rain", "0=no; 1=yes", UC_NONE},
+   /*  2 */ {0, 1, 193, "CFRZR", "Categorical Freezing Rain", "0=no; 1=yes", UC_NONE},
+   /*  3 */ {0, 1, 194, "CICEP", "Categorical Ice Pellets", "0=no; 1=yes", UC_NONE},
+   /*  4 */ {0, 1, 195, "CSNOW", "Categorical Snow", "0=no; 1=yes", UC_NONE},
    /*  5 */ {0, 1, 196, "CPRAT", "Convective Precipitation Rate", "kg/(m^2*s)", UC_NONE},
    /*  6 */ {0, 1, 197, "MCONV", "Horizontal Moisture Divergence", "kg/(kg*s)", UC_NONE},
-/* Following was grandfathered in... Should use: 1, 1, 193 */
-   /*  7 */ {0, 1, 198, "CPOFP", "Percent Frozen Precipitation", "%", UC_NONE},
+   /*  7 */ {0, 1, 198, "MINRH", "Minimum Relative Humidity", "%", UC_NONE},
    /*  8 */ {0, 1, 199, "PEVAP", "Potential Evaporation", "kg/(m^2)", UC_NONE},
    /*  9 */ {0, 1, 200, "PEVPR", "Potential Evaporation Rate", "W/(m^2)", UC_NONE},
    /* 10 */ {0, 1, 201, "SNOWC", "Snow Cover", "%", UC_NONE},
@@ -1252,6 +1588,30 @@ static const GRIB2LocalTable NCEP_LclTable[] = {
             {0, 1, 206, "TIPD", "Total Icing Potential Diagnostic", "-", UC_NONE},
             {0, 1, 207, "NCIP", "Number concentration for ice particles", "-", UC_NONE},
             {0, 1, 208, "SNOT", "Snow temperature", "K", UC_NONE},
+            {0, 1, 209, "TCLSW", "Total column-integrated supercooled liquid water", "kg/(m^2)", UC_NONE},
+            {0, 1, 210, "TCOLM", "Total column-integrated melting ice", "kg/(m^2)", UC_NONE},
+            {0, 1, 211, "EMNP", "Evaporation - Precipitation", "cm/day", UC_NONE},
+            {0, 1, 212, "SBSNO", "Sublimination (evaporation from snow)", "W/(m^2)", UC_NONE},
+            {0, 1, 213, "CNVMR", "Deep Convective Moistening Rate", "kg/(kg*s)", UC_NONE},
+            {0, 1, 214, "SHAMR", "Shallow Convective Moistening Rate", "kg/(kg*s)", UC_NONE},
+            {0, 1, 215, "VDFMR", "Vertical Diffusion Moistening Rate", "kg/(kg*s)", UC_NONE},
+            {0, 1, 216, "CONDP", "Condensation Pressure of Parcali Lifted From Indicate Surface", "Pa", UC_NONE},
+            {0, 1, 217, "LRGMR", "Large scale moistening rate", "kg/(kg/s)", UC_NONE},
+            {0, 1, 218, "QZ0", "Specific humidity at top of viscous sublayer", "kg/kg", UC_NONE},
+            {0, 1, 219, "QMAX", "Maximum specific humidity at 2m", "kg/kg", UC_NONE},
+            {0, 1, 220, "QMIN", "Minimum specific humidity at 2m", "kg/kg", UC_NONE},
+            {0, 1, 221, "ARAIN", "Liquid precipitation (rainfall)", "kg/(m^2)", UC_NONE},
+            {0, 1, 222, "SNOWT", "Snow temperature, depth-avg", "K", UC_NONE},
+            {0, 1, 223, "APCPN", "Total precipitation (nearest grid point)", "kg/(m^2)", UC_NONE},
+            {0, 1, 224, "ACPCPN", "Convective precipitation (nearest grid point)", "kg/(m^2)", UC_NONE},
+            {0, 1, 225, "FRZR", "Freezing rain", "kg/(m^2)", UC_NONE},
+/* It is important to use 'Wx' instead of 'PWTHER' since the rest of the code
+ * uses "Wx" to test if it should be dealing with weather strings.  Since these
+ * are the same as the NDFD "Wx" strings, it was simpler to maintain the NDFD
+ * convention on abbreviations.  We could use 'Predominant Weather' as the long
+ * descriptor, but the NDFD 'Weather String' seems quite reasonable. */
+/*            {0, 1, 226, "PWTHER", "Predominant Weather", "-", UC_NONE},*/
+            {0, 1, 226, "Wx", "Weather String", "-", UC_NONE},
 
    /* 15 */ {0, 2, 192, "VWSH", "Vertical speed sheer", "1/s", UC_NONE},
    /* 16 */ {0, 2, 193, "MFLX", "Horizontal Momentum Flux", "N/(m^2)", UC_NONE},
@@ -1259,24 +1619,73 @@ static const GRIB2LocalTable NCEP_LclTable[] = {
    /* 18 */ {0, 2, 195, "VSTM", "V-Component Storm Motion", "m/s", UC_NONE},
    /* 19 */ {0, 2, 196, "CD", "Drag Coefficient", "-", UC_NONE},
    /* 20 */ {0, 2, 197, "FRICV", "Frictional Velocity", "m/s", UC_NONE},
-
-   /* 21 */ {0, 3, 192, "MSLET", "Mean Sea Level Pressure (Eta Reduction)", "Pa", UC_NONE},
+            {0, 2, 198, "LAUV", "Latitude of U Wind Component of Velocity", "deg", UC_NONE},
+            {0, 2, 199, "LOUV", "Longitude of U Wind Component of Velocity", "deg", UC_NONE},
+            {0, 2, 200, "LAVV", "Latitude of V Wind Component of Velocity", "deg", UC_NONE},
+            {0, 2, 201, "LOVV", "Longitude of V Wind Component of Velocity", "deg", UC_NONE},
+            {0, 2, 202, "LAPP", "Latitude of Presure Point", "deg", UC_NONE},
+            {0, 2, 203, "LOPP", "Longitude of Presure Point", "deg", UC_NONE},
+            {0, 2, 204, "VEDH", "Vertical Eddy Diffusivity Heat exchange", "m^2/s", UC_NONE},
+            {0, 2, 205, "COVMZ", "Covariance between Meridional and Zonal Components of the wind", "m^2/s^2", UC_NONE},
+            {0, 2, 206, "COVTZ", "Covariance between Temperature and Zonal Components of the wind", "K*m/s", UC_NONE},
+            {0, 2, 207, "COVTM", "Covariance between Temperature and Meridional Components of the wind", "K*m/s", UC_NONE},
+            {0, 2, 208, "VDFUA", "Vertical Diffusion Zonal Acceleration", "m/s^2", UC_NONE},
+            {0, 2, 209, "VDFVA", "Vertical Diffusion Meridional Acceleration", "m/s^2", UC_NONE},
+            {0, 2, 210, "GWDU", "Gravity wave drag zonal acceleration", "m/s^2", UC_NONE},
+            {0, 2, 211, "GWDV", "Gravity wave drag meridional acceleration", "m/s^2", UC_NONE},
+            {0, 2, 212, "CNVU", "Convective zonal momentum mixing acceleration", "m/s^2", UC_NONE},
+            {0, 2, 213, "CNVV", "Convective meridional momentum mixing acceleration", "m/s^2", UC_NONE},
+            {0, 2, 214, "WTEND", "Tendency of vertical velocity", "m/s^2", UC_NONE},
+            {0, 2, 215, "OMGALF", "Omega (Dp/Dt) divide by density", "K", UC_NONE},
+            {0, 2, 216, "CNGWDU", "Convective Gravity wave drag zonal acceleration", "m/s^2", UC_NONE},
+            {0, 2, 217, "CNGWDV", "Convective Gravity wave drag meridional acceleration", "m/s^2", UC_NONE},
+            {0, 2, 218, "LMV", "Velocity point model surface", "-", UC_NONE},
+            {0, 2, 219, "PVMWW", "Potential vorticity (mass-weighted)", "1/(s/m)", UC_NONE},
+/* Removed 8/19/2008 */ /*           {0, 2, 220, "MFLX", "Momentum flux", "N/m^2", UC_NONE},*/
+
+   /* 21 */ {0, 3, 192, "MSLET", "MSLP (Eta model reduction)", "Pa", UC_NONE},
    /* 22 */ {0, 3, 193, "5WAVH", "5-Wave Geopotential Height", "gpm", UC_NONE},
    /* 23 */ {0, 3, 194, "U-GWD", "Zonal Flux of Gravity Wave Stress", "N/(m^2)", UC_NONE},
    /* 24 */ {0, 3, 195, "V-GWD", "Meridional Flux of Gravity Wave Stress", "N/(m^2)", UC_NONE},
    /* 25 */ {0, 3, 196, "HPBL", "Planetary Boundary Layer Height", "m", UC_NONE},
    /* 26 */ {0, 3, 197, "5WAVA", "5-Wave Geopotential Height Anomaly", "gpm", UC_NONE},
-            {0, 3, 198, "MSLMA", "Mean Sea Level Pressure (MAPS System Reduction)", "Pa", UC_NONE},
+            {0, 3, 198, "MSLMA", "MSLP (MAPS System Reduction)", "Pa", UC_NONE},
             {0, 3, 199, "TSLSA", "3-hr pressure tendency (Std. Atmos. Reduction)", "Pa/s", UC_NONE},
             {0, 3, 200, "PLPL", "Pressure of level from which parcel was lifted", "Pa", UC_NONE},
+            {0, 3, 201, "LPSX", "X-gradiant of Log Pressure", "1/m", UC_NONE},
+            {0, 3, 202, "LPSY", "Y-gradiant of Log Pressure", "1/m", UC_NONE},
+            {0, 3, 203, "HGTX", "X-gradiant of Height", "1/m", UC_NONE},
+            {0, 3, 204, "HGTY", "Y-gradiant of Height", "1/m", UC_NONE},
+            {0, 3, 205, "LAYTH", "Layer Thickness", "m", UC_NONE},
+            {0, 3, 206, "NLGSP", "Natural Log of Surface Pressure", "ln(kPa)", UC_NONE},
+            {0, 3, 207, "CNVUMF", "Convective updraft mass flux", "kg/m^2/s", UC_NONE},
+            {0, 3, 208, "CNVDMF", "Convective downdraft mass flux", "kg/m^2/s", UC_NONE},
+            {0, 3, 209, "CNVDEMF", "Convective detrainment mass flux", "kg/m^2/s", UC_NONE},
+            {0, 3, 210, "LMH", "Mass point model surface", "-", UC_NONE},
+            {0, 3, 211, "HGTN", "Geopotential height (nearest grid point)", "gpm", UC_NONE},
+            {0, 3, 212, "PRESN", "Pressure (nearest grid point)", "Pa", UC_NONE},
 
    /* 27 */ {0, 4, 192, "DSWRF", "Downward Short-Wave Rad. Flux", "W/(m^2)", UC_NONE},
    /* 28 */ {0, 4, 193, "USWRF", "Upward Short-Wave Rad. Flux", "W/(m^2)", UC_NONE},
             {0, 4, 194, "DUVB", "UV-B downward solar flux", "W/(m^2)", UC_NONE},
             {0, 4, 195, "CDUVB", "Clear sky UV-B downward solar flux", "W/(m^2)", UC_NONE},
+            {0, 4, 196, "CSDSF", "Clear sky Downward Solar Flux", "W/(m^2)", UC_NONE},
+            {0, 4, 197, "SWHR", "Solar Radiative Heating Rate", "K/s", UC_NONE},
+            {0, 4, 198, "CSUSF", "Clear Sky Upward Solar Flux", "W/(m^2)", UC_NONE},
+            {0, 4, 199, "CFNSF", "Cloud Forcing Net Solar Flux", "W/(m^2)", UC_NONE},
+            {0, 4, 200, "VBDSF", "Visible Beam Downward Solar Flux", "W/(m^2)", UC_NONE},
+            {0, 4, 201, "VDDSF", "Visible Diffuse Downward Solar Flux", "W/(m^2)", UC_NONE},
+            {0, 4, 202, "NBDSF", "Near IR Beam Downward Solar Flux", "W/(m^2)", UC_NONE},
+            {0, 4, 203, "NDDSF", "Near IR Diffuse Downward Solar Flux", "W/(m^2)", UC_NONE},
+            {0, 4, 204, "DTRF", "Downward Total radiation Flux", "W/(m^2)", UC_NONE},
+            {0, 4, 205, "UTRF", "Upward Total radiation Flux", "W/(m^2)", UC_NONE},
 
    /* 29 */ {0, 5, 192, "DLWRF", "Downward Long-Wave Rad. Flux", "W/(m^2)", UC_NONE},
    /* 30 */ {0, 5, 193, "ULWRF", "Upward Long-Wave Rad. Flux", "W/(m^2)", UC_NONE},
+            {0, 5, 194, "LWHR", "Long-Wave Radiative Heating Rate", "K/s", UC_NONE},
+            {0, 5, 195, "CSULF", "Clear Sky Upward Long Wave Flux", "W/(m^2)", UC_NONE},
+            {0, 5, 196, "CSDLF", "Clear Sky Downward Long Wave Flux", "W/(m^2)", UC_NONE},
+            {0, 5, 197, "CFNLF", "Cloud Forcing Net Long Wave Flux", "W/(m^2)", UC_NONE},
 
    /* 31 */ {0, 6, 192, "CDLYR", "Non-Convective Cloud Cover", "%", UC_NONE},
    /* 32 */ {0, 6, 193, "CWORK", "Cloud Work Function", "J/kg", UC_NONE},
@@ -1286,47 +1695,135 @@ static const GRIB2LocalTable NCEP_LclTable[] = {
    /* 36 */ {0, 6, 197, "TCOLI", "Total Column-Integrated Cloud Ice", "kg/(m^2)", UC_NONE},
    /* 37 */ {0, 6, 198, "TCOLC", "Total Column-Integrated Condensate", "kg/(m^2)", UC_NONE},
    /* 38 */ {0, 6, 199, "FICE", "Ice fraction of total condensate", "-", UC_NONE},
+            {0, 6, 200, "MFLUX", "Convective Cloud Mass Flux", "Pa/s", UC_NONE},
+            {0, 6, 201, "SUNSD", "SunShine duration", "s", UC_NONE},
 
    /* 39 */ {0, 7, 192, "LFTX", "Surface Lifted Index", "K", UC_NONE},
    /* 40 */ {0, 7, 193, "4LFTX", "Best (4 layer) Lifted Index", "K", UC_NONE},
    /* 41 */ {0, 7, 194, "RI", "Richardson Number", "-", UC_NONE},
+            {0, 7, 195, "CWDI", "Convective Weather Detection Index", "-", UC_NONE},
+            {0, 7, 196, "UVI", "Ultra Violet Index", "W/(m^2)", UC_UVIndex},
+            {0, 7, 197, "UPHL", "Updraft Helicity", "m^2/s^2", UC_NONE},
+            {0, 7, 198, "LAI", "Leaf area index", "-", UC_NONE},
 
-            {0, 13, 192, "PMTC", "Particulate matter (coarse)", "\xB5" "g/m^3", UC_NONE},
-            {0, 13, 193, "PMTF", "Particulate matter (fine)", "\xB5" "g/m^3", UC_NONE},
+            {0, 13, 192, "PMTC", "Particulate matter (coarse)", "µg/m^3", UC_NONE},
+            {0, 13, 193, "PMTF", "Particulate matter (fine)", "µg/m^3", UC_NONE},
             {0, 13, 194, "LPMTF", "Particulate matter (fine)",
-             "log10(\xB5" "g/m^3)", UC_LOG10},
-            {0, 13, 195, "LIPMF", "Integrated column particulate matter "
-             "(fine)", "log10(\xB5" "g/m^3)", UC_LOG10},
+             "log10(µg/m^3)", UC_LOG10},
+            {0, 13, 195, "LIPMF", "Integrated column particulate matter " /* over-ride in the code based on surface */
+             "(fine)", "log10(µg/m^3)", UC_LOG10},
 
    /* 42 */ {0, 14, 192, "O3MR", "Ozone Mixing Ratio", "kg/kg", UC_NONE},
    /* 43 */ {0, 14, 193, "OZCON", "Ozone Concentration", "PPB", UC_NONE},
    /* 44 */ {0, 14, 194, "OZCAT", "Categorical Ozone Concentration", "-", UC_NONE},
+            {0, 14, 195, "VDFOZ", "Ozone Vertical Diffusion", "kg/kg/s", UC_NONE},
+            {0, 14, 196, "POZ", "Ozone Production", "kg/kg/s", UC_NONE},
+            {0, 14, 197, "TOZ", "Ozone Tendency", "kg/kg/s", UC_NONE},
+            {0, 14, 198, "POZT", "Ozone Production from Temperature Term", "kg/kg/s", UC_NONE},
+            {0, 14, 199, "POZO", "Ozone Production from Column Ozone Term", "kg/kg/s", UC_NONE},
+            {0, 14, 200, "OZMAX1", "Ozone Daily Max from 1-hour Average", "ppbV", UC_NONE},
+            {0, 14, 201, "OZMAX8", "Ozone Daily Max from 8-hour Average", "ppbV", UC_NONE},
+            {0, 14, 202, "PDMAX1", "PM 2.5 Daily Max from 1-hour Average", "ug/(m^3)", UC_NONE},
+            {0, 14, 203, "PDMAX24", "PM 2.5 Daily Max from 24-hour Average", "ug/(m^3)", UC_NONE},
 
             {0, 16, 192, "REFZR", "Derived radar reflectivity backscatter from rain", "mm^6/m^3", UC_NONE},
             {0, 16, 193, "REFZI", "Derived radar reflectivity backscatter from ice", "mm^6/m^3", UC_NONE},
             {0, 16, 194, "REFZC", "Derived radar reflectivity backscatter from parameterized convection", "mm^6/m^3", UC_NONE},
             {0, 16, 195, "REFD", "Derived radar reflectivity", "dB", UC_NONE},
             {0, 16, 196, "REFC", "Maximum / Composite radar reflectivity", "dB", UC_NONE},
+            {0, 16, 197, "RETOP", "Radar Echo Top (18.3 DBZ)", "m", UC_NONE},
 
             {0, 17, 192, "LTNG", "Lightning", "-", UC_NONE},
 
    /* 45 */ {0, 19, 192, "MXSALB", "Maximum Snow Albedo", "%", UC_NONE},
    /* 46 */ {0, 19, 193, "SNFALB", "Snow-Free Albedo", "%", UC_NONE},
-            {0, 19, 194, "", "Slight risk convective outlook", "categorical", UC_NONE},
-            {0, 19, 195, "", "Moderate risk convective outlook", "categorical", UC_NONE},
-            {0, 19, 196, "", "High risk convective outlook", "categorical", UC_NONE},
-            {0, 19, 197, "", "Tornado probability", "%", UC_NONE},
-            {0, 19, 198, "", "Hail probability", "%", UC_NONE},
-            {0, 19, 199, "", "Wind probability", "%", UC_NONE},
-            {0, 19, 200, "", "Significant Tornado probability", "%", UC_NONE},
-            {0, 19, 201, "", "Significant Hail probability", "%", UC_NONE},
-            {0, 19, 202, "", "Significant Wind probability", "%", UC_NONE},
-            {0, 19, 203, "TSTMC", "Categorical Thunderstorm", "0=no, 1=yes", UC_NONE},
+            {0, 19, 194, "SRCONO", "Slight risk convective outlook", "categorical", UC_NONE},
+            {0, 19, 195, "MRCONO", "Moderate risk convective outlook", "categorical", UC_NONE},
+            {0, 19, 196, "HRCONO", "High risk convective outlook", "categorical", UC_NONE},
+            {0, 19, 197, "TORPROB", "Tornado probability", "%", UC_NONE},
+            {0, 19, 198, "HAILPROB", "Hail probability", "%", UC_NONE},
+            {0, 19, 199, "WINDPROB", "Wind probability", "%", UC_NONE},
+            {0, 19, 200, "STORPROB", "Significant Tornado probability", "%", UC_NONE},
+            {0, 19, 201, "SHAILPRO", "Significant Hail probability", "%", UC_NONE},
+            {0, 19, 202, "SWINDPRO", "Significant Wind probability", "%", UC_NONE},
+            {0, 19, 203, "TSTMC", "Categorical Thunderstorm", "0=no; 1=yes", UC_NONE},
             {0, 19, 204, "MIXLY", "Number of mixed layers next to surface", "integer", UC_NONE},
+            {0, 19, 205, "FLGHT", "Flight Category", "-", UC_NONE},
+            {0, 19, 206, "CICEL", "Confidence Ceiling", "-", UC_NONE},
+            {0, 19, 207, "CIVIS", "Confidence Visibility", "-", UC_NONE},
+            {0, 19, 208, "CIFLT", "Confidence Flight Category", "-", UC_NONE},
+            {0, 19, 209, "LAVNI", "Low Level aviation interest", "-", UC_NONE},
+            {0, 19, 210, "HAVNI", "High Level aviation interest", "-", UC_NONE},
+            {0, 19, 211, "SBSALB", "Visible; Black Sky Albedo", "%", UC_NONE},
+            {0, 19, 212, "SWSALB", "Visible; White Sky Albedo", "%", UC_NONE},
+            {0, 19, 213, "NBSALB", "Near IR; Black Sky Albedo", "%", UC_NONE},
+            {0, 19, 214, "NWSALB", "Near IR; White Sky Albedo", "%", UC_NONE},
+            {0, 19, 215, "PRSVR", "Total Probability of Severe Thunderstorms (Days 2,3)", "%", UC_NONE},
+            {0, 19, 216, "PRSIGSVR", "Total Probability of Extreme Severe Thunderstorms (Days 2,3)", "%", UC_NONE},
+            {0, 19, 217, "SIPD", "Supercooled Large Droplet Icing",
+                         "0=None; 1=Light; 2=Moderate; 3=Severe; 4=Trace; 5=Heavy; 255=missing", UC_NONE},
+            {0, 19, 218, "EPSR", "Radiative emissivity", "", UC_NONE},
+            {0, 19, 219, "TPFI", "Turbulence potential forecast index", "-", UC_NONE},
+            {0, 19, 220, "SVRTS", "Categorical Severe Thunderstorm", "0=No; 1=Yes; "
+             "2-3=Reserved; 4=Low; 5=Reserved; 6=Medium; 7=Reserved; 8=High; "
+             "255=missing", UC_NONE},
+            {0, 19, 221, "PROCON", "Probability of Convection", "%", UC_NONE},
+            {0, 19, 222, "CONVP", "Convection Potential",  "0=No; 1=Yes; "
+             "2-3=Reserved; 4=Low; 5=Reserved; 6=Medium; 7=Reserved; 8=High; "
+             "255=missing", UC_NONE},
+            {0, 19, 223, "", "Reserved", "-", UC_NONE},
+            {0, 19, 224, "", "Reserved", "-", UC_NONE},
+            {0, 19, 225, "", "Reserved", "-", UC_NONE},
+            {0, 19, 226, "", "Reserved", "-", UC_NONE},
+            {0, 19, 227, "", "Reserved", "-", UC_NONE},
+            {0, 19, 228, "", "Reserved", "-", UC_NONE},
+            {0, 19, 229, "", "Reserved", "-", UC_NONE},
+            {0, 19, 230, "", "Reserved", "-", UC_NONE},
+            {0, 19, 231, "", "Reserved", "-", UC_NONE},
+/* These stopped being used? 3/26/2008 */
+/*
+            {0, 19, 217, "MEIP", "Mean Icing Potential", "kg/m^2", UC_NONE},
+            {0, 19, 218, "MAIP", "Maximum Icing Potential", "kg/m^2", UC_NONE},
+            {0, 19, 219, "MECTP", "Mean in-Cloud Turbulence Potential", "kg/m^2", UC_NONE},
+            {0, 19, 220, "MACTP", "Max in-Cloud Turbulence Potential", "kg/m^2", UC_NONE},
+            {0, 19, 221, "MECAT", "Mean Cloud Air Turbulence Potential", "kg/m^2", UC_NONE},
+            {0, 19, 222, "MACAT", "Maximum Cloud Air Turbulence Potential", "kg/m^2", UC_NONE},
+            {0, 19, 223, "CBHE", "Cumulonimbus Horizontal Extent", "%", UC_NONE},
+            {0, 19, 224, "PCBB", "Pressure at Cumulonimbus Base", "Pa", UC_NONE},
+            {0, 19, 225, "PCBT", "Pressure at Cumulonimbus Top", "Pa", UC_NONE},
+            {0, 19, 226, "PECBB", "Pressure at Embedded Cumulonimbus Base", "Pa", UC_NONE},
+            {0, 19, 227, "PECBT", "Pressure at Embedded Cumulonimbus Top", "Pa", UC_NONE},
+            {0, 19, 228, "HCBB", "ICAO Height at Cumulonimbus Base", "m", UC_NONE},
+            {0, 19, 229, "HCBT", "ICAO Height at Cumulonimbus Top", "m", UC_NONE},
+            {0, 19, 230, "HECBB", "ICAO Height at Embedded Cumulonimbus Base", "m", UC_NONE},
+            {0, 19, 231, "HECBT", "ICAO Height at Embedded Cumulonimbus Top", "m", UC_NONE},
+*/
+            {0, 19, 232, "VAFTD", "Volcanic Ash Forecast Transport and Dispersion", "log10(kg/m^3)", UC_NONE},
+            {0, 19, 233, "ICPRB", "Icing probability", "-", UC_NONE},
+            {0, 19, 234, "ICSEV", "Icing severity", "-", UC_NONE},
 
    /* 47 */ {0, 191, 192, "NLAT", "Latitude (-90 to 90)", "deg", UC_NONE},
    /* 48 */ {0, 191, 193, "ELON", "East Longitude (0 to 360)", "deg", UC_NONE},
    /* 49 */ {0, 191, 194, "TSEC", "Seconds prior to initial reference time", "s", UC_NONE},
+            {0, 191, 195, "MLYNO", "Model Layer number (From bottom up)", "", UC_NONE},
+            {0, 191, 196, "NLATN", "Latitude (nearest neighbor) (-90 to 90)", "deg", UC_NONE},
+            {0, 191, 197, "ELONN", "East longitude (nearest neighbor) (0 to 360)", "deg", UC_NONE},
+
+/* table 4.2 : 0.192 according to NCEP is "Covariance". */
+            {0, 192, 1, "COVZM", "Covariance between zonal and meridonial components of the wind", "m^2/s^2", UC_NONE},
+            {0, 192, 2, "COVTZ", "Covariance between zonal component of the wind and temperature", "K*m/s", UC_NONE},
+            {0, 192, 3, "COVTM", "Covariance between meridonial component of the wind and temperature", "K*m/s", UC_NONE},
+            {0, 192, 4, "COVTW", "Covariance between temperature and vertical component of the wind", "K*m/s", UC_NONE},
+            {0, 192, 5, "COVZZ", "Covariance between zonal and zonal components of the wind", "m^2/s^2", UC_NONE},
+            {0, 192, 6, "COVMM", "Covariance between meridonial and meridonial components of the wind", "m^2/s^2", UC_NONE},
+            {0, 192, 7, "COVQZ", "Covariance between specific humidity and zonal components of the wind", "kg/kg*m/s", UC_NONE},
+            {0, 192, 8, "COVQM", "Covariance between specific humidity and meridonial components of the wind", "kg/kg*m/s", UC_NONE},
+            {0, 192, 9, "COVTVV", "Covariance between temperature and vertical components of the wind", "K*Pa/s", UC_NONE},
+            {0, 192, 10, "COVQVV", "Covariance between specific humidity and vertical components of the wind", "kg/kg*Pa/s", UC_NONE},
+            {0, 192, 11, "COVPSPS", "Covariance between surface pressure and surface pressure", "Pa*Pa", UC_NONE},
+            {0, 192, 12, "COVQQ", "Covariance between specific humidity and specific humidity", "kg/kg*kg/kg", UC_NONE},
+            {0, 192, 13, "COVVVVV", "Covariance between vertical and vertical components of the wind", "Pa^2/s^2", UC_NONE},
+            {0, 192, 14, "COVTT", "Covariance between temperature and temperature", "K*K", UC_NONE},
 
    /* 50 */ {1, 0, 192, "BGRUN", "Baseflow-Groundwater Runoff", "kg/(m^2)", UC_NONE},
    /* 51 */ {1, 0, 193, "SSRUN", "Storm Surface Runoff", "kg/(m^2)", UC_NONE},
@@ -1334,6 +1831,7 @@ static const GRIB2LocalTable NCEP_LclTable[] = {
             {1, 1, 192, "CPOZP", "Probability of Freezing Precipitation", "%", UC_NONE},
             {1, 1, 193, "CPOFP", "Probability of Frozen Precipitation", "%", UC_NONE},
             {1, 1, 194, "PPFFG", "Probability of precipitation exceeding flash flood guidance values", "%", UC_NONE},
+            {1, 1, 195, "CWR", "Probability of Wetting Rain; exceeding in 0.1 inch in a given time period", "%", UC_NONE},
 
    /* 52 */ {2, 0, 192, "SOILW", "Volumetric Soil Moisture Content", "Fraction", UC_NONE},
    /* 53 */ {2, 0, 193, "GFLUX", "Ground Heat Flux", "W/(m^2)", UC_NONE},
@@ -1351,22 +1849,218 @@ static const GRIB2LocalTable NCEP_LclTable[] = {
    /* 65 */ {2, 0, 205, "RCSOL", "Soil moisture parameter in canopy conductance", "Fraction", UC_NONE},
             {2, 0, 206, "RDRIP", "Rate of water dropping from canopy to ground", "unknown", UC_NONE},
             {2, 0, 207, "ICWAT", "Ice-free water surface", "%", UC_NONE},
-
+            {2, 0, 208, "AKHS", "Surface exchange coefficients for T and Q divided by delta z", "m/s", UC_NONE},
+            {2, 0, 209, "AKMS", "Surface exchange coefficients for U and V divided by delta z", "m/s", UC_NONE},
+            {2, 0, 210, "VEGT", "Vegetation canopy temperature", "K", UC_NONE},
+            {2, 0, 211, "SSTOR", "Surface water storage", "K g/m^2", UC_NONE},
+            {2, 0, 212, "LSOIL", "Liquid soil moisture content (non-frozen)", "K g/m^2", UC_NONE},
+            {2, 0, 213, "EWATR", "Open water evaporation (standing water)", "W/m^2", UC_NONE},
+            {2, 0, 214, "GWREC", "Groundwater recharge", "kg/m^2", UC_NONE},
+            {2, 0, 215, "QREC", "Flood plain recharge", "kg/m^2", UC_NONE},
+            {2, 0, 216, "SFCRH", "Roughness length for heat", "m", UC_NONE},
+            {2, 0, 217, "NDVI", "Normalized difference vegetation index", "-", UC_NONE},
+            {2, 0, 218, "LANDN", "Land-sea coverage (nearest neighbor)", "0=sea; 1=land", UC_NONE},
+            {2, 0, 219, "AMIXL", "Asymptotic mixing length scale", "m", UC_NONE},
+            {2, 0, 220, "WVINC", "Water vapor added by precip assimilation", "kg/m^2", UC_NONE},
+            {2, 0, 221, "WCINC", "Water condensate added by precip assimilation", "kg/m^2", UC_NONE},
+            {2, 0, 222, "WVCONV", "Water vapor flux convergence (vertical int)", "kg/m^2", UC_NONE},
+            {2, 0, 223, "WCCONV", "Water condensate flux convergence (vertical int)", "kg/m^2", UC_NONE},
+            {2, 0, 224, "WVUFLX", "Water vapor zonal flux (vertical int)", "kg/m^2", UC_NONE},
+            {2, 0, 225, "WVVFLX", "Water vapor meridional flux (vertical int)", "kg/m^2", UC_NONE},
+            {2, 0, 226, "WCUFLX", "Water condensate zonal flux (vertical int)", "kg/m^2", UC_NONE},
+            {2, 0, 227, "WCVFLX", "Water condensate meridional flux (vertical int)", "kg/m^2", UC_NONE},
+            {2, 0, 228, "ACOND", "Aerodynamic conductance", "m/s", UC_NONE},
+            {2, 0, 229, "EVCW", "Canopy water evaporation", "W/(m^2)", UC_NONE},
+            {2, 0, 230, "TRANS", "Transpiration", "W/(m^2)", UC_NONE},
+           /* Mike added 1/13 */
+           {2, 1, 192, "CANL", "Cold Advisory for Newborn Livestock", "0=none; 2=slight; 4=mild; 6=moderate; 8=severe; 10=extreme", UC_NONE},
    /* 66 */ {2, 3, 192, "SOILL", "Liquid Volumetric Soil Moisture (non Frozen)", "Proportion", UC_NONE},
    /* 67 */ {2, 3, 193, "RLYRS", "Number of Soil Layers in Root Zone", "-", UC_NONE},
    /* 68 */ {2, 3, 194, "SLTYP", "Surface Slope Type", "Index", UC_NONE},
    /* 69 */ {2, 3, 195, "SMREF", "Transpiration Stress-onset (soil moisture)", "Proportion", UC_NONE},
    /* 70 */ {2, 3, 196, "SMDRY", "Direct Evaporation Cease (soil moisture)", "Proportion", UC_NONE},
    /* 71 */ {2, 3, 197, "POROS", "Soil Porosity", "Proportion", UC_NONE},
+            {2, 3, 198, "EVBS", "Direct evaporation from bare soil", "W/m^2", UC_NONE},
+            {2, 3, 199, "LSPA", "Land Surface Precipitation Accumulation", "kg/m^2", UC_NONE},
+            {2, 3, 200, "BARET", "Bare soil surface skin temperature", "K", UC_NONE},
+            {2, 3, 201, "AVSFT", "Average surface skin temperature", "K", UC_NONE},
+            {2, 3, 202, "RADT", "Effective radiative skin temperature", "K", UC_NONE},
+            {2, 3, 203, "FLDCP", "Field Capacity", "fraction", UC_NONE},
 
 /* ScatEstUWind -> USCT, ScatEstVWind -> VSCT as of 7/5/2006 (pre 1.80) */
    /* 72 */ {3, 1, 192, "USCT", "Scatterometer Estimated U Wind", "m/s", UC_NONE},
    /* 73 */ {3, 1, 193, "VSCT", "Scatterometer Estimated V Wind", "m/s", UC_NONE},
 
+/* table 4.2 : 3.192 according to NCEP is "Forecast Satellite Imagery". */
+            {3, 192, 0, "SBT122", "Simulated Brightness Temperature for GOES 12, Channel 2", "K", UC_NONE},
+            {3, 192, 1, "SBT123", "Simulated Brightness Temperature for GOES 12, Channel 3", "K", UC_NONE},
+            {3, 192, 2, "SBT124", "Simulated Brightness Temperature for GOES 12, Channel 4", "K", UC_NONE},
+            {3, 192, 3, "SBT125", "Simulated Brightness Temperature for GOES 12, Channel 5", "K", UC_NONE},
+            {3, 192, 4, "SBC123", "Simulated Brightness Counts for GOES 12, Channel 3", "numeric", UC_NONE},
+            {3, 192, 5, "SBC124", "Simulated Brightness Counts for GOES 12, Channel 4", "numeric", UC_NONE},
+
+           {10, 0, 192, "WSTP", "Wave Steepness", "0", UC_NONE},
+
+/* The following entry was moved to 10,3,196 */
+/*
+           {10, 1, 192, "P2OMLT", "Ocean Mixed Layer Potential Density (Reference 2000m)", "kg/(m^3)", UC_NONE},
+*/
+           {10, 1, 192, "OMLU", "Ocean Mixed Layer U Velocity", "m/s", UC_NONE},
+           {10, 1, 193, "OMLV", "Ocean Mixed Layer V Velocity", "m/s", UC_NONE},
+           {10, 1, 194, "UBARO", "Barotropic U Velocity", "m/s", UC_NONE},
+           {10, 1, 195, "VBARO", "Barotropic V Velocity", "m/s", UC_NONE},
+
    /* Arthur Added this to both NDFD and NCEP local tables. (5/1/2006) */
            {10, 3, 192, "SURGE", "Hurricane Storm Surge", "m", UC_M2Feet},
            {10, 3, 193, "ETSRG", "Extra Tropical Storm Surge", "m", UC_M2Feet},
+           {10, 3, 194, "ELEV", "Ocean Surface Elevation Relative to Geoid", "m", UC_NONE},
+           {10, 3, 195, "SSHG", "Sea Surface Height Relative to Geoid", "m", UC_NONE},
+/* The following entry were moved to 10,4,192, 10,4,193 */
+/*
+           {10, 3, 196, "WTMPC", "3-D Temperature", "deg C", UC_NONE},
+           {10, 3, 197, "SALIN", "3-D Salinity", "", UC_NONE},
+*/
+           {10, 3, 196, "P2OMLT", "Ocean Mixed Layer Potential Density (Reference 2000m)", "kg/(m^3)", UC_NONE},
+           {10, 3, 197, "AOHFLX", "Net Air-Ocean Heat Flux", "W/(m^2)", UC_NONE},
+           {10, 3, 198, "ASHFL", "Assimilative Heat Flux", "W/(m^2)", UC_NONE},
+           {10, 3, 199, "SSTT", "Surface Temperature Trend", "degree/day", UC_NONE},
+           {10, 3, 200, "SSST", "Surface Salinity Trend", "psu/day", UC_NONE},
+           {10, 3, 201, "KENG", "Kinetic Energy", "J/kg", UC_NONE},
+           {10, 3, 202, "SLTFL", "Salt Flux", "kg/(m^2*s)", UC_NONE},
+
+           {10, 3, 242, "TCSRG20", "20% Tropical Cyclone Storm Surge Exceedance", "m", UC_M2Feet},
+           {10, 3, 243, "TCSRG30", "30% Tropical Cyclone Storm Surge Exceedance", "m", UC_M2Feet},
+           {10, 3, 244, "TCSRG40", "40% Tropical Cyclone Storm Surge Exceedance", "m", UC_M2Feet},
+           {10, 3, 245, "TCSRG50", "50% Tropical Cyclone Storm Surge Exceedance", "m", UC_M2Feet},
+           {10, 3, 246, "TCSRG60", "60% Tropical Cyclone Storm Surge Exceedance", "m", UC_M2Feet},
+           {10, 3, 247, "TCSRG70", "70% Tropical Cyclone Storm Surge Exceedance", "m", UC_M2Feet},
+           {10, 3, 248, "TCSRG80", "80% Tropical Cyclone Storm Surge Exceedance", "m", UC_M2Feet},
+           {10, 3, 249, "TCSRG90", "90% Tropical Cyclone Storm Surge Exceedance", "m", UC_M2Feet},
+
+           {10, 4, 192, "WTMPC", "3-D Temperature", "deg C", UC_NONE},
+           {10, 4, 193, "SALIN", "3-D Salinity", "", UC_NONE},
+           {10, 4, 194, "BKENG", "Barotropic Kinetic Energy", "J/kg", UC_NONE},
+           {10, 4, 195, "DBSS", "Geometric Depth Below Sea Surface", "m", UC_NONE},
+           {10, 4, 196, "INTFD", "Interface Depths", "m", UC_NONE},
+           {10, 4, 197, "OHC", "Ocean Heat Content", "J/m^2", UC_NONE},
+};
+
+/*
+  From http://www.nssl.noaa.gov/projects/mrms/operational/tables.php
+*/
+static const GRIB2LocalTable MRMS_LclTable[] = {
+   /* 0 */ {209, 2, 0, "LightningDensityNLDN1min", "CG Lightning Density 1-min - NLDN", "flashes/km^2/min", UC_NONE},
+   /* 1 */ {209, 2, 1, "LightningDensityNLDN5min", "CG Lightning Density 5-min - NLDN", "flashes/km^2/min", UC_NONE},
+   /* 2 */ {209, 2, 2, "LightningDensityNLDN15min", "CG Lightning Density 15-min - NLDN", "flashes/km^2/min", UC_NONE},
+   /* 3 */ {209, 2, 3, "LightningDensityNLDN30min", "CG Lightning Density 30-min - NLDN", "flashes/km^2/min", UC_NONE},
+   /* 4 */ {209, 2, 4, "LightningProbabilityNext30min", "Lightning Probability 0-30 minutes - NLDN", "%", UC_NONE},
+   /* 5 */ {209, 3, 0, "MergedAzShear0to2kmAGL", "Azimuth Shear 0-2km AGL", ".001/s", UC_NONE},
+   /* 6 */ {209, 3, 1, "MergedAzShear3to6kmAGL", "Azimuth Shear 3-6km AGL", ".001/s", UC_NONE},
+   /* 7 */ {209, 3, 2, "RotationTrack30min", "Rotation Track 0-2km AGL 30-min", ".001/s", UC_NONE},
+   /* 8 */ {209, 3, 3, "RotationTrack60min", "Rotation Track 0-2km AGL 60-min", ".001/s", UC_NONE},
+   /* 9 */ {209, 3, 4, "RotationTrack120min", "Rotation Track 0-2km AGL 120-min", ".001/s", UC_NONE},
+   /* 10 */ {209, 3, 5, "RotationTrack240min", "Rotation Track 0-2km AGL 240-min", ".001/s", UC_NONE},
+   /* 11 */ {209, 3, 6, "RotationTrack360min", "Rotation Track 0-2km AGL 360-min", ".001/s", UC_NONE},
+   /* 12 */ {209, 3, 7, "RotationTrack1440min", "Rotation Track 0-2km AGL 1440-min", ".001/s", UC_NONE},
+   /* 13 */ {209, 3, 14, "RotationTrackML30min", "Rotation Track 0-2km AGL 30-min", ".001/s", UC_NONE},
+   /* 14 */ {209, 3, 15, "RotationTrackML60min", "Rotation Track 0-2km AGL 60-min", ".001/s", UC_NONE},
+   /* 15 */ {209, 3, 16, "RotationTrackML120min", "Rotation Track 0-2km AGL 120-min", ".001/s", UC_NONE},
+   /* 16 */ {209, 3, 17, "RotationTrackML240min", "Rotation Track 0-2km AGL 240-min", ".001/s", UC_NONE},
+   /* 17 */ {209, 3, 18, "RotationTrackML360min", "Rotation Track 0-2km AGL 360-min", ".001/s", UC_NONE},
+   /* 18 */ {209, 3, 19, "RotationTrackML1440min", "Rotation Track 0-2km AGL 1440-min", ".001/s", UC_NONE},
+   /* 19 */ {209, 3, 26, "SHI", "Severe Hail Index", "index", UC_NONE},
+   /* 20 */ {209, 3, 27, "POSH", "Prob of Severe Hail", "%", UC_NONE},
+   /* 21 */ {209, 3, 28, "MESH", "Maximum Estimated Size of Hail (MESH)", "mm", UC_NONE},
+   /* 22 */ {209, 3, 29, "MESHMax30min", "MESH Hail Swath 30-min", "mm", UC_NONE},
+   /* 23 */ {209, 3, 30, "MESHMax60min", "MESH Hail Swath 60-min", "mm", UC_NONE},
+   /* 24 */ {209, 3, 31, "MESHMax120min", "MESH Hail Swath 120-min", "mm", UC_NONE},
+   /* 25 */ {209, 3, 32, "MESHMax240min", "MESH Hail Swath 240-min", "mm", UC_NONE},
+   /* 26 */ {209, 3, 33, "MESHMax360min", "MESH Hail Swath 360-min", "mm", UC_NONE},
+   /* 27 */ {209, 3, 34, "MESHMax1440min", "MESH Hail Swath 1440-min", "mm", UC_NONE},
+   /* 28 */ {209, 3, 41, "VIL", "Vertically Integrated Liquid", "kg/m^2", UC_NONE},
+   /* 29 */ {209, 3, 42, "VILDensity", "Vertically Integrated Liquid Density", "g/m^3", UC_NONE},
+   /* 30 */ {209, 3, 43, "VII", "Vertically Integrated Ice", "kg/m^2", UC_NONE},
+   /* 31 */ {209, 3, 44, "EchoTop18", "Echo Top - 18 dBZ", "km", UC_NONE},
+   /* 32 */ {209, 3, 45, "EchoTop30", "Echo Top - 30 dBZ", "km", UC_NONE},
+   /* 33 */ {209, 3, 46, "EchoTop50", "Echo Top - 50 dBZ", "km", UC_NONE},
+   /* 34 */ {209, 3, 47, "EchoTop60", "Echo Top - 60 dBZ", "km", UC_NONE},
+   /* 35 */ {209, 3, 48, "H50AboveM20C", "Thickness [50 dBZ top - (-20C)]", "km", UC_NONE},
+   /* 36 */ {209, 3, 49, "H50Above0C", "Thickness [50 dBZ top - 0C]", "km", UC_NONE},
+   /* 37 */ {209, 3, 50, "H60AboveM20C", "Thickness [60 dBZ top - (-20C)]", "km", UC_NONE},
+   /* 38 */ {209, 3, 51, "H60Above0C", "Thickness [60 dBZ top - 0C]", "km", UC_NONE},
+   /* 39 */ {209, 3, 52, "Reflectivity0C", "Isothermal Reflectivity at 0C", "dBZ", UC_NONE},
+   /* 40 */ {209, 3, 53, "ReflectivityM5C", "Isothermal Reflectivity at -5C", "dBZ", UC_NONE},
+   /* 41 */ {209, 3, 54, "ReflectivityM10C", "Isothermal Reflectivity at -10C", "dBZ", UC_NONE},
+   /* 42 */ {209, 3, 55, "ReflectivityM15C", "Isothermal Reflectivity at -15C", "dBZ", UC_NONE},
+   /* 43 */ {209, 3, 56, "ReflectivityM20C", "Isothermal Reflectivity at -20C", "dBZ", UC_NONE},
+   /* 44 */ {209, 3, 57, "ReflectivityAtLowestAltitude", "ReflectivityAtLowestAltitude", "dBZ", UC_NONE},
+   /* 45 */ {209, 3, 58, "MergedReflectivityAtLowestAltitude", "Non Quality Controlled Reflectivity At Lowest Altitude", "dBZ", UC_NONE},
+   /* 46 */ {209, 4, 0, "IRband4", "Infrared (E/W blend)", "K", UC_NONE},
+   /* 47 */ {209, 4, 1, "Visible", "Visible (E/W blend)", "non-dim", UC_NONE},
+   /* 48 */ {209, 4, 2, "WaterVapor", "Water Vapor (E/W blend)", "K", UC_NONE},
+   /* 49 */ {209, 4, 3, "CloudCover", "Cloud Cover", "K", UC_NONE},
+   /* 50 */ {209, 6, 0, "PrecipFlag", "Surface Precipitation Type (Convective; Stratiform; Tropical; Hail; Snow)", "flag", UC_NONE},
+   /* 51 */ {209, 6, 1, "PrecipRate", "Radar Precipitation Rate", "mm/hr", UC_NONE},
+   /* 52 */ {209, 6, 2, "RadarOnlyQPE01H", "Radar Precipitation Accumulation 1-hour", "mm", UC_NONE},
+   /* 53 */ {209, 6, 3, "RadarOnlyQPE03H", "Radar Precipitation Accumulation 3-hour", "mm", UC_NONE},
+   /* 54 */ {209, 6, 4, "RadarOnlyQPE06H", "Radar Precipitation Accumulation 6-hour", "mm", UC_NONE},
+   /* 55 */ {209, 6, 5, "RadarOnlyQPE12H", "Radar Precipitation Accumulation 12-hour", "mm", UC_NONE},
+   /* 56 */ {209, 6, 6, "RadarOnlyQPE24H", "Radar Precipitation Accumulation 24-hour", "mm", UC_NONE},
+   /* 57 */ {209, 6, 7, "RadarOnlyQPE48H", "Radar Precipitation Accumulation 48-hour", "mm", UC_NONE},
+   /* 58 */ {209, 6, 8, "RadarOnlyQPE72H", "Radar Precipitation Accumulation 72-hour", "mm", UC_NONE},
+   /* 59 */ {209, 6, 9, "GaugeCorrQPE01H", "Local Gauge Bias Corrected Radar Precipitation Accumulation 1-hour", "mm", UC_NONE},
+   /* 60 */ {209, 6, 10, "GaugeCorrQPE03H", "Local Gauge Bias Corrected Radar Precipitation Accumulation 3-hour", "mm", UC_NONE},
+   /* 61 */ {209, 6, 11, "GaugeCorrQPE06H", "Local Gauge Bias Corrected Radar Precipitation Accumulation 6-hour", "mm", UC_NONE},
+   /* 62 */ {209, 6, 12, "GaugeCorrQPE12H", "Local Gauge Bias Corrected Radar Precipitation Accumulation 12-hour", "mm", UC_NONE},
+   /* 63 */ {209, 6, 13, "GaugeCorrQPE24H", "Local Gauge Bias Corrected Radar Precipitation Accumulation 24-hour", "mm", UC_NONE},
+   /* 64 */ {209, 6, 14, "GaugeCorrQPE48H", "Local Gauge Bias Corrected Radar Precipitation Accumulation 48-hour", "mm", UC_NONE},
+   /* 65 */ {209, 6, 15, "GaugeCorrQPE72H", "Local Gauge Bias Corrected Radar Precipitation Accumulation 72-hour", "mm", UC_NONE},
+   /* 66 */ {209, 6, 16, "GaugeOnlyQPE01H", "Gauge Only Precipitation Accumulation 1-hour", "mm", UC_NONE},
+   /* 67 */ {209, 6, 17, "GaugeOnlyQPE03H", "Gauge Only Precipitation Accumulation 3-hour", "mm", UC_NONE},
+   /* 68 */ {209, 6, 18, "GaugeOnlyQPE06H", "Gauge Only Precipitation Accumulation 6-hour", "mm", UC_NONE},
+   /* 69 */ {209, 6, 19, "GaugeOnlyQPE12H", "Gauge Only Precipitation Accumulation 12-hour", "mm", UC_NONE},
+   /* 70 */ {209, 6, 20, "GaugeOnlyQPE24H", "Gauge Only Precipitation Accumulation 24-hour", "mm", UC_NONE},
+   /* 71 */ {209, 6, 21, "GaugeOnlyQPE48H", "Gauge Only Precipitation Accumulation 48-hour", "mm", UC_NONE},
+   /* 72 */ {209, 6, 22, "GaugeOnlyQPE72H", "Gauge Only Precipitation Accumulation 72-hour", "mm", UC_NONE},
+   /* 73 */ {209, 6, 23, "MountainMapperQPE01H", "Mountain Mapper Precipitation Accumulation 1-hour", "mm", UC_NONE},
+   /* 74 */ {209, 6, 24, "MountainMapperQPE03H", "Mountain Mapper Precipitation Accumulation 3-hour", "mm", UC_NONE},
+   /* 75 */ {209, 6, 25, "MountainMapperQPE06H", "Mountain Mapper Precipitation Accumulation 6-hour", "mm", UC_NONE},
+   /* 76 */ {209, 6, 26, "MountainMapperQPE12H", "Mountain Mapper Precipitation Accumulation 12-hour", "mm", UC_NONE},
+   /* 77 */ {209, 6, 27, "MountainMapperQPE24H", "Mountain Mapper Precipitation Accumulation 24-hour", "mm", UC_NONE},
+   /* 78 */ {209, 6, 28, "MountainMapperQPE48H", "Mountain Mapper Precipitation Accumulation 48-hour", "mm", UC_NONE},
+   /* 79 */ {209, 6, 29, "MountainMapperQPE72H", "Mountain Mapper Precipitation Accumulation 72-hour", "mm", UC_NONE},
+   /* 80 */ {209, 7, 0, "ModelSurfaceTemp", "Model Surface Temperature [RAP 13km]", "C", UC_NONE},
+   /* 81 */ {209, 7, 1, "ModelWetBulbTemp", "Model Surface Wet Bulb Temperature [RAP 13km]", "C", UC_NONE},
+   /* 82 */ {209, 7, 2, "WarmRainProbability", "Probability of Warm Rain [RAP 13km derived]", "%", UC_NONE},
+   /* 83 */ {209, 7, 3, "ModelHeight0C", "Model Freezing Level Height [RAP 13km]", "m", UC_NONE},
+   /* 84 */ {209, 7, 4, "BrightBandTopHeight", "Brightband Top Radar [RAP 13km derived]", "m", UC_NONE},
+   /* 85 */ {209, 7, 5, "BrightBandBottomHeight", "Brightband Bottom Radar [RAP 13km derived]", "m", UC_NONE},
+   /* 86 */ {209, 8, 0, "RadarQualityIndex", "Radar Quality Index", "non-dim", UC_NONE},
+   /* 87 */ {209, 8, 1, "GaugeInflIndex01H", "Gauge Influence Index for 1-hour QPE", "non-dim", UC_NONE},
+   /* 88 */ {209, 8, 2, "GaugeInflIndex03H", "Gauge Influence Index for 3-hour QPE", "non-dim", UC_NONE},
+   /* 89 */ {209, 8, 3, "GaugeInflIndex06H", "Gauge Influence Index for 6-hour QPE", "non-dim", UC_NONE},
+   /* 90 */ {209, 8, 4, "GaugeInflIndex12H", "Gauge Influence Index for 12-hour QPE", "non-dim", UC_NONE},
+   /* 91 */ {209, 8, 5, "GaugeInflIndex24H", "Gauge Influence Index for 24-hour QPE", "non-dim", UC_NONE},
+   /* 92 */ {209, 8, 6, "GaugeInflIndex48H", "Gauge Influence Index for 48-hour QPE", "non-dim", UC_NONE},
+   /* 93 */ {209, 8, 7, "GaugeInflIndex72H", "Gauge Influence Index for 72-hour QPE", "non-dim", UC_NONE},
+   /* 94 */ {209, 8, 8, "SeamlessHSR", "Seamless Hybrid Scan Reflectivity with VPR Correction", "dBZ", UC_NONE},
+   /* 95 */ {209, 8, 9, "SeamlessHSRHeight", "Height of Seamless Hybrid Scan Reflectivity", "km", UC_NONE},
+   /* 96 */ {209, 9, 0, "CONUSMergedReflectivityQC", "WSR-88D 3D Reflectivity Mosaic - 33 CAPPIS (500-19000m)", "dBZ", UC_NONE},
+   /* 97 */ {209, 9, 1, "CONUSPlusMergedReflectivityQC", "All Radar 3D Reflectivity Mosaic - 33 CAPPIS (500-19000m)", "dBZ", UC_NONE},
+   /* 98 */ {209, 10, 0, "MergedReflectivityQCComposite", "Composite Reflectivity Mosaic (optimal method)", "dBZ", UC_NONE},
+   /* 99 */ {209, 10, 1, "HeightCompositeReflectivity", "Height of Composite Reflectivity Mosaic (optimal method)", "m", UC_NONE},
+   /* 100 */ {209, 10, 2, "LowLevelCompositeReflectivity", "Low-Level Composite Reflectivity Mosaic (0-4 km)", "dBZ", UC_NONE},
+   /* 101 */ {209, 10, 3, "HeightLowLevelCompositeReflectivity", "Height of Low-Level Composite Reflectivity Mosaic (0-4 km)", "m", UC_NONE},
+   /* 102 */ {209, 10, 4, "LayerCompositeReflectivity_Low", "Layer Composite Reflectivity Mosaic 0-24kft (low altitude)", "dBZ", UC_NONE},
+   /* 103 */ {209, 10, 5, "LayerCompositeReflectivity_High", "Layer Composite Reflectivity Mosaic 24-60kft (highest altitude)", "dBZ", UC_NONE},
+   /* 104 */ {209, 10, 6, "LayerCompositeReflectivity_Super", "Layer Composite Reflectivity Mosaic 33-60kft (super high altitude)", "dBZ", UC_NONE},
+   /* 105 */ {209, 10, 7, "ReflectivityCompositeHourlyMax", "Composite Reflectivity Hourly Maximum", "dBZ", UC_NONE},
+   /* 106 */ {209, 10, 8, "ReflectivityMaxAboveM10C", "Maximum Reflectivity at -10 deg C height and above", "dBZ", UC_NONE},
+   /* 107 */ {209, 11, 0, "MergedBaseReflectivityQC", "Mosaic Base Reflectivity (optimal method)", "dBZ", UC_NONE},
+   /* 108 */ {209, 11, 1, "MergedReflectivityComposite", "UnQC'd Composite Reflectivity Mosaic (max ref)", "dBZ", UC_NONE},
+   /* 109 */ {209, 11, 2, "MergedReflectivityQComposite", "Composite Reflectivity Mosaic (max ref)", "dBZ", UC_NONE},
 };
+
 /* *INDENT-ON* */
 
 int IsData_NDFD (unsigned short int center, unsigned short int subcenter)
@@ -1439,6 +2133,9 @@ static const GRIB2LocalTable *Choose_LocalParmTable (unsigned short int center,
                *tableLen = 0;
                return NULL;
          }
+      case 161:
+         *tableLen = sizeof (MRMS_LclTable) / sizeof (GRIB2LocalTable);
+         return &MRMS_LclTable[0];
       default:
          *tableLen = 0;
          return NULL;
@@ -1490,6 +2187,7 @@ static const GRIB2LocalTable *Choose_LocalParmTable (unsigned short int center,
 static void ElemNameProb (uShort2 center, uShort2 subcenter, int prodType,
                           CPL_UNUSED int templat,
                           uChar cat, uChar subcat, sInt4 lenTime,
+                          uChar timeRangeUnit,
                           uChar timeIncrType,
                           CPL_UNUSED uChar genID,
                           uChar probType,
@@ -1506,26 +2204,105 @@ static void ElemNameProb (uShort2 center, uShort2 subcenter, int prodType,
    *unit = (char *) malloc (strlen ("[%]") + 1);
    strcpy (*unit, "[%]");
 
+   {
+      // 25.4 mm = 1 inch
+      const double tmp = upperProb * 25.4;
+
+      // TODO(schwehr): Make a function and reuse it for other limit checks.
+      if (upperProb > tmp ||
+          tmp > std::numeric_limits<int>::max() ||
+          tmp < std::numeric_limits<int>::min() ||
+          CPLIsNan(tmp) ) {
+         // TODO(schwehr): What is the correct response?
+         errSprintf ("ERROR: upperProb out of range.  Setting to 0.\n");
+         upperProb = 0.0;
+      }
+   }
+
    if (f_isNdfd || f_isMos) {
       /* Deal with NDFD/MOS handling of Prob Precip_Tot -> PoP12 */
       if ((prodType == 0) && (cat == 1) && (subcat == 8)) {
-         myAssert (probType == 1);
-         if (lenTime > 0) {
-            mallocSprintf (name, "PoP%02d", lenTime);
-            mallocSprintf (comment, "%02d hr Prob of Precip > 0.01 "
-                           "In. [%%]", lenTime);
+         if (probType == 0) {
+            if (lenTime > 0) {
+               if (timeRangeUnit == 3) {
+                  mallocSprintf (name, "ProbPrcpBlw%02dm", lenTime);
+                  mallocSprintf (comment, "%02d mon Prob of Precip below average", lenTime);
+               } else if (timeRangeUnit == 4) {
+                  mallocSprintf (name, "ProbPrcpBlw%02dy", lenTime);
+                  mallocSprintf (comment, "%02d yr Prob of Precip below average", lenTime);
+               } else {
+                  mallocSprintf (name, "ProbPrcpBlw%02d", lenTime);
+                  mallocSprintf (comment, "%02d hr Prob of Precip below average", lenTime);
+               }
+            } else {
+               mallocSprintf (name, "ProbPrcpBlw");
+               mallocSprintf (comment, "Prob of precip below average");
+            }
+            *convert = UC_NONE;
+         } else if (probType == 3) {
+            if (lenTime > 0) {
+               if (timeRangeUnit == 3) {
+                  mallocSprintf (name, "ProbPrcpAbv%02dm", lenTime);
+                  mallocSprintf (comment, "%02d mon Prob of Precip above average", lenTime);
+               } else if (timeRangeUnit == 4) {
+                  mallocSprintf (name, "ProbPrcpAbv%02dy", lenTime);
+                  mallocSprintf (comment, "%02d yr Prob of Precip above average", lenTime);
+               } else {
+                  mallocSprintf (name, "ProbPrcpAbv%02d", lenTime);
+                  mallocSprintf (comment, "%02d hr Prob of Precip above average", lenTime);
+               }
+            } else {
+               mallocSprintf (name, "ProbPrcpAbv");
+               mallocSprintf (comment, "Prob of precip above average");
+            }
+            *convert = UC_NONE;
          } else {
-            *name = (char *) malloc (strlen ("PoP") + 1);
-            strcpy (*name, "PoP");
-            *comment =
-                  (char *) malloc (strlen ("Prob of Precip > 0.01 In. [%]") +
-                                   1);
-            strcpy (*comment, "Prob of Precip > 0.01 In. [%]");
+            myAssert (probType == 1);
+            if (lenTime > 0) {
+               if (timeRangeUnit == 3) {
+                  if (upperProb != (double) .254) {
+                     mallocSprintf (name, "PoP%02dm-%03d", lenTime, (int) (upperProb / .254 + .5));
+                  } else {
+                     mallocSprintf (name, "PoP%02dm", lenTime);
+                  }
+                  mallocSprintf (comment, "%02d mon Prob of Precip > %g In.", lenTime, upperProb / 25.4);
+               } else if (timeRangeUnit == 4) {
+                  if (upperProb != (double) .254) {
+                     mallocSprintf (name, "PoP%02dy-%03d", lenTime, (int) (upperProb / .254 + .5));
+                  } else {
+                     mallocSprintf (name, "PoP%02dy", lenTime);
+                  }
+                  mallocSprintf (comment, "%02d yr Prob of Precip > %g In.", lenTime, upperProb / 25.4);
+               } else {
+                  /* The 300 is to deal with an old NDFD encoding bug from 2002:
+                   * PDS-S4 | Upper limit (scale value, scale factor) | 300 (3, -2)
+                   * 25.4 mm = 1 inch.  Rain typically .01 inches = .254 mm
+                   */
+                  if ((upperProb != (double) .254) && (upperProb != (double) 300)) {
+                     mallocSprintf (name, "PoP%02d-%03d", lenTime, (int) (upperProb / .254 + .5));
+                  } else {
+                     mallocSprintf (name, "PoP%02d", lenTime);
+                  }
+                  if (upperProb != (double) 300) {
+                     mallocSprintf (comment, "%02d hr Prob of Precip > %g In.", lenTime, upperProb / 25.4);
+                  } else {
+                     mallocSprintf (comment, "%02d hr Prob of Precip > 0.01 In.", lenTime);
+                  }
+               }
+            } else {
+               if (upperProb != (double) .254) {
+                  mallocSprintf (name, "PoP-p%03d", (int) (upperProb / .254 + .5));
+               } else {
+                  mallocSprintf (name, "PoP");
+               }
+               mallocSprintf (comment, "Prob of Precip > %g In.", upperProb / 25.4);
+            }
+            *convert = UC_NONE;
          }
          *convert = UC_NONE;
          return;
       }
-      /* 
+      /*
        * Deal with NDFD handling of Prob. Wind speeds.
        * There are different solutions for naming the Prob. Wind fields
        * AAT(Mine): ProbSurge5c
@@ -1543,14 +2320,22 @@ static void ElemNameProb (uShort2 center, uShort2 subcenter, int prodType,
             mallocSprintf (name, "ProbSurge%02dc",
                            (int) ((upperProb / 0.3048) + .5));
          }
-         mallocSprintf (comment, "%02d hr Prob of Hurricane Storm Surge > %g "
-                        "m [%%]", lenTime, upperProb);
+         if (timeRangeUnit == 3) {
+            mallocSprintf (comment, "%02d mon Prob of Hurricane Storm Surge > %g "
+                           "m", lenTime, upperProb);
+         } else if (timeRangeUnit == 4) {
+            mallocSprintf (comment, "%02d yr Prob of Hurricane Storm Surge > %g "
+                           "m", lenTime, upperProb);
+         } else {
+            mallocSprintf (comment, "%02d hr Prob of Hurricane Storm Surge > %g "
+                           "m", lenTime, upperProb);
+         }
          *convert = UC_NONE;
          return;
       }
    }
    if (f_isNdfd) {
-      /* 
+      /*
        * Deal with NDFD handling of Prob. Wind speeds.
        * There are different solutions for naming the Prob. Wind fields
        * Tim Boyer: TCWindSpdIncr34 TCWindSpdIncr50 TCWindSpdIncr64
@@ -1573,8 +2358,16 @@ static void ElemNameProb (uShort2 center, uShort2 subcenter, int prodType,
             mallocSprintf (name, "ProbWindSpd%02dc",
                            (int) ((upperProb * 3600. / 1852.) + .5));
          }
-         mallocSprintf (comment, "%02d hr Prob of Wind speed > %g m/s [%%]",
-                        lenTime, upperProb);
+         if (timeRangeUnit == 3) {
+            mallocSprintf (comment, "%02d mon Prob of Wind speed > %g m/s",
+                           lenTime, upperProb);
+         } else if (timeRangeUnit == 4) {
+            mallocSprintf (comment, "%02d yr Prob of Wind speed > %g m/s",
+                           lenTime, upperProb);
+         } else {
+            mallocSprintf (comment, "%02d hr Prob of Wind speed > %g m/s",
+                           lenTime, upperProb);
+         }
          *convert = UC_NONE;
          return;
       }
@@ -1588,30 +2381,100 @@ static void ElemNameProb (uShort2 center, uShort2 subcenter, int prodType,
          /* The NDFD over-rides for probability templates have already been
           * handled. */
          if (lenTime > 0) {
-            mallocSprintf (name, "Prob%s%02d", table[subcat].name, lenTime);
-            mallocSprintf (comment, "%02d hr Prob of %s ", lenTime,
-                           table[subcat].comment);
+            if (timeRangeUnit == 3) {
+               mallocSprintf (name, "Prob%s%02dm", table[subcat].name, lenTime);
+               mallocSprintf (comment, "%02d mon Prob of %s ", lenTime,
+                              table[subcat].comment);
+            } else if (timeRangeUnit == 4) {
+               mallocSprintf (name, "Prob%s%02dy", table[subcat].name, lenTime);
+               mallocSprintf (comment, "%02d yr Prob of %s ", lenTime,
+                              table[subcat].comment);
+            } else {
+               mallocSprintf (name, "Prob%s%02d", table[subcat].name, lenTime);
+               mallocSprintf (comment, "%02d hr Prob of %s ", lenTime,
+                              table[subcat].comment);
+            }
          } else {
             mallocSprintf (name, "Prob%s", table[subcat].name);
             mallocSprintf (comment, "Prob of %s ", table[subcat].comment);
          }
          if (probType == 0) {
-            reallocSprintf (comment, "< %g %s [%%]", lowerProb,
-                            table[subcat].unit);
+            if ((f_isNdfd || f_isMos) && (strcmp (table[subcat].name, "TMP") == 0)) {
+               reallocSprintf (comment, "below average");
+               free (*name);
+               if (lenTime > 0) {
+                  if (timeRangeUnit == 3) {
+                     mallocSprintf (name, "Prob%sBlw%02dm", table[subcat].name, lenTime);
+                  } else if (timeRangeUnit == 4) {
+                     mallocSprintf (name, "Prob%sBlw%02dy", table[subcat].name, lenTime);
+                  } else {
+                     mallocSprintf (name, "Prob%sBlw%02d", table[subcat].name, lenTime);
+                  }
+               } else {
+                  mallocSprintf (name, "Prob%sBlw", table[subcat].name);
+               }
+            } else {
+               reallocSprintf (comment, "< %g %s", lowerProb, table[subcat].unit);
+            }
          } else if (probType == 1) {
-            reallocSprintf (comment, "> %g %s [%%]", upperProb,
-                            table[subcat].unit);
+            if ((f_isNdfd || f_isMos) && (strcmp (table[subcat].name, "TMP") == 0)) {
+               reallocSprintf (comment, "above average");
+               free (*name);
+               if (lenTime > 0) {
+                  if (timeRangeUnit == 3) {
+                     mallocSprintf (name, "Prob%sAbv%02dm", table[subcat].name, lenTime);
+                  } else if (timeRangeUnit == 4) {
+                     mallocSprintf (name, "Prob%sAbv%02dy", table[subcat].name, lenTime);
+                  } else {
+                     mallocSprintf (name, "Prob%sAbv%02d", table[subcat].name, lenTime);
+                  }
+               } else {
+                  mallocSprintf (name, "Prob%sAbv", table[subcat].name);
+               }
+            } else {
+               reallocSprintf (comment, "> %g %s", upperProb, table[subcat].unit);
+            }
          } else if (probType == 2) {
-            reallocSprintf (comment, ">= %g, < %g %s [%%]", lowerProb,
-                            upperProb, table[subcat].unit);
-         } else if (probType == 3) {
-            reallocSprintf (comment, "> %g %s [%%]", lowerProb,
+            reallocSprintf (comment, ">= %g, < %g %s", lowerProb, upperProb,
                             table[subcat].unit);
+         } else if (probType == 3) {
+            if ((f_isNdfd || f_isMos) && (strcmp (table[subcat].name, "TMP") == 0)) {
+               reallocSprintf (comment, "above average");
+               free (*name);
+               if (lenTime > 0) {
+                  if (timeRangeUnit == 3) {
+                     mallocSprintf (name, "Prob%sAbv%02dm", table[subcat].name, lenTime);
+                  } else if (timeRangeUnit == 4) {
+                     mallocSprintf (name, "Prob%sAbv%02dy", table[subcat].name, lenTime);
+                  } else {
+                     mallocSprintf (name, "Prob%sAbv%02d", table[subcat].name, lenTime);
+                  }
+               } else {
+                  mallocSprintf (name, "Prob%sAbv", table[subcat].name);
+               }
+            } else {
+               reallocSprintf (comment, "> %g %s", lowerProb, table[subcat].unit);
+            }
          } else if (probType == 4) {
-            reallocSprintf (comment, "< %g %s [%%]", upperProb,
-                            table[subcat].unit);
+            if ((f_isNdfd || f_isMos) && (strcmp (table[subcat].name, "TMP") == 0)) {
+               reallocSprintf (comment, "below average");
+               free (*name);
+               if (lenTime > 0) {
+                  if (timeRangeUnit == 3) {
+                     mallocSprintf (name, "Prob%sBlw%02dm", table[subcat].name, lenTime);
+                  } else if (timeRangeUnit == 4) {
+                     mallocSprintf (name, "Prob%sBlw%02dy", table[subcat].name, lenTime);
+                  } else {
+                     mallocSprintf (name, "Prob%sBlw%02d", table[subcat].name, lenTime);
+                  }
+               } else {
+                  mallocSprintf (name, "Prob%sBlw", table[subcat].name);
+               }
+            } else {
+               reallocSprintf (comment, "< %g %s", upperProb, table[subcat].unit);
+            }
          } else {
-            reallocSprintf (comment, "%s [%%]", table[subcat].unit);
+            reallocSprintf (comment, "%s", table[subcat].unit);
          }
          *convert = UC_NONE;
          return;
@@ -1624,31 +2487,44 @@ static void ElemNameProb (uShort2 center, uShort2 subcenter, int prodType,
       for (i = 0; i < tableLen; i++) {
          if ((prodType == local[i].prodType) && (cat == local[i].cat) &&
              (subcat == local[i].subcat)) {
+
+            /* Ignore adding Prob prefix and "Probability of" to NDFD SPC prob
+             * products. */
             if (lenTime > 0) {
-               mallocSprintf (name, "Prob%s%02d", local[i].name, lenTime);
-               mallocSprintf (comment, "%02d hr Prob of %s ", lenTime,
-                              local[i].comment);
+               if (timeRangeUnit == 3) {
+                  mallocSprintf (name, "Prob%s%02dm", local[i].name, lenTime);
+                  mallocSprintf (comment, "%02d mon Prob of %s ", lenTime,
+                                 local[i].comment);
+               } else if (timeRangeUnit == 4) {
+                  mallocSprintf (name, "Prob%s%02dy", local[i].name, lenTime);
+                  mallocSprintf (comment, "%02d yr Prob of %s ", lenTime,
+                                 local[i].comment);
+               } else {
+                  mallocSprintf (name, "Prob%s%02d", local[i].name, lenTime);
+                  mallocSprintf (comment, "%02d hr Prob of %s ", lenTime,
+                                 local[i].comment);
+               }
             } else {
                mallocSprintf (name, "Prob%s", local[i].name);
                mallocSprintf (comment, "Prob of %s ", local[i].comment);
             }
             if (probType == 0) {
-               reallocSprintf (comment, "< %g %s [%%]", lowerProb,
+               reallocSprintf (comment, "< %g %s", lowerProb,
                                local[i].unit);
             } else if (probType == 1) {
-               reallocSprintf (comment, "> %g %s [%%]", upperProb,
+               reallocSprintf (comment, "> %g %s", upperProb,
                                local[i].unit);
             } else if (probType == 2) {
-               reallocSprintf (comment, ">= %g, < %g %s [%%]", lowerProb,
+               reallocSprintf (comment, ">= %g, < %g %s", lowerProb,
                                upperProb, local[i].unit);
             } else if (probType == 3) {
-               reallocSprintf (comment, "> %g %s [%%]", lowerProb,
+               reallocSprintf (comment, "> %g %s", lowerProb,
                                local[i].unit);
             } else if (probType == 4) {
-               reallocSprintf (comment, "< %g %s [%%]", upperProb,
+               reallocSprintf (comment, "< %g %s", upperProb,
                                local[i].unit);
             } else {
-               reallocSprintf (comment, "%s [%%]", local[i].unit);
+               reallocSprintf (comment, "%s", local[i].unit);
             }
             *convert = UC_NONE;
             return;
@@ -1658,7 +2534,7 @@ static void ElemNameProb (uShort2 center, uShort2 subcenter, int prodType,
 
    *name = (char *) malloc (strlen ("ProbUnknown") + 1);
    strcpy (*name, "ProbUnknown");
-   mallocSprintf (comment, "Prob of (prodType %d, cat %d, subcat %d) [-]",
+   mallocSprintf (comment, "Prob of (prodType %d, cat %d, subcat %d)",
                   prodType, cat, subcat);
    *convert = UC_NONE;
    return;
@@ -1668,6 +2544,7 @@ static void ElemNameProb (uShort2 center, uShort2 subcenter, int prodType,
 static void ElemNamePerc (uShort2 center, uShort2 subcenter, int prodType,
                           CPL_UNUSED int templat,
                           uChar cat, uChar subcat, sInt4 lenTime,
+                          uChar timeRangeUnit,
                           sChar percentile, char **name, char **comment,
                           char **unit, int *convert)
 {
@@ -1675,6 +2552,7 @@ static void ElemNamePerc (uShort2 center, uShort2 subcenter, int prodType,
    const GRIB2LocalTable *local;
    size_t tableLen;
    size_t i;
+   size_t len;
 
    /* Generic tables. */
    table = Choose_GRIB2ParmTable (prodType, cat, &tableLen);
@@ -1690,13 +2568,22 @@ static void ElemNamePerc (uShort2 center, uShort2 subcenter, int prodType,
                   mallocSprintf (name, "%s%02d", NDFD_Overide[i].NDFDname,
                                  percentile);
                   if (lenTime > 0) {
-                     mallocSprintf (comment, "%02d hr %s Percentile(%d) [%s]",
-                                    lenTime, table[subcat].comment,
-                                    percentile, table[subcat].unit);
+                     if (timeRangeUnit == 3) {
+                        mallocSprintf (comment, "%02d mon %s Percentile(%d)",
+                                       lenTime, table[subcat].comment,
+                                       percentile);
+                     } else if (timeRangeUnit == 4) {
+                        mallocSprintf (comment, "%02d yr %s Percentile(%d)",
+                                       lenTime, table[subcat].comment,
+                                       percentile);
+                     } else {
+                        mallocSprintf (comment, "%02d hr %s Percentile(%d)",
+                                       lenTime, table[subcat].comment,
+                                       percentile);
+                     }
                   } else {
-                     mallocSprintf (comment, "%s Percentile(%d) [%s]",
-                                    table[subcat].comment, percentile,
-                                    table[subcat].unit);
+                     mallocSprintf (comment, "%s Percentile(%d)",
+                                    table[subcat].comment, percentile);
                   }
                   mallocSprintf (unit, "[%s]", table[subcat].unit);
                   *convert = table[subcat].convert;
@@ -1706,13 +2593,19 @@ static void ElemNamePerc (uShort2 center, uShort2 subcenter, int prodType,
          }
          mallocSprintf (name, "%s%02d", table[subcat].name, percentile);
          if (lenTime > 0) {
-            mallocSprintf (comment, "%02d hr %s Percentile(%d) [%s]",
-                           lenTime, table[subcat].comment, percentile,
-                           table[subcat].unit);
+            if (timeRangeUnit == 3) {
+               mallocSprintf (comment, "%02d mon %s Percentile(%d)",
+                              lenTime, table[subcat].comment, percentile);
+            } else if (timeRangeUnit == 4) {
+               mallocSprintf (comment, "%02d yr %s Percentile(%d)",
+                              lenTime, table[subcat].comment, percentile);
+            } else {
+               mallocSprintf (comment, "%02d hr %s Percentile(%d)",
+                              lenTime, table[subcat].comment, percentile);
+            }
          } else {
-            mallocSprintf (comment, "%s Percentile(%d) [%s]",
-                           table[subcat].comment, percentile,
-                           table[subcat].unit);
+            mallocSprintf (comment, "%s Percentile(%d)",
+                           table[subcat].comment, percentile);
          }
          mallocSprintf (unit, "[%s]", table[subcat].unit);
          *convert = table[subcat].convert;
@@ -1726,14 +2619,35 @@ static void ElemNamePerc (uShort2 center, uShort2 subcenter, int prodType,
       for (i = 0; i < tableLen; i++) {
          if ((prodType == local[i].prodType) && (cat == local[i].cat) &&
              (subcat == local[i].subcat)) {
-            mallocSprintf (name, "%s%02d", local[i].name, percentile);
+/* If last two characters in name are numbers, then the name contains
+ * the percentile (or exceedance value) so don't tack on percentile here.*/
+            len = strlen(local[i].name);
+            if (isdigit(local[i].name[len -1]) && isdigit(local[i].name[len -2])) {
+               mallocSprintf (name, "%s", local[i].name);
+            } else if ((strcmp (local[i].name, "Surge") == 0) ||
+                       (strcmp (local[i].name, "SURGE") == 0)) {
+/* Provide a special exception for storm surge exceedance.
+ * Want exceedance value rather than percentile value.
+ */
+               mallocSprintf (name, "%s%02d", local[i].name, 100 - percentile);
+            } else {
+               mallocSprintf (name, "%s%02d", local[i].name, percentile);
+            }
+
             if (lenTime > 0) {
-               mallocSprintf (comment, "%02d hr %s Percentile(%d) [%s]",
-                              lenTime, local[i].comment, percentile,
-                              local[i].unit);
+               if (timeRangeUnit == 3) {
+                  mallocSprintf (comment, "%02d mon %s Percentile(%d)",
+                                 lenTime, local[i].comment, percentile);
+               } else if (timeRangeUnit == 4) {
+                  mallocSprintf (comment, "%02d yr %s Percentile(%d)",
+                                 lenTime, local[i].comment, percentile);
+               } else {
+                  mallocSprintf (comment, "%02d hr %s Percentile(%d)",
+                                 lenTime, local[i].comment, percentile);
+               }
             } else {
-               mallocSprintf (comment, "%s Percentile(%d) [%s]",
-                              local[i].comment, percentile, local[i].unit);
+               mallocSprintf (comment, "%s Percentile(%d)",
+                              local[i].comment, percentile);
             }
             mallocSprintf (unit, "[%s]", local[i].unit);
             *convert = local[i].convert;
@@ -1755,79 +2669,187 @@ static void ElemNamePerc (uShort2 center, uShort2 subcenter, int prodType,
 /* Deal with non-prob templates 2/16/2006 */
 static void ElemNameNorm (uShort2 center, uShort2 subcenter, int prodType,
                           int templat, uChar cat, uChar subcat, sInt4 lenTime,
+                          uChar timeRangeUnit,
                           CPL_UNUSED uChar timeIncrType,
                           CPL_UNUSED uChar genID,
                           CPL_UNUSED uChar probType,
                           CPL_UNUSED double lowerProb,
                           CPL_UNUSED double upperProb,
                           char **name,
-                          char **comment, char **unit, int *convert)
+                          char **comment, char **unit, int *convert,
+                          sChar f_fstValue, double fstSurfValue,
+                          sChar f_sndValue, double sndSurfValue)
 {
    const GRIB2ParmTable *table;
    const GRIB2LocalTable *local;
    size_t tableLen;
    size_t i;
    sChar f_accum;
+   float delt;
 
    /* Check for over-ride case for ozone.  Originally just for NDFD, but I
     * think it is useful for ozone data that originated elsewhere. */
    if ((prodType == 0) && (templat == 8) && (cat == 14) && (subcat == 193)) {
       if (lenTime > 0) {
-         mallocSprintf (name, "Ozone%02d", lenTime);
-         mallocSprintf (comment, "%d hr Average Ozone Concentration "
-                        "[PPB]", lenTime);
+         if (timeRangeUnit == 3) {
+            mallocSprintf (name, "Ozone%02dm", lenTime);
+            mallocSprintf (comment, "%d mon Average Ozone Concentration", lenTime);
+         } else if (timeRangeUnit == 4) {
+            mallocSprintf (name, "Ozone%02dy", lenTime);
+            mallocSprintf (comment, "%d yr Average Ozone Concentration", lenTime);
+         } else {
+            mallocSprintf (name, "Ozone%02d", lenTime);
+            mallocSprintf (comment, "%d hr Average Ozone Concentration", lenTime);
+         }
       } else {
          *name = (char *) malloc (strlen ("AVGOZCON") + 1);
          strcpy (*name, "AVGOZCON");
-         *comment =
-               (char *) malloc (strlen ("Average Ozone Concentration [PPB]") +
-                                1);
-         strcpy (*comment, "Average Ozone Concentration [PPB]");
+         *comment = (char *) malloc (strlen ("Average Ozone Concentration") +
+                                     1);
+         strcpy (*comment, "Average Ozone Concentration");
       }
       *unit = (char *) malloc (strlen ("[PPB]") + 1);
       strcpy (*unit, "[PPB]");
       *convert = UC_NONE;
       return;
    }
+   /* Check for over-ride case for smokec / smokes. */
+   if (center == 7) {
+      if ((prodType == 0) && (cat == 13) && (subcat == 195)) {
+         /* If NCEP/ARL (genID=6) then it is dust */
+         if (genID == 6) {
+            if (f_fstValue && f_sndValue) {
+               delt = static_cast<float>(fstSurfValue - sndSurfValue);
+               if ((delt <= 100) && (delt >= -100)) {
+                  *name = (char *) malloc (strlen ("dusts") + 1);
+                  strcpy (*name, "dusts");
+                  *comment = (char *) malloc (strlen ("Surface level dust") + 1);
+                  strcpy (*comment, "Surface level dust");
+                  *unit = (char *) malloc (strlen ("[log10(µg/m^3)]") + 1);
+                  strcpy (*unit, "[log10(µg/m^3)]");
+                  *convert = UC_LOG10;
+                  return;
+               } else if ((delt <= 5000) && (delt >= -5000)) {
+                  *name = (char *) malloc (strlen ("dustc") + 1);
+                  strcpy (*name, "dustc");
+                  *comment = (char *) malloc (strlen ("Average vertical column dust") + 1);
+                  strcpy (*comment, "Average vertical column dust");
+                  *unit = (char *) malloc (strlen ("[log10(µg/m^3)]") + 1);
+                  strcpy (*unit, "[log10(µg/m^3)]");
+                  *convert = UC_LOG10;
+                  return;
+               }
+            }
+         } else {
+            if (f_fstValue && f_sndValue) {
+               delt = static_cast<float>(fstSurfValue - sndSurfValue);
+               if ((delt <= 100) && (delt >= -100)) {
+                  *name = (char *) malloc (strlen ("smokes") + 1);
+                  strcpy (*name, "smokes");
+                  *comment = (char *) malloc (strlen ("Surface level smoke from fires") + 1);
+                  strcpy (*comment, "Surface level smoke from fires");
+                  *unit = (char *) malloc (strlen ("[log10(µg/m^3)]") + 1);
+                  strcpy (*unit, "[log10(µg/m^3)]");
+                  *convert = UC_LOG10;
+                  return;
+               } else if ((delt <= 5000) && (delt >= -5000)) {
+                  *name = (char *) malloc (strlen ("smokec") + 1);
+                  strcpy (*name, "smokec");
+                  *comment = (char *) malloc (strlen ("Average vertical column smoke from fires") + 1);
+                  strcpy (*comment, "Average vertical column smoke from fires");
+                  *unit = (char *) malloc (strlen ("[log10(µg/m^3)]") + 1);
+                  strcpy (*unit, "[log10(µg/m^3)]");
+                  *convert = UC_LOG10;
+                  return;
+               }
+            }
+         }
+      }
+   }
 
    /* Generic tables. */
    table = Choose_GRIB2ParmTable (prodType, cat, &tableLen);
    if (table != NULL) {
       if (subcat < tableLen) {
          /* Check for NDFD over-rides. */
-         if (IsData_NDFD (center, subcenter) ||
-             IsData_MOS (center, subcenter)) {
+         if (IsData_MOS (center, subcenter)) {
+            if (strcmp (table[subcat].name, "APCP") == 0) {
+               if (timeRangeUnit == 3) {
+                  mallocSprintf (name, "%s%02dm", "QPF", lenTime);
+                  mallocSprintf (comment, "%02d mon %s", lenTime,
+                                 table[subcat].comment);
+               } else if (timeRangeUnit == 4) {
+                  mallocSprintf (name, "%s%02dy", "QPF", lenTime);
+                  mallocSprintf (comment, "%02d yr %s", lenTime,
+                                 table[subcat].comment);
+               } else {
+                  mallocSprintf (name, "%s%02d", "QPF", lenTime);
+                  mallocSprintf (comment, "%02d hr %s", lenTime,
+                                 table[subcat].comment);
+               }
+               mallocSprintf (unit, "[%s]", table[subcat].unit);
+               *convert = table[subcat].convert;
+               return;
+            }
+            if (strcmp (table[subcat].name, "ASNOW") == 0) {
+               if (timeRangeUnit == 3) {
+                  mallocSprintf (name, "%s%02dm", "SnowAmt", lenTime);
+                  mallocSprintf (comment, "%02d mon %s", lenTime,
+                                 table[subcat].comment);
+               } else if (timeRangeUnit == 4) {
+                  mallocSprintf (name, "%s%02dy", "SnowAmt", lenTime);
+                  mallocSprintf (comment, "%02d yr %s", lenTime,
+                                 table[subcat].comment);
+               } else {
+                  mallocSprintf (name, "%s%02d", "SnowAmt", lenTime);
+                  mallocSprintf (comment, "%02d hr %s", lenTime,
+                                 table[subcat].comment);
+               }
+               mallocSprintf (unit, "[%s]", table[subcat].unit);
+               *convert = table[subcat].convert;
+               return;
+            }
+         }
+         if (IsData_NDFD (center, subcenter) || IsData_MOS (center, subcenter)) {
             for (i = 0; i < (sizeof (NDFD_Overide) /
                              sizeof (NDFD_AbrevOverideTable)); i++) {
                if (strcmp (NDFD_Overide[i].GRIB2name, table[subcat].name) ==
                    0) {
-                  *name =
-                        (char *) malloc (strlen (NDFD_Overide[i].NDFDname) +
-                                         1);
+                  *name = (char *) malloc (strlen (NDFD_Overide[i].NDFDname) + 1);
                   strcpy (*name, NDFD_Overide[i].NDFDname);
-                  mallocSprintf (comment, "%s [%s]", table[subcat].comment,
-                                 table[subcat].unit);
+                  *comment = (char *) malloc (strlen (table[subcat].comment) + 1);
+                  strcpy (*comment, table[subcat].comment);
                   mallocSprintf (unit, "[%s]", table[subcat].unit);
                   *convert = table[subcat].convert;
                   return;
                }
             }
          }
-         /* Allow hydrologic PoP, thunderstorm probability (TSTM), or APCP to 
+         /* Allow hydrologic PoP, thunderstorm probability (TSTM), or APCP to
           * have lenTime labels. */
          f_accum = (((prodType == 1) && (cat == 1) && (subcat == 2)) ||
                     ((prodType == 0) && (cat == 19) && (subcat == 2)) ||
                     ((prodType == 0) && (cat == 1) && (subcat == 8)) ||
                     ((prodType == 0) && (cat == 19) && (subcat == 203)));
          if (f_accum && (lenTime > 0)) {
-            mallocSprintf (name, "%s%02d", table[subcat].name, lenTime);
-            mallocSprintf (comment, "%02d hr %s [%s]", lenTime,
-                           table[subcat].comment, table[subcat].unit);
+            if (timeRangeUnit == 3) {
+               mallocSprintf (name, "%s%02dm", table[subcat].name, lenTime);
+               mallocSprintf (comment, "%02d mon %s", lenTime,
+                              table[subcat].comment);
+            } else if (timeRangeUnit == 4) {
+               mallocSprintf (name, "%s%02dy", table[subcat].name, lenTime);
+               mallocSprintf (comment, "%02d yr %s", lenTime,
+                              table[subcat].comment);
+            } else {
+               mallocSprintf (name, "%s%02d", table[subcat].name, lenTime);
+               mallocSprintf (comment, "%02d hr %s", lenTime,
+                              table[subcat].comment);
+            }
          } else {
             *name = (char *) malloc (strlen (table[subcat].name) + 1);
             strcpy (*name, table[subcat].name);
-            mallocSprintf (comment, "%s [%s]", table[subcat].comment,
-                           table[subcat].unit);
+            *comment = (char *) malloc (strlen (table[subcat].comment) + 1);
+            strcpy (*comment, table[subcat].comment);
          }
          mallocSprintf (unit, "[%s]", table[subcat].unit);
          *convert = table[subcat].convert;
@@ -1841,18 +2863,28 @@ static void ElemNameNorm (uShort2 center, uShort2 subcenter, int prodType,
       for (i = 0; i < tableLen; i++) {
          if ((prodType == local[i].prodType) && (cat == local[i].cat) &&
              (subcat == local[i].subcat)) {
-            /* Allow specific products with non-zero lenTime to reflect that. 
+            /* Allow specific products with non-zero lenTime to reflect that.
              */
             f_accum = 0;
             if (f_accum && (lenTime > 0)) {
-               mallocSprintf (name, "%s%02d", local[i].name, lenTime);
-               mallocSprintf (comment, "%02d hr %s [%s]", lenTime,
-                              local[i].comment, local[i].unit);
+               if (timeRangeUnit == 3) {
+                  mallocSprintf (name, "%s%02dm", local[i].name, lenTime);
+                  mallocSprintf (comment, "%02d mon %s", lenTime,
+                                 local[i].comment);
+               } else if (timeRangeUnit == 4) {
+                  mallocSprintf (name, "%s%02dy", local[i].name, lenTime);
+                  mallocSprintf (comment, "%02d yr %s", lenTime,
+                                 local[i].comment);
+               } else {
+                  mallocSprintf (name, "%s%02d", local[i].name, lenTime);
+                  mallocSprintf (comment, "%02d hr %s", lenTime,
+                                 local[i].comment);
+               }
             } else {
                *name = (char *) malloc (strlen (local[i].name) + 1);
                strcpy (*name, local[i].name);
-               mallocSprintf (comment, "%s [%s]", local[i].comment,
-                              local[i].unit);
+               *comment = (char *) malloc (strlen (local[i].comment) + 1);
+               strcpy (*comment, local[i].comment);
             }
             mallocSprintf (unit, "[%s]", local[i].unit);
             *convert = local[i].convert;
@@ -1873,27 +2905,48 @@ static void ElemNameNorm (uShort2 center, uShort2 subcenter, int prodType,
 
 void ParseElemName (uShort2 center, uShort2 subcenter, int prodType,
                     int templat, int cat, int subcat, sInt4 lenTime,
+                    uChar timeRangeUnit,
                     uChar timeIncrType, uChar genID, uChar probType,
                     double lowerProb, double upperProb, char **name,
                     char **comment, char **unit, int *convert,
-                    sChar percentile)
+                    sChar percentile, uChar genProcess,
+                    sChar f_fstValue, double fstSurfValue,
+                    sChar f_sndValue, double sndSurfValue)
 {
+   char f_isNdfd = IsData_NDFD (center, subcenter);
    myAssert (*name == NULL);
    myAssert (*comment == NULL);
    myAssert (*unit == NULL);
 
    /* Check if this is Probability data */
    if ((templat == GS4_PROBABIL_TIME) || (templat == GS4_PROBABIL_PNT)) {
-      ElemNameProb (center, subcenter, prodType, templat, cat, subcat,
-                    lenTime, timeIncrType, genID, probType, lowerProb,
-                    upperProb, name, comment, unit, convert);
-   } else if (templat == GS4_PERCENTILE) {
+      if (f_isNdfd && (prodType == 0) && (cat == 19)) {
+         /* don't use ElemNameProb. */
+         ElemNameNorm (center, subcenter, prodType, templat, cat, subcat,
+                       lenTime, timeRangeUnit, timeIncrType, genID, probType, lowerProb,
+                       upperProb, name, comment, unit, convert, f_fstValue, fstSurfValue,
+                       f_sndValue, sndSurfValue);
+
+      } else {
+         ElemNameProb (center, subcenter, prodType, templat, cat, subcat,
+                       lenTime, timeRangeUnit, timeIncrType, genID, probType, lowerProb,
+                       upperProb, name, comment, unit, convert);
+      }
+   } else if ((templat == GS4_PERCENT_TIME) || (templat == GS4_PERCENT_PNT)) {
       ElemNamePerc (center, subcenter, prodType, templat, cat, subcat,
-                    lenTime, percentile, name, comment, unit, convert);
+                    lenTime, timeRangeUnit, percentile, name, comment, unit, convert);
    } else {
       ElemNameNorm (center, subcenter, prodType, templat, cat, subcat,
-                    lenTime, timeIncrType, genID, probType, lowerProb,
-                    upperProb, name, comment, unit, convert);
+                    lenTime, timeRangeUnit, timeIncrType, genID, probType, lowerProb,
+                    upperProb, name, comment, unit, convert, f_fstValue, fstSurfValue,
+                       f_sndValue, sndSurfValue);
+   }
+   if ((genProcess == 6) || (genProcess == 7)) {
+      *convert = UC_NONE;
+      reallocSprintf (name, "ERR");
+      reallocSprintf (comment, " error %s", *unit);
+   } else {
+      reallocSprintf (comment, " %s", *unit);
    }
 }
 
@@ -2120,7 +3173,7 @@ int ComputeUnit (int convert, char *origName, sChar f_unit, double *unitM,
       case UC_InchWater: /* Convert from kg/(m^2) to inches water. */
          if (f_unit == 1) {
             strcpy (name, "[inch]");
-            /* 
+            /*
              * kg/m**2 / density of water (1000 kg/m**3)
              * 1/1000 m * 1/2.54 in/cm * 100 cm/m = 1/25.4 inches
              */
@@ -2146,6 +3199,14 @@ int ComputeUnit (int convert, char *origName, sChar f_unit, double *unitM,
             return 0;
          }
          break;
+      case UC_M2StatuteMile: /* Convert from meters to statute miles. */
+         if (f_unit == 1) {
+            strcpy (name, "[statute mile]");
+            *unitM = 1. / 1609.344; /* mile / m */
+            *unitB = 0;
+            return 0;
+         }
+         break;
          /* NCEP goes with a convention of 1 nm = 1853.248 m.
           * http://www.sizes.com/units/mile_USnautical.htm Shows that on
           * 7/1/1954 US Department of Commerce switched to 1 nm = 1852 m
@@ -2158,6 +3219,14 @@ int ComputeUnit (int convert, char *origName, sChar f_unit, double *unitM,
             return 0;
          }
          break;
+      case UC_UVIndex: /* multiply by Watts/ m**2 by 40 for the UV index. */
+         if (f_unit == 1) {
+            strcpy (name, "[UVI]");
+            *unitM = 40;
+            *unitB = 0;
+            return 0;
+         }
+         break;
       case UC_LOG10:   /* convert from log10 (x) to x */
          if ((f_unit == 1) || (f_unit == 2)) {
             origName[strlen (origName) - 2] = '\0';
diff --git a/frmts/grib/degrib18/degrib/metaname.h b/frmts/grib/degrib18/degrib/metaname.h
index f341765..3b1794f 100644
--- a/frmts/grib/degrib18/degrib/metaname.h
+++ b/frmts/grib/degrib18/degrib/metaname.h
@@ -17,10 +17,14 @@ const char *processLookup(unsigned short int center, unsigned char process);
 
 void ParseElemName (unsigned short int center, unsigned short int subcenter,
                     int prodType, int templat, int cat, int subcat,
-                    sInt4 lenTime, uChar timeIncrType, uChar genID,
+                    sInt4 lenTime,
+                    uChar timeRangeUnit,
+                    uChar timeIncrType, uChar genID,
                     uChar probType, double lowerProb, double upperProb,
                     char **name, char **comment, char **unit, int *convert,
-                    sChar percentile);
+                    sChar percentile, uChar genProcess,
+                    sChar f_fstValue, double fstSurfValue,
+                    sChar f_sndValue, double sndSurfValue);
 
 int ComputeUnit (int convert, char * origName, sChar f_unit, double *unitM,
                  double *unitB, char *name);
diff --git a/frmts/grib/degrib18/degrib/metaparse.cpp b/frmts/grib/degrib18/degrib/metaparse.cpp
index c420696..75b05c8 100644
--- a/frmts/grib/degrib18/degrib/metaparse.cpp
+++ b/frmts/grib/degrib18/degrib/metaparse.cpp
@@ -989,7 +989,7 @@ static int ParseSect3 (sInt4 *is3, sInt4 ns3, grib_MetaData *meta)
    }
    if (meta->gds.scan != GRIB2BIT_2) {
 #ifdef DEBUG
-      printf ("Scan mode is expected to be 0100 (i.e. %d) not %d\n",
+      printf ("Scan mode is expected to be 0100 (i.e. %d) not %u\n",
               GRIB2BIT_2, meta->gds.scan);
       printf ("The merged GRIB2 Library should return it in 0100\n");
       printf ("The merged library swaps both NCEP and MDL data to scan "
@@ -1166,7 +1166,8 @@ static int ParseSect4 (sInt4 *is4, sInt4 ns4, grib_MetaData *meta)
        (is4[7] != GS4_DERIVED) && (is4[7] != GS4_PROBABIL_PNT) &&
        (is4[7] != GS4_STATISTIC) && (is4[7] != GS4_PROBABIL_TIME) &&
        (is4[7] != GS4_PERCENTILE) && (is4[7] != GS4_ENSEMBLE_STAT) &&
-       (is4[7] != GS4_SATELLITE) && (is4[7] != GS4_DERIVED_INTERVAL)) {
+       (is4[7] != GS4_SATELLITE) && (is4[7] != GS4_DERIVED_INTERVAL) &&
+       (is4[7] != GS4_STATISTIC_SPATIAL_AREA)) {
 #ifdef DEBUG
       printf ("Un-supported Template. %d\n", is4[7]);
 #endif
@@ -1175,7 +1176,7 @@ static int ParseSect4 (sInt4 *is4, sInt4 ns4, grib_MetaData *meta)
    }
    meta->pds2.sect4.templat = (unsigned short int) is4[7];
 
-   /* 
+   /*
     * Handle variables common to the supported templates.
     */
    if (ns4 < 34) {
@@ -1564,6 +1565,12 @@ static int ParseSect4 (sInt4 *is4, sInt4 ns4, grib_MetaData *meta)
             meta->pds2.sect4.Interval[i].timeIncr = (uChar) is4[67 + i * 12];
          }
          break;
+      case GS4_STATISTIC_SPATIAL_AREA: /* 4.15 */
+            // TODO. Need to fetch
+            // 35 Statistical process used within the spatial area defined by octet 36 (see Code Table 4.10)
+            // 36 Type of spatial processing used to arrive at given data value from source data (see Code Table 4.15)
+            // 37 Number of data points used in spatial processing defined in octet 36
+            break;
       default:
          errSprintf ("Un-supported Template. %ld\n", is4[7]);
          return -4;
@@ -1725,6 +1732,16 @@ int MetaParse (grib_MetaData *meta, sInt4 *is0, sInt4 ns0,
    double upperProb;    /* The upper limit on probability forecast if
                          * template 4.5 or 4.9 */
    sInt4 lenTime;       /* Length of time for element (see 4.8 and 4.9) */
+   uChar timeRangeUnit = 1;
+   uChar incrType;
+   uChar fstSurfType;   /* Type of the first fixed surface. */
+   sInt4 value;         /* The scaled value from GRIB2 file. */
+   sChar scale;         /* Surface scale as opposed to probility factor. */
+   double fstSurfValue; /* Value of first fixed surface. */
+   sChar f_fstValue;    /* flag if FstValue is valid. */
+   uChar sndSurfType;   /* Type of the second fixed surface. */
+   double sndSurfValue; /* Value of second fixed surface. */
+   sChar f_sndValue;    /* flag if SndValue is valid. */
 
    if ((ierr = ParseSect0 (is0, ns0, grib_len, meta)) != 0) {
       preErrSprintf ("Parse error Section 0\n");
@@ -1823,22 +1840,54 @@ int MetaParse (grib_MetaData *meta, sInt4 *is0, sInt4 ns0,
       if (lenTime == GRIB2MISSING_s4) {
          lenTime = 0;
       }
-      ParseElemName (meta->center, meta->subcenter,
-                     meta->pds2.prodType, meta->pds2.sect4.templat,
-                     meta->pds2.sect4.cat, meta->pds2.sect4.subcat,
-                     lenTime, meta->pds2.sect4.Interval[0].incrType,
-                     meta->pds2.sect4.genID, probType, lowerProb,
-                     upperProb, &(meta->element), &(meta->comment),
-                     &(meta->unitName), &(meta->convert),
-                     meta->pds2.sect4.percentile);
+      incrType = meta->pds2.sect4.Interval[0].incrType;
+   } else {
+      lenTime = 0;
+      timeRangeUnit = 1;
+      incrType = 255;
+   }
+
+   if ((meta->pds2.sect4.templat == GS4_RADAR) || (meta->pds2.sect4.templat == GS4_SATELLITE)
+       || (meta->pds2.sect4.templat == 254) || (meta->pds2.sect4.templat == 1000) || (meta->pds2.sect4.templat == 1001)
+       || (meta->pds2.sect4.templat == 1002)) {
+      fstSurfValue = 0;
+      f_fstValue = 0;
+      fstSurfType = 0;
+      sndSurfValue = 0;
+      f_sndValue = 0;
    } else {
-      ParseElemName (meta->center, meta->subcenter,
-                     meta->pds2.prodType, meta->pds2.sect4.templat,
-                     meta->pds2.sect4.cat, meta->pds2.sect4.subcat, 0, 255,
-                     meta->pds2.sect4.genID, probType, lowerProb, upperProb,
-                     &(meta->element), &(meta->comment), &(meta->unitName),
-                     &(meta->convert), meta->pds2.sect4.percentile);
+      fstSurfType = meta->pds2.sect4.fstSurfType;
+      scale = meta->pds2.sect4.fstSurfScale;
+      value = static_cast<int>(meta->pds2.sect4.fstSurfValue);
+      if ((value == GRIB2MISSING_s4) || (scale == GRIB2MISSING_s1) ||
+          (fstSurfType == GRIB2MISSING_u1)) {
+         fstSurfValue = 0;
+         f_fstValue = 1;
+      } else {
+         fstSurfValue = value * pow (10.0, -1 * scale);
+         f_fstValue = 1;
+      }
+      sndSurfType = meta->pds2.sect4.sndSurfType;
+      scale = meta->pds2.sect4.sndSurfScale;
+      value = static_cast<int>(meta->pds2.sect4.sndSurfValue);
+      if ((value == GRIB2MISSING_s4) || (scale == GRIB2MISSING_s1) ||
+          (sndSurfType == GRIB2MISSING_u1)) {
+         sndSurfValue = 0;
+         f_sndValue = 0;
+      } else {
+         sndSurfValue = value * pow (10.0, -1 * scale);
+         f_sndValue = 1;
+      }
    }
+
+   ParseElemName (meta->center, meta->subcenter, meta->pds2.prodType,
+                  meta->pds2.sect4.templat, meta->pds2.sect4.cat,
+                  meta->pds2.sect4.subcat, lenTime, timeRangeUnit, incrType,
+                  meta->pds2.sect4.genID, probType, lowerProb, upperProb,
+                  &(meta->element), &(meta->comment), &(meta->unitName),
+                  &(meta->convert), meta->pds2.sect4.percentile,
+                  meta->pds2.sect4.genProcess,
+                  f_fstValue, fstSurfValue, f_sndValue, sndSurfValue);
 #ifdef DEBUG
 /*
    printf ("Element: %s\nunitName: %s\ncomment: %s\n", meta->element,
@@ -1846,66 +1895,13 @@ int MetaParse (grib_MetaData *meta, sInt4 *is0, sInt4 ns0,
 */
 #endif
 
-/*
-   if (strcmp (element, "") == 0) {
-      meta->element = (char *) realloc ((void *) (meta->element),
-                                        (1 + strlen ("unknown")) *
-                                        sizeof (char));
-      strcpy (meta->element, "unknown");
-   } else {
-      if (IsData_MOS (meta->pds2.center, meta->pds2.subcenter)) {
-         * See : http://www.nco.ncep.noaa.gov/pmb/docs/on388/tablea.html *
-         if (meta->pds2.sect4.genID == 96) {
-            meta->element = (char *) realloc ((void *) (meta->element),
-                                              (1 + 7 + strlen (element)) *
-                                              sizeof (char));
-            sprintf (meta->element, "MOSGFS-%s", element);
-         } else {
-            meta->element = (char *) realloc ((void *) (meta->element),
-                                              (1 + 4 + strlen (element)) *
-                                              sizeof (char));
-            sprintf (meta->element, "MOS-%s", element);
-         }
-      } else {
-         meta->element = (char *) realloc ((void *) (meta->element),
-                                           (1 + strlen (element)) *
-                                           sizeof (char));
-         strcpy (meta->element, element);
-      }
-   }
-   meta->unitName = (char *) realloc ((void *) (meta->unitName),
-                                      (1 + 2 + strlen (unitName)) *
-                                      sizeof (char));
-   sprintf (meta->unitName, "[%s]", unitName);
-   meta->comment = (char *) realloc ((void *) (meta->comment),
-                                     (1 + strlen (comment) +
-                                      strlen (unitName)
-                                      + 2 + 1) * sizeof (char));
-   sprintf (meta->comment, "%s [%s]", comment, unitName);
-*/
-   if ((meta->pds2.sect4.sndSurfScale == GRIB2MISSING_s1) ||
-       (meta->pds2.sect4.sndSurfType == GRIB2MISSING_u1)) {
-/*
-      if ((meta->pds2.sect4.fstSurfScale == GRIB2MISSING_s1) ||
-          (meta->pds2.sect4.fstSurfType == GRIB2MISSING_u1)) {
-         ParseLevelName (meta->center, meta->subcenter,
-                         meta->pds2.sect4.fstSurfType, 0, 0, 0,
-                         &(meta->shortFstLevel), &(meta->longFstLevel));
-      } else {
-*/
-         ParseLevelName (meta->center, meta->subcenter,
-                         meta->pds2.sect4.fstSurfType,
-                         meta->pds2.sect4.fstSurfValue, 0, 0,
-                         &(meta->shortFstLevel), &(meta->longFstLevel));
-/*
-      }
-*/
+   if (! f_fstValue) {
+      reallocSprintf (&(meta->shortFstLevel), "0 undefined");
+      reallocSprintf (&(meta->longFstLevel), "0.000[-] undefined ()");
    } else {
-      ParseLevelName (meta->center, meta->subcenter,
-                      meta->pds2.sect4.fstSurfType,
-                      meta->pds2.sect4.fstSurfValue, 1,
-                      meta->pds2.sect4.sndSurfValue, &(meta->shortFstLevel),
-                      &(meta->longFstLevel));
+      ParseLevelName (meta->center, meta->subcenter, fstSurfType,
+                      fstSurfValue, f_sndValue, sndSurfValue,
+                      &(meta->shortFstLevel), &(meta->longFstLevel));
    }
 
    /* Continue parsing section 2 data. */
@@ -2156,7 +2152,7 @@ static void ParseGridPrimMiss (gridAttribType *attrib, double *grib_Data,
                         if (WxType->ugly[index].f_valid) {
                            WxType->ugly[index].f_valid = 2;
                         } else {
-                           /* Table is not valid here so set value to missPri 
+                           /* Table is not valid here so set value to missPri
                             */
                            value = attrib->missPri;
                            (*missCnt)++;
@@ -2284,7 +2280,7 @@ static void ParseGridSecMiss (gridAttribType *attrib, double *grib_Data,
                         if (WxType->ugly[index].f_valid) {
                            WxType->ugly[index].f_valid = 2;
                         } else {
-                           /* Table is not valid here so set value to missPri 
+                           /* Table is not valid here so set value to missPri
                             */
                            value = attrib->missPri;
                            (*missCnt)++;
@@ -2383,7 +2379,8 @@ void ParseGrid (gridAttribType *attrib, double **Grib_Data,
    sInt4 x, y;          /* Where we are in a grid of scan value 0100 */
    sInt4 newIndex;      /* x,y in a 1 dimensional array. */
    double value;        /* The data in the new units. */
-   double *grib_Data;   /* A pointer to Grib_Data for ease of manipulation. */
+   /* A pointer to Grib_Data for ease of manipulation. */
+   double *grib_Data = NULL;
    sInt4 missCnt = 0;   /* Number of detected missing values. */
    uInt4 index;         /* Current index into Wx table. */
    float *ain = (float *) iain;
@@ -2431,7 +2428,7 @@ void ParseGrid (gridAttribType *attrib, double **Grib_Data,
          } else {
             value = ain[scanIndex];
          }
-         /* Make sure value is not a missing value when converting units, and 
+         /* Make sure value is not a missing value when converting units, and
           * while computing max/min. */
          if ((attrib->f_miss == 0) ||
              ((attrib->f_miss == 1) && (value != attrib->missPri)) ||
@@ -2601,7 +2598,7 @@ void FreqPrint (char **ans, double *Data, sInt4 DataLen, sInt4 Nx,
                 sInt4 Ny, sChar decimal, char *comment)
 {
    int x, y, i;
-   double *ptr;
+   double *ptr = NULL;
    double value;
    freqType *freq = NULL;
    int numFreq = 0;
diff --git a/frmts/grib/degrib18/degrib/metaprint.cpp b/frmts/grib/degrib18/degrib/metaprint.cpp
index 89ebd25..c4937d1 100644
--- a/frmts/grib/degrib18/degrib/metaprint.cpp
+++ b/frmts/grib/degrib18/degrib/metaprint.cpp
@@ -57,6 +57,7 @@
  * Instead do sizeof(table) in calling procedure.
  *****************************************************************************
  */
+#if 0  // Unused with GDAL.
 static const char *Lookup(const char * const *table, size_t n, size_t index)
 {
    static const char * const def[] =
@@ -71,6 +72,7 @@ static const char *Lookup(const char * const *table, size_t n, size_t index)
       return def[2];
    }
 }
+#endif
 
 /*****************************************************************************
  * Print() --
@@ -116,7 +118,7 @@ static const char *Lookup(const char * const *table, size_t n, size_t index)
  * Using enumerated type instead of "ds" "dss" etc.  For speed considerations.
  *****************************************************************************
  */
-char *Print(const char *label, const char *varName, Prt_TYPE fmt, ...)
+char *Print(const char *label, const char *varName, int fmt, ...)
 {
    static char *buffer = NULL; /* Copy of message generated so far. */
    va_list ap;          /* pointer to variable argument list. */
@@ -197,6 +199,7 @@ char *Print(const char *label, const char *varName, Prt_TYPE fmt, ...)
    return NULL;
 }
 
+#if 0  // Unused with GDAL.
 /*****************************************************************************
  * PrintSect1() --
  *
@@ -828,7 +831,7 @@ static int PrintSect4 (grib_MetaData *meta, sChar f_unit)
                 sect4->upperLimit.value *
                 pow (10.0, -1 * sect4->upperLimit.factor), buffer);
          /* Intentionally fall through. */
-         // CPL_FALLTHROUGH
+         CPL_FALLTHROUGH
       case GS4_STATISTIC:
 /*         strftime (buffer, 100, "%m/%d/%Y %H:%M:%S UTC",
                    gmtime (&(sect4->validTime)));*/
@@ -1412,3 +1415,4 @@ int MetaPrint (grib_MetaData *meta, char **ans, sChar decimal, sChar f_unit)
    *ans = Print (NULL, NULL, Prt_NULL);
    return 0;
 }
+#endif  // Unused with GDAL.
diff --git a/frmts/grib/degrib18/degrib/myassert.h b/frmts/grib/degrib18/degrib/myassert.h
index 5157b49..789daa7 100644
--- a/frmts/grib/degrib18/degrib/myassert.h
+++ b/frmts/grib/degrib18/degrib/myassert.h
@@ -32,7 +32,6 @@
 #define DEGRIB_NO_RETURN
 #endif
 
-
 CPL_C_START
    void _myAssert (const char *file, int lineNum) DEGRIB_NO_RETURN;
 CPL_C_END
diff --git a/frmts/grib/degrib18/degrib/myerror.c b/frmts/grib/degrib18/degrib/myerror.c
index 02af990..df297b0 100644
--- a/frmts/grib/degrib18/degrib/myerror.c
+++ b/frmts/grib/degrib18/degrib/myerror.c
@@ -168,7 +168,7 @@ static void AllocSprintf (char **Ptr, size_t *LenBuff, const char *fmt,
                   case 'L':
                      sprintf (bufpart, format, va_arg (ap, sInt4));
                      break;
-                     /* 
+                     /*
                       * gcc warning for 'h': "..." promotes short int to
                       * int.  Could get rid of 'h' option but decided to
                       * leave it in since we might have a different
diff --git a/frmts/grib/degrib18/degrib/myutil.c b/frmts/grib/degrib18/degrib/myutil.c
index 17d9a1a..1df6d73 100644
--- a/frmts/grib/degrib18/degrib/myutil.c
+++ b/frmts/grib/degrib18/degrib/myutil.c
@@ -12,7 +12,20 @@
  */
 
 /* For S_IFDIR */
+#if defined(__sun__) && __STDC_VERSION__ >= 201112L
+#if _XOPEN_SOURCE < 600
+#ifdef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE
+#endif
+#define _XOPEN_SOURCE 600
+#endif
+#else
+#ifdef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE
+#endif
 #define _XOPEN_SOURCE 500
+#endif
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <ctype.h>
@@ -75,6 +88,7 @@
  *     same as fgets except it can expand as needed.
  *****************************************************************************
  */
+#if 0  // Unused with GDAL.
 #define MIN_STEPSIZE 80
 size_t reallocFGets (char **Ptr, size_t *LenBuff, FILE *fp)
 {
@@ -111,6 +125,7 @@ size_t reallocFGets (char **Ptr, size_t *LenBuff, FILE *fp)
 }
 
 #undef MIN_STEPSIZE
+#endif
 
 /*****************************************************************************
  * mySplit() --
@@ -136,6 +151,8 @@ size_t reallocFGets (char **Ptr, size_t *LenBuff, FILE *fp)
  * NOTES
  *****************************************************************************
  */
+
+#if 0  // Unused with GDAL.
 void mySplit (const char *data, char symbol, size_t *Argc, char ***Argv,
               char f_trim)
 {
@@ -163,7 +180,7 @@ void mySplit (const char *data, char symbol, size_t *Argc, char ***Argv,
          }
          argc++;
          head = ptr + 1;
-         /* The following head != NULL is in case data is not '\0' terminated 
+         /* The following head != NULL is in case data is not '\0' terminated
           */
          if ((head != NULL) && (*head == '\0')) {
             /* Handle a break character just before the \0 */
@@ -185,7 +202,9 @@ void mySplit (const char *data, char symbol, size_t *Argc, char ***Argv,
    *Argc = argc;
    *Argv = argv;
 }
+#endif
 
+#if 0  // Unused with GDAL.
 int myAtoI (const char *ptr, sInt4 *value)
 {
    char *extra = NULL;         /* The data after the end of the double. */
@@ -228,6 +247,7 @@ int myAtoI (const char *ptr, sInt4 *value)
    }
    return 1;
 }
+#endif
 
 /*****************************************************************************
  * myAtoF() -- used to be myIsReal()
@@ -254,6 +274,8 @@ int myAtoI (const char *ptr, sInt4 *value)
  * NOTES
  *****************************************************************************
  */
+
+#if 0  // Unused with GDAL.
 int myAtoF (const char *ptr, double *value)
 {
    char *extra = NULL;         /* The data after the end of the double. */
@@ -296,7 +318,9 @@ int myAtoF (const char *ptr, double *value)
    }
    return 1;
 }
+#endif
 
+#if 0  // Unused with GDAL.
 /* Change of name was to deprecate usage... Switch to myAtoF */
 int myIsReal_old (const char *ptr, double *value)
 {
@@ -324,6 +348,7 @@ int myIsReal_old (const char *ptr, double *value)
    *value = atof (ptr);
    return 1;
 }
+#endif
 
 /* Return:
  * 0 if 'can't stat the file' (most likely not a file)
@@ -339,6 +364,7 @@ int myIsReal_old (const char *ptr, double *value)
  * Could return mode: RDCF___rwxrwxrwx where R is 1/0 based on regular file
  * D is 1/0 based on directory, first rwx is user permissions...
  */
+#if 0  // Unused with GDAL.
 int myStat (char *filename, char *perm, sInt4 *size, double *mtime)
 {
    struct stat stbuf;
@@ -424,8 +450,9 @@ int myStat (char *filename, char *perm, sInt4 *size, double *mtime)
       return 3;
    }
 }
+#endif
 
-/** 
+/**
 static int FileMatch (const char *filename, const char *filter)
 {
    const char *ptr1;
@@ -458,6 +485,7 @@ static int FileMatch (const char *filename, const char *filter)
 }
 **/
 
+#if 0  // Unused with GDAL.
 int myGlob (CPL_UNUSED const char *dirName,
             CPL_UNUSED const char *filter,
             CPL_UNUSED size_t *Argc,
@@ -494,6 +522,7 @@ return 0; // TODO: reimplement for Win32
    return 0;
 */
 }
+#endif
 
 /*****************************************************************************
  * FileCopy() --
@@ -519,6 +548,7 @@ return 0; // TODO: reimplement for Win32
  * NOTES
  *****************************************************************************
  */
+#if 0  // Unused with GDAL.
 int FileCopy (const char *fileIn, const char *fileOut)
 {
    FILE *ifp;           /* The file pointer to read from. */
@@ -545,6 +575,7 @@ int FileCopy (const char *fileIn, const char *fileOut)
    fclose (ofp);
    return 0;
 }
+#endif
 
 /*****************************************************************************
  * FileTail() --
@@ -567,6 +598,8 @@ int FileCopy (const char *fileIn, const char *fileOut)
  * NOTES
  *****************************************************************************
  */
+
+#if 0  // Unused with GDAL.
 void FileTail (const char *fileName, char **tail)
 {
    const char *ptr;     /* A pointer to last \ or // in fileName. */
@@ -588,6 +621,7 @@ void FileTail (const char *fileName, char **tail)
    *tail = (char *) malloc (strlen (ptr) + 1);
    strcpy (*tail, ptr);
 }
+#endif
 
 /*****************************************************************************
  * myRound() --
@@ -670,7 +704,14 @@ void strTrim (char *str)
 
    /* Remove the trailing white space before working on the leading ones. */
    len = strlen (str);
-   for (i = len - 1; (/* (i >= 0) && */ (isspace ((unsigned char)str[i]))); i--) {
+   if (len == 0) {
+       return;
+   }
+   for (i = len - 1; i > 0 && isspace ((unsigned char)str[i]); i--) {
+   }
+   if (i == 0 && str[i] == ' ') {
+       str[0] = '\0';
+       return;
    }
    len = i + 1;
    str[len] = '\0';
@@ -711,15 +752,19 @@ void strTrim (char *str)
 void strTrimRight (char *str, char c)
 {
    size_t i;            /* loop counter for traversing str. */
+   const size_t len = str == NULL ? 0 : strlen(str);
 
    /* str shouldn't be null, but if it is, we want to handle it. */
    myAssert (str != NULL);
-   if (str == NULL) {
+   if (len == 0) {
       return;
    }
 
    for (i = strlen (str) - 1;
-        (/* (i >= 0) && */ ((isspace ((unsigned char)str[i])) || (str[i] == c))); i--) {
+        i > 0 && (isspace ((unsigned char)str[i]) || str[i] == c); i--) {
+   }
+   if (i == 0 && (isspace ((unsigned char)str[i]) || str[i] == c)) {
+     str[i] = '\0';
    }
    str[i + 1] = '\0';
 }
@@ -785,6 +830,7 @@ void strCompact (char *str, char c)
  * NOTES
  *****************************************************************************
  */
+#if 0  // Unused with GDAL.
 void strReplace (char *str, char c1, char c2)
 {
    char *ptr = str;
@@ -801,6 +847,7 @@ void strReplace (char *str, char c1, char c2)
       }
    }
 }
+#endif
 
 /*****************************************************************************
  * strToUpper() --
@@ -821,6 +868,7 @@ void strReplace (char *str, char c1, char c2)
  * NOTES
  *****************************************************************************
  */
+#if 0  // Unused with GDAL.
 void strToUpper (char *str)
 {
    char *ptr = str;     /* Used to traverse str. */
@@ -834,6 +882,7 @@ void strToUpper (char *str)
    while ((*ptr++ = toupper (*str++)) != '\0') {
    }
 }
+#endif
 
 /*****************************************************************************
  * strToLower() --
@@ -854,6 +903,7 @@ void strToUpper (char *str)
  * NOTES
  *****************************************************************************
  */
+#if 0  // Unused with GDAL.
 void strToLower (char *str)
 {
    char *ptr = str;     /* Used to traverse str. */
@@ -867,6 +917,7 @@ void strToLower (char *str)
    while ((*ptr++ = tolower (*str++)) != '\0') {
    }
 }
+#endif
 
 /*
  * Returns: Length of the string.
@@ -906,6 +957,7 @@ int str2lw (char *s) {
  *   See K&R p 106
  *****************************************************************************
  */
+#if 0  // Unused with GDAL.
 int strcmpNoCase (const char *str1, const char *str2)
 {
    /* str1, str2 shouldn't be null, but if it is, we want to handle it. */
@@ -948,6 +1000,7 @@ int strcmpNoCase (const char *str1, const char *str2)
    return 0;
 */
 }
+#endif
 
  /*****************************************************************************
  * GetIndexFromStr() -- Review 12/2002
@@ -955,7 +1008,7 @@ int strcmpNoCase (const char *str1, const char *str2)
  * Arthur Taylor / MDL
  *
  * PURPOSE
- *   Looks through a list of strings (with a NULL value at the end) for a
+ *   Looks through a list of strings (with a NUL value at the end) for a
  * given string.  Returns the index where it found it.
  *
  * ARGUMENTS
@@ -975,7 +1028,7 @@ int strcmpNoCase (const char *str1, const char *str2)
  *   Why not const char **Opt?
  *****************************************************************************
  */
-int GetIndexFromStr (const char *str, char **Opt, int *Index)
+int GetIndexFromStr (const char *str, const char * const *Opt, int *Index)
 {
    int cnt = 0;         /* Current Count in Opt. */
 
@@ -1018,6 +1071,7 @@ int GetIndexFromStr (const char *str, char **Opt, int *Index)
  * NOTES
  *****************************************************************************
  */
+#if 0  // Unused with GDAL.
 static sChar Clock_GetTimeZone ()
 {
    struct tm l_time;
@@ -1039,6 +1093,7 @@ static sChar Clock_GetTimeZone ()
    }
    return timeZone;
 }
+#endif
 
 /*****************************************************************************
  * myParseTime() --
@@ -1067,6 +1122,7 @@ static sChar Clock_GetTimeZone ()
  *   Use: int Clock_ScanDateNumber (double *clock, char *buffer) instead.
  *****************************************************************************
  */
+#if 0  // Unused with GDAL.
 int myParseTime3 (const char *is, time_t * AnsTime)
 {
    char buffer[5];      /* A temporary variable for parsing "is". */
@@ -1113,6 +1169,7 @@ int myParseTime3 (const char *is, time_t * AnsTime)
    *AnsTime = mktime (&l_time) - (Clock_GetTimeZone () * 3600);
    return 0;
 }
+#endif
 
 #ifdef MYUTIL_TEST
 int main (int argc, char **argv)
diff --git a/frmts/grib/degrib18/degrib/myutil.h b/frmts/grib/degrib18/degrib/myutil.h
index af773e2..4fab173 100644
--- a/frmts/grib/degrib18/degrib/myutil.h
+++ b/frmts/grib/degrib18/degrib/myutil.h
@@ -21,6 +21,7 @@ extern "C" {
 #include <time.h>
 #include "type.h"
 
+#if 0  // Unused with GDAL.
 size_t reallocFGets (char **Ptr, size_t *LenBuff, FILE * fp);
 
 void mySplit (const char *data, char symbol, size_t *Argc, char ***Argv,
@@ -42,6 +43,7 @@ int myGlob (const char *dirName, const char *filter, size_t * Argc,
 int FileCopy (const char *fileIn, const char *fileOut);
 
 void FileTail (const char *fileName, char **tail);
+#endif  // Unused with GDAL.
 
 double myRound (double data, uChar place);
 
@@ -51,6 +53,7 @@ void strTrimRight (char *str, char c);
 
 void strCompact (char *str, char c);
 
+#if 0  // Unused with GDAL.
 void strReplace (char *str, char c1, char c2);
 
 void strToUpper (char *str);
@@ -58,12 +61,15 @@ void strToUpper (char *str);
 void strToLower (char *str);
 
 int strcmpNoCase (const char *str1, const char *str2);
+#endif  // Unused with GDAL.
 
-int GetIndexFromStr (const char *str, char **Opt, int *Index);
+int GetIndexFromStr (const char *str, const char * const *Opt, int *Index);
 
+#if 0  // Unused with GDAL.
 /* Rename because changed error return from -1 to 1 */
 /* Rename because trying to phase it out. */
 int myParseTime3 (const char *is, time_t * AnsTime);
+#endif  // Unused with GDAL.
 
 #ifdef __cplusplus
 }
diff --git a/frmts/grib/degrib18/degrib/scan.c b/frmts/grib/degrib18/degrib/scan.c
index e94e1d6..8b1ff38 100644
--- a/frmts/grib/degrib18/degrib/scan.c
+++ b/frmts/grib/degrib18/degrib/scan.c
@@ -242,7 +242,7 @@ int main (int argc, char **argv)
       for (x = 0; x < NxNy; x++) {
          printf ("%d ", ray1[x]);
          ScanIndex2XY (x, &x1, &y1, scan, Nx, Ny);
-         /* 
+         /*
           * To get scan 0000 do the following:
           * row = x1 + ((Ny-1) - y1) * Nx;
           */
diff --git a/frmts/grib/degrib18/degrib/tdlpack.cpp b/frmts/grib/degrib18/degrib/tdlpack.cpp
index 3a81930..a552e8a 100644
--- a/frmts/grib/degrib18/degrib/tdlpack.cpp
+++ b/frmts/grib/degrib18/degrib/tdlpack.cpp
@@ -90,7 +90,7 @@ typedef struct {
                          * group. However, the # of bits for a number can't
                          * be > 64, and is probably < 32, so bit is < 6 and
                          * probably < 5. */
-   uInt4 num;           /* number of values in the group. May need this to be 
+   uInt4 num;           /* number of values in the group. May need this to be
                          * signed. */
    sInt4 max;           /* Max value for the group */
    uInt4 start;         /* index in Data where group starts. */
@@ -529,7 +529,7 @@ int TDLP_Inventory (DataSource &fp, sInt4 tdlpLen, inventoryType *inv)
        return -1;
    }
    pds = (uChar *) malloc (sectLen * sizeof (uChar));
-   if( pds == NULL ) 
+   if( pds == NULL )
    {
       errSprintf ("Ran out of memory in PDS (TDLP_Inventory)\n");
       return -1;
@@ -1086,8 +1086,8 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
 #ifdef DEBUG
    printf ("nbit %d, ibit %d, jbit %d, kbit %d\n", nbit, ibit, jbit, kbit);
    if ((t_numBytes + ceil (t_numBits / 8.)) != sectLen) {
-      printf ("Caution: # bytes in groups %d (%d + %d / 8) != "
-              "sectLen %d\n", (sInt4) (t_numBytes + ceil (t_numBits / 8.)),
+      printf ("Caution: # bytes in groups %d (%u + %u / 8) != "
+              "sectLen %u\n", (sInt4) (t_numBytes + ceil (t_numBits / 8.)),
               t_numBytes, t_numBits, sectLen);
    }
 #endif
@@ -1188,16 +1188,16 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
                f_missing = 0;
                if (li_temp == maxVal) {
                   data[dataInd] = meta->gridAttrib.missPri;
-                  /* In the case of grp[i].bit == 0, if grp[i].min == 0, then 
+                  /* In the case of grp[i].bit == 0, if grp[i].min == 0, then
                    * it is the missing value, otherwise regular value. Only
                    * need to be concerned for primary missing values. */
                   f_missing = 1;
                   if ((grp[i].bit == 0) && (grp[i].min != 0)) {
 #ifdef DEBUG
                      printf ("This doesn't happen often.\n");
-                     printf ("%d %d %d\n", (int) i, grp[i].bit, grp[i].min);
+                     printf ("%d %u %d\n", (int) i, grp[i].bit, grp[i].min);
 #endif
-                     myAssert (1 == 2);
+                     myAssert (0);
                      f_missing = 0;
                   }
                }
@@ -1387,15 +1387,15 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
                f_missing = 0;
                if (li_temp == maxVal) {
                   data[dataInd] = meta->gridAttrib.missPri;
-                  /* In the case of grp[i].bit == 0, if grp[i].min == 0, then 
+                  /* In the case of grp[i].bit == 0, if grp[i].min == 0, then
                    * it is the missing value, otherwise regular value. Only
                    * need to be concerned for primary missing values. */
                   f_missing = 1;
                   if ((grp[i].bit == 0) && (grp[i].min != 0)) {
 #ifdef DEBUG
                      printf ("This doesn't happen often.\n");
-                     printf ("%d %d %d\n", (int) i, grp[i].bit, grp[i].min);
-                     myAssert (1 == 2);
+                     printf ("%d %u %d\n", (int) i, grp[i].bit, grp[i].min);
+                     myAssert (0);
 #endif
                      f_missing = 0;
                   }
@@ -1453,7 +1453,7 @@ static int ReadTDLPSect4 (uChar *bds, sInt4 tdlpLen, sInt4 *curLoc,
       }
    }
    meta->gridAttrib.numMiss = dataCnt - numVal;
-   meta->gridAttrib.refVal = minVal * scale;
+   meta->gridAttrib.refVal = (float)(minVal * scale);
 
    free (grp);
    return 0;
@@ -3217,7 +3217,9 @@ static int splitGroup (sInt4 *Data, int numData, TDLGroupType * group,
    if (f_secMiss) {
       /* 11 = primMiss 10 = secMiss 01, 00 = data. */
       minBit = 2;
-   } else if (f_primMiss) {
+   }
+   // cppcheck-suppress duplicateBranch
+   else if (f_primMiss) {
       /* 1 = primMiss 0 = data. */
       /* might try minBit = 1 here. */
       minBit = 1;
@@ -3248,7 +3250,7 @@ static int splitGroup (sInt4 *Data, int numData, TDLGroupType * group,
             if (scoreB < scoreA) {
                f_keep = 1;
             } else if (numSubGroup > 2) {
-               /* We can do "doSplitLeft" (which is breaking it into 2 groups 
+               /* We can do "doSplitLeft" (which is breaking it into 2 groups
                 * the first having range n - 1, the second having range n,
                 * using what we know from doSplit. */
                subGroup[1].num = group[i].num - subGroup[0].num;
@@ -3621,10 +3623,10 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
                Data[i] -= OverallMin;
                // Check if we accidentally adjusted to prim or sec, if so add 1.
                if ((Data[i] == li_secMiss) || (Data[i] == li_primMiss)) {
-                  myAssert (1 == 2);
+                  myAssert (0);
                   Data[i]++;
                   if ((Data[i] == li_secMiss) || (Data[i] == li_primMiss)) {
-                     myAssert (1 == 2);
+                     myAssert (0);
                      Data[i]++;
                   }
                }
@@ -3636,7 +3638,7 @@ static void GroupIt (sInt4 OverallMin, sInt4 *Data, size_t numData,
                Data[i] -= OverallMin;
                // Check if we accidentally adjusted to prim or sec, if so add 1.
                if (Data[i] == li_primMiss) {
-                  myAssert (1 == 2);
+                  myAssert (0);
                   Data[i]++;
                }
             }
@@ -4080,7 +4082,7 @@ int WriteTDLPRecord (FILE * fp, double *Data, sInt4 DataLen, int DSF,
    char f_simple = 0;   /* Simple Pack flag: not implemented in specs. */
    int gridType;        /* Which type of grid. (Polar, Mercator, Lambert). */
    int dataCnt;         /* Keeps track of which element we are writing. */
-   sInt4 max0;          /* The max value in a group.  Represents primary or * 
+   sInt4 max0;          /* The max value in a group.  Represents primary or *
                          * secondary missing value depending on scheme. */
    sInt4 max1;          /* The next to max value in a group.  Represents *
                          * secondary missing value. */
diff --git a/frmts/grib/degrib18/degrib/tdlpack.h b/frmts/grib/degrib18/degrib/tdlpack.h
index fa8994b..c21fedb 100644
--- a/frmts/grib/degrib18/degrib/tdlpack.h
+++ b/frmts/grib/degrib18/degrib/tdlpack.h
@@ -17,7 +17,6 @@ typedef struct {
    const char *data;
 } TDLP_TableType;
 
-
 int TDLP_Inventory (DataSource &fp, sInt4 tdlpLen, inventoryType * inv);
 int TDLP_RefTime (DataSource &fp, sInt4 tdlpLen, double * refTime);
 int ReadTDLPRecord (DataSource &fp, double **TDLP_Data, uInt4 *tdlp_DataLen,
diff --git a/frmts/grib/degrib18/degrib/type.h b/frmts/grib/degrib18/degrib/type.h
index fe09160..ad7e707 100644
--- a/frmts/grib/degrib18/degrib/type.h
+++ b/frmts/grib/degrib18/degrib/type.h
@@ -16,20 +16,15 @@
 #ifndef SINT4_TYPE
  #define SINT4_TYPE
 /*   #ifdef _64Bit
- *   typedef of sInt4 and uInt4 determination now moved to config.h  
+ *   typedef of sInt4 and uInt4 determination now moved to config.h
  *    A D T Aug 26, 2006
  *   Moved back to here with assumption that SIZEOF_LONG_INT is set
  *    by makefile.
  *    AATaylor 9/20/2006
  */
 
-#if SIZEOF_LONG_INT != 4
   typedef signed int sInt4;
   typedef unsigned int uInt4;
- #else
-  typedef signed long int sInt4;
-  typedef unsigned long int uInt4;
- #endif
  typedef unsigned char uChar;
  typedef signed char sChar;
  typedef unsigned short int uShort2;
diff --git a/frmts/grib/degrib18/degrib/weather.c b/frmts/grib/degrib18/degrib/weather.c
index b8f8555..e981445 100644
--- a/frmts/grib/degrib18/degrib/weather.c
+++ b/frmts/grib/degrib18/degrib/weather.c
@@ -550,7 +550,7 @@ static int NDFD_WxTable1 (UglyStringType * ugly)
             }
          }
       case WX_T:
-         /* 
+         /*
           * Check Severe storms.  If so, this is most important weather
           * type.
           */
@@ -1025,7 +1025,7 @@ static int NDFD_WxTable2 (UglyStringType * ugly)
             }
          }
       case WX_T:
-         /* 
+         /*
           * Check Severe storms.  If so, this is most important weather
           * type.
           */
@@ -2303,7 +2303,7 @@ static void Ugly2English (UglyStringType * ugly)
             }
          }
       }
-      /* Hazard is now smallest number first... we now convert from "00 00 00 
+      /* Hazard is now smallest number first... we now convert from "00 00 00
        * 04 05" to 405 */
       ugly->HazCode[i] = 0;
       for (j = 0; j < NUM_UGLY_ATTRIB; j++) {
@@ -2477,7 +2477,7 @@ int ParseUglyString (UglyStringType * ugly, char *wxData, int simpleVer)
       }
 */
    }
-   if (start != '\0') {
+   if (start != NULL) {
       if (UglyLookUp (ugly, start, word, place, attNum) != 0) {
 #ifdef VERBOSE
          printf ("(E) '%s'\n", wxData);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/README b/frmts/grib/degrib18/g2clib-1.0.4/README
index 86fdf92..fc1bd7f 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/README
+++ b/frmts/grib/degrib18/g2clib-1.0.4/README
@@ -23,7 +23,7 @@ if they are not already installed on your system.
 
 If you do not wish to bother with the external libs and
 don't need PNG and JPEG2000 support, you can remove the
--DUSE_PNG and -DUSE_JPEG2000 flags from the DEFS variable 
+-DUSE_PNG and -DUSE_JPEG2000 flags from the DEFS variable
 in the makefile.
 
 
@@ -31,16 +31,16 @@ in the makefile.
 
      External Libraries:
 
-libjasper.a - This library is a C implementation of the JPEG-2000 Part-1 
+libjasper.a - This library is a C implementation of the JPEG-2000 Part-1
               standard (i.e., ISO/IEC 15444-1).  This library is required
               if JPEG2000 support in GRIB2 is desired.  If not, remove
-              the -DUSE_JPEG2000 option from the DEFS variable 
+              the -DUSE_JPEG2000 option from the DEFS variable
               in the makefile.
 
               Download version jasper-1.700.2 from the JasPer Project's
               home page, http://www.ece.uvic.ca/~mdadams/jasper/.
-        
-              More information about JPEG2000 can be found at 
+
+              More information about JPEG2000 can be found at
               http://www.jpeg.org/JPEG2000.html.
 
 libpng.a      This library is a C implementation of the Portable Network
@@ -49,19 +49,19 @@ libpng.a      This library is a C implementation of the Portable Network
               the -DUSE_PNG option from the DEFS variable
               in the makefile.
 
-              If not already installed on your system, download version 
+              If not already installed on your system, download version
               libpng-1.2.5 from http://www.libpng.org/pub/png/libpng.html.
 
-              More information about PNG can be found at 
+              More information about PNG can be found at
               http://www.libpng.org/pub/png/.
 
 libz.a        This library contains compression/decompression routines
-              used by libpng.a for PNG image compression support. 
-              This library is required if PNG support in GRIB2 is desired.  
+              used by libpng.a for PNG image compression support.
+              This library is required if PNG support in GRIB2 is desired.
               If not, remove the -DUSE_PNG option from the DEFS variable
               in g2lib/makefile.
 
-              If not already installed on your system, download version 
+              If not already installed on your system, download version
               zlib-1.1.4 from http://www.gzip.org/zlib/.
 
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c b/frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c
index bed4d8f..27d3f3c 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/cmplxpack.c
@@ -11,7 +11,7 @@ void cmplxpack(g2float *fld,g2int ndpts, g2int idrsnum,g2int *idrstmpl,
 //   packing algorithm as defined in the GRIB2 documentation.  It
 //   supports GRIB2 complex packing templates with or without
 //   spatial differences (i.e. DRTs 5.2 and 5.3).
-//   It also fills in GRIB2 Data Representation Template 5.2 or 5.3 
+//   It also fills in GRIB2 Data Representation Template 5.2 or 5.3
 //   with the appropriate values.
 //
 // PROGRAM HISTORY LOG:
@@ -40,7 +40,7 @@ void cmplxpack(g2float *fld,g2int ndpts, g2int idrsnum,g2int *idrstmpl,
 //                    .
 //                    .
 //
-//   OUTPUT ARGUMENT LIST: 
+//   OUTPUT ARGUMENT LIST:
 //     idrstmpl - Contains the array of values for Data Representation
 //                Template 5.3
 //                [0] = Reference value - set by compack routine.
@@ -59,7 +59,7 @@ void cmplxpack(g2float *fld,g2int ndpts, g2int idrsnum,g2int *idrstmpl,
 //
 //$$$
 {
-      
+
 
       if ( idrstmpl[6] == 0 ) {       // No internal missing values
          compack(fld,ndpts,idrsnum,idrstmpl,cpack,lcpack);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/compack.c b/frmts/grib/degrib18/g2clib-1.0.4/compack.c
index bdd0340..c92acfc 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/compack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/compack.c
@@ -14,7 +14,7 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //   packing algorithm as defined in the GRIB2 documentation.  It
 //   supports GRIB2 complex packing templates with or without
 //   spatial differences (i.e. DRTs 5.2 and 5.3).
-//   It also fills in GRIB2 Data Representation Template 5.2 or 5.3 
+//   It also fills in GRIB2 Data Representation Template 5.2 or 5.3
 //   with the appropriate values.
 //
 // PROGRAM HISTORY LOG:
@@ -44,7 +44,7 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //                    .
 //                    .
 //
-//   OUTPUT ARGUMENTS: 
+//   OUTPUT ARGUMENTS:
 //     idrstmpl - Contains the array of values for Data Representation
 //                Template 5.3
 //                [0] = Reference value - set by compack routine.
@@ -77,11 +77,11 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
       g2int  missopt, miss1, miss2, ier;
       g2float  bscale,dscale,rmax,rmin,temp;
       const g2int simple_alg = 0;
-      const g2float alog2=0.69314718;       //  ln(2.0)
+      const g2float alog2=0.69314718f;       //  ln(2.0)
       const g2int one=1;
 
-      bscale=int_power(2.0,-idrstmpl[1]);
-      dscale=int_power(10.0,idrstmpl[2]);
+      bscale=(float)int_power(2.0,-idrstmpl[1]);
+      dscale=(float)int_power(10.0,idrstmpl[2]);
 //
 //  Find max and min values in the data
 //
@@ -111,13 +111,13 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            imin=(g2int)RINT(rmin*dscale);
            //imax=(g2int)rint(rmax*dscale);
            rmin=(g2float)imin;
-           for (j=0;j<ndpts;j++) 
+           for (j=0;j<ndpts;j++)
               ifld[j]=(g2int)RINT(fld[j]*dscale)-imin;
         }
         else {                             //  Use binary scaling factor
            rmin=rmin*dscale;
            //rmax=rmax*dscale;
-           for (j=0;j<ndpts;j++) 
+           for (j=0;j<ndpts;j++)
              ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale);
         }
         //
@@ -127,14 +127,14 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            if (idrstmpl[16]!=1 && idrstmpl[16]!=2) idrstmpl[16]=1;
            if (idrstmpl[16] == 1) {      // first order
               ival1=ifld[0];
-              for (j=ndpts-1;j>0;j--) 
+              for (j=ndpts-1;j>0;j--)
                  ifld[j]=ifld[j]-ifld[j-1];
               ifld[0]=0;
            }
            else if (idrstmpl[16] == 2) {      // second order
               ival1=ifld[0];
               ival2=ifld[1];
-              for (j=ndpts-1;j>1;j--) 
+              for (j=ndpts-1;j>1;j--)
                  ifld[j]=ifld[j]-(2*ifld[j-1])+ifld[j-2];
               ifld[0]=0;
               ifld[1]=0;
@@ -150,7 +150,7 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            //   find num of bits need to store minsd and add 1 extra bit
            //   to indicate sign
            //
-           temp=log((double)(abs(minsd)+1))/alog2;
+           temp=(float)(log((double)(abs(minsd)+1))/alog2);
            nbitsd=(g2int)ceil(temp)+1;
            //
            //   find num of bits need to store ifld[0] ( and ifld[1]
@@ -158,7 +158,7 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            //
            maxorig=ival1;
            if (idrstmpl[16]==2 && ival2>ival1) maxorig=ival2;
-           temp=log((double)(maxorig+1))/alog2;
+           temp=(float)(log((double)(maxorig+1))/alog2);
            nbitorig=(g2int)ceil(temp)+1;
            if (nbitorig > nbitsd) nbitsd=nbitorig;
            //   increase number of bits to even multiple of 8 ( octet )
@@ -243,7 +243,7 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            free(jmax);
            free(lbit);
         }
-        //  
+        //
         //  For each group, find the group's reference value
         //  and the number of bits needed to hold the remaining values
         //
@@ -254,16 +254,16 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            imax=ifld[n];
            j=n+1;
            for (lg=1;lg<glen[ng];lg++) {
-              if (ifld[j] < gref[ng]) gref[ng]=ifld[j]; 
+              if (ifld[j] < gref[ng]) gref[ng]=ifld[j];
               if (ifld[j] > imax) imax=ifld[j];
               j++;
            }
            //   calc num of bits needed to hold data
            if ( gref[ng] != imax ) {
-              temp=log((double)(imax-gref[ng]+1))/alog2;
+              temp=(float)(log((double)(imax-gref[ng]+1))/alog2);
               gwidth[ng]=(g2int)ceil(temp);
            }
-           else 
+           else
               gwidth[ng]=0;
            //   Subtract min from data
            j=n;
@@ -274,15 +274,15 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            //   increment fld array counter
            n=n+glen[ng];
         }
-        //  
-        //  Find max of the group references and calc num of bits needed 
+        //
+        //  Find max of the group references and calc num of bits needed
         //  to pack each groups reference value, then
         //  pack up group reference values
         //
         igmax=gref[0];
         for (j=1;j<ngroups;j++) if (gref[j] > igmax) igmax=gref[j];
         if (igmax != 0) {
-           temp=log((double)(igmax+1))/alog2;
+           temp=(float)(log((double)(igmax+1))/alog2);
            nbitsgref=(g2int)ceil(temp);
            sbits(cpack,gref,iofst,nbitsgref,0,ngroups);
            itemp=nbitsgref*ngroups;
@@ -308,9 +308,9 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            if (gwidth[j] < ngwidthref) ngwidthref=gwidth[j];
         }
         if (iwmax != ngwidthref) {
-           temp=log((double)(iwmax-ngwidthref+1))/alog2;
+           temp=(float)(log((double)(iwmax-ngwidthref+1))/alog2);
            nbitsgwidth=(g2int)ceil(temp);
-           for (i=0;i<ngroups;i++) 
+           for (i=0;i<ngroups;i++)
               gwidth[i]=gwidth[i]-ngwidthref;
            sbits(cpack,gwidth,iofst,nbitsgwidth,0,ngroups);
            itemp=nbitsgwidth*ngroups;
@@ -340,7 +340,7 @@ void compack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
         }
         nglenlast=glen[ngroups-1];
         if (ilmax != nglenref) {
-           temp=log((double)(ilmax-nglenref+1))/alog2;
+           temp=(float)(log((double)(ilmax-nglenref+1))/alog2);
            nbitsglen=(g2int)ceil(temp);
            for (i=0;i<ngroups-1;i++)  glen[i]=glen[i]-nglenref;
            sbits(cpack,glen,iofst,nbitsglen,0,ngroups);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/comunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/comunpack.c
index 40f5321..6015f27 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/comunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/comunpack.c
@@ -41,17 +41,17 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE: 
+//   MACHINE:
 //
 //$$$//
 {
 
-      g2int   nbitsd=0,isign;
-      g2int  j,iofst,ival1,ival2,minsd,itemp,l,k,n,non=0;
-      g2int  *ifld,*ifldmiss=0;
-      g2int  *gref,*gwidth,*glen;
-      g2int  itype,ngroups,nbitsgref,nbitsgwidth,nbitsglen;
-      g2int  msng1,msng2;
+      g2int nbitsd=0,isign;
+      g2int j,iofst,ival1,ival2,minsd,itemp,l,k,n,non=0;
+      g2int *ifld=NULL,*ifldmiss=NULL;
+      g2int *gref=NULL,*gwidth=NULL,*glen=NULL;
+      g2int itype,ngroups,nbitsgref,nbitsgwidth,nbitsglen;
+      g2int msng1,msng2;
       g2float ref,bscale,dscale,rmiss1,rmiss2;
       g2int totBit, totLen;
 
@@ -86,9 +86,9 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
 //  Get missing values, if supplied
 //
       if ( idrstmpl[6] == 1 ) {
-         if (itype == 0) 
+         if (itype == 0)
             rdieee(idrstmpl+7,&rmiss1,1);
-         else 
+         else
             rmiss1=(g2float)idrstmpl[7];
       }
       if ( idrstmpl[6] == 2 ) {
@@ -101,9 +101,9 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
             rmiss2=(g2float)idrstmpl[8];
          }
       }
-      
+
       //printf("RMISSs: %f %f %f \n",rmiss1,rmiss2,ref);
-// 
+//
 //  Extract spatial differencing values, if using DRS Template 5.3
 //
       if (idrsnum == 3) {
@@ -164,7 +164,7 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
 
       for (j=0;j<ngroups;j++)
           gwidth[j]=gwidth[j]+idrstmpl[10];
-      
+
 //
 //  Extract Each Group's length (number of values in each group)
 //
@@ -181,7 +181,7 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
          for (j=0;j<ngroups;j++)
               glen[j]=0;
       }
-      for (j=0;j<ngroups;j++) 
+      for (j=0;j<ngroups;j++)
            glen[j]=(glen[j]*idrstmpl[13])+idrstmpl[12];
       glen[ngroups-1]=idrstmpl[14];
 //
@@ -194,10 +194,11 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
         totBit += (gwidth[j]*glen[j]);
         totLen += glen[j];
       }
-      if (totLen != ndpts) {
-        return 1;
-      }
-      if (totBit / 8. > lensec) {
+      if (totLen != ndpts || totBit / 8. > lensec) {
+        free(ifld);
+        free(gwidth);
+        free(glen);
+        free(gref);
         return 1;
       }
 //
@@ -315,9 +316,9 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
                fld[n]=(((g2float)ifld[non++]*bscale)+ref)*dscale;
                //printf(" SAG %d %f %d %f %f %f\n",n,fld[n],ifld[non-1],bscale,ref,dscale);
             }
-            else if ( ifldmiss[n] == 1 ) 
+            else if ( ifldmiss[n] == 1 )
                fld[n]=rmiss1;
-            else if ( ifldmiss[n] == 2 ) 
+            else if ( ifldmiss[n] == 2 )
                fld[n]=rmiss2;
          }
          if ( ifldmiss != 0 ) free(ifldmiss);
@@ -326,5 +327,5 @@ int comunpack(unsigned char *cpack,g2int lensec,g2int idrsnum,g2int *idrstmpl,g2
       if ( ifld != 0 ) free(ifld);
 
       return(0);
-      
+
 }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp b/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp
index 0f32c59..3dfca90 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp
+++ b/frmts/grib/degrib18/g2clib-1.0.4/dec_jpeg2000.cpp
@@ -1,43 +1,25 @@
 #include <cpl_port.h>
 
-#include "grib2.h"
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-/* -------------------------------------------------------------------- */
-/* ==================================================================== */
-/*      We prefer to use JasPer directly if it is available.  If not    */
-/*      we fallback on calling back to GDAL to try and process the      */
-/*      jpeg2000 chunks.                                                */
-/* ==================================================================== */
-/* -------------------------------------------------------------------- */
-
-#ifdef HAVE_JASPER
-#include <jasper/jasper.h>
-#define JAS_1_700_2
-#else
 #include <gdal_pam.h>
 #include <cpl_conv.h>
-#endif
 
 CPL_C_START
-// Should this go in an include file?  Otherwise it should be static, correct?
-int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld);
+#include "grib2.h"
 CPL_C_END
 
-int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
+int dec_jpeg2000(const void *injpc,g2int bufsize,g2int *outfld,g2int outpixels)
 /*$$$  SUBPROGRAM DOCUMENTATION BLOCK
 *                .      .    .                                       .
 * SUBPROGRAM:    dec_jpeg2000      Decodes JPEG2000 code stream
 *   PRGMMR: Gilbert          ORG: W/NP11     DATE: 2002-12-02
 *
 * ABSTRACT: This Function decodes a JPEG2000 code stream specified in the
-*   JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1) using JasPer
-*   Software version 1.500.4 (or 1.700.2) written by the University of British
-*   Columbia and Image Power Inc, and others.
-*   JasPer is available at http://www.ece.uvic.ca/~mdadams/jasper/.
+*   JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1) using a GDAL JPEG2000
+*   capable driver.
 *
 * PROGRAM HISTORY LOG:
 * 2002-12-02  Gilbert
@@ -56,11 +38,7 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
 *         -3 = Error decode jpeg2000 code stream.
 *         -5 = decoded image had multiple color components.
 *              Only grayscale is expected.
-*
-* REMARKS:
-*
-*      Requires JasPer Software version 1.500.4 or 1.700.2
-*
+
 * ATTRIBUTES:
 *   LANGUAGE: C
 *   MACHINE:  IBM SP
@@ -68,18 +46,9 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
 *$$$*/
 
 {
-#ifndef HAVE_JASPER
-    // J2K_SUBFILE method
-
     // create "memory file" from buffer
-    int fileNumber = 0;
-    VSIStatBufL   sStatBuf;
-    CPLString osFileName = "/vsimem/work.jpc";
-
-    // ensure we don't overwrite an existing file accidentally
-    while ( VSIStatL( osFileName, &sStatBuf ) == 0 ) {
-        osFileName.Printf( "/vsimem/work%d.jpc", ++fileNumber );
-    }
+    CPLString osFileName;
+    osFileName.Printf( "/vsimem/work_grib_%p.jpc", injpc );
 
     VSIFCloseL( VSIFileFromMemBuffer(
                     osFileName, (unsigned char*)injpc, bufsize,
@@ -91,20 +60,33 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
 
     if( poJ2KDataset == NULL )
     {
-        printf("dec_jpeg2000: Unable to open JPEG2000 image within GRIB file.\n"
+        fprintf(stderr, "dec_jpeg2000: Unable to open JPEG2000 image within GRIB file.\n"
                   "Is the JPEG2000 driver available?" );
+        VSIUnlink( osFileName );
         return -3;
     }
 
     if( poJ2KDataset->GetRasterCount() != 1 )
     {
-       printf("dec_jpeg2000: Found color image.  Grayscale expected.\n");
+       fprintf(stderr, "dec_jpeg2000: Found color image.  Grayscale expected.\n");
+       GDALClose( poJ2KDataset );
+       VSIUnlink( osFileName );
        return (-5);
     }
 
     // Fulfill administration: initialize parameters required for RasterIO
     const int nXSize = poJ2KDataset->GetRasterXSize();
     const int nYSize = poJ2KDataset->GetRasterYSize();
+    // Do not test strict equality, since there are cases where the image
+    // is actually smaller than the requested number of pixels
+    if( nYSize == 0 || nXSize > outpixels / nYSize )
+    {
+        fprintf(stderr, "dec_jpeg2000: Image contains %d pixels > %d.\n",
+                nXSize * nYSize, outpixels);
+       GDALClose( poJ2KDataset );
+       VSIUnlink( osFileName );
+       return (-5);
+    }
     int nXOff = 0;
     int nYOff = 0;
     int nBufXSize = nXSize;
@@ -127,67 +109,4 @@ int dec_jpeg2000(char *injpc,g2int bufsize,g2int *outfld)
     VSIUnlink( osFileName );
 
     return (eErr == CE_None) ? 0 : -3;
-
-#else
-
-    // JasPer method
-
-    g2int i,j,k;
-    jas_image_t *image=NULL;
-    jas_stream_t *jpcstream;
-    jas_image_cmpt_t *pcmpt;
-    char *opts=NULL;
-    jas_matrix_t *data;
-
-//    jas_init();
-
-//
-//     Create jas_stream_t containing input JPEG200 codestream in memory.
-//
-
-    jpcstream=jas_stream_memopen(injpc,bufsize);
-
-//
-//     Decode JPEG200 codestream into jas_image_t structure.
-//
-
-    image=jpc_decode(jpcstream,opts);
-    if ( image == NULL ) {
-       printf(" jpc_decode failed\n");
-       return -3;
-    }
-
-    pcmpt=image->cmpts_[0];
-
-//   Expecting jpeg2000 image to be grayscale only.
-//   No color components.
-//
-    if (image->numcmpts_ != 1 ) {
-       printf("dec_jpeg2000: Found color image.  Grayscale expected.\n");
-       return (-5);
-    }
-
-//
-//    Create a data matrix of grayscale image values decoded from
-//    the jpeg2000 codestream.
-//
-    data=jas_matrix_create(static_cast<int>(jas_image_height(image)), static_cast<int>(jas_image_width(image)));
-    jas_image_readcmpt(image,0,0,0,jas_image_width(image),
-                       jas_image_height(image),data);
-//
-//    Copy data matrix to output integer array.
-//
-    k=0;
-    for (i=0;i<pcmpt->height_;i++)
-      for (j=0;j<pcmpt->width_;j++)
-        outfld[k++]=static_cast<g2int>(data->rows_[i][j]);
-//
-//     Clean up JasPer work structures.
-//
-    jas_matrix_destroy(data);
-    jas_stream_close(jpcstream);
-    jas_image_destroy(image);
-
-    return 0;
-#endif
 }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/dec_png.c b/frmts/grib/degrib18/g2clib-1.0.4/dec_png.c
index 86d476a..8e50211 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/dec_png.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/dec_png.c
@@ -1,6 +1,6 @@
 #include "grib2.h"
 #ifndef USE_PNG
-int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout){return 0;}
+int dec_png(unsigned char *pngbuf,g2int len,g2int *width,g2int *height,unsigned char *cout, g2int ndpts, g2int nbits){return 0;}
 #else   /* USE_PNG */
 #include <stdio.h>
 #include <stdlib.h>
@@ -11,6 +11,7 @@ int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout){return
 struct png_stream {
    unsigned char *stream_ptr;     /*  location to write PNG stream  */
    g2int stream_len;               /*  number of bytes written       */
+   g2int stream_total_len;
 };
 typedef struct png_stream png_stream;
 
@@ -27,6 +28,13 @@ void user_read_data(png_structp png_ptr,png_bytep data, png_uint_32 length)
      png_stream *mem;
 
      mem=(png_stream *)png_get_io_ptr(png_ptr);
+     if( (g2int)length + mem->stream_len > mem->stream_total_len )
+     {
+        jmp_buf* psSetJmpContext = (jmp_buf *)png_get_error_ptr( png_ptr );
+        if (psSetJmpContext)
+            longjmp( *psSetJmpContext, 1 );
+     }
+
      ptr=(void *)mem->stream_ptr;
      offset=mem->stream_len;
 /*     printf("SAGrd %ld %ld %x\n",offset,length,ptr);  */
@@ -36,23 +44,25 @@ void user_read_data(png_structp png_ptr,png_bytep data, png_uint_32 length)
 
 
 
-int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout)
+int dec_png(unsigned char *pngbuf,g2int len,g2int *width,g2int *height,unsigned char *cout, g2int ndpts, g2int nbits)
 {
-    int interlace,color,compress,filter,bit_depth;
+    int interlace,color,l_compress,filter,bit_depth;
     g2int j,k,n,bytes,clen;
     png_structp png_ptr;
     png_infop info_ptr,end_info;
     png_bytepp row_pointers;
     png_stream read_io_ptr;
+    png_uint_32 u_width;
+    png_uint_32 u_height;
 
 /*  check if stream is a valid PNG format   */
 
-    if ( png_sig_cmp(pngbuf,0,8) != 0) 
+    if ( png_sig_cmp(pngbuf,0,8) != 0)
        return (-3);
 
 /* create and initialize png_structs  */
 
-    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, 
+    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
                                       NULL, NULL);
     if (!png_ptr)
        return (-1);
@@ -83,10 +93,11 @@ int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout)
 
     read_io_ptr.stream_ptr=(png_voidp)pngbuf;
     read_io_ptr.stream_len=0;
+    read_io_ptr.stream_total_len = len;
 
 /*    Set new custom read function    */
 
-    png_set_read_fn(png_ptr,(voidp)&read_io_ptr,(png_rw_ptr)user_read_data);
+    png_set_read_fn(png_ptr,(png_voidp)&read_io_ptr,(png_rw_ptr)user_read_data);
 /*     png_init_io(png_ptr, fptr);   */
 
 /*     Read and decode PNG stream   */
@@ -100,8 +111,27 @@ int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout)
 /*     Get image info, such as size, depth, colortype, etc...   */
 
     /*printf("SAGT:png %d %d %d\n",info_ptr->width,info_ptr->height,info_ptr->bit_depth);*/
-    (void)png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)width, (png_uint_32 *)height,
-               &bit_depth, &color, &interlace, &compress, &filter);
+    if( !png_get_IHDR(png_ptr, info_ptr, &u_width, &u_height,
+               &bit_depth, &color, &interlace, &l_compress, &filter) )
+    {
+        fprintf(stderr, "png_get_IHDR() failed\n");
+        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+        return( -4 );
+    }
+    if( u_width > 0x7FFFFFFFU || u_height > 0x7FFFFFFFU )
+    {
+        fprintf(stderr, "invalid width/height\n");
+        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+        return( -5 );
+    }
+    *width = (g2int) u_width;
+    *height = (g2int) u_height;
+    if( (*width) * (*height) != ndpts )
+    {
+        fprintf(stderr, "invalid width/height\n");
+        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+        return( -6 );
+    }
 
 /*     Check if image was grayscale      */
 
@@ -116,6 +146,12 @@ int dec_png(unsigned char *pngbuf,g2int *width,g2int *height,char *cout)
     else if ( color == PNG_COLOR_TYPE_RGB_ALPHA ) {
        bit_depth=32;
     }
+    if( bit_depth != nbits )
+    {
+        fprintf(stderr, "inconsistent PNG bit depth\n");
+        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+        return( -7 );
+    }
 /*     Copy image data to output string   */
 
     n=0;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c b/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c
index 34f2bb5..a56477a 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.c
@@ -12,7 +12,7 @@ static const struct drstemplate templatesdrs[MAXDRSTEMP] = {
          { 3, 18, 0, {4,-2,-2,1,1,1,1,4,4,4,1,1,4,1,4,1,1,1} },
              // 5.50: Spectral Data - Simple Packing
          { 50, 5, 0, {4,-2,-2,1,4} },
-             // 5.51: Spherical Harmonics data - Complex packing 
+             // 5.51: Spherical Harmonics data - Complex packing
          { 51, 10, 0, {4,-2,-2,1,-4,2,2,2,4,1} },
 //           // 5.1: Matrix values at gridpoint - Simple packing
 //         { 1, 15, 1, {4,-2,-2,1,1,1,4,2,2,1,1,1,1,1,1} },
@@ -35,10 +35,10 @@ const struct drstemplate *get_templatesdrs()
 g2int getdrsindex(g2int number)
 /*!$$$  SUBPROGRAM DOCUMENTATION BLOCK
 !                .      .    .                                       .
-! SUBPROGRAM:    getdrsindex 
+! SUBPROGRAM:    getdrsindex
 !   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2001-06-28
 !
-! ABSTRACT: This function returns the index of specified Data 
+! ABSTRACT: This function returns the index of specified Data
 !   Representation Template 5.NN (NN=number) in array templates.
 !
 ! PROGRAM HISTORY LOG:
@@ -46,7 +46,7 @@ g2int getdrsindex(g2int number)
 !
 ! USAGE:    index=getdrsindex(number)
 !   INPUT ARGUMENT LIST:
-!     number   - NN, indicating the number of the Data Representation 
+!     number   - NN, indicating the number of the Data Representation
 !                Template 5.NN that is being requested.
 !
 ! RETURNS:  Index of DRT 5.NN in array templates, if template exists.
@@ -76,10 +76,10 @@ g2int getdrsindex(g2int number)
 xxtemplate *getdrstemplate(g2int number)
 /*!$$$  SUBPROGRAM DOCUMENTATION BLOCK
 !                .      .    .                                       .
-! SUBPROGRAM:    getdrstemplate 
+! SUBPROGRAM:    getdrstemplate
 !   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-11
 !
-! ABSTRACT: This subroutine returns DRS template information for a 
+! ABSTRACT: This subroutine returns DRS template information for a
 !   specified Data Representation Template 5.NN.
 !   The number of entries in the template is returned along with a map
 !   of the number of octets occupied by each entry.  Also, a flag is
@@ -90,11 +90,11 @@ xxtemplate *getdrstemplate(g2int number)
 !
 ! USAGE:    new=getdrstemplate(number);
 !   INPUT ARGUMENT LIST:
-!     number   - NN, indicating the number of the Data Representation 
+!     number   - NN, indicating the number of the Data Representation
 !                Template 5.NN that is being requested.
 !
-!   RETURN VALUE:      
-!        - Pointer to the returned template struct. 
+!   RETURN VALUE:
+!        - Pointer to the returned template struct.
 !          Returns NULL pointer, if template not found.
 !
 ! REMARKS: None
@@ -132,12 +132,12 @@ xxtemplate *getdrstemplate(g2int number)
 xxtemplate *extdrstemplate(g2int number,g2int *list)
 /*!$$$  SUBPROGRAM DOCUMENTATION BLOCK
 !                .      .    .                                       .
-! SUBPROGRAM:    extdrstemplate 
+! SUBPROGRAM:    extdrstemplate
 !   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-11
 !
 ! ABSTRACT: This subroutine generates the remaining octet map for a
 !   given Data Representation Template, if required.  Some Templates can
-!   vary depending on data values given in an earlier part of the 
+!   vary depending on data values given in an earlier part of the
 !   Template, and it is necessary to know some of the earlier entry
 !   values to generate the full octet map of the Template.
 !
@@ -146,13 +146,13 @@ xxtemplate *extdrstemplate(g2int number,g2int *list)
 !
 ! USAGE:    new=extdrstemplate(number,list);
 !   INPUT ARGUMENT LIST:
-!     number   - NN, indicating the number of the Data Representation 
+!     number   - NN, indicating the number of the Data Representation
 !                Template 5.NN that is being requested.
-!     list()   - The list of values for each entry in the 
+!     list()   - The list of values for each entry in the
 !                the Data Representation Template 5.NN.
 !
-!   RETURN VALUE:      
-!        - Pointer to the returned template struct. 
+!   RETURN VALUE:
+!        - Pointer to the returned template struct.
 !          Returns NULL pointer, if template not found.
 !
 ! ATTRIBUTES:
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h b/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h
index f35de99..835c935 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h
+++ b/frmts/grib/degrib18/g2clib-1.0.4/drstemplates.h
@@ -4,7 +4,7 @@
 
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-26
 //
-// ABSTRACT: This Fortran Module contains info on all the available 
+// ABSTRACT: This Fortran Module contains info on all the available
 //   GRIB2 Data Representation Templates used in Section 5 (DRS).
 //   The information describing each template is stored in the
 //   drstemplate structure defined below.
@@ -12,12 +12,12 @@
 //   Each Template has three parts: The number of entries in the template
 //   (mapdrslen);  A map of the template (mapdrs), which contains the
 //   number of octets in which to pack each of the template values; and
-//   a logical value (needext) that indicates whether the Template needs 
-//   to be extended.  In some cases the number of entries in a template 
-//   can vary depending upon values specified in the "static" part of 
+//   a logical value (needext) that indicates whether the Template needs
+//   to be extended.  In some cases the number of entries in a template
+//   can vary depending upon values specified in the "static" part of
 //   the template.  ( See Template 5.1 as an example )
 //
-//   NOTE:  Array mapdrs contains the number of octets in which the 
+//   NOTE:  Array mapdrs contains the number of octets in which the
 //   corresponding template values will be stored.  A negative value in
 //   mapdrs is used to indicate that the corresponding template entry can
 //   contain negative values.  This information is used later when packing
@@ -25,9 +25,9 @@
 //   are stored with the left most bit set to one, and a negative number
 //   of octets value in mapdrs[] indicates that this possibility should
 //   be considered.  The number of octets used to store the data value
-//   in this case would be the absolute value of the negative value in 
+//   in this case would be the absolute value of the negative value in
 //   mapdrs[].
-//  
+//
 //
 ///////////////////////////////////////////////////////////////////////
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/enc_jpeg2000.c b/frmts/grib/degrib18/g2clib-1.0.4/enc_jpeg2000.c
index c6076cf..db75536 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/enc_jpeg2000.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/enc_jpeg2000.c
@@ -26,7 +26,7 @@ int enc_jpeg2000(CPL_UNUSED unsigned char *cin,
 #endif /* USE_JPEG2000_J2KSUBFILE */
 
 int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,g2int nbits,
-                 g2int ltype, g2int ratio, g2int retry, char *outjpc, 
+                 g2int ltype, g2int ratio, g2int retry, char *outjpc,
                  g2int jpclen)
 /*$$$  SUBPROGRAM DOCUMENTATION BLOCK
 *                .      .    .                                       .
@@ -34,8 +34,8 @@ int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,g2int nbits,
 *   PRGMMR: Gilbert          ORG: W/NP11     DATE: 2002-12-02
 *
 * ABSTRACT: This Function encodes a grayscale image into a JPEG2000 code stream
-*   specified in the JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1) 
-*   using JasPer Software version 1.500.4 (or 1.700.2 ) written by the 
+*   specified in the JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1)
+*   using JasPer Software version 1.500.4 (or 1.700.2 ) written by the
 *   University of British Columbia, Image Power Inc, and others.
 *   JasPer is available at http://www.ece.uvic.ca/~mdadams/jasper/.
 *
@@ -46,7 +46,7 @@ int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,g2int nbits,
 *                       JPEG2000 algorithm.
 *
 * USAGE:    int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,
-*                            g2int nbits, g2int ltype, g2int ratio, 
+*                            g2int nbits, g2int ltype, g2int ratio,
 *                            g2int retry, char *outjpc, g2int jpclen)
 *
 *   INPUT ARGUMENTS:
@@ -87,7 +87,7 @@ int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,g2int nbits,
 {
 
 #ifdef USE_JPEG2000_J2KSUBFILE
-     
+
     // J2KSUBFILE method ... TODO!!
     return 0;
 
@@ -123,17 +123,17 @@ int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,g2int nbits,
        strcat(opts,"\nnumgbits=4");
     }
     //printf("SAGopts: %s\n",opts);
-    
+
 //
 //     Initialize the JasPer image structure describing the grayscale
 //     image to encode into the JPEG2000 code stream.
 //
     image.tlx_=0;
     image.tly_=0;
-#ifdef JAS_1_500_4 
+#ifdef JAS_1_500_4
     image.brx_=(uint_fast32_t)width;
     image.bry_=(uint_fast32_t)height;
-#endif 
+#endif
 #ifdef JAS_1_700_2
     image.brx_=(jas_image_coord_t)width;
     image.bry_=(jas_image_coord_t)height;
@@ -145,7 +145,7 @@ int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,g2int nbits,
 #endif
 #ifdef JAS_1_700_2
     image.clrspc_=JAS_CLRSPC_SGRAY;         /* grayscale Image */
-    image.cmprof_=0; 
+    image.cmprof_=0;
 #endif
     image.inmem_=1;
 
@@ -191,7 +191,7 @@ int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,g2int nbits,
     }
 //
 //     Clean up JasPer work structures.
-//    
+//
     rwcnt=jpcstream->rwcnt_;
     ier=jas_stream_close(istream);
     ier=jas_stream_close(jpcstream);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/enc_png.c b/frmts/grib/degrib18/g2clib-1.0.4/enc_png.c
index 0e4afde..2e49243 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/enc_png.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/enc_png.c
@@ -43,14 +43,13 @@ void user_flush_data(png_structp png_ptr)
         Dummy Custom flush function
 */
 {
-   int *do_nothing;
-   do_nothing=NULL;
+   (void)png_ptr;
 }
 
 
 int enc_png(char *data,g2int width,g2int height,g2int nbits,char *pngbuf)
 {
- 
+
     int color_type;
     g2int j,bytes,pnglen,bit_depth;
     png_structp png_ptr;
@@ -61,7 +60,7 @@ int enc_png(char *data,g2int width,g2int height,g2int nbits,char *pngbuf)
 
 /* create and initialize png_structs  */
 
-    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, 
+    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
                                       NULL, NULL);
     if (!png_ptr)
        return (-1);
@@ -88,7 +87,7 @@ int enc_png(char *data,g2int width,g2int height,g2int nbits,char *pngbuf)
 
 /*    Set new custom write functions    */
 
-    png_set_write_fn(png_ptr,(voidp)&write_io_ptr,(png_rw_ptr)user_write_data,
+    png_set_write_fn(png_ptr,(png_voidp)&write_io_ptr,(png_rw_ptr)user_write_data,
                     (png_flush_ptr)user_flush_data);
 /*    png_init_io(png_ptr, fptr);   */
 /*    png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);  */
@@ -114,7 +113,7 @@ int enc_png(char *data,g2int width,g2int height,g2int nbits,char *pngbuf)
 
     /*bytes=bit_depth/8;*/
     bytes=nbits/8;
-    row_pointers=malloc(height*sizeof(png_bytep));
+    row_pointers=malloc(height*sizeof(png_bytep*));
     for (j=0;j<height;j++) row_pointers[j]=(png_bytep *)(data+(j*width*bytes));
     png_set_rows(png_ptr, info_ptr, (png_bytepp)row_pointers);
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c
index b02dfbe..d7d6153 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_addfield.c
@@ -20,19 +20,19 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
                 g2float *fld,g2int ngrdpts,g2int ibmap,g2int *bmap)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_addfield 
+// SUBPROGRAM:    g2_addfield
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-11-05
 //
 // ABSTRACT: This routine packs up Sections 4 through 7 for a given field
 //   and adds them to a GRIB2 message.  They are Product Definition Section,
-//   Data Representation Section, Bit-Map Section and Data Section, 
+//   Data Representation Section, Bit-Map Section and Data Section,
 //   respectively.
-//   This routine is used with routines "g2_create", "g2_addlocal", 
-//   "g2_addgrid", and "g2_gribend" to create a complete GRIB2 message.  
+//   This routine is used with routines "g2_create", "g2_addlocal",
+//   "g2_addgrid", and "g2_gribend" to create a complete GRIB2 message.
 //   g2_create must be called first to initialize a new GRIB2 message.
 //   Also, routine g2_addgrid must be called after g2_create and
 //   before this routine to add the appropriate grid description to
-//   the GRIB2 message.   Also, a call to g2_gribend is required to complete 
+//   the GRIB2 message.   Also, a call to g2_gribend is required to complete
 //   GRIB2 message after all fields have been added.
 //
 // PROGRAM HISTORY LOG:
@@ -54,7 +54,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
 //                4 through 7 should be added.
 //     ipdsnum  - Product Definition Template Number ( see Code Table 4.0)
 //     ipdstmpl - Contains the data values for the specified Product Definition
-//                Template ( N=ipdsnum ).  Each element of this integer 
+//                Template ( N=ipdsnum ).  Each element of this integer
 //                array contains an entry (in the order specified) of Product
 //                Definition Template 4.N
 //     coordlist- Array containing floating point values intended to document
@@ -63,7 +63,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
 //     numcoord - number of values in array coordlist.
 //     idrsnum  - Data Representation Template Number ( see Code Table 5.0 )
 //     idrstmpl - Contains the data values for the specified Data Representation
-//                Template ( N=idrsnum ).  Each element of this integer 
+//                Template ( N=idrsnum ).  Each element of this integer
 //                array contains an entry (in the order specified) of Data
 //                Representation Template 5.N
 //                Note that some values in this template (eg. reference
@@ -81,7 +81,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
 //                255 = Bit map does not apply to this product.
 //     bmap[]   - Integer array containing bitmap to be added. ( if ibmap=0 )
 //
-//   OUTPUT ARGUMENT LIST:      
+//   OUTPUT ARGUMENT LIST:
 //     cgrib    - Character array to contain the updated GRIB2 message.
 //                Must be allocated large enough to store the entire
 //                GRIB2 message.
@@ -108,7 +108,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 {
@@ -131,7 +131,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       g2float *pfld;
       xxtemplate  *mappds,*mapdrs;
       const unsigned int allones=4294967295u;
- 
+
 //
 //  Check to see if beginning of GRIB message exists
 //
@@ -142,11 +142,11 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       }
 //
 //  Get current length of GRIB message
-//  
+//
       gbit(cgrib,&lencurr,96,32);
 //
 //  Check to see if GRIB message is already complete
-//  
+//
       if ( cgrib[lencurr-4]==s7 && cgrib[lencurr-3]==s7 &&
            cgrib[lencurr-2]==s7 && cgrib[lencurr-1]==s7 ) {
         printf("g2_addfield: GRIB message already complete.  Cannot add new section.\n");
@@ -159,7 +159,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       issec3=0;
       isprevbmap=0;
       len=16;    // length of Section 0
-      for (;;) { 
+      for (;;) {
       //    Get number and length of next section
         iofst=len*8;
         gbit(cgrib,&ilen,iofst,32);
@@ -316,11 +316,11 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
         simpack(pfld,ndpts,idrstmpl,cpack,&lcpack);
       else if (idrsnum==2 || idrsnum==3)           //  Complex Packing
         cmplxpack(pfld,ndpts,idrsnum,idrstmpl,cpack,&lcpack);
-      else if (idrsnum == 50) {         //  Sperical Harmonic Simple Packing 
+      else if (idrsnum == 50) {         //  Sperical Harmonic Simple Packing
         simpack(pfld+1,ndpts-1,idrstmpl,cpack,&lcpack);
         mkieee(pfld+0,idrstmpl+4,1);  // ensure RE(0,0) value is IEEE format
       }
-      else if (idrsnum == 51) {         //  Sperical Harmonic Complex Packing 
+      else if (idrsnum == 51) {         //  Sperical Harmonic Complex Packing
         getpoly(cgrib+lpos3,&JJ,&KK,&MM);
         if ( JJ!=0 && KK!=0 && MM!=0 )
            specpack(pfld,ndpts,JJ,KK,MM,idrstmpl,cpack,&lcpack);
@@ -478,7 +478,7 @@ g2int g2_addfield(unsigned char *cgrib,g2int ipdsnum,g2int *ipdstmpl,
       }
       //
       //   Calculate length of section 7 and store it in octets
-      //   1-4 of section 7.  
+      //   1-4 of section 7.
       //
       lensec7=(iofst-ibeg)/8;
       sbit(cgrib,&lensec7,ibeg,32);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c
index 7fdb274..863380e 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_addgrid.c
@@ -6,10 +6,10 @@
 g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflist,g2int idefnum)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_addgrid 
+// SUBPROGRAM:    g2_addgrid
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-11-01
 //
-// ABSTRACT: This routine packs up a Grid Definition Section (Section 3) 
+// ABSTRACT: This routine packs up a Grid Definition Section (Section 3)
 //   and adds it to a GRIB2 message.  It is used with routines "g2_create",
 //   "g2_addlocal", "g2_addfield",
 //   and "g2_gribend" to create a complete GRIB2 message.
@@ -27,17 +27,17 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
 //                Must be dimensioned >= 5.
 //                igds[0]=Source of grid definition (see Code Table 3.0)
 //                igds[1]=Number of grid points in the defined grid.
-//                igds[2]=Number of octets needed for each 
-//                            additional grid points definition.  
+//                igds[2]=Number of octets needed for each
+//                            additional grid points definition.
 //                            Used to define number of
 //                            points in each row ( or column ) for
-//                            non-regular grids.  
+//                            non-regular grids.
 //                            = 0, if using regular grid.
-//                igds[3]=Interpretation of list for optional points 
+//                igds[3]=Interpretation of list for optional points
 //                            definition.  (Code Table 3.11)
 //                igds[4]=Grid Definition Template Number (Code Table 3.1)
 //     igdstmpl - Contains the data values for the specified Grid Definition
-//                Template ( NN=igds[4] ).  Each element of this integer 
+//                Template ( NN=igds[4] ).  Each element of this integer
 //                array contains an entry (in the order specified) of Grid
 //                Definition Template 3.NN
 //     ideflist - (Used if igds[2] != 0)  This array contains the
@@ -46,7 +46,7 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
 //                in array ideflist.  i.e. number of rows ( or columns )
 //                for which optional grid points are defined.
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     cgrib    - Char array to contain the updated GRIB2 message.
 //                Must be allocated large enough to store the entire
 //                GRIB2 message.
@@ -66,7 +66,7 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 {
@@ -81,7 +81,7 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
       g2int   lensec3,iofst,ibeg,lencurr,len;
       g2int   i,j,temp,ilen,isecnum,nbits;
       xxtemplate *mapgrid=0;
- 
+
 //
 //  Check to see if beginning of GRIB message exists
 //
@@ -92,11 +92,11 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
       }
 //
 //  Get current length of GRIB message
-//  
+//
       gbit(cgrib,&lencurr,96,32);
 //
 //  Check to see if GRIB message is already complete
-//  
+//
       if ( cgrib[lencurr-4]==seven && cgrib[lencurr-3]==seven &&
            cgrib[lencurr-2]==seven && cgrib[lencurr-1]==seven ) {
         printf("g2_addgrid: GRIB message already complete.  Cannot add new section.\n");
@@ -107,7 +107,7 @@ g2int g2_addgrid(unsigned char *cgrib,g2int *igds,g2int *igdstmpl,g2int *ideflis
 //  find the last section number.
 //
       len=16;    // length of Section 0
-      for (;;) { 
+      for (;;) {
       //    Get section number and length of next section
         iofst=len*8;
         gbit(cgrib,&ilen,iofst,32);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c
index cf44c00..d55eb5c 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_addlocal.c
@@ -4,13 +4,13 @@
 g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_addlocal 
+// SUBPROGRAM:    g2_addlocal
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-11-01
 //
-// ABSTRACT: This routine adds a Local Use Section (Section 2) to 
-//   a GRIB2 message.  It is used with routines "g2_create", 
+// ABSTRACT: This routine adds a Local Use Section (Section 2) to
+//   a GRIB2 message.  It is used with routines "g2_create",
 //   "g2_addgrid", "g2_addfield",
-//   and "g2_gribend" to create a complete GRIB2 message.  
+//   and "g2_gribend" to create a complete GRIB2 message.
 //   g2_create must be called first to initialize a new GRIB2 message.
 //
 // PROGRAM HISTORY LOG:
@@ -26,7 +26,7 @@ g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
 //     lcsec2   - Number of bytes of character array csec2 to be added to
 //                Section 2.
 //
-//   OUTPUT ARGUMENT:      
+//   OUTPUT ARGUMENT:
 //     cgrib    - Char array to contain the updated GRIB2 message.
 //                Must be allocated large enough to store the entire
 //                GRIB2 message.
@@ -45,7 +45,7 @@ g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE: 
+//   MACHINE:
 //
 //$$$
 {
@@ -70,12 +70,12 @@ g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
       }
 //
 //  Get current length of GRIB message
-//  
+//
       gbit(cgrib,&lencurr,96,32);
 //
 //  Check to see if GRIB message is already complete
-//  
-      if ( cgrib[lencurr-4]==seven && cgrib[lencurr-3]==seven && 
+//
+      if ( cgrib[lencurr-4]==seven && cgrib[lencurr-3]==seven &&
            cgrib[lencurr-2]==seven && cgrib[lencurr-1]==seven ) {
         printf("g2_addlocal: GRIB message already complete.  Cannot add new section.\n");
         return(-2);
@@ -85,7 +85,7 @@ g2int g2_addlocal(unsigned char *cgrib,unsigned char *csec2,g2int lcsec2)
 //  find the last section number.
 //
       len=16;    // length of Section 0
-      for (;;) { 
+      for (;;) {
       //    Get section number and length of next section
         iofst=len*8;
         gbit(cgrib,&ilen,iofst,32);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_create.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_create.c
index 9944284..bea798f 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_create.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_create.c
@@ -6,13 +6,13 @@
 g2int g2_create(unsigned char *cgrib,g2int *listsec0,g2int *listsec1)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_create 
+// SUBPROGRAM:    g2_create
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This routine initializes a new GRIB2 message and packs
 //   GRIB2 sections 0 (Indicator Section) and 1 (Identification Section).
-//   This routine is used with routines "g2_addlocal", "g2_addgrid", 
-//   "g2_addfield", and "g2_gribend" to create a complete GRIB2 message.  
+//   This routine is used with routines "g2_addlocal", "g2_addgrid",
+//   "g2_addfield", and "g2_gribend" to create a complete GRIB2 message.
 //   g2_create must be called first to initialize a new GRIB2 message.
 //   Also, a call to g2_gribend is required to complete GRIB2 message
 //   after all fields have been added.
@@ -44,7 +44,7 @@ g2int g2_create(unsigned char *cgrib,g2int *listsec0,g2int *listsec1)
 //                listsec1[11]=Production status of data (Code Table 1.3)
 //                listsec1[12]=Type of processed data (Code Table 1.4)
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     cgrib    - Char array to contain the new GRIB2 message.
 //                Must be allocated large enough to store the entire
 //                GRIB2 message.
@@ -54,13 +54,13 @@ g2int g2_create(unsigned char *cgrib,g2int *listsec0,g2int *listsec1)
 //              > 0 = Current size of new GRIB2 message
 //               -1 = Tried to use for version other than GRIB Edition 2
 //
-// REMARKS: This routine is intended for use with routines "g2_addlocal", 
-//          "g2_addgrid", "g2_addfield", and "g2_gribend" to create a complete 
+// REMARKS: This routine is intended for use with routines "g2_addlocal",
+//          "g2_addgrid", "g2_addfield", and "g2_gribend" to create a complete
 //          GRIB2 message.
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 {
@@ -72,13 +72,13 @@ g2int g2_create(unsigned char *cgrib,g2int *listsec0,g2int *listsec1)
 
 //
 //  Currently handles only GRIB Edition 2.
-//  
+//
       if (listsec0[1] != 2) {
         printf("g2_create: can only code GRIB edition 2.");
         return (-1);
       }
 //
-//  Pack Section 0 - Indicator Section 
+//  Pack Section 0 - Indicator Section
 //  ( except for total length of GRIB message )
 //
       cgrib[0]=0x47;   // 'G'            // Beginning of GRIB message
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_free.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_free.c
index 04a1792..15f227e 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_free.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_free.c
@@ -4,7 +4,7 @@
 void g2_free(gribfield *gfld)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_free 
+// SUBPROGRAM:    g2_free
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-28
 //
 // ABSTRACT: This routine frees up memory that was allocated for
@@ -24,10 +24,10 @@ void g2_free(gribfield *gfld)
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
-{ 
+{
 
       if (gfld->idsect != 0 ) free(gfld->idsect);
       if (gfld->local != 0 ) free(gfld->local);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c
index 2c1e81e..27488ec 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_getfld.c
@@ -17,10 +17,10 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
                 gribfield **gfld)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_getfld 
+// SUBPROGRAM:    g2_getfld
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-28
 //
-// ABSTRACT: This subroutine returns all the metadata, template values, 
+// ABSTRACT: This subroutine returns all the metadata, template values,
 //   Bit-map ( if applicable ), and the unpacked data for a given data
 //   field.  All of the information returned is stored in a gribfield
 //   structure, which is defined in file grib2.h.
@@ -44,20 +44,20 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //     unpack   - Boolean value indicating whether to unpack bitmap/data field
 //                1 = unpack bitmap (if present) and data values
 //                0 = do not unpack bitmap and data values
-//     expand   - Boolean value indicating whether the data points should be 
+//     expand   - Boolean value indicating whether the data points should be
 //                expanded to the correspond grid, if a bit-map is present.
-//                1 = if possible, expand data field to grid, inserting zero 
-//                    values at gridpoints that are bitmapped out. 
+//                1 = if possible, expand data field to grid, inserting zero
+//                    values at gridpoints that are bitmapped out.
 //                    (SEE REMARKS2)
 //                0 = do not expand data field, leaving it an array of
 //                    consecutive data points for each "1" in the bitmap.
 //                This argument is ignored if unpack == 0 OR if the
 //                returned field does not contain a bit-map.
 //
-//   OUTPUT ARGUMENT:      
+//   OUTPUT ARGUMENT:
 //     gribfield gfld; - pointer to structure gribfield containing
 //                       all decoded data for the data field.
-// 
+//
 //        gfld->version = GRIB edition number ( currently 2 )
 //        gfld->discipline = Message Discipline ( see Code Table 0.0 )
 //        gfld->idsect = Contains the entries in the Identification
@@ -135,7 +135,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //                          This element is a pointer to an array
 //                          that holds the data.  This pointer is nullified
 //                          if gfld->numoct_opt=0.
-//        gfld->num_opt = (Used if gfld->numoct_opt .ne. 0) 
+//        gfld->num_opt = (Used if gfld->numoct_opt .ne. 0)
 //                        The number of entries
 //                       in array ideflist.  i.e. number of rows ( or columns )
 //                       for which optional grid points are defined.  This value
@@ -173,10 +173,10 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //        gfld->unpacked = logical value indicating whether the bitmap and
 //                        data values were unpacked.  If false,
 //                        gfld->bmap and gfld->fld pointers are nullified.
-//        gfld->expanded = Logical value indicating whether the data field 
-//                         was expanded to the grid in the case where a 
+//        gfld->expanded = Logical value indicating whether the data field
+//                         was expanded to the grid in the case where a
 //                         bit-map is present.  If true, the data points in
-//                         gfld->fld match the grid points and zeros were 
+//                         gfld->fld match the grid points and zeros were
 //                         inserted at grid points where data was bit-mapped
 //                         out.  If false, the data values in gfld->fld were
 //                         not expanded to the grid and are just a consecutive
@@ -195,7 +195,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //                     This element is a pointer to an array
 //                     that holds the data.
 //
-// 
+//
 //   RETURN VALUES:
 //     ierr     - Error return code.
 //                0 = no error
@@ -219,7 +219,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //
 // REMARKS: Note that struct gribfield is allocated by this routine and it
 //          also contains pointers to many arrays of data that were allocated
-//          during decoding.  Users are encouraged to free up this memory, 
+//          during decoding.  Users are encouraged to free up this memory,
 //          when it is no longer needed, by an explicit call to routine g2_free.
 //          EXAMPLE:
 //              #include "grib2.h"
@@ -233,18 +233,18 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //
 // REMARKS2: It may not always be possible to expand a bit-mapped data field.
 //           If a pre-defined bit-map is used and not included in the GRIB2
-//           message itself, this routine would not have the necessary 
+//           message itself, this routine would not have the necessary
 //           information to expand the data.  In this case, gfld->expanded would
-//           would be set to 0 (false), regardless of the value of input 
+//           would be set to 0 (false), regardless of the value of input
 //           argument expand.
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 {
-    
+
       g2int have3,have4,have5,have6,have7,ierr,jerr;
       g2int numfld,j,n,istart,iofst,ipos;
       g2int disc,ver,lensec0,lengrib,lensec,isecnum;
@@ -276,7 +276,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
       lgfld->fld=0;
 //
 //  Check for valid request number
-//  
+//
       if (ifldnum <= 0) {
         printf("g2_getfld: Request for field number must be positive.\n");
         ierr=3;
@@ -287,7 +287,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
 //
       istart=-1;
       for (j=0;j<100;j++) {
-        if (cgrib[j]=='G' && cgrib[j+1]=='R' &&cgrib[j+2]=='I' && 
+        if (cgrib[j]=='G' && cgrib[j+1]=='R' &&cgrib[j+2]=='I' &&
             cgrib[j+3]=='B') {
           istart=j;
           break;
@@ -299,7 +299,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
         return(ierr);
       }
 //
-//  Unpack Section 0 - Indicator Section 
+//  Unpack Section 0 - Indicator Section
 //
       iofst=8*(istart+6);
       gbit(cgrib,&disc,iofst,8);     // Discipline
@@ -313,20 +313,20 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
       ipos=istart+lensec0;
 //
 //  Currently handles only GRIB Edition 2.
-//  
+//
       if (ver != 2) {
         printf("g2_getfld: can only decode GRIB edition 2.\n");
         ierr=2;
         return(ierr);
       }
 //
-//  Loop through the remaining sections keeping track of the 
+//  Loop through the remaining sections keeping track of the
 //  length of each.  Also keep the latest Grid Definition Section info.
 //  Unpack the requested field number.
 //
       for (;;) {
         //    Check to see if we are at end of GRIB message
-        if (cgrib[ipos]=='7' && cgrib[ipos+1]=='7' && cgrib[ipos+2]=='7' && 
+        if (cgrib[ipos]=='7' && cgrib[ipos+1]=='7' && cgrib[ipos+2]=='7' &&
             cgrib[ipos+3]=='7') {
           ipos=ipos+4;
           //    If end of GRIB message not where expected, issue error
@@ -378,7 +378,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
           }
         }
         //
-        //   If found Section 3, unpack the GDS info using the 
+        //   If found Section 3, unpack the GDS info using the
         //   appropriate template.  Save in case this is the latest
         //   grid before the requested field.
         //
@@ -455,7 +455,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
             if (jerr == 0) {
               have6=1;
               if (lgfld->ibmap == 254)     // use previously specified bitmap
-                 if( bmpsave!=0 ) 
+                 if( bmpsave!=0 )
                     lgfld->bmap=bmpsave;
                  else {
                     printf("g2_getfld: Prev bit-map specified, but none exist.\n");
@@ -486,7 +486,7 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
                           &lgfld->fld);
           if (jerr == 0) {
             have7=1;
-            //  If bitmap is used with this field, expand data field 
+            //  If bitmap is used with this field, expand data field
             //  to grid, if possible.
             if ( lgfld->ibmap != 255 && lgfld->bmap != 0 ) {
                if ( expand == 1 ) {
@@ -530,12 +530,12 @@ g2int g2_getfld(unsigned char *cgrib,g2int ifldnum,g2int unpack,g2int expand,
         if (unpack && have3 && have4 && have5 && have6 && have7)
             return(ierr);
         //
-        //  If unpacking is not requested, return when sections 
+        //  If unpacking is not requested, return when sections
         //  3 through 6 have been processed
         //
         if ((! unpack) && have3 && have4 && have5 && have6)
             return(ierr);
-        
+
       }
 
 //
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c
index c6d838a..52907a6 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_gribend.c
@@ -4,14 +4,14 @@
 g2int g2_gribend(unsigned char *cgrib)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_gribend 
+// SUBPROGRAM:    g2_gribend
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This routine finalizes a GRIB2 message after all grids
 //   and fields have been added.  It adds the End Section ( "7777" )
 //   to the end of the GRIB message and calculates the length and stores
 //   it in the appropriate place in Section 0.
-//   This routine is used with routines "g2_create", "g2_addlocal", 
+//   This routine is used with routines "g2_create", "g2_addlocal",
 //   "g2_addgrid", and "g2_addfield" to create a complete GRIB2 message.
 //   g2_create must be called first to initialize a new GRIB2 message.
 //
@@ -24,7 +24,7 @@ g2int g2_gribend(unsigned char *cgrib)
 //                be previous calls to g2_create, g2_addlocal, g2_addgrid,
 //                and g2_addfield.
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     cgrib    - Char array containing the finalized GRIB2 message
 //
 //   RETURN VALUES:
@@ -32,12 +32,12 @@ g2int g2_gribend(unsigned char *cgrib)
 //              > 0 = Length of the final GRIB2 message in bytes.
 //               -1 = GRIB message was not initialized.  Need to call
 //                    routine g2_create first.
-//               -2 = GRIB message already complete.  
+//               -2 = GRIB message already complete.
 //               -3 = Sum of Section byte counts doesn't add to total byte count
 //               -4 = Previous Section was not 7.
 //
-// REMARKS: This routine is intended for use with routines "g2_create", 
-//          "g2_addlocal", "g2_addgrid", and "g2_addfield" to create a complete 
+// REMARKS: This routine is intended for use with routines "g2_create",
+//          "g2_addlocal", "g2_addgrid", and "g2_addfield" to create a complete
 //          GRIB2 message.
 //
 // ATTRIBUTES:
@@ -54,7 +54,7 @@ g2int g2_gribend(unsigned char *cgrib)
       const unsigned char I=0x49;       // 'I'
       const unsigned char B=0x42;       // 'B'
       const unsigned char seven=0x37;   // '7'
- 
+
 //
 //  Check to see if beginning of GRIB message exists
 //
@@ -64,14 +64,14 @@ g2int g2_gribend(unsigned char *cgrib)
       }
 //
 //  Get current length of GRIB message
-//  
+//
       gbit(cgrib,&lencurr,96,32);
 //
 //  Loop through all current sections of the GRIB message to
 //  find the last section number.
 //
       len=16;    // Length of Section 0
-      for (;;) { 
+      for (;;) {
       //    Get number and length of next section
         iofst=len*8;
         gbit(cgrib,&ilen,iofst,32);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_info.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_info.c
index 06bc156..d85bb15 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_info.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_info.c
@@ -6,7 +6,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
             g2int *numfields,g2int *numlocal)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_info 
+// SUBPROGRAM:    g2_info
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-28
 //
 // ABSTRACT: This subroutine searches through a GRIB2 message and
@@ -23,21 +23,21 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
 //   INPUT ARGUMENT:
 //     cgrib    - Character pointer to the GRIB2 message
 //
-//   OUTPUT ARGUMENTS:      
-//     listsec0 - pointer to an array containing information decoded from 
+//   OUTPUT ARGUMENTS:
+//     listsec0 - pointer to an array containing information decoded from
 //                GRIB Indicator Section 0.
 //                Must be allocated with >= 3 elements.
 //                listsec0[0]=Discipline-GRIB Master Table Number
 //                            (see Code Table 0.0)
 //                listsec0[1]=GRIB Edition Number (currently 2)
 //                listsec0[2]=Length of GRIB message
-//     listsec1 - pointer to an array containing information read from GRIB 
+//     listsec1 - pointer to an array containing information read from GRIB
 //                Identification Section 1.
 //                Must be allocated with >= 13 elements.
 //                listsec1[0]=Id of originating centre (Common Code Table C-1)
 //                listsec1[1]=Id of originating sub-centre (local table)
 //                listsec1[2]=GRIB Master Tables Version Number (Code Table 1.0)
-//                listsec1[3]=GRIB Local Tables Version Number 
+//                listsec1[3]=GRIB Local Tables Version Number
 //                listsec1[4]=Significance of Reference Time (Code Table 1.1)
 //                listsec1[5]=Reference Time - Year (4 digits)
 //                listsec1[6]=Reference Time - Month
@@ -49,7 +49,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
 //                listsec1[12]=Type of processed data (Code Table 1.3)
 //     numfields- The number of gridded fields found in the GRIB message.
 //                That is, the number of occurrences of Sections 4 - 7.
-//     numlocal - The number of Local Use Sections ( Section 2 ) found in 
+//     numlocal - The number of Local Use Sections ( Section 2 ) found in
 //                the GRIB message.
 //
 //     RETURN VALUES:
@@ -66,11 +66,11 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 {
- 
+
       g2int mapsec1len=13;
       g2int mapsec1[13]={2,2,1,1,1,2,1,1,1,1,1,1,1};
       g2int  i,j,istart,iofst,lengrib,lensec0,lensec1;
@@ -94,7 +94,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
         return(1);
       }
 //
-//  Unpack Section 0 - Indicator Section 
+//  Unpack Section 0 - Indicator Section
 //
       iofst=8*(istart+6);
       gbit(cgrib,listsec0+0,iofst,8);     // Discipline
@@ -109,7 +109,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
       ipos=istart+lensec0;
 //
 //  Currently handles only GRIB Edition 2.
-//  
+//
       if (listsec0[1] != 2) {
         printf("g2_info: can only decode GRIB edition 2.");
         return(2);
@@ -151,7 +151,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
           }
           break;
         }
-        
+
         iofst=ipos*8;
         gbit(cgrib,&lensec,iofst,32);        // Get Length of Section
         iofst=iofst+32;
@@ -166,7 +166,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
            if (isecnum == 2)      // Local Section 2
               //   increment counter for total number of local sections found
               (*numlocal)++;
-            
+
            else if (isecnum == 4)
               //   increment counter for total number of fields found
               (*numfields)++;
@@ -175,7 +175,7 @@ g2int g2_info(unsigned char *cgrib,g2int *listsec0,g2int *listsec1,
            printf("g2_info: Invalid section number found in GRIB message: %d\n"                   ,isecnum);
            return(6);
         }
-        
+
       }
 
       return(0);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c
index dc10716..a29636f 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_miss.c
@@ -3,27 +3,27 @@
 void g2_miss( gribfield *gfld, float *rmiss, int *nmiss )
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_miss 
+// SUBPROGRAM:    g2_miss
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2004-12-16
 //
 // ABSTRACT: This routine checks the Data Representation Template to see if
-// missing value management is used, and returns the missing value(s) 
+// missing value management is used, and returns the missing value(s)
 // in the data field.
 //
 // PROGRAM HISTORY LOG:
 // 2004-12-16  Gilbert
 //
 // USAGE:    g2_miss( gribfield *gfld, float *rmiss, int *nmiss )
-//                   
+//
 //   INPUT ARGUMENT LIST:
-//     *gfld    - pointer to gribfield structure (defined in include file 
+//     *gfld    - pointer to gribfield structure (defined in include file
 //                   grib2.h)
 //
-//   OUTPUT ARGUMENT LIST:      
+//   OUTPUT ARGUMENT LIST:
 //     rmiss    - List of the missing values used
 //     nmiss    - NUmber of the missing values included in the field
 //
-// REMARKS:  rmiss must be allocated in the calling program with enough space 
+// REMARKS:  rmiss must be allocated in the calling program with enough space
 //           hold all the missing values.
 //
 // ATTRIBUTES:
@@ -32,7 +32,7 @@ void g2_miss( gribfield *gfld, float *rmiss, int *nmiss )
 //
 //$$$
 {
-    g2int     itype;    
+    g2int     itype;
 
     /*
      *  Missing value management currently only used in
@@ -42,7 +42,7 @@ void g2_miss( gribfield *gfld, float *rmiss, int *nmiss )
        *nmiss=0;
        return;
     }
-                                                                                
+
     itype = gfld->idrtmpl[4];
     if ( gfld->idrtmpl[6] == 1 ) {
          *nmiss=1;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack1.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack1.c
index 02114e9..140b6da 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack1.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack1.c
@@ -5,7 +5,7 @@
 g2int g2_unpack1(unsigned char *cgrib,g2int *iofst,g2int **ids,g2int *idslen)
 /*//$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_unpack1 
+// SUBPROGRAM:    g2_unpack1
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-29
 //
 // ABSTRACT: This subroutine unpacks Section 1 (Identification Section)
@@ -20,9 +20,9 @@ g2int g2_unpack1(unsigned char *cgrib,g2int *iofst,g2int **ids,g2int *idslen)
 //     cgrib    - char array containing Section 1 of the GRIB2 message
 //     iofst    - Bit offset for the beginning of Section 1 in cgrib.
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     iofst    - Bit offset at the end of Section 1, returned.
-//     ids      - address of pointer to integer array containing information 
+//     ids      - address of pointer to integer array containing information
 //                read from Section 1, the Identification section.
 //            ids[0]  = Identification of originating Centre
 //                                 ( see Common Code Table C-1 )
@@ -49,7 +49,7 @@ g2int g2_unpack1(unsigned char *cgrib,g2int *iofst,g2int **ids,g2int *idslen)
 //                2 = Array passed is not section 1
 //                6 = memory allocation error
 //
-// REMARKS: 
+// REMARKS:
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
@@ -88,12 +88,12 @@ g2int g2_unpack1(unsigned char *cgrib,g2int *iofst,g2int **ids,g2int *idslen)
          ierr=6;
          return(ierr);
       }
-      
+
       for (i=0;i<*idslen;i++) {
         nbits=mapid[i]*8;
         gbit(cgrib,*ids+i,*iofst,nbits);
         *iofst=*iofst+nbits;
       }
-      
+
       return(ierr);    // End of Section 1 processing
 }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack2.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack2.c
index ebab94b..ff49723 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack2.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack2.c
@@ -5,7 +5,7 @@
 g2int g2_unpack2(unsigned char *cgrib,g2int *iofst,g2int *lencsec2,unsigned char **csec2)
 ////$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_unpack2 
+// SUBPROGRAM:    g2_unpack2
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This subroutine unpacks Section 2 (Local Use Section)
@@ -20,7 +20,7 @@ g2int g2_unpack2(unsigned char *cgrib,g2int *iofst,g2int *lencsec2,unsigned char
 //     cgrib    - char array containing Section 2 of the GRIB2 message
 //     iofst    - Bit offset for the beginning of Section 2 in cgrib.
 //
-//   OUTPUT ARGUMENT LIST:      
+//   OUTPUT ARGUMENT LIST:
 //     iofst    - Bit offset at the end of Section 2, returned.
 //     lencsec2 - Length (in octets) of Local Use data
 //     csec2    - Pointer to a char array containing local use data
@@ -35,7 +35,7 @@ g2int g2_unpack2(unsigned char *cgrib,g2int *iofst,g2int *lencsec2,unsigned char
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE: 
+//   MACHINE:
 //
 //$$$//
 {
@@ -67,7 +67,7 @@ g2int g2_unpack2(unsigned char *cgrib,g2int *iofst,g2int *lencsec2,unsigned char
          *lencsec2=0;
          return(ierr);
       }
-      
+
       //printf(" SAGIPO %d \n",(int)ipos);
       for (j=0;j<*lencsec2;j++) {
          *(*csec2+j)=cgrib[ipos+j];
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c
index f9462aa..53c27b8 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack3.c
@@ -7,7 +7,7 @@ g2int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,g2int **igdstmpl
                          g2int *mapgridlen,g2int **ideflist,g2int *idefnum)
 ////$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_unpack3 
+// SUBPROGRAM:    g2_unpack3
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This routine unpacks Section 3 (Grid Definition Section)
@@ -23,24 +23,24 @@ g2int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,g2int **igdstmpl
 //     cgrib    - Char array containing Section 3 of the GRIB2 message.
 //     iofst    - Bit offset for the beginning of Section 3 in cgrib.
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     iofst    - Bit offset at the end of Section 3, returned.
-//     igds     - Contains information read from the appropriate GRIB Grid 
+//     igds     - Contains information read from the appropriate GRIB Grid
 //                Definition Section 3 for the field being returned.
 //                igds[0]=Source of grid definition (see Code Table 3.0)
 //                igds[1]=Number of grid points in the defined grid.
-//                igds[2]=Number of octets needed for each 
-//                            additional grid points definition.  
+//                igds[2]=Number of octets needed for each
+//                            additional grid points definition.
 //                            Used to define number of
 //                            points in each row ( or column ) for
-//                            non-regular grids.  
+//                            non-regular grids.
 //                            = 0, if using regular grid.
-//                igds[3]=Interpretation of list for optional points 
+//                igds[3]=Interpretation of list for optional points
 //                            definition.  (Code Table 3.11)
 //                igds[4]=Grid Definition Template Number (Code Table 3.1)
-//     igdstmpl - Pointer to integer array containing the data values for 
+//     igdstmpl - Pointer to integer array containing the data values for
 //                the specified Grid Definition
-//                Template ( NN=igds[4] ).  Each element of this integer 
+//                Template ( NN=igds[4] ).  Each element of this integer
 //                array contains an entry (in the order specified) of Grid
 //                Definition Template 3.NN
 //     mapgridlen- Number of elements in igdstmpl[].  i.e. number of entries
@@ -58,7 +58,7 @@ g2int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,g2int **igdstmpl
 //                    Template.
 //                6 = memory allocation error
 //
-// REMARKS: 
+// REMARKS:
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
@@ -124,7 +124,7 @@ g2int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,g2int **igdstmpl
               ierr=6;
               *mapgridlen=0;
               *igdstmpl=0;    //NULL
-              if( mapgrid != 0 ) free(mapgrid);
+              free(mapgrid);
               return(ierr);
            }
            else {
@@ -208,6 +208,6 @@ g2int g2_unpack3(unsigned char *cgrib,g2int *iofst,g2int **igds,g2int **igdstmpl
          *idefnum=0;
          *ideflist=0;    // NULL
       }
-      
+
       return(ierr);    // End of Section 3 processing
 }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c
index d0b6e9f..7c09d40 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack4.c
@@ -7,7 +7,7 @@ g2int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,g2int **ipdstm
                g2int *mappdslen,g2float **coordlist,g2int *numcoord)
 ////$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_unpack4 
+// SUBPROGRAM:    g2_unpack4
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This subroutine unpacks Section 4 (Product Definition Section)
@@ -23,17 +23,17 @@ g2int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,g2int **ipdstm
 //     cgrib    - Char array containing Section 4 of the GRIB2 message
 //     iofst    - Bit offset of the beginning of Section 4 in cgrib.
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     iofst    - Bit offset of the end of Section 4, returned.
 //     ipdsnum  - Product Definition Template Number ( see Code Table 4.0)
-//     ipdstmpl - Pointer to integer array containing the data values for 
+//     ipdstmpl - Pointer to integer array containing the data values for
 //                the specified Product Definition
 //                Template ( N=ipdsnum ).  Each element of this integer
 //                array contains an entry (in the order specified) of Product
 //                Definition Template 4.N
 //     mappdslen- Number of elements in ipdstmpl[].  i.e. number of entries
 //                in Product Definition Template 4.N  ( N=ipdsnum ).
-//     coordlist- Pointer to real array containing floating point values 
+//     coordlist- Pointer to real array containing floating point values
 //                intended to document
 //                the vertical discretisation associated to model data
 //                on hybrid coordinate vertical levels.  (part of Section 4)
@@ -47,11 +47,11 @@ g2int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,g2int **ipdstm
 //                    Template.
 //                6 = memory allocation error
 //
-// REMARKS: 
+// REMARKS:
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$//
 {
@@ -104,7 +104,7 @@ g2int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,g2int **ipdstm
          ierr=6;
          *mappdslen=0;
          *ipdstmpl=0;     //NULL
-         if ( mappds != 0 ) free(mappds);
+         free(mappds);
          return(ierr);
       }
       else {
@@ -178,7 +178,7 @@ g2int g2_unpack4(unsigned char *cgrib,g2int *iofst,g2int *ipdsnum,g2int **ipdstm
         free(coordieee);
         *iofst=*iofst+(32*(*numcoord));
       }
-      
+
       return(ierr);    // End of Section 4 processing
 
 }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack5.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack5.c
index 61cb6dd..ff5be67 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack5.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack5.c
@@ -7,7 +7,7 @@ g2int g2_unpack5(unsigned char *cgrib,g2int *iofst,g2int *ndpts,g2int *idrsnum,
                g2int **idrstmpl,g2int *mapdrslen)
 ////$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_unpack5 
+// SUBPROGRAM:    g2_unpack5
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This subroutine unpacks Section 5 (Data Representation Section)
@@ -22,11 +22,11 @@ g2int g2_unpack5(unsigned char *cgrib,g2int *iofst,g2int *ndpts,g2int *idrsnum,
 //     cgrib    - char array containing Section 5 of the GRIB2 message
 //     iofst    - Bit offset for the beginning of Section 5 in cgrib.
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     iofst    - Bit offset at the end of Section 5, returned.
 //     ndpts    - Number of data points unpacked and returned.
 //     idrsnum  - Data Representation Template Number ( see Code Table 5.0)
-//     idrstmpl - Pointer to an integer array containing the data values for 
+//     idrstmpl - Pointer to an integer array containing the data values for
 //                the specified Data Representation
 //                Template ( N=idrsnum ).  Each element of this integer
 //                array contains an entry (in the order specified) of Data
@@ -46,7 +46,7 @@ g2int g2_unpack5(unsigned char *cgrib,g2int *iofst,g2int *ndpts,g2int *idrsnum,
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$//
 {
@@ -95,7 +95,7 @@ g2int g2_unpack5(unsigned char *cgrib,g2int *iofst,g2int *ndpts,g2int *idrsnum,
          ierr=6;
          *mapdrslen=0;
          *idrstmpl=0;     //NULL
-         if ( mapdrs != 0 ) free(mapdrs);
+         free(mapdrs);
          return(ierr);
       }
       else {
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack6.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack6.c
index 9f6da7e..4563286 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack6.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack6.c
@@ -6,7 +6,7 @@ g2int g2_unpack6(unsigned char *cgrib,g2int *iofst,g2int ngpts,g2int *ibmap,
                g2int **bmap)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_unpack6 
+// SUBPROGRAM:    g2_unpack6
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This subroutine unpacks Section 6 (Bit-Map Section)
@@ -22,14 +22,14 @@ g2int g2_unpack6(unsigned char *cgrib,g2int *iofst,g2int ngpts,g2int *ibmap,
 //     iofst    - Bit offset of the beginning of Section 6 in cgrib.
 //     ngpts    - Number of grid points specified in the bit-map
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     iofst    - Bit offset at the end of Section 6, returned.
 //     ibmap    - Bitmap indicator ( see Code Table 6.0 )
 //                0 = bitmap applies and is included in Section 6.
 //                1-253 = Predefined bitmap applies
 //                254 = Previously defined bitmap applies to this field
 //                255 = Bit map does not apply to this product.
-//     bmap     - Pointer to an integer array containing decoded bitmap. 
+//     bmap     - Pointer to an integer array containing decoded bitmap.
 //                ( if ibmap=0 )
 //
 //   RETURN VALUES:
@@ -56,7 +56,7 @@ g2int g2_unpack6(unsigned char *cgrib,g2int *iofst,g2int ngpts,g2int *ibmap,
 
       *iofst=*iofst+32;    // skip Length of Section
       gbit(cgrib,&isecnum,*iofst,8);         // Get Section Number
-      *iofst=*iofst+8; 
+      *iofst=*iofst+8;
 
       if ( isecnum != 6 ) {
          ierr=2;
@@ -76,7 +76,7 @@ g2int g2_unpack6(unsigned char *cgrib,g2int *iofst,g2int ngpts,g2int *ibmap,
          else {
             *bmap=lbmap;
          }
-         intbmap=(g2int *)calloc(ngpts,sizeof(g2int));  
+         intbmap=(g2int *)calloc(ngpts,sizeof(g2int));
          gbits(cgrib,intbmap,*iofst,1,0,ngpts);
          *iofst=*iofst+ngpts;
          for (j=0;j<ngpts;j++) {
@@ -91,7 +91,7 @@ g2int g2_unpack6(unsigned char *cgrib,g2int *iofst,g2int ngpts,g2int *ibmap,
 //        print *,'gf_unpack6: Predefined bitmap ',*ibmap,' not recognized.'
 //        ierr=4;
       }
-      
+
       return(ierr);    // End of Section 6 processing
 
 }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c
index c1125b6..6214ab0 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/g2_unpack7.c
@@ -14,7 +14,7 @@ g2int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,g2int *igdstmpl
                g2int idrsnum,g2int *idrstmpl,g2int ndpts,g2float **fld)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_unpack7 
+// SUBPROGRAM:    g2_unpack7
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This subroutine unpacks Section 7 (Data Section)
@@ -52,7 +52,7 @@ g2int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,g2int *igdstmpl
 //                Representation Template 5.N
 //     ndpts    - Number of data points unpacked and returned.
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     iofst    - Bit offset at the end of Section 7, returned.
 //     fld      - Pointer to a float array containing the unpacked data field.
 //
@@ -81,7 +81,7 @@ g2int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,g2int *igdstmpl
       *fld=0;     //NULL
 
       gbit(cgrib,&lensec,*iofst,32);        // Get Length of Section
-      *iofst=*iofst+32;    
+      *iofst=*iofst+32;
       gbit(cgrib,&isecnum,*iofst,8);         // Get Section Number
       *iofst=*iofst+8;
 
@@ -101,7 +101,7 @@ g2int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,g2int *igdstmpl
          *fld=lfld;
       }
 
-      if (idrsnum == 0) 
+      if (idrsnum == 0)
         simunpack(cgrib+ipos,idrstmpl,ndpts,lfld);
       else if (idrsnum == 2 || idrsnum == 3) {
         if (comunpack(cgrib+ipos,lensec,idrsnum,idrstmpl,ndpts,lfld) != 0) {
@@ -113,7 +113,7 @@ g2int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,g2int *igdstmpl
         rdieee(idrstmpl+4,lfld+0,1);
       }
       else if (idrsnum == 51)              //  Spectral complex
-        if ( igdsnum>=50 && igdsnum <=53 ) 
+        if ( igdsnum>=50 && igdsnum <=53 )
           specunpack(cgrib+ipos,idrstmpl,ndpts,igdstmpl[0],igdstmpl[2],igdstmpl[2],lfld);
         else {
           fprintf(stderr,"g2_unpack7: Cannot use GDT 3.%d to unpack Data Section 5.51.\n",(int)igdsnum);
@@ -139,7 +139,7 @@ g2int g2_unpack7(unsigned char *cgrib,g2int *iofst,g2int igdsnum,g2int *igdstmpl
       }
 
       *iofst=*iofst+(8*lensec);
-      
+
       return(ierr);    // End of Section 7 processing
 
 }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/gbits.c b/frmts/grib/degrib18/g2clib-1.0.4/gbits.c
index ccee324..f3f52d4 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/gbits.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/gbits.c
@@ -90,7 +90,7 @@ void sbits(unsigned char *out,const g2int *in,g2int iskip,g2int nbyte,g2int nski
          ibit=nbit%8;
          nbit = nbit + nbyte + nskip;
 
-//        make byte aligned 
+//        make byte aligned
          if (ibit != 7) {
              tbit= ( bitcnt < (ibit+1) ) ? bitcnt : ibit+1;  // find min
              imask = ones[tbit-1] << (7-ibit);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/getdim.c b/frmts/grib/degrib18/g2clib-1.0.4/getdim.c
index 318184e..7e9d454 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/getdim.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/getdim.c
@@ -5,10 +5,10 @@
 g2int getdim(unsigned char *csec3,g2int *width,g2int *height,g2int *iscan)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    getdim 
+// SUBPROGRAM:    getdim
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-12-11
 //
-// ABSTRACT: This subroutine returns the dimensions and scanning mode of 
+// ABSTRACT: This subroutine returns the dimensions and scanning mode of
 //   a grid definition packed in GRIB2 Grid Definition Section 3 format.
 //
 // PROGRAM HISTORY LOG:
@@ -19,7 +19,7 @@ g2int getdim(unsigned char *csec3,g2int *width,g2int *height,g2int *iscan)
 //   INPUT ARGUMENT LIST:
 //     csec3    - Character array that contains the packed GRIB2 GDS
 //
-//   OUTPUT ARGUMENT LIST:      
+//   OUTPUT ARGUMENT LIST:
 //     width    - x (or i) dimension of the grid.
 //     height   - y (or j) dimension of the grid.
 //     iscan    - Scanning mode ( see Code Table 3.4 )
@@ -33,7 +33,7 @@ g2int getdim(unsigned char *csec3,g2int *width,g2int *height,g2int *iscan)
 //
 //$$$
 {
-    
+
       g2int  *igdstmpl,*list_opt;
       g2int  *igds;
       g2int  iofst,igdtlen,num_opt,jerr;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/getpoly.c b/frmts/grib/degrib18/g2clib-1.0.4/getpoly.c
index e60d05c..4df5373 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/getpoly.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/getpoly.c
@@ -5,7 +5,7 @@
 g2int getpoly(unsigned char *csec3,g2int *jj,g2int *kk,g2int *mm)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    getpoly 
+// SUBPROGRAM:    getpoly
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-12-11
 //
 // ABSTRACT: This subroutine returns the J, K, and M pentagonal resolution
@@ -19,7 +19,7 @@ g2int getpoly(unsigned char *csec3,g2int *jj,g2int *kk,g2int *mm)
 //   INPUT ARGUMENTS:
 //     csec3    - Character array that contains the packed GRIB2 GDS
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //         JJ   = J - pentagonal resolution parameter
 //         KK   = K - pentagonal resolution parameter
 //         MM   = M - pentagonal resolution parameter
@@ -33,7 +33,7 @@ g2int getpoly(unsigned char *csec3,g2int *jj,g2int *kk,g2int *mm)
 //
 //$$$
 {
-    
+
       g2int   *igdstmpl,*list_opt;
       g2int   *igds;
       g2int   iofst,igdtlen,num_opt,jerr;
@@ -68,7 +68,7 @@ g2int getpoly(unsigned char *csec3,g2int *jj,g2int *kk,g2int *mm)
          *kk=0;
          *mm=0;
       }
-        
+
       if (igds != 0) free(igds);
       if (igdstmpl != 0) free(igdstmpl);
       if (list_opt != 0) free(list_opt);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/grib2.h b/frmts/grib/degrib18/g2clib-1.0.4/grib2.h
index e5fe610..c9e226a 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/grib2.h
+++ b/frmts/grib/degrib18/g2clib-1.0.4/grib2.h
@@ -7,7 +7,7 @@
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-25
 //
 //   Each element of structure gribfield is defined as:
-//   
+//
 //   gribfield gfld;
 //
 //        gfld->version = GRIB edition number ( currently 2 )
@@ -124,10 +124,10 @@
 //        gfld->unpacked = logical value indicating whether the bitmap and
 //                        data values were unpacked.  If false,
 //                        gfld->bmap and gfld->fld pointers are nullified.
-//        gfld->expanded = Logical value indicating whether the data field 
-//                         was expanded to the grid in the case where a 
+//        gfld->expanded = Logical value indicating whether the data field
+//                         was expanded to the grid in the case where a
 //                         bit-map is present.  If true, the data points in
-//                         gfld->fld match the grid points and zeros were 
+//                         gfld->fld match the grid points and zeros were
 //                         inserted at grid points where data was bit-mapped
 //                         out.  If false, the data values in gfld->fld were
 //                         not expanded to the grid and are just a consecutive
@@ -207,7 +207,7 @@ void g2_free(gribfield *);
 /*  Prototypes for packing API  */
 g2int g2_create(unsigned char *,g2int *,g2int *);
 g2int g2_addlocal(unsigned char *,unsigned char *,g2int );
-g2int g2_addgrid(unsigned char *,g2int *,g2int *,g2int *,g2int ); 
+g2int g2_addgrid(unsigned char *,g2int *,g2int *,g2int *,g2int );
 g2int g2_addfield(unsigned char *,g2int ,g2int *,
                        g2float *,g2int ,g2int ,g2int *,
                        g2float *,g2int ,g2int ,g2int *);
@@ -270,8 +270,17 @@ g2int getpoly(unsigned char *csec3,g2int *jj,g2int *kk,g2int *mm);
 void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
              unsigned char *cpack,g2int *lcpack);
 int enc_jpeg2000(unsigned char *cin,g2int width,g2int height,g2int nbits,
-                 g2int ltype, g2int ratio, g2int retry, char *outjpc, 
+                 g2int ltype, g2int ratio, g2int retry, char *outjpc,
                  g2int jpclen);
 
+int dec_png(unsigned char *pngbuf,g2int len,g2int *width,g2int *height,unsigned char *cout, g2int ndpts, g2int nbits);
+int enc_png(char *data,g2int width,g2int height,g2int nbits,char *pngbuf);
+g2int pngunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
+                g2float *fld);
+void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
+             unsigned char *cpack,g2int *lcpack);
+
+int dec_jpeg2000(const void *injpc,g2int bufsize,g2int *outfld,g2int outpixels);
+
 #endif  /*  grib2_H  */
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc b/frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc
index 104375e..6dde39e 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc
+++ b/frmts/grib/degrib18/g2clib-1.0.4/grib2c.doc
@@ -11,14 +11,14 @@ Contents:
 - GRIB2 Routine Documentation
 
 ===============================================================================
- 
+
                                 Introduction
 
 This document briefly describes the routines available for encoding/decoding
 GRIB Edition 2 (GRIB2) messages.  A basic familiarity with GRIB is assumed.
 
 A GRIB Edition 2 message is a machine independent format for storing
-one or more gridded data fields.  Each GRIB2 message consists of the 
+one or more gridded data fields.  Each GRIB2 message consists of the
 following sections:
 
 SECTION 0 - Indicator Section
@@ -58,8 +58,8 @@ a number of different grids, several routines are used to encode a message.
 This should give users more flexibility in how to organize data
 within one or more GRIB2 messages.
 
-To start a new GRIB2 message, call function g2_create.  G2_create 
-encodes Sections 0 and 1 at the beginning of the message.  This routine 
+To start a new GRIB2 message, call function g2_create.  G2_create
+encodes Sections 0 and 1 at the beginning of the message.  This routine
 must be used to create each message.
 
 Routine g2_addlocal can be used to add a Local Use Section ( Section 2 ).
@@ -67,7 +67,7 @@ Note that this section is optional and need not appear in a GRIB2 message.
 
 Function g2_addgrid is used to encode a grid definition into Section 3.
 This grid definition defines the geometry of the data values in the
-fields that follow it.  g2_addgrid can be called again to change the grid 
+fields that follow it.  g2_addgrid can be called again to change the grid
 definition describing subsequent data fields.
 
 Each data field is added to the GRIB2 message using routine g2_addfield,
@@ -90,16 +90,16 @@ and data fields are contained in a given GRIB2 message.  This routine also
 returns all the information stored in Sections 0 and 1 of the GRIB2
 message.
 
-g2_getfld can be used to get all information pertaining to the nth 
+g2_getfld can be used to get all information pertaining to the nth
 data field in the message.  The subroutine returns all the unpacked metadata
 for each Section and Template in a gribfield structure,
 which is defined in include file grib2.h.  An option exists that lets the
-user decide if the decoder should unpack the Bit-map ( if applicable ) 
+user decide if the decoder should unpack the Bit-map ( if applicable )
 and the data values or just return the field description information.
 
-Note that a struct gribfield is allocated by g2_getfld, and it also 
+Note that a struct gribfield is allocated by g2_getfld, and it also
 contains pointers to many arrays of data that are alloated during decoding.
-Because of this, users are encouraged to free up this memory, when it is 
+Because of this, users are encouraged to free up this memory, when it is
 no longer needed, by an explicit call to routine g2_free.
 
 Please see the "GRIB2 Routine Documentation" section below for subroutine
@@ -122,7 +122,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
     gribfield  *gfld;
     FILE   *fptr;
     size_t  lengrib;
- 
+
     iseek=0;
     unpack=1;
     expand=1;
@@ -162,7 +162,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-25
 //
 //   Each element of structure gribfield is defined as:
-//   
+//
 //   gribfield gfld;
 //
 //        gfld->version = GRIB edition number ( currently 2 )
@@ -242,7 +242,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                          This element is a pointer to an array
 //                          that holds the data.  This pointer is nullified
 //                          if gfld->numoct_opt=0.
-//        gfld->num_opt = (Used if gfld->numoct_opt .ne. 0) 
+//        gfld->num_opt = (Used if gfld->numoct_opt .ne. 0)
 //                       The number of entries
 //                       in array ideflist.  i.e. number of rows ( or columns )
 //                       for which optional grid points are defined.  This value
@@ -295,7 +295,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                     254 = Previously defined bitmap applies to this field
 //                     255 = Bit map does not apply to this product.
 //        gfld->bmap  = integer array containing decoded bitmap,
-//                      if gfld->ibmap=0 or gfld->ibap=254.  
+//                      if gfld->ibmap=0 or gfld->ibap=254.
 //                      Otherwise nullified.
 //                      This element is a pointer to an array
 //                      that holds the data.
@@ -312,7 +312,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //   PRGMMR: Gilbert          ORG: W/NP11      DATE: 2002-10-28
 //
 // ABSTRACT: This subprogram searches a file for the next GRIB Message.
-//   The search is done starting at byte offset iseek of the file referenced 
+//   The search is done starting at byte offset iseek of the file referenced
 //   by lugb for mseek bytes at a time.
 //   If found, the starting position and length of the message are returned
 //   in lskip and lgrib, respectively.
@@ -341,7 +341,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK  ///////////////////////////////////
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_info 
+// SUBPROGRAM:    g2_info
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-28
 //
 // ABSTRACT: This subroutine searches through a GRIB2 message and
@@ -358,21 +358,21 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //   INPUT ARGUMENT:
 //     cgrib    - Character pointer to the GRIB2 message
 //
-//   OUTPUT ARGUMENTS:      
-//     listsec0 - pointer to an array containing information decoded from 
+//   OUTPUT ARGUMENTS:
+//     listsec0 - pointer to an array containing information decoded from
 //                GRIB Indicator Section 0.
 //                Must be allocated with >= 3 elements.
 //                listsec0[0]=Discipline-GRIB Master Table Number
 //                            (see Code Table 0.0)
 //                listsec0[1]=GRIB Edition Number (currently 2)
 //                listsec0[2]=Length of GRIB message
-//     listsec1 - pointer to an array containing information read from GRIB 
+//     listsec1 - pointer to an array containing information read from GRIB
 //                Identification Section 1.
 //                Must be allocated with >= 13 elements.
 //                listsec1[0]=Id of originating centre (Common Code Table C-1)
 //                listsec1[1]=Id of originating sub-centre (local table)
 //                listsec1[2]=GRIB Master Tables Version Number (Code Table 1.0)
-//                listsec1[3]=GRIB Local Tables Version Number 
+//                listsec1[3]=GRIB Local Tables Version Number
 //                listsec1[4]=Significance of Reference Time (Code Table 1.1)
 //                listsec1[5]=Reference Time - Year (4 digits)
 //                listsec1[6]=Reference Time - Month
@@ -384,7 +384,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                listsec1[12]=Type of processed data (Code Table 1.3)
 //     numfields- The number of gridded fields found in the GRIB message.
 //                That is, the number of occurrences of Sections 4 - 7.
-//     numlocal - The number of Local Use Sections ( Section 2 ) found in 
+//     numlocal - The number of Local Use Sections ( Section 2 ) found in
 //                the GRIB message.
 //
 //     RETURN VALUES:
@@ -401,7 +401,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //////////////////////////////////////////////////////////////////////////
 
@@ -409,10 +409,10 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK  ///////////////////////////////////
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_getfld 
+// SUBPROGRAM:    g2_getfld
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-28
 //
-// ABSTRACT: This subroutine returns all the metadata, template values, 
+// ABSTRACT: This subroutine returns all the metadata, template values,
 //   Bit-map ( if applicable ), and the unpacked data for a given data
 //   field.  All of the information returned is stored in a gribfield
 //   structure, which is defined in file grib2.h.
@@ -446,10 +446,10 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                This argument is ignored if unpack == 0 OR if the
 //                returned field does not contain a bit-map.
 //
-//   OUTPUT ARGUMENT:      
+//   OUTPUT ARGUMENT:
 //     gribfield gfld; - pointer to structure gribfield containing
 //                       all decoded data for the data field.
-// 
+//
 //        gfld->version = GRIB edition number ( currently 2 )
 //        gfld->discipline = Message Discipline ( see Code Table 0.0 )
 //        gfld->idsect = Contains the entries in the Identification
@@ -527,7 +527,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                          This element is a pointer to an array
 //                          that holds the data.  This pointer is nullified
 //                          if gfld->numoct_opt=0.
-//        gfld->num_opt = (Used if gfld->numoct_opt .ne. 0) 
+//        gfld->num_opt = (Used if gfld->numoct_opt .ne. 0)
 //                        The number of entries
 //                       in array ideflist.  i.e. number of rows ( or columns )
 //                       for which optional grid points are defined.  This value
@@ -587,7 +587,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                     This element is a pointer to an array
 //                     that holds the data.
 //
-// 
+//
 //   RETURN VALUES:
 //     ierr     - Error return code.
 //                0 = no error
@@ -610,7 +610,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //
 // REMARKS: Note that struct gribfield is allocated by this routine and it
 //          also contains pointers to many arrays of data that were allocated
-//          during decoding.  Users are encouraged to free up this memory, 
+//          during decoding.  Users are encouraged to free up this memory,
 //          when it is no longer needed, by an explicit call to routine g2_free.
 //          EXAMPLE:
 //              #include "grib2.h"
@@ -631,7 +631,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 ///////////////////////////////////////////////////////////////////////////
 
@@ -639,13 +639,13 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_create 
+// SUBPROGRAM:    g2_create
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This routine initializes a new GRIB2 message and packs
 //   GRIB2 sections 0 (Indicator Section) and 1 (Identification Section).
-//   This routine is used with routines "g2_addlocal", "g2_addgrid", 
-//   "g2_addfield", and "g2_gribend" to create a complete GRIB2 message.  
+//   This routine is used with routines "g2_addlocal", "g2_addgrid",
+//   "g2_addfield", and "g2_gribend" to create a complete GRIB2 message.
 //   g2_create must be called first to initialize a new GRIB2 message.
 //   Also, a call to g2_gribend is required to complete GRIB2 message
 //   after all fields have been added.
@@ -663,8 +663,8 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                listsec0[1]=GRIB Edition Number (currently 2)
 //     listsec1 - Contains information needed for GRIB Identification Section 1.
 //                Must be dimensioned >= 13.
-//                listsec1[0]=Id of orginating centre (Common Code Table C-1)
-//                listsec1[1]=Id of orginating sub-centre (local table)
+//                listsec1[0]=Id of originating centre (Common Code Table C-1)
+//                listsec1[1]=Id of originating sub-centre (local table)
 //                listsec1[2]=GRIB Master Tables Version Number (Code Table 1.0)
 //                listsec1[3]=GRIB Local Tables Version Number (Code Table 1.1)
 //                listsec1[4]=Significance of Reference Time (Code Table 1.2)
@@ -677,7 +677,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                listsec1[11]=Production status of data (Code Table 1.3)
 //                listsec1[12]=Type of processed data (Code Table 1.4)
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     cgrib    - Char array to contain the new GRIB2 message.
 //                Must be allocated large enough to store the entire
 //                GRIB2 message.
@@ -687,13 +687,13 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //              > 0 = Current size of new GRIB2 message
 //               -1 = Tried to use for version other than GRIB Edition 2
 //
-// REMARKS: This routine is intended for use with routines "g2_addlocal", 
-//          "g2_addgrid", "g2_addfield", and "g2_gribend" to create a complete 
+// REMARKS: This routine is intended for use with routines "g2_addlocal",
+//          "g2_addgrid", "g2_addfield", and "g2_gribend" to create a complete
 //          GRIB2 message.
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 
@@ -701,13 +701,13 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_addlocal 
+// SUBPROGRAM:    g2_addlocal
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-11-01
 //
-// ABSTRACT: This routine adds a Local Use Section (Section 2) to 
-//   a GRIB2 message.  It is used with routines "g2_create", 
+// ABSTRACT: This routine adds a Local Use Section (Section 2) to
+//   a GRIB2 message.  It is used with routines "g2_create",
 //   "g2_addgrid", "g2_addfield",
-//   and "g2_gribend" to create a complete GRIB2 message.  
+//   and "g2_gribend" to create a complete GRIB2 message.
 //   g2_create must be called first to initialize a new GRIB2 message.
 //
 // PROGRAM HISTORY LOG:
@@ -723,7 +723,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //     lcsec2   - Number of bytes of character array csec2 to be added to
 //                Section 2.
 //
-//   OUTPUT ARGUMENT:      
+//   OUTPUT ARGUMENT:
 //     cgrib    - Char array to contain the updated GRIB2 message.
 //                Must be allocated large enough to store the entire
 //                GRIB2 message.
@@ -742,7 +742,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE: 
+//   MACHINE:
 //
 //$$$
 
@@ -750,10 +750,10 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_addgrid 
+// SUBPROGRAM:    g2_addgrid
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-11-01
 //
-// ABSTRACT: This routine packs up a Grid Definition Section (Section 3) 
+// ABSTRACT: This routine packs up a Grid Definition Section (Section 3)
 //   and adds it to a GRIB2 message.  It is used with routines "g2_create",
 //   "g2_addlocal", "g2_addfield",
 //   and "g2_gribend" to create a complete GRIB2 message.
@@ -771,17 +771,17 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                Must be dimensioned >= 5.
 //                igds[0]=Source of grid definition (see Code Table 3.0)
 //                igds[1]=Number of grid points in the defined grid.
-//                igds[2]=Number of octets needed for each 
-//                            additional grid points definition.  
+//                igds[2]=Number of octets needed for each
+//                            additional grid points definition.
 //                            Used to define number of
 //                            points in each row ( or column ) for
-//                            non-regular grids.  
+//                            non-regular grids.
 //                            = 0, if using regular grid.
-//                igds[3]=Interpretation of list for optional points 
+//                igds[3]=Interpretation of list for optional points
 //                            definition.  (Code Table 3.11)
 //                igds[4]=Grid Definition Template Number (Code Table 3.1)
 //     igdstmpl - Contains the data values for the specified Grid Definition
-//                Template ( NN=igds[4] ).  Each element of this integer 
+//                Template ( NN=igds[4] ).  Each element of this integer
 //                array contains an entry (in the order specified) of Grid
 //                Definition Template 3.NN
 //     ideflist - (Used if igds[2] != 0)  This array contains the
@@ -790,7 +790,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                in array ideflist.  i.e. number of rows ( or columns )
 //                for which optional grid points are defined.
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     cgrib    - Char array to contain the updated GRIB2 message.
 //                Must be allocated large enough to store the entire
 //                GRIB2 message.
@@ -810,7 +810,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 
@@ -818,19 +818,19 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_addfield 
+// SUBPROGRAM:    g2_addfield
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-11-05
 //
 // ABSTRACT: This routine packs up Sections 4 through 7 for a given field
 //   and adds them to a GRIB2 message.  They are Product Definition Section,
-//   Data Representation Section, Bit-Map Section and Data Section, 
+//   Data Representation Section, Bit-Map Section and Data Section,
 //   respectively.
-//   This routine is used with routines "g2_create", "g2_addlocal", 
-//   "g2_addgrid", and "g2_gribend" to create a complete GRIB2 message.  
+//   This routine is used with routines "g2_create", "g2_addlocal",
+//   "g2_addgrid", and "g2_gribend" to create a complete GRIB2 message.
 //   g2_create must be called first to initialize a new GRIB2 message.
 //   Also, routine g2_addgrid must be called after g2_create and
 //   before this routine to add the appropriate grid description to
-//   the GRIB2 message.   Also, a call to g2_gribend is required to complete 
+//   the GRIB2 message.   Also, a call to g2_gribend is required to complete
 //   GRIB2 message after all fields have been added.
 //
 // PROGRAM HISTORY LOG:
@@ -844,7 +844,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                4 through 7 should be added.
 //     ipdsnum  - Product Definition Template Number ( see Code Table 4.0)
 //     ipdstmpl - Contains the data values for the specified Product Definition
-//                Template ( N=ipdsnum ).  Each element of this integer 
+//                Template ( N=ipdsnum ).  Each element of this integer
 //                array contains an entry (in the order specified) of Product
 //                Definition Template 4.N
 //     coordlist- Array containing floating point values intended to document
@@ -853,7 +853,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //     numcoord - number of values in array coordlist.
 //     idrsnum  - Data Representation Template Number ( see Code Table 5.0 )
 //     idrstmpl - Contains the data values for the specified Data Representation
-//                Template ( N=idrsnum ).  Each element of this integer 
+//                Template ( N=idrsnum ).  Each element of this integer
 //                array contains an entry (in the order specified) of Data
 //                Representation Template 5.N
 //                Note that some values in this template (eg. reference
@@ -871,7 +871,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                255 = Bit map does not apply to this product.
 //     bmap[]   - Integer array containing bitmap to be added. ( if ibmap=0 )
 //
-//   OUTPUT ARGUMENT LIST:      
+//   OUTPUT ARGUMENT LIST:
 //     cgrib    - Character array to contain the updated GRIB2 message.
 //                Must be allocated large enough to store the entire
 //                GRIB2 message.
@@ -895,7 +895,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 
@@ -903,14 +903,14 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    g2_gribend 
+// SUBPROGRAM:    g2_gribend
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-31
 //
 // ABSTRACT: This routine finalizes a GRIB2 message after all grids
 //   and fields have been added.  It adds the End Section ( "7777" )
 //   to the end of the GRIB message and calculates the length and stores
 //   it in the appropriate place in Section 0.
-//   This routine is used with routines "g2_create", "g2_addlocal", 
+//   This routine is used with routines "g2_create", "g2_addlocal",
 //   "g2_addgrid", and "g2_addfield" to create a complete GRIB2 message.
 //   g2_create must be called first to initialize a new GRIB2 message.
 //
@@ -923,7 +923,7 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //                be previous calls to g2_create, g2_addlocal, g2_addgrid,
 //                and g2_addfield.
 //
-//   OUTPUT ARGUMENTS:      
+//   OUTPUT ARGUMENTS:
 //     cgrib    - Char array containing the finalized GRIB2 message
 //
 //   RETURN VALUES:
@@ -931,12 +931,12 @@ all the GRIB2 fields in a file.  This is illustrated by the following example:
 //              > 0 = Length of the final GRIB2 message in bytes.
 //               -1 = GRIB message was not initialized.  Need to call
 //                    routine g2_create first.
-//               -2 = GRIB message already complete.  
+//               -2 = GRIB message already complete.
 //               -3 = Sum of Section byte counts doesn't add to total byte count
 //               -4 = Previous Section was not 7.
 //
-// REMARKS: This routine is intended for use with routines "g2_create", 
-//          "g2_addlocal", "g2_addgrid", and "g2_addfield" to create a complete 
+// REMARKS: This routine is intended for use with routines "g2_create",
+//          "g2_addlocal", "g2_addgrid", and "g2_addfield" to create a complete
 //          GRIB2 message.
 //
 // ATTRIBUTES:
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c b/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c
index 3940f94..9d1be4d 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.c
@@ -105,10 +105,10 @@ g2int getgridindex(g2int number)
 xxtemplate *getgridtemplate(g2int number)
 /*!$$$  SUBPROGRAM DOCUMENTATION BLOCK
 !                .      .    .                                       .
-! SUBPROGRAM:    getgridtemplate 
+! SUBPROGRAM:    getgridtemplate
 !   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-09
 !
-! ABSTRACT: This subroutine returns grid template information for a 
+! ABSTRACT: This subroutine returns grid template information for a
 !   specified Grid Definition Template 3.NN.
 !   The number of entries in the template is returned along with a map
 !   of the number of octets occupied by each entry.  Also, a flag is
@@ -119,7 +119,7 @@ xxtemplate *getgridtemplate(g2int number)
 !
 ! USAGE:    template *getgridtemplate(number)
 !   INPUT ARGUMENT LIST:
-!     number   - NN, indicating the number of the Grid Definition 
+!     number   - NN, indicating the number of the Grid Definition
 !                Template 3.NN that is being requested.
 !
 !   RETURN VALUE:
@@ -162,12 +162,12 @@ xxtemplate *getgridtemplate(g2int number)
 xxtemplate *extgridtemplate(g2int number,g2int *list)
 /*!$$$  SUBPROGRAM DOCUMENTATION BLOCK
 !                .      .    .                                       .
-! SUBPROGRAM:    extgridtemplate 
+! SUBPROGRAM:    extgridtemplate
 !   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-09
 !
-! ABSTRACT: This subroutine generates the remaining octet map for a 
-!   given Grid Definition Template, if required.  Some Templates can 
-!   vary depending on data values given in an earlier part of the 
+! ABSTRACT: This subroutine generates the remaining octet map for a
+!   given Grid Definition Template, if required.  Some Templates can
+!   vary depending on data values given in an earlier part of the
 !   Template, and it is necessary to know some of the earlier entry
 !   values to generate the full octet map of the Template.
 !
@@ -176,9 +176,9 @@ xxtemplate *extgridtemplate(g2int number,g2int *list)
 !
 ! USAGE:    CALL extgridtemplate(number,list)
 !   INPUT ARGUMENT LIST:
-!     number   - NN, indicating the number of the Grid Definition 
+!     number   - NN, indicating the number of the Grid Definition
 !                Template 3.NN that is being requested.
-!     list()   - The list of values for each entry in 
+!     list()   - The list of values for each entry in
 !                the Grid Definition Template.
 !
 !   RETURN VALUE:
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h b/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h
index ba4ebef..e8ff125 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h
+++ b/frmts/grib/degrib18/g2clib-1.0.4/gridtemplates.h
@@ -4,7 +4,7 @@
 
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2001-10-26
 //
-// ABSTRACT: This Fortran Module contains info on all the available 
+// ABSTRACT: This Fortran Module contains info on all the available
 //   GRIB2 Grid Definition Templates used in Section 3 (GDS).
 //   The information describing each template is stored in the
 //   gridtemplate structure defined below.
@@ -12,12 +12,12 @@
 //   Each Template has three parts: The number of entries in the template
 //   (mapgridlen);  A map of the template (mapgrid), which contains the
 //   number of octets in which to pack each of the template values; and
-//   a logical value (needext) that indicates whether the Template needs 
-//   to be extended.  In some cases the number of entries in a template 
-//   can vary depending upon values specified in the "static" part of 
+//   a logical value (needext) that indicates whether the Template needs
+//   to be extended.  In some cases the number of entries in a template
+//   can vary depending upon values specified in the "static" part of
 //   the template.  ( See Template 3.120 as an example )
 //
-//   NOTE:  Array mapgrid contains the number of octets in which the 
+//   NOTE:  Array mapgrid contains the number of octets in which the
 //   corresponding template values will be stored.  A negative value in
 //   mapgrid is used to indicate that the corresponding template entry can
 //   contain negative values.  This information is used later when packing
@@ -25,9 +25,9 @@
 //   are stored with the left most bit set to one, and a negative number
 //   of octets value in mapgrid[] indicates that this possibility should
 //   be considered.  The number of octets used to store the data value
-//   in this case would be the absolute value of the negative value in 
+//   in this case would be the absolute value of the negative value in
 //   mapgrid[].
-//  
+//
 //
 ////////////////////////////////////////////////////////////////////
 
@@ -42,7 +42,6 @@
           g2int mapgrid[MAXGRIDMAPLEN];
       };
 
-
 const struct gridtemplate *get_templatesgrid(void);
 g2int getgridindex(g2int number);
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c b/frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c
index b55e3af..a81e6df 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/jpcpack.c
@@ -12,7 +12,7 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
 // ABSTRACT: This subroutine packs up a data field into a JPEG2000 code stream.
 //   After the data field is scaled, and the reference value is subtracted out,
 //   it is treated as a grayscale image and passed to a JPEG2000 encoder.
-//   It also fills in GRIB2 Data Representation Template 5.40 or 5.40000 with 
+//   It also fills in GRIB2 Data Representation Template 5.40 or 5.40000 with
 //   the appropriate values.
 //
 // PROGRAM HISTORY LOG:
@@ -45,7 +45,7 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
 //                      Set to 255, if idrstmpl[5]=0.
 //     lcpack   - size of array cpack[]
 //
-//   OUTPUT ARGUMENT LIST: 
+//   OUTPUT ARGUMENT LIST:
 //     idrstmpl - Contains the array of values for Data Representation
 //                Template 5.0
 //                [0] = Reference value - set by jpcpack routine.
@@ -57,7 +57,7 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
 //                [5] = 0 - use lossless compression
 //                    = 1 - use lossy compression
 //                [6] = Desired compression ratio, if idrstmpl[5]=1
-//     cpack    - The packed data field 
+//     cpack    - The packed data field
 //     lcpack   - length of packed field in cpack.
 //
 // REMARKS: None
@@ -69,16 +69,16 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
 //$$$
 {
       g2int  *ifld;
-      const g2float alog2=0.69314718;       //  ln(2.0)
+      const g2float alog2=0.69314718f;       //  ln(2.0)
       g2int  j,nbits,imin,imax,maxdif;
       g2int  ndpts,nbytes,nsize,retry;
       g2float  bscale,dscale,rmax,rmin,temp;
       unsigned char *ctemp;
-      
+
       ifld=0;
       ndpts=width*height;
-      bscale=int_power(2.0,-idrstmpl[1]);
-      dscale=int_power(10.0,idrstmpl[2]);
+      bscale=(float)int_power(2.0,-idrstmpl[1]);
+      dscale=(float)int_power(10.0,idrstmpl[2]);
 //
 //  Find max and min values in the data
 //
@@ -88,7 +88,7 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
         if (fld[j] > rmax) rmax=fld[j];
         if (fld[j] < rmin) rmin=fld[j];
       }
-      if (idrstmpl[1] == 0) 
+      if (idrstmpl[1] == 0)
          maxdif = (g2int) (RINT(rmax*dscale) - RINT(rmin*dscale));
       else
          maxdif = (g2int)RINT( (rmax-rmin)*dscale*bscale );
@@ -101,7 +101,7 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
       if ( rmin != rmax  &&  maxdif != 0 ) {
         ifld=(g2int *)malloc(ndpts*sizeof(g2int));
         //
-        //  Determine which algorithm to use based on user-supplied 
+        //  Determine which algorithm to use based on user-supplied
         //  binary scale factor and number of bits.
         //
         if (idrstmpl[1] == 0) {
@@ -112,7 +112,7 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
            imin=(g2int)RINT(rmin*dscale);
            imax=(g2int)RINT(rmax*dscale);
            maxdif=imax-imin;
-           temp=log((double)(maxdif+1))/alog2;
+           temp=(float)(log((double)(maxdif+1))/alog2);
            nbits=(g2int)ceil(temp);
            rmin=(g2float)imin;
            //   scale data
@@ -121,13 +121,13 @@ void jpcpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
         }
         else {
            //
-           //  Use binary scaling factor and calculate minimum number of 
+           //  Use binary scaling factor and calculate minimum number of
            //  bits in which the data will fit.
            //
            rmin=rmin*dscale;
            rmax=rmax*dscale;
            maxdif=(g2int)RINT((rmax-rmin)*bscale);
-           temp=log((double)(maxdif+1))/alog2;
+           temp=(float)(log((double)(maxdif+1))/alog2);
            nbits=(g2int)ceil(temp);
            //   scale data
            for (j=0;j<ndpts;j++)
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c
index 006652f..4df9ec7 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/jpcunpack.c
@@ -2,8 +2,6 @@
 #include <stdlib.h>
 #include "grib2.h"
 
-   int dec_jpeg2000(char *,g2int ,g2int *);
-
 g2int jpcunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
                 g2float *fld)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
@@ -44,8 +42,8 @@ g2int jpcunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
       g2float  ref,bscale,dscale;
 
       rdieee(idrstmpl+0,&ref,1);
-      bscale = int_power(2.0,idrstmpl[1]);
-      dscale = int_power(10.0,-idrstmpl[2]);
+      bscale = (float)int_power(2.0,idrstmpl[1]);
+      dscale = (float)int_power(10.0,-idrstmpl[2]);
       nbits = idrstmpl[3];
 //
 //  if nbits equals 0, we have a constant field where the reference value
@@ -59,7 +57,7 @@ g2int jpcunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
                     "Data field NOT unpacked.\n");
             return(1);
          }
-         /* iret= (g2int) */ dec_jpeg2000((char *) cpack,len,ifld);
+         /* iret= (g2int) */ dec_jpeg2000(cpack,len,ifld,ndpts);
          for (j=0;j<ndpts;j++) {
            fld[j]=(((g2float)ifld[j]*bscale)+ref)*dscale;
          }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/makefile.vc b/frmts/grib/degrib18/g2clib-1.0.4/makefile.vc
index 43be202..4131ac7 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/makefile.vc
+++ b/frmts/grib/degrib18/g2clib-1.0.4/makefile.vc
@@ -8,10 +8,6 @@ GDAL_ROOT       =       ..\..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-!IFDEF JASPER_DIR
-EXTRAFLAGS = $(EXTRAFLAGS) $(JASPER_INCLUDE) -DHAVE_JASPER
-!ENDIF
-
 default: $(OBJ)
         xcopy /D /Y *.obj ..\..\..\o
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/misspack.c b/frmts/grib/degrib18/g2clib-1.0.4/misspack.c
index 1b5b754..c5f0cd2 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/misspack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/misspack.c
@@ -13,7 +13,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //   packing algorithm as defined in the GRIB2 documentation.  It
 //   supports GRIB2 complex packing templates with or without
 //   spatial differences (i.e. DRTs 5.2 and 5.3).
-//   It also fills in GRIB2 Data Representation Template 5.2 or 5.3 
+//   It also fills in GRIB2 Data Representation Template 5.2 or 5.3
 //   with the appropriate values.
 //   This version assumes that Missing Value Management is being used and that
 //   1 or 2 missing values appear in the data.
@@ -44,7 +44,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //                    .
 //                    .
 //
-//   OUTPUT ARGUMENT LIST: 
+//   OUTPUT ARGUMENT LIST:
 //     idrstmpl - Contains the array of values for Data Representation
 //                Template 5.3
 //                [0] = Reference value - set by misspack routine.
@@ -59,7 +59,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 {
@@ -78,11 +78,11 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
       g2int  kfildo, minpk, inc, maxgrps, ibit, jbit, kbit, novref, lbitref;
       g2float  rmissp, rmisss, bscale, dscale, rmin, temp;
       const g2int simple_alg = 0;
-      const g2float alog2=0.69314718;       //  ln(2.0)
+      const g2float alog2=0.69314718f;       //  ln(2.0)
       const g2int one=1;
 
-      bscale=int_power(2.0,-idrstmpl[1]);
-      dscale=int_power(10.0,idrstmpl[2]);
+      bscale=(float)int_power(2.0,-idrstmpl[1]);
+      dscale=(float)int_power(10.0,idrstmpl[2]);
       missopt=idrstmpl[6];
       if ( missopt != 1 && missopt != 2 ) {
          printf("misspack: Unrecognized option.\n");
@@ -98,7 +98,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
 //  AND set up missing value mapping of the field.
 //
       ifldmiss = calloc(ndpts,sizeof(g2int));
-      rmin=1E+37;
+      rmin=1E+37f;
       if ( missopt ==  1 ) {        // Primary missing value only
          for ( j=0; j<ndpts; j++) {
            if (fld[j] == rmissp) {
@@ -126,10 +126,10 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
       }
 //
 //  Allocate work arrays:
-//  Note: -ifldmiss[j],j=0,ndpts-1 is a map of original field indicating 
+//  Note: -ifldmiss[j],j=0,ndpts-1 is a map of original field indicating
 //         which of the original data values
 //         are primary missing (1), secondary missing (2) or non-missing (0).
-//        -jfld[j],j=0,nonmiss-1 is a subarray of just the non-missing values 
+//        -jfld[j],j=0,nonmiss-1 is a subarray of just the non-missing values
 //         from the original field.
 //
       //if (rmin != rmax) {
@@ -194,7 +194,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            //   find num of bits need to store minsd and add 1 extra bit
            //   to indicate sign
            //
-           temp=log((double)(abs(minsd)+1))/alog2;
+           temp=(float)(log((double)(abs(minsd)+1))/alog2);
            nbitsd=(g2int)ceil(temp)+1;
            //
            //   find num of bits need to store ifld[0] ( and ifld[1]
@@ -202,7 +202,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            //
            maxorig=ival1;
            if (idrstmpl[16]==2 && ival2>ival1) maxorig=ival2;
-           temp=log((double)(maxorig+1))/alog2;
+           temp=(float)(log((double)(maxorig+1))/alog2);
            nbitorig=(g2int)ceil(temp)+1;
            if (nbitorig > nbitsd) nbitsd=nbitorig;
            //   increase number of bits to even multiple of 8 ( octet )
@@ -306,7 +306,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            free(jmax);
            free(lbit);
         }
-        //  
+        //
         //  For each group, find the group's reference value (min)
         //  and the number of bits needed to hold the remaining values
         //
@@ -341,7 +341,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
              for ( lg=0; lg<glen[ng]; lg++ ) {
                 if ( ifldmiss[j] == 0 ) {
                   if (ifld[j] < gref[ng]) gref[ng]=ifld[j];
-                  if (ifld[j] > imax) imax=ifld[j]; 
+                  if (ifld[j] > imax) imax=ifld[j];
                 }
                 j++;
              }
@@ -349,7 +349,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
              if (missopt == 2) imax=imax+2;
              //   calc num of bits needed to hold data
              if ( gref[ng] != imax ) {
-                temp=log((double)(imax-gref[ng]+1))/alog2;
+                temp=(float)(log((double)(imax-gref[ng]+1))/alog2);
                 gwidth[ng]=(g2int)ceil(temp);
              }
              else {
@@ -366,14 +366,14 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
                  ifld[j]=mtemp-1;
               else if (ifldmiss[j] == 2)         // secondary missing
                  ifld[j]=mtemp-2;
-              
+
               j++;
            }
            //   increment fld array counter
            n=n+glen[ng];
         }
-        //  
-        //  Find max of the group references and calc num of bits needed 
+        //
+        //  Find max of the group references and calc num of bits needed
         //  to pack each groups reference value, then
         //  pack up group reference values
         //
@@ -384,7 +384,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
         if (missopt == 1) igmax=igmax+1;
         if (missopt == 2) igmax=igmax+2;
         if (igmax != 0) {
-           temp=log((double)(igmax+1))/alog2;
+           temp=(float)(log((double)(igmax+1))/alog2);
            nbitsgref=(g2int)ceil(temp);
            // reset the ref values of any "missing only" groups.
            mtemp=(g2int)int_power(2.,nbitsgref);
@@ -418,7 +418,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
            if (gwidth[j] < ngwidthref) ngwidthref=gwidth[j];
         }
         if (iwmax != ngwidthref) {
-           temp=log((double)(iwmax-ngwidthref+1))/alog2;
+           temp=(float)(log((double)(iwmax-ngwidthref+1))/alog2);
            nbitsgwidth=(g2int)ceil(temp);
            for ( i=0; i<ngroups; i++) gwidth[i]=gwidth[i]-ngwidthref;
            sbits(cpack,gwidth,iofst,nbitsgwidth,0,ngroups);
@@ -450,7 +450,7 @@ void misspack(g2float *fld,g2int ndpts,g2int idrsnum,g2int *idrstmpl,
         }
         nglenlast=glen[ngroups-1];
         if (ilmax != nglenref) {
-           temp=log((double)(ilmax-nglenref+1))/alog2;
+           temp=(float)(log((double)(ilmax-nglenref+1))/alog2);
            nbitsglen=(g2int)ceil(temp);
            for ( i=0; i<ngroups-1; i++) glen[i]=glen[i]-nglenref;
            sbits(cpack,glen,iofst,nbitsglen,0,ngroups);
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/mkieee.c b/frmts/grib/degrib18/g2clib-1.0.4/mkieee.c
index f0931a2..82c58d6 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/mkieee.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/mkieee.c
@@ -6,10 +6,10 @@
 void mkieee(g2float *a,g2int *rieee,g2int num)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    mkieee 
+// SUBPROGRAM:    mkieee
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-29
 //
-// ABSTRACT: This subroutine stores a list of real values in 
+// ABSTRACT: This subroutine stores a list of real values in
 //   32-bit IEEE floating point format.
 //
 // PROGRAM HISTORY LOG:
@@ -20,7 +20,7 @@ void mkieee(g2float *a,g2int *rieee,g2int num)
 //     a        - Input array of floating point values.
 //     num      - Number of floating point values to convert.
 //
-//   OUTPUT ARGUMENT LIST:      
+//   OUTPUT ARGUMENT LIST:
 //     rieee    - Output array of data values in 32-bit IEEE format
 //                stored in g2int integer array.  rieee must be allocated
 //                with at least 4*num bytes of memory before calling this
@@ -30,7 +30,7 @@ void mkieee(g2float *a,g2int *rieee,g2int num)
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 {
@@ -53,14 +53,14 @@ void mkieee(g2float *a,g2int *rieee,g2int num)
       // alog2=0.69314718;       //  ln(2.0)
 
       for (j=0;j<num;j++) {
-      
+
         ieee=0;
 
         if (a[j] == 0.0) {
           rieee[j]=ieee;
           continue;
         }
-        
+
 //
 //  Set Sign bit (bit 31 - leftmost bit)
 //
@@ -97,9 +97,9 @@ void mkieee(g2float *a,g2int *rieee,g2int num)
         ieee = ieee | ( iexp << 23 );
 //
 //  Determine Mantissa
-// 
+//
         if (iexp != 255) {
-          if (iexp != 0) 
+          if (iexp != 0)
             atemp=(atemp/int_power(2.0,n))-1.0;
           else
             atemp=atemp*two126;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c b/frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c
index 969de58..95bdf6c 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pack_gp.c
@@ -17,9 +17,9 @@ typedef g2int logical;
 #define TRUE_ (1)
 #define FALSE_ (0)
 
-/* Subroutine */ int pack_gp(integer *kfildo, integer *ic, integer *nxy, 
-	integer *is523, integer *minpk, integer *inc, integer *missp, integer 
-	*misss, integer *jmin, integer *jmax, integer *lbit, integer *nov, 
+/* Subroutine */ int pack_gp(integer *kfildo, integer *ic, integer *nxy,
+	integer *is523, integer *minpk, integer *inc, integer *missp, integer
+	*misss, integer *jmin, integer *jmax, integer *lbit, integer *nov,
 	integer *ndg, integer *lx, integer *ibit, integer *jbit, integer *
 	kbit, integer *novref, integer *lbitref, integer *ier)
 {
@@ -37,13 +37,13 @@ typedef g2int logical;
     static logical adda;
     static integer ired, kinc, mina, maxa, minb, maxb, minc, maxc, ibxx2[31];
     static char cfeed[1];
-    static integer nenda, nendb, ibita, ibitb, minak, minbk, maxak, maxbk, 
+    static integer nenda, nendb, ibita, ibitb, minak, minbk, maxak, maxbk,
 	    minck, maxck, nouta, lmiss, itest, nount;
-    extern /* Subroutine */ int reduce(integer *, integer *, integer *, 
-	    integer *, integer *, integer *, integer *, integer *, integer *, 
+    extern /* Subroutine */ int reduce(integer *, integer *, integer *,
+	    integer *, integer *, integer *, integer *, integer *, integer *,
 	    integer *, integer *, integer *, integer *);
-    static integer ibitbs, mislla, misllb, misllc, iersav, lminpk, ktotal, 
-	    kounta, kountb, kstart, mstart, mintst, maxtst, 
+    static integer ibitbs, mislla, misllb, misllc, iersav, lminpk, ktotal,
+	    kounta, kountb, kstart, mstart, mintst, maxtst,
 	    kounts, mintstk, maxtstk;
     integer *misslx;
 
@@ -455,7 +455,8 @@ L105:
 
 		if (ic[k] != ic[kstart]) {
 /* Computing MAX */
-		    i__2 = nenda, i__3 = k - 1;
+		    i__2 = nenda;
+            i__3 = k - 1;
 		    /*nenda = max(i__2,i__3);*/
 		    nenda = (i__2 > i__3) ? i__2 : i__3;
 		    goto L114;
@@ -477,7 +478,8 @@ L105:
 
 		    if (ic[k] != ic[kstart]) {
 /* Computing MAX */
-			i__2 = nenda, i__3 = k - 1;
+			i__2 = nenda;
+            i__3 = k - 1;
 			/*nenda = max(i__2,i__3);*/
 			nenda = (i__2 > i__3) ? i__2 : i__3;
 			goto L114;
@@ -501,7 +503,8 @@ L105:
 
 		    if (ic[k] != ic[kstart]) {
 /* Computing MAX */
-			i__2 = nenda, i__3 = k - 1;
+			i__2 = nenda;
+            i__3 = k - 1;
 			/*nenda = max(i__2,i__3);*/
 			nenda = (i__2 > i__3) ? i__2 : i__3;
 			goto L114;
@@ -672,7 +675,8 @@ L150:
 /* Computing MIN */
     i__3 = ktotal + lminpk;
     /*i__1 = nendb, i__2 = min(i__3,*nxy);*/
-    i__1 = nendb, i__2 = (i__3 < *nxy) ? i__3 : *nxy;
+    i__1 = nendb;
+    i__2 = (i__3 < *nxy) ? i__3 : *nxy;
     /*nendb = max(i__1,i__2);*/
     nendb = (i__1 > i__2) ? i__1 : i__2;
 /* **** 150  NENDB=MIN(KTOTAL+LMINPK,NXY) */
@@ -1413,7 +1417,7 @@ L420:
 /*        FOR SPACE EFFICIENCY. */
 
     if (ired == 0) {
-	reduce(kfildo, &jmin[1], &jmax[1], &lbit[1], &nov[1], lx, ndg, ibit, 
+	reduce(kfildo, &jmin[1], &jmax[1], &lbit[1], &nov[1], lx, ndg, ibit,
 		jbit, kbit, novref, ibxx2, ier);
 
 	if (*ier == 714 || *ier == 715) {
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c b/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c
index e0ce6af..2f52fe8 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.c
@@ -49,6 +49,11 @@ static const struct pdstemplate templatespds[MAXPDSTEMP] = {
              // 4.14: Derived Fcst based on Ensemble cluster over circular
              //       area at Horiz Level/Layer in a time interval
          {14,44,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1,1,1,1,1,-4,4,4,1,-1,4,-1,4,2,1,1,1,1,1,1,4,1,1,1,4,1,4} },
+
+             // 4.15: Average, Accumulation, Extreme values or Other statistically-processed values over
+            // values over a spatial area at horizontal level or in a horizontal layer at a point in time
+         {15,18,0, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1} },
+
              // 4.20: Radar Product
          {20,19,0, {1,1,1,1,1,-4,4,2,4,2,1,1,1,1,1,2,1,3,2} },
              // 4.30: Satellite Product
@@ -122,10 +127,10 @@ g2int getpdsindex(g2int number)
 xxtemplate *getpdstemplate(g2int number)
 ///$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    getpdstemplate 
+// SUBPROGRAM:    getpdstemplate
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-11
 //
-// ABSTRACT: This subroutine returns PDS template information for a 
+// ABSTRACT: This subroutine returns PDS template information for a
 //   specified Product Definition Template 4.NN.
 //   The number of entries in the template is returned along with a map
 //   of the number of octets occupied by each entry.  Also, a flag is
@@ -136,7 +141,7 @@ xxtemplate *getpdstemplate(g2int number)
 //
 // USAGE:    CALL getpdstemplate(number)
 //   INPUT ARGUMENT LIST:
-//     number   - NN, indicating the number of the Product Definition 
+//     number   - NN, indicating the number of the Product Definition
 //                Template 4.NN that is being requested.
 //
 //   RETURN VALUE:
@@ -174,17 +179,17 @@ xxtemplate *getpdstemplate(g2int number)
 
          return(0);        //NULL
 }
-         
-        
+
+
 xxtemplate *extpdstemplate(g2int number,g2int *list)
 ///$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    extpdstemplate 
+// SUBPROGRAM:    extpdstemplate
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-11
 //
 // ABSTRACT: This subroutine generates the remaining octet map for a
 //   given Product Definition Template, if required.  Some Templates can
-//   vary depending on data values given in an earlier part of the 
+//   vary depending on data values given in an earlier part of the
 //   Template, and it is necessary to know some of the earlier entry
 //   values to generate the full octet map of the Template.
 //
@@ -193,9 +198,9 @@ xxtemplate *extpdstemplate(g2int number,g2int *list)
 //
 // USAGE:    CALL extpdstemplate(number,list)
 //   INPUT ARGUMENT LIST:
-//     number   - NN, indicating the number of the Product Definition 
+//     number   - NN, indicating the number of the Product Definition
 //                Template 4.NN that is being requested.
-//     list()   - The list of values for each entry in the 
+//     list()   - The list of values for each entry in the
 //                the Product Definition Template 4.NN.
 //
 //   RETURN VALUE:
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h b/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h
index 3819fb2..d2a828b 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pdstemplates.h
@@ -4,7 +4,7 @@
 
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-26
 //
-// ABSTRACT: This include file contains info on all the available 
+// ABSTRACT: This include file contains info on all the available
 //   GRIB2 Product Definition Templates used in Section 4 (PDS).
 //   The information describing each template is stored in the
 //   pdstemplate structure defined below.
@@ -12,12 +12,12 @@
 //   Each Template has three parts: The number of entries in the template
 //   (mappdslen);  A map of the template (mappds), which contains the
 //   number of octets in which to pack each of the template values; and
-//   a logical value (needext) that indicates whether the Template needs 
-//   to be extended.  In some cases the number of entries in a template 
-//   can vary depending upon values specified in the "static" part of 
+//   a logical value (needext) that indicates whether the Template needs
+//   to be extended.  In some cases the number of entries in a template
+//   can vary depending upon values specified in the "static" part of
 //   the template.  ( See Template 4.3 as an example )
 //
-//   NOTE:  Array mappds contains the number of octets in which the 
+//   NOTE:  Array mappds contains the number of octets in which the
 //   corresponding template values will be stored.  A negative value in
 //   mappds is used to indicate that the corresponding template entry can
 //   contain negative values.  This information is used later when packing
@@ -25,18 +25,18 @@
 //   are stored with the left most bit set to one, and a negative number
 //   of octets value in mappds[] indicates that this possibility should
 //   be considered.  The number of octets used to store the data value
-//   in this case would be the absolute value of the negative value in 
+//   in this case would be the absolute value of the negative value in
 //   mappds[].
-//  
+//
 // 2005-12-08  Gilbert  -  Allow negative scale factors and limits for
 //                         Templates 4.5 and 4.9
 //
 //$$$
 
-      #define MAXPDSTEMP 23           // maximum number of templates
+      #define MAXPDSTEMP 24           // maximum number of templates
       #define MAXPDSMAPLEN 200        // maximum template map length
 
-      struct pdstemplate 
+      struct pdstemplate
       {
           g2int template_num;
           g2int mappdslen;
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pngpack.c b/frmts/grib/degrib18/g2clib-1.0.4/pngpack.c
index 55d158f..d5787ad 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pngpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pngpack.c
@@ -2,8 +2,6 @@
 #include <math.h>
 #include "grib2.h"
 
-int enc_png(char *,g2int ,g2int ,g2int ,char *);
-
 void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
              unsigned char *cpack,g2int *lcpack)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
@@ -14,7 +12,7 @@ void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
 // ABSTRACT: This subroutine packs up a data field into PNG image format.
 //   After the data field is scaled, and the reference value is subtracted out,
 //   it is treated as a grayscale image and passed to a PNG encoder.
-//   It also fills in GRIB2 Data Representation Template 5.41 or 5.40010 with 
+//   It also fills in GRIB2 Data Representation Template 5.41 or 5.40010 with
 //   the appropriate values.
 //
 // PROGRAM HISTORY LOG:
@@ -35,7 +33,7 @@ void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
 //                [4] = Original field type - currently ignored on input
 //                      Data values assumed to be reals.
 //
-//   OUTPUT ARGUMENT LIST: 
+//   OUTPUT ARGUMENT LIST:
 //     idrstmpl - Contains the array of values for Data Representation
 //                Template 5.41 or 5.40010
 //                [0] = Reference value - set by pngpack routine.
@@ -44,7 +42,7 @@ void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
 //                [3] = Number of bits containing each grayscale pixel value
 //                [4] = Original field type - currently set = 0 on output.
 //                      Data values assumed to be reals.
-//     cpack    - The packed data field 
+//     cpack    - The packed data field
 //     lcpack   - length of packed field cpack.
 //
 // REMARKS: None
@@ -56,16 +54,16 @@ void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
 //$$$
 {
       g2int  *ifld;
-      static g2float alog2=0.69314718;       //  ln(2.0)
+      const g2float alog2=0.69314718f;       //  ln(2.0)
       g2int  j,nbits,imin,imax,maxdif;
       g2int  ndpts,nbytes;
       g2float  bscale,dscale,rmax,rmin,temp;
       unsigned char *ctemp;
-      
+
       ifld=0;
       ndpts=width*height;
-      bscale=int_power(2.0,-idrstmpl[1]);
-      dscale=int_power(10.0,idrstmpl[2]);
+      bscale=(g2float)int_power(2.0,-idrstmpl[1]);
+      dscale=(g2float)int_power(10.0,idrstmpl[2]);
 //
 //  Find max and min values in the data
 //
@@ -85,18 +83,18 @@ void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
       if (rmin != rmax  &&  maxdif != 0 ) {
         ifld=(g2int *)malloc(ndpts*sizeof(g2int));
         //
-        //  Determine which algorithm to use based on user-supplied 
+        //  Determine which algorithm to use based on user-supplied
         //  binary scale factor and number of bits.
         //
         if (idrstmpl[1] == 0) {
            //
-           //  No binary scaling and calculate minimum number of 
+           //  No binary scaling and calculate minimum number of
            //  bits in which the data will fit.
            //
            imin=(g2int)RINT(rmin*dscale);
            imax=(g2int)RINT(rmax*dscale);
            maxdif=imax-imin;
-           temp=log((double)(maxdif+1))/alog2;
+           temp=(g2float)log((double)(maxdif+1))/alog2;
            nbits=(g2int)ceil(temp);
            rmin=(g2float)imin;
            //   scale data
@@ -105,13 +103,13 @@ void pngpack(g2float *fld,g2int width,g2int height,g2int *idrstmpl,
         }
         else {
            //
-           //  Use binary scaling factor and calculate minimum number of 
+           //  Use binary scaling factor and calculate minimum number of
            //  bits in which the data will fit.
            //
            rmin=rmin*dscale;
            rmax=rmax*dscale;
            maxdif=(g2int)RINT((rmax-rmin)*bscale);
-           temp=log((double)(maxdif+1))/alog2;
+           temp=(g2float)log((double)(maxdif+1))/alog2;
            nbits=(g2int)ceil(temp);
            //   scale data
            for (j=0;j<ndpts;j++)
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c
index 373d854..e0490a3 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/pngunpack.c
@@ -2,8 +2,6 @@
 #include <stdlib.h>
 #include "grib2.h"
 
-int dec_png(unsigned char *,g2int *,g2int *,char *);
-
 g2int pngunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
                 g2float *fld)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
@@ -11,7 +9,7 @@ g2int pngunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
 // SUBPROGRAM:    pngunpack
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2003-08-27
 //
-// ABSTRACT: This subroutine unpacks a data field that was packed into a 
+// ABSTRACT: This subroutine unpacks a data field that was packed into a
 //   PNG image format
 //   using info from the GRIB2 Data Representation Template 5.41 or 5.40010.
 //
@@ -40,38 +38,44 @@ g2int pngunpack(unsigned char *cpack,g2int len,g2int *idrstmpl,g2int ndpts,
 {
 
       g2int  *ifld;
-      g2int  j,nbits,iret,width,height;
-      g2float  ref,bscale,dscale;
+      g2int  j,nbits,iret = 0,width,height;
+      g2float  refD, refV,bscale,dscale;
       unsigned char *ctemp;
 
-      rdieee(idrstmpl+0,&ref,1);
-      bscale = int_power(2.0,idrstmpl[1]);
-      dscale = int_power(10.0,-idrstmpl[2]);
+      rdieee(idrstmpl+0,&refV,1);
+      bscale = (g2float)int_power(2.0,idrstmpl[1]);
+      dscale = (g2float)int_power(10.0,-idrstmpl[2]);
+      bscale *= dscale;
+      refV *= dscale;
+      refD = refV;
+
       nbits = idrstmpl[3];
 //
 //  if nbits equals 0, we have a constant field where the reference value
 //  is the data value at each gridpoint
 //
       if (nbits != 0) {
-
+         int nbytes = nbits/8;
          ifld=(g2int *)calloc(ndpts,sizeof(g2int));
-         ctemp=(unsigned char *)calloc(ndpts*4,1);
-         if ( ifld == 0 || ctemp == 0) {
+         ctemp=(unsigned char *)calloc(ndpts*nbytes,1);
+         if ( ifld == NULL || ctemp == NULL) {
             fprintf(stderr, "Could not allocate space in jpcunpack.\n"
                     "Data field NOT unpacked.\n");
+            free(ifld);
+            free(ctemp);
             return(1);
          }
-         iret=(g2int)dec_png(cpack,&width,&height,ctemp);
+         iret=(g2int)dec_png(cpack,len,&width,&height,ctemp, ndpts, nbits);
          gbits(ctemp,ifld,0,nbits,0,ndpts);
          for (j=0;j<ndpts;j++) {
-           fld[j]=(((g2float)ifld[j]*bscale)+ref)*dscale;
+            fld[j] = refD + bscale*(g2float)(ifld[j]);
          }
          free(ctemp);
          free(ifld);
       }
       else {
-         for (j=0;j<ndpts;j++) fld[j]=ref;
+         for (j=0;j<ndpts;j++) fld[j]=refD;
       }
 
-      return(0);
+      return(iret);
 }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/rdieee.c b/frmts/grib/degrib18/g2clib-1.0.4/rdieee.c
index 35fe338..b2fd62f 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/rdieee.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/rdieee.c
@@ -3,10 +3,10 @@
 void rdieee(g2int *rieee,g2float *a,g2int num)
 //$$$  SUBPROGRAM DOCUMENTATION BLOCK
 //                .      .    .                                       .
-// SUBPROGRAM:    rdieee 
+// SUBPROGRAM:    rdieee
 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2002-10-25
 //
-// ABSTRACT: This subroutine reads a list of real values in 
+// ABSTRACT: This subroutine reads a list of real values in
 //   32-bit IEEE floating point format.
 //
 // PROGRAM HISTORY LOG:
@@ -17,7 +17,7 @@ void rdieee(g2int *rieee,g2float *a,g2int num)
 //     rieee    - g2int array of floating point values in 32-bit IEEE format.
 //     num      - Number of floating point values to convert.
 //
-//   OUTPUT ARGUMENT LIST:      
+//   OUTPUT ARGUMENT LIST:
 //     a        - float array of real values.  a must be allocated with at
 //                least 4*num bytes of memory before calling this function.
 //
@@ -57,20 +57,20 @@ void rdieee(g2int *rieee,g2float *a,g2int num)
 
         sign=1.0;
         if (isign == 1) sign=-1.0;
-        
+
         if ( (iexp > 0) && (iexp < 255) ) {
           temp=(g2float)int_power(2.0,(iexp-127));
-          a[j]=sign*temp*(1.0+(two23*(g2float)imant));
+          a[j]=(float)(sign*temp*(1.0+(two23*(g2float)imant)));
         }
         else if ( iexp == 0 ) {
           if ( imant != 0 )
             a[j]=sign*two126*two23*(g2float)imant;
           else
-            a[j]=sign*0.0;
-          
+            a[j]=(float)(sign*0.0);
+
         }
         else if ( iexp == 255 )
-           a[j]=sign*(1E+37);
+           a[j]=(float)(sign*(1E+37));
 
 
       }
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/reduce.c b/frmts/grib/degrib18/g2clib-1.0.4/reduce.c
index b1b18b4..8c47baf 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/reduce.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/reduce.c
@@ -168,7 +168,8 @@
     jj = 0;
 
 /* Computing MIN */
-    i__1 = 30, i__2 = *kbit - 1;
+    i__1 = 30;
+    i__2 = *kbit - 1;
     /*for (j = min(i__1,i__2); j >= 2; --j) {*/
     for (j = (i__1 < i__2) ? i__1 : i__2; j >= 2; --j) {
 /*           VALUES GE KBIT WILL NOT REQUIRE SPLITS.  ONCE THE TOTAL */
@@ -219,7 +220,7 @@ L190:
 
 	/* nboxj[j - 1] = newboxt; */
 	ntotpr = ntotbt[j];
-	ntotbt[j - 1] = (*ibit + *jbit) * (*lx + newboxt) + j * (*lx + 
+	ntotbt[j - 1] = (*ibit + *jbit) * (*lx + newboxt) + j * (*lx +
 		newboxt);
 
 	if (ntotbt[j - 1] >= ntotpr) {
@@ -335,8 +336,8 @@ L250:
 	    }
 
 	    if (newboxp[l - 1] > 0) {
-		if ((movmin + *novref) * newboxp[l - 1] + *novref <= nov[l] + 
-			*novref && (movmin + *novref) * (newboxp[l - 1] + 1) 
+		if ((movmin + *novref) * newboxp[l - 1] + *novref <= nov[l] +
+			*novref && (movmin + *novref) * (newboxp[l - 1] + 1)
 			>= nov[l] + *novref) {
 		    goto L288;
 		} else {
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/seekgb.c b/frmts/grib/degrib18/g2clib-1.0.4/seekgb.c
index 424197f..e9c8c85 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/seekgb.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/seekgb.c
@@ -35,7 +35,7 @@ void seekgb(FILE *lugb,g2int iseek,g2int mseek,g2int *lskip,g2int *lgrib)
 //$$$
 {
       // g2int  ret;
-      g2int k,k4,ipos,nread,lim,start,vers,end,lengrib;
+      g2int k,k4,ipos,nread,lim,start,vers,end = 0,lengrib;
       unsigned char *cbuf;
 
 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/simpack.c b/frmts/grib/degrib18/g2clib-1.0.4/simpack.c
index 15940b8..3565d52 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/simpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/simpack.c
@@ -29,21 +29,21 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
 //                [3] = Number of bits used to pack data, if value is
 //                      > 0 and  <= 31.
 //                      If this input value is 0 or outside above range
-//                      then the num of bits is calculated based on given 
+//                      then the num of bits is calculated based on given
 //                      data and scale factors.
 //                [4] = Original field type - currently ignored on input
 //                      Data values assumed to be reals.
 //
-//   OUTPUT ARGUMENT LIST: 
+//   OUTPUT ARGUMENT LIST:
 //     idrstmpl - Contains the array of values for Data Representation
 //                Template 5.0
 //                [0] = Reference value - set by simpack routine.
 //                [1] = Binary Scale Factor - unchanged from input
 //                [2] = Decimal Scale Factor - unchanged from input
-//                [3] = Number of bits used to pack data, unchanged from 
+//                [3] = Number of bits used to pack data, unchanged from
 //                      input if value is between 0 and 31.
 //                      If this input value is 0 or outside above range
-//                      then the num of bits is calculated based on given 
+//                      then the num of bits is calculated based on given
 //                      data and scale factors.
 //                [4] = Original field type - currently set = 0 on output.
 //                      Data values assumed to be reals.
@@ -54,7 +54,7 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 {
@@ -64,10 +64,10 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
       g2int  j,nbits,imin,imax,maxdif,nbittot,left;
       g2float  bscale,dscale,rmax,rmin,temp;
       double maxnum;
-      const g2float alog2=0.69314718;       //  ln(2.0)
-      
-      bscale=int_power(2.0,-idrstmpl[1]);
-      dscale=int_power(10.0,idrstmpl[2]);
+      const g2float alog2=0.69314718f;       //  ln(2.0)
+
+      bscale=(float)int_power(2.0,-idrstmpl[1]);
+      dscale=(float)int_power(10.0,idrstmpl[2]);
       if (idrstmpl[3] <= 0 || idrstmpl[3] > 31)
          nbits=0;
       else
@@ -81,7 +81,7 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
         if (fld[j] > rmax) rmax=fld[j];
         if (fld[j] < rmin) rmin=fld[j];
       }
-     
+
       ifld=calloc(ndpts,sizeof(g2int));
 //
 //  If max and min values are not equal, pack up field.
@@ -91,18 +91,18 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
 //
       if (rmin != rmax) {
         //
-        //  Determine which algorithm to use based on user-supplied 
+        //  Determine which algorithm to use based on user-supplied
         //  binary scale factor and number of bits.
         //
         if (nbits==0 && idrstmpl[1]==0) {
            //
-           //  No binary scaling and calculate minimum number of 
+           //  No binary scaling and calculate minimum number of
            //  bits in which the data will fit.
            //
            imin=(g2int)RINT(rmin*dscale);
            imax=(g2int)RINT(rmax*dscale);
            maxdif=imax-imin;
-           temp=log((double)(maxdif+1))/alog2;
+           temp=(float)(log((double)(maxdif+1))/alog2);
            nbits=(g2int)ceil(temp);
            rmin=(g2float)imin;
            //   scale data
@@ -117,22 +117,22 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
            rmin=rmin*dscale;
            rmax=rmax*dscale;
            maxnum=int_power(2.0,nbits)-1;
-           temp=log(maxnum/(rmax-rmin))/alog2;
+           temp=(float)(log(maxnum/(rmax-rmin))/alog2);
            idrstmpl[1]=(g2int)ceil(-1.0*temp);
-           bscale=int_power(2.0,-idrstmpl[1]);
+           bscale=(float)int_power(2.0,-idrstmpl[1]);
            //   scale data
            for (j=0;j<ndpts;j++)
              ifld[j]=(g2int)RINT(((fld[j]*dscale)-rmin)*bscale);
         }
         else if (nbits==0 && idrstmpl[1]!=0) {
            //
-           //  Use binary scaling factor and calculate minimum number of 
+           //  Use binary scaling factor and calculate minimum number of
            //  bits in which the data will fit.
            //
            rmin=rmin*dscale;
            rmax=rmax*dscale;
            maxdif=(g2int)RINT((rmax-rmin)*bscale);
-           temp=log((double)(maxdif+1))/alog2;
+           temp=(float)(log((double)(maxdif+1))/alog2);
            nbits=(g2int)ceil(temp);
            //   scale data
            for (j=0;j<ndpts;j++)
@@ -140,7 +140,7 @@ void simpack(g2float *fld,g2int ndpts,g2int *idrstmpl,unsigned char *cpack,g2int
         }
         else if (nbits!=0 && idrstmpl[1]!=0) {
            //
-           //  Use binary scaling factor and use minimum number of 
+           //  Use binary scaling factor and use minimum number of
            //  bits specified by user.   Dangerous - may loose
            //  information if binary scale factor and nbits not set
            //  properly by user.
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/simunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/simunpack.c
index 3826b9a..bc47f05 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/simunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/simunpack.c
@@ -10,7 +10,7 @@ g2int simunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2float *fld)
 // SUBPROGRAM:    simunpack
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2002-10-29
 //
-// ABSTRACT: This subroutine unpacks a data field that was packed using a 
+// ABSTRACT: This subroutine unpacks a data field that was packed using a
 //   simple packing algorithm as defined in the GRIB2 documentation,
 //   using info from the GRIB2 Data Representation Template 5.0.
 //
@@ -44,8 +44,8 @@ g2int simunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2float *fld)
       g2float ref,bscale,dscale;
 
       rdieee(idrstmpl+0,&ref,1);
-      bscale = int_power(2.0,idrstmpl[1]);
-      dscale = int_power(10.0,-idrstmpl[2]);
+      bscale = (float)int_power(2.0,idrstmpl[1]);
+      dscale = (float)int_power(10.0,-idrstmpl[2]);
       nbits = idrstmpl[3];
       /* itype = idrstmpl[4]; */
 
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/specpack.c b/frmts/grib/degrib18/g2clib-1.0.4/specpack.c
index c52f817..2b67087 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/specpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/specpack.c
@@ -12,7 +12,7 @@ void specpack(g2float *fld,g2int ndpts,g2int JJ,g2int KK,g2int MM,
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2002-12-19
 //
 // ABSTRACT: This subroutine packs a spectral data field using the complex
-//   packing algorithm for spherical harmonic data as 
+//   packing algorithm for spherical harmonic data as
 //   defined in the GRIB2 Data Representation Template 5.51.
 //
 // PROGRAM HISTORY LOG:
@@ -58,12 +58,12 @@ void specpack(g2float *fld,g2int ndpts,g2int JJ,g2int KK,g2int MM,
 //   Calculate Laplacian scaling factors for each possible wave number.
 //
       pscale=(g2float *)malloc((JJ+MM)*sizeof(g2float));
-      tscale=(g2float)idrstmpl[4]*1E-6;
+      tscale=(g2float)(idrstmpl[4]*1E-6);
       for (n=Js;n<=JJ+MM;n++)
-           pscale[n]=pow((g2float)(n*(n+1)),tscale);
+           pscale[n]=(float)pow((g2float)(n*(n+1)),tscale);
 //
 //   Separate spectral coeffs into two lists; one to contain unpacked
-//   values within the sub-spectrum Js, Ks, Ms, and the other with values 
+//   values within the sub-spectrum Js, Ks, Ms, and the other with values
 //   outside of the sub-spectrum to be packed.
 //
       tfld=(g2float *)malloc(ndpts*sizeof(g2float));
@@ -104,7 +104,7 @@ void specpack(g2float *fld,g2int ndpts,g2int JJ,g2int KK,g2int MM,
       ipos=4*Ts;
 //
 //  Scale and pack the rest of the coefficients
-// 
+//
       tmplsim[1]=idrstmpl[1];
       tmplsim[2]=idrstmpl[2];
       tmplsim[3]=idrstmpl[3];
diff --git a/frmts/grib/degrib18/g2clib-1.0.4/specunpack.c b/frmts/grib/degrib18/g2clib-1.0.4/specunpack.c
index bc47b4c..2b70442 100644
--- a/frmts/grib/degrib18/g2clib-1.0.4/specunpack.c
+++ b/frmts/grib/degrib18/g2clib-1.0.4/specunpack.c
@@ -11,8 +11,8 @@ g2int specunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2int JJ,
 // SUBPROGRAM:    specunpack
 //   PRGMMR: Gilbert          ORG: W/NP11    DATE: 2000-06-21
 //
-// ABSTRACT: This subroutine unpacks a spectral data field that was packed 
-//   using the complex packing algorithm for spherical harmonic data as 
+// ABSTRACT: This subroutine unpacks a spectral data field that was packed
+//   using the complex packing algorithm for spherical harmonic data as
 //   defined in the GRIB2 documentation,
 //   using info from the GRIB2 Data Representation Template 5.51.
 //
@@ -39,7 +39,7 @@ g2int specunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2int JJ,
 //
 // ATTRIBUTES:
 //   LANGUAGE: C
-//   MACHINE:  
+//   MACHINE:
 //
 //$$$
 {
@@ -51,8 +51,8 @@ g2int specunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2int JJ,
       g2int   inc,incu,incp;
 
       rdieee(idrstmpl+0,&ref,1);
-      bscale = int_power(2.0,idrstmpl[1]);
-      dscale = int_power(10.0,-idrstmpl[2]);
+      bscale = (float)int_power(2.0,idrstmpl[1]);
+      dscale = (float)int_power(10.0,-idrstmpl[2]);
       nbits = idrstmpl[3];
       Js=idrstmpl[5];
       Ks=idrstmpl[6];
@@ -72,9 +72,9 @@ g2int specunpack(unsigned char *cpack,g2int *idrstmpl,g2int ndpts,g2int JJ,
 //   Calculate Laplacian scaling factors for each possible wave number.
 //
          pscale=(g2float *)malloc((JJ+MM+1)*sizeof(g2float));
-         tscale=(g2float)idrstmpl[4]*1E-6;
-         for (n=Js;n<=JJ+MM;n++) 
-              pscale[n]=pow((g2float)(n*(n+1)),-tscale);
+         tscale=(g2float)(idrstmpl[4]*1E-6);
+         for (n=Js;n<=JJ+MM;n++)
+              pscale[n]=(float)pow((g2float)(n*(n+1)),-tscale);
 //
 //   Assemble spectral coeffs back to original order.
 //
diff --git a/frmts/grib/gribdataset.cpp b/frmts/grib/gribdataset.cpp
index 90b024e..afb276c 100644
--- a/frmts/grib/gribdataset.cpp
+++ b/frmts/grib/gribdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gribdataset.cpp 33813 2016-03-29 23:48:36Z goatbar $
  *
  * Project:  GRIB Driver
  * Purpose:  GDALDataset driver for GRIB translator for read support
@@ -30,100 +29,50 @@
  *
  */
 
-#include "cpl_multiproc.h"
-#include "gdal_frmts.h"
-#include "gdal_pam.h"
-#include "ogr_spatialref.h"
+#include "cpl_port.h"
+#include "gribdataset.h"
 
+#include <cerrno>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "degrib18/degrib/datasource.h"
 #include "degrib18/degrib/degrib2.h"
-#include "degrib18/degrib/inventory.h"
-#include "degrib18/degrib/myerror.h"
 #include "degrib18/degrib/filedatasource.h"
+#include "degrib18/degrib/inventory.h"
 #include "degrib18/degrib/memorydatasource.h"
+#include "degrib18/degrib/meta.h"
+#include "degrib18/degrib/myerror.h"
+#include "degrib18/degrib/type.h"
+#include "gdal.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gribdataset.cpp 33813 2016-03-29 23:48:36Z goatbar $");
+CPL_CVSID("$Id: gribdataset.cpp 37827 2017-03-23 06:07:27Z goatbar $");
 
 static CPLMutex *hGRIBMutex = NULL;
 
 /************************************************************************/
-/* ==================================================================== */
-/*                              GRIBDataset                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class GRIBRasterBand;
-
-class GRIBDataset : public GDALPamDataset
-{
-    friend class GRIBRasterBand;
-
-  public:
-                GRIBDataset();
-                ~GRIBDataset();
-
-    static GDALDataset *Open( GDALOpenInfo * );
-    static int          Identify( GDALOpenInfo * );
-
-    CPLErr      GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
-
-  private:
-    void SetGribMetaData(grib_MetaData* meta);
-    VSILFILE    *fp;
-    char  *pszProjection;
-    // Calculate and store once as GetGeoTransform may be called multiple times.
-    double adfGeoTransform[6];
-
-    GIntBig  nCachedBytes;
-    GIntBig  nCachedBytesThreshold;
-    int      bCacheOnlyOneBand;
-    GRIBRasterBand* poLastUsedBand;
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            GRIBRasterBand                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class GRIBRasterBand : public GDALPamRasterBand
-{
-    friend class GRIBDataset;
-
-public:
-    GRIBRasterBand( GRIBDataset*, int, inventoryType* );
-    virtual ~GRIBRasterBand();
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual const char *GetDescription() const;
-
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-
-    void    FindPDSTemplate();
-
-    void    UncacheData();
-
-private:
-
-    CPLErr       LoadData();
-
-    static void ReadGribData( DataSource &, sInt4, int, double**,
-                              grib_MetaData** );
-    sInt4 start;
-    int subgNum;
-    char *longFstLevel;
-
-    double * m_Grib_Data;
-    grib_MetaData* m_Grib_MetaData;
-
-    int      nGribDataXSize;
-    int      nGribDataYSize;
-};
-
-/************************************************************************/
 /*                         ConvertUnitInText()                          */
 /************************************************************************/
 
-static CPLString ConvertUnitInText( bool bMetricUnits, const char* pszTxt )
+static CPLString ConvertUnitInText( bool bMetricUnits, const char *pszTxt )
 {
     if( !bMetricUnits )
         return pszTxt;
@@ -159,22 +108,22 @@ GRIBRasterBand::GRIBRasterBand( GRIBDataset *poDSIn, int nBandIn,
     nBlockXSize = poDSIn->nRasterXSize;
     nBlockYSize = 1;
 
-    const char* pszGribNormalizeUnits =
+    const char *pszGribNormalizeUnits =
         CPLGetConfigOption("GRIB_NORMALIZE_UNITS", "YES");
     bool bMetricUnits = CPLTestBool(pszGribNormalizeUnits);
 
-    SetMetadataItem( "GRIB_UNIT",
-                     ConvertUnitInText(bMetricUnits, psInv->unitName) );
-    SetMetadataItem( "GRIB_COMMENT",
-                     ConvertUnitInText(bMetricUnits, psInv->comment) );
-    SetMetadataItem( "GRIB_ELEMENT", psInv->element );
-    SetMetadataItem( "GRIB_SHORT_NAME", psInv->shortFstLevel );
-    SetMetadataItem( "GRIB_REF_TIME",
-                     CPLString().Printf("%12.0f sec UTC", psInv->refTime ) );
-    SetMetadataItem( "GRIB_VALID_TIME",
-                     CPLString().Printf("%12.0f sec UTC", psInv->validTime ) );
-    SetMetadataItem( "GRIB_FORECAST_SECONDS",
-                     CPLString().Printf("%.0f sec", psInv->foreSec ) );
+    SetMetadataItem("GRIB_UNIT",
+                    ConvertUnitInText(bMetricUnits, psInv->unitName));
+    SetMetadataItem("GRIB_COMMENT",
+                    ConvertUnitInText(bMetricUnits, psInv->comment));
+    SetMetadataItem("GRIB_ELEMENT", psInv->element);
+    SetMetadataItem("GRIB_SHORT_NAME", psInv->shortFstLevel);
+    SetMetadataItem("GRIB_REF_TIME",
+                    CPLString().Printf("%12.0f sec UTC", psInv->refTime));
+    SetMetadataItem("GRIB_VALID_TIME",
+                    CPLString().Printf("%12.0f sec UTC", psInv->validTime));
+    SetMetadataItem("GRIB_FORECAST_SECONDS",
+                    CPLString().Printf("%.0f sec", psInv->foreSec));
 }
 
 /************************************************************************/
@@ -187,75 +136,72 @@ GRIBRasterBand::GRIBRasterBand( GRIBDataset *poDSIn, int nBandIn,
 void GRIBRasterBand::FindPDSTemplate()
 
 {
-    GRIBDataset *poGDS = reinterpret_cast<GRIBDataset *>( poDS );
+    GRIBDataset *poGDS = static_cast<GRIBDataset *>(poDS);
 
-/* -------------------------------------------------------------------- */
-/*      Collect section 4 octet information ... we read the file        */
-/*      ourselves since the GRIB API does not appear to preserve all    */
-/*      this for us.                                                    */
-/* -------------------------------------------------------------------- */
-    GIntBig nOffset = VSIFTellL( poGDS->fp );
+    // Collect section 4 octet information.  We read the file
+    // ourselves since the GRIB API does not appear to preserve all
+    // this for us.
+    GIntBig nOffset = VSIFTellL(poGDS->fp);
 
-    VSIFSeekL( poGDS->fp, start+16, SEEK_SET );
+    VSIFSeekL(poGDS->fp, start + 16, SEEK_SET);
 
     GByte abyHead[5] = { 0 };
-    VSIFReadL( abyHead, 5, 1, poGDS->fp );
+    VSIFReadL(abyHead, 5, 1, poGDS->fp);
 
     GUInt32 nSectSize = 0;
     while( abyHead[4] != 4 )
     {
-        memcpy( &nSectSize, abyHead, 4 );
-        CPL_MSBPTR32( &nSectSize );
+        memcpy(&nSectSize, abyHead, 4);
+        CPL_MSBPTR32(&nSectSize);
 
-        if( VSIFSeekL( poGDS->fp, nSectSize-5, SEEK_CUR ) != 0
-            || VSIFReadL( abyHead, 5, 1, poGDS->fp ) != 1 )
+        if( VSIFSeekL(poGDS->fp, nSectSize - 5, SEEK_CUR) != 0 ||
+            VSIFReadL(abyHead, 5, 1, poGDS->fp) != 1 )
             break;
     }
 
     if( abyHead[4] == 4 )
     {
-        memcpy( &nSectSize, abyHead, 4 );
-        CPL_MSBPTR32( &nSectSize );
+        memcpy(&nSectSize, abyHead, 4);
+        CPL_MSBPTR32(&nSectSize);
 
-        GByte *pabyBody = static_cast<GByte *>( CPLMalloc(nSectSize - 5) );
-        VSIFReadL( pabyBody, 1, nSectSize-5, poGDS->fp );
+        GByte *pabyBody = static_cast<GByte *>(CPLMalloc(nSectSize - 5));
+        VSIFReadL(pabyBody, 1, nSectSize - 5, poGDS->fp);
 
         GUInt16 nCoordCount = 0;
-        memcpy( &nCoordCount, pabyBody + 5 - 5, 2 );
-        CPL_MSBPTR16( &nCoordCount );
+        memcpy(&nCoordCount, pabyBody + 5 - 5, 2);
+        CPL_MSBPTR16(&nCoordCount);
 
         GUInt16 nPDTN = 0;
-        memcpy( &nPDTN, pabyBody + 7 - 5, 2 );
-        CPL_MSBPTR16( &nPDTN );
+        memcpy(&nPDTN, pabyBody + 7 - 5, 2);
+        CPL_MSBPTR16(&nPDTN);
 
-        SetMetadataItem( "GRIB_PDS_PDTN",
-                         CPLString().Printf( "%d", nPDTN ) );
+        SetMetadataItem("GRIB_PDS_PDTN", CPLString().Printf("%d", nPDTN));
 
         CPLString osOctet;
-        for( int i = 9; i < static_cast<int>( nSectSize ); i++ )
+        for( int i = 9; i < static_cast<int>(nSectSize); i++ )
         {
             char szByte[10] = { '\0' };
 
             if( i == 9 )
-                snprintf( szByte, sizeof(szByte), "%d", pabyBody[i-5] );
+                snprintf(szByte, sizeof(szByte), "%d", pabyBody[i - 5]);
             else
-                snprintf( szByte, sizeof(szByte), " %d", pabyBody[i-5] );
+                snprintf(szByte, sizeof(szByte), " %d", pabyBody[i - 5]);
             osOctet += szByte;
         }
 
-        SetMetadataItem( "GRIB_PDS_TEMPLATE_NUMBERS", osOctet );
+        SetMetadataItem("GRIB_PDS_TEMPLATE_NUMBERS", osOctet);
 
-        CPLFree( pabyBody );
+        CPLFree(pabyBody);
     }
 
-    VSIFSeekL( poGDS->fp, nOffset, SEEK_SET );
+    VSIFSeekL(poGDS->fp, nOffset, SEEK_SET);
 }
 
 /************************************************************************/
 /*                         GetDescription()                             */
 /************************************************************************/
 
-const char * GRIBRasterBand::GetDescription() const
+const char *GRIBRasterBand::GetDescription() const
 {
     if( longFstLevel == NULL )
         return GDALPamRasterBand::GetDescription();
@@ -272,7 +218,7 @@ CPLErr GRIBRasterBand::LoadData()
 {
     if( !m_Grib_Data )
     {
-        GRIBDataset *poGDS = reinterpret_cast<GRIBDataset *>( poDS );
+        GRIBDataset *poGDS = static_cast<GRIBDataset *>(poDS);
 
         if (poGDS->bCacheOnlyOneBand)
         {
@@ -289,50 +235,47 @@ CPLErr GRIBRasterBand::LoadData()
             // all bands that have been accessed.
             if (poGDS->nCachedBytes > poGDS->nCachedBytesThreshold)
             {
-                CPLDebug( "GRIB",
-                          "Maximum band cache size reached for this dataset. "
-                          "Caching only one band at a time from now");
-                for(int i=0;i<poGDS->nBands;i++)
+                CPLDebug("GRIB",
+                         "Maximum band cache size reached for this dataset. "
+                         "Caching only one band at a time from now");
+                for(int i = 0; i < poGDS->nBands; i++)
                 {
-                    reinterpret_cast<GRIBRasterBand*>(
-                        poGDS->GetRasterBand(i+1))->UncacheData();
+                    reinterpret_cast<GRIBRasterBand *>(
+                        poGDS->GetRasterBand(i + 1))
+                        ->UncacheData();
                 }
                 poGDS->nCachedBytes = 0;
                 poGDS->bCacheOnlyOneBand = TRUE;
             }
         }
 
-        FileDataSource grib_fp (poGDS->fp);
+        FileDataSource grib_fp(poGDS->fp);
 
         // we don't seem to have any way to detect errors in this!
         ReadGribData(grib_fp, start, subgNum, &m_Grib_Data, &m_Grib_MetaData);
         if( !m_Grib_Data )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "Out of memory." );
+            CPLError(CE_Failure, CPLE_AppDefined, "Out of memory.");
             return CE_Failure;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Check that this band matches the dataset as a whole, size       */
-/*      wise. (#3246)                                                   */
-/* -------------------------------------------------------------------- */
+        // Check the band matches the dataset as a whole, size wise. (#3246)
         nGribDataXSize = m_Grib_MetaData->gds.Nx;
         nGribDataYSize = m_Grib_MetaData->gds.Ny;
 
         poGDS->nCachedBytes += nGribDataXSize * nGribDataYSize * sizeof(double);
         poGDS->poLastUsedBand = this;
 
-        if( nGribDataXSize != nRasterXSize
-            || nGribDataYSize != nRasterYSize )
+        if( nGribDataXSize != nRasterXSize || nGribDataYSize != nRasterYSize )
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Band %d of GRIB dataset is %dx%d, while the first band "
-                      "and dataset is %dx%d.  Georeferencing of band %d may "
-                      "be incorrect, and data access may be incomplete.",
-                      nBand,
-                      nGribDataXSize, nGribDataYSize,
-                      nRasterXSize, nRasterYSize,
-                      nBand );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Band %d of GRIB dataset is %dx%d, while the first band "
+                     "and dataset is %dx%d.  Georeferencing of band %d may "
+                     "be incorrect, and data access may be incomplete.",
+                     nBand,
+                     nGribDataXSize, nGribDataYSize,
+                     nRasterXSize, nRasterYSize,
+                     nBand);
         }
     }
 
@@ -345,21 +288,19 @@ CPLErr GRIBRasterBand::LoadData()
 
 CPLErr GRIBRasterBand::IReadBlock( int /* nBlockXOff */,
                                    int nBlockYOff,
-                                   void * pImage )
+                                   void *pImage )
 
 {
     CPLErr eErr = LoadData();
     if (eErr != CE_None)
         return eErr;
 
-/* -------------------------------------------------------------------- */
-/*      The image as read is always upside down to our normal           */
-/*      orientation so we need to effectively flip it at this           */
-/*      point.  We also need to deal with bands that are a different    */
-/*      size than the dataset as a whole.                               */
-/* -------------------------------------------------------------------- */
-    if( nGribDataXSize == nRasterXSize
-        && nGribDataYSize == nRasterYSize )
+    // The image as read is always upside down to our normal
+    // orientation so we need to effectively flip it at this
+    // point.  We also need to deal with bands that are a different
+    // size than the dataset as a whole.
+
+    if( nGribDataXSize == nRasterXSize && nGribDataYSize == nRasterYSize )
     {
         // Simple 1:1 case.
         memcpy(pImage,
@@ -369,16 +310,16 @@ CPLErr GRIBRasterBand::IReadBlock( int /* nBlockXOff */,
         return CE_None;
     }
 
-    memset( pImage, 0, sizeof(double) * nRasterXSize );
+    memset(pImage, 0, sizeof(double) * nRasterXSize);
 
-    if( nBlockYOff >= nGribDataYSize ) // off image?
+    if( nBlockYOff >= nGribDataYSize )  // Off image?
         return CE_None;
 
-    const int nCopyWords = MIN(nRasterXSize,nGribDataXSize);
+    const int nCopyWords = std::min(nRasterXSize, nGribDataXSize);
 
-    memcpy( pImage,
-            m_Grib_Data + nGribDataXSize*(nGribDataYSize-nBlockYOff-1),
-            nCopyWords * sizeof(double) );
+    memcpy(pImage,
+           m_Grib_Data + nGribDataXSize * (nGribDataYSize - nBlockYOff - 1),
+           nCopyWords * sizeof(double));
 
     return CE_None;
 }
@@ -401,7 +342,7 @@ double GRIBRasterBand::GetNoDataValue( int *pbSuccess )
 
     if (m_Grib_MetaData->gridAttrib.f_miss == 2)
     {
-        /* what TODO ? */
+        // What TODO?
         CPLDebug("GRIB", "Secondary missing value also set for band %d : %f",
                  nBand, m_Grib_MetaData->gridAttrib.missSec);
     }
@@ -415,51 +356,51 @@ double GRIBRasterBand::GetNoDataValue( int *pbSuccess )
 /*                            ReadGribData()                            */
 /************************************************************************/
 
-void GRIBRasterBand::ReadGribData( DataSource & fp, sInt4 start, int subgNum,
-                                   double** data, grib_MetaData** metaData)
+void GRIBRasterBand::ReadGribData( DataSource &fp, sInt4 start, int subgNum,
+                                   double **data, grib_MetaData **metaData)
 {
     // Initialization, for calling the ReadGrib2Record function.
     sInt4 f_endMsg = 1;  // 1 if we read the last grid in a GRIB message, or we
                          // haven't read any messages.
     // int subgNum = 0; // The subgrid in the message that we are interested in.
-    sChar f_unit = 2;        // None = 0, English = 1, Metric = 2
-    double majEarth = 0.0;   // -radEarth if < 6000 ignore, otherwise use this
-                             // to override the radEarth in the GRIB1 or GRIB2
-                             // message.  Needed because NCEP uses 6371.2 but
-                             // GRIB1 could only state 6367.47.
-    double minEarth = 0.0;   // -minEarth if < 6000 ignore, otherwise use this
-                             // to override the minEarth in the GRIB1 or GRIB2
-                             // message.
-    sChar f_SimpleVer = 4;   // Which version of the simple NDFD Weather table
-                             // to use. (1 is 6/2003) (2 is 1/2004) (3 is
-                             // 2/2004) (4 is 11/2004) (default 4)
-    LatLon lwlf;         // lower left corner (cookie slicing) -lwlf
-    LatLon uprt;         // upper right corner (cookie slicing) -uprt
-    IS_dataType is;      // Un-parsed meta data for this GRIB2 message. As well
-                         // as some memory used by the unpacker.
-
-    lwlf.lat = -100; // lat == -100 instructs the GRIB decoder that we don't
-                     // want a subgrid
-
-    IS_Init (&is);
-
-    const char* pszGribNormalizeUnits =
+    sChar f_unit = 2;       // None = 0, English = 1, Metric = 2
+    double majEarth = 0.0;  // -radEarth if < 6000 ignore, otherwise use this
+                            // to override the radEarth in the GRIB1 or GRIB2
+                            // message.  Needed because NCEP uses 6371.2 but
+                            // GRIB1 could only state 6367.47.
+    double minEarth = 0.0;  // -minEarth if < 6000 ignore, otherwise use this
+                            // to override the minEarth in the GRIB1 or GRIB2
+                            // message.
+    sChar f_SimpleVer = 4;  // Which version of the simple NDFD Weather table
+                            // to use. (1 is 6/2003) (2 is 1/2004) (3 is
+                            // 2/2004) (4 is 11/2004) (default 4)
+    LatLon lwlf;            // Lower left corner (cookie slicing) -lwlf
+    LatLon uprt;            // Upper right corner (cookie slicing) -uprt
+    IS_dataType is;  // Un-parsed meta data for this GRIB2 message. As well
+                     // as some memory used by the unpacker.
+
+    lwlf.lat = -100;  // lat == -100 instructs the GRIB decoder that we don't
+                      // want a subgrid
+
+    IS_Init(&is);
+
+    const char *pszGribNormalizeUnits =
         CPLGetConfigOption("GRIB_NORMALIZE_UNITS", "YES");
     if ( !CPLTestBool(pszGribNormalizeUnits) )
-        f_unit = 0; /* do not normalize units to metric */
+        f_unit = 0;  // Do not normalize units to metric.
 
-    /* Read GRIB message from file position "start". */
+    // Read GRIB message from file position "start".
     fp.DataSourceFseek(start, SEEK_SET);
-    uInt4 grib_DataLen = 0;  /* Size of Grib_Data. */
+    uInt4 grib_DataLen = 0;  // Size of Grib_Data.
     *metaData = new grib_MetaData();
-    MetaInit (*metaData);
-    ReadGrib2Record (fp, f_unit, data, &grib_DataLen, *metaData, &is, subgNum,
-                     majEarth, minEarth, f_SimpleVer, &f_endMsg, &lwlf, &uprt);
+    MetaInit(*metaData);
+    ReadGrib2Record(fp, f_unit, data, &grib_DataLen, *metaData, &is, subgNum,
+                    majEarth, minEarth, f_SimpleVer, &f_endMsg, &lwlf, &uprt);
 
-    // no intention to show errors, just swallow it and free the memory.
-    char * errMsg = errSprintf(NULL);
+    // No intention to show errors, just swallow it and free the memory.
+    char *errMsg = errSprintf(NULL);
     if( errMsg != NULL )
-        CPLDebug( "GRIB", "%s", errMsg );
+        CPLDebug("GRIB", "%s", errMsg);
     free(errMsg);
     IS_Free(&is);
 }
@@ -471,11 +412,11 @@ void GRIBRasterBand::ReadGribData( DataSource & fp, sInt4 start, int subgNum,
 void GRIBRasterBand::UncacheData()
 {
     if (m_Grib_Data)
-        free (m_Grib_Data);
+        free(m_Grib_Data);
     m_Grib_Data = NULL;
     if (m_Grib_MetaData)
     {
-        MetaFree( m_Grib_MetaData );
+        MetaFree(m_Grib_MetaData);
         delete m_Grib_MetaData;
     }
     m_Grib_MetaData = NULL;
@@ -501,21 +442,20 @@ GRIBDataset::GRIBDataset() :
     fp(NULL),
     pszProjection(CPLStrdup("")),
     nCachedBytes(0),
+    // Switch caching strategy once 100 MB threshold is reached.
+    // Why 100 MB? --> Why not.
+    nCachedBytesThreshold(
+        static_cast<GIntBig>(atoi(CPLGetConfigOption("GRIB_CACHEMAX", "100")))
+        * 1024 * 1024),
     bCacheOnlyOneBand(FALSE),
     poLastUsedBand(NULL)
 {
-  adfGeoTransform[0] = 0.0;
-  adfGeoTransform[1] = 1.0;
-  adfGeoTransform[2] = 0.0;
-  adfGeoTransform[3] = 0.0;
-  adfGeoTransform[4] = 0.0;
-  adfGeoTransform[5] = 1.0;
-
-  /* Switch caching strategy once 100 MB threshold is reached */
-  /* Why 100 MB ? --> why not ! */
-  nCachedBytesThreshold =
-      static_cast<GIntBig>(atoi(CPLGetConfigOption("GRIB_CACHEMAX", "100")))
-      * 1024 * 1024;
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 1.0;
 }
 
 /************************************************************************/
@@ -527,19 +467,19 @@ GRIBDataset::~GRIBDataset()
 {
     FlushCache();
     if( fp != NULL )
-        VSIFCloseL( fp );
+        VSIFCloseL(fp);
 
-    CPLFree( pszProjection );
+    CPLFree(pszProjection);
 }
 
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr GRIBDataset::GetGeoTransform( double * padfTransform )
+CPLErr GRIBDataset::GetGeoTransform( double *padfTransform )
 
 {
-    memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
+    memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
     return CE_None;
 }
 
@@ -547,28 +487,23 @@ CPLErr GRIBDataset::GetGeoTransform( double * padfTransform )
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char *GRIBDataset::GetProjectionRef()
-
-{
-    return pszProjection;
-}
+const char *GRIBDataset::GetProjectionRef() { return pszProjection; }
 
 /************************************************************************/
 /*                            Identify()                                */
 /************************************************************************/
 
-int GRIBDataset::Identify( GDALOpenInfo * poOpenInfo )
+int GRIBDataset::Identify( GDALOpenInfo *poOpenInfo )
 {
     if (poOpenInfo->nHeaderBytes < 8)
         return FALSE;
 
-/* -------------------------------------------------------------------- */
-/*      Does a part of what ReadSECT0() but in a thread-safe way.       */
-/* -------------------------------------------------------------------- */
-    for(int i=0;i<poOpenInfo->nHeaderBytes-3;i++)
+    const char *pasHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
+    // Does a part of what ReadSECT0(), but in a thread-safe way.
+    for(int i = 0; i < poOpenInfo->nHeaderBytes - 3; i++)
     {
-        if (STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader + i, "GRIB") ||
-            STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader + i, "TDLP"))
+        if(STARTS_WITH_CI(pasHeader + i, "GRIB") ||
+           STARTS_WITH_CI(pasHeader + i, "TDLP"))
             return TRUE;
     }
 
@@ -579,62 +514,60 @@ int GRIBDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *GRIBDataset::Open( GDALOpenInfo *poOpenInfo )
 
 {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    // During fuzzing, do not use Identify to reject crazy content.
     if( !Identify(poOpenInfo) )
         return NULL;
+#endif
 
-/* -------------------------------------------------------------------- */
-/*      A fast "probe" on the header that is partially read in memory.  */
-/* -------------------------------------------------------------------- */
+    // A fast "probe" on the header that is partially read in memory.
     char *buff = NULL;
     uInt4 buffLen = 0;
     sInt4 sect0[SECT0LEN_WORD] = { 0 };
     uInt4 gribLen = 0;
     int version = 0;
-// grib is not thread safe, make sure not to cause problems
-// for other thread safe formats
 
+    // grib is not thread safe, make sure not to cause problems
+    // for other thread safe formats
     CPLMutexHolderD(&hGRIBMutex);
-    MemoryDataSource mds (poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes);
-    if (ReadSECT0 (mds, &buff, &buffLen, -1, sect0, &gribLen, &version) < 0) {
-        free (buff);
-        char * errMsg = errSprintf(NULL);
+    MemoryDataSource mds(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes);
+    if (ReadSECT0(mds, &buff, &buffLen, -1, sect0, &gribLen, &version) < 0) {
+        free(buff);
+        char *errMsg = errSprintf(NULL);
         if( errMsg != NULL && strstr(errMsg,"Ran out of file") == NULL )
-            CPLDebug( "GRIB", "%s", errMsg );
+            CPLDebug("GRIB", "%s", errMsg);
         free(errMsg);
         return NULL;
     }
     free(buff);
 
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
+    // Confirm the requested access is supported.
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "The GRIB driver does not support update access to existing"
-                  " datasets.\n" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The GRIB driver does not support update access to existing "
+                 "datasets.");
         return NULL;
     }
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
+
+    // Create a corresponding GDALDataset.
     GRIBDataset *poDS = new GRIBDataset();
 
-    poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
+    poDS->fp = VSIFOpenL(poOpenInfo->pszFilename, "r");
 
-    /* Check the return values */
+    // Check the return values.
     if (!poDS->fp) {
-        // we have no FP, so we don't have anywhere to read from
-        char * errMsg = errSprintf(NULL);
+        // We have no FP, so we don't have anywhere to read from.
+        char *errMsg = errSprintf(NULL);
         if( errMsg != NULL )
-            CPLDebug( "GRIB", "%s", errMsg );
+            CPLDebug("GRIB", "%s", errMsg);
         free(errMsg);
 
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Error (%d) opening file %s", errno, poOpenInfo->pszFilename);
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Error (%d) opening file %s", errno, poOpenInfo->pszFilename);
         // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own
         // hGRIBMutex.
         CPLReleaseMutex(hGRIBMutex);
@@ -643,39 +576,33 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the header.                                                */
-/* -------------------------------------------------------------------- */
+    // Read the header.
 
-/* -------------------------------------------------------------------- */
-/*      Make an inventory of the GRIB file.                             */
-/* The inventory does not contain all the information needed for        */
-/* creating the RasterBands (especially the x and y size), therefore    */
-/* the first GRIB band is also read for some additional metadata.       */
-/* The band-data that is read is stored into the first RasterBand,      */
-/* simply so that the same portion of the file is not read twice.       */
-/* -------------------------------------------------------------------- */
+    // Make an inventory of the GRIB file.
+    // The inventory does not contain all the information needed for
+    // creating the RasterBands (especially the x and y size), therefore
+    // the first GRIB band is also read for some additional metadata.
+    // The band-data that is read is stored into the first RasterBand,
+    // simply so that the same portion of the file is not read twice.
 
-    VSIFSeekL( poDS->fp, 0, SEEK_SET );
+    VSIFSeekL(poDS->fp, 0, SEEK_SET);
 
     FileDataSource grib_fp(poDS->fp);
 
     // Contains an GRIB2 message inventory of the file.
-    inventoryType *Inv = NULL;
-    uInt4 LenInv = 0;        // Size of Inv (also # of GRIB2 messages).
-    int msgNum = 0;          // The messageNumber during the inventory.
+    gdal::grib::InventoryWrapper oInventories(grib_fp);
 
-    if( GRIB2Inventory (grib_fp, &Inv, &LenInv, 0, &msgNum) <= 0 )
+    if( oInventories.result() <= 0 )
     {
-        char * errMsg = errSprintf(NULL);
+        char *errMsg = errSprintf(NULL);
         if( errMsg != NULL )
-            CPLDebug( "GRIB", "%s", errMsg );
+            CPLDebug("GRIB", "%s", errMsg);
         free(errMsg);
 
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "%s is a grib file, "
-                  "but no raster dataset was successfully identified.",
-                  poOpenInfo->pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "%s is a grib file, "
+                 "but no raster dataset was successfully identified.",
+                 poOpenInfo->pszFilename);
         // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own
         // hGRIBMutex.
         CPLReleaseMutex(hGRIBMutex);
@@ -684,28 +611,27 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create band objects.                                            */
-/* -------------------------------------------------------------------- */
-    for (uInt4 i = 0; i < LenInv; ++i)
+    // Create band objects.
+    for (uInt4 i = 0; i < oInventories.length(); ++i)
     {
         GRIBRasterBand *gribBand = NULL;
-        uInt4 bandNr = i+1;
+        uInt4 bandNr = i + 1;
         if (bandNr == 1)
         {
             // Important: set DataSet extents before creating first RasterBand
             // in it.
             double *data = NULL;
             grib_MetaData *metaData = NULL;
-            GRIBRasterBand::ReadGribData( grib_fp, 0, Inv[i].subgNum,
-                                          &data, &metaData );
+            GRIBRasterBand::ReadGribData(grib_fp, 0,
+                                         oInventories.get(i)->subgNum,
+                                         &data, &metaData);
             if( data == NULL || metaData == NULL || metaData->gds.Nx < 1 ||
-                 metaData->gds.Ny < 1 )
+                metaData->gds.Ny < 1 )
             {
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                          "%s is a grib file, "
-                          "but no raster dataset was successfully identified.",
-                          poOpenInfo->pszFilename );
+                CPLError(CE_Failure, CPLE_OpenFailed,
+                         "%s is a grib file, "
+                         "but no raster dataset was successfully identified.",
+                         poOpenInfo->pszFilename);
                 // Release hGRIBMutex otherwise we'll deadlock with GDALDataset
                 // own hGRIBMutex.
                 CPLReleaseMutex(hGRIBMutex);
@@ -722,12 +648,12 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
                 return NULL;
             }
 
-             // Set the DataSet's x,y size, georeference and projection from
-             // the first GRIB band.
+            // Set the DataSet's x,y size, georeference and projection from
+            // the first GRIB band.
             poDS->SetGribMetaData(metaData);
-            gribBand = new GRIBRasterBand( poDS, bandNr, Inv+i);
+            gribBand = new GRIBRasterBand(poDS, bandNr, oInventories.get(i));
 
-            if( Inv->GribVersion == 2 )
+            if( oInventories.get(i)->GribVersion == 2 )
                 gribBand->FindPDSTemplate();
 
             gribBand->m_Grib_Data = data;
@@ -735,75 +661,63 @@ GDALDataset *GRIBDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else
         {
-            gribBand = new GRIBRasterBand( poDS, bandNr, Inv+i );
-            if( CPLTestBool(
-                   CPLGetConfigOption( "GRIB_PDS_ALL_BANDS", "ON" ) ) )
+            gribBand = new GRIBRasterBand(poDS, bandNr, oInventories.get(i));
+            if( CPLTestBool(CPLGetConfigOption("GRIB_PDS_ALL_BANDS", "ON")) )
             {
-                if( Inv->GribVersion == 2 )
+                if( oInventories.get(i)->GribVersion == 2 )
                     gribBand->FindPDSTemplate();
             }
         }
-        poDS->SetBand( bandNr, gribBand);
-        GRIB2InventoryFree (Inv + i);
+        poDS->SetBand(bandNr, gribBand);
     }
-    free (Inv);
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    // Initialize any PAM information.
+    poDS->SetDescription(poOpenInfo->pszFilename);
 
     // Release hGRIBMutex otherwise we'll deadlock with GDALDataset own
     // hGRIBMutex.
     CPLReleaseMutex(hGRIBMutex);
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Check for external overviews.                                   */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
-                                 poOpenInfo->GetSiblingFiles() );
+    // Check for external overviews.
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename,
+                                poOpenInfo->GetSiblingFiles());
     CPLAcquireMutex(hGRIBMutex, 1000.0);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
 /*                            SetMetadata()                             */
 /************************************************************************/
 
-void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
+void GRIBDataset::SetGribMetaData(grib_MetaData *meta)
 {
     nRasterXSize = meta->gds.Nx;
     nRasterYSize = meta->gds.Ny;
 
-/* -------------------------------------------------------------------- */
-/*      Image projection.                                               */
-/* -------------------------------------------------------------------- */
+    // Image projection.
     OGRSpatialReference oSRS;
 
     switch(meta->gds.projType)
     {
-      case GS3_LATLON:
-      case GS3_GAUSSIAN_LATLON:
-          // No projection, only latlon system (geographic)
-          break;
-      case GS3_MERCATOR:
-        oSRS.SetMercator(meta->gds.meshLat, meta->gds.orientLon,
-                         1.0, 0.0, 0.0);
+    case GS3_LATLON:
+    case GS3_GAUSSIAN_LATLON:
+        // No projection, only latlon system (geographic).
         break;
-      case GS3_POLAR:
-        oSRS.SetPS(meta->gds.meshLat, meta->gds.orientLon,
-                   meta->gds.scaleLat1,
+    case GS3_MERCATOR:
+        oSRS.SetMercator(meta->gds.meshLat, meta->gds.orientLon, 1.0, 0.0, 0.0);
+        break;
+    case GS3_POLAR:
+        oSRS.SetPS(meta->gds.meshLat, meta->gds.orientLon, meta->gds.scaleLat1,
                    0.0, 0.0);
         break;
-      case GS3_LAMBERT:
-        oSRS.SetLCC(meta->gds.scaleLat1, meta->gds.scaleLat2,
-                    meta->gds.meshLat, meta->gds.orientLon,
-                    0.0, 0.0); // set projection
+    case GS3_LAMBERT:
+        oSRS.SetLCC(meta->gds.scaleLat1, meta->gds.scaleLat2, meta->gds.meshLat,
+                    meta->gds.orientLon, 0.0, 0.0);  // Set projection.
         break;
 
-      case GS3_ORTHOGRAPHIC:
+    case GS3_ORTHOGRAPHIC:
 
         // oSRS.SetOrthographic( 0.0, meta->gds.orientLon,
         //                       meta->gds.lon2, meta->gds.lat2);
@@ -812,43 +726,34 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
         //               meta->gds.lon2, meta->gds.lat2);
 
         // TODO: Hardcoded for now. How to parse the meta->gds section?
-        oSRS.SetGEOS(  0, 35785831, 0, 0 );
+        oSRS.SetGEOS(0, 35785831, 0, 0);
         break;
-      case GS3_EQUATOR_EQUIDIST:
+    case GS3_EQUATOR_EQUIDIST:
         break;
-      case GS3_AZIMUTH_RANGE:
+    case GS3_AZIMUTH_RANGE:
         break;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Earth model                                                     */
-/* -------------------------------------------------------------------- */
-    double a = meta->gds.majEarth * 1000.0; // in meters
-    double b = meta->gds.minEarth * 1000.0;
-    if( a == 0 && b == 0 )
-    {
-        a = 6377563.396;
-        b = 6356256.910;
-    }
+    const bool bHaveEarthModel =
+        meta->gds.majEarth != 0.0 || meta->gds.minEarth != 0.0;
+    // In meters.
+    const double a = bHaveEarthModel ? meta->gds.majEarth * 1.0e3 : 6377563.396;
+    const double b = bHaveEarthModel ? meta->gds.minEarth * 1.0e3 : 6356256.910;
 
     if (meta->gds.f_sphere)
     {
-        oSRS.SetGeogCS( "Coordinate System imported from GRIB file",
-                        NULL,
-                        "Sphere",
-                        a, 0.0 );
+        oSRS.SetGeogCS("Coordinate System imported from GRIB file", NULL,
+                       "Sphere", a, 0.0);
     }
     else
     {
         const double fInv = a / (a - b);
-        oSRS.SetGeogCS( "Coordinate System imported from GRIB file",
-                        NULL,
-                        "Spheroid imported from GRIB file",
-                        a, fInv );
+        oSRS.SetGeogCS("Coordinate System imported from GRIB file", NULL,
+                       "Spheroid imported from GRIB file", a, fInv);
     }
 
-    OGRSpatialReference oLL; // construct the "geographic" part of oSRS
-    oLL.CopyGeogCSFrom( &oSRS );
+    OGRSpatialReference oLL;  // Construct the "geographic" part of oSRS.
+    oLL.CopyGeogCSFrom(&oSRS);
 
     double rMinX = 0.0;
     double rMaxY = 0.0;
@@ -856,7 +761,7 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
     double rPixelSizeY = 0.0;
     if (meta->gds.projType == GS3_ORTHOGRAPHIC)
     {
-        // This is what should work, but it doesn't .. Dx seems to have an
+        // This is what should work, but it doesn't. Dx seems to have an
         // inverse relation with pixel size.
         // rMinX = -meta->gds.Dx * (meta->gds.Nx / 2);
         // rMaxY = meta->gds.Dy * (meta->gds.Ny / 2);
@@ -875,12 +780,12 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
         // Latitude in degrees, to be transformed to meters.
         rMaxY = meta->gds.lat1;
         OGRCoordinateTransformation *poTransformLLtoSRS =
-            OGRCreateCoordinateTransformation( &(oLL), &(oSRS) );
+            OGRCreateCoordinateTransformation(&(oLL), &(oSRS));
         // Transform it to meters.
         if( (poTransformLLtoSRS != NULL) &&
-            poTransformLLtoSRS->Transform( 1, &rMinX, &rMaxY ))
+            poTransformLLtoSRS->Transform(1, &rMinX, &rMaxY) )
         {
-            if (meta->gds.scan == GRIB2BIT_2) // Y is minY, GDAL wants maxY
+            if (meta->gds.scan == GRIB2BIT_2)  // Y is minY, GDAL wants maxY.
             {
                 // -1 because we GDAL needs the coordinates of the centre of
                 // the pixel.
@@ -899,11 +804,11 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
 
             oSRS.Clear();
 
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Unable to perform coordinate transformations, so the "
-                      "correct projected geotransform could not be deduced "
-                      "from the lat/long control points.  "
-                      "Defaulting to ungeoreferenced." );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Unable to perform coordinate transformations, so the "
+                     "correct projected geotransform could not be deduced "
+                     "from the lat/long control points.  "
+                     "Defaulting to ungeoreferenced.");
         }
         delete poTransformLLtoSRS;
     }
@@ -918,17 +823,18 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
         double rMinY = meta->gds.lat2;
         if (meta->gds.lat2 > rMaxY)
         {
-          rMaxY = meta->gds.lat2;
-          rMinY = meta->gds.lat1;
+            rMaxY = meta->gds.lat2;
+            rMinY = meta->gds.lat1;
         }
 
         if( meta->gds.Nx == 1 )
-          rPixelSizeX = meta->gds.Dx;
+            rPixelSizeX = meta->gds.Dx;
         else if (meta->gds.lon1 > meta->gds.lon2)
-          rPixelSizeX =
-              (360.0 - (meta->gds.lon1 - meta->gds.lon2)) / (meta->gds.Nx - 1);
+            rPixelSizeX = (360.0 - (meta->gds.lon1 - meta->gds.lon2)) /
+                          (meta->gds.Nx - 1);
         else
-          rPixelSizeX = (meta->gds.lon2 - meta->gds.lon1) / (meta->gds.Nx - 1);
+            rPixelSizeX =
+                (meta->gds.lon2 - meta->gds.lon1) / (meta->gds.Nx - 1);
 
         if( meta->gds.Ny == 1 )
             rPixelSizeY = meta->gds.Dy;
@@ -939,33 +845,33 @@ void GRIBDataset::SetGribMetaData(grib_MetaData* meta)
         // pixel size corrections. GRIB1 has a minimum precision of 0.001
         // for latitudes and longitudes, so we'll allow a bit higher than that.
         if (rPixelSizeX < 0 || fabs(rPixelSizeX - meta->gds.Dx) > 0.002)
-          rPixelSizeX = meta->gds.Dx;
+            rPixelSizeX = meta->gds.Dx;
 
         if (rPixelSizeY < 0 || fabs(rPixelSizeY - meta->gds.Dy) > 0.002)
-          rPixelSizeY = meta->gds.Dy;
+            rPixelSizeY = meta->gds.Dy;
     }
 
     // http://gdal.org/gdal_datamodel.html :
     //   we need the top left corner of the top left pixel.
     //   At the moment we have the center of the pixel.
-    rMinX-=rPixelSizeX/2;
-    rMaxY+=rPixelSizeY/2;
+    rMinX -= rPixelSizeX / 2;
+    rMaxY += rPixelSizeY / 2;
 
     adfGeoTransform[0] = rMinX;
     adfGeoTransform[3] = rMaxY;
     adfGeoTransform[1] = rPixelSizeX;
     adfGeoTransform[5] = -rPixelSizeY;
 
-    CPLFree( pszProjection );
+    CPLFree(pszProjection);
     pszProjection = NULL;
-    oSRS.exportToWkt( &(pszProjection) );
+    oSRS.exportToWkt(&pszProjection);
 }
 
 /************************************************************************/
 /*                       GDALDeregister_GRIB()                          */
 /************************************************************************/
 
-static void GDALDeregister_GRIB(GDALDriver* )
+static void GDALDeregister_GRIB( GDALDriver * )
 {
     if( hGRIBMutex != NULL )
     {
@@ -981,21 +887,21 @@ static void GDALDeregister_GRIB(GDALDriver* )
 void GDALRegister_GRIB()
 
 {
-    if( GDALGetDriverByName( "GRIB" ) != NULL )
+    if( GDALGetDriverByName("GRIB") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "GRIB" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GRIdded Binary (.grb)" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_grib.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grb" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription("GRIB");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "GRIdded Binary (.grb)");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_grib.html");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "grb");
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
 
     poDriver->pfnOpen = GRIBDataset::Open;
     poDriver->pfnIdentify = GRIBDataset::Identify;
     poDriver->pfnUnloadDriver = GDALDeregister_GRIB;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/grib/gribdataset.h b/frmts/grib/gribdataset.h
new file mode 100644
index 0000000..071aff9
--- /dev/null
+++ b/frmts/grib/gribdataset.h
@@ -0,0 +1,184 @@
+/******************************************************************************
+ * $Id: gribdataset.h 37828 2017-03-23 06:20:46Z goatbar $
+ *
+ * Project:  GRIB Driver
+ * Purpose:  GDALDataset driver for GRIB translator for read support
+ * Author:   Bas Retsios, retsios at itc.nl
+ *
+ ******************************************************************************
+ * Copyright (c) 2007, ITC
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ******************************************************************************
+ *
+ */
+
+#include "cpl_port.h"
+
+#include <cerrno>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "degrib18/degrib/datasource.h"
+#include "degrib18/degrib/degrib2.h"
+#include "degrib18/degrib/filedatasource.h"
+#include "degrib18/degrib/inventory.h"
+#include "degrib18/degrib/memorydatasource.h"
+#include "degrib18/degrib/meta.h"
+#include "degrib18/degrib/myerror.h"
+#include "degrib18/degrib/type.h"
+#include "gdal.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              GRIBDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class GRIBRasterBand;
+
+class GRIBDataset : public GDALPamDataset
+{
+    friend class GRIBRasterBand;
+
+  public:
+                GRIBDataset();
+                ~GRIBDataset();
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+
+    CPLErr      GetGeoTransform( double *padfTransform ) override;
+    const char *GetProjectionRef() override;
+
+  private:
+    void SetGribMetaData(grib_MetaData *meta);
+    VSILFILE *fp;
+    char *pszProjection;
+    // Calculate and store once as GetGeoTransform may be called multiple times.
+    double adfGeoTransform[6];
+
+    GIntBig nCachedBytes;
+    GIntBig nCachedBytesThreshold;
+    int bCacheOnlyOneBand;
+    GRIBRasterBand *poLastUsedBand;
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            GRIBRasterBand                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class GRIBRasterBand : public GDALPamRasterBand
+{
+    friend class GRIBDataset;
+
+public:
+    GRIBRasterBand( GRIBDataset *, int, inventoryType * );
+    virtual ~GRIBRasterBand();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual const char *GetDescription() const override;
+
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+
+    void    FindPDSTemplate();
+
+    void    UncacheData();
+
+private:
+    CPLErr       LoadData();
+
+    static void ReadGribData( DataSource &, sInt4, int, double **,
+                              grib_MetaData ** );
+    sInt4 start;
+    int subgNum;
+    char *longFstLevel;
+
+    double *m_Grib_Data;
+    grib_MetaData *m_Grib_MetaData;
+
+    int nGribDataXSize;
+    int nGribDataYSize;
+};
+
+namespace gdal {
+namespace grib {
+
+// Thin layer to manage allocation and deallocation.
+class InventoryWrapper {
+  public:
+    explicit InventoryWrapper(const std::string &filepath)
+        : inv_(NULL), inv_len_(0), num_messages_(0), result_(0) {
+      FileDataSource grib(filepath.c_str());
+      result_ = GRIB2Inventory(grib, &inv_, &inv_len_, 0 /* all messages */,
+                               &num_messages_);
+    }
+    explicit InventoryWrapper(FileDataSource file_data_source)
+        : inv_(NULL), inv_len_(0), num_messages_(0), result_(0) {
+      result_ = GRIB2Inventory(file_data_source, &inv_, &inv_len_,
+                               0 /* all messages */, &num_messages_);
+    }
+
+    ~InventoryWrapper() {
+        if (inv_ == NULL) return;
+        for (uInt4 i = 0; i < inv_len_; i++) {
+            GRIB2InventoryFree(inv_ + i);
+        }
+        free(inv_);
+    }
+
+    // Modifying the contents pointed to by the return is allowed.
+    inventoryType * get(int i) const {
+      if (i < 0 || i >= static_cast<int>(inv_len_)) return NULL;
+      return inv_ + i;
+    }
+
+    uInt4 length() const { return inv_len_; }
+    size_t num_messages() const { return num_messages_; }
+    int result() const { return result_; }
+
+  private:
+    inventoryType *inv_;
+    uInt4 inv_len_;
+    int num_messages_;
+    int result_;
+};
+
+}  // namespace grib
+}  // namespace gdal
diff --git a/frmts/grib/makefile.vc b/frmts/grib/makefile.vc
index 5fe3622..1dd285a 100644
--- a/frmts/grib/makefile.vc
+++ b/frmts/grib/makefile.vc
@@ -11,6 +11,11 @@ LINK_PNG	=	$(PNG_LIB)
 LINK_PNG	=	..\png\libpng\*.obj
 !ENDIF
 
+!IFDEF ZLIB_EXTERNAL_LIB
+LINK_ZLIB = $(ZLIB_LIB)
+!ELSE
+LINK_ZLIB = ..\zlib\*.obj
+!ENDIF
 
 default:	$(OBJ)
         cd degrib18 && $(MAKE) /f makefile.vc && cd ..
@@ -29,4 +34,4 @@ plugin:	gdal_GRIB.dll
 gdal_GRIB.dll: default
 	link /dll $(LDEBUG) /out:gdal_GRIB.dll \
 		$(OBJ) degrib18\degrib\*.obj degrib18\g2clib-1.0.4\*.obj \
-		$(GDAL_ROOT)/gdal_i.lib $(LINK_PNG) ..\zlib\*.obj
+		$(GDAL_ROOT)/gdal_i.lib $(LINK_PNG) $(LINK_ZLIB)
diff --git a/frmts/gsg/gs7bgdataset.cpp b/frmts/gsg/gs7bgdataset.cpp
index 6ab7e64..15d5ca5 100644
--- a/frmts/gsg/gs7bgdataset.cpp
+++ b/frmts/gsg/gs7bgdataset.cpp
@@ -1,5 +1,4 @@
 /****************************************************************************
- * $Id: gs7bgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software Surfer 7 Binary Grid Format.
@@ -38,6 +37,8 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
+CPL_CVSID("$Id: gs7bgdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+
 #ifndef DBL_MAX
 # ifdef __DBL_MAX__
 #  define DBL_MAX __DBL_MAX__
@@ -62,8 +63,6 @@
 # define SHRT_MAX 32767
 #endif /* SHRT_MAX */
 
-CPL_CVSID("$Id: gs7bgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
-
 /************************************************************************/
 /* ==================================================================== */
 /*                GS7BGDataset                */
@@ -110,11 +109,10 @@ class GS7BGDataset : public GDALPamDataset
                     GDALProgressFunc pfnProgress,
                     void *pProgressData );
 
-    CPLErr GetGeoTransform( double *padfGeoTransform );
-    CPLErr SetGeoTransform( double *padfGeoTransform );
+    CPLErr GetGeoTransform( double *padfGeoTransform ) override;
+    CPLErr SetGeoTransform( double *padfGeoTransform ) override;
 };
 
-
 const size_t GS7BGDataset::nHEADER_SIZE = 100;
 
 static const long  nHEADER_TAG = 0x42525344;
@@ -153,12 +151,12 @@ class GS7BGRasterBand : public GDALPamRasterBand
     GS7BGRasterBand( GS7BGDataset *, int );
     ~GS7BGRasterBand();
 
-    CPLErr IReadBlock( int, int, void * );
-    CPLErr IWriteBlock( int, int, void * );
-    double GetMinimum( int *pbSuccess = NULL );
-    double GetMaximum( int *pbSuccess = NULL );
+    CPLErr IReadBlock( int, int, void * ) override;
+    CPLErr IWriteBlock( int, int, void * ) override;
+    double GetMinimum( int *pbSuccess = NULL ) override;
+    double GetMaximum( int *pbSuccess = NULL ) override;
 
-    double GetNoDataValue( int *pbSuccess = NULL );
+    double GetNoDataValue( int *pbSuccess = NULL ) override;
 };
 
 /************************************************************************/
@@ -166,7 +164,11 @@ class GS7BGRasterBand : public GDALPamRasterBand
 /************************************************************************/
 
 GS7BGRasterBand::GS7BGRasterBand( GS7BGDataset *poDSIn, int nBandIn ) :
-    dfMinX(0.0), dfMaxX(0.0), dfMinY(0.0), dfMaxY(0.0), dfMinZ(0.0),
+    dfMinX(0.0),
+    dfMaxX(0.0),
+    dfMinY(0.0),
+    dfMaxY(0.0),
+    dfMinZ(0.0),
     dfMaxZ(0.0),
     pafRowMinZ(NULL),
     pafRowMaxZ(NULL),
@@ -174,8 +176,8 @@ GS7BGRasterBand::GS7BGRasterBand( GS7BGDataset *poDSIn, int nBandIn ) :
     nMaxZRow(-1)
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Float64;
 
@@ -1092,7 +1094,6 @@ CPLErr GS7BGDataset::WriteHeader( VSILFILE *fp, GInt32 nXSize, GInt32 nYSize,
         return CE_Failure;
     }
 
-
     return CE_None;
 }
 
diff --git a/frmts/gsg/gsagdataset.cpp b/frmts/gsg/gsagdataset.cpp
index f011b65..a38fcaa 100644
--- a/frmts/gsg/gsagdataset.cpp
+++ b/frmts/gsg/gsagdataset.cpp
@@ -1,10 +1,9 @@
 /******************************************************************************
- * $Id: gsagdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software ASCII Grid Format.
  * Author:   Kevin Locke, kwl7 at cornell.edu
- *	     (Based largely on aaigriddataset.cpp by Frank Warmerdam)
+ *           (Based largely on aaigriddataset.cpp by Frank Warmerdam)
  *
  ******************************************************************************
  * Copyright (c) 2006, Kevin Locke <kwl7 at cornell.edu>
@@ -39,6 +38,8 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
+CPL_CVSID("$Id: gsagdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+
 #ifndef DBL_MAX
 # ifdef __DBL_MAX__
 #  define DBL_MAX __DBL_MAX__
@@ -51,11 +52,9 @@
 # define INT_MAX 2147483647
 #endif /* INT_MAX */
 
-CPL_CVSID("$Id: gsagdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
-
 /************************************************************************/
 /* ==================================================================== */
-/*				GSAGDataset				*/
+/*                              GSAGDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -71,26 +70,26 @@ class GSAGDataset : public GDALPamDataset
 
     static CPLErr ShiftFileContents( VSILFILE *, vsi_l_offset, int, const char * );
 
-    VSILFILE	*fp;
-    size_t	 nMinMaxZOffset;
-    char	 szEOL[3];
+    VSILFILE    *fp;
+    size_t       nMinMaxZOffset;
+    char         szEOL[3];
 
     CPLErr UpdateHeader();
 
   public:
-		GSAGDataset( const char *pszEOL = "\x0D\x0A" );
-		~GSAGDataset();
+    explicit     GSAGDataset( const char *pszEOL = "\x0D\x0A" );
+                ~GSAGDataset();
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *CreateCopy( const char *pszFilename,
-				    GDALDataset *poSrcDS,
-				    int bStrict, char **papszOptions,
-				    GDALProgressFunc pfnProgress,
-				    void *pProgressData );
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char **papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void *pProgressData );
 
-    CPLErr GetGeoTransform( double *padfGeoTransform );
-    CPLErr SetGeoTransform( double *padfGeoTransform );
+    CPLErr GetGeoTransform( double *padfGeoTransform ) override;
+    CPLErr SetGeoTransform( double *padfGeoTransform ) override;
 };
 
 /* NOTE:  This is not mentioned in the spec, but Surfer 8 uses this value */
@@ -129,23 +128,23 @@ class GSAGRasterBand : public GDALPamRasterBand
 
   public:
 
-    		GSAGRasterBand( GSAGDataset *, int, vsi_l_offset );
-    		~GSAGRasterBand();
+                GSAGRasterBand( GSAGDataset *, int, vsi_l_offset );
+                ~GSAGRasterBand();
 
-    CPLErr IReadBlock( int, int, void * );
-    CPLErr IWriteBlock( int, int, void * );
+    CPLErr IReadBlock( int, int, void * ) override;
+    CPLErr IWriteBlock( int, int, void * ) override;
 
-    double GetNoDataValue( int *pbSuccess = NULL );
-    double GetMinimum( int *pbSuccess = NULL );
-    double GetMaximum( int *pbSuccess = NULL );
+    double GetNoDataValue( int *pbSuccess = NULL ) override;
+    double GetMinimum( int *pbSuccess = NULL ) override;
+    double GetMaximum( int *pbSuccess = NULL ) override;
 };
 
 /************************************************************************/
 /*                            AlmostEqual()                             */
 /* This function is needed because in release mode "1.70141E+38" is not */
-/* parsed as 1.70141E+38 in the last bit of the mantissa.		*/
-/* See http://gcc.gnu.org/ml/gcc/2003-08/msg01195.html for some		*/
-/* explanation.								*/
+/* parsed as 1.70141E+38 in the last bit of the mantissa.               */
+/* See http://gcc.gnu.org/ml/gcc/2003-08/msg01195.html for some         */
+/* explanation.                                                         */
 /************************************************************************/
 
 static bool AlmostEqual( double dfVal1, double dfVal2 )
@@ -153,7 +152,7 @@ static bool AlmostEqual( double dfVal1, double dfVal2 )
 {
     const double dfTOLERANCE = 0.0000000001;
     if( dfVal1 == 0.0 || dfVal2 == 0.0 )
-	return fabs(dfVal1 - dfVal2) < dfTOLERANCE;
+        return fabs(dfVal1 - dfVal2) < dfTOLERANCE;
     return fabs((dfVal1 - dfVal2)/dfVal1) < dfTOLERANCE;
 }
 
@@ -162,37 +161,36 @@ static bool AlmostEqual( double dfVal1, double dfVal2 )
 /************************************************************************/
 
 GSAGRasterBand::GSAGRasterBand( GSAGDataset *poDSIn, int nBandIn,
-				vsi_l_offset nDataStart ) :
+                                vsi_l_offset nDataStart ) :
     dfMinX(0.0),
     dfMaxX(0.0),
     dfMinY(0.0),
     dfMaxY(0.0),
     dfMinZ(0.0),
     dfMaxZ(0.0),
-    nLastReadLine(0),
+    nLastReadLine(poDSIn->nRasterYSize),
     nMaxLineSize(128),
     padfRowMinZ(NULL),
     padfRowMaxZ(NULL),
     nMinZRow(-1),
     nMaxZRow(-1)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Float64;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 
-    panLineOffset =
-	(vsi_l_offset *)VSI_CALLOC_VERBOSE( poDSIn->nRasterYSize+1, sizeof(vsi_l_offset) );
+    panLineOffset = static_cast<vsi_l_offset *>(
+        VSI_CALLOC_VERBOSE( poDSIn->nRasterYSize+1, sizeof(vsi_l_offset) ));
     if( panLineOffset == NULL )
     {
-	return;
+        return;
     }
 
-    panLineOffset[poDSIn->nRasterYSize-1] = nDataStart;
-    nLastReadLine = poDSIn->nRasterYSize;
+    panLineOffset[poDSIn->nRasterYSize - 1] = nDataStart;
 }
 
 /************************************************************************/
@@ -216,7 +214,7 @@ CPLErr GSAGRasterBand::ScanForMinMaxZ()
     double *padfRowValues = (double *)VSI_MALLOC2_VERBOSE( nBlockXSize, sizeof(double) );
     if( padfRowValues == NULL )
     {
-	return CE_Failure;
+        return CE_Failure;
     }
 
     double dfNewMinZ = DBL_MAX;
@@ -230,53 +228,53 @@ CPLErr GSAGRasterBand::ScanForMinMaxZ()
     unsigned long nValuesRead = 0;
     for( int iRow=0; iRow<nRasterYSize; iRow++ )
     {
-	CPLErr eErr = IReadBlock( 0, iRow, padfRowValues );
-	if( eErr != CE_None )
-	{
-	    VSIFree( padfRowValues );
-	    return eErr;
-	}
+        CPLErr eErr = IReadBlock( 0, iRow, padfRowValues );
+        if( eErr != CE_None )
+        {
+            VSIFree( padfRowValues );
+            return eErr;
+        }
 
-	padfRowMinZ[iRow] = DBL_MAX;
-	padfRowMaxZ[iRow] = -DBL_MAX;
-	for( int iCell=0; iCell<nRasterXSize; iCell++ )
-	{
-	    if( AlmostEqual(padfRowValues[iCell], GSAGDataset::dfNODATA_VALUE) )
-		continue;
+        padfRowMinZ[iRow] = DBL_MAX;
+        padfRowMaxZ[iRow] = -DBL_MAX;
+        for( int iCell=0; iCell<nRasterXSize; iCell++ )
+        {
+            if( AlmostEqual(padfRowValues[iCell], GSAGDataset::dfNODATA_VALUE) )
+                continue;
 
-	    if( padfRowValues[iCell] < padfRowMinZ[iRow] )
-		padfRowMinZ[iRow] = padfRowValues[iCell];
+            if( padfRowValues[iCell] < padfRowMinZ[iRow] )
+                padfRowMinZ[iRow] = padfRowValues[iCell];
 
-	    if( padfRowValues[iCell] > padfRowMaxZ[iRow] )
-		padfRowMaxZ[iRow] = padfRowValues[iCell];
+            if( padfRowValues[iCell] > padfRowMaxZ[iRow] )
+                padfRowMaxZ[iRow] = padfRowValues[iCell];
 
-	    dfSum += padfRowValues[iCell];
-	    dfSum2 += padfRowValues[iCell] * padfRowValues[iCell];
-	    nValuesRead++;
-	}
+            dfSum += padfRowValues[iCell];
+            dfSum2 += padfRowValues[iCell] * padfRowValues[iCell];
+            nValuesRead++;
+        }
 
-	if( padfRowMinZ[iRow] < dfNewMinZ )
-	{
-	    dfNewMinZ = padfRowMinZ[iRow];
-	    nNewMinZRow = iRow;
-	}
+        if( padfRowMinZ[iRow] < dfNewMinZ )
+        {
+            dfNewMinZ = padfRowMinZ[iRow];
+            nNewMinZRow = iRow;
+        }
 
-	if( padfRowMaxZ[iRow] > dfNewMaxZ )
-	{
-	    dfNewMaxZ = padfRowMaxZ[iRow];
-	    nNewMaxZRow = iRow;
-	}
+        if( padfRowMaxZ[iRow] > dfNewMaxZ )
+        {
+            dfNewMaxZ = padfRowMaxZ[iRow];
+            nNewMaxZRow = iRow;
+        }
     }
 
     VSIFree( padfRowValues );
 
     if( nValuesRead == 0 )
     {
-	dfMinZ = 0.0;
-	dfMaxZ = 0.0;
-	nMinZRow = 0;
-	nMaxZRow = 0;
-	return CE_None;
+        dfMinZ = 0.0;
+        dfMaxZ = 0.0;
+        nMinZRow = 0;
+        nMaxZRow = 0;
+        return CE_None;
     }
 
     dfMinZ = dfNewMinZ;
@@ -296,7 +294,7 @@ CPLErr GSAGRasterBand::ScanForMinMaxZ()
 /************************************************************************/
 
 CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-				   void * pImage )
+                                   void * pImage )
 {
     GSAGDataset *poGDS = (GSAGDataset *)poDS;
     assert( poGDS != NULL );
@@ -330,25 +328,25 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     /* If we know the offsets, we can just read line directly */
     if( (nBlockYOff > 0) && ( panLineOffset[nBlockYOff-1] != 0 ) )
     {
-	assert(panLineOffset[nBlockYOff-1] > panLineOffset[nBlockYOff]);
-	nLineBufSize = (size_t) (panLineOffset[nBlockYOff-1]
+        assert(panLineOffset[nBlockYOff-1] > panLineOffset[nBlockYOff]);
+        nLineBufSize = (size_t) (panLineOffset[nBlockYOff-1]
                                  - panLineOffset[nBlockYOff] + 1);
     }
 
     char *szLineBuf = (char *)VSI_MALLOC_VERBOSE( nLineBufSize );
     if( szLineBuf == NULL )
     {
-	return CE_Failure;
+        return CE_Failure;
     }
 
     size_t nCharsRead = VSIFReadL( szLineBuf, 1, nLineBufSize - 1, poGDS->fp );
     if( nCharsRead == 0 )
     {
-	VSIFree( szLineBuf );
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Can't read grid row %d at offset %ld.\n",
-		  nBlockYOff, (long) panLineOffset[nBlockYOff] );
-	return CE_Failure;
+        VSIFree( szLineBuf );
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Can't read grid row %d at offset %ld.\n",
+                  nBlockYOff, (long) panLineOffset[nBlockYOff] );
+        return CE_Failure;
     }
     szLineBuf[nCharsRead] = '\0';
 
@@ -357,10 +355,10 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     char *szEnd = szStart;
     for( int iCell=0; iCell<nBlockXSize; szStart = szEnd )
     {
-	double dfValue = CPLStrtod( szStart, &szEnd );
-	if( szStart == szEnd )
-	{
-	    /* No number found */
+        double dfValue = CPLStrtod( szStart, &szEnd );
+        if( szStart == szEnd )
+        {
+            /* No number found */
             if( *szStart == '.' )
             {
                 CPLError( CE_Warning, CPLE_FileIO,
@@ -370,82 +368,82 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 return CE_Failure;
             }
 
-	    /* Check if this was an expected failure */
-	    while( isspace( (unsigned char)*szStart ) )
-		szStart++;
+            /* Check if this was an expected failure */
+            while( isspace( (unsigned char)*szStart ) )
+                szStart++;
 
-	    /* Found sign at end of input, seek back to re-read it */
+            /* Found sign at end of input, seek back to re-read it */
             bool bOnlySign = false;
-	    if ( (*szStart == '-' || *szStart == '+') && *(szStart+1) == '\0' )
-	    {
-	    	if( VSIFSeekL( poGDS->fp,
+            if ( (*szStart == '-' || *szStart == '+') && *(szStart+1) == '\0' )
+            {
+                if( VSIFSeekL( poGDS->fp,
                                VSIFTellL( poGDS->fp)-1,
                                SEEK_SET ) != 0 )
-	    	{
-		    VSIFree( szLineBuf );
-		    CPLError( CE_Failure, CPLE_FileIO,
-			      "Unable to seek in grid row %d "
-			      "(offset %ld, seek %d).\n",
-			      nBlockYOff,
+                {
+                    VSIFree( szLineBuf );
+                    CPLError( CE_Failure, CPLE_FileIO,
+                              "Unable to seek in grid row %d "
+                              "(offset %ld, seek %d).\n",
+                              nBlockYOff,
                               (long) VSIFTellL(poGDS->fp),
-			      -1 );
-
-		    return CE_Failure;
-		}
-		bOnlySign = true;
-	    }
-	    else if( *szStart != '\0' )
-	    {
-		szEnd = szStart;
-		while( !isspace( (unsigned char)*szEnd ) && *szEnd != '\0' )
-		    szEnd++;
-		char cOldEnd = *szEnd;
-		*szEnd = '\0';
-
-		CPLError( CE_Warning, CPLE_FileIO,
-			  "Unexpected value in grid row %d (expected floating "
-			  "point value, found \"%s\").\n",
-			  nBlockYOff, szStart );
-
-		*szEnd = cOldEnd;
-
-		szEnd = szStart;
-		while( !isdigit( *szEnd ) && *szEnd != '.' && *szEnd != '\0' )
-		    szEnd++;
-
-		continue;
-	    }
-	    else if( static_cast<size_t>(szStart - szLineBuf) != nCharsRead )
-	    {
-		CPLError( CE_Warning, CPLE_FileIO,
-			  "Unexpected ASCII null-character in grid row %d at "
-			  "offset %ld.\n",
+                              -1 );
+
+                    return CE_Failure;
+                }
+                bOnlySign = true;
+            }
+            else if( *szStart != '\0' )
+            {
+                szEnd = szStart;
+                while( !isspace( (unsigned char)*szEnd ) && *szEnd != '\0' )
+                    szEnd++;
+                char cOldEnd = *szEnd;
+                *szEnd = '\0';
+
+                CPLError( CE_Warning, CPLE_FileIO,
+                          "Unexpected value in grid row %d (expected floating "
+                          "point value, found \"%s\").\n",
+                          nBlockYOff, szStart );
+
+                *szEnd = cOldEnd;
+
+                szEnd = szStart;
+                while( !isdigit( *szEnd ) && *szEnd != '.' && *szEnd != '\0' )
+                    szEnd++;
+
+                continue;
+            }
+            else if( static_cast<size_t>(szStart - szLineBuf) != nCharsRead )
+            {
+                CPLError( CE_Warning, CPLE_FileIO,
+                          "Unexpected ASCII null-character in grid row %d at "
+                          "offset %ld.\n",
                           nBlockYOff,
                           (long) (szStart - szLineBuf) );
 
-		while( *szStart == '\0' &&
+                while( *szStart == '\0' &&
                        static_cast<size_t>(szStart - szLineBuf) < nCharsRead )
-		    szStart++;
-
-		szEnd = szStart;
-		continue;
-	    }
-
-	    nCharsExamined += szStart - szLineBuf;
-	    nCharsRead = VSIFReadL( szLineBuf, 1, nLineBufSize - 1, poGDS->fp );
-	    if( nCharsRead == 0 || (bOnlySign && nCharsRead == 1) )
-	    {
-		VSIFree( szLineBuf );
-		CPLError( CE_Failure, CPLE_FileIO,
-			  "Can't read portion of grid row %d at offset %ld.",
-			  nBlockYOff, (long) panLineOffset[nBlockYOff] );
-		return CE_Failure;
-	    }
-	    szLineBuf[nCharsRead] = '\0';
-	    szEnd = szLineBuf;
-	    continue;
-	}
-	else if( *szEnd == '\0'
+                    szStart++;
+
+                szEnd = szStart;
+                continue;
+            }
+
+            nCharsExamined += szStart - szLineBuf;
+            nCharsRead = VSIFReadL( szLineBuf, 1, nLineBufSize - 1, poGDS->fp );
+            if( nCharsRead == 0 || (bOnlySign && nCharsRead == 1) )
+            {
+                VSIFree( szLineBuf );
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Can't read portion of grid row %d at offset %ld.",
+                          nBlockYOff, (long) panLineOffset[nBlockYOff] );
+                return CE_Failure;
+            }
+            szLineBuf[nCharsRead] = '\0';
+            szEnd = szLineBuf;
+            continue;
+        }
+        else if( *szEnd == '\0'
                  || (*szEnd == '.' && *(szEnd+1) == '\0')
                  || (*szEnd == '-' && *(szEnd+1) == '\0')
                  || (*szEnd == '+' && *(szEnd+1) == '\0')
@@ -455,83 +453,83 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                  || (*szEnd == 'e' && *(szEnd+1) == '\0')
                  || (*szEnd == 'e' && *(szEnd+1) == '-' && *(szEnd+2) == '\0')
                  || (*szEnd == 'e' && *(szEnd+1) == '+' && *(szEnd+2) == '\0'))
-	{
-	    /* Number was interrupted by a nul character */
-	    while( *szEnd != '\0' )
-		szEnd++;
-
-	    if( static_cast<size_t>(szEnd - szLineBuf) != nCharsRead )
-	    {
-		CPLError( CE_Warning, CPLE_FileIO,
-			  "Unexpected ASCII null-character in grid row %d at "
-			  "offset %ld.\n",
+        {
+            /* Number was interrupted by a nul character */
+            while( *szEnd != '\0' )
+                szEnd++;
+
+            if( static_cast<size_t>(szEnd - szLineBuf) != nCharsRead )
+            {
+                CPLError( CE_Warning, CPLE_FileIO,
+                          "Unexpected ASCII null-character in grid row %d at "
+                          "offset %ld.\n",
                           nBlockYOff,
                           (long) (szStart - szLineBuf) );
 
-		while( *szEnd == '\0' &&
-		       static_cast<size_t>(szEnd - szLineBuf) < nCharsRead )
-		    szEnd++;
+                while( *szEnd == '\0' &&
+                       static_cast<size_t>(szEnd - szLineBuf) < nCharsRead )
+                    szEnd++;
 
-		continue;
-	    }
+                continue;
+            }
 
-	    /* End of buffer, could be interrupting a number */
-	    if( VSIFSeekL( poGDS->fp, VSIFTellL(poGDS->fp) + szStart - szEnd, SEEK_SET ) != 0 )
-	    {
-		VSIFree( szLineBuf );
-		CPLError( CE_Failure, CPLE_FileIO,
-			  "Unable to seek in grid row %d (offset %ld, seek %d)"
-			  ".\n", nBlockYOff,
+            /* End of buffer, could be interrupting a number */
+            if( VSIFSeekL( poGDS->fp, VSIFTellL(poGDS->fp) + szStart - szEnd, SEEK_SET ) != 0 )
+            {
+                VSIFree( szLineBuf );
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Unable to seek in grid row %d (offset %ld, seek %d)"
+                          ".\n", nBlockYOff,
                           (long) VSIFTellL(poGDS->fp),
-			  (int) (szStart - szEnd) );
-
-		return CE_Failure;
-	    }
-	    nCharsExamined += szStart - szLineBuf;
-	    nCharsRead = VSIFReadL( szLineBuf, 1, nLineBufSize - 1, poGDS->fp );
-	    szLineBuf[nCharsRead] = '\0';
-
-	    if( nCharsRead == 0 )
-	    {
-		VSIFree( szLineBuf );
-		CPLError( CE_Failure, CPLE_FileIO,
-			  "Can't read portion of grid row %d at offset %ld.",
-			  nBlockYOff, (long) panLineOffset[nBlockYOff] );
-		return CE_Failure;
-	    }
-	    else if( nCharsRead > static_cast<size_t>(szEnd - szStart) )
-	    {
-		/* Read new data, this was not really the end */
-		szEnd = szStart = szLineBuf;
-		continue;
-	    }
-
-	    /* This is really the last value and has no tailing newline */
-	    szEnd = szLineBuf + nCharsRead;
-	}
-
-	if( pdfImage != NULL )
-	{
-	    *(pdfImage+iCell) = dfValue;
-	}
-
-	iCell++;
+                          (int) (szStart - szEnd) );
+
+                return CE_Failure;
+            }
+            nCharsExamined += szStart - szLineBuf;
+            nCharsRead = VSIFReadL( szLineBuf, 1, nLineBufSize - 1, poGDS->fp );
+            szLineBuf[nCharsRead] = '\0';
+
+            if( nCharsRead == 0 )
+            {
+                VSIFree( szLineBuf );
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Can't read portion of grid row %d at offset %ld.",
+                          nBlockYOff, (long) panLineOffset[nBlockYOff] );
+                return CE_Failure;
+            }
+            else if( nCharsRead > static_cast<size_t>(szEnd - szStart) )
+            {
+                /* Read new data, this was not really the end */
+                szEnd = szLineBuf;
+                continue;
+            }
+
+            /* This is really the last value and has no tailing newline */
+            szEnd = szLineBuf + nCharsRead;
+        }
+
+        if( pdfImage != NULL )
+        {
+            *(pdfImage+iCell) = dfValue;
+        }
+
+        iCell++;
     }
 
     while( *szEnd == ' ' )
-	szEnd++;
+        szEnd++;
 
     if( *szEnd != '\0' && *szEnd != poGDS->szEOL[0] )
-	CPLDebug( "GSAG", "Grid row %d does not end with a newline.  "
+        CPLDebug( "GSAG", "Grid row %d does not end with a newline.  "
                   "Possible skew.\n", nBlockYOff );
 
     while( isspace( (unsigned char)*szEnd ) )
-	szEnd++;
+        szEnd++;
 
     nCharsExamined += szEnd - szLineBuf;
 
     if( nCharsExamined >= nMaxLineSize )
-	nMaxLineSize = nCharsExamined + 1;
+        nMaxLineSize = nCharsExamined + 1;
 
     if( nBlockYOff > 0 )
         panLineOffset[nBlockYOff - 1] =
@@ -549,49 +547,49 @@ CPLErr GSAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr GSAGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-				    void * pImage )
+                                    void * pImage )
 
 {
     if( eAccess == GA_ReadOnly )
     {
-	CPLError( CE_Failure, CPLE_NoWriteAccess,
-		  "Unable to write block, dataset opened read only.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to write block, dataset opened read only.\n" );
+        return CE_Failure;
     }
 
     if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
-	return CE_Failure;
+        return CE_Failure;
 
     GSAGDataset *poGDS = (GSAGDataset *)poDS;
     assert( poGDS != NULL );
 
     if( padfRowMinZ == NULL || padfRowMaxZ == NULL
-	|| nMinZRow < 0 || nMaxZRow < 0 )
+        || nMinZRow < 0 || nMaxZRow < 0 )
     {
-	padfRowMinZ = (double *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(double) );
-	if( padfRowMinZ == NULL )
-	{
-	    return CE_Failure;
-	}
+        padfRowMinZ = (double *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(double) );
+        if( padfRowMinZ == NULL )
+        {
+            return CE_Failure;
+        }
 
-	padfRowMaxZ = (double *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(double) );
-	if( padfRowMaxZ == NULL )
-	{
-	    VSIFree( padfRowMinZ );
-	    padfRowMinZ = NULL;
-	    return CE_Failure;
-	}
+        padfRowMaxZ = (double *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(double) );
+        if( padfRowMaxZ == NULL )
+        {
+            VSIFree( padfRowMinZ );
+            padfRowMinZ = NULL;
+            return CE_Failure;
+        }
 
-	CPLErr eErr = ScanForMinMaxZ();
-	if( eErr != CE_None )
-	    return eErr;
+        CPLErr eErr = ScanForMinMaxZ();
+        if( eErr != CE_None )
+            return eErr;
     }
 
     if( panLineOffset[nBlockYOff+1] == 0 )
-	IReadBlock( nBlockXOff, nBlockYOff, NULL );
+        IReadBlock( nBlockXOff, nBlockYOff, NULL );
 
     if( panLineOffset[nBlockYOff+1] == 0 || panLineOffset[nBlockYOff] == 0 )
-	return CE_Failure;
+        return CE_Failure;
 
     std::ostringstream ssOutBuf;
     ssOutBuf.precision( GSAGDataset::nFIELD_PRECISION );
@@ -602,120 +600,120 @@ CPLErr GSAGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     padfRowMaxZ[nBlockYOff] = -DBL_MAX;
     for( int iCell=0; iCell<nBlockXSize; )
     {
-	for( int iCol=0; iCol<10 && iCell<nBlockXSize; iCol++, iCell++ )
-	{
-	    if( AlmostEqual( pdfImage[iCell], GSAGDataset::dfNODATA_VALUE ) )
-	    {
-		if( pdfImage[iCell] < padfRowMinZ[nBlockYOff] )
-		    padfRowMinZ[nBlockYOff] = pdfImage[iCell];
+        for( int iCol=0; iCol<10 && iCell<nBlockXSize; iCol++, iCell++ )
+        {
+            if( AlmostEqual( pdfImage[iCell], GSAGDataset::dfNODATA_VALUE ) )
+            {
+                if( pdfImage[iCell] < padfRowMinZ[nBlockYOff] )
+                    padfRowMinZ[nBlockYOff] = pdfImage[iCell];
 
-		if( pdfImage[iCell] > padfRowMaxZ[nBlockYOff] )
-		    padfRowMaxZ[nBlockYOff] = pdfImage[iCell];
-	    }
+                if( pdfImage[iCell] > padfRowMaxZ[nBlockYOff] )
+                    padfRowMaxZ[nBlockYOff] = pdfImage[iCell];
+            }
 
-	    ssOutBuf << pdfImage[iCell] << " ";
-	}
-	ssOutBuf << poGDS->szEOL;
+            ssOutBuf << pdfImage[iCell] << " ";
+        }
+        ssOutBuf << poGDS->szEOL;
     }
     ssOutBuf << poGDS->szEOL;
 
     CPLString sOut = ssOutBuf.str();
     if( sOut.length() != panLineOffset[nBlockYOff+1]-panLineOffset[nBlockYOff] )
     {
-	int nShiftSize = (int) (sOut.length() - (panLineOffset[nBlockYOff+1]
+        int nShiftSize = (int) (sOut.length() - (panLineOffset[nBlockYOff+1]
                                                  - panLineOffset[nBlockYOff]));
-	if( nBlockYOff != poGDS->nRasterYSize
-	    && GSAGDataset::ShiftFileContents( poGDS->fp,
-					       panLineOffset[nBlockYOff+1],
-					       nShiftSize,
-					       poGDS->szEOL ) != CE_None )
-	{
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Failure writing block, "
-		      "unable to shift file contents.\n" );
-	    return CE_Failure;
-	}
-
-	for( size_t iLine=nBlockYOff+1;
-	     iLine < static_cast<unsigned>(poGDS->nRasterYSize+1)
-		&& panLineOffset[iLine] != 0; iLine++ )
-	    panLineOffset[iLine] += nShiftSize;
+        if( nBlockYOff != poGDS->nRasterYSize
+            && GSAGDataset::ShiftFileContents( poGDS->fp,
+                                               panLineOffset[nBlockYOff+1],
+                                               nShiftSize,
+                                               poGDS->szEOL ) != CE_None )
+        {
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Failure writing block, "
+                      "unable to shift file contents.\n" );
+            return CE_Failure;
+        }
+
+        for( size_t iLine=nBlockYOff+1;
+             iLine < static_cast<unsigned>(poGDS->nRasterYSize+1)
+                && panLineOffset[iLine] != 0; iLine++ )
+            panLineOffset[iLine] += nShiftSize;
     }
 
     if( VSIFSeekL( poGDS->fp, panLineOffset[nBlockYOff], SEEK_SET ) != 0 )
     {
-	CPLError( CE_Failure, CPLE_FileIO, "Unable to seek to grid line.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO, "Unable to seek to grid line.\n" );
+        return CE_Failure;
     }
 
     if( VSIFWriteL( sOut.c_str(), 1, sOut.length(),
-		    poGDS->fp ) != sOut.length() )
+                    poGDS->fp ) != sOut.length() )
     {
-	CPLError( CE_Failure, CPLE_FileIO, "Unable to write grid block.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO, "Unable to write grid block.\n" );
+        return CE_Failure;
     }
 
     /* Update header as needed */
     bool bHeaderNeedsUpdate = false;
     if( nMinZRow == nBlockYOff && padfRowMinZ[nBlockYOff] > dfMinZ )
     {
-	double dfNewMinZ = -DBL_MAX;
-	for( int iRow=0; iRow<nRasterYSize; iRow++ )
-	{
-	    if( padfRowMinZ[iRow] < dfNewMinZ )
-	    {
-		dfNewMinZ = padfRowMinZ[iRow];
-		nMinZRow = iRow;
-	    }
-	}
+        double dfNewMinZ = -DBL_MAX;
+        for( int iRow=0; iRow<nRasterYSize; iRow++ )
+        {
+            if( padfRowMinZ[iRow] < dfNewMinZ )
+            {
+                dfNewMinZ = padfRowMinZ[iRow];
+                nMinZRow = iRow;
+            }
+        }
 
-	if( dfNewMinZ != dfMinZ )
-	{
-	    dfMinZ = dfNewMinZ;
-	    bHeaderNeedsUpdate = true;
-	}
+        if( dfNewMinZ != dfMinZ )
+        {
+            dfMinZ = dfNewMinZ;
+            bHeaderNeedsUpdate = true;
+        }
     }
 
     if( nMaxZRow == nBlockYOff && padfRowMaxZ[nBlockYOff] < dfMaxZ )
     {
-	double dfNewMaxZ = -DBL_MAX;
-	for( int iRow=0; iRow<nRasterYSize; iRow++ )
-	{
-	    if( padfRowMaxZ[iRow] > dfNewMaxZ )
-	    {
-		dfNewMaxZ = padfRowMaxZ[iRow];
-		nMaxZRow = iRow;
-	    }
-	}
+        double dfNewMaxZ = -DBL_MAX;
+        for( int iRow=0; iRow<nRasterYSize; iRow++ )
+        {
+            if( padfRowMaxZ[iRow] > dfNewMaxZ )
+            {
+                dfNewMaxZ = padfRowMaxZ[iRow];
+                nMaxZRow = iRow;
+            }
+        }
 
-	if( dfNewMaxZ != dfMaxZ )
-	{
-	    dfMaxZ = dfNewMaxZ;
-	    bHeaderNeedsUpdate = true;
-	}
+        if( dfNewMaxZ != dfMaxZ )
+        {
+            dfMaxZ = dfNewMaxZ;
+            bHeaderNeedsUpdate = true;
+        }
     }
 
     if( padfRowMinZ[nBlockYOff] < dfMinZ || padfRowMaxZ[nBlockYOff] > dfMaxZ )
     {
-	if( padfRowMinZ[nBlockYOff] < dfMinZ )
-	{
-	    dfMinZ = padfRowMinZ[nBlockYOff];
-	    nMinZRow = nBlockYOff;
-	}
+        if( padfRowMinZ[nBlockYOff] < dfMinZ )
+        {
+            dfMinZ = padfRowMinZ[nBlockYOff];
+            nMinZRow = nBlockYOff;
+        }
 
-	if( padfRowMaxZ[nBlockYOff] > dfMaxZ )
-	{
-	    dfMaxZ = padfRowMaxZ[nBlockYOff];
-	    nMaxZRow = nBlockYOff;
-	}
+        if( padfRowMaxZ[nBlockYOff] > dfMaxZ )
+        {
+            dfMaxZ = padfRowMaxZ[nBlockYOff];
+            nMaxZRow = nBlockYOff;
+        }
 
-	bHeaderNeedsUpdate = true;
+        bHeaderNeedsUpdate = true;
     }
 
     if( bHeaderNeedsUpdate && dfMaxZ > dfMinZ )
     {
-	CPLErr eErr = poGDS->UpdateHeader();
-	return eErr;
+        CPLErr eErr = poGDS->UpdateHeader();
+        return eErr;
     }
 
     return CE_None;
@@ -759,7 +757,7 @@ double GSAGRasterBand::GetMaximum( int *pbSuccess )
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GSAGDataset				*/
+/*                              GSAGDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -773,15 +771,14 @@ GSAGDataset::GSAGDataset( const char *pszEOL ) :
 {
     if( pszEOL == NULL || EQUAL(pszEOL, "") )
     {
-	CPLDebug( "GSAG", "GSAGDataset() created with invalid EOL string.\n" );
-	szEOL[0] = '\x0D';
-	szEOL[1] = '\x0A';
-	szEOL[2] = '\0';
+        CPLDebug( "GSAG", "GSAGDataset() created with invalid EOL string.\n" );
+        szEOL[0] = '\x0D';
+        szEOL[1] = '\x0A';
+        szEOL[2] = '\0';
         return;
     }
 
-    strncpy(szEOL, pszEOL, sizeof(szEOL));
-    szEOL[sizeof(this->szEOL) - 1] = '\0';
+    snprintf(szEOL, sizeof(szEOL), "%s", pszEOL);
 }
 
 /************************************************************************/
@@ -833,12 +830,12 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     szEOL[1] = poOpenInfo->pabyHeader[5];
     szEOL[2] = '\0';
     if( szEOL[1] != '\x0D' && szEOL[1] != '\x0A' )
-	szEOL[1] = '\0';
+        szEOL[1] = '\0';
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GSAGDataset	*poDS = new GSAGDataset( szEOL );
+    GSAGDataset *poDS = new GSAGDataset( szEOL );
 
 /* -------------------------------------------------------------------- */
 /*      Open file with large file API.                                  */
@@ -846,59 +843,59 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->eAccess = poOpenInfo->eAccess;
     if( poOpenInfo->eAccess == GA_ReadOnly )
-	poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     else
-	poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
+        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
 
     if( poDS->fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "VSIFOpenL(%s) failed unexpectedly.",
                   poOpenInfo->pszFilename );
-	delete poDS;
+        delete poDS;
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
-    char *pabyHeader;
+    char *pabyHeader = NULL;
     bool bMustFreeHeader = false;
     if( poOpenInfo->nHeaderBytes >= static_cast<int>(nMAX_HEADER_SIZE) )
     {
-	pabyHeader = (char *)poOpenInfo->pabyHeader;
+        pabyHeader = (char *)poOpenInfo->pabyHeader;
     }
     else
     {
-	bMustFreeHeader = true;
-	pabyHeader = (char *)VSI_MALLOC_VERBOSE( nMAX_HEADER_SIZE );
-	if( pabyHeader == NULL )
-	{
+        bMustFreeHeader = true;
+        pabyHeader = (char *)VSI_MALLOC_VERBOSE( nMAX_HEADER_SIZE );
+        if( pabyHeader == NULL )
+        {
             delete poDS;
-	    return NULL;
-	}
+            return NULL;
+        }
 
-	size_t nRead = VSIFReadL( pabyHeader, 1, nMAX_HEADER_SIZE-1, poDS->fp );
-	pabyHeader[nRead] = '\0';
+        size_t nRead = VSIFReadL( pabyHeader, 1, nMAX_HEADER_SIZE-1, poDS->fp );
+        pabyHeader[nRead] = '\0';
     }
 
     const char *szErrorMsg = NULL;
     const char *szStart = pabyHeader + 5;
-    char *szEnd;
+    char *szEnd = NULL;
     double dfTemp;
 
     /* Parse number of X axis grid rows */
     long nTemp = strtol( szStart, &szEnd, 10 );
     if( szStart == szEnd || nTemp < 0l )
     {
-	szErrorMsg = "Unable to parse the number of X axis grid columns.\n";
-	goto error;
+        szErrorMsg = "Unable to parse the number of X axis grid columns.\n";
+        goto error;
     }
     else if( nTemp > INT_MAX )
     {
-	CPLError( CE_Warning, CPLE_AppDefined,
-		  "Number of X axis grid columns not representable.\n" );
-	poDS->nRasterXSize = INT_MAX;
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Number of X axis grid columns not representable.\n" );
+        poDS->nRasterXSize = INT_MAX;
     }
     else if ( nTemp == 0 )
     {
@@ -907,7 +904,7 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-	poDS->nRasterXSize = static_cast<int>(nTemp);
+        poDS->nRasterXSize = static_cast<int>(nTemp);
     }
     szStart = szEnd;
 
@@ -915,14 +912,14 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     nTemp = strtol( szStart, &szEnd, 10 );
     if( szStart == szEnd || nTemp < 0l )
     {
-	szErrorMsg = "Unable to parse the number of Y axis grid rows.\n";
-	goto error;
+        szErrorMsg = "Unable to parse the number of Y axis grid rows.\n";
+        goto error;
     }
     else if( nTemp > INT_MAX - 1 )
     {
-	CPLError( CE_Warning, CPLE_AppDefined,
-		  "Number of Y axis grid rows not representable.\n" );
-	poDS->nRasterYSize = INT_MAX - 1;
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Number of Y axis grid rows not representable.\n" );
+        poDS->nRasterYSize = INT_MAX - 1;
     }
     else if ( nTemp == 0)
     {
@@ -931,7 +928,7 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-	poDS->nRasterYSize = static_cast<int>(nTemp);
+        poDS->nRasterYSize = static_cast<int>(nTemp);
     }
     szStart = szEnd;
 
@@ -940,12 +937,12 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
-	szErrorMsg = "Unable to parse the minimum X value.\n";
-	goto error;
+        szErrorMsg = "Unable to parse the minimum X value.\n";
+        goto error;
     }
     else
     {
-	dfMinX = dfTemp;
+        dfMinX = dfTemp;
     }
     szStart = szEnd;
 
@@ -954,12 +951,12 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
-	szErrorMsg = "Unable to parse the maximum X value.\n";
-	goto error;
+        szErrorMsg = "Unable to parse the maximum X value.\n";
+        goto error;
     }
     else
     {
-	dfMaxX = dfTemp;
+        dfMaxX = dfTemp;
     }
     szStart = szEnd;
 
@@ -968,12 +965,12 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
-	szErrorMsg = "Unable to parse the minimum Y value.\n";
-	goto error;
+        szErrorMsg = "Unable to parse the minimum Y value.\n";
+        goto error;
     }
     else
     {
-	dfMinY = dfTemp;
+        dfMinY = dfTemp;
     }
     szStart = szEnd;
 
@@ -982,30 +979,30 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
-	szErrorMsg = "Unable to parse the maximum Y value.\n";
-	goto error;
+        szErrorMsg = "Unable to parse the maximum Y value.\n";
+        goto error;
     }
     else
     {
-	dfMaxY = dfTemp;
+        dfMaxY = dfTemp;
     }
     szStart = szEnd;
 
     /* Parse the minimum Z value of the grid */
     while( isspace( (unsigned char)*szStart ) )
-	szStart++;
+        szStart++;
     poDS->nMinMaxZOffset = szStart - pabyHeader;
 
     double dfMinZ;
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
-	szErrorMsg = "Unable to parse the minimum Z value.\n";
-	goto error;
+        szErrorMsg = "Unable to parse the minimum Z value.\n";
+        goto error;
     }
     else
     {
-	dfMinZ = dfTemp;
+        dfMinZ = dfTemp;
     }
     szStart = szEnd;
 
@@ -1014,16 +1011,16 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
     dfTemp = CPLStrtod( szStart, &szEnd );
     if( szStart == szEnd )
     {
-	szErrorMsg = "Unable to parse the maximum Z value.\n";
-	goto error;
+        szErrorMsg = "Unable to parse the maximum Z value.\n";
+        goto error;
     }
     else
     {
-	dfMaxZ = dfTemp;
+        dfMaxZ = dfTemp;
     }
 
     while( isspace((unsigned char)*szEnd) )
-	    szEnd++;
+            szEnd++;
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
@@ -1048,7 +1045,7 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( bMustFreeHeader )
     {
-	CPLFree( pabyHeader );
+        CPLFree( pabyHeader );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1062,12 +1059,12 @@ GDALDataset *GSAGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
 
-    return( poDS );
+    return poDS;
 
 error:
     if ( bMustFreeHeader )
     {
-	CPLFree( pabyHeader );
+        CPLFree( pabyHeader );
     }
 
     delete poDS;
@@ -1084,19 +1081,19 @@ error:
 CPLErr GSAGDataset::GetGeoTransform( double *padfGeoTransform )
 {
     if( padfGeoTransform == NULL )
-	return CE_Failure;
+        return CE_Failure;
 
     GSAGRasterBand *poGRB = (GSAGRasterBand *)GetRasterBand( 1 );
 
     if( poGRB == NULL )
     {
-	padfGeoTransform[0] = 0;
-	padfGeoTransform[1] = 1;
-	padfGeoTransform[2] = 0;
-	padfGeoTransform[3] = 0;
-	padfGeoTransform[4] = 0;
-	padfGeoTransform[5] = 1;
-	return CE_Failure;
+        padfGeoTransform[0] = 0;
+        padfGeoTransform[1] = 1;
+        padfGeoTransform[2] = 0;
+        padfGeoTransform[3] = 0;
+        padfGeoTransform[4] = 0;
+        padfGeoTransform[5] = 1;
+        return CE_Failure;
     }
 
     /* check if we have a PAM GeoTransform stored */
@@ -1105,7 +1102,7 @@ CPLErr GSAGDataset::GetGeoTransform( double *padfGeoTransform )
     CPLPopErrorHandler();
 
     if( eErr == CE_None )
-	return CE_None;
+        return CE_None;
 
     /* calculate pixel size first */
     padfGeoTransform[1] = (poGRB->dfMaxX - poGRB->dfMinX)/(nRasterXSize - 1);
@@ -1130,21 +1127,20 @@ CPLErr GSAGDataset::SetGeoTransform( double *padfGeoTransform )
 {
     if( eAccess == GA_ReadOnly )
     {
-	CPLError( CE_Failure, CPLE_NoWriteAccess,
-		  "Unable to set GeoTransform, dataset opened read only.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set GeoTransform, dataset opened read only.\n" );
+        return CE_Failure;
     }
 
     GSAGRasterBand *poGRB = (GSAGRasterBand *)GetRasterBand( 1 );
 
     if( poGRB == NULL || padfGeoTransform == NULL)
-	return CE_Failure;
+        return CE_Failure;
 
     /* non-zero transform 2 or 4 or negative 1 or 5 not supported natively */
-    CPLErr eErr = CE_None;
     /*if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0
-	|| padfGeoTransform[1] < 0.0 || padfGeoTransform[5] < 0.0 )
-	eErr = GDALPamDataset::SetGeoTransform( padfGeoTransform );*/
+        || padfGeoTransform[1] < 0.0 || padfGeoTransform[5] < 0.0 )
+        eErr = GDALPamDataset::SetGeoTransform( padfGeoTransform );*/
     // if( eErr != CE_None )
     //     return eErr;
 
@@ -1160,14 +1156,14 @@ CPLErr GSAGDataset::SetGeoTransform( double *padfGeoTransform )
         padfGeoTransform[5] * (nRasterYSize - 0.5) + padfGeoTransform[3];
     poGRB->dfMaxY = padfGeoTransform[3] + padfGeoTransform[5] / 2;
 
-    eErr = UpdateHeader();
+    CPLErr eErr = UpdateHeader();
 
     if( eErr != CE_None )
     {
-	poGRB->dfMinX = dfOldMinX;
-	poGRB->dfMaxX = dfOldMaxX;
-	poGRB->dfMinY = dfOldMinY;
-	poGRB->dfMaxY = dfOldMaxY;
+        poGRB->dfMinX = dfOldMinX;
+        poGRB->dfMaxX = dfOldMaxX;
+        poGRB->dfMinY = dfOldMinY;
+        poGRB->dfMaxY = dfOldMaxY;
     }
 
     return eErr;
@@ -1177,25 +1173,25 @@ CPLErr GSAGDataset::SetGeoTransform( double *padfGeoTransform )
 /*                         ShiftFileContents()                          */
 /************************************************************************/
 CPLErr GSAGDataset::ShiftFileContents( VSILFILE *fp, vsi_l_offset nShiftStart,
-				       int nShiftSize, const char *pszEOL )
+                                       int nShiftSize, const char *pszEOL )
 {
     /* nothing to do for zero-shift */
     if( nShiftSize == 0 )
-	return CE_None;
+        return CE_None;
 
     /* make sure start location is sane */
 /* Tautology is always false.  nShiftStart is unsigned. */
     if( /* nShiftStart < 0
            || */ (nShiftSize < 0
-	    && nShiftStart < static_cast<vsi_l_offset>(-nShiftSize)) )
-	nShiftStart = /*(nShiftSize > 0) ? 0 :*/  -nShiftSize;
+            && nShiftStart < static_cast<vsi_l_offset>(-nShiftSize)) )
+        nShiftStart = /*(nShiftSize > 0) ? 0 :*/  -nShiftSize;
 
     /* get offset at end of file */
     if( VSIFSeekL( fp, 0, SEEK_END ) != 0 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to seek to end of grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to seek to end of grid file.\n" );
+        return CE_Failure;
     }
 
     vsi_l_offset nOldEnd = VSIFTellL( fp );
@@ -1203,48 +1199,48 @@ CPLErr GSAGDataset::ShiftFileContents( VSILFILE *fp, vsi_l_offset nShiftStart,
     /* If shifting past end, just zero-pad as necessary */
     if( nShiftStart >= nOldEnd )
     {
-	if( nShiftSize < 0 )
-	{
-	    if( nShiftStart + nShiftSize >= nOldEnd )
-		return CE_None;
-
-	    if( VSIFSeekL( fp, nShiftStart + nShiftSize, SEEK_SET ) != 0 )
-	    {
-		CPLError( CE_Failure, CPLE_FileIO,
-			  "Unable to seek near end of file.\n" );
-		return CE_Failure;
-	    }
-
-	    /* ftruncate()? */
-	    for( vsi_l_offset nPos = nShiftStart + nShiftSize;
-		 nPos > nOldEnd; nPos++ )
-	    {
-		if( VSIFWriteL( (void *)" ", 1, 1, fp ) != 1 )
-		{
-		    CPLError( CE_Failure, CPLE_FileIO,
-			      "Unable to write padding to grid file "
-			      "(Out of space?).\n" );
-		    return CE_Failure;
-		}
-	    }
-
-	    return CE_None;
-	}
-	else
-	{
-	    for( vsi_l_offset nPos = nOldEnd;
-		 nPos < nShiftStart + nShiftSize; nPos++ )
-	    {
-		if( VSIFWriteL( (void *)" ", 1, 1, fp ) != 1 )
-		{
-		    CPLError( CE_Failure, CPLE_FileIO,
-			      "Unable to write padding to grid file "
-			      "(Out of space?).\n" );
-		    return CE_Failure;
-		}
-	    }
-	    return CE_None;
-	}
+        if( nShiftSize < 0 )
+        {
+            if( nShiftStart + nShiftSize >= nOldEnd )
+                return CE_None;
+
+            if( VSIFSeekL( fp, nShiftStart + nShiftSize, SEEK_SET ) != 0 )
+            {
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Unable to seek near end of file.\n" );
+                return CE_Failure;
+            }
+
+            /* ftruncate()? */
+            for( vsi_l_offset nPos = nShiftStart + nShiftSize;
+                 nPos > nOldEnd; nPos++ )
+            {
+                if( VSIFWriteL( (void *)" ", 1, 1, fp ) != 1 )
+                {
+                    CPLError( CE_Failure, CPLE_FileIO,
+                              "Unable to write padding to grid file "
+                              "(Out of space?).\n" );
+                    return CE_Failure;
+                }
+            }
+
+            return CE_None;
+        }
+        else
+        {
+            for( vsi_l_offset nPos = nOldEnd;
+                 nPos < nShiftStart + nShiftSize; nPos++ )
+            {
+                if( VSIFWriteL( (void *)" ", 1, 1, fp ) != 1 )
+                {
+                    CPLError( CE_Failure, CPLE_FileIO,
+                              "Unable to write padding to grid file "
+                              "(Out of space?).\n" );
+                    return CE_Failure;
+                }
+            }
+            return CE_None;
+        }
     }
 
     /* prepare buffer for real shifting */
@@ -1252,15 +1248,15 @@ CPLErr GSAGDataset::ShiftFileContents( VSILFILE *fp, vsi_l_offset nShiftStart,
     char *pabyBuffer = (char *)VSI_MALLOC_VERBOSE( nBufferSize );
     if( pabyBuffer == NULL)
     {
-	return CE_Failure;
+        return CE_Failure;
     }
 
     if( VSIFSeekL( fp, nShiftStart, SEEK_SET ) != 0 )
     {
-	VSIFree( pabyBuffer );
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to seek to start of shift in grid file.\n" );
-	return CE_Failure;
+        VSIFree( pabyBuffer );
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to seek to start of shift in grid file.\n" );
+        return CE_Failure;
     }
 
     size_t nRead;
@@ -1268,151 +1264,151 @@ CPLErr GSAGDataset::ShiftFileContents( VSILFILE *fp, vsi_l_offset nShiftStart,
     /* If there is overlap, fill buffer with the overlap to start */
     if( nOverlap > 0)
     {
-	nRead = VSIFReadL( (void *)pabyBuffer, 1, nOverlap, fp );
-	if( nRead < nOverlap && !VSIFEofL( fp ) )
-	{
-	    VSIFree( pabyBuffer );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Error reading grid file.\n" );
-	    return CE_Failure;
-	}
-
-	/* overwrite the new space with ' ' */
-    	if( VSIFSeekL( fp, nShiftStart, SEEK_SET ) != 0 )
-	{
-	    VSIFree( pabyBuffer );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to seek to start of shift in grid file.\n" );
-	    return CE_Failure;
-	}
-
-	for( int iFill=0; iFill<nShiftSize; iFill++ )
-	{
-	    if( VSIFWriteL( (void *)" ", 1, 1, fp ) != 1 )
-	    {
-		VSIFree( pabyBuffer );
-		CPLError( CE_Failure, CPLE_FileIO,
-			  "Unable to write padding to grid file "
-			  "(Out of space?).\n" );
-		return CE_Failure;
-	    }
-	}
-
-	/* if we have already read the entire file, finish it off */
-	if( VSIFTellL( fp ) >= nOldEnd )
-	{
-	    if( VSIFWriteL( (void *)pabyBuffer, 1, nRead, fp ) != nRead )
-	    {
-		VSIFree( pabyBuffer );
-		CPLError( CE_Failure, CPLE_FileIO,
-			  "Unable to write to grid file (Out of space?).\n" );
-		return CE_Failure;
-	    }
-
-	    VSIFree( pabyBuffer );
-	    return CE_None;
-	}
+        nRead = VSIFReadL( (void *)pabyBuffer, 1, nOverlap, fp );
+        if( nRead < nOverlap && !VSIFEofL( fp ) )
+        {
+            VSIFree( pabyBuffer );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Error reading grid file.\n" );
+            return CE_Failure;
+        }
+
+        /* overwrite the new space with ' ' */
+        if( VSIFSeekL( fp, nShiftStart, SEEK_SET ) != 0 )
+        {
+            VSIFree( pabyBuffer );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to seek to start of shift in grid file.\n" );
+            return CE_Failure;
+        }
+
+        for( int iFill=0; iFill<nShiftSize; iFill++ )
+        {
+            if( VSIFWriteL( (void *)" ", 1, 1, fp ) != 1 )
+            {
+                VSIFree( pabyBuffer );
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Unable to write padding to grid file "
+                          "(Out of space?).\n" );
+                return CE_Failure;
+            }
+        }
+
+        /* if we have already read the entire file, finish it off */
+        if( VSIFTellL( fp ) >= nOldEnd )
+        {
+            if( VSIFWriteL( (void *)pabyBuffer, 1, nRead, fp ) != nRead )
+            {
+                VSIFree( pabyBuffer );
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Unable to write to grid file (Out of space?).\n" );
+                return CE_Failure;
+            }
+
+            VSIFree( pabyBuffer );
+            return CE_None;
+        }
     }
 
     /* iterate over the remainder of the file and shift as requested */
     bool bEOF = false;
     while( !bEOF )
     {
-	nRead = VSIFReadL( (void *)(pabyBuffer+nOverlap), 1,
-			   nBufferSize - nOverlap, fp );
+        nRead = VSIFReadL( (void *)(pabyBuffer+nOverlap), 1,
+                           nBufferSize - nOverlap, fp );
 
         if( VSIFEofL( fp ) )
             bEOF = true;
         else
             bEOF = false;
 
-	if( nRead == 0 && !bEOF )
-	{
-	    VSIFree( pabyBuffer );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to read from grid file (possible corruption).\n");
-	    return CE_Failure;
-	}
-
-	/* FIXME:  Should use SEEK_CUR, review integer promotions... */
-	if( VSIFSeekL( fp, VSIFTellL(fp)-nRead+nShiftSize-nOverlap,
-		       SEEK_SET ) != 0 )
-	{
-	    VSIFree( pabyBuffer );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to seek in grid file (possible corruption).\n" );
-	    return CE_Failure;
-	}
-
-	size_t nWritten = VSIFWriteL( (void *)pabyBuffer, 1, nRead, fp );
-	if( nWritten != nRead )
-	{
-	    VSIFree( pabyBuffer );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to write to grid file (out of space?).\n" );
-	    return CE_Failure;
-	}
-
-	/* shift overlapped contents to the front of the buffer if necessary */
-	if( nOverlap > 0)
-	    memmove(pabyBuffer, pabyBuffer+nRead, nOverlap);
+        if( nRead == 0 && !bEOF )
+        {
+            VSIFree( pabyBuffer );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to read from grid file (possible corruption).\n");
+            return CE_Failure;
+        }
+
+        /* FIXME:  Should use SEEK_CUR, review integer promotions... */
+        if( VSIFSeekL( fp, VSIFTellL(fp)-nRead+nShiftSize-nOverlap,
+                       SEEK_SET ) != 0 )
+        {
+            VSIFree( pabyBuffer );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to seek in grid file (possible corruption).\n" );
+            return CE_Failure;
+        }
+
+        size_t nWritten = VSIFWriteL( (void *)pabyBuffer, 1, nRead, fp );
+        if( nWritten != nRead )
+        {
+            VSIFree( pabyBuffer );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to write to grid file (out of space?).\n" );
+            return CE_Failure;
+        }
+
+        /* shift overlapped contents to the front of the buffer if necessary */
+        if( nOverlap > 0)
+            memmove(pabyBuffer, pabyBuffer+nRead, nOverlap);
     }
 
     /* write the remainder of the buffer or overwrite leftovers and finish */
     if( nShiftSize > 0 )
     {
-	size_t nTailSize = nOverlap;
-	while( nTailSize > 0 && isspace( (unsigned char)pabyBuffer[nTailSize-1] ) )
-	    nTailSize--;
+        size_t nTailSize = nOverlap;
+        while( nTailSize > 0 && isspace( (unsigned char)pabyBuffer[nTailSize-1] ) )
+            nTailSize--;
 
-	if( VSIFWriteL( (void *)pabyBuffer, 1, nTailSize, fp ) != nTailSize )
-	{
-	    VSIFree( pabyBuffer );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to write to grid file (out of space?).\n" );
-	    return CE_Failure;
-	}
+        if( VSIFWriteL( (void *)pabyBuffer, 1, nTailSize, fp ) != nTailSize )
+        {
+            VSIFree( pabyBuffer );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to write to grid file (out of space?).\n" );
+            return CE_Failure;
+        }
 
-	if( VSIFWriteL( (void *)pszEOL, 1, strlen(pszEOL), fp )
+        if( VSIFWriteL( (void *)pszEOL, 1, strlen(pszEOL), fp )
             != strlen(pszEOL) )
-	{
-	    VSIFree( pabyBuffer );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to write to grid file (out of space?).\n" );
-	    return CE_Failure;
-	}
+        {
+            VSIFree( pabyBuffer );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to write to grid file (out of space?).\n" );
+            return CE_Failure;
+        }
     }
     else
     {
-	/* FIXME: ftruncate()? */
-	/* FIXME:  Should use SEEK_CUR, review integer promotions... */
-	if( VSIFSeekL( fp, VSIFTellL(fp)-strlen(pszEOL), SEEK_SET ) != 0 )
-	{
-	    VSIFree( pabyBuffer );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to seek in grid file.\n" );
-	    return CE_Failure;
-	}
-
-	for( int iPadding=0; iPadding<-nShiftSize; iPadding++ )
-	{
-	    if( VSIFWriteL( (void *)" ", 1, 1, fp ) != 1 )
-	    {
-		VSIFree( pabyBuffer );
-		CPLError( CE_Failure, CPLE_FileIO,
-			  "Error writing to grid file.\n" );
-		return CE_Failure;
-	    }
-	}
-
-	if( VSIFWriteL( (void *)pszEOL, 1, strlen(pszEOL), fp )
+        /* FIXME: ftruncate()? */
+        /* FIXME:  Should use SEEK_CUR, review integer promotions... */
+        if( VSIFSeekL( fp, VSIFTellL(fp)-strlen(pszEOL), SEEK_SET ) != 0 )
+        {
+            VSIFree( pabyBuffer );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to seek in grid file.\n" );
+            return CE_Failure;
+        }
+
+        for( int iPadding=0; iPadding<-nShiftSize; iPadding++ )
+        {
+            if( VSIFWriteL( (void *)" ", 1, 1, fp ) != 1 )
+            {
+                VSIFree( pabyBuffer );
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Error writing to grid file.\n" );
+                return CE_Failure;
+            }
+        }
+
+        if( VSIFWriteL( (void *)pszEOL, 1, strlen(pszEOL), fp )
             != strlen(pszEOL) )
-	{
-	    VSIFree( pabyBuffer );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to write to grid file (out of space?).\n" );
-	    return CE_Failure;
-	}
+        {
+            VSIFree( pabyBuffer );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to write to grid file (out of space?).\n" );
+            return CE_Failure;
+        }
     }
 
     VSIFree( pabyBuffer );
@@ -1429,8 +1425,8 @@ CPLErr GSAGDataset::UpdateHeader()
     GSAGRasterBand *poBand = (GSAGRasterBand *)GetRasterBand( 1 );
     if( poBand == NULL )
     {
-	CPLError( CE_Failure, CPLE_FileIO, "Unable to open raster band.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO, "Unable to open raster band.\n" );
+        return CE_Failure;
     }
 
     std::ostringstream ssOutBuf;
@@ -1455,35 +1451,35 @@ CPLErr GSAGDataset::UpdateHeader()
     CPLString sOut = ssOutBuf.str();
     if( sOut.length() != poBand->panLineOffset[0] )
     {
-	int nShiftSize = (int) (sOut.length() - poBand->panLineOffset[0]);
-	if( ShiftFileContents( fp, poBand->panLineOffset[0], nShiftSize,
-			       szEOL ) != CE_None )
-	{
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to update grid header, "
-		      "failure shifting file contents.\n" );
-	    return CE_Failure;
-	}
+        int nShiftSize = (int) (sOut.length() - poBand->panLineOffset[0]);
+        if( ShiftFileContents( fp, poBand->panLineOffset[0], nShiftSize,
+                               szEOL ) != CE_None )
+        {
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to update grid header, "
+                      "failure shifting file contents.\n" );
+            return CE_Failure;
+        }
 
-	for( size_t iLine=0;
-	     iLine < static_cast<unsigned>(nRasterYSize+1)
-		&& poBand->panLineOffset[iLine] != 0;
-	     iLine++ )
-	    poBand->panLineOffset[iLine] += nShiftSize;
+        for( size_t iLine=0;
+             iLine < static_cast<unsigned>(nRasterYSize+1)
+                && poBand->panLineOffset[iLine] != 0;
+             iLine++ )
+            poBand->panLineOffset[iLine] += nShiftSize;
     }
 
     if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to seek to start of grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to seek to start of grid file.\n" );
+        return CE_Failure;
     }
 
     if( VSIFWriteL( sOut.c_str(), 1, sOut.length(), fp ) != sOut.length() )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to update file header.  Disk full?\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to update file header.  Disk full?\n" );
+        return CE_Failure;
     }
 
     return CE_None;
@@ -1494,14 +1490,14 @@ CPLErr GSAGDataset::UpdateHeader()
 /************************************************************************/
 
 GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
-				      GDALDataset *poSrcDS,
-				      int bStrict,
+                                      GDALDataset *poSrcDS,
+                                      int bStrict,
                                       CPL_UNUSED char **papszOptions,
-				      GDALProgressFunc pfnProgress,
-				      void *pProgressData )
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData )
 {
     if( pfnProgress == NULL )
-	pfnProgress = GDALDummyProgress;
+        pfnProgress = GDALDummyProgress;
 
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
@@ -1512,17 +1508,17 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
     }
     else if (nBands > 1)
     {
-	if( bStrict )
-	{
-	    CPLError( CE_Failure, CPLE_NotSupported,
-		      "Unable to create copy, Golden Software ASCII Grid "
-		      "format only supports one raster band.\n" );
-	    return NULL;
-	}
-	else
-	    CPLError( CE_Warning, CPLE_NotSupported,
-		      "Golden Software ASCII Grid format only supports one "
-		      "raster band, first band will be copied.\n" );
+        if( bStrict )
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Unable to create copy, Golden Software ASCII Grid "
+                      "format only supports one raster band.\n" );
+            return NULL;
+        }
+        else
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Golden Software ASCII Grid format only supports one "
+                      "raster band, first band will be copied.\n" );
     }
 
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
@@ -1543,7 +1539,7 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
 
     const int nXSize = poSrcDS->GetRasterXSize();
     const int nYSize = poSrcDS->GetRasterYSize();
-    double	 adfGeoTransform[6];
+    double adfGeoTransform[6];
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
 
@@ -1556,17 +1552,17 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
     ssHeader << nXSize << " " << nYSize << "\x0D\x0A";
 
     ssHeader << adfGeoTransform[0] + adfGeoTransform[1] / 2 << " "
-	     << adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0]
-	     << "\x0D\x0A";
+             << adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0]
+             << "\x0D\x0A";
 
     ssHeader << adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3] << " "
-	     << adfGeoTransform[3] + adfGeoTransform[5] / 2
-	     << "\x0D\x0A";
+             << adfGeoTransform[3] + adfGeoTransform[5] / 2
+             << "\x0D\x0A";
 
     if( VSIFWriteL( (void *)ssHeader.str().c_str(), 1, ssHeader.str().length(),
-		    fp ) != ssHeader.str().length() )
+                    fp ) != ssHeader.str().length() )
     {
-	VSIFCloseL( fp );
+        VSIFCloseL( fp );
         CPLError( CE_Failure, CPLE_FileIO,
                   "Unable to create copy, writing header failed.\n" );
         return NULL;
@@ -1577,22 +1573,22 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
     const char *szDummyRange = "0.0000000000001 0.0000000000001\x0D\x0A";
     size_t nDummyRangeLen = strlen( szDummyRange );
     if( VSIFWriteL( (void *)szDummyRange, 1, nDummyRangeLen,
-		    fp ) != nDummyRangeLen )
+                    fp ) != nDummyRangeLen )
     {
-	VSIFCloseL( fp );
+        VSIFCloseL( fp );
         CPLError( CE_Failure, CPLE_FileIO,
                   "Unable to create copy, writing header failed.\n" );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Copy band data.							*/
+/*      Copy band data.                                                 */
 /* -------------------------------------------------------------------- */
     double *pdfData = (double *)VSI_MALLOC2_VERBOSE( nXSize, sizeof( double ) );
     if( pdfData == NULL )
     {
-	VSIFCloseL( fp );
-	return NULL;
+        VSIFCloseL( fp );
+        return NULL;
     }
 
     GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1);
@@ -1602,82 +1598,82 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
     double dfMax = -DBL_MAX;
     for( int iRow=0; iRow<nYSize; iRow++ )
     {
-	CPLErr eErr = poSrcBand->RasterIO( GF_Read, 0, nYSize-iRow-1,
-					   nXSize, 1, pdfData,
-					   nXSize, 1, GDT_Float64, 0, 0, NULL );
-
-	if( eErr != CE_None )
-	{
-	    VSIFCloseL( fp );
-	    VSIFree( pdfData );
-	    return NULL;
-	}
-
-	for( int iCol=0; iCol<nXSize; )
-	{
-	    for( int iCount=0;
-		 iCount<10 && iCol<nXSize;
-		 iCount++, iCol++ )
-	    {
-		double dfValue = pdfData[iCol];
-
-		if( bSrcHasNDValue && AlmostEqual( dfValue, dfSrcNoDataValue ) )
-		{
-		    dfValue = dfNODATA_VALUE;
-		}
-		else
-		{
-		    if( dfValue > dfMax )
-			dfMax = dfValue;
-
-		    if( dfValue < dfMin )
-			dfMin = dfValue;
-		}
-
-		std::ostringstream ssOut;
-		ssOut.precision(nFIELD_PRECISION);
-		ssOut.setf( std::ios::uppercase );
-		ssOut << dfValue << " ";
-		CPLString sOut = ssOut.str();
-
-		if( VSIFWriteL( sOut.c_str(), 1, sOut.length(), fp )
-		    != sOut.length() )
-		{
-		    VSIFCloseL( fp );
-		    VSIFree( pdfData );
-		    CPLError( CE_Failure, CPLE_FileIO,
-			      "Unable to write grid cell.  Disk full?\n" );
-		    return NULL;
-		}
-	    }
-
-	    if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 )
-	    {
-		VSIFCloseL( fp );
-		VSIFree( pdfData );
-		CPLError( CE_Failure, CPLE_FileIO,
-			  "Unable to finish write of grid line. Disk full?\n" );
-		return NULL;
-	    }
-	}
-
-	if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 )
-	{
-	    VSIFCloseL( fp );
-	    VSIFree( pdfData );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to finish write of grid row. Disk full?\n" );
-	    return NULL;
-	}
-
-	if( !pfnProgress( static_cast<double>(iRow + 1)/nYSize,
-			  NULL, pProgressData ) )
-	{
-	    VSIFCloseL( fp );
-	    VSIFree( pdfData );
-	    CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-	    return NULL;
-	}
+        CPLErr eErr = poSrcBand->RasterIO( GF_Read, 0, nYSize-iRow-1,
+                                           nXSize, 1, pdfData,
+                                           nXSize, 1, GDT_Float64, 0, 0, NULL );
+
+        if( eErr != CE_None )
+        {
+            VSIFCloseL( fp );
+            VSIFree( pdfData );
+            return NULL;
+        }
+
+        for( int iCol=0; iCol<nXSize; )
+        {
+            for( int iCount=0;
+                 iCount<10 && iCol<nXSize;
+                 iCount++, iCol++ )
+            {
+                double dfValue = pdfData[iCol];
+
+                if( bSrcHasNDValue && AlmostEqual( dfValue, dfSrcNoDataValue ) )
+                {
+                    dfValue = dfNODATA_VALUE;
+                }
+                else
+                {
+                    if( dfValue > dfMax )
+                        dfMax = dfValue;
+
+                    if( dfValue < dfMin )
+                        dfMin = dfValue;
+                }
+
+                std::ostringstream ssOut;
+                ssOut.precision(nFIELD_PRECISION);
+                ssOut.setf( std::ios::uppercase );
+                ssOut << dfValue << " ";
+                CPLString sOut = ssOut.str();
+
+                if( VSIFWriteL( sOut.c_str(), 1, sOut.length(), fp )
+                    != sOut.length() )
+                {
+                    VSIFCloseL( fp );
+                    VSIFree( pdfData );
+                    CPLError( CE_Failure, CPLE_FileIO,
+                              "Unable to write grid cell.  Disk full?\n" );
+                    return NULL;
+                }
+            }
+
+            if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 )
+            {
+                VSIFCloseL( fp );
+                VSIFree( pdfData );
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Unable to finish write of grid line. Disk full?\n" );
+                return NULL;
+            }
+        }
+
+        if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 )
+        {
+            VSIFCloseL( fp );
+            VSIFree( pdfData );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to finish write of grid row. Disk full?\n" );
+            return NULL;
+        }
+
+        if( !pfnProgress( static_cast<double>(iRow + 1)/nYSize,
+                          NULL, pProgressData ) )
+        {
+            VSIFCloseL( fp );
+            VSIFree( pdfData );
+            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+            return NULL;
+        }
     }
 
     VSIFree( pdfData );
@@ -1689,29 +1685,29 @@ GDALDataset *GSAGDataset::CreateCopy( const char *pszFilename,
     ssRange << dfMin << " " << dfMax << "\x0D\x0A";
     if( ssRange.str().length() != nDummyRangeLen )
     {
-	int nShiftSize = static_cast<int>(ssRange.str().length() - nDummyRangeLen);
-	if( ShiftFileContents( fp, nRangeStart + nDummyRangeLen,
-			       nShiftSize, "\x0D\x0A" ) != CE_None )
-	{
-	    VSIFCloseL( fp );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to shift file contents.\n" );
-	    return NULL;
-	}
+        int nShiftSize = static_cast<int>(ssRange.str().length() - nDummyRangeLen);
+        if( ShiftFileContents( fp, nRangeStart + nDummyRangeLen,
+                               nShiftSize, "\x0D\x0A" ) != CE_None )
+        {
+            VSIFCloseL( fp );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to shift file contents.\n" );
+            return NULL;
+        }
     }
 
     if( VSIFSeekL( fp, nRangeStart, SEEK_SET ) != 0 )
     {
-	VSIFCloseL( fp );
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to seek to start of grid file copy.\n" );
-	return NULL;
+        VSIFCloseL( fp );
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to seek to start of grid file copy.\n" );
+        return NULL;
     }
 
     if( VSIFWriteL( (void *)ssRange.str().c_str(), 1, ssRange.str().length(),
-		    fp ) != ssRange.str().length() )
+                    fp ) != ssRange.str().length() )
     {
-	VSIFCloseL( fp );
+        VSIFCloseL( fp );
         CPLError( CE_Failure, CPLE_FileIO,
                   "Unable to write range information.\n" );
         return NULL;
diff --git a/frmts/gsg/gsbgdataset.cpp b/frmts/gsg/gsbgdataset.cpp
index 1b1df5e..e435755 100644
--- a/frmts/gsg/gsbgdataset.cpp
+++ b/frmts/gsg/gsbgdataset.cpp
@@ -1,10 +1,9 @@
 /******************************************************************************
- * $Id: gsbgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements the Golden Software Binary Grid Format.
  * Author:   Kevin Locke, kwl7 at cornell.edu
- *	     (Based largely on aaigriddataset.cpp by Frank Warmerdam)
+ *           (Based largely on aaigriddataset.cpp by Frank Warmerdam)
  *
  ******************************************************************************
  * Copyright (c) 2006, Kevin Locke <kwl7 at cornell.edu>
@@ -38,6 +37,8 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
+CPL_CVSID("$Id: gsbgdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+
 #ifndef DBL_MAX
 # ifdef __DBL_MAX__
 #  define DBL_MAX __DBL_MAX__
@@ -62,11 +63,9 @@
 # define SHRT_MAX 32767
 #endif /* SHRT_MAX */
 
-CPL_CVSID("$Id: gsbgdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
-
 /************************************************************************/
 /* ==================================================================== */
-/*				GSBGDataset				*/
+/*                              GSBGDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -80,30 +79,30 @@ class GSBGDataset : public GDALPamDataset
     static const size_t nHEADER_SIZE;
 
     static CPLErr WriteHeader( VSILFILE *fp, GInt16 nXSize, GInt16 nYSize,
-			       double dfMinX, double dfMaxX,
-			       double dfMinY, double dfMaxY,
-			       double dfMinZ, double dfMaxZ );
+                               double dfMinX, double dfMaxX,
+                               double dfMinY, double dfMaxY,
+                               double dfMinZ, double dfMaxZ );
 
-    VSILFILE	*fp;
+    VSILFILE    *fp;
 
   public:
                  GSBGDataset() : fp(NULL) {}
-		~GSBGDataset();
+                ~GSBGDataset();
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
-			 	int nXSize, int nYSize, int nBands,
-				GDALDataType eType,
-				char **papszParmList );
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType,
+                                char **papszParmList );
     static GDALDataset *CreateCopy( const char *pszFilename,
-				    GDALDataset *poSrcDS,
-				    int bStrict, char **papszOptions,
-				    GDALProgressFunc pfnProgress,
-				    void *pProgressData );
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char **papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void *pProgressData );
 
-    CPLErr GetGeoTransform( double *padfGeoTransform );
-    CPLErr SetGeoTransform( double *padfGeoTransform );
+    CPLErr GetGeoTransform( double *padfGeoTransform ) override;
+    CPLErr SetGeoTransform( double *padfGeoTransform ) override;
 };
 
 /* NOTE:  This is not mentioned in the spec, but Surfer 8 uses this value */
@@ -138,15 +137,15 @@ class GSBGRasterBand : public GDALPamRasterBand
 
   public:
 
-    		GSBGRasterBand( GSBGDataset *, int );
-		~GSBGRasterBand();
+                GSBGRasterBand( GSBGDataset *, int );
+                ~GSBGRasterBand();
 
-    CPLErr IReadBlock( int, int, void * );
-    CPLErr IWriteBlock( int, int, void * );
+    CPLErr IReadBlock( int, int, void * ) override;
+    CPLErr IWriteBlock( int, int, void * ) override;
 
-    double GetNoDataValue( int *pbSuccess = NULL );
-    double GetMinimum( int *pbSuccess = NULL );
-    double GetMaximum( int *pbSuccess = NULL );
+    double GetNoDataValue( int *pbSuccess = NULL ) override;
+    double GetMinimum( int *pbSuccess = NULL ) override;
+    double GetMaximum( int *pbSuccess = NULL ) override;
 };
 
 /************************************************************************/
@@ -182,9 +181,9 @@ GSBGRasterBand::~GSBGRasterBand( )
 
 {
     if( pafRowMinZ != NULL )
-	CPLFree( pafRowMinZ );
+        CPLFree( pafRowMinZ );
     if( pafRowMaxZ != NULL )
-	CPLFree( pafRowMaxZ );
+        CPLFree( pafRowMaxZ );
 }
 
 /************************************************************************/
@@ -198,7 +197,7 @@ CPLErr GSBGRasterBand::ScanForMinMaxZ()
 
     if( pafRowVals == NULL )
     {
-	return CE_Failure;
+        return CE_Failure;
     }
 
     double dfNewMinZ = DBL_MAX;
@@ -212,53 +211,53 @@ CPLErr GSBGRasterBand::ScanForMinMaxZ()
     unsigned long nValuesRead = 0;
     for( int iRow=0; iRow<nRasterYSize; iRow++ )
     {
-	CPLErr eErr = IReadBlock( 0, iRow, pafRowVals );
-	if( eErr != CE_None )
-	{
-	    VSIFree( pafRowVals );
-	    return CE_Failure;
-	}
-
-	pafRowMinZ[iRow] = FLT_MAX;
-	pafRowMaxZ[iRow] = -FLT_MAX;
-	for( int iCol=0; iCol<nRasterXSize; iCol++ )
-	{
-	    if( pafRowVals[iCol] == GSBGDataset::fNODATA_VALUE )
-		continue;
-
-	    if( pafRowVals[iCol] < pafRowMinZ[iRow] )
-		pafRowMinZ[iRow] = pafRowVals[iCol];
-
-	    if( pafRowVals[iCol] > pafRowMinZ[iRow] )
-		pafRowMaxZ[iRow] = pafRowVals[iCol];
-
-	    dfSum += pafRowVals[iCol];
-	    dfSum2 += pafRowVals[iCol] * pafRowVals[iCol];
-	    nValuesRead++;
-	}
-
-	if( pafRowMinZ[iRow] < dfNewMinZ )
-	{
-	    dfNewMinZ = pafRowMinZ[iRow];
-	    nNewMinZRow = iRow;
-	}
-
-	if( pafRowMaxZ[iRow] > dfNewMaxZ )
-	{
-	    dfNewMaxZ = pafRowMaxZ[iRow];
-	    nNewMaxZRow = iRow;
-	}
+        CPLErr eErr = IReadBlock( 0, iRow, pafRowVals );
+        if( eErr != CE_None )
+        {
+            VSIFree( pafRowVals );
+            return CE_Failure;
+        }
+
+        pafRowMinZ[iRow] = FLT_MAX;
+        pafRowMaxZ[iRow] = -FLT_MAX;
+        for( int iCol=0; iCol<nRasterXSize; iCol++ )
+        {
+            if( pafRowVals[iCol] == GSBGDataset::fNODATA_VALUE )
+                continue;
+
+            if( pafRowVals[iCol] < pafRowMinZ[iRow] )
+                pafRowMinZ[iRow] = pafRowVals[iCol];
+
+            if( pafRowVals[iCol] > pafRowMinZ[iRow] )
+                pafRowMaxZ[iRow] = pafRowVals[iCol];
+
+            dfSum += pafRowVals[iCol];
+            dfSum2 += pafRowVals[iCol] * pafRowVals[iCol];
+            nValuesRead++;
+        }
+
+        if( pafRowMinZ[iRow] < dfNewMinZ )
+        {
+            dfNewMinZ = pafRowMinZ[iRow];
+            nNewMinZRow = iRow;
+        }
+
+        if( pafRowMaxZ[iRow] > dfNewMaxZ )
+        {
+            dfNewMaxZ = pafRowMaxZ[iRow];
+            nNewMaxZRow = iRow;
+        }
     }
 
     VSIFree( pafRowVals );
 
     if( nValuesRead == 0 )
     {
-	dfMinZ = 0.0;
-	dfMaxZ = 0.0;
-	nMinZRow = 0;
-	nMaxZRow = 0;
-	return CE_None;
+        dfMinZ = 0.0;
+        dfMaxZ = 0.0;
+        nMinZRow = 0;
+        nMaxZRow = 0;
+        return CE_None;
     }
 
     dfMinZ = dfNewMinZ;
@@ -278,35 +277,35 @@ CPLErr GSBGRasterBand::ScanForMinMaxZ()
 /************************************************************************/
 
 CPLErr GSBGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-				   void * pImage )
+                                   void * pImage )
 
 {
     if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
-	return CE_Failure;
+        return CE_Failure;
 
     GSBGDataset *poGDS = reinterpret_cast<GSBGDataset *>(poDS);
     if( VSIFSeekL( poGDS->fp,
-		   GSBGDataset::nHEADER_SIZE +
+                   GSBGDataset::nHEADER_SIZE +
                         4 * static_cast<vsi_l_offset>(nRasterXSize) * (nRasterYSize - nBlockYOff - 1),
-		   SEEK_SET ) != 0 )
+                   SEEK_SET ) != 0 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to seek to beginning of grid row.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to seek to beginning of grid row.\n" );
+        return CE_Failure;
     }
 
     if( VSIFReadL( pImage, sizeof(float), nBlockXSize,
-		   poGDS->fp ) != static_cast<unsigned>(nBlockXSize) )
+                   poGDS->fp ) != static_cast<unsigned>(nBlockXSize) )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to read block from grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to read block from grid file.\n" );
+        return CE_Failure;
     }
 
 #ifdef CPL_MSB
     float *pfImage = (float *)pImage;
     for( int iPixel=0; iPixel<nBlockXSize; iPixel++ ) {
-	CPL_LSBPTR32( pfImage+iPixel );
+        CPL_LSBPTR32( pfImage+iPixel );
     }
 #endif
 
@@ -318,52 +317,52 @@ CPLErr GSBGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr GSBGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-				    void *pImage )
+                                    void *pImage )
 
 {
     if( eAccess == GA_ReadOnly )
     {
-	CPLError( CE_Failure, CPLE_NoWriteAccess,
-		  "Unable to write block, dataset opened read only.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to write block, dataset opened read only.\n" );
+        return CE_Failure;
     }
 
     if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
-	return CE_Failure;
+        return CE_Failure;
 
     GSBGDataset *poGDS = dynamic_cast<GSBGDataset *>(poDS);
     assert( poGDS != NULL );
 
     if( pafRowMinZ == NULL || pafRowMaxZ == NULL
-	|| nMinZRow < 0 || nMaxZRow < 0 )
+        || nMinZRow < 0 || nMaxZRow < 0 )
     {
-	pafRowMinZ = (float *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(float) );
-	if( pafRowMinZ == NULL )
-	{
-	    return CE_Failure;
-	}
-
-	pafRowMaxZ = (float *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(float) );
-	if( pafRowMaxZ == NULL )
-	{
-	    VSIFree( pafRowMinZ );
-	    pafRowMinZ = NULL;
-	    return CE_Failure;
-	}
-
-	CPLErr eErr = ScanForMinMaxZ();
-	if( eErr != CE_None )
-	    return eErr;
+        pafRowMinZ = (float *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(float) );
+        if( pafRowMinZ == NULL )
+        {
+            return CE_Failure;
+        }
+
+        pafRowMaxZ = (float *)VSI_MALLOC2_VERBOSE( nRasterYSize,sizeof(float) );
+        if( pafRowMaxZ == NULL )
+        {
+            VSIFree( pafRowMinZ );
+            pafRowMinZ = NULL;
+            return CE_Failure;
+        }
+
+        CPLErr eErr = ScanForMinMaxZ();
+        if( eErr != CE_None )
+            return eErr;
     }
 
     if( VSIFSeekL( poGDS->fp,
-		   GSBGDataset::nHEADER_SIZE +
+                   GSBGDataset::nHEADER_SIZE +
                         4 * nRasterXSize * (nRasterYSize - nBlockYOff - 1),
-		   SEEK_SET ) != 0 )
+                   SEEK_SET ) != 0 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to seek to beginning of grid row.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to seek to beginning of grid row.\n" );
+        return CE_Failure;
     }
 
     float *pfImage = (float *)pImage;
@@ -371,92 +370,92 @@ CPLErr GSBGRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     pafRowMaxZ[nBlockYOff] = -FLT_MAX;
     for( int iPixel=0; iPixel<nBlockXSize; iPixel++ )
     {
-	if( pfImage[iPixel] != GSBGDataset::fNODATA_VALUE )
-	{
-	    if( pfImage[iPixel] < pafRowMinZ[nBlockYOff] )
-		pafRowMinZ[nBlockYOff] = pfImage[iPixel];
+        if( pfImage[iPixel] != GSBGDataset::fNODATA_VALUE )
+        {
+            if( pfImage[iPixel] < pafRowMinZ[nBlockYOff] )
+                pafRowMinZ[nBlockYOff] = pfImage[iPixel];
 
-	    if( pfImage[iPixel] > pafRowMaxZ[nBlockYOff] )
-		pafRowMaxZ[nBlockYOff] = pfImage[iPixel];
-	}
+            if( pfImage[iPixel] > pafRowMaxZ[nBlockYOff] )
+                pafRowMaxZ[nBlockYOff] = pfImage[iPixel];
+        }
 
-	CPL_LSBPTR32( pfImage+iPixel );
+        CPL_LSBPTR32( pfImage+iPixel );
     }
 
     if( VSIFWriteL( pImage, sizeof(float), nBlockXSize,
-		    poGDS->fp ) != static_cast<unsigned>(nBlockXSize) )
+                    poGDS->fp ) != static_cast<unsigned>(nBlockXSize) )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write block to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write block to grid file.\n" );
+        return CE_Failure;
     }
 
     /* Update min/max Z values as appropriate */
     bool bHeaderNeedsUpdate = false;
     if( nMinZRow == nBlockYOff && pafRowMinZ[nBlockYOff] > dfMinZ )
     {
-	double dfNewMinZ = DBL_MAX;
-	for( int iRow=0; iRow<nRasterYSize; iRow++ )
-	{
-	    if( pafRowMinZ[iRow] < dfNewMinZ )
-	    {
-		dfNewMinZ = pafRowMinZ[iRow];
-		nMinZRow = iRow;
-	    }
-	}
-
-	if( dfNewMinZ != dfMinZ )
-	{
-	    dfMinZ = dfNewMinZ;
-	    bHeaderNeedsUpdate = true;
-	}
+        double dfNewMinZ = DBL_MAX;
+        for( int iRow=0; iRow<nRasterYSize; iRow++ )
+        {
+            if( pafRowMinZ[iRow] < dfNewMinZ )
+            {
+                dfNewMinZ = pafRowMinZ[iRow];
+                nMinZRow = iRow;
+            }
+        }
+
+        if( dfNewMinZ != dfMinZ )
+        {
+            dfMinZ = dfNewMinZ;
+            bHeaderNeedsUpdate = true;
+        }
     }
 
     if( nMaxZRow == nBlockYOff && pafRowMaxZ[nBlockYOff] < dfMaxZ )
     {
-	double dfNewMaxZ = -DBL_MAX;
-	for( int iRow=0; iRow<nRasterYSize; iRow++ )
-	{
-	    if( pafRowMaxZ[iRow] > dfNewMaxZ )
-	    {
-		dfNewMaxZ = pafRowMaxZ[iRow];
-		nMaxZRow = iRow;
-	    }
-	}
-
-	if( dfNewMaxZ != dfMaxZ )
-	{
-	    dfMaxZ = dfNewMaxZ;
-	    bHeaderNeedsUpdate = true;
-	}
+        double dfNewMaxZ = -DBL_MAX;
+        for( int iRow=0; iRow<nRasterYSize; iRow++ )
+        {
+            if( pafRowMaxZ[iRow] > dfNewMaxZ )
+            {
+                dfNewMaxZ = pafRowMaxZ[iRow];
+                nMaxZRow = iRow;
+            }
+        }
+
+        if( dfNewMaxZ != dfMaxZ )
+        {
+            dfMaxZ = dfNewMaxZ;
+            bHeaderNeedsUpdate = true;
+        }
     }
 
     if( pafRowMinZ[nBlockYOff] < dfMinZ || pafRowMaxZ[nBlockYOff] > dfMaxZ )
     {
-	if( pafRowMinZ[nBlockYOff] < dfMinZ )
-	{
-	    dfMinZ = pafRowMinZ[nBlockYOff];
-	    nMinZRow = nBlockYOff;
-	}
-
-	if( pafRowMaxZ[nBlockYOff] > dfMaxZ )
-	{
-	    dfMaxZ = pafRowMaxZ[nBlockYOff];
-	    nMaxZRow = nBlockYOff;
-	}
-
-	bHeaderNeedsUpdate = true;
+        if( pafRowMinZ[nBlockYOff] < dfMinZ )
+        {
+            dfMinZ = pafRowMinZ[nBlockYOff];
+            nMinZRow = nBlockYOff;
+        }
+
+        if( pafRowMaxZ[nBlockYOff] > dfMaxZ )
+        {
+            dfMaxZ = pafRowMaxZ[nBlockYOff];
+            nMaxZRow = nBlockYOff;
+        }
+
+        bHeaderNeedsUpdate = true;
     }
 
     if( bHeaderNeedsUpdate && dfMaxZ > dfMinZ )
     {
-	CPLErr eErr = poGDS->WriteHeader( poGDS->fp,
-					  (GInt16) nRasterXSize,
+        CPLErr eErr = poGDS->WriteHeader( poGDS->fp,
+                                          (GInt16) nRasterXSize,
                                           (GInt16) nRasterYSize,
-					  dfMinX, dfMaxX,
-					  dfMinY, dfMaxY,
-					  dfMinZ, dfMaxZ );
-	return eErr;
+                                          dfMinX, dfMaxX,
+                                          dfMinY, dfMaxY,
+                                          dfMinZ, dfMaxZ );
+        return eErr;
     }
 
     return CE_None;
@@ -500,7 +499,7 @@ double GSBGRasterBand::GetMaximum( int *pbSuccess )
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GSBGDataset				*/
+/*                              GSBGDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -544,20 +543,20 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GSBGDataset	*poDS = new GSBGDataset();
+    GSBGDataset *poDS = new GSBGDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Open file with large file API.                                  */
 /* -------------------------------------------------------------------- */
     poDS->eAccess = poOpenInfo->eAccess;
     if( poOpenInfo->eAccess == GA_ReadOnly )
-    	poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     else
-    	poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
+        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
 
     if( poDS->fp == NULL )
     {
-	delete poDS;
+        delete poDS;
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "VSIFOpenL(%s) failed unexpectedly.",
                   poOpenInfo->pszFilename );
@@ -569,27 +568,27 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( VSIFSeekL( poDS->fp, 4, SEEK_SET ) != 0 )
     {
-	delete poDS;
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to seek to start of grid file header.\n" );
-	return NULL;
+        delete poDS;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to seek to start of grid file header.\n" );
+        return NULL;
     }
 
     /* Parse number of X axis grid rows */
     GInt16 nTemp;
     if( VSIFReadL( (void *)&nTemp, 2, 1, poDS->fp ) != 1 )
     {
-	delete poDS;
-	CPLError( CE_Failure, CPLE_FileIO, "Unable to read raster X size.\n" );
-	return NULL;
+        delete poDS;
+        CPLError( CE_Failure, CPLE_FileIO, "Unable to read raster X size.\n" );
+        return NULL;
     }
     poDS->nRasterXSize = CPL_LSBWORD16( nTemp );
 
     if( VSIFReadL( (void *)&nTemp, 2, 1, poDS->fp ) != 1 )
     {
-	delete poDS;
-	CPLError( CE_Failure, CPLE_FileIO, "Unable to read raster Y size.\n" );
-	return NULL;
+        delete poDS;
+        CPLError( CE_Failure, CPLE_FileIO, "Unable to read raster Y size.\n" );
+        return NULL;
     }
     poDS->nRasterYSize = CPL_LSBWORD16( nTemp );
 
@@ -607,66 +606,66 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
     double dfTemp;
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
-	delete poDS;
+        delete poDS;
         delete poBand;
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to read minimum X value.\n" );
-	return NULL;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to read minimum X value.\n" );
+        return NULL;
     }
     CPL_LSBPTR64( &dfTemp );
     poBand->dfMinX = dfTemp;
 
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
-	delete poDS;
+        delete poDS;
         delete poBand;
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to read maximum X value.\n" );
-	return NULL;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to read maximum X value.\n" );
+        return NULL;
     }
     CPL_LSBPTR64( &dfTemp );
     poBand->dfMaxX = dfTemp;
 
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
-	delete poDS;
+        delete poDS;
         delete poBand;
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to read minimum Y value.\n" );
-	return NULL;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to read minimum Y value.\n" );
+        return NULL;
     }
     CPL_LSBPTR64( &dfTemp );
     poBand->dfMinY = dfTemp;
 
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
-	delete poDS;
+        delete poDS;
         delete poBand;
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to read maximum Y value.\n" );
-	return NULL;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to read maximum Y value.\n" );
+        return NULL;
     }
     CPL_LSBPTR64( &dfTemp );
     poBand->dfMaxY = dfTemp;
 
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
-	delete poDS;
+        delete poDS;
         delete poBand;
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to read minimum Z value.\n" );
-	return NULL;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to read minimum Z value.\n" );
+        return NULL;
     }
     CPL_LSBPTR64( &dfTemp );
     poBand->dfMinZ = dfTemp;
 
     if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 )
     {
-	delete poDS;
+        delete poDS;
         delete poBand;
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to read maximum Z value.\n" );
-	return NULL;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to read maximum Z value.\n" );
+        return NULL;
     }
     CPL_LSBPTR64( &dfTemp );
     poBand->dfMaxZ = dfTemp;
@@ -694,19 +693,19 @@ GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo )
 CPLErr GSBGDataset::GetGeoTransform( double *padfGeoTransform )
 {
     if( padfGeoTransform == NULL )
-	return CE_Failure;
+        return CE_Failure;
 
     GSBGRasterBand *poGRB = dynamic_cast<GSBGRasterBand *>(GetRasterBand( 1 ));
 
     if( poGRB == NULL )
     {
-	padfGeoTransform[0] = 0;
-	padfGeoTransform[1] = 1;
-	padfGeoTransform[2] = 0;
-	padfGeoTransform[3] = 0;
-	padfGeoTransform[4] = 0;
-	padfGeoTransform[5] = 1;
-	return CE_Failure;
+        padfGeoTransform[0] = 0;
+        padfGeoTransform[1] = 1;
+        padfGeoTransform[2] = 0;
+        padfGeoTransform[3] = 0;
+        padfGeoTransform[4] = 0;
+        padfGeoTransform[5] = 1;
+        return CE_Failure;
     }
 
     /* check if we have a PAM GeoTransform stored */
@@ -715,7 +714,7 @@ CPLErr GSBGDataset::GetGeoTransform( double *padfGeoTransform )
     CPLPopErrorHandler();
 
     if( eErr == CE_None )
-	return CE_None;
+        return CE_None;
 
     /* calculate pixel size first */
     padfGeoTransform[1] = (poGRB->dfMaxX - poGRB->dfMinX)/(nRasterXSize - 1);
@@ -740,24 +739,24 @@ CPLErr GSBGDataset::SetGeoTransform( double *padfGeoTransform )
 {
     if( eAccess == GA_ReadOnly )
     {
-	CPLError( CE_Failure, CPLE_NoWriteAccess,
-		  "Unable to set GeoTransform, dataset opened read only.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to set GeoTransform, dataset opened read only.\n" );
+        return CE_Failure;
     }
 
     GSBGRasterBand *poGRB = dynamic_cast<GSBGRasterBand *>(GetRasterBand( 1 ));
 
     if( poGRB == NULL || padfGeoTransform == NULL)
-	return CE_Failure;
+        return CE_Failure;
 
     /* non-zero transform 2 or 4 or negative 1 or 5 not supported natively */
     CPLErr eErr = CE_None;
     /*if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0
-	|| padfGeoTransform[1] < 0.0 || padfGeoTransform[5] < 0.0 )
-	eErr = GDALPamDataset::SetGeoTransform( padfGeoTransform );
+        || padfGeoTransform[1] < 0.0 || padfGeoTransform[5] < 0.0 )
+        eErr = GDALPamDataset::SetGeoTransform( padfGeoTransform );
 
     if( eErr != CE_None )
-	return eErr;*/
+        return eErr;*/
 
     double dfMinX = padfGeoTransform[0] + padfGeoTransform[1] / 2;
     double dfMaxX =
@@ -769,15 +768,15 @@ CPLErr GSBGDataset::SetGeoTransform( double *padfGeoTransform )
     eErr = WriteHeader( fp,
                         (GInt16) poGRB->nRasterXSize,
                         (GInt16) poGRB->nRasterYSize,
-			dfMinX, dfMaxX, dfMinY, dfMaxY,
-			poGRB->dfMinZ, poGRB->dfMaxZ );
+                        dfMinX, dfMaxX, dfMinY, dfMaxY,
+                        poGRB->dfMinZ, poGRB->dfMaxZ );
 
     if( eErr == CE_None )
     {
-	poGRB->dfMinX = dfMinX;
-	poGRB->dfMaxX = dfMaxX;
-	poGRB->dfMinY = dfMinY;
-	poGRB->dfMaxY = dfMaxY;
+        poGRB->dfMinX = dfMinX;
+        poGRB->dfMaxX = dfMaxX;
+        poGRB->dfMinY = dfMinY;
+        poGRB->dfMaxY = dfMaxY;
     }
 
     return eErr;
@@ -788,93 +787,93 @@ CPLErr GSBGDataset::SetGeoTransform( double *padfGeoTransform )
 /************************************************************************/
 
 CPLErr GSBGDataset::WriteHeader( VSILFILE *fp, GInt16 nXSize, GInt16 nYSize,
-				 double dfMinX, double dfMaxX,
-				 double dfMinY, double dfMaxY,
-				 double dfMinZ, double dfMaxZ )
+                                 double dfMinX, double dfMaxX,
+                                 double dfMinY, double dfMaxY,
+                                 double dfMinZ, double dfMaxZ )
 
 {
     if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to seek to start of grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to seek to start of grid file.\n" );
+        return CE_Failure;
     }
 
     if( VSIFWriteL( (void *)"DSBB", 1, 4, fp ) != 4 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write signature to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write signature to grid file.\n" );
+        return CE_Failure;
     }
 
     GInt16 nTemp = CPL_LSBWORD16(nXSize);
     if( VSIFWriteL( (void *)&nTemp, 2, 1, fp ) != 1 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write raster X size to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write raster X size to grid file.\n" );
+        return CE_Failure;
     }
 
     nTemp = CPL_LSBWORD16(nYSize);
     if( VSIFWriteL( (void *)&nTemp, 2, 1, fp ) != 1 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write raster Y size to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write raster Y size to grid file.\n" );
+        return CE_Failure;
     }
 
     double dfTemp = dfMinX;
     CPL_LSBPTR64( &dfTemp );
     if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write minimum X value to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write minimum X value to grid file.\n" );
+        return CE_Failure;
     }
 
     dfTemp = dfMaxX;
     CPL_LSBPTR64( &dfTemp );
     if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write maximum X value to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write maximum X value to grid file.\n" );
+        return CE_Failure;
     }
 
     dfTemp = dfMinY;
     CPL_LSBPTR64( &dfTemp );
     if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write minimum Y value to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write minimum Y value to grid file.\n" );
+        return CE_Failure;
     }
 
     dfTemp = dfMaxY;
     CPL_LSBPTR64( &dfTemp );
     if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write maximum Y value to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write maximum Y value to grid file.\n" );
+        return CE_Failure;
     }
 
     dfTemp = dfMinZ;
     CPL_LSBPTR64( &dfTemp );
     if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write minimum Z value to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write minimum Z value to grid file.\n" );
+        return CE_Failure;
     }
 
     dfTemp = dfMaxZ;
     CPL_LSBPTR64( &dfTemp );
     if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 )
     {
-	CPLError( CE_Failure, CPLE_FileIO,
-		  "Unable to write maximum Z value to grid file.\n" );
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Unable to write maximum Z value to grid file.\n" );
+        return CE_Failure;
     }
 
     return CE_None;
@@ -885,38 +884,38 @@ CPLErr GSBGDataset::WriteHeader( VSILFILE *fp, GInt16 nXSize, GInt16 nYSize,
 /************************************************************************/
 
 GDALDataset *GSBGDataset::Create( const char * pszFilename,
-				  int nXSize,
+                                  int nXSize,
                                   int nYSize,
                                   CPL_UNUSED int nBands,
-				  GDALDataType eType,
-				  CPL_UNUSED char **papszParmList )
+                                  GDALDataType eType,
+                                  CPL_UNUSED char **papszParmList )
 {
     if( nXSize <= 0 || nYSize <= 0 )
     {
-	CPLError( CE_Failure, CPLE_IllegalArg,
-		  "Unable to create grid, both X and Y size must be "
-		  "non-negative.\n" );
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "Unable to create grid, both X and Y size must be "
+                  "non-negative.\n" );
 
-	return NULL;
+        return NULL;
     }
     else if( nXSize > SHRT_MAX
-	     || nYSize > SHRT_MAX )
+             || nYSize > SHRT_MAX )
     {
-	CPLError( CE_Failure, CPLE_IllegalArg,
-		  "Unable to create grid, Golden Software Binary Grid format "
-		  "only supports sizes up to %dx%d.  %dx%d not supported.\n",
-		  SHRT_MAX, SHRT_MAX, nXSize, nYSize );
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "Unable to create grid, Golden Software Binary Grid format "
+                  "only supports sizes up to %dx%d.  %dx%d not supported.\n",
+                  SHRT_MAX, SHRT_MAX, nXSize, nYSize );
 
-	return NULL;
+        return NULL;
     }
 
     if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16
         && eType != GDT_Int16 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-		  "Golden Software Binary Grid only supports Byte, Int16, "
-		  "Uint16, and Float32 datatypes.  Unable to create with "
-		  "type %s.\n", GDALGetDataTypeName( eType ) );
+                  "Golden Software Binary Grid only supports Byte, Int16, "
+                  "Uint16, and Float32 datatypes.  Unable to create with "
+                  "type %s.\n", GDALGetDataTypeName( eType ) );
 
         return NULL;
     }
@@ -932,27 +931,27 @@ GDALDataset *GSBGDataset::Create( const char * pszFilename,
     }
 
     CPLErr eErr = WriteHeader( fp, (GInt16) nXSize, (GInt16) nYSize,
-			       0.0, nXSize, 0.0, nYSize, 0.0, 0.0 );
+                               0.0, nXSize, 0.0, nYSize, 0.0, 0.0 );
     if( eErr != CE_None )
     {
-	VSIFCloseL( fp );
-	return NULL;
+        VSIFCloseL( fp );
+        return NULL;
     }
 
     float fVal = fNODATA_VALUE;
     CPL_LSBPTR32( &fVal );
     for( int iRow = 0; iRow < nYSize; iRow++ )
     {
-	for( int iCol=0; iCol<nXSize; iCol++ )
-	{
-	    if( VSIFWriteL( (void *)&fVal, 4, 1, fp ) != 1 )
-	    {
-		VSIFCloseL( fp );
-		CPLError( CE_Failure, CPLE_FileIO,
-			  "Unable to write grid cell.  Disk full?\n" );
-		return NULL;
-	    }
-	}
+        for( int iCol=0; iCol<nXSize; iCol++ )
+        {
+            if( VSIFWriteL( (void *)&fVal, 4, 1, fp ) != 1 )
+            {
+                VSIFCloseL( fp );
+                CPLError( CE_Failure, CPLE_FileIO,
+                          "Unable to write grid cell.  Disk full?\n" );
+                return NULL;
+            }
+        }
     }
 
     VSIFCloseL( fp );
@@ -965,14 +964,14 @@ GDALDataset *GSBGDataset::Create( const char * pszFilename,
 /************************************************************************/
 
 GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
-				      GDALDataset *poSrcDS,
-				      int bStrict,
+                                      GDALDataset *poSrcDS,
+                                      int bStrict,
                                       CPL_UNUSED char **papszOptions,
-				      GDALProgressFunc pfnProgress,
-				      void *pProgressData )
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData )
 {
     if( pfnProgress == NULL )
-	pfnProgress = GDALDummyProgress;
+        pfnProgress = GDALDummyProgress;
 
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
@@ -983,30 +982,30 @@ GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
     }
     else if (nBands > 1)
     {
-	if( bStrict )
-	{
-	    CPLError( CE_Failure, CPLE_NotSupported,
-		      "Unable to create copy, Golden Software Binary Grid "
-		      "format only supports one raster band.\n" );
-	    return NULL;
-	}
-	else
-	    CPLError( CE_Warning, CPLE_NotSupported,
-		      "Golden Software Binary Grid format only supports one "
-		      "raster band, first band will be copied.\n" );
+        if( bStrict )
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Unable to create copy, Golden Software Binary Grid "
+                      "format only supports one raster band.\n" );
+            return NULL;
+        }
+        else
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Golden Software Binary Grid format only supports one "
+                      "raster band, first band will be copied.\n" );
     }
 
     GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
     if( poSrcBand->GetXSize() > SHRT_MAX
-	|| poSrcBand->GetYSize() > SHRT_MAX )
+        || poSrcBand->GetYSize() > SHRT_MAX )
     {
-	CPLError( CE_Failure, CPLE_IllegalArg,
-		  "Unable to create grid, Golden Software Binary Grid format "
-		  "only supports sizes up to %dx%d.  %dx%d not supported.\n",
-		  SHRT_MAX, SHRT_MAX,
-		  poSrcBand->GetXSize(), poSrcBand->GetYSize() );
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "Unable to create grid, Golden Software Binary Grid format "
+                  "only supports sizes up to %dx%d.  %dx%d not supported.\n",
+                  SHRT_MAX, SHRT_MAX,
+                  poSrcBand->GetXSize(), poSrcBand->GetYSize() );
 
-	return NULL;
+        return NULL;
     }
 
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
@@ -1036,22 +1035,22 @@ GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
     double dfMinY = adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3];
     double dfMaxY = adfGeoTransform[3] + adfGeoTransform[5] / 2;
     CPLErr eErr = WriteHeader( fp, nXSize, nYSize,
-			       dfMinX, dfMaxX, dfMinY, dfMaxY, 0.0, 0.0 );
+                               dfMinX, dfMaxX, dfMinY, dfMaxY, 0.0, 0.0 );
 
     if( eErr != CE_None )
     {
-	VSIFCloseL( fp );
+        VSIFCloseL( fp );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Copy band data.							*/
+/*      Copy band data.                                                 */
 /* -------------------------------------------------------------------- */
     float *pfData = (float *)VSI_MALLOC2_VERBOSE( nXSize, sizeof( float ) );
     if( pfData == NULL )
     {
-	VSIFCloseL( fp );
-	return NULL;
+        VSIFCloseL( fp );
+        return NULL;
     }
 
     int     bSrcHasNDValue;
@@ -1060,64 +1059,64 @@ GDALDataset *GSBGDataset::CreateCopy( const char *pszFilename,
     double  dfMaxZ = -DBL_MAX;
     for( GInt16 iRow = nYSize - 1; iRow >= 0; iRow-- )
     {
-	eErr = poSrcBand->RasterIO( GF_Read, 0, iRow,
-				    nXSize, 1, pfData,
-				    nXSize, 1, GDT_Float32, 0, 0, NULL );
-
-	if( eErr != CE_None )
-	{
-	    VSIFCloseL( fp );
-	    VSIFree( pfData );
-	    return NULL;
-	}
-
-	for( int iCol=0; iCol<nXSize; iCol++ )
-	{
-	    if( bSrcHasNDValue && pfData[iCol] == fSrcNoDataValue )
-	    {
-		pfData[iCol] = fNODATA_VALUE;
-	    }
-	    else
-	    {
-		if( pfData[iCol] > dfMaxZ )
-		    dfMaxZ = pfData[iCol];
-
-		if( pfData[iCol] < dfMinZ )
-		    dfMinZ = pfData[iCol];
-	    }
-
-	    CPL_LSBPTR32( pfData+iCol );
-	}
-
-	if( VSIFWriteL( (void *)pfData, 4, nXSize,
-			fp ) != static_cast<unsigned>(nXSize) )
-	{
-	    VSIFCloseL( fp );
-	    VSIFree( pfData );
-	    CPLError( CE_Failure, CPLE_FileIO,
-		      "Unable to write grid row. Disk full?\n" );
-	    return NULL;
-	}
-
-	if( !pfnProgress( static_cast<double>(nYSize - iRow)/nYSize,
-			  NULL, pProgressData ) )
-	{
-	    VSIFCloseL( fp );
-	    VSIFree( pfData );
-	    CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-	    return NULL;
-	}
+        eErr = poSrcBand->RasterIO( GF_Read, 0, iRow,
+                                    nXSize, 1, pfData,
+                                    nXSize, 1, GDT_Float32, 0, 0, NULL );
+
+        if( eErr != CE_None )
+        {
+            VSIFCloseL( fp );
+            VSIFree( pfData );
+            return NULL;
+        }
+
+        for( int iCol=0; iCol<nXSize; iCol++ )
+        {
+            if( bSrcHasNDValue && pfData[iCol] == fSrcNoDataValue )
+            {
+                pfData[iCol] = fNODATA_VALUE;
+            }
+            else
+            {
+                if( pfData[iCol] > dfMaxZ )
+                    dfMaxZ = pfData[iCol];
+
+                if( pfData[iCol] < dfMinZ )
+                    dfMinZ = pfData[iCol];
+            }
+
+            CPL_LSBPTR32( pfData+iCol );
+        }
+
+        if( VSIFWriteL( (void *)pfData, 4, nXSize,
+                        fp ) != static_cast<unsigned>(nXSize) )
+        {
+            VSIFCloseL( fp );
+            VSIFree( pfData );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Unable to write grid row. Disk full?\n" );
+            return NULL;
+        }
+
+        if( !pfnProgress( static_cast<double>(nYSize - iRow)/nYSize,
+                          NULL, pProgressData ) )
+        {
+            VSIFCloseL( fp );
+            VSIFree( pfData );
+            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+            return NULL;
+        }
     }
 
     VSIFree( pfData );
 
     /* write out the min and max values */
     eErr = WriteHeader( fp, nXSize, nYSize,
-			dfMinX, dfMaxX, dfMinY, dfMaxY, dfMinZ, dfMaxZ );
+                        dfMinX, dfMaxX, dfMinY, dfMaxY, dfMinZ, dfMaxZ );
 
     if( eErr != CE_None )
     {
-	VSIFCloseL( fp );
+        VSIFCloseL( fp );
         return NULL;
     }
 
diff --git a/frmts/gta/gtadataset.cpp b/frmts/gta/gtadataset.cpp
index ea45dfe..b4152b6 100644
--- a/frmts/gta/gtadataset.cpp
+++ b/frmts/gta/gtadataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gtadataset.cpp 33005 2016-01-15 17:28:49Z rouault $
  *
  * Project:  GTA read/write Driver
  * Purpose:  GDAL bindings over GTA library.
@@ -92,7 +91,7 @@
 #include "gdal_pam.h"
 #include "gta_headers.h"
 
-CPL_CVSID("$Id: gtadataset.cpp 33005 2016-01-15 17:28:49Z rouault $");
+CPL_CVSID("$Id: gtadataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* Helper functions                                                     */
@@ -149,7 +148,7 @@ class GTAIO : public gta::custom_io
     int open( const char *pszFilename, const char *pszMode )
     {
         fp = VSIFOpenL( pszFilename, pszMode );
-        return ( fp == NULL ? -1 : 0 );
+        return fp == NULL ? -1 : 0;
     }
 
     void close( )
@@ -166,7 +165,7 @@ class GTAIO : public gta::custom_io
         return VSIFTellL( fp );
     }
 
-    virtual size_t read(void *buffer, size_t size, bool *error) throw ()
+    virtual size_t read(void *buffer, size_t size, bool *error) throw () override
     {
         size_t s;
         s = VSIFReadL( buffer, 1, size, fp );
@@ -178,7 +177,7 @@ class GTAIO : public gta::custom_io
         return size;
     }
 
-    virtual size_t write(const void *buffer, size_t size, bool *error) throw ()
+    virtual size_t write(const void *buffer, size_t size, bool *error) throw () override
     {
         size_t s;
         s = VSIFWriteL( buffer, 1, size, fp );
@@ -190,12 +189,12 @@ class GTAIO : public gta::custom_io
         return size;
     }
 
-    virtual bool seekable() throw ()
+    virtual bool seekable() throw () override
     {
         return true;
     }
 
-    virtual void seek(intmax_t offset, int whence, bool *error) throw ()
+    virtual void seek(intmax_t offset, int whence, bool *error) throw () override
     {
         int r;
         r = VSIFSeekL( fp, offset, whence );
@@ -246,16 +245,16 @@ class GTADataset : public GDALPamDataset
 
     static GDALDataset *Open( GDALOpenInfo * );
 
-    CPLErr      GetGeoTransform( double * padfTransform );
-    CPLErr      SetGeoTransform( double * padfTransform );
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
+    CPLErr      SetGeoTransform( double * padfTransform ) override;
 
-    const char *GetProjectionRef( );
-    CPLErr      SetProjection( const char *pszProjection );
+    const char *GetProjectionRef( ) override;
+    CPLErr      SetProjection( const char *pszProjection ) override;
 
-    int         GetGCPCount( );
-    const char *GetGCPProjection( );
-    const GDAL_GCP *GetGCPs( );
-    CPLErr      SetGCPs( int, const GDAL_GCP *, const char * );
+    int         GetGCPCount( ) override;
+    const char *GetGCPProjection( ) override;
+    const GDAL_GCP *GetGCPs( ) override;
+    CPLErr      SetGCPs( int, const GDAL_GCP *, const char * ) override;
 };
 
 /************************************************************************/
@@ -281,25 +280,25 @@ class GTARasterBand : public GDALPamRasterBand
                 GTARasterBand( GTADataset *, int );
                 ~GTARasterBand( );
 
-    CPLErr      IReadBlock( int, int, void * );
-    CPLErr      IWriteBlock( int, int, void * );
-
-    char      **GetCategoryNames( );
-    CPLErr      SetCategoryNames( char ** );
-
-    double      GetMinimum( int * );
-    double      GetMaximum( int * );
-
-    double      GetNoDataValue( int * );
-    CPLErr      SetNoDataValue( double );
-    double      GetOffset( int * );
-    CPLErr      SetOffset( double );
-    double      GetScale( int * );
-    CPLErr      SetScale( double );
-    const char *GetUnitType( );
-    CPLErr      SetUnitType( const char * );
-    GDALColorInterp GetColorInterpretation( );
-    CPLErr      SetColorInterpretation( GDALColorInterp );
+    CPLErr      IReadBlock( int, int, void * ) override;
+    CPLErr      IWriteBlock( int, int, void * ) override;
+
+    char      **GetCategoryNames( ) override;
+    CPLErr      SetCategoryNames( char ** ) override;
+
+    double      GetMinimum( int * ) override;
+    double      GetMaximum( int * ) override;
+
+    double      GetNoDataValue( int * ) override;
+    CPLErr      SetNoDataValue( double ) override;
+    double      GetOffset( int * ) override;
+    CPLErr      SetOffset( double ) override;
+    double      GetScale( int * ) override;
+    CPLErr      SetScale( double ) override;
+    const char *GetUnitType( ) override;
+    CPLErr      SetUnitType( const char * ) override;
+    GDALColorInterp GetColorInterpretation( ) override;
+    CPLErr      SetColorInterpretation( GDALColorInterp ) override;
 };
 
 /************************************************************************/
@@ -775,6 +774,7 @@ GTADataset::GTADataset()
     nLastBlockYOff = -1;
     pBlock = NULL;
     DataOffset = 0;
+    memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
 }
 
 /************************************************************************/
@@ -931,7 +931,7 @@ const char *GTADataset::GetProjectionRef()
 
 {
     const char *p = oHeader.global_taglist().get("GDAL/PROJECTION");
-    return ( p ? p : "" );
+    return p ? p : "";
 }
 
 /************************************************************************/
@@ -1004,9 +1004,7 @@ GDALDataset *GTADataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GTADataset  *poDS;
-
-    poDS = new GTADataset();
+    GTADataset *poDS = new GTADataset();
 
     if( poDS->oGTAIO.open( poOpenInfo->pszFilename,
             poOpenInfo->eAccess == GA_Update ? "r+" : "r" ) != 0 )
@@ -1250,7 +1248,7 @@ GDALDataset *GTADataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/gtiff/GNUmakefile b/frmts/gtiff/GNUmakefile
index 6a8bf9c..eedefbf 100644
--- a/frmts/gtiff/GNUmakefile
+++ b/frmts/gtiff/GNUmakefile
@@ -7,7 +7,7 @@ OBJ	=	geotiff.o gt_wkt_srs.o gt_citation.o  gt_overview.o \
 SUBLIBS 	=
 
 ifeq ($(TIFF_SETTING),internal)
-SUBLIBS	:= lib-tiff $(SUBLIBS) 
+SUBLIBS	:= lib-tiff $(SUBLIBS)
 TIFF_OPTS	:=	-DINTERNAL_LIBTIFF -Ilibtiff $(TIFF_OPTS)
 ifeq ($(RENAME_INTERNAL_LIBTIFF_SYMBOLS),yes)
 TIFF_OPTS	:=	-DRENAME_INTERNAL_LIBTIFF_SYMBOLS $(TIFF_OPTS)
@@ -15,7 +15,7 @@ endif
 endif
 
 ifeq ($(GEOTIFF_SETTING),internal)
-SUBLIBS	:= lib-geotiff $(SUBLIBS) 
+SUBLIBS	:= lib-geotiff $(SUBLIBS)
 TIFF_OPTS	:=	-DINTERNAL_LIBGEOTIFF -Ilibgeotiff $(TIFF_OPTS)
 ifeq ($(RENAME_INTERNAL_LIBGEOTIFF_SYMBOLS),yes)
 TIFF_OPTS	:=	-DRENAME_INTERNAL_LIBGEOTIFF_SYMBOLS $(TIFF_OPTS)
@@ -49,7 +49,7 @@ gt_write:	gt_write.$(OBJ_EXT) gt_gs.$(OBJ_EXT) cpl_csv.$(OBJ_EXT)
 	$(CC) gt_write.$(OBJ_EXT) gt_gs.$(OBJ_EXT) cpl_csv.$(OBJ_EXT) ../../port/*.$(OBJ_EXT) \
 		libgeotiff/libgeotiff.a libtiff/libtiff.a $(LIBS) -o gt_write
 
-epsg_to_wkt:	epsg_to_wkt.$(OBJ_EXT) gt_wkt_srs.$(OBJ_EXT) 
+epsg_to_wkt:	epsg_to_wkt.$(OBJ_EXT) gt_wkt_srs.$(OBJ_EXT)
 	$(CXX) epsg_to_wkt.$(OBJ_EXT) gt_wkt_srs.$(OBJ_EXT) ../../port/*.$(OBJ_EXT) \
 	    libgeotiff/libgeotiff.a libtiff/libtiff.a \
 	    $(GDAL_LIB) $(LIBS) -o epsg_to_wkt
diff --git a/frmts/gtiff/frmt_gtiff.html b/frmts/gtiff/frmt_gtiff.html
index 29224a5..938eaa9 100644
--- a/frmts/gtiff/frmt_gtiff.html
+++ b/frmts/gtiff/frmt_gtiff.html
@@ -27,12 +27,12 @@ reading as well. </p>
 such as YCbCr color model files, are automatically translated into RGBA
 (red, green, blue, alpha) form, and treated as four eight bit bands. </p>
 
-<h2>Georeferencing</h2>
+<h2><a name="georeferencing">Georeferencing</a></h2>
 
 <p>Most GeoTIFF projections should be supported, with the caveat that in order
 to translate uncommon Projected, and Geographic coordinate systems into
 OGC WKT it is necessary to have the EPSG .csv files available.  They must
-be found at the location pointed to by the GEOTIFF_CSV environment variable.
+be found at the location pointed to by the GDAL_DATA or GEOTIFF_CSV environment variable.
 </p>
 
 <p>Georeferencing from GeoTIFF is supported in the form of one tiepoint and
@@ -43,6 +43,23 @@ information is available in the TIFF file itself, GDAL will also check for,
 and use an ESRI <a href="frmt_various.html#WLD">world file</a> with the
 extension .tfw, .tifw/.tiffw or .wld, as well as a MapInfo .tab file.</p>
 
+<p>
+By default, information is fetched in following order (first listed is the most
+prioritary): PAM (Persitant Auxiliary metadata) .aux.xml sidecar file,
+INTERNAL (GeoTIFF keys and tags), TABFILE (.tab), WORLDFILE (.tfw, .tifw/.tiffw or .wld).
+</p>
+<p>Starting with GDAL 2.2, the allowed sources
+and their priority order can be changed with the GDAL_GEOREF_SOURCES
+configuration option (or GEOREF_SOURCES open option) whose value is a
+comma-separated list of the following keywords : PAM, INTERNAL, TABFILE, WORLDFILE, NONE.
+First mentioned sources are the most prioritary over the next ones. A non mentioned
+source will be ignored.
+</p>
+<p>
+For example setting it to "WORLDFILE,PAM,INTERNAL" will make a geotransformation
+matrix from a potential worldfile prioritary over PAM or GeoTIFF.
+</p>
+
 <p>GDAL can read and write the <i>RPCCoefficientTag</i> as described in the <a href="http://geotiff.maptools.org/rpc_prop.html">
 RPCs in GeoTIFF</a> proposed extension. The tag is written only for
 files created with the default profile GDALGeoTIFF. For other profiles, a .RPB file
@@ -157,6 +174,45 @@ stored the EXIF metadata domain.</p>
 files created with the default profile GDALGeoTIFF. Note that all bands must use the same nodata value.
 When BASELINE or GeoTIFF profile are used, the nodata value is stored into a PAM .aux.xml file.</p>
 
+<h2>Sparse files</h2>
+
+<p>GDAL makes a special interpretation of a TIFF tile or strip whose offset
+and byte count are set to 0, that is to say a tile or strip that has no corresponding
+allocated physical storage. On reading, such tiles or strips are considered to
+be implictly set to 0 or to the nodata value when it is defined. On writing, it
+is possible to enable generating such files through the Create() interface by setting
+the SPARSE_OK creation option to YES. Then, blocks that are never written
+through the IWriteBlock()/IRasterIO() interfaces will have their offset and
+byte count set to 0. This is particularly useful to save disk space and time when
+the file must be initialized empty before being passed to a further processing
+stage that will fill it.
+To avoid ambiguities with anoter sparse mechanism discussed in the next paragraphs,
+we will call such files with implicit tiles/strips "TIFF sparse files". They will
+be likely <b>not</b> interoperable with TIFF readers that are not GDAL based and
+would consider such files with implicit tiles/strips as defective.
+</p>
+
+<p>Starting with GDAL 2.2, this mechanism is extended to the CreateCopy() and
+Open() interfaces (for update mode) as well. If the SPARSE_OK creation option
+(or the SPARSE_OK open option for Open()) is set to YES, even an attempt to
+write a all 0/nodata block will be detected so that the tile/strip is not
+allocated (if it was already allocated, then its content will be replaced by
+the 0/nodata content).</p>
+
+<p>Starting with GDAL 2.2, in the case where SPARSE_OK is <b>not</b> defined (or set
+to its default value FALSE), for uncompressed files whose nodata value is not
+set, or set to 0, in Create() and CreateCopy() mode, the driver will delay the
+allocation of 0-blocks until file closing, so as to be able to write them at
+the very end of the file, and in a way compatible of the filesystem sparse file
+mechanisms (to be distinguished from the TIFF sparse file extension discussed
+earlier). That is that all the empty blocks will be seen as properly allocated
+from the TIFF point of view (corresponding strips/tiles will have valid offsets
+and byte counts), but will have no corresponding physical storage. Provided that
+the filesystem supports such sparse files, which is the case for most Linux
+popular filesystems (ext2/3/4, xfs, btfs, ...) or NTFS on Windows. If the file
+system does not support sparse files, physical storage will be
+allocated and filled with zeros.</p>
+
 <h2>Open options</h2>
 
 <ul>
@@ -166,22 +222,37 @@ Enable multi-threaded compression by specifying the number of worker threads.
 Worth it for slow compression algorithms such as DEFLATE or LZMA. Will be
 ignored for JPEG.  Default is compression in the main thread.</p></li>
 
+<li><p><b>GEOREF_SOURCES=string</b>: (GDAL > 2.2) Define which georeferencing sources are
+allowed and their priority order. See <a href="#georeferencing"><i>Georeferencing</i></a> paragraph.</li>
+
+<li><p><b>SPARSE_OK=TRUE/FALSE</b> ((GDAL > 2.2): Should empty blocks be omitted on disk?
+When this option is set, any attempt of writing a block whose all pixels are 0
+or the nodata value will cause it not to be written at all (unless there is a
+corresponding block already allocated in the file).
+Sparse files have 0 tile/strip offsets for blocks never written and save space;
+however, most non-GDAL packages cannot read such files.
+The default is FALSE.</p></li>
+
 </ul>
 
 <h2>Creation Issues</h2>
 
 <p>GeoTIFF files can be created with any GDAL defined band type, including
 the complex types.  Created files may have any number of bands.  Files
-with exactly 3 bands will be
-given a photometric interpretation of RGB, files with exactly four bands
+of type Byte with exactly 3 bands will be given a photometric interpretation
+of RGB, files of type Byte with exactly four bands
 will have a photometric interpretation of RGBA, while all other combinations
-will have a photometric interpretation of MIN_IS_WHITE.  Files with
-pseudo-color tables, or GCPs can currently only be created when creating from
-an existing GDAL dataset with those objects (GDALDriver::CreateCopy()).</p>
+will have a photometric interpretation of MIN_IS_BLACK. Starting with GDAL 2.2,
+non-standard (regarding to the intrinsics TIFF capabilities) band color
+interpretation, such as BGR ordering, will be handled in creation and reading,
+by storing them in the GDAL internal metadata TIFF tag.</p>
 
 <p>Note that the GeoTIFF format does not support parametric description of datums,
 so TOWGS84 parameters in coordinate systems are lost in GeoTIFF format.</p>
 
+<p>You may want to read hints to <a href="https://trac.osgeo.org/gdal/wiki/CloudOptimizedGeoTIFF">
+generate and read cloud optimized GeoTIFF files</a></p>
+
 <h3>Creation Options</h3>
 
 <ul>
@@ -212,7 +283,10 @@ option can be used to force creation of tiled TIFF files.</p></li>
 <li><p><b>BLOCKYSIZE=n</b>: Set tile or strip height.  Tile height defaults to
 256, strip height defaults to a value such that one strip is 8K or less. </p></li>
 
-<li><p><b>NBITS=n</b>: Create a file with less than 8 bits per sample by passing a value from 1 to 7.  The apparent pixel type should be Byte. From GDAL 1.6.0, values of n=9...15 (UInt16 type) and n=17...31 (UInt32 type) are also accepted. </p></li>
+<li><p><b>NBITS=n</b>: Create a file with less than 8 bits per sample by passing
+a value from 1 to 7.  The apparent pixel type should be Byte.
+From GDAL 1.6.0, values of n=9...15 (UInt16 type) and n=17...31 (UInt32 type) are also accepted.
+From GDAL 2.2, n=16 is accepted for Float32 type to generate half-precision floating point values.</p></li>
 
 <li><p><b>COMPRESS=[JPEG/LZW/PACKBITS/DEFLATE/CCITTRLE/CCITTFAX3/CCITTFAX4/LZMA/NONE]</b>:
 Set the compression to use.  JPEG should generally only be used with Byte data (8 bit per channel).
@@ -234,7 +308,15 @@ Default is compression in the main thread.</p></li>
 Set the number of least-significant bits to clear, possibly different per band.
 Lossy compression scheme to be best used with PREDICTOR=2 and LZW/DEFLATE compression.</p></li>
 
-<li><p><b>SPARSE_OK=TRUE/FALSE</b> (From GDAL 1.6.0): Should newly created files be allowed to be sparse?  Sparse files have 0 tile/strip offsets for blocks never written and save space; however, most non-GDAL packages cannot read such files.  The default is FALSE.</p></li>
+<li><p><b>SPARSE_OK=TRUE/FALSE</b> (From GDAL 1.6.0): Should newly created files (through Create() interface) be allowed to be sparse?
+Sparse files have 0 tile/strip offsets for blocks never written and save space;
+however, most non-GDAL packages cannot read such files.
+Starting with GDAL 2.2, SPARSE_OK=TRUE is also supported through the CreateCopy()
+interface.
+Starting with GDAL 2.2, even an attempt to write a block whose
+all pixels are 0 or the nodata value will cause it not to be written at all
+(unless there is a corresponding block already allocated in the file).
+The default is FALSE.</p></li>
 
 <li><p><b>JPEG_QUALITY=[1-100]</b>:  Set the JPEG quality when using JPEG compression.  A value of 100 is best quality (least compression), and 1 is worst quality (best compression).  The default is 75.</p></li>
 
@@ -397,8 +479,8 @@ This paragraph lists the configuration options that can be set to alter the defa
 Can help reading partially corrupted TIFF files</li>
 <li>ESRI_XML_PAM: Can be set to TRUE to force metadata in the xml:ESRI domain to be written to PAM.</li>
 <li>JPEG_QUALITY_OVERVIEW: Integer between 0 and 100. Default value : 75. Quality of JPEG compressed overviews, either internal or external.</li>
-<li>GDAL_TIFF_INTERNAL_MASK: See <a href="#internal_mask"><i>Internal nodata masks</i> section</a>. Default value : FALSE.</li>
-<li>GDAL_TIFF_INTERNAL_MASK_TO_8BIT: See <a href="#internal_mask"><i>Internal nodata masks</i> section</a>. Default value : TRUE</li>
+<li>GDAL_TIFF_INTERNAL_MASK: See <a href="#internal_mask"><i>Internal nodata masks</i></a>  section. Default value : FALSE.</li>
+<li>GDAL_TIFF_INTERNAL_MASK_TO_8BIT: See <a href="#internal_mask"><i>Internal nodata masks</i></a>  section. Default value : TRUE</li>
 <li>USE_RRD: Can be set to TRUE to force external overviews in the RRD format. Default value : FALSE</li>
 <li>TIFF_USE_OVR: Can be set to TRUE to force external overviews in the GeoTIFF (.ovr) format. Default value : FALSE</li>
 <li>GTIFF_POINT_GEO_IGNORE: Can be set to TRUE to revert back to the behaviour of GDAL < 1.8.0
@@ -409,7 +491,7 @@ RFC 33: GTiff - Fixing PixelIsPoint Interpretation</a> for more details. Default
 <!-- debug option : <li>GDAL_TIFF_ENDIANNESS : Possible values : LITTLE, BIG, INVERTED, NATIVE. Default value : NATIVE</li> -->
 <!-- not sure it is wise to advertize this one. I doubt it works correctly if set to NO. CONVERT_YCBCR_TO_RGB -->
 <!-- debug/autotest option : GTIFF_DELETE_ON_ERROR -->
-<li>GDAL_TIFF_OVR_BLOCKSIZE : See <a href="#overviews"><i>Overviews</i> section</a>.
+<li>GDAL_TIFF_OVR_BLOCKSIZE : See <a href="#overviews"><i>Overviews</i></a> section.
 <li>GTIFF_LINEAR_UNITS: Can be set to BROKEN to read GeoTIFF files that
 have false easting/northing improperly set in meters when it ought to be in
 coordinate system linear units.  (<a href="http://trac.osgeo.org/gdal/ticket/3901">Ticket #3901</a>).
@@ -431,6 +513,14 @@ might occur if the whole file is read. Setting it to IF_ENOUGH_RAM will first
 check if the uncompressed file size is no bigger than the physical memory. Default value:NO.
 If both GTIFF_VIRTUAL_MEM_IO and GTIFF_DIRECT_IO are enabled, the former is used
 in priority, and if not possible, the later is tried.
+<li>GDAL_GEOREF_SOURCES=comma-separated list with one or several of
+PAM, INTERNAL, TABFILE or WORLDFILE. (GDAL >= 2.2).
+See <a href="#georeferencing"><i>Georeferencing</i></a> paragraph.
+<li>GDAL_NUM_THREADS=number_of_threads/ALL_CPUS: (GDAL >= 2.1)
+Enable multi-threaded compression by specifying the number of worker threads.
+Worth it for slow compression algorithms such as DEFLATE or LZMA. Will be
+ignored for JPEG.  Default is compression in the main thread. Note: this
+configuration option also apply to other parts to GDAL (warping, gridding, ...).</li>
 </ul>
 </p>
 
@@ -439,10 +529,12 @@ in priority, and if not possible, the later is tried.
 <p>See Also:</p>
 
 <ul>
-<li> <a href="http://www.remotesensing.org/geotiff/geotiff.html">GeoTIFF Information Page</a></li>
-<li> <a href="http://www.remotesensing.org/libtiff/">libtiff Page</a></li>
+<li> <a href="https://trac.osgeo.org/geotiff">GeoTIFF Information Page</a></li>
+<li> <a href="http://www.simplesystems.org/libtiff/">libtiff Page</a></li>
 <li> <a href="http://www.awaresystems.be/imaging/tiff/bigtiff.html">
         Details on BigTIFF file format</a></li>
+<li> <a href="https://trac.osgeo.org/gdal/wiki/CloudOptimizedGeoTIFF">
+        How to generate and read cloud optimized GeoTIFF files</a></li>
 
 </ul>
 
diff --git a/frmts/gtiff/geotiff.cpp b/frmts/gtiff/geotiff.cpp
index d9e6044..d6a83ca 100644
--- a/frmts/gtiff/geotiff.cpp
+++ b/frmts/gtiff/geotiff.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: geotiff.cpp 37071 2017-01-07 20:49:39Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -28,50 +27,94 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-/* If we use sunpro compiler on linux. Weird idea indeed ! */
+// If we use sunpro compiler on linux. Weird idea indeed!
 #if defined(__SUNPRO_CC) && defined(__linux__)
 #define _GNU_SOURCE
 #elif defined(__GNUC__) && !defined(_GNU_SOURCE)
-/* Required to use RTLD_DEFAULT of dlfcn.h */
+// Required to use RTLD_DEFAULT of dlfcn.h.
 #define _GNU_SOURCE
 #endif
 
 #include "cpl_port.h"  // Must be first.
+#include "gtiff.h"
+
+// TODO(schwehr): Move this to cpl_port.h?
+#if HAVE_CXX11 && !defined(__MINGW32__)
+#define HAVE_CXX11_MUTEX 1
+#endif
+
+#include <cerrno>
+#include <climits>
+#include <cmath>
+#include <cstdarg>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
 
+#include <algorithm>
+#include <memory>
+#if HAVE_CXX11_MUTEX
+#  include <mutex>
+#endif
 #include <set>
+#include <string>
+#include <vector>
 
+#include "cpl_config.h"
+#include "cpl_conv.h"
 #include "cpl_csv.h"
-#include "cplkeywordparser.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
 #include "cpl_multiproc.h"
+#include "cpl_port.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_virtualmem.h"
+#include "cpl_vsi.h"
 #include "cpl_vsi_virtual.h"
 #include "cpl_worker_thread_pool.h"
+#include "cplkeywordparser.h"
+#include "gdal.h"
 #include "gdal_csv.h"
 #include "gdal_frmts.h"
 #include "gdal_mdreader.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "geo_normalize.h"
+#include "geotiff.h"
 #include "geovalues.h"
 #include "gt_jpeg_copy.h"
 #include "gt_overview.h"
 #include "gt_wkt_srs.h"
 #include "gt_wkt_srs_priv.h"
-#include "gtiff.h"
 #include "ogr_spatialref.h"
+#include "tiff.h"
 #include "tif_float.h"
+#include "tiffio.h"
 #ifdef INTERNAL_LIBTIFF
 #  include "tiffiop.h"
 #endif
+#include "tiffvers.h"
 #include "tifvsi.h"
 #include "xtiffio.h"
 
-CPL_CVSID("$Id: geotiff.cpp 37071 2017-01-07 20:49:39Z rouault $");
+
+CPL_CVSID("$Id: geotiff.cpp 37723 2017-03-16 17:07:53Z rouault $");
 
 #if SIZEOF_VOIDP == 4
-static int bGlobalStripIntegerOverflow = FALSE;
+static bool bGlobalStripIntegerOverflow = false;
 #endif
 static bool bGlobalInExternalOvr = false;
 
+const char* const szJPEGGTiffDatasetTmpPrefix = "/vsimem/gtiffdataset_jpg_tmp_";
+
 typedef enum
 {
     GTIFFTAGTYPE_STRING,
@@ -89,7 +132,8 @@ typedef struct
 static const GTIFFTags asTIFFTags[] =
 {
     { "TIFFTAG_DOCUMENTNAME", TIFFTAG_DOCUMENTNAME, GTIFFTAGTYPE_STRING },
-    { "TIFFTAG_IMAGEDESCRIPTION", TIFFTAG_IMAGEDESCRIPTION, GTIFFTAGTYPE_STRING },
+    { "TIFFTAG_IMAGEDESCRIPTION", TIFFTAG_IMAGEDESCRIPTION,
+        GTIFFTAGTYPE_STRING },
     { "TIFFTAG_SOFTWARE", TIFFTAG_SOFTWARE, GTIFFTAGTYPE_STRING },
     { "TIFFTAG_DATETIME", TIFFTAG_DATETIME, GTIFFTAGTYPE_STRING },
     { "TIFFTAG_ARTIST", TIFFTAG_ARTIST, GTIFFTAGTYPE_STRING },
@@ -97,7 +141,8 @@ static const GTIFFTags asTIFFTags[] =
     { "TIFFTAG_COPYRIGHT", TIFFTAG_COPYRIGHT, GTIFFTAGTYPE_STRING },
     { "TIFFTAG_XRESOLUTION", TIFFTAG_XRESOLUTION, GTIFFTAGTYPE_FLOAT },
     { "TIFFTAG_YRESOLUTION", TIFFTAG_YRESOLUTION, GTIFFTAGTYPE_FLOAT },
-    { "TIFFTAG_RESOLUTIONUNIT", TIFFTAG_RESOLUTIONUNIT, GTIFFTAGTYPE_SHORT }, /* dealt as special case */
+    // Dealt as special case.
+    { "TIFFTAG_RESOLUTIONUNIT", TIFFTAG_RESOLUTIONUNIT, GTIFFTAGTYPE_SHORT },
     { "TIFFTAG_MINSAMPLEVALUE", TIFFTAG_MINSAMPLEVALUE, GTIFFTAGTYPE_SHORT },
     { "TIFFTAG_MAXSAMPLEVALUE", TIFFTAG_MAXSAMPLEVALUE, GTIFFTAGTYPE_SHORT },
 };
@@ -106,13 +151,13 @@ static const GTIFFTags asTIFFTags[] =
 /*                            IsPowerOfTwo()                            */
 /************************************************************************/
 
-static bool IsPowerOfTwo(unsigned int i)
+static bool IsPowerOfTwo( unsigned int i )
 {
     int nBitSet = 0;
     while(i != 0)
     {
-        if ((i & 1))
-            nBitSet ++;
+        if( i & 1 )
+            ++nBitSet;
         i >>= 1;
     }
     return nBitSet == 1;
@@ -122,7 +167,7 @@ static bool IsPowerOfTwo(unsigned int i)
 /*                          GTIFFSetInExternalOvr()                     */
 /************************************************************************/
 
-void GTIFFSetInExternalOvr(bool b)
+void GTIFFSetInExternalOvr( bool b )
 {
     bGlobalInExternalOvr = b;
 }
@@ -131,20 +176,21 @@ void GTIFFSetInExternalOvr(bool b)
 /*                     GTIFFGetOverviewBlockSize()                      */
 /************************************************************************/
 
-void GTIFFGetOverviewBlockSize(int* pnBlockXSize, int* pnBlockYSize)
+void GTIFFGetOverviewBlockSize( int* pnBlockXSize, int* pnBlockYSize )
 {
-    static bool bHasWarned = false;
     const char* pszVal = CPLGetConfigOption("GDAL_TIFF_OVR_BLOCKSIZE", "128");
     int nOvrBlockSize = atoi(pszVal);
-    if (nOvrBlockSize < 64 || nOvrBlockSize > 4096 ||
-        !IsPowerOfTwo(nOvrBlockSize))
+    if( nOvrBlockSize < 64 || nOvrBlockSize > 4096 ||
+        !IsPowerOfTwo(nOvrBlockSize) )
     {
-        if (!bHasWarned)
+        static bool bHasWarned = false;
+        if( !bHasWarned )
         {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                    "Wrong value for GDAL_TIFF_OVR_BLOCKSIZE : %s. "
-                    "Should be a power of 2 between 64 and 4096. Defaulting to 128",
-                    pszVal);
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Wrong value for GDAL_TIFF_OVR_BLOCKSIZE : %s. "
+                      "Should be a power of 2 between 64 and 4096. "
+                      "Defaulting to 128",
+                      pszVal );
             bHasWarned = true;
         }
         nOvrBlockSize = 128;
@@ -167,11 +213,12 @@ enum
 /* ==================================================================== */
 /************************************************************************/
 
-class GTiffRasterBand;
-class GTiffRGBABand;
 class GTiffBitmapBand;
-class GTiffJPEGOverviewDS;
+class GTiffDataset;
 class GTiffJPEGOverviewBand;
+class GTiffJPEGOverviewDS;
+class GTiffRasterBand;
+class GTiffRGBABand;
 
 typedef enum
 {
@@ -180,11 +227,13 @@ typedef enum
     VIRTUAL_MEM_IO_IF_ENOUGH_RAM
 } VirtualMemIOEnum;
 
-class GTiffDataset;
+#if !defined(__MINGW32__)
+namespace {
+#endif
 typedef struct
 {
     GTiffDataset *poDS;
-    int           bTIFFIsBigEndian;
+    bool          bTIFFIsBigEndian;
     char         *pszTmpFilename;
     int           nHeight;
     uint16        nPredictor;
@@ -192,42 +241,47 @@ typedef struct
     int           nBufferSize;
     int           nStripOrTile;
 
-    GByte        *pabyCompressedBuffer; /* owned by pszTmpFilename */
+    GByte        *pabyCompressedBuffer;  // Owned by pszTmpFilename.
     int           nCompressedBufferSize;
-    int           bReady;
+    bool          bReady;
 } GTiffCompressionJob;
+#if !defined(__MINGW32__)
+}
+#endif
 
 class GTiffDataset CPL_FINAL : public GDALPamDataset
 {
-    friend class GTiffRasterBand;
-    friend class GTiffSplitBand;
-    friend class GTiffRGBABand;
     friend class GTiffBitmapBand;
-    friend class GTiffSplitBitmapBand;
-    friend class GTiffOddBitsBand;
     friend class GTiffJPEGOverviewDS;
     friend class GTiffJPEGOverviewBand;
+    friend class GTiffOddBitsBand;
+    friend class GTiffRasterBand;
+    friend class GTiffRGBABand;
+    friend class GTiffSplitBand;
+    friend class GTiffSplitBitmapBand;
 
-    friend void    GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality);
+    friend void  GTIFFSetJpegQuality( GDALDatasetH hGTIFFDS, int nJpegQuality );
+    friend void  GTIFFSetJpegTablesMode( GDALDatasetH hGTIFFDS, int nJpegTablesMode );
 
     TIFF       *hTIFF;
     VSILFILE   *fpL;
-    int         bStreamingIn;
+    bool        bStreamingIn;
 
-    int         bStreamingOut;
+    bool        bStreamingOut;
     CPLString   osTmpFilename;
     VSILFILE*   fpToWrite;
     int         nLastWrittenBlockId;
 
     GTiffDataset **ppoActiveDSRef;
-    GTiffDataset *poActiveDS; /* only used in actual base */
+    GTiffDataset *poActiveDS;  // Only used in actual base.
 
-    int         bScanDeferred;
+    bool        bScanDeferred;
     void        ScanDirectories();
 
     toff_t      nDirOffset;
-    int         bBase;
-    int         bCloseTIFFHandle; /* useful for closing TIFF handle opened by GTIFF_DIR: */
+    bool        bBase;
+    // Useful for closing TIFF handle opened by GTIFF_DIR:
+    bool        bCloseTIFFHandle;
 
     uint16      nPlanarConfig;
     uint16      nSamplesPerPixel;
@@ -239,20 +293,21 @@ class GTiffDataset CPL_FINAL : public GDALPamDataset
 
     int         nBlocksPerBand;
 
-    uint32      nBlockXSize;
-    uint32      nBlockYSize;
+    int         nBlockXSize;
+    int         nBlockYSize;
 
-    int         nLoadedBlock;  /* or tile */
-    int         bLoadedBlockDirty;
+    int         nLoadedBlock;  // Or tile.
+    bool        bLoadedBlockDirty;
     GByte       *pabyBlockBuf;
 
-    CPLErr      LoadBlockBuf( int nBlockId, int bReadFromDisk = TRUE );
+    CPLErr      LoadBlockBuf( int nBlockId, bool bReadFromDisk = true );
     CPLErr      FlushBlockBuf();
-    int         bWriteErrorInFlushBlockBuf;
+    bool        bWriteErrorInFlushBlockBuf;
 
     char        *pszProjection;
-    int         bLookedForProjection;
-    int         bLookedForMDAreaOrPoint;
+    CPLString   m_osVertUnit;
+    bool        bLookedForProjection;
+    bool        bLookedForMDAreaOrPoint;
 
     void        LoadMDAreaOrPoint();
     void        LookForProjection();
@@ -261,45 +316,49 @@ class GTiffDataset CPL_FINAL : public GDALPamDataset
 #endif
 
     double      adfGeoTransform[6];
-    int         bGeoTransformValid;
+    bool        bGeoTransformValid;
 
-    int         bTreatAsRGBA;
-    int         bCrystalized;
-    bool        bCheckIfColorInterpMustGoToPamAtCrystalization;
+    bool        bTreatAsRGBA;
+    bool        bCrystalized;
 
     void        Crystalize();  // TODO: Spelling.
 
     GDALColorTable *poColorTable;
 
     void        WriteGeoTIFFInfo();
-    int         SetDirectory( toff_t nDirOffset = 0 );
+    bool        SetDirectory( toff_t nDirOffset = 0 );
 
     int         nOverviewCount;
     GTiffDataset **papoOverviewDS;
 
-    int         nJPEGOverviewVisibilityFlag; /* if > 0, the implicit JPEG overviews are visible through GetOverviewCount() */
-    int         nJPEGOverviewCount; /* currently visible overviews. Generally == nJPEGOverviewCountOri */
-    int         nJPEGOverviewCountOri; /* size of papoJPEGOverviewDS */
+    // If > 0, the implicit JPEG overviews are visible through
+    // GetOverviewCount().
+    int         nJPEGOverviewVisibilityCounter;
+    // Currently visible overviews. Generally == nJPEGOverviewCountOri.
+    int         nJPEGOverviewCount;
+    int         nJPEGOverviewCountOri;  // Size of papoJPEGOverviewDS.
     GTiffJPEGOverviewDS **papoJPEGOverviewDS;
     int         GetJPEGOverviewCount();
 
     int         nGCPCount;
     GDAL_GCP    *pasGCPList;
 
-    int         IsBlockAvailable( int nBlockId );
+    bool        IsBlockAvailable( int nBlockId,
+                                  vsi_l_offset* pnOffset = NULL,
+                                  vsi_l_offset* pnSize = NULL );
 
-    int         bGeoTIFFInfoChanged;
-    int         bForceUnsetGTOrGCPs;
-    int         bForceUnsetProjection;
+    bool        bGeoTIFFInfoChanged;
+    bool        bForceUnsetGTOrGCPs;
+    bool        bForceUnsetProjection;
 
-    int         bNoDataChanged;
-    int         bNoDataSet;
+    bool        bNoDataChanged;
+    bool        bNoDataSet;
     double      dfNoDataValue;
 
-    int         bMetadataChanged;
-    int         bColorProfileMetadataChanged;
+    bool        bMetadataChanged;
+    bool        bColorProfileMetadataChanged;
 
-    int         bNeedsRewrite;
+    bool        bNeedsRewrite;
 
     void        ApplyPamInfo();
     void        PushMetadataToPam();
@@ -309,68 +368,77 @@ class GTiffDataset CPL_FINAL : public GDALPamDataset
     CPLString   osProfile;
     char      **papszCreationOptions;
 
-    int         bLoadingOtherBands;
+    bool        bLoadingOtherBands;
 
     void*        pabyTempWriteBuffer;
     int          nTempWriteBufferSize;
-    bool         WriteEncodedTile(uint32 tile, GByte* pabyData, int bPreserveDataBuffer);
-    bool         WriteEncodedStrip(uint32 strip, GByte* pabyData, int bPreserveDataBuffer);
+    bool         WriteEncodedTile( uint32 tile, GByte* pabyData,
+                                   int bPreserveDataBuffer );
+    bool         WriteEncodedStrip( uint32 strip, GByte* pabyData,
+                                    int bPreserveDataBuffer );
+    template<class T>
+    bool         HasOnlyNoDataT( const T* pBuffer, int nWidth, int nHeight,
+                                int nLineStride, int nComponents );
+    bool         HasOnlyNoData( const void* pBuffer, int nWidth, int nHeight,
+                                int nLineStride, int nComponents );
+    inline bool  IsFirstPixelEqualToNoData( const void* pBuffer );
 
     GTiffDataset* poMaskDS;
     GTiffDataset* poBaseDS;
 
     CPLString    osFilename;
 
-    int          bFillEmptyTiles;
-    void         FillEmptyTiles(void);
+    bool         bWriteEmptyTiles;
+    bool         bFillEmptyTilesAtClosing;
+    void         FillEmptyTiles();
 
     void         FlushDirectory();
     CPLErr       CleanOverviews();
 
-    /* Used for the all-in-on-strip case */
+    // Used for the all-in-on-strip case.
     int           nLastLineRead;
     int           nLastBandRead;
-    int           bTreatAsSplit;
-    int           bTreatAsSplitBitmap;
+    bool          bTreatAsSplit;
+    bool          bTreatAsSplitBitmap;
 
-    int           bClipWarn;
+    bool          bClipWarn;
 
-    int           bIMDRPCMetadataLoaded;
+    bool          bIMDRPCMetadataLoaded;
     char**        papszMetadataFiles;
     void          LoadMetadata();
 
-    int           bEXIFMetadataLoaded;
+    bool          bEXIFMetadataLoaded;
     void          LoadEXIFMetadata();
 
-    int           bICCMetadataLoaded;
+    bool          bICCMetadataLoaded;
     void          LoadICCProfile();
 
-    int           bHasWarnedDisableAggressiveBandCaching;
+    bool          bHasWarnedDisableAggressiveBandCaching;
 
-    int           bDontReloadFirstBlock; /* Hack for libtiff 3.X and #3633 */
+    bool          bDontReloadFirstBlock;  // Hack for libtiff 3.X and #3633.
 
     int           nZLevel;
     int           nLZMAPreset;
     int           nJpegQuality;
     int           nJpegTablesMode;
 
-    int           bPromoteTo8Bits;
+    bool          bPromoteTo8Bits;
 
-    int           bDebugDontWriteBlocks;
+    bool          bDebugDontWriteBlocks;
 
-    CPLErr        RegisterNewOverviewDataset(toff_t nOverviewOffset);
-    CPLErr        CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS);
-    CPLErr        CreateInternalMaskOverviews(int nOvrBlockXSize,
-                                              int nOvrBlockYSize);
+    CPLErr        RegisterNewOverviewDataset( toff_t nOverviewOffset, int l_nJpegQuality );
+    CPLErr        CreateOverviewsFromSrcOverviews( GDALDataset* poSrcDS );
+    CPLErr        CreateInternalMaskOverviews( int nOvrBlockXSize,
+                                               int nOvrBlockYSize );
 
-    int           bIsFinalized;
+    bool          bIsFinalized;
     int           Finalize();
 
-    int           bIgnoreReadErrors;
+    bool          bIgnoreReadErrors;
 
     CPLString     osGeorefFilename;
 
-    int           bDirectIO;
+    bool          bDirectIO;
 
     VirtualMemIOEnum eVirtualMemIOUsage;
     CPLVirtualMem* psVirtualMemIOMapping;
@@ -380,55 +448,58 @@ class GTiffDataset CPL_FINAL : public GDALPamDataset
     CPLVirtualMem *pBaseMapping;
     int            nRefBaseMapping;
 
-    int            bHasDiscardedLsb;
-    std::vector<int> anMaskLsb, anOffsetLsb;
+    bool           bHasDiscardedLsb;
+    std::vector<int> anMaskLsb;
+    std::vector<int> anOffsetLsb;
     void           DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand);
-    void           GetDiscardLsbOption(char** papszOptions);
+    void           GetDiscardLsbOption( char** papszOptions );
 
     CPLWorkerThreadPool *poCompressThreadPool;
     std::vector<GTiffCompressionJob> asCompressionJobs;
     CPLMutex      *hCompressThreadPoolMutex;
-    void           InitCompressionThreads(char** papszOptions);
-    void           InitCreationOrOpenOptions(char** papszOptions);
-    static void    ThreadCompressionFunc(void* pData);
-    void           WaitCompletionForBlock(int nBlockId);
-    void           WriteRawStripOrTile(int nStripOrTile,
-                                 GByte* pabyCompressedBuffer,
-                                 int nCompressedBufferSize);
-    int            SubmitCompressionJob(int nStripOrTile, GByte* pabyData,
-                                        int cc, int nHeight);
-
-    int            GuessJPEGQuality(int& bOutHasQuantizationTable,
-                                    int& bOutHasHuffmanTable);
+    void           InitCompressionThreads( char** papszOptions );
+    void           InitCreationOrOpenOptions( char** papszOptions );
+    static void    ThreadCompressionFunc( void* pData );
+    void           WaitCompletionForBlock( int nBlockId );
+    void           WriteRawStripOrTile( int nStripOrTile,
+                                        GByte* pabyCompressedBuffer,
+                                        int nCompressedBufferSize );
+    bool           SubmitCompressionJob( int nStripOrTile, GByte* pabyData,
+                                         int cc, int nHeight) ;
+
+    int            GuessJPEGQuality( bool& bOutHasQuantizationTable,
+                                     bool& bOutHasHuffmanTable );
+
+    void           SetJPEGQualityAndTablesModeFromFile();
 
     int            DirectIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg );
+                             int nXOff, int nYOff, int nXSize, int nYSize,
+                             void * pData, int nBufXSize, int nBufYSize,
+                             GDALDataType eBufType,
+                             int nBandCount, int *panBandMap,
+                             GSpacing nPixelSpace, GSpacing nLineSpace,
+                             GSpacing nBandSpace,
+                             GDALRasterIOExtraArg* psExtraArg );
 
     int            VirtualMemIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg );
+                                 int nXOff, int nYOff, int nXSize, int nYSize,
+                                 void * pData, int nBufXSize, int nBufYSize,
+                                 GDALDataType eBufType,
+                                 int nBandCount, int *panBandMap,
+                                 GSpacing nPixelSpace, GSpacing nLineSpace,
+                                 GSpacing nBandSpace,
+                                 GDALRasterIOExtraArg* psExtraArg );
 
     GByte          *m_pTempBufferForCommonDirectIO;
     size_t          m_nTempBufferForCommonDirectIOSize;
     template<class FetchBuffer> CPLErr CommonDirectIO(
-                               FetchBuffer& oFetcher,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace );
+        FetchBuffer& oFetcher,
+        int nXOff, int nYOff, int nXSize, int nYSize,
+        void * pData, int nBufXSize, int nBufYSize,
+        GDALDataType eBufType,
+        int nBandCount, int *panBandMap,
+        GSpacing nPixelSpace, GSpacing nLineSpace,
+        GSpacing nBandSpace );
 
     bool        m_bReadGeoTransform;
     bool        m_bLoadPam;
@@ -437,41 +508,50 @@ class GTiffDataset CPL_FINAL : public GDALPamDataset
     bool        m_bHasGotSiblingFiles;
     char      **GetSiblingFiles();
 
+    void        IdentifyAuthorizedGeoreferencingSources();
+    bool        m_bHasIdentifiedAuthorizedGeoreferencingSources;
+    int         m_nPAMGeorefSrcIndex;
+    int         m_nINTERNALGeorefSrcIndex;
+    int         m_nTABFILEGeorefSrcIndex;
+    int         m_nWORLDFILEGeorefSrcIndex;
+    int         m_nGeoTransformGeorefSrcIndex;
+
     void        FlushCacheInternal( bool bFlushDirectory );
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
   public:
-                 GTiffDataset();
-                 ~GTiffDataset();
+             GTiffDataset();
+    virtual ~GTiffDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-    CPLErr         SetGCPs( int, const GDAL_GCP *, const char * );
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
+    CPLErr         SetGCPs( int, const GDAL_GCP *, const char * ) override;
 
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
-    virtual char **GetFileList(void);
+                              int nXOff, int nYOff, int nXSize, int nYSize,
+                              void * pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
+                              int nBandCount, int *panBandMap,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GSpacing nBandSpace,
+                              GDALRasterIOExtraArg* psExtraArg ) override;
+    virtual char **GetFileList() override;
 
     virtual CPLErr IBuildOverviews( const char *, int, int *, int, int *,
-                                    GDALProgressFunc, void * );
+                                    GDALProgressFunc, void * ) override;
 
     CPLErr         OpenOffset( TIFF *, GTiffDataset **ppoActiveDSRef,
-                               toff_t nDirOffset, int bBaseIn, GDALAccess,
-                               int bAllowRGBAInterface = TRUE, bool bReadGeoTransform = false);
+                               toff_t nDirOffset, bool bBaseIn, GDALAccess,
+                               bool bAllowRGBAInterface = true,
+                               bool bReadGeoTransform = false );
 
     static GDALDataset *OpenDir( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
@@ -484,24 +564,26 @@ class GTiffDataset CPL_FINAL : public GDALPamDataset
                                     int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress,
                                     void * pProgressData );
-    virtual void    FlushCache( void );
+    virtual void    FlushCache() override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual CPLErr  SetMetadata( char **, const char * = "" );
-    virtual char  **GetMetadata( const char * pszDomain = "" );
+    virtual char  **GetMetadataDomainList() override;
+    virtual CPLErr  SetMetadata( char **, const char * = "" ) override;
+    virtual char  **GetMetadata( const char * pszDomain = "" ) override;
     virtual CPLErr  SetMetadataItem( const char*, const char*,
-                                     const char* = "" );
+                                     const char* = "" ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
-    virtual void   *GetInternalHandle( const char * );
+                                         const char * pszDomain = "" ) override;
+    virtual void   *GetInternalHandle( const char * ) override;
 
-    virtual CPLErr          CreateMaskBand( int nFlags );
+    virtual CPLErr          CreateMaskBand( int nFlags ) override;
 
-    // only needed by createcopy and close code.
+    // Only needed by createcopy and close code.
     static void     WriteRPC( GDALDataset *, TIFF *, int, const char *,
-                                   const char *, char **, int bWriteOnlyInPAMIfNeeded = FALSE );
-    static int      WriteMetadata( GDALDataset *, TIFF *, int, const char *,
-                                   const char *, char **, int bExcludeRPBandIMGFileWriting = FALSE );
+                              const char *, char **,
+                              bool bWriteOnlyInPAMIfNeeded = false );
+    static bool     WriteMetadata( GDALDataset *, TIFF *, bool, const char *,
+                                   const char *, char **,
+                                   bool bExcludeRPBandIMGFileWriting = false );
     static void     WriteNoDataValue( TIFF *, double );
     static void     UnsetNoDataValue( TIFF * );
 
@@ -511,14 +593,15 @@ class GTiffDataset CPL_FINAL : public GDALPamDataset
                               double dfExtraSpaceForOverviews,
                               char **papszParmList,
                               VSILFILE** pfpL,
-                              CPLString& osTmpFilename);
+                              CPLString& osTmpFilename );
 
-    CPLErr   WriteEncodedTileOrStrip(uint32 tile_or_strip, void* data, int bPreserveDataBuffer);
+    CPLErr   WriteEncodedTileOrStrip( uint32 tile_or_strip, void* data,
+                                      int bPreserveDataBuffer );
 
-    static void SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszParmList, uint32 nBitsPerSample);
+    static void SaveICCProfile( GTiffDataset *pDS, TIFF *hTIFF,
+                                char **papszParmList, uint32 nBitsPerSample );
 };
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                        GTiffJPEGOverviewDS                           */
@@ -527,79 +610,91 @@ class GTiffDataset CPL_FINAL : public GDALPamDataset
 
 class GTiffJPEGOverviewDS CPL_FINAL : public GDALDataset
 {
-        friend class GTiffJPEGOverviewBand;
-        GTiffDataset* poParentDS;
-        int nOverviewLevel;
+    friend class GTiffJPEGOverviewBand;
+    GTiffDataset* poParentDS;
+    int nOverviewLevel;
 
-        int        nJPEGTableSize;
-        GByte     *pabyJPEGTable;
-        CPLString  osTmpFilenameJPEGTable;
+    int        nJPEGTableSize;
+    GByte     *pabyJPEGTable;
+    CPLString  osTmpFilenameJPEGTable;
 
-        CPLString    osTmpFilename;
-        GDALDataset* poJPEGDS;
-        int          nBlockId; /* valid block id of the parent DS that match poJPEGDS */
+    CPLString    osTmpFilename;
+    GDALDataset* poJPEGDS;
+    // Valid block id of the parent DS that match poJPEGDS.
+    int          nBlockId;
 
-    public:
-        GTiffJPEGOverviewDS(GTiffDataset* poParentDS, int nOverviewLevel,
-                            const void* pJPEGTable, int nJPEGTableSize);
-       ~GTiffJPEGOverviewDS();
+  public:
+    GTiffJPEGOverviewDS( GTiffDataset* poParentDS, int nOverviewLevel,
+                         const void* pJPEGTable, int nJPEGTableSize );
+    virtual ~GTiffJPEGOverviewDS();
 
-       virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+    virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
+                              int nXOff, int nYOff, int nXSize, int nYSize,
+                              void * pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
+                              int nBandCount, int *panBandMap,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GSpacing nBandSpace,
+                              GDALRasterIOExtraArg* psExtraArg ) override;
 };
 
 class GTiffJPEGOverviewBand CPL_FINAL : public GDALRasterBand
 {
-    public:
-        GTiffJPEGOverviewBand(GTiffJPEGOverviewDS* poDS, int nBand);
+  public:
+    GTiffJPEGOverviewBand( GTiffJPEGOverviewDS* poDS, int nBand );
+    virtual ~GTiffJPEGOverviewBand() {}
 
-        virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
 /*                        GTiffJPEGOverviewDS()                         */
 /************************************************************************/
 
-GTiffJPEGOverviewDS::GTiffJPEGOverviewDS(GTiffDataset* poParentDSIn, int nOverviewLevelIn,
-                                         const void* pJPEGTable, int nJPEGTableSizeIn) :
+GTiffJPEGOverviewDS::GTiffJPEGOverviewDS( GTiffDataset* poParentDSIn,
+                                          int nOverviewLevelIn,
+                                          const void* pJPEGTable,
+                                          int nJPEGTableSizeIn ) :
+    poParentDS(poParentDSIn),
+    nOverviewLevel(nOverviewLevelIn),
     nJPEGTableSize(nJPEGTableSizeIn),
+    pabyJPEGTable(NULL),
     poJPEGDS(NULL),
     nBlockId(-1)
 {
-    poParentDS = poParentDSIn;
-    nOverviewLevel = nOverviewLevelIn;
-
     osTmpFilenameJPEGTable.Printf("/vsimem/jpegtable_%p", this);
 
     const GByte abyAdobeAPP14RGB[] = {
         0xFF, 0xEE, 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x00,
         0x64, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    bool bAddAdobe = ( poParentDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
-                       poParentDS->nPhotometric != PHOTOMETRIC_YCBCR && poParentDS->nBands == 3 );
-    pabyJPEGTable = (GByte*) CPLMalloc(nJPEGTableSize + ((bAddAdobe) ? sizeof(abyAdobeAPP14RGB) : 0));
+    const bool bAddAdobe =
+        poParentDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
+        poParentDS->nPhotometric != PHOTOMETRIC_YCBCR &&
+        poParentDS->nBands == 3;
+    pabyJPEGTable =
+        static_cast<GByte*>( CPLMalloc(
+            nJPEGTableSize + (bAddAdobe ? sizeof(abyAdobeAPP14RGB) : 0)) );
     memcpy(pabyJPEGTable, pJPEGTable, nJPEGTableSize);
     if( bAddAdobe )
     {
-        memcpy(pabyJPEGTable + nJPEGTableSize, abyAdobeAPP14RGB, sizeof(abyAdobeAPP14RGB));
+        memcpy( pabyJPEGTable + nJPEGTableSize, abyAdobeAPP14RGB,
+                sizeof(abyAdobeAPP14RGB) );
         nJPEGTableSize += sizeof(abyAdobeAPP14RGB);
     }
-    CPL_IGNORE_RET_VAL(VSIFCloseL(VSIFileFromMemBuffer( osTmpFilenameJPEGTable, pabyJPEGTable, nJPEGTableSize, TRUE )));
+    CPL_IGNORE_RET_VAL(
+        VSIFCloseL(
+            VSIFileFromMemBuffer(
+                osTmpFilenameJPEGTable, pabyJPEGTable, nJPEGTableSize, TRUE )));
 
-    int nScaleFactor = 1 << nOverviewLevel;
+    const int nScaleFactor = 1 << nOverviewLevel;
     nRasterXSize = (poParentDS->nRasterXSize + nScaleFactor - 1) / nScaleFactor;
     nRasterYSize = (poParentDS->nRasterYSize + nScaleFactor - 1) / nScaleFactor;
 
-    for(int i=1;i<=poParentDS->nBands;i++)
+    for( int i = 1; i <= poParentDS->nBands; ++i )
         SetBand(i, new GTiffJPEGOverviewBand(this, i));
 
     SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
-    if ( poParentDS->nPhotometric == PHOTOMETRIC_YCBCR )
+    if( poParentDS->nPhotometric == PHOTOMETRIC_YCBCR )
         SetMetadataItem( "COMPRESSION", "YCbCr JPEG", "IMAGE_STRUCTURE" );
     else
         SetMetadataItem( "COMPRESSION", "JPEG", "IMAGE_STRUCTURE" );
@@ -612,9 +707,9 @@ GTiffJPEGOverviewDS::GTiffJPEGOverviewDS(GTiffDataset* poParentDSIn, int nOvervi
 GTiffJPEGOverviewDS::~GTiffJPEGOverviewDS()
 {
     if( poJPEGDS != NULL )
-        GDALClose( (GDALDatasetH) poJPEGDS );
+        GDALClose( poJPEGDS );
     VSIUnlink(osTmpFilenameJPEGTable);
-    if( osTmpFilename.size() )
+    if( !osTmpFilename.empty() )
         VSIUnlink(osTmpFilename);
 }
 
@@ -622,48 +717,51 @@ GTiffJPEGOverviewDS::~GTiffJPEGOverviewDS()
 /*                            IRasterIO()                               */
 /************************************************************************/
 
-CPLErr GTiffJPEGOverviewDS::IRasterIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg)
+CPLErr GTiffJPEGOverviewDS::IRasterIO(
+    GDALRWFlag eRWFlag,
+    int nXOff, int nYOff, int nXSize, int nYSize,
+    void * pData, int nBufXSize, int nBufYSize,
+    GDALDataType eBufType,
+    int nBandCount, int *panBandMap,
+    GSpacing nPixelSpace, GSpacing nLineSpace,
+    GSpacing nBandSpace,
+    GDALRasterIOExtraArg* psExtraArg )
 
 {
-    /* For non-single strip JPEG-IN-TIFF, the block based strategy will */
-    /* be the most efficient one, to avoid decompressing the JPEG content */
-    /* for each requested band */
+    // For non-single strip JPEG-IN-TIFF, the block based strategy will
+    // be the most efficient one, to avoid decompressing the JPEG content
+    // for each requested band.
     if( nBandCount > 1 && poParentDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
-        ((int)poParentDS->nBlockXSize < poParentDS->nRasterXSize ||
-        poParentDS->nBlockYSize > 1) )
+        (poParentDS->nBlockXSize < poParentDS->nRasterXSize ||
+         poParentDS->nBlockYSize > 1) )
     {
         return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                    pData, nBufXSize, nBufYSize,
                                    eBufType, nBandCount, panBandMap,
-                                   nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
-    }
-    else
-    {
-        return GDALDataset::IRasterIO(
-                eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                pData, nBufXSize, nBufYSize, eBufType,
-                nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
+                                   nPixelSpace, nLineSpace, nBandSpace,
+                                   psExtraArg );
     }
 
+    return GDALDataset::IRasterIO(
+        eRWFlag, nXOff, nYOff, nXSize, nYSize,
+        pData, nBufXSize, nBufYSize, eBufType,
+        nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
+        psExtraArg );
 }
 
 /************************************************************************/
 /*                        GTiffJPEGOverviewBand()                       */
 /************************************************************************/
 
-GTiffJPEGOverviewBand::GTiffJPEGOverviewBand(GTiffJPEGOverviewDS* poDSIn, int nBandIn)
+GTiffJPEGOverviewBand::GTiffJPEGOverviewBand( GTiffJPEGOverviewDS* poDSIn,
+                                              int nBandIn )
 {
     poDS = poDSIn;
     nBand = nBandIn;
-    eDataType = poDSIn->poParentDS->GetRasterBand(nBandIn)->GetRasterDataType();
-    poDSIn->poParentDS->GetRasterBand(nBandIn)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    eDataType =
+        poDSIn->poParentDS->GetRasterBand(nBandIn)->GetRasterDataType();
+    poDSIn->poParentDS->GetRasterBand(nBandIn)->
+        GetBlockSize(&nBlockXSize, &nBlockYSize);
     const int nScaleFactor = 1 << poDSIn->nOverviewLevel;
     nBlockXSize = (nBlockXSize + nScaleFactor - 1) / nScaleFactor;
     nBlockYSize = (nBlockYSize + nScaleFactor - 1) / nScaleFactor;
@@ -673,17 +771,14 @@ GTiffJPEGOverviewBand::GTiffJPEGOverviewBand(GTiffJPEGOverviewDS* poDSIn, int nB
 /*                          IReadBlock()                                */
 /************************************************************************/
 
-CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage )
+CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                          void *pImage )
 {
-    GTiffJPEGOverviewDS* poGDS = (GTiffJPEGOverviewDS*)poDS;
+    GTiffJPEGOverviewDS* poGDS = static_cast<GTiffJPEGOverviewDS *>(poDS);
 
-    /* Compute the source block ID */
-    int nBlockId;
-    if( nBlockYSize == 1 )
-    {
-        nBlockId = 0;
-    }
-    else
+    // Compute the source block ID.
+    int nBlockId = 0;
+    if( nBlockYSize != 1 )
     {
         nBlocksPerRow = DIV_ROUND_UP(poGDS->poParentDS->nRasterXSize,
                                                poGDS->poParentDS->nBlockXSize);
@@ -697,50 +792,37 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
     if( !poGDS->poParentDS->SetDirectory() )
         return CE_Failure;
 
-    /* Make sure it is available */
-    const int nDataTypeSize = GDALGetDataTypeSize(eDataType)/8;
-    if( !poGDS->poParentDS->IsBlockAvailable(nBlockId) )
+    // Make sure it is available.
+    const int nDataTypeSize = GDALGetDataTypeSizeBytes(eDataType);
+    vsi_l_offset nOffset = 0;
+    vsi_l_offset nByteCount = 0;
+    if( !poGDS->poParentDS->IsBlockAvailable(nBlockId, &nOffset, &nByteCount) )
     {
         memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize );
         return CE_None;
     }
 
-    int nScaleFactor = 1 << poGDS->nOverviewLevel;
+    const int nScaleFactor = 1 << poGDS->nOverviewLevel;
     if( poGDS->poJPEGDS == NULL || nBlockId != poGDS->nBlockId )
     {
-        toff_t *panByteCounts = NULL;
-        toff_t *panOffsets = NULL;
-        vsi_l_offset nOffset = 0;
-        vsi_l_offset nByteCount = 0;
-
-        /* Find offset and size of the JPEG tile/strip */
-        TIFF* hTIFF = poGDS->poParentDS->hTIFF;
-        if( (( TIFFIsTiled( hTIFF )
-            && TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts )
-            && TIFFGetField( hTIFF, TIFFTAG_TILEOFFSETS, &panOffsets ) )
-            || ( !TIFFIsTiled( hTIFF )
-            && TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts )
-            && TIFFGetField( hTIFF, TIFFTAG_STRIPOFFSETS, &panOffsets ) )) &&
-            panByteCounts != NULL && panOffsets != NULL )
-        {
-            if( panByteCounts[nBlockId] < 2 )
-                return CE_Failure;
-            nOffset = panOffsets[nBlockId] + 2; /* skip leading 0xFF 0xF8 */
-            nByteCount = panByteCounts[nBlockId] - 2;
-        }
-        else
-        {
+        if( nByteCount < 2 )
             return CE_Failure;
-        }
+        nOffset += 2;  // Skip leading 0xFF 0xF8.
+        nByteCount -= 2;
 
-        /* Special case for last strip that might be smaller than other strips */
-        /* In which case we must invalidate the dataset */
+        // Special case for last strip that might be smaller than other strips
+        // In which case we must invalidate the dataset.
+        TIFF* hTIFF = poGDS->poParentDS->hTIFF;
         if( !TIFFIsTiled( hTIFF ) && poGDS->poParentDS->nBlockYSize > 1 &&
-            (nBlockYOff + 1 == (int)DIV_ROUND_UP(poGDS->poParentDS->nRasterYSize, poGDS->poParentDS->nBlockYSize) ||
-             (poGDS->poJPEGDS != NULL && poGDS->poJPEGDS->GetRasterYSize() != nBlockYSize * nScaleFactor)) )
+            (nBlockYOff + 1 ==
+                 DIV_ROUND_UP( poGDS->poParentDS->nRasterYSize,
+                               poGDS->poParentDS->nBlockYSize ) ||
+             (poGDS->poJPEGDS != NULL &&
+              poGDS->poJPEGDS->GetRasterYSize() !=
+              nBlockYSize * nScaleFactor)) )
         {
             if( poGDS->poJPEGDS != NULL )
-                GDALClose( (GDALDatasetH) poGDS->poJPEGDS );
+                GDALClose( poGDS->poJPEGDS );
             poGDS->poJPEGDS = NULL;
         }
 
@@ -748,33 +830,36 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
         poGDS->osTmpFilename.Printf("/vsimem/sparse_%p", poGDS);
         VSILFILE* fp = VSIFOpenL(poGDS->osTmpFilename, "wb+");
 
-        /* If the size of the JPEG strip/tile is small enough, we will */
-        /* read it from the TIFF file and forge a in-memory JPEG file with */
-        /* the JPEG table followed by the JPEG data. */
-        bool bInMemoryJPEGFile = ( nByteCount < 256 * 256 );
+        // If the size of the JPEG strip/tile is small enough, we will
+        // read it from the TIFF file and forge a in-memory JPEG file with
+        // the JPEG table followed by the JPEG data.
+        const bool bInMemoryJPEGFile = nByteCount < 256 * 256;
         if( bInMemoryJPEGFile )
         {
-            /* If the previous file was opened as a /vsisparse/, we have to re-open */
+            // If the previous file was opened as a /vsisparse/, must re-open.
             if( poGDS->poJPEGDS != NULL &&
                 STARTS_WITH(poGDS->poJPEGDS->GetDescription(), "/vsisparse/") )
             {
-                GDALClose( (GDALDatasetH) poGDS->poJPEGDS );
+                GDALClose( poGDS->poJPEGDS );
                 poGDS->poJPEGDS = NULL;
             }
             osFileToOpen = poGDS->osTmpFilename;
 
-            bool bError = FALSE;
-            if( VSIFSeekL(fp, poGDS->nJPEGTableSize + nByteCount - 1, SEEK_SET) != 0 )
+            bool bError = false;
+            if( VSIFSeekL(fp, poGDS->nJPEGTableSize + nByteCount - 1, SEEK_SET)
+                != 0 )
                 bError = true;
             char ch = 0;
             if( !bError && VSIFWriteL(&ch, 1, 1, fp) != 1 )
                 bError = true;
-            GByte* pabyBuffer = VSIGetMemFileBuffer( poGDS->osTmpFilename, NULL, FALSE);
+            GByte* pabyBuffer =
+                VSIGetMemFileBuffer( poGDS->osTmpFilename, NULL, FALSE);
             memcpy(pabyBuffer, poGDS->pabyJPEGTable, poGDS->nJPEGTableSize);
             VSILFILE* fpTIF = VSI_TIFFGetVSILFile(TIFFClientdata( hTIFF ));
             if( !bError && VSIFSeekL(fpTIF, nOffset, SEEK_SET) != 0 )
                 bError = true;
-            if( VSIFReadL(pabyBuffer + poGDS->nJPEGTableSize, (size_t)nByteCount, 1, fpTIF) != 1 )
+            if( VSIFReadL( pabyBuffer + poGDS->nJPEGTableSize,
+                           static_cast<size_t>(nByteCount), 1, fpTIF) != 1 )
                 bError = true;
             if( bError )
             {
@@ -784,32 +869,37 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
         }
         else
         {
-            /* If the JPEG strip/tile is too big (e.g. a single-strip JPEG-in-TIFF) */
-            /* we will use /vsisparse mechanism to make a fake JPEG file */
+            // If the JPEG strip/tile is too big (e.g. a single-strip
+            // JPEG-in-TIFF), we will use /vsisparse mechanism to make a
+            // fake JPEG file.
 
-            /* Always re-open */
-            GDALClose( (GDALDatasetH) poGDS->poJPEGDS );
+            // Always re-open.
+            GDALClose( poGDS->poJPEGDS );
             poGDS->poJPEGDS = NULL;
 
-            osFileToOpen = CPLSPrintf("/vsisparse/%s", poGDS->osTmpFilename.c_str());
-
-            if( VSIFPrintfL(fp, "<VSISparseFile><SubfileRegion><Filename relative='0'>%s</Filename>"
-                        "<DestinationOffset>0</DestinationOffset>"
-                        "<SourceOffset>0</SourceOffset>"
-                        "<RegionLength>%d</RegionLength>"
-                        "</SubfileRegion>"
-                        "<SubfileRegion>"
-                        "<Filename relative='0'>%s</Filename>"
-                        "<DestinationOffset>%d</DestinationOffset>"
-                        "<SourceOffset>" CPL_FRMT_GUIB "</SourceOffset>"
-                        "<RegionLength>" CPL_FRMT_GUIB "</RegionLength>"
-                        "</SubfileRegion></VSISparseFile>",
-                        poGDS->osTmpFilenameJPEGTable.c_str(),
-                        (int)poGDS->nJPEGTableSize,
-                        poGDS->poParentDS->GetDescription(),
-                        (int)poGDS->nJPEGTableSize,
-                        nOffset,
-                        nByteCount) < 0 )
+            osFileToOpen =
+                CPLSPrintf("/vsisparse/%s", poGDS->osTmpFilename.c_str());
+
+            if( VSIFPrintfL(
+                    fp,
+                    "<VSISparseFile><SubfileRegion>"
+                    "<Filename relative='0'>%s</Filename>"
+                    "<DestinationOffset>0</DestinationOffset>"
+                    "<SourceOffset>0</SourceOffset>"
+                    "<RegionLength>%d</RegionLength>"
+                    "</SubfileRegion>"
+                    "<SubfileRegion>"
+                    "<Filename relative='0'>%s</Filename>"
+                    "<DestinationOffset>%d</DestinationOffset>"
+                    "<SourceOffset>" CPL_FRMT_GUIB "</SourceOffset>"
+                    "<RegionLength>" CPL_FRMT_GUIB "</RegionLength>"
+                    "</SubfileRegion></VSISparseFile>",
+                    poGDS->osTmpFilenameJPEGTable.c_str(),
+                    static_cast<int>(poGDS->nJPEGTableSize),
+                    poGDS->poParentDS->GetDescription(),
+                    static_cast<int>(poGDS->nJPEGTableSize),
+                    nOffset,
+                    nByteCount) < 0 )
             {
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                 return CE_Failure;
@@ -820,42 +910,52 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
         if( poGDS->poJPEGDS == NULL )
         {
             const char* apszDrivers[] = { "JPEG", NULL };
-            
+
             CPLString osOldVal;
-            if( poGDS->poParentDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands == 4 )
+            if( poGDS->poParentDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
+                poGDS->nBands == 4 )
             {
-                osOldVal = CPLGetThreadLocalConfigOption("GDAL_JPEG_TO_RGB", "");
+                osOldVal =
+                    CPLGetThreadLocalConfigOption("GDAL_JPEG_TO_RGB", "");
                 CPLSetThreadLocalConfigOption("GDAL_JPEG_TO_RGB", "NO");
             }
 
-            poGDS->poJPEGDS = (GDALDataset*) GDALOpenEx(osFileToOpen,
-                                                        GDAL_OF_RASTER | GDAL_OF_INTERNAL,
-                                                                apszDrivers,
-                                                                NULL, NULL);
+            poGDS->poJPEGDS =
+                static_cast<GDALDataset *>( GDALOpenEx(
+                    osFileToOpen,
+                    GDAL_OF_RASTER | GDAL_OF_INTERNAL,
+                    apszDrivers, NULL, NULL) );
+
             if( poGDS->poJPEGDS != NULL )
             {
-                /* Force all implicit overviews to be available, even for small tiles */
-                CPLSetThreadLocalConfigOption("JPEG_FORCE_INTERNAL_OVERVIEWS", "YES");
+                // Force all implicit overviews to be available, even for
+                // small tiles.
+                CPLSetThreadLocalConfigOption( "JPEG_FORCE_INTERNAL_OVERVIEWS",
+                                               "YES");
                 GDALGetOverviewCount(GDALGetRasterBand(poGDS->poJPEGDS, 1));
-                CPLSetThreadLocalConfigOption("JPEG_FORCE_INTERNAL_OVERVIEWS", NULL);
+                CPLSetThreadLocalConfigOption( "JPEG_FORCE_INTERNAL_OVERVIEWS",
+                                               NULL);
 
                 poGDS->nBlockId = nBlockId;
             }
-            
-            if( poGDS->poParentDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands == 4 )
+
+            if( poGDS->poParentDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
+                poGDS->nBands == 4 )
             {
-                CPLSetThreadLocalConfigOption("GDAL_JPEG_TO_RGB", osOldVal.size() ? osOldVal.c_str() : NULL);
+                CPLSetThreadLocalConfigOption(
+                    "GDAL_JPEG_TO_RGB",
+                    !osOldVal.empty() ? osOldVal.c_str() : NULL );
             }
         }
         else
         {
-            /* Trick: we invalidate the JPEG dataset to force a reload */
-            /* of the new content */
+            // Trick: we invalidate the JPEG dataset to force a reload
+            // of the new content.
             CPLErrorReset();
             poGDS->poJPEGDS->FlushCache();
             if( CPLGetLastErrorNo() != 0 )
             {
-                GDALClose( (GDALDatasetH) poGDS->poJPEGDS );
+                GDALClose( poGDS->poJPEGDS );
                 poGDS->poJPEGDS = NULL;
                 return CE_Failure;
             }
@@ -868,7 +968,10 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
     {
         GDALDataset* l_poDS = poGDS->poJPEGDS;
 
-        int nReqXOff = 0, nReqYOff, nReqXSize, nReqYSize;
+        int nReqXOff = 0;
+        int nReqYOff = 0;
+        int nReqXSize = 0;
+        int nReqYSize = 0;
         if( nBlockYSize == 1 )
         {
             nReqYOff = nBlockYOff * nScaleFactor;
@@ -877,7 +980,6 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
         }
         else
         {
-            nReqYOff = 0;
             nReqXSize = nBlockXSize * nScaleFactor;
             nReqYSize = nBlockYSize * nScaleFactor;
         }
@@ -896,7 +998,9 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
             if( nBufYSize == 0 ) nBufYSize = 1;
         }
 
-        int nSrcBand = ( poGDS->poParentDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) ? 1 : nBand;
+        const int nSrcBand =
+            poGDS->poParentDS->nPlanarConfig == PLANARCONFIG_SEPARATE ?
+            1 : nBand;
         if( nSrcBand <= l_poDS->GetRasterCount() )
         {
             eErr = l_poDS->GetRasterBand(nSrcBand)->RasterIO(GF_Read,
@@ -913,23 +1017,44 @@ CPLErr GTiffJPEGOverviewBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *
 /************************************************************************/
 /*                        GTIFFSetJpegQuality()                         */
 /* Called by GTIFFBuildOverviews() to set the jpeg quality on the IFD   */
-/* of the .ovr file                                                     */
+/* of the .ovr file.                                                    */
 /************************************************************************/
 
-void GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality)
+void GTIFFSetJpegQuality( GDALDatasetH hGTIFFDS, int nJpegQuality )
 {
-    CPLAssert(EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
+    CPLAssert(
+        EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
 
-    GTiffDataset* poDS = (GTiffDataset*)hGTIFFDS;
+    GTiffDataset* const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
     poDS->nJpegQuality = nJpegQuality;
 
     poDS->ScanDirectories();
 
-    for(int i=0;i<poDS->nOverviewCount;i++)
+    for( int i = 0; i < poDS->nOverviewCount; ++i )
         poDS->papoOverviewDS[i]->nJpegQuality = nJpegQuality;
 }
 
 /************************************************************************/
+/*                     GTIFFSetJpegTablesMode()                         */
+/* Called by GTIFFBuildOverviews() to set the jpeg tables mode on the   */
+/* of the .ovr file.                                                    */
+/************************************************************************/
+
+void GTIFFSetJpegTablesMode( GDALDatasetH hGTIFFDS, int nJpegTablesMode )
+{
+    CPLAssert(
+        EQUAL(GDALGetDriverShortName(GDALGetDatasetDriver(hGTIFFDS)), "GTIFF"));
+
+    GTiffDataset* const poDS = static_cast<GTiffDataset *>(hGTIFFDS);
+    poDS->nJpegTablesMode = nJpegTablesMode;
+
+    poDS->ScanDirectories();
+
+    for( int i = 0; i < poDS->nOverviewCount; ++i )
+        poDS->papoOverviewDS[i]->nJpegTablesMode = nJpegTablesMode;
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*                            GTiffRasterBand                           */
 /* ==================================================================== */
@@ -941,107 +1066,117 @@ class GTiffRasterBand : public GDALPamRasterBand
 
     GDALColorInterp    eBandInterp;
 
-    int                bHaveOffsetScale;
+    bool               bHaveOffsetScale;
     double             dfOffset;
     double             dfScale;
     CPLString          osUnitType;
     CPLString          osDescription;
 
     int                DirectIO( GDALRWFlag eRWFlag,
-                                  int nXOff, int nYOff, int nXSize, int nYSize,
-                                  void * pData, int nBufXSize, int nBufYSize,
-                                  GDALDataType eBufType,
-                                  GSpacing nPixelSpace, GSpacing nLineSpace,
-                                  GDALRasterIOExtraArg* psExtraArg );
+                                 int nXOff, int nYOff, int nXSize, int nYSize,
+                                 void * pData, int nBufXSize, int nBufYSize,
+                                 GDALDataType eBufType,
+                                 GSpacing nPixelSpace, GSpacing nLineSpace,
+                                 GDALRasterIOExtraArg* psExtraArg );
 
     std::set<GTiffRasterBand **> aSetPSelf;
-    static void     DropReferenceVirtualMem(void* pUserData);
+    static void     DropReferenceVirtualMem( void* pUserData );
     CPLVirtualMem * GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
                                                int *pnPixelSpace,
                                                GIntBig *pnLineSpace,
                                                char **papszOptions );
+
 protected:
     GTiffDataset       *poGDS;
     GDALMultiDomainMetadata oGTiffMDMD;
 
-    int                bNoDataSet;
+    bool               bNoDataSet;
     double             dfNoDataValue;
 
     void NullBlock( void *pData );
     CPLErr FillCacheForOtherBands( int nBlockXOff, int nBlockYOff );
 
 public:
-                   GTiffRasterBand( GTiffDataset *, int );
-                  ~GTiffRasterBand();
+             GTiffRasterBand( GTiffDataset *, int );
+    virtual ~GTiffRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
+
+    virtual int IGetDataCoverageStatus( int nXOff, int nYOff,
+                                        int nXSize, int nYSize,
+                                        int nMaskFlagStop,
+                                        double* pdfDataPct) override;
 
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
-                                  int nXOff, int nYOff, int nXSize, int nYSize,
-                                  void * pData, int nBufXSize, int nBufYSize,
-                                  GDALDataType eBufType,
-                                  GSpacing nPixelSpace, GSpacing nLineSpace,
-                                  GDALRasterIOExtraArg* psExtraArg ) CPL_FINAL;
-
-    virtual const char *GetDescription() const CPL_FINAL;
-    virtual void        SetDescription( const char * ) CPL_FINAL;
-
-    virtual GDALColorInterp GetColorInterpretation() /*CPL_FINAL*/;
-    virtual GDALColorTable *GetColorTable() /*CPL_FINAL*/;
-    virtual CPLErr          SetColorTable( GDALColorTable * ) CPL_FINAL;
-    virtual double          GetNoDataValue( int * ) CPL_FINAL;
-    virtual CPLErr          SetNoDataValue( double ) CPL_FINAL;
-    virtual CPLErr DeleteNoDataValue() CPL_FINAL;
-
-    virtual double GetOffset( int *pbSuccess = NULL ) CPL_FINAL;
-    virtual CPLErr SetOffset( double dfNewValue ) CPL_FINAL;
-    virtual double GetScale( int *pbSuccess = NULL ) CPL_FINAL;
-    virtual CPLErr SetScale( double dfNewValue ) CPL_FINAL;
-    virtual const char* GetUnitType() CPL_FINAL;
-    virtual CPLErr SetUnitType( const char *pszNewValue ) CPL_FINAL;
-    virtual CPLErr SetColorInterpretation( GDALColorInterp ) CPL_FINAL;
-
-    virtual char      **GetMetadataDomainList() CPL_FINAL;
-    virtual CPLErr  SetMetadata( char **, const char * = "" ) CPL_FINAL;
-    virtual char  **GetMetadata( const char * pszDomain = "" ) CPL_FINAL;
+                              int nXOff, int nYOff, int nXSize, int nYSize,
+                              void * pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GDALRasterIOExtraArg* psExtraArg ) override CPL_FINAL;
+
+    virtual const char *GetDescription() const override CPL_FINAL;
+    virtual void        SetDescription( const char * ) override CPL_FINAL;
+
+    virtual GDALColorInterp GetColorInterpretation() override /*CPL_FINAL*/;
+    virtual GDALColorTable *GetColorTable() override /*CPL_FINAL*/;
+    virtual CPLErr          SetColorTable( GDALColorTable * ) override CPL_FINAL;
+    virtual double          GetNoDataValue( int * ) override CPL_FINAL;
+    virtual CPLErr          SetNoDataValue( double ) override CPL_FINAL;
+    virtual CPLErr DeleteNoDataValue() override CPL_FINAL;
+
+    virtual double GetOffset( int *pbSuccess = NULL ) override CPL_FINAL;
+    virtual CPLErr SetOffset( double dfNewValue ) override CPL_FINAL;
+    virtual double GetScale( int *pbSuccess = NULL ) override CPL_FINAL;
+    virtual CPLErr SetScale( double dfNewValue ) override CPL_FINAL;
+    virtual const char* GetUnitType() override CPL_FINAL;
+    virtual CPLErr SetUnitType( const char *pszNewValue ) override CPL_FINAL;
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) override CPL_FINAL;
+
+    virtual char      **GetMetadataDomainList() override CPL_FINAL;
+    virtual CPLErr  SetMetadata( char **, const char * = "" ) override CPL_FINAL;
+    virtual char  **GetMetadata( const char * pszDomain = "" ) override CPL_FINAL;
     virtual CPLErr  SetMetadataItem( const char*, const char*,
-                                     const char* = "" ) CPL_FINAL;
-    virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" ) CPL_FINAL;
-    virtual int    GetOverviewCount() CPL_FINAL;
-    virtual GDALRasterBand *GetOverview( int ) CPL_FINAL;
+                                     const char* = "" ) override CPL_FINAL;
+    virtual const char *GetMetadataItem(
+        const char * pszName, const char * pszDomain = "" ) override CPL_FINAL;
+    virtual int    GetOverviewCount()  override CPL_FINAL;
+    virtual GDALRasterBand *GetOverview( int ) override CPL_FINAL;
 
-    virtual GDALRasterBand *GetMaskBand() CPL_FINAL;
-    virtual int             GetMaskFlags() CPL_FINAL;
-    virtual CPLErr          CreateMaskBand( int nFlags ) CPL_FINAL;
+    virtual GDALRasterBand *GetMaskBand() override CPL_FINAL;
+    virtual int             GetMaskFlags() override CPL_FINAL;
+    virtual CPLErr          CreateMaskBand( int nFlags )  override CPL_FINAL;
 
     virtual CPLVirtualMem  *GetVirtualMemAuto( GDALRWFlag eRWFlag,
                                                int *pnPixelSpace,
                                                GIntBig *pnLineSpace,
-                                               char **papszOptions ) CPL_FINAL;
+                                               char **papszOptions )  override CPL_FINAL;
 
-    virtual CPLErr  GetHistogram( double dfMin, double dfMax,
-                          int nBuckets, GUIntBig * panHistogram,
-                          int bIncludeOutOfRange, int bApproxOK,
-                          GDALProgressFunc, void *pProgressData ) CPL_FINAL;
+    virtual CPLErr  GetHistogram(
+        double dfMin, double dfMax,
+        int nBuckets, GUIntBig * panHistogram,
+        int bIncludeOutOfRange, int bApproxOK,
+        GDALProgressFunc, void *pProgressData )  override CPL_FINAL;
 
     virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
-                                        int *pnBuckets, GUIntBig ** ppanHistogram,
+                                        int *pnBuckets,
+                                        GUIntBig ** ppanHistogram,
                                         int bForce,
-                                        GDALProgressFunc, void *pProgressData) CPL_FINAL;
+                                        GDALProgressFunc,
+                                        void *pProgressData)  override CPL_FINAL;
 };
 
 /************************************************************************/
 /*                           GTiffRasterBand()                          */
 /************************************************************************/
 
-GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDSIn, int nBandIn) :
-    bHaveOffsetScale(FALSE),
+GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDSIn, int nBandIn ) :
+    eBandInterp(GCI_Undefined),
+    bHaveOffsetScale(false),
     dfOffset(0.0),
     dfScale(1.0),
     poGDS(poDSIn),
-    bNoDataSet(FALSE),
+    bNoDataSet(false),
     dfNoDataValue(-9999.0)
 {
     poDS = poDSIn;
@@ -1059,7 +1194,8 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDSIn, int nBandIn) :
     {
         eDataType = GDT_Byte;
         if( nSampleFormat == SAMPLEFORMAT_INT )
-            oGTiffMDMD.SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
+            oGTiffMDMD.SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
+                                        "IMAGE_STRUCTURE" );
     }
     else if( nBitsPerSample <= 16 )
     {
@@ -1100,12 +1236,14 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDSIn, int nBandIn) :
     bool bLookForExtraSamples = false;
 
     if( poGDS->poColorTable != NULL && nBand == 1 )
+    {
         eBandInterp = GCI_PaletteIndex;
+    }
     else if( poGDS->nPhotometric == PHOTOMETRIC_RGB
              || (poGDS->nPhotometric == PHOTOMETRIC_YCBCR
                  && poGDS->nCompression == COMPRESSION_JPEG
                  && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
-                                                       "YES") )) )
+                                                    "YES") )) )
     {
         if( nBand == 1 )
             eBandInterp = GCI_RedBand;
@@ -1141,13 +1279,17 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDSIn, int nBandIn) :
             bLookForExtraSamples = true;
     }
     else if( poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK && nBand == 1 )
+    {
         eBandInterp = GCI_GrayIndex;
+    }
     else
+    {
         bLookForExtraSamples = true;
+    }
 
     if( bLookForExtraSamples )
     {
-        uint16 *v;
+        uint16 *v = NULL;
         uint16 count = 0;
 
         if( TIFFGetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
@@ -1178,7 +1320,9 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDSIn, int nBandIn) :
                 eBandInterp = GCI_Undefined;
         }
         else
+        {
             eBandInterp = GCI_Undefined;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1195,13 +1339,15 @@ GTiffRasterBand::GTiffRasterBand( GTiffDataset *poDSIn, int nBandIn) :
 GTiffRasterBand::~GTiffRasterBand()
 {
     // So that any future DropReferenceVirtualMem() will not try to access the
-    // raster band object, but this would not conform the advertised contract.
-    if( aSetPSelf.size() != 0 )
+    // raster band object, but this would not conform to the advertised
+    // contract.
+    if( !aSetPSelf.empty() )
     {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                 "Virtual memory objects still exist at GTiffRasterBand destruction");
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Virtual memory objects still exist at GTiffRasterBand "
+                  "destruction" );
         std::set<GTiffRasterBand**>::iterator oIter = aSetPSelf.begin();
-        for(; oIter != aSetPSelf.end(); ++oIter )
+        for( ; oIter != aSetPSelf.end(); ++oIter )
             *(*oIter) = NULL;
     }
 }
@@ -1217,15 +1363,17 @@ class FetchBufferDirectIO CPL_FINAL
     size_t       nTempBufferSize;
 
 public:
-            FetchBufferDirectIO(VSILFILE* fpIn, GByte* pTempBufferIn, size_t nTempBufferSizeIn) :
-                    fp(fpIn),
-                    pTempBuffer(pTempBufferIn),
-                    nTempBufferSize(nTempBufferSizeIn) {}
-
-    const GByte* FetchBytes(vsi_l_offset nOffset,
-                            int nPixels, int nDTSize,
-                            bool bIsByteSwapped, bool bIsComplex,
-                            int nBlockId)
+            FetchBufferDirectIO( VSILFILE* fpIn,
+                                 GByte* pTempBufferIn,
+                                 size_t nTempBufferSizeIn ) :
+                fp(fpIn),
+                pTempBuffer(pTempBufferIn),
+                nTempBufferSize(nTempBufferSizeIn) {}
+
+    const GByte* FetchBytes( vsi_l_offset nOffset,
+                             int nPixels, int nDTSize,
+                             bool bIsByteSwapped, bool bIsComplex,
+                             int nBlockId )
     {
         if( !FetchBytes(pTempBuffer, nOffset, nPixels, nDTSize, bIsByteSwapped,
                         bIsComplex, nBlockId) )
@@ -1235,11 +1383,11 @@ public:
         return pTempBuffer;
     }
 
-    bool  FetchBytes(GByte* pabyDstBuffer,
+    bool FetchBytes( GByte* pabyDstBuffer,
                      vsi_l_offset nOffset,
                      int nPixels, int nDTSize,
                      bool bIsByteSwapped, bool bIsComplex,
-                     int nBlockId)
+                     int nBlockId )
     {
         vsi_l_offset nSeekForward = 0;
         if( nOffset <= VSIFTellL(fp) ||
@@ -1256,8 +1404,11 @@ public:
         {
             while( nSeekForward > 0 )
             {
-                size_t nToRead = (size_t) MIN( nTempBufferSize, nSeekForward );
-                if( VSIFReadL(pTempBuffer, nToRead, 1, fp) != 1 )
+                vsi_l_offset nToRead = nSeekForward;
+                if( nToRead > nTempBufferSize )
+                    nToRead = nTempBufferSize;
+                if( VSIFReadL(pTempBuffer, static_cast<size_t>(nToRead),
+                              1, fp) != 1 )
                 {
                     CPLError(CE_Failure, CPLE_FileIO,
                              "Cannot seek to block %d", nBlockId);
@@ -1269,14 +1420,15 @@ public:
         if( VSIFReadL(pabyDstBuffer, nPixels * nDTSize, 1, fp) != 1 )
         {
             CPLError(CE_Failure, CPLE_FileIO,
-                    "Missing data for block %d", nBlockId);
+                     "Missing data for block %d", nBlockId);
             return false;
         }
 
         if( bIsByteSwapped )
         {
             if( bIsComplex )
-                GDALSwapWords( pabyDstBuffer, nDTSize / 2, 2 * nPixels, nDTSize / 2);
+                GDALSwapWords( pabyDstBuffer, nDTSize / 2, 2 * nPixels,
+                               nDTSize / 2 );
             else
                 GDALSwapWords( pabyDstBuffer, nDTSize, nPixels, nDTSize);
         }
@@ -1290,20 +1442,20 @@ public:
 /*                           DirectIO()                                 */
 /************************************************************************/
 
-/* Reads directly bytes from the file using ReadMultiRange(), and by-pass */
-/* block reading. Restricted to simple TIFF configurations */
-/* (uncompressed data, standard data types). Particularly useful to extract */
-/* sub-windows of data on a large /vsicurl dataset). */
-/* Returns -1 if DirectIO() can't be supported on that file */
+// Reads directly bytes from the file using ReadMultiRange(), and by-pass
+// block reading. Restricted to simple TIFF configurations
+// (uncompressed data, standard data types). Particularly useful to extract
+// sub-windows of data on a large /vsicurl dataset).
+// Returns -1 if DirectIO() can't be supported on that file.
 
 int GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
-                                  int nXOff, int nYOff, int nXSize, int nYSize,
-                                  void * pData, int nBufXSize, int nBufYSize,
-                                  GDALDataType eBufType,
-                                  GSpacing nPixelSpace, GSpacing nLineSpace,
-                                  GDALRasterIOExtraArg* psExtraArg )
+                               int nXOff, int nYOff, int nXSize, int nYSize,
+                               void * pData, int nBufXSize, int nBufYSize,
+                               GDALDataType eBufType,
+                               GSpacing nPixelSpace, GSpacing nLineSpace,
+                               GDALRasterIOExtraArg* psExtraArg )
 {
-    const int nDTSizeBits = GDALGetDataTypeSize(eDataType);
+    const int nDTSizeBits = GDALGetDataTypeSizeBits(eDataType);
     if( !(eRWFlag == GF_Read &&
           poGDS->nCompression == COMPRESSION_NONE &&
           (poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK ||
@@ -1315,7 +1467,7 @@ int GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
         return -1;
     }
 
-    /* we only know how to deal with nearest neighbour in this optimized routine */
+    // Only know how to deal with nearest neighbour in this optimized routine.
     if( (nXSize != nBufXSize || nYSize != nBufYSize) &&
         psExtraArg != NULL &&
         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour )
@@ -1323,12 +1475,14 @@ int GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
         return -1;
     }
 
-    /*CPLDebug("GTiff", "DirectIO(%d,%d,%d,%d -> %dx%d)",
-             nXOff, nYOff, nXSize, nYSize,
-             nBufXSize, nBufYSize);*/
+#if DEBUG_VERBOSE
+    CPLDebug( "GTiff", "DirectIO(%d,%d,%d,%d -> %dx%d)",
+              nXOff, nYOff, nXSize, nYSize,
+              nBufXSize, nBufYSize );
+#endif
 
-    /* Make sure that TIFFTAG_STRIPOFFSETS is up-to-date */
-    if (poGDS->GetAccess() == GA_Update)
+    // Make sure that TIFFTAG_STRIPOFFSETS is up-to-date.
+    if( poGDS->GetAccess() == GA_Update )
     {
         poGDS->FlushCache();
         VSI_TIFFFlushBufferedWrite( TIFFClientdata( poGDS->hTIFF ) );
@@ -1340,10 +1494,14 @@ int GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
         {
             const int nDTSize = nDTSizeBits / 8;
             poGDS->m_nTempBufferForCommonDirectIOSize =
-                (size_t)(nBlockXSize * nBlockYSize * nDTSize *
-                ((poGDS->nPlanarConfig == PLANARCONFIG_CONTIG) ? poGDS->nBands : 1));
-
-            poGDS->m_pTempBufferForCommonDirectIO = (GByte*)VSI_MALLOC_VERBOSE(poGDS->m_nTempBufferForCommonDirectIOSize);
+                static_cast<size_t>(
+                    nBlockXSize * nBlockYSize * nDTSize *
+                    (poGDS->nPlanarConfig == PLANARCONFIG_CONTIG ?
+                     poGDS->nBands : 1) );
+
+            poGDS->m_pTempBufferForCommonDirectIO =
+                static_cast<GByte *>( VSI_MALLOC_VERBOSE(
+                    poGDS->m_nTempBufferForCommonDirectIOSize ) );
             if( poGDS->m_pTempBufferForCommonDirectIO == NULL )
                 return CE_Failure;
         }
@@ -1352,68 +1510,76 @@ int GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
         FetchBufferDirectIO oFetcher(fp, poGDS->m_pTempBufferForCommonDirectIO,
                                      poGDS->m_nTempBufferForCommonDirectIOSize);
 
-        return poGDS->CommonDirectIO( oFetcher,
-                            nXOff, nYOff, nXSize, nYSize,
-                            pData, nBufXSize, nBufYSize,
-                            eBufType,
-                            1, &nBand,
-                            nPixelSpace, nLineSpace,
-                            0 );
+        return poGDS->CommonDirectIO(
+            oFetcher,
+            nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize,
+            eBufType,
+            1, &nBand,
+            nPixelSpace, nLineSpace,
+            0 );
     }
 
-    /* Get strip offsets */
+    // Get strip offsets.
     toff_t *panTIFFOffsets = NULL;
-    if ( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
-         panTIFFOffsets == NULL )
+    if( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
+        panTIFFOffsets == NULL )
     {
         return CE_Failure;
     }
 
-    int nReqXSize = nXSize; /* sub-sampling or over-sampling can only be done at last stage */
-    int nReqYSize = MIN(nBufYSize, nYSize); /* we can do sub-sampling at the extraction stage */
-    void** ppData = (void**) VSI_MALLOC_VERBOSE(nReqYSize * sizeof(void*));
-    vsi_l_offset* panOffsets = (vsi_l_offset*)
-                            VSI_MALLOC_VERBOSE(nReqYSize * sizeof(vsi_l_offset));
-    size_t* panSizes = (size_t*) VSI_MALLOC_VERBOSE(nReqYSize * sizeof(size_t));
-    int nDTSize = GDALGetDataTypeSize(eDataType) / 8;
+    // Sub-sampling or over-sampling can only be done at last stage.
+    int nReqXSize = nXSize;
+    // Can do sub-sampling at the extraction stage.
+    const int nReqYSize = std::min(nBufYSize, nYSize);
+    // TODO(schwehr): Make ppData be GByte**.
+    void** ppData = static_cast<void **>(
+        VSI_MALLOC_VERBOSE(nReqYSize * sizeof(void*)) );
+    vsi_l_offset* panOffsets = static_cast<vsi_l_offset *>(
+        VSI_MALLOC_VERBOSE(nReqYSize * sizeof(vsi_l_offset)) );
+    size_t* panSizes = static_cast<size_t *>(
+        VSI_MALLOC_VERBOSE(nReqYSize * sizeof(size_t)) );
+    const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     void* pTmpBuffer = NULL;
     int eErr = CE_None;
-    int nContigBands = ((poGDS->nPlanarConfig == PLANARCONFIG_CONTIG) ? poGDS->nBands : 1);
+    int nContigBands =
+        poGDS->nPlanarConfig == PLANARCONFIG_CONTIG ? poGDS->nBands : 1;
     int nSrcPixelSize = nDTSize * nContigBands;
 
-    if (ppData == NULL || panOffsets == NULL || panSizes == NULL)
+    if( ppData == NULL || panOffsets == NULL || panSizes == NULL )
         eErr = CE_Failure;
-    else if (nXSize != nBufXSize || nYSize != nBufYSize ||
+    else if( nXSize != nBufXSize || nYSize != nBufYSize ||
              eBufType != eDataType ||
-             nPixelSpace != GDALGetDataTypeSize(eBufType) / 8 ||
-             nContigBands > 1)
+             nPixelSpace != GDALGetDataTypeSizeBytes(eBufType) ||
+             nContigBands > 1 )
     {
-        /* We need a temporary buffer for over-sampling/sub-sampling */
-        /* and/or data type conversion */
+        // We need a temporary buffer for over-sampling/sub-sampling
+        // and/or data type conversion.
         pTmpBuffer = VSI_MALLOC_VERBOSE(nReqXSize * nReqYSize * nSrcPixelSize);
-        if (pTmpBuffer == NULL)
+        if( pTmpBuffer == NULL )
             eErr = CE_Failure;
     }
 
-    /* Prepare data extraction */
-    const double dfSrcYInc = nYSize / (double) nBufYSize;
+    // Prepare data extraction.
+    const double dfSrcYInc = nYSize / static_cast<double>( nBufYSize );
 
-    int iLine;
-    for(iLine=0;eErr == CE_None && iLine<nReqYSize;iLine++)
+    for( int iLine = 0; eErr == CE_None && iLine < nReqYSize; ++iLine )
     {
-        if (pTmpBuffer == NULL)
-            ppData[iLine] = ((GByte*)pData) + iLine * nLineSpace;
+        if( pTmpBuffer == NULL )
+            ppData[iLine] = static_cast<GByte *>(pData) + iLine * nLineSpace;
         else
-            ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * nSrcPixelSize;
-        int nSrcLine;
-        if (nBufYSize < nYSize) /* Sub-sampling in y */
-            nSrcLine = nYOff + (int)((iLine + 0.5) * dfSrcYInc);
+            ppData[iLine] =
+                static_cast<GByte *>(pTmpBuffer) +
+                iLine * nReqXSize * nSrcPixelSize;
+        int nSrcLine = 0;
+        if( nBufYSize < nYSize )  // Sub-sampling in y.
+            nSrcLine = nYOff + static_cast<int>((iLine + 0.5) * dfSrcYInc);
         else
             nSrcLine = nYOff + iLine;
 
-        int nBlockXOff = 0;
-        int nBlockYOff = nSrcLine / nBlockYSize;
-        int nYOffsetInBlock = nSrcLine % nBlockYSize;
+        const int nBlockXOff = 0;
+        const int nBlockYOff = nSrcLine / nBlockYSize;
+        const int nYOffsetInBlock = nSrcLine % nBlockYSize;
         nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
         int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
         if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
@@ -1422,81 +1588,92 @@ int GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
         }
 
         panOffsets[iLine] = panTIFFOffsets[nBlockId];
-        if (panOffsets[iLine] == 0) /* We don't support sparse files */
+        if( panOffsets[iLine] == 0 )  // We don't support sparse files.
             eErr = -1;
 
-        panOffsets[iLine] += (nXOff + nYOffsetInBlock * nBlockXSize) * nSrcPixelSize;
+        panOffsets[iLine] +=
+            (nXOff + nYOffsetInBlock * nBlockXSize) * nSrcPixelSize;
         panSizes[iLine] = nReqXSize * nSrcPixelSize;
     }
 
-    /* Extract data from the file */
-    if (eErr == CE_None)
+    // Extract data from the file.
+    if( eErr == CE_None )
     {
         VSILFILE* fp = VSI_TIFFGetVSILFile(TIFFClientdata( poGDS->hTIFF ));
-        int nRet = VSIFReadMultiRangeL(nReqYSize, ppData, panOffsets, panSizes, fp);
-        if (nRet != 0)
+        const int nRet =
+            VSIFReadMultiRangeL( nReqYSize, ppData, panOffsets, panSizes, fp );
+        if( nRet != 0 )
             eErr = CE_Failure;
     }
 
-    /* Byte-swap if necessary */
-    if (eErr == CE_None && TIFFIsByteSwapped(poGDS->hTIFF))
+    // Byte-swap if necessary.
+    if( eErr == CE_None && TIFFIsByteSwapped(poGDS->hTIFF) )
     {
-        for(iLine=0;iLine<nReqYSize;iLine++)
+        for( int iLine = 0; iLine < nReqYSize; ++iLine )
         {
             if( GDALDataTypeIsComplex(eDataType) )
-                GDALSwapWords( ppData[iLine], nDTSize / 2, 2 * nReqXSize * nContigBands, nDTSize / 2);
+                GDALSwapWords( ppData[iLine], nDTSize / 2,
+                               2 * nReqXSize * nContigBands, nDTSize / 2 );
             else
-                GDALSwapWords( ppData[iLine], nDTSize, nReqXSize * nContigBands, nDTSize);
+                GDALSwapWords( ppData[iLine], nDTSize,
+                               nReqXSize * nContigBands, nDTSize );
         }
     }
 
-    /* Over-sampling/sub-sampling and/or data type conversion */
-    const double dfSrcXInc = nXSize / (double) nBufXSize;
-    if (eErr == CE_None && pTmpBuffer != NULL)
+    // Over-sampling/sub-sampling and/or data type conversion.
+    const double dfSrcXInc = nXSize / static_cast<double>( nBufXSize );
+    if( eErr == CE_None && pTmpBuffer != NULL )
     {
-        for(int iY=0;iY<nBufYSize;iY++)
+        for( int iY=0; iY < nBufYSize; ++iY )
         {
-            int iSrcY = (nBufYSize <= nYSize) ? iY :
-                            (int)((iY + 0.5) * dfSrcYInc);
+            const int iSrcY =
+                nBufYSize <= nYSize ?
+                iY : static_cast<int>((iY + 0.5) * dfSrcYInc);
 
-            GByte* pabySrcData = ((GByte*)ppData[iSrcY]) +
-                        ((nContigBands > 1) ? (nBand-1) : 0) * nDTSize;
-            GByte* pabyDstData = ((GByte*)pData) + iY * nLineSpace;
+            GByte* pabySrcData =
+                static_cast<GByte*>(ppData[iSrcY]) +
+                (nContigBands > 1 ? (nBand-1) : 0) * nDTSize;
+            GByte* pabyDstData =
+                static_cast<GByte *>(pData) + iY * nLineSpace;
             if( nBufXSize == nXSize )
             {
                 GDALCopyWords( pabySrcData,
-                                eDataType, nSrcPixelSize,
-                                pabyDstData,
-                                eBufType, static_cast<int>(nPixelSpace), nBufXSize);
+                               eDataType,
+                               nSrcPixelSize,
+                               pabyDstData,
+                               eBufType,
+                               static_cast<int>(nPixelSpace),
+                               nBufXSize );
             }
             else
             {
                 if( eDataType == GDT_Byte && eBufType == GDT_Byte )
                 {
                     double dfSrcX = 0.5 * dfSrcXInc;
-                    for(int iX=0;iX<nBufXSize;iX++, dfSrcX += dfSrcXInc)
+                    for( int iX = 0; iX < nBufXSize; ++iX, dfSrcX += dfSrcXInc )
                     {
-                        int iSrcX = (int)dfSrcX;
-                        pabyDstData[iX * nPixelSpace] = pabySrcData[iSrcX * nSrcPixelSize];
+                        const int iSrcX = static_cast<int>(dfSrcX);
+                        pabyDstData[iX * nPixelSpace] =
+                            pabySrcData[iSrcX * nSrcPixelSize];
                     }
                 }
                 else
                 {
                     double dfSrcX = 0.5 * dfSrcXInc;
-                    for(int iX=0;iX<nBufXSize;iX++, dfSrcX += dfSrcXInc)
+                    for( int iX = 0; iX < nBufXSize; ++iX, dfSrcX += dfSrcXInc )
                     {
-                        int iSrcX = (int)dfSrcX;
+                        const int iSrcX = static_cast<int>(dfSrcX);
                         GDALCopyWords( pabySrcData + iSrcX * nSrcPixelSize,
-                                    eDataType, 0,
-                                    pabyDstData + iX * nPixelSpace,
-                                    eBufType, 0, 1);
+                                       eDataType, 0,
+                                       pabyDstData + iX * nPixelSpace,
+                                       eBufType, 0, 1 );
                     }
                 }
             }
         }
     }
 
-    /* Cleanup */
+    // Cleanup.
     CPLFree(pTmpBuffer);
     CPLFree(ppData);
     CPLFree(panOffsets);
@@ -1510,40 +1687,54 @@ int GTiffRasterBand::DirectIO( GDALRWFlag eRWFlag,
 /************************************************************************/
 
 CPLVirtualMem* GTiffRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
-                                                  int *pnPixelSpace,
-                                                  GIntBig *pnLineSpace,
-                                                  char **papszOptions )
+                                                   int *pnPixelSpace,
+                                                   GIntBig *pnLineSpace,
+                                                   char **papszOptions )
 {
-    if( !CPLTestBool(CSLFetchNameValueDef(papszOptions, "USE_DEFAULT_IMPLEMENTATION", "NO")) )
+    const char* pszImpl = CSLFetchNameValueDef(
+            papszOptions, "USE_DEFAULT_IMPLEMENTATION", "AUTO");
+    if( EQUAL(pszImpl, "YES") || EQUAL(pszImpl, "ON") ||
+        EQUAL(pszImpl, "1") || EQUAL(pszImpl, "TRUE") )
     {
-        CPLVirtualMem *psRet
-            = GetVirtualMemAutoInternal(eRWFlag, pnPixelSpace, pnLineSpace,
-                                        papszOptions);
-        if( psRet != NULL )
-        {
-            CPLDebug("GTiff", "GetVirtualMemAuto(): Using memory file mapping");
-            return psRet;
-        }
+        return GDALRasterBand::GetVirtualMemAuto( eRWFlag, pnPixelSpace,
+                                                  pnLineSpace, papszOptions );
+    }
+
+    CPLVirtualMem *psRet =
+        GetVirtualMemAutoInternal( eRWFlag, pnPixelSpace, pnLineSpace,
+                                   papszOptions );
+    if( psRet != NULL )
+    {
+        CPLDebug("GTiff", "GetVirtualMemAuto(): Using memory file mapping");
+        return psRet;
+    }
+
+    if( EQUAL(pszImpl, "NO") || EQUAL(pszImpl, "OFF") ||
+        EQUAL(pszImpl, "0") || EQUAL(pszImpl, "FALSE") )
+    {
+        return NULL;
     }
 
     CPLDebug("GTiff", "GetVirtualMemAuto(): Defaulting to base implementation");
-    return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
-                                             pnLineSpace, papszOptions);
+    return GDALRasterBand::GetVirtualMemAuto( eRWFlag, pnPixelSpace,
+                                              pnLineSpace, papszOptions );
 }
 
 /************************************************************************/
 /*                           GetHistogram()                             */
 /************************************************************************/
 
-CPLErr  GTiffRasterBand::GetHistogram( double dfMin, double dfMax,
-                          int nBuckets, GUIntBig * panHistogram,
-                          int bIncludeOutOfRange, int bApproxOK,
-                          GDALProgressFunc pfnProgress, void *pProgressData )
+CPLErr GTiffRasterBand::GetHistogram(
+    double dfMin, double dfMax,
+    int nBuckets, GUIntBig * panHistogram,
+    int bIncludeOutOfRange, int bApproxOK,
+    GDALProgressFunc pfnProgress, void *pProgressData )
 {
     poGDS->LoadGeoreferencingAndPamIfNeeded();
-    return GDALPamRasterBand::GetHistogram(dfMin, dfMax, nBuckets, panHistogram,
-                                           bIncludeOutOfRange, bApproxOK,
-                                           pfnProgress, pProgressData);
+    return GDALPamRasterBand::GetHistogram( dfMin, dfMax,
+                                            nBuckets, panHistogram,
+                                            bIncludeOutOfRange, bApproxOK,
+                                            pfnProgress, pProgressData );
 }
 
 /************************************************************************/
@@ -1558,24 +1749,24 @@ CPLErr GTiffRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                              void *pProgressData )
 {
     poGDS->LoadGeoreferencingAndPamIfNeeded();
-    return GDALPamRasterBand::GetDefaultHistogram(pdfMin, pdfMax,
-                                                  pnBuckets, ppanHistogram,
-                                                  bForce,
-                                                  pfnProgress, pProgressData);
+    return GDALPamRasterBand::GetDefaultHistogram( pdfMin, pdfMax,
+                                                   pnBuckets, ppanHistogram,
+                                                   bForce,
+                                                   pfnProgress, pProgressData );
 }
 
 /************************************************************************/
 /*                     DropReferenceVirtualMem()                        */
 /************************************************************************/
 
-void GTiffRasterBand::DropReferenceVirtualMem(void* pUserData)
+void GTiffRasterBand::DropReferenceVirtualMem( void* pUserData )
 {
-    /* This function may also be called when the dataset and rasterband */
-    /* objects have been destroyed */
-    /* If they are still alive, it updates the reference counter of the */
-    /* base mapping to invalidate the pointer to it if needed */
+    // This function may also be called when the dataset and rasterband
+    // objects have been destroyed.
+    // If they are still alive, it updates the reference counter of the
+    // base mapping to invalidate the pointer to it if needed.
 
-    GTiffRasterBand** ppoSelf = (GTiffRasterBand**) pUserData;
+    GTiffRasterBand** ppoSelf = static_cast<GTiffRasterBand **>( pUserData );
     GTiffRasterBand* poSelf = *ppoSelf;
 
     if( poSelf != NULL )
@@ -1598,39 +1789,43 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
                                                            GIntBig *pnLineSpace,
                                                            char **papszOptions )
 {
-    int nLineSize = nBlockXSize * (GDALGetDataTypeSize(eDataType) / 8);
+    int nLineSize = nBlockXSize * GDALGetDataTypeSizeBytes(eDataType);
     if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
         nLineSize *= poGDS->nBands;
 
     if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
     {
-        /* In case of a pixel interleaved file, we save virtual memory space */
-        /* by reusing a base mapping that embraces the whole imagery */
+        // In case of a pixel interleaved file, we save virtual memory space
+        // by reusing a base mapping that embraces the whole imagery.
         if( poGDS->pBaseMapping != NULL )
         {
-            /* Offset between the base mapping and the requested mapping */
-            vsi_l_offset nOffset = (vsi_l_offset)(nBand - 1) * GDALGetDataTypeSize(eDataType) / 8;
+            // Offset between the base mapping and the requested mapping.
+            vsi_l_offset nOffset =
+                static_cast<vsi_l_offset>(nBand - 1) *
+                GDALGetDataTypeSizeBytes(eDataType);
 
-            GTiffRasterBand** ppoSelf = (GTiffRasterBand** )CPLCalloc(1, sizeof(GTiffRasterBand*));
+            GTiffRasterBand** ppoSelf =
+                static_cast<GTiffRasterBand** >(
+                    CPLCalloc(1, sizeof(GTiffRasterBand*)) );
             *ppoSelf = this;
 
             CPLVirtualMem* pVMem = CPLVirtualMemDerivedNew(
-                    poGDS->pBaseMapping,
-                    nOffset,
-                    CPLVirtualMemGetSize(poGDS->pBaseMapping) - nOffset,
-                    GTiffRasterBand::DropReferenceVirtualMem,
-                    ppoSelf);
+                poGDS->pBaseMapping,
+                nOffset,
+                CPLVirtualMemGetSize(poGDS->pBaseMapping) - nOffset,
+                GTiffRasterBand::DropReferenceVirtualMem,
+                ppoSelf);
             if( pVMem == NULL )
             {
                 CPLFree(ppoSelf);
                 return NULL;
             }
 
-            /* Mechanism used so that the memory mapping object can be */
-            /* destroyed after the raster band */
+            // Mechanism used so that the memory mapping object can be
+            // destroyed after the raster band.
             aSetPSelf.insert(ppoSelf);
-            poGDS->nRefBaseMapping ++;
-            *pnPixelSpace = GDALGetDataTypeSize(eDataType) / 8;
+            ++poGDS->nRefBaseMapping;
+            *pnPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
             if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
                 *pnPixelSpace *= poGDS->nBands;
             *pnLineSpace = nLineSize;
@@ -1638,66 +1833,67 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
         }
     }
 
-    if( !poGDS->SetDirectory() ) /* very important to make hTIFF up-to-date */
+    if( !poGDS->SetDirectory() )  // Very important to make hTIFF up-to-date.
         return NULL;
     VSILFILE* fp = VSI_TIFFGetVSILFile(TIFFClientdata( poGDS->hTIFF ));
 
-    vsi_l_offset nLength = (vsi_l_offset)nRasterYSize * nLineSize;
+    vsi_l_offset nLength = static_cast<vsi_l_offset>(nRasterYSize) * nLineSize;
 
     if( !(CPLIsVirtualMemFileMapAvailable() &&
           VSIFGetNativeFileDescriptorL(fp) != NULL &&
 #if SIZEOF_VOIDP == 4
-          nLength == (size_t)nLength &&
+          nLength == static_cast<size_t>(nLength) &&
 #endif
           poGDS->nCompression == COMPRESSION_NONE &&
           (poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK ||
            poGDS->nPhotometric == PHOTOMETRIC_RGB ||
            poGDS->nPhotometric == PHOTOMETRIC_PALETTE) &&
-          poGDS->nBitsPerSample == GDALGetDataTypeSize(eDataType) &&
+          poGDS->nBitsPerSample == GDALGetDataTypeSizeBits(eDataType) &&
           !TIFFIsTiled( poGDS->hTIFF ) && !TIFFIsByteSwapped(poGDS->hTIFF)) )
     {
         return NULL;
     }
 
-    /* Make sure that TIFFTAG_STRIPOFFSETS is up-to-date */
-    if (poGDS->GetAccess() == GA_Update)
+    // Make sure that TIFFTAG_STRIPOFFSETS is up-to-date.
+    if( poGDS->GetAccess() == GA_Update )
     {
         poGDS->FlushCache();
         VSI_TIFFFlushBufferedWrite( TIFFClientdata( poGDS->hTIFF ) );
     }
 
-    /* Get strip offsets */
+    // Get strip offsets.
     toff_t *panTIFFOffsets = NULL;
-    if ( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
-         panTIFFOffsets == NULL )
+    if( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
+        panTIFFOffsets == NULL )
     {
         return NULL;
     }
 
     int nBlockSize =
-        nBlockXSize * nBlockYSize * GDALGetDataTypeSize(eDataType) / 8;
+        nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType);
     if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
         nBlockSize *= poGDS->nBands;
 
     int nBlocks = poGDS->nBlocksPerBand;
     if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
         nBlocks *= poGDS->nBands;
-    int i;
-    for(i = 0; i < nBlocks; i ++)
+    int i = 0;  // Used after for.
+    for( ; i < nBlocks; ++i )
     {
         if( panTIFFOffsets[i] != 0 )
             break;
     }
     if( i == nBlocks )
     {
-        /* All zeroes */
+        // All zeroes.
         if( poGDS->eAccess == GA_Update )
         {
-            /* Initialize the file with empty blocks so that the file has */
-            /* the appropriate size */
+            // Initialize the file with empty blocks so that the file has
+            // the appropriate size.
 
             toff_t* panByteCounts = NULL;
-            if( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts ) ||
+            if( !TIFFGetField( poGDS->hTIFF, TIFFTAG_STRIPBYTECOUNTS,
+                               &panByteCounts ) ||
                 panByteCounts == NULL )
             {
                 return NULL;
@@ -1706,13 +1902,17 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
                 return NULL;
             vsi_l_offset nBaseOffset = VSIFTellL(fp);
 
-            /* Just write one tile with libtiff to put it in appropriate state */
-            GByte* pabyData = (GByte*)VSI_CALLOC_VERBOSE(1, nBlockSize);
+            // Just write one tile with libtiff to put it in appropriate state.
+            GByte* pabyData =
+                static_cast<GByte*>(VSI_CALLOC_VERBOSE(1, nBlockSize));
             if( pabyData == NULL )
             {
                 return NULL;
             }
-            int ret = static_cast<int>(TIFFWriteEncodedStrip(poGDS->hTIFF, 0, pabyData, nBlockSize));
+            int ret =
+                static_cast<int>(
+                    TIFFWriteEncodedStrip( poGDS->hTIFF, 0, pabyData,
+                                           nBlockSize ) );
             VSI_TIFFFlushBufferedWrite( TIFFClientdata( poGDS->hTIFF ) );
             VSIFree(pabyData);
             if( ret != nBlockSize )
@@ -1720,27 +1920,24 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
                 return NULL;
             }
             CPLAssert(panTIFFOffsets[0] == nBaseOffset);
-            CPLAssert(panByteCounts[0] == (toff_t)nBlockSize);
+            CPLAssert(panByteCounts[0] == static_cast<toff_t>(nBlockSize));
 
-            /* Now simulate the writing of other blocks */
-            vsi_l_offset nDataSize = (vsi_l_offset)nBlockSize * nBlocks;
-            if( VSIFSeekL(fp, nBaseOffset + nDataSize - 1, SEEK_SET) != 0 )
-                return NULL;
-            char ch = 0;
-            if( VSIFWriteL(&ch, 1, 1, fp) != 1 )
-            {
+            // Now simulate the writing of other blocks.
+            const vsi_l_offset nDataSize =
+                static_cast<vsi_l_offset>(nBlockSize) * nBlocks;
+            if( VSIFTruncateL(fp, nBaseOffset + nDataSize) != 0 )
                 return NULL;
-            }
 
-            for(i = 1; i < nBlocks; i ++)
+            for( i = 1; i < nBlocks; ++i)
             {
-                panTIFFOffsets[i] = nBaseOffset + i * (toff_t)nBlockSize;
+                panTIFFOffsets[i] =
+                    nBaseOffset + i * static_cast<toff_t>(nBlockSize);
                 panByteCounts[i] = nBlockSize;
             }
         }
         else
         {
-            CPLDebug("GTiff", "Sparse files not supported in file mapping");
+            CPLDebug( "GTiff", "Sparse files not supported in file mapping" );
             return NULL;
         }
     }
@@ -1748,11 +1945,12 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
     GIntBig nBlockSpacing = 0;
     bool bCompatibleSpacing = true;
     toff_t nPrevOffset = 0;
-    for(i = 0; i < poGDS->nBlocksPerBand; i ++)
+    for( i = 0; i < poGDS->nBlocksPerBand; ++i )
     {
-        toff_t nCurOffset;
+        toff_t nCurOffset = 0;
         if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
-            nCurOffset = panTIFFOffsets[poGDS->nBlocksPerBand * (nBand - 1) + i];
+            nCurOffset =
+                panTIFFOffsets[poGDS->nBlocksPerBand * (nBand - 1) + i];
         else
             nCurOffset = panTIFFOffsets[i];
         if( nCurOffset == 0 )
@@ -1762,10 +1960,11 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
         }
         if( i > 0 )
         {
-            GIntBig nCurSpacing = nCurOffset - nPrevOffset;
+            const GIntBig nCurSpacing = nCurOffset - nPrevOffset;
             if( i == 1 )
             {
-                if( nCurSpacing != (GIntBig)nBlockYSize * nLineSize )
+                if( nCurSpacing !=
+                    static_cast<GIntBig>(nBlockYSize) * nLineSize )
                 {
                     bCompatibleSpacing = false;
                     break;
@@ -1785,48 +1984,47 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
     {
         return NULL;
     }
+
+    vsi_l_offset nOffset = 0;
+    if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+    {
+        CPLAssert( poGDS->pBaseMapping == NULL );
+        nOffset = panTIFFOffsets[0];
+    }
     else
     {
-        vsi_l_offset nOffset;
-        if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
-        {
-            CPLAssert( poGDS->pBaseMapping == NULL );
-            nOffset = panTIFFOffsets[0];
-        }
-        else
-            nOffset = panTIFFOffsets[poGDS->nBlocksPerBand * (nBand - 1)];
-        CPLVirtualMem* pVMem = CPLVirtualMemFileMapNew(
-            fp, nOffset, nLength,
-            (eRWFlag == GF_Write) ? VIRTUALMEM_READWRITE : VIRTUALMEM_READONLY,
-            NULL, NULL);
+        nOffset = panTIFFOffsets[poGDS->nBlocksPerBand * (nBand - 1)];
+    }
+    CPLVirtualMem* pVMem = CPLVirtualMemFileMapNew(
+        fp, nOffset, nLength,
+        eRWFlag == GF_Write ? VIRTUALMEM_READWRITE : VIRTUALMEM_READONLY,
+        NULL, NULL);
+    if( pVMem == NULL )
+    {
+        return NULL;
+    }
+
+    if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+    {
+        // TODO(schwehr): Revisit this block.
+        poGDS->pBaseMapping = pVMem;
+        pVMem = GetVirtualMemAutoInternal( eRWFlag,
+                                           pnPixelSpace,
+                                           pnLineSpace,
+                                           papszOptions );
+        // Drop ref on base mapping.
+        CPLVirtualMemFree(poGDS->pBaseMapping);
         if( pVMem == NULL )
-        {
-            return NULL;
-        }
-        else
-        {
-            if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
-            {
-                poGDS->pBaseMapping = pVMem;
-                pVMem = GetVirtualMemAutoInternal( eRWFlag,
-                                                   pnPixelSpace,
-                                                   pnLineSpace,
-                                                   papszOptions );
-                /* drop ref on base mapping */
-                CPLVirtualMemFree(poGDS->pBaseMapping);
-                if( pVMem == NULL )
-                    poGDS->pBaseMapping = NULL;
-            }
-            else
-            {
-                *pnPixelSpace = GDALGetDataTypeSize(eDataType) / 8;
-                if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
-                    *pnPixelSpace *= poGDS->nBands;
-                *pnLineSpace = nLineSize;
-            }
-            return pVMem;
-        }
+            poGDS->pBaseMapping = NULL;
+    }
+    else
+    {
+        *pnPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
+        if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
+            *pnPixelSpace *= poGDS->nBands;
+        *pnLineSpace = nLineSize;
     }
+    return pVMem;
 }
 
 /************************************************************************/
@@ -1834,60 +2032,64 @@ CPLVirtualMem* GTiffRasterBand::GetVirtualMemAutoInternal( GDALRWFlag eRWFlag,
 /************************************************************************/
 
 CPLErr GTiffDataset::IRasterIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg)
+                                int nXOff, int nYOff, int nXSize, int nYSize,
+                                void * pData, int nBufXSize, int nBufYSize,
+                                GDALDataType eBufType,
+                                int nBandCount, int *panBandMap,
+                                GSpacing nPixelSpace, GSpacing nLineSpace,
+                                GSpacing nBandSpace,
+                                GDALRasterIOExtraArg* psExtraArg )
 
 {
-    CPLErr eErr;
-    /* Try to pass the request to the most appropriate overview dataset */
+    // Try to pass the request to the most appropriate overview dataset.
     if( nBufXSize < nXSize && nBufYSize < nYSize )
     {
-        int bTried;
-        nJPEGOverviewVisibilityFlag ++;
-        eErr = TryOverviewRasterIO( eRWFlag,
-                                    nXOff, nYOff, nXSize, nYSize,
-                                    pData, nBufXSize, nBufYSize,
-                                    eBufType,
-                                    nBandCount, panBandMap,
-                                    nPixelSpace, nLineSpace,
-                                    nBandSpace,
-                                    psExtraArg,
-                                    &bTried );
-        nJPEGOverviewVisibilityFlag --;
+        int bTried = FALSE;
+        ++nJPEGOverviewVisibilityCounter;
+        const CPLErr eErr =
+            TryOverviewRasterIO( eRWFlag,
+                                 nXOff, nYOff, nXSize, nYSize,
+                                 pData, nBufXSize, nBufYSize,
+                                 eBufType,
+                                 nBandCount, panBandMap,
+                                 nPixelSpace, nLineSpace,
+                                 nBandSpace,
+                                 psExtraArg,
+                                 &bTried );
+        --nJPEGOverviewVisibilityCounter;
         if( bTried )
             return eErr;
     }
 
     if( eVirtualMemIOUsage != VIRTUAL_MEM_IO_NO )
     {
-        int nErr = VirtualMemIO(
-                eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                pData, nBufXSize, nBufYSize, eBufType,
-                nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
-        if (nErr >= 0)
-            return (CPLErr)nErr;
-    }
-    if (bDirectIO)
-    {
-        int nErr = DirectIO(
-                eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                pData, nBufXSize, nBufYSize, eBufType,
-                nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
-        if (nErr >= 0)
-            return (CPLErr)nErr;
-    }
-
-    nJPEGOverviewVisibilityFlag ++;
-    eErr =  GDALPamDataset::IRasterIO(
-                eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                pData, nBufXSize, nBufYSize, eBufType,
-                nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
-    nJPEGOverviewVisibilityFlag --;
+        const int nErr = VirtualMemIO(
+            eRWFlag, nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize, eBufType,
+            nBandCount, panBandMap, nPixelSpace, nLineSpace,
+            nBandSpace, psExtraArg );
+        if( nErr >= 0 )
+            return static_cast<CPLErr>(nErr);
+    }
+    if( bDirectIO )
+    {
+        const int nErr = DirectIO(
+            eRWFlag, nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize, eBufType,
+            nBandCount, panBandMap, nPixelSpace, nLineSpace,
+            nBandSpace, psExtraArg );
+        if( nErr >= 0 )
+            return static_cast<CPLErr>(nErr);
+    }
+
+    ++nJPEGOverviewVisibilityCounter;
+    const CPLErr eErr =
+        GDALPamDataset::IRasterIO(
+            eRWFlag, nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize, eBufType,
+            nBandCount, panBandMap, nPixelSpace, nLineSpace,
+            nBandSpace, psExtraArg);
+    nJPEGOverviewVisibilityCounter--;
     return eErr;
 }
 
@@ -1902,22 +2104,22 @@ class FetchBufferVirtualMemIO CPL_FINAL
     GByte       *pTempBuffer;
 
 public:
-            FetchBufferVirtualMemIO(const GByte* pabySrcDataIn,
-                                    size_t nMappingSizeIn,
-                                    GByte* pTempBufferIn) :
-                    pabySrcData(pabySrcDataIn),
-                    nMappingSize(nMappingSizeIn),
-                    pTempBuffer(pTempBufferIn) {}
-
-    const GByte* FetchBytes(vsi_l_offset nOffset,
-                            int nPixels, int nDTSize,
-                            bool bIsByteSwapped, bool bIsComplex,
-                            int nBlockId)
+            FetchBufferVirtualMemIO( const GByte* pabySrcDataIn,
+                                     size_t nMappingSizeIn,
+                                     GByte* pTempBufferIn ) :
+                pabySrcData(pabySrcDataIn),
+                nMappingSize(nMappingSizeIn),
+                pTempBuffer(pTempBufferIn) {}
+
+    const GByte* FetchBytes( vsi_l_offset nOffset,
+                             int nPixels, int nDTSize,
+                             bool bIsByteSwapped, bool bIsComplex,
+                             int nBlockId )
     {
         if( nOffset + nPixels * nDTSize > nMappingSize )
         {
             CPLError(CE_Failure, CPLE_FileIO,
-                    "Missing data for block %d", nBlockId);
+                     "Missing data for block %d", nBlockId);
             return NULL;
         }
         if( !bIsByteSwapped )
@@ -1930,23 +2132,24 @@ public:
         return pTempBuffer;
     }
 
-    bool  FetchBytes(GByte* pabyDstBuffer,
+    bool FetchBytes( GByte* pabyDstBuffer,
                      vsi_l_offset nOffset,
                      int nPixels, int nDTSize,
                      bool bIsByteSwapped, bool bIsComplex,
-                     int nBlockId)
+                     int nBlockId )
     {
         if( nOffset + nPixels * nDTSize > nMappingSize )
         {
             CPLError(CE_Failure, CPLE_FileIO,
-                    "Missing data for block %d", nBlockId);
+                     "Missing data for block %d", nBlockId);
             return false;
         }
         memcpy(pabyDstBuffer, pabySrcData + nOffset, nPixels * nDTSize);
         if( bIsByteSwapped )
         {
             if( bIsComplex )
-                GDALSwapWords( pabyDstBuffer, nDTSize / 2, 2 * nPixels, nDTSize / 2);
+                GDALSwapWords( pabyDstBuffer, nDTSize / 2, 2 * nPixels,
+                               nDTSize / 2);
             else
                 GDALSwapWords( pabyDstBuffer, nDTSize, nPixels, nDTSize);
         }
@@ -1961,18 +2164,18 @@ public:
 /************************************************************************/
 
 int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg )
+                                int nXOff, int nYOff, int nXSize, int nYSize,
+                                void * pData, int nBufXSize, int nBufYSize,
+                                GDALDataType eBufType,
+                                int nBandCount, int *panBandMap,
+                                GSpacing nPixelSpace, GSpacing nLineSpace,
+                                GSpacing nBandSpace,
+                                GDALRasterIOExtraArg* psExtraArg )
 {
     if( eAccess == GA_Update || eRWFlag == GF_Write || bStreamingIn )
         return -1;
 
-    /* we only know how to deal with nearest neighbour in this optimized routine */
+    // Only know how to deal with nearest neighbour in this optimized routine.
     if( (nXSize != nBufXSize || nYSize != nBufYSize) &&
         psExtraArg != NULL &&
         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour )
@@ -1984,7 +2187,7 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
         return CE_Failure;
 
     const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
-    const int nDTSizeBits = GDALGetDataTypeSize(eDataType);
+    const int nDTSizeBits = GDALGetDataTypeSizeBits(eDataType);
     if( !(nCompression == COMPRESSION_NONE &&
         (nPhotometric == PHOTOMETRIC_MINISBLACK ||
         nPhotometric == PHOTOMETRIC_RGB ||
@@ -2000,8 +2203,9 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
     if( STARTS_WITH(GetDescription(), "/vsimem/") )
     {
         vsi_l_offset nDataLength = 0;
-        pabySrcData = VSIGetMemFileBuffer(GetDescription(), &nDataLength, FALSE);
-        nMappingSize = (size_t)nDataLength;
+        pabySrcData =
+            VSIGetMemFileBuffer(GetDescription(), &nDataLength, FALSE);
+        nMappingSize = static_cast<size_t>(nDataLength);
         if( pabySrcData == NULL )
             return -1;
     }
@@ -2019,8 +2223,8 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
             eVirtualMemIOUsage = VIRTUAL_MEM_IO_NO;
             return -1;
         }
-        vsi_l_offset nLength = VSIFTellL(fp);
-        if( (size_t)nLength != nLength )
+        const vsi_l_offset nLength = VSIFTellL(fp);
+        if( static_cast<size_t>(nLength) != nLength )
         {
             eVirtualMemIOUsage = VIRTUAL_MEM_IO_NO;
             return -1;
@@ -2028,9 +2232,10 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
         if( eVirtualMemIOUsage == VIRTUAL_MEM_IO_IF_ENOUGH_RAM )
         {
             GIntBig nRAM = CPLGetUsablePhysicalRAM();
-            if( (GIntBig)nLength > nRAM )
+            if( static_cast<GIntBig>(nLength) > nRAM )
             {
-                CPLDebug("GTiff", "Not enough RAM to map whole file into memory.");
+                CPLDebug( "GTiff",
+                          "Not enough RAM to map whole file into memory." );
                 eVirtualMemIOUsage = VIRTUAL_MEM_IO_NO;
                 return -1;
             }
@@ -2051,22 +2256,27 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
         CPLDebug("GTiff", "Using VirtualMemIO");
 #endif
         nMappingSize = CPLVirtualMemGetSize(psVirtualMemIOMapping);
-        pabySrcData = (GByte*)CPLVirtualMemGetAddr(psVirtualMemIOMapping);
+        pabySrcData = static_cast<GByte *>(
+            CPLVirtualMemGetAddr(psVirtualMemIOMapping) );
     }
 
     if( TIFFIsByteSwapped(hTIFF) && m_pTempBufferForCommonDirectIO == NULL )
     {
         const int nDTSize = nDTSizeBits / 8;
         m_nTempBufferForCommonDirectIOSize =
-            (size_t)(nBlockXSize * nDTSize * ((nPlanarConfig == PLANARCONFIG_CONTIG) ? nBands : 1));
+            static_cast<size_t>(nBlockXSize * nDTSize *
+                (nPlanarConfig == PLANARCONFIG_CONTIG ? nBands : 1));
         if( TIFFIsTiled(hTIFF) )
             m_nTempBufferForCommonDirectIOSize *= nBlockYSize;
 
-        m_pTempBufferForCommonDirectIO = (GByte*)VSI_MALLOC_VERBOSE(m_nTempBufferForCommonDirectIOSize);
+        m_pTempBufferForCommonDirectIO =
+            static_cast<GByte *>(
+                VSI_MALLOC_VERBOSE(m_nTempBufferForCommonDirectIOSize) );
         if( m_pTempBufferForCommonDirectIO == NULL )
             return CE_Failure;
     }
-    FetchBufferVirtualMemIO oFetcher(pabySrcData, nMappingSize, m_pTempBufferForCommonDirectIO);
+    FetchBufferVirtualMemIO oFetcher( pabySrcData, nMappingSize,
+                                      m_pTempBufferForCommonDirectIO );
 
     return CommonDirectIO( oFetcher,
                            nXOff, nYOff, nXSize, nYSize,
@@ -2082,9 +2292,9 @@ int GTiffDataset::VirtualMemIO( GDALRWFlag eRWFlag,
 /************************************************************************/
 
 static inline void CopyContigByteMultiBand(
-                            const GByte* CPL_RESTRICT pabySrc, int nSrcStride,
-                            GByte* CPL_RESTRICT pabyDest, int nDestStride,
-                            int nIters, int nBandCount)
+    const GByte* CPL_RESTRICT pabySrc, int nSrcStride,
+    GByte* CPL_RESTRICT pabyDest, int nDestStride,
+    int nIters, int nBandCount )
 {
     if( nBandCount == 3 )
     {
@@ -2145,7 +2355,7 @@ static inline void CopyContigByteMultiBand(
     {
         while( nIters-- > 0 )
         {
-            for(int iBand=0;iBand<nBandCount;iBand++)
+            for( int iBand = 0; iBand < nBandCount; ++iBand )
                 pabyDest[iBand] = pabySrc[iBand];
             pabySrc += nSrcStride;
             pabyDest += nDestStride;
@@ -2157,43 +2367,47 @@ static inline void CopyContigByteMultiBand(
 /*                         CommonDirectIO()                             */
 /************************************************************************/
 
-//#define DEBUG_REACHED_VIRTUAL_MEM_IO
+// #define DEBUG_REACHED_VIRTUAL_MEM_IO
 #ifdef DEBUG_REACHED_VIRTUAL_MEM_IO
 static int anReachedVirtualMemIO[52] = { 0 };
-#define REACHED(x)  anReachedVirtualMemIO[x] = 1
+#define REACHED(x) anReachedVirtualMemIO[x] = 1
 #else
 #define REACHED(x)
 #endif
 
 template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
-                               FetchBuffer& oFetcher,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace )
+    FetchBuffer& oFetcher,
+    int nXOff, int nYOff, int nXSize, int nYSize,
+    void * pData, int nBufXSize, int nBufYSize,
+    GDALDataType eBufType,
+    int nBandCount, int *panBandMap,
+    GSpacing nPixelSpace, GSpacing nLineSpace,
+    GSpacing nBandSpace )
 {
     const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
-    const int nDTSize = GDALGetDataTypeSize(eDataType) / 8;
+    const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     const bool bIsComplex = CPL_TO_BOOL(GDALDataTypeIsComplex(eDataType));
-    const int nBufDTSize = GDALGetDataTypeSize(eBufType) / 8;
+    const int nBufDTSize = GDALGetDataTypeSizeBytes(eBufType);
 
-    /* Get strip offsets */
+    // Get strip offsets.
     toff_t *panOffsets = NULL;
-    if ( !TIFFGetField( hTIFF, (TIFFIsTiled( hTIFF )) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, &panOffsets ) ||
-         panOffsets == NULL )
+    if( !TIFFGetField( hTIFF, (TIFFIsTiled( hTIFF )) ?
+                       TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS,
+                       &panOffsets ) ||
+        panOffsets == NULL )
     {
         return CE_Failure;
     }
 
     bool bUseContigImplementation =
-        ( nPlanarConfig == PLANARCONFIG_CONTIG ) && (nBandCount > 1) && (nBandSpace == nBufDTSize);
+        nPlanarConfig == PLANARCONFIG_CONTIG &&
+        nBandCount > 1 &&
+        nBandSpace == nBufDTSize;
     if( bUseContigImplementation )
     {
-        for(int iBand = 0; iBand < nBandCount; iBand ++ )
+        for( int iBand = 0; iBand < nBandCount; ++iBand )
         {
-            int nBand = panBandMap[iBand];
+            const int nBand = panBandMap[iBand];
             if( nBand != iBand + 1 )
             {
                 bUseContigImplementation = false;
@@ -2202,7 +2416,8 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
         }
     }
 
-    const int nBandsPerBlock = ( nPlanarConfig == PLANARCONFIG_SEPARATE ) ? 1 : nBands;
+    const int nBandsPerBlock =
+        nPlanarConfig == PLANARCONFIG_SEPARATE ? 1 : nBands;
     const int nBandsPerBlockDTSize = nBandsPerBlock * nDTSize;
     const int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
     const bool bNoTypeChange = (eDataType == eBufType);
@@ -2211,28 +2426,30 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
     const bool bByteOnly = (bNoTypeChange && nDTSize == 1 );
     const bool bByteNoXResampling = ( bByteOnly && bNoXResamplingNoTypeChange );
     const bool bIsByteSwapped = CPL_TO_BOOL(TIFFIsByteSwapped(hTIFF));
-    const double dfSrcXInc = nXSize / (double) nBufXSize;
-    const double dfSrcYInc = nYSize / (double) nBufYSize;
+    const double dfSrcXInc = nXSize / static_cast<double>( nBufXSize );
+    const double dfSrcYInc = nYSize / static_cast<double>( nBufYSize );
 
-    int bNoDataSetIn;
+    int bNoDataSetIn = FALSE;
     double dfNoData = GetRasterBand(1)->GetNoDataValue( &bNoDataSetIn );
     GByte abyNoData = 0;
     if( !bNoDataSetIn )
         dfNoData = 0;
     else if( dfNoData >= 0 && dfNoData <= 255 )
-        abyNoData = (GByte) (dfNoData + 0.5);
+        abyNoData = static_cast<GByte>(dfNoData + 0.5);
 
     if( FetchBuffer::bMinimizeIO &&
              TIFFIsTiled( hTIFF ) && bNoXResampling && (nYSize == nBufYSize ) &&
              nPlanarConfig == PLANARCONFIG_CONTIG && nBandCount > 1 )
     {
-        GByte* pabyData = (GByte*)pData;
-        for(int y=0;y<nBufYSize;)
+        GByte* pabyData = static_cast<GByte *>(pData);
+        for( int y = 0; y < nBufYSize; )
         {
             const int nSrcLine = nYOff + y;
             const int nBlockYOff = nSrcLine / nBlockYSize;
             const int nYOffsetInBlock = nSrcLine % nBlockYSize;
-            const int nUsedBlockHeight = MIN(nBufYSize - y, (int)nBlockYSize - nYOffsetInBlock);
+            const int nUsedBlockHeight =
+                std::min( nBufYSize - y,
+                          nBlockYSize - nYOffsetInBlock );
 
             int nBlockXOff = nXOff / nBlockXSize;
             int nXOffsetInBlock = nXOff % nBlockXSize;
@@ -2242,21 +2459,27 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
             while( x < nBufXSize )
             {
                 const toff_t nCurOffset = panOffsets[nBlockId];
-                const int nUsedBlockWidth = MIN((int)nBlockXSize - nXOffsetInBlock, nBufXSize - x);
+                const int nUsedBlockWidth =
+                    std::min( nBlockXSize - nXOffsetInBlock,
+                              nBufXSize - x );
 
                 if( nCurOffset == 0 )
                 {
                     REACHED(30);
-                    for( int k=0;k<nUsedBlockHeight;k++)
+                    for( int k = 0; k < nUsedBlockHeight; ++k )
                     {
-                        GByte* pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
-                        for(int iBand=0;iBand<nBandCount;iBand++)
+                        GByte* pabyLocalData =
+                            pabyData + (y + k) * nLineSpace + x * nPixelSpace;
+                        for( int iBand = 0; iBand < nBandCount; ++iBand )
                         {
-                            GByte* pabyLocalDataBand = pabyLocalData + iBand * nBandSpace;
-
-                            GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                    pabyLocalDataBand, eBufType, static_cast<int>(nPixelSpace),
-                                    nUsedBlockWidth);
+                            GByte* pabyLocalDataBand =
+                                pabyLocalData + iBand * nBandSpace;
+
+                            GDALCopyWords(
+                                &dfNoData, GDT_Float64, 0,
+                                pabyLocalDataBand, eBufType,
+                                static_cast<int>(nPixelSpace),
+                                nUsedBlockWidth );
                         }
                     }
                 }
@@ -2266,48 +2489,56 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                         nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
                     const GByte* pabyLocalSrcDataK0 = oFetcher.FetchBytes(
                             nCurOffset + nByteOffsetInBlock,
-                            (int)nBlockXSize * nUsedBlockHeight * nBandsPerBlock,
+                            nBlockXSize *
+                            nUsedBlockHeight * nBandsPerBlock,
                             nDTSize, bIsByteSwapped, bIsComplex, nBlockId);
                     if( pabyLocalSrcDataK0 == NULL )
                         return CE_Failure;
 
-                    for( int k=0;k<nUsedBlockHeight;k++)
+                    for( int k = 0; k < nUsedBlockHeight; ++k )
                     {
-                        GByte* pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
+                        GByte* pabyLocalData =
+                            pabyData + (y + k) * nLineSpace + x * nPixelSpace;
                         const GByte* pabyLocalSrcData =
-                            pabyLocalSrcDataK0 + (k * nBlockXSize + nXOffsetInBlock) * nBandsPerBlockDTSize;
+                            pabyLocalSrcDataK0 +
+                            (k * nBlockXSize + nXOffsetInBlock) *
+                            nBandsPerBlockDTSize;
 
                         if( bUseContigImplementation && nBands == nBandCount &&
                             nPixelSpace == nBandsPerBlockDTSize )
                         {
                             REACHED(31);
-                            GDALCopyWords(pabyLocalSrcData,
-                                            eDataType, nDTSize,
-                                            pabyLocalData,
-                                            eBufType, nBufDTSize,
-                                            nUsedBlockWidth * nBands);
+                            GDALCopyWords( pabyLocalSrcData,
+                                           eDataType, nDTSize,
+                                           pabyLocalData,
+                                           eBufType, nBufDTSize,
+                                           nUsedBlockWidth * nBands );
                         }
                         else
                         {
                             REACHED(32);
-                            for(int iBand=0;iBand<nBandCount;iBand++)
+                            for( int iBand = 0; iBand < nBandCount; ++iBand )
                             {
-                                GByte* pabyLocalDataBand = pabyLocalData + iBand * nBandSpace;
-                                const GByte* pabyLocalSrcDataBand = pabyLocalSrcData + (panBandMap[iBand]-1) * nDTSize;
-
-                                GDALCopyWords(pabyLocalSrcDataBand,
-                                                eDataType, nBandsPerBlockDTSize,
-                                                pabyLocalDataBand,
-                                                eBufType, static_cast<int>(nPixelSpace),
-                                                nUsedBlockWidth);
+                                GByte* pabyLocalDataBand =
+                                    pabyLocalData + iBand * nBandSpace;
+                                const GByte* pabyLocalSrcDataBand =
+                                    pabyLocalSrcData +
+                                    (panBandMap[iBand]-1) * nDTSize;
+
+                                GDALCopyWords(
+                                    pabyLocalSrcDataBand,
+                                    eDataType, nBandsPerBlockDTSize,
+                                    pabyLocalDataBand,
+                                    eBufType, static_cast<int>(nPixelSpace),
+                                    nUsedBlockWidth );
                             }
                         }
                     }
                 }
 
                 nXOffsetInBlock = 0;
-                nBlockXOff ++;
-                nBlockId ++;
+                ++nBlockXOff;
+                ++nBlockId;
                 x += nUsedBlockWidth;
             }
 
@@ -2315,24 +2546,27 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
         }
     }
     else if( FetchBuffer::bMinimizeIO &&
-             TIFFIsTiled( hTIFF ) && bNoXResampling && (nYSize == nBufYSize ) /*&&
-             (nPlanarConfig == PLANARCONFIG_SEPARATE || nBandCount == 1)*/ )
+             TIFFIsTiled( hTIFF ) && bNoXResampling &&
+             (nYSize == nBufYSize ) )
+             // && (nPlanarConfig == PLANARCONFIG_SEPARATE || nBandCount == 1) )
     {
-        for(int iBand=0;iBand<nBandCount;iBand++)
+        for( int iBand = 0; iBand < nBandCount; ++iBand )
         {
-            GByte* pabyData = (GByte*)pData + iBand * nBandSpace;
+            GByte* pabyData = static_cast<GByte *>(pData) + iBand * nBandSpace;
             const int nBand = panBandMap[iBand];
-            for(int y=0;y<nBufYSize;)
+            for( int y = 0; y < nBufYSize; )
             {
                 const int nSrcLine = nYOff + y;
                 const int nBlockYOff = nSrcLine / nBlockYSize;
                 const int nYOffsetInBlock = nSrcLine % nBlockYSize;
-                const int nUsedBlockHeight = MIN(nBufYSize - y, (int)nBlockYSize - nYOffsetInBlock);
+                const int nUsedBlockHeight =
+                    std::min( nBufYSize - y,
+                              nBlockYSize - nYOffsetInBlock);
 
                 int nBlockXOff = nXOff / nBlockXSize;
                 int nXOffsetInBlock = nXOff % nBlockXSize;
                 int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
-                if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
+                if( nPlanarConfig == PLANARCONFIG_SEPARATE )
                 {
                     REACHED(33);
                     nBlockId += nBlocksPerBand * (nBand - 1);
@@ -2346,32 +2580,41 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                 while( x < nBufXSize )
                 {
                     const toff_t nCurOffset = panOffsets[nBlockId];
-                    const int nUsedBlockWidth = MIN((int)nBlockXSize - nXOffsetInBlock, nBufXSize - x);
+                    const int nUsedBlockWidth =
+                        std::min(
+                            nBlockXSize - nXOffsetInBlock,
+                            nBufXSize - x);
 
                     if( nCurOffset == 0 )
                     {
                         REACHED(35);
-                        for( int k=0;k<nUsedBlockHeight;k++)
+                        for( int k = 0; k < nUsedBlockHeight; ++k )
                         {
-                            GByte* pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
-
-                            GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                    pabyLocalData, eBufType, static_cast<int>(nPixelSpace),
-                                    nUsedBlockWidth);
+                            GByte* pabyLocalData =
+                                pabyData + (y + k) * nLineSpace + x * nPixelSpace;
+
+                            GDALCopyWords(
+                                &dfNoData, GDT_Float64, 0,
+                                pabyLocalData, eBufType,
+                                static_cast<int>(nPixelSpace),
+                                nUsedBlockWidth );
                         }
                     }
                     else
                     {
                         const int nByteOffsetInBlock =
-                            nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
-                        const GByte* pabyLocalSrcDataK0 = oFetcher.FetchBytes(
+                            nYOffsetInBlock * nBlockXSize *
+                            nBandsPerBlockDTSize;
+                        const GByte* pabyLocalSrcDataK0 =
+                            oFetcher.FetchBytes(
                                 nCurOffset + nByteOffsetInBlock,
-                                (int)nBlockXSize * nUsedBlockHeight * nBandsPerBlock,
+                                nBlockXSize *
+                                nUsedBlockHeight * nBandsPerBlock,
                                 nDTSize, bIsByteSwapped, bIsComplex, nBlockId);
                         if( pabyLocalSrcDataK0 == NULL )
                             return CE_Failure;
 
-                        if ( nPlanarConfig == PLANARCONFIG_CONTIG )
+                        if( nPlanarConfig == PLANARCONFIG_CONTIG )
                         {
                             REACHED(36);
                             pabyLocalSrcDataK0 += (nBand - 1) * nDTSize;
@@ -2381,23 +2624,28 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                             REACHED(37);
                         }
 
-                        for( int k=0;k<nUsedBlockHeight;k++)
+                        for( int k = 0; k < nUsedBlockHeight; ++k )
                         {
-                            GByte* pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
+                            GByte* pabyLocalData =
+                                pabyData + (y + k) * nLineSpace +
+                                x * nPixelSpace;
                             const GByte* pabyLocalSrcData =
-                                pabyLocalSrcDataK0 + (k * nBlockXSize + nXOffsetInBlock) * nBandsPerBlockDTSize;
-
-                            GDALCopyWords(pabyLocalSrcData,
-                                            eDataType, nBandsPerBlockDTSize,
-                                            pabyLocalData,
-                                            eBufType, static_cast<int>(nPixelSpace),
-                                            nUsedBlockWidth);
+                                pabyLocalSrcDataK0 +
+                                (k * nBlockXSize + nXOffsetInBlock) *
+                                nBandsPerBlockDTSize;
+
+                            GDALCopyWords(
+                                pabyLocalSrcData,
+                                eDataType, nBandsPerBlockDTSize,
+                                pabyLocalData,
+                                eBufType, static_cast<int>(nPixelSpace),
+                                nUsedBlockWidth);
                         }
                     }
 
                     nXOffsetInBlock = 0;
-                    nBlockXOff ++;
-                    nBlockId ++;
+                    ++nBlockXOff;
+                    ++nBlockId;
                     x += nUsedBlockWidth;
                 }
 
@@ -2409,54 +2657,62 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
              TIFFIsTiled( hTIFF ) &&
              nPlanarConfig == PLANARCONFIG_CONTIG && nBandCount > 1 )
     {
-        GByte* pabyData = (GByte*)pData;
-        int anSrcYOffset[256];
-        for(int y=0;y<nBufYSize;)
+        GByte* pabyData = static_cast<GByte *>(pData);
+        int anSrcYOffset[256] = { 0 };
+        for( int y = 0; y < nBufYSize; )
         {
             const double dfYOffStart = nYOff + (y + 0.5) * dfSrcYInc;
-            const int nSrcLine = (int)dfYOffStart;
+            const int nSrcLine = static_cast<int>(dfYOffStart);
             const int nYOffsetInBlock = nSrcLine % nBlockYSize;
             const int nBlockYOff = nSrcLine / nBlockYSize;
-            const int nBaseByteOffsetInBlock = nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
+            const int nBaseByteOffsetInBlock =
+                nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
             int ychunk = 1;
             int nLastSrcLineK = nSrcLine;
             anSrcYOffset[0] = 0;
-            for(int k=1;k<nBufYSize-y;k++)
+            for( int k = 1; k < nBufYSize - y; ++k )
             {
-                int nSrcLineK = nYOff + (int)((y + k + 0.5) * dfSrcYInc);
+                int nSrcLineK =
+                    nYOff + static_cast<int>((y + k + 0.5) * dfSrcYInc);
                 const int nBlockYOffK = nSrcLineK / nBlockYSize;
                 if( k < 256)
-                    anSrcYOffset[k] = ((nSrcLineK % nBlockYSize) - nYOffsetInBlock) * nBlockXSize * nBandsPerBlockDTSize;
+                    anSrcYOffset[k] =
+                        ((nSrcLineK % nBlockYSize) - nYOffsetInBlock) *
+                        nBlockXSize * nBandsPerBlockDTSize;
                 if( nBlockYOffK != nBlockYOff )
                 {
                     break;
                 }
-                ychunk ++;
+                ++ychunk;
                 nLastSrcLineK = nSrcLineK;
             }
             const int nUsedBlockHeight = nLastSrcLineK - nSrcLine + 1;
-            //CPLAssert(nUsedBlockHeight <= nBlockYSize);
+            // CPLAssert(nUsedBlockHeight <= nBlockYSize);
 
             double dfSrcX = nXOff + 0.5 * dfSrcXInc;
             int nCurBlockXOff = 0;
             int nNextBlockXOff = 0;
             toff_t nCurOffset = 0;
             const GByte* pabyLocalSrcDataStartLine = NULL;
-            for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+            for( int x = 0; x < nBufXSize; ++x, dfSrcX += dfSrcXInc)
             {
-                int nSrcPixel = (int)dfSrcX;
+                const int nSrcPixel = static_cast<int>(dfSrcX);
                 if( nSrcPixel >= nNextBlockXOff )
                 {
                     const int nBlockXOff = nSrcPixel / nBlockXSize;
                     nCurBlockXOff = nBlockXOff * nBlockXSize;
                     nNextBlockXOff = nCurBlockXOff + nBlockXSize;
-                    int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+                    const int nBlockId =
+                        nBlockXOff + nBlockYOff * nBlocksPerRow;
                     nCurOffset = panOffsets[nBlockId];
                     if( nCurOffset != 0 )
                     {
-                        pabyLocalSrcDataStartLine = oFetcher.FetchBytes(
+                        pabyLocalSrcDataStartLine =
+                            oFetcher.FetchBytes(
                                 nCurOffset + nBaseByteOffsetInBlock,
-                                (int)nBlockXSize * nBandsPerBlock * nUsedBlockHeight, nDTSize,
+                                nBlockXSize *
+                                nBandsPerBlock * nUsedBlockHeight,
+                                nDTSize,
                                 bIsByteSwapped, bIsComplex, nBlockId);
                         if( pabyLocalSrcDataStartLine == NULL )
                             return CE_Failure;
@@ -2467,66 +2723,82 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                 {
                     REACHED(38);
 
-                    for( int k = 0; k < ychunk; k ++ )
+                    for( int k = 0; k < ychunk; ++k )
                     {
-                        GByte* const pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
-                        for(int iBand=0;iBand<nBandCount;iBand++)
+                        GByte* const pabyLocalData =
+                            pabyData + (y + k) * nLineSpace + x * nPixelSpace;
+                        for( int iBand = 0; iBand < nBandCount; ++iBand )
                         {
-                            GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                          pabyLocalData + nBandSpace * iBand, eBufType, 0,
-                                          1);
+                            GDALCopyWords(
+                                &dfNoData, GDT_Float64, 0,
+                                pabyLocalData + nBandSpace * iBand, eBufType, 0,
+                                1);
                         }
                     }
                 }
-
                 else
                 {
                     const int nXOffsetInBlock = nSrcPixel - nCurBlockXOff;
                     double dfYOff = dfYOffStart;
                     const GByte* const pabyLocalSrcDataK0 =
-                        pabyLocalSrcDataStartLine + nXOffsetInBlock * nBandsPerBlockDTSize;
-                    GByte* pabyLocalData = pabyData + y * nLineSpace + x * nPixelSpace;
-                    for( int k = 0; k < ychunk; k ++, pabyLocalData += nLineSpace )
+                        pabyLocalSrcDataStartLine +
+                        nXOffsetInBlock * nBandsPerBlockDTSize;
+                    GByte* pabyLocalData =
+                        pabyData + y * nLineSpace + x * nPixelSpace;
+                    for( int k = 0;
+                         k < ychunk;
+                         ++k, pabyLocalData += nLineSpace )
                     {
-                        const GByte* pabyLocalSrcData;
+                        const GByte* pabyLocalSrcData = NULL;
                         if( ychunk <= 256 )
                         {
                             REACHED(39);
-                            pabyLocalSrcData = pabyLocalSrcDataK0 + anSrcYOffset[k];
+                            pabyLocalSrcData =
+                                pabyLocalSrcDataK0 + anSrcYOffset[k];
                         }
                         else
                         {
                             REACHED(40);
-                            const int nYOffsetInBlockK = ((int)dfYOff) % nBlockYSize;
-                            //CPLAssert(nYOffsetInBlockK - nYOffsetInBlock <= nUsedBlockHeight);
-                            pabyLocalSrcData = pabyLocalSrcDataK0 +
-                                (nYOffsetInBlockK - nYOffsetInBlock) * nBlockXSize * nBandsPerBlockDTSize;
+                            const int nYOffsetInBlockK =
+                                static_cast<int>(dfYOff) % nBlockYSize;
+                            // CPLAssert(
+                            //     nYOffsetInBlockK - nYOffsetInBlock <=
+                            //     nUsedBlockHeight);
+                            pabyLocalSrcData =
+                                pabyLocalSrcDataK0 +
+                                (nYOffsetInBlockK - nYOffsetInBlock) *
+                                nBlockXSize * nBandsPerBlockDTSize;
                             dfYOff += dfSrcYInc;
                         }
 
                         if( bByteOnly )
                         {
                             REACHED(41);
-                            for(int iBand=0;iBand<nBandCount;iBand++)
+                            for( int iBand=0; iBand < nBandCount; ++iBand )
                             {
-                                GByte* pabyLocalDataBand = pabyLocalData + iBand * nBandSpace;
-                                const GByte* pabyLocalSrcDataBand = pabyLocalSrcData + (panBandMap[iBand]-1) /* * nDTSize*/;
+                                GByte* pabyLocalDataBand =
+                                    pabyLocalData + iBand * nBandSpace;
+                                const GByte* pabyLocalSrcDataBand =
+                                    pabyLocalSrcData + (panBandMap[iBand]-1);
                                 *pabyLocalDataBand = *pabyLocalSrcDataBand;
                             }
                         }
                         else
                         {
                             REACHED(42);
-                            for(int iBand=0;iBand<nBandCount;iBand++)
+                            for( int iBand = 0; iBand < nBandCount; ++iBand )
                             {
-                                GByte* pabyLocalDataBand = pabyLocalData + iBand * nBandSpace;
-                                const GByte* pabyLocalSrcDataBand = pabyLocalSrcData + (panBandMap[iBand]-1) * nDTSize;
-
-                                GDALCopyWords(pabyLocalSrcDataBand,
-                                                eDataType, 0,
-                                                pabyLocalDataBand,
-                                                eBufType, 0,
-                                                1);
+                                GByte* pabyLocalDataBand =
+                                    pabyLocalData + iBand * nBandSpace;
+                                const GByte* pabyLocalSrcDataBand =
+                                    pabyLocalSrcData +
+                                    (panBandMap[iBand]-1) * nDTSize;
+
+                                GDALCopyWords( pabyLocalSrcDataBand,
+                                               eDataType, 0,
+                                               pabyLocalDataBand,
+                                               eBufType, 0,
+                                               1 );
                             }
                         }
                     }
@@ -2537,55 +2809,59 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
         }
     }
     else if( FetchBuffer::bMinimizeIO &&
-             TIFFIsTiled( hTIFF ) /* &&
-             (nPlanarConfig == PLANARCONFIG_SEPARATE || nBandCount == 1) */ )
+             TIFFIsTiled( hTIFF ) )
+             // && (nPlanarConfig == PLANARCONFIG_SEPARATE || nBandCount == 1) )
     {
-        for(int iBand=0;iBand<nBandCount;iBand++)
+        for( int iBand = 0; iBand < nBandCount; ++iBand )
         {
-            GByte* pabyData = (GByte*)pData + iBand * nBandSpace;
+            GByte* pabyData = static_cast<GByte*>(pData) + iBand * nBandSpace;
             const int nBand = panBandMap[iBand];
-            int anSrcYOffset[256];
-            for(int y=0;y<nBufYSize;)
+            int anSrcYOffset[256] = { 0 };
+            for( int y = 0; y < nBufYSize; )
             {
                 const double dfYOffStart = nYOff + (y + 0.5) * dfSrcYInc;
-                const int nSrcLine = (int)dfYOffStart;
+                const int nSrcLine = static_cast<int>(dfYOffStart);
                 const int nYOffsetInBlock = nSrcLine % nBlockYSize;
                 const int nBlockYOff = nSrcLine / nBlockYSize;
-                const int nBaseByteOffsetInBlock = nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
+                const int nBaseByteOffsetInBlock =
+                    nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
                 int ychunk = 1;
                 int nLastSrcLineK = nSrcLine;
                 anSrcYOffset[0] = 0;
-                for(int k=1;k<nBufYSize-y;k++)
+                for( int k = 1; k < nBufYSize - y; ++k )
                 {
-                    int nSrcLineK = nYOff + (int)((y + k + 0.5) * dfSrcYInc);
+                    const int nSrcLineK =
+                        nYOff + static_cast<int>((y + k + 0.5) * dfSrcYInc);
                     const int nBlockYOffK = nSrcLineK / nBlockYSize;
                     if( k < 256)
-                        anSrcYOffset[k] = ((nSrcLineK % nBlockYSize) - nYOffsetInBlock) * nBlockXSize * nBandsPerBlockDTSize;
+                        anSrcYOffset[k] =
+                            ((nSrcLineK % nBlockYSize) - nYOffsetInBlock) *
+                            nBlockXSize * nBandsPerBlockDTSize;
                     if( nBlockYOffK != nBlockYOff )
                     {
                         break;
                     }
-                    ychunk ++;
+                    ++ychunk;
                     nLastSrcLineK = nSrcLineK;
                 }
                 const int nUsedBlockHeight = nLastSrcLineK - nSrcLine + 1;
-                //CPLAssert(nUsedBlockHeight <= nBlockYSize);
+                // CPLAssert(nUsedBlockHeight <= nBlockYSize);
 
                 double dfSrcX = nXOff + 0.5 * dfSrcXInc;
                 int nCurBlockXOff = 0;
                 int nNextBlockXOff = 0;
                 toff_t nCurOffset = 0;
                 const GByte* pabyLocalSrcDataStartLine = NULL;
-                for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                for( int x = 0; x < nBufXSize; ++x, dfSrcX += dfSrcXInc )
                 {
-                    int nSrcPixel = (int)dfSrcX;
+                    int nSrcPixel = static_cast<int>(dfSrcX);
                     if( nSrcPixel >= nNextBlockXOff )
                     {
                         const int nBlockXOff = nSrcPixel / nBlockXSize;
                         nCurBlockXOff = nBlockXOff * nBlockXSize;
                         nNextBlockXOff = nCurBlockXOff + nBlockXSize;
                         int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
-                        if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
+                        if( nPlanarConfig == PLANARCONFIG_SEPARATE )
                         {
                             REACHED(43);
                             nBlockId += nBlocksPerBand * (nBand - 1);
@@ -2597,23 +2873,26 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                         nCurOffset = panOffsets[nBlockId];
                         if( nCurOffset != 0 )
                         {
-                            pabyLocalSrcDataStartLine = oFetcher.FetchBytes(
+                            pabyLocalSrcDataStartLine =
+                                oFetcher.FetchBytes(
                                     nCurOffset + nBaseByteOffsetInBlock,
-                                    (int)nBlockXSize * nBandsPerBlock * nUsedBlockHeight, nDTSize,
+                                    nBlockXSize *
+                                    nBandsPerBlock * nUsedBlockHeight,
+                                    nDTSize,
                                     bIsByteSwapped, bIsComplex, nBlockId);
                             if( pabyLocalSrcDataStartLine == NULL )
                                 return CE_Failure;
 
-                            if ( nPlanarConfig == PLANARCONFIG_CONTIG )
+                            if( nPlanarConfig == PLANARCONFIG_CONTIG )
                             {
                                 REACHED(45);
-                                pabyLocalSrcDataStartLine += (nBand - 1) * nDTSize;
+                                pabyLocalSrcDataStartLine +=
+                                    (nBand - 1) * nDTSize;
                             }
                             else
                             {
                                 REACHED(46);
                             }
-
                         }
                     }
 
@@ -2621,38 +2900,47 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                     {
                         REACHED(47);
 
-                        for( int k = 0; k < ychunk; k ++ )
+                        for( int k = 0; k < ychunk; ++k )
                         {
-                            GByte* const pabyLocalData = pabyData + (y+k) * nLineSpace + x * nPixelSpace;
+                            GByte* const pabyLocalData =
+                                pabyData + (y + k) * nLineSpace + x * nPixelSpace;
 
-                            GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                            pabyLocalData, eBufType, 0,
-                                            1);
+                            GDALCopyWords( &dfNoData, GDT_Float64, 0,
+                                           pabyLocalData, eBufType, 0,
+                                           1 );
                         }
                     }
-
                     else
                     {
                         const int nXOffsetInBlock = nSrcPixel - nCurBlockXOff;
                         double dfYOff = dfYOffStart;
                         const GByte* const pabyLocalSrcDataK0 =
-                            pabyLocalSrcDataStartLine + nXOffsetInBlock * nBandsPerBlockDTSize;
-                        GByte* pabyLocalData = pabyData + y * nLineSpace + x * nPixelSpace;
-                        for( int k = 0; k < ychunk; k ++, pabyLocalData += nLineSpace )
+                            pabyLocalSrcDataStartLine +
+                            nXOffsetInBlock * nBandsPerBlockDTSize;
+                        GByte* pabyLocalData =
+                            pabyData + y * nLineSpace + x * nPixelSpace;
+                        for( int k = 0;
+                             k < ychunk;
+                             ++k, pabyLocalData += nLineSpace )
                         {
-                            const GByte* pabyLocalSrcData;
+                            const GByte* pabyLocalSrcData = NULL;
                             if( ychunk <= 256 )
                             {
                                 REACHED(48);
-                                pabyLocalSrcData = pabyLocalSrcDataK0 + anSrcYOffset[k];
+                                pabyLocalSrcData =
+                                    pabyLocalSrcDataK0 + anSrcYOffset[k];
                             }
                             else
                             {
                                 REACHED(49);
-                                const int nYOffsetInBlockK = ((int)dfYOff) % nBlockYSize;
-                                //CPLAssert(nYOffsetInBlockK - nYOffsetInBlock <= nUsedBlockHeight);
+                                const int nYOffsetInBlockK =
+                                    static_cast<int>(dfYOff) % nBlockYSize;
+                                // CPLAssert(
+                                //     nYOffsetInBlockK - nYOffsetInBlock <=
+                                //     nUsedBlockHeight);
                                 pabyLocalSrcData = pabyLocalSrcDataK0 +
-                                    (nYOffsetInBlockK - nYOffsetInBlock) * nBlockXSize * nBandsPerBlockDTSize;
+                                    (nYOffsetInBlockK - nYOffsetInBlock) *
+                                    nBlockXSize * nBandsPerBlockDTSize;
                                 dfYOff += dfSrcYInc;
                             }
 
@@ -2666,11 +2954,11 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                             {
                                 REACHED(51);
 
-                                GDALCopyWords(pabyLocalSrcData,
-                                                eDataType, 0,
-                                                pabyLocalData,
-                                                eBufType, 0,
-                                                1);
+                                GDALCopyWords( pabyLocalSrcData,
+                                               eDataType, 0,
+                                               pabyLocalData,
+                                               eBufType, 0,
+                                               1 );
                             }
                         }
                     }
@@ -2684,13 +2972,15 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
     {
         if( !FetchBuffer::bMinimizeIO && TIFFIsTiled( hTIFF ) )
         {
-            GByte* pabyData = (GByte*)pData;
-            for(int y=0;y<nBufYSize;y++)
+            GByte* pabyData = static_cast<GByte *>(pData);
+            for( int y = 0; y < nBufYSize; ++y )
             {
-                const int nSrcLine = nYOff + (int)((y + 0.5) * dfSrcYInc);
+                const int nSrcLine =
+                    nYOff + static_cast<int>((y + 0.5) * dfSrcYInc);
                 const int nBlockYOff = nSrcLine / nBlockYSize;
                 const int nYOffsetInBlock = nSrcLine % nBlockYSize;
-                const int nBaseByteOffsetInBlock = nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
+                const int nBaseByteOffsetInBlock =
+                    nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
 
                 if( bNoXResampling )
                 {
@@ -2705,7 +2995,10 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                         const int nByteOffsetInBlock = nBaseByteOffsetInBlock +
                                         nXOffsetInBlock * nBandsPerBlockDTSize;
                         const toff_t nCurOffset = panOffsets[nBlockId];
-                        const int nUsedBlockWidth = MIN((int)nBlockXSize - nXOffsetInBlock, nBufXSize - x);
+                        const int nUsedBlockWidth =
+                            std::min(
+                                nBlockXSize - nXOffsetInBlock,
+                                nBufXSize - x);
 
                         int nIters = nUsedBlockWidth;
                         if( nCurOffset == 0 )
@@ -2715,8 +3008,12 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                                 REACHED(0);
                                 while( nIters-- > 0 )
                                 {
-                                    for(int iBand=0;iBand<nBandCount;iBand++)
+                                    for( int iBand = 0;
+                                         iBand < nBandCount;
+                                         ++iBand )
+                                    {
                                         pabyLocalData[iBand] = abyNoData;
+                                    }
                                     pabyLocalData += nPixelSpace;
                                 }
                             }
@@ -2725,9 +3022,11 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                                 REACHED(1);
                                 while( nIters-- > 0 )
                                 {
-                                    GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                          pabyLocalData, eBufType, static_cast<int>(nBandSpace),
-                                          nBandCount);
+                                    GDALCopyWords(
+                                        &dfNoData, GDT_Float64, 0,
+                                        pabyLocalData, eBufType,
+                                        static_cast<int>(nBandSpace),
+                                        nBandCount);
                                     pabyLocalData += nPixelSpace;
                                 }
                             }
@@ -2746,11 +3045,13 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                                 {
                                     return CE_Failure;
                                 }
-                                pabyLocalData += nIters * nBandsPerBlock * nDTSize;
+                                pabyLocalData +=
+                                    nIters * nBandsPerBlock * nDTSize;
                             }
                             else
                             {
-                                const GByte* pabyLocalSrcData = oFetcher.FetchBytes(
+                                const GByte* pabyLocalSrcData =
+                                    oFetcher.FetchBytes(
                                         nCurOffset + nByteOffsetInBlock,
                                         nIters * nBandsPerBlock, nDTSize,
                                         bIsByteSwapped, bIsComplex, nBlockId);
@@ -2759,12 +3060,13 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                                 if( bByteNoXResampling )
                                 {
                                     REACHED(3);
-                                    CopyContigByteMultiBand(pabyLocalSrcData,
-                                                        nBandsPerBlockDTSize,
-                                                        pabyLocalData,
-                                                        static_cast<int>(nPixelSpace),
-                                                        nIters,
-                                                        nBandCount);
+                                    CopyContigByteMultiBand(
+                                        pabyLocalSrcData,
+                                        nBandsPerBlockDTSize,
+                                        pabyLocalData,
+                                        static_cast<int>(nPixelSpace),
+                                        nIters,
+                                        nBandCount);
                                     pabyLocalData += nIters * nPixelSpace;
                                 }
                                 else
@@ -2772,12 +3074,15 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                                     REACHED(4);
                                     while( nIters-- > 0 )
                                     {
-                                        GDALCopyWords(pabyLocalSrcData,
-                                                      eDataType, nDTSize,
-                                                      pabyLocalData,
-                                                      eBufType, static_cast<int>(nBandSpace),
-                                                      nBandCount);
-                                        pabyLocalSrcData += nBandsPerBlockDTSize;
+                                        GDALCopyWords(
+                                            pabyLocalSrcData,
+                                            eDataType, nDTSize,
+                                            pabyLocalData,
+                                            eBufType,
+                                            static_cast<int>(nBandSpace),
+                                            nBandCount);
+                                        pabyLocalSrcData +=
+                                            nBandsPerBlockDTSize;
                                         pabyLocalData += nPixelSpace;
                                     }
                                 }
@@ -2785,12 +3090,12 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                         }
 
                         nXOffsetInBlock = 0;
-                        nBlockXOff ++;
-                        nBlockId ++;
+                        ++nBlockXOff;
+                        ++nBlockId;
                         x += nUsedBlockWidth;
                     }
                 }
-                else /* contig, tiled, potential resampling and data type change */
+                else  // Contig, tiled, potential resampling & data type change.
                 {
                     const GByte* pabyLocalSrcDataStartLine = NULL;
                     GByte* pabyLocalData = pabyData + y * nLineSpace;
@@ -2798,21 +3103,25 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                     int nCurBlockXOff = 0;
                     int nNextBlockXOff = 0;
                     toff_t nCurOffset = 0;
-                    for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                    for( int x = 0; x < nBufXSize; ++x, dfSrcX += dfSrcXInc )
                     {
-                        int nSrcPixel = (int)dfSrcX;
+                        int nSrcPixel = static_cast<int>(dfSrcX);
                         if( nSrcPixel >= nNextBlockXOff )
                         {
                             const int nBlockXOff = nSrcPixel / nBlockXSize;
                             nCurBlockXOff = nBlockXOff * nBlockXSize;
                             nNextBlockXOff = nCurBlockXOff + nBlockXSize;
-                            int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+                            const int nBlockId =
+                                nBlockXOff + nBlockYOff * nBlocksPerRow;
                             nCurOffset = panOffsets[nBlockId];
                             if( nCurOffset != 0 )
                             {
-                                pabyLocalSrcDataStartLine = oFetcher.FetchBytes(
+                                pabyLocalSrcDataStartLine =
+                                    oFetcher.FetchBytes(
                                         nCurOffset + nBaseByteOffsetInBlock,
-                                        (int)nBlockXSize * nBandsPerBlock, nDTSize,
+                                        nBlockXSize *
+                                        nBandsPerBlock,
+                                        nDTSize,
                                         bIsByteSwapped, bIsComplex, nBlockId);
                                 if( pabyLocalSrcDataStartLine == NULL )
                                     return CE_Failure;
@@ -2823,30 +3132,36 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                         if( nCurOffset == 0 )
                         {
                             REACHED(5);
-                            GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                          pabyLocalData,
-                                          eBufType, static_cast<int>(nBandSpace),
-                                          nBandCount);
+                            GDALCopyWords(
+                                &dfNoData, GDT_Float64, 0,
+                                pabyLocalData,
+                                eBufType,
+                                static_cast<int>(nBandSpace),
+                                nBandCount );
                             pabyLocalData += nPixelSpace;
                         }
                         else
                         {
-                            const GByte* pabyLocalSrcData = pabyLocalSrcDataStartLine +
-                                    nXOffsetInBlock * nBandsPerBlockDTSize;
+                            const GByte* pabyLocalSrcData =
+                                pabyLocalSrcDataStartLine +
+                                nXOffsetInBlock * nBandsPerBlockDTSize;
 
                             REACHED(6);
                             if( bByteOnly )
                             {
-                                for(int iBand = 0; iBand < nBands; iBand ++ )
-                                    pabyLocalData[iBand] = pabyLocalSrcData[iBand];
+                                for( int iBand = 0; iBand < nBands; ++iBand )
+                                    pabyLocalData[iBand] =
+                                        pabyLocalSrcData[iBand];
                             }
                             else
                             {
-                                GDALCopyWords(pabyLocalSrcData,
-                                            eDataType, nDTSize,
-                                            pabyLocalData,
-                                            eBufType, static_cast<int>(nBandSpace),
-                                            nBandCount);
+                                GDALCopyWords(
+                                    pabyLocalSrcData,
+                                    eDataType, nDTSize,
+                                    pabyLocalData,
+                                    eBufType,
+                                    static_cast<int>(nBandSpace),
+                                    nBandCount );
                             }
                             pabyLocalData += nPixelSpace;
                         }
@@ -2854,12 +3169,13 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                 }
             }
         }
-        else /* contig, stripped organized */
+        else  // Contig, stripped organized.
         {
-            GByte* pabyData = (GByte*)pData;
-            for(int y=0;y<nBufYSize;y++)
+            GByte* pabyData = static_cast<GByte*>(pData);
+            for( int y = 0; y < nBufYSize; ++y )
             {
-                const int nSrcLine = nYOff + (int)((y + 0.5) * dfSrcYInc);
+                const int nSrcLine =
+                    nYOff + static_cast<int>((y + 0.5) * dfSrcYInc);
                 const int nBlockYOff = nSrcLine / nBlockYSize;
                 const int nYOffsetInBlock = nSrcLine % nBlockYSize;
                 const int nBlockId = nBlockYOff;
@@ -2867,27 +3183,31 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                 if( nCurOffset == 0 )
                 {
                     REACHED(7);
-                    for(int x=0;x<nBufXSize;x++)
+                    for( int x = 0; x < nBufXSize; ++x )
                     {
-                        GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                      pabyData + y * nLineSpace + x * nPixelSpace,
-                                      eBufType, static_cast<int>(nBandSpace),
-                                      nBandCount);
+                        GDALCopyWords(
+                            &dfNoData, GDT_Float64, 0,
+                            pabyData + y * nLineSpace + x * nPixelSpace,
+                            eBufType, static_cast<int>(nBandSpace),
+                            nBandCount);
                     }
                 }
                 else
                 {
                     GByte* pabyLocalData = pabyData + y * nLineSpace;
-                    const int nBaseByteOffsetInBlock = (nYOffsetInBlock * nBlockXSize + nXOff) * nBandsPerBlockDTSize;
+                    const int nBaseByteOffsetInBlock =
+                        (nYOffsetInBlock * nBlockXSize + nXOff) *
+                        nBandsPerBlockDTSize;
 
                     if( bNoXResamplingNoTypeChange && nBands == nBandCount &&
                         nPixelSpace == nBandsPerBlockDTSize )
                     {
                         REACHED(8);
                         if( !oFetcher.FetchBytes(
-                            pabyLocalData,
-                            nCurOffset + nBaseByteOffsetInBlock,
-                            nXSize * nBandsPerBlock, nDTSize, bIsByteSwapped, bIsComplex, nBlockId) )
+                               pabyLocalData,
+                               nCurOffset + nBaseByteOffsetInBlock,
+                               nXSize * nBandsPerBlock, nDTSize, bIsByteSwapped,
+                               bIsComplex, nBlockId) )
                         {
                             return CE_Failure;
                         }
@@ -2896,31 +3216,40 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                     {
                         const GByte* pabyLocalSrcData = oFetcher.FetchBytes(
                             nCurOffset + nBaseByteOffsetInBlock,
-                            nXSize * nBandsPerBlock, nDTSize, bIsByteSwapped, bIsComplex, nBlockId);
+                            nXSize * nBandsPerBlock, nDTSize, bIsByteSwapped,
+                            bIsComplex, nBlockId);
                         if( pabyLocalSrcData == NULL )
                             return CE_Failure;
 
                         if( bByteNoXResampling )
                         {
                             REACHED(9);
-                            CopyContigByteMultiBand(pabyLocalSrcData,
-                                                nBandsPerBlockDTSize,
-                                                pabyLocalData,
-                                                static_cast<int>(nPixelSpace),
-                                                nBufXSize,
-                                                nBandCount);
+                            CopyContigByteMultiBand(
+                                pabyLocalSrcData,
+                                nBandsPerBlockDTSize,
+                                pabyLocalData,
+                                static_cast<int>(nPixelSpace),
+                                nBufXSize,
+                                nBandCount);
                         }
                         else if( bByteOnly )
                         {
                             REACHED(10);
                             double dfSrcX = 0.5 * dfSrcXInc;
-                            for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                            for( int x = 0;
+                                 x < nBufXSize;
+                                 ++x, dfSrcX += dfSrcXInc )
                             {
-                                int nSrcPixelMinusXOff = (int)dfSrcX;
-                                for(int iBand=0;iBand<nBandCount;iBand++)
+                                const int nSrcPixelMinusXOff =
+                                    static_cast<int>(dfSrcX);
+                                for( int iBand = 0;
+                                     iBand < nBandCount;
+                                     ++iBand )
                                 {
-                                    pabyLocalData[x * nPixelSpace + iBand /* * nBandSpace*/] =
-                                        pabyLocalSrcData[nSrcPixelMinusXOff * nBandsPerBlockDTSize + iBand];
+                                    pabyLocalData[x * nPixelSpace + iBand] =
+                                        pabyLocalSrcData[nSrcPixelMinusXOff *
+                                                         nBandsPerBlockDTSize +
+                                                         iBand];
                                 }
                             }
                         }
@@ -2928,14 +3257,20 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                         {
                             REACHED(11);
                             double dfSrcX = 0.5 * dfSrcXInc;
-                            for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                            for( int x = 0;
+                                 x < nBufXSize;
+                                 ++x, dfSrcX += dfSrcXInc )
                             {
-                                int nSrcPixelMinusXOff = (int)dfSrcX;
-                                GDALCopyWords(pabyLocalSrcData + nSrcPixelMinusXOff * nBandsPerBlockDTSize,
-                                            eDataType, nDTSize,
-                                            pabyLocalData + x * nPixelSpace,
-                                            eBufType, static_cast<int>(nBandSpace),
-                                            nBandCount);
+                                int nSrcPixelMinusXOff =
+                                    static_cast<int>(dfSrcX);
+                                GDALCopyWords(
+                                    pabyLocalSrcData +
+                                    nSrcPixelMinusXOff * nBandsPerBlockDTSize,
+                                    eDataType, nDTSize,
+                                    pabyLocalData + x * nPixelSpace,
+                                    eBufType,
+                                    static_cast<int>(nBandSpace),
+                                    nBandCount );
                             }
                         }
                     }
@@ -2943,25 +3278,28 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
             }
         }
     }
-    else /* non contig reading case */
+    else  // Non-contig reading case.
     {
         if( !FetchBuffer::bMinimizeIO && TIFFIsTiled( hTIFF ) )
         {
-            for(int iBand = 0; iBand < nBandCount; iBand ++ )
+            for( int iBand = 0; iBand < nBandCount; ++iBand )
             {
                 const int nBand = panBandMap[iBand];
-                GByte* const pabyData = (GByte*)pData + iBand * nBandSpace;
-                for(int y=0;y<nBufYSize;y++)
+                GByte* const pabyData =
+                    static_cast<GByte*>(pData) + iBand * nBandSpace;
+                for( int y = 0; y < nBufYSize; ++y )
                 {
-                    const int nSrcLine = nYOff + (int)((y + 0.5) * dfSrcYInc);
+                    const int nSrcLine =
+                        nYOff + static_cast<int>((y + 0.5) * dfSrcYInc);
                     const int nBlockYOff = nSrcLine / nBlockYSize;
                     const int nYOffsetInBlock = nSrcLine % nBlockYSize;
 
-                    int nBaseByteOffsetInBlock = nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
-                    if ( nPlanarConfig == PLANARCONFIG_CONTIG )
+                    int nBaseByteOffsetInBlock =
+                        nYOffsetInBlock * nBlockXSize * nBandsPerBlockDTSize;
+                    if( nPlanarConfig == PLANARCONFIG_CONTIG )
                     {
                         REACHED(12);
-                        nBaseByteOffsetInBlock += (nBand-1) * nDTSize;
+                        nBaseByteOffsetInBlock += (nBand - 1) * nDTSize;
                     }
                     else
                     {
@@ -2973,7 +3311,7 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                         GByte* pabyLocalData = pabyData + y * nLineSpace;
                         int nBlockXOff = nXOff / nBlockXSize;
                         int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
-                        if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
+                        if( nPlanarConfig == PLANARCONFIG_SEPARATE )
                         {
                             REACHED(14);
                             nBlockId += nBlocksPerBand * (nBand - 1);
@@ -2987,29 +3325,39 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                         int x = 0;
                         while( x < nBufXSize )
                         {
-                            const int nByteOffsetInBlock = nBaseByteOffsetInBlock +
-                                    nXOffsetInBlock * nBandsPerBlockDTSize;
+                            const int nByteOffsetInBlock =
+                                nBaseByteOffsetInBlock +
+                                nXOffsetInBlock * nBandsPerBlockDTSize;
                             const toff_t nCurOffset = panOffsets[nBlockId];
-                            const int nUsedBlockWidth = MIN((int)nBlockXSize - nXOffsetInBlock, nBufXSize - x);
+                            const int nUsedBlockWidth =
+                                std::min(
+                                    nBlockXSize - nXOffsetInBlock,
+                                    nBufXSize - x );
                             int nIters = nUsedBlockWidth;
 
                             if( nCurOffset == 0 )
                             {
                                 REACHED(16);
-                                GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                              pabyLocalData, eBufType, static_cast<int>(nPixelSpace),
-                                              nIters);
+                                GDALCopyWords(
+                                    &dfNoData, GDT_Float64, 0,
+                                    pabyLocalData, eBufType,
+                                    static_cast<int>(nPixelSpace),
+                                    nIters);
                                 pabyLocalData += nIters * nPixelSpace;
                             }
                             else
                             {
-                                if( bNoTypeChange && nPixelSpace == nBandsPerBlockDTSize )
+                                if( bNoTypeChange &&
+                                    nPixelSpace == nBandsPerBlockDTSize )
                                 {
                                     REACHED(17);
-                                    if( !oFetcher.FetchBytes( pabyLocalData,
-                                            nCurOffset + nByteOffsetInBlock,
-                                            (nIters - 1) * nBandsPerBlock + 1, nDTSize,
-                                            bIsByteSwapped, bIsComplex, nBlockId) )
+                                    if( !oFetcher.FetchBytes(
+                                           pabyLocalData,
+                                           nCurOffset + nByteOffsetInBlock,
+                                           (nIters - 1) * nBandsPerBlock + 1,
+                                           nDTSize,
+                                           bIsByteSwapped, bIsComplex,
+                                           nBlockId) )
                                     {
                                         return CE_Failure;
                                     }
@@ -3017,45 +3365,56 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                                 }
                                 else
                                 {
-                                    const GByte* pabyLocalSrcData = oFetcher.FetchBytes(
-                                        nCurOffset + nByteOffsetInBlock,
-                                        (nIters - 1) * nBandsPerBlock + 1, nDTSize,
-                                        bIsByteSwapped, bIsComplex, nBlockId);
+                                    const GByte* pabyLocalSrcData =
+                                        oFetcher.FetchBytes(
+                                            nCurOffset + nByteOffsetInBlock,
+                                            (nIters - 1) * nBandsPerBlock + 1,
+                                            nDTSize,
+                                            bIsByteSwapped,
+                                            bIsComplex,
+                                            nBlockId );
                                     if( pabyLocalSrcData == NULL )
                                         return CE_Failure;
 
                                     REACHED(18);
-                                    GDALCopyWords(pabyLocalSrcData, eDataType, nBandsPerBlockDTSize,
-                                                    pabyLocalData, eBufType, static_cast<int>(nPixelSpace),
-                                                    nIters);
+                                    GDALCopyWords(
+                                        pabyLocalSrcData, eDataType,
+                                        nBandsPerBlockDTSize,
+                                        pabyLocalData, eBufType,
+                                        static_cast<int>(nPixelSpace),
+                                        nIters );
                                     pabyLocalData += nIters * nPixelSpace;
                                 }
                             }
 
                             nXOffsetInBlock = 0;
-                            nBlockXOff ++;
-                            nBlockId ++;
+                            ++nBlockXOff;
+                            ++nBlockId;
                             x += nUsedBlockWidth;
                         }
                     }
-                    else /* non contig reading, tiled, potential resampling and data type change */
+                    else
                     {
+                        // Non-contig reading, tiled, potential resampling and
+                        // data type change.
+
                         const GByte* pabyLocalSrcDataStartLine = NULL;
                         GByte* pabyLocalData = pabyData + y * nLineSpace;
                         double dfSrcX = nXOff + 0.5 * dfSrcXInc;
                         int nCurBlockXOff = 0;
                         int nNextBlockXOff = 0;
                         toff_t nCurOffset = 0;
-                        for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                        for( int x = 0; x < nBufXSize; ++x, dfSrcX += dfSrcXInc)
                         {
-                            int nSrcPixel = (int)dfSrcX;
+                            const int nSrcPixel = static_cast<int>(dfSrcX);
                             if( nSrcPixel >= nNextBlockXOff )
                             {
                                 const int nBlockXOff = nSrcPixel / nBlockXSize;
                                 nCurBlockXOff = nBlockXOff * nBlockXSize;
                                 nNextBlockXOff = nCurBlockXOff + nBlockXSize;
-                                int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
-                                if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
+                                int nBlockId =
+                                    nBlockXOff + nBlockYOff * nBlocksPerRow;
+                                if( nPlanarConfig == PLANARCONFIG_SEPARATE )
                                 {
                                     REACHED(19);
                                     nBlockId += nBlocksPerBand * (nBand - 1);
@@ -3067,33 +3426,41 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                                 nCurOffset = panOffsets[nBlockId];
                                 if( nCurOffset != 0 )
                                 {
-                                    pabyLocalSrcDataStartLine = oFetcher.FetchBytes(
+                                    pabyLocalSrcDataStartLine =
+                                        oFetcher.FetchBytes(
                                             nCurOffset + nBaseByteOffsetInBlock,
-                                            (int)nBlockXSize * nBandsPerBlock, nDTSize,
-                                            bIsByteSwapped, bIsComplex, nBlockId);
+                                            nBlockXSize * nBandsPerBlock,
+                                            nDTSize,
+                                            bIsByteSwapped,
+                                            bIsComplex,
+                                            nBlockId);
                                     if( pabyLocalSrcDataStartLine == NULL )
                                         return CE_Failure;
                                 }
                             }
-                            const int nXOffsetInBlock = nSrcPixel - nCurBlockXOff;
+                            const int nXOffsetInBlock =
+                                nSrcPixel - nCurBlockXOff;
 
                             if( nCurOffset == 0 )
                             {
                                 REACHED(21);
-                                GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                              pabyLocalData,
-                                              eBufType, 0,
-                                              1);
+                                GDALCopyWords( &dfNoData, GDT_Float64, 0,
+                                               pabyLocalData,
+                                               eBufType, 0,
+                                               1 );
                                 pabyLocalData += nPixelSpace;
                             }
                             else
                             {
-                                const GByte* pabyLocalSrcData = pabyLocalSrcDataStartLine +
-                                        nXOffsetInBlock * nBandsPerBlockDTSize;
+                                const GByte* pabyLocalSrcData =
+                                    pabyLocalSrcDataStartLine +
+                                    nXOffsetInBlock * nBandsPerBlockDTSize;
 
                                 REACHED(22);
                                 if( bByteOnly )
+                                {
                                     *pabyLocalData = *pabyLocalSrcData;
+                                }
                                 else
                                 {
                                     GDALCopyWords(pabyLocalSrcData,
@@ -3109,19 +3476,21 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                 }
             }
         }
-        else /* non contig reading, stripped */
+        else  // Non-contig reading, stripped.
         {
-            for(int iBand = 0; iBand < nBandCount; iBand ++ )
+            for( int iBand = 0; iBand < nBandCount; ++iBand )
             {
                 const int nBand = panBandMap[iBand];
-                GByte* pabyData = (GByte*)pData + iBand * nBandSpace;
-                for(int y=0;y<nBufYSize;y++)
+                GByte* pabyData =
+                    static_cast<GByte *>(pData) + iBand * nBandSpace;
+                for( int y = 0; y < nBufYSize; ++y )
                 {
-                    const int nSrcLine = nYOff + (int)((y + 0.5) * dfSrcYInc);
+                    const int nSrcLine =
+                        nYOff + static_cast<int>((y + 0.5) * dfSrcYInc);
                     const int nBlockYOff = nSrcLine / nBlockYSize;
                     const int nYOffsetInBlock = nSrcLine % nBlockYSize;
                     int nBlockId = nBlockYOff;
-                    if ( nPlanarConfig == PLANARCONFIG_SEPARATE )
+                    if( nPlanarConfig == PLANARCONFIG_SEPARATE )
                     {
                         REACHED(23);
                         nBlockId += nBlocksPerBand * (nBand - 1);
@@ -3134,25 +3503,31 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                     if( nCurOffset == 0 )
                     {
                         REACHED(25);
-                        GDALCopyWords(&dfNoData, GDT_Float64, 0,
-                                      pabyData + y * nLineSpace, eBufType, static_cast<int>(nPixelSpace),
-                                      nBufXSize);
+                        GDALCopyWords(
+                            &dfNoData, GDT_Float64, 0,
+                            pabyData + y * nLineSpace,
+                            eBufType,
+                            static_cast<int>(nPixelSpace),
+                            nBufXSize);
                     }
                     else
                     {
                         int nBaseByteOffsetInBlock =
-                            (nYOffsetInBlock * nBlockXSize + nXOff) * nBandsPerBlockDTSize;
-                        if ( nPlanarConfig == PLANARCONFIG_CONTIG )
-                            nBaseByteOffsetInBlock += (nBand-1) * nDTSize;
+                            (nYOffsetInBlock * nBlockXSize + nXOff) *
+                            nBandsPerBlockDTSize;
+                        if( nPlanarConfig == PLANARCONFIG_CONTIG )
+                            nBaseByteOffsetInBlock += (nBand - 1) * nDTSize;
 
                         GByte* pabyLocalData = pabyData + y * nLineSpace;
-                        if( bNoXResamplingNoTypeChange && nPixelSpace == nBandsPerBlockDTSize )
+                        if( bNoXResamplingNoTypeChange &&
+                            nPixelSpace == nBandsPerBlockDTSize )
                         {
                             REACHED(26);
-                            if( !oFetcher.FetchBytes(pabyLocalData,
-                                        nCurOffset + nBaseByteOffsetInBlock,
-                                        (nXSize-1) * nBandsPerBlock + 1, nDTSize,
-                                        bIsByteSwapped, bIsComplex, nBlockId) )
+                            if( !oFetcher.FetchBytes(
+                                pabyLocalData,
+                                nCurOffset + nBaseByteOffsetInBlock,
+                                (nXSize - 1) * nBandsPerBlock + 1, nDTSize,
+                                bIsByteSwapped, bIsComplex, nBlockId) )
                             {
                                 return CE_Failure;
                             }
@@ -3161,7 +3536,7 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                         {
                             const GByte* pabyLocalSrcData = oFetcher.FetchBytes(
                                 nCurOffset + nBaseByteOffsetInBlock,
-                                (nXSize-1) * nBandsPerBlock + 1, nDTSize,
+                                (nXSize - 1) * nBandsPerBlock + 1, nDTSize,
                                 bIsByteSwapped, bIsComplex, nBlockId);
                             if( pabyLocalSrcData == NULL )
                                 return CE_Failure;
@@ -3171,33 +3546,43 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
                                 REACHED(27);
                                 GDALCopyWords(pabyLocalSrcData,
                                               eDataType, nBandsPerBlockDTSize,
-                                              pabyLocalData, eBufType, static_cast<int>(nPixelSpace),
+                                              pabyLocalData, eBufType,
+                                              static_cast<int>(nPixelSpace),
                                               nBufXSize);
                             }
                             else if( bByteOnly )
                             {
                                 REACHED(28);
                                 double dfSrcX = 0.5 * dfSrcXInc;
-                                for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                                for( int x = 0;
+                                     x < nBufXSize;
+                                     ++x, dfSrcX += dfSrcXInc )
                                 {
-                                    int nSrcPixelMinusXOff = (int)dfSrcX;
+                                    const int nSrcPixelMinusXOff =
+                                        static_cast<int>(dfSrcX);
                                     pabyLocalData[x * nPixelSpace] =
-                                        pabyLocalSrcData[nSrcPixelMinusXOff * nBandsPerBlockDTSize];
+                                        pabyLocalSrcData[nSrcPixelMinusXOff *
+                                                         nBandsPerBlockDTSize];
                                 }
                             }
                             else
                             {
                                 REACHED(29);
                                 double dfSrcX = 0.5 * dfSrcXInc;
-                                for(int x=0;x<nBufXSize;x++, dfSrcX += dfSrcXInc)
+                                for( int x = 0;
+                                     x < nBufXSize;
+                                     ++x, dfSrcX += dfSrcXInc )
                                 {
-                                    int nSrcPixelMinusXOff = (int)dfSrcX;
-                                    GDALCopyWords(pabyLocalSrcData +
-                                                    nSrcPixelMinusXOff * nBandsPerBlockDTSize,
-                                                eDataType, 0,
-                                                pabyLocalData + x * nPixelSpace,
-                                                eBufType, 0,
-                                                1);
+                                    const int nSrcPixelMinusXOff =
+                                        static_cast<int>(dfSrcX);
+                                    GDALCopyWords(
+                                        pabyLocalSrcData +
+                                        nSrcPixelMinusXOff *
+                                        nBandsPerBlockDTSize,
+                                        eDataType, 0,
+                                        pabyLocalData + x * nPixelSpace,
+                                        eBufType, 0,
+                                        1 );
                                 }
                             }
                         }
@@ -3214,35 +3599,35 @@ template<class FetchBuffer> CPLErr GTiffDataset::CommonDirectIO(
 /*                           DirectIO()                                 */
 /************************************************************************/
 
-/* Reads directly bytes from the file using ReadMultiRange(), and by-pass */
-/* block reading. Restricted to simple TIFF configurations */
-/* (uncompressed data, standard data types). Particularly useful to extract */
-/* sub-windows of data on a large /vsicurl dataset). */
-/* Returns -1 if DirectIO() can't be supported on that file */
+// Reads directly bytes from the file using ReadMultiRange(), and by-pass
+// block reading. Restricted to simple TIFF configurations
+// (uncompressed data, standard data types). Particularly useful to extract
+// sub-windows of data on a large /vsicurl dataset).
+// Returns -1 if DirectIO() can't be supported on that file.
 
 int GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg )
+                            int nXOff, int nYOff, int nXSize, int nYSize,
+                            void * pData, int nBufXSize, int nBufYSize,
+                            GDALDataType eBufType,
+                            int nBandCount, int *panBandMap,
+                            GSpacing nPixelSpace, GSpacing nLineSpace,
+                            GSpacing nBandSpace,
+                            GDALRasterIOExtraArg* psExtraArg )
 {
     const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
-    const int nDTSizeBits = GDALGetDataTypeSize(eDataType);
+    const int nDTSizeBits = GDALGetDataTypeSizeBits(eDataType);
     if( !(eRWFlag == GF_Read &&
           nCompression == COMPRESSION_NONE &&
           (nPhotometric == PHOTOMETRIC_MINISBLACK ||
            nPhotometric == PHOTOMETRIC_RGB ||
            nPhotometric == PHOTOMETRIC_PALETTE) &&
           nBitsPerSample == nDTSizeBits &&
-          SetDirectory() /* very important to make hTIFF uptodate! */) )
+          SetDirectory() /* Very important to make hTIFF uptodate! */ ) )
     {
         return -1;
     }
 
-    /* we only know how to deal with nearest neighbour in this optimized routine */
+    // Only know how to deal with nearest neighbour in this optimized routine.
     if( (nXSize != nBufXSize || nYSize != nBufYSize) &&
         psExtraArg != NULL &&
         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour )
@@ -3250,8 +3635,8 @@ int GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
         return -1;
     }
 
-    /* if the file is band interleave or only one band is requested, then */
-    /* fallback to band DirectIO */
+    // If the file is band interleave or only one band is requested, then
+    // fallback to band DirectIO.
     bool bUseBandRasterIO = false;
     if( nPlanarConfig == PLANARCONFIG_SEPARATE || nBandCount == 1 )
     {
@@ -3259,8 +3644,8 @@ int GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
     }
     else
     {
-        /* For the sake of simplicity, only deals with "naturally ordered" bands */
-        for(int iBand = 0; iBand < nBandCount; iBand ++ )
+        // For simplicity, only deals with "naturally ordered" bands.
+        for( int iBand = 0; iBand < nBandCount; ++iBand )
         {
             if( panBandMap[iBand] != iBand + 1)
             {
@@ -3272,28 +3657,30 @@ int GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
     if( bUseBandRasterIO )
     {
         CPLErr eErr = CE_None;
-        for(int iBand = 0; eErr == CE_None && iBand < nBandCount; iBand ++ )
+        for( int iBand = 0; eErr == CE_None && iBand < nBandCount; ++iBand )
         {
             eErr = GetRasterBand(panBandMap[iBand])->RasterIO(
-                                       eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                       (GByte*)pData + iBand * nBandSpace,
-                                       nBufXSize, nBufYSize,
-                                       eBufType,
-                                       nPixelSpace, nLineSpace,
-                                       psExtraArg);
+                eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                static_cast<GByte *>(pData) + iBand * nBandSpace,
+                nBufXSize, nBufYSize,
+                eBufType,
+                nPixelSpace, nLineSpace,
+                psExtraArg );
         }
         return eErr;
     }
 
-    /*CPLDebug("GTiff", "DirectIO(%d,%d,%d,%d -> %dx%d)",
-             nXOff, nYOff, nXSize, nYSize,
-             nBufXSize, nBufYSize);*/
+#if DEBUG_VERBOSE
+    CPLDebug( "GTiff", "DirectIO(%d,%d,%d,%d -> %dx%d)",
+              nXOff, nYOff, nXSize, nYSize,
+              nBufXSize, nBufYSize );
+#endif
 
-    /* No need to look if overviews can satisfy the request as it has already */
-    /* been done in GTiffDataset::IRasterIO() */
+    // No need to look if overviews can satisfy the request as it has already */
+    // been done in GTiffDataset::IRasterIO().
 
-    /* Make sure that TIFFTAG_STRIPOFFSETS is up-to-date */
-    if (GetAccess() == GA_Update)
+    // Make sure that TIFFTAG_STRIPOFFSETS is up-to-date.
+    if( GetAccess() == GA_Update )
     {
         FlushCache();
         VSI_TIFFFlushBufferedWrite( TIFFClientdata( hTIFF ) );
@@ -3305,10 +3692,12 @@ int GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
         {
             const int nDTSize = nDTSizeBits / 8;
             m_nTempBufferForCommonDirectIOSize =
-                (size_t)(nBlockXSize * nBlockYSize * nDTSize *
+                static_cast<size_t>(nBlockXSize * nBlockYSize * nDTSize *
                 ((nPlanarConfig == PLANARCONFIG_CONTIG) ? nBands : 1));
 
-            m_pTempBufferForCommonDirectIO = (GByte*)VSI_MALLOC_VERBOSE(m_nTempBufferForCommonDirectIOSize);
+            m_pTempBufferForCommonDirectIO =
+                static_cast<GByte *>(
+                    VSI_MALLOC_VERBOSE(m_nTempBufferForCommonDirectIOSize) );
             if( m_pTempBufferForCommonDirectIO == NULL )
                 return CE_Failure;
         }
@@ -3318,163 +3707,190 @@ int GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
                                      m_nTempBufferForCommonDirectIOSize);
 
         return CommonDirectIO( oFetcher,
-                            nXOff, nYOff, nXSize, nYSize,
-                            pData, nBufXSize, nBufYSize,
-                            eBufType,
-                            nBandCount, panBandMap,
-                            nPixelSpace, nLineSpace,
-                            nBandSpace );
+                               nXOff, nYOff, nXSize, nYSize,
+                               pData, nBufXSize, nBufYSize,
+                               eBufType,
+                               nBandCount, panBandMap,
+                               nPixelSpace, nLineSpace,
+                              nBandSpace );
     }
 
-    /* Get strip offsets */
+    // Get strip offsets.
     toff_t *panTIFFOffsets = NULL;
-    if ( !TIFFGetField( hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
-         panTIFFOffsets == NULL )
+    if( !TIFFGetField( hTIFF, TIFFTAG_STRIPOFFSETS, &panTIFFOffsets ) ||
+        panTIFFOffsets == NULL )
     {
         return CE_Failure;
     }
 
-    int nReqXSize = nXSize; /* sub-sampling or over-sampling can only be done at last stage */
-    int nReqYSize = MIN(nBufYSize, nYSize); /* we can do sub-sampling at the extraction stage */
-    void** ppData = (void**) VSI_MALLOC_VERBOSE(nReqYSize * sizeof(void*));
-    vsi_l_offset* panOffsets = (vsi_l_offset*)
-                            VSI_MALLOC_VERBOSE(nReqYSize * sizeof(vsi_l_offset));
-    size_t* panSizes = (size_t*) VSI_MALLOC_VERBOSE(nReqYSize * sizeof(size_t));
-    int nDTSize = GDALGetDataTypeSize(eDataType) / 8;
+    // Sub-sampling or over-sampling can only be done at last stage.
+    int nReqXSize = nXSize;
+    // Can do sub-sampling at the extraction stage.
+    const int nReqYSize = std::min(nBufYSize, nYSize);
+    void** ppData =
+        static_cast<void **>( VSI_MALLOC_VERBOSE(nReqYSize * sizeof(void*)) );
+    vsi_l_offset* panOffsets =
+        static_cast<vsi_l_offset *>(
+            VSI_MALLOC_VERBOSE(nReqYSize * sizeof(vsi_l_offset)) );
+    size_t* panSizes =
+        static_cast<size_t *>( VSI_MALLOC_VERBOSE(nReqYSize * sizeof(size_t)) );
+    const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
     void* pTmpBuffer = NULL;
     int eErr = CE_None;
     int nContigBands = nBands;
-    int nSrcPixelSize = nDTSize * nContigBands;
+    const int nSrcPixelSize = nDTSize * nContigBands;
 
-    if (ppData == NULL || panOffsets == NULL || panSizes == NULL)
+    if( ppData == NULL || panOffsets == NULL || panSizes == NULL )
+    {
         eErr = CE_Failure;
-    /* For now we always allocate a temp buffer as it's easier */
-    else /*if (nXSize != nBufXSize || nYSize != nBufYSize ||
-             eBufType != eDataType ||
-             nPixelSpace != GDALGetDataTypeSize(eBufType) / 8 ||
-             check if the user buffer is large enough)*/
+    }
+    // For now we always allocate a temp buffer as it's easier.
+    else
+        // if( nXSize != nBufXSize || nYSize != nBufYSize ||
+        //   eBufType != eDataType ||
+        //   nPixelSpace != GDALGetDataTypeSizeBytes(eBufType) ||
+        //   check if the user buffer is large enough )
     {
-        /* We need a temporary buffer for over-sampling/sub-sampling */
-        /* and/or data type conversion */
+        // We need a temporary buffer for over-sampling/sub-sampling
+        // and/or data type conversion.
         pTmpBuffer = VSI_MALLOC_VERBOSE(nReqXSize * nReqYSize * nSrcPixelSize);
-        if (pTmpBuffer == NULL)
+        if( pTmpBuffer == NULL )
             eErr = CE_Failure;
     }
 
-    /* Prepare data extraction */
-    const double dfSrcYInc = nYSize / (double) nBufYSize;
+    // Prepare data extraction.
+    const double dfSrcYInc = nYSize / static_cast<double>( nBufYSize );
 
-    int iLine;
-    for(iLine=0;eErr == CE_None && iLine<nReqYSize;iLine++)
+    for( int iLine = 0; eErr == CE_None && iLine < nReqYSize; ++iLine )
     {
-        /*if (pTmpBuffer == NULL)
-            ppData[iLine] = ((GByte*)pData) + iLine * nLineSpace;
-        else*/
-            ppData[iLine] = ((GByte*)pTmpBuffer) + iLine * nReqXSize * nSrcPixelSize;
-        int nSrcLine;
-        if (nBufYSize < nYSize) /* Sub-sampling in y */
-            nSrcLine = nYOff + (int)((iLine + 0.5) * dfSrcYInc);
+        ppData[iLine] =
+            static_cast<GByte *>(pTmpBuffer) +
+            iLine * nReqXSize * nSrcPixelSize;
+        int nSrcLine = 0;
+        if( nBufYSize < nYSize )  // Sub-sampling in y.
+            nSrcLine = nYOff + static_cast<int>((iLine + 0.5) * dfSrcYInc);
         else
             nSrcLine = nYOff + iLine;
 
-        int nBlockXOff = 0;
-        int nBlockYOff = nSrcLine / nBlockYSize;
-        int nYOffsetInBlock = nSrcLine % nBlockYSize;
-        int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
-        int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+        const int nBlockXOff = 0;
+        const int nBlockYOff = nSrcLine / nBlockYSize;
+        const int nYOffsetInBlock = nSrcLine % nBlockYSize;
+        const int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+        const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
 
         panOffsets[iLine] = panTIFFOffsets[nBlockId];
-        if (panOffsets[iLine] == 0) /* We don't support sparse files */
+        if( panOffsets[iLine] == 0)  // We don't support sparse files.
             eErr = -1;
 
-        panOffsets[iLine] += (nXOff + nYOffsetInBlock * nBlockXSize) * nSrcPixelSize;
+        panOffsets[iLine] +=
+            (nXOff + nYOffsetInBlock * nBlockXSize) * nSrcPixelSize;
         panSizes[iLine] = nReqXSize * nSrcPixelSize;
     }
 
-    /* Extract data from the file */
-    if (eErr == CE_None)
+    // Extract data from the file.
+    if( eErr == CE_None )
     {
         VSILFILE* fp = VSI_TIFFGetVSILFile(TIFFClientdata( hTIFF ));
-        int nRet = VSIFReadMultiRangeL(nReqYSize, ppData, panOffsets, panSizes, fp);
-        if (nRet != 0)
+        const int nRet =
+            VSIFReadMultiRangeL(nReqYSize, ppData, panOffsets, panSizes, fp);
+        if( nRet != 0 )
             eErr = CE_Failure;
     }
 
-    /* Byte-swap if necessary */
-    if (eErr == CE_None && TIFFIsByteSwapped(hTIFF))
+    // Byte-swap if necessary.
+    if( eErr == CE_None && TIFFIsByteSwapped(hTIFF) )
     {
-        for(iLine=0;iLine<nReqYSize;iLine++)
+        for( int iLine = 0; iLine < nReqYSize; ++iLine )
         {
             if( GDALDataTypeIsComplex(eDataType) )
-                GDALSwapWords( ppData[iLine], nDTSize / 2, 2 * nReqXSize * nContigBands, nDTSize / 2);
+                GDALSwapWords( ppData[iLine], nDTSize / 2,
+                               2 * nReqXSize * nContigBands, nDTSize / 2);
             else
-                GDALSwapWords( ppData[iLine], nDTSize, nReqXSize * nContigBands, nDTSize);
+                GDALSwapWords( ppData[iLine], nDTSize,
+                               nReqXSize * nContigBands, nDTSize);
         }
     }
 
-    /* Over-sampling/sub-sampling and/or data type conversion */
-    const double dfSrcXInc = nXSize / (double) nBufXSize;
-    if (eErr == CE_None && pTmpBuffer != NULL)
+    // Over-sampling/sub-sampling and/or data type conversion.
+    const double dfSrcXInc = nXSize / static_cast<double>( nBufXSize );
+    if( eErr == CE_None && pTmpBuffer != NULL )
     {
-        for(int iY=0;iY<nBufYSize;iY++)
+        for( int iY = 0; iY < nBufYSize; ++iY )
         {
-            int iSrcY = (nBufYSize <= nYSize) ? iY :
-                            (int)((iY + 0.5) * dfSrcYInc);
-            /* Optimization: no resampling, no data type change, number of bands requested == number of bands */
-            /* and buffer is packed pixel-interleaved */
-            if (nBufXSize == nXSize && nContigBands == nBandCount &&
+            const int iSrcY =
+                nBufYSize <= nYSize ?
+                iY : static_cast<int>((iY + 0.5) * dfSrcYInc);
+            // Optimization: no resampling, no data type change, number of
+            // bands requested == number of bands and buffer is packed
+            // pixel-interleaved.
+            if( nBufXSize == nXSize && nContigBands == nBandCount &&
                 eDataType == eBufType &&
-                nBandSpace == nDTSize && nPixelSpace == nBandCount * nBandSpace )
+                nBandSpace == nDTSize &&
+                nPixelSpace == nBandCount * nBandSpace )
             {
-                memcpy( ((GByte*)pData) + iY * nLineSpace, ppData[iSrcY],
-                        static_cast<size_t>(nReqXSize * nPixelSpace) );
+                memcpy(
+                    static_cast<GByte *>(pData) + iY * nLineSpace,
+                    ppData[iSrcY],
+                    static_cast<size_t>(nReqXSize * nPixelSpace) );
             }
-            /* Other optimization: no resampling, no data type change, */
-            /* data type is Byte */
-            else if (nBufXSize == nXSize &&
+            // Other optimization: no resampling, no data type change,
+            // data type is Byte.
+            else if( nBufXSize == nXSize &&
                      eDataType == eBufType && eDataType == GDT_Byte )
             {
-                GByte* pabySrcData = ((GByte*)ppData[iSrcY]);
-                GByte* pabyDstData = ((GByte*)pData) + iY * nLineSpace;
+                GByte* pabySrcData = static_cast<GByte *>(ppData[iSrcY]);
+                GByte* pabyDstData =
+                    static_cast<GByte *>(pData) + iY * nLineSpace;
                 if( nBandSpace == 1 && nPixelSpace > nBandCount )
                 {
-                    /* buffer is pixel-interleaved (with some stridding between pixels) */
-                    CopyContigByteMultiBand(pabySrcData, nSrcPixelSize,
-                                            pabyDstData, static_cast<int>(nPixelSpace),
-                                            nBufXSize, nBandCount);
+                    // Buffer is pixel-interleaved (with some stridding
+                    // between pixels).
+                    CopyContigByteMultiBand( pabySrcData, nSrcPixelSize,
+                                             pabyDstData,
+                                             static_cast<int>(nPixelSpace),
+                                             nBufXSize, nBandCount );
                 }
                 else
                 {
-                    for(int iBand = 0; iBand < nBandCount; iBand ++ )
+                    for( int iBand = 0; iBand < nBandCount; ++iBand )
                     {
-                        GDALCopyWords(pabySrcData + iBand, GDT_Byte, nSrcPixelSize,
-                                      pabyDstData + iBand * nBandSpace, GDT_Byte, static_cast<int>(nPixelSpace),
-                                      nBufXSize);
+                        GDALCopyWords(
+                            pabySrcData + iBand, GDT_Byte, nSrcPixelSize,
+                            pabyDstData + iBand * nBandSpace,
+                            GDT_Byte, static_cast<int>(nPixelSpace),
+                            nBufXSize );
                     }
                 }
             }
-            /* General case */
-            else
+            else  // General case.
             {
-                for(int iBand = 0; iBand < nBandCount; iBand ++ )
+                for( int iBand = 0; iBand < nBandCount; ++iBand )
                 {
-                    GByte* pabySrcData = ((GByte*)ppData[iSrcY]) + iBand * nDTSize;
-                    GByte* pabyDstData = ((GByte*)pData) + iBand * nBandSpace + iY * nLineSpace;
+                    GByte* pabySrcData =
+                        static_cast<GByte *>(ppData[iSrcY]) + iBand * nDTSize;
+                    GByte* pabyDstData =
+                        static_cast<GByte *>(pData) +
+                        iBand * nBandSpace + iY * nLineSpace;
                     if( eDataType == GDT_Byte && eBufType == GDT_Byte )
                     {
                         double dfSrcX = 0.5 * dfSrcXInc;
-                        for(int iX=0;iX<nBufXSize;iX++, dfSrcX += dfSrcXInc)
+                        for( int iX = 0;
+                             iX < nBufXSize;
+                             ++iX, dfSrcX += dfSrcXInc)
                         {
-                            int iSrcX = (int)dfSrcX;
-                            pabyDstData[iX * nPixelSpace] = pabySrcData[iSrcX * nSrcPixelSize];
+                            int iSrcX = static_cast<int>(dfSrcX);
+                            pabyDstData[iX * nPixelSpace] =
+                                pabySrcData[iSrcX * nSrcPixelSize];
                         }
                     }
                     else
                     {
                         double dfSrcX = 0.5 * dfSrcXInc;
-                        for(int iX=0;iX<nBufXSize;iX++, dfSrcX += dfSrcXInc)
+                        for( int iX = 0;
+                             iX < nBufXSize;
+                             ++iX, dfSrcX += dfSrcXInc)
                         {
-                            int iSrcX = (int)dfSrcX;
+                            int iSrcX = static_cast<int>(dfSrcX);
                             GDALCopyWords( pabySrcData + iSrcX * nSrcPixelSize,
                                         eDataType, 0,
                                         pabyDstData + iX * nPixelSpace,
@@ -3486,7 +3902,6 @@ int GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
         }
     }
 
-    /* Cleanup */
     CPLFree(pTmpBuffer);
     CPLFree(ppData);
     CPLFree(panOffsets);
@@ -3495,97 +3910,192 @@ int GTiffDataset::DirectIO( GDALRWFlag eRWFlag,
     return eErr;
 }
 
-
 /************************************************************************/
 /*                            IRasterIO()                               */
 /************************************************************************/
 
 CPLErr GTiffRasterBand::IRasterIO( GDALRWFlag eRWFlag,
-                                  int nXOff, int nYOff, int nXSize, int nYSize,
-                                  void * pData, int nBufXSize, int nBufYSize,
-                                  GDALDataType eBufType,
-                                  GSpacing nPixelSpace, GSpacing nLineSpace,
-                                  GDALRasterIOExtraArg* psExtraArg )
+                                   int nXOff, int nYOff, int nXSize, int nYSize,
+                                   void * pData, int nBufXSize, int nBufYSize,
+                                   GDALDataType eBufType,
+                                   GSpacing nPixelSpace, GSpacing nLineSpace,
+                                   GDALRasterIOExtraArg* psExtraArg )
 {
-    CPLErr eErr;
-
-    //CPLDebug("GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)",
-    //         nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize);
+#if DEBUG_VERBOSE
+    CPLDebug( "GTiff", "RasterIO(%d, %d, %d, %d, %d, %d)",
+              nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize );
+#endif
 
-    /* Try to pass the request to the most appropriate overview dataset */
+    // Try to pass the request to the most appropriate overview dataset.
     if( nBufXSize < nXSize && nBufYSize < nYSize )
     {
-        int bTried;
-        poGDS->nJPEGOverviewVisibilityFlag ++;
-        eErr = TryOverviewRasterIO( eRWFlag,
-                                    nXOff, nYOff, nXSize, nYSize,
-                                    pData, nBufXSize, nBufYSize,
-                                    eBufType,
-                                    nPixelSpace, nLineSpace,
-                                    psExtraArg,
-                                    &bTried );
-        poGDS->nJPEGOverviewVisibilityFlag --;
+        int bTried = FALSE;
+        ++poGDS->nJPEGOverviewVisibilityCounter;
+        const CPLErr eErr =
+            TryOverviewRasterIO( eRWFlag,
+                                 nXOff, nYOff, nXSize, nYSize,
+                                 pData, nBufXSize, nBufYSize,
+                                 eBufType,
+                                 nPixelSpace, nLineSpace,
+                                 psExtraArg,
+                                 &bTried );
+        --poGDS->nJPEGOverviewVisibilityCounter;
         if( bTried )
             return eErr;
     }
 
-
     if( poGDS->eVirtualMemIOUsage != VIRTUAL_MEM_IO_NO )
     {
-        int nErr = poGDS->VirtualMemIO(
-                eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                pData, nBufXSize, nBufYSize, eBufType,
-                1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg);
-        if (nErr >= 0)
-            return (CPLErr)nErr;
+        const int nErr = poGDS->VirtualMemIO(
+            eRWFlag, nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize, eBufType,
+            1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg);
+        if( nErr >= 0 )
+            return static_cast<CPLErr>(nErr);
     }
-    if (poGDS->bDirectIO)
+    if( poGDS->bDirectIO )
     {
         int nErr = DirectIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                        pData, nBufXSize, nBufYSize, eBufType,
-                        nPixelSpace, nLineSpace, psExtraArg);
-        if (nErr >= 0)
-            return (CPLErr)nErr;
+                            pData, nBufXSize, nBufYSize, eBufType,
+                            nPixelSpace, nLineSpace, psExtraArg);
+        if( nErr >= 0 )
+            return static_cast<CPLErr>(nErr);
     }
 
-    if (poGDS->nBands != 1 &&
+    if( poGDS->nBands != 1 &&
         poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
         eRWFlag == GF_Read &&
-        nXSize == nBufXSize && nYSize == nBufYSize)
-    {
-        int nBlockX1 = nXOff / nBlockXSize;
-        int nBlockY1 = nYOff / nBlockYSize;
-        int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
-        int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
-        int nXBlocks = nBlockX2 - nBlockX1 + 1;
-        int nYBlocks = nBlockY2 - nBlockY1 + 1;
-        GIntBig nRequiredMem = (GIntBig)poGDS->nBands * nXBlocks * nYBlocks *
-                                nBlockXSize * nBlockYSize *
-                               (GDALGetDataTypeSize(eDataType) / 8);
-        if (nRequiredMem > GDALGetCacheMax64())
-        {
-            if (!poGDS->bHasWarnedDisableAggressiveBandCaching)
+        nXSize == nBufXSize && nYSize == nBufYSize )
+    {
+        const int nBlockX1 = nXOff / nBlockXSize;
+        const int nBlockY1 = nYOff / nBlockYSize;
+        const int nBlockX2 = (nXOff + nXSize - 1) / nBlockXSize;
+        const int nBlockY2 = (nYOff + nYSize - 1) / nBlockYSize;
+        const int nXBlocks = nBlockX2 - nBlockX1 + 1;
+        const int nYBlocks = nBlockY2 - nBlockY1 + 1;
+        const GIntBig nRequiredMem =
+            static_cast<GIntBig>(poGDS->nBands) * nXBlocks * nYBlocks *
+            nBlockXSize * nBlockYSize *
+            GDALGetDataTypeSizeBytes(eDataType);
+        if( nRequiredMem > GDALGetCacheMax64() )
+        {
+            if( !poGDS->bHasWarnedDisableAggressiveBandCaching )
             {
-                CPLDebug("GTiff", "Disable aggressive band caching. Cache not big enough. "
-                         "At least " CPL_FRMT_GIB " bytes necessary", nRequiredMem);
-                poGDS->bHasWarnedDisableAggressiveBandCaching = TRUE;
+                CPLDebug( "GTiff",
+                          "Disable aggressive band caching. "
+                          "Cache not big enough. "
+                          "At least " CPL_FRMT_GIB " bytes necessary",
+                          nRequiredMem );
+                poGDS->bHasWarnedDisableAggressiveBandCaching = true;
             }
-            poGDS->bLoadingOtherBands = TRUE;
+            poGDS->bLoadingOtherBands = true;
         }
     }
 
-    poGDS->nJPEGOverviewVisibilityFlag ++;
-    eErr = GDALPamRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                        pData, nBufXSize, nBufYSize, eBufType,
-                                        nPixelSpace, nLineSpace, psExtraArg);
-    poGDS->nJPEGOverviewVisibilityFlag --;
+    ++poGDS->nJPEGOverviewVisibilityCounter;
+    const CPLErr eErr =
+        GDALPamRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                      pData, nBufXSize, nBufYSize, eBufType,
+                                      nPixelSpace, nLineSpace, psExtraArg );
+    --poGDS->nJPEGOverviewVisibilityCounter;
 
-    poGDS->bLoadingOtherBands = FALSE;
+    poGDS->bLoadingOtherBands = false;
 
     return eErr;
 }
 
 /************************************************************************/
+/*                       IGetDataCoverageStatus()                       */
+/************************************************************************/
+
+int GTiffRasterBand::IGetDataCoverageStatus( int nXOff, int nYOff,
+                                             int nXSize, int nYSize,
+                                             int nMaskFlagStop,
+                                             double* pdfDataPct)
+{
+    if( eAccess == GA_Update )
+        poGDS->FlushCache();
+
+    const int iXBlockStart = nXOff / nBlockXSize;
+    const int iXBlockEnd = (nXOff + nXSize - 1) / nBlockXSize;
+    const int iYBlockStart = nYOff / nBlockYSize;
+    const int iYBlockEnd = (nYOff + nYSize - 1) / nBlockYSize;
+    int nStatus = 0;
+    VSILFILE* fp = VSI_TIFFGetVSILFile(TIFFClientdata( poGDS->hTIFF ));
+    GIntBig nPixelsData = 0;
+    // We need to compute this here as it might not have been computed
+    // previously (which sucks...)
+    nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+    for( int iY = iYBlockStart; iY <= iYBlockEnd; ++iY )
+    {
+        for( int iX = iXBlockStart; iX <= iXBlockEnd; ++iX )
+        {
+            const int nBlockIdBand0 =
+                iX + iY * nBlocksPerRow;
+            int nBlockId = nBlockIdBand0;
+            if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
+                nBlockId = nBlockIdBand0 + (nBand - 1) * poGDS->nBlocksPerBand;
+            vsi_l_offset nOffset = 0;
+            vsi_l_offset nLength = 0;
+            bool bHasData = false;
+            if( !poGDS->IsBlockAvailable(nBlockId,&nOffset,&nLength) )
+            {
+                nStatus |= GDAL_DATA_COVERAGE_STATUS_EMPTY;
+            }
+            else
+            {
+                if( poGDS->nCompression == COMPRESSION_NONE &&
+                    poGDS->eAccess == GA_ReadOnly &&
+                    (!bNoDataSet || dfNoDataValue == 0.0) )
+                {
+                    VSIRangeStatus eStatus =
+                          VSIFGetRangeStatusL( fp, nOffset, nLength );
+                    if( eStatus == VSI_RANGE_STATUS_HOLE )
+                    {
+                        nStatus |= GDAL_DATA_COVERAGE_STATUS_EMPTY;
+                    }
+                    else
+                    {
+                        bHasData = true;
+                    }
+                }
+                else
+                {
+                    bHasData = true;
+                }
+            }
+            if( bHasData )
+            {
+                const int nXBlockRight =
+                    ( iX * nBlockXSize > INT_MAX - nBlockXSize ) ? INT_MAX :
+                    (iX + 1) * nBlockXSize;
+                const int nYBlockBottom =
+                    ( iY * nBlockYSize > INT_MAX - nBlockYSize ) ? INT_MAX :
+                    (iY + 1) * nBlockYSize;
+
+                nPixelsData +=
+                    (std::min( nXBlockRight, nXOff + nXSize ) -
+                     std::max( iX * nBlockXSize, nXOff )) *
+                    (std::min( nYBlockBottom, nYOff + nYSize ) -
+                     std::max( iY * nBlockYSize, nYOff ));
+                nStatus |= GDAL_DATA_COVERAGE_STATUS_DATA;
+            }
+            if( nMaskFlagStop != 0 && (nMaskFlagStop & nStatus) != 0 )
+            {
+                if( pdfDataPct )
+                    *pdfDataPct = -1.0;
+                return nStatus;
+            }
+        }
+    }
+    if( pdfDataPct )
+        *pdfDataPct =
+          100.0 * nPixelsData /
+          (static_cast<GIntBig>(nXSize) * nYSize);
+    return nStatus;
+}
+
+/************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
@@ -3593,14 +4103,14 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                     void * pImage )
 
 {
-    int nBlockBufSize, nBlockId, nBlockIdBand0;
-    CPLErr eErr = CE_None;
-
-    if (!poGDS->SetDirectory())
+    if( !poGDS->SetDirectory() )
         return CE_Failure;
 
+    int nBlockBufSize = 0;
     if( TIFFIsTiled(poGDS->hTIFF) )
+    {
         nBlockBufSize = static_cast<int>(TIFFTileSize( poGDS->hTIFF ));
+    }
     else
     {
         CPLAssert( nBlockXOff == 0 );
@@ -3608,11 +4118,11 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     }
 
     CPLAssert(nBlocksPerRow != 0);
-    nBlockIdBand0 = nBlockXOff + nBlockYOff * nBlocksPerRow;
+    const int nBlockIdBand0 =
+        nBlockXOff + nBlockYOff * nBlocksPerRow;
+    int nBlockId = nBlockIdBand0;
     if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
-        nBlockId = nBlockIdBand0 + (nBand-1) * poGDS->nBlocksPerBand;
-    else
-        nBlockId = nBlockIdBand0;
+        nBlockId = nBlockIdBand0 + (nBand - 1) * poGDS->nBlocksPerBand;
 
 /* -------------------------------------------------------------------- */
 /*      The bottom most partial tiles and strips are sometimes only     */
@@ -3621,10 +4131,12 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     int nBlockReqSize = nBlockBufSize;
 
-    if( (nBlockYOff+1) * nBlockYSize > nRasterYSize )
+    if( nBlockYOff * nBlockYSize > nRasterYSize - nBlockYSize )
     {
         nBlockReqSize = (nBlockBufSize / nBlockYSize)
-            * (nBlockYSize - (((nBlockYOff+1) * nBlockYSize) % nRasterYSize));
+            * (nBlockYSize - static_cast<int>(
+                (static_cast<GIntBig>(nBlockYOff + 1) * nBlockYSize)
+                    % nRasterYSize));
     }
 
     poGDS->WaitCompletionForBlock(nBlockId);
@@ -3633,26 +4145,27 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      Handle the case of a strip or tile that doesn't exist yet.      */
 /*      Just set to zeros and return.                                   */
 /* -------------------------------------------------------------------- */
-    if( nBlockId != poGDS->nLoadedBlock && !poGDS->IsBlockAvailable(nBlockId) )
+    vsi_l_offset nOffset = 0;
+    if( nBlockId != poGDS->nLoadedBlock &&
+        !poGDS->IsBlockAvailable(nBlockId, &nOffset) )
     {
         NullBlock( pImage );
         return CE_None;
     }
 
     if( poGDS->bStreamingIn &&
-        !(poGDS->nBands > 1 && poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && nBlockId == poGDS->nLoadedBlock) )
+        !(poGDS->nBands > 1 &&
+          poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
+          nBlockId == poGDS->nLoadedBlock) )
     {
-        toff_t* panOffsets = NULL;
-        TIFFGetField( poGDS->hTIFF, (TIFFIsTiled( poGDS->hTIFF )) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS , &panOffsets );
-        if( panOffsets == NULL )
-            return CE_Failure;
-        if( panOffsets[nBlockId] < VSIFTellL(poGDS->fpL) )
+        if( nOffset < VSIFTellL(poGDS->fpL) )
         {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "Trying to load block %d at offset " CPL_FRMT_GUIB
-                     " whereas current pos is " CPL_FRMT_GUIB " (backward read not supported)",
-                     nBlockId, (GUIntBig)panOffsets[nBlockId],
-                     (GUIntBig)VSIFTellL(poGDS->fpL) );
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Trying to load block %d at offset " CPL_FRMT_GUIB
+                      " whereas current pos is " CPL_FRMT_GUIB
+                      " (backward read not supported)",
+                      nBlockId, static_cast<GUIntBig>(nOffset),
+                      static_cast<GUIntBig>(VSIFTellL(poGDS->fpL)) );
             return CE_Failure;
         }
     }
@@ -3666,6 +4179,7 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         if( nBlockReqSize < nBlockBufSize )
             memset( pImage, 0, nBlockBufSize );
 
+        CPLErr eErr = CE_None;
         if( TIFFIsTiled( poGDS->hTIFF ) )
         {
             if( TIFFReadEncodedTile( poGDS->hTIFF, nBlockId, pImage,
@@ -3674,7 +4188,7 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             {
                 memset( pImage, 0, nBlockBufSize );
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "TIFFReadEncodedTile() failed.\n" );
+                          "TIFFReadEncodedTile() failed." );
 
                 eErr = CE_Failure;
             }
@@ -3687,7 +4201,7 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             {
                 memset( pImage, 0, nBlockBufSize );
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "TIFFReadEncodedStrip() failed.\n" );
+                        "TIFFReadEncodedStrip() failed." );
 
                 eErr = CE_Failure;
             }
@@ -3699,68 +4213,35 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Load desired block                                              */
 /* -------------------------------------------------------------------- */
-    eErr = poGDS->LoadBlockBuf( nBlockId );
-    if( eErr != CE_None )
     {
-        memset( pImage, 0,
-                nBlockXSize * nBlockYSize
-                * (GDALGetDataTypeSize(eDataType) / 8) );
-        return eErr;
+        const CPLErr eErr = poGDS->LoadBlockBuf( nBlockId );
+        if( eErr != CE_None )
+        {
+            memset( pImage, 0,
+                    nBlockXSize * nBlockYSize
+                    * GDALGetDataTypeSizeBytes(eDataType) );
+            return eErr;
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Special case for YCbCr subsampled data.                         */
 /* -------------------------------------------------------------------- */
-#ifdef notdef
-    if( (eBandInterp == GCI_YCbCr_YBand
-         || eBandInterp == GCI_YCbCr_CbBand
-         ||  eBandInterp == GCI_YCbCr_CrBand)
-        && poGDS->nBitsPerSample == 8 )
-    {
-        uint16 hs, vs;
-        int iX, iY;
-
-        TIFFGetFieldDefaulted( poGDS->hTIFF, TIFFTAG_YCBCRSUBSAMPLING,
-                               &hs, &vs);
-
-        for( iY = 0; iY < nBlockYSize; iY++ )
-        {
-            for( iX = 0; iX < nBlockXSize; iX++ )
-            {
-                int iBlock = (iY / vs) * (nBlockXSize/hs) + (iX / hs);
-                GByte *pabySrcBlock = poGDS->pabyBlockBuf +
-                    (vs * hs + 2) * iBlock;
 
-                if( eBandInterp == GCI_YCbCr_YBand )
-                    ((GByte *)pImage)[iY*nBlockXSize + iX] =
-                        pabySrcBlock[(iX % hs) + (iY % vs) * hs];
-                else if( eBandInterp == GCI_YCbCr_CbBand )
-                    ((GByte *)pImage)[iY*nBlockXSize + iX] =
-                        pabySrcBlock[vs * hs + 0];
-                else if( eBandInterp == GCI_YCbCr_CrBand )
-                    ((GByte *)pImage)[iY*nBlockXSize + iX] =
-                        pabySrcBlock[vs * hs + 1];
-            }
-        }
-
-        return CE_None;
-    }
-#endif
+    // Removed "Special case for YCbCr" added in r9432; disabled in r9470
 
-    int nWordBytes = poGDS->nBitsPerSample / 8;
+    const int nWordBytes = poGDS->nBitsPerSample / 8;
     GByte* pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
 
     GDALCopyWords(pabyImage, eDataType, poGDS->nBands * nWordBytes,
                   pImage, eDataType, nWordBytes,
                   nBlockXSize * nBlockYSize);
 
-    if (eErr == CE_None)
-        eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
+    const CPLErr eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
 
     return eErr;
 }
 
-
 /************************************************************************/
 /*                       FillCacheForOtherBands()                       */
 /************************************************************************/
@@ -3768,7 +4249,6 @@ CPLErr GTiffRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 CPLErr GTiffRasterBand::FillCacheForOtherBands( int nBlockXOff, int nBlockYOff )
 
 {
-    CPLErr eErr = CE_None;
 /* -------------------------------------------------------------------- */
 /*      In the fairly common case of pixel interleaved 8bit data        */
 /*      that is multi-band, lets push the rest of the data into the     */
@@ -3785,23 +4265,21 @@ CPLErr GTiffRasterBand::FillCacheForOtherBands( int nBlockXOff, int nBlockYOff )
 /*      If there are many bands and the block cache size is not big     */
 /*      enough to accommodate the size of all the blocks, don't enter   */
 /* -------------------------------------------------------------------- */
+    CPLErr eErr = CE_None;
     if( poGDS->nBands != 1 && !poGDS->bLoadingOtherBands &&
-        nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8) < GDALGetCacheMax64() / poGDS->nBands)
+        nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType) <
+        GDALGetCacheMax64() / poGDS->nBands )
     {
-        int iOtherBand;
+        poGDS->bLoadingOtherBands = true;
 
-        poGDS->bLoadingOtherBands = TRUE;
-
-        for( iOtherBand = 1; iOtherBand <= poGDS->nBands; iOtherBand++ )
+        for( int iOtherBand = 1; iOtherBand <= poGDS->nBands; ++iOtherBand )
         {
             if( iOtherBand == nBand )
                 continue;
 
-            GDALRasterBlock *poBlock;
-
-            poBlock = poGDS->GetRasterBand(iOtherBand)->
+            GDALRasterBlock *poBlock = poGDS->GetRasterBand(iOtherBand)->
                 GetLockedBlockRef(nBlockXOff,nBlockYOff);
-            if (poBlock == NULL)
+            if( poBlock == NULL )
             {
                 eErr = CE_Failure;
                 break;
@@ -3809,7 +4287,7 @@ CPLErr GTiffRasterBand::FillCacheForOtherBands( int nBlockXOff, int nBlockYOff )
             poBlock->DropLock();
         }
 
-        poGDS->bLoadingOtherBands = FALSE;
+        poGDS->bLoadingOtherBands = false;
     }
 
     return eErr;
@@ -3823,21 +4301,18 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                      void * pImage )
 
 {
-    int nBlockId;
-    CPLErr      eErr = CE_None;
-
-    if (poGDS->bDebugDontWriteBlocks)
+    if( poGDS->bDebugDontWriteBlocks )
         return CE_None;
 
-    if (poGDS->bWriteErrorInFlushBlockBuf)
+    if( poGDS->bWriteErrorInFlushBlockBuf )
     {
-        /* Report as an error if a previously loaded block couldn't be */
-        /* written correctly */
-        poGDS->bWriteErrorInFlushBlockBuf = FALSE;
+        // Report as an error if a previously loaded block couldn't be written
+        // correctly.
+        poGDS->bWriteErrorInFlushBlockBuf = false;
         return CE_Failure;
     }
 
-    if (!poGDS->SetDirectory())
+    if( !poGDS->SetDirectory() )
         return CE_Failure;
 
     CPLAssert( poGDS != NULL
@@ -3852,10 +4327,11 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE
         || poGDS->nBands == 1 )
     {
-        nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow
-            + (nBand-1) * poGDS->nBlocksPerBand;
+        const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow
+            + (nBand - 1) * poGDS->nBlocksPerBand;
 
-        eErr = poGDS->WriteEncodedTileOrStrip(nBlockId, pImage, TRUE);
+        const CPLErr eErr =
+            poGDS->WriteEncodedTileOrStrip(nBlockId, pImage, true);
 
         return eErr;
     }
@@ -3863,32 +4339,91 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Handle case of pixel interleaved (PLANARCONFIG_CONTIG) images.  */
 /* -------------------------------------------------------------------- */
-    nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+    const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+     // Why 10 ? Somewhat arbitrary
+    static const int MAX_BANDS_FOR_DIRTY_CHECK = 10;
+    GDALRasterBlock* apoBlocks[MAX_BANDS_FOR_DIRTY_CHECK] = {};
+    const int nBands = poGDS->nBands;
+    bool bAllBlocksDirty = false;
 
-    eErr = poGDS->LoadBlockBuf( nBlockId );
-    if( eErr != CE_None )
-        return eErr;
+/* -------------------------------------------------------------------- */
+/*     If all blocks are cached and dirty then we do not need to reload */
+/*     the tile/strip from disk                                         */
+/* -------------------------------------------------------------------- */
+    if( nBands <= MAX_BANDS_FOR_DIRTY_CHECK )
+    {
+        bAllBlocksDirty = true;
+        for( int iBand = 0; iBand < nBands; ++iBand )
+        {
+            if( iBand + 1 != nBand )
+            {
+                apoBlocks[iBand] =
+                    reinterpret_cast<GTiffRasterBand *>(
+                        poGDS->GetRasterBand( iBand + 1 ))
+                            ->TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
+
+                if( apoBlocks[iBand] == NULL )
+                {
+                    bAllBlocksDirty = false;
+                }
+                else if( !apoBlocks[iBand]->GetDirty() )
+                {
+                    apoBlocks[iBand]->DropLock();
+                    apoBlocks[iBand] = NULL;
+                    bAllBlocksDirty = false;
+                }
+            }
+            else
+                apoBlocks[iBand] = NULL;
+        }
+#if DEBUG_VERBOSE
+        if( bAllBlocksDirty )
+            CPLDebug("GTIFF", "Saved reloading block %d", nBlockId);
+        else
+            CPLDebug("GTIFF", "Must reload block %d", nBlockId);
+#endif
+    }
+
+    {
+        const CPLErr eErr = poGDS->LoadBlockBuf( nBlockId, !bAllBlocksDirty );
+        if( eErr != CE_None )
+        {
+            if( nBands <= MAX_BANDS_FOR_DIRTY_CHECK )
+            {
+                for( int iBand = 0; iBand < nBands; ++iBand )
+                {
+                    if( apoBlocks[iBand] != NULL )
+                        apoBlocks[iBand]->DropLock();
+                }
+            }
+            return eErr;
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      On write of pixel interleaved data, we might as well flush      */
 /*      out any other bands that are dirty in our cache.  This is       */
 /*      especially helpful when writing compressed blocks.              */
 /* -------------------------------------------------------------------- */
-    int iBand;
-    int nWordBytes = poGDS->nBitsPerSample / 8;
-    int nBands = poGDS->nBands;
+    const int nWordBytes = poGDS->nBitsPerSample / 8;
 
-    for( iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < nBands; ++iBand )
     {
         const GByte *pabyThisImage = NULL;
         GDALRasterBlock *poBlock = NULL;
 
-        if( iBand+1 == nBand )
-            pabyThisImage = (GByte *) pImage;
+        if( iBand + 1 == nBand )
+        {
+            pabyThisImage = static_cast<GByte *>( pImage );
+        }
         else
         {
-            poBlock = ((GTiffRasterBand *)poGDS->GetRasterBand( iBand+1 ))
-                ->TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
+            if( nBands <= MAX_BANDS_FOR_DIRTY_CHECK )
+                poBlock = apoBlocks[iBand];
+            else
+                poBlock = reinterpret_cast<GTiffRasterBand *>(
+                    poGDS->GetRasterBand( iBand + 1 ))
+                        ->TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
 
             if( poBlock == NULL )
                 continue;
@@ -3899,7 +4434,7 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 continue;
             }
 
-            pabyThisImage = (GByte *) poBlock->GetDataRef();
+            pabyThisImage = static_cast<GByte *>( poBlock->GetDataRef() );
         }
 
         GByte *pabyOut = poGDS->pabyBlockBuf + iBand*nWordBytes;
@@ -3915,7 +4450,16 @@ CPLErr GTiffRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         }
     }
 
-    poGDS->bLoadedBlockDirty = TRUE;
+    if( bAllBlocksDirty )
+    {
+        // We can synchronously write the block now.
+        const CPLErr eErr =
+            poGDS->WriteEncodedTileOrStrip(nBlockId, poGDS->pabyBlockBuf, true);
+        poGDS->bLoadedBlockDirty = false;
+        return eErr;
+    }
+
+    poGDS->bLoadedBlockDirty = true;
 
     return CE_None;
 }
@@ -3973,9 +4517,9 @@ CPLErr GTiffRasterBand::SetOffset( double dfNewValue )
     poGDS->LoadGeoreferencingAndPamIfNeeded();
 
     if( !bHaveOffsetScale || dfNewValue != dfOffset )
-        poGDS->bMetadataChanged = TRUE;
+        poGDS->bMetadataChanged = true;
 
-    bHaveOffsetScale = TRUE;
+    bHaveOffsetScale = true;
     dfOffset = dfNewValue;
     return CE_None;
 }
@@ -4004,9 +4548,9 @@ CPLErr GTiffRasterBand::SetScale( double dfNewValue )
     poGDS->LoadGeoreferencingAndPamIfNeeded();
 
     if( !bHaveOffsetScale || dfNewValue != dfScale )
-        poGDS->bMetadataChanged = TRUE;
+        poGDS->bMetadataChanged = true;
 
-    bHaveOffsetScale = TRUE;
+    bHaveOffsetScale = true;
     dfScale = dfNewValue;
     return CE_None;
 }
@@ -4019,6 +4563,11 @@ const char* GTiffRasterBand::GetUnitType()
 
 {
     poGDS->LoadGeoreferencingAndPamIfNeeded();
+    if( osUnitType.empty() )
+    {
+        poGDS->LookForProjection();
+        return poGDS->m_osVertUnit.c_str();
+    }
 
     return osUnitType.c_str();
 }
@@ -4034,7 +4583,7 @@ CPLErr GTiffRasterBand::SetUnitType( const char* pszNewValue )
 
     CPLString osNewValue(pszNewValue ? pszNewValue : "");
     if( osNewValue.compare(osUnitType) != 0 )
-        poGDS->bMetadataChanged = TRUE;
+        poGDS->bMetadataChanged = true;
 
     osUnitType = osNewValue;
     return CE_None;
@@ -4077,8 +4626,9 @@ CPLErr GTiffRasterBand::SetMetadata( char ** papszMD, const char *pszDomain )
 
     if( poGDS->bStreamingOut && poGDS->bCrystalized )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot modify metadata at that point in a streamed output file");
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Cannot modify metadata at that point in a streamed "
+                  "output file" );
         return CE_Failure;
     }
 
@@ -4086,8 +4636,8 @@ CPLErr GTiffRasterBand::SetMetadata( char ** papszMD, const char *pszDomain )
     {
         if( papszMD != NULL || GetMetadata(pszDomain) != NULL )
         {
-            poGDS->bMetadataChanged = TRUE;
-            // Cancel any existing metadata from PAM file
+            poGDS->bMetadataChanged = true;
+            // Cancel any existing metadata from PAM file.
             if( eAccess == GA_Update &&
                 GDALPamRasterBand::GetMetadata(pszDomain) != NULL )
                 GDALPamRasterBand::SetMetadata(NULL, pszDomain);
@@ -4112,7 +4662,8 @@ const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
 
     if( pszName != NULL && pszDomain != NULL && EQUAL(pszDomain, "TIFF") )
     {
-        int nBlockXOff, nBlockYOff;
+        int nBlockXOff = 0;
+        int nBlockYOff = 0;
 
         if( EQUAL(pszName, "JPEGTABLES") )
         {
@@ -4121,23 +4672,39 @@ const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
 
             uint32 nJPEGTableSize = 0;
             void* pJPEGTable = NULL;
-            if( TIFFGetField(poGDS->hTIFF, TIFFTAG_JPEGTABLES, &nJPEGTableSize, &pJPEGTable) != 1 ||
-                pJPEGTable == NULL || (int)nJPEGTableSize <= 0 )
+            if( TIFFGetField( poGDS->hTIFF, TIFFTAG_JPEGTABLES,
+                              &nJPEGTableSize, &pJPEGTable ) != 1 ||
+                pJPEGTable == NULL || nJPEGTableSize > INT_MAX )
             {
                 return NULL;
             }
-            char* pszHex = CPLBinaryToHex( nJPEGTableSize, (const GByte*)pJPEGTable );
+            char* const pszHex =
+                CPLBinaryToHex( nJPEGTableSize, (const GByte*)pJPEGTable );
             const char* pszReturn = CPLSPrintf("%s", pszHex);
             CPLFree(pszHex);
+
             return pszReturn;
         }
-        else if( sscanf(pszName, "BLOCK_OFFSET_%d_%d", &nBlockXOff, &nBlockYOff) == 2 )
+
+        if( EQUAL(pszName, "IFD_OFFSET") )
+        {
+            if( !poGDS->SetDirectory() )
+                return NULL;
+
+            return CPLSPrintf( CPL_FRMT_GUIB,
+                               static_cast<GUIntBig>(poGDS->nDirOffset) );
+        }
+
+        if( sscanf( pszName, "BLOCK_OFFSET_%d_%d",
+                         &nBlockXOff, &nBlockYOff ) == 2 )
         {
             if( !poGDS->SetDirectory() )
                 return NULL;
 
-            nBlocksPerRow = DIV_ROUND_UP(poGDS->nRasterXSize, poGDS->nBlockXSize);
-            nBlocksPerColumn = DIV_ROUND_UP(poGDS->nRasterYSize, poGDS->nBlockYSize);
+            nBlocksPerRow =
+                DIV_ROUND_UP(poGDS->nRasterXSize, poGDS->nBlockXSize);
+            nBlocksPerColumn =
+                DIV_ROUND_UP(poGDS->nRasterYSize, poGDS->nBlockYSize);
             if( nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn )
                 return NULL;
@@ -4145,36 +4712,28 @@ const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
             int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
             if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
             {
-                nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
+                nBlockId += (nBand - 1) * poGDS->nBlocksPerBand;
             }
 
-            if( !poGDS->IsBlockAvailable(nBlockId) )
+            vsi_l_offset nOffset = 0;
+            if( !poGDS->IsBlockAvailable(nBlockId, &nOffset) )
             {
                 return NULL;
             }
 
-            toff_t *panOffsets = NULL;
-            TIFF* hTIFF = poGDS->hTIFF;
-            if( (( TIFFIsTiled( hTIFF )
-                && TIFFGetField( hTIFF, TIFFTAG_TILEOFFSETS, &panOffsets ) )
-                || ( !TIFFIsTiled( hTIFF )
-                && TIFFGetField( hTIFF, TIFFTAG_STRIPOFFSETS, &panOffsets ) )) &&
-                panOffsets != NULL )
-            {
-                return CPLSPrintf(CPL_FRMT_GUIB, (GUIntBig)panOffsets[nBlockId]);
-            }
-            else
-            {
-                return NULL;
-            }
+            return CPLSPrintf( CPL_FRMT_GUIB, static_cast<GUIntBig>(nOffset) );
         }
-        else if( sscanf(pszName, "BLOCK_SIZE_%d_%d", &nBlockXOff, &nBlockYOff) == 2 )
+
+        if( sscanf( pszName, "BLOCK_SIZE_%d_%d",
+                    &nBlockXOff, &nBlockYOff ) == 2 )
         {
             if( !poGDS->SetDirectory() )
                 return NULL;
 
-            nBlocksPerRow = DIV_ROUND_UP(poGDS->nRasterXSize, poGDS->nBlockXSize);
-            nBlocksPerColumn = DIV_ROUND_UP(poGDS->nRasterYSize, poGDS->nBlockYSize);
+            nBlocksPerRow =
+                DIV_ROUND_UP(poGDS->nRasterXSize, poGDS->nBlockXSize);
+            nBlocksPerColumn =
+                DIV_ROUND_UP(poGDS->nRasterYSize, poGDS->nBlockYSize);
             if( nBlockXOff < 0 || nBlockXOff >= nBlocksPerRow ||
                 nBlockYOff < 0 || nBlockYOff >= nBlocksPerColumn )
                 return NULL;
@@ -4182,28 +4741,16 @@ const char *GTiffRasterBand::GetMetadataItem( const char * pszName,
             int nBlockId = nBlockYOff * nBlocksPerRow + nBlockXOff;
             if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
             {
-                nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
+                nBlockId += (nBand - 1) * poGDS->nBlocksPerBand;
             }
 
-            if( !poGDS->IsBlockAvailable(nBlockId) )
+            vsi_l_offset nByteCount = 0;
+            if( !poGDS->IsBlockAvailable(nBlockId, NULL, &nByteCount) )
             {
                 return NULL;
             }
 
-            toff_t *panByteCounts = NULL;
-            TIFF* hTIFF = poGDS->hTIFF;
-            if( (( TIFFIsTiled( hTIFF )
-                && TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts ) )
-                || ( !TIFFIsTiled( hTIFF )
-                && TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts ) )) &&
-                panByteCounts != NULL )
-            {
-                return CPLSPrintf(CPL_FRMT_GUIB, (GUIntBig)panByteCounts[nBlockId]);
-            }
-            else
-            {
-                return NULL;
-            }
+            return CPLSPrintf(CPL_FRMT_GUIB, static_cast<GUIntBig>(nByteCount));
         }
     }
     return oGTiffMDMD.GetMetadataItem( pszName, pszDomain );
@@ -4222,15 +4769,16 @@ CPLErr GTiffRasterBand::SetMetadataItem( const char *pszName,
 
     if( poGDS->bStreamingOut && poGDS->bCrystalized )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot modify metadata at that point in a streamed output file");
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Cannot modify metadata at that point in a streamed "
+                  "output file" );
         return CE_Failure;
     }
 
     if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
     {
-        poGDS->bMetadataChanged = TRUE;
-        // Cancel any existing metadata from PAM file
+        poGDS->bMetadataChanged = true;
+        // Cancel any existing metadata from PAM file.
         if( eAccess == GA_Update &&
             GDALPamRasterBand::GetMetadataItem(pszName, pszDomain) != NULL )
             GDALPamRasterBand::SetMetadataItem(pszName, NULL, pszDomain);
@@ -4255,24 +4803,24 @@ GDALColorInterp GTiffRasterBand::GetColorInterpretation()
 /*                         GTiffGetAlphaValue()                         */
 /************************************************************************/
 
- /* Note: was EXTRASAMPLE_ASSOCALPHA in GDAL < 1.10 */
-#define DEFAULT_ALPHA_TYPE              EXTRASAMPLE_UNASSALPHA
+// Note: Was EXTRASAMPLE_ASSOCALPHA in GDAL < 1.10.
+static const uint16 DEFAULT_ALPHA_TYPE = EXTRASAMPLE_UNASSALPHA;
 
 static uint16 GTiffGetAlphaValue(const char* pszValue, uint16 nDefault)
 {
-    if (pszValue == NULL)
+    if( pszValue == NULL )
         return nDefault;
-    else if (EQUAL(pszValue, "YES"))
+    if( EQUAL(pszValue, "YES") )
         return DEFAULT_ALPHA_TYPE;
-    else if (EQUAL(pszValue, "PREMULTIPLIED"))
+    if( EQUAL(pszValue, "PREMULTIPLIED") )
         return EXTRASAMPLE_ASSOCALPHA;
-    else if (EQUAL(pszValue, "NON-PREMULTIPLIED"))
+    if( EQUAL(pszValue, "NON-PREMULTIPLIED") )
         return EXTRASAMPLE_UNASSALPHA;
-    else if (EQUAL(pszValue, "NO") ||
-             EQUAL(pszValue, "UNSPECIFIED"))
+    if( EQUAL(pszValue, "NO") ||
+        EQUAL(pszValue, "UNSPECIFIED") )
         return EXTRASAMPLE_UNSPECIFIED;
-    else
-        return nDefault;
+
+    return nDefault;
 }
 
 /************************************************************************/
@@ -4291,30 +4839,32 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
 
     if( poGDS->bCrystalized )
     {
-        CPLDebug("GTIFF", "ColorInterpretation %s for band %d goes to PAM instead of TIFF tag",
-                 GDALGetColorInterpretationName(eInterp), nBand);
+        CPLDebug( "GTIFF", "ColorInterpretation %s for band %d goes to PAM "
+                  "instead of TIFF tag",
+                  GDALGetColorInterpretationName(eInterp), nBand );
         return GDALPamRasterBand::SetColorInterpretation( eInterp );
     }
 
-    /* greyscale + alpha */
+    // Greyscale + alpha.
     if( eInterp == GCI_AlphaBand
         && nBand == 2
         && poGDS->nSamplesPerPixel == 2
         && poGDS->nPhotometric == PHOTOMETRIC_MINISBLACK )
     {
-        uint16 v[1];
-        v[0] = GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", NULL),
-                                  DEFAULT_ALPHA_TYPE);
+        const uint16 v[1] = {
+            GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", NULL),
+                               DEFAULT_ALPHA_TYPE) };
 
         TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
         return CE_None;
     }
 
-    /* Try to autoset TIFFTAG_PHOTOMETRIC = PHOTOMETRIC_RGB if possible */
+    // Try to autoset TIFFTAG_PHOTOMETRIC = PHOTOMETRIC_RGB if possible.
     if( poGDS->nBands >= 3 &&
         poGDS->nCompression != COMPRESSION_JPEG &&
         poGDS->nPhotometric != PHOTOMETRIC_RGB &&
-        CSLFetchNameValue( poGDS->papszCreationOptions, "PHOTOMETRIC") == NULL &&
+        CSLFetchNameValue( poGDS->papszCreationOptions,
+                           "PHOTOMETRIC" ) == NULL &&
         ((nBand == 1 && eInterp == GCI_RedBand) ||
          (nBand == 2 && eInterp == GCI_GreenBand) ||
          (nBand == 3 && eInterp == GCI_BlueBand)) )
@@ -4324,34 +4874,39 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
             poGDS->GetRasterBand(3)->GetColorInterpretation() == GCI_BlueBand )
         {
             poGDS->nPhotometric = PHOTOMETRIC_RGB;
-            TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
+            TIFFSetField( poGDS->hTIFF, TIFFTAG_PHOTOMETRIC,
+                          poGDS->nPhotometric );
 
-            /* We need to update the number of extra samples */
-            uint16 *v;
+            // We need to update the number of extra samples.
+            uint16 *v = NULL;
             uint16 count = 0;
-            uint16 nNewExtraSamplesCount = static_cast<uint16>(poGDS->nBands - 3);
+            const uint16 nNewExtraSamplesCount =
+                static_cast<uint16>(poGDS->nBands - 3);
             if( poGDS->nBands >= 4 &&
-                TIFFGetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) &&
+                TIFFGetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES,
+                              &count, &v ) &&
                 count > nNewExtraSamplesCount )
             {
-                uint16* pasNewExtraSamples =
-                    (uint16*)CPLMalloc( nNewExtraSamplesCount * sizeof(uint16) );
+                uint16 * const pasNewExtraSamples =
+                    static_cast<uint16 *>( CPLMalloc(
+                        nNewExtraSamplesCount * sizeof(uint16) ) );
                 memcpy( pasNewExtraSamples, v + count - nNewExtraSamplesCount,
                         nNewExtraSamplesCount * sizeof(uint16) );
 
-                TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, nNewExtraSamplesCount, pasNewExtraSamples);
+                TIFFSetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES,
+                              nNewExtraSamplesCount, pasNewExtraSamples );
 
                 CPLFree(pasNewExtraSamples);
             }
         }
-        poGDS->bCheckIfColorInterpMustGoToPamAtCrystalization = true;
         return CE_None;
     }
 
     // On the contrary, cancel the above if needed
     if( poGDS->nCompression != COMPRESSION_JPEG &&
         poGDS->nPhotometric == PHOTOMETRIC_RGB &&
-        CSLFetchNameValue( poGDS->papszCreationOptions, "PHOTOMETRIC") == NULL &&
+        CSLFetchNameValue( poGDS->papszCreationOptions,
+                           "PHOTOMETRIC") == NULL &&
         ((nBand == 1 && eInterp != GCI_RedBand) ||
          (nBand == 2 && eInterp != GCI_GreenBand) ||
          (nBand == 3 && eInterp != GCI_BlueBand)) )
@@ -4359,63 +4914,71 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
         poGDS->nPhotometric = PHOTOMETRIC_MINISBLACK;
         TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
 
-        /* We need to update the number of extra samples */
-        uint16 *v;
+        // We need to update the number of extra samples.
+        uint16 *v = NULL;
         uint16 count = 0;
-        uint16 nNewExtraSamplesCount = static_cast<uint16>(poGDS->nBands - 1);
+        const uint16 nNewExtraSamplesCount =
+            static_cast<uint16>(poGDS->nBands - 1);
         if( poGDS->nBands >= 2 )
         {
             TIFFGetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v );
             if( nNewExtraSamplesCount > count )
             {
-                uint16* pasNewExtraSamples =
-                    (uint16*)CPLMalloc( nNewExtraSamplesCount * sizeof(uint16) );
-                for(int i=0; i < (int)(nNewExtraSamplesCount - count); i++)
+                uint16 * const pasNewExtraSamples =
+                    static_cast<uint16 *>( CPLMalloc(
+                        nNewExtraSamplesCount * sizeof(uint16) ) );
+                for( int i = 0;
+                     i < static_cast<int>(nNewExtraSamplesCount - count);
+                     ++i )
                     pasNewExtraSamples[i] = EXTRASAMPLE_UNSPECIFIED;
-                if (count > 0 )
+                if( count > 0 )
                 {
-                    memcpy( pasNewExtraSamples + nNewExtraSamplesCount - count, v,
+                    memcpy( pasNewExtraSamples + nNewExtraSamplesCount - count,
+                            v,
                             count * sizeof(uint16) );
                 }
 
-                TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, nNewExtraSamplesCount, pasNewExtraSamples);
+                TIFFSetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES,
+                              nNewExtraSamplesCount, pasNewExtraSamples );
 
                 CPLFree(pasNewExtraSamples);
             }
         }
-
-        poGDS->bCheckIfColorInterpMustGoToPamAtCrystalization = true;
     }
 
-    /* Mark alpha band in extrasamples */
+    // Mark alpha band in extrasamples.
     if( eInterp == GCI_AlphaBand )
     {
-        uint16 *v;
+        uint16 *v = NULL;
         uint16 count = 0;
         if( TIFFGetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
         {
-            int nBaseSamples = poGDS->nSamplesPerPixel - count;
+            const int nBaseSamples = poGDS->nSamplesPerPixel - count;
 
-            for(int i=1;i<=poGDS->nBands;i++)
+            for( int i = 1; i <= poGDS->nBands; ++i )
             {
                 if( i != nBand &&
-                    poGDS->GetRasterBand(i)->GetColorInterpretation()  == GCI_AlphaBand )
+                    poGDS->GetRasterBand(i)->GetColorInterpretation() ==
+                    GCI_AlphaBand )
                 {
                     if( i == nBaseSamples + 1 &&
-                        CSLFetchNameValue(poGDS->papszCreationOptions, "ALPHA") != NULL )
+                        CSLFetchNameValue( poGDS->papszCreationOptions,
+                                           "ALPHA" ) != NULL )
                     {
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                "Band %d was already identified as alpha band, "
-                                "and band %d is now marked as alpha too. "
-                                "Presumably ALPHA creation option is not needed",
-                                i, nBand);
+                        CPLError(
+                            CE_Warning, CPLE_AppDefined,
+                            "Band %d was already identified as alpha band, "
+                            "and band %d is now marked as alpha too. "
+                            "Presumably ALPHA creation option is not needed",
+                            i, nBand );
                     }
                     else
                     {
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                "Band %d was already identified as alpha band, "
-                                "and band %d is now marked as alpha too",
-                                i, nBand);
+                        CPLError(
+                            CE_Warning, CPLE_AppDefined,
+                            "Band %d was already identified as alpha band, "
+                            "and band %d is now marked as alpha too",
+                            i, nBand );
                     }
                 }
             }
@@ -4427,13 +4990,15 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
                 // TIFFGetField().
 
                 uint16* pasNewExtraSamples =
-                    (uint16*)CPLMalloc( count * sizeof(uint16) );
+                    static_cast<uint16 *>(
+                        CPLMalloc( count * sizeof(uint16) ) );
                 memcpy( pasNewExtraSamples, v, count * sizeof(uint16) );
                 pasNewExtraSamples[nBand - nBaseSamples - 1] =
                     GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", NULL),
                                             DEFAULT_ALPHA_TYPE);
 
-                TIFFSetField(poGDS->hTIFF, TIFFTAG_EXTRASAMPLES, count, pasNewExtraSamples);
+                TIFFSetField( poGDS->hTIFF, TIFFTAG_EXTRASAMPLES,
+                              count, pasNewExtraSamples);
 
                 CPLFree(pasNewExtraSamples);
 
@@ -4449,7 +5014,6 @@ CPLErr GTiffRasterBand::SetColorInterpretation( GDALColorInterp eInterp )
         TIFFSetField(poGDS->hTIFF, TIFFTAG_PHOTOMETRIC, poGDS->nPhotometric);
     }
 
-    poGDS->bCheckIfColorInterpMustGoToPamAtCrystalization = true;
     return CE_None;
 }
 
@@ -4464,8 +5028,8 @@ GDALColorTable *GTiffRasterBand::GetColorTable()
 
     if( nBand == 1 )
         return poGDS->poColorTable;
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -4490,7 +5054,8 @@ CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
     if( poGDS->nSamplesPerPixel != 1 && poGDS->nSamplesPerPixel != 2)
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "SetColorTable() not supported for multi-sample TIFF files." );
+                  "SetColorTable() not supported for multi-sample TIFF "
+                  "files." );
         return CE_Failure;
     }
 
@@ -4508,7 +5073,7 @@ CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
 /* -------------------------------------------------------------------- */
     if( poGDS->bCrystalized )
     {
-        if (!poGDS->SetDirectory())
+        if( !poGDS->SetDirectory() )
             return CE_Failure;
     }
 
@@ -4523,8 +5088,9 @@ CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
 #ifdef HAVE_UNSETFIELD
         TIFFUnsetField( poGDS->hTIFF, TIFFTAG_COLORMAP );
 #else
-        CPLDebug( "GTiff",
-                  "TIFFUnsetField() not supported, colormap may not be cleared." );
+        CPLDebug(
+            "GTiff",
+            "TIFFUnsetField() not supported, colormap may not be cleared." );
 #endif
 
         if( poGDS->poColorTable )
@@ -4539,34 +5105,34 @@ CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
 /* -------------------------------------------------------------------- */
 /*      Write out the colortable, and update the configuration.         */
 /* -------------------------------------------------------------------- */
-    int nColors;
+    int nColors = 65536;
 
     if( eDataType == GDT_Byte )
         nColors = 256;
-    else
-        nColors = 65536;
 
-    unsigned short *panTRed, *panTGreen, *panTBlue;
+    unsigned short *panTRed = static_cast<unsigned short *>(
+        CPLMalloc(sizeof(unsigned short)*nColors) );
+    unsigned short *panTGreen = static_cast<unsigned short *>(
+        CPLMalloc(sizeof(unsigned short)*nColors) );
+    unsigned short *panTBlue = static_cast<unsigned short *>(
+        CPLMalloc(sizeof(unsigned short)*nColors) );
 
-    panTRed = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
-    panTGreen = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
-    panTBlue = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
-
-    for( int iColor = 0; iColor < nColors; iColor++ )
+    for( int iColor = 0; iColor < nColors; ++iColor )
     {
         if( iColor < poCT->GetColorEntryCount() )
         {
-            GDALColorEntry  sRGB;
-
+            GDALColorEntry sRGB;
             poCT->GetColorEntryAsRGB( iColor, &sRGB );
 
-            panTRed[iColor] = (unsigned short) (257 * sRGB.c1);
-            panTGreen[iColor] = (unsigned short) (257 * sRGB.c2);
-            panTBlue[iColor] = (unsigned short) (257 * sRGB.c3);
+            panTRed[iColor] = static_cast<unsigned short>(257 * sRGB.c1);
+            panTGreen[iColor] = static_cast<unsigned short>(257 * sRGB.c2);
+            panTBlue[iColor] = static_cast<unsigned short>(257 * sRGB.c3);
         }
         else
         {
-            panTRed[iColor] = panTGreen[iColor] = panTBlue[iColor] = 0;
+            panTRed[iColor] = 0;
+            panTGreen[iColor] = 0;
+            panTBlue[iColor] = 0;
         }
     }
 
@@ -4581,13 +5147,10 @@ CPLErr GTiffRasterBand::SetColorTable( GDALColorTable * poCT )
     if( poGDS->poColorTable )
         delete poGDS->poColorTable;
 
-    /* libtiff 3.X needs setting this in all cases (creation or update) */
-    /* whereas libtiff 4.X would just need it if there */
-    /* was no color table before */
-#if 0
-    else
-#endif
-        poGDS->bNeedsRewrite = TRUE;
+    // libtiff 3.X needs setting this in all cases (creation or update)
+    // whereas libtiff 4.X would just need it if there
+    // was no color table before.
+    poGDS->bNeedsRewrite = true;
 
     poGDS->poColorTable = poCT->Clone();
     eBandInterp = GCI_PaletteIndex;
@@ -4634,19 +5197,21 @@ CPLErr GTiffRasterBand::SetNoDataValue( double dfNoData )
 
     if( poGDS->bNoDataSet && poGDS->dfNoDataValue == dfNoData )
         return CE_None;
+
     if( poGDS->bStreamingOut && poGDS->bCrystalized )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot modify nodata at that point in a streamed output file");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Cannot modify nodata at that point in a streamed output file" );
         return CE_Failure;
     }
 
-    poGDS->bNoDataSet = TRUE;
+    poGDS->bNoDataSet = true;
     poGDS->dfNoDataValue = dfNoData;
 
-    poGDS->bNoDataChanged = TRUE;
+    poGDS->bNoDataChanged = true;
 
-    bNoDataSet = TRUE;
+    bNoDataSet = true;
     dfNoDataValue = dfNoData;
     return CE_None;
 }
@@ -4662,20 +5227,22 @@ CPLErr GTiffRasterBand::DeleteNoDataValue()
 
     if( !poGDS->bNoDataSet )
         return CE_None;
+
     if( poGDS->bStreamingOut && poGDS->bCrystalized )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot modify nodata at that point in a streamed output file");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Cannot modify nodata at that point in a streamed output file" );
         return CE_Failure;
     }
 
-    poGDS->bNoDataSet = FALSE;
+    poGDS->bNoDataSet = false;
     poGDS->dfNoDataValue = -9999.0;
 
-    poGDS->bNoDataChanged = TRUE;
+    poGDS->bNoDataChanged = true;
 
-    bNoDataSet = FALSE;
-    dfNoDataValue = -9999.0;;
+    bNoDataSet = false;
+    dfNoDataValue = -9999.0;
     return CE_None;
 }
 
@@ -4689,25 +5256,25 @@ CPLErr GTiffRasterBand::DeleteNoDataValue()
 void GTiffRasterBand::NullBlock( void *pData )
 
 {
-    int nWords = nBlockXSize * nBlockYSize;
-    int nChunkSize = MAX(1,GDALGetDataTypeSize(eDataType)/8);
+    const int nWords = nBlockXSize * nBlockYSize;
+    const int nChunkSize = std::max(1, GDALGetDataTypeSizeBytes(eDataType));
 
-    int bNoDataSetIn;
-    double dfNoData = GetNoDataValue( &bNoDataSetIn );
+    int bNoDataSetIn = FALSE;
+    const double dfNoData = GetNoDataValue( &bNoDataSetIn );
     if( !bNoDataSetIn )
     {
 #ifdef ESRI_BUILD
-        if ( poGDS->nBitsPerSample >= 2 )
-            memset( pData, 0, nWords*nChunkSize );
+        if( poGDS->nBitsPerSample >= 2 )
+            memset( pData, 0, nWords * nChunkSize );
         else
-            memset( pData, 1, nWords*nChunkSize );
+            memset( pData, 1, nWords * nChunkSize );
 #else
-        memset( pData, 0, nWords*nChunkSize );
+        memset( pData, 0, nWords * nChunkSize );
 #endif
     }
     else
     {
-        /* Will convert nodata value to the right type and copy efficiently */
+        // Will convert nodata value to the right type and copy efficiently.
         GDALCopyWords( &dfNoData, GDT_Float64, 0,
                        pData, eDataType, nChunkSize, nWords);
     }
@@ -4726,19 +5293,17 @@ int GTiffRasterBand::GetOverviewCount()
     {
         return poGDS->nOverviewCount;
     }
-    else
-    {
-        int nOverviewCount = GDALRasterBand::GetOverviewCount();
-        if( nOverviewCount > 0 )
-            return nOverviewCount;
 
-        /* Implicit JPEG overviews are normally hidden, except when doing */
-        /* IRasterIO() operations. */
-        if( poGDS->nJPEGOverviewVisibilityFlag )
-            return poGDS->GetJPEGOverviewCount();
-        else
-            return 0;
-    }
+    const int nOverviewCount = GDALRasterBand::GetOverviewCount();
+    if( nOverviewCount > 0 )
+        return nOverviewCount;
+
+    // Implicit JPEG overviews are normally hidden, except when doing
+    // IRasterIO() operations.
+    if( poGDS->nJPEGOverviewVisibilityCounter )
+        return poGDS->GetJPEGOverviewCount();
+
+    return 0;
 }
 
 /************************************************************************/
@@ -4752,26 +5317,24 @@ GDALRasterBand *GTiffRasterBand::GetOverview( int i )
 
     if( poGDS->nOverviewCount > 0 )
     {
-        /* Do we have internal overviews ? */
+        // Do we have internal overviews?
         if( i < 0 || i >= poGDS->nOverviewCount )
             return NULL;
-        else
-            return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
-    }
-    else
-    {
-        GDALRasterBand* poOvrBand = GDALRasterBand::GetOverview( i );
-        if( poOvrBand != NULL )
-            return poOvrBand;
 
-        /* For consistency with GetOverviewCount(), we should also test */
-        /* nJPEGOverviewVisibilityFlag, but it is also convenient to be able */
-        /* to query them for testing purposes. */
-        if( i >= 0 && i < poGDS->GetJPEGOverviewCount() )
-            return poGDS->papoJPEGOverviewDS[i]->GetRasterBand(nBand);
-        else
-            return NULL;
+        return poGDS->papoOverviewDS[i]->GetRasterBand(nBand);
     }
+
+    GDALRasterBand* const poOvrBand = GDALRasterBand::GetOverview( i );
+    if( poOvrBand != NULL )
+        return poOvrBand;
+
+    // For consistency with GetOverviewCount(), we should also test
+    // nJPEGOverviewVisibilityCounter, but it is also convenient to be able
+    // to query them for testing purposes.
+    if( i >= 0 && i < poGDS->GetJPEGOverviewCount() )
+        return poGDS->papoJPEGOverviewDS[i]->GetRasterBand(nBand);
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -4788,13 +5351,11 @@ int GTiffRasterBand::GetMaskFlags()
         {
             return GMF_PER_DATASET;
         }
-        else
-        {
-            return 0;
-        }
+
+        return 0;
     }
-    else
-        return GDALPamRasterBand::GetMaskFlags();
+
+    return GDALPamRasterBand::GetMaskFlags();
 }
 
 /************************************************************************/
@@ -4807,18 +5368,18 @@ GDALRasterBand *GTiffRasterBand::GetMaskBand()
 
     if( poGDS->poMaskDS != NULL )
     {
-        if( poGDS->poMaskDS->GetRasterCount() == 1)
+        if( poGDS->poMaskDS->GetRasterCount() == 1 )
             return poGDS->poMaskDS->GetRasterBand(1);
-        else
-            return poGDS->poMaskDS->GetRasterBand(nBand);
+
+        return poGDS->poMaskDS->GetRasterBand(nBand);
     }
-    else
-        return GDALPamRasterBand::GetMaskBand();
+
+    return GDALPamRasterBand::GetMaskBand();
 }
 
 /************************************************************************/
 /* ==================================================================== */
-/*                             GTiffSplitBand                            */
+/*                             GTiffSplitBand                           */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -4827,60 +5388,50 @@ class GTiffSplitBand CPL_FINAL : public GTiffRasterBand
     friend class GTiffDataset;
 
   public:
+             GTiffSplitBand( GTiffDataset *, int );
+    virtual ~GTiffSplitBand() {};
 
-                   GTiffSplitBand( GTiffDataset *, int );
-    virtual       ~GTiffSplitBand();
-
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
 /*                           GTiffSplitBand()                           */
 /************************************************************************/
 
-GTiffSplitBand::GTiffSplitBand( GTiffDataset *poDSIn, int nBandIn )
-        : GTiffRasterBand( poDSIn, nBandIn )
-
+GTiffSplitBand::GTiffSplitBand( GTiffDataset *poDSIn, int nBandIn ) :
+    GTiffRasterBand( poDSIn, nBandIn )
 {
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 }
 
 /************************************************************************/
-/*                          ~GTiffSplitBand()                          */
-/************************************************************************/
-
-GTiffSplitBand::~GTiffSplitBand()
-{
-}
-
-/************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+CPLErr GTiffSplitBand::IReadBlock( int /* nBlockXOff */, int nBlockYOff,
                                    void * pImage )
 
 {
-    (void) nBlockXOff;
-
-    /* Optimization when reading the same line in a contig multi-band TIFF */
+    // Optimization when reading the same line in a contig multi-band TIFF.
     if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands > 1 &&
         poGDS->nLastLineRead == nBlockYOff )
     {
         goto extract_band_data;
     }
 
-    if (!poGDS->SetDirectory())
+    if( !poGDS->SetDirectory() )
         return CE_Failure;
 
-    if (poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
-        poGDS->nBands > 1)
+    if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
+        poGDS->nBands > 1 )
     {
-        if (poGDS->pabyBlockBuf == NULL)
+        if( poGDS->pabyBlockBuf == NULL )
         {
-            poGDS->pabyBlockBuf = (GByte *) VSI_MALLOC_VERBOSE(TIFFScanlineSize(poGDS->hTIFF));
+            poGDS->pabyBlockBuf =
+                static_cast<GByte *>(
+                    VSI_MALLOC_VERBOSE(TIFFScanlineSize(poGDS->hTIFF)) );
             if( poGDS->pabyBlockBuf == NULL )
             {
                 return CE_Failure;
@@ -4900,9 +5451,9 @@ CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE && poGDS->nBands > 1 )
     {
-        /* If we change of band, we must start reading the */
-        /* new strip from its beginning */
-        if ( poGDS->nLastBandRead != nBand )
+        // If we change of band, we must start reading the
+        // new strip from its beginning.
+        if( poGDS->nLastBandRead != nBand )
             poGDS->nLastLineRead = -1;
         poGDS->nLastBandRead = nBand;
     }
@@ -4910,10 +5461,12 @@ CPLErr GTiffSplitBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     while( poGDS->nLastLineRead < nBlockYOff )
     {
         ++poGDS->nLastLineRead;
-        if( TIFFReadScanline( poGDS->hTIFF,
-                              poGDS->pabyBlockBuf ? poGDS->pabyBlockBuf : pImage,
-                              poGDS->nLastLineRead,
-                              (poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE) ? (uint16) (nBand-1) : 0 ) == -1
+        if( TIFFReadScanline(
+                poGDS->hTIFF,
+                poGDS->pabyBlockBuf ? poGDS->pabyBlockBuf : pImage,
+                poGDS->nLastLineRead,
+                (poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE) ?
+                 static_cast<uint16>(nBand - 1) : 0 ) == -1
             && !poGDS->bIgnoreReadErrors )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -4927,13 +5480,14 @@ extract_band_data:
 /* -------------------------------------------------------------------- */
 /*      Extract band data from contig buffer.                           */
 /* -------------------------------------------------------------------- */
-    if ( poGDS->pabyBlockBuf != NULL )
+    if( poGDS->pabyBlockBuf != NULL )
     {
-        int iPixel, iSrcOffset= nBand - 1, iDstOffset=0;
-
-        for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset+=poGDS->nBands, iDstOffset++ )
+        for( int iPixel = 0, iSrcOffset= nBand - 1, iDstOffset = 0;
+             iPixel < nBlockXSize;
+             ++iPixel, iSrcOffset += poGDS->nBands, ++iDstOffset )
         {
-            ((GByte *) pImage)[iDstOffset] = poGDS->pabyBlockBuf[iSrcOffset];
+            static_cast<GByte *>(pImage)[iDstOffset] =
+                poGDS->pabyBlockBuf[iSrcOffset];
         }
     }
 
@@ -4944,14 +5498,10 @@ extract_band_data:
 /*                            IWriteBlock()                             */
 /************************************************************************/
 
-CPLErr GTiffSplitBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-                                    void * pImage )
+CPLErr GTiffSplitBand::IWriteBlock( int /* nBlockXOff */, int /* nBlockYOff */,
+                                    void * /* pImage */ )
 
 {
-    (void) nBlockXOff;
-    (void) nBlockYOff;
-    (void) pImage;
-
     CPLError( CE_Failure, CPLE_AppDefined,
               "Split bands are read-only." );
     return CE_Failure;
@@ -4968,23 +5518,21 @@ class GTiffRGBABand CPL_FINAL : public GTiffRasterBand
     friend class GTiffDataset;
 
   public:
-
                    GTiffRGBABand( GTiffDataset *, int );
+    virtual ~GTiffRGBABand() {}
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
-
 /************************************************************************/
 /*                           GTiffRGBABand()                            */
 /************************************************************************/
 
-GTiffRGBABand::GTiffRGBABand( GTiffDataset *poDSIn, int nBandIn )
-        : GTiffRasterBand( poDSIn, nBandIn )
-
+GTiffRGBABand::GTiffRGBABand( GTiffDataset *poDSIn, int nBandIn ) :
+    GTiffRasterBand( poDSIn, nBandIn )
 {
     eDataType = GDT_Byte;
 }
@@ -5006,43 +5554,55 @@ CPLErr GTiffRGBABand::IWriteBlock( int, int, void * )
 /************************************************************************/
 
 CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                    void * pImage )
+                                  void * pImage )
 
 {
-    int nBlockBufSize, nBlockId;
-    CPLErr eErr = CE_None;
-
-    if (!poGDS->SetDirectory())
+    if( !poGDS->SetDirectory() )
         return CE_Failure;
 
-    CPLAssert(nBlocksPerRow != 0);
-    nBlockBufSize = 4 * nBlockXSize * nBlockYSize;
-    nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+    CPLAssert( nBlocksPerRow != 0 );
+    const int nBlockBufSize = 4 * nBlockXSize * nBlockYSize;
+    const int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate a temporary buffer for this strip.                     */
 /* -------------------------------------------------------------------- */
     if( poGDS->pabyBlockBuf == NULL )
     {
-        poGDS->pabyBlockBuf = (GByte *) VSI_MALLOC3_VERBOSE( 4, nBlockXSize, nBlockYSize );
+        poGDS->pabyBlockBuf =
+            static_cast<GByte *>(
+                VSI_MALLOC3_VERBOSE( 4, nBlockXSize, nBlockYSize ) );
         if( poGDS->pabyBlockBuf == NULL )
-            return( CE_Failure );
+            return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Read the strip                                                  */
 /* -------------------------------------------------------------------- */
+    CPLErr eErr = CE_None;
+
     if( poGDS->nLoadedBlock != nBlockId )
     {
         if( TIFFIsTiled( poGDS->hTIFF ) )
         {
-            if( TIFFReadRGBATile(poGDS->hTIFF,
-                                 nBlockXOff * nBlockXSize,
-                                 nBlockYOff * nBlockYSize,
-                                 (uint32 *) poGDS->pabyBlockBuf) == -1
+#if defined(INTERNAL_LIBTIFF) || TIFFLIB_VERSION > 20161119
+            if( TIFFReadRGBATileExt(
+                   poGDS->hTIFF,
+                   nBlockXOff * nBlockXSize,
+                   nBlockYOff * nBlockYSize,
+                   reinterpret_cast<uint32 *>(poGDS->pabyBlockBuf),
+                   !poGDS->bIgnoreReadErrors) == 0
                 && !poGDS->bIgnoreReadErrors )
+#else
+            if( TIFFReadRGBATile(
+                   poGDS->hTIFF,
+                   nBlockXOff * nBlockXSize,
+                   nBlockYOff * nBlockYSize,
+                   reinterpret_cast<uint32 *>(poGDS->pabyBlockBuf)) == 0
+                && !poGDS->bIgnoreReadErrors )
+#endif
             {
-                /* Once TIFFError() is properly hooked, this can go away */
+                // Once TIFFError() is properly hooked, this can go away.
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "TIFFReadRGBATile() failed." );
 
@@ -5053,12 +5613,22 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
         }
         else
         {
-            if( TIFFReadRGBAStrip(poGDS->hTIFF,
-                                  nBlockId * nBlockYSize,
-                                  (uint32 *) poGDS->pabyBlockBuf) == -1
+#if defined(INTERNAL_LIBTIFF) || TIFFLIB_VERSION > 20161119
+            if( TIFFReadRGBAStripExt(
+                   poGDS->hTIFF,
+                   nBlockId * nBlockYSize,
+                   reinterpret_cast<uint32 *>(poGDS->pabyBlockBuf),
+                   !poGDS->bIgnoreReadErrors) == 0
+                && !poGDS->bIgnoreReadErrors )
+#else
+            if( TIFFReadRGBAStrip(
+                   poGDS->hTIFF,
+                   nBlockId * nBlockYSize,
+                   reinterpret_cast<uint32 *>(poGDS->pabyBlockBuf)) == 0
                 && !poGDS->bIgnoreReadErrors )
+#endif
             {
-                /* Once TIFFError() is properly hooked, this can go away */
+                // Once TIFFError() is properly hooked, this can go away.
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "TIFFReadRGBAStrip() failed." );
 
@@ -5074,33 +5644,30 @@ CPLErr GTiffRGBABand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Handle simple case of eight bit data, and pixel interleaving.   */
 /* -------------------------------------------------------------------- */
-    int   iDestLine, nBO;
-    int   nThisBlockYSize;
+    int nThisBlockYSize = nBlockYSize;
 
-    if( (nBlockYOff+1) * nBlockYSize > GetYSize()
+    if( nBlockYOff * nBlockYSize > GetYSize() - nBlockYSize
         && !TIFFIsTiled( poGDS->hTIFF ) )
         nThisBlockYSize = GetYSize() - nBlockYOff * nBlockYSize;
-    else
-        nThisBlockYSize = nBlockYSize;
 
 #ifdef CPL_LSB
-    nBO = nBand - 1;
+    const int nBO = nBand - 1;
 #else
-    nBO = 4 - nBand;
+    const int nBO = 4 - nBand;
 #endif
 
-    for( iDestLine = 0; iDestLine < nThisBlockYSize; iDestLine++ )
+    for( int iDestLine = 0; iDestLine < nThisBlockYSize; ++iDestLine )
     {
-        int nSrcOffset;
-
-        nSrcOffset = (nThisBlockYSize - iDestLine - 1) * nBlockXSize * 4;
+        const int nSrcOffset =
+            (nThisBlockYSize - iDestLine - 1) * nBlockXSize * 4;
 
-        GDALCopyWords( poGDS->pabyBlockBuf + nBO + nSrcOffset, GDT_Byte, 4,
-                       ((GByte *) pImage)+iDestLine*nBlockXSize, GDT_Byte, 1,
-                       nBlockXSize );
+        GDALCopyWords(
+            poGDS->pabyBlockBuf + nBO + nSrcOffset, GDT_Byte, 4,
+            static_cast<GByte *>(pImage)+iDestLine*nBlockXSize, GDT_Byte, 1,
+            nBlockXSize );
     }
 
-    if (eErr == CE_None)
+    if( eErr == CE_None )
         eErr = FillCacheForOtherBands(nBlockXOff, nBlockYOff);
 
     return eErr;
@@ -5115,12 +5682,12 @@ GDALColorInterp GTiffRGBABand::GetColorInterpretation()
 {
     if( nBand == 1 )
         return GCI_RedBand;
-    else if( nBand == 2 )
+    if( nBand == 2 )
         return GCI_GreenBand;
-    else if( nBand == 3 )
+    if( nBand == 3 )
         return GCI_BlueBand;
-    else
-        return GCI_AlphaBand;
+
+    return GCI_AlphaBand;
 }
 
 /************************************************************************/
@@ -5135,13 +5702,12 @@ class GTiffOddBitsBand : public GTiffRasterBand
   public:
 
                    GTiffOddBitsBand( GTiffDataset *, int );
-    virtual       ~GTiffOddBitsBand();
+    virtual ~GTiffOddBitsBand() {};
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                           GTiffOddBitsBand()                         */
 /************************************************************************/
@@ -5160,34 +5726,96 @@ GTiffOddBitsBand::GTiffOddBitsBand( GTiffDataset *poGDSIn, int nBandIn )
 }
 
 /************************************************************************/
-/*                          ~GTiffOddBitsBand()                          */
-/************************************************************************/
-
-GTiffOddBitsBand::~GTiffOddBitsBand()
-
-{
-}
-
-/************************************************************************/
-/*                            IWriteBlock()                             */
+/*                            FloatToHalf()                             */
 /************************************************************************/
 
-CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-                                      void *pImage )
-
+static GUInt16 FloatToHalf( GUInt32 iFloat32, bool& bHasWarned )
 {
-    int nBlockId;
-    CPLErr      eErr = CE_None;
+    GUInt32 iSign =     (iFloat32 >> 31) & 0x00000001;
+    GUInt32 iExponent = (iFloat32 >> 23) & 0x000000ff;
+    GUInt32 iMantissa = iFloat32         & 0x007fffff;
 
-    if (poGDS->bWriteErrorInFlushBlockBuf)
+    if (iExponent == 255)
     {
-        /* Report as an error if a previously loaded block couldn't be */
-        /* written correctly */
-        poGDS->bWriteErrorInFlushBlockBuf = FALSE;
-        return CE_Failure;
+        if (iMantissa == 0)
+        {
+/* -------------------------------------------------------------------- */
+/*       Positive or negative infinity.                                 */
+/* -------------------------------------------------------------------- */
+
+            return static_cast<GUInt16>((iSign << 15) | 0x7C00);
+        }
+        else
+        {
+/* -------------------------------------------------------------------- */
+/*       NaN -- preserve sign and significand bits.                     */
+/* -------------------------------------------------------------------- */
+            if( iMantissa >> 13 )
+                return static_cast<GUInt16>((iSign << 15) | 0x7C00 |
+                                                            (iMantissa >> 13));
+
+            return static_cast<GUInt16>((iSign << 15) | 0x7E00);
+        }
     }
 
-    if (!poGDS->SetDirectory())
+    if( iExponent <= 127 - 15 )
+    {
+        // Zero, float32 denormalized number or float32 too small normalized
+        // number
+        if( 13 + 1 + 127 - 15 - iExponent >= 32 )
+            return static_cast<GUInt16>(iSign << 15);
+
+        // Return a denormalized number
+        return static_cast<GUInt16>((iSign << 15) |
+                ((iMantissa | 0x00800000) >> (13 + 1 + 127 - 15 - iExponent)));
+    }
+    if( iExponent - (127 - 15) >= 31 )
+    {
+        if( !bHasWarned )
+        {
+            bHasWarned = true;
+            float fVal = 0.0f;
+            memcpy(&fVal, &iFloat32, 4);
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Value %.8g is beyond range of float16. Converted to %sinf",
+                fVal, (fVal > 0) ? "+" : "-");
+        }
+        return static_cast<GUInt16>((iSign << 15) | 0x7C00);  // Infinity
+    }
+
+/* -------------------------------------------------------------------- */
+/*       Normalized number.                                             */
+/* -------------------------------------------------------------------- */
+
+    iExponent = iExponent - (127 - 15);
+    iMantissa = iMantissa >> 13;
+
+/* -------------------------------------------------------------------- */
+/*       Assemble sign, exponent and mantissa.                          */
+/* -------------------------------------------------------------------- */
+
+    // coverity[overflow_sink]
+    return static_cast<GUInt16>((iSign << 15) | (iExponent << 10) | iMantissa);
+}
+
+/************************************************************************/
+/*                            IWriteBlock()                             */
+/************************************************************************/
+
+CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
+                                      void *pImage )
+
+{
+    if( poGDS->bWriteErrorInFlushBlockBuf )
+    {
+        // Report as an error if a previously loaded block couldn't be written
+        // correctly.
+        poGDS->bWriteErrorInFlushBlockBuf = false;
+        return CE_Failure;
+    }
+
+    if( !poGDS->SetDirectory() )
         return CE_Failure;
 
     CPLAssert( poGDS != NULL
@@ -5195,10 +5823,11 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                && nBlockYOff >= 0
                && pImage != NULL );
 
-    if( eDataType == GDT_Float32 )
+    if( eDataType == GDT_Float32 && poGDS->nBitsPerSample != 16 )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "Writing float data with nBitsPerSample < 32 is unsupported");
+                 "Writing float data with nBitsPerSample = %d is unsupported",
+                 poGDS->nBitsPerSample);
         return CE_Failure;
     }
 
@@ -5206,18 +5835,22 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*      Load the block buffer.                                          */
 /* -------------------------------------------------------------------- */
     CPLAssert(nBlocksPerRow != 0);
-    nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+    int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
 
     if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
-        nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
+        nBlockId += (nBand - 1) * poGDS->nBlocksPerBand;
 
-    /* Only read content from disk in the CONTIG case */
-    eErr = poGDS->LoadBlockBuf( nBlockId,
-                                poGDS->nPlanarConfig == PLANARCONFIG_CONTIG && poGDS->nBands > 1 );
-    if( eErr != CE_None )
-        return eErr;
+    // Only read content from disk in the CONTIG case.
+    {
+        const CPLErr eErr =
+            poGDS->LoadBlockBuf( nBlockId,
+                                 poGDS->nPlanarConfig == PLANARCONFIG_CONTIG &&
+                                 poGDS->nBands > 1 );
+        if( eErr != CE_None )
+            return eErr;
+    }
 
-    GUInt32 nMaxVal = (1 << poGDS->nBitsPerSample) - 1;
+    const GUInt32 nMaxVal = (1 << poGDS->nBitsPerSample) - 1;
 
 /* -------------------------------------------------------------------- */
 /*      Handle case of "separate" images or single band images where    */
@@ -5226,63 +5859,114 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE
         || poGDS->nBands == 1 )
     {
-        int iBit, iPixel, iBitOffset = 0;
-        int     iX, iY, nBitsPerLine;
-
-        // bits per line rounds up to next byte boundary.
-        nBitsPerLine = nBlockXSize * poGDS->nBitsPerSample;
+        // TODO(schwehr): Create a CplNumBits8Aligned.
+        // Bits per line rounds up to next byte boundary.
+        int nBitsPerLine = nBlockXSize * poGDS->nBitsPerSample;
         if( (nBitsPerLine & 7) != 0 )
             nBitsPerLine = (nBitsPerLine + 7) & (~7);
 
-        /* Initialize to zero as we set the buffer with binary or operations */
-        if (poGDS->nBitsPerSample != 24)
-            memset(poGDS->pabyBlockBuf, 0, (nBitsPerLine / 8) * nBlockYSize);
+        int iPixel = 0;
 
-        iPixel = 0;
-        for( iY = 0; iY < nBlockYSize; iY++ )
+        // Small optimization in 1 bit case.
+        if( poGDS->nBitsPerSample == 1 )
         {
-            iBitOffset = iY * nBitsPerLine;
-
-            /* Small optimization in 1 bit case */
-            if (poGDS->nBitsPerSample == 1)
+            for( int iY = 0; iY < nBlockYSize; ++iY, iPixel += nBlockXSize )
             {
-                for( iX = 0; iX < nBlockXSize; iX++ )
+                int iBitOffset = iY * nBitsPerLine;
+
+                const GByte* pabySrc =
+                    static_cast<const GByte*>(pImage) + iPixel;
+                int iByteOffset = iBitOffset / 8;
+                int iX = 0;  // Used after for.
+                for( ; iX + 7 < nBlockXSize; iX += 8, iByteOffset++ )
                 {
-                    if (((GByte *) pImage)[iPixel++])
-                        poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
-                    iBitOffset++;
+                    int nRes = (!(!pabySrc[iX+0])) << 7;
+                    nRes |= (!(!pabySrc[iX+1])) << 6;
+                    nRes |= (!(!pabySrc[iX+2])) << 5;
+                    nRes |= (!(!pabySrc[iX+3])) << 4;
+                    nRes |= (!(!pabySrc[iX+4])) << 3;
+                    nRes |= (!(!pabySrc[iX+5])) << 2;
+                    nRes |= (!(!pabySrc[iX+6])) << 1;
+                    nRes |= (!(!pabySrc[iX+7])) << 0;
+                    poGDS->pabyBlockBuf[iByteOffset] = static_cast<GByte>(nRes);
                 }
+                iBitOffset = iByteOffset * 8;
+                if( iX < nBlockXSize )
+                {
+                    int nRes = 0;
+                    for( ; iX < nBlockXSize; ++iX )
+                    {
+                        if( pabySrc[iX] )
+                            nRes |= (0x80 >>(iBitOffset & 7) );
+                        ++iBitOffset;
+                    }
+                    poGDS->pabyBlockBuf[iBitOffset>>3] =
+                        static_cast<GByte>(nRes);
+                }
+            }
 
-                continue;
+            poGDS->bLoadedBlockDirty = true;
+
+            return CE_None;
+        }
+
+        if( eDataType == GDT_Float32 && poGDS->nBitsPerSample == 16 )
+        {
+            for( ; iPixel < nBlockYSize * nBlockXSize; iPixel++ )
+            {
+                GUInt32 nInWord = static_cast<GUInt32 *>(pImage)[iPixel];
+                GUInt16 nHalf = FloatToHalf(nInWord, poGDS->bClipWarn);
+                reinterpret_cast<GUInt16*>(poGDS->pabyBlockBuf)[iPixel] = nHalf;
             }
 
-            if (poGDS->nBitsPerSample == 12 )
+            poGDS->bLoadedBlockDirty = true;
+
+            return CE_None;
+        }
+
+        // Initialize to zero as we set the buffer with binary or operations.
+        if( poGDS->nBitsPerSample != 24 )
+            memset(poGDS->pabyBlockBuf, 0, (nBitsPerLine / 8) * nBlockYSize);
+
+        for( int iY = 0; iY < nBlockYSize; ++iY )
+        {
+            int iBitOffset = iY * nBitsPerLine;
+
+            if( poGDS->nBitsPerSample == 12 )
             {
-                for( iX = 0; iX < nBlockXSize; iX++ )
+                for( int iX = 0; iX < nBlockXSize; ++iX )
                 {
-                    GUInt32 nInWord = ((GUInt16 *) pImage)[iPixel++];
-                    if (nInWord > nMaxVal)
+                    GUInt32 nInWord = static_cast<GUInt16 *>(pImage)[iPixel++];
+                    if( nInWord > nMaxVal )
                     {
                         nInWord = nMaxVal;
                         if( !poGDS->bClipWarn )
                         {
-                            poGDS->bClipWarn = TRUE;
-                            CPLError( CE_Warning, CPLE_AppDefined,
-                                      "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
+                            poGDS->bClipWarn = true;
+                            CPLError(
+                                CE_Warning, CPLE_AppDefined,
+                                "One or more pixels clipped to fit %d bit "
+                                "domain.", poGDS->nBitsPerSample );
                         }
                     }
 
                     if( (iBitOffset % 8) == 0 )
                     {
-                        poGDS->pabyBlockBuf[iBitOffset>>3] = (GByte) (nInWord >> 4);
-                        /* let 4 lower bits to zero as they're going to be overridden by the next word */
-                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] = (GByte) ((nInWord & 0xf) << 4);
+                        poGDS->pabyBlockBuf[iBitOffset>>3] =
+                            static_cast<GByte>(nInWord >> 4);
+                        // Let 4 lower bits to zero as they're going to be
+                        // overridden by the next word.
+                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] =
+                            static_cast<GByte>((nInWord & 0xf) << 4);
                     }
                     else
                     {
-                        /* we must or to preserve the 4 upper bits written for the previous word */
-                        poGDS->pabyBlockBuf[iBitOffset>>3] |= (GByte) (nInWord >> 8);
-                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] = (GByte) (nInWord & 0xff);
+                        // Must or to preserve the 4 upper bits written
+                        // for the previous word.
+                        poGDS->pabyBlockBuf[iBitOffset>>3] |=
+                            static_cast<GByte>(nInWord >> 8);
+                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] =
+                            static_cast<GByte>(nInWord & 0xff);
                     }
 
                     iBitOffset += poGDS->nBitsPerSample;
@@ -5290,31 +5974,40 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 continue;
             }
 
-            for( iX = 0; iX < nBlockXSize; iX++ )
+            for( int iX = 0; iX < nBlockXSize; ++iX )
             {
-                GUInt32  nInWord = 0;
+                GUInt32 nInWord = 0;
                 if( eDataType == GDT_Byte )
-                    nInWord = ((GByte *) pImage)[iPixel++];
+                {
+                    nInWord = static_cast<GByte *>(pImage)[iPixel++];
+                }
                 else if( eDataType == GDT_UInt16 )
-                    nInWord = ((GUInt16 *) pImage)[iPixel++];
+                {
+                    nInWord = static_cast<GUInt16 *>(pImage)[iPixel++];
+                }
                 else if( eDataType == GDT_UInt32 )
-                    nInWord = ((GUInt32 *) pImage)[iPixel++];
-                else {
-                    CPLAssert(0);
+                {
+                    nInWord = static_cast<GUInt32 *>(pImage)[iPixel++];
+                }
+                else
+                {
+                    CPLAssert(false);
                 }
 
-                if (nInWord > nMaxVal)
+                if( nInWord > nMaxVal )
                 {
                     nInWord = nMaxVal;
                     if( !poGDS->bClipWarn )
                     {
-                        poGDS->bClipWarn = TRUE;
-                        CPLError( CE_Warning, CPLE_AppDefined,
-                                  "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
+                        poGDS->bClipWarn = true;
+                        CPLError(
+                            CE_Warning, CPLE_AppDefined,
+                            "One or more pixels clipped to fit %d bit domain.",
+                            poGDS->nBitsPerSample );
                     }
                 }
 
-                if (poGDS->nBitsPerSample == 24)
+                if( poGDS->nBitsPerSample == 24 )
                 {
 /* -------------------------------------------------------------------- */
 /*      Special case for 24bit data which is pre-byteswapped since      */
@@ -5322,36 +6015,38 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 #ifdef CPL_MSB
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
-                        (GByte) nInWord;
+                        static_cast<GByte>( nInWord );
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
-                        (GByte) (nInWord >> 8);
+                        static_cast<GByte>( nInWord >> 8 );
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
-                        (GByte) (nInWord >> 16);
+                        static_cast<GByte>( nInWord >> 16 );
 #else
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
-                        (GByte) (nInWord >> 16);
+                        static_cast<GByte>( nInWord >> 16 );
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
-                        (GByte) (nInWord >> 8);
+                        static_cast<GByte>( nInWord >> 8 );
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
-                        (GByte) nInWord;
+                        static_cast<GByte>( nInWord );
 #endif
                     iBitOffset += 24;
                 }
                 else
                 {
-                    for( iBit = 0; iBit < poGDS->nBitsPerSample; iBit++ )
+                    for( int iBit = 0; iBit < poGDS->nBitsPerSample; ++iBit )
                     {
-                        if (nInWord & (1 << (poGDS->nBitsPerSample - 1 - iBit)))
-                            poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
-                        iBitOffset++;
+                        if( nInWord &
+                            (1 << (poGDS->nBitsPerSample - 1 - iBit)) )
+                            poGDS->pabyBlockBuf[iBitOffset>>3] |=
+                                ( 0x80 >> (iBitOffset & 7) );
+                        ++iBitOffset;
                     }
                 }
             }
         }
 
-        poGDS->bLoadedBlockDirty = TRUE;
+        poGDS->bLoadedBlockDirty = true;
 
-        return eErr;
+        return CE_None;
     }
 
 /* -------------------------------------------------------------------- */
@@ -5363,21 +6058,21 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*      out any other bands that are dirty in our cache.  This is       */
 /*      especially helpful when writing compressed blocks.              */
 /* -------------------------------------------------------------------- */
-    int iBand;
-
-    for( iBand = 0; iBand < poGDS->nBands; iBand++ )
+    for( int iBand = 0; iBand < poGDS->nBands; ++iBand )
     {
         const GByte *pabyThisImage = NULL;
         GDALRasterBlock *poBlock = NULL;
-        int iBit, iPixel, iBitOffset = 0;
-        int     iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
 
-        if( iBand+1 == nBand )
-            pabyThisImage = (GByte *) pImage;
+        if( iBand + 1 == nBand )
+        {
+            pabyThisImage = static_cast<GByte *>( pImage );
+        }
         else
         {
-            poBlock = ((GTiffOddBitsBand *)poGDS->GetRasterBand( iBand+1 ))
-                ->TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
+            poBlock =
+                reinterpret_cast<GTiffOddBitsBand *>(
+                    poGDS->GetRasterBand( iBand + 1 ))
+                        ->TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
 
             if( poBlock == NULL )
                 continue;
@@ -5388,50 +6083,81 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 continue;
             }
 
-            pabyThisImage = (GByte *) poBlock->GetDataRef();
+            pabyThisImage = static_cast<GByte *>(poBlock->GetDataRef());
         }
 
-        iPixelBitSkip = poGDS->nBitsPerSample * poGDS->nBands;
-        iBandBitOffset = iBand * poGDS->nBitsPerSample;
+        const int iPixelBitSkip = poGDS->nBitsPerSample * poGDS->nBands;
+        const int iBandBitOffset = iBand * poGDS->nBitsPerSample;
 
-        // bits per line rounds up to next byte boundary.
-        nBitsPerLine = nBlockXSize * iPixelBitSkip;
+        // Bits per line rounds up to next byte boundary.
+        int nBitsPerLine = nBlockXSize * iPixelBitSkip;
         if( (nBitsPerLine & 7) != 0 )
             nBitsPerLine = (nBitsPerLine + 7) & (~7);
 
-        iPixel = 0;
-        for( iY = 0; iY < nBlockYSize; iY++ )
+        int iPixel = 0;
+
+        if( eDataType == GDT_Float32 && poGDS->nBitsPerSample == 16 )
+        {
+            for( ; iPixel < nBlockYSize * nBlockXSize; iPixel++ )
+            {
+                GUInt32 nInWord = reinterpret_cast<const GUInt32 *>(
+                                                        pabyThisImage)[iPixel];
+                GUInt16 nHalf = FloatToHalf(nInWord, poGDS->bClipWarn);
+                reinterpret_cast<GUInt16*>(poGDS->pabyBlockBuf)[
+                                    iPixel * poGDS->nBands + iBand] = nHalf;
+            }
+
+            if( poBlock != NULL )
+            {
+                poBlock->MarkClean();
+                poBlock->DropLock();
+            }
+            continue;
+        }
+
+        for( int iY = 0; iY < nBlockYSize; ++iY )
         {
-            iBitOffset = iBandBitOffset + iY * nBitsPerLine;
+            int iBitOffset = iBandBitOffset + iY * nBitsPerLine;
 
-            if (poGDS->nBitsPerSample == 12 )
+            if( poGDS->nBitsPerSample == 12 )
             {
-                for( iX = 0; iX < nBlockXSize; iX++ )
+                for( int iX = 0; iX < nBlockXSize; ++iX )
                 {
-                    GUInt32 nInWord = ((GUInt16 *) pabyThisImage)[iPixel++];
-                    if (nInWord > nMaxVal)
+                    GUInt32 nInWord =
+                        reinterpret_cast<const GUInt16 *>(
+                            pabyThisImage)[iPixel++];
+                    if( nInWord > nMaxVal )
                     {
                         nInWord = nMaxVal;
                         if( !poGDS->bClipWarn )
                         {
-                            poGDS->bClipWarn = TRUE;
-                            CPLError( CE_Warning, CPLE_AppDefined,
-                                      "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
+                            poGDS->bClipWarn = true;
+                            CPLError(
+                                CE_Warning, CPLE_AppDefined,
+                                "One or more pixels clipped to fit %d bit "
+                                "domain.", poGDS->nBitsPerSample );
                         }
                     }
 
                     if( (iBitOffset % 8) == 0 )
                     {
-                        poGDS->pabyBlockBuf[iBitOffset>>3] = (GByte) (nInWord >> 4);
+                        poGDS->pabyBlockBuf[iBitOffset>>3] =
+                            static_cast<GByte>( nInWord >> 4 );
                         poGDS->pabyBlockBuf[(iBitOffset>>3)+1] =
-                            (GByte) (((nInWord & 0xf) << 4) | (poGDS->pabyBlockBuf[(iBitOffset>>3)+1] & 0xf));
+                            static_cast<GByte>(
+                                ((nInWord & 0xf) << 4) |
+                                (poGDS->pabyBlockBuf[(iBitOffset>>3)+1] &
+                                 0xf) );
                     }
                     else
                     {
                         poGDS->pabyBlockBuf[iBitOffset>>3] =
-                            (GByte) ((poGDS->pabyBlockBuf[iBitOffset>>3] & 0xf0) |
-                                     (nInWord >> 8));
-                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] = (GByte) (nInWord & 0xff);
+                            static_cast<GByte>(
+                                (poGDS->pabyBlockBuf[iBitOffset>>3] &
+                                 0xf0) |
+                                (nInWord >> 8));
+                        poGDS->pabyBlockBuf[(iBitOffset>>3)+1] =
+                            static_cast<GByte>(nInWord & 0xff);
                     }
 
                     iBitOffset += iPixelBitSkip;
@@ -5439,31 +6165,43 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 continue;
             }
 
-            for( iX = 0; iX < nBlockXSize; iX++ )
+            for( int iX = 0; iX < nBlockXSize; ++iX )
             {
-                GUInt32  nInWord = 0;
+                GUInt32 nInWord = 0;
                 if( eDataType == GDT_Byte )
-                    nInWord = ((GByte *) pabyThisImage)[iPixel++];
+                {
+                    nInWord =
+                        static_cast<const GByte *>(pabyThisImage)[iPixel++];
+                }
                 else if( eDataType == GDT_UInt16 )
-                    nInWord = ((GUInt16 *) pabyThisImage)[iPixel++];
+                {
+                    nInWord = reinterpret_cast<const GUInt16 *>(
+                        pabyThisImage)[iPixel++];
+                }
                 else if( eDataType == GDT_UInt32 )
-                    nInWord = ((GUInt32 *) pabyThisImage)[iPixel++];
-                else {
-                    CPLAssert(0);
+                {
+                    nInWord = reinterpret_cast<const GUInt32 *>(
+                        pabyThisImage)[iPixel++];
+                }
+                else
+                {
+                    CPLAssert(false);
                 }
 
-                if (nInWord > nMaxVal)
+                if( nInWord > nMaxVal )
                 {
                     nInWord = nMaxVal;
                     if( !poGDS->bClipWarn )
                     {
-                        poGDS->bClipWarn = TRUE;
-                        CPLError( CE_Warning, CPLE_AppDefined,
-                                  "One or more pixels clipped to fit %d bit domain.", poGDS->nBitsPerSample );
+                        poGDS->bClipWarn = true;
+                        CPLError(
+                            CE_Warning, CPLE_AppDefined,
+                            "One or more pixels clipped to fit %d bit domain.",
+                            poGDS->nBitsPerSample );
                     }
                 }
 
-                if (poGDS->nBitsPerSample == 24)
+                if( poGDS->nBitsPerSample == 24 )
                 {
 /* -------------------------------------------------------------------- */
 /*      Special case for 24bit data which is pre-byteswapped since      */
@@ -5471,39 +6209,45 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 #ifdef CPL_MSB
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
-                        (GByte) nInWord;
+                        static_cast<GByte>(nInWord);
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
-                        (GByte) (nInWord >> 8);
+                        static_cast<GByte>(nInWord >> 8);
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
-                        (GByte) (nInWord >> 16);
+                        static_cast<GByte>(nInWord >> 16);
 #else
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 0] =
-                        (GByte) (nInWord >> 16);
+                        static_cast<GByte>(nInWord >> 16);
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 1] =
-                        (GByte) (nInWord >> 8);
+                        static_cast<GByte>(nInWord >> 8);
                     poGDS->pabyBlockBuf[(iBitOffset>>3) + 2] =
-                        (GByte) nInWord;
+                        static_cast<GByte>(nInWord);
 #endif
                     iBitOffset += 24;
                 }
                 else
                 {
-                    for( iBit = 0; iBit < poGDS->nBitsPerSample; iBit++ )
+                    for( int iBit = 0; iBit < poGDS->nBitsPerSample; ++iBit )
                     {
-                        if (nInWord & (1 << (poGDS->nBitsPerSample - 1 - iBit)))
-                            poGDS->pabyBlockBuf[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
+                        // TODO(schwehr): Revisit this block.
+                        if( nInWord &
+                            (1 << (poGDS->nBitsPerSample - 1 - iBit)) )
+                        {
+                            poGDS->pabyBlockBuf[iBitOffset>>3] |=
+                                ( 0x80 >> (iBitOffset & 7) );
+                        }
                         else
                         {
                             // We must explicitly unset the bit as we
                             // may update an existing block.
-                            poGDS->pabyBlockBuf[iBitOffset>>3] &= ~(0x80 >>(iBitOffset & 7));
+                            poGDS->pabyBlockBuf[iBitOffset>>3] &=
+                                ~(0x80 >>(iBitOffset & 7));
                         }
 
-                        iBitOffset++;
+                        ++iBitOffset;
                     }
                 }
 
-                iBitOffset= iBitOffset + iPixelBitSkip - poGDS->nBitsPerSample;
+                iBitOffset = iBitOffset + iPixelBitSkip - poGDS->nBitsPerSample;
             }
         }
 
@@ -5514,7 +6258,7 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         }
     }
 
-    poGDS->bLoadedBlockDirty = TRUE;
+    poGDS->bLoadedBlockDirty = true;
 
     return CE_None;
 }
@@ -5523,21 +6267,72 @@ CPLErr GTiffOddBitsBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                    void * pImage )
+static void ExpandPacked8ToByte1( const GByte * const CPL_RESTRICT pabySrc,
+                                  GByte* const CPL_RESTRICT pabyDest,
+                                  int nBytes )
+{
+    for( int i = 0, j = 0; i < nBytes; i++, j+= 8 )
+    {
+        const GByte byVal = pabySrc[i];
+        pabyDest[j+0] = (byVal >> 7) & 0x1;
+        pabyDest[j+1] = (byVal >> 6) & 0x1;
+        pabyDest[j+2] = (byVal >> 5) & 0x1;
+        pabyDest[j+3] = (byVal >> 4) & 0x1;
+        pabyDest[j+4] = (byVal >> 3) & 0x1;
+        pabyDest[j+5] = (byVal >> 2) & 0x1;
+        pabyDest[j+6] = (byVal >> 1) & 0x1;
+        pabyDest[j+7] = (byVal >> 0) & 0x1;
+    }
+}
 
+#if defined(__GNUC__) || defined(_MSC_VER)
+// Signedness of char implementation dependent, so be explicit.
+// Assumes 2-complement integer types and sign extension of right shifting
+// GCC guarantees such:
+// https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html#Integers-implementation
+static inline GByte ExtractBitAndConvertTo255(GByte byVal, int nBit)
 {
-    int nBlockId;
-    CPLErr eErr = CE_None;
+    return
+        static_cast<GByte>(static_cast<signed char>(byVal << (7 - nBit)) >> 7);
+}
+#else
+// Portable way
+static inline GByte ExtractBitAndConvertTo255(GByte byVal, int nBit)
+{
+    return (byVal & (1 << nBit)) ? 255 : 0;
+}
+#endif
 
-    if (!poGDS->SetDirectory())
+static void ExpandPacked8ToByte255( const GByte * const CPL_RESTRICT pabySrc,
+                                    GByte* const CPL_RESTRICT pabyDest,
+                                    int nBytes )
+{
+    for( int i = 0, j = 0; i < nBytes; i++, j += 8 )
+    {
+        const GByte byVal = pabySrc[i];
+        pabyDest[j+0] = ExtractBitAndConvertTo255(byVal, 7);
+        pabyDest[j+1] = ExtractBitAndConvertTo255(byVal, 6);
+        pabyDest[j+2] = ExtractBitAndConvertTo255(byVal, 5);
+        pabyDest[j+3] = ExtractBitAndConvertTo255(byVal, 4);
+        pabyDest[j+4] = ExtractBitAndConvertTo255(byVal, 3);
+        pabyDest[j+5] = ExtractBitAndConvertTo255(byVal, 2);
+        pabyDest[j+6] = ExtractBitAndConvertTo255(byVal, 1);
+        pabyDest[j+7] = ExtractBitAndConvertTo255(byVal, 0);
+    }
+}
+
+CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+                                     void * pImage )
+
+{
+    if( !poGDS->SetDirectory() )
         return CE_Failure;
 
     CPLAssert(nBlocksPerRow != 0);
-    nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
+    int nBlockId = nBlockXOff + nBlockYOff * nBlocksPerRow;
 
     if( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
-        nBlockId += (nBand-1) * poGDS->nBlocksPerBand;
+        nBlockId += (nBand - 1) * poGDS->nBlocksPerBand;
 
 /* -------------------------------------------------------------------- */
 /*      Handle the case of a strip in a writable file that doesn't      */
@@ -5553,32 +6348,50 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Load the block buffer.                                          */
 /* -------------------------------------------------------------------- */
-    eErr = poGDS->LoadBlockBuf( nBlockId );
-    if( eErr != CE_None )
-        return eErr;
+    {
+        const CPLErr eErr = poGDS->LoadBlockBuf( nBlockId );
+        if( eErr != CE_None )
+            return eErr;
+    }
 
-    if (  poGDS->nBitsPerSample == 1 && (poGDS->nBands == 1 || poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) )
+    if( poGDS->nBitsPerSample == 1 &&
+        (poGDS->nBands == 1 || poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) )
     {
 /* -------------------------------------------------------------------- */
 /*      Translate 1bit data to eight bit.                               */
 /* -------------------------------------------------------------------- */
-        int iDstOffset=0, iLine;
-        const GByte * const pabyBlockBuf = poGDS->pabyBlockBuf;
+        int iDstOffset = 0;
+        const GByte * const CPL_RESTRICT pabyBlockBuf = poGDS->pabyBlockBuf;
+        GByte* CPL_RESTRICT pabyDest = static_cast<GByte *>(pImage);
 
-        for( iLine = 0; iLine < nBlockYSize; iLine++ )
+        for( int iLine = 0; iLine < nBlockYSize; ++iLine )
         {
-            int iSrcOffset, iPixel;
-
-            iSrcOffset = ((nBlockXSize+7) >> 3) * 8 * iLine;
-
-            GByte bSetVal = (poGDS->bPromoteTo8Bits) ? 255 : 1;
+            int iSrcOffsetByte = ((nBlockXSize + 7) >> 3) * iLine;
 
-            for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset++ )
+            if( !poGDS->bPromoteTo8Bits )
+            {
+                ExpandPacked8ToByte1( pabyBlockBuf + iSrcOffsetByte,
+                                      pabyDest + iDstOffset,
+                                      nBlockXSize / 8 );
+            }
+            else
             {
-                if( pabyBlockBuf[iSrcOffset >>3] & (0x80 >> (iSrcOffset & 0x7)) )
-                    ((GByte *) pImage)[iDstOffset++] = bSetVal;
+                ExpandPacked8ToByte255( pabyBlockBuf + iSrcOffsetByte,
+                                        pabyDest + iDstOffset,
+                                        nBlockXSize / 8 );
+            }
+            int iSrcOffsetBit = (iSrcOffsetByte + nBlockXSize / 8) * 8;
+            iDstOffset += nBlockXSize & ~0x7;
+            const GByte bSetVal = poGDS->bPromoteTo8Bits ? 255 : 1;
+            for( int iPixel = nBlockXSize & ~0x7 ;
+                 iPixel < nBlockXSize;
+                 ++iPixel, ++iSrcOffsetBit )
+            {
+                if( pabyBlockBuf[iSrcOffsetBit >>3] &
+                    (0x80 >> (iSrcOffsetBit & 0x7)) )
+                    static_cast<GByte *>(pImage)[iDstOffset++] = bSetVal;
                 else
-                    ((GByte *) pImage)[iDstOffset++] = 0;
+                    static_cast<GByte *>(pImage)[iDstOffset++] = 0;
             }
         }
     }
@@ -5588,38 +6401,38 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     else if( eDataType == GDT_Float32 )
     {
-        int i, nBlockPixels, nWordBytes, iSkipBytes;
-        GByte *pabyImage;
-
-        nWordBytes = poGDS->nBitsPerSample / 8;
-        pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
-        iSkipBytes = ( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) ?
+        const int nWordBytes = poGDS->nBitsPerSample / 8;
+        GByte *pabyImage = poGDS->pabyBlockBuf + (nBand - 1) * nWordBytes;
+        const int iSkipBytes =
+            ( poGDS->nPlanarConfig == PLANARCONFIG_SEPARATE ) ?
             nWordBytes : poGDS->nBands * nWordBytes;
 
-        nBlockPixels = nBlockXSize * nBlockYSize;
-        if ( poGDS->nBitsPerSample == 16 )
+        const int nBlockPixels = nBlockXSize * nBlockYSize;
+        if( poGDS->nBitsPerSample == 16 )
         {
-            for( i = 0; i < nBlockPixels; i++ )
+            for( int i = 0; i < nBlockPixels; ++i )
             {
-                ((GUInt32 *) pImage)[i] =
-                    HalfToFloat( *((GUInt16 *)pabyImage) );
+                static_cast<GUInt32 *>(pImage)[i] =
+                    HalfToFloat( *reinterpret_cast<GUInt16 *>(pabyImage) );
                 pabyImage += iSkipBytes;
             }
         }
-        else if ( poGDS->nBitsPerSample == 24 )
+        else if( poGDS->nBitsPerSample == 24 )
         {
-            for( i = 0; i < nBlockPixels; i++ )
+            for( int i = 0; i < nBlockPixels; ++i )
             {
 #ifdef CPL_MSB
-                ((GUInt32 *) pImage)[i] =
-                    TripleToFloat( ((GUInt32)*(pabyImage + 0) << 16)
-                                   | ((GUInt32)*(pabyImage + 1) << 8)
-                                   | (GUInt32)*(pabyImage + 2) );
+                static_cast<GUInt32 *>(pImage)[i] =
+                    TripleToFloat(
+                        ( static_cast<GUInt32>(*(pabyImage + 0)) << 16)
+                        | (static_cast<GUInt32>(*(pabyImage + 1)) << 8)
+                        | static_cast<GUInt32>(*(pabyImage + 2)) );
 #else
-                ((GUInt32 *) pImage)[i] =
-                    TripleToFloat( ((GUInt32)*(pabyImage + 2) << 16)
-                                   | ((GUInt32)*(pabyImage + 1) << 8)
-                                   | (GUInt32)*pabyImage );
+                static_cast<GUInt32 *>(pImage)[i] =
+                    TripleToFloat(
+                        ( static_cast<GUInt32>(*(pabyImage + 2)) << 16)
+                        | (static_cast<GUInt32>(*(pabyImage + 1)) << 8)
+                        | static_cast<GUInt32>(*pabyImage) );
 #endif
                 pabyImage += iSkipBytes;
             }
@@ -5631,47 +6444,46 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     else if( poGDS->nBitsPerSample == 12 )
     {
-        int iPixel, iBitOffset = 0;
-        int iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
+        int iPixelBitSkip = 0;
+        int iBandBitOffset = 0;
 
         if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
         {
             iPixelBitSkip = poGDS->nBands * poGDS->nBitsPerSample;
-            iBandBitOffset = (nBand-1) * poGDS->nBitsPerSample;
+            iBandBitOffset = (nBand - 1) * poGDS->nBitsPerSample;
         }
         else
         {
             iPixelBitSkip = poGDS->nBitsPerSample;
-            iBandBitOffset = 0;
         }
 
-        // bits per line rounds up to next byte boundary.
-        nBitsPerLine = nBlockXSize * iPixelBitSkip;
+        // Bits per line rounds up to next byte boundary.
+        int nBitsPerLine = nBlockXSize * iPixelBitSkip;
         if( (nBitsPerLine & 7) != 0 )
             nBitsPerLine = (nBitsPerLine + 7) & (~7);
 
-        iPixel = 0;
-        for( iY = 0; iY < nBlockYSize; iY++ )
+        int iPixel = 0;
+        for( int iY = 0; iY < nBlockYSize; ++iY )
         {
-            iBitOffset = iBandBitOffset + iY * nBitsPerLine;
+            int iBitOffset = iBandBitOffset + iY * nBitsPerLine;
 
-            for( iX = 0; iX < nBlockXSize; iX++ )
+            for( int iX = 0; iX < nBlockXSize; ++iX )
             {
-                int iByte = iBitOffset>>3;
+                const int iByte = iBitOffset >> 3;
 
                 if( (iBitOffset & 0x7) == 0 )
                 {
-                    /* starting on byte boundary */
+                    // Starting on byte boundary.
 
-                    ((GUInt16 *) pImage)[iPixel++] =
+                    static_cast<GUInt16 *>(pImage)[iPixel++] =
                         (poGDS->pabyBlockBuf[iByte] << 4)
                         | (poGDS->pabyBlockBuf[iByte+1] >> 4);
                 }
                 else
                 {
-                    /* starting off byte boundary */
+                    // Starting off byte boundary.
 
-                    ((GUInt16 *) pImage)[iPixel++] =
+                    static_cast<GUInt16 *>(pImage)[iPixel++] =
                         ((poGDS->pabyBlockBuf[iByte] & 0xf) << 8)
                         | (poGDS->pabyBlockBuf[iByte+1]);
                 }
@@ -5686,40 +6498,39 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     else if( poGDS->nBitsPerSample == 24 )
     {
-        int iPixel;
-        int     iPixelByteSkip, iBandByteOffset, iX, iY, nBytesPerLine;
+        int iPixelByteSkip = 0;
+        int iBandByteOffset = 0;
 
         if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
         {
             iPixelByteSkip = (poGDS->nBands * poGDS->nBitsPerSample) / 8;
-            iBandByteOffset = ((nBand-1) * poGDS->nBitsPerSample) / 8;
+            iBandByteOffset = ((nBand - 1) * poGDS->nBitsPerSample) / 8;
         }
         else
         {
             iPixelByteSkip = poGDS->nBitsPerSample / 8;
-            iBandByteOffset = 0;
         }
 
-        nBytesPerLine = nBlockXSize * iPixelByteSkip;
+        const int nBytesPerLine = nBlockXSize * iPixelByteSkip;
 
-        iPixel = 0;
-        for( iY = 0; iY < nBlockYSize; iY++ )
+        int iPixel = 0;
+        for( int iY = 0; iY < nBlockYSize; ++iY )
         {
             GByte *pabyImage =
                 poGDS->pabyBlockBuf + iBandByteOffset + iY * nBytesPerLine;
 
-            for( iX = 0; iX < nBlockXSize; iX++ )
+            for( int iX = 0; iX < nBlockXSize; ++iX )
             {
 #ifdef CPL_MSB
-                ((GUInt32 *) pImage)[iPixel++] =
-                    ((GUInt32)*(pabyImage + 2) << 16)
-                    | ((GUInt32)*(pabyImage + 1) << 8)
-                    | (GUInt32)*(pabyImage + 0);
+                static_cast<GUInt32 *>(pImage)[iPixel++] =
+                    ( static_cast<GUInt32>(*(pabyImage + 2)) << 16)
+                    | (static_cast<GUInt32>(*(pabyImage + 1)) << 8)
+                    | static_cast<GUInt32>(*(pabyImage + 0));
 #else
-                ((GUInt32 *) pImage)[iPixel++] =
-                    ((GUInt32)*(pabyImage + 0) << 16)
-                    | ((GUInt32)*(pabyImage + 1) << 8)
-                    | (GUInt32)*(pabyImage + 2);
+                static_cast<GUInt32 *>(pImage)[iPixel++] =
+                    ( static_cast<GUInt32>(*(pabyImage + 0)) << 16)
+                    | (static_cast<GUInt32>(*(pabyImage + 1)) << 8)
+                    | static_cast<GUInt32>(*(pabyImage + 2));
 #endif
                 pabyImage += iPixelByteSkip;
             }
@@ -5731,55 +6542,63 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
     else
     {
-        int iBit, iPixel, iBitOffset = 0;
-        int     iPixelBitSkip, iBandBitOffset, iX, iY, nBitsPerLine;
+        int iPixelBitSkip = 0;
+        int iBandBitOffset = 0;
 
         if( poGDS->nPlanarConfig == PLANARCONFIG_CONTIG )
         {
             iPixelBitSkip = poGDS->nBands * poGDS->nBitsPerSample;
-            iBandBitOffset = (nBand-1) * poGDS->nBitsPerSample;
+            iBandBitOffset = (nBand - 1) * poGDS->nBitsPerSample;
         }
         else
         {
             iPixelBitSkip = poGDS->nBitsPerSample;
-            iBandBitOffset = 0;
         }
 
-        // bits per line rounds up to next byte boundary.
-        nBitsPerLine = nBlockXSize * iPixelBitSkip;
+        // Bits per line rounds up to next byte boundary.
+        int nBitsPerLine = nBlockXSize * iPixelBitSkip;
         if( (nBitsPerLine & 7) != 0 )
             nBitsPerLine = (nBitsPerLine + 7) & (~7);
 
         const GByte * const pabyBlockBuf = poGDS->pabyBlockBuf;
         const int nBitsPerSample = poGDS->nBitsPerSample;
-        iPixel = 0;
+        int iPixel = 0;
 
-        for( iY = 0; iY < nBlockYSize; iY++ )
+        for( int iY = 0; iY < nBlockYSize; ++iY )
         {
-            iBitOffset = iBandBitOffset + iY * nBitsPerLine;
+            int iBitOffset = iBandBitOffset + iY * nBitsPerLine;
 
-            for( iX = 0; iX < nBlockXSize; iX++ )
+            for( int iX = 0; iX < nBlockXSize; ++iX )
             {
-                int  nOutWord = 0;
+                int nOutWord = 0;
 
-                for( iBit = 0; iBit < nBitsPerSample; iBit++ )
+                for( int iBit = 0; iBit < nBitsPerSample; ++iBit )
                 {
                     if( pabyBlockBuf[iBitOffset>>3]
                         & (0x80 >>(iBitOffset & 7)) )
                         nOutWord |= (1 << (nBitsPerSample - 1 - iBit));
-                    iBitOffset++;
+                    ++iBitOffset;
                 }
 
-                iBitOffset= iBitOffset + iPixelBitSkip - nBitsPerSample;
+                iBitOffset = iBitOffset + iPixelBitSkip - nBitsPerSample;
 
                 if( eDataType == GDT_Byte )
-                    ((GByte *) pImage)[iPixel++] = (GByte) nOutWord;
+                {
+                    static_cast<GByte *>(pImage)[iPixel++] =
+                        static_cast<GByte>(nOutWord);
+                }
                 else if( eDataType == GDT_UInt16 )
-                    ((GUInt16 *) pImage)[iPixel++] = (GUInt16) nOutWord;
+                {
+                  static_cast<GUInt16 *>(pImage)[iPixel++] =
+                      static_cast<GUInt16>(nOutWord);
+                }
                 else if( eDataType == GDT_UInt32 )
-                    ((GUInt32 *) pImage)[iPixel++] = nOutWord;
-                else {
-                    CPLAssert(0);
+                {
+                  static_cast<GUInt32 *>(pImage)[iPixel++] = nOutWord;
+                }
+                else
+                {
+                    CPLAssert(false);
                 }
             }
         }
@@ -5788,7 +6607,6 @@ CPLErr GTiffOddBitsBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     return CE_None;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                             GTiffBitmapBand                          */
@@ -5806,11 +6624,10 @@ class GTiffBitmapBand : public GTiffOddBitsBand
                    GTiffBitmapBand( GTiffDataset *, int );
     virtual       ~GTiffBitmapBand();
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
 };
 
-
 /************************************************************************/
 /*                           GTiffBitmapBand()                          */
 /************************************************************************/
@@ -5822,23 +6639,16 @@ GTiffBitmapBand::GTiffBitmapBand( GTiffDataset *poDSIn, int nBandIn )
     eDataType = GDT_Byte;
 
     if( poDSIn->poColorTable != NULL )
+    {
         poColorTable = poDSIn->poColorTable->Clone();
+    }
     else
     {
 #ifdef ESRI_BUILD
         poColorTable = NULL;
 #else
-        GDALColorEntry oWhite, oBlack;
-
-        oWhite.c1 = 255;
-        oWhite.c2 = 255;
-        oWhite.c3 = 255;
-        oWhite.c4 = 255;
-
-        oBlack.c1 = 0;
-        oBlack.c2 = 0;
-        oBlack.c3 = 0;
-        oBlack.c4 = 255;
+        const GDALColorEntry oWhite = { 255, 255, 255, 255 };
+        const GDALColorEntry oBlack = { 0, 0, 0, 255 };
 
         poColorTable = new GDALColorTable();
 
@@ -5852,7 +6662,7 @@ GTiffBitmapBand::GTiffBitmapBand( GTiffDataset *poDSIn, int nBandIn )
             poColorTable->SetColorEntry( 0, &oBlack );
             poColorTable->SetColorEntry( 1, &oWhite );
         }
-#endif /* not defined ESRI_BUILD */
+#endif  // not defined ESRI_BUILD.
     }
 }
 
@@ -5873,10 +6683,10 @@ GTiffBitmapBand::~GTiffBitmapBand()
 GDALColorInterp GTiffBitmapBand::GetColorInterpretation()
 
 {
-    if (poGDS->bPromoteTo8Bits)
+    if( poGDS->bPromoteTo8Bits )
         return GCI_Undefined;
-    else
-        return GCI_PaletteIndex;
+
+    return GCI_PaletteIndex;
 }
 
 /************************************************************************/
@@ -5886,10 +6696,10 @@ GDALColorInterp GTiffBitmapBand::GetColorInterpretation()
 GDALColorTable *GTiffBitmapBand::GetColorTable()
 
 {
-    if (poGDS->bPromoteTo8Bits)
+    if( poGDS->bPromoteTo8Bits )
         return NULL;
-    else
-        return poColorTable;
+
+    return poColorTable;
 }
 
 /************************************************************************/
@@ -5907,11 +6717,10 @@ class GTiffSplitBitmapBand CPL_FINAL : public GTiffBitmapBand
                    GTiffSplitBitmapBand( GTiffDataset *, int );
     virtual       ~GTiffSplitBitmapBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                       GTiffSplitBitmapBand()                         */
 /************************************************************************/
@@ -5928,28 +6737,24 @@ GTiffSplitBitmapBand::GTiffSplitBitmapBand( GTiffDataset *poDSIn, int nBandIn )
 /*                      ~GTiffSplitBitmapBand()                         */
 /************************************************************************/
 
-GTiffSplitBitmapBand::~GTiffSplitBitmapBand()
-
-{
-}
-
+GTiffSplitBitmapBand::~GTiffSplitBitmapBand() {}
 
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr GTiffSplitBitmapBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+CPLErr GTiffSplitBitmapBand::IReadBlock( int /* nBlockXOff */, int nBlockYOff,
                                          void * pImage )
 
 {
-    (void) nBlockXOff;
-
-    if (!poGDS->SetDirectory())
+    if( !poGDS->SetDirectory() )
         return CE_Failure;
 
-    if (poGDS->pabyBlockBuf == NULL)
+    if( poGDS->pabyBlockBuf == NULL )
     {
-        poGDS->pabyBlockBuf = (GByte *) VSI_MALLOC_VERBOSE(TIFFScanlineSize(poGDS->hTIFF));
+        poGDS->pabyBlockBuf =
+            static_cast<GByte *>(
+                VSI_MALLOC_VERBOSE(TIFFScanlineSize(poGDS->hTIFF)) );
         if( poGDS->pabyBlockBuf == NULL )
         {
             return CE_Failure;
@@ -5965,7 +6770,8 @@ CPLErr GTiffSplitBitmapBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     while( poGDS->nLastLineRead < nBlockYOff )
     {
         ++poGDS->nLastLineRead;
-        if( TIFFReadScanline( poGDS->hTIFF, poGDS->pabyBlockBuf, poGDS->nLastLineRead, 0 ) == -1
+        if( TIFFReadScanline( poGDS->hTIFF, poGDS->pabyBlockBuf,
+                              poGDS->nLastLineRead, 0 ) == -1
             && !poGDS->bIgnoreReadErrors )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -5978,14 +6784,15 @@ CPLErr GTiffSplitBitmapBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Translate 1bit data to eight bit.                               */
 /* -------------------------------------------------------------------- */
-    int iPixel, iSrcOffset=0, iDstOffset=0;
+    int iSrcOffset = 0;
+    int iDstOffset = 0;
 
-    for( iPixel = 0; iPixel < nBlockXSize; iPixel++, iSrcOffset++ )
+    for( int iPixel = 0; iPixel < nBlockXSize; ++iPixel, ++iSrcOffset )
     {
         if( poGDS->pabyBlockBuf[iSrcOffset >>3] & (0x80 >> (iSrcOffset & 0x7)) )
-            ((GByte *) pImage)[iDstOffset++] = 1;
+            static_cast<GByte *>(pImage)[iDstOffset++] = 1;
         else
-            ((GByte *) pImage)[iDstOffset++] = 0;
+            static_cast<GByte *>(pImage)[iDstOffset++] = 0;
     }
 
     return CE_None;
@@ -5995,14 +6802,11 @@ CPLErr GTiffSplitBitmapBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                            IWriteBlock()                             */
 /************************************************************************/
 
-CPLErr GTiffSplitBitmapBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-                                          void * pImage )
+CPLErr GTiffSplitBitmapBand::IWriteBlock( int /* nBlockXOff */,
+                                          int /* nBlockYOff */,
+                                          void * /* pImage */ )
 
 {
-    (void) nBlockXOff;
-    (void) nBlockYOff;
-    (void) pImage;
-
     CPLError( CE_Failure, CPLE_AppDefined,
               "Split bitmap bands are read-only." );
     return CE_Failure;
@@ -6014,57 +6818,110 @@ CPLErr GTiffSplitBitmapBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            GTiffDataset()                            */
 /************************************************************************/
 
 GTiffDataset::GTiffDataset() :
-    nPlanarConfig(0), nSamplesPerPixel(0), nBitsPerSample(0), nRowsPerStrip(0),
-    nPhotometric(0), nSampleFormat(0), nCompression(0), nBlocksPerBand(0),
-    nBlockXSize(0), nBlockYSize(0)
+    hTIFF(NULL),
+    fpL(NULL),
+    bStreamingIn(false),
+    bStreamingOut(false),
+    fpToWrite(NULL),
+    nLastWrittenBlockId(-1),
+    ppoActiveDSRef(NULL),
+    poActiveDS(NULL),
+    bScanDeferred(true),
+    nDirOffset(0),
+    bBase(true),
+    bCloseTIFFHandle(false),
+    nPlanarConfig(0),
+    nSamplesPerPixel(0),
+    nBitsPerSample(0),
+    nRowsPerStrip(0),
+    nPhotometric(0),
+    nSampleFormat(0),
+    nCompression(0),
+    nBlocksPerBand(0),
+    nBlockXSize(0),
+    nBlockYSize(0),
+    nLoadedBlock(-1),
+    bLoadedBlockDirty(false),
+    pabyBlockBuf(NULL),
+    bWriteErrorInFlushBlockBuf(false),
+    pszProjection(CPLStrdup("")),
+    bLookedForProjection(false),
+    bLookedForMDAreaOrPoint(false),
+    bGeoTransformValid(false),
+    bTreatAsRGBA(false),
+    bCrystalized(true),
+    poColorTable(NULL),
+    nOverviewCount(0),
+    papoOverviewDS(NULL),
+    nJPEGOverviewVisibilityCounter(0),
+    nJPEGOverviewCount(-1),
+    nJPEGOverviewCountOri(0),
+    papoJPEGOverviewDS(NULL),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    bGeoTIFFInfoChanged(false),
+    bForceUnsetGTOrGCPs(false),
+    bForceUnsetProjection(false),
+    bNoDataChanged(false),
+    bNoDataSet(false),
+    dfNoDataValue(-9999.0),
+    bMetadataChanged(false),
+    bColorProfileMetadataChanged(false),
+    bNeedsRewrite(false),
+    osProfile("GDALGeoTIFF"),
+    papszCreationOptions(NULL),
+    bLoadingOtherBands(false),
+    pabyTempWriteBuffer(NULL),
+    nTempWriteBufferSize(0),
+    poMaskDS(NULL),
+    poBaseDS(NULL),
+    bWriteEmptyTiles(true),
+    bFillEmptyTilesAtClosing(false),
+    nLastLineRead(-1),
+    nLastBandRead(-1),
+    bTreatAsSplit(false),
+    bTreatAsSplitBitmap(false),
+    bClipWarn(false),
+    bIMDRPCMetadataLoaded(false),
+    papszMetadataFiles(NULL),
+    bEXIFMetadataLoaded(false),
+    bICCMetadataLoaded(false),
+    bHasWarnedDisableAggressiveBandCaching(false),
+    bDontReloadFirstBlock(false),
+    nZLevel(-1),
+    nLZMAPreset(-1),
+    nJpegQuality(-1),
+    nJpegTablesMode(-1),
+    bPromoteTo8Bits(false),
+    bDebugDontWriteBlocks(false),
+    bIsFinalized(false),
+    bIgnoreReadErrors(false),
+    bDirectIO(false),
+    eVirtualMemIOUsage(VIRTUAL_MEM_IO_NO),
+    psVirtualMemIOMapping(NULL),
+    eGeoTIFFKeysFlavor(GEOTIFF_KEYS_STANDARD),
+    pBaseMapping(NULL),
+    nRefBaseMapping(0),
+    bHasDiscardedLsb(false),
+    poCompressThreadPool(NULL),
+    hCompressThreadPoolMutex(NULL),
+    m_pTempBufferForCommonDirectIO(NULL),
+    m_nTempBufferForCommonDirectIOSize(0),
+    m_bReadGeoTransform(false),
+    m_bLoadPam(false),
+    m_bHasGotSiblingFiles(false),
+    m_bHasIdentifiedAuthorizedGeoreferencingSources(false),
+    m_nPAMGeorefSrcIndex(-1),
+    m_nINTERNALGeorefSrcIndex(-1),
+    m_nTABFILEGeorefSrcIndex(-1),
+    m_nWORLDFILEGeorefSrcIndex(-1),
+    m_nGeoTransformGeorefSrcIndex(-1)
 {
-    nLoadedBlock = -1;
-    bLoadedBlockDirty = FALSE;
-    pabyBlockBuf = NULL;
-    bWriteErrorInFlushBlockBuf = FALSE;
-    hTIFF = NULL;
-    fpL = NULL;
-    bStreamingIn = FALSE;
-    bStreamingOut = FALSE;
-    fpToWrite = NULL;
-    nLastWrittenBlockId = -1;
-    bNeedsRewrite = FALSE;
-    bMetadataChanged = FALSE;
-    bColorProfileMetadataChanged = FALSE;
-    bGeoTIFFInfoChanged = FALSE;
-    bForceUnsetGTOrGCPs = FALSE;
-    bForceUnsetProjection = FALSE;
-    bCrystalized = TRUE;
-    bCheckIfColorInterpMustGoToPamAtCrystalization = false;
-    poColorTable = NULL;
-    bNoDataChanged = FALSE;
-    bNoDataSet = FALSE;
-    dfNoDataValue = -9999.0;
-    pszProjection = CPLStrdup("");
-    bLookedForProjection = FALSE;
-    bLookedForMDAreaOrPoint = FALSE;
-    bBase = TRUE;
-    bCloseTIFFHandle = FALSE;
-    bTreatAsRGBA = FALSE;
-    nOverviewCount = 0;
-    papoOverviewDS = NULL;
-
-    nJPEGOverviewVisibilityFlag = FALSE;
-    nJPEGOverviewCount = -1;
-    nJPEGOverviewCountOri = 0;
-    papoJPEGOverviewDS = NULL;
-
-    nDirOffset = 0;
-    poActiveDS = NULL;
-    ppoActiveDSRef = NULL;
-
-    bGeoTransformValid = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -6072,74 +6929,20 @@ GTiffDataset::GTiffDataset() :
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
 
-    nGCPCount = 0;
-    pasGCPList = NULL;
-
-    osProfile = "GDALGeoTIFF";
-
-    papszCreationOptions = NULL;
-
-    nTempWriteBufferSize = 0;
-    pabyTempWriteBuffer = NULL;
-
-    poMaskDS = NULL;
-    poBaseDS = NULL;
-
-    bFillEmptyTiles = FALSE;
-    bLoadingOtherBands = FALSE;
-    nLastLineRead = -1;
-    nLastBandRead = -1;
-    bTreatAsSplit = FALSE;
-    bTreatAsSplitBitmap = FALSE;
-    bClipWarn = FALSE;
-    bHasWarnedDisableAggressiveBandCaching = FALSE;
-    bDontReloadFirstBlock = FALSE;
-
-    nZLevel = -1;
-    nLZMAPreset = -1;
-    nJpegQuality = -1;
-    nJpegTablesMode = -1;
-
-    bPromoteTo8Bits = FALSE;
-
-    bDebugDontWriteBlocks = CPLTestBool(CPLGetConfigOption("GTIFF_DONT_WRITE_BLOCKS", "NO"));
-
-    bIsFinalized = FALSE;
-    bIgnoreReadErrors = CPLTestBool(CPLGetConfigOption("GTIFF_IGNORE_READ_ERRORS", "NO"));
-
-    bEXIFMetadataLoaded = FALSE;
-    bICCMetadataLoaded = FALSE;
+    bDebugDontWriteBlocks =
+        CPLTestBool(CPLGetConfigOption("GTIFF_DONT_WRITE_BLOCKS", "NO"));
 
-    bScanDeferred = TRUE;
+    bIgnoreReadErrors =
+        CPLTestBool(CPLGetConfigOption("GTIFF_IGNORE_READ_ERRORS", "NO"));
 
     bDirectIO = CPLTestBool(CPLGetConfigOption("GTIFF_DIRECT_IO", "NO"));
-    const char* pszVirtualMemIO = CPLGetConfigOption("GTIFF_VIRTUAL_MEM_IO", "NO");
+
+    const char* pszVirtualMemIO =
+        CPLGetConfigOption("GTIFF_VIRTUAL_MEM_IO", "NO");
     if( EQUAL(pszVirtualMemIO, "IF_ENOUGH_RAM") )
         eVirtualMemIOUsage = VIRTUAL_MEM_IO_IF_ENOUGH_RAM;
     else if( CPLTestBool(pszVirtualMemIO) )
         eVirtualMemIOUsage = VIRTUAL_MEM_IO_YES;
-    else
-        eVirtualMemIOUsage = VIRTUAL_MEM_IO_NO;
-    psVirtualMemIOMapping = NULL;
-
-    eGeoTIFFKeysFlavor = GEOTIFF_KEYS_STANDARD;
-
-    pBaseMapping = NULL;
-    nRefBaseMapping = 0;
-
-    bHasDiscardedLsb = FALSE;
-
-    bIMDRPCMetadataLoaded = FALSE;
-    papszMetadataFiles = NULL;
-    poCompressThreadPool = NULL;
-    hCompressThreadPoolMutex = NULL;
-
-    m_pTempBufferForCommonDirectIO = NULL;
-    m_nTempBufferForCommonDirectIOSize = 0;
-
-    m_bReadGeoTransform = false;
-    m_bLoadPam = false;
-    m_bHasGotSiblingFiles = false;
 }
 
 /************************************************************************/
@@ -6158,17 +6961,17 @@ GTiffDataset::~GTiffDataset()
 
 int GTiffDataset::Finalize()
 {
-    if (bIsFinalized)
+    if( bIsFinalized )
         return FALSE;
 
     bool bHasDroppedRef = false;
 
     Crystalize();
 
-    if ( bColorProfileMetadataChanged )
+    if( bColorProfileMetadataChanged )
     {
         SaveICCProfile(this, NULL, NULL, 0);
-        bColorProfileMetadataChanged = FALSE;
+        bColorProfileMetadataChanged = false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -6190,7 +6993,7 @@ int GTiffDataset::Finalize()
 /* -------------------------------------------------------------------- */
 /*      Fill in missing blocks with empty data.                         */
 /* -------------------------------------------------------------------- */
-    if( bFillEmptyTiles )
+    if( bFillEmptyTilesAtClosing )
     {
 /* -------------------------------------------------------------------- */
 /*  Ensure any blocks write cached by GDAL gets pushed through libtiff. */
@@ -6198,7 +7001,7 @@ int GTiffDataset::Finalize()
         FlushCacheInternal( false /* do not call FlushDirectory */ );
 
         FillEmptyTiles();
-        bFillEmptyTiles = false;
+        bFillEmptyTilesAtClosing = false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -6207,7 +7010,7 @@ int GTiffDataset::Finalize()
 /* -------------------------------------------------------------------- */
     FlushCacheInternal( true );
 
-    // Destroy compression pool
+    // Destroy compression pool.
     if( poCompressThreadPool )
     {
         delete poCompressThreadPool;
@@ -6231,7 +7034,7 @@ int GTiffDataset::Finalize()
     if( bMetadataChanged )
     {
         PushMetadataToPam();
-        bMetadataChanged = FALSE;
+        bMetadataChanged = false;
         GDALPamDataset::FlushCache();
     }
 
@@ -6240,14 +7043,14 @@ int GTiffDataset::Finalize()
 /* -------------------------------------------------------------------- */
     if( bBase )
     {
-        for( int i = 0; i < nOverviewCount; i++ )
+        for( int i = 0; i < nOverviewCount; ++i )
         {
             delete papoOverviewDS[i];
             bHasDroppedRef = true;
         }
         nOverviewCount = 0;
 
-        for( int i = 0; i < nJPEGOverviewCountOri; i++ )
+        for( int i = 0; i < nJPEGOverviewCountOri; ++i )
         {
             delete papoJPEGOverviewDS[i];
             bHasDroppedRef = true;
@@ -6258,15 +7061,15 @@ int GTiffDataset::Finalize()
         papoJPEGOverviewDS = NULL;
     }
 
-    /* If we are a mask dataset, we can have overviews, but we don't */
-    /* own them. We can only free the array, not the overviews themselves */
+    // If we are a mask dataset, we can have overviews, but we don't
+    // own them. We can only free the array, not the overviews themselves.
     CPLFree( papoOverviewDS );
     papoOverviewDS = NULL;
 
-    /* poMaskDS is owned by the main image and the overviews */
-    /* so because of the latter case, we can delete it even if */
-    /* we are not the base image */
-    if (poMaskDS)
+    // poMaskDS is owned by the main image and the overviews
+    // so because of the latter case, we can delete it even if
+    // we are not the base image.
+    if( poMaskDS )
     {
         delete poMaskDS;
         poMaskDS = NULL;
@@ -6321,14 +7124,14 @@ int GTiffDataset::Finalize()
         *ppoActiveDSRef = NULL;
     ppoActiveDSRef = NULL;
 
-    bIMDRPCMetadataLoaded = FALSE;
+    bIMDRPCMetadataLoaded = false;
     CSLDestroy(papszMetadataFiles);
     papszMetadataFiles = NULL;
 
     VSIFree(m_pTempBufferForCommonDirectIO);
     m_pTempBufferForCommonDirectIO = NULL;
 
-    bIsFinalized = TRUE;
+    bIsFinalized = true;
 
     return bHasDroppedRef;
 }
@@ -6339,7 +7142,7 @@ int GTiffDataset::Finalize()
 
 int GTiffDataset::CloseDependentDatasets()
 {
-    if (!bBase)
+    if( !bBase )
         return FALSE;
 
     int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
@@ -6366,17 +7169,19 @@ int GTiffDataset::GetJPEGOverviewCount()
     {
         return 0;
     }
-    const char* pszSourceColorSpace = oGTiffMDMD.GetMetadataItem( "SOURCE_COLOR_SPACE", "IMAGE_STRUCTURE");
+    const char* pszSourceColorSpace =
+        oGTiffMDMD.GetMetadataItem( "SOURCE_COLOR_SPACE", "IMAGE_STRUCTURE" );
     if( pszSourceColorSpace != NULL && EQUAL(pszSourceColorSpace, "CMYK") )
     {
-        // We cannot handle implicit overviews on JPEG CMYK datasets converted to RGBA
-        // This would imply doing the conversion in GTiffJPEGOverviewBand
-       return 0;
+        // We cannot handle implicit overviews on JPEG CMYK datasets converted
+        // to RGBA This would imply doing the conversion in
+        // GTiffJPEGOverviewBand.
+        return 0;
     }
 
-    /* libjpeg-6b only supports 2, 4 and 8 scale denominators */
-    /* TODO: Later versions support more */
-    for(int i = 2; i >= 0; i--)
+    // libjpeg-6b only supports 2, 4 and 8 scale denominators.
+    // TODO: Later versions support more.
+    for( int i = 2; i >= 0; i-- )
     {
         if( nRasterXSize >= (256 << i) || nRasterYSize >= (256 << i) )
         {
@@ -6390,18 +7195,19 @@ int GTiffDataset::GetJPEGOverviewCount()
     if( !SetDirectory() )
         return 0;
 
-    /* Get JPEG tables */
+    // Get JPEG tables.
     uint32 nJPEGTableSize = 0;
     void* pJPEGTable = NULL;
     GByte abyFFD8[] = { 0xFF, 0xD8 };
     if( TIFFGetField(hTIFF, TIFFTAG_JPEGTABLES, &nJPEGTableSize, &pJPEGTable) )
     {
-        if( pJPEGTable == NULL || (int)nJPEGTableSize <= 0 ||
-            ((GByte*)pJPEGTable)[nJPEGTableSize-1] != 0xD9 )
+        if( pJPEGTable == NULL ||
+            nJPEGTableSize > INT_MAX ||
+            static_cast<GByte*>(pJPEGTable)[nJPEGTableSize-1] != 0xD9 )
         {
             return 0;
         }
-        nJPEGTableSize --; /* remove final 0xD9 */
+        nJPEGTableSize--;  // Remove final 0xD9.
     }
     else
     {
@@ -6409,12 +7215,15 @@ int GTiffDataset::GetJPEGOverviewCount()
         nJPEGTableSize = 2;
     }
 
-    papoJPEGOverviewDS = (GTiffJPEGOverviewDS**) CPLMalloc(
-                        sizeof(GTiffJPEGOverviewDS*) * nJPEGOverviewCount );
-    for(int i = 0; i < nJPEGOverviewCount; i++)
+    papoJPEGOverviewDS =
+        static_cast<GTiffJPEGOverviewDS **>(
+            CPLMalloc( sizeof(GTiffJPEGOverviewDS*) * nJPEGOverviewCount ) );
+    for( int i = 0; i < nJPEGOverviewCount; ++i )
     {
-        papoJPEGOverviewDS[i] = new GTiffJPEGOverviewDS(this, i+1,
-                                            pJPEGTable, (int)nJPEGTableSize);
+        papoJPEGOverviewDS[i] =
+            new GTiffJPEGOverviewDS(
+                this, i + 1,
+                pJPEGTable, static_cast<int>(nJPEGTableSize) );
     }
 
     nJPEGOverviewCountOri = nJPEGOverviewCount;
@@ -6429,18 +7238,16 @@ int GTiffDataset::GetJPEGOverviewCount()
 void GTiffDataset::FillEmptyTiles()
 
 {
-    if (!SetDirectory())
+    if( !SetDirectory() )
         return;
 
 /* -------------------------------------------------------------------- */
 /*      How many blocks are there in this file?                         */
 /* -------------------------------------------------------------------- */
-    int nBlockCount;
-
-    if( nPlanarConfig == PLANARCONFIG_SEPARATE )
-        nBlockCount = nBlocksPerBand * nBands;
-    else
-        nBlockCount = nBlocksPerBand;
+    const int nBlockCount =
+        nPlanarConfig == PLANARCONFIG_SEPARATE ?
+        nBlocksPerBand * nBands :
+        nBlocksPerBand;
 
 /* -------------------------------------------------------------------- */
 /*      Fetch block maps.                                               */
@@ -6452,60 +7259,485 @@ void GTiffDataset::FillEmptyTiles()
     else
         TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts );
 
-    if (panByteCounts == NULL)
+    if( panByteCounts == NULL )
     {
-        /* Got here with libtiff 3.9.3 and tiff_write_8 test */
-        CPLError(CE_Failure, CPLE_AppDefined, "FillEmptyTiles() failed because panByteCounts == NULL");
+        // Got here with libtiff 3.9.3 and tiff_write_8 test.
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "FillEmptyTiles() failed because panByteCounts == NULL" );
         return;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Prepare a blank data buffer to write for uninitialized blocks.  */
 /* -------------------------------------------------------------------- */
-    int nBlockBytes;
+    const int nBlockBytes =
+        TIFFIsTiled( hTIFF ) ?
+        static_cast<int>(TIFFTileSize(hTIFF)) :
+        static_cast<int>(TIFFStripSize(hTIFF));
 
-    if( TIFFIsTiled( hTIFF ) )
-        nBlockBytes = static_cast<int>(TIFFTileSize(hTIFF));
-    else
-        nBlockBytes = static_cast<int>(TIFFStripSize(hTIFF));
+    GByte *pabyData =
+        static_cast<GByte *>( VSI_CALLOC_VERBOSE(nBlockBytes, 1) );
+    if( pabyData == NULL )
+    {
+        return;
+    }
+
+    // Force tiles completely filled with the nodata value to be written.
+    bWriteEmptyTiles = true;
 
-    GByte *pabyData = (GByte *) VSI_CALLOC_VERBOSE(nBlockBytes,1);
-    if (pabyData == NULL)
+/* -------------------------------------------------------------------- */
+/*      If set, fill data buffer with no data value.                    */
+/* -------------------------------------------------------------------- */
+    if( bNoDataSet && dfNoDataValue != 0.0 )
     {
+        const GDALDataType eDataType = GetRasterBand( 1 )->GetRasterDataType();
+        const int nDataTypeSize = GDALGetDataTypeSizeBytes( eDataType );
+        if( nDataTypeSize &&
+            nDataTypeSize * 8 == static_cast<int>(nBitsPerSample) )
+        {
+            GDALCopyWords( &dfNoDataValue, GDT_Float64, 0,
+                           pabyData, eDataType,
+                           nDataTypeSize,
+                           nBlockBytes / nDataTypeSize );
+        }
+        else if( nDataTypeSize )
+        {
+            // Handle non power-of-two depths.
+            // Ideally make a packed buffer, but that is a bit tedious,
+            // so use the normal I/O interfaces.
+
+            CPLFree( pabyData );
+
+            pabyData = static_cast<GByte *>(
+                VSI_MALLOC3_VERBOSE(nBlockXSize, nBlockYSize, nDataTypeSize) );
+            if( pabyData == NULL )
+                return;
+            GDALCopyWords( &dfNoDataValue, GDT_Float64, 0,
+                           pabyData, eDataType,
+                           nDataTypeSize,
+                           nBlockXSize * nBlockYSize );
+            const int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+            for( int iBlock = 0; iBlock < nBlockCount; ++iBlock )
+            {
+                if( panByteCounts[iBlock] == 0 )
+                {
+                    if( nPlanarConfig == PLANARCONFIG_SEPARATE || nBands == 1 )
+                    {
+                        CPL_IGNORE_RET_VAL( GetRasterBand(
+                            1 + iBlock / nBlocksPerBand )->WriteBlock(
+                                (iBlock % nBlocksPerBand) % nBlocksPerRow,
+                                (iBlock % nBlocksPerBand) / nBlocksPerRow,
+                                pabyData ) );
+                    }
+                    else
+                    {
+                        // In contig case, don't directly call WriteBlock(), as
+                        // it could cause useless decompression-recompression.
+                        const int nXOff =
+                            (iBlock % nBlocksPerRow) * nBlockXSize;
+                        const int nYOff =
+                            (iBlock / nBlocksPerRow) * nBlockYSize;
+                        const int nXSize =
+                            (nXOff + nBlockXSize <= nRasterXSize) ?
+                            nBlockXSize : nRasterXSize - nXOff;
+                        const int nYSize =
+                            (nYOff + nBlockYSize <= nRasterYSize) ?
+                            nBlockYSize : nRasterYSize - nYOff;
+                        for( int iBand = 1; iBand <= nBands; ++iBand )
+                        {
+                            CPL_IGNORE_RET_VAL( GetRasterBand( iBand )->
+                                RasterIO(
+                                    GF_Write, nXOff, nYOff, nXSize, nYSize,
+                                    pabyData, nXSize, nYSize,
+                                    eDataType, 0, 0, NULL ) );
+                        }
+                    }
+                }
+            }
+            CPLFree( pabyData );
+            return;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      When we must fill with zeroes, try to create non-sparse file    */
+/*      w.r.t TIFF spec ... as a sparse file w.r.t filesystem, ie by    */
+/*      seeking to end of file instead of writing zero blocks.          */
+/* -------------------------------------------------------------------- */
+    else if( nCompression == COMPRESSION_NONE && (nBitsPerSample % 8) == 0 )
+    {
+        // Only use libtiff to write the first sparse block to ensure that it
+        // will serialize offset and count arrays back to disk.
+        int nCountBlocksToZero = 0;
+        for( int iBlock = 0; iBlock < nBlockCount; ++iBlock )
+        {
+            if( panByteCounts[iBlock] == 0 )
+            {
+                if( nCountBlocksToZero == 0 )
+                {
+                    const bool bWriteEmptyTilesBak = bWriteEmptyTiles;
+                    bWriteEmptyTiles = true;
+                    const bool bOK =
+                        WriteEncodedTileOrStrip( iBlock, pabyData,
+                                                 FALSE ) == CE_None;
+                    bWriteEmptyTiles = bWriteEmptyTilesBak;
+                    if( !bOK )
+                        break;
+                }
+                nCountBlocksToZero++;
+            }
+        }
+        CPLFree( pabyData );
+
+        --nCountBlocksToZero;
+
+        // And then seek to end of file for other ones.
+        if( nCountBlocksToZero > 0 )
+        {
+            toff_t *panByteOffsets = NULL;
+
+            if( TIFFIsTiled( hTIFF ) )
+                TIFFGetField( hTIFF, TIFFTAG_TILEOFFSETS, &panByteOffsets );
+            else
+                TIFFGetField( hTIFF, TIFFTAG_STRIPOFFSETS, &panByteOffsets );
+
+            if( panByteOffsets == NULL )
+            {
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "FillEmptyTiles() failed because panByteOffsets == NULL");
+                return;
+            }
+
+            VSILFILE* fpTIF = VSI_TIFFGetVSILFile(TIFFClientdata( hTIFF ));
+            VSIFSeekL( fpTIF, 0, SEEK_END );
+            const vsi_l_offset nOffset = VSIFTellL(fpTIF);
+
+            vsi_l_offset iBlockToZero = 0;
+            for( int iBlock = 0; iBlock < nBlockCount; ++iBlock )
+            {
+                if( panByteCounts[iBlock] == 0 )
+                {
+                    panByteOffsets[iBlock] = static_cast<toff_t>(
+                                        nOffset + iBlockToZero * nBlockBytes);
+                    panByteCounts[iBlock] = nBlockBytes;
+                    iBlockToZero++;
+                }
+            }
+            CPLAssert( iBlockToZero ==
+                       static_cast<vsi_l_offset>(nCountBlocksToZero) );
+
+            if( VSIFTruncateL( fpTIF,
+                               nOffset + iBlockToZero * nBlockBytes ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Cannot initialize empty blocks");
+            }
+        }
+
         return;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Check all blocks, writing out data for uninitialized blocks.    */
 /* -------------------------------------------------------------------- */
-    for( int iBlock = 0; iBlock < nBlockCount; iBlock++ )
+
+    GByte* pabyRaw = NULL;
+    vsi_l_offset nRawSize = 0;
+    for( int iBlock = 0; iBlock < nBlockCount; ++iBlock )
     {
         if( panByteCounts[iBlock] == 0 )
         {
-            if( WriteEncodedTileOrStrip( iBlock, pabyData, FALSE ) != CE_None )
-                break;
+            if( pabyRaw == NULL )
+            {
+                if( WriteEncodedTileOrStrip( iBlock, pabyData, FALSE
+                                                                ) != CE_None )
+                    break;
+                vsi_l_offset nOffset = 0;
+                bool b = IsBlockAvailable( iBlock, &nOffset, &nRawSize);
+#ifdef DEBUG
+                CPLAssert(b);
+#else
+                CPL_IGNORE_RET_VAL(b);
+#endif
+                // When using compression, get back the compressed block
+                // so we can use the raw API to write it faster.
+                if( nCompression != COMPRESSION_NONE )
+                {
+                    pabyRaw = static_cast<GByte*>(
+                            VSI_MALLOC_VERBOSE(static_cast<int>(nRawSize)));
+                    if( pabyRaw )
+                    {
+                        VSILFILE* fp = VSI_TIFFGetVSILFile(
+                                                    TIFFClientdata( hTIFF ));
+                        const vsi_l_offset nCurOffset = VSIFTellL(fp);
+                        VSIFSeekL(fp, nOffset, SEEK_SET);
+                        VSIFReadL(pabyRaw, 1, static_cast<int>(nRawSize), fp);
+                        VSIFSeekL(fp, nCurOffset, SEEK_SET);
+                    }
+                }
+            }
+            else
+            {
+                WriteRawStripOrTile( iBlock, pabyRaw,
+                                     static_cast<int>(nRawSize) );
+            }
         }
     }
 
     CPLFree( pabyData );
+    VSIFree( pabyRaw );
+}
+
+/************************************************************************/
+/*                         HasOnlyNoData()                              */
+/************************************************************************/
+
+template<class T>
+static inline bool IsEqualToNoData( T value, T noDataValue )
+{
+    return value == noDataValue;
+}
+
+template<> bool IsEqualToNoData<float>( float value, float noDataValue )
+{
+    return
+        CPLIsNan(noDataValue) ?
+        CPL_TO_BOOL(CPLIsNan(value)) : value == noDataValue;
+}
+
+template<> bool IsEqualToNoData<double>( double value, double noDataValue )
+{
+    return
+        CPLIsNan(noDataValue) ?
+        CPL_TO_BOOL(CPLIsNan(value)) : value == noDataValue;
+}
+
+template<class T>
+bool GTiffDataset::HasOnlyNoDataT( const T* pBuffer, int nWidth, int nHeight,
+                                   int nLineStride, int nComponents )
+{
+    const T noDataValue = static_cast<T>((bNoDataSet) ? dfNoDataValue : 0.0);
+    // Fast test: check the 4 corners and the middle pixel.
+    for( int iBand = 0; iBand < nComponents; iBand++ )
+    {
+        if( !(IsEqualToNoData(pBuffer[iBand], noDataValue) &&
+              IsEqualToNoData(
+                  pBuffer[static_cast<size_t>(nWidth - 1) * nComponents +
+                          iBand],
+                  noDataValue) &&
+              IsEqualToNoData(
+                  pBuffer[(static_cast<size_t>(nHeight-1)/2 * nLineStride +
+                           (nWidth - 1)/2) * nComponents + iBand],
+                  noDataValue) &&
+              IsEqualToNoData(
+                  pBuffer[static_cast<size_t>(nHeight - 1) * nLineStride *
+                          nComponents + iBand], noDataValue) &&
+              IsEqualToNoData(
+                  pBuffer[(static_cast<size_t>(nHeight - 1) * nLineStride +
+                           nWidth - 1) * nComponents + iBand], noDataValue) ) )
+        {
+            return false;
+        }
+    }
+
+    // Test all pixels.
+    for( int iY = 0; iY < nHeight; iY++ )
+    {
+        for( int iX = 0; iX < nWidth * nComponents; iX++ )
+        {
+            if( !IsEqualToNoData(
+                   pBuffer[iY * static_cast<size_t>(nLineStride) * nComponents +
+                           iX], noDataValue) )
+            {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool GTiffDataset::HasOnlyNoData( const void* pBuffer, int nWidth, int nHeight,
+                                  int nLineStride, int nComponents )
+{
+    const GDALDataType eDT = GetRasterBand(1)->GetRasterDataType();
+
+    // In the case where the nodata is 0, we can compare several bytes at
+    // once. Select the largest natural integer type for the architecture.
+#if SIZEOF_VOIDP == 8 || defined(__x86_64__)
+    // We test __x86_64__ for x32 arch where SIZEOF_VOIDP == 4
+    typedef GUInt64 WordType;
+#else
+    typedef unsigned int WordType;
+#endif
+    if( (!bNoDataSet || dfNoDataValue == 0.0) && nWidth == nLineStride
+#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
+        && CPL_IS_ALIGNED(pBuffer, sizeof(WordType))
+#endif
+        )
+    {
+        const GByte* pabyBuffer = reinterpret_cast<const GByte*>(pBuffer);
+        const size_t nSize = static_cast<size_t>(nWidth) * nHeight *
+                             nComponents * GDALGetDataTypeSizeBytes(eDT);
+        size_t i = 0;
+        for( ; i + sizeof(WordType) - 1 < nSize; i += sizeof(WordType) )
+        {
+            if( *(reinterpret_cast<const WordType*>(pabyBuffer + i)) )
+                return false;
+        }
+        for( ; i < nSize; i++ )
+        {
+            if( pabyBuffer[i] )
+                return false;
+        }
+        return true;
+    }
+
+    if( nBitsPerSample == 8 )
+    {
+        if( nSampleFormat == SAMPLEFORMAT_INT )
+        {
+            return HasOnlyNoDataT(reinterpret_cast<const signed char*>(pBuffer),
+                                  nWidth, nHeight, nLineStride, nComponents);
+        }
+        return HasOnlyNoDataT(reinterpret_cast<const GByte*>(pBuffer),
+                              nWidth, nHeight, nLineStride, nComponents);
+    }
+    if( nBitsPerSample == 16 && eDT == GDT_UInt16 )
+    {
+        return HasOnlyNoDataT(reinterpret_cast<const GUInt16*>(pBuffer),
+                              nWidth, nHeight, nLineStride, nComponents);
+    }
+    if( nBitsPerSample == 16 && eDT== GDT_Int16 )
+    {
+        return HasOnlyNoDataT(reinterpret_cast<const GInt16*>(pBuffer),
+                              nWidth, nHeight, nLineStride, nComponents);
+    }
+    if( nBitsPerSample == 32 && eDT == GDT_UInt32 )
+    {
+        return HasOnlyNoDataT(reinterpret_cast<const GUInt32*>(pBuffer),
+                              nWidth, nHeight, nLineStride, nComponents);
+    }
+    if( nBitsPerSample == 32 && eDT == GDT_Int32 )
+    {
+        return HasOnlyNoDataT(reinterpret_cast<const GInt32*>(pBuffer),
+                              nWidth, nHeight, nLineStride, nComponents);
+    }
+    if( nBitsPerSample == 32 && eDT == GDT_Float32 )
+    {
+        return HasOnlyNoDataT(reinterpret_cast<const float*>(pBuffer),
+                              nWidth, nHeight, nLineStride, nComponents);
+    }
+    if( nBitsPerSample == 64 && eDT == GDT_Float64 )
+    {
+        return HasOnlyNoDataT(reinterpret_cast<const double*>(pBuffer),
+                              nWidth, nHeight, nLineStride, nComponents);
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                     IsFirstPixelEqualToNoData()                      */
+/************************************************************************/
+
+inline bool GTiffDataset::IsFirstPixelEqualToNoData( const void* pBuffer )
+{
+    const GDALDataType eDT = GetRasterBand(1)->GetRasterDataType();
+    const double dfEffectiveNoData = (bNoDataSet) ? dfNoDataValue : 0.0;
+    if( nBitsPerSample == 8 )
+    {
+        if( nSampleFormat == SAMPLEFORMAT_INT )
+        {
+            return *(reinterpret_cast<const signed char*>(pBuffer)) ==
+                        static_cast<signed char>(dfEffectiveNoData);
+        }
+        return *(reinterpret_cast<const GByte*>(pBuffer)) ==
+                        static_cast<GByte>(dfEffectiveNoData);
+    }
+    if( nBitsPerSample == 16 && eDT == GDT_UInt16 )
+    {
+        return *(reinterpret_cast<const GUInt16*>(pBuffer)) ==
+                        static_cast<GUInt16>(dfEffectiveNoData);
+    }
+    if( nBitsPerSample == 16 && eDT == GDT_Int16 )
+    {
+        return *(reinterpret_cast<const GInt16*>(pBuffer)) ==
+                        static_cast<GInt16>(dfEffectiveNoData);
+    }
+    if( nBitsPerSample == 32 && eDT == GDT_UInt32 )
+    {
+        return *(reinterpret_cast<const GUInt32*>(pBuffer)) ==
+                        static_cast<GUInt32>(dfEffectiveNoData);
+    }
+    if( nBitsPerSample == 32 && eDT == GDT_Int32 )
+    {
+        return *(reinterpret_cast<const GInt32*>(pBuffer)) ==
+                        static_cast<GInt32>(dfEffectiveNoData);
+    }
+    if( nBitsPerSample == 32 && eDT == GDT_Float32 )
+    {
+        if( CPLIsNan(dfNoDataValue) )
+            return CPL_TO_BOOL(
+                CPLIsNan(*(reinterpret_cast<const float*>(pBuffer))));
+        return *(reinterpret_cast<const float*>(pBuffer)) ==
+                        static_cast<float>(dfEffectiveNoData);
+    }
+    if( nBitsPerSample == 64 && eDT == GDT_Float64 )
+    {
+        if( CPLIsNan(dfEffectiveNoData) )
+            return CPL_TO_BOOL(
+                CPLIsNan(*(reinterpret_cast<const double*>(pBuffer))));
+        return *(reinterpret_cast<const double*>(pBuffer)) == dfEffectiveNoData;
+    }
+    return false;
 }
 
 /************************************************************************/
 /*                        WriteEncodedTile()                            */
 /************************************************************************/
 
-bool GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
-                                    int bPreserveDataBuffer)
+bool GTiffDataset::WriteEncodedTile( uint32 tile, GByte *pabyData,
+                                     int bPreserveDataBuffer )
 {
-    int cc = static_cast<int>(TIFFTileSize( hTIFF ));
-    bool bNeedTileFill = false;
-    int iRow=0, iColumn=0;
-    int nBlocksPerRow=1, nBlocksPerColumn=1;
+    int iRow = 0;
+    int iColumn = 0;
+    int nBlocksPerRow = 1;
+    int nBlocksPerColumn = 1;
+
+/* -------------------------------------------------------------------- */
+/*      Don't write empty blocks in some cases.                         */
+/* -------------------------------------------------------------------- */
+    if( !bWriteEmptyTiles && IsFirstPixelEqualToNoData(pabyData) )
+    {
+        if( !IsBlockAvailable(tile) )
+        {
+            const int nComponents =
+                nPlanarConfig == PLANARCONFIG_CONTIG ? nBands : 1;
+            nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+            nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
+
+            iColumn = (tile % nBlocksPerBand) % nBlocksPerRow;
+            iRow = (tile % nBlocksPerBand) / nBlocksPerRow;
 
-    /*
-    ** Do we need to spread edge values right or down for a partial
-    ** JPEG encoded tile?  We do this to avoid edge artifacts.
-    */
+            const int nActualBlockWidth =
+                ( iColumn == nBlocksPerRow - 1 ) ?
+                nRasterXSize - iColumn * nBlockXSize : nBlockXSize;
+            const int nActualBlockHeight =
+                ( iRow == nBlocksPerColumn - 1 ) ?
+                nRasterYSize - iRow * nBlockYSize : nBlockYSize;
+
+            if( HasOnlyNoData(pabyData,
+                              nActualBlockWidth, nActualBlockHeight,
+                              nBlockXSize, nComponents ) )
+            {
+                return true;
+            }
+        }
+    }
+
+    // Do we need to spread edge values right or down for a partial
+    // JPEG encoded tile?  We do this to avoid edge artifacts.
+    bool bNeedTileFill = false;
     if( nCompression == COMPRESSION_JPEG )
     {
         nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
@@ -6525,52 +7757,50 @@ bool GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
             bNeedTileFill = true;
     }
 
-    /*
-    ** If we need to fill out the tile, or if we want to prevent
-    ** TIFFWriteEncodedTile from altering the buffer as part of
-    ** byte swapping the data on write then we will need a temporary
-    ** working buffer.  If not, we can just do a direct write.
-    */
-    if (bPreserveDataBuffer
+    // If we need to fill out the tile, or if we want to prevent
+    // TIFFWriteEncodedTile from altering the buffer as part of
+    // byte swapping the data on write then we will need a temporary
+    // working buffer.  If not, we can just do a direct write.
+    const int cc = static_cast<int>(TIFFTileSize( hTIFF ));
+
+    if( bPreserveDataBuffer
         && (TIFFIsByteSwapped(hTIFF) || bNeedTileFill || bHasDiscardedLsb) )
     {
-        if (cc != nTempWriteBufferSize)
+        if( cc != nTempWriteBufferSize )
         {
             pabyTempWriteBuffer = CPLRealloc(pabyTempWriteBuffer, cc);
             nTempWriteBufferSize = cc;
         }
         memcpy(pabyTempWriteBuffer, pabyData, cc);
 
-        pabyData = (GByte *) pabyTempWriteBuffer;
+        pabyData = static_cast<GByte *>( pabyTempWriteBuffer );
     }
 
-    /*
-    ** Perform tile fill if needed.
-    */
+    // Perform tile fill if needed.
     // TODO: we should also handle the case of nBitsPerSample == 12
-    // but this is more involved...
+    // but this is more involved.
     if( bNeedTileFill && nBitsPerSample == 8 )
     {
-        int nRightPixelsToFill = 0;
-        int nBottomPixelsToFill = 0;
-        unsigned int iX, iY, iSrcX, iSrcY;
-        int nComponents = 1;
-        if( nPlanarConfig == PLANARCONFIG_CONTIG )
-            nComponents = nBands;
+        const int nComponents =
+            nPlanarConfig == PLANARCONFIG_CONTIG ? nBands : 1;
 
         CPLDebug( "GTiff", "Filling out jpeg edge tile on write." );
 
-        if( iColumn == nBlocksPerRow - 1 )
-            nRightPixelsToFill = nBlockXSize * (iColumn+1) - nRasterXSize;
-        if( iRow == nBlocksPerColumn - 1 )
-            nBottomPixelsToFill = nBlockYSize * (iRow+1) - nRasterYSize;
+        const int nRightPixelsToFill =
+            iColumn == nBlocksPerRow - 1 ?
+            nBlockXSize * (iColumn + 1) - nRasterXSize :
+            0;
+        const int nBottomPixelsToFill =
+            iRow == nBlocksPerColumn - 1 ?
+            nBlockYSize * (iRow + 1) - nRasterYSize :
+            0;
 
         // Fill out to the right.
-        iSrcX = nBlockXSize - nRightPixelsToFill - 1;
+        const int iSrcX = nBlockXSize - nRightPixelsToFill - 1;
 
-        for( iX = iSrcX+1; iX < nBlockXSize; iX++ )
+        for( int iX = iSrcX + 1; iX < nBlockXSize; ++iX )
         {
-            for( iY = 0; iY < nBlockYSize; iY++ )
+            for( int iY = 0; iY < nBlockYSize; ++iY )
             {
                 memcpy( pabyData + (nBlockXSize * iY + iX) * nComponents,
                         pabyData + (nBlockXSize * iY + iSrcX) * nComponents,
@@ -6578,9 +7808,9 @@ bool GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
             }
         }
 
-        // now fill out the bottom.
-        iSrcY = nBlockYSize - nBottomPixelsToFill - 1;
-        for( iY = iSrcY+1; iY < nBlockYSize; iY++ )
+        // Now fill out the bottom.
+        const int iSrcY = nBlockYSize - nBottomPixelsToFill - 1;
+        for( int iY = iSrcY + 1; iY < nBlockYSize; ++iY )
         {
             memcpy( pabyData + nBlockXSize * nComponents * iY,
                     pabyData + nBlockXSize * nComponents * iSrcY,
@@ -6588,25 +7818,27 @@ bool GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
         }
     }
 
-    if( bHasDiscardedLsb != 0 )
+    if( bHasDiscardedLsb )
     {
-        int iBand = (nPlanarConfig == PLANARCONFIG_SEPARATE ) ? (int)tile / nBlocksPerBand : -1;
+        const int iBand =
+            nPlanarConfig == PLANARCONFIG_SEPARATE ?
+            static_cast<int>(tile) / nBlocksPerBand : -1;
         DiscardLsb(pabyData, cc, iBand);
     }
 
     if( bStreamingOut )
     {
-        if( tile != (uint32)(nLastWrittenBlockId + 1) )
+        if( tile != static_cast<uint32>(nLastWrittenBlockId + 1) )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Attempt to write block %d whereas %d was expected",
-                     tile,  nLastWrittenBlockId + 1);
+                     tile, nLastWrittenBlockId + 1);
             return false;
         }
-        if( (int)VSIFWriteL(pabyData, 1, cc, fpToWrite) != cc )
+        if( static_cast<int>( VSIFWriteL(pabyData, 1, cc, fpToWrite) ) != cc )
         {
-            CPLError(CE_Failure, CPLE_FileIO, "Could not write %d bytes",
-                     cc);
+            CPLError( CE_Failure, CPLE_FileIO, "Could not write %d bytes",
+                      cc );
             return false;
         }
         nLastWrittenBlockId = tile;
@@ -6619,14 +7851,15 @@ bool GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
     if( SubmitCompressionJob(tile, pabyData, cc, nBlockYSize) )
         return true;
 
-    // libtiff 4.0.6 or older do not always properly report write errors
+    // libtiff 4.0.6 or older do not always properly report write errors.
 #if !defined(INTERNAL_LIBTIFF) && (!defined(TIFFLIB_VERSION) || (TIFFLIB_VERSION <= 20150912))
-    CPLErr eBefore = CPLGetLastErrorType();
+    const CPLErr eBefore = CPLGetLastErrorType();
 #endif
-    bool bRet = static_cast<int>(TIFFWriteEncodedTile(hTIFF, tile, pabyData, cc)) == cc;
+    const bool bRet =
+        static_cast<int>(TIFFWriteEncodedTile(hTIFF, tile, pabyData, cc)) == cc;
 #if !defined(INTERNAL_LIBTIFF) && (!defined(TIFFLIB_VERSION) || (TIFFLIB_VERSION <= 20150912))
     if( eBefore == CE_None && CPLGetLastErrorType() == CE_Failure )
-        bRet = FALSE;
+        return false;
 #endif
     return bRet;
 }
@@ -6635,8 +7868,8 @@ bool GTiffDataset::WriteEncodedTile(uint32 tile, GByte *pabyData,
 /*                        WriteEncodedStrip()                           */
 /************************************************************************/
 
-bool GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
-                                     int bPreserveDataBuffer)
+bool GTiffDataset::WriteEncodedStrip( uint32 strip, GByte* pabyData,
+                                      int bPreserveDataBuffer )
 {
     int cc = static_cast<int>(TIFFStripSize( hTIFF ));
 
@@ -6645,15 +7878,34 @@ bool GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
 /*      we need to trim the number of scanlines written to the          */
 /*      amount of valid data we have. (#2748)                           */
 /* -------------------------------------------------------------------- */
-    int nStripWithinBand = strip % nBlocksPerBand;
+    const int nStripWithinBand = strip % nBlocksPerBand;
     int nStripHeight = nRowsPerStrip;
 
-    if( (int) ((nStripWithinBand+1) * nRowsPerStrip) > GetRasterYSize() )
+    if( nStripWithinBand * nStripHeight > GetRasterYSize() - nStripHeight )
     {
         nStripHeight = GetRasterYSize() - nStripWithinBand * nRowsPerStrip;
         cc = (cc / nRowsPerStrip) * nStripHeight;
         CPLDebug( "GTiff", "Adjusted bytes to write from %d to %d.",
-                  (int) TIFFStripSize(hTIFF), cc );
+                  static_cast<int>(TIFFStripSize(hTIFF)), cc );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Don't write empty blocks in some cases.                         */
+/* -------------------------------------------------------------------- */
+    if( !bWriteEmptyTiles && IsFirstPixelEqualToNoData(pabyData) )
+    {
+        if( !IsBlockAvailable(strip) )
+        {
+            const int nComponents =
+                nPlanarConfig == PLANARCONFIG_CONTIG ? nBands : 1;
+
+            if( HasOnlyNoData(pabyData,
+                              nBlockXSize, nStripHeight,
+                              nBlockXSize, nComponents ) )
+            {
+                return true;
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -6661,33 +7913,35 @@ bool GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
 /*      byte-swapping is necessary so we use a temporary buffer         */
 /*      before calling it.                                              */
 /* -------------------------------------------------------------------- */
-    if (bPreserveDataBuffer && (TIFFIsByteSwapped(hTIFF) || bHasDiscardedLsb))
+    if( bPreserveDataBuffer && (TIFFIsByteSwapped(hTIFF) || bHasDiscardedLsb) )
     {
-        if (cc != nTempWriteBufferSize)
+        if( cc != nTempWriteBufferSize )
         {
             pabyTempWriteBuffer = CPLRealloc(pabyTempWriteBuffer, cc);
             nTempWriteBufferSize = cc;
         }
         memcpy(pabyTempWriteBuffer, pabyData, cc);
-        pabyData = (GByte *) pabyTempWriteBuffer;
+        pabyData = static_cast<GByte *>( pabyTempWriteBuffer );
     }
 
-    if( bHasDiscardedLsb != 0 )
+    if( bHasDiscardedLsb )
     {
-        int iBand = (nPlanarConfig == PLANARCONFIG_SEPARATE ) ? (int)strip / nBlocksPerBand : -1;
+        int iBand =
+            nPlanarConfig == PLANARCONFIG_SEPARATE ?
+            static_cast<int>(strip) / nBlocksPerBand : -1;
         DiscardLsb(pabyData, cc, iBand);
     }
 
     if( bStreamingOut )
     {
-        if( strip != (uint32)(nLastWrittenBlockId + 1) )
+        if( strip != static_cast<uint32>(nLastWrittenBlockId + 1) )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Attempt to write block %d whereas %d was expected",
-                     strip,  nLastWrittenBlockId + 1);
+                     strip, nLastWrittenBlockId + 1);
             return false;
         }
-        if( (int)VSIFWriteL(pabyData, 1, cc, fpToWrite) != cc )
+        if( static_cast<int>( VSIFWriteL(pabyData, 1, cc, fpToWrite) ) != cc )
         {
             CPLError(CE_Failure, CPLE_FileIO, "Could not write %d bytes",
                      cc);
@@ -6703,11 +7957,13 @@ bool GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
     if( SubmitCompressionJob(strip, pabyData, cc, nStripHeight) )
         return true;
 
-    // libtiff 4.0.6 or older do not always properly report write errors
+    // libtiff 4.0.6 or older do not always properly report write errors.
 #if !defined(INTERNAL_LIBTIFF) && (!defined(TIFFLIB_VERSION) || (TIFFLIB_VERSION <= 20150912))
     CPLErr eBefore = CPLGetLastErrorType();
 #endif
-    bool bRet = static_cast<int>(TIFFWriteEncodedStrip(hTIFF, strip, pabyData, cc)) == cc;
+    bool bRet =
+        static_cast<int>(TIFFWriteEncodedStrip( hTIFF, strip,
+                                                pabyData, cc)) == cc;
 #if !defined(INTERNAL_LIBTIFF) && (!defined(TIFFLIB_VERSION) || (TIFFLIB_VERSION <= 20150912))
     if( eBefore == CE_None && CPLGetLastErrorType() == CE_Failure )
         bRet = FALSE;
@@ -6719,24 +7975,22 @@ bool GTiffDataset::WriteEncodedStrip(uint32 strip, GByte* pabyData,
 /*                        InitCompressionThreads()                      */
 /************************************************************************/
 
-void GTiffDataset::InitCompressionThreads(char** papszOptions)
+void GTiffDataset::InitCompressionThreads( char** papszOptions )
 {
     const char* pszValue = CSLFetchNameValue( papszOptions, "NUM_THREADS" );
-    if (pszValue == NULL)
+    if( pszValue == NULL )
         pszValue = CPLGetConfigOption("GDAL_NUM_THREADS", NULL);
     if( pszValue )
     {
-        int nThreads;
-        if (EQUAL(pszValue, "ALL_CPUS"))
-            nThreads = CPLGetNumCPUs();
-        else
-            nThreads = atoi(pszValue);
+        const int nThreads =
+            EQUAL(pszValue, "ALL_CPUS") ? CPLGetNumCPUs() : atoi(pszValue);
         if( nThreads > 1 )
         {
             if( nCompression == COMPRESSION_NONE ||
                 nCompression == COMPRESSION_JPEG )
             {
-                CPLDebug("GTiff", "NUM_THREADS ignored with uncompressed or JPEG");
+                CPLDebug( "GTiff",
+                          "NUM_THREADS ignored with uncompressed or JPEG" );
             }
             else
             {
@@ -6751,11 +8005,14 @@ void GTiffDataset::InitCompressionThreads(char** papszOptions)
                 {
                     // Add a margin of an extra job w.r.t thread number
                     // so as to optimize compression time (enables the main
-                    // thread to do boring I/O while all CPUs are working)
+                    // thread to do boring I/O while all CPUs are working).
                     asCompressionJobs.resize(nThreads + 1);
                     memset(&asCompressionJobs[0], 0,
-                           asCompressionJobs.size() * sizeof(GTiffCompressionJob));
-                    for(int i=0;i<(int)asCompressionJobs.size();i++)
+                           asCompressionJobs.size() *
+                           sizeof(GTiffCompressionJob));
+                    for( int i = 0;
+                         i < static_cast<int>(asCompressionJobs.size());
+                         ++i )
                     {
                         asCompressionJobs[i].pszTmpFilename =
                             CPLStrdup(CPLSPrintf("/vsimem/gtiff/thread/job/%p",
@@ -6767,16 +8024,19 @@ void GTiffDataset::InitCompressionThreads(char** papszOptions)
 
                     // This is kind of a hack, but basically using
                     // TIFFWriteRawStrip/Tile and then TIFFReadEncodedStrip/Tile
-                    // does not work on a newly created file, because TIFF_MYBUFFER
-                    // is not set in tif_flags
-                    // (if using TIFFWriteEncodedStrip/Tile first, TIFFWriteBufferSetup()
-                    // is automatically called)
-                    // This should likely rather fixed in libtiff itself...
+                    // does not work on a newly created file, because
+                    // TIFF_MYBUFFER is not set in tif_flags
+                    // (if using TIFFWriteEncodedStrip/Tile first,
+                    // TIFFWriteBufferSetup() is automatically called).
+                    // This should likely rather fixed in libtiff itself.
                     TIFFWriteBufferSetup(hTIFF, NULL, -1);
                 }
             }
         }
-        else if (nThreads < 0 || (!EQUAL(pszValue, "0") && !EQUAL(pszValue, "1") && !EQUAL(pszValue, "ALL_CPUS")) )
+        else if( nThreads < 0 ||
+                 (!EQUAL(pszValue, "0") &&
+                  !EQUAL(pszValue, "1") &&
+                  !EQUAL(pszValue, "ALL_CPUS")) )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Invalid value for NUM_THREADS: %s", pszValue);
@@ -6788,11 +8048,10 @@ void GTiffDataset::InitCompressionThreads(char** papszOptions)
 /*                       GetGTIFFKeysFlavor()                           */
 /************************************************************************/
 
-static GTIFFKeysFlavorEnum GetGTIFFKeysFlavor(char** papszOptions)
+static GTIFFKeysFlavorEnum GetGTIFFKeysFlavor( char** papszOptions )
 {
-    const char* pszGeoTIFFKeysFlavor = CSLFetchNameValueDef(papszOptions,
-                                                            "GEOTIFF_KEYS_FLAVOR",
-                                                            "STANDARD");
+    const char* pszGeoTIFFKeysFlavor =
+        CSLFetchNameValueDef( papszOptions, "GEOTIFF_KEYS_FLAVOR", "STANDARD" );
     if( EQUAL(pszGeoTIFFKeysFlavor, "ESRI_PE") )
         return GEOTIFF_KEYS_ESRI_PE;
     return GEOTIFF_KEYS_STANDARD;
@@ -6802,7 +8061,7 @@ static GTIFFKeysFlavorEnum GetGTIFFKeysFlavor(char** papszOptions)
 /*                      InitCreationOrOpenOptions()                     */
 /************************************************************************/
 
-void GTiffDataset::InitCreationOrOpenOptions(char** papszOptions)
+void GTiffDataset::InitCreationOrOpenOptions( char** papszOptions )
 {
     InitCompressionThreads(papszOptions);
 
@@ -6813,18 +8072,16 @@ void GTiffDataset::InitCreationOrOpenOptions(char** papszOptions)
 /*                      ThreadCompressionFunc()                         */
 /************************************************************************/
 
-void GTiffDataset::ThreadCompressionFunc(void* pData)
+void GTiffDataset::ThreadCompressionFunc( void* pData )
 {
-    GTiffCompressionJob* psJob = (GTiffCompressionJob*)pData;
+    GTiffCompressionJob* psJob = static_cast<GTiffCompressionJob *>(pData);
     GTiffDataset* poDS = psJob->poDS;
 
     VSILFILE* fpTmp = VSIFOpenL(psJob->pszTmpFilename, "wb+");
     TIFF* hTIFFTmp = VSI_TIFFOpen(psJob->pszTmpFilename,
-        (psJob->bTIFFIsBigEndian) ? "wb+" : "wl+", fpTmp);
+        psJob->bTIFFIsBigEndian ? "wb+" : "wl+", fpTmp);
     CPLAssert( hTIFFTmp != NULL );
-    int nBlockXSize, nBlockYSize;
-    poDS->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
-    TIFFSetField(hTIFFTmp, TIFFTAG_IMAGEWIDTH, nBlockXSize);
+    TIFFSetField(hTIFFTmp, TIFFTAG_IMAGEWIDTH, poDS->nBlockXSize);
     TIFFSetField(hTIFFTmp, TIFFTAG_IMAGELENGTH, psJob->nHeight);
     TIFFSetField(hTIFFTmp, TIFFTAG_BITSPERSAMPLE, poDS->nBitsPerSample);
     TIFFSetField(hTIFFTmp, TIFFTAG_COMPRESSION, poDS->nCompression);
@@ -6840,9 +8097,9 @@ void GTiffDataset::ThreadCompressionFunc(void* pData)
     TIFFSetField(hTIFFTmp, TIFFTAG_ROWSPERSTRIP, poDS->nBlockYSize);
     TIFFSetField(hTIFFTmp, TIFFTAG_PLANARCONFIG, poDS->nPlanarConfig);
 
-    bool bOK
-        = (TIFFWriteEncodedStrip(hTIFFTmp, 0, psJob->pabyBuffer,
-                                 psJob->nBufferSize) == psJob->nBufferSize);
+    bool bOK =
+        TIFFWriteEncodedStrip(hTIFFTmp, 0, psJob->pabyBuffer,
+                              psJob->nBufferSize) == psJob->nBufferSize;
 
     int nOffset = 0;
     if( bOK )
@@ -6852,13 +8109,14 @@ void GTiffDataset::ThreadCompressionFunc(void* pData)
         TIFFGetField(hTIFFTmp, TIFFTAG_STRIPOFFSETS, &panOffsets);
         TIFFGetField(hTIFFTmp, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts);
 
-        nOffset = (int) panOffsets[0];
-        psJob->nCompressedBufferSize = (int) panByteCounts[0];
+        nOffset = static_cast<int>( panOffsets[0]);
+        psJob->nCompressedBufferSize = static_cast<int>( panByteCounts[0] );
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Error when compressing strip/tile %d",
-                 psJob->nStripOrTile);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error when compressing strip/tile %d",
+                  psJob->nStripOrTile);
     }
 
     XTIFFClose(hTIFFTmp);
@@ -6867,8 +8125,9 @@ void GTiffDataset::ThreadCompressionFunc(void* pData)
         if( bOK )
         {
             bOK = false;
-            CPLError(CE_Failure, CPLE_AppDefined, "Error when compressing strip/tile %d",
-                    psJob->nStripOrTile);
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Error when compressing strip/tile %d",
+                      psJob->nStripOrTile);
         }
     }
 
@@ -6876,9 +8135,10 @@ void GTiffDataset::ThreadCompressionFunc(void* pData)
     {
         vsi_l_offset nFileSize = 0;
         GByte* pabyCompressedBuffer = VSIGetMemFileBuffer(psJob->pszTmpFilename,
-                                                                &nFileSize,
-                                                                FALSE);
-        CPLAssert(nOffset + psJob->nCompressedBufferSize <= (int)nFileSize);
+                                                          &nFileSize,
+                                                          FALSE);
+        CPLAssert( nOffset + psJob->nCompressedBufferSize <=
+                   static_cast<int>(nFileSize) );
         psJob->pabyCompressedBuffer = pabyCompressedBuffer + nOffset;
     }
     else
@@ -6888,7 +8148,7 @@ void GTiffDataset::ThreadCompressionFunc(void* pData)
     }
 
     CPLAcquireMutex(poDS->hCompressThreadPoolMutex, 1000.0);
-    psJob->bReady = TRUE;
+    psJob->bReady = true;
     CPLReleaseMutex(poDS->hCompressThreadPoolMutex);
 }
 
@@ -6896,24 +8156,31 @@ void GTiffDataset::ThreadCompressionFunc(void* pData)
 /*                        WriteRawStripOrTile()                         */
 /************************************************************************/
 
-void GTiffDataset::WriteRawStripOrTile(int nStripOrTile,
-                                       GByte* pabyCompressedBuffer,
-                                       int nCompressedBufferSize)
+void GTiffDataset::WriteRawStripOrTile( int nStripOrTile,
+                                        GByte* pabyCompressedBuffer,
+                                        int nCompressedBufferSize )
 {
-    //CPLDebug("GTIFF", "Writing raw strip/tile %d, size %d",
-    //         nStripOrTile, nCompressedBufferSize);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GTIFF", "Writing raw strip/tile %d, size %d",
+             nStripOrTile, nCompressedBufferSize);
+#endif
     toff_t *panOffsets = NULL;
-    if( TIFFGetField( hTIFF,
-        TIFFIsTiled( hTIFF ) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, &panOffsets ) &&
-        panOffsets[nStripOrTile] != 0 )
-    {
-        // Make sure that if the tile/strip already exists, we write at end of file
+    if( TIFFGetField(
+            hTIFF,
+            TIFFIsTiled( hTIFF ) ?
+            TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, &panOffsets ) &&
+            panOffsets[nStripOrTile] != 0 )
+    {
+        // Make sure that if the tile/strip already exists,
+        // we write at end of file.
         TIFFSetWriteOffset(hTIFF, 0);
     }
     if( TIFFIsTiled( hTIFF ) )
-        TIFFWriteRawTile(hTIFF, nStripOrTile, pabyCompressedBuffer, nCompressedBufferSize);
+        TIFFWriteRawTile( hTIFF, nStripOrTile, pabyCompressedBuffer,
+                          nCompressedBufferSize );
     else
-        TIFFWriteRawStrip(hTIFF, nStripOrTile, pabyCompressedBuffer, nCompressedBufferSize);
+        TIFFWriteRawStrip( hTIFF, nStripOrTile, pabyCompressedBuffer,
+                           nCompressedBufferSize );
 }
 
 /************************************************************************/
@@ -6924,7 +8191,7 @@ void GTiffDataset::WaitCompletionForBlock(int nBlockId)
 {
     if( poCompressThreadPool != NULL )
     {
-        for(int i=0;i<(int)asCompressionJobs.size();i++)
+        for( int i = 0; i < static_cast<int>(asCompressionJobs.size()); ++i )
         {
             if( asCompressionJobs[i].nStripOrTile == nBlockId )
             {
@@ -6933,12 +8200,12 @@ void GTiffDataset::WaitCompletionForBlock(int nBlockId)
                          nBlockId);
 
                 CPLAcquireMutex(hCompressThreadPoolMutex, 1000.0);
-                int bReady = asCompressionJobs[i].bReady;
+                const bool bReady = asCompressionJobs[i].bReady;
                 CPLReleaseMutex(hCompressThreadPoolMutex);
                 if( !bReady )
                 {
                     poCompressThreadPool->WaitCompletion(0);
-                    CPLAssert( asCompressionJobs[i].bReady == TRUE );
+                    CPLAssert( asCompressionJobs[i].bReady );
                 }
 
                 if( asCompressionJobs[i].nCompressedBufferSize )
@@ -6949,7 +8216,7 @@ void GTiffDataset::WaitCompletionForBlock(int nBlockId)
                 }
                 asCompressionJobs[i].pabyCompressedBuffer = NULL;
                 asCompressionJobs[i].nBufferSize = 0;
-                asCompressionJobs[i].bReady = FALSE;
+                asCompressionJobs[i].bReady = false;
                 asCompressionJobs[i].nStripOrTile = -1;
                 return;
             }
@@ -6961,8 +8228,8 @@ void GTiffDataset::WaitCompletionForBlock(int nBlockId)
 /*                      SubmitCompressionJob()                          */
 /************************************************************************/
 
-int GTiffDataset::SubmitCompressionJob(int nStripOrTile, GByte* pabyData,
-                                       int cc, int nHeight)
+bool GTiffDataset::SubmitCompressionJob( int nStripOrTile, GByte* pabyData,
+                                         int cc, int nHeight )
 {
 /* -------------------------------------------------------------------- */
 /*      Should we do compression in a worker thread ?                   */
@@ -6972,15 +8239,16 @@ int GTiffDataset::SubmitCompressionJob(int nStripOrTile, GByte* pabyData,
             nCompression == COMPRESSION_LZW ||
             nCompression == COMPRESSION_PACKBITS ||
             nCompression == COMPRESSION_LZMA) ) )
-        return FALSE;
+        return false;
 
     int nNextCompressionJobAvail = -1;
-    // Wait that at least one job is finished
-    poCompressThreadPool->WaitCompletion(static_cast<int>(asCompressionJobs.size() - 1));
-    for(int i=0;i<(int)asCompressionJobs.size();i++)
+    // Wait that at least one job is finished.
+    poCompressThreadPool->WaitCompletion(
+        static_cast<int>(asCompressionJobs.size() - 1) );
+    for( int i = 0; i < static_cast<int>(asCompressionJobs.size()); ++i )
     {
         CPLAcquireMutex(hCompressThreadPoolMutex, 1000.0);
-        int bReady = asCompressionJobs[i].bReady;
+        const bool bReady = asCompressionJobs[i].bReady;
         CPLReleaseMutex(hCompressThreadPoolMutex);
         if( bReady )
         {
@@ -6992,7 +8260,7 @@ int GTiffDataset::SubmitCompressionJob(int nStripOrTile, GByte* pabyData,
             }
             asCompressionJobs[i].pabyCompressedBuffer = NULL;
             asCompressionJobs[i].nBufferSize = 0;
-            asCompressionJobs[i].bReady = FALSE;
+            asCompressionJobs[i].bReady = false;
             asCompressionJobs[i].nStripOrTile = -1;
         }
         if( asCompressionJobs[i].nBufferSize == 0 )
@@ -7005,28 +8273,29 @@ int GTiffDataset::SubmitCompressionJob(int nStripOrTile, GByte* pabyData,
 
     GTiffCompressionJob* psJob = &asCompressionJobs[nNextCompressionJobAvail];
     psJob->poDS = this;
-    psJob->bTIFFIsBigEndian = TIFFIsBigEndian(hTIFF);
-    psJob->pabyBuffer = (GByte*)CPLRealloc(psJob->pabyBuffer, cc);
+    psJob->bTIFFIsBigEndian = CPL_TO_BOOL( TIFFIsBigEndian(hTIFF) );
+    psJob->pabyBuffer =
+        static_cast<GByte*>( CPLRealloc(psJob->pabyBuffer, cc) );
     memcpy(psJob->pabyBuffer, pabyData, cc);
     psJob->nBufferSize = cc;
     psJob->nHeight = nHeight;
     psJob->nStripOrTile = nStripOrTile;
     psJob->nPredictor = PREDICTOR_NONE;
-    if ( nCompression == COMPRESSION_LZW ||
-         nCompression == COMPRESSION_ADOBE_DEFLATE )
+    if( nCompression == COMPRESSION_LZW ||
+        nCompression == COMPRESSION_ADOBE_DEFLATE )
     {
         TIFFGetField( hTIFF, TIFFTAG_PREDICTOR, &psJob->nPredictor );
     }
 
     poCompressThreadPool->SubmitJob(ThreadCompressionFunc, psJob);
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
-/*                          DiscardLsb()                               */
+/*                          DiscardLsb()                                */
 /************************************************************************/
 
-void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
+void GTiffDataset::DiscardLsb( GByte* pabyBuffer, int nBytes, int iBand )
 {
     if( nBitsPerSample == 8 )
     {
@@ -7034,21 +8303,25 @@ void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
         {
             const int nMask = anMaskLsb[iBand];
             const int nOffset = anOffsetLsb[iBand];
-            for( int i = 0; i < nBytes; i ++ )
+            for( int i = 0; i < nBytes; ++i )
             {
-                if( pabyBuffer[i] != 255 ) /* we want to keep 255 in case it is alpha */
-                    pabyBuffer[i] = static_cast<GByte>((pabyBuffer[i] & nMask) | nOffset);
+                // Keep 255 in case it is alpha.
+                if( pabyBuffer[i] != 255 )
+                    pabyBuffer[i] =
+                        static_cast<GByte>((pabyBuffer[i] & nMask) | nOffset);
             }
         }
         else
         {
             for( int i = 0; i < nBytes; i += nBands )
             {
-                for( int j = 0; j < nBands; j ++ )
+                for( int j = 0; j < nBands; ++j )
                 {
-                    if( pabyBuffer[i + j] != 255 ) /* we want to keep 255 in case it is alpha */
-                        pabyBuffer[i + j] = static_cast<GByte>((pabyBuffer[i + j] &
-                                    anMaskLsb[j]) | anOffsetLsb[j]);
+                    // Keep 255 in case it is alpha.
+                    if( pabyBuffer[i + j] != 255 )
+                        pabyBuffer[i + j] =
+                            static_cast<GByte>((pabyBuffer[i + j] &
+                                                anMaskLsb[j]) | anOffsetLsb[j]);
                 }
             }
         }
@@ -7059,19 +8332,25 @@ void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
         {
             const int nMask = anMaskLsb[iBand];
             const int nOffset = anOffsetLsb[iBand];
-            for( int i = 0; i < nBytes/2; i ++ )
+            for( int i = 0; i < nBytes/2; ++i )
             {
-                ((GUInt16*)pabyBuffer)[i] = static_cast<GUInt16>((((GUInt16*)pabyBuffer)[i] & nMask) | nOffset);
+                reinterpret_cast<GUInt16*>(pabyBuffer)[i] =
+                    static_cast<GUInt16>(
+                        (reinterpret_cast<GUInt16 *>(pabyBuffer)[i] & nMask) |
+                        nOffset);
             }
         }
         else
         {
             for( int i = 0; i < nBytes/2; i += nBands )
             {
-                for( int j = 0; j < nBands; j ++ )
+                for( int j = 0; j < nBands; ++j )
                 {
-                    ((GUInt16*)pabyBuffer)[i + j] = static_cast<GUInt16>((((GUInt16*)pabyBuffer)[i + j] &
-                                    anMaskLsb[j]) | anOffsetLsb[j]);
+                    reinterpret_cast<GUInt16*>(pabyBuffer)[i + j] =
+                        static_cast<GUInt16>(
+                            (reinterpret_cast<GUInt16*>(pabyBuffer)[i + j] &
+                             anMaskLsb[j]) |
+                            anOffsetLsb[j]);
                 }
             }
         }
@@ -7082,19 +8361,23 @@ void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
         {
             const int nMask = anMaskLsb[iBand];
             const int nOffset = anOffsetLsb[iBand];
-            for( int i = 0; i < nBytes/4; i ++ )
+            for( int i = 0; i < nBytes/4; ++i )
             {
-                ((GUInt32*)pabyBuffer)[i] = (((GUInt32*)pabyBuffer)[i] & nMask) | nOffset;
+                reinterpret_cast<GUInt32 *>(pabyBuffer)[i] =
+                    (reinterpret_cast<GUInt32*>(pabyBuffer)[i] & nMask) |
+                    nOffset;
             }
         }
         else
         {
             for( int i = 0; i < nBytes/4; i += nBands )
             {
-                for( int j = 0; j < nBands; j ++ )
+                for( int j = 0; j < nBands; ++j )
                 {
-                    ((GUInt32*)pabyBuffer)[i + j] = (((GUInt32*)pabyBuffer)[i + j] &
-                                    anMaskLsb[j]) | anOffsetLsb[j];
+                    reinterpret_cast<GUInt32 *>(pabyBuffer)[i + j] =
+                        (reinterpret_cast<GUInt32 *>(pabyBuffer)[i + j] &
+                         anMaskLsb[j]) |
+                        anOffsetLsb[j];
                 }
             }
         }
@@ -7105,23 +8388,27 @@ void GTiffDataset::DiscardLsb(GByte* pabyBuffer, int nBytes, int iBand)
 /*                  WriteEncodedTileOrStrip()                           */
 /************************************************************************/
 
-CPLErr  GTiffDataset::WriteEncodedTileOrStrip(uint32 tile_or_strip, void* data,
-                                              int bPreserveDataBuffer)
+CPLErr GTiffDataset::WriteEncodedTileOrStrip( uint32 tile_or_strip, void* data,
+                                              int bPreserveDataBuffer )
 {
     CPLErr eErr = CE_None;
 
     if( TIFFIsTiled( hTIFF ) )
     {
-        if( !(WriteEncodedTile(tile_or_strip, (GByte*) data,
-                               bPreserveDataBuffer)) )
+        if( !(WriteEncodedTile(
+               tile_or_strip,
+               static_cast<GByte *>(data),
+               bPreserveDataBuffer)) )
         {
             eErr = CE_Failure;
         }
     }
     else
     {
-        if( !(WriteEncodedStrip(tile_or_strip, (GByte *) data,
-                                bPreserveDataBuffer)) )
+        if( !(WriteEncodedStrip(
+               tile_or_strip,
+               static_cast<GByte *>(data),
+               bPreserveDataBuffer)) )
         {
             eErr = CE_Failure;
         }
@@ -7140,17 +8427,18 @@ CPLErr GTiffDataset::FlushBlockBuf()
     if( nLoadedBlock < 0 || !bLoadedBlockDirty )
         return CE_None;
 
-    bLoadedBlockDirty = FALSE;
+    bLoadedBlockDirty = false;
 
-    if (!SetDirectory())
+    if( !SetDirectory() )
         return CE_Failure;
 
-    CPLErr eErr = WriteEncodedTileOrStrip(nLoadedBlock, pabyBlockBuf, TRUE);
-    if (eErr != CE_None)
+    const CPLErr eErr =
+        WriteEncodedTileOrStrip(nLoadedBlock, pabyBlockBuf, true);
+    if( eErr != CE_None )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                     "WriteEncodedTile/Strip() failed." );
-        bWriteErrorInFlushBlockBuf = TRUE;
+        bWriteErrorInFlushBlockBuf = true;
     }
 
     return eErr;
@@ -7162,7 +8450,7 @@ CPLErr GTiffDataset::FlushBlockBuf()
 /*      Load working block buffer with request block (tile/strip).      */
 /************************************************************************/
 
-CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
+CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, bool bReadFromDisk )
 
 {
     if( nLoadedBlock == nBlockId )
@@ -7171,27 +8459,23 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
 /* -------------------------------------------------------------------- */
 /*      If we have a dirty loaded block, flush it out first.            */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr = CE_None;
     if( nLoadedBlock != -1 && bLoadedBlockDirty )
     {
-        eErr = FlushBlockBuf();
+        const CPLErr eErr = FlushBlockBuf();
         if( eErr != CE_None )
             return eErr;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Get block size.                                                 */
-/* -------------------------------------------------------------------- */
-    int nBlockBufSize;
-    if( TIFFIsTiled(hTIFF) )
-        nBlockBufSize = static_cast<int>(TIFFTileSize( hTIFF ));
-    else
-        nBlockBufSize = static_cast<int>(TIFFStripSize( hTIFF ));
-
-    if ( !nBlockBufSize )
+/* -------------------------------------------------------------------- */
+    const int nBlockBufSize =
+        static_cast<int>(
+            TIFFIsTiled(hTIFF) ? TIFFTileSize(hTIFF) : TIFFStripSize(hTIFF));
+    if( !nBlockBufSize )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Bogus block size; unable to allocate a buffer.");
+                  "Bogus block size; unable to allocate a buffer." );
         return CE_Failure;
     }
 
@@ -7200,10 +8484,11 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
 /* -------------------------------------------------------------------- */
     if( pabyBlockBuf == NULL )
     {
-        pabyBlockBuf = (GByte *) VSI_CALLOC_VERBOSE( 1, nBlockBufSize );
+        pabyBlockBuf =
+            static_cast<GByte *>( VSI_CALLOC_VERBOSE( 1, nBlockBufSize ) );
         if( pabyBlockBuf == NULL )
         {
-            return( CE_Failure );
+            return CE_Failure;
         }
     }
 
@@ -7218,12 +8503,12 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
         return CE_None;
     }
 
-    /* libtiff 3.X doesn't like mixing read&write of JPEG compressed blocks */
-    /* The below hack is necessary due to another hack that consist in */
-    /* writing zero block to force creation of JPEG tables */
+    // libtiff 3.X doesn't like mixing read&write of JPEG compressed blocks
+    // The below hack is necessary due to another hack that consist in
+    // writing zero block to force creation of JPEG tables.
     if( nBlockId == 0 && bDontReloadFirstBlock )
     {
-        bDontReloadFirstBlock = FALSE;
+        bDontReloadFirstBlock = false;
         memset( pabyBlockBuf, 0, nBlockBufSize );
         nLoadedBlock = nBlockId;
         return CE_None;
@@ -7235,13 +8520,15 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
 /*      an error won't be reported in this case. (#1179)                */
 /* -------------------------------------------------------------------- */
     int nBlockReqSize = nBlockBufSize;
-    int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
-    int nBlockYOff = (nBlockId % nBlocksPerBand) / nBlocksPerRow;
+    const int nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+    const int nBlockYOff = (nBlockId % nBlocksPerBand) / nBlocksPerRow;
 
-    if( (int)((nBlockYOff+1) * nBlockYSize) > nRasterYSize )
+    if( nBlockYOff * nBlockYSize > nRasterYSize - nBlockYSize )
     {
         nBlockReqSize = (nBlockBufSize / nBlockYSize)
-            * (nBlockYSize - (((nBlockYOff+1) * nBlockYSize) % nRasterYSize));
+            * (nBlockYSize - static_cast<int>(
+                (static_cast<GIntBig>(nBlockYOff + 1) * nBlockYSize) %
+                    nRasterYSize));
         memset( pabyBlockBuf, 0, nBlockBufSize );
     }
 
@@ -7262,13 +8549,14 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
 /* -------------------------------------------------------------------- */
 /*      Load the block, if it isn't our current block.                  */
 /* -------------------------------------------------------------------- */
+    CPLErr eErr = CE_None;
     if( TIFFIsTiled( hTIFF ) )
     {
         if( TIFFReadEncodedTile(hTIFF, nBlockId, pabyBlockBuf,
                                 nBlockReqSize) == -1
             && !bIgnoreReadErrors )
         {
-            /* Once TIFFError() is properly hooked, this can go away */
+            // Once TIFFError() is properly hooked, this can go away.
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TIFFReadEncodedTile() failed." );
 
@@ -7283,7 +8571,7 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
                                  nBlockReqSize) == -1
             && !bIgnoreReadErrors )
         {
-            /* Once TIFFError() is properly hooked, this can go away */
+            // Once TIFFError() is properly hooked, this can go away.
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TIFFReadEncodedStrip() failed." );
 
@@ -7301,7 +8589,7 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
     {
         nLoadedBlock = -1;
     }
-    bLoadedBlockDirty = FALSE;
+    bLoadedBlockDirty = false;
 
     return eErr;
 }
@@ -7310,31 +8598,40 @@ CPLErr GTiffDataset::LoadBlockBuf( int nBlockId, int bReadFromDisk )
 /*                   GTiffFillStreamableOffsetAndCount()                */
 /************************************************************************/
 
-static void GTiffFillStreamableOffsetAndCount(TIFF* hTIFF, int nSize)
+static void GTiffFillStreamableOffsetAndCount( TIFF* hTIFF, int nSize )
 {
-    uint32  nXSize, nYSize;
+    uint32 nXSize = 0;
+    uint32 nYSize = 0;
     TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
     TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
-    toff_t* panOffset = NULL, *panSize = NULL;
     const bool bIsTiled = CPL_TO_BOOL( TIFFIsTiled(hTIFF) );
-    int nBlockCount = ( bIsTiled ) ? TIFFNumberOfTiles(hTIFF) : TIFFNumberOfStrips(hTIFF);
-    TIFFGetField( hTIFF, bIsTiled ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, &panOffset );
-    TIFFGetField( hTIFF, bIsTiled ? TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS, &panSize );
+    const int nBlockCount =
+        bIsTiled ? TIFFNumberOfTiles(hTIFF) : TIFFNumberOfStrips(hTIFF);
+
+    toff_t *panOffset = NULL;
+    TIFFGetField( hTIFF, bIsTiled ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS,
+                  &panOffset );
+    toff_t *panSize = NULL;
+    TIFFGetField( hTIFF,
+                  bIsTiled ? TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS,
+                  &panSize );
     toff_t nOffset = nSize;
-    int nBlocksPerBand = 1; /* trick to avoid clang static analyzer raising false positive about divide by zero later */
+    // Trick to avoid clang static analyzer raising false positive about
+    // divide by zero later.
+    int nBlocksPerBand = 1;
     uint32 nRowsPerStrip = 0;
-    if( !bIsTiled  )
+    if( !bIsTiled )
     {
         TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &nRowsPerStrip);
-        if( nRowsPerStrip > (uint32)nYSize )
+        if( nRowsPerStrip > static_cast<uint32>(nYSize) )
             nRowsPerStrip = nYSize;
         nBlocksPerBand = DIV_ROUND_UP(nYSize, nRowsPerStrip);
     }
-    for(int i=0;i<nBlockCount;i++)
+    for( int i = 0; i < nBlockCount; ++i )
     {
         int cc = bIsTiled ? static_cast<int>(TIFFTileSize(hTIFF)) :
                             static_cast<int>(TIFFStripSize(hTIFF));
-        if( !bIsTiled  )
+        if( !bIsTiled )
         {
 /* -------------------------------------------------------------------- */
 /*      If this is the last strip in the image, and is partial, then    */
@@ -7342,7 +8639,7 @@ static void GTiffFillStreamableOffsetAndCount(TIFF* hTIFF, int nSize)
 /*      amount of valid data we have. (#2748)                           */
 /* -------------------------------------------------------------------- */
             int nStripWithinBand = i % nBlocksPerBand;
-            if( (int) ((nStripWithinBand+1) * nRowsPerStrip) > (int) nYSize )
+            if( nStripWithinBand * nRowsPerStrip > nYSize - nRowsPerStrip )
             {
                 cc = (cc / nRowsPerStrip)
                     * (nYSize - nStripWithinBand * nRowsPerStrip);
@@ -7364,156 +8661,113 @@ static void GTiffFillStreamableOffsetAndCount(TIFF* hTIFF, int nSize)
 void GTiffDataset::Crystalize()
 
 {
-    if( !bCrystalized )
-    {
-        if( bCheckIfColorInterpMustGoToPamAtCrystalization )
-        {
-            bool bColorInterpToPam = false;
-            if( nPhotometric == PHOTOMETRIC_MINISBLACK )
-            {
-                for( int i=0;i<nBands;i++)
-                {
-                    GDALColorInterp eInterp = GetRasterBand(i+1)->GetColorInterpretation();
-                    if( !(eInterp == GCI_GrayIndex || eInterp == GCI_Undefined ||
-                          (i > 0 && eInterp == GCI_AlphaBand)) )
-                    {
-                        bColorInterpToPam = true;
-                        break;
-                    }
-                }
-            }
-            else if( nPhotometric == PHOTOMETRIC_RGB )
-            {
-                for( int i=0;i<nBands;i++)
-                {
-                    GDALColorInterp eInterp = GetRasterBand(i+1)->GetColorInterpretation();
-                    if( !((i == 0 && eInterp == GCI_RedBand) ||
-                          (i == 1 && eInterp == GCI_GreenBand) ||
-                          (i == 2 && eInterp == GCI_BlueBand) ||
-                          (i >= 3 && (eInterp == GCI_Undefined || eInterp == GCI_AlphaBand))) )
-                    {
-                        bColorInterpToPam = true;
-                        break;
-                    }
-                }
-            }
-            else
-            {
-                bColorInterpToPam = true;
-            }
-            if( bColorInterpToPam )
-            {
-                CPLDebug("GTiff", "Color interpretations have to go to PAM");
-                for( int i=0;i<nBands;i++)
-                {
-                    static_cast<GDALPamRasterBand*>(GetRasterBand(i+1))->
-                        GDALPamRasterBand::SetColorInterpretation(
-                            GetRasterBand(i+1)->GetColorInterpretation() );
-                }
-            }
-            bCheckIfColorInterpMustGoToPamAtCrystalization = false;
-        }
+    if( bCrystalized )
+        return;
 
-        // FIXME? libtiff writes extended tags in the order they are specified
-        // and not in increasing order
-        WriteMetadata( this, hTIFF, TRUE, osProfile, osFilename,
-                       papszCreationOptions );
-        WriteGeoTIFFInfo();
-        if( bNoDataSet )
-            WriteNoDataValue( hTIFF, dfNoDataValue );
+    // TODO: libtiff writes extended tags in the order they are specified
+    // and not in increasing order.
+    WriteMetadata( this, hTIFF, true, osProfile, osFilename,
+                   papszCreationOptions );
+    WriteGeoTIFFInfo();
+    if( bNoDataSet )
+        WriteNoDataValue( hTIFF, dfNoDataValue );
 
-        bMetadataChanged = FALSE;
-        bGeoTIFFInfoChanged = FALSE;
-        bNoDataChanged = FALSE;
-        bNeedsRewrite = FALSE;
+    bMetadataChanged = false;
+    bGeoTIFFInfoChanged = false;
+    bNoDataChanged = false;
+    bNeedsRewrite = false;
 
-        bCrystalized = TRUE;
+    bCrystalized = true;
 
-        TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTiffDataset::Crystalize");
+    TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTiffDataset::Crystalize");
 
-        // Keep zip and tiff quality, and jpegcolormode which get reset when we call
-        // TIFFWriteDirectory
-        int jquality = -1, zquality = -1, nColorMode = -1, nJpegTablesModeIn = -1;
-        TIFFGetField(hTIFF, TIFFTAG_JPEGQUALITY, &jquality);
-        TIFFGetField(hTIFF, TIFFTAG_ZIPQUALITY, &zquality);
-        TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode );
-        TIFFGetField( hTIFF, TIFFTAG_JPEGTABLESMODE, &nJpegTablesModeIn );
+    // Keep zip and tiff quality, and jpegcolormode which get reset when
+    // we call TIFFWriteDirectory.
+    int jquality = -1;
+    TIFFGetField(hTIFF, TIFFTAG_JPEGQUALITY, &jquality);
+    int zquality = -1;
+    TIFFGetField(hTIFF, TIFFTAG_ZIPQUALITY, &zquality);
+    int nColorMode = -1;
+    TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode );
+    int nJpegTablesModeIn = -1;
+    TIFFGetField( hTIFF, TIFFTAG_JPEGTABLESMODE, &nJpegTablesModeIn );
 
+    TIFFWriteDirectory( hTIFF );
+    if( bStreamingOut )
+    {
+        // We need to write twice the directory to be sure that custom
+        // TIFF tags are correctly sorted and that padding bytes have been
+        // added.
+        TIFFSetDirectory( hTIFF, 0 );
         TIFFWriteDirectory( hTIFF );
-        if( bStreamingOut )
-        {
-            /* We need to write twice the directory to be sure that custom */
-            /* TIFF tags are correctly sorted and that padding bytes have been */
-            /* added */
-            TIFFSetDirectory( hTIFF, 0 );
-            TIFFWriteDirectory( hTIFF );
-
-            if( VSIFSeekL( fpL, 0, SEEK_END ) != 0 )
-            {
-                CPLError(CE_Failure, CPLE_FileIO, "Could not seek");
-            }
-            int nSize = (int) VSIFTellL(fpL);
-
-            TIFFSetDirectory( hTIFF, 0 );
-            GTiffFillStreamableOffsetAndCount( hTIFF, nSize );
-            TIFFWriteDirectory( hTIFF );
 
-            vsi_l_offset nDataLength;
-            void* pabyBuffer = VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE);
-            if( (int)VSIFWriteL( pabyBuffer, 1, (int)nDataLength, fpToWrite ) != (int)nDataLength )
-            {
-                CPLError(CE_Failure, CPLE_FileIO, "Could not write %d bytes",
-                        (int)nDataLength);
-            }
-            /* In case of single strip file, there's a libtiff check that would */
-            /* issue a warning since the file hasn't the required size */
-            CPLPushErrorHandler(CPLQuietErrorHandler);
-            TIFFSetDirectory( hTIFF, 0 );
-            CPLPopErrorHandler();
+        if( VSIFSeekL( fpL, 0, SEEK_END ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "Could not seek");
         }
-        else
-            TIFFSetDirectory( hTIFF, 0 );
-
+        const int nSize = static_cast<int>( VSIFTellL(fpL) );
 
-        // Now, reset zip and tiff quality and jpegcolormode.
-        if(jquality > 0)
-            TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, jquality);
-        if(zquality > 0)
-            TIFFSetField(hTIFF, TIFFTAG_ZIPQUALITY, zquality);
-        if (nColorMode >= 0)
-            TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, nColorMode);
-        if (nJpegTablesModeIn >= 0 )
-            TIFFSetField(hTIFF, TIFFTAG_JPEGTABLESMODE, nJpegTablesModeIn);
+        TIFFSetDirectory( hTIFF, 0 );
+        GTiffFillStreamableOffsetAndCount( hTIFF, nSize );
+        TIFFWriteDirectory( hTIFF );
 
-        nDirOffset = TIFFCurrentDirOffset( hTIFF );
+        vsi_l_offset nDataLength = 0;
+        void* pabyBuffer =
+            VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE);
+        if( static_cast<int>(
+                VSIFWriteL( pabyBuffer, 1,
+                            static_cast<int>(nDataLength), fpToWrite ) ) !=
+            static_cast<int>(nDataLength) )
+        {
+            CPLError( CE_Failure, CPLE_FileIO, "Could not write %d bytes",
+                      static_cast<int>(nDataLength) );
+        }
+        // In case of single strip file, there's a libtiff check that would
+        // issue a warning since the file hasn't the required size.
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        TIFFSetDirectory( hTIFF, 0 );
+        CPLPopErrorHandler();
+    }
+    else
+    {
+        TIFFSetDirectory( hTIFF, 0 );
     }
+
+    // Now, reset zip and tiff quality and jpegcolormode.
+    if( jquality > 0 )
+        TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, jquality);
+    if( zquality > 0 )
+        TIFFSetField(hTIFF, TIFFTAG_ZIPQUALITY, zquality);
+    if( nColorMode >= 0 )
+        TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, nColorMode);
+    if( nJpegTablesModeIn >= 0 )
+        TIFFSetField(hTIFF, TIFFTAG_JPEGTABLESMODE, nJpegTablesModeIn);
+
+    nDirOffset = TIFFCurrentDirOffset( hTIFF );
 }
 
 #ifdef INTERNAL_LIBTIFF
 
-#define IO_CACHE_PAGE_SIZE      4096
-
 static
-void GTiffCacheOffsetOrCount(VSILFILE* fp,
-                             vsi_l_offset nBaseOffset,
-                             int nBlockId,
-                             uint32 nstrips,
-                             uint64* panVals,
-                             size_t sizeofval)
+void GTiffCacheOffsetOrCount( VSILFILE* fp,
+                              vsi_l_offset nBaseOffset,
+                              int nBlockId,
+                              uint32 nstrips,
+                              uint64* panVals,
+                              size_t sizeofval )
 {
-    int i, iStartBefore;
-    vsi_l_offset nOffset, nOffsetStartPage, nOffsetEndPage;
-    GByte buffer[2 * IO_CACHE_PAGE_SIZE];
+    static const vsi_l_offset IO_CACHE_PAGE_SIZE = 4096;
 
-    nOffset = nBaseOffset + sizeofval * nBlockId;
-    nOffsetStartPage = (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE;
-    nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE;
+    const vsi_l_offset nOffset = nBaseOffset + sizeofval * nBlockId;
+    const vsi_l_offset nOffsetStartPage =
+        (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE;
+    vsi_l_offset nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE;
 
     if( nOffset + sizeofval > nOffsetEndPage )
         nOffsetEndPage += IO_CACHE_PAGE_SIZE;
     vsi_l_offset nLastStripOffset = nBaseOffset + nstrips * sizeofval;
     if( nLastStripOffset < nOffsetEndPage )
-        nOffsetEndPage  = nLastStripOffset;
+        nOffsetEndPage = nLastStripOffset;
     if( nOffsetStartPage >= nOffsetEndPage )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -7526,19 +8780,26 @@ void GTiffCacheOffsetOrCount(VSILFILE* fp,
         panVals[nBlockId] = 0;
         return;
     }
-    size_t nToRead = (size_t)(nOffsetEndPage - nOffsetStartPage);
-    size_t nRead = VSIFReadL(buffer, 1, nToRead, fp);
+
+    const size_t nToRead =
+        static_cast<size_t>(nOffsetEndPage - nOffsetStartPage);
+    GByte buffer[2 * IO_CACHE_PAGE_SIZE] = {};  // TODO(schwehr): Off the stack.
+    const size_t nRead = VSIFReadL(buffer, 1, nToRead, fp);
     if( nRead < nToRead )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot read offset/size for strile around ~%d", nBlockId);
         memset(buffer + nRead, 0, nToRead - nRead);
     }
-    iStartBefore = - (int)((nOffset - nOffsetStartPage) / sizeofval);
+    int iStartBefore =
+        - static_cast<int>((nOffset - nOffsetStartPage) / sizeofval);
     if( nBlockId + iStartBefore < 0 )
         iStartBefore = -nBlockId;
-    for(i=iStartBefore; (uint32)(nBlockId + i) < nstrips &&
-        (GIntBig)nOffset + (i+1) * (int)sizeofval <= (GIntBig)nOffsetEndPage; i++)
+    for( int i = iStartBefore;
+         static_cast<uint32>(nBlockId + i) < nstrips &&
+         static_cast<GIntBig>(nOffset) + (i + 1) * static_cast<int>(sizeofval) <=
+         static_cast<GIntBig>(nOffsetEndPage);
+         ++i )
     {
         if( sizeofval == 4 )
         {
@@ -7559,22 +8820,25 @@ void GTiffCacheOffsetOrCount(VSILFILE* fp,
     }
 }
 
-#endif /* INTERNAL_LIBTIFF */
+#endif  // INTERNAL_LIBTIFF
 
 /************************************************************************/
 /*                          IsBlockAvailable()                          */
 /*                                                                      */
-/*      Return TRUE if the indicated strip/tile is available.  We       */
+/*      Return true if the indicated strip/tile is available.  We       */
 /*      establish this by testing if the stripbytecount is zero.  If    */
 /*      zero then the block has never been committed to disk.           */
 /************************************************************************/
 
-int GTiffDataset::IsBlockAvailable( int nBlockId )
+bool GTiffDataset::IsBlockAvailable( int nBlockId,
+                                     vsi_l_offset* pnOffset,
+                                     vsi_l_offset* pnSize )
 
 {
 #ifdef INTERNAL_LIBTIFF
 #ifdef DEFER_STRILE_LOAD
-    /* Optimization to avoid fetching the whole Strip/TileCounts and Strip/TileOffsets arrays */
+    // Optimization to avoid fetching the whole Strip/TileCounts and
+    // Strip/TileOffsets arrays.
     if( eAccess == GA_ReadOnly &&
         !(hTIFF->tif_flags & TIFF_SWAB) &&
         hTIFF->tif_dir.td_nstrips > 2 &&
@@ -7587,10 +8851,13 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
         if( hTIFF->tif_dir.td_stripoffset == NULL )
         {
             hTIFF->tif_dir.td_stripoffset =
-                (uint64*) _TIFFmalloc( sizeof(uint64) * hTIFF->tif_dir.td_nstrips );
+                static_cast<uint64 *>( _TIFFmalloc(
+                    sizeof(uint64) * hTIFF->tif_dir.td_nstrips ) );
             hTIFF->tif_dir.td_stripbytecount =
-                (uint64*) _TIFFmalloc( sizeof(uint64) * hTIFF->tif_dir.td_nstrips );
-            if( hTIFF->tif_dir.td_stripoffset && hTIFF->tif_dir.td_stripbytecount )
+                static_cast<uint64 *>( _TIFFmalloc(
+                    sizeof(uint64) * hTIFF->tif_dir.td_nstrips ) );
+            if( hTIFF->tif_dir.td_stripoffset &&
+                hTIFF->tif_dir.td_stripbytecount )
             {
                 memset(hTIFF->tif_dir.td_stripoffset, 0xFF,
                        sizeof(uint64) * hTIFF->tif_dir.td_nstrips );
@@ -7606,19 +8873,23 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
             }
         }
         if( hTIFF->tif_dir.td_stripbytecount == NULL )
-            return FALSE;
+            return false;
         if( ~(hTIFF->tif_dir.td_stripoffset[nBlockId]) == 0 ||
             ~(hTIFF->tif_dir.td_stripbytecount[nBlockId]) == 0 )
         {
             VSILFILE* fp = VSI_TIFFGetVSILFile(TIFFClientdata( hTIFF ));
-            vsi_l_offset nCurOffset = VSIFTellL(fp);
+            const vsi_l_offset nCurOffset = VSIFTellL(fp);
             if( ~(hTIFF->tif_dir.td_stripoffset[nBlockId]) == 0 )
             {
-                vsi_l_offset l_nDirOffset;
+                vsi_l_offset l_nDirOffset = 0;
                 if( hTIFF->tif_flags&TIFF_BIGTIFF )
-                    l_nDirOffset = hTIFF->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8;
+                    l_nDirOffset =
+                        hTIFF->
+                            tif_dir.td_stripoffset_entry.tdir_offset.toff_long8;
                 else
-                    l_nDirOffset = hTIFF->tif_dir.td_stripoffset_entry.tdir_offset.toff_long;
+                    l_nDirOffset =
+                        hTIFF->
+                            tif_dir.td_stripoffset_entry.tdir_offset.toff_long;
 
                 if( hTIFF->tif_dir.td_stripoffset_entry.tdir_type == TIFF_LONG )
                 {
@@ -7642,13 +8913,18 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
 
             if( ~(hTIFF->tif_dir.td_stripbytecount[nBlockId]) == 0 )
             {
-                vsi_l_offset l_nDirOffset;
+                vsi_l_offset l_nDirOffset = 0;
                 if( hTIFF->tif_flags&TIFF_BIGTIFF )
-                    l_nDirOffset = hTIFF->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8;
+                    l_nDirOffset =
+                        hTIFF->
+                            tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8;
                 else
-                    l_nDirOffset = hTIFF->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long;
+                    l_nDirOffset =
+                        hTIFF->
+                            tif_dir.td_stripbytecount_entry.tdir_offset.toff_long;
 
-                if( hTIFF->tif_dir.td_stripbytecount_entry.tdir_type == TIFF_LONG )
+                if( hTIFF->tif_dir.td_stripbytecount_entry.tdir_type ==
+                    TIFF_LONG )
                 {
                     GTiffCacheOffsetOrCount(fp,
                                             l_nDirOffset,
@@ -7669,30 +8945,45 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
             }
             if( VSIFSeekL(fp, nCurOffset, SEEK_SET) != 0 )
             {
-                /* For some reason Coverity tells: */
-                /* Value of non-local "this->hTIFF->tif_dir.td_stripoffset" that was verified to be "NULL" is not restored as it was along other paths. */
-                /* coverity[end_of_path] */
-                return FALSE;
+                // For some reason Coverity reports:
+                // Value of non-local "this->hTIFF->tif_dir.td_stripoffset"
+                // that was verified to be "NULL" is not restored as it was
+                // along other paths.
+                // coverity[end_of_path]
+                return false;
             }
         }
+        if( pnOffset )
+            *pnOffset = hTIFF->tif_dir.td_stripoffset[nBlockId];
+        if( pnSize )
+            *pnSize = hTIFF->tif_dir.td_stripbytecount[nBlockId];
         return hTIFF->tif_dir.td_stripbytecount[nBlockId] != 0;
     }
-#endif /* DEFER_STRILE_LOAD */
-#endif /* INTERNAL_LIBTIFF */
+#endif  // DEFER_STRILE_LOAD
+#endif  // INTERNAL_LIBTIFF
     toff_t *panByteCounts = NULL;
+    toff_t *panOffsets = NULL;
 
     if( ( TIFFIsTiled( hTIFF )
-          && TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts ) )
+          && TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts )
+          && (pnOffset == NULL ||
+              TIFFGetField( hTIFF, TIFFTAG_TILEOFFSETS, &panOffsets )) )
         || ( !TIFFIsTiled( hTIFF )
-          && TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts ) ) )
+          && TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts )
+          && (pnOffset == NULL ||
+              TIFFGetField( hTIFF, TIFFTAG_STRIPOFFSETS, &panOffsets )) ) )
     {
-        if( panByteCounts == NULL )
-            return FALSE;
-        else
-            return panByteCounts[nBlockId] != 0;
+        if( panByteCounts == NULL || (pnOffset != NULL && panOffsets == NULL) )
+            return false;
+
+        if( pnOffset )
+            *pnOffset = panOffsets[nBlockId];
+        if( pnSize )
+            *pnSize = panByteCounts[nBlockId];
+        return panByteCounts[nBlockId] != 0;
     }
-    else
-        return FALSE;
+
+    return false;
 }
 
 /************************************************************************/
@@ -7702,7 +8993,6 @@ int GTiffDataset::IsBlockAvailable( int nBlockId )
 /*      cache if need be.                                               */
 /************************************************************************/
 
-
 void GTiffDataset::FlushCache()
 
 {
@@ -7711,7 +9001,7 @@ void GTiffDataset::FlushCache()
 
 void GTiffDataset::FlushCacheInternal( bool bFlushDirectory )
 {
-    if (bIsFinalized || ppoActiveDSRef == NULL)
+    if( bIsFinalized || ppoActiveDSRef == NULL )
         return;
 
     GDALPamDataset::FlushCache();
@@ -7767,24 +9057,24 @@ void GTiffDataset::FlushDirectory()
     {
         if( bMetadataChanged )
         {
-            if (!SetDirectory())
+            if( !SetDirectory() )
                 return;
             bNeedsRewrite =
-                WriteMetadata( this, hTIFF, TRUE, osProfile, osFilename,
-                               papszCreationOptions );
-            bMetadataChanged = FALSE;
+                    WriteMetadata( this, hTIFF, true, osProfile, osFilename,
+                                   papszCreationOptions );
+            bMetadataChanged = false;
         }
 
         if( bGeoTIFFInfoChanged )
         {
-            if (!SetDirectory())
+            if( !SetDirectory() )
                 return;
             WriteGeoTIFFInfo();
         }
 
         if( bNoDataChanged )
         {
-            if (!SetDirectory())
+            if( !SetDirectory() )
                 return;
             if( bNoDataSet )
             {
@@ -7794,48 +9084,48 @@ void GTiffDataset::FlushDirectory()
             {
                 UnsetNoDataValue( hTIFF );
             }
-            bNeedsRewrite = TRUE;
-            bNoDataChanged = FALSE;
+            bNeedsRewrite = true;
+            bNoDataChanged = false;
         }
 
         if( bNeedsRewrite )
         {
 #if defined(TIFFLIB_VERSION)
 #if defined(HAVE_TIFFGETSIZEPROC)
-            if (!SetDirectory())
+            if( !SetDirectory() )
                 return;
 
-            TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
+            const TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
 
             nDirOffset = pfnSizeProc( TIFFClientdata( hTIFF ) );
             if( (nDirOffset % 2) == 1 )
-                nDirOffset++;
+                ++nDirOffset;
 
             TIFFRewriteDirectory( hTIFF );
 
             TIFFSetSubDirectory( hTIFF, nDirOffset );
-#elif  TIFFLIB_VERSION > 20010925 && TIFFLIB_VERSION != 20011807
-            if (!SetDirectory())
+#elif TIFFLIB_VERSION > 20010925 && TIFFLIB_VERSION != 20011807
+            if( !SetDirectory() )
                 return;
 
             TIFFRewriteDirectory( hTIFF );
 #endif
 #endif
-            bNeedsRewrite = FALSE;
+            bNeedsRewrite = false;
         }
     }
 
-    // there are some circumstances in which we can reach this point
+    // There are some circumstances in which we can reach this point
     // without having made this our directory (SetDirectory()) in which
     // case we should not risk a flush.
     if( GetAccess() == GA_Update && TIFFCurrentDirOffset(hTIFF) == nDirOffset )
     {
 #if defined(BIGTIFF_SUPPORT)
-        TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
+        const TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
 
         toff_t nNewDirOffset = pfnSizeProc( TIFFClientdata( hTIFF ) );
         if( (nNewDirOffset % 2) == 1 )
-            nNewDirOffset++;
+            ++nNewDirOffset;
 
         TIFFFlush( hTIFF );
 
@@ -7846,8 +9136,8 @@ void GTiffDataset::FlushDirectory()
                       "directory moved during flush in FlushDirectory()" );
         }
 #else
-        /* For libtiff 3.X, the above causes regressions and crashes in */
-        /* tiff_write.py and tiff_ovr.py */
+        // For libtiff 3.X, the above causes regressions and crashes in
+        // tiff_write.py and tiff_ovr.py.
         TIFFFlush( hTIFF );
 #endif
     }
@@ -7871,10 +9161,9 @@ CPLErr GTiffDataset::CleanOverviews()
 /*      Cleanup overviews objects, and get offsets to all overview      */
 /*      directories.                                                    */
 /* -------------------------------------------------------------------- */
-    std::vector<toff_t>  anOvDirOffsets;
-    int i;
+    std::vector<toff_t> anOvDirOffsets;
 
-    for( i = 0; i < nOverviewCount; i++ )
+    for( int i = 0; i < nOverviewCount; ++i )
     {
         anOvDirOffsets.push_back( papoOverviewDS[i]->nDirOffset );
         delete papoOverviewDS[i];
@@ -7891,13 +9180,13 @@ CPLErr GTiffDataset::CleanOverviews()
 
     while( true )
     {
-        for( i = 0; i < nOverviewCount; i++ )
+        for( int i = 0; i < nOverviewCount; ++i )
         {
             if( anOvDirOffsets[i] == TIFFCurrentDirOffset( hTIFF ) )
             {
                 CPLDebug( "GTiff", "%d -> %d",
-                          (int) anOvDirOffsets[i], iThisOffset );
-                anOvDirIndexes.push_back( (uint16) iThisOffset );
+                          static_cast<int>(anOvDirOffsets[i]), iThisOffset );
+                anOvDirIndexes.push_back( static_cast<uint16>(iThisOffset) );
             }
         }
 
@@ -7905,7 +9194,7 @@ CPLErr GTiffDataset::CleanOverviews()
             break;
 
         TIFFReadDirectory( hTIFF );
-        iThisOffset++;
+        ++iThisOffset;
     }
 
 /* -------------------------------------------------------------------- */
@@ -7924,50 +9213,90 @@ CPLErr GTiffDataset::CleanOverviews()
     nOverviewCount = 0;
     papoOverviewDS = NULL;
 
-    if (!SetDirectory())
+    if( !SetDirectory() )
         return CE_Failure;
 
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                   RegisterNewOverviewDataset()                       */
 /************************************************************************/
 
-CPLErr GTiffDataset::RegisterNewOverviewDataset(toff_t nOverviewOffset)
+CPLErr GTiffDataset::RegisterNewOverviewDataset(toff_t nOverviewOffset,
+                                                int l_nJpegQuality)
 {
     GTiffDataset* poODS = new GTiffDataset();
-    poODS->nJpegQuality = nJpegQuality;
+    poODS->nJpegQuality = l_nJpegQuality;
     poODS->nZLevel = nZLevel;
     poODS->nLZMAPreset = nLZMAPreset;
+    poODS->nJpegTablesMode = nJpegTablesMode;
 
-    if( nCompression == COMPRESSION_JPEG )
-    {
-        if ( CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
-        {
-            poODS->nJpegQuality =  atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
-        }
-        TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY,
-                        poODS->nJpegQuality );
-    }
-
-    if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nOverviewOffset, FALSE,
+    if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nOverviewOffset, false,
                             GA_Update ) != CE_None )
     {
         delete poODS;
         return CE_Failure;
     }
+
+    ++nOverviewCount;
+    papoOverviewDS = static_cast<GTiffDataset **>(
+        CPLRealloc( papoOverviewDS,
+                    nOverviewCount * (sizeof(void*))) );
+    papoOverviewDS[nOverviewCount-1] = poODS;
+    poODS->poBaseDS = this;
+    return CE_None;
+}
+
+/************************************************************************/
+/*                     CreateTIFFColorTable()                           */
+/************************************************************************/
+
+static void CreateTIFFColorTable(GDALColorTable* poColorTable,
+                                 int nBits,
+                                 std::vector<unsigned short>& anTRed,
+                                 std::vector<unsigned short>& anTGreen,
+                                 std::vector<unsigned short>& anTBlue,
+                                 unsigned short*& panRed,
+                                 unsigned short*& panGreen,
+                                 unsigned short*& panBlue)
+{
+    int nColors;
+
+    if( nBits == 8 )
+        nColors = 256;
+    else if( nBits < 8 )
+        nColors = 1 << nBits;
     else
+        nColors = 65536;
+
+    anTRed.resize(nColors,0);
+    anTGreen.resize(nColors,0);
+    anTBlue.resize(nColors,0);
+
+    for( int iColor = 0; iColor < nColors; ++iColor )
     {
-        nOverviewCount++;
-        papoOverviewDS = (GTiffDataset **)
-            CPLRealloc(papoOverviewDS,
-                        nOverviewCount * (sizeof(void*)));
-        papoOverviewDS[nOverviewCount-1] = poODS;
-        poODS->poBaseDS = this;
-        return CE_None;
+        if( iColor < poColorTable->GetColorEntryCount() )
+        {
+            GDALColorEntry sRGB;
+
+            poColorTable->GetColorEntryAsRGB( iColor, &sRGB );
+
+            anTRed[iColor] = static_cast<unsigned short>(256 * sRGB.c1);
+            anTGreen[iColor] = static_cast<unsigned short>(256 * sRGB.c2);
+            anTBlue[iColor] = static_cast<unsigned short>(256 * sRGB.c3);
+        }
+        else
+        {
+            anTRed[iColor] = 0;
+            anTGreen[iColor] = 0;
+            anTBlue[iColor] = 0;
+        }
     }
+
+    panRed = &(anTRed[0]);
+    panGreen = &(anTGreen[0]);
+    panBlue = &(anTBlue[0]);
 }
 
 /************************************************************************/
@@ -7984,7 +9313,7 @@ CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
 /* -------------------------------------------------------------------- */
 /*      Move to the directory for this dataset.                         */
 /* -------------------------------------------------------------------- */
-    if (!SetDirectory())
+    if( !SetDirectory() )
         return CE_Failure;
     FlushDirectory();
 
@@ -7993,45 +9322,18 @@ CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
 /* -------------------------------------------------------------------- */
 /*      Do we have a palette?  If so, create a TIFF compatible version. */
 /* -------------------------------------------------------------------- */
-    std::vector<unsigned short> anTRed, anTGreen, anTBlue;
-    unsigned short      *panRed=NULL, *panGreen=NULL, *panBlue=NULL;
+    std::vector<unsigned short> anTRed;
+    std::vector<unsigned short> anTGreen;
+    std::vector<unsigned short> anTBlue;
+    unsigned short *panRed = NULL;
+    unsigned short *panGreen = NULL;
+    unsigned short *panBlue = NULL;
 
     if( nPhotometric == PHOTOMETRIC_PALETTE && poColorTable != NULL )
     {
-        int nColors;
-
-        if( nOvBitsPerSample == 8 )
-            nColors = 256;
-        else if( nOvBitsPerSample < 8 )
-            nColors = 1 << nOvBitsPerSample;
-        else
-            nColors = 65536;
-
-        anTRed.resize(nColors,0);
-        anTGreen.resize(nColors,0);
-        anTBlue.resize(nColors,0);
-
-        for( int iColor = 0; iColor < nColors; iColor++ )
-        {
-            if( iColor < poColorTable->GetColorEntryCount() )
-            {
-                GDALColorEntry  sRGB;
-
-                poColorTable->GetColorEntryAsRGB( iColor, &sRGB );
-
-                anTRed[iColor] = (unsigned short) (256 * sRGB.c1);
-                anTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
-                anTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
-            }
-            else
-            {
-                anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
-            }
-        }
-
-        panRed = &(anTRed[0]);
-        panGreen = &(anTGreen[0]);
-        panBlue = &(anTBlue[0]);
+        CreateTIFFColorTable(poColorTable, nOvBitsPerSample,
+                             anTRed, anTGreen, anTBlue,
+                             panRed, panGreen, panBlue);
     }
 
 /* -------------------------------------------------------------------- */
@@ -8047,10 +9349,14 @@ CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
     uint16 *panExtraSampleValues = NULL;
     uint16 nExtraSamples = 0;
 
-    if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &nExtraSamples, &panExtraSampleValues) )
+    if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &nExtraSamples,
+                      &panExtraSampleValues) )
     {
-        uint16* panExtraSampleValuesNew = (uint16*) CPLMalloc(nExtraSamples * sizeof(uint16));
-        memcpy(panExtraSampleValuesNew, panExtraSampleValues, nExtraSamples * sizeof(uint16));
+        uint16* panExtraSampleValuesNew =
+            static_cast<uint16*>(
+                CPLMalloc(nExtraSamples * sizeof(uint16)) );
+        memcpy( panExtraSampleValuesNew, panExtraSampleValues,
+                nExtraSamples * sizeof(uint16));
         panExtraSampleValues = panExtraSampleValuesNew;
     }
     else
@@ -8063,37 +9369,62 @@ CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
 /*      Fetch predictor tag                                             */
 /* -------------------------------------------------------------------- */
     uint16 nPredictor = PREDICTOR_NONE;
-    if ( nCompression == COMPRESSION_LZW ||
-         nCompression == COMPRESSION_ADOBE_DEFLATE )
+    if( nCompression == COMPRESSION_LZW ||
+        nCompression == COMPRESSION_ADOBE_DEFLATE )
         TIFFGetField( hTIFF, TIFFTAG_PREDICTOR, &nPredictor );
-    int nOvrBlockXSize, nOvrBlockYSize;
+    int nOvrBlockXSize = 0;
+    int nOvrBlockYSize = 0;
     GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
 
     int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
-    int i;
     CPLErr eErr = CE_None;
 
-    for(i=0;i<nSrcOverviews && eErr == CE_None;i++)
+    for( int i = 0; i < nSrcOverviews && eErr == CE_None; ++i )
     {
         GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(1)->GetOverview(i);
 
-        int         nOXSize = poOvrBand->GetXSize(), nOYSize = poOvrBand->GetYSize();
+        int nOXSize = poOvrBand->GetXSize();
+        int nOYSize = poOvrBand->GetYSize();
+
+        int nOvrJpegQuality = nJpegQuality;
+        if( nCompression == COMPRESSION_JPEG &&
+            CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
+        {
+            nOvrJpegQuality =
+                atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
+        }
+
+        CPLString osNoData; // don't move this in inner scope
+        const char* pszNoData = NULL;
+        if( bNoDataSet )
+        {
+            osNoData = GTiffFormatGDALNoDataTagValue(dfNoDataValue);
+            pszNoData = osNoData.c_str();
+        }
 
         toff_t nOverviewOffset =
                 GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE,
                                     nOXSize, nOYSize,
                                     nOvBitsPerSample, nPlanarConfig,
-                                    nSamplesPerPixel, nOvrBlockXSize, nOvrBlockYSize, TRUE,
+                                    nSamplesPerPixel,
+                                    nOvrBlockXSize,
+                                    nOvrBlockYSize,
+                                    TRUE,
                                     nCompression, nPhotometric, nSampleFormat,
                                     nPredictor,
                                     panRed, panGreen, panBlue,
                                     nExtraSamples, panExtraSampleValues,
-                                    osMetadata );
+                                    osMetadata,
+                                    nOvrJpegQuality >= 0 ?
+                                        CPLSPrintf("%d", nOvrJpegQuality) : NULL,
+                                    CPLSPrintf("%d", nJpegTablesMode),
+                                    pszNoData
+                                   );
 
         if( nOverviewOffset == 0 )
             eErr = CE_Failure;
         else
-            eErr = RegisterNewOverviewDataset(nOverviewOffset);
+            eErr = RegisterNewOverviewDataset(nOverviewOffset, nOvrJpegQuality);
     }
 
     CPLFree(panExtraSampleValues);
@@ -8102,13 +9433,12 @@ CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
 /* -------------------------------------------------------------------- */
 /*      Create overviews for the mask.                                  */
 /* -------------------------------------------------------------------- */
-    if (eErr == CE_None)
+    if( eErr == CE_None )
         eErr = CreateInternalMaskOverviews(nOvrBlockXSize, nOvrBlockYSize);
 
     return eErr;
 }
 
-
 /************************************************************************/
 /*                       CreateInternalMaskOverviews()                  */
 /************************************************************************/
@@ -8116,8 +9446,6 @@ CPLErr GTiffDataset::CreateOverviewsFromSrcOverviews(GDALDataset* poSrcDS)
 CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
                                                  int nOvrBlockYSize)
 {
-    GTiffDataset *poODS;
-
     ScanDirectories();
 
 /* -------------------------------------------------------------------- */
@@ -8125,10 +9453,11 @@ CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
 /* -------------------------------------------------------------------- */
     CPLErr eErr = CE_None;
 
-    const char* pszInternalMask = CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", NULL);
-    if (poMaskDS != NULL &&
+    const char* pszInternalMask =
+        CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", NULL);
+    if( poMaskDS != NULL &&
         poMaskDS->GetRasterCount() == 1 &&
-        (pszInternalMask == NULL || CPLTestBool(pszInternalMask)))
+        (pszInternalMask == NULL || CPLTestBool(pszInternalMask)) )
     {
         int nMaskOvrCompression;
         if( strstr(GDALGetMetadataItem(GDALGetDriverByName( "GTiff" ),
@@ -8138,21 +9467,22 @@ CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
         else
             nMaskOvrCompression = COMPRESSION_PACKBITS;
 
-        int i;
-        for( i = 0; i < nOverviewCount; i++ )
+        for( int i = 0; i < nOverviewCount; ++i )
         {
-            if (papoOverviewDS[i]->poMaskDS == NULL)
+            if( papoOverviewDS[i]->poMaskDS == NULL )
             {
-                toff_t  nOverviewOffset;
-
-                nOverviewOffset =
-                    GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE | FILETYPE_MASK,
-                                        papoOverviewDS[i]->nRasterXSize, papoOverviewDS[i]->nRasterYSize,
-                                        1, PLANARCONFIG_CONTIG,
-                                        1, nOvrBlockXSize, nOvrBlockYSize, TRUE,
-                                        nMaskOvrCompression, PHOTOMETRIC_MASK, SAMPLEFORMAT_UINT, PREDICTOR_NONE,
-                                        NULL, NULL, NULL, 0, NULL,
-                                        "" );
+                const toff_t nOverviewOffset =
+                    GTIFFWriteDirectory(
+                        hTIFF, FILETYPE_REDUCEDIMAGE | FILETYPE_MASK,
+                        papoOverviewDS[i]->nRasterXSize,
+                        papoOverviewDS[i]->nRasterYSize,
+                        1, PLANARCONFIG_CONTIG,
+                        1, nOvrBlockXSize, nOvrBlockYSize, TRUE,
+                        nMaskOvrCompression, PHOTOMETRIC_MASK,
+                        SAMPLEFORMAT_UINT, PREDICTOR_NONE,
+                        NULL, NULL, NULL, 0, NULL,
+                        "",
+                        NULL, NULL, NULL );
 
                 if( nOverviewOffset == 0 )
                 {
@@ -8160,9 +9490,9 @@ CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
                     continue;
                 }
 
-                poODS = new GTiffDataset();
+                GTiffDataset *poODS = new GTiffDataset();
                 if( poODS->OpenOffset( hTIFF, ppoActiveDSRef,
-                                       nOverviewOffset, FALSE,
+                                       nOverviewOffset, false,
                                        GA_Update ) != CE_None )
                 {
                     delete poODS;
@@ -8170,14 +9500,19 @@ CPLErr GTiffDataset::CreateInternalMaskOverviews(int nOvrBlockXSize,
                 }
                 else
                 {
-                    poODS->bPromoteTo8Bits = CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
+                    poODS->bPromoteTo8Bits =
+                        CPLTestBool(
+                            CPLGetConfigOption(
+                                "GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES" ) );
                     poODS->poBaseDS = this;
                     papoOverviewDS[i]->poMaskDS = poODS;
-                    poMaskDS->nOverviewCount++;
-                    poMaskDS->papoOverviewDS = (GTiffDataset **)
-                    CPLRealloc(poMaskDS->papoOverviewDS,
-                               poMaskDS->nOverviewCount * (sizeof(void*)));
-                    poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] = poODS;
+                    ++poMaskDS->nOverviewCount;
+                    poMaskDS->papoOverviewDS = static_cast<GTiffDataset **>(
+                        CPLRealloc(
+                            poMaskDS->papoOverviewDS,
+                            poMaskDS->nOverviewCount * (sizeof(void*))) );
+                    poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] =
+                        poODS;
                 }
             }
         }
@@ -8197,26 +9532,23 @@ CPLErr GTiffDataset::IBuildOverviews(
     GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    CPLErr       eErr = CE_None;
-    int          i;
-    GTiffDataset *poODS;
-    int          bUseGenericHandling = FALSE;
-
     ScanDirectories();
 
-    /* Make implicit JPEG overviews invisible, but do not destroy */
-    /* them in case they are already used (not sure that the client */
-    /* has the right to do that. behaviour undefined in GDAL API I think) */
+    // Make implicit JPEG overviews invisible, but do not destroy
+    // them in case they are already used (not sure that the client
+    // has the right to do that.  Behaviour maybe undefined in GDAL API.
     nJPEGOverviewCount = 0;
 
 /* -------------------------------------------------------------------- */
 /*      If RRD or external OVR overviews requested, then invoke         */
 /*      generic handling.                                               */
 /* -------------------------------------------------------------------- */
+    bool bUseGenericHandling = false;
+
     if( CPLTestBool(CPLGetConfigOption( "USE_RRD", "NO" ))
         || CPLTestBool(CPLGetConfigOption( "TIFF_USE_OVR", "NO" )) )
     {
-        bUseGenericHandling = TRUE;
+        bUseGenericHandling = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -8229,15 +9561,17 @@ CPLErr GTiffDataset::IBuildOverviews(
                   "File open for read-only accessing, "
                   "creating overviews externally." );
 
-        bUseGenericHandling = TRUE;
+        bUseGenericHandling = true;
     }
 
     if( bUseGenericHandling )
     {
-        if (nOverviewCount != 0)
+        if( nOverviewCount != 0 )
         {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "Cannot add external overviews when there are already internal overviews");
+            CPLError(
+                CE_Failure, CPLE_NotSupported,
+                "Cannot add external overviews when there are already "
+                "internal overviews" );
             return CE_Failure;
         }
 
@@ -8253,9 +9587,9 @@ CPLErr GTiffDataset::IBuildOverviews(
     if( nBandsIn != GetRasterCount() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Generation of overviews in TIFF currently only"
-                  " supported when operating on all bands.\n"
-                  "Operation failed.\n" );
+                  "Generation of overviews in TIFF currently only "
+                  "supported when operating on all bands.  "
+                  "Operation failed." );
         return CE_Failure;
     }
 
@@ -8269,20 +9603,24 @@ CPLErr GTiffDataset::IBuildOverviews(
             return GDALDataset::IBuildOverviews(
                 pszResampling, nOverviews, panOverviewList,
                 nBandsIn, panBandList, pfnProgress, pProgressData );
-        else
-            return CleanOverviews();
+
+        return CleanOverviews();
     }
 
 /* -------------------------------------------------------------------- */
 /*      libtiff 3.X has issues when generating interleaved overviews.   */
 /*      so generate them one after another one.                         */
 /* -------------------------------------------------------------------- */
+
+    CPLErr eErr = CE_None;
+
 #ifndef BIGTIFF_SUPPORT
     if( nOverviews > 1 )
     {
-        double* padfOvrRasterFactor = (double*) CPLMalloc(sizeof(double) * nOverviews);
+        double* padfOvrRasterFactor =
+            static_cast<double*>( CPLMalloc(sizeof(double) * nOverviews) );
         double dfTotal = 0;
-        for( i = 0; i < nOverviews; i++ )
+        for( int i = 0; i < nOverviews; ++i )
         {
             if( panOverviewList[i] <= 0 )
             {
@@ -8291,23 +9629,25 @@ CPLErr GTiffDataset::IBuildOverviews(
                 eErr = CE_Failure;
                 break;
             }
-            padfOvrRasterFactor[i] = 1.0 / (panOverviewList[i] * panOverviewList[i]);
+            padfOvrRasterFactor[i] =
+                1.0 / (panOverviewList[i] * panOverviewList[i]);
             dfTotal += padfOvrRasterFactor[i];
         }
 
         double dfAcc = 0.0;
-        for( i = 0; i < nOverviews && eErr == CE_None; i++ )
+        for( int i = 0; i < nOverviews && eErr == CE_None; ++i )
         {
-            void *pScaledProgressData;
-            pScaledProgressData =
-                GDALCreateScaledProgress( dfAcc / dfTotal,
-                                          (dfAcc + padfOvrRasterFactor[i]) / dfTotal,
-                                         pfnProgress, pProgressData );
+            void *pScaledProgressData =
+                GDALCreateScaledProgress(
+                    dfAcc / dfTotal,
+                    (dfAcc + padfOvrRasterFactor[i]) / dfTotal,
+                    pfnProgress, pProgressData );
             dfAcc += padfOvrRasterFactor[i];
 
             eErr = IBuildOverviews(
-                    pszResampling, 1, &panOverviewList[i],
-                    nBandsIn, panBandList, GDALScaledProgress, pScaledProgressData );
+                pszResampling, 1, &panOverviewList[i],
+                nBandsIn, panBandList, GDALScaledProgress,
+                pScaledProgressData );
 
             GDALDestroyScaledProgress(pScaledProgressData);
         }
@@ -8330,7 +9670,7 @@ CPLErr GTiffDataset::IBuildOverviews(
 /* -------------------------------------------------------------------- */
 /*      Move to the directory for this dataset.                         */
 /* -------------------------------------------------------------------- */
-    if (!SetDirectory())
+    if( !SetDirectory() )
         return CE_Failure;
     FlushDirectory();
 
@@ -8346,45 +9686,18 @@ CPLErr GTiffDataset::IBuildOverviews(
 /* -------------------------------------------------------------------- */
 /*      Do we have a palette?  If so, create a TIFF compatible version. */
 /* -------------------------------------------------------------------- */
-    std::vector<unsigned short> anTRed, anTGreen, anTBlue;
-    unsigned short      *panRed=NULL, *panGreen=NULL, *panBlue=NULL;
+    std::vector<unsigned short> anTRed;
+    std::vector<unsigned short> anTGreen;
+    std::vector<unsigned short> anTBlue;
+    unsigned short *panRed = NULL;
+    unsigned short *panGreen = NULL;
+    unsigned short *panBlue = NULL;
 
     if( nPhotometric == PHOTOMETRIC_PALETTE && poColorTable != NULL )
     {
-        int nColors;
-
-        if( nOvBitsPerSample == 8 )
-            nColors = 256;
-        else if( nOvBitsPerSample < 8 )
-            nColors = 1 << nOvBitsPerSample;
-        else
-            nColors = 65536;
-
-        anTRed.resize(nColors,0);
-        anTGreen.resize(nColors,0);
-        anTBlue.resize(nColors,0);
-
-        for( int iColor = 0; iColor < nColors; iColor++ )
-        {
-            if( iColor < poColorTable->GetColorEntryCount() )
-            {
-                GDALColorEntry  sRGB;
-
-                poColorTable->GetColorEntryAsRGB( iColor, &sRGB );
-
-                anTRed[iColor] = (unsigned short) (256 * sRGB.c1);
-                anTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
-                anTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
-            }
-            else
-            {
-                anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
-            }
-        }
-
-        panRed = &(anTRed[0]);
-        panGreen = &(anTGreen[0]);
-        panBlue = &(anTBlue[0]);
+        CreateTIFFColorTable(poColorTable, nOvBitsPerSample,
+                             anTRed, anTGreen, anTBlue,
+                             panRed, panGreen, panBlue);
     }
 
 /* -------------------------------------------------------------------- */
@@ -8400,10 +9713,13 @@ CPLErr GTiffDataset::IBuildOverviews(
     uint16 *panExtraSampleValues = NULL;
     uint16 nExtraSamples = 0;
 
-    if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &nExtraSamples, &panExtraSampleValues) )
+    if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &nExtraSamples,
+                      &panExtraSampleValues) )
     {
-        uint16* panExtraSampleValuesNew = (uint16*) CPLMalloc(nExtraSamples * sizeof(uint16));
-        memcpy(panExtraSampleValuesNew, panExtraSampleValues, nExtraSamples * sizeof(uint16));
+        uint16* panExtraSampleValuesNew =
+            static_cast<uint16*>( CPLMalloc(nExtraSamples * sizeof(uint16)) );
+        memcpy( panExtraSampleValuesNew, panExtraSampleValues,
+                nExtraSamples * sizeof(uint16) );
         panExtraSampleValues = panExtraSampleValuesNew;
     }
     else
@@ -8416,8 +9732,8 @@ CPLErr GTiffDataset::IBuildOverviews(
 /*      Fetch predictor tag                                             */
 /* -------------------------------------------------------------------- */
     uint16 nPredictor = PREDICTOR_NONE;
-    if ( nCompression == COMPRESSION_LZW ||
-         nCompression == COMPRESSION_ADOBE_DEFLATE )
+    if( nCompression == COMPRESSION_LZW ||
+        nCompression == COMPRESSION_ADOBE_DEFLATE )
         TIFFGetField( hTIFF, TIFFTAG_PREDICTOR, &nPredictor );
 
 /* -------------------------------------------------------------------- */
@@ -8425,22 +9741,20 @@ CPLErr GTiffDataset::IBuildOverviews(
 /*      which are new.  We assume that band 1 of the file is            */
 /*      representative.                                                 */
 /* -------------------------------------------------------------------- */
-    int nOvrBlockXSize, nOvrBlockYSize;
+    int nOvrBlockXSize = 0;
+    int nOvrBlockYSize = 0;
     GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
-    for( i = 0; i < nOverviews && eErr == CE_None; i++ )
+    for( int i = 0; i < nOverviews && eErr == CE_None; ++i )
     {
-        int   j;
-
-        for( j = 0; j < nOverviewCount && eErr == CE_None; j++ )
+        for( int j = 0; j < nOverviewCount && eErr == CE_None; ++j )
         {
-            int    nOvFactor;
-
-            poODS = papoOverviewDS[j];
+            GTiffDataset *poODS = papoOverviewDS[j];
 
-            nOvFactor = GDALComputeOvFactor(poODS->GetRasterXSize(),
-                                             GetRasterXSize(),
-                                             poODS->GetRasterYSize(),
-                                             GetRasterYSize());
+            const int nOvFactor =
+                GDALComputeOvFactor(poODS->GetRasterXSize(),
+                                    GetRasterXSize(),
+                                    poODS->GetRasterYSize(),
+                                    GetRasterYSize());
 
             if( nOvFactor == panOverviewList[i]
                 || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
@@ -8451,33 +9765,55 @@ CPLErr GTiffDataset::IBuildOverviews(
 
         if( panOverviewList[i] > 0 )
         {
-            toff_t nOverviewOffset;
-            int         nOXSize, nOYSize;
-
-            nOXSize = (GetRasterXSize() + panOverviewList[i] - 1)
+            const int nOXSize =
+                (GetRasterXSize() + panOverviewList[i] - 1)
                 / panOverviewList[i];
-            nOYSize = (GetRasterYSize() + panOverviewList[i] - 1)
+            const int nOYSize =
+                (GetRasterYSize() + panOverviewList[i] - 1)
                 / panOverviewList[i];
 
-            nOverviewOffset =
-                GTIFFWriteDirectory(hTIFF, FILETYPE_REDUCEDIMAGE,
-                                    nOXSize, nOYSize,
-                                    nOvBitsPerSample, nPlanarConfig,
-                                    nSamplesPerPixel, nOvrBlockXSize, nOvrBlockYSize, TRUE,
-                                    nCompression, nPhotometric, nSampleFormat,
-                                    nPredictor,
-                                    panRed, panGreen, panBlue,
-                                    nExtraSamples, panExtraSampleValues,
-                                    osMetadata );
+            int nOvrJpegQuality = nJpegQuality;
+            if( nCompression == COMPRESSION_JPEG &&
+                CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
+            {
+                nOvrJpegQuality =
+                    atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
+            }
+
+            CPLString osNoData; // don't move this in inner scope
+            const char* pszNoData = NULL;
+            if( bNoDataSet )
+            {
+                osNoData = GTiffFormatGDALNoDataTagValue(dfNoDataValue);
+                pszNoData = osNoData.c_str();
+            }
 
+            const toff_t nOverviewOffset =
+                GTIFFWriteDirectory(
+                    hTIFF, FILETYPE_REDUCEDIMAGE,
+                    nOXSize, nOYSize,
+                    nOvBitsPerSample, nPlanarConfig,
+                    nSamplesPerPixel, nOvrBlockXSize, nOvrBlockYSize, TRUE,
+                    nCompression, nPhotometric, nSampleFormat,
+                    nPredictor,
+                    panRed, panGreen, panBlue,
+                    nExtraSamples, panExtraSampleValues,
+                    osMetadata,
+                    nOvrJpegQuality >= 0 ?
+                                CPLSPrintf("%d", nOvrJpegQuality) : NULL,
+                    CPLSPrintf("%d", nJpegTablesMode),
+                    pszNoData );
 
             if( nOverviewOffset == 0 )
                 eErr = CE_Failure;
             else
-                eErr = RegisterNewOverviewDataset(nOverviewOffset);
+                eErr = RegisterNewOverviewDataset(nOverviewOffset,
+                                                  nOvrJpegQuality);
         }
         else
+        {
             panOverviewList[i] *= -1;
+        }
     }
 
     CPLFree(panExtraSampleValues);
@@ -8486,77 +9822,79 @@ CPLErr GTiffDataset::IBuildOverviews(
 /* -------------------------------------------------------------------- */
 /*      Create overviews for the mask.                                  */
 /* -------------------------------------------------------------------- */
-    if (eErr == CE_None)
-        eErr = CreateInternalMaskOverviews(nOvrBlockXSize, nOvrBlockYSize);
-    else
+    if( eErr != CE_None )
         return eErr;
 
+    eErr = CreateInternalMaskOverviews(nOvrBlockXSize, nOvrBlockYSize);
+
 /* -------------------------------------------------------------------- */
 /*      Refresh overviews for the mask                                  */
 /* -------------------------------------------------------------------- */
-    if (poMaskDS != NULL &&
-        poMaskDS->GetRasterCount() == 1)
+    if( poMaskDS != NULL &&
+        poMaskDS->GetRasterCount() == 1 )
     {
-        GDALRasterBand **papoOverviewBands;
         int nMaskOverviews = 0;
 
-        papoOverviewBands = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviewCount);
-        for( i = 0; i < nOverviewCount; i++ )
+        GDALRasterBand **papoOverviewBands = static_cast<GDALRasterBand **>(
+            CPLCalloc(sizeof(void*),nOverviewCount) );
+        for( int i = 0; i < nOverviewCount; ++i )
         {
-            if (papoOverviewDS[i]->poMaskDS != NULL)
+            if( papoOverviewDS[i]->poMaskDS != NULL )
             {
-                papoOverviewBands[nMaskOverviews ++] =
+                papoOverviewBands[nMaskOverviews++] =
                         papoOverviewDS[i]->poMaskDS->GetRasterBand(1);
             }
         }
-        eErr = GDALRegenerateOverviews( (GDALRasterBandH)
-                                        poMaskDS->GetRasterBand(1),
-                                        nMaskOverviews,
-                                        (GDALRasterBandH *) papoOverviewBands,
-                                        pszResampling, GDALDummyProgress, NULL);
+        eErr = GDALRegenerateOverviews(
+            poMaskDS->GetRasterBand(1),
+            nMaskOverviews,
+            reinterpret_cast<GDALRasterBandH *>( papoOverviewBands ),
+            pszResampling, GDALDummyProgress, NULL );
         CPLFree(papoOverviewBands);
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Refresh old overviews that were listed.                         */
 /* -------------------------------------------------------------------- */
-    if (nPlanarConfig == PLANARCONFIG_CONTIG &&
-        GDALDataTypeIsComplex(GetRasterBand( panBandList[0] )->GetRasterDataType()) == FALSE &&
+    if( nPlanarConfig == PLANARCONFIG_CONTIG &&
+        GDALDataTypeIsComplex(GetRasterBand( panBandList[0] )->
+                              GetRasterDataType()) == FALSE &&
         GetRasterBand( panBandList[0] )->GetColorTable() == NULL &&
-        (STARTS_WITH_CI(pszResampling, "NEAR") || EQUAL(pszResampling, "AVERAGE") ||
-         EQUAL(pszResampling, "GAUSS") || EQUAL(pszResampling, "CUBIC") ||
-         EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") ||
-         EQUAL(pszResampling, "BILINEAR")))
-    {
-        /* In the case of pixel interleaved compressed overviews, we want to generate */
-        /* the overviews for all the bands block by block, and not band after band, */
-        /* in order to write the block once and not loose space in the TIFF file */
-        /* We also use that logic for uncompressed overviews, since GDALRegenerateOverviewsMultiBand() */
-        /* will be able to trigger cascading overview regeneration even in the presence */
-        /* of an alpha band. */
-
-        GDALRasterBand ***papapoOverviewBands;
-        GDALRasterBand  **papoBandList;
+        (STARTS_WITH_CI(pszResampling, "NEAR") ||
+         EQUAL(pszResampling, "AVERAGE") ||
+         EQUAL(pszResampling, "GAUSS") ||
+         EQUAL(pszResampling, "CUBIC") ||
+         EQUAL(pszResampling, "CUBICSPLINE") ||
+         EQUAL(pszResampling, "LANCZOS") ||
+         EQUAL(pszResampling, "BILINEAR")) )
+    {
+        // In the case of pixel interleaved compressed overviews, we want to
+        // generate the overviews for all the bands block by block, and not
+        // band after band, in order to write the block once and not loose
+        // space in the TIFF file.  We also use that logic for uncompressed
+        // overviews, since GDALRegenerateOverviewsMultiBand() will be able to
+        // trigger cascading overview regeneration even in the presence
+        // of an alpha band.
 
         int nNewOverviews = 0;
-        int iBand;
 
-        papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBandsIn);
-        papoBandList = (GDALRasterBand **) CPLCalloc(sizeof(void*),nBandsIn);
-        for( iBand = 0; iBand < nBandsIn; iBand++ )
+        GDALRasterBand ***papapoOverviewBands =
+            static_cast<GDALRasterBand ***>(CPLCalloc(sizeof(void*),nBandsIn));
+        GDALRasterBand **papoBandList =
+            static_cast<GDALRasterBand **>(CPLCalloc(sizeof(void*),nBandsIn));
+        for( int iBand = 0; iBand < nBandsIn; ++iBand )
         {
             GDALRasterBand* poBand = GetRasterBand( panBandList[iBand] );
 
             papoBandList[iBand] = poBand;
-            papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*), poBand->GetOverviewCount());
+            papapoOverviewBands[iBand] =
+                static_cast<GDALRasterBand **>( CPLCalloc(
+                    sizeof(void*), poBand->GetOverviewCount()) );
 
             int iCurOverview = 0;
-            for( i = 0; i < nOverviews; i++ )
+            for( int i = 0; i < nOverviews; ++i )
             {
-                int   j;
-
-                for( j = 0; j < poBand->GetOverviewCount(); j++ )
+                for( int j = 0; j < poBand->GetOverviewCount(); ++j )
                 {
                     int    nOvFactor;
                     GDALRasterBand * poOverview = poBand->GetOverview( j );
@@ -8566,38 +9904,42 @@ CPLErr GTiffDataset::IBuildOverviews(
                                                      poOverview->GetYSize(),
                                                      poBand->GetYSize());
 
-                    int bHasNoData;
+                    int bHasNoData = FALSE;
                     double noDataValue = poBand->GetNoDataValue(&bHasNoData);
 
-                    if (bHasNoData)
+                    if( bHasNoData )
                         poOverview->SetNoDataValue(noDataValue);
 
                     if( nOvFactor == panOverviewList[i]
-                        || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
-                                                            poBand->GetXSize(),
-                                                            poBand->GetYSize() ) )
+                        || nOvFactor == GDALOvLevelAdjust2(
+                                            panOverviewList[i],
+                                            poBand->GetXSize(),
+                                            poBand->GetYSize() ) )
                     {
                         papapoOverviewBands[iBand][iCurOverview] = poOverview;
-                        iCurOverview++ ;
+                        ++iCurOverview ;
                         break;
                     }
                 }
             }
 
-            if (nNewOverviews == 0)
+            if( nNewOverviews == 0 )
+            {
                 nNewOverviews = iCurOverview;
-            else if (nNewOverviews != iCurOverview)
+            }
+            else if( nNewOverviews != iCurOverview )
             {
-                CPLAssert(0);
+                CPLAssert(false);
                 return CE_Failure;
             }
         }
 
-        GDALRegenerateOverviewsMultiBand(nBandsIn, papoBandList,
-                                         nNewOverviews, papapoOverviewBands,
-                                         pszResampling, pfnProgress, pProgressData );
+        GDALRegenerateOverviewsMultiBand( nBandsIn, papoBandList,
+                                          nNewOverviews, papapoOverviewBands,
+                                          pszResampling, pfnProgress,
+                                          pProgressData );
 
-        for( iBand = 0; iBand < nBandsIn; iBand++ )
+        for( int iBand = 0; iBand < nBandsIn; ++iBand )
         {
             CPLFree(papapoOverviewBands[iBand]);
         }
@@ -8606,43 +9948,37 @@ CPLErr GTiffDataset::IBuildOverviews(
     }
     else
     {
-        GDALRasterBand **papoOverviewBands;
+        GDALRasterBand **papoOverviewBands = static_cast<GDALRasterBand **>(
+            CPLCalloc(sizeof(void*), nOverviews) );
 
-        papoOverviewBands = (GDALRasterBand **)
-            CPLCalloc(sizeof(void*),nOverviews);
-
-        for( int iBand = 0; iBand < nBandsIn && eErr == CE_None; iBand++ )
+        for( int iBand = 0; iBand < nBandsIn && eErr == CE_None; ++iBand )
         {
-            GDALRasterBand *poBand;
-            int            nNewOverviews;
-
-            poBand = GetRasterBand( panBandList[iBand] );
+            GDALRasterBand *poBand = GetRasterBand( panBandList[iBand] );
 
-            nNewOverviews = 0;
-            for( i = 0; i < nOverviews && poBand != NULL; i++ )
+            int nNewOverviews = 0;
+            for( int i = 0; i < nOverviews && poBand != NULL; ++i )
             {
-                int   j;
-
-                for( j = 0; j < poBand->GetOverviewCount(); j++ )
+                for( int j = 0; j < poBand->GetOverviewCount(); ++j )
                 {
-                    int    nOvFactor;
                     GDALRasterBand * poOverview = poBand->GetOverview( j );
 
-                    int bHasNoData;
+                    int bHasNoData = FALSE;
                     double noDataValue = poBand->GetNoDataValue(&bHasNoData);
 
-                    if (bHasNoData)
+                    if( bHasNoData )
                         poOverview->SetNoDataValue(noDataValue);
 
-                    nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
-                                                     poBand->GetXSize(),
-                                                     poOverview->GetYSize(),
-                                                     poBand->GetYSize());
+                    const int nOvFactor =
+                        GDALComputeOvFactor(poOverview->GetXSize(),
+                                            poBand->GetXSize(),
+                                            poOverview->GetYSize(),
+                                            poBand->GetYSize());
 
                     if( nOvFactor == panOverviewList[i]
-                        || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
-                                                            poBand->GetXSize(),
-                                                            poBand->GetYSize() ) )
+                        || nOvFactor == GDALOvLevelAdjust2(
+                                            panOverviewList[i],
+                                            poBand->GetXSize(),
+                                            poBand->GetYSize() ) )
                     {
                         papoOverviewBands[nNewOverviews++] = poOverview;
                         break;
@@ -8650,19 +9986,19 @@ CPLErr GTiffDataset::IBuildOverviews(
                 }
             }
 
-            void         *pScaledProgressData;
+            void *pScaledProgressData =
+                GDALCreateScaledProgress(
+                    iBand / static_cast<double>( nBandsIn ),
+                    (iBand + 1) / static_cast<double>( nBandsIn ),
+                    pfnProgress, pProgressData );
 
-            pScaledProgressData =
-                GDALCreateScaledProgress( iBand / (double) nBandsIn,
-                                        (iBand+1) / (double) nBandsIn,
-                                        pfnProgress, pProgressData );
-
-            eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
-                                            nNewOverviews,
-                                            (GDALRasterBandH *) papoOverviewBands,
-                                            pszResampling,
-                                            GDALScaledProgress,
-                                            pScaledProgressData);
+            eErr = GDALRegenerateOverviews(
+                poBand,
+                nNewOverviews,
+                reinterpret_cast<GDALRasterBandH *>( papoOverviewBands ),
+                pszResampling,
+                GDALScaledProgress,
+                pScaledProgressData );
 
             GDALDestroyScaledProgress( pScaledProgressData );
         }
@@ -8673,7 +10009,6 @@ CPLErr GTiffDataset::IBuildOverviews(
         CPLFree( papoOverviewBands );
     }
 
-
     pfnProgress( 1.0, NULL, pProgressData );
 
     return eErr;
@@ -8683,18 +10018,18 @@ CPLErr GTiffDataset::IBuildOverviews(
 /*                      GTiffWriteDummyGeokeyDirectory()                */
 /************************************************************************/
 
-static void GTiffWriteDummyGeokeyDirectory(TIFF* hTIFF)
+static void GTiffWriteDummyGeokeyDirectory( TIFF* hTIFF )
 {
     // If we have existing geokeys, try to wipe them
     // by writing a dummy geokey directory. (#2546)
     uint16 *panVI = NULL;
-    uint16 nKeyCount;
+    uint16 nKeyCount = 0;
 
     if( TIFFGetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY,
                         &nKeyCount, &panVI ) )
     {
         GUInt16 anGKVersionInfo[4] = { 1, 1, 0, 0 };
-        double  adfDummyDoubleParams[1] = { 0.0 };
+        double adfDummyDoubleParams[1] = { 0.0 };
         TIFFSetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY,
                         4, anGKVersionInfo );
         TIFFSetField( hTIFF, TIFFTAG_GEODOUBLEPARAMS,
@@ -8725,8 +10060,8 @@ void GTiffDataset::WriteGeoTIFFInfo()
 
     if( bForceUnsetGTOrGCPs )
     {
-        bNeedsRewrite = TRUE;
-        bForceUnsetGTOrGCPs = FALSE;
+        bNeedsRewrite = true;
+        bForceUnsetGTOrGCPs = false;
 
 #ifdef HAVE_UNSETFIELD
         TIFFUnsetField( hTIFF, TIFFTAG_GEOPIXELSCALE );
@@ -8737,8 +10072,8 @@ void GTiffDataset::WriteGeoTIFFInfo()
 
     if( bForceUnsetProjection )
     {
-        bNeedsRewrite = TRUE;
-        bForceUnsetProjection = FALSE;
+        bNeedsRewrite = true;
+        bForceUnsetProjection = false;
 
 #ifdef HAVE_UNSETFIELD
         TIFFUnsetField( hTIFF, TIFFTAG_GEOKEYDIRECTORY );
@@ -8754,9 +10089,9 @@ void GTiffDataset::WriteGeoTIFFInfo()
 /* -------------------------------------------------------------------- */
     if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
         || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
-        || adfGeoTransform[4] != 0.0 || ABS(adfGeoTransform[5]) != 1.0 )
+        || adfGeoTransform[4] != 0.0 || std::abs(adfGeoTransform[5]) != 1.0 )
     {
-        bNeedsRewrite = TRUE;
+        bNeedsRewrite = true;
 
 /* -------------------------------------------------------------------- */
 /*      Clear old tags to ensure we don't end up with conflicting       */
@@ -8775,26 +10110,22 @@ void GTiffDataset::WriteGeoTIFFInfo()
         if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
                 && adfGeoTransform[5] < 0.0 )
         {
-            double adfPixelScale[3], adfTiePoints[6];
-
-            adfPixelScale[0] = adfGeoTransform[1];
-            adfPixelScale[1] = fabs(adfGeoTransform[5]);
-            adfPixelScale[2] = 0.0;
-
             if( !EQUAL(osProfile,"BASELINE") )
+            {
+                const double adfPixelScale[3] = {
+                    adfGeoTransform[1], fabs(adfGeoTransform[5]), 0.0 };
                 TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
+            }
 
-            adfTiePoints[0] = 0.0;
-            adfTiePoints[1] = 0.0;
-            adfTiePoints[2] = 0.0;
-            adfTiePoints[3] = adfGeoTransform[0];
-            adfTiePoints[4] = adfGeoTransform[3];
-            adfTiePoints[5] = 0.0;
+            double adfTiePoints[6] = {
+                0.0, 0.0, 0.0, adfGeoTransform[0], adfGeoTransform[3], 0.0 };
 
             if( bPixelIsPoint && !bPointGeoIgnore )
             {
-                adfTiePoints[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
-                adfTiePoints[4] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
+                adfTiePoints[3] +=
+                    adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
+                adfTiePoints[4] +=
+                    adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
             }
 
             if( !EQUAL(osProfile,"BASELINE") )
@@ -8802,9 +10133,7 @@ void GTiffDataset::WriteGeoTIFFInfo()
         }
         else
         {
-            double adfMatrix[16];
-
-            memset(adfMatrix,0,sizeof(double) * 16);
+            double adfMatrix[16] = {};
 
             adfMatrix[0] = adfGeoTransform[1];
             adfMatrix[1] = adfGeoTransform[2];
@@ -8816,8 +10145,10 @@ void GTiffDataset::WriteGeoTIFFInfo()
 
             if( bPixelIsPoint && !bPointGeoIgnore )
             {
-                adfMatrix[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
-                adfMatrix[7] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
+                adfMatrix[3] +=
+                    adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
+                adfMatrix[7] +=
+                    adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
             }
 
             if( !EQUAL(osProfile,"BASELINE") )
@@ -8825,22 +10156,19 @@ void GTiffDataset::WriteGeoTIFFInfo()
         }
 
         // Do we need a world file?
-        if( CSLFetchBoolean( papszCreationOptions, "TFW", FALSE ) )
+        if( CPLFetchBool( papszCreationOptions, "TFW", false ) )
             GDALWriteWorldFile( osFilename, "tfw", adfGeoTransform );
-        else if( CSLFetchBoolean( papszCreationOptions, "WORLDFILE", FALSE ) )
+        else if( CPLFetchBool( papszCreationOptions, "WORLDFILE", false ) )
             GDALWriteWorldFile( osFilename, "wld", adfGeoTransform );
     }
     else if( GetGCPCount() > 0 )
     {
-        double *padfTiePoints;
-        int iGCP;
-
-        bNeedsRewrite = TRUE;
+        bNeedsRewrite = true;
 
-        padfTiePoints = (double *)
-            CPLMalloc( 6 * sizeof(double) * GetGCPCount() );
+        double *padfTiePoints = static_cast<double *>(
+            CPLMalloc( 6 * sizeof(double) * GetGCPCount() ) );
 
-        for( iGCP = 0; iGCP < GetGCPCount(); iGCP++ )
+        for( int iGCP = 0; iGCP < GetGCPCount(); ++iGCP )
         {
 
             padfTiePoints[iGCP*6+0] = pasGCPList[iGCP].dfGCPPixel;
@@ -8866,21 +10194,20 @@ void GTiffDataset::WriteGeoTIFFInfo()
 /* -------------------------------------------------------------------- */
 /*      Write out projection definition.                                */
 /* -------------------------------------------------------------------- */
-    const bool bHasProjection = (pszProjection != NULL && strlen(pszProjection) > 0);
+    const bool bHasProjection =
+        pszProjection != NULL && strlen(pszProjection) > 0;
     if( (bHasProjection || bPixelIsPoint)
         && !EQUAL(osProfile,"BASELINE") )
     {
-        GTIF *psGTIF;
-
-        bNeedsRewrite = TRUE;
+        bNeedsRewrite = true;
 
         // If we have existing geokeys, try to wipe them
         // by writing a dummy geokey directory. (#2546)
         GTiffWriteDummyGeokeyDirectory(hTIFF);
 
-        psGTIF = GTIFNew( hTIFF );
+        GTIF *psGTIF = GTIFNew( hTIFF );
 
-        // set according to coordinate system.
+        // Set according to coordinate system.
         if( bHasProjection )
         {
             GTIFSetFromOGISDefnEx( psGTIF, pszProjection, eGeoTIFFKeysFlavor );
@@ -8907,18 +10234,16 @@ static void AppendMetadataItem( CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
                                 const char *pszDomain )
 
 {
-    char szBandId[32];
-    CPLXMLNode *psItem;
-
 /* -------------------------------------------------------------------- */
 /*      Create the Item element, and subcomponents.                     */
 /* -------------------------------------------------------------------- */
-    psItem = CPLCreateXMLNode( NULL, CXT_Element, "Item" );
+    CPLXMLNode *psItem = CPLCreateXMLNode( NULL, CXT_Element, "Item" );
     CPLCreateXMLNode( CPLCreateXMLNode( psItem, CXT_Attribute, "name"),
                       CXT_Text, pszKey );
 
     if( nBand > 0 )
     {
+        char szBandId[32] = {};
         snprintf( szBandId, sizeof(szBandId), "%d", nBand - 1 );
         CPLCreateXMLNode( CPLCreateXMLNode( psItem,CXT_Attribute,"sample"),
                           CXT_Text, szBandId );
@@ -8955,48 +10280,45 @@ static void AppendMetadataItem( CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
 }
 
 /************************************************************************/
-/*                         WriteMDMetadata()                          */
+/*                         WriteMDMetadata()                            */
 /************************************************************************/
 
 static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
                              CPLXMLNode **ppsRoot, CPLXMLNode **ppsTail,
-                             int nBand, const char *pszProfile )
+                             int nBand, const char * /* pszProfile */ )
 
 {
-    int iDomain;
-    char **papszDomainList;
-
-    (void) pszProfile;
 
 /* ==================================================================== */
 /*      Process each domain.                                            */
 /* ==================================================================== */
-    papszDomainList = poMDMD->GetDomainList();
-    for( iDomain = 0; papszDomainList && papszDomainList[iDomain]; iDomain++ )
+    char **papszDomainList = poMDMD->GetDomainList();
+    for( int iDomain = 0;
+         papszDomainList && papszDomainList[iDomain];
+         ++iDomain )
     {
         char **papszMD = poMDMD->GetMetadata( papszDomainList[iDomain] );
-        int iItem;
         bool bIsXML = false;
 
         if( EQUAL(papszDomainList[iDomain], "IMAGE_STRUCTURE") )
-            continue; // ignored
+            continue;  // Ignored.
         if( EQUAL(papszDomainList[iDomain], "COLOR_PROFILE") )
-            continue; // ignored
+            continue;  // Ignored.
         if( EQUAL(papszDomainList[iDomain], MD_DOMAIN_RPC) )
-            continue; // handled elsewhere
+            continue;  // Handled elsewhere.
         if( EQUAL(papszDomainList[iDomain], "xml:ESRI")
             && CPLTestBool(CPLGetConfigOption( "ESRI_XML_PAM", "NO" )) )
-            continue; // handled elsewhere
+            continue;  // Handled elsewhere.
 
         if( STARTS_WITH_CI(papszDomainList[iDomain], "xml:") )
-            bIsXML = TRUE;
+            bIsXML = true;
 
 /* -------------------------------------------------------------------- */
 /*      Process each item in this domain.                               */
 /* -------------------------------------------------------------------- */
-        for( iItem = 0; papszMD && papszMD[iItem]; iItem++ )
+        for( int iItem = 0; papszMD && papszMD[iItem]; ++iItem )
         {
-            const char *pszItemValue;
+            const char *pszItemValue = NULL;
             char *pszItemName = NULL;
 
             if( bIsXML )
@@ -9009,7 +10331,8 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
                 pszItemValue = CPLParseNameValue( papszMD[iItem], &pszItemName);
                 if( pszItemName == NULL )
                 {
-                    CPLDebug("GTiff", "Invalid metadata item : %s", papszMD[iItem]);
+                    CPLDebug( "GTiff",
+                              "Invalid metadata item : %s", papszMD[iItem] );
                     continue;
                 }
             }
@@ -9020,44 +10343,59 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
             if( strlen(papszDomainList[iDomain]) == 0
                 && nBand == 0 && STARTS_WITH_CI(pszItemName, "TIFFTAG_") )
             {
-                if( EQUAL(pszItemName,"TIFFTAG_RESOLUTIONUNIT") ) {
-                    /* ResolutionUnit can't be 0, which is the default if atoi() fails.
-                       Set to 1=Unknown */
+                if( EQUAL(pszItemName, "TIFFTAG_RESOLUTIONUNIT") )
+                {
+                    // ResolutionUnit can't be 0, which is the default if
+                    // atoi() fails.  Set to 1=Unknown.
                     int v = atoi(pszItemValue);
-                    if (!v) v = RESUNIT_NONE;
+                    if( !v ) v = RESUNIT_NONE;
                     TIFFSetField( hTIFF, TIFFTAG_RESOLUTIONUNIT, v);
                 }
                 else
                 {
-                    int bFoundTag = FALSE;
-                    size_t iTag;
-                    for(iTag=0;iTag<sizeof(asTIFFTags)/sizeof(asTIFFTags[0]);iTag++)
+                    bool bFoundTag = false;
+                    size_t iTag = 0;  // Used after for.
+                    for( ;
+                         iTag < sizeof(asTIFFTags) / sizeof(asTIFFTags[0]);
+                         ++iTag )
                     {
                         if( EQUAL(pszItemName, asTIFFTags[iTag].pszTagName) )
                         {
-                            bFoundTag = TRUE;
+                            bFoundTag = true;
                             break;
                         }
                     }
 
-                    if( bFoundTag && asTIFFTags[iTag].eType == GTIFFTAGTYPE_STRING )
-                        TIFFSetField( hTIFF, asTIFFTags[iTag].nTagVal, pszItemValue );
-                    else if( bFoundTag && asTIFFTags[iTag].eType == GTIFFTAGTYPE_FLOAT )
-                        TIFFSetField( hTIFF, asTIFFTags[iTag].nTagVal, CPLAtof(pszItemValue) );
-                    else if( bFoundTag && asTIFFTags[iTag].eType == GTIFFTAGTYPE_SHORT )
-                        TIFFSetField( hTIFF, asTIFFTags[iTag].nTagVal, atoi(pszItemValue) );
+                    if( bFoundTag &&
+                        asTIFFTags[iTag].eType == GTIFFTAGTYPE_STRING )
+                        TIFFSetField( hTIFF, asTIFFTags[iTag].nTagVal,
+                                      pszItemValue );
+                    else if( bFoundTag &&
+                             asTIFFTags[iTag].eType == GTIFFTAGTYPE_FLOAT )
+                        TIFFSetField( hTIFF, asTIFFTags[iTag].nTagVal,
+                                      CPLAtof(pszItemValue) );
+                    else if( bFoundTag &&
+                             asTIFFTags[iTag].eType == GTIFFTAGTYPE_SHORT )
+                        TIFFSetField( hTIFF, asTIFFTags[iTag].nTagVal,
+                                      atoi(pszItemValue) );
                     else
-                        CPLError(CE_Warning, CPLE_NotSupported,
-                                "%s metadata item is unhandled and will not be written",
-                                pszItemName);
+                        CPLError(
+                            CE_Warning, CPLE_NotSupported,
+                            "%s metadata item is unhandled and "
+                            "will not be written",
+                            pszItemName);
                 }
             }
             else if( nBand == 0 && EQUAL(pszItemName,GDALMD_AREA_OR_POINT) )
-                /* do nothing, handled elsewhere */;
+            {
+                /* Do nothing, handled elsewhere. */;
+            }
             else
+            {
                 AppendMetadataItem( ppsRoot, ppsTail,
                                     pszItemName, pszItemValue,
                                     nBand, NULL, papszDomainList[iDomain] );
+            }
 
             CPLFree( pszItemName );
         }
@@ -9068,17 +10406,23 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
 /* -------------------------------------------------------------------- */
         if( strlen(papszDomainList[iDomain]) == 0 && nBand == 0 )
         {
-            size_t iTag;
-            for(iTag=0;iTag<sizeof(asTIFFTags)/sizeof(asTIFFTags[0]);iTag++)
+            for( size_t iTag = 0;
+                 iTag < sizeof(asTIFFTags) / sizeof(asTIFFTags[0]);
+                 ++iTag )
             {
                 char* pszText = NULL;
                 int16 nVal = 0;
                 float fVal = 0.0f;
-                const char* pszVal = CSLFetchNameValue(papszMD, asTIFFTags[iTag].pszTagName);
+                const char* pszVal =
+                    CSLFetchNameValue(papszMD, asTIFFTags[iTag].pszTagName);
                 if( pszVal == NULL &&
-                    ((asTIFFTags[iTag].eType == GTIFFTAGTYPE_STRING && TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &pszText )) ||
-                     (asTIFFTags[iTag].eType == GTIFFTAGTYPE_SHORT && TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &nVal )) ||
-                     (asTIFFTags[iTag].eType == GTIFFTAGTYPE_FLOAT && TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &fVal ))) )
+                    ((asTIFFTags[iTag].eType == GTIFFTAGTYPE_STRING &&
+                      TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal,
+                                    &pszText )) ||
+                     (asTIFFTags[iTag].eType == GTIFFTAGTYPE_SHORT &&
+                      TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &nVal )) ||
+                     (asTIFFTags[iTag].eType == GTIFFTAGTYPE_FLOAT &&
+                      TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &fVal ))) )
                 {
 #ifdef HAVE_UNSETFIELD
                     TIFFUnsetField( hTIFF, asTIFFTags[iTag].nTagVal );
@@ -9091,7 +10435,6 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
                 }
             }
         }
-
     }
 }
 
@@ -9099,77 +10442,128 @@ static void WriteMDMetadata( GDALMultiDomainMetadata *poMDMD, TIFF *hTIFF,
 /*                           WriteRPC()                                 */
 /************************************************************************/
 
-void GTiffDataset::WriteRPC( GDALDataset *poSrcDS, TIFF *hTIFF,
+void GTiffDataset::WriteRPC( GDALDataset *poSrcDS, TIFF *l_hTIFF,
                              int bSrcIsGeoTIFF,
                              const char *pszProfile,
                              const char *pszTIFFFilename,
-                             char **papszCreationOptions,
-                             int bWriteOnlyInPAMIfNeeded )
+                             char **l_papszCreationOptions,
+                             bool bWriteOnlyInPAMIfNeeded )
 {
-
 /* -------------------------------------------------------------------- */
 /*      Handle RPC data written to an RPB file.                         */
 /* -------------------------------------------------------------------- */
     char **papszRPCMD = poSrcDS->GetMetadata(MD_DOMAIN_RPC);
     if( papszRPCMD != NULL )
     {
-        int bRPCSerializedOtherWay = FALSE;
+        bool bRPCSerializedOtherWay = false;
 
         if( EQUAL(pszProfile,"GDALGeoTIFF") )
         {
             if( !bWriteOnlyInPAMIfNeeded )
-                GTiffDatasetWriteRPCTag( hTIFF, papszRPCMD );
-            bRPCSerializedOtherWay = TRUE;
+                GTiffDatasetWriteRPCTag( l_hTIFF, papszRPCMD );
+            bRPCSerializedOtherWay = true;
         }
 
-        /* Write RPB file if explicitly asked, or if a non GDAL specific */
-        /* profile is selected and RPCTXT is not asked */
-        int bRPBExplicitlyAsked = CSLFetchBoolean( papszCreationOptions, "RPB", FALSE );
-        int bRPBExplicitlyDenied = !CSLFetchBoolean( papszCreationOptions, "RPB", TRUE );
+        // Write RPB file if explicitly asked, or if a non GDAL specific
+        // profile is selected and RPCTXT is not asked.
+        bool bRPBExplicitlyAsked =
+            CPLFetchBool( l_papszCreationOptions, "RPB", false );
+        bool bRPBExplicitlyDenied =
+            !CPLFetchBool( l_papszCreationOptions, "RPB", true );
         if( (!EQUAL(pszProfile,"GDALGeoTIFF") &&
-             !CSLFetchBoolean( papszCreationOptions, "RPCTXT", FALSE ) &&
+             !CPLFetchBool( l_papszCreationOptions, "RPCTXT", false ) &&
              !bRPBExplicitlyDenied )
             || bRPBExplicitlyAsked )
         {
             if( !bWriteOnlyInPAMIfNeeded )
                 GDALWriteRPBFile( pszTIFFFilename, papszRPCMD );
-            bRPCSerializedOtherWay = TRUE;
+            bRPCSerializedOtherWay = true;
         }
 
-        if( CSLFetchBoolean( papszCreationOptions, "RPCTXT", FALSE ) )
+        if( CPLFetchBool( l_papszCreationOptions, "RPCTXT", false ) )
         {
             if( !bWriteOnlyInPAMIfNeeded )
                 GDALWriteRPCTXTFile( pszTIFFFilename, papszRPCMD );
-            bRPCSerializedOtherWay = TRUE;
+            bRPCSerializedOtherWay = true;
         }
 
-        if( !bRPCSerializedOtherWay && bWriteOnlyInPAMIfNeeded && bSrcIsGeoTIFF )
-            ((GTiffDataset*)poSrcDS)->GDALPamDataset::SetMetadata(papszRPCMD, MD_DOMAIN_RPC);
+        if( !bRPCSerializedOtherWay && bWriteOnlyInPAMIfNeeded &&
+            bSrcIsGeoTIFF )
+            reinterpret_cast<GTiffDataset*>(poSrcDS)->
+                GDALPamDataset::SetMetadata( papszRPCMD, MD_DOMAIN_RPC );
+    }
+}
+
+/************************************************************************/
+/*                  IsStandardColorInterpretation()                     */
+/************************************************************************/
+
+static bool IsStandardColorInterpretation(GDALDataset* poSrcDS,
+                                          uint16 nPhotometric)
+{
+    bool bStardardColorInterp = true;
+    if( nPhotometric == PHOTOMETRIC_MINISBLACK )
+    {
+        for( int i = 0; i < poSrcDS->GetRasterCount(); ++i )
+        {
+            const GDALColorInterp eInterp =
+                poSrcDS->GetRasterBand(i + 1)->GetColorInterpretation();
+            if( !(eInterp == GCI_GrayIndex || eInterp == GCI_Undefined ||
+                    (i > 0 && eInterp == GCI_AlphaBand)) )
+            {
+                bStardardColorInterp = false;
+                break;
+            }
+        }
+    }
+    else if( nPhotometric == PHOTOMETRIC_RGB )
+    {
+        for( int i = 0; i < poSrcDS->GetRasterCount(); ++i )
+        {
+            const GDALColorInterp eInterp =
+                poSrcDS->GetRasterBand(i+1)->GetColorInterpretation();
+            if( !((i == 0 && eInterp == GCI_RedBand) ||
+                    (i == 1 && eInterp == GCI_GreenBand) ||
+                    (i == 2 && eInterp == GCI_BlueBand) ||
+                    (i >= 3 && (eInterp == GCI_Undefined ||
+                                eInterp == GCI_AlphaBand))) )
+            {
+                bStardardColorInterp = false;
+                break;
+            }
+        }
     }
+    else
+    {
+        bStardardColorInterp = false;
+    }
+    return bStardardColorInterp;
 }
 
 /************************************************************************/
 /*                           WriteMetadata()                            */
 /************************************************************************/
 
-int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
-                                  int bSrcIsGeoTIFF,
+bool GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *l_hTIFF,
+                                  bool bSrcIsGeoTIFF,
                                   const char *pszProfile,
                                   const char *pszTIFFFilename,
-                                  char **papszCreationOptions,
-                                  int bExcludeRPBandIMGFileWriting)
+                                  char **l_papszCreationOptions,
+                                  bool bExcludeRPBandIMGFileWriting)
 
 {
 /* -------------------------------------------------------------------- */
 /*      Convert all the remaining metadata into a simple XML            */
 /*      format.                                                         */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psRoot = NULL, *psTail = NULL;
+    CPLXMLNode *psRoot = NULL;
+    CPLXMLNode *psTail = NULL;
 
     if( bSrcIsGeoTIFF )
     {
-        WriteMDMetadata( &(((GTiffDataset *)poSrcDS)->oGTiffMDMD),
-                         hTIFF, &psRoot, &psTail, 0, pszProfile );
+        WriteMDMetadata(
+            &reinterpret_cast<GTiffDataset *>(poSrcDS)->oGTiffMDMD,
+            l_hTIFF, &psRoot, &psTail, 0, pszProfile );
     }
     else
     {
@@ -9177,18 +10571,19 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
 
         if( CSLCount(papszMD) > 0 )
         {
-            GDALMultiDomainMetadata oMDMD;
-            oMDMD.SetMetadata( papszMD );
+            GDALMultiDomainMetadata l_oMDMD;
+            l_oMDMD.SetMetadata( papszMD );
 
-            WriteMDMetadata( &oMDMD, hTIFF, &psRoot, &psTail, 0, pszProfile );
+            WriteMDMetadata( &l_oMDMD, l_hTIFF, &psRoot, &psTail,
+                             0, pszProfile );
         }
     }
 
     if( !bExcludeRPBandIMGFileWriting )
     {
-        WriteRPC(poSrcDS, hTIFF, bSrcIsGeoTIFF,
+        WriteRPC(poSrcDS, l_hTIFF, bSrcIsGeoTIFF,
                  pszProfile, pszTIFFFilename,
-                 papszCreationOptions);
+                 l_papszCreationOptions);
 
 /* -------------------------------------------------------------------- */
 /*      Handle metadata data written to an IMD file.                    */
@@ -9199,19 +10594,27 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
             GDALWriteIMDFile( pszTIFFFilename, papszIMDMD );
         }
     }
+
+    uint16 nPhotometric = 0;
+    if( !TIFFGetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, &(nPhotometric) ) )
+        nPhotometric = PHOTOMETRIC_MINISBLACK;
+
+    const bool bStardardColorInterp =
+        IsStandardColorInterpretation(poSrcDS, nPhotometric);
+
 /* -------------------------------------------------------------------- */
 /*      We also need to address band specific metadata, and special     */
 /*      "role" metadata.                                                */
 /* -------------------------------------------------------------------- */
-    int nBand;
-    for( nBand = 1; nBand <= poSrcDS->GetRasterCount(); nBand++ )
+    for( int nBand = 1; nBand <= poSrcDS->GetRasterCount(); ++nBand )
     {
         GDALRasterBand *poBand = poSrcDS->GetRasterBand( nBand );
 
         if( bSrcIsGeoTIFF )
         {
-            WriteMDMetadata( &(((GTiffRasterBand *)poBand)->oGTiffMDMD),
-                             hTIFF, &psRoot, &psTail, nBand, pszProfile );
+            WriteMDMetadata(
+                &reinterpret_cast<GTiffRasterBand *>(poBand)->oGTiffMDMD,
+                l_hTIFF, &psRoot, &psTail, nBand, pszProfile );
         }
         else
         {
@@ -9219,20 +10622,20 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
 
             if( CSLCount(papszMD) > 0 )
             {
-                GDALMultiDomainMetadata oMDMD;
-                oMDMD.SetMetadata( papszMD );
+                GDALMultiDomainMetadata l_oMDMD;
+                l_oMDMD.SetMetadata( papszMD );
 
-                WriteMDMetadata( &oMDMD, hTIFF, &psRoot, &psTail, nBand,
+                WriteMDMetadata( &l_oMDMD, l_hTIFF, &psRoot, &psTail, nBand,
                                  pszProfile );
             }
         }
 
-        double dfOffset = poBand->GetOffset();
-        double dfScale = poBand->GetScale();
+        const double dfOffset = poBand->GetOffset();
+        const double dfScale = poBand->GetScale();
 
         if( dfOffset != 0.0 || dfScale != 1.0 )
         {
-            char szValue[128];
+            char szValue[128] = {};
 
             CPLsnprintf( szValue, sizeof(szValue), "%.18g", dfOffset );
             AppendMetadataItem( &psRoot, &psTail, "OFFSET", szValue, nBand,
@@ -9243,17 +10646,26 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
         }
 
         const char* pszUnitType = poBand->GetUnitType();
-        if (pszUnitType != NULL && pszUnitType[0] != '\0')
-            AppendMetadataItem( &psRoot, &psTail, "UNITTYPE", pszUnitType, nBand,
+        if( pszUnitType != NULL && pszUnitType[0] != '\0' )
+            AppendMetadataItem( &psRoot, &psTail, "UNITTYPE",
+                                pszUnitType, nBand,
                                 "unittype", "" );
 
-
-        if (strlen(poBand->GetDescription()) > 0)
+        if( strlen(poBand->GetDescription()) > 0 )
         {
             AppendMetadataItem( &psRoot, &psTail, "DESCRIPTION",
                                 poBand->GetDescription(), nBand,
                                 "description", "" );
         }
+
+        if( !bStardardColorInterp )
+        {
+            AppendMetadataItem( &psRoot, &psTail, "COLORINTERP",
+                                GDALGetColorInterpretationName(
+                                    poBand->GetColorInterpretation()),
+                                nBand,
+                                "colorinterp", "" );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -9261,7 +10673,7 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
 /* -------------------------------------------------------------------- */
     if( psRoot != NULL )
     {
-        int bRet = TRUE;
+        bool bRet = true;
 
         if( EQUAL(pszProfile,"GDALGeoTIFF") )
         {
@@ -9270,59 +10682,64 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
             {
                 if( bSrcIsGeoTIFF )
                 {
-                    if( ((GTiffDataset *) poSrcDS)->GetPamFlags() & GPF_DISABLED )
+                    if( reinterpret_cast<GTiffDataset *>(
+                           poSrcDS)->GetPamFlags() & GPF_DISABLED )
                     {
-                        CPLError( CE_Warning, CPLE_AppDefined,
-                            "Metadata exceeding 32000 bytes cannot be written into GeoTIFF." );
+                        CPLError(
+                            CE_Warning, CPLE_AppDefined,
+                            "Metadata exceeding 32000 bytes cannot be written "
+                            "into GeoTIFF." );
                     }
                     else
                     {
-                        ((GTiffDataset *) poSrcDS)->PushMetadataToPam();
-                        CPLError( CE_Warning, CPLE_AppDefined,
-                            "Metadata exceeding 32000 bytes cannot be written into GeoTIFF. Transferred to PAM instead." );
+                        reinterpret_cast<GTiffDataset *>(poSrcDS)->
+                            PushMetadataToPam();
+                        CPLError(
+                            CE_Warning, CPLE_AppDefined,
+                            "Metadata exceeding 32000 bytes cannot be written "
+                            "into GeoTIFF. Transferred to PAM instead." );
                     }
                 }
                 else
                 {
-                    bRet = FALSE;
+                    bRet = false;
                 }
             }
             else
             {
-                TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, pszXML_MD );
+                TIFFSetField( l_hTIFF, TIFFTAG_GDAL_METADATA, pszXML_MD );
             }
             CPLFree( pszXML_MD );
         }
         else
         {
             if( bSrcIsGeoTIFF )
-                ((GTiffDataset *) poSrcDS)->PushMetadataToPam();
+                reinterpret_cast<GTiffDataset *>(poSrcDS)->PushMetadataToPam();
             else
-                bRet = FALSE;
+                bRet = false;
         }
 
         CPLDestroyXMLNode( psRoot );
 
         return bRet;
     }
-    else
+
+    // If we have no more metadata but it existed before,
+    // remove the GDAL_METADATA tag.
+    if( EQUAL(pszProfile,"GDALGeoTIFF") )
     {
-        /* If we have no more metadata but it existed before, remove the GDAL_METADATA tag */
-        if( EQUAL(pszProfile,"GDALGeoTIFF") )
+        char* pszText = NULL;
+        if( TIFFGetField( l_hTIFF, TIFFTAG_GDAL_METADATA, &pszText ) )
         {
-            char* pszText = NULL;
-            if( TIFFGetField( hTIFF, TIFFTAG_GDAL_METADATA, &pszText ) )
-            {
 #ifdef HAVE_UNSETFIELD
-                TIFFUnsetField( hTIFF, TIFFTAG_GDAL_METADATA );
+            TIFFUnsetField( l_hTIFF, TIFFTAG_GDAL_METADATA );
 #else
-                TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, "" );
+            TIFFSetField( l_hTIFF, TIFFTAG_GDAL_METADATA, "" );
 #endif
-            }
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -9339,30 +10756,31 @@ int  GTiffDataset::WriteMetadata( GDALDataset *poSrcDS, TIFF *hTIFF,
 void GTiffDataset::PushMetadataToPam()
 
 {
-    int nBand;
-    for( nBand = 0; nBand <= GetRasterCount(); nBand++ )
+    const bool bStardardColorInterp =
+        IsStandardColorInterpretation(this, nPhotometric);
+
+    for( int nBand = 0; nBand <= GetRasterCount(); ++nBand )
     {
-        GDALMultiDomainMetadata *poSrcMDMD;
+        GDALMultiDomainMetadata *poSrcMDMD = NULL;
         GTiffRasterBand *poBand = NULL;
 
         if( nBand == 0 )
+        {
             poSrcMDMD = &(this->oGTiffMDMD);
+        }
         else
         {
-            poBand = (GTiffRasterBand *) GetRasterBand(nBand);
+            poBand = reinterpret_cast<GTiffRasterBand *>(GetRasterBand(nBand));
             poSrcMDMD = &(poBand->oGTiffMDMD);
         }
 
 /* -------------------------------------------------------------------- */
 /*      Loop over the available domains.                                */
 /* -------------------------------------------------------------------- */
-        int iDomain, i;
-        char **papszDomainList;
-
-        papszDomainList = poSrcMDMD->GetDomainList();
-        for( iDomain = 0;
+        char **papszDomainList = poSrcMDMD->GetDomainList();
+        for( int iDomain = 0;
              papszDomainList && papszDomainList[iDomain];
-             iDomain++ )
+             ++iDomain )
         {
             char **papszMD = poSrcMDMD->GetMetadata( papszDomainList[iDomain] );
 
@@ -9375,16 +10793,20 @@ void GTiffDataset::PushMetadataToPam()
 
             papszMD = CSLDuplicate(papszMD);
 
-            for( i = CSLCount(papszMD)-1; i >= 0; i-- )
+            for( int i = CSLCount(papszMD)-1; i >= 0; --i )
             {
                 if( STARTS_WITH_CI(papszMD[i], "TIFFTAG_")
                     || EQUALN(papszMD[i],GDALMD_AREA_OR_POINT,
-                              strlen(GDALMD_AREA_OR_POINT)) )                    papszMD = CSLRemoveStrings( papszMD, i, 1, NULL );            }
+                              strlen(GDALMD_AREA_OR_POINT)) )
+                    papszMD = CSLRemoveStrings( papszMD, i, 1, NULL );
+            }
 
             if( nBand == 0 )
                 GDALPamDataset::SetMetadata( papszMD, papszDomainList[iDomain]);
             else
-                poBand->GDALPamRasterBand::SetMetadata( papszMD, papszDomainList[iDomain]);
+                poBand->
+                    GDALPamRasterBand::SetMetadata( papszMD,
+                                                    papszDomainList[iDomain]);
 
             CSLDestroy( papszMD );
         }
@@ -9397,7 +10819,13 @@ void GTiffDataset::PushMetadataToPam()
             poBand->GDALPamRasterBand::SetOffset( poBand->GetOffset() );
             poBand->GDALPamRasterBand::SetScale( poBand->GetScale() );
             poBand->GDALPamRasterBand::SetUnitType( poBand->GetUnitType() );
-            poBand->GDALPamRasterBand::SetDescription( poBand->GetDescription() );
+            poBand->
+                GDALPamRasterBand::SetDescription( poBand->GetDescription() );
+            if( !bStardardColorInterp )
+            {
+                poBand->GDALPamRasterBand::SetColorInterpretation(
+                                        poBand->GetColorInterpretation() );
+            }
         }
     }
     MarkPamDirty();
@@ -9414,12 +10842,12 @@ void GTiffDataset::PushMetadataToPam()
 void GTiffDatasetWriteRPCTag( TIFF *hTIFF, char **papszRPCMD )
 
 {
-    double adfRPCTag[92];
     GDALRPCInfo sRPC;
 
     if( !GDALExtractRPCInfo( papszRPCMD, &sRPC ) )
         return;
 
+    double adfRPCTag[92] = {};
     adfRPCTag[0] = -1.0;  // Error Bias
     adfRPCTag[1] = -1.0;  // Error Random
 
@@ -9453,17 +10881,14 @@ void GTiffDatasetWriteRPCTag( TIFF *hTIFF, char **papszRPCMD )
 char** GTiffDatasetReadRPCTag(TIFF* hTIFF)
 
 {
-    double *padfRPCTag;
-    CPLString osField;
-    CPLString osMultiField;
-    CPLStringList asMD;
-    int i;
+    double *padfRPCTag = NULL;
     uint16 nCount;
 
     if( !TIFFGetField( hTIFF, TIFFTAG_RPCCOEFFICIENT, &nCount, &padfRPCTag )
         || nCount != 92 )
         return NULL;
 
+    CPLStringList asMD;
     asMD.SetNameValue(RPC_LINE_OFF, CPLOPrintf("%.15g", padfRPCTag[2]));
     asMD.SetNameValue(RPC_SAMP_OFF, CPLOPrintf("%.15g", padfRPCTag[3]));
     asMD.SetNameValue(RPC_LAT_OFF, CPLOPrintf("%.15g", padfRPCTag[4]));
@@ -9475,7 +10900,10 @@ char** GTiffDatasetReadRPCTag(TIFF* hTIFF)
     asMD.SetNameValue(RPC_LONG_SCALE, CPLOPrintf("%.15g", padfRPCTag[10]));
     asMD.SetNameValue(RPC_HEIGHT_SCALE, CPLOPrintf("%.15g", padfRPCTag[11]));
 
-    for( i = 0; i < 20; i++ )
+    CPLString osField;
+    CPLString osMultiField;
+
+    for( int i = 0; i < 20; ++i )
     {
         osField.Printf( "%.15g", padfRPCTag[12+i] );
         if( i > 0 )
@@ -9486,7 +10914,7 @@ char** GTiffDatasetReadRPCTag(TIFF* hTIFF)
     }
     asMD.SetNameValue(RPC_LINE_NUM_COEFF, osMultiField );
 
-    for( i = 0; i < 20; i++ )
+    for( int i = 0; i < 20; ++i )
     {
         osField.Printf( "%.15g", padfRPCTag[32+i] );
         if( i > 0 )
@@ -9497,7 +10925,7 @@ char** GTiffDatasetReadRPCTag(TIFF* hTIFF)
     }
     asMD.SetNameValue( RPC_LINE_DEN_COEFF, osMultiField );
 
-    for( i = 0; i < 20; i++ )
+    for( int i = 0; i < 20; ++i )
     {
         osField.Printf( "%.15g", padfRPCTag[52+i] );
         if( i > 0 )
@@ -9508,7 +10936,7 @@ char** GTiffDatasetReadRPCTag(TIFF* hTIFF)
     }
     asMD.SetNameValue( RPC_SAMP_NUM_COEFF, osMultiField );
 
-    for( i = 0; i < 20; i++ )
+    for( int i = 0; i < 20; ++i )
     {
         osField.Printf( "%.15g", padfRPCTag[72+i] );
         if( i > 0 )
@@ -9523,31 +10951,41 @@ char** GTiffDatasetReadRPCTag(TIFF* hTIFF)
 }
 
 /************************************************************************/
+/*                  GTiffFormatGDALNoDataTagValue()                     */
+/************************************************************************/
+
+CPLString GTiffFormatGDALNoDataTagValue( double dfNoData )
+{
+    CPLString osVal;
+    if( CPLIsNan(dfNoData) )
+        osVal = "nan";
+    else
+        osVal.Printf("%.18g", dfNoData);
+    return osVal;
+}
+
+/************************************************************************/
 /*                         WriteNoDataValue()                           */
 /************************************************************************/
 
-void GTiffDataset::WriteNoDataValue( TIFF *hTIFF, double dfNoData )
+void GTiffDataset::WriteNoDataValue( TIFF *l_hTIFF, double dfNoData )
 
 {
-    char szVal[400];
-    if (CPLIsNan(dfNoData))
-        strcpy(szVal, "nan");
-    else
-        CPLsnprintf(szVal, sizeof(szVal), "%.18g", dfNoData);
-    TIFFSetField( hTIFF, TIFFTAG_GDAL_NODATA, szVal );
+    CPLString osVal( GTiffFormatGDALNoDataTagValue(dfNoData) );
+    TIFFSetField( l_hTIFF, TIFFTAG_GDAL_NODATA, osVal.c_str() );
 }
 
 /************************************************************************/
 /*                         UnsetNoDataValue()                           */
 /************************************************************************/
 
-void GTiffDataset::UnsetNoDataValue( TIFF *hTIFF )
+void GTiffDataset::UnsetNoDataValue( TIFF *l_hTIFF )
 
 {
 #ifdef HAVE_UNSETFIELD
-    TIFFUnsetField( hTIFF, TIFFTAG_GDAL_NODATA );
+    TIFFUnsetField( l_hTIFF, TIFFTAG_GDAL_NODATA );
 #else
-    TIFFSetField( hTIFF, TIFFTAG_GDAL_NODATA, "" );
+    TIFFSetField( l_hTIFF, TIFFTAG_GDAL_NODATA, "" );
 #endif
 }
 
@@ -9555,7 +10993,7 @@ void GTiffDataset::UnsetNoDataValue( TIFF *hTIFF )
 /*                            SetDirectory()                            */
 /************************************************************************/
 
-int GTiffDataset::SetDirectory( toff_t nNewOffset )
+bool GTiffDataset::SetDirectory( toff_t nNewOffset )
 
 {
     Crystalize();
@@ -9567,7 +11005,7 @@ int GTiffDataset::SetDirectory( toff_t nNewOffset )
     {
         CPLAssert( *ppoActiveDSRef == this || *ppoActiveDSRef == NULL );
         *ppoActiveDSRef = this;
-        return TRUE;
+        return true;
     }
 
     if( GetAccess() == GA_Update )
@@ -9577,13 +11015,13 @@ int GTiffDataset::SetDirectory( toff_t nNewOffset )
     }
 
     if( nNewOffset == 0)
-        return TRUE;
+        return true;
 
     (*ppoActiveDSRef) = this;
 
-    int nSetDirResult = TIFFSetSubDirectory( hTIFF, nNewOffset );
-    if (!nSetDirResult)
-        return nSetDirResult;
+    const int nSetDirResult = TIFFSetSubDirectory( hTIFF, nNewOffset );
+    if( !nSetDirResult )
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      YCbCr JPEG compressed images should be translated on the fly    */
@@ -9601,7 +11039,7 @@ int GTiffDataset::SetDirectory( toff_t nNewOffset )
         && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
                                               "YES") ) )
     {
-        int nColorMode;
+        int nColorMode = JPEGCOLORMODE_RAW;  // Initialize to 0;
 
         TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode );
         if( nColorMode != JPEGCOLORMODE_RGB )
@@ -9616,8 +11054,10 @@ int GTiffDataset::SetDirectory( toff_t nNewOffset )
         // Now, reset zip and jpeg quality.
         if(nJpegQuality > 0 && nCompression == COMPRESSION_JPEG)
         {
+#ifdef DEBUG_VERBOSE
             CPLDebug( "GTiff", "Propagate JPEG_QUALITY(%d) in SetDirectory()",
                       nJpegQuality );
+#endif
             TIFFSetField(hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality);
         }
         if(nJpegTablesMode >= 0 && nCompression == COMPRESSION_JPEG)
@@ -9628,17 +11068,17 @@ int GTiffDataset::SetDirectory( toff_t nNewOffset )
             TIFFSetField(hTIFF, TIFFTAG_LZMAPRESET, nLZMAPreset);
     }
 
-    return nSetDirResult;
+    return true;
 }
 
 /************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
 
-int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
+int GTiffDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    const char  *pszFilename = poOpenInfo->pszFilename;
+    const char *pszFilename = poOpenInfo->pszFilename;
     if( STARTS_WITH_CI(pszFilename, "GTIFF_RAW:") )
     {
         pszFilename += strlen("GTIFF_RAW:");
@@ -9661,7 +11101,8 @@ int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
         return FALSE;
 
     if( (poOpenInfo->pabyHeader[0] != 'I' || poOpenInfo->pabyHeader[1] != 'I')
-        && (poOpenInfo->pabyHeader[0] != 'M' || poOpenInfo->pabyHeader[1] != 'M'))
+        && (poOpenInfo->pabyHeader[0] != 'M'
+        || poOpenInfo->pabyHeader[1] != 'M'))
         return FALSE;
 
 #ifndef BIGTIFF_SUPPORT
@@ -9669,7 +11110,7 @@ int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
         (poOpenInfo->pabyHeader[2] == 0 && poOpenInfo->pabyHeader[3] == 0x2B) )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "This is a BigTIFF file.  BigTIFF is not supported by this\n"
+                  "This is a BigTIFF file.  BigTIFF is not supported by this "
                   "version of GDAL and libtiff." );
         return FALSE;
     }
@@ -9678,7 +11119,8 @@ int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( (poOpenInfo->pabyHeader[2] != 0x2A || poOpenInfo->pabyHeader[3] != 0)
         && (poOpenInfo->pabyHeader[3] != 0x2A || poOpenInfo->pabyHeader[2] != 0)
         && (poOpenInfo->pabyHeader[2] != 0x2B || poOpenInfo->pabyHeader[3] != 0)
-        && (poOpenInfo->pabyHeader[3] != 0x2B || poOpenInfo->pabyHeader[2] != 0))
+        && (poOpenInfo->pabyHeader[3] != 0x2B ||
+            poOpenInfo->pabyHeader[2] != 0))
         return FALSE;
 
     return TRUE;
@@ -9688,22 +11130,26 @@ int GTiffDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                            GTIFFErrorHandler()                       */
 /************************************************************************/
 
+namespace {
 class GTIFFErrorStruct CPL_FINAL
 {
-public:
+  public:
     CPLErr type;
     CPLErrorNum no;
     CPLString msg;
 
-        GTIFFErrorStruct() : type(CE_None), no(CPLE_None) {}
-        GTIFFErrorStruct(CPLErr eErrIn, CPLErrorNum noIn, const char* msgIn) :
-            type(eErrIn), no(noIn), msg(msgIn) {}
+    GTIFFErrorStruct() : type(CE_None), no(CPLE_None) {}
+    GTIFFErrorStruct(CPLErr eErrIn, CPLErrorNum noIn, const char* msgIn) :
+        type(eErrIn), no(noIn), msg(msgIn) {}
 };
+}
 
-static void CPL_STDCALL GTIFFErrorHandler(CPLErr eErr, CPLErrorNum no, const char* msg)
+static void CPL_STDCALL GTIFFErrorHandler( CPLErr eErr, CPLErrorNum no,
+                                           const char* msg )
 {
     std::vector<GTIFFErrorStruct>* paoErrors =
-        (std::vector<GTIFFErrorStruct>*) CPLGetErrorHandlerUserData();
+        static_cast<std::vector<GTIFFErrorStruct> *>(
+            CPLGetErrorHandlerUserData());
     paoErrors->push_back(GTIFFErrorStruct(eErr, no, msg));
 }
 
@@ -9711,66 +11157,82 @@ static void CPL_STDCALL GTIFFErrorHandler(CPLErr eErr, CPLErrorNum no, const cha
 /*                          GTIFFExtendMemoryFile()                     */
 /************************************************************************/
 
-static int GTIFFExtendMemoryFile(const CPLString& osTmpFilename,
-                                 VSILFILE* fpTemp,
-                                 VSILFILE* fpL,
-                                 int nNewLength,
-                                 GByte*& pabyBuffer,
-                                 vsi_l_offset& nDataLength)
+static bool GTIFFExtendMemoryFile( const CPLString& osTmpFilename,
+                                   VSILFILE* fpTemp,
+                                   VSILFILE* fpL,
+                                   int nNewLength,
+                                   GByte*& pabyBuffer,
+                                   vsi_l_offset& nDataLength )
 {
-    if( nNewLength <= (int)nDataLength )
-        return TRUE;
+    if( nNewLength <= static_cast<int>(nDataLength) )
+        return true;
     if( VSIFSeekL(fpTemp, nNewLength - 1, SEEK_SET) != 0 )
-        return FALSE;
+        return false;
     char ch = 0;
     if( VSIFWriteL(&ch, 1, 1, fpTemp) != 1 )
-        return FALSE;
-    int nOldDataLength = static_cast<int>(nDataLength);
-    pabyBuffer = (GByte*)VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE);
-    int nToRead = nNewLength - nOldDataLength;
-    int nRead = (int)VSIFReadL( pabyBuffer + nOldDataLength, 1, nToRead, fpL);
+        return false;
+    const int nOldDataLength = static_cast<int>(nDataLength);
+    pabyBuffer = static_cast<GByte*>(
+        VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE) );
+    const int nToRead = nNewLength - nOldDataLength;
+    const int nRead = static_cast<int>(
+        VSIFReadL( pabyBuffer + nOldDataLength, 1, nToRead, fpL) );
     if( nRead != nToRead )
     {
         CPLError(CE_Failure, CPLE_FileIO,
                  "Needed to read %d bytes. Only %d got", nToRead, nRead);
-        return FALSE;
+        return false;
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                         GTIFFMakeBufferedStream()                    */
 /************************************************************************/
 
-static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
+static bool GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
 {
     CPLString osTmpFilename;
     static int nCounter = 0;
     osTmpFilename.Printf("/vsimem/stream_%d.tif", ++nCounter);
     VSILFILE* fpTemp = VSIFOpenL(osTmpFilename, "wb+");
     if( fpTemp == NULL )
-        return FALSE;
-    /* The seek is needed for /vsistdin/ that has some rewind capabilities */
+        return false;
+    // The seek is needed for /vsistdin/ that has some rewind capabilities.
     if( VSIFSeekL(poOpenInfo->fpL, poOpenInfo->nHeaderBytes, SEEK_SET) != 0 )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
-        return FALSE;
+        return false;
     }
-    CPLAssert( (int)VSIFTellL(poOpenInfo->fpL) == poOpenInfo->nHeaderBytes );
-    if( VSIFWriteL(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes, 1, fpTemp) != 1 )
+    CPLAssert( static_cast<int>( VSIFTellL(poOpenInfo->fpL) ) ==
+               poOpenInfo->nHeaderBytes );
+    if( VSIFWriteL(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes,
+                   1, fpTemp) != 1 )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
-        return FALSE;
-    }
-    vsi_l_offset nDataLength;
-    GByte* pabyBuffer = (GByte*)VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE);
-    int bLittleEndian = (pabyBuffer[0] == 'I');
-    int bSwap = (bLittleEndian && !CPL_IS_LSB) || (!bLittleEndian && CPL_IS_LSB);
-    int bBigTIFF = ( pabyBuffer[2] == 43 || pabyBuffer[3] == 43 );
+        return false;
+    }
+    vsi_l_offset nDataLength = 0;
+    GByte* pabyBuffer =
+        static_cast<GByte*>(
+            VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE) );
+    const bool bLittleEndian = (pabyBuffer[0] == 'I');
+#if CPL_IS_LSB
+    const bool bSwap = !bLittleEndian;
+#else
+    const bool bSwap = bLittleEndian;
+#endif
+    const bool bBigTIFF = pabyBuffer[2] == 43 || pabyBuffer[3] == 43;
     vsi_l_offset nMaxOffset = 0;
     if( bBigTIFF )
     {
-        GUIntBig nTmp;
+#ifndef CPL_HAS_GINT64
+        CPLError(CE_Failure, CPLE_NotSupported, "BigTIFF not supported");
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
+        VSIUnlink(osTmpFilename);
+        return false;
+#else
+        GUInt64 nTmp = 0;
         memcpy(&nTmp, pabyBuffer + 8, 8);
         if( bSwap ) CPL_SWAP64PTR(&nTmp);
         if( nTmp != 16 )
@@ -9779,7 +11241,7 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
                      "IFD start should be at offset 16 for a streamed BigTIFF");
             CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
-            return FALSE;
+            return false;
         }
         memcpy(&nTmp, pabyBuffer + 16, 8);
         if( bSwap ) CPL_SWAP64PTR(&nTmp);
@@ -9789,60 +11251,64 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
                      "Too many tags : " CPL_FRMT_GIB, nTmp);
             CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
-            return FALSE;
+            return false;
         }
-        int nTags = static_cast<int>(nTmp);
-        int nSpaceForTags = nTags * 20;
+        const int nTags = static_cast<int>(nTmp);
+        const int nSpaceForTags = nTags * 20;
         if( !GTIFFExtendMemoryFile(osTmpFilename, fpTemp, poOpenInfo->fpL,
                                     24 + nSpaceForTags,
                                     pabyBuffer, nDataLength) )
         {
             CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
-            return FALSE;
+            return false;
         }
         nMaxOffset = 24 + nSpaceForTags + 8;
-        for(int i=0;i<nTags;i++)
+        for( int i = 0; i < nTags; ++i )
         {
-            GUInt16 nTmp16;
+            GUInt16 nTmp16 = 0;
             memcpy(&nTmp16, pabyBuffer + 24 + i * 20, 2);
             if( bSwap ) CPL_SWAP16PTR(&nTmp16);
-            int nTag = nTmp16;
+            const int nTag = nTmp16;
             memcpy(&nTmp16, pabyBuffer + 24 + i * 20 + 2, 2);
             if( bSwap ) CPL_SWAP16PTR(&nTmp16);
-            int nDataType = nTmp16;
+            const int nDataType = nTmp16;
             memcpy(&nTmp, pabyBuffer + 24 + i * 20 + 4, 8);
             if( bSwap ) CPL_SWAP64PTR(&nTmp);
             if( nTmp >= 16 * 1024 * 1024 )
             {
-                CPLError(CE_Failure, CPLE_NotSupported,
-                         "Too many elements for tag %d : " CPL_FRMT_GUIB, nTag, nTmp);
+                CPLError(
+                    CE_Failure, CPLE_NotSupported,
+                    "Too many elements for tag %d : " CPL_FRMT_GUIB,
+                    nTag, nTmp );
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
                 VSIUnlink(osTmpFilename);
-                return FALSE;
+                return false;
             }
-            GUInt32 nCount = (GUInt32)nTmp;
-            GUInt32 nTagSize = TIFFDataWidth((TIFFDataType)nDataType) * nCount;
+            const GUInt32 nCount = static_cast<GUInt32>(nTmp);
+            const GUInt32 nTagSize =
+                TIFFDataWidth((TIFFDataType)nDataType) * nCount;
             if( nTagSize > 8 )
             {
                 memcpy(&nTmp, pabyBuffer + 24 + i * 20 + 12, 8);
                 if( bSwap ) CPL_SWAP64PTR(&nTmp);
-                if( nTmp > (GUIntBig)((((GIntBig)INT_MAX) << 32) - nTagSize) )
+                if( nTmp > GUINT64_MAX - nTagSize )
                 {
                     CPLError(CE_Failure, CPLE_NotSupported,
                              "Overflow with tag %d", nTag);
                     CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
                     VSIUnlink(osTmpFilename);
-                    return FALSE;
+                    return false;
                 }
-                if( (vsi_l_offset)(nTmp + nTagSize) > nMaxOffset )
+                if( static_cast<vsi_l_offset>(nTmp + nTagSize) > nMaxOffset )
                     nMaxOffset = nTmp + nTagSize;
             }
         }
+#endif
     }
     else
     {
-        GUInt32 nTmp;
+        GUInt32 nTmp = 0;
         memcpy(&nTmp, pabyBuffer + 4, 4);
         if( bSwap ) CPL_SWAP32PTR(&nTmp);
         if( nTmp != 8 )
@@ -9851,9 +11317,9 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
                      "IFD start should be at offset 8 for a streamed TIFF");
             CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
-            return FALSE;
+            return false;
         }
-        GUInt16 nTmp16;
+        GUInt16 nTmp16 = 0;
         memcpy(&nTmp16, pabyBuffer + 8, 2);
         if( bSwap ) CPL_SWAP16PTR(&nTmp16);
         if( nTmp16 > 1024 )
@@ -9862,27 +11328,27 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
                      "Too many tags : %d", nTmp16);
             CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
-            return FALSE;
+            return false;
         }
-        int nTags = nTmp16;
-        int nSpaceForTags = nTags * 12;
+        const int nTags = nTmp16;
+        const int nSpaceForTags = nTags * 12;
         if( !GTIFFExtendMemoryFile(osTmpFilename, fpTemp, poOpenInfo->fpL,
-                                    10 + nSpaceForTags,
-                                    pabyBuffer, nDataLength) )
+                                   10 + nSpaceForTags,
+                                   pabyBuffer, nDataLength) )
         {
             CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
             VSIUnlink(osTmpFilename);
-            return FALSE;
+            return false;
         }
         nMaxOffset = 10 + nSpaceForTags + 4;
-        for(int i=0;i<nTags;i++)
+        for( int i = 0; i < nTags; ++i )
         {
             memcpy(&nTmp16, pabyBuffer + 10 + i * 12, 2);
             if( bSwap ) CPL_SWAP16PTR(&nTmp16);
-            int nTag = nTmp16;
+            const int nTag = nTmp16;
             memcpy(&nTmp16, pabyBuffer + 10 + i * 12 + 2, 2);
             if( bSwap ) CPL_SWAP16PTR(&nTmp16);
-            int nDataType = nTmp16;
+            const int nDataType = nTmp16;
             memcpy(&nTmp, pabyBuffer + 10 + i * 12 + 4, 4);
             if( bSwap ) CPL_SWAP32PTR(&nTmp);
             if( nTmp >= 16 * 1024 * 1024 )
@@ -9891,21 +11357,22 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
                          "Too many elements for tag %d : %u", nTag, nTmp);
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
                 VSIUnlink(osTmpFilename);
-                return FALSE;
+                return false;
             }
-            GUInt32 nCount = nTmp;
-            GUInt32 nTagSize = TIFFDataWidth((TIFFDataType)nDataType) * nCount;
+            const GUInt32 nCount = nTmp;
+            const GUInt32 nTagSize =
+                TIFFDataWidth(static_cast<TIFFDataType>(nDataType)) * nCount;
             if( nTagSize > 4 )
             {
                 memcpy(&nTmp, pabyBuffer + 10 + i * 12 + 8, 4);
                 if( bSwap ) CPL_SWAP32PTR(&nTmp);
-                if( nTmp > (GUInt32)(0xFFFFFFFFU - nTagSize) )
+                if( nTmp > static_cast<GUInt32>(0xFFFFFFFFU - nTagSize) )
                 {
                     CPLError(CE_Failure, CPLE_NotSupported,
                              "Overflow with tag %d", nTag);
                     CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
                     VSIUnlink(osTmpFilename);
-                    return FALSE;
+                    return false;
                 }
                 if( nTmp + nTagSize > nMaxOffset )
                     nMaxOffset = nTmp + nTagSize;
@@ -9916,23 +11383,27 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
         VSIUnlink(osTmpFilename);
-        return FALSE;
+        return false;
     }
-    if( !GTIFFExtendMemoryFile(osTmpFilename, fpTemp, poOpenInfo->fpL,
-                               static_cast<int>(nMaxOffset), pabyBuffer, nDataLength) )
+    if( !GTIFFExtendMemoryFile(
+           osTmpFilename, fpTemp, poOpenInfo->fpL,
+           static_cast<int>(nMaxOffset), pabyBuffer, nDataLength) )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpTemp));
         VSIUnlink(osTmpFilename);
-        return FALSE;
+        return false;
     }
     CPLAssert(nDataLength == VSIFTellL(poOpenInfo->fpL));
-    poOpenInfo->fpL = (VSILFILE*)VSICreateBufferedReaderHandle(
-        (VSIVirtualHandle*)poOpenInfo->fpL, pabyBuffer, ((vsi_l_offset)INT_MAX) << 32 );
+    poOpenInfo->fpL = reinterpret_cast<VSILFILE *>(
+        VSICreateBufferedReaderHandle(
+            reinterpret_cast<VSIVirtualHandle*>(poOpenInfo->fpL),
+            pabyBuffer,
+            static_cast<vsi_l_offset>(INT_MAX) << 32 ) );
     if( VSIFCloseL(fpTemp) != 0 )
-        return FALSE;
+        return false;
     VSIUnlink(osTmpFilename);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -9942,20 +11413,19 @@ static int GTIFFMakeBufferedStream(GDALOpenInfo* poOpenInfo)
 GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    TIFF *hTIFF;
-    int          bAllowRGBAInterface = TRUE;
-    const char  *pszFilename = poOpenInfo->pszFilename;
+    const char *pszFilename = poOpenInfo->pszFilename;
 
 /* -------------------------------------------------------------------- */
 /*      Check if it looks like a TIFF file.                             */
 /* -------------------------------------------------------------------- */
-    if (!Identify(poOpenInfo))
+    if( !Identify(poOpenInfo) )
         return NULL;
 
+    bool bAllowRGBAInterface = true;
     if( STARTS_WITH_CI(pszFilename, "GTIFF_RAW:") )
     {
-        bAllowRGBAInterface = FALSE;
-        pszFilename +=  strlen("GTIFF_RAW:");
+        bAllowRGBAInterface = false;
+        pszFilename += strlen("GTIFF_RAW:");
     }
 
 /* -------------------------------------------------------------------- */
@@ -9965,158 +11435,186 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
     if( STARTS_WITH_CI(pszFilename, "GTIFF_DIR:") )
         return OpenDir( poOpenInfo );
 
-    if (!GTiffOneTimeInit())
+    if( !GTiffOneTimeInit() )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-
-    /* Disable strip chop for now */
-    int bStreaming = FALSE;
-    const char* pszReadStreaming = CPLGetConfigOption("TIFF_READ_STREAMING", NULL);
+    // Disable strip chop for now.
+    bool bStreaming = false;
+    const char* pszReadStreaming =
+        CPLGetConfigOption("TIFF_READ_STREAMING", NULL);
     if( poOpenInfo->fpL == NULL )
     {
-        poOpenInfo->fpL = VSIFOpenL( pszFilename, ( poOpenInfo->eAccess == GA_ReadOnly ) ? "rb" : "r+b" );
+        poOpenInfo->fpL =
+            VSIFOpenL( pszFilename,
+                       poOpenInfo->eAccess == GA_ReadOnly ? "rb" : "r+b" );
         if( poOpenInfo->fpL == NULL )
             return NULL;
     }
     else if( !(pszReadStreaming && !CPLTestBool(pszReadStreaming)) &&
              poOpenInfo->nHeaderBytes >= 24 &&
-             ((int)VSIFTellL(poOpenInfo->fpL) == poOpenInfo->nHeaderBytes || /* A pipe has no seeking capability, so its position is 0 despite having read bytes */
+             // A pipe has no seeking capability, so its position is 0 despite
+             // having read bytes.
+             (static_cast<int>( VSIFTellL(poOpenInfo->fpL) ) ==
+              poOpenInfo->nHeaderBytes ||
               strcmp(pszFilename, "/vsistdin/") == 0 ||
-              //STARTS_WITH(pszFilename, "/vsicurl_streaming/") ||
+              // STARTS_WITH(pszFilename, "/vsicurl_streaming/") ||
               (pszReadStreaming && CPLTestBool(pszReadStreaming))) )
     {
-        bStreaming = TRUE;
+        bStreaming = true;
         if( !GTIFFMakeBufferedStream(poOpenInfo) )
             return NULL;
     }
 
-    /* Store errors/warnings and emit them later */
+    // Store errors/warnings and emit them later.
     std::vector<GTIFFErrorStruct> aoErrors;
     CPLPushErrorHandlerEx(GTIFFErrorHandler, &aoErrors);
     CPLSetCurrentErrorHandlerCatchDebug( FALSE );
-    hTIFF = VSI_TIFFOpen( pszFilename, ( poOpenInfo->eAccess == GA_ReadOnly ) ? "rc" : "r+c",
-                          poOpenInfo->fpL );
+    TIFF *l_hTIFF =
+        VSI_TIFFOpen( pszFilename,
+                      poOpenInfo->eAccess == GA_ReadOnly ? "rc" : "r+c",
+                      poOpenInfo->fpL );
     CPLPopErrorHandler();
 #if SIZEOF_VOIDP == 4
-    if( hTIFF == NULL )
+    if( l_hTIFF == NULL )
     {
-        /* Case of one-strip file where the strip size is > 2GB (#5403) */
+        // Case of one-strip file where the strip size is > 2GB (#5403).
         if( bGlobalStripIntegerOverflow )
         {
-            hTIFF = VSI_TIFFOpen( pszFilename, ( poOpenInfo->eAccess == GA_ReadOnly ) ? "r" : "r+",
-                                  poOpenInfo->fpL );
-            bGlobalStripIntegerOverflow = FALSE;
+            l_hTIFF =
+                VSI_TIFFOpen( pszFilename,
+                              poOpenInfo->eAccess == GA_ReadOnly ? "r" : "r+",
+                              poOpenInfo->fpL );
+            bGlobalStripIntegerOverflow = false;
         }
     }
     else
     {
-        bGlobalStripIntegerOverflow = FALSE;
+        bGlobalStripIntegerOverflow = false;
     }
 #endif
 
-    /* Now emit errors and change their criticality if needed */
-    /* We only emit failures if we didn't manage to open the file */
-    /* Otherwise it make Python bindings unhappy (#5616) */
-    for(size_t iError=0;iError<aoErrors.size();iError++)
+    // Now emit errors and change their criticality if needed
+    // We only emit failures if we didn't manage to open the file.
+    // Otherwise it makes Python bindings unhappy (#5616).
+    for( size_t iError = 0; iError < aoErrors.size(); ++iError )
     {
-        CPLError( (hTIFF == NULL && aoErrors[iError].type == CE_Failure) ? CE_Failure : CE_Warning,
+        CPLError( (l_hTIFF == NULL && aoErrors[iError].type == CE_Failure) ?
+                  CE_Failure : CE_Warning,
                   aoErrors[iError].no,
                   "%s",
                   aoErrors[iError].msg.c_str() );
     }
     aoErrors.resize(0);
 
-    if( hTIFF == NULL )
-        return( NULL );
-
-    uint32  nXSize, nYSize;
-    uint16  nPlanarConfig;
-    uint32  nRowsPerStrip;
-    uint16  nCompression;
+    if( l_hTIFF == NULL )
+        return NULL;
 
-    TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
-    TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
+    uint32 nXSize = 0;
+    TIFFGetField( l_hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
+    uint32 nYSize = 0;
+    TIFFGetField( l_hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
 
     if( nXSize > INT_MAX || nYSize > INT_MAX )
     {
-        /* GDAL only supports signed 32bit dimensions */
-        XTIFFClose( hTIFF );
-        return( NULL );
+        // GDAL only supports signed 32bit dimensions.
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Too large image size: %u x %u",
+                 nXSize, nYSize);
+        XTIFFClose( l_hTIFF );
+        return NULL;
     }
 
-    if( !TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(nPlanarConfig) ) )
-        nPlanarConfig = PLANARCONFIG_CONTIG;
-
-    if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
-        nCompression = COMPRESSION_NONE;
-
-    if( !TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nRowsPerStrip) ) )
-        nRowsPerStrip = nYSize;
-
-    if (!TIFFIsTiled( hTIFF ) &&
-        nCompression == COMPRESSION_NONE &&
-        nRowsPerStrip >= nYSize &&
-        nPlanarConfig == PLANARCONFIG_CONTIG)
-    {
-        int bReopenWithStripChop = TRUE;
-        if ( nYSize > 128 * 1024 * 1024 )
-        {
-            uint16  nSamplesPerPixel;
-            uint16  nBitsPerSample;
-
-            if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamplesPerPixel ) )
-                nSamplesPerPixel = 1;
-
-            if( !TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &(nBitsPerSample)) )
-                nBitsPerSample = 1;
-
-            vsi_l_offset nLineSize = (nSamplesPerPixel * (vsi_l_offset)nXSize * nBitsPerSample + 7) / 8;
-            int nDefaultStripHeight = (int)(8192 / nLineSize);
-            if (nDefaultStripHeight == 0) nDefaultStripHeight = 1;
-            vsi_l_offset nStrips = nYSize / nDefaultStripHeight;
-
-            /* There is a risk of DoS due to huge amount of memory allocated in ChopUpSingleUncompressedStrip() */
-            /* in libtiff */
-            if (nStrips > 128 * 1024 * 1024 &&
-                !CPLTestBool(CPLGetConfigOption("GTIFF_FORCE_STRIP_CHOP", "NO")))
+    uint16 l_nPlanarConfig = 0;
+    if( !TIFFGetField( l_hTIFF, TIFFTAG_PLANARCONFIG, &(l_nPlanarConfig) ) )
+        l_nPlanarConfig = PLANARCONFIG_CONTIG;
+
+    uint16 l_nCompression = 0;
+    if( !TIFFGetField( l_hTIFF, TIFFTAG_COMPRESSION, &(l_nCompression) ) )
+        l_nCompression = COMPRESSION_NONE;
+
+    uint32 l_nRowsPerStrip = 0;
+    if( !TIFFGetField( l_hTIFF, TIFFTAG_ROWSPERSTRIP, &(l_nRowsPerStrip) ) )
+        l_nRowsPerStrip = nYSize;
+
+    if( !TIFFIsTiled( l_hTIFF ) &&
+        l_nCompression == COMPRESSION_NONE &&
+        l_nRowsPerStrip >= nYSize &&
+        l_nPlanarConfig == PLANARCONFIG_CONTIG )
+    {
+        bool bReopenWithStripChop = true;
+        if( nYSize > 128 * 1024 * 1024 )
+        {
+            uint16 l_nSamplesPerPixel = 0;
+            if( !TIFFGetField( l_hTIFF, TIFFTAG_SAMPLESPERPIXEL,
+                               &l_nSamplesPerPixel ) )
+                l_nSamplesPerPixel = 1;
+
+            uint16 l_nBitsPerSample = 0;
+            if( !TIFFGetField(l_hTIFF, TIFFTAG_BITSPERSAMPLE,
+                              &(l_nBitsPerSample)) )
+                l_nBitsPerSample = 1;
+
+            const vsi_l_offset nLineSize =
+                (l_nSamplesPerPixel * static_cast<vsi_l_offset>(nXSize) *
+                 l_nBitsPerSample + 7) / 8;
+            int nDefaultStripHeight = static_cast<int>(8192 / nLineSize);
+            if( nDefaultStripHeight == 0 ) nDefaultStripHeight = 1;
+            const vsi_l_offset nStrips = nYSize / nDefaultStripHeight;
+
+            // There is a risk of DoS due to huge amount of memory allocated in
+            // ChopUpSingleUncompressedStrip() in libtiff.
+            if( nStrips > 128 * 1024 * 1024 &&
+                !CPLTestBool(
+                    CPLGetConfigOption("GTIFF_FORCE_STRIP_CHOP", "NO")) )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                        "Potential denial of service detected. Avoid using strip chop. "
-                        "Set the GTIFF_FORCE_STRIP_CHOP configuration open to go over this test.");
-                bReopenWithStripChop = FALSE;
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Potential denial of service detected. Avoid using strip "
+                    "chop. Set the GTIFF_FORCE_STRIP_CHOP configuration open "
+                    "to go over this test." );
+                bReopenWithStripChop = false;
             }
         }
 
-        if (bReopenWithStripChop)
+        if( bReopenWithStripChop )
         {
             CPLDebug("GTiff", "Reopen with strip chop enabled");
-            XTIFFClose(hTIFF);
-            hTIFF = VSI_TIFFOpen( pszFilename, ( poOpenInfo->eAccess == GA_ReadOnly ) ? "r" : "r+",
-                                  poOpenInfo->fpL );
-            if( hTIFF == NULL )
-                return( NULL );
+            XTIFFClose(l_hTIFF);
+            l_hTIFF =
+                VSI_TIFFOpen( pszFilename,
+                              poOpenInfo->eAccess == GA_ReadOnly ? "r" : "r+",
+                              poOpenInfo->fpL );
+            if( l_hTIFF == NULL )
+                return NULL;
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GTiffDataset *poDS;
-
-    poDS = new GTiffDataset();
+    GTiffDataset *poDS = new GTiffDataset();
     poDS->SetDescription( pszFilename );
     poDS->osFilename = pszFilename;
     poDS->poActiveDS = poDS;
     poDS->fpL = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
     poDS->bStreamingIn = bStreaming;
-    poDS->nCompression = nCompression;
+    poDS->nCompression = l_nCompression;
+
+    // In the case of GDAL_DISABLE_READDIR_ON_OPEN = NO / EMPTY_DIR
+    if( poOpenInfo->AreSiblingFilesLoaded() &&
+        CSLCount( poOpenInfo->GetSiblingFiles() ) <= 1 )
+    {
+        poDS->oOvManager.TransferSiblingFiles( CSLDuplicate(
+                                            poOpenInfo->GetSiblingFiles() ) );
+        poDS->m_bHasGotSiblingFiles = true;
+    }
 
-    if( poDS->OpenOffset( hTIFF, &(poDS->poActiveDS),
-                          TIFFCurrentDirOffset(hTIFF), TRUE,
+    if( poDS->OpenOffset( l_hTIFF, &(poDS->poActiveDS),
+                          TIFFCurrentDirOffset(l_hTIFF), true,
                           poOpenInfo->eAccess,
                           bAllowRGBAInterface, true) != CE_None )
     {
@@ -10124,115 +11622,35 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+    // Do we want blocks that are set to zero and that haven't yet being
+    // allocated as tile/strip to remain implicit?
+    if( CPLFetchBool( poOpenInfo->papszOpenOptions, "SPARSE_OK", false ) )
+        poDS->bWriteEmptyTiles = false;
+
     if( poOpenInfo->eAccess == GA_Update )
     {
         poDS->InitCreationOrOpenOptions(poOpenInfo->papszOpenOptions);
     }
 
-    if( nCompression == COMPRESSION_JPEG && poOpenInfo->eAccess == GA_Update )
-    {
-        int bHasQuantizationTable = FALSE, bHasHuffmanTable = FALSE;
-        int nQuality = poDS->GuessJPEGQuality(bHasQuantizationTable,
-                                              bHasHuffmanTable);
-        if( nQuality > 0 )
-        {
-            CPLDebug("GTiff", "Guessed JPEG quality to be %d", nQuality);
-            poDS->nJpegQuality = nQuality;
-            TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nQuality );
-
-            /* This means we will use the quantization tables from the JpegTables */
-            /* tag */
-            poDS->nJpegTablesMode = JPEGTABLESMODE_QUANT;
-        }
-        else
-        {
-            uint32 nJPEGTableSize = 0;
-            void* pJPEGTable = NULL;
-            if( !TIFFGetField(hTIFF, TIFFTAG_JPEGTABLES, &nJPEGTableSize, &pJPEGTable) )
-            {
-                int bFoundNonEmptyBlock = FALSE;
-                toff_t *panByteCounts = NULL;
-                int nBlockCount;
-                if( poDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
-                    nBlockCount = poDS->nBlocksPerBand * poDS->nBands;
-                else
-                    nBlockCount = poDS->nBlocksPerBand;
-                if( TIFFIsTiled( hTIFF ) )
-                    TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS, &panByteCounts );
-                else
-                    TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS, &panByteCounts );
-                if( panByteCounts != NULL )
-                {
-                    for( int iBlock = 0; iBlock < nBlockCount; iBlock++ )
-                    {
-                        if( panByteCounts[iBlock] != 0 )
-                        {
-                            bFoundNonEmptyBlock = TRUE;
-                            break;
-                        }
-                    }
-                }
-                if( bFoundNonEmptyBlock )
-                {
-                    CPLDebug("GTiff", "Could not guess JPEG quality. "
-                             "JPEG tables are missing, so going in "
-                             "TIFFTAG_JPEGTABLESMODE = 0/2 mode");
-                    /* Write quantization tables in each strile */
-                    poDS->nJpegTablesMode = 0;
-                }
-            }
-            else
-            {
-                if( bHasQuantizationTable )
-                {
-                    // FIXME in libtiff: this is likely going to cause issues since
-                    // libtiff will reuse in each strile the number of the global
-                    // quantization table, which is invalid.
-
-                    CPLDebug("GTiff", "Could not guess JPEG quality although JPEG "
-                            "quantization tables are present, so going in "
-                            "TIFFTAG_JPEGTABLESMODE = 0/2 mode");
-                }
-                else
-                {
-                    CPLDebug("GTiff", "Could not guess JPEG quality since JPEG "
-                            "quantization tables are not present, so going in "
-                            "TIFFTAG_JPEGTABLESMODE = 0/2 mode");
-                }
-
-                /* Write quantization tables in each strile */
-                poDS->nJpegTablesMode = 0;
-            }
-        }
-        if( bHasHuffmanTable )
-        {
-            /* If there are Huffman tables in header use them, otherwise */
-            /* if we use optimized tables, libtiff will currently reuse */
-            /* the number of the Huffman tables of the header for the */
-            /* optimized version of each strile, which is illegal */
-            poDS->nJpegTablesMode |= JPEGTABLESMODE_HUFF;
-        }
-        if( poDS->nJpegTablesMode >= 0 )
-            TIFFSetField( hTIFF, TIFFTAG_JPEGTABLESMODE, poDS->nJpegTablesMode);
-    }
-
     poDS->m_bLoadPam = true;
-    poDS->bColorProfileMetadataChanged = FALSE;
-    poDS->bMetadataChanged = FALSE;
-    poDS->bGeoTIFFInfoChanged = FALSE;
-    poDS->bNoDataChanged = FALSE;
-    poDS->bForceUnsetGTOrGCPs = FALSE;
-    poDS->bForceUnsetProjection = FALSE;
+    poDS->bColorProfileMetadataChanged = false;
+    poDS->bMetadataChanged = false;
+    poDS->bGeoTIFFInfoChanged = false;
+    poDS->bNoDataChanged = false;
+    poDS->bForceUnsetGTOrGCPs = false;
+    poDS->bForceUnsetProjection = false;
 
 /* -------------------------------------------------------------------- */
 /*      Initialize info for external overviews.                         */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, pszFilename );
     if( poOpenInfo->AreSiblingFilesLoaded() )
-        poDS->oOvManager.TransferSiblingFiles( poOpenInfo->StealSiblingFiles() );
+        poDS->oOvManager.TransferSiblingFiles(
+            poOpenInfo->StealSiblingFiles() );
 
-    /* For backward compatibility, in case GTIFF_POINT_GEO_IGNORE is defined */
-    /* load georeferencing right now */
+    // For backward compatibility, in case GTIFF_POINT_GEO_IGNORE is defined
+    // load georeferencing right now so as to not require it to be defined
+    // at the GetGeoTransform() time.
     if( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE", NULL) != NULL )
     {
         poDS->LoadGeoreferencingAndPamIfNeeded();
@@ -10245,19 +11663,19 @@ GDALDataset *GTiffDataset::Open( GDALOpenInfo * poOpenInfo )
 /*                      GTiffDatasetSetAreaOrPointMD()                  */
 /************************************************************************/
 
-static void GTiffDatasetSetAreaOrPointMD(GTIF* hGTIF,
-                                         GDALMultiDomainMetadata& oGTiffMDMD)
+static void GTiffDatasetSetAreaOrPointMD( GTIF* hGTIF,
+                                          GDALMultiDomainMetadata& oGTiffMDMD )
 {
     // Is this a pixel-is-point dataset?
-    short nRasterType;
+    short nRasterType = 0;
 
     if( GDALGTIFKeyGetSHORT(hGTIF, GTRasterTypeGeoKey, &nRasterType,
                     0, 1 ) == 1 )
     {
-        if( nRasterType == (short) RasterPixelIsPoint )
-            oGTiffMDMD.SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
+        if( nRasterType == static_cast<short>(RasterPixelIsPoint) )
+            oGTiffMDMD.SetMetadataItem(GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT);
         else
-            oGTiffMDMD.SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_AREA );
+            oGTiffMDMD.SetMetadataItem(GDALMD_AREA_OR_POINT, GDALMD_AOP_AREA);
     }
 }
 
@@ -10265,9 +11683,9 @@ static void GTiffDatasetSetAreaOrPointMD(GTIF* hGTIF,
 /*                         LoadMDAreaOrPoint()                          */
 /************************************************************************/
 
-/* This is a light version of LookForProjection(), which saves the */
-/* potential costly cost of GTIFGetOGISDefn(), since we just need to */
-/* access to a raw GeoTIFF key, and not build the full projection object. */
+// This is a light version of LookForProjection(), which saves the
+// potential costly cost of GTIFGetOGISDefn(), since we just need to
+// access to a raw GeoTIFF key, and not build the full projection object.
 
 void GTiffDataset::LoadMDAreaOrPoint()
 {
@@ -10275,14 +11693,14 @@ void GTiffDataset::LoadMDAreaOrPoint()
         oGTiffMDMD.GetMetadataItem( GDALMD_AREA_OR_POINT ) != NULL )
         return;
 
-    bLookedForMDAreaOrPoint = TRUE;
+    bLookedForMDAreaOrPoint = true;
 
-    if (!SetDirectory())
+    if( !SetDirectory() )
         return;
 
     GTIF* hGTIF = GTIFNew(hTIFF);
 
-    if ( !hGTIF )
+    if( !hGTIF )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "GeoTIFF tags apparently corrupt, they are being ignored." );
@@ -10305,57 +11723,69 @@ void GTiffDataset::LookForProjection()
     if( bLookedForProjection )
         return;
 
-    bLookedForProjection = TRUE;
-    if (!SetDirectory())
+    bLookedForProjection = true;
+
+    IdentifyAuthorizedGeoreferencingSources();
+    if( m_nINTERNALGeorefSrcIndex < 0 )
+        return;
+
+    if( !SetDirectory() )
         return;
 
 /* -------------------------------------------------------------------- */
 /*      Capture the GeoTIFF projection, if available.                   */
 /* -------------------------------------------------------------------- */
-    GTIF *hGTIF;
-
     CPLFree( pszProjection );
     pszProjection = NULL;
 
-    hGTIF = GTIFNew(hTIFF);
+    GTIF *hGTIF = GTIFNew(hTIFF);
 
-    if ( !hGTIF )
+    if( !hGTIF )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "GeoTIFF tags apparently corrupt, they are being ignored." );
     }
     else
     {
-        GTIFDefn      *psGTIFDefn;
-
 #if LIBGEOTIFF_VERSION >= 1410
-        psGTIFDefn = GTIFAllocDefn();
+        GTIFDefn *psGTIFDefn = GTIFAllocDefn();
 #else
-        psGTIFDefn = (GTIFDefn *) CPLCalloc(1,sizeof(GTIFDefn));
+        GTIFDefn *psGTIFDefn =
+            static_cast<GTIFDefn *>(CPLCalloc(1, sizeof(GTIFDefn)));
 #endif
 
         if( GTIFGetDefn( hGTIF, psGTIFDefn ) )
         {
             pszProjection = GTIFGetOGISDefn( hGTIF, psGTIFDefn );
 
-            // Should we simplify away vertical CS stuff?
-            if( STARTS_WITH_CI(pszProjection, "COMPD_CS")
-                && !CPLTestBool( CPLGetConfigOption("GTIFF_REPORT_COMPD_CS",
-                                                       "NO") ) )
+            if( STARTS_WITH_CI(pszProjection, "COMPD_CS") )
             {
                 OGRSpatialReference oSRS;
 
-                CPLDebug( "GTiff", "Got COMPD_CS, but stripping it." );
                 char *pszWKT = pszProjection;
                 oSRS.importFromWkt( &pszWKT );
-                CPLFree( pszProjection );
 
-                oSRS.StripVertical();
-                oSRS.exportToWkt( &pszProjection );
+                char* pszVertUnit = NULL;
+                oSRS.GetTargetLinearUnits("COMPD_CS|VERT_CS", &pszVertUnit);
+                if( pszVertUnit && !EQUAL(pszVertUnit, "unknown") )
+                {
+                    m_osVertUnit = pszVertUnit;
+                }
+
+                // Should we simplify away vertical CS stuff?
+                if( !CPLTestBool( CPLGetConfigOption("GTIFF_REPORT_COMPD_CS",
+                                                    "NO") ) )
+                {
+                    CPLDebug( "GTiff", "Got COMPD_CS, but stripping it." );
+
+                    oSRS.StripVertical();
+                    CPLFree( pszProjection );
+                    oSRS.exportToWkt( &pszProjection );
+                }
             }
         }
 
-        // check the tif linear unit and the CS linear unit
+        // Check the tif linear unit and the CS linear unit.
 #ifdef ESRI_BUILD
         AdjustLinearUnit(psGTIFDefn.UOMLength);
 #endif
@@ -10375,10 +11805,14 @@ void GTiffDataset::LookForProjection()
     {
         pszProjection = CPLStrdup( "" );
     }
+    // else if( !EQUAL(pszProjection, "") )
+    // {
+    //     m_nProjectionGeorefSrcIndex = m_nINTERNALGeorefSrcIndex;
+    // }
 
-    bGeoTIFFInfoChanged = FALSE;
-    bForceUnsetGTOrGCPs = FALSE;
-    bForceUnsetProjection = FALSE;
+    bGeoTIFFInfoChanged = false;
+    bForceUnsetGTOrGCPs = false;
+    bForceUnsetProjection = false;
 }
 
 /************************************************************************/
@@ -10390,37 +11824,37 @@ void GTiffDataset::LookForProjection()
 /************************************************************************/
 #ifdef ESRI_BUILD
 
-void GTiffDataset::AdjustLinearUnit(short UOMLength)
+void GTiffDataset::AdjustLinearUnit( short UOMLength )
 {
-    if (!pszProjection || strlen(pszProjection) == 0)
+    if( !pszProjection || strlen(pszProjection) == 0 )
         return;
-    if( UOMLength == 9001)
+    if( UOMLength == 9001 )
     {
         char* pstr = strstr(pszProjection, "PARAMETER");
-        if (!pstr)
+        if( !pstr )
             return;
         pstr = strstr(pstr, "UNIT[");
-        if (!pstr)
+        if( !pstr )
             return;
         pstr = strchr(pstr, ',') + 1;
-        if (!pstr)
+        if( !pstr )
             return;
         char* pstr1 = strchr(pstr, ']');
-        if (!pstr1 || pstr1 - pstr >= 128)
+        if( !pstr1 || pstr1 - pstr >= 128 )
             return;
         char csUnitStr[128];
-        strncpy(csUnitStr, pstr, pstr1-pstr);
+        strncpy(csUnitStr, pstr, pstr1 - pstr);
         csUnitStr[pstr1-pstr] = '\0';
-        double csUnit = CPLAtof(csUnitStr);
-        if(fabs(csUnit - 1.0) > 0.000001)
+        const double csUnit = CPLAtof(csUnitStr);
+        if( fabs(csUnit - 1.0) > 0.000001 )
         {
-            for(long i=0; i<6; i++)
+            for( long i = 0; i < 6; ++i )
                 adfGeoTransform[i] /= csUnit;
         }
     }
 }
 
-#endif /* def ESRI_BUILD */
+#endif  // def ESRI_BUILD
 
 /************************************************************************/
 /*                            ApplyPamInfo()                            */
@@ -10433,28 +11867,65 @@ void GTiffDataset::AdjustLinearUnit(short UOMLength)
 void GTiffDataset::ApplyPamInfo()
 
 {
-    double adfPamGeoTransform[6];
-
-    if( GDALPamDataset::GetGeoTransform( adfPamGeoTransform ) == CE_None
-        && (adfPamGeoTransform[0] != 0.0 || adfPamGeoTransform[1] != 1.0
-            || adfPamGeoTransform[2] != 0.0 || adfPamGeoTransform[3] != 0.0
-            || adfPamGeoTransform[4] != 0.0 || adfPamGeoTransform[5] != 1.0 ))
+    if( m_nPAMGeorefSrcIndex >= 0 &&
+        ((bGeoTransformValid &&
+          m_nPAMGeorefSrcIndex < m_nGeoTransformGeorefSrcIndex) ||
+          m_nGeoTransformGeorefSrcIndex < 0 || !bGeoTransformValid) )
     {
-        memcpy( adfGeoTransform, adfPamGeoTransform, sizeof(double)*6 );
-        bGeoTransformValid = TRUE;
+        double adfPamGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+        if( GDALPamDataset::GetGeoTransform( adfPamGeoTransform ) == CE_None
+            && (adfPamGeoTransform[0] != 0.0 || adfPamGeoTransform[1] != 1.0
+                || adfPamGeoTransform[2] != 0.0 || adfPamGeoTransform[3] != 0.0
+                || adfPamGeoTransform[4] != 0.0
+                || adfPamGeoTransform[5] != 1.0 ))
+        {
+            if( m_nGeoTransformGeorefSrcIndex == m_nWORLDFILEGeorefSrcIndex )
+                osGeorefFilename.clear();
+            memcpy(adfGeoTransform, adfPamGeoTransform, sizeof(double) * 6);
+            bGeoTransformValid = true;
+        }
     }
 
-    const char *pszPamSRS = GDALPamDataset::GetProjectionRef();
-
-    if( pszPamSRS != NULL && strlen(pszPamSRS) > 0 )
+    if( m_nPAMGeorefSrcIndex >= 0 )
     {
-        CPLFree( pszProjection );
-        pszProjection = CPLStrdup( pszPamSRS );
-        bLookedForProjection = TRUE;
+        if( (m_nTABFILEGeorefSrcIndex < 0 ||
+             m_nPAMGeorefSrcIndex < m_nTABFILEGeorefSrcIndex) &&
+            (m_nINTERNALGeorefSrcIndex < 0 ||
+             m_nPAMGeorefSrcIndex < m_nINTERNALGeorefSrcIndex) )
+        {
+            const char *pszPamSRS = GDALPamDataset::GetProjectionRef();
+            if( pszPamSRS != NULL && strlen(pszPamSRS) > 0 )
+            {
+                CPLFree( pszProjection );
+                pszProjection = CPLStrdup( pszPamSRS );
+                bLookedForProjection = true;
+                // m_nProjectionGeorefSrcIndex = m_nPAMGeorefSrcIndex;
+            }
+        }
+        else
+        {
+            if( m_nINTERNALGeorefSrcIndex >= 0 )
+                LookForProjection();
+            if( pszProjection == NULL || strlen(pszProjection) == 0 )
+            {
+                const char *pszPamSRS = GDALPamDataset::GetProjectionRef();
+                if( pszPamSRS != NULL && strlen(pszPamSRS) > 0 )
+                {
+                    CPLFree( pszProjection );
+                    pszProjection = CPLStrdup( pszPamSRS );
+                    bLookedForProjection = true;
+                    // m_nProjectionGeorefSrcIndex = m_nPAMGeorefSrcIndex;
+                }
+            }
+        }
     }
 
-    int nPamGCPCount = GDALPamDataset::GetGCPCount();
-    if( nPamGCPCount > 0 )
+    int nPamGCPCount;
+    if( m_nPAMGeorefSrcIndex >= 0 &&
+        (nPamGCPCount = GDALPamDataset::GetGCPCount()) > 0 &&
+        ( (nGCPCount > 0 &&
+           m_nPAMGeorefSrcIndex < m_nGeoTransformGeorefSrcIndex) ||
+          m_nGeoTransformGeorefSrcIndex < 0 || nGCPCount == 0 ) )
     {
         if( nGCPCount > 0 )
         {
@@ -10468,12 +11939,87 @@ void GTiffDataset::ApplyPamInfo()
 
         CPLFree( pszProjection );
         pszProjection = NULL;
+        // m_nProjectionGeorefSrcIndex = m_nPAMGeorefSrcIndex;
 
         const char *pszPamGCPProjection = GDALPamDataset::GetGCPProjection();
         if( pszPamGCPProjection != NULL && strlen(pszPamGCPProjection) > 0 )
             pszProjection = CPLStrdup(pszPamGCPProjection);
 
-        bLookedForProjection = TRUE;
+        bLookedForProjection = true;
+    }
+
+    if( m_nPAMGeorefSrcIndex >= 0 && nGCPCount == 0 )
+    {
+        CPLXMLNode *psValueAsXML = NULL;
+        CPLXMLNode *psGeodataXform = NULL;
+        char** papszXML = oMDMD.GetMetadata( "xml:ESRI" );
+        if (CSLCount(papszXML) == 1)
+        {
+            psValueAsXML = CPLParseXMLString( papszXML[0] );
+            if( psValueAsXML )
+                psGeodataXform = CPLGetXMLNode(psValueAsXML, "=GeodataXform");
+        }
+
+        const char* pszTIFFTagResUnit = GetMetadataItem("TIFFTAG_RESOLUTIONUNIT");
+        const char* pszTIFFTagXRes = GetMetadataItem("TIFFTAG_XRESOLUTION");
+        const char* pszTIFFTagYRes = GetMetadataItem("TIFFTAG_YRESOLUTION");
+        if (psGeodataXform && pszTIFFTagResUnit &&pszTIFFTagXRes &&
+            pszTIFFTagYRes && atoi(pszTIFFTagResUnit) == 2 )
+        {
+            CPLXMLNode* psSourceGCPs = CPLGetXMLNode(psGeodataXform,
+                                                        "SourceGCPs");
+            CPLXMLNode* psTargetGCPs = CPLGetXMLNode(psGeodataXform,
+                                                        "TargetGCPs");
+            if( psSourceGCPs && psTargetGCPs )
+            {
+                std::vector<double> adfSourceGCPs, adfTargetGCPs;
+                for( CPLXMLNode* psIter = psSourceGCPs->psChild;
+                                    psIter != NULL;
+                                    psIter = psIter->psNext )
+                {
+                    if( psIter->eType == CXT_Element &&
+                        EQUAL(psIter->pszValue, "Double") )
+                    {
+                        adfSourceGCPs.push_back(
+                            CPLAtof( CPLGetXMLValue(psIter, NULL, "") ) );
+                    }
+                }
+                for( CPLXMLNode* psIter = psTargetGCPs->psChild;
+                                    psIter != NULL;
+                                    psIter = psIter->psNext )
+                {
+                    if( psIter->eType == CXT_Element &&
+                        EQUAL(psIter->pszValue, "Double") )
+                    {
+                        adfTargetGCPs.push_back(
+                            CPLAtof( CPLGetXMLValue(psIter, NULL, "") ) );
+                    }
+                }
+                if( adfSourceGCPs.size() == adfTargetGCPs.size() &&
+                    (adfSourceGCPs.size() % 2) == 0 )
+                {
+                    nGCPCount = static_cast<int>(
+                                            adfSourceGCPs.size() / 2);
+                    pasGCPList = static_cast<GDAL_GCP *>(
+                            CPLCalloc(sizeof(GDAL_GCP), nGCPCount) );
+                    for( int i = 0; i < nGCPCount; ++i )
+                    {
+                        pasGCPList[i].pszId = CPLStrdup("");
+                        pasGCPList[i].pszInfo = CPLStrdup("");
+                        // The origin used is the bottom left corner,
+                        // and raw values are in inches!
+                        pasGCPList[i].dfGCPPixel = adfSourceGCPs[2*i] *
+                                                        CPLAtof(pszTIFFTagXRes);
+                        pasGCPList[i].dfGCPLine = nRasterYSize -
+                                adfSourceGCPs[2*i+1] * CPLAtof(pszTIFFTagYRes);
+                        pasGCPList[i].dfGCPX = adfTargetGCPs[2*i];
+                        pasGCPList[i].dfGCPY = adfTargetGCPs[2*i+1];
+                    }
+                }
+            }
+        }
+        if( psValueAsXML )
+            CPLDestroyXMLNode(psValueAsXML);
     }
 
 /* -------------------------------------------------------------------- */
@@ -10482,7 +12028,9 @@ void GTiffDataset::ApplyPamInfo()
 /* -------------------------------------------------------------------- */
     char **papszPamDomains = oMDMD.GetDomainList();
 
-    for( int iDomain = 0; papszPamDomains && papszPamDomains[iDomain] != NULL; iDomain++ )
+    for( int iDomain = 0;
+         papszPamDomains && papszPamDomains[iDomain] != NULL;
+         ++iDomain )
     {
         const char *pszDomain = papszPamDomains[iDomain];
         char **papszGT_MD = CSLDuplicate(oGTiffMDMD.GetMetadata( pszDomain ));
@@ -10494,15 +12042,19 @@ void GTiffDataset::ApplyPamInfo()
         CSLDestroy( papszGT_MD );
     }
 
-    for( int i = 1; i <= GetRasterCount(); i++)
+    for( int i = 1; i <= GetRasterCount(); ++i )
     {
-        GTiffRasterBand* poBand = (GTiffRasterBand *)GetRasterBand(i);
+        GTiffRasterBand* poBand =
+            reinterpret_cast<GTiffRasterBand *>(GetRasterBand(i));
         papszPamDomains = poBand->oMDMD.GetDomainList();
 
-        for( int iDomain = 0; papszPamDomains && papszPamDomains[iDomain] != NULL; iDomain++ )
+        for( int iDomain = 0;
+             papszPamDomains && papszPamDomains[iDomain] != NULL;
+             ++iDomain )
         {
             const char *pszDomain = papszPamDomains[iDomain];
-            char **papszGT_MD = CSLDuplicate(poBand->oGTiffMDMD.GetMetadata( pszDomain ));
+            char **papszGT_MD =
+                CSLDuplicate(poBand->oGTiffMDMD.GetMetadata( pszDomain ));
             char **papszPAM_MD = poBand->oMDMD.GetMetadata( pszDomain );
 
             papszGT_MD = CSLMerge( papszGT_MD, papszPAM_MD );
@@ -10522,11 +12074,11 @@ void GTiffDataset::ApplyPamInfo()
 GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
 
 {
-    int bAllowRGBAInterface = TRUE;
+    bool bAllowRGBAInterface = true;
     const char* pszFilename = poOpenInfo->pszFilename;
     if( STARTS_WITH_CI(pszFilename, "GTIFF_RAW:") )
     {
-        bAllowRGBAInterface = FALSE;
+        bAllowRGBAInterface = false;
         pszFilename += strlen("GTIFF_RAW:");
     }
 
@@ -10537,45 +12089,43 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
 /*      Split out filename, and dir#/offset.                            */
 /* -------------------------------------------------------------------- */
     pszFilename += strlen("GTIFF_DIR:");
-    int        bAbsolute = FALSE;
-    toff_t     nOffset;
+    bool bAbsolute = false;
 
     if( STARTS_WITH_CI(pszFilename, "off:") )
     {
-        bAbsolute = TRUE;
+        bAbsolute = true;
         pszFilename += 4;
     }
 
-    nOffset = atol(pszFilename);
+    toff_t nOffset = atol(pszFilename);
     pszFilename += 1;
 
     while( *pszFilename != '\0' && pszFilename[-1] != ':' )
-        pszFilename++;
+        ++pszFilename;
 
     if( *pszFilename == '\0' || nOffset == 0 )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unable to extract offset or filename, should take the form\n"
-                  "GTIFF_DIR:<dir>:filename or GTIFF_DIR:off:<dir_offset>:filename" );
+        CPLError(
+            CE_Failure, CPLE_OpenFailed,
+            "Unable to extract offset or filename, should take the form:\n"
+            "GTIFF_DIR:<dir>:filename or GTIFF_DIR:off:<dir_offset>:filename" );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    TIFF *hTIFF;
-
-    if (!GTiffOneTimeInit())
+    if( !GTiffOneTimeInit() )
         return NULL;
 
-    VSILFILE* fpL = VSIFOpenL(pszFilename, "r");
-    if( fpL == NULL )
+    VSILFILE* l_fpL = VSIFOpenL(pszFilename, "r");
+    if( l_fpL == NULL )
         return NULL;
-    hTIFF = VSI_TIFFOpen( pszFilename, "r", fpL );
-    if( hTIFF == NULL )
+    TIFF *l_hTIFF = VSI_TIFFOpen( pszFilename, "r", l_fpL );
+    if( l_hTIFF == NULL )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
-        return( NULL );
+        CPL_IGNORE_RET_VAL(VSIFCloseL(l_fpL));
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -10583,33 +12133,33 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( !bAbsolute )
     {
-        toff_t nOffsetRequested = nOffset;
+        const toff_t nOffsetRequested = nOffset;
         while( nOffset > 1 )
         {
-            if( TIFFReadDirectory( hTIFF ) == 0 )
+            if( TIFFReadDirectory( l_hTIFF ) == 0 )
             {
-                XTIFFClose( hTIFF );
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                          "Requested directory %lu not found.", (long unsigned int)nOffsetRequested );
-                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
+                XTIFFClose( l_hTIFF );
+                CPLError(
+                    CE_Failure, CPLE_OpenFailed,
+                    "Requested directory %lu not found.",
+                    static_cast<long unsigned int>(nOffsetRequested));
+                CPL_IGNORE_RET_VAL(VSIFCloseL(l_fpL));
                 return NULL;
             }
             nOffset--;
         }
 
-        nOffset = TIFFCurrentDirOffset( hTIFF );
+        nOffset = TIFFCurrentDirOffset( l_hTIFF );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GTiffDataset *poDS;
-
-    poDS = new GTiffDataset();
+    GTiffDataset *poDS = new GTiffDataset();
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->osFilename = poOpenInfo->pszFilename;
     poDS->poActiveDS = poDS;
-    poDS->fpL = fpL;
+    poDS->fpL = l_fpL;
 
     if( !EQUAL(pszFilename,poOpenInfo->pszFilename)
         && !STARTS_WITH_CI(poOpenInfo->pszFilename, "GTIFF_RAW:") )
@@ -10619,27 +12169,28 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
         poDS->osFilename = pszFilename;
     }
 
-    if (poOpenInfo->eAccess == GA_Update)
+    if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Opening a specific TIFF directory is not supported in update mode. Switching to read-only" );
+        CPLError(
+            CE_Warning, CPLE_AppDefined,
+            "Opening a specific TIFF directory is not supported in "
+            "update mode. Switching to read-only" );
     }
 
     if( poOpenInfo->AreSiblingFilesLoaded() )
-        poDS->oOvManager.TransferSiblingFiles( poOpenInfo->StealSiblingFiles() );
+        poDS->oOvManager.TransferSiblingFiles(
+            poOpenInfo->StealSiblingFiles() );
 
-    if( poDS->OpenOffset( hTIFF, &(poDS->poActiveDS),
-                          nOffset, FALSE, GA_ReadOnly,
+    if( poDS->OpenOffset( l_hTIFF, &(poDS->poActiveDS),
+                          nOffset, false, GA_ReadOnly,
                           bAllowRGBAInterface, true ) != CE_None )
     {
         delete poDS;
         return NULL;
     }
-    else
-    {
-        poDS->bCloseTIFFHandle = TRUE;
-        return poDS;
-    }
+
+    poDS->bCloseTIFFHandle = true;
+    return poDS;
 }
 
 /************************************************************************/
@@ -10648,16 +12199,19 @@ GDALDataset *GTiffDataset::OpenDir( GDALOpenInfo * poOpenInfo )
 /*      Convert a transfer function table into a string.                */
 /*      Used by LoadICCProfile().                                       */
 /************************************************************************/
-static CPLString ConvertTransferFunctionToString( const uint16 *pTable, uint32 nTableEntries )
+static CPLString ConvertTransferFunctionToString( const uint16 *pTable,
+                                                  uint32 nTableEntries )
 {
     CPLString sValue;
 
-    for(uint32 i = 0; i < nTableEntries; i++)
+    for( uint32 i = 0; i < nTableEntries; ++i )
     {
-        if (i == 0)
+        if( i == 0 )
             sValue = sValue.Printf("%d", (uint32)pTable[i]);
         else
-        sValue = sValue.Printf("%s, %d", (const char*)sValue, (uint32)pTable[i]);
+            sValue = sValue.Printf( "%s, %d",
+                                    (const char*)sValue,
+                                    (uint32)pTable[i]);
     }
 
     return sValue;
@@ -10671,76 +12225,114 @@ static CPLString ConvertTransferFunctionToString( const uint16 *pTable, uint32 n
 
 void GTiffDataset::LoadICCProfile()
 {
-    uint32 nEmbedLen;
-    uint8* pEmbedBuffer;
-    float* pCHR;
-    float* pWP;
-    uint16 *pTFR, *pTFG, *pTFB;
-    uint16 *pTransferRange = NULL;
-    const int TIFFTAG_TRANSFERRANGE = 0x0156;
-
-    if (bICCMetadataLoaded)
+    if( bICCMetadataLoaded )
         return;
-    bICCMetadataLoaded = TRUE;
+    bICCMetadataLoaded = true;
 
-    if (!SetDirectory())
+    if( !SetDirectory() )
         return;
 
-    if (TIFFGetField(hTIFF, TIFFTAG_ICCPROFILE, &nEmbedLen, &pEmbedBuffer))
+    uint32 nEmbedLen = 0;
+    uint8* pEmbedBuffer = NULL;
+
+
+    if( TIFFGetField(hTIFF, TIFFTAG_ICCPROFILE, &nEmbedLen, &pEmbedBuffer) )
     {
-        char *pszBase64Profile = CPLBase64Encode(nEmbedLen, (const GByte*)pEmbedBuffer);
+        char *pszBase64Profile =
+            CPLBase64Encode(nEmbedLen, (const GByte*)pEmbedBuffer);
 
-        oGTiffMDMD.SetMetadataItem( "SOURCE_ICC_PROFILE", pszBase64Profile, "COLOR_PROFILE" );
+        oGTiffMDMD.SetMetadataItem( "SOURCE_ICC_PROFILE", pszBase64Profile,
+                                    "COLOR_PROFILE" );
 
         CPLFree(pszBase64Profile);
 
         return;
     }
 
-    /* Check for colorimetric tiff */
-    if (TIFFGetField(hTIFF, TIFFTAG_PRIMARYCHROMATICITIES, &pCHR))
+    // Check for colorimetric tiff.
+    float* pCHR = NULL;
+    float* pWP = NULL;
+    uint16 *pTFR = NULL;
+    uint16 *pTFG = NULL;
+    uint16 *pTFB = NULL;
+    uint16 *pTransferRange = NULL;
+
+    if( TIFFGetField(hTIFF, TIFFTAG_PRIMARYCHROMATICITIES, &pCHR) )
     {
-        if (TIFFGetField(hTIFF, TIFFTAG_WHITEPOINT, &pWP))
+        if( TIFFGetField(hTIFF, TIFFTAG_WHITEPOINT, &pWP) )
         {
-            if (!TIFFGetFieldDefaulted(hTIFF, TIFFTAG_TRANSFERFUNCTION, &pTFR, &pTFG, &pTFB))
+            if( !TIFFGetFieldDefaulted( hTIFF, TIFFTAG_TRANSFERFUNCTION, &pTFR,
+                                        &pTFG, &pTFB) )
                 return;
 
-            TIFFGetFieldDefaulted(hTIFF, TIFFTAG_TRANSFERRANGE, &pTransferRange);
+            const int TIFFTAG_TRANSFERRANGE = 0x0156;
+            TIFFGetFieldDefaulted( hTIFF, TIFFTAG_TRANSFERRANGE,
+                                   &pTransferRange);
 
             // Set all the colorimetric metadata.
-            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_RED",
-                CPLString().Printf( "%.9f, %.9f, 1.0", (double)pCHR[0], (double)pCHR[1] ) , "COLOR_PROFILE" );
-            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_GREEN",
-                CPLString().Printf( "%.9f, %.9f, 1.0", (double)pCHR[2], (double)pCHR[3] ) , "COLOR_PROFILE" );
-            oGTiffMDMD.SetMetadataItem( "SOURCE_PRIMARIES_BLUE",
-                CPLString().Printf( "%.9f, %.9f, 1.0", (double)pCHR[4], (double)pCHR[5] ) , "COLOR_PROFILE" );
-
-            oGTiffMDMD.SetMetadataItem( "SOURCE_WHITEPOINT",
-                CPLString().Printf( "%.9f, %.9f, 1.0", (double)pWP[0], (double)pWP[1] ) , "COLOR_PROFILE" );
-
-            /* Set transfer function metadata */
-
-            /* Get length of table. */
+            oGTiffMDMD.SetMetadataItem(
+                "SOURCE_PRIMARIES_RED",
+                CPLString().Printf( "%.9f, %.9f, 1.0",
+                                    static_cast<double>(pCHR[0]),
+                                    static_cast<double>(pCHR[1]) ),
+                "COLOR_PROFILE" );
+            oGTiffMDMD.SetMetadataItem(
+                "SOURCE_PRIMARIES_GREEN",
+                CPLString().Printf( "%.9f, %.9f, 1.0",
+                                    static_cast<double>(pCHR[2]),
+                                    static_cast<double>(pCHR[3]) ),
+                "COLOR_PROFILE" );
+            oGTiffMDMD.SetMetadataItem(
+                "SOURCE_PRIMARIES_BLUE",
+                CPLString().Printf( "%.9f, %.9f, 1.0",
+                                    static_cast<double>(pCHR[4]),
+                                    static_cast<double>(pCHR[5]) ),
+                "COLOR_PROFILE" );
+
+            oGTiffMDMD.SetMetadataItem(
+                "SOURCE_WHITEPOINT",
+                CPLString().Printf( "%.9f, %.9f, 1.0",
+                                    static_cast<double>(pWP[0]),
+                                    static_cast<double>(pWP[1]) ),
+                "COLOR_PROFILE" );
+
+            // Set transfer function metadata.
+
+            // Get length of table.
             const uint32 nTransferFunctionLength = 1 << nBitsPerSample;
 
-            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_RED",
-                ConvertTransferFunctionToString( pTFR, nTransferFunctionLength), "COLOR_PROFILE" );
+            oGTiffMDMD.SetMetadataItem(
+                "TIFFTAG_TRANSFERFUNCTION_RED",
+                ConvertTransferFunctionToString( pTFR, nTransferFunctionLength),
+                "COLOR_PROFILE" );
 
-            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_GREEN",
-                ConvertTransferFunctionToString( pTFG, nTransferFunctionLength), "COLOR_PROFILE" );
+            oGTiffMDMD.SetMetadataItem(
+                "TIFFTAG_TRANSFERFUNCTION_GREEN",
+                ConvertTransferFunctionToString( pTFG, nTransferFunctionLength),
+                "COLOR_PROFILE" );
 
-            oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_BLUE",
-                ConvertTransferFunctionToString( pTFB, nTransferFunctionLength), "COLOR_PROFILE" );
+            oGTiffMDMD.SetMetadataItem(
+                "TIFFTAG_TRANSFERFUNCTION_BLUE",
+                ConvertTransferFunctionToString( pTFB, nTransferFunctionLength),
+                "COLOR_PROFILE" );
 
-            /* Set transfer range */
-            if (pTransferRange)
+            // Set transfer range.
+            if( pTransferRange )
             {
-                oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERRANGE_BLACK",
+                oGTiffMDMD.SetMetadataItem(
+                    "TIFFTAG_TRANSFERRANGE_BLACK",
                     CPLString().Printf( "%d, %d, %d",
-                        (int)pTransferRange[0], (int)pTransferRange[2], (int)pTransferRange[4]), "COLOR_PROFILE" );
-                oGTiffMDMD.SetMetadataItem( "TIFFTAG_TRANSFERRANGE_WHITE",
+                                        static_cast<int>(pTransferRange[0]),
+                                        static_cast<int>(pTransferRange[2]),
+                                        static_cast<int>(pTransferRange[4])),
+                    "COLOR_PROFILE" );
+                oGTiffMDMD.SetMetadataItem(
+                    "TIFFTAG_TRANSFERRANGE_WHITE",
                     CPLString().Printf( "%d, %d, %d",
-                        (int)pTransferRange[1], (int)pTransferRange[3], (int)pTransferRange[5]), "COLOR_PROFILE" );
+                                        static_cast<int>(pTransferRange[1]),
+                                        static_cast<int>(pTransferRange[3]),
+                                        static_cast<int>(pTransferRange[5])),
+                    "COLOR_PROFILE" );
             }
         }
     }
@@ -10764,47 +12356,46 @@ void GTiffDataset::LoadICCProfile()
 /*      Bits per sample. Ignored if pDS is not NULL.                    */
 /************************************************************************/
 
-void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszParmList, uint32 nBitsPerSample)
+void GTiffDataset::SaveICCProfile( GTiffDataset *pDS, TIFF *l_hTIFF,
+                                   char **papszParmList,
+                                   uint32 l_nBitsPerSample )
 {
-    if ((pDS != NULL) && (pDS->eAccess != GA_Update))
+    if( (pDS != NULL) && (pDS->eAccess != GA_Update) )
         return;
 
-    if (hTIFF == NULL)
+    if( l_hTIFF == NULL )
     {
-        if (pDS == NULL)
+        if( pDS == NULL )
             return;
 
-        hTIFF = pDS->hTIFF;
-        if (hTIFF == NULL)
+        l_hTIFF = pDS->hTIFF;
+        if( l_hTIFF == NULL )
             return;
     }
 
-    if ((papszParmList == NULL) && (pDS == NULL))
+    if( (papszParmList == NULL) && (pDS == NULL) )
         return;
 
     const char *pszValue = NULL;
-    if (pDS != NULL)
+    if( pDS != NULL )
         pszValue = pDS->GetMetadataItem("SOURCE_ICC_PROFILE", "COLOR_PROFILE");
     else
         pszValue = CSLFetchNameValue(papszParmList, "SOURCE_ICC_PROFILE");
     if( pszValue != NULL )
     {
-        int32 nEmbedLen;
         char *pEmbedBuffer = CPLStrdup(pszValue);
-        nEmbedLen = CPLBase64DecodeInPlace((GByte*)pEmbedBuffer);
+        int32 nEmbedLen =
+            CPLBase64DecodeInPlace(reinterpret_cast<GByte *>(pEmbedBuffer));
 
-        TIFFSetField(hTIFF, TIFFTAG_ICCPROFILE, nEmbedLen, pEmbedBuffer);
+        TIFFSetField(l_hTIFF, TIFFTAG_ICCPROFILE, nEmbedLen, pEmbedBuffer);
 
         CPLFree(pEmbedBuffer);
     }
     else
     {
-        /* Output colorimetric data. */
-        const int TIFFTAG_TRANSFERRANGE = 0x0156;
-
-        float pCHR[6]; // Primaries
-        float pWP[2];  // Whitepoint
-        uint16 pTXR[6]; // Transfer range
+        // Output colorimetric data.
+        float pCHR[6] = {};  // Primaries.
+        uint16 pTXR[6] = {};  // Transfer range.
         const char* pszCHRNames[] = {
             "SOURCE_PRIMARIES_RED",
             "SOURCE_PRIMARIES_GREEN",
@@ -10815,39 +12406,42 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
             "TIFFTAG_TRANSFERRANGE_WHITE"
         };
 
-        /* Output chromacities */
+        // Output chromacities.
         bool bOutputCHR = true;
-        for(int i = 0; ((i < 3) && bOutputCHR); i++)
+        for( int i = 0; i < 3 && bOutputCHR; ++i )
         {
-            if (pDS != NULL)
-                pszValue = pDS->GetMetadataItem(pszCHRNames[i], "COLOR_PROFILE");
+            if( pDS != NULL )
+                pszValue =
+                    pDS->GetMetadataItem(pszCHRNames[i], "COLOR_PROFILE");
             else
                 pszValue = CSLFetchNameValue(papszParmList, pszCHRNames[i]);
-            if (pszValue == NULL)
+            if( pszValue == NULL )
             {
                 bOutputCHR = false;
                 break;
             }
 
-            char** papszTokens = CSLTokenizeString2( pszValue, ",",
-                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+            char** papszTokens =
+                CSLTokenizeString2(
+                    pszValue, ",",
+                    CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES |
+                    CSLT_STRIPENDSPACES );
 
-            if (CSLCount( papszTokens ) != 3)
+            if( CSLCount( papszTokens ) != 3 )
             {
                 bOutputCHR = false;
                 CSLDestroy( papszTokens );
                 break;
             }
 
-            int j;
-            for( j = 0; j < 3; j++ )
+            for( int j = 0; j < 3; ++j )
             {
-                float v = (float)CPLAtof(papszTokens[j]);
+                float v = static_cast<float>(CPLAtof(papszTokens[j]));
 
-                if (j == 2)
+                if( j == 2 )
                 {
-                    /* Last term of xyY color must be 1.0 */
-                    if (v != 1.0)
+                    // Last term of xyY color must be 1.0.
+                    if( v != 1.0 )
                     {
                         bOutputCHR = false;
                         break;
@@ -10862,37 +12456,41 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
             CSLDestroy( papszTokens );
         }
 
-        if (bOutputCHR)
+        if( bOutputCHR )
         {
-            TIFFSetField(hTIFF, TIFFTAG_PRIMARYCHROMATICITIES, pCHR);
+            TIFFSetField(l_hTIFF, TIFFTAG_PRIMARYCHROMATICITIES, pCHR);
         }
 
-        /* Output whitepoint */
-        bool bOutputWhitepoint = true;
-        if (pDS != NULL)
-            pszValue = pDS->GetMetadataItem("SOURCE_WHITEPOINT", "COLOR_PROFILE");
+        // Output whitepoint.
+        if( pDS != NULL )
+            pszValue =
+                pDS->GetMetadataItem("SOURCE_WHITEPOINT", "COLOR_PROFILE");
         else
             pszValue = CSLFetchNameValue(papszParmList, "SOURCE_WHITEPOINT");
-        if (pszValue != NULL)
+        if( pszValue != NULL )
         {
-            char** papszTokens = CSLTokenizeString2( pszValue, ",",
-                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+            char** papszTokens =
+                CSLTokenizeString2(
+                    pszValue, ",",
+                    CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES |
+                    CSLT_STRIPENDSPACES );
 
-            if (CSLCount( papszTokens ) != 3)
+            bool bOutputWhitepoint = true;
+            float pWP[2] = { 0.0f, 0.0f };  // Whitepoint
+            if( CSLCount( papszTokens ) != 3 )
             {
                 bOutputWhitepoint = false;
             }
             else
             {
-                int j;
-                for( j = 0; j < 3; j++ )
+                for( int j = 0; j < 3; ++j )
                 {
-                    float v = (float)CPLAtof(papszTokens[j]);
+                    const float v = static_cast<float>(CPLAtof(papszTokens[j]));
 
-                    if (j == 2)
+                    if( j == 2 )
                     {
-                        /* Last term of xyY color must be 1.0 */
-                        if (v != 1.0)
+                        // Last term of xyY color must be 1.0.
+                        if( v != 1.0 )
                         {
                             bOutputWhitepoint = false;
                             break;
@@ -10906,61 +12504,91 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
             }
             CSLDestroy( papszTokens );
 
-            if (bOutputWhitepoint)
+            if( bOutputWhitepoint )
             {
-                TIFFSetField(hTIFF, TIFFTAG_WHITEPOINT, pWP);
+                TIFFSetField(l_hTIFF, TIFFTAG_WHITEPOINT, pWP);
             }
         }
 
-        /* Set transfer function metadata */
+        // Set transfer function metadata.
         char const *pszTFRed = NULL;
-        char const *pszTFGreen = NULL;
-        char const *pszTFBlue = NULL;
-        if (pDS != NULL)
-            pszTFRed = pDS->GetMetadataItem("TIFFTAG_TRANSFERFUNCTION_RED", "COLOR_PROFILE");
+        if( pDS != NULL )
+            pszTFRed =
+                pDS->GetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_RED",
+                                      "COLOR_PROFILE" );
         else
-            pszTFRed = CSLFetchNameValue(papszParmList, "TIFFTAG_TRANSFERFUNCTION_RED");
+            pszTFRed =
+                CSLFetchNameValue( papszParmList,
+                                   "TIFFTAG_TRANSFERFUNCTION_RED" );
 
-        if (pDS != NULL)
-            pszTFGreen = pDS->GetMetadataItem("TIFFTAG_TRANSFERFUNCTION_GREEN", "COLOR_PROFILE");
+        char const *pszTFGreen = NULL;
+        if( pDS != NULL )
+            pszTFGreen =
+                pDS->GetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_GREEN",
+                                      "COLOR_PROFILE" );
         else
-            pszTFGreen = CSLFetchNameValue(papszParmList, "TIFFTAG_TRANSFERFUNCTION_GREEN");
+            pszTFGreen =
+                CSLFetchNameValue( papszParmList,
+                                   "TIFFTAG_TRANSFERFUNCTION_GREEN" );
 
-        if (pDS != NULL)
-            pszTFBlue = pDS->GetMetadataItem("TIFFTAG_TRANSFERFUNCTION_BLUE", "COLOR_PROFILE");
+        char const *pszTFBlue = NULL;
+        if( pDS != NULL )
+            pszTFBlue =
+                pDS->GetMetadataItem( "TIFFTAG_TRANSFERFUNCTION_BLUE",
+                                      "COLOR_PROFILE" );
         else
-            pszTFBlue = CSLFetchNameValue(papszParmList, "TIFFTAG_TRANSFERFUNCTION_BLUE");
-
-        if ((pszTFRed != NULL) && (pszTFGreen != NULL) && (pszTFBlue != NULL))
-        {
-            /* Get length of table. */
-            const int nTransferFunctionLength = 1 << ((pDS!=NULL)?pDS->nBitsPerSample:nBitsPerSample);
-
-            char** papszTokensRed = CSLTokenizeString2( pszTFRed, ",",
-                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-            char** papszTokensGreen = CSLTokenizeString2( pszTFGreen, ",",
-                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-            char** papszTokensBlue = CSLTokenizeString2( pszTFBlue, ",",
-                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
-
-            if ((CSLCount( papszTokensRed ) == nTransferFunctionLength) &&
+            pszTFBlue =
+                CSLFetchNameValue( papszParmList,
+                                   "TIFFTAG_TRANSFERFUNCTION_BLUE" );
+
+        if( (pszTFRed != NULL) && (pszTFGreen != NULL) && (pszTFBlue != NULL) )
+        {
+            // Get length of table.
+            const int nTransferFunctionLength =
+                1 << ((pDS!=NULL)?pDS->nBitsPerSample:l_nBitsPerSample);
+
+            char** papszTokensRed =
+                CSLTokenizeString2(
+                    pszTFRed, ",",
+                    CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES |
+                    CSLT_STRIPENDSPACES );
+            char** papszTokensGreen =
+                CSLTokenizeString2(
+                    pszTFGreen, ",",
+                    CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES |
+                    CSLT_STRIPENDSPACES );
+            char** papszTokensBlue =
+                CSLTokenizeString2(
+                    pszTFBlue, ",",
+                    CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES |
+                    CSLT_STRIPENDSPACES );
+
+            if( (CSLCount( papszTokensRed ) == nTransferFunctionLength) &&
                 (CSLCount( papszTokensGreen ) == nTransferFunctionLength) &&
-                (CSLCount( papszTokensBlue ) == nTransferFunctionLength))
+                (CSLCount( papszTokensBlue ) == nTransferFunctionLength) )
             {
-                uint16 *pTransferFuncRed, *pTransferFuncGreen, *pTransferFuncBlue;
-                pTransferFuncRed = (uint16*)CPLMalloc(sizeof(uint16) * nTransferFunctionLength);
-                pTransferFuncGreen = (uint16*)CPLMalloc(sizeof(uint16) * nTransferFunctionLength);
-                pTransferFuncBlue = (uint16*)CPLMalloc(sizeof(uint16) * nTransferFunctionLength);
-
-                /* Convert our table in string format into int16 format. */
-                for(int i = 0; i < nTransferFunctionLength; i++)
+                uint16 *pTransferFuncRed =
+                    static_cast<uint16*>( CPLMalloc(
+                        sizeof(uint16) * nTransferFunctionLength ) );
+                uint16 *pTransferFuncGreen =
+                    static_cast<uint16*>( CPLMalloc(
+                        sizeof(uint16) * nTransferFunctionLength ) );
+                uint16 *pTransferFuncBlue =
+                    static_cast<uint16*>( CPLMalloc(
+                        sizeof(uint16) * nTransferFunctionLength ) );
+
+                // Convert our table in string format into int16 format.
+                for( int i = 0; i < nTransferFunctionLength; ++i )
                 {
-                    pTransferFuncRed[i] = (uint16)atoi(papszTokensRed[i]);
-                    pTransferFuncGreen[i] = (uint16)atoi(papszTokensGreen[i]);
-                    pTransferFuncBlue[i] = (uint16)atoi(papszTokensBlue[i]);
+                    pTransferFuncRed[i] =
+                        static_cast<uint16>(atoi(papszTokensRed[i]));
+                    pTransferFuncGreen[i] =
+                        static_cast<uint16>(atoi(papszTokensGreen[i]));
+                    pTransferFuncBlue[i] =
+                        static_cast<uint16>(atoi(papszTokensBlue[i]));
                 }
 
-                TIFFSetField(hTIFF, TIFFTAG_TRANSFERFUNCTION,
+                TIFFSetField(l_hTIFF, TIFFTAG_TRANSFERFUNCTION,
                     pTransferFuncRed, pTransferFuncGreen, pTransferFuncBlue);
 
                 CPLFree(pTransferFuncRed);
@@ -10973,42 +12601,46 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
             CSLDestroy( papszTokensBlue );
         }
 
-        /* Output transfer range */
+        // Output transfer range.
         bool bOutputTransferRange = true;
-        for(int i = 0; ((i < 2) && bOutputTransferRange); i++)
+        for( int i = 0; (i < 2) && bOutputTransferRange; ++i )
         {
-            if (pDS != NULL)
-                pszValue = pDS->GetMetadataItem(pszTXRNames[i], "COLOR_PROFILE");
+            if( pDS != NULL )
+                pszValue = pDS->GetMetadataItem( pszTXRNames[i],
+                                                 "COLOR_PROFILE" );
             else
                 pszValue = CSLFetchNameValue(papszParmList, pszTXRNames[i]);
-            if (pszValue == NULL)
+            if( pszValue == NULL )
             {
                 bOutputTransferRange = false;
                 break;
             }
 
-            char** papszTokens = CSLTokenizeString2( pszValue, ",",
-                CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+            char** papszTokens =
+                CSLTokenizeString2(
+                    pszValue, ",",
+                    CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES |
+                    CSLT_STRIPENDSPACES );
 
-            if (CSLCount( papszTokens ) != 3)
+            if( CSLCount( papszTokens ) != 3 )
             {
                 bOutputTransferRange = false;
                 CSLDestroy( papszTokens );
                 break;
             }
 
-            int j;
-            for( j = 0; j < 3; j++ )
+            for( int j = 0; j < 3; ++j )
             {
-                pTXR[i + j * 2] = (uint16)atoi(papszTokens[j]);
+                pTXR[i + j * 2] = static_cast<uint16>(atoi(papszTokens[j]));
             }
 
             CSLDestroy( papszTokens );
         }
 
-        if (bOutputTransferRange)
+        if( bOutputTransferRange )
         {
-            TIFFSetField(hTIFF, TIFFTAG_TRANSFERRANGE, pTXR);
+            const int TIFFTAG_TRANSFERRANGE = 0x0156;
+            TIFFSetField(l_hTIFF, TIFFTAG_TRANSFERRANGE, pTXR);
         }
     }
 }
@@ -11024,14 +12656,11 @@ void GTiffDataset::SaveICCProfile(GTiffDataset *pDS, TIFF *hTIFF, char **papszPa
 CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
                                  GTiffDataset **ppoActiveDSRefIn,
                                  toff_t nDirOffsetIn,
-                                 int bBaseIn, GDALAccess eAccessIn,
-                                 int bAllowRGBAInterface,
+                                 bool bBaseIn, GDALAccess eAccessIn,
+                                 bool bAllowRGBAInterface,
                                  bool bReadGeoTransform )
 
 {
-    bool bTreatAsBitmap = false;
-    bool bTreatAsOdd = false;
-
     eAccess = eAccessIn;
 
     hTIFF = hTIFFIn;
@@ -11039,7 +12668,7 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 
     nDirOffset = nDirOffsetIn;
 
-    if (!SetDirectory( nDirOffsetIn ))
+    if( !SetDirectory( nDirOffsetIn ) )
         return CE_Failure;
 
     bBase = bBaseIn;
@@ -11047,9 +12676,18 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
-    uint32 nXSize, nYSize;
+    uint32 nXSize = 0;
+    uint32 nYSize = 0;
     TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
     TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
+    if( nXSize > INT_MAX || nYSize > INT_MAX )
+    {
+        // GDAL only supports signed 32bit dimensions.
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Too large image size: %u x %u",
+                 nXSize, nYSize);
+        return CE_Failure;
+    }
     nRasterXSize = nXSize;
     nRasterYSize = nYSize;
 
@@ -11073,9 +12711,9 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
         nCompression = COMPRESSION_NONE;
 
-#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 /* 3.6.0 */
-    if (nCompression != COMPRESSION_NONE &&
-        !TIFFIsCODECConfigured(nCompression))
+#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 // 3.6.0
+    if( nCompression != COMPRESSION_NONE &&
+        !TIFFIsCODECConfigured(nCompression) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Cannot open TIFF file due to missing codec." );
@@ -11090,14 +12728,13 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
     if( nCompression == COMPRESSION_JPEG
         && nPhotometric == PHOTOMETRIC_YCBCR
-        && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
-                                              "YES") ) )
+        && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB", "YES") ) )
     {
-        int nColorMode;
-
-        oGTiffMDMD.SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
-        if ( !TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode ) ||
-              nColorMode != JPEGCOLORMODE_RGB )
+        oGTiffMDMD.SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr",
+                                    "IMAGE_STRUCTURE" );
+        int nColorMode = 0;
+        if( !TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode ) ||
+            nColorMode != JPEGCOLORMODE_RGB )
             TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
     }
 
@@ -11106,8 +12743,19 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
     if( TIFFIsTiled(hTIFF) )
     {
-        TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(nBlockXSize) );
-        TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(nBlockYSize) );
+        uint32 l_nBlockXSize = 0;
+        uint32 l_nBlockYSize = 0;
+        TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(l_nBlockXSize) );
+        TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(l_nBlockYSize) );
+        if( l_nBlockXSize > INT_MAX || l_nBlockYSize > INT_MAX )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Too large block size: %u x %u",
+                     l_nBlockXSize, l_nBlockYSize);
+            return CE_Failure;
+        }
+        nBlockXSize = static_cast<int>(l_nBlockXSize);
+        nBlockYSize = static_cast<int>(l_nBlockYSize);
     }
     else
     {
@@ -11116,13 +12764,13 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "RowsPerStrip not defined ... assuming all one strip." );
-            nRowsPerStrip = nYSize; /* dummy value */
+            nRowsPerStrip = nYSize;  // Dummy value.
         }
 
         // If the rows per strip is larger than the file we will get
         // confused.  libtiff internally will treat the rowsperstrip as
         // the image height and it is best if we do too. (#4468)
-        if (nRowsPerStrip > (uint32)nRasterYSize)
+        if( nRowsPerStrip > static_cast<uint32>(nRasterYSize) )
             nRowsPerStrip = nRasterYSize;
 
         nBlockXSize = nRasterXSize;
@@ -11130,23 +12778,27 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     }
 
     nBlocksPerBand =
-        DIV_ROUND_UP(nYSize, nBlockYSize) * DIV_ROUND_UP(nXSize, nBlockXSize);
+        DIV_ROUND_UP(nRasterYSize, nBlockYSize) *
+        DIV_ROUND_UP(nRasterXSize, nBlockXSize);
 
 /* -------------------------------------------------------------------- */
 /*      Should we handle this using the GTiffBitmapBand?                */
 /* -------------------------------------------------------------------- */
+    bool bTreatAsBitmap = false;
+
     if( nBitsPerSample == 1 && nBands == 1 )
     {
         bTreatAsBitmap = true;
 
         // Lets treat large "one row" bitmaps using the scanline api.
         if( !TIFFIsTiled(hTIFF)
-            && nBlockYSize == nYSize
-            && nYSize > 2000
-            /* libtiff does not support reading JBIG files with TIFFReadScanline() */
+            && nBlockYSize == nRasterYSize
+            && nRasterYSize > 2000
+            // libtiff does not support reading JBIG files with
+            // TIFFReadScanline().
             && nCompression != COMPRESSION_JBIG )
         {
-            bTreatAsSplitBitmap = TRUE;
+            bTreatAsSplitBitmap = true;
         }
     }
 
@@ -11166,12 +12818,13 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
             ( nPhotometric == PHOTOMETRIC_YCBCR
               && nCompression != COMPRESSION_JPEG ))) )
     {
-        char szMessage[1024];
+        char szMessage[1024] = {};
 
         if( TIFFRGBAImageOK( hTIFF, szMessage ) == 1 )
         {
             const char* pszSourceColorSpace = NULL;
-            switch (nPhotometric)
+            nBands = 4;
+            switch( nPhotometric )
             {
                 case PHOTOMETRIC_CIELAB:
                     pszSourceColorSpace = "CIELAB";
@@ -11187,12 +12840,15 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
                     break;
                 case PHOTOMETRIC_YCBCR:
                     pszSourceColorSpace = "YCbCr";
+                    nBands = 3; // probably true for other photometric values
                     break;
             }
-            if (pszSourceColorSpace)
-                oGTiffMDMD.SetMetadataItem( "SOURCE_COLOR_SPACE", pszSourceColorSpace, "IMAGE_STRUCTURE" );
-            bTreatAsRGBA = TRUE;
-            nBands = 4;
+            if( pszSourceColorSpace )
+                oGTiffMDMD.SetMetadataItem( "SOURCE_COLOR_SPACE",
+                                            pszSourceColorSpace,
+                                            "IMAGE_STRUCTURE" );
+            bTreatAsRGBA = true;
+
         }
         else
         {
@@ -11200,9 +12856,9 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         }
     }
 
-    // libtiff has various issues with OJPEG compression and chunky-strip support
-    // with the "classic" scanline/strip/tile interfaces, and that wouldn't
-    // work either, so better bail out
+    // libtiff has various issues with OJPEG compression and chunky-strip
+    // support with the "classic" scanline/strip/tile interfaces, and that
+    // wouldn't work either, so better bail out.
     if( nCompression == COMPRESSION_OJPEG &&
         !bTreatAsRGBA )
     {
@@ -11217,90 +12873,98 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
     if( !TIFFIsTiled(hTIFF)
         && nBitsPerSample == 8
-        && nBlockYSize == nYSize
-        && nYSize > 2000
+        && nBlockYSize == nRasterYSize
+        && nRasterYSize > 2000
         && !bTreatAsRGBA
-        && CPLTestBool(CPLGetConfigOption("GDAL_ENABLE_TIFF_SPLIT", "YES")))
+        && CPLTestBool(CPLGetConfigOption("GDAL_ENABLE_TIFF_SPLIT", "YES")) )
     {
-        /* libtiff 3.9.2 (20091104) and older, libtiff 4.0.0beta5 (also 20091104) */
-        /* and older will crash when trying to open a all-in-one-strip */
-        /* YCbCr JPEG compressed TIFF (see #3259). */
+        // libtiff 3.9.2 (20091104) and older, libtiff 4.0.0beta5 (also
+        // 20091104) and older will crash when trying to open a
+        // all-in-one-strip YCbCr JPEG compressed TIFF (see #3259).
 #if (TIFFLIB_VERSION <= 20091104 && !defined(BIGTIFF_SUPPORT)) || \
     (TIFFLIB_VERSION <= 20091104 && defined(BIGTIFF_SUPPORT))
-        if (nPhotometric == PHOTOMETRIC_YCBCR  &&
-            nCompression == COMPRESSION_JPEG)
+        if( nPhotometric == PHOTOMETRIC_YCBCR &&
+            nCompression == COMPRESSION_JPEG )
         {
-            CPLDebug("GTiff", "Avoid using split band to open all-in-one-strip "
-                              "YCbCr JPEG compressed TIFF because of older libtiff");
+            CPLDebug(
+                "GTiff",
+                "Avoid using split band to open all-in-one-strip "
+                "YCbCr JPEG compressed TIFF because of older libtiff" );
         }
         else
 #endif
-            bTreatAsSplit = TRUE;
+        {
+            bTreatAsSplit = true;
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Should we treat this via the odd bits interface?                */
 /* -------------------------------------------------------------------- */
-    if ( nSampleFormat == SAMPLEFORMAT_IEEEFP )
+    bool bTreatAsOdd = false;
+    if( nSampleFormat == SAMPLEFORMAT_IEEEFP )
     {
-        if ( nBitsPerSample == 16 || nBitsPerSample == 24 )
+        if( nBitsPerSample == 16 || nBitsPerSample == 24 )
             bTreatAsOdd = true;
     }
-    else if ( !bTreatAsRGBA && !bTreatAsBitmap
-              && nBitsPerSample != 8
-              && nBitsPerSample != 16
-              && nBitsPerSample != 32
-              && nBitsPerSample != 64
-              && nBitsPerSample != 128 )
+    else if( !bTreatAsRGBA && !bTreatAsBitmap
+             && nBitsPerSample != 8
+             && nBitsPerSample != 16
+             && nBitsPerSample != 32
+             && nBitsPerSample != 64
+             && nBitsPerSample != 128 )
+    {
         bTreatAsOdd = true;
-
+    }
 
 /* -------------------------------------------------------------------- */
 /*      We don't support 'chunks' bigger than 2GB although libtiff v4   */
 /*      can.                                                            */
 /* -------------------------------------------------------------------- */
 #if defined(BIGTIFF_SUPPORT)
-    tmsize_t nChunkSize;
+    uint64 nChunkSize = 0;
     if( bTreatAsRGBA )
     {
-        nChunkSize = 4 * static_cast<tmsize_t>(nBlockXSize) * nBlockYSize;
+        nChunkSize = 4 * static_cast<uint64>(nBlockXSize) * nBlockYSize;
     }
     else if( bTreatAsSplit || bTreatAsSplitBitmap )
     {
-        nChunkSize = TIFFScanlineSize( hTIFF );
+        nChunkSize = TIFFScanlineSize64( hTIFF );
     }
     else
     {
         if( TIFFIsTiled(hTIFF) )
-            nChunkSize = TIFFTileSize( hTIFF );
+            nChunkSize = TIFFTileSize64( hTIFF );
         else
-            nChunkSize = TIFFStripSize( hTIFF );
+            nChunkSize = TIFFStripSize64( hTIFF );
     }
-    if( nChunkSize > INT_MAX )
+    if( nChunkSize > static_cast<uint64>(INT_MAX) )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                "Scanline/tile/strip size bigger than 2GB." );
+                  "Scanline/tile/strip size bigger than 2GB." );
         return CE_Failure;
     }
 #endif
 
-    bool bMinIsWhite = nPhotometric == PHOTOMETRIC_MINISWHITE;
+    const bool bMinIsWhite = nPhotometric == PHOTOMETRIC_MINISWHITE;
 
 /* -------------------------------------------------------------------- */
 /*      Check for NODATA                                                */
 /* -------------------------------------------------------------------- */
-    char    *pszText;
+    char *pszText = NULL;
     if( TIFFGetField( hTIFF, TIFFTAG_GDAL_NODATA, &pszText ) &&
         !EQUAL(pszText, "") )
     {
-        bNoDataSet = TRUE;
+        bNoDataSet = true;
         dfNoDataValue = CPLAtofM( pszText );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Capture the color table if there is one.                        */
 /* -------------------------------------------------------------------- */
-    unsigned short *panRed, *panGreen, *panBlue;
+    unsigned short *panRed = NULL;
+    unsigned short *panGreen = NULL;
+    unsigned short *panBlue = NULL;
 
     if( bTreatAsRGBA || nBitsPerSample > 16
         || TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
@@ -11308,31 +12972,32 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     {
         // Build inverted palette if we have inverted photometric.
         // Pixel values remains unchanged.  Avoid doing this for *deep*
-            // data types (per #1882)
+        // data types (per #1882)
         if( nBitsPerSample <= 16 && nPhotometric == PHOTOMETRIC_MINISWHITE )
         {
-            GDALColorEntry  oEntry;
-
             poColorTable = new GDALColorTable();
             const int nColorCount = 1 << nBitsPerSample;
 
-            for ( int iColor = 0; iColor < nColorCount; iColor++ )
+            for( int iColor = 0; iColor < nColorCount; ++iColor )
             {
-            oEntry.c1 = oEntry.c2 = oEntry.c3 = (short)
-                        ((255 * (nColorCount - 1 - iColor)) / (nColorCount-1));
-            oEntry.c4 = 255;
-            poColorTable->SetColorEntry( iColor, &oEntry );
+                const short nValue =
+                    static_cast<short>(((255 * (nColorCount - 1 - iColor)) /
+                                        (nColorCount - 1)));
+                const GDALColorEntry oEntry =
+                    { nValue, nValue, nValue, static_cast<short>(255) };
+                poColorTable->SetColorEntry( iColor, &oEntry );
             }
 
             nPhotometric = PHOTOMETRIC_PALETTE;
         }
         else
+        {
             poColorTable = NULL;
+        }
     }
     else
     {
-        int nMaxColor = 0;
-        GDALColorEntry oEntry;
+        unsigned short nMaxColor = 0;
 
         poColorTable = new GDALColorTable();
 
@@ -11340,16 +13005,23 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 
         for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
         {
-            oEntry.c1 = panRed[iColor] / 256;
-            oEntry.c2 = panGreen[iColor] / 256;
-            oEntry.c3 = panBlue[iColor] / 256;
-            oEntry.c4 = (bNoDataSet && (int)dfNoDataValue == iColor) ? 0 : 255;
+            // TODO(schwehr): Ensure the color entries are never negative?
+            const unsigned short divisor = 256;
+            const GDALColorEntry oEntry = {
+                static_cast<short>(panRed[iColor] / divisor),
+                static_cast<short>(panGreen[iColor] / divisor),
+                static_cast<short>(panBlue[iColor] / divisor),
+                static_cast<short>(
+                    bNoDataSet && static_cast<int>(dfNoDataValue) == iColor
+                    ? 0
+                    : 255)
+            };
 
             poColorTable->SetColorEntry( iColor, &oEntry );
 
-            nMaxColor = MAX(nMaxColor,panRed[iColor]);
-            nMaxColor = MAX(nMaxColor,panGreen[iColor]);
-            nMaxColor = MAX(nMaxColor,panBlue[iColor]);
+            nMaxColor = std::max(nMaxColor, panRed[iColor]);
+            nMaxColor = std::max(nMaxColor, panGreen[iColor]);
+            nMaxColor = std::max(nMaxColor, panBlue[iColor]);
         }
 
         // Bug 1384 - Some TIFF files are generated with color map entry
@@ -11357,14 +13029,22 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         // gracefully.
         if( nMaxColor > 0 && nMaxColor < 256 )
         {
-            CPLDebug( "GTiff", "TIFF ColorTable seems to be improperly scaled, fixing up." );
+            CPLDebug(
+                "GTiff",
+                "TIFF ColorTable seems to be improperly scaled, fixing up." );
 
             for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
             {
-                oEntry.c1 = panRed[iColor];
-                oEntry.c2 = panGreen[iColor];
-                oEntry.c3 = panBlue[iColor];
-                oEntry.c4 = (bNoDataSet && (int)dfNoDataValue == iColor) ? 0 : 255;
+                // TODO(schwehr): Ensure the color entries are never negative?
+                const GDALColorEntry oEntry = {
+                    static_cast<short>(panRed[iColor]),
+                    static_cast<short>(panGreen[iColor]),
+                    static_cast<short>(panBlue[iColor]),
+                    bNoDataSet &&
+                    static_cast<int>(dfNoDataValue) == iColor
+                    ? static_cast<short>(0)
+                    : static_cast<short>(255)
+                };
 
                 poColorTable->SetColorEntry( iColor, &oEntry );
             }
@@ -11374,20 +13054,20 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( int iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < nBands; ++iBand )
     {
         if( bTreatAsRGBA )
-            SetBand( iBand+1, new GTiffRGBABand( this, iBand+1 ) );
+            SetBand( iBand + 1, new GTiffRGBABand( this, iBand + 1 ) );
         else if( bTreatAsSplitBitmap )
-            SetBand( iBand+1, new GTiffSplitBitmapBand( this, iBand+1 ) );
+            SetBand( iBand + 1, new GTiffSplitBitmapBand( this, iBand + 1 ) );
         else if( bTreatAsSplit )
-            SetBand( iBand+1, new GTiffSplitBand( this, iBand+1 ) );
+            SetBand( iBand + 1, new GTiffSplitBand( this, iBand + 1 ) );
         else if( bTreatAsBitmap )
-            SetBand( iBand+1, new GTiffBitmapBand( this, iBand+1 ) );
+            SetBand( iBand + 1, new GTiffBitmapBand( this, iBand + 1 ) );
         else if( bTreatAsOdd )
-            SetBand( iBand+1, new GTiffOddBitsBand( this, iBand+1 ) );
+            SetBand( iBand + 1, new GTiffOddBitsBand( this, iBand + 1 ) );
         else
-            SetBand( iBand+1, new GTiffRasterBand( this, iBand+1 ) );
+            SetBand( iBand + 1, new GTiffRasterBand( this, iBand + 1 ) );
     }
 
     if( GetRasterBand(1)->GetRasterDataType() == GDT_Unknown )
@@ -11402,24 +13082,27 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 /* -------------------------------------------------------------------- */
 /*      Capture some other potentially interesting information.         */
 /* -------------------------------------------------------------------- */
-    char szWorkMDI[200];
-    uint16  nShort;
+    char szWorkMDI[200] = {};
+    uint16 nShort = 0;
 
-    size_t iTag;
-    for(iTag=0;iTag<sizeof(asTIFFTags)/sizeof(asTIFFTags[0]);iTag++)
+    for( size_t iTag = 0;
+         iTag < sizeof(asTIFFTags) / sizeof(asTIFFTags[0]);
+         ++iTag )
     {
         if( asTIFFTags[iTag].eType == GTIFFTAGTYPE_STRING )
         {
             if( TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &pszText ) )
-                oGTiffMDMD.SetMetadataItem( asTIFFTags[iTag].pszTagName,  pszText );
+                oGTiffMDMD.SetMetadataItem( asTIFFTags[iTag].pszTagName,
+                                            pszText );
         }
         else if( asTIFFTags[iTag].eType == GTIFFTAGTYPE_FLOAT )
         {
-            float   fVal;
+            float fVal = 0.0;
             if( TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &fVal ) )
             {
                 CPLsnprintf( szWorkMDI, sizeof(szWorkMDI), "%.8g", fVal );
-                oGTiffMDMD.SetMetadataItem( asTIFFTags[iTag].pszTagName, szWorkMDI );
+                oGTiffMDMD.SetMetadataItem( asTIFFTags[iTag].pszTagName,
+                                            szWorkMDI );
             }
         }
         else if( asTIFFTags[iTag].eType == GTIFFTAGTYPE_SHORT &&
@@ -11428,7 +13111,8 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
             if( TIFFGetField( hTIFF, asTIFFTags[iTag].nTagVal, &nShort ) )
             {
                 snprintf( szWorkMDI, sizeof(szWorkMDI), "%d", nShort );
-                oGTiffMDMD.SetMetadataItem( asTIFFTags[iTag].pszTagName, szWorkMDI );
+                oGTiffMDMD.SetMetadataItem( asTIFFTags[iTag].pszTagName,
+                                            szWorkMDI );
             }
         }
     }
@@ -11438,7 +13122,8 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         if( nShort == RESUNIT_NONE )
             snprintf( szWorkMDI, sizeof(szWorkMDI), "%d (unitless)", nShort );
         else if( nShort == RESUNIT_INCH )
-            snprintf( szWorkMDI, sizeof(szWorkMDI), "%d (pixels/inch)", nShort );
+            snprintf( szWorkMDI, sizeof(szWorkMDI),
+                      "%d (pixels/inch)", nShort );
         else if( nShort == RESUNIT_CENTIMETER )
             snprintf( szWorkMDI, sizeof(szWorkMDI), "%d (pixels/cm)", nShort );
         else
@@ -11446,19 +13131,18 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
         oGTiffMDMD.SetMetadataItem( "TIFFTAG_RESOLUTIONUNIT", szWorkMDI );
     }
 
-    int nTagSize;
-    void* pData;
+    int nTagSize = 0;
+    void* pData = NULL;
     if( TIFFGetField( hTIFF, TIFFTAG_XMLPACKET, &nTagSize, &pData ) )
     {
-        char* pszXMP = (char*)VSI_MALLOC_VERBOSE(nTagSize + 1);
-        if (pszXMP)
+        char* pszXMP =
+            static_cast<char *>( VSI_MALLOC_VERBOSE(nTagSize + 1) );
+        if( pszXMP )
         {
             memcpy(pszXMP, pData, nTagSize);
             pszXMP[nTagSize] = '\0';
 
-            char *apszMDList[2];
-            apszMDList[0] = pszXMP;
-            apszMDList[1] = NULL;
+            char *apszMDList[2] = { pszXMP, NULL };
             oGTiffMDMD.SetMetadata(apszMDList, "xml:XMP");
 
             CPLFree(pszXMP);
@@ -11468,56 +13152,108 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     if( nCompression == COMPRESSION_NONE )
         /* no compression tag */;
     else if( nCompression == COMPRESSION_CCITTRLE )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTRLE", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTRLE",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_CCITTFAX3 )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTFAX3", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTFAX3",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_CCITTFAX4 )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTFAX4", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTFAX4",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_LZW )
+    {
         oGTiffMDMD.SetMetadataItem( "COMPRESSION", "LZW", "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_OJPEG )
+    {
         oGTiffMDMD.SetMetadataItem( "COMPRESSION", "OJPEG", "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_JPEG )
     {
-        if ( nPhotometric == PHOTOMETRIC_YCBCR )
-            oGTiffMDMD.SetMetadataItem( "COMPRESSION", "YCbCr JPEG", "IMAGE_STRUCTURE" );
+        if( nPhotometric == PHOTOMETRIC_YCBCR )
+            oGTiffMDMD.SetMetadataItem( "COMPRESSION", "YCbCr JPEG",
+                                        "IMAGE_STRUCTURE" );
         else
-            oGTiffMDMD.SetMetadataItem( "COMPRESSION", "JPEG", "IMAGE_STRUCTURE" );
+            oGTiffMDMD.SetMetadataItem( "COMPRESSION", "JPEG",
+                                        "IMAGE_STRUCTURE" );
     }
     else if( nCompression == COMPRESSION_NEXT )
+    {
         oGTiffMDMD.SetMetadataItem( "COMPRESSION", "NEXT", "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_CCITTRLEW )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTRLEW", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "CCITTRLEW",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_PACKBITS )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "PACKBITS", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "PACKBITS",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_THUNDERSCAN )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "THUNDERSCAN", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "THUNDERSCAN",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_PIXARFILM )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "PIXARFILM", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "PIXARFILM",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_PIXARLOG )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "PIXARLOG", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "PIXARLOG",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_DEFLATE )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "DEFLATE",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_ADOBE_DEFLATE )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "DEFLATE",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_DCS )
+    {
         oGTiffMDMD.SetMetadataItem( "COMPRESSION", "DCS", "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_JBIG )
+    {
         oGTiffMDMD.SetMetadataItem( "COMPRESSION", "JBIG", "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_SGILOG )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "SGILOG", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "SGILOG",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_SGILOG24 )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "SGILOG24", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "SGILOG24",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_JP2000 )
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "JP2000", "IMAGE_STRUCTURE" );
+    {
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", "JP2000",
+                                    "IMAGE_STRUCTURE" );
+    }
     else if( nCompression == COMPRESSION_LZMA )
+    {
         oGTiffMDMD.SetMetadataItem( "COMPRESSION", "LZMA", "IMAGE_STRUCTURE" );
-
+    }
     else
     {
         CPLString oComp;
-        oGTiffMDMD.SetMetadataItem( "COMPRESSION",
-                         (const char *) oComp.Printf( "%d", nCompression));
+        oComp.Printf( "%d", nCompression);
+        oGTiffMDMD.SetMetadataItem( "COMPRESSION", oComp.c_str());
     }
 
     if( nPlanarConfig == PLANARCONFIG_CONTIG && nBands != 1 )
@@ -11525,14 +13261,21 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     else
         oGTiffMDMD.SetMetadataItem( "INTERLEAVE", "BAND", "IMAGE_STRUCTURE" );
 
-    if(  (GetRasterBand(1)->GetRasterDataType() == GDT_Byte   && nBitsPerSample != 8 ) ||
-         (GetRasterBand(1)->GetRasterDataType() == GDT_UInt16 && nBitsPerSample != 16) ||
-         (GetRasterBand(1)->GetRasterDataType() == GDT_UInt32 && nBitsPerSample != 32) )
+    if( (GetRasterBand(1)->GetRasterDataType() == GDT_Byte &&
+         nBitsPerSample != 8 ) ||
+        (GetRasterBand(1)->GetRasterDataType() == GDT_UInt16 &&
+         nBitsPerSample != 16) ||
+        ((GetRasterBand(1)->GetRasterDataType() == GDT_UInt32 ||
+          GetRasterBand(1)->GetRasterDataType() == GDT_Float32) &&
+         nBitsPerSample != 32) )
     {
-        for (int i = 0; i < nBands; ++i)
-            static_cast<GTiffRasterBand*>(GetRasterBand(i+1))->oGTiffMDMD.SetMetadataItem( "NBITS",
-                                                 CPLString().Printf( "%d", (int)nBitsPerSample ),
-                                                 "IMAGE_STRUCTURE" );
+        for( int i = 0; i < nBands; ++i )
+            static_cast<GTiffRasterBand*>(GetRasterBand(i + 1))->
+                oGTiffMDMD.SetMetadataItem(
+                    "NBITS",
+                    CPLString().Printf(
+                        "%d", static_cast<int>(nBitsPerSample) ),
+                    "IMAGE_STRUCTURE" );
     }
 
     if( bMinIsWhite )
@@ -11556,7 +13299,8 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 
             const char *pszKey = CPLGetXMLValue( psItem, "name", NULL );
             const char *pszValue = CPLGetXMLValue( psItem, NULL, NULL );
-            const int nBand = atoi(CPLGetXMLValue( psItem, "sample", "-1" )) + 1;
+            const int nBand =
+                atoi(CPLGetXMLValue( psItem, "sample", "-1" )) + 1;
             const char *pszRole = CPLGetXMLValue( psItem, "role", "" );
             const char *pszDomain = CPLGetXMLValue( psItem, "domain", "" );
 
@@ -11568,8 +13312,8 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
             if( STARTS_WITH_CI(pszDomain, "xml:") )
                 bIsXML = TRUE;
 
-            char *pszUnescapedValue
-                = CPLUnescapeString( pszValue, NULL, CPLES_XML );
+            char *pszUnescapedValue =
+                CPLUnescapeString( pszValue, NULL, CPLES_XML );
             if( nBand == 0 )
             {
                 if( bIsXML )
@@ -11578,27 +13322,40 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
                     oGTiffMDMD.SetMetadata( apszMD, pszDomain );
                 }
                 else
-                    oGTiffMDMD.SetMetadataItem( pszKey, pszUnescapedValue, pszDomain );
+                {
+                    oGTiffMDMD.SetMetadataItem( pszKey, pszUnescapedValue,
+                                                pszDomain );
+                }
             }
             else
             {
-                GTiffRasterBand *poBand = static_cast<GTiffRasterBand*>(GetRasterBand(nBand));
+                GTiffRasterBand *poBand =
+                    static_cast<GTiffRasterBand*>(GetRasterBand(nBand));
                 if( poBand != NULL )
                 {
                     if( EQUAL(pszRole,"scale") )
                     {
-                        poBand->bHaveOffsetScale = TRUE;
+                        poBand->bHaveOffsetScale = true;
                         poBand->dfScale = CPLAtofM(pszUnescapedValue);
                     }
                     else if( EQUAL(pszRole,"offset") )
                     {
-                        poBand->bHaveOffsetScale = TRUE;
+                        poBand->bHaveOffsetScale = true;
                         poBand->dfOffset = CPLAtofM(pszUnescapedValue);
                     }
                     else if( EQUAL(pszRole,"unittype") )
+                    {
                         poBand->osUnitType = pszUnescapedValue;
+                    }
                     else if( EQUAL(pszRole,"description") )
+                    {
                         poBand->osDescription = pszUnescapedValue;
+                    }
+                    else if( EQUAL(pszRole, "colorinterp") )
+                    {
+                        poBand->eBandInterp =
+                            GDALGetColorInterpretationByName(pszUnescapedValue);
+                    }
                     else
                     {
                         if( bIsXML )
@@ -11607,8 +13364,12 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
                             poBand->oGTiffMDMD.SetMetadata( apszMD, pszDomain );
                         }
                         else
-                            poBand->oGTiffMDMD.SetMetadataItem(pszKey,pszUnescapedValue,
-                                                    pszDomain );
+                        {
+                            poBand->oGTiffMDMD.SetMetadataItem(
+                                pszKey,
+                                pszUnescapedValue,
+                                pszDomain );
+                        }
                     }
                 }
             }
@@ -11621,29 +13382,42 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
     if( bStreamingIn )
     {
         toff_t* panOffsets = NULL;
-        TIFFGetField( hTIFF, (TIFFIsTiled( hTIFF )) ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS , &panOffsets );
+        TIFFGetField( hTIFF,
+                      TIFFIsTiled( hTIFF ) ?
+                      TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS,
+                      &panOffsets );
         if( panOffsets )
         {
-            int nBlockCount = ( TIFFIsTiled(hTIFF) ) ? TIFFNumberOfTiles(hTIFF) : TIFFNumberOfStrips(hTIFF);
-            for(int i=1;i<nBlockCount;i++)
+            int nBlockCount =
+                TIFFIsTiled(hTIFF) ?
+                TIFFNumberOfTiles(hTIFF) : TIFFNumberOfStrips(hTIFF);
+            for( int i = 1; i < nBlockCount; ++i )
             {
                 if( panOffsets[i] < panOffsets[i-1] )
                 {
-                    oGTiffMDMD.SetMetadataItem("UNORDERED_BLOCKS", "YES", "TIFF");
-                    CPLDebug("GTIFF",
-                             "Offset of block %d is lower than previous block. Reader must be careful",
-                             i);
+                    oGTiffMDMD.SetMetadataItem( "UNORDERED_BLOCKS", "YES",
+                                                "TIFF");
+                    CPLDebug(
+                        "GTIFF",
+                        "Offset of block %d is lower than previous block. "
+                        "Reader must be careful",
+                        i );
                     break;
                 }
             }
         }
     }
 
+    if( nCompression == COMPRESSION_JPEG && eAccess == GA_Update )
+    {
+        SetJPEGQualityAndTablesModeFromFile();
+    }
+
     CPLAssert(m_bReadGeoTransform == bReadGeoTransform);
     CPLAssert(!bMetadataChanged);
-    bMetadataChanged = FALSE;
+    bMetadataChanged = false;
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -11652,177 +13426,267 @@ CPLErr GTiffDataset::OpenOffset( TIFF *hTIFFIn,
 
 char** GTiffDataset::GetSiblingFiles()
 {
-    char** papszSiblingFiles;
     if( m_bHasGotSiblingFiles )
-        papszSiblingFiles = oOvManager.GetSiblingFiles();
-    else
     {
-        m_bHasGotSiblingFiles = true;
-        const int nMaxFiles = atoi(CPLGetConfigOption("GDAL_READDIR_LIMIT_ON_OPEN", "1000"));
-        papszSiblingFiles = VSIReadDirEx(CPLGetDirname(osFilename), nMaxFiles);
-        if( nMaxFiles > 0 && CSLCount(papszSiblingFiles) > nMaxFiles )
-        {
-            CPLDebug("GTiff", "GDAL_READDIR_LIMIT_ON_OPEN reached on %s",
-                     CPLGetDirname(osFilename));
-            CSLDestroy(papszSiblingFiles);
-            papszSiblingFiles = NULL;
-        }
-        oOvManager.TransferSiblingFiles( papszSiblingFiles );
+        return oOvManager.GetSiblingFiles();
     }
+
+    m_bHasGotSiblingFiles = true;
+    const int nMaxFiles =
+        atoi(CPLGetConfigOption("GDAL_READDIR_LIMIT_ON_OPEN", "1000"));
+    char** papszSiblingFiles =
+        VSIReadDirEx(CPLGetDirname(osFilename), nMaxFiles);
+    if( nMaxFiles > 0 && CSLCount(papszSiblingFiles) > nMaxFiles )
+    {
+        CPLDebug("GTiff", "GDAL_READDIR_LIMIT_ON_OPEN reached on %s",
+                 CPLGetDirname(osFilename));
+        CSLDestroy(papszSiblingFiles);
+        papszSiblingFiles = NULL;
+    }
+    oOvManager.TransferSiblingFiles( papszSiblingFiles );
+
     return papszSiblingFiles;
 }
 
 /************************************************************************/
+/*                   IdentifyAuthorizedGeoreferencingSources()          */
+/************************************************************************/
+
+void GTiffDataset::IdentifyAuthorizedGeoreferencingSources()
+{
+    if( m_bHasIdentifiedAuthorizedGeoreferencingSources )
+        return;
+    m_bHasIdentifiedAuthorizedGeoreferencingSources = true;
+    CPLString osGeorefSources = CSLFetchNameValueDef( papszOpenOptions,
+        "GEOREF_SOURCES",
+        CPLGetConfigOption("GDAL_GEOREF_SOURCES",
+                           "PAM,INTERNAL,TABFILE,WORLDFILE") );
+    char** papszTokens = CSLTokenizeString2(osGeorefSources, ",", 0);
+    m_nPAMGeorefSrcIndex = CSLFindString(papszTokens, "PAM");
+    m_nINTERNALGeorefSrcIndex = CSLFindString(papszTokens, "INTERNAL");
+    m_nTABFILEGeorefSrcIndex = CSLFindString(papszTokens, "TABFILE");
+    m_nWORLDFILEGeorefSrcIndex = CSLFindString(papszTokens, "WORLDFILE");
+    CSLDestroy(papszTokens);
+}
+
+/************************************************************************/
 /*                     LoadGeoreferencingAndPamIfNeeded()               */
 /************************************************************************/
 
 void GTiffDataset::LoadGeoreferencingAndPamIfNeeded()
 
 {
+    if( !m_bReadGeoTransform && !m_bLoadPam )
+        return;
+
+    IdentifyAuthorizedGeoreferencingSources();
+
 /* -------------------------------------------------------------------- */
 /*      Get the transform or gcps from the GeoTIFF file.                */
 /* -------------------------------------------------------------------- */
     if( m_bReadGeoTransform )
     {
-        char    *pszTabWKT = NULL;
-        double  *padfTiePoints, *padfScale, *padfMatrix;
-        uint16  nCount;
-        bool    bPixelIsPoint = false;
-        short nRasterType;
-        bool bPointGeoIgnore = false;
-
         m_bReadGeoTransform = false;
 
         if( !SetDirectory() )
             return;
 
-        GTIF    *psGTIF = GTIFNew( hTIFF ); // I wonder how expensive this is?
+        char *pszTabWKT = NULL;
+        double *padfTiePoints = NULL;
+        double *padfScale = NULL;
+        double *padfMatrix = NULL;
+        uint16 nCount = 0;
+        bool bPixelIsPoint = false;
+        short nRasterType = 0;
+        bool bPointGeoIgnore = false;
 
-        if( psGTIF )
-        {
-            if( GDALGTIFKeyGetSHORT(psGTIF, GTRasterTypeGeoKey, &nRasterType,
-                        0, 1 ) == 1
-                && nRasterType == (short) RasterPixelIsPoint )
+        std::set<int> aoSetPriorities;
+        if( m_nINTERNALGeorefSrcIndex >= 0 )
+            aoSetPriorities.insert(m_nINTERNALGeorefSrcIndex);
+        if( m_nTABFILEGeorefSrcIndex >= 0 )
+            aoSetPriorities.insert(m_nTABFILEGeorefSrcIndex);
+        if( m_nWORLDFILEGeorefSrcIndex >= 0 )
+            aoSetPriorities.insert(m_nWORLDFILEGeorefSrcIndex);
+        std::set<int>::iterator oIter = aoSetPriorities.begin();
+        for( ; oIter != aoSetPriorities.end(); ++oIter )
+        {
+            int nIndex = *oIter;
+            if( m_nINTERNALGeorefSrcIndex == nIndex )
             {
-                bPixelIsPoint = true;
-                bPointGeoIgnore =
-                    CPLTestBool( CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
-                                                    "FALSE") );
-            }
+                GTIF *psGTIF = GTIFNew( hTIFF );  // How expensive this is?
 
-            GTIFFree( psGTIF );
-        }
+                if( psGTIF )
+                {
+                    if( GDALGTIFKeyGetSHORT(psGTIF, GTRasterTypeGeoKey,
+                                            &nRasterType, 0, 1 ) == 1
+                        && nRasterType ==
+                           static_cast<short>(RasterPixelIsPoint) )
+                    {
+                        bPixelIsPoint = true;
+                        bPointGeoIgnore =
+                            CPLTestBool(
+                                CPLGetConfigOption("GTIFF_POINT_GEO_IGNORE",
+                                                   "FALSE") );
+                    }
 
-        adfGeoTransform[0] = 0.0;
-        adfGeoTransform[1] = 1.0;
-        adfGeoTransform[2] = 0.0;
-        adfGeoTransform[3] = 0.0;
-        adfGeoTransform[4] = 0.0;
-        adfGeoTransform[5] = 1.0;
+                    GTIFFree( psGTIF );
+                }
 
-        if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
-            && nCount >= 2
-            && padfScale[0] != 0.0 && padfScale[1] != 0.0 )
-        {
-            adfGeoTransform[1] = padfScale[0];
-            adfGeoTransform[5] = - ABS(padfScale[1]);
+                adfGeoTransform[0] = 0.0;
+                adfGeoTransform[1] = 1.0;
+                adfGeoTransform[2] = 0.0;
+                adfGeoTransform[3] = 0.0;
+                adfGeoTransform[4] = 0.0;
+                adfGeoTransform[5] = 1.0;
+
+                if( TIFFGetField(hTIFF, TIFFTAG_GEOPIXELSCALE,
+                                 &nCount, &padfScale )
+                    && nCount >= 2
+                    && padfScale[0] != 0.0 && padfScale[1] != 0.0 )
+                {
+                    adfGeoTransform[1] = padfScale[0];
+                    adfGeoTransform[5] = -std::abs(padfScale[1]);
 
-            if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
-                && nCount >= 6 )
-            {
-                adfGeoTransform[0] =
-                    padfTiePoints[3] - padfTiePoints[0] * adfGeoTransform[1];
-                adfGeoTransform[3] =
-                    padfTiePoints[4] - padfTiePoints[1] * adfGeoTransform[5];
+                    if( TIFFGetField(hTIFF, TIFFTAG_GEOTIEPOINTS,
+                                     &nCount, &padfTiePoints )
+                        && nCount >= 6 )
+                    {
+                        adfGeoTransform[0] =
+                            padfTiePoints[3] -
+                            padfTiePoints[0] * adfGeoTransform[1];
+                        adfGeoTransform[3] =
+                            padfTiePoints[4] -
+                            padfTiePoints[1] * adfGeoTransform[5];
+
+                        if( bPixelIsPoint && !bPointGeoIgnore )
+                        {
+                            adfGeoTransform[0] -=
+                                (adfGeoTransform[1] * 0.5 +
+                                 adfGeoTransform[2] * 0.5);
+                            adfGeoTransform[3] -=
+                                (adfGeoTransform[4] * 0.5 +
+                                 adfGeoTransform[5] * 0.5);
+                        }
 
-                if( bPixelIsPoint && !bPointGeoIgnore )
-                {
-                    adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
-                    adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
+                        bGeoTransformValid = true;
+                        m_nGeoTransformGeorefSrcIndex = nIndex;
+                    }
                 }
 
-                bGeoTransformValid = TRUE;
-            }
-        }
-
-        else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix )
-                 && nCount == 16 )
-        {
-            adfGeoTransform[0] = padfMatrix[3];
-            adfGeoTransform[1] = padfMatrix[0];
-            adfGeoTransform[2] = padfMatrix[1];
-            adfGeoTransform[3] = padfMatrix[7];
-            adfGeoTransform[4] = padfMatrix[4];
-            adfGeoTransform[5] = padfMatrix[5];
+                else if( TIFFGetField(hTIFF, TIFFTAG_GEOTRANSMATRIX,
+                                      &nCount, &padfMatrix )
+                        && nCount == 16 )
+                {
+                    adfGeoTransform[0] = padfMatrix[3];
+                    adfGeoTransform[1] = padfMatrix[0];
+                    adfGeoTransform[2] = padfMatrix[1];
+                    adfGeoTransform[3] = padfMatrix[7];
+                    adfGeoTransform[4] = padfMatrix[4];
+                    adfGeoTransform[5] = padfMatrix[5];
+
+                    if( bPixelIsPoint && !bPointGeoIgnore )
+                    {
+                        adfGeoTransform[0] -=
+                            adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
+                        adfGeoTransform[3] -=
+                            adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
+                    }
 
-            if( bPixelIsPoint && !bPointGeoIgnore )
-            {
-                adfGeoTransform[0] -= (adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5);
-                adfGeoTransform[3] -= (adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5);
+                    bGeoTransformValid = true;
+                    m_nGeoTransformGeorefSrcIndex = nIndex;
+                }
+                if( bGeoTransformValid )
+                    break;
             }
 
-            bGeoTransformValid = TRUE;
-        }
-
 /* -------------------------------------------------------------------- */
 /*      Otherwise try looking for a .tab, .tfw, .tifw or .wld file.     */
 /* -------------------------------------------------------------------- */
-        else
-        {
-            char* pszGeorefFilename = NULL;
+            if( m_nTABFILEGeorefSrcIndex == nIndex )
+            {
+                char* pszGeorefFilename = NULL;
 
-            char** papszSiblingFiles = GetSiblingFiles();
+                char** papszSiblingFiles = GetSiblingFiles();
 
-            /* Begin with .tab since it can also have projection info */
-            int bTabFileOK =
-                GDALReadTabFile2( osFilename, adfGeoTransform,
-                                    &pszTabWKT, &nGCPCount, &pasGCPList,
-                                    papszSiblingFiles, &pszGeorefFilename );
+                // Begin with .tab since it can also have projection info.
+                const int bTabFileOK =
+                    GDALReadTabFile2( osFilename, adfGeoTransform,
+                                        &pszTabWKT, &nGCPCount, &pasGCPList,
+                                        papszSiblingFiles, &pszGeorefFilename );
 
-            if( bTabFileOK )
-            {
-                if( nGCPCount == 0 )
-                    bGeoTransformValid = TRUE;
+                if( bTabFileOK )
+                {
+                    m_nGeoTransformGeorefSrcIndex = nIndex;
+                    // if( pszTabWKT )
+                    // {
+                    //     m_nProjectionGeorefSrcIndex = nIndex;
+                    // }
+                    if( nGCPCount == 0 )
+                    {
+                        bGeoTransformValid = true;
+                    }
+                }
+
+                if( pszGeorefFilename )
+                {
+                    osGeorefFilename = pszGeorefFilename;
+                    CPLFree(pszGeorefFilename);
+                }
+                if( bGeoTransformValid )
+                    break;
             }
-            else
+
+            if( m_nWORLDFILEGeorefSrcIndex == nIndex )
             {
+                char* pszGeorefFilename = NULL;
+
+                char** papszSiblingFiles = GetSiblingFiles();
+
+                bGeoTransformValid = CPL_TO_BOOL( GDALReadWorldFile2(
+                                osFilename, NULL, adfGeoTransform,
+                                papszSiblingFiles, &pszGeorefFilename) );
+
                 if( !bGeoTransformValid )
                 {
                     bGeoTransformValid =
-                        GDALReadWorldFile2( osFilename, NULL, adfGeoTransform,
-                                            papszSiblingFiles, &pszGeorefFilename);
+                        CPL_TO_BOOL( GDALReadWorldFile2(
+                            osFilename, "wld", adfGeoTransform,
+                            papszSiblingFiles, &pszGeorefFilename ) );
                 }
+                if( bGeoTransformValid )
+                    m_nGeoTransformGeorefSrcIndex = nIndex;
 
-                if( !bGeoTransformValid )
+                if( pszGeorefFilename )
                 {
-                    bGeoTransformValid =
-                        GDALReadWorldFile2( osFilename, "wld", adfGeoTransform,
-                                            papszSiblingFiles, &pszGeorefFilename);
+                    osGeorefFilename = pszGeorefFilename;
+                    CPLFree(pszGeorefFilename);
                 }
-            }
-
-            if (pszGeorefFilename)
-            {
-                osGeorefFilename = pszGeorefFilename;
-                CPLFree(pszGeorefFilename);
+                if( bGeoTransformValid )
+                    break;
             }
         }
 
 /* -------------------------------------------------------------------- */
-/*      Check for GCPs.  Note, we will allow there to be GCPs and a     */
-/*      transform in some circumstances.                                */
+/*      Check for GCPs.                                                 */
 /* -------------------------------------------------------------------- */
-        if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
+        if( m_nINTERNALGeorefSrcIndex >= 0 &&
+            TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
             && !bGeoTransformValid )
         {
+            if( nGCPCount > 0 )
+            {
+                GDALDeinitGCPs( nGCPCount, pasGCPList );
+                CPLFree( pasGCPList );
+            }
             nGCPCount = nCount / 6;
-            pasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPCount);
+            pasGCPList =
+                static_cast<GDAL_GCP *>(CPLCalloc(sizeof(GDAL_GCP), nGCPCount));
 
-            for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
+            for( int iGCP = 0; iGCP < nGCPCount; ++iGCP )
             {
-                char    szID[32];
+                char szID[32] = {};
 
-                snprintf( szID, sizeof(szID), "%d", iGCP+1 );
+                snprintf( szID, sizeof(szID), "%d", iGCP + 1 );
                 pasGCPList[iGCP].pszId = CPLStrdup( szID );
                 pasGCPList[iGCP].pszInfo = CPLStrdup("");
                 pasGCPList[iGCP].dfGCPPixel = padfTiePoints[iGCP*6+0];
@@ -11837,10 +13701,11 @@ void GTiffDataset::LoadGeoreferencingAndPamIfNeeded()
                     pasGCPList[iGCP].dfGCPLine -= 0.5;
                 }
             }
+            m_nGeoTransformGeorefSrcIndex = m_nINTERNALGeorefSrcIndex;
         }
 
 /* -------------------------------------------------------------------- */
-/*      Did we find a tab file?  If so we will use it's coordinate      */
+/*      Did we find a tab file?  If so we will use its coordinate       */
 /*      system and give it precedence.                                  */
 /* -------------------------------------------------------------------- */
         if( pszTabWKT != NULL
@@ -11849,18 +13714,14 @@ void GTiffDataset::LoadGeoreferencingAndPamIfNeeded()
             CPLFree( pszProjection );
             pszProjection = pszTabWKT;
             pszTabWKT = NULL;
-            bLookedForProjection = TRUE;
+            bLookedForProjection = true;
         }
 
         CPLFree( pszTabWKT );
     }
 
-
-
-    if( m_bLoadPam )
+    if( m_bLoadPam && m_nPAMGeorefSrcIndex >= 0 )
     {
-        m_bLoadPam = false;
-
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
@@ -11869,39 +13730,51 @@ void GTiffDataset::LoadGeoreferencingAndPamIfNeeded()
         CPLAssert(!bGeoTIFFInfoChanged);
         CPLAssert(!bNoDataChanged);
 
+        // We must absolutely unset m_bLoadPam now, otherwise calling
+        // GetFileList() on a .tif with a .aux will result in an (almost)
+        // endless sequence of calls.
+        m_bLoadPam = false;
+
         TryLoadXML( GetSiblingFiles() );
         ApplyPamInfo();
 
-        bColorProfileMetadataChanged = FALSE;
-        bMetadataChanged = FALSE;
-        bGeoTIFFInfoChanged = FALSE;
-        bNoDataChanged = FALSE;
+        bColorProfileMetadataChanged = false;
+        bMetadataChanged = false;
+        bGeoTIFFInfoChanged = false;
+        bNoDataChanged = false;
 
-        int i;
-        for(i=1;i<=nBands;i++)
+        for( int i = 1; i <= nBands; ++i )
         {
-            GTiffRasterBand* poBand = (GTiffRasterBand*) GetRasterBand(i);
+            GTiffRasterBand* poBand =
+                reinterpret_cast<GTiffRasterBand *>(GetRasterBand(i));
 
             /* Load scale, offset and unittype from PAM if available */
-            if (!poBand->bHaveOffsetScale)
+            if( !poBand->bHaveOffsetScale )
             {
-                poBand->dfScale = poBand->GDALPamRasterBand::GetScale(&poBand->bHaveOffsetScale);
+                int nHaveOffsetScale = FALSE;
+                poBand->dfScale =
+                    poBand->GDALPamRasterBand::GetScale( &nHaveOffsetScale );
+                poBand->bHaveOffsetScale = CPL_TO_BOOL(nHaveOffsetScale);
                 poBand->dfOffset = poBand->GDALPamRasterBand::GetOffset();
             }
-            if (poBand->osUnitType.size() == 0)
+            if( poBand->osUnitType.empty() )
             {
-                const char* pszUnitType = poBand->GDALPamRasterBand::GetUnitType();
-                if (pszUnitType)
+                const char* pszUnitType =
+                    poBand->GDALPamRasterBand::GetUnitType();
+                if( pszUnitType )
                     poBand->osUnitType = pszUnitType;
             }
-            if( poBand->osDescription.size() == 0 )
-                poBand->osDescription = poBand->GDALPamRasterBand::GetDescription();
+            if( poBand->osDescription.empty() )
+                poBand->osDescription =
+                    poBand->GDALPamRasterBand::GetDescription();
 
-            GDALColorInterp ePAMColorInterp = poBand->GDALPamRasterBand::GetColorInterpretation();
+            GDALColorInterp ePAMColorInterp =
+                poBand->GDALPamRasterBand::GetColorInterpretation();
             if( ePAMColorInterp != GCI_Undefined )
                 poBand->eBandInterp = ePAMColorInterp;
         }
     }
+    m_bLoadPam = false;
 }
 
 /************************************************************************/
@@ -11920,7 +13793,7 @@ void GTiffDataset::ScanDirectories()
     if( !bScanDeferred )
         return;
 
-    bScanDeferred = FALSE;
+    bScanDeferred = false;
 
     if( !bBase )
         return;
@@ -11934,13 +13807,13 @@ void GTiffDataset::ScanDirectories()
 /*      Scan all directories.                                           */
 /* ==================================================================== */
     CPLStringList aosSubdatasets;
-    int  iDirIndex = 0;
+    int iDirIndex = 0;
 
     FlushDirectory();
     while( !TIFFLastDirectory( hTIFF )
            && (iDirIndex == 0 || TIFFReadDirectory( hTIFF ) != 0) )
     {
-        /* Only libtiff 4.0.4 can handle between 32768 and 65535 directories */
+        // Only libtiff 4.0.4 can handle between 32768 and 65535 directories.
 #if !defined(INTERNAL_LIBTIFF) && (!defined(TIFFLIB_VERSION) || (TIFFLIB_VERSION < 20120922))
         if( iDirIndex == 32768 )
             break;
@@ -11948,21 +13821,21 @@ void GTiffDataset::ScanDirectories()
         toff_t nThisDir = TIFFCurrentDirOffset(hTIFF);
         uint32 nSubType = 0;
 
-        *ppoActiveDSRef = NULL; // our directory no longer matches this ds
+        *ppoActiveDSRef = NULL; // Our directory no longer matches this ds.
 
-        iDirIndex++;
+        ++iDirIndex;
 
         if( !TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType) )
             nSubType = 0;
 
         /* Embedded overview of the main image */
-        if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
+        if( (nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
             (nSubType & FILETYPE_MASK) == 0 &&
             iDirIndex != 1 &&
             nOverviewCount < 30 /* to avoid DoS */ )
         {
             GTiffDataset *poODS = new GTiffDataset();
-            if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
+            if( poODS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, false,
                                    eAccess ) != CE_None
                 || poODS->GetRasterCount() != GetRasterCount() )
             {
@@ -11970,38 +13843,39 @@ void GTiffDataset::ScanDirectories()
             }
             else
             {
-                CPLDebug( "GTiff", "Opened %dx%d overview.\n",
+                CPLDebug( "GTiff", "Opened %dx%d overview.",
                           poODS->GetRasterXSize(), poODS->GetRasterYSize());
-                nOverviewCount++;
-                papoOverviewDS = (GTiffDataset **)
+                ++nOverviewCount;
+                papoOverviewDS = static_cast<GTiffDataset **>(
                     CPLRealloc(papoOverviewDS,
-                               nOverviewCount * (sizeof(void*)));
+                               nOverviewCount * (sizeof(void*))) );
                 papoOverviewDS[nOverviewCount-1] = poODS;
                 poODS->poBaseDS = this;
             }
         }
-
-        /* Embedded mask of the main image */
-        else if ((nSubType & FILETYPE_MASK) != 0 &&
+        // Embedded mask of the main image.
+        else if( (nSubType & FILETYPE_MASK) != 0 &&
                  (nSubType & FILETYPE_REDUCEDIMAGE) == 0 &&
                  iDirIndex != 1 &&
                  poMaskDS == NULL )
         {
             poMaskDS = new GTiffDataset();
 
-            /* The TIFF6 specification - page 37 - only allows 1 SamplesPerPixel and 1 BitsPerSample
-               Here we support either 1 or 8 bit per sample
-               and we support either 1 sample per pixel or as many samples as in the main image
-               We don't check the value of the PhotometricInterpretation tag, which should be
-               set to "Transparency mask" (4) according to the specification (page 36)
-               ... But the TIFF6 specification allows image masks to have a higher resolution than
-               the main image, what we don't support here
-            */
+            // The TIFF6 specification - page 37 - only allows 1
+            // SamplesPerPixel and 1 BitsPerSample Here we support either 1 or
+            // 8 bit per sample and we support either 1 sample per pixel or as
+            // many samples as in the main image We don't check the value of
+            // the PhotometricInterpretation tag, which should be set to
+            // "Transparency mask" (4) according to the specification (page
+            // 36).  However, the TIFF6 specification allows image masks to
+            // have a higher resolution than the main image, what we don't
+            // support here.
 
             if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir,
-                                      FALSE, eAccess ) != CE_None
+                                      false, eAccess ) != CE_None
                 || poMaskDS->GetRasterCount() == 0
-                || !(poMaskDS->GetRasterCount() == 1 || poMaskDS->GetRasterCount() == GetRasterCount())
+                || !(poMaskDS->GetRasterCount() == 1
+                     || poMaskDS->GetRasterCount() == GetRasterCount())
                 || poMaskDS->GetRasterXSize() != GetRasterXSize()
                 || poMaskDS->GetRasterYSize() != GetRasterYSize()
                 || poMaskDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
@@ -12011,18 +13885,21 @@ void GTiffDataset::ScanDirectories()
             }
             else
             {
-                CPLDebug( "GTiff", "Opened band mask.\n");
+                CPLDebug( "GTiff", "Opened band mask.");
                 poMaskDS->poBaseDS = this;
 
-                poMaskDS->bPromoteTo8Bits = CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
+                poMaskDS->bPromoteTo8Bits =
+                    CPLTestBool(
+                        CPLGetConfigOption( "GDAL_TIFF_INTERNAL_MASK_TO_8BIT",
+                                            "YES" ) );
             }
         }
 
-        /* Embedded mask of an overview */
-        /* The TIFF6 specification allows the combination of the FILETYPE_xxxx masks */
-        else if ((nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
+        // Embedded mask of an overview.  The TIFF6 specification allows the
+        // combination of the FILETYPE_xxxx masks.
+        else if( (nSubType & FILETYPE_REDUCEDIMAGE) != 0 &&
                  (nSubType & FILETYPE_MASK) != 0 &&
-                 iDirIndex != 1)
+                 iDirIndex != 1 )
         {
             GTiffDataset* poDS = new GTiffDataset();
             if( poDS->OpenOffset( hTIFF, ppoActiveDSRef, nThisDir, FALSE,
@@ -12034,46 +13911,70 @@ void GTiffDataset::ScanDirectories()
             }
             else
             {
-                int i;
-                for(i=0;i<nOverviewCount;i++)
+                int i = 0;  // Used after for.
+                for( ; i < nOverviewCount; ++i )
                 {
-                    if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS == NULL &&
-                        poDS->GetRasterXSize() == papoOverviewDS[i]->GetRasterXSize() &&
-                        poDS->GetRasterYSize() == papoOverviewDS[i]->GetRasterYSize() &&
-                        (poDS->GetRasterCount() == 1 || poDS->GetRasterCount() == GetRasterCount()))
+                    if( reinterpret_cast<GTiffDataset *>(
+                           papoOverviewDS[i])->poMaskDS == NULL &&
+                        poDS->GetRasterXSize() ==
+                        papoOverviewDS[i]->GetRasterXSize() &&
+                        poDS->GetRasterYSize() ==
+                        papoOverviewDS[i]->GetRasterYSize() &&
+                        (poDS->GetRasterCount() == 1 ||
+                         poDS->GetRasterCount() == GetRasterCount()))
                     {
-                        CPLDebug( "GTiff", "Opened band mask for %dx%d overview.\n",
-                                  poDS->GetRasterXSize(), poDS->GetRasterYSize());
-                        ((GTiffDataset*)papoOverviewDS[i])->poMaskDS = poDS;
-                        poDS->bPromoteTo8Bits = CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
+                        CPLDebug(
+                            "GTiff", "Opened band mask for %dx%d overview.",
+                            poDS->GetRasterXSize(), poDS->GetRasterYSize());
+                        reinterpret_cast<GTiffDataset*>(papoOverviewDS[i])->
+                            poMaskDS = poDS;
+                        poDS->bPromoteTo8Bits =
+                            CPLTestBool(
+                                CPLGetConfigOption(
+                                    "GDAL_TIFF_INTERNAL_MASK_TO_8BIT",
+                                    "YES" ) );
                         poDS->poBaseDS = this;
                         break;
                     }
                 }
-                if (i == nOverviewCount)
+                if( i == nOverviewCount )
                 {
                     delete poDS;
                 }
             }
         }
-        else if( nSubType == 0 || nSubType == FILETYPE_PAGE ) {
-            uint32 nXSize, nYSize;
-            uint16 nSPP;
+        else if( nSubType == 0 || nSubType == FILETYPE_PAGE )
+        {
+            uint32 nXSize = 0;
+            uint32 nYSize = 0;
 
             TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
             TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
-            if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSPP ) )
-                nSPP = 1;
-
-            CPLString osName, osDesc;
-            osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s",
-                           iDirIndex, iDirIndex, osFilename.c_str() );
-            osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)",
-                           iDirIndex, iDirIndex,
-                           (int)nXSize, (int)nYSize, nSPP );
 
-            aosSubdatasets.AddString(osName);
-            aosSubdatasets.AddString(osDesc);
+            if( nXSize > INT_MAX || nYSize > INT_MAX )
+            {
+                CPLDebug("GTiff",
+                         "Skipping directory with too large image: %u x %u",
+                         nXSize, nYSize);
+            }
+            else
+            {
+                uint16 nSPP = 0;
+                if( !TIFFGetField(hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSPP ) )
+                    nSPP = 1;
+
+                CPLString osName, osDesc;
+                osName.Printf( "SUBDATASET_%d_NAME=GTIFF_DIR:%d:%s",
+                            iDirIndex, iDirIndex, osFilename.c_str() );
+                osDesc.Printf( "SUBDATASET_%d_DESC=Page %d (%dP x %dL x %dB)",
+                            iDirIndex, iDirIndex,
+                            static_cast<int>(nXSize),
+                            static_cast<int>(nYSize),
+                            nSPP );
+
+                aosSubdatasets.AddString(osName);
+                aosSubdatasets.AddString(osDesc);
+            }
         }
 
         // Make sure we are stepping from the expected directory regardless
@@ -12083,20 +13984,22 @@ void GTiffDataset::ScanDirectories()
         *ppoActiveDSRef = NULL;
     }
 
-    /* If we have a mask for the main image, loop over the overviews, and if they */
-    /* have a mask, let's set this mask as an overview of the main mask... */
-    if (poMaskDS != NULL)
+    // If we have a mask for the main image, loop over the overviews, and if
+    // they have a mask, let's set this mask as an overview of the main mask.
+    if( poMaskDS != NULL )
     {
-        for(int i=0;i<nOverviewCount;i++)
+        for( int i = 0; i < nOverviewCount; ++i )
         {
-            if (((GTiffDataset*)papoOverviewDS[i])->poMaskDS != NULL)
+            if( reinterpret_cast<GTiffDataset *>(
+                   papoOverviewDS[i])->poMaskDS != NULL)
             {
-                poMaskDS->nOverviewCount++;
-                poMaskDS->papoOverviewDS = (GTiffDataset **)
+                ++poMaskDS->nOverviewCount;
+                poMaskDS->papoOverviewDS = static_cast<GTiffDataset **>(
                     CPLRealloc(poMaskDS->papoOverviewDS,
-                               poMaskDS->nOverviewCount * (sizeof(void*)));
+                               poMaskDS->nOverviewCount * (sizeof(void*))) );
                 poMaskDS->papoOverviewDS[poMaskDS->nOverviewCount-1] =
-                    ((GTiffDataset*)papoOverviewDS[i])->poMaskDS;
+                    reinterpret_cast<GTiffDataset*>(
+                        papoOverviewDS[i])->poMaskDS;
             }
         }
     }
@@ -12111,38 +14014,36 @@ void GTiffDataset::ScanDirectories()
     }
 }
 
-
 static int GTiffGetLZMAPreset(char** papszOptions)
 {
     int nLZMAPreset = -1;
     const char* pszValue = CSLFetchNameValue( papszOptions, "LZMA_PRESET" );
-    if( pszValue  != NULL )
+    if( pszValue != NULL )
     {
-        nLZMAPreset =  atoi( pszValue );
-        if (!(nLZMAPreset >= 0 && nLZMAPreset <= 9))
+        nLZMAPreset = atoi( pszValue );
+        if( !(nLZMAPreset >= 0 && nLZMAPreset <= 9) )
         {
             CPLError( CE_Warning, CPLE_IllegalArg,
-                    "LZMA_PRESET=%s value not recognised, ignoring.",
-                    pszValue );
+                      "LZMA_PRESET=%s value not recognised, ignoring.",
+                      pszValue );
             nLZMAPreset = -1;
         }
     }
     return nLZMAPreset;
 }
 
-
 static int GTiffGetZLevel(char** papszOptions)
 {
     int nZLevel = -1;
     const char* pszValue = CSLFetchNameValue( papszOptions, "ZLEVEL" );
-    if( pszValue  != NULL )
+    if( pszValue != NULL )
     {
-        nZLevel =  atoi( pszValue );
-        if (!(nZLevel >= 1 && nZLevel <= 9))
+        nZLevel = atoi( pszValue );
+        if( nZLevel < 1 || nZLevel > 9 )
         {
             CPLError( CE_Warning, CPLE_IllegalArg,
-                    "ZLEVEL=%s value not recognised, ignoring.",
-                    pszValue );
+                      "ZLEVEL=%s value not recognised, ignoring.",
+                      pszValue );
             nZLevel = -1;
         }
     }
@@ -12153,14 +14054,14 @@ static int GTiffGetJpegQuality(char** papszOptions)
 {
     int nJpegQuality = -1;
     const char* pszValue = CSLFetchNameValue( papszOptions, "JPEG_QUALITY" );
-    if( pszValue  != NULL )
+    if( pszValue != NULL )
     {
         nJpegQuality = atoi( pszValue );
-        if (!(nJpegQuality >= 1 && nJpegQuality <= 100))
+        if( nJpegQuality < 1 || nJpegQuality > 100 )
         {
             CPLError( CE_Warning, CPLE_IllegalArg,
-                    "JPEG_QUALITY=%s value not recognised, ignoring.",
-                    pszValue );
+                      "JPEG_QUALITY=%s value not recognised, ignoring.",
+                      pszValue );
             nJpegQuality = -1;
         }
     }
@@ -12170,7 +14071,8 @@ static int GTiffGetJpegQuality(char** papszOptions)
 static int GTiffGetJpegTablesMode(char** papszOptions)
 {
     return atoi(CSLFetchNameValueDef( papszOptions, "JPEGTABLESMODE",
-                                   "1" /* JPEGTABLESMODE_QUANT */));
+                                      CPLSPrintf("%d",
+                                                knGTIFFJpegTablesModeDefault)));
 }
 
 /************************************************************************/
@@ -12199,26 +14101,26 @@ void GTiffDataset::GetDiscardLsbOption(char** papszOptions)
     char** papszTokens = CSLTokenizeString2( pszBits, ",", 0 );
     if( CSLCount(papszTokens) == 1 )
     {
-        bHasDiscardedLsb = TRUE;
-        for(int i=0;i<nBands;i++)
+        bHasDiscardedLsb = true;
+        for( int i = 0; i < nBands; ++i )
         {
             int nBits = atoi(papszTokens[0]);
             anMaskLsb.push_back(~((1 << nBits)-1));
             if( nBits > 1 )
-                anOffsetLsb.push_back(1 << (nBits-1));
+                anOffsetLsb.push_back(1 << (nBits - 1));
             else
                 anOffsetLsb.push_back(0);
         }
     }
     else if( CSLCount(papszTokens) == nBands )
     {
-        bHasDiscardedLsb = TRUE;
-        for(int i=0;i<nBands;i++)
+        bHasDiscardedLsb = true;
+        for( int i = 0; i < nBands; ++i )
         {
             int nBits = atoi(papszTokens[i]);
             anMaskLsb.push_back(~((1 << nBits)-1));
             if( nBits > 1 )
-                anOffsetLsb.push_back(1 << (nBits-1));
+                anOffsetLsb.push_back(1 << (nBits - 1));
             else
                 anOffsetLsb.push_back(0);
         }
@@ -12240,47 +14142,37 @@ void GTiffDataset::GetDiscardLsbOption(char** papszOptions)
 /************************************************************************/
 
 TIFF *GTiffDataset::CreateLL( const char * pszFilename,
-                              int nXSize, int nYSize, int nBands,
+                              int nXSize, int nYSize, int l_nBands,
                               GDALDataType eType,
                               double dfExtraSpaceForOverviews,
                               char **papszParmList,
                               VSILFILE** pfpL,
-                              CPLString& osTmpFilename )
+                              CPLString& l_osTmpFilename )
 
 {
-    if (!GTiffOneTimeInit())
+    if( !GTiffOneTimeInit() )
         return NULL;
 
-    TIFF *hTIFF;
-    int                 nBlockXSize = 0, nBlockYSize = 0;
-    int                 bTiled = FALSE;
-    int                 nCompression = COMPRESSION_NONE;
-    int                 nPredictor = PREDICTOR_NONE;
-    uint16              nSampleFormat;
-    int nPlanar;
-    const char          *pszValue;
-    const char          *pszProfile;
-    int                 bCreateBigTIFF = FALSE;
-
 /* -------------------------------------------------------------------- */
 /*      Blow on a few errors.                                           */
 /* -------------------------------------------------------------------- */
-    if( nXSize < 1 || nYSize < 1 || nBands < 1 )
+    if( nXSize < 1 || nYSize < 1 || l_nBands < 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to create %dx%dx%d TIFF file, but width, height and bands\n"
-                  "must be positive.",
-                  nXSize, nYSize, nBands );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Attempt to create %dx%dx%d TIFF file, but width, height and bands"
+            "must be positive.",
+            nXSize, nYSize, l_nBands );
 
         return NULL;
     }
 
-    if (nBands > 65535)
+    if( l_nBands > 65535 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to create %dx%dx%d TIFF file, but bands\n"
+                  "Attempt to create %dx%dx%d TIFF file, but bands "
                   "must be lesser or equal to 65535.",
-                  nXSize, nYSize, nBands );
+                  nXSize, nYSize, l_nBands );
 
         return NULL;
     }
@@ -12288,28 +14180,32 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Setup values based on options.                                  */
 /* -------------------------------------------------------------------- */
-    pszProfile = CSLFetchNameValue(papszParmList,"PROFILE");
+    const char *pszProfile = CSLFetchNameValue(papszParmList, "PROFILE");
     if( pszProfile == NULL )
         pszProfile = "GDALGeoTIFF";
 
-    if( CSLFetchBoolean( papszParmList, "TILED", FALSE ) )
-        bTiled = TRUE;
+    const bool bTiled = CPLFetchBool( papszParmList, "TILED", false );
 
-    pszValue = CSLFetchNameValue(papszParmList,"BLOCKXSIZE");
+    int l_nBlockXSize = 0;
+    const char *pszValue = CSLFetchNameValue(papszParmList, "BLOCKXSIZE");
     if( pszValue != NULL )
-        nBlockXSize = atoi( pszValue );
+        l_nBlockXSize = atoi( pszValue );
 
-    pszValue = CSLFetchNameValue(papszParmList,"BLOCKYSIZE");
+    int l_nBlockYSize = 0;
+    pszValue = CSLFetchNameValue(papszParmList, "BLOCKYSIZE");
     if( pszValue != NULL )
-        nBlockYSize = atoi( pszValue );
+        l_nBlockYSize = atoi( pszValue );
 
-    pszValue = CSLFetchNameValue(papszParmList,"INTERLEAVE");
+    int nPlanar = 0;
+    pszValue = CSLFetchNameValue(papszParmList, "INTERLEAVE");
     if( pszValue != NULL )
     {
         if( EQUAL( pszValue, "PIXEL" ) )
             nPlanar = PLANARCONFIG_CONTIG;
         else if( EQUAL( pszValue, "BAND" ) )
+        {
             nPlanar = PLANARCONFIG_SEPARATE;
+        }
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -12323,81 +14219,92 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
         nPlanar = PLANARCONFIG_CONTIG;
     }
 
+    int l_nCompression = COMPRESSION_NONE;
     pszValue = CSLFetchNameValue( papszParmList, "COMPRESS" );
-    if( pszValue  != NULL )
+    if( pszValue != NULL )
     {
-        nCompression = GTIFFGetCompressionMethod(pszValue, "COMPRESS");
-        if (nCompression < 0)
+        l_nCompression = GTIFFGetCompressionMethod(pszValue, "COMPRESS");
+        if( l_nCompression < 0 )
             return NULL;
     }
 
+    int nPredictor = PREDICTOR_NONE;
     pszValue = CSLFetchNameValue( papszParmList, "PREDICTOR" );
-    if( pszValue  != NULL )
-        nPredictor =  atoi( pszValue );
+    if( pszValue != NULL )
+        nPredictor = atoi( pszValue );
 
-    int nZLevel = GTiffGetZLevel(papszParmList);
-    int nLZMAPreset = GTiffGetLZMAPreset(papszParmList);
-    int nJpegQuality = GTiffGetJpegQuality(papszParmList);
-    int nJpegTablesMode = GTiffGetJpegTablesMode(papszParmList);
+    const int l_nZLevel = GTiffGetZLevel(papszParmList);
+    const int l_nLZMAPreset = GTiffGetLZMAPreset(papszParmList);
+    const int l_nJpegQuality = GTiffGetJpegQuality(papszParmList);
+    const int l_nJpegTablesMode = GTiffGetJpegTablesMode(papszParmList);
 
 /* -------------------------------------------------------------------- */
 /*      Streaming related code                                          */
 /* -------------------------------------------------------------------- */
     const CPLString osOriFilename(pszFilename);
-    int bStreaming = ( strcmp(pszFilename, "/vsistdout/") == 0 ||
-                       CSLFetchBoolean(papszParmList, "STREAMABLE_OUTPUT", FALSE) );
+    bool bStreaming =
+        strcmp(pszFilename, "/vsistdout/") == 0 ||
+        CPLFetchBool(papszParmList, "STREAMABLE_OUTPUT", false);
 #ifdef S_ISFIFO
     if( !bStreaming )
     {
         VSIStatBufL sStat;
-        if( VSIStatExL(pszFilename, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
+        if( VSIStatExL( pszFilename, &sStat,
+                        VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
              S_ISFIFO(sStat.st_mode) )
         {
-            bStreaming = TRUE;
+            bStreaming = true;
         }
     }
 #endif
     if( bStreaming &&
-        !EQUAL("NONE", CSLFetchNameValueDef(papszParmList, "COMPRESS", "NONE")) )
+        !EQUAL( "NONE",
+                CSLFetchNameValueDef(papszParmList, "COMPRESS", "NONE")) )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "Streaming only supported to uncompressed TIFF");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Streaming only supported to uncompressed TIFF" );
         return NULL;
     }
-    if( bStreaming &&
-        CSLFetchBoolean(papszParmList, "SPARSE_OK", FALSE) )
+    if( bStreaming && CPLFetchBool(papszParmList, "SPARSE_OK", false) )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "Streaming not supported with SPARSE_OK");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Streaming not supported with SPARSE_OK" );
         return NULL;
     }
-    if( bStreaming &&
-        CSLFetchBoolean(papszParmList, "COPY_SRC_OVERVIEWS", FALSE) )
+    if( bStreaming && CPLFetchBool(papszParmList, "COPY_SRC_OVERVIEWS", false) )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "Streaming not supported with COPY_SRC_OVERVIEWS");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Streaming not supported with COPY_SRC_OVERVIEWS" );
         return NULL;
     }
     if( bStreaming )
     {
         static int nCounter = 0;
-        osTmpFilename = CPLSPrintf("/vsimem/vsistdout_%d.tif",  ++nCounter);
-        pszFilename = osTmpFilename.c_str();
+        l_osTmpFilename = CPLSPrintf("/vsimem/vsistdout_%d.tif", ++nCounter);
+        pszFilename = l_osTmpFilename.c_str();
     }
 
 /* -------------------------------------------------------------------- */
 /*      Compute the uncompressed size.                                  */
 /* -------------------------------------------------------------------- */
-    double  dfUncompressedImageSize
-        = nXSize * ((double)nYSize) * nBands * (GDALGetDataTypeSize(eType)/8);
-    dfUncompressedImageSize += dfExtraSpaceForOverviews;
+    const double dfUncompressedImageSize =
+        nXSize * static_cast<double>(nYSize) * l_nBands *
+        GDALGetDataTypeSizeBytes(eType)
+        + dfExtraSpaceForOverviews;
 
-    if( nCompression == COMPRESSION_NONE
+    if( l_nCompression == COMPRESSION_NONE
         && dfUncompressedImageSize > 4200000000.0 )
     {
 #ifndef BIGTIFF_SUPPORT
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "A %d pixels x %d lines x %d bands %s image would be larger than 4GB\n"
-                  "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n"
-                  "Creation failed.",
-                  nXSize, nYSize, nBands, GDALGetDataTypeName(eType) );
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "A %d pixels x %d lines x %d bands %s image would be larger than "
+            "4GB but this is the largest size a TIFF can be, and BigTIFF "
+            "is unavailable.  Creation failed.",
+            nXSize, nYSize, l_nBands, GDALGetDataTypeName(eType) );
         return NULL;
 #endif
     }
@@ -12405,20 +14312,23 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Check free space (only for big, non sparse, uncompressed)       */
 /* -------------------------------------------------------------------- */
-    if( nCompression == COMPRESSION_NONE &&
+    if( l_nCompression == COMPRESSION_NONE &&
         dfUncompressedImageSize >= 1e9 &&
-        !CSLFetchBoolean(papszParmList, "SPARSE_OK", FALSE) &&
+        !CPLFetchBool(papszParmList, "SPARSE_OK", false) &&
         osOriFilename != "/vsistdout/" &&
         osOriFilename != "/vsistdout_redirect/" &&
         CPLTestBool(CPLGetConfigOption("CHECK_DISK_FREE_SPACE", "TRUE")) )
     {
-        GIntBig nFreeDiskSpace = VSIGetDiskFreeSpace(CPLGetDirname(pszFilename));
+        GIntBig nFreeDiskSpace =
+            VSIGetDiskFreeSpace(CPLGetDirname(pszFilename));
         if( nFreeDiskSpace >= 0 &&
             nFreeDiskSpace < dfUncompressedImageSize )
         {
             CPLError( CE_Failure, CPLE_FileIO,
                       "Free disk space available is " CPL_FRMT_GIB " bytes, "
-                      "whereas " CPL_FRMT_GIB " are at least necessary.",
+                      "whereas " CPL_FRMT_GIB " are at least necessary. "
+                      "You can disable this check by defining the "
+                      "CHECK_DISK_FREE_SPACE configuration option to FALSE.",
                       nFreeDiskSpace,
                       static_cast<GIntBig>(dfUncompressedImageSize) );
             return NULL;
@@ -12433,27 +14343,28 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     if( pszBIGTIFF == NULL )
         pszBIGTIFF = "IF_NEEDED";
 
-    if( EQUAL(pszBIGTIFF,"IF_NEEDED") )
+    bool bCreateBigTIFF = false;
+    if( EQUAL(pszBIGTIFF, "IF_NEEDED") )
     {
-        if( nCompression == COMPRESSION_NONE
+        if( l_nCompression == COMPRESSION_NONE
             && dfUncompressedImageSize > 4200000000.0 )
-            bCreateBigTIFF = TRUE;
+            bCreateBigTIFF = true;
     }
-    else if( EQUAL(pszBIGTIFF,"IF_SAFER") )
+    else if( EQUAL(pszBIGTIFF, "IF_SAFER") )
     {
         if( dfUncompressedImageSize > 2000000000.0 )
-            bCreateBigTIFF = TRUE;
+            bCreateBigTIFF = true;
     }
-
     else
     {
         bCreateBigTIFF = CPLTestBool( pszBIGTIFF );
-        if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE &&
+        if( !bCreateBigTIFF && l_nCompression == COMPRESSION_NONE &&
              dfUncompressedImageSize > 4200000000.0 )
         {
-            CPLError( CE_Failure, CPLE_NotSupported,
-                "The TIFF file will be larger than 4GB, so BigTIFF is necessary.\n"
-                "Creation failed.");
+            CPLError(
+                CE_Failure, CPLE_NotSupported,
+                "The TIFF file will be larger than 4GB, so BigTIFF is "
+                "necessary.  Creation failed.");
             return NULL;
         }
     }
@@ -12462,9 +14373,9 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
     if( bCreateBigTIFF )
     {
         CPLError( CE_Warning, CPLE_NotSupported,
-                  "BigTIFF requested, but GDAL built without BigTIFF\n"
+                  "BigTIFF requested, but GDAL built without BigTIFF "
                   "enabled libtiff, request ignored." );
-        bCreateBigTIFF = FALSE;
+        bCreateBigTIFF = false;
     }
 #endif
 
@@ -12477,15 +14388,19 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 
     int eEndianness = ENDIANNESS_NATIVE;
     pszValue = CSLFetchNameValue(papszParmList, "ENDIANNESS");
-    if ( pszValue == NULL )
+    if( pszValue == NULL )
         pszValue = CPLGetConfigOption( "GDAL_TIFF_ENDIANNESS", NULL );
-    if ( pszValue != NULL )
+    if( pszValue != NULL )
     {
-        if (EQUAL(pszValue, "LITTLE"))
+        if( EQUAL(pszValue, "LITTLE") )
+        {
             eEndianness = ENDIANNESS_LITTLE;
-        else if (EQUAL(pszValue, "BIG"))
+        }
+        else if( EQUAL(pszValue, "BIG") )
+        {
             eEndianness = ENDIANNESS_BIG;
-        else if (EQUAL(pszValue, "INVERTED"))
+        }
+        else if( EQUAL(pszValue, "INVERTED") )
         {
 #ifdef CPL_LSB
             eEndianness = ENDIANNESS_BIG;
@@ -12493,10 +14408,11 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
             eEndianness = ENDIANNESS_LITTLE;
 #endif
         }
-        else if (!EQUAL(pszValue, "NATIVE"))
+        else if( !EQUAL(pszValue, "NATIVE") )
         {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                      "ENDIANNESS=%s not supported. Defaulting to NATIVE", pszValue );
+            CPLError(
+                CE_Warning, CPLE_NotSupported,
+                "ENDIANNESS=%s not supported. Defaulting to NATIVE", pszValue );
         }
     }
 
@@ -12504,32 +14420,32 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
 
-    char szOpeningFlag[5];
+    char szOpeningFlag[5] = {};
     strcpy(szOpeningFlag, "w+");
-    if (bCreateBigTIFF)
+    if( bCreateBigTIFF )
         strcat(szOpeningFlag, "8");
-    if (eEndianness == ENDIANNESS_BIG)
+    if( eEndianness == ENDIANNESS_BIG )
         strcat(szOpeningFlag, "b");
-    else if (eEndianness == ENDIANNESS_LITTLE)
+    else if( eEndianness == ENDIANNESS_LITTLE )
         strcat(szOpeningFlag, "l");
 
-    VSILFILE* fpL = VSIFOpenL( pszFilename, "w+b" );
-    if( fpL == NULL )
+    VSILFILE* l_fpL = VSIFOpenL( pszFilename, "w+b" );
+    if( l_fpL == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Attempt to create new tiff file `%s' failed: %s",
                   pszFilename, VSIStrerror(errno) );
         return NULL;
     }
-    hTIFF = VSI_TIFFOpen( pszFilename, szOpeningFlag, fpL );
-    if( hTIFF == NULL )
+    TIFF *l_hTIFF = VSI_TIFFOpen( pszFilename, szOpeningFlag, l_fpL );
+    if( l_hTIFF == NULL )
     {
         if( CPLGetLastErrorNo() == 0 )
             CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Attempt to create new tiff file `%s'\n"
-                      "failed in XTIFFOpen().\n",
+                      "Attempt to create new tiff file `%s' "
+                      "failed in XTIFFOpen().",
                       pszFilename );
-        CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(l_fpL));
         return NULL;
     }
 
@@ -12537,12 +14453,13 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /*      How many bits per sample?  We have a special case if NBITS      */
 /*      specified for GDT_Byte, GDT_UInt16, GDT_UInt32.                 */
 /* -------------------------------------------------------------------- */
-    int nBitsPerSample = GDALGetDataTypeSize(eType);
-    if (CSLFetchNameValue(papszParmList, "NBITS") != NULL)
+    int l_nBitsPerSample = GDALGetDataTypeSizeBits(eType);
+    if( CSLFetchNameValue(papszParmList, "NBITS") != NULL )
     {
-        int nMinBits = 0, nMaxBits = 0;
-        nBitsPerSample = atoi(CSLFetchNameValue(papszParmList, "NBITS"));
-        if( eType == GDT_Byte  )
+        int nMinBits = 0;
+        int nMaxBits = 0;
+        l_nBitsPerSample = atoi(CSLFetchNameValue(papszParmList, "NBITS"));
+        if( eType == GDT_Byte )
         {
             nMinBits = 1;
             nMaxBits = 8;
@@ -12552,34 +14469,46 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
             nMinBits = 9;
             nMaxBits = 16;
         }
-        else if( eType == GDT_UInt32  )
+        else if( eType == GDT_UInt32 )
         {
             nMinBits = 17;
             nMaxBits = 32;
         }
+        else if( eType == GDT_Float32 )
+        {
+            if( l_nBitsPerSample != 16 && l_nBitsPerSample != 32 )
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                     "NBITS is not supported for data type %s",
+                     GDALGetDataTypeName(eType));
+                l_nBitsPerSample = GDALGetDataTypeSizeBits(eType);
+            }
+        }
         else
         {
             CPLError(CE_Warning, CPLE_NotSupported,
                      "NBITS is not supported for data type %s",
                      GDALGetDataTypeName(eType));
-            nBitsPerSample = GDALGetDataTypeSize(eType);
+            l_nBitsPerSample = GDALGetDataTypeSizeBits(eType);
         }
 
-        if (nMinBits != 0)
+        if( nMinBits != 0 )
         {
-            if (nBitsPerSample < nMinBits)
+            if( l_nBitsPerSample < nMinBits )
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
                          "NBITS=%d is invalid for data type %s. Using NBITS=%d",
-                         nBitsPerSample, GDALGetDataTypeName(eType), nMinBits);
-                nBitsPerSample = nMinBits;
+                         l_nBitsPerSample, GDALGetDataTypeName(eType),
+                         nMinBits);
+                l_nBitsPerSample = nMinBits;
             }
-            else if (nBitsPerSample > nMaxBits)
+            else if( l_nBitsPerSample > nMaxBits )
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
                          "NBITS=%d is invalid for data type %s. Using NBITS=%d",
-                         nBitsPerSample, GDALGetDataTypeName(eType), nMaxBits);
-                nBitsPerSample = nMaxBits;
+                         l_nBitsPerSample, GDALGetDataTypeName(eType),
+                         nMaxBits);
+                l_nBitsPerSample = nMaxBits;
             }
         }
     }
@@ -12594,162 +14523,173 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Setup some standard flags.                                      */
 /* -------------------------------------------------------------------- */
-    TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
-    TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
-    TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerSample );
+    TIFFSetField( l_hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
+    TIFFSetField( l_hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
+    TIFFSetField( l_hTIFF, TIFFTAG_BITSPERSAMPLE, l_nBitsPerSample );
 
+    uint16 l_nSampleFormat = 0;
     if( (eType == GDT_Byte && EQUAL(pszPixelType,"SIGNEDBYTE"))
         || eType == GDT_Int16 || eType == GDT_Int32 )
-        nSampleFormat = SAMPLEFORMAT_INT;
+        l_nSampleFormat = SAMPLEFORMAT_INT;
     else if( eType == GDT_CInt16 || eType == GDT_CInt32 )
-        nSampleFormat = SAMPLEFORMAT_COMPLEXINT;
+        l_nSampleFormat = SAMPLEFORMAT_COMPLEXINT;
     else if( eType == GDT_Float32 || eType == GDT_Float64 )
-        nSampleFormat = SAMPLEFORMAT_IEEEFP;
+        l_nSampleFormat = SAMPLEFORMAT_IEEEFP;
     else if( eType == GDT_CFloat32 || eType == GDT_CFloat64 )
-        nSampleFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
+        l_nSampleFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
     else
-        nSampleFormat = SAMPLEFORMAT_UINT;
+        l_nSampleFormat = SAMPLEFORMAT_UINT;
 
-    TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );
-    TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nBands );
-    TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanar );
+    TIFFSetField( l_hTIFF, TIFFTAG_SAMPLEFORMAT, l_nSampleFormat );
+    TIFFSetField( l_hTIFF, TIFFTAG_SAMPLESPERPIXEL, l_nBands );
+    TIFFSetField( l_hTIFF, TIFFTAG_PLANARCONFIG, nPlanar );
 
 /* -------------------------------------------------------------------- */
 /*      Setup Photometric Interpretation. Take this value from the user */
 /*      passed option or guess correct value otherwise.                 */
 /* -------------------------------------------------------------------- */
     int nSamplesAccountedFor = 1;
-    int bForceColorTable = FALSE;
+    bool bForceColorTable = false;
 
     pszValue = CSLFetchNameValue(papszParmList,"PHOTOMETRIC");
     if( pszValue != NULL )
     {
         if( EQUAL( pszValue, "MINISBLACK" ) )
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC,
+                          PHOTOMETRIC_MINISBLACK );
         else if( EQUAL( pszValue, "MINISWHITE" ) )
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE );
+        {
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC,
+                          PHOTOMETRIC_MINISWHITE );
+        }
         else if( EQUAL( pszValue, "PALETTE" ))
         {
             if( eType == GDT_Byte || eType == GDT_UInt16 )
             {
-                TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
+                TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC,
+                              PHOTOMETRIC_PALETTE );
                 nSamplesAccountedFor = 1;
-                bForceColorTable = TRUE;
+                bForceColorTable = true;
             }
             else
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "PHOTOMETRIC=PALETTE only compatible with Byte or UInt16");
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "PHOTOMETRIC=PALETTE only compatible with Byte or UInt16" );
             }
         }
         else if( EQUAL( pszValue, "RGB" ))
         {
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
             nSamplesAccountedFor = 3;
         }
         else if( EQUAL( pszValue, "CMYK" ))
         {
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED );
             nSamplesAccountedFor = 4;
         }
         else if( EQUAL( pszValue, "YCBCR" ))
         {
-            /* Because of subsampling, setting YCBCR without JPEG compression leads */
-            /* to a crash currently. Would need to make GTiffRasterBand::IWriteBlock() */
-            /* aware of subsampling so that it doesn't overrun buffer size returned */
-            /* by libtiff */
-            if ( nCompression != COMPRESSION_JPEG )
+            // Because of subsampling, setting YCBCR without JPEG compression
+            // leads to a crash currently. Would need to make
+            // GTiffRasterBand::IWriteBlock() aware of subsampling so that it
+            // doesn't overrun buffer size returned by libtiff.
+            if( l_nCompression != COMPRESSION_JPEG )
             {
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "Currently, PHOTOMETRIC=YCBCR requires COMPRESS=JPEG");
-                XTIFFClose(hTIFF);
-                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
+                XTIFFClose(l_hTIFF);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(l_fpL));
                 return NULL;
             }
 
-            if ( nPlanar == PLANARCONFIG_SEPARATE )
+            if( nPlanar == PLANARCONFIG_SEPARATE )
             {
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "PHOTOMETRIC=YCBCR requires INTERLEAVE=PIXEL");
-                XTIFFClose(hTIFF);
-                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
+                XTIFFClose(l_hTIFF);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(l_fpL));
                 return NULL;
             }
 
-            /* YCBCR strictly requires 3 bands. Not less, not more */
-            /* Issue an explicit error message as libtiff one is a bit cryptic : */
-            /* TIFFVStripSize64:Invalid td_samplesperpixel value */
-            if ( nBands != 3 )
+            // YCBCR strictly requires 3 bands. Not less, not more Issue an
+            // explicit error message as libtiff one is a bit cryptic:
+            // TIFFVStripSize64:Invalid td_samplesperpixel value.
+            if( l_nBands != 3 )
             {
-                CPLError(CE_Failure, CPLE_NotSupported,
-                         "PHOTOMETRIC=YCBCR requires a source raster with only 3 bands (RGB)");
-                XTIFFClose(hTIFF);
-                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
+                CPLError(
+                    CE_Failure, CPLE_NotSupported,
+                    "PHOTOMETRIC=YCBCR requires a source raster with "
+                    "only 3 bands (RGB)" );
+                XTIFFClose(l_hTIFF);
+                CPL_IGNORE_RET_VAL(VSIFCloseL(l_fpL));
                 return NULL;
             }
 
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR );
             nSamplesAccountedFor = 3;
+
+            // Explicitly register the subsampling so that JPEGFixupTags
+            // is a no-op (helps for cloud optimized geotiffs)
+            TIFFSetField( l_hTIFF, TIFFTAG_YCBCRSUBSAMPLING, 2, 2 );
         }
         else if( EQUAL( pszValue, "CIELAB" ))
         {
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CIELAB );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CIELAB );
             nSamplesAccountedFor = 3;
         }
         else if( EQUAL( pszValue, "ICCLAB" ))
         {
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ICCLAB );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ICCLAB );
             nSamplesAccountedFor = 3;
         }
         else if( EQUAL( pszValue, "ITULAB" ))
         {
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ITULAB );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_ITULAB );
             nSamplesAccountedFor = 3;
         }
         else
         {
             CPLError( CE_Warning, CPLE_IllegalArg,
-                      "PHOTOMETRIC=%s value not recognised, ignoring.\n"
+                      "PHOTOMETRIC=%s value not recognised, ignoring.  "
                       "Set the Photometric Interpretation as MINISBLACK.",
                       pszValue );
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
+            TIFFSetField(l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
         }
 
-        if ( nBands < nSamplesAccountedFor )
+        if( l_nBands < nSamplesAccountedFor )
         {
             CPLError( CE_Warning, CPLE_IllegalArg,
                       "PHOTOMETRIC=%s value does not correspond to number "
-                      "of bands (%d), ignoring.\n"
+                      "of bands (%d), ignoring.  "
                       "Set the Photometric Interpretation as MINISBLACK.",
-                      pszValue, nBands );
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
+                      pszValue, l_nBands );
+            TIFFSetField(l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
         }
     }
     else
     {
-        /*
-         * If image contains 3 or 4 bands and datatype is Byte then we will
-         * assume it is RGB. In all other cases assume it is MINISBLACK.
-         */
-        if( nBands == 3 && eType == GDT_Byte )
+        // If image contains 3 or 4 bands and datatype is Byte then we will
+        // assume it is RGB. In all other cases assume it is MINISBLACK.
+        if( l_nBands == 3 && eType == GDT_Byte )
         {
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
             nSamplesAccountedFor = 3;
         }
-        else if( nBands == 4 && eType == GDT_Byte )
+        else if( l_nBands == 4 && eType == GDT_Byte )
         {
-            uint16 v[1];
-
-            v[0] = GTiffGetAlphaValue(CSLFetchNameValue(papszParmList,"ALPHA"),
-                                      DEFAULT_ALPHA_TYPE);
+            uint16 v[1] = {
+                GTiffGetAlphaValue(CSLFetchNameValue(papszParmList, "ALPHA"),
+                                   DEFAULT_ALPHA_TYPE)
+            };
 
-            TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
+            TIFFSetField( l_hTIFF, TIFFTAG_EXTRASAMPLES, 1, v);
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB );
             nSamplesAccountedFor = 4;
         }
         else
         {
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK );
+            TIFFSetField(l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
             nSamplesAccountedFor = 1;
         }
     }
@@ -12758,80 +14698,79 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /*      If there are extra samples, we need to mark them with an        */
 /*      appropriate extrasamples definition here.                       */
 /* -------------------------------------------------------------------- */
-    if( nBands > nSamplesAccountedFor )
+    if( l_nBands > nSamplesAccountedFor )
     {
-        int nExtraSamples = nBands - nSamplesAccountedFor;
+        const int nExtraSamples = l_nBands - nSamplesAccountedFor;
 
-        uint16 *v = (uint16 *) CPLMalloc( sizeof(uint16) * nExtraSamples );
+        uint16 *v = static_cast<uint16 *>(
+            CPLMalloc( sizeof(uint16) * nExtraSamples ) );
 
-        v[0] = GTiffGetAlphaValue(CSLFetchNameValue(papszParmList, "ALPHA"),
-                                  EXTRASAMPLE_UNSPECIFIED);
+        v[0] = GTiffGetAlphaValue( CSLFetchNameValue(papszParmList, "ALPHA"),
+                                   EXTRASAMPLE_UNSPECIFIED );
 
-        for( int i = 1; i < nExtraSamples; i++ )
+        for( int i = 1; i < nExtraSamples; ++i )
             v[i] = EXTRASAMPLE_UNSPECIFIED;
 
-        TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples, v );
+        TIFFSetField(l_hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples, v );
 
         CPLFree(v);
     }
 
-    /* Set the ICC color profile. */
-    if (!EQUAL(pszProfile,"BASELINE"))
+    // Set the ICC color profile.
+    if( !EQUAL(pszProfile,"BASELINE") )
     {
-        SaveICCProfile(NULL, hTIFF, papszParmList, nBitsPerSample);
+        SaveICCProfile(NULL, l_hTIFF, papszParmList, l_nBitsPerSample);
     }
 
-    /* Set the compression method before asking the default strip size */
-    /* This is useful when translating to a JPEG-In-TIFF file where */
-    /* the default strip size is 8 or 16 depending on the photometric value */
-    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompression );
+    // Set the compression method before asking the default strip size
+    // This is useful when translating to a JPEG-In-TIFF file where
+    // the default strip size is 8 or 16 depending on the photometric value.
+    TIFFSetField( l_hTIFF, TIFFTAG_COMPRESSION, l_nCompression );
 
 /* -------------------------------------------------------------------- */
 /*      Setup tiling/stripping flags.                                   */
 /* -------------------------------------------------------------------- */
     if( bTiled )
     {
-        if( nBlockXSize == 0 )
-            nBlockXSize = 256;
+        if( l_nBlockXSize == 0 )
+            l_nBlockXSize = 256;
 
-        if( nBlockYSize == 0 )
-            nBlockYSize = 256;
+        if( l_nBlockYSize == 0 )
+            l_nBlockYSize = 256;
 
-        if (!TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize ) ||
-            !TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize ))
+        if( !TIFFSetField( l_hTIFF, TIFFTAG_TILEWIDTH, l_nBlockXSize ) ||
+            !TIFFSetField( l_hTIFF, TIFFTAG_TILELENGTH, l_nBlockYSize ) )
         {
-            XTIFFClose(hTIFF);
-            CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
+            XTIFFClose(l_hTIFF);
+            CPL_IGNORE_RET_VAL(VSIFCloseL(l_fpL));
             return NULL;
         }
     }
     else
     {
-        const uint32 nRowsPerStrip = MIN(nYSize,
-            (nBlockYSize == 0
-            ? static_cast<int>(TIFFDefaultStripSize(hTIFF,0))
-            : nBlockYSize) );
+        const uint32 l_nRowsPerStrip = std::min(nYSize,
+            l_nBlockYSize == 0
+            ? static_cast<int>(TIFFDefaultStripSize(l_hTIFF,0))
+            : l_nBlockYSize );
 
-        TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nRowsPerStrip );
+        TIFFSetField( l_hTIFF, TIFFTAG_ROWSPERSTRIP, l_nRowsPerStrip );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set compression related tags.                                   */
 /* -------------------------------------------------------------------- */
-    if ( nCompression == COMPRESSION_LZW ||
-         nCompression == COMPRESSION_ADOBE_DEFLATE )
-        TIFFSetField( hTIFF, TIFFTAG_PREDICTOR, nPredictor );
-    if (nCompression == COMPRESSION_ADOBE_DEFLATE
-        && nZLevel != -1)
-        TIFFSetField( hTIFF, TIFFTAG_ZIPQUALITY, nZLevel );
-    else if( nCompression == COMPRESSION_JPEG
-        && nJpegQuality != -1 )
-        TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nJpegQuality );
-    else if( nCompression == COMPRESSION_LZMA && nLZMAPreset != -1)
-        TIFFSetField( hTIFF, TIFFTAG_LZMAPRESET, nLZMAPreset );
+    if( l_nCompression == COMPRESSION_LZW ||
+         l_nCompression == COMPRESSION_ADOBE_DEFLATE )
+        TIFFSetField( l_hTIFF, TIFFTAG_PREDICTOR, nPredictor );
+    if( l_nCompression == COMPRESSION_ADOBE_DEFLATE && l_nZLevel != -1 )
+        TIFFSetField( l_hTIFF, TIFFTAG_ZIPQUALITY, l_nZLevel );
+    else if( l_nCompression == COMPRESSION_JPEG && l_nJpegQuality != -1 )
+        TIFFSetField( l_hTIFF, TIFFTAG_JPEGQUALITY, l_nJpegQuality );
+    else if( l_nCompression == COMPRESSION_LZMA && l_nLZMAPreset != -1)
+        TIFFSetField( l_hTIFF, TIFFTAG_LZMAPRESET, l_nLZMAPreset );
 
-    if( nCompression == COMPRESSION_JPEG )
-        TIFFSetField( hTIFF, TIFFTAG_JPEGTABLESMODE, nJpegTablesMode );
+    if( l_nCompression == COMPRESSION_JPEG )
+        TIFFSetField( l_hTIFF, TIFFTAG_JPEGTABLESMODE, l_nJpegTablesMode );
 
 /* -------------------------------------------------------------------- */
 /*      If we forced production of a file with photometric=palette,     */
@@ -12839,36 +14778,32 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     if( bForceColorTable )
     {
-        int nColors;
-
-        if( eType == GDT_Byte )
-            nColors = 256;
-        else
-            nColors = 65536;
-
-        unsigned short *panTRed, *panTGreen, *panTBlue;
+        const int nColors = eType == GDT_Byte ? 256 : 65536;
 
-        panTRed = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
-        panTGreen = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
-        panTBlue = (unsigned short *) CPLMalloc(sizeof(unsigned short)*nColors);
+        unsigned short *panTRed = static_cast<unsigned short *>(
+            CPLMalloc(sizeof(unsigned short)*nColors) );
+        unsigned short *panTGreen = static_cast<unsigned short *>(
+            CPLMalloc(sizeof(unsigned short)*nColors) );
+        unsigned short *panTBlue = static_cast<unsigned short *>(
+            CPLMalloc(sizeof(unsigned short)*nColors) );
 
-        for( int iColor = 0; iColor < nColors; iColor++ )
+        for( int iColor = 0; iColor < nColors; ++iColor )
         {
             if( eType == GDT_Byte )
             {
-                panTRed[iColor] = (unsigned short) (257 * iColor);
-                panTGreen[iColor] = (unsigned short) (257 * iColor);
-                panTBlue[iColor] = (unsigned short) (257 * iColor);
+                panTRed[iColor] = static_cast<unsigned short>(257 * iColor);
+                panTGreen[iColor] = static_cast<unsigned short>(257 * iColor);
+                panTBlue[iColor] = static_cast<unsigned short>(257 * iColor);
             }
             else
             {
-                panTRed[iColor] = (unsigned short) iColor;
-                panTGreen[iColor] = (unsigned short) iColor;
-                panTBlue[iColor] = (unsigned short) iColor;
+                panTRed[iColor] = static_cast<unsigned short>(iColor);
+                panTGreen[iColor] = static_cast<unsigned short>(iColor);
+                panTBlue[iColor] = static_cast<unsigned short>(iColor);
             }
         }
 
-        TIFFSetField( hTIFF, TIFFTAG_COLORMAP,
+        TIFFSetField( l_hTIFF, TIFFTAG_COLORMAP,
                       panTRed, panTGreen, panTBlue );
 
         CPLFree( panTRed );
@@ -12876,105 +14811,163 @@ TIFF *GTiffDataset::CreateLL( const char * pszFilename,
         CPLFree( panTBlue );
     }
 
-    /* Would perhaps works with libtiff 3.X but didn't bother trying */
-    /* This trick creates a temporary in-memory file and fetches its JPEG tables */
-    /* so that we can directly set them, before tif_jpeg.c compute them at */
-    /* the first strip/tile writing, which is too late, since we have already */
-    /* crystalized the directory. This way we avoid a directory rewriting */
+    // Would perhaps works with libtiff 3.X but didn't bother trying This trick
+    // creates a temporary in-memory file and fetches its JPEG tables so that
+    // we can directly set them, before tif_jpeg.c compute them at the first
+    // strip/tile writing, which is too late, since we have already crystalized
+    // the directory. This way we avoid a directory rewriting.
 #if defined(BIGTIFF_SUPPORT)
-    if( nCompression == COMPRESSION_JPEG &&
-        !STARTS_WITH(pszFilename, "/vsimem/gtiffdataset_jpg_tmp_") &&
-        CPLTestBool(CSLFetchNameValueDef(papszParmList, "WRITE_JPEGTABLE_TAG", "YES")) )
+    if( l_nCompression == COMPRESSION_JPEG &&
+        !STARTS_WITH(pszFilename, szJPEGGTiffDatasetTmpPrefix) &&
+        CPLTestBool(
+            CSLFetchNameValueDef(papszParmList, "WRITE_JPEGTABLE_TAG", "YES")) )
     {
-        CPLString osTmpFilenameIn;
-        osTmpFilenameIn.Printf("/vsimem/gtiffdataset_jpg_tmp_%p", hTIFF);
-        VSILFILE* fpTmp = NULL;
-        CPLString osTmp;
-        char** papszLocalParameters = NULL;
-        papszLocalParameters = CSLSetNameValue(papszLocalParameters,
-                                               "COMPRESS", "JPEG");
-        papszLocalParameters = CSLSetNameValue(papszLocalParameters,
-                "JPEG_QUALITY", CSLFetchNameValue(papszParmList, "JPEG_QUALITY"));
-        papszLocalParameters = CSLSetNameValue(papszLocalParameters,
-                "PHOTOMETRIC", CSLFetchNameValue(papszParmList, "PHOTOMETRIC"));
-        papszLocalParameters = CSLSetNameValue(papszLocalParameters,
-                                               "BLOCKYSIZE", "16");
-        papszLocalParameters = CSLSetNameValue(papszLocalParameters,
-                "NBITS", CSLFetchNameValue(papszParmList, "NBITS"));
-        papszLocalParameters = CSLSetNameValue(papszLocalParameters,
-                "JPEGTABLESMODE", CSLFetchNameValue(papszParmList, "JPEGTABLESMODE"));
-        TIFF* hTIFFTmp = CreateLL( osTmpFilenameIn, 16, 16, (nBands <= 4) ? nBands : 1,
-                                   eType, 0.0, papszLocalParameters, &fpTmp, osTmp );
-        CSLDestroy(papszLocalParameters);
-        if( hTIFFTmp )
-        {
-            uint16 nPhotometric;
-            int nJpegTablesModeIn;
-            TIFFGetField( hTIFFTmp, TIFFTAG_PHOTOMETRIC, &(nPhotometric) );
-            TIFFGetField( hTIFFTmp, TIFFTAG_JPEGTABLESMODE, &nJpegTablesModeIn );
-            TIFFWriteCheck( hTIFFTmp, FALSE, "CreateLL" );
-            TIFFWriteDirectory( hTIFFTmp );
-            TIFFSetDirectory( hTIFFTmp, 0 );
-            // Now, reset quality and jpegcolormode.
-            if(nJpegQuality > 0)
-                TIFFSetField(hTIFFTmp, TIFFTAG_JPEGQUALITY, nJpegQuality);
-            if( nPhotometric == PHOTOMETRIC_YCBCR
-                && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
-                                                    "YES") ) )
-            {
-                TIFFSetField(hTIFFTmp, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
-            }
-            if (nJpegTablesModeIn >= 0 )
-                TIFFSetField(hTIFFTmp, TIFFTAG_JPEGTABLESMODE, nJpegTablesModeIn);
-
-            GByte abyZeroData[(16*16*4*3)/2];
-            memset(abyZeroData, 0, (16*16*4*3)/2);
-            int nBlockSize = 16 * 16 * ((nBands <= 4) ? nBands : 1);
-            if( nBitsPerSample == 12 )
-               nBlockSize = (nBlockSize * 3) / 2;
-            TIFFWriteEncodedStrip( hTIFFTmp, 0, abyZeroData, nBlockSize);
+        GTiffWriteJPEGTables( l_hTIFF,
+                              CSLFetchNameValue(papszParmList, "PHOTOMETRIC"),
+                              CSLFetchNameValue(papszParmList, "JPEG_QUALITY"),
+                              CSLFetchNameValue(papszParmList,
+                                                "JPEGTABLESMODE") );
+    }
+#endif
 
-            uint32 nJPEGTableSize = 0;
-            void* pJPEGTable = NULL;
-            if( TIFFGetField(hTIFFTmp, TIFFTAG_JPEGTABLES, &nJPEGTableSize, &pJPEGTable) )
-                TIFFSetField(hTIFF, TIFFTAG_JPEGTABLES, nJPEGTableSize, pJPEGTable);
+    *pfpL = l_fpL;
+
+    return l_hTIFF;
+}
 
-            float *ref;
-            if( TIFFGetField(hTIFFTmp, TIFFTAG_REFERENCEBLACKWHITE, &ref) )
-                TIFFSetField(hTIFF, TIFFTAG_REFERENCEBLACKWHITE, ref);
+/************************************************************************/
+/*                      GTiffWriteJPEGTables()                          */
+/*                                                                      */
+/*      Sets the TIFFTAG_JPEGTABLES (and TIFFTAG_REFERENCEBLACKWHITE)   */
+/*      tags immediately, instead of relying on the TIFF JPEG codec     */
+/*      to write them when it starts compressing imagery. This avoids   */
+/*      an IFD rewrite at the end of the file.                          */
+/*      Must be used after having set TIFFTAG_SAMPLESPERPIXEL,          */
+/*      TIFFTAG_BITSPERSAMPLE.                                          */
+/************************************************************************/
+
+void GTiffWriteJPEGTables( TIFF* hTIFF,
+                           const char* pszPhotometric,
+                           const char* pszJPEGQuality,
+                           const char* pszJPEGTablesMode )
+{
+    // Would perhaps works with libtiff 3.X but didn't bother trying This trick
+    // creates a temporary in-memory file and fetches its JPEG tables so that
+    // we can directly set them, before tif_jpeg.c compute them at the first
+    // strip/tile writing, which is too late, since we have already crystalized
+    // the directory. This way we avoid a directory rewriting.
+#if defined(BIGTIFF_SUPPORT)
+    uint16 nBands = 0;
+    if( !TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL,
+                        &nBands ) )
+        nBands = 1;
+
+    uint16 l_nBitsPerSample = 0;
+    if( !TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE,
+                        &(l_nBitsPerSample)) )
+        l_nBitsPerSample = 1;
 
-            XTIFFClose(hTIFFTmp);
-            CPL_IGNORE_RET_VAL(VSIFCloseL(fpTmp));
+    CPLString osTmpFilenameIn;
+    osTmpFilenameIn.Printf("%s%p", szJPEGGTiffDatasetTmpPrefix, hTIFF);
+    VSILFILE* fpTmp = NULL;
+    CPLString osTmp;
+    char** papszLocalParameters = NULL;
+    const int nInMemImageWidth = 16;
+    const int nInMemImageHeight = 16;
+    papszLocalParameters = CSLSetNameValue( papszLocalParameters,
+                                            "COMPRESS", "JPEG" );
+    papszLocalParameters = CSLSetNameValue( papszLocalParameters,
+                                            "JPEG_QUALITY",
+                                            pszJPEGQuality );
+    papszLocalParameters = CSLSetNameValue( papszLocalParameters,
+                                            "PHOTOMETRIC", pszPhotometric );
+    papszLocalParameters = CSLSetNameValue( papszLocalParameters,
+                                            "BLOCKYSIZE",
+                                            CPLSPrintf("%u", nInMemImageHeight)
+                                          );
+    papszLocalParameters = CSLSetNameValue( papszLocalParameters,
+                                            "NBITS",
+                                            CPLSPrintf("%u", l_nBitsPerSample));
+    papszLocalParameters = CSLSetNameValue( papszLocalParameters,
+                                            "JPEGTABLESMODE",
+                                            pszJPEGTablesMode );
+
+    TIFF* hTIFFTmp = GTiffDataset::CreateLL(
+                    osTmpFilenameIn, nInMemImageWidth, nInMemImageHeight,
+                    (nBands <= 4) ? nBands : 1,
+                    (l_nBitsPerSample <= 8) ? GDT_Byte : GDT_UInt16, 0.0,
+                    papszLocalParameters, &fpTmp, osTmp );
+    CSLDestroy(papszLocalParameters);
+    if( hTIFFTmp )
+    {
+        uint16 l_nPhotometric = 0;
+        int nJpegTablesModeIn = 0;
+        TIFFGetField( hTIFFTmp, TIFFTAG_PHOTOMETRIC, &(l_nPhotometric) );
+        TIFFGetField( hTIFFTmp, TIFFTAG_JPEGTABLESMODE,
+                        &nJpegTablesModeIn );
+        TIFFWriteCheck( hTIFFTmp, FALSE, "CreateLL" );
+        TIFFWriteDirectory( hTIFFTmp );
+        TIFFSetDirectory( hTIFFTmp, 0 );
+        // Now, reset quality and jpegcolormode.
+        const int l_nJpegQuality = pszJPEGQuality ? atoi(pszJPEGQuality) : 0;
+        if(l_nJpegQuality > 0)
+            TIFFSetField(hTIFFTmp, TIFFTAG_JPEGQUALITY, l_nJpegQuality);
+        if( l_nPhotometric == PHOTOMETRIC_YCBCR
+            && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
+                                                "YES") ) )
+        {
+            TIFFSetField( hTIFFTmp, TIFFTAG_JPEGCOLORMODE,
+                            JPEGCOLORMODE_RGB);
         }
-        VSIUnlink(osTmpFilenameIn);
-    }
-#endif
+        if( nJpegTablesModeIn >= 0 )
+            TIFFSetField( hTIFFTmp, TIFFTAG_JPEGTABLESMODE,
+                            nJpegTablesModeIn);
+
+        int nBlockSize = nInMemImageWidth * nInMemImageHeight *
+                                        ((nBands <= 4) ? nBands : 1);
+        if( l_nBitsPerSample == 12 )
+            nBlockSize = (nBlockSize * 3) / 2;
+        std::vector<GByte> abyZeroData( nBlockSize, 0 );
+        TIFFWriteEncodedStrip( hTIFFTmp, 0, &abyZeroData[0], nBlockSize);
+
+        uint32 nJPEGTableSize = 0;
+        void* pJPEGTable = NULL;
+        if( TIFFGetField( hTIFFTmp, TIFFTAG_JPEGTABLES, &nJPEGTableSize,
+                            &pJPEGTable) )
+            TIFFSetField( hTIFF, TIFFTAG_JPEGTABLES, nJPEGTableSize,
+                            pJPEGTable);
 
-    *pfpL = fpL;
+        float *ref = NULL;
+        if( TIFFGetField(hTIFFTmp, TIFFTAG_REFERENCEBLACKWHITE, &ref) )
+            TIFFSetField(hTIFF, TIFFTAG_REFERENCEBLACKWHITE, ref);
 
-    return( hTIFF );
+        XTIFFClose(hTIFFTmp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTmp));
+    }
+    VSIUnlink(osTmpFilenameIn);
+#endif
 }
 
 /************************************************************************/
-/*                              GuessJPEGQuality()                      */
+/*                            GuessJPEGQuality()                        */
 /*                                                                      */
 /*      Guess JPEG quality from JPEGTABLES tag.                         */
 /************************************************************************/
 
-static const GByte* GTIFFFindNextTable(const GByte* paby, GByte byMarker,
-                                       int nLen, int* pnLenTable)
+static const GByte* GTIFFFindNextTable( const GByte* paby, GByte byMarker,
+                                        int nLen, int* pnLenTable )
 {
-    for(int i = 0; i+1 < nLen; )
+    for( int i = 0; i + 1 < nLen; )
     {
         if( paby[i] != 0xFF )
             return NULL;
-        i ++;
+        ++i;
         if( paby[i] == 0xD8 )
         {
-            i ++;
+            ++i;
             continue;
         }
-        if( i+2 >= nLen )
+        if( i + 2 >= nLen )
             return NULL;
         int nMarkerLen = paby[i+1] * 256 + paby[i+2];
         if( i+1+nMarkerLen >= nLen )
@@ -12989,54 +14982,60 @@ static const GByte* GTIFFFindNextTable(const GByte* paby, GByte byMarker,
     return NULL;
 }
 
-/* We assume that if there are several quantization tables, they are */
-/* in the same order. Which is a reasonable assumption for updating */
-/* a file generated by ourselves */
-static int GTIFFQuantizationTablesEqual(const GByte* paby1, int nLen1,
-                                        const GByte* paby2, int nLen2)
+// We assume that if there are several quantization tables, they are
+// in the same order. Which is a reasonable assumption for updating
+// a file generated by ourselves.
+static bool GTIFFQuantizationTablesEqual( const GByte* paby1, int nLen1,
+                                          const GByte* paby2, int nLen2 )
 {
-    int bFound = FALSE;
-    while(true)
+    bool bFound = false;
+    while( true )
     {
         int nLenTable1 = 0;
         int nLenTable2 = 0;
-        const GByte* paby1New = GTIFFFindNextTable(paby1, 0xDB, nLen1, &nLenTable1);
-        const GByte* paby2New = GTIFFFindNextTable(paby2, 0xDB, nLen2, &nLenTable2);
+        const GByte* paby1New =
+            GTIFFFindNextTable(paby1, 0xDB, nLen1, &nLenTable1);
+        const GByte* paby2New =
+            GTIFFFindNextTable(paby2, 0xDB, nLen2, &nLenTable2);
         if( paby1New == NULL && paby2New == NULL )
             return bFound;
         if( paby1New == NULL && paby2New != NULL )
-            return FALSE;
+            return false;
         if( paby1New != NULL && paby2New == NULL )
-            return FALSE;
+            return false;
         if( nLenTable1 != nLenTable2 )
-            return FALSE;
+            return false;
         if( memcmp(paby1New, paby2New, nLenTable1) != 0 )
-            return FALSE;
+            return false;
         paby1New += nLenTable1;
         paby2New += nLenTable2;
         nLen1 -= static_cast<int>(paby1New - paby1);
         nLen2 -= static_cast<int>(paby2New - paby2);
         paby1 = paby1New;
         paby2 = paby2New;
-        bFound = TRUE;
+        bFound = true;
     }
 }
 
-int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
-                                   int& bOutHasHuffmanTable)
+int GTiffDataset::GuessJPEGQuality( bool& bOutHasQuantizationTable,
+                                    bool& bOutHasHuffmanTable )
 {
     CPLAssert( nCompression == COMPRESSION_JPEG );
     uint32 nJPEGTableSize = 0;
     void* pJPEGTable = NULL;
     if( !TIFFGetField(hTIFF, TIFFTAG_JPEGTABLES, &nJPEGTableSize, &pJPEGTable) )
     {
-        bOutHasQuantizationTable = FALSE;
-        bOutHasHuffmanTable = FALSE;
+        bOutHasQuantizationTable = false;
+        bOutHasHuffmanTable = false;
         return -1;
     }
 
-    bOutHasQuantizationTable = GTIFFFindNextTable((const GByte*)pJPEGTable, 0xDB, nJPEGTableSize, NULL) != NULL;
-    bOutHasHuffmanTable = GTIFFFindNextTable((const GByte*)pJPEGTable, 0xC4, nJPEGTableSize, NULL) != NULL;
+    bOutHasQuantizationTable =
+        GTIFFFindNextTable( (const GByte*)pJPEGTable, 0xDB,
+                            nJPEGTableSize, NULL) != NULL;
+    bOutHasHuffmanTable =
+        GTIFFFindNextTable( (const GByte*)pJPEGTable, 0xC4,
+                            nJPEGTableSize, NULL) != NULL;
     if( !bOutHasQuantizationTable )
         return -1;
 
@@ -13056,10 +15055,11 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
                                                 "NBITS", "12");
 
     CPLString osTmpFilenameIn;
-    osTmpFilenameIn.Printf("/vsimem/gtiffdataset_guess_jpeg_quality_tmp_%p", this);
+    osTmpFilenameIn.Printf( "/vsimem/gtiffdataset_guess_jpeg_quality_tmp_%p",
+                            this );
 
     int nRet = -1;
-    for(int nQuality=0;nQuality<=100 && nRet < 0;nQuality++)
+    for( int nQuality = 0; nQuality <= 100 && nRet < 0; ++nQuality )
     {
         VSILFILE* fpTmp = NULL;
         if( nQuality == 0 )
@@ -13071,9 +15071,10 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
 
         CPLPushErrorHandler(CPLQuietErrorHandler);
         CPLString osTmp;
-        TIFF* hTIFFTmp = CreateLL( osTmpFilenameIn, 16, 16, (nBands <= 4) ? nBands : 1,
-                                   GetRasterBand(1)->GetRasterDataType(), 0.0,
-                                   papszLocalParameters, &fpTmp, osTmp );
+        TIFF* hTIFFTmp =
+            CreateLL( osTmpFilenameIn, 16, 16, (nBands <= 4) ? nBands : 1,
+                      GetRasterBand(1)->GetRasterDataType(), 0.0,
+                      papszLocalParameters, &fpTmp, osTmp );
         CPLPopErrorHandler();
         if( !hTIFFTmp )
         {
@@ -13091,9 +15092,9 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
             TIFFSetField(hTIFFTmp, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
         }
 
-        GByte abyZeroData[(16*16*4*3)/2];
-        memset(abyZeroData, 0, (16*16*4*3)/2);
-        int nBlockSize = (16 * 16 * ((nBands <= 4) ? nBands : 1) * nBitsPerSample) / 8;
+        GByte abyZeroData[(16*16*4*3)/2] = {};
+        const int nBlockSize =
+            (16 * 16 * ((nBands <= 4) ? nBands : 1) * nBitsPerSample) / 8;
         TIFFWriteEncodedStrip( hTIFFTmp, 0, abyZeroData, nBlockSize);
 
         uint32 nJPEGTableSizeTry = 0;
@@ -13101,21 +15102,118 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
         if( TIFFGetField(hTIFFTmp, TIFFTAG_JPEGTABLES,
                          &nJPEGTableSizeTry, &pJPEGTableTry) )
         {
-            if( GTIFFQuantizationTablesEqual((GByte*)pJPEGTable, nJPEGTableSize,
-                                             (GByte*)pJPEGTableTry, nJPEGTableSizeTry) )
+            if( GTIFFQuantizationTablesEqual(
+                   static_cast<GByte *>(pJPEGTable), nJPEGTableSize,
+                   static_cast<GByte *>(pJPEGTableTry), nJPEGTableSizeTry) )
             {
                 nRet = (nQuality == 0 ) ? 75 : nQuality;
             }
         }
 
-        XTIFFClose(hTIFFTmp);
-        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTmp));
+        XTIFFClose(hTIFFTmp);
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpTmp));
+    }
+
+    CSLDestroy(papszLocalParameters);
+    VSIUnlink(osTmpFilenameIn);
+
+    return nRet;
+}
+
+/************************************************************************/
+/*               SetJPEGQualityAndTablesModeFromFile()                  */
+/************************************************************************/
+
+void GTiffDataset::SetJPEGQualityAndTablesModeFromFile()
+{
+    bool bHasQuantizationTable = false;
+    bool bHasHuffmanTable = false;
+    int nQuality = GuessJPEGQuality( bHasQuantizationTable,
+                                     bHasHuffmanTable );
+    if( nQuality > 0 )
+    {
+        CPLDebug("GTiff", "Guessed JPEG quality to be %d", nQuality);
+        nJpegQuality = nQuality;
+        TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, nQuality );
+
+        // This means we will use the quantization tables from the
+        // JpegTables tag.
+        nJpegTablesMode = JPEGTABLESMODE_QUANT;
+    }
+    else
+    {
+        uint32 nJPEGTableSize = 0;
+        void* pJPEGTable = NULL;
+        if( !TIFFGetField( hTIFF, TIFFTAG_JPEGTABLES,
+                            &nJPEGTableSize, &pJPEGTable) )
+        {
+            toff_t *panByteCounts = NULL;
+            const int nBlockCount =
+                nPlanarConfig == PLANARCONFIG_SEPARATE
+                ? nBlocksPerBand * nBands
+                : nBlocksPerBand;
+            if( TIFFIsTiled( hTIFF ) )
+                TIFFGetField( hTIFF, TIFFTAG_TILEBYTECOUNTS,
+                                &panByteCounts );
+            else
+                TIFFGetField( hTIFF, TIFFTAG_STRIPBYTECOUNTS,
+                                &panByteCounts );
+
+            bool bFoundNonEmptyBlock = false;
+            if( panByteCounts != NULL )
+            {
+                for( int iBlock = 0; iBlock < nBlockCount; ++iBlock )
+                {
+                    if( panByteCounts[iBlock] != 0 )
+                    {
+                        bFoundNonEmptyBlock = true;
+                        break;
+                    }
+                }
+            }
+            if( bFoundNonEmptyBlock )
+            {
+                CPLDebug("GTiff", "Could not guess JPEG quality. "
+                            "JPEG tables are missing, so going in "
+                            "TIFFTAG_JPEGTABLESMODE = 0/2 mode");
+                // Write quantization tables in each strile.
+                nJpegTablesMode = 0;
+            }
+        }
+        else
+        {
+            if( bHasQuantizationTable )
+            {
+                // FIXME in libtiff: this is likely going to cause issues
+                // since libtiff will reuse in each strile the number of
+                // the global quantization table, which is invalid.
+                CPLDebug(
+                    "GTiff", "Could not guess JPEG quality although JPEG "
+                    "quantization tables are present, so going in "
+                    "TIFFTAG_JPEGTABLESMODE = 0/2 mode" );
+            }
+            else
+            {
+                CPLDebug("GTiff", "Could not guess JPEG quality since JPEG "
+                        "quantization tables are not present, so going in "
+                        "TIFFTAG_JPEGTABLESMODE = 0/2 mode");
+            }
+
+            // Write quantization tables in each strile.
+            nJpegTablesMode = 0;
+        }
     }
-
-    CSLDestroy(papszLocalParameters);
-    VSIUnlink(osTmpFilenameIn);
-
-    return nRet;
+    if( bHasHuffmanTable )
+    {
+        // If there are Huffman tables in header use them, otherwise
+        // if we use optimized tables, libtiff will currently reuse
+        // the number of the Huffman tables of the header for the
+        // optimized version of each strile, which is illegal.
+        nJpegTablesMode |= JPEGTABLESMODE_HUFF;
+    }
+    if( nJpegTablesMode >= 0 )
+        TIFFSetField( hTIFF, TIFFTAG_JPEGTABLESMODE,
+                        nJpegTablesMode);
 }
 
 /************************************************************************/
@@ -13125,41 +15223,40 @@ int GTiffDataset::GuessJPEGQuality(int& bOutHasQuantizationTable,
 /************************************************************************/
 
 GDALDataset *GTiffDataset::Create( const char * pszFilename,
-                                   int nXSize, int nYSize, int nBands,
+                                   int nXSize, int nYSize, int l_nBands,
                                    GDALDataType eType,
                                    char **papszParmList )
 
 {
-    GTiffDataset *poDS;
-    TIFF *hTIFF;
-    VSILFILE* fpL = NULL;
-    CPLString           osTmpFilename;
+    VSILFILE* l_fpL = NULL;
+    CPLString l_osTmpFilename;
 
 /* -------------------------------------------------------------------- */
 /*      Create the underlying TIFF file.                                */
 /* -------------------------------------------------------------------- */
-    hTIFF = CreateLL( pszFilename,
-                      nXSize, nYSize, nBands,
-                      eType, 0, papszParmList, &fpL, osTmpFilename );
-    int bStreaming = (osTmpFilename.size() != 0);
+    TIFF *l_hTIFF = CreateLL(
+        pszFilename,
+        nXSize, nYSize, l_nBands,
+        eType, 0, papszParmList, &l_fpL, l_osTmpFilename );
+    const bool bStreaming = !l_osTmpFilename.empty();
 
-    if( hTIFF == NULL )
+    if( l_hTIFF == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create the new GTiffDataset object.                             */
 /* -------------------------------------------------------------------- */
-    poDS = new GTiffDataset();
-    poDS->hTIFF = hTIFF;
-    poDS->fpL = fpL;
+    GTiffDataset *poDS = new GTiffDataset();
+    poDS->hTIFF = l_hTIFF;
+    poDS->fpL = l_fpL;
     if( bStreaming )
     {
-        poDS->bStreamingOut = TRUE;
-        poDS->osTmpFilename = osTmpFilename;
+        poDS->bStreamingOut = true;
+        poDS->osTmpFilename = l_osTmpFilename;
         poDS->fpToWrite = VSIFOpenL( pszFilename, "wb" );
         if( poDS->fpToWrite == NULL )
         {
-            VSIUnlink(osTmpFilename);
+            VSIUnlink(l_osTmpFilename);
             delete poDS;
             return NULL;
         }
@@ -13170,38 +15267,41 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
     poDS->eAccess = GA_Update;
-    poDS->bCrystalized = FALSE;
-    poDS->nSamplesPerPixel = (uint16) nBands;
+    poDS->bCrystalized = false;
+    poDS->nSamplesPerPixel = (uint16) l_nBands;
     poDS->osFilename = pszFilename;
- 
-    // Don't try to load external metadata files (#6597)
-    poDS->bIMDRPCMetadataLoaded = TRUE;
-
-    /* Avoid premature crystalization that will cause directory re-writing */
-    /* if GetProjectionRef() or GetGeoTransform() are called on the newly created GeoTIFF */
-    poDS->bLookedForProjection = TRUE;
-
-    TIFFGetField( hTIFF, TIFFTAG_SAMPLEFORMAT, &(poDS->nSampleFormat) );
-    TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(poDS->nPlanarConfig) );
-    // Weird that we need this, but otherwise we get a Valgrind warning on tiff_write_124
-    if( !TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(poDS->nPhotometric) ) )
+
+    // Don't try to load external metadata files (#6597).
+    poDS->bIMDRPCMetadataLoaded = true;
+
+    // Avoid premature crystalization that will cause directory re-writing if
+    // GetProjectionRef() or GetGeoTransform() are called on the newly created
+    // GeoTIFF.
+    poDS->bLookedForProjection = true;
+
+    TIFFGetField( l_hTIFF, TIFFTAG_SAMPLEFORMAT, &(poDS->nSampleFormat) );
+    TIFFGetField( l_hTIFF, TIFFTAG_PLANARCONFIG, &(poDS->nPlanarConfig) );
+    // Weird that we need this, but otherwise we get a Valgrind warning on
+    // tiff_write_124.
+    if( !TIFFGetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, &(poDS->nPhotometric) ) )
         poDS->nPhotometric = PHOTOMETRIC_MINISBLACK;
-    TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &(poDS->nBitsPerSample) );
-    TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(poDS->nCompression) );
+    TIFFGetField( l_hTIFF, TIFFTAG_BITSPERSAMPLE, &(poDS->nBitsPerSample) );
+    TIFFGetField( l_hTIFF, TIFFTAG_COMPRESSION, &(poDS->nCompression) );
 
-    if( TIFFIsTiled(hTIFF) )
+    if( TIFFIsTiled(l_hTIFF) )
     {
-        TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(poDS->nBlockXSize) );
-        TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(poDS->nBlockYSize) );
+        TIFFGetField( l_hTIFF, TIFFTAG_TILEWIDTH, &(poDS->nBlockXSize) );
+        TIFFGetField( l_hTIFF, TIFFTAG_TILELENGTH, &(poDS->nBlockYSize) );
     }
     else
     {
-        if( !TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP,
+        if( !TIFFGetField( l_hTIFF, TIFFTAG_ROWSPERSTRIP,
                            &(poDS->nRowsPerStrip) ) )
-            poDS->nRowsPerStrip = 1; /* dummy value */
+            poDS->nRowsPerStrip = 1;  // Dummy value.
 
         poDS->nBlockXSize = nXSize;
-        poDS->nBlockYSize = MIN((int)poDS->nRowsPerStrip,nYSize);
+        poDS->nBlockYSize =
+            std::min( static_cast<int>(poDS->nRowsPerStrip) , nYSize );
     }
 
     poDS->nBlocksPerBand =
@@ -13218,39 +15318,41 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     if( poDS->nCompression == COMPRESSION_JPEG
         && poDS->nPhotometric == PHOTOMETRIC_YCBCR
-        && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB",
-                                              "YES") ) )
+        && CPLTestBool( CPLGetConfigOption("CONVERT_YCBCR_TO_RGB", "YES") ) )
     {
-        int nColorMode;
+        int nColorMode = 0;
 
-        poDS->SetMetadataItem( "SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE" );
-        if ( !TIFFGetField( hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode ) ||
-             nColorMode != JPEGCOLORMODE_RGB )
-            TIFFSetField(hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
+        poDS->SetMetadataItem("SOURCE_COLOR_SPACE", "YCbCr", "IMAGE_STRUCTURE");
+        if( !TIFFGetField( l_hTIFF, TIFFTAG_JPEGCOLORMODE, &nColorMode ) ||
+            nColorMode != JPEGCOLORMODE_RGB )
+            TIFFSetField(l_hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Read palette back as a color table if it has one.               */
 /* -------------------------------------------------------------------- */
-    unsigned short *panRed, *panGreen, *panBlue;
+    unsigned short *panRed = NULL;
+    unsigned short *panGreen = NULL;
+    unsigned short *panBlue = NULL;
 
     if( poDS->nPhotometric == PHOTOMETRIC_PALETTE
-        && TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
+        && TIFFGetField( l_hTIFF, TIFFTAG_COLORMAP,
                          &panRed, &panGreen, &panBlue) )
     {
-        int nColorCount;
-        GDALColorEntry oEntry;
 
         poDS->poColorTable = new GDALColorTable();
 
-        nColorCount = 1 << poDS->nBitsPerSample;
+        const int nColorCount = 1 << poDS->nBitsPerSample;
 
         for( int iColor = nColorCount - 1; iColor >= 0; iColor-- )
         {
-            oEntry.c1 = panRed[iColor] / 256;
-            oEntry.c2 = panGreen[iColor] / 256;
-            oEntry.c3 = panBlue[iColor] / 256;
-            oEntry.c4 = 255;
+            const unsigned short divisor = 256;
+            const GDALColorEntry oEntry = {
+                static_cast<short>(panRed[iColor] / divisor),
+                static_cast<short>(panGreen[iColor] / divisor),
+                static_cast<short>(panBlue[iColor] / divisor),
+                static_cast<short>(255)
+            };
 
             poDS->poColorTable->SetColorEntry( iColor, &oEntry );
         }
@@ -13260,8 +15362,23 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
 /*      Do we want to ensure all blocks get written out on close to     */
 /*      avoid sparse files?                                             */
 /* -------------------------------------------------------------------- */
-    if( !CSLFetchBoolean( papszParmList, "SPARSE_OK", FALSE ) )
-        poDS->bFillEmptyTiles = TRUE;
+    if( !CPLFetchBool( papszParmList, "SPARSE_OK", false ) )
+        poDS->bFillEmptyTilesAtClosing = true;
+
+    poDS->bWriteEmptyTiles = bStreaming ||
+        (poDS->nCompression != COMPRESSION_NONE &&
+         poDS->bFillEmptyTilesAtClosing);
+    // Only required for people writing non-compressed stripped files in the
+    // right order and wanting all tstrips to be written in the same order
+    // so that the end result can be memory mapped without knowledge of each
+    // strip offset.
+    if( CPLTestBool( CSLFetchNameValueDef( papszParmList,
+                              "WRITE_EMPTY_TILES_SYNCHRONOUSLY", "FALSE" )) ||
+         CPLTestBool( CSLFetchNameValueDef( papszParmList,
+                              "@WRITE_EMPTY_TILES_SYNCHRONOUSLY", "FALSE" )) )
+    {
+        poDS->bWriteEmptyTiles = true;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Preserve creation options for consulting later (for instance    */
@@ -13286,41 +15403,43 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
     {
         CPLDebug( "GDAL",
                   "Writing zero block to force creation of JPEG tables." );
-        if( TIFFIsTiled( hTIFF ) )
+        if( TIFFIsTiled( l_hTIFF ) )
         {
-            int cc = TIFFTileSize( hTIFF );
-            unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
-            TIFFWriteEncodedTile(hTIFF, 0, pabyZeros, cc);
+            const int cc = TIFFTileSize( l_hTIFF );
+            unsigned char *pabyZeros =
+                static_cast<unsigned char *>(CPLCalloc(cc, 1));
+            TIFFWriteEncodedTile(l_hTIFF, 0, pabyZeros, cc);
             CPLFree( pabyZeros );
         }
         else
         {
-            int cc = TIFFStripSize( hTIFF );
-            unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
-            TIFFWriteEncodedStrip(hTIFF, 0, pabyZeros, cc);
+            const int cc = TIFFStripSize( l_hTIFF );
+            unsigned char *pabyZeros =
+                static_cast<unsigned char *>(CPLCalloc(cc, 1));
+            TIFFWriteEncodedStrip(l_hTIFF, 0, pabyZeros, cc);
             CPLFree( pabyZeros );
         }
-        poDS->bDontReloadFirstBlock = TRUE;
+        poDS->bDontReloadFirstBlock = true;
     }
 #endif
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int iBand;
-
-    for( iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < l_nBands; ++iBand )
     {
         if( poDS->nBitsPerSample == 8 ||
-            poDS->nBitsPerSample == 16 ||
+            (poDS->nBitsPerSample == 16 && eType != GDT_Float32) ||
             poDS->nBitsPerSample == 32 ||
             poDS->nBitsPerSample == 64 ||
             poDS->nBitsPerSample == 128)
-            poDS->SetBand( iBand+1, new GTiffRasterBand( poDS, iBand+1 ) );
+        {
+            poDS->SetBand( iBand + 1, new GTiffRasterBand( poDS, iBand + 1 ) );
+        }
         else
         {
-            poDS->SetBand( iBand+1, new GTiffOddBitsBand( poDS, iBand+1 ) );
-            poDS->GetRasterBand( iBand+1 )->
+            poDS->SetBand( iBand + 1, new GTiffOddBitsBand( poDS, iBand + 1 ) );
+            poDS->GetRasterBand( iBand + 1 )->
                 SetMetadataItem( "NBITS",
                                  CPLString().Printf("%d",poDS->nBitsPerSample),
                                  "IMAGE_STRUCTURE" );
@@ -13329,14 +15448,14 @@ GDALDataset *GTiffDataset::Create( const char * pszFilename,
 
     poDS->GetDiscardLsbOption(papszParmList);
 
-    if( poDS->nPlanarConfig == PLANARCONFIG_CONTIG && nBands != 1 )
+    if( poDS->nPlanarConfig == PLANARCONFIG_CONTIG && l_nBands != 1 )
         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
     else
         poDS->SetMetadataItem( "INTERLEAVE", "BAND", "IMAGE_STRUCTURE" );
 
     poDS->oOvManager.Initialize( poDS, pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -13349,15 +15468,6 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                           GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    TIFF *hTIFF;
-    int nXSize = poSrcDS->GetRasterXSize();
-    int nYSize = poSrcDS->GetRasterYSize();
-    int nBands = poSrcDS->GetRasterCount();
-    CPLErr      eErr = CE_None;
-    uint16 nPlanarConfig;
-    uint16 nBitsPerSample;
-    GDALRasterBand *poPBand;
-
     if( poSrcDS->GetRasterCount() == 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -13365,28 +15475,33 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-    poPBand = poSrcDS->GetRasterBand(1);
-    GDALDataType eType = poPBand->GetRasterDataType();
+    GDALRasterBand * const poPBand = poSrcDS->GetRasterBand(1);
+    const GDALDataType eType = poPBand->GetRasterDataType();
 
 /* -------------------------------------------------------------------- */
 /*      Check, whether all bands in input dataset has the same type.    */
 /* -------------------------------------------------------------------- */
-    for ( int iBand = 2; iBand <= nBands; iBand++ )
+    const int l_nBands = poSrcDS->GetRasterCount();
+    for( int iBand = 2; iBand <= l_nBands; ++iBand )
     {
-        if ( eType != poSrcDS->GetRasterBand(iBand)->GetRasterDataType() )
+        if( eType != poSrcDS->GetRasterBand(iBand)->GetRasterDataType() )
         {
-            if ( bStrict )
+            if( bStrict )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Unable to export GeoTIFF file with different datatypes per\n"
-                          "different bands. All bands should have the same types in TIFF." );
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Unable to export GeoTIFF file with different datatypes "
+                    "per different bands. All bands should have the same "
+                    "types in TIFF." );
                 return NULL;
             }
             else
             {
-                CPLError( CE_Warning, CPLE_AppDefined,
-                          "Unable to export GeoTIFF file with different datatypes per\n"
-                          "different bands. All bands should have the same types in TIFF." );
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Unable to export GeoTIFF file with different datatypes "
+                    "per different bands. All bands should have the same "
+                    "types in TIFF." );
             }
         }
     }
@@ -13397,16 +15512,13 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Capture the profile.                                            */
 /* -------------------------------------------------------------------- */
-    const char          *pszProfile;
-    int                 bGeoTIFF;
-
-    pszProfile = CSLFetchNameValue(papszOptions,"PROFILE");
+    const char *pszProfile = CSLFetchNameValue(papszOptions, "PROFILE");
     if( pszProfile == NULL )
         pszProfile = "GDALGeoTIFF";
 
-    if( !EQUAL(pszProfile,"BASELINE")
-        && !EQUAL(pszProfile,"GeoTIFF")
-        && !EQUAL(pszProfile,"GDALGeoTIFF") )
+    if( !EQUAL(pszProfile, "BASELINE")
+        && !EQUAL(pszProfile, "GeoTIFF")
+        && !EQUAL(pszProfile, "GDALGeoTIFF") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "PROFILE=%s not supported in GTIFF driver.",
@@ -13414,15 +15526,12 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-    if( EQUAL(pszProfile,"BASELINE") )
-        bGeoTIFF = FALSE;
-    else
-        bGeoTIFF = TRUE;
+    const bool bGeoTIFF = !EQUAL(pszProfile, "BASELINE");
 
 /* -------------------------------------------------------------------- */
 /*      Special handling for NBITS.  Copy from band metadata if found.  */
 /* -------------------------------------------------------------------- */
-    char     **papszCreateOptions = CSLDuplicate( papszOptions );
+    char **papszCreateOptions = CSLDuplicate( papszOptions );
 
     if( poPBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) != NULL
         && atoi(poPBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" )) > 0
@@ -13447,7 +15556,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Color profile.  Copy from band metadata if found.              */
 /* -------------------------------------------------------------------- */
-    if (bGeoTIFF)
+    if( bGeoTIFF )
     {
         const char* pszOptionsMD[] = {
             "SOURCE_ICC_PROFILE",
@@ -13463,105 +15572,126 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             NULL
         };
 
-        /* Copy all the tags. Options will override tags in the source */
+        // Copy all the tags.  Options will override tags in the source.
         int i = 0;
         while(pszOptionsMD[i] != NULL)
         {
-            char const *pszMD = CSLFetchNameValue(papszOptions, pszOptionsMD[i]);
-            if (pszMD == NULL)
-                pszMD = poSrcDS->GetMetadataItem( pszOptionsMD[i], "COLOR_PROFILE" );
+            char const *pszMD =
+                CSLFetchNameValue(papszOptions, pszOptionsMD[i]);
+            if( pszMD == NULL )
+                pszMD = poSrcDS->GetMetadataItem( pszOptionsMD[i],
+                                                  "COLOR_PROFILE" );
 
-            if ((pszMD != NULL) && !EQUAL(pszMD, "") )
+            if( (pszMD != NULL) && !EQUAL(pszMD, "") )
             {
                 papszCreateOptions =
-                    CSLSetNameValue( papszCreateOptions, pszOptionsMD[i], pszMD );
+                    CSLSetNameValue( papszCreateOptions, pszOptionsMD[i],
+                                     pszMD );
 
-                /* If an ICC profile exists, other tags are not needed */
-                if (EQUAL(pszOptionsMD[i], "SOURCE_ICC_PROFILE"))
+                // If an ICC profile exists, other tags are not needed.
+                if( EQUAL(pszOptionsMD[i], "SOURCE_ICC_PROFILE") )
                     break;
             }
 
-            i++;
+            ++i;
         }
     }
 
-    int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
     double dfExtraSpaceForOverviews = 0;
-    if (nSrcOverviews != 0 &&
-        CSLFetchBoolean(papszOptions, "COPY_SRC_OVERVIEWS", FALSE))
+    if( CPLFetchBool(papszOptions, "COPY_SRC_OVERVIEWS", false) )
     {
-        for(int j=1;j<=nBands;j++)
+        const int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
+        if( nSrcOverviews )
         {
-            if( poSrcDS->GetRasterBand(j)->GetOverviewCount() != nSrcOverviews )
+            for( int j = 1; j <= l_nBands; ++j )
             {
-                CPLError( CE_Failure, CPLE_NotSupported,
-                  "COPY_SRC_OVERVIEWS cannot be used when the bands have not the same number of overview levels." );
-                CSLDestroy(papszCreateOptions);
-                return NULL;
-            }
-            for(int i=0;i<nSrcOverviews;i++)
-            {
-                GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(j)->GetOverview(i);
-                if( poOvrBand == NULL )
+                if( poSrcDS->GetRasterBand(j)->GetOverviewCount() !=
+                                                        nSrcOverviews )
                 {
-                    CPLError( CE_Failure, CPLE_NotSupported,
-                        "COPY_SRC_OVERVIEWS cannot be used when one overview band is NULL." );
+                    CPLError(
+                        CE_Failure, CPLE_NotSupported,
+                        "COPY_SRC_OVERVIEWS cannot be used when the bands have "
+                        "not the same number of overview levels." );
                     CSLDestroy(papszCreateOptions);
                     return NULL;
                 }
-                GDALRasterBand* poOvrFirstBand = poSrcDS->GetRasterBand(1)->GetOverview(i);
-                if( poOvrBand->GetXSize() != poOvrFirstBand->GetXSize() ||
-                    poOvrBand->GetYSize() != poOvrFirstBand->GetYSize() )
+                for( int i = 0; i < nSrcOverviews; ++i )
                 {
-                    CPLError( CE_Failure, CPLE_NotSupported,
-                    "COPY_SRC_OVERVIEWS cannot be used when the overview bands have not the same dimensions among bands." );
-                    CSLDestroy(papszCreateOptions);
-                    return NULL;
+                    GDALRasterBand* poOvrBand =
+                        poSrcDS->GetRasterBand(j)->GetOverview(i);
+                    if( poOvrBand == NULL )
+                    {
+                        CPLError(
+                            CE_Failure, CPLE_NotSupported,
+                            "COPY_SRC_OVERVIEWS cannot be used when one "
+                            "overview band is NULL." );
+                        CSLDestroy(papszCreateOptions);
+                        return NULL;
+                    }
+                    GDALRasterBand* poOvrFirstBand =
+                        poSrcDS->GetRasterBand(1)->GetOverview(i);
+                    if( poOvrBand->GetXSize() != poOvrFirstBand->GetXSize() ||
+                        poOvrBand->GetYSize() != poOvrFirstBand->GetYSize() )
+                    {
+                        CPLError(
+                            CE_Failure, CPLE_NotSupported,
+                            "COPY_SRC_OVERVIEWS cannot be used when the "
+                            "overview bands have not the same dimensions "
+                            "among bands." );
+                        CSLDestroy(papszCreateOptions);
+                        return NULL;
+                    }
                 }
             }
-        }
 
-        for(int i=0;i<nSrcOverviews;i++)
-        {
-            dfExtraSpaceForOverviews += ((double)poSrcDS->GetRasterBand(1)->GetOverview(i)->GetXSize()) *
-                                        poSrcDS->GetRasterBand(1)->GetOverview(i)->GetYSize();
+            for( int i = 0; i < nSrcOverviews; ++i )
+            {
+                dfExtraSpaceForOverviews +=
+                    static_cast<double>(
+                      poSrcDS->GetRasterBand(1)->GetOverview(i)->GetXSize() ) *
+                      poSrcDS->GetRasterBand(1)->GetOverview(i)->GetYSize();
+            }
+            dfExtraSpaceForOverviews *=
+                                l_nBands * GDALGetDataTypeSizeBytes(eType);
         }
-        dfExtraSpaceForOverviews *= nBands * (GDALGetDataTypeSize(eType) / 8);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Should we use optimized way of copying from an input JPEG       */
-/*      dataset ?                                                       */
+/*      dataset?                                                        */
 /* -------------------------------------------------------------------- */
-#if defined(HAVE_LIBJPEG)
-    int bCopyFromJPEG = FALSE;
-#endif
+
+// TODO(schwehr): Refactor bDirectCopyFromJPEG to be a const.
 #if defined(HAVE_LIBJPEG) || defined(JPEG_DIRECT_COPY)
-    int bDirectCopyFromJPEG = FALSE;
+    bool bDirectCopyFromJPEG = false;
 #endif
 
-    /* Note: JPEG_DIRECT_COPY is not defined by default, because it is mainly */
-    /* useful for debugging purposes */
+    // Note: JPEG_DIRECT_COPY is not defined by default, because it is mainly
+    // useful for debugging purposes.
 #ifdef JPEG_DIRECT_COPY
-    if (CSLFetchBoolean(papszCreateOptions, "JPEG_DIRECT_COPY", FALSE) &&
-        GTIFF_CanDirectCopyFromJPEG(poSrcDS, papszCreateOptions))
+    if( CPLFetchBool(papszCreateOptions, "JPEG_DIRECT_COPY", false) &&
+        GTIFF_CanDirectCopyFromJPEG(poSrcDS, papszCreateOptions) )
     {
         CPLDebug("GTiff", "Using special direct copy mode from a JPEG dataset");
 
-        bDirectCopyFromJPEG = TRUE;
+        bDirectCopyFromJPEG = true;
     }
 #endif
 
 #ifdef HAVE_LIBJPEG
-    /* when CreateCopy'ing() from a JPEG dataset, and asking for COMPRESS=JPEG, */
-    /* use DCT coefficients (unless other options are incompatible, like strip/tile dimensions, */
-    /* specifying JPEG_QUALITY option, incompatible PHOTOMETRIC with the source colorspace, etc...) */
-    /* to avoid the lossy steps involved by decompression/recompression */
-    if (!bDirectCopyFromJPEG && GTIFF_CanCopyFromJPEG(poSrcDS, papszCreateOptions))
+    bool bCopyFromJPEG = false;
+
+    // When CreateCopy'ing() from a JPEG dataset, and asking for COMPRESS=JPEG,
+    // use DCT coefficients (unless other options are incompatible, like
+    // strip/tile dimensions, specifying JPEG_QUALITY option, incompatible
+    // PHOTOMETRIC with the source colorspace, etc.) to avoid the lossy steps
+    // involved by decompression/recompression.
+    if( !bDirectCopyFromJPEG &&
+        GTIFF_CanCopyFromJPEG(poSrcDS, papszCreateOptions) )
     {
-        CPLDebug("GTiff", "Using special copy mode from a JPEG dataset");
+        CPLDebug( "GTiff", "Using special copy mode from a JPEG dataset" );
 
-        bCopyFromJPEG = TRUE;
+        bCopyFromJPEG = true;
     }
 #endif
 
@@ -13572,7 +15702,7 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     const bool bForcePhotometric =
         CSLFetchNameValue(papszOptions, "PHOTOMETRIC") != NULL;
 
-    if( nBands >= 3 && !bForcePhotometric &&
+    if( l_nBands >= 3 && !bForcePhotometric &&
 #ifdef HAVE_LIBJPEG
         !bCopyFromJPEG &&
 #endif
@@ -13587,54 +15717,67 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Create the file.                                                */
 /* -------------------------------------------------------------------- */
-    VSILFILE* fpL = NULL;
-    CPLString osTmpFilename;
+    VSILFILE* l_fpL = NULL;
+    CPLString l_osTmpFilename;
 
-    hTIFF = CreateLL( pszFilename, nXSize, nYSize, nBands,
-                      eType, dfExtraSpaceForOverviews, papszCreateOptions, &fpL, osTmpFilename );
-    int bStreaming = (osTmpFilename.size() != 0);
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+    TIFF *l_hTIFF =
+        CreateLL( pszFilename, nXSize, nYSize, l_nBands,
+                  eType, dfExtraSpaceForOverviews, papszCreateOptions, &l_fpL,
+                  l_osTmpFilename );
+    const bool bStreaming = !l_osTmpFilename.empty();
 
     CSLDestroy( papszCreateOptions );
     papszCreateOptions = NULL;
 
-    if( hTIFF == NULL )
+    if( l_hTIFF == NULL )
     {
-        if( bStreaming ) VSIUnlink(osTmpFilename);
+        if( bStreaming ) VSIUnlink(l_osTmpFilename);
         return NULL;
     }
 
-    TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig );
-    TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerSample );
+    uint16 l_nPlanarConfig = 0;
+    TIFFGetField( l_hTIFF, TIFFTAG_PLANARCONFIG, &l_nPlanarConfig );
 
-    uint16      nCompression;
+    uint16 l_nBitsPerSample = 0;
+    TIFFGetField(l_hTIFF, TIFFTAG_BITSPERSAMPLE, &l_nBitsPerSample );
 
-    if( !TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &(nCompression) ) )
-        nCompression = COMPRESSION_NONE;
+    uint16 l_nCompression = 0;
+
+    if( !TIFFGetField( l_hTIFF, TIFFTAG_COMPRESSION, &(l_nCompression) ) )
+        l_nCompression = COMPRESSION_NONE;
 
 /* -------------------------------------------------------------------- */
 /*      Set the alpha channel if it is the last one.                    */
 /* -------------------------------------------------------------------- */
-    if( poSrcDS->GetRasterBand(nBands)->GetColorInterpretation()==GCI_AlphaBand )
+    if( poSrcDS->GetRasterBand(l_nBands)->GetColorInterpretation() ==
+        GCI_AlphaBand )
     {
-        uint16 *v;
+        uint16 *v = NULL;
         uint16 count = 0;
-        if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
+        if( TIFFGetField( l_hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
         {
-            int nBaseSamples = nBands - count;
-            if( nBands > nBaseSamples && nBands - nBaseSamples - 1 < count )
+            const int nBaseSamples = l_nBands - count;
+            if( l_nBands > nBaseSamples && l_nBands - nBaseSamples - 1 < count )
             {
                 // We need to allocate a new array as (current) libtiff
                 // versions will not like that we reuse the array we got from
                 // TIFFGetField().
 
                 uint16* pasNewExtraSamples =
-                    (uint16*)CPLMalloc( count * sizeof(uint16) );
+                    static_cast<uint16 *>(
+                        CPLMalloc( count * sizeof(uint16) ) );
                 memcpy( pasNewExtraSamples, v, count * sizeof(uint16) );
-                pasNewExtraSamples[nBands - nBaseSamples - 1] =
-                    GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", CSLFetchNameValue(papszOptions,"ALPHA")),
-                                            DEFAULT_ALPHA_TYPE);
+                pasNewExtraSamples[l_nBands - nBaseSamples - 1] =
+                    GTiffGetAlphaValue(
+                        CPLGetConfigOption(
+                            "GTIFF_ALPHA",
+                            CSLFetchNameValue(papszOptions,"ALPHA") ),
+                        DEFAULT_ALPHA_TYPE);
 
-                TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, count, pasNewExtraSamples);
+                TIFFSetField( l_hTIFF, TIFFTAG_EXTRASAMPLES, count,
+                              pasNewExtraSamples);
 
                 CPLFree(pasNewExtraSamples);
             }
@@ -13646,9 +15789,9 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      sure we note that.                                              */
 /* -------------------------------------------------------------------- */
 
-    if( nCompression == COMPRESSION_JPEG )
+    if( l_nCompression == COMPRESSION_JPEG )
     {
-        if( nBands >= 3
+        if( l_nBands >= 3
             && (poSrcDS->GetRasterBand(1)->GetColorInterpretation()
                 == GCI_YCbCr_YBand)
             && (poSrcDS->GetRasterBand(2)->GetColorInterpretation()
@@ -13656,13 +15799,13 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             && (poSrcDS->GetRasterBand(3)->GetColorInterpretation()
                 == GCI_YCbCr_CrBand) )
         {
-            /* do nothing ... */
+            // Do nothing.
         }
         else
         {
-            /* we assume RGB if it isn't explicitly YCbCr */
+            // Assume RGB if it is not explicitly YCbCr.
             CPLDebug( "GTiff", "Setting JPEGCOLORMODE_RGB" );
-            TIFFSetField( hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB );
+            TIFFSetField( l_hTIFF, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB );
         }
     }
 
@@ -13670,91 +15813,98 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Does the source image consist of one band, with a palette?      */
 /*      If so, copy over.                                               */
 /* -------------------------------------------------------------------- */
-    if( (nBands == 1 || nBands == 2) && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
+    if( (l_nBands == 1 || l_nBands == 2) &&
+        poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
         && eType == GDT_Byte )
     {
-        unsigned short anTRed[256], anTGreen[256], anTBlue[256];
-        GDALColorTable *poCT;
+        unsigned short anTRed[256] = { 0 };
+        unsigned short anTGreen[256] = { 0 };
+        unsigned short anTBlue[256] = { 0 };
+        GDALColorTable *poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
 
-        poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
-
-        for( int iColor = 0; iColor < 256; iColor++ )
+        for( int iColor = 0; iColor < 256; ++iColor )
         {
             if( iColor < poCT->GetColorEntryCount() )
             {
-                GDALColorEntry  sRGB;
+                GDALColorEntry sRGB = { 0, 0, 0, 0 };
 
                 poCT->GetColorEntryAsRGB( iColor, &sRGB );
 
-                anTRed[iColor] = (unsigned short) (257 * sRGB.c1);
-                anTGreen[iColor] = (unsigned short) (257 * sRGB.c2);
-                anTBlue[iColor] = (unsigned short) (257 * sRGB.c3);
+                anTRed[iColor] = static_cast<unsigned short>(257 * sRGB.c1);
+                anTGreen[iColor] = static_cast<unsigned short>(257 * sRGB.c2);
+                anTBlue[iColor] = static_cast<unsigned short>(257 * sRGB.c3);
             }
             else
             {
-                anTRed[iColor] = anTGreen[iColor] = anTBlue[iColor] = 0;
+                anTRed[iColor] = 0;
+                anTGreen[iColor] = 0;
+                anTBlue[iColor] = 0;
             }
         }
 
         if( !bForcePhotometric )
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
-        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, anTRed, anTGreen, anTBlue );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
+        TIFFSetField( l_hTIFF, TIFFTAG_COLORMAP, anTRed, anTGreen, anTBlue );
     }
-    else if( (nBands == 1 || nBands == 2)
+    else if( (l_nBands == 1 || l_nBands == 2)
              && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
              && eType == GDT_UInt16 )
     {
-        unsigned short *panTRed, *panTGreen, *panTBlue;
-        GDALColorTable *poCT;
-
-        panTRed   = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
-        panTGreen = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
-        panTBlue  = (unsigned short *) CPLMalloc(65536*sizeof(unsigned short));
+        unsigned short *panTRed = static_cast<unsigned short *>(
+            CPLMalloc(65536 * sizeof(unsigned short)) );
+        unsigned short *panTGreen = static_cast<unsigned short *>(
+            CPLMalloc(65536 * sizeof(unsigned short)) );
+        unsigned short *panTBlue = static_cast<unsigned short *>(
+            CPLMalloc(65536 * sizeof(unsigned short)) );
 
-        poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
+        GDALColorTable *poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
 
-        for( int iColor = 0; iColor < 65536; iColor++ )
+        for( int iColor = 0; iColor < 65536; ++iColor )
         {
             if( iColor < poCT->GetColorEntryCount() )
             {
-                GDALColorEntry  sRGB;
+                GDALColorEntry sRGB = { 0, 0, 0, 0 };
 
                 poCT->GetColorEntryAsRGB( iColor, &sRGB );
 
-                panTRed[iColor] = (unsigned short) (256 * sRGB.c1);
-                panTGreen[iColor] = (unsigned short) (256 * sRGB.c2);
-                panTBlue[iColor] = (unsigned short) (256 * sRGB.c3);
+                panTRed[iColor] = static_cast<unsigned short>(256 * sRGB.c1);
+                panTGreen[iColor] = static_cast<unsigned short>(256 * sRGB.c2);
+                panTBlue[iColor] = static_cast<unsigned short>(256 * sRGB.c3);
             }
             else
             {
-                panTRed[iColor] = panTGreen[iColor] = panTBlue[iColor] = 0;
+                panTRed[iColor] = 0;
+                panTGreen[iColor] = 0;
+                panTBlue[iColor] = 0;
             }
         }
 
         if( !bForcePhotometric )
-            TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
-        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panTRed, panTGreen, panTBlue );
+            TIFFSetField( l_hTIFF, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE );
+        TIFFSetField( l_hTIFF, TIFFTAG_COLORMAP, panTRed, panTGreen, panTBlue );
 
         CPLFree( panTRed );
         CPLFree( panTGreen );
         CPLFree( panTBlue );
     }
     else if( poSrcDS->GetRasterBand(1)->GetColorTable() != NULL )
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Unable to export color table to GeoTIFF file.  Color tables\n"
-                  "can only be written to 1 band or 2 bands Byte or UInt16 GeoTIFF files." );
+        CPLError(
+            CE_Warning, CPLE_AppDefined,
+            "Unable to export color table to GeoTIFF file.  Color tables "
+            "can only be written to 1 band or 2 bands Byte or "
+            "UInt16 GeoTIFF files." );
 
-    if( nBands == 2
+    if( l_nBands == 2
         && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL
         && (eType == GDT_Byte || eType == GDT_UInt16) )
     {
         uint16 v[1] = { EXTRASAMPLE_UNASSALPHA };
 
-        TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, 1, v );
+        TIFFSetField(l_hTIFF, TIFFTAG_EXTRASAMPLES, 1, v );
     }
 
     // FIXME? libtiff writes extended tags in the order they are specified
-    // and not in increasing order
+    // and not in increasing order.
 
 /* -------------------------------------------------------------------- */
 /*      Transfer some TIFF specific metadata, if available.             */
@@ -13762,21 +15912,20 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      PAM because the profile doesn't allow to write some metadata    */
 /*      as TIFF tag                                                     */
 /* -------------------------------------------------------------------- */
-    int bHasWrittenMDInGeotiffTAG =
-            GTiffDataset::WriteMetadata( poSrcDS, hTIFF, FALSE, pszProfile,
-                                 pszFilename, papszOptions );
+    const bool bHasWrittenMDInGeotiffTAG =
+            GTiffDataset::WriteMetadata( poSrcDS, l_hTIFF, false, pszProfile,
+                                         pszFilename, papszOptions );
 
 /* -------------------------------------------------------------------- */
 /*      Write NoData value, if exist.                                   */
 /* -------------------------------------------------------------------- */
     if( EQUAL(pszProfile,"GDALGeoTIFF") )
     {
-        int bSuccess;
-        double dfNoData;
-
-        dfNoData = poSrcDS->GetRasterBand(1)->GetNoDataValue( &bSuccess );
-        if ( bSuccess )
-            GTiffDataset::WriteNoDataValue( hTIFF, dfNoData );
+        int bSuccess = FALSE;
+        const double dfNoData =
+            poSrcDS->GetRasterBand(1)->GetNoDataValue( &bSuccess );
+        if( bSuccess )
+            GTiffDataset::WriteNoDataValue( l_hTIFF, dfNoData );
     }
 
 /* -------------------------------------------------------------------- */
@@ -13792,82 +15941,85 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         bPixelIsPoint = true;
         bPointGeoIgnore =
             CPLTestBool( CPLGetConfigOption( "GTIFF_POINT_GEO_IGNORE",
-                                                "FALSE") );
+                                             "FALSE") );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Write affine transform if it is meaningful.                     */
 /* -------------------------------------------------------------------- */
-    const char *pszProjection = NULL;
-    double      adfGeoTransform[6];
+    const char *l_pszProjection = NULL;
+    double l_adfGeoTransform[6] = { 0.0 };
 
-    if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
-        && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
-            || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
-            || adfGeoTransform[4] != 0.0 || adfGeoTransform[5] != 1.0 ))
+    if( poSrcDS->GetGeoTransform( l_adfGeoTransform ) == CE_None
+        && (l_adfGeoTransform[0] != 0.0 || l_adfGeoTransform[1] != 1.0
+            || l_adfGeoTransform[2] != 0.0 || l_adfGeoTransform[3] != 0.0
+            || l_adfGeoTransform[4] != 0.0 || l_adfGeoTransform[5] != 1.0 ))
     {
         if( bGeoTIFF )
         {
-            if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0
-                && adfGeoTransform[5] < 0.0 )
+            if( l_adfGeoTransform[2] == 0.0 && l_adfGeoTransform[4] == 0.0
+                && l_adfGeoTransform[5] < 0.0 )
             {
+                {
+                    const double adfPixelScale[3] = {
+                        l_adfGeoTransform[1], fabs(l_adfGeoTransform[5]), 0.0 };
 
-                double adfPixelScale[3], adfTiePoints[6];
-
-                adfPixelScale[0] = adfGeoTransform[1];
-                adfPixelScale[1] = fabs(adfGeoTransform[5]);
-                adfPixelScale[2] = 0.0;
-
-                TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
+                    TIFFSetField( l_hTIFF, TIFFTAG_GEOPIXELSCALE, 3,
+                                  adfPixelScale );
+                }
 
-                adfTiePoints[0] = 0.0;
-                adfTiePoints[1] = 0.0;
-                adfTiePoints[2] = 0.0;
-                adfTiePoints[3] = adfGeoTransform[0];
-                adfTiePoints[4] = adfGeoTransform[3];
-                adfTiePoints[5] = 0.0;
+                double adfTiePoints[6] = {
+                    0.0,
+                    0.0,
+                    0.0,
+                    l_adfGeoTransform[0],
+                    l_adfGeoTransform[3],
+                    0.0
+                };
 
                 if( bPixelIsPoint && !bPointGeoIgnore )
                 {
-                    adfTiePoints[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
-                    adfTiePoints[4] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
+                    adfTiePoints[3] +=
+                        l_adfGeoTransform[1] * 0.5 + l_adfGeoTransform[2] * 0.5;
+                    adfTiePoints[4] +=
+                        l_adfGeoTransform[4] * 0.5 + l_adfGeoTransform[5] * 0.5;
                 }
 
-                TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
+                TIFFSetField( l_hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
             }
             else
             {
-                double adfMatrix[16];
-
-                memset(adfMatrix,0,sizeof(double) * 16);
-
-                adfMatrix[0] = adfGeoTransform[1];
-                adfMatrix[1] = adfGeoTransform[2];
-                adfMatrix[3] = adfGeoTransform[0];
-                adfMatrix[4] = adfGeoTransform[4];
-                adfMatrix[5] = adfGeoTransform[5];
-                adfMatrix[7] = adfGeoTransform[3];
+                double adfMatrix[16] = { 0.0 };
+
+                adfMatrix[0] = l_adfGeoTransform[1];
+                adfMatrix[1] = l_adfGeoTransform[2];
+                adfMatrix[3] = l_adfGeoTransform[0];
+                adfMatrix[4] = l_adfGeoTransform[4];
+                adfMatrix[5] = l_adfGeoTransform[5];
+                adfMatrix[7] = l_adfGeoTransform[3];
                 adfMatrix[15] = 1.0;
 
                 if( bPixelIsPoint && !bPointGeoIgnore )
                 {
-                    adfMatrix[3] += adfGeoTransform[1] * 0.5 + adfGeoTransform[2] * 0.5;
-                    adfMatrix[7] += adfGeoTransform[4] * 0.5 + adfGeoTransform[5] * 0.5;
+                    adfMatrix[3] +=
+                        l_adfGeoTransform[1] * 0.5 + l_adfGeoTransform[2] * 0.5;
+                    adfMatrix[7] +=
+                        l_adfGeoTransform[4] * 0.5 + l_adfGeoTransform[5] * 0.5;
                 }
 
-                TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
+                TIFFSetField( l_hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
             }
 
-            pszProjection = poSrcDS->GetProjectionRef();
+            l_pszProjection = poSrcDS->GetProjectionRef();
         }
 
 /* -------------------------------------------------------------------- */
 /*      Do we need a TFW file?                                          */
 /* -------------------------------------------------------------------- */
-        if( CSLFetchBoolean( papszOptions, "TFW", FALSE ) )
-            GDALWriteWorldFile( pszFilename, "tfw", adfGeoTransform );
-        else if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
-            GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
+        if( CPLFetchBool( papszOptions, "TFW", false ) )
+            GDALWriteWorldFile( pszFilename, "tfw", l_adfGeoTransform );
+        else if( CPLFetchBool( papszOptions, "WORLDFILE", false ) )
+            GDALWriteWorldFile( pszFilename, "wld", l_adfGeoTransform );
     }
 
 /* -------------------------------------------------------------------- */
@@ -13876,12 +16028,10 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     else if( poSrcDS->GetGCPCount() > 0 && bGeoTIFF )
     {
         const GDAL_GCP *pasGCPs = poSrcDS->GetGCPs();
-        double *padfTiePoints;
+        double *padfTiePoints = static_cast<double *>(
+            CPLMalloc(6 * sizeof(double) * poSrcDS->GetGCPCount()) );
 
-        padfTiePoints = (double *)
-            CPLMalloc(6*sizeof(double)*poSrcDS->GetGCPCount());
-
-        for( int iGCP = 0; iGCP < poSrcDS->GetGCPCount(); iGCP++ )
+        for( int iGCP = 0; iGCP < poSrcDS->GetGCPCount(); ++iGCP )
         {
 
             padfTiePoints[iGCP*6+0] = pasGCPs[iGCP].dfGCPPixel;
@@ -13898,60 +16048,59 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             }
         }
 
-        TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS,
+        TIFFSetField( l_hTIFF, TIFFTAG_GEOTIEPOINTS,
                       6*poSrcDS->GetGCPCount(), padfTiePoints );
         CPLFree( padfTiePoints );
 
-        pszProjection = poSrcDS->GetGCPProjection();
+        l_pszProjection = poSrcDS->GetGCPProjection();
 
-        if( CSLFetchBoolean( papszOptions, "TFW", FALSE )
-            || CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
+        if( CPLFetchBool( papszOptions, "TFW", false )
+            || CPLFetchBool( papszOptions, "WORLDFILE", false ) )
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "TFW=ON or WORLDFILE=ON creation options are ignored when GCPs are available");
+            CPLError(
+                CE_Warning, CPLE_AppDefined,
+                "TFW=ON or WORLDFILE=ON creation options are ignored when "
+                "GCPs are available" );
         }
     }
-
     else
-        pszProjection = poSrcDS->GetProjectionRef();
+    {
+        l_pszProjection = poSrcDS->GetProjectionRef();
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Write the projection information, if possible.                  */
 /* -------------------------------------------------------------------- */
-    const bool bHasProjection = (pszProjection != NULL && strlen(pszProjection) > 0);
+    const bool bHasProjection =
+        l_pszProjection != NULL && strlen(l_pszProjection) > 0;
     if( (bHasProjection || bPixelIsPoint) && bGeoTIFF )
     {
-        GTIF *psGTIF;
-
-        psGTIF = GTIFNew( hTIFF );
+        GTIF *psGTIF = GTIFNew( l_hTIFF );
 
         if( bHasProjection )
         {
-            GTIFSetFromOGISDefnEx( psGTIF, pszProjection, GetGTIFFKeysFlavor(papszOptions) );
+            GTIFSetFromOGISDefnEx( psGTIF, l_pszProjection,
+                                   GetGTIFFKeysFlavor(papszOptions) );
         }
 
         if( bPixelIsPoint )
         {
-            GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
-                       RasterPixelIsPoint);
+            GTIFKeySet( psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
+                        RasterPixelIsPoint );
         }
 
         GTIFWriteKeys( psGTIF );
         GTIFFree( psGTIF );
     }
 
-    int bDontReloadFirstBlock = FALSE;
+    bool l_bDontReloadFirstBlock = false;
 
 #ifdef HAVE_LIBJPEG
-    if (bCopyFromJPEG)
+    if( bCopyFromJPEG )
     {
-        GTIFF_CopyFromJPEG_WriteAdditionalTags(hTIFF,
+        GTIFF_CopyFromJPEG_WriteAdditionalTags(l_hTIFF,
                                                poSrcDS);
     }
-#else
-    if (0)
-    {
-    }
 #endif
 
 #if !defined(BIGTIFF_SUPPORT)
@@ -13965,21 +16114,23 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         CPLDebug( "GDAL",
                   "Writing zero block to force creation of JPEG tables." );
-        if( TIFFIsTiled( hTIFF ) )
+        if( TIFFIsTiled( l_hTIFF ) )
         {
-            int cc = TIFFTileSize( hTIFF );
-            unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
-            TIFFWriteEncodedTile(hTIFF, 0, pabyZeros, cc);
+            const int cc = TIFFTileSize( l_hTIFF );
+            unsigned char *pabyZeros =
+                static_cast<unsigned char *>( CPLCalloc(cc, 1) );
+            TIFFWriteEncodedTile( l_hTIFF, 0, pabyZeros, cc );
             CPLFree( pabyZeros );
         }
         else
         {
-            int cc = TIFFStripSize( hTIFF );
-            unsigned char *pabyZeros = (unsigned char *) CPLCalloc(cc,1);
-            TIFFWriteEncodedStrip(hTIFF, 0, pabyZeros, cc);
+            int cc = TIFFStripSize( l_hTIFF );
+            unsigned char *pabyZeros =
+                static_cast<unsigned char *>( CPLCalloc(cc,1) );
+            TIFFWriteEncodedStrip( l_hTIFF, 0, pabyZeros, cc );
             CPLFree( pabyZeros );
         }
-        bDontReloadFirstBlock = TRUE;
+        l_bDontReloadFirstBlock = true;
     }
 #endif
 
@@ -13987,55 +16138,62 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
 
-    TIFFWriteCheck( hTIFF, TIFFIsTiled(hTIFF), "GTiffCreateCopy()");
-    TIFFWriteDirectory( hTIFF );
+    TIFFWriteCheck( l_hTIFF, TIFFIsTiled(l_hTIFF), "GTiffCreateCopy()" );
+    TIFFWriteDirectory( l_hTIFF );
     if( bStreaming )
     {
-        /* We need to write twice the directory to be sure that custom */
-        /* TIFF tags are correctly sorted and that padding bytes have been */
-        /* added */
-        TIFFSetDirectory( hTIFF, 0 );
-        TIFFWriteDirectory( hTIFF );
+        // We need to write twice the directory to be sure that custom
+        // TIFF tags are correctly sorted and that padding bytes have been
+        // added.
+        TIFFSetDirectory( l_hTIFF, 0 );
+        TIFFWriteDirectory( l_hTIFF );
 
-        if( VSIFSeekL( fpL, 0, SEEK_END ) != 0 )
+        if( VSIFSeekL( l_fpL, 0, SEEK_END ) != 0 )
             CPLError(CE_Failure, CPLE_FileIO, "Cannot seek");
-        int nSize = (int) VSIFTellL(fpL);
+        const int nSize = static_cast<int>( VSIFTellL(l_fpL) );
 
-        vsi_l_offset nDataLength;
-        VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE);
-        TIFFSetDirectory( hTIFF, 0 );
-        GTiffFillStreamableOffsetAndCount( hTIFF, nSize );
-        TIFFWriteDirectory( hTIFF );
+        vsi_l_offset nDataLength = 0;
+        VSIGetMemFileBuffer( l_osTmpFilename, &nDataLength, FALSE);
+        TIFFSetDirectory( l_hTIFF, 0 );
+        GTiffFillStreamableOffsetAndCount( l_hTIFF, nSize );
+        TIFFWriteDirectory( l_hTIFF );
     }
-    TIFFFlush( hTIFF );
-    XTIFFClose( hTIFF );
-    hTIFF = NULL;
-    if( VSIFCloseL(fpL) != 0 )
-        eErr = CE_Failure;
-    fpL = NULL;
+    TIFFFlush( l_hTIFF );
+    XTIFFClose( l_hTIFF );
+    l_hTIFF = NULL;
 
-    if( eErr != CE_None )
     {
-        VSIUnlink( bStreaming ? osTmpFilename.c_str() : pszFilename );
-        return NULL;
+        const CPLErr eErr = VSIFCloseL(l_fpL) == 0 ? CE_None : CE_Failure;
+        l_fpL = NULL;
+
+        if( eErr != CE_None )
+        {
+            VSIUnlink( bStreaming ? l_osTmpFilename.c_str() : pszFilename );
+            return NULL;
+        }
     }
 
+    // fpStreaming will assigned to the instance and not closed here.
+    VSILFILE *fpStreaming = NULL;
     if( bStreaming )
     {
-        vsi_l_offset nDataLength;
-        void* pabyBuffer = VSIGetMemFileBuffer( osTmpFilename, &nDataLength, FALSE);
-        fpL = VSIFOpenL( pszFilename, "wb" );
-        if( fpL == NULL )
+        vsi_l_offset nDataLength = 0;
+        void* pabyBuffer =
+            VSIGetMemFileBuffer( l_osTmpFilename, &nDataLength, FALSE);
+        fpStreaming = VSIFOpenL( pszFilename, "wb" );
+        if( fpStreaming == NULL )
         {
-            VSIUnlink(osTmpFilename);
+            VSIUnlink(l_osTmpFilename);
             return NULL;
         }
-        if( (int)VSIFWriteL( pabyBuffer, 1, (int)nDataLength, fpL ) != (int)nDataLength )
+        if( static_cast<vsi_l_offset>(
+                VSIFWriteL( pabyBuffer, 1, static_cast<int>(nDataLength),
+                            fpStreaming ) ) != nDataLength )
         {
-            CPLError(CE_Failure, CPLE_FileIO, "Could not write %d bytes",
-                     (int)nDataLength);
-            CPL_IGNORE_RET_VAL(VSIFCloseL( fpL ));
-            VSIUnlink(osTmpFilename);
+            CPLError( CE_Failure, CPLE_FileIO, "Could not write %d bytes",
+                      static_cast<int>(nDataLength) );
+            CPL_IGNORE_RET_VAL(VSIFCloseL( fpStreaming ));
+            VSIUnlink(l_osTmpFilename);
             return NULL;
         }
     }
@@ -14044,57 +16202,61 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Re-open as a dataset and copy over missing metadata using       */
 /*      PAM facilities.                                                 */
 /* -------------------------------------------------------------------- */
-    GTiffDataset *poDS;
     CPLString osFileName("GTIFF_RAW:");
 
-    osFileName += bStreaming ? osTmpFilename.c_str() : pszFilename;
+    osFileName += bStreaming ? l_osTmpFilename.c_str() : pszFilename;
 
     GDALOpenInfo oOpenInfo( osFileName, GA_Update );
     if( bStreaming )
     {
-        /* In case of single strip file, there's a libtiff check that would */
-        /* issue a warning since the file hasn't the required size */
+        // In case of single strip file, there's a libtiff check that would
+        // issue a warning since the file hasn't the required size.
         CPLPushErrorHandler(CPLQuietErrorHandler);
     }
-    poDS = (GTiffDataset *) Open(&oOpenInfo);
+    GTiffDataset *poDS = static_cast<GTiffDataset *>( Open(&oOpenInfo) );
     if( bStreaming )
         CPLPopErrorHandler();
     if( poDS == NULL )
     {
         oOpenInfo.eAccess = GA_ReadOnly;
-        poDS = (GTiffDataset *) Open(&oOpenInfo);
+        poDS = static_cast<GTiffDataset *>( Open(&oOpenInfo) );
     }
 
-    if ( poDS == NULL )
+    if( poDS == NULL )
     {
-        VSIUnlink( bStreaming ? osTmpFilename.c_str() : pszFilename );
+        VSIUnlink( bStreaming ? l_osTmpFilename.c_str() : pszFilename );
         return NULL;
     }
 
     if( bStreaming )
     {
-        VSIUnlink(osTmpFilename);
-        poDS->fpToWrite = fpL;
+        VSIUnlink(l_osTmpFilename);
+        poDS->fpToWrite = fpStreaming;
     }
     poDS->osProfile = pszProfile;
 
     int nCloneInfoFlags = GCIF_PAM_DEFAULT & ~GCIF_MASK;
 
-    // If we explicitly asked not to tag the alpha band as such, don't
+    // If we explicitly asked not to tag the alpha band as such, do not
     // reintroduce this alpha color interpretation in PAM.
-    if( poSrcDS->GetRasterBand(nBands)->GetColorInterpretation()==GCI_AlphaBand &&
-        GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", CSLFetchNameValue(papszOptions,"ALPHA")), DEFAULT_ALPHA_TYPE) == EXTRASAMPLE_UNSPECIFIED )
+    if( poSrcDS->GetRasterBand(l_nBands)->GetColorInterpretation() ==
+        GCI_AlphaBand &&
+        GTiffGetAlphaValue(
+            CPLGetConfigOption(
+                "GTIFF_ALPHA",
+                CSLFetchNameValue(papszOptions,"ALPHA") ),
+            DEFAULT_ALPHA_TYPE) == EXTRASAMPLE_UNSPECIFIED )
     {
-        nCloneInfoFlags = nCloneInfoFlags & ~GCIF_COLORINTERP;
+        nCloneInfoFlags &= ~GCIF_COLORINTERP;
     }
 
     poDS->CloneInfo( poSrcDS, nCloneInfoFlags );
     poDS->papszCreationOptions = CSLDuplicate( papszOptions );
-    poDS->bDontReloadFirstBlock = bDontReloadFirstBlock;
+    poDS->bDontReloadFirstBlock = l_bDontReloadFirstBlock;
 
 /* -------------------------------------------------------------------- */
-/*      CloneInfo() doesn't merge metadata, it just replaces it totally */
-/*      So we have to merge it                                          */
+/*      CloneInfo() does not merge metadata, it just replaces it        */
+/*      totally.  So we have to merge it.                               */
 /* -------------------------------------------------------------------- */
 
     char **papszSRC_MD = poSrcDS->GetMetadata();
@@ -14105,11 +16267,12 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     poDS->SetMetadata( papszDST_MD );
     CSLDestroy( papszDST_MD );
 
-    /* Depending on the PHOTOMETRIC tag, the TIFF file may not have */
-    /* the same band count as the source. Will fail later in GDALDatasetCopyWholeRaster anyway... */
+    // Depending on the PHOTOMETRIC tag, the TIFF file may not have the same
+    // band count as the source. Will fail later in GDALDatasetCopyWholeRaster
+    // anyway.
     for( int nBand = 1;
-         nBand <= MIN(poDS->GetRasterCount(), poSrcDS->GetRasterCount()) ;
-         nBand++ )
+         nBand <= std::min(poDS->GetRasterCount(), poSrcDS->GetRasterCount()) ;
+         ++nBand )
     {
         GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(nBand);
         GDALRasterBand* poDstBand = poDS->GetRasterBand(nBand);
@@ -14121,13 +16284,12 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         poDstBand->SetMetadata( papszDST_MD );
         CSLDestroy( papszDST_MD );
 
-        char** papszCatNames;
-        papszCatNames = poSrcBand->GetCategoryNames();
-        if (NULL != papszCatNames)
+        char** papszCatNames = poSrcBand->GetCategoryNames();
+        if( NULL != papszCatNames )
             poDstBand->SetCategoryNames( papszCatNames );
     }
 
-    hTIFF = (TIFF*) poDS->GetInternalHandle(NULL);
+    l_hTIFF = static_cast<TIFF *>( poDS->GetInternalHandle(NULL) );
 
 /* -------------------------------------------------------------------- */
 /*      Handle forcing xml:ESRI data to be written to PAM.              */
@@ -14145,29 +16307,33 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Second chance: now that we have a PAM dataset, it is possible   */
 /*      to write metadata that we could not write as a TIFF tag.        */
 /* -------------------------------------------------------------------- */
-    if (!bHasWrittenMDInGeotiffTAG && !bStreaming)
-        GTiffDataset::WriteMetadata( poDS, hTIFF, TRUE, pszProfile,
-                                     pszFilename, papszOptions, TRUE /* don't write RPC and IMD file again */);
+    if( !bHasWrittenMDInGeotiffTAG && !bStreaming )
+        GTiffDataset::WriteMetadata(
+            poDS, l_hTIFF, true, pszProfile,
+            pszFilename, papszOptions,
+            true /* don't write RPC and IMD file again */ );
 
     if( !bStreaming )
-        GTiffDataset::WriteRPC( poDS, hTIFF, TRUE, pszProfile,
-                                     pszFilename, papszOptions, TRUE /* write only in PAM AND if needed */ );
-
-    /* To avoid unnecessary directory rewriting */
-    poDS->bMetadataChanged = FALSE;
-    poDS->bGeoTIFFInfoChanged = FALSE;
-    poDS->bNoDataChanged = FALSE;
-    poDS->bForceUnsetGTOrGCPs = FALSE;
-    poDS->bForceUnsetProjection = FALSE;
+        GTiffDataset::WriteRPC(
+            poDS, l_hTIFF, true, pszProfile,
+            pszFilename, papszOptions,
+            true /* write only in PAM AND if needed */ );
+
+    // To avoid unnecessary directory rewriting.
+    poDS->bMetadataChanged = false;
+    poDS->bGeoTIFFInfoChanged = false;
+    poDS->bNoDataChanged = false;
+    poDS->bForceUnsetGTOrGCPs = false;
+    poDS->bForceUnsetProjection = false;
     poDS->bStreamingOut = bStreaming;
 
-    // Don't try to load external metadata files (#6597)
-    poDS->bIMDRPCMetadataLoaded = TRUE;
+    // Don't try to load external metadata files (#6597).
+    poDS->bIMDRPCMetadataLoaded = true;
 
-    /* We must re-set the compression level at this point, since it has */
-    /* been lost a few lines above when closing the newly create TIFF file */
-    /* The TIFFTAG_ZIPQUALITY & TIFFTAG_JPEGQUALITY are not store in the TIFF file. */
-    /* They are just TIFF session parameters */
+    // We must re-set the compression level at this point, since it has been
+    // lost a few lines above when closing the newly create TIFF file The
+    // TIFFTAG_ZIPQUALITY & TIFFTAG_JPEGQUALITY are not store in the TIFF file.
+    // They are just TIFF session parameters.
 
     poDS->nZLevel = GTiffGetZLevel(papszOptions);
     poDS->nLZMAPreset = GTiffGetLZMAPreset(papszOptions);
@@ -14176,34 +16342,35 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     poDS->GetDiscardLsbOption(papszOptions);
     poDS->InitCreationOrOpenOptions(papszOptions);
 
-    if (nCompression == COMPRESSION_ADOBE_DEFLATE)
+    if( l_nCompression == COMPRESSION_ADOBE_DEFLATE )
     {
-        if (poDS->nZLevel != -1)
+        if( poDS->nZLevel != -1 )
         {
-            TIFFSetField( hTIFF, TIFFTAG_ZIPQUALITY, poDS->nZLevel );
+            TIFFSetField( l_hTIFF, TIFFTAG_ZIPQUALITY, poDS->nZLevel );
         }
     }
-    else if( nCompression == COMPRESSION_JPEG)
+    else if( l_nCompression == COMPRESSION_JPEG )
     {
-        if (poDS->nJpegQuality != -1)
+        if( poDS->nJpegQuality != -1 )
         {
-            TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, poDS->nJpegQuality );
+            TIFFSetField( l_hTIFF, TIFFTAG_JPEGQUALITY, poDS->nJpegQuality );
         }
-        TIFFSetField( hTIFF, TIFFTAG_JPEGTABLESMODE, poDS->nJpegTablesMode );
+        TIFFSetField( l_hTIFF, TIFFTAG_JPEGTABLESMODE, poDS->nJpegTablesMode );
     }
-    else if( nCompression == COMPRESSION_LZMA)
+    else if( l_nCompression == COMPRESSION_LZMA )
     {
-        if (poDS->nLZMAPreset != -1)
+        if( poDS->nLZMAPreset != -1 )
         {
-            TIFFSetField( hTIFF, TIFFTAG_LZMAPRESET, poDS->nLZMAPreset );
+            TIFFSetField( l_hTIFF, TIFFTAG_LZMAPRESET, poDS->nLZMAPreset );
         }
     }
 
-    /* Precreate (internal) mask, so that the IBuildOverviews() below */
-    /* has a chance to create also the overviews of the mask */
-    int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
-    if( eErr == CE_None
-        && !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) )
+    // Precreate (internal) mask, so that the IBuildOverviews() below
+    // has a chance to create also the overviews of the mask.
+    CPLErr eErr = CE_None;
+
+    const int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
+    if( !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) )
         && (nMaskFlags & GMF_PER_DATASET) )
     {
         eErr = poDS->CreateMaskBand( nMaskFlags );
@@ -14217,74 +16384,88 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*  compressed stream.                                                  */
 /* -------------------------------------------------------------------- */
 
-    /* For scaled progress due to overview copying */
-    double dfTotalPixels = ((double)nXSize) * nYSize;
+    // For scaled progress due to overview copying.
+    double dfTotalPixels = static_cast<double>(nXSize) * nYSize;
     double dfCurPixels = 0;
 
-    if (eErr == CE_None &&
-        nSrcOverviews != 0 &&
-        CSLFetchBoolean(papszOptions, "COPY_SRC_OVERVIEWS", FALSE))
+    if( eErr == CE_None &&
+        CPLFetchBool(papszOptions, "COPY_SRC_OVERVIEWS", false) )
     {
-        eErr = poDS->CreateOverviewsFromSrcOverviews(poSrcDS);
-
-        if (poDS->nOverviewCount != nSrcOverviews)
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Did only manage to instantiate %d overview levels, "
-                      "whereas source contains %d",
-                     poDS->nOverviewCount, nSrcOverviews);
-            eErr = CE_Failure;
-        }
-
-        int i;
-        for(i=0;i<nSrcOverviews;i++)
-        {
-            GDALRasterBand* poOvrBand = poSrcDS->GetRasterBand(1)->GetOverview(i);
-            dfTotalPixels += ((double)poOvrBand->GetXSize()) *
-                                      poOvrBand->GetYSize();
-        }
-
-        char* papszCopyWholeRasterOptions[2] = { NULL, NULL };
-        if (nCompression != COMPRESSION_NONE)
-            papszCopyWholeRasterOptions[0] = (char*) "COMPRESSED=YES";
-        /* Now copy the imagery */
-        for(i=0;eErr == CE_None && i<nSrcOverviews;i++)
+        const int nSrcOverviews = poSrcDS->GetRasterBand(1)->GetOverviewCount();
+        if( nSrcOverviews )
         {
-            /* Begin with the smallest overview */
-            int iOvrLevel = nSrcOverviews-1-i;
-
-            /* Create a fake dataset with the source overview level so that */
-            /* GDALDatasetCopyWholeRaster can cope with it */
-            GDALDataset* poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS, iOvrLevel, TRUE, FALSE);
-
-            GDALRasterBand* poOvrBand =
-                    poSrcDS->GetRasterBand(1)->GetOverview(iOvrLevel);
-            double dfNextCurPixels = dfCurPixels +
-                    ((double)poOvrBand->GetXSize()) * poOvrBand->GetYSize();
-
-            void* pScaledData = GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
-                                      dfNextCurPixels / dfTotalPixels,
-                                      pfnProgress, pProgressData);
+            eErr = poDS->CreateOverviewsFromSrcOverviews(poSrcDS);
 
-            eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcOvrDS,
-                                                (GDALDatasetH) poDS->papoOverviewDS[iOvrLevel],
-                                                papszCopyWholeRasterOptions,
-                                                GDALScaledProgress, pScaledData );
-
-            dfCurPixels = dfNextCurPixels;
-            GDALDestroyScaledProgress(pScaledData);
+            if( poDS->nOverviewCount != nSrcOverviews )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Did only manage to instantiate %d overview levels, "
+                        "whereas source contains %d",
+                        poDS->nOverviewCount, nSrcOverviews);
+                eErr = CE_Failure;
+            }
 
-            delete poSrcOvrDS;
-            poDS->papoOverviewDS[iOvrLevel]->FlushCache();
+            for( int i = 0; i < nSrcOverviews; ++i )
+            {
+                GDALRasterBand* poOvrBand =
+                    poSrcDS->GetRasterBand(1)->GetOverview(i);
+                dfTotalPixels += static_cast<double>(poOvrBand->GetXSize()) *
+                                poOvrBand->GetYSize();
+            }
 
-            /* Copy mask of the overview */
-            if (eErr == CE_None && poDS->poMaskDS != NULL)
+            char* papszCopyWholeRasterOptions[2] = { NULL, NULL };
+            if( l_nCompression != COMPRESSION_NONE )
+                papszCopyWholeRasterOptions[0] =
+                    const_cast<char*>( "COMPRESSED=YES" );
+            // Now copy the imagery.
+            for( int i = 0; eErr == CE_None && i < nSrcOverviews; ++i )
             {
-                eErr = GDALRasterBandCopyWholeRaster( poOvrBand->GetMaskBand(),
-                                                    poDS->papoOverviewDS[iOvrLevel]->poMaskDS->GetRasterBand(1),
-                                                    papszCopyWholeRasterOptions,
-                                                    GDALDummyProgress, NULL);
-                poDS->papoOverviewDS[iOvrLevel]->poMaskDS->FlushCache();
+                // Begin with the smallest overview.
+                const int iOvrLevel = nSrcOverviews - 1 - i;
+
+                // Create a fake dataset with the source overview level so that
+                // GDALDatasetCopyWholeRaster can cope with it.
+                GDALDataset* poSrcOvrDS =
+                    GDALCreateOverviewDataset(poSrcDS, iOvrLevel, TRUE);
+
+                GDALRasterBand* poOvrBand =
+                        poSrcDS->GetRasterBand(1)->GetOverview(iOvrLevel);
+                double dfNextCurPixels =
+                    dfCurPixels +
+                    static_cast<double>(poOvrBand->GetXSize()) *
+                    poOvrBand->GetYSize();
+
+                void* pScaledData =
+                    GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
+                                            dfNextCurPixels / dfTotalPixels,
+                                            pfnProgress, pProgressData );
+
+                eErr =
+                    GDALDatasetCopyWholeRaster(
+                        (GDALDatasetH) poSrcOvrDS,
+                        (GDALDatasetH) poDS->papoOverviewDS[iOvrLevel],
+                        papszCopyWholeRasterOptions,
+                        GDALScaledProgress, pScaledData );
+
+                dfCurPixels = dfNextCurPixels;
+                GDALDestroyScaledProgress(pScaledData);
+
+                delete poSrcOvrDS;
+                poSrcOvrDS = NULL;
+                poDS->papoOverviewDS[iOvrLevel]->FlushCache();
+
+                // Copy mask of the overview.
+                if( eErr == CE_None && poDS->poMaskDS != NULL )
+                {
+                    eErr =
+                        GDALRasterBandCopyWholeRaster(
+                            poOvrBand->GetMaskBand(),
+                            poDS->papoOverviewDS[iOvrLevel]->
+                            poMaskDS->GetRasterBand(1),
+                            papszCopyWholeRasterOptions,
+                            GDALDummyProgress, NULL);
+                    poDS->papoOverviewDS[iOvrLevel]->poMaskDS->FlushCache();
+                }
             }
         }
     }
@@ -14292,160 +16473,206 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Copy actual imagery.                                            */
 /* -------------------------------------------------------------------- */
-    void* pScaledData = GDALCreateScaledProgress( dfCurPixels / dfTotalPixels,
-                                                  1.0,
-                                                  pfnProgress, pProgressData);
+    void* pScaledData = GDALCreateScaledProgress(dfCurPixels / dfTotalPixels,
+                                                 1.0,
+                                                 pfnProgress, pProgressData);
 
-    int bTryCopy = TRUE;
+    int bTryCopy = TRUE;  // TODO(schwehr): Make this a bool.
 
 #ifdef HAVE_LIBJPEG
-    if (bCopyFromJPEG)
+    if( bCopyFromJPEG )
     {
-        eErr = GTIFF_CopyFromJPEG(poDS, poSrcDS,
-                                  pfnProgress, pProgressData,
-                                  bTryCopy);
+        eErr = GTIFF_CopyFromJPEG( poDS, poSrcDS,
+                                   pfnProgress, pProgressData,
+                                   bTryCopy );
 
-        /* In case of failure in the decompression step, try normal copy */
-        if (bTryCopy)
+        // In case of failure in the decompression step, try normal copy.
+        if( bTryCopy )
             eErr = CE_None;
     }
 #endif
 
 #ifdef JPEG_DIRECT_COPY
-    if (bDirectCopyFromJPEG)
+    if( bDirectCopyFromJPEG )
     {
         eErr = GTIFF_DirectCopyFromJPEG(poDS, poSrcDS,
                                         pfnProgress, pProgressData,
                                         bTryCopy);
 
-        /* In case of failure in the reading step, try normal copy */
-        if (bTryCopy)
+        // In case of failure in the reading step, try normal copy.
+        if( bTryCopy )
             eErr = CE_None;
     }
 #endif
 
-    if (bTryCopy && (poDS->bTreatAsSplit || poDS->bTreatAsSplitBitmap))
+    if( bTryCopy && (poDS->bTreatAsSplit || poDS->bTreatAsSplitBitmap) )
     {
-        /* For split bands, we use TIFFWriteScanline() interface */
+        // For split bands, we use TIFFWriteScanline() interface.
         CPLAssert(poDS->nBitsPerSample == 8 || poDS->nBitsPerSample == 1);
 
-        if (poDS->nPlanarConfig == PLANARCONFIG_CONTIG && poDS->nBands > 1)
+        if( poDS->nPlanarConfig == PLANARCONFIG_CONTIG && poDS->nBands > 1 )
         {
-            int j;
-            GByte* pabyScanline = (GByte *) VSI_MALLOC_VERBOSE(TIFFScanlineSize(hTIFF));
+            GByte* pabyScanline =
+                static_cast<GByte *>(
+                    VSI_MALLOC_VERBOSE(TIFFScanlineSize(l_hTIFF)) );
             if( pabyScanline == NULL )
                 eErr = CE_Failure;
-            for(j=0;j<nYSize && eErr == CE_None;j++)
-            {
-                eErr = poSrcDS->RasterIO(GF_Read, 0, j, nXSize, 1,
-                                         pabyScanline, nXSize, 1,
-                                         GDT_Byte, nBands, NULL, poDS->nBands, 0, 1,
-                                         NULL);
-                if (eErr == CE_None &&
-                    TIFFWriteScanline( hTIFF, pabyScanline, j, 0) == -1)
+            for( int j = 0; j < nYSize && eErr == CE_None; ++j )
+            {
+                eErr =
+                    poSrcDS->RasterIO(
+                        GF_Read, 0, j, nXSize, 1,
+                        pabyScanline, nXSize, 1,
+                        GDT_Byte, l_nBands, NULL, poDS->nBands, 0, 1,
+                        NULL );
+                if( eErr == CE_None &&
+                    TIFFWriteScanline( l_hTIFF, pabyScanline, j, 0) == -1 )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
                               "TIFFWriteScanline() failed." );
                     eErr = CE_Failure;
                 }
-                if( !GDALScaledProgress( (j+1) * 1.0 / nYSize, NULL, pScaledData ) )
+                if( !GDALScaledProgress( (j + 1) * 1.0 / nYSize,
+                                         NULL, pScaledData ) )
                     eErr = CE_Failure;
             }
-            CPLFree(pabyScanline);
+            CPLFree( pabyScanline );
         }
         else
         {
-            int j;
-            GByte* pabyScanline = (GByte *) VSI_MALLOC_VERBOSE(nXSize);
+            GByte* pabyScanline = static_cast<GByte *>(
+                VSI_MALLOC_VERBOSE(nXSize) );
             if( pabyScanline == NULL )
                 eErr = CE_Failure;
             else
                 eErr = CE_None;
-            for(int iBand=1;iBand<=nBands && eErr == CE_None;iBand++)
+            for( int iBand = 1; iBand <= l_nBands && eErr == CE_None; ++iBand )
             {
-                for(j=0;j<nYSize && eErr == CE_None;j++)
+                for( int j = 0; j < nYSize && eErr == CE_None; ++j )
                 {
                     eErr = poSrcDS->GetRasterBand(iBand)->RasterIO(
-                                                    GF_Read, 0, j, nXSize, 1,
-                                                    pabyScanline, nXSize, 1,
-                                                    GDT_Byte, 0, 0, NULL);
-                    if (poDS->bTreatAsSplitBitmap)
+                        GF_Read, 0, j, nXSize, 1,
+                        pabyScanline, nXSize, 1,
+                        GDT_Byte, 0, 0, NULL );
+                    if( poDS->bTreatAsSplitBitmap )
                     {
-                        for(int i=0;i<nXSize;i++)
+                        for( int i = 0; i < nXSize; ++i )
                         {
-                            GByte byVal = pabyScanline[i];
-                            if ((i & 0x7) == 0)
+                            const GByte byVal = pabyScanline[i];
+                            if( (i & 0x7) == 0 )
                                 pabyScanline[i >> 3] = 0;
-                            if (byVal)
-                                pabyScanline[i >> 3] |= (0x80 >> (i & 0x7));
+                            if( byVal )
+                                pabyScanline[i >> 3] |= 0x80 >> (i & 0x7);
                         }
                     }
-                    if (eErr == CE_None &&
-                        TIFFWriteScanline( hTIFF, pabyScanline, j, (uint16) (iBand-1)) == -1)
+                    if( eErr == CE_None &&
+                        TIFFWriteScanline(
+                            l_hTIFF, pabyScanline, j,
+                            static_cast<uint16>(iBand - 1)) == -1 )
                     {
                         CPLError( CE_Failure, CPLE_AppDefined,
                                   "TIFFWriteScanline() failed." );
                         eErr = CE_Failure;
                     }
-                    if( !GDALScaledProgress( (j+1 + (iBand - 1) * nYSize) * 1.0 /
-                                      (nBands * nYSize), NULL, pScaledData ) )
+                    if( !GDALScaledProgress(
+                           (j + 1 + (iBand - 1) * nYSize) * 1.0 /
+                           (l_nBands * nYSize),
+                           NULL, pScaledData ) )
                         eErr = CE_Failure;
                 }
             }
             CPLFree(pabyScanline);
         }
 
-        /* Necessary to be able to read the file without re-opening */
+        // Necessary to be able to read the file without re-opening.
 #if defined(HAVE_TIFFGETSIZEPROC)
-        TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( hTIFF );
+        TIFFSizeProc pfnSizeProc = TIFFGetSizeProc( l_hTIFF );
 
-        TIFFFlushData( hTIFF );
+        TIFFFlushData( l_hTIFF );
 
-        toff_t nNewDirOffset = pfnSizeProc( TIFFClientdata( hTIFF ) );
+        toff_t nNewDirOffset = pfnSizeProc( TIFFClientdata( l_hTIFF ) );
         if( (nNewDirOffset % 2) == 1 )
-            nNewDirOffset++;
+            ++nNewDirOffset;
 #endif
 
-        TIFFFlush( hTIFF );
+        TIFFFlush( l_hTIFF );
 
 #if defined(HAVE_TIFFGETSIZEPROC)
-        if( poDS->nDirOffset != TIFFCurrentDirOffset( hTIFF ) )
+        if( poDS->nDirOffset != TIFFCurrentDirOffset( l_hTIFF ) )
         {
             poDS->nDirOffset = nNewDirOffset;
             CPLDebug( "GTiff", "directory moved during flush." );
         }
 #endif
     }
-    else if (bTryCopy && eErr == CE_None)
+    else if( bTryCopy && eErr == CE_None )
     {
-        char* papszCopyWholeRasterOptions[2] = { NULL, NULL };
-        if (nCompression != COMPRESSION_NONE)
-            papszCopyWholeRasterOptions[0] = (char*) "COMPRESSED=YES";
-        /* For streaming with separate, we really want that bands are written */
-        /* after each other, even if the source is pixel interleaved */
+        char* papszCopyWholeRasterOptions[3] = { NULL, NULL, NULL };
+        int iNextOption = 0;
+        papszCopyWholeRasterOptions[iNextOption++] =
+                const_cast<char *>( "SKIP_HOLES=YES" );
+        if( l_nCompression != COMPRESSION_NONE )
+        {
+            papszCopyWholeRasterOptions[iNextOption++] =
+                const_cast<char *>( "COMPRESSED=YES" );
+        }
+        // For streaming with separate, we really want that bands are written
+        // after each other, even if the source is pixel interleaved.
         else if( bStreaming && poDS->nPlanarConfig == PLANARCONFIG_SEPARATE )
-            papszCopyWholeRasterOptions[0] = (char*) "INTERLEAVE=BAND";
-        eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
-                                            (GDALDatasetH) poDS,
-                                            papszCopyWholeRasterOptions,
-                                            GDALScaledProgress, pScaledData );
+        {
+            papszCopyWholeRasterOptions[iNextOption++] =
+                const_cast<char *>("INTERLEAVE=BAND");
+        }
+
+    /* -------------------------------------------------------------------- */
+    /*      Do we want to ensure all blocks get written out on close to     */
+    /*      avoid sparse files?                                             */
+    /* -------------------------------------------------------------------- */
+        if( !CPLFetchBool( papszOptions, "SPARSE_OK", false ) )
+            poDS->bFillEmptyTilesAtClosing = true;
+
+        poDS->bWriteEmptyTiles =
+            bStreaming ||
+            (poDS->nCompression != COMPRESSION_NONE &&
+             poDS->bFillEmptyTilesAtClosing);
+        // Only required for people writing non-compressed stripped files in the
+        // rightorder and wanting all tstrips to be written in the same order
+        // so that the end result can be memory mapped without knowledge of each
+        // strip offset
+        if( CPLTestBool( CSLFetchNameValueDef(
+                             papszOptions,
+                             "WRITE_EMPTY_TILES_SYNCHRONOUSLY", "FALSE" )) ||
+           CPLTestBool( CSLFetchNameValueDef(
+                             papszOptions,
+                             "@WRITE_EMPTY_TILES_SYNCHRONOUSLY", "FALSE" )) )
+        {
+            poDS->bWriteEmptyTiles = true;
+        }
+
+        eErr = GDALDatasetCopyWholeRaster(
+            /* (GDALDatasetH) */ poSrcDS,
+            /* (GDALDatasetH) */ poDS,
+            papszCopyWholeRasterOptions,
+            GDALScaledProgress, pScaledData );
     }
 
     GDALDestroyScaledProgress(pScaledData);
 
-    if (eErr == CE_None && !bStreaming)
+    if( eErr == CE_None && !bStreaming )
     {
-        if (poDS->poMaskDS)
+        if( poDS->poMaskDS )
         {
             const char* l_papszOptions[2] = { "COMPRESSED=YES", NULL };
             eErr = GDALRasterBandCopyWholeRaster(
                                     poSrcDS->GetRasterBand(1)->GetMaskBand(),
                                     poDS->GetRasterBand(1)->GetMaskBand(),
-                                    (char**)l_papszOptions,
+                                    const_cast<char **>(l_papszOptions),
                                     GDALDummyProgress, NULL);
         }
         else
+        {
             eErr = GDALDriver::DefaultCopyMasks( poSrcDS, poDS, bStrict );
+        }
     }
 
     if( eErr == CE_Failure )
@@ -14453,10 +16680,13 @@ GTiffDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         delete poDS;
         poDS = NULL;
 
-        if (CPLTestBool(CPLGetConfigOption("GTIFF_DELETE_ON_ERROR", "YES")))
+        if( CPLTestBool(CPLGetConfigOption("GTIFF_DELETE_ON_ERROR", "YES")) )
         {
             if( !bStreaming )
-                VSIUnlink( pszFilename ); // should really delete more carefully.
+            {
+                // Should really delete more carefully.
+                VSIUnlink( pszFilename );
+            }
         }
     }
 
@@ -14475,13 +16705,10 @@ const char *GTiffDataset::GetProjectionRef()
         LoadGeoreferencingAndPamIfNeeded();
         LookForProjection();
 
-        if( EQUAL(pszProjection,"") )
-            return GDALPamDataset::GetProjectionRef();
-        else
-            return( pszProjection );
+        return pszProjection;
     }
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -14493,8 +16720,10 @@ CPLErr GTiffDataset::SetProjection( const char * pszNewProjection )
 {
     if( bStreamingOut && bCrystalized )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot modify projection at that point in a streamed output file");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Cannot modify projection at that point in "
+            "a streamed output file" );
         return CE_Failure;
     }
 
@@ -14509,24 +16738,24 @@ CPLErr GTiffDataset::SetProjection( const char * pszNewProjection )
         && !EQUAL(pszNewProjection,"") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                "Only OGC WKT Projections supported for writing to GeoTIFF.\n"
+                "Only OGC WKT Projections supported for writing to GeoTIFF.  "
                 "%s not supported.",
                   pszNewProjection );
 
         return CE_Failure;
     }
 
-    if ( EQUAL(pszNewProjection, "") &&
-         pszProjection != NULL &&
-         !EQUAL(pszProjection, "") )
+    if( EQUAL(pszNewProjection, "") &&
+        pszProjection != NULL &&
+        !EQUAL(pszProjection, "") )
     {
-        bForceUnsetProjection = TRUE;
+        bForceUnsetProjection = true;
     }
 
     CPLFree( pszProjection );
     pszProjection = CPLStrdup( pszNewProjection );
 
-    bGeoTIFFInfoChanged = TRUE;
+    bGeoTIFFInfoChanged = true;
 
     return CE_None;
 }
@@ -14540,12 +16769,12 @@ CPLErr GTiffDataset::GetGeoTransform( double * padfTransform )
 {
     LoadGeoreferencingAndPamIfNeeded();
 
-    memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
+    memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
 
     if( !bGeoTransformValid )
         return CE_Failure;
-    else
-        return CE_None;
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -14557,8 +16786,10 @@ CPLErr GTiffDataset::SetGeoTransform( double * padfTransform )
 {
     if( bStreamingOut && bCrystalized )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot modify geotransform at that point in a streamed output file");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Cannot modify geotransform at that point in a "
+            "streamed output file" );
         return CE_Failure;
     }
 
@@ -14566,8 +16797,18 @@ CPLErr GTiffDataset::SetGeoTransform( double * padfTransform )
 
     if( GetAccess() == GA_Update )
     {
-        if (
-            padfTransform[0] == 0.0 &&
+        if( nGCPCount > 0 )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "GCPs previously set are going to be cleared "
+                     "due to the setting of a geotransform.");
+            bForceUnsetGTOrGCPs = true;
+            GDALDeinitGCPs( nGCPCount, pasGCPList );
+            CPLFree( pasGCPList );
+            nGCPCount = 0;
+            pasGCPList = NULL;
+        }
+        else if( padfTransform[0] == 0.0 &&
             padfTransform[1] == 1.0 &&
             padfTransform[2] == 0.0 &&
             padfTransform[3] == 0.0 &&
@@ -14580,19 +16821,20 @@ CPLErr GTiffDataset::SetGeoTransform( double * padfTransform )
             adfGeoTransform[4] == 0.0 &&
             adfGeoTransform[5] == 1.0) )
         {
-            bForceUnsetGTOrGCPs = TRUE;
+            bForceUnsetGTOrGCPs = true;
         }
 
         memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
-        bGeoTransformValid = TRUE;
-        bGeoTIFFInfoChanged = TRUE;
+        bGeoTransformValid = true;
+        bGeoTIFFInfoChanged = true;
 
-        return( CE_None );
+        return CE_None;
     }
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Attempt to call SetGeoTransform() on a read-only GeoTIFF file." );
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Attempt to call SetGeoTransform() on a read-only GeoTIFF file." );
         return CE_Failure;
     }
 }
@@ -14622,10 +16864,10 @@ const char *GTiffDataset::GetGCPProjection()
     {
         LookForProjection();
     }
-    if (pszProjection != NULL)
+    if( pszProjection != NULL )
         return pszProjection;
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -14653,12 +16895,35 @@ CPLErr GTiffDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
     {
         LookForProjection();
 
-        if (nGCPCount > 0 && nGCPCountIn == 0)
-            bForceUnsetGTOrGCPs = TRUE;
+        if( nGCPCount > 0 && nGCPCountIn == 0 )
+        {
+            bForceUnsetGTOrGCPs = true;
+        }
+        else if( nGCPCountIn > 0 &&
+                 !(adfGeoTransform[0] == 0.0 &&
+                   adfGeoTransform[1] == 1.0 &&
+                   adfGeoTransform[2] == 0.0 &&
+                   adfGeoTransform[3] == 0.0 &&
+                   adfGeoTransform[4] == 0.0 &&
+                   adfGeoTransform[5] == 1.0) )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "A geotransform previously set is going to be cleared "
+                     "due to the setting of GCPs.");
+            adfGeoTransform[0] = 0.0;
+            adfGeoTransform[1] = 1.0;
+            adfGeoTransform[2] = 0.0;
+            adfGeoTransform[3] = 0.0;
+            adfGeoTransform[4] = 0.0;
+            adfGeoTransform[5] = 1.0;
+            bGeoTransformValid = false;
+            bForceUnsetGTOrGCPs = true;
+        }
+
         if( !EQUAL(pszProjection, "") &&
                    (pszGCPProjection == NULL ||
                    pszGCPProjection[0] == '\0') )
-            bForceUnsetProjection = TRUE;
+            bForceUnsetProjection = true;
 
         if( nGCPCount > 0 )
         {
@@ -14671,14 +16936,14 @@ CPLErr GTiffDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
 
         CPLFree( pszProjection );
         pszProjection = CPLStrdup( pszGCPProjection );
-        bGeoTIFFInfoChanged = TRUE;
+        bGeoTIFFInfoChanged = true;
 
         return CE_None;
     }
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-            "SetGCPs() is only supported on newly created GeoTIFF files." );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SetGCPs() is only supported on newly created GeoTIFF files.");
         return CE_Failure;
     }
 }
@@ -14691,10 +16956,22 @@ char **GTiffDataset::GetMetadataDomainList()
 {
     LoadGeoreferencingAndPamIfNeeded();
 
-    return BuildMetadataDomainList(CSLDuplicate(oGTiffMDMD.GetDomainList()),
-                                   TRUE,
-                                   "", "ProxyOverviewRequest", MD_DOMAIN_RPC, MD_DOMAIN_IMD, "SUBDATASETS", "EXIF",
-                                   "xml:XMP", "COLOR_PROFILE", NULL);
+    char **papszDomainList = CSLDuplicate(oGTiffMDMD.GetDomainList());
+    char **papszBaseList = GDALDataset::GetMetadataDomainList();
+
+    const int nbBaseDomains = CSLCount(papszBaseList);
+
+    for( int domainId = 0; domainId < nbBaseDomains; ++domainId )
+        papszDomainList = CSLAddString(papszDomainList,papszBaseList[domainId]);
+
+    CSLDestroy(papszBaseList);
+
+    return BuildMetadataDomainList(
+        papszDomainList,
+        TRUE,
+        "", "ProxyOverviewRequest", MD_DOMAIN_RPC, MD_DOMAIN_IMD,
+        "SUBDATASETS", "EXIF",
+        "xml:XMP", "COLOR_PROFILE", NULL);
 }
 
 /************************************************************************/
@@ -14709,25 +16986,30 @@ char **GTiffDataset::GetMetadata( const char * pszDomain )
         LoadGeoreferencingAndPamIfNeeded();
     }
 
-    if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
+    if( pszDomain != NULL && EQUAL(pszDomain, "ProxyOverviewRequest") )
         return GDALPamDataset::GetMetadata( pszDomain );
 
+    if( pszDomain != NULL && EQUAL(pszDomain, "DERIVED_SUBDATASETS"))
+    {
+        return GDALDataset::GetMetadata(pszDomain);
+    }
+
     else if( pszDomain != NULL && (EQUAL(pszDomain, MD_DOMAIN_RPC) ||
                                    EQUAL(pszDomain, MD_DOMAIN_IMD) ||
                                    EQUAL(pszDomain, MD_DOMAIN_IMAGERY)) )
         LoadMetadata();
 
-    else if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
+    else if( pszDomain != NULL && EQUAL(pszDomain, "SUBDATASETS") )
         ScanDirectories();
 
-    else if( pszDomain != NULL && EQUAL(pszDomain,"EXIF") )
+    else if( pszDomain != NULL && EQUAL(pszDomain, "EXIF") )
         LoadEXIFMetadata();
 
-    else if( pszDomain != NULL && EQUAL(pszDomain,"COLOR_PROFILE") )
+    else if( pszDomain != NULL && EQUAL(pszDomain, "COLOR_PROFILE") )
         LoadICCProfile();
 
     else if( pszDomain == NULL || EQUAL(pszDomain, "") )
-        LoadMDAreaOrPoint(); /* to set GDALMD_AREA_OR_POINT */
+        LoadMDAreaOrPoint();  // To set GDALMD_AREA_OR_POINT.
 
     return oGTiffMDMD.GetMetadata( pszDomain );
 }
@@ -14742,17 +17024,22 @@ CPLErr GTiffDataset::SetMetadata( char ** papszMD, const char *pszDomain )
 
     if( bStreamingOut && bCrystalized )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot modify metadata at that point in a streamed output file");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Cannot modify metadata at that point in a streamed output file" );
         return CE_Failure;
     }
 
-    if ((papszMD != NULL) && (pszDomain != NULL) && EQUAL(pszDomain, "COLOR_PROFILE"))
-        bColorProfileMetadataChanged = TRUE;
+    if( (papszMD != NULL) &&
+        (pszDomain != NULL) &&
+        EQUAL(pszDomain, "COLOR_PROFILE") )
+    {
+        bColorProfileMetadataChanged = true;
+    }
     else if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
     {
-        bMetadataChanged = TRUE;
-        // Cancel any existing metadata from PAM file
+        bMetadataChanged = true;
+        // Cancel any existing metadata from PAM file.
         if( eAccess == GA_Update &&
             GDALPamDataset::GetMetadata(pszDomain) != NULL )
             GDALPamDataset::SetMetadata(NULL, pszDomain);
@@ -14765,11 +17052,11 @@ CPLErr GTiffDataset::SetMetadata( char ** papszMD, const char *pszDomain )
                 GetMetadataItem(GDALMD_AREA_OR_POINT);
         const char* pszNewValue =
                 CSLFetchNameValue(papszMD, GDALMD_AREA_OR_POINT);
-        if (pszPrevValue == NULL || pszNewValue == NULL ||
-            !EQUAL(pszPrevValue, pszNewValue))
+        if( pszPrevValue == NULL || pszNewValue == NULL ||
+            !EQUAL(pszPrevValue, pszNewValue) )
         {
             LookForProjection();
-            bGeoTIFFInfoChanged = TRUE;
+            bGeoTIFFInfoChanged = true;
         }
     }
 
@@ -14780,8 +17067,8 @@ CPLErr GTiffDataset::SetMetadata( char ** papszMD, const char *pszDomain )
 /*                          GetMetadataItem()                           */
 /************************************************************************/
 
-const char *GTiffDataset::GetMetadataItem( const char * pszName,
-                                           const char * pszDomain )
+const char *GTiffDataset::GetMetadataItem( const char *pszName,
+                                           const char *pszDomain )
 
 {
     if( pszDomain == NULL || !EQUAL(pszDomain, "IMAGE_STRUCTURE") )
@@ -14790,38 +17077,45 @@ const char *GTiffDataset::GetMetadataItem( const char * pszName,
     }
 
     if( pszDomain != NULL && EQUAL(pszDomain,"ProxyOverviewRequest") )
+    {
         return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
-
+    }
     else if( pszDomain != NULL && (EQUAL(pszDomain, MD_DOMAIN_RPC) ||
                                    EQUAL(pszDomain, MD_DOMAIN_IMD) ||
                                    EQUAL(pszDomain, MD_DOMAIN_IMAGERY)) )
+    {
         LoadMetadata();
-
-    else if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
+    }
+    else if( pszDomain != NULL && EQUAL(pszDomain, "SUBDATASETS") )
+    {
         ScanDirectories();
-
-    else if( pszDomain != NULL && EQUAL(pszDomain,"EXIF") )
+    }
+    else if( pszDomain != NULL && EQUAL(pszDomain, "EXIF") )
+    {
         LoadEXIFMetadata();
-
-    else if( pszDomain != NULL && EQUAL(pszDomain,"COLOR_PROFILE") )
+    }
+    else if( pszDomain != NULL && EQUAL(pszDomain, "COLOR_PROFILE") )
+    {
         LoadICCProfile();
-
+    }
     else if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
         pszName != NULL && EQUAL(pszName, GDALMD_AREA_OR_POINT) )
     {
-        LoadMDAreaOrPoint(); /* to set GDALMD_AREA_OR_POINT */
+        LoadMDAreaOrPoint();  // To set GDALMD_AREA_OR_POINT.
     }
 
 #ifdef DEBUG_REACHED_VIRTUAL_MEM_IO
     else if( pszDomain != NULL && EQUAL(pszDomain, "_DEBUG_") &&
-             pszName != NULL && EQUAL(pszName, "UNREACHED_VIRTUALMEMIO_CODE_PATH") )
+             pszName != NULL &&
+             EQUAL(pszName, "UNREACHED_VIRTUALMEMIO_CODE_PATH") )
     {
         CPLString osMissing;
-        for(int i=0;i<(int)(sizeof(anReachedVirtualMemIO)/sizeof(anReachedVirtualMemIO[0]));i++)
+        for( int i = 0; i < static_cast<int>(
+                                CPL_ARRAYSIZE(anReachedVirtualMemIO)); ++i )
         {
             if( !anReachedVirtualMemIO[i] )
             {
-                if( osMissing.size() ) osMissing += ",";
+                if( !osMissing.empty() ) osMissing += ",";
                 osMissing += CPLSPrintf("%d", i);
             }
         }
@@ -14832,12 +17126,12 @@ const char *GTiffDataset::GetMetadataItem( const char * pszName,
              pszName != NULL && EQUAL(pszName, "TIFFTAG_EXTRASAMPLES") )
     {
         CPLString osRet;
-        uint16 *v;
+        uint16 *v = NULL;
         uint16 count = 0;
 
         if( TIFFGetField( hTIFF, TIFFTAG_EXTRASAMPLES, &count, &v ) )
         {
-            for(int i=0; i < (int)count; i++)
+            for( int i = 0; i < static_cast<int>(count); ++i )
             {
                 if( i > 0 ) osRet += ",";
                 osRet += CPLSPrintf("%d", v[i]);
@@ -14851,6 +17145,16 @@ const char *GTiffDataset::GetMetadataItem( const char * pszName,
         return CPLSPrintf("%d", nPhotometric);
     }
 
+    else if( pszDomain != NULL && EQUAL(pszDomain, "_DEBUG_") &&
+             pszName != NULL && EQUAL( pszName, "TIFFTAG_GDAL_METADATA") )
+    {
+        char* pszText = NULL;
+        if( !TIFFGetField( hTIFF, TIFFTAG_GDAL_METADATA, &pszText ) )
+            return NULL;
+
+        return CPLSPrintf("%s", pszText);
+    }
+
     return oGTiffMDMD.GetMetadataItem( pszName, pszDomain );
 }
 
@@ -14867,17 +17171,20 @@ CPLErr GTiffDataset::SetMetadataItem( const char *pszName,
 
     if( bStreamingOut && bCrystalized )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Cannot modify metadata at that point in a streamed output file");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Cannot modify metadata at that point in a streamed output file" );
         return CE_Failure;
     }
 
-    if ((pszDomain != NULL) && EQUAL(pszDomain, "COLOR_PROFILE"))
-        bColorProfileMetadataChanged = TRUE;
+    if( (pszDomain != NULL) && EQUAL(pszDomain, "COLOR_PROFILE") )
+    {
+        bColorProfileMetadataChanged = true;
+    }
     else if( pszDomain == NULL || !EQUAL(pszDomain,"_temporary_") )
     {
-        bMetadataChanged = TRUE;
-        // Cancel any existing metadata from PAM file
+        bMetadataChanged = true;
+        // Cancel any existing metadata from PAM file.
         if( eAccess == GA_Update &&
             GDALPamDataset::GetMetadataItem(pszName, pszDomain) != NULL )
             GDALPamDataset::SetMetadataItem(pszName, NULL, pszDomain);
@@ -14887,7 +17194,7 @@ CPLErr GTiffDataset::SetMetadataItem( const char *pszName,
         pszName != NULL && EQUAL(pszName, GDALMD_AREA_OR_POINT) )
     {
         LookForProjection();
-        bGeoTIFFInfoChanged = TRUE;
+        bGeoTIFFInfoChanged = true;
     }
 
     return oGTiffMDMD.SetMetadataItem( pszName, pszValue, pszDomain );
@@ -14909,42 +17216,47 @@ void *GTiffDataset::GetInternalHandle( const char * /* pszHandleName */ )
 
 void GTiffDataset::LoadEXIFMetadata()
 {
-    if (bEXIFMetadataLoaded)
+    if( bEXIFMetadataLoaded )
         return;
-    bEXIFMetadataLoaded = TRUE;
+    bEXIFMetadataLoaded = true;
 
-    if (!SetDirectory())
+    if( !SetDirectory() )
         return;
 
     VSILFILE* fp = VSI_TIFFGetVSILFile(TIFFClientdata( hTIFF ));
 
-    GByte          abyHeader[2];
+    GByte abyHeader[2] = { 0 };
     if( VSIFSeekL(fp, 0, SEEK_SET) != 0 ||
         VSIFReadL(abyHeader, 1, 2, fp) != 2 )
         return;
 
-    int bLittleEndian = abyHeader[0] == 'I' && abyHeader[1] == 'I';
-    int bSwabflag = bLittleEndian ^ CPL_IS_LSB;
+    const bool bLittleEndian = abyHeader[0] == 'I' && abyHeader[1] == 'I';
+    const bool bLeastSignificantBit = CPL_IS_LSB != 0;
+    const bool bSwabflag = bLittleEndian != bLeastSignificantBit;  // != is XOR.
 
     char** papszMetadata = NULL;
-    toff_t nOffset;
+    toff_t nOffset = 0;  // TODO(b/28199387): Refactor to simplify casting.
 
-    if (TIFFGetField(hTIFF, TIFFTAG_EXIFIFD, &nOffset))
+    if( TIFFGetField(hTIFF, TIFFTAG_EXIFIFD, &nOffset) )
     {
-        int nExifOffset = (int)nOffset, nInterOffset = 0, nGPSOffset = 0;
-        EXIFExtractMetadata(papszMetadata,
-                            fp, (int)nOffset,
-                            bSwabflag, 0,
-                            nExifOffset, nInterOffset, nGPSOffset);
+        int nExifOffset = static_cast<int>(nOffset);
+        int nInterOffset = 0;
+        int nGPSOffset = 0;
+        EXIFExtractMetadata( papszMetadata,
+                             fp, static_cast<int>(nOffset),
+                             bSwabflag, 0,
+                             nExifOffset, nInterOffset, nGPSOffset);
     }
 
-    if (TIFFGetField(hTIFF, TIFFTAG_GPSIFD, &nOffset))
+    if( TIFFGetField(hTIFF, TIFFTAG_GPSIFD, &nOffset) )
     {
-        int nExifOffset = 0, nInterOffset = 0, nGPSOffset = (int)nOffset;
-        EXIFExtractMetadata(papszMetadata,
-                            fp, (int)nOffset,
-                            bSwabflag, 0,
-                            nExifOffset, nInterOffset, nGPSOffset);
+        int nExifOffset = 0;  // TODO(b/28199387): Refactor to simplify casting.
+        int nInterOffset = 0;
+        int nGPSOffset = static_cast<int>(nOffset);
+        EXIFExtractMetadata( papszMetadata,
+                             fp, static_cast<int>(nOffset),
+                             bSwabflag, 0,
+                             nExifOffset, nInterOffset, nGPSOffset );
     }
 
     oGTiffMDMD.SetMetadata( papszMetadata, "EXIF" );
@@ -14956,15 +17268,16 @@ void GTiffDataset::LoadEXIFMetadata()
 /************************************************************************/
 void GTiffDataset::LoadMetadata()
 {
-    if(TRUE == bIMDRPCMetadataLoaded)
+    if( bIMDRPCMetadataLoaded )
         return;
-    bIMDRPCMetadataLoaded = TRUE;
+    bIMDRPCMetadataLoaded = true;
 
     GDALMDReaderManager mdreadermanager;
-    GDALMDReaderBase* mdreader = mdreadermanager.GetReader(osFilename,
-                                         oOvManager.GetSiblingFiles(), MDR_ANY);
+    GDALMDReaderBase* mdreader =
+        mdreadermanager.GetReader(osFilename,
+                                  oOvManager.GetSiblingFiles(), MDR_ANY);
 
-    if(NULL != mdreader)
+    if( NULL != mdreader )
     {
         mdreader->FillMetadata(&oGTiffMDMD);
 
@@ -15005,14 +17318,15 @@ char **GTiffDataset::GetFileList()
     LoadMetadata();
     if(NULL != papszMetadataFiles)
     {
-        for( int i = 0; papszMetadataFiles[i] != NULL; i++ )
+        for( int i = 0; papszMetadataFiles[i] != NULL; ++i )
         {
-            papszFileList = CSLAddString( papszFileList, papszMetadataFiles[i] );
+            papszFileList =
+                CSLAddString( papszFileList, papszMetadataFiles[i] );
         }
     }
 
-    if (osGeorefFilename.size() != 0 &&
-        CSLFindString(papszFileList, osGeorefFilename) == -1)
+    if( !osGeorefFilename.empty() &&
+        CSLFindString(papszFileList, osGeorefFilename) == -1 )
     {
         papszFileList = CSLAddString( papszFileList, osGeorefFilename );
     }
@@ -15028,33 +17342,28 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlagsIn)
 {
     ScanDirectories();
 
-    if (poMaskDS != NULL)
+    if( poMaskDS != NULL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "This TIFF dataset has already an internal mask band");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "This TIFF dataset has already an internal mask band" );
         return CE_Failure;
     }
-    else if (CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
+    else if( CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")) )
     {
-        toff_t  nOffset;
-        int     bIsTiled;
-        int     bIsOverview = FALSE;
-        uint32 nSubType;
-        int     l_nCompression;
-
-        if (nFlagsIn != GMF_PER_DATASET)
+        if( nFlagsIn != GMF_PER_DATASET )
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "The only flag value supported for internal mask is GMF_PER_DATASET");
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "The only flag value supported for internal mask is "
+                "GMF_PER_DATASET" );
             return CE_Failure;
         }
 
+        int l_nCompression = COMPRESSION_PACKBITS;
         if( strstr(GDALGetMetadataItem(GDALGetDriverByName( "GTiff" ),
                                        GDAL_DMD_CREATIONOPTIONLIST, NULL ),
                    "<Value>DEFLATE</Value>") != NULL )
             l_nCompression = COMPRESSION_ADOBE_DEFLATE;
-        else
-            l_nCompression = COMPRESSION_PACKBITS;
 
     /* -------------------------------------------------------------------- */
     /*      If we don't have read access, then create the mask externally.  */
@@ -15062,25 +17371,25 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlagsIn)
         if( GetAccess() != GA_Update )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                    "File open for read-only accessing, "
-                    "creating mask externally." );
+                      "File open for read-only accessing, "
+                      "creating mask externally." );
 
             return GDALPamDataset::CreateMaskBand(nFlagsIn);
         }
 
-        if (poBaseDS)
-        {
-            if (!poBaseDS->SetDirectory())
-                return CE_Failure;
-        }
-        if (!SetDirectory())
+        if( poBaseDS && !poBaseDS->SetDirectory() )
             return CE_Failure;
 
-        if( TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType))
+        if( !SetDirectory() )
+            return CE_Failure;
+
+        bool bIsOverview = false;
+        uint32 nSubType = 0;
+        if( TIFFGetField(hTIFF, TIFFTAG_SUBFILETYPE, &nSubType) )
         {
             bIsOverview = (nSubType & FILETYPE_REDUCEDIMAGE) != 0;
 
-            if ((nSubType & FILETYPE_MASK) != 0)
+            if( (nSubType & FILETYPE_MASK) != 0 )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Cannot create a mask on a TIFF mask IFD !" );
@@ -15088,25 +17397,31 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlagsIn)
             }
         }
 
-        bIsTiled = TIFFIsTiled(hTIFF);
+        const int bIsTiled = TIFFIsTiled(hTIFF);
 
         FlushDirectory();
 
-        nOffset = GTIFFWriteDirectory(hTIFF,
-                                      (bIsOverview) ? FILETYPE_REDUCEDIMAGE | FILETYPE_MASK : FILETYPE_MASK,
-                                      nRasterXSize, nRasterYSize,
-                                      1, PLANARCONFIG_CONTIG, 1,
-                                      nBlockXSize, nBlockYSize,
-                                      bIsTiled, l_nCompression,
-                                      PHOTOMETRIC_MASK, PREDICTOR_NONE,
-                                      SAMPLEFORMAT_UINT, NULL, NULL, NULL, 0, NULL, "");
-        if (nOffset == 0)
+        const toff_t nOffset =
+            GTIFFWriteDirectory(
+                hTIFF,
+                bIsOverview ?
+                FILETYPE_REDUCEDIMAGE | FILETYPE_MASK : FILETYPE_MASK,
+                nRasterXSize, nRasterYSize,
+                1, PLANARCONFIG_CONTIG, 1,
+                nBlockXSize, nBlockYSize,
+                bIsTiled, l_nCompression,
+                PHOTOMETRIC_MASK, PREDICTOR_NONE,
+                SAMPLEFORMAT_UINT, NULL, NULL, NULL, 0, NULL, "", NULL, NULL,
+                NULL );
+        if( nOffset == 0 )
             return CE_Failure;
 
         poMaskDS = new GTiffDataset();
-        poMaskDS->bPromoteTo8Bits = CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
+        poMaskDS->bPromoteTo8Bits =
+            CPLTestBool(
+                CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES"));
         if( poMaskDS->OpenOffset( hTIFF, ppoActiveDSRef, nOffset,
-                                  FALSE, GA_Update ) != CE_None)
+                                  false, GA_Update ) != CE_None)
         {
             delete poMaskDS;
             poMaskDS = NULL;
@@ -15115,34 +17430,31 @@ CPLErr GTiffDataset::CreateMaskBand(int nFlagsIn)
 
         return CE_None;
     }
-    else
-    {
-        return GDALPamDataset::CreateMaskBand(nFlagsIn);
-    }
+
+    return GDALPamDataset::CreateMaskBand(nFlagsIn);
 }
 
 /************************************************************************/
 /*                         CreateMaskBand()                             */
 /************************************************************************/
 
-CPLErr GTiffRasterBand::CreateMaskBand(int nFlagsIn)
+CPLErr GTiffRasterBand::CreateMaskBand( int nFlagsIn )
 {
     poGDS->ScanDirectories();
 
-    if (poGDS->poMaskDS != NULL)
+    if( poGDS->poMaskDS != NULL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "This TIFF dataset has already an internal mask band");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "This TIFF dataset has already an internal mask band" );
         return CE_Failure;
     }
-    else if (CPLTestBool(CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO")))
+
+    if( CPLTestBool( CPLGetConfigOption("GDAL_TIFF_INTERNAL_MASK", "NO") ) )
     {
         return poGDS->CreateMaskBand(nFlagsIn);
     }
-    else
-    {
-        return GDALPamRasterBand::CreateMaskBand(nFlagsIn);
-    }
+
+    return GDALPamRasterBand::CreateMaskBand(nFlagsIn);
 }
 
 /************************************************************************/
@@ -15156,20 +17468,27 @@ CPLErr GTiffRasterBand::CreateMaskBand(int nFlagsIn)
 static char *PrepareTIFFErrorFormat( const char *module, const char *fmt )
 
 {
-    char      *pszModFmt;
-    int       iIn, iOut;
+    const size_t nModuleSize = strlen(module);
+    const size_t nModFmtSize = nModuleSize * 2 + strlen(fmt) + 2;
+    char *pszModFmt = static_cast<char *>( CPLMalloc( nModFmtSize ) );
 
-    pszModFmt = (char *) CPLMalloc( strlen(module)*2 + strlen(fmt) + 2 );
-    for( iOut = 0, iIn = 0; module[iIn] != '\0'; iIn++ )
+    size_t iOut = 0;  // Used after for.
+
+    for( size_t iIn = 0; iIn < nModuleSize; ++iIn )
     {
         if( module[iIn] == '%' )
         {
+            CPLAssert(iOut < nModFmtSize - 2);
             pszModFmt[iOut++] = '%';
             pszModFmt[iOut++] = '%';
         }
         else
+        {
+            CPLAssert(iOut < nModFmtSize - 1);
             pszModFmt[iOut++] = module[iIn];
+        }
     }
+    CPLAssert(iOut < nModFmtSize);
     pszModFmt[iOut] = '\0';
     strcat( pszModFmt, ":" );
     strcat( pszModFmt, fmt );
@@ -15183,12 +17502,10 @@ static char *PrepareTIFFErrorFormat( const char *module, const char *fmt )
 static void
 GTiffWarningHandler(const char* module, const char* fmt, va_list ap )
 {
-    char *pszModFmt;
-
     if( strstr(fmt,"nknown field") != NULL )
         return;
 
-    pszModFmt = PrepareTIFFErrorFormat( module, fmt );
+    char *pszModFmt = PrepareTIFFErrorFormat( module, fmt );
     if( strstr(fmt, "does not end in null byte") != NULL )
     {
         CPLString osMsg;
@@ -15196,7 +17513,9 @@ GTiffWarningHandler(const char* module, const char* fmt, va_list ap )
         CPLDebug( "GTiff", "%s", osMsg.c_str() );
     }
     else
+    {
         CPLErrorV( CE_Warning, CPLE_AppDefined, pszModFmt, ap );
+    }
     CPLFree( pszModFmt );
 }
 
@@ -15204,16 +17523,16 @@ GTiffWarningHandler(const char* module, const char* fmt, va_list ap )
 /*                         GTiffErrorHandler()                          */
 /************************************************************************/
 static void
-GTiffErrorHandler(const char* module, const char* fmt, va_list ap )
+GTiffErrorHandler( const char* module, const char* fmt, va_list ap )
 {
-    char *pszModFmt;
+    char *pszModFmt = NULL;
 
 #if SIZEOF_VOIDP == 4
-    /* Case of one-strip file where the strip size is > 2GB (#5403) */
+    // Case of one-strip file where the strip size is > 2GB (#5403).
     if( strcmp(module, "TIFFStripSize") == 0 &&
         strstr(fmt, "Integer overflow") != NULL )
     {
-        bGlobalStripIntegerOverflow = TRUE;
+        bGlobalStripIntegerOverflow = true;
         return;
     }
     if( bGlobalStripIntegerOverflow &&
@@ -15231,9 +17550,13 @@ GTiffErrorHandler(const char* module, const char* fmt, va_list ap )
         // handler is for all TIFF handles, and not necessarily the ones of
         // this driver.
         if( bGlobalInExternalOvr )
-            fmt = "Maximum TIFF file size exceeded. Use --config BIGTIFF_OVERVIEW YES configuration option.";
+            fmt =
+                "Maximum TIFF file size exceeded. "
+                "Use --config BIGTIFF_OVERVIEW YES configuration option.";
         else
-            fmt = "Maximum TIFF file size exceeded. Use BIGTIFF=YES creation option.";
+            fmt =
+                "Maximum TIFF file size exceeded. "
+                "Use BIGTIFF=YES creation option.";
     }
 #endif
 
@@ -15253,16 +17576,16 @@ static TIFFExtendProc _ParentExtender = NULL;
 static void GTiffTagExtender(TIFF *tif)
 
 {
-    static const TIFFFieldInfo xtiffFieldInfo[] = {
-        { TIFFTAG_GDAL_METADATA,    -1,-1, TIFF_ASCII, FIELD_CUSTOM,
-          TRUE, FALSE, (char*) "GDALMetadata" },
-        { TIFFTAG_GDAL_NODATA, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
-          TRUE, FALSE, (char*) "GDALNoDataValue" },
-        { TIFFTAG_RPCCOEFFICIENT,   -1,-1, TIFF_DOUBLE, FIELD_CUSTOM,
-          TRUE, TRUE, (char*) "RPCCoefficient" }
+    const TIFFFieldInfo xtiffFieldInfo[] = {
+        { TIFFTAG_GDAL_METADATA, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+          TRUE, FALSE, const_cast<char *>( "GDALMetadata" ) },
+        { TIFFTAG_GDAL_NODATA, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+          TRUE, FALSE, const_cast<char*>( "GDALNoDataValue" ) },
+        { TIFFTAG_RPCCOEFFICIENT, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM,
+          TRUE, TRUE, const_cast<char *>( "RPCCoefficient" ) }
     };
 
-    if (_ParentExtender)
+    if( _ParentExtender )
         (*_ParentExtender)(tif);
 
     TIFFMergeFieldInfo( tif, xtiffFieldInfo,
@@ -15282,41 +17605,51 @@ static void GTiffTagExtender(TIFF *tif)
 #include <dlfcn.h>
 #endif
 
+#if HAVE_CXX11_MUTEX
+static std::mutex oDeleteMutex;
+#else
 static CPLMutex* hGTiffOneTimeInitMutex = NULL;
+#endif  // HAVE_CXX11_MUTEX
 
 int GTiffOneTimeInit()
 
 {
-    static int bInitIsOk = TRUE;
-    static int bOneTimeInitDone = FALSE;
+#if HAVE_CXX11_MUTEX
+    std::lock_guard<std::mutex> oLock(oDeleteMutex);
+#else
     CPLMutexHolder oHolder( &hGTiffOneTimeInitMutex);
+#endif
+
+    static bool bOneTimeInitDone = false;
     if( bOneTimeInitDone )
-        return bInitIsOk;
+        return TRUE;
 
-    bOneTimeInitDone = TRUE;
+    bOneTimeInitDone = true;
 
-    /* This is a frequent configuration error that is difficult to track down */
-    /* for people unaware of the issue : GDAL built against internal libtiff (4.X) */
-    /* but used by an application that links with external libtiff (3.X) */
-    /* Note: on my conf, the order that cause GDAL to crash - and that is detected */
-    /* by the following code - is "-ltiff -lgdal". "-lgdal -ltiff" works for the */
-    /* GTiff driver but probably breaks the application that believes it uses libtiff 3.X */
-    /* but we cannot detect that... */
+    // This is a frequent configuration error that is difficult to track down
+    // for people unaware of the issue : GDAL built against internal libtiff
+    // (4.X), but used by an application that links with external libtiff (3.X)
+    // Note: on my conf, the order that cause GDAL to crash - and that is
+    // detected by the following code - is "-ltiff -lgdal". "-lgdal -ltiff"
+    // works for the GTiff driver but probably breaks the application that
+    // believes it uses libtiff 3.X but we cannot detect that.
 #if defined(BIGTIFF_SUPPORT) && !defined(RENAME_INTERNAL_LIBTIFF_SYMBOLS)
 #if defined(HAVE_DLFCN_H) && !defined(WIN32)
     const char* (*pfnVersion)(void);
     pfnVersion = (const char* (*)(void)) dlsym(RTLD_DEFAULT, "TIFFGetVersion");
-    if (pfnVersion)
+    if( pfnVersion )
     {
         const char* pszVersion = pfnVersion();
-        if (pszVersion && strstr(pszVersion, "Version 3.") != NULL)
+        if( pszVersion && strstr(pszVersion, "Version 3.") != NULL )
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "libtiff version mismatch : You're linking against libtiff 3.X, but GDAL has been compiled against libtiff >= 4.0.0");
+            CPLError(
+                CE_Warning, CPLE_AppDefined,
+                "libtiff version mismatch: You're linking against libtiff 3.X, "
+                "but GDAL has been compiled against libtiff >= 4.0.0" );
         }
     }
-#endif
-#endif
+#endif  // HAVE_DLFCN_H
+#endif  // BIGTIFF_SUPPORT
 
     _ParentExtender = TIFFSetTagExtender(GTiffTagExtender);
 
@@ -15342,11 +17675,13 @@ void GDALDeregister_GTiff( GDALDriver * )
     GTIFDeaccessCSV();
 #endif
 
+#if !HAVE_CXX11
     if( hGTiffOneTimeInitMutex != NULL )
     {
         CPLDestroyMutex(hGTiffOneTimeInitMutex);
         hGTiffOneTimeInitMutex = NULL;
     }
+#endif  // !HAVE_CXX11
 
     LibgeotiffOneTimeCleanupMutex();
 }
@@ -15369,10 +17704,10 @@ int GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName)
     else if( EQUAL( pszValue, "DEFLATE" ) || EQUAL( pszValue, "ZIP" ))
         nCompression = COMPRESSION_ADOBE_DEFLATE;
     else if( EQUAL( pszValue, "FAX3" )
-                || EQUAL( pszValue, "CCITTFAX3" ))
+             || EQUAL( pszValue, "CCITTFAX3" ))
         nCompression = COMPRESSION_CCITTFAX3;
     else if( EQUAL( pszValue, "FAX4" )
-                || EQUAL( pszValue, "CCITTFAX4" ))
+             || EQUAL( pszValue, "CCITTFAX4" ))
         nCompression = COMPRESSION_CCITTFAX4;
     else if( EQUAL( pszValue, "CCITTRLE" ) )
         nCompression = COMPRESSION_CCITTRLE;
@@ -15380,15 +17715,16 @@ int GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName)
         nCompression = COMPRESSION_LZMA;
     else
         CPLError( CE_Warning, CPLE_IllegalArg,
-                    "%s=%s value not recognised, ignoring.",
-                    pszVariableName,pszValue );
+                  "%s=%s value not recognised, ignoring.",
+                  pszVariableName,pszValue );
 
-#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007 /* 3.6.0 */
-    if (nCompression != COMPRESSION_NONE &&
-        !TIFFIsCODECConfigured((uint16) nCompression))
+#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION > 20031007  // 3.6.0
+    if( nCompression != COMPRESSION_NONE &&
+        !TIFFIsCODECConfigured((uint16) nCompression) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                "Cannot create TIFF file due to missing codec for %s.", pszValue );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Cannot create TIFF file due to missing codec for %s.", pszValue );
         return -1;
     }
 #endif
@@ -15406,8 +17742,8 @@ void GDALRegister_GTiff()
     if( GDALGetDriverByName( "GTiff" ) != NULL )
         return;
 
-    char szCreateOptions[5000];
-    char szOptionalCompressItems[500];
+    char szCreateOptions[5000] = { '\0' };
+    char szOptionalCompressItems[500] = { '\0' };
     bool bHasJPEG = false;
     bool bHasLZW = false;
     bool bHasDEFLATE = false;
@@ -15428,16 +17764,18 @@ void GDALRegister_GTiff()
             "       <Value>JPEG</Value>"
             "       <Value>LZW</Value>"
             "       <Value>DEFLATE</Value>" );
-    bHasLZW = bHasDEFLATE = true;
+    bHasLZW = true;
+    bHasDEFLATE = true;
 #else
-    TIFFCodec *c;
     TIFFCodec *codecs = TIFFGetConfiguredCODECs();
 
-    for( c = codecs; c->name; c++ )
+    for( TIFFCodec *c = codecs; c->name; ++c )
     {
         if( c->scheme == COMPRESSION_PACKBITS )
+        {
             strcat( szOptionalCompressItems,
                     "       <Value>PACKBITS</Value>" );
+        }
         else if( c->scheme == COMPRESSION_JPEG )
         {
             bHasJPEG = true;
@@ -15446,25 +17784,31 @@ void GDALRegister_GTiff()
         }
         else if( c->scheme == COMPRESSION_LZW )
         {
-            bHasLZW = TRUE;
+            bHasLZW = true;
             strcat( szOptionalCompressItems,
                     "       <Value>LZW</Value>" );
         }
         else if( c->scheme == COMPRESSION_ADOBE_DEFLATE )
         {
-            bHasDEFLATE = TRUE;
+            bHasDEFLATE = true;
             strcat( szOptionalCompressItems,
                     "       <Value>DEFLATE</Value>" );
         }
         else if( c->scheme == COMPRESSION_CCITTRLE )
+        {
             strcat( szOptionalCompressItems,
                     "       <Value>CCITTRLE</Value>" );
+        }
         else if( c->scheme == COMPRESSION_CCITTFAX3 )
+        {
             strcat( szOptionalCompressItems,
                     "       <Value>CCITTFAX3</Value>" );
+        }
         else if( c->scheme == COMPRESSION_CCITTFAX4 )
+        {
             strcat( szOptionalCompressItems,
                     "       <Value>CCITTFAX4</Value>" );
+        }
         else if( c->scheme == COMPRESSION_LZMA )
         {
             bHasLZMA = true;
@@ -15483,12 +17827,12 @@ void GDALRegister_GTiff()
               "   <Option name='COMPRESS' type='string-select'>",
               szOptionalCompressItems,
               "   </Option>");
-    if (bHasLZW || bHasDEFLATE)
+    if( bHasLZW || bHasDEFLATE )
         strcat( szCreateOptions, ""
 "   <Option name='PREDICTOR' type='int' description='Predictor Type (1=default, 2=horizontal differencing, 3=floating point prediction)'/>");
     strcat( szCreateOptions, ""
 "   <Option name='DISCARD_LSB' type='string' description='Number of least-significant bits to set to clear as a single value or comma-separated list of values for per-band values'/>" );
-    if (bHasJPEG)
+    if( bHasJPEG )
     {
         strcat( szCreateOptions, ""
 "   <Option name='JPEG_QUALITY' type='int' description='JPEG quality 1-100' default='75'/>"
@@ -15498,15 +17842,15 @@ void GDALRegister_GTiff()
 "   <Option name='JPEG_DIRECT_COPY' type='boolean' description='To copy without any decompression/recompression a JPEG source file' default='NO'/>");
 #endif
     }
-    if (bHasDEFLATE)
+    if( bHasDEFLATE )
         strcat( szCreateOptions, ""
 "   <Option name='ZLEVEL' type='int' description='DEFLATE compression level 1-9' default='6'/>");
-    if (bHasLZMA)
+    if( bHasLZMA )
         strcat( szCreateOptions, ""
 "   <Option name='LZMA_PRESET' type='int' description='LZMA compression level 0(fast)-9(slow)' default='6'/>");
     strcat( szCreateOptions, ""
 "   <Option name='NUM_THREADS' type='string' description='Number of worker threads for compression. Can be set to ALL_CPUS' default='1'/>"
-"   <Option name='NBITS' type='int' description='BITS for sub-byte files (1-7), sub-uint16 (9-15), sub-uint32 (17-31)'/>"
+"   <Option name='NBITS' type='int' description='BITS for sub-byte files (1-7), sub-uint16 (9-15), sub-uint32 (17-31), or float32 (16)'/>"
 "   <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
 "       <Value>BAND</Value>"
 "       <Value>PIXEL</Value>"
@@ -15528,7 +17872,7 @@ void GDALRegister_GTiff()
 "       <Value>ICCLAB</Value>"
 "       <Value>ITULAB</Value>"
 "   </Option>"
-"   <Option name='SPARSE_OK' type='boolean' description='Can newly created files have missing blocks?' default='FALSE'/>"
+"   <Option name='SPARSE_OK' type='boolean' description='Should empty blocks be omitted on disk?' default='FALSE'/>"
 "   <Option name='ALPHA' type='string-select' description='Mark first extrasample as being alpha'>"
 "       <Value>NON-PREMULTIPLIED</Value>"
 "       <Value>PREMULTIPLIED</Value>"
@@ -15598,6 +17942,8 @@ void GDALRegister_GTiff()
 "       <Value>STANDARD</Value>"
 "       <Value>ESRI_PE</Value>"
 "   </Option>"
+"   <Option name='GEOREF_SOURCES' type='string' description='Comma separated list made with values INTERNAL/TABFILE/WORLDFILE/PAM/NONE that describe the priority order for georeferencing' default='PAM,INTERNAL,TABFILE,WORLDFILE'/>"
+"   <Option name='SPARSE_OK' type='boolean' description='Should empty blocks be omitted on disk?' default='FALSE'/>"
 "</OpenOptionList>" );
     poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
diff --git a/frmts/gtiff/gt_citation.cpp b/frmts/gtiff/gt_citation.cpp
index c09b400..24ad952 100644
--- a/frmts/gtiff/gt_citation.cpp
+++ b/frmts/gtiff/gt_citation.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gt_citation.cpp 33796 2016-03-27 13:21:07Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements special parsing of Imagine citation strings, and
@@ -30,13 +29,23 @@
  ****************************************************************************/
 
 #include "cpl_port.h"
-#include "cpl_string.h"
+#include "gt_citation.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <string>
 
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "geokeys.h"
+#include "geotiff.h"
 #include "geovalues.h"
-#include "gt_citation.h"
 #include "gt_wkt_srs_priv.h"
+#include "ogr_core.h"
 
-CPL_CVSID("$Id: gt_citation.cpp 33796 2016-03-27 13:21:07Z goatbar $");
+CPL_CVSID("$Id: gt_citation.cpp 37477 2017-02-26 03:04:08Z goatbar $");
 
 static const char * const apszUnitMap[] = {
     "meters", "1.0",
@@ -88,51 +97,48 @@ static const char * const apszUnitMap[] = {
 /*                                                                      */
 /*      Translate ERDAS Imagine GeoTif citation                         */
 /************************************************************************/
-char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
+char* ImagineCitationTranslation( char* psCitation, geokey_t keyID )
 {
-    static const char * const keyNames[] = {
-        "NAD = ", "Datum = ", "Ellipsoid = ", "Units = ", NULL
-    };
-
+    if( !psCitation )
+        return NULL;
     char* ret = NULL;
-    int i;
-    if(!psCitation)
-        return ret;
-    if(STARTS_WITH_CI(psCitation, "IMAGINE GeoTIFF Support"))
+    if( STARTS_WITH_CI(psCitation, "IMAGINE GeoTIFF Support") )
     {
-        // this is a handle IMAGING style citation
-        char name[256];
-        name[0] = '\0';
-        char* p = NULL;
+        static const char * const keyNames[] = {
+            "NAD = ", "Datum = ", "Ellipsoid = ", "Units = ", NULL };
+
+        // This is a handle IMAGING style citation.
+        char name[256] = { '\0' };
         char* p1 = NULL;
 
-        p = strchr(psCitation, '$');
+        char* p = strchr(psCitation, '$');
         if( p && strchr(p, '\n') )
             p = strchr(p, '\n') + 1;
-        if(p)
+        if( p )
         {
             p1 = p + strlen(p);
             char *p2 = strchr(p, '\n');
-            if(p2)
-                p1 = MIN(p1, p2);
+            if( p2 )
+                p1 = std::min(p1, p2);
             p2 = strchr(p, '\0');
-            if(p2)
-                p1 = MIN(p1, p2);
-            for(i=0; keyNames[i]!=NULL; i++)
+            if( p2 )
+                p1 = std::min(p1, p2);
+
+            for( int i = 0; keyNames[i] != NULL; i++ )
             {
                 p2 = strstr(p, keyNames[i]);
                 if(p2)
-                    p1 = MIN(p1, p2);
+                    p1 = std::min(p1, p2);
             }
         }
 
-        // PCS name, GCS name and PRJ name
-        if(p && p1)
+        // PCS name, GCS name and PRJ name.
+        if( p && p1 )
         {
-            switch (keyID)
+            switch( keyID )
             {
               case PCSCitationGeoKey:
-                if(strstr(psCitation, "Projection = "))
+                if( strstr(psCitation, "Projection = ") )
                     strcpy(name, "PRJ Name = ");
                 else
                     strcpy(name, "PCS Name = ");
@@ -141,82 +147,93 @@ char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
                 strcpy(name, "PCS Name = ");
                 break;
               case GeogCitationGeoKey:
-                if(!strstr(p, "Unable to"))
+                if( !strstr(p, "Unable to") )
                     strcpy(name, "GCS Name = ");
                 break;
               default:
                 break;
             }
-            if(strlen(name)>0)
+            if( strlen(name)>0 )
             {
-                char* p2;
-                if((p2 = strstr(psCitation, "Projection Name = ")) != NULL)
+                // TODO(schwehr): What exactly is this code trying to do?
+                // Added in r15993 and modified in r21844 by warmerdam.
+                char* p2 = NULL;
+                if( (p2 = strstr(psCitation, "Projection Name = ")) != NULL )
                     p = p2 + strlen("Projection Name = ");
-                if((p2 = strstr(psCitation, "Projection = ")) != NULL)
+                if( (p2 = strstr(psCitation, "Projection = ")) != NULL )
                     p = p2 + strlen("Projection = ");
-                if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
-                    p1 --;
+                if( p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ' )
+                    p1--;
                 p2 = p1 - 1;
-                while( p2 != NULL && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
+                while( p2 != NULL &&
+                       (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
+                {
                     p2--;
-                if(p2 != p1 - 1)
+                }
+                if( p2 != p1 - 1 )
+                {
                     p1 = p2;
-                if(p1 >= p)
+                }
+                if( p1 >= p )
                 {
-                    strncat(name, p, p1-p+1);
+                    strncat(name, p, p1 - p + 1);
                     strcat(name, "|");
                     name[strlen(name)] = '\0';
                 }
             }
         }
 
-        // All other parameters
-        for(i=0; keyNames[i]!=NULL; i++)
+        // All other parameters.
+        for( int i = 0; keyNames[i] != NULL; i++ )
         {
             p = strstr(psCitation, keyNames[i]);
-            if(p)
+            if( p )
             {
                 p += strlen(keyNames[i]);
                 p1 = p + strlen(p);
                 char *p2 = strchr(p, '\n');
-                if(p2)
-                    p1 = MIN(p1, p2);
+                if( p2 )
+                    p1 = std::min(p1, p2);
                 p2 = strchr(p, '\0');
-                if(p2)
-                    p1 = MIN(p1, p2);
-                for(int j=0; keyNames[j]!=NULL; j++)
+                if( p2 )
+                    p1 = std::min(p1, p2);
+                for( int j = 0; keyNames[j] != NULL; j++ )
                 {
                     p2 = strstr(p, keyNames[j]);
-                    if(p2)
-                        p1 = MIN(p1, p2);
+                    if( p2 )
+                        p1 = std::min(p1, p2);
                 }
             }
-            if(p && p1 && p1>p)
+            if( p && p1 && p1>p )
             {
-                if(EQUAL(keyNames[i], "Units = "))
+                if( EQUAL(keyNames[i], "Units = ") )
                     strcat(name, "LUnits = ");
                 else
                     strcat(name, keyNames[i]);
-                if(p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ')
-                    p1 --;
+                if( p1[0] == '\0' || p1[0] == '\n' || p1[0] == ' ' )
+                    p1--;
                 char* p2 = p1 - 1;
-                while( p2 != NULL && (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
+                while( p2 != NULL &&
+                       (p2[0] == ' ' || p2[0] == '\0' || p2[0] == '\n') )
+                {
                     p2--;
-                if(p2 != p1 - 1)
+                }
+                if( p2 != p1 - 1 )
+                {
                     p1 = p2;
-                if(p1 >= p)
+                }
+                if( p1 >= p )
                 {
-                    strncat(name, p, p1-p+1);
+                    strncat(name, p, p1 - p + 1);
                     strcat(name, "|");
                     name[strlen(name)] = '\0';
                 }
             }
         }
-        if(strlen(name) > 0)
+        if( strlen(name) > 0 )
             ret = CPLStrdup(name);
     }
     return ret;
-
 }
 
 /************************************************************************/
@@ -227,103 +244,106 @@ char* ImagineCitationTranslation(char* psCitation, geokey_t keyID)
 
 char** CitationStringParse(char* psCitation, geokey_t keyID)
 {
-    char ** ret = NULL;
-    if(!psCitation)
-        return ret;
+    if( !psCitation )
+        return NULL;
 
-    ret = (char **) CPLCalloc(sizeof(char*), nCitationNameTypes);
+    char **ret = static_cast<char **>(
+        CPLCalloc(sizeof(char*), nCitationNameTypes) );
     char* pDelimit = NULL;
     char* pStr = psCitation;
-    char name[512];
-    int nameSet = FALSE;
+    char name[512] = { '\0' };
+    bool nameSet = false;
     int nameLen = static_cast<int>(strlen(psCitation));
-    OGRBoolean nameFound = FALSE;
-    while((pStr-psCitation+1)< nameLen)
+    bool nameFound = false;
+    while( (pStr - psCitation + 1) < nameLen )
     {
         if( (pDelimit = strstr(pStr, "|")) != NULL )
         {
-            strncpy( name, pStr, pDelimit-pStr );
+            strncpy( name, pStr, pDelimit - pStr );
             name[pDelimit-pStr] = '\0';
-            pStr = pDelimit+1;
-            nameSet = TRUE;
+            pStr = pDelimit + 1;
+            nameSet = true;
         }
         else
         {
             strcpy (name, pStr);
             pStr += strlen(pStr);
-            nameSet = TRUE;
+            nameSet = true;
         }
         if( strstr(name, "PCS Name = ") )
         {
-            ret[CitPcsName] = CPLStrdup(name+strlen("PCS Name = "));
-            nameFound = TRUE;
+            ret[CitPcsName] = CPLStrdup(name + strlen("PCS Name = "));
+            nameFound = true;
         }
-        if(strstr(name, "PRJ Name = "))
+        if( strstr(name, "PRJ Name = ") )
         {
-            ret[CitProjectionName] = CPLStrdup(name+strlen("PRJ Name = "));
-            nameFound = TRUE;
+            ret[CitProjectionName] =
+                CPLStrdup(name + strlen("PRJ Name = "));
+            nameFound = true;
         }
-        if(strstr(name, "LUnits = "))
+        if( strstr(name, "LUnits = ") )
         {
-            ret[CitLUnitsName] = CPLStrdup(name+strlen("LUnits = "));
-            nameFound = TRUE;
+            ret[CitLUnitsName] = CPLStrdup(name + strlen("LUnits = "));
+            nameFound = true;
         }
-        if(strstr(name, "GCS Name = "))
+        if( strstr(name, "GCS Name = ") )
         {
-            ret[CitGcsName] = CPLStrdup(name+strlen("GCS Name = "));
-            nameFound = TRUE;
+            ret[CitGcsName] = CPLStrdup(name + strlen("GCS Name = "));
+            nameFound = true;
         }
-        if(strstr(name, "Datum = "))
+        if( strstr(name, "Datum = ") )
         {
-            ret[CitDatumName] = CPLStrdup(name+strlen("Datum = "));
-            nameFound = TRUE;
+            ret[CitDatumName] = CPLStrdup(name + strlen("Datum = "));
+            nameFound = true;
         }
-        if(strstr(name, "Ellipsoid = "))
+        if( strstr(name, "Ellipsoid = ") )
         {
-            ret[CitEllipsoidName] = CPLStrdup(name+strlen("Ellipsoid = "));
-            nameFound = TRUE;
+            ret[CitEllipsoidName] = CPLStrdup(name + strlen("Ellipsoid = "));
+            nameFound = true;
         }
-        if(strstr(name, "Primem = "))
+        if( strstr(name, "Primem = ") )
         {
-            ret[CitPrimemName] = CPLStrdup(name+strlen("Primem = "));
-            nameFound = TRUE;
+            ret[CitPrimemName] = CPLStrdup(name + strlen("Primem = "));
+            nameFound = true;
         }
-        if(strstr(name, "AUnits = "))
+        if( strstr(name, "AUnits = ") )
         {
-            ret[CitAUnitsName] = CPLStrdup(name+strlen("AUnits = "));
-            nameFound = TRUE;
+            ret[CitAUnitsName] = CPLStrdup(name + strlen("AUnits = "));
+            nameFound = true;
         }
     }
     if( !nameFound && keyID == GeogCitationGeoKey && nameSet )
     {
         ret[CitGcsName] = CPLStrdup(name);
-        nameFound = TRUE;
+        nameFound = true;
     }
-    if(!nameFound)
+    if( !nameFound )
     {
         CPLFree( ret );
-        ret = (char**)NULL;
+        ret = NULL;
     }
     return ret;
 }
 
-
 /************************************************************************/
 /*                       SetLinearUnitCitation()                        */
 /*                                                                      */
 /*      Set linear unit Citation string                                 */
 /************************************************************************/
-void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName)
+void SetLinearUnitCitation( GTIF* psGTIF, char* pszLinearUOMName )
 {
-    char szName[512];
-    CPLString osCitation;
+    char szName[512] = { '\0' };
     int n = 0;
-    if( GDALGTIFKeyGetASCII( psGTIF, PCSCitationGeoKey, szName, 0, sizeof(szName) ) )
+    if( GDALGTIFKeyGetASCII( psGTIF, PCSCitationGeoKey, szName,
+                             0, sizeof(szName) ) )
+    {
         n = static_cast<int>(strlen(szName));
-    if(n>0)
+    }
+    CPLString osCitation;
+    if( n > 0 )
     {
         osCitation = szName;
-        if(osCitation[n-1] != '|')
+        if( osCitation[n-1] != '|' )
             osCitation += "|";
         osCitation += "LUnits = ";
         osCitation += pszLinearUOMName;
@@ -343,18 +363,22 @@ void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName)
 /*                                                                      */
 /*      Set geogcs Citation string                                      */
 /************************************************************************/
-void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitName, int nDatum, short nSpheroid)
+void SetGeogCSCitation( GTIF * psGTIF, OGRSpatialReference *poSRS,
+                        char* angUnitName, int nDatum, short nSpheroid )
 {
-    int bRewriteGeogCitation = FALSE;
-    char szName[256];
-    CPLString osCitation;
+    bool bRewriteGeogCitation = false;
+    char szName[256] = { '\0' };
     size_t n = 0;
-    if( GDALGTIFKeyGetASCII( psGTIF, GeogCitationGeoKey, szName, 0, sizeof(szName) ) )
+    if( GDALGTIFKeyGetASCII( psGTIF, GeogCitationGeoKey, szName,
+                             0, sizeof(szName) ) )
+    {
         n = strlen(szName);
-    if (n == 0)
+    }
+    if( n == 0 )
         return;
 
-    if(!STARTS_WITH_CI(szName, "GCS Name = "))
+    CPLString osCitation;
+    if( !STARTS_WITH_CI(szName, "GCS Name = ") )
     {
         osCitation = "GCS Name = ";
         osCitation += szName;
@@ -364,55 +388,57 @@ void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitN
         osCitation = szName;
     }
 
-    if(nDatum == KvUserDefined )
+    if( nDatum == KvUserDefined )
     {
         const char* datumName = poSRS->GetAttrValue( "DATUM" );
-        if(datumName && strlen(datumName) > 0)
+        if( datumName && strlen(datumName) > 0 )
         {
             osCitation += "|Datum = ";
             osCitation += datumName;
-            bRewriteGeogCitation = TRUE;
+            bRewriteGeogCitation = true;
         }
     }
-    if(nSpheroid == KvUserDefined )
+    if( nSpheroid == KvUserDefined )
     {
         const char* spheroidName = poSRS->GetAttrValue( "SPHEROID" );
-        if(spheroidName && strlen(spheroidName) > 0)
+        if( spheroidName && strlen(spheroidName) > 0 )
         {
             osCitation += "|Ellipsoid = ";
             osCitation += spheroidName;
-            bRewriteGeogCitation = TRUE;
+            bRewriteGeogCitation = true;
         }
     }
 
     const char* primemName = poSRS->GetAttrValue( "PRIMEM" );
-    if(primemName && strlen(primemName) > 0)
+    if( primemName && strlen(primemName) > 0 )
     {
         osCitation += "|Primem = ";
         osCitation += primemName;
-        bRewriteGeogCitation = TRUE;
+        bRewriteGeogCitation = true;
 
         double primemValue = poSRS->GetPrimeMeridian(NULL);
-        if(angUnitName && !EQUAL(angUnitName, "Degree"))
+        if( angUnitName && !EQUAL(angUnitName, "Degree") )
         {
-            double aUnit = poSRS->GetAngularUnits(NULL);
+            const double aUnit = poSRS->GetAngularUnits(NULL);
             primemValue *= aUnit;
         }
         GTIFKeySet( psGTIF, GeogPrimeMeridianLongGeoKey, TYPE_DOUBLE, 1,
                     primemValue );
     }
-    if(angUnitName && strlen(angUnitName) > 0 && !EQUAL(angUnitName, "Degree"))
+    if( angUnitName && strlen(angUnitName) > 0 &&
+        !EQUAL(angUnitName, "Degree") )
     {
         osCitation += "|AUnits = ";
         osCitation += angUnitName;
-        bRewriteGeogCitation = TRUE;
+        bRewriteGeogCitation = true;
     }
 
-    if (osCitation[strlen(osCitation) - 1] != '|')
+    if( osCitation.back() != '|' )
         osCitation += "|";
 
-    if (bRewriteGeogCitation)
-        GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0, osCitation.c_str() );
+    if( bRewriteGeogCitation )
+        GTIFKeySet( psGTIF, GeogCitationGeoKey, TYPE_ASCII,
+                    0, osCitation.c_str() );
 
     return;
 }
@@ -422,43 +448,45 @@ void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitN
 /*                                                                      */
 /*      Parse and set Citation string to SRS                            */
 /************************************************************************/
-OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
-                            geokey_t geoKey,  OGRSpatialReference *poSRS, OGRBoolean* linearUnitIsSet)
+OGRBoolean SetCitationToSRS( GTIF* hGTIF, char* szCTString, int nCTStringLen,
+                             geokey_t geoKey,  OGRSpatialReference *poSRS,
+                             OGRBoolean* linearUnitIsSet)
 {
     OGRBoolean ret = FALSE;
     char* lUnitName = NULL;
 
     poSRS->GetLinearUnits( &lUnitName );
-    if(!lUnitName || strlen(lUnitName) == 0  || EQUAL(lUnitName, "unknown"))
+    if( !lUnitName || strlen(lUnitName) == 0 ||
+        EQUAL(lUnitName, "unknown") )
         *linearUnitIsSet = FALSE;
     else
         *linearUnitIsSet = TRUE;
 
     char* imgCTName = ImagineCitationTranslation(szCTString, geoKey);
-    if(imgCTName)
+    if( imgCTName )
     {
         strncpy(szCTString, imgCTName, nCTStringLen);
         szCTString[nCTStringLen-1] = '\0';
         CPLFree( imgCTName );
     }
     char** ctNames = CitationStringParse(szCTString, geoKey);
-    if(ctNames)
+    if( ctNames )
     {
         if( poSRS->GetRoot() == NULL)
             poSRS->SetNode( "PROJCS", "unnamed" );
-        if(ctNames[CitPcsName])
+        if( ctNames[CitPcsName] )
         {
             poSRS->SetNode( "PROJCS", ctNames[CitPcsName] );
             ret = TRUE;
         }
-        if(ctNames[CitProjectionName])
+        if( ctNames[CitProjectionName] )
             poSRS->SetProjection( ctNames[CitProjectionName] );
 
-        if(ctNames[CitLUnitsName])
+        if( ctNames[CitLUnitsName] )
         {
             double unitSize = 0.0;
             int size = static_cast<int>(strlen(ctNames[CitLUnitsName]));
-            if(strchr(ctNames[CitLUnitsName], '\0'))
+            if( strchr(ctNames[CitLUnitsName], '\0') )
                 size -= 1;
             for( int i = 0; apszUnitMap[i] != NULL; i += 2 )
             {
@@ -469,23 +497,26 @@ OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
                 }
             }
             if( unitSize == 0.0 )
-                GDALGTIFKeyGetDOUBLE(hGTIF, ProjLinearUnitSizeGeoKey, &unitSize, 0, 1 );
+                GDALGTIFKeyGetDOUBLE( hGTIF, ProjLinearUnitSizeGeoKey,
+                                      &unitSize, 0, 1 );
             poSRS->SetLinearUnits( ctNames[CitLUnitsName], unitSize);
             *linearUnitIsSet = TRUE;
         }
-        for(int i= 0; i<nCitationNameTypes; i++)
+        for( int i = 0; i < nCitationNameTypes; i++ )
             CPLFree( ctNames[i] );
         CPLFree( ctNames );
     }
 
-    /* if no "PCS Name = " (from Erdas) in GTCitationGeoKey */
-    if(geoKey == GTCitationGeoKey)
+    // If no "PCS Name = " (from Erdas) in GTCitationGeoKey.
+    if( geoKey == GTCitationGeoKey )
     {
-        if(strlen(szCTString) > 0 && !strstr(szCTString, "PCS Name = "))
+        if( strlen(szCTString) > 0 &&
+            !strstr(szCTString, "PCS Name = ") )
         {
             const char* pszProjCS = poSRS->GetAttrValue( "PROJCS" );
-            if((!(pszProjCS && strlen(pszProjCS) > 0) && !strstr(szCTString, "Projected Coordinates"))
-               ||(pszProjCS && strstr(pszProjCS, "unnamed")))
+            if((!(pszProjCS && strlen(pszProjCS) > 0)
+                && !strstr(szCTString, "Projected Coordinates"))
+               || (pszProjCS && strstr(pszProjCS, "unnamed")))
                 poSRS->SetNode( "PROJCS", szCTString );
             ret = TRUE;
         }
@@ -499,56 +530,60 @@ OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
 /*                                                                      */
 /*      Parse and get geogcs names from a Citation string               */
 /************************************************************************/
-void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
-                           geokey_t geoKey,
-                           char **ppszGeogName,
-                           char **ppszDatumName,
-                           char **ppszPMName,
-                           char **ppszSpheroidName,
-                           char **ppszAngularUnits)
+void GetGeogCSFromCitation( char* szGCSName, int nGCSName,
+                            geokey_t geoKey,
+                            char **ppszGeogName,
+                            char **ppszDatumName,
+                            char **ppszPMName,
+                            char **ppszSpheroidName,
+                            char **ppszAngularUnits)
 {
-    *ppszGeogName = *ppszDatumName = *ppszPMName =
-        *ppszSpheroidName = *ppszAngularUnits = NULL;
+    *ppszGeogName = NULL;
+    *ppszDatumName = NULL;
+    *ppszPMName = NULL;
+    *ppszSpheroidName = NULL;
+    *ppszAngularUnits = NULL;
 
     char* imgCTName = ImagineCitationTranslation(szGCSName, geoKey);
-    if(imgCTName)
+    if( imgCTName )
     {
         strncpy(szGCSName, imgCTName, nGCSName);
         szGCSName[nGCSName-1] = '\0';
         CPLFree( imgCTName );
     }
     char** ctNames = CitationStringParse(szGCSName, geoKey);
-    if(ctNames)
+    if( ctNames )
     {
-        if(ctNames[CitGcsName])
+        if( ctNames[CitGcsName] )
             *ppszGeogName = CPLStrdup( ctNames[CitGcsName] );
 
-        if(ctNames[CitDatumName])
+        if( ctNames[CitDatumName] )
             *ppszDatumName = CPLStrdup( ctNames[CitDatumName] );
 
-        if(ctNames[CitEllipsoidName])
+        if( ctNames[CitEllipsoidName] )
             *ppszSpheroidName = CPLStrdup( ctNames[CitEllipsoidName] );
 
-        if(ctNames[CitPrimemName])
+        if( ctNames[CitPrimemName] )
             *ppszPMName = CPLStrdup( ctNames[CitPrimemName] );
 
-        if(ctNames[CitAUnitsName])
+        if( ctNames[CitAUnitsName] )
             *ppszAngularUnits = CPLStrdup( ctNames[CitAUnitsName] );
 
-        for(int i= 0; i<nCitationNameTypes; i++)
+        for( int i = 0; i < nCitationNameTypes; i++ )
             CPLFree( ctNames[i] );
         CPLFree( ctNames );
     }
     return;
 }
 
-
 /************************************************************************/
 /*               CheckCitationKeyForStatePlaneUTM()                     */
 /*                                                                      */
 /*      Handle state plane and UTM in citation key                      */
 /************************************************************************/
-OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSpatialReference* poSRS, OGRBoolean* pLinearUnitIsSet)
+OGRBoolean CheckCitationKeyForStatePlaneUTM( GTIF* hGTIF, GTIFDefn* psDefn,
+                                             OGRSpatialReference* poSRS,
+                                             OGRBoolean* pLinearUnitIsSet )
 {
     if( !hGTIF || !psDefn || !poSRS )
         return FALSE;
@@ -563,15 +598,14 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
         return FALSE;
 #endif
 
-    char  szCTString[512];
-    szCTString[0] = '\0';
+    char szCTString[512] = { '\0' };
 
-    /* Check units */
-    char units[32];
-    units[0] = '\0';
+    // Check units.
+    char units[32] = { '\0' };
 
-    OGRBoolean hasUnits = FALSE;
-    if( GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
+    bool hasUnits = false;
+    if( GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szCTString,
+                             0, sizeof(szCTString) ) )
     {
         CPLString osLCCT = szCTString;
 
@@ -580,28 +614,33 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
         if( strstr(osLCCT,"us") && strstr(osLCCT,"survey")
             && (strstr(osLCCT,"feet") || strstr(osLCCT,"foot")) )
             strcpy(units, "us_survey_feet");
-        else if(strstr(osLCCT, "linear_feet")
+        else if( strstr(osLCCT, "linear_feet")
                 || strstr(osLCCT, "linear_foot")
-                || strstr(osLCCT, "international"))
+                || strstr(osLCCT, "international") )
             strcpy(units, "international_feet");
         else if( strstr(osLCCT,"meter") )
             strcpy(units, "meters");
 
-        if (strlen(units) > 0)
-            hasUnits = TRUE;
+        if( strlen(units) > 0 )
+            hasUnits = true;
 
-        if( strstr( szCTString, "Projection Name = ") && strstr( szCTString, "_StatePlane_"))
+        if( strstr( szCTString, "Projection Name = ") &&
+            strstr( szCTString, "_StatePlane_") )
         {
-            const char *pStr = strstr( szCTString, "Projection Name = ") + strlen("Projection Name = ");
+            const char *pStr =
+                strstr( szCTString, "Projection Name = ") +
+                strlen("Projection Name = ");
             const char* pReturn = strchr( pStr, '\n');
-            char CSName[128];
-            strncpy(CSName, pStr, pReturn-pStr);
+            char CSName[128] = { '\0' };
+            strncpy(CSName, pStr, pReturn - pStr);
             CSName[pReturn-pStr] = '\0';
-            if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, NULL, 32767, CSName) == OGRERR_NONE )
+            if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, NULL, 32767, CSName)
+                == OGRERR_NONE )
             {
-                // for some erdas citation keys, the state plane CS name is incomplete, the unit check is necessary.
-                OGRBoolean done = FALSE;
-                if (hasUnits)
+                // For some erdas citation keys, the state plane CS name is
+                // incomplete, the unit check is necessary.
+                bool done = false;
+                if( hasUnits )
                 {
                     OGR_SRSNode *poUnit = poSRS->GetAttrNode( "PROJCS|UNIT" );
 
@@ -610,25 +649,27 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
                         CPLString unitName = poUnit->GetChild(0)->GetValue();
                         unitName.tolower();
 
-                        if (strstr(units, "us_survey_feet"))
+                        if( strstr(units, "us_survey_feet") )
                         {
-                            if (strstr(unitName, "us_survey_feet") || strstr(unitName, "foot_us") )
-                                done = TRUE;
+                            if( strstr(unitName, "us_survey_feet") ||
+                                strstr(unitName, "foot_us") )
+                                done = true;
                         }
-                        else if (strstr(units, "international_feet"))
+                        else if( strstr(units, "international_feet") )
                         {
-                            if (strstr(unitName, "feet") || strstr(unitName, "foot"))
-                                done = TRUE;
+                            if( strstr(unitName, "feet") ||
+                                strstr(unitName, "foot") )
+                                done = true;
                         }
                         else if (strstr(units, "meters"))
                         {
-                            if (strstr(unitName, "meter") )
-                                done = TRUE;
+                            if( strstr(unitName, "meter") )
+                                done = true;
                         }
                     }
                 }
-                if (done)
-                    return TRUE;
+                if( done )
+                    return true;
             }
         }
     }
@@ -643,26 +684,30 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
             osLCCT.tolower();
 
             if( strstr(osLCCT, "us") && strstr(osLCCT, "survey")
-                && (strstr(osLCCT, "feet") || strstr(osLCCT, "foot")))
+                && (strstr(osLCCT, "feet") || strstr(osLCCT, "foot")) )
                 strcpy(units, "us_survey_feet");
-            else if(strstr(osLCCT, "feet") || strstr(osLCCT, "foot"))
+            else if( strstr(osLCCT, "feet") || strstr(osLCCT, "foot") )
                 strcpy(units, "international_feet");
-            else if(strstr(osLCCT, "meter"))
+            else if( strstr(osLCCT, "meter") )
                 strcpy(units, "meters");
-            /*hasUnits = TRUE;*/
+            // hasUnits = true;
         }
     }
 
-    if (strlen(units) == 0)
+    if( strlen(units) == 0 )
         strcpy(units, "meters");
 
-    /* check PCSCitationGeoKey if it exists */
+    // Check PCSCitationGeoKey if it exists.
     szCTString[0] = '\0';
-    if( hGTIF && GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szCTString, 0, sizeof(szCTString)) )
+    if( hGTIF && GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szCTString,
+                                      0, sizeof(szCTString)) )
     {
-        /* For tif created by LEICA(ERDAS), ESRI state plane pe string was used and */
-        /* the state plane zone is given in PCSCitation. Therefore try Esri pe string first. */
-        SetCitationToSRS(hGTIF, szCTString, static_cast<int>(strlen(szCTString)), PCSCitationGeoKey, poSRS, pLinearUnitIsSet);
+        // For tif created by LEICA(ERDAS), ESRI state plane pe string was
+        // used and the state plane zone is given in PCSCitation. Therefore
+        // try ESRI pe string first.
+        SetCitationToSRS( hGTIF, szCTString,
+                          static_cast<int>(strlen(szCTString)),
+                          PCSCitationGeoKey, poSRS, pLinearUnitIsSet );
         const char *pcsName = poSRS->GetAttrValue("PROJCS");
         const char *pStr = NULL;
         if( (pcsName && (pStr = strstr(pcsName, "State Plane Zone ")) != NULL)
@@ -674,19 +719,26 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
             strcpy(nad, "HARN");
             if( strstr(szCTString, "NAD83") || strstr(szCTString, "NAD = 83") )
                 strcpy(nad, "NAD83");
-            else if( strstr(szCTString, "NAD27") || strstr(szCTString, "NAD = 27") )
+            else if( strstr(szCTString, "NAD27") ||
+                     strstr(szCTString, "NAD = 27") )
                 strcpy(nad, "NAD27");
-            if( poSRS->ImportFromESRIStatePlaneWKT(statePlaneZone, (const char*)nad, (const char*)units, psDefn->PCS) == OGRERR_NONE )
+            if( poSRS->ImportFromESRIStatePlaneWKT(
+                    statePlaneZone, (const char*)nad, (const char*)units,
+                    psDefn->PCS) == OGRERR_NONE )
                 return TRUE;
         }
-        else if( pcsName && (pStr = strstr(pcsName, "UTM Zone ")) != NULL )
+        else if( pcsName &&
+                 (/* pStr = */ strstr(pcsName, "UTM Zone ")) != NULL )
+        {
             CheckUTM( psDefn, szCTString );
+        }
     }
 
-    /* check state plane again to see if a pe string is available */
+    // Check state plane again to see if a pe string is available.
     if( psDefn->PCS != KvUserDefined )
     {
-        if( poSRS->ImportFromESRIStatePlaneWKT(0, NULL, (const char*)units, psDefn->PCS) == OGRERR_NONE )
+        if( poSRS->ImportFromESRIStatePlaneWKT( 0, NULL, (const char*)units,
+                                                psDefn->PCS) == OGRERR_NONE )
             return TRUE;
     }
 
@@ -700,65 +752,73 @@ OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSp
 /************************************************************************/
 void CheckUTM( GTIFDefn * psDefn, const char * pszCtString )
 {
-    if(!psDefn || !pszCtString)
+    if( !psDefn || !pszCtString )
         return;
 
-    static const char * const apszUtmProjCode[] = {
-        "PSAD56", "17N", "16017",
-        "PSAD56", "18N", "16018",
-        "PSAD56", "19N", "16019",
-        "PSAD56", "20N", "16020",
-        "PSAD56", "21N", "16021",
-        "PSAD56", "17S", "16117",
-        "PSAD56", "18S", "16118",
-        "PSAD56", "19S", "16119",
-        "PSAD56", "20S", "16120",
-        "PSAD56", "21S", "16121",
-        "PSAD56", "22S", "16122",
-        NULL, NULL, NULL};
-
     const char* p = strstr(pszCtString, "Datum = ");
-    char datumName[128];
-    if(p)
+    char datumName[128] = { '\0' };
+    if( p )
     {
         p += strlen("Datum = ");
         const char* p1 = strchr(p, '|');
-        if(p1 && p1-p < (int)sizeof(datumName))
+        if( p1 && p1 - p < static_cast<int>(sizeof(datumName)) )
         {
-            strncpy(datumName, p, (p1-p));
+            strncpy(datumName, p, p1 - p);
             datumName[p1-p] = '\0';
         }
         else
+        {
             CPLStrlcpy(datumName, p, sizeof(datumName));
+        }
     }
     else
     {
         datumName[0] = '\0';
     }
 
-    char utmName[64];
     p = strstr(pszCtString, "UTM Zone ");
-    if(p)
+    if( p )
     {
         p += strlen("UTM Zone ");
         const char* p1 = strchr(p, '|');
-        if(p1 && p1-p < (int)sizeof(utmName))
+        char utmName[64] = { '\0' };
+        if( p1 && p1 - p < static_cast<int>(sizeof(utmName)) )
         {
-            strncpy(utmName, p, (p1-p));
+            strncpy(utmName, p, p1 - p);
             utmName[p1-p] = '\0';
         }
         else
+        {
             CPLStrlcpy(utmName, p, sizeof(utmName));
+        }
 
-        for(int i=0; apszUtmProjCode[i]!=NULL; i += 3)
+        // Static to get this off the stack and constructed only one time.
+        static const char * const apszUtmProjCode[] = {
+            "PSAD56", "17N", "16017",
+            "PSAD56", "18N", "16018",
+            "PSAD56", "19N", "16019",
+            "PSAD56", "20N", "16020",
+            "PSAD56", "21N", "16021",
+            "PSAD56", "17S", "16117",
+            "PSAD56", "18S", "16118",
+            "PSAD56", "19S", "16119",
+            "PSAD56", "20S", "16120",
+            "PSAD56", "21S", "16121",
+            "PSAD56", "22S", "16122",
+            NULL, NULL, NULL };
+
+        for( int i = 0; apszUtmProjCode[i]!=NULL; i += 3 )
         {
-            if(EQUALN(utmName, apszUtmProjCode[i+1], strlen(apszUtmProjCode[i+1])) &&
-            EQUAL(datumName, apszUtmProjCode[i]) )
+            if( EQUALN(utmName, apszUtmProjCode[i+1],
+                       strlen(apszUtmProjCode[i+1])) &&
+                 EQUAL(datumName, apszUtmProjCode[i]) )
             {
-                if(psDefn->ProjCode != atoi(apszUtmProjCode[i+2]))
+                if( psDefn->ProjCode != atoi(apszUtmProjCode[i+2]) )
                 {
-                    psDefn->ProjCode = (short) atoi(apszUtmProjCode[i+2]);
-                    GTIFGetProjTRFInfo( psDefn->ProjCode, NULL, &(psDefn->Projection),
+                    psDefn->ProjCode =
+                        static_cast<short>( atoi(apszUtmProjCode[i+2]) );
+                    GTIFGetProjTRFInfo( psDefn->ProjCode, NULL,
+                                        &(psDefn->Projection),
                                         psDefn->ProjParm );
                     break;
                 }
diff --git a/frmts/gtiff/gt_citation.h b/frmts/gtiff/gt_citation.h
index 661efc2..004eace 100644
--- a/frmts/gtiff/gt_citation.h
+++ b/frmts/gtiff/gt_citation.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_citation.h 33796 2016-03-27 13:21:07Z goatbar $
+ * $Id: gt_citation.h 34124 2016-04-26 22:00:13Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements special parsing of Imagine citation strings, and
@@ -36,8 +36,8 @@
 #include "geo_normalize.h"
 #include "ogr_spatialref.h"
 
-char* ImagineCitationTranslation(char* psCitation, geokey_t keyID);
-char** CitationStringParse(char* psCitation, geokey_t keyID);
+char* ImagineCitationTranslation( char* psCitation, geokey_t keyID );
+char** CitationStringParse( char* psCitation, geokey_t keyID );
 
 #define nCitationNameTypes 9
 typedef enum
@@ -53,21 +53,25 @@ typedef enum
   CitAUnitsName = 8
 } CitationNameType;
 
-OGRBoolean CheckCitationKeyForStatePlaneUTM(GTIF* hGTIF, GTIFDefn* psDefn, OGRSpatialReference* poSRS, OGRBoolean* pLinearUnitIsSet);
-//char* ImagineCitationTranslation(char* psCitation, geokey_t keyID);
-//char** CitationStringParse(char* psCitation, geokey_t keyID);
-void SetLinearUnitCitation(GTIF* psGTIF, char* pszLinearUOMName);
-void SetGeogCSCitation(GTIF * psGTIF, OGRSpatialReference *poSRS, char* angUnitName, int nDatum, short nSpheroid);
+OGRBoolean CheckCitationKeyForStatePlaneUTM( GTIF* hGTIF,
+                                             GTIFDefn* psDefn,
+                                             OGRSpatialReference* poSRS,
+                                             OGRBoolean* pLinearUnitIsSet );
+// char* ImagineCitationTranslation( char* psCitation, geokey_t keyID );
+// char** CitationStringParse( char* psCitation, geokey_t keyID );
+void SetLinearUnitCitation( GTIF* psGTIF, char* pszLinearUOMName );
+void SetGeogCSCitation( GTIF * psGTIF, OGRSpatialReference *poSRS,
+                        char* angUnitName, int nDatum, short nSpheroid );
 OGRBoolean SetCitationToSRS(GTIF* hGTIF, char* szCTString, int nCTStringLen,
-                            geokey_t geoKey, OGRSpatialReference* poSRS, OGRBoolean* linearUnitIsSet);
-void GetGeogCSFromCitation(char* szGCSName, int nGCSName,
-                           geokey_t geoKey,
-                          char **ppszGeogName,
-                          char **ppszDatumName,
-                          char **ppszPMName,
-                          char **ppszSpheroidName,
-                          char **ppszAngularUnits);
+                            geokey_t geoKey, OGRSpatialReference* poSRS,
+                            OGRBoolean* linearUnitIsSet );
+void GetGeogCSFromCitation( char* szGCSName, int nGCSName,
+                            geokey_t geoKey,
+                            char **ppszGeogName,
+                            char **ppszDatumName,
+                            char **ppszPMName,
+                            char **ppszSpheroidName,
+                            char **ppszAngularUnits );
 void CheckUTM( GTIFDefn * psDefn, const char * pszCtString );
 
-
 #endif // GT_CITATION_H_INCLUDED
diff --git a/frmts/gtiff/gt_jpeg_copy.cpp b/frmts/gtiff/gt_jpeg_copy.cpp
index 4d897d3..40869de 100644
--- a/frmts/gtiff/gt_jpeg_copy.cpp
+++ b/frmts/gtiff/gt_jpeg_copy.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gt_jpeg_copy.cpp 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Specialized copy of JPEG content into TIFF.
@@ -27,8 +26,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi.h"
+#include "cpl_port.h"
 #include "gt_jpeg_copy.h"
+
+#include "cpl_vsi.h"
+
 #if defined(JPEG_DIRECT_COPY) || defined(HAVE_LIBJPEG)
 #  include "vrt/vrtdataset.h"
 #endif
@@ -37,10 +39,12 @@
 #define tmsize_t tsize_t
 #endif
 
-/* Note: JPEG_DIRECT_COPY is not defined by default, because it is mainly */
-/* useful for debugging purposes */
+#include <algorithm>
 
-CPL_CVSID("$Id: gt_jpeg_copy.cpp 33806 2016-03-28 22:26:19Z goatbar $");
+// Note: JPEG_DIRECT_COPY is not defined by default, because it is mainly
+// useful for debugging purposes.
+
+CPL_CVSID("$Id: gt_jpeg_copy.cpp 37477 2017-02-26 03:04:08Z goatbar $");
 
 #if defined(JPEG_DIRECT_COPY) || defined(HAVE_LIBJPEG)
 
@@ -48,12 +52,11 @@ CPL_CVSID("$Id: gt_jpeg_copy.cpp 33806 2016-03-28 22:26:19Z goatbar $");
 /*                      GetUnderlyingDataset()                          */
 /************************************************************************/
 
-static GDALDataset* GetUnderlyingDataset(GDALDataset* poSrcDS)
+static GDALDataset* GetUnderlyingDataset( GDALDataset* poSrcDS )
 {
-    /* Test if we can directly copy original JPEG content */
-    /* if available */
-    if (poSrcDS->GetDriver() != NULL &&
-        poSrcDS->GetDriver() == GDALGetDriverByName("VRT"))
+    // Test if we can directly copy original JPEG content if available.
+    if( poSrcDS->GetDriver() != NULL &&
+        poSrcDS->GetDriver() == GDALGetDriverByName("VRT") )
     {
         VRTDataset* poVRTDS = (VRTDataset* )poSrcDS;
         poSrcDS = poVRTDS->GetSingleSimpleSource();
@@ -64,52 +67,54 @@ static GDALDataset* GetUnderlyingDataset(GDALDataset* poSrcDS)
 
 #endif // defined(JPEG_DIRECT_COPY) || defined(HAVE_LIBJPEG)
 
-
 #ifdef JPEG_DIRECT_COPY
 
 /************************************************************************/
 /*                        IsBaselineDCTJPEG()                           */
 /************************************************************************/
 
-static int IsBaselineDCTJPEG(VSILFILE* fp)
+static bool IsBaselineDCTJPEG(VSILFILE* fp)
 {
-    GByte abyBuf[4];
+    GByte abyBuf[4] = { 0 };
 
-    if (VSIFReadL(abyBuf, 1, 2, fp) != 2 ||
+    if( VSIFReadL(abyBuf, 1, 2, fp) != 2 ||
         abyBuf[0] != 0xff || abyBuf[1] != 0xd8 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Not a valid JPEG file");
-        return FALSE;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Not a valid JPEG file" );
+        return false;
     }
 
     int nOffset = 2;
     while( true )
     {
         VSIFSeekL(fp, nOffset, SEEK_SET);
-        if (VSIFReadL(abyBuf, 1, 4, fp) != 4 ||
-            abyBuf[0] != 0xFF)
+        if( VSIFReadL(abyBuf, 1, 4, fp) != 4 ||
+            abyBuf[0] != 0xFF )
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                 "Not a valid JPEG file");
-            return FALSE;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Not a valid JPEG file" );
+            return false;
         }
 
-        int nMarker = abyBuf[1];
+        const int nMarker = abyBuf[1];
 
-        if (nMarker == 0xC0 /* Start of Frame 0 = Baseline DCT */)
-            return TRUE;
+        // Start of Frame 0 = Baseline DCT.
+        if( nMarker == 0xC0 )
+            return true;
 
-        if (nMarker == 0xD9)
-            return FALSE;
+        if( nMarker == 0xD9 )
+            return false;
 
-        if (nMarker == 0xF7 /* JPEG Extension 7, JPEG-LS */ ||
-            nMarker == 0xF8 /* JPEG Extension 8, JPEG-LS Extension */ ||
-            (nMarker >= 0xC1 && nMarker <= 0xCF) /* Other Start of Frames that we don't want to support */)
+        if( nMarker == 0xF7 ||  // JPEG Extension 7, JPEG-LS
+            nMarker == 0xF8 ||  // JPEG Extension 8, JPEG-LS Extension.
+            // Other Start of Frames that we don't want to support.
+            (nMarker >= 0xC1 && nMarker <= 0xCF) )
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Unsupported type of JPEG file for JPEG_DIRECT_COPY mode");
-            return FALSE;
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Unsupported type of JPEG file for JPEG_DIRECT_COPY mode" );
+            return false;
         }
 
         nOffset += 2 + abyBuf[2] * 256 + abyBuf[3];
@@ -120,54 +125,66 @@ static int IsBaselineDCTJPEG(VSILFILE* fp)
 /*                    GTIFF_CanDirectCopyFromJPEG()                     */
 /************************************************************************/
 
-int GTIFF_CanDirectCopyFromJPEG(GDALDataset* poSrcDS, char** &papszCreateOptions)
+int GTIFF_CanDirectCopyFromJPEG( GDALDataset* poSrcDS,
+                                 char** &papszCreateOptions )
 {
     poSrcDS = GetUnderlyingDataset(poSrcDS);
-    if (poSrcDS == NULL)
+    if( poSrcDS == NULL )
         return FALSE;
-    if (poSrcDS->GetDriver() == NULL)
+    if( poSrcDS->GetDriver() == NULL )
         return FALSE;
-    if (!EQUAL(GDALGetDriverShortName(poSrcDS->GetDriver()), "JPEG"))
+    if( !EQUAL(GDALGetDriverShortName(poSrcDS->GetDriver()), "JPEG") )
         return FALSE;
 
     const char* pszCompress = CSLFetchNameValue(papszCreateOptions, "COMPRESS");
-    if (pszCompress != NULL && !EQUAL(pszCompress, "JPEG"))
+    if(pszCompress != NULL && !EQUAL(pszCompress, "JPEG") )
         return FALSE;
 
-    const char* pszSrcColorSpace = poSrcDS->GetMetadataItem("SOURCE_COLOR_SPACE", "IMAGE_STRUCTURE");
-    if (pszSrcColorSpace != NULL &&
-        (EQUAL(pszSrcColorSpace, "CMYK") || EQUAL(pszSrcColorSpace, "YCbCrK")))
+    const char* pszSrcColorSpace =
+        poSrcDS->GetMetadataItem("SOURCE_COLOR_SPACE", "IMAGE_STRUCTURE");
+    if( pszSrcColorSpace != NULL &&
+        (EQUAL(pszSrcColorSpace, "CMYK") || EQUAL(pszSrcColorSpace, "YCbCrK")) )
         return FALSE;
 
-    int bJPEGDirectCopy = FALSE;
+    bool bJPEGDirectCopy = false;
 
     VSILFILE* fpJPEG = VSIFOpenL(poSrcDS->GetDescription(), "rb");
-    if (fpJPEG && IsBaselineDCTJPEG(fpJPEG))
+    if( fpJPEG && IsBaselineDCTJPEG(fpJPEG) )
     {
-        bJPEGDirectCopy = TRUE;
+        bJPEGDirectCopy = true;
 
-        if (pszCompress == NULL)
-            papszCreateOptions = CSLSetNameValue(papszCreateOptions, "COMPRESS", "JPEG");
+        if(pszCompress == NULL )
+            papszCreateOptions =
+                CSLSetNameValue(papszCreateOptions, "COMPRESS", "JPEG");
 
-        papszCreateOptions = CSLSetNameValue(papszCreateOptions, "BLOCKXSIZE", NULL);
-        papszCreateOptions = CSLSetNameValue(papszCreateOptions, "BLOCKYSIZE",
-                                                CPLSPrintf("%d", poSrcDS->GetRasterYSize()));
+        papszCreateOptions =
+            CSLSetNameValue(papszCreateOptions, "BLOCKXSIZE", NULL);
+        papszCreateOptions =
+            CSLSetNameValue(papszCreateOptions, "BLOCKYSIZE",
+                             CPLSPrintf("%d", poSrcDS->GetRasterYSize()));
 
-        if (pszSrcColorSpace != NULL && EQUAL(pszSrcColorSpace, "YCbCr"))
-            papszCreateOptions = CSLSetNameValue(papszCreateOptions, "PHOTOMETRIC", "YCBCR");
+        if( pszSrcColorSpace != NULL && EQUAL(pszSrcColorSpace, "YCbCr") )
+            papszCreateOptions =
+                CSLSetNameValue(papszCreateOptions, "PHOTOMETRIC", "YCBCR");
         else
-            papszCreateOptions = CSLSetNameValue(papszCreateOptions, "PHOTOMETRIC", NULL);
+            papszCreateOptions =
+                CSLSetNameValue(papszCreateOptions, "PHOTOMETRIC", NULL);
 
-        if (poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte)
-            papszCreateOptions = CSLSetNameValue(papszCreateOptions, "NBITS", "12");
+        if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte )
+            papszCreateOptions =
+                CSLSetNameValue(papszCreateOptions, "NBITS", "12");
         else
-            papszCreateOptions = CSLSetNameValue(papszCreateOptions, "NBITS", NULL);
+            papszCreateOptions =
+                CSLSetNameValue(papszCreateOptions, "NBITS", NULL);
 
         papszCreateOptions = CSLSetNameValue(papszCreateOptions, "TILED", NULL);
-        papszCreateOptions = CSLSetNameValue(papszCreateOptions, "JPEG_QUALITY", NULL);
+        papszCreateOptions =
+            CSLSetNameValue(papszCreateOptions, "JPEG_QUALITY", NULL);
     }
-    if (fpJPEG)
+    if( fpJPEG )
+    {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpJPEG));
+    }
 
     return bJPEGDirectCopy;
 }
@@ -176,40 +193,42 @@ int GTIFF_CanDirectCopyFromJPEG(GDALDataset* poSrcDS, char** &papszCreateOptions
 /*                     GTIFF_DirectCopyFromJPEG()                       */
 /************************************************************************/
 
-CPLErr GTIFF_DirectCopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
-                                GDALProgressFunc pfnProgress, void * pProgressData,
-                                int& bShouldFallbackToNormalCopyIfFail)
+CPLErr GTIFF_DirectCopyFromJPEG( GDALDataset* poDS, GDALDataset* poSrcDS,
+                                 GDALProgressFunc pfnProgress,
+                                 void * pProgressData,
+                                 int& bShouldFallbackToNormalCopyIfFail )
 {
     bShouldFallbackToNormalCopyIfFail = TRUE;
 
     poSrcDS = GetUnderlyingDataset(poSrcDS);
-    if (poSrcDS == NULL)
+    if( poSrcDS == NULL )
         return CE_Failure;
 
     VSILFILE* fpJPEG = VSIFOpenL(poSrcDS->GetDescription(), "rb");
-    if (fpJPEG == NULL)
+    if( fpJPEG == NULL )
         return CE_Failure;
 
     CPLErr eErr = CE_None;
 
     VSIFSeekL(fpJPEG, 0, SEEK_END);
-    tmsize_t nSize = (tmsize_t) VSIFTellL(fpJPEG);
+    tmsize_t nSize = static_cast<tmsize_t>( VSIFTellL(fpJPEG) );
     VSIFSeekL(fpJPEG, 0, SEEK_SET);
 
     void* pabyJPEGData = VSIMalloc(nSize);
-    if (pabyJPEGData == NULL)
+    if( pabyJPEGData == NULL )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpJPEG));
         return CE_Failure;
     }
 
-    if (pabyJPEGData != NULL &&
-        (tmsize_t)VSIFReadL(pabyJPEGData, 1, nSize, fpJPEG) == nSize)
+    if( pabyJPEGData != NULL &&
+        static_cast<tmsize_t>( VSIFReadL(pabyJPEGData, 1, nSize, fpJPEG) ) ==
+        nSize )
     {
         bShouldFallbackToNormalCopyIfFail = FALSE;
 
         TIFF* hTIFF = (TIFF*) poDS->GetInternalHandle(NULL);
-        if (TIFFWriteRawStrip(hTIFF, 0, pabyJPEGData, nSize) != nSize)
+        if( TIFFWriteRawStrip(hTIFF, 0, pabyJPEGData, nSize) != nSize )
             eErr = CE_Failure;
 
         if( !pfnProgress( 1.0, NULL, pProgressData ) )
@@ -221,7 +240,7 @@ CPLErr GTIFF_DirectCopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     }
 
     VSIFree(pabyJPEGData);
-    if VSIFCloseL(fpJPEG) != 0 )
+    if( VSIFCloseL(fpJPEG) != 0 )
         eErr = CE_Failure;
 
     return eErr;
@@ -250,94 +269,106 @@ CPLErr GTIFF_DirectCopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
 /*                      GTIFF_CanCopyFromJPEG()                         */
 /************************************************************************/
 
-int GTIFF_CanCopyFromJPEG(GDALDataset* poSrcDS, char** &papszCreateOptions)
+int GTIFF_CanCopyFromJPEG( GDALDataset* poSrcDS, char** &papszCreateOptions )
 {
     poSrcDS = GetUnderlyingDataset(poSrcDS);
-    if (poSrcDS == NULL)
+    if( poSrcDS == NULL )
         return FALSE;
-    if (poSrcDS->GetDriver() == NULL)
+    if( poSrcDS->GetDriver() == NULL )
         return FALSE;
-    if (!EQUAL(GDALGetDriverShortName(poSrcDS->GetDriver()), "JPEG"))
+    if( !EQUAL(GDALGetDriverShortName(poSrcDS->GetDriver()), "JPEG") )
         return FALSE;
 
     const char* pszCompress = CSLFetchNameValue(papszCreateOptions, "COMPRESS");
-    if (pszCompress == NULL || !EQUAL(pszCompress, "JPEG"))
+    if( pszCompress == NULL || !EQUAL(pszCompress, "JPEG") )
         return FALSE;
 
-    int nBlockXSize = atoi(CSLFetchNameValueDef(papszCreateOptions, "BLOCKXSIZE", "0"));
-    int nBlockYSize = atoi(CSLFetchNameValueDef(papszCreateOptions, "BLOCKYSIZE", "0"));
+    const int nBlockXSize =
+        atoi(CSLFetchNameValueDef(papszCreateOptions, "BLOCKXSIZE", "0"));
+    const int nBlockYSize =
+        atoi(CSLFetchNameValueDef(papszCreateOptions, "BLOCKYSIZE", "0"));
     int nMCUSize = 8;
     const char* pszSrcColorSpace =
         poSrcDS->GetMetadataItem("SOURCE_COLOR_SPACE", "IMAGE_STRUCTURE");
-    if (pszSrcColorSpace != NULL && EQUAL(pszSrcColorSpace, "YCbCr"))
+    if( pszSrcColorSpace != NULL && EQUAL(pszSrcColorSpace, "YCbCr") )
         nMCUSize = 16;
 
-    int     nXSize = poSrcDS->GetRasterXSize();
-    int     nYSize = poSrcDS->GetRasterYSize();
-    int     nBands = poSrcDS->GetRasterCount();
-
-    const char* pszPhotometric = CSLFetchNameValue(papszCreateOptions, "PHOTOMETRIC");
-    int bCompatiblePhotometric = (
-            pszPhotometric == NULL ||
-            (nMCUSize == 16 && EQUAL(pszPhotometric, "YCbCr")) ||
-            (nMCUSize == 8 && nBands == 4 &&
-             poSrcDS->GetRasterBand(1)->GetColorInterpretation() == GCI_CyanBand &&
-             poSrcDS->GetRasterBand(2)->GetColorInterpretation() == GCI_MagentaBand &&
-             poSrcDS->GetRasterBand(3)->GetColorInterpretation() == GCI_YellowBand &&
-             poSrcDS->GetRasterBand(4)->GetColorInterpretation() == GCI_BlackBand) ||
-            (nMCUSize == 8 && EQUAL(pszPhotometric, "RGB") && nBands == 3) ||
-            (nMCUSize == 8 && EQUAL(pszPhotometric, "MINISBLACK") && nBands == 1) );
-    if (!bCompatiblePhotometric)
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+    const int nBands = poSrcDS->GetRasterCount();
+
+    const char* pszPhotometric =
+        CSLFetchNameValue(papszCreateOptions, "PHOTOMETRIC");
+
+    const bool bCompatiblePhotometric =
+        pszPhotometric == NULL ||
+        (nMCUSize == 16 && EQUAL(pszPhotometric, "YCbCr")) ||
+        (nMCUSize == 8 && nBands == 4 &&
+         poSrcDS->GetRasterBand(1)->GetColorInterpretation() == GCI_CyanBand &&
+         poSrcDS->GetRasterBand(2)->GetColorInterpretation() ==
+         GCI_MagentaBand &&
+         poSrcDS->GetRasterBand(3)->GetColorInterpretation() ==
+         GCI_YellowBand &&
+         poSrcDS->GetRasterBand(4)->GetColorInterpretation() ==
+         GCI_BlackBand) ||
+        (nMCUSize == 8 && EQUAL(pszPhotometric, "RGB") && nBands == 3) ||
+        (nMCUSize == 8 && EQUAL(pszPhotometric, "MINISBLACK") && nBands == 1);
+    if( !bCompatiblePhotometric )
         return FALSE;
 
-    if ( nBands == 4 && pszPhotometric == NULL &&
+    if( nBands == 4 && pszPhotometric == NULL &&
          poSrcDS->GetRasterBand(1)->GetColorInterpretation() == GCI_CyanBand &&
-         poSrcDS->GetRasterBand(2)->GetColorInterpretation() == GCI_MagentaBand &&
-         poSrcDS->GetRasterBand(3)->GetColorInterpretation() == GCI_YellowBand &&
+         poSrcDS->GetRasterBand(2)->GetColorInterpretation() ==
+         GCI_MagentaBand &&
+         poSrcDS->GetRasterBand(3)->GetColorInterpretation() ==
+         GCI_YellowBand &&
          poSrcDS->GetRasterBand(4)->GetColorInterpretation() == GCI_BlackBand )
     {
-        papszCreateOptions = CSLSetNameValue(papszCreateOptions, "PHOTOMETRIC", "CMYK");
+        papszCreateOptions =
+            CSLSetNameValue(papszCreateOptions, "PHOTOMETRIC", "CMYK");
     }
 
-    const char* pszInterleave = CSLFetchNameValue(papszCreateOptions, "INTERLEAVE");
-    int bCompatibleInterleave = ( pszInterleave == NULL ||
-                                  (nBands > 1 && EQUAL(pszInterleave, "PIXEL")) ||
-                                  nBands == 1 );
+    const char* pszInterleave =
+        CSLFetchNameValue(papszCreateOptions, "INTERLEAVE");
+
+    const bool bCompatibleInterleave =
+        pszInterleave == NULL ||
+        (nBands > 1 && EQUAL(pszInterleave, "PIXEL")) ||
+        nBands == 1;
     if( !bCompatibleInterleave )
         return FALSE;
 
-    if ( (nBlockXSize == nXSize || (nBlockXSize % nMCUSize) == 0) &&
+    if( (nBlockXSize == nXSize || (nBlockXSize % nMCUSize) == 0) &&
          (nBlockYSize == nYSize || (nBlockYSize % nMCUSize) == 0) &&
          poSrcDS->GetRasterBand(1)->GetRasterDataType() == GDT_Byte &&
          CSLFetchNameValue(papszCreateOptions, "NBITS") == NULL &&
          CSLFetchNameValue(papszCreateOptions, "JPEG_QUALITY") == NULL )
     {
-        if (nMCUSize == 16 && pszPhotometric == NULL)
-            papszCreateOptions = CSLSetNameValue(papszCreateOptions, "PHOTOMETRIC", "YCBCR");
+        if( nMCUSize == 16 && pszPhotometric == NULL )
+            papszCreateOptions =
+                CSLSetNameValue(papszCreateOptions, "PHOTOMETRIC", "YCBCR");
         return TRUE;
     }
-    else
-    {
-        return FALSE;
-    }
+
+    return FALSE;
 }
 
 /************************************************************************/
 /*                      GTIFF_ErrorExitJPEG()                           */
 /************************************************************************/
 
-static void GTIFF_ErrorExitJPEG(j_common_ptr cinfo)
+static void GTIFF_ErrorExitJPEG( j_common_ptr cinfo )
 {
     jmp_buf *setjmp_buffer = (jmp_buf *) cinfo->client_data;
-    char buffer[JMSG_LENGTH_MAX];
+    char buffer[JMSG_LENGTH_MAX] = { '\0' };
 
-    /* Create the message */
+    // Create the message.
     (*cinfo->err->format_message) (cinfo, buffer);
 
     CPLError( CE_Failure, CPLE_AppDefined,
               "libjpeg: %s", buffer );
 
-    /* Return control to the setjmp point */
+    // Return control to the setjmp point.
     longjmp(*setjmp_buffer, 1);
 }
 
@@ -346,32 +377,31 @@ static void GTIFF_ErrorExitJPEG(j_common_ptr cinfo)
 /************************************************************************/
 
 static
-void GTIFF_Set_TIFFTAG_JPEGTABLES(TIFF* hTIFF,
-                                  jpeg_decompress_struct& sDInfo,
-                                  jpeg_compress_struct& sCInfo)
+void GTIFF_Set_TIFFTAG_JPEGTABLES( TIFF* hTIFF,
+                                   jpeg_decompress_struct& sDInfo,
+                                   jpeg_compress_struct& sCInfo )
 {
-    char szTmpFilename[128];
-    snprintf(szTmpFilename, sizeof(szTmpFilename), "/vsimem/tables_%p", &sDInfo);
+    char szTmpFilename[128] = { '\0' };
+    snprintf(szTmpFilename, sizeof(szTmpFilename),
+             "/vsimem/tables_%p", &sDInfo);
     VSILFILE* fpTABLES = VSIFOpenL(szTmpFilename, "wb+");
 
-    uint16  nPhotometric;
+    uint16 nPhotometric = 0;
     TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric );
 
     jpeg_vsiio_dest( &sCInfo, fpTABLES );
 
-    // Avoid unnecessary tables to be emitted
+    // Avoid unnecessary tables to be emitted.
     if( nPhotometric != PHOTOMETRIC_YCBCR )
     {
-        JQUANT_TBL* qtbl;
-        JHUFF_TBL* htbl;
-        qtbl = sCInfo.quant_tbl_ptrs[1];
-        if (qtbl != NULL)
+        JQUANT_TBL* qtbl = sCInfo.quant_tbl_ptrs[1];
+        if( qtbl != NULL )
             qtbl->sent_table = TRUE;
-        htbl = sCInfo.dc_huff_tbl_ptrs[1];
-        if (htbl != NULL)
+        JHUFF_TBL* htbl = sCInfo.dc_huff_tbl_ptrs[1];
+        if( htbl != NULL )
             htbl->sent_table = TRUE;
         htbl = sCInfo.ac_huff_tbl_ptrs[1];
-        if (htbl != NULL)
+        if( htbl != NULL )
             htbl->sent_table = TRUE;
     }
     jpeg_write_tables( &sCInfo );
@@ -379,8 +409,11 @@ void GTIFF_Set_TIFFTAG_JPEGTABLES(TIFF* hTIFF,
     CPL_IGNORE_RET_VAL(VSIFCloseL(fpTABLES));
 
     vsi_l_offset nSizeTables = 0;
-    GByte* pabyJPEGTablesData = VSIGetMemFileBuffer(szTmpFilename, &nSizeTables, FALSE);
-    TIFFSetField(hTIFF, TIFFTAG_JPEGTABLES, (int)nSizeTables, pabyJPEGTablesData);
+    GByte* pabyJPEGTablesData =
+        VSIGetMemFileBuffer(szTmpFilename, &nSizeTables, FALSE);
+    TIFFSetField( hTIFF, TIFFTAG_JPEGTABLES,
+                  static_cast<int>(nSizeTables),
+                  pabyJPEGTablesData );
 
     VSIUnlink(szTmpFilename);
 }
@@ -389,11 +422,11 @@ void GTIFF_Set_TIFFTAG_JPEGTABLES(TIFF* hTIFF,
 /*             GTIFF_CopyFromJPEG_WriteAdditionalTags()                 */
 /************************************************************************/
 
-CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags(TIFF* hTIFF,
-                                              GDALDataset* poSrcDS)
+CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags( TIFF* hTIFF,
+                                               GDALDataset* poSrcDS )
 {
     poSrcDS = GetUnderlyingDataset(poSrcDS);
-    if (poSrcDS == NULL)
+    if( poSrcDS == NULL )
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
@@ -401,13 +434,13 @@ CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags(TIFF* hTIFF,
 /* -------------------------------------------------------------------- */
 
     VSILFILE* fpJPEG = VSIFOpenL(poSrcDS->GetDescription(), "rb");
-    if (fpJPEG == NULL)
+    if( fpJPEG == NULL )
         return CE_Failure;
 
     struct jpeg_error_mgr sJErr;
     struct jpeg_decompress_struct sDInfo;
     jmp_buf setjmp_buffer;
-    if (setjmp(setjmp_buffer))
+    if( setjmp(setjmp_buffer) )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpJPEG));
         return CE_Failure;
@@ -438,35 +471,33 @@ CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags(TIFF* hTIFF,
 /*      Write TIFFTAG_REFERENCEBLACKWHITE if needed.                    */
 /* -------------------------------------------------------------------- */
 
-    uint16 nPhotometric;
+    uint16 nPhotometric = 0;
     if( !TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &(nPhotometric) ) )
         nPhotometric = PHOTOMETRIC_MINISBLACK;
 
-    uint16 nBitsPerSample;
+    uint16 nBitsPerSample = 0;
     if( !TIFFGetField(hTIFF, TIFFTAG_BITSPERSAMPLE, &(nBitsPerSample)) )
         nBitsPerSample = 1;
 
-    if ( nPhotometric == PHOTOMETRIC_YCBCR )
+    if( nPhotometric == PHOTOMETRIC_YCBCR )
     {
         /*
          * A ReferenceBlackWhite field *must* be present since the
          * default value is inappropriate for YCbCr.  Fill in the
          * proper value if application didn't set it.
          */
-        float *ref;
-        if (!TIFFGetField(hTIFF, TIFFTAG_REFERENCEBLACKWHITE,
-                    &ref))
+        float *ref = NULL;
+        if( !TIFFGetField(hTIFF, TIFFTAG_REFERENCEBLACKWHITE, &ref) )
         {
-            float refbw[6];
             long top = 1L << nBitsPerSample;
-            refbw[0] = 0;
-            refbw[1] = (float)(top-1L);
-            refbw[2] = (float)(top>>1);
+            float refbw[6] = { 0.0 };
+            refbw[1] = static_cast<float>(top - 1L);
+            refbw[2] = static_cast<float>(top >> 1);
             refbw[3] = refbw[1];
             refbw[4] = refbw[2];
             refbw[5] = refbw[1];
-            TIFFSetField(hTIFF, TIFFTAG_REFERENCEBLACKWHITE,
-                        refbw);
+            TIFFSetField( hTIFF, TIFFTAG_REFERENCEBLACKWHITE,
+                          refbw );
         }
     }
 
@@ -474,14 +505,16 @@ CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags(TIFF* hTIFF,
 /*      Write TIFFTAG_YCBCRSUBSAMPLING if needed.                       */
 /* -------------------------------------------------------------------- */
 
-    if ( nPhotometric == PHOTOMETRIC_YCBCR && sDInfo.num_components == 3 )
+    if( nPhotometric == PHOTOMETRIC_YCBCR && sDInfo.num_components == 3 )
     {
-        if ((sDInfo.comp_info[0].h_samp_factor == 1 || sDInfo.comp_info[0].h_samp_factor == 2) &&
-            (sDInfo.comp_info[0].v_samp_factor == 1 || sDInfo.comp_info[0].v_samp_factor == 2) &&
+        if( (sDInfo.comp_info[0].h_samp_factor == 1 ||
+             sDInfo.comp_info[0].h_samp_factor == 2) &&
+            (sDInfo.comp_info[0].v_samp_factor == 1 ||
+             sDInfo.comp_info[0].v_samp_factor == 2) &&
             sDInfo.comp_info[1].h_samp_factor == 1 &&
             sDInfo.comp_info[1].v_samp_factor == 1 &&
             sDInfo.comp_info[2].h_samp_factor == 1 &&
-            sDInfo.comp_info[2].v_samp_factor == 1)
+            sDInfo.comp_info[2].v_samp_factor == 1 )
         {
             TIFFSetField(hTIFF, TIFFTAG_YCBCRSUBSAMPLING,
                          sDInfo.comp_info[0].h_samp_factor,
@@ -489,7 +522,10 @@ CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags(TIFF* hTIFF,
         }
         else
         {
-            CPLDebug("GTiff", "Unusual sampling factors. TIFFTAG_YCBCRSUBSAMPLING not written.");
+            CPLDebug(
+                "GTiff",
+                "Unusual sampling factors. "
+                "TIFFTAG_YCBCRSUBSAMPLING not written." );
         }
     }
 
@@ -526,7 +562,7 @@ typedef struct
     jvirt_barray_ptr *pSrcCoeffs;
 } GTIFF_CopyBlockFromJPEGArgs;
 
-static CPLErr GTIFF_CopyBlockFromJPEG(GTIFF_CopyBlockFromJPEGArgs* psArgs)
+static CPLErr GTIFF_CopyBlockFromJPEG( GTIFF_CopyBlockFromJPEGArgs* psArgs )
 {
     CPLString osTmpFilename(CPLSPrintf("/vsimem/%p", psArgs->psDInfo));
     VSILFILE* fpMEM = VSIFOpenL(osTmpFilename, "wb+");
@@ -535,7 +571,7 @@ static CPLErr GTIFF_CopyBlockFromJPEG(GTIFF_CopyBlockFromJPEGArgs* psArgs)
 /*      Initialization of the compressor                                */
 /* -------------------------------------------------------------------- */
     jmp_buf setjmp_buffer;
-    if (setjmp(setjmp_buffer))
+    if( setjmp(setjmp_buffer) )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpMEM));
         VSIUnlink(osTmpFilename);
@@ -561,34 +597,30 @@ static CPLErr GTIFF_CopyBlockFromJPEG(GTIFF_CopyBlockFromJPEGArgs* psArgs)
     sJErr.error_exit = GTIFF_ErrorExitJPEG;
     sCInfo.client_data = (void *) &setjmp_buffer;
 
-    /* Initialize destination compression parameters from source values */
+    // Initialize destination compression parameters from source values.
     jpeg_create_compress(&sCInfo);
     jpeg_copy_critical_parameters(psDInfo, &sCInfo);
 
-    /* ensure libjpeg won't write any extraneous markers */
+    // Ensure libjpeg won't write any extraneous markers.
     sCInfo.write_JFIF_header = FALSE;
     sCInfo.write_Adobe_marker = FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Allocated destination coefficient array                         */
 /* -------------------------------------------------------------------- */
-    int bIsTiled = TIFFIsTiled(hTIFF);
+    const bool bIsTiled = CPL_TO_BOOL(TIFFIsTiled(hTIFF));
 
-    int nJPEGWidth, nJPEGHeight;
-    if (bIsTiled)
+    int nJPEGWidth = nBlockXSize;
+    int nJPEGHeight = nBlockYSize;
+    if( !bIsTiled )
     {
-        nJPEGWidth = nBlockXSize;
-        nJPEGHeight = nBlockYSize;
-    }
-    else
-    {
-        nJPEGWidth = MIN(nBlockXSize, nXSize - iX * nBlockXSize);
-        nJPEGHeight = MIN(nBlockYSize, nYSize - iY * nBlockYSize);
+        nJPEGWidth = std::min(nBlockXSize, nXSize - iX * nBlockXSize);
+        nJPEGHeight = std::min(nBlockYSize, nYSize - iY * nBlockYSize);
     }
 
-    /* Code partially derived from libjpeg transupp.c */
+    // Code partially derived from libjpeg transupp.c.
 
-    /* Correct the destination's image dimensions as necessary */
+    // Correct the destination's image dimensions as necessary.
     #if JPEG_LIB_VERSION >= 70
     sCInfo.jpeg_width = nJPEGWidth;
     sCInfo.jpeg_height = nJPEGHeight;
@@ -597,23 +629,23 @@ static CPLErr GTIFF_CopyBlockFromJPEG(GTIFF_CopyBlockFromJPEGArgs* psArgs)
     sCInfo.image_height = nJPEGHeight;
     #endif
 
-    /* Save x/y offsets measured in iMCUs */
-    int x_crop_offset = (iX * nBlockXSize) / iMCU_sample_width;
-    int y_crop_offset = (iY * nBlockYSize) / iMCU_sample_height;
+    // Save x/y offsets measured in iMCUs.
+    const int x_crop_offset = (iX * nBlockXSize) / iMCU_sample_width;
+    const int y_crop_offset = (iY * nBlockYSize) / iMCU_sample_height;
 
     jvirt_barray_ptr* pDstCoeffs = (jvirt_barray_ptr *)
         (*sCInfo.mem->alloc_small) ((j_common_ptr) &sCInfo, JPOOL_IMAGE,
                                     sizeof(jvirt_barray_ptr) * sCInfo.num_components);
-    int ci;
 
-    for (ci = 0; ci < sCInfo.num_components; ci++)
+    for( int ci = 0; ci < sCInfo.num_components; ci++ )
     {
         jpeg_component_info *compptr = sCInfo.comp_info + ci;
         int h_samp_factor, v_samp_factor;
-        if (sCInfo.num_components == 1)
+        if( sCInfo.num_components == 1 )
         {
-            /* we're going to force samp factors to 1x1 in this case */
-            h_samp_factor = v_samp_factor = 1;
+            // Force samp factors to 1x1 in this case.
+            h_samp_factor = 1;
+            v_samp_factor = 1;
         }
         else
         {
@@ -626,90 +658,95 @@ static CPLErr GTIFF_CopyBlockFromJPEG(GTIFF_CopyBlockFromJPEGArgs* psArgs)
                 (nJPEGHeight + iMCU_sample_height - 1) / iMCU_sample_height;
         int nWidth_in_blocks = width_in_iMCUs * h_samp_factor;
         int nHeight_in_blocks = height_in_iMCUs * v_samp_factor;
-        pDstCoeffs[ci] = (*sCInfo.mem->request_virt_barray)
-                ((j_common_ptr) &sCInfo, JPOOL_IMAGE, FALSE,
-                nWidth_in_blocks, nHeight_in_blocks, (JDIMENSION) v_samp_factor);
+        pDstCoeffs[ci] = (*sCInfo.mem->request_virt_barray)(
+            (j_common_ptr) &sCInfo, JPOOL_IMAGE, FALSE,
+            nWidth_in_blocks, nHeight_in_blocks,
+            (JDIMENSION) v_samp_factor );
     }
 
     jpeg_vsiio_dest( &sCInfo, fpMEM );
 
-    /* Start compressor (note no image data is actually written here) */
+    // Start compressor (note no image data is actually written here).
     jpeg_write_coefficients(&sCInfo, pDstCoeffs);
 
     jpeg_suppress_tables( &sCInfo, TRUE );
 
-    /* We simply have to copy the right amount of data (the destination's
-    * image size) starting at the given X and Y offsets in the source.
-    */
-    for (ci = 0; ci < sCInfo.num_components; ci++)
+    // Must copy the right amount of data (the destination's image size)
+    // starting at the given X and Y offsets in the source.
+    for( int ci = 0; ci < sCInfo.num_components; ci++ )
     {
         jpeg_component_info *compptr = sCInfo.comp_info + ci;
-        int x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
-        int y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
-        JDIMENSION nSrcWidthInBlocks = psDInfo->comp_info[ci].width_in_blocks;
-        JDIMENSION nSrcHeightInBlocks = psDInfo->comp_info[ci].height_in_blocks;
+        const int x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+        const int y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
+        const JDIMENSION nSrcWidthInBlocks =
+            psDInfo->comp_info[ci].width_in_blocks;
+        const JDIMENSION nSrcHeightInBlocks =
+            psDInfo->comp_info[ci].height_in_blocks;
 
         JDIMENSION nXBlocksToCopy = compptr->width_in_blocks;
-        if (x_crop_blocks + compptr->width_in_blocks > nSrcWidthInBlocks)
+        if( x_crop_blocks + compptr->width_in_blocks > nSrcWidthInBlocks )
             nXBlocksToCopy = nSrcWidthInBlocks - x_crop_blocks;
 
-        for (JDIMENSION dst_blk_y = 0;
-                        dst_blk_y < compptr->height_in_blocks;
-                        dst_blk_y += compptr->v_samp_factor)
+        for( JDIMENSION dst_blk_y = 0;
+             dst_blk_y < compptr->height_in_blocks;
+             dst_blk_y += compptr->v_samp_factor )
         {
-            JBLOCKARRAY dst_buffer = (*psDInfo->mem->access_virt_barray)
-                            ((j_common_ptr) psDInfo, pDstCoeffs[ci],
-                                dst_blk_y,
-                                (JDIMENSION) compptr->v_samp_factor, TRUE);
+            JBLOCKARRAY dst_buffer = (*psDInfo->mem->access_virt_barray)(
+                (j_common_ptr) psDInfo, pDstCoeffs[ci],
+                dst_blk_y,
+                (JDIMENSION) compptr->v_samp_factor, TRUE );
 
             int offset_y = 0;
             if( bIsTiled &&
                 dst_blk_y + y_crop_blocks + compptr->v_samp_factor >
-                                                        nSrcHeightInBlocks)
+                                                        nSrcHeightInBlocks )
             {
-                int nYBlocks = nSrcHeightInBlocks - (dst_blk_y + y_crop_blocks);
-                if (nYBlocks > 0)
+                const int nYBlocks =
+                    nSrcHeightInBlocks - (dst_blk_y + y_crop_blocks);
+                if( nYBlocks > 0 )
                 {
-                    JBLOCKARRAY src_buffer = (*psDInfo->mem->access_virt_barray)
-                                ((j_common_ptr) psDInfo, pSrcCoeffs[ci],
-                                dst_blk_y + y_crop_blocks,
-                                    (JDIMENSION) 1, FALSE);
-                    for (; offset_y < nYBlocks; offset_y++)
+                    JBLOCKARRAY src_buffer =
+                        (*psDInfo->mem->access_virt_barray)(
+                            (j_common_ptr) psDInfo, pSrcCoeffs[ci],
+                            dst_blk_y + y_crop_blocks,
+                            (JDIMENSION) 1, FALSE );
+                    for( ; offset_y < nYBlocks; offset_y++ )
                     {
-                        memcpy(dst_buffer[offset_y],
-                               src_buffer[offset_y] + x_crop_blocks,
-                               nXBlocksToCopy * (DCTSIZE2 * sizeof(JCOEF)));
-                        if (nXBlocksToCopy < compptr->width_in_blocks)
+                        memcpy( dst_buffer[offset_y],
+                                src_buffer[offset_y] + x_crop_blocks,
+                                nXBlocksToCopy * (DCTSIZE2 * sizeof(JCOEF)));
+                        if( nXBlocksToCopy < compptr->width_in_blocks )
                         {
-                            memset(dst_buffer[offset_y]  + nXBlocksToCopy, 0,
+                            memset(dst_buffer[offset_y] + nXBlocksToCopy, 0,
                                    (compptr->width_in_blocks - nXBlocksToCopy) *
-                                                    (DCTSIZE2 * sizeof(JCOEF)));
+                                   (DCTSIZE2 * sizeof(JCOEF)));
                         }
                     }
                 }
 
-                for (; offset_y < compptr->v_samp_factor; offset_y++)
+                for( ; offset_y < compptr->v_samp_factor; offset_y++ )
                 {
-                    memset(dst_buffer[offset_y], 0,
-                           compptr->width_in_blocks * (DCTSIZE2 * sizeof(JCOEF)));
+                    memset(
+                        dst_buffer[offset_y], 0,
+                        compptr->width_in_blocks * DCTSIZE2 * sizeof(JCOEF) );
                 }
             }
             else
             {
-                JBLOCKARRAY src_buffer = (*psDInfo->mem->access_virt_barray)
-                                ((j_common_ptr) psDInfo, pSrcCoeffs[ci],
-                                dst_blk_y + y_crop_blocks,
-                                (JDIMENSION) compptr->v_samp_factor, FALSE);
-                for (; offset_y < compptr->v_samp_factor; offset_y++)
+                JBLOCKARRAY src_buffer = (*psDInfo->mem->access_virt_barray)(
+                    (j_common_ptr) psDInfo, pSrcCoeffs[ci],
+                    dst_blk_y + y_crop_blocks,
+                    (JDIMENSION) compptr->v_samp_factor, FALSE );
+                for( ; offset_y < compptr->v_samp_factor; offset_y++ )
                 {
                     memcpy(dst_buffer[offset_y],
                            src_buffer[offset_y] + x_crop_blocks,
                            nXBlocksToCopy * (DCTSIZE2 * sizeof(JCOEF)));
-                    if (nXBlocksToCopy < compptr->width_in_blocks)
+                    if( nXBlocksToCopy < compptr->width_in_blocks )
                     {
                         memset(dst_buffer[offset_y] + nXBlocksToCopy, 0,
                                (compptr->width_in_blocks - nXBlocksToCopy) *
-                                                   (DCTSIZE2 * sizeof(JCOEF)));
+                               (DCTSIZE2 * sizeof(JCOEF)));
                     }
                 }
             }
@@ -729,16 +766,21 @@ static CPLErr GTIFF_CopyBlockFromJPEG(GTIFF_CopyBlockFromJPEGArgs* psArgs)
 
     CPLErr eErr = CE_None;
 
-    if ( bIsTiled )
+    if( bIsTiled )
     {
-        if ((vsi_l_offset)TIFFWriteRawTile(hTIFF, iX + iY * nXBlocks,
-                                           pabyJPEGData, static_cast<tmsize_t>(nSize)) != nSize)
+        if( static_cast<vsi_l_offset>(
+               TIFFWriteRawTile(
+                   hTIFF, iX + iY * nXBlocks,
+                   pabyJPEGData,
+                   static_cast<tmsize_t>(nSize) ) ) != nSize )
             eErr = CE_Failure;
     }
     else
     {
-        if ((vsi_l_offset)TIFFWriteRawStrip(hTIFF, iX + iY * nXBlocks,
-                                            pabyJPEGData, static_cast<tmsize_t>(nSize)) != nSize)
+        if( static_cast<vsi_l_offset>(
+               TIFFWriteRawStrip(
+                   hTIFF, iX + iY * nXBlocks,
+                   pabyJPEGData, static_cast<tmsize_t>(nSize) ) ) != nSize )
             eErr = CE_Failure;
     }
 
@@ -758,11 +800,11 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     bShouldFallbackToNormalCopyIfFail = TRUE;
 
     poSrcDS = GetUnderlyingDataset(poSrcDS);
-    if (poSrcDS == NULL)
+    if( poSrcDS == NULL )
         return CE_Failure;
 
     VSILFILE* fpJPEG = VSIFOpenL(poSrcDS->GetDescription(), "rb");
-    if (fpJPEG == NULL)
+    if( fpJPEG == NULL )
         return CE_Failure;
 
     CPLErr eErr = CE_None;
@@ -774,7 +816,7 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     struct jpeg_decompress_struct sDInfo;
     memset(&sDInfo, 0, sizeof(sDInfo));
     jmp_buf setjmp_buffer;
-    if (setjmp(setjmp_buffer))
+    if( setjmp(setjmp_buffer) )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpJPEG));
         jpeg_destroy_decompress(&sDInfo);
@@ -787,13 +829,14 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
 
     jpeg_create_decompress(&sDInfo);
 
-    /* This is to address bug related in ticket #1795 */
-    if (CPLGetConfigOption("JPEGMEM", NULL) == NULL)
+    // This is to address bug related in ticket #1795.
+    if( CPLGetConfigOption("JPEGMEM", NULL) == NULL )
     {
-        /* If the user doesn't provide a value for JPEGMEM, we want to be sure */
-        /* that at least 500 MB will be used before creating the temporary file */
+        // If the user doesn't provide a value for JPEGMEM, be sure that at
+        // least 500 MB will be used before creating the temporary file.
+        const long nMinMemory = 500 * 1024 * 1024;
         sDInfo.mem->max_memory_to_use =
-                MAX(sDInfo.mem->max_memory_to_use, 500 * 1024 * 1024);
+            std::max(sDInfo.mem->max_memory_to_use, nMinMemory);
     }
 
     jpeg_vsiio_src( &sDInfo, fpJPEG );
@@ -804,13 +847,9 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Compute MCU dimensions                                          */
 /* -------------------------------------------------------------------- */
-    int iMCU_sample_width, iMCU_sample_height;
-    if (sDInfo.num_components == 1)
-    {
-        iMCU_sample_width = 8;
-        iMCU_sample_height = 8;
-    }
-    else
+    int iMCU_sample_width = 8;
+    int iMCU_sample_height = 8;
+    if( sDInfo.num_components != 1 )
     {
         iMCU_sample_width = sDInfo.max_h_samp_factor * 8;
         iMCU_sample_height = sDInfo.max_v_samp_factor * 8;
@@ -819,18 +858,18 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Get raster and block dimensions                                 */
 /* -------------------------------------------------------------------- */
-    int nXSize, nYSize /* , nBands */;
-    int nBlockXSize, nBlockYSize;
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
 
-    nXSize = poDS->GetRasterXSize();
-    nYSize = poDS->GetRasterYSize();
-    /* nBands = poDS->GetRasterCount(); */
+    const int nXSize = poDS->GetRasterXSize();
+    const int nYSize = poDS->GetRasterYSize();
+    // nBands = poDS->GetRasterCount();
 
-    /* We don't use the GDAL block dimensions because of the split-band */
-    /* mechanism that can expose a pseudo one-line-strip whereas the */
-    /* real layout is a single big strip */
+    // Don't use the GDAL block dimensions because of the split-band
+    // mechanism that can expose a pseudo one-line-strip whereas the
+    // real layout is a single big strip.
 
-    TIFF* hTIFF = (TIFF*) poDS->GetInternalHandle(NULL);
+    TIFF* hTIFF = static_cast<TIFF*>( poDS->GetInternalHandle(NULL) );
     if( TIFFIsTiled(hTIFF) )
     {
         TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(nBlockXSize) );
@@ -838,27 +877,27 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     }
     else
     {
-        uint32  nRowsPerStrip;
+        uint32 nRowsPerStrip = 0;
         if( !TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP,
                         &(nRowsPerStrip) ) )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                    "RowsPerStrip not defined ... assuming all one strip." );
-            nRowsPerStrip = nYSize; /* dummy value */
+                      "RowsPerStrip not defined ... assuming all one strip." );
+            nRowsPerStrip = nYSize;  // Dummy value.
         }
 
         // If the rows per strip is larger than the file we will get
         // confused.  libtiff internally will treat the rowsperstrip as
         // the image height and it is best if we do too. (#4468)
-        if (nRowsPerStrip > (uint32)nYSize)
+        if( nRowsPerStrip > static_cast<uint32>(nYSize) )
             nRowsPerStrip = nYSize;
 
         nBlockXSize = nXSize;
         nBlockYSize = nRowsPerStrip;
     }
 
-    int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize;
-    int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize;
+    const int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize;
+    const int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize;
 
 /* -------------------------------------------------------------------- */
 /*      Copy blocks.                                                    */
@@ -866,9 +905,9 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
 
     bShouldFallbackToNormalCopyIfFail = FALSE;
 
-    for(int iY=0;iY<nYBlocks && eErr == CE_None;iY++)
+    for( int iY = 0; iY < nYBlocks && eErr == CE_None; iY++ )
     {
-        for(int iX=0;iX<nXBlocks && eErr == CE_None;iX++)
+        for( int iX = 0; iX < nXBlocks && eErr == CE_None; iX++ )
         {
             GTIFF_CopyBlockFromJPEGArgs sArgs;
             sArgs.hTIFF = hTIFF;
@@ -886,7 +925,7 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
 
             eErr = GTIFF_CopyBlockFromJPEG( &sArgs );
 
-            if (!pfnProgress((iY * nXBlocks + iX + 1) * 1.0 /
+            if( !pfnProgress((iY * nXBlocks + iX + 1) * 1.0 /
                                 (nXBlocks * nYBlocks),
                              NULL, pProgressData ) )
                 eErr = CE_Failure;
@@ -906,4 +945,4 @@ CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
     return eErr;
 }
 
-#endif // HAVE_LIBJPEG
+#endif  // HAVE_LIBJPEG
diff --git a/frmts/gtiff/gt_jpeg_copy.h b/frmts/gtiff/gt_jpeg_copy.h
index 513f101..b62bb6c 100644
--- a/frmts/gtiff/gt_jpeg_copy.h
+++ b/frmts/gtiff/gt_jpeg_copy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_jpeg_copy.h 33806 2016-03-28 22:26:19Z goatbar $
+ * $Id: gt_jpeg_copy.h 34122 2016-04-26 14:48:21Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Specialized copy of JPEG content into TIFF.
@@ -36,11 +36,13 @@
 
 #ifdef JPEG_DIRECT_COPY
 
-int GTIFF_CanDirectCopyFromJPEG(GDALDataset* poSrcDS, char** &papszCreateOptions);
+int GTIFF_CanDirectCopyFromJPEG( GDALDataset* poSrcDS,
+                                 char** &papszCreateOptions );
 
-CPLErr GTIFF_DirectCopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
-                                GDALProgressFunc pfnProgress, void * pProgressData,
-                                int& bShouldFallbackToNormalCopyIfFail);
+CPLErr GTIFF_DirectCopyFromJPEG( GDALDataset* poDS, GDALDataset* poSrcDS,
+                                 GDALProgressFunc pfnProgress,
+                                 void * pProgressData,
+                                 int& bShouldFallbackToNormalCopyIfFail );
 
 #endif // JPEG_DIRECT_COPY
 
@@ -48,14 +50,14 @@ CPLErr GTIFF_DirectCopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
 
 #include "tiffio.h"
 
-int GTIFF_CanCopyFromJPEG(GDALDataset* poSrcDS, char** &papszCreateOptions);
+int GTIFF_CanCopyFromJPEG( GDALDataset* poSrcDS, char** &papszCreateOptions );
 
-CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags(TIFF* hTIFF,
-                                              GDALDataset* poSrcDS);
+CPLErr GTIFF_CopyFromJPEG_WriteAdditionalTags( TIFF* hTIFF,
+                                               GDALDataset* poSrcDS );
 
-CPLErr GTIFF_CopyFromJPEG(GDALDataset* poDS, GDALDataset* poSrcDS,
-                          GDALProgressFunc pfnProgress, void * pProgressData,
-                          int& bShouldFallbackToNormalCopyIfFail);
+CPLErr GTIFF_CopyFromJPEG( GDALDataset* poDS, GDALDataset* poSrcDS,
+                           GDALProgressFunc pfnProgress, void * pProgressData,
+                           int& bShouldFallbackToNormalCopyIfFail );
 
 #endif // HAVE_LIBJPEG
 
diff --git a/frmts/gtiff/gt_overview.cpp b/frmts/gtiff/gt_overview.cpp
index cc7981d..98e65bf 100644
--- a/frmts/gtiff/gt_overview.cpp
+++ b/frmts/gtiff/gt_overview.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gt_overview.cpp 35041 2016-08-10 14:04:52Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Code to build overviews of external databases as a TIFF file.
@@ -29,15 +28,32 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
+#include "cpl_port.h"
 #include "gt_overview.h"
+
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
 #include "gtiff.h"
+#include "tiff.h"
+#include "tiffvers.h"
 #include "tifvsi.h"
 #include "xtiffio.h"
 
-#include <algorithm>
+CPL_CVSID("$Id: gt_overview.cpp 37477 2017-02-26 03:04:08Z goatbar $");
 
-CPL_CVSID("$Id: gt_overview.cpp 35041 2016-08-10 14:04:52Z rouault $");
+// TODO(schwehr): Explain why 128 and not 127.
+static const int knMaxOverviews = 128;
 
 /************************************************************************/
 /*                         GTIFFWriteDirectory()                        */
@@ -49,30 +65,31 @@ CPL_CVSID("$Id: gt_overview.cpp 35041 2016-08-10 14:04:52Z rouault $");
 /*      function is called.                                             */
 /************************************************************************/
 
-toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize,
-                           int nBitsPerPixel, int nPlanarConfig, int nSamples,
-                           int nBlockXSize, int nBlockYSize,
-                           int bTiled, int nCompressFlag, int nPhotometric,
-                           int nSampleFormat,
-                           int nPredictor,
-                           unsigned short *panRed,
-                           unsigned short *panGreen,
-                           unsigned short *panBlue,
-                           int nExtraSamples,
-                           unsigned short *panExtraSampleValues,
-                           const char *pszMetadata )
+toff_t GTIFFWriteDirectory( TIFF *hTIFF, int nSubfileType,
+                            int nXSize, int nYSize,
+                            int nBitsPerPixel, int nPlanarConfig, int nSamples,
+                            int nBlockXSize, int nBlockYSize,
+                            int bTiled, int nCompressFlag, int nPhotometric,
+                            int nSampleFormat,
+                            int nPredictor,
+                            unsigned short *panRed,
+                            unsigned short *panGreen,
+                            unsigned short *panBlue,
+                            int nExtraSamples,
+                            unsigned short *panExtraSampleValues,
+                            const char *pszMetadata,
+                            const char* pszJPEGQuality,
+                            const char* pszJPEGTablesMode,
+                            const char* pszNoData )
 
 {
-    toff_t nBaseDirOffset;
-    toff_t nOffset;
-
-    nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );
+    const toff_t nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );
 
-    /* This is a bit of a hack to cause (*tif->tif_cleanup)(tif); to be called */
-    /* See https://trac.osgeo.org/gdal/ticket/2055 */
+    // This is a bit of a hack to cause (*tif->tif_cleanup)(tif); to be called.
+    // See https://trac.osgeo.org/gdal/ticket/2055
     TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, COMPRESSION_NONE );
 
-#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION >= 20051201 /* 3.8.0 */
+#if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION >= 20051201  // 3.8.0
     TIFFFreeDirectory( hTIFF );
 #endif
 
@@ -100,17 +117,20 @@ toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize
         TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
     }
     else
+    {
         TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );
+    }
 
     TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, nSubfileType );
 
-    if (panExtraSampleValues != NULL)
+    if( panExtraSampleValues != NULL )
     {
-        TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples, panExtraSampleValues );
+        TIFFSetField( hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples,
+                      panExtraSampleValues );
     }
 
-    if ( nCompressFlag == COMPRESSION_LZW ||
-         nCompressFlag == COMPRESSION_ADOBE_DEFLATE )
+    if( nCompressFlag == COMPRESSION_LZW ||
+        nCompressFlag == COMPRESSION_ADOBE_DEFLATE )
         TIFFSetField( hTIFF, TIFFTAG_PREDICTOR, nPredictor );
 
 /* -------------------------------------------------------------------- */
@@ -127,6 +147,35 @@ toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize
     if( pszMetadata && strlen(pszMetadata) > 0 )
         TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, pszMetadata );
 
+
+/* -------------------------------------------------------------------- */
+/*      Write JPEG tables if needed.                                    */
+/* -------------------------------------------------------------------- */
+    if( nCompressFlag == COMPRESSION_JPEG )
+    {
+        GTiffWriteJPEGTables( hTIFF,
+                              (nPhotometric == PHOTOMETRIC_RGB) ? "RGB" :
+                              (nPhotometric == PHOTOMETRIC_YCBCR) ? "YCBCR" :
+                                                                "MINISBLACK",
+                              pszJPEGQuality,
+                              pszJPEGTablesMode );
+
+        if( nPhotometric == PHOTOMETRIC_YCBCR )
+        {
+            // Explicitly register the subsampling so that JPEGFixupTags
+            // is a no-op (helps for cloud optimized geotiffs)
+            TIFFSetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, 2, 2 );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write no data value if we have one.                             */
+/* -------------------------------------------------------------------- */
+    if( pszNoData != NULL )
+    {
+        TIFFSetField( hTIFF, TIFFTAG_GDAL_NODATA, pszNoData );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Write directory, and return byte offset.                        */
 /* -------------------------------------------------------------------- */
@@ -137,9 +186,10 @@ toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize
     }
 
     TIFFWriteDirectory( hTIFF );
-    TIFFSetDirectory( hTIFF, (tdir_t) (TIFFNumberOfDirectories(hTIFF)-1) );
+    TIFFSetDirectory( hTIFF,
+                      static_cast<tdir_t>(TIFFNumberOfDirectories(hTIFF) - 1) );
 
-    nOffset = TIFFCurrentDirOffset( hTIFF );
+    const toff_t nOffset = TIFFCurrentDirOffset( hTIFF );
 
     TIFFSetSubDirectory( hTIFF, nBaseDirOffset );
 
@@ -158,18 +208,18 @@ void GTIFFBuildOverviewMetadata( const char *pszResampling,
     osMetadata = "<GDALMetadata>";
 
     if( pszResampling && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
-        osMetadata += "<Item name=\"RESAMPLING\" sample=\"0\">AVERAGE_BIT2GRAYSCALE</Item>";
+        osMetadata +=
+            "<Item name=\"RESAMPLING\" sample=\"0\">"
+            "AVERAGE_BIT2GRAYSCALE</Item>";
 
     if( poBaseDS->GetMetadataItem( "INTERNAL_MASK_FLAGS_1" ) )
     {
-        int iBand;
-
-        for( iBand = 0; iBand < 200; iBand++ )
+        for( int iBand = 0; iBand < 200; iBand++ )
         {
             CPLString osItem;
             CPLString osName;
 
-            osName.Printf( "INTERNAL_MASK_FLAGS_%d", iBand+1 );
+            osName.Printf( "INTERNAL_MASK_FLAGS_%d", iBand + 1 );
             if( poBaseDS->GetMetadataItem( osName ) )
             {
                 osItem.Printf( "<Item name=\"%s\">%s</Item>",
@@ -181,10 +231,11 @@ void GTIFFBuildOverviewMetadata( const char *pszResampling,
     }
 
     const char* pszNoDataValues = poBaseDS->GetMetadataItem("NODATA_VALUES");
-    if (pszNoDataValues)
+    if( pszNoDataValues )
     {
         CPLString osItem;
-        osItem.Printf( "<Item name=\"NODATA_VALUES\">%s</Item>", pszNoDataValues );
+        osItem.Printf( "<Item name=\"NODATA_VALUES\">%s</Item>",
+                       pszNoDataValues );
         osMetadata += osItem;
     }
 
@@ -206,24 +257,30 @@ GTIFFBuildOverviews( const char * pszFilename,
                      GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    TIFF    *hOTIFF;
-    int     nBitsPerPixel=0, nCompression=COMPRESSION_NONE, nPhotometric=0;
-    int     nSampleFormat=0, nPlanarConfig, iOverview, iBand;
-    int     nXSize=0, nYSize=0;
-
     if( nBands == 0 || nOverviews == 0 )
         return CE_None;
 
-    if (!GTiffOneTimeInit())
+    if( !GTiffOneTimeInit() )
         return CE_Failure;
 
+    TIFF *hOTIFF = NULL;
+    int nBitsPerPixel = 0;
+    int nCompression = COMPRESSION_NONE;
+    int nPhotometric = 0;
+    int nSampleFormat = 0;
+    int nPlanarConfig = 0;
+    int iOverview = 0;
+    int nXSize = 0;
+    int nYSize = 0;
+
 /* -------------------------------------------------------------------- */
 /*      Verify that the list of bands is suitable for emitting in       */
 /*      TIFF file.                                                      */
 /* -------------------------------------------------------------------- */
-    for( iBand = 0; iBand < nBands; iBand++ )
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        int     nBandBits, nBandFormat;
+        int nBandBits = 0;
+        int nBandFormat = 0;
         GDALRasterBand *hBand = papoBandList[iBand];
 
         switch( hBand->GetRasterDataType() )
@@ -284,14 +341,14 @@ GTIFFBuildOverviews( const char * pszFilename,
             break;
 
           default:
-            CPLAssert( FALSE );
+            CPLAssert( false );
             return CE_Failure;
         }
 
         if( hBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) )
         {
             nBandBits =
-                atoi(hBand->GetMetadataItem("NBITS","IMAGE_STRUCTURE"));
+                atoi(hBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE"));
 
             if( nBandBits == 1
                 && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
@@ -336,8 +393,9 @@ GTIFFBuildOverviews( const char * pszFilename,
 
     if( pszCompress != NULL && pszCompress[0] != '\0' )
     {
-        nCompression = GTIFFGetCompressionMethod(pszCompress, "COMPRESS_OVERVIEW");
-        if (nCompression < 0)
+        nCompression =
+            GTIFFGetCompressionMethod(pszCompress, "COMPRESS_OVERVIEW");
+        if( nCompression < 0 )
             return CE_Failure;
     }
 
@@ -362,8 +420,9 @@ GTIFFBuildOverviews( const char * pszFilename,
     else
         nPlanarConfig = PLANARCONFIG_SEPARATE;
 
-    const char* pszInterleave = CPLGetConfigOption( "INTERLEAVE_OVERVIEW", NULL );
-    if (pszInterleave != NULL && pszInterleave[0] != '\0')
+    const char* pszInterleave =
+        CPLGetConfigOption( "INTERLEAVE_OVERVIEW", NULL );
+    if( pszInterleave != NULL && pszInterleave[0] != '\0' )
     {
         if( EQUAL( pszInterleave, "PIXEL" ) )
             nPlanarConfig = PLANARCONFIG_CONTIG;
@@ -371,9 +430,11 @@ GTIFFBuildOverviews( const char * pszFilename,
             nPlanarConfig = PLANARCONFIG_SEPARATE;
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "INTERLEAVE_OVERVIEW=%s unsupported, value must be PIXEL or BAND. ignoring",
-                      pszInterleave );
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "INTERLEAVE_OVERVIEW=%s unsupported, "
+                "value must be PIXEL or BAND. ignoring",
+                pszInterleave );
         }
     }
 
@@ -386,13 +447,14 @@ GTIFFBuildOverviews( const char * pszFilename,
              && !STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
     {
         nPhotometric = PHOTOMETRIC_PALETTE;
-        /* should set the colormap up at this point too! */
+        // Should set the colormap up at this point too!
     }
     else
         nPhotometric = PHOTOMETRIC_MINISBLACK;
 
-    const char* pszPhotometric = CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", NULL );
-    if (pszPhotometric != NULL && pszPhotometric[0] != '\0')
+    const char* pszPhotometric =
+        CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", NULL );
+    if( pszPhotometric != NULL && pszPhotometric[0] != '\0' )
     {
         if( EQUAL( pszPhotometric, "MINISBLACK" ) )
             nPhotometric = PHOTOMETRIC_MINISBLACK;
@@ -410,21 +472,27 @@ GTIFFBuildOverviews( const char * pszFilename,
         {
             nPhotometric = PHOTOMETRIC_YCBCR;
 
-            /* Because of subsampling, setting YCBCR without JPEG compression leads */
-            /* to a crash currently. Would need to make GTiffRasterBand::IWriteBlock() */
-            /* aware of subsampling so that it doesn't overrun buffer size returned */
-            /* by libtiff */
-            if ( nCompression != COMPRESSION_JPEG )
+            // Because of subsampling, setting YCBCR without JPEG compression
+            // leads to a crash currently. Would need to make
+            // GTiffRasterBand::IWriteBlock() aware of subsampling so that it
+            // doesn't overrun buffer size returned by libtiff.
+            if( nCompression != COMPRESSION_JPEG )
             {
-                CPLError(CE_Failure, CPLE_NotSupported,
-                         "Currently, PHOTOMETRIC_OVERVIEW=YCBCR requires COMPRESS_OVERVIEW=JPEG");
+                CPLError(
+                    CE_Failure, CPLE_NotSupported,
+                    "Currently, PHOTOMETRIC_OVERVIEW=YCBCR requires "
+                    "COMPRESS_OVERVIEW=JPEG" );
                 return CE_Failure;
             }
 
-            if (pszInterleave != NULL && pszInterleave[0] != '\0' && nPlanarConfig == PLANARCONFIG_SEPARATE)
+            if( pszInterleave != NULL &&
+                pszInterleave[0] != '\0' &&
+                nPlanarConfig == PLANARCONFIG_SEPARATE )
             {
-                CPLError(CE_Failure, CPLE_NotSupported,
-                         "PHOTOMETRIC_OVERVIEW=YCBCR requires INTERLEAVE_OVERVIEW=PIXEL");
+                CPLError(
+                    CE_Failure, CPLE_NotSupported,
+                    "PHOTOMETRIC_OVERVIEW=YCBCR requires "
+                    "INTERLEAVE_OVERVIEW=PIXEL" );
                 return CE_Failure;
             }
             else
@@ -432,13 +500,15 @@ GTIFFBuildOverviews( const char * pszFilename,
                 nPlanarConfig = PLANARCONFIG_CONTIG;
             }
 
-            /* YCBCR strictly requires 3 bands. Not less, not more */
-            /* Issue an explicit error message as libtiff one is a bit cryptic : */
-            /* JPEGLib:Bogus input colorspace */
-            if ( nBands != 3 )
+            // YCBCR strictly requires 3 bands. Not less, not more
+            // Issue an explicit error message as libtiff one is a bit cryptic:
+            // JPEGLib:Bogus input colorspace.
+            if( nBands != 3 )
             {
-                CPLError(CE_Failure, CPLE_NotSupported,
-                         "PHOTOMETRIC_OVERVIEW=YCBCR requires a source raster with only 3 bands (RGB)");
+                CPLError(
+                    CE_Failure, CPLE_NotSupported,
+                    "PHOTOMETRIC_OVERVIEW=YCBCR requires a source raster "
+                    "with only 3 bands (RGB)" );
                 return CE_Failure;
             }
         }
@@ -456,9 +526,10 @@ GTIFFBuildOverviews( const char * pszFilename,
         }
         else
         {
-            CPLError( CE_Warning, CPLE_IllegalArg,
-                      "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.\n",
-                      pszPhotometric );
+            CPLError(
+                CE_Warning, CPLE_IllegalArg,
+                "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.",
+                pszPhotometric );
         }
     }
 
@@ -466,20 +537,21 @@ GTIFFBuildOverviews( const char * pszFilename,
 /*      Figure out the predictor value to use.                          */
 /* -------------------------------------------------------------------- */
     int nPredictor = PREDICTOR_NONE;
-    if ( nCompression == COMPRESSION_LZW ||
-         nCompression == COMPRESSION_ADOBE_DEFLATE )
+    if( nCompression == COMPRESSION_LZW ||
+        nCompression == COMPRESSION_ADOBE_DEFLATE )
     {
-        const char* pszPredictor = CPLGetConfigOption( "PREDICTOR_OVERVIEW", NULL );
-        if( pszPredictor  != NULL )
+        const char* pszPredictor =
+            CPLGetConfigOption( "PREDICTOR_OVERVIEW", NULL );
+        if( pszPredictor != NULL )
         {
-            nPredictor =  atoi( pszPredictor );
+            nPredictor = atoi( pszPredictor );
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create the file, if it does not already exist.                  */
 /* -------------------------------------------------------------------- */
-    VSIStatBufL  sStatBuf;
+    VSIStatBufL sStatBuf;
     VSILFILE* fpL = NULL;
 
     if( VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
@@ -487,30 +559,31 @@ GTIFFBuildOverviews( const char * pszFilename,
     /* -------------------------------------------------------------------- */
     /*      Compute the uncompressed size.                                  */
     /* -------------------------------------------------------------------- */
-        double  dfUncompressedOverviewSize = 0;
-        int nDataTypeSize = GDALGetDataTypeSize(papoBandList[0]->GetRasterDataType())/8;
+        double dfUncompressedOverviewSize = 0;
+        int nDataTypeSize =
+            GDALGetDataTypeSizeBytes(papoBandList[0]->GetRasterDataType());
 
         for( iOverview = 0; iOverview < nOverviews; iOverview++ )
         {
-            int    nOXSize, nOYSize;
-
-            nOXSize = (nXSize + panOverviewList[iOverview] - 1)
+            const int nOXSize = (nXSize + panOverviewList[iOverview] - 1)
                 / panOverviewList[iOverview];
-            nOYSize = (nYSize + panOverviewList[iOverview] - 1)
+            const int nOYSize = (nYSize + panOverviewList[iOverview] - 1)
                 / panOverviewList[iOverview];
 
             dfUncompressedOverviewSize +=
-                nOXSize * ((double)nOYSize) * nBands * nDataTypeSize;
+                nOXSize * static_cast<double>(nOYSize) * nBands * nDataTypeSize;
         }
 
         if( nCompression == COMPRESSION_NONE
             && dfUncompressedOverviewSize > 4200000000.0 )
         {
     #ifndef BIGTIFF_SUPPORT
-            CPLError( CE_Failure, CPLE_NotSupported,
-                    "The overview file would be larger than 4GB\n"
-                    "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n"
-                    "Creation failed." );
+            CPLError(
+                CE_Failure, CPLE_NotSupported,
+                "The overview file would be larger than 4GB, "
+                "but this is the largest size a TIFF can be, "
+                "and BigTIFF is unavailable.  "
+                "Creation failed." );
             return CE_Failure;
     #endif
         }
@@ -522,33 +595,35 @@ GTIFFBuildOverviews( const char * pszFilename,
         if( pszBIGTIFF == NULL )
             pszBIGTIFF = "IF_NEEDED";
 
-        int bCreateBigTIFF = FALSE;
+        bool bCreateBigTIFF = false;
         if( EQUAL(pszBIGTIFF,"IF_NEEDED") )
         {
             if( nCompression == COMPRESSION_NONE
                 && dfUncompressedOverviewSize > 4200000000.0 )
-                bCreateBigTIFF = TRUE;
+                bCreateBigTIFF = true;
         }
         else if( EQUAL(pszBIGTIFF,"IF_SAFER") )
         {
-            /* Look at the size of the base image and suppose that */
-            /* the added overview levels won't be more than 1/2 of */
-            /* the size of the base image. The theory says 1/3 of the */
-            /* base image size if the overview levels are 2, 4, 8, 16... */
-            /* Thus take 1/2 as the security margin for 1/3 */
-            double dfUncompressedImageSize =
-                        nXSize * ((double)nYSize) * nBands * nDataTypeSize;
-            if( dfUncompressedImageSize * .5 > 4200000000.0 )
-                bCreateBigTIFF = TRUE;
+            // Look at the size of the base image and suppose that
+            // the added overview levels won't be more than 1/2 of
+            // the size of the base image. The theory says 1/3 of the
+            // base image size if the overview levels are 2, 4, 8, 16.
+            // Thus take 1/2 as the security margin for 1/3.
+            const double dfUncompressedImageSize =
+                nXSize * static_cast<double>(nYSize) * nBands * nDataTypeSize;
+            if( dfUncompressedImageSize * 0.5 > 4200000000.0 )
+                bCreateBigTIFF = true;
         }
         else
         {
             bCreateBigTIFF = CPLTestBool( pszBIGTIFF );
-            if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE
+            if( !bCreateBigTIFF && nCompression == COMPRESSION_NONE
                 && dfUncompressedOverviewSize > 4200000000.0 )
             {
-                CPLError( CE_Failure, CPLE_NotSupported,
-                    "The overview file will be larger than 4GB, so BigTIFF is necessary.\n"
+                CPLError(
+                    CE_Failure, CPLE_NotSupported,
+                    "The overview file will be larger than 4GB, "
+                    "so BigTIFF is necessary.  "
                     "Creation failed.");
                 return CE_Failure;
             }
@@ -557,10 +632,11 @@ GTIFFBuildOverviews( const char * pszFilename,
     #ifndef BIGTIFF_SUPPORT
         if( bCreateBigTIFF )
         {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                    "BigTIFF requested, but GDAL built without BigTIFF\n"
-                    "enabled libtiff, request ignored." );
-            bCreateBigTIFF = FALSE;
+            CPLError(
+                CE_Warning, CPLE_NotSupported,
+                "BigTIFF requested, but GDAL built without BigTIFF "
+                "enabled libtiff, request ignored." );
+            bCreateBigTIFF = false;
         }
     #endif
 
@@ -571,13 +647,14 @@ GTIFFBuildOverviews( const char * pszFilename,
         if( fpL == NULL )
             hOTIFF = NULL;
         else
-            hOTIFF = VSI_TIFFOpen( pszFilename, (bCreateBigTIFF) ? "w+8" : "w+", fpL );
+            hOTIFF =
+               VSI_TIFFOpen( pszFilename, bCreateBigTIFF ? "w+8" : "w+", fpL );
         if( hOTIFF == NULL )
         {
             if( CPLGetLastErrorNo() == 0 )
                 CPLError( CE_Failure, CPLE_OpenFailed,
-                          "Attempt to create new tiff file `%s'\n"
-                          "failed in VSI_TIFFOpen().\n",
+                          "Attempt to create new tiff file `%s' "
+                          "failed in VSI_TIFFOpen().",
                           pszFilename );
             if( fpL != NULL )
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
@@ -598,8 +675,8 @@ GTIFFBuildOverviews( const char * pszFilename,
         {
             if( CPLGetLastErrorNo() == 0 )
                 CPLError( CE_Failure, CPLE_OpenFailed,
-                          "Attempt to create new tiff file `%s'\n"
-                          "failed in VSI_TIFFOpen().\n",
+                          "Attempt to create new tiff file `%s' "
+                          "failed in VSI_TIFFOpen().",
                           pszFilename );
             if( fpL != NULL )
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
@@ -610,34 +687,36 @@ GTIFFBuildOverviews( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Do we have a palette?  If so, create a TIFF compatible version. */
 /* -------------------------------------------------------------------- */
-    unsigned short      *panRed=NULL, *panGreen=NULL, *panBlue=NULL;
+    unsigned short *panRed = NULL;
+    unsigned short *panGreen = NULL;
+    unsigned short *panBlue = NULL;
 
     if( nPhotometric == PHOTOMETRIC_PALETTE )
     {
         GDALColorTable *poCT = papoBandList[0]->GetColorTable();
-        int nColorCount;
+        int nColorCount = 65536;
 
         if( nBitsPerPixel <= 8 )
             nColorCount = 256;
-        else
-            nColorCount = 65536;
 
-        panRed   = (unsigned short *)
-            CPLCalloc(nColorCount,sizeof(unsigned short));
-        panGreen = (unsigned short *)
-            CPLCalloc(nColorCount,sizeof(unsigned short));
-        panBlue  = (unsigned short *)
-            CPLCalloc(nColorCount,sizeof(unsigned short));
+        panRed = static_cast<unsigned short *>(
+            CPLCalloc(nColorCount, sizeof(unsigned short)) );
+        panGreen = static_cast<unsigned short *>(
+            CPLCalloc(nColorCount, sizeof(unsigned short)) );
+        panBlue = static_cast<unsigned short *>(
+            CPLCalloc(nColorCount, sizeof(unsigned short)) );
 
         for( int iColor = 0; iColor < nColorCount; iColor++ )
         {
-            GDALColorEntry  sRGB;
+          GDALColorEntry sRGB = { 0, 0, 0, 0 };
 
             if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) )
             {
-                panRed[iColor] = (unsigned short) (257 * sRGB.c1);
-                panGreen[iColor] = (unsigned short) (257 * sRGB.c2);
-                panBlue[iColor] = (unsigned short) (257 * sRGB.c3);
+                // TODO(schwehr): Check for underflow.
+                // Going from signed short to unsigned short.
+                panRed[iColor] = static_cast<unsigned short>(257 * sRGB.c1);
+                panGreen[iColor] = static_cast<unsigned short>(257 * sRGB.c2);
+                panBlue[iColor] = static_cast<unsigned short>(257 * sRGB.c3);
             }
         }
     }
@@ -653,37 +732,54 @@ GTIFFBuildOverviews( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Loop, creating overviews.                                       */
 /* -------------------------------------------------------------------- */
-    int nOvrBlockXSize, nOvrBlockYSize;
+    int nOvrBlockXSize = 0;
+    int nOvrBlockYSize = 0;
     GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
-    for( iOverview = 0; iOverview < nOverviews; iOverview++ )
+
+    CPLString osNoData; // don't move this in inner scope
+    const char* pszNoData = NULL;
+    int bNoDataSet = FALSE;
+    const double dfNoDataValue = papoBandList[0]->GetNoDataValue(&bNoDataSet);
+    if( bNoDataSet )
     {
-        int    nOXSize, nOYSize;
+        osNoData = GTiffFormatGDALNoDataTagValue(dfNoDataValue);
+        pszNoData = osNoData.c_str();
+    }
 
-        nOXSize = (nXSize + panOverviewList[iOverview] - 1)
+    for( iOverview = 0; iOverview < nOverviews; iOverview++ )
+    {
+        const int nOXSize = (nXSize + panOverviewList[iOverview] - 1)
             / panOverviewList[iOverview];
-        nOYSize = (nYSize + panOverviewList[iOverview] - 1)
+        const int nOYSize = (nYSize + panOverviewList[iOverview] - 1)
             / panOverviewList[iOverview];
 
-        GTIFFWriteDirectory(hOTIFF, FILETYPE_REDUCEDIMAGE,
-                            nOXSize, nOYSize, nBitsPerPixel,
-                            nPlanarConfig, nBands,
-                            nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression,
-                            nPhotometric, nSampleFormat, nPredictor,
-                            panRed, panGreen, panBlue,
-                            0, NULL, /* FIXME? how can we fetch extrasamples */
-                            osMetadata );
+        GTIFFWriteDirectory( hOTIFF, FILETYPE_REDUCEDIMAGE,
+                             nOXSize, nOYSize, nBitsPerPixel,
+                             nPlanarConfig, nBands,
+                             nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression,
+                             nPhotometric, nSampleFormat, nPredictor,
+                             panRed, panGreen, panBlue,
+                             0,
+                             NULL, // TODO: How can we fetch extrasamples?
+                             osMetadata,
+                             CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ),
+                             CPLGetConfigOption( "JPEG_TABLESMODE_OVERVIEW", NULL ),
+                             pszNoData
+                           );
     }
 
-    if (panRed)
+    if( panRed )
     {
         CPLFree(panRed);
         CPLFree(panGreen);
         CPLFree(panBlue);
-        panRed = panGreen = panBlue = NULL;
+        panRed = NULL;
+        panGreen = NULL;
+        panBlue = NULL;
     }
 
     XTIFFClose( hOTIFF );
-    if (VSIFCloseL(fpL) != 0 )
+    if( VSIFCloseL(fpL) != 0 )
         return CE_Failure;
     fpL = NULL;
 
@@ -691,45 +787,60 @@ GTIFFBuildOverviews( const char * pszFilename,
 /*      Open the overview dataset so that we can get at the overview    */
 /*      bands.                                                          */
 /* -------------------------------------------------------------------- */
-    GDALDataset *hODS;
-    CPLErr eErr = CE_None;
-
-    hODS = (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    GDALDataset *hODS =
+        static_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
     if( hODS == NULL )
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
 /*      Do we need to set the jpeg quality?                             */
 /* -------------------------------------------------------------------- */
-    TIFF *hTIFF = (TIFF*) hODS->GetInternalHandle(NULL);
+    TIFF *hTIFF = static_cast<TIFF *>( hODS->GetInternalHandle(NULL) );
 
     if( nCompression == COMPRESSION_JPEG
         && CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
     {
-        int nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
+        const int nJpegQuality =
+            atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
         TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY,
                       nJpegQuality );
         GTIFFSetJpegQuality((GDALDatasetH)hODS, nJpegQuality);
     }
 
+    if( nCompression == COMPRESSION_JPEG
+        && CPLGetConfigOption( "JPEG_TABLESMODE_OVERVIEW", NULL ) != NULL )
+    {
+        const int nJpegTablesMode =
+            atoi(CPLGetConfigOption("JPEG_TABLESMODE_OVERVIEW",
+                            CPLSPrintf("%d", knGTIFFJpegTablesModeDefault)));
+        TIFFSetField( hTIFF, TIFFTAG_JPEGTABLESMODE,
+                      nJpegTablesMode );
+        GTIFFSetJpegTablesMode((GDALDatasetH)hODS, nJpegTablesMode);
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Loop writing overview data.                                     */
 /* -------------------------------------------------------------------- */
 
-    int * panOverviewListSorted = static_cast<int*>(
-                                        CPLMalloc(sizeof(int) * nOverviews));
+    int *panOverviewListSorted =
+        static_cast<int*>(CPLMalloc(sizeof(int) * nOverviews));
     memcpy( panOverviewListSorted, panOverviewList, sizeof(int) * nOverviews);
     std::sort(panOverviewListSorted, panOverviewListSorted + nOverviews);
 
     GTIFFSetInExternalOvr(true);
 
-    if (nCompression != COMPRESSION_NONE &&
+    CPLErr eErr = CE_None;
+
+    if( nCompression != COMPRESSION_NONE &&
         nPlanarConfig == PLANARCONFIG_CONTIG &&
-        GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) == FALSE &&
+        !GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) &&
         papoBandList[0]->GetColorTable() == NULL &&
-        (STARTS_WITH_CI(pszResampling, "NEAR") || EQUAL(pszResampling, "AVERAGE") ||
-         EQUAL(pszResampling, "GAUSS") || EQUAL(pszResampling, "CUBIC") ||
-         EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") ||
+        (STARTS_WITH_CI(pszResampling, "NEAR") ||
+         EQUAL(pszResampling, "AVERAGE") ||
+         EQUAL(pszResampling, "GAUSS") ||
+         EQUAL(pszResampling, "CUBIC") ||
+         EQUAL(pszResampling, "CUBICSPLINE") ||
+         EQUAL(pszResampling, "LANCZOS") ||
          EQUAL(pszResampling, "BILINEAR")))
     {
         // In the case of pixel interleaved compressed overviews, we want to
@@ -739,10 +850,10 @@ GTIFFBuildOverviews( const char * pszFilename,
         GDALRasterBand ***papapoOverviewBands =
             static_cast<GDALRasterBand ***>(
                 CPLCalloc(sizeof(void *), nBands) );
-        for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
+        for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
         {
             GDALRasterBand *poSrcBand = papoBandList[iBand];
-            GDALRasterBand *poDstBand = hODS->GetRasterBand( iBand+1 );
+            GDALRasterBand *poDstBand = hODS->GetRasterBand( iBand + 1 );
             papapoOverviewBands[iBand] =
                 static_cast<GDALRasterBand **>(
                     CPLCalloc(sizeof(void *), nOverviews) );
@@ -757,7 +868,6 @@ GTIFFBuildOverviews( const char * pszFilename,
                 for( int j = -1; j < poDstBand->GetOverviewCount() &&
                                  eErr == CE_None; j++ )
                 {
-                    int    nOvFactor;
                     GDALRasterBand * poOverview =
                             (j < 0 ) ? poDstBand : poDstBand->GetOverview( j );
                     if( poOverview == NULL )
@@ -766,10 +876,11 @@ GTIFFBuildOverviews( const char * pszFilename,
                         continue;
                     }
 
-                    nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
-                                                    poSrcBand->GetXSize(),
-                                                    poOverview->GetYSize(),
-                                                    poSrcBand->GetYSize());
+                    const int nOvFactor =
+                        GDALComputeOvFactor(poOverview->GetXSize(),
+                                            poSrcBand->GetXSize(),
+                                            poOverview->GetYSize(),
+                                            poSrcBand->GetYSize());
 
                     if( nOvFactor == panOverviewListSorted[i]
                         || nOvFactor == GDALOvLevelAdjust2(
@@ -794,7 +905,7 @@ GTIFFBuildOverviews( const char * pszFilename,
                     nOverviews, papapoOverviewBands,
                     pszResampling, pfnProgress, pProgressData );
 
-        for( iBand = 0; iBand < nBands; iBand++ )
+        for( int iBand = 0; iBand < nBands; iBand++ )
         {
             CPLFree(papapoOverviewBands[iBand]);
         }
@@ -802,58 +913,58 @@ GTIFFBuildOverviews( const char * pszFilename,
     }
     else
     {
-        GDALRasterBand   **papoOverviews;
-
-        papoOverviews = (GDALRasterBand **) CPLCalloc(sizeof(void*),128);
+        GDALRasterBand **papoOverviews =
+            static_cast<GDALRasterBand **>(
+                CPLCalloc( sizeof(void*), knMaxOverviews ) );
 
-        for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
+        for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
         {
-            GDALRasterBand    *hSrcBand = papoBandList[iBand];
-            GDALRasterBand    *hDstBand;
-            int               nDstOverviews;
+            GDALRasterBand *hSrcBand = papoBandList[iBand];
+            GDALRasterBand *hDstBand = hODS->GetRasterBand( iBand + 1 );
 
-            hDstBand = hODS->GetRasterBand( iBand+1 );
-
-            int bHasNoData;
-            double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData);
-            if (bHasNoData)
+            int bHasNoData = FALSE;
+            const double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData);
+            if( bHasNoData )
                 hDstBand->SetNoDataValue(noDataValue);
 
             // FIXME: this logic regenerates all overview bands, not only the
-            // ones requested
+            // ones requested.
 
             papoOverviews[0] = hDstBand;
-            nDstOverviews = hDstBand->GetOverviewCount() + 1;
-            CPLAssert( nDstOverviews < 128 );
-            nDstOverviews = MIN(128,nDstOverviews);
+            int nDstOverviews = hDstBand->GetOverviewCount() + 1;
+            CPLAssert( nDstOverviews < knMaxOverviews );
+            nDstOverviews = std::min(knMaxOverviews, nDstOverviews);
 
-            for( int i = 0; i < nDstOverviews-1 && eErr == CE_None; i++ )
+            // TODO(schwehr): Convert to starting with i = 1 and remove +1.
+            for( int i = 0; i < nDstOverviews - 1 && eErr == CE_None; i++ )
             {
                 papoOverviews[i+1] = hDstBand->GetOverview(i);
-                if (papoOverviews[i+1] == NULL)
+                if( papoOverviews[i+1] == NULL )
+                {
                     eErr = CE_Failure;
+                }
                 else
                 {
-                    if (bHasNoData)
+                    if( bHasNoData )
                         papoOverviews[i+1]->SetNoDataValue(noDataValue);
                 }
             }
 
-            void         *pScaledProgressData;
-
-            pScaledProgressData =
-                GDALCreateScaledProgress( iBand / (double) nBands,
-                                        (iBand+1) / (double) nBands,
-                                        pfnProgress, pProgressData );
+            void *pScaledProgressData =
+                GDALCreateScaledProgress(
+                    iBand / static_cast<double>( nBands ),
+                    (iBand + 1) / static_cast<double>( nBands ),
+                    pfnProgress, pProgressData );
 
-            if (eErr == CE_None)
+            if( eErr == CE_None )
                 eErr =
-                    GDALRegenerateOverviews( (GDALRasterBandH) hSrcBand,
-                                        nDstOverviews,
-                                        (GDALRasterBandH *) papoOverviews,
-                                        pszResampling,
-                                        GDALScaledProgress,
-                                        pScaledProgressData);
+                    GDALRegenerateOverviews(
+                        hSrcBand,
+                        nDstOverviews,
+                        reinterpret_cast<GDALRasterBandH *>( papoOverviews ),
+                        pszResampling,
+                        GDALScaledProgress,
+                        pScaledProgressData );
 
             GDALDestroyScaledProgress( pScaledProgressData );
         }
@@ -864,7 +975,7 @@ GTIFFBuildOverviews( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    if (eErr == CE_None)
+    if( eErr == CE_None )
         hODS->FlushCache();
     delete hODS;
 
diff --git a/frmts/gtiff/gt_overview.h b/frmts/gtiff/gt_overview.h
index ffa62a0..270272a 100644
--- a/frmts/gtiff/gt_overview.h
+++ b/frmts/gtiff/gt_overview.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_overview.h 13297 2007-12-09 19:03:50Z rouault $
+ * $Id: gt_overview.h 37184 2017-01-19 12:26:29Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Code to build overviews of external databases as a TIFF file.
@@ -35,18 +35,22 @@
 #include "gdal_priv.h"
 #include "tiffio.h"
 
-toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize,
-                           int nBitsPerPixel, int nPlanarConfig, int nSamples,
-                           int nBlockXSize, int nBlockYSize,
-                           int bTiled, int nCompressFlag, int nPhotometric,
-                           int nSampleFormat,
-                           int nPredictor,
-                           unsigned short *panRed,
-                           unsigned short *panGreen,
-                           unsigned short *panBlue,
-                           int nExtraSamples,
-                           unsigned short *panExtraSampleValues,
-                           const char *pszMetadata );
+toff_t GTIFFWriteDirectory( TIFF *hTIFF, int nSubfileType,
+                            int nXSize, int nYSize,
+                            int nBitsPerPixel, int nPlanarConfig, int nSamples,
+                            int nBlockXSize, int nBlockYSize,
+                            int bTiled, int nCompressFlag, int nPhotometric,
+                            int nSampleFormat,
+                            int nPredictor,
+                            unsigned short *panRed,
+                            unsigned short *panGreen,
+                            unsigned short *panBlue,
+                            int nExtraSamples,
+                            unsigned short *panExtraSampleValues,
+                            const char *pszMetadata,
+                            const char* pszJPEGQuality,
+                            const char* pszJPEGTablesMode,
+                            const char* pszNoData );
 
 void GTIFFBuildOverviewMetadata( const char *pszResampling,
                                  GDALDataset *poBaseDS,
diff --git a/frmts/gtiff/gt_wkt_srs.cpp b/frmts/gtiff/gt_wkt_srs.cpp
index 5d1081d..fe7dfe7 100644
--- a/frmts/gtiff/gt_wkt_srs.cpp
+++ b/frmts/gtiff/gt_wkt_srs.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gt_wkt_srs.cpp 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements translation between GeoTIFF normalized projection
@@ -29,25 +28,48 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_error.h"
+#include "cpl_port.h"
+#include "gt_wkt_srs.h"
+
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+#if HAVE_CXX11 && !defined(__MINGW32__)
+#define HAVE_CXX11_MUTEX 1
+#endif
+#if HAVE_CXX11_MUTEX
+#include <mutex>
+#endif
+
 #include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
-#include "gdal.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "gdal_csv.h"
-#include "geovalues.h"
 #include "gt_citation.h"
-#include "gt_wkt_srs.h"
 #include "gt_wkt_srs_for_gdal.h"
 #include "gt_wkt_srs_priv.h"
 #include "gtiff.h"
+#include "gdal.h"
+#include "geokeys.h"
+#include "geovalues.h"
+#include "ogr_core.h"
 #include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
+#include "tiff.h"
+#include "tiffio.h"
 #include "tifvsi.h"
 #include "xtiffio.h"
 
-CPL_CVSID("$Id: gt_wkt_srs.cpp 33806 2016-03-28 22:26:19Z goatbar $")
+CPL_CVSID("$Id: gt_wkt_srs.cpp 36582 2016-11-30 17:06:18Z goatbar $")
 
-#define ProjLinearUnitsInterpCorrectGeoKey   3059
+static const geokey_t ProjLinearUnitsInterpCorrectGeoKey =
+    static_cast<geokey_t>(3059);
 
 #ifndef CT_HotineObliqueMercatorAzimuthCenter
 #  define CT_HotineObliqueMercatorAzimuthCenter 9815
@@ -82,7 +104,7 @@ static const char * const papszDatumEquiv[] =
     NULL
 };
 
-// older libgeotiff's won't list this.
+// Older libgeotiff's won't list this.
 #ifndef CT_CylindricalEqualArea
 # define CT_CylindricalEqualArea 28
 #endif
@@ -91,17 +113,26 @@ static const char * const papszDatumEquiv[] =
 /*                       LibgeotiffOneTimeInit()                        */
 /************************************************************************/
 
+#if HAVE_CXX11_MUTEX
+static std::mutex oDeleteMutex;
+#else
 static CPLMutex* hMutex = NULL;
+#endif  // HAVE_CXX11_MUTEX
 
 void LibgeotiffOneTimeInit()
 {
-    static int bOneTimeInitDone = FALSE;
+#if HAVE_CXX11_MUTEX
+    std::lock_guard<std::mutex> oLock(oDeleteMutex);
+#else
     CPLMutexHolder oHolder( &hMutex);
+#endif  // HAVE_CXX11_MUTEX
+
+    static bool bOneTimeInitDone = false;
 
-    if (bOneTimeInitDone)
+    if( bOneTimeInitDone )
         return;
 
-    bOneTimeInitDone = TRUE;
+    bOneTimeInitDone = true;
 
     // If linking with an external libgeotiff we hope this will call the
     // SetCSVFilenameHook() in libgeotiff, not the one in gdal/port!
@@ -117,11 +148,14 @@ void LibgeotiffOneTimeInit()
 
 void LibgeotiffOneTimeCleanupMutex()
 {
-    if( hMutex != NULL )
-    {
-        CPLDestroyMutex(hMutex);
-        hMutex = NULL;
-    }
+#if !HAVE_CXX11_MUTEX
+    // >= C++11 uses a lock_guard that does not need cleanup.
+    if( hMutex == NULL )
+        return;
+
+    CPLDestroyMutex(hMutex);
+    hMutex = NULL;
+#endif
 }
 
 /************************************************************************/
@@ -152,17 +186,14 @@ static void GTIFToCPLRecycleString( char **ppszTarget )
 static void WKTMassageDatum( char ** ppszDatum )
 
 {
-    int i, j;
-    char *pszDatum;
-
-    pszDatum = *ppszDatum;
-    if (pszDatum[0] == '\0')
+    char *pszDatum = *ppszDatum;
+    if( !pszDatum || pszDatum[0] == '\0' )
         return;
 
 /* -------------------------------------------------------------------- */
 /*      Translate non-alphanumeric values to underscores.               */
 /* -------------------------------------------------------------------- */
-    for( i = 0; pszDatum[i] != '\0'; i++ )
+    for( int i = 0; pszDatum[i] != '\0'; i++ )
     {
         if( pszDatum[i] != '+'
             && !(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
@@ -176,7 +207,8 @@ static void WKTMassageDatum( char ** ppszDatum )
 /* -------------------------------------------------------------------- */
 /*      Remove repeated and trailing underscores.                       */
 /* -------------------------------------------------------------------- */
-    for( i = 1, j = 0; pszDatum[i] != '\0'; i++ )
+    int j = 0;  // Used after for.
+    for( int i = 1; pszDatum[i] != '\0'; i++ )
     {
         if( pszDatum[j] == '_' && pszDatum[i] == '_' )
             continue;
@@ -192,7 +224,7 @@ static void WKTMassageDatum( char ** ppszDatum )
 /*      Search for datum equivalences.  Specific massaged names get     */
 /*      mapped to OpenGIS specified names.                              */
 /* -------------------------------------------------------------------- */
-    for( i = 0; papszDatumEquiv[i] != NULL; i += 2 )
+    for( int i = 0; papszDatumEquiv[i] != NULL; i += 2 )
     {
         if( EQUAL(*ppszDatum,papszDatumEquiv[i]) )
         {
@@ -213,11 +245,11 @@ static void WKTMassageDatum( char ** ppszDatum )
 /************************************************************************/
 
 /* For example:
-   GTCitationGeoKey (Ascii,215): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 33806 $ $Date: 2016-03-28 15:26:19 -0700 (Mon, 28 Mar 2016) $\nProjection Name = UTM\nUnits = meters\nGeoTIFF Units = meters"
+   GTCitationGeoKey (Ascii,215): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 34309 $ $Date: 2016-05-29 11:29:40 -0700 (Sun, 29 May 2016) $\nProjection Name = UTM\nUnits = meters\nGeoTIFF Units = meters"
 
-   GeogCitationGeoKey (Ascii,267): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 33806 $ $Date: 2016-03-28 15:26:19 -0700 (Mon, 28 Mar 2016) $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
+   GeogCitationGeoKey (Ascii,267): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 34309 $ $Date: 2016-05-29 11:29:40 -0700 (Sun, 29 May 2016) $\nUnable to match Ellipsoid (Datum) to a GeographicTypeGeoKey value\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
 
-   PCSCitationGeoKey (Ascii,214): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 33806 $ $Date: 2016-03-28 15:26:19 -0700 (Mon, 28 Mar 2016) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
+   PCSCitationGeoKey (Ascii,214): "IMAGINE GeoTIFF Support\nCopyright 1991 - 2001 by ERDAS, Inc. All Rights Reserved\n@(#)$RCSfile$ $Revision: 34309 $ $Date: 2016-05-29 11:29:40 -0700 (Sun, 29 May 2016) $\nUTM Zone 10N\nEllipsoid = Clarke 1866\nDatum = NAD27 (CONUS)"
 */
 
 static void GTIFCleanupImagineNames( char *pszCitation )
@@ -230,14 +262,16 @@ static void GTIFCleanupImagineNames( char *pszCitation )
 /*      First, we skip past all the copyright, and RCS stuff.  We       */
 /*      assume that this will have a "$" at the end of it all.          */
 /* -------------------------------------------------------------------- */
-    char *pszSkip;
+    char *pszSkip = pszCitation + strlen(pszCitation) - 1;
 
-    for( pszSkip = pszCitation + strlen(pszCitation) - 1;
+    for( ;
          pszSkip != pszCitation && *pszSkip != '$';
          pszSkip-- ) {}
 
     if( *pszSkip == '$' )
         pszSkip++;
+    if( *pszSkip == '\n' )
+        pszSkip++;
 
     memmove( pszCitation, pszSkip, strlen(pszSkip)+1 );
 
@@ -245,9 +279,7 @@ static void GTIFCleanupImagineNames( char *pszCitation )
 /*      Convert any newlines into spaces, they really gum up the        */
 /*      WKT.                                                            */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; pszCitation[i] != '\0'; i++ )
+    for( int i = 0; pszCitation[i] != '\0'; i++ )
     {
         if( pszCitation[i] == '\n' )
             pszCitation[i] = ' ';
@@ -264,14 +296,15 @@ static int GDALGTIFKeyGet( GTIF *hGTIF, geokey_t key,
                            int nCount,
                            tagtype_t expected_tagtype )
 {
-    tagtype_t tagtype;
+    tagtype_t tagtype = TYPE_UNKNOWN;
     if( !GTIFKeyInfo(hGTIF, key, NULL, &tagtype) )
         return 0;
     if( tagtype != expected_tagtype )
     {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                 "Expected key %s to be of type %s. Got %s",
-                 GTIFKeyName(key), GTIFTypeName(expected_tagtype), GTIFTypeName(tagtype));
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Expected key %s to be of type %s. Got %s",
+                  GTIFKeyName(key), GTIFTypeName(expected_tagtype),
+                  GTIFTypeName(tagtype) );
         return 0;
     }
     return GTIFKeyGet( hGTIF, key, pData, nIndex, nCount );
@@ -282,12 +315,12 @@ static int GDALGTIFKeyGet( GTIF *hGTIF, geokey_t key,
 /************************************************************************/
 
 int GDALGTIFKeyGetASCII( GTIF *hGTIF, geokey_t key,
-                                char* szStr,
-                                int nIndex,
-                                int szStrMaxLen )
+                         char* szStr,
+                         int nIndex,
+                         int szStrMaxLen )
 {
     CPLAssert(nIndex == 0);
-    return GDALGTIFKeyGet(hGTIF, key, szStr, nIndex, szStrMaxLen, TYPE_ASCII);
+    return GDALGTIFKeyGet( hGTIF, key, szStr, nIndex, szStrMaxLen, TYPE_ASCII );
 }
 
 /************************************************************************/
@@ -295,11 +328,11 @@ int GDALGTIFKeyGetASCII( GTIF *hGTIF, geokey_t key,
 /************************************************************************/
 
 int GDALGTIFKeyGetSHORT( GTIF *hGTIF, geokey_t key,
-                                short* pnVal,
-                                int nIndex,
-                                int nCount )
+                         short* pnVal,
+                         int nIndex,
+                         int nCount )
 {
-    return GDALGTIFKeyGet(hGTIF, key, pnVal, nIndex, nCount, TYPE_SHORT);
+    return GDALGTIFKeyGet( hGTIF, key, pnVal, nIndex, nCount, TYPE_SHORT );
 }
 
 /************************************************************************/
@@ -307,11 +340,11 @@ int GDALGTIFKeyGetSHORT( GTIF *hGTIF, geokey_t key,
 /************************************************************************/
 
 int GDALGTIFKeyGetDOUBLE( GTIF *hGTIF, geokey_t key,
-                                 double* pdfVal,
-                                 int nIndex,
-                                 int nCount )
+                          double* pdfVal,
+                          int nIndex,
+                          int nCount )
 {
-    return GDALGTIFKeyGet(hGTIF, key, pdfVal, nIndex, nCount, TYPE_DOUBLE);
+    return GDALGTIFKeyGet( hGTIF, key, pdfVal, nIndex, nCount, TYPE_DOUBLE );
 }
 
 /************************************************************************/
@@ -344,20 +377,25 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         && psDefn->Model != ModelTypeGeographic
         && psDefn->Model != ModelTypeGeocentric )
     {
-        char *pszWKT;
-        char    szPeStr[2400];
+        char *pszWKT = NULL;
+        char szPeStr[2400] = { '\0' };
 
         /** check if there is a pe string citation key **/
-        if( GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szPeStr, 0, sizeof(szPeStr) ) &&
+        if( GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szPeStr,
+                                 0, sizeof(szPeStr) ) &&
             strstr(szPeStr, "ESRI PE String = " ) )
         {
             pszWKT = CPLStrdup( szPeStr + strlen("ESRI PE String = ") );
 
-            if( strstr(pszWKT, "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\"") )
+            if( strstr( pszWKT,
+                        "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\"" ) )
             {
                 oSRS.SetFromUserInput(pszWKT);
-                oSRS.SetExtension( "PROJCS", "PROJ4",
-                                   "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" );
+                oSRS.SetExtension(
+                    "PROJCS", "PROJ4",
+                    "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 "
+                    "+x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null "
+                    "+wktext  +no_defs" );  // TODO(schwehr): Why 2 spaces?
                 oSRS.FixupOrdering();
                 CPLFree(pszWKT);
                 pszWKT = NULL;
@@ -369,21 +407,20 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         else
         {
             char *pszUnitsName = NULL;
-            char    szPCSName[300];
-            int     nKeyCount = 0;
-            int     anVersion[3];
+            char szPCSName[300] = { '\0' };
+            int nKeyCount = 0;
+            int anVersion[3] = { 0 };
 
-            if( hGTIF != NULL )
-                GTIFDirectoryInfo( hGTIF, anVersion, &nKeyCount );
+            GTIFDirectoryInfo( hGTIF, anVersion, &nKeyCount );
 
             if( nKeyCount > 0 ) // Use LOCAL_CS if we have any geokeys at all.
             {
                 // Handle citation.
                 strcpy( szPCSName, "unnamed" );
                 if( !GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szPCSName,
-                                 0, sizeof(szPCSName) ) )
+                                          0, sizeof(szPCSName) ) )
                     GDALGTIFKeyGetASCII( hGTIF, GeogCitationGeoKey, szPCSName,
-                                0, sizeof(szPCSName) );
+                                         0, sizeof(szPCSName) );
 
                 GTIFCleanupImagineNames( szPCSName );
                 oSRS.SetLocalCS( szPCSName );
@@ -393,8 +430,10 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
                 if( pszUnitsName != NULL && psDefn->UOMLength != KvUserDefined )
                 {
-                    oSRS.SetLinearUnits( pszUnitsName, psDefn->UOMLengthInMeters );
-                    oSRS.SetAuthority( "LOCAL_CS|UNIT", "EPSG", psDefn->UOMLength);
+                    oSRS.SetLinearUnits( pszUnitsName,
+                                         psDefn->UOMLengthInMeters );
+                    oSRS.SetAuthority( "LOCAL_CS|UNIT", "EPSG",
+                                       psDefn->UOMLength );
                 }
                 else
                     oSRS.SetLinearUnits( "unknown", psDefn->UOMLengthInMeters );
@@ -412,13 +451,13 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
     if( psDefn->Model == ModelTypeGeocentric )
     {
-        char    szName[300];
+        char szName[300] = { '\0' };
 
         strcpy( szName, "unnamed" );
         if( !GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szName,
-                         0, sizeof(szName) ) )
+                                  0, sizeof(szName) ) )
             GDALGTIFKeyGetASCII( hGTIF, GeogCitationGeoKey, szName,
-                        0, sizeof(szName) );
+                                 0, sizeof(szName) );
 
         oSRS.SetGeocCS( szName );
 
@@ -445,14 +484,13 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /*      to provide mechanisms for fixing the issue if we are linked     */
 /*      with an older version of libgeotiff.                            */
 /* -------------------------------------------------------------------- */
-    int iParm;
     const char *pszLinearUnits =
         CPLGetConfigOption( "GTIFF_LINEAR_UNITS", "DEFAULT" );
 
 #if LIBGEOTIFF_VERSION <= 1300
     if( EQUAL(pszLinearUnits,"DEFAULT") && psDefn->Projection == KvUserDefined )
     {
-        for( iParm = 0; iParm < psDefn->nParms; iParm++ )
+        for( int iParm = 0; iParm < psDefn->nParms; iParm++ )
         {
             switch( psDefn->ProjParmId[iParm] )
             {
@@ -466,7 +504,10 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                     && psDefn->UOMLengthInMeters != 1.0 )
                 {
                     psDefn->ProjParm[iParm] *= psDefn->UOMLengthInMeters;
-                    CPLDebug( "GTIFF", "converting geokey to meters to fix bug in old libgeotiff" );
+                    CPLDebug(
+                        "GTIFF",
+                        "Converting geokey to meters to fix bug in "
+                        "old libgeotiff" );
                 }
                 break;
 
@@ -475,7 +516,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             }
         }
     }
-#endif /* LIBGEOTIFF_VERSION <= 1300 */
+#endif  // LIBGEOTIFF_VERSION <= 1300
 
 /* -------------------------------------------------------------------- */
 /*      #3901: If folks have broken GeoTIFF files generated with        */
@@ -487,14 +528,14 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
     short bLinearUnitsMarkedCorrect = FALSE;
 
-    GDALGTIFKeyGetSHORT(hGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey,
+    GDALGTIFKeyGetSHORT(hGTIF, ProjLinearUnitsInterpCorrectGeoKey,
                &bLinearUnitsMarkedCorrect, 0, 1);
 
     if( EQUAL(pszLinearUnits,"BROKEN")
         && psDefn->Projection == KvUserDefined
         && !bLinearUnitsMarkedCorrect )
     {
-        for( iParm = 0; iParm < psDefn->nParms; iParm++ )
+        for( int iParm = 0; iParm < psDefn->nParms; iParm++ )
         {
             switch( psDefn->ProjParmId[iParm] )
             {
@@ -508,7 +549,10 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                     && psDefn->UOMLengthInMeters != 1.0 )
                 {
                     psDefn->ProjParm[iParm] /= psDefn->UOMLengthInMeters;
-                    CPLDebug( "GTIFF", "converting geokey to accommodate old broken file due to GTIFF_LINEAR_UNITS=BROKEN setting." );
+                    CPLDebug(
+                        "GTIFF",
+                        "Converting geokey to accommodate old broken file "
+                        "due to GTIFF_LINEAR_UNITS=BROKEN setting." );
                 }
                 break;
 
@@ -525,11 +569,10 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     OGRBoolean linearUnitIsSet = FALSE;
     if( psDefn->Model == ModelTypeProjected )
     {
-        char        szCTString[512];
-        strcpy( szCTString, "unnamed" );
+        char szCTString[512] = { '\0' };
         if( psDefn->PCS != KvUserDefined )
         {
-            char    *pszPCSName = NULL;
+            char *pszPCSName = NULL;
 
             GTIFGetPCSInfo( psDefn->PCS, &pszPCSName, NULL, NULL, NULL );
 
@@ -539,40 +582,61 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
             oSRS.SetAuthority( "PROJCS", "EPSG", psDefn->PCS );
         }
-        else if(hGTIF && GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey, szCTString, 0,
-                                     sizeof(szCTString)) )
-        {
-            if (!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
-                                  PCSCitationGeoKey, &oSRS, &linearUnitIsSet))
-                oSRS.SetNode("PROJCS",szCTString);
-        }
         else
         {
-            if( hGTIF )
+            bool bTryGTCitationGeoKey = true;
+            if( GDALGTIFKeyGetASCII( hGTIF, PCSCitationGeoKey,
+                                              szCTString, 0,
+                                              sizeof(szCTString)) )
             {
-                GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) );
-                if(!SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString),
-                                     GTCitationGeoKey, &oSRS, &linearUnitIsSet))
+                bTryGTCitationGeoKey = false;
+                if (!SetCitationToSRS( hGTIF, szCTString, sizeof(szCTString),
+                                       PCSCitationGeoKey, &oSRS,
+                                       &linearUnitIsSet) )
+                {
+                    if( !STARTS_WITH_CI(szCTString, "LUnits = ") )
+                    {
+                        oSRS.SetNode( "PROJCS",szCTString );
+                    }
+                    else
+                    {
+                        bTryGTCitationGeoKey = true;
+                    }
+                }
+            }
+
+            if( bTryGTCitationGeoKey &&
+                GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szCTString,
+                                     0, sizeof(szCTString) ) )
+            {
+                if( !SetCitationToSRS( hGTIF, szCTString, sizeof(szCTString),
+                                       GTCitationGeoKey, &oSRS,
+                                       &linearUnitIsSet ) )
                     oSRS.SetNode( "PROJCS", szCTString );
             }
             else
-                oSRS.SetNode( "PROJCS", szCTString );
+            {
+                oSRS.SetNode( "PROJCS", "unnamed" );
+            }
         }
 
         /* Handle ESRI/Erdas style state plane and UTM in citation key */
-        if( CheckCitationKeyForStatePlaneUTM(hGTIF, psDefn, &oSRS, &linearUnitIsSet) )
+        if( CheckCitationKeyForStatePlaneUTM( hGTIF, psDefn, &oSRS,
+                                              &linearUnitIsSet ) )
         {
-            char *pszWKT;
             oSRS.morphFromESRI();
             oSRS.FixupOrdering();
+            char *pszWKT = NULL;
             if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
                 return pszWKT;
         }
 
         /* Handle ESRI PE string in citation */
         szCTString[0] = '\0';
-        if( hGTIF && GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szCTString, 0, sizeof(szCTString) ) )
-            SetCitationToSRS(hGTIF, szCTString, sizeof(szCTString), GTCitationGeoKey, &oSRS, &linearUnitIsSet);
+        if( GDALGTIFKeyGetASCII( hGTIF, GTCitationGeoKey, szCTString,
+                                 0, sizeof(szCTString) ) )
+            SetCitationToSRS( hGTIF, szCTString, sizeof(szCTString),
+                              GTCitationGeoKey, &oSRS, &linearUnitIsSet );
     }
 
 /* ==================================================================== */
@@ -583,12 +647,9 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     char *pszPMName = NULL;
     char *pszSpheroidName = NULL;
     char *pszAngularUnits = NULL;
-    double dfInvFlattening=0.0, dfSemiMajor=0.0;
-    char  szGCSName[512];
-    OGRBoolean aUnitGot = FALSE;
+    char szGCSName[512] = { '\0' };
 
     if( !GTIFGetGCSInfo( psDefn->GCS, &pszGeogName, NULL, NULL, NULL )
-        && hGTIF != NULL
         && GDALGTIFKeyGetASCII( hGTIF, GeogCitationGeoKey, szGCSName, 0,
                        sizeof(szGCSName)) )
     {
@@ -599,13 +660,18 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                               &pszAngularUnits);
     }
     else
+    {
         GTIFToCPLRecycleString( &pszGeogName );
+    }
 
     if( !pszDatumName )
     {
         GTIFGetDatumInfo( psDefn->Datum, &pszDatumName, NULL );
         GTIFToCPLRecycleString( &pszDatumName );
     }
+
+    double dfSemiMajor = 0.0;
+    double dfInvFlattening = 0.0;
     if( !pszSpheroidName )
     {
         GTIFGetEllipsoidInfo( psDefn->Ellipsoid, &pszSpheroidName, NULL, NULL );
@@ -613,8 +679,10 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     }
     else
     {
-        GDALGTIFKeyGetDOUBLE(hGTIF, GeogSemiMajorAxisGeoKey, &(psDefn->SemiMajor), 0, 1 );
-        GDALGTIFKeyGetDOUBLE(hGTIF, GeogInvFlatteningGeoKey, &dfInvFlattening, 0, 1 );
+        GDALGTIFKeyGetDOUBLE( hGTIF, GeogSemiMajorAxisGeoKey,
+                              &(psDefn->SemiMajor), 0, 1 );
+        GDALGTIFKeyGetDOUBLE( hGTIF, GeogInvFlatteningGeoKey,
+                              &dfInvFlattening, 0, 1 );
     }
     if( !pszPMName )
     {
@@ -622,8 +690,12 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         GTIFToCPLRecycleString( &pszPMName );
     }
     else
-        GDALGTIFKeyGetDOUBLE(hGTIF, GeogPrimeMeridianLongGeoKey, &(psDefn->PMLongToGreenwich), 0, 1 );
+    {
+        GDALGTIFKeyGetDOUBLE( hGTIF, GeogPrimeMeridianLongGeoKey,
+                              &(psDefn->PMLongToGreenwich), 0, 1 );
+    }
 
+    bool aUnitGot = false;
     if( !pszAngularUnits )
     {
         GTIFGetUOMAngleInfo( psDefn->UOMAngle, &pszAngularUnits, NULL );
@@ -635,9 +707,10 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     else
     {
         double dfRadians = 0.0;
-        if( GDALGTIFKeyGetDOUBLE(hGTIF, GeogAngularUnitSizeGeoKey, &dfRadians, 0, 1 ) )
+        if( GDALGTIFKeyGetDOUBLE(hGTIF, GeogAngularUnitSizeGeoKey, &dfRadians,
+                                 0, 1) )
         {
-            aUnitGot = TRUE;
+            aUnitGot = true;
             psDefn->UOMAngleInDegrees = dfRadians / CPLAtof(SRS_UA_DEGREE_CONV);
         }
     }
@@ -653,13 +726,16 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         dfSemiMajor = SRS_WGS84_SEMIMAJOR;
         dfInvFlattening = SRS_WGS84_INVFLATTENING;
     }
-    else if( dfInvFlattening == 0.0 && ((psDefn->SemiMinor / psDefn->SemiMajor) < 0.99999999999999999
-                                        || (psDefn->SemiMinor / psDefn->SemiMajor) > 1.00000000000000001 ) )
+    else if( dfInvFlattening == 0.0
+             && ((psDefn->SemiMinor / psDefn->SemiMajor) < 0.99999999999999999
+                 || (psDefn->SemiMinor / psDefn->SemiMajor) >
+                 1.00000000000000001 ) )
     {
-        dfInvFlattening = OSRCalcInvFlattening(psDefn->SemiMajor,psDefn->SemiMinor);
+        dfInvFlattening = OSRCalcInvFlattening( psDefn->SemiMajor,
+                                                psDefn->SemiMinor );
 
         /* Take official inverse flattening definition in the WGS84 case */
-        if (fabs(dfSemiMajor-SRS_WGS84_SEMIMAJOR) < 1e-10 &&
+        if (fabs(dfSemiMajor - SRS_WGS84_SEMIMAJOR) < 1e-10 &&
             fabs(dfInvFlattening - SRS_WGS84_INVFLATTENING) < 1e-10)
             dfInvFlattening = SRS_WGS84_INVFLATTENING;
     }
@@ -707,7 +783,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /* -------------------------------------------------------------------- */
     if( psDefn->Model == ModelTypeProjected && !linearUnitIsSet )
     {
-        char        *pszUnitsName = NULL;
+        char *pszUnitsName = NULL;
 
         GTIFGetUOMLengthInfo( psDefn->UOMLength, &pszUnitsName, NULL );
 
@@ -728,15 +804,15 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /*      but that should do for now. This may mask shortcomings in the   */
 /*      libgeotiff GTIFGetDefn() function.                              */
 /* ==================================================================== */
-    short tmp;
-    int bGotFromEPSG = FALSE;
+    short tmp = 0;
+    bool bGotFromEPSG = false;
     if( psDefn->Model == ModelTypeProjected &&
         psDefn->PCS != KvUserDefined &&
-        GDALGTIFKeyGetSHORT(hGTIF, ProjectionGeoKey, &tmp, 0, 1  ) == 0 &&
-        GDALGTIFKeyGetSHORT(hGTIF, ProjCoordTransGeoKey, &tmp, 0, 1  ) == 0 &&
-        GDALGTIFKeyGetSHORT(hGTIF, GeographicTypeGeoKey, &tmp, 0, 1  ) == 0 &&
-        GDALGTIFKeyGetSHORT(hGTIF, GeogGeodeticDatumGeoKey, &tmp, 0, 1  ) == 0 &&
-        GDALGTIFKeyGetSHORT(hGTIF, GeogEllipsoidGeoKey, &tmp, 0, 1  ) == 0 &&
+        GDALGTIFKeyGetSHORT(hGTIF, ProjectionGeoKey, &tmp, 0, 1) == 0 &&
+        GDALGTIFKeyGetSHORT(hGTIF, ProjCoordTransGeoKey, &tmp, 0, 1) == 0 &&
+        GDALGTIFKeyGetSHORT(hGTIF, GeographicTypeGeoKey, &tmp, 0, 1) == 0 &&
+        GDALGTIFKeyGetSHORT(hGTIF, GeogGeodeticDatumGeoKey, &tmp, 0, 1) == 0 &&
+        GDALGTIFKeyGetSHORT(hGTIF, GeogEllipsoidGeoKey, &tmp, 0, 1) == 0 &&
         CPLTestBool(CPLGetConfigOption("GTIFF_IMPORT_FROM_EPSG", "YES")) )
     {
         // Save error state as importFromEPSGA() will call CPLReset()
@@ -751,7 +827,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         // Restore error state
         CPLErrorSetState( eErr, errNo, pszLastErrorMsg);
         CPLFree(pszLastErrorMsg);
-        bGotFromEPSG = (eImportErr == OGRERR_NONE);
+        bGotFromEPSG = eImportErr == OGRERR_NONE;
 
         if( bGotFromEPSG )
         {
@@ -761,19 +837,25 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             double dfUOMLengthInMeters = oSRS.GetLinearUnits( &pszUnitsName );
             if( dfUOMLengthInMeters != oSRSTmp.GetLinearUnits(NULL) )
             {
-                CPLDebug("GTiff", "Modify EPSG:%d to have %s linear units...",
-                            psDefn->PCS, pszUnitsName ? pszUnitsName : "unknown");
+                CPLDebug( "GTiff", "Modify EPSG:%d to have %s linear units...",
+                          psDefn->PCS,
+                          pszUnitsName ? pszUnitsName : "unknown" );
 
                 if( pszUnitsName )
-                    oSRSTmp.SetLinearUnitsAndUpdateParameters( pszUnitsName, dfUOMLengthInMeters );
+                    oSRSTmp.SetLinearUnitsAndUpdateParameters(
+                        pszUnitsName, dfUOMLengthInMeters );
 
-                const char* pszAuthorityCode = oSRS.GetAuthorityCode( "PROJCS|UNIT" );
-                const char* pszAuthorityName = oSRS.GetAuthorityName( "PROJCS|UNIT" );
+                const char* pszAuthorityCode =
+                    oSRS.GetAuthorityCode( "PROJCS|UNIT" );
+                const char* pszAuthorityName =
+                    oSRS.GetAuthorityName( "PROJCS|UNIT" );
                 if( pszAuthorityCode && pszAuthorityName )
-                    oSRSTmp.SetAuthority( "PROJCS|UNIT",pszAuthorityName, atoi(pszAuthorityCode) );
+                    oSRSTmp.SetAuthority( "PROJCS|UNIT", pszAuthorityName,
+                                          atoi(pszAuthorityCode) );
 
                 if( oSRSTmp.GetRoot()->FindChild( "AUTHORITY" ) != -1 )
-                    oSRSTmp.GetRoot()->DestroyChild( oSRSTmp.GetRoot()->FindChild( "AUTHORITY" ) );
+                    oSRSTmp.GetRoot()->DestroyChild( oSRSTmp.GetRoot()->
+                                                     FindChild( "AUTHORITY" ) );
             }
 
             oSRS = oSRSTmp;
@@ -790,10 +872,10 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /*      angular units of the GEOGCS and the linear units of the         */
 /*      projection.                                                     */
 /* -------------------------------------------------------------------- */
-        double adfParm[10];
-        int i;
+        double adfParm[10] = { 0.0 };
+        int i = 0;  // Used after for.
 
-        for( i = 0; i < MIN(10,psDefn->nParms); i++ )
+        for( ; i < std::min(10, psDefn->nParms); i++ )
             adfParm[i] = psDefn->ProjParm[i];
 
         for( ; i < 10; i++ )
@@ -825,13 +907,15 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
             break;
 
           case CT_Mercator:
-            /* If a lat_ts was specified use 2SP, otherwise use 1SP */
+            // If a lat_ts was specified use 2SP, otherwise use 1SP.
             if (psDefn->ProjParmId[2] == ProjStdParallel1GeoKey)
             {
                 if (psDefn->ProjParmId[4] == ProjScaleAtNatOriginGeoKey)
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "Mercator projection should not define both StdParallel1 and ScaleAtNatOrigin.\n"
-                              "Using StdParallel1 and ignoring ScaleAtNatOrigin.\n" );
+                    CPLError(
+                        CE_Warning, CPLE_AppDefined,
+                        "Mercator projection should not define "
+                        "both StdParallel1 and ScaleAtNatOrigin.  "
+                        "Using StdParallel1 and ignoring ScaleAtNatOrigin." );
                 oSRS.SetMercator2SP( adfParm[2],
                                      adfParm[0], adfParm[1],
                                      adfParm[5], adfParm[6]);
@@ -841,10 +925,14 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                                   adfParm[4],
                                   adfParm[5], adfParm[6] );
 
-            if (psDefn->Projection == 1024 || psDefn->Projection == 9841) // override hack for google mercator.
+            // Override hack for google mercator.
+            if (psDefn->Projection == 1024 || psDefn->Projection == 9841)
             {
-                oSRS.SetExtension( "PROJCS", "PROJ4",
-                                   "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs" );
+                oSRS.SetExtension(
+                    "PROJCS", "PROJ4",
+                    "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 "
+                    "+x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null "
+                    "+wktext  +no_defs" );  // TODO(schwehr): Why 2 spaces?
             }
             break;
 
@@ -860,7 +948,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                         adfParm[5], adfParm[6] );
             break;
 
-          case CT_ObliqueMercator: /* hotine */
+          case CT_ObliqueMercator:  // Hotine.
             oSRS.SetHOM( adfParm[0], adfParm[1],
                          adfParm[2], adfParm[3],
                          adfParm[4],
@@ -978,11 +1066,13 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
     if( oSRS.IsProjected())
     {
-        // Hack to be able to read properly what we have written for EPSG:102113 (ESRI ancient WebMercator)
+        // Hack to be able to read properly what we have written for
+        // EPSG:102113 (ESRI ancient WebMercator).
         if( EQUAL(oSRS.GetAttrValue("PROJCS"), "WGS_1984_Web_Mercator") )
             oSRS.importFromEPSG(102113);
         // And for EPSG:900913
-        else if( EQUAL(oSRS.GetAttrValue("PROJCS"), "Google Maps Global Mercator") )
+        else if( EQUAL( oSRS.GetAttrValue("PROJCS"),
+                        "Google Maps Global Mercator" ) )
             oSRS.importFromEPSG(900913);
     }
 
@@ -993,10 +1083,10 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
     short verticalDatum = -1;
     short verticalUnits = -1;
     const char *pszFilename = NULL;
-    const char *pszValue;
-    char szSearchKey[128];
+    const char *pszValue = NULL;
+    char szSearchKey[128] = { '\0' };
     bool bNeedManualVertCS = false;
-    char citation[2048];
+    char citation[2048] = { '\0' };
 
     // Don't do anything if there is no apparent vertical information.
     GDALGTIFKeyGetSHORT( hGTIF, VerticalCSTypeGeoKey, &verticalCSType, 0, 1 );
@@ -1007,7 +1097,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         && (oSRS.IsGeographic() || oSRS.IsProjected() || oSRS.IsLocal()) )
     {
         if( !GDALGTIFKeyGetASCII( hGTIF, VerticalCitationGeoKey, citation,
-                         0, sizeof(citation) ) )
+                                  0, sizeof(citation) ) )
             strcpy( citation, "unknown" );
 
 /* -------------------------------------------------------------------- */
@@ -1046,7 +1136,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         if( (verticalCSType >= 5001 && verticalCSType <= 5033)
             && verticalDatum == -1 )
         {
-            verticalDatum = verticalCSType+1000;
+            verticalDatum = verticalCSType + 1000;
             verticalCSType = -1;
         }
 
@@ -1104,7 +1194,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
                                         szSearchKey, CC_Integer,
                                         "coord_ref_sys_name" );
                 if( pszValue != NULL && *pszValue != '\0' )
-                    strncpy( citation, pszValue, sizeof(citation) );
+                    snprintf( citation, sizeof(citation), "%s", pszValue );
             }
 
             if( verticalUnits < 1 || verticalUnits == KvUserDefined )
@@ -1139,9 +1229,14 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
         if( verticalDatum > 0 && verticalDatum != KvUserDefined )
         {
-            pszFilename = CSVFilename( "datum.csv" );
-            if( EQUAL(pszFilename,"datum.csv") )
-                pszFilename = CSVFilename( "gdal_datum.csv" );
+            pszFilename = CSVFilename( "gdal_datum.csv" );
+            if( EQUAL(pszFilename,"gdal_datum.csv") )
+            {
+                // Fallback to see if libgeotiff datum.csv is available.
+                // TODO(schwehr): Can we drop searching for datum.csv?
+                // See #6531.
+                pszFilename = CSVFilename( "datum.csv" );
+            }
 
             snprintf( szSearchKey, sizeof(szSearchKey), "%d", verticalDatum );
 
@@ -1174,11 +1269,11 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
         if( verticalUnits > 0 && verticalUnits != KvUserDefined
             && verticalUnits != 9001 )
         {
-            char szInMeters[128];
+            char szInMeters[128] = {};
 
             pszFilename = CSVFilename("unit_of_measure.csv");
 
-            // Name
+            // Name.
             snprintf( szSearchKey, sizeof(szSearchKey), "%d", verticalUnits );
             pszValue = CSVGetField( pszFilename,
                                     "uom_code", szSearchKey, CC_Integer,
@@ -1188,22 +1283,21 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 
             oSRS.SetNode( "COMPD_CS|VERT_CS|UNIT", pszValue );
 
-            // Value
-            double dfFactorB, dfFactorC;
-            dfFactorB = GTIFAtof(
+            // Value.
+            const double dfFactorB = GTIFAtof(
                 CSVGetField( pszFilename,
                              "uom_code", szSearchKey, CC_Integer,
                              "factor_b" ));
-            dfFactorC = GTIFAtof(
+            const double dfFactorC = GTIFAtof(
                 CSVGetField( pszFilename,
                              "uom_code", szSearchKey, CC_Integer,
                              "factor_c" ));
             if( dfFactorB != 0.0 && dfFactorC != 0.0 )
-                CPLsnprintf( szInMeters, sizeof(szInMeters), "%.16g", dfFactorB / dfFactorC );
+                CPLsnprintf( szInMeters, sizeof(szInMeters),
+                             "%.16g", dfFactorB / dfFactorC );
             else
                 strcpy( szInMeters, "1" );
 
-
             oSRS.GetAttrNode( "COMPD_CS|VERT_CS|UNIT" )
                 ->AddChild( new OGR_SRSNode( szInMeters ) );
 
@@ -1231,14 +1325,13 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 /* ==================================================================== */
 /*      Return the WKT serialization of the object.                     */
 /* ==================================================================== */
-    char *pszWKT;
-
     oSRS.FixupOrdering();
 
+    char *pszWKT = NULL;
     if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
         return pszWKT;
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -1248,7 +1341,7 @@ char *GTIFGetOGISDefn( GTIF *hGTIF, GTIFDefn * psDefn )
 static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
 
 {
-    char **papszTokens;
+    char **papszTokens = NULL;
     int nReturn = KvUserDefined;
 
 /* -------------------------------------------------------------------- */
@@ -1290,6 +1383,7 @@ static int OGCDatumName2EPSGDatumCode( const char * pszOGCName )
     {
         WKTMassageDatum( papszTokens + 1 );
 
+        CPLAssert(papszTokens[1] != NULL);  // Silence clang static analyzer.
         if( EQUAL(papszTokens[1], pszOGCName) )
             nReturn = atoi(papszTokens[0]);
 
@@ -1317,19 +1411,13 @@ int GTIFSetFromOGISDefn( GTIF * psGTIF, const char *pszOGCWKT )
 int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
                            GTIFFKeysFlavorEnum eFlavor )
 {
-    OGRSpatialReference *poSRS;
-    int nPCS = KvUserDefined;
-    OGRErr      eErr;
-    OGRBoolean peStrStored = FALSE;
-
-    GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1,
-               RasterPixelIsArea);
+    GTIFKeySet(psGTIF, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsArea);
 
 /* -------------------------------------------------------------------- */
 /*      Create an OGRSpatialReference object corresponding to the       */
 /*      string.                                                         */
 /* -------------------------------------------------------------------- */
-    poSRS = new OGRSpatialReference();
+    OGRSpatialReference *poSRS = new OGRSpatialReference();
     if( poSRS->importFromWkt((char **) &pszOGCWKT) != OGRERR_NONE )
     {
         delete poSRS;
@@ -1340,24 +1428,24 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
 /*      Get the ellipsoid definition.                                   */
 /* -------------------------------------------------------------------- */
     short nSpheroid = KvUserDefined;
-    double dfSemiMajor, dfInvFlattening;
 
     if( poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID") != NULL
         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS|DATUM|SPHEROID"),
                  "EPSG"))
     {
-        nSpheroid = (short)
-            atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM|SPHEROID"));
+        nSpheroid = static_cast<short>(
+            atoi(poSRS->GetAuthorityCode("PROJCS|GEOGCS|DATUM|SPHEROID")) );
     }
     else if( poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID") != NULL
              && EQUAL(poSRS->GetAuthorityName("GEOGCS|DATUM|SPHEROID"),"EPSG"))
     {
-        nSpheroid = (short)
-            atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM|SPHEROID"));
+        nSpheroid = static_cast<short>(
+            atoi(poSRS->GetAuthorityCode("GEOGCS|DATUM|SPHEROID")) );
     }
 
-    dfSemiMajor = poSRS->GetSemiMajor( &eErr );
-    dfInvFlattening = poSRS->GetInvFlattening( &eErr );
+    OGRErr eErr = OGRERR_NONE;
+    double dfSemiMajor = poSRS->GetSemiMajor( &eErr );
+    double dfInvFlattening = poSRS->GetInvFlattening( &eErr );
     if( eErr != OGRERR_NONE )
     {
         dfSemiMajor = 0.0;
@@ -1381,7 +1469,7 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
 /* -------------------------------------------------------------------- */
 /*      Get the GCS if possible.                                        */
 /* -------------------------------------------------------------------- */
-    int         nGCS = KvUserDefined;
+    int nGCS = KvUserDefined;
 
     if( poSRS->GetAuthorityName("PROJCS|GEOGCS") != NULL
         && EQUAL(poSRS->GetAuthorityName("PROJCS|GEOGCS"),"EPSG") )
@@ -1396,28 +1484,32 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
 /* -------------------------------------------------------------------- */
 /*      Get the linear units.                                           */
 /* -------------------------------------------------------------------- */
-    char        *pszLinearUOMName = NULL;
-    double dfLinearUOM = poSRS->GetLinearUnits( &pszLinearUOMName );
-    int         nUOMLengthCode = 9001; /* meters */
+    char *pszLinearUOMName = NULL;
+    const double dfLinearUOM = poSRS->GetLinearUnits( &pszLinearUOMName );
+    int nUOMLengthCode = 9001;  // Meters.
 
     if( poSRS->GetAuthorityName("PROJCS|UNIT") != NULL
         && EQUAL(poSRS->GetAuthorityName("PROJCS|UNIT"),"EPSG")
-        && poSRS->GetAttrNode( "PROJCS|UNIT" ) != poSRS->GetAttrNode("GEOGCS|UNIT") )
+        && poSRS->GetAttrNode( "PROJCS|UNIT" ) !=
+        poSRS->GetAttrNode("GEOGCS|UNIT") )
         nUOMLengthCode = atoi(poSRS->GetAuthorityCode("PROJCS|UNIT"));
     else if( (pszLinearUOMName != NULL
          && EQUAL(pszLinearUOMName,SRS_UL_FOOT))
-        || fabs(dfLinearUOM-GTIFAtof(SRS_UL_FOOT_CONV)) < 0.0000001 )
-        nUOMLengthCode = 9002; /* international foot */
+        || fabs(dfLinearUOM - GTIFAtof(SRS_UL_FOOT_CONV)) < 0.0000001 )
+        nUOMLengthCode = 9002;  // International foot.
     else if( (pszLinearUOMName != NULL
-              && EQUAL(pszLinearUOMName,SRS_UL_US_FOOT))
-             || ABS(dfLinearUOM-GTIFAtof(SRS_UL_US_FOOT_CONV)) < 0.0000001 )
-        nUOMLengthCode = 9003; /* us survey foot */
-    else if( fabs(dfLinearUOM-1.0) > 0.00000001 )
+              && EQUAL(pszLinearUOMName,SRS_UL_US_FOOT)) ||
+             std::abs(dfLinearUOM - GTIFAtof(SRS_UL_US_FOOT_CONV)) <
+             0.0000001 )
+        nUOMLengthCode = 9003;  // US survey foot.
+    else if( fabs(dfLinearUOM - 1.0) > 0.00000001 )
         nUOMLengthCode = KvUserDefined;
 
 /* -------------------------------------------------------------------- */
 /*      Get some authority values.                                      */
 /* -------------------------------------------------------------------- */
+    int nPCS = KvUserDefined;
+
     if( poSRS->GetAuthorityName("PROJCS") != NULL
         && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG") )
     {
@@ -1436,7 +1528,7 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
     {
         // If ESRI_PE flavor is explicitly required, then for EPSG:3857
         // we will have to write a completely non-standard definition
-        // that requires not setting GTModelTypeGeoKey to ProjectedCSTypeGeoKey
+        // that requires not setting GTModelTypeGeoKey to ProjectedCSTypeGeoKey.
         if( eFlavor == GEOTIFF_KEYS_ESRI_PE && nPCS == 3857 )
         {
             bWritePEString = true;
@@ -1458,7 +1550,7 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
         if( poSRS->IsGeographic() )
             GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                        ModelTypeGeographic);
-        // otherwise, presumably something like LOCAL_CS.
+        // Otherwise, presumably something like LOCAL_CS.
     }
     else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
@@ -1493,12 +1585,13 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
 
     else if( poSRS->GetUTMZone() != 0 )
     {
-        int bNorth, nZone, nProjection;
-
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
 
-        nZone = poSRS->GetUTMZone( &bNorth );
+        int bNorth = 0;
+        const int nZone = poSRS->GetUTMZone( &bNorth );
+
+        int nProjection = 0;
 
         if( nDatum == Datum_North_American_Datum_1983 && nZone >= 3
             && nZone <= 22 && bNorth && nUOMLengthCode == 9001 )
@@ -1530,7 +1623,6 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
             else
                 nProjection = 16100 + nZone;
 
-
             GTIFKeySet(psGTIF, ProjectedCSTypeGeoKey, TYPE_SHORT, 1,
                        KvUserDefined );
 
@@ -1616,10 +1708,10 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
 
         if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
             GTIFKeySet(psGTIF, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1,
-                       poSRS->GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 ) );
+                       poSRS->GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0));
         else
             GTIFKeySet(psGTIF, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1,
-                       poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) );
+                       poSRS->GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 ));
 
         GTIFKeySet(psGTIF, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_EASTING, 0.0 ) );
@@ -1746,7 +1838,8 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
 
-    else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) )
+    else if( EQUAL(pszProjection,
+                   SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) )
     {
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    ModelTypeProjected);
@@ -2191,7 +2284,6 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
         GTIFKeySet(psGTIF, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1,
                    poSRS->GetProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) );
     }
-
     else
     {
         bWritePEString = true;
@@ -2206,36 +2298,41 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
     bWritePEString &=
         CPLTestBool( CPLGetConfigOption("GTIFF_ESRI_CITATION", "YES") );
 
+    bool peStrStored = false;
+
     if( bWritePEString )
     {
-        /* Anyhing we can't map, we store as an ESRI PE string with a citation key */
+        // Anyhing we can't map, store as an ESRI PE string with a citation key.
         char *pszPEString = NULL;
         poSRS->morphToESRI();
         poSRS->exportToWkt( &pszPEString );
-        int peStrLen = static_cast<int>(strlen(pszPEString));
+        const int peStrLen = static_cast<int>(strlen(pszPEString));
         if(peStrLen > 0)
         {
-            char *outPeStr = (char *) CPLMalloc( peStrLen + strlen("ESRI PE String = ")+1 );
+            char *outPeStr = static_cast<char *>(
+                CPLMalloc( peStrLen + strlen("ESRI PE String = ") + 1 ) );
             strcpy(outPeStr, "ESRI PE String = ");
             strcat(outPeStr, pszPEString);
             GTIFKeySet( psGTIF, PCSCitationGeoKey, TYPE_ASCII, 0, outPeStr );
-            peStrStored = TRUE;
+            peStrStored = true;
             CPLFree( outPeStr );
         }
         CPLFree( pszPEString );
         GTIFKeySet(psGTIF, GTModelTypeGeoKey, TYPE_SHORT, 1,
                    KvUserDefined );
 
-        /* Not completely sure we really need to imitate ArcGIS to that point */
-        /* but that cannot hurt */
+        // Not completely sure we really need to imitate ArcGIS to that point
+        // but that cannot hurt.
         if( nPCS == 3857 )
         {
-            GTIFKeySet(psGTIF, GTCitationGeoKey, TYPE_ASCII, 0,
-                       "PCS Name = WGS_1984_Web_Mercator_Auxiliary_Sphere");
+            GTIFKeySet( psGTIF, GTCitationGeoKey, TYPE_ASCII, 0,
+                        "PCS Name = WGS_1984_Web_Mercator_Auxiliary_Sphere" );
             GTIFKeySet( psGTIF, GeographicTypeGeoKey, TYPE_SHORT,
                         1, GCS_WGS_84 );
-            GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1, 6378137.0);
-            GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1, 298.257223563);
+            GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
+                        6378137.0 );
+            GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
+                        298.257223563 );
         }
     }
 
@@ -2244,17 +2341,21 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
 /*      special geokey tag to indicate that GDAL has written these      */
 /*      with the proper interpretation of the linear units.             */
 /* -------------------------------------------------------------------- */
-    double dfFE = 0.0, dfFN = 0.0;
+    double dfFE = 0.0;
+    double dfFN = 0.0;
 
     if( (GDALGTIFKeyGetDOUBLE(psGTIF, ProjFalseEastingGeoKey, &dfFE, 0, 1)
          || GDALGTIFKeyGetDOUBLE(psGTIF, ProjFalseNorthingGeoKey, &dfFN, 0, 1)
-         || GDALGTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginEastingGeoKey, &dfFE, 0, 1)
-         || GDALGTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginNorthingGeoKey, &dfFN, 0, 1))
+         || GDALGTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginEastingGeoKey, &dfFE,
+                                 0, 1)
+         || GDALGTIFKeyGetDOUBLE(psGTIF, ProjFalseOriginNorthingGeoKey, &dfFN,
+                                 0, 1))
         && (dfFE != 0.0 || dfFN != 0.0)
         && nUOMLengthCode != 9001 )
     {
-        GTIFKeySet(psGTIF, (geokey_t) ProjLinearUnitsInterpCorrectGeoKey,
-                   TYPE_SHORT, 1, (short) 1 );
+        GTIFKeySet(
+            psGTIF, ProjLinearUnitsInterpCorrectGeoKey,
+            TYPE_SHORT, 1, static_cast<short>(1));
     }
 
 /* -------------------------------------------------------------------- */
@@ -2276,13 +2377,14 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
             GTIFKeySet( psGTIF, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1,
                         dfLinearUOM);
 
-        /* if linear units name is available and user defined, store it as citation */
-        if(!peStrStored
-           && nUOMLengthCode == KvUserDefined
-           && pszLinearUOMName
-           && strlen(pszLinearUOMName)>0
-           && CPLTestBool( CPLGetConfigOption("GTIFF_ESRI_CITATION",
-                                                 "YES") ) )
+        // If linear units name is available and user defined, store it as
+        // citation.
+        if( !peStrStored
+            && nUOMLengthCode == KvUserDefined
+            && pszLinearUOMName
+            && strlen(pszLinearUOMName)>0
+            && CPLTestBool( CPLGetConfigOption("GTIFF_ESRI_CITATION",
+                                               "YES") ) )
         {
             SetLinearUnitCitation(psGTIF, pszLinearUOMName);
         }
@@ -2312,13 +2414,14 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
     else if (EQUAL(angUnitName, "radian"))
         GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1,
                    Angular_Radian);
-    /*else if (EQUAL(angUnitName, "microradian"))
-        GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1,
-                   9109);*/
+    // else if (EQUAL(angUnitName, "microradian"))
+    //    GTIFKeySet(psGTIF, GeogAngularUnitsGeoKey, TYPE_SHORT, 1,
+    //               9109);
     else
     {
+        // GeogCitationGeoKey may be rewritten if the gcs is user defined.
         GTIFKeySet(psGTIF, GeogCitationGeoKey, TYPE_ASCII, 0,
-                   angUnitName ); // it may be rewritten if the gcs is userdefined
+                   angUnitName );
         GTIFKeySet(psGTIF, GeogAngularUnitSizeGeoKey, TYPE_DOUBLE, 1,
                    angUnitValue );
     }
@@ -2404,28 +2507,28 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
                             dfInvFlattening );
         }
         else if( poSRS->GetAttrValue("DATUM") != NULL
-                 && strstr(poSRS->GetAttrValue("DATUM"),"unknown") == NULL
-                 && strstr(poSRS->GetAttrValue("DATUM"),"unnamed") == NULL )
+                 && strstr(poSRS->GetAttrValue("DATUM"), "unknown") == NULL
+                 && strstr(poSRS->GetAttrValue("DATUM"), "unnamed") == NULL )
 
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Couldn't translate `%s' to a GeoTIFF datum.\n",
+                      "Couldn't translate `%s' to a GeoTIFF datum.",
                       poSRS->GetAttrValue("DATUM") );
         }
 
-        /* Always set InvFlattening if it is available.  */
-        /* So that it doesn't need to calculate from SemiMinor */
+        // Always set InvFlattening if it is available.
+        // So that it doesn't need to calculate from SemiMinor.
         if( dfInvFlattening != 0.0 )
             GTIFKeySet( psGTIF, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1,
                         dfInvFlattening );
-        /* Always set SemiMajor to keep the precision and in case of editing */
+        // Always set SemiMajor to keep the precision and in case of editing.
         if( dfSemiMajor != 0.0 )
             GTIFKeySet( psGTIF, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1,
                         dfSemiMajor );
 
         if( nGCS == KvUserDefined
             && CPLTestBool( CPLGetConfigOption("GTIFF_ESRI_CITATION",
-                                                  "YES") ) )
+                                               "YES") ) )
             SetGeogCSCitation(psGTIF, poSRS, angUnitName, nDatum, nSpheroid);
     }
 
@@ -2434,7 +2537,7 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
 /* -------------------------------------------------------------------- */
 
 #if LIBGEOTIFF_VERSION >= 1310 && !defined(GEO_NORMALIZE_DISABLE_TOWGS84)
-    double adfTOWGS84[7];
+    double adfTOWGS84[7] = { 0.0 };
 
     if( poSRS->GetTOWGS84( adfTOWGS84 ) == OGRERR_NONE )
     {
@@ -2444,7 +2547,7 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
             if( nGCS == GCS_WGS_84 && adfTOWGS84[0] == 0.0
                 && adfTOWGS84[1] == 0.0 && adfTOWGS84[2] == 0.0 )
             {
-                ; /* do nothing */
+                ; // Do nothing.
             }
             else
                 GTIFKeySet( psGTIF, GeogTOWGS84GeoKey, TYPE_DOUBLE, 3,
@@ -2461,7 +2564,7 @@ int GTIFSetFromOGISDefnEx( GTIF * psGTIF, const char *pszOGCWKT,
 /* -------------------------------------------------------------------- */
     if( poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) != NULL )
     {
-        const char *pszValue;
+        const char *pszValue = NULL;
 
         GTIFKeySet( psGTIF, VerticalCitationGeoKey, TYPE_ASCII, 0,
                     poSRS->GetAttrValue( "COMPD_CS|VERT_CS" ) );
@@ -2497,8 +2600,8 @@ CPLErr GTIFWktFromMemBuf( int nSize, unsigned char *pabyBuffer,
                           char **ppszWKT, double *padfGeoTransform,
                           int *pnGCPCount, GDAL_GCP **ppasGCPList )
 {
-    return GTIFWktFromMemBufEx(nSize, pabyBuffer, ppszWKT, padfGeoTransform,
-                               pnGCPCount, ppasGCPList, NULL, NULL);
+    return GTIFWktFromMemBufEx( nSize, pabyBuffer, ppszWKT, padfGeoTransform,
+                                pnGCPCount, ppasGCPList, NULL, NULL );
 }
 
 CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
@@ -2507,18 +2610,16 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
                             int *pbPixelIsPoint, char*** ppapszRPCMD )
 
 {
-    bool    bPixelIsPoint = false;
-    int     bPointGeoIgnore = FALSE;
-    short nRasterType;
-    char szFilename[100];
+    char szFilename[100] = {};
 
-    snprintf( szFilename, sizeof(szFilename), "/vsimem/wkt_from_mem_buf_%ld.tif",
-             (long) CPLGetPID() );
+    snprintf( szFilename, sizeof(szFilename),
+              "/vsimem/wkt_from_mem_buf_%ld.tif",
+              static_cast<long>( CPLGetPID() ) );
 
 /* -------------------------------------------------------------------- */
 /*      Make sure we have hooked CSVFilename().                         */
 /* -------------------------------------------------------------------- */
-    GTiffOneTimeInit(); /* for RPC tag */
+    GTiffOneTimeInit();  // For RPC tag.
     LibgeotiffOneTimeInit();
 
 /* -------------------------------------------------------------------- */
@@ -2531,9 +2632,7 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
 /* -------------------------------------------------------------------- */
 /*      Initialize access to the memory geotiff structure.              */
 /* -------------------------------------------------------------------- */
-    TIFF        *hTIFF;
-
-    hTIFF = VSI_TIFFOpen( szFilename, "rc", fp );
+    TIFF *hTIFF = VSI_TIFFOpen( szFilename, "rc", fp );
 
     if( hTIFF == NULL )
     {
@@ -2547,14 +2646,15 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
 /* -------------------------------------------------------------------- */
 /*      Get the projection definition.                                  */
 /* -------------------------------------------------------------------- */
-    GTIF *hGTIF;
-    GTIFDefn    *psGTIFDefn;
+    bool bPixelIsPoint = false;
+    bool bPointGeoIgnore = false;
+    short nRasterType = 0;
 
-    hGTIF = GTIFNew(hTIFF);
+    GTIF *hGTIF = GTIFNew(hTIFF);
 
-    if( hGTIF != NULL && GDALGTIFKeyGetSHORT(hGTIF, GTRasterTypeGeoKey, &nRasterType,
-                0, 1 ) == 1
-        && nRasterType == (short) RasterPixelIsPoint )
+    if( hGTIF != NULL && GDALGTIFKeyGetSHORT(hGTIF, GTRasterTypeGeoKey,
+                                             &nRasterType, 0, 1 ) == 1
+        && nRasterType == static_cast<short>( RasterPixelIsPoint ) )
     {
         bPixelIsPoint = true;
         bPointGeoIgnore =
@@ -2567,12 +2667,12 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
         *ppapszRPCMD = NULL;
 
 #if LIBGEOTIFF_VERSION >= 1410
-    psGTIFDefn = GTIFAllocDefn();
+    GTIFDefn *psGTIFDefn = GTIFAllocDefn();
 #else
-    psGTIFDefn = (GTIFDefn *) CPLCalloc(1,sizeof(GTIFDefn));
+    GTIFDefn *psGTIFDefn = static_cast<GTIFDefn *>(
+        CPLCalloc(1, sizeof(GTIFDefn)) );
 #endif
 
-
     if( hGTIF != NULL && GTIFGetDefn( hGTIF, psGTIFDefn ) )
         *ppszWKT = GTIFGetOGISDefn( hGTIF, psGTIFDefn );
     else
@@ -2590,8 +2690,10 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
 /* -------------------------------------------------------------------- */
 /*      Get geotransform or tiepoints.                                  */
 /* -------------------------------------------------------------------- */
-    double *padfTiePoints, *padfScale, *padfMatrix;
-    int16 nCount;
+    double *padfTiePoints = NULL;
+    double *padfScale = NULL;
+    double *padfMatrix = NULL;
+    int16 nCount = 0;
 
     padfGeoTransform[0] = 0.0;
     padfGeoTransform[1] = 1.0;
@@ -2603,11 +2705,11 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
     *pnGCPCount = 0;
     *ppasGCPList = NULL;
 
-    if( TIFFGetField(hTIFF,TIFFTAG_GEOPIXELSCALE,&nCount,&padfScale )
+    if( TIFFGetField(hTIFF, TIFFTAG_GEOPIXELSCALE, &nCount, &padfScale )
         && nCount >= 2 )
     {
         padfGeoTransform[1] = padfScale[0];
-        padfGeoTransform[5] = - ABS(padfScale[1]);
+        padfGeoTransform[5] = -std::abs(padfScale[1]);
 
         if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
             && nCount >= 6 )
@@ -2617,27 +2719,29 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
             padfGeoTransform[3] =
                 padfTiePoints[4] - padfTiePoints[1] * padfGeoTransform[5];
 
-            // adjust for pixel is point in transform
+            // Adjust for pixel is point in transform.
             if( bPixelIsPoint && !bPointGeoIgnore )
             {
-                padfGeoTransform[0] -= (padfGeoTransform[1] * 0.5 + padfGeoTransform[2] * 0.5);
-                padfGeoTransform[3] -= (padfGeoTransform[4] * 0.5 + padfGeoTransform[5] * 0.5);
+                padfGeoTransform[0] -=
+                    padfGeoTransform[1] * 0.5 + padfGeoTransform[2] * 0.5;
+                padfGeoTransform[3] -=
+                    padfGeoTransform[4] * 0.5 + padfGeoTransform[5] * 0.5;
             }
         }
     }
-
     else if( TIFFGetField(hTIFF,TIFFTAG_GEOTIEPOINTS,&nCount,&padfTiePoints )
              && nCount >= 6 )
     {
         *pnGCPCount = nCount / 6;
-        *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),*pnGCPCount);
+        *ppasGCPList = static_cast<GDAL_GCP *>(
+            CPLCalloc(sizeof(GDAL_GCP), *pnGCPCount) );
 
         for( int iGCP = 0; iGCP < *pnGCPCount; iGCP++ )
         {
-            char szID[32];
+            char szID[32] = {};
             GDAL_GCP *psGCP = *ppasGCPList + iGCP;
 
-            snprintf( szID, sizeof(szID), "%d", iGCP+1 );
+            snprintf( szID, sizeof(szID), "%d", iGCP + 1 );
             psGCP->pszId = CPLStrdup( szID );
             psGCP->pszInfo = CPLStrdup("");
             psGCP->dfGCPPixel = padfTiePoints[iGCP*6+0];
@@ -2647,7 +2751,6 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
             psGCP->dfGCPZ = padfTiePoints[iGCP*6+5];
         }
     }
-
     else if( TIFFGetField(hTIFF,TIFFTAG_GEOTRANSMATRIX,&nCount,&padfMatrix )
              && nCount == 16 )
     {
@@ -2664,7 +2767,7 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
 /* -------------------------------------------------------------------- */
     if( ppapszRPCMD != NULL )
     {
-        *ppapszRPCMD =  GTiffDatasetReadRPCTag( hTIFF );
+        *ppapszRPCMD = GTiffDatasetReadRPCTag( hTIFF );
     }
 
 /* -------------------------------------------------------------------- */
@@ -2677,8 +2780,8 @@ CPLErr GTIFWktFromMemBufEx( int nSize, unsigned char *pabyBuffer,
 
     if( *ppszWKT == NULL )
         return CE_Failure;
-    else
-        return CE_None;
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -2700,17 +2803,16 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
                             int bPixelIsPoint, char** papszRPCMD )
 
 {
-    TIFF        *hTIFF;
-    GTIF *hGTIF;
-    char        szFilename[100];
+    char szFilename[100] = {};
 
-    snprintf( szFilename, sizeof(szFilename), "/vsimem/wkt_from_mem_buf_%ld.tif",
-             (long) CPLGetPID() );
+    snprintf( szFilename, sizeof(szFilename),
+              "/vsimem/wkt_from_mem_buf_%ld.tif",
+              static_cast<long>( CPLGetPID() ) );
 
 /* -------------------------------------------------------------------- */
 /*      Make sure we have hooked CSVFilename().                         */
 /* -------------------------------------------------------------------- */
-    GTiffOneTimeInit(); /* for RPC tag */
+    GTiffOneTimeInit();  // For RPC tag.
     LibgeotiffOneTimeInit();
 
 /* -------------------------------------------------------------------- */
@@ -2720,7 +2822,7 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
     if( fpL == NULL )
         return CE_Failure;
 
-    hTIFF = VSI_TIFFOpen( szFilename, "w", fpL );
+    TIFF *hTIFF = VSI_TIFFOpen( szFilename, "w", fpL );
 
     if( hTIFF == NULL )
     {
@@ -2745,7 +2847,7 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
 /*      Get the projection definition.                                  */
 /* -------------------------------------------------------------------- */
 
-    int bPointGeoIgnore = FALSE;
+    bool bPointGeoIgnore = false;
     if( bPixelIsPoint )
     {
         bPointGeoIgnore =
@@ -2753,6 +2855,7 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
                                              "FALSE") );
     }
 
+    GTIF *hGTIF = NULL;
     if( pszWKT != NULL || bPixelIsPoint )
     {
         hGTIF = GTIFNew(hTIFF);
@@ -2775,39 +2878,35 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
 
     if( padfGeoTransform[0] != 0.0 || padfGeoTransform[1] != 1.0
         || padfGeoTransform[2] != 0.0 || padfGeoTransform[3] != 0.0
-        || padfGeoTransform[4] != 0.0 || ABS(padfGeoTransform[5]) != 1.0 )
+        || padfGeoTransform[4] != 0.0 || std::abs(padfGeoTransform[5]) != 1.0 )
     {
 
         if( padfGeoTransform[2] == 0.0 && padfGeoTransform[4] == 0.0 )
         {
-            double adfPixelScale[3], adfTiePoints[6];
-
-            adfPixelScale[0] = padfGeoTransform[1];
-            adfPixelScale[1] = fabs(padfGeoTransform[5]);
-            adfPixelScale[2] = 0.0;
+            double adfPixelScale[3] = {
+                padfGeoTransform[1],
+                fabs(padfGeoTransform[5]),
+                0.0
+            };
 
             TIFFSetField( hTIFF, TIFFTAG_GEOPIXELSCALE, 3, adfPixelScale );
 
-            adfTiePoints[0] = 0.0;
-            adfTiePoints[1] = 0.0;
-            adfTiePoints[2] = 0.0;
-            adfTiePoints[3] = padfGeoTransform[0];
-            adfTiePoints[4] = padfGeoTransform[3];
-            adfTiePoints[5] = 0.0;
+            double adfTiePoints[6] = {
+                0.0, 0.0, 0.0, padfGeoTransform[0], padfGeoTransform[3], 0.0 };
 
             if( bPixelIsPoint && !bPointGeoIgnore )
             {
-                adfTiePoints[3] += padfGeoTransform[1] * 0.5 + padfGeoTransform[2] * 0.5;
-                adfTiePoints[4] += padfGeoTransform[4] * 0.5 + padfGeoTransform[5] * 0.5;
+                adfTiePoints[3] +=
+                    padfGeoTransform[1] * 0.5 + padfGeoTransform[2] * 0.5;
+                adfTiePoints[4] +=
+                    padfGeoTransform[4] * 0.5 + padfGeoTransform[5] * 0.5;
             }
 
             TIFFSetField( hTIFF, TIFFTAG_GEOTIEPOINTS, 6, adfTiePoints );
         }
         else
         {
-            double adfMatrix[16];
-
-            memset(adfMatrix,0,sizeof(double) * 16);
+            double adfMatrix[16] = { 0.0 };
 
             adfMatrix[0] = padfGeoTransform[1];
             adfMatrix[1] = padfGeoTransform[2];
@@ -2819,8 +2918,10 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
 
             if( bPixelIsPoint && !bPointGeoIgnore )
             {
-                adfMatrix[3] += padfGeoTransform[1] * 0.5 + padfGeoTransform[2] * 0.5;
-                adfMatrix[7] += padfGeoTransform[4] * 0.5 + padfGeoTransform[5] * 0.5;
+                adfMatrix[3] +=
+                    padfGeoTransform[1] * 0.5 + padfGeoTransform[2] * 0.5;
+                adfMatrix[7] +=
+                    padfGeoTransform[4] * 0.5 + padfGeoTransform[5] * 0.5;
             }
 
             TIFFSetField( hTIFF, TIFFTAG_GEOTRANSMATRIX, 16, adfMatrix );
@@ -2832,9 +2933,8 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
 /* -------------------------------------------------------------------- */
     else if( nGCPCount > 0 )
     {
-        double *padfTiePoints;
-
-        padfTiePoints = (double *) CPLMalloc(6*sizeof(double)*nGCPCount);
+        double *padfTiePoints = static_cast<double *>(
+            CPLMalloc(6*sizeof(double)*nGCPCount) );
 
         for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
         {
@@ -2876,10 +2976,10 @@ CPLErr GTIFMemBufFromWktEx( const char *pszWKT, const double *padfGeoTransform,
 /*      to be able to "steal" the memory buffer, but there isn't        */
 /*      currently any support for this.                                 */
 /* -------------------------------------------------------------------- */
-    GUIntBig nBigLength;
+    GUIntBig nBigLength = 0;
 
     *ppabyBuffer = VSIGetMemFileBuffer( szFilename, &nBigLength, TRUE );
-    *pnSize = (int) nBigLength;
+    *pnSize = static_cast<int>( nBigLength );
 
     return CE_None;
 }
diff --git a/frmts/gtiff/gt_wkt_srs.h b/frmts/gtiff/gt_wkt_srs.h
index bb7c95e..768211b 100644
--- a/frmts/gtiff/gt_wkt_srs.h
+++ b/frmts/gtiff/gt_wkt_srs.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gt_wkt_srs.h 33806 2016-03-28 22:26:19Z goatbar $
+ * $Id: gt_wkt_srs.h 34121 2016-04-26 14:24:38Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implements translation between GeoTIFF normalized projection
@@ -39,8 +39,8 @@
 #include "geotiff.h"
 
 CPL_C_START
-char CPL_DLL *  GTIFGetOGISDefn( GTIF *, GTIFDefn * );
-int  CPL_DLL   GTIFSetFromOGISDefn( GTIF *, const char * );
+char CPL_DLL *GTIFGetOGISDefn( GTIF *, GTIFDefn * );
+int  CPL_DLL GTIFSetFromOGISDefn( GTIF *, const char * );
 
 typedef enum
 {
diff --git a/frmts/gtiff/gtiff.h b/frmts/gtiff/gtiff.h
index 1d21254..da244e6 100644
--- a/frmts/gtiff/gtiff.h
+++ b/frmts/gtiff/gtiff.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtiff.h 33806 2016-03-28 22:26:19Z goatbar $
+ * $Id: gtiff.h 37184 2017-01-19 12:26:29Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  GDAL GeoTIFF support.
@@ -32,6 +32,7 @@
 #define GTIFF_H_INCLUDED
 
 #include "cpl_port.h"
+#include "cpl_string.h"
 
 #include "gdal.h"
 #include "tiffio.h"
@@ -42,14 +43,24 @@ void CPL_DLL LibgeotiffOneTimeInit();
 void   LibgeotiffOneTimeCleanupMutex();
 CPL_C_END
 
-void    GTIFFSetInExternalOvr(bool b);
-void    GTIFFGetOverviewBlockSize(int* pnBlockXSize, int* pnBlockYSize);
-void    GTIFFSetJpegQuality(GDALDatasetH hGTIFFDS, int nJpegQuality);
-int     GTIFFGetCompressionMethod(const char* pszValue, const char* pszVariableName);
+void    GTIFFSetInExternalOvr( bool b );
+void    GTIFFGetOverviewBlockSize( int* pnBlockXSize, int* pnBlockYSize );
+void    GTIFFSetJpegQuality( GDALDatasetH hGTIFFDS, int nJpegQuality );
+void    GTIFFSetJpegTablesMode( GDALDatasetH hGTIFFDS, int nJpegTablesMode );
+int     GTIFFGetCompressionMethod( const char* pszValue,
+                                   const char* pszVariableName );
 
 void GTiffDatasetWriteRPCTag( TIFF *hTIFF, char **papszRPCMD );
 char** GTiffDatasetReadRPCTag( TIFF *hTIFF );
 
+void GTiffWriteJPEGTables( TIFF* hTIFF,
+                           const char* pszPhotometric,
+                           const char* pszJPEGQuality,
+                           const char* pszJPEGTablesMode );
+CPLString GTiffFormatGDALNoDataTagValue( double dfNoData );
+
+const int knGTIFFJpegTablesModeDefault = 1; /* JPEGTABLESMODE_QUANT */
+
 #define TIFFTAG_GDAL_METADATA  42112
 #define TIFFTAG_GDAL_NODATA    42113
 #define TIFFTAG_RPCCOEFFICIENT 50844
diff --git a/frmts/gtiff/libgeotiff/epsg_datum.inc b/frmts/gtiff/libgeotiff/epsg_datum.inc
index 916ec7d..198e78f 100644
--- a/frmts/gtiff/libgeotiff/epsg_datum.inc
+++ b/frmts/gtiff/libgeotiff/epsg_datum.inc
@@ -1,7 +1,7 @@
 /*
  *  EPSG/POSC Datum database -- GeoTIFF Rev. 0.2
  */
-
+ 
 /* C database for Geotiff include files.   */
 /* the macro ValuePair() must be defined   */
 /* by the enclosing include file           */
diff --git a/frmts/gtiff/libgeotiff/epsg_units.inc b/frmts/gtiff/libgeotiff/epsg_units.inc
index 50110f5..fe1b5db 100644
--- a/frmts/gtiff/libgeotiff/epsg_units.inc
+++ b/frmts/gtiff/libgeotiff/epsg_units.inc
@@ -1,7 +1,7 @@
 /*
  * Rev. 0.2 EPSG/POSC Units Database.
  */
-
+ 
 #ifdef INCLUDE_OLD_CODES
 #include geo_units.inc
 #endif /* OLD Codes */
diff --git a/frmts/gtiff/libgeotiff/geo_ctrans.inc b/frmts/gtiff/libgeotiff/geo_ctrans.inc
index ce3cb89..9bad7c1 100644
--- a/frmts/gtiff/libgeotiff/geo_ctrans.inc
+++ b/frmts/gtiff/libgeotiff/geo_ctrans.inc
@@ -2,7 +2,7 @@
  * $Id: geo_ctrans.inc 2209 2012-05-09 01:34:58Z warmerdam $
  *
  * Project:  libgeotiff
- * Purpose:  GeoTIFF Projection Method codes.
+ * Purpose:  GeoTIFF Projection Method codes. 
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
  ******************************************************************************
@@ -38,8 +38,8 @@
 /* by the enclosing include file           */
 
 /*
- *  Revised 12 Jul 1995   NDR -- changed South Oriented to a code
- *  Revised 28 Sep 1995   NDR -- Added Rev. 1.0 aliases.
+ *  Revised 12 Jul 1995   NDR -- changed South Oriented to a code 
+ *  Revised 28 Sep 1995   NDR -- Added Rev. 1.0 aliases. 
  */
 
 ValuePair(CT_TransverseMercator,	1)
diff --git a/frmts/gtiff/libgeotiff/geo_extra.c b/frmts/gtiff/libgeotiff/geo_extra.c
index a2ee182..3438840 100644
--- a/frmts/gtiff/libgeotiff/geo_extra.c
+++ b/frmts/gtiff/libgeotiff/geo_extra.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geo_extra.c 2691 2015-12-06 21:54:31Z rouault $
+ * $Id: geo_extra.c 2741 2016-09-04 18:50:49Z rouault $
  *
  * Project:  libgeotiff
  * Purpose:  Code to normalize a few common PCS values without use of CSV
diff --git a/frmts/gtiff/libgeotiff/geo_get.c b/frmts/gtiff/libgeotiff/geo_get.c
index 801c70d..1ce961b 100644
--- a/frmts/gtiff/libgeotiff/geo_get.c
+++ b/frmts/gtiff/libgeotiff/geo_get.c
@@ -68,12 +68,12 @@ that pointer's to <i>int</i> should never be passed to GTIFKeyGet() for
 integer values as they will be shorts, and the int's may not be properly
 initialized (and will be grossly wrong on MSB systems).
 
- at param index Indicates how far into the list of values
+ at param nIndex Indicates how far into the list of values
 for this geokey to offset. Should normally be zero.
 
 @param count Indicates how many values
 to read.  At this time all keys except for strings have only one value,
-so <b>index</b> should be zero, and <b>count</b> should be one.
+so <b>nIndex</b> should be zero, and <b>count</b> should be one.
 
 @return The GTIFKeyGet() function returns the number of values read.  Normally
 this would be one if successful or zero if the key doesn't exist for this
diff --git a/frmts/gtiff/libgeotiff/geo_new.c b/frmts/gtiff/libgeotiff/geo_new.c
index 9a4608e..8728d68 100644
--- a/frmts/gtiff/libgeotiff/geo_new.c
+++ b/frmts/gtiff/libgeotiff/geo_new.c
@@ -79,7 +79,7 @@ GTIF *GTIFNewSimpleTags( void *tif )
 
 GTIF* GTIFNewWithMethods(void *tif, TIFFMethod* methods)
 {
-    GTIF* gt=(GTIF*)0;
+    GTIF* gt;
     int count,bufcount,nIndex;
     GeoKey *keyptr;
     pinfo_t *data;
diff --git a/frmts/gtiff/libgeotiff/geo_normalize.c b/frmts/gtiff/libgeotiff/geo_normalize.c
index c3f954d..4089be6 100644
--- a/frmts/gtiff/libgeotiff/geo_normalize.c
+++ b/frmts/gtiff/libgeotiff/geo_normalize.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geo_normalize.c 2712 2016-01-11 11:36:59Z rouault $
+ * $Id: geo_normalize.c 2741 2016-09-04 18:50:49Z rouault $
  *
  * Project:  libgeotiff
  * Purpose:  Code to normalize PCS and other composite codes in a GeoTIFF file.
diff --git a/frmts/gtiff/libgeotiff/geo_print.c b/frmts/gtiff/libgeotiff/geo_print.c
index babcb83..775c279 100644
--- a/frmts/gtiff/libgeotiff/geo_print.c
+++ b/frmts/gtiff/libgeotiff/geo_print.c
@@ -27,15 +27,15 @@
 #include <stdio.h>     /* for sprintf             */
 
 #define FMT_GEOTIFF "Geotiff_Information:"
-#define FMT_VERSION "Version: %hd"
-#define FMT_REV     "Key_Revision: %1hd.%hd"
+#define FMT_VERSION "Version: %hu"
+#define FMT_REV     "Key_Revision: %1hu.%hu"
 #define FMT_TAGS    "Tagged_Information:"
 #define FMT_TAGEND  "End_Of_Tags."
 #define FMT_KEYS    "Keyed_Information:"
 #define FMT_KEYEND  "End_Of_Keys."
 #define FMT_GEOEND  "End_Of_Geotiff."
 #define FMT_DOUBLE  "%-17.15g"
-#define FMT_SHORT   "%-11hd"
+#define FMT_SHORT   "%-11hu"
 
 static void DefaultPrint(char *string, void *aux);
 static void PrintKey(GeoKey *key, GTIFPrintMethod print,void *aux);
@@ -67,7 +67,6 @@ void GTIFPrint(GTIF *gtif, GTIFPrintMethod print,void *aux)
 
     sprintf(message,FMT_GEOTIFF "\n");
     print(message,aux);
-    sprintf(message, "Version: %hd" ,gtif->gt_version);
     sprintf(message, FMT_VERSION,gtif->gt_version);
     print("   ",aux); print(message,aux); print("\n",aux);
     sprintf(message, FMT_REV,gtif->gt_rev_major,
@@ -262,6 +261,7 @@ static void DefaultPrint(char *string, void *aux)
 int GTIFImport(GTIF *gtif, GTIFReadMethod scan,void *aux)
 {
     int status;
+    /* Caution: if you change this size, also change it in DefaultRead */
     char message[1024];
 
     if (!scan) scan = (GTIFReadMethod) &DefaultRead;
@@ -270,10 +270,10 @@ int GTIFImport(GTIF *gtif, GTIFReadMethod scan,void *aux)
     scan(message,aux);
     if (strncmp(message,FMT_GEOTIFF,8)) return 0;
     scan(message,aux);
-    if (!sscanf(message,FMT_VERSION,(short int*)&gtif->gt_version)) return 0;
+    if (!sscanf(message,FMT_VERSION,(short unsigned*)&gtif->gt_version)) return 0;
     scan(message,aux);
-    if (sscanf(message,FMT_REV,(short int*)&gtif->gt_rev_major,
-               (short int*)&gtif->gt_rev_minor) !=2) return 0;
+    if (sscanf(message,FMT_REV,(short unsigned*)&gtif->gt_rev_major,
+               (short unsigned*)&gtif->gt_rev_minor) !=2) return 0;
 
     scan(message,aux);
     if (strncmp(message,FMT_TAGS,8)) return 0;
@@ -310,7 +310,7 @@ static int ReadTag(GTIF *gt,GTIFReadMethod scan,void *aux)
     scan(message,aux);
     if (!strncmp(message,FMT_TAGEND,8)) return 0;
 
-    num=sscanf(message,"%[^( ] (%d,%d):\n",tagname,&nrows,&ncols);
+    num=sscanf(message,"%99[^( ] (%d,%d):\n",tagname,&nrows,&ncols);
     if (num!=3) return StringError(message);
 
     tag = GTIFTagCode(tagname);
@@ -365,7 +365,7 @@ static int ReadKey(GTIF *gt, GTIFReadMethod scan, void *aux)
     scan(message,aux);
     if (!strncmp(message,FMT_KEYEND,8)) return 0;
 
-    num=sscanf(message,"%[^( ] (%[^,],%d):\n",name,type,&count);
+    num=sscanf(message,"%99[^( ] (%19[^,],%d):\n",name,type,&count);
     if (num!=3) return StringError(message);
 
     vptr = message;
@@ -507,7 +507,8 @@ static void DefaultRead(char *string, void *aux)
 {
     /* Pretty boring */
     int num_read;
-    num_read = fscanf((FILE *)aux, "%[^\n]\n", string);
+    /* 1023 comes from char message[1024]; in GTIFFImport */
+    num_read = fscanf((FILE *)aux, "%1023[^\n]\n", string);
     if (num_read != 0) {
       fprintf(stderr, "geo_print.c DefaultRead failed to read anything.\n");
     }
diff --git a/frmts/gtiff/libgeotiff/geo_set.c b/frmts/gtiff/libgeotiff/geo_set.c
index 7831dcc..e3c2a61 100644
--- a/frmts/gtiff/libgeotiff/geo_set.c
+++ b/frmts/gtiff/libgeotiff/geo_set.c
@@ -26,23 +26,13 @@ This function writes a geokey_t value to a GeoTIFF file.
 This must come from the list of legal geokey_t values
 (an enumeration) listed below.
 
- at param val The <b>val</b> argument is a pointer to the
-variable into which the value should be read.  The type of the variable
-varies depending on the geokey_t given.  While there is no ready mapping
-of geokey_t values onto types, in general code values are of type <i>short</i>,
-citations are strings, and everything else is of type <i>double</i>.  Note
-that pointer's to <i>int</i> should never be passed to GTIFKeyGet() for
-integer values as they will be shorts, and the int's may not be properly
-initialized (and will be grossly wrong on MSB systems).
-
- at param index Indicates how far into the list of values
-for this geokey to offset. Should normally be zero.
+ at param type Type of the key.
 
 @param count Indicates how many values
 to read.  At this time all keys except for strings have only one value,
 so <b>index</b> should be zero, and <b>count</b> should be one.<p>
 
-The <b>key</b> indicates the key name to be written to the
+The <b>keyID</b> indicates the key name to be written to the
 file and should from the geokey_t enumeration
 (eg. <tt>ProjectedCSTypeGeoKey</tt>).  The full list of possible geokey_t
 values can be found in geokeys.inc, or in the online documentation for
@@ -123,8 +113,16 @@ int GTIFKeySet(GTIF *gtif, geokey_t keyID, tagtype_t type, int count,...)
     }
     else switch (type)
     {
-      case TYPE_SHORT:  sval=(pinfo_t) va_arg(ap, int); val=(char *)&sval;     break;
-      case TYPE_DOUBLE: dval=va_arg(ap, dblparam_t); val=(char *)&dval;  break;
+      case TYPE_SHORT:
+        /* cppcheck-suppress unreadVariable */
+        sval=(pinfo_t) va_arg(ap, int);
+        val=(char *)&sval;
+        break;
+      case TYPE_DOUBLE:
+        /* cppcheck-suppress unreadVariable */
+        dval=va_arg(ap, dblparam_t);
+        val=(char *)&dval;
+        break;
       case TYPE_ASCII:
         val=va_arg(ap, char*);
         count = (int)strlen(val) + 1; /* force = string length */
diff --git a/frmts/gtiff/libgeotiff/geo_simpletags.c b/frmts/gtiff/libgeotiff/geo_simpletags.c
index 9db79d8..f6e75e1 100644
--- a/frmts/gtiff/libgeotiff/geo_simpletags.c
+++ b/frmts/gtiff/libgeotiff/geo_simpletags.c
@@ -152,6 +152,7 @@ static int ST_TypeSize( int st_type )
         return 1;
     else if( st_type == STT_SHORT )
         return 2;
+    /* cppcheck-suppress duplicateBranch */
     else if( st_type == STT_DOUBLE )
         return 8;
     else
diff --git a/frmts/gtiff/libgeotiff/geo_trans.c b/frmts/gtiff/libgeotiff/geo_trans.c
index 8f5460f..740eaf9 100644
--- a/frmts/gtiff/libgeotiff/geo_trans.c
+++ b/frmts/gtiff/libgeotiff/geo_trans.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geo_trans.c 2678 2015-10-28 19:06:57Z rouault $
+ * $Id: geo_trans.c 2741 2016-09-04 18:50:49Z rouault $
  *
  * Project:  libgeotiff
  * Purpose:  Code to abstract translation between pixel/line and PCS
diff --git a/frmts/gtiff/libgeotiff/geokeys.inc b/frmts/gtiff/libgeotiff/geokeys.inc
index 21263e2..03be6e0 100644
--- a/frmts/gtiff/libgeotiff/geokeys.inc
+++ b/frmts/gtiff/libgeotiff/geokeys.inc
@@ -68,7 +68,7 @@ ValuePair(  ProjStraightVertPoleLongGeoKey, 3095) /* GeogAngularUnit */
 ValuePair(  ProjRectifiedGridAngleGeoKey, 3096)   /* GeogAngularUnit */
 
 /* 6.2.4 Vertical CS Keys */
-
+   
 ValuePair(  VerticalCSTypeGeoKey,	4096)  /* Section 6.3.4.1 codes   */
 ValuePair(  VerticalCitationGeoKey,	4097)  /* documentation */
 ValuePair(  VerticalDatumGeoKey,	4098)  /* Section 6.3.4.2 codes   */
diff --git a/frmts/gtiff/libgeotiff/geotiff.h b/frmts/gtiff/libgeotiff/geotiff.h
index 2cab1bb..7b82446 100644
--- a/frmts/gtiff/libgeotiff/geotiff.h
+++ b/frmts/gtiff/libgeotiff/geotiff.h
@@ -30,7 +30,7 @@
  */
 #define GvCurrentVersion   1
 
-#define LIBGEOTIFF_VERSION 1410
+#define LIBGEOTIFF_VERSION 1420
 
 #include "geo_config.h"
 #include "geokeys.h"
diff --git a/frmts/gtiff/libgeotiff/geotiff_proj4.c b/frmts/gtiff/libgeotiff/geotiff_proj4.c
index 6c0e2c5..21c2987 100644
--- a/frmts/gtiff/libgeotiff/geotiff_proj4.c
+++ b/frmts/gtiff/libgeotiff/geotiff_proj4.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: geotiff_proj4.c 2653 2015-05-02 12:07:17Z rouault $
+ * $Id: geotiff_proj4.c 2741 2016-09-04 18:50:49Z rouault $
  *
  * Project:  libgeotiff
  * Purpose:  Code to convert a normalized GeoTIFF definition into a PROJ.4
diff --git a/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h b/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
index 88ffdd3..41656bb 100644
--- a/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
+++ b/frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h
@@ -385,6 +385,7 @@
 #define TIFFLastDirectory gdal_TIFFLastDirectory
 #define TIFFLinkDirectory gdal_TIFFLinkDirectory
 #define _TIFFmalloc gdal__TIFFmalloc
+#define _TIFFcalloc gdal__TIFFcalloc
 #define _tiffMapProc gdal__tiffMapProc
 #define _TIFFmemcmp gdal__TIFFmemcmp
 #define _TIFFmemcpy gdal__TIFFmemcpy
@@ -512,6 +513,8 @@
 #define TIFFReadRGBAImageOriented gdal_TIFFReadRGBAImageOriented
 #define TIFFReadRGBAStrip gdal_TIFFReadRGBAStrip
 #define TIFFReadRGBATile gdal_TIFFReadRGBATile
+#define TIFFReadRGBAStripExt gdal_TIFFReadRGBAStripExt
+#define TIFFReadRGBATileExt gdal_TIFFReadRGBATileExt
 #define TIFFReadScanline gdal_TIFFReadScanline
 #define TIFFReadTile gdal_TIFFReadTile
 #define TIFFReadUInt64 gdal_TIFFReadUInt64
diff --git a/frmts/gtiff/libtiff/makefile.vc b/frmts/gtiff/libtiff/makefile.vc
index d802a42..58fca09 100644
--- a/frmts/gtiff/libtiff/makefile.vc
+++ b/frmts/gtiff/libtiff/makefile.vc
@@ -44,7 +44,7 @@ GDAL_ROOT	=	..\..\..
 # /wd4324 silents warning C4324: '<unnamed-tag>' : structure was padded due to __declspec(align())
 # in tif_jpeg.c:147 and tif_ojpeg.c:248
 
-EXTRAFLAGS = 	-I..\..\zlib -DZIP_SUPPORT -DPIXARLOG_SUPPORT \
+EXTRAFLAGS = 	$(ZLIB_FLAGS) -DZIP_SUPPORT -DPIXARLOG_SUPPORT \
 		$(JPEG_FLAGS) $(JPEG12_FLAGS) $(LZMA_FLAGS) /wd4324
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
@@ -57,6 +57,12 @@ JPEG_FLAGS =	-I..\..\jpeg\libjpeg -DJPEG_SUPPORT -DOJPEG_SUPPORT
 !ENDIF
 !ENDIF
 
+!IFDEF ZLIB_EXTERNAL_LIB
+ZLIB_FLAGS = $(ZLIB_INC)
+!ELSE
+ZLIB_FLAGS = -I..\..\zlib
+!ENDIF
+
 !IFDEF JPEG12_SUPPORTED
 JPEG12_FLAGS =	-DJPEG_DUAL_MODE_8_12
 EXTRA_DEP    =  libjpeg12src
diff --git a/frmts/gtiff/libtiff/tif_aux.c b/frmts/gtiff/libtiff/tif_aux.c
index fb6ece1..3d35ba9 100644
--- a/frmts/gtiff/libtiff/tif_aux.c
+++ b/frmts/gtiff/libtiff/tif_aux.c
@@ -1,4 +1,4 @@
-/* $Id: tif_aux.c,v 1.28 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_aux.c,v 1.29 2016-11-11 20:45:53 erouault Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
@@ -212,11 +212,18 @@ TIFFVGetFieldDefaulted(TIFF* tif, uint32 tag, va_list ap)
 		*va_arg(ap, uint16 *) = td->td_resolutionunit;
 		return (1);
 	case TIFFTAG_PREDICTOR:
-                {
-			TIFFPredictorState* sp = (TIFFPredictorState*) tif->tif_data;
-			*va_arg(ap, uint16*) = (uint16) sp->predictor;
-			return 1;
-                }
+    {
+        TIFFPredictorState* sp = (TIFFPredictorState*) tif->tif_data;
+        if( sp == NULL )
+        {
+            TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+                         "Cannot get \"Predictor\" tag as plugin is not configured");
+            *va_arg(ap, uint16*) = 0;
+            return 0;
+        }
+        *va_arg(ap, uint16*) = (uint16) sp->predictor;
+        return 1;
+    }
 	case TIFFTAG_DOTRANGE:
 		*va_arg(ap, uint16 *) = 0;
 		*va_arg(ap, uint16 *) = (1<<td->td_bitspersample)-1;
diff --git a/frmts/gtiff/libtiff/tif_color.c b/frmts/gtiff/libtiff/tif_color.c
index d7a1ecd..89194c2 100644
--- a/frmts/gtiff/libtiff/tif_color.c
+++ b/frmts/gtiff/libtiff/tif_color.c
@@ -1,4 +1,4 @@
-/* $Id: tif_color.c,v 1.20 2015-10-17 10:13:14 erouault Exp $ */
+/* $Id: tif_color.c,v 1.22 2016-09-04 21:32:56 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -175,7 +175,7 @@ TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab,
 #define	SHIFT			16
 #define	FIX(x)			((int32)((x) * (1L<<SHIFT) + 0.5))
 #define	ONE_HALF		((int32)(1<<(SHIFT-1)))
-#define	Code2V(c, RB, RW, CR)	((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)) ? ((RW)-(RB)) : 1))
+#define	Code2V(c, RB, RW, CR)	((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)!=0) ? ((RW)-(RB)) : 1))
 #define	CLAMP(f,min,max)	((f)<(min)?(min):(f)>(max)?(max):(f))
 #define HICLAMP(f,max)		((f)>(max)?(max):(f))
 
@@ -186,7 +186,9 @@ TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr,
 	int32 i;
 
 	/* XXX: Only 8-bit YCbCr input supported for now */
-	Y = HICLAMP(Y, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255);
+	Y = HICLAMP(Y, 255);
+	Cb = CLAMP(Cb, 0, 255);
+	Cr = CLAMP(Cr, 0, 255);
 
 	i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr];
 	*r = CLAMP(i, 0, 255);
diff --git a/frmts/gtiff/libtiff/tif_compress.c b/frmts/gtiff/libtiff/tif_compress.c
index f6b32df..b571d19 100644
--- a/frmts/gtiff/libtiff/tif_compress.c
+++ b/frmts/gtiff/libtiff/tif_compress.c
@@ -1,4 +1,4 @@
-/* $Id: tif_compress.c,v 1.24 2015-11-22 15:31:03 erouault Exp $ */
+/* $Id: tif_compress.c,v 1.25 2016-10-25 20:04:22 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -82,7 +82,7 @@ TIFFNoDecode(TIFF* tif, const char* method)
 		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
 			     "Compression scheme %u %s decoding is not implemented",
 			     tif->tif_dir.td_compression, method);
-	return (-1);
+	return (0);
 }
 
 static int
diff --git a/frmts/gtiff/libtiff/tif_dir.c b/frmts/gtiff/libtiff/tif_dir.c
index 328b9d6..36c7ae5 100644
--- a/frmts/gtiff/libtiff/tif_dir.c
+++ b/frmts/gtiff/libtiff/tif_dir.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dir.c,v 1.125 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_dir.c,v 1.129 2017-01-11 16:09:02 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -31,6 +31,7 @@
  * (and also some miscellaneous stuff)
  */
 #include "tiffiop.h"
+#include <float.h>
 
 /*
  * These are used in the backwards compatibility code...
@@ -43,8 +44,10 @@
 static void
 setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size)
 {
-	if (*vpp)
-		_TIFFfree(*vpp), *vpp = 0;
+	if (*vpp) {
+		_TIFFfree(*vpp);
+		*vpp = 0;
+	}
 	if (vp) {
 		tmsize_t bytes = (tmsize_t)(nmemb * elem_size);
 		if (elem_size && bytes / elem_size == nmemb)
@@ -152,6 +155,15 @@ bad:
 	return (0);
 }
 
+static float TIFFClampDoubleToFloat( double val )
+{
+    if( val > FLT_MAX )
+        return FLT_MAX;
+    if( val < -FLT_MAX )
+        return -FLT_MAX;
+    return (float)val;
+}
+
 static int
 _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 {
@@ -254,6 +266,28 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 		v = (uint16) va_arg(ap, uint16_vap);
 		if (v == 0)
 			goto badvalue;
+        if( v != td->td_samplesperpixel )
+        {
+            /* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 */
+            if( td->td_sminsamplevalue != NULL )
+            {
+                TIFFWarningExt(tif->tif_clientdata,module,
+                    "SamplesPerPixel tag value is changing, "
+                    "but SMinSampleValue tag was read with a different value. Cancelling it");
+                TIFFClrFieldBit(tif,FIELD_SMINSAMPLEVALUE);
+                _TIFFfree(td->td_sminsamplevalue);
+                td->td_sminsamplevalue = NULL;
+            }
+            if( td->td_smaxsamplevalue != NULL )
+            {
+                TIFFWarningExt(tif->tif_clientdata,module,
+                    "SamplesPerPixel tag value is changing, "
+                    "but SMaxSampleValue tag was read with a different value. Cancelling it");
+                TIFFClrFieldBit(tif,FIELD_SMAXSAMPLEVALUE);
+                _TIFFfree(td->td_smaxsamplevalue);
+                td->td_smaxsamplevalue = NULL;
+            }
+        }
 		td->td_samplesperpixel = (uint16) v;
 		break;
 	case TIFFTAG_ROWSPERSTRIP:
@@ -288,13 +322,13 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
         dblval = va_arg(ap, double);
         if( dblval < 0 )
             goto badvaluedouble;
-		td->td_xresolution = (float) dblval;
+		td->td_xresolution = TIFFClampDoubleToFloat( dblval );
 		break;
 	case TIFFTAG_YRESOLUTION:
         dblval = va_arg(ap, double);
         if( dblval < 0 )
             goto badvaluedouble;
-		td->td_yresolution = (float) dblval;
+		td->td_yresolution = TIFFClampDoubleToFloat( dblval );
 		break;
 	case TIFFTAG_PLANARCONFIG:
 		v = (uint16) va_arg(ap, uint16_vap);
@@ -303,10 +337,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 		td->td_planarconfig = (uint16) v;
 		break;
 	case TIFFTAG_XPOSITION:
-		td->td_xposition = (float) va_arg(ap, double);
+		td->td_xposition = TIFFClampDoubleToFloat( va_arg(ap, double) );
 		break;
 	case TIFFTAG_YPOSITION:
-		td->td_yposition = (float) va_arg(ap, double);
+		td->td_yposition = TIFFClampDoubleToFloat( va_arg(ap, double) );
 		break;
 	case TIFFTAG_RESOLUTIONUNIT:
 		v = (uint16) va_arg(ap, uint16_vap);
@@ -830,6 +864,32 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
 	if( fip == NULL ) /* cannot happen since TIFFGetField() already checks it */
 	    return 0;
 	
+        if( tag == TIFFTAG_NUMBEROFINKS )
+        {
+            int i;
+            for (i = 0; i < td->td_customValueCount; i++) {
+                uint16 val;
+                TIFFTagValue *tv = td->td_customValues + i;
+                if (tv->info->field_tag != tag)
+                    continue;
+                val = *(uint16 *)tv->value;
+                /* Truncate to SamplesPerPixel, since the */
+                /* setting code for INKNAMES assume that there are SamplesPerPixel */
+                /* inknames. */
+                /* Fixes http://bugzilla.maptools.org/show_bug.cgi?id=2599 */
+                if( val > td->td_samplesperpixel )
+                {
+                    TIFFWarningExt(tif->tif_clientdata,"_TIFFVGetField",
+                                   "Truncating NumberOfInks from %u to %u",
+                                   val, td->td_samplesperpixel);
+                    val = td->td_samplesperpixel;
+                }
+                *va_arg(ap, uint16*) = val;
+                return 1;
+            }
+            return 0;
+        }
+
 	/*
 	 * We want to force the custom code to be used for custom
 	 * fields even if the tag happens to match a well known 
diff --git a/frmts/gtiff/libtiff/tif_dirinfo.c b/frmts/gtiff/libtiff/tif_dirinfo.c
index 3d4f50f..23ad002 100644
--- a/frmts/gtiff/libtiff/tif_dirinfo.c
+++ b/frmts/gtiff/libtiff/tif_dirinfo.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirinfo.c,v 1.125 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_dirinfo.c,v 1.126 2016-11-18 02:52:13 bfriesen Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -721,7 +721,7 @@ _TIFFCreateAnonField(TIFF *tif, uint32 tag, TIFFDataType field_type)
 	 * note that this name is a special sign to TIFFClose() and
 	 * _TIFFSetupFields() to free the field
 	 */
-	snprintf(fld->field_name, 32, "Tag %d", (int) tag);
+	(void) snprintf(fld->field_name, 32, "Tag %d", (int) tag);
 
 	return fld;    
 }
diff --git a/frmts/gtiff/libtiff/tif_dirread.c b/frmts/gtiff/libtiff/tif_dirread.c
index a8597db..f8628fd 100644
--- a/frmts/gtiff/libtiff/tif_dirread.c
+++ b/frmts/gtiff/libtiff/tif_dirread.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirread.c,v 1.200 2016-01-03 10:01:25 erouault Exp $ */
+/* $Id: tif_dirread.c,v 1.207 2017-01-11 16:09:02 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -40,6 +40,7 @@
  */
 
 #include "tiffiop.h"
+#include <float.h>
 
 #define IGNORE 0          /* tag placeholder used below */
 #define FAILED_FII    ((uint32) -1)
@@ -2406,7 +2407,14 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryFloatArray(TIFF* tif, TIFFDirEnt
 				ma=(double*)origdata;
 				mb=data;
 				for (n=0; n<count; n++)
-					*mb++=(float)(*ma++);
+                                {
+                                    double val = *ma++;
+                                    if( val > FLT_MAX )
+                                        val = FLT_MAX;
+                                    else if( val < -FLT_MAX )
+                                        val = -FLT_MAX;
+                                    *mb++=(float)val;
+                                }
 			}
 			break;
 	}
@@ -2872,7 +2880,10 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedRational(TIFF* tif, TIFFD
 		m.l = direntry->tdir_offset.toff_long8;
 	if (tif->tif_flags&TIFF_SWAB)
 		TIFFSwabArrayOfLong(m.i,2);
-	if (m.i[0]==0)
+        /* Not completely sure what we should do when m.i[1]==0, but some */
+        /* sanitizers do not like division by 0.0: */
+        /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */
+	if (m.i[0]==0 || m.i[1]==0)
 		*value=0.0;
 	else
 		*value=(double)m.i[0]/(double)m.i[1];
@@ -2900,7 +2911,10 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSrational(TIFF* tif, TIFF
 		m.l=direntry->tdir_offset.toff_long8;
 	if (tif->tif_flags&TIFF_SWAB)
 		TIFFSwabArrayOfLong(m.i,2);
-	if ((int32)m.i[0]==0)
+        /* Not completely sure what we should do when m.i[1]==0, but some */
+        /* sanitizers do not like division by 0.0: */
+        /* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */
+	if ((int32)m.i[0]==0 || m.i[1]==0)
 		*value=0.0;
 	else
 		*value=(double)((int32)m.i[0])/(double)m.i[1];
@@ -3628,6 +3642,7 @@ TIFFReadDirectory(TIFF* tif)
 	if (tif->tif_dir.td_planarconfig == PLANARCONFIG_SEPARATE)
 		tif->tif_dir.td_stripsperimage /= tif->tif_dir.td_samplesperpixel;
 	if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) {
+#ifdef OJPEG_SUPPORT
 		if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG) &&
 		    (isTiled(tif)==0) &&
 		    (tif->tif_dir.td_nstrips==1)) {
@@ -3640,7 +3655,9 @@ TIFFReadDirectory(TIFF* tif)
 			 * JpegInterchangeFormat stream.
 			 */
 			TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
-		} else {
+		} else
+#endif
+        {
 			MissingRequired(tif,
 				isTiled(tif) ? "TileOffsets" : "StripOffsets");
 			goto bad;
@@ -4997,6 +5014,11 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
 					if (err==TIFFReadDirEntryErrOk)
 					{
 						int m;
+                        if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
+                        {
+                            TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
+                            data[dp->tdir_count-1] = '\0';
+                        }
 						m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data);
 						if (data!=0)
 							_TIFFfree(data);
@@ -5169,6 +5191,11 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
 				if (err==TIFFReadDirEntryErrOk)
 				{
 					int m;
+                    if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
+                    {
+                        TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
+                        data[dp->tdir_count-1] = '\0';
+                    }
 					m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data);
 					if (data!=0)
 						_TIFFfree(data);
@@ -5489,8 +5516,7 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
 	uint64 rowblockbytes;
 	uint64 stripbytes;
 	uint32 strip;
-	uint64 nstrips64;
-	uint32 nstrips32;
+	uint32 nstrips;
 	uint32 rowsperstrip;
 	uint64* newcounts;
 	uint64* newoffsets;
@@ -5521,18 +5547,17 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
 	    return;
 
 	/*
-	 * never increase the number of strips in an image
+	 * never increase the number of rows per strip
 	 */
 	if (rowsperstrip >= td->td_rowsperstrip)
 		return;
-	nstrips64 = TIFFhowmany_64(bytecount, stripbytes);
-	if ((nstrips64==0)||(nstrips64>0xFFFFFFFF)) /* something is wonky, do nothing. */
-	    return;
-	nstrips32 = (uint32)nstrips64;
+        nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip);
+        if( nstrips == 0 )
+            return;
 
-	newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips32, sizeof (uint64),
+	newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
 				"for chopped \"StripByteCounts\" array");
-	newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips32, sizeof (uint64),
+	newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
 				"for chopped \"StripOffsets\" array");
 	if (newcounts == NULL || newoffsets == NULL) {
 		/*
@@ -5549,18 +5574,18 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
 	 * Fill the strip information arrays with new bytecounts and offsets
 	 * that reflect the broken-up format.
 	 */
-	for (strip = 0; strip < nstrips32; strip++) {
+	for (strip = 0; strip < nstrips; strip++) {
 		if (stripbytes > bytecount)
 			stripbytes = bytecount;
 		newcounts[strip] = stripbytes;
-		newoffsets[strip] = offset;
+		newoffsets[strip] = stripbytes ? offset : 0;
 		offset += stripbytes;
 		bytecount -= stripbytes;
 	}
 	/*
 	 * Replace old single strip info with multi-strip info.
 	 */
-	td->td_stripsperimage = td->td_nstrips = nstrips32;
+	td->td_stripsperimage = td->td_nstrips = nstrips;
 	TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
 
 	_TIFFfree(td->td_stripbytecount);
diff --git a/frmts/gtiff/libtiff/tif_dirwrite.c b/frmts/gtiff/libtiff/tif_dirwrite.c
index 33befd4..f733968 100644
--- a/frmts/gtiff/libtiff/tif_dirwrite.c
+++ b/frmts/gtiff/libtiff/tif_dirwrite.c
@@ -1,4 +1,4 @@
-/* $Id: tif_dirwrite.c,v 1.81 2015-12-18 11:11:00 erouault Exp $ */
+/* $Id: tif_dirwrite.c,v 1.85 2017-01-11 16:09:02 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -30,6 +30,7 @@
  * Directory Write Support Routines.
  */
 #include "tiffiop.h"
+#include <float.h>
 
 #ifdef HAVE_IEEEFP
 #define TIFFCvtNativeToIEEEFloat(tif, n, fp)
@@ -542,8 +543,20 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
 			{
 				if (!isTiled(tif))
 				{
-					if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset))
-						goto bad;
+                    /* td_stripoffset might be NULL in an odd OJPEG case. See
+                     *  tif_dirread.c around line 3634.
+                     * XXX: OJPEG hack.
+                     * If a) compression is OJPEG, b) it's not a tiled TIFF,
+                     * and c) the number of strips is 1,
+                     * then we tolerate the absence of stripoffsets tag,
+                     * because, presumably, all required data is in the
+                     * JpegInterchangeFormat stream.
+                     * We can get here when using tiffset on such a file.
+                     * See http://bugzilla.maptools.org/show_bug.cgi?id=2500
+                    */
+                    if (tif->tif_dir.td_stripoffset != NULL &&
+                        !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset))
+                        goto bad;
 				}
 				else
 				{
@@ -927,6 +940,69 @@ bad:
 	return(0);
 }
 
+static float TIFFClampDoubleToFloat( double val )
+{
+    if( val > FLT_MAX )
+        return FLT_MAX;
+    if( val < -FLT_MAX )
+        return -FLT_MAX;
+    return (float)val;
+}
+
+static int8 TIFFClampDoubleToInt8( double val )
+{
+    if( val > 127 )
+        return 127;
+    if( val < -128 || val != val )
+        return -128;
+    return (int8)val;
+}
+
+static int16 TIFFClampDoubleToInt16( double val )
+{
+    if( val > 32767 )
+        return 32767;
+    if( val < -32768 || val != val )
+        return -32768;
+    return (int16)val;
+}
+
+static int32 TIFFClampDoubleToInt32( double val )
+{
+    if( val > 0x7FFFFFFF )
+        return 0x7FFFFFFF;
+    if( val < -0x7FFFFFFF-1 || val != val )
+        return -0x7FFFFFFF-1;
+    return (int32)val;
+}
+
+static uint8 TIFFClampDoubleToUInt8( double val )
+{
+    if( val < 0 )
+        return 0;
+    if( val > 255 || val != val )
+        return 255;
+    return (uint8)val;
+}
+
+static uint16 TIFFClampDoubleToUInt16( double val )
+{
+    if( val < 0 )
+        return 0;
+    if( val > 65535 || val != val )
+        return 65535;
+    return (uint16)val;
+}
+
+static uint32 TIFFClampDoubleToUInt32( double val )
+{
+    if( val < 0 )
+        return 0;
+    if( val > 0xFFFFFFFFU || val != val )
+        return 0xFFFFFFFFU;
+    return (uint32)val;
+}
+
 static int
 TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, double* value)
 {
@@ -947,7 +1023,7 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di
 			if (tif->tif_dir.td_bitspersample<=32)
 			{
 				for (i = 0; i < count; ++i)
-					((float*)conv)[i] = (float)value[i];
+					((float*)conv)[i] = TIFFClampDoubleToFloat(value[i]);
 				ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv);
 			}
 			else
@@ -959,19 +1035,19 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di
 			if (tif->tif_dir.td_bitspersample<=8)
 			{
 				for (i = 0; i < count; ++i)
-					((int8*)conv)[i] = (int8)value[i];
+					((int8*)conv)[i] = TIFFClampDoubleToInt8(value[i]);
 				ok = TIFFWriteDirectoryTagSbyteArray(tif,ndir,dir,tag,count,(int8*)conv);
 			}
 			else if (tif->tif_dir.td_bitspersample<=16)
 			{
 				for (i = 0; i < count; ++i)
-					((int16*)conv)[i] = (int16)value[i];
+					((int16*)conv)[i] = TIFFClampDoubleToInt16(value[i]);
 				ok = TIFFWriteDirectoryTagSshortArray(tif,ndir,dir,tag,count,(int16*)conv);
 			}
 			else
 			{
 				for (i = 0; i < count; ++i)
-					((int32*)conv)[i] = (int32)value[i];
+					((int32*)conv)[i] = TIFFClampDoubleToInt32(value[i]);
 				ok = TIFFWriteDirectoryTagSlongArray(tif,ndir,dir,tag,count,(int32*)conv);
 			}
 			break;
@@ -979,19 +1055,19 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di
 			if (tif->tif_dir.td_bitspersample<=8)
 			{
 				for (i = 0; i < count; ++i)
-					((uint8*)conv)[i] = (uint8)value[i];
+					((uint8*)conv)[i] = TIFFClampDoubleToUInt8(value[i]);
 				ok = TIFFWriteDirectoryTagByteArray(tif,ndir,dir,tag,count,(uint8*)conv);
 			}
 			else if (tif->tif_dir.td_bitspersample<=16)
 			{
 				for (i = 0; i < count; ++i)
-					((uint16*)conv)[i] = (uint16)value[i];
+					((uint16*)conv)[i] = TIFFClampDoubleToUInt16(value[i]);
 				ok = TIFFWriteDirectoryTagShortArray(tif,ndir,dir,tag,count,(uint16*)conv);
 			}
 			else
 			{
 				for (i = 0; i < count; ++i)
-					((uint32*)conv)[i] = (uint32)value[i];
+					((uint32*)conv)[i] = TIFFClampDoubleToUInt32(value[i]);
 				ok = TIFFWriteDirectoryTagLongArray(tif,ndir,dir,tag,count,(uint32*)conv);
 			}
 			break;
@@ -2082,15 +2158,25 @@ TIFFWriteDirectoryTagCheckedSlong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* d
 static int
 TIFFWriteDirectoryTagCheckedRational(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, double value)
 {
+        static const char module[] = "TIFFWriteDirectoryTagCheckedRational";
 	uint32 m[2];
-	assert(value>=0.0);
 	assert(sizeof(uint32)==4);
-	if (value<=0.0)
+        if( value < 0 )
+        {
+            TIFFErrorExt(tif->tif_clientdata,module,"Negative value is illegal");
+            return 0;
+        }
+        else if( value != value )
+        {
+            TIFFErrorExt(tif->tif_clientdata,module,"Not-a-number value is illegal");
+            return 0;
+        }
+	else if (value==0.0)
 	{
 		m[0]=0;
 		m[1]=1;
 	}
-	else if (value==(double)(uint32)value)
+	else if (value <= 0xFFFFFFFFU && value==(double)(uint32)value)
 	{
 		m[0]=(uint32)value;
 		m[1]=1;
@@ -2131,25 +2217,26 @@ TIFFWriteDirectoryTagCheckedRationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry*
 	}
 	for (na=value, nb=m, nc=0; nc<count; na++, nb+=2, nc++)
 	{
-		if (*na<=0.0)
+		if (*na<=0.0 || *na != *na)
 		{
 			nb[0]=0;
 			nb[1]=1;
 		}
-		else if (*na==(float)(uint32)(*na))
+		else if (*na >= 0 && *na <= (float)0xFFFFFFFFU &&
+                         *na==(float)(uint32)(*na))
 		{
 			nb[0]=(uint32)(*na);
 			nb[1]=1;
 		}
 		else if (*na<1.0)
 		{
-			nb[0]=(uint32)((*na)*0xFFFFFFFF);
+			nb[0]=(uint32)((double)(*na)*0xFFFFFFFF);
 			nb[1]=0xFFFFFFFF;
 		}
 		else
 		{
 			nb[0]=0xFFFFFFFF;
-			nb[1]=(uint32)(0xFFFFFFFF/(*na));
+			nb[1]=(uint32)((double)0xFFFFFFFF/(*na));
 		}
 	}
 	if (tif->tif_flags&TIFF_SWAB)
@@ -2186,13 +2273,13 @@ TIFFWriteDirectoryTagCheckedSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry
 			}
 			else if (*na>-1.0)
 			{
-				nb[0]=-(int32)((-*na)*0x7FFFFFFF);
+				nb[0]=-(int32)((double)(-*na)*0x7FFFFFFF);
 				nb[1]=0x7FFFFFFF;
 			}
 			else
 			{
 				nb[0]=-0x7FFFFFFF;
-				nb[1]=(int32)(0x7FFFFFFF/(-*na));
+				nb[1]=(int32)((double)0x7FFFFFFF/(-*na));
 			}
 		}
 		else
@@ -2204,13 +2291,13 @@ TIFFWriteDirectoryTagCheckedSrationalArray(TIFF* tif, uint32* ndir, TIFFDirEntry
 			}
 			else if (*na<1.0)
 			{
-				nb[0]=(int32)((*na)*0x7FFFFFFF);
+				nb[0]=(int32)((double)(*na)*0x7FFFFFFF);
 				nb[1]=0x7FFFFFFF;
 			}
 			else
 			{
 				nb[0]=0x7FFFFFFF;
-				nb[1]=(int32)(0x7FFFFFFF/(*na));
+				nb[1]=(int32)((double)0x7FFFFFFF/(*na));
 			}
 		}
 	}
diff --git a/frmts/gtiff/libtiff/tif_fax3.c b/frmts/gtiff/libtiff/tif_fax3.c
index e053b52..519b285 100644
--- a/frmts/gtiff/libtiff/tif_fax3.c
+++ b/frmts/gtiff/libtiff/tif_fax3.c
@@ -1,4 +1,4 @@
-/* $Id: tif_fax3.c,v 1.77 2015-12-19 21:50:52 erouault Exp $ */
+/* $Id: tif_fax3.c,v 1.79 2017-02-25 17:05:12 erouault Exp $ */
 
 /*
  * Copyright (c) 1990-1997 Sam Leffler
@@ -329,34 +329,64 @@ Fax3Decode2D(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 #if SIZEOF_UNSIGNED_LONG == 8
 # define FILL(n, cp)							    \
     switch (n) {							    \
-    case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\
-    case 12:(cp)[11] = 0xff; case 11:(cp)[10] = 0xff; case 10: (cp)[9] = 0xff;\
-    case  9: (cp)[8] = 0xff; case  8: (cp)[7] = 0xff; case  7: (cp)[6] = 0xff;\
-    case  6: (cp)[5] = 0xff; case  5: (cp)[4] = 0xff; case  4: (cp)[3] = 0xff;\
-    case  3: (cp)[2] = 0xff; case  2: (cp)[1] = 0xff;			      \
-    case  1: (cp)[0] = 0xff; (cp) += (n); case 0:  ;			      \
+    case 15:(cp)[14] = 0xff; /*-fallthrough*/ \
+    case 14:(cp)[13] = 0xff; /*-fallthrough*/ \
+    case 13:(cp)[12] = 0xff; /*-fallthrough*/ \
+    case 12:(cp)[11] = 0xff; /*-fallthrough*/ \
+    case 11:(cp)[10] = 0xff; /*-fallthrough*/ \
+    case 10: (cp)[9] = 0xff; /*-fallthrough*/ \
+    case  9: (cp)[8] = 0xff; /*-fallthrough*/ \
+    case  8: (cp)[7] = 0xff; /*-fallthrough*/ \
+    case  7: (cp)[6] = 0xff; /*-fallthrough*/ \
+    case  6: (cp)[5] = 0xff; /*-fallthrough*/ \
+    case  5: (cp)[4] = 0xff; /*-fallthrough*/ \
+    case  4: (cp)[3] = 0xff; /*-fallthrough*/ \
+    case  3: (cp)[2] = 0xff; /*-fallthrough*/ \
+    case  2: (cp)[1] = 0xff; /*-fallthrough*/ \
+    case  1: (cp)[0] = 0xff; (cp) += (n); /*-fallthrough*/ \
+    case 0:  ;			      \
     }
 # define ZERO(n, cp)							\
     switch (n) {							\
-    case 15:(cp)[14] = 0; case 14:(cp)[13] = 0; case 13: (cp)[12] = 0;	\
-    case 12:(cp)[11] = 0; case 11:(cp)[10] = 0; case 10: (cp)[9] = 0;	\
-    case  9: (cp)[8] = 0; case  8: (cp)[7] = 0; case  7: (cp)[6] = 0;	\
-    case  6: (cp)[5] = 0; case  5: (cp)[4] = 0; case  4: (cp)[3] = 0;	\
-    case  3: (cp)[2] = 0; case  2: (cp)[1] = 0;				\
-    case  1: (cp)[0] = 0; (cp) += (n); case 0:  ;			\
+    case 15:(cp)[14] = 0; /*-fallthrough*/ \
+    case 14:(cp)[13] = 0; /*-fallthrough*/ \
+    case 13:(cp)[12] = 0; /*-fallthrough*/ \
+    case 12:(cp)[11] = 0; /*-fallthrough*/ \
+    case 11:(cp)[10] = 0; /*-fallthrough*/ \
+    case 10: (cp)[9] = 0; /*-fallthrough*/ \
+    case  9: (cp)[8] = 0; /*-fallthrough*/ \
+    case  8: (cp)[7] = 0; /*-fallthrough*/ \
+    case  7: (cp)[6] = 0; /*-fallthrough*/ \
+    case  6: (cp)[5] = 0; /*-fallthrough*/ \
+    case  5: (cp)[4] = 0; /*-fallthrough*/ \
+    case  4: (cp)[3] = 0; /*-fallthrough*/ \
+    case  3: (cp)[2] = 0; /*-fallthrough*/ \
+    case  2: (cp)[1] = 0; /*-fallthrough*/ \
+    case  1: (cp)[0] = 0; (cp) += (n); /*-fallthrough*/ \
+    case 0:  ;			\
     }
 #else
 # define FILL(n, cp)							    \
     switch (n) {							    \
-    case 7: (cp)[6] = 0xff; case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; \
-    case 4: (cp)[3] = 0xff; case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \
-    case 1: (cp)[0] = 0xff; (cp) += (n); case 0:  ;			    \
+    case 7: (cp)[6] = 0xff; /*-fallthrough*/ \
+    case 6: (cp)[5] = 0xff; /*-fallthrough*/ \
+    case 5: (cp)[4] = 0xff; /*-fallthrough*/ \
+    case 4: (cp)[3] = 0xff; /*-fallthrough*/ \
+    case 3: (cp)[2] = 0xff; /*-fallthrough*/ \
+    case 2: (cp)[1] = 0xff; /*-fallthrough*/ \
+    case 1: (cp)[0] = 0xff; (cp) += (n);  /*-fallthrough*/ \
+    case 0:  ;			    \
     }
 # define ZERO(n, cp)							\
     switch (n) {							\
-    case 7: (cp)[6] = 0; case 6: (cp)[5] = 0; case 5: (cp)[4] = 0;	\
-    case 4: (cp)[3] = 0; case 3: (cp)[2] = 0; case 2: (cp)[1] = 0;	\
-    case 1: (cp)[0] = 0; (cp) += (n); case 0:  ;			\
+    case 7: (cp)[6] = 0; /*-fallthrough*/ \
+    case 6: (cp)[5] = 0; /*-fallthrough*/ \
+    case 5: (cp)[4] = 0; /*-fallthrough*/ \
+    case 4: (cp)[3] = 0; /*-fallthrough*/ \
+    case 3: (cp)[2] = 0; /*-fallthrough*/ \
+    case 2: (cp)[1] = 0; /*-fallthrough*/ \
+    case 1: (cp)[0] = 0; (cp) += (n); /*-fallthrough*/ \
+    case 0:  ;			\
     }
 #endif
 
@@ -644,7 +674,8 @@ putspan(TIFF* tif, int32 span, const tableentry* tab)
 
 	while (span >= 2624) {
 		const tableentry* te = &tab[63 + (2560>>6)];
-		code = te->code, length = te->length;
+		code = te->code;
+		length = te->length;
 #ifdef FAX3_DEBUG
 		DEBUG_PRINT("MakeUp", te->runlen);
 #endif
@@ -654,14 +685,16 @@ putspan(TIFF* tif, int32 span, const tableentry* tab)
 	if (span >= 64) {
 		const tableentry* te = &tab[63 + (span>>6)];
 		assert(te->runlen == 64*(span>>6));
-		code = te->code, length = te->length;
+		code = te->code;
+		length = te->length;
 #ifdef FAX3_DEBUG
 		DEBUG_PRINT("MakeUp", te->runlen);
 #endif
 		_PutBits(tif, code, length);
 		span -= te->runlen;
 	}
-	code = tab[span].code, length = tab[span].length;
+	code = tab[span].code;
+	length = tab[span].length;
 #ifdef FAX3_DEBUG
 	DEBUG_PRINT("  Term", tab[span].runlen);
 #endif
@@ -701,9 +734,12 @@ Fax3PutEOL(TIFF* tif)
 			_PutBits(tif, 0, tparm);
 		}
 	}
-	code = EOL, length = 12;
-	if (is2DEncoding(sp))
-		code = (code<<1) | (sp->tag == G3_1D), length++;
+	code = EOL;
+	length = 12;
+	if (is2DEncoding(sp)) {
+		code = (code<<1) | (sp->tag == G3_1D);
+		length++;
+	}
 	_PutBits(tif, code, length);
 
 	sp->data = data;
@@ -834,12 +870,14 @@ find0span(unsigned char* bp, int32 bs, int32 be)
 		while (!isAligned(bp, long)) {
 			if (*bp != 0x00)
 				return (span + zeroruns[*bp]);
-			span += 8, bits -= 8;
+			span += 8;
+			bits -= 8;
 			bp++;
 		}
 		lp = (long*) bp;
 		while ((bits >= (int32)(8 * sizeof(long))) && (0 == *lp)) {
-			span += 8*sizeof (long), bits -= 8*sizeof (long);
+			span += 8*sizeof (long);
+			bits -= 8*sizeof (long);
 			lp++;
 		}
 		bp = (unsigned char*) lp;
@@ -850,7 +888,8 @@ find0span(unsigned char* bp, int32 bs, int32 be)
 	while (bits >= 8) {
 		if (*bp != 0x00)	/* end of run */
 			return (span + zeroruns[*bp]);
-		span += 8, bits -= 8;
+		span += 8;
+		bits -= 8;
 		bp++;
 	}
 	/*
@@ -893,12 +932,14 @@ find1span(unsigned char* bp, int32 bs, int32 be)
 		while (!isAligned(bp, long)) {
 			if (*bp != 0xff)
 				return (span + oneruns[*bp]);
-			span += 8, bits -= 8;
+			span += 8;
+			bits -= 8;
 			bp++;
 		}
 		lp = (long*) bp;
 		while ((bits >= (int32)(8 * sizeof(long))) && (~0 == *lp)) {
-			span += 8*sizeof (long), bits -= 8*sizeof (long);
+			span += 8*sizeof (long);
+			bits -= 8*sizeof (long);
 			lp++;
 		}
 		bp = (unsigned char*) lp;
@@ -909,7 +950,8 @@ find1span(unsigned char* bp, int32 bs, int32 be)
 	while (bits >= 8) {
 		if (*bp != 0xff)	/* end of run */
 			return (span + oneruns[*bp]);
-		span += 8, bits -= 8;
+		span += 8;
+		bits -= 8;
 		bp++;
 	}
 	/*
@@ -1093,8 +1135,10 @@ Fax3Close(TIFF* tif)
 		unsigned int length = 12;
 		int i;
 
-		if (is2DEncoding(sp))
-			code = (code<<1) | (sp->tag == G3_1D), length++;
+		if (is2DEncoding(sp)) {
+			code = (code<<1) | (sp->tag == G3_1D);
+			length++;
+		}
 		for (i = 0; i < 6; i++)
 			Fax3PutBits(tif, code, length);
 		Fax3FlushBits(tif, sp);
@@ -1240,10 +1284,14 @@ Fax3PrintDir(TIFF* tif, FILE* fd, long flags)
 		} else {
 
 			fprintf(fd, "  Group 3 Options:");
-			if (sp->groupoptions & GROUP3OPT_2DENCODING)
-				fprintf(fd, "%s2-d encoding", sep), sep = "+";
-			if (sp->groupoptions & GROUP3OPT_FILLBITS)
-				fprintf(fd, "%sEOL padding", sep), sep = "+";
+			if (sp->groupoptions & GROUP3OPT_2DENCODING) {
+				fprintf(fd, "%s2-d encoding", sep);
+				sep = "+";
+			}
+			if (sp->groupoptions & GROUP3OPT_FILLBITS) {
+				fprintf(fd, "%sEOL padding", sep);
+				sep = "+";
+			}
 			if (sp->groupoptions & GROUP3OPT_UNCOMPRESSED)
 				fprintf(fd, "%suncompressed data", sep);
 		}
diff --git a/frmts/gtiff/libtiff/tif_fax3.h b/frmts/gtiff/libtiff/tif_fax3.h
index e0b2ca6..8a43505 100644
--- a/frmts/gtiff/libtiff/tif_fax3.h
+++ b/frmts/gtiff/libtiff/tif_fax3.h
@@ -1,4 +1,4 @@
-/* $Id: tif_fax3.h,v 1.11 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_fax3.h,v 1.13 2016-12-14 18:36:27 faxguy Exp $ */
 
 /*
  * Copyright (c) 1990-1997 Sam Leffler
@@ -81,10 +81,12 @@ extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32);
 #define S_MakeUp   11
 #define S_EOL      12
 
+/* WARNING: do not change the layout of this structure as the HylaFAX software */
+/* really depends on it. See http://bugzilla.maptools.org/show_bug.cgi?id=2636 */
 typedef struct {                /* state table entry */
 	unsigned char State;    /* see above */
 	unsigned char Width;    /* width of code in bits */
-	uint16 Param;           /* unsigned 16-bit run length in bits */
+	uint32 Param;           /* unsigned 32-bit run length in bits (holds on 16 bit actually, but cannot be changed. See above warning) */
 } TIFFFaxTabEnt;
 
 extern const TIFFFaxTabEnt TIFFFaxMainTable[];
diff --git a/frmts/gtiff/libtiff/tif_getimage.c b/frmts/gtiff/libtiff/tif_getimage.c
index c55dc22..58d7fc4 100644
--- a/frmts/gtiff/libtiff/tif_getimage.c
+++ b/frmts/gtiff/libtiff/tif_getimage.c
@@ -1,4 +1,4 @@
-/* $Id: tif_getimage.c,v 1.95 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_getimage.c,v 1.103 2017-02-25 17:05:12 erouault Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
@@ -95,6 +95,10 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
 			    td->td_bitspersample);
 			return (0);
 	}
+        if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP) {
+                sprintf(emsg, "Sorry, can not handle images with IEEE floating-point samples");
+                return (0);
+        }
 	colorchannels = td->td_samplesperpixel - td->td_extrasamples;
 	if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
 		switch (colorchannels) {
@@ -182,27 +186,25 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
 				    "Planarconfiguration", td->td_planarconfig);
 				return (0);
 			}
-			if( td->td_samplesperpixel != 3 || colorchannels != 3 )
-            {
-                sprintf(emsg,
-                        "Sorry, can not handle image with %s=%d, %s=%d",
-                        "Samples/pixel", td->td_samplesperpixel,
-                        "colorchannels", colorchannels);
-                return 0;
-            }
+			if ( td->td_samplesperpixel != 3 || colorchannels != 3 ) {
+                                sprintf(emsg,
+                                        "Sorry, can not handle image with %s=%d, %s=%d",
+                                        "Samples/pixel", td->td_samplesperpixel,
+                                        "colorchannels", colorchannels);
+                                return 0;
+                        }
 			break;
 		case PHOTOMETRIC_CIELAB:
-            if( td->td_samplesperpixel != 3 || colorchannels != 3 || td->td_bitspersample != 8 )
-            {
-                sprintf(emsg,
-                        "Sorry, can not handle image with %s=%d, %s=%d and %s=%d",
-                        "Samples/pixel", td->td_samplesperpixel,
-                        "colorchannels", colorchannels,
-                        "Bits/sample", td->td_bitspersample);
-                return 0;
-            }
+                        if ( td->td_samplesperpixel != 3 || colorchannels != 3 || td->td_bitspersample != 8 ) {
+                                sprintf(emsg,
+                                        "Sorry, can not handle image with %s=%d, %s=%d and %s=%d",
+                                        "Samples/pixel", td->td_samplesperpixel,
+                                        "colorchannels", colorchannels,
+                                        "Bits/sample", td->td_bitspersample);
+                                return 0;
+                        }
 			break;
-		default:
+                default:
 			sprintf(emsg, "Sorry, can not handle image with %s=%d",
 			    photoTag, photometric);
 			return (0);
@@ -213,20 +215,34 @@ TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
 void
 TIFFRGBAImageEnd(TIFFRGBAImage* img)
 {
-	if (img->Map)
-		_TIFFfree(img->Map), img->Map = NULL;
-	if (img->BWmap)
-		_TIFFfree(img->BWmap), img->BWmap = NULL;
-	if (img->PALmap)
-		_TIFFfree(img->PALmap), img->PALmap = NULL;
-	if (img->ycbcr)
-		_TIFFfree(img->ycbcr), img->ycbcr = NULL;
-	if (img->cielab)
-		_TIFFfree(img->cielab), img->cielab = NULL;
-	if (img->UaToAa)
-		_TIFFfree(img->UaToAa), img->UaToAa = NULL;
-	if (img->Bitdepth16To8)
-		_TIFFfree(img->Bitdepth16To8), img->Bitdepth16To8 = NULL;
+	if (img->Map) {
+		_TIFFfree(img->Map);
+		img->Map = NULL;
+	}
+	if (img->BWmap) {
+		_TIFFfree(img->BWmap);
+		img->BWmap = NULL;
+	}
+	if (img->PALmap) {
+		_TIFFfree(img->PALmap);
+		img->PALmap = NULL;
+	}
+	if (img->ycbcr) {
+		_TIFFfree(img->ycbcr);
+		img->ycbcr = NULL;
+	}
+	if (img->cielab) {
+		_TIFFfree(img->cielab);
+		img->cielab = NULL;
+	}
+	if (img->UaToAa) {
+		_TIFFfree(img->UaToAa);
+		img->UaToAa = NULL;
+	}
+	if (img->Bitdepth16To8) {
+		_TIFFfree(img->Bitdepth16To8);
+		img->Bitdepth16To8 = NULL;
+	}
 
 	if( img->redcmap ) {
 		_TIFFfree( img->redcmap );
@@ -267,6 +283,13 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 	img->redcmap = NULL;
 	img->greencmap = NULL;
 	img->bluecmap = NULL;
+	img->Map = NULL;
+	img->BWmap = NULL;
+	img->PALmap = NULL;
+	img->ycbcr = NULL;
+	img->cielab = NULL;
+	img->UaToAa = NULL;
+	img->Bitdepth16To8 = NULL;
 	img->req_orientation = ORIENTATION_BOTLEFT;     /* It is the default */
 
 	img->tif = tif;
@@ -452,13 +475,6 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 			    photoTag, img->photometric);
                         goto fail_return;
 	}
-	img->Map = NULL;
-	img->BWmap = NULL;
-	img->PALmap = NULL;
-	img->ycbcr = NULL;
-	img->cielab = NULL;
-	img->UaToAa = NULL;
-	img->Bitdepth16To8 = NULL;
 	TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
 	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
 	TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
@@ -478,10 +494,7 @@ TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
 	return 1;
 
   fail_return:
-        _TIFFfree( img->redcmap );
-        _TIFFfree( img->greencmap );
-        _TIFFfree( img->bluecmap );
-        img->redcmap = img->greencmap = img->bluecmap = NULL;
+        TIFFRGBAImageEnd( img );
         return 0;
 }
 
@@ -686,7 +699,7 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 	    this_toskew = toskew;
 	}
 
-        y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
+        y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow);
     }
     _TIFFfree(buf);
 
@@ -701,7 +714,8 @@ gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 			    uint32 temp = *left;
 			    *left = *right;
 			    *right = temp;
-			    left++, right--;
+			    left++;
+				right--;
 		    }
 	    }
     }
@@ -854,7 +868,7 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 			this_toskew = toskew;
 		}
 
-		y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow);
+		y += ((flip & FLIP_VERTICALLY) ?-(int32) nrow : (int32) nrow);
 	}
 
 	if (flip & FLIP_HORIZONTALLY) {
@@ -868,7 +882,8 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 				uint32 temp = *left;
 				*left = *right;
 				*right = temp;
-				left++, right--;
+				left++;
+				right--;
 			}
 		}
 	}
@@ -944,7 +959,7 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 		pos = ((row + img->row_offset) % rowsperstrip) * scanline + \
 			((tmsize_t) img->col_offset * img->samplesperpixel);
 		(*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos);
-		y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
+		y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow);
 	}
 
 	if (flip & FLIP_HORIZONTALLY) {
@@ -958,7 +973,8 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 				uint32 temp = *left;
 				*left = *right;
 				*right = temp;
-				left++, right--;
+				left++;
+				right--;
 			}
 		}
 	}
@@ -1078,7 +1094,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 			((tmsize_t) img->col_offset * img->samplesperpixel);
 		(*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos,
 		    p2 + pos, (alpha?(pa+pos):NULL));
-		y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
+		y += ((flip & FLIP_VERTICALLY) ? -(int32) nrow : (int32) nrow);
 	}
 
 	if (flip & FLIP_HORIZONTALLY) {
@@ -1092,7 +1108,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 				uint32 temp = *left;
 				*left = *right;
 				*right = temp;
-				left++, right--;
+				left++;
+				right--;
 			}
 		}
 	}
@@ -1116,11 +1133,15 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
 #define	REPEAT2(op)	op; op
 #define	CASE8(x,op)			\
     switch (x) {			\
-    case 7: op; case 6: op; case 5: op;	\
-    case 4: op; case 3: op; case 2: op;	\
+    case 7: op; /*-fallthrough*/ \
+    case 6: op; /*-fallthrough*/ \
+    case 5: op; /*-fallthrough*/ \
+    case 4: op; /*-fallthrough*/ \
+    case 3: op; /*-fallthrough*/ \
+    case 2: op; /*-fallthrough*/ \
     case 1: op;				\
     }
-#define	CASE4(x,op)	switch (x) { case 3: op; case 2: op; case 1: op; }
+#define	CASE4(x,op)	switch (x) { case 3: op; /*-fallthrough*/ case 2: op; /*-fallthrough*/ case 1: op; }
 #define	NOP
 
 #define	UNROLL8(w, op1, op2) {		\
@@ -1285,7 +1306,7 @@ DECLAREContigPutFunc(putagreytile)
     while (h-- > 0) {
 	for (x = w; x-- > 0;)
         {
-            *cp++ = BWmap[*pp][0] & (*(pp+1) << 24 | ~A1);
+            *cp++ = BWmap[*pp][0] & ((uint32)*(pp+1) << 24 | ~A1);
             pp += samplesperpixel;
         }
 	cp += toskew;
@@ -1420,7 +1441,7 @@ DECLAREContigPutFunc(putRGBUAcontig8bittile)
 		uint8* m;
 		for (x = w; x-- > 0;) {
 			a = pp[3];
-			m = img->UaToAa+(a<<8);
+			m = img->UaToAa+((size_t) a<<8);
 			r = m[pp[0]];
 			g = m[pp[1]];
 			b = m[pp[2]];
@@ -1491,7 +1512,7 @@ DECLAREContigPutFunc(putRGBUAcontig16bittile)
 		uint8* m;
 		for (x = w; x-- > 0;) {
 			a = img->Bitdepth16To8[wp[3]];
-			m = img->UaToAa+(a<<8);
+			m = img->UaToAa+((size_t) a<<8);
 			r = m[img->Bitdepth16To8[wp[0]]];
 			g = m[img->Bitdepth16To8[wp[1]]];
 			b = m[img->Bitdepth16To8[wp[2]]];
@@ -1622,7 +1643,7 @@ DECLARESepPutFunc(putRGBUAseparate8bittile)
 		uint8* m;
 		for (x = w; x-- > 0;) {
 			av = *a++;
-			m = img->UaToAa+(av<<8);
+			m = img->UaToAa+((size_t) av<<8);
 			rv = m[*r++];
 			gv = m[*g++];
 			bv = m[*b++];
@@ -1688,7 +1709,7 @@ DECLARESepPutFunc(putRGBUAseparate16bittile)
 		uint8* m;
 		for (x = w; x-- > 0;) {
 			a2 = img->Bitdepth16To8[*wa++];
-			m = img->UaToAa+(a2<<8);
+			m = img->UaToAa+((size_t) a2<<8);
 			r2 = m[img->Bitdepth16To8[*wr++]];
 			g2 = m[img->Bitdepth16To8[*wg++]];
 			b2 = m[img->Bitdepth16To8[*wb++]];
@@ -1847,10 +1868,16 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
                 YCbCrtoRGB(cp3[2], pp[14]);
                 YCbCrtoRGB(cp3[3], pp[15]);
 
-                cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
+                cp += 4;
+                cp1 += 4;
+                cp2 += 4;
+                cp3 += 4;
                 pp += 18;
             } while (--x);
-            cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
+            cp += incr;
+            cp1 += incr;
+            cp2 += incr;
+            cp3 += incr;
             pp += fromskew;
         }
     } else {
@@ -1901,7 +1928,10 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
             if (h <= 4)
                 break;
             h -= 4;
-            cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
+            cp += incr;
+            cp1 += incr;
+            cp2 += incr;
+            cp3 += incr;
             pp += fromskew;
         }
     }
@@ -1933,10 +1963,12 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
                 YCbCrtoRGB(cp1[2], pp[6]);
                 YCbCrtoRGB(cp1[3], pp[7]);
                 
-                cp += 4, cp1 += 4;
+                cp += 4;
+                cp1 += 4;
                 pp += 10;
             } while (--x);
-            cp += incr, cp1 += incr;
+            cp += incr;
+            cp1 += incr;
             pp += fromskew;
         }
     } else {
@@ -1979,7 +2011,8 @@ DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
             if (h <= 2)
                 break;
             h -= 2;
-            cp += incr, cp1 += incr;
+            cp += incr;
+            cp1 += incr;
             pp += fromskew;
         }
     }
@@ -2014,9 +2047,9 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
 	    int32 Cr = pp[5];
 
             switch( (w&3) ) {
-              case 3: YCbCrtoRGB(cp [2], pp[2]);
-              case 2: YCbCrtoRGB(cp [1], pp[1]);
-              case 1: YCbCrtoRGB(cp [0], pp[0]);
+              case 3: YCbCrtoRGB(cp [2], pp[2]); /*-fallthrough*/
+              case 2: YCbCrtoRGB(cp [1], pp[1]); /*-fallthrough*/
+              case 1: YCbCrtoRGB(cp [0], pp[0]); /*-fallthrough*/
               case 0: break;
             }
 
@@ -2368,7 +2401,8 @@ setupMap(TIFFRGBAImage* img)
 	if (!makebwmap(img))
 	    return (0);
 	/* no longer need Map, free it */
-	_TIFFfree(img->Map), img->Map = NULL;
+	_TIFFfree(img->Map);
+	img->Map = NULL;
     }
     return (1);
 }
@@ -2783,6 +2817,13 @@ int
 TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster )
 
 {
+    return TIFFReadRGBAStripExt(tif, row, raster, 0 );
+}
+
+int
+TIFFReadRGBAStripExt(TIFF* tif, uint32 row, uint32 * raster, int stop_on_error)
+
+{
     char 	emsg[1024] = "";
     TIFFRGBAImage img;
     int 	ok;
@@ -2803,7 +2844,7 @@ TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster )
 		return (0);
     }
 
-    if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
+    if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg)) {
 
         img.row_offset = row;
         img.col_offset = 0;
@@ -2834,6 +2875,13 @@ int
 TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster)
 
 {
+    return TIFFReadRGBATileExt(tif, col, row, raster, 0 );
+}
+
+
+int
+TIFFReadRGBATileExt(TIFF* tif, uint32 col, uint32 row, uint32 * raster, int stop_on_error )
+{
     char 	emsg[1024] = "";
     TIFFRGBAImage img;
     int 	ok;
@@ -2868,7 +2916,7 @@ TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster)
      */
     
     if (!TIFFRGBAImageOK(tif, emsg) 
-	|| !TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
+	|| !TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg)) {
 	    TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "%s", emsg);
 	    return( 0 );
     }
diff --git a/frmts/gtiff/libtiff/tif_jpeg.c b/frmts/gtiff/libtiff/tif_jpeg.c
index 70b72d8..1553e86 100644
--- a/frmts/gtiff/libtiff/tif_jpeg.c
+++ b/frmts/gtiff/libtiff/tif_jpeg.c
@@ -1,4 +1,4 @@
-/* $Id: tif_jpeg.c,v 1.123 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_jpeg.c,v 1.127 2017-01-31 13:02:27 erouault Exp $ */
 
 /*
  * Copyright (c) 1994-1997 Sam Leffler
@@ -697,9 +697,11 @@ static int
 JPEGFixupTags(TIFF* tif)
 {
 #ifdef CHECK_JPEG_YCBCR_SUBSAMPLING
+        JPEGState* sp = JState(tif);
 	if ((tif->tif_dir.td_photometric==PHOTOMETRIC_YCBCR)&&
 	    (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)&&
-	    (tif->tif_dir.td_samplesperpixel==3))
+	    (tif->tif_dir.td_samplesperpixel==3) &&
+            !sp->ycbcrsampling_fetched)
 		JPEGFixupTagsSubsampling(tif);
 #endif
         
@@ -1626,6 +1628,20 @@ JPEGSetupEncode(TIFF* tif)
 	case PHOTOMETRIC_YCBCR:
 		sp->h_sampling = td->td_ycbcrsubsampling[0];
 		sp->v_sampling = td->td_ycbcrsubsampling[1];
+                if( sp->h_sampling == 0 || sp->v_sampling == 0 )
+                {
+                    TIFFErrorExt(tif->tif_clientdata, module,
+                            "Invalig horizontal/vertical sampling value");
+                    return (0);
+                }
+                if( td->td_bitspersample > 16 )
+                {
+                    TIFFErrorExt(tif->tif_clientdata, module,
+                                 "BitsPerSample %d not allowed for JPEG",
+                                 td->td_bitspersample);
+                    return (0);
+                }
+
 		/*
 		 * A ReferenceBlackWhite field *must* be present since the
 		 * default value is inappropriate for YCbCr.  Fill in the
@@ -2291,6 +2307,15 @@ static int JPEGInitializeLibJPEG( TIFF * tif, int decompress )
     } else {
         if (!TIFFjpeg_create_compress(sp))
             return (0);
+#ifndef TIFF_JPEG_MAX_MEMORY_TO_USE
+#define TIFF_JPEG_MAX_MEMORY_TO_USE (10 * 1024 * 1024)
+#endif
+        /* Increase the max memory usable. This helps when creating files */
+        /* with "big" tile, without using libjpeg temporary files. */
+        /* For example a 512x512 tile with 3 bands */
+        /* requires 1.5 MB which is above libjpeg 1MB default */
+        if( sp->cinfo.c.mem->max_memory_to_use < TIFF_JPEG_MAX_MEMORY_TO_USE )
+            sp->cinfo.c.mem->max_memory_to_use = TIFF_JPEG_MAX_MEMORY_TO_USE;
     }
 
     sp->cinfo_initialized = TRUE;
diff --git a/frmts/gtiff/libtiff/tif_luv.c b/frmts/gtiff/libtiff/tif_luv.c
index 60a174d..1f6d8ba 100644
--- a/frmts/gtiff/libtiff/tif_luv.c
+++ b/frmts/gtiff/libtiff/tif_luv.c
@@ -1,4 +1,4 @@
-/* $Id: tif_luv.c,v 1.41 2015-12-27 16:25:11 erouault Exp $ */
+/* $Id: tif_luv.c,v 1.45 2017-01-11 20:33:35 erouault Exp $ */
 
 /*
  * Copyright (c) 1997 Greg Ward Larson
@@ -158,6 +158,7 @@
 typedef struct logLuvState LogLuvState;
 
 struct logLuvState {
+        int                     encoder_state;  /* 1 if encoder correctly initialized */
 	int                     user_datafmt;   /* user data format */
 	int                     encode_meth;    /* encoding method */
 	int                     pixel_size;     /* bytes per pixel */
@@ -401,8 +402,10 @@ LogLuvDecodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
                 return 0;
 
 	assert(cc%rowlen == 0);
-	while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
-		bp += rowlen, cc -= rowlen;
+	while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) {
+		bp += rowlen;
+		cc -= rowlen;
+	}
 	return (cc == 0);
 }
 
@@ -420,8 +423,10 @@ LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
                 return 0;
 
 	assert(cc%rowlen == 0);
-	while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
-		bp += rowlen, cc -= rowlen;
+	while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) {
+		bp += rowlen;
+		cc -= rowlen;
+	}
 	return (cc == 0);
 }
 
@@ -468,7 +473,7 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 				tif->tif_rawcp = op;
 				tif->tif_rawcc = tif->tif_rawdatasize - occ;
 				if (!TIFFFlushData1(tif))
-					return (-1);
+					return (0);
 				op = tif->tif_rawcp;
 				occ = tif->tif_rawdatasize - tif->tif_rawcc;
 			}
@@ -500,7 +505,7 @@ LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 					tif->tif_rawcp = op;
 					tif->tif_rawcc = tif->tif_rawdatasize - occ;
 					if (!TIFFFlushData1(tif))
-						return (-1);
+						return (0);
 					op = tif->tif_rawcp;
 					occ = tif->tif_rawdatasize - tif->tif_rawcc;
 				}
@@ -560,7 +565,7 @@ LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 			tif->tif_rawcp = op;
 			tif->tif_rawcc = tif->tif_rawdatasize - occ;
 			if (!TIFFFlushData1(tif))
-				return (-1);
+				return (0);
 			op = tif->tif_rawcp;
 			occ = tif->tif_rawdatasize - tif->tif_rawcc;
 		}
@@ -619,7 +624,7 @@ LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 				tif->tif_rawcp = op;
 				tif->tif_rawcc = tif->tif_rawdatasize - occ;
 				if (!TIFFFlushData1(tif))
-					return (-1);
+					return (0);
 				op = tif->tif_rawcp;
 				occ = tif->tif_rawdatasize - tif->tif_rawcc;
 			}
@@ -651,7 +656,7 @@ LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 					tif->tif_rawcp = op;
 					tif->tif_rawcc = tif->tif_rawdatasize - occ;
 					if (!TIFFFlushData1(tif))
-						return (-1);
+						return (0);
 					op = tif->tif_rawcp;
 					occ = tif->tif_rawdatasize - tif->tif_rawcc;
 				}
@@ -687,8 +692,10 @@ LogLuvEncodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
                 return 0;
 
 	assert(cc%rowlen == 0);
-	while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
-		bp += rowlen, cc -= rowlen;
+	while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) {
+		bp += rowlen;
+		cc -= rowlen;
+	}
 	return (cc == 0);
 }
 
@@ -705,8 +712,10 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
                 return 0;
 
 	assert(cc%rowlen == 0);
-	while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
-		bp += rowlen, cc -= rowlen;
+	while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1) {
+		bp += rowlen;
+		cc -= rowlen;
+	}
 	return (cc == 0);
 }
 
@@ -1276,6 +1285,14 @@ LogL16InitState(TIFF* tif)
 	assert(sp != NULL);
 	assert(td->td_photometric == PHOTOMETRIC_LOGL);
 
+	if( td->td_samplesperpixel != 1 )
+	{
+		TIFFErrorExt(tif->tif_clientdata, module,
+		             "Sorry, can not handle LogL image with %s=%d",
+			     "Samples/pixel", td->td_samplesperpixel);
+		return 0;
+	}
+
 	/* for some reason, we can't do this in TIFFInitLogL16 */
 	if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
 		sp->user_datafmt = LogL16GuessDataFmt(td);
@@ -1536,6 +1553,7 @@ LogLuvSetupEncode(TIFF* tif)
 		    td->td_photometric, "must be either LogLUV or LogL");
 		break;
 	}
+	sp->encoder_state = 1;
 	return (1);
 notsupported:
 	TIFFErrorExt(tif->tif_clientdata, module,
@@ -1547,19 +1565,27 @@ notsupported:
 static void
 LogLuvClose(TIFF* tif)
 {
+        LogLuvState* sp = (LogLuvState*) tif->tif_data;
 	TIFFDirectory *td = &tif->tif_dir;
 
+	assert(sp != 0);
 	/*
 	 * For consistency, we always want to write out the same
 	 * bitspersample and sampleformat for our TIFF file,
 	 * regardless of the data format being used by the application.
 	 * Since this routine is called after tags have been set but
 	 * before they have been recorded in the file, we reset them here.
+         * Note: this is really a nasty approach. See PixarLogClose
 	 */
-	td->td_samplesperpixel =
-	    (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
-	td->td_bitspersample = 16;
-	td->td_sampleformat = SAMPLEFORMAT_INT;
+        if( sp->encoder_state )
+        {
+            /* See PixarLogClose. Might avoid issues with tags whose size depends
+             * on those below, but not completely sure this is enough. */
+            td->td_samplesperpixel =
+                (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
+            td->td_bitspersample = 16;
+            td->td_sampleformat = SAMPLEFORMAT_INT;
+        }
 }
 
 static void
@@ -1598,17 +1624,21 @@ LogLuvVSetField(TIFF* tif, uint32 tag, va_list ap)
 		 */
 		switch (sp->user_datafmt) {
 		case SGILOGDATAFMT_FLOAT:
-			bps = 32, fmt = SAMPLEFORMAT_IEEEFP;
+			bps = 32;
+			fmt = SAMPLEFORMAT_IEEEFP;
 			break;
 		case SGILOGDATAFMT_16BIT:
-			bps = 16, fmt = SAMPLEFORMAT_INT;
+			bps = 16;
+			fmt = SAMPLEFORMAT_INT;
 			break;
 		case SGILOGDATAFMT_RAW:
-			bps = 32, fmt = SAMPLEFORMAT_UINT;
+			bps = 32;
+			fmt = SAMPLEFORMAT_UINT;
 			TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
 			break;
 		case SGILOGDATAFMT_8BIT:
-			bps = 8, fmt = SAMPLEFORMAT_UINT;
+			bps = 8;
+			fmt = SAMPLEFORMAT_UINT;
 			break;
 		default:
 			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
diff --git a/frmts/gtiff/libtiff/tif_lzma.c b/frmts/gtiff/libtiff/tif_lzma.c
index 0a9ad31..80fc394 100644
--- a/frmts/gtiff/libtiff/tif_lzma.c
+++ b/frmts/gtiff/libtiff/tif_lzma.c
@@ -1,4 +1,4 @@
-/* $Id: tif_lzma.c,v 1.5 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_lzma.c,v 1.6 2016-09-17 09:18:59 erouault Exp $ */
 
 /*
  * Copyright (c) 2010, Andrey Kiselev <dron at ak4719.spb.edu>
diff --git a/frmts/gtiff/libtiff/tif_lzw.c b/frmts/gtiff/libtiff/tif_lzw.c
index b2282b3..7edd13c 100644
--- a/frmts/gtiff/libtiff/tif_lzw.c
+++ b/frmts/gtiff/libtiff/tif_lzw.c
@@ -1,4 +1,4 @@
-/* $Id: tif_lzw.c,v 1.51 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_lzw.c,v 1.54 2017-02-18 18:46:00 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -411,7 +411,8 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 		/*
 		 * Residue satisfies only part of the decode request.
 		 */
-		op += residue, occ -= residue;
+		op += residue;
+		occ -= residue;
 		tp = op;
 		do {
 			int t;
@@ -454,7 +455,8 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 					     tif->tif_row);
 				return (0);
 			}
-			*op++ = (char)code, occ--;
+			*op++ = (char)code;
+			occ--;
 			oldcodep = sp->dec_codetab + code;
 			continue;
 		}
@@ -539,9 +541,12 @@ LZWDecode(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 			    break;
 			}
 			assert(occ >= len);
-			op += len, occ -= len;
-		} else
-			*op++ = (char)code, occ--;
+			op += len;
+			occ -= len;
+		} else {
+			*op++ = (char)code;
+			occ--;
+		}
 	}
 
 	tif->tif_rawcp = (uint8*) bp;
@@ -635,7 +640,8 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 		/*
 		 * Residue satisfies only part of the decode request.
 		 */
-		op += residue, occ -= residue;
+		op += residue;
+		occ -= residue;
 		tp = op;
 		do {
 			*--tp = codep->value;
@@ -675,7 +681,8 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 					     tif->tif_row);
 				return (0);
 			}
-			*op++ = (char)code, occ--;
+			*op++ = (char)code;
+			occ--;
 			oldcodep = sp->dec_codetab + code;
 			continue;
 		}
@@ -741,13 +748,16 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 				break;
 			}
 			assert(occ >= codep->length);
-			op += codep->length, occ -= codep->length;
+			op += codep->length;
+			occ -= codep->length;
 			tp = op;
 			do {
 				*--tp = codep->value;
 			} while( (codep = codep->next) != NULL );
-		} else
-			*op++ = (char)code, occ--;
+		} else {
+			*op++ = (char)code;
+			occ--;
+		}
 	}
 
 	tif->tif_rawcp = (uint8*) bp;
@@ -959,7 +969,8 @@ LZWEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 		 */
 		if (op > limit) {
 			tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata);
-			TIFFFlushData1(tif);
+			if( !TIFFFlushData1(tif) )
+                            return 0;
 			op = tif->tif_rawdata;
 		}
 		PutNextCode(op, ent);
@@ -1044,12 +1055,32 @@ LZWPostEncode(TIFF* tif)
 
 	if (op > sp->enc_rawlimit) {
 		tif->tif_rawcc = (tmsize_t)(op - tif->tif_rawdata);
-		TIFFFlushData1(tif);
+		if( !TIFFFlushData1(tif) )
+                    return 0;
 		op = tif->tif_rawdata;
 	}
 	if (sp->enc_oldcode != (hcode_t) -1) {
+                int free_ent = sp->lzw_free_ent;
+
 		PutNextCode(op, sp->enc_oldcode);
 		sp->enc_oldcode = (hcode_t) -1;
+                free_ent ++;
+
+                if (free_ent == CODE_MAX-1) {
+                        /* table is full, emit clear code and reset */
+                        outcount = 0;
+                        PutNextCode(op, CODE_CLEAR);
+                        nbits = BITS_MIN;
+                } else {
+                        /*
+                        * If the next entry is going to be too big for
+                        * the code size, then increase it, if possible.
+                        */
+                        if (free_ent > sp->lzw_maxcode) {
+                                nbits++;
+                                assert(nbits <= BITS_MAX);
+                        }
+                }
 	}
 	PutNextCode(op, CODE_EOI);
         /* Explicit 0xff masking to make icc -check=conversions happy */
diff --git a/frmts/gtiff/libtiff/tif_next.c b/frmts/gtiff/libtiff/tif_next.c
index 1a0cd0d..0821178 100644
--- a/frmts/gtiff/libtiff/tif_next.c
+++ b/frmts/gtiff/libtiff/tif_next.c
@@ -1,4 +1,4 @@
-/* $Id: tif_next.c,v 1.18 2015-12-27 17:14:52 erouault Exp $ */
+/* $Id: tif_next.c,v 1.19 2016-09-04 21:32:56 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -72,7 +72,8 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
 		return (0);
 	}
 	for (row = buf; cc > 0 && occ > 0; occ -= scanline, row += scanline) {
-		n = *bp++, cc--;
+		n = *bp++;
+		cc--;
 		switch (n) {
 		case LITERALROW:
 			/*
@@ -134,7 +135,8 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s)
                 }
 				if (cc == 0)
 					goto bad;
-				n = *bp++, cc--;
+				n = *bp++;
+				cc--;
 			}
 			break;
 		}
diff --git a/frmts/gtiff/libtiff/tif_ojpeg.c b/frmts/gtiff/libtiff/tif_ojpeg.c
index b0efcf5..bd4cff5 100644
--- a/frmts/gtiff/libtiff/tif_ojpeg.c
+++ b/frmts/gtiff/libtiff/tif_ojpeg.c
@@ -1,4 +1,4 @@
-/* $Id: tif_ojpeg.c,v 1.64 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_ojpeg.c,v 1.68 2017-01-12 19:23:20 erouault Exp $ */
 
 /* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0
    specification is now totally obsolete and deprecated for new applications and
@@ -244,6 +244,7 @@ typedef enum {
 
 typedef struct {
 	TIFF* tif;
+        int decoder_ok;
 	#ifndef LIBJPEG_ENCAP_EXTERNAL
 	JMP_BUF exit_jmpbuf;
 	#endif
@@ -722,6 +723,7 @@ OJPEGPreDecode(TIFF* tif, uint16 s)
 		}
 		sp->write_curstrile++;
 	}
+	sp->decoder_ok = 1;
 	return(1);
 }
 
@@ -784,8 +786,14 @@ OJPEGPreDecodeSkipScanlines(TIFF* tif)
 static int
 OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 {
+        static const char module[]="OJPEGDecode";
 	OJPEGState* sp=(OJPEGState*)tif->tif_data;
 	(void)s;
+        if( !sp->decoder_ok )
+        {
+            TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized");
+            return 0;
+        }
 	if (sp->libjpeg_jpeg_query_style==0)
 	{
 		if (OJPEGDecodeRaw(tif,buf,cc)==0)
@@ -1782,7 +1790,10 @@ OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif)
 			TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET); 
 			p=(uint32)TIFFReadFile(tif,&ob[sizeof(uint32)+5],64);
 			if (p!=64)
+                        {
+                                _TIFFfree(ob);
 				return(0);
+                        }
 			sp->qtable[m]=ob;
 			sp->sof_tq[m]=m;
 		}
@@ -1846,7 +1857,10 @@ OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif)
 				rb[sizeof(uint32)+5+n]=o[n];
 			p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
 			if (p!=q)
+                        {
+                                _TIFFfree(rb);
 				return(0);
+                        }
 			sp->dctable[m]=rb;
 			sp->sos_tda[m]=(m<<4);
 		}
@@ -1910,7 +1924,10 @@ OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif)
 				rb[sizeof(uint32)+5+n]=o[n];
 			p=(uint32)TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
 			if (p!=q)
+                        {
+                                _TIFFfree(rb);
 				return(0);
+                        }
 			sp->actable[m]=rb;
 			sp->sos_tda[m]=(sp->sos_tda[m]|m);
 		}
@@ -2386,7 +2403,12 @@ OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len)
 static int
 jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
 {
-	return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_create_decompress(cinfo),1));
+	if( SETJMP(sp->exit_jmpbuf) )
+		return 0;
+	else {
+		jpeg_create_decompress(cinfo);
+		return 1;
+	}
 }
 #endif
 
@@ -2394,7 +2416,12 @@ jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
 static int
 jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image)
 {
-	return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_header(cinfo,require_image),1));
+	if( SETJMP(sp->exit_jmpbuf) )
+		return 0;
+	else {
+		jpeg_read_header(cinfo,require_image);
+		return 1;
+	}
 }
 #endif
 
@@ -2402,7 +2429,12 @@ jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 requ
 static int
 jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
 {
-	return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_start_decompress(cinfo),1));
+	if( SETJMP(sp->exit_jmpbuf) )
+		return 0;
+	else {
+		jpeg_start_decompress(cinfo);
+		return 1;
+	}
 }
 #endif
 
@@ -2410,7 +2442,12 @@ jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
 static int
 jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines)
 {
-	return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_scanlines(cinfo,scanlines,max_lines),1));
+	if( SETJMP(sp->exit_jmpbuf) )
+		return 0;
+	else {
+		jpeg_read_scanlines(cinfo,scanlines,max_lines);
+		return 1;
+	}
 }
 #endif
 
@@ -2418,7 +2455,12 @@ jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* s
 static int
 jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines)
 {
-	return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_raw_data(cinfo,data,max_lines),1));
+	if( SETJMP(sp->exit_jmpbuf) )
+		return 0;
+	else {
+		jpeg_read_raw_data(cinfo,data,max_lines);
+		return 1;
+	}
 }
 #endif
 
diff --git a/frmts/gtiff/libtiff/tif_open.c b/frmts/gtiff/libtiff/tif_open.c
index 5c9036e..a7279e1 100644
--- a/frmts/gtiff/libtiff/tif_open.c
+++ b/frmts/gtiff/libtiff/tif_open.c
@@ -1,4 +1,4 @@
-/* $Id: tif_open.c,v 1.47 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_open.c,v 1.48 2016-11-20 22:29:47 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -279,10 +279,10 @@ TIFFClientOpen(
 		 * Setup header and write.
 		 */
 		#ifdef WORDS_BIGENDIAN
-		tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB
+		tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB)
 		    ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
 		#else
-		tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB
+		tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB)
 		    ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
 		#endif
 		if (!(tif->tif_flags&TIFF_BIGTIFF))
diff --git a/frmts/gtiff/libtiff/tif_packbits.c b/frmts/gtiff/libtiff/tif_packbits.c
index c79c0aa..0495e68 100644
--- a/frmts/gtiff/libtiff/tif_packbits.c
+++ b/frmts/gtiff/libtiff/tif_packbits.c
@@ -1,4 +1,4 @@
-/* $Id: tif_packbits.c,v 1.23 2015-11-22 15:31:03 erouault Exp $ */
+/* $Id: tif_packbits.c,v 1.25 2017-01-11 20:33:35 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -82,7 +82,9 @@ PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 		/*
 		 * Find the longest string of identical bytes.
 		 */
-		b = *bp++, cc--, n = 1;
+		b = *bp++;
+		cc--;
+		n = 1;
 		for (; cc > 0 && b == *bp; cc--, bp++)
 			n++;
 	again:
@@ -97,7 +99,7 @@ PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 				slop = (long)(op - lastliteral);
 				tif->tif_rawcc += (tmsize_t)(lastliteral - tif->tif_rawcp);
 				if (!TIFFFlushData1(tif))
-					return (-1);
+					return (0);
 				op = tif->tif_rawcp;
 				while (slop-- > 0)
 					*op++ = *lastliteral++;
@@ -105,7 +107,7 @@ PackBitsEncode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
 			} else {
 				tif->tif_rawcc += (tmsize_t)(op - tif->tif_rawcp);
 				if (!TIFFFlushData1(tif))
-					return (-1);
+					return (0);
 				op = tif->tif_rawcp;
 			}
 		}
@@ -223,7 +225,8 @@ PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 	bp = (char*) tif->tif_rawcp;
 	cc = tif->tif_rawcc;
 	while (cc > 0 && occ > 0) {
-		n = (long) *bp++, cc--;
+		n = (long) *bp++;
+		cc--;
 		/*
 		 * Watch out for compilers that
 		 * don't sign extend chars...
@@ -242,7 +245,8 @@ PackBitsDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 				n = (long)occ;
 			}
 			occ -= n;
-			b = *bp++, cc--;
+			b = *bp++;
+			cc--;
 			while (n-- > 0)
 				*op++ = (uint8) b;
 		} else {		/* copy next n+1 bytes literally */
diff --git a/frmts/gtiff/libtiff/tif_pixarlog.c b/frmts/gtiff/libtiff/tif_pixarlog.c
index fe25829..9836dce 100644
--- a/frmts/gtiff/libtiff/tif_pixarlog.c
+++ b/frmts/gtiff/libtiff/tif_pixarlog.c
@@ -1,4 +1,4 @@
-/* $Id: tif_pixarlog.c,v 1.43 2015-12-27 20:14:11 erouault Exp $ */
+/* $Id: tif_pixarlog.c,v 1.49 2016-12-02 23:05:51 erouault Exp $ */
 
 /*
  * Copyright (c) 1996-1997 Sam Leffler
@@ -459,6 +459,7 @@ horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op,
 typedef	struct {
 	TIFFPredictorState	predict;
 	z_stream		stream;
+	tmsize_t		tbuf_size; /* only set/used on reading for now */
 	uint16			*tbuf; 
 	uint16			stride;
 	int			state;
@@ -694,6 +695,7 @@ PixarLogSetupDecode(TIFF* tif)
 	sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size);
 	if (sp->tbuf == NULL)
 		return (0);
+	sp->tbuf_size = tbuf_size;
 	if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
 		sp->user_datafmt = PixarLogGuessDataFmt(td);
 	if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
@@ -783,6 +785,12 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 		TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
 		return (0);
 	}
+	/* Check that we will not fill more than what was allocated */
+	if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size)
+	{
+		TIFFErrorExt(tif->tif_clientdata, module, "sp->stream.avail_out > sp->tbuf_size");
+		return (0);
+	}
 	do {
 		int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
 		if (state == Z_STREAM_END) {
@@ -975,17 +983,14 @@ horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2)
 		a1 = (int32) CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1;
 	    }
 	} else {
-	    ip += n - 1;	/* point to last one */
-	    wp += n - 1;	/* point to last one */
-	    n -= stride;
-	    while (n > 0) {
-		REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]);
-				wp[stride] -= wp[0];
-				wp[stride] &= mask;
-				wp--; ip--)
-		n -= stride;
-	    }
-	    REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--)
+        REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp++; ip++)
+        n -= stride;
+        while (n > 0) {
+            REPEAT(stride,
+                wp[0] = (uint16)(((int32)CLAMP(ip[0])-(int32)CLAMP(ip[-stride])) & mask);
+                wp++; ip++)
+            n -= stride;
+        }
 	}
     }
 }
@@ -1028,17 +1033,14 @@ horizontalDifference16(unsigned short *ip, int n, int stride,
 		a1 = CLAMP(ip[3]); wp[3] = (uint16)((a1-a2) & mask); a2 = a1;
 	    }
 	} else {
-	    ip += n - 1;	/* point to last one */
-	    wp += n - 1;	/* point to last one */
+        REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
 	    n -= stride;
 	    while (n > 0) {
-		REPEAT(stride, wp[0] = CLAMP(ip[0]);
-				wp[stride] -= wp[0];
-				wp[stride] &= mask;
-				wp--; ip--)
-		n -= stride;
-	    }
-	    REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
+            REPEAT(stride,
+                wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask);
+                wp++; ip++)
+            n -= stride;
+        }
 	}
     }
 }
@@ -1081,18 +1083,15 @@ horizontalDifference8(unsigned char *ip, int n, int stride,
 		ip += 4;
 	    }
 	} else {
-	    wp += n + stride - 1;	/* point to last one */
-	    ip += n + stride - 1;	/* point to last one */
-	    n -= stride;
-	    while (n > 0) {
-		REPEAT(stride, wp[0] = CLAMP(ip[0]);
-				wp[stride] -= wp[0];
-				wp[stride] &= mask;
-				wp--; ip--)
-		n -= stride;
-	    }
-	    REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
-	}
+        REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
+        n -= stride;
+        while (n > 0) {
+            REPEAT(stride,
+                wp[0] = (uint16)((CLAMP(ip[0])-CLAMP(ip[-stride])) & mask);
+                wp++; ip++)
+            n -= stride;
+        }
+    }
     }
 }
 
@@ -1133,6 +1132,13 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 	}
 
 	llen = sp->stride * td->td_imagewidth;
+    /* Check against the number of elements (of size uint16) of sp->tbuf */
+    if( n > (tmsize_t)(td->td_rowsperstrip * llen) )
+    {
+        TIFFErrorExt(tif->tif_clientdata, module,
+                     "Too many input bytes provided");
+        return 0;
+    }
 
 	for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) {
 		switch (sp->user_datafmt)  {
@@ -1227,8 +1233,10 @@ PixarLogPostEncode(TIFF* tif)
 static void
 PixarLogClose(TIFF* tif)
 {
+        PixarLogState* sp = (PixarLogState*) tif->tif_data;
 	TIFFDirectory *td = &tif->tif_dir;
 
+	assert(sp != 0);
 	/* In a really sneaky (and really incorrect, and untruthful, and
 	 * troublesome, and error-prone) maneuver that completely goes against
 	 * the spirit of TIFF, and breaks TIFF, on close, we covertly
@@ -1237,8 +1245,19 @@ PixarLogClose(TIFF* tif)
 	 * readers that don't know about PixarLog, or how to set
 	 * the PIXARLOGDATFMT pseudo-tag.
 	 */
-	td->td_bitspersample = 8;
-	td->td_sampleformat = SAMPLEFORMAT_UINT;
+
+        if (sp->state&PLSTATE_INIT) {
+            /* We test the state to avoid an issue such as in
+             * http://bugzilla.maptools.org/show_bug.cgi?id=2604
+             * What appends in that case is that the bitspersample is 1 and
+             * a TransferFunction is set. The size of the TransferFunction
+             * depends on 1<<bitspersample. So if we increase it, an access
+             * out of the buffer will happen at directory flushing.
+             * Another option would be to clear those targs. 
+             */
+            td->td_bitspersample = 8;
+            td->td_sampleformat = SAMPLEFORMAT_UINT;
+        }
 }
 
 static void
diff --git a/frmts/gtiff/libtiff/tif_predict.c b/frmts/gtiff/libtiff/tif_predict.c
index 556b1c4..78b9707 100644
--- a/frmts/gtiff/libtiff/tif_predict.c
+++ b/frmts/gtiff/libtiff/tif_predict.c
@@ -1,4 +1,4 @@
-/* $Id: tif_predict.c,v 1.37 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tif_predict.c,v 1.42 2017-02-25 17:05:12 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -34,18 +34,18 @@
 
 #define	PredictorState(tif)	((TIFFPredictorState*) (tif)->tif_data)
 
-static void horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc);
-static void fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc);
+static int fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc);
 static int PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s);
 static int PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s);
 static int PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
@@ -80,6 +80,15 @@ PredictorSetup(TIFF* tif)
 				    td->td_sampleformat);
 				return 0;
 			}
+                        if (td->td_bitspersample != 16
+                            && td->td_bitspersample != 24
+                            && td->td_bitspersample != 32
+                            && td->td_bitspersample != 64) { /* Should 64 be allowed? */
+                                TIFFErrorExt(tif->tif_clientdata, module,
+                                             "Floating point \"Predictor\" not supported with %d-bit samples",
+                                             td->td_bitspersample);
+				return 0;
+                            }
 			break;
 		default:
 			TIFFErrorExt(tif->tif_clientdata, module,
@@ -174,7 +183,7 @@ PredictorSetupDecode(TIFF* tif)
 		}
 		/*
 		 * Allocate buffer to keep the decoded bytes before
-		 * rearranging in the ight order
+		 * rearranging in the right order
 		 */
 	}
 
@@ -250,11 +259,12 @@ PredictorSetupEncode(TIFF* tif)
 
 #define REPEAT4(n, op)		\
     switch (n) {		\
-    default: { tmsize_t i; for (i = n-4; i > 0; i--) { op; } } \
-    case 4:  op;		\
-    case 3:  op;		\
-    case 2:  op;		\
-    case 1:  op;		\
+    default: { \
+        tmsize_t i; for (i = n-4; i > 0; i--) { op; } }  /*-fallthrough*/  \
+    case 4:  op; /*-fallthrough*/ \
+    case 3:  op; /*-fallthrough*/ \
+    case 2:  op; /*-fallthrough*/ \
+    case 1:  op; /*-fallthrough*/ \
     case 0:  ;			\
     }
 
@@ -264,13 +274,19 @@ PredictorSetupEncode(TIFF* tif)
 /* - when storing into the byte stream, we explicitly mask with 0xff so */
 /*   as to make icc -check=conversions happy (not necessary by the standard) */
 
-static void
+static int
 horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
 
 	unsigned char* cp = (unsigned char*) cp0;
-	assert((cc%stride)==0);
+    if((cc%stride)!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horAcc8",
+                     "%s", "(cc%stride)!=0");
+        return 0;
+    }
+
 	if (cc > stride) {
 		/*
 		 * Pipeline the most common cases.
@@ -312,26 +328,32 @@ horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
 			} while (cc>0);
 		}
 	}
+	return 1;
 }
 
-static void
+static int
 swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	uint16* wp = (uint16*) cp0;
 	tmsize_t wc = cc / 2;
 
         TIFFSwabArrayOfShort(wp, wc);
-        horAcc16(tif, cp0, cc);
+        return horAcc16(tif, cp0, cc);
 }
 
-static void
+static int
 horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
 	uint16* wp = (uint16*) cp0;
 	tmsize_t wc = cc / 2;
 
-	assert((cc%(2*stride))==0);
+    if((cc%(2*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horAcc16",
+                     "%s", "cc%(2*stride))!=0");
+        return 0;
+    }
 
 	if (wc > stride) {
 		wc -= stride;
@@ -340,26 +362,32 @@ horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
 			wc -= stride;
 		} while (wc > 0);
 	}
+	return 1;
 }
 
-static void
+static int
 swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	uint32* wp = (uint32*) cp0;
 	tmsize_t wc = cc / 4;
 
         TIFFSwabArrayOfLong(wp, wc);
-	horAcc32(tif, cp0, cc);
+	return horAcc32(tif, cp0, cc);
 }
 
-static void
+static int
 horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
 	uint32* wp = (uint32*) cp0;
 	tmsize_t wc = cc / 4;
 
-	assert((cc%(4*stride))==0);
+    if((cc%(4*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horAcc32",
+                     "%s", "cc%(4*stride))!=0");
+        return 0;
+    }
 
 	if (wc > stride) {
 		wc -= stride;
@@ -368,12 +396,13 @@ horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
 			wc -= stride;
 		} while (wc > 0);
 	}
+	return 1;
 }
 
 /*
  * Floating point predictor accumulation routine.
  */
-static void
+static int
 fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
@@ -381,12 +410,18 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc)
 	tmsize_t wc = cc / bps;
 	tmsize_t count = cc;
 	uint8 *cp = (uint8 *) cp0;
-	uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
+	uint8 *tmp;
 
-	assert((cc%(bps*stride))==0);
+    if(cc%(bps*stride)!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "fpAcc",
+                     "%s", "cc%(bps*stride))!=0");
+        return 0;
+    }
 
+    tmp = (uint8 *)_TIFFmalloc(cc);
 	if (!tmp)
-		return;
+		return 0;
 
 	while (count > stride) {
 		REPEAT4(stride, cp[stride] =
@@ -408,6 +443,7 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc)
 		}
 	}
 	_TIFFfree(tmp);
+    return 1;
 }
 
 /*
@@ -423,8 +459,7 @@ PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 	assert(sp->decodepfunc != NULL);  
 
 	if ((*sp->decoderow)(tif, op0, occ0, s)) {
-		(*sp->decodepfunc)(tif, op0, occ0);
-		return 1;
+		return (*sp->decodepfunc)(tif, op0, occ0);
 	} else
 		return 0;
 }
@@ -447,10 +482,16 @@ PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 	if ((*sp->decodetile)(tif, op0, occ0, s)) {
 		tmsize_t rowsize = sp->rowsize;
 		assert(rowsize > 0);
-		assert((occ0%rowsize)==0);
+		if((occ0%rowsize) !=0)
+        {
+            TIFFErrorExt(tif->tif_clientdata, "PredictorDecodeTile",
+                         "%s", "occ0%rowsize != 0");
+            return 0;
+        }
 		assert(sp->decodepfunc != NULL);
 		while (occ0 > 0) {
-			(*sp->decodepfunc)(tif, op0, rowsize);
+			if( !(*sp->decodepfunc)(tif, op0, rowsize) )
+                return 0;
 			occ0 -= rowsize;
 			op0 += rowsize;
 		}
@@ -459,14 +500,19 @@ PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
 		return 0;
 }
 
-static void
+static int
 horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	TIFFPredictorState* sp = PredictorState(tif);
 	tmsize_t stride = sp->stride;
 	unsigned char* cp = (unsigned char*) cp0;
 
-	assert((cc%stride)==0);
+    if((cc%stride)!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horDiff8",
+                     "%s", "(cc%stride)!=0");
+        return 0;
+    }
 
 	if (cc > stride) {
 		cc -= stride;
@@ -504,9 +550,10 @@ horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc)
 			} while ((cc -= stride) > 0);
 		}
 	}
+	return 1;
 }
 
-static void
+static int
 horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	TIFFPredictorState* sp = PredictorState(tif);
@@ -514,7 +561,12 @@ horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
 	uint16 *wp = (uint16*) cp0;
 	tmsize_t wc = cc/2;
 
-	assert((cc%(2*stride))==0);
+    if((cc%(2*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horDiff8",
+                     "%s", "(cc%(2*stride))!=0");
+        return 0;
+    }
 
 	if (wc > stride) {
 		wc -= stride;
@@ -524,20 +576,23 @@ horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
 			wc -= stride;
 		} while (wc > 0);
 	}
+	return 1;
 }
 
-static void
+static int
 swabHorDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
     uint16* wp = (uint16*) cp0;
     tmsize_t wc = cc / 2;
 
-    horDiff16(tif, cp0, cc);
+    if( !horDiff16(tif, cp0, cc) )
+        return 0;
 
     TIFFSwabArrayOfShort(wp, wc);
+    return 1;
 }
 
-static void
+static int
 horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	TIFFPredictorState* sp = PredictorState(tif);
@@ -545,7 +600,12 @@ horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
 	uint32 *wp = (uint32*) cp0;
 	tmsize_t wc = cc/4;
 
-	assert((cc%(4*stride))==0);
+    if((cc%(4*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "horDiff32",
+                     "%s", "(cc%(4*stride))!=0");
+        return 0;
+    }
 
 	if (wc > stride) {
 		wc -= stride;
@@ -555,23 +615,26 @@ horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
 			wc -= stride;
 		} while (wc > 0);
 	}
+	return 1;
 }
 
-static void
+static int
 swabHorDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
     uint32* wp = (uint32*) cp0;
     tmsize_t wc = cc / 4;
 
-    horDiff32(tif, cp0, cc);
+    if( !horDiff32(tif, cp0, cc) )
+        return 0;
 
     TIFFSwabArrayOfLong(wp, wc);
+    return 1;
 }
 
 /*
  * Floating point predictor differencing routine.
  */
-static void
+static int
 fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
 {
 	tmsize_t stride = PredictorState(tif)->stride;
@@ -579,12 +642,18 @@ fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
 	tmsize_t wc = cc / bps;
 	tmsize_t count;
 	uint8 *cp = (uint8 *) cp0;
-	uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
+	uint8 *tmp;
 
-	assert((cc%(bps*stride))==0);
+    if((cc%(bps*stride))!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "fpDiff",
+                     "%s", "(cc%(bps*stride))!=0");
+        return 0;
+    }
 
+    tmp = (uint8 *)_TIFFmalloc(cc);
 	if (!tmp)
-		return;
+		return 0;
 
 	_TIFFmemcpy(tmp, cp0, cc);
 	for (count = 0; count < wc; count++) {
@@ -604,6 +673,7 @@ fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
 	cp += cc - stride - 1;
 	for (count = cc; count > stride; count -= stride)
 		REPEAT4(stride, cp[stride] = (unsigned char)((cp[stride] - cp[0])&0xff); cp--)
+    return 1;
 }
 
 static int
@@ -616,7 +686,8 @@ PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 	assert(sp->encoderow != NULL);
 
 	/* XXX horizontal differencing alters user's data XXX */
-	(*sp->encodepfunc)(tif, bp, cc);
+	if( !(*sp->encodepfunc)(tif, bp, cc) )
+        return 0;
 	return (*sp->encoderow)(tif, bp, cc, s);
 }
 
@@ -651,7 +722,13 @@ PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s)
 
 	rowsize = sp->rowsize;
 	assert(rowsize > 0);
-	assert((cc0%rowsize)==0);
+	if((cc0%rowsize)!=0)
+    {
+        TIFFErrorExt(tif->tif_clientdata, "PredictorEncodeTile",
+                     "%s", "(cc0%rowsize)!=0");
+        _TIFFfree( working_copy );
+        return 0;
+    }
 	while (cc > 0) {
 		(*sp->encodepfunc)(tif, bp, rowsize);
 		cc -= rowsize;
@@ -721,7 +798,7 @@ PredictorPrintDir(TIFF* tif, FILE* fd, long flags)
 			case 2: fprintf(fd, "horizontal differencing "); break;
 			case 3: fprintf(fd, "floating point predictor "); break;
 		}
-		fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor);
+		fprintf(fd, "%d (0x%x)\n", sp->predictor, sp->predictor);
 	}
 	if (sp->printdir)
 		(*sp->printdir)(tif, fd, flags);
diff --git a/frmts/gtiff/libtiff/tif_predict.h b/frmts/gtiff/libtiff/tif_predict.h
index dc7144c..6c68e21 100644
--- a/frmts/gtiff/libtiff/tif_predict.h
+++ b/frmts/gtiff/libtiff/tif_predict.h
@@ -1,4 +1,4 @@
-/* $Id: tif_predict.h,v 1.8 2010-03-10 18:56:49 bfriesen Exp $ */
+/* $Id: tif_predict.h,v 1.9 2016-10-31 17:24:26 erouault Exp $ */
 
 /*
  * Copyright (c) 1995-1997 Sam Leffler
@@ -30,6 +30,8 @@
  * ``Library-private'' Support for the Predictor Tag
  */
 
+typedef int (*TIFFEncodeDecodeMethod)(TIFF* tif, uint8* buf, tmsize_t size);
+
 /*
  * Codecs that want to support the Predictor tag must place
  * this structure first in their private state block so that
@@ -43,12 +45,12 @@ typedef struct {
 	TIFFCodeMethod  encoderow;	/* parent codec encode/decode row */
 	TIFFCodeMethod  encodestrip;	/* parent codec encode/decode strip */
 	TIFFCodeMethod  encodetile;	/* parent codec encode/decode tile */ 
-	TIFFPostMethod  encodepfunc;	/* horizontal differencer */
+	TIFFEncodeDecodeMethod  encodepfunc;	/* horizontal differencer */
 
 	TIFFCodeMethod  decoderow;	/* parent codec encode/decode row */
 	TIFFCodeMethod  decodestrip;	/* parent codec encode/decode strip */
 	TIFFCodeMethod  decodetile;	/* parent codec encode/decode tile */ 
-	TIFFPostMethod  decodepfunc;	/* horizontal accumulator */
+	TIFFEncodeDecodeMethod  decodepfunc;	/* horizontal accumulator */
 
 	TIFFVGetMethod  vgetparent;	/* super-class method */
 	TIFFVSetMethod  vsetparent;	/* super-class method */
diff --git a/frmts/gtiff/libtiff/tif_print.c b/frmts/gtiff/libtiff/tif_print.c
index 186f2ee..24d4b98 100644
--- a/frmts/gtiff/libtiff/tif_print.c
+++ b/frmts/gtiff/libtiff/tif_print.c
@@ -1,4 +1,4 @@
-/* $Id: tif_print.c,v 1.64 2015-12-06 22:19:56 erouault Exp $ */
+/* $Id: tif_print.c,v 1.65 2016-11-20 22:31:22 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -262,7 +262,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 		if (td->td_subfiletype & FILETYPE_MASK)
 			fprintf(fd, "%stransparency mask", sep);
 		fprintf(fd, " (%lu = 0x%lx)\n",
-		    (long) td->td_subfiletype, (long) td->td_subfiletype);
+		    (unsigned long) td->td_subfiletype, (long) td->td_subfiletype);
 	}
 	if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) {
 		fprintf(fd, "  Image Width: %lu Image Length: %lu",
@@ -521,7 +521,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 			fprintf(fd, "\n");
 			n = 1L<<td->td_bitspersample;
 			for (l = 0; l < n; l++)
-				fprintf(fd, "   %5lu: %5u %5u %5u\n",
+				fprintf(fd, "   %5ld: %5u %5u %5u\n",
 				    l,
 				    td->td_colormap[0][l],
 				    td->td_colormap[1][l],
@@ -544,7 +544,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 			n = 1L<<td->td_bitspersample;
 			for (l = 0; l < n; l++) {
 				uint16 i;
-				fprintf(fd, "    %2lu: %5u",
+				fprintf(fd, "    %2ld: %5u",
 				    l, td->td_transferfunction[0][l]);
 				for (i = 1; i < td->td_samplesperpixel; i++)
 					fprintf(fd, " %5u",
@@ -661,7 +661,7 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 		uint32 s;
 
 		fprintf(fd, "  %lu %s:\n",
-		    (long) td->td_nstrips,
+		    (unsigned long) td->td_nstrips,
 		    isTiled(tif) ? "Tiles" : "Strips");
 		for (s = 0; s < td->td_nstrips; s++)
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
diff --git a/frmts/gtiff/libtiff/tif_read.c b/frmts/gtiff/libtiff/tif_read.c
index 9d67bf2..6a8c7da 100644
--- a/frmts/gtiff/libtiff/tif_read.c
+++ b/frmts/gtiff/libtiff/tif_read.c
@@ -1,4 +1,4 @@
-/* $Id: tif_read.c,v 1.47 2016-01-03 10:01:25 erouault Exp $ */
+/* $Id: tif_read.c,v 1.53 2017-01-11 19:02:49 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -31,6 +31,9 @@
 #include "tiffiop.h"
 #include <stdio.h>
 
+#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
+#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
+
 int TIFFFillStrip(TIFF* tif, uint32 strip);
 int TIFFFillTile(TIFF* tif, uint32 tile);
 static int TIFFStartStrip(TIFF* tif, uint32 strip);
@@ -38,6 +41,8 @@ static int TIFFStartTile(TIFF* tif, uint32 tile);
 static int TIFFCheckRead(TIFF*, int);
 static tmsize_t
 TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,const char* module);
+static tmsize_t
+TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module);
 
 #define NOSTRIP ((uint32)(-1))       /* undefined state */
 #define NOTILE ((uint32)(-1))         /* undefined state */
@@ -341,7 +346,7 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
 	rowsperstrip=td->td_rowsperstrip;
 	if (rowsperstrip>td->td_imagelength)
 		rowsperstrip=td->td_imagelength;
-	stripsperplane=((td->td_imagelength+rowsperstrip-1)/rowsperstrip);
+	stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
 	stripinplane=(strip%stripsperplane);
 	plane=(uint16)(strip/stripsperplane);
 	rows=td->td_imagelength-stripinplane*rowsperstrip;
@@ -350,6 +355,24 @@ TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
 	stripsize=TIFFVStripSize(tif,rows);
 	if (stripsize==0)
 		return((tmsize_t)(-1));
+
+    /* shortcut to avoid an extra memcpy() */
+    if( td->td_compression == COMPRESSION_NONE &&
+        size!=(tmsize_t)(-1) && size >= stripsize &&
+        !isMapped(tif) &&
+        ((tif->tif_flags&TIFF_NOREADRAW)==0) )
+    {
+        if (TIFFReadRawStrip1(tif, strip, buf, stripsize, module) != stripsize)
+            return ((tmsize_t)(-1));
+
+        if (!isFillOrder(tif, td->td_fillorder) &&
+            (tif->tif_flags & TIFF_NOBITREV) == 0)
+            TIFFReverseBits(buf,stripsize);
+
+        (*tif->tif_postdecode)(tif,buf,stripsize);
+        return (stripsize);
+    }
+
 	if ((size!=(tmsize_t)(-1))&&(size<stripsize))
 		stripsize=size;
 	if (!TIFFFillStrip(tif,strip))
@@ -397,16 +420,25 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
 			return ((tmsize_t)(-1));
 		}
 	} else {
-		tmsize_t ma,mb;
+		tmsize_t ma = 0;
 		tmsize_t n;
-		ma=(tmsize_t)td->td_stripoffset[strip];
-		mb=ma+size;
-		if (((uint64)ma!=td->td_stripoffset[strip])||(ma>tif->tif_size))
-			n=0;
-		else if ((mb<ma)||(mb<size)||(mb>tif->tif_size))
-			n=tif->tif_size-ma;
-		else
-			n=size;
+		if ((td->td_stripoffset[strip] > (uint64)TIFF_TMSIZE_T_MAX)||
+                    ((ma=(tmsize_t)td->td_stripoffset[strip])>tif->tif_size))
+                {
+                    n=0;
+                }
+                else if( ma > TIFF_TMSIZE_T_MAX - size )
+                {
+                    n=0;
+                }
+                else
+                {
+                    tmsize_t mb=ma+size;
+                    if (mb>tif->tif_size)
+                            n=tif->tif_size-ma;
+                    else
+                            n=size;
+                }
 		if (n!=size) {
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
 			TIFFErrorExt(tif->tif_clientdata, module,
@@ -661,6 +693,24 @@ TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size)
 		    (unsigned long) tile, (unsigned long) td->td_nstrips);
 		return ((tmsize_t)(-1));
 	}
+
+    /* shortcut to avoid an extra memcpy() */
+    if( td->td_compression == COMPRESSION_NONE &&
+        size!=(tmsize_t)(-1) && size >= tilesize &&
+        !isMapped(tif) &&
+        ((tif->tif_flags&TIFF_NOREADRAW)==0) )
+    {
+        if (TIFFReadRawTile1(tif, tile, buf, tilesize, module) != tilesize)
+            return ((tmsize_t)(-1));
+
+        if (!isFillOrder(tif, td->td_fillorder) &&
+            (tif->tif_flags & TIFF_NOBITREV) == 0)
+            TIFFReverseBits(buf,tilesize);
+
+        (*tif->tif_postdecode)(tif,buf,tilesize);
+        return (tilesize);
+    }
+
 	if (size == (tmsize_t)(-1))
 		size = tilesize;
 	else if (size > tilesize)
@@ -717,7 +767,7 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
 		tmsize_t n;
 		ma=(tmsize_t)td->td_stripoffset[tile];
 		mb=ma+size;
-		if (((uint64)ma!=td->td_stripoffset[tile])||(ma>tif->tif_size))
+		if ((td->td_stripoffset[tile] > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size))
 			n=0;
 		else if ((mb<ma)||(mb<size)||(mb>tif->tif_size))
 			n=tif->tif_size-ma;
@@ -935,7 +985,9 @@ TIFFReadBufferSetup(TIFF* tif, void* bp, tmsize_t size)
 				 "Invalid buffer size");
 		    return (0);
 		}
-		tif->tif_rawdata = (uint8*) _TIFFmalloc(tif->tif_rawdatasize);
+		/* Initialize to zero to avoid uninitialized buffers in case of */
+                /* short reads (http://bugzilla.maptools.org/show_bug.cgi?id=2651) */
+		tif->tif_rawdata = (uint8*) _TIFFcalloc(1, tif->tif_rawdatasize);
 		tif->tif_flags |= TIFF_MYBUFFER;
 	}
 	if (tif->tif_rawdata == NULL) {
diff --git a/frmts/gtiff/libtiff/tif_strip.c b/frmts/gtiff/libtiff/tif_strip.c
index 6cac71d..6e9f2ef 100644
--- a/frmts/gtiff/libtiff/tif_strip.c
+++ b/frmts/gtiff/libtiff/tif_strip.c
@@ -1,4 +1,4 @@
-/* $Id: tif_strip.c,v 1.36 2015-06-07 22:35:40 bfriesen Exp $ */
+/* $Id: tif_strip.c,v 1.38 2016-12-03 11:02:15 erouault Exp $ */
 
 /*
  * Copyright (c) 1991-1997 Sam Leffler
diff --git a/frmts/gtiff/libtiff/tif_swab.c b/frmts/gtiff/libtiff/tif_swab.c
index f37e33f..211dc57 100644
--- a/frmts/gtiff/libtiff/tif_swab.c
+++ b/frmts/gtiff/libtiff/tif_swab.c
@@ -1,4 +1,4 @@
-/* $Id: tif_swab.c,v 1.13 2010-03-10 18:56:49 bfriesen Exp $ */
+/* $Id: tif_swab.c,v 1.14 2016-09-04 21:32:56 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -296,8 +296,10 @@ TIFFReverseBits(uint8* cp, tmsize_t n)
 		cp[7] = TIFFBitRevTable[cp[7]];
 		cp += 8;
 	}
-	while (n-- > 0)
-		*cp = TIFFBitRevTable[*cp], cp++;
+	while (n-- > 0) {
+		*cp = TIFFBitRevTable[*cp];
+		cp++;
+	}
 }
 
 /* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/frmts/gtiff/libtiff/tif_thunder.c b/frmts/gtiff/libtiff/tif_thunder.c
index 390891c..183199d 100644
--- a/frmts/gtiff/libtiff/tif_thunder.c
+++ b/frmts/gtiff/libtiff/tif_thunder.c
@@ -1,4 +1,4 @@
-/* $Id: tif_thunder.c,v 1.12 2011-04-02 20:54:09 bfriesen Exp $ */
+/* $Id: tif_thunder.c,v 1.13 2016-09-04 21:32:56 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -100,7 +100,8 @@ ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels)
 	while (cc > 0 && npixels < maxpixels) {
 		int n, delta;
 
-		n = *bp++, cc--;
+		n = *bp++;
+		cc--;
 		switch (n & THUNDER_CODE) {
 		case THUNDER_RUN:		/* pixel run */
 			/*
diff --git a/frmts/gtiff/libtiff/tif_vsi.c b/frmts/gtiff/libtiff/tif_vsi.c
index 7a34f78..2235685 100644
--- a/frmts/gtiff/libtiff/tif_vsi.c
+++ b/frmts/gtiff/libtiff/tif_vsi.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tif_vsi.c 32883 2016-01-09 18:24:40Z rouault $
+ * $Id: tif_vsi.c 37104 2017-01-11 19:08:08Z rouault $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
@@ -112,9 +112,10 @@ TIFFOpen(const char* name, const char* mode)
         char          szAccess[32];
         VSILFILE          *fp;
         TIFF          *tif;
+        char         *pszAccess = szAccess;
 
         a_out = 0;
-        szAccess[0] = '\0';
+        pszAccess[0] = '\0';
         for( i = 0; mode[i] != '\0'; i++ )
         {
             if( mode[i] == 'r'
@@ -158,6 +159,14 @@ _TIFFmalloc(tsize_t s)
     return VSIMalloc((size_t) s);
 }
 
+void* _TIFFcalloc(tmsize_t nmemb, tmsize_t siz)
+{
+    if( nmemb == 0 || siz == 0 )
+        return ((void *) NULL);
+
+    return VSICalloc((size_t) nmemb, (size_t)siz);
+}
+
 void
 _TIFFfree(tdata_t p)
 {
diff --git a/frmts/gtiff/libtiff/tif_write.c b/frmts/gtiff/libtiff/tif_write.c
index 77114fd..4c216ec 100644
--- a/frmts/gtiff/libtiff/tif_write.c
+++ b/frmts/gtiff/libtiff/tif_write.c
@@ -1,4 +1,4 @@
-/* $Id: tif_write.c,v 1.43 2015-12-12 18:04:26 erouault Exp $ */
+/* $Id: tif_write.c,v 1.46 2016-12-03 21:57:44 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -258,6 +258,23 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
     tif->tif_rawcp = tif->tif_rawdata;
 
 	tif->tif_flags &= ~TIFF_POSTENCODE;
+
+    /* shortcut to avoid an extra memcpy() */
+    if( td->td_compression == COMPRESSION_NONE )
+    {
+        /* swab if needed - note that source buffer will be altered */
+        tif->tif_postdecode( tif, (uint8*) data, cc );
+
+        if (!isFillOrder(tif, td->td_fillorder) &&
+            (tif->tif_flags & TIFF_NOBITREV) == 0)
+            TIFFReverseBits((uint8*) data, cc);
+
+        if (cc > 0 &&
+            !TIFFAppendToStrip(tif, strip, (uint8*) data, cc))
+            return ((tmsize_t) -1);
+        return (cc);
+    }
+
 	sample = (uint16)(strip / td->td_stripsperimage);
 	if (!(*tif->tif_preencode)(tif, sample))
 		return ((tmsize_t) -1);
@@ -431,9 +448,7 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
 		tif->tif_flags |= TIFF_CODERSETUP;
 	}
 	tif->tif_flags &= ~TIFF_POSTENCODE;
-	sample = (uint16)(tile/td->td_stripsperimage);
-	if (!(*tif->tif_preencode)(tif, sample))
-		return ((tmsize_t)(-1));
+
 	/*
 	 * Clamp write amount to the tile size.  This is mostly
 	 * done so that callers can pass in some large number
@@ -442,22 +457,41 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
 	if ( cc < 1 || cc > tif->tif_tilesize)
 		cc = tif->tif_tilesize;
 
+    /* shortcut to avoid an extra memcpy() */
+    if( td->td_compression == COMPRESSION_NONE )
+    {
         /* swab if needed - note that source buffer will be altered */
-	tif->tif_postdecode( tif, (uint8*) data, cc );
-
-	if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample))
-		return ((tmsize_t) -1);
-	if (!(*tif->tif_postencode)(tif))
-		return ((tmsize_t)(-1));
-	if (!isFillOrder(tif, td->td_fillorder) &&
-	    (tif->tif_flags & TIFF_NOBITREV) == 0)
-		TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc);
-	if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
-	    tif->tif_rawdata, tif->tif_rawcc))
-		return ((tmsize_t)(-1));
-	tif->tif_rawcc = 0;
-	tif->tif_rawcp = tif->tif_rawdata;
-	return (cc);
+        tif->tif_postdecode( tif, (uint8*) data, cc );
+
+        if (!isFillOrder(tif, td->td_fillorder) &&
+            (tif->tif_flags & TIFF_NOBITREV) == 0)
+            TIFFReverseBits((uint8*) data, cc);
+
+        if (cc > 0 &&
+            !TIFFAppendToStrip(tif, tile, (uint8*) data, cc))
+            return ((tmsize_t) -1);
+        return (cc);
+    }
+
+    sample = (uint16)(tile/td->td_stripsperimage);
+    if (!(*tif->tif_preencode)(tif, sample))
+        return ((tmsize_t)(-1));
+    /* swab if needed - note that source buffer will be altered */
+    tif->tif_postdecode( tif, (uint8*) data, cc );
+
+    if (!(*tif->tif_encodetile)(tif, (uint8*) data, cc, sample))
+            return ((tmsize_t) -1);
+    if (!(*tif->tif_postencode)(tif))
+            return ((tmsize_t)(-1));
+    if (!isFillOrder(tif, td->td_fillorder) &&
+        (tif->tif_flags & TIFF_NOBITREV) == 0)
+            TIFFReverseBits((uint8*)tif->tif_rawdata, tif->tif_rawcc);
+    if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
+        tif->tif_rawdata, tif->tif_rawcc))
+            return ((tmsize_t)(-1));
+    tif->tif_rawcc = 0;
+    tif->tif_rawcp = tif->tif_rawdata;
+    return (cc);
 }
 
 /*
@@ -764,7 +798,14 @@ TIFFFlushData1(TIFF* tif)
 		if (!TIFFAppendToStrip(tif,
 		    isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
 		    tif->tif_rawdata, tif->tif_rawcc))
+        {
+            /* We update those variables even in case of error since there's */
+            /* code that doesn't really check the return code of this */
+            /* function */
+            tif->tif_rawcc = 0;
+            tif->tif_rawcp = tif->tif_rawdata;
 			return (0);
+        }
 		tif->tif_rawcc = 0;
 		tif->tif_rawcp = tif->tif_rawdata;
 	}
diff --git a/frmts/gtiff/libtiff/tif_zip.c b/frmts/gtiff/libtiff/tif_zip.c
index 954a1e5..8c35aea 100644
--- a/frmts/gtiff/libtiff/tif_zip.c
+++ b/frmts/gtiff/libtiff/tif_zip.c
@@ -1,4 +1,4 @@
-/* $Id: tif_zip.c,v 1.35 2015-11-22 22:37:27 erouault Exp $ */
+/* $Id: tif_zip.c,v 1.36 2016-11-12 16:48:28 erouault Exp $ */
 
 /*
  * Copyright (c) 1995-1997 Sam Leffler
diff --git a/frmts/gtiff/libtiff/tiffio.h b/frmts/gtiff/libtiff/tiffio.h
index 6a84d80..ef61b5c 100644
--- a/frmts/gtiff/libtiff/tiffio.h
+++ b/frmts/gtiff/libtiff/tiffio.h
@@ -1,4 +1,4 @@
-/* $Id: tiffio.h,v 1.92 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tiffio.h,v 1.94 2017-01-11 19:02:49 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -293,6 +293,7 @@ extern TIFFCodec* TIFFGetConfiguredCODECs(void);
  */
 
 extern void* _TIFFmalloc(tmsize_t s);
+extern void* _TIFFcalloc(tmsize_t nmemb, tmsize_t siz);
 extern void* _TIFFrealloc(void* p, tmsize_t s);
 extern void _TIFFmemset(void* p, int v, tmsize_t c);
 extern void _TIFFmemcpy(void* d, const void* s, tmsize_t c);
@@ -430,6 +431,8 @@ extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, int, int);
 
 extern int TIFFReadRGBAStrip(TIFF*, uint32, uint32 * );
 extern int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * );
+extern int TIFFReadRGBAStripExt(TIFF*, uint32, uint32 *, int stop_on_error );
+extern int TIFFReadRGBATileExt(TIFF*, uint32, uint32, uint32 *, int stop_on_error );
 extern int TIFFRGBAImageOK(TIFF*, char [1024]);
 extern int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]);
 extern int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32);
diff --git a/frmts/gtiff/libtiff/tiffiop.h b/frmts/gtiff/libtiff/tiffiop.h
index 8bcd0c1..5294ee7 100644
--- a/frmts/gtiff/libtiff/tiffiop.h
+++ b/frmts/gtiff/libtiff/tiffiop.h
@@ -1,4 +1,4 @@
-/* $Id: tiffiop.h,v 1.89 2016-01-23 21:20:34 erouault Exp $ */
+/* $Id: tiffiop.h,v 1.90 2016-12-02 21:56:56 erouault Exp $ */
 
 /*
  * Copyright (c) 1988-1997 Sam Leffler
@@ -250,6 +250,10 @@ struct tiff {
 #define TIFFhowmany_32(x, y) (((uint32)x < (0xffffffff - (uint32)(y-1))) ? \
 			   ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y))) : \
 			   0U)
+/* Variant of TIFFhowmany_32() that doesn't return 0 if x close to MAXUINT. */
+/* Caution: TIFFhowmany_32_maxuint_compat(x,y)*y might overflow */
+#define TIFFhowmany_32_maxuint_compat(x, y) \
+			   (((uint32)(x) / (uint32)(y)) + ((((uint32)(x) % (uint32)(y)) != 0) ? 1 : 0))
 #define TIFFhowmany8_32(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
 #define TIFFroundup_32(x, y) (TIFFhowmany_32(x,y)*(y))
 #define TIFFhowmany_64(x, y) ((((uint64)(x))+(((uint64)(y))-1))/((uint64)(y)))
diff --git a/frmts/gtiff/libtiff/tiffvers.h b/frmts/gtiff/libtiff/tiffvers.h
index e965814..fe55c72 100644
--- a/frmts/gtiff/libtiff/tiffvers.h
+++ b/frmts/gtiff/libtiff/tiffvers.h
@@ -1,4 +1,4 @@
-#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.6\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.7\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
 /*
  * This define can be used in code that requires
  * compilation-related definitions specific to a
@@ -6,4 +6,4 @@
  * version checking should be done based on the
  * string returned by TIFFGetVersion.
  */
-#define TIFFLIB_VERSION 20150912
+#define TIFFLIB_VERSION 20161119
diff --git a/frmts/gtiff/tif_float.c b/frmts/gtiff/tif_float.c
index 7575d42..a6f5808 100644
--- a/frmts/gtiff/tif_float.c
+++ b/frmts/gtiff/tif_float.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tif_float.c 33796 2016-03-27 13:21:07Z goatbar $
+ * $Id: tif_float.c 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Floating point conversion functions. Convert 16- and 24-bit
diff --git a/frmts/gtiff/tifvsi.cpp b/frmts/gtiff/tifvsi.cpp
index 7a25846..fabf56b 100644
--- a/frmts/gtiff/tifvsi.cpp
+++ b/frmts/gtiff/tifvsi.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tifvsi.cpp 33806 2016-03-28 22:26:19Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
@@ -30,14 +29,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-/*
- * TIFF Library UNIX-specific Routines.
- */
-#include "cpl_vsi.h"
-#include "cpl_conv.h"
+// TIFF Library UNIX-specific Routines.
+
+#include "cpl_port.h"
 #include "tifvsi.h"
 
+#include <string.h>
 #include <cerrno>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include "cpl_conv.h"
+#include "cpl_vsi.h"
 
 // We avoid including xtiffio.h since it drags in the libgeotiff version
 // of the VSI functions.
@@ -46,41 +50,44 @@
 #include "gdal_libgeotiff_symbol_rename.h"
 #endif
 
+CPL_CVSID("$Id: tifvsi.cpp 36579 2016-11-30 15:06:24Z goatbar $");
+
 CPL_C_START
-extern TIFF CPL_DLL * XTIFFClientOpen(const char* name, const char* mode,
-                                      thandle_t thehandle,
-                                      TIFFReadWriteProc, TIFFReadWriteProc,
-                                      TIFFSeekProc, TIFFCloseProc,
-                                      TIFFSizeProc,
-                                      TIFFMapFileProc, TIFFUnmapFileProc);
+extern TIFF CPL_DLL * XTIFFClientOpen( const char* name, const char* mode,
+                                       thandle_t thehandle,
+                                       TIFFReadWriteProc, TIFFReadWriteProc,
+                                       TIFFSeekProc, TIFFCloseProc,
+                                       TIFFSizeProc,
+                                       TIFFMapFileProc, TIFFUnmapFileProc );
 CPL_C_END
 
-#define BUFFER_SIZE     (65536)
+static const int BUFFER_SIZE = 65536;
 
 typedef struct
 {
     VSILFILE*   fpL;
-    int         bAtEndOfFile;
+    bool        bAtEndOfFile;
     vsi_l_offset nExpectedPos;
     GByte      *abyWriteBuffer;
     int         nWriteBufferSize;
 } GDALTiffHandle;
 
 static tsize_t
-_tiffReadProc(thandle_t th, tdata_t buf, tsize_t size)
+_tiffReadProc( thandle_t th, tdata_t buf, tsize_t size )
 {
-    GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
+    GDALTiffHandle* psGTH = reinterpret_cast<GDALTiffHandle *>(th);
     return VSIFReadL( buf, 1, size, psGTH->fpL );
 }
 
-static int GTHFlushBuffer(thandle_t th)
+static bool GTHFlushBuffer( thandle_t th )
 {
     GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
-    int bRet = TRUE;
+    bool bRet = true;
     if( psGTH->abyWriteBuffer && psGTH->nWriteBufferSize )
     {
-        tsize_t nRet = VSIFWriteL( psGTH->abyWriteBuffer, 1, psGTH->nWriteBufferSize, psGTH->fpL );
-        bRet = (nRet == psGTH->nWriteBufferSize);
+        const tsize_t nRet = VSIFWriteL( psGTH->abyWriteBuffer, 1,
+                                         psGTH->nWriteBufferSize, psGTH->fpL );
+        bRet = nRet == psGTH->nWriteBufferSize;
         if( !bRet )
         {
             TIFFErrorExt( th, "_tiffWriteProc", "%s", VSIStrerror( errno ) );
@@ -90,17 +97,16 @@ static int GTHFlushBuffer(thandle_t th)
     return bRet;
 }
 
-
 static tsize_t
-_tiffWriteProc(thandle_t th, tdata_t buf, tsize_t size)
+_tiffWriteProc( thandle_t th, tdata_t buf, tsize_t size )
 {
-    GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
+    GDALTiffHandle* psGTH = reinterpret_cast<GDALTiffHandle *>( th );
 
     // If we have a write buffer and are at end of file, then accumulate
-    // the bytes until the buffer is full
+    // the bytes until the buffer is full.
     if( psGTH->bAtEndOfFile && psGTH->abyWriteBuffer )
     {
-        const GByte* pabyData = (const GByte*) buf;
+        const GByte* pabyData = reinterpret_cast<GByte *>( buf );
         tsize_t nRemainingBytes = size;
         while( true )
         {
@@ -116,7 +122,8 @@ _tiffWriteProc(thandle_t th, tdata_t buf, tsize_t size)
             int nAppendable = BUFFER_SIZE - psGTH->nWriteBufferSize;
             memcpy( psGTH->abyWriteBuffer + psGTH->nWriteBufferSize, pabyData,
                     nAppendable );
-            tsize_t nRet = VSIFWriteL( psGTH->abyWriteBuffer, 1, BUFFER_SIZE, psGTH->fpL );
+            const tsize_t nRet = VSIFWriteL( psGTH->abyWriteBuffer, 1,
+                                             BUFFER_SIZE, psGTH->fpL );
             psGTH->nWriteBufferSize = 0;
             if( nRet != BUFFER_SIZE )
             {
@@ -129,8 +136,8 @@ _tiffWriteProc(thandle_t th, tdata_t buf, tsize_t size)
         }
     }
 
-    tsize_t nRet = VSIFWriteL( buf, 1, size, psGTH->fpL );
-    if (nRet < size)
+    const tsize_t nRet = VSIFWriteL( buf, 1, size, psGTH->fpL );
+    if( nRet < size )
     {
         TIFFErrorExt( th, "_tiffWriteProc", "%s", VSIStrerror( errno ) );
     }
@@ -142,46 +149,48 @@ _tiffWriteProc(thandle_t th, tdata_t buf, tsize_t size)
 }
 
 static toff_t
-_tiffSeekProc(thandle_t th, toff_t off, int whence)
+_tiffSeekProc( thandle_t th, toff_t off, int whence )
 {
-    GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
+    GDALTiffHandle* psGTH = reinterpret_cast<GDALTiffHandle *>( th );
 
-    /* Optimization: if we are already at end, then no need to */
-    /* issue a VSIFSeekL() */
+    // Optimization: if we are already at end, then no need to
+    // issue a VSIFSeekL().
     if( whence == SEEK_END )
     {
         if( psGTH->bAtEndOfFile )
         {
-            return (toff_t) psGTH->nExpectedPos;
+            return static_cast<toff_t>( psGTH->nExpectedPos );
         }
 
         if( VSIFSeekL( psGTH->fpL, off, whence ) != 0 )
         {
             TIFFErrorExt( th, "_tiffSeekProc", "%s", VSIStrerror( errno ) );
-            return (toff_t) -1;
+            return static_cast<toff_t>( -1 );
         }
-        psGTH->bAtEndOfFile = TRUE;
+        psGTH->bAtEndOfFile = true;
         psGTH->nExpectedPos = VSIFTellL( psGTH->fpL );
-        return (toff_t) (psGTH->nExpectedPos);
+        return static_cast<toff_t>(psGTH->nExpectedPos);
     }
 
     GTHFlushBuffer(th);
-    psGTH->bAtEndOfFile = FALSE;
+    psGTH->bAtEndOfFile = false;
     psGTH->nExpectedPos = 0;
 
     if( VSIFSeekL( psGTH->fpL, off, whence ) == 0 )
-        return (toff_t) VSIFTellL( psGTH->fpL );
+    {
+        return static_cast<toff_t>( VSIFTellL( psGTH->fpL ) );
+    }
     else
     {
         TIFFErrorExt( th, "_tiffSeekProc", "%s", VSIStrerror( errno ) );
-        return (toff_t) -1;
+        return static_cast<toff_t>(-1);
     }
 }
 
 static int
-_tiffCloseProc(thandle_t th)
+_tiffCloseProc( thandle_t th )
 {
-    GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
+    GDALTiffHandle* psGTH = reinterpret_cast<GDALTiffHandle*>( th );
     GTHFlushBuffer(th);
     CPLFree(psGTH->abyWriteBuffer);
     CPLFree(psGTH);
@@ -189,67 +198,55 @@ _tiffCloseProc(thandle_t th)
 }
 
 static toff_t
-_tiffSizeProc(thandle_t th)
+_tiffSizeProc( thandle_t th )
 {
-    GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
-    vsi_l_offset  old_off;
-    toff_t        file_size;
-
+    GDALTiffHandle* psGTH = reinterpret_cast<GDALTiffHandle*>( th );
     if( psGTH->bAtEndOfFile )
     {
-        return (toff_t) psGTH->nExpectedPos;
+        return static_cast<toff_t>( psGTH->nExpectedPos );
     }
 
-    old_off = VSIFTellL( psGTH->fpL );
+    const vsi_l_offset old_off = VSIFTellL( psGTH->fpL );
     CPL_IGNORE_RET_VAL(VSIFSeekL( psGTH->fpL, 0, SEEK_END ));
 
-    file_size = (toff_t) VSIFTellL( psGTH->fpL );
+    const toff_t file_size = (toff_t) VSIFTellL( psGTH->fpL );
     CPL_IGNORE_RET_VAL(VSIFSeekL( psGTH->fpL, old_off, SEEK_SET ));
 
     return file_size;
 }
 
 static int
-_tiffMapProc(thandle_t th, tdata_t* pbase, toff_t* psize)
+_tiffMapProc( thandle_t /* th */, tdata_t* /* pbase */ , toff_t* /* psize */ )
 {
-    (void) th; (void) pbase; (void) psize;
-    return (0);
+    return 0;
 }
 
 static void
-_tiffUnmapProc(thandle_t th, tdata_t base, toff_t size)
-{
-    (void) th; (void) base; (void) size;
-}
+_tiffUnmapProc( thandle_t /* th */, tdata_t /* base */, toff_t /* size */ )
+{}
 
-VSILFILE* VSI_TIFFGetVSILFile(thandle_t th)
+VSILFILE* VSI_TIFFGetVSILFile( thandle_t th )
 {
-    GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
+    GDALTiffHandle* psGTH = reinterpret_cast<GDALTiffHandle *>( th );
     VSI_TIFFFlushBufferedWrite(th);
     return psGTH->fpL;
 }
 
-int VSI_TIFFFlushBufferedWrite(thandle_t th)
+int VSI_TIFFFlushBufferedWrite( thandle_t th )
 {
-    GDALTiffHandle* psGTH = (GDALTiffHandle*) th;
-    psGTH->bAtEndOfFile = FALSE;
+    GDALTiffHandle* psGTH = reinterpret_cast<GDALTiffHandle*>( th );
+    psGTH->bAtEndOfFile = false;
     return GTHFlushBuffer(th);
 }
 
-/*
- * Open a TIFF file for read/writing.
- */
-TIFF* VSI_TIFFOpen(const char* name, const char* mode,
-                   VSILFILE* fpL)
+// Open a TIFF file for read/writing.
+TIFF* VSI_TIFFOpen( const char* name, const char* mode,
+                    VSILFILE* fpL )
 {
-    int           i, a_out;
-    char          access[32];
-    TIFF          *tif;
-    int           bAllocBuffer = FALSE;
-
-    a_out = 0;
-    access[0] = '\0';
-    for( i = 0; mode[i] != '\0'; i++ )
+    char access[32] = { '\0' };
+    bool bAllocBuffer = false;
+    int a_out = 0;
+    for( int i = 0; mode[i] != '\0'; i++ )
     {
         if( mode[i] == 'r'
             || mode[i] == 'w'
@@ -262,30 +259,35 @@ TIFF* VSI_TIFFOpen(const char* name, const char* mode,
         if( mode[i] == 'w'
             || mode[i] == '+'
             || mode[i] == 'a' )
-            bAllocBuffer = TRUE;
+        {
+            bAllocBuffer = true;
+        }
     }
 
     // No need to buffer on /vsimem/
     if( STARTS_WITH(name, "/vsimem/") )
-        bAllocBuffer = FALSE;
+        bAllocBuffer = false;
 
     strcat( access, "b" );
 
     if( VSIFSeekL(fpL, 0, SEEK_SET) < 0 )
         return NULL;
 
-    GDALTiffHandle* psGTH = (GDALTiffHandle*) CPLMalloc(sizeof(GDALTiffHandle));
+    GDALTiffHandle* psGTH = static_cast<GDALTiffHandle *>(
+        CPLMalloc(sizeof(GDALTiffHandle)) );
     psGTH->fpL = fpL;
     psGTH->nExpectedPos = 0;
-    psGTH->bAtEndOfFile = FALSE;
-    psGTH->abyWriteBuffer = (bAllocBuffer) ? (GByte*)VSIMalloc(BUFFER_SIZE) : NULL;
+    psGTH->bAtEndOfFile = false;
+    psGTH->abyWriteBuffer =
+        bAllocBuffer ? static_cast<GByte *>( VSIMalloc(BUFFER_SIZE) ) : NULL;
     psGTH->nWriteBufferSize = 0;
 
-    tif = XTIFFClientOpen(name, mode,
-                          (thandle_t) psGTH,
-                          _tiffReadProc, _tiffWriteProc,
-                          _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
-                          _tiffMapProc, _tiffUnmapProc);
+    TIFF *tif =
+        XTIFFClientOpen( name, mode,
+                         (thandle_t) psGTH,
+                         _tiffReadProc, _tiffWriteProc,
+                         _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
+                         _tiffMapProc, _tiffUnmapProc );
     if( tif == NULL )
         CPLFree(psGTH);
 
diff --git a/frmts/gtiff/tifvsi.h b/frmts/gtiff/tifvsi.h
index a0e3ced..8230c1a 100644
--- a/frmts/gtiff/tifvsi.h
+++ b/frmts/gtiff/tifvsi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: tifvsi.h 31787 2015-11-26 17:41:42Z rouault $
+ * $Id: tifvsi.h 36579 2016-11-30 15:06:24Z goatbar $
  *
  * Project:  GeoTIFF Driver
  * Purpose:  Implement system hook functions for libtiff on top of CPL/VSI,
@@ -33,10 +33,12 @@
 #ifndef TIFVSI_H_INCLUDED
 #define TIFVSI_H_INCLUDED
 
+#include "cpl_port.h"
+#include "cpl_vsi.h"
 #include "tiffio.h"
 
-TIFF* VSI_TIFFOpen(const char* name, const char* mode, VSILFILE* fp);
-VSILFILE* VSI_TIFFGetVSILFile(thandle_t th);
-int VSI_TIFFFlushBufferedWrite(thandle_t th);
+TIFF* VSI_TIFFOpen( const char* name, const char* mode, VSILFILE* fp );
+VSILFILE* VSI_TIFFGetVSILFile( thandle_t th );
+int VSI_TIFFFlushBufferedWrite( thandle_t th );
 
 #endif // TIFVSI_H_INCLUDED
diff --git a/frmts/gxf/Doxyfile b/frmts/gxf/Doxyfile
index 751deb8..2c90b48 100644
--- a/frmts/gxf/Doxyfile
+++ b/frmts/gxf/Doxyfile
@@ -10,19 +10,19 @@
 #---------------------------------------------------------------------------
 
 # The PROJECT_NAME tag is a single word (or a sequence of word surrounded
-# by quotes) that should identify the project. 
+# by quotes) that should identify the project.
 
 PROJECT_NAME         =	GXF
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or 
+# This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER       =	
+PROJECT_NUMBER       =
 
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
 # where doxygen was started. If left blank the current directory will be used.
 
 OUTPUT_DIRECTORY     =
@@ -39,14 +39,14 @@ HTML_OUTPUT          =
 
 LATEX_OUTPUT          =
 
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard header.
 
 HTML_HEADER          =
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard footer.
 
 HTML_FOOTER          =
@@ -94,7 +94,7 @@ GENERATE_LATEX       = NO
 GENERATE_HTML        = YES
 
 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in 
+# include brief member descriptions after the members that are listed in
 # the file and class documentation (similar to JavaDoc).
 # Set to NO to disable this.
 
@@ -110,22 +110,22 @@ FULL_PATH_NAMES = NO
 # configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag is used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
 INPUT            =	gxfopen.c gxfopen.h gxf_proj4.c gxf.dox gxf_ogcwkt.c
 
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
 # blank all files are included.
 
 FILE_PATTERNS    =	*.*
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
 # the \include command).
 
 EXAMPLE_PATH     = .
@@ -137,16 +137,16 @@ EXAMPLE_PATH     = .
 RECURSIVE        = NO
 
 # The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program 
+# invoke to filter for each input file. Doxygen will invoke the filter program
 # by executing (via popen()) the command <filter> <input-file>, where <filter>
 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an
 # input file. Doxygen will then use the output that the filter program writes
 # to standard output.
 
-INPUT_FILTER     = 
+INPUT_FILTER     =
 
 #---------------------------------------------------------------------------
-# Configuration options related to the preprocessor 
+# Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
 # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
@@ -156,7 +156,7 @@ INPUT_FILTER     =
 ENABLE_PREPROCESSING = YES
 
 # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional 
+# names in the source code. If set to NO (the default) only conditional
 # compilation will be performed.
 
 MACRO_EXPANSION = NO
@@ -187,10 +187,10 @@ PREDEFINED =
 EXPAND_ONLY_PREDEF = NO
 
 #---------------------------------------------------------------------------
-# Configuration options related to external references 
+# Configuration options related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES tag can be used to specify one or more tagfiles. 
+# The TAGFILES tag can be used to specify one or more tagfiles.
 
 TAGFILES         =
 
@@ -211,10 +211,10 @@ ALLEXTERNALS     = NO
 PERL_PATH        = /usr/local/bin/perl
 
 #---------------------------------------------------------------------------
-# Configuration options related to the search engine 
+# Configuration options related to the search engine
 #---------------------------------------------------------------------------
 
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# The SEARCHENGINE tag specifies whether or not a search engine should be
 # used. If set to NO the values of all tags below this one will be ignored.
 
 SEARCHENGINE     = NO
@@ -226,13 +226,13 @@ SEARCHENGINE     = NO
 CGI_NAME         = search.cgi
 
 # The CGI_URL tag should be the absolute URL to the directory where the
-# cgi binaries are located. See the documentation of your http daemon for 
+# cgi binaries are located. See the documentation of your http daemon for
 # details.
 
 CGI_URL          =
 
 # The DOC_URL tag should be the absolute URL to the directory where the
-# documentation is located. If left blank the absolute path to the 
+# documentation is located. If left blank the absolute path to the
 # documentation, with file:// prepended to it, will be used.
 
 DOC_URL          =
@@ -248,7 +248,7 @@ DOC_ABSPATH      =
 
 BIN_ABSPATH      = /usr/local/bin/
 
-# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
 # documentation generated for other projects. This allows doxysearch to search
 # the documentation for these projects as well.
 
diff --git a/frmts/gxf/GNUmakefile b/frmts/gxf/GNUmakefile
index 4bdf883..b446ec7 100644
--- a/frmts/gxf/GNUmakefile
+++ b/frmts/gxf/GNUmakefile
@@ -22,7 +22,7 @@ gxftest$(EXE):	gxftest.$(OBJ_EXT)
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
 
 $(SHARED_LIB):	$(OBJ)
-	$(LD_SHARED) $(OBJ) $(GDAL_SLIB_LINK) $(LIBS) -o $(SHARED_LIB) 
+	$(LD_SHARED) $(OBJ) $(GDAL_SLIB_LINK) $(LIBS) -o $(SHARED_LIB)
 
 install-lib:	$(SHARED_LIB)
 	cp $(SHARED_LIB) ../../lib
diff --git a/frmts/gxf/README b/frmts/gxf/README
index eead1e8..a716570 100644
--- a/frmts/gxf/README
+++ b/frmts/gxf/README
@@ -3,7 +3,7 @@ Notes
 
 Gilles Clement of Global Geomatics approved this support library
 for general OpenSource release six months after it was released
-as part of OGDI.  This should be approximately September of 1999. 
+as part of OGDI.  This should be approximately September of 1999.
 
 
 GXF Irregularities
@@ -13,12 +13,12 @@ GXF Irregularities
    example files it has spaces.  Treating both the same.
 
  o The document doesn't mention it, but it seems that the first five
-   characters have to be taken as sufficient for a field name.  For 
+   characters have to be taken as sufficient for a field name.  For
    instance the old sample file I have has only #TITL for the title,
-   while new ones have #TITLE. 
+   while new ones have #TITLE.
 
  o It seems according to the documentation that Geographic projected
-   files should list "Geographic" as their projection method, but 
+   files should list "Geographic" as their projection method, but
    samples seem to just skip the third line of the map projection
    definition.
 
@@ -38,28 +38,28 @@ GG GeoTIFF Irregularities
  o LCC_1SP seems to ignore the scale factor at natural origin parameter.
    (ProjScaleAtNatOriginGeoKey) (should be +k= in PROJ.4).
 
- o 1SP form of LCC doesn't seem to have an analog in PROJ.4 -- 
+ o 1SP form of LCC doesn't seem to have an analog in PROJ.4 --
    I have transformed the Longitude of Natural Origin as +lon_0, and the
    scale as +k, but it isn't clear that the scale parameter is really
-   used for +proj=lcc, at least according to the documentation.  
+   used for +proj=lcc, at least according to the documentation.
    This _isn't_ done by the GG Geotiff translator.
 
  o the PROJ.4 Oblique Mercator support doesn't (apparently) include
    support for an ``Angle from Rectified to Skew Grid'' though via the
    the +no_rot flag it seems possible to choose between having this
    angle be zero or -azimuth.  Currently I am just using the angle
-   to decide if +no_rot should be set. 
+   to decide if +no_rot should be set.
 
- o The Polar Stereographic projection in GeoTIFF is translated to 
+ o The Polar Stereographic projection in GeoTIFF is translated to
    +proj=ups, ignoring any other polar stereographic parameters.  This
    would appear to be an error.  For the time being I am translating as
    Stereographic.
 
  o It appears that PROJ.4's polyconic projection doesn't include support
-   for the scale at the origin (presumably 1.0). 
+   for the scale at the origin (presumably 1.0).
+
 
 
 
 
-	
 
diff --git a/frmts/gxf/gxf.dox b/frmts/gxf/gxf.dox
index 0e525f5..690bd1e 100644
--- a/frmts/gxf/gxf.dox
+++ b/frmts/gxf/gxf.dox
@@ -7,16 +7,16 @@
 <h2>Introduction</h2>
 
 The GXF-3 library is intended to make correct implementation of GXF-3 file
-format readers easy.  It consists of free (OpenSource) C source code for 
-functions to read GXF-3 raster files, and an example program using them to 
+format readers easy.  It consists of free (OpenSource) C source code for
+functions to read GXF-3 raster files, and an example program using them to
 convert GXF data to GeoTIFF format.<p>
 
-GXF (Grid eXchange File) is a standard ASCII file format for exchanging 
-gridded data among different software systems. Software that supports the 
-GXF standard will be able to import properly formatted GXF files and export 
+GXF (Grid eXchange File) is a standard ASCII file format for exchanging
+gridded data among different software systems. Software that supports the
+GXF standard will be able to import properly formatted GXF files and export
 grids in GXF format.  GXF-3 is an adopted standard format of the
 Gravity/Magnetics Committee of the Society of Exploration Geophysicists (SEG).
-GXF-3 is the primary gridded data interchange format for 
+GXF-3 is the primary gridded data interchange format for
 <a href="http://www.Geosoft.com/">Geosoft</a>.<p>
 
 <h2>Resources</h2>
@@ -61,18 +61,18 @@ The precise license text is:<p>
 
 <h2>Building the Source</h2>
 
-Unix developers should be able to unpack the .tar.gz file, run configure, 
+Unix developers should be able to unpack the .tar.gz file, run configure,
 and type make to build the library (libgxf3.a), and a simple test program
 (gxftest.c).<p>
 
-Windows developers should unpack the .zip file, and type 
+Windows developers should unpack the .zip file, and type
 <tt>nmake /f makefile.vc</tt> to build with VC++. <p>
 
 <h2>Author and Acknowledgements</h2>
 
-The primary author of the GXF3 library is 
-<a href="http://pobox.com/warmerdam">Frank Warmerdam</a>, 
-and I can be reached at 
+The primary author of the GXF3 library is
+<a href="http://pobox.com/warmerdam">Frank Warmerdam</a>,
+and I can be reached at
 <a href="mailto:warmerdam at pobox.com">warmerdam at pobox.com</a>.  I am open to
 bug reports, and suggestions.<p>
 
@@ -80,7 +80,7 @@ I would like to thank:<p>
 
 <ul>
 <li> <a href="http://www.globalgeo.com/">Global Geomatics</a>
-who funded development the majority of the work on this library, 
+who funded development the majority of the work on this library,
 and agreed for it to be Open Source.<p>
 
 <li> Ian Macleod of Geosoft who answered a number of questions I had,
diff --git a/frmts/gxf/gxf_ogcwkt.c b/frmts/gxf/gxf_ogcwkt.c
index 04cc175..9d1a1fe 100644
--- a/frmts/gxf/gxf_ogcwkt.c
+++ b/frmts/gxf/gxf_ogcwkt.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxf_ogcwkt.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: gxf_ogcwkt.c 36380 2016-11-21 10:21:20Z rouault $
  *
  * Project:  GXF Reader
  * Purpose:  Handle GXF to OGC WKT projection transformation.
@@ -31,7 +31,7 @@
 #include "gxfopen.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: gxf_ogcwkt.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gxf_ogcwkt.c 36380 2016-11-21 10:21:20Z rouault $");
 
 /* -------------------------------------------------------------------- */
 /* the following #defines come from ogr_spatialref.h in the GDAL/OGR	*/
@@ -207,7 +207,7 @@ static void OGCWKTSetProj( char * pszProjection,
 
 {
     int		iParm, nCount = CSLCount(papszMethods);
-    const char	*apszParmNames[8];
+    const char	*apszParmNames[8] = { NULL };
 
     apszParmNames[0] = pszParm1;
     apszParmNames[1] = pszParm2;
diff --git a/frmts/gxf/gxf_proj4.c b/frmts/gxf/gxf_proj4.c
index 915f0aa..bd7952e 100644
--- a/frmts/gxf/gxf_proj4.c
+++ b/frmts/gxf/gxf_proj4.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxf_proj4.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: gxf_proj4.c 36380 2016-11-21 10:21:20Z rouault $
  *
  * Project:  GXF Reader
  * Purpose:  Handle GXF to PROJ.4 projection transformation.
@@ -30,7 +30,7 @@
 
 #include "gxfopen.h"
 
-CPL_CVSID("$Id: gxf_proj4.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gxf_proj4.c 36380 2016-11-21 10:21:20Z rouault $");
 
 
 #define SAFE_strcat(x,y) snprintf(x + strlen(x),sizeof(x) - strlen(x), "%s", y)
@@ -75,7 +75,7 @@ char *GXFGetMapProjectionAsPROJ4( GXFHandle hGXF )
 {
     GXFInfo_t	*psGXF = (GXFInfo_t *) hGXF;
     char	**papszMethods = NULL;
-    char	szPROJ4[512];
+    char	szPROJ4[512] = { 0 };
 
 /* -------------------------------------------------------------------- */
 /*      If there was nothing in the file return "unknown".              */
@@ -83,8 +83,6 @@ char *GXFGetMapProjectionAsPROJ4( GXFHandle hGXF )
     if( CSLCount(psGXF->papszMapProjection) < 2 )
         return( CPLStrdup( "unknown" ) );
 
-    szPROJ4[0] = '\0';
-
 /* -------------------------------------------------------------------- */
 /*      Parse the third line, looking for known projection methods.     */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/gxf/gxfdataset.cpp b/frmts/gxf/gxfdataset.cpp
index 8ca0780..fec96ec 100644
--- a/frmts/gxf/gxfdataset.cpp
+++ b/frmts/gxf/gxfdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gxfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GXF Reader
  * Purpose:  GDAL binding for GXF reader.
@@ -32,11 +31,11 @@
 #include "gdal_pam.h"
 #include "gxfopen.h"
 
-CPL_CVSID("$Id: gxfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gxfdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GXFDataset				*/
+/*                              GXFDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -46,20 +45,20 @@ class GXFDataset : public GDALPamDataset
 {
     friend class GXFRasterBand;
 
-    GXFHandle	hGXF;
+    GXFHandle   hGXF;
 
-    char	*pszProjection;
+    char        *pszProjection;
     double      dfNoDataValue;
     GDALDataType eDataType;
 
   public:
                 GXFDataset();
-		~GXFDataset();
+                ~GXFDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
 
-    CPLErr 	GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
 /************************************************************************/
@@ -74,13 +73,12 @@ class GXFRasterBand : public GDALPamRasterBand
 
   public:
 
-    		GXFRasterBand( GXFDataset *, int );
-    double      GetNoDataValue(int* bGotNoDataValue);
+                GXFRasterBand( GXFDataset *, int );
+    double      GetNoDataValue( int* bGotNoDataValue ) override;
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                           GXFRasterBand()                            */
 /************************************************************************/
@@ -104,13 +102,13 @@ GXFRasterBand::GXFRasterBand( GXFDataset *poDSIn, int nBandIn )
 double GXFRasterBand::GetNoDataValue(int* bGotNoDataValue)
 
 {
-    GXFDataset	*poGXF_DS = (GXFDataset *) poDS;
-    if (bGotNoDataValue)
+    GXFDataset *poGXF_DS = (GXFDataset *) poDS;
+    if( bGotNoDataValue )
         *bGotNoDataValue = (fabs(poGXF_DS->dfNoDataValue - -1e12) > .1);
-    if (eDataType == GDT_Float32)
+    if( eDataType == GDT_Float32 )
         return (double)(float)poGXF_DS->dfNoDataValue;
-    else
-        return poGXF_DS->dfNoDataValue;
+
+    return poGXF_DS->dfNoDataValue;
 }
 
 /************************************************************************/
@@ -121,37 +119,36 @@ CPLErr GXFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                   int nBlockYOff,
                                   void * pImage )
 {
-    GXFDataset	*poGXF_DS = (GXFDataset *) poDS;
-    double	*padfBuffer;
-    float	*pafBuffer = (float *) pImage;
-    int		i;
-    CPLErr	eErr;
+    GXFDataset * const poGXF_DS = (GXFDataset *) poDS;
 
-    CPLAssert( nBlockXOff == 0 );
-
-    if (eDataType == GDT_Float32)
+    if( eDataType == GDT_Float32)
     {
-        padfBuffer = (double *) VSIMalloc2(sizeof(double), nBlockXSize);
-        if( padfBuffer == NULL )
-            return CE_Failure;
-        eErr = GXFGetScanline( poGXF_DS->hGXF, nBlockYOff, padfBuffer );
+       double *padfBuffer = (double *) VSIMalloc2(sizeof(double), nBlockXSize);
+       if( padfBuffer == NULL )
+           return CE_Failure;
+       const CPLErr eErr =
+           GXFGetScanline( poGXF_DS->hGXF, nBlockYOff, padfBuffer );
+
+       float *pafBuffer = (float *) pImage;
+       for( int i = 0; i < nBlockXSize; i++ )
+           pafBuffer[i] = (float) padfBuffer[i];
 
-        for( i = 0; i < nBlockXSize; i++ )
-            pafBuffer[i] = (float) padfBuffer[i];
+       CPLFree( padfBuffer );
 
-        CPLFree( padfBuffer );
+       return eErr;
     }
-    else if (eDataType == GDT_Float64)
-        eErr = GXFGetScanline( poGXF_DS->hGXF, nBlockYOff, (double*)pImage );
-    else
-        eErr = CE_Failure;
+
+    const CPLErr eErr =
+        eDataType == GDT_Float64
+        ? GXFGetScanline( poGXF_DS->hGXF, nBlockYOff, (double*)pImage )
+        : CE_Failure;
 
     return eErr;
 }
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GXFDataset				*/
+/*                              GXFDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -159,14 +156,12 @@ CPLErr GXFRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                             GXFDataset()                             */
 /************************************************************************/
 
-GXFDataset::GXFDataset()
-
-{
-    pszProjection = NULL;
-    hGXF = NULL;
-    dfNoDataValue = 0;
-    eDataType = GDT_Float32;
-}
+GXFDataset::GXFDataset() :
+    hGXF(NULL),
+    pszProjection(NULL),
+    dfNoDataValue(0),
+    eDataType(GDT_Float32)
+{}
 
 /************************************************************************/
 /*                            ~GXFDataset()                             */
@@ -181,7 +176,6 @@ GXFDataset::~GXFDataset()
     CPLFree( pszProjection );
 }
 
-
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
@@ -189,17 +183,21 @@ GXFDataset::~GXFDataset()
 CPLErr GXFDataset::GetGeoTransform( double * padfTransform )
 
 {
-    CPLErr	eErr;
-    double	dfXOrigin, dfYOrigin, dfXSize, dfYSize, dfRotation;
+    double dfXOrigin = 0.0;
+    double dfYOrigin = 0.0;
+    double dfXSize = 0.0;
+    double dfYSize = 0.0;
+    double dfRotation = 0.0;
 
-    eErr = GXFGetPosition( hGXF, &dfXOrigin, &dfYOrigin,
-                           &dfXSize, &dfYSize, &dfRotation );
+    const CPLErr eErr =
+        GXFGetPosition( hGXF, &dfXOrigin, &dfYOrigin,
+                        &dfXSize, &dfYSize, &dfRotation );
 
     if( eErr != CE_None )
         return eErr;
 
     // Transform to radians.
-    dfRotation = (dfRotation / 360.0) * 2 * M_PI;
+    dfRotation = (dfRotation / 360.0) * 2.0 * M_PI;
 
     padfTransform[1] = dfXSize * cos(dfRotation);
     padfTransform[2] = dfYSize * sin(dfRotation);
@@ -220,7 +218,7 @@ CPLErr GXFDataset::GetGeoTransform( double * padfTransform )
 const char *GXFDataset::GetProjectionRef()
 
 {
-    return( pszProjection );
+    return pszProjection;
 }
 
 /************************************************************************/
@@ -230,9 +228,6 @@ const char *GXFDataset::GetProjectionRef()
 GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    GXFHandle	l_hGXF;
-    int		i, bFoundKeyword, bFoundIllegal;
-
 /* -------------------------------------------------------------------- */
 /*      Before trying GXFOpen() we first verify that there is at        */
 /*      least one "\n#keyword" type signature in the first chunk of     */
@@ -241,25 +236,28 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 50 )
         return NULL;
 
-    bFoundKeyword = FALSE;
-    bFoundIllegal = FALSE;
-    for( i = 0; i < poOpenInfo->nHeaderBytes-1; i++ )
+    bool bFoundKeyword = false;
+    bool bFoundIllegal = false;
+    for( int i = 0; i < poOpenInfo->nHeaderBytes-1; i++ )
     {
         if( (poOpenInfo->pabyHeader[i] == 10
              || poOpenInfo->pabyHeader[i] == 13)
             && poOpenInfo->pabyHeader[i+1] == '#' )
         {
-            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "include") )
+            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2,
+                            "include") )
                 return NULL;
-            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "define") )
+            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2,
+                            "define") )
                 return NULL;
-            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "ifdef") )
+            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2,
+                            "ifdef") )
                 return NULL;
-            bFoundKeyword = TRUE;
+            bFoundKeyword = true;
         }
         if( poOpenInfo->pabyHeader[i] == 0 )
         {
-            bFoundIllegal = TRUE;
+            bFoundIllegal = true;
             break;
         }
     }
@@ -272,19 +270,19 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      we also now verify that there is a #GRID keyword before         */
 /*      passing it off to GXFOpen().  We check in the first 50K.        */
 /* -------------------------------------------------------------------- */
-#define BIGBUFSIZE 50000
-    int nBytesRead, bGotGrid = FALSE;
-    FILE *fp;
-
-    fp = VSIFOpen( poOpenInfo->pszFilename, "rb" );
+    FILE *fp = VSIFOpen( poOpenInfo->pszFilename, "rb" );
     if( fp == NULL )
         return NULL;
 
+    const size_t BIGBUFSIZE = 50000;
     char *pszBigBuf = (char *) CPLMalloc(BIGBUFSIZE);
-    nBytesRead = static_cast<int>(VSIFRead( pszBigBuf, 1, BIGBUFSIZE, fp ));
+    const int nBytesRead =
+        static_cast<int>(VSIFRead( pszBigBuf, 1, BIGBUFSIZE, fp ));
     VSIFClose( fp );
 
-    for( i = 0; i < nBytesRead - 5 && !bGotGrid; i++ )
+    bool bGotGrid = false;
+
+    for( int i = 0; i < nBytesRead - 5 && !bGotGrid; i++ )
     {
         if( pszBigBuf[i] == '#' && STARTS_WITH_CI(pszBigBuf+i+1, "GRID") )
             bGotGrid = TRUE;
@@ -299,10 +297,10 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
 
-    l_hGXF = GXFOpen( poOpenInfo->pszFilename );
+    GXFHandle l_hGXF = GXFOpen( poOpenInfo->pszFilename );
 
     if( l_hGXF == NULL )
-        return( NULL );
+        return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
@@ -312,20 +310,18 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
         GXFClose(l_hGXF);
         CPLError( CE_Failure, CPLE_NotSupported,
                   "The GXF driver does not support update access to existing"
-                  " datasets.\n" );
+                  " datasets." );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    GXFDataset 	*poDS;
-
-    poDS = new GXFDataset();
+    GXFDataset *poDS = new GXFDataset();
 
     const char* pszGXFDataType = CPLGetConfigOption("GXF_DATATYPE", "Float32");
     GDALDataType eDT = GDALGetDataTypeByName(pszGXFDataType);
-    if (!(eDT == GDT_Float32 || eDT == GDT_Float64))
+    if( !(eDT == GDT_Float32 || eDT == GDT_Float64) )
     {
         CPLError(CE_Warning, CPLE_NotSupported,
                  "Unsupported value for GXF_DATATYPE : %s", pszGXFDataType);
@@ -336,7 +332,7 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->eDataType = eDT;
 
 /* -------------------------------------------------------------------- */
-/*	Establish the projection.					*/
+/*      Establish the projection.                                       */
 /* -------------------------------------------------------------------- */
     poDS->pszProjection = GXFGetMapProjectionAsOGCWKT( l_hGXF );
 
@@ -346,7 +342,7 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
     GXFGetRawInfo( l_hGXF, &(poDS->nRasterXSize), &(poDS->nRasterYSize), NULL,
                    NULL, NULL, &(poDS->dfNoDataValue) );
 
-    if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
+    if( poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid dimensions : %d x %d",
@@ -370,9 +366,10 @@ GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
+                                 poOpenInfo->GetSiblingFiles() );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/gxf/gxfopen.c b/frmts/gxf/gxfopen.c
index b0de5a7..f291b5b 100644
--- a/frmts/gxf/gxfopen.c
+++ b/frmts/gxf/gxfopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxfopen.c 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: gxfopen.c 36436 2016-11-22 21:41:51Z rouault $
  *
  * Project:  GXF Reader
  * Purpose:  Majority of Geosoft GXF reading code.
@@ -29,10 +29,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+
 #include <ctype.h>
 #include "gxfopen.h"
 
-CPL_CVSID("$Id: gxfopen.c 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gxfopen.c 36436 2016-11-22 21:41:51Z rouault $");
 
 
 /* this is also defined in gdal.h which we avoid in this separable component */
@@ -44,7 +46,7 @@ CPL_CVSID("$Id: gxfopen.c 33720 2016-03-15 00:39:53Z goatbar $");
 /************************************************************************/
 /*                         GXFReadHeaderValue()                         */
 /*                                                                      */
-/*      Read one entry from the file header, and return it and it's     */
+/*      Read one entry from the file header, and return it and its      */
 /*      value in clean form.                                            */
 /************************************************************************/
 
@@ -72,7 +74,7 @@ static char **GXFReadHeaderValue( FILE * fp, char * pszHTitle )
 /*      Extract the title.  It should be terminated by some sort of     */
 /*      white space.                                                    */
 /* -------------------------------------------------------------------- */
-    for( i = 0; !isspace((unsigned char)pszLine[i]) && pszLine[i] != '\0' && i < 70; i++ ) {}
+    for( i = 0; i < 70 && !isspace((unsigned char)pszLine[i]) && pszLine[i] != '\0'; i++ ) {}
 
     strncpy( pszHTitle, pszLine, i );
     pszHTitle[i] = '\0';
diff --git a/frmts/gxf/gxfopen.h b/frmts/gxf/gxfopen.h
index 8aa1251..cd9a042 100644
--- a/frmts/gxf/gxfopen.h
+++ b/frmts/gxf/gxfopen.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gxfopen.h 32179 2015-12-14 16:22:34Z goatbar $
+ * $Id: gxfopen.h 35335 2016-09-05 20:18:57Z goatbar $
  *
  * Project:  GXF Reader
  * Purpose:  GXF-3 access function declarations.
@@ -57,10 +57,10 @@ CPLErr   GXFGetInfo( GXFHandle hGXF, int *pnXSize, int *pnYSize );
 CPLErr   GXFGetRawScanline( GXFHandle, int iScanline, double * padfLineBuf );
 CPLErr   GXFGetScanline( GXFHandle, int iScanline, double * padfLineBuf );
 
-char	**GXFGetMapProjection( GXFHandle );
-char	**GXFGetMapDatumTransform( GXFHandle );
-char	*GXFGetMapProjectionAsPROJ4( GXFHandle );
-char	*GXFGetMapProjectionAsOGCWKT( GXFHandle );
+char    **GXFGetMapProjection( GXFHandle );
+char    **GXFGetMapDatumTransform( GXFHandle );
+char    *GXFGetMapProjectionAsPROJ4( GXFHandle );
+char    *GXFGetMapProjectionAsOGCWKT( GXFHandle );
 
 CPLErr  GXFGetRawPosition( GXFHandle, double *, double *, double *, double *,
                            double * );
@@ -72,14 +72,14 @@ CPLErr  GXFGetPROJ4Position( GXFHandle, double *, double *, double *, double *,
 
 void     GXFClose( GXFHandle hGXF );
 
-#define GXFS_LL_UP	-1
-#define GXFS_LL_RIGHT	1
-#define GXFS_UL_RIGHT	-2
-#define GXFS_UL_DOWN	2
-#define GXFS_UR_DOWN	-3
-#define GXFS_UR_LEFT	3
-#define GXFS_LR_LEFT	-4
-#define GXFS_LR_UP	4
+#define GXFS_LL_UP      -1
+#define GXFS_LL_RIGHT   1
+#define GXFS_UL_RIGHT   -2
+#define GXFS_UL_DOWN    2
+#define GXFS_UR_DOWN    -3
+#define GXFS_UR_LEFT    3
+#define GXFS_LR_LEFT    -4
+#define GXFS_LR_UP      4
 
 CPL_C_END
 
@@ -87,38 +87,38 @@ CPL_C_END
 /*      This is consider to be a private structure.                     */
 /* -------------------------------------------------------------------- */
 typedef struct {
-    FILE	*fp;
+    FILE        *fp;
 
-    int		nRawXSize;
-    int		nRawYSize;
-    int		nSense;		/* GXFS_ codes */
-    int		nGType;		/* 0 is uncompressed */
+    int         nRawXSize;
+    int         nRawYSize;
+    int         nSense;         /* GXFS_ codes */
+    int         nGType;         /* 0 is uncompressed */
 
-    double	dfXPixelSize;
-    double	dfYPixelSize;
-    double	dfRotation;
-    double	dfXOrigin;	/* lower left corner */
-    double	dfYOrigin;	/* lower left corner */
+    double      dfXPixelSize;
+    double      dfYPixelSize;
+    double      dfRotation;
+    double      dfXOrigin;      /* lower left corner */
+    double      dfYOrigin;      /* lower left corner */
 
-    char	szDummy[64];
-    double	dfSetDummyTo;
+    char        szDummy[64];
+    double      dfSetDummyTo;
 
-    char	*pszTitle;
+    char        *pszTitle;
 
-    double	dfTransformScale;
-    double	dfTransformOffset;
-    char	*pszTransformName;
+    double      dfTransformScale;
+    double      dfTransformOffset;
+    char        *pszTransformName;
 
-    char	**papszMapProjection;
-    char	**papszMapDatumTransform;
+    char        **papszMapProjection;
+    char        **papszMapDatumTransform;
 
-    char	*pszUnitName;
-    double	dfUnitToMeter;
+    char        *pszUnitName;
+    double      dfUnitToMeter;
 
-    double	dfZMaximum;
-    double	dfZMinimum;
+    double      dfZMaximum;
+    double      dfZMinimum;
 
-    long	*panRawLineOffset;
+    long        *panRawLineOffset;
 } GXFInfo_t;
 
 #endif /* ndef GXFOPEN_H_INCLUDED */
diff --git a/frmts/hdf4/hdf-eos/GDapi.c b/frmts/hdf4/hdf-eos/GDapi.c
index 58adbf9..2cf8b79 100644
--- a/frmts/hdf4/hdf-eos/GDapi.c
+++ b/frmts/hdf4/hdf-eos/GDapi.c
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: GDapi.c 33123 2016-01-23 18:59:28Z rouault $
+ * $Id: GDapi.c 36456 2016-11-22 23:34:00Z rouault $
  *
  * This module has a number of additions and improvements over the original
  * implementation to be suitable for usage in GDAL HDF driver.
@@ -6169,7 +6169,7 @@ GDgetdefaults(int32 projcode, int32 zonecode, float64 projparm[],
 	 * format.
 	 */
 	plon = EHconvAng(projparm[4], HDFE_DMS_DEG);
-	plat = EHconvAng(projparm[5], HDFE_DMS_DEG);
+	/*plat = EHconvAng(projparm[5], HDFE_DMS_DEG); */
 
 	/*
 	 * Compute the longitudes at 90, 180 and 270 degrees from the central
diff --git a/frmts/hdf4/hdf-eos/HDFEOSVersion.h b/frmts/hdf4/hdf-eos/HDFEOSVersion.h
index e9ea958..6d316c9 100644
--- a/frmts/hdf4/hdf-eos/HDFEOSVersion.h
+++ b/frmts/hdf4/hdf-eos/HDFEOSVersion.h
@@ -6,13 +6,13 @@
 #define  HDFEOSd_BANNER  "@(#)## =================  HDFEOS  ================"
 #ifdef __GNUC__
 #define  HDFEOSd_HDFEOS_VER  "@(#)## HDFEOS Version: "HDFEOSVERSION1
-#define  HDFEOSd_DATE    "@(#)## Build date: "__DATE__" @ "__TIME__
+/* #define  HDFEOSd_DATE    "@(#)## Build date: "__DATE__" @ "__TIME__ */
 #else
 #define  HDFEOSd_HDFEOS_VER  "@(#)## HDFEOS Version: "##HDFEOSVERSION1
-#define  HDFEOSd_DATE    "@(#)## Build date: "##__DATE__##" @ "##__TIME__
+/* #define  HDFEOSd_DATE    "@(#)## Build date: "##__DATE__##" @ "##__TIME__ */
 #endif
  
 const char *hdfeosg_LibraryVersionString01 = HDFEOSd_BANNER;
 const char *hdfeosg_LibraryVersionString02 = HDFEOSd_HDFEOS_VER;
-const char *hdfeosg_LibraryVersionString03 = HDFEOSd_DATE;
+/*const char *hdfeosg_LibraryVersionString03 = HDFEOSd_DATE; */
 const char *hdfeosg_LibraryVersionString04 = HDFEOSd_BANNER;
diff --git a/frmts/hdf4/hdf-eos/SWapi.c b/frmts/hdf4/hdf-eos/SWapi.c
index 6765694..2267984 100644
--- a/frmts/hdf4/hdf-eos/SWapi.c
+++ b/frmts/hdf4/hdf-eos/SWapi.c
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: SWapi.c 32805 2016-01-07 19:53:43Z rouault $
+ * $Id: SWapi.c 36473 2016-11-23 16:43:20Z rouault $
  *
  * This module has a number of additions and improvements over the original
  * implementation to be suitable for usage in GDAL HDF driver.
@@ -75,6 +75,8 @@ June 05, 2003 Abe Taaheri / Bruce Beaumont
 ******************************************************************************/
 
 #include "cpl_port.h" /* for M_PI */
+#include "cpl_string.h" /* for CPLsnprintf */
+
 #include "mfhdf.h"
 #include "hcomp.h"
 #include "HdfEosDef.h"
@@ -199,14 +201,14 @@ static intn SWscan2longlat(int32, char *, VOIDP, int32 [], int32 [],
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
 int32
-SWopen(char *filename, intn access)
+SWopen(char *filename, intn i_access)
 
 {
     int32           fid /* HDF-EOS file ID */ ;
 
     /* Call EHopen to perform file access */
     /* ---------------------------------- */
-    fid = EHopen(filename, access);
+    fid = EHopen(filename, i_access);
 
     return (fid);
 }
@@ -249,7 +251,7 @@ SWcreate(int32 fid, char *swathname)
     intn            nswathopen = 0;	/* # of swath structures open */
     intn            status = 0;	/* routine return status variable */
 
-    uint8           access;	/* Read/Write file access code */
+    uint8           l_access;	/* Read/Write file access code */
 
     int32           HDFfid;	/* HDF file id */
     int32           vgRef;	/* Vgroup reference number */
@@ -270,7 +272,7 @@ SWcreate(int32 fid, char *swathname)
      * Check HDF-EOS file ID, get back HDF file ID, SD interface ID  and
      * access code
      */
-    status = EHchkfid(fid, swathname, &HDFfid, &sdInterfaceID, &access);
+    status = EHchkfid(fid, swathname, &HDFfid, &sdInterfaceID, &l_access);
 
 
     /* Check swathname for length */
@@ -402,7 +404,7 @@ SWcreate(int32 fid, char *swathname)
 		strcat(utlbuf, "\t\tEND_GROUP=DataField\n");
 		strcat(utlbuf, "\t\tGROUP=MergedFields\n");
 		strcat(utlbuf, "\t\tEND_GROUP=MergedFields\n");
-		snprintf(utlbuf2, sizeof(utlbuf2), "%s%ld%s",
+		CPLsnprintf(utlbuf2, sizeof(utlbuf2), "%s%ld%s",
 			"\tEND_GROUP=SWATH_", (long)nSwath + 1, "\n");
 		strcat(utlbuf, utlbuf2);
 
@@ -821,7 +823,7 @@ SWchkswid(int32 swathID, char *routname,
 
 {
     intn            status = 0;	/* routine return status variable */
-    uint8           access;	/* Read/Write access code */
+    uint8           l_access;	/* Read/Write access code */
 
     int32           idOffset = SWIDOFFSET;	/* Swath ID offset */
 
@@ -855,7 +857,7 @@ SWchkswid(int32 swathID, char *routname,
 	    /* Get file & SDS ids and Swath Vgroup */
 	    /* ----------------------------------- */
 	    status = EHchkfid(SWXSwath[swathID % idOffset].fid, " ", fid,
-			      sdInterfaceID, &access);
+			      sdInterfaceID, &l_access);
 	    *swVgrpID = SWXSwath[swathID % idOffset].IDTable;
 	}
     }
@@ -1262,7 +1264,7 @@ SWidxmapinfo(int32 swathID, char *geodim, char *datadim, int32 l_index[])
 	}
 	else
 	{
-	    status = -1;
+	    /*status = -1;*/
 	    HEpush(DFE_GENAPP, "SWidxmapinfo", __FILE__, __LINE__);
 	    HEreport("Index Mapping \"%s\" not found.\n", utlbuf);
 	}
@@ -4399,7 +4401,7 @@ SWinqswath(char *filename, char *swathlist, int32 * strbufsize)
 |  END_PROLOG                                                                 |
 -----------------------------------------------------------------------------*/
 static intn
-SW1dfldsrch(int32 fid, int32 swathID, const char *fieldname, const char *access,
+SW1dfldsrch(int32 fid, int32 swathID, const char *fieldname, const char *i_access,
 	    int32 * vgidout, int32 * vdataIDout, int32 * fldtype)
 
 {
@@ -4419,7 +4421,7 @@ SW1dfldsrch(int32 fid, int32 swathID, const char *fieldname, const char *access,
     /* Get Geolocation Vgroup id and 1D field name Vdata id */
     /* ---------------------------------------------------- */
     vgid = SWXSwath[sID].VIDTable[0];
-    vdataID = EHgetid(fid, vgid, fieldname, 1, access);
+    vdataID = EHgetid(fid, vgid, fieldname, 1, i_access);
     *fldtype = 0;
 
 
@@ -4430,7 +4432,7 @@ SW1dfldsrch(int32 fid, int32 swathID, const char *fieldname, const char *access,
     if (vdataID == -1)
     {
 	vgid = SWXSwath[sID].VIDTable[1];;
-	vdataID = EHgetid(fid, vgid, fieldname, 1, access);
+	vdataID = EHgetid(fid, vgid, fieldname, 1, i_access);
 	*fldtype = 1;
 
 	/* If field also not found in Data Vgroup then set error status */
@@ -5029,8 +5031,7 @@ SWwrrdfield(int32 swathID, const char *fieldname, const char *code,
 
 		    /* Fill buffer with "Fill" value (if any) */
 		    /* -------------------------------------- */
-		    strncpy(attrName, "_FV_", 80);
-		    strcat(attrName, fieldname);
+                    snprintf( attrName, sizeof(attrName), "_FV_%s", fieldname);
 
 		    status = SWreadattr(swathID, attrName, (char *) fillbuf);
 		    if (status == 0)
diff --git a/frmts/hdf4/hdf-eos/makefile.vc b/frmts/hdf4/hdf-eos/makefile.vc
index 5dfe538..acc8a36 100644
--- a/frmts/hdf4/hdf-eos/makefile.vc
+++ b/frmts/hdf4/hdf-eos/makefile.vc
@@ -6,7 +6,7 @@ GDAL_ROOT	=	..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS = 	-I$(HDF4_DIR)\include -I.\ -I..\ -DFRMT_hdf4 -DWIN32
+EXTRAFLAGS = 	-I$(HDF4_INCLUDE) -I$(HDF4_DIR)\include -I.\ -I..\ -DFRMT_hdf4 -DWIN32
 
 !IF "$(HDF4_HAS_MAXOPENFILES)" == "YES"
 EXTRAFLAGS = $(EXTRAFLAGS) -DHDF4_HAS_MAXOPENFILES
diff --git a/frmts/hdf4/hdf4dataset.cpp b/frmts/hdf4/hdf4dataset.cpp
index 0b390a6..92e845f 100644
--- a/frmts/hdf4/hdf4dataset.cpp
+++ b/frmts/hdf4/hdf4dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hdf4dataset.cpp 35971 2016-10-27 11:27:35Z jef $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  HDF4 Datasets. Open HDF4 file, fetch metadata and list of
@@ -43,7 +42,7 @@
 #include "hdf4compat.h"
 #include "hdf4dataset.h"
 
-CPL_CVSID("$Id: hdf4dataset.cpp 35971 2016-10-27 11:27:35Z jef $");
+CPL_CVSID("$Id: hdf4dataset.cpp 36821 2016-12-12 11:17:39Z rouault $");
 
 extern const char * const pszGDALSignature;
 
@@ -115,15 +114,15 @@ char **HDF4Dataset::GetMetadata( const char *pszDomain )
 
 /************************************************************************/
 /*                           SPrintArray()                              */
-/*	Prints numerical arrays in string buffer.			*/
-/*	This function takes pfaDataArray as a pointer to printed array,	*/
-/*	nValues as a number of values to print and pszDelimiter as a	*/
-/*	field delimiting strings.					*/
-/*	Pointer to filled buffer will be returned.			*/
+/*      Prints numerical arrays in string buffer.                       */
+/*      This function takes pfaDataArray as a pointer to printed array, */
+/*      nValues as a number of values to print and pszDelimiter as a    */
+/*      field delimiting strings.                                       */
+/*      Pointer to filled buffer will be returned.                      */
 /************************************************************************/
 
 char *SPrintArray( GDALDataType eDataType, const void *paDataArray,
-                          int nValues, const char *pszDelimiter )
+                   int nValues, const char *pszDelimiter )
 {
     const int iFieldSize = 32 + static_cast<int>(strlen( pszDelimiter ) );
     char *pszField = static_cast<char *>( CPLMalloc( iFieldSize + 1 ) );
@@ -227,33 +226,33 @@ const char *HDF4Dataset::GetDataTypeName( int32 iNumType )
     switch (iNumType)
     {
         case DFNT_CHAR8: // The same as DFNT_CHAR
-	    return "8-bit character";
-	case DFNT_UCHAR8: // The same as DFNT_UCHAR
-	    return "8-bit unsigned character";
+            return "8-bit character";
+        case DFNT_UCHAR8: // The same as DFNT_UCHAR
+            return "8-bit unsigned character";
         case DFNT_INT8:
-	    return "8-bit integer";
+            return "8-bit integer";
         case DFNT_UINT8:
-	    return "8-bit unsigned integer";
+            return "8-bit unsigned integer";
         case DFNT_INT16:
-	    return "16-bit integer";
+            return "16-bit integer";
         case DFNT_UINT16:
-	    return "16-bit unsigned integer";
+            return "16-bit unsigned integer";
         case DFNT_INT32:
-	    return "32-bit integer";
+            return "32-bit integer";
         case DFNT_UINT32:
-	    return "32-bit unsigned integer";
+            return "32-bit unsigned integer";
         case DFNT_INT64:
-	    return "64-bit integer";
+            return "64-bit integer";
         case DFNT_UINT64:
-	    return "64-bit unsigned integer";
+            return "64-bit unsigned integer";
         case DFNT_FLOAT32:
-	    return "32-bit floating-point";
+            return "32-bit floating-point";
         case DFNT_FLOAT64:
-	    return "64-bit floating-point";
+            return "64-bit floating-point";
         default:
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Unknown type %d\n", static_cast<int>(iNumType) );
+                      "Unknown type %d", static_cast<int>(iNumType) );
 
             return "unknown type";
         }
@@ -269,25 +268,25 @@ int HDF4Dataset::GetDataTypeSize( int32 iNumType )
     switch (iNumType)
     {
         case DFNT_CHAR8: // The same as DFNT_CHAR
-	case DFNT_UCHAR8: // The same as DFNT_UCHAR
+        case DFNT_UCHAR8: // The same as DFNT_UCHAR
         case DFNT_INT8:
         case DFNT_UINT8:
-	    return 1;
+            return 1;
         case DFNT_INT16:
         case DFNT_UINT16:
-	    return 2;
+            return 2;
         case DFNT_INT32:
         case DFNT_UINT32:
         case DFNT_FLOAT32:
-	    return 4;
+            return 4;
         case DFNT_INT64:
         case DFNT_UINT64:
         case DFNT_FLOAT64:
-	    return 8;
+            return 8;
         default:
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Unknown type %d\n", static_cast<int>(iNumType) );
+                      "Unknown type %d", static_cast<int>(iNumType) );
             return 0;
         }
     }
@@ -299,7 +298,6 @@ int HDF4Dataset::GetDataTypeSize( int32 iNumType )
 
 double HDF4Dataset::AnyTypeToDouble( int32 iNumType, void *pData )
 {
-    CPL_STATIC_ASSERT(sizeof(GIntBig) == 8);
     switch ( iNumType )
     {
         case DFNT_INT8:
@@ -314,10 +312,12 @@ double HDF4Dataset::AnyTypeToDouble( int32 iNumType, void *pData )
             return static_cast<double>(*reinterpret_cast<GInt32 *>(pData));
         case DFNT_UINT32:
             return static_cast<double>(*reinterpret_cast<GUInt32 *>(pData));
+#ifdef CPL_HAS_GINT64
         case DFNT_INT64:
-            return static_cast<double>(*reinterpret_cast<GIntBig *>(pData));
+            return static_cast<double>(*reinterpret_cast<GInt64 *>(pData));
         case DFNT_UINT64:
-            return static_cast<double>(*reinterpret_cast<GIntBig *>(pData));
+            return static_cast<double>(*reinterpret_cast<GUInt64 *>(pData));
+#endif
         case DFNT_FLOAT32:
             return static_cast<double>(*reinterpret_cast<float *>(pData));
         case DFNT_FLOAT64:
@@ -325,7 +325,7 @@ double HDF4Dataset::AnyTypeToDouble( int32 iNumType, void *pData )
         default:
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Unknown type %d\n", static_cast<int>(iNumType) );
+                      "Unknown type %d", static_cast<int>(iNumType) );
             return 0.0;
         }
     }
@@ -379,16 +379,16 @@ char **HDF4Dataset::HDF4EOSTokenizeAttrs( const char * pszString )
             }
             else if ( *pszString == '(' )
             {
-                bInBracket = TRUE;
+                bInBracket = true;
                 continue;
             }
-	    else if ( *pszString == ')' )
+            else if ( *pszString == ')' )
             {
-		bInBracket = FALSE;
+                bInBracket = false;
                 continue;
             }
 
-	    if( nTokenLen >= nTokenMax - 2 )
+            if( nTokenLen >= nTokenMax - 2 )
             {
                 nTokenMax = nTokenMax * 2 + 10;
                 pszToken = static_cast<char *>(
@@ -470,8 +470,8 @@ char **HDF4Dataset::HDF4EOSGetObject( char **papszAttrList,
 /*         Translate HDF4-EOS attributes in GDAL metadata items         */
 /************************************************************************/
 
-char** HDF4Dataset::TranslateHDF4EOSAttributes( int32 iHandle,
-    int32 iAttribute, int32 nValues, char **papszMetadata )
+char** HDF4Dataset::TranslateHDF4EOSAttributes(
+    int32 iHandle, int32 iAttribute, int32 nValues, char **papszMetadata )
 {
     char *pszData = static_cast<char *>(
         CPLMalloc( (nValues + 1) * sizeof(char) ) );
@@ -539,27 +539,32 @@ char** HDF4Dataset::TranslateHDF4EOSAttributes( int32 iHandle,
     char ** papszAttrs = papszAttrList;
     while ( papszAttrs )
     {
-	papszAttrs = HDF4EOSGetObject( papszAttrs, &pszAttrName,
+        papszAttrs = HDF4EOSGetObject( papszAttrs, &pszAttrName,
                                        &pszAttrClass, &pszAttrValue );
-	if ( pszAttrName && pszAttrValue )
+        if ( pszAttrName && pszAttrValue )
         {
-	    // Now we should recognize special type of HDF EOS metastructures:
-	    // ADDITIONALATTRIBUTENAME = <name>
-	    // PARAMETERVALUE = <value>
-	    if ( EQUAL( pszAttrName, "ADDITIONALATTRIBUTENAME" ) )
-		pszAddAttrName = pszAttrValue;
-	    else if ( pszAddAttrName && EQUAL( pszAttrName, "PARAMETERVALUE" ) )
+            // Now we should recognize special type of HDF EOS metastructures:
+            // ADDITIONALATTRIBUTENAME = <name>
+            // PARAMETERVALUE = <value>
+            if ( EQUAL( pszAttrName, "ADDITIONALATTRIBUTENAME" ) )
             {
-		papszMetadata =
-		    CSLAddNameValue( papszMetadata, pszAddAttrName, pszAttrValue );
-		pszAddAttrName = NULL;
+                pszAddAttrName = pszAttrValue;
+            }
+            else if ( pszAddAttrName && EQUAL( pszAttrName, "PARAMETERVALUE" ) )
+            {
+                papszMetadata =
+                    CSLAddNameValue( papszMetadata, pszAddAttrName,
+                                     pszAttrValue );
+                pszAddAttrName = NULL;
             }
             else
             {
-                // Add class suffix to the key name if applicable
-		papszMetadata = CSLAddNameValue( papszMetadata,
-                    pszAttrClass ?
-                    CPLSPrintf("%s.%s", pszAttrName, pszAttrClass) : pszAttrName,
+                // Add class suffix to the key name if applicable.
+                papszMetadata = CSLAddNameValue(
+                    papszMetadata,
+                    pszAttrClass
+                    ? CPLSPrintf("%s.%s", pszAttrName, pszAttrClass)
+                    : pszAttrName,
                     pszAttrValue );
             }
         }
@@ -575,9 +580,9 @@ char** HDF4Dataset::TranslateHDF4EOSAttributes( int32 iHandle,
 /*         Translate HDF4 attributes in GDAL metadata items             */
 /************************************************************************/
 
-char** HDF4Dataset::TranslateHDF4Attributes( int32 iHandle,
-    int32 iAttribute, char *pszAttrName, int32 iNumType, int32 nValues,
-    char **papszMetadata )
+char** HDF4Dataset::TranslateHDF4Attributes(
+    int32 iHandle, int32 iAttribute, char *pszAttrName, int32 iNumType,
+    int32 nValues, char **papszMetadata )
 {
 
 /* -------------------------------------------------------------------- */
@@ -622,11 +627,12 @@ CPLErr HDF4Dataset::ReadGlobalAttributes( int32 iHandler )
 /* -------------------------------------------------------------------- */
 /*     Obtain number of SDSs and global attributes in input file.       */
 /* -------------------------------------------------------------------- */
-    int32 nDatasets, nAttributes;
+    int32 nDatasets = 0;
+    int32 nAttributes = 0;
     if ( SDfileinfo( iHandler, &nDatasets, &nAttributes ) != 0 )
         return CE_Failure;
 
-    char szAttrName[H4_MAX_NC_NAME];  // TODO: Get this off the stack.
+    char szAttrName[H4_MAX_NC_NAME] = {};  // TODO: Get this off the stack.
 
     // Loop through the all attributes
     for( int32 iAttribute = 0; iAttribute < nAttributes; iAttribute++ )
@@ -639,18 +645,18 @@ CPLErr HDF4Dataset::ReadGlobalAttributes( int32 iHandler )
         SDattrinfo( iHandler, iAttribute, szAttrName, &iNumType, &nValues );
 
         if ( STARTS_WITH_CI(szAttrName, "coremetadata")    ||
-	     STARTS_WITH_CI(szAttrName, "archivemetadata.") ||
-	     STARTS_WITH_CI(szAttrName, "productmetadata.") ||
+             STARTS_WITH_CI(szAttrName, "archivemetadata.") ||
+             STARTS_WITH_CI(szAttrName, "productmetadata.") ||
              STARTS_WITH_CI(szAttrName, "badpixelinformation") ||
-	     STARTS_WITH_CI(szAttrName, "product_summary") ||
-	     STARTS_WITH_CI(szAttrName, "dem_specific") ||
-	     STARTS_WITH_CI(szAttrName, "bts_specific") ||
-	     STARTS_WITH_CI(szAttrName, "etse_specific") ||
-	     STARTS_WITH_CI(szAttrName, "dst_specific") ||
-	     STARTS_WITH_CI(szAttrName, "acv_specific") ||
-	     STARTS_WITH_CI(szAttrName, "act_specific") ||
-	     STARTS_WITH_CI(szAttrName, "etst_specific") ||
-	     STARTS_WITH_CI(szAttrName, "level_1_carryover") )
+             STARTS_WITH_CI(szAttrName, "product_summary") ||
+             STARTS_WITH_CI(szAttrName, "dem_specific") ||
+             STARTS_WITH_CI(szAttrName, "bts_specific") ||
+             STARTS_WITH_CI(szAttrName, "etse_specific") ||
+             STARTS_WITH_CI(szAttrName, "dst_specific") ||
+             STARTS_WITH_CI(szAttrName, "acv_specific") ||
+             STARTS_WITH_CI(szAttrName, "act_specific") ||
+             STARTS_WITH_CI(szAttrName, "etst_specific") ||
+             STARTS_WITH_CI(szAttrName, "level_1_carryover") )
         {
             bIsHDFEOS = true;
             papszGlobalMetadata
@@ -660,7 +666,7 @@ CPLErr HDF4Dataset::ReadGlobalAttributes( int32 iHandler )
 
         // Skip "StructMetadata.N" records. We will fetch information
         // from them using HDF-EOS API
-	else if ( STARTS_WITH_CI(szAttrName, "structmetadata.") )
+        else if ( STARTS_WITH_CI(szAttrName, "structmetadata.") )
         {
             bIsHDFEOS = true;
             continue;
@@ -668,8 +674,9 @@ CPLErr HDF4Dataset::ReadGlobalAttributes( int32 iHandler )
 
         else
         {
-	    papszGlobalMetadata = TranslateHDF4Attributes( iHandler,
-		iAttribute, szAttrName,	iNumType, nValues, papszGlobalMetadata );
+            papszGlobalMetadata = TranslateHDF4Attributes(
+                iHandler, iAttribute, szAttrName, iNumType, nValues,
+                papszGlobalMetadata );
         }
     }
 
@@ -686,7 +693,7 @@ int HDF4Dataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 4 )
         return FALSE;
 
-    if( memcmp(poOpenInfo->pabyHeader,"\016\003\023\001",4) != 0 )
+    if( memcmp(poOpenInfo->pabyHeader, "\016\003\023\001", 4) != 0 )
         return FALSE;
 
     return TRUE;
@@ -708,7 +715,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
 
-    // Attempt to increase maximum number of opened HDF files
+    // Attempt to increase maximum number of opened HDF files.
 #ifdef HDF4_HAS_MAXOPENFILES
     intn nCurrMax = 0;
     intn nSysLimit = 0;
@@ -723,7 +730,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
     int32 hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0);
 
     if( hHDF4 <= 0 )
-        return( NULL );
+        return NULL;
 
     Hclose( hHDF4 );
 
@@ -753,7 +760,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to open HDF4 file \"%s\" for SDS reading.\n",
+                  "Failed to open HDF4 file \"%s\" for SDS reading.",
                   poOpenInfo->pszFilename );
         return NULL;
     }
@@ -768,7 +775,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to read global attributes from HDF4 file \"%s\".\n",
+                  "Failed to read global attributes from HDF4 file \"%s\".",
                   poOpenInfo->pszFilename );
         return NULL;
     }
@@ -783,49 +790,52 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     if ( pszValue != NULL && EQUAL( pszValue, pszGDALSignature ) )
     {
-	poDS->iSubdatasetType = H4ST_GDAL;
-	poDS->pszSubdatasetType = "GDAL_HDF4";
+        poDS->iSubdatasetType = H4ST_GDAL;
+        poDS->pszSubdatasetType = "GDAL_HDF4";
     }
 
-    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL
-	 && EQUAL( pszValue, "SeaWiFS Level-1A Data" ) )
+    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                            "Title")) != NULL
+         && EQUAL( pszValue, "SeaWiFS Level-1A Data" ) )
     {
-	poDS->iSubdatasetType = H4ST_SEAWIFS_L1A;
-	poDS->pszSubdatasetType = "SEAWIFS_L1A";
+        poDS->iSubdatasetType = H4ST_SEAWIFS_L1A;
+        poDS->pszSubdatasetType = "SEAWIFS_L1A";
     }
 
-    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL
-	&& EQUAL( pszValue, "SeaWiFS Level-2 Data" ) )
+    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                            "Title")) != NULL
+        && EQUAL( pszValue, "SeaWiFS Level-2 Data" ) )
     {
-	poDS->iSubdatasetType = H4ST_SEAWIFS_L2;
-	poDS->pszSubdatasetType = "SEAWIFS_L2";
+        poDS->iSubdatasetType = H4ST_SEAWIFS_L2;
+        poDS->pszSubdatasetType = "SEAWIFS_L2";
     }
 
-    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL
-	&& EQUAL( pszValue, "SeaWiFS Level-3 Standard Mapped Image" ) )
+    else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                            "Title")) != NULL
+        && EQUAL( pszValue, "SeaWiFS Level-3 Standard Mapped Image" ) )
     {
-	poDS->iSubdatasetType = H4ST_SEAWIFS_L3;
-	poDS->pszSubdatasetType = "SEAWIFS_L3";
+        poDS->iSubdatasetType = H4ST_SEAWIFS_L3;
+        poDS->pszSubdatasetType = "SEAWIFS_L3";
     }
 
     else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
                                             "L1 File Generated By")) != NULL
-	&& STARTS_WITH_CI(pszValue, "HYP version ") )
+        && STARTS_WITH_CI(pszValue, "HYP version ") )
     {
-	poDS->iSubdatasetType = H4ST_HYPERION_L1;
-	poDS->pszSubdatasetType = "HYPERION_L1";
+        poDS->iSubdatasetType = H4ST_HYPERION_L1;
+        poDS->pszSubdatasetType = "HYPERION_L1";
     }
 
     else
     {
-	poDS->iSubdatasetType = H4ST_UNKNOWN;
-	poDS->pszSubdatasetType = "UNKNOWN";
+        poDS->iSubdatasetType = H4ST_UNKNOWN;
+        poDS->pszSubdatasetType = "UNKNOWN";
     }
 
 /* -------------------------------------------------------------------- */
 /*  If we have HDF-EOS dataset, process it here.                        */
 /* -------------------------------------------------------------------- */
-    int32 aiDimSizes[H4_MAX_VAR_DIMS];  // TODO: Get this off of the stack.
+    int32 aiDimSizes[H4_MAX_VAR_DIMS] = {};  // TODO: Get this off of the stack.
     int32 iRank = 0;
     int32 iNumType = 0;
     int32 nAttrs = 0;
@@ -849,13 +859,13 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
             delete poDS;
             CPLAcquireMutex(hHDF4Mutex, 1000.0);
             CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Failed to open HDF-EOS file \"%s\" for swath reading.\n",
+                      "Failed to open HDF-EOS file \"%s\" for swath reading.",
                       poOpenInfo->pszFilename );
             return NULL;
         }
-        int32 nStrBufSize;
-        int32 nSubDatasets
-            = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize);
+        int32 nStrBufSize = 0;
+        int32 nSubDatasets =
+            SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize);
 
 #ifdef DEBUG
         CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d",
@@ -864,8 +874,8 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
         if ( nSubDatasets > 0 && nStrBufSize > 0 )
         {
-            char *pszSwathList
-                = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
+            char *pszSwathList =
+                static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
             SWinqswath( poOpenInfo->pszFilename, pszSwathList, &nStrBufSize );
             pszSwathList[nStrBufSize] = '\0';
 
@@ -932,9 +942,10 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                     if ( iRank < 2 )
                         continue;
 
-                    // Add field to the list of GDAL subdatasets
+                    // Add field to the list of GDAL subdatasets.
                     const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
-                    snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 );
+                    snprintf( szTemp, sizeof(szTemp),
+                              "SUBDATASET_%d_NAME", nCount + 1 );
                     // We will use the field index as an identificator.
                     poDS->papszSubDatasets =
                         CSLSetNameValue( poDS->papszSubDatasets, szTemp,
@@ -942,7 +953,8 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                                            poOpenInfo->pszFilename,
                                            papszSwaths[i], papszFields[j]) );
 
-                    snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 );
+                    snprintf( szTemp, sizeof(szTemp),
+                              "SUBDATASET_%d_DESC", nCount + 1 );
                     char *pszString = SPrintArray( GDT_UInt32, aiDimSizes,
                                                    iRank, "x" );
                     poDS->papszSubDatasets =
@@ -1048,7 +1060,8 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
                     // Add field to the list of GDAL subdatasets
                     const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
-                    snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 );
+                    snprintf( szTemp, sizeof(szTemp),
+                              "SUBDATASET_%d_NAME", nCount + 1 );
                     // We will use the field index as an identificator.
                     poDS->papszSubDatasets =
                         CSLSetNameValue(poDS->papszSubDatasets, szTemp,
@@ -1056,7 +1069,8 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                                             poOpenInfo->pszFilename,
                                             papszGrids[i], papszFields[j]));
 
-                    snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 );
+                    snprintf( szTemp, sizeof(szTemp),
+                              "SUBDATASET_%d_DESC", nCount + 1 );
                     char *pszString = SPrintArray( GDT_UInt32, aiDimSizes,
                                                    iRank, "x" );
                     poDS->papszSubDatasets =
@@ -1116,9 +1130,11 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
             else
                 pszName = szName;
 
-            // Add datasets with multiple dimensions to the list of GDAL subdatasets
+            // Add datasets with multiple dimensions to the list of GDAL
+            // subdatasets.
             const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
-            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 );
+            snprintf( szTemp, sizeof(szTemp),
+                      "SUBDATASET_%d_NAME", nCount + 1 );
             // We will use SDS index as an identificator, because SDS names
             // are not unique. Filename also needed for further file opening
             poDS->papszSubDatasets = CSLSetNameValue(
@@ -1127,7 +1143,8 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                   CPLSPrintf( "HDF4_SDS:%s:\"%s\":%ld", poDS->pszSubdatasetType,
                               poOpenInfo->pszFilename,
                               static_cast<long>( i ) ) );
-            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 );
+            snprintf( szTemp, sizeof(szTemp),
+                      "SUBDATASET_%d_DESC", nCount + 1 );
             char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" );
             poDS->papszSubDatasets = CSLSetNameValue(
                 poDS->papszSubDatasets,
@@ -1174,7 +1191,7 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
             // iRank in GR interface has another meaning. It represents number
             // of samples per pixel. aiDimSizes has only two dimensions.
-            int32 iInterlaceMode;
+            int32 iInterlaceMode = 0;
             if ( GRgetiminfo( iGR, szName, &iRank, &iNumType, &iInterlaceMode,
                               aiDimSizes, &nAttrs ) != 0 )
             {
@@ -1189,12 +1206,14 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
                 return NULL;
             }
             const int nCount = CSLCount( poDS->papszSubDatasets ) / 2;
-            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 );
+            snprintf( szTemp, sizeof(szTemp),
+                      "SUBDATASET_%d_NAME", nCount + 1 );
             poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
                 szTemp,CPLSPrintf( "HDF4_GR:UNKNOWN:\"%s\":%ld",
                                    poOpenInfo->pszFilename,
                                    static_cast<long>( i ) ) );
-            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 );
+            snprintf( szTemp, sizeof(szTemp),
+                      "SUBDATASET_%d_DESC", nCount + 1 );
             char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, 2, "x" );
             poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets,
                 szTemp, CPLSPrintf( "[%sx%ld] %s (%s)", pszString,
@@ -1212,7 +1231,8 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     Hclose( hHDF4 );
 
-    poDS->nRasterXSize = poDS->nRasterYSize = 512; // XXX: bogus values
+    poDS->nRasterXSize = 512; // XXX: bogus value
+    poDS->nRasterYSize = 512; // XXX: bogus value
 
     // Make sure we don't try to do any pam stuff with this dataset.
     poDS->nPamFlags |= GPF_NOSAVE;
@@ -1257,13 +1277,12 @@ GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo )
 
             CPLError( CE_Failure, CPLE_NotSupported,
                       "The HDF4 driver does not support update access to "
-                      "existing datasets.\n" );
+                      "existing datasets." );
             return NULL;
         }
-
     }
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/hdf4/hdf4dataset.h b/frmts/hdf4/hdf4dataset.h
index d66f8d8..cda4b24 100644
--- a/frmts/hdf4/hdf4dataset.h
+++ b/frmts/hdf4/hdf4dataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf4dataset.h 33794 2016-03-26 13:19:07Z goatbar $
+ * $Id: hdf4dataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  Header file for HDF4 datasets reader.
@@ -33,30 +33,30 @@
 #include "cpl_list.h"
 #include "gdal_pam.h"
 
-typedef enum			// Types of dataset:
+typedef enum                    // Types of dataset:
 {
-    HDF4_SDS,			// Scientific Dataset
-    HDF4_GR,			// General Raster Image
+    HDF4_SDS,                   // Scientific Dataset
+    HDF4_GR,                    // General Raster Image
     HDF4_EOS,                   // HDF EOS
     HDF4_UNKNOWN
 } HDF4DatasetType;
 
-typedef enum			// Types of data products:
+typedef enum                    // Types of data products:
 {
-    H4ST_GDAL,		        // HDF written by GDAL
+    H4ST_GDAL,                  // HDF written by GDAL
     H4ST_EOS_GRID,              // HDF-EOS Grid
     H4ST_EOS_SWATH,             // HDF-EOS Swath
     H4ST_EOS_SWATH_GEOL,        // HDF-EOS Swath Geolocation Array
-    H4ST_SEAWIFS_L1A,		// SeaWiFS Level-1A Data
-    H4ST_SEAWIFS_L2,		// SeaWiFS Level-2 Data
-    H4ST_SEAWIFS_L3,		// SeaWiFS Level-3 Standard Mapped Image
+    H4ST_SEAWIFS_L1A,           // SeaWiFS Level-1A Data
+    H4ST_SEAWIFS_L2,            // SeaWiFS Level-2 Data
+    H4ST_SEAWIFS_L3,            // SeaWiFS Level-3 Standard Mapped Image
     H4ST_HYPERION_L1,           // Hyperion L1 Data Product
     H4ST_UNKNOWN
 } HDF4SubdatasetType;
 
 /************************************************************************/
 /* ==================================================================== */
-/*				HDF4Dataset				*/
+/*                              HDF4Dataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -72,14 +72,14 @@ class HDF4Dataset : public GDALPamDataset
                                     char **ppszAttrClass, char **ppszAttrValue );
 
   protected:
-    int32	hGR;
-    int32	hSD;
-    int32	nImages;
+    int32       hGR;
+    int32       hSD;
+    int32       nImages;
     HDF4SubdatasetType iSubdatasetType;
-    const char	*pszSubdatasetType;
+    const char  *pszSubdatasetType;
 
-    char	**papszGlobalMetadata;
-    char	**papszSubDatasets;
+    char        **papszGlobalMetadata;
+    char        **papszSubDatasets;
 
     CPLErr              ReadGlobalAttributes( int32 );
 
@@ -96,8 +96,8 @@ class HDF4Dataset : public GDALPamDataset
                 HDF4Dataset();
     virtual ~HDF4Dataset();
 
-    virtual char      **GetMetadataDomainList();
-    virtual char        **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char        **GetMetadata( const char * pszDomain = "" ) override;
     static GDALDataset  *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
 };
@@ -105,5 +105,4 @@ class HDF4Dataset : public GDALPamDataset
 char *SPrintArray( GDALDataType eDataType, const void *paDataArray,
                    int nValues, const char *pszDelimiter );
 
-
 #endif /* HDF4DATASET_H_INCLUDED_ */
diff --git a/frmts/hdf4/hdf4imagedataset.cpp b/frmts/hdf4/hdf4imagedataset.cpp
index b716e2f..c360511 100644
--- a/frmts/hdf4/hdf4imagedataset.cpp
+++ b/frmts/hdf4/hdf4imagedataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hdf4imagedataset.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 4 (HDF4)
  * Purpose:  Read subdatasets of HDF4 file.
@@ -56,15 +55,15 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: hdf4imagedataset.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: hdf4imagedataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 static const int HDF4_SDS_MAXNAMELEN = 65;
 
 extern const char * const pszGDALSignature;
 
-// Signature to recognize files written by GDAL
-const char      * const pszGDALSignature =
-        "Created with GDAL (http://www.remotesensing.org/gdal/)";
+// Signature to recognize files written by GDAL.
+const char * const pszGDALSignature =
+    "Created with GDAL (http://www.remotesensing.org/gdal/)";
 
 extern CPLMutex *hHDF4Mutex;
 
@@ -94,20 +93,32 @@ enum HDF4EOSProduct
 /* ==================================================================== */
 /************************************************************************/
 
+static const int N_COLOR_ENTRIES = 256;
+
 class HDF4ImageDataset : public HDF4Dataset
 {
     friend class HDF4ImageRasterBand;
 
     char        *pszFilename;
-    int32       hHDF4, iGR, iPal, iDataset;
-    int32       iRank, iNumType, nAttrs,
-                iInterlaceMode, iPalInterlaceMode, iPalDataType;
-    int32       nComps, nPalEntries;
+    int32       hHDF4;
+    int32       iGR;
+    int32       iPal;
+    int32       iDataset;
+    int32       iRank;
+    int32       iNumType;
+    int32       nAttrs;
+    int32       iInterlaceMode;
+    int32       iPalInterlaceMode;
+    int32       iPalDataType;
+    int32       nComps;
+    int32       nPalEntries;
     int32       aiDimSizes[H4_MAX_VAR_DIMS];
-    int         iXDim, iYDim, iBandDim, i4Dim;
+    int         iXDim;
+    int         iYDim;
+    int         iBandDim;
+    int         i4Dim;
     int         nBandCount;
     char        **papszLocalMetadata;
-#define    N_COLOR_ENTRIES    256
     uint8       aiPaletteData[N_COLOR_ENTRIES][3]; // XXX: Static array for now
     char        szName[HDF4_SDS_MAXNAMELEN];
     char        *pszSubdatasetName;
@@ -116,7 +127,7 @@ class HDF4ImageDataset : public HDF4Dataset
     GDALColorTable *poColorTable;
 
     OGRSpatialReference oSRS;
-    int         bHasGeoTransform;
+    bool        bHasGeoTransform;
     double      adfGeoTransform[6];
     char        *pszProjection;
     char        *pszGCPProjection;
@@ -152,14 +163,14 @@ class HDF4ImageDataset : public HDF4Dataset
     static GDALDataset  *Create( const char * pszFilename,
                                  int nXSize, int nYSize, int nBands,
                                  GDALDataType eType, char ** papszParmList );
-    virtual void        FlushCache( void );
-    CPLErr              GetGeoTransform( double * padfTransform );
-    virtual CPLErr      SetGeoTransform( double * );
-    const char          *GetProjectionRef();
-    virtual CPLErr      SetProjection( const char * );
-    virtual int         GetGCPCount();
-    virtual const char  *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual void        FlushCache( void ) override;
+    CPLErr              GetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr      SetGeoTransform( double * ) override;
+    const char          *GetProjectionRef() override;
+    virtual CPLErr      SetProjection( const char * ) override;
+    virtual int         GetGCPCount() override;
+    virtual const char  *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 };
 
 /************************************************************************/
@@ -172,30 +183,29 @@ class HDF4ImageRasterBand : public GDALPamRasterBand
 {
     friend class HDF4ImageDataset;
 
-    int         bNoDataSet;
+    bool        bNoDataSet;
     double      dfNoDataValue;
 
-    int         bHaveScale;
-    int         bHaveOffset;
+    bool        bHaveScale;
+    bool        bHaveOffset;
     double      dfScale;
     double      dfOffset;
 
     CPLString   osUnitType;
 
   public:
-
                 HDF4ImageRasterBand( HDF4ImageDataset *, int, GDALDataType );
     virtual ~HDF4ImageRasterBand() {}
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual CPLErr          IWriteBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual double          GetNoDataValue( int * );
-    virtual CPLErr          SetNoDataValue( double );
-    virtual double          GetOffset( int *pbSuccess );
-    virtual double          GetScale( int *pbSuccess );
-    virtual const char     *GetUnitType();
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual CPLErr          IWriteBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual double          GetNoDataValue( int * ) override;
+    virtual CPLErr          SetNoDataValue( double ) override;
+    virtual double          GetOffset( int *pbSuccess ) override;
+    virtual double          GetScale( int *pbSuccess ) override;
+    virtual const char     *GetUnitType() override;
 };
 
 /************************************************************************/
@@ -204,15 +214,15 @@ class HDF4ImageRasterBand : public GDALPamRasterBand
 
 HDF4ImageRasterBand::HDF4ImageRasterBand( HDF4ImageDataset *poDSIn, int nBandIn,
                                           GDALDataType eType ) :
-    bNoDataSet(FALSE),
+    bNoDataSet(false),
     dfNoDataValue(-9999.0),
-    bHaveScale(FALSE),
-    bHaveOffset(FALSE),
+    bHaveScale(false),
+    bHaveOffset(false),
     dfScale(1.0),
     dfOffset(0.0)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     eDataType = eType;
 
     nBlockXSize = poDSIn->GetRasterXSize();
@@ -228,25 +238,26 @@ HDF4ImageRasterBand::HDF4ImageRasterBand( HDF4ImageDataset *poDSIn, int nBandIn,
             atoi( CPLGetConfigOption("HDF4_BLOCK_PIXELS", "1000000") );
 
         nBlockYSize = nChunkSize / poDSIn->GetRasterXSize();
-        nBlockYSize = MAX(1,MIN(nBlockYSize,poDSIn->GetRasterYSize()));
+        nBlockYSize =
+            std::max(1, std::min(nBlockYSize, poDSIn->GetRasterYSize()));
     }
     else
     {
         nBlockYSize = 1;
     }
 
-    /* HDF4_EOS:EOS_GRID case. We ensure that the block size matches */
-    /* the raster width, as the IReadBlock() code can only handle multiple */
-    /* blocks per row */
-    if ( poDSIn->nBlockPreferredXSize == nBlockXSize &&
+    // HDF4_EOS:EOS_GRID case. We ensure that the block size matches
+    // the raster width, as the IReadBlock() code can only handle multiple
+    // blocks per row.
+    if( poDSIn->nBlockPreferredXSize == nBlockXSize &&
          poDSIn->nBlockPreferredYSize > 0 )
     {
-        if (poDSIn->nBlockPreferredYSize == 1)
+        if( poDSIn->nBlockPreferredYSize == 1 )
         {
-            /* Avoid defaulting to tile reading when the preferred height is 1 */
-            /* as it leads to very poor performance with : */
+            // Avoid defaulting to tile reading when the preferred height is 1
+            // as it leads to very poor performance with:
             // ftp://e4ftl01u.ecs.nasa.gov/MODIS_Composites/MOLT/MOD13Q1.005/2006.06.10/MOD13Q1.A2006161.h21v13.005.2008234103220.hd
-            poDSIn->bReadTile = FALSE;
+            poDSIn->bReadTile = false;
         }
         else
         {
@@ -261,7 +272,7 @@ HDF4ImageRasterBand::HDF4ImageRasterBand( HDF4ImageDataset *poDSIn, int nBandIn,
     if( nBlockXSize != poDSIn->nBlockPreferredXSize
         || nBlockYSize != poDSIn->nBlockPreferredYSize )
     {
-        poDSIn->bReadTile = FALSE;
+        poDSIn->bReadTile = false;
     }
 }
 
@@ -274,9 +285,6 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 {
     CPLAssert( nBlockXOff == 0 );
     HDF4ImageDataset *poGDS = reinterpret_cast<HDF4ImageDataset *>( poDS );
-    int32 aiStart[H4_MAX_NC_DIMS];
-    int32 aiEdges[H4_MAX_NC_DIMS];
-    CPLErr              eErr = CE_None;
 
     CPLMutexHolderD(&hHDF4Mutex);
 
@@ -292,7 +300,8 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*      Work out some block oriented details.                           */
 /* -------------------------------------------------------------------- */
     const int nYOff = nBlockYOff * nBlockYSize;
-    const int nYSize = MIN(nYOff + nBlockYSize, poDS->GetRasterYSize()) - nYOff;
+    const int nYSize =
+        std::min(nYOff + nBlockYSize, poDS->GetRasterYSize()) - nYOff;
 
 /* -------------------------------------------------------------------- */
 /*      HDF files with external data files, such as some landsat        */
@@ -305,14 +314,18 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*      Handle different configurations.                                */
 /* -------------------------------------------------------------------- */
+    CPLErr eErr = CE_None;
+    int32 aiStart[H4_MAX_NC_DIMS] = {};
+    int32 aiEdges[H4_MAX_NC_DIMS] = {};
+
     switch ( poGDS->iDatasetType )
     {
       case HDF4_SDS:
       {
-          /* We avoid doing SDselect() / SDendaccess() for each block access */
-          /* as this is very slow when zlib compression is used */
+          // We avoid doing SDselect() / SDendaccess() for each block access
+          // as this is very slow when zlib compression is used.
 
-          if (poGDS->iSDS == FAIL)
+          if( poGDS->iSDS == FAIL )
               poGDS->iSDS = SDselect( poGDS->hSD, poGDS->iDataset );
 
           /* HDF rank:
@@ -341,12 +354,14 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
           {
             case 4:     // 4Dim: volume-time
                         // FIXME: needs sample file. Does not work currently.
-              aiStart[3] = 0/* range: 0--aiDimSizes[3]-1 */;
+              aiStart[3] = 0;  // range: 0--aiDimSizes[3]-1
               aiEdges[3] = 1;
-              aiStart[2] = 0/* range: 0--aiDimSizes[2]-1 */;
+              aiStart[2] = 0;  // range: 0--aiDimSizes[2]-1
               aiEdges[2] = 1;
-              aiStart[1] = nYOff; aiEdges[1] = nYSize;
-              aiStart[0] = nBlockXOff; aiEdges[0] = nBlockXSize;
+              aiStart[1] = nYOff;
+              aiEdges[1] = nYSize;
+              aiStart[0] = nBlockXOff;
+              aiEdges[0] = nBlockXSize;
               break;
             case 3: // 3Dim: volume
               aiStart[poGDS->iBandDim] = nBand - 1;
@@ -463,9 +478,9 @@ CPLErr HDF4ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
                 /* Ensure that we don't overlap the bottom or right edges */
                 /* of the dataset in order to use the GDreadtile() API */
-                if ( poGDS->bReadTile &&
-                     (nBlockXOff + 1) * nBlockXSize <= nRasterXSize &&
-                     (nBlockYOff + 1) * nBlockYSize <= nRasterYSize )
+                if( poGDS->bReadTile &&
+                    (nBlockXOff + 1) * nBlockXSize <= nRasterXSize &&
+                    (nBlockYOff + 1) * nBlockYSize <= nRasterYSize )
                 {
                     int32 tilecoords[] = { nBlockYOff , nBlockXOff };
                     if( GDreadtile( hGD, poGDS->pszFieldName,
@@ -550,9 +565,9 @@ CPLErr HDF4ImageRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     HDF4ImageDataset *poGDS = reinterpret_cast<HDF4ImageDataset *>( poDS );
     CPLAssert( poGDS != NULL );
 
-    int32 aiStart[H4_MAX_NC_DIMS];
-    int32 aiEdges[H4_MAX_NC_DIMS];
-    CPLErr              eErr = CE_None;
+    int32 aiStart[H4_MAX_NC_DIMS] = {};
+    int32 aiEdges[H4_MAX_NC_DIMS] = {};
+    CPLErr eErr = CE_None;
 
     CPLMutexHolderD(&hHDF4Mutex);
 
@@ -560,7 +575,8 @@ CPLErr HDF4ImageRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*      Work out some block oriented details.                           */
 /* -------------------------------------------------------------------- */
     const int nYOff = nBlockYOff * nBlockYSize;
-    const int nYSize = MIN(nYOff + nBlockYSize, poDS->GetRasterYSize()) - nYOff;
+    const int nYSize =
+        std::min(nYOff + nBlockYSize, poDS->GetRasterYSize()) - nYOff;
 
 /* -------------------------------------------------------------------- */
 /*      Process based on rank.                                          */
@@ -580,8 +596,8 @@ CPLErr HDF4ImageRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 aiStart[poGDS->iXDim] = nBlockXOff;
                 aiEdges[poGDS->iXDim] = nBlockXSize;
 
-                if ( (SDwritedata( l_iSDS, aiStart, NULL,
-                                   aiEdges, (VOIDP)pImage )) < 0 )
+                if( (SDwritedata( l_iSDS, aiStart, NULL,
+                                  aiEdges, (VOIDP)pImage )) < 0 )
                     eErr = CE_Failure;
 
                 SDendaccess( l_iSDS );
@@ -597,8 +613,8 @@ CPLErr HDF4ImageRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                 aiStart[poGDS->iXDim] = nBlockXOff;
                 aiEdges[poGDS->iXDim] = nBlockXSize;
 
-                if ( (SDwritedata( l_iSDS, aiStart, NULL,
-                                   aiEdges, (VOIDP)pImage )) < 0 )
+                if( (SDwritedata( l_iSDS, aiStart, NULL,
+                                  aiEdges, (VOIDP)pImage )) < 0 )
                     eErr = CE_Failure;
 
                 SDendaccess( l_iSDS );
@@ -632,27 +648,33 @@ GDALColorInterp HDF4ImageRasterBand::GetColorInterpretation()
 {
     HDF4ImageDataset *poGDS = reinterpret_cast<HDF4ImageDataset *>( poDS );
 
-    if ( poGDS->iDatasetType == HDF4_SDS )
+    if( poGDS->iDatasetType == HDF4_SDS )
+    {
         return GCI_GrayIndex;
-    else if ( poGDS->iDatasetType == HDF4_GR )
+    }
+    else if( poGDS->iDatasetType == HDF4_GR )
     {
-        if ( poGDS->poColorTable != NULL )
+        if( poGDS->poColorTable != NULL )
+        {
             return GCI_PaletteIndex;
-        else if ( poGDS->nBands != 1 )
+        }
+        else if( poGDS->nBands != 1 )
         {
-            if ( nBand == 1 )
+            if( nBand == 1 )
                 return GCI_RedBand;
-            else if ( nBand == 2 )
+            else if( nBand == 2 )
                 return GCI_GreenBand;
-            else if ( nBand == 3 )
+            else if( nBand == 3 )
                 return GCI_BlueBand;
-            else if ( nBand == 4 )
+            else if( nBand == 4 )
                 return GCI_AlphaBand;
             else
                 return GCI_Undefined;
         }
         else
+        {
             return GCI_GrayIndex;
+        }
     }
 
     return GCI_GrayIndex;
@@ -678,7 +700,7 @@ double HDF4ImageRasterBand::GetNoDataValue( int * pbSuccess )
 CPLErr HDF4ImageRasterBand::SetNoDataValue( double dfNoData )
 
 {
-    bNoDataSet = TRUE;
+    bNoDataSet = true;
     dfNoDataValue = dfNoData;
 
     return CE_None;
@@ -691,7 +713,7 @@ CPLErr HDF4ImageRasterBand::SetNoDataValue( double dfNoData )
 const char *HDF4ImageRasterBand::GetUnitType()
 
 {
-    if( osUnitType.size() > 0 )
+    if( !osUnitType.empty() )
         return osUnitType;
 
     return GDALRasterBand::GetUnitType();
@@ -741,52 +763,50 @@ double HDF4ImageRasterBand::GetScale( int *pbSuccess )
 /*                           HDF4ImageDataset()                         */
 /************************************************************************/
 
-HDF4ImageDataset::HDF4ImageDataset()
+HDF4ImageDataset::HDF4ImageDataset() :
+    pszFilename(NULL),
+    hHDF4(0),
+    iGR(0),
+    iPal(0),
+    iDataset(0),
+    iRank(0),
+    iNumType(0),
+    nAttrs(0),
+    iInterlaceMode(0),
+    iPalInterlaceMode(0),
+    iPalDataType(0),
+    nComps(0),
+    nPalEntries(0),
+    iXDim(0),
+    iYDim(0),
+    iBandDim(-1),
+    i4Dim(0),
+    nBandCount(0),
+    pszSubdatasetName(NULL),
+    pszFieldName(NULL),
+    poColorTable(NULL),
+    oSRS( OGRSpatialReference() ),
+    bHasGeoTransform(false),
+    pszProjection(CPLStrdup( "" )),
+    pszGCPProjection(CPLStrdup( "" )),
+    pasGCPList(NULL),
+    nGCPCount(0),
+    iDatasetType(HDF4_UNKNOWN),
+    iSDS(FAIL),
+    nBlockPreferredXSize(-1),
+    nBlockPreferredYSize(-1),
+    bReadTile(false)
 {
-    pszFilename = NULL;
-    hHDF4 = 0;
-    iGR = 0;
-    iPal = 0;
-    iDataset = 0;
-    iRank = 0;
-    iNumType = 0;
-    nAttrs = 0;
-    iInterlaceMode = 0;
-    iPalInterlaceMode = 0;
-    iPalDataType = 0;
-    nComps = 0;
-    nPalEntries = 0;
     memset(aiDimSizes, 0, sizeof(aiDimSizes));
-    iXDim = 0;
-    iYDim = 0;
-    iBandDim = -1;
-    i4Dim = 0;
-    nBandCount = 0;
     papszLocalMetadata = NULL;
     memset(aiPaletteData, 0, sizeof(aiPaletteData));
     memset(szName, 0, sizeof(szName));
-    pszSubdatasetName = NULL;
-    pszFieldName = NULL;
-    poColorTable = NULL;
-    bHasGeoTransform = FALSE;
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
-    pszProjection = CPLStrdup( "" );
-    pszGCPProjection = CPLStrdup( "" );
-    pasGCPList = NULL;
-    nGCPCount = 0;
-
-    iDatasetType = HDF4_UNKNOWN;
-    iSDS = FAIL;
-
-    nBlockPreferredXSize = -1;
-    nBlockPreferredYSize = -1;
-    bReadTile = false;
-
 }
 
 /************************************************************************/
@@ -799,43 +819,37 @@ HDF4ImageDataset::~HDF4ImageDataset()
 
     FlushCache();
 
-    if ( pszFilename )
-        CPLFree( pszFilename );
-    if ( iSDS != FAIL )
+    CPLFree( pszFilename );
+    if( iSDS != FAIL )
         SDendaccess( iSDS );
-    if ( hSD > 0 )
+    if( hSD > 0 )
         SDend( hSD );
     hSD = 0;
-    if ( iGR > 0 )
+    if( iGR > 0 )
         GRendaccess( iGR );
-    if ( hGR > 0 )
+    if( hGR > 0 )
         GRend( hGR );
     hGR = 0;
-    if ( pszSubdatasetName )
-        CPLFree( pszSubdatasetName );
-    if ( pszFieldName )
-        CPLFree( pszFieldName );
-    if ( papszLocalMetadata )
+    CPLFree( pszSubdatasetName );
+    CPLFree( pszFieldName );
+    if( papszLocalMetadata )
         CSLDestroy( papszLocalMetadata );
-    if ( poColorTable != NULL )
+    if( poColorTable != NULL )
         delete poColorTable;
-    if ( pszProjection )
-        CPLFree( pszProjection );
-    if ( pszGCPProjection )
-        CPLFree( pszGCPProjection );
+
+    CPLFree( pszProjection );
+    CPLFree( pszGCPProjection );
     if( nGCPCount > 0 )
     {
         for( int i = 0; i < nGCPCount; i++ )
         {
-            if ( pasGCPList[i].pszId )
-                CPLFree( pasGCPList[i].pszId );
-            if ( pasGCPList[i].pszInfo )
-                CPLFree( pasGCPList[i].pszInfo );
+            CPLFree( pasGCPList[i].pszId );
+            CPLFree( pasGCPList[i].pszInfo );
         }
 
         CPLFree( pasGCPList );
     }
-    if ( hHDF4 > 0 )
+    if( hHDF4 > 0 )
     {
         switch ( iDatasetType )
         {
@@ -871,7 +885,7 @@ CPLErr HDF4ImageDataset::GetGeoTransform( double * padfTransform )
 {
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
 
-    if ( !bHasGeoTransform )
+    if( !bHasGeoTransform )
         return CE_Failure;
 
     return CE_None;
@@ -883,7 +897,7 @@ CPLErr HDF4ImageDataset::GetGeoTransform( double * padfTransform )
 
 CPLErr HDF4ImageDataset::SetGeoTransform( double * padfTransform )
 {
-    bHasGeoTransform = TRUE;
+    bHasGeoTransform = true;
     memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
 
     return CE_None;
@@ -906,8 +920,7 @@ const char *HDF4ImageDataset::GetProjectionRef()
 CPLErr HDF4ImageDataset::SetProjection( const char *pszNewProjection )
 
 {
-    if ( pszProjection )
-        CPLFree( pszProjection );
+    CPLFree( pszProjection );
     pszProjection = CPLStrdup( pszNewProjection );
 
     return CE_None;
@@ -952,9 +965,6 @@ const GDAL_GCP *HDF4ImageDataset::GetGCPs()
 void HDF4ImageDataset::FlushCache()
 
 {
-    char        *pszName;
-    const char  *pszValue;
-
     CPLMutexHolderD(&hHDF4Mutex);
 
     GDALDataset::FlushCache();
@@ -962,12 +972,13 @@ void HDF4ImageDataset::FlushCache()
     if( eAccess == GA_ReadOnly )
         return;
 
-    // Write out transformation matrix
-    pszValue = CPLSPrintf( "%f, %f, %f, %f, %f, %f",
-                                   adfGeoTransform[0], adfGeoTransform[1],
-                                   adfGeoTransform[2], adfGeoTransform[3],
-                                   adfGeoTransform[4], adfGeoTransform[5] );
-    if ( (SDsetattr( hSD, "TransformationMatrix", DFNT_CHAR8,
+    // Write out transformation matrix.
+    const char *pszValue =
+        CPLSPrintf( "%f, %f, %f, %f, %f, %f",
+                    adfGeoTransform[0], adfGeoTransform[1],
+                    adfGeoTransform[2], adfGeoTransform[3],
+                    adfGeoTransform[4], adfGeoTransform[5] );
+    if( (SDsetattr( hSD, "TransformationMatrix", DFNT_CHAR8,
                      static_cast<int>(strlen(pszValue)) + 1, pszValue )) < 0 )
     {
         CPLDebug( "HDF4Image",
@@ -975,30 +986,33 @@ void HDF4ImageDataset::FlushCache()
     }
 
     // Write out projection
-    if ( pszProjection != NULL && !EQUAL( pszProjection, "" ) )
+    if( pszProjection != NULL && !EQUAL( pszProjection, "" ) )
     {
-        if ( (SDsetattr( hSD, "Projection", DFNT_CHAR8,
-                         static_cast<int>(strlen(pszProjection)) + 1, pszProjection )) < 0 )
+        if( (SDsetattr( hSD, "Projection", DFNT_CHAR8,
+                        static_cast<int>(strlen(pszProjection)) + 1,
+                        pszProjection )) < 0 )
             {
-                CPLDebug( "HDF4Image",
-                          "Cannot write projection information to output file");
+                CPLDebug("HDF4Image",
+                         "Cannot write projection information to output file");
             }
     }
 
     // Store all metadata from source dataset as HDF attributes
     if( GetMetadata() )
     {
-        char    **papszMeta = GetMetadata();
+        char **papszMeta = GetMetadata();
 
-        while ( *papszMeta )
+        while( *papszMeta )
         {
-            pszName = NULL;
+            char *pszName = NULL;
             pszValue = CPLParseNameValue( *papszMeta++, &pszName );
-            if ( pszName != NULL && (SDsetattr( hSD, pszName, DFNT_CHAR8,
-                             static_cast<int>(strlen(pszValue)) + 1, pszValue )) < 0 )
+            if( pszName != NULL &&
+                (SDsetattr( hSD, pszName, DFNT_CHAR8,
+                            static_cast<int>(strlen(pszValue)) + 1,
+                            pszValue )) < 0 )
             {
                 CPLDebug( "HDF4Image",
-                          "Cannot write metadata information to output file");
+                          "Cannot write metadata information to output file" );
             }
 
             CPLFree( pszName );
@@ -1011,12 +1025,13 @@ void HDF4ImageDataset::FlushCache()
         HDF4ImageRasterBand *poBand =
             reinterpret_cast<HDF4ImageRasterBand *>( GetRasterBand(iBand) );
 
-        if ( poBand->bNoDataSet )
+        if( poBand->bNoDataSet )
         {
-            pszName = CPLStrdup( CPLSPrintf( "NoDataValue%d", iBand ) );
+            char *pszName = CPLStrdup( CPLSPrintf( "NoDataValue%d", iBand ) );
             pszValue = CPLSPrintf( "%f", poBand->dfNoDataValue );
-            if ( (SDsetattr( hSD, pszName, DFNT_CHAR8,
-                             static_cast<int>(strlen(pszValue)) + 1, pszValue )) < 0 )
+            if( (SDsetattr( hSD, pszName, DFNT_CHAR8,
+                            static_cast<int>(strlen(pszValue)) + 1,
+                            pszValue )) < 0 )
                 {
                     CPLDebug( "HDF4Image",
                               "Cannot write NoData value for band %d "
@@ -1033,12 +1048,13 @@ void HDF4ImageDataset::FlushCache()
         HDF4ImageRasterBand *poBand =
             reinterpret_cast<HDF4ImageRasterBand *>( GetRasterBand(iBand) );
 
-        pszName = CPLStrdup( CPLSPrintf( "BandDesc%d", iBand ) );
+        char *pszName = CPLStrdup( CPLSPrintf( "BandDesc%d", iBand ) );
         pszValue = poBand->GetDescription();
-        if ( pszValue != NULL && !EQUAL( pszValue, "" ) )
+        if( pszValue != NULL && !EQUAL( pszValue, "" ) )
         {
-            if ( (SDsetattr( hSD, pszName, DFNT_CHAR8,
-                             static_cast<int>(strlen(pszValue)) + 1, pszValue )) < 0 )
+            if( SDsetattr( hSD, pszName, DFNT_CHAR8,
+                           static_cast<int>(strlen(pszValue)) + 1,
+                           pszValue ) < 0 )
             {
                 CPLDebug( "HDF4Image",
                           "Cannot write band's %d description to output file",
@@ -1056,21 +1072,21 @@ void HDF4ImageDataset::FlushCache()
 
 long HDF4ImageDataset::USGSMnemonicToCode( const char* pszMnemonic )
 {
-    if ( EQUAL(pszMnemonic, "UTM") )
+    if( EQUAL(pszMnemonic, "UTM") )
         return 1L;
-    else if ( EQUAL(pszMnemonic, "LAMCC") )
+    else if( EQUAL(pszMnemonic, "LAMCC") )
         return 4L;
-    else if ( EQUAL(pszMnemonic, "PS") )
+    else if( EQUAL(pszMnemonic, "PS") )
         return 6L;
-    else if ( EQUAL(pszMnemonic, "PC") )
+    else if( EQUAL(pszMnemonic, "PC") )
         return 7L;
-    else if ( EQUAL(pszMnemonic, "TM") )
+    else if( EQUAL(pszMnemonic, "TM") )
         return 9L;
-    else if ( EQUAL(pszMnemonic, "EQRECT") )
+    else if( EQUAL(pszMnemonic, "EQRECT") )
         return 17L;
-    else if ( EQUAL(pszMnemonic, "OM") )
+    else if( EQUAL(pszMnemonic, "OM") )
         return 20L;
-    else if ( EQUAL(pszMnemonic, "SOM") )
+    else if( EQUAL(pszMnemonic, "SOM") )
         return 22L;
     else
         return 1L;  // UTM by default
@@ -1245,7 +1261,13 @@ void HDF4ImageDataset::CaptureL1GMTLInfo()
         = CPLAtof( oMTL.GetKeyword( (osPrefix+"UR_CORNER_LAT").c_str(), "0" ) );
 
     CPLFree( pszGCPProjection );
-    pszGCPProjection = CPLStrdup( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" );
+    pszGCPProjection = CPLStrdup(
+        "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,"
+        "298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],"
+        "AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,"
+        "AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,"
+        "AUTHORITY[\"EPSG\",\"9108\"]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST]"
+        ",AUTHORITY[\"EPSG\",\"4326\"]]" );
 
     nGCPCount = 4;
     pasGCPList = (GDAL_GCP *) CPLCalloc( nGCPCount, sizeof( GDAL_GCP ) );
@@ -1336,7 +1358,7 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
 /* -------------------------------------------------------------------- */
 /*      Collect the four corners.                                       */
 /* -------------------------------------------------------------------- */
-    double adfXY[8];
+    double adfXY[8] = {};
     static const char * const apszItems[] = {
         "mapUpperLeft", "mapUpperRight", "mapLowerLeft", "mapLowerRight" };
     bool bLLPossible = true;
@@ -1373,7 +1395,7 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
     if( adfXY[0*2+0] == adfXY[2*2+0] && adfXY[0*2+1] == adfXY[1*2+1]
         && bLLPossible )
     {
-        bHasGeoTransform = TRUE;
+        bHasGeoTransform = true;
         adfGeoTransform[0] = adfXY[0*2+0];
         adfGeoTransform[1] = (adfXY[1*2+0] - adfXY[0*2+0]) / nRasterXSize;
         adfGeoTransform[2] = 0.0;
@@ -1403,13 +1425,15 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
 
     if( l_iSDS != FAIL )
     {
-        char        l_szName[HDF4_SDS_MAXNAMELEN];
-        int32 l_iRank, l_iNumType, l_nAttrs;
-        int32       l_aiDimSizes[H4_MAX_VAR_DIMS];
+        char l_szName[HDF4_SDS_MAXNAMELEN] = {};
+        int32 l_iRank = 0;
+        int32 l_iNumType = 0;
+        int32 l_nAttrs = 0;
+        int32 l_aiDimSizes[H4_MAX_VAR_DIMS] = {};
 
-        double adfGCTP[29];
-        int32 aiStart[H4_MAX_NC_DIMS];
-        int32 aiEdges[H4_MAX_NC_DIMS];
+        double adfGCTP[29] = {};
+        int32 aiStart[H4_MAX_NC_DIMS] = {};
+        int32 aiEdges[H4_MAX_NC_DIMS] = {};
 
         aiStart[0] = 0;
         aiEdges[0] = 29;
@@ -1461,7 +1485,7 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
 
             CPLFree( pszProjection );
             oSRS.exportToWkt( &pszProjection );
-            bGotGCTPProjection = TRUE;
+            bGotGCTPProjection = true;
         }
 
         SDendaccess(l_iSDS);
@@ -1490,7 +1514,7 @@ void HDF4ImageDataset::CaptureNRLGeoTransform()
         if( poCT->Transform( 1, &dfULX, &dfULY )
             && poCT->Transform( 1, &dfLRX, &dfLRY ) )
         {
-            bHasGeoTransform = TRUE;
+            bHasGeoTransform = true;
             adfGeoTransform[0] = dfULX;
             adfGeoTransform[1] = (dfLRX - dfULX) / nRasterXSize;
             adfGeoTransform[2] = 0.0;
@@ -1611,7 +1635,7 @@ void HDF4ImageDataset::CaptureCoastwatchGCTPInfo()
         return;
     }
 
-    bHasGeoTransform = TRUE;
+    bHasGeoTransform = true;
     adfGeoTransform[0] = CPLAtof( papszTokens[4] );
     adfGeoTransform[1] = CPLAtof( papszTokens[2] );
     adfGeoTransform[2] = 0.0;
@@ -1640,18 +1664,20 @@ void HDF4ImageDataset::GetImageDimensions( char *pszDimList )
 
     // Search for the "Band" word in the name of dimension
     // or take the first one as a number of bands
-    if ( iRank == 2 )
+    if( iRank == 2 )
+    {
         nBandCount = 1;
+    }
     else
     {
         for( int i = 0; i < nDimCount; i++ )
         {
-            if ( strstr( papszDimList[i], "band" ) )
+            if( strstr( papszDimList[i], "band" ) )
             {
                 iBandDim = i;
                 nBandCount = aiDimSizes[i];
                 // Handle 4D datasets
-                if ( iRank > 3 && i < nDimCount - 1 )
+                if( iRank > 3 && i < nDimCount - 1 )
                 {
                     // FIXME: is there a better way to search for
                     // the 4th dimension?
@@ -1664,21 +1690,21 @@ void HDF4ImageDataset::GetImageDimensions( char *pszDimList )
     }
 
     // Search for the starting "X" and "Y" in the names or take
-    // the last two dimensions as X and Y sizes
+    // the last two dimensions as X and Y sizes.
     iXDim = nDimCount - 1;
     iYDim = nDimCount - 2;
 
     for( int i = 0; i < nDimCount; i++ )
     {
-        if ( STARTS_WITH_CI(papszDimList[i], "X") && iBandDim != i )
+        if( STARTS_WITH_CI(papszDimList[i], "X") && iBandDim != i )
             iXDim = i;
-        else if ( STARTS_WITH_CI(papszDimList[i], "Y") && iBandDim != i )
+        else if( STARTS_WITH_CI(papszDimList[i], "Y") && iBandDim != i )
             iYDim = i;
     }
 
     // If didn't get a band dimension yet, but have an extra
     // dimension, use it as the band dimension.
-    if ( iRank > 2 && iBandDim == -1 )
+    if( iRank > 2 && iBandDim == -1 )
     {
         if( iXDim != 0 && iYDim != 0 )
             iBandDim = 0;
@@ -1702,7 +1728,7 @@ void HDF4ImageDataset::GetSwatAttrs( int32 hSW )
 /* -------------------------------------------------------------------- */
 /*      At the start we will fetch the global HDF attributes.           */
 /* -------------------------------------------------------------------- */
-    int32   hDummy;
+    int32 hDummy = 0;
 
     EHidinfo( hHDF4, &hDummy, &hSD );
     ReadGlobalAttributes( hSD );
@@ -1711,9 +1737,9 @@ void HDF4ImageDataset::GetSwatAttrs( int32 hSW )
 /* -------------------------------------------------------------------- */
 /*      Fetch the esoteric HDF-EOS attributes then.                     */
 /* -------------------------------------------------------------------- */
-    int32   nStrBufSize = 0;
+    int32 nStrBufSize = 0;
 
-    if ( SWinqattrs( hSW, NULL, &nStrBufSize ) > 0 && nStrBufSize > 0 )
+    if( SWinqattrs( hSW, NULL, &nStrBufSize ) > 0 && nStrBufSize > 0 )
     {
         char *pszAttrList
             = reinterpret_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
@@ -1729,21 +1755,23 @@ void HDF4ImageDataset::GetSwatAttrs( int32 hSW )
         const int l_nAttrs = CSLCount( papszAttributes );
         for( int i = 0; i < l_nAttrs; i++ )
         {
-            int32 l_iNumType;
-            int32 nValues;
+            int32 l_iNumType = 0;
+            int32 nValues = 0;
 
-            if( SWattrinfo( hSW, papszAttributes[i], &l_iNumType, &nValues ) < 0 )
+            if( SWattrinfo( hSW, papszAttributes[i],
+                            &l_iNumType, &nValues ) < 0 )
                 continue;
 
             void *pData = NULL;
-            if ( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
-                pData = CPLMalloc( (nValues + 1) * GetDataTypeSize(l_iNumType) );
+            if( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
+                pData =
+                    CPLMalloc( (nValues + 1) * GetDataTypeSize(l_iNumType) );
             else
                 pData = CPLMalloc( nValues * GetDataTypeSize(l_iNumType) );
 
             SWreadattr( hSW, papszAttributes[i], pData );
 
-            if ( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
+            if( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
             {
                 reinterpret_cast<char *>( pData )[nValues] = '\0';
                 papszLocalMetadata = CSLAddNameValue(
@@ -1773,20 +1801,22 @@ void HDF4ImageDataset::GetSwatAttrs( int32 hSW )
 /*      After fetching HDF-EOS specific stuff we will read the generic  */
 /*      HDF attributes and append them to the list of metadata.         */
 /* -------------------------------------------------------------------- */
-    int32   l_iSDS;
-    if ( SWsdid(hSW, pszFieldName, &l_iSDS) != -1 )
+    int32 l_iSDS = 0;
+    if( SWsdid(hSW, pszFieldName, &l_iSDS) != -1 )
     {
-        int32 l_iRank, l_iNumType, l_nAttrs;
-        char        l_szName[HDF4_SDS_MAXNAMELEN];
-        int32       l_aiDimSizes[H4_MAX_VAR_DIMS];
+        int32 l_iRank = 0;
+        int32 l_iNumType = 0;
+        int32 l_nAttrs = 0;
+        char l_szName[HDF4_SDS_MAXNAMELEN] = {};
+        int32 l_aiDimSizes[H4_MAX_VAR_DIMS] = {};
 
         if( SDgetinfo( l_iSDS, l_szName, &l_iRank, l_aiDimSizes, &l_iNumType,
                        &l_nAttrs) == 0 )
         {
             for( int32 iAttribute = 0; iAttribute < l_nAttrs; iAttribute++ )
             {
-                char szAttrName[H4_MAX_NC_NAME];
-                int32 nValues;
+                char szAttrName[H4_MAX_NC_NAME] = {};
+                int32 nValues = 0;
                 SDattrinfo( l_iSDS, iAttribute, szAttrName,
                             &l_iNumType, &nValues );
                 papszLocalMetadata =
@@ -1812,7 +1842,7 @@ void HDF4ImageDataset::GetGridAttrs( int32 hGD )
 /* -------------------------------------------------------------------- */
 /*      At the start we will fetch the global HDF attributes.           */
 /* -------------------------------------------------------------------- */
-    int32   hDummy;
+    int32 hDummy = 0;
 
     EHidinfo( hHDF4, &hDummy, &hSD );
     ReadGlobalAttributes( hSD );
@@ -1821,9 +1851,9 @@ void HDF4ImageDataset::GetGridAttrs( int32 hGD )
 /* -------------------------------------------------------------------- */
 /*      Fetch the esoteric HDF-EOS attributes then.                     */
 /* -------------------------------------------------------------------- */
-    int32       nStrBufSize = 0;
+    int32 nStrBufSize = 0;
 
-    if ( GDinqattrs( hGD, NULL, &nStrBufSize ) > 0 && nStrBufSize > 0 )
+    if( GDinqattrs( hGD, NULL, &nStrBufSize ) > 0 && nStrBufSize > 0 )
     {
         char *pszAttrList
             = reinterpret_cast<char *>( CPLMalloc( nStrBufSize + 1 ) );
@@ -1839,19 +1869,21 @@ void HDF4ImageDataset::GetGridAttrs( int32 hGD )
         const int l_nAttrs = CSLCount( papszAttributes );
         for ( int i = 0; i < l_nAttrs; i++ )
         {
-            int32       l_iNumType, nValues;
+            int32 l_iNumType = 0;
+            int32 nValues = 0;
 
             GDattrinfo( hGD, papszAttributes[i], &l_iNumType, &nValues );
 
             void *pData = NULL;
-            if ( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
-                pData = CPLMalloc( (nValues + 1) * GetDataTypeSize(l_iNumType) );
+            if( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
+                pData =
+                    CPLMalloc( (nValues + 1) * GetDataTypeSize(l_iNumType) );
             else
                 pData = CPLMalloc( nValues * GetDataTypeSize(l_iNumType) );
 
             GDreadattr( hGD, papszAttributes[i], pData );
 
-            if ( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
+            if( l_iNumType == DFNT_CHAR8 || l_iNumType == DFNT_UCHAR8 )
             {
                 reinterpret_cast<char *>( pData )[nValues] = '\0';
                 papszLocalMetadata = CSLAddNameValue( papszLocalMetadata,
@@ -1879,19 +1911,22 @@ void HDF4ImageDataset::GetGridAttrs( int32 hGD )
 /*      After fetching HDF-EOS specific stuff we will read the generic  */
 /*      HDF attributes and append them to the list of metadata.         */
 /* -------------------------------------------------------------------- */
-    int32   l_iSDS;
-    if ( GDsdid(hGD, pszFieldName, &l_iSDS) != -1 )
+    int32 l_iSDS = 0;
+    if( GDsdid(hGD, pszFieldName, &l_iSDS) != -1 )
     {
-        int32 l_iRank, l_iNumType, l_nAttrs, nValues;
-        char        l_szName[HDF4_SDS_MAXNAMELEN];
-        int32       l_aiDimSizes[H4_MAX_VAR_DIMS];
+        int32 l_iRank = 0;
+        int32 l_iNumType = 0;
+        int32 l_nAttrs = 0;
+        int32 nValues = 0;
+        char l_szName[HDF4_SDS_MAXNAMELEN] = {};
+        int32 l_aiDimSizes[H4_MAX_VAR_DIMS] = {};
 
         if( SDgetinfo( l_iSDS, l_szName, &l_iRank, l_aiDimSizes, &l_iNumType,
                        &l_nAttrs) == 0 )
         {
             for( int32 iAttribute = 0; iAttribute < l_nAttrs; iAttribute++ )
             {
-                char    szAttrName[H4_MAX_NC_NAME];
+                char szAttrName[H4_MAX_NC_NAME] = {};
                 SDattrinfo( l_iSDS, iAttribute, szAttrName,
                             &l_iNumType, &nValues );
                 papszLocalMetadata =
@@ -1926,15 +1961,16 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
     if( EQUAL(szName,"longitude") || EQUAL(szName,"latitude") )
         return;
 
-    if (nRasterYSize == 1)
+    if( nRasterYSize == 1 )
         return;
 
 /* -------------------------------------------------------------------- */
 /*      Scan for latitude and longitude sections.                       */
 /* -------------------------------------------------------------------- */
-    int32   nDatasets, nAttributes;
+    int32 nDatasets = 0;
+    int32 nAttributes = 0;
 
-    if ( SDfileinfo( hSD, &nDatasets, &nAttributes ) != 0 )
+    if( SDfileinfo( hSD, &nDatasets, &nAttributes ) != 0 )
         return;
 
     int nLongitudeWidth = 0;
@@ -1945,9 +1981,11 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
     int iYIndex=-1;
     for( int iDSIndex = 0; iDSIndex < nDatasets; iDSIndex++ )
     {
-        int32 l_iRank, l_iNumType, l_nAttrs;
-        char        l_szName[HDF4_SDS_MAXNAMELEN];
-        int32       l_aiDimSizes[H4_MAX_VAR_DIMS];
+        int32 l_iRank = 0;
+        int32 l_iNumType = 0;
+        int32 l_nAttrs = 0;
+        char l_szName[HDF4_SDS_MAXNAMELEN] = {};
+        int32 l_aiDimSizes[H4_MAX_VAR_DIMS] = {};
 
         const int32 l_iSDS = SDselect( hSD, iDSIndex );
 
@@ -1981,9 +2019,12 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
     if( iXIndex == -1 || iYIndex == -1 )
         return;
 
-    int nPixelOffset = 0, nLineOffset = 0;
-    int nPixelStep = 1, nLineStep = 1;
-    if( nLongitudeWidth != nLatitudeWidth || nLongitudeHeight != nLatitudeHeight )
+    int nPixelOffset = 0;
+    int nLineOffset = 0;
+    int nPixelStep = 1;
+    int nLineStep = 1;
+    if( nLongitudeWidth != nLatitudeWidth ||
+        nLongitudeHeight != nLatitudeHeight )
     {
         CPLDebug("HDF4", "Longitude and latitude subdatasets don't have same "
                  "dimensions...");
@@ -2015,10 +2056,13 @@ void HDF4ImageDataset::ProcessModisSDSGeolocation(void)
     SetMetadataItem( "Y_DATASET", osWrk, "GEOLOCATION" );
     SetMetadataItem( "Y_BAND", "1" , "GEOLOCATION" );
 
-    SetMetadataItem( "PIXEL_OFFSET", CPLSPrintf("%d", nPixelOffset), "GEOLOCATION" );
-    SetMetadataItem( "PIXEL_STEP", CPLSPrintf("%d", nPixelStep), "GEOLOCATION" );
+    SetMetadataItem( "PIXEL_OFFSET", CPLSPrintf("%d", nPixelOffset),
+                     "GEOLOCATION" );
+    SetMetadataItem( "PIXEL_STEP", CPLSPrintf("%d", nPixelStep),
+                     "GEOLOCATION" );
 
-    SetMetadataItem( "LINE_OFFSET", CPLSPrintf("%d", nLineOffset), "GEOLOCATION" );
+    SetMetadataItem( "LINE_OFFSET", CPLSPrintf("%d", nLineOffset),
+                     "GEOLOCATION" );
     SetMetadataItem( "LINE_STEP", CPLSPrintf("%d", nLineStep), "GEOLOCATION" );
 }
 
@@ -2041,27 +2085,27 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         CSLFetchNameValue( papszLocalMetadata, "SHORTNAME" );
 
     HDF4EOSProduct eProduct = PROD_UNKNOWN;
-    if ( pszProduct )
+    if( pszProduct )
     {
-        if ( STARTS_WITH_CI(pszProduct, "ASTL1A") )
+        if( STARTS_WITH_CI(pszProduct, "ASTL1A") )
             eProduct = PROD_ASTER_L1A;
-        else if ( STARTS_WITH_CI(pszProduct, "ASTL1B") )
+        else if( STARTS_WITH_CI(pszProduct, "ASTL1B") )
             eProduct = PROD_ASTER_L1B;
-        else if ( STARTS_WITH_CI(pszProduct, "AST_04")
-                  || STARTS_WITH_CI(pszProduct, "AST_05")
-                  || STARTS_WITH_CI(pszProduct, "AST_06")
-                  || STARTS_WITH_CI(pszProduct, "AST_07")
-                  || STARTS_WITH_CI(pszProduct, "AST_08")
-                  || STARTS_WITH_CI(pszProduct, "AST_09")
-                  || STARTS_WITH_CI(pszProduct, "AST13")
-                  || STARTS_WITH_CI(pszProduct, "AST3") )
+        else if( STARTS_WITH_CI(pszProduct, "AST_04")
+                 || STARTS_WITH_CI(pszProduct, "AST_05")
+                 || STARTS_WITH_CI(pszProduct, "AST_06")
+                 || STARTS_WITH_CI(pszProduct, "AST_07")
+                 || STARTS_WITH_CI(pszProduct, "AST_08")
+                 || STARTS_WITH_CI(pszProduct, "AST_09")
+                 || STARTS_WITH_CI(pszProduct, "AST13")
+                 || STARTS_WITH_CI(pszProduct, "AST3") )
             eProduct = PROD_ASTER_L2;
-        else if ( STARTS_WITH_CI(pszProduct, "AST14") )
+        else if( STARTS_WITH_CI(pszProduct, "AST14") )
             eProduct = PROD_ASTER_L3;
-        else if ( STARTS_WITH_CI(pszProduct, "MOD02")
-                  || STARTS_WITH_CI(pszProduct, "MYD02") )
+        else if( STARTS_WITH_CI(pszProduct, "MOD02")
+                 || STARTS_WITH_CI(pszProduct, "MYD02") )
             eProduct = PROD_MODIS_L1B;
-        else if ( STARTS_WITH_CI(pszProduct, "MOD07_L2") )
+        else if( STARTS_WITH_CI(pszProduct, "MOD07_L2") )
             eProduct = PROD_MODIS_L2;
     }
 
@@ -2069,7 +2113,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 /*      Read names of geolocation fields and corresponding              */
 /*      geolocation maps.                                               */
 /* -------------------------------------------------------------------- */
-    int32 nStrBufSize;
+    int32 nStrBufSize = 0;
     const int32 nDataFields = SWnentries( hSW, HDFE_NENTGFLD, &nStrBufSize );
     if( nDataFields < 0 || nDataFields > 1024 * 1024 )
         return FALSE;
@@ -2079,8 +2123,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
     int32 *paiNumType
         = reinterpret_cast<int32 *>( CPLMalloc( nDataFields * sizeof(int32) ) );
 
-    if ( nDataFields !=
-         SWinqgeofields(hSW, pszGeoList, paiRank, paiNumType) )
+    if( nDataFields != SWinqgeofields(hSW, pszGeoList, paiRank, paiNumType) )
     {
         CPLDebug( "HDF4Image",
                   "Can't get the list of geolocation fields in swath \"%s\"",
@@ -2118,7 +2161,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
     int32 *paiIncrement = NULL;
 
     int32   nDimMaps = SWnentries( hSW, HDFE_NENTMAP, &nStrBufSize );
-    if ( nDimMaps <= 0 )
+    if( nDimMaps <= 0 )
     {
 
 #ifdef DEBUG
@@ -2130,17 +2173,13 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
                   papszDimList[iXDim], papszDimList[iYDim] );
 #endif
 
-        strncpy( szPixel, papszDimList[iXDim], N_BUF_SIZE );
-        szPixel[N_BUF_SIZE - 1] = '\0';
+        snprintf( szPixel, sizeof(szPixel), "%s", papszDimList[iXDim] );
 
-        strncpy( szLine, papszDimList[iYDim], N_BUF_SIZE );
-        szLine[N_BUF_SIZE - 1] = '\0';
+        snprintf( szLine, sizeof(szLine), "%s", papszDimList[iYDim]);
 
-        strncpy( szXGeo, papszDimList[iXDim], N_BUF_SIZE );
-        szXGeo[N_BUF_SIZE - 1] = '\0';
+        snprintf( szXGeo, sizeof(szXGeo), "%s", papszDimList[iXDim]);
 
-        strncpy( szYGeo, papszDimList[iYDim], N_BUF_SIZE );
-        szYGeo[N_BUF_SIZE - 1] = '\0';
+        snprintf( szYGeo, sizeof(szYGeo), "%s", papszDimList[iYDim]);
 
         paiOffset = reinterpret_cast<int32 *>( CPLCalloc( 2, sizeof(int32) ) );
         paiIncrement
@@ -2160,7 +2199,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
             = reinterpret_cast<int32 *>( CPLCalloc( nDimMaps, sizeof(int32) ) );
 
         *pszDimMaps = '\0';
-        if ( nDimMaps != SWinqmaps(hSW, pszDimMaps, paiOffset, paiIncrement) )
+        if( nDimMaps != SWinqmaps(hSW, pszDimMaps, paiOffset, paiIncrement) )
         {
             CPLDebug( "HDF4Image",
                       "Can't get the list of geolocation maps in swath \"%s\"",
@@ -2187,32 +2226,30 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         }
 #endif
 
-        char    **papszDimMap = CSLTokenizeString2( pszDimMaps, ",",
-                                                    CSLT_HONOURSTRINGS );
+        char **papszDimMap =
+            CSLTokenizeString2( pszDimMaps, ",", CSLT_HONOURSTRINGS );
         const int nDimMapCount = CSLCount(papszDimMap);
 
         for( int i = 0; i < nDimMapCount; i++ )
         {
-            if ( strstr(papszDimMap[i], papszDimList[iXDim]) )
+            if( strstr(papszDimMap[i], papszDimList[iXDim]) )
             {
-                strncpy( szPixel, papszDimList[iXDim], N_BUF_SIZE );
-                szPixel[N_BUF_SIZE - 1] = '\0';
+                snprintf( szPixel, sizeof(szPixel), "%s", papszDimList[iXDim] );
 
-                strncpy( szXGeo, papszDimMap[i], N_BUF_SIZE );
-                szXGeo[N_BUF_SIZE - 1] = '\0';
+                snprintf( szXGeo, sizeof(szXGeo), "%s", papszDimMap[i] );
 
                 char *pszTemp = strchr( szXGeo, '/' );
-                if ( pszTemp )
+                if( pszTemp )
                     *pszTemp = '\0';
             }
-            else if ( strstr(papszDimMap[i], papszDimList[iYDim]) )
+            else if( strstr(papszDimMap[i], papszDimList[iYDim]) )
             {
-                strncpy( szLine, papszDimList[iYDim], N_BUF_SIZE );
-                szLine[N_BUF_SIZE - 1] = '\0';
-                strncpy( szYGeo, papszDimMap[i], N_BUF_SIZE );
-                szYGeo[N_BUF_SIZE - 1] = '\0';
+                snprintf( szLine, sizeof(szLine), "%s", papszDimList[iYDim] );
+
+                snprintf( szYGeo, sizeof(szYGeo), "%s", papszDimMap[i] );
+
                 char *pszTemp = strchr( szYGeo, '/' );
-                if ( pszTemp )
+                if( pszTemp )
                     *pszTemp = '\0';
             }
         }
@@ -2221,7 +2258,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         CPLFree( pszDimMaps );
     }
 
-    if ( *szXGeo == 0 || *szYGeo == 0 )
+    if( *szXGeo == 0 || *szYGeo == 0 )
     {
         CPLFree( paiOffset );
         CPLFree( paiIncrement );
@@ -2232,17 +2269,17 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 /* -------------------------------------------------------------------- */
 /*      Read geolocation fields.                                        */
 /* -------------------------------------------------------------------- */
-    char    szGeoDimList[N_BUF_SIZE] = "";
-    char    **papszGeolocations = CSLTokenizeString2( pszGeoList, ",",
-                                                      CSLT_HONOURSTRINGS );
-    int     nGeolocationsCount = CSLCount( papszGeolocations );
-    int32   l_aiDimSizes[H4_MAX_VAR_DIMS];
+    char szGeoDimList[N_BUF_SIZE] = "";
+    char **papszGeolocations = CSLTokenizeString2( pszGeoList, ",",
+                                                   CSLT_HONOURSTRINGS );
+    const int nGeolocationsCount = CSLCount( papszGeolocations );
+    int32 l_aiDimSizes[H4_MAX_VAR_DIMS] = {};
 
     int32 iWrkNumType = 0;
     void *pLat = NULL;
     void *pLong = NULL;
 
-    int32 l_iRank;
+    int32 l_iRank = 0;
     int32 nLatCount = 0;
     int32 nLongCount = 0;
     int32 nXPoints = 0;
@@ -2258,11 +2295,11 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
     {
         // Skip "SceneLineNumber" table if present in the list of geolocation
         // fields. It is not needed to fetch geocoding data.
-        if ( EQUAL(papszGeolocations[i], "SceneLineNumber") )
+        if( EQUAL(papszGeolocations[i], "SceneLineNumber") )
             continue;
 
-        if ( SWfieldinfo( hSW, papszGeolocations[i], &l_iRank,
-                          l_aiDimSizes, &iWrkNumType, szGeoDimList ) < 0 )
+        if( SWfieldinfo( hSW, papszGeolocations[i], &l_iRank,
+                         l_aiDimSizes, &iWrkNumType, szGeoDimList ) < 0 )
         {
 
             CPLDebug( "HDF4Image",
@@ -2282,8 +2319,8 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         char **papszGeoDimList = CSLTokenizeString2( szGeoDimList,
                                                      ",", CSLT_HONOURSTRINGS );
 
-        int iXGeo = CSLFindString( papszGeoDimList, szXGeo );
-        int iYGeo = CSLFindString( papszGeoDimList, szYGeo );
+        const int iXGeo = CSLFindString( papszGeoDimList, szXGeo );
+        const int iYGeo = CSLFindString( papszGeoDimList, szYGeo );
         if( CSLCount(papszGeoDimList) > H4_MAX_VAR_DIMS
             || iXGeo < 0
             || iYGeo < 0 )
@@ -2299,7 +2336,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         nXPoints = l_aiDimSizes[iXGeo];
         nYPoints = l_aiDimSizes[iYGeo];
 
-        if ( EQUAL(szPixel, papszDimList[iXDim]) )
+        if( EQUAL(szPixel, papszDimList[iXDim]) )
         {
             iPixelDim = 1;
             iLineDim = 0;
@@ -2311,13 +2348,13 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         }
 
         iDataSize = GetDataTypeSize( iWrkNumType );
-        if ( strstr( papszGeolocations[i], "Latitude" ) )
+        if( strstr( papszGeolocations[i], "Latitude" ) )
         {
             iLatDim = i;
             nLatCount = nXPoints * nYPoints;
             pLat = CPLMalloc( nLatCount * iDataSize );
-            if (SWreadfield( hSW, papszGeolocations[i], NULL,
-                             NULL, NULL, (VOIDP)pLat ) < 0)
+            if( SWreadfield( hSW, papszGeolocations[i], NULL,
+                             NULL, NULL, (VOIDP)pLat ) < 0 )
             {
                 CPLDebug( "HDF4Image",
                           "Can't read geolocation field %s",
@@ -2326,13 +2363,13 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
                 pLat = NULL;
             }
         }
-        else if ( strstr( papszGeolocations[i], "Longitude" ) )
+        else if( strstr( papszGeolocations[i], "Longitude" ) )
         {
             iLongDim = i;
             nLongCount = nXPoints * nYPoints;
             pLong = CPLMalloc( nLongCount * iDataSize );
-            if (SWreadfield( hSW, papszGeolocations[i], NULL,
-                             NULL, NULL, (VOIDP)pLong ) < 0)
+            if( SWreadfield( hSW, papszGeolocations[i], NULL,
+                             NULL, NULL, (VOIDP)pLong ) < 0 )
             {
                 CPLDebug( "HDF4Image",
                           "Can't read geolocation field %s",
@@ -2350,20 +2387,20 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 /* -------------------------------------------------------------------- */
     void *pLatticeX = NULL;
     void *pLatticeY = NULL;
-    int32 iLatticeType;
+    int32 iLatticeType = 0;
     int32 iLatticeDataSize = 0;
-    if (SWfieldinfo(hSW, "LatticePoint", &l_iRank, l_aiDimSizes,
+    char pszLatticePoint[] = "LatticePoint";
+    if( SWfieldinfo(hSW, pszLatticePoint, &l_iRank, l_aiDimSizes,
                     &iLatticeType, szGeoDimList) == 0
         && l_iRank == 3
         && nXPoints == l_aiDimSizes[1]
         && nYPoints == l_aiDimSizes[0]
         && l_aiDimSizes[2] == 2 )
     {
-        iLatticeDataSize =
-            GetDataTypeSize( iLatticeType );
+        iLatticeDataSize = GetDataTypeSize( iLatticeType );
 
-        int32 iStart[H4_MAX_NC_DIMS];
-        int32 iEdges[H4_MAX_NC_DIMS];
+        int32 iStart[H4_MAX_NC_DIMS] = {};
+        int32 iEdges[H4_MAX_NC_DIMS] = {};
         iStart[1] = 0;
         iEdges[1] = nXPoints;
 
@@ -2374,8 +2411,8 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         iEdges[2] = 1;
 
         pLatticeX = CPLMalloc( nLatCount * iLatticeDataSize );
-        if (SWreadfield( hSW, "LatticePoint", iStart, NULL,
-                         iEdges, (VOIDP)pLatticeX ) < 0)
+        if( SWreadfield( hSW, pszLatticePoint, iStart, NULL,
+                         iEdges, (VOIDP)pLatticeX ) < 0 )
         {
             CPLDebug( "HDF4Image", "Can't read lattice field" );
             CPLFree( pLatticeX );
@@ -2386,14 +2423,13 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         iEdges[2] = 1;
 
         pLatticeY = CPLMalloc( nLatCount * iLatticeDataSize );
-        if (SWreadfield( hSW, "LatticePoint", iStart, NULL,
-                         iEdges, (VOIDP)pLatticeY ) < 0)
+        if( SWreadfield( hSW, pszLatticePoint, iStart, NULL,
+                         iEdges, (VOIDP)pLatticeY ) < 0 )
         {
             CPLDebug( "HDF4Image", "Can't read lattice field" );
             CPLFree( pLatticeY );
             pLatticeY = NULL;
         }
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -2401,48 +2437,56 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 /* -------------------------------------------------------------------- */
     const char *pszGEOL_AS_GCPS = CPLGetConfigOption( "GEOL_AS_GCPS",
                                                       "PARTIAL" );
-    int iGCPStepX;
-    int iGCPStepY;
+    int iGCPStepX = 0;
+    int iGCPStepY = 0;
 
     if( EQUAL(pszGEOL_AS_GCPS,"NONE") )
     {
-        iGCPStepX = iGCPStepY = 0;
+        // Leave as is: iGCPStepX = iGCPStepY = 0;
     }
     else if( EQUAL(pszGEOL_AS_GCPS,"FULL") )
     {
-        iGCPStepX = iGCPStepY = 1;
+        iGCPStepX = 1;
+        iGCPStepY = 1;
     }
     else
     {
         // Aim for 10x10 grid or so.
-        iGCPStepX = std::max( static_cast<int32>(1), ((nXPoints-1) / 11) );
-        iGCPStepY = std::max( static_cast<int32>(1), ((nYPoints-1) / 11) );
+        iGCPStepX = std::max(static_cast<int32>(1), ((nXPoints - 1) / 11));
+        iGCPStepY = std::max(static_cast<int32>(1), ((nYPoints - 1) / 11));
     }
 
 /* -------------------------------------------------------------------- */
 /*  Fetch projection information for various datasets.                  */
 /* -------------------------------------------------------------------- */
-    if ( nLatCount && nLongCount && nLatCount == nLongCount
-         && pLat && pLong )
+    if( nLatCount && nLongCount && nLatCount == nLongCount
+        && pLat && pLong )
     {
         CPLFree( pszGCPProjection );
         pszGCPProjection = NULL;
 
         // ASTER Level 1A
-        if ( eProduct == PROD_ASTER_L1A )
+        if( eProduct == PROD_ASTER_L1A )
         {
-            pszGCPProjection = CPLStrdup( "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST],AUTHORITY[\"EPSG\",\"4326\"]]" );
+            pszGCPProjection = CPLStrdup(
+                "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\","
+                "6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],"
+                "TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6326\"]],"
+                "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],"
+                "UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\","
+                "\"9108\"]],AXIS[\"Lat\",NORTH],AXIS[\"Long\",EAST],"
+                "AUTHORITY[\"EPSG\",\"4326\"]]" );
         }
 
         // ASTER Level 1B, Level 2
-        else if ( eProduct == PROD_ASTER_L1B
-                  || eProduct == PROD_ASTER_L2 )
+        else if( eProduct == PROD_ASTER_L1B
+                 || eProduct == PROD_ASTER_L2 )
         {
             // Constuct the metadata keys.
             // A band number is taken from the field name.
             const char *pszBand = strpbrk( pszFieldName, "0123456789" );
 
-            if ( !pszBand )
+            if( !pszBand )
                 pszBand = "";
 
             char *pszProjLine =
@@ -2468,11 +2512,12 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
             const char *pszZone =
                 CSLFetchNameValue( papszLocalMetadata,
                                    pszZoneLine );
+
+#ifdef DEBUG
             const char* pszEllipsoid =
                 CSLFetchNameValue( papszLocalMetadata,
                                    pszEllipsoidLine );
 
-#ifdef DEBUG
             CPLDebug( "HDF4Image",
                       "Projection %s=%s, parameters %s=%s, "
                       "zone %s=%s",
@@ -2483,31 +2528,29 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 #endif
 
             // Transform all mnemonic codes in the values.
-            int nParms;
             // Projection is UTM by default
-            long iProjSys = (pszProj) ?
-                USGSMnemonicToCode(pszProj) : 1L;
-            long iZone =
-                (pszZone && iProjSys == 1L) ? atoi(pszZone): 0L;
+            const long iProjSys = pszProj ? USGSMnemonicToCode(pszProj) : 1L;
+            const long iZone = (pszZone && iProjSys == 1L) ? atoi(pszZone): 0L;
+#if 0  // Not needed without the WGS84 check.
             char **papszEllipsoid = (pszEllipsoid) ?
                 CSLTokenizeString2( pszEllipsoid, ",",
                                     CSLT_HONOURSTRINGS ) : NULL;
+#endif
 
-            long iEllipsoid = 8L; // WGS84 by default
-            if ( papszEllipsoid
-                 && CSLCount(papszEllipsoid) > 0 )
+            const long iEllipsoid = 8L; // WGS84 by default
+#if 0  // This block is redundant.
+            if( papszEllipsoid && CSLCount(papszEllipsoid) > 0 )
             {
                 if (EQUAL( papszEllipsoid[0], "WGS84"))
                     iEllipsoid = 8L;
             }
-
-            char **papszParms = (pszParms) ?
-                CSLTokenizeString2( pszParms, ",",
-                                    CSLT_HONOURSTRINGS ) : NULL;
-            nParms = CSLCount(papszParms);
-            if (nParms >= 15)
+#endif
+            char **papszParms = pszParms ?
+                CSLTokenizeString2( pszParms, ",", CSLT_HONOURSTRINGS ) : NULL;
+            int nParms = CSLCount(papszParms);
+            if( nParms >= 15 )
                 nParms = 15;
-            double adfProjParms[15];
+            double adfProjParms[15] = {};
             for( int i = 0; i < nParms; i++)
                 adfProjParms[i] = CPLAtof( papszParms[i] );
             for ( int i = nParms; i < 15; i++)
@@ -2527,9 +2570,10 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         }
 
         // ASTER Level 3 (DEM)
-        else if ( eProduct == PROD_ASTER_L3 )
+        else if( eProduct == PROD_ASTER_L3 )
         {
-            double  dfCenterX, dfCenterY;
+            double dfCenterX = 0.0;
+            double dfCenterY = 0.0;
 
             ReadCoordinates( CSLFetchNameValue(
                                  papszGlobalMetadata, "SCENECENTER" ),
@@ -2549,8 +2593,8 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
         }
 
         // MODIS L1B
-        else if ( eProduct == PROD_MODIS_L1B
-                  || eProduct == PROD_MODIS_L2 )
+        else if( eProduct == PROD_MODIS_L1B
+                 || eProduct == PROD_MODIS_L2 )
         {
             pszGCPProjection = CPLStrdup( SRS_WKT_WGS84 );
         }
@@ -2572,7 +2616,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
             {
                 for( int j = 0; j < nXPoints; j += iGCPStepX )
                 {
-                    int iGeoOff =  i * nXPoints + j;
+                    const int iGeoOff = i * nXPoints + j;
 
                     pasGCPList[iGCP].dfGCPX =
                         AnyTypeToDouble(
@@ -2593,8 +2637,8 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
                     // do not need to be converted, because
                     // they are the same).
                     // This calculation valid for WGS84 datum only.
-                    if ( eProduct == PROD_ASTER_L1A
-                         || eProduct == PROD_ASTER_L1B )
+                    if( eProduct == PROD_ASTER_L1A
+                        || eProduct == PROD_ASTER_L1B )
                     {
                         pasGCPList[iGCP].dfGCPY =
                             atan(tan(pasGCPList[iGCP].dfGCPY
@@ -2606,7 +2650,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
 
                     pasGCPList[iGCP].dfGCPZ = 0.0;
 
-                    if ( pLatticeX && pLatticeY )
+                    if( pLatticeX && pLatticeY )
                     {
                         pasGCPList[iGCP].dfGCPPixel =
                             AnyTypeToDouble(
@@ -2621,7 +2665,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
                                     reinterpret_cast<char *>( pLatticeY )
                                     + iGeoOff*iLatticeDataSize ) ) + 0.5;
                     }
-                    else if ( paiOffset && paiIncrement )
+                    else if( paiOffset && paiIncrement )
                     {
                         pasGCPList[iGCP].dfGCPPixel =
                             paiOffset[iPixelDim] +
@@ -2659,7 +2703,7 @@ int HDF4ImageDataset::ProcessSwathGeolocation( int32 hSW, char **papszDimList )
             SetMetadataItem( "Y_DATASET", osWrk, "GEOLOCATION" );
             SetMetadataItem( "Y_BAND", "1" , "GEOLOCATION" );
 
-            if ( paiOffset && paiIncrement )
+            if( paiOffset && paiIncrement )
             {
                 osWrk.Printf( "%ld",
                               static_cast<long>( paiOffset[iPixelDim] ) );
@@ -2729,12 +2773,13 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     char **papszSubdatasetName
         = CSLTokenizeString2( poOpenInfo->pszFilename,
                               ":", CSLT_HONOURSTRINGS | CSLT_PRESERVEESCAPES);
-    if ( CSLCount( papszSubdatasetName ) != 4
-         && CSLCount( papszSubdatasetName ) != 5
-         && CSLCount( papszSubdatasetName ) != 6 )
+    if( CSLCount( papszSubdatasetName ) != 4
+        && CSLCount( papszSubdatasetName ) != 5
+        && CSLCount( papszSubdatasetName ) != 6 )
     {
         CSLDestroy( papszSubdatasetName );
-        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        // Release mutex otherwise we deadlock with GDALDataset own mutex.
+        CPLReleaseMutex(hHDF4Mutex);
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         return NULL;
@@ -2743,19 +2788,19 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     /* -------------------------------------------------------------------- */
     /*    Check for drive name in windows HDF4:"D:\...                      */
     /* -------------------------------------------------------------------- */
-    if (strlen(papszSubdatasetName[2]) == 1)
+    if( strlen(papszSubdatasetName[2]) == 1 )
     {
         const size_t nLen = 2 + strlen(papszSubdatasetName[3]) + 1;
-        char* pszFilename = reinterpret_cast<char *>(
-            CPLMalloc( nLen ) );
-        snprintf(pszFilename, nLen, "%s:%s", papszSubdatasetName[2], papszSubdatasetName[3]);
+        char* pszFilename = reinterpret_cast<char *>( CPLMalloc( nLen ) );
+        snprintf(pszFilename, nLen,
+                 "%s:%s", papszSubdatasetName[2], papszSubdatasetName[3]);
         CPLFree(papszSubdatasetName[2]);
         CPLFree(papszSubdatasetName[3]);
         papszSubdatasetName[2] = pszFilename;
 
         /* Move following arguments one rank upper */
         papszSubdatasetName[3] = papszSubdatasetName[4];
-        if (papszSubdatasetName[4] != NULL)
+        if( papszSubdatasetName[4] != NULL )
         {
             papszSubdatasetName[4] = papszSubdatasetName[5];
             papszSubdatasetName[5] = NULL;
@@ -2766,9 +2811,9 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( EQUAL( papszSubdatasetName[0], "HDF4_SDS" ) )
         poDS->iDatasetType = HDF4_SDS;
-    else if ( EQUAL( papszSubdatasetName[0], "HDF4_GR" ) )
+    else if( EQUAL( papszSubdatasetName[0], "HDF4_GR" ) )
         poDS->iDatasetType = HDF4_GR;
-    else if ( EQUAL( papszSubdatasetName[0], "HDF4_EOS" ) )
+    else if( EQUAL( papszSubdatasetName[0], "HDF4_EOS" ) )
         poDS->iDatasetType = HDF4_EOS;
     else
         poDS->iDatasetType = HDF4_UNKNOWN;
@@ -2791,10 +2836,11 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Is our file still here?                                         */
 /* -------------------------------------------------------------------- */
-    if ( !Hishdf( poDS->pszFilename ) )
+    if( !Hishdf( poDS->pszFilename ) )
     {
         CSLDestroy( papszSubdatasetName );
-        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        // Release mutex otherwise we deadlock with GDALDataset own mutex.
+        CPLReleaseMutex(hHDF4Mutex);
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         return NULL;
@@ -2814,18 +2860,25 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    double      dfNoData = 0, dfScale = 1, dfOffset = 0;
-    int         bNoDataSet = FALSE, bHaveScale = FALSE, bHaveOffset = FALSE;
-    const char  *pszUnits = NULL, *pszDescription = NULL;
+    double dfNoData = 0.0;
+    double dfScale = 1.0;
+    double dfOffset = 0.0;
+    bool bNoDataSet = false;
+    bool bHaveScale = false;
+    bool bHaveOffset = false;
+    const char *pszUnits = NULL;
+    const char *pszDescription = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Select SDS or GR to read from.                                  */
 /* -------------------------------------------------------------------- */
-    if ( poDS->iDatasetType == HDF4_EOS )
+    if( poDS->iDatasetType == HDF4_EOS )
     {
-        if (papszSubdatasetName[4] == NULL)
+        if( papszSubdatasetName[4] == NULL )
         {
-            CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            // Release mutex.  Otherwise it will deadlock with GDALDataset's own
+            // mutex.
+            CPLReleaseMutex(hHDF4Mutex);
             delete poDS;
             CPLAcquireMutex(hHDF4Mutex, 1000.0);
             return NULL;
@@ -2834,7 +2887,9 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->pszFieldName = CPLStrdup( papszSubdatasetName[4] );
     }
     else
+    {
         poDS->iDataset = atoi( papszSubdatasetName[3] );
+    }
     CSLDestroy( papszSubdatasetName );
 
     switch ( poDS->iDatasetType )
@@ -2860,10 +2915,12 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     CPLDebug( "HDF4Image",
                               "Can't open file \"%s\" for swath reading",
                               poDS->pszFilename );
-                    CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                    // Release mutex otherwise we deadlock with GDALDataset own
+                    // mutex.
+                    CPLReleaseMutex(hHDF4Mutex);
                     delete poDS;
                     CPLAcquireMutex(hHDF4Mutex, 1000.0);
-                    return( NULL );
+                    return NULL;
                 }
 
                 const int32 hSW
@@ -2872,23 +2929,27 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                 {
                     CPLDebug( "HDF4Image", "Can't attach to subdataset %s",
                               poDS->pszSubdatasetName );
-                    CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                     // Release mutex otherwise we deadlock with GDALDataset own
+                     // mutex.
+                    CPLReleaseMutex(hHDF4Mutex);
                     delete poDS;
                     CPLAcquireMutex(hHDF4Mutex, 1000.0);
-                    return( NULL );
+                    return NULL;
                 }
 
 /* -------------------------------------------------------------------- */
 /*      Decode the dimension map.                                       */
 /* -------------------------------------------------------------------- */
-                int32   nStrBufSize = 0;
+                int32 nStrBufSize = 0;
 
-                if ( SWnentries( hSW, HDFE_NENTDIM, &nStrBufSize ) < 0
-                     || nStrBufSize <= 0 )
+                if( SWnentries( hSW, HDFE_NENTDIM, &nStrBufSize ) < 0
+                    || nStrBufSize <= 0 )
                 {
                     CPLDebug( "HDF4Image",
                               "Can't read a number of dimension maps." );
-                    CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                    // Release mutex otherwise we deadlock with GDALDataset own
+                    // mutex.
+                    CPLReleaseMutex(hHDF4Mutex);
                     delete poDS;
                     CPLAcquireMutex(hHDF4Mutex, 1000.0);
                     return NULL;
@@ -2896,13 +2957,15 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
                 char *pszDimList = reinterpret_cast<char *>(
                     CPLMalloc( nStrBufSize + 1 ) );
-                if ( SWfieldinfo( hSW, poDS->pszFieldName, &poDS->iRank,
-                                  poDS->aiDimSizes, &poDS->iNumType,
-                                  pszDimList ) < 0 )
+                if( SWfieldinfo( hSW, poDS->pszFieldName, &poDS->iRank,
+                                 poDS->aiDimSizes, &poDS->iNumType,
+                                 pszDimList ) < 0 )
                 {
                     CPLDebug( "HDF4Image", "Can't read dimension maps." );
                     CPLFree( pszDimList );
-                    CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                     // Release mutex otherwise we deadlock with GDALDataset own
+                     // mutex.
+                    CPLReleaseMutex(hHDF4Mutex);
                     delete poDS;
                     CPLAcquireMutex(hHDF4Mutex, 1000.0);
                     return NULL;
@@ -2935,22 +2998,22 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
                 void *pNoDataValue =
                     CPLMalloc( poDS->GetDataTypeSize(poDS->iNumType) );
-                if ( SWgetfillvalue( hSW, poDS->pszFieldName,
-                                     pNoDataValue ) != -1 )
+                if( SWgetfillvalue( hSW, poDS->pszFieldName,
+                                    pNoDataValue ) != -1 )
                 {
                     dfNoData = poDS->AnyTypeToDouble( poDS->iNumType,
                                                       pNoDataValue );
-                    bNoDataSet = TRUE;
+                    bNoDataSet = true;
                 }
                 else
                 {
                     const char *pszNoData =
                         CSLFetchNameValue( poDS->papszLocalMetadata,
                                            "_FillValue" );
-                    if ( pszNoData )
+                    if( pszNoData )
                     {
                         dfNoData = CPLAtof( pszNoData );
-                        bNoDataSet = TRUE;
+                        bNoDataSet = true;
                     }
                 }
                 CPLFree( pNoDataValue );
@@ -2995,10 +3058,12 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     CPLDebug( "HDF4Image",
                               "Can't open file \"%s\" for grid reading",
                               poDS->pszFilename );
-                    CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                    // Release mutex otherwise we deadlock with GDALDataset own
+                    // mutex.
+                    CPLReleaseMutex(hHDF4Mutex);
                     delete poDS;
                     CPLAcquireMutex(hHDF4Mutex, 1000.0);
-                    return( NULL );
+                    return NULL;
                 }
 
                 const int32 hGD
@@ -3007,7 +3072,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Decode the dimension map.                                       */
 /* -------------------------------------------------------------------- */
-                char szDimList[N_BUF_SIZE];
+                char szDimList[N_BUF_SIZE] = {};
                 GDfieldinfo( hGD, poDS->pszFieldName, &poDS->iRank,
                              poDS->aiDimSizes, &poDS->iNumType, szDimList );
 #ifdef DEBUG
@@ -3017,17 +3082,18 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 #endif
                 poDS->GetImageDimensions( szDimList );
 
-                int32 tilecode, tilerank;
+                int32 tilecode = 0;
+                int32 tilerank = 0;
                 if( GDtileinfo( hGD, poDS->pszFieldName, &tilecode, &tilerank,
                                 NULL ) == 0 )
                 {
-                    if ( tilecode == HDFE_TILE )
+                    if( tilecode == HDFE_TILE )
                     {
                         int32 *tiledims = reinterpret_cast<int32 *>(
                             CPLCalloc( tilerank , sizeof( int32 ) ) );
                         GDtileinfo( hGD, poDS->pszFieldName, &tilecode,
                                     &tilerank, tiledims );
-                        if ( ( tilerank == 2 ) && ( poDS->iRank == tilerank  ) )
+                        if( ( tilerank == 2 ) && ( poDS->iRank == tilerank  ) )
                         {
                             poDS->nBlockPreferredXSize = tiledims[1];
                             poDS->nBlockPreferredYSize = tiledims[0];
@@ -3082,8 +3148,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                 int32 iSphereCode = 0;
                 double adfProjParms[15];
 
-                if ( GDprojinfo( hGD, &iProjCode, &iZoneCode,
-                                 &iSphereCode, adfProjParms) >= 0 )
+                if( GDprojinfo( hGD, &iProjCode, &iZoneCode,
+                                &iSphereCode, adfProjParms) >= 0 )
                 {
 #ifdef DEBUG
                     CPLDebug( "HDF4Image",
@@ -3098,20 +3164,19 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                                                adfProjParms, iSphereCode,
                                                USGS_ANGLE_RADIANS );
 
-                    if ( poDS->pszProjection )
-                        CPLFree( poDS->pszProjection );
+                    CPLFree( poDS->pszProjection );
                     poDS->oSRS.exportToWkt( &poDS->pszProjection );
                 }
 
 /* -------------------------------------------------------------------- */
 /*      Fetch geotransformation matrix                                  */
 /* -------------------------------------------------------------------- */
-                int32 nXSize;
-                int32 nYSize;
+                int32 nXSize = 0;
+                int32 nYSize = 0;
                 double adfUpLeft[2];
                 double adfLowRight[2];
-                if ( GDgridinfo( hGD, &nXSize, &nYSize,
-                                 adfUpLeft, adfLowRight ) >= 0 )
+                if( GDgridinfo( hGD, &nXSize, &nYSize,
+                                adfUpLeft, adfLowRight ) >= 0 )
                 {
 #ifdef DEBUG
                     CPLDebug( "HDF4Image",
@@ -3124,9 +3189,9 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                               static_cast<long>( nXSize ),
                               static_cast<long>( nYSize ) );
 #endif
-                    if ( iProjCode )
+                    if( iProjCode )
                     {
-                        // For projected systems coordinates are in meters
+                        // For projected systems coordinates are in meters.
                         poDS->adfGeoTransform[1] =
                             (adfLowRight[0] - adfUpLeft[0]) / nXSize;
                         poDS->adfGeoTransform[5] =
@@ -3136,7 +3201,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     }
                     else
                     {
-                        // Handle angular geographic coordinates here
+                        // Handle angular geographic coordinates here.
                         poDS->adfGeoTransform[1] =
                             (CPLPackedDMSToDec(adfLowRight[0]) -
                              CPLPackedDMSToDec(adfUpLeft[0])) / nXSize;
@@ -3150,7 +3215,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     }
                     poDS->adfGeoTransform[2] = 0.0;
                     poDS->adfGeoTransform[4] = 0.0;
-                    poDS->bHasGeoTransform = TRUE;
+                    poDS->bHasGeoTransform = true;
                 }
 
 /* -------------------------------------------------------------------- */
@@ -3165,22 +3230,22 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
                 void *pNoDataValue =
                     CPLMalloc( poDS->GetDataTypeSize(poDS->iNumType) );
-                if ( GDgetfillvalue( hGD, poDS->pszFieldName,
-                                     pNoDataValue ) != -1 )
+                if( GDgetfillvalue( hGD, poDS->pszFieldName,
+                                    pNoDataValue ) != -1 )
                 {
                     dfNoData = poDS->AnyTypeToDouble( poDS->iNumType,
                                                       pNoDataValue );
-                    bNoDataSet = TRUE;
+                    bNoDataSet = true;
                 }
                 else
                 {
                     const char *pszNoData =
                         CSLFetchNameValue( poDS->papszLocalMetadata,
                                            "_FillValue" );
-                    if ( pszNoData )
+                    if( pszNoData )
                     {
                         dfNoData = CPLAtof( pszNoData );
-                        bNoDataSet = TRUE;
+                        bNoDataSet = true;
                     }
                 }
                 CPLFree( pNoDataValue );
@@ -3199,10 +3264,10 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
               const char *pszTmp =
                   CSLFetchNameValue( poDS->papszLocalMetadata,
                                      "scale_factor" );
-              if ( pszTmp )
+              if( pszTmp )
               {
                   dfScale = CPLAtof( pszTmp );
-                  // some producers (i.e. lndcsm from LEDAPS) emit
+                  // Some producers (i.e. lndcsm from LEDAPS) emit
                   // files with scale_factor=0 which is crazy to carry
                   // through.
                   if( dfScale == 0.0 )
@@ -3213,10 +3278,10 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
               pszTmp =
                   CSLFetchNameValue( poDS->papszLocalMetadata, "add_offset" );
-              if ( pszTmp )
+              if( pszTmp )
               {
                   dfOffset = CPLAtof( pszTmp );
-                  bHaveOffset = TRUE;
+                  bHaveOffset = true;
               }
 
               pszUnits = CSLFetchNameValue( poDS->papszLocalMetadata,
@@ -3232,17 +3297,17 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
       case HDF4_SDS:
       {
-
 #ifdef HDF4_HAS_MAXOPENFILES
           // Attempt to increase maximum number of opened HDF files
-          intn  nCurrMax, nSysLimit;
+          intn nCurrMax = 0;
+          intn nSysLimit = 0;
 
-          if ( SDget_maxopenfiles(&nCurrMax, &nSysLimit) >= 0
-               && nCurrMax < nSysLimit )
+          if( SDget_maxopenfiles(&nCurrMax, &nSysLimit) >= 0
+              && nCurrMax < nSysLimit )
           {
               SDreset_maxopenfiles( nSysLimit );
           }
-#endif /* HDF4_HAS_MAXOPENFILES */
+#endif // HDF4_HAS_MAXOPENFILES
 
           if( poOpenInfo->eAccess == GA_ReadOnly )
               poDS->hHDF4 = Hopen( poDS->pszFilename, DFACC_READ, 0 );
@@ -3251,44 +3316,50 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
           if( poDS->hHDF4 <= 0 )
           {
-              CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+              // Release mutex otherwise we deadlock with GDALDataset own mutex.
+              CPLReleaseMutex(hHDF4Mutex);
               delete poDS;
               CPLAcquireMutex(hHDF4Mutex, 1000.0);
-              return( NULL );
+              return NULL;
           }
 
           poDS->hSD = SDstart( poDS->pszFilename, DFACC_READ );
-          if ( poDS->hSD == -1 )
+          if( poDS->hSD == -1 )
           {
-              CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            // Release mutex otherwise we deadlock with GDALDataset own mutex.
+              CPLReleaseMutex(hHDF4Mutex);
               delete poDS;
               CPLAcquireMutex(hHDF4Mutex, 1000.0);
               return NULL;
           }
 
-          if ( poDS->ReadGlobalAttributes( poDS->hSD ) != CE_None )
+          if( poDS->ReadGlobalAttributes( poDS->hSD ) != CE_None )
           {
-              CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+              // Release mutex otherwise we deadlock with GDALDataset own mutex.
+              CPLReleaseMutex(hHDF4Mutex);
               delete poDS;
               CPLAcquireMutex(hHDF4Mutex, 1000.0);
               return NULL;
           }
 
-          int32   nDatasets, l_nAttrs;
-          if ( SDfileinfo( poDS->hSD, &nDatasets, &l_nAttrs ) != 0 )
+          int32 nDatasets = 0;
+          int32 l_nAttrs = 0;
+          if( SDfileinfo( poDS->hSD, &nDatasets, &l_nAttrs ) != 0 )
           {
-              CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+              // Release mutex otherwise we deadlock with GDALDataset own mutex.
+              CPLReleaseMutex(hHDF4Mutex);
               delete poDS;
               CPLAcquireMutex(hHDF4Mutex, 1000.0);
               return NULL;
           }
 
-          if (poDS->iDataset < 0 || poDS->iDataset >= nDatasets)
+          if( poDS->iDataset < 0 || poDS->iDataset >= nDatasets )
           {
               CPLError(CE_Failure, CPLE_AppDefined,
                        "Subdataset index should be between 0 and %ld",
                        static_cast<long int>( nDatasets ) - 1);
-              CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+              // Release mutex otherwise we deadlock with GDALDataset own mutex.
+              CPLReleaseMutex(hHDF4Mutex);
               delete poDS;
               CPLAcquireMutex(hHDF4Mutex, 1000.0);
               return NULL;
@@ -3299,15 +3370,15 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
           SDgetinfo( iSDS, poDS->szName, &poDS->iRank, poDS->aiDimSizes,
                      &poDS->iNumType, &poDS->nAttrs);
 
-          // We will duplicate global metadata for every subdataset
+          // We will duplicate global metadata for every subdataset.
           poDS->papszLocalMetadata =
               CSLDuplicate( poDS->papszGlobalMetadata );
 
           for( int32 iAttribute = 0; iAttribute < poDS->nAttrs; iAttribute++ )
           {
-              char  szAttrName[H4_MAX_NC_NAME];
-              int32 iAttrNumType;
-              int32 nValues;
+              char szAttrName[H4_MAX_NC_NAME] = {};
+              int32 iAttrNumType = 0;
+              int32 nValues = 0;
               SDattrinfo( iSDS, iAttribute, szAttrName,
                           &iAttrNumType, &nValues );
               poDS->papszLocalMetadata =
@@ -3328,7 +3399,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                     static_cast<long>( poDS->aiDimSizes[2] ),
                     static_cast<long>( poDS->aiDimSizes[3] ) );
 #endif
-
           switch( poDS->iRank )
           {
             case 1:
@@ -3342,11 +3412,12 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
               poDS->iYDim = 0;
               break;
             case 3:
-              /* FIXME: We should probably remove the following test as there are valid datasets */
-              /* where the height is lower than the band number : for example
-                 http://www.iapmw.unibe.ch/research/projects/FriOWL/data/otd/LISOTD_HRAC_V2.2.hdf */
-              /* which is a 720x360 x 365 bands */
-              /* Use a HACK for now */
+              // TODO: We should probably remove the following test as there are
+              // valid datasets where the height is lower than the band number.
+              // For example:
+              //   http://www.iapmw.unibe.ch/research/projects/FriOWL/data/otd/LISOTD_HRAC_V2.2.hdf
+              // which is a 720x360 x 365 bands.
+              // Use a HACK for now.
               if( poDS->aiDimSizes[0] < poDS->aiDimSizes[2] &&
                   !(poDS->aiDimSizes[0] == 360 &&
                     poDS->aiDimSizes[1] == 720 &&
@@ -3383,7 +3454,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
           // We preset this because CaptureNRLGeoTransform needs it.
           poDS->nRasterXSize = poDS->aiDimSizes[poDS->iXDim];
-          if (poDS->iYDim >= 0)
+          if( poDS->iYDim >= 0 )
             poDS->nRasterYSize = poDS->aiDimSizes[poDS->iYDim];
           else
             poDS->nRasterYSize = 1;
@@ -3415,17 +3486,18 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /*  'Plain' HDF rasters.                                                */
 /* -------------------------------------------------------------------- */
       case HDF4_GR:
-
-        // Attempt to increase maximum number of opened HDF files
+      {
+        // Attempt to increase maximum number of opened HDF files.
 #ifdef HDF4_HAS_MAXOPENFILES
-        intn    nCurrMax, nSysLimit;
+        intn nCurrMax = 0;
+        intn nSysLimit = 0;
 
-        if ( SDget_maxopenfiles(&nCurrMax, &nSysLimit) >= 0
-             && nCurrMax < nSysLimit )
+        if( SDget_maxopenfiles(&nCurrMax, &nSysLimit) >= 0
+            && nCurrMax < nSysLimit )
         {
             SDreset_maxopenfiles( nSysLimit );
         }
-#endif /* HDF4_HAS_MAXOPENFILES */
+#endif  // HDF4_HAS_MAXOPENFILES
 
         if( poOpenInfo->eAccess == GA_ReadOnly )
             poDS->hHDF4 = Hopen( poDS->pszFilename, DFACC_READ, 0 );
@@ -3434,40 +3506,44 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if( poDS->hHDF4 <= 0 )
         {
-            CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            // Release mutex otherwise we deadlock with GDALDataset own mutex.
+            CPLReleaseMutex(hHDF4Mutex);
             delete poDS;
             CPLAcquireMutex(hHDF4Mutex, 1000.0);
-            return( NULL );
+            return NULL;
         }
 
         poDS->hGR = GRstart( poDS->hHDF4 );
-        if ( poDS->hGR == -1 )
+        if( poDS->hGR == -1 )
         {
-            CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            // Release mutex otherwise wel deadlock with GDALDataset own mutex.
+            CPLReleaseMutex(hHDF4Mutex);
             delete poDS;
             CPLAcquireMutex(hHDF4Mutex, 1000.0);
             return NULL;
         }
 
         poDS->iGR = GRselect( poDS->hGR, poDS->iDataset );
-        if ( GRgetiminfo( poDS->iGR, poDS->szName,
-                          &poDS->iRank, &poDS->iNumType,
-                          &poDS->iInterlaceMode, poDS->aiDimSizes,
-                          &poDS->nAttrs ) != 0 )
+        if( GRgetiminfo( poDS->iGR, poDS->szName,
+                         &poDS->iRank, &poDS->iNumType,
+                         &poDS->iInterlaceMode, poDS->aiDimSizes,
+                         &poDS->nAttrs ) != 0 )
         {
-            CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            // Release mutex otherwise we deadlock with GDALDataset own mutex.
+            CPLReleaseMutex(hHDF4Mutex);
             delete poDS;
             CPLAcquireMutex(hHDF4Mutex, 1000.0);
             return NULL;
         }
 
-        // We will duplicate global metadata for every subdataset
+        // We will duplicate global metadata for every subdataset.
         poDS->papszLocalMetadata = CSLDuplicate( poDS->papszGlobalMetadata );
 
         for( int32 iAttribute = 0; iAttribute < poDS->nAttrs; iAttribute++ )
         {
-            char    szAttrName[H4_MAX_NC_NAME];
-            int32 nValues, iAttrNumType;
+            char szAttrName[H4_MAX_NC_NAME] = {};
+            int32 nValues = 0;
+            int32 iAttrNumType = 0;
             GRattrinfo( poDS->iGR, iAttribute, szAttrName,
                         &iAttrNumType, &nValues );
             poDS->papszLocalMetadata =
@@ -3480,7 +3556,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
         // Read colour table
 
         poDS->iPal = GRgetlutid ( poDS->iGR, poDS->iDataset );
-        if ( poDS->iPal != -1 )
+        if( poDS->iPal != -1 )
         {
             GRgetlutinfo( poDS->iPal, &poDS->nComps, &poDS->iPalDataType,
                           &poDS->iPalInterlaceMode, &poDS->nPalEntries );
@@ -3502,23 +3578,25 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->iYDim = 1;
         poDS->nBandCount = poDS->iRank;
         break;
+      }
       default:
-        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        CPLReleaseMutex(hHDF4Mutex);
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         return NULL;
     }
 
     poDS->nRasterXSize = poDS->aiDimSizes[poDS->iXDim];
-    if (poDS->iYDim >= 0)
+    if( poDS->iYDim >= 0 )
         poDS->nRasterYSize = poDS->aiDimSizes[poDS->iYDim];
     else
         poDS->nRasterYSize = 1;
 
-    if ( poDS->iSubdatasetType == H4ST_HYPERION_L1 )
+    if( poDS->iSubdatasetType == H4ST_HYPERION_L1 )
     {
         // XXX: Hyperion SDSs has Height x Bands x Width dimensions scheme
-        if ( poDS->iRank > 2 )
+        if( poDS->iRank > 2 )
         {
             poDS->nBandCount = poDS->aiDimSizes[1];
             poDS->nRasterXSize = poDS->aiDimSizes[2];
@@ -3542,21 +3620,21 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                                      poDS->GetDataType( poDS->iNumType ) );
         poDS->SetBand( i, poBand );
 
-        if ( bNoDataSet )
+        if( bNoDataSet )
             poBand->SetNoDataValue( dfNoData );
-        if ( bHaveScale )
+        if( bHaveScale )
         {
-            poBand->bHaveScale = TRUE;
+            poBand->bHaveScale = true;
             poBand->dfScale = dfScale;
         }
-        if ( bHaveOffset )
+        if( bHaveOffset )
         {
-            poBand->bHaveOffset = TRUE;
+            poBand->bHaveOffset = true;
             poBand->dfOffset = dfOffset;
         }
-        if ( pszUnits )
+        if( pszUnits )
             poBand->osUnitType =  pszUnits;
-        if ( pszDescription )
+        if( pszDescription )
             poBand->SetDescription( pszDescription );
     }
 
@@ -3577,35 +3655,35 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
           const char  *pszValue =
             CSLFetchNameValue( poDS->papszGlobalMetadata, "Projection" );
-          if ( pszValue != NULL )
+          if( pszValue != NULL )
           {
               CPLFree( poDS->pszProjection );
               poDS->pszProjection = CPLStrdup( pszValue );
           }
-          if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                             "TransformationMatrix")) != NULL )
+          if( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                            "TransformationMatrix")) != NULL )
           {
               int i = 0;
               char *pszString = const_cast<char *>( pszValue );
-              while ( *pszValue && i < 6 )
+              while( *pszValue && i < 6 )
               {
                   poDS->adfGeoTransform[i++] = CPLStrtod(pszString, &pszString);
                   pszString++;
               }
-              poDS->bHasGeoTransform = TRUE;
+              poDS->bHasGeoTransform = true;
           }
           for( int i = 1; i <= poDS->nBands; i++ )
           {
-              if ( (pszValue =
-                    CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                      CPLSPrintf("BandDesc%d", i))) != NULL )
+              if( (pszValue =
+                   CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                     CPLSPrintf("BandDesc%d", i))) != NULL )
                   poDS->GetRasterBand( i )->SetDescription( pszValue );
           }
           for( int i = 1; i <= poDS->nBands; i++ )
           {
-              if ( (pszValue =
-                    CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                      CPLSPrintf("NoDataValue%d", i))) != NULL )
+              if( (pszValue =
+                   CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                     CPLSPrintf("NoDataValue%d", i))) != NULL )
                   poDS->GetRasterBand(i)->SetNoDataValue( CPLAtof(pszValue) );
           }
       }
@@ -3626,17 +3704,16 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                   CSLFetchNameValue( poDS->papszGlobalMetadata, "Parameter" ) );
           }
 
-          // Read coordinate system and geotransform matrix
+          // Read coordinate system and geotransform matrix.
           poDS->oSRS.SetWellKnownGeogCS( "WGS84" );
 
-          if ( EQUAL(CSLFetchNameValue(poDS->papszGlobalMetadata,
-                                       "Map Projection"),
-                     "Equidistant Cylindrical") )
+          if( EQUAL(CSLFetchNameValue(poDS->papszGlobalMetadata,
+                                      "Map Projection"),
+                    "Equidistant Cylindrical") )
           {
               poDS->oSRS.SetEquirectangular( 0.0, 0.0, 0.0, 0.0 );
               poDS->oSRS.SetLinearUnits( SRS_UL_METER, 1 );
-              if ( poDS->pszProjection )
-                  CPLFree( poDS->pszProjection );
+              CPLFree( poDS->pszProjection );
               poDS->oSRS.exportToWkt( &poDS->pszProjection );
           }
 
@@ -3654,11 +3731,11 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
           poDS->adfGeoTransform[3] = dfULY;
           poDS->adfGeoTransform[1] = (dfLRX - dfULX) / poDS->nRasterXSize;
           poDS->adfGeoTransform[5] = (dfULY - dfLRY) / poDS->nRasterYSize;
-          if ( dfULY > 0)     // Northern hemisphere
+          if( dfULY > 0)  // Northern hemisphere.
               poDS->adfGeoTransform[5] = - poDS->adfGeoTransform[5];
           poDS->adfGeoTransform[2] = 0.0;
           poDS->adfGeoTransform[4] = 0.0;
-          poDS->bHasGeoTransform = TRUE;
+          poDS->bHasGeoTransform = true;
       }
       break;
 
@@ -3667,7 +3744,6 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
       case H4ST_UNKNOWN:
       {
-
           // This is a coastwatch convention.
           if( CSLFetchNameValue( poDS->papszLocalMetadata, "missing_value" ) )
           {
@@ -3689,14 +3765,15 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                       = reinterpret_cast<HDF4ImageRasterBand *>(
                           poDS->GetRasterBand(i) );
 
-                  poBand->bHaveScale = poBand->bHaveOffset = TRUE;
+                  poBand->bHaveScale = true;
+                  poBand->bHaveOffset = true;
                   poBand->dfScale =
                       CPLAtof( CSLFetchNameValue( poDS->papszLocalMetadata,
                                                   "scale_factor" ) );
                   // See #4891 regarding offset interpretation.
-                  //poBand->dfOffset = -1 * poBand->dfScale *
-                  //  CPLAtof( CSLFetchNameValue( poDS->papszLocalMetadata,
-                  //                              "add_offset" ) );
+                  //  poBand->dfOffset = -1 * poBand->dfScale *
+                  //      CPLAtof( CSLFetchNameValue( poDS->papszLocalMetadata,
+                  //                                  "add_offset" ) );
                   poBand->dfOffset =
                       CPLAtof( CSLFetchNameValue( poDS->papszLocalMetadata,
                                                   "add_offset" ) );
@@ -3726,7 +3803,8 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
                       reinterpret_cast<HDF4ImageRasterBand *>(
                           poDS->GetRasterBand(i) );
 
-                  poBand->bHaveScale = poBand->bHaveOffset = TRUE;
+                  poBand->bHaveScale = true;
+                  poBand->bHaveOffset = true;
                   poBand->dfScale =
                       CPLAtof( CSLFetchNameValue( poDS->papszLocalMetadata,
                                                   "scalingSlope" ) );
@@ -3753,7 +3831,7 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
 
 #ifdef DEBUG_VERBOSE
         CPLError( CE_Debug, CPLE_AppDefined,
-                  "Unknown subdata type %d\n", poDS->iSubdatasetType );
+                  "Unknown subdata type %d", poDS->iSubdatasetType );
 #endif
         break;
     }
@@ -3764,13 +3842,14 @@ GDALDataset *HDF4ImageDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->SetPhysicalFilename( poDS->pszFilename );
     poDS->SetSubdatasetName( osSubdatasetName );
 
-    CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    // Release mutex otherwise we'll deadlock with GDALDataset own mutex.
+    CPLReleaseMutex(hHDF4Mutex);
     poDS->TryLoadXML();
 
     poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
     CPLAcquireMutex(hHDF4Mutex, 1000.0);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -3813,16 +3892,17 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
 /*      Choose rank for the created dataset.                            */
 /* -------------------------------------------------------------------- */
     poDS->iRank = 3;
-    if ( CSLFetchNameValue( papszOptions, "RANK" ) != NULL &&
-         EQUAL( CSLFetchNameValue( papszOptions, "RANK" ), "2" ) )
+    if( CSLFetchNameValue( papszOptions, "RANK" ) != NULL &&
+        EQUAL( CSLFetchNameValue( papszOptions, "RANK" ), "2" ) )
         poDS->iRank = 2;
 
     poDS->hSD = SDstart( pszFilename, DFACC_CREATE );
-    if ( poDS->hSD == -1 )
+    if( poDS->hSD == -1 )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Can't create HDF4 file %s", pszFilename );
-        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        // Release mutex otherwise we'll deadlock with GDALDataset own mutex.
+        CPLReleaseMutex(hHDF4Mutex);
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         return NULL;
@@ -3831,7 +3911,7 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
     poDS->iYDim = 0;
     poDS->iBandDim = 2;
 
-    int32 aiDimSizes[H4_MAX_VAR_DIMS];
+    int32 aiDimSizes[H4_MAX_VAR_DIMS] = {};
     aiDimSizes[poDS->iXDim] = nXSize;
     aiDimSizes[poDS->iYDim] = nYSize;
     aiDimSizes[poDS->iBandDim] = nBands;
@@ -3839,7 +3919,7 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
     const char *pszSDSName = NULL;
     int32 iSDS = -1;
 
-    if ( poDS->iRank == 2 )
+    if( poDS->iRank == 2 )
     {
         for( int iBand = 0; iBand < nBands; iBand++ )
         {
@@ -3879,7 +3959,7 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
             SDendaccess( iSDS );
         }
     }
-    else if ( poDS->iRank == 3 )
+    else if( poDS->iRank == 3 )
     {
         pszSDSName = "3-dimensional Scientific Dataset";
         poDS->iDataset = 0;
@@ -3918,19 +3998,21 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
     }
     else
     {
-        // Should never happen
-        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        // Should never happen.
+        // Release mutex otherwise we'll deadlock with GDALDataset own mutex.
+        CPLReleaseMutex(hHDF4Mutex);
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         return NULL;
     }
 
-    if ( iSDS < 0 )
+    if( iSDS < 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Can't create SDS with rank %ld for file %s",
                   static_cast<long>( poDS->iRank ), pszFilename );
-        CPLReleaseMutex(hHDF4Mutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        // Release mutex otherwise we'll deadlock with GDALDataset own mutex.
+        CPLReleaseMutex(hHDF4Mutex);
         delete poDS;
         CPLAcquireMutex(hHDF4Mutex, 1000.0);
         return NULL;
@@ -3949,7 +4031,8 @@ GDALDataset *HDF4ImageDataset::Create( const char * pszFilename,
     for( int iBand = 1; iBand <= nBands; iBand++ )
         poDS->SetBand( iBand, new HDF4ImageRasterBand( poDS, iBand, eType ) );
 
-    SDsetattr( poDS->hSD, "Signature", DFNT_CHAR8, static_cast<int>(strlen(pszGDALSignature)) + 1,
+    SDsetattr( poDS->hSD, "Signature", DFNT_CHAR8,
+               static_cast<int>(strlen(pszGDALSignature)) + 1,
                pszGDALSignature );
 
     return reinterpret_cast<GDALDataset *>( poDS );
@@ -3974,10 +4057,11 @@ void GDALRegister_HDF4Image()
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
                                "Byte Int16 UInt16 Int32 UInt32 "
                                "Float32 Float64" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-"<CreationOptionList>"
-"   <Option name='RANK' type='int' description='Rank of output SDS'/>"
-"</CreationOptionList>" );
+    poDriver->SetMetadataItem(
+        GDAL_DMD_CREATIONOPTIONLIST,
+        "<CreationOptionList>"
+        "   <Option name='RANK' type='int' description='Rank of output SDS'/>"
+        "</CreationOptionList>" );
 
     poDriver->pfnOpen = HDF4ImageDataset::Open;
     poDriver->pfnCreate = HDF4ImageDataset::Create;
diff --git a/frmts/hdf4/makefile.vc b/frmts/hdf4/makefile.vc
index 4e2f3f4..92ece89 100644
--- a/frmts/hdf4/makefile.vc
+++ b/frmts/hdf4/makefile.vc
@@ -6,7 +6,7 @@ OBJ	=	hdf4dataset.obj hdf4imagedataset.obj
 
 PLUGIN_DLL 	=	gdal_HDF4.dll
 
-EXTRAFLAGS = 	-I..\pds -I$(HDF4_DIR)\include -Ihdf-eos -DFRMT_hdf4 
+EXTRAFLAGS = 	-I..\pds -I$(HDF4_INCLUDE) -I$(HDF4_DIR)\include -Ihdf-eos -DFRMT_hdf4 
 
 !IF "$(HDF4_PLUGIN)" == "YES"
 EXTRAFLAGS = $(EXTRAFLAGS) -DHDF4_PLUGIN
@@ -31,7 +31,7 @@ clean:
 plugin:	$(PLUGIN_DLL)
 
 $(PLUGIN_DLL): $(OBJ)
-	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) ..\o\SWapi.obj ..\o\GDapi.obj ..\o\EHapi.obj ..\o\gctp_wrap.obj ..\o\nasakeywordhandler.obj $(GDALLIB) $(HDF4_LIB)
+	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) ..\o\SWapi.obj ..\o\GDapi.obj ..\o\EHapi.obj ..\o\gctp_wrap.obj $(GDALLIB) $(HDF4_LIB)
 	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
 
 plugin-install:
diff --git a/frmts/hdf5/GNUmakefile b/frmts/hdf5/GNUmakefile
index a513630..2795aa1 100644
--- a/frmts/hdf5/GNUmakefile
+++ b/frmts/hdf5/GNUmakefile
@@ -4,7 +4,7 @@ include ../../GDALmake.opt
 OBJ	=	hdf5dataset.o hdf5imagedataset.o \
 		bagdataset.o gh5_convenience.o iso19115_srs.o
 
-HDFEOS_OPTS	=	
+HDFEOS_OPTS	=
 SUBLIBS 	=
 
 CPPFLAGS	:=	 $(HDF5_INCLUDE) $(CPPFLAGS)
diff --git a/frmts/hdf5/bagdataset.cpp b/frmts/hdf5/bagdataset.cpp
index 54ded40..244054e 100644
--- a/frmts/hdf5/bagdataset.cpp
+++ b/frmts/hdf5/bagdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: bagdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Read BAG datasets.
@@ -28,18 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gh5_convenience.h"
 
 #include "cpl_string.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "gdal_priv.h"
+#include "iso19115_srs.h"
+#include "ogr_core.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: bagdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <algorithm>
 
-OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
-                                   const char *pszISOXML );
+CPL_CVSID("$Id: bagdataset.cpp 37926 2017-04-08 21:03:01Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -62,12 +63,12 @@ class BAGDataset : public GDALPamDataset
 
 public:
     BAGDataset();
-    ~BAGDataset();
+    virtual ~BAGDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char *GetProjectionRef(void);
-    virtual char      **GetMetadataDomainList();
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char *GetProjectionRef(void) override;
+    virtual char      **GetMetadataDomainList() override;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
 
     static GDALDataset  *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -94,23 +95,27 @@ class BAGRasterBand : public GDALPamRasterBand
 
 public:
     BAGRasterBand( BAGDataset *, int );
-    ~BAGRasterBand();
+    virtual ~BAGRasterBand();
 
     bool                    Initialize( hid_t hDataset, const char *pszName );
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual double	    GetNoDataValue( int * );
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual double          GetNoDataValue( int * ) override;
 
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum( int *pbSuccess = NULL );
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum( int *pbSuccess = NULL ) override;
 };
 
 /************************************************************************/
 /*                           BAGRasterBand()                            */
 /************************************************************************/
 BAGRasterBand::BAGRasterBand( BAGDataset *poDS_, int nBand_ ) :
-    hDatasetID(-1), native(-1), dataspace(-1), bMinMaxSet(false),
-    dfMinimum(0.0), dfMaximum(0.0)
+    hDatasetID(-1),
+    native(-1),
+    dataspace(-1),
+    bMinMaxSet(false),
+    dfMinimum(0.0),
+    dfMaximum(0.0)
 {
     poDS = poDS_;
     nBand = nBand_;
@@ -122,14 +127,14 @@ BAGRasterBand::BAGRasterBand( BAGDataset *poDS_, int nBand_ ) :
 
 BAGRasterBand::~BAGRasterBand()
 {
-  if( dataspace > 0 )
-    H5Sclose(dataspace);
+    if( dataspace > 0 )
+        H5Sclose(dataspace);
 
-  if( native > 0 )
-    H5Tclose( native );
+    if( native > 0 )
+        H5Tclose(native);
 
-  if( hDatasetID > 0 )
-    H5Dclose( hDatasetID );
+    if( hDatasetID > 0 )
+        H5Dclose(hDatasetID);
 }
 
 /************************************************************************/
@@ -139,14 +144,14 @@ BAGRasterBand::~BAGRasterBand()
 bool BAGRasterBand::Initialize( hid_t hDatasetIDIn, const char *pszName )
 
 {
-    SetDescription( pszName );
+    SetDescription(pszName);
 
     hDatasetID = hDatasetIDIn;
 
-    const hid_t datatype = H5Dget_type( hDatasetIDIn );
-    dataspace = H5Dget_space( hDatasetIDIn );
-    const int n_dims = H5Sget_simple_extent_ndims( dataspace );
-    native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
+    const hid_t datatype = H5Dget_type(hDatasetIDIn);
+    dataspace = H5Dget_space(hDatasetIDIn);
+    const int n_dims = H5Sget_simple_extent_ndims(dataspace);
+    native = H5Tget_native_type(datatype, H5T_DIR_ASCEND);
     hsize_t dims[3] = {
       static_cast<hsize_t>(0),
       static_cast<hsize_t>(0),
@@ -158,31 +163,27 @@ bool BAGRasterBand::Initialize( hid_t hDatasetIDIn, const char *pszName )
       static_cast<hsize_t>(0)
     };
 
-    eDataType = GH5_GetDataType( native );
+    eDataType = GH5_GetDataType(native);
 
     if( n_dims == 2 )
     {
-        H5Sget_simple_extent_dims( dataspace, dims, maxdims );
+        H5Sget_simple_extent_dims(dataspace, dims, maxdims);
 
         nRasterXSize = static_cast<int>(dims[1]);
         nRasterYSize = static_cast<int>(dims[0]);
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Dataset not of rank 2." );
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset not of rank 2.");
         return false;
     }
 
-    nBlockXSize   = nRasterXSize;
-    nBlockYSize   = 1;
+    nBlockXSize = nRasterXSize;
+    nBlockYSize = 1;
 
-/* -------------------------------------------------------------------- */
-/*      Check for chunksize, and use it as blocksize for optimized      */
-/*      reading.                                                        */
-/* -------------------------------------------------------------------- */
-    const hid_t listid = H5Dget_create_plist( hDatasetIDIn );
-    if (listid>0)
+    // Check for chunksize, and use it as blocksize for optimized reading.
+    const hid_t listid = H5Dget_create_plist(hDatasetIDIn);
+    if( listid > 0 )
     {
         if(H5Pget_layout(listid) == H5D_CHUNKED)
         {
@@ -192,59 +193,60 @@ bool BAGRasterBand::Initialize( hid_t hDatasetIDIn, const char *pszName )
               static_cast<hsize_t>(0)
             };
             const int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
-            nBlockXSize  = static_cast<int>(panChunkDims[nDimSize-1]);
-            nBlockYSize  = static_cast<int>(panChunkDims[nDimSize-2]);
+            nBlockXSize = static_cast<int>(panChunkDims[nDimSize - 1]);
+            nBlockYSize = static_cast<int>(panChunkDims[nDimSize - 2]);
         }
 
-        int nfilters = H5Pget_nfilters( listid );
+        int nfilters = H5Pget_nfilters(listid);
 
-        char name[120];
-        size_t       cd_nelmts = 20;
-        unsigned int cd_values[20];
-        unsigned int flags;
-        for (int i = 0; i < nfilters; i++)
+        char name[120] = {};
+        size_t cd_nelmts = 20;
+        unsigned int cd_values[20] = {};
+        unsigned int flags = 0;
+        for( int i = 0; i < nfilters; i++ )
         {
-          const H5Z_filter_t filter =
-              H5Pget_filter(listid, i, &flags, &cd_nelmts, cd_values, 120, name);
-          if (filter == H5Z_FILTER_DEFLATE)
-            poDS->SetMetadataItem( "COMPRESSION", "DEFLATE", "IMAGE_STRUCTURE" );
-          else if (filter == H5Z_FILTER_NBIT)
-            poDS->SetMetadataItem( "COMPRESSION", "NBIT", "IMAGE_STRUCTURE" );
-          else if (filter == H5Z_FILTER_SCALEOFFSET)
-            poDS->SetMetadataItem( "COMPRESSION", "SCALEOFFSET", "IMAGE_STRUCTURE" );
-          else if (filter == H5Z_FILTER_SZIP)
-            poDS->SetMetadataItem( "COMPRESSION", "SZIP", "IMAGE_STRUCTURE" );
+            const H5Z_filter_t filter = H5Pget_filter(
+                listid, i, &flags, &cd_nelmts, cd_values, 120, name);
+            if( filter == H5Z_FILTER_DEFLATE )
+                poDS->SetMetadataItem("COMPRESSION", "DEFLATE",
+                                      "IMAGE_STRUCTURE");
+            else if( filter == H5Z_FILTER_NBIT )
+                poDS->SetMetadataItem("COMPRESSION", "NBIT", "IMAGE_STRUCTURE");
+            else if( filter == H5Z_FILTER_SCALEOFFSET )
+                poDS->SetMetadataItem("COMPRESSION", "SCALEOFFSET",
+                                      "IMAGE_STRUCTURE");
+            else if( filter == H5Z_FILTER_SZIP )
+                poDS->SetMetadataItem("COMPRESSION", "SZIP", "IMAGE_STRUCTURE");
         }
 
         H5Pclose(listid);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Load min/max information.                                       */
-/* -------------------------------------------------------------------- */
-    if( EQUAL(pszName,"elevation")
-        && GH5_FetchAttribute( hDatasetIDIn, "Maximum Elevation Value",
-                            dfMaximum )
-        && GH5_FetchAttribute( hDatasetIDIn, "Minimum Elevation Value",
-                               dfMinimum ) )
+    // Load min/max information.
+    if( EQUAL(pszName,"elevation") &&
+        GH5_FetchAttribute(hDatasetIDIn, "Maximum Elevation Value",
+                           dfMaximum) &&
+        GH5_FetchAttribute(hDatasetIDIn, "Minimum Elevation Value", dfMinimum) )
+    {
         bMinMaxSet = true;
-    else if( EQUAL(pszName,"uncertainty")
-             && GH5_FetchAttribute( hDatasetIDIn, "Maximum Uncertainty Value",
-                                    dfMaximum )
-             && GH5_FetchAttribute( hDatasetIDIn, "Minimum Uncertainty Value",
-                                    dfMinimum ) )
-    {
-        /* Some products where uncertainty band is completely set to nodata */
-        /* wrongly declare minimum and maximum to 0.0 */
+    }
+    else if( EQUAL(pszName, "uncertainty") &&
+             GH5_FetchAttribute(hDatasetIDIn, "Maximum Uncertainty Value",
+                                dfMaximum) &&
+             GH5_FetchAttribute(hDatasetIDIn, "Minimum Uncertainty Value",
+                                dfMinimum) )
+    {
+        // Some products where uncertainty band is completely set to nodata
+        // wrongly declare minimum and maximum to 0.0.
         if( dfMinimum != 0.0 && dfMaximum != 0.0 )
             bMinMaxSet = true;
     }
-    else if( EQUAL(pszName,"nominal_elevation")
-             && GH5_FetchAttribute( hDatasetIDIn, "max_value",
-                                    dfMaximum )
-             && GH5_FetchAttribute( hDatasetIDIn, "min_value",
-                                    dfMinimum ) )
+    else if( EQUAL(pszName, "nominal_elevation") &&
+             GH5_FetchAttribute(hDatasetIDIn, "max_value", dfMaximum) &&
+             GH5_FetchAttribute(hDatasetIDIn, "min_value", dfMinimum) )
+    {
         bMinMaxSet = true;
+    }
 
     return true;
 }
@@ -263,14 +265,14 @@ double BAGRasterBand::GetMinimum( int * pbSuccess )
         return dfMinimum;
     }
 
-    return GDALRasterBand::GetMinimum( pbSuccess );
+    return GDALRasterBand::GetMinimum(pbSuccess);
 }
 
 /************************************************************************/
 /*                             GetMaximum()                             */
 /************************************************************************/
 
-double BAGRasterBand::GetMaximum( int * pbSuccess )
+double BAGRasterBand::GetMaximum( int *pbSuccess )
 
 {
     if( bMinMaxSet )
@@ -280,126 +282,108 @@ double BAGRasterBand::GetMaximum( int * pbSuccess )
         return dfMaximum;
     }
 
-    return GDALRasterBand::GetMaximum( pbSuccess );
+    return GDALRasterBand::GetMaximum(pbSuccess);
 }
 
 /************************************************************************/
 /*                           GetNoDataValue()                           */
 /************************************************************************/
-double BAGRasterBand::GetNoDataValue( int * pbSuccess )
+double BAGRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
     if( pbSuccess )
         *pbSuccess = TRUE;
 
-    if( EQUAL(GetDescription(),"elevation") )
-        return  1000000.0;
-    if( EQUAL(GetDescription(),"uncertainty") )
+    if( EQUAL(GetDescription(), "elevation") )
         return 1000000.0;
-    if( EQUAL(GetDescription(),"nominal_elevation") )
+    if( EQUAL(GetDescription(), "uncertainty") )
+        return 1000000.0;
+    if( EQUAL(GetDescription(), "nominal_elevation") )
         return 1000000.0;
 
-    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+    return GDALPamRasterBand::GetNoDataValue(pbSuccess);
 }
 
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 CPLErr BAGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                  void * pImage )
+                                  void *pImage )
 {
+    const int nXOff = nBlockXOff * nBlockXSize;
     H5OFFSET_TYPE offset[3] = {
-      static_cast<H5OFFSET_TYPE>(MAX(0, nRasterYSize - (nBlockYOff+1)*nBlockYSize)),
-      static_cast<H5OFFSET_TYPE>(nBlockXOff * nBlockXSize),
-      static_cast<H5OFFSET_TYPE>(0)
-    };
-    hsize_t count[3] = {
-      static_cast<hsize_t>(nBlockYSize),
-      static_cast<hsize_t>(nBlockXSize),
-      static_cast<hsize_t>(0)
+        static_cast<H5OFFSET_TYPE>(
+            std::max(0, nRasterYSize - (nBlockYOff + 1) * nBlockYSize)),
+        static_cast<H5OFFSET_TYPE>(nXOff),
+        static_cast<H5OFFSET_TYPE>(0)
     };
 
-    const int nSizeOfData = static_cast<int>(H5Tget_size( native ));
-    memset( pImage,0,nBlockXSize*nBlockYSize*nSizeOfData );
+    const int nSizeOfData = static_cast<int>(H5Tget_size(native));
+    memset(pImage, 0, nBlockXSize * nBlockYSize * nSizeOfData);
 
-/*  blocksize may not be a multiple of imagesize */
-    count[0] = MIN( size_t(nBlockYSize), GetYSize() - offset[0] );
-    count[1] = MIN( size_t(nBlockXSize), GetXSize() - offset[1] );
+    //  Blocksize may not be a multiple of imagesize.
+    hsize_t count[3] = {
+        std::min(static_cast<hsize_t>(nBlockYSize), GetYSize() - offset[0]),
+        std::min(static_cast<hsize_t>(nBlockXSize), GetXSize() - offset[1]),
+        static_cast<hsize_t>(0)
+    };
 
-    if( nRasterYSize - (nBlockYOff+1)*nBlockYSize < 0 )
+    if( nRasterYSize - (nBlockYOff + 1) * nBlockYSize < 0 )
     {
-        count[0] += (nRasterYSize - (nBlockYOff+1)*nBlockYSize );
+        count[0] += (nRasterYSize - (nBlockYOff + 1) * nBlockYSize);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Select block from file space                                    */
-/* -------------------------------------------------------------------- */
-    herr_t status =  H5Sselect_hyperslab( dataspace,
-                                          H5S_SELECT_SET,
-                                          offset, NULL,
-                                          count, NULL );
-    if( status < 0 )
-        return CE_Failure;
+    // Select block from file space.
+    {
+        const herr_t status =
+            H5Sselect_hyperslab(dataspace, H5S_SELECT_SET,
+                                 offset, NULL, count, NULL);
+        if( status < 0 )
+            return CE_Failure;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Create memory space to receive the data                         */
-/* -------------------------------------------------------------------- */
+    // Create memory space to receive the data.
     hsize_t col_dims[3] = {
-      static_cast<hsize_t>(nBlockYSize),
-      static_cast<hsize_t>(nBlockXSize),
-      static_cast<hsize_t>(0)
+        static_cast<hsize_t>(nBlockYSize),
+        static_cast<hsize_t>(nBlockXSize),
+        static_cast<hsize_t>(0)
     };
-    hsize_t rank = 2;
-    const hid_t memspace =
-        H5Screate_simple( static_cast<int>(rank), col_dims, NULL );
-    H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
-    status =  H5Sselect_hyperslab(memspace,
-                                  H5S_SELECT_SET,
-                                  mem_offset, NULL,
-                                  count, NULL);
+    const int rank = 2;
+    const hid_t memspace = H5Screate_simple(rank, col_dims, NULL);
+    H5OFFSET_TYPE mem_offset[3] = { 0, 0, 0 };
+    const herr_t status =
+        H5Sselect_hyperslab(memspace, H5S_SELECT_SET,
+                            mem_offset, NULL, count, NULL);
     if( status < 0 )
         return CE_Failure;
 
-    status = H5Dread ( hDatasetID,
-                       native,
-                       memspace,
-                       dataspace,
-                       H5P_DEFAULT,
-                       pImage );
+    const herr_t status_read =
+        H5Dread(hDatasetID, native, memspace, dataspace, H5P_DEFAULT, pImage);
 
-    H5Sclose( memspace );
+    H5Sclose(memspace);
 
-/* -------------------------------------------------------------------- */
-/*      Y flip the data.                                                */
-/* -------------------------------------------------------------------- */
+    // Y flip the data.
     const int nLinesToFlip = static_cast<int>(count[0]);
     const int nLineSize = nSizeOfData * nBlockXSize;
-    GByte *pabyTemp = static_cast<GByte *>(CPLMalloc(nLineSize));
+    GByte * const pabyTemp = static_cast<GByte *>(CPLMalloc(nLineSize));
+    GByte * const pbyImage = static_cast<GByte *>(pImage);
 
-    for( int iY = 0; iY < nLinesToFlip/2; iY++ )
+    for( int iY = 0; iY < nLinesToFlip / 2; iY++ )
     {
-        memcpy( pabyTemp,
-                reinterpret_cast<GByte *>(pImage) + iY * nLineSize,
-                nLineSize );
-        memcpy( reinterpret_cast<GByte *>(pImage) + iY * nLineSize,
-                (reinterpret_cast<GByte *>(pImage) + (nLinesToFlip-iY-1) *
-                 nLineSize),
-                nLineSize );
-        memcpy( (reinterpret_cast<GByte *>(pImage) + (nLinesToFlip-iY-1) *
-                 nLineSize),
-                pabyTemp,
-                nLineSize );
+        memcpy(pabyTemp, pbyImage + iY * nLineSize, nLineSize);
+        memcpy(pbyImage + iY * nLineSize,
+               pbyImage + (nLinesToFlip - iY - 1) * nLineSize,
+               nLineSize);
+        memcpy(pbyImage + (nLinesToFlip - iY - 1) * nLineSize, pabyTemp,
+               nLineSize);
     }
 
-    CPLFree( pabyTemp );
+    CPLFree(pabyTemp);
 
-/* -------------------------------------------------------------------- */
-/*      Return success or failure.                                      */
-/* -------------------------------------------------------------------- */
-    if( status < 0 )
+    // Return success or failure.
+    if( status_read < 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "H5Dread() failed for block." );
+        CPLError(CE_Failure, CPLE_AppDefined, "H5Dread() failed for block.");
         return CE_Failure;
     }
 
@@ -435,15 +419,15 @@ BAGDataset::BAGDataset() :
 /************************************************************************/
 /*                            ~BAGDataset()                             */
 /************************************************************************/
-BAGDataset::~BAGDataset( )
+BAGDataset::~BAGDataset()
 {
     FlushCache();
 
     if( hHDF5 >= 0 )
-        H5Fclose( hHDF5 );
+        H5Fclose(hHDF5);
 
-    CPLFree( pszProjection );
-    CPLFree( pszXMLMetadata );
+    CPLFree(pszProjection);
+    CPLFree(pszXMLMetadata);
 }
 
 /************************************************************************/
@@ -453,19 +437,15 @@ BAGDataset::~BAGDataset( )
 int BAGDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Is it an HDF5 file?                                             */
-/* -------------------------------------------------------------------- */
+    // Is it an HDF5 file?
     static const char achSignature[] = "\211HDF\r\n\032\n";
 
-    if( poOpenInfo->pabyHeader == NULL
-        || memcmp(poOpenInfo->pabyHeader,achSignature,8) != 0 )
+    if( poOpenInfo->pabyHeader == NULL ||
+        memcmp(poOpenInfo->pabyHeader, achSignature, 8) != 0 )
         return FALSE;
 
-/* -------------------------------------------------------------------- */
-/*      Does it have the extension .bag?                                */
-/* -------------------------------------------------------------------- */
-    if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"bag") )
+    // Does it have the extension .bag?
+    if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "bag") )
         return FALSE;
 
     return TRUE;
@@ -475,82 +455,67 @@ int BAGDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *BAGDataset::Open( GDALOpenInfo *poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Confirm that this appears to be a BAG file.                     */
-/* -------------------------------------------------------------------- */
-    if( !Identify( poOpenInfo ) )
+    // Confirm that this appears to be a BAG file.
+    if( !Identify(poOpenInfo) )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
+    // Confirm the requested access is supported.
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "The BAG driver does not support update access." );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The BAG driver does not support update access.");
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Open the file as an HDF5 file.                                  */
-/* -------------------------------------------------------------------- */
-    hid_t hHDF5 = H5Fopen( poOpenInfo->pszFilename,
-                           H5F_ACC_RDONLY, H5P_DEFAULT );
+    // Open the file as an HDF5 file.
+    hid_t hHDF5 = H5Fopen(poOpenInfo->pszFilename, H5F_ACC_RDONLY, H5P_DEFAULT);
 
     if( hHDF5 < 0 )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Confirm it is a BAG dataset by checking for the                 */
-/*      BAG_Root/Bag Version attribute.                                 */
-/* -------------------------------------------------------------------- */
-    const hid_t hBagRoot = H5Gopen( hHDF5, "/BAG_root" );
+    // Confirm it is a BAG dataset by checking for the
+    // BAG_Root/Bag Version attribute.
+    const hid_t hBagRoot = H5Gopen(hHDF5, "/BAG_root");
     const hid_t hVersion =
-        ( hBagRoot >= 0 ) ? H5Aopen_name( hBagRoot, "Bag Version" ) : -1;
+        hBagRoot >= 0 ? H5Aopen_name(hBagRoot, "Bag Version") : -1;
 
     if( hVersion < 0 )
     {
         if( hBagRoot >= 0 )
-            H5Gclose( hBagRoot );
-        H5Fclose( hHDF5 );
+            H5Gclose(hBagRoot);
+        H5Fclose(hHDF5);
         return NULL;
     }
-    H5Aclose( hVersion );
+    H5Aclose(hVersion);
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding dataset.                                 */
-/* -------------------------------------------------------------------- */
-    BAGDataset * const poDS = new BAGDataset();
+    // Create a corresponding dataset.
+    BAGDataset *const poDS = new BAGDataset();
 
     poDS->hHDF5 = hHDF5;
 
-/* -------------------------------------------------------------------- */
-/*      Extract version as metadata.                                    */
-/* -------------------------------------------------------------------- */
+    // Extract version as metadata.
     CPLString osVersion;
 
-    if( GH5_FetchAttribute( hBagRoot, "Bag Version", osVersion ) )
-        poDS->SetMetadataItem( "BagVersion", osVersion );
+    if( GH5_FetchAttribute(hBagRoot, "Bag Version", osVersion) )
+        poDS->SetMetadataItem("BagVersion", osVersion);
 
-    H5Gclose( hBagRoot );
+    H5Gclose(hBagRoot);
 
-/* -------------------------------------------------------------------- */
-/*      Fetch the elevation dataset and attach as a band.               */
-/* -------------------------------------------------------------------- */
+    // Fetch the elevation dataset and attach as a band.
     int nNextBand = 1;
-    const hid_t hElevation = H5Dopen( hHDF5, "/BAG_root/elevation" );
+    const hid_t hElevation = H5Dopen(hHDF5, "/BAG_root/elevation");
     if( hElevation < 0 )
     {
         delete poDS;
         return NULL;
     }
 
-    BAGRasterBand *poElevBand = new BAGRasterBand( poDS, nNextBand );
+    BAGRasterBand *poElevBand = new BAGRasterBand(poDS, nNextBand);
 
-    if( !poElevBand->Initialize( hElevation, "elevation" ) )
+    if( !poElevBand->Initialize(hElevation, "elevation") )
     {
         delete poElevBand;
         delete poDS;
@@ -560,56 +525,49 @@ GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterXSize = poElevBand->nRasterXSize;
     poDS->nRasterYSize = poElevBand->nRasterYSize;
 
-    poDS->SetBand( nNextBand++, poElevBand );
+    poDS->SetBand(nNextBand++, poElevBand);
 
-/* -------------------------------------------------------------------- */
-/*      Try to do the same for the uncertainty band.                    */
-/* -------------------------------------------------------------------- */
-    const hid_t hUncertainty = H5Dopen( hHDF5, "/BAG_root/uncertainty" );
-    BAGRasterBand *poUBand = new BAGRasterBand( poDS, nNextBand );
+    // Try to do the same for the uncertainty band.
+    const hid_t hUncertainty = H5Dopen(hHDF5, "/BAG_root/uncertainty");
+    BAGRasterBand *poUBand = new BAGRasterBand(poDS, nNextBand);
 
-    if( hUncertainty >= 0 && poUBand->Initialize( hUncertainty, "uncertainty") )
+    if( hUncertainty >= 0 && poUBand->Initialize(hUncertainty, "uncertainty") )
     {
-        poDS->SetBand( nNextBand++, poUBand );
+        poDS->SetBand(nNextBand++, poUBand);
     }
     else
+    {
         delete poUBand;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Try to do the same for the nominal_elevation band.              */
-/* -------------------------------------------------------------------- */
+    // Try to do the same for the nominal_elevation band.
     hid_t hNominal = -1;
 
     H5E_BEGIN_TRY {
-        hNominal = H5Dopen( hHDF5, "/BAG_root/nominal_elevation" );
+        hNominal = H5Dopen(hHDF5, "/BAG_root/nominal_elevation");
     } H5E_END_TRY;
 
-    BAGRasterBand * const poNBand = new BAGRasterBand( poDS, nNextBand );
-    if( hNominal >= 0 && poNBand->Initialize( hNominal,
-                                              "nominal_elevation" ) )
+    BAGRasterBand *const poNBand = new BAGRasterBand(poDS, nNextBand);
+    if( hNominal >= 0 && poNBand->Initialize(hNominal, "nominal_elevation") )
     {
-        poDS->SetBand( nNextBand++, poNBand );
+        poDS->SetBand(nNextBand++, poNBand);
     }
     else
+    {
         delete poNBand;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Load the XML metadata.                                          */
-/* -------------------------------------------------------------------- */
+    // Load the XML metadata.
     poDS->LoadMetadata();
 
-/* -------------------------------------------------------------------- */
-/*      Setup/check for pam .aux.xml.                                   */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    // Setup/check for pam .aux.xml.
+    poDS->SetDescription(poOpenInfo->pszFilename);
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Setup overviews.                                                */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    // Setup overviews.
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -619,103 +577,93 @@ GDALDataset *BAGDataset::Open( GDALOpenInfo * poOpenInfo )
 void BAGDataset::LoadMetadata()
 
 {
-/* -------------------------------------------------------------------- */
-/*      Load the metadata from the file.                                */
-/* -------------------------------------------------------------------- */
-    const hid_t hMDDS = H5Dopen( hHDF5, "/BAG_root/metadata" );
-    const hid_t datatype = H5Dget_type( hMDDS );
-    const hid_t dataspace = H5Dget_space( hMDDS );
-    const hid_t native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
+    // Load the metadata from the file.
+    const hid_t hMDDS = H5Dopen(hHDF5, "/BAG_root/metadata");
+    const hid_t datatype = H5Dget_type(hMDDS);
+    const hid_t dataspace = H5Dget_space(hMDDS);
+    const hid_t native = H5Tget_native_type(datatype, H5T_DIR_ASCEND);
     hsize_t dims[3] = {
-      static_cast<hsize_t>(0),
-      static_cast<hsize_t>(0),
-      static_cast<hsize_t>(0)
+        static_cast<hsize_t>(0),
+        static_cast<hsize_t>(0),
+        static_cast<hsize_t>(0)
     };
     hsize_t maxdims[3] = {
-      static_cast<hsize_t>(0),
-      static_cast<hsize_t>(0),
-      static_cast<hsize_t>(0)
+        static_cast<hsize_t>(0),
+        static_cast<hsize_t>(0),
+        static_cast<hsize_t>(0)
     };
 
-    H5Sget_simple_extent_dims( dataspace, dims, maxdims );
+    H5Sget_simple_extent_dims(dataspace, dims, maxdims);
 
-    pszXMLMetadata = static_cast<char *>(
-        CPLCalloc(static_cast<int>(dims[0]+1),1));
+    pszXMLMetadata =
+        static_cast<char *>(CPLCalloc(static_cast<int>(dims[0] + 1), 1));
 
-    H5Dread( hMDDS, native, H5S_ALL, dataspace, H5P_DEFAULT, pszXMLMetadata );
+    H5Dread(hMDDS, native, H5S_ALL, dataspace, H5P_DEFAULT, pszXMLMetadata);
 
-    H5Tclose( native );
-    H5Sclose( dataspace );
-    H5Tclose( datatype );
-    H5Dclose( hMDDS );
+    H5Tclose(native);
+    H5Sclose(dataspace);
+    H5Tclose(datatype);
+    H5Dclose(hMDDS);
 
     if( strlen(pszXMLMetadata) == 0 )
         return;
 
-/* -------------------------------------------------------------------- */
-/*      Try to get the geotransform.                                    */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode *psRoot = CPLParseXMLString( pszXMLMetadata );
+    // Try to get the geotransform.
+    CPLXMLNode *psRoot = CPLParseXMLString(pszXMLMetadata);
 
     if( psRoot == NULL )
         return;
 
-    CPLStripXMLNamespace( psRoot, NULL, TRUE );
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
 
-    CPLXMLNode * const psGeo = CPLSearchXMLNode( psRoot, "=MD_Georectified" );
+    CPLXMLNode *const psGeo = CPLSearchXMLNode(psRoot, "=MD_Georectified");
 
     if( psGeo != NULL )
     {
-        char **papszCornerTokens =
-            CSLTokenizeStringComplex(
-                CPLGetXMLValue( psGeo, "cornerPoints.Point.coordinates", "" ),
-                " ,", FALSE, FALSE );
+        char **papszCornerTokens = CSLTokenizeStringComplex(
+            CPLGetXMLValue(psGeo, "cornerPoints.Point.coordinates", ""), " ,",
+            FALSE, FALSE);
 
-        if( CSLCount(papszCornerTokens ) == 4 )
+        if( CSLCount(papszCornerTokens) == 4 )
         {
-            const double dfLLX = CPLAtof( papszCornerTokens[0] );
-            const double dfLLY = CPLAtof( papszCornerTokens[1] );
-            const double dfURX = CPLAtof( papszCornerTokens[2] );
-            const double dfURY = CPLAtof( papszCornerTokens[3] );
+            const double dfLLX = CPLAtof(papszCornerTokens[0]);
+            const double dfLLY = CPLAtof(papszCornerTokens[1]);
+            const double dfURX = CPLAtof(papszCornerTokens[2]);
+            const double dfURY = CPLAtof(papszCornerTokens[3]);
 
             adfGeoTransform[0] = dfLLX;
-            adfGeoTransform[1] = (dfURX - dfLLX) / (GetRasterXSize()-1);
+            adfGeoTransform[1] = (dfURX - dfLLX) / (GetRasterXSize() - 1);
             adfGeoTransform[3] = dfURY;
-            adfGeoTransform[5] = (dfLLY - dfURY) / (GetRasterYSize()-1);
+            adfGeoTransform[5] = (dfLLY - dfURY) / (GetRasterYSize() - 1);
 
             adfGeoTransform[0] -= adfGeoTransform[1] * 0.5;
             adfGeoTransform[3] -= adfGeoTransform[5] * 0.5;
         }
-        CSLDestroy( papszCornerTokens );
+        CSLDestroy(papszCornerTokens);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try to get the coordinate system.                               */
-/* -------------------------------------------------------------------- */
+    // Try to get the coordinate system.
     OGRSpatialReference oSRS;
 
-    if( OGR_SRS_ImportFromISO19115( &oSRS, pszXMLMetadata )
-        == OGRERR_NONE )
+    if( OGR_SRS_ImportFromISO19115(&oSRS, pszXMLMetadata) == OGRERR_NONE )
     {
-        oSRS.exportToWkt( &pszProjection );
+        oSRS.exportToWkt(&pszProjection);
     }
     else
     {
-        ParseWKTFromXML( pszXMLMetadata );
+        ParseWKTFromXML(pszXMLMetadata);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Fetch acquisition date.                                         */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode * const psDateTime = CPLSearchXMLNode( psRoot, "=dateTime" );
+    // Fetch acquisition date.
+    CPLXMLNode *const psDateTime = CPLSearchXMLNode(psRoot, "=dateTime");
     if( psDateTime != NULL )
     {
-        const char *pszDateTimeValue = CPLGetXMLValue( psDateTime, NULL, "" );
+        const char *pszDateTimeValue = CPLGetXMLValue(psDateTime, NULL, "");
         if( pszDateTimeValue )
-            SetMetadataItem( "BAG_DATETIME", pszDateTimeValue );
+            SetMetadataItem("BAG_DATETIME", pszDateTimeValue);
     }
 
-    CPLDestroyXMLNode( psRoot );
+    CPLDestroyXMLNode(psRoot);
 }
 
 /************************************************************************/
@@ -723,108 +671,106 @@ void BAGDataset::LoadMetadata()
 /************************************************************************/
 OGRErr BAGDataset::ParseWKTFromXML( const char *pszISOXML )
 {
-    CPLXMLNode * const psRoot = CPLParseXMLString( pszISOXML );
-    OGRErr eOGRErr = OGRERR_FAILURE;
+    CPLXMLNode *const psRoot = CPLParseXMLString(pszISOXML);
 
     if( psRoot == NULL )
-        return eOGRErr;
+        return OGRERR_FAILURE;
 
-    CPLStripXMLNamespace( psRoot, NULL, TRUE );
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
 
-    CPLXMLNode *psRSI = CPLSearchXMLNode( psRoot, "=referenceSystemInfo" );
+    CPLXMLNode *psRSI = CPLSearchXMLNode(psRoot, "=referenceSystemInfo");
     if( psRSI == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-          "Unable to find <referenceSystemInfo> in metadata." );
-        CPLDestroyXMLNode( psRoot );
-        return eOGRErr;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to find <referenceSystemInfo> in metadata.");
+        CPLDestroyXMLNode(psRoot);
+        return OGRERR_FAILURE;
     }
 
     OGRSpatialReference oSRS;
     oSRS.Clear();
 
     const char *pszSRCodeString =
-        CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
-                        "RS_Identifier.code.CharacterString", NULL );
+        CPLGetXMLValue(psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
+                       "RS_Identifier.code.CharacterString", NULL);
     if( pszSRCodeString == NULL )
     {
         CPLDebug("BAG",
                  "Unable to find /MI_Metadata/referenceSystemInfo[1]/"
                  "MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/"
-                 "RS_Identifier[1]/code[1]/CharacterString[1] in metadata." );
-        CPLDestroyXMLNode( psRoot );
-        return eOGRErr;
+                 "RS_Identifier[1]/code[1]/CharacterString[1] in metadata.");
+        CPLDestroyXMLNode(psRoot);
+        return OGRERR_FAILURE;
     }
 
     const char *pszSRCodeSpace =
-        CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
-                        "RS_Identifier.codeSpace.CharacterString", "" );
-    if( !EQUAL( pszSRCodeSpace, "WKT" ) )
+        CPLGetXMLValue(psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
+                       "RS_Identifier.codeSpace.CharacterString", "");
+    if( !EQUAL(pszSRCodeSpace, "WKT") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-            "Spatial reference string is not in WKT." );
-        CPLDestroyXMLNode( psRoot );
-        return eOGRErr;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Spatial reference string is not in WKT.");
+        CPLDestroyXMLNode(psRoot);
+        return OGRERR_FAILURE;
     }
 
-    char* pszWKT = const_cast<char *>( pszSRCodeString );
-    if( oSRS.importFromWkt( &pszWKT ) != OGRERR_NONE )
+    char *pszWKT = const_cast<char *>(pszSRCodeString);
+    if( oSRS.importFromWkt(&pszWKT) != OGRERR_NONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-          "Failed parsing WKT string \"%s\".", pszSRCodeString );
-        CPLDestroyXMLNode( psRoot );
-        return eOGRErr;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failed parsing WKT string \"%s\".", pszSRCodeString);
+        CPLDestroyXMLNode(psRoot);
+        return OGRERR_FAILURE;
     }
 
-    oSRS.exportToWkt( &pszProjection );
-    eOGRErr = OGRERR_NONE;
+    oSRS.exportToWkt(&pszProjection);
 
-    psRSI = CPLSearchXMLNode( psRSI->psNext, "=referenceSystemInfo" );
+    psRSI = CPLSearchXMLNode(psRSI->psNext, "=referenceSystemInfo");
     if( psRSI == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to find second instance of <referenceSystemInfo> "
-                  "in metadata." );
-        CPLDestroyXMLNode( psRoot );
-        return eOGRErr;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to find second instance of <referenceSystemInfo> "
+                 "in metadata.");
+        CPLDestroyXMLNode(psRoot);
+        return OGRERR_NONE;
     }
 
     pszSRCodeString =
-      CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
-                      "RS_Identifier.code.CharacterString", NULL );
+      CPLGetXMLValue(psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
+                     "RS_Identifier.code.CharacterString", NULL);
     if( pszSRCodeString == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-            "Unable to find /MI_Metadata/referenceSystemInfo[2]/"
-                  "MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/"
-                  "RS_Identifier[1]/code[1]/CharacterString[1] in metadata." );
-        CPLDestroyXMLNode( psRoot );
-        return eOGRErr;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to find /MI_Metadata/referenceSystemInfo[2]/"
+                 "MD_ReferenceSystem[1]/referenceSystemIdentifier[1]/"
+                 "RS_Identifier[1]/code[1]/CharacterString[1] in metadata.");
+        CPLDestroyXMLNode(psRoot);
+        return OGRERR_NONE;
     }
 
     pszSRCodeSpace =
-        CPLGetXMLValue( psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
-                        "RS_Identifier.codeSpace.CharacterString", "" );
-    if( !EQUAL( pszSRCodeSpace, "WKT" ) )
+        CPLGetXMLValue(psRSI, "MD_ReferenceSystem.referenceSystemIdentifier."
+                       "RS_Identifier.codeSpace.CharacterString", "");
+    if( !EQUAL(pszSRCodeSpace, "WKT") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-            "Spatial reference string is not in WKT." );
-        CPLDestroyXMLNode( psRoot );
-        return eOGRErr;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Spatial reference string is not in WKT.");
+        CPLDestroyXMLNode(psRoot);
+        return OGRERR_NONE;
     }
 
     if( STARTS_WITH_CI(pszSRCodeString, "VERTCS") )
     {
-        CPLString oString( pszProjection );
-        CPLFree( pszProjection );
+        CPLString oString(pszProjection);
+        CPLFree(pszProjection);
         oString += ",";
         oString += pszSRCodeString;
-        pszProjection = CPLStrdup( oString );
+        pszProjection = CPLStrdup(oString);
     }
 
-    CPLDestroyXMLNode( psRoot );
+    CPLDestroyXMLNode(psRoot);
 
-    return eOGRErr;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -836,11 +782,11 @@ CPLErr BAGDataset::GetGeoTransform( double *padfGeoTransform )
 {
     if( adfGeoTransform[0] != 0.0 || adfGeoTransform[3] != 0.0 )
     {
-        memcpy( padfGeoTransform, adfGeoTransform, sizeof(double)*6 );
+        memcpy(padfGeoTransform, adfGeoTransform, sizeof(double)*6);
         return CE_None;
     }
 
-    return GDALPamDataset::GetGeoTransform( padfGeoTransform );
+    return GDALPamDataset::GetGeoTransform(padfGeoTransform);
 }
 
 /************************************************************************/
@@ -882,30 +828,29 @@ char **BAGDataset::GetMetadata( const char *pszDomain )
         return apszMDList;
     }
 
-    return GDALPamDataset::GetMetadata( pszDomain );
+    return GDALPamDataset::GetMetadata(pszDomain);
 }
 
 /************************************************************************/
 /*                          GDALRegister_BAG()                          */
 /************************************************************************/
-void GDALRegister_BAG( )
+void GDALRegister_BAG()
 
 {
-    if( !GDAL_CHECK_VERSION( "BAG" ) )
+    if( !GDAL_CHECK_VERSION("BAG") )
         return;
 
-    if( GDALGetDriverByName( "BAG" ) != NULL )
+    if( GDALGetDriverByName("BAG") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "BAG" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                               "Bathymetry Attributed Grid" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_bag.html" );
+    poDriver->SetDescription("BAG");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Bathymetry Attributed Grid");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_bag.html");
     poDriver->pfnOpen = BAGDataset::Open;
     poDriver->pfnIdentify = BAGDataset::Identify;
 
-    GetGDALDriverManager( )->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/hdf5/gh5_convenience.cpp b/frmts/hdf5/gh5_convenience.cpp
index ae9fafd..1296de9 100644
--- a/frmts/hdf5/gh5_convenience.cpp
+++ b/frmts/hdf5/gh5_convenience.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gh5_convenience.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  HDF5 convenience functions.
@@ -29,59 +28,58 @@
 
 #include "gh5_convenience.h"
 
-CPL_CVSID("$Id: gh5_convenience.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gh5_convenience.cpp 37927 2017-04-09 05:09:10Z goatbar $");
 
 /************************************************************************/
 /*                    GH5_FetchAttribute(CPLString)                     */
 /************************************************************************/
 
 bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
-                        CPLString &osResult, bool bReportError )
+                         CPLString &osResult, bool bReportError )
 
 {
-    bool retVal = false;
-
-    hid_t hAttr = H5Aopen_name( loc_id, pszAttrName );
+    hid_t hAttr = H5Aopen_name(loc_id, pszAttrName);
 
     osResult.clear();
 
     if( hAttr < 0 )
     {
         if( bReportError )
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to read attribute %s failed, not found.",
-                      pszAttrName );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Attempt to read attribute %s failed, not found.",
+                     pszAttrName);
         return false;
     }
 
-    hid_t hAttrTypeID      = H5Aget_type( hAttr );
-    hid_t hAttrNativeType  = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
+    hid_t hAttrTypeID = H5Aget_type(hAttr);
+    hid_t hAttrNativeType = H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT);
 
-    if( H5Tget_class( hAttrNativeType ) == H5T_STRING )
+    bool retVal = false;
+    if( H5Tget_class(hAttrNativeType) == H5T_STRING )
     {
-	size_t nAttrSize = H5Tget_size( hAttrTypeID );
-        char *pachBuffer = (char *) CPLCalloc(nAttrSize+1,1);
-	H5Aread( hAttr, hAttrNativeType, pachBuffer );
+        const size_t nAttrSize = H5Tget_size(hAttrTypeID);
+        char *pachBuffer = static_cast<char *>(CPLCalloc(nAttrSize + 1, 1));
+        H5Aread(hAttr, hAttrNativeType, pachBuffer);
 
         osResult = pachBuffer;
-        CPLFree( pachBuffer );
+        CPLFree(pachBuffer);
 
         retVal = true;
     }
-
     else
     {
         if( bReportError )
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attribute %s of unsupported type for conversion to string.",
-                      pszAttrName );
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Attribute %s of unsupported type for conversion to string.",
+                pszAttrName);
 
         retVal = false;
     }
 
-    H5Tclose( hAttrNativeType );
-    H5Tclose( hAttrTypeID );
-    H5Aclose( hAttr );
+    H5Tclose(hAttrNativeType);
+    H5Tclose(hAttrTypeID);
+    H5Aclose(hAttr);
     return retVal;
 }
 
@@ -93,86 +91,81 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
                          double &dfResult, bool bReportError )
 
 {
-    hid_t hAttr = H5Aopen_name( loc_id, pszAttrName );
+    const hid_t hAttr = H5Aopen_name(loc_id, pszAttrName);
 
     dfResult = 0.0;
     if( hAttr < 0 )
     {
         if( bReportError )
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to read attribute %s failed, not found.",
-                      pszAttrName );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Attempt to read attribute %s failed, not found.",
+                     pszAttrName);
         return false;
     }
 
-    hid_t hAttrTypeID      = H5Aget_type( hAttr );
-    hid_t hAttrNativeType  = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
-
-/* -------------------------------------------------------------------- */
-/*      Confirm that we have a single element value.                    */
-/* -------------------------------------------------------------------- */
+    hid_t hAttrTypeID = H5Aget_type(hAttr);
+    hid_t hAttrNativeType = H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT);
 
-    hid_t hAttrSpace       = H5Aget_space( hAttr );
-    hsize_t anSize[64];
-    int nAttrDims       = H5Sget_simple_extent_dims( hAttrSpace, anSize, NULL );
+    // Confirm that we have a single element value.
+    hid_t hAttrSpace = H5Aget_space(hAttr);
+    hsize_t anSize[64] = {};
+    int nAttrDims = H5Sget_simple_extent_dims(hAttrSpace, anSize, NULL);
 
     int i, nAttrElements = 1;
 
-    for( i=0; i < nAttrDims; i++ ) {
-        nAttrElements *= (int) anSize[i];
+    for( i = 0; i < nAttrDims; i++ )
+    {
+        nAttrElements *= (int)anSize[i];
     }
 
     if( nAttrElements != 1 )
     {
         if( bReportError )
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to read attribute %s failed, count=%d, not 1.",
-                      pszAttrName, nAttrElements );
-
-        H5Sclose( hAttrSpace );
-        H5Tclose( hAttrNativeType );
-        H5Tclose( hAttrTypeID );
-        H5Aclose( hAttr );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Attempt to read attribute %s failed, count=%d, not 1.",
+                     pszAttrName, nAttrElements);
+
+        H5Sclose(hAttrSpace);
+        H5Tclose(hAttrNativeType);
+        H5Tclose(hAttrTypeID);
+        H5Aclose(hAttr);
         return false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the value.                                                 */
-/* -------------------------------------------------------------------- */
-    void *buf = (void *)CPLMalloc( H5Tget_size( hAttrNativeType ));
-    H5Aread( hAttr, hAttrNativeType, buf );
-
-/* -------------------------------------------------------------------- */
-/*      Translate to double.                                            */
-/* -------------------------------------------------------------------- */
-    if( H5Tequal( H5T_NATIVE_INT, hAttrNativeType ) )
-        dfResult = *((int *) buf);
-    else if( H5Tequal( H5T_NATIVE_FLOAT,    hAttrNativeType ) )
-        dfResult = *((float *) buf);
-    else if( H5Tequal( H5T_NATIVE_DOUBLE,    hAttrNativeType ) )
-        dfResult = *((double *) buf);
+    // Read the value.
+    void *buf = CPLMalloc(H5Tget_size(hAttrNativeType));
+    H5Aread(hAttr, hAttrNativeType, buf);
+
+    // Translate to double.
+    if( H5Tequal(H5T_NATIVE_INT, hAttrNativeType) )
+        dfResult = *((int *)buf);
+    else if( H5Tequal(H5T_NATIVE_FLOAT,    hAttrNativeType) )
+        dfResult = *((float *)buf);
+    else if( H5Tequal(H5T_NATIVE_DOUBLE,    hAttrNativeType) )
+        dfResult = *((double *)buf);
     else
     {
         if( bReportError )
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attribute %s of unsupported type for conversion to double.",
-                      pszAttrName );
-        CPLFree( buf );
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Attribute %s of unsupported type for conversion to double.",
+                pszAttrName);
+        CPLFree(buf);
 
-        H5Sclose( hAttrSpace );
-        H5Tclose( hAttrNativeType );
-        H5Tclose( hAttrTypeID );
-        H5Aclose( hAttr );
+        H5Sclose(hAttrSpace);
+        H5Tclose(hAttrNativeType);
+        H5Tclose(hAttrTypeID);
+        H5Aclose(hAttr);
 
         return false;
     }
 
-    CPLFree( buf );
+    CPLFree(buf);
 
-    H5Sclose( hAttrSpace );
-    H5Tclose( hAttrNativeType );
-    H5Tclose( hAttrTypeID );
-    H5Aclose( hAttr );
+    H5Sclose(hAttrSpace);
+    H5Tclose(hAttrNativeType);
+    H5Tclose(hAttrTypeID);
+    H5Aclose(hAttr);
     return true;
 }
 
@@ -183,44 +176,44 @@ bool GH5_FetchAttribute( hid_t loc_id, const char *pszAttrName,
 /************************************************************************/
 GDALDataType GH5_GetDataType(hid_t TypeID)
 {
-    if( H5Tequal( H5T_NATIVE_CHAR,        TypeID ) )
-	return GDT_Byte;
-    else if( H5Tequal( H5T_NATIVE_SCHAR,  TypeID ) )
-	return GDT_Byte;
-    else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) )
-	return GDT_Byte;
-    else if( H5Tequal( H5T_NATIVE_SHORT,  TypeID ) )
-	return GDT_Int16;
-    else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) )
-	return GDT_UInt16;
-    else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) )
-	return GDT_Int32;
-    else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) )
-	return GDT_UInt32;
-    else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) )
+    if( H5Tequal(H5T_NATIVE_CHAR,        TypeID) )
+        return GDT_Byte;
+    else if( H5Tequal(H5T_NATIVE_SCHAR,  TypeID) )
+        return GDT_Byte;
+    else if( H5Tequal(H5T_NATIVE_UCHAR,  TypeID) )
+        return GDT_Byte;
+    else if( H5Tequal(H5T_NATIVE_SHORT,  TypeID) )
+        return GDT_Int16;
+    else if( H5Tequal(H5T_NATIVE_USHORT, TypeID) )
+        return GDT_UInt16;
+    else if( H5Tequal(H5T_NATIVE_INT,    TypeID) )
+        return GDT_Int32;
+    else if( H5Tequal(H5T_NATIVE_UINT,   TypeID) )
+        return GDT_UInt32;
+    else if( H5Tequal(H5T_NATIVE_LONG,   TypeID) )
     {
         if( sizeof(long) == 4 )
             return GDT_Int32;
         else
             return GDT_Unknown;
     }
-    else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_ULONG,  TypeID) )
     {
         if( sizeof(unsigned long) == 4 )
             return GDT_UInt32;
         else
             return GDT_Unknown;
     }
-    else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) )
-	return GDT_Float32;
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
-	return GDT_Float64;
-    else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) )
-	return GDT_Unknown;
-    else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) )
-	return GDT_Unknown;
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
-	return GDT_Unknown;
+    else if( H5Tequal(H5T_NATIVE_FLOAT,  TypeID) )
+        return GDT_Float32;
+    else if( H5Tequal(H5T_NATIVE_DOUBLE, TypeID) )
+        return GDT_Float64;
+    else if( H5Tequal(H5T_NATIVE_LLONG,  TypeID) )
+        return GDT_Unknown;
+    else if( H5Tequal(H5T_NATIVE_ULLONG, TypeID) )
+        return GDT_Unknown;
+    else if( H5Tequal(H5T_NATIVE_DOUBLE, TypeID) )
+        return GDT_Unknown;
 
     return GDT_Unknown;
 }
diff --git a/frmts/hdf5/gh5_convenience.h b/frmts/hdf5/gh5_convenience.h
index 78e2a4c..8bde91d 100644
--- a/frmts/hdf5/gh5_convenience.h
+++ b/frmts/hdf5/gh5_convenience.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gh5_convenience.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: gh5_convenience.h 37931 2017-04-09 06:26:02Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  HDF5 convenience functions.
@@ -33,12 +33,12 @@
 #define H5_USE_16_API
 
 #ifdef _MSC_VER
-#pragma warning( push )
-#pragma warning( disable : 4005 ) /* warning C4005: '_HDF5USEDLL_' : macro redefinition */
+#pragma warning(push)
+#pragma warning(disable : 4005) // warning C4005: '_HDF5USEDLL_' : macro redefinition
 #endif
 #include "hdf5.h"
 #ifdef _MSC_VER
-#pragma warning( pop )
+#pragma warning(pop)
 #endif
 
 #include "cpl_string.h"
@@ -46,8 +46,8 @@
 
 /* release 1.6.3 or 1.6.4 changed the type of count in some api functions */
 
-#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6 \
-       && (H5_VERS_MINOR < 6 || H5_VERS_RELEASE < 3)
+#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6 && \
+       (H5_VERS_MINOR < 6 || H5_VERS_RELEASE < 3)
 #  define H5OFFSET_TYPE hssize_t
 #else
 #  define H5OFFSET_TYPE  hsize_t
diff --git a/frmts/hdf5/hdf5dataset.cpp b/frmts/hdf5/hdf5dataset.cpp
index 25fc6e9..5df3dd1 100644
--- a/frmts/hdf5/hdf5dataset.cpp
+++ b/frmts/hdf5/hdf5dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hdf5dataset.cpp 33460 2016-02-15 16:48:24Z rouault $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  HDF5 Datasets. Open HDF5 file, fetch metadata and list of
@@ -30,26 +29,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+
 #define H5_USE_16_API
 
 #ifdef _MSC_VER
-#pragma warning( push )
-/* warning C4005: '_HDF5USEDLL_' : macro redefinition */
-#pragma warning( disable : 4005 )
+#pragma warning(push)
+// Warning C4005: '_HDF5USEDLL_' : macro redefinition.
+#pragma warning(disable : 4005)
 #endif
 
 #include "hdf5.h"
+#include "hdf5dataset.h"
 
 #ifdef _MSC_VER
-#pragma warning( pop )
+#pragma warning(pop)
 #endif
 
+#include <stdio.h>
+#include <string.h>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
 #include "gdal_priv.h"
-#include "hdf5dataset.h"
+#
 
-CPL_CVSID("$Id: hdf5dataset.cpp 33460 2016-02-15 16:48:24Z rouault $");
+CPL_CVSID("$Id: hdf5dataset.cpp 37930 2017-04-09 06:15:28Z goatbar $");
 
 static const size_t MAX_METADATA_LEN = 32768;
 
@@ -65,17 +74,16 @@ static const size_t MAX_METADATA_LEN = 32768;
 void GDALRegister_HDF5()
 
 {
-    if( GDALGetDriverByName( "HDF5" ) != NULL )
+    if( GDALGetDriverByName("HDF5") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
     poDriver->SetDescription("HDF5");
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
     poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
                               "Hierarchical Data Format Release 5");
-    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
-                              "frmt_hdf5.html");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_hdf5.html");
     poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "hdf5");
     poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
 
@@ -89,7 +97,7 @@ void GDALRegister_HDF5()
 }
 
 /************************************************************************/
-/*                           HDF5Dataset()                      	*/
+/*                           HDF5Dataset()                              */
 /************************************************************************/
 HDF5Dataset::HDF5Dataset() :
     hHDF5(-1),
@@ -108,19 +116,20 @@ HDF5Dataset::HDF5Dataset() :
 /************************************************************************/
 HDF5Dataset::~HDF5Dataset()
 {
-    CSLDestroy( papszMetadata );
+    CSLDestroy(papszMetadata);
     if( hGroupID > 0 )
-        H5Gclose( hGroupID );
+        H5Gclose(hGroupID);
     if( hHDF5 > 0 )
-        H5Fclose( hHDF5 );
-    CSLDestroy( papszSubDatasets );
-    if( poH5RootGroup != NULL ) {
-        DestroyH5Objects( poH5RootGroup );
-        CPLFree( poH5RootGroup->pszName );
-        CPLFree( poH5RootGroup->pszPath );
-        CPLFree( poH5RootGroup->pszUnderscorePath );
-        CPLFree( poH5RootGroup->poHchild );
-        CPLFree( poH5RootGroup );
+        H5Fclose(hHDF5);
+    CSLDestroy(papszSubDatasets);
+    if( poH5RootGroup != NULL )
+    {
+        DestroyH5Objects(poH5RootGroup);
+        CPLFree(poH5RootGroup->pszName);
+        CPLFree(poH5RootGroup->pszPath);
+        CPLFree(poH5RootGroup->pszUnderscorePath);
+        CPLFree(poH5RootGroup->poHchild);
+        CPLFree(poH5RootGroup);
     }
 }
 
@@ -131,43 +140,43 @@ HDF5Dataset::~HDF5Dataset()
 /************************************************************************/
 GDALDataType HDF5Dataset::GetDataType(hid_t TypeID)
 {
-    if( H5Tequal( H5T_NATIVE_CHAR,        TypeID ) )
+    if( H5Tequal(H5T_NATIVE_CHAR,        TypeID) )
         return GDT_Byte;
-    else if( H5Tequal( H5T_NATIVE_SCHAR,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_SCHAR,  TypeID) )
         return GDT_Byte;
-    else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_UCHAR,  TypeID) )
         return GDT_Byte;
-    else if( H5Tequal( H5T_NATIVE_SHORT,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_SHORT,  TypeID) )
         return GDT_Int16;
-    else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_USHORT, TypeID) )
         return GDT_UInt16;
-    else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_INT,    TypeID) )
         return GDT_Int32;
-    else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_UINT,   TypeID) )
         return GDT_UInt32;
-    else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_LONG,   TypeID) )
     {
         if( sizeof(long) == 4 )
             return GDT_Int32;
         else
             return GDT_Unknown;
     }
-    else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_ULONG,  TypeID) )
     {
         if( sizeof(unsigned long) == 4 )
             return GDT_UInt32;
         else
             return GDT_Unknown;
     }
-    else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_FLOAT,  TypeID) )
         return GDT_Float32;
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_DOUBLE, TypeID) )
         return GDT_Float64;
-    else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_LLONG,  TypeID) )
         return GDT_Unknown;
-    else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_ULLONG, TypeID) )
         return GDT_Unknown;
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_DOUBLE, TypeID) )
         return GDT_Unknown;
 
     return GDT_Unknown;
@@ -180,33 +189,33 @@ GDALDataType HDF5Dataset::GetDataType(hid_t TypeID)
 /************************************************************************/
 const char *HDF5Dataset::GetDataTypeName(hid_t TypeID)
 {
-    if( H5Tequal( H5T_NATIVE_CHAR,        TypeID ) )
+    if( H5Tequal(H5T_NATIVE_CHAR,        TypeID) )
         return "8-bit character";
-    else if( H5Tequal( H5T_NATIVE_SCHAR,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_SCHAR,  TypeID) )
         return "8-bit signed character";
-    else if( H5Tequal( H5T_NATIVE_UCHAR,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_UCHAR,  TypeID) )
         return "8-bit unsigned character";
-    else if( H5Tequal( H5T_NATIVE_SHORT,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_SHORT,  TypeID) )
         return "16-bit integer";
-    else if( H5Tequal( H5T_NATIVE_USHORT, TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_USHORT, TypeID) )
         return "16-bit unsigned integer";
-    else if( H5Tequal( H5T_NATIVE_INT,    TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_INT,    TypeID) )
         return "32-bit integer";
-    else if( H5Tequal( H5T_NATIVE_UINT,   TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_UINT,   TypeID) )
         return "32-bit unsigned integer";
-    else if( H5Tequal( H5T_NATIVE_LONG,   TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_LONG,   TypeID) )
         return "32/64-bit integer";
-    else if( H5Tequal( H5T_NATIVE_ULONG,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_ULONG,  TypeID) )
         return "32/64-bit unsigned integer";
-    else if( H5Tequal( H5T_NATIVE_FLOAT,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_FLOAT,  TypeID) )
         return "32-bit floating-point";
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_DOUBLE, TypeID) )
         return "64-bit floating-point";
-    else if( H5Tequal( H5T_NATIVE_LLONG,  TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_LLONG,  TypeID) )
         return "64-bit integer";
-    else if( H5Tequal( H5T_NATIVE_ULLONG, TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_ULLONG, TypeID) )
         return "64-bit unsigned integer";
-    else if( H5Tequal( H5T_NATIVE_DOUBLE, TypeID ) )
+    else if( H5Tequal(H5T_NATIVE_DOUBLE, TypeID) )
         return "64-bit floating-point";
 
     return "Unknown";
@@ -219,47 +228,45 @@ const char *HDF5Dataset::GetDataTypeName(hid_t TypeID)
 int HDF5Dataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Is it an HDF5 file?                                             */
-/* -------------------------------------------------------------------- */
+    // Is it an HDF5 file?
     static const char achSignature[] = "\211HDF\r\n\032\n";
 
-    if( ! poOpenInfo->pabyHeader )
+    if( !poOpenInfo->pabyHeader )
         return FALSE;
 
-    if( memcmp(poOpenInfo->pabyHeader,achSignature,8) == 0 )
+    if( memcmp(poOpenInfo->pabyHeader, achSignature, 8) == 0 )
     {
         CPLString osExt(CPLGetExtension(poOpenInfo->pszFilename));
 
-        /* The tests to avoid opening KEA and BAG drivers are not */
-        /* necessary when drivers are built in the core lib, as they */
-        /* are registered after HDF5, but in the case of plugins, we */
-        /* cannot do assumptions about the registration order */
+        // The tests to avoid opening KEA and BAG drivers are not
+        // necessary when drivers are built in the core lib, as they
+        // are registered after HDF5, but in the case of plugins, we
+        // cannot do assumptions about the registration order.
 
-        /* Avoid opening kea files if the kea driver is available */
-        if( EQUAL(osExt, "KEA") &&
-            GDALGetDriverByName("KEA") != NULL )
+        // Avoid opening kea files if the kea driver is available.
+        if( EQUAL(osExt, "KEA") && GDALGetDriverByName("KEA") != NULL )
         {
             return FALSE;
         }
 
-        /* Avoid opening BAG files if the bag driver is available */
-        if( EQUAL(osExt, "BAG") &&
-            GDALGetDriverByName("BAG") != NULL )
+        // Avoid opening BAG files if the bag driver is available.
+        if( EQUAL(osExt, "BAG") && GDALGetDriverByName("BAG") != NULL )
         {
             return FALSE;
         }
 
-        /* Avoid opening NC files if the netCDF driver is available and */
-        /* they are recognized by it */
-        if( (EQUAL(osExt, "NC") || EQUAL(osExt, "CDF") || EQUAL(osExt, "NC4")) &&
+        // Avoid opening NC files if the netCDF driver is available and
+        // they are recognized by it.
+        if( (EQUAL(osExt, "NC") ||
+             EQUAL(osExt, "CDF") ||
+             EQUAL(osExt, "NC4")) &&
             GDALGetDriverByName("netCDF") != NULL )
         {
-            const char* const apszAllowedDriver [] = { "netCDF", NULL };
+            const char *const apszAllowedDriver[] = { "netCDF", NULL };
             CPLPushErrorHandler(CPLQuietErrorHandler);
-            GDALDatasetH hDS =
-                GDALOpenEx( poOpenInfo->pszFilename, GDAL_OF_RASTER | GDAL_OF_VECTOR,
-                            apszAllowedDriver, NULL, NULL);
+            GDALDatasetH hDS = GDALOpenEx(poOpenInfo->pszFilename,
+                                          GDAL_OF_RASTER | GDAL_OF_VECTOR,
+                                          apszAllowedDriver, NULL, NULL);
             CPLPopErrorHandler();
             if( hDS )
             {
@@ -271,7 +278,7 @@ int HDF5Dataset::Identify( GDALOpenInfo * poOpenInfo )
         return TRUE;
     }
 
-    if( memcmp(poOpenInfo->pabyHeader,"<HDF_UserBlock>",15) == 0)
+    if( memcmp(poOpenInfo->pabyHeader, "<HDF_UserBlock>", 15) == 0)
     {
         if( H5Fis_hdf5(poOpenInfo->pszFilename) )
           return TRUE;
@@ -283,73 +290,65 @@ int HDF5Dataset::Identify( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
-GDALDataset *HDF5Dataset::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *HDF5Dataset::Open( GDALOpenInfo *poOpenInfo )
 {
-    if( !Identify( poOpenInfo ) )
+    if( !Identify(poOpenInfo) )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Create datasource.                                              */
-/* -------------------------------------------------------------------- */
-    HDF5Dataset * const poDS = new HDF5Dataset();
+    // Create datasource.
+    HDF5Dataset *const poDS = new HDF5Dataset();
 
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->SetDescription(poOpenInfo->pszFilename);
 
-/* -------------------------------------------------------------------- */
-/*      Try opening the dataset.                                        */
-/* -------------------------------------------------------------------- */
-    poDS->hHDF5 = H5Fopen( poOpenInfo->pszFilename,
-                           H5F_ACC_RDONLY,
-                           H5P_DEFAULT );
-    if( poDS->hHDF5 < 0 )  {
+    // Try opening the dataset.
+    poDS->hHDF5 = H5Fopen(poOpenInfo->pszFilename, H5F_ACC_RDONLY, H5P_DEFAULT);
+    if( poDS->hHDF5 < 0 )
+    {
         delete poDS;
         return NULL;
     }
 
-    poDS->hGroupID = H5Gopen( poDS->hHDF5, "/" );
-    if( poDS->hGroupID < 0 ) {
-        poDS->bIsHDFEOS=false;
+    poDS->hGroupID = H5Gopen(poDS->hHDF5, "/");
+    if( poDS->hGroupID < 0 )
+    {
+        poDS->bIsHDFEOS = false;
         delete poDS;
         return NULL;
     }
 
-    poDS->bIsHDFEOS=true;
-    poDS->ReadGlobalAttributes( true );
+    poDS->bIsHDFEOS = true;
+    poDS->ReadGlobalAttributes(true);
 
-    poDS->SetMetadata( poDS->papszMetadata  );
+    poDS->SetMetadata(poDS->papszMetadata);
 
-    if ( CSLCount( poDS->papszSubDatasets ) / 2 >= 1 )
-        poDS->SetMetadata( poDS->papszSubDatasets, "SUBDATASETS" );
+    if ( CSLCount(poDS->papszSubDatasets) / 2 >= 1 )
+        poDS->SetMetadata(poDS->papszSubDatasets, "SUBDATASETS");
 
     // Make sure we don't try to do any pam stuff with this dataset.
     poDS->nPamFlags |= GPF_NOSAVE;
 
-/* -------------------------------------------------------------------- */
-/*      If we have single subdataset only, open it immediately          */
-/* -------------------------------------------------------------------- */
-    int nSubDatasets = CSLCount( poDS->papszSubDatasets ) / 2;
+    // If we have single subdataset only, open it immediately.
+    int nSubDatasets = CSLCount(poDS->papszSubDatasets) / 2;
     if( nSubDatasets == 1 )
     {
-        CPLString osDSName = CSLFetchNameValue( poDS->papszSubDatasets,
-                                                "SUBDATASET_1_NAME" );
+        CPLString osDSName =
+            CSLFetchNameValue(poDS->papszSubDatasets, "SUBDATASET_1_NAME");
         delete poDS;
-        return (GDALDataset *) GDALOpen( osDSName, poOpenInfo->eAccess );
+        return (GDALDataset *)GDALOpen(osDSName, poOpenInfo->eAccess);
     }
     else
     {
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
+        // Confirm the requested access is supported.
         if( poOpenInfo->eAccess == GA_Update )
         {
             delete poDS;
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "The HDF5 driver does not support update access to existing"
-                      " datasets.\n" );
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "The HDF5 driver does not support update access to "
+                     "existing datasets.");
             return NULL;
         }
     }
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -359,42 +358,37 @@ GDALDataset *HDF5Dataset::Open( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 void HDF5Dataset::DestroyH5Objects( HDF5GroupObjects *poH5Object )
 {
-/* -------------------------------------------------------------------- */
-/*      Visit all objects                                               */
-/* -------------------------------------------------------------------- */
+    // Visit all objects.
     unsigned i = 0;  // i is used after the for loop.
 
     for( ; i < poH5Object->nbObjs; i++ )
-        if( poH5Object->poHchild+i != NULL )
-            DestroyH5Objects( poH5Object->poHchild+i );
+        if( poH5Object->poHchild + i != NULL )
+            DestroyH5Objects(poH5Object->poHchild + i);
 
     if( poH5Object->poHparent ==NULL )
         return;
 
-/* -------------------------------------------------------------------- */
-/*      Erase some data                                                 */
-/* -------------------------------------------------------------------- */
-    CPLFree( poH5Object->paDims );
+    // Erase some data.
+    CPLFree(poH5Object->paDims);
     poH5Object->paDims = NULL;
 
-    CPLFree( poH5Object->pszPath );
+    CPLFree(poH5Object->pszPath);
     poH5Object->pszPath = NULL;
 
-    CPLFree( poH5Object->pszName );
+    CPLFree(poH5Object->pszName);
     poH5Object->pszName = NULL;
 
-    CPLFree( poH5Object->pszUnderscorePath );
+    CPLFree(poH5Object->pszUnderscorePath);
     poH5Object->pszUnderscorePath = NULL;
 
     if( poH5Object->native > 0 )
-        H5Tclose( poH5Object->native );
+        H5Tclose(poH5Object->native);
     poH5Object->native = 0;
 
-/* -------------------------------------------------------------------- */
-/*      All Children are visited and can be deleted.                    */
-/* -------------------------------------------------------------------- */
-    if( ( i==poH5Object->nbObjs ) && ( poH5Object->nbObjs!=0 ) ) {
-        CPLFree( poH5Object->poHchild );
+    // All Children are visited and can be deleted.
+    if( i == poH5Object->nbObjs && poH5Object->nbObjs != 0 )
+    {
+        CPLFree(poH5Object->poHchild);
         poH5Object->poHchild = NULL;
     }
 }
@@ -406,68 +400,65 @@ void HDF5Dataset::DestroyH5Objects( HDF5GroupObjects *poH5Object )
 /************************************************************************/
 static void CreatePath( HDF5GroupObjects *poH5Object )
 {
-/* -------------------------------------------------------------------- */
-/*      Recurse to the root path                                        */
-/* -------------------------------------------------------------------- */
+    // Recurse to the root path.
     CPLString osPath;
-    if( poH5Object->poHparent !=NULL ) {
-        CreatePath( poH5Object->poHparent );
+    if( poH5Object->poHparent != NULL )
+    {
+        CreatePath(poH5Object->poHparent);
         osPath = poH5Object->poHparent->pszPath;
     }
 
-/* -------------------------------------------------------------------- */
-/*      add name to the path                                            */
-/* -------------------------------------------------------------------- */
-    if( !EQUAL( poH5Object->pszName,"/" ) ){
-        osPath.append( "/" );
-        osPath.append( poH5Object->pszName );
+    // Add name to the path.
+    if( !EQUAL(poH5Object->pszName, "/") )
+    {
+        osPath.append("/");
+        osPath.append(poH5Object->pszName);
     }
 
-/* -------------------------------------------------------------------- */
-/*      fill up path for each object                                    */
-/* -------------------------------------------------------------------- */
+    // Fill up path for each object.
     CPLString osUnderscoreSpaceInName;
-    if( poH5Object->pszPath == NULL ) {
+    if( poH5Object->pszPath == NULL )
+    {
 
-        if( strlen( poH5Object->pszName ) == 1 ) {
-            osPath.append( poH5Object->pszName );
+        if( strlen(poH5Object->pszName) == 1 )
+        {
+            osPath.append(poH5Object->pszName);
             osUnderscoreSpaceInName = poH5Object->pszName;
         }
-        else {
-/* -------------------------------------------------------------------- */
-/*      Change space for underscore                                     */
-/* -------------------------------------------------------------------- */
-            char** papszPath = CSLTokenizeString2(
-                osPath.c_str(), " ", CSLT_HONOURSTRINGS );
-
-            for( int i=0; papszPath[i] != NULL ; i++ ) {
+        else
+        {
+            // Change space for underscore.
+            char **papszPath =
+                CSLTokenizeString2(osPath.c_str(), " ", CSLT_HONOURSTRINGS);
+
+            for( int i = 0; papszPath[i] != NULL ; i++ )
+            {
                 if( i > 0 )
-                    osUnderscoreSpaceInName.append( "_" );
-                osUnderscoreSpaceInName.append( papszPath[ i ] );
+                    osUnderscoreSpaceInName.append("_");
+                osUnderscoreSpaceInName.append(papszPath[i]);
             }
             CSLDestroy(papszPath);
-
         }
 
         // -1 to give room for NUL in C strings.
         static const size_t MAX_PATH = 8192 - 1;
         // TODO(schwehr): Is it an issue if the results are longer than 8192?
         // It appears that the output can never be longer than the source.
-        if ( osUnderscoreSpaceInName.size() > MAX_PATH )
-            CPLError( CE_Fatal, CPLE_AppDefined,
-                      "osUnderscoreSpaceInName longer than MAX_PATH: "
-                      "%u > %u",
-                      static_cast<unsigned int>(osUnderscoreSpaceInName.size()),
-                      static_cast<unsigned int>(MAX_PATH) );
-        if ( osPath.size() > MAX_PATH )
-            CPLError( CE_Fatal, CPLE_AppDefined,
-                      "osPath longer than MAX_PATH: %u > %u",
-                      static_cast<unsigned int>(osPath.size()),
-                      static_cast<unsigned int>(MAX_PATH) );
-
-        poH5Object->pszUnderscorePath  =
-            CPLStrdup( osUnderscoreSpaceInName.c_str() );
-        poH5Object->pszPath = CPLStrdup( osPath.c_str() );
+        if( osUnderscoreSpaceInName.size() > MAX_PATH )
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "osUnderscoreSpaceInName longer than MAX_PATH: "
+                     "%u > %u",
+                     static_cast<unsigned int>(osUnderscoreSpaceInName.size()),
+                     static_cast<unsigned int>(MAX_PATH));
+        if( osPath.size() > MAX_PATH )
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "osPath longer than MAX_PATH: %u > %u",
+                     static_cast<unsigned int>(osPath.size()),
+                     static_cast<unsigned int>(MAX_PATH));
+
+        poH5Object->pszUnderscorePath =
+            CPLStrdup(osUnderscoreSpaceInName.c_str());
+        poH5Object->pszPath = CPLStrdup(osPath.c_str());
     }
 }
 
@@ -484,8 +475,8 @@ static int HDF5GroupCheckDuplicate( HDF5GroupObjects *poHparent,
 {
     while( poHparent != NULL )
     {
-        if( poHparent->objno[0] == objno[0]
-            && poHparent->objno[1] == objno[1] )
+        if( poHparent->objno[0] == objno[0] &&
+            poHparent->objno[1] == objno[1] )
             return TRUE;
 
         poHparent = poHparent->poHparent;
@@ -502,160 +493,161 @@ static int HDF5GroupCheckDuplicate( HDF5GroupObjects *poHparent,
 herr_t HDF5CreateGroupObjs( hid_t hHDF5, const char *pszObjName,
                             void *poHObjParent)
 {
-    HDF5GroupObjects * const poHparent =
+    HDF5GroupObjects *const poHparent =
         static_cast<HDF5GroupObjects *>(poHObjParent);
-    HDF5GroupObjects * poHchild = poHparent->poHchild;
+    HDF5GroupObjects *poHchild = poHparent->poHchild;
     H5G_stat_t oStatbuf;
 
-    if( H5Gget_objinfo( hHDF5, pszObjName, FALSE, &oStatbuf ) < 0  )
+    if( H5Gget_objinfo(hHDF5, pszObjName, FALSE, &oStatbuf) < 0  )
         return -1;
 
-
-/* -------------------------------------------------------------------- */
-/*      Look for next child                                             */
-/* -------------------------------------------------------------------- */
+    // Look for next child.
     unsigned idx = 0;  // idx is used after the for loop.
-    for( ; idx < poHparent->nbObjs; idx++ ) {
+    for( ; idx < poHparent->nbObjs; idx++ )
+    {
         if( poHchild->pszName == NULL ) break;
         poHchild++;
     }
 
     if( idx == poHparent->nbObjs )
-        return -1;  // all children parsed
+        return -1;  // All children parsed.
 
-/* -------------------------------------------------------------------- */
-/*      Save child information                                          */
-/* -------------------------------------------------------------------- */
-    poHchild->pszName  = CPLStrdup( pszObjName );
+    // Save child information.
+    poHchild->pszName = CPLStrdup(pszObjName);
 
-    poHchild->nType  = oStatbuf.type;
+    poHchild->nType = oStatbuf.type;
     poHchild->nIndex = idx;
     poHchild->poHparent = poHparent;
-    poHchild->nRank     = 0;
-    poHchild->paDims    = NULL;
+    poHchild->nRank = 0;
+    poHchild->paDims = NULL;
     poHchild->HDatatype = 0;
-    poHchild->objno[0]  = oStatbuf.objno[0];
-    poHchild->objno[1]  = oStatbuf.objno[1];
-    if( poHchild->pszPath == NULL ) {
-        CreatePath( poHchild );
+    poHchild->objno[0] = oStatbuf.objno[0];
+    poHchild->objno[1] = oStatbuf.objno[1];
+    if( poHchild->pszPath == NULL )
+    {
+        CreatePath(poHchild);
     }
-    if( poHparent->pszPath == NULL ) {
-        CreatePath( poHparent );
+    if( poHparent->pszPath == NULL )
+    {
+        CreatePath(poHparent);
     }
 
-    switch ( oStatbuf.type )
+    switch( oStatbuf.type )
+    {
+    case H5G_LINK:
+    {
+        poHchild->nbAttrs = 0;
+        poHchild->nbObjs = 0;
+        poHchild->poHchild = NULL;
+        poHchild->nRank = 0;
+        poHchild->paDims = NULL;
+        poHchild->HDatatype = 0;
+        break;
+    }
+    case H5G_GROUP:
     {
-        case H5G_LINK:
+        hid_t hGroupID = H5I_INVALID_HID;  // Identifier of group.
+        if( (hGroupID = H5Gopen(hHDF5, pszObjName)) == -1)
         {
-            poHchild->nbAttrs = 0;
-            poHchild->nbObjs = 0;
-            poHchild->poHchild = NULL;
-            poHchild->nRank      = 0;
-            poHchild->paDims    = NULL;
-            poHchild->HDatatype = 0;
-            break;
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "unable to access \"%s\" group.", pszObjName);
+            return -1;
         }
-        case H5G_GROUP:
+        // Number of attributes in object.
+        const int nbAttrs = H5Aget_num_attrs(hGroupID);
+        hsize_t nbObjs = 0;  // Number of objects in a group.
+        H5Gget_num_objs(hGroupID, &nbObjs);
+        poHchild->nbAttrs = nbAttrs;
+        poHchild->nbObjs = static_cast<int>(nbObjs);
+        poHchild->nRank = 0;
+        poHchild->paDims = NULL;
+        poHchild->HDatatype = 0;
+
+        if( nbObjs > 0 )
         {
-            hid_t hGroupID = H5I_INVALID_HID;  // Identifier of group.
-            if( ( hGroupID = H5Gopen( hHDF5, pszObjName ) ) == -1  ) {
-                printf( "Error: unable to access \"%s\" group.\n",
-                        pszObjName );
-                return -1;
-            }
-            // Number of attributes in object.
-            const int nbAttrs = H5Aget_num_attrs( hGroupID );
-            hsize_t nbObjs = 0;  // Number of objects in a group.
-            H5Gget_num_objs( hGroupID, &nbObjs );
-            poHchild->nbAttrs= nbAttrs;
-            poHchild->nbObjs = (int) nbObjs;
-            poHchild->nRank      = 0;
-            poHchild->paDims    = NULL;
-            poHchild->HDatatype = 0;
-
-            if( nbObjs > 0 ) {
-                poHchild->poHchild = static_cast<HDF5GroupObjects *>(
-                    CPLCalloc( static_cast<int>(nbObjs),
-                               sizeof( HDF5GroupObjects ) ) );
-                memset( poHchild->poHchild, 0,
-                        (size_t) (sizeof( HDF5GroupObjects ) * nbObjs) );
-            }
-            else
-                poHchild->poHchild = NULL;
+            poHchild->poHchild = static_cast<HDF5GroupObjects *>(
+                CPLCalloc(static_cast<int>(nbObjs), sizeof(HDF5GroupObjects)));
+            memset(poHchild->poHchild, 0,
+                   static_cast<size_t>(sizeof(HDF5GroupObjects) * nbObjs));
+        }
+        else
+        {
+            poHchild->poHchild = NULL;
+        }
 
-            if( !HDF5GroupCheckDuplicate( poHparent, oStatbuf.objno ) )
-                H5Giterate( hHDF5, pszObjName, NULL,
-                            HDF5CreateGroupObjs,  (void*) poHchild );
-            else
-                CPLDebug( "HDF5", "avoiding link looping on node '%s'.",
-                        pszObjName );
+        if( !HDF5GroupCheckDuplicate(poHparent, oStatbuf.objno) )
+            H5Giterate(hHDF5, pszObjName, NULL, HDF5CreateGroupObjs, poHchild);
+        else
+            CPLDebug("HDF5", "avoiding link looping on node '%s'.", pszObjName);
 
-            H5Gclose( hGroupID );
-            break;
+        H5Gclose(hGroupID);
+        break;
+    }
+    case H5G_DATASET:
+    {
+        hid_t hDatasetID = H5I_INVALID_HID;  // Identifier of dataset.
+        if( (hDatasetID = H5Dopen(hHDF5, pszObjName)) == -1)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "unable to access \"%s\" dataset.", pszObjName);
+            return -1;
         }
-        case H5G_DATASET:
+        const int nbAttrs = H5Aget_num_attrs(hDatasetID);
+        const hid_t datatype = H5Dget_type(hDatasetID);
+        const hid_t dataspace = H5Dget_space(hDatasetID);
+        const int n_dims = H5Sget_simple_extent_ndims(dataspace);
+        const hid_t native = H5Tget_native_type(datatype, H5T_DIR_ASCEND);
+        hsize_t *maxdims = NULL;
+        hsize_t *dims = NULL;
+
+        if( n_dims > 0 )
         {
-            hid_t hDatasetID = H5I_INVALID_HID;  // Identifier of dataset.
-            if( ( hDatasetID = H5Dopen( hHDF5, pszObjName ) ) == -1  ) {
-                printf( "Error: unable to access \"%s\" dataset.\n",
-                        pszObjName );
-                return -1;
-            }
-            const int nbAttrs = H5Aget_num_attrs( hDatasetID );
-            const hid_t datatype = H5Dget_type( hDatasetID );
-            const hid_t dataspace = H5Dget_space( hDatasetID );
-            const int n_dims = H5Sget_simple_extent_ndims( dataspace );
-            const hid_t native = H5Tget_native_type( datatype, H5T_DIR_ASCEND );
-            hsize_t *maxdims = NULL;
-            hsize_t *dims = NULL;
-
-            if( n_dims > 0 ) {
-                dims = static_cast<hsize_t *>(
-                    CPLCalloc( n_dims,sizeof( hsize_t ) ) );
-                maxdims  = static_cast<hsize_t *>(
-                    CPLCalloc( n_dims,sizeof( hsize_t ) ) );
-            }
-            H5Sget_simple_extent_dims( dataspace, dims, maxdims );
-            if( maxdims != NULL )
-                CPLFree( maxdims );
-
-            if( n_dims > 0 ) {
-                poHchild->nRank     = n_dims;   // rank of the array
-                poHchild->paDims    = dims;      // dimension of the array.
-                poHchild->HDatatype = datatype;  // HDF5 datatype
-            }
-            else  {
-                poHchild->nRank     = -1;
-                poHchild->paDims    = NULL;
-                poHchild->HDatatype = 0;
-            }
-            poHchild->nbAttrs   = nbAttrs;
-            poHchild->nbObjs    = 0;
-            poHchild->poHchild  = NULL;
-            poHchild->native    = native;
-            H5Tclose( datatype );
-            H5Sclose( dataspace );
-            H5Dclose( hDatasetID );
-            break;
+            dims = static_cast<hsize_t *>(CPLCalloc(n_dims, sizeof(hsize_t)));
+            maxdims =
+                static_cast<hsize_t *>(CPLCalloc(n_dims, sizeof(hsize_t)));
         }
-        case H5G_TYPE:
+        H5Sget_simple_extent_dims(dataspace, dims, maxdims);
+        if( maxdims != NULL )
+            CPLFree(maxdims);
+
+        if( n_dims > 0 )
         {
-            poHchild->nbAttrs = 0;
-            poHchild->nbObjs = 0;
-            poHchild->poHchild = NULL;
-            poHchild->nRank      = 0;
-            poHchild->paDims    = NULL;
+            poHchild->nRank = n_dims;        // rank of the array
+            poHchild->paDims = dims;         // dimension of the array.
+            poHchild->HDatatype = datatype;  // HDF5 datatype
+        }
+        else
+        {
+            poHchild->nRank = -1;
+            poHchild->paDims = NULL;
             poHchild->HDatatype = 0;
-            break;
         }
-        default:
-            break;
+        poHchild->nbAttrs = nbAttrs;
+        poHchild->nbObjs = 0;
+        poHchild->poHchild = NULL;
+        poHchild->native = native;
+        H5Tclose(datatype);
+        H5Sclose(dataspace);
+        H5Dclose(hDatasetID);
+        break;
+    }
+    case H5G_TYPE:
+    {
+        poHchild->nbAttrs = 0;
+        poHchild->nbObjs = 0;
+        poHchild->poHchild = NULL;
+        poHchild->nRank = 0;
+        poHchild->paDims = NULL;
+        poHchild->HDatatype = 0;
+        break;
+    }
+    default:
+        break;
     }
 
     return 0;
 }
 
-
 /************************************************************************/
 /*                          HDF5AttrIterate()                           */
 /************************************************************************/
@@ -667,13 +659,13 @@ static herr_t HDF5AttrIterate( hid_t hH5ObjID,
 {
     char **papszTokens = NULL;
     CPLString osKey;
-    HDF5Dataset * const poDS = static_cast<HDF5Dataset *>(pDS);
+    HDF5Dataset *const poDS = static_cast<HDF5Dataset *>(pDS);
 
     // Convert "/" into "_" for the path component
-    const char* pszPath = poDS->poH5CurrentObject->pszUnderscorePath;
+    const char *pszPath = poDS->poH5CurrentObject->pszUnderscorePath;
     if(pszPath != NULL && strlen(pszPath) > 0)
     {
-        papszTokens = CSLTokenizeString2( pszPath, "/", CSLT_HONOURSTRINGS );
+        papszTokens = CSLTokenizeString2(pszPath, "/", CSLT_HONOURSTRINGS);
 
         for( hsize_t i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
         {
@@ -681,34 +673,36 @@ static herr_t HDF5AttrIterate( hid_t hH5ObjID,
                 osKey += '_';
             osKey += papszTokens[i];
         }
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
     }
 
     // Convert whitespaces into "_" for the attribute name component
-    papszTokens = CSLTokenizeString2( pszAttrName, " ",
-                            CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+    papszTokens = CSLTokenizeString2(
+        pszAttrName, " ", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
     for( hsize_t i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
     {
         if(!osKey.empty())
             osKey += '_';
         osKey += papszTokens[i];
     }
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
 
-    const hid_t hAttrID         = H5Aopen_name( hH5ObjID, pszAttrName );
-    const hid_t hAttrTypeID     = H5Aget_type( hAttrID );
-    const hid_t hAttrNativeType = H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
-    const hid_t hAttrSpace      = H5Aget_space( hAttrID );
+    const hid_t hAttrID = H5Aopen_name(hH5ObjID, pszAttrName);
+    const hid_t hAttrTypeID = H5Aget_type(hAttrID);
+    const hid_t hAttrNativeType =
+        H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT);
+    const hid_t hAttrSpace = H5Aget_space(hAttrID);
 
-    if( H5Tget_class( hAttrNativeType ) == H5T_VLEN )
+    if( H5Tget_class(hAttrNativeType) == H5T_VLEN )
         return 0;
 
-    hsize_t nSize[64];
+    hsize_t nSize[64] = {};
     const unsigned int nAttrDims =
-        H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL );
+        H5Sget_simple_extent_dims(hAttrSpace, nSize, NULL);
 
     unsigned int nAttrElmts = 1;
-    for( hsize_t i=0; i < nAttrDims; i++ ) {
+    for( hsize_t i = 0; i < nAttrDims; i++ )
+    {
         nAttrElmts *= static_cast<int>(nSize[i]);
     }
 
@@ -716,153 +710,178 @@ static herr_t HDF5AttrIterate( hid_t hH5ObjID,
     hsize_t nAttrSize = 0;
     char *szValue = NULL;
 
-    if( H5Tget_class( hAttrNativeType ) == H5T_STRING )
+    if( H5Tget_class(hAttrNativeType) == H5T_STRING )
     {
         if ( H5Tis_variable_str(hAttrNativeType) )
         {
-            char** papszStrings = static_cast<char**>(
-                CPLMalloc( nAttrElmts * sizeof(char*) ) );
+            char **papszStrings =
+                static_cast<char **>(CPLMalloc(nAttrElmts * sizeof(char *)));
 
-            // Read the values
-            H5Aread( hAttrID, hAttrNativeType, papszStrings );
+            // Read the values.
+            H5Aread(hAttrID, hAttrNativeType, papszStrings);
 
-            // Concatenate all values as one string (separated by a space)
+            // Concatenate all values as one string separated by a space.
             CPLString osVal = papszStrings[0];
-            for( hsize_t i=1; i < nAttrElmts; i++ ) {
+            for( hsize_t i = 1; i < nAttrElmts; i++ )
+            {
                 osVal += " ";
                 osVal += papszStrings[i];
             }
 
-            szValue = (char*) CPLMalloc(osVal.length() + 1);
-            strcpy( szValue, osVal.c_str() );
+            szValue = static_cast<char *>(CPLMalloc(osVal.length() + 1));
+            strcpy(szValue, osVal.c_str());
 
-            H5Dvlen_reclaim( hAttrNativeType, hAttrSpace, H5P_DEFAULT,
-                             papszStrings );
-            CPLFree( papszStrings );
+            H5Dvlen_reclaim(hAttrNativeType, hAttrSpace, H5P_DEFAULT,
+                            papszStrings);
+            CPLFree(papszStrings);
         }
         else
         {
-            nAttrSize = H5Aget_storage_size( hAttrID );
-            szValue = (char*) CPLMalloc((size_t) (nAttrSize+1));
-            H5Aread( hAttrID, hAttrNativeType, szValue );
+            nAttrSize = H5Aget_storage_size(hAttrID);
+            szValue = static_cast<char *>(CPLMalloc((size_t)(nAttrSize + 1)));
+            H5Aread(hAttrID, hAttrNativeType, szValue);
             szValue[nAttrSize] = '\0';
         }
     }
-    else {
+    else
+    {
         const size_t nDataLen = 8192;
         void *buf = NULL;
 
-        if( nAttrElmts > 0 ) {
-            buf = (void *) CPLMalloc( nAttrElmts*
-                          H5Tget_size( hAttrNativeType ));
-            szData = static_cast<char*>(CPLMalloc( nDataLen ));
-            szValue = static_cast<char*>(CPLMalloc( MAX_METADATA_LEN ));
+        if( nAttrElmts > 0 )
+        {
+            buf = CPLMalloc(nAttrElmts * H5Tget_size(hAttrNativeType));
+            szData = static_cast<char *>(CPLMalloc(nDataLen));
+            szValue = static_cast<char *>(CPLMalloc(MAX_METADATA_LEN));
             szData[0] = '\0';
-            szValue[0] ='\0';
-            H5Aread( hAttrID, hAttrNativeType, buf );
+            szValue[0] = '\0';
+            H5Aread(hAttrID, hAttrNativeType, buf);
         }
-        if( H5Tequal( H5T_NATIVE_CHAR, hAttrNativeType )
-            || H5Tequal( H5T_NATIVE_SCHAR,  hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                snprintf( szData, nDataLen, "%c ", ((char *) buf)[i]);
+        if( H5Tequal(H5T_NATIVE_CHAR, hAttrNativeType ) ||
+            H5Tequal(H5T_NATIVE_SCHAR, hAttrNativeType) )
+        {
+            for( hsize_t i = 0; i < nAttrElmts; i++ )
+            {
+                snprintf(szData, nDataLen, "%c ", static_cast<char *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        else if( H5Tequal( H5T_NATIVE_UCHAR,  hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                snprintf( szData, nDataLen, "%c", ((char *) buf)[i] );
+        else if( H5Tequal(H5T_NATIVE_UCHAR, hAttrNativeType) )
+        {
+            for( hsize_t i = 0; i < nAttrElmts; i++ )
+            {
+                snprintf(szData, nDataLen, "%c", static_cast<char *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        else if( H5Tequal( H5T_NATIVE_SHORT,  hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                snprintf( szData, nDataLen, "%d ", ((short *) buf)[i] );
+        else if( H5Tequal(H5T_NATIVE_SHORT, hAttrNativeType) )
+        {
+            for( hsize_t i = 0; i < nAttrElmts; i++ )
+            {
+                snprintf(szData, nDataLen, "%d ", static_cast<short *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        else if( H5Tequal( H5T_NATIVE_USHORT, hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                snprintf( szData, nDataLen, "%ud ", ((unsigned short *) buf)[i] );
+        else if( H5Tequal(H5T_NATIVE_USHORT, hAttrNativeType) )
+        {
+            for( hsize_t i = 0; i < nAttrElmts; i++ )
+            {
+              snprintf(szData, nDataLen, "%ud ",
+                       static_cast<unsigned short *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        else if( H5Tequal( H5T_NATIVE_INT,    hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                snprintf( szData, nDataLen, "%d ", ((int *) buf)[i] );
+        else if( H5Tequal(H5T_NATIVE_INT, hAttrNativeType) )
+        {
+            for( hsize_t i=0; i < nAttrElmts; i++ )
+            {
+                snprintf(szData, nDataLen, "%d ", static_cast<int *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        else if( H5Tequal( H5T_NATIVE_UINT,   hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                snprintf( szData, nDataLen, "%ud ", ((unsigned int *) buf)[i] );
+        else if( H5Tequal(H5T_NATIVE_UINT, hAttrNativeType) )
+        {
+            for( hsize_t i = 0; i < nAttrElmts; i++ )
+            {
+                snprintf(szData, nDataLen, "%ud ",
+                         static_cast<unsigned int *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        else if( H5Tequal( H5T_NATIVE_LONG,   hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                snprintf( szData, nDataLen, "%ld ", ((long *)buf)[i] );
+        else if( H5Tequal(H5T_NATIVE_LONG, hAttrNativeType) )
+        {
+            for( hsize_t i = 0; i < nAttrElmts; i++ )
+            {
+                snprintf(szData, nDataLen, "%ld ", static_cast<long *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        else if( H5Tequal( H5T_NATIVE_ULONG,  hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                snprintf( szData, nDataLen, "%ld ", ((unsigned long *)buf)[i] );
+        else if( H5Tequal(H5T_NATIVE_ULONG, hAttrNativeType) )
+        {
+            for( hsize_t i = 0; i < nAttrElmts; i++ ) {
+                snprintf(szData, nDataLen, "%ld ",
+                         static_cast<unsigned long *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        else if( H5Tequal( H5T_NATIVE_FLOAT,  hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                CPLsnprintf( szData, nDataLen, "%.8g ",  ((float *)buf)[i] );
+        else if( H5Tequal(H5T_NATIVE_FLOAT, hAttrNativeType) )
+        {
+            for( hsize_t i = 0; i < nAttrElmts; i++ )
+            {
+                CPLsnprintf(szData, nDataLen, "%.8g ",
+                            static_cast<float *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        else if( H5Tequal( H5T_NATIVE_DOUBLE, hAttrNativeType ) ) {
-            for( hsize_t i=0; i < nAttrElmts; i++ ) {
-                CPLsnprintf( szData, nDataLen, "%.15g ",  ((double *)buf)[i] );
+        else if( H5Tequal(H5T_NATIVE_DOUBLE, hAttrNativeType) )
+        {
+            for( hsize_t i = 0; i < nAttrElmts; i++ )
+            {
+                CPLsnprintf(szData, nDataLen, "%.15g ",
+                            static_cast<double *>(buf)[i]);
                 if( CPLStrlcat(szValue, szData, MAX_METADATA_LEN) >=
-                                                            MAX_METADATA_LEN )
-                    CPLError( CE_Warning, CPLE_OutOfMemory,
-                              "Header data too long. Truncated\n");
+                    MAX_METADATA_LEN )
+                    CPLError(CE_Warning, CPLE_OutOfMemory,
+                             "Header data too long. Truncated");
             }
         }
-        CPLFree( buf );
-
+        CPLFree(buf);
     }
     H5Sclose(hAttrSpace);
     H5Tclose(hAttrNativeType);
     H5Tclose(hAttrTypeID);
-    H5Aclose( hAttrID );
-    poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata, osKey, szValue);
+    H5Aclose(hAttrID);
+    poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, osKey, szValue);
 
-    CPLFree( szData );
-    CPLFree( szValue );
+    CPLFree(szData);
+    CPLFree(szValue);
 
     return 0;
 }
@@ -876,34 +895,31 @@ CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
     if( !poH5Object->pszPath )
         return CE_None;
 
-    HDF5Dataset * const poDS = this;
-
     poH5CurrentObject = poH5Object;
-    int nbAttrs = poH5Object->nbAttrs;
 
-    if( poH5Object->pszPath == NULL || EQUAL(poH5Object->pszPath, "" ) )
+    if( poH5Object->pszPath == NULL || EQUAL(poH5Object->pszPath, "") )
         return CE_None;
 
-    switch( nType ) {
+    HDF5Dataset *const poDS = this;
+    const int nbAttrs = poH5Object->nbAttrs;
 
+    switch( nType )
+    {
     case H5G_GROUP:
-
-        if( nbAttrs > 0 ) {
+        if( nbAttrs > 0 )
+        {
             // Identifier of group.
-            const hid_t l_hGroupID = H5Gopen( hHDF5, poH5Object->pszPath );
-            H5Aiterate( l_hGroupID, NULL, HDF5AttrIterate, (void *)poDS  );
-            H5Gclose( l_hGroupID );
+            const hid_t l_hGroupID = H5Gopen(hHDF5, poH5Object->pszPath);
+            H5Aiterate(l_hGroupID, NULL, HDF5AttrIterate, poDS);
+            H5Gclose(l_hGroupID);
         }
-
         break;
-
     case H5G_DATASET:
-
-        if( nbAttrs > 0 ) {
-            hid_t hDatasetID =  H5Dopen(hHDF5, poH5Object->pszPath );
-            H5Aiterate( hDatasetID, NULL, HDF5AttrIterate,
-                        reinterpret_cast<void *>(poDS) );
-            H5Dclose( hDatasetID );
+        if( nbAttrs > 0 )
+        {
+            const hid_t hDatasetID = H5Dopen(hHDF5, poH5Object->pszPath);
+            H5Aiterate(hDatasetID, NULL, HDF5AttrIterate, poDS);
+            H5Dclose(hDatasetID);
         }
         break;
 
@@ -914,57 +930,55 @@ CPLErr HDF5Dataset::CreateMetadata( HDF5GroupObjects *poH5Object, int nType)
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                       HDF5FindDatasetObjectsbyPath()                 */
 /*      Find object by name                                             */
 /************************************************************************/
-HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjectsbyPath
-    ( HDF5GroupObjects *poH5Objects, const char* pszDatasetPath )
+HDF5GroupObjects *
+HDF5Dataset::HDF5FindDatasetObjectsbyPath( HDF5GroupObjects *poH5Objects,
+                                           const char *pszDatasetPath )
 {
     if( poH5Objects->nType == H5G_DATASET &&
-        EQUAL( poH5Objects->pszUnderscorePath,pszDatasetPath ) ) {
+        EQUAL(poH5Objects->pszUnderscorePath, pszDatasetPath) )
+    {
 
 #ifdef DEBUG_VERBOSE
-      printf("found it! %p\n", poH5Objects);
+        printf("found it! %p\n", poH5Objects); /*ok*/
 #endif
         return poH5Objects;
     }
 
-    HDF5Dataset * const poDS = this;
+    HDF5Dataset *const poDS = this;
 
-    if( poH5Objects->nbObjs >0 )
+    if( poH5Objects->nbObjs > 0 )
     {
-        for( unsigned int i=0; i <poH5Objects->nbObjs; i++ )   {
+        for( unsigned int i = 0; i <poH5Objects->nbObjs; i++ )   {
             HDF5GroupObjects *poObjectsFound =
-                poDS->HDF5FindDatasetObjectsbyPath( poH5Objects->poHchild+i,
-                                                    pszDatasetPath );
-/* -------------------------------------------------------------------- */
-/*      Is this our dataset??                                           */
-/* -------------------------------------------------------------------- */
+                poDS->HDF5FindDatasetObjectsbyPath(poH5Objects->poHchild + i,
+                                                   pszDatasetPath);
+            // Is this our dataset?
             if( poObjectsFound != NULL )
                 return poObjectsFound;
         }
     }
-/* -------------------------------------------------------------------- */
-/*      Dataset has not been found!                                     */
-/* -------------------------------------------------------------------- */
+    // Dataset has not been found.
     return NULL;
 }
 
-
 /************************************************************************/
 /*                       HDF5FindDatasetObjects()                       */
 /*      Find object by name                                             */
 /************************************************************************/
-HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjects
-    ( HDF5GroupObjects *poH5Objects, const char* pszDatasetName )
+HDF5GroupObjects *
+HDF5Dataset::HDF5FindDatasetObjects( HDF5GroupObjects *poH5Objects,
+                                     const char *pszDatasetName )
 {
     if( poH5Objects->nType == H5G_DATASET &&
-        EQUAL( poH5Objects->pszName,pszDatasetName ) ) {
+        EQUAL(poH5Objects->pszName, pszDatasetName) )
+    {
 
 #ifdef DEBUG_VERBOSE
-        printf("found it! %p\n", poH5Objects);
+        printf("found it! %p\n", poH5Objects); /*ok*/
 #endif
         return poH5Objects;
     }
@@ -973,165 +987,155 @@ HDF5GroupObjects* HDF5Dataset::HDF5FindDatasetObjects
 
     if( poH5Objects->nbObjs > 0 )
     {
-        for( unsigned int i=0; i <poH5Objects->nbObjs; i++ )   {
-            HDF5GroupObjects *poObjectsFound =
-                poDS->HDF5FindDatasetObjects( poH5Objects->poHchild+i,
-                                              pszDatasetName );
-/* -------------------------------------------------------------------- */
-/*      Is this our dataset??                                           */
-/* -------------------------------------------------------------------- */
+        for( unsigned int i = 0; i <poH5Objects->nbObjs; i++ )
+        {
+            HDF5GroupObjects *poObjectsFound = poDS->HDF5FindDatasetObjects(
+                poH5Objects->poHchild + i, pszDatasetName);
+            // Is this our dataset?
             if( poObjectsFound != NULL )
                 return poObjectsFound;
-
         }
     }
-/* -------------------------------------------------------------------- */
-/*      Dataset has not been found!                                     */
-/* -------------------------------------------------------------------- */
+
+    // Dataset has not been found.
     return NULL;
 }
 
-
 /************************************************************************/
 /*                        HDF5ListGroupObjects()                        */
 /*                                                                      */
 /*      List all objects in HDF5                                        */
 /************************************************************************/
 CPLErr HDF5Dataset::HDF5ListGroupObjects( HDF5GroupObjects *poRootGroup,
-					  int bSUBDATASET )
+                                          int bSUBDATASET )
 {
     HDF5Dataset *poDS = this;
 
-    if( poRootGroup->nbObjs >0 )
-        for( hsize_t i=0; i < poRootGroup->nbObjs; i++ ) {
-            poDS->HDF5ListGroupObjects( poRootGroup->poHchild+i, bSUBDATASET );
+    if( poRootGroup->nbObjs > 0 )
+        for( hsize_t i = 0; i < poRootGroup->nbObjs; i++ )
+        {
+            poDS->HDF5ListGroupObjects(poRootGroup->poHchild + i, bSUBDATASET);
         }
 
-
     if( poRootGroup->nType == H5G_GROUP ) {
-        CreateMetadata( poRootGroup, H5G_GROUP );
+        CreateMetadata(poRootGroup, H5G_GROUP);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create Sub dataset list                                         */
-/* -------------------------------------------------------------------- */
-    char szTemp[8192];  // TODO: Get this off of the stack.
-    char szDim[8192];  // TODO: Get this off of the stack.
+    // Create Sub dataset list.
 
-    if( (poRootGroup->nType == H5G_DATASET ) && bSUBDATASET
-        && poDS->GetDataType( poRootGroup->native ) == GDT_Unknown )
+    if( poRootGroup->nType == H5G_DATASET && bSUBDATASET &&
+        poDS->GetDataType(poRootGroup->native) == GDT_Unknown )
     {
-        CPLDebug( "HDF5", "Skipping unsupported %s of type %s",
-                  poRootGroup->pszUnderscorePath,
-                  poDS->GetDataTypeName( poRootGroup->native ) );
+        CPLDebug("HDF5", "Skipping unsupported %s of type %s",
+                 poRootGroup->pszUnderscorePath,
+                 poDS->GetDataTypeName(poRootGroup->native));
     }
-    else if( (poRootGroup->nType == H5G_DATASET ) && bSUBDATASET )
+    else if( poRootGroup->nType == H5G_DATASET && bSUBDATASET )
     {
-        CreateMetadata( poRootGroup, H5G_DATASET );
-
-        szDim[0]='\0';
-        switch( poRootGroup->nRank ) {
-        case 3:
-            snprintf( szTemp, sizeof(szTemp), "%dx%dx%d",
-                      static_cast<int>(poRootGroup->paDims[0]),
-                      static_cast<int>(poRootGroup->paDims[1]),
-                      static_cast<int>(poRootGroup->paDims[2]) );
-            break;
+        CreateMetadata(poRootGroup, H5G_DATASET);
 
+        char szTemp[8192];  // TODO(schwehr): Get this off of the stack.
+        switch( poRootGroup->nRank )
+        {
         case 2:
-            snprintf( szTemp, sizeof(szTemp), "%dx%d",
-                      static_cast<int>(poRootGroup->paDims[0]),
-                      static_cast<int>(poRootGroup->paDims[1]) );
+            snprintf(szTemp, sizeof(szTemp), "%dx%d",
+                     static_cast<int>(poRootGroup->paDims[0]),
+                     static_cast<int>(poRootGroup->paDims[1]));
+            break;
+        case 3:
+            snprintf(szTemp, sizeof(szTemp), "%dx%dx%d",
+                     static_cast<int>(poRootGroup->paDims[0]),
+                     static_cast<int>(poRootGroup->paDims[1]),
+                     static_cast<int>(poRootGroup->paDims[2]));
             break;
-
         default:
             return CE_None;
-
         }
-        strcat( szDim,szTemp );
-
-        snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME",
-                  ++(poDS->nSubDataCount) );
 
-        poDS->papszSubDatasets =
-            CSLSetNameValue( poDS->papszSubDatasets, szTemp,
-                    CPLSPrintf( "HDF5:\"%s\":%s",
-                        poDS->GetDescription(),
-                        poRootGroup->pszUnderscorePath ) );
+        const std::string osDim = szTemp;
 
-        snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC",
-                  poDS->nSubDataCount );
+        snprintf(szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME",
+                 ++(poDS->nSubDataCount));
 
         poDS->papszSubDatasets =
-            CSLSetNameValue( poDS->papszSubDatasets, szTemp,
-                    CPLSPrintf( "[%s] %s (%s)",
-                        szDim,
-                        poRootGroup->pszUnderscorePath,
-                        poDS->GetDataTypeName
-                        ( poRootGroup->native ) ) );
-
+            CSLSetNameValue(poDS->papszSubDatasets, szTemp,
+                            CPLSPrintf("HDF5:\"%s\":%s",
+                                       poDS->GetDescription(),
+                                       poRootGroup->pszUnderscorePath));
+
+        snprintf(szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC",
+                 poDS->nSubDataCount);
+
+        poDS->papszSubDatasets = CSLSetNameValue(
+            poDS->papszSubDatasets, szTemp,
+            CPLSPrintf("[%s] %s (%s)", osDim.c_str(),
+                       poRootGroup->pszUnderscorePath,
+                       poDS->GetDataTypeName(poRootGroup->native)));
     }
 
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                       ReadGlobalAttributes()                         */
 /************************************************************************/
 CPLErr HDF5Dataset::ReadGlobalAttributes(int bSUBDATASET)
 {
-    HDF5GroupObjects *poRootGroup = static_cast<HDF5GroupObjects*>(
-        CPLCalloc(sizeof(HDF5GroupObjects), 1) );
+    HDF5GroupObjects *poRootGroup =
+        static_cast<HDF5GroupObjects *>(CPLCalloc(sizeof(HDF5GroupObjects), 1));
 
-    poH5RootGroup=poRootGroup;
-    poRootGroup->pszName   = CPLStrdup( "/" );
-    poRootGroup->nType     = H5G_GROUP;
+    poH5RootGroup = poRootGroup;
+    poRootGroup->pszName = CPLStrdup("/");
+    poRootGroup->nType = H5G_GROUP;
     poRootGroup->poHparent = NULL;
     poRootGroup->pszPath = NULL;
     poRootGroup->pszUnderscorePath = NULL;
 
-    if( hHDF5 < 0 )  {
-        printf( "hHDF5 <0!!\n" );
+    if( hHDF5 < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "hHDF5 < 0!");
         return CE_None;
     }
 
     H5G_stat_t oStatbuf = {{0, 0}, {0, 0}, 0, H5G_UNKNOWN, 0, 0, {0, 0, 0, 0}};
 
-    if( H5Gget_objinfo( hHDF5, "/", FALSE, &oStatbuf ) < 0  )
+    if( H5Gget_objinfo(hHDF5, "/", FALSE, &oStatbuf) < 0 )
         return CE_Failure;
     poRootGroup->objno[0] = oStatbuf.objno[0];
     poRootGroup->objno[1] = oStatbuf.objno[1];
 
     if( hGroupID > 0 )
-        H5Gclose( hGroupID );
-    hGroupID = H5Gopen( hHDF5, "/" );
-    if( hGroupID < 0 ){
-        printf( "hGroupID <0!!\n" );
+        H5Gclose(hGroupID);
+    hGroupID = H5Gopen(hHDF5, "/");
+    if( hGroupID < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "hGroupId <0!");
         return CE_None;
     }
 
-    poRootGroup->nbAttrs = H5Aget_num_attrs( hGroupID );
+    poRootGroup->nbAttrs = H5Aget_num_attrs(hGroupID);
 
-    H5Gget_num_objs( hGroupID, &( poRootGroup->nbObjs ) );
+    H5Gget_num_objs(hGroupID, &(poRootGroup->nbObjs));
 
-    if( poRootGroup->nbObjs > 0 ) {
+    if( poRootGroup->nbObjs > 0 )
+    {
         poRootGroup->poHchild = static_cast<HDF5GroupObjects *>(
-            CPLCalloc( static_cast<size_t>(poRootGroup->nbObjs),
-                       sizeof( HDF5GroupObjects ) ) );
-        H5Giterate( hGroupID, "/", NULL,
-                    HDF5CreateGroupObjs, reinterpret_cast<void *>(poRootGroup) );
+            CPLCalloc(static_cast<size_t>(poRootGroup->nbObjs),
+                      sizeof(HDF5GroupObjects)));
+        H5Giterate(hGroupID, "/", NULL, HDF5CreateGroupObjs, poRootGroup);
+    }
+    else
+    {
+        poRootGroup->poHchild = NULL;
     }
-    else poRootGroup->poHchild = NULL;
 
-    HDF5ListGroupObjects( poRootGroup, bSUBDATASET );
+    HDF5ListGroupObjects(poRootGroup, bSUBDATASET);
     return CE_None;
 }
 
-
 /**
  * Reads an array of double attributes from the HDF5 metadata.
- * It reads the attributes directly on it's binary form directly,
+ * It reads the attributes directly on its binary form directly,
  * thus avoiding string conversions.
  *
  * Important: It allocates the memory for the attributes internally,
@@ -1145,8 +1149,8 @@ CPLErr HDF5Dataset::ReadGlobalAttributes(int bSUBDATASET)
  *        inform the length of the array.
  * @return CPLErr CE_None in case of success, CE_Failure in case of failure
  */
-CPLErr HDF5Dataset::HDF5ReadDoubleAttr(const char* pszAttrFullPath,
-                                       double **pdfValues,int *nLen)
+CPLErr HDF5Dataset::HDF5ReadDoubleAttr(const char *pszAttrFullPath,
+                                       double **pdfValues, int *nLen)
 {
     CPLString osAttrFullPath(pszAttrFullPath);
 
@@ -1156,83 +1160,85 @@ CPLErr HDF5Dataset::HDF5ReadDoubleAttr(const char* pszAttrFullPath,
     CPLString osObjName;
     CPLString osAttrName;
 
-    //If objects name have been found
-    if(nSlashPos != CPLString::npos )
+    // If objects name have been found.
+    if( nSlashPos != CPLString::npos )
     {
-        //Split Object name (dataset, group)
-        osObjName = osAttrFullPath.substr(0,nSlashPos);
-        //Split attribute name
-        osAttrName = osAttrFullPath.substr(nSlashPos+1);
+        // Split Object name (dataset, group).
+        osObjName = osAttrFullPath.substr(0, nSlashPos);
+        // Split attribute name.
+        osAttrName = osAttrFullPath.substr(nSlashPos + 1);
     }
     else
     {
-        //By default the group is root, and
-        //the attribute is the full path
+        // By default the group is root, and
+        // the attribute is the full path.
         osObjName = "/";
         osAttrName = pszAttrFullPath;
     }
 
-    const hid_t hObjAttrID = H5Oopen( hHDF5, osObjName.c_str(), H5P_DEFAULT );
+    const hid_t hObjAttrID = H5Oopen(hHDF5, osObjName.c_str(), H5P_DEFAULT);
 
     CPLErr retVal = CE_Failure;
 
     if(hObjAttrID < 0)
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Object %s could not be opened\n", pszAttrFullPath );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Object %s could not be opened", pszAttrFullPath);
         retVal = CE_Failure;
     }
     else
     {
         // Open attribute handler by name, from the object handler opened
         // earlier.
-        const hid_t hAttrID = H5Aopen_name( hObjAttrID, osAttrName.c_str() );
+        const hid_t hAttrID = H5Aopen_name(hObjAttrID, osAttrName.c_str());
 
         // Check for errors opening the attribute.
-        if(hAttrID <0)
+        if( hAttrID < 0 )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Attribute %s could not be opened\n", pszAttrFullPath );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Attribute %s could not be opened", pszAttrFullPath);
             retVal = CE_Failure;
         }
         else
         {
-            const hid_t hAttrTypeID = H5Aget_type( hAttrID );
+            const hid_t hAttrTypeID = H5Aget_type(hAttrID);
             const hid_t hAttrNativeType =
-                H5Tget_native_type( hAttrTypeID, H5T_DIR_DEFAULT );
-            const hid_t hAttrSpace = H5Aget_space( hAttrID );
-            hsize_t nSize[64];
-            unsigned int nAttrDims =
-                H5Sget_simple_extent_dims( hAttrSpace, nSize, NULL );
+                H5Tget_native_type(hAttrTypeID, H5T_DIR_DEFAULT);
+            const hid_t hAttrSpace = H5Aget_space(hAttrID);
+            hsize_t nSize[64] = {};
+            const unsigned int nAttrDims =
+                H5Sget_simple_extent_dims(hAttrSpace, nSize, NULL);
 
-            if( !H5Tequal( H5T_NATIVE_DOUBLE, hAttrNativeType ) )
+            if( !H5Tequal(H5T_NATIVE_DOUBLE, hAttrNativeType) )
             {
-                 CPLError( CE_Failure, CPLE_OpenFailed,
-                                 "Attribute %s is not of type double\n", pszAttrFullPath);
-                 retVal = CE_Failure;
+                CPLError(CE_Failure, CPLE_OpenFailed,
+                         "Attribute %s is not of type double",
+                         pszAttrFullPath);
+                retVal = CE_Failure;
             }
             else
             {
                 // Get the amount of elements.
                 unsigned int nAttrElmts = 1;
-                for( hsize_t i=0; i < nAttrDims; i++ )
+                for( hsize_t i = 0; i < nAttrDims; i++ )
                 {
-                    //For multidimensional attributes
-                     nAttrElmts *= static_cast<unsigned int>(nSize[i]);
+                    // For multidimensional attributes
+                    nAttrElmts *= static_cast<unsigned int>(nSize[i]);
                 }
 
                 if(nLen != NULL)
                     *nLen = nAttrElmts;
 
-                (*pdfValues) = (double *) CPLMalloc(nAttrElmts*sizeof(double));
+                *pdfValues = static_cast<double *>(
+                    CPLMalloc(nAttrElmts * sizeof(double)));
 
-                //Read the attribute contents
-                if(H5Aread( hAttrID, hAttrNativeType, *pdfValues )<0)
+                // Read the attribute contents
+                if( H5Aread(hAttrID, hAttrNativeType, *pdfValues) < 0 )
                 {
-                     CPLError( CE_Failure, CPLE_OpenFailed,
-                               "Attribute %s could not be opened\n",
-                               pszAttrFullPath);
-                     retVal = CE_Failure;
+                    CPLError(CE_Failure, CPLE_OpenFailed,
+                             "Attribute %s could not be opened",
+                             pszAttrFullPath);
+                    retVal = CE_Failure;
                 }
                 else
                 {
diff --git a/frmts/hdf5/hdf5dataset.h b/frmts/hdf5/hdf5dataset.h
index 3f09246..c1787d9 100644
--- a/frmts/hdf5/hdf5dataset.h
+++ b/frmts/hdf5/hdf5dataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hdf5dataset.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: hdf5dataset.h 37931 2017-04-09 06:26:02Z goatbar $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Header file for HDF5 datasets reader.
@@ -31,29 +31,29 @@
 #ifndef HDF5DATASET_H_INCLUDED_
 #define HDF5DATASET_H_INCLUDED_
 
-#include "gdal_pam.h"
 #include "cpl_list.h"
+#include "gdal_pam.h"
 
-typedef struct HDF5GroupObjects {
-  char         *pszName;
-  char         *pszPath;
-  char         *pszUnderscorePath;
-  char         *pszTemp;
-  int           nType;
-  int           nIndex;
-  hsize_t       nbObjs;
-  int           nbAttrs;
-  int           nRank;
-  hsize_t       *paDims;
-  hid_t          native;
-  hid_t          HDatatype;
-  unsigned long  objno[2];
-  struct HDF5GroupObjects *poHparent;
-  struct HDF5GroupObjects *poHchild;
+typedef struct HDF5GroupObjects
+{
+    char *pszName;
+    char *pszPath;
+    char *pszUnderscorePath;
+    char *pszTemp;
+    int nType;
+    int nIndex;
+    hsize_t nbObjs;
+    int nbAttrs;
+    int nRank;
+    hsize_t *paDims;
+    hid_t native;
+    hid_t HDatatype;
+    unsigned long objno[2];
+    struct HDF5GroupObjects *poHparent;
+    struct HDF5GroupObjects *poHchild;
 } HDF5GroupObjects;
 
-
-herr_t HDF5CreateGroupObjs(hid_t, const char *,void *);
+herr_t HDF5CreateGroupObjs(hid_t, const char *, void *);
 
 /************************************************************************/
 /* ==================================================================== */
@@ -63,56 +63,56 @@ herr_t HDF5CreateGroupObjs(hid_t, const char *,void *);
 class HDF5Dataset : public GDALPamDataset
 {
 protected:
+    hid_t            hHDF5;
+    hid_t            hGroupID; // H handler interface.
+    char             **papszSubDatasets;
+    int              bIsHDFEOS;
+    int              nDatasetType;
+    int              nSubDataCount;
 
-  hid_t            hHDF5;
-  hid_t            hGroupID; /* H handler interface */
-  char             **papszSubDatasets;
-  int              bIsHDFEOS;
-  int              nDatasetType;
-  int              nSubDataCount;
-
-  HDF5GroupObjects *poH5RootGroup; /* Contain hdf5 Groups information */
+    HDF5GroupObjects *poH5RootGroup; /* Contain hdf5 Groups information */
 
-  CPLErr ReadGlobalAttributes(int);
-  CPLErr HDF5ListGroupObjects(HDF5GroupObjects *, int );
-  CPLErr CreateMetadata( HDF5GroupObjects *, int );
+    CPLErr ReadGlobalAttributes(int);
+    CPLErr HDF5ListGroupObjects(HDF5GroupObjects *, int );
+    CPLErr CreateMetadata( HDF5GroupObjects *, int );
 
-  HDF5GroupObjects* HDF5FindDatasetObjects( HDF5GroupObjects *, const char * );
-  HDF5GroupObjects* HDF5FindDatasetObjectsbyPath( HDF5GroupObjects *, const char * );
-  char* CreatePath(HDF5GroupObjects *);
-  void DestroyH5Objects(HDF5GroupObjects *);
+    HDF5GroupObjects *HDF5FindDatasetObjects( HDF5GroupObjects *, const char * );
+    HDF5GroupObjects *HDF5FindDatasetObjectsbyPath( HDF5GroupObjects *, const char * );
+    char *CreatePath(HDF5GroupObjects *);
+    void DestroyH5Objects(HDF5GroupObjects *);
 
-  GDALDataType GetDataType(hid_t);
-  const char * GetDataTypeName(hid_t);
+    static GDALDataType GetDataType(hid_t);
+    static const char *GetDataTypeName(hid_t);
 
   /**
    * Reads an array of double attributes from the HDF5 metadata.
-   * It reads the attributes directly on it's binary form directly,
+   * It reads the attributes directly on its binary form directly,
    * thus avoiding string conversions.
    *
    * Important: It allocates the memory for the attributes internally,
    * so the caller must free the returned array after using it.
    * @param pszAttrName Name of the attribute to be read.
-   * 			the attribute name must be the form:
-   * 					root attribute name
-   * 					SUBDATASET/subdataset attribute name
+   *                    the attribute name must be the form:
+   *                                    root attribute name
+   *                                    SUBDATASET/subdataset attribute name
    * @param pdfValues pointer which will store the array of doubles read.
    * @param nLen it stores the length of the array read. If NULL it doesn't inform
    *        the length of the array.
    * @return CPLErr CE_None in case of success, CE_Failure in case of failure
    */
-  CPLErr HDF5ReadDoubleAttr(const char* pszAttrName,double **pdfValues,int *nLen=NULL);
+    CPLErr HDF5ReadDoubleAttr(const char *pszAttrName, double **pdfValues,
+                              int *nLen = NULL);
 
-public:
+  public:
 
-  char	           **papszMetadata;
-  HDF5GroupObjects *poH5CurrentObject;
+    char             **papszMetadata;
+    HDF5GroupObjects *poH5CurrentObject;
 
-  HDF5Dataset();
-  ~HDF5Dataset();
+    HDF5Dataset();
+    ~HDF5Dataset();
 
-  static GDALDataset *Open(GDALOpenInfo *);
-  static int Identify(GDALOpenInfo *);
+    static GDALDataset *Open(GDALOpenInfo *);
+    static int Identify(GDALOpenInfo *);
 };
 
 #endif /* HDF5DATASET_H_INCLUDED_ */
diff --git a/frmts/hdf5/hdf5imagedataset.cpp b/frmts/hdf5/hdf5imagedataset.cpp
index 88de305..16be029 100644
--- a/frmts/hdf5/hdf5imagedataset.cpp
+++ b/frmts/hdf5/hdf5imagedataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hdf5imagedataset.cpp 35557 2016-09-30 11:12:06Z rouault $
  *
  * Project:  Hierarchical Data Format Release 5 (HDF5)
  * Purpose:  Read subdatasets of HDF5 file.
@@ -31,15 +30,15 @@
 #define H5_USE_16_API
 
 #ifdef _MSC_VER
-#pragma warning( push )
+#pragma warning(push)
 // warning C4005: '_HDF5USEDLL_' : macro redefinition.
-#pragma warning( disable : 4005 )
+#pragma warning(disable : 4005)
 #endif
 
 #include "hdf5.h"
 
 #ifdef _MSC_VER
-#pragma warning( pop )
+#pragma warning(pop)
 #endif
 
 #include "cpl_string.h"
@@ -49,9 +48,11 @@
 #include "hdf5dataset.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: hdf5imagedataset.cpp 35557 2016-09-30 11:12:06Z rouault $");
+#include <algorithm>
 
-/* release 1.6.3 or 1.6.4 changed the type of count in some api functions */
+CPL_CVSID("$Id: hdf5imagedataset.cpp 37929 2017-04-09 05:42:52Z goatbar $");
+
+// Release 1.6.3 or 1.6.4 changed the type of count in some API functions.
 
 #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6 \
        && (H5_VERS_MINOR < 6 || H5_VERS_RELEASE < 3)
@@ -62,15 +63,11 @@ CPL_CVSID("$Id: hdf5imagedataset.cpp 35557 2016-09-30 11:12:06Z rouault $");
 
 class HDF5ImageDataset : public HDF5Dataset
 {
-    typedef enum
-    {
-        UNKNOWN_PRODUCT=0,
-        CSK_PRODUCT
-    } Hdf5ProductType;
+    typedef enum { UNKNOWN_PRODUCT = 0, CSK_PRODUCT } Hdf5ProductType;
 
     typedef enum
     {
-        PROD_UNKNOWN=0,
+        PROD_UNKNOWN = 0,
         PROD_CSK_L0,
         PROD_CSK_L1A,
         PROD_CSK_L1B,
@@ -86,9 +83,11 @@ class HDF5ImageDataset : public HDF5Dataset
     int         nGCPCount;
     OGRSpatialReference oSRS;
 
-    hsize_t      *dims,*maxdims;
+    hsize_t      *dims;
+    hsize_t      *maxdims;
     HDF5GroupObjects *poH5Objects;
-    int          ndims,dimensions;
+    int          ndims;
+    int          dimensions;
     hid_t        dataset_id;
     hid_t        dataspace_id;
     hsize_t      size;
@@ -107,27 +106,27 @@ public:
     HDF5ImageDataset();
     virtual ~HDF5ImageDataset();
 
-    CPLErr CreateProjections( );
+    CPLErr CreateProjections();
     static GDALDataset  *Open( GDALOpenInfo * );
     static int           Identify( GDALOpenInfo * );
 
-    const char          *GetProjectionRef();
-    virtual int         GetGCPCount( );
-    virtual const char  *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs( );
-    virtual CPLErr GetGeoTransform( double * padfTransform );
+    const char          *GetProjectionRef() override;
+    virtual int         GetGCPCount() override;
+    virtual const char  *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
+    virtual CPLErr GetGeoTransform( double *padfTransform ) override;
 
-    Hdf5ProductType GetSubdatasetType() const {return iSubdatasetType;}
-    HDF5CSKProductEnum GetCSKProductType() const {return iCSKProductType;}
+    Hdf5ProductType GetSubdatasetType() const { return iSubdatasetType; }
+    HDF5CSKProductEnum GetCSKProductType() const { return iCSKProductType; }
 
     int     IsComplexCSKL1A() const
     {
-        return (GetSubdatasetType() == CSK_PRODUCT) &&
-               (GetCSKProductType() == PROD_CSK_L1A) &&
-               (ndims == 3);
+        return GetSubdatasetType() == CSK_PRODUCT &&
+               GetCSKProductType() == PROD_CSK_L1A &&
+               ndims == 3;
     }
-    int     GetYIndex() const { return IsComplexCSKL1A() ? 0 : ndims - 2; }
-    int     GetXIndex() const { return IsComplexCSKL1A() ? 1 : ndims - 1; }
+    int GetYIndex() const { return IsComplexCSKL1A() ? 0 : ndims - 2; }
+    int GetXIndex() const { return IsComplexCSKL1A() ? 1 : ndims - 1; }
 
     /**
      * Identify if the subdataset has a known product format
@@ -175,10 +174,12 @@ HDF5ImageDataset::HDF5ImageDataset() :
     pszGCPProjection(NULL),
     pasGCPList(NULL),
     nGCPCount(0),
+    oSRS(OGRSpatialReference()),
     dims(NULL),
     maxdims(NULL),
     poH5Objects(NULL),
-    ndims(0), dimensions(0),
+    ndims(0),
+    dimensions(0),
     dataset_id(-1),
     dataspace_id(-1),
     size(0),
@@ -201,7 +202,7 @@ HDF5ImageDataset::HDF5ImageDataset() :
 /************************************************************************/
 /*                            ~HDF5ImageDataset()                       */
 /************************************************************************/
-HDF5ImageDataset::~HDF5ImageDataset( )
+HDF5ImageDataset::~HDF5ImageDataset()
 {
     FlushCache();
 
@@ -217,17 +218,17 @@ HDF5ImageDataset::~HDF5ImageDataset( )
     CPLFree(pszProjection);
     CPLFree(pszGCPProjection);
 
-    CPLFree( dims );
-    CPLFree( maxdims );
+    CPLFree(dims);
+    CPLFree(maxdims);
 
     if( nGCPCount > 0 )
     {
         for( int i = 0; i < nGCPCount; i++ )
         {
-            CPLFree( pasGCPList[i].pszId );
-            CPLFree( pasGCPList[i].pszInfo );
+            CPLFree(pasGCPList[i].pszId);
+            CPLFree(pasGCPList[i].pszInfo);
         }
-        CPLFree( pasGCPList );
+        CPLFree(pasGCPList);
     }
 }
 
@@ -243,15 +244,14 @@ class HDF5ImageRasterBand : public GDALPamRasterBand
     bool        bNoDataSet;
     double      dfNoDataValue;
 
-public:
-
+  public:
     HDF5ImageRasterBand( HDF5ImageDataset *, int, GDALDataType );
-    ~HDF5ImageRasterBand();
+    virtual ~HDF5ImageRasterBand();
 
-    virtual CPLErr      IReadBlock( int, int, void * );
-    virtual double      GetNoDataValue( int * );
-    virtual CPLErr      SetNoDataValue( double );
-    /*  virtual CPLErr          IWriteBlock( int, int, void * ); */
+    virtual CPLErr      IReadBlock( int, int, void * ) override;
+    virtual double      GetNoDataValue( int * ) override;
+    virtual CPLErr      SetNoDataValue( double ) override;
+    // virtual CPLErr IWriteBlock( int, int, void * );
 };
 
 /************************************************************************/
@@ -270,44 +270,41 @@ HDF5ImageRasterBand::HDF5ImageRasterBand( HDF5ImageDataset *poDSIn, int nBandIn,
 {
     poDS = poDSIn;
     nBand = nBandIn;
-    eDataType     = eType;
-    nBlockXSize   = poDS->GetRasterXSize( );
-    nBlockYSize   = 1;
-
-/* -------------------------------------------------------------------- */
-/*      Take a copy of Global Metadata since  I can't pass Raster       */
-/*      variable to Iterate function.                                   */
-/* -------------------------------------------------------------------- */
-    char **papszMetaGlobal = CSLDuplicate( poDSIn->papszMetadata );
-    CSLDestroy( poDSIn->papszMetadata );
+    eDataType = eType;
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
+
+    // Take a copy of Global Metadata since  I can't pass Raster
+    // variable to Iterate function.
+    char **papszMetaGlobal = CSLDuplicate(poDSIn->papszMetadata);
+    CSLDestroy(poDSIn->papszMetadata);
     poDSIn->papszMetadata = NULL;
 
-    if( poDSIn->poH5Objects->nType == H5G_DATASET ) {
-        poDSIn->CreateMetadata( poDSIn->poH5Objects, H5G_DATASET );
+    if( poDSIn->poH5Objects->nType == H5G_DATASET )
+    {
+        poDSIn->CreateMetadata(poDSIn->poH5Objects, H5G_DATASET);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Recover Global Metadata and set Band Metadata                   */
-/* -------------------------------------------------------------------- */
+    // Recover Global Metadata and set Band Metadata.
 
-    SetMetadata( poDSIn->papszMetadata );
+    SetMetadata(poDSIn->papszMetadata);
 
-    CSLDestroy( poDSIn->papszMetadata );
-    poDSIn->papszMetadata = CSLDuplicate( papszMetaGlobal );
-    CSLDestroy( papszMetaGlobal );
+    CSLDestroy(poDSIn->papszMetadata);
+    poDSIn->papszMetadata = CSLDuplicate(papszMetaGlobal);
+    CSLDestroy(papszMetaGlobal);
 
-    /* check for chunksize and set it as the blocksize (optimizes read) */
+    // Check for chunksize and set it as the blocksize (optimizes read).
     const hid_t listid = H5Dget_create_plist(poDSIn->dataset_id);
-    if (listid>0)
+    if( listid > 0 )
     {
-        if(H5Pget_layout(listid) == H5D_CHUNKED)
+        if( H5Pget_layout(listid) == H5D_CHUNKED )
         {
             hsize_t panChunkDims[3] = {0, 0, 0};
             const int nDimSize = H5Pget_chunk(listid, 3, panChunkDims);
             CPL_IGNORE_RET_VAL(nDimSize);
             CPLAssert(nDimSize == poDSIn->ndims);
-            nBlockXSize   = (int) panChunkDims[poDSIn->GetXIndex()];
-            nBlockYSize   = (int) panChunkDims[poDSIn->GetYIndex()];
+            nBlockXSize = static_cast<int>(panChunkDims[poDSIn->GetXIndex()]);
+            nBlockYSize = static_cast<int>(panChunkDims[poDSIn->GetYIndex()]);
         }
 
         H5Pclose(listid);
@@ -317,7 +314,7 @@ HDF5ImageRasterBand::HDF5ImageRasterBand( HDF5ImageDataset *poDSIn, int nBandIn,
 /************************************************************************/
 /*                           GetNoDataValue()                           */
 /************************************************************************/
-double HDF5ImageRasterBand::GetNoDataValue( int * pbSuccess )
+double HDF5ImageRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
     if( bNoDataSet )
@@ -328,7 +325,7 @@ double HDF5ImageRasterBand::GetNoDataValue( int * pbSuccess )
         return dfNoDataValue;
     }
 
-    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+    return GDALPamRasterBand::GetNoDataValue(pbSuccess);
 }
 
 /************************************************************************/
@@ -347,14 +344,14 @@ CPLErr HDF5ImageRasterBand::SetNoDataValue( double dfNoData )
 /*                             IReadBlock()                             */
 /************************************************************************/
 CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                        void * pImage )
+                                        void *pImage )
 {
-    HDF5ImageDataset *poGDS = reinterpret_cast<HDF5ImageDataset * >(poDS);
+    HDF5ImageDataset *poGDS = static_cast<HDF5ImageDataset *>(poDS);
 
-    if( poGDS->eAccess == GA_Update ) {
-        memset( pImage, 0,
-            nBlockXSize * nBlockYSize *
-            GDALGetDataTypeSize( eDataType )/8 );
+    if( poGDS->eAccess == GA_Update )
+    {
+        memset(pImage, 0,
+               nBlockXSize * nBlockYSize * GDALGetDataTypeSize(eDataType) / 8);
         return CE_None;
     }
 
@@ -366,53 +363,49 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( poGDS->IsComplexCSKL1A() )
     {
         rank = 3;
-        offset[2]   = nBand-1;
-        count[2]    = 1;
+        offset[2] = nBand - 1;
+        count[2] = 1;
         col_dims[2] = 1;
     }
     else if( poGDS->ndims == 3 )
     {
         rank = 3;
-        offset[0]   = nBand-1;
-        count[0]    = 1;
+        offset[0] = nBand - 1;
+        count[0] = 1;
         col_dims[0] = 1;
     }
     // Defaults to rank = 2;
 
-    offset[poGDS->GetYIndex()] = nBlockYOff*static_cast<hsize_t>(nBlockYSize);
-    offset[poGDS->GetXIndex()] = nBlockXOff*static_cast<hsize_t>(nBlockXSize);
-    count[poGDS->GetYIndex()]  = nBlockYSize;
-    count[poGDS->GetXIndex()]  = nBlockXSize;
-
-    const int nSizeOfData = static_cast<int>(H5Tget_size( poGDS->native ));
-    memset( pImage,0,nBlockXSize*nBlockYSize*nSizeOfData );
-
-    /*  blocksize may not be a multiple of imagesize */
-    count[poGDS->GetYIndex()]  = MIN( size_t(nBlockYSize),
-                                    poDS->GetRasterYSize() -
-                                    offset[poGDS->GetYIndex()]);
-    count[poGDS->GetXIndex()]  = MIN( size_t(nBlockXSize),
-                                    poDS->GetRasterXSize()-
-                                    offset[poGDS->GetXIndex()]);
-
-/* -------------------------------------------------------------------- */
-/*      Select block from file space                                    */
-/* -------------------------------------------------------------------- */
-    herr_t status =  H5Sselect_hyperslab( poGDS->dataspace_id,
-                                          H5S_SELECT_SET,
-                                          offset, NULL,
-                                          count, NULL );
+    offset[poGDS->GetYIndex()] = nBlockYOff * static_cast<hsize_t>(nBlockYSize);
+    offset[poGDS->GetXIndex()] = nBlockXOff * static_cast<hsize_t>(nBlockXSize);
+    count[poGDS->GetYIndex()] = nBlockYSize;
+    count[poGDS->GetXIndex()] = nBlockXSize;
+
+    const int nSizeOfData = static_cast<int>(H5Tget_size(poGDS->native));
+    memset(pImage, 0, nBlockXSize * nBlockYSize * nSizeOfData);
+
+    // Blocksize may not be a multiple of imagesize.
+    count[poGDS->GetYIndex()] =
+        std::min(hsize_t(nBlockYSize),
+                 poDS->GetRasterYSize() - offset[poGDS->GetYIndex()]);
+    count[poGDS->GetXIndex()] =
+        std::min(hsize_t(nBlockXSize),
+                 poDS->GetRasterXSize() - offset[poGDS->GetXIndex()]);
+
+    // Select block from file space.
+    herr_t status = H5Sselect_hyperslab(poGDS->dataspace_id,
+                                        H5S_SELECT_SET,
+                                        offset, NULL,
+                                        count, NULL);
     if( status < 0 )
         return CE_Failure;
 
-/* -------------------------------------------------------------------- */
-/*      Create memory space to receive the data                         */
-/* -------------------------------------------------------------------- */
-    col_dims[poGDS->GetYIndex()]=nBlockYSize;
-    col_dims[poGDS->GetXIndex()]=nBlockXSize;
+    // Create memory space to receive the data.
+    col_dims[poGDS->GetYIndex()] = nBlockYSize;
+    col_dims[poGDS->GetXIndex()] = nBlockXSize;
 
     const hid_t memspace =
-        H5Screate_simple( static_cast<int>(rank), col_dims, NULL );
+        H5Screate_simple(static_cast<int>(rank), col_dims, NULL);
     H5OFFSET_TYPE mem_offset[3] = {0, 0, 0};
     status =  H5Sselect_hyperslab(memspace,
                                   H5S_SELECT_SET,
@@ -421,19 +414,14 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( status < 0 )
         return CE_Failure;
 
-    status = H5Dread ( poGDS->dataset_id,
-                       poGDS->native,
-                       memspace,
-                       poGDS->dataspace_id,
-                       H5P_DEFAULT,
-                       pImage );
+    status = H5Dread(poGDS->dataset_id, poGDS->native, memspace,
+                     poGDS->dataspace_id, H5P_DEFAULT, pImage);
 
-    H5Sclose( memspace );
+    H5Sclose(memspace);
 
     if( status < 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "H5Dread() failed for block." );
+        CPLError(CE_Failure, CPLE_AppDefined, "H5Dread() failed for block.");
         return CE_Failure;
     }
 
@@ -447,7 +435,7 @@ CPLErr HDF5ImageRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 int HDF5ImageDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    if(!STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:") )
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:") )
         return FALSE;
 
     return TRUE;
@@ -456,44 +444,37 @@ int HDF5ImageDataset::Identify( GDALOpenInfo *poOpenInfo )
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
-GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo *poOpenInfo )
 {
-    if(!STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:") )
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "HDF5:") )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
+    // Confirm the requested access is supported.
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "The HDF5ImageDataset driver does not support update access "
-                  " to existing datasets.\n" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The HDF5ImageDataset driver does not support update access "
+                 "to existing datasets.");
         return NULL;
     }
 
     HDF5ImageDataset *poDS = new HDF5ImageDataset();
 
-    /* -------------------------------------------------------------------- */
-    /*      Create a corresponding GDALDataset.                             */
-    /* -------------------------------------------------------------------- */
-    /* printf("poOpenInfo->pszFilename %s\n",poOpenInfo->pszFilename); */
+    // Create a corresponding GDALDataset.
     char **papszName =
-        CSLTokenizeString2(  poOpenInfo->pszFilename,
-                             ":", CSLT_HONOURSTRINGS|CSLT_PRESERVEESCAPES );
+        CSLTokenizeString2(poOpenInfo->pszFilename, ":",
+                           CSLT_HONOURSTRINGS | CSLT_PRESERVEESCAPES);
 
-    if( !((CSLCount(papszName) == 3) || (CSLCount(papszName) == 4)) )
+    if( !(CSLCount(papszName) == 3 || CSLCount(papszName) == 4) )
     {
         CSLDestroy(papszName);
         delete poDS;
         return NULL;
     }
 
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->SetDescription(poOpenInfo->pszFilename);
 
-    /* -------------------------------------------------------------------- */
-    /*    Check for drive name in windows HDF5:"D:\...                      */
-    /* -------------------------------------------------------------------- */
+    // Check for drive name in windows HDF5:"D:\...
     CPLString osSubdatasetName;
 
     CPLString osFilename(papszName[1]);
@@ -505,26 +486,25 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
         osSubdatasetName = papszName[3];
     }
     else
+    {
         osSubdatasetName = papszName[2];
+    }
 
-    poDS->SetSubdatasetName( osSubdatasetName );
+    poDS->SetSubdatasetName(osSubdatasetName);
 
     CSLDestroy(papszName);
     papszName = NULL;
 
-    if( !H5Fis_hdf5(osFilename) ) {
+    if( !H5Fis_hdf5(osFilename) )
+    {
         delete poDS;
         return NULL;
     }
 
-    poDS->SetPhysicalFilename( osFilename );
+    poDS->SetPhysicalFilename(osFilename);
 
-    /* -------------------------------------------------------------------- */
-    /*      Try opening the dataset.                                        */
-    /* -------------------------------------------------------------------- */
-    poDS->hHDF5 = H5Fopen(osFilename,
-                          H5F_ACC_RDONLY,
-                          H5P_DEFAULT );
+    // Try opening the dataset.
+    poDS->hHDF5 = H5Fopen(osFilename, H5F_ACC_RDONLY, H5P_DEFAULT);
 
     if( poDS->hHDF5 < 0 )
     {
@@ -532,161 +512,157 @@ GDALDataset *HDF5ImageDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    poDS->hGroupID = H5Gopen( poDS->hHDF5, "/" );
+    poDS->hGroupID = H5Gopen(poDS->hHDF5, "/");
     if( poDS->hGroupID < 0 )
     {
-        poDS->bIsHDFEOS=false;
+        poDS->bIsHDFEOS = false;
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      THIS IS AN HDF5 FILE                                            */
-/* -------------------------------------------------------------------- */
-    poDS->bIsHDFEOS=TRUE;
-    poDS->ReadGlobalAttributes( FALSE );
+    // This is an HDF5 file.
+    poDS->bIsHDFEOS = TRUE;
+    poDS->ReadGlobalAttributes(FALSE);
 
-/* -------------------------------------------------------------------- */
-/*      Create HDF5 Data Hierarchy in a link list                       */
-/* -------------------------------------------------------------------- */
+    // Create HDF5 Data Hierarchy in a link list.
     poDS->poH5Objects =
-        poDS->HDF5FindDatasetObjectsbyPath( poDS->poH5RootGroup,
-                                            osSubdatasetName );
+        poDS->HDF5FindDatasetObjectsbyPath(poDS->poH5RootGroup,
+                                            osSubdatasetName);
 
-    if( poDS->poH5Objects == NULL ) {
+    if( poDS->poH5Objects == NULL )
+    {
         delete poDS;
         return NULL;
     }
-/* -------------------------------------------------------------------- */
-/*      Retrieve HDF5 data information                                  */
-/* -------------------------------------------------------------------- */
-    poDS->dataset_id   = H5Dopen( poDS->hHDF5,poDS->poH5Objects->pszPath );
-    poDS->dataspace_id = H5Dget_space( poDS->dataset_id );
-    poDS->ndims        = H5Sget_simple_extent_ndims( poDS->dataspace_id );
+
+    // Retrieve HDF5 data information.
+    poDS->dataset_id = H5Dopen(poDS->hHDF5, poDS->poH5Objects->pszPath);
+    poDS->dataspace_id = H5Dget_space(poDS->dataset_id);
+    poDS->ndims = H5Sget_simple_extent_ndims(poDS->dataspace_id);
     if( poDS->ndims < 0 )
     {
         delete poDS;
         return NULL;
     }
-    poDS->dims         = (hsize_t*)CPLCalloc( poDS->ndims, sizeof(hsize_t) );
-    poDS->maxdims      = (hsize_t*)CPLCalloc( poDS->ndims, sizeof(hsize_t) );
-    poDS->dimensions   = H5Sget_simple_extent_dims( poDS->dataspace_id,
-                                                    poDS->dims,
-                                                    poDS->maxdims );
-    poDS->datatype = H5Dget_type( poDS->dataset_id );
-    poDS->class_   = H5Tget_class( poDS->datatype );
-    poDS->size     = H5Tget_size( poDS->datatype );
-    poDS->address = H5Dget_offset( poDS->dataset_id );
-    poDS->native  = H5Tget_native_type( poDS->datatype, H5T_DIR_ASCEND );
+    poDS->dims =
+        static_cast<hsize_t *>(CPLCalloc(poDS->ndims, sizeof(hsize_t)));
+    poDS->maxdims =
+        static_cast<hsize_t *>(CPLCalloc(poDS->ndims, sizeof(hsize_t)));
+    poDS->dimensions = H5Sget_simple_extent_dims(poDS->dataspace_id, poDS->dims,
+                                                 poDS->maxdims);
+    poDS->datatype = H5Dget_type(poDS->dataset_id);
+    poDS->class_ = H5Tget_class(poDS->datatype);
+    poDS->size = H5Tget_size(poDS->datatype);
+    poDS->address = H5Dget_offset(poDS->dataset_id);
+    poDS->native = H5Tget_native_type(poDS->datatype, H5T_DIR_ASCEND);
 
     // CSK code in IdentifyProductType() and CreateProjections()
     // uses dataset metadata.
-    poDS->SetMetadata( poDS->papszMetadata );
+    poDS->SetMetadata(poDS->papszMetadata);
 
     // Check if the hdf5 is a well known product type
     poDS->IdentifyProductType();
 
-    poDS->nRasterYSize=static_cast<int>(poDS->dims[poDS->GetYIndex()]); // nRows
-    poDS->nRasterXSize=static_cast<int>(poDS->dims[poDS->GetXIndex()]); // nCols
+    poDS->nRasterYSize =
+        static_cast<int>(poDS->dims[poDS->GetYIndex()]);  // nRows
+    poDS->nRasterXSize =
+        static_cast<int>(poDS->dims[poDS->GetXIndex()]);  // nCols
     if( poDS->IsComplexCSKL1A() )
     {
-        poDS->nBands=(int) poDS->dims[2]; // nBands
+        poDS->nBands = static_cast<int>(poDS->dims[2]);
     }
     else if( poDS->ndims == 3 )
     {
-        poDS->nBands=(int) poDS->dims[0];
+        poDS->nBands = static_cast<int>(poDS->dims[0]);
     }
     else
     {
-        poDS->nBands=1;
+        poDS->nBands = 1;
     }
 
-    for( int i = 1; i <= poDS->nBands; i++ ) {
-        HDF5ImageRasterBand * const poBand =
-            new HDF5ImageRasterBand( poDS, i,
-                            poDS->GetDataType( poDS->native ) );
+    for( int i = 1; i <= poDS->nBands; i++ )
+    {
+        HDF5ImageRasterBand *const poBand =
+            new HDF5ImageRasterBand(poDS, i, poDS->GetDataType(poDS->native));
 
-        poDS->SetBand( i, poBand );
+        poDS->SetBand(i, poBand);
         if( poBand->bNoDataSet )
-            poBand->SetNoDataValue( 255 );
+            poBand->SetNoDataValue(255);
     }
 
-    poDS->CreateProjections( );
+    poDS->CreateProjections();
 
-/* -------------------------------------------------------------------- */
-/*      Setup/check for pam .aux.xml.                                   */
-/* -------------------------------------------------------------------- */
+    // Setup/check for pam .aux.xml.
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Setup overviews.                                                */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
+    // Setup overviews.
+    poDS->oOvManager.Initialize(poDS, ":::VIRTUAL:::");
 
     return poDS;
 }
 
-
 /************************************************************************/
 /*                        GDALRegister_HDF5Image()                      */
 /************************************************************************/
-void GDALRegister_HDF5Image( )
+void GDALRegister_HDF5Image()
 
 {
-    if( !GDAL_CHECK_VERSION( "HDF5Image driver" ) )
+    if( !GDAL_CHECK_VERSION("HDF5Image driver") )
         return;
 
-    if( GDALGetDriverByName( "HDF5Image" ) != NULL )
+    if( GDALGetDriverByName("HDF5Image") != NULL )
         return;
 
-    GDALDriver *poDriver = new GDALDriver( );
+    GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "HDF5Image" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "HDF5 Dataset" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_hdf5.html" );
+    poDriver->SetDescription("HDF5Image");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "HDF5 Dataset");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_hdf5.html");
 
     poDriver->pfnOpen = HDF5ImageDataset::Open;
     poDriver->pfnIdentify = HDF5ImageDataset::Identify;
 
-    GetGDALDriverManager( )->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
 
 /************************************************************************/
 /*                       CreateODIMH5Projection()                       */
 /************************************************************************/
 
-/* Reference : http://www.knmi.nl/opera/opera3/OPERA_2008_03_WP2.1b_ODIM_H5_v2.1.pdf */
-/* 4.3.2 where for geographically referenced image Groups */
-/* We don't use the where_xscale and where_yscale parameters, but recompute them */
-/* from the lower-left and upper-right coordinates. There's some difference. */
-/* As all those parameters are linked together, I'm not sure which one should be */
-/* considered as the reference */
+// Reference:
+//   http://www.knmi.nl/opera/opera3/OPERA_2008_03_WP2.1b_ODIM_H5_v2.1.pdf
+//
+// 4.3.2 where for geographically referenced image Groups
+// We don't use the where_xscale and where_yscale parameters, but recompute them
+// from the lower-left and upper-right coordinates. There's some difference.
+// As all those parameters are linked together, I'm not sure which one should be
+// considered as the reference.
 
 CPLErr HDF5ImageDataset::CreateODIMH5Projection()
 {
-    const char* const pszProj4String = GetMetadataItem("where_projdef");
-    const char* const pszLL_lon = GetMetadataItem("where_LL_lon");
-    const char* const pszLL_lat = GetMetadataItem("where_LL_lat");
-    const char* const pszUR_lon = GetMetadataItem("where_UR_lon");
-    const char* const pszUR_lat = GetMetadataItem("where_UR_lat");
+    const char *const pszProj4String = GetMetadataItem("where_projdef");
+    const char *const pszLL_lon = GetMetadataItem("where_LL_lon");
+    const char *const pszLL_lat = GetMetadataItem("where_LL_lat");
+    const char *const pszUR_lon = GetMetadataItem("where_UR_lon");
+    const char *const pszUR_lat = GetMetadataItem("where_UR_lat");
     if( pszProj4String == NULL ||
         pszLL_lon == NULL || pszLL_lat == NULL ||
         pszUR_lon == NULL || pszUR_lat == NULL )
         return CE_Failure;
 
-    if( oSRS.importFromProj4( pszProj4String ) != OGRERR_NONE )
+    if( oSRS.importFromProj4(pszProj4String) != OGRERR_NONE )
         return CE_Failure;
 
     OGRSpatialReference oSRSWGS84;
-    oSRSWGS84.SetWellKnownGeogCS( "WGS84" );
+    oSRSWGS84.SetWellKnownGeogCS("WGS84");
 
-    OGRCoordinateTransformation* poCT =
-        OGRCreateCoordinateTransformation( &oSRSWGS84, &oSRS );
+    OGRCoordinateTransformation *poCT =
+        OGRCreateCoordinateTransformation(&oSRSWGS84, &oSRS);
     if( poCT == NULL )
         return CE_Failure;
 
-    /* Reproject corners from long,lat WGS84 to the target SRS */
+    // Reproject corners from long,lat WGS84 to the target SRS.
     double dfLLX = CPLAtof(pszLL_lon);
     double dfLLY = CPLAtof(pszLL_lat);
     double dfURX = CPLAtof(pszUR_lon);
@@ -699,7 +675,7 @@ CPLErr HDF5ImageDataset::CreateODIMH5Projection()
     }
     delete poCT;
 
-    /* Compute the geotransform now */
+    // Compute the geotransform now.
     const double dfPixelX = (dfURX - dfLLX) / nRasterXSize;
     const double dfPixelY = (dfURY - dfLLY) / nRasterYSize;
 
@@ -711,8 +687,8 @@ CPLErr HDF5ImageDataset::CreateODIMH5Projection()
     adfGeoTransform[4] = 0;
     adfGeoTransform[5] = -dfPixelY;
 
-    CPLFree( pszProjection );
-    oSRS.exportToWkt( &pszProjection );
+    CPLFree(pszProjection);
+    oSRS.exportToWkt(&pszProjection);
 
     return CE_None;
 }
@@ -722,32 +698,32 @@ CPLErr HDF5ImageDataset::CreateODIMH5Projection()
 /************************************************************************/
 CPLErr HDF5ImageDataset::CreateProjections()
 {
- switch(iSubdatasetType)
- {
-  case CSK_PRODUCT:
-  {
-        const char *osMissionLevel = NULL;
+    switch(iSubdatasetType)
+    {
+    case CSK_PRODUCT:
+    {
         int productType = PROD_UNKNOWN;
 
-        if(GetMetadataItem("Product_Type")!=NULL)
+        if(GetMetadataItem("Product_Type") != NULL)
         {
-            //Get the format's level
-            osMissionLevel = HDF5Dataset::GetMetadataItem("Product_Type");
+            // Get the format's level.
+            const char *osMissionLevel =
+                HDF5Dataset::GetMetadataItem("Product_Type");
 
             if(STARTS_WITH_CI(osMissionLevel, "RAW"))
-                productType  = PROD_CSK_L0;
+                productType = PROD_CSK_L0;
 
             if(STARTS_WITH_CI(osMissionLevel, "SSC"))
-                productType  = PROD_CSK_L1A;
+                productType = PROD_CSK_L1A;
 
             if(STARTS_WITH_CI(osMissionLevel, "DGM"))
-                productType  = PROD_CSK_L1B;
+                productType = PROD_CSK_L1B;
 
             if(STARTS_WITH_CI(osMissionLevel, "GEC"))
-                productType  = PROD_CSK_L1C;
+                productType = PROD_CSK_L1C;
 
             if(STARTS_WITH_CI(osMissionLevel, "GTC"))
-                productType  = PROD_CSK_L1D;
+                productType = PROD_CSK_L1D;
         }
 
         CaptureCSKGeoTransform(productType);
@@ -755,149 +731,142 @@ CPLErr HDF5ImageDataset::CreateProjections()
         CaptureCSKGCPs(productType);
 
         break;
-  }
-  case UNKNOWN_PRODUCT:
-  {
-    static const int NBGCPLAT = 100;
-    static const int NBGCPLON = 30;
+    }
+    case UNKNOWN_PRODUCT:
+    {
+        static const int NBGCPLAT = 100;
+        static const int NBGCPLON = 30;
 
-    const int nDeltaLat = nRasterYSize / NBGCPLAT;
-    const int nDeltaLon = nRasterXSize / NBGCPLON;
+        const int nDeltaLat = nRasterYSize / NBGCPLAT;
+        const int nDeltaLon = nRasterXSize / NBGCPLON;
 
-    if( nDeltaLat == 0 || nDeltaLon == 0 )
-        return CE_None;
+        if( nDeltaLat == 0 || nDeltaLon == 0 )
+            return CE_None;
 
-    /* -------------------------------------------------------------------- */
-    /*      Create HDF5 Data Hierarchy in a link list                       */
-    /* -------------------------------------------------------------------- */
-    poH5Objects=HDF5FindDatasetObjects( poH5RootGroup,  "Latitude" );
-    if( !poH5Objects ) {
-        if( GetMetadataItem("where_projdef") != NULL )
-            return CreateODIMH5Projection();
-        return CE_None;
-    }
-    /* -------------------------------------------------------------------- */
-    /*      The Latitude and Longitude arrays must have a rank of 2 to     */
-    /*      retrieve GCPs.                                                  */
-    /* -------------------------------------------------------------------- */
-    if( poH5Objects->nRank != 2 ) {
-        return CE_None;
-    }
+        // Create HDF5 Data Hierarchy in a link list.
+        poH5Objects = HDF5FindDatasetObjects(poH5RootGroup, "Latitude");
+        if( !poH5Objects )
+        {
+            if( GetMetadataItem("where_projdef") != NULL )
+                return CreateODIMH5Projection();
+            return CE_None;
+        }
 
-    /* -------------------------------------------------------------------- */
-    /*      Retrieve HDF5 data information                                  */
-    /* -------------------------------------------------------------------- */
-    const hid_t LatitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath );
-    // LatitudeDataspaceID = H5Dget_space( dataset_id );
-
-    poH5Objects=HDF5FindDatasetObjects( poH5RootGroup, "Longitude" );
-    const hid_t LongitudeDatasetID   = H5Dopen( hHDF5,poH5Objects->pszPath );
-    // LongitudeDataspaceID = H5Dget_space( dataset_id );
-
-    if( ( LatitudeDatasetID > 0 ) && ( LongitudeDatasetID > 0) ) {
-        float * const Latitude = static_cast<float *>(
-            CPLCalloc( nRasterYSize*nRasterXSize, sizeof( float ) ) );
-        float * const Longitude = static_cast<float *>(
-            CPLCalloc( nRasterYSize*nRasterXSize, sizeof( float ) ) );
-        memset( Latitude, 0, nRasterXSize*nRasterYSize*sizeof(  float ) );
-        memset( Longitude, 0, nRasterXSize*nRasterYSize*sizeof( float ) );
-
-        H5Dread ( LatitudeDatasetID,
-            H5T_NATIVE_FLOAT,
-            H5S_ALL,
-            H5S_ALL,
-            H5P_DEFAULT,
-            Latitude );
-
-        H5Dread ( LongitudeDatasetID,
-            H5T_NATIVE_FLOAT,
-            H5S_ALL,
-            H5S_ALL,
-            H5P_DEFAULT,
-            Longitude );
-
-        oSRS.SetWellKnownGeogCS( "WGS84" );
-        CPLFree(pszProjection);
-        CPLFree(pszGCPProjection);
-        oSRS.exportToWkt( &pszProjection );
-        oSRS.exportToWkt( &pszGCPProjection );
-
-    /* -------------------------------------------------------------------- */
-    /*  Fill the GCPs list.                                                 */
-    /* -------------------------------------------------------------------- */
-        nGCPCount = (nRasterYSize/nDeltaLat) * (nRasterXSize/nDeltaLon);
-
-        pasGCPList = static_cast<GDAL_GCP *>(
-            CPLCalloc( nGCPCount, sizeof( GDAL_GCP ) ) );
-
-        GDALInitGCPs( nGCPCount, pasGCPList );
-        int k=0;
-
-        const int nYLimit = (static_cast<int>(nRasterYSize)/nDeltaLat) * nDeltaLat;
-        const int nXLimit = (static_cast<int>(nRasterXSize)/nDeltaLon) * nDeltaLon;
-
-        // The original code in https://trac.osgeo.org/gdal/changeset/8066
-        // always add +180 to the longitudes, but without justification
-        // I suspect this might be due to handling products crossing the
-        // antimeridian. Trying to do it just when needed through a heuristics.
-        bool bHasLonNearMinus180 = false;
-        bool bHasLonNearPlus180 = false;
-        bool bHasLonNearZero = false;
-        for( int j = 0; j < nYLimit; j+=nDeltaLat )
+        // The Latitude and Longitude arrays must have a rank of 2 to retrieve
+        // GCPs.
+        if( poH5Objects->nRank != 2 )
         {
-            for( int i = 0; i < nXLimit; i+=nDeltaLon )
+            return CE_None;
+        }
+
+        // Retrieve HDF5 data information.
+        const hid_t LatitudeDatasetID = H5Dopen(hHDF5, poH5Objects->pszPath);
+        // LatitudeDataspaceID = H5Dget_space(dataset_id);
+
+        poH5Objects = HDF5FindDatasetObjects(poH5RootGroup, "Longitude");
+        const hid_t LongitudeDatasetID = H5Dopen(hHDF5, poH5Objects->pszPath);
+        // LongitudeDataspaceID = H5Dget_space(dataset_id);
+
+        if( LatitudeDatasetID > 0 && LongitudeDatasetID > 0 )
+        {
+            float *const Latitude = static_cast<float *>(
+                CPLCalloc(nRasterYSize * nRasterXSize, sizeof(float)));
+            float *const Longitude = static_cast<float *>(
+                CPLCalloc(nRasterYSize * nRasterXSize, sizeof(float)));
+            memset(Latitude, 0, nRasterXSize * nRasterYSize * sizeof(float));
+            memset(Longitude, 0, nRasterXSize * nRasterYSize * sizeof(float));
+
+            H5Dread(LatitudeDatasetID, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL,
+                    H5P_DEFAULT, Latitude);
+
+            H5Dread(LongitudeDatasetID, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL,
+                    H5P_DEFAULT, Longitude);
+
+            oSRS.SetWellKnownGeogCS("WGS84");
+            CPLFree(pszProjection);
+            CPLFree(pszGCPProjection);
+            oSRS.exportToWkt(&pszProjection);
+            oSRS.exportToWkt(&pszGCPProjection);
+
+            // Fill the GCPs list.
+
+            nGCPCount = (nRasterYSize / nDeltaLat) * (nRasterXSize / nDeltaLon);
+
+            pasGCPList =
+                static_cast<GDAL_GCP *>(CPLCalloc(nGCPCount, sizeof(GDAL_GCP)));
+
+            GDALInitGCPs(nGCPCount, pasGCPList);
+
+            const int nYLimit =
+                (static_cast<int>(nRasterYSize) / nDeltaLat) * nDeltaLat;
+            const int nXLimit =
+                (static_cast<int>(nRasterXSize) / nDeltaLon) * nDeltaLon;
+
+            // The original code in https://trac.osgeo.org/gdal/changeset/8066
+            // always add +180 to the longitudes, but without justification
+            // I suspect this might be due to handling products crossing the
+            // antimeridian. Trying to do it just when needed through a
+            // heuristics.
+            bool bHasLonNearMinus180 = false;
+            bool bHasLonNearPlus180 = false;
+            bool bHasLonNearZero = false;
+            for( int j = 0; j < nYLimit; j += nDeltaLat )
             {
-                const int iGCP =  j * nRasterXSize + i;
-                if( Longitude[iGCP] > 170 && Longitude[iGCP] <= 180 )
-                    bHasLonNearPlus180 = true;
-                if( Longitude[iGCP] < -170 && Longitude[iGCP] >= -180 )
-                    bHasLonNearMinus180 = true;
-                if( fabs(Longitude[iGCP]) < 90 )
-                    bHasLonNearZero = true;
+                for( int i = 0; i < nXLimit; i += nDeltaLon )
+                {
+                    const int iGCP = j * nRasterXSize + i;
+                    if( Longitude[iGCP] > 170 && Longitude[iGCP] <= 180 )
+                        bHasLonNearPlus180 = true;
+                    if( Longitude[iGCP] < -170 && Longitude[iGCP] >= -180 )
+                        bHasLonNearMinus180 = true;
+                    if( fabs(Longitude[iGCP]) < 90 )
+                        bHasLonNearZero = true;
+                }
             }
-        }
-        const char* pszShiftGCP =
+            const char *pszShiftGCP =
                 CPLGetConfigOption("HDF5_SHIFT_GCPX_BY_180", NULL);
-        const bool bAdd180 = (bHasLonNearPlus180 && bHasLonNearMinus180 &&
-                              !bHasLonNearZero && pszShiftGCP == NULL) ||
-                             (pszShiftGCP != NULL && CPLTestBool(pszShiftGCP));
+            const bool bAdd180 =
+                (bHasLonNearPlus180 && bHasLonNearMinus180 &&
+                 !bHasLonNearZero && pszShiftGCP == NULL) ||
+                (pszShiftGCP != NULL && CPLTestBool(pszShiftGCP));
 
-        for( int j = 0; j < nYLimit; j+=nDeltaLat )
-        {
-            for( int i = 0; i < nXLimit; i+=nDeltaLon )
+            int k = 0;
+            for( int j = 0; j < nYLimit; j += nDeltaLat )
             {
-                const int iGCP =  j * nRasterXSize + i;
-                pasGCPList[k].dfGCPX = static_cast<double>(Longitude[iGCP]);
-                if( bAdd180 )
-                    pasGCPList[k].dfGCPX += 180.0;
-                pasGCPList[k].dfGCPY = static_cast<double>(Latitude[iGCP]);
-
-                pasGCPList[k].dfGCPPixel = i + 0.5;
-                pasGCPList[k++].dfGCPLine =  j + 0.5;
+                for( int i = 0; i < nXLimit; i += nDeltaLon )
+                {
+                    const int iGCP = j * nRasterXSize + i;
+                    pasGCPList[k].dfGCPX = static_cast<double>(Longitude[iGCP]);
+                    if( bAdd180 )
+                        pasGCPList[k].dfGCPX += 180.0;
+                    pasGCPList[k].dfGCPY = static_cast<double>(Latitude[iGCP]);
+
+                    pasGCPList[k].dfGCPPixel = i + 0.5;
+                    pasGCPList[k++].dfGCPLine = j + 0.5;
+                }
             }
-        }
 
-        CPLFree( Latitude );
-        CPLFree( Longitude );
-    }
+            CPLFree(Latitude);
+            CPLFree(Longitude);
+        }
 
-    if( LatitudeDatasetID > 0 )
-        H5Dclose(LatitudeDatasetID);
-    if( LongitudeDatasetID > 0 )
-        H5Dclose(LongitudeDatasetID);
+        if( LatitudeDatasetID > 0 )
+            H5Dclose(LatitudeDatasetID);
+        if( LongitudeDatasetID > 0 )
+            H5Dclose(LongitudeDatasetID);
 
-    break;
-  }
- }
+        break;
+    }
+    }
 
- return CE_None;
+    return CE_None;
 }
 
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char *HDF5ImageDataset::GetProjectionRef( )
+const char *HDF5ImageDataset::GetProjectionRef()
 
 {
     if( pszProjection )
@@ -910,7 +879,7 @@ const char *HDF5ImageDataset::GetProjectionRef( )
 /*                            GetGCPCount()                             */
 /************************************************************************/
 
-int HDF5ImageDataset::GetGCPCount( )
+int HDF5ImageDataset::GetGCPCount()
 
 {
     if( nGCPCount > 0 )
@@ -923,7 +892,7 @@ int HDF5ImageDataset::GetGCPCount( )
 /*                          GetGCPProjection()                          */
 /************************************************************************/
 
-const char *HDF5ImageDataset::GetGCPProjection( )
+const char *HDF5ImageDataset::GetGCPProjection()
 
 {
     if( nGCPCount > 0 )
@@ -936,7 +905,7 @@ const char *HDF5ImageDataset::GetGCPProjection( )
 /*                               GetGCPs()                              */
 /************************************************************************/
 
-const GDAL_GCP *HDF5ImageDataset::GetGCPs( )
+const GDAL_GCP *HDF5ImageDataset::GetGCPs()
 {
     if( nGCPCount > 0 )
         return pasGCPList;
@@ -948,11 +917,11 @@ const GDAL_GCP *HDF5ImageDataset::GetGCPs( )
 /*                         GetGeoTransform()                            */
 /************************************************************************/
 
-CPLErr HDF5ImageDataset::GetGeoTransform( double * padfTransform )
+CPLErr HDF5ImageDataset::GetGeoTransform( double *padfTransform )
 {
-    if ( bHasGeoTransform )
+    if( bHasGeoTransform )
     {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
+        memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
         return CE_None;
     }
 
@@ -972,44 +941,40 @@ void HDF5ImageDataset::IdentifyProductType()
 {
     iSubdatasetType = UNKNOWN_PRODUCT;
 
-/************************************************************************/
-/*                               COSMO-SKYMED                           */
-/************************************************************************/
+    // COSMO-SKYMED
 
-    //Get the Mission Id as a char *, because the
-    //field may not exist
-    const char * const pszMissionId = HDF5Dataset::GetMetadataItem("Mission_ID");
+    // Get the Mission Id as a char *, because the field may not exist.
+    const char *const pszMissionId = HDF5Dataset::GetMetadataItem("Mission_ID");
 
-    //If there is a Mission_ID field
+    // If there is a Mission_ID field.
     if(pszMissionId != NULL && strstr(GetDescription(), "QLK") == NULL)
     {
-        //Check if the mission type is CSK or KMPS
-        //KMPS: Komsat-5 is Korean mission with a SAR instrument.
-        if(EQUAL(pszMissionId,"CSK") || EQUAL(pszMissionId,"KMPS"))
+        // Check if the mission type is CSK or KMPS.
+        // KMPS: Komsat-5 is Korean mission with a SAR instrument.
+        if(EQUAL(pszMissionId, "CSK") || EQUAL(pszMissionId, "KMPS"))
         {
             iSubdatasetType = CSK_PRODUCT;
 
-            const char *osMissionLevel = NULL;
-
-            if(GetMetadataItem("Product_Type")!=NULL)
+            if(GetMetadataItem("Product_Type") != NULL)
             {
-                //Get the format's level
-                osMissionLevel = HDF5Dataset::GetMetadataItem("Product_Type");
+                // Get the format's level.
+                const char *osMissionLevel =
+                    HDF5Dataset::GetMetadataItem("Product_Type");
 
                 if(STARTS_WITH_CI(osMissionLevel, "RAW"))
-                    iCSKProductType  = PROD_CSK_L0;
+                    iCSKProductType = PROD_CSK_L0;
 
                 if(STARTS_WITH_CI(osMissionLevel, "SCS"))
-                    iCSKProductType  = PROD_CSK_L1A;
+                    iCSKProductType = PROD_CSK_L1A;
 
                 if(STARTS_WITH_CI(osMissionLevel, "DGM"))
-                    iCSKProductType  = PROD_CSK_L1B;
+                    iCSKProductType = PROD_CSK_L1B;
 
                 if(STARTS_WITH_CI(osMissionLevel, "GEC"))
-                    iCSKProductType  = PROD_CSK_L1C;
+                    iCSKProductType = PROD_CSK_L1C;
 
                 if(STARTS_WITH_CI(osMissionLevel, "GTC"))
-                    iCSKProductType  = PROD_CSK_L1D;
+                    iCSKProductType = PROD_CSK_L1D;
             }
         }
     }
@@ -1030,33 +995,36 @@ void HDF5ImageDataset::IdentifyProductType()
 void HDF5ImageDataset::CaptureCSKGeolocation(int iProductType)
 {
     // Set the ellipsoid to WGS84.
-    oSRS.SetWellKnownGeogCS( "WGS84" );
+    oSRS.SetWellKnownGeogCS("WGS84");
 
-    if(iProductType == PROD_CSK_L1C||iProductType == PROD_CSK_L1D)
+    if(iProductType == PROD_CSK_L1C || iProductType == PROD_CSK_L1D)
     {
         double *dfProjFalseEastNorth = NULL;
         double *dfProjScaleFactor = NULL;
         double *dfCenterCoord = NULL;
 
         // Check if all the metadata attributes are present.
-        if(HDF5ReadDoubleAttr("Map Projection False East-North", &dfProjFalseEastNorth) == CE_Failure||
-           HDF5ReadDoubleAttr("Map Projection Scale Factor", &dfProjScaleFactor) == CE_Failure||
-           HDF5ReadDoubleAttr("Map Projection Centre", &dfCenterCoord) == CE_Failure||
+        if(HDF5ReadDoubleAttr("Map Projection False East-North",
+                              &dfProjFalseEastNorth) == CE_Failure ||
+           HDF5ReadDoubleAttr("Map Projection Scale Factor",
+                              &dfProjScaleFactor) == CE_Failure ||
+           HDF5ReadDoubleAttr("Map Projection Centre", &dfCenterCoord) ==
+               CE_Failure ||
            GetMetadataItem("Projection_ID") == NULL)
         {
             pszProjection = CPLStrdup("");
             pszGCPProjection = CPLStrdup("");
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "The CSK hdf5 file geolocation information is "
-                      "malformed\n" );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "The CSK hdf5 file geolocation information is "
+                     "malformed");
         }
         else
         {
             // Fetch projection Type.
             CPLString osProjectionID = GetMetadataItem("Projection_ID");
 
-            //If the projection is UTM
-            if(EQUAL(osProjectionID,"UTM"))
+            // If the projection is UTM.
+            if(EQUAL(osProjectionID, "UTM"))
             {
                 // @TODO: use SetUTM
                 oSRS.SetProjCS(SRS_PT_TRANSVERSE_MERCATOR);
@@ -1068,9 +1036,9 @@ void HDF5ImageDataset::CaptureCSKGeolocation(int iProductType)
             }
             else
             {
-                //TODO Test! I didn't had any UPS projected files to test!
-                //If the projection is UPS
-                if(EQUAL(osProjectionID,"UPS"))
+                // TODO: No UPS projected files to test!
+                // If the projection is UPS.
+                if(EQUAL(osProjectionID, "UPS"))
                 {
                     oSRS.SetProjCS(SRS_PT_POLAR_STEREOGRAPHIC);
                     oSRS.SetPS(dfCenterCoord[0],
@@ -1081,9 +1049,9 @@ void HDF5ImageDataset::CaptureCSKGeolocation(int iProductType)
                 }
             }
 
-            //Export Projection to Wkt.
-            //In case of error then clean the projection
-            if (oSRS.exportToWkt(&pszProjection) != OGRERR_NONE)
+            // Export Projection to Wkt.
+            // In case of error then clean the projection.
+            if(oSRS.exportToWkt(&pszProjection) != OGRERR_NONE)
                 pszProjection = CPLStrdup("");
 
             CPLFree(dfCenterCoord);
@@ -1093,8 +1061,8 @@ void HDF5ImageDataset::CaptureCSKGeolocation(int iProductType)
     }
     else
     {
-        //Export GCPProjection to Wkt.
-        //In case of error then clean the projection
+        // Export GCPProjection to Wkt.
+        // In case of error then clean the projection
         if(oSRS.exportToWkt(&pszGCPProjection) != OGRERR_NONE)
             pszGCPProjection = CPLStrdup("");
     }
@@ -1116,14 +1084,14 @@ void HDF5ImageDataset::CaptureCSKGeoTransform(int iProductType)
     const char *pszSubdatasetName = GetSubdatasetName();
 
     bHasGeoTransform = false;
-    //If the product level is not L1C or L1D then
-    //it doesn't have a valid projection
+    // If the product level is not L1C or L1D then
+    // it doesn't have a valid projection.
     if(iProductType == PROD_CSK_L1C || iProductType == PROD_CSK_L1D)
     {
-        //If there is a subdataset
+        // If there is a subdataset.
         if(pszSubdatasetName != NULL)
         {
-            CPLString osULPath = pszSubdatasetName ;
+            CPLString osULPath = pszSubdatasetName;
             osULPath += "/Top Left East-North";
 
             CPLString osLineSpacingPath = pszSubdatasetName;
@@ -1136,19 +1104,23 @@ void HDF5ImageDataset::CaptureCSKGeoTransform(int iProductType)
             double *pdLineSpacing = NULL;
             double *pdColumnSpacing = NULL;
 
-            //If it could find the attributes on the metadata
+            // If it could find the attributes on the metadata.
             if(HDF5ReadDoubleAttr(osULPath.c_str(), &pdOutUL) == CE_Failure ||
-               HDF5ReadDoubleAttr(osLineSpacingPath.c_str(), &pdLineSpacing) == CE_Failure ||
-               HDF5ReadDoubleAttr(osColumnSpacingPath.c_str(), &pdColumnSpacing) == CE_Failure)
+               HDF5ReadDoubleAttr(osLineSpacingPath.c_str(), &pdLineSpacing) ==
+                   CE_Failure ||
+               HDF5ReadDoubleAttr(osColumnSpacingPath.c_str(),
+                                  &pdColumnSpacing) == CE_Failure)
             {
                 bHasGeoTransform = false;
             }
             else
             {
-//            	geotransform[1] : width of pixel
-//            	geotransform[4] : rotational coefficient, zero for north up images.
-//            	geotransform[2] : rotational coefficient, zero for north up images.
-//            	geotransform[5] : height of pixel (but negative)
+                // geotransform[1] : width of pixel
+                // geotransform[4] : rotational coefficient, zero for north up
+                // images.
+                // geotransform[2] : rotational coefficient, zero for north up
+                // images.
+                // geotransform[5] : height of pixel (but negative)
 
                 adfGeoTransform[0] = pdOutUL[0];
                 adfGeoTransform[1] = pdLineSpacing[0];
@@ -1161,13 +1133,12 @@ void HDF5ImageDataset::CaptureCSKGeoTransform(int iProductType)
                 CPLFree(pdLineSpacing);
                 CPLFree(pdColumnSpacing);
 
-                bHasGeoTransform = TRUE;
+                bHasGeoTransform = true;
             }
         }
     }
 }
 
-
 /************************************************************************/
 /*                          CaptureCSKGCPs()                            */
 /************************************************************************/
@@ -1181,24 +1152,24 @@ void HDF5ImageDataset::CaptureCSKGeoTransform(int iProductType)
  */
 void HDF5ImageDataset::CaptureCSKGCPs(int iProductType)
 {
-    //Only retrieve GCPs for L0,L1A and L1B products
-    if(iProductType == PROD_CSK_L0||iProductType == PROD_CSK_L1A||
-       iProductType == PROD_CSK_L1B)
+    // Only retrieve GCPs for L0,L1A and L1B products.
+    if( iProductType == PROD_CSK_L0 || iProductType == PROD_CSK_L1A ||
+        iProductType == PROD_CSK_L1B )
     {
         nGCPCount = 4;
-        pasGCPList = static_cast<GDAL_GCP *>( CPLCalloc(sizeof(GDAL_GCP),4) );
+        pasGCPList = static_cast<GDAL_GCP *>(CPLCalloc(sizeof(GDAL_GCP), 4));
         CPLString osCornerName[4];
         double pdCornerPixel[4] = {0.0, 0.0, 0.0, 0.0};
         double pdCornerLine[4] = {0.0, 0.0, 0.0, 0.0};
 
-        const char * const pszSubdatasetName = GetSubdatasetName();
+        const char *const pszSubdatasetName = GetSubdatasetName();
 
-        //Load the subdataset name first
-        for( int i=0; i < 4; i++ )
+        // Load the subdataset name first.
+        for( int i = 0; i < 4; i++ )
             osCornerName[i] = pszSubdatasetName;
 
-        //Load the attribute name, and raster coordinates for
-        //all the corners
+        // Load the attribute name, and raster coordinates for
+        // all the corners.
         osCornerName[0] += "/Top Left Geodetic Coordinates";
         pdCornerPixel[0] = 0;
         pdCornerLine[0] = 0;
@@ -1215,12 +1186,12 @@ void HDF5ImageDataset::CaptureCSKGCPs(int iProductType)
         pdCornerPixel[3] = GetRasterXSize();
         pdCornerLine[3] = GetRasterYSize();
 
-        //For all the image's corners
-        for( int i=0;i<4;i++)
+        // For all the image's corners.
+        for( int i = 0; i < 4; i++ )
         {
-            GDALInitGCPs( 1, pasGCPList + i );
+            GDALInitGCPs(1, pasGCPList + i);
 
-            CPLFree( pasGCPList[i].pszId );
+            CPLFree(pasGCPList[i].pszId);
             pasGCPList[i].pszId = NULL;
 
             double *pdCornerCoordinates = NULL;
@@ -1229,33 +1200,33 @@ void HDF5ImageDataset::CaptureCSKGCPs(int iProductType)
             if(HDF5ReadDoubleAttr(osCornerName[i].c_str(),
                                   &pdCornerCoordinates) == CE_Failure)
             {
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                             "Error retrieving CSK GCPs\n" );
+                CPLError(CE_Failure, CPLE_OpenFailed,
+                         "Error retrieving CSK GCPs");
                 // Free on failure, e.g. in case of QLK subdataset.
                 for( i = 0; i < 4; i++ )
                 {
                     if( pasGCPList[i].pszId )
-                        CPLFree( pasGCPList[i].pszId );
+                        CPLFree(pasGCPList[i].pszId);
                     if( pasGCPList[i].pszInfo )
-                        CPLFree( pasGCPList[i].pszInfo );
-	            }
-                CPLFree( pasGCPList );
+                        CPLFree(pasGCPList[i].pszInfo);
+                }
+                CPLFree(pasGCPList);
                 pasGCPList = NULL;
                 nGCPCount = 0;
                 break;
             }
 
-            //Fill the GCPs name
-            pasGCPList[i].pszId = CPLStrdup( osCornerName[i].c_str() );
+            // Fill the GCPs name.
+            pasGCPList[i].pszId = CPLStrdup(osCornerName[i].c_str());
 
-            //Fill the coordinates
+            // Fill the coordinates.
             pasGCPList[i].dfGCPX = pdCornerCoordinates[1];
             pasGCPList[i].dfGCPY = pdCornerCoordinates[0];
             pasGCPList[i].dfGCPZ = pdCornerCoordinates[2];
             pasGCPList[i].dfGCPPixel = pdCornerPixel[i];
             pasGCPList[i].dfGCPLine = pdCornerLine[i];
 
-            //Free the returned coordinates
+            // Free the returned coordinates.
             CPLFree(pdCornerCoordinates);
         }
     }
diff --git a/frmts/hdf5/iso19115_srs.cpp b/frmts/hdf5/iso19115_srs.cpp
index 5c10d4f..2986cda 100644
--- a/frmts/hdf5/iso19115_srs.cpp
+++ b/frmts/hdf5/iso19115_srs.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: iso19115_srs.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  BAG Driver
  * Purpose:  Implements code to parse ISO 19115 metadata to extract a
@@ -30,15 +29,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
-#include "cpl_minixml.h"
-#include "cpl_error.h"
+#include "cpl_port.h"
 
-CPL_CVSID("$Id: iso19115_srs.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <cstdlib>
+#include <cstring>
 
-/* used by bagdataset.cpp */
-OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
-                                   const char *pszISOXML );
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "iso19115_srs.h"
+#include "ogr_core.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: iso19115_srs.cpp 37925 2017-04-08 19:19:03Z goatbar $");
 
 /************************************************************************/
 /*                     OGR_SRS_ImportFromISO19115()                     */
@@ -48,67 +50,61 @@ OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
                                    const char *pszISOXML )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Parse the XML into tree form.                                   */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode *psRoot = CPLParseXMLString( pszISOXML );
+    // Parse the XML into tree form.
+    CPLXMLNode *psRoot = CPLParseXMLString(pszISOXML);
 
     if( psRoot == NULL )
         return OGRERR_FAILURE;
 
-    CPLStripXMLNamespace( psRoot, NULL, TRUE );
-
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
 
-/* -------------------------------------------------------------------- */
-/*      For now we look for projection codes recognised in the BAG      */
-/*      format (see ons_fsd.pdf: Metadata Dataset Character String      */
-/*      Constants).                                                     */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode *psRSI = CPLSearchXMLNode( psRoot, "=referenceSystemInfo" );
+    // For now we look for projection codes recognised in the BAG
+    // format (see ons_fsd.pdf: Metadata Dataset Character String
+    // Constants).
+    CPLXMLNode *psRSI = CPLSearchXMLNode(psRoot, "=referenceSystemInfo");
     if( psRSI == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to find <referenceSystemInfo> in metadata." );
-        CPLDestroyXMLNode( psRoot );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to find <referenceSystemInfo> in metadata.");
+        CPLDestroyXMLNode(psRoot);
         return OGRERR_FAILURE;
     }
 
     poThis->Clear();
 
-/* -------------------------------------------------------------------- */
-/*      First, set the datum.                                           */
-/* -------------------------------------------------------------------- */
+    // First, set the datum.
     const char *pszDatum =
-        CPLGetXMLValue( psRSI, "MD_CRS.datum.RS_Identifier.code", "" );
+        CPLGetXMLValue(psRSI, "MD_CRS.datum.RS_Identifier.code", "");
 
-    if( strlen(pszDatum) > 0
-        && poThis->SetWellKnownGeogCS( pszDatum ) != OGRERR_NONE )
+    if( strlen(pszDatum) > 0 &&
+        poThis->SetWellKnownGeogCS(pszDatum) != OGRERR_NONE )
     {
-        CPLDestroyXMLNode( psRoot );
+        CPLDestroyXMLNode(psRoot);
         return OGRERR_FAILURE;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Then try to extract the projection.                             */
-/* -------------------------------------------------------------------- */
+    // Then try to extract the projection.
     const char *pszProjection =
-        CPLGetXMLValue( psRSI, "MD_CRS.projection.RS_Identifier.code", "" );
+        CPLGetXMLValue(psRSI, "MD_CRS.projection.RS_Identifier.code", "");
 
-    if( EQUAL(pszProjection,"UTM") )
+    if( EQUAL(pszProjection, "UTM") )
     {
-        int nZone = atoi(CPLGetXMLValue( psRSI, "MD_CRS.projectionParameters.MD_ProjectionParameters.zone", "0" ));
-
-        /*
-        ** We have encountered files (#5152) that identify the southern
-        ** hemisphere with a false northing of 10000000 value.  The existing
-        ** code checked for negative zones but it isn't clear if any actual
-        ** files use that.
-        */
-        int bNorth =  nZone > 0;
+        int nZone = atoi(CPLGetXMLValue(
+            psRSI, "MD_CRS.projectionParameters.MD_ProjectionParameters.zone",
+            "0"));
+
+        // We have encountered files (#5152) that identify the southern
+        // hemisphere with a false northing of 10000000 value.  The existing
+        // code checked for negative zones, but it isn't clear if any actual
+        // files use that.
+        int bNorth = nZone > 0;
         if( bNorth )
         {
-            const char *pszFalseNorthing = CPLGetXMLValue( psRSI, "MD_CRS.projectionParameters.MD_ProjectionParameters.falseNorthing", "" );
-            if ( strlen(pszFalseNorthing) > 0 )
+            const char *pszFalseNorthing =
+                CPLGetXMLValue(psRSI, "MD_CRS.projectionParameters.MD_"
+                                      "ProjectionParameters.falseNorthing",
+                               "");
+            if( strlen(pszFalseNorthing) > 0 )
             {
                 if( EQUAL(pszFalseNorthing, "10000000"))
                 {
@@ -116,36 +112,37 @@ OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
                 }
                 else
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, "falseNorthing value not recognized: %s", pszFalseNorthing);
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "falseNorthing value not recognized: %s",
+                             pszFalseNorthing);
                 }
             }
         }
-        poThis->SetUTM( ABS(nZone), bNorth );
+        poThis->SetUTM(std::abs(nZone), bNorth);
     }
-    else if( EQUAL(pszProjection,"Geodetic") )
+    else if( EQUAL(pszProjection, "Geodetic") )
     {
         const char *pszEllipsoid =
-            CPLGetXMLValue( psRSI, "MD_CRS.ellipsoid.RS_Identifier.code", "" );
+            CPLGetXMLValue(psRSI, "MD_CRS.ellipsoid.RS_Identifier.code", "");
 
-        if( !EQUAL(pszDatum, "WGS84") ||
-            !EQUAL(pszEllipsoid, "WGS84") )
+        if( !EQUAL(pszDatum, "WGS84") || !EQUAL(pszEllipsoid, "WGS84") )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "ISO 19115 parser does not support custom GCS." );
-            CPLDestroyXMLNode( psRoot );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "ISO 19115 parser does not support custom GCS.");
+            CPLDestroyXMLNode(psRoot);
             return OGRERR_FAILURE;
         }
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "projection = %s not recognised by ISO 19115 parser.",
-                  pszProjection );
-        CPLDestroyXMLNode( psRoot );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "projection = %s not recognised by ISO 19115 parser.",
+                 pszProjection);
+        CPLDestroyXMLNode(psRoot);
         return OGRERR_FAILURE;
     }
 
-    CPLDestroyXMLNode( psRoot );
+    CPLDestroyXMLNode(psRoot);
 
     return OGRERR_NONE;
 }
diff --git a/frmts/hdf5/iso19115_srs.h b/frmts/hdf5/iso19115_srs.h
new file mode 100644
index 0000000..dab598b
--- /dev/null
+++ b/frmts/hdf5/iso19115_srs.h
@@ -0,0 +1,43 @@
+/******************************************************************************
+ * $Id: iso19115_srs.cpp 35951 2016-10-26 16:53:54Z goatbar $
+ *
+ * Project:  BAG Driver
+ * Purpose:  Implements code to parse ISO 19115 metadata to extract a
+ *           spatial reference system.  Eventually intended to be made
+ *           a method on OGRSpatialReference.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef ISO19155_SRS_H_INCLUDED_
+#define ISO19155_SRS_H_INCLUDED_
+
+#include "cpl_port.h"
+#include "ogr_core.h"
+#include "ogr_spatialref.h"
+
+OGRErr OGR_SRS_ImportFromISO19115( OGRSpatialReference *poThis,
+                                   const char *pszISOXML );
+
+#endif  // ISO19155_SRS_H_INCLUDED_
diff --git a/frmts/hf2/hf2dataset.cpp b/frmts/hf2/hf2dataset.cpp
index 42aa869..235d9b0 100644
--- a/frmts/hf2/hf2dataset.cpp
+++ b/frmts/hf2/hf2dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hf2dataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  HF2 driver
  * Purpose:  GDALDataset driver for HF2/HFZ dataset.
@@ -32,9 +31,13 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
+#include <cstdlib>
+#include <cmath>
+
+#include <algorithm>
 #include <limits>
 
-CPL_CVSID("$Id: hf2dataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: hf2dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -61,8 +64,8 @@ class HF2Dataset : public GDALPamDataset
                  HF2Dataset();
     virtual     ~HF2Dataset();
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char* GetProjectionRef();
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char* GetProjectionRef() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -87,12 +90,11 @@ class HF2RasterBand : public GDALPamRasterBand
   public:
 
                 HF2RasterBand( HF2Dataset *, int, GDALDataType );
-               ~HF2RasterBand();
+    virtual ~HF2RasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                           HF2RasterBand()                            */
 /************************************************************************/
@@ -101,8 +103,8 @@ HF2RasterBand::HF2RasterBand( HF2Dataset *poDSIn, int nBandIn, GDALDataType eDT
     pafBlockData(NULL),
     nLastBlockYOff(-1)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = eDT;
 
@@ -166,8 +168,10 @@ CPLErr HF2RasterBand::IReadBlock( int nBlockXOff, int nLineYOff,
             CPL_LSBPTR32(&fScale);
             CPL_LSBPTR32(&fOff);
 
-            const int nTileWidth = MIN(nBlockXSize, nRasterXSize - nxoff * nBlockXSize);
-            const int nTileHeight = MIN(nBlockXSize, nRasterYSize - nBlockYOff * nBlockXSize);
+            const int nTileWidth =
+                std::min(nBlockXSize, nRasterXSize - nxoff * nBlockXSize);
+            const int nTileHeight =
+                std::min(nBlockXSize, nRasterYSize - nBlockYOff * nBlockXSize);
 
             for(int j=0;j<nTileHeight;j++)
             {
@@ -231,7 +235,8 @@ CPLErr HF2RasterBand::IReadBlock( int nBlockXOff, int nLineYOff,
         CPLFree(pabyData);
     }
 
-    const int nTileWidth = MIN(nBlockXSize, nRasterXSize - nBlockXOff * nBlockXSize);
+    const int nTileWidth =
+        std::min(nBlockXSize, nRasterXSize - nBlockXOff * nBlockXSize);
     memcpy(pImage, pafBlockData + nBlockXOff * nBlockXSize * nBlockXSize +
                                   nYOffInTile * nBlockXSize,
            nTileWidth * sizeof(float));
@@ -303,8 +308,9 @@ int HF2Dataset::LoadBlockMap()
             CPL_LSBPTR32(&fScale);
             CPL_LSBPTR32(&fOff);
             //printf("fScale = %f, fOff = %f\n", fScale, fOff);
-            const int nCols = MIN(nTileSize, nRasterXSize - nTileSize *i);
-            const int nLines = MIN(nTileSize, nRasterYSize - nTileSize *j);
+            const int nCols = std::min(nTileSize, nRasterXSize - nTileSize * i);
+            const int nLines =
+                std::min(nTileSize, nRasterYSize - nTileSize * j);
             for(int k = 0; k < nLines; k++)
             {
                 GByte nWordSize;
@@ -464,7 +470,10 @@ GDALDataset *HF2Dataset::Open( GDALOpenInfo * poOpenInfo )
     VSIFSeekL(fp, 28, SEEK_SET);
 
     int bHasExtent = FALSE;
-    double dfMinX = 0, dfMaxX = 0, dfMinY = 0, dfMaxY = 0;
+    double dfMinX = 0.0;
+    double dfMaxX = 0.0;
+    double dfMinY = 0.0;
+    double dfMaxY = 0.0;
     int bHasUTMZone = FALSE;
     GInt16 nUTMZone = 0;
     int bHasEPSGDatumCode = FALSE;
@@ -472,9 +481,8 @@ GDALDataset *HF2Dataset::Open( GDALOpenInfo * poOpenInfo )
     int bHasEPSGCode = FALSE;
     GInt16 nEPSGCode = 0;
     int bHasRelativePrecision = FALSE;
-    float fRelativePrecision = 0;
-    char szApplicationName[256];
-    szApplicationName[0] = 0;
+    float fRelativePrecision = 0.0f;
+    char szApplicationName[256] = { 0 };
 
     GUInt32 nExtendedHeaderOff = 0;
     while(nExtendedHeaderOff < nExtendedHeaderLen)
@@ -546,7 +554,7 @@ GDALDataset *HF2Dataset::Open( GDALOpenInfo * poOpenInfo )
             bHasRelativePrecision = TRUE;
         }
         else if (strcmp(szBlockName, "app-name") == 0 &&
-                 nBlockSize < 256)
+                 nBlockSize < sizeof(szApplicationName))
         {
             VSIFReadL(szApplicationName, nBlockSize, 1, fp);
             szApplicationName[nBlockSize] = 0;
@@ -607,10 +615,10 @@ GDALDataset *HF2Dataset::Open( GDALOpenInfo * poOpenInfo )
             }
         }
 
-        if (bHasUTMZone && ABS(nUTMZone) >= 1 && ABS(nUTMZone) <= 60)
+        if (bHasUTMZone && std::abs(nUTMZone) >= 1 && std::abs(nUTMZone) <= 60)
         {
             bHasSRS = true;
-            oSRS.SetUTM(ABS(nUTMZone), nUTMZone > 0);
+            oSRS.SetUTM(std::abs(static_cast<int>(nUTMZone)), nUTMZone > 0);
         }
         if (bHasSRS)
             oSRS.exportToWkt(&poDS->pszWKT);
@@ -642,7 +650,7 @@ GDALDataset *HF2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Support overviews.                                              */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, osOriginalFilename.c_str() );
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -654,10 +662,9 @@ CPLErr HF2Dataset::GetGeoTransform( double * padfTransform )
 {
     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
 
-    return( CE_None );
+    return CE_None;
 }
 
-
 static void WriteShort(VSILFILE* fp, GInt16 val)
 {
     CPL_LSBPTR16(&val);
@@ -824,9 +831,10 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
         {
             const double dfLinear = oSRS.GetLinearUnits();
 
-            if( ABS(dfLinear - 0.3048) < 0.0000001 )
+            if( std::abs(dfLinear - 0.3048) < 0.0000001 )
                 nExtentUnits = 2;
-            else if( ABS(dfLinear - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
+            else if( std::abs(dfLinear - CPLAtof(SRS_UL_US_FOOT_CONV)) <
+                     0.00000001 )
                 nExtentUnits = 3;
             else
                 nExtentUnits = 1;
@@ -938,13 +946,14 @@ GDALDataset* HF2Dataset::CreateCopy( const char * pszFilename,
     {
         for(int i=0;i<nXBlocks && eErr == CE_None;i++)
         {
-            const int nReqXSize = MIN(nTileSize, nXSize - i * nTileSize);
-            const int nReqYSize = MIN(nTileSize, nYSize - j * nTileSize);
-            eErr = poSrcDS->GetRasterBand(1)->RasterIO(GF_Read,
-                                                i * nTileSize, MAX(0, nYSize - (j + 1) * nTileSize),
-                                                nReqXSize, nReqYSize,
-                                                pTileBuffer, nReqXSize, nReqYSize,
-                                                eReqDT, 0, 0, NULL);
+            const int nReqXSize = std::min(nTileSize, nXSize - i * nTileSize);
+            const int nReqYSize = std::min(nTileSize, nYSize - j * nTileSize);
+            eErr = poSrcDS->GetRasterBand(1)->RasterIO(
+                GF_Read,
+                i * nTileSize, std::max(0, nYSize - (j + 1) * nTileSize),
+                nReqXSize, nReqYSize,
+                pTileBuffer, nReqXSize, nReqYSize,
+                eReqDT, 0, 0, NULL);
             if (eErr != CE_None)
                 break;
 
diff --git a/frmts/hfa/GNUmakefile b/frmts/hfa/GNUmakefile
index 27d6dee..eaca47f 100644
--- a/frmts/hfa/GNUmakefile
+++ b/frmts/hfa/GNUmakefile
@@ -1,24 +1,19 @@
-
-
 include ../../GDALmake.opt
 
-HFAOBJ  =	hfaopen.o hfaentry.o hfadictionary.o hfafield.o hfatype.o \
-		hfaband.o hfacompress.o
-OBJ	=	$(HFAOBJ) hfadataset.o hfa_overviews.o
-
-ALL_C_FLAGS	=	 $(CFLAGS)
+HFAOBJ := hfaopen.o hfaentry.o hfadictionary.o hfafield.o hfatype.o
+HFAOBJ += hfaband.o hfacompress.o
+OBJ := $(HFAOBJ) hfadataset.o hfa_overviews.o
 
+ALL_C_FLAGS = $(CFLAGS)
 
-
-default:	$(OBJ:.o=.$(OBJ_EXT))
+default: $(OBJ:.o=.$(OBJ_EXT))
 
 clean:
 	rm -f *.o hfatest $(O_OBJ)
 
-$(O_OBJ):  hfa.h hfa_p.h
+$(O_OBJ): hfa.h hfa_p.h
 
-hfatest:	hfatest.$(OBJ_EXT) $(HFAOBJ:.o=.$(OBJ_EXT))
+hfatest: hfatest.$(OBJ_EXT) $(HFAOBJ:.o=.$(OBJ_EXT))
 	$(LD) hfatest.$(OBJ_EXT) $(HFAOBJ:.o=.$(OBJ_EXT)) ../../port/*.$(OBJ_EXT) $(LIBS) -o hfatest
 
-install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
-
+install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/hfa/TODO_Projections.txt b/frmts/hfa/TODO_Projections.txt
index 7109051..1f66e8c 100644
--- a/frmts/hfa/TODO_Projections.txt
+++ b/frmts/hfa/TODO_Projections.txt
@@ -7,11 +7,11 @@ EPRJ_HOTINE_OBLIQUE_MERCATOR:
   What should we do if proParams[12] *not* > 0.0?
 
 EPRJ_KROVAK:
-  still issues around axis orientation - esri uses special parameters to 
+  still issues around axis orientation - esri uses special parameters to
   represent this.  hfadataset.cpp is ignoring these parameters from .img.
 
-"Anchored LSR" (53) 
+"Anchored LSR" (53)
   - was EPRJ_LOCAL in 1.6-esri.
 
- 
+
 
diff --git a/frmts/hfa/frmt_hfa.html b/frmts/hfa/frmt_hfa.html
index a732a7d..87709de 100644
--- a/frmts/hfa/frmt_hfa.html
+++ b/frmts/hfa/frmt_hfa.html
@@ -54,6 +54,12 @@ the original .img) set the global config option HFA_USE_RRD=YES).<p>
 
 Layer names can be set and retrieved with the GDALSetDescription/GDALGetDescription calls on the Raster Band objects. <p>
 
+<p>Some HFA band metadata exported to GDAL metadata:</p>
+<ul>
+<li>LAYER_TYPE - layer type (athematic, ... )</li>
+<li>OVERVIEWS_ALGORITHM - layer overviews algorithm ('IMAGINE 2X2 Resampling', 'IMAGINE 4X4 Resampling', and others)</li>
+</ul>
+
 <h2>Configuration Options</h2>
 Currently two <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">runtime configuration options</a> are supported by the HFA driver:
 
@@ -79,8 +85,8 @@ See Also:<p>
 <li> Implemented as <tt>gdal/frmts/hfa/hfadataset.cpp</tt>.<p>
 
 <li> More information, and other tools are available on the
-<a href="http://home.gdal.org/projects/imagine/hfa_index.html">
-Imagine (.img) Reader</a> page.<p>
+<a href="http://web.archive.org/web/20130730133056/http://home.gdal.org/projects/imagine/hfa_index.html">
+Imagine (.img) Reader</a> page as saved by archive.org.<p>
 
 <li> <a href="http://www.erdas.com/">Erdas.com</a><p>
 
diff --git a/frmts/hfa/hfa.h b/frmts/hfa/hfa.h
index a173102..20bf91d 100644
--- a/frmts/hfa/hfa.h
+++ b/frmts/hfa/hfa.h
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: hfa.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: hfa.h 36236 2016-11-14 20:02:32Z rouault $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Public (C callable) interface for the Erdas Imagine reading
- *           code.  This include files, and it's implementing code depends
+ *           code.  This include files, and its implementing code depends
  *           on CPL, but not GDAL.
  * Author:   Frank Warmerdam, warmerdam at pobox.com
  *
@@ -45,79 +45,77 @@ typedef struct hfainfo *HFAHandle;
 /*      simplifications.                                                */
 /* -------------------------------------------------------------------- */
 typedef struct {
-	double x;			/* coordinate x-value */
-	double y;			/* coordinate y-value */
+        double x;                       /* coordinate x-value */
+        double y;                       /* coordinate y-value */
 } Eprj_Coordinate;
 
-
 typedef struct {
-	double width;			/* pixelsize width */
-	double height;			/* pixelsize height */
+        double width;                   /* pixelsize width */
+        double height;                  /* pixelsize height */
 } Eprj_Size;
 
-
 typedef struct {
-	char * proName;		    /* projection name */
-	Eprj_Coordinate upperLeftCenter;    /* map coordinates of center of
-						   upper left pixel */
-	Eprj_Coordinate lowerRightCenter;   /* map coordinates of center of
-						   lower right pixel */
-	Eprj_Size pixelSize;		    /* pixel size in map units */
-	char * units;		    /* units of the map */
+        char * proName;             /* projection name */
+        Eprj_Coordinate upperLeftCenter;    /* map coordinates of center of
+                                               upper left pixel */
+        Eprj_Coordinate lowerRightCenter;   /* map coordinates of center of
+                                               lower right pixel */
+        Eprj_Size pixelSize;        /* pixel size in map units */
+        char * units;               /* units of the map */
 } Eprj_MapInfo;
 
 typedef enum {
-	EPRJ_INTERNAL,		/* Indicates that the projection is built into
-				   the eprj package as function calls */
-	EPRJ_EXTERNAL		/* Indicates that the projection is accessible
-				   as an EXTERNal executable */
+        EPRJ_INTERNAL,          /* Indicates that the projection is built into
+                                   the eprj package as function calls */
+        EPRJ_EXTERNAL           /* Indicates that the projection is accessible
+                                   as an EXTERNal executable */
 } Eprj_ProType;
 
 typedef enum {
-	EPRJ_NAD27=1,		/* Use the North America Datum 1927 */
-	EPRJ_NAD83=2,		/* Use the North America Datum 1983 */
-	EPRJ_HARN		/* Use the North America Datum High Accuracy
-				   Reference Network */
+        EPRJ_NAD27=1,           /* Use the North America Datum 1927 */
+        EPRJ_NAD83=2,           /* Use the North America Datum 1983 */
+        EPRJ_HARN               /* Use the North America Datum High Accuracy
+                                   Reference Network */
 } Eprj_NAD;
 
 typedef enum {
-	EPRJ_DATUM_PARAMETRIC,		/* The datum info is 7 doubles */
-	EPRJ_DATUM_GRID,		/* The datum info is a name */
-	EPRJ_DATUM_REGRESSION,
-	EPRJ_DATUM_NONE
+        EPRJ_DATUM_PARAMETRIC,          /* The datum info is 7 doubles */
+        EPRJ_DATUM_GRID,                /* The datum info is a name */
+        EPRJ_DATUM_REGRESSION,
+        EPRJ_DATUM_NONE
 } Eprj_DatumType;
 
 typedef struct {
-	char *datumname;		/* name of the datum */
-	Eprj_DatumType type;		/* The datum type */
-	double  params[7];		/* The parameters for type
-						   EPRJ_DATUM_PARAMETRIC */
-	char *gridname;		/* name of the grid file */
+        char *datumname;                /* name of the datum */
+        Eprj_DatumType type;            /* The datum type */
+        double  params[7];              /* The parameters for type
+                                           EPRJ_DATUM_PARAMETRIC */
+        char *gridname;                 /* name of the grid file */
 } Eprj_Datum;
 
 typedef struct {
-	char * sphereName;	/* name of the ellipsoid */
-	double a;			/* semi-major axis of ellipsoid */
-	double b;			/* semi-minor axis of ellipsoid */
-	double eSquared;		/* eccentricity-squared */
-	double radius;			/* radius of the sphere */
+        char * sphereName;              /* name of the ellipsoid */
+        double a;                       /* semi-major axis of ellipsoid */
+        double b;                       /* semi-minor axis of ellipsoid */
+        double eSquared;                /* eccentricity-squared */
+        double radius;                  /* radius of the sphere */
 } Eprj_Spheroid;
 
 typedef struct {
-	Eprj_ProType proType;		/* projection type */
-	int proNumber;			/* projection number for internal
-					   projections */
-	char * proExeName;	/* projection executable name for
-					   EXTERNal projections */
-	char * proName;	/* projection name */
-	int proZone;			/* projection zone (UTM, SP only) */
-	double proParams[15];	/* projection parameters array in the
-					   GCTP form */
-	Eprj_Spheroid proSpheroid;	/* projection spheroid */
+        Eprj_ProType proType;           /* projection type */
+        int proNumber;                  /* projection number for internal
+                                           projections */
+        char * proExeName;              /* projection executable name for
+                                           EXTERNal projections */
+        char * proName;                 /* projection name */
+        int proZone;                    /* projection zone (UTM, SP only) */
+        double proParams[15];           /* projection parameters array in the
+                                           GCTP form */
+        Eprj_Spheroid proSpheroid;      /* projection spheroid */
 } Eprj_ProParameters;
 
 typedef struct {
-    int		order;
+    int         order;
     double      polycoefmtx[18];
     double      polycoefvector[2];
 } Efga_Polynomial;
@@ -151,7 +149,7 @@ typedef enum
 CPL_C_START
 
 HFAHandle CPL_DLL HFAOpen( const char * pszFilename, const char * pszMode );
-int	CPL_DLL HFAClose( HFAHandle ); /* 0 = success */
+int CPL_DLL HFAClose( HFAHandle ); /* 0 = success */
 CPLErr HFADelete( const char *pszFilename );
 CPLErr HFARenameReferences( HFAHandle, const char *, const char * );
 
@@ -159,13 +157,14 @@ HFAHandle CPL_DLL HFACreateLL( const char *pszFilename );
 HFAHandle CPL_DLL HFACreate( const char *pszFilename, int nXSize, int nYSize,
                              int nBands, EPTType eDataType, char ** papszOptions );
 const char CPL_DLL *HFAGetIGEFilename( HFAHandle );
-CPLErr  CPL_DLL HFAFlush( HFAHandle );
+CPLErr CPL_DLL HFAFlush( HFAHandle );
 int CPL_DLL HFACreateOverview( HFAHandle hHFA, int nBand, int nOverviewLevel,
                                const char *pszResampling );
 
 const Eprj_MapInfo CPL_DLL *HFAGetMapInfo( HFAHandle );
 int CPL_DLL HFAGetGeoTransform( HFAHandle, double* );
-CPLErr CPL_DLL HFASetGeoTransform( HFAHandle, const char*, const char*,double*);
+CPLErr CPL_DLL HFASetGeoTransform( HFAHandle, const char*,
+                                   const char*, double *);
 CPLErr CPL_DLL HFASetMapInfo( HFAHandle, const Eprj_MapInfo * );
 const Eprj_Datum CPL_DLL *HFAGetDatum( HFAHandle );
 CPLErr CPL_DLL HFASetDatum( HFAHandle, const Eprj_Datum * );
@@ -193,20 +192,20 @@ CPLErr CPL_DLL HFAGetRasterBlockEx( HFAHandle hHFA, int nBand, int nXBlock,
 CPLErr CPL_DLL HFAGetOverviewRasterBlock( HFAHandle hHFA, int nBand,
                                           int iOverview,
                                    int nXBlock, int nYBlock, void * pData );
-CPLErr CPL_DLL HFAGetOverviewRasterBlockEx( HFAHandle hHFA, int nBand,
-                                          int iOverview,
-                                   int nXBlock, int nYBlock, void * pData, int nDataSize );
+CPLErr CPL_DLL HFAGetOverviewRasterBlockEx(
+                   HFAHandle hHFA, int nBand, int iOverview,
+                   int nXBlock, int nYBlock, void * pData, int nDataSize );
 CPLErr CPL_DLL HFASetRasterBlock( HFAHandle hHFA, int nBand,
                                   int nXBlock, int nYBlock,
                                   void * pData );
 CPLErr CPL_DLL HFASetOverviewRasterBlock(
-    HFAHandle hHFA, int nBand, int iOverview,int nXBlock, int nYBlock,
+    HFAHandle hHFA, int nBand, int iOverview, int nXBlock, int nYBlock,
     void * pData );
 const char * HFAGetBandName( HFAHandle hHFA, int nBand );
 void HFASetBandName( HFAHandle hHFA, int nBand, const char *pszName );
 int     CPL_DLL HFAGetDataTypeBits( EPTType eDataType );
 const char CPL_DLL *HFAGetDataTypeName( EPTType eDataType );
-CPLErr	CPL_DLL HFAGetPCT( HFAHandle, int, int *,
+CPLErr  CPL_DLL HFAGetPCT( HFAHandle, int, int *,
                            double **, double **, double ** , double **,
                            double **);
 CPLErr  CPL_DLL HFASetPCT( HFAHandle, int, int, double *, double *, double *, double * );
@@ -231,16 +230,16 @@ HFAEvaluateXFormStack( int nStepCount, int bForward,
                        double *pdfX, double *pdfY );
 
 char CPL_DLL **HFAReadCameraModel( HFAHandle psInfo );
-
+const char CPL_DLL *HFAReadElevationUnit( HFAHandle psInfo, int iBand );
 
 /* -------------------------------------------------------------------- */
 /*      Projection codes.                                               */
 /* -------------------------------------------------------------------- */
-#define EPRJ_LATLONG				0
-#define EPRJ_UTM				1
-#define EPRJ_STATE_PLANE 			2
-#define EPRJ_ALBERS_CONIC_EQUAL_AREA		3
-#define EPRJ_LAMBERT_CONFORMAL_CONIC	        4
+#define EPRJ_LATLONG                            0
+#define EPRJ_UTM                                1
+#define EPRJ_STATE_PLANE                        2
+#define EPRJ_ALBERS_CONIC_EQUAL_AREA            3
+#define EPRJ_LAMBERT_CONFORMAL_CONIC            4
 #define EPRJ_MERCATOR                           5
 #define EPRJ_POLAR_STEREOGRAPHIC                6
 #define EPRJ_POLYCONIC                          7
@@ -306,8 +305,10 @@ char CPL_DLL **HFAReadCameraModel( HFAHandle psInfo );
 #define EPRJ_LAMBERT_CONFORMAL_CONIC_1SP        67
 #define EPRJ_PSEUDO_MERCATOR                    68
 #define EPRJ_MERCATOR_VARIANT_A                 69
+#define EPRJ_HOTINE_OBLIQUE_MERCATOR_VARIANT_A                70
+#define EPRJ_TRANSVERSE_MERCATOR_SOUTH_ORIENTATED             71
 
-#define EPRJ_EXTERNAL_RSO			"eprj_rso"
+#define EPRJ_EXTERNAL_RSO                       "eprj_rso"
 #define EPRJ_EXTERNAL_NZMG                      "nzmg"
 #define EPRJ_EXTERNAL_INTEGERIZED_SINUSOIDAL    "isin"
 
diff --git a/frmts/hfa/hfa_overviews.cpp b/frmts/hfa/hfa_overviews.cpp
index f6a12ff..ffbb38f 100644
--- a/frmts/hfa/hfa_overviews.cpp
+++ b/frmts/hfa/hfa_overviews.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfa_overviews.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine Driver
  * Purpose:  Entry point for building overviews, used by non-imagine formats.
@@ -27,11 +26,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
+#include "cpl_port.h"
 #include "hfa_p.h"
+
+#include <cstddef>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "gdal.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: hfa_overviews.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: hfa_overviews.cpp 37899 2017-04-05 15:40:03Z goatbar $");
 
 CPLErr HFAAuxBuildOverviews( const char *pszOvrFilename,
                              GDALDataset *poParentDS,
@@ -43,84 +52,75 @@ CPLErr HFAAuxBuildOverviews( const char *pszOvrFilename,
                              void *pProgressData )
 
 {
-/* ==================================================================== */
-/*      If the .aux file doesn't exist yet then create it now.          */
-/* ==================================================================== */
+    // If the .aux file doesn't exist yet then create it now.
     if( *ppoODS == NULL )
     {
         GDALDataType eDT = GDT_Unknown;
-/* -------------------------------------------------------------------- */
-/*      Determine the band datatype, and verify that all bands are      */
-/*      the same.                                                       */
-/* -------------------------------------------------------------------- */
-        int iBand;
-
-        for( iBand = 0; iBand < nBands; iBand++ )
+        // Determine the band datatype, and verify that all bands are the same.
+        for( int iBand = 0; iBand < nBands; iBand++ )
         {
             GDALRasterBand *poBand =
-                poParentDS->GetRasterBand( panBandList[iBand] );
+                poParentDS->GetRasterBand(panBandList[iBand]);
 
             if( iBand == 0 )
+            {
                 eDT = poBand->GetRasterDataType();
+            }
             else
             {
                 if( eDT != poBand->GetRasterDataType() )
                 {
-                    CPLError( CE_Failure, CPLE_NotSupported,
-                              "HFAAuxBuildOverviews() doesn't support a mixture of band"
-                              " data types." );
+                    CPLError(CE_Failure, CPLE_NotSupported,
+                             "HFAAuxBuildOverviews() doesn't support a "
+                             "mixture of band data types.");
                     return CE_Failure;
                 }
             }
         }
 
-/* -------------------------------------------------------------------- */
-/*      Create the HFA (.aux) file.  We create it with                  */
-/*      COMPRESSED=YES so that no space will be allocated for the       */
-/*      base band.                                                      */
-/* -------------------------------------------------------------------- */
-        GDALDriver *poHFADriver = (GDALDriver *) GDALGetDriverByName("HFA");
-        if (poHFADriver == NULL)
+        // Create the HFA (.aux) file.  We create it with
+        // COMPRESSED=YES so that no space will be allocated for the
+        // base band.
+        GDALDriver *poHFADriver =
+            static_cast<GDALDriver *>(GDALGetDriverByName("HFA"));
+        if( poHFADriver == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "HFA driver is unavailable." );
+            CPLError(CE_Failure, CPLE_AppDefined, "HFA driver is unavailable.");
             return CE_Failure;
         }
 
-        const char *apszOptions[4] = { "COMPRESSED=YES", "AUX=YES",
-                                       NULL, NULL };
-
         CPLString osDepFileOpt = "DEPENDENT_FILE=";
         osDepFileOpt += CPLGetFilename(poParentDS->GetDescription());
-        apszOptions[2] = osDepFileOpt.c_str();
+
+        const char *apszOptions[4] =
+            { "COMPRESSED=YES", "AUX=YES", osDepFileOpt.c_str(), NULL };
 
         *ppoODS =
-            poHFADriver->Create( pszOvrFilename,
-                                 poParentDS->GetRasterXSize(),
-                                 poParentDS->GetRasterYSize(),
-                                 poParentDS->GetRasterCount(), eDT, (char **)apszOptions );
+            poHFADriver->Create(pszOvrFilename,
+                                poParentDS->GetRasterXSize(),
+                                poParentDS->GetRasterYSize(),
+                                poParentDS->GetRasterCount(),
+                                eDT, const_cast<char **>(apszOptions));
 
         if( *ppoODS == NULL )
             return CE_Failure;
     }
 
-/* ==================================================================== */
-/*      Create the layers.  We depend on the normal buildoverviews      */
-/*      support for HFA to do this.  But we disable the internal        */
-/*      computation of the imagery for these layers.                    */
-/*                                                                      */
-/*      We avoid regenerating the new layers here, because if we did    */
-/*      it would use the base layer from the .aux file as the source    */
-/*      data, and that is fake (all invalid tiles).                     */
-/* ==================================================================== */
+    // Create the layers.  We depend on the normal buildoverviews
+    // support for HFA to do this.  But we disable the internal
+    // computation of the imagery for these layers.
+    //
+    // We avoid regenerating the new layers here, because if we did
+    // it would use the base layer from the .aux file as the source
+    // data, and that is fake (all invalid tiles).
     CPLString oAdjustedResampling = "NO_REGEN:";
     oAdjustedResampling += pszResampling;
 
     CPLErr eErr =
-        (*ppoODS)->BuildOverviews( oAdjustedResampling,
-                                   nNewOverviews, panNewOverviewList,
-                                   nBands, panBandList,
-                                   pfnProgress, pProgressData );
+        (*ppoODS)->BuildOverviews(oAdjustedResampling,
+                                  nNewOverviews, panNewOverviewList,
+                                  nBands, panBandList,
+                                  pfnProgress, pProgressData);
 
     return eErr;
 }
diff --git a/frmts/hfa/hfa_p.h b/frmts/hfa/hfa_p.h
index 4c23140..df036df 100644
--- a/frmts/hfa/hfa_p.h
+++ b/frmts/hfa/hfa_p.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: hfa_p.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: hfa_p.h 37904 2017-04-05 17:19:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Private class declarations for the HFA classes used to read
@@ -33,23 +33,27 @@
 #define HFA_P_H_INCLUDED
 
 #include "cpl_port.h"
+#include "hfa.h"
+
+#include <cstdio>
+#include <vector>
+
 #include "cpl_error.h"
 #include "cpl_vsi.h"
-#include <vector>
 
 #ifdef CPL_LSB
-#  define HFAStandard(n,p)	{}
+#  define HFAStandard(n,p) {}
 #else
    void HFAStandard( int, void *);
 #endif
 
 #include "hfa.h"
 
-class HFAEntry;
-class HFAType;
-class HFADictionary;
 class HFABand;
+class HFADictionary;
+class HFAEntry;
 class HFASpillFile;
+class HFAType;
 
 /************************************************************************/
 /*      Flag indicating read/write, or read-only access to data.        */
@@ -66,34 +70,34 @@ typedef enum {
 /*      dataset within hfaopen.cpp                                      */
 /************************************************************************/
 struct hfainfo {
-    VSILFILE	*fp;
+    VSILFILE    *fp;
 
-    char	*pszPath;
-    char        *pszFilename; /* sans path */
-    char        *pszIGEFilename; /* sans path */
+    char        *pszPath;
+    char        *pszFilename;  // Sans path.
+    char        *pszIGEFilename;  // Sans path.
 
-    HFAAccess	eAccess;
+    HFAAccess   eAccess;
 
     GUInt32     nEndOfFile;
-    GUInt32	nRootPos;
-    GUInt32	nDictionaryPos;
+    GUInt32     nRootPos;
+    GUInt32     nDictionaryPos;
 
-    GInt16	nEntryHeaderLength;
-    GInt32	nVersion;
+    GInt16      nEntryHeaderLength;
+    GInt32      nVersion;
 
-    int         bTreeDirty;
-    HFAEntry	*poRoot;
+    bool        bTreeDirty;
+    HFAEntry    *poRoot;
 
     HFADictionary *poDictionary;
-    char	*pszDictionary;
+    char        *pszDictionary;
 
-    int		nXSize;
-    int		nYSize;
+    int         nXSize;
+    int         nYSize;
 
-    int		nBands;
-    HFABand	**papoBand;
+    int         nBands;
+    HFABand     **papoBand;
 
-    void	*pMapInfo;
+    void        *pMapInfo;
     void        *pDatum;
     void        *pProParameters;
 
@@ -106,10 +110,10 @@ GUInt32 HFAAllocateSpace( HFAInfo_t *, GUInt32 );
 CPLErr  HFAParseBandInfo( HFAInfo_t * );
 HFAInfo_t *HFAGetDependent( HFAInfo_t *, const char * );
 HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase );
-int HFACreateSpillStack( HFAInfo_t *, int nXSize, int nYSize, int nLayers,
-                         int nBlockSize, EPTType eDataType,
-                         GIntBig *pnValidFlagsOffset,
-                         GIntBig *pnDataOffset );
+bool HFACreateSpillStack( HFAInfo_t *, int nXSize, int nYSize, int nLayers,
+                          int nBlockSize, EPTType eDataType,
+                          GIntBig *pnValidFlagsOffset,
+                          GIntBig *pnDataOffset );
 
 const char * const * GetHFAAuxMetaDataList();
 
@@ -124,7 +128,7 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
                 int nXSize, int nYSize, EPTType eDataType,
                 char **papszOptions,
 
-                // these are only related to external (large) files
+                // These are only related to external (large) files.
                 GIntBig nStackValidFlagsOffset,
                 GIntBig nStackDataOffset,
                 int nStackCount, int nStackIndex );
@@ -141,28 +145,28 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 
 class HFABand
 {
-    int		nBlocks;
+    int         nBlocks;
 
-    // Used for single-file modification
+    // Used for single-file modification.
     vsi_l_offset *panBlockStart;
-    int		*panBlockSize;
-    int		*panBlockFlag;
+    int         *panBlockSize;
+    int         *panBlockFlag;
 
-    // Used for spill-file modification
+    // Used for spill-file modification.
     vsi_l_offset nBlockStart;
     vsi_l_offset nBlockSize;
     int         nLayerStackCount;
     int         nLayerStackIndex;
 
-#define BFLG_VALID	0x01
-#define BFLG_COMPRESSED	0x02
+#define BFLG_VALID      0x01
+#define BFLG_COMPRESSED 0x02
 
-    int		nPCTColors;
-    double	*apadfPCT[4];
+    int         nPCTColors;
+    double      *apadfPCT[4];
     double      *padfPCTBins;
 
-    CPLErr	LoadBlockInfo();
-    CPLErr	LoadExternalBlockInfo();
+    CPLErr      LoadBlockInfo();
+    CPLErr      LoadExternalBlockInfo();
 
     void ReAllocBlock( int iBlock, int nSize );
     void NullBlock( void * );
@@ -170,43 +174,44 @@ class HFABand
     CPLString   osOverName;
 
   public:
-    		HFABand( HFAInfo_t *, HFAEntry * );
+                HFABand( HFAInfo_t *, HFAEntry * );
                 ~HFABand();
 
-    HFAInfo_t	*psInfo;
+    HFAInfo_t   *psInfo;
 
-    VSILFILE	*fpExternal;
+    VSILFILE    *fpExternal;
 
-    EPTType	eDataType;
-    HFAEntry	*poNode;
+    EPTType     eDataType;
+    HFAEntry    *poNode;
 
-    int		nBlockXSize;
-    int		nBlockYSize;
+    int         nBlockXSize;
+    int         nBlockYSize;
 
-    int		nWidth;
-    int		nHeight;
+    int         nWidth;
+    int         nHeight;
 
-    int		nBlocksPerRow;
-    int		nBlocksPerColumn;
+    int         nBlocksPerRow;
+    int         nBlocksPerColumn;
 
-    int         bNoDataSet;
+    bool        bNoDataSet;
     double      dfNoData;
 
-    int         bOverviewsPending;
-    int		nOverviews;
+    bool        bOverviewsPending;
+    int         nOverviews;
     HFABand     **papoOverviews;
 
-    CPLErr	GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDataSize );
-    CPLErr	SetRasterBlock( int nXBlock, int nYBlock, void * pData );
+    CPLErr      GetRasterBlock( int nXBlock, int nYBlock, void * pData,
+                                int nDataSize );
+    CPLErr      SetRasterBlock( int nXBlock, int nYBlock, void * pData );
 
     const char * GetBandName();
     void SetBandName(const char *pszName);
 
     CPLErr  SetNoDataValue( double dfValue );
 
-    CPLErr	GetPCT( int *, double **, double **, double **, double **,
+    CPLErr      GetPCT( int *, double **, double **, double **, double **,
                         double ** );
-    CPLErr	SetPCT( int, double *, double *, double *, double * );
+    CPLErr      SetPCT( int, double *, double *, double *, double * );
 
     int         CreateOverview( int nOverviewLevel, const char *pszResampling );
     CPLErr      CleanOverviews();
@@ -214,7 +219,6 @@ class HFABand
     CPLErr      LoadOverviews();
 };
 
-
 /************************************************************************/
 /*                               HFAEntry                               */
 /*                                                                      */
@@ -224,35 +228,35 @@ class HFABand
 /************************************************************************/
 class HFAEntry
 {
-    int         bDirty;
-    GUInt32	nFilePos;
+    bool        bDirty;
+    GUInt32     nFilePos;
 
-    HFAInfo_t	*psHFA;
-    HFAEntry	*poParent;
-    HFAEntry	*poPrev;
+    HFAInfo_t   *psHFA;
+    HFAEntry    *poParent;
+    HFAEntry    *poPrev;
 
-    GUInt32	nNextPos;
-    HFAEntry	*poNext;
+    GUInt32     nNextPos;
+    HFAEntry    *poNext;
 
-    GUInt32	nChildPos;
-    HFAEntry	*poChild;
+    GUInt32     nChildPos;
+    HFAEntry    *poChild;
 
-    char	szName[64];
-    char	szType[32];
+    char        szName[64];
+    char        szType[32];
 
-    HFAType	*poType;
+    HFAType     *poType;
 
-    GUInt32	nDataPos;
-    GUInt32	nDataSize;
-    GByte	*pabyData;
+    GUInt32     nDataPos;
+    GUInt32     nDataSize;
+    GByte      *pabyData;
 
-    void	LoadData();
+    void        LoadData();
 
-    int 	GetFieldValue( const char *, char, void *,
+    bool        GetFieldValue( const char *, char, void *,
                                int *pnRemainingDataSize );
     CPLErr      SetFieldValue( const char *, char, void * );
 
-    int         bIsMIFObject;
+    bool        bIsMIFObject;
 
                 HFAEntry();
                 HFAEntry( const char * pszDictionary,
@@ -266,9 +270,10 @@ class HFAEntry
 
 public:
     static HFAEntry* New( HFAInfo_t * psHFA, GUInt32 nPos,
-                          HFAEntry * poParent, HFAEntry *poPrev) CPL_WARN_UNUSED_RESULT;
+                          HFAEntry * poParent,
+                          HFAEntry *poPrev) CPL_WARN_UNUSED_RESULT;
 
-                 HFAEntry( HFAInfo_t *psHFA,
+                HFAEntry( HFAInfo_t *psHFA,
                           const char *pszNodeName,
                           const char *pszTypeName,
                           HFAEntry *poParent );
@@ -280,31 +285,33 @@ public:
 
     virtual     ~HFAEntry();
 
-    static HFAEntry*  BuildEntryFromMIFObject( HFAEntry *poContainer, const char *pszMIFObjectPath ) CPL_WARN_UNUSED_RESULT;
+    static HFAEntry*  BuildEntryFromMIFObject(
+                          HFAEntry *poContainer,
+                          const char *pszMIFObjectPath ) CPL_WARN_UNUSED_RESULT;
 
     CPLErr      RemoveAndDestroy();
 
-    GUInt32	GetFilePos() CPL_WARN_UNUSED_RESULT { return nFilePos; }
+    GUInt32     GetFilePos() const CPL_WARN_UNUSED_RESULT { return nFilePos; }
 
-    const char	*GetName() CPL_WARN_UNUSED_RESULT { return szName; }
+    const char  *GetName() const CPL_WARN_UNUSED_RESULT { return szName; }
     void SetName( const char *pszNodeName );
 
     const char  *GetType() CPL_WARN_UNUSED_RESULT { return szType; }
     HFAType     *GetTypeObject() CPL_WARN_UNUSED_RESULT;
 
     GByte      *GetData() CPL_WARN_UNUSED_RESULT { LoadData(); return pabyData; }
-    GUInt32	GetDataPos() CPL_WARN_UNUSED_RESULT { return nDataPos; }
-    GUInt32	GetDataSize() CPL_WARN_UNUSED_RESULT { return nDataSize; }
+    GUInt32     GetDataPos() const CPL_WARN_UNUSED_RESULT { return nDataPos; }
+    GUInt32     GetDataSize() const CPL_WARN_UNUSED_RESULT { return nDataSize; }
 
-    HFAEntry	*GetChild() CPL_WARN_UNUSED_RESULT;
-    HFAEntry	*GetNext() CPL_WARN_UNUSED_RESULT;
+    HFAEntry    *GetChild() CPL_WARN_UNUSED_RESULT;
+    HFAEntry    *GetNext() CPL_WARN_UNUSED_RESULT;
     HFAEntry    *GetNamedChild( const char * ) CPL_WARN_UNUSED_RESULT;
     std::vector<HFAEntry*> FindChildren( const char *pszName,
                                          const char *pszType) CPL_WARN_UNUSED_RESULT;
 
-    GInt32	GetIntField( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
-    double	GetDoubleField( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
-    const char	*GetStringField( const char *, CPLErr * = NULL, int *pnRemainingDataSize = NULL ) CPL_WARN_UNUSED_RESULT;
+    GInt32      GetIntField( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
+    double      GetDoubleField( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
+    const char  *GetStringField( const char *, CPLErr * = NULL, int *pnRemainingDataSize = NULL ) CPL_WARN_UNUSED_RESULT;
     GIntBig     GetBigIntField( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
     int         GetFieldCount( const char *, CPLErr * = NULL ) CPL_WARN_UNUSED_RESULT;
 
@@ -312,12 +319,12 @@ public:
     CPLErr      SetDoubleField( const char *, double );
     CPLErr      SetStringField( const char *, const char * );
 
-    void	DumpFieldValues( FILE *, const char * = NULL );
+    void        DumpFieldValues( FILE *, const char * = NULL );
 
     void        SetPosition();
     CPLErr      FlushToDisk();
 
-    void	MarkDirty();
+    void        MarkDirty();
     GByte      *MakeData( int nSize = 0 );
 };
 
@@ -330,47 +337,51 @@ public:
 class HFAField
 {
   public:
-    int		nBytes;
+    int         nBytes;
 
-    int		nItemCount;
-    char	chPointer; 	/* '\0', '*' or 'p' */
-    char	chItemType;	/* 1|2|4|e|... */
+    int         nItemCount;
+    // TODO(schwehr): Rename chPointer to something more meaningful.
+    // It's not a pointer.
+    char        chPointer;      // '\0', '*' or 'p'
+    char        chItemType;     // 1|2|4|e|...
 
-    char	*pszItemObjectType; /* if chItemType == 'o' */
-    HFAType	*poItemObjectType;
+    char        *pszItemObjectType;  // if chItemType == 'o'
+    HFAType     *poItemObjectType;
 
-    char	**papszEnumNames; /* normally NULL if not an enum */
+    char        **papszEnumNames;  // Normally NULL if not an enum.
 
-    char	*pszFieldName;
+    char        *pszFieldName;
 
-    char        szNumberString[36]; /* buffer used to return an int as a string */
+    char        szNumberString[36];  // Buffer used to return int as a string.
 
-    		HFAField();
+                HFAField();
                 ~HFAField();
 
     const char *Initialize( const char * );
 
-    void	CompleteDefn( HFADictionary * );
+    void        CompleteDefn( HFADictionary * );
 
-    void	Dump( FILE * );
+    void        Dump( FILE * );
 
-    int 	ExtractInstValue( const char * pszField, int nIndexValue,
-                     GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
-                     char chReqType, void *pReqReturn, int *pnRemainingDataSize = NULL );
+    bool        ExtractInstValue( const char * pszField, int nIndexValue,
+                                  GByte *pabyData, GUInt32 nDataOffset,
+                                  int nDataSize, char chReqType,
+                                  void *pReqReturn,
+                                  int *pnRemainingDataSize = NULL );
 
     CPLErr      SetInstValue( const char * pszField, int nIndexValue,
-                     GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
-                     char chReqType, void *pValue );
+                              GByte *pabyData, GUInt32 nDataOffset,
+                              int nDataSize,
+                              char chReqType, void *pValue );
 
-    void	DumpInstValue( FILE *fpOut,
-                     GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
-                     const char *pszPrefix = NULL );
+    void        DumpInstValue( FILE *fpOut, GByte *pabyData,
+                               GUInt32 nDataOffset, int nDataSize,
+                               const char *pszPrefix = NULL );
 
-    int		GetInstBytes( GByte *, int );
-    int		GetInstCount( GByte * pabyData, int nDataSize );
+    int         GetInstBytes( GByte *, int );
+    int         GetInstCount( GByte * pabyData, int nDataSize );
 };
 
-
 /************************************************************************/
 /*                               HFAType                                */
 /*                                                                      */
@@ -379,37 +390,38 @@ class HFAField
 
 class HFAType
 {
-    int     bInCompleteDefn;
+    bool bInCompleteDefn;
 
   public:
-    int		nBytes;
+    int         nBytes;
 
-    int		nFields;
-    HFAField	**papoFields;
+    int         nFields;
+    HFAField    **papoFields;
 
-    char	*pszTypeName;
+    char        *pszTypeName;
 
-    		HFAType();
+                HFAType();
                 ~HFAType();
 
     const char *Initialize( const char * );
 
-    void	CompleteDefn( HFADictionary * );
-
-    void	Dump( FILE * );
-
-    int		GetInstBytes( GByte *, int );
-    int         GetInstCount( const char *pszField,
-                          GByte *pabyData, GUInt32 nDataOffset, int nDataSize);
-    int         ExtractInstValue( const char * pszField,
-                                  GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
-                               char chReqType, void *pReqReturn, int *pnRemainingDataSize );
-    CPLErr      SetInstValue( const char * pszField,
-                           GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
-                           char chReqType, void * pValue );
-    void	DumpInstValue( FILE *fpOut,
-                           GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
-                           const char *pszPrefix = NULL );
+    void        CompleteDefn( HFADictionary * );
+
+    void        Dump( FILE * );
+
+    int         GetInstBytes( GByte *, int );
+    int         GetInstCount( const char *pszField, GByte *pabyData,
+                              GUInt32 nDataOffset, int nDataSize );
+    bool        ExtractInstValue( const char * pszField,
+                                  GByte *pabyData, GUInt32 nDataOffset,
+                                  int nDataSize, char chReqType,
+                                  void *pReqReturn, int *pnRemainingDataSize );
+    CPLErr      SetInstValue( const char * pszField, GByte *pabyData,
+                              GUInt32 nDataOffset, int nDataSize,
+                              char chReqType, void * pValue );
+    void        DumpInstValue( FILE *fpOut, GByte *pabyData,
+                               GUInt32 nDataOffset, int nDataSize,
+                               const char *pszPrefix = NULL );
 };
 
 /************************************************************************/
@@ -419,22 +431,25 @@ class HFAType
 class HFADictionary
 {
   public:
-    int		nTypes;
-    int         nTypesMax;
-    HFAType	**papoTypes;
-
-    CPLString   osDictionaryText;
-    int         bDictionaryTextDirty;
-
-                HFADictionary( const char *pszDict );
+    explicit     HFADictionary( const char *pszDict );
                 ~HFADictionary();
 
-    HFAType	*FindType( const char * );
+    HFAType     *FindType( const char * );
     void        AddType( HFAType * );
 
-    static int	GetItemSize( char );
+    static int  GetItemSize( char );
+
+    void        Dump( FILE * );
 
-    void	Dump( FILE * );
+  private:
+    int         nTypes;
+    int         nTypesMax;
+    HFAType     **papoTypes;
+
+  public:
+    // TODO(schwehr): Make these members private.
+    CPLString   osDictionaryText;
+    bool        bDictionaryTextDirty;
 };
 
 /************************************************************************/
@@ -453,20 +468,20 @@ public:
   // This is the method that does the work.
   bool compressBlock();
 
-  // static method to allow us to query whether HFA type supported
+  // Static method to allow us to query whether HFA type supported.
   static bool QueryDataTypeSupported( EPTType eHFADataType );
 
   // Get methods - only valid after compressBlock has been called.
-  GByte*  getCounts()     { return m_pCounts; };
-  GUInt32 getCountSize()  { return m_nSizeCounts; };
-  GByte*  getValues()     { return m_pValues; };
-  GUInt32 getValueSize()  { return m_nSizeValues; };
-  GUInt32 getMin()        { return m_nMin; };
-  GUInt32 getNumRuns()    { return m_nNumRuns; };
-  GByte   getNumBits()    { return m_nNumBits; };
+  GByte*  getCounts() const { return m_pCounts; };
+  GUInt32 getCountSize() const { return m_nSizeCounts; };
+  GByte*  getValues() const { return m_pValues; };
+  GUInt32 getValueSize() const { return m_nSizeValues; };
+  GUInt32 getMin() const { return m_nMin; };
+  GUInt32 getNumRuns() const { return m_nNumRuns; };
+  GByte   getNumBits() const { return m_nNumBits; };
 
 private:
-  void makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCount );
+  static void makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCount );
   GUInt32 findMin( GByte *pNumBits );
   GUInt32 valueAsUInt32( GUInt32 index );
   void encodeValue( GUInt32 val, GUInt32 repeat );
@@ -475,7 +490,8 @@ private:
   GUInt32 m_nBlockSize;
   GUInt32 m_nBlockCount;
   EPTType m_eDataType;
-  int m_nDataTypeNumBits; // the number of bits the datatype we are trying to compress takes
+  // The number of bits the datatype we are trying to compress takes.
+  int m_nDataTypeNumBits;
 
   GByte   *m_pCounts;
   GByte   *m_pCurrCount;
@@ -487,8 +503,8 @@ private:
 
   GUInt32  m_nMin;
   GUInt32  m_nNumRuns;
-  GByte    m_nNumBits; // the number of bits needed to compress the range of values in the block
-
+  // The number of bits needed to compress the range of values in the block.
+  GByte    m_nNumBits;
 };
 
 #endif /* ndef HFA_P_H_INCLUDED */
diff --git a/frmts/hfa/hfaband.cpp b/frmts/hfa/hfaband.cpp
index 9d8eff0..791f99e 100644
--- a/frmts/hfa/hfaband.cpp
+++ b/frmts/hfa/hfaband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfaband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFABand, for accessing one Eimg_Layer.
@@ -28,80 +27,106 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "hfa_p.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "hfa.h"
 #include "gdal_priv.h"
 
-/* include the compression code */
-
-CPL_CVSID("$Id: hfaband.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: hfaband.cpp 37879 2017-04-01 03:19:26Z goatbar $");
 
 /************************************************************************/
 /*                              HFABand()                               */
 /************************************************************************/
 
 HFABand::HFABand( HFAInfo_t * psInfoIn, HFAEntry * poNodeIn ) :
+    nBlocks(0),
     panBlockStart(NULL),
     panBlockSize(NULL),
     panBlockFlag(NULL),
+    nBlockStart(0),
+    nBlockSize(0),
+    nLayerStackCount(0),
+    nLayerStackIndex(0),
     nPCTColors(-1),
     padfPCTBins(NULL),
     psInfo(psInfoIn),
     fpExternal(NULL),
+    eDataType(static_cast<EPTType>(poNodeIn->GetIntField("pixelType"))),
     poNode(poNodeIn),
-    bNoDataSet(FALSE),
+    nBlockXSize(poNodeIn->GetIntField("blockWidth")),
+    nBlockYSize(poNodeIn->GetIntField("blockHeight")),
+    nWidth(poNodeIn->GetIntField("width")),
+    nHeight(poNodeIn->GetIntField("height")),
+    nBlocksPerRow(0),
+    nBlocksPerColumn(0),
+    bNoDataSet(false),
     dfNoData(0.0),
-    bOverviewsPending(TRUE),
+    bOverviewsPending(true),
     nOverviews(0),
     papoOverviews(NULL)
 {
-    nBlockXSize = poNodeIn->GetIntField( "blockWidth" );
-    nBlockYSize = poNodeIn->GetIntField( "blockHeight" );
-    int nDataType = poNodeIn->GetIntField( "pixelType" );
+    const int nDataType = poNodeIn->GetIntField("pixelType");
 
-    nWidth = poNodeIn->GetIntField( "width" );
-    nHeight = poNodeIn->GetIntField( "height" );
+    apadfPCT[0] = NULL;
+    apadfPCT[1] = NULL;
+    apadfPCT[2] = NULL;
+    apadfPCT[3] = NULL;
 
-    apadfPCT[0] = apadfPCT[1] = apadfPCT[2] = apadfPCT[3] = NULL;
-
-    if (nWidth <= 0 || nHeight <= 0 || nBlockXSize <= 0 || nBlockYSize <= 0)
+    if( nWidth <= 0 || nHeight <= 0 || nBlockXSize <= 0 || nBlockYSize <= 0 )
     {
-        nWidth = nHeight = 0;
+        nWidth = 0;
+        nHeight = 0;
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "HFABand::HFABand : (nWidth <= 0 || nHeight <= 0 || nBlockXSize <= 0 || nBlockYSize <= 0)");
+                 "HFABand::HFABand : (nWidth <= 0 || nHeight <= 0 || "
+                 "nBlockXSize <= 0 || nBlockYSize <= 0)");
         return;
     }
-    if (nDataType < EPT_MIN || nDataType > EPT_MAX)
+    if( nDataType < EPT_MIN || nDataType > EPT_MAX )
     {
-        nWidth = nHeight = 0;
+        nWidth = 0;
+        nHeight = 0;
         CPLError(CE_Failure, CPLE_AppDefined,
                  "HFABand::HFABand : nDataType=%d unhandled", nDataType);
         return;
     }
-    eDataType = static_cast<EPTType>(nDataType);
 
+    // TODO(schwehr): Move to initializer list.
     nBlocksPerRow = DIV_ROUND_UP(nWidth, nBlockXSize);
     nBlocksPerColumn = DIV_ROUND_UP(nHeight, nBlockYSize);
 
     if( nBlocksPerRow > INT_MAX / nBlocksPerColumn )
     {
-        nWidth = nHeight = 0;
+        nWidth = 0;
+        nHeight = 0;
         CPLError(CE_Failure, CPLE_AppDefined,
                  "HFABand::HFABand : too big dimensions / block size");
         return;
     }
     nBlocks = nBlocksPerRow * nBlocksPerColumn;
 
-/* -------------------------------------------------------------------- */
-/*      Check for nodata.  This is really an RDO (ESRI Raster Data      */
-/*      Objects?), not used by Imagine itself.                          */
-/* -------------------------------------------------------------------- */
-    HFAEntry	*poNDNode = poNode->GetNamedChild("Eimg_NonInitializedValue");
+    // Check for nodata.  This is really an RDO (ESRI Raster Data Objects?),
+    // not used by Imagine itself.
+    HFAEntry *poNDNode = poNode->GetNamedChild("Eimg_NonInitializedValue");
 
     if( poNDNode != NULL )
     {
-        bNoDataSet = TRUE;
-        dfNoData = poNDNode->GetDoubleField( "valueBD" );
+        bNoDataSet = true;
+        dfNoData = poNDNode->GetDoubleField("valueBD");
     }
 }
 
@@ -116,20 +141,20 @@ HFABand::~HFABand()
         delete papoOverviews[iOverview];
 
     if( nOverviews > 0 )
-        CPLFree( papoOverviews );
+        CPLFree(papoOverviews);
 
-    CPLFree( panBlockStart );
-    CPLFree( panBlockSize );
-    CPLFree( panBlockFlag );
+    CPLFree(panBlockStart);
+    CPLFree(panBlockSize);
+    CPLFree(panBlockFlag);
 
-    CPLFree( apadfPCT[0] );
-    CPLFree( apadfPCT[1] );
-    CPLFree( apadfPCT[2] );
-    CPLFree( apadfPCT[3] );
-    CPLFree( padfPCTBins );
+    CPLFree(apadfPCT[0]);
+    CPLFree(apadfPCT[1]);
+    CPLFree(apadfPCT[2]);
+    CPLFree(apadfPCT[3]);
+    CPLFree(padfPCTBins);
 
     if( fpExternal != NULL )
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fpExternal ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpExternal));
 }
 
 /************************************************************************/
@@ -142,38 +167,36 @@ CPLErr HFABand::LoadOverviews()
     if( !bOverviewsPending )
         return CE_None;
 
-    bOverviewsPending = FALSE;
+    bOverviewsPending = false;
 
-/* -------------------------------------------------------------------- */
-/*      Does this band have overviews?  Try to find them.               */
-/* -------------------------------------------------------------------- */
-    HFAEntry	*poRRDNames = poNode->GetNamedChild( "RRDNamesList" );
+    // Does this band have overviews?  Try to find them.
+    HFAEntry *poRRDNames = poNode->GetNamedChild("RRDNamesList");
 
     if( poRRDNames != NULL )
     {
         for( int iName = 0; true; iName++ )
         {
-            char  szField[128];
-            snprintf( szField, sizeof(szField), "nameList[%d].string", iName );
+            char szField[128] = {};
+            snprintf(szField, sizeof(szField), "nameList[%d].string", iName);
 
-            CPLErr eErr;
-            const char *pszName = poRRDNames->GetStringField( szField, &eErr );
+            CPLErr eErr = CE_None;
+            const char *pszName = poRRDNames->GetStringField(szField, &eErr);
             if( pszName == NULL || eErr != CE_None )
                 break;
 
             char *pszFilename = CPLStrdup(pszName);
-            char *pszEnd = strstr(pszFilename,"(:");
+            char *pszEnd = strstr(pszFilename, "(:");
             if( pszEnd == NULL )
             {
-                CPLFree( pszFilename );
+                CPLFree(pszFilename);
                 continue;
             }
 
             pszEnd[0] = '\0';
 
             char *pszJustFilename = CPLStrdup(CPLGetFilename(pszFilename));
-            HFAInfo_t *psHFA = HFAGetDependent( psInfo, pszJustFilename );
-            CPLFree( pszJustFilename );
+            HFAInfo_t *psHFA = HFAGetDependent(psInfo, pszJustFilename);
+            CPLFree(pszJustFilename);
 
             // Try finding the dependent file as this file with the
             // extension .rrd.  This is intended to address problems
@@ -185,16 +208,17 @@ CPLErr HFABand::LoadOverviews()
 
                 pszJustFilename =
                     CPLStrdup(CPLFormFilename(NULL, pszBasename, "rrd"));
-                CPLDebug( "HFA", "Failed to find overview file with expected name,\ntry %s instead.",
-                          pszJustFilename );
-                psHFA = HFAGetDependent( psInfo, pszJustFilename );
-                CPLFree( pszJustFilename );
-                CPLFree( pszBasename );
+                CPLDebug("HFA", "Failed to find overview file with "
+                         "expected name, try %s instead.",
+                         pszJustFilename);
+                psHFA = HFAGetDependent(psInfo, pszJustFilename);
+                CPLFree(pszJustFilename);
+                CPLFree(pszBasename);
             }
 
             if( psHFA == NULL )
             {
-                CPLFree( pszFilename );
+                CPLFree(pszFilename);
                 continue;
             }
 
@@ -202,97 +226,96 @@ CPLErr HFABand::LoadOverviews()
             if( pszPath[strlen(pszPath)-1] == ')' )
                 pszPath[strlen(pszPath)-1] = '\0';
 
-            for( int i=0; pszPath[i] != '\0'; i++ )
+            for( int i = 0; pszPath[i] != '\0'; i++ )
             {
                 if( pszPath[i] == ':' )
                     pszPath[i] = '.';
             }
 
-            HFAEntry *poOvEntry = psHFA->poRoot->GetNamedChild( pszPath );
-            CPLFree( pszFilename );
+            HFAEntry *poOvEntry = psHFA->poRoot->GetNamedChild(pszPath);
+            CPLFree(pszFilename);
 
             if( poOvEntry == NULL )
                 continue;
 
-            /*
-             * We have an overview node.  Instanatiate a HFABand from it,
-             * and add to the list.
-             */
-            papoOverviews = (HFABand **)
-                CPLRealloc(papoOverviews, sizeof(void*) * ++nOverviews );
-            papoOverviews[nOverviews-1] = new HFABand( psHFA, poOvEntry );
-            if (papoOverviews[nOverviews-1]->nWidth == 0)
+            // We have an overview node.  Instantiate a HFABand from it, and
+            // add to the list.
+            papoOverviews = static_cast<HFABand **>(
+                CPLRealloc(papoOverviews, sizeof(void *) * ++nOverviews));
+            papoOverviews[nOverviews - 1] = new HFABand(psHFA, poOvEntry);
+            if( papoOverviews[nOverviews-1]->nWidth == 0 )
             {
-                nWidth = nHeight = 0;
-                delete papoOverviews[nOverviews-1];
-                papoOverviews[nOverviews-1] = NULL;
+                nWidth = 0;
+                nHeight = 0;
+                delete papoOverviews[nOverviews - 1];
+                papoOverviews[nOverviews - 1] = NULL;
                 return CE_None;
             }
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      If there are no overviews mentioned in this file, probe for     */
-/*      an .rrd file anyways.                                           */
-/* -------------------------------------------------------------------- */
+    // If there are no overviews mentioned in this file, probe for
+    // an .rrd file anyways.
     HFAEntry *poBandProxyNode = poNode;
     HFAInfo_t *psOvHFA = psInfo;
 
-    if( nOverviews == 0
-        && EQUAL(CPLGetExtension(psInfo->pszFilename),"aux") )
+    if( nOverviews == 0 &&
+        EQUAL(CPLGetExtension(psInfo->pszFilename), "aux") )
     {
-        CPLString osRRDFilename = CPLResetExtension( psInfo->pszFilename,"rrd");
-        CPLString osFullRRD = CPLFormFilename( psInfo->pszPath, osRRDFilename,
-                                               NULL );
+        const CPLString osRRDFilename =
+            CPLResetExtension(psInfo->pszFilename, "rrd");
+        const CPLString osFullRRD =
+            CPLFormFilename(psInfo->pszPath, osRRDFilename, NULL);
         VSIStatBufL sStatBuf;
 
-        if( VSIStatL( osFullRRD, &sStatBuf ) == 0 )
+        if( VSIStatL(osFullRRD, &sStatBuf) == 0 )
         {
-            psOvHFA = HFAGetDependent( psInfo, osRRDFilename );
+            psOvHFA = HFAGetDependent(psInfo, osRRDFilename);
             if( psOvHFA )
                 poBandProxyNode =
-                    psOvHFA->poRoot->GetNamedChild( poNode->GetName() );
+                    psOvHFA->poRoot->GetNamedChild(poNode->GetName());
             else
                 psOvHFA = psInfo;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      If there are no named overviews, try looking for unnamed        */
-/*      overviews within the same layer, as occurs in floodplain.img    */
-/*      for instance, or in the not-referenced rrd mentioned in #3463.  */
-/* -------------------------------------------------------------------- */
+    // If there are no named overviews, try looking for unnamed
+    // overviews within the same layer, as occurs in floodplain.img
+    // for instance, or in the not-referenced rrd mentioned in #3463.
     if( nOverviews == 0 && poBandProxyNode != NULL )
     {
         for( HFAEntry *poChild = poBandProxyNode->GetChild();
              poChild != NULL;
              poChild = poChild->GetNext() )
         {
-            if( EQUAL(poChild->GetType(),"Eimg_Layer_SubSample") )
+            if( EQUAL(poChild->GetType(), "Eimg_Layer_SubSample") )
             {
-                papoOverviews = (HFABand **)
-                    CPLRealloc(papoOverviews, sizeof(void*) * ++nOverviews );
-                papoOverviews[nOverviews-1] = new HFABand( psOvHFA, poChild );
-                if (papoOverviews[nOverviews-1]->nWidth == 0)
+                papoOverviews = static_cast<HFABand **>(
+                    CPLRealloc(papoOverviews, sizeof(void *) * ++nOverviews));
+                papoOverviews[nOverviews - 1] = new HFABand(psOvHFA, poChild);
+                if( papoOverviews[nOverviews - 1]->nWidth == 0 )
                 {
-                    nWidth = nHeight = 0;
-                    delete papoOverviews[nOverviews-1];
-                    papoOverviews[nOverviews-1] = NULL;
+                    nWidth = 0;
+                    nHeight = 0;
+                    delete papoOverviews[nOverviews - 1];
+                    papoOverviews[nOverviews - 1] = NULL;
                     return CE_None;
                 }
             }
         }
 
-        // bubble sort into biggest to smallest order.
+        // TODO(schwehr): Can this use std::sort?
+        // Bubble sort into biggest to smallest order.
         for( int i1 = 0; i1 < nOverviews; i1++ )
         {
             for( int i2 = 0; i2 < nOverviews-1; i2++ )
             {
                 if( papoOverviews[i2]->nWidth <
-                    papoOverviews[i2+1]->nWidth )
+                    papoOverviews[i2 + 1]->nWidth )
                 {
-                    HFABand *poTemp = papoOverviews[i2+1];
-                    papoOverviews[i2+1] = papoOverviews[i2];
+                    // TODO(schwehr): Use std::swap.
+                    HFABand *poTemp = papoOverviews[i2 + 1];
+                    papoOverviews[i2 + 1] = papoOverviews[i2];
                     papoOverviews[i2] = poTemp;
                 }
             }
@@ -305,29 +328,32 @@ CPLErr HFABand::LoadOverviews()
 /*                           LoadBlockInfo()                            */
 /************************************************************************/
 
-CPLErr	HFABand::LoadBlockInfo()
+CPLErr HFABand::LoadBlockInfo()
 
 {
     if( panBlockFlag != NULL )
-        return( CE_None );
+        return CE_None;
 
-    HFAEntry *poDMS = poNode->GetNamedChild( "RasterDMS" );
+    HFAEntry *poDMS = poNode->GetNamedChild("RasterDMS");
     if( poDMS == NULL )
     {
-        if( poNode->GetNamedChild( "ExternalRasterDMS" ) != NULL )
+        if( poNode->GetNamedChild("ExternalRasterDMS") != NULL )
             return LoadExternalBlockInfo();
 
-        CPLError( CE_Failure, CPLE_AppDefined,
-               "Can't find RasterDMS field in Eimg_Layer with block list.\n");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Can't find RasterDMS field in Eimg_Layer with block list.");
 
         return CE_Failure;
     }
 
-    panBlockStart = (vsi_l_offset *)VSI_MALLOC2_VERBOSE(sizeof(vsi_l_offset), nBlocks);
-    panBlockSize = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nBlocks);
-    panBlockFlag = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nBlocks);
+    panBlockStart = static_cast<vsi_l_offset *>(
+        VSI_MALLOC2_VERBOSE(sizeof(vsi_l_offset), nBlocks));
+    panBlockSize =
+        static_cast<int *>(VSI_MALLOC2_VERBOSE(sizeof(int), nBlocks));
+    panBlockFlag =
+        static_cast<int *>(VSI_MALLOC2_VERBOSE(sizeof(int), nBlocks));
 
-    if (panBlockStart == NULL || panBlockSize == NULL || panBlockFlag == NULL)
+    if( panBlockStart == NULL || panBlockSize == NULL || panBlockFlag == NULL )
     {
         CPLFree(panBlockStart);
         CPLFree(panBlockSize);
@@ -340,20 +366,20 @@ CPLErr	HFABand::LoadBlockInfo()
 
     for( int iBlock = 0; iBlock < nBlocks; iBlock++ )
     {
-        CPLErr  eErr = CE_None;
-        char	szVarName[64];
-        int	nLogvalid, nCompressType;
+        CPLErr eErr = CE_None;
 
-        snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].offset", iBlock );
-        panBlockStart[iBlock] = (GUInt32)poDMS->GetIntField( szVarName, &eErr);
+        char szVarName[64] = {};
+        snprintf(szVarName, sizeof(szVarName), "blockinfo[%d].offset", iBlock);
+        panBlockStart[iBlock] =
+            static_cast<GUInt32>(poDMS->GetIntField(szVarName, &eErr));
         if( eErr == CE_Failure )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot read %s", szVarName);
             return eErr;
         }
 
-        snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].size", iBlock );
-        panBlockSize[iBlock] = poDMS->GetIntField( szVarName, &eErr );
+        snprintf(szVarName, sizeof(szVarName), "blockinfo[%d].size", iBlock);
+        panBlockSize[iBlock] = poDMS->GetIntField(szVarName, &eErr);
         if( eErr == CE_Failure )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot read %s", szVarName);
@@ -365,16 +391,18 @@ CPLErr	HFABand::LoadBlockInfo()
             return CE_Failure;
         }
 
-        snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].logvalid", iBlock );
-        nLogvalid = poDMS->GetIntField( szVarName, &eErr );
+        snprintf(szVarName, sizeof(szVarName),
+                 "blockinfo[%d].logvalid", iBlock);
+        const int nLogvalid = poDMS->GetIntField(szVarName, &eErr);
         if( eErr == CE_Failure )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot read %s", szVarName);
             return eErr;
         }
 
-        snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].compressionType", iBlock );
-        nCompressType = poDMS->GetIntField( szVarName, &eErr );
+        snprintf(szVarName, sizeof(szVarName),
+                 "blockinfo[%d].compressionType", iBlock);
+        const int nCompressType = poDMS->GetIntField(szVarName, &eErr);
         if( eErr == CE_Failure )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot read %s", szVarName);
@@ -388,104 +416,94 @@ CPLErr	HFABand::LoadBlockInfo()
             panBlockFlag[iBlock] |= BFLG_COMPRESSED;
     }
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
 /*                       LoadExternalBlockInfo()                        */
 /************************************************************************/
 
-CPLErr	HFABand::LoadExternalBlockInfo()
+CPLErr HFABand::LoadExternalBlockInfo()
 
 {
     if( panBlockFlag != NULL )
-        return( CE_None );
-
-/* -------------------------------------------------------------------- */
-/*      Get the info structure.                                         */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poDMS = poNode->GetNamedChild( "ExternalRasterDMS" );
-    CPLAssert( poDMS != NULL );
-
-    nLayerStackCount = poDMS->GetIntField( "layerStackCount" );
-    nLayerStackIndex = poDMS->GetIntField( "layerStackIndex" );
-
-/* -------------------------------------------------------------------- */
-/*      Open raw data file.                                             */
-/* -------------------------------------------------------------------- */
-    const char *pszFullFilename = HFAGetIGEFilename( psInfo );
-    if (pszFullFilename == NULL)
+        return CE_None;
+
+    // Get the info structure.
+    HFAEntry *poDMS = poNode->GetNamedChild("ExternalRasterDMS");
+    CPLAssert(poDMS != NULL);
+
+    nLayerStackCount = poDMS->GetIntField("layerStackCount");
+    nLayerStackIndex = poDMS->GetIntField("layerStackIndex");
+
+    // Open raw data file.
+    const char *pszFullFilename = HFAGetIGEFilename(psInfo);
+    if( pszFullFilename == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Cannot find external data file name" );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Cannot find external data file name");
         return CE_Failure;
     }
 
     if( psInfo->eAccess == HFA_ReadOnly )
-	fpExternal = VSIFOpenL( pszFullFilename, "rb" );
+        fpExternal = VSIFOpenL(pszFullFilename, "rb");
     else
-	fpExternal = VSIFOpenL( pszFullFilename, "r+b" );
+        fpExternal = VSIFOpenL(pszFullFilename, "r+b");
     if( fpExternal == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unable to open external data file:\n%s\n",
-                  pszFullFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Unable to open external data file: %s", pszFullFilename);
         return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Verify header.                                                  */
-/* -------------------------------------------------------------------- */
-    char	szHeader[49];
+    // Verify header.
+    char szHeader[49] = {};
 
-    if( VSIFReadL( szHeader, 49, 1, fpExternal ) != 1 ||
-        !STARTS_WITH( szHeader, "ERDAS_IMG_EXTERNAL_RASTER") )
+    if( VSIFReadL(szHeader, sizeof(szHeader), 1, fpExternal) != 1 ||
+        !STARTS_WITH(szHeader, "ERDAS_IMG_EXTERNAL_RASTER") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Raw data file %s appears to be corrupt.\n",
-                  pszFullFilename );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Raw data file %s appears to be corrupt.",
+                 pszFullFilename);
         return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Allocate blockmap.                                              */
-/* -------------------------------------------------------------------- */
-    panBlockFlag = (int *) VSI_MALLOC2_VERBOSE(sizeof(int), nBlocks);
-    if (panBlockFlag == NULL)
+    // Allocate blockmap.
+    panBlockFlag =
+        static_cast<int *>(VSI_MALLOC2_VERBOSE(sizeof(int), nBlocks));
+    if( panBlockFlag == NULL )
     {
         return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Load the validity bitmap.                                       */
-/* -------------------------------------------------------------------- */
+    // Load the validity bitmap.
     const int nBytesPerRow = (nBlocksPerRow + 7) / 8;
-    unsigned char *pabyBlockMap = (unsigned char *)
-        VSI_MALLOC_VERBOSE(nBytesPerRow*nBlocksPerColumn+20);
-    if (pabyBlockMap == NULL)
+    unsigned char *pabyBlockMap = static_cast<unsigned char *>(
+        VSI_MALLOC_VERBOSE(nBytesPerRow * nBlocksPerColumn + 20));
+    if( pabyBlockMap == NULL )
     {
         return CE_Failure;
     }
 
-    if( VSIFSeekL( fpExternal,
-               poDMS->GetBigIntField( "layerStackValidFlagsOffset" ),
-               SEEK_SET ) < 0 ||
-        VSIFReadL( pabyBlockMap, nBytesPerRow * nBlocksPerColumn + 20, 1,
-                   fpExternal ) != 1 )
+    if( VSIFSeekL(fpExternal,
+                  poDMS->GetBigIntField("layerStackValidFlagsOffset"),
+                  SEEK_SET) < 0 ||
+        VSIFReadL(pabyBlockMap, nBytesPerRow * nBlocksPerColumn + 20, 1,
+                  fpExternal) != 1 )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read block validity map." );
+        CPLError(CE_Failure, CPLE_FileIO, "Failed to read block validity map.");
         return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Establish block information.  Block position is computed        */
-/*      from data base address.  Blocks are never compressed.           */
-/*      Validity is determined from the validity bitmap.                */
-/* -------------------------------------------------------------------- */
-    nBlockStart = poDMS->GetBigIntField( "layerStackDataOffset" );
-    nBlockSize = (nBlockXSize*static_cast<vsi_l_offset>(nBlockYSize)
-                  *HFAGetDataTypeBits(eDataType)+7) / 8;
+    // Establish block information.  Block position is computed
+    // from data base address.  Blocks are never compressed.
+    // Validity is determined from the validity bitmap.
+
+    nBlockStart = poDMS->GetBigIntField("layerStackDataOffset");
+    nBlockSize = (nBlockXSize * static_cast<vsi_l_offset>(nBlockYSize) *
+                      HFAGetDataTypeBits(eDataType) +
+                  7) /
+                 8;
 
     for( int iBlock = 0; iBlock < nBlocks; iBlock++ )
     {
@@ -493,15 +511,15 @@ CPLErr	HFABand::LoadExternalBlockInfo()
         const int nRow = iBlock / nBlocksPerRow;
         const int nBit = nRow * nBytesPerRow * 8 + nColumn + 20 * 8;
 
-        if( (pabyBlockMap[nBit>>3] >> (nBit&7)) & 0x1 )
+        if( (pabyBlockMap[nBit >> 3] >> (nBit & 7)) & 0x1 )
             panBlockFlag[iBlock] = BFLG_VALID;
         else
             panBlockFlag[iBlock] = 0;
     }
 
-    CPLFree( pabyBlockMap );
+    CPLFree(pabyBlockMap);
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -510,83 +528,88 @@ CPLErr	HFABand::LoadExternalBlockInfo()
 /*      Uncompress ESRI Grid compression format block.                  */
 /************************************************************************/
 
+// TODO(schwehr): Get rid of this macro without a goto.
 #define CHECK_ENOUGH_BYTES(n) \
-    if (nSrcBytes < (n)) goto not_enough_bytes;
+    if( nSrcBytes < (n) ) \
+    { \
+        CPLError(CE_Failure, CPLE_AppDefined, \
+                 "Not enough bytes in compressed block"); \
+        return CE_Failure; \
+    }
 
 static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
                                GByte *pabyDest, int nMaxPixels,
                                EPTType eDataType )
 
 {
-    GUInt32  nDataMin;
-    int      nNumBits, nPixelsOutput=0;
-    GInt32   nNumRuns, nDataOffset;
-    GByte *pabyCounter, *pabyValues;
-    int   nValueBitOffset;
-    int nCounterOffset;
-
     CHECK_ENOUGH_BYTES(13);
 
-    memcpy( &nDataMin, pabyCData, 4 );
-    nDataMin = CPL_LSBWORD32( nDataMin );
+    GUInt32 nTmp = 0;
+
+    memcpy(&nTmp, pabyCData, 4);
+    const GUInt32 nDataMin = CPL_LSBWORD32(nTmp);
+
+    memcpy(&nTmp, pabyCData + 4, 4);
+    const GInt32 nNumRuns = CPL_LSBWORD32(nTmp);
 
-    memcpy( &nNumRuns, pabyCData+4, 4 );
-    nNumRuns = CPL_LSBWORD32( nNumRuns );
+    memcpy(&nTmp, pabyCData + 8, 4);
+    const GInt32 nDataOffset = CPL_LSBWORD32(nTmp);
 
-    memcpy( &nDataOffset, pabyCData+8, 4 );
-    nDataOffset = CPL_LSBWORD32( nDataOffset );
+    const int nNumBits = pabyCData[12];
 
-    nNumBits = pabyCData[12];
+    // If this is not run length encoded, but just reduced
+    // precision, handle it now.
+
+    int nPixelsOutput = 0;
+    GByte *pabyValues = NULL;
+    int nValueBitOffset = 0;
 
-/* ==================================================================== */
-/*      If this is not run length encoded, but just reduced             */
-/*      precision, handle it now.                                       */
-/* ==================================================================== */
     if( nNumRuns == -1 )
     {
         pabyValues = pabyCData + 13;
         nValueBitOffset = 0;
 
-        if (nNumBits > INT_MAX / nMaxPixels ||
+        if( nNumBits > INT_MAX / nMaxPixels ||
             nNumBits * nMaxPixels > INT_MAX - 7 ||
-            (nNumBits * nMaxPixels + 7)/8 > INT_MAX - 13)
+            (nNumBits * nMaxPixels + 7) / 8 > INT_MAX - 13 )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Integer overflow : nNumBits * nMaxPixels + 7");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Integer overflow : nNumBits * nMaxPixels + 7");
             return CE_Failure;
         }
-        CHECK_ENOUGH_BYTES(13 + (nNumBits * nMaxPixels + 7)/8);
+        CHECK_ENOUGH_BYTES(13 + (nNumBits * nMaxPixels + 7) / 8);
 
-/* -------------------------------------------------------------------- */
-/*      Loop over block pixels.                                         */
-/* -------------------------------------------------------------------- */
+        // Loop over block pixels.
         for( nPixelsOutput = 0; nPixelsOutput < nMaxPixels; nPixelsOutput++ )
         {
-            int	nDataValue, nRawValue;
+            // Extract the data value in a way that depends on the number
+            // of bits in it.
+
+            int nRawValue = 0;
 
-/* -------------------------------------------------------------------- */
-/*      Extract the data value in a way that depends on the number      */
-/*      of bits in it.                                                  */
-/* -------------------------------------------------------------------- */
             if( nNumBits == 0 )
             {
-                nRawValue = 0;
+                // nRawValue = 0;
             }
             else if( nNumBits == 1 )
             {
                 nRawValue =
-                    (pabyValues[nValueBitOffset>>3] >> (nValueBitOffset&7)) & 0x1;
+                    (pabyValues[nValueBitOffset >> 3] >> (nValueBitOffset & 7))
+                    & 0x1;
                 nValueBitOffset++;
             }
             else if( nNumBits == 2 )
             {
                 nRawValue =
-                    (pabyValues[nValueBitOffset>>3] >> (nValueBitOffset&7)) & 0x3;
+                    (pabyValues[nValueBitOffset >> 3] >> (nValueBitOffset & 7))
+                    & 0x3;
                 nValueBitOffset += 2;
             }
             else if( nNumBits == 4 )
             {
                 nRawValue =
-                    (pabyValues[nValueBitOffset>>3] >> (nValueBitOffset&7)) & 0xf;
+                    (pabyValues[nValueBitOffset >> 3] >> (nValueBitOffset & 7))
+                    & 0xf;
                 nValueBitOffset += 4;
             }
             else if( nNumBits == 8 )
@@ -609,81 +632,87 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
             else
             {
                 CPLError(CE_Failure, CPLE_NotSupported,
-                         "Unsupported nNumBits value : %d", nNumBits);
+                         "Unsupported nNumBits value: %d", nNumBits);
                 return CE_Failure;
             }
 
-/* -------------------------------------------------------------------- */
-/*      Offset by the minimum value.                                    */
-/* -------------------------------------------------------------------- */
-            nDataValue = nRawValue + nDataMin;
+            // Offset by the minimum value.
+            const int nDataValue = nRawValue + nDataMin;
 
-/* -------------------------------------------------------------------- */
-/*      Now apply to the output buffer in a type specific way.          */
-/* -------------------------------------------------------------------- */
+            // Now apply to the output buffer in a type specific way.
             if( eDataType == EPT_u8 )
             {
-                ((GByte *) pabyDest)[nPixelsOutput] = (GByte) nDataValue;
+                ((GByte *)pabyDest)[nPixelsOutput] =
+                    static_cast<GByte>(nDataValue);
             }
             else if( eDataType == EPT_u1 )
             {
                 if( nDataValue == 1 )
-                    pabyDest[nPixelsOutput>>3] |= (1 << (nPixelsOutput & 0x7));
+                    pabyDest[nPixelsOutput >> 3] |=
+                        (1 << (nPixelsOutput & 0x7));
                 else
-                    pabyDest[nPixelsOutput>>3] &= ~(1<<(nPixelsOutput & 0x7));
+                    pabyDest[nPixelsOutput >> 3] &=
+                        ~(1 << (nPixelsOutput & 0x7));
             }
             else if( eDataType == EPT_u2 )
             {
                 if( (nPixelsOutput & 0x3) == 0 )
-                    pabyDest[nPixelsOutput>>2] = (GByte) nDataValue;
+                    pabyDest[nPixelsOutput >> 2] =
+                        static_cast<GByte>(nDataValue);
                 else if( (nPixelsOutput & 0x3) == 1 )
-                    pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<2);
+                    pabyDest[nPixelsOutput >> 2] |=
+                        static_cast<GByte>(nDataValue << 2);
                 else if( (nPixelsOutput & 0x3) == 2 )
-                    pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<4);
+                    pabyDest[nPixelsOutput >> 2] |=
+                        static_cast<GByte>(nDataValue << 4);
                 else
-                    pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<6);
+                    pabyDest[nPixelsOutput >> 2] |=
+                        static_cast<GByte>(nDataValue << 6);
             }
             else if( eDataType == EPT_u4 )
             {
-                if( (nPixelsOutput & 0x1) == 0 )
-                    pabyDest[nPixelsOutput>>1] = (GByte) nDataValue;
+                if( (nPixelsOutput & 0x1) == 0)
+                    pabyDest[nPixelsOutput >> 1] =
+                        static_cast<GByte>(nDataValue);
                 else
-                    pabyDest[nPixelsOutput>>1] |= (GByte) (nDataValue<<4);
+                    pabyDest[nPixelsOutput >> 1] |=
+                        static_cast<GByte>(nDataValue << 4);
             }
             else if( eDataType == EPT_s8 )
             {
-                ((GByte *) pabyDest)[nPixelsOutput] = (GByte) nDataValue;
+                ((GByte *)pabyDest)[nPixelsOutput] =
+                    static_cast<GByte>(nDataValue);
             }
             else if( eDataType == EPT_u16 )
             {
-                ((GUInt16 *) pabyDest)[nPixelsOutput] = (GUInt16) nDataValue;
+                ((GUInt16 *)pabyDest)[nPixelsOutput] =
+                    static_cast<GUInt16>(nDataValue);
             }
             else if( eDataType == EPT_s16 )
             {
-                ((GInt16 *) pabyDest)[nPixelsOutput] = (GInt16) nDataValue;
+                ((GInt16 *)pabyDest)[nPixelsOutput] =
+                    static_cast<GInt16>(nDataValue);
             }
             else if( eDataType == EPT_s32 )
             {
-                ((GInt32 *) pabyDest)[nPixelsOutput] = nDataValue;
+                ((GInt32 *)pabyDest)[nPixelsOutput] = nDataValue;
             }
             else if( eDataType == EPT_u32 )
             {
-                ((GUInt32 *) pabyDest)[nPixelsOutput] = nDataValue;
+                ((GUInt32 *)pabyDest)[nPixelsOutput] = nDataValue;
             }
             else if( eDataType == EPT_f32 )
             {
-/* -------------------------------------------------------------------- */
-/*      Note, floating point values are handled as if they were signed  */
-/*      32-bit integers (bug #1000).                                    */
-/* -------------------------------------------------------------------- */
-                memcpy(&(((float *) pabyDest)[nPixelsOutput]),
-                       &nDataValue,
+                // Note, floating point values are handled as if they were
+                // signed 32-bit integers (bug #1000).
+                memcpy(&(((float *)pabyDest)[nPixelsOutput]), &nDataValue,
                        sizeof(float));
             }
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to uncompress an unsupported pixel data type.");
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Attempt to uncompress an unsupported pixel data type.");
                 return CE_Failure;
             }
         }
@@ -691,50 +720,43 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
         return CE_None;
     }
 
-/* ==================================================================== */
-/*      Establish data pointers for runs.                               */
-/* ==================================================================== */
-    if (nNumRuns < 0 || nDataOffset < 0)
+    // Establish data pointers for runs.
+    if( nNumRuns < 0 || nDataOffset < 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "nNumRuns=%d, nDataOffset=%d",
                  nNumRuns, nDataOffset);
         return CE_Failure;
     }
 
-    if (nNumRuns != 0 &&
+    if( nNumRuns != 0 &&
         (nNumBits > INT_MAX / nNumRuns ||
          nNumBits * nNumRuns > INT_MAX - 7 ||
-         (nNumBits * nNumRuns + 7)/8 > INT_MAX - nDataOffset) )
+         (nNumBits * nNumRuns + 7) / 8 > INT_MAX - nDataOffset) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Integer overflow : nDataOffset + (nNumBits * nNumRuns + 7)/8");
+                 "Integer overflow: nDataOffset + (nNumBits * nNumRuns + 7)/8");
         return CE_Failure;
     }
-    CHECK_ENOUGH_BYTES(nDataOffset + (nNumBits * nNumRuns + 7)/8);
+    CHECK_ENOUGH_BYTES(nDataOffset + (nNumBits * nNumRuns + 7) / 8);
 
-    pabyCounter = pabyCData + 13;
-    nCounterOffset = 13;
+    GByte *pabyCounter = pabyCData + 13;
+    int nCounterOffset = 13;
     pabyValues = pabyCData + nDataOffset;
     nValueBitOffset = 0;
 
-/* -------------------------------------------------------------------- */
-/*      Loop over runs.                                                 */
-/* -------------------------------------------------------------------- */
+    // Loop over runs.
     for( int iRun = 0; iRun < nNumRuns; iRun++ )
     {
-        int	nRepeatCount = 0;
-        int	nDataValue;
+        int nRepeatCount = 0;
 
-/* -------------------------------------------------------------------- */
-/*      Get the repeat count.  This can be stored as one, two, three    */
-/*      or four bytes depending on the low order two bits of the        */
-/*      first byte.                                                     */
-/* -------------------------------------------------------------------- */
-        CHECK_ENOUGH_BYTES(nCounterOffset+1);
-        if( ((*pabyCounter) & 0xc0) == 0x00 )
+        // Get the repeat count.  This can be stored as one, two, three
+        // or four bytes depending on the low order two bits of the
+        // first byte.
+        CHECK_ENOUGH_BYTES(nCounterOffset + 1);
+        if( (*pabyCounter & 0xc0) == 0x00)
         {
             nRepeatCount = (*(pabyCounter++)) & 0x3f;
-            nCounterOffset ++;
+            nCounterOffset++;
         }
         else if( ((*pabyCounter) & 0xc0) == 0x40 )
         {
@@ -761,13 +783,13 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
             nCounterOffset += 4;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Extract the data value in a way that depends on the number      */
-/*      of bits in it.                                                  */
-/* -------------------------------------------------------------------- */
+        // Extract the data value in a way that depends on the number
+        // of bits in it.
+        int nDataValue = 0;
+
         if( nNumBits == 0 )
         {
-            nDataValue = 0;
+            // nDataValue = 0;
         }
         else if( nNumBits == 1 )
         {
@@ -811,18 +833,14 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
             return CE_Failure;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Offset by the minimum value.                                    */
-/* -------------------------------------------------------------------- */
+        // Offset by the minimum value.
         nDataValue += nDataMin;
 
-/* -------------------------------------------------------------------- */
-/*      Now apply to the output buffer in a type specific way.          */
-/* -------------------------------------------------------------------- */
+        // Now apply to the output buffer in a type specific way.
         if( nRepeatCount > INT_MAX - nPixelsOutput ||
             nPixelsOutput + nRepeatCount > nMaxPixels )
         {
-            CPLDebug("HFA", "Repeat count too big : %d", nRepeatCount);
+            CPLDebug("HFA", "Repeat count too big: %d", nRepeatCount);
             nRepeatCount = nMaxPixels - nPixelsOutput;
         }
 
@@ -830,65 +848,97 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
         {
             for( int i = 0; i < nRepeatCount; i++ )
             {
-                //CPLAssert( nDataValue < 256 );
-                ((GByte *) pabyDest)[nPixelsOutput++] = (GByte)nDataValue;
+#if DEBUG_VERBOSE
+                // TODO(schwehr): Do something smarter with out-of-range data.
+                // Bad data can trigger this assert.  r23498
+                CPLAssert(nDataValue < 256);
+#endif
+                ((GByte *)pabyDest)[nPixelsOutput++] =
+                    static_cast<GByte>(nDataValue);
             }
         }
         else if( eDataType == EPT_u16 )
         {
             for( int i = 0; i < nRepeatCount; i++ )
             {
-                ((GUInt16 *) pabyDest)[nPixelsOutput++] = (GUInt16)nDataValue;
+#if DEBUG_VERBOSE
+                CPLAssert(nDataValue >= 0);
+                CPLAssert(nDataValue < 65536);
+#endif
+                ((GUInt16 *)pabyDest)[nPixelsOutput++] =
+                    static_cast<GUInt16>(nDataValue);
             }
         }
         else if( eDataType == EPT_s8 )
         {
             for( int i = 0; i < nRepeatCount; i++ )
             {
-                //CPLAssert( nDataValue < 256 );
-                ((GByte *) pabyDest)[nPixelsOutput++] = (GByte)nDataValue;
+#if DEBUG_VERBOSE
+                // TODO(schwehr): Do something smarter with out-of-range data.
+                // Bad data can trigger this assert.  r23498
+                CPLAssert(nDataValue >= -127);
+                CPLAssert(nDataValue < 128);
+#endif
+                ((GByte *)pabyDest)[nPixelsOutput++] =
+                    static_cast<GByte>(nDataValue);
             }
         }
         else if( eDataType == EPT_s16 )
         {
             for( int i = 0; i < nRepeatCount; i++ )
             {
-                ((GInt16 *) pabyDest)[nPixelsOutput++] = (GInt16)nDataValue;
+#if DEBUG_VERBOSE
+                // TODO(schwehr): Do something smarter with out-of-range data.
+                // Bad data can trigger this assert.  r23498
+                CPLAssert(nDataValue >= -32768);
+                CPLAssert(nDataValue < 32768);
+#endif
+                ((GInt16 *)pabyDest)[nPixelsOutput++] =
+                    static_cast<GInt16>(nDataValue);
             }
         }
         else if( eDataType == EPT_u32 )
         {
             for( int i = 0; i < nRepeatCount; i++ )
             {
-                ((GUInt32 *) pabyDest)[nPixelsOutput++] = (GUInt32)nDataValue;
+#if DEBUG_VERBOSE
+                // TODO(schwehr): Do something smarter with out-of-range data.
+                // Bad data can trigger this assert.  r23498
+                CPLAssert(nDataValue >= 0);
+#endif
+                ((GUInt32 *)pabyDest)[nPixelsOutput++] =
+                    static_cast<GUInt32>(nDataValue);
             }
         }
         else if( eDataType == EPT_s32 )
         {
             for( int i = 0; i < nRepeatCount; i++ )
             {
-                ((GInt32 *) pabyDest)[nPixelsOutput++] = (GInt32)nDataValue;
+                ((GInt32 *)pabyDest)[nPixelsOutput++] =
+                    static_cast<GInt32>(nDataValue);
             }
         }
         else if( eDataType == EPT_f32 )
         {
-            float fDataValue;
+            float fDataValue = 0.0f;
 
-            memcpy( &fDataValue, &nDataValue, 4);
+            memcpy(&fDataValue, &nDataValue, 4);
             for( int i = 0; i < nRepeatCount; i++ )
             {
-                ((float *) pabyDest)[nPixelsOutput++] = fDataValue;
+                ((float *)pabyDest)[nPixelsOutput++] = fDataValue;
             }
         }
         else if( eDataType == EPT_u1 )
         {
-            //CPLAssert( nDataValue == 0 || nDataValue == 1 );
-
+#ifdef DEBUG_VERBOSE
+            CPLAssert(nDataValue == 0 || nDataValue == 1);
+#endif
             if( nDataValue == 1 )
             {
                 for( int i = 0; i < nRepeatCount; i++ )
                 {
-                    pabyDest[nPixelsOutput>>3] |= (1 << (nPixelsOutput & 0x7));
+                    pabyDest[nPixelsOutput >> 3] |=
+                        (1 << (nPixelsOutput & 0x7));
                     nPixelsOutput++;
                 }
             }
@@ -896,56 +946,60 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
             {
                 for( int i = 0; i < nRepeatCount; i++ )
                 {
-                    pabyDest[nPixelsOutput>>3] &= ~(1<<(nPixelsOutput & 0x7));
+                    pabyDest[nPixelsOutput >> 3] &=
+                        ~(1 << (nPixelsOutput & 0x7));
                     nPixelsOutput++;
                 }
             }
         }
         else if( eDataType == EPT_u2 )
         {
-            //CPLAssert( nDataValue >= 0 && nDataValue < 4 );
-
+#ifdef DEBUG_VERBOSE
+            CPLAssert(nDataValue >= 0 && nDataValue < 4);
+#endif
             for( int i = 0; i < nRepeatCount; i++ )
             {
                 if( (nPixelsOutput & 0x3) == 0 )
-                    pabyDest[nPixelsOutput>>2] = (GByte) nDataValue;
+                    pabyDest[nPixelsOutput >> 2] =
+                        static_cast<GByte>(nDataValue);
                 else if( (nPixelsOutput & 0x3) == 1 )
-                    pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<2);
+                    pabyDest[nPixelsOutput >> 2] |=
+                        static_cast<GByte>(nDataValue << 2);
                 else if( (nPixelsOutput & 0x3) == 2 )
-                    pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<4);
+                    pabyDest[nPixelsOutput >> 2] |=
+                        static_cast<GByte>(nDataValue << 4);
                 else
-                    pabyDest[nPixelsOutput>>2] |= (GByte) (nDataValue<<6);
+                    pabyDest[nPixelsOutput >> 2] |=
+                        static_cast<GByte>(nDataValue << 6);
                 nPixelsOutput++;
             }
         }
         else if( eDataType == EPT_u4 )
         {
-            //CPLAssert( nDataValue >= 0 && nDataValue < 16 );
-
+#ifdef DEBUG_VERBOSE
+            CPLAssert(nDataValue >= 0 && nDataValue < 16);
+#endif
             for( int i = 0; i < nRepeatCount; i++ )
             {
                 if( (nPixelsOutput & 0x1) == 0 )
-                    pabyDest[nPixelsOutput>>1] = (GByte) nDataValue;
+                    pabyDest[nPixelsOutput >> 1] =
+                        static_cast<GByte>(nDataValue);
                 else
-                    pabyDest[nPixelsOutput>>1] |= (GByte) (nDataValue<<4);
+                    pabyDest[nPixelsOutput >> 1] |=
+                        static_cast<GByte>(nDataValue << 4);
 
                 nPixelsOutput++;
             }
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to uncompress an unsupported pixel data type.");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Attempt to uncompress an unsupported pixel data type.");
             return CE_Failure;
         }
     }
 
     return CE_None;
-
-  not_enough_bytes:
-
-    CPLError(CE_Failure, CPLE_AppDefined, "Not enough bytes in compressed block");
-    return CE_Failure;
 }
 
 /************************************************************************/
@@ -958,19 +1012,19 @@ static CPLErr UncompressBlock( GByte *pabyCData, int nSrcBytes,
 void HFABand::NullBlock( void *pData )
 
 {
-    int nChunkSize = MAX(1,HFAGetDataTypeBits(eDataType)/8);
+    const int nChunkSize = std::max(1, HFAGetDataTypeBits(eDataType) / 8);
     int nWords = nBlockXSize * nBlockYSize;
 
     if( !bNoDataSet )
     {
 #ifdef ESRI_BUILD
         // We want special defaulting for 1 bit data in ArcGIS.
-        if ( eDataType >= EPT_u2 )
-            memset( pData,   0, nChunkSize*nWords );
+        if( eDataType >= EPT_u2 )
+            memset(pData, 0, nChunkSize * nWords);
         else
-            memset( pData, 255, nChunkSize*nWords );
+            memset(pData, 255, nChunkSize * nWords);
 #else
-        memset( pData,   0, nChunkSize*nWords );
+        memset(pData, 0, nChunkSize * nWords);
 #endif
     }
     else
@@ -979,19 +1033,19 @@ void HFABand::NullBlock( void *pData )
 
         switch( eDataType )
         {
-          case EPT_u1:
-          {
-              nWords = (nWords + 7)/8;
+        case EPT_u1:
+        {
+              nWords = (nWords + 7) / 8;
               if( dfNoData != 0.0 )
                   ((unsigned char *) abyTmp)[0] = 0xff;
               else
                   ((unsigned char *) abyTmp)[0] = 0x00;
-          }
-          break;
+        }
+        break;
 
-          case EPT_u2:
-          {
-              nWords = (nWords + 3)/4;
+        case EPT_u2:
+        {
+              nWords = (nWords + 3) / 4;
               if( dfNoData == 0.0 )
                   ((unsigned char *) abyTmp)[0] = 0x00;
               else if( dfNoData == 1.0 )
@@ -1000,129 +1054,124 @@ void HFABand::NullBlock( void *pData )
                   ((unsigned char *) abyTmp)[0] = 0xaa;
               else
                   ((unsigned char *) abyTmp)[0] = 0xff;
-          }
-          break;
+        }
+        break;
 
-          case EPT_u4:
-          {
-              unsigned char byVal =
-                  (unsigned char) MAX(0,MIN(15,(int)dfNoData));
+        case EPT_u4:
+        {
+            const unsigned char byVal = static_cast<unsigned char>(
+                std::max(0, std::min(15, static_cast<int>(dfNoData))));
 
-              nWords = (nWords + 1)/2;
+            nWords = (nWords + 1) / 2;
 
-              ((unsigned char *) abyTmp)[0] = byVal + (byVal << 4);
-          }
-          break;
+            ((unsigned char *)abyTmp)[0] = byVal + (byVal << 4);
+        }
+        break;
 
-          case EPT_u8:
-            ((unsigned char *) abyTmp)[0] =
-                (unsigned char) MAX(0,MIN(255,(int)dfNoData));
+        case EPT_u8:
+            ((unsigned char *)abyTmp)[0] = static_cast<unsigned char>(
+                std::max(0, std::min(255, static_cast<int>(dfNoData))));
             break;
 
-          case EPT_s8:
-            ((signed char *) abyTmp)[0] =
-                (signed char) MAX(-128,MIN(127,(int)dfNoData));
+        case EPT_s8:
+            ((signed char *)abyTmp)[0] = static_cast<signed char>(
+                std::max(-128, std::min(127, static_cast<int>(dfNoData))));
             break;
 
-          case EPT_u16:
-          {
-            GUInt16 nTmp = (GUInt16) dfNoData;
+        case EPT_u16:
+        {
+            GUInt16 nTmp = static_cast<GUInt16>(dfNoData);
             memcpy(abyTmp, &nTmp, sizeof(nTmp));
             break;
-          }
+        }
 
-          case EPT_s16:
-          {
-            GInt16 nTmp = (GInt16) dfNoData;
+        case EPT_s16:
+        {
+            GInt16 nTmp = static_cast<GInt16>(dfNoData);
             memcpy(abyTmp, &nTmp, sizeof(nTmp));
             break;
-          }
+        }
 
-          case EPT_u32:
-          {
-            GUInt32 nTmp = (GUInt32) dfNoData;
+        case EPT_u32:
+        {
+            GUInt32 nTmp = static_cast<GUInt32>(dfNoData);
             memcpy(abyTmp, &nTmp, sizeof(nTmp));
             break;
-          }
+        }
 
-          case EPT_s32:
-          {
-            GInt32 nTmp = (GInt32) dfNoData;
+        case EPT_s32:
+        {
+            GInt32 nTmp = static_cast<GInt32>(dfNoData);
             memcpy(abyTmp, &nTmp, sizeof(nTmp));
             break;
-          }
+        }
 
-          case EPT_f32:
-          {
-            float fTmp = (float) dfNoData;
+        case EPT_f32:
+        {
+            float fTmp = static_cast<float>(dfNoData);
             memcpy(abyTmp, &fTmp, sizeof(fTmp));
             break;
-          }
+        }
 
-          case EPT_f64:
-          {
+        case EPT_f64:
+        {
             memcpy(abyTmp, &dfNoData, sizeof(dfNoData));
             break;
-          }
+        }
 
-          case EPT_c64:
-          {
-            float fTmp = (float) dfNoData;
+        case EPT_c64:
+        {
+            float fTmp = static_cast<float>(dfNoData);
             memcpy(abyTmp, &fTmp, sizeof(fTmp));
-            memset(abyTmp+4, 0, sizeof(float));
+            memset(abyTmp + 4, 0, sizeof(float));
             break;
-          }
+        }
 
-          case EPT_c128:
-          {
+        case EPT_c128:
+        {
             memcpy(abyTmp, &dfNoData, sizeof(dfNoData));
-            memset(abyTmp+8, 0, sizeof(double));
+            memset(abyTmp + 8, 0, sizeof(double));
             break;
-          }
+        }
         }
 
         for( int i = 0; i < nWords; i++ )
-            memcpy( ((GByte *) pData) + nChunkSize * i,
-                    abyTmp, nChunkSize );
+            memcpy(((GByte *)pData) + nChunkSize * i, abyTmp, nChunkSize);
     }
-
 }
 
 /************************************************************************/
 /*                           GetRasterBlock()                           */
 /************************************************************************/
 
-CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDataSize )
+CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock,
+                                void * pData, int nDataSize )
 
 {
     if( LoadBlockInfo() != CE_None )
         return CE_Failure;
 
-    int iBlock = nXBlock + nYBlock * nBlocksPerRow;
+    const int iBlock = nXBlock + nYBlock * nBlocksPerRow;
 
-/* -------------------------------------------------------------------- */
-/*      If the block isn't valid, we just return all zeros, and an	*/
-/*	indication of success.                        			*/
-/* -------------------------------------------------------------------- */
+    // If the block isn't valid, we just return all zeros, and an
+    // indication of success.
     if( (panBlockFlag[iBlock] & BFLG_VALID) == 0 )
     {
         NullBlock( pData );
-        return( CE_None );
+        return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Otherwise we really read the data.                              */
-/* -------------------------------------------------------------------- */
-    vsi_l_offset    nBlockOffset;
-    VSILFILE	*fpData;
+    // Otherwise we really read the data.
+    vsi_l_offset nBlockOffset = 0;
+    VSILFILE *fpData = NULL;
 
     // Calculate block offset in case we have spill file. Use predefined
     // block map otherwise.
-    if ( fpExternal )
+    if( fpExternal )
     {
         fpData = fpExternal;
-        nBlockOffset = nBlockStart + nBlockSize * iBlock * nLayerStackCount
-            + nLayerStackIndex * nBlockSize;
+        nBlockOffset = nBlockStart + nBlockSize * iBlock * nLayerStackCount +
+                       nLayerStackIndex * nBlockSize;
     }
     else
     {
@@ -1131,114 +1180,109 @@ CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDat
         nBlockSize = panBlockSize[iBlock];
     }
 
-    if( VSIFSeekL( fpData, nBlockOffset, SEEK_SET ) != 0 )
+    if( VSIFSeekL(fpData, nBlockOffset, SEEK_SET) != 0 )
     {
         // XXX: We will not report error here, because file just may be
-	// in update state and data for this block will be available later
-        if ( psInfo->eAccess == HFA_Update )
+        // in update state and data for this block will be available later.
+        if( psInfo->eAccess == HFA_Update )
         {
-            memset( pData, 0,
-                    HFAGetDataTypeBits(eDataType)*nBlockXSize*nBlockYSize/8 );
+            memset(pData, 0, HFAGetDataTypeBits(eDataType) * nBlockXSize *
+                                 nBlockYSize / 8);
             return CE_None;
         }
         else
         {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Seek to %x:%08x on %p failed\n%s",
-                      (int) (nBlockOffset >> 32),
-                      (int) (nBlockOffset & 0xffffffff),
-                      fpData, VSIStrerror(errno) );
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Seek to %x:%08x on %p failed\n%s",
+                     static_cast<int>(nBlockOffset >> 32),
+                     static_cast<int>(nBlockOffset & 0xffffffff),
+                     fpData, VSIStrerror(errno));
             return CE_Failure;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*	If the block is compressed, read into an intermediate buffer	*/
-/*	and convert.							*/
-/* -------------------------------------------------------------------- */
+    // If the block is compressed, read into an intermediate buffer
+    // and convert.
     if( panBlockFlag[iBlock] & BFLG_COMPRESSED )
     {
-        GByte *pabyCData = (GByte *) VSI_MALLOC_VERBOSE( (size_t) nBlockSize );
-        if (pabyCData == NULL)
+        GByte *pabyCData = static_cast<GByte *>(
+            VSI_MALLOC_VERBOSE(static_cast<size_t>(nBlockSize)));
+        if( pabyCData == NULL )
         {
             return CE_Failure;
         }
 
-        if( VSIFReadL( pabyCData, (size_t) nBlockSize, 1, fpData ) != 1 )
+        if( VSIFReadL(pabyCData, static_cast<size_t>(nBlockSize),
+                      1, fpData) != 1 )
         {
-            CPLFree( pabyCData );
+            CPLFree(pabyCData);
 
-	    // XXX: Suppose that file in update state
-            if ( psInfo->eAccess == HFA_Update )
+            // XXX: Suppose that file in update state
+            if( psInfo->eAccess == HFA_Update )
             {
-                memset( pData, 0,
-                    HFAGetDataTypeBits(eDataType)*nBlockXSize*nBlockYSize/8 );
+                memset(pData, 0, HFAGetDataTypeBits(eDataType) * nBlockXSize *
+                                     nBlockYSize / 8);
                 return CE_None;
             }
             else
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Read of %d bytes at %x:%08x on %p failed.\n%s",
-                          (int) nBlockSize,
-                          (int) (nBlockOffset >> 32),
-                          (int) (nBlockOffset & 0xffffffff),
-                          fpData, VSIStrerror(errno) );
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Read of %d bytes at %x:%08x on %p failed.\n%s",
+                         static_cast<int>(nBlockSize),
+                         static_cast<int>(nBlockOffset >> 32),
+                         static_cast<int>(nBlockOffset & 0xffffffff), fpData,
+                         VSIStrerror(errno));
                 return CE_Failure;
             }
         }
 
-        CPLErr eErr = UncompressBlock( pabyCData, (int) nBlockSize,
-                                       (GByte *) pData, nBlockXSize*nBlockYSize,
-                                       eDataType );
+        CPLErr eErr = UncompressBlock(pabyCData, static_cast<int>(nBlockSize),
+                                      static_cast<GByte *>(pData),
+                                      nBlockXSize * nBlockYSize, eDataType);
 
-        CPLFree( pabyCData );
+        CPLFree(pabyCData);
 
         return eErr;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read uncompressed data directly into the return buffer.         */
-/* -------------------------------------------------------------------- */
-    if ( nDataSize != -1 && (nBlockSize > INT_MAX ||
-                             (int)nBlockSize > nDataSize) )
+    // Read uncompressed data directly into the return buffer.
+    if( nDataSize != -1 && (nBlockSize > INT_MAX ||
+                            static_cast<int>(nBlockSize) > nDataSize) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                    "Invalid block size : %d", (int)nBlockSize);
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid block size: %d",
+                 static_cast<int>(nBlockSize));
         return CE_Failure;
     }
 
-    if( VSIFReadL( pData, (size_t) nBlockSize, 1, fpData ) != 1 )
+    if( VSIFReadL(pData, static_cast<size_t>(nBlockSize), 1, fpData) != 1 )
     {
-	memset( pData, 0,
-	    HFAGetDataTypeBits(eDataType)*nBlockXSize*nBlockYSize/8 );
+        memset(pData, 0,
+               HFAGetDataTypeBits(eDataType) * nBlockXSize * nBlockYSize / 8);
 
         if( fpData != fpExternal )
-            CPLDebug( "HFABand",
-                      "Read of %x:%08x bytes at %d on %p failed.\n%s",
-                      (int) nBlockSize,
-                      (int) (nBlockOffset >> 32),
-                      (int) (nBlockOffset & 0xffffffff),
-                      fpData, VSIStrerror(errno) );
-
-	return CE_None;
+            CPLDebug("HFABand", "Read of %x:%08x bytes at %d on %p failed.\n%s",
+                     static_cast<int>(nBlockSize),
+                     static_cast<int>(nBlockOffset >> 32),
+                     static_cast<int>(nBlockOffset & 0xffffffff), fpData,
+                     VSIStrerror(errno));
+
+        return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Byte swap to local byte order if required.  It appears that     */
-/*      raster data is always stored in Intel byte order in Imagine     */
-/*      files.                                                          */
-/* -------------------------------------------------------------------- */
+    // Byte swap to local byte order if required.  It appears that
+    // raster data is always stored in Intel byte order in Imagine
+    // files.
 
 #ifdef CPL_MSB
     if( HFAGetDataTypeBits(eDataType) == 16 )
     {
-        for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
-            CPL_SWAP16PTR( ((unsigned char *) pData) + ii*2 );
+        for( int ii = 0; ii < nBlockXSize * nBlockYSize; ii++ )
+            CPL_SWAP16PTR(((unsigned char *)pData) + ii * 2);
     }
     else if( HFAGetDataTypeBits(eDataType) == 32 )
     {
-        for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
-            CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
+        for( int ii = 0; ii < nBlockXSize * nBlockYSize; ii++ )
+            CPL_SWAP32PTR(((unsigned char *)pData) + ii * 4);
     }
     else if( eDataType == EPT_f64 )
     {
@@ -1247,60 +1291,59 @@ CPLErr HFABand::GetRasterBlock( int nXBlock, int nYBlock, void * pData, int nDat
     }
     else if( eDataType == EPT_c64 )
     {
-        for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
-            CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
+        for( int ii = 0; ii < nBlockXSize * nBlockYSize * 2; ii++ )
+            CPL_SWAP32PTR(((unsigned char *)pData) + ii * 4);
     }
     else if( eDataType == EPT_c128 )
     {
-        for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
-            CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
+        for( int ii = 0; ii < nBlockXSize * nBlockYSize * 2; ii++ )
+            CPL_SWAP64PTR(((unsigned char *)pData) + ii * 8 );
     }
-#endif /* def CPL_MSB */
+#endif  // def CPL_MSB
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
-/*                           ReAllocBlock()                           */
+/*                           ReAllocBlock()                             */
 /************************************************************************/
 
 void HFABand::ReAllocBlock( int iBlock, int nSize )
 {
-    /* For compressed files - need to realloc the space for the block */
+    // For compressed files - need to realloc the space for the block.
 
-    // TODO: Should check to see if panBlockStart[iBlock] is not zero then do a HFAFreeSpace()
-    // but that doesn't exist yet.
+    // TODO: Should check to see if panBlockStart[iBlock] is not zero then do a
+    // HFAFreeSpace() but that doesn't exist yet.
     // Instead as in interim measure it will reuse the existing block if
     // the new data will fit in.
-    if( ( panBlockStart[iBlock] != 0 ) && ( nSize <= panBlockSize[iBlock] ) )
+    if( (panBlockStart[iBlock] != 0) && (nSize <= panBlockSize[iBlock]) )
     {
         panBlockSize[iBlock] = nSize;
-        //fprintf( stderr, "Reusing block %d\n", iBlock );
+        // fprintf( stderr, "Reusing block %d\n", iBlock );
         return;
     }
 
-    panBlockStart[iBlock] = HFAAllocateSpace( psInfo, nSize );
+    panBlockStart[iBlock] = HFAAllocateSpace(psInfo, nSize);
 
     panBlockSize[iBlock] = nSize;
 
-    // need to re - write this info to the RasterDMS node
-    HFAEntry	*poDMS = poNode->GetNamedChild( "RasterDMS" );
+    // Need to rewrite this info to the RasterDMS node.
+    HFAEntry *poDMS = poNode->GetNamedChild("RasterDMS");
 
-    if (!poDMS)
+    if( !poDMS )
     {
         CPLError(CE_Failure, CPLE_FileIO, "Unable to load RasterDMS");
         return;
     }
 
-    char	szVarName[64];
-    snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].offset", iBlock );
-    poDMS->SetIntField( szVarName, (int) panBlockStart[iBlock] );
+    char szVarName[64];
+    snprintf(szVarName, sizeof(szVarName), "blockinfo[%d].offset", iBlock);
+    poDMS->SetIntField(szVarName, static_cast<int>(panBlockStart[iBlock]));
 
-    snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].size", iBlock );
-    poDMS->SetIntField( szVarName, panBlockSize[iBlock] );
+    snprintf(szVarName, sizeof(szVarName), "blockinfo[%d].size", iBlock);
+    poDMS->SetIntField(szVarName, panBlockSize[iBlock]);
 }
 
-
 /************************************************************************/
 /*                           SetRasterBlock()                           */
 /************************************************************************/
@@ -1310,8 +1353,8 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 {
     if( psInfo->eAccess == HFA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
-                  "Attempt to write block to read-only HFA file failed." );
+        CPLError(CE_Failure, CPLE_NoWriteAccess,
+                 "Attempt to write block to read-only HFA file failed.");
         return CE_Failure;
     }
 
@@ -1320,33 +1363,29 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 
     const int iBlock = nXBlock + nYBlock * nBlocksPerRow;
 
-/* -------------------------------------------------------------------- */
-/*      For now we don't support write invalid uncompressed blocks.     */
-/*      To do so we will need logic to make space at the end of the     */
-/*      file in the right size.                                         */
-/* -------------------------------------------------------------------- */
-    if( (panBlockFlag[iBlock] & BFLG_VALID) == 0
-        && !(panBlockFlag[iBlock] & BFLG_COMPRESSED)
-        && panBlockStart[iBlock] == 0 )
+    // For now we don't support write invalid uncompressed blocks.
+    // To do so we will need logic to make space at the end of the
+    // file in the right size.
+    if( (panBlockFlag[iBlock] & BFLG_VALID) == 0 &&
+        !(panBlockFlag[iBlock] & BFLG_COMPRESSED) &&
+        panBlockStart[iBlock] == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to write to invalid tile with number %d "
-                  "(X position %d, Y position %d).  This\n operation currently "
-                  "unsupported by HFABand::SetRasterBlock().\n",
-                  iBlock, nXBlock, nYBlock );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Attempt to write to invalid tile with number %d "
+                 "(X position %d, Y position %d).  This operation is "
+                 "currently unsupported by HFABand::SetRasterBlock().",
+                 iBlock, nXBlock, nYBlock);
 
         return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Move to the location that the data sits.                        */
-/* -------------------------------------------------------------------- */
+    // Move to the location that the data sits.
     VSILFILE *fpData = NULL;
     vsi_l_offset nBlockOffset = 0;
 
     // Calculate block offset in case we have spill file. Use predefined
     // block map otherwise.
-    if ( fpExternal )
+    if( fpExternal )
     {
         fpData = fpExternal;
         nBlockOffset = nBlockStart + nBlockSize * iBlock * nLayerStackCount
@@ -1359,28 +1398,25 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
         nBlockSize = panBlockSize[iBlock];
     }
 
-/* ==================================================================== */
-/*      Compressed Tile Handling.                                       */
-/* ==================================================================== */
+    // Compressed Tile Handling.
     if( panBlockFlag[iBlock] & BFLG_COMPRESSED )
     {
-        /* ------------------------------------------------------------ */
-        /*      Write compressed data.				        */
-        /* ------------------------------------------------------------ */
-        int nInBlockSize = (nBlockXSize * nBlockYSize * HFAGetDataTypeBits(eDataType) + 7 ) / 8;
+        // Write compressed data.
+        int nInBlockSize =
+            (nBlockXSize * nBlockYSize * HFAGetDataTypeBits(eDataType) + 7) / 8;
 
-        /* create the compressor object */
-        HFACompress compress( pData, nInBlockSize, eDataType );
+        // Create the compressor object.
+        HFACompress compress(pData, nInBlockSize, eDataType);
         if( compress.getCounts() == NULL ||
             compress.getValues() == NULL)
         {
             return CE_Failure;
         }
 
-        /* compress the data */
+        // Compress the data.
         if( compress.compressBlock() )
         {
-            /* get the data out of the object */
+            // Get the data out of the object.
             GByte *pCounts      = compress.getCounts();
             GUInt32 nSizeCount  = compress.getCountSize();
             GByte *pValues      = compress.getValues();
@@ -1389,9 +1425,9 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
             GUInt32 nNumRuns    = compress.getNumRuns();
             GByte nNumBits      = compress.getNumBits();
 
-            /* Compensate for the header info */
+            // Compensate for the header info.
             GUInt32 nDataOffset = nSizeCount + 13;
-            int nTotalSize  = nSizeCount + nSizeValues + 13;
+            int nTotalSize = nSizeCount + nSizeValues + 13;
 
             // Allocate space for the compressed block and seek to it.
             ReAllocBlock( iBlock, nTotalSize );
@@ -1399,214 +1435,206 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
             nBlockOffset = panBlockStart[iBlock];
             nBlockSize = panBlockSize[iBlock];
 
-            // Seek to offset
-            if( VSIFSeekL( fpData, nBlockOffset, SEEK_SET ) != 0 )
+            // Seek to offset.
+            if( VSIFSeekL(fpData, nBlockOffset, SEEK_SET) != 0 )
             {
-                CPLError( CE_Failure, CPLE_FileIO, "Seek to %x:%08x on %p failed\n%s",
-                          (int) (nBlockOffset >> 32),
-                          (int) (nBlockOffset & 0xffffffff),
-                          fpData, VSIStrerror(errno) );
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Seek to %x:%08x on %p failed\n%s",
+                         static_cast<int>(nBlockOffset >> 32),
+                         static_cast<int>(nBlockOffset & 0xffffffff),
+                         fpData, VSIStrerror(errno));
                 return CE_Failure;
             }
 
-   /* -------------------------------------------------------------------- */
-   /*      Byte swap to local byte order if required.  It appears that     */
-   /*      raster data is always stored in Intel byte order in Imagine     */
-   /*      files.                                                          */
-   /* -------------------------------------------------------------------- */
+            // Byte swap to local byte order if required.  It appears that
+            // raster data is always stored in Intel byte order in Imagine
+            // files.
 
 #ifdef CPL_MSB
+            CPL_SWAP32PTR(&nMin);
+            CPL_SWAP32PTR(&nNumRuns);
+            CPL_SWAP32PTR(&nDataOffset);
+#endif  // def CPL_MSB
 
-            CPL_SWAP32PTR( &nMin );
-            CPL_SWAP32PTR( &nNumRuns );
-            CPL_SWAP32PTR( &nDataOffset );
-
-#endif /* def CPL_MSB */
-
-       /* Write out the Minimum value */
-            bool bRet = VSIFWriteL( &nMin, (size_t) sizeof( nMin ), 1, fpData ) > 0;
+            // Write out the Minimum value.
+            bool bRet = VSIFWriteL(&nMin, sizeof(nMin), 1, fpData) > 0;
 
-            /* the number of runs */
-            bRet &= VSIFWriteL( &nNumRuns, (size_t) sizeof( nNumRuns ), 1, fpData ) > 0;
+            // The number of runs.
+            bRet &= VSIFWriteL(&nNumRuns, sizeof(nNumRuns), 1, fpData) > 0;
 
-            /* The offset to the data */
-            bRet &= VSIFWriteL( &nDataOffset, (size_t) sizeof( nDataOffset ), 1, fpData ) > 0;
+            // The offset to the data.
+            bRet &=
+                VSIFWriteL(&nDataOffset, sizeof(nDataOffset), 1, fpData) > 0;
 
-            /* The number of bits */
-            bRet &= VSIFWriteL( &nNumBits, (size_t) sizeof( nNumBits ), 1, fpData ) > 0;
+            // The number of bits.
+            bRet &= VSIFWriteL(&nNumBits, sizeof(nNumBits), 1, fpData) > 0;
 
-            /* The counters - MSB stuff handled in HFACompress */
-            bRet &= VSIFWriteL( pCounts, nSizeCount, 1, fpData ) > 0;
+            // The counters - MSB stuff handled in HFACompress.
+            bRet &= VSIFWriteL(pCounts, nSizeCount, 1, fpData) > 0;
 
-            /* The values - MSB stuff handled in HFACompress */
-            bRet &= VSIFWriteL( pValues, nSizeValues, 1, fpData ) > 0;
+            // The values - MSB stuff handled in HFACompress.
+            bRet &= VSIFWriteL(pValues, nSizeValues, 1, fpData) > 0;
 
             if( !bRet )
                 return CE_Failure;
 
-            /* Compressed data is freed in the HFACompress destructor */
+            // Compressed data is freed in the HFACompress destructor.
         }
         else
         {
-            /* If we have actually made the block bigger - i.e. does not compress well */
+            // If we have actually made the block bigger - i.e. does not
+            // compress well.
             panBlockFlag[iBlock] ^= BFLG_COMPRESSED;
-            // alloc more space for the uncompressed block
-            ReAllocBlock( iBlock, nInBlockSize );
+            // Alloc more space for the uncompressed block.
+            ReAllocBlock(iBlock, nInBlockSize);
 
             nBlockOffset = panBlockStart[iBlock];
             nBlockSize = panBlockSize[iBlock];
 
-            /* Need to change the RasterDMS entry */
-            HFAEntry	*poDMS = poNode->GetNamedChild( "RasterDMS" );
+            // Need to change the RasterDMS entry.
+            HFAEntry *poDMS = poNode->GetNamedChild("RasterDMS");
 
-            if (!poDMS)
+            if( !poDMS )
             {
                 CPLError(CE_Failure, CPLE_FileIO, "Unable to load RasterDMS");
                 return CE_Failure;
             }
 
-            char	szVarName[64];
-            snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].compressionType", iBlock );
-            poDMS->SetIntField( szVarName, 0 );
+            char szVarName[64] = {};
+            snprintf(szVarName, sizeof(szVarName),
+                     "blockinfo[%d].compressionType", iBlock);
+            poDMS->SetIntField(szVarName, 0);
         }
 
-/* -------------------------------------------------------------------- */
-/*      If the block was previously invalid, mark it as valid now.      */
-/* -------------------------------------------------------------------- */
+        // If the block was previously invalid, mark it as valid now.
         if( (panBlockFlag[iBlock] & BFLG_VALID) == 0 )
         {
-            char	szVarName[64];
-            HFAEntry	*poDMS = poNode->GetNamedChild( "RasterDMS" );
+            char szVarName[64];
+            HFAEntry *poDMS = poNode->GetNamedChild("RasterDMS");
 
-            if (!poDMS)
+            if( !poDMS )
             {
                 CPLError(CE_Failure, CPLE_FileIO, "Unable to load RasterDMS");
                 return CE_Failure;
             }
 
-            snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].logvalid", iBlock );
-            poDMS->SetStringField( szVarName, "true" );
+            snprintf(szVarName, sizeof(szVarName), "blockinfo[%d].logvalid", iBlock);
+            poDMS->SetStringField(szVarName, "true");
 
             panBlockFlag[iBlock] |= BFLG_VALID;
         }
     }
 
-/* ==================================================================== */
-/*      Uncompressed TILE handling.                                     */
-/* ==================================================================== */
-    if( ( panBlockFlag[iBlock] & BFLG_COMPRESSED ) == 0 )
+    // Uncompressed TILE handling.
+    if( (panBlockFlag[iBlock] & BFLG_COMPRESSED) == 0 )
     {
 
-        if( VSIFSeekL( fpData, nBlockOffset, SEEK_SET ) != 0 )
+        if( VSIFSeekL(fpData, nBlockOffset, SEEK_SET) != 0 )
         {
-            CPLError( CE_Failure, CPLE_FileIO, "Seek to %x:%08x on %p failed\n%s",
-                      (int) (nBlockOffset >> 32),
-                      (int) (nBlockOffset & 0xffffffff),
-                      fpData, VSIStrerror(errno) );
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Seek to %x:%08x on %p failed\n%s",
+                     static_cast<int>(nBlockOffset >> 32),
+                     static_cast<int>(nBlockOffset & 0xffffffff), fpData,
+                     VSIStrerror(errno));
             return CE_Failure;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Byte swap to local byte order if required.  It appears that     */
-/*      raster data is always stored in Intel byte order in Imagine     */
-/*      files.                                                          */
-/* -------------------------------------------------------------------- */
+        // Byte swap to local byte order if required.  It appears that
+        // raster data is always stored in Intel byte order in Imagine
+        // files.
 
 #ifdef CPL_MSB
         if( HFAGetDataTypeBits(eDataType) == 16 )
         {
-            for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
-                CPL_SWAP16PTR( ((unsigned char *) pData) + ii*2 );
+            for( int ii = 0; ii < nBlockXSize * nBlockYSize; ii++ )
+                CPL_SWAP16PTR(((unsigned char *)pData) + ii * 2);
         }
         else if( HFAGetDataTypeBits(eDataType) == 32 )
         {
-            for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
-                CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
+            for( int ii = 0; ii < nBlockXSize * nBlockYSize; ii++ )
+                CPL_SWAP32PTR(((unsigned char *)pData) + ii * 4);
         }
         else if( eDataType == EPT_f64 )
         {
-            for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
-                CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
+            for( int ii = 0; ii < nBlockXSize * nBlockYSize; ii++ )
+                CPL_SWAP64PTR(((unsigned char *)pData) + ii * 8);
         }
         else if( eDataType == EPT_c64 )
         {
-            for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
-                CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
+            for( int ii = 0; ii < nBlockXSize * nBlockYSize * 2; ii++ )
+                CPL_SWAP32PTR(((unsigned char *)pData) + ii * 4);
         }
         else if( eDataType == EPT_c128 )
         {
-            for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
-                CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
+            for( int ii = 0; ii < nBlockXSize * nBlockYSize * 2; ii++ )
+                CPL_SWAP64PTR(((unsigned char *)pData) + ii * 8);
         }
-#endif /* def CPL_MSB */
+#endif  // def CPL_MSB
 
-/* -------------------------------------------------------------------- */
-/*      Write uncompressed data.				        */
-/* -------------------------------------------------------------------- */
-        if( VSIFWriteL( pData, (size_t) nBlockSize, 1, fpData ) != 1 )
+        // Write uncompressed data.
+        if( VSIFWriteL(pData, static_cast<size_t>(nBlockSize),
+                       1, fpData) != 1 )
         {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Write of %d bytes at %x:%08x on %p failed.\n%s",
-                      (int) nBlockSize,
-                      (int) (nBlockOffset >> 32),
-                      (int) (nBlockOffset & 0xffffffff),
-                      fpData, VSIStrerror(errno) );
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Write of %d bytes at %x:%08x on %p failed.\n%s",
+                     static_cast<int>(nBlockSize),
+                     static_cast<int>(nBlockOffset >> 32),
+                     static_cast<int>(nBlockOffset & 0xffffffff), fpData,
+                     VSIStrerror(errno));
             return CE_Failure;
         }
 
-/* -------------------------------------------------------------------- */
-/*      If the block was previously invalid, mark it as valid now.      */
-/* -------------------------------------------------------------------- */
+        // If the block was previously invalid, mark it as valid now.
         if( (panBlockFlag[iBlock] & BFLG_VALID) == 0 )
         {
-            char	szVarName[64];
-            HFAEntry	*poDMS = poNode->GetNamedChild( "RasterDMS" );
-            if (poDMS == NULL) {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Unable to get RasterDMS when trying to mark "
-                          "block valid." );
+            char szVarName[64];
+            HFAEntry *poDMS = poNode->GetNamedChild("RasterDMS");
+            if( poDMS == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Unable to get RasterDMS when trying to mark "
+                         "block valid.");
                 return CE_Failure;
             }
-            snprintf( szVarName, sizeof(szVarName), "blockinfo[%d].logvalid", iBlock );
-            poDMS->SetStringField( szVarName, "true" );
+            snprintf(szVarName, sizeof(szVarName), "blockinfo[%d].logvalid",
+                     iBlock);
+            poDMS->SetStringField(szVarName, "true");
 
             panBlockFlag[iBlock] |= BFLG_VALID;
         }
     }
-/* -------------------------------------------------------------------- */
-/*      Swap back, since we don't really have permission to change      */
-/*      the callers buffer.                                             */
-/* -------------------------------------------------------------------- */
+    // Swap back, since we don't really have permission to change
+    // the callers buffer.
 
 #ifdef CPL_MSB
     if( HFAGetDataTypeBits(eDataType) == 16 )
     {
-        for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
-            CPL_SWAP16PTR( ((unsigned char *) pData) + ii*2 );
+        for( int ii = 0; ii < nBlockXSize * nBlockYSize; ii++ )
+            CPL_SWAP16PTR(((unsigned char *)pData) + ii * 2);
     }
     else if( HFAGetDataTypeBits(eDataType) == 32 )
     {
-        for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
-            CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
+        for( int ii = 0; ii < nBlockXSize * nBlockYSize; ii++ )
+            CPL_SWAP32PTR(((unsigned char *)pData) + ii * 4);
     }
     else if( eDataType == EPT_f64 )
     {
-        for( int ii = 0; ii < nBlockXSize*nBlockYSize; ii++ )
-            CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
+        for( int ii = 0; ii < nBlockXSize * nBlockYSize; ii++ )
+            CPL_SWAP64PTR(((unsigned char *)pData) + ii * 8);
     }
     else if( eDataType == EPT_c64 )
     {
-        for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
-            CPL_SWAP32PTR( ((unsigned char *) pData) + ii*4 );
+        for( int ii = 0; ii < nBlockXSize * nBlockYSize * 2; ii++ )
+            CPL_SWAP32PTR(((unsigned char *)pData) + ii * 4);
     }
     else if( eDataType == EPT_c128 )
     {
-        for( int ii = 0; ii < nBlockXSize*nBlockYSize*2; ii++ )
-            CPL_SWAP64PTR( ((unsigned char *) pData) + ii*8 );
+        for( int ii = 0; ii < nBlockXSize * nBlockYSize * 2; ii++ )
+            CPL_SWAP64PTR(((unsigned char *)pData) + ii * 8);
     }
-#endif /* def CPL_MSB */
+#endif  // def CPL_MSB
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1615,7 +1643,7 @@ CPLErr HFABand::SetRasterBlock( int nXBlock, int nYBlock, void * pData )
 /*      Return the Layer Name                                           */
 /************************************************************************/
 
-const char * HFABand::GetBandName()
+const char *HFABand::GetBandName()
 {
     if( strlen(poNode->GetName()) > 0 )
         return poNode->GetName();
@@ -1624,12 +1652,12 @@ const char * HFABand::GetBandName()
     {
         if( psInfo->papoBand[iBand] == this )
         {
-            osOverName.Printf( "Layer_%d", iBand+1 );
+            osOverName.Printf("Layer_%d", iBand + 1);
             return osOverName;
         }
     }
 
-    osOverName.Printf( "Layer_%x", poNode->GetFilePos() );
+    osOverName.Printf("Layer_%x", poNode->GetFilePos());
     return osOverName;
 }
 
@@ -1655,30 +1683,30 @@ void HFABand::SetBandName(const char *pszName)
 
 CPLErr HFABand::SetNoDataValue( double dfValue )
 {
-    if ( psInfo->eAccess != HFA_Update )
+    if( psInfo->eAccess != HFA_Update )
         return CE_Failure;
 
-    HFAEntry *poNDNode = poNode->GetNamedChild( "Eimg_NonInitializedValue" );
+    HFAEntry *poNDNode = poNode->GetNamedChild("Eimg_NonInitializedValue");
 
-    if ( poNDNode == NULL )
+    if( poNDNode == NULL )
     {
-        poNDNode = HFAEntry::New( psInfo,
+        poNDNode = HFAEntry::New(psInfo,
                                  "Eimg_NonInitializedValue",
                                  "Eimg_NonInitializedValue",
-                                 poNode );
+                                 poNode);
     }
 
-    poNDNode->MakeData( 8 + 12 + 8 );
+    poNDNode->MakeData(8 + 12 + 8);
     poNDNode->SetPosition();
 
-    poNDNode->SetIntField( "valueBD[-3]", EPT_f64 );
-    poNDNode->SetIntField( "valueBD[-2]", 1 );
-    poNDNode->SetIntField( "valueBD[-1]", 1 );
+    poNDNode->SetIntField("valueBD[-3]", EPT_f64);
+    poNDNode->SetIntField("valueBD[-2]", 1);
+    poNDNode->SetIntField("valueBD[-1]", 1);
 
-    if ( poNDNode->SetDoubleField( "valueBD[0]", dfValue) == CE_Failure )
+    if( poNDNode->SetDoubleField("valueBD[0]", dfValue) == CE_Failure )
         return CE_Failure;
 
-    bNoDataSet = TRUE;
+    bNoDataSet = true;
     dfNoData = dfValue;
     return CE_None;
 }
@@ -1693,62 +1721,56 @@ CPLErr HFABand::SetNoDataValue( double dfValue )
 double *HFAReadBFUniqueBins( HFAEntry *poBinFunc, int nPCTColors )
 
 {
-/* -------------------------------------------------------------------- */
-/*      First confirm this is a "BFUnique" bin function.  We don't      */
-/*      know what to do with any other types.                           */
-/* -------------------------------------------------------------------- */
+    // First confirm this is a "BFUnique" bin function.  We don't
+    // know what to do with any other types.
     const char *pszBinFunctionType =
-        poBinFunc->GetStringField( "binFunction.type.string" );
+        poBinFunc->GetStringField("binFunction.type.string");
 
-    if( pszBinFunctionType == NULL
-        || !EQUAL(pszBinFunctionType,"BFUnique") )
+    if( pszBinFunctionType == NULL ||
+        !EQUAL(pszBinFunctionType, "BFUnique") )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Process dictionary.                                             */
-/* -------------------------------------------------------------------- */
+    // Process dictionary.
     const char *pszDict =
-        poBinFunc->GetStringField( "binFunction.MIFDictionary.string" );
+        poBinFunc->GetStringField("binFunction.MIFDictionary.string");
     if( pszDict == NULL )
-        pszDict = poBinFunc->GetStringField( "binFunction.MIFDictionary" );
+        pszDict = poBinFunc->GetStringField("binFunction.MIFDictionary");
     if( pszDict == NULL )
         return NULL;
 
-    HFADictionary oMiniDict( pszDict );
+    HFADictionary oMiniDict(pszDict);
 
-    HFAType *poBFUnique = oMiniDict.FindType( "BFUnique" );
+    HFAType *poBFUnique = oMiniDict.FindType("BFUnique");
     if( poBFUnique == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Field the MIFObject raw data pointer.                           */
-/* -------------------------------------------------------------------- */
-    const GByte *pabyMIFObject = (const GByte *)
-        poBinFunc->GetStringField("binFunction.MIFObject");
+    // Field the MIFObject raw data pointer.
+    const GByte *pabyMIFObject =
+        (const GByte *)poBinFunc->GetStringField("binFunction.MIFObject");
 
     if( pabyMIFObject == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Confirm that this is a 64bit floating point basearray.          */
-/* -------------------------------------------------------------------- */
+    // Confirm that this is a 64bit floating point basearray.
     if( pabyMIFObject[20] != 0x0a || pabyMIFObject[21] != 0x00 )
     {
-        CPLDebug( "HFA", "HFAReadPCTBins(): The basedata does not appear to be EGDA_TYPE_F64." );
+        CPLDebug("HFA", "HFAReadPCTBins(): "
+                        "The basedata does not appear to be EGDA_TYPE_F64.");
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Decode bins.                                                    */
-/* -------------------------------------------------------------------- */
-    double *padfBins = (double *) CPLCalloc(sizeof(double),nPCTColors);
+    // Decode bins.
+    double *padfBins =
+        static_cast<double *>(CPLCalloc(sizeof(double), nPCTColors));
 
-    memcpy( padfBins, pabyMIFObject + 24, sizeof(double) * nPCTColors );
+    memcpy(padfBins, pabyMIFObject + 24, sizeof(double) * nPCTColors);
 
     for( int i = 0; i < nPCTColors; i++ )
     {
-        HFAStandard( 8, padfBins + i );
-//        CPLDebug( "HFA", "Bin[%d] = %g", i, padfBins[i] );
+        HFAStandard(8, padfBins + i);
+#if DEBUG_VERBOSE
+        CPLDebug("HFA", "Bin[%d] = %g", i, padfBins[i]);
+#endif
     }
 
     return padfBins;
@@ -1775,9 +1797,7 @@ CPLErr HFABand::GetPCT( int * pnColors,
     *ppadfAlpha = NULL;
     *ppadfBins = NULL;
 
-/* -------------------------------------------------------------------- */
-/*      If we haven't already tried to load the colors, do so now.      */
-/* -------------------------------------------------------------------- */
+    // If we haven't already tried to load the colors, do so now.
     if( nPCTColors == -1 )
     {
 
@@ -1785,73 +1805,79 @@ CPLErr HFABand::GetPCT( int * pnColors,
 
         HFAEntry *poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Red");
         if( poColumnEntry == NULL )
-            return( CE_Failure );
+            return CE_Failure;
 
-        /* FIXME? : we could also check that nPCTColors is not too big */
-        nPCTColors = poColumnEntry->GetIntField( "numRows" );
+        // TODO(schwehr): Check that nPCTColors is not too big.
+        nPCTColors = poColumnEntry->GetIntField("numRows");
         for( int iColumn = 0; iColumn < 4; iColumn++ )
         {
-            apadfPCT[iColumn] = (double *)VSI_MALLOC2_VERBOSE(sizeof(double),nPCTColors);
-            if (apadfPCT[iColumn] == NULL)
+            apadfPCT[iColumn] = static_cast<double *>(
+                 VSI_MALLOC2_VERBOSE(sizeof(double), nPCTColors));
+            if( apadfPCT[iColumn] == NULL )
             {
                 return CE_Failure;
             }
 
             if( iColumn == 0 )
+            {
                 poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Red");
+            }
             else if( iColumn == 1 )
-                poColumnEntry= poNode->GetNamedChild("Descriptor_Table.Green");
+            {
+                poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Green");
+            }
             else if( iColumn == 2 )
+            {
                 poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Blue");
-            else if( iColumn == 3 ) {
-                poColumnEntry = poNode->GetNamedChild("Descriptor_Table.Opacity");
-	    }
+            }
+            else if( iColumn == 3 )
+            {
+                poColumnEntry =
+                    poNode->GetNamedChild("Descriptor_Table.Opacity");
+            }
 
             if( poColumnEntry == NULL )
             {
-                double  *pdCol = apadfPCT[iColumn];
+                double *pdCol = apadfPCT[iColumn];
                 for( int i = 0; i < nPCTColors; i++ )
                     pdCol[i] = 1.0;
             }
             else
             {
-                if (VSIFSeekL( psInfo->fp, poColumnEntry->GetIntField("columnDataPtr"),
-                               SEEK_SET ) < 0)
+                if( VSIFSeekL(psInfo->fp,
+                              poColumnEntry->GetIntField("columnDataPtr"),
+                              SEEK_SET) < 0 )
                 {
-                    CPLError( CE_Failure, CPLE_FileIO,
-                              "VSIFSeekL() failed in HFABand::GetPCT()." );
+                    CPLError(CE_Failure, CPLE_FileIO,
+                             "VSIFSeekL() failed in HFABand::GetPCT().");
                     return CE_Failure;
                 }
-                if (VSIFReadL( apadfPCT[iColumn], sizeof(double), nPCTColors,
-                               psInfo->fp) != (size_t)nPCTColors)
+                if( VSIFReadL(apadfPCT[iColumn], sizeof(double), nPCTColors,
+                              psInfo->fp) != static_cast<size_t>(nPCTColors) )
                 {
-                    CPLError( CE_Failure, CPLE_FileIO,
-                              "VSIFReadL() failed in HFABand::GetPCT()." );
+                    CPLError(CE_Failure, CPLE_FileIO,
+                             "VSIFReadL() failed in HFABand::GetPCT().");
                     return CE_Failure;
                 }
 
                 for( int i = 0; i < nPCTColors; i++ )
-                    HFAStandard( 8, apadfPCT[iColumn] + i );
+                    HFAStandard(8, apadfPCT[iColumn] + i);
             }
         }
 
-/* -------------------------------------------------------------------- */
-/*      Do we have a custom binning function? If so, try reading it.    */
-/* -------------------------------------------------------------------- */
+        // Do we have a custom binning function? If so, try reading it.
         HFAEntry *poBinFunc =
             poNode->GetNamedChild("Descriptor_Table.#Bin_Function840#");
 
         if( poBinFunc != NULL )
         {
-            padfPCTBins = HFAReadBFUniqueBins( poBinFunc, nPCTColors );
+            padfPCTBins = HFAReadBFUniqueBins(poBinFunc, nPCTColors);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Return the values.                                              */
-/* -------------------------------------------------------------------- */
+    // Return the values.
     if( nPCTColors == 0 )
-        return( CE_Failure );
+        return CE_Failure;
 
     *pnColors = nPCTColors;
     *ppadfRed = apadfPCT[0];
@@ -1860,7 +1886,7 @@ CPLErr HFABand::GetPCT( int * pnColors,
     *ppadfAlpha = apadfPCT[3];
     *ppadfBins = padfPCTBins;
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1872,26 +1898,25 @@ CPLErr HFABand::GetPCT( int * pnColors,
 CPLErr HFABand::SetPCT( int nColors,
                         double *padfRed,
                         double *padfGreen,
-                        double *padfBlue ,
-			double *padfAlpha)
+                        double *padfBlue,
+                        double *padfAlpha )
 
 {
-    static const char * const apszColNames[4] = {"Red", "Green", "Blue", "Opacity"};
-    HFAEntry	*poEdsc_Table;
+    static const char *const apszColNames[4] =
+        {"Red", "Green", "Blue", "Opacity"};
+    HFAEntry *poEdsc_Table;
 
-/* -------------------------------------------------------------------- */
-/*      Do we need to try and clear any existing color table?           */
-/* -------------------------------------------------------------------- */
+    // Do we need to try and clear any existing color table?
     if( nColors == 0 )
     {
-        poEdsc_Table = poNode->GetNamedChild( "Descriptor_Table" );
+        poEdsc_Table = poNode->GetNamedChild("Descriptor_Table");
         if( poEdsc_Table == NULL )
             return CE_None;
 
         for( int iColumn = 0; iColumn < 4; iColumn++ )
         {
-          HFAEntry *poEdsc_Column
-              = poEdsc_Table->GetNamedChild(apszColNames[iColumn]);
+            HFAEntry *poEdsc_Column =
+                poEdsc_Table->GetNamedChild(apszColNames[iColumn]);
             if( poEdsc_Column )
                 poEdsc_Column->RemoveAndDestroy();
         }
@@ -1899,44 +1924,38 @@ CPLErr HFABand::SetPCT( int nColors,
         return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the Descriptor table.                                    */
-/* -------------------------------------------------------------------- */
-    poEdsc_Table = poNode->GetNamedChild( "Descriptor_Table" );
-    if( poEdsc_Table == NULL
-        || !EQUAL(poEdsc_Table->GetType(),"Edsc_Table") )
-        poEdsc_Table = HFAEntry::New( psInfo, "Descriptor_Table",
-                                     "Edsc_Table", poNode );
+    // Create the Descriptor table.
+    poEdsc_Table = poNode->GetNamedChild("Descriptor_Table");
+    if( poEdsc_Table == NULL ||
+        !EQUAL(poEdsc_Table->GetType(), "Edsc_Table") )
+        poEdsc_Table =
+            HFAEntry::New(psInfo, "Descriptor_Table", "Edsc_Table", poNode);
 
     poEdsc_Table->SetIntField( "numrows", nColors );
 
-/* -------------------------------------------------------------------- */
-/*      Create the Binning function node.  I am not sure that we        */
-/*      really need this though.                                        */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poEdsc_BinFunction
-        = poEdsc_Table->GetNamedChild( "#Bin_Function#" );
-    if( poEdsc_BinFunction == NULL
-        || !EQUAL(poEdsc_BinFunction->GetType(),"Edsc_BinFunction") )
-        poEdsc_BinFunction = HFAEntry::New( psInfo, "#Bin_Function#",
+    // Create the Binning function node.  I am not sure that we
+    // really need this though.
+    HFAEntry *poEdsc_BinFunction =
+        poEdsc_Table->GetNamedChild("#Bin_Function#");
+    if( poEdsc_BinFunction == NULL ||
+        !EQUAL(poEdsc_BinFunction->GetType(), "Edsc_BinFunction") )
+        poEdsc_BinFunction = HFAEntry::New(psInfo, "#Bin_Function#",
                                            "Edsc_BinFunction",
-                                           poEdsc_Table );
+                                           poEdsc_Table);
 
     // Because of the BaseData we have to hardcode the size.
-    poEdsc_BinFunction->MakeData( 30 );
+    poEdsc_BinFunction->MakeData(30);
 
-    poEdsc_BinFunction->SetIntField( "numBins", nColors );
-    poEdsc_BinFunction->SetStringField( "binFunction", "direct" );
-    poEdsc_BinFunction->SetDoubleField( "minLimit", 0.0 );
-    poEdsc_BinFunction->SetDoubleField( "maxLimit", nColors - 1.0 );
+    poEdsc_BinFunction->SetIntField("numBins", nColors);
+    poEdsc_BinFunction->SetStringField("binFunction", "direct");
+    poEdsc_BinFunction->SetDoubleField("minLimit", 0.0);
+    poEdsc_BinFunction->SetDoubleField("maxLimit", nColors - 1.0);
 
-/* -------------------------------------------------------------------- */
-/*      Process each color component                                    */
-/* -------------------------------------------------------------------- */
+    // Process each color component.
     for( int iColumn = 0; iColumn < 4; iColumn++ )
     {
-        double	    *padfValues=NULL;
-        const char      *pszName = apszColNames[iColumn];
+        double *padfValues=NULL;
+        const char *pszName = apszColNames[iColumn];
 
         if( iColumn == 0 )
             padfValues = padfRed;
@@ -1947,45 +1966,41 @@ CPLErr HFABand::SetPCT( int nColors,
         else if( iColumn == 3 )
             padfValues = padfAlpha;
 
-/* -------------------------------------------------------------------- */
-/*      Create the Edsc_Column.                                         */
-/* -------------------------------------------------------------------- */
-        HFAEntry *poEdsc_Column = poEdsc_Table->GetNamedChild( pszName );
-        if( poEdsc_Column == NULL
-            || !EQUAL(poEdsc_Column->GetType(),"Edsc_Column") )
-            poEdsc_Column = HFAEntry::New( psInfo, pszName, "Edsc_Column",
-                                          poEdsc_Table );
+        // Create the Edsc_Column.
+        HFAEntry *poEdsc_Column = poEdsc_Table->GetNamedChild(pszName);
+        if( poEdsc_Column == NULL ||
+            !EQUAL(poEdsc_Column->GetType(), "Edsc_Column") )
+            poEdsc_Column =
+                HFAEntry::New(psInfo, pszName, "Edsc_Column", poEdsc_Table);
 
-        poEdsc_Column->SetIntField( "numRows", nColors );
-        poEdsc_Column->SetStringField( "dataType", "real" );
-        poEdsc_Column->SetIntField( "maxNumChars", 0 );
+        poEdsc_Column->SetIntField("numRows", nColors);
+        poEdsc_Column->SetStringField("dataType", "real");
+        poEdsc_Column->SetIntField("maxNumChars", 0);
 
-/* -------------------------------------------------------------------- */
-/*      Write the data out.                                             */
-/* -------------------------------------------------------------------- */
-        int nOffset = HFAAllocateSpace( psInfo, 8*nColors);
+        // Write the data out.
+        const int nOffset = HFAAllocateSpace(psInfo, 8 * nColors);
 
-        poEdsc_Column->SetIntField( "columnDataPtr", nOffset );
+        poEdsc_Column->SetIntField("columnDataPtr", nOffset);
 
-        double *padfFileData = (double *) CPLMalloc(nColors*sizeof(double));
+        double *padfFileData =
+            static_cast<double *>(CPLMalloc(nColors * sizeof(double)));
         for( int iColor = 0; iColor < nColors; iColor++ )
         {
             padfFileData[iColor] = padfValues[iColor];
-            HFAStandard( 8, padfFileData + iColor );
+            HFAStandard(8, padfFileData + iColor);
         }
-        bool bRet = VSIFSeekL( psInfo->fp, nOffset, SEEK_SET ) >= 0;
-        bRet &= VSIFWriteL( padfFileData, 8, nColors, psInfo->fp ) == (size_t)nColors;
-        CPLFree( padfFileData );
+        const bool bRet = VSIFSeekL(psInfo->fp, nOffset, SEEK_SET) >= 0 &&
+                          VSIFWriteL(padfFileData, 8, nColors, psInfo->fp) ==
+                              static_cast<size_t>(nColors);
+        CPLFree(padfFileData);
         if( !bRet )
             return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Update the layer type to be thematic.                           */
-/* -------------------------------------------------------------------- */
-    poNode->SetStringField( "layerType", "thematic" );
+    // Update the layer type to be thematic.
+    poNode->SetStringField("layerType", "thematic");
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1998,149 +2013,132 @@ int HFABand::CreateOverview( int nOverviewLevel, const char *pszResampling )
     const int nOXSize = (psInfo->nXSize + nOverviewLevel - 1) / nOverviewLevel;
     const int nOYSize = (psInfo->nYSize + nOverviewLevel - 1) / nOverviewLevel;
 
-/* -------------------------------------------------------------------- */
-/*      Do we want to use a dependent file (.rrd) for the overviews?    */
-/*      Or just create them directly in this file?                      */
-/* -------------------------------------------------------------------- */
+    // Do we want to use a dependent file (.rrd) for the overviews?
+    // Or just create them directly in this file?
     HFAInfo_t *psRRDInfo = psInfo;
     HFAEntry *poParent = poNode;
 
-    if( CPLTestBool( CPLGetConfigOption( "HFA_USE_RRD", "NO" ) ) )
+    if( CPLTestBool(CPLGetConfigOption("HFA_USE_RRD", "NO")) )
     {
-        psRRDInfo = HFACreateDependent( psInfo );
+        psRRDInfo = HFACreateDependent(psInfo);
         if( psRRDInfo == NULL )
             return -1;
 
-        poParent = psRRDInfo->poRoot->GetNamedChild( GetBandName() );
+        poParent = psRRDInfo->poRoot->GetNamedChild(GetBandName());
 
         // Need to create layer object.
         if( poParent == NULL )
         {
-            poParent =
-                HFAEntry::New( psRRDInfo, GetBandName(),
-                              "Eimg_Layer", psRRDInfo->poRoot );
+            poParent = HFAEntry::New(psRRDInfo, GetBandName(), "Eimg_Layer",
+                                     psRRDInfo->poRoot);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      What pixel type should we use for the overview.  Usually        */
-/*      this is the same as the base layer, but when                    */
-/*      AVERAGE_BIT2GRAYSCALE is in effect we force it to u8 from u1.   */
-/* -------------------------------------------------------------------- */
+    // What pixel type should we use for the overview.  Usually
+    // this is the same as the base layer, but when
+    // AVERAGE_BIT2GRAYSCALE is in effect we force it to u8 from u1.
     EPTType eOverviewDataType = eDataType;
 
     if( STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2GR") )
         eOverviewDataType = EPT_u8;
 
-/* -------------------------------------------------------------------- */
-/*      Eventually we need to decide on the whether to use the spill    */
-/*      file, primarily on the basis of whether the new overview        */
-/*      will drive our .img file size near 4GB.  For now, just base     */
-/*      it on the config options.                                       */
-/* -------------------------------------------------------------------- */
-    int bCreateLargeRaster = CPLTestBool(
-        CPLGetConfigOption("USE_SPILL","NO") );
-    GIntBig nValidFlagsOffset = 0, nDataOffset = 0;
+    // Eventually we need to decide on the whether to use the spill
+    // file, primarily on the basis of whether the new overview
+    // will drive our .img file size near 4GB.  For now, just base
+    // it on the config options.
+    bool bCreateLargeRaster =
+        CPLTestBool(CPLGetConfigOption("USE_SPILL", "NO"));
+    GIntBig nValidFlagsOffset = 0;
+    GIntBig nDataOffset = 0;
 
     if( (psRRDInfo->nEndOfFile
-         + (nOXSize * (double) nOYSize)
+         + (nOXSize * static_cast<double>(nOYSize))
          * (HFAGetDataTypeBits(eOverviewDataType) / 8)) > 2000000000.0 )
-        bCreateLargeRaster = TRUE;
+        bCreateLargeRaster = true;
 
     if( bCreateLargeRaster )
     {
-        if( !HFACreateSpillStack( psRRDInfo, nOXSize, nOYSize, 1,
-                                  64, eOverviewDataType,
-                                  &nValidFlagsOffset, &nDataOffset ) )
-	{
-	    return -1;
-	}
+        if( !HFACreateSpillStack(psRRDInfo, nOXSize, nOYSize, 1,
+                                 64, eOverviewDataType,
+                                 &nValidFlagsOffset, &nDataOffset) )
+        {
+            return -1;
+        }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Are we compressed? If so, overview should be too (unless        */
-/*      HFA_COMPRESS_OVR is defined).                                   */
-/*      Check RasterDMS like HFAGetBandInfo                             */
-/* -------------------------------------------------------------------- */
-    int bCompressionType = FALSE;
-    const char* pszCompressOvr = CPLGetConfigOption("HFA_COMPRESS_OVR", NULL);
+    // Are we compressed? If so, overview should be too (unless
+    // HFA_COMPRESS_OVR is defined).
+    // Check RasterDMS like HFAGetBandInfo.
+    bool bCompressionType = false;
+    const char *pszCompressOvr = CPLGetConfigOption("HFA_COMPRESS_OVR", NULL);
     if( pszCompressOvr != NULL )
+    {
         bCompressionType = CPLTestBool(pszCompressOvr);
+    }
     else
     {
-        HFAEntry *poDMS = poNode->GetNamedChild( "RasterDMS" );
+        HFAEntry *poDMS = poNode->GetNamedChild("RasterDMS");
 
         if( poDMS != NULL )
-            bCompressionType = poDMS->GetIntField( "compressionType" ) != 0;
+            bCompressionType = poDMS->GetIntField("compressionType") != 0;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the layer.                                               */
-/* -------------------------------------------------------------------- */
+    // Create the layer.
     CPLString osLayerName;
-    osLayerName.Printf( "_ss_%d_", nOverviewLevel );
+    osLayerName.Printf("_ss_%d_", nOverviewLevel);
 
-    if( !HFACreateLayer( psRRDInfo, poParent, osLayerName,
-                         TRUE, 64, bCompressionType, bCreateLargeRaster, FALSE,
-                         nOXSize, nOYSize, eOverviewDataType, NULL,
-                         nValidFlagsOffset, nDataOffset, 1, 0 ) )
+    if( !HFACreateLayer(psRRDInfo, poParent, osLayerName,
+                        TRUE, 64, bCompressionType, bCreateLargeRaster, FALSE,
+                        nOXSize, nOYSize, eOverviewDataType, NULL,
+                        nValidFlagsOffset, nDataOffset, 1, 0) )
         return -1;
 
-    HFAEntry *poOverLayer = poParent->GetNamedChild( osLayerName );
+    HFAEntry *poOverLayer = poParent->GetNamedChild(osLayerName);
     if( poOverLayer == NULL )
         return -1;
 
-/* -------------------------------------------------------------------- */
-/*      Create RRDNamesList list if it does not yet exist.              */
-/* -------------------------------------------------------------------- */
+    // Create RRDNamesList list if it does not yet exist.
     HFAEntry *poRRDNamesList = poNode->GetNamedChild("RRDNamesList");
     if( poRRDNamesList == NULL )
     {
-        poRRDNamesList = HFAEntry::New( psInfo, "RRDNamesList",
-                                       "Eimg_RRDNamesList",
-                                       poNode );
-        poRRDNamesList->MakeData( 23+16+8+ 3000 /* hack for growth room*/ );
+        poRRDNamesList =
+            HFAEntry::New(psInfo, "RRDNamesList", "Eimg_RRDNamesList", poNode);
+        poRRDNamesList->MakeData(23 + 16 + 8 + 3000);  // Hack for growth room.
 
-        /* we need to hardcode file offset into the data, so locate it now */
+        // We need to hardcode file offset into the data, so locate it now.
         poRRDNamesList->SetPosition();
 
-        poRRDNamesList->SetStringField( "algorithm.string",
-                                        "IMAGINE 2X2 Resampling" );
+        poRRDNamesList->SetStringField("algorithm.string",
+                                       "IMAGINE 2X2 Resampling");
     }
 
-/* -------------------------------------------------------------------- */
-/*      Add new overview layer to RRDNamesList.                         */
-/* -------------------------------------------------------------------- */
-    int iNextName = poRRDNamesList->GetFieldCount( "nameList" );
+    // Add new overview layer to RRDNamesList.
+    int iNextName = poRRDNamesList->GetFieldCount("nameList");
     char szName[50];
     CPLString osNodeName;
 
-    snprintf( szName, sizeof(szName), "nameList[%d].string", iNextName );
+    snprintf(szName, sizeof(szName), "nameList[%d].string", iNextName);
 
-    osLayerName.Printf( "%s(:%s:_ss_%d_)",
-                        psRRDInfo->pszFilename, GetBandName(),
-                        nOverviewLevel );
+    osLayerName.Printf("%s(:%s:_ss_%d_)",
+                       psRRDInfo->pszFilename, GetBandName(),
+                       nOverviewLevel);
 
     // TODO: Need to add to end of array (that is pretty hard).
-    if( poRRDNamesList->SetStringField( szName, osLayerName ) != CE_None )
+    if( poRRDNamesList->SetStringField(szName, osLayerName) != CE_None )
     {
-        poRRDNamesList->MakeData( poRRDNamesList->GetDataSize() + 3000 );
-        if( poRRDNamesList->SetStringField( szName, osLayerName ) != CE_None )
+        poRRDNamesList->MakeData(poRRDNamesList->GetDataSize() + 3000);
+        if( poRRDNamesList->SetStringField(szName, osLayerName) != CE_None )
             return -1;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Add to the list of overviews for this band.                     */
-/* -------------------------------------------------------------------- */
-    papoOverviews = (HFABand **)
-        CPLRealloc(papoOverviews, sizeof(void*) * ++nOverviews );
-    papoOverviews[nOverviews-1] = new HFABand( psRRDInfo, poOverLayer );
+    // Add to the list of overviews for this band.
+    papoOverviews = static_cast<HFABand **>(
+        CPLRealloc(papoOverviews, sizeof(void *) * ++nOverviews));
+    papoOverviews[nOverviews - 1] = new HFABand(psRRDInfo, poOverLayer);
 
-/* -------------------------------------------------------------------- */
-/*      If there is a nodata value, copy it to the overview band.       */
-/* -------------------------------------------------------------------- */
+    // If there is a nodata value, copy it to the overview band.
     if( bNoDataSet )
-        papoOverviews[nOverviews-1]->SetNoDataValue( dfNoData );
+        papoOverviews[nOverviews - 1]->SetNoDataValue(dfNoData);
 
-    return nOverviews-1;
+    return nOverviews - 1;
 }
diff --git a/frmts/hfa/hfacompress.cpp b/frmts/hfa/hfacompress.cpp
index 8002332..9ba950b 100644
--- a/frmts/hfa/hfacompress.cpp
+++ b/frmts/hfa/hfacompress.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfacompress.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Name:     hfadataset.cpp
  * Project:  Erdas Imagine Driver
@@ -28,272 +27,293 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfacompress.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <cstddef>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "hfa.h"
+
+CPL_CVSID("$Id: hfacompress.cpp 37890 2017-04-03 19:26:01Z goatbar $");
 
 HFACompress::HFACompress( void *pData, GUInt32 nBlockSize, EPTType eDataType ) :
     m_pData(pData),
     m_nBlockSize(nBlockSize),
+    m_nBlockCount((nBlockSize * 8) / HFAGetDataTypeBits(eDataType)),
     m_eDataType(eDataType),
+    m_nDataTypeNumBits(HFAGetDataTypeBits(eDataType)),
+    m_pCounts(NULL),
     m_pCurrCount(NULL),
     m_nSizeCounts(0),
+    m_pValues(NULL),
     m_pCurrValues(NULL),
     m_nSizeValues(0),
     m_nMin(0),
     m_nNumRuns(0),
     m_nNumBits(0)
 {
-  m_nDataTypeNumBits    = HFAGetDataTypeBits( m_eDataType );
-  m_nBlockCount = (nBlockSize * 8) / m_nDataTypeNumBits;
-
-  /* Allocate some memory for the count and values - probably too big */
-  /* About right for worst case scenario tho */
-  m_pCounts     = (GByte*)VSI_MALLOC_VERBOSE( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
+    // Allocate some memory for the count and values - probably too big.
+    // About right for worst case scenario.
+    m_pCounts = static_cast<GByte *>(
+        VSI_MALLOC_VERBOSE(m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32)));
 
-  m_pValues     = (GByte*)VSI_MALLOC_VERBOSE( m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32) );
+    m_pValues = static_cast<GByte *>(
+        VSI_MALLOC_VERBOSE(m_nBlockCount * sizeof(GUInt32) + sizeof(GUInt32)));
 }
 
 HFACompress::~HFACompress()
 {
-  /* free the compressed data */
-  CPLFree( m_pCounts );
-  CPLFree( m_pValues );
+    // Free the compressed data.
+    CPLFree(m_pCounts);
+    CPLFree(m_pValues);
 }
 
-/* returns the number of bits needed to encode a count */
+// Returns the number of bits needed to encode a count.
 static GByte _FindNumBits( GUInt32 range )
 {
-  if( range < 0xff )
-  {
-    return 8;
-  }
+    if( range < 0xff )
+    {
+        return 8;
+    }
 
-  if( range < 0xffff )
-  {
-    return 16;
-  }
+    if( range < 0xffff )
+    {
+        return 16;
+    }
 
-  return 32;
+    return 32;
 }
 
-/* Gets the value from the uncompressed block as a GUInt32 no matter the data type */
+// Gets the value from the uncompressed block as a GUInt32 no matter
+// the data type.
 GUInt32 HFACompress::valueAsUInt32( GUInt32 iPixel )
 {
-  GUInt32 val = 0;
-
-  if( m_nDataTypeNumBits == 8 )
-  {
-    val = ((GByte*)m_pData)[iPixel];
-  }
-  else if( m_nDataTypeNumBits == 16 )
-  {
-    val = ((GUInt16*)m_pData)[iPixel];
-  }
-  else if( m_nDataTypeNumBits == 32 )
-  {
-    val = ((GUInt32*)m_pData)[iPixel];
-  }
-  else if( m_nDataTypeNumBits == 4 )
-  {
-      if( iPixel % 2 == 0 )
-          val = ((GByte*)m_pData)[iPixel/2] & 0x0f;
-      else
-          val = (((GByte*)m_pData)[iPixel/2] & 0xf0) >> 4;
-  }
-  else if( m_nDataTypeNumBits == 2 )
-  {
-      if( iPixel % 4 == 0 )
-          val = ((GByte*)m_pData)[iPixel/4] & 0x03;
-      else if( iPixel % 4 == 1 )
-          val = (((GByte*)m_pData)[iPixel/4] & 0x0c) >> 2;
-      else if( iPixel % 4 == 2 )
-          val = (((GByte*)m_pData)[iPixel/4] & 0x30) >> 4;
-      else
-          val = (((GByte*)m_pData)[iPixel/4] & 0xc0) >> 6;
-  }
-  else if( m_nDataTypeNumBits == 1 )
-  {
-      if( ((GByte*)m_pData)[iPixel >> 3] & (0x1 << (iPixel & 0x07)) )
-          val = 1;
-      else
-          val = 0;
-  }
-  else
-  {
-    /* Should not get to here - check in compressBlock() should return false if
-    we can't compress this blcok because we don't know about the type */
-    CPLError( CE_Failure, CPLE_FileIO, "Imagine Datatype 0x%x (0x%x bits) not supported\n",
-          m_eDataType,
-          m_nDataTypeNumBits );
-    CPLAssert( FALSE );
-  }
-
-  return val;
+    GUInt32 val = 0;
+
+    if( m_nDataTypeNumBits == 8 )
+    {
+        val = ((GByte *)m_pData)[iPixel];
+    }
+    else if( m_nDataTypeNumBits == 16 )
+    {
+        val = ((GUInt16 *)m_pData)[iPixel];
+    }
+    else if( m_nDataTypeNumBits == 32 )
+    {
+        val = ((GUInt32 *)m_pData)[iPixel];
+    }
+    else if( m_nDataTypeNumBits == 4 )
+    {
+        if( iPixel % 2 == 0 )
+            val = ((GByte *)m_pData)[iPixel / 2] & 0x0f;
+        else
+            val = (((GByte *)m_pData)[iPixel / 2] & 0xf0) >> 4;
+    }
+    else if( m_nDataTypeNumBits == 2 )
+    {
+        if( iPixel % 4 == 0 )
+            val = ((GByte *)m_pData)[iPixel / 4] & 0x03;
+        else if( iPixel % 4 == 1 )
+            val = (((GByte *)m_pData)[iPixel / 4] & 0x0c) >> 2;
+        else if( iPixel % 4 == 2 )
+            val = (((GByte *)m_pData)[iPixel / 4] & 0x30) >> 4;
+        else
+            val = (((GByte *)m_pData)[iPixel / 4] & 0xc0) >> 6;
+    }
+    else if( m_nDataTypeNumBits == 1 )
+    {
+        if( ((GByte *)m_pData)[iPixel >> 3] & (0x1 << (iPixel & 0x07)) )
+            val = 1;
+        else
+            val = 0;
+    }
+    else
+    {
+        // Should not get to here.  Check in compressBlock() should return false
+        // if we can't compress this blcok because we don't know about the type.
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Imagine Datatype 0x%x (0x%x bits) not supported",
+                 m_eDataType,
+                 m_nDataTypeNumBits);
+        CPLAssert(false);
+    }
+
+    return val;
 }
 
-/* Finds the minimum value in a type specific fashion. This value is
-  subtracted from each value in the compressed dataset. The maxmimum
-  value is also found and the number of bits that the range can be stored
-  is also returned. */
-/* TODO: Minimum value returned as pNumBits is now 8 - Imagine
-  can handle 1, 2, and 4 bits as well */
+// Finds the minimum value in a type specific fashion. This value is
+// subtracted from each value in the compressed dataset. The maxmimum
+// value is also found and the number of bits that the range can be stored
+// is also returned.
+//
+// TODO: Minimum value returned as pNumBits is now 8 - Imagine
+// can handle 1, 2, and 4 bits as well.
 GUInt32 HFACompress::findMin( GByte *pNumBits )
 {
-  GUInt32 u32Min = valueAsUInt32( 0 );
-  GUInt32 u32Max = u32Min;
+    GUInt32 u32Min = valueAsUInt32(0);
+    GUInt32 u32Max = u32Min;
 
-  for( GUInt32 count = 1; count < m_nBlockCount; count++ )
-  {
-    GUInt32 u32Val = valueAsUInt32( count );
-    if( u32Val < u32Min )
-      u32Min = u32Val;
-    else if( u32Val > u32Max )
-      u32Max = u32Val;
-  }
+    for( GUInt32 count = 1; count < m_nBlockCount; count++ )
+    {
+        GUInt32 u32Val = valueAsUInt32( count );
+        if( u32Val < u32Min )
+            u32Min = u32Val;
+        else if( u32Val > u32Max )
+            u32Max = u32Val;
+    }
 
-  *pNumBits = _FindNumBits( u32Max - u32Min );
+    *pNumBits = _FindNumBits(u32Max - u32Min);
 
-  return u32Min;
+    return u32Min;
 }
 
-/* Codes the count in the way expected by Imagine - i.e. the lower 2 bits specify how many bytes
-   the count takes up */
-void HFACompress::makeCount( GUInt32 count, GByte *pCounter, GUInt32 *pnSizeCount )
+// Codes the count in the way expected by Imagine - i.e. the lower 2 bits
+// specify how many bytes the count takes up.
+void HFACompress::makeCount( GUInt32 count, GByte *pCounter,
+                             GUInt32 *pnSizeCount )
 {
-  /* Because Imagine stores the number of bits used in the
-      lower 2 bits of the data it restricts what we can use */
-  if( count < 0x40 )
-  {
-    pCounter[0] = (GByte) count;
-    *pnSizeCount = 1;
-  }
-  else if( count < 0x8000 )
-  {
-    pCounter[1] = count & 0xff;
-    count /= 256;
-    pCounter[0] = (GByte) (count | 0x40);
-    *pnSizeCount = 2;
-  }
-  else if( count < 0x800000 )
-  {
-    pCounter[2] = count & 0xff;
-    count /= 256;
-    pCounter[1] = count & 0xff;
-    count /= 256;
-    pCounter[0] = (GByte) (count | 0x80);
-    *pnSizeCount = 3;
-  }
-  else
-  {
-    pCounter[3] = count & 0xff;
-    count /= 256;
-    pCounter[2] = count & 0xff;
-    count /= 256;
-    pCounter[1] = count & 0xff;
-    count /= 256;
-    pCounter[0] = (GByte) (count | 0xc0);
-    *pnSizeCount = 4;
-  }
+    // Because Imagine stores the number of bits used in the lower 2 bits of the
+    // data it restricts what we can use.
+    if( count < 0x40 )
+    {
+        pCounter[0] = static_cast<GByte>(count);
+        *pnSizeCount = 1;
+    }
+    else if( count < 0x8000 )
+    {
+        pCounter[1] = count & 0xff;
+        count /= 256;
+        pCounter[0] = static_cast<GByte>(count | 0x40);
+        *pnSizeCount = 2;
+    }
+    else if( count < 0x800000 )
+    {
+        pCounter[2] = count & 0xff;
+        count /= 256;
+        pCounter[1] = count & 0xff;
+        count /= 256;
+        pCounter[0] = static_cast<GByte>(count | 0x80);
+        *pnSizeCount = 3;
+    }
+    else
+    {
+        pCounter[3] = count & 0xff;
+        count /= 256;
+        pCounter[2] = count & 0xff;
+        count /= 256;
+        pCounter[1] = count & 0xff;
+        count /= 256;
+        pCounter[0] = static_cast<GByte>(count | 0xc0);
+        *pnSizeCount = 4;
+    }
 }
 
-/* Encodes the value depending on the number of bits we are using */
+// Encodes the value depending on the number of bits we are using.
 void HFACompress::encodeValue( GUInt32 val, GUInt32 repeat )
 {
-  GUInt32 nSizeCount;
-
-  makeCount( repeat, m_pCurrCount, &nSizeCount );
-  m_pCurrCount += nSizeCount;
-  if( m_nNumBits == 8 )
-  {
-    /* Only storing 8 bits per value as the range is small */
-    *(GByte*)m_pCurrValues = GByte(val - m_nMin);
-    m_pCurrValues += sizeof( GByte );
-  }
-  else if( m_nNumBits == 16 )
-  {
-    /* Only storing 16 bits per value as the range is small */
-    *(GUInt16*)m_pCurrValues = GUInt16(val - m_nMin);
+    GUInt32 nSizeCount = 0;
+
+    makeCount(repeat, m_pCurrCount, &nSizeCount);
+    m_pCurrCount += nSizeCount;
+    if( m_nNumBits == 8 )
+    {
+        // Only storing 8 bits per value as the range is small.
+        *(GByte*)m_pCurrValues = GByte(val - m_nMin);
+        m_pCurrValues += sizeof(GByte);
+    }
+    else if( m_nNumBits == 16 )
+    {
+        // Only storing 16 bits per value as the range is small.
+        *(GUInt16 *)m_pCurrValues = GUInt16(val - m_nMin);
 #ifndef CPL_MSB
-   CPL_SWAP16PTR( m_pCurrValues );
-#endif /* ndef CPL_MSB */
-    m_pCurrValues += sizeof( GUInt16 );
-  }
-  else
-  {
-    *(GUInt32*)m_pCurrValues = GUInt32(val - m_nMin);
+        CPL_SWAP16PTR(m_pCurrValues);
+#endif  // ndef CPL_MSB
+        m_pCurrValues += sizeof(GUInt16);
+    }
+    else
+    {
+        *(GUInt32 *)m_pCurrValues = GUInt32(val - m_nMin);
 #ifndef CPL_MSB
-   CPL_SWAP32PTR( m_pCurrValues );
-#endif /* ndef CPL_MSB */
-    m_pCurrValues += sizeof( GUInt32 );
-  }
+        CPL_SWAP32PTR(m_pCurrValues);
+#endif  // ndef CPL_MSB
+        m_pCurrValues += sizeof(GUInt32);
+    }
 }
 
-/* This is the guts of the file - call this to compress the block */
-/* returns false if the compression fails - i.e. compressed block bigger than input */
+// This is the guts of the file - call this to compress the block returns false
+// if the compression fails - i.e. compressed block bigger than input.
 bool HFACompress::compressBlock()
 {
-  GUInt32 nLastUnique = 0;
-
-  /* Check we know about the datatype to be compressed.
-     If we can't compress it we should return false so that
-     the block cannot be compressed (we can handle just about
-     any type uncompressed). */
-  if( ! QueryDataTypeSupported( m_eDataType ) )
-  {
-    CPLDebug( "HFA", "Cannot compress HFA datatype 0x%x (0x%x bits). "
-              "Writing uncompressed instead.\n",
-              m_eDataType,
-              m_nDataTypeNumBits );
-    return false;
-  }
-
-  /* reset our pointers */
-  m_pCurrCount  = m_pCounts;
-  m_pCurrValues = m_pValues;
-
-  /* Get the minimum value.  this can be subtracted from each value in
-     the image. */
-  m_nMin = findMin( &m_nNumBits );
-
-  /* Go through the block. */
-  GUInt32 u32Last = valueAsUInt32( 0 );
-  for( GUInt32 count = 1; count < m_nBlockCount; count++ )
-  {
-    GUInt32 u32Val = valueAsUInt32( count );
-    if( u32Val != u32Last )
-    {
-      /* The values have changed - i.e. a run has come to and end */
-      encodeValue( u32Last, count - nLastUnique );
+    GUInt32 nLastUnique = 0;
 
-      if( ( m_pCurrValues - m_pValues ) > (int) m_nBlockSize )
-      {
+    // Check we know about the datatype to be compressed.
+    // If we can't compress it we should return false so that
+    // the block cannot be compressed (we can handle just about
+    // any type uncompressed).
+    if( !QueryDataTypeSupported(m_eDataType) )
+    {
+        CPLDebug("HFA", "Cannot compress HFA datatype 0x%x (0x%x bits). "
+                 "Writing uncompressed instead.",
+                 m_eDataType,
+                 m_nDataTypeNumBits);
         return false;
-      }
+    }
+
+    // Reset our pointers.
+    m_pCurrCount = m_pCounts;
+    m_pCurrValues = m_pValues;
+
+    // Get the minimum value.  this can be subtracted from each value in
+    // the image.
+    m_nMin = findMin(&m_nNumBits);
+
+    // Go through the block.
+    GUInt32 u32Last = valueAsUInt32(0);
+    for( GUInt32 count = 1; count < m_nBlockCount; count++ )
+    {
+        const GUInt32 u32Val = valueAsUInt32(count);
+        if( u32Val != u32Last )
+        {
+            // The values have changed - i.e. a run has come to and end.
+            encodeValue(u32Last, count - nLastUnique);
+
+            if( (m_pCurrValues - m_pValues) > static_cast<int>(m_nBlockSize) )
+            {
+                return false;
+            }
 
-      m_nNumRuns++;
-      u32Last = u32Val;
-      nLastUnique = count;
+            m_nNumRuns++;
+            u32Last = u32Val;
+            nLastUnique = count;
+        }
     }
-  }
 
-  /* OK we have done the block but have not got the last run because we
-     were only looking for a change in values */
-  encodeValue( u32Last, m_nBlockCount - nLastUnique );
-  m_nNumRuns++;
+    // We have done the block but have not got the last run because we
+    // were only looking for a change in values.
+    encodeValue(u32Last, m_nBlockCount - nLastUnique);
+    m_nNumRuns++;
 
-  /* set the size variables */
-  m_nSizeCounts = static_cast<GUInt32>(m_pCurrCount - m_pCounts);
-  m_nSizeValues = static_cast<GUInt32>(m_pCurrValues - m_pValues);
+    // Set the size variables.
+    m_nSizeCounts = static_cast<GUInt32>(m_pCurrCount - m_pCounts);
+    m_nSizeValues = static_cast<GUInt32>(m_pCurrValues - m_pValues);
 
-  // The 13 is for the header size - maybe this should live with some constants somewhere?
-  return ( m_nSizeCounts +  m_nSizeValues + 13 ) < m_nBlockSize;
+    // The 13 is for the header size - maybe this should live with some
+    // constants somewhere?
+    return (m_nSizeCounts + m_nSizeValues + 13) < m_nBlockSize;
 }
 
 bool HFACompress::QueryDataTypeSupported( EPTType eHFADataType )
 {
-  int nBits = HFAGetDataTypeBits( eHFADataType );
+    const int nBits = HFAGetDataTypeBits(eHFADataType);
 
-  return ( nBits == 8 ) || ( nBits == 16 ) || ( nBits == 32 ) || (nBits == 4)
-      || (nBits == 2) || (nBits == 1);
+    return
+        nBits == 1 ||
+        nBits == 2 ||
+        nBits == 4 ||
+        nBits == 8 ||
+        nBits == 16 ||
+        nBits == 32;
 }
diff --git a/frmts/hfa/hfadataset.cpp b/frmts/hfa/hfadataset.cpp
index 64022c3..9cbf24c 100644
--- a/frmts/hfa/hfadataset.cpp
+++ b/frmts/hfa/hfadataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Name:     hfadataset.cpp
  * Project:  Erdas Imagine Driver
@@ -29,27 +28,53 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "hfadataset.h"
+#include "hfa_p.h"
+
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
 #include "gdal_rat.h"
-#include "hfa_p.h"
+#include "hfa.h"
+#include "ogr_core.h"
 #include "ogr_spatialref.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: hfadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: hfadataset.cpp 37967 2017-04-12 03:44:05Z goatbar $");
 
-#ifndef R2D
-#  define R2D	(180/M_PI)
-#endif
-#ifndef D2R
-#  define D2R	(M_PI/180)
-#endif
+static const double R2D = 180.0 / M_PI;
+static const double D2R = M_PI / 180.0;
 
-int WritePeStringIfNeeded(OGRSpatialReference* poSRS, HFAHandle hHFA);
-void ClearSR(HFAHandle hHFA);
+static const double ARCSEC2RAD = M_PI / 648000.0;
+static const double RAD2ARCSEC = 648000.0 / M_PI;
 
-static const char * const apszDatumMap[] = {
-    /* Imagine name, WKT name */
+int WritePeStringIfNeeded( OGRSpatialReference *poSRS, HFAHandle hHFA );
+void ClearSR( HFAHandle hHFA );
+
+static const char *const apszDatumMap[] = {
+    // Imagine name, WKT name.
     "NAD27", "North_American_Datum_1927",
     "NAD83", "North_American_Datum_1983",
     "WGS 84", "WGS_1984",
@@ -58,7 +83,7 @@ static const char * const apszDatumMap[] = {
     NULL, NULL
 };
 
-static const char * const apszUnitMap[] = {
+static const char *const apszUnitMap[] = {
     "meters", "1.0",
     "meter", "1.0",
     "m", "1.0",
@@ -96,7 +121,6 @@ static const char * const apszUnitMap[] = {
     NULL, NULL
 };
 
-
 /* ==================================================================== */
 /*      Table relating USGS and ESRI state plane zones.                 */
 /* ==================================================================== */
@@ -244,374 +268,119 @@ static const int anUsgsEsriZones[] =
  5400,    0
 };
 
-
-/************************************************************************/
-/* ==================================================================== */
-/*				HFADataset				*/
-/* ==================================================================== */
-/************************************************************************/
-
-class HFARasterBand;
-
-class HFADataset CPL_FINAL : public GDALPamDataset
-{
-    friend class HFARasterBand;
-
-    HFAHandle	hHFA;
-
-    int         bMetadataDirty;
-
-    int         bGeoDirty;
-    double      adfGeoTransform[6];
-    char	*pszProjection;
-
-    int         bIgnoreUTM;
-
-    CPLErr      ReadProjection();
-    CPLErr      WriteProjection();
-    int         bForceToPEString;
-
-    int		nGCPCount;
-    GDAL_GCP	asGCPList[36];
-
-    void        UseXFormStack( int nStepCount,
-                               Efga_Polynomial *pasPolyListForward,
-                               Efga_Polynomial *pasPolyListReverse );
-
-  protected:
-    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
-                              void *, int, int, GDALDataType,
-                              int, int *,
-                              GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
-
-  public:
-                HFADataset();
-                ~HFADataset();
-
-    static int          Identify( GDALOpenInfo * );
-    static CPLErr       Rename( const char *pszNewName, const char *pszOldName);
-    static CPLErr       CopyFiles( const char *pszNewName, const char *pszOldName);
-    static GDALDataset *Open( GDALOpenInfo * );
-    static GDALDataset *Create( const char * pszFilename,
-                                int nXSize, int nYSize, int nBands,
-                                GDALDataType eType, char ** papszParmList );
-    static GDALDataset *CreateCopy( const char * pszFilename,
-                                    GDALDataset *poSrcDS,
-                                    int bStrict, char ** papszOptions,
-                                    GDALProgressFunc pfnProgress,
-                                    void * pProgressData );
-    static CPLErr       Delete( const char *pszFilename );
-
-    virtual char **GetFileList(void);
-
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
-
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-
-    virtual CPLErr SetMetadata( char **, const char * = "" );
-    virtual CPLErr SetMetadataItem( const char *, const char *, const char * = "" );
-
-    virtual void   FlushCache( void );
-    virtual CPLErr IBuildOverviews( const char *pszResampling,
-                                    int nOverviews, int *panOverviewList,
-                                    int nListBands, int *panBandList,
-                                    GDALProgressFunc pfnProgress,
-                                    void * pProgressData );
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            HFARasterBand                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class HFARasterBand CPL_FINAL : public GDALPamRasterBand
-{
-    friend class HFADataset;
-    friend class HFARasterAttributeTable;
-
-    GDALColorTable *poCT;
-
-    EPTType	eHFADataType;
-
-    int         nOverviews;
-    int		nThisOverview;
-    HFARasterBand **papoOverviewBands;
-
-    CPLErr      CleanOverviews();
-
-    HFAHandle	hHFA;
-
-    int         bMetadataDirty;
-
-    GDALRasterAttributeTable *poDefaultRAT;
-
-    void        ReadAuxMetadata();
-    void        ReadHistogramMetadata();
-    void        EstablishOverviews();
-    CPLErr      WriteNamedRAT( const char *pszName, const GDALRasterAttributeTable *poRAT );
-
-
-  public:
-
-                   HFARasterBand( HFADataset *, int, int );
-    virtual        ~HFARasterBand();
-
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
-
-    virtual const char *GetDescription() const;
-    virtual void        SetDescription( const char * );
-
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual CPLErr          SetColorTable( GDALColorTable * );
-    virtual int    GetOverviewCount();
-    virtual GDALRasterBand *GetOverview( int );
-
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum(int *pbSuccess = NULL );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr SetNoDataValue( double dfValue );
-
-    virtual CPLErr SetMetadata( char **, const char * = "" );
-    virtual CPLErr SetMetadataItem( const char *, const char *, const char * = "" );
-    virtual CPLErr BuildOverviews( const char *, int, int *,
-                                   GDALProgressFunc, void * );
-
-    virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
-                                        int *pnBuckets, GUIntBig ** ppanHistogram,
-                                        int bForce,
-                                        GDALProgressFunc, void *pProgressData);
-
-    virtual GDALRasterAttributeTable *GetDefaultRAT();
-    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
-};
-
-class HFAAttributeField
-{
-public:
-    CPLString         sName;
-    GDALRATFieldType  eType;
-    GDALRATFieldUsage eUsage;
-    int               nDataOffset;
-    int               nElementSize;
-    HFAEntry         *poColumn;
-    int               bIsBinValues; // handled differently
-    int               bConvertColors; // map 0-1 floats to 0-255 ints
-};
-
-class HFARasterAttributeTable CPL_FINAL : public GDALRasterAttributeTable
-{
-private:
-
-    HFAHandle	hHFA;
-    HFAEntry   *poDT;
-    CPLString   osName;
-    int         nBand;
-    GDALAccess  eAccess;
-
-    std::vector<HFAAttributeField>  aoFields;
-    int         nRows;
-
-    int bLinearBinning;
-    double dfRow0Min;
-    double dfBinSize;
-
-    CPLString osWorkingResult;
-
-    void AddColumn(const char *pszName, GDALRATFieldType eType, GDALRATFieldUsage eUsage,
-                int nDataOffset, int nElementSize, HFAEntry *poColumn, int bIsBinValues=FALSE,
-                int bConvertColors=FALSE)
-    {
-        HFAAttributeField aField;
-        aField.sName = pszName;
-        aField.eType = eType;
-        aField.eUsage = eUsage;
-        aField.nDataOffset = nDataOffset;
-        aField.nElementSize = nElementSize;
-        aField.poColumn = poColumn;
-        aField.bIsBinValues = bIsBinValues;
-        aField.bConvertColors = bConvertColors;
-
-        this->aoFields.push_back(aField);
-    }
-
-    void CreateDT()
-    {
-        poDT = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
-                              osName, "Edsc_Table",
-                              hHFA->papoBand[nBand-1]->poNode );
-        poDT->SetIntField( "numrows", nRows );
-    }
-
-public:
-    HFARasterAttributeTable(HFARasterBand *poBand, const char *pszName);
-    ~HFARasterAttributeTable();
-
-    GDALDefaultRasterAttributeTable *Clone() const;
-
-    virtual int           GetColumnCount() const;
-
-    virtual const char   *GetNameOfCol( int ) const;
-    virtual GDALRATFieldUsage GetUsageOfCol( int ) const;
-    virtual GDALRATFieldType GetTypeOfCol( int ) const;
-
-    virtual int           GetColOfUsage( GDALRATFieldUsage ) const;
-
-    virtual int           GetRowCount() const;
-
-    virtual const char   *GetValueAsString( int iRow, int iField ) const;
-    virtual int           GetValueAsInt( int iRow, int iField ) const;
-    virtual double        GetValueAsDouble( int iRow, int iField ) const;
-
-    virtual void          SetValue( int iRow, int iField, const char *pszValue );
-    virtual void          SetValue( int iRow, int iField, double dfValue);
-    virtual void          SetValue( int iRow, int iField, int nValue );
-
-    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData);
-    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData);
-    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList);
-
-    virtual int           ChangesAreWrittenToFile();
-    virtual void          SetRowCount( int iCount );
-
-    virtual int           GetRowOfValue( double dfValue ) const;
-    virtual int           GetRowOfValue( int nValue ) const;
-
-    virtual CPLErr        CreateColumn( const char *pszFieldName,
-                                GDALRATFieldType eFieldType,
-                                GDALRATFieldUsage eFieldUsage );
-    virtual CPLErr        SetLinearBinning( double dfRow0Min, double dfBinSize );
-    virtual int           GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const;
-
-    virtual CPLXMLNode   *Serialize() const;
-
-protected:
-    CPLErr                ColorsIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData);
-};
-
 /************************************************************************/
 /*                     HFARasterAttributeTable()                        */
 /************************************************************************/
 
-HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const char *pszName) :
+HFARasterAttributeTable::HFARasterAttributeTable(
+    HFARasterBand *poBand, const char *pszName) :
+    hHFA(poBand->hHFA),
+    poDT(poBand->hHFA->papoBand[poBand->nBand-1]->
+         poNode->GetNamedChild(pszName)),
+    osName(pszName),
+    nBand(poBand->nBand),
+    eAccess(poBand->GetAccess()),
+    nRows(0),
+    bLinearBinning(false),
     dfRow0Min(0.0),
     dfBinSize(0.0)
 {
-    this->hHFA = poBand->hHFA;
-    this->poDT = poBand->hHFA->papoBand[poBand->nBand-1]->poNode->GetNamedChild(pszName);
-    this->nBand = poBand->nBand;
-    this->eAccess = poBand->GetAccess();
-    this->osName = pszName;
-    this->nRows = 0;
-    this->bLinearBinning = FALSE;
-
-    if( this->poDT != NULL )
+    if( poDT != NULL )
     {
-        this->nRows = this->poDT->GetIntField( "numRows" );
+        nRows = poDT->GetIntField("numRows");
 
-/* -------------------------------------------------------------------- */
-/*      Scan under table for columns.                                   */
-/* -------------------------------------------------------------------- */
+        // Scan under table for columns.
         for( HFAEntry *poDTChild = poDT->GetChild();
              poDTChild != NULL;
              poDTChild = poDTChild->GetNext() )
         {
-            if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction") )
+            if( EQUAL(poDTChild->GetType(), "Edsc_BinFunction") )
             {
-                const double dfMax = poDTChild->GetDoubleField( "maxLimit" );
-                const double dfMin = poDTChild->GetDoubleField( "minLimit" );
-                const int nBinCount = poDTChild->GetIntField( "numBins" );
+                const double dfMax = poDTChild->GetDoubleField("maxLimit");
+                const double dfMin = poDTChild->GetDoubleField("minLimit");
+                const int nBinCount = poDTChild->GetIntField("numBins");
 
-                if( nBinCount == this->nRows
-                    && dfMax != dfMin && nBinCount != 0 )
+                if( nBinCount == nRows && dfMax != dfMin && nBinCount != 0 )
                 {
-                    // can't call SetLinearBinning since it will re-write
-                    // which we might not have permission to do
-                    this->bLinearBinning = TRUE;
-                    this->dfRow0Min = dfMin;
-                    this->dfBinSize = (dfMax-dfMin) / (nBinCount-1);
+                    // Can't call SetLinearBinning since it will re-write
+                    // which we might not have permission to do.
+                    bLinearBinning = true;
+                    dfRow0Min = dfMin;
+                    dfBinSize = (dfMax - dfMin) / (nBinCount - 1);
                 }
             }
 
-            if( EQUAL(poDTChild->GetType(),"Edsc_BinFunction840") )
+            if( EQUAL(poDTChild->GetType(), "Edsc_BinFunction840") )
             {
-                const char* pszValue =
-                    poDTChild->GetStringField( "binFunction.type.string" );
+                const char *pszValue =
+                    poDTChild->GetStringField("binFunction.type.string");
                 if( pszValue && EQUAL(pszValue, "BFUnique") )
                 {
-                    AddColumn( "BinValues", GFT_Real, GFU_MinMax, 0, 0, poDTChild, TRUE);
+                    AddColumn("BinValues", GFT_Real, GFU_MinMax, 0, 0,
+                              poDTChild, true);
                 }
             }
 
-            if( !EQUAL(poDTChild->GetType(),"Edsc_Column") )
+            if( !EQUAL(poDTChild->GetType(), "Edsc_Column") )
                 continue;
 
-            const int nOffset = poDTChild->GetIntField( "columnDataPtr" );
-            const char *pszType = poDTChild->GetStringField( "dataType" );
+            const int nOffset = poDTChild->GetIntField("columnDataPtr");
+            const char *pszType = poDTChild->GetStringField("dataType");
             GDALRATFieldUsage eUsage = GFU_Generic;
-            int bConvertColors = FALSE;
+            bool bConvertColors = false;
 
             if( pszType == NULL || nOffset == 0 )
                 continue;
 
             GDALRATFieldType eType;
-            if( EQUAL(pszType,"real") )
+            if( EQUAL(pszType, "real") )
                 eType = GFT_Real;
-            else if( EQUAL(pszType,"string") )
+            else if( EQUAL(pszType, "string") )
                 eType = GFT_String;
             else if( STARTS_WITH_CI(pszType, "int") )
                 eType = GFT_Integer;
             else
                 continue;
 
-            if( EQUAL(poDTChild->GetName(),"Histogram") )
+            if( EQUAL(poDTChild->GetName(), "Histogram") )
                 eUsage = GFU_PixelCount;
-            else if( EQUAL(poDTChild->GetName(),"Red") )
+            else if( EQUAL(poDTChild->GetName(), "Red") )
             {
                 eUsage = GFU_Red;
-                // treat color columns as ints regardless
-                // of how they are stored
-                bConvertColors = (eType == GFT_Real);
+                // Treat color columns as ints regardless
+                // of how they are stored.
+                bConvertColors = eType == GFT_Real;
                 eType = GFT_Integer;
             }
-            else if( EQUAL(poDTChild->GetName(),"Green") )
+            else if( EQUAL(poDTChild->GetName(), "Green") )
             {
                 eUsage = GFU_Green;
-                bConvertColors = (eType == GFT_Real);
+                bConvertColors = eType == GFT_Real;
                 eType = GFT_Integer;
             }
-            else if( EQUAL(poDTChild->GetName(),"Blue") )
+            else if( EQUAL(poDTChild->GetName(), "Blue") )
             {
                 eUsage = GFU_Blue;
-                bConvertColors = (eType == GFT_Real);
+                bConvertColors = eType == GFT_Real;
                 eType = GFT_Integer;
             }
-            else if( EQUAL(poDTChild->GetName(),"Opacity") )
+            else if( EQUAL(poDTChild->GetName(), "Opacity") )
             {
                 eUsage = GFU_Alpha;
-                bConvertColors = (eType == GFT_Real);
+                bConvertColors = eType == GFT_Real;
                 eType = GFT_Integer;
             }
-            else if( EQUAL(poDTChild->GetName(),"Class_Names") )
+            else if( EQUAL(poDTChild->GetName(), "Class_Names") )
                 eUsage = GFU_Name;
 
             if( eType == GFT_Real )
             {
-                AddColumn(poDTChild->GetName(), GFT_Real, eUsage, nOffset, sizeof(double), poDTChild);
+                AddColumn(poDTChild->GetName(), GFT_Real, eUsage,
+                          nOffset, sizeof(double), poDTChild);
             }
             else if( eType == GFT_String )
             {
-                int nMaxNumChars = poDTChild->GetIntField( "maxNumChars" );
+                int nMaxNumChars = poDTChild->GetIntField("maxNumChars");
                 if( nMaxNumChars <= 0 )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
@@ -619,15 +388,17 @@ HFARasterAttributeTable::HFARasterAttributeTable(HFARasterBand *poBand, const ch
                              nMaxNumChars, poDTChild->GetName());
                     nMaxNumChars = 1;
                 }
-                AddColumn(poDTChild->GetName(), GFT_String, eUsage, nOffset, nMaxNumChars, poDTChild);
+                AddColumn(poDTChild->GetName(), GFT_String, eUsage,
+                          nOffset, nMaxNumChars, poDTChild);
             }
             else if( eType == GFT_Integer )
             {
                 int nSize = sizeof(GInt32);
                 if( bConvertColors )
                     nSize = sizeof(double);
-                AddColumn(poDTChild->GetName(), GFT_Integer, eUsage, nOffset, nSize, poDTChild,
-                                        FALSE, bConvertColors);
+                AddColumn(poDTChild->GetName(), GFT_Integer,
+                          eUsage, nOffset, nSize, poDTChild,
+                          false, bConvertColors);
             }
         }
     }
@@ -645,34 +416,37 @@ HFARasterAttributeTable::~HFARasterAttributeTable() {}
 
 GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
 {
-    if( ( GetRowCount() * GetColumnCount() ) > RAT_MAX_ELEM_FOR_CLONE )
+    if( (GetRowCount() * GetColumnCount()) > RAT_MAX_ELEM_FOR_CLONE )
         return NULL;
 
-    GDALDefaultRasterAttributeTable *poRAT = new GDALDefaultRasterAttributeTable();
+    GDALDefaultRasterAttributeTable *poRAT =
+        new GDALDefaultRasterAttributeTable();
 
-    for( int iCol = 0; iCol < (int)aoFields.size(); iCol++)
+    for( int iCol = 0; iCol < static_cast<int>(aoFields.size()); iCol++)
     {
-        poRAT->CreateColumn(aoFields[iCol].sName, aoFields[iCol].eType, aoFields[iCol].eUsage);
-        poRAT->SetRowCount(this->nRows);
+        poRAT->CreateColumn(aoFields[iCol].sName, aoFields[iCol].eType,
+                            aoFields[iCol].eUsage);
+        poRAT->SetRowCount(nRows);
 
         if( aoFields[iCol].eType == GFT_Integer )
         {
-            int *panColData = (int*)VSI_MALLOC2_VERBOSE(sizeof(int), this->nRows);
+            int *panColData =
+                static_cast<int *>(VSI_MALLOC2_VERBOSE(sizeof(int), nRows));
             if( panColData == NULL )
             {
                 delete poRAT;
                 return NULL;
             }
 
-            if( ((GDALDefaultRasterAttributeTable*)this)->
-                        ValuesIO(GF_Read, iCol, 0, this->nRows, panColData ) != CE_None )
+            if( ((GDALDefaultRasterAttributeTable *)this)
+                    ->ValuesIO(GF_Read, iCol, 0, nRows, panColData) != CE_None )
             {
                 CPLFree(panColData);
                 delete poRAT;
                 return NULL;
             }
 
-            for( int iRow = 0; iRow < this->nRows; iRow++ )
+            for( int iRow = 0; iRow < nRows; iRow++ )
             {
                 poRAT->SetValue(iRow, iCol, panColData[iRow]);
             }
@@ -680,22 +454,23 @@ GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
         }
         if( aoFields[iCol].eType == GFT_Real )
         {
-            double *padfColData = (double*)VSI_MALLOC2_VERBOSE(sizeof(double), this->nRows);
+            double *padfColData = static_cast<double *>(
+                VSI_MALLOC2_VERBOSE(sizeof(double), nRows));
             if( padfColData == NULL )
             {
                 delete poRAT;
                 return NULL;
             }
 
-            if( ((GDALDefaultRasterAttributeTable*)this)->
-                        ValuesIO(GF_Read, iCol, 0, this->nRows, padfColData ) != CE_None )
+            if( ((GDALDefaultRasterAttributeTable *)this)
+                    ->ValuesIO(GF_Read, iCol, 0, nRows, padfColData) != CE_None )
             {
                 CPLFree(padfColData);
                 delete poRAT;
                 return NULL;
             }
 
-            for( int iRow = 0; iRow < this->nRows; iRow++ )
+            for( int iRow = 0; iRow < nRows; iRow++ )
             {
                 poRAT->SetValue(iRow, iCol, padfColData[iRow]);
             }
@@ -703,22 +478,23 @@ GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
         }
         if( aoFields[iCol].eType == GFT_String )
         {
-            char **papszColData = (char**)VSI_MALLOC2_VERBOSE(sizeof(char*), this->nRows);
+            char **papszColData = static_cast<char **>(
+                VSI_MALLOC2_VERBOSE(sizeof(char *), nRows));
             if( papszColData == NULL )
             {
                 delete poRAT;
                 return NULL;
             }
 
-            if( ((GDALDefaultRasterAttributeTable*)this)->
-                    ValuesIO(GF_Read, iCol, 0, this->nRows, papszColData ) != CE_None )
+            if( ((GDALDefaultRasterAttributeTable *)this)
+                    ->ValuesIO(GF_Read, iCol, 0, nRows, papszColData) != CE_None )
             {
                 CPLFree(papszColData);
                 delete poRAT;
                 return NULL;
             }
 
-            for( int iRow = 0; iRow < this->nRows; iRow++ )
+            for( int iRow = 0; iRow < nRows; iRow++ )
             {
                 poRAT->SetValue(iRow, iCol, papszColData[iRow]);
                 CPLFree(papszColData[iRow]);
@@ -727,8 +503,8 @@ GDALDefaultRasterAttributeTable *HFARasterAttributeTable::Clone() const
         }
     }
 
-    if( this->bLinearBinning )
-        poRAT->SetLinearBinning( this->dfRow0Min, this->dfBinSize );
+    if( bLinearBinning )
+        poRAT->SetLinearBinning(dfRow0Min, dfBinSize);
 
     return poRAT;
 }
@@ -748,10 +524,10 @@ int HFARasterAttributeTable::GetColumnCount() const
 
 const char *HFARasterAttributeTable::GetNameOfCol( int nCol ) const
 {
-    if( ( nCol < 0 ) || ( nCol >= (int)this->aoFields.size() ) )
+    if( nCol < 0 || nCol >= static_cast<int>(aoFields.size()) )
         return NULL;
 
-    return this->aoFields[nCol].sName;
+    return aoFields[nCol].sName;
 }
 
 /************************************************************************/
@@ -760,10 +536,10 @@ const char *HFARasterAttributeTable::GetNameOfCol( int nCol ) const
 
 GDALRATFieldUsage HFARasterAttributeTable::GetUsageOfCol( int nCol ) const
 {
-    if( ( nCol < 0 ) || ( nCol >= (int)this->aoFields.size() ) )
+    if( nCol < 0 || nCol >= static_cast<int>(aoFields.size()) )
         return GFU_Generic;
 
-    return this->aoFields[nCol].eUsage;
+    return aoFields[nCol].eUsage;
 }
 
 /************************************************************************/
@@ -772,10 +548,10 @@ GDALRATFieldUsage HFARasterAttributeTable::GetUsageOfCol( int nCol ) const
 
 GDALRATFieldType HFARasterAttributeTable::GetTypeOfCol( int nCol ) const
 {
-    if( ( nCol < 0 ) || ( nCol >= (int)this->aoFields.size() ) )
+    if( nCol < 0 || nCol >= static_cast<int>(aoFields.size()) )
         return GFT_Integer;
 
-    return this->aoFields[nCol].eType;
+    return aoFields[nCol].eType;
 }
 
 /************************************************************************/
@@ -784,39 +560,36 @@ GDALRATFieldType HFARasterAttributeTable::GetTypeOfCol( int nCol ) const
 
 int HFARasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) const
 {
-    for( unsigned int i = 0; i < this->aoFields.size(); i++ )
+    for( unsigned int i = 0; i < aoFields.size(); i++ )
     {
-        if( this->aoFields[i].eUsage == eUsage )
+        if( aoFields[i].eUsage == eUsage )
             return i;
     }
 
     return -1;
-
 }
 /************************************************************************/
 /*                          GetRowCount()                               */
 /************************************************************************/
 
-int HFARasterAttributeTable::GetRowCount() const
-{
-    return this->nRows;
-}
+int HFARasterAttributeTable::GetRowCount() const { return nRows; }
 
 /************************************************************************/
 /*                      GetValueAsString()                              */
 /************************************************************************/
 
-const char *HFARasterAttributeTable::GetValueAsString( int iRow, int iField ) const
+const char *HFARasterAttributeTable::GetValueAsString( int iRow,
+                                                       int iField ) const
 {
-    // Get ValuesIO do do the work
+    // Get ValuesIO do do the work.
     char *apszStrList[1] = { NULL };
-    if( ((HFARasterAttributeTable*)this)->
-                ValuesIO(GF_Read, iField, iRow, 1, apszStrList ) != CE_None )
+    if( ((HFARasterAttributeTable *)this)
+            ->ValuesIO(GF_Read, iField, iRow, 1, apszStrList) != CE_None )
     {
         return "";
     }
 
-    ((HFARasterAttributeTable *) this)->osWorkingResult = apszStrList[0];
+    ((HFARasterAttributeTable *)this)->osWorkingResult = apszStrList[0];
     CPLFree(apszStrList[0]);
 
     return osWorkingResult;
@@ -828,10 +601,10 @@ const char *HFARasterAttributeTable::GetValueAsString( int iRow, int iField ) co
 
 int HFARasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
 {
-    // Get ValuesIO do do the work
+    // Get ValuesIO do do the work.
     int nValue = 0;
-    if( ((HFARasterAttributeTable*)this)->
-                ValuesIO(GF_Read, iField, iRow, 1, &nValue ) != CE_None )
+    if( ((HFARasterAttributeTable *)this)
+            ->ValuesIO(GF_Read, iField, iRow, 1, &nValue) != CE_None )
     {
         return 0;
     }
@@ -845,12 +618,12 @@ int HFARasterAttributeTable::GetValueAsInt( int iRow, int iField ) const
 
 double HFARasterAttributeTable::GetValueAsDouble( int iRow, int iField ) const
 {
-    // Get ValuesIO do do the work
+    // Get ValuesIO do do the work.
     double dfValue = 0.0;
-    if( ((HFARasterAttributeTable*)this)->
-                ValuesIO(GF_Read, iField, iRow, 1, &dfValue ) != CE_None )
+    if( ((HFARasterAttributeTable *)this)
+            ->ValuesIO(GF_Read, iField, iRow, 1, &dfValue) != CE_None )
     {
-        return 0;
+        return 0.0;
     }
 
     return dfValue;
@@ -860,20 +633,21 @@ double HFARasterAttributeTable::GetValueAsDouble( int iRow, int iField ) const
 /*                          SetValue()                                  */
 /************************************************************************/
 
-void HFARasterAttributeTable::SetValue( int iRow, int iField, const char *pszValue )
+void HFARasterAttributeTable::SetValue( int iRow, int iField,
+                                        const char *pszValue )
 {
-    // Get ValuesIO do do the work
-    ValuesIO(GF_Write, iField, iRow, 1, (char**)&pszValue );
+    // Get ValuesIO do do the work.
+    ValuesIO(GF_Write, iField, iRow, 1, (char **)&pszValue);
 }
 
 /************************************************************************/
 /*                          SetValue()                                  */
 /************************************************************************/
 
-void HFARasterAttributeTable::SetValue( int iRow, int iField, double dfValue)
+void HFARasterAttributeTable::SetValue( int iRow, int iField, double dfValue )
 {
-    // Get ValuesIO do do the work
-    ValuesIO(GF_Write, iField, iRow, 1, &dfValue );
+    // Get ValuesIO do do the work.
+    ValuesIO(GF_Write, iField, iRow, 1, &dfValue);
 }
 
 /************************************************************************/
@@ -882,45 +656,49 @@ void HFARasterAttributeTable::SetValue( int iRow, int iField, double dfValue)
 
 void HFARasterAttributeTable::SetValue( int iRow, int iField, int nValue )
 {
-    // Get ValuesIO do do the work
-    ValuesIO(GF_Write, iField, iRow, 1, &nValue );
+    // Get ValuesIO do do the work.
+    ValuesIO(GF_Write, iField, iRow, 1, &nValue);
 }
 
 /************************************************************************/
 /*                          ValuesIO()                                  */
 /************************************************************************/
 
-CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData)
+CPLErr HFARasterAttributeTable::ValuesIO( GDALRWFlag eRWFlag, int iField,
+                                          int iStartRow, int iLength,
+                                          double *pdfData )
 {
-    if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
+    if( eRWFlag == GF_Write && eAccess == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
-            "Dataset not open in update mode");
+        CPLError(CE_Failure, CPLE_NoWriteAccess,
+                 "Dataset not open in update mode");
         return CE_Failure;
     }
 
-    if( iField < 0 || iField >= (int) aoFields.size() )
+    if( iField < 0 || iField >= static_cast<int>(aoFields.size()) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iField (%d) out of range.", iField );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "iField (%d) out of range.", iField);
 
         return CE_Failure;
     }
 
     if( iStartRow < 0 ||
         iLength >= INT_MAX - iStartRow ||
-        (iStartRow+iLength) > this->nRows )
+        (iStartRow + iLength) > nRows )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow, iLength );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "iStartRow (%d) + iLength(%d) out of range.",
+                 iStartRow, iLength);
 
         return CE_Failure;
     }
 
     if( aoFields[iField].bConvertColors )
     {
-        // convert to/from float color field
-        int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
+        // Convert to/from float color field.
+        int *panColData =
+            static_cast<int *>(VSI_MALLOC2_VERBOSE(iLength, sizeof(int)));
         if( panColData == NULL )
         {
             CPLFree(panColData);
@@ -933,11 +711,12 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
                 panColData[i] = static_cast<int>(pdfData[i]);
         }
 
-        CPLErr ret = ColorsIO(eRWFlag, iField, iStartRow, iLength, panColData);
+        const CPLErr ret =
+            ColorsIO(eRWFlag, iField, iStartRow, iLength, panColData);
 
         if( eRWFlag == GF_Read )
         {
-            // copy them back to doubles
+            // Copy them back to doubles.
             for( int i = 0; i < iLength; i++ )
                 pdfData[i] = panColData[i];
         }
@@ -950,8 +729,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
     {
         case GFT_Integer:
         {
-            // allocate space for ints
-            int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
+            // Allocate space for ints.
+            int *panColData = static_cast<int *>(
+                VSI_MALLOC2_VERBOSE(iLength, sizeof(int)));
             if( panColData == NULL )
             {
                 CPLFree(panColData);
@@ -960,13 +740,14 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Write )
             {
-                // copy the application supplied doubles to ints
+                // Copy the application supplied doubles to ints.
                 for( int i = 0; i < iLength; i++ )
                     panColData[i] = static_cast<int>(pdfData[i]);
             }
 
-            // do the ValuesIO as ints
-            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData );
+            // Do the ValuesIO as ints.
+            const CPLErr eVal =
+                ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData );
             if( eVal != CE_None )
             {
                 CPLFree(panColData);
@@ -975,7 +756,7 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Read )
             {
-                // copy them back to doubles
+                // Copy them back to doubles.
                 for( int i = 0; i < iLength; i++ )
                     pdfData[i] = panColData[i];
             }
@@ -987,45 +768,63 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         {
             if( (eRWFlag == GF_Read ) && aoFields[iField].bIsBinValues )
             {
-                // probably could change HFAReadBFUniqueBins to only read needed rows
-                double *padfBinValues = HFAReadBFUniqueBins( aoFields[iField].poColumn, iStartRow+iLength );
+                // Probably could change HFAReadBFUniqueBins to only read needed
+                // rows.
+                double *padfBinValues =
+                    HFAReadBFUniqueBins(aoFields[iField].poColumn,
+                                        iStartRow+iLength);
                 if( padfBinValues == NULL )
                     return CE_Failure;
-                memcpy(pdfData, &padfBinValues[iStartRow], sizeof(double) * iLength);
+                memcpy(pdfData, &padfBinValues[iStartRow],
+                       sizeof(double) * iLength);
                 CPLFree(padfBinValues);
             }
             else
             {
-                if(VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(iStartRow)*aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+                if( VSIFSeekL(
+                       hHFA->fp,
+                       aoFields[iField].nDataOffset +
+                       (static_cast<vsi_l_offset>(iStartRow) *
+                        aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+                {
                     return CE_Failure;
+                }
 
                 if( eRWFlag == GF_Read )
                 {
-                    if ((int)VSIFReadL(pdfData, sizeof(double), iLength, hHFA->fp ) != iLength)
+                    if( static_cast<int>(
+                           VSIFReadL(pdfData, sizeof(double),
+                                     iLength, hHFA->fp )) != iLength )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                            "HFARasterAttributeTable::ValuesIO : Cannot read values");
+                        CPLError(
+                            CE_Failure, CPLE_AppDefined,
+                            "HFARasterAttributeTable::ValuesIO: "
+                            "Cannot read values");
                         return CE_Failure;
                     }
 #ifdef CPL_MSB
-                    GDALSwapWords( pdfData, 8, iLength, 8 );
+                    GDALSwapWords(pdfData, 8, iLength, 8);
 #endif
                 }
                 else
                 {
 #ifdef CPL_MSB
-                    GDALSwapWords( pdfData, 8, iLength, 8 );
+                    GDALSwapWords(pdfData, 8, iLength, 8);
 #endif
-                    // Note: HFAAllocateSpace now called by CreateColumn so space should exist
-                    if((int)VSIFWriteL(pdfData, sizeof(double), iLength, hHFA->fp) != iLength)
+                    // Note: HFAAllocateSpace now called by CreateColumn so
+                    // space should exist.
+                    if( static_cast<int>(
+                            VSIFWriteL(pdfData, sizeof(double), iLength,
+                                       hHFA->fp)) != iLength )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                            "HFARasterAttributeTable::ValuesIO : Cannot write values");
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "HFARasterAttributeTable::ValuesIO: "
+                                 "Cannot write values");
                         return CE_Failure;
                     }
 #ifdef CPL_MSB
-                    // swap back
-                    GDALSwapWords( pdfData, 8, iLength, 8 );
+                    // Swap back.
+                    GDALSwapWords(pdfData, 8, iLength, 8);
 #endif
                 }
             }
@@ -1033,8 +832,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         break;
         case GFT_String:
         {
-            // allocate space for string pointers
-            char **papszColData = (char**)VSI_MALLOC2_VERBOSE(iLength, sizeof(char*));
+            // Allocate space for string pointers.
+            char **papszColData = static_cast<char **>(
+                VSI_MALLOC2_VERBOSE(iLength, sizeof(char*)));
             if( papszColData == NULL )
             {
                 return CE_Failure;
@@ -1042,16 +842,17 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Write )
             {
-                // copy the application supplied doubles to strings
+                // Copy the application supplied doubles to strings.
                 for( int i = 0; i < iLength; i++ )
                 {
-                    osWorkingResult.Printf( "%.16g", pdfData[i] );
+                    osWorkingResult.Printf("%.16g", pdfData[i]);
                     papszColData[i] = CPLStrdup(osWorkingResult);
                 }
             }
 
-            // do the ValuesIO as strings
-            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData );
+            // Do the ValuesIO as strings.
+            const CPLErr eVal =
+                ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData );
             if( eVal != CE_None )
             {
                 if( eRWFlag == GF_Write )
@@ -1065,13 +866,13 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Read )
             {
-                // copy them back to doubles
+                // Copy them back to doubles.
                 for( int i = 0; i < iLength; i++ )
                     pdfData[i] = CPLAtof(papszColData[i]);
             }
 
-            // either we allocated them for write, or they were allocated
-            // by ValuesIO on read
+            // Either we allocated them for write, or they were allocated
+            // by ValuesIO on read.
             for( int i = 0; i < iLength; i++ )
                 CPLFree(papszColData[i]);
 
@@ -1087,36 +888,39 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 /*                          ValuesIO()                                  */
 /************************************************************************/
 
-CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData)
+CPLErr HFARasterAttributeTable::ValuesIO( GDALRWFlag eRWFlag, int iField,
+                                          int iStartRow, int iLength,
+                                          int *pnData )
 {
-    if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
+    if( eRWFlag == GF_Write && eAccess == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
-            "Dataset not open in update mode");
+        CPLError(CE_Failure, CPLE_NoWriteAccess,
+                 "Dataset not open in update mode");
         return CE_Failure;
     }
 
-    if( iField < 0 || iField >= (int) aoFields.size() )
+    if( iField < 0 || iField >= static_cast<int>(aoFields.size()) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iField (%d) out of range.", iField );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "iField (%d) out of range.", iField);
 
         return CE_Failure;
     }
 
     if( iStartRow < 0 ||
         iLength >= INT_MAX - iStartRow ||
-        (iStartRow+iLength) > this->nRows )
+        (iStartRow + iLength) > nRows )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow, iLength );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "iStartRow (%d) + iLength(%d) out of range.",
+                 iStartRow, iLength);
 
         return CE_Failure;
     }
 
     if( aoFields[iField].bConvertColors )
     {
-        // convert to/from float color field
+        // Convert to/from float color field.
         return ColorsIO(eRWFlag, iField, iStartRow, iLength, pnData);
     }
 
@@ -1124,9 +928,16 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
     {
         case GFT_Integer:
         {
-            if( VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(iStartRow)*aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+            if( VSIFSeekL(hHFA->fp,
+                          aoFields[iField].nDataOffset +
+                          (static_cast<vsi_l_offset>(iStartRow) *
+                           aoFields[iField].nElementSize),
+                          SEEK_SET) != 0 )
+            {
                 return CE_Failure;
-            GInt32 *panColData = (GInt32*)VSI_MALLOC2_VERBOSE(iLength, sizeof(GInt32));
+            }
+            GInt32 *panColData = static_cast<GInt32 *>(
+                VSI_MALLOC2_VERBOSE(iLength, sizeof(GInt32)));
             if( panColData == NULL )
             {
                 return CE_Failure;
@@ -1134,35 +945,42 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Read )
             {
-                if ((int)VSIFReadL( panColData, sizeof(GInt32), iLength, hHFA->fp ) != iLength)
+                if( static_cast<int>(
+                        VSIFReadL(panColData, sizeof(GInt32), iLength,
+                                  hHFA->fp)) != iLength )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                        "HFARasterAttributeTable::ValuesIO : Cannot read values");
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "HFARasterAttributeTable::ValuesIO: "
+                             "Cannot read values");
                     CPLFree(panColData);
                     return CE_Failure;
                 }
 #ifdef CPL_MSB
-                GDALSwapWords( panColData, 4, iLength, 4 );
+                GDALSwapWords(panColData, 4, iLength, 4);
 #endif
-                // now copy into application buffer. This extra step
-                // may not be necessary if sizeof(int) == sizeof(GInt32)
+                // Now copy into application buffer. This extra step
+                // may not be necessary if sizeof(int) == sizeof(GInt32).
                 for( int i = 0; i < iLength; i++ )
                     pnData[i] = panColData[i];
             }
             else
             {
-                // copy from application buffer
+                // Copy from application buffer.
                 for( int i = 0; i < iLength; i++ )
                     panColData[i] = pnData[i];
 
 #ifdef CPL_MSB
-                GDALSwapWords( panColData, 4, iLength, 4 );
+                GDALSwapWords(panColData, 4, iLength, 4);
 #endif
-                // Note: HFAAllocateSpace now called by CreateColumn so space should exist
-                if((int)VSIFWriteL(panColData, sizeof(GInt32), iLength, hHFA->fp) != iLength)
+                // Note: HFAAllocateSpace now called by CreateColumn so space
+                // should exist.
+                if( static_cast<int>(
+                        VSIFWriteL(panColData, sizeof(GInt32), iLength,
+                                   hHFA->fp)) != iLength )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                        "HFARasterAttributeTable::ValuesIO : Cannot write values");
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "HFARasterAttributeTable::ValuesIO: "
+                             "Cannot write values");
                     CPLFree(panColData);
                     return CE_Failure;
                 }
@@ -1172,8 +990,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         break;
         case GFT_Real:
         {
-            // allocate space for doubles
-            double *padfColData = (double*)VSI_MALLOC2_VERBOSE(iLength, sizeof(double) );
+            // Allocate space for doubles.
+            double *padfColData = static_cast<double *>(
+                VSI_MALLOC2_VERBOSE(iLength, sizeof(double)));
             if( padfColData == NULL )
             {
                 return CE_Failure;
@@ -1181,13 +1000,14 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Write )
             {
-                // copy the application supplied ints to doubles
+                // Copy the application supplied ints to doubles.
                 for( int i = 0; i < iLength; i++ )
                     padfColData[i] = pnData[i];
             }
 
-            // do the ValuesIO as doubles
-            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData );
+            // Do the ValuesIO as doubles.
+            const CPLErr eVal =
+                ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData );
             if( eVal != CE_None )
             {
                 CPLFree(padfColData);
@@ -1196,7 +1016,7 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Read )
             {
-                // copy them back to ints
+                // Copy them back to ints.
                 for( int i = 0; i < iLength; i++ )
                     pnData[i] = static_cast<int>(padfColData[i]);
             }
@@ -1206,8 +1026,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         break;
         case GFT_String:
         {
-            // allocate space for string pointers
-            char **papszColData = (char**)VSI_MALLOC2_VERBOSE(iLength, sizeof(char*));
+            // Allocate space for string pointers.
+            char **papszColData = static_cast<char **>(
+                VSI_MALLOC2_VERBOSE(iLength, sizeof(char*)));
             if( papszColData == NULL )
             {
                 return CE_Failure;
@@ -1215,16 +1036,17 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Write )
             {
-                // copy the application supplied ints to strings
+                // Copy the application supplied ints to strings.
                 for( int i = 0; i < iLength; i++ )
                 {
-                    osWorkingResult.Printf( "%d", pnData[i] );
+                    osWorkingResult.Printf("%d", pnData[i]);
                     papszColData[i] = CPLStrdup(osWorkingResult);
                 }
             }
 
-            // do the ValuesIO as strings
-            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData );
+            // Do the ValuesIO as strings.
+            const CPLErr eVal =
+                ValuesIO(eRWFlag, iField, iStartRow, iLength, papszColData );
             if( eVal != CE_None )
             {
                 if( eRWFlag == GF_Write )
@@ -1238,13 +1060,13 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Read )
             {
-                // copy them back to ints
+                // Copy them back to ints.
                 for( int i = 0; i < iLength; i++ )
                     pnData[i] = atoi(papszColData[i]);
             }
 
-            // either we allocated them for write, or they were allocated
-            // by ValuesIO on read
+            // Either we allocated them for write, or they were allocated
+            // by ValuesIO on read.
             for( int i = 0; i < iLength; i++ )
                 CPLFree(papszColData[i]);
 
@@ -1260,37 +1082,41 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 /*                          ValuesIO()                                  */
 /************************************************************************/
 
-CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList)
+CPLErr HFARasterAttributeTable::ValuesIO( GDALRWFlag eRWFlag, int iField,
+                                          int iStartRow, int iLength,
+                                          char **papszStrList )
 {
-    if( ( eRWFlag == GF_Write ) && ( this->eAccess == GA_ReadOnly ) )
+    if( eRWFlag == GF_Write && eAccess == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
-            "Dataset not open in update mode");
+        CPLError(CE_Failure, CPLE_NoWriteAccess,
+                 "Dataset not open in update mode");
         return CE_Failure;
     }
 
-    if( iField < 0 || iField >= (int) aoFields.size() )
+    if( iField < 0 || iField >= static_cast<int>(aoFields.size()) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iField (%d) out of range.", iField );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "iField (%d) out of range.", iField);
 
         return CE_Failure;
     }
 
     if( iStartRow < 0 ||
         iLength >= INT_MAX - iStartRow ||
-        (iStartRow+iLength) > this->nRows )
+        (iStartRow + iLength) > nRows )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "iStartRow (%d) + iLength(%d) out of range.", iStartRow, iLength );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "iStartRow (%d) + iLength(%d) out of range.",
+                 iStartRow, iLength);
 
         return CE_Failure;
     }
 
     if( aoFields[iField].bConvertColors )
     {
-        // convert to/from float color field
-        int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
+        // Convert to/from float color field.
+        int *panColData = static_cast<int *>(
+            VSI_MALLOC2_VERBOSE(iLength, sizeof(int)));
         if( panColData == NULL )
         {
             CPLFree(panColData);
@@ -1303,14 +1129,15 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
                 panColData[i] = atoi(papszStrList[i]);
         }
 
-        CPLErr ret = ColorsIO(eRWFlag, iField, iStartRow, iLength, panColData);
+        const CPLErr ret =
+            ColorsIO(eRWFlag, iField, iStartRow, iLength, panColData);
 
         if( eRWFlag == GF_Read )
         {
-            // copy them back to strings
+            // Copy them back to strings.
             for( int i = 0; i < iLength; i++ )
             {
-                osWorkingResult.Printf( "%d", panColData[i]);
+                osWorkingResult.Printf("%d", panColData[i]);
                 papszStrList[i] = CPLStrdup(osWorkingResult);
             }
         }
@@ -1323,8 +1150,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
     {
         case GFT_Integer:
         {
-            // allocate space for ints
-            int *panColData = (int*)VSI_MALLOC2_VERBOSE(iLength, sizeof(int) );
+            // Allocate space for ints.
+            int *panColData = static_cast<int *>(
+                VSI_MALLOC2_VERBOSE(iLength, sizeof(int)));
             if( panColData == NULL )
             {
                 return CE_Failure;
@@ -1332,26 +1160,26 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Write )
             {
-                // convert user supplied strings to ints
+                // Convert user supplied strings to ints.
                 for( int i = 0; i < iLength; i++ )
                     panColData[i] = atoi(papszStrList[i]);
             }
 
-            // call values IO to read/write ints
-            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
+            // Call values IO to read/write ints.
+            const CPLErr eVal =
+                ValuesIO(eRWFlag, iField, iStartRow, iLength, panColData);
             if( eVal != CE_None )
             {
                 CPLFree(panColData);
                 return eVal;
             }
 
-
             if( eRWFlag == GF_Read )
             {
-                // convert ints back to strings
+                // Convert ints back to strings.
                 for( int i = 0; i < iLength; i++ )
                 {
-                    osWorkingResult.Printf( "%d", panColData[i]);
+                    osWorkingResult.Printf("%d", panColData[i]);
                     papszStrList[i] = CPLStrdup(osWorkingResult);
                 }
             }
@@ -1360,8 +1188,9 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         break;
         case GFT_Real:
         {
-            // allocate space for doubles
-            double *padfColData = (double*)VSI_MALLOC2_VERBOSE(iLength, sizeof(double) );
+            // Allocate space for doubles.
+            double *padfColData = static_cast<double *>(
+                VSI_MALLOC2_VERBOSE(iLength, sizeof(double)));
             if( padfColData == NULL )
             {
                 return CE_Failure;
@@ -1369,13 +1198,14 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Write )
             {
-                // convert user supplied strings to doubles
+                // Convert user supplied strings to doubles.
                 for( int i = 0; i < iLength; i++ )
                     padfColData[i] = CPLAtof(papszStrList[i]);
             }
 
-            // call value IO to read/write doubles
-            CPLErr eVal = ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
+            // Call value IO to read/write doubles.
+            const CPLErr eVal =
+                ValuesIO(eRWFlag, iField, iStartRow, iLength, padfColData);
             if( eVal != CE_None )
             {
                 CPLFree(padfColData);
@@ -1384,10 +1214,10 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Read )
             {
-                // convert doubles back to strings
+                // Convert doubles back to strings.
                 for( int i = 0; i < iLength; i++ )
                 {
-                    osWorkingResult.Printf( "%.16g", padfColData[i]);
+                    osWorkingResult.Printf("%.16g", padfColData[i]);
                     papszStrList[i] = CPLStrdup(osWorkingResult);
                 }
             }
@@ -1396,9 +1226,15 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
         break;
         case GFT_String:
         {
-            if( VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(iStartRow)*aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+            if( VSIFSeekL(hHFA->fp,
+                          aoFields[iField].nDataOffset +
+                          (static_cast<vsi_l_offset>(iStartRow) *
+                           aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+            {
                 return CE_Failure;
-            char *pachColData = (char*)VSI_MALLOC2_VERBOSE(iLength, aoFields[iField].nElementSize);
+            }
+            char *pachColData = static_cast<char *>(
+                VSI_MALLOC2_VERBOSE(iLength, aoFields[iField].nElementSize));
             if( pachColData == NULL )
             {
                 return CE_Failure;
@@ -1406,97 +1242,135 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 
             if( eRWFlag == GF_Read )
             {
-                if ((int)VSIFReadL( pachColData, aoFields[iField].nElementSize, iLength, hHFA->fp ) != iLength)
+                if( static_cast<int>(
+                        VSIFReadL(pachColData, aoFields[iField].nElementSize,
+                                  iLength, hHFA->fp)) != iLength )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                        "HFARasterAttributeTable::ValuesIO : Cannot read values");
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "HFARasterAttributeTable::ValuesIO: "
+                             "Cannot read values");
                     CPLFree(pachColData);
                     return CE_Failure;
                 }
 
-                // now copy into application buffer
+                // Now copy into application buffer.
                 for( int i = 0; i < iLength; i++ )
                 {
-                    osWorkingResult.assign(pachColData+aoFields[iField].nElementSize*i, aoFields[iField].nElementSize );
+                    osWorkingResult.assign(
+                        pachColData+aoFields[iField].nElementSize * i,
+                        aoFields[iField].nElementSize );
                     papszStrList[i] = CPLStrdup(osWorkingResult);
                 }
             }
             else
             {
-                // we need to check that these strings will fit in the allocated space
+                // We need to check that these strings will fit in the allocated
+                // space.
                 int nNewMaxChars = aoFields[iField].nElementSize;
                 for( int i = 0; i < iLength; i++ )
                 {
-                    int nStringSize = static_cast<int>(strlen(papszStrList[i])) + 1;
+                    const int nStringSize =
+                        static_cast<int>(strlen(papszStrList[i])) + 1;
                     if( nStringSize > nNewMaxChars )
                         nNewMaxChars = nStringSize;
                 }
 
                 if( nNewMaxChars > aoFields[iField].nElementSize )
                 {
-                    // OK we have a problem - the allocated space is not big enough
-                    // we need to re-allocate the space and update the pointers
-                    // and copy across the old data
-                    const int nNewOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
-                                            this->nRows * nNewMaxChars);
-                    char *pszBuffer = (char*)VSIMalloc2(aoFields[iField].nElementSize, sizeof(char));
-                    char cNullByte = '\0';
-                    for( int i = 0; i < this->nRows; i++ )
+                    // OK we have a problem: The allocated space is not big
+                    // enough we need to re-allocate the space and update the
+                    // pointers and copy across the old data.
+                    const int nNewOffset =
+                        HFAAllocateSpace(hHFA->papoBand[nBand-1]->psInfo,
+                                         nRows * nNewMaxChars);
+                    char *pszBuffer = static_cast<char *>(
+                        VSIMalloc2(aoFields[iField].nElementSize,
+                                   sizeof(char)));
+                    for( int i = 0; i < nRows; i++ )
                     {
-                        // seek to the old place
-                        CPL_IGNORE_RET_VAL(VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(i)*aoFields[iField].nElementSize), SEEK_SET ));
-                        // read in old data
-                        CPL_IGNORE_RET_VAL(VSIFReadL(pszBuffer, aoFields[iField].nElementSize, 1, hHFA->fp ));
-                        // seek to new place
-                        bool bOK = VSIFSeekL( hHFA->fp, nNewOffset + (static_cast<vsi_l_offset>(i)*nNewMaxChars), SEEK_SET ) == 0;
-                        // write data to new place
-                        bOK &= VSIFWriteL(pszBuffer, aoFields[iField].nElementSize, 1, hHFA->fp) == 1;
-                        // make sure there is a terminating null byte just to be safe
-                        bOK &= VSIFWriteL(&cNullByte, sizeof(char), 1, hHFA->fp) == 1;
+                        // Seek to the old place.
+                        CPL_IGNORE_RET_VAL(
+                            VSIFSeekL(hHFA->fp,
+                                      aoFields[iField].nDataOffset +
+                                      (static_cast<vsi_l_offset>(i) *
+                                       aoFields[iField].nElementSize),
+                                      SEEK_SET ));
+                        // Read in old data.
+                        CPL_IGNORE_RET_VAL(
+                            VSIFReadL(pszBuffer, aoFields[iField].nElementSize,
+                                      1, hHFA->fp ));
+                        // Seek to new place.
+                        bool bOK =
+                            VSIFSeekL(hHFA->fp,
+                                      nNewOffset +
+                                      (static_cast<vsi_l_offset>(i) *
+                                       nNewMaxChars), SEEK_SET ) == 0;
+                        // Write data to new place.
+                        bOK &= VSIFWriteL(pszBuffer,
+                                          aoFields[iField].nElementSize, 1,
+                                          hHFA->fp) == 1;
+                        // Make sure there is a terminating null byte just to be
+                        // safe.
+                        const char cNullByte = '\0';
+                        bOK &= VSIFWriteL(&cNullByte, sizeof(char), 1,
+                                          hHFA->fp) == 1;
                         if( !bOK )
                         {
                             CPLFree(pszBuffer);
                             CPLFree(pachColData);
-                            CPLError( CE_Failure, CPLE_AppDefined,
-                                "HFARasterAttributeTable::ValuesIO : Cannot write values");
+                            CPLError(CE_Failure, CPLE_AppDefined,
+                                     "HFARasterAttributeTable::ValuesIO: "
+                                     "Cannot write values");
                             return CE_Failure;
                         }
                     }
-                    // update our data structures
+                    // Update our data structures.
                     aoFields[iField].nElementSize = nNewMaxChars;
                     aoFields[iField].nDataOffset = nNewOffset;
-                    // update file
-                    aoFields[iField].poColumn->SetIntField( "columnDataPtr", nNewOffset );
-                    aoFields[iField].poColumn->SetIntField( "maxNumChars", nNewMaxChars );
-
-                    // Note: there isn't an HFAFreeSpace so we can't un-allocate the old space in the file
+                    // Update file.
+                    aoFields[iField].poColumn->SetIntField("columnDataPtr",
+                                                           nNewOffset);
+                    aoFields[iField].poColumn->SetIntField("maxNumChars",
+                                                           nNewMaxChars);
+
+                    // Note: There isn't an HFAFreeSpace so we can't un-allocate
+                    // the old space in the file.
                     CPLFree(pszBuffer);
 
-                    // re-allocate our buffer
+                    // Re-allocate our buffer.
                     CPLFree(pachColData);
-                    pachColData = (char*)VSI_MALLOC2_VERBOSE(iLength, nNewMaxChars);
-                    if(pachColData == NULL )
+                    pachColData = static_cast<char *>(
+                        VSI_MALLOC2_VERBOSE(iLength, nNewMaxChars));
+                    if( pachColData == NULL )
                     {
                         return CE_Failure;
                     }
 
-                    // lastly seek to the right place in the new space ready to write
-                    if( VSIFSeekL( hHFA->fp, nNewOffset + (static_cast<vsi_l_offset>(iStartRow)*nNewMaxChars), SEEK_SET ) != 0 )
+                    // Lastly seek to the right place in the new space ready to
+                    // write.
+                    if( VSIFSeekL(hHFA->fp,
+                                  nNewOffset +
+                                  (static_cast<vsi_l_offset>(iStartRow) *
+                                   nNewMaxChars), SEEK_SET) != 0 )
                     {
                         VSIFree(pachColData);
                         return CE_Failure;
                     }
                 }
 
-                // copy from application buffer
+                // Copy from application buffer.
                 for( int i = 0; i < iLength; i++ )
                     strcpy(&pachColData[nNewMaxChars*i], papszStrList[i]);
 
-                // Note: HFAAllocateSpace now called by CreateColumn so space should exist
-                if((int)VSIFWriteL(pachColData, aoFields[iField].nElementSize, iLength, hHFA->fp) != iLength)
+                // Note: HFAAllocateSpace now called by CreateColumn so space
+                // should exist.
+                if( static_cast<int>(
+                        VSIFWriteL(pachColData, aoFields[iField].nElementSize,
+                                   iLength, hHFA->fp)) != iLength )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                        "HFARasterAttributeTable::ValuesIO : Cannot write values");
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "HFARasterAttributeTable::ValuesIO: "
+                             "Cannot write values");
                     CPLFree(pachColData);
                     return CE_Failure;
                 }
@@ -1514,11 +1388,14 @@ CPLErr HFARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
 /************************************************************************/
 
 // Handle the fact that HFA stores colours as floats, but we need to
-// read them in as ints 0...255
-CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData)
+// read them in as ints 0...255.
+CPLErr HFARasterAttributeTable::ColorsIO( GDALRWFlag eRWFlag, int iField,
+                                          int iStartRow, int iLength,
+                                          int *pnData )
 {
-    // allocate space for doubles
-    double *padfData = (double*)VSI_MALLOC2_VERBOSE(iLength, sizeof(double) );
+    // Allocate space for doubles.
+    double *padfData =
+        static_cast<double *>(VSI_MALLOC2_VERBOSE(iLength, sizeof(double)));
     if( padfData == NULL )
     {
         return CE_Failure;
@@ -1526,14 +1403,17 @@ CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iSt
 
     if( eRWFlag == GF_Write )
     {
-        // copy the application supplied ints to doubles
+        // Copy the application supplied ints to doubles
         // and convert 0..255 to 0..1 in the same manner
-        // as the color table
+        // as the color table.
         for( int i = 0; i < iLength; i++ )
             padfData[i] = pnData[i] / 255.0;
     }
 
-    if( VSIFSeekL( hHFA->fp, aoFields[iField].nDataOffset + (static_cast<vsi_l_offset>(iStartRow)*aoFields[iField].nElementSize), SEEK_SET ) != 0 )
+    if( VSIFSeekL(hHFA->fp,
+                  aoFields[iField].nDataOffset +
+                  (static_cast<vsi_l_offset>(iStartRow) *
+                   aoFields[iField].nElementSize), SEEK_SET) != 0 )
     {
         CPLFree(padfData);
         return CE_Failure;
@@ -1541,27 +1421,31 @@ CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iSt
 
     if( eRWFlag == GF_Read )
     {
-        if ((int)VSIFReadL(padfData, sizeof(double), iLength, hHFA->fp ) != iLength)
+        if( static_cast<int>(VSIFReadL(padfData, sizeof(double), iLength,
+                                       hHFA->fp)) != iLength )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                "HFARasterAttributeTable::ColorsIO : Cannot read values");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "HFARasterAttributeTable::ColorsIO: Cannot read values");
             CPLFree(padfData);
             return CE_Failure;
         }
 #ifdef CPL_MSB
-        GDALSwapWords( padfData, 8, iLength, 8 );
+        GDALSwapWords(padfData, 8, iLength, 8);
 #endif
     }
     else
     {
 #ifdef CPL_MSB
-        GDALSwapWords( padfData, 8, iLength, 8 );
+        GDALSwapWords(padfData, 8, iLength, 8);
 #endif
-        // Note: HFAAllocateSpace now called by CreateColumn so space should exist
-        if((int)VSIFWriteL(padfData, sizeof(double), iLength, hHFA->fp) != iLength)
+        // Note: HFAAllocateSpace now called by CreateColumn so space should
+        // exist.
+        if( static_cast<int>(
+                VSIFWriteL(padfData, sizeof(double), iLength,
+                           hHFA->fp)) != iLength )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                "HFARasterAttributeTable::ColorsIO : Cannot write values");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "HFARasterAttributeTable::ColorsIO: Cannot write values");
             CPLFree(padfData);
             return CE_Failure;
         }
@@ -1569,10 +1453,11 @@ CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iSt
 
     if( eRWFlag == GF_Read )
     {
-        // copy them back to ints converting 0..1 to 0..255 in
-        // the same manner as the color table
+        // Copy them back to ints converting 0..1 to 0..255 in
+        // the same manner as the color table.
+        // TODO(schwehr): Symbolic constants for 255 and 256.
         for( int i = 0; i < iLength; i++ )
-            pnData[i] = MIN(255,(int) (padfData[i] * 256));
+            pnData[i] = std::min(255, static_cast<int>(padfData[i] * 256));
     }
 
     CPLFree(padfData);
@@ -1584,10 +1469,7 @@ CPLErr HFARasterAttributeTable::ColorsIO(GDALRWFlag eRWFlag, int iField, int iSt
 /*                       ChangesAreWrittenToFile()                      */
 /************************************************************************/
 
-int HFARasterAttributeTable::ChangesAreWrittenToFile()
-{
-    return TRUE;
-}
+int HFARasterAttributeTable::ChangesAreWrittenToFile() { return TRUE; }
 
 /************************************************************************/
 /*                          SetRowCount()                               */
@@ -1595,75 +1477,88 @@ int HFARasterAttributeTable::ChangesAreWrittenToFile()
 
 void HFARasterAttributeTable::SetRowCount( int iCount )
 {
-    if( this->eAccess == GA_ReadOnly )
+    if( eAccess == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
-            "Dataset not open in update mode");
+        CPLError(CE_Failure, CPLE_NoWriteAccess,
+                 "Dataset not open in update mode");
         return;
     }
 
-    if( iCount > this->nRows )
+    if( iCount > nRows )
     {
-        // making the RAT larger - a bit hard
-        // We need to re-allocate space on disc
-        for( int iCol = 0; iCol < (int)this->aoFields.size(); iCol++ )
+        // Making the RAT larger - a bit hard.
+        // We need to re-allocate space on disc.
+        for( int iCol = 0;
+             iCol < static_cast<int>(aoFields.size());
+             iCol++ )
         {
-            // new space
-            const int nNewOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
-                                            iCount * aoFields[iCol].nElementSize);
+            // New space.
+            const int nNewOffset =
+                HFAAllocateSpace(hHFA->papoBand[nBand - 1]->psInfo,
+                                 iCount * aoFields[iCol].nElementSize);
 
-            // only need to bother if there are actually rows
-            if( this->nRows > 0 )
+            // Only need to bother if there are actually rows.
+            if( nRows > 0 )
             {
-                // temp buffer for this column
-                void *pData = VSI_MALLOC2_VERBOSE(this->nRows, aoFields[iCol].nElementSize);
+                // Temp buffer for this column.
+                void *pData =
+                    VSI_MALLOC2_VERBOSE(nRows, aoFields[iCol].nElementSize);
                 if( pData == NULL )
                 {
                     return;
                 }
-                // read old data
-                if( VSIFSeekL( hHFA->fp, aoFields[iCol].nDataOffset, SEEK_SET ) != 0 ||
-                    (int)VSIFReadL(pData, aoFields[iCol].nElementSize, this->nRows, hHFA->fp) != this->nRows )
+                // Read old data.
+                if( VSIFSeekL(hHFA->fp, aoFields[iCol].nDataOffset,
+                              SEEK_SET) != 0 ||
+                    static_cast<int>(
+                        VSIFReadL(pData, aoFields[iCol].nElementSize,
+                                  nRows, hHFA->fp)) != nRows )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                        "HFARasterAttributeTable::SetRowCount : Cannot read values");
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "HFARasterAttributeTable::SetRowCount: "
+                             "Cannot read values");
                     CPLFree(pData);
                     return;
                 }
 
-                // write data - new space will be uninitialised
-                if( VSIFSeekL( hHFA->fp, nNewOffset, SEEK_SET ) != 0 ||
-                    (int)VSIFWriteL(pData, aoFields[iCol].nElementSize, this->nRows, hHFA->fp) != this->nRows )
+                // Write data - new space will be uninitialised.
+                if( VSIFSeekL(hHFA->fp, nNewOffset, SEEK_SET ) != 0 ||
+                    static_cast<int>(
+                        VSIFWriteL(pData, aoFields[iCol].nElementSize,
+                                   nRows, hHFA->fp)) != nRows )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                            "HFARasterAttributeTable::SetRowCount : Cannot write values");
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "HFARasterAttributeTable::SetRowCount: "
+                             "Cannot write values");
                     CPLFree(pData);
                     return;
                 }
                 CPLFree(pData);
             }
 
-            // update our data structures
+            // Update our data structures.
             aoFields[iCol].nDataOffset = nNewOffset;
-            // update file
-            aoFields[iCol].poColumn->SetIntField( "columnDataPtr", nNewOffset );
-            aoFields[iCol].poColumn->SetIntField( "numRows", iCount);
+            // Update file.
+            aoFields[iCol].poColumn->SetIntField("columnDataPtr", nNewOffset);
+            aoFields[iCol].poColumn->SetIntField("numRows", iCount);
         }
     }
-    else if( iCount < this->nRows )
+    else if( iCount < nRows )
     {
-        // update the numRows
-        for( int iCol = 0; iCol < (int)this->aoFields.size(); iCol++ )
+        // Update the numRows.
+        for( int iCol = 0;
+             iCol < static_cast<int>(aoFields.size());
+             iCol++ )
         {
-            aoFields[iCol].poColumn->SetIntField( "numRows", iCount);
+            aoFields[iCol].poColumn->SetIntField("numRows", iCount);
         }
     }
 
-    this->nRows = iCount;
+    nRows = iCount;
 
-    if( ( this->poDT != NULL ) && ( EQUAL(this->poDT->GetType(),"Edsc_Table")))
+    if( poDT != NULL && EQUAL(poDT->GetType(), "Edsc_Table") )
     {
-        this->poDT->SetIntField( "numrows", iCount );
+        poDT->SetIntField("numrows", iCount);
     }
 }
 
@@ -1673,43 +1568,39 @@ void HFARasterAttributeTable::SetRowCount( int iCount )
 
 int HFARasterAttributeTable::GetRowOfValue( double dfValue ) const
 {
-/* -------------------------------------------------------------------- */
-/*      Handle case of regular binning.                                 */
-/* -------------------------------------------------------------------- */
+    // Handle case of regular binning.
     if( bLinearBinning )
     {
-        int iBin = (int) floor((dfValue - dfRow0Min) / dfBinSize);
-        if( iBin < 0 || iBin >= this->nRows )
+        const int iBin =
+            static_cast<int>(floor((dfValue - dfRow0Min) / dfBinSize));
+        if( iBin < 0 || iBin >= nRows )
             return -1;
 
         return iBin;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we have any information?                                     */
-/* -------------------------------------------------------------------- */
-    int nMinCol = GetColOfUsage( GFU_Min );
+    // Do we have any information?
+    int nMinCol = GetColOfUsage(GFU_Min);
     if( nMinCol == -1 )
-        nMinCol = GetColOfUsage( GFU_MinMax );
+        nMinCol = GetColOfUsage(GFU_MinMax);
 
-    int nMaxCol = GetColOfUsage( GFU_Max );
+    int nMaxCol = GetColOfUsage(GFU_Max);
     if( nMaxCol == -1 )
-        nMaxCol = GetColOfUsage( GFU_MinMax );
+        nMaxCol = GetColOfUsage(GFU_MinMax);
 
     if( nMinCol == -1 && nMaxCol == -1 )
         return -1;
 
-/* -------------------------------------------------------------------- */
-/*      Search through rows for match.                                  */
-/* -------------------------------------------------------------------- */
-    for( int iRow = 0; iRow < this->nRows; iRow++ )
+    // Search through rows for match.
+    for( int iRow = 0; iRow < nRows; iRow++ )
     {
         if( nMinCol != -1 )
         {
-            while( iRow < this->nRows && dfValue < GetValueAsDouble(iRow, nMinCol) )
-                    iRow++;
+            while( iRow < nRows &&
+                   dfValue < GetValueAsDouble(iRow, nMinCol) )
+                iRow++;
 
-            if( iRow == this->nRows )
+            if( iRow == nRows )
                 break;
         }
 
@@ -1734,7 +1625,7 @@ int HFARasterAttributeTable::GetRowOfValue( double dfValue ) const
 
 int HFARasterAttributeTable::GetRowOfValue( int nValue ) const
 {
-    return GetRowOfValue( (double) nValue );
+    return GetRowOfValue(static_cast<double>(nValue));
 }
 
 /************************************************************************/
@@ -1747,49 +1638,49 @@ CPLErr HFARasterAttributeTable::CreateColumn( const char *pszFieldName,
 {
     if( eAccess == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
-            "Dataset not open in update mode");
+        CPLError(CE_Failure, CPLE_NoWriteAccess,
+                 "Dataset not open in update mode");
         return CE_Failure;
     }
 
-    // do we have a descriptor table already?
-    if( poDT == NULL || !EQUAL(poDT->GetType(),"Edsc_Table") )
+    // Do we have a descriptor table already?
+    if( poDT == NULL || !EQUAL(poDT->GetType(), "Edsc_Table") )
         CreateDT();
 
-    int bConvertColors = FALSE;
+    bool bConvertColors = false;
 
     // Imagine doesn't have a concept of usage - works of the names instead.
-    // must make sure name matches use
+    // Must make sure name matches use.
     if( eFieldUsage == GFU_Red )
     {
         pszFieldName = "Red";
-        // create a real column in the file, but make it
-        // available as int to GDAL
-        bConvertColors = TRUE;
+        // Create a real column in the file, but make it
+        // available as int to GDAL.
+        bConvertColors = true;
         eFieldType = GFT_Real;
     }
     else if( eFieldUsage == GFU_Green )
     {
         pszFieldName = "Green";
-        bConvertColors = TRUE;
+        bConvertColors = true;
         eFieldType = GFT_Real;
     }
     else if( eFieldUsage == GFU_Blue )
     {
         pszFieldName = "Blue";
-        bConvertColors = TRUE;
+        bConvertColors = true;
         eFieldType = GFT_Real;
     }
     else if( eFieldUsage == GFU_Alpha )
     {
         pszFieldName = "Opacity";
-        bConvertColors = TRUE;
+        bConvertColors = true;
         eFieldType = GFT_Real;
     }
     else if( eFieldUsage == GFU_PixelCount )
     {
         pszFieldName = "Histogram";
-        // histogram is always float in HFA
+        // Histogram is always float in HFA.
         eFieldType = GFT_Real;
     }
     else if( eFieldUsage == GFU_Name )
@@ -1797,56 +1688,56 @@ CPLErr HFARasterAttributeTable::CreateColumn( const char *pszFieldName,
         pszFieldName = "Class_Names";
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check to see if a column with pszFieldName exists and create it */
-/*      if necessary.                                                   */
-/* -------------------------------------------------------------------- */
-
+    // Check to see if a column with pszFieldName exists and create it
+    // if necessary.
     HFAEntry *poColumn = poDT->GetNamedChild(pszFieldName);
 
-    if(poColumn == NULL || !EQUAL(poColumn->GetType(),"Edsc_Column"))
-        poColumn = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
-                                     pszFieldName, "Edsc_Column",
-                                     poDT );
+    if( poColumn == NULL || !EQUAL(poColumn->GetType(), "Edsc_Column") )
+        poColumn = HFAEntry::New(hHFA->papoBand[nBand - 1]->psInfo,
+                                 pszFieldName, "Edsc_Column", poDT);
 
-    poColumn->SetIntField( "numRows", this->nRows );
+    poColumn->SetIntField("numRows", nRows);
     int nElementSize = 0;
 
     if( eFieldType == GFT_Integer )
     {
         nElementSize = sizeof(GInt32);
-        poColumn->SetStringField( "dataType", "integer" );
+        poColumn->SetStringField("dataType", "integer");
     }
     else if( eFieldType == GFT_Real )
     {
         nElementSize = sizeof(double);
-        poColumn->SetStringField( "dataType", "real" );
+        poColumn->SetStringField("dataType", "real");
     }
     else if( eFieldType == GFT_String )
     {
-        // just have to guess here since we don't have any
-        // strings to check
+        // Just have to guess here since we don't have any strings to check.
         nElementSize = 10;
-        poColumn->SetStringField( "dataType", "string" );
-        poColumn->SetIntField( "maxNumChars", nElementSize);
+        poColumn->SetStringField("dataType", "string");
+        poColumn->SetIntField("maxNumChars", nElementSize);
     }
     else
     {
-        /* can't deal with any of the others yet */
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Writing this data type in a column is not supported for this Raster Attribute Table.");
+        // Cannot deal with any of the others yet.
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Writing this data type in a column is not supported "
+                 "for this Raster Attribute Table.");
         return CE_Failure;
     }
 
-    const int nOffset = HFAAllocateSpace( this->hHFA->papoBand[this->nBand-1]->psInfo,
-                                          this->nRows * nElementSize );
-    poColumn->SetIntField( "columnDataPtr", nOffset );
+    const int nOffset =
+        HFAAllocateSpace(hHFA->papoBand[nBand - 1]->psInfo,
+                         nRows * nElementSize);
+    poColumn->SetIntField("columnDataPtr", nOffset);
 
     if( bConvertColors )
+    {
         // GDAL Int column
         eFieldType = GFT_Integer;
+    }
 
-    AddColumn(pszFieldName, eFieldType, eFieldUsage, nOffset, nElementSize, poColumn, FALSE, bConvertColors);
+    AddColumn(pszFieldName, eFieldType, eFieldUsage,
+              nOffset, nElementSize, poColumn, false, bConvertColors);
 
     return CE_None;
 }
@@ -1855,37 +1746,42 @@ CPLErr HFARasterAttributeTable::CreateColumn( const char *pszFieldName,
 /*                          SetLinearBinning()                          */
 /************************************************************************/
 
-CPLErr HFARasterAttributeTable::SetLinearBinning( double dfRow0MinIn, double dfBinSizeIn )
+CPLErr HFARasterAttributeTable::SetLinearBinning(
+    double dfRow0MinIn, double dfBinSizeIn )
 {
-    if( this->eAccess == GA_ReadOnly )
+    if( eAccess == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
-            "Dataset not open in update mode");
+        CPLError(CE_Failure, CPLE_NoWriteAccess,
+                 "Dataset not open in update mode");
         return CE_Failure;
     }
 
-    this->bLinearBinning = TRUE;
-    this->dfRow0Min = dfRow0MinIn;
-    this->dfBinSize = dfBinSizeIn;
+    bLinearBinning = true;
+    dfRow0Min = dfRow0MinIn;
+    dfBinSize = dfBinSizeIn;
 
-    // do we have a descriptor table already?
-    if( this->poDT == NULL || !EQUAL(this->poDT->GetType(),"Edsc_Table") )
+    // Do we have a descriptor table already?
+    if( poDT == NULL || !EQUAL(poDT->GetType(), "Edsc_Table") )
         CreateDT();
 
-    /* we should have an Edsc_BinFunction */
-    HFAEntry *poBinFunction = this->poDT->GetNamedChild( "#Bin_Function#" );
-    if( poBinFunction == NULL || !EQUAL(poBinFunction->GetType(),"Edsc_BinFunction") )
-        poBinFunction = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
-                                       "#Bin_Function#", "Edsc_BinFunction",
-                                       poDT );
+    // We should have an Edsc_BinFunction.
+    HFAEntry *poBinFunction = poDT->GetNamedChild("#Bin_Function#");
+    if( poBinFunction == NULL ||
+        !EQUAL(poBinFunction->GetType(), "Edsc_BinFunction") )
+    {
+        poBinFunction = HFAEntry::New(hHFA->papoBand[nBand - 1]->psInfo,
+                                      "#Bin_Function#", "Edsc_BinFunction",
+                                      poDT);
+    }
 
     // Because of the BaseData we have to hardcode the size.
-    poBinFunction->MakeData( 30 );
+    poBinFunction->MakeData(30);
 
     poBinFunction->SetStringField("binFunction", "direct");
-    poBinFunction->SetDoubleField("minLimit",this->dfRow0Min);
-    poBinFunction->SetDoubleField("maxLimit",(this->nRows -1)*this->dfBinSize+this->dfRow0Min);
-    poBinFunction->SetIntField("numBins",this->nRows);
+    poBinFunction->SetDoubleField("minLimit", dfRow0Min);
+    poBinFunction->SetDoubleField(
+        "maxLimit", (nRows - 1) * dfBinSize + dfRow0Min);
+    poBinFunction->SetIntField("numBins", nRows);
 
     return CE_None;
 }
@@ -1894,7 +1790,8 @@ CPLErr HFARasterAttributeTable::SetLinearBinning( double dfRow0MinIn, double dfB
 /*                          GetLinearBinning()                          */
 /************************************************************************/
 
-int HFARasterAttributeTable::GetLinearBinning( double *pdfRow0Min, double *pdfBinSize ) const
+int HFARasterAttributeTable::GetLinearBinning( double *pdfRow0Min,
+                                               double *pdfBinSize ) const
 {
     if( !bLinearBinning )
         return FALSE;
@@ -1922,161 +1819,174 @@ CPLXMLNode *HFARasterAttributeTable::Serialize() const
 /*                           HFARasterBand()                            */
 /************************************************************************/
 
-HFARasterBand::HFARasterBand( HFADataset *poDSIn, int nBandIn, int iOverview )
+namespace {
+
+// Convert 0..1 input color range to 0..255.
+// Clamp overflow and underflow.
+short ColorToShort(double val)
+{
+    const double dfScaled = val * 256.0;
+    // Clamp to [0..255].
+    const double dfClamped = std::max(0.0, std::min(255.0, dfScaled));
+    return static_cast<short>(dfClamped);
+}
 
+}  // namespace
+
+HFARasterBand::HFARasterBand( HFADataset *poDSIn, int nBandIn, int iOverview ) :
+    poCT(NULL),
+    // eHFADataType
+    nOverviews(-1),
+    nThisOverview(iOverview),
+    papoOverviewBands(NULL),
+    hHFA(poDSIn->hHFA),
+    bMetadataDirty(false),
+    poDefaultRAT(NULL)
 {
     if( iOverview == -1 )
         poDS = poDSIn;
     else
         poDS = NULL;
 
-    this->hHFA = poDSIn->hHFA;
     nBand = nBandIn;
-    this->poCT = NULL;
-    this->nThisOverview = iOverview;
-    this->papoOverviewBands = NULL;
-    this->bMetadataDirty = FALSE;
-    this->poDefaultRAT = NULL;
-    this->nOverviews = -1;
-
-    int nCompression;
-    HFAGetBandInfo( hHFA, nBand, &eHFADataType,
-                    &nBlockXSize, &nBlockYSize, &nCompression );
-
-/* -------------------------------------------------------------------- */
-/*      If this is an overview, we need to fetch the actual size,       */
-/*      and block size.                                                 */
-/* -------------------------------------------------------------------- */
+
+    int nCompression = 0;
+    HFAGetBandInfo(hHFA, nBand, &eHFADataType,
+                   &nBlockXSize, &nBlockYSize, &nCompression);
+
+    // If this is an overview, we need to fetch the actual size,
+    // and block size.
     if( iOverview > -1 )
     {
         EPTType eHFADataTypeO;
 
         nOverviews = 0;
-        if (HFAGetOverviewInfo( hHFA, nBand, iOverview,
-                                &nRasterXSize, &nRasterYSize,
-                                &nBlockXSize, &nBlockYSize, &eHFADataTypeO ) != CE_None)
+        if( HFAGetOverviewInfo(
+               hHFA, nBand, iOverview,
+               &nRasterXSize, &nRasterYSize,
+               &nBlockXSize, &nBlockYSize, &eHFADataTypeO ) != CE_None )
         {
-            nRasterXSize = nRasterYSize = 0;
+            nRasterXSize = 0;
+            nRasterYSize = 0;
             return;
         }
 
-/* -------------------------------------------------------------------- */
-/*      If we are an 8bit overview of a 1bit layer, we need to mark     */
-/*      ourselves as being "resample: average_bit2grayscale".           */
-/* -------------------------------------------------------------------- */
+        // If we are an 8bit overview of a 1bit layer, we need to mark
+        // ourselves as being "resample: average_bit2grayscale".
         if( eHFADataType == EPT_u1 && eHFADataTypeO == EPT_u8 )
         {
-            GDALMajorObject::SetMetadataItem( "RESAMPLING",
-                                              "AVERAGE_BIT2GRAYSCALE" );
-            GDALMajorObject::SetMetadataItem( "NBITS", "8" );
+            GDALMajorObject::SetMetadataItem("RESAMPLING",
+                                             "AVERAGE_BIT2GRAYSCALE");
+            GDALMajorObject::SetMetadataItem("NBITS", "8");
         }
         eHFADataType = eHFADataTypeO;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set some other information.                                     */
-/* -------------------------------------------------------------------- */
+    // Set some other information.
     if( nCompression != 0 )
-        GDALMajorObject::SetMetadataItem( "COMPRESSION", "RLE",
-                                          "IMAGE_STRUCTURE" );
+        GDALMajorObject::SetMetadataItem("COMPRESSION", "RLE",
+                                         "IMAGE_STRUCTURE");
 
     switch( eHFADataType )
     {
-      case EPT_u1:
-      case EPT_u2:
-      case EPT_u4:
-      case EPT_u8:
-      case EPT_s8:
+    case EPT_u1:
+    case EPT_u2:
+    case EPT_u4:
+    case EPT_u8:
+    case EPT_s8:
         eDataType = GDT_Byte;
         break;
 
-      case EPT_u16:
+    case EPT_u16:
         eDataType = GDT_UInt16;
         break;
 
-      case EPT_s16:
+    case EPT_s16:
         eDataType = GDT_Int16;
         break;
 
-      case EPT_u32:
+    case EPT_u32:
         eDataType = GDT_UInt32;
         break;
 
-      case EPT_s32:
+    case EPT_s32:
         eDataType = GDT_Int32;
         break;
 
-      case EPT_f32:
+    case EPT_f32:
         eDataType = GDT_Float32;
         break;
 
-      case EPT_f64:
+    case EPT_f64:
         eDataType = GDT_Float64;
         break;
 
-      case EPT_c64:
+    case EPT_c64:
         eDataType = GDT_CFloat32;
         break;
 
-      case EPT_c128:
+    case EPT_c128:
         eDataType = GDT_CFloat64;
         break;
 
-      default:
+    default:
         eDataType = GDT_Byte;
-        /* notdef: this should really report an error, but this isn't
-           so easy from within constructors. */
-        CPLDebug( "GDAL", "Unsupported pixel type in HFARasterBand: %d.",
-                  eHFADataType );
+        // This should really report an error, but this isn't
+        // so easy from within constructors.
+        CPLDebug("GDAL", "Unsupported pixel type in HFARasterBand: %d.",
+                 eHFADataType);
         break;
     }
 
-    if( HFAGetDataTypeBits( eHFADataType ) < 8 )
+    if( HFAGetDataTypeBits(eHFADataType) < 8 )
     {
         GDALMajorObject::SetMetadataItem(
             "NBITS",
-            CPLString().Printf( "%d", HFAGetDataTypeBits( eHFADataType ) ), "IMAGE_STRUCTURE" );
+            CPLString().Printf("%d", HFAGetDataTypeBits(eHFADataType)),
+            "IMAGE_STRUCTURE");
     }
 
     if( eHFADataType == EPT_s8 )
     {
-        GDALMajorObject::SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
-                                          "IMAGE_STRUCTURE" );
+        GDALMajorObject::SetMetadataItem("PIXELTYPE", "SIGNEDBYTE",
+                                         "IMAGE_STRUCTURE");
     }
 
-/* -------------------------------------------------------------------- */
-/*      Collect color table if present.                                 */
-/* -------------------------------------------------------------------- */
-    double    *padfRed, *padfGreen, *padfBlue, *padfAlpha, *padfBins;
-    int       nColors;
+    // Collect color table if present.
+    double *padfRed = NULL;
+    double *padfGreen = NULL;
+    double *padfBlue = NULL;
+    double *padfAlpha = NULL;
+    double *padfBins = NULL;
+    int nColors = 0;
 
-    if( iOverview == -1
-        && HFAGetPCT( hHFA, nBand, &nColors,
-                      &padfRed, &padfGreen, &padfBlue, &padfAlpha,
-                      &padfBins ) == CE_None
-        && nColors > 0 )
+    if( iOverview == -1 &&
+        HFAGetPCT(hHFA, nBand, &nColors,
+                     &padfRed, &padfGreen, &padfBlue, &padfAlpha,
+                     &padfBins) == CE_None &&
+        nColors > 0 )
     {
         poCT = new GDALColorTable();
         for( int iColor = 0; iColor < nColors; iColor++ )
         {
-            GDALColorEntry   sEntry;
-
             // The following mapping assigns "equal sized" section of
             // the [0...1] range to each possible output value and avoid
             // rounding issues for the "normal" values generated using n/255.
             // See bug #1732 for some discussion.
-            sEntry.c1 = MIN(255,(short) (padfRed[iColor]   * 256));
-            sEntry.c2 = MIN(255,(short) (padfGreen[iColor] * 256));
-            sEntry.c3 = MIN(255,(short) (padfBlue[iColor]  * 256));
-            sEntry.c4 = MIN(255,(short) (padfAlpha[iColor] * 256));
+            GDALColorEntry sEntry = {
+                ColorToShort(padfRed[iColor]),
+                ColorToShort(padfGreen[iColor]),
+                ColorToShort(padfBlue[iColor]),
+                ColorToShort(padfAlpha[iColor])
+            };
 
             if( padfBins != NULL )
-                poCT->SetColorEntry( (int) padfBins[iColor], &sEntry );
+                poCT->SetColorEntry(static_cast<int>(padfBins[iColor]),
+                                    &sEntry);
             else
-                poCT->SetColorEntry( iColor, &sEntry );
+                poCT->SetColorEntry(iColor, &sEntry);
         }
     }
-
 }
 
 /************************************************************************/
@@ -2092,7 +2002,7 @@ HFARasterBand::~HFARasterBand()
     {
         delete papoOverviewBands[iOvIndex];
     }
-    CPLFree( papoOverviewBands );
+    CPLFree(papoOverviewBands);
 
     if( poCT != NULL )
         delete poCT;
@@ -2108,53 +2018,53 @@ HFARasterBand::~HFARasterBand()
 void HFARasterBand::ReadAuxMetadata()
 
 {
-    // only load metadata for full resolution layer.
+    // Only load metadata for full resolution layer.
     if( nThisOverview != -1 )
         return;
 
     HFABand *poBand = hHFA->papoBand[nBand-1];
 
-    const char * const * pszAuxMetaData = GetHFAAuxMetaDataList();
+    const char *const *pszAuxMetaData = GetHFAAuxMetaDataList();
     for( int i = 0; pszAuxMetaData[i] != NULL; i += 4 )
     {
-        HFAEntry *poEntry;
-
-        if( strlen(pszAuxMetaData[i]) > 0 )
-            poEntry = poBand->poNode->GetNamedChild( pszAuxMetaData[i] );
-        else
-            poEntry = poBand->poNode;
-
-        const char *pszFieldName = pszAuxMetaData[i+1] + 1;
-        CPLErr eErr = CE_None;
+        HFAEntry *poEntry = (strlen(pszAuxMetaData[i]) > 0)
+            ? poBand->poNode->GetNamedChild(pszAuxMetaData[i])
+            : poBand->poNode;
 
         if( poEntry == NULL )
             continue;
 
-        switch( pszAuxMetaData[i+1][0] )
+        const char *pszFieldName = pszAuxMetaData[i + 1] + 1;
+
+        switch( pszAuxMetaData[i + 1][0] )
         {
           case 'd':
           {
               CPLString osValueList;
 
-              int nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
-              for( int iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
+              CPLErr eErr = CE_None;
+              const int nCount = poEntry->GetFieldCount(pszFieldName, &eErr);
+              for( int iValue = 0;
+                   eErr == CE_None && iValue < nCount;
+                   iValue++ )
               {
                   CPLString osSubFieldName;
-                  osSubFieldName.Printf( "%s[%d]", pszFieldName, iValue );
-                  double dfValue
-                      = poEntry->GetDoubleField( osSubFieldName, &eErr );
+                  osSubFieldName.Printf("%s[%d]", pszFieldName, iValue);
+                  const double dfValue =
+                      poEntry->GetDoubleField(osSubFieldName, &eErr);
                   if( eErr != CE_None )
                       break;
 
-                  char szValueAsString[100];
-                  CPLsnprintf( szValueAsString, sizeof(szValueAsString), "%.14g", dfValue );
+                  char szValueAsString[100] = {};
+                  CPLsnprintf(szValueAsString, sizeof(szValueAsString),
+                              "%.14g", dfValue);
 
                   if( iValue > 0 )
                       osValueList += ",";
                   osValueList += szValueAsString;
               }
               if( eErr == CE_None )
-                  SetMetadataItem( pszAuxMetaData[i+2], osValueList );
+                  SetMetadataItem(pszAuxMetaData[i + 2], osValueList);
           }
           break;
           case 'i':
@@ -2162,37 +2072,42 @@ void HFARasterBand::ReadAuxMetadata()
           {
               CPLString osValueList;
 
-              int nCount = poEntry->GetFieldCount( pszFieldName, &eErr );
-              for( int iValue = 0; eErr == CE_None && iValue < nCount; iValue++ )
+              CPLErr eErr = CE_None;
+              const int nCount = poEntry->GetFieldCount(pszFieldName, &eErr);
+              for( int iValue = 0;
+                   eErr == CE_None && iValue < nCount;
+                   iValue++ )
               {
                   CPLString osSubFieldName;
-                  osSubFieldName.Printf( "%s[%d]", pszFieldName, iValue );
-                  int nValue = poEntry->GetIntField( osSubFieldName, &eErr );
+                  osSubFieldName.Printf("%s[%d]", pszFieldName, iValue);
+                  int nValue = poEntry->GetIntField(osSubFieldName, &eErr);
                   if( eErr != CE_None )
                       break;
 
-                  char szValueAsString[100];
-                  snprintf( szValueAsString, sizeof(szValueAsString), "%d", nValue );
+                  char szValueAsString[100] = {};
+                  snprintf(szValueAsString, sizeof(szValueAsString),
+                           "%d", nValue);
 
                   if( iValue > 0 )
                       osValueList += ",";
                   osValueList += szValueAsString;
               }
               if( eErr == CE_None )
-                  SetMetadataItem( pszAuxMetaData[i+2], osValueList );
+                  SetMetadataItem(pszAuxMetaData[i + 2], osValueList);
           }
           break;
           case 's':
           case 'e':
           {
-              const char *pszValue
-                  = poEntry->GetStringField( pszFieldName, &eErr );
+              CPLErr eErr = CE_None;
+              const char *pszValue =
+                  poEntry->GetStringField(pszFieldName, &eErr);
               if( eErr == CE_None )
-                  SetMetadataItem( pszAuxMetaData[i+2], pszValue );
+                  SetMetadataItem(pszAuxMetaData[i + 2], pszValue);
           }
           break;
           default:
-            CPLAssert( FALSE );
+            CPLAssert(false);
         }
     }
 }
@@ -2204,157 +2119,191 @@ void HFARasterBand::ReadAuxMetadata()
 void HFARasterBand::ReadHistogramMetadata()
 
 {
-    // only load metadata for full resolution layer.
+    // Only load metadata for full resolution layer.
     if( nThisOverview != -1 )
         return;
 
     HFABand *poBand = hHFA->papoBand[nBand-1];
 
     HFAEntry *poEntry =
-        poBand->poNode->GetNamedChild( "Descriptor_Table.Histogram" );
-    if ( poEntry == NULL )
+        poBand->poNode->GetNamedChild("Descriptor_Table.Histogram");
+    if( poEntry == NULL )
         return;
 
-    int nNumBins = poEntry->GetIntField( "numRows" );
-    if (nNumBins < 0)
+    int nNumBins = poEntry->GetIntField("numRows");
+    if( nNumBins < 0 )
         return;
+    // TODO(schwehr): Can we do a better/tighter check?
+    if( nNumBins > 1000000 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Unreasonably large histogram: %d", nNumBins);
+        return;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Fetch the histogram values.                                     */
-/* -------------------------------------------------------------------- */
-
-    int nOffset =  poEntry->GetIntField( "columnDataPtr" );
-    const char *pszType =  poEntry->GetStringField( "dataType" );
+    // Fetch the histogram values.
+    const int nOffset = poEntry->GetIntField("columnDataPtr");
+    const char *pszType = poEntry->GetStringField("dataType");
     int nBinSize = 4;
 
     if( pszType != NULL && STARTS_WITH_CI(pszType, "real") )
         nBinSize = 8;
 
-    GUIntBig *panHistValues = (GUIntBig *) VSI_MALLOC2_VERBOSE(sizeof(GUIntBig), nNumBins);
-    GByte  *pabyWorkBuf = (GByte *) VSI_MALLOC2_VERBOSE(nBinSize, nNumBins);
+    GUIntBig *panHistValues = static_cast<GUIntBig *>(
+        VSI_MALLOC2_VERBOSE(sizeof(GUIntBig), nNumBins));
+    GByte *pabyWorkBuf =
+        static_cast<GByte *>(VSI_MALLOC2_VERBOSE(nBinSize, nNumBins));
 
-    if (panHistValues == NULL || pabyWorkBuf == NULL)
+    if( panHistValues == NULL || pabyWorkBuf == NULL )
     {
         VSIFree(panHistValues);
         VSIFree(pabyWorkBuf);
         return;
     }
 
-    if( VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) != 0 ||
-        (int)VSIFReadL( pabyWorkBuf, nBinSize, nNumBins, hHFA->fp ) != nNumBins)
+    if( VSIFSeekL(hHFA->fp, nOffset, SEEK_SET) != 0 ||
+        static_cast<int>(VSIFReadL(pabyWorkBuf, nBinSize, nNumBins,
+                                   hHFA->fp)) != nNumBins)
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Cannot read histogram values." );
-        CPLFree( panHistValues );
-        CPLFree( pabyWorkBuf );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Cannot read histogram values.");
+        CPLFree(panHistValues);
+        CPLFree(pabyWorkBuf);
         return;
     }
 
     // Swap into local order.
     for( int i = 0; i < nNumBins; i++ )
-        HFAStandard( nBinSize, pabyWorkBuf + i*nBinSize );
+        HFAStandard(nBinSize, pabyWorkBuf + i * nBinSize);
 
-    if( nBinSize == 8 ) // source is doubles
+    if( nBinSize == 8 )  // Source is doubles.
     {
+        const double *padfWorkBuf = reinterpret_cast<double *>(pabyWorkBuf);
         for( int i = 0; i < nNumBins; i++ )
-            panHistValues[i] = (GUIntBig) ((double *) pabyWorkBuf)[i];
+        {
+            const double dfNumber = padfWorkBuf[i];
+            if( dfNumber >= std::numeric_limits<GUIntBig>::max() ||
+                dfNumber < std::numeric_limits<GUIntBig>::min() ||
+                CPLIsNan(dfNumber) )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "Out of range hist vals.");
+                CPLFree(panHistValues);
+                CPLFree(pabyWorkBuf);
+                return;
+            }
+            panHistValues[i] = static_cast<GUIntBig>(dfNumber);
+        }
     }
-    else // source is 32bit integers
+    else  // Source is 32bit integers.
     {
+        const int *panWorkBuf = reinterpret_cast<int *>(pabyWorkBuf);
         for( int i = 0; i < nNumBins; i++ )
-            panHistValues[i] = (GUIntBig) ((int *) pabyWorkBuf)[i];
+        {
+            const int nNumber = panWorkBuf[i];
+            // Positive int should always fit.
+            if( nNumber < 0 )
+            {
+                CPLError(CE_Failure, CPLE_FileIO, "Out of range hist vals.");
+                CPLFree(panHistValues);
+                CPLFree(pabyWorkBuf);
+                return;
+            }
+            panHistValues[i] = static_cast<GUIntBig>(nNumber);
+        }
     }
 
-    CPLFree( pabyWorkBuf );
+    CPLFree(pabyWorkBuf);
     pabyWorkBuf = NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Do we have unique values for the bins?                          */
-/* -------------------------------------------------------------------- */
+    // Do we have unique values for the bins?
     double *padfBinValues = NULL;
-    HFAEntry *poBinEntry = poBand->poNode->GetNamedChild( "Descriptor_Table.#Bin_Function840#" );
+    HFAEntry *poBinEntry =
+        poBand->poNode->GetNamedChild("Descriptor_Table.#Bin_Function840#");
 
-    if( poBinEntry != NULL
-        && EQUAL(poBinEntry->GetType(),"Edsc_BinFunction840")  )
+    if( poBinEntry != NULL &&
+        EQUAL(poBinEntry->GetType(), "Edsc_BinFunction840") )
     {
-        const char* pszValue = poBinEntry->GetStringField( "binFunction.type.string" );
-        if( pszValue && EQUAL(pszValue,"BFUnique") )
-            padfBinValues = HFAReadBFUniqueBins( poBinEntry, nNumBins );
+        const char *pszValue =
+            poBinEntry->GetStringField("binFunction.type.string");
+        if( pszValue && EQUAL(pszValue, "BFUnique") )
+            padfBinValues = HFAReadBFUniqueBins(poBinEntry, nNumBins);
     }
 
     if( padfBinValues )
     {
         int nMaxValue = 0;
         int nMinValue = 1000000;
-        int bAllInteger = TRUE;
+        bool bAllInteger = true;
 
         for( int i = 0; i < nNumBins; i++ )
         {
             if( padfBinValues[i] != floor(padfBinValues[i]) )
-                bAllInteger = FALSE;
+                bAllInteger = false;
 
-            nMaxValue = MAX(nMaxValue,(int)padfBinValues[i]);
-            nMinValue = MIN(nMinValue,(int)padfBinValues[i]);
+            nMaxValue = std::max(nMaxValue, static_cast<int>(padfBinValues[i]));
+            nMinValue = std::min(nMinValue, static_cast<int>(padfBinValues[i]));
         }
 
         if( nMinValue < 0 || nMaxValue > 1000 || !bAllInteger )
         {
-            CPLFree( padfBinValues );
-            CPLFree( panHistValues );
-            CPLDebug( "HFA", "Unable to offer histogram because unique values list is not convenient to reform as HISTOBINVALUES." );
+            CPLFree(padfBinValues);
+            CPLFree(panHistValues);
+            CPLDebug("HFA", "Unable to offer histogram because unique values "
+                     "list is not convenient to reform as HISTOBINVALUES.");
             return;
         }
 
         const int nNewBins = nMaxValue + 1;
-        GUIntBig *panNewHistValues = (GUIntBig *) CPLCalloc(sizeof(GUIntBig),nNewBins);
+        GUIntBig *panNewHistValues =
+            static_cast<GUIntBig *>(CPLCalloc(sizeof(GUIntBig), nNewBins));
 
         for( int i = 0; i < nNumBins; i++ )
-            panNewHistValues[(int) padfBinValues[i]] = panHistValues[i];
+            panNewHistValues[static_cast<int>(padfBinValues[i])] =
+                panHistValues[i];
 
-        CPLFree( panHistValues );
+        CPLFree(panHistValues);
         panHistValues = panNewHistValues;
         nNumBins = nNewBins;
 
-        SetMetadataItem( "STATISTICS_HISTOMIN", "0" );
-        SetMetadataItem( "STATISTICS_HISTOMAX",
-                         CPLString().Printf("%d", nMaxValue ) );
-        SetMetadataItem( "STATISTICS_HISTONUMBINS",
-                         CPLString().Printf("%d", nMaxValue+1 ) );
+        SetMetadataItem("STATISTICS_HISTOMIN", "0");
+        SetMetadataItem("STATISTICS_HISTOMAX",
+                        CPLString().Printf("%d", nMaxValue));
+        SetMetadataItem("STATISTICS_HISTONUMBINS",
+                        CPLString().Printf("%d", nMaxValue + 1));
 
         CPLFree(padfBinValues);
         padfBinValues = NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Format into HISTOBINVALUES text format.                         */
-/* -------------------------------------------------------------------- */
+    // Format into HISTOBINVALUES text format.
     unsigned int nBufSize = 1024;
-    char * pszBinValues = (char *)CPLMalloc( nBufSize );
-    int    nBinValuesLen = 0;
+    char *pszBinValues = static_cast<char *>(CPLMalloc(nBufSize));
     pszBinValues[0] = 0;
+    int nBinValuesLen = 0;
 
-    for ( int nBin = 0; nBin < nNumBins; ++nBin )
+    for( int nBin = 0; nBin < nNumBins; ++nBin )
     {
-        char szBuf[32];
-        snprintf( szBuf, 31, CPL_FRMT_GUIB, panHistValues[nBin] );
-        if ( ( nBinValuesLen + strlen( szBuf ) + 2 ) > nBufSize )
+        char szBuf[32] = {};
+        snprintf(szBuf, 31, CPL_FRMT_GUIB, panHistValues[nBin]);
+        if( (nBinValuesLen + strlen(szBuf) + 2) > nBufSize )
         {
             nBufSize *= 2;
-            char* pszNewBinValues = (char *)VSI_REALLOC_VERBOSE( pszBinValues, nBufSize );
-            if (pszNewBinValues == NULL)
+            char *pszNewBinValues = static_cast<char *>(
+                VSI_REALLOC_VERBOSE(pszBinValues, nBufSize));
+            if( pszNewBinValues == NULL )
             {
                 break;
             }
             pszBinValues = pszNewBinValues;
         }
-        strcat( pszBinValues+nBinValuesLen, szBuf );
-        strcat( pszBinValues+nBinValuesLen, "|" );
-        nBinValuesLen += static_cast<int>(strlen(pszBinValues+nBinValuesLen));
+        strcat(pszBinValues + nBinValuesLen, szBuf);
+        strcat(pszBinValues + nBinValuesLen, "|");
+        nBinValuesLen += static_cast<int>(strlen(pszBinValues + nBinValuesLen));
     }
 
-    SetMetadataItem( "STATISTICS_HISTOBINVALUES", pszBinValues );
-    CPLFree( panHistValues );
-    CPLFree( pszBinValues );
+    SetMetadataItem("STATISTICS_HISTOBINVALUES", pszBinValues);
+    CPLFree(panHistValues);
+    CPLFree(pszBinValues);
 }
 
 /************************************************************************/
@@ -2364,16 +2313,16 @@ void HFARasterBand::ReadHistogramMetadata()
 double HFARasterBand::GetNoDataValue( int *pbSuccess )
 
 {
-    double dfNoData;
+    double dfNoData = 0.0;
 
-    if( HFAGetBandNoData( hHFA, nBand, &dfNoData ) )
+    if( HFAGetBandNoData(hHFA, nBand, &dfNoData) )
     {
         if( pbSuccess )
             *pbSuccess = TRUE;
         return dfNoData;
     }
 
-    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+    return GDALPamRasterBand::GetNoDataValue(pbSuccess);
 }
 
 /************************************************************************/
@@ -2382,7 +2331,7 @@ double HFARasterBand::GetNoDataValue( int *pbSuccess )
 
 CPLErr HFARasterBand::SetNoDataValue( double dfValue )
 {
-    return HFASetBandNoData( hHFA, nBand, dfValue );
+    return HFASetBandNoData(hHFA, nBand, dfValue);
 }
 
 /************************************************************************/
@@ -2392,7 +2341,7 @@ CPLErr HFARasterBand::SetNoDataValue( double dfValue )
 double HFARasterBand::GetMinimum( int *pbSuccess )
 
 {
-    const char *pszValue = GetMetadataItem( "STATISTICS_MINIMUM" );
+    const char *pszValue = GetMetadataItem("STATISTICS_MINIMUM");
 
     if( pszValue != NULL )
     {
@@ -2401,7 +2350,7 @@ double HFARasterBand::GetMinimum( int *pbSuccess )
         return CPLAtofM(pszValue);
     }
 
-    return GDALRasterBand::GetMinimum( pbSuccess );
+    return GDALRasterBand::GetMinimum(pbSuccess);
 }
 
 /************************************************************************/
@@ -2411,7 +2360,7 @@ double HFARasterBand::GetMinimum( int *pbSuccess )
 double HFARasterBand::GetMaximum( int *pbSuccess )
 
 {
-    const char *pszValue = GetMetadataItem( "STATISTICS_MAXIMUM" );
+    const char *pszValue = GetMetadataItem("STATISTICS_MAXIMUM");
 
     if( pszValue != NULL )
     {
@@ -2420,7 +2369,7 @@ double HFARasterBand::GetMaximum( int *pbSuccess )
         return CPLAtofM(pszValue);
     }
 
-    return GDALRasterBand::GetMaximum( pbSuccess );
+    return GDALRasterBand::GetMaximum(pbSuccess);
 }
 
 /************************************************************************/
@@ -2435,17 +2384,17 @@ void HFARasterBand::EstablishOverviews()
     if( nOverviews != -1 )
         return;
 
-    nOverviews = HFAGetOverviewCount( hHFA, nBand );
+    nOverviews = HFAGetOverviewCount(hHFA, nBand);
     if( nOverviews > 0 )
     {
-        papoOverviewBands = (HFARasterBand **)
-            CPLMalloc(sizeof(void*)*nOverviews);
+        papoOverviewBands = static_cast<HFARasterBand **>(
+            CPLMalloc(sizeof(void*) * nOverviews));
 
         for( int iOvIndex = 0; iOvIndex < nOverviews; iOvIndex++ )
         {
             papoOverviewBands[iOvIndex] =
-                new HFARasterBand( (HFADataset *) poDS, nBand, iOvIndex );
-            if (papoOverviewBands[iOvIndex]->GetXSize() == 0)
+                new HFARasterBand((HFADataset *) poDS, nBand, iOvIndex);
+            if( papoOverviewBands[iOvIndex]->GetXSize() == 0 )
             {
                 delete papoOverviewBands[iOvIndex];
                 papoOverviewBands[iOvIndex] = NULL;
@@ -2479,7 +2428,7 @@ GDALRasterBand *HFARasterBand::GetOverview( int i )
     EstablishOverviews();
 
     if( nOverviews == 0 )
-        return GDALRasterBand::GetOverview( i );
+        return GDALRasterBand::GetOverview(i);
     else if( i < 0 || i >= nOverviews )
         return NULL;
     else
@@ -2491,54 +2440,54 @@ GDALRasterBand *HFARasterBand::GetOverview( int i )
 /************************************************************************/
 
 CPLErr HFARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                  void * pImage )
+                                  void *pImage )
 
 {
-    CPLErr	eErr;
+    CPLErr eErr = CE_None;
 
     if( nThisOverview == -1 )
-        eErr = HFAGetRasterBlockEx( hHFA, nBand, nBlockXOff, nBlockYOff,
-                                    pImage,
-                                    nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8) );
+        eErr = HFAGetRasterBlockEx(
+            hHFA, nBand, nBlockXOff, nBlockYOff,
+            pImage,
+            nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType) );
     else
-    {
-        eErr =  HFAGetOverviewRasterBlockEx( hHFA, nBand, nThisOverview,
-                                           nBlockXOff, nBlockYOff,
-                                           pImage,
-                                           nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8));
-    }
+        eErr = HFAGetOverviewRasterBlockEx(
+            hHFA, nBand, nThisOverview,
+            nBlockXOff, nBlockYOff,
+            pImage,
+            nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eDataType) );
 
     if( eErr == CE_None && eHFADataType == EPT_u4 )
     {
-        GByte	*pabyData = (GByte *) pImage;
+        GByte *pabyData = static_cast<GByte *>(pImage);
 
         for( int ii = nBlockXSize * nBlockYSize - 2; ii >= 0; ii -= 2 )
         {
-            int k = ii>>1;
-            pabyData[ii+1] = (pabyData[k]>>4) & 0xf;
-            pabyData[ii]   = (pabyData[k]) & 0xf;
+            int k = ii >> 1;
+            pabyData[ii + 1] = (pabyData[k] >> 4) & 0xf;
+            pabyData[ii] = (pabyData[k]) & 0xf;
         }
     }
     if( eErr == CE_None && eHFADataType == EPT_u2 )
     {
-        GByte	*pabyData = (GByte *) pImage;
+        GByte *pabyData = static_cast<GByte *>(pImage);
 
         for( int ii = nBlockXSize * nBlockYSize - 4; ii >= 0; ii -= 4 )
         {
-            int k = ii>>2;
-            pabyData[ii+3] = (pabyData[k]>>6) & 0x3;
-            pabyData[ii+2] = (pabyData[k]>>4) & 0x3;
-            pabyData[ii+1] = (pabyData[k]>>2) & 0x3;
-            pabyData[ii]   = (pabyData[k]) & 0x3;
+            int k = ii >> 2;
+            pabyData[ii + 3] = (pabyData[k] >> 6) & 0x3;
+            pabyData[ii + 2] = (pabyData[k] >> 4) & 0x3;
+            pabyData[ii + 1] = (pabyData[k] >> 2) & 0x3;
+            pabyData[ii] = (pabyData[k]) & 0x3;
         }
     }
     if( eErr == CE_None && eHFADataType == EPT_u1)
     {
-        GByte	*pabyData = (GByte *) pImage;
+        GByte *pabyData = static_cast<GByte *>(pImage);
 
         for( int ii = nBlockXSize * nBlockYSize - 1; ii >= 0; ii-- )
         {
-            if( (pabyData[ii>>3] & (1 << (ii & 0x7))) )
+            if( (pabyData[ii >> 3] & (1 << (ii & 0x7))) )
                 pabyData[ii] = 1;
             else
                 pabyData[ii] = 0;
@@ -2553,78 +2502,69 @@ CPLErr HFARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr HFARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-                                   void * pImage )
+                                   void *pImage )
 
 {
-    GByte *pabyOutBuf = (GByte *) pImage;
-
-/* -------------------------------------------------------------------- */
-/*      Do we need to pack 1/2/4 bit data?                              */
-/* -------------------------------------------------------------------- */
-    if( eHFADataType == EPT_u1
-        || eHFADataType == EPT_u2
-        || eHFADataType == EPT_u4 )
-    {
-        const int nPixCount =  nBlockXSize * nBlockYSize;
-        pabyOutBuf = (GByte *) VSIMalloc2(nBlockXSize, nBlockYSize);
-        if (pabyOutBuf == NULL)
+    GByte *pabyOutBuf = static_cast<GByte *>(pImage);
+
+    // Do we need to pack 1/2/4 bit data?
+    // TODO(schwehr): Make symbolic constants with explanations.
+    if( eHFADataType == EPT_u1 ||
+        eHFADataType == EPT_u2 ||
+        eHFADataType == EPT_u4 )
+    {
+        const int nPixCount = nBlockXSize * nBlockYSize;
+        pabyOutBuf = static_cast<GByte *>(VSIMalloc2(nBlockXSize, nBlockYSize));
+        if( pabyOutBuf == NULL )
             return CE_Failure;
 
         if( eHFADataType == EPT_u1 )
         {
             for( int ii = 0; ii < nPixCount - 7; ii += 8 )
             {
-                int k = ii>>3;
-                pabyOutBuf[k] =
-                    (((GByte *) pImage)[ii] & 0x1)
-                    | ((((GByte *) pImage)[ii+1]&0x1) << 1)
-                    | ((((GByte *) pImage)[ii+2]&0x1) << 2)
-                    | ((((GByte *) pImage)[ii+3]&0x1) << 3)
-                    | ((((GByte *) pImage)[ii+4]&0x1) << 4)
-                    | ((((GByte *) pImage)[ii+5]&0x1) << 5)
-                    | ((((GByte *) pImage)[ii+6]&0x1) << 6)
-                    | ((((GByte *) pImage)[ii+7]&0x1) << 7);
+                const int k = ii >> 3;
+                // TODO(schwehr): Create a temp for (GByte *)pImage.
+                pabyOutBuf[k] = (((GByte *)pImage)[ii] & 0x1) |
+                                ((((GByte *)pImage)[ii + 1] & 0x1) << 1) |
+                                ((((GByte *)pImage)[ii + 2] & 0x1) << 2) |
+                                ((((GByte *)pImage)[ii + 3] & 0x1) << 3) |
+                                ((((GByte *)pImage)[ii + 4] & 0x1) << 4) |
+                                ((((GByte *)pImage)[ii + 5] & 0x1) << 5) |
+                                ((((GByte *)pImage)[ii + 6] & 0x1) << 6) |
+                                ((((GByte *)pImage)[ii + 7] & 0x1) << 7);
             }
         }
         else if( eHFADataType == EPT_u2 )
         {
             for( int ii = 0; ii < nPixCount - 3; ii += 4 )
             {
-                int k = ii>>2;
-                pabyOutBuf[k] =
-                    (((GByte *) pImage)[ii] & 0x3)
-                    | ((((GByte *) pImage)[ii+1]&0x3) << 2)
-                    | ((((GByte *) pImage)[ii+2]&0x3) << 4)
-                    | ((((GByte *) pImage)[ii+3]&0x3) << 6);
+                const int k = ii >> 2;
+                pabyOutBuf[k] = (((GByte *)pImage)[ii] & 0x3) |
+                                ((((GByte *)pImage)[ii + 1] & 0x3) << 2) |
+                                ((((GByte *)pImage)[ii + 2] & 0x3) << 4) |
+                                ((((GByte *)pImage)[ii + 3] & 0x3) << 6);
             }
         }
         else if( eHFADataType == EPT_u4 )
         {
             for( int ii = 0; ii < nPixCount - 1; ii += 2 )
             {
-                int k = ii>>1;
-                pabyOutBuf[k] =
-                    (((GByte *) pImage)[ii] & 0xf)
-                    | ((((GByte *) pImage)[ii+1]&0xf) << 4);
+                const int k = ii >> 1;
+                pabyOutBuf[k] = (((GByte *)pImage)[ii] & 0xf) |
+                                ((((GByte *)pImage)[ii + 1] & 0xf) << 4);
             }
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Actually write out.                                             */
-/* -------------------------------------------------------------------- */
-    CPLErr nRetCode;
-
-    if( nThisOverview == -1 )
-        nRetCode = HFASetRasterBlock( hHFA, nBand, nBlockXOff, nBlockYOff,
-                                      pabyOutBuf );
-    else
-        nRetCode = HFASetOverviewRasterBlock( hHFA, nBand, nThisOverview,
-                                              nBlockXOff, nBlockYOff,
-                                              pabyOutBuf );
+    // Actually write out.
+    const CPLErr nRetCode =
+        nThisOverview == -1
+        ? HFASetRasterBlock(hHFA, nBand, nBlockXOff, nBlockYOff, pabyOutBuf)
+        : HFASetOverviewRasterBlock(hHFA, nBand, nThisOverview,
+                                    nBlockXOff, nBlockYOff, pabyOutBuf);
 
-    if( pabyOutBuf != pImage  )
-        CPLFree( pabyOutBuf );
+    if( pabyOutBuf != pImage )
+        CPLFree(pabyOutBuf);
 
     return nRetCode;
 }
@@ -2633,9 +2573,9 @@ CPLErr HFARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /*                         GetDescription()                             */
 /************************************************************************/
 
-const char * HFARasterBand::GetDescription() const
+const char *HFARasterBand::GetDescription() const
 {
-    const char *pszName = HFAGetBandName( hHFA, nBand );
+    const char *pszName = HFAGetBandName(hHFA, nBand);
 
     if( pszName == NULL )
         return GDALPamRasterBand::GetDescription();
@@ -2649,7 +2589,7 @@ const char * HFARasterBand::GetDescription() const
 void HFARasterBand::SetDescription( const char *pszName )
 {
     if( strlen(pszName) > 0 )
-        HFASetBandName( hHFA, nBand, pszName );
+        HFASetBandName(hHFA, nBand, pszName);
 }
 
 /************************************************************************/
@@ -2669,56 +2609,50 @@ GDALColorInterp HFARasterBand::GetColorInterpretation()
 /*                           GetColorTable()                            */
 /************************************************************************/
 
-GDALColorTable *HFARasterBand::GetColorTable()
-
-{
-    return poCT;
-}
+GDALColorTable *HFARasterBand::GetColorTable() { return poCT; }
 
 /************************************************************************/
 /*                           SetColorTable()                            */
 /************************************************************************/
 
-CPLErr HFARasterBand::SetColorTable( GDALColorTable * poCTable )
+CPLErr HFARasterBand::SetColorTable( GDALColorTable *poCTable )
 
 {
     if( GetAccess() == GA_ReadOnly )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
-                  "Unable to set color table on read-only file." );
+        CPLError(CE_Failure, CPLE_NoWriteAccess,
+                 "Unable to set color table on read-only file.");
         return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Special case if we are clearing the color table.                */
-/* -------------------------------------------------------------------- */
+    // Special case if we are clearing the color table.
     if( poCTable == NULL )
     {
         delete poCT;
         poCT = NULL;
 
-        HFASetPCT( hHFA, nBand, 0, NULL, NULL, NULL, NULL );
+        HFASetPCT(hHFA, nBand, 0, NULL, NULL, NULL, NULL);
 
         return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write out the colortable, and update the configuration.         */
-/* -------------------------------------------------------------------- */
+    // Write out the colortable, and update the configuration.
     const int nColors = poCTable->GetColorEntryCount();
 
-    double *padfRed, *padfGreen, *padfBlue, *padfAlpha;
-
-    padfRed   = (double *) CPLMalloc(sizeof(double) * nColors);
-    padfGreen = (double *) CPLMalloc(sizeof(double) * nColors);
-    padfBlue  = (double *) CPLMalloc(sizeof(double) * nColors);
-    padfAlpha = (double *) CPLMalloc(sizeof(double) * nColors);
+    double *padfRed =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nColors));
+    double *padfGreen =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nColors));
+    double *padfBlue =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nColors));
+    double *padfAlpha =
+        static_cast<double *>(CPLMalloc(sizeof(double) * nColors));
 
     for( int iColor = 0; iColor < nColors; iColor++ )
     {
-        GDALColorEntry  sRGB;
+        GDALColorEntry sRGB;
 
-        poCTable->GetColorEntryAsRGB( iColor, &sRGB );
+        poCTable->GetColorEntryAsRGB(iColor, &sRGB);
 
         padfRed[iColor] = sRGB.c1 / 255.0;
         padfGreen[iColor] = sRGB.c2 / 255.0;
@@ -2726,13 +2660,12 @@ CPLErr HFARasterBand::SetColorTable( GDALColorTable * poCTable )
         padfAlpha[iColor] = sRGB.c4 / 255.0;
     }
 
-    HFASetPCT( hHFA, nBand, nColors,
-	       padfRed, padfGreen, padfBlue, padfAlpha);
+    HFASetPCT(hHFA, nBand, nColors, padfRed, padfGreen, padfBlue, padfAlpha);
 
-    CPLFree( padfRed );
-    CPLFree( padfGreen );
-    CPLFree( padfBlue );
-    CPLFree( padfAlpha );
+    CPLFree(padfRed);
+    CPLFree(padfGreen);
+    CPLFree(padfBlue);
+    CPLFree(padfAlpha);
 
     if( poCT )
       delete poCT;
@@ -2749,9 +2682,9 @@ CPLErr HFARasterBand::SetColorTable( GDALColorTable * poCTable )
 CPLErr HFARasterBand::SetMetadata( char **papszMDIn, const char *pszDomain )
 
 {
-    bMetadataDirty = TRUE;
+    bMetadataDirty = true;
 
-    return GDALPamRasterBand::SetMetadata( papszMDIn, pszDomain );
+    return GDALPamRasterBand::SetMetadata(papszMDIn, pszDomain);
 }
 
 /************************************************************************/
@@ -2762,9 +2695,9 @@ CPLErr HFARasterBand::SetMetadataItem( const char *pszTag, const char *pszValue,
                                        const char *pszDomain )
 
 {
-    bMetadataDirty = TRUE;
+    bMetadataDirty = true;
 
-    return GDALPamRasterBand::SetMetadataItem( pszTag, pszValue, pszDomain );
+    return GDALPamRasterBand::SetMetadataItem(pszTag, pszValue, pszDomain);
 }
 
 /************************************************************************/
@@ -2777,56 +2710,47 @@ CPLErr HFARasterBand::CleanOverviews()
     if( nOverviews == 0 )
         return CE_None;
 
-/* -------------------------------------------------------------------- */
-/*      Clear our reference to overviews as bands.                      */
-/* -------------------------------------------------------------------- */
+    // Clear our reference to overviews as bands.
     for( int iOverview = 0; iOverview < nOverviews; iOverview++ )
         delete papoOverviewBands[iOverview];
 
-    CPLFree( papoOverviewBands );
+    CPLFree(papoOverviewBands);
     papoOverviewBands = NULL;
     nOverviews = 0;
 
-/* -------------------------------------------------------------------- */
-/*      Search for any RRDNamesList and destroy it.                     */
-/* -------------------------------------------------------------------- */
-    HFABand *poBand = hHFA->papoBand[nBand-1];
-    HFAEntry *poEntry = poBand->poNode->GetNamedChild( "RRDNamesList" );
+    // Search for any RRDNamesList and destroy it.
+    HFABand *poBand = hHFA->papoBand[nBand - 1];
+    HFAEntry *poEntry = poBand->poNode->GetNamedChild("RRDNamesList");
     if( poEntry != NULL )
     {
         poEntry->RemoveAndDestroy();
     }
 
-/* -------------------------------------------------------------------- */
-/*      Destroy and subsample layers under our band.                    */
-/* -------------------------------------------------------------------- */
+    // Destroy and subsample layers under our band.
     for( HFAEntry *poChild = poBand->poNode->GetChild();
          poChild != NULL; )
     {
         HFAEntry *poNext = poChild->GetNext();
 
-        if( EQUAL(poChild->GetType(),"Eimg_Layer_SubSample") )
+        if( EQUAL(poChild->GetType(), "Eimg_Layer_SubSample") )
             poChild->RemoveAndDestroy();
 
         poChild = poNext;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Clean up dependent file if we are the last band under the       */
-/*      assumption there will be nothing else referencing it after      */
-/*      this.                                                           */
-/* -------------------------------------------------------------------- */
+    // Clean up dependent file if we are the last band under the
+    // assumption there will be nothing else referencing it after
+    // this.
     if( hHFA->psDependent != hHFA && hHFA->psDependent != NULL )
     {
-        CPLString osFilename =
-            CPLFormFilename( hHFA->psDependent->pszPath,
-                             hHFA->psDependent->pszFilename, NULL );
+        CPLString osFilename = CPLFormFilename(
+            hHFA->psDependent->pszPath, hHFA->psDependent->pszFilename, NULL);
 
-        CPL_IGNORE_RET_VAL(HFAClose( hHFA->psDependent ));
+        CPL_IGNORE_RET_VAL(HFAClose(hHFA->psDependent));
         hHFA->psDependent = NULL;
 
-        CPLDebug( "HFA", "Unlink(%s)", osFilename.c_str() );
-        VSIUnlink( osFilename );
+        CPLDebug("HFA", "Unlink(%s)", osFilename.c_str());
+        VSIUnlink(osFilename);
     }
 
     return CE_None;
@@ -2846,8 +2770,8 @@ CPLErr HFARasterBand::BuildOverviews( const char *pszResampling,
 
     if( nThisOverview != -1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to build overviews on an overview layer." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Attempt to build overviews on an overview layer.");
 
         return CE_Failure;
     }
@@ -2855,89 +2779,81 @@ CPLErr HFARasterBand::BuildOverviews( const char *pszResampling,
     if( nReqOverviews == 0 )
         return CleanOverviews();
 
-    GDALRasterBand **papoOvBands
-        = (GDALRasterBand **) CPLCalloc(sizeof(void*),nReqOverviews);
+    GDALRasterBand **papoOvBands = static_cast<GDALRasterBand **>(
+        CPLCalloc(sizeof(void*), nReqOverviews));
 
-    int bNoRegen = FALSE;
+    bool bNoRegen = false;
     if( STARTS_WITH_CI(pszResampling, "NO_REGEN:") )
     {
         pszResampling += 9;
-        bNoRegen = TRUE;
+        bNoRegen = true;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Loop over overview levels requested.                            */
-/* -------------------------------------------------------------------- */
+    // Loop over overview levels requested.
     for( int iOverview = 0; iOverview < nReqOverviews; iOverview++ )
     {
-/* -------------------------------------------------------------------- */
-/*      Find this overview level.                                       */
-/* -------------------------------------------------------------------- */
-        int nReqOvLevel =
-            GDALOvLevelAdjust2(panOverviewList[iOverview],nRasterXSize,nRasterYSize);
+        // Find this overview level.
+        const int nReqOvLevel =
+            GDALOvLevelAdjust2(panOverviewList[iOverview],
+                               nRasterXSize, nRasterYSize);
 
         for( int i = 0; i < nOverviews && papoOvBands[iOverview] == NULL; i++ )
         {
             if( papoOverviewBands[i] == NULL )
             {
-                CPLDebug("HFA", "Shouldn't happen happened at line %d", __LINE__);
+                CPLDebug("HFA",
+                         "Shouldn't happen happened at line %d", __LINE__);
                 continue;
             }
 
-            int nThisOvLevel = GDALComputeOvFactor(papoOverviewBands[i]->GetXSize(),
-                                                   GetXSize(),
-                                                   papoOverviewBands[i]->GetYSize(),
-                                                   GetYSize());
+            const int nThisOvLevel = GDALComputeOvFactor(
+                papoOverviewBands[i]->GetXSize(), GetXSize(),
+                papoOverviewBands[i]->GetYSize(), GetYSize());
 
             if( nReqOvLevel == nThisOvLevel )
                 papoOvBands[iOverview] = papoOverviewBands[i];
         }
 
-/* -------------------------------------------------------------------- */
-/*      If this overview level does not yet exist, create it now.       */
-/* -------------------------------------------------------------------- */
+        // If this overview level does not yet exist, create it now.
         if( papoOvBands[iOverview] == NULL )
         {
-            int iResult = HFACreateOverview( hHFA, nBand,
-                                         panOverviewList[iOverview],
-                                         pszResampling );
+            const int iResult = HFACreateOverview(hHFA, nBand,
+                                                  panOverviewList[iOverview],
+                                                  pszResampling);
             if( iResult < 0 )
             {
-                CPLFree( papoOvBands );
+                CPLFree(papoOvBands);
                 return CE_Failure;
             }
 
-            if( papoOverviewBands == NULL && nOverviews == 0 && iResult > 0)
+            if( papoOverviewBands == NULL && nOverviews == 0 && iResult > 0 )
             {
-                CPLDebug("HFA", "Shouldn't happen happened at line %d", __LINE__);
-                papoOverviewBands = (HFARasterBand **)
-                    CPLCalloc( sizeof(void*), iResult );
+                CPLDebug("HFA",
+                         "Shouldn't happen happened at line %d", __LINE__);
+                papoOverviewBands = static_cast<HFARasterBand **>(
+                    CPLCalloc(sizeof(void *), iResult));
             }
 
             nOverviews = iResult + 1;
-            papoOverviewBands = (HFARasterBand **)
-                CPLRealloc( papoOverviewBands, sizeof(void*) * nOverviews);
-            papoOverviewBands[iResult] = new HFARasterBand(
-                (HFADataset *) poDS, nBand, iResult );
+            papoOverviewBands = static_cast<HFARasterBand **>(
+                CPLRealloc(papoOverviewBands, sizeof(void *) * nOverviews));
+            papoOverviewBands[iResult] =
+                new HFARasterBand((HFADataset *)poDS, nBand, iResult);
 
             papoOvBands[iOverview] = papoOverviewBands[iResult];
         }
-
     }
 
-/* -------------------------------------------------------------------- */
-/*      Regenerate the overviews.                                       */
-/* -------------------------------------------------------------------- */
     CPLErr eErr = CE_None;
 
     if( !bNoRegen )
-        eErr = GDALRegenerateOverviews( (GDALRasterBandH) this,
-                                        nReqOverviews,
-                                        (GDALRasterBandH *) papoOvBands,
-                                        pszResampling,
-                                        pfnProgress, pProgressData );
+        eErr = GDALRegenerateOverviews((GDALRasterBandH) this,
+                                       nReqOverviews,
+                                       (GDALRasterBandH *) papoOvBands,
+                                       pszResampling,
+                                       pfnProgress, pProgressData);
 
-    CPLFree( papoOvBands );
+    CPLFree(papoOvBands);
 
     return eErr;
 }
@@ -2951,16 +2867,14 @@ HFARasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                     int *pnBuckets, GUIntBig ** ppanHistogram,
                                     int bForce,
                                     GDALProgressFunc pfnProgress,
-                                    void *pProgressData)
+                                    void *pProgressData )
 
 {
-    if( GetMetadataItem( "STATISTICS_HISTOBINVALUES" ) != NULL
-        && GetMetadataItem( "STATISTICS_HISTOMIN" ) != NULL
-        && GetMetadataItem( "STATISTICS_HISTOMAX" ) != NULL )
+    if( GetMetadataItem("STATISTICS_HISTOBINVALUES") != NULL &&
+        GetMetadataItem("STATISTICS_HISTOMIN") != NULL &&
+        GetMetadataItem("STATISTICS_HISTOMAX") != NULL )
     {
-        const char *pszNextBin;
-        const char *pszBinValues =
-            GetMetadataItem( "STATISTICS_HISTOBINVALUES" );
+        const char *pszBinValues = GetMetadataItem("STATISTICS_HISTOBINVALUES");
 
         *pdfMin = CPLAtof(GetMetadataItem("STATISTICS_HISTOMIN"));
         *pdfMax = CPLAtof(GetMetadataItem("STATISTICS_HISTOMAX"));
@@ -2972,12 +2886,14 @@ HFARasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
                 (*pnBuckets)++;
         }
 
-        *ppanHistogram = (GUIntBig *) CPLCalloc(sizeof(GUIntBig),*pnBuckets);
+        *ppanHistogram =
+            static_cast<GUIntBig *>(CPLCalloc(sizeof(GUIntBig), *pnBuckets));
 
-        pszNextBin = pszBinValues;
+        const char *pszNextBin = pszBinValues;
         for( int i = 0; i < *pnBuckets; i++ )
         {
-            (*ppanHistogram)[i] = (GUIntBig) CPLAtoGIntBig(pszNextBin);
+            (*ppanHistogram)[i] =
+                static_cast<GUIntBig>(CPLAtoGIntBig(pszNextBin));
 
             while( *pszNextBin != '|' && *pszNextBin != '\0' )
                 pszNextBin++;
@@ -2986,18 +2902,18 @@ HFARasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
         }
 
         // Adjust min/max to reflect outer edges of buckets.
-        double dfBucketWidth = (*pdfMax - *pdfMin) / (*pnBuckets-1);
+        double dfBucketWidth = (*pdfMax - *pdfMin) / (*pnBuckets - 1);
         *pdfMax += 0.5 * dfBucketWidth;
         *pdfMin -= 0.5 * dfBucketWidth;
 
         return CE_None;
     }
-    else
-        return GDALPamRasterBand::GetDefaultHistogram( pdfMin, pdfMax,
-                                                       pnBuckets,ppanHistogram,
-                                                       bForce,
-                                                       pfnProgress,
-                                                       pProgressData );
+
+    return GDALPamRasterBand::GetDefaultHistogram(pdfMin, pdfMax,
+                                                  pnBuckets, ppanHistogram,
+                                                  bForce,
+                                                  pfnProgress,
+                                                  pProgressData);
 }
 
 /************************************************************************/
@@ -3010,7 +2926,7 @@ CPLErr HFARasterBand::SetDefaultRAT( const GDALRasterAttributeTable * poRAT )
     if( poRAT == NULL )
         return CE_Failure;
 
-    return WriteNamedRAT( "Descriptor_Table", poRAT );
+    return WriteNamedRAT("Descriptor_Table", poRAT);
 }
 
 /************************************************************************/
@@ -3021,7 +2937,7 @@ GDALRasterAttributeTable *HFARasterBand::GetDefaultRAT()
 
 {
     if( poDefaultRAT == NULL )
-        poDefaultRAT = new HFARasterAttributeTable(this, "Descriptor_Table" );
+        poDefaultRAT = new HFARasterAttributeTable(this, "Descriptor_Table");
 
     return poDefaultRAT;
 }
@@ -3031,41 +2947,51 @@ GDALRasterAttributeTable *HFARasterBand::GetDefaultRAT()
 /************************************************************************/
 
 CPLErr HFARasterBand::WriteNamedRAT( const char * /*pszName*/,
-                                     const GDALRasterAttributeTable* poRAT )
+                                     const GDALRasterAttributeTable *poRAT )
 {
-/* -------------------------------------------------------------------- */
-/*      Find the requested table.                                       */
-/* -------------------------------------------------------------------- */
-    HFAEntry * poDT = hHFA->papoBand[nBand-1]->poNode->GetNamedChild( "Descriptor_Table" );
-    if( poDT == NULL || !EQUAL(poDT->GetType(),"Edsc_Table") )
-        poDT = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
+    // Find the requested table.
+    HFAEntry *poDT =
+        hHFA->papoBand[nBand - 1]->poNode->GetNamedChild("Descriptor_Table");
+    if( poDT == NULL || !EQUAL(poDT->GetType(), "Edsc_Table") )
+        poDT = HFAEntry::New(hHFA->papoBand[nBand - 1]->psInfo,
                              "Descriptor_Table", "Edsc_Table",
-                             hHFA->papoBand[nBand-1]->poNode );
+                             hHFA->papoBand[nBand - 1]->poNode );
 
     const int nRowCount = poRAT->GetRowCount();
 
-    poDT->SetIntField( "numrows", nRowCount );
-    /* Check if binning is set on this RAT */
-    double dfBinSize, dfRow0Min;
-    if(poRAT->GetLinearBinning( &dfRow0Min, &dfBinSize))
+    poDT->SetIntField("numrows", nRowCount);
+    // Check if binning is set on this RAT.
+    double dfBinSize = 0.0;
+    double dfRow0Min = 0.0;
+    if( poRAT->GetLinearBinning(&dfRow0Min, &dfBinSize) )
     {
-        /* then it should have an Edsc_BinFunction */
-        HFAEntry *poBinFunction = poDT->GetNamedChild( "#Bin_Function#" );
-        if( poBinFunction == NULL || !EQUAL(poBinFunction->GetType(),"Edsc_BinFunction") )
-            poBinFunction = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
+        // Then it should have an Edsc_BinFunction.
+        HFAEntry *poBinFunction = poDT->GetNamedChild("#Bin_Function#");
+        if( poBinFunction == NULL ||
+            !EQUAL(poBinFunction->GetType(), "Edsc_BinFunction") )
+        {
+            poBinFunction = HFAEntry::New(hHFA->papoBand[nBand - 1]->psInfo,
                                           "#Bin_Function#", "Edsc_BinFunction",
-                                          poDT );
+                                          poDT);
+        }
 
-        poBinFunction->SetStringField("binFunction", "direct");
-        poBinFunction->SetDoubleField("minLimit",dfRow0Min);
-        poBinFunction->SetDoubleField("maxLimit",(nRowCount -1)*dfBinSize+dfRow0Min);
-        poBinFunction->SetIntField("numBins",nRowCount);
+        // direct for thematic layers, linear otherwise
+        const char* pszLayerType =
+            hHFA->papoBand[nBand-1]->poNode->GetStringField("layerType");
+        if( pszLayerType == NULL ||
+            STARTS_WITH_CI(pszLayerType, "thematic") )
+            poBinFunction->SetStringField("binFunctionType", "direct");
+        else
+            poBinFunction->SetStringField("binFunctionType", "linear" );
+
+        poBinFunction->SetDoubleField("minLimit", dfRow0Min);
+        poBinFunction->SetDoubleField(
+           "maxLimit", (nRowCount - 1) * dfBinSize + dfRow0Min);
+        poBinFunction->SetIntField("numBins", nRowCount);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Loop through each column in the RAT                             */
-/* -------------------------------------------------------------------- */
-    for(int col = 0; col < poRAT->GetColumnCount(); col++)
+    // Loop through each column in the RAT.
+    for( int col = 0; col < poRAT->GetColumnCount(); col++ )
     {
         const char *pszName = NULL;
 
@@ -3098,127 +3024,139 @@ CPLErr HFARasterBand::WriteNamedRAT( const char * /*pszName*/,
             pszName = poRAT->GetNameOfCol(col);
         }
 
-/* -------------------------------------------------------------------- */
-/*      Check to see if a column with pszName exists and create if      */
-/*      if necessary.                                                   */
-/* -------------------------------------------------------------------- */
-
+        // Check to see if a column with pszName exists and create if
+        // if necessary.
         HFAEntry *poColumn = poDT->GetNamedChild(pszName);
 
-        if(poColumn == NULL || !EQUAL(poColumn->GetType(),"Edsc_Column"))
-	    poColumn = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
+        if( poColumn == NULL || !EQUAL(poColumn->GetType(), "Edsc_Column") )
+            poColumn = HFAEntry::New(hHFA->papoBand[nBand-1]->psInfo,
                                      pszName, "Edsc_Column",
-                                     poDT );
+                                     poDT);
 
-
-        poColumn->SetIntField( "numRows", nRowCount );
-        // color cols which are integer in GDAL are written as floats in HFA
+        poColumn->SetIntField("numRows", nRowCount);
+        // Color cols which are integer in GDAL are written as floats in HFA.
         bool bIsColorCol = false;
-        if( ( poRAT->GetUsageOfCol(col) == GFU_Red ) || ( poRAT->GetUsageOfCol(col) == GFU_Green ) ||
-            ( poRAT->GetUsageOfCol(col) == GFU_Blue) || ( poRAT->GetUsageOfCol(col) == GFU_Alpha ) )
+        if( poRAT->GetUsageOfCol(col) == GFU_Red ||
+            poRAT->GetUsageOfCol(col) == GFU_Green ||
+            poRAT->GetUsageOfCol(col) == GFU_Blue ||
+            poRAT->GetUsageOfCol(col) == GFU_Alpha )
         {
             bIsColorCol = true;
         }
 
-        // write float also if a color column, or histogram
-        if( ( poRAT->GetTypeOfCol(col) == GFT_Real ) || bIsColorCol || (poRAT->GetUsageOfCol(col) == GFU_PixelCount) )
+        // Write float also if a color column or histogram.
+        if( poRAT->GetTypeOfCol(col) == GFT_Real ||
+            bIsColorCol ||
+            poRAT->GetUsageOfCol(col) == GFU_PixelCount )
         {
-            int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
-                                            (GUInt32)nRowCount * (GUInt32)sizeof(double) );
-            poColumn->SetIntField( "columnDataPtr", nOffset );
-            poColumn->SetStringField( "dataType", "real" );
-
-            double *padfColData = (double*)CPLCalloc( nRowCount, sizeof(double) );
+            const int nOffset =
+                HFAAllocateSpace(hHFA->papoBand[nBand - 1]->psInfo,
+                                 static_cast<GUInt32>(nRowCount) *
+                                 static_cast<GUInt32>(sizeof(double)));
+            poColumn->SetIntField("columnDataPtr", nOffset);
+            poColumn->SetStringField("dataType", "real");
+
+            double *padfColData =
+                static_cast<double *>(CPLCalloc(nRowCount, sizeof(double)));
             for( int i = 0; i < nRowCount; i++)
             {
                 if( bIsColorCol )
-                    // stored 0..1
-                    padfColData[i] = poRAT->GetValueAsInt(i,col) / 255.0;
+                    // Stored 0..1
+                    padfColData[i] = poRAT->GetValueAsInt(i, col) / 255.0;
                 else
-                    padfColData[i] = poRAT->GetValueAsDouble(i,col);
+                    padfColData[i] = poRAT->GetValueAsDouble(i, col);
             }
 #ifdef CPL_MSB
-            GDALSwapWords( padfColData, 8, nRowCount, 8 );
+            GDALSwapWords(padfColData, 8, nRowCount, 8);
 #endif
-            if( VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) != 0 ||
-                VSIFWriteL( padfColData, nRowCount, sizeof(double), hHFA->fp ) != sizeof(double) )
+            if( VSIFSeekL(hHFA->fp, nOffset, SEEK_SET ) != 0 ||
+                VSIFWriteL(padfColData, nRowCount, sizeof(double),
+                           hHFA->fp ) != sizeof(double) )
             {
                 CPLError(CE_Failure, CPLE_FileIO, "WriteNamedRAT() failed");
-                CPLFree( padfColData );
+                CPLFree(padfColData);
                 return CE_Failure;
             }
-            CPLFree( padfColData );
+            CPLFree(padfColData);
         }
         else if( poRAT->GetTypeOfCol(col) == GFT_String )
         {
-            unsigned int nMaxNumChars = 0, nNumChars;
-            /* find the length of the longest string */
+            unsigned int nMaxNumChars = 0;
+            // Find the length of the longest string.
             for( int i = 0; i < nRowCount; i++)
             {
-                /* Include terminating byte */
-                nNumChars = static_cast<int>(strlen(poRAT->GetValueAsString(i,col)) + 1);
-                if(nMaxNumChars < nNumChars)
+                // Include terminating byte.
+                const unsigned int nNumChars = static_cast<unsigned int>(
+                    strlen(poRAT->GetValueAsString(i, col)) + 1);
+                if( nMaxNumChars < nNumChars )
                 {
                     nMaxNumChars = nNumChars;
                 }
             }
 
-            int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
-                                            (nRowCount+1) * nMaxNumChars );
-            poColumn->SetIntField( "columnDataPtr", nOffset );
-            poColumn->SetStringField( "dataType", "string" );
-            poColumn->SetIntField( "maxNumChars", nMaxNumChars );
+            const int nOffset =
+                HFAAllocateSpace(hHFA->papoBand[nBand - 1]->psInfo,
+                                 (nRowCount + 1) * nMaxNumChars);
+            poColumn->SetIntField("columnDataPtr", nOffset);
+            poColumn->SetStringField("dataType", "string");
+            poColumn->SetIntField("maxNumChars", nMaxNumChars);
 
-            char *pachColData = (char*)CPLCalloc(nRowCount+1,nMaxNumChars);
-            for( int i = 0; i < nRowCount; i++)
+            char *pachColData =
+                static_cast<char *>(CPLCalloc(nRowCount + 1, nMaxNumChars));
+            for( int i = 0; i < nRowCount; i++ )
             {
-                strcpy(&pachColData[nMaxNumChars*i],poRAT->GetValueAsString(i,col));
+                strcpy(&pachColData[nMaxNumChars * i],
+                       poRAT->GetValueAsString(i, col));
             }
-            if( VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) != 0 ||
-                VSIFWriteL( pachColData, nRowCount, nMaxNumChars, hHFA->fp ) != nMaxNumChars )
+            if( VSIFSeekL(hHFA->fp, nOffset, SEEK_SET) != 0 ||
+                VSIFWriteL(pachColData, nRowCount,
+                           nMaxNumChars, hHFA->fp) != nMaxNumChars )
             {
                 CPLError(CE_Failure, CPLE_FileIO, "WriteNamedRAT() failed");
-                CPLFree( pachColData );
+                CPLFree(pachColData);
                 return CE_Failure;
             }
-            CPLFree( pachColData );
+            CPLFree(pachColData);
         }
-        else if (poRAT->GetTypeOfCol(col) == GFT_Integer)
+        else if( poRAT->GetTypeOfCol(col) == GFT_Integer )
         {
-            int nOffset = HFAAllocateSpace( hHFA->papoBand[nBand-1]->psInfo,
-                                            (GUInt32)nRowCount * (GUInt32)sizeof(GInt32) );
-            poColumn->SetIntField( "columnDataPtr", nOffset );
-            poColumn->SetStringField( "dataType", "integer" );
-
-            GInt32 *panColData = (GInt32*)CPLCalloc(nRowCount, sizeof(GInt32));
+            const int nOffset = HFAAllocateSpace(
+                hHFA->papoBand[nBand - 1]->psInfo,
+                static_cast<GUInt32>(nRowCount) * (GUInt32)sizeof(GInt32));
+            poColumn->SetIntField("columnDataPtr", nOffset);
+            poColumn->SetStringField("dataType", "integer");
+
+            GInt32 *panColData =
+                static_cast<GInt32 *>(CPLCalloc(nRowCount, sizeof(GInt32)));
             for( int i = 0; i < nRowCount; i++)
             {
-                panColData[i] = poRAT->GetValueAsInt(i,col);
+                panColData[i] = poRAT->GetValueAsInt(i, col);
             }
 #ifdef CPL_MSB
-            GDALSwapWords( panColData, 4, nRowCount, 4 );
+            GDALSwapWords(panColData, 4, nRowCount, 4);
 #endif
-            if( VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) != 0 ||
-                VSIFWriteL( panColData, nRowCount, sizeof(GInt32), hHFA->fp ) != sizeof(GInt32) )
+            if( VSIFSeekL(hHFA->fp, nOffset, SEEK_SET) != 0 ||
+                VSIFWriteL(panColData, nRowCount,
+                           sizeof(GInt32), hHFA->fp) != sizeof(GInt32) )
             {
                 CPLError(CE_Failure, CPLE_FileIO, "WriteNamedRAT() failed");
-                CPLFree( panColData );
+                CPLFree(panColData);
                 return CE_Failure;
             }
-            CPLFree( panColData );
+            CPLFree(panColData);
         }
         else
         {
-            /* can't deal with any of the others yet */
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "Writing this data type in a column is not supported for this Raster Attribute Table.");
+            // Can't deal with any of the others yet.
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Writing this data type in a column is not supported "
+                     "for this Raster Attribute Table.");
         }
     }
 
     return CE_None;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                            HFADataset                               */
@@ -3229,18 +3167,17 @@ CPLErr HFARasterBand::WriteNamedRAT( const char * /*pszName*/,
 /*                            HFADataset()                            */
 /************************************************************************/
 
-HFADataset::HFADataset()
-
+HFADataset::HFADataset() :
+    hHFA(NULL),
+    bMetadataDirty(false),
+    bGeoDirty(false),
+    pszProjection(CPLStrdup("")),
+    bIgnoreUTM(false),
+    bForceToPEString(false),
+    nGCPCount(0)
 {
-    hHFA = NULL;
-    bGeoDirty = FALSE;
-    pszProjection = CPLStrdup("");
-    bMetadataDirty = FALSE;
-    bIgnoreUTM = FALSE;
-    bForceToPEString = FALSE;
-
-    nGCPCount = 0;
     memset(asGCPList, 0, sizeof(asGCPList));
+    memset(adfGeoTransform, 0, sizeof(adfGeoTransform));
 }
 
 /************************************************************************/
@@ -3252,38 +3189,31 @@ HFADataset::~HFADataset()
 {
     FlushCache();
 
-/* -------------------------------------------------------------------- */
-/*      Destroy the raster bands if they exist.  We forcibly clean      */
-/*      them up now to avoid any effort to write to them after the      */
-/*      file is closed.                                                 */
-/* -------------------------------------------------------------------- */
+    // Destroy the raster bands if they exist.  We forcibly clean
+    // them up now to avoid any effort to write to them after the
+    // file is closed.
     for( int i = 0; i < nBands && papoBands != NULL; i++ )
     {
         if( papoBands[i] != NULL )
             delete papoBands[i];
     }
 
-    CPLFree( papoBands );
+    CPLFree(papoBands);
     papoBands = NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Close the file                                                  */
-/* -------------------------------------------------------------------- */
+    // Close the file.
     if( hHFA != NULL )
     {
-        if( HFAClose( hHFA ) != 0 )
+        if( HFAClose(hHFA) != 0 )
         {
             CPLError(CE_Failure, CPLE_FileIO, "I/O error");
         }
         hHFA = NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-    CPLFree( pszProjection );
+    CPLFree(pszProjection);
     if( nGCPCount > 0 )
-        GDALDeinitGCPs( 36, asGCPList );
+        GDALDeinitGCPs(36, asGCPList);
 }
 
 /************************************************************************/
@@ -3303,23 +3233,24 @@ void HFADataset::FlushCache()
 
     if( bMetadataDirty && GetMetadata() != NULL )
     {
-        HFASetMetadata( hHFA, 0, GetMetadata() );
-        bMetadataDirty = FALSE;
+        HFASetMetadata(hHFA, 0, GetMetadata());
+        bMetadataDirty = false;
     }
 
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        HFARasterBand *poBand = (HFARasterBand *) GetRasterBand(iBand+1);
+        HFARasterBand *poBand =
+            static_cast<HFARasterBand *>(GetRasterBand(iBand + 1));
         if( poBand->bMetadataDirty && poBand->GetMetadata() != NULL )
         {
-            HFASetMetadata( hHFA, iBand+1, poBand->GetMetadata() );
-            poBand->bMetadataDirty = FALSE;
+            HFASetMetadata(hHFA, iBand + 1, poBand->GetMetadata());
+            poBand->bMetadataDirty = false;
         }
     }
 
     if( nGCPCount > 0 )
     {
-        GDALDeinitGCPs( nGCPCount, asGCPList );
+        GDALDeinitGCPs(nGCPCount, asGCPList);
     }
 }
 
@@ -3330,117 +3261,111 @@ void HFADataset::FlushCache()
 CPLErr HFADataset::WriteProjection()
 
 {
-    OGRSpatialReference	oSRS;
-    char		*pszP = pszProjection;
+    OGRSpatialReference oSRS;
+    char *pszP = pszProjection;
     bool bPEStringStored = false;
 
-    bGeoDirty = FALSE;
+    bGeoDirty = false;
 
-    bool bHaveSRS;
-    if( pszProjection != NULL && strlen(pszProjection) > 0
-        && oSRS.importFromWkt( &pszP ) == OGRERR_NONE )
-        bHaveSRS = true;
-    else
-        bHaveSRS = false;
-
-/* -------------------------------------------------------------------- */
-/*      Initialize projection and datum.                                */
-/* -------------------------------------------------------------------- */
-    Eprj_Datum	        sDatum;
-    Eprj_ProParameters  sPro;
-    Eprj_MapInfo	sMapInfo;
-    memset( &sPro, 0, sizeof(sPro) );
-    memset( &sDatum, 0, sizeof(sDatum) );
-    memset( &sMapInfo, 0, sizeof(sMapInfo) );
-
-/* -------------------------------------------------------------------- */
-/*      Collect datum information.                                      */
-/* -------------------------------------------------------------------- */
-    OGRSpatialReference *poGeogSRS = NULL;
-    if( bHaveSRS )
-    {
-        poGeogSRS = oSRS.CloneGeogCS();
-    }
+    const bool bHaveSRS =
+        pszProjection != NULL && strlen(pszProjection) > 0 &&
+        oSRS.importFromWkt(&pszP) == OGRERR_NONE;
+
+    // Initialize projection and datum.
+    Eprj_Datum sDatum;
+    Eprj_ProParameters sPro;
+    Eprj_MapInfo sMapInfo;
+    memset(&sPro, 0, sizeof(sPro));
+    memset(&sDatum, 0, sizeof(sDatum));
+    memset(&sMapInfo, 0, sizeof(sMapInfo));
+
+    // Collect datum information.
+    OGRSpatialReference *poGeogSRS = bHaveSRS ? oSRS.CloneGeogCS() : NULL;
 
     if( poGeogSRS )
     {
-        sDatum.datumname = (char *) poGeogSRS->GetAttrValue( "GEOGCS|DATUM" );
+        sDatum.datumname =
+            const_cast<char *>(poGeogSRS->GetAttrValue("GEOGCS|DATUM"));
         if( sDatum.datumname == NULL )
-            sDatum.datumname = (char*) "";
+            sDatum.datumname = const_cast<char *>("");
 
-        /* WKT to Imagine translation */
+        // WKT to Imagine translation.
         for( int i = 0; apszDatumMap[i] != NULL; i += 2 )
         {
-            if( EQUAL(sDatum.datumname,apszDatumMap[i+1]) )
+            if( EQUAL(sDatum.datumname, apszDatumMap[i+1]) )
             {
-                sDatum.datumname = (char *) apszDatumMap[i];
+                sDatum.datumname = (char *)apszDatumMap[i];
                 break;
             }
         }
 
-        /* Map some EPSG datum codes directly to Imagine names */
-        int nGCS = poGeogSRS->GetEPSGGeogCS();
+        // Map some EPSG datum codes directly to Imagine names.
+        const int nGCS = poGeogSRS->GetEPSGGeogCS();
 
         if( nGCS == 4326 )
-            sDatum.datumname = (char*) "WGS 84";
+            sDatum.datumname = const_cast<char *>("WGS 84");
         if( nGCS == 4322 )
-            sDatum.datumname = (char*) "WGS 1972";
+            sDatum.datumname = const_cast<char*>("WGS 1972");
         if( nGCS == 4267 )
-            sDatum.datumname = (char*) "NAD27";
+            sDatum.datumname = const_cast<char *>("NAD27");
         if( nGCS == 4269 )
-            sDatum.datumname = (char*) "NAD83";
+            sDatum.datumname = const_cast<char *>("NAD83");
         if( nGCS == 4283 )
-            sDatum.datumname = (char*) "GDA94";
+            sDatum.datumname = const_cast<char *>("GDA94");
 
-        if( poGeogSRS->GetTOWGS84( sDatum.params ) == OGRERR_NONE )
+        if( poGeogSRS->GetTOWGS84(sDatum.params) == OGRERR_NONE )
+        {
             sDatum.type = EPRJ_DATUM_PARAMETRIC;
-        else if( EQUAL(sDatum.datumname,"NAD27") )
+            sDatum.params[3] *= -ARCSEC2RAD;
+            sDatum.params[4] *= -ARCSEC2RAD;
+            sDatum.params[5] *= -ARCSEC2RAD;
+            sDatum.params[6] *= 1e-6;
+        }
+        else if( EQUAL(sDatum.datumname, "NAD27") )
         {
             sDatum.type = EPRJ_DATUM_GRID;
-            sDatum.gridname = (char*) "nadcon.dat";
+            sDatum.gridname = const_cast<char *>("nadcon.dat");
         }
         else
         {
-            /* we will default to this (effectively WGS84) for now */
+            // We will default to this (effectively WGS84) for now.
             sDatum.type = EPRJ_DATUM_PARAMETRIC;
         }
 
-        /* Verify if we need to write a ESRI PE string */
+        // Verify if we need to write a ESRI PE string.
         bPEStringStored = CPL_TO_BOOL(WritePeStringIfNeeded(&oSRS, hHFA));
 
-        sPro.proSpheroid.sphereName = (char *)
-            poGeogSRS->GetAttrValue( "GEOGCS|DATUM|SPHEROID" );
+        sPro.proSpheroid.sphereName =
+            (char *)poGeogSRS->GetAttrValue("GEOGCS|DATUM|SPHEROID");
         sPro.proSpheroid.a = poGeogSRS->GetSemiMajor();
         sPro.proSpheroid.b = poGeogSRS->GetSemiMinor();
         sPro.proSpheroid.radius = sPro.proSpheroid.a;
 
-        double a2 = sPro.proSpheroid.a*sPro.proSpheroid.a;
-        double b2 = sPro.proSpheroid.b*sPro.proSpheroid.b;
+        const double a2 = sPro.proSpheroid.a * sPro.proSpheroid.a;
+        const double b2 = sPro.proSpheroid.b * sPro.proSpheroid.b;
 
-        sPro.proSpheroid.eSquared = (a2-b2)/a2;
+        sPro.proSpheroid.eSquared = (a2 - b2) / a2;
     }
 
     if( sDatum.datumname == NULL )
-        sDatum.datumname = (char*) "";
+        sDatum.datumname = const_cast<char *>("");
     if( sPro.proSpheroid.sphereName == NULL )
-        sPro.proSpheroid.sphereName = (char*) "";
+        sPro.proSpheroid.sphereName = const_cast<char *>("");
 
-/* -------------------------------------------------------------------- */
-/*      Recognise various projections.                                  */
-/* -------------------------------------------------------------------- */
-    const char * pszProjName = NULL;
+    // Recognise various projections.
+    const char *pszProjName = NULL;
 
     if( bHaveSRS )
-        pszProjName = oSRS.GetAttrValue( "PROJCS|PROJECTION" );
+        pszProjName = oSRS.GetAttrValue("PROJCS|PROJECTION");
 
     if( bForceToPEString && !bPEStringStored )
     {
         char *pszPEString = NULL;
         oSRS.morphToESRI();
-        oSRS.exportToWkt( &pszPEString );
-        // need to transform this into ESRI format.
-        HFASetPEString( hHFA, pszPEString );
-        CPLFree( pszPEString );
+        oSRS.exportToWkt(&pszPEString);
+        // Need to transform this into ESRI format.
+        HFASetPEString(hHFA, pszPEString);
+        CPLFree(pszPEString);
 
         bPEStringStored = true;
     }
@@ -3449,512 +3374,546 @@ CPLErr HFADataset::WriteProjection()
         if( bHaveSRS && oSRS.IsGeographic() )
         {
             sPro.proNumber = EPRJ_LATLONG;
-            sPro.proName = (char*) "Geographic (Lat/Lon)";
+            sPro.proName = const_cast<char *>("Geographic (Lat/Lon)");
         }
     }
-
-    /* FIXME/NOTDEF/TODO: Add State Plane */
-    else if( !bIgnoreUTM && oSRS.GetUTMZone( NULL ) != 0 )
+    // TODO: Add State Plane.
+    else if( !bIgnoreUTM && oSRS.GetUTMZone(NULL) != 0 )
     {
-        int	bNorth, nZone;
-
-        nZone = oSRS.GetUTMZone( &bNorth );
+        int bNorth = FALSE;
+        const int nZone = oSRS.GetUTMZone(&bNorth);
         sPro.proNumber = EPRJ_UTM;
-        sPro.proName = (char*) "UTM";
+        sPro.proName = const_cast<char *>("UTM");
         sPro.proZone = nZone;
         if( bNorth )
             sPro.proParams[3] = 1.0;
         else
             sPro.proParams[3] = -1.0;
     }
-
-    else if( EQUAL(pszProjName,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
+    else if( EQUAL(pszProjName, SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
         sPro.proNumber = EPRJ_ALBERS_CONIC_EQUAL_AREA;
-        sPro.proName = (char*) "Albers Conical Equal Area";
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
-        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2)*D2R;
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proName = const_cast<char *>("Albers Conical Equal Area");
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2) * D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
+    else if( EQUAL(pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
     {
         sPro.proNumber = EPRJ_LAMBERT_CONFORMAL_CONIC;
-        sPro.proName = (char*) "Lambert Conformal Conic";
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
-        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2)*D2R;
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proName = const_cast<char *>("Lambert Conformal Conic");
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2) * D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP)
-             && oSRS.GetProjParm(SRS_PP_SCALE_FACTOR) == 1.0 )
+    else if( EQUAL(pszProjName, SRS_PT_MERCATOR_1SP) &&
+             oSRS.GetProjParm(SRS_PP_SCALE_FACTOR) == 1.0 )
     {
         sPro.proNumber = EPRJ_MERCATOR;
-        sPro.proName = (char*) "Mercator";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proName = const_cast<char *>("Mercator");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_MERCATOR_1SP) )
+    else if( EQUAL(pszProjName, SRS_PT_MERCATOR_1SP) )
     {
         sPro.proNumber = EPRJ_MERCATOR_VARIANT_A;
-        sPro.proName = (char*) "Mercator (Variant A)";
+        sPro.proName = const_cast<char *>("Mercator (Variant A)");
         sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
         sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR);
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_KROVAK) )
+    else if( EQUAL(pszProjName, SRS_PT_KROVAK) )
     {
         sPro.proNumber = EPRJ_KROVAK;
-        sPro.proName = (char*) "Krovak";
+        sPro.proName = const_cast<char *>("Krovak");
         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR);
-        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH) * D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
         sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_PSEUDO_STD_PARALLEL_1);
 
-        // XY plane rotation
-        sPro.proParams[8] = 0.0;
-        // X scale
-        sPro.proParams[10] = 1.0;
-        // Y scale
-        sPro.proParams[11] = 1.0;
+        sPro.proParams[8] = 0.0;  // XY plane rotation
+        sPro.proParams[10] = 1.0;  // X scale
+        sPro.proParams[11] = 1.0;  // Y scale
     }
-    else if( EQUAL(pszProjName,SRS_PT_POLAR_STEREOGRAPHIC) )
+    else if( EQUAL(pszProjName, SRS_PT_POLAR_STEREOGRAPHIC) )
     {
         sPro.proNumber = EPRJ_POLAR_STEREOGRAPHIC;
-        sPro.proName = (char*) "Polar Stereographic";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
-        /* hopefully the scale factor is 1.0! */
+        sPro.proName = const_cast<char *>("Polar Stereographic");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
+        // Hopefully the scale factor is 1.0!
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_POLYCONIC) )
+    else if( EQUAL(pszProjName, SRS_PT_POLYCONIC) )
     {
         sPro.proNumber = EPRJ_POLYCONIC;
-        sPro.proName = (char*) "Polyconic";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proName = const_cast<char *>("Polyconic");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_EQUIDISTANT_CONIC) )
+    else if( EQUAL(pszProjName, SRS_PT_EQUIDISTANT_CONIC) )
     {
         sPro.proNumber = EPRJ_EQUIDISTANT_CONIC;
-        sPro.proName = (char*) "Equidistant Conic";
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
-        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2)*D2R;
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proName = const_cast<char *>("Equidistant Conic");
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_2) * D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
         sPro.proParams[8] = 1.0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_TRANSVERSE_MERCATOR) )
+    else if( EQUAL(pszProjName, SRS_PT_TRANSVERSE_MERCATOR) )
     {
         sPro.proNumber = EPRJ_TRANSVERSE_MERCATOR;
-        sPro.proName = (char*) "Transverse Mercator";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
+        sPro.proName = const_cast<char *>("Transverse Mercator");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_STEREOGRAPHIC) )
+    else if( EQUAL(pszProjName, SRS_PT_STEREOGRAPHIC) )
     {
         sPro.proNumber = EPRJ_STEREOGRAPHIC_EXTENDED;
-        sPro.proName = (char*) "Stereographic (Extended)";
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proName = const_cast<char *>("Stereographic (Extended)");
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
+    else if( EQUAL(pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
         sPro.proNumber = EPRJ_LAMBERT_AZIMUTHAL_EQUAL_AREA;
-        sPro.proName = (char*) "Lambert Azimuthal Equal-area";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proName = const_cast<char *>("Lambert Azimuthal Equal-area");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
+    else if( EQUAL(pszProjName, SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     {
         sPro.proNumber = EPRJ_AZIMUTHAL_EQUIDISTANT;
-        sPro.proName = (char*) "Azimuthal Equidistant";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proName = const_cast<char *>("Azimuthal Equidistant");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_GNOMONIC) )
+    else if( EQUAL(pszProjName, SRS_PT_GNOMONIC) )
     {
         sPro.proNumber = EPRJ_GNOMONIC;
-        sPro.proName = (char*) "Gnomonic";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proName = const_cast<char *>("Gnomonic");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_ORTHOGRAPHIC) )
+    else if( EQUAL(pszProjName, SRS_PT_ORTHOGRAPHIC) )
     {
         sPro.proNumber = EPRJ_ORTHOGRAPHIC;
-        sPro.proName = (char*) "Orthographic";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proName = const_cast<char *>("Orthographic");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_SINUSOIDAL) )
+    else if( EQUAL(pszProjName, SRS_PT_SINUSOIDAL) )
     {
         sPro.proNumber = EPRJ_SINUSOIDAL;
-        sPro.proName = (char*) "Sinusoidal";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
+        sPro.proName = const_cast<char *>("Sinusoidal");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_EQUIRECTANGULAR) )
+    else if( EQUAL(pszProjName, SRS_PT_EQUIRECTANGULAR) )
     {
         sPro.proNumber = EPRJ_EQUIRECTANGULAR;
-        sPro.proName = (char*) "Equirectangular";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proName = const_cast<char *>("Equirectangular");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_MILLER_CYLINDRICAL) )
+    else if( EQUAL(pszProjName, SRS_PT_MILLER_CYLINDRICAL) )
     {
         sPro.proNumber = EPRJ_MILLER_CYLINDRICAL;
-        sPro.proName = (char*) "Miller Cylindrical";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
-        /* hopefully the latitude is zero! */
+        sPro.proName = const_cast<char *>("Miller Cylindrical");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+        // Hopefully the latitude is zero!
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_VANDERGRINTEN) )
+    else if( EQUAL(pszProjName, SRS_PT_VANDERGRINTEN) )
     {
         sPro.proNumber = EPRJ_VANDERGRINTEN;
-        sPro.proName = (char*) "Van der Grinten";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Van der Grinten");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
+    else if( EQUAL(pszProjName, SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     {
-        sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR;
-        sPro.proName = (char*) "Oblique Mercator (Hotine)";
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
-        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
-        /* hopefully the rectified grid angle is zero */
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
-        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
-        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
-        sPro.proParams[12] = 1.0;
+        if( oSRS.GetProjParm(SRS_PP_RECTIFIED_GRID_ANGLE) == 0.0 )
+        {
+            sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR;
+            sPro.proName = const_cast<char *>("Oblique Mercator (Hotine)");
+            sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+            sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH) * D2R;
+            sPro.proParams[4] =
+                oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+            sPro.proParams[5] =
+                oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER) * D2R;
+            sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+            sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+            sPro.proParams[12] = 1.0;
+        }
+        else
+        {
+            sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_VARIANT_A;
+            sPro.proName =
+                const_cast<char *>("Hotine Oblique Mercator (Variant A)");
+            sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+            sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH) * D2R;
+            sPro.proParams[4] =
+                oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+            sPro.proParams[5] =
+                oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER) * D2R;
+            sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+            sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+            sPro.proParams[8] =
+                oSRS.GetProjParm(SRS_PP_RECTIFIED_GRID_ANGLE) * D2R;
+        }
     }
-    else if( EQUAL(pszProjName,SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) )
+    else if( EQUAL(pszProjName, SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) )
     {
         sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER;
-        sPro.proName = (char*) "Hotine Oblique Mercator Azimuth Center";
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR,1.0);
-        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proName =
+            const_cast<char *>("Hotine Oblique Mercator Azimuth Center");
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH) * D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
         sPro.proParams[12] = 1.0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_ROBINSON) )
+    else if( EQUAL(pszProjName, SRS_PT_ROBINSON) )
     {
         sPro.proNumber = EPRJ_ROBINSON;
-        sPro.proName = (char*) "Robinson";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
+        sPro.proName = const_cast<char *>("Robinson");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_MOLLWEIDE) )
+    else if( EQUAL(pszProjName, SRS_PT_MOLLWEIDE) )
     {
         sPro.proNumber = EPRJ_MOLLWEIDE;
-        sPro.proName = (char*) "Mollweide";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Mollweide");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_ECKERT_I) )
+    else if( EQUAL(pszProjName, SRS_PT_ECKERT_I) )
     {
         sPro.proNumber = EPRJ_ECKERT_I;
-        sPro.proName = (char*) "Eckert I";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Eckert I");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_ECKERT_II) )
+    else if( EQUAL(pszProjName, SRS_PT_ECKERT_II) )
     {
         sPro.proNumber = EPRJ_ECKERT_II;
-        sPro.proName = (char*) "Eckert II";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Eckert II");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_ECKERT_III) )
+    else if( EQUAL(pszProjName, SRS_PT_ECKERT_III) )
     {
         sPro.proNumber = EPRJ_ECKERT_III;
-        sPro.proName = (char*) "Eckert III";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Eckert III");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_ECKERT_IV) )
+    else if( EQUAL(pszProjName, SRS_PT_ECKERT_IV) )
     {
         sPro.proNumber = EPRJ_ECKERT_IV;
-        sPro.proName = (char*) "Eckert IV";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Eckert IV");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_ECKERT_V) )
+    else if( EQUAL(pszProjName, SRS_PT_ECKERT_V) )
     {
         sPro.proNumber = EPRJ_ECKERT_V;
-        sPro.proName = (char*) "Eckert V";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Eckert V");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_ECKERT_VI) )
+    else if( EQUAL(pszProjName, SRS_PT_ECKERT_VI) )
     {
         sPro.proNumber = EPRJ_ECKERT_VI;
-        sPro.proName = (char*) "Eckert VI";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Eckert VI");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_GALL_STEREOGRAPHIC) )
+    else if( EQUAL(pszProjName, SRS_PT_GALL_STEREOGRAPHIC) )
     {
         sPro.proNumber = EPRJ_GALL_STEREOGRAPHIC;
-        sPro.proName = (char*) "Gall Stereographic";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Gall Stereographic");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_CASSINI_SOLDNER) )
+    else if( EQUAL(pszProjName, SRS_PT_CASSINI_SOLDNER) )
     {
         sPro.proNumber = EPRJ_CASSINI;
-        sPro.proName = (char*) "Cassini";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proName = const_cast<char *>("Cassini");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,SRS_PT_TWO_POINT_EQUIDISTANT) )
+    else if( EQUAL(pszProjName, SRS_PT_TWO_POINT_EQUIDISTANT) )
     {
         sPro.proNumber = EPRJ_TWO_POINT_EQUIDISTANT;
-        sPro.proName = (char*) "Two_Point_Equidistant";
+        sPro.proName = const_cast<char *>("Two_Point_Equidistant");
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
-        sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
-        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
-        sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
-        sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
+        sPro.proParams[8] =
+            oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0) * D2R;
+        sPro.proParams[9] =
+            oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0) * D2R;
+        sPro.proParams[10] =
+            oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0) * D2R;
+        sPro.proParams[11] =
+            oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0) * D2R;
     }
-    else if( EQUAL(pszProjName,SRS_PT_BONNE) )
+    else if( EQUAL(pszProjName, SRS_PT_BONNE) )
     {
         sPro.proNumber = EPRJ_BONNE;
-        sPro.proName = (char*) "Bonne";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
+        sPro.proName = const_cast<char *>("Bonne");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,"Loximuthal") )
+    else if( EQUAL(pszProjName, "Loximuthal") )
     {
         sPro.proNumber = EPRJ_LOXIMUTHAL;
-        sPro.proName = (char*) "Loximuthal";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm("central_parallel")*D2R;
+        sPro.proName = const_cast<char *>("Loximuthal");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm("central_parallel") * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,"Quartic_Authalic") )
+    else if( EQUAL(pszProjName, "Quartic_Authalic") )
     {
         sPro.proNumber = EPRJ_QUARTIC_AUTHALIC;
-        sPro.proName = (char*) "Quartic Authalic";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Quartic Authalic");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,"Winkel_I") )
+    else if( EQUAL(pszProjName, "Winkel_I") )
     {
         sPro.proNumber = EPRJ_WINKEL_I;
-        sPro.proName = (char*) "Winkel I";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
+        sPro.proName = const_cast<char *>("Winkel I");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,"Winkel_II") )
+    else if( EQUAL(pszProjName, "Winkel_II") )
     {
         sPro.proNumber = EPRJ_WINKEL_II;
-        sPro.proName = (char*) "Winkel II";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
+        sPro.proName = const_cast<char *>("Winkel II");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,"Behrmann") )
+    else if( EQUAL(pszProjName, "Behrmann") )
     {
         sPro.proNumber = EPRJ_BEHRMANN;
-        sPro.proName = (char*) "Behrmann";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Behrmann");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
-    else if( EQUAL(pszProjName,"Equidistant_Cylindrical") )
+    else if( EQUAL(pszProjName, "Equidistant_Cylindrical") )
     {
         sPro.proNumber = EPRJ_EQUIDISTANT_CYLINDRICAL;
-        sPro.proName = (char*) "Equidistant_Cylindrical";
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Equidistant_Cylindrical");
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, SRS_PT_KROVAK) )
     {
         sPro.proNumber = EPRJ_KROVAK;
-        sPro.proName = (char*) "Krovak";
+        sPro.proName = const_cast<char *>("Krovak");
         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
-        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH)*D2R;
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER)*D2R;
+        sPro.proParams[3] = oSRS.GetProjParm(SRS_PP_AZIMUTH) * D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
-        sPro.proParams[8] = oSRS.GetProjParm("XY_Plane_Rotation", 0.0)*D2R;
-        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
+        sPro.proParams[8] = oSRS.GetProjParm("XY_Plane_Rotation", 0.0) * D2R;
+        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
         sPro.proParams[10] = oSRS.GetProjParm("X_Scale", 1.0);
         sPro.proParams[11] = oSRS.GetProjParm("Y_Scale", 1.0);
     }
     else if( EQUAL(pszProjName, "Double_Stereographic") )
     {
         sPro.proNumber = EPRJ_DOUBLE_STEREOGRAPHIC;
-        sPro.proName = (char*) "Double_Stereographic";
+        sPro.proName = const_cast<char *>("Double_Stereographic");
         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN)*D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, "Aitoff") )
     {
         sPro.proNumber = EPRJ_AITOFF;
-        sPro.proName = (char*) "Aitoff";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Aitoff");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, "Craster_Parabolic") )
     {
         sPro.proNumber = EPRJ_CRASTER_PARABOLIC;
-        sPro.proName = (char*) "Craster_Parabolic";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Craster_Parabolic");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, SRS_PT_CYLINDRICAL_EQUAL_AREA) )
     {
         sPro.proNumber = EPRJ_CYLINDRICAL_EQUAL_AREA;
-        sPro.proName = (char*) "Cylindrical_Equal_Area";
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Cylindrical_Equal_Area");
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, "Flat_Polar_Quartic") )
     {
         sPro.proNumber = EPRJ_FLAT_POLAR_QUARTIC;
-        sPro.proName = (char*) "Flat_Polar_Quartic";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Flat_Polar_Quartic");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, "Times") )
     {
         sPro.proNumber = EPRJ_TIMES;
-        sPro.proName = (char*) "Times";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Times");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, "Winkel_Tripel") )
     {
         sPro.proNumber = EPRJ_WINKEL_TRIPEL;
-        sPro.proName = (char*) "Winkel_Tripel";
-        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1)*D2R;
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Winkel_Tripel");
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_STANDARD_PARALLEL_1) * D2R;
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, "Hammer_Aitoff") )
     {
         sPro.proNumber = EPRJ_HAMMER_AITOFF;
-        sPro.proName = (char*) "Hammer_Aitoff";
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN)*D2R;
+        sPro.proName = const_cast<char *>("Hammer_Aitoff");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, "Vertical_Near_Side_Perspective") )
     {
         sPro.proNumber = EPRJ_VERTICAL_NEAR_SIDE_PERSPECTIVE;
-        sPro.proName = (char*) "Vertical_Near_Side_Perspective";
+        sPro.proName = const_cast<char *>("Vertical_Near_Side_Perspective");
         sPro.proParams[2] = oSRS.GetProjParm("Height");
-        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER, 75.0)*D2R;
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
+        sPro.proParams[4] =
+            oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_CENTER, 75.0) * D2R;
+        sPro.proParams[5] =
+            oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
     }
     else if( EQUAL(pszProjName, "Hotine_Oblique_Mercator_Two_Point_Center") )
     {
         sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_CENTER;
-        sPro.proName = (char*) "Hotine_Oblique_Mercator_Two_Point_Center";
+        sPro.proName =
+            const_cast<char *>("Hotine_Oblique_Mercator_Two_Point_Center");
         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
+        sPro.proParams[5] =
+            oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
-        sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
-        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
-        sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
-        sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
-    }
-    else if( EQUAL(pszProjName, SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
+        sPro.proParams[8] =
+            oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0) * D2R;
+        sPro.proParams[9] =
+            oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0) * D2R;
+        sPro.proParams[10] =
+            oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0) * D2R;
+        sPro.proParams[11] =
+            oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0) * D2R;
+    }
+    else if( EQUAL(pszProjName,
+                   SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
     {
         sPro.proNumber = EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN;
-        sPro.proName = (char*) "Hotine_Oblique_Mercator_Two_Point_Natural_Origin";
+        sPro.proName = const_cast<char *>(
+            "Hotine_Oblique_Mercator_Two_Point_Natural_Origin");
         sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
-        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0)*D2R;
+        sPro.proParams[5] =
+            oSRS.GetProjParm(SRS_PP_LATITUDE_OF_CENTER, 40.0) * D2R;
         sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
         sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
-        sPro.proParams[8] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0)*D2R;
-        sPro.proParams[9] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0)*D2R;
-        sPro.proParams[10] = oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0)*D2R;
-        sPro.proParams[11] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0)*D2R;
+        sPro.proParams[8] =
+            oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0) * D2R;
+        sPro.proParams[9] =
+            oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0) * D2R;
+        sPro.proParams[10] =
+            oSRS.GetProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 60.0) * D2R;
+        sPro.proParams[11] =
+            oSRS.GetProjParm(SRS_PP_LATITUDE_OF_POINT_2, 60.0) * D2R;
     }
-    else if( EQUAL(pszProjName,"New_Zealand_Map_Grid") )
+    else if( EQUAL(pszProjName, "New_Zealand_Map_Grid") )
     {
         sPro.proType = EPRJ_EXTERNAL;
         sPro.proNumber = 0;
-        sPro.proExeName = (char*) EPRJ_EXTERNAL_NZMG;
-        sPro.proName = (char*) "New Zealand Map Grid";
+        sPro.proExeName = const_cast<char *>(EPRJ_EXTERNAL_NZMG);
+        sPro.proName = const_cast<char *>("New Zealand Map Grid");
         sPro.proZone = 0;
-        sPro.proParams[0] = 0;  // false easting etc not stored in .img it seems
+        sPro.proParams[0] = 0;  // False easting etc not stored in .img it seems
         sPro.proParams[1] = 0;  // always fixed by definition.
         sPro.proParams[2] = 0;
         sPro.proParams[3] = 0;
@@ -3963,118 +3922,125 @@ CPLErr HFADataset::WriteProjection()
         sPro.proParams[6] = 0;
         sPro.proParams[7] = 0;
     }
-    // Anything we can't map, we store as an ESRI PE_STRING
+    else if( EQUAL(pszProjName, SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
+    {
+        sPro.proNumber = EPRJ_TRANSVERSE_MERCATOR_SOUTH_ORIENTATED;
+        sPro.proName =
+            const_cast<char *>("Transverse Mercator (South Orientated)");
+        sPro.proParams[4] = oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN) * D2R;
+        sPro.proParams[5] = oSRS.GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN) * D2R;
+        sPro.proParams[2] = oSRS.GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+        sPro.proParams[6] = oSRS.GetProjParm(SRS_PP_FALSE_EASTING);
+        sPro.proParams[7] = oSRS.GetProjParm(SRS_PP_FALSE_NORTHING);
+    }
+
+    // Anything we can't map, we store as an ESRI PE_STRING.
     else if( oSRS.IsProjected() || oSRS.IsGeographic() )
     {
-        if(!bPEStringStored)
+        if( !bPEStringStored )
         {
             oSRS.morphToESRI();
             char *pszPEString = NULL;
-            oSRS.exportToWkt( &pszPEString );
-            // need to transform this into ESRI format.
-            HFASetPEString( hHFA, pszPEString );
-            CPLFree( pszPEString );
+            oSRS.exportToWkt(&pszPEString);
+            // Need to transform this into ESRI format.
+            HFASetPEString(hHFA, pszPEString);
+            CPLFree(pszPEString);
             bPEStringStored = true;
         }
     }
     else
     {
-        CPLError( CE_Warning, CPLE_NotSupported,
-                  "Projection %s not supported for translation to Imagine.",
-                  pszProjName );
+        CPLError(CE_Warning, CPLE_NotSupported,
+                 "Projection %s not supported for translation to Imagine.",
+                 pszProjName);
     }
 
-/* -------------------------------------------------------------------- */
-/*      MapInfo                                                         */
-/* -------------------------------------------------------------------- */
-    const char *pszPROJCS = oSRS.GetAttrValue( "PROJCS" );
+    // MapInfo
+    const char *pszPROJCS = oSRS.GetAttrValue("PROJCS");
 
     if( pszPROJCS )
-        sMapInfo.proName = (char *) pszPROJCS;
+        sMapInfo.proName = (char *)pszPROJCS;
     else if( bHaveSRS && sPro.proName != NULL )
         sMapInfo.proName = sPro.proName;
     else
-        sMapInfo.proName = (char*) "Unknown";
+        sMapInfo.proName = const_cast<char *>("Unknown");
 
-    sMapInfo.upperLeftCenter.x =
-        adfGeoTransform[0] + adfGeoTransform[1]*0.5;
-    sMapInfo.upperLeftCenter.y =
-        adfGeoTransform[3] + adfGeoTransform[5]*0.5;
+    sMapInfo.upperLeftCenter.x = adfGeoTransform[0] + adfGeoTransform[1] * 0.5;
+    sMapInfo.upperLeftCenter.y = adfGeoTransform[3] + adfGeoTransform[5] * 0.5;
 
     sMapInfo.lowerRightCenter.x =
-        adfGeoTransform[0] + adfGeoTransform[1] * (GetRasterXSize()-0.5);
+        adfGeoTransform[0] + adfGeoTransform[1] * (GetRasterXSize() - 0.5);
     sMapInfo.lowerRightCenter.y =
-        adfGeoTransform[3] + adfGeoTransform[5] * (GetRasterYSize()-0.5);
+        adfGeoTransform[3] + adfGeoTransform[5] * (GetRasterYSize() - 0.5);
 
-    sMapInfo.pixelSize.width = ABS(adfGeoTransform[1]);
-    sMapInfo.pixelSize.height = ABS(adfGeoTransform[5]);
+    sMapInfo.pixelSize.width = std::abs(adfGeoTransform[1]);
+    sMapInfo.pixelSize.height = std::abs(adfGeoTransform[5]);
 
-/* -------------------------------------------------------------------- */
-/*      Handle units.  Try to match up with a known name.               */
-/* -------------------------------------------------------------------- */
-    sMapInfo.units = (char*) "meters";
+    // Handle units.  Try to match up with a known name.
+    sMapInfo.units = const_cast<char *>("meters");
 
     if( bHaveSRS && oSRS.IsGeographic() )
-        sMapInfo.units = (char*) "dd";
+        sMapInfo.units = const_cast<char *>("dd");
     else if( bHaveSRS && oSRS.GetLinearUnits() != 1.0 )
     {
         double dfClosestDiff = 100.0;
-        int    iClosest=-1;
+        int iClosest = -1;
         char *pszUnitName = NULL;
-        double dfActualSize = oSRS.GetLinearUnits( &pszUnitName );
+        const double dfActualSize = oSRS.GetLinearUnits(&pszUnitName);
 
         for( int iUnit = 0; apszUnitMap[iUnit] != NULL; iUnit += 2 )
         {
-            if( fabs(CPLAtof(apszUnitMap[iUnit+1]) - dfActualSize) < dfClosestDiff )
+            if( fabs(CPLAtof(apszUnitMap[iUnit + 1]) - dfActualSize) <
+                dfClosestDiff )
             {
                 iClosest = iUnit;
-                dfClosestDiff = fabs(CPLAtof(apszUnitMap[iUnit+1])-dfActualSize);
+                dfClosestDiff =
+                    fabs(CPLAtof(apszUnitMap[iUnit+1])-dfActualSize);
             }
         }
 
-        if( iClosest == -1 ||  fabs(dfClosestDiff/dfActualSize) > 0.0001 )
+        if( iClosest == -1 || fabs(dfClosestDiff / dfActualSize) > 0.0001 )
         {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                      "Unable to identify Erdas units matching %s/%gm,\n"
-                      "output units will be wrong.",
-                      pszUnitName, dfActualSize );
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "Unable to identify Erdas units matching %s/%gm, "
+                     "output units will be wrong.",
+                     pszUnitName, dfActualSize);
         }
         else
-            sMapInfo.units = (char *) apszUnitMap[iClosest];
+        {
+            sMapInfo.units = (char *)apszUnitMap[iClosest];
+        }
 
-        /* We need to convert false easting and northing to meters. */
+        // We need to convert false easting and northing to meters.
         sPro.proParams[6] *= dfActualSize;
         sPro.proParams[7] *= dfActualSize;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write out definitions.                                          */
-/* -------------------------------------------------------------------- */
+    // Write out definitions.
     if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
     {
-        HFASetMapInfo( hHFA, &sMapInfo );
+        HFASetMapInfo(hHFA, &sMapInfo);
     }
     else
     {
-        HFASetGeoTransform( hHFA,
-                            sMapInfo.proName, sMapInfo.units,
-                            adfGeoTransform );
+        HFASetGeoTransform(hHFA,
+                           sMapInfo.proName, sMapInfo.units,
+                           adfGeoTransform);
     }
 
-    if( bHaveSRS && sPro.proName != NULL)
+    if( bHaveSRS && sPro.proName != NULL )
     {
-        HFASetProParameters( hHFA, &sPro );
-        HFASetDatum( hHFA, &sDatum );
+        HFASetProParameters(hHFA, &sPro);
+        HFASetDatum(hHFA, &sDatum);
 
         if( !bPEStringStored )
-            HFASetPEString( hHFA, "" );
+            HFASetPEString(hHFA, "");
     }
     else if( !bPEStringStored )
+    {
         ClearSR(hHFA);
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
     if( poGeogSRS != NULL )
         delete poGeogSRS;
 
@@ -4084,144 +4050,153 @@ CPLErr HFADataset::WriteProjection()
 /************************************************************************/
 /*                       WritePeStringIfNeeded()                        */
 /************************************************************************/
-int WritePeStringIfNeeded(OGRSpatialReference* poSRS, HFAHandle hHFA)
+int WritePeStringIfNeeded( OGRSpatialReference* poSRS, HFAHandle hHFA )
 {
-  OGRBoolean ret = FALSE;
-  if(!poSRS || !hHFA)
-    return ret;
+    if( !poSRS || !hHFA )
+        return FALSE;
 
-  const char *pszGEOGCS = poSRS->GetAttrValue( "GEOGCS" );
-  const char *pszDatum = poSRS->GetAttrValue( "DATUM" );
-  int gcsNameOffset = 0;
-  int datumNameOffset = 0;
-  if( pszGEOGCS == NULL )
-      pszGEOGCS = "";
-  if( pszDatum == NULL )
-      pszDatum = "";
-  if(strstr(pszGEOGCS, "GCS_"))
-    gcsNameOffset = static_cast<int>(strlen("GCS_"));
-  if(strstr(pszDatum, "D_"))
-    datumNameOffset = static_cast<int>(strlen("D_"));
-
-  if(!EQUAL(pszGEOGCS+gcsNameOffset, pszDatum+datumNameOffset))
-    ret = TRUE;
-  else
-  {
-    const char* name = poSRS->GetAttrValue("PRIMEM");
-    if(name && !EQUAL(name,"Greenwich"))
-      ret = TRUE;
-    if(!ret)
-    {
-      OGR_SRSNode * poAUnits = poSRS->GetAttrNode( "GEOGCS|UNIT" );
-      name = poAUnits->GetChild(0)->GetValue();
-      if(name && !EQUAL(name,"Degree"))
-        ret = TRUE;
-    }
-    if(!ret)
-    {
-      name = poSRS->GetAttrValue("UNIT");
-      if(name)
-      {
-        ret = TRUE;
-        for(int i=0; apszUnitMap[i] != NULL; i+=2)
-          if(EQUAL(name, apszUnitMap[i]))
-            ret = FALSE;
-      }
+    const char *pszGEOGCS = poSRS->GetAttrValue("GEOGCS");
+    if( pszGEOGCS == NULL )
+        pszGEOGCS = "";
+
+    const char *pszDatum = poSRS->GetAttrValue("DATUM");
+    if( pszDatum == NULL )
+        pszDatum = "";
+
+    // The strlen() checks are just there to make Coverity happy because it
+    // doesn't seem to realize that STARTS_WITH() success implies them.
+    const size_t gcsNameOffset =
+         (strlen(pszGEOGCS) > strlen("GCS_") &&
+          STARTS_WITH(pszGEOGCS, "GCS_")) ? strlen("GCS_") : 0;
+
+    const size_t datumNameOffset =
+        (strlen(pszDatum) > strlen("D_") &&
+         STARTS_WITH(pszDatum, "D_")) ? strlen("D_") : 0;
+
+    bool ret = false;
+    if( !EQUAL(pszGEOGCS + gcsNameOffset, pszDatum + datumNameOffset) )
+    {
+        ret = true;
     }
-    if(!ret)
+    else
     {
-        int nGCS = poSRS->GetEPSGGeogCS();
-        switch(nGCS)
+        const char *name = poSRS->GetAttrValue("PRIMEM");
+        if( name && !EQUAL(name, "Greenwich") )
+            ret = true;
+
+        if( !ret )
+        {
+            OGR_SRSNode *poAUnits = poSRS->GetAttrNode("GEOGCS|UNIT");
+            name = poAUnits->GetChild(0)->GetValue();
+            if( name && !EQUAL(name, "Degree") )
+                ret = true;
+        }
+        if( !ret )
+        {
+            name = poSRS->GetAttrValue("UNIT");
+            if( name )
+            {
+                ret = true;
+                for( int i = 0; apszUnitMap[i] != NULL; i += 2 )
+                    if( EQUAL(name, apszUnitMap[i]) )
+                        ret = false;
+            }
+        }
+        if( !ret )
         {
-          case 4326:
-            if(!EQUAL(pszDatum+datumNameOffset, "WGS_84"))
-              ret = TRUE;
-            break;
-          case 4322:
-            if(!EQUAL(pszDatum+datumNameOffset, "WGS_72"))
-              ret = TRUE;
-            break;
-          case 4267:
-            if(!EQUAL(pszDatum+datumNameOffset, "North_America_1927"))
-              ret = TRUE;
-            break;
-          case 4269:
-            if(!EQUAL(pszDatum+datumNameOffset, "North_America_1983"))
-              ret = TRUE;
-            break;
+            const int nGCS = poSRS->GetEPSGGeogCS();
+            switch(nGCS)
+            {
+            case 4326:
+                if( !EQUAL(pszDatum+datumNameOffset, "WGS_84") )
+                    ret = true;
+                break;
+            case 4322:
+                if( !EQUAL(pszDatum+datumNameOffset, "WGS_72") )
+                    ret = true;
+                break;
+            case 4267:
+                if( !EQUAL(pszDatum+datumNameOffset, "North_America_1927") )
+                    ret = true;
+                break;
+            case 4269:
+                if( !EQUAL(pszDatum+datumNameOffset, "North_America_1983") )
+                    ret = true;
+                break;
+            }
         }
     }
-  }
-  if(ret)
-  {
-    char *pszPEString = NULL;
-    poSRS->morphToESRI();
-    poSRS->exportToWkt( &pszPEString );
-    HFASetPEString( hHFA, pszPEString );
-    CPLFree( pszPEString );
-  }
-
-  return ret;
+    if( ret )
+    {
+        char *pszPEString = NULL;
+        poSRS->morphToESRI();
+        poSRS->exportToWkt(&pszPEString);
+        HFASetPEString(hHFA, pszPEString);
+        CPLFree(pszPEString);
+    }
+
+    return ret;
 }
 
 /************************************************************************/
 /*                              ClearSR()                               */
 /************************************************************************/
-void ClearSR(HFAHandle hHFA)
+void ClearSR( HFAHandle hHFA )
 {
     for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
     {
-        HFAEntry	*poMIEntry;
-        if( hHFA->papoBand[iBand]->poNode && (poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection")) != NULL )
+        HFAEntry *poMIEntry = NULL;
+        if( hHFA->papoBand[iBand]->poNode &&
+            (poMIEntry = hHFA->papoBand[iBand]->poNode->
+             GetNamedChild("Projection")) != NULL )
         {
             poMIEntry->MarkDirty();
-            poMIEntry->SetIntField( "proType", 0 );
-            poMIEntry->SetIntField( "proNumber", 0 );
-            poMIEntry->SetStringField( "proExeName", "");
-            poMIEntry->SetStringField( "proName", "");
-            poMIEntry->SetIntField( "proZone", 0 );
-            poMIEntry->SetDoubleField( "proParams[0]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[1]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[2]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[3]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[4]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[5]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[6]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[7]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[8]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[9]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[10]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[11]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[12]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[13]", 0.0 );
-            poMIEntry->SetDoubleField( "proParams[14]", 0.0 );
-            poMIEntry->SetStringField( "proSpheroid.sphereName", "" );
-            poMIEntry->SetDoubleField( "proSpheroid.a", 0.0 );
-            poMIEntry->SetDoubleField( "proSpheroid.b", 0.0 );
-            poMIEntry->SetDoubleField( "proSpheroid.eSquared", 0.0 );
-            poMIEntry->SetDoubleField( "proSpheroid.radius", 0.0 );
-            HFAEntry* poDatumEntry = poMIEntry->GetNamedChild("Datum");
+            poMIEntry->SetIntField("proType", 0);
+            poMIEntry->SetIntField("proNumber", 0);
+            poMIEntry->SetStringField("proExeName", "");
+            poMIEntry->SetStringField("proName", "");
+            poMIEntry->SetIntField("proZone", 0);
+            poMIEntry->SetDoubleField("proParams[0]", 0.0);
+            poMIEntry->SetDoubleField("proParams[1]", 0.0);
+            poMIEntry->SetDoubleField("proParams[2]", 0.0);
+            poMIEntry->SetDoubleField("proParams[3]", 0.0);
+            poMIEntry->SetDoubleField("proParams[4]", 0.0);
+            poMIEntry->SetDoubleField("proParams[5]", 0.0);
+            poMIEntry->SetDoubleField("proParams[6]", 0.0);
+            poMIEntry->SetDoubleField("proParams[7]", 0.0);
+            poMIEntry->SetDoubleField("proParams[8]", 0.0);
+            poMIEntry->SetDoubleField("proParams[9]", 0.0);
+            poMIEntry->SetDoubleField("proParams[10]", 0.0);
+            poMIEntry->SetDoubleField("proParams[11]", 0.0);
+            poMIEntry->SetDoubleField("proParams[12]", 0.0);
+            poMIEntry->SetDoubleField("proParams[13]", 0.0);
+            poMIEntry->SetDoubleField("proParams[14]", 0.0);
+            poMIEntry->SetStringField("proSpheroid.sphereName", "");
+            poMIEntry->SetDoubleField("proSpheroid.a", 0.0);
+            poMIEntry->SetDoubleField("proSpheroid.b", 0.0);
+            poMIEntry->SetDoubleField("proSpheroid.eSquared", 0.0);
+            poMIEntry->SetDoubleField("proSpheroid.radius", 0.0);
+            HFAEntry *poDatumEntry = poMIEntry->GetNamedChild("Datum");
             if( poDatumEntry != NULL )
             {
                 poDatumEntry->MarkDirty();
-                poDatumEntry->SetStringField( "datumname", "" );
-                poDatumEntry->SetIntField( "type", 0 );
-                poDatumEntry->SetDoubleField( "params[0]", 0.0 );
-                poDatumEntry->SetDoubleField( "params[1]", 0.0 );
-                poDatumEntry->SetDoubleField( "params[2]", 0.0 );
-                poDatumEntry->SetDoubleField( "params[3]", 0.0 );
-                poDatumEntry->SetDoubleField( "params[4]", 0.0 );
-                poDatumEntry->SetDoubleField( "params[5]", 0.0 );
-                poDatumEntry->SetDoubleField( "params[6]", 0.0 );
-                poDatumEntry->SetStringField( "gridname", "" );
+                poDatumEntry->SetStringField("datumname", "");
+                poDatumEntry->SetIntField("type", 0);
+                poDatumEntry->SetDoubleField("params[0]", 0.0);
+                poDatumEntry->SetDoubleField("params[1]", 0.0);
+                poDatumEntry->SetDoubleField("params[2]", 0.0);
+                poDatumEntry->SetDoubleField("params[3]", 0.0);
+                poDatumEntry->SetDoubleField("params[4]", 0.0);
+                poDatumEntry->SetDoubleField("params[5]", 0.0);
+                poDatumEntry->SetDoubleField("params[6]", 0.0);
+                poDatumEntry->SetStringField("gridname", "");
             }
             poMIEntry->FlushToDisk();
-            char* peStr = HFAGetPEString( hHFA );
-            if( peStr != NULL && strlen(peStr) > 0 )
-                HFASetPEString( hHFA, "" );
+            char *peStr = HFAGetPEString(hHFA);
+            if( peStr != NULL && strlen(peStr) > 0)
+                HFASetPEString(hHFA, "");
         }
     }
-    return;
 }
 
 /************************************************************************/
@@ -4237,13 +4212,13 @@ static int ESRIToUSGSZone( int nESRIZone )
     if( nESRIZone == INT_MIN )
         return 0;
     if( nESRIZone < 0 )
-        return ABS(nESRIZone);
+        return std::abs(nESRIZone);
 
-    const int nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
+    const int nPairs = sizeof(anUsgsEsriZones) / (2 * sizeof(int));
     for( int i = 0; i < nPairs; i++ )
     {
-        if( anUsgsEsriZones[i*2+1] == nESRIZone )
-            return anUsgsEsriZones[i*2];
+        if( anUsgsEsriZones[i * 2 + 1] == nESRIZone )
+            return anUsgsEsriZones[i * 2];
     }
 
     return 0;
@@ -4263,98 +4238,91 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
                    HFAEntry *poMapInformation )
 
 {
-    OGRSpatialReference oSRS;
-    char *pszNewProj = NULL;
+    // General case for Erdas style projections.
 
-/* -------------------------------------------------------------------- */
-/*      General case for Erdas style projections.                       */
-/*                                                                      */
-/*      We make a particular effort to adapt the mapinfo->proname as    */
-/*      the PROJCS[] name per #2422.                                    */
-/* -------------------------------------------------------------------- */
+    // We make a particular effort to adapt the mapinfo->proname as
+    // the PROJCS[] name per #2422.
+    OGRSpatialReference oSRS;
 
     if( psPro == NULL && psMapInfo != NULL )
     {
-        oSRS.SetLocalCS( psMapInfo->proName );
+        oSRS.SetLocalCS(psMapInfo->proName);
     }
-
     else if( psPro == NULL )
     {
         return NULL;
     }
-
     else if( psPro->proType == EPRJ_EXTERNAL )
     {
-        if( EQUALN(psPro->proExeName,EPRJ_EXTERNAL_NZMG,4) )
+        if( EQUALN(psPro->proExeName, EPRJ_EXTERNAL_NZMG, 4) )
         {
-            /* -------------------------------------------------------------------- */
-            /*         handle NZMG which is an external projection see              */
-            /*         http://www.linz.govt.nz/core/surveysystem/geodeticinfo\      */
-            /*                /datums-projections/projections/nzmg/index.html       */
-            /* -------------------------------------------------------------------- */
-            /* Is there a better way that doesn't require hardcoding of these numbers? */
-            oSRS.SetNZMG(-41.0,173.0,2510000,6023150);
+            // Handle New Zealand Map Grid (NZMG) external projection.  See:
+            // http://www.linz.govt.nz/
+            //
+            // Is there a better way that doesn't require hardcoding
+            // of these numbers?
+            oSRS.SetNZMG(-41.0, 173.0, 2510000, 6023150);
         }
         else
         {
-            oSRS.SetLocalCS( psPro->proName );
+            oSRS.SetLocalCS(psPro->proName);
         }
     }
-
-    else if( psPro->proNumber != EPRJ_LATLONG
-             && psMapInfo != NULL )
+    else if( psPro->proNumber != EPRJ_LATLONG &&
+             psMapInfo != NULL )
     {
-        oSRS.SetProjCS( psMapInfo->proName );
+        oSRS.SetProjCS(psMapInfo->proName);
     }
     else if( psPro->proNumber != EPRJ_LATLONG )
     {
-        oSRS.SetProjCS( psPro->proName );
+        oSRS.SetProjCS(psPro->proName);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Handle units.  It is important to deal with this first so       */
-/*      that the projection Set methods will automatically do           */
-/*      translation of linear values (like false easting) to PROJCS     */
-/*      units from meters.  Erdas linear projection values are          */
-/*      always in meters.                                               */
-/* -------------------------------------------------------------------- */
-    int iUnitIndex = 0;
-
+    // Handle units.  It is important to deal with this first so
+    // that the projection Set methods will automatically do
+    // translation of linear values (like false easting) to PROJCS
+    // units from meters.  Erdas linear projection values are
+    // always in meters.
     if( oSRS.IsProjected() || oSRS.IsLocal() )
     {
-        const char  *pszUnits = NULL;
+        const char *pszUnits = NULL;
 
         if( psMapInfo )
             pszUnits = psMapInfo->units;
         else if( poMapInformation != NULL )
-            pszUnits = poMapInformation->GetStringField( "units.string" );
+            pszUnits = poMapInformation->GetStringField("units.string");
 
         if( pszUnits != NULL )
         {
-            for( iUnitIndex = 0;
+            int iUnitIndex = 0;  // Used after for.
+            for( ;
                  apszUnitMap[iUnitIndex] != NULL;
                  iUnitIndex += 2 )
             {
-                if( EQUAL(apszUnitMap[iUnitIndex], pszUnits ) )
+                if( EQUAL(apszUnitMap[iUnitIndex], pszUnits) )
                     break;
             }
 
             if( apszUnitMap[iUnitIndex] == NULL )
                 iUnitIndex = 0;
 
-            oSRS.SetLinearUnits( pszUnits,
-                                 CPLAtof(apszUnitMap[iUnitIndex+1]) );
+            oSRS.SetLinearUnits(pszUnits, CPLAtof(apszUnitMap[iUnitIndex + 1]));
         }
         else
-            oSRS.SetLinearUnits( SRS_UL_METER, 1.0 );
+        {
+            oSRS.SetLinearUnits(SRS_UL_METER, 1.0);
+        }
     }
 
+    char *pszNewProj = NULL;
     if( psPro == NULL )
     {
         if( oSRS.IsLocal() )
         {
-            if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
+            if( oSRS.exportToWkt(&pszNewProj) == OGRERR_NONE )
+            {
                 return pszNewProj;
+            }
             else
             {
                 pszNewProj = NULL;
@@ -4365,21 +4333,20 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
             return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try to work out ellipsoid and datum information.                */
-/* -------------------------------------------------------------------- */
+    // Try to work out ellipsoid and datum information.
     const char *pszDatumName = psPro->proSpheroid.sphereName;
     const char *pszEllipsoidName = psPro->proSpheroid.sphereName;
-    double	dfInvFlattening;
 
     if( psDatum != NULL )
     {
         pszDatumName = psDatum->datumname;
 
-        /* Imagine to WKT translation */
-        for( int i = 0; pszDatumName != NULL && apszDatumMap[i] != NULL; i += 2 )
+        // Imagine to WKT translation.
+        for( int i = 0;
+             pszDatumName != NULL && apszDatumMap[i] != NULL;
+             i += 2 )
         {
-            if( EQUAL(pszDatumName,apszDatumMap[i]) )
+            if( EQUAL(pszDatumName, apszDatumMap[i]) )
             {
                 pszDatumName = apszDatumMap[i+1];
                 break;
@@ -4388,15 +4355,14 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
     }
 
     if( psPro->proSpheroid.a == 0.0 )
-        ((Eprj_ProParameters *) psPro)->proSpheroid.a = 6378137.0;
+        ((Eprj_ProParameters *)psPro)->proSpheroid.a = 6378137.0;
     if( psPro->proSpheroid.b == 0.0 )
-        ((Eprj_ProParameters *) psPro)->proSpheroid.b = 6356752.3;
+        ((Eprj_ProParameters *)psPro)->proSpheroid.b = 6356752.3;
 
-    dfInvFlattening = OSRCalcInvFlattening(psPro->proSpheroid.a, psPro->proSpheroid.b);
+    const double dfInvFlattening =
+        OSRCalcInvFlattening(psPro->proSpheroid.a, psPro->proSpheroid.b);
 
-/* -------------------------------------------------------------------- */
-/*      Handle different projection methods.                            */
-/* -------------------------------------------------------------------- */
+    // Handle different projection methods.
     switch( psPro->proNumber )
     {
       case EPRJ_LATLONG:
@@ -4405,375 +4371,384 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
       case EPRJ_UTM:
         // We change this to unnamed so that SetUTM will set the long
         // UTM description.
-        oSRS.SetProjCS( "unnamed" );
-        oSRS.SetUTM( psPro->proZone, psPro->proParams[3] >= 0.0 );
-
-        // The PCS name from the above function may be different with the input name.
-        // If there is a PCS name in psMapInfo that is different with
-        // the one in psPro, just use it as the PCS name. This case happens
-        // if the dataset's SR was written by the new GDAL.
-        if( psMapInfo && strlen(psMapInfo->proName) > 0
-            && strlen(psPro->proName) > 0
-            && !EQUAL(psMapInfo->proName, psPro->proName) )
-            oSRS.SetProjCS( psMapInfo->proName );
+        oSRS.SetProjCS("unnamed");
+        oSRS.SetUTM(psPro->proZone, psPro->proParams[3] >= 0.0);
+
+        // The PCS name from the above function may be different with the input
+        // name.  If there is a PCS name in psMapInfo that is different with the
+        // one in psPro, just use it as the PCS name. This case happens if the
+        // dataset's SR was written by the new GDAL.
+        if( psMapInfo && strlen(psMapInfo->proName) > 0 &&
+            strlen(psPro->proName) > 0 &&
+            !EQUAL(psMapInfo->proName, psPro->proName) )
+            oSRS.SetProjCS(psMapInfo->proName);
         break;
 
       case EPRJ_STATE_PLANE:
       {
           char *pszUnitsName = NULL;
-          double dfLinearUnits = oSRS.GetLinearUnits( &pszUnitsName );
+          double dfLinearUnits = oSRS.GetLinearUnits(&pszUnitsName);
 
-          pszUnitsName = CPLStrdup( pszUnitsName );
+          pszUnitsName = CPLStrdup(pszUnitsName);
 
-          /* Historically, hfa used esri state plane zone code. Try esri pe string first. */
-          int zoneCode = ESRIToUSGSZone(psPro->proZone);
-          const char* pszDatum;
-          if(psDatum)
+          // Historically, hfa used esri state plane zone code. Try esri pe
+          // string first.
+          const int zoneCode = ESRIToUSGSZone(psPro->proZone);
+          const char *pszDatum;
+          if( psDatum )
               pszDatum = psDatum->datumname;
           else
               pszDatum = "HARN";
-          const char* pszUnits;
-          if(psMapInfo)
+          const char *pszUnits;
+          if( psMapInfo )
               pszUnits = psMapInfo->units;
-          else if(pszUnitsName && strlen(pszUnitsName) > 0)
+          else if( pszUnitsName && strlen(pszUnitsName) > 0 )
               pszUnits = pszUnitsName;
           else
               pszUnits = "meters";
-          int proNu = 0;
-          if(psPro)
-              proNu = psPro->proNumber;
-          if(oSRS.ImportFromESRIStatePlaneWKT(zoneCode, pszDatum, pszUnits, proNu) == OGRERR_NONE)
+          const int proNu = psPro->proNumber;
+          if( oSRS.ImportFromESRIStatePlaneWKT(zoneCode, pszDatum,
+                                               pszUnits, proNu) == OGRERR_NONE )
           {
-              CPLFree( pszUnitsName );
+              CPLFree(pszUnitsName);
               oSRS.morphFromESRI();
               oSRS.AutoIdentifyEPSG();
               oSRS.Fixup();
-              if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
+              if( oSRS.exportToWkt(&pszNewProj) == OGRERR_NONE )
                   return pszNewProj;
               else
                   return NULL;
           }
 
-          /* Set state plane zone.  Set NAD83/27 on basis of spheroid */
-          oSRS.SetStatePlane( ESRIToUSGSZone(psPro->proZone),
-                              fabs(psPro->proSpheroid.a - 6378137.0)< 1.0,
-                              pszUnitsName, dfLinearUnits );
+          // Set state plane zone.  Set NAD83/27 on basis of spheroid.
+          oSRS.SetStatePlane(ESRIToUSGSZone(psPro->proZone),
+                             fabs(psPro->proSpheroid.a - 6378137.0)< 1.0,
+                             pszUnitsName, dfLinearUnits);
 
-          CPLFree( pszUnitsName );
+          CPLFree(pszUnitsName);
 
           // Same as the UTM, The following is needed.
-          if( psMapInfo && strlen(psMapInfo->proName) > 0
-              && strlen(psPro->proName) > 0
-              && !EQUAL(psMapInfo->proName, psPro->proName) )
-              oSRS.SetProjCS( psMapInfo->proName );
+          if( psMapInfo && strlen(psMapInfo->proName) > 0 &&
+              strlen(psPro->proName) > 0 &&
+              !EQUAL(psMapInfo->proName, psPro->proName) )
+              oSRS.SetProjCS(psMapInfo->proName);
       }
       break;
 
       case EPRJ_ALBERS_CONIC_EQUAL_AREA:
-        oSRS.SetACEA( psPro->proParams[2]*R2D, psPro->proParams[3]*R2D,
-                      psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                      psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetACEA(psPro->proParams[2] * R2D, psPro->proParams[3] * R2D,
+                     psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                     psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_LAMBERT_CONFORMAL_CONIC:
-        // check the possible Wisconsin first
-        if(psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN"))
+        // Check the possible Wisconsin first.
+        if( psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN") )
         {
-            if(oSRS.ImportFromESRIWisconsinWKT("Lambert_Conformal_Conic", psPro->proParams[4]*R2D, psPro->proParams[5]*R2D, psMapInfo->units) == OGRERR_NONE)
+            if( oSRS.ImportFromESRIWisconsinWKT(
+                    "Lambert_Conformal_Conic", psPro->proParams[4] * R2D,
+                    psPro->proParams[5] * R2D,
+                    psMapInfo->units) == OGRERR_NONE )
             {
                 oSRS.morphFromESRI();
                 oSRS.AutoIdentifyEPSG();
                 oSRS.Fixup();
-                if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
+                if( oSRS.exportToWkt(&pszNewProj) == OGRERR_NONE )
                     return pszNewProj;
             }
         }
-        oSRS.SetLCC( psPro->proParams[2]*R2D, psPro->proParams[3]*R2D,
-                     psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                     psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetLCC(psPro->proParams[2] * R2D, psPro->proParams[3] * R2D,
+                    psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                    psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_MERCATOR:
-        oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                          1.0,
-                          psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetMercator(psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
+                         1.0,
+                         psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_POLAR_STEREOGRAPHIC:
-        oSRS.SetPS( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                    1.0,
-                    psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetPS(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                   1.0,
+                   psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_POLYCONIC:
-        oSRS.SetPolyconic( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                           psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetPolyconic(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                          psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_EQUIDISTANT_CONIC:
-        double		dfStdParallel2;
-
-        if( psPro->proParams[8] != 0.0 )
-            dfStdParallel2 = psPro->proParams[3]*R2D;
-        else
-            dfStdParallel2 = psPro->proParams[2]*R2D;
-        oSRS.SetEC( psPro->proParams[2]*R2D, dfStdParallel2,
-                    psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                    psPro->proParams[6], psPro->proParams[7] );
-        break;
-
+      {
+          const double dfStdParallel2 =
+              psPro->proParams[8] != 0.0
+              ? psPro->proParams[3] * R2D
+              : psPro->proParams[2] * R2D;
+          oSRS.SetEC(psPro->proParams[2] * R2D, dfStdParallel2,
+                     psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                     psPro->proParams[6], psPro->proParams[7]);
+          break;
+      }
       case EPRJ_TRANSVERSE_MERCATOR:
       case EPRJ_GAUSS_KRUGER:
-        // check the possible Wisconsin first
-        if(psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN"))
+        // Check the possible Wisconsin first.
+        if( psDatum && psMapInfo && EQUAL(psDatum->datumname, "HARN") )
         {
-            if(oSRS.ImportFromESRIWisconsinWKT("Transverse_Mercator", psPro->proParams[4]*R2D, psPro->proParams[5]*R2D, psMapInfo->units) == OGRERR_NONE)
+            if( oSRS.ImportFromESRIWisconsinWKT(
+                    "Transverse_Mercator",
+                    psPro->proParams[4] * R2D,
+                    psPro->proParams[5] * R2D,
+                    psMapInfo->units) == OGRERR_NONE )
             {
                 oSRS.morphFromESRI();
                 oSRS.AutoIdentifyEPSG();
                 oSRS.Fixup();
-                if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
+                if( oSRS.exportToWkt(&pszNewProj) == OGRERR_NONE )
                     return pszNewProj;
             }
         }
-        oSRS.SetTM( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                    psPro->proParams[2],
-                    psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetTM(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                   psPro->proParams[2],
+                   psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_STEREOGRAPHIC:
-        oSRS.SetStereographic( psPro->proParams[5]*R2D,psPro->proParams[4]*R2D,
-                               1.0,
-                               psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetStereographic(psPro->proParams[5] * R2D,
+                              psPro->proParams[4] * R2D,
+                              1.0,
+                              psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_LAMBERT_AZIMUTHAL_EQUAL_AREA:
-        oSRS.SetLAEA( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                      psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetLAEA(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                     psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_AZIMUTHAL_EQUIDISTANT:
-        oSRS.SetAE( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                    psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetAE(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                   psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_GNOMONIC:
-        oSRS.SetGnomonic( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                          psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetGnomonic(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                         psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_ORTHOGRAPHIC:
-        oSRS.SetOrthographic( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                              psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetOrthographic(psPro->proParams[5] * R2D,
+                             psPro->proParams[4] * R2D,
+                             psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_SINUSOIDAL:
-        oSRS.SetSinusoidal( psPro->proParams[4]*R2D,
-                            psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetSinusoidal(psPro->proParams[4] * R2D,
+                           psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_PLATE_CARREE:
       case EPRJ_EQUIRECTANGULAR:
-        oSRS.SetEquirectangular2( 0.0,
-                                  psPro->proParams[4]*R2D,
-                                  psPro->proParams[5]*R2D,
-                                  psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetEquirectangular2(0.0,
+                                 psPro->proParams[4] * R2D,
+                                 psPro->proParams[5] * R2D,
+                                 psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_EQUIDISTANT_CYLINDRICAL:
-        oSRS.SetEquirectangular2( 0.0,
-                                  psPro->proParams[4]*R2D,
-                                  psPro->proParams[2]*R2D,
-                                  psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetEquirectangular2(0.0,
+                                 psPro->proParams[4] * R2D,
+                                 psPro->proParams[2] * R2D,
+                                 psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_MILLER_CYLINDRICAL:
-        oSRS.SetMC( 0.0, psPro->proParams[4]*R2D,
-                    psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetMC(0.0, psPro->proParams[4] * R2D,
+                   psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_VANDERGRINTEN:
-        oSRS.SetVDG( psPro->proParams[4]*R2D,
-                     psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetVDG(psPro->proParams[4] * R2D,
+                    psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_HOTINE_OBLIQUE_MERCATOR:
         if( psPro->proParams[12] > 0.0 )
-            oSRS.SetHOM( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                         psPro->proParams[3]*R2D, 0.0,
-                         psPro->proParams[2],
-                         psPro->proParams[6], psPro->proParams[7] );
+            oSRS.SetHOM(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                        psPro->proParams[3] * R2D, 0.0,
+                        psPro->proParams[2],
+                        psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER:
-        oSRS.SetHOMAC( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                        psPro->proParams[3]*R2D, 0.0,
-                        psPro->proParams[2],
-                        psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetHOMAC(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                      psPro->proParams[3] * R2D, 0.0,
+                      psPro->proParams[2],
+                      psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_ROBINSON:
-        oSRS.SetRobinson( psPro->proParams[4]*R2D,
-                          psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetRobinson(psPro->proParams[4] * R2D,
+                         psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_MOLLWEIDE:
-        oSRS.SetMollweide( psPro->proParams[4]*R2D,
-                           psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetMollweide(psPro->proParams[4] * R2D,
+                          psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_GALL_STEREOGRAPHIC:
-        oSRS.SetGS( psPro->proParams[4]*R2D,
-                    psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetGS(psPro->proParams[4] * R2D,
+                   psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_ECKERT_I:
-        oSRS.SetEckert( 1, psPro->proParams[4]*R2D,
-                        psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetEckert(1, psPro->proParams[4] * R2D,
+                       psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_ECKERT_II:
-        oSRS.SetEckert( 2, psPro->proParams[4]*R2D,
-                        psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetEckert(2, psPro->proParams[4] * R2D,
+                       psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_ECKERT_III:
-        oSRS.SetEckert( 3, psPro->proParams[4]*R2D,
-                        psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetEckert(3, psPro->proParams[4] * R2D,
+                       psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_ECKERT_IV:
-        oSRS.SetEckert( 4, psPro->proParams[4]*R2D,
-                        psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetEckert(4, psPro->proParams[4] * R2D,
+                       psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_ECKERT_V:
-        oSRS.SetEckert( 5, psPro->proParams[4]*R2D,
-                        psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetEckert(5, psPro->proParams[4] * R2D,
+                       psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_ECKERT_VI:
-        oSRS.SetEckert( 6, psPro->proParams[4]*R2D,
-                        psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetEckert(6, psPro->proParams[4] * R2D,
+                       psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_CASSINI:
-        oSRS.SetCS( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                    psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetCS(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                   psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_TWO_POINT_EQUIDISTANT:
-        oSRS.SetTPED( psPro->proParams[9] * R2D,
-                      psPro->proParams[8] * R2D,
-                      psPro->proParams[11] * R2D,
-                      psPro->proParams[10] * R2D,
-                      psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetTPED(psPro->proParams[9] * R2D,
+                     psPro->proParams[8] * R2D,
+                     psPro->proParams[11] * R2D,
+                     psPro->proParams[10] * R2D,
+                     psPro->proParams[6], psPro->proParams[7]);
       break;
 
       case EPRJ_STEREOGRAPHIC_EXTENDED:
-        oSRS.SetStereographic( psPro->proParams[5]*R2D,psPro->proParams[4]*R2D,
-                               psPro->proParams[2],
-                               psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetStereographic(psPro->proParams[5] * R2D,
+                              psPro->proParams[4] * R2D,
+                              psPro->proParams[2],
+                              psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_BONNE:
-        oSRS.SetBonne( psPro->proParams[2]*R2D, psPro->proParams[4]*R2D,
-                       psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetBonne(psPro->proParams[2] * R2D, psPro->proParams[4] * R2D,
+                      psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_LOXIMUTHAL:
       {
-          oSRS.SetProjection( "Loximuthal" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( "central_parallel",
-                           psPro->proParams[5] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Loximuthal");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm("central_parallel",
+                           psPro->proParams[5] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_QUARTIC_AUTHALIC:
       {
-          oSRS.SetProjection( "Quartic_Authalic" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Quartic_Authalic");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_WINKEL_I:
       {
-          oSRS.SetProjection( "Winkel_I" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
-                           psPro->proParams[2] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Winkel_I");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,
+                           psPro->proParams[2] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_WINKEL_II:
       {
-          oSRS.SetProjection( "Winkel_II" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
-                           psPro->proParams[2] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Winkel_II");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,
+                           psPro->proParams[2] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_BEHRMANN:
       {
-          oSRS.SetProjection( "Behrmann" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Behrmann");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_KROVAK:
-        oSRS.SetKrovak( psPro->proParams[4]*R2D, psPro->proParams[5]*R2D,
-                        psPro->proParams[3]*R2D, psPro->proParams[9]*R2D,
-                        psPro->proParams[2],
-                        psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetKrovak(psPro->proParams[4] * R2D, psPro->proParams[5] * R2D,
+                       psPro->proParams[3] * R2D, psPro->proParams[9] * R2D,
+                       psPro->proParams[2],
+                       psPro->proParams[6], psPro->proParams[7]);
         break;
 
       case EPRJ_DOUBLE_STEREOGRAPHIC:
       {
-          oSRS.SetProjection( "Double_Stereographic" );
-          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN,
-                           psPro->proParams[5] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR, psPro->proParams[2] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Double_Stereographic");
+          oSRS.SetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,
+                           psPro->proParams[5] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_SCALE_FACTOR, psPro->proParams[2]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_AITOFF:
       {
-          oSRS.SetProjection( "Aitoff" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Aitoff");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_CRASTER_PARABOLIC:
       {
-          oSRS.SetProjection( "Craster_Parabolic" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Craster_Parabolic");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
@@ -4784,161 +4759,168 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 
       case EPRJ_FLAT_POLAR_QUARTIC:
       {
-          oSRS.SetProjection( "Flat_Polar_Quartic" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Flat_Polar_Quartic");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_TIMES:
       {
-          oSRS.SetProjection( "Times" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Times");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_WINKEL_TRIPEL:
       {
-          oSRS.SetProjection( "Winkel_Tripel" );
-          oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1,
-                           psPro->proParams[2] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Winkel_Tripel");
+          oSRS.SetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,
+                           psPro->proParams[2] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_HAMMER_AITOFF:
       {
-          oSRS.SetProjection( "Hammer_Aitoff" );
-          oSRS.SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Hammer_Aitoff");
+          oSRS.SetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_VERTICAL_NEAR_SIDE_PERSPECTIVE:
       {
-          oSRS.SetProjection( "Vertical_Near_Side_Perspective" );
-          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
-                           psPro->proParams[5] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER,
-                           psPro->proParams[4] * R2D );
-          oSRS.SetNormProjParm( "height",
-                           psPro->proParams[2] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Vertical_Near_Side_Perspective");
+          oSRS.SetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,
+                           psPro->proParams[5] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,
+                           psPro->proParams[4] * R2D);
+          oSRS.SetNormProjParm("height",
+                           psPro->proParams[2]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_CENTER:
       {
-          oSRS.SetProjection( "Hotine_Oblique_Mercator_Twp_Point_Center" );
-          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER,
-                           psPro->proParams[5] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_1ST_POINT,
-                           psPro->proParams[9] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_1ST_POINT,
-                           psPro->proParams[8] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_LATITUDE_OF_2ND_POINT,
-                           psPro->proParams[11] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_LONGITUDE_OF_2ND_POINT,
-                           psPro->proParams[10] * R2D );
-          oSRS.SetNormProjParm( SRS_PP_SCALE_FACTOR,
-                           psPro->proParams[2] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_EASTING, psPro->proParams[6] );
-          oSRS.SetNormProjParm( SRS_PP_FALSE_NORTHING, psPro->proParams[7] );
+          oSRS.SetProjection("Hotine_Oblique_Mercator_Twp_Point_Center");
+          oSRS.SetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,
+                           psPro->proParams[5] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT,
+                           psPro->proParams[9] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_LONGITUDE_OF_1ST_POINT,
+                           psPro->proParams[8] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT,
+                           psPro->proParams[11] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_LONGITUDE_OF_2ND_POINT,
+                           psPro->proParams[10] * R2D);
+          oSRS.SetNormProjParm(SRS_PP_SCALE_FACTOR,
+                           psPro->proParams[2]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_EASTING, psPro->proParams[6]);
+          oSRS.SetNormProjParm(SRS_PP_FALSE_NORTHING, psPro->proParams[7]);
       }
       break;
 
       case EPRJ_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN:
-        oSRS.SetHOM2PNO( psPro->proParams[5] * R2D,
-                         psPro->proParams[8] * R2D,
-                         psPro->proParams[9] * R2D,
-                         psPro->proParams[10] * R2D,
-                         psPro->proParams[11] * R2D,
-                         psPro->proParams[2],
-                         psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetHOM2PNO(psPro->proParams[5] * R2D,
+                        psPro->proParams[8] * R2D,
+                        psPro->proParams[9] * R2D,
+                        psPro->proParams[10] * R2D,
+                        psPro->proParams[11] * R2D,
+                        psPro->proParams[2],
+                        psPro->proParams[6], psPro->proParams[7]);
       break;
 
       case EPRJ_LAMBERT_CONFORMAL_CONIC_1SP:
-        oSRS.SetLCC1SP( psPro->proParams[3]*R2D, psPro->proParams[2]*R2D,
-                        psPro->proParams[4],
-                        psPro->proParams[5], psPro->proParams[6] );
+        oSRS.SetLCC1SP(psPro->proParams[3] * R2D, psPro->proParams[2] * R2D,
+                       psPro->proParams[4],
+                       psPro->proParams[5], psPro->proParams[6]);
         break;
 
       case EPRJ_MERCATOR_VARIANT_A:
-        oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                          psPro->proParams[2],
-                          psPro->proParams[6], psPro->proParams[7] );
+        oSRS.SetMercator(psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
+                         psPro->proParams[2],
+                         psPro->proParams[6], psPro->proParams[7]);
         break;
 
-      case EPRJ_PSEUDO_MERCATOR: // likely this is google mercator?
-        oSRS.SetMercator( psPro->proParams[5]*R2D, psPro->proParams[4]*R2D,
-                          1.0,
-                          psPro->proParams[6], psPro->proParams[7] );
+      case EPRJ_PSEUDO_MERCATOR:  // Likely this is google mercator?
+        oSRS.SetMercator(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+                         1.0,
+                         psPro->proParams[6], psPro->proParams[7]);
+        break;
+
+      case EPRJ_HOTINE_OBLIQUE_MERCATOR_VARIANT_A:
+        oSRS.SetHOM(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+            psPro->proParams[3] * R2D, psPro->proParams[8] * R2D,
+            psPro->proParams[2],
+            psPro->proParams[6], psPro->proParams[7]);
+        break;
+
+      case EPRJ_TRANSVERSE_MERCATOR_SOUTH_ORIENTATED:
+        oSRS.SetTMSO(psPro->proParams[5] * R2D, psPro->proParams[4] * R2D,
+            psPro->proParams[2],
+            psPro->proParams[6], psPro->proParams[7]);
         break;
 
       default:
         if( oSRS.IsProjected() )
-            oSRS.GetRoot()->SetValue( "LOCAL_CS" );
+            oSRS.GetRoot()->SetValue("LOCAL_CS");
         else
-            oSRS.SetLocalCS( psPro->proName );
+            oSRS.SetLocalCS(psPro->proName);
         break;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try and set the GeogCS information.                             */
-/* -------------------------------------------------------------------- */
-    if( oSRS.GetAttrNode("GEOGCS") == NULL
-        && oSRS.GetAttrNode("LOCAL_CS") == NULL )
+    // Try and set the GeogCS information.
+    if( oSRS.GetAttrNode("GEOGCS") == NULL &&
+        oSRS.GetAttrNode("LOCAL_CS") == NULL )
     {
         if( pszDatumName == NULL)
-            oSRS.SetGeogCS( pszDatumName, pszDatumName, pszEllipsoidName,
-                            psPro->proSpheroid.a, dfInvFlattening );
-        else if( EQUAL(pszDatumName,"WGS 84")
-            ||  EQUAL(pszDatumName,"WGS_1984") )
-            oSRS.SetWellKnownGeogCS( "WGS84" );
-        else if( strstr(pszDatumName,"NAD27") != NULL
+            oSRS.SetGeogCS(pszDatumName, pszDatumName, pszEllipsoidName,
+                           psPro->proSpheroid.a, dfInvFlattening);
+        else if( EQUAL(pszDatumName, "WGS 84")
+            || EQUAL(pszDatumName,"WGS_1984") )
+            oSRS.SetWellKnownGeogCS("WGS84" );
+        else if( strstr(pszDatumName, "NAD27") != NULL
                  || EQUAL(pszDatumName,"North_American_Datum_1927") )
-            oSRS.SetWellKnownGeogCS( "NAD27" );
-        else if( strstr(pszDatumName,"NAD83") != NULL
-                 || EQUAL(pszDatumName,"North_American_Datum_1983"))
-            oSRS.SetWellKnownGeogCS( "NAD83" );
+            oSRS.SetWellKnownGeogCS("NAD27");
+        else if( strstr(pszDatumName, "NAD83") != NULL
+                 || EQUAL(pszDatumName, "North_American_Datum_1983"))
+            oSRS.SetWellKnownGeogCS("NAD83");
         else
-            oSRS.SetGeogCS( pszDatumName, pszDatumName, pszEllipsoidName,
-                            psPro->proSpheroid.a, dfInvFlattening );
+            oSRS.SetGeogCS(pszDatumName, pszDatumName, pszEllipsoidName,
+                           psPro->proSpheroid.a, dfInvFlattening);
 
         if( psDatum != NULL && psDatum->type == EPRJ_DATUM_PARAMETRIC )
         {
-            oSRS.SetTOWGS84( psDatum->params[0],
-                             psDatum->params[1],
-                             psDatum->params[2],
-                             psDatum->params[3],
-                             psDatum->params[4],
-                             psDatum->params[5],
-                             psDatum->params[6] );
+            oSRS.SetTOWGS84(psDatum->params[0],
+                            psDatum->params[1],
+                            psDatum->params[2],
+                            -psDatum->params[3] * RAD2ARCSEC,
+                            -psDatum->params[4] * RAD2ARCSEC,
+                            -psDatum->params[5] * RAD2ARCSEC,
+                            psDatum->params[6] * 1e+6);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try to insert authority information if possible.  Fixup any     */
-/*      ordering oddities.                                              */
-/* -------------------------------------------------------------------- */
+    // Try to insert authority information if possible.  Fixup any
+    // ordering oddities.
     oSRS.AutoIdentifyEPSG();
     oSRS.Fixup();
 
-/* -------------------------------------------------------------------- */
-/*      Get the WKT representation of the coordinate system.            */
-/* -------------------------------------------------------------------- */
-    if( oSRS.exportToWkt( &pszNewProj ) == OGRERR_NONE )
+    // Get the WKT representation of the coordinate system.
+    if( oSRS.exportToWkt(&pszNewProj) == OGRERR_NONE )
         return pszNewProj;
 
     return NULL;
@@ -4951,19 +4933,13 @@ HFAPCSStructToWKT( const Eprj_Datum *psDatum,
 CPLErr HFADataset::ReadProjection()
 
 {
-    OGRSpatialReference        oSRS;
-    char *pszPE_COORDSYS = NULL;
-    int bTryReadingPEString = TRUE;
-
-/* -------------------------------------------------------------------- */
-/*      General case for Erdas style projections.                       */
-/*                                                                      */
-/*      We make a particular effort to adapt the mapinfo->proname as    */
-/*      the PROJCS[] name per #2422.                                    */
-/* -------------------------------------------------------------------- */
-    const Eprj_Datum *psDatum = HFAGetDatum( hHFA );
-    const Eprj_ProParameters *psPro = HFAGetProParameters( hHFA );
-    const Eprj_MapInfo *psMapInfo = HFAGetMapInfo( hHFA );
+    // General case for Erdas style projections.
+    //
+    // We make a particular effort to adapt the mapinfo->proname as
+    // the PROJCS[] name per #2422.
+    const Eprj_Datum *psDatum = HFAGetDatum(hHFA);
+    const Eprj_ProParameters *psPro = HFAGetProParameters(hHFA);
+    const Eprj_MapInfo *psMapInfo = HFAGetMapInfo(hHFA);
 
     HFAEntry *poMapInformation = NULL;
     if( psMapInfo == NULL )
@@ -4972,44 +4948,49 @@ CPLErr HFADataset::ReadProjection()
         poMapInformation = poBand->poNode->GetNamedChild("MapInformation");
     }
 
-    CPLFree( pszProjection );
+    CPLFree(pszProjection);
 
-    if((psMapInfo == NULL && poMapInformation == NULL) ||
-       ((!psDatum || strlen(psDatum->datumname) == 0 || EQUAL(psDatum->datumname, "Unknown")) &&
-       (!psPro || strlen(psPro->proName) == 0 || EQUAL(psPro->proName, "Unknown")) &&
-       (psMapInfo && (strlen(psMapInfo->proName) == 0 || EQUAL(psMapInfo->proName, "Unknown"))) &&
-       (!psPro || psPro->proZone == 0)) )
+    if( (psMapInfo == NULL && poMapInformation == NULL) ||
+        ((!psDatum || strlen(psDatum->datumname) == 0 ||
+          EQUAL(psDatum->datumname, "Unknown")) &&
+         (!psPro || strlen(psPro->proName) == 0 ||
+          EQUAL(psPro->proName, "Unknown")) &&
+         (psMapInfo && (strlen(psMapInfo->proName) == 0 ||
+                        EQUAL(psMapInfo->proName, "Unknown"))) &&
+         (!psPro || psPro->proZone == 0)) )
     {
         pszProjection = CPLStrdup("");
         return CE_None;
     }
 
-    pszProjection = HFAPCSStructToWKT( psDatum, psPro, psMapInfo,
-                                       poMapInformation );
+    pszProjection =
+        HFAPCSStructToWKT(psDatum, psPro, psMapInfo, poMapInformation);
 
     // If we got a valid projection and managed to identify a EPSG code,
     // then do not use the ESRI PE String.
+    bool bTryReadingPEString = true;
+
+    OGRSpatialReference oSRS;
     if( pszProjection != NULL )
     {
         OGRSpatialReference oSRS2(pszProjection);
         if( oSRS2.GetAuthorityCode(NULL) != NULL )
-            bTryReadingPEString = FALSE;
+            bTryReadingPEString = false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Special logic for PE string in ProjectionX node.                */
-/* -------------------------------------------------------------------- */
+    // Special logic for PE string in ProjectionX node.
+    char *pszPE_COORDSYS = NULL;
     if( bTryReadingPEString )
-        pszPE_COORDSYS = HFAGetPEString( hHFA );
+        pszPE_COORDSYS = HFAGetPEString(hHFA);
     if( pszPE_COORDSYS != NULL
         && strlen(pszPE_COORDSYS) > 0
-        && oSRS.SetFromUserInput( pszPE_COORDSYS ) == OGRERR_NONE )
+        && oSRS.SetFromUserInput(pszPE_COORDSYS) == OGRERR_NONE )
     {
-        CPLFree( pszPE_COORDSYS );
+        CPLFree(pszPE_COORDSYS);
 
         oSRS.morphFromESRI();
 
-        // Copy TOWGS84 clause from HFA SRS to PE SRS
+        // Copy TOWGS84 clause from HFA SRS to PE SRS.
         if( pszProjection != NULL )
         {
             OGRSpatialReference oSRS_HFA(pszProjection);
@@ -5029,22 +5010,20 @@ CPLErr HFADataset::ReadProjection()
 
         oSRS.Fixup();
 
-        CPLFree( pszProjection );
+        CPLFree(pszProjection);
         pszProjection = NULL;
-        oSRS.exportToWkt( &pszProjection );
+        oSRS.exportToWkt(&pszProjection);
 
         return CE_None;
     }
 
-    CPLFree( pszPE_COORDSYS );
+    CPLFree(pszPE_COORDSYS);
 
     if( pszProjection != NULL )
         return CE_None;
-    else
-    {
-        pszProjection = CPLStrdup("");
-        return CE_Failure;
-    }
+
+    pszProjection = CPLStrdup("");
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -5055,47 +5034,46 @@ CPLErr HFADataset::IBuildOverviews( const char *pszResampling,
                                     int nOverviews, int *panOverviewList,
                                     int nListBands, int *panBandList,
                                     GDALProgressFunc pfnProgress,
-                                    void * pProgressData )
+                                    void *pProgressData )
 
 {
     if( GetAccess() == GA_ReadOnly )
     {
         for( int i = 0; i < nListBands; i++ )
         {
-            if (HFAGetOverviewCount(hHFA, panBandList[i]) > 0)
+            if( HFAGetOverviewCount(hHFA, panBandList[i]) > 0 )
             {
                 CPLError(CE_Failure, CPLE_NotSupported,
-                        "Cannot add external overviews when there are already internal overviews");
+                         "Cannot add external overviews when there are already "
+                         "internal overviews");
                 return CE_Failure;
             }
         }
 
-        return GDALDataset::IBuildOverviews( pszResampling,
-                                             nOverviews, panOverviewList,
-                                             nListBands, panBandList,
-                                             pfnProgress, pProgressData );
+        return GDALDataset::IBuildOverviews(
+            pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
+            pfnProgress, pProgressData);
     }
 
     for( int i = 0; i < nListBands; i++ )
     {
-        void* pScaledProgressData = GDALCreateScaledProgress(
-                i * 1.0 / nListBands, (i + 1) * 1.0 / nListBands,
-                pfnProgress, pProgressData);
+        void *pScaledProgressData = GDALCreateScaledProgress(
+            i * 1.0 / nListBands, (i + 1) * 1.0 / nListBands,
+            pfnProgress, pProgressData);
 
-        GDALRasterBand *poBand = GetRasterBand( panBandList[i] );
+        GDALRasterBand *poBand = GetRasterBand(panBandList[i]);
 
-        //GetRasterBand can return NULL
-        if(poBand == NULL)
+        // GetRasterBand can return NULL.
+        if( poBand == NULL )
         {
-            CPLError(CE_Failure, CPLE_ObjectNull,
-                        "GetRasterBand failed");
+            CPLError(CE_Failure, CPLE_ObjectNull, "GetRasterBand failed");
             GDALDestroyScaledProgress(pScaledProgressData);
             return CE_Failure;
         }
 
-        CPLErr eErr
-            = poBand->BuildOverviews( pszResampling, nOverviews, panOverviewList,
-                                    GDALScaledProgress, pScaledProgressData );
+        const CPLErr eErr =
+            poBand->BuildOverviews(pszResampling, nOverviews, panOverviewList,
+                                   GDALScaledProgress, pScaledProgressData);
 
         GDALDestroyScaledProgress(pScaledProgressData);
 
@@ -5110,14 +5088,12 @@ CPLErr HFADataset::IBuildOverviews( const char *pszResampling,
 /*                              Identify()                              */
 /************************************************************************/
 
-int HFADataset::Identify( GDALOpenInfo * poOpenInfo )
+int HFADataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Verify that this is a HFA file.                                 */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 15
-        || !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "EHFA_HEADER_TAG") )
+    // Verify that this is a HFA file.
+    if( poOpenInfo->nHeaderBytes < 15 ||
+        !STARTS_WITH_CI((char *) poOpenInfo->pabyHeader, "EHFA_HEADER_TAG") )
         return FALSE;
 
     return TRUE;
@@ -5130,190 +5106,173 @@ int HFADataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *HFADataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Verify that this is a HFA file.                                 */
-/* -------------------------------------------------------------------- */
-    if( !Identify( poOpenInfo ) )
+    // Verify that this is a HFA file.
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    // During fuzzing, do not use Identify to reject crazy content.
+    if( !Identify(poOpenInfo) )
         return NULL;
+#endif
 
-/* -------------------------------------------------------------------- */
-/*      Open the file.                                                  */
-/* -------------------------------------------------------------------- */
-    HFAHandle	hHFA;
-
-    if( poOpenInfo->eAccess == GA_Update )
-        hHFA = HFAOpen( poOpenInfo->pszFilename, "r+" );
-    else
-        hHFA = HFAOpen( poOpenInfo->pszFilename, "r" );
+    // Open the file.
+    HFAHandle hHFA =
+      HFAOpen(poOpenInfo->pszFilename,
+              (poOpenInfo->eAccess == GA_Update ? "r+" : "r"));
 
     if( hHFA == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
-    HFADataset 	*poDS = new HFADataset();
+    // Create a corresponding GDALDataset.
+    HFADataset *poDS = new HFADataset();
 
     poDS->hHFA = hHFA;
     poDS->eAccess = poOpenInfo->eAccess;
 
-/* -------------------------------------------------------------------- */
-/*      Establish raster info.                                          */
-/* -------------------------------------------------------------------- */
-    HFAGetRasterInfo( hHFA, &poDS->nRasterXSize, &poDS->nRasterYSize,
-                      &poDS->nBands );
+    // Establish raster info.
+    HFAGetRasterInfo(hHFA, &poDS->nRasterXSize, &poDS->nRasterYSize,
+                     &poDS->nBands);
 
     if( poDS->nBands == 0 )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to open %s, it has zero usable bands.",
-                  poOpenInfo->pszFilename );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to open %s, it has zero usable bands.",
+                 poOpenInfo->pszFilename);
         return NULL;
     }
 
     if( poDS->nRasterXSize == 0 || poDS->nRasterYSize == 0 )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to open %s, it has no pixels.",
-                  poOpenInfo->pszFilename );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to open %s, it has no pixels.",
+                 poOpenInfo->pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Get geotransform, or if that fails, try to find XForms to 	*/
-/*	build gcps, and metadata.					*/
-/* -------------------------------------------------------------------- */
-    if( !HFAGetGeoTransform( hHFA, poDS->adfGeoTransform ) )
+    // Get geotransform, or if that fails, try to find XForms to
+    // build gcps, and metadata.
+    if( !HFAGetGeoTransform(hHFA, poDS->adfGeoTransform) )
     {
         Efga_Polynomial *pasPolyListForward = NULL;
         Efga_Polynomial *pasPolyListReverse = NULL;
-        int nStepCount =
-            HFAReadXFormStack( hHFA, &pasPolyListForward,
-                               &pasPolyListReverse );
+        const int nStepCount =
+            HFAReadXFormStack(hHFA, &pasPolyListForward, &pasPolyListReverse);
 
         if( nStepCount > 0 )
         {
-            poDS->UseXFormStack( nStepCount,
-                                 pasPolyListForward,
-                                 pasPolyListReverse );
-            CPLFree( pasPolyListForward );
-            CPLFree( pasPolyListReverse );
+            poDS->UseXFormStack(nStepCount,
+                                pasPolyListForward,
+                                pasPolyListReverse);
+            CPLFree(pasPolyListForward);
+            CPLFree(pasPolyListReverse);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Get the projection.                                             */
-/* -------------------------------------------------------------------- */
     poDS->ReadProjection();
 
-/* -------------------------------------------------------------------- */
-/*      Read the camera model as metadata, if present.                  */
-/* -------------------------------------------------------------------- */
-    char **papszCM = HFAReadCameraModel( hHFA );
+    char **papszCM = HFAReadCameraModel(hHFA);
 
     if( papszCM != NULL )
     {
-        poDS->SetMetadata( papszCM, "CAMERA_MODEL" );
-        CSLDestroy( papszCM );
+        poDS->SetMetadata(papszCM, "CAMERA_MODEL");
+        CSLDestroy(papszCM);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
     for( int i = 0; i < poDS->nBands; i++ )
     {
-        poDS->SetBand( i+1, new HFARasterBand( poDS, i+1, -1 ) );
+        poDS->SetBand(i + 1, new HFARasterBand(poDS, i + 1, -1));
     }
 
-/* -------------------------------------------------------------------- */
-/*      Collect GDAL custom Metadata, and "auxiliary" metadata from     */
-/*      well known HFA structures for the bands.  We defer this till    */
-/*      now to ensure that the bands are properly setup before          */
-/*      interacting with PAM.                                           */
-/* -------------------------------------------------------------------- */
+    // Collect GDAL custom Metadata, and "auxiliary" metadata from
+    // well known HFA structures for the bands.  We defer this till
+    // now to ensure that the bands are properly setup before
+    // interacting with PAM.
     for( int i = 0; i < poDS->nBands; i++ )
     {
-        HFARasterBand *poBand = (HFARasterBand *) poDS->GetRasterBand( i+1 );
+        HFARasterBand *poBand =
+            static_cast<HFARasterBand *>(poDS->GetRasterBand(i + 1));
 
-        char **papszMD = HFAGetMetadata( hHFA, i+1 );
+        char **papszMD = HFAGetMetadata(hHFA, i + 1);
         if( papszMD != NULL )
         {
-            poBand->SetMetadata( papszMD );
-            CSLDestroy( papszMD );
+            poBand->SetMetadata(papszMD);
+            CSLDestroy(papszMD);
         }
 
         poBand->ReadAuxMetadata();
         poBand->ReadHistogramMetadata();
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check for GDAL style metadata.                                  */
-/* -------------------------------------------------------------------- */
-    char **papszMD = HFAGetMetadata( hHFA, 0 );
+    // Check for GDAL style metadata.
+    char **papszMD = HFAGetMetadata(hHFA, 0);
     if( papszMD != NULL )
     {
-        poDS->SetMetadata( papszMD );
-        CSLDestroy( papszMD );
+        poDS->SetMetadata(papszMD);
+        CSLDestroy(papszMD);
+    }
+
+    // Read the elevation metadata, if present.
+    for( int iBand = 0; iBand < poDS->nBands; iBand++ )
+    {
+        HFARasterBand *poBand =
+            static_cast<HFARasterBand *>(poDS->GetRasterBand(iBand + 1));
+        const char *pszEU = HFAReadElevationUnit(hHFA, iBand);
+
+        if( pszEU != NULL )
+        {
+            poBand->SetUnitType(pszEU);
+            if( poDS->nBands == 1 )
+            {
+                poDS->SetMetadataItem("ELEVATION_UNITS", pszEU);
+            }
+        }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check for dependent dataset value.                              */
-/* -------------------------------------------------------------------- */
-    HFAInfo_t *psInfo = (HFAInfo_t *) hHFA;
-    HFAEntry  *poEntry = psInfo->poRoot->GetNamedChild("DependentFile");
+    // Check for dependent dataset value.
+    HFAInfo_t *psInfo = hHFA;
+    HFAEntry *poEntry = psInfo->poRoot->GetNamedChild("DependentFile");
     if( poEntry != NULL )
     {
-        poDS->SetMetadataItem( "HFA_DEPENDENT_FILE",
-                               poEntry->GetStringField( "dependent.string" ),
-                               "HFA" );
+        poDS->SetMetadataItem("HFA_DEPENDENT_FILE",
+                              poEntry->GetStringField("dependent.string"),
+                              "HFA");
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    // Initialize any PAM information.
+    poDS->SetDescription(poOpenInfo->pszFilename);
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Check for external overviews.                                   */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    // Check for external overviews.
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
 
-/* -------------------------------------------------------------------- */
-/*      Clear dirty metadata flags.                                     */
-/* -------------------------------------------------------------------- */
+    // Clear dirty metadata flags.
     for( int i = 0; i < poDS->nBands; i++ )
     {
-        HFARasterBand *poBand = (HFARasterBand *) poDS->GetRasterBand( i+1 );
-        poBand->bMetadataDirty = FALSE;
+        HFARasterBand *poBand =
+            static_cast<HFARasterBand *>(poDS->GetRasterBand(i + 1));
+        poBand->bMetadataDirty = false;
     }
-    poDS->bMetadataDirty = FALSE;
+    poDS->bMetadataDirty = false;
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char *HFADataset::GetProjectionRef()
-
-{
-    return pszProjection;
-}
+const char *HFADataset::GetProjectionRef() { return pszProjection; }
 
 /************************************************************************/
 /*                           SetProjection()                            */
 /************************************************************************/
 
-CPLErr HFADataset::SetProjection( const char * pszNewProjection )
+CPLErr HFADataset::SetProjection( const char *pszNewProjection )
 
 {
-    CPLFree( pszProjection );
-    pszProjection = CPLStrdup( pszNewProjection );
-    bGeoDirty = TRUE;
+    CPLFree(pszProjection);
+    pszProjection = CPLStrdup(pszNewProjection);
+    bGeoDirty = true;
 
     return CE_None;
 }
@@ -5325,9 +5284,9 @@ CPLErr HFADataset::SetProjection( const char * pszNewProjection )
 CPLErr HFADataset::SetMetadata( char **papszMDIn, const char *pszDomain )
 
 {
-    bMetadataDirty = TRUE;
+    bMetadataDirty = true;
 
-    return GDALPamDataset::SetMetadata( papszMDIn, pszDomain );
+    return GDALPamDataset::SetMetadata(papszMDIn, pszDomain);
 }
 
 /************************************************************************/
@@ -5338,16 +5297,16 @@ CPLErr HFADataset::SetMetadataItem( const char *pszTag, const char *pszValue,
                                     const char *pszDomain )
 
 {
-    bMetadataDirty = TRUE;
+    bMetadataDirty = true;
 
-    return GDALPamDataset::SetMetadataItem( pszTag, pszValue, pszDomain );
+    return GDALPamDataset::SetMetadataItem(pszTag, pszValue, pszDomain);
 }
 
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr HFADataset::GetGeoTransform( double * padfTransform )
+CPLErr HFADataset::GetGeoTransform( double *padfTransform )
 
 {
     if( adfGeoTransform[0] != 0.0
@@ -5357,11 +5316,11 @@ CPLErr HFADataset::GetGeoTransform( double * padfTransform )
         || adfGeoTransform[4] != 0.0
         || adfGeoTransform[5] != 1.0 )
     {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
+        memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
         return CE_None;
     }
 
-    return GDALPamDataset::GetGeoTransform( padfTransform );
+    return GDALPamDataset::GetGeoTransform(padfTransform);
 }
 
 /************************************************************************/
@@ -5371,8 +5330,8 @@ CPLErr HFADataset::GetGeoTransform( double * padfTransform )
 CPLErr HFADataset::SetGeoTransform( double * padfTransform )
 
 {
-    memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
-    bGeoDirty = TRUE;
+    memcpy(adfGeoTransform, padfTransform, sizeof(double) * 6);
+    bGeoDirty = true;
 
     return CE_None;
 }
@@ -5394,20 +5353,22 @@ CPLErr HFADataset::IRasterIO( GDALRWFlag eRWFlag,
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg )
+                              GDALRasterIOExtraArg *psExtraArg )
 
 {
-    if( hHFA->papoBand[panBandMap[0]-1]->fpExternal != NULL
+    if( hHFA->papoBand[panBandMap[0] - 1]->fpExternal != NULL
         && nBandCount > 1 )
         return GDALDataset::BlockBasedRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
             pData, nBufXSize, nBufYSize, eBufType,
-            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
-
-    return GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                    pData, nBufXSize, nBufYSize, eBufType,
-                                    nBandCount, panBandMap,
-                                    nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
+            nBandCount, panBandMap,
+            nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
+
+    return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                  pData, nBufXSize, nBufYSize, eBufType,
+                                  nBandCount, panBandMap,
+                                  nPixelSpace, nLineSpace, nBandSpace,
+                                  psExtraArg);
 }
 
 /************************************************************************/
@@ -5419,19 +5380,17 @@ void HFADataset::UseXFormStack( int nStepCount,
                                 Efga_Polynomial *pasPLReverse )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Generate GCPs using the transform.                              */
-/* -------------------------------------------------------------------- */
+    // Generate GCPs using the transform.
     nGCPCount = 0;
-    GDALInitGCPs( 36, asGCPList );
+    GDALInitGCPs(36, asGCPList);
 
     for( double dfYRatio = 0.0; dfYRatio < 1.001; dfYRatio += 0.2 )
     {
         for( double dfXRatio = 0.0; dfXRatio < 1.001; dfXRatio += 0.2 )
         {
-            double dfLine = 0.5 + (GetRasterYSize()-1) * dfYRatio;
-            double dfPixel = 0.5 + (GetRasterXSize()-1) * dfXRatio;
-            int iGCP = nGCPCount;
+            const double dfLine = 0.5 + (GetRasterYSize() - 1) * dfYRatio;
+            const double dfPixel = 0.5 + (GetRasterXSize() - 1) * dfXRatio;
+            const int iGCP = nGCPCount;
 
             asGCPList[iGCP].dfGCPPixel = dfPixel;
             asGCPList[iGCP].dfGCPLine = dfLine;
@@ -5440,27 +5399,22 @@ void HFADataset::UseXFormStack( int nStepCount,
             asGCPList[iGCP].dfGCPY = dfLine;
             asGCPList[iGCP].dfGCPZ = 0.0;
 
-            if( HFAEvaluateXFormStack( nStepCount, FALSE, pasPLReverse,
-                                       &(asGCPList[iGCP].dfGCPX),
-                                       &(asGCPList[iGCP].dfGCPY) ) )
+            if( HFAEvaluateXFormStack(nStepCount, FALSE, pasPLReverse,
+                                      &(asGCPList[iGCP].dfGCPX),
+                                      &(asGCPList[iGCP].dfGCPY)) )
                 nGCPCount++;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Store the transform as metadata.                                */
-/* -------------------------------------------------------------------- */
+    // Store the transform as metadata.
     GDALMajorObject::SetMetadataItem(
-        "XFORM_STEPS",
-        CPLString().Printf("%d",nStepCount),
-        "XFORMS" );
+        "XFORM_STEPS", CPLString().Printf("%d", nStepCount), "XFORMS");
 
     for( int iStep = 0; iStep < nStepCount; iStep++ )
     {
         GDALMajorObject::SetMetadataItem(
             CPLString().Printf("XFORM%d_ORDER", iStep),
-            CPLString().Printf("%d",pasPLForward[iStep].order),
-            "XFORMS" );
+            CPLString().Printf("%d", pasPLForward[iStep].order), "XFORMS");
 
         if( pasPLForward[iStep].order == 1 )
         {
@@ -5469,55 +5423,51 @@ void HFADataset::UseXFormStack( int nStepCount,
                     CPLString().Printf("XFORM%d_POLYCOEFMTX[%d]", iStep, i),
                     CPLString().Printf("%.15g",
                                        pasPLForward[iStep].polycoefmtx[i]),
-                    "XFORMS" );
+                    "XFORMS");
 
             for( int i = 0; i < 2; i++ )
                 GDALMajorObject::SetMetadataItem(
                     CPLString().Printf("XFORM%d_POLYCOEFVECTOR[%d]", iStep, i),
                     CPLString().Printf("%.15g",
                                        pasPLForward[iStep].polycoefvector[i]),
-                    "XFORMS" );
+                    "XFORMS");
 
             continue;
         }
 
-        int nCoefCount;
+        int nCoefCount = 10;
 
-        if( pasPLForward[iStep].order == 2 )
-            nCoefCount = 10;
-        else
+        if( pasPLForward[iStep].order != 2 )
         {
-            CPLAssert( pasPLForward[iStep].order == 3 );
+            CPLAssert(pasPLForward[iStep].order == 3);
             nCoefCount = 18;
         }
 
         for( int i = 0; i < nCoefCount; i++ )
             GDALMajorObject::SetMetadataItem(
                 CPLString().Printf("XFORM%d_FWD_POLYCOEFMTX[%d]", iStep, i),
-                CPLString().Printf("%.15g",
-                                   pasPLForward[iStep].polycoefmtx[i]),
-                "XFORMS" );
+                CPLString().Printf("%.15g", pasPLForward[iStep].polycoefmtx[i]),
+                "XFORMS");
 
         for( int i = 0; i < 2; i++ )
             GDALMajorObject::SetMetadataItem(
                 CPLString().Printf("XFORM%d_FWD_POLYCOEFVECTOR[%d]", iStep, i),
                 CPLString().Printf("%.15g",
                                    pasPLForward[iStep].polycoefvector[i]),
-                "XFORMS" );
+                "XFORMS");
 
         for( int i = 0; i < nCoefCount; i++ )
             GDALMajorObject::SetMetadataItem(
                 CPLString().Printf("XFORM%d_REV_POLYCOEFMTX[%d]", iStep, i),
-                CPLString().Printf("%.15g",
-                                   pasPLReverse[iStep].polycoefmtx[i]),
-                "XFORMS" );
+                CPLString().Printf("%.15g", pasPLReverse[iStep].polycoefmtx[i]),
+                "XFORMS");
 
         for( int i = 0; i < 2; i++ )
             GDALMajorObject::SetMetadataItem(
                 CPLString().Printf("XFORM%d_REV_POLYCOEFVECTOR[%d]", iStep, i),
                 CPLString().Printf("%.15g",
                                    pasPLReverse[iStep].polycoefvector[i]),
-                "XFORMS" );
+                "XFORMS");
     }
 }
 
@@ -5525,11 +5475,7 @@ void HFADataset::UseXFormStack( int nStepCount,
 /*                            GetGCPCount()                             */
 /************************************************************************/
 
-int HFADataset::GetGCPCount()
-
-{
-    return nGCPCount;
-}
+int HFADataset::GetGCPCount() { return nGCPCount; }
 
 /************************************************************************/
 /*                          GetGCPProjection()                          */
@@ -5548,11 +5494,7 @@ const char *HFADataset::GetGCPProjection()
 /*                               GetGCPs()                              */
 /************************************************************************/
 
-const GDAL_GCP *HFADataset::GetGCPs()
-
-{
-    return asGCPList;
-}
+const GDAL_GCP *HFADataset::GetGCPs() { return asGCPList; }
 
 /************************************************************************/
 /*                            GetFileList()                             */
@@ -5563,30 +5505,26 @@ char **HFADataset::GetFileList()
 {
     char **papszFileList = GDALPamDataset::GetFileList();
 
-    if( HFAGetIGEFilename( hHFA ) != NULL )
+    if( HFAGetIGEFilename(hHFA) != NULL )
     {
-        papszFileList = CSLAddString( papszFileList,
-                                      HFAGetIGEFilename( hHFA ) );
+        papszFileList = CSLAddString(papszFileList, HFAGetIGEFilename(hHFA));
     }
 
-    // Request an overview to force opening of dependent overview
-    // files.
-    if( nBands > 0
-        && GetRasterBand(1)->GetOverviewCount() > 0 )
+    // Request an overview to force opening of dependent overview files.
+    if( nBands > 0 && GetRasterBand(1)->GetOverviewCount() > 0 )
         GetRasterBand(1)->GetOverview(0);
 
     if( hHFA->psDependent != NULL )
     {
         HFAInfo_t *psDep = hHFA->psDependent;
 
-        papszFileList =
-            CSLAddString( papszFileList,
-                          CPLFormFilename( psDep->pszPath,
-                                           psDep->pszFilename, NULL ));
+        papszFileList = CSLAddString(
+            papszFileList,
+            CPLFormFilename(psDep->pszPath, psDep->pszFilename, NULL));
 
-        if( HFAGetIGEFilename( psDep ) != NULL )
-            papszFileList = CSLAddString( papszFileList,
-                                          HFAGetIGEFilename( psDep ) );
+        if( HFAGetIGEFilename(psDep) != NULL )
+            papszFileList =
+                CSLAddString(papszFileList, HFAGetIGEFilename(psDep));
     }
 
     return papszFileList;
@@ -5602,117 +5540,105 @@ GDALDataset *HFADataset::Create( const char * pszFilenameIn,
                                  char ** papszParmList )
 
 {
-    int         nBits = 0;
+    const int nBits =
+        CSLFetchNameValue(papszParmList, "NBITS") != NULL
+        ? atoi(CSLFetchNameValue(papszParmList, "NBITS"))
+        : 0;
 
-    if( CSLFetchNameValue( papszParmList, "NBITS" ) != NULL )
-        nBits = atoi(CSLFetchNameValue(papszParmList,"NBITS"));
-
-    const char *pszPixelType
-        = CSLFetchNameValue( papszParmList, "PIXELTYPE" );
+    const char *pszPixelType =
+        CSLFetchNameValue(papszParmList, "PIXELTYPE");
     if( pszPixelType == NULL )
         pszPixelType = "";
 
-/* -------------------------------------------------------------------- */
-/*      Translate the data type.                                        */
-/* -------------------------------------------------------------------- */
-    EPTType	eHfaDataType;
+    // Translate the data type.
+    EPTType eHfaDataType;
     switch( eType )
     {
-      case GDT_Byte:
+    case GDT_Byte:
         if( nBits == 1 )
             eHfaDataType = EPT_u1;
         else if( nBits == 2 )
             eHfaDataType = EPT_u2;
         else if( nBits == 4 )
             eHfaDataType = EPT_u4;
-        else if( EQUAL(pszPixelType,"SIGNEDBYTE") )
+        else if( EQUAL(pszPixelType, "SIGNEDBYTE") )
             eHfaDataType = EPT_s8;
         else
             eHfaDataType = EPT_u8;
         break;
 
-      case GDT_UInt16:
+    case GDT_UInt16:
         eHfaDataType = EPT_u16;
         break;
 
-      case GDT_Int16:
+    case GDT_Int16:
         eHfaDataType = EPT_s16;
         break;
 
-      case GDT_Int32:
+    case GDT_Int32:
         eHfaDataType = EPT_s32;
         break;
 
-      case GDT_UInt32:
+    case GDT_UInt32:
         eHfaDataType = EPT_u32;
         break;
 
-      case GDT_Float32:
+    case GDT_Float32:
         eHfaDataType = EPT_f32;
         break;
 
-      case GDT_Float64:
+    case GDT_Float64:
         eHfaDataType = EPT_f64;
         break;
 
-      case GDT_CFloat32:
+    case GDT_CFloat32:
         eHfaDataType = EPT_c64;
         break;
 
-      case GDT_CFloat64:
+    case GDT_CFloat64:
         eHfaDataType = EPT_c128;
         break;
 
-      default:
-        CPLError( CE_Failure, CPLE_NotSupported,
-                 "Data type %s not supported by Erdas Imagine (HFA) format.\n",
-                  GDALGetDataTypeName( eType ) );
+    default:
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Data type %s not supported by Erdas Imagine (HFA) format.",
+                 GDALGetDataTypeName(eType));
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the new file.                                            */
-/* -------------------------------------------------------------------- */
-    HFAHandle hHFA = HFACreate( pszFilenameIn, nXSize, nYSize, nBands,
-                                eHfaDataType, papszParmList );
+    // Create the new file.
+    HFAHandle hHFA = HFACreate(pszFilenameIn, nXSize, nYSize, nBands,
+                                eHfaDataType, papszParmList);
     if( hHFA == NULL )
         return NULL;
 
-    if( HFAClose( hHFA ) != 0 )
+    if( HFAClose(hHFA) != 0 )
     {
         CPLError(CE_Failure, CPLE_FileIO, "I/O error");
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Open the dataset normally.                                      */
-/* -------------------------------------------------------------------- */
-    HFADataset *poDS = (HFADataset *) GDALOpen( pszFilenameIn, GA_Update );
+    // Open the dataset normally.
+    HFADataset *poDS = (HFADataset *)GDALOpen(pszFilenameIn, GA_Update);
 
-/* -------------------------------------------------------------------- */
-/*      Special creation option to disable checking for UTM             */
-/*      parameters when writing the projection.  This is a special      */
-/*      hack for sam.gillingham at nrm.qld.gov.au.                         */
-/* -------------------------------------------------------------------- */
+    // Special creation option to disable checking for UTM
+    // parameters when writing the projection.  This is a special
+    // hack for sam.gillingham at nrm.qld.gov.au.
     if( poDS != NULL )
     {
-        poDS->bIgnoreUTM = CSLFetchBoolean( papszParmList, "IGNOREUTM",
-                                            FALSE );
+        poDS->bIgnoreUTM = CPLFetchBool(papszParmList, "IGNOREUTM", false);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Sometimes we can improve ArcGIS compatibility by forcing        */
-/*      generation of a PEString instead of traditional Imagine         */
-/*      coordinate system descriptions.                                 */
-/* -------------------------------------------------------------------- */
+    // Sometimes we can improve ArcGIS compatibility by forcing
+    // generation of a PEString instead of traditional Imagine
+    // coordinate system descriptions.
     if( poDS != NULL )
     {
         poDS->bForceToPEString =
-            CSLFetchBoolean( papszParmList, "FORCETOPESTRING", FALSE );
+            CPLFetchBool(papszParmList, "FORCETOPESTRING", false);
     }
 
     return poDS;
-
 }
 
 /************************************************************************/
@@ -5725,37 +5651,30 @@ GDALDataset *HFADataset::Create( const char * pszFilenameIn,
 CPLErr HFADataset::Rename( const char *pszNewName, const char *pszOldName )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Rename all the files at the filesystem level.                   */
-/* -------------------------------------------------------------------- */
-    GDALDriver *poDriver = (GDALDriver*) GDALGetDriverByName( "HFA" );
-
-    CPLErr eErr = poDriver->DefaultRename( pszNewName, pszOldName );
+    // Rename all the files at the filesystem level.
+    CPLErr eErr = GDALDriver::DefaultRename(pszNewName, pszOldName);
     if( eErr != CE_None )
         return eErr;
 
-/* -------------------------------------------------------------------- */
-/*      Now try to go into the .img file and update RRDNames[]          */
-/*      lists.                                                          */
-/* -------------------------------------------------------------------- */
-    CPLString osOldBasename = CPLGetBasename( pszOldName );
-    CPLString osNewBasename = CPLGetBasename( pszNewName );
+    // Now try to go into the .img file and update RRDNames[] lists.
+    CPLString osOldBasename = CPLGetBasename(pszOldName);
+    CPLString osNewBasename = CPLGetBasename(pszNewName);
 
     if( osOldBasename != osNewBasename )
     {
-        HFAHandle hHFA = HFAOpen( pszNewName, "r+" );
+        HFAHandle hHFA = HFAOpen(pszNewName, "r+");
 
         if( hHFA != NULL )
         {
-            eErr = HFARenameReferences( hHFA, osNewBasename, osOldBasename );
+            eErr = HFARenameReferences(hHFA, osNewBasename, osOldBasename);
 
-            HFAGetOverviewCount( hHFA, 1 );
+            HFAGetOverviewCount(hHFA, 1);
 
             if( hHFA->psDependent != NULL )
-                HFARenameReferences( hHFA->psDependent,
-                                     osNewBasename, osOldBasename );
+                HFARenameReferences(hHFA->psDependent,
+                                    osNewBasename, osOldBasename);
 
-            if( HFAClose( hHFA ) != 0 )
+            if( HFAClose(hHFA) != 0 )
                 eErr = CE_Failure;
         }
     }
@@ -5773,38 +5692,31 @@ CPLErr HFADataset::Rename( const char *pszNewName, const char *pszOldName )
 CPLErr HFADataset::CopyFiles( const char *pszNewName, const char *pszOldName )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Rename all the files at the filesystem level.                   */
-/* -------------------------------------------------------------------- */
-    GDALDriver *poDriver = (GDALDriver*) GDALGetDriverByName( "HFA" );
-
-    CPLErr eErr = poDriver->DefaultCopyFiles( pszNewName, pszOldName );
+    // Rename all the files at the filesystem level.
+    CPLErr eErr = GDALDriver::DefaultCopyFiles(pszNewName, pszOldName);
 
     if( eErr != CE_None )
         return eErr;
 
-/* -------------------------------------------------------------------- */
-/*      Now try to go into the .img file and update RRDNames[]          */
-/*      lists.                                                          */
-/* -------------------------------------------------------------------- */
-    CPLString osOldBasename = CPLGetBasename( pszOldName );
-    CPLString osNewBasename = CPLGetBasename( pszNewName );
+    // Now try to go into the .img file and update RRDNames[] lists.
+    CPLString osOldBasename = CPLGetBasename(pszOldName);
+    CPLString osNewBasename = CPLGetBasename(pszNewName);
 
     if( osOldBasename != osNewBasename )
     {
-        HFAHandle hHFA = HFAOpen( pszNewName, "r+" );
+        HFAHandle hHFA = HFAOpen(pszNewName, "r+");
 
         if( hHFA != NULL )
         {
-            eErr = HFARenameReferences( hHFA, osNewBasename, osOldBasename );
+            eErr = HFARenameReferences(hHFA, osNewBasename, osOldBasename);
 
-            HFAGetOverviewCount( hHFA, 1 );
+            HFAGetOverviewCount(hHFA, 1);
 
             if( hHFA->psDependent != NULL )
-                HFARenameReferences( hHFA->psDependent,
-                                     osNewBasename, osOldBasename );
+                HFARenameReferences(hHFA->psDependent,
+                                    osNewBasename, osOldBasename);
 
-            if( HFAClose( hHFA ) != 0 )
+            if( HFAClose(hHFA) != 0 )
                 eErr = CE_Failure;
         }
     }
@@ -5817,21 +5729,17 @@ CPLErr HFADataset::CopyFiles( const char *pszNewName, const char *pszOldName )
 /************************************************************************/
 
 GDALDataset *
-HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
-                        CPL_UNUSED int bStrict,
-                        char ** papszOptions,
-                        GDALProgressFunc pfnProgress, void * pProgressData )
+HFADataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS,
+                        int /* bStrict */,
+                        char **papszOptions,
+                        GDALProgressFunc pfnProgress, void *pProgressData )
 {
-/* -------------------------------------------------------------------- */
-/*      Do we really just want to create an .aux file?                  */
-/* -------------------------------------------------------------------- */
-    bool bCreateAux = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "AUX", FALSE ));
+    // Do we really just want to create an .aux file?
+    const bool bCreateAux = CPLFetchBool(papszOptions, "AUX", false);
 
-/* -------------------------------------------------------------------- */
-/*      Establish a representative data type to use.                    */
-/* -------------------------------------------------------------------- */
-    char **papszModOptions = CSLDuplicate( papszOptions );
-    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    // Establish a representative data type to use.
+    char **papszModOptions = CSLDuplicate(papszOptions);
+    if( !pfnProgress(0.0, NULL, pProgressData) )
     {
         CSLDestroy(papszModOptions);
         return NULL;
@@ -5842,103 +5750,87 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
-        GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
-        eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
+        GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand+1);
+        eType = GDALDataTypeUnion(eType, poBand->GetRasterDataType());
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we have PIXELTYPE metadata in the source, pass it            */
-/*      through as a creation option.                                   */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL
-        && nBandCount > 0
-        && eType == GDT_Byte
-        && poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE",
-                                                       "IMAGE_STRUCTURE" ) )
+    // If we have PIXELTYPE metadata in the source, pass it
+    // through as a creation option.
+    if( CSLFetchNameValue(papszOptions, "PIXELTYPE") == NULL &&
+        nBandCount > 0 &&
+        eType == GDT_Byte &&
+        poSrcDS->GetRasterBand(1)->GetMetadataItem("PIXELTYPE",
+                                                   "IMAGE_STRUCTURE") )
     {
         papszModOptions =
-            CSLSetNameValue( papszModOptions, "PIXELTYPE",
-                             poSrcDS->GetRasterBand(1)->GetMetadataItem(
-                                 "PIXELTYPE", "IMAGE_STRUCTURE" ) );
+            CSLSetNameValue(papszModOptions, "PIXELTYPE",
+                            poSrcDS->GetRasterBand(1)->GetMetadataItem(
+                                "PIXELTYPE", "IMAGE_STRUCTURE"));
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the file.                                                */
-/* -------------------------------------------------------------------- */
-    HFADataset *poDS
-        = (HFADataset *) Create( pszFilename,
-                                 poSrcDS->GetRasterXSize(),
-                                 poSrcDS->GetRasterYSize(),
-                                 nBandCount,
-                                 eType, papszModOptions );
+    HFADataset *poDS =
+        (HFADataset *)Create(pszFilename,
+                             poSrcDS->GetRasterXSize(),
+                             poSrcDS->GetRasterYSize(),
+                             nBandCount,
+                             eType, papszModOptions);
 
-    CSLDestroy( papszModOptions );
+    CSLDestroy(papszModOptions);
 
     if( poDS == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Does the source have a PCT for any of the bands?  If so,        */
-/*      copy it over.                                                   */
-/* -------------------------------------------------------------------- */
+    // Does the source have a PCT for any of the bands?  If so, copy it over.
     for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
-        GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
+        GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1);
         GDALColorTable *poCT = poBand->GetColorTable();
         if( poCT != NULL )
         {
-            poDS->GetRasterBand(iBand+1)->SetColorTable(poCT);
+            poDS->GetRasterBand(iBand + 1)->SetColorTable(poCT);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we have metadata for any of the bands or the dataset as a    */
-/*      whole?                                                          */
-/* -------------------------------------------------------------------- */
+    // Do we have metadata for any of the bands or the dataset as a whole?
     if( poSrcDS->GetMetadata() != NULL )
-        poDS->SetMetadata( poSrcDS->GetMetadata() );
+        poDS->SetMetadata(poSrcDS->GetMetadata());
 
     for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
-        GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
-        GDALRasterBand *poDstBand = poDS->GetRasterBand(iBand+1);
+        GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(iBand + 1);
+        GDALRasterBand *poDstBand = poDS->GetRasterBand(iBand + 1);
 
         if( poSrcBand->GetMetadata() != NULL )
-            poDstBand->SetMetadata( poSrcBand->GetMetadata() );
+            poDstBand->SetMetadata(poSrcBand->GetMetadata());
 
         if( strlen(poSrcBand->GetDescription()) > 0 )
-            poDstBand->SetDescription( poSrcBand->GetDescription() );
+            poDstBand->SetDescription(poSrcBand->GetDescription());
 
-        int bSuccess;
-        double dfNoDataValue = poSrcBand->GetNoDataValue( &bSuccess );
+        int bSuccess = FALSE;
+        const double dfNoDataValue = poSrcBand->GetNoDataValue(&bSuccess);
         if( bSuccess )
-            poDstBand->SetNoDataValue( dfNoDataValue );
+            poDstBand->SetNoDataValue(dfNoDataValue);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Copy projection information.                                    */
-/* -------------------------------------------------------------------- */
-    double	adfGeoTransform[6];
+    // Copy projection information.
+    double adfGeoTransform[6] = {};
 
-    if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
-        && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
-            || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
-            || adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0))
-        poDS->SetGeoTransform( adfGeoTransform );
+    if( poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None &&
+        (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0 ||
+         adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0 ||
+         adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0) )
+        poDS->SetGeoTransform(adfGeoTransform);
 
     const char *pszProj = poSrcDS->GetProjectionRef();
     if( pszProj != NULL && strlen(pszProj) > 0 )
-        poDS->SetProjection( pszProj );
+        poDS->SetProjection(pszProj);
 
-/* -------------------------------------------------------------------- */
-/*      Copy the imagery.                                               */
-/* -------------------------------------------------------------------- */
+    // Copy the imagery.
     if( !bCreateAux )
     {
-        CPLErr eErr
-            = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
-                                          (GDALDatasetH) poDS,
-                                          NULL, pfnProgress, pProgressData );
+        const CPLErr eErr = GDALDatasetCopyWholeRaster(
+            (GDALDatasetH)poSrcDS, (GDALDatasetH)poDS, NULL, pfnProgress,
+            pProgressData);
 
         if( eErr != CE_None )
         {
@@ -5947,111 +5839,101 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we want to generate statistics and a histogram?              */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchBoolean( papszOptions, "STATISTICS", FALSE ) )
+    // Do we want to generate statistics and a histogram?
+    if( CPLFetchBool(papszOptions, "STATISTICS", false) )
     {
         for( int iBand = 0; iBand < nBandCount; iBand++ )
         {
-            GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
-            double dfMin, dfMax, dfMean, dfStdDev;
+            GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(iBand + 1);
+            double dfMin = 0.0;
+            double dfMax = 0.0;
+            double dfMean = 0.0;
+            double dfStdDev = 0.0;
             char **papszStatsMD = NULL;
 
-            // -----------------------------------------------------------
             // Statistics
-            // -----------------------------------------------------------
-
-            if( poSrcBand->GetStatistics( TRUE, FALSE, &dfMin, &dfMax,
-                                          &dfMean, &dfStdDev ) == CE_None
-                || poSrcBand->ComputeStatistics( TRUE, &dfMin, &dfMax,
-                                                 &dfMean, &dfStdDev,
-                                                 pfnProgress, pProgressData )
-                == CE_None )
+            if( poSrcBand->GetStatistics(TRUE, FALSE, &dfMin, &dfMax, &dfMean,
+                                         &dfStdDev) == CE_None ||
+                poSrcBand->ComputeStatistics(TRUE, &dfMin, &dfMax, &dfMean,
+                                             &dfStdDev, pfnProgress,
+                                             pProgressData) == CE_None )
             {
                 CPLString osValue;
 
                 papszStatsMD =
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_MINIMUM",
-                                     osValue.Printf( "%.15g", dfMin ) );
-                papszStatsMD =
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_MAXIMUM",
-                                     osValue.Printf( "%.15g", dfMax ) );
+                    CSLSetNameValue(papszStatsMD, "STATISTICS_MINIMUM",
+                                    osValue.Printf("%.15g", dfMin));
                 papszStatsMD =
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_MEAN",
-                                     osValue.Printf( "%.15g", dfMean ) );
+                    CSLSetNameValue(papszStatsMD, "STATISTICS_MAXIMUM",
+                                    osValue.Printf("%.15g", dfMax));
+                papszStatsMD = CSLSetNameValue(papszStatsMD, "STATISTICS_MEAN",
+                                               osValue.Printf("%.15g", dfMean));
                 papszStatsMD =
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_STDDEV",
-                                     osValue.Printf( "%.15g", dfStdDev ) );
+                    CSLSetNameValue(papszStatsMD, "STATISTICS_STDDEV",
+                                    osValue.Printf("%.15g", dfStdDev));
             }
 
-            // -----------------------------------------------------------
             // Histogram
-            // -----------------------------------------------------------
-
-            int nBuckets;
+            int nBuckets = 0;
             GUIntBig *panHistogram = NULL;
 
-            if( poSrcBand->GetDefaultHistogram( &dfMin, &dfMax,
-                                                &nBuckets, &panHistogram,
-                                                TRUE,
-                                                pfnProgress, pProgressData )
+            if( poSrcBand->GetDefaultHistogram(&dfMin, &dfMax,
+                                               &nBuckets, &panHistogram,
+                                               TRUE,
+                                               pfnProgress, pProgressData)
                 == CE_None )
             {
                 CPLString osValue;
-                double dfBinWidth = (dfMax - dfMin) / nBuckets;
+                const double dfBinWidth = (dfMax - dfMin) / nBuckets;
 
                 papszStatsMD = CSLSetNameValue(
                     papszStatsMD, "STATISTICS_HISTOMIN",
-                    osValue.Printf( "%.15g", dfMin+dfBinWidth*0.5 ) );
+                    osValue.Printf("%.15g", dfMin + dfBinWidth * 0.5));
                 papszStatsMD = CSLSetNameValue(
                     papszStatsMD, "STATISTICS_HISTOMAX",
-                    osValue.Printf( "%.15g", dfMax-dfBinWidth*0.5 ) );
+                    osValue.Printf("%.15g", dfMax - dfBinWidth * 0.5));
                 papszStatsMD =
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_HISTONUMBINS",
-                                     osValue.Printf( "%d", nBuckets ) );
+                    CSLSetNameValue(papszStatsMD, "STATISTICS_HISTONUMBINS",
+                                    osValue.Printf("%d", nBuckets));
 
                 int nBinValuesLen = 0;
-                char *pszBinValues = (char *) CPLCalloc(20, nBuckets+1);
+                char *pszBinValues =
+                    static_cast<char *>(CPLCalloc(20, nBuckets + 1));
                 for( int iBin = 0; iBin < nBuckets; iBin++ )
                 {
 
-                    strcat( pszBinValues+nBinValuesLen,
-                            osValue.Printf( CPL_FRMT_GUIB, panHistogram[iBin]) );
-                    strcat( pszBinValues+nBinValuesLen, "|" );
-                    nBinValuesLen += static_cast<int>(strlen(pszBinValues+nBinValuesLen));
+                    strcat(pszBinValues + nBinValuesLen,
+                           osValue.Printf(CPL_FRMT_GUIB, panHistogram[iBin]));
+                    strcat(pszBinValues + nBinValuesLen, "|");
+                    nBinValuesLen +=
+                        static_cast<int>(strlen(pszBinValues + nBinValuesLen));
                 }
-                papszStatsMD =
-                    CSLSetNameValue( papszStatsMD, "STATISTICS_HISTOBINVALUES",
-                                     pszBinValues );
-                CPLFree( pszBinValues );
+                papszStatsMD = CSLSetNameValue(
+                    papszStatsMD, "STATISTICS_HISTOBINVALUES", pszBinValues);
+                CPLFree(pszBinValues);
             }
 
             CPLFree(panHistogram);
 
             if( CSLCount(papszStatsMD) > 0 )
-                HFASetMetadata( poDS->hHFA, iBand+1, papszStatsMD );
+                HFASetMetadata(poDS->hHFA, iBand + 1, papszStatsMD);
 
-            CSLDestroy( papszStatsMD );
+            CSLDestroy(papszStatsMD);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      All report completion.                                          */
-/* -------------------------------------------------------------------- */
-    if( !pfnProgress( 1.0, NULL, pProgressData ) )
+    // All report completion.
+    if( !pfnProgress(1.0, NULL, pProgressData) )
     {
-        CPLError( CE_Failure, CPLE_UserInterrupt,
-                  "User terminated" );
+        CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
         delete poDS;
 
-        GDALDriver *poHFADriver =
-            (GDALDriver *) GDALGetDriverByName( "HFA" );
-        poHFADriver->Delete( pszFilename );
+        GDALDriver *poHFADriver = (GDALDriver *)GDALGetDriverByName("HFA");
+        poHFADriver->Delete(pszFilename);
         return NULL;
     }
 
-    poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+    poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT);
 
     return poDS;
 }
@@ -6063,21 +5945,21 @@ HFADataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_HFA()
 
 {
-    if( GDALGetDriverByName( "HFA" ) != NULL )
+    if( GDALGetDriverByName("HFA") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "HFA" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                               "Erdas Imagine Images (.img)" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_hfa.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "img" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                               "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CFloat32 CFloat64" );
+    poDriver->SetDescription("HFA");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Erdas Imagine Images (.img)");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_hfa.html");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "img");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
+                              "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 "
+                              "CFloat32 CFloat64");
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='BLOCKSIZE' type='integer' description='tile width/height (32-2048)' default='64'/>"
 "   <Option name='USE_SPILL' type='boolean' description='Force use of spill file'/>"
@@ -6089,9 +5971,9 @@ void GDALRegister_HFA()
 "   <Option name='STATISTICS' type='boolean' description='Generate statistics and a histogram'/>"
 "   <Option name='DEPENDENT_FILE' type='string' description='Name of dependent file (must not have absolute path)'/>"
 "   <Option name='FORCETOPESTRING' type='boolean' description='Force use of ArcGIS PE String in file instead of Imagine coordinate system format'/>"
-"</CreationOptionList>" );
+"</CreationOptionList>");
 
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
 
     poDriver->pfnOpen = HFADataset::Open;
     poDriver->pfnCreate = HFADataset::Create;
@@ -6100,5 +5982,5 @@ void GDALRegister_HFA()
     poDriver->pfnRename = HFADataset::Rename;
     poDriver->pfnCopyFiles = HFADataset::CopyFiles;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/hfa/hfadataset.h b/frmts/hfa/hfadataset.h
new file mode 100644
index 0000000..bf7213f
--- /dev/null
+++ b/frmts/hfa/hfadataset.h
@@ -0,0 +1,312 @@
+/******************************************************************************
+ *
+ * Name:     hfadataset.cpp
+ * Project:  Erdas Imagine Driver
+ * Purpose:  Main driver for Erdas Imagine format.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef HFADATASET_H_INCLUDED
+#define HFADATASET_H_INCLUDED
+
+#include <cstddef>
+#include <vector>
+
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_rat.h"
+#include "hfa_p.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              HFADataset                              */
+/* ==================================================================== */
+/************************************************************************/
+
+class HFARasterBand;
+
+class HFADataset CPL_FINAL : public GDALPamDataset
+{
+    friend class HFARasterBand;
+
+    HFAHandle   hHFA;
+
+    bool        bMetadataDirty;
+
+    bool        bGeoDirty;
+    double      adfGeoTransform[6];
+    char        *pszProjection;
+
+    bool        bIgnoreUTM;
+
+    CPLErr      ReadProjection();
+    CPLErr      WriteProjection();
+    bool        bForceToPEString;
+
+    int         nGCPCount;
+    GDAL_GCP    asGCPList[36];
+
+    void        UseXFormStack( int nStepCount,
+                               Efga_Polynomial *pasPolyListForward,
+                               Efga_Polynomial *pasPolyListReverse );
+
+  protected:
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+                              int, int *,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GSpacing nBandSpace,
+                              GDALRasterIOExtraArg* psExtraArg ) override;
+
+  public:
+             HFADataset();
+    virtual ~HFADataset();
+
+    static int          Identify( GDALOpenInfo * );
+    static CPLErr       Rename( const char *pszNewName,
+                                const char *pszOldName );
+    static CPLErr       CopyFiles( const char *pszNewName,
+                                   const char *pszOldName );
+    static GDALDataset *Open( GDALOpenInfo * );
+    static GDALDataset *Create( const char * pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType, char ** papszParmList );
+    static GDALDataset *CreateCopy( const char * pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData );
+    static CPLErr       Delete( const char *pszFilename );
+
+    virtual char **GetFileList() override;
+
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr SetProjection( const char * ) override;
+
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
+
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
+
+    virtual CPLErr SetMetadata( char **, const char * = "" ) override;
+    virtual CPLErr SetMetadataItem( const char *, const char *,
+                                    const char * = "" ) override;
+
+    virtual void   FlushCache() override;
+    virtual CPLErr IBuildOverviews( const char *pszResampling,
+                                    int nOverviews, int *panOverviewList,
+                                    int nListBands, int *panBandList,
+                                    GDALProgressFunc pfnProgress,
+                                    void * pProgressData ) override;
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            HFARasterBand                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class HFARasterBand CPL_FINAL : public GDALPamRasterBand
+{
+    friend class HFADataset;
+    friend class HFARasterAttributeTable;
+
+    GDALColorTable *poCT;
+
+    EPTType     eHFADataType;
+
+    int         nOverviews;
+    int         nThisOverview;
+    HFARasterBand **papoOverviewBands;
+
+    CPLErr      CleanOverviews();
+
+    HFAHandle   hHFA;
+
+    bool        bMetadataDirty;
+
+    GDALRasterAttributeTable *poDefaultRAT;
+
+    void        ReadAuxMetadata();
+    void        ReadHistogramMetadata();
+    void        EstablishOverviews();
+    CPLErr      WriteNamedRAT( const char *pszName,
+                               const GDALRasterAttributeTable *poRAT );
+
+  public:
+                   HFARasterBand( HFADataset *, int, int );
+    virtual        ~HFARasterBand();
+
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
+
+    virtual const char *GetDescription() const override;
+    virtual void        SetDescription( const char * ) override;
+
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual CPLErr          SetColorTable( GDALColorTable * ) override;
+    virtual int    GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview( int ) override;
+
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum( int *pbSuccess = NULL ) override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual CPLErr SetNoDataValue( double dfValue ) override;
+
+    virtual CPLErr SetMetadata( char **, const char * = "" ) override;
+    virtual CPLErr SetMetadataItem( const char *, const char *,
+                                    const char * = "" ) override;
+    virtual CPLErr BuildOverviews( const char *, int, int *,
+                                   GDALProgressFunc, void * ) override;
+
+    virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
+                                        int *pnBuckets,
+                                        GUIntBig ** ppanHistogram,
+                                        int bForce,
+                                        GDALProgressFunc, void *pProgressData ) override;
+
+    virtual GDALRasterAttributeTable *GetDefaultRAT() override;
+    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * ) override;
+};
+
+class HFAAttributeField
+{
+  public:
+    CPLString         sName;
+    GDALRATFieldType  eType;
+    GDALRATFieldUsage eUsage;
+    int               nDataOffset;
+    int               nElementSize;
+    HFAEntry         *poColumn;
+    bool              bIsBinValues;  // Handled differently.
+    bool              bConvertColors;  // Map 0-1 floats to 0-255 ints.
+};
+
+class HFARasterAttributeTable CPL_FINAL : public GDALRasterAttributeTable
+{
+  private:
+    HFAHandle   hHFA;
+    HFAEntry   *poDT;
+    CPLString   osName;
+    int         nBand;
+    GDALAccess  eAccess;
+
+    std::vector<HFAAttributeField> aoFields;
+    int         nRows;
+
+    bool bLinearBinning;
+    double dfRow0Min;
+    double dfBinSize;
+
+    CPLString osWorkingResult;
+
+    void AddColumn( const char *pszName, GDALRATFieldType eType,
+                    GDALRATFieldUsage eUsage,
+                    int nDataOffset, int nElementSize, HFAEntry *poColumn,
+                    bool bIsBinValues=false,
+                    bool bConvertColors=false )
+    {
+        HFAAttributeField aField;
+        aField.sName = pszName;
+        aField.eType = eType;
+        aField.eUsage = eUsage;
+        aField.nDataOffset = nDataOffset;
+        aField.nElementSize = nElementSize;
+        aField.poColumn = poColumn;
+        aField.bIsBinValues = bIsBinValues;
+        aField.bConvertColors = bConvertColors;
+
+        aoFields.push_back(aField);
+    }
+
+    void CreateDT()
+    {
+        poDT = HFAEntry::New( hHFA->papoBand[nBand-1]->psInfo,
+                              osName, "Edsc_Table",
+                              hHFA->papoBand[nBand-1]->poNode );
+        poDT->SetIntField( "numrows", nRows );
+    }
+
+  public:
+    HFARasterAttributeTable( HFARasterBand *poBand, const char *pszName );
+    virtual ~HFARasterAttributeTable();
+
+    GDALDefaultRasterAttributeTable *Clone() const override;
+
+    virtual int           GetColumnCount() const override;
+
+    virtual const char   *GetNameOfCol( int ) const override;
+    virtual GDALRATFieldUsage GetUsageOfCol( int ) const override;
+    virtual GDALRATFieldType GetTypeOfCol( int ) const override;
+
+    virtual int           GetColOfUsage( GDALRATFieldUsage ) const override;
+
+    virtual int           GetRowCount() const override;
+
+    virtual const char   *GetValueAsString( int iRow, int iField ) const override;
+    virtual int           GetValueAsInt( int iRow, int iField ) const override;
+    virtual double        GetValueAsDouble( int iRow, int iField ) const override;
+
+    virtual void          SetValue( int iRow, int iField,
+                                    const char *pszValue ) override;
+    virtual void          SetValue( int iRow, int iField, double dfValue ) override;
+    virtual void          SetValue( int iRow, int iField, int nValue ) override;
+
+    virtual CPLErr        ValuesIO( GDALRWFlag eRWFlag, int iField,
+                                    int iStartRow, int iLength,
+                                    double *pdfData ) override;
+    virtual CPLErr        ValuesIO( GDALRWFlag eRWFlag, int iField,
+                                    int iStartRow, int iLength, int *pnData ) override;
+    virtual CPLErr        ValuesIO( GDALRWFlag eRWFlag, int iField,
+                                    int iStartRow, int iLength,
+                                    char **papszStrList ) override;
+
+    virtual int           ChangesAreWrittenToFile() override;
+    virtual void          SetRowCount( int iCount ) override;
+
+    virtual int           GetRowOfValue( double dfValue ) const override;
+    virtual int           GetRowOfValue( int nValue ) const override;
+
+    virtual CPLErr        CreateColumn( const char *pszFieldName,
+                                        GDALRATFieldType eFieldType,
+                                        GDALRATFieldUsage eFieldUsage ) override;
+    virtual CPLErr        SetLinearBinning( double dfRow0Min,
+                                            double dfBinSize ) override;
+    virtual int           GetLinearBinning( double *pdfRow0Min,
+                                            double *pdfBinSize ) const override;
+
+    virtual CPLXMLNode   *Serialize() const override;
+
+protected:
+    CPLErr                ColorsIO( GDALRWFlag eRWFlag, int iField,
+                                    int iStartRow, int iLength, int *pnData );
+};
+
+#endif  // HFADATASET_H_INCLUDED
diff --git a/frmts/hfa/hfadictionary.cpp b/frmts/hfa/hfadictionary.cpp
index cd67e10..59f712f 100644
--- a/frmts/hfa/hfadictionary.cpp
+++ b/frmts/hfa/hfadictionary.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfadictionary.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFADictionary class for managing the
@@ -29,13 +28,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "hfa_p.h"
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: hfadictionary.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: hfadictionary.cpp 37904 2017-04-05 17:19:53Z goatbar $");
 
 static const char * const apszDefDefn[] = {
-
     "Edsc_Table",
     "{1:lnumrows,}Edsc_Table",
 
@@ -83,40 +90,38 @@ static const char * const apszDefDefn[] = {
 
 /************************************************************************/
 /* ==================================================================== */
-/*	                       HFADictionary                            */
+/*                             HFADictionary                            */
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                           HFADictionary()                            */
 /************************************************************************/
 
-HFADictionary::HFADictionary( const char * pszString ) :
-    nTypes(0), nTypesMax(0), papoTypes(NULL), osDictionaryText(pszString),
-    bDictionaryTextDirty(FALSE)
+HFADictionary::HFADictionary( const char *pszString ) :
+    nTypes(0),
+    nTypesMax(0),
+    papoTypes(NULL),
+    osDictionaryText(pszString),
+    bDictionaryTextDirty(false)
 {
-
-/* -------------------------------------------------------------------- */
-/*      Read all the types.                                             */
-/* -------------------------------------------------------------------- */
+    // Read all the types.
+    // TODO(schwehr): Refactor this approach to be more obvious.
     while( pszString != NULL && *pszString != '.' )
     {
-        HFAType	*poNewType = new HFAType();
-        pszString = poNewType->Initialize( pszString );
+        HFAType *poNewType = new HFAType();
+        pszString = poNewType->Initialize(pszString);
 
         if( pszString != NULL )
-            AddType( poNewType );
+            AddType(poNewType);
         else
             delete poNewType;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Complete the definitions.                                       */
-/* -------------------------------------------------------------------- */
+    // Complete the definitions.
     for( int i = 0; i < nTypes; i++ )
     {
-        papoTypes[i]->CompleteDefn( this );
+        papoTypes[i]->CompleteDefn(this);
     }
 }
 
@@ -130,7 +135,7 @@ HFADictionary::~HFADictionary()
     for( int i = 0; i < nTypes; i++ )
         delete papoTypes[i];
 
-    CPLFree( papoTypes );
+    CPLFree(papoTypes);
 }
 
 /************************************************************************/
@@ -148,8 +153,8 @@ void HFADictionary::AddType( HFAType *poType )
         )
     {
         nTypesMax = nTypes * 2 + 10;
-        papoTypes = (HFAType **) CPLRealloc( papoTypes,
-                                             sizeof(void*) * nTypesMax );
+        papoTypes = static_cast<HFAType **>(
+            CPLRealloc(papoTypes, sizeof(void *) * nTypesMax));
     }
 
     papoTypes[nTypes++] = poType;
@@ -165,31 +170,29 @@ HFAType * HFADictionary::FindType( const char * pszName )
     for( int i = 0; i < nTypes; i++ )
     {
         if( papoTypes[i]->pszTypeName != NULL &&
-            strcmp(pszName,papoTypes[i]->pszTypeName) == 0 )
-            return( papoTypes[i] );
+            strcmp(pszName, papoTypes[i]->pszTypeName) == 0 )
+            return papoTypes[i];
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check if this is a type have other knowledge of.  If so, add    */
-/*      it to the dictionary now.  I'm not sure how some files end      */
-/*      up being distributed using types not in the dictionary.         */
-/* -------------------------------------------------------------------- */
+    // Check if this is a type have other knowledge of.  If so, add
+    // it to the dictionary now.  I'm not sure how some files end
+    // up being distributed using types not in the dictionary.
     for( int i = 0; apszDefDefn[i] != NULL; i += 2 )
     {
-        if( strcmp( pszName, apszDefDefn[i] ) == 0 )
+        if( strcmp(pszName, apszDefDefn[i]) == 0 )
         {
             HFAType *poNewType = new HFAType();
 
-            poNewType->Initialize( apszDefDefn[i+1] );
-            AddType( poNewType );
-            poNewType->CompleteDefn( this );
+            poNewType->Initialize(apszDefDefn[i + 1]);
+            AddType(poNewType);
+            poNewType->CompleteDefn(this);
 
-            if( osDictionaryText.size() > 0 )
-                osDictionaryText.erase( osDictionaryText.size() - 1, 1 );
-            osDictionaryText += apszDefDefn[i+1];
+            if( !osDictionaryText.empty() )
+                osDictionaryText.erase(osDictionaryText.size() - 1, 1);
+            osDictionaryText += apszDefDefn[i + 1];
             osDictionaryText += ",.";
 
-            bDictionaryTextDirty = TRUE;
+            bDictionaryTextDirty = true;
 
             return poNewType;
         }
@@ -209,40 +212,40 @@ int HFADictionary::GetItemSize( char chType )
 {
     switch( chType )
     {
-      case '1':
-      case '2':
-      case '4':
-      case 'c':
-      case 'C':
+    case '1':
+    case '2':
+    case '4':
+    case 'c':
+    case 'C':
         return 1;
 
-      case 'e':
-      case 's':
-      case 'S':
+    case 'e':
+    case 's':
+    case 'S':
         return 2;
 
-      case 't':
-      case 'l':
-      case 'L':
-      case 'f':
+    case 't':
+    case 'l':
+    case 'L':
+    case 'f':
         return 4;
 
-      case 'd':
-      case 'm':
+    case 'd':
+    case 'm':
         return 8;
 
-      case 'M':
+    case 'M':
         return 16;
 
-      case 'b':
+    case 'b':
         return -1;
 
-      case 'o':
-      case 'x':
+    case 'o':
+    case 'x':
         return 0;
 
-      default:
-        CPLAssert( FALSE );
+    default:
+        CPLAssert(false);
     }
 
     return 0;
@@ -255,10 +258,10 @@ int HFADictionary::GetItemSize( char chType )
 void HFADictionary::Dump( FILE * fp )
 
 {
-    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "\nHFADictionary:\n" ));
+    CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "\nHFADictionary:\n"));
 
     for( int i = 0; i < nTypes; i++ )
     {
-        papoTypes[i]->Dump( fp );
+        papoTypes[i]->Dump(fp);
     }
 }
diff --git a/frmts/hfa/hfaentry.cpp b/frmts/hfa/hfaentry.cpp
index c64c478..178b8c2 100644
--- a/frmts/hfa/hfaentry.cpp
+++ b/frmts/hfa/hfaentry.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfaentry.cpp 33845 2016-04-01 13:43:02Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAEntry class for reading and relating
@@ -35,17 +34,32 @@
  *
  */
 
+#include "cpl_port.h"
 #include "hfa_p.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <vector>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: hfaentry.cpp 33845 2016-04-01 13:43:02Z goatbar $");
+CPL_CVSID("$Id: hfaentry.cpp 37892 2017-04-03 20:05:39Z goatbar $");
 
 /************************************************************************/
 /*                              HFAEntry()                              */
 /************************************************************************/
 
 HFAEntry::HFAEntry() :
-    bDirty(FALSE),
+    bDirty(false),
     nFilePos(0),
     psHFA(NULL),
     poParent(NULL),
@@ -58,7 +72,7 @@ HFAEntry::HFAEntry() :
     nDataPos(0),
     nDataSize(0),
     pabyData(NULL),
-    bIsMIFObject(FALSE)
+    bIsMIFObject(false)
 {
     szName[0] = '\0';
     szType[0] = '\0';
@@ -70,55 +84,50 @@ HFAEntry::HFAEntry() :
 /*      Construct an HFAEntry from the source file.                     */
 /************************************************************************/
 
-HFAEntry* HFAEntry::New( HFAInfo_t * psHFAIn, GUInt32 nPos,
-                         HFAEntry * poParentIn, HFAEntry * poPrevIn )
+HFAEntry* HFAEntry::New( HFAInfo_t *psHFAIn, GUInt32 nPos,
+                         HFAEntry * poParentIn, HFAEntry *poPrevIn )
 
 {
-    HFAEntry* poEntry = new HFAEntry;
+    HFAEntry *poEntry = new HFAEntry;
     poEntry->psHFA = psHFAIn;
 
     poEntry->nFilePos = nPos;
     poEntry->poParent = poParentIn;
     poEntry->poPrev = poPrevIn;
 
-/* -------------------------------------------------------------------- */
-/*      Read the entry information from the file.                       */
-/* -------------------------------------------------------------------- */
-    GInt32	anEntryNums[6];
+    // Read the entry information from the file.
+    GInt32 anEntryNums[6] = {};
 
-    if( VSIFSeekL( poEntry->psHFA->fp, poEntry->nFilePos, SEEK_SET ) == -1
-        || VSIFReadL( anEntryNums, sizeof(GInt32), 6, poEntry->psHFA->fp ) < 1 )
+    if( VSIFSeekL( poEntry->psHFA->fp, poEntry->nFilePos, SEEK_SET ) == -1 ||
+        VSIFReadL( anEntryNums, sizeof(GInt32), 6, poEntry->psHFA->fp ) < 1 )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "VSIFReadL(%p,6*4) @ %d failed in HFAEntry().\n%s",
-                  poEntry->psHFA->fp, poEntry->nFilePos, VSIStrerror( errno ) );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "VSIFReadL(%p,6*4) @ %d failed in HFAEntry().\n%s",
+                 poEntry->psHFA->fp, poEntry->nFilePos, VSIStrerror(errno));
         delete poEntry;
         return NULL;
     }
 
     for( int i = 0; i < 6; i++ )
-        HFAStandard( 4, anEntryNums + i );
+        HFAStandard(4, anEntryNums + i);
 
     poEntry->nNextPos = anEntryNums[0];
     poEntry->nChildPos = anEntryNums[3];
     poEntry->nDataPos = anEntryNums[4];
     poEntry->nDataSize = anEntryNums[5];
 
-/* -------------------------------------------------------------------- */
-/*      Read the name, and type.                                        */
-/* -------------------------------------------------------------------- */
-    if( VSIFReadL( poEntry->szName, 1, 64, poEntry->psHFA->fp ) < 1
-        || VSIFReadL( poEntry->szType, 1, 32, poEntry->psHFA->fp ) < 1 )
+    // Read the name, and type.
+    if( VSIFReadL(poEntry->szName, 1, 64, poEntry->psHFA->fp) < 1 ||
+        VSIFReadL(poEntry->szType, 1, 32, poEntry->psHFA->fp) < 1 )
     {
-        poEntry->szName[sizeof(poEntry->szName)-1] = '\0';
-        poEntry->szType[sizeof(poEntry->szType)-1] = '\0';
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "VSIFReadL() failed in HFAEntry()." );
+        poEntry->szName[sizeof(poEntry->szName) - 1] = '\0';
+        poEntry->szType[sizeof(poEntry->szType) - 1] = '\0';
+        CPLError(CE_Failure, CPLE_FileIO, "VSIFReadL() failed in HFAEntry().");
         delete poEntry;
         return NULL;
     }
-    poEntry->szName[sizeof(poEntry->szName)-1] = '\0';
-    poEntry->szType[sizeof(poEntry->szType)-1] = '\0';
+    poEntry->szName[sizeof(poEntry->szName) - 1] = '\0';
+    poEntry->szType[sizeof(poEntry->szType) - 1] = '\0';
     return poEntry;
 }
 
@@ -145,22 +154,17 @@ HFAEntry::HFAEntry( HFAInfo_t * psHFAIn,
     nDataPos(0),
     nDataSize(0),
     pabyData(NULL),
-    bIsMIFObject(FALSE)
+    bIsMIFObject(false)
 {
-/* -------------------------------------------------------------------- */
-/*      Initialize Entry                                                */
-/* -------------------------------------------------------------------- */
-    SetName( pszNodeName );
-    memset( szType, 0, sizeof(szType) );
-    strncpy( szType, pszTypeName, sizeof(szType) );
-    szType[sizeof(szType)-1] = '\0';
-
-/* -------------------------------------------------------------------- */
-/*      Update the previous or parent node to refer to this one.        */
-/* -------------------------------------------------------------------- */
+    // Initialize Entry.
+    SetName(pszNodeName);
+    memset(szType, 0, sizeof(szType));
+    snprintf(szType, sizeof(szType), "%s", pszTypeName);
+
+    // Update the previous or parent node to refer to this one.
     if( poParent == NULL )
     {
-        /* do nothing */
+        // Do nothing.
     }
     else if( poParent->poChild == NULL )
     {
@@ -187,12 +191,12 @@ HFAEntry::HFAEntry( HFAInfo_t * psHFAIn,
 /*      would be written to disk later.                                 */
 /************************************************************************/
 
-HFAEntry* HFAEntry::New( HFAInfo_t * psHFAIn,
-                         const char * pszNodeName,
-                         const char * pszTypeName,
-                         HFAEntry * poParentIn )
+HFAEntry* HFAEntry::New( HFAInfo_t *psHFAIn,
+                         const char *pszNodeName,
+                         const char *pszTypeName,
+                         HFAEntry *poParentIn )
 {
-    CPLAssert( poParentIn != NULL );
+    CPLAssert(poParentIn != NULL);
     return new HFAEntry(psHFAIn, pszNodeName, pszTypeName, poParentIn);
 }
 
@@ -202,14 +206,14 @@ HFAEntry* HFAEntry::New( HFAInfo_t * psHFAIn,
 /*      Create a pseudo-HFAEntry wrapping a MIFObject.                  */
 /************************************************************************/
 
-HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer,
+HFAEntry *HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer,
                                              const char *pszMIFObjectPath )
 {
     CPLString osFieldName;
 
-    osFieldName.Printf("%s.%s", pszMIFObjectPath, "MIFDictionary" );
-    const char *pszField = poContainer->GetStringField( osFieldName.c_str() );
-    if (pszField == NULL)
+    osFieldName.Printf("%s.%s", pszMIFObjectPath, "MIFDictionary");
+    const char *pszField = poContainer->GetStringField(osFieldName.c_str());
+    if( pszField == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry",
                  osFieldName.c_str());
@@ -217,9 +221,9 @@ HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer,
     }
     CPLString osDictionary = pszField;
 
-    osFieldName.Printf("%s.%s", pszMIFObjectPath, "type.string" );
-    pszField = poContainer->GetStringField( osFieldName.c_str() );
-    if (pszField == NULL)
+    osFieldName.Printf("%s.%s", pszMIFObjectPath, "type.string");
+    pszField = poContainer->GetStringField(osFieldName.c_str());
+    if( pszField == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry",
                  osFieldName.c_str());
@@ -227,45 +231,44 @@ HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer,
     }
     CPLString osType = pszField;
 
-    osFieldName.Printf("%s.%s", pszMIFObjectPath, "MIFObject" );
+    osFieldName.Printf("%s.%s", pszMIFObjectPath, "MIFObject");
     int nRemainingDataSize = 0;
-    pszField = poContainer->GetStringField( osFieldName.c_str(),
-                                            NULL, &nRemainingDataSize );
-    if (pszField == NULL)
+    pszField = poContainer->GetStringField(osFieldName.c_str(),
+                                           NULL, &nRemainingDataSize);
+    if( pszField == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s entry",
                  osFieldName.c_str());
         return NULL;
     }
 
-    GInt32 nMIFObjectSize;
-    // we rudely look before the field data to get at the pointer/size info
-    memcpy( &nMIFObjectSize, pszField-8, 4 );
-    HFAStandard( 4, &nMIFObjectSize );
-    if (nMIFObjectSize <= 0)
+    GInt32 nMIFObjectSize = 0;
+    // We rudely look before the field data to get at the pointer/size info.
+    memcpy(&nMIFObjectSize, pszField - 8, 4);
+    HFAStandard(4, &nMIFObjectSize);
+    if( nMIFObjectSize <= 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid MIF object size (%d)",
                  nMIFObjectSize);
         return NULL;
     }
 
-    // check that we won't copy more bytes than available in the buffer
-    if (nMIFObjectSize > nRemainingDataSize)
+    // Check that we won't copy more bytes than available in the buffer.
+    if( nMIFObjectSize > nRemainingDataSize )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Invalid MIF object size (%d > %d)",
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid MIF object size (%d > %d)",
                  nMIFObjectSize, nRemainingDataSize);
         return NULL;
     }
 
-    GByte* l_pabyData = (GByte *) VSIMalloc(nMIFObjectSize);
-    if (l_pabyData == NULL)
+    GByte *l_pabyData = static_cast<GByte *>(VSIMalloc(nMIFObjectSize));
+    if( l_pabyData == NULL )
         return NULL;
 
-    memcpy( l_pabyData, pszField, nMIFObjectSize );
-
-    return new HFAEntry(osDictionary, osType,
-                        nMIFObjectSize, l_pabyData);
+    memcpy(l_pabyData, pszField, nMIFObjectSize);
 
+    return new HFAEntry(osDictionary, osType, nMIFObjectSize, l_pabyData);
 }
 
 /************************************************************************/
@@ -274,11 +277,11 @@ HFAEntry* HFAEntry::BuildEntryFromMIFObject( HFAEntry *poContainer,
 /*      Create a pseudo-HFAEntry wrapping a MIFObject.                  */
 /************************************************************************/
 
-HFAEntry::HFAEntry( const char * pszDictionary,
-                    const char * pszTypeName,
+HFAEntry::HFAEntry( const char *pszDictionary,
+                    const char *pszTypeName,
                     int nDataSizeIn,
-                    GByte* pabyDataIn ) :
-    bDirty(FALSE),
+                    GByte *pabyDataIn ) :
+    bDirty(false),
     nFilePos(0),
     poParent(NULL),
     poPrev(NULL),
@@ -288,32 +291,25 @@ HFAEntry::HFAEntry( const char * pszDictionary,
     poChild(NULL),
     nDataPos(0),
     nDataSize(0),
-    bIsMIFObject(TRUE)
+    bIsMIFObject(true)
 {
-/* -------------------------------------------------------------------- */
-/*      Initialize Entry                                                */
-/* -------------------------------------------------------------------- */
-    memset( szName, 0, sizeof(szName) );
+    // Initialize Entry
+    memset(szName, 0, sizeof(szName));
 
-/* -------------------------------------------------------------------- */
-/*      Create a dummy HFAInfo_t.                                       */
-/* -------------------------------------------------------------------- */
-    psHFA = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1);
+    // Create a dummy HFAInfo_t.
+    psHFA = static_cast<HFAInfo_t *>(CPLCalloc(sizeof(HFAInfo_t), 1));
 
     psHFA->eAccess = HFA_ReadOnly;
-    psHFA->bTreeDirty = FALSE;
+    psHFA->bTreeDirty = false;
     psHFA->poRoot = this;
 
-    psHFA->poDictionary = new HFADictionary( pszDictionary );
+    psHFA->poDictionary = new HFADictionary(pszDictionary);
 
-/* -------------------------------------------------------------------- */
-/*      Work out the type for this MIFObject.                           */
-/* -------------------------------------------------------------------- */
-    memset( szType, 0, sizeof(szType) );
-    strncpy( szType, pszTypeName, sizeof(szType) );
-    szType[sizeof(szType)-1] = '\0';
+    // Work out the type for this MIFObject.
+    memset(szType, 0, sizeof(szType));
+    snprintf(szType, sizeof(szType), "%s", pszTypeName);
 
-    poType = psHFA->poDictionary->FindType( szType );
+    poType = psHFA->poDictionary->FindType(szType);
 
     nDataSize = nDataSizeIn;
     pabyData = pabyDataIn;
@@ -329,7 +325,7 @@ HFAEntry::HFAEntry( const char * pszDictionary,
 HFAEntry::~HFAEntry()
 
 {
-    CPLFree( pabyData );
+    CPLFree(pabyData);
 
     if( poNext != NULL )
         delete poNext;
@@ -340,14 +336,14 @@ HFAEntry::~HFAEntry()
     if( bIsMIFObject )
     {
         delete psHFA->poDictionary;
-        CPLFree( psHFA );
+        CPLFree(psHFA);
     }
 }
 
 /************************************************************************/
 /*                          RemoveAndDestroy()                          */
 /*                                                                      */
-/*      Removes this entry, and it's children from the current          */
+/*      Removes this entry, and its children from the current           */
 /*      tree.  The parent and/or siblings are appropriately updated     */
 /*      so that they will be flushed back to disk without the           */
 /*      reference to this node.                                         */
@@ -397,11 +393,10 @@ CPLErr HFAEntry::RemoveAndDestroy()
 
 void HFAEntry::SetName( const char *pszNodeName )
 {
-  memset( szName, 0, sizeof(szName) );
-  strncpy( szName, pszNodeName, sizeof(szName) );
-  szName[sizeof(szName)-1] = '\0';
+    memset(szName, 0, sizeof(szName));
+    snprintf(szName, sizeof(szName), "%s", pszNodeName);
 
-  MarkDirty();
+    MarkDirty();
 }
 
 /************************************************************************/
@@ -411,17 +406,15 @@ void HFAEntry::SetName( const char *pszNodeName )
 HFAEntry *HFAEntry::GetChild()
 
 {
-/* -------------------------------------------------------------------- */
-/*      Do we need to create the child node?                            */
-/* -------------------------------------------------------------------- */
+    // Do we need to create the child node?
     if( poChild == NULL && nChildPos != 0 )
     {
-        poChild = HFAEntry::New( psHFA, nChildPos, this, NULL );
+        poChild = HFAEntry::New(psHFA, nChildPos, this, NULL);
         if( poChild == NULL )
             nChildPos = 0;
     }
 
-    return( poChild );
+    return poChild;
 }
 
 /************************************************************************/
@@ -431,9 +424,7 @@ HFAEntry *HFAEntry::GetChild()
 HFAEntry *HFAEntry::GetNext()
 
 {
-/* -------------------------------------------------------------------- */
-/*      Do we need to create the next node?                             */
-/* -------------------------------------------------------------------- */
+    // Do we need to create the next node?
     if( poNext == NULL && nNextPos != 0 )
     {
         // Check if we have a loop on the next node in this sibling chain.
@@ -445,20 +436,21 @@ HFAEntry *HFAEntry::GetNext()
 
         if( poPast != NULL )
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Corrupt (looping) entry in %s, ignoring some entries after %s.",
-                      psHFA->pszFilename,
-                      szName );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Corrupt (looping) entry in %s, "
+                     "ignoring some entries after %s.",
+                     psHFA->pszFilename,
+                     szName);
             nNextPos = 0;
             return NULL;
         }
 
-        poNext = HFAEntry::New( psHFA, nNextPos, poParent, this );
+        poNext = HFAEntry::New(psHFA, nNextPos, poParent, this);
         if( poNext == NULL )
             nNextPos = 0;
     }
 
-    return( poNext );
+    return poNext;
 }
 
 /************************************************************************/
@@ -475,42 +467,38 @@ void HFAEntry::LoadData()
         return;
     if( nDataSize > INT_MAX - 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Invalid value for nDataSize = %u", nDataSize);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid value for nDataSize = %u", nDataSize);
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Allocate buffer, and read data.                                 */
-/* -------------------------------------------------------------------- */
-    pabyData = (GByte *) VSI_MALLOC_VERBOSE(nDataSize + 1);
-    if (pabyData == NULL)
+    // Allocate buffer, and read data.
+    pabyData = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nDataSize + 1));
+    if( pabyData == NULL )
     {
         return;
     }
 
-    if( VSIFSeekL( psHFA->fp, nDataPos, SEEK_SET ) < 0 )
+    if( VSIFSeekL(psHFA->fp, nDataPos, SEEK_SET) < 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "VSIFSeekL() failed in HFAEntry::LoadData()." );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "VSIFSeekL() failed in HFAEntry::LoadData().");
         return;
     }
 
-    if( VSIFReadL( pabyData, 1, nDataSize, psHFA->fp ) < 1 )
+    if( VSIFReadL(pabyData, 1, nDataSize, psHFA->fp) < 1 )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "VSIFReadL() failed in HFAEntry::LoadData()." );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "VSIFReadL() failed in HFAEntry::LoadData().");
         return;
     }
 
-    /* Make sure the buffer is always null terminated to avoid */
-    /* issues when extracting strings from a corrupted file */
+    // Make sure the buffer is always null terminated to avoid
+    // issues when extracting strings from a corrupted file.
     pabyData[nDataSize] = '\0';
 
-/* -------------------------------------------------------------------- */
-/*      Get the type corresponding to this entry.                       */
-/* -------------------------------------------------------------------- */
-    poType = psHFA->poDictionary->FindType( szType );
+    // Get the type corresponding to this entry.
+    poType = psHFA->poDictionary->FindType(szType);
     if( poType == NULL )
         return;
 }
@@ -523,7 +511,7 @@ HFAType *HFAEntry::GetTypeObject()
 
 {
     if( poType == NULL )
-        poType = psHFA->poDictionary->FindType( szType );
+        poType = psHFA->poDictionary->FindType(szType);
 
     return poType;
 }
@@ -543,7 +531,7 @@ GByte *HFAEntry::MakeData( int nSize )
 {
     if( poType == NULL )
     {
-        poType = psHFA->poDictionary->FindType( szType );
+        poType = psHFA->poDictionary->FindType(szType);
         if( poType == NULL )
             return NULL;
     }
@@ -551,42 +539,42 @@ GByte *HFAEntry::MakeData( int nSize )
     if( nSize == 0 && poType->nBytes > 0 )
         nSize = poType->nBytes;
 
-    if( (int) nDataSize < nSize && nSize > 0 )
+    // nDataSize is a GUInt32.
+    if( static_cast<int>(nDataSize) < nSize && nSize > 0 )
     {
-        pabyData = (GByte *) CPLRealloc(pabyData, nSize);
-        memset( pabyData + nDataSize, 0, nSize - nDataSize );
+        pabyData = static_cast<GByte *>(CPLRealloc(pabyData, nSize));
+        memset(pabyData + nDataSize, 0, nSize - nDataSize);
         nDataSize = nSize;
 
         MarkDirty();
 
-/* -------------------------------------------------------------------- */
-/*      If the data already had a file position, we now need to         */
-/*      clear that, forcing it to be rewritten at the end of the        */
-/*      file.  Referencing nodes will need to be marked dirty so        */
-/*      they are rewritten.                                             */
-/* -------------------------------------------------------------------- */
+        // If the data already had a file position, we now need to
+        // clear that, forcing it to be rewritten at the end of the
+        // file.  Referencing nodes will need to be marked dirty so
+        // they are rewritten.
         if( nFilePos != 0 )
         {
             nFilePos = 0;
             nDataPos = 0;
-            if (poPrev != NULL) poPrev->MarkDirty();
-            if (poNext != NULL) poNext->MarkDirty();
-            if (poChild != NULL) poChild->MarkDirty();
-            if (poParent != NULL) poParent->MarkDirty();
+            if( poPrev != NULL ) poPrev->MarkDirty();
+            if( poNext != NULL ) poNext->MarkDirty();
+            if( poChild != NULL ) poChild->MarkDirty();
+            if( poParent != NULL ) poParent->MarkDirty();
         }
     }
     else
-        LoadData(); // make sure the data is loaded before we return pointer.
+    {
+        LoadData();  // Make sure the data is loaded before we return pointer.
+    }
 
     return pabyData;
 }
 
-
 /************************************************************************/
 /*                          DumpFieldValues()                           */
 /************************************************************************/
 
-void HFAEntry::DumpFieldValues( FILE * fp, const char * pszPrefix )
+void HFAEntry::DumpFieldValues( FILE *fp, const char *pszPrefix )
 
 {
     if( pszPrefix == NULL )
@@ -597,9 +585,7 @@ void HFAEntry::DumpFieldValues( FILE * fp, const char * pszPrefix )
     if( pabyData == NULL || poType == NULL )
         return;
 
-    poType->DumpInstValue( fp,
-                           pabyData, nDataPos, nDataSize,
-                           pszPrefix );
+    poType->DumpInstValue(fp, pabyData, nDataPos, nDataSize, pszPrefix);
 }
 
 /************************************************************************/
@@ -614,10 +600,10 @@ void HFAEntry::DumpFieldValues( FILE * fp, const char * pszPrefix )
 std::vector<HFAEntry*> HFAEntry::FindChildren( const char *pszName,
                                                const char *pszType,
                                                int nRecLevel,
-                                               int* pbErrorDetected )
+                                               int *pbErrorDetected )
 
 {
-    std::vector<HFAEntry*> apoChildren;
+    std::vector<HFAEntry *> apoChildren;
 
     if( *pbErrorDetected )
         return apoChildren;
@@ -629,21 +615,23 @@ std::vector<HFAEntry*> HFAEntry::FindChildren( const char *pszName,
         return apoChildren;
     }
 
-    for( HFAEntry *poEntry = GetChild(); poEntry != NULL; poEntry = poEntry->GetNext() )
+    for( HFAEntry *poEntry = GetChild();
+         poEntry != NULL;
+         poEntry = poEntry->GetNext() )
     {
-        std::vector<HFAEntry*> apoEntryChildren;
+        std::vector<HFAEntry *> apoEntryChildren;
 
-        if( (pszName == NULL || EQUAL(poEntry->GetName(),pszName))
-            && (pszType == NULL || EQUAL(poEntry->GetType(),pszType)) )
-            apoChildren.push_back( poEntry );
+        if( (pszName == NULL || EQUAL(poEntry->GetName(), pszName)) &&
+            (pszType == NULL || EQUAL(poEntry->GetType(), pszType)) )
+            apoChildren.push_back(poEntry);
 
-        apoEntryChildren = poEntry->FindChildren( pszName, pszType, nRecLevel + 1,
-                                                  pbErrorDetected);
+        apoEntryChildren = poEntry->FindChildren(
+            pszName, pszType, nRecLevel + 1, pbErrorDetected);
         if( *pbErrorDetected )
             return apoChildren;
 
         for( size_t i = 0; i < apoEntryChildren.size(); i++ )
-            apoChildren.push_back( apoEntryChildren[i] );
+            apoChildren.push_back(apoEntryChildren[i]);
     }
 
     return apoChildren;
@@ -661,33 +649,31 @@ std::vector<HFAEntry*> HFAEntry::FindChildren( const char *pszName,
 /*                           GetNamedChild()                            */
 /************************************************************************/
 
-HFAEntry *HFAEntry::GetNamedChild( const char * pszName )
+HFAEntry *HFAEntry::GetNamedChild( const char *pszName )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Establish how much of this name path is for the next child.     */
-/*      Up to the '.' or end of the string.                             */
-/* -------------------------------------------------------------------- */
+    // Establish how much of this name path is for the next child.
+    // Up to the '.' or end of the string.
     int nNameLen = 0;
     for( ;
-         pszName[nNameLen] != '.'
-             && pszName[nNameLen] != '\0'
-             && pszName[nNameLen] != ':';
+         pszName[nNameLen] != '.' &&
+         pszName[nNameLen] != '\0' &&
+         pszName[nNameLen] != ':';
          nNameLen++ ) {}
 
-/* -------------------------------------------------------------------- */
-/*      Scan children looking for this name.                            */
-/* -------------------------------------------------------------------- */
-    for( HFAEntry *poEntry = GetChild(); poEntry != NULL; poEntry = poEntry->GetNext() )
+    // Scan children looking for this name.
+    for( HFAEntry *poEntry = GetChild();
+         poEntry != NULL;
+         poEntry = poEntry->GetNext() )
     {
-        if( EQUALN(poEntry->GetName(),pszName,nNameLen)
-            && (int) strlen(poEntry->GetName()) == nNameLen )
+        if( EQUALN(poEntry->GetName(), pszName, nNameLen) &&
+            static_cast<int>(strlen(poEntry->GetName())) == nNameLen )
         {
             if( pszName[nNameLen] == '.' )
             {
                 HFAEntry *poResult;
 
-                poResult = poEntry->GetNamedChild( pszName+nNameLen+1 );
+                poResult = poEntry->GetNamedChild(pszName + nNameLen + 1);
                 if( poResult != NULL )
                     return poResult;
             }
@@ -703,65 +689,54 @@ HFAEntry *HFAEntry::GetNamedChild( const char * pszName )
 /*                           GetFieldValue()                            */
 /************************************************************************/
 
-int HFAEntry::GetFieldValue( const char * pszFieldPath,
-                             char chReqType, void *pReqReturn,
-                             int *pnRemainingDataSize)
+bool HFAEntry::GetFieldValue( const char *pszFieldPath,
+                              char chReqType, void *pReqReturn,
+                              int *pnRemainingDataSize )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Is there a node path in this string?                            */
-/* -------------------------------------------------------------------- */
-    if( strchr(pszFieldPath,':') != NULL )
+    // Is there a node path in this string?
+    if( strchr(pszFieldPath, ':') != NULL )
     {
-        HFAEntry* poEntry = GetNamedChild( pszFieldPath );
+        HFAEntry *poEntry = GetNamedChild(pszFieldPath);
         if( poEntry == NULL )
-            return FALSE;
+            return false;
 
-        pszFieldPath = strchr(pszFieldPath,':') + 1;
+        pszFieldPath = strchr(pszFieldPath, ':') + 1;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we have the data and type for this node?                     */
-/* -------------------------------------------------------------------- */
+    // Do we have the data and type for this node?
     LoadData();
 
     if( pabyData == NULL )
-        return FALSE;
+        return false;
 
     if( poType == NULL )
-        return FALSE;
+        return false;
 
-/* -------------------------------------------------------------------- */
-/*      Extract the instance information.                               */
-/* -------------------------------------------------------------------- */
-
-
-    return( poType->ExtractInstValue( pszFieldPath,
-                                      pabyData, nDataPos, nDataSize,
-                                      chReqType, pReqReturn, pnRemainingDataSize ) );
+    // Extract the instance information.
+    return
+        poType->ExtractInstValue(pszFieldPath,
+                                 pabyData, nDataPos, nDataSize,
+                                 chReqType, pReqReturn, pnRemainingDataSize);
 }
 
 /************************************************************************/
 /*                           GetFieldCount()                            */
 /************************************************************************/
 
-int HFAEntry::GetFieldCount( const char * pszFieldPath, CPL_UNUSED CPLErr *peErr )
+int HFAEntry::GetFieldCount( const char *pszFieldPath, CPLErr * /* peErr */ )
 {
-/* -------------------------------------------------------------------- */
-/*      Is there a node path in this string?                            */
-/* -------------------------------------------------------------------- */
-    if( strchr(pszFieldPath,':') != NULL )
+    // Is there a node path in this string?
+    if( strchr(pszFieldPath, ':') != NULL )
     {
-        HFAEntry* poEntry = GetNamedChild( pszFieldPath );
+        HFAEntry *poEntry = GetNamedChild(pszFieldPath);
         if( poEntry == NULL )
             return -1;
 
-        pszFieldPath = strchr(pszFieldPath,':') + 1;
+        pszFieldPath = strchr(pszFieldPath, ':') + 1;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we have the data and type for this node?                     */
-/* -------------------------------------------------------------------- */
+    // Do we have the data and type for this node?
     LoadData();
 
     if( pabyData == NULL )
@@ -770,24 +745,22 @@ int HFAEntry::GetFieldCount( const char * pszFieldPath, CPL_UNUSED CPLErr *peErr
     if( poType == NULL )
         return -1;
 
-/* -------------------------------------------------------------------- */
-/*      Extract the instance information.                               */
-/* -------------------------------------------------------------------- */
+    // Extract the instance information.
 
-    return( poType->GetInstCount( pszFieldPath,
-                                  pabyData, nDataPos, nDataSize ) );
+    return poType->GetInstCount( pszFieldPath,
+                                 pabyData, nDataPos, nDataSize );
 }
 
 /************************************************************************/
 /*                            GetIntField()                             */
 /************************************************************************/
 
-GInt32 HFAEntry::GetIntField( const char * pszFieldPath, CPLErr *peErr )
+GInt32 HFAEntry::GetIntField( const char *pszFieldPath, CPLErr *peErr )
 
 {
-    GInt32	nIntValue;
+    GInt32 nIntValue = 0;
 
-    if( !GetFieldValue( pszFieldPath, 'i', &nIntValue, NULL ) )
+    if( !GetFieldValue(pszFieldPath, 'i', &nIntValue, NULL) )
     {
         if( peErr != NULL )
             *peErr = CE_Failure;
@@ -815,29 +788,29 @@ GIntBig HFAEntry::GetBigIntField( const char *pszFieldPath, CPLErr *peErr )
 {
     char szFullFieldPath[1024];
 
-    snprintf( szFullFieldPath, sizeof(szFullFieldPath), "%s[0]", pszFieldPath );
-    const GUInt32 nLower = GetIntField( szFullFieldPath, peErr );
+    snprintf(szFullFieldPath, sizeof(szFullFieldPath), "%s[0]", pszFieldPath);
+    const GUInt32 nLower = GetIntField(szFullFieldPath, peErr);
     if( peErr != NULL && *peErr != CE_None )
         return 0;
 
-    snprintf( szFullFieldPath, sizeof(szFullFieldPath), "%s[1]", pszFieldPath );
-    const GUInt32 nUpper = GetIntField( szFullFieldPath, peErr );
+    snprintf(szFullFieldPath, sizeof(szFullFieldPath), "%s[1]", pszFieldPath);
+    const GUInt32 nUpper = GetIntField(szFullFieldPath, peErr);
     if( peErr != NULL && *peErr != CE_None )
         return 0;
 
-    return nLower + (((GIntBig) nUpper) << 32);
+    return nLower + (static_cast<GIntBig>(nUpper) << 32);
 }
 
 /************************************************************************/
 /*                           GetDoubleField()                           */
 /************************************************************************/
 
-double HFAEntry::GetDoubleField( const char * pszFieldPath, CPLErr *peErr )
+double HFAEntry::GetDoubleField( const char *pszFieldPath, CPLErr *peErr )
 
 {
-    double dfDoubleValue;
+    double dfDoubleValue = 0;
 
-    if( !GetFieldValue( pszFieldPath, 'd', &dfDoubleValue, NULL ) )
+    if( !GetFieldValue(pszFieldPath, 'd', &dfDoubleValue, NULL) )
     {
         if( peErr != NULL )
             *peErr = CE_Failure;
@@ -855,13 +828,13 @@ double HFAEntry::GetDoubleField( const char * pszFieldPath, CPLErr *peErr )
 /*                           GetStringField()                           */
 /************************************************************************/
 
-const char *HFAEntry::GetStringField( const char * pszFieldPath, CPLErr *peErr,
+const char *HFAEntry::GetStringField( const char *pszFieldPath, CPLErr *peErr,
                                       int *pnRemainingDataSize)
 
 {
     char *pszResult = NULL;
 
-    if( !GetFieldValue( pszFieldPath, 's', &pszResult, pnRemainingDataSize ) )
+    if( !GetFieldValue(pszFieldPath, 's', &pszResult, pnRemainingDataSize) )
     {
         if( peErr != NULL )
             *peErr = CE_Failure;
@@ -879,51 +852,41 @@ const char *HFAEntry::GetStringField( const char * pszFieldPath, CPLErr *peErr,
 /*                           SetFieldValue()                            */
 /************************************************************************/
 
-CPLErr HFAEntry::SetFieldValue( const char * pszFieldPath,
+CPLErr HFAEntry::SetFieldValue( const char *pszFieldPath,
                                 char chReqType, void *pValue )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Is there a node path in this string?                            */
-/* -------------------------------------------------------------------- */
-    if( strchr(pszFieldPath,':') != NULL )
+    // Is there a node path in this string?
+    if( strchr(pszFieldPath, ':') != NULL )
     {
-        HFAEntry* poEntry = GetNamedChild( pszFieldPath );
+        HFAEntry *poEntry = GetNamedChild(pszFieldPath);
         if( poEntry == NULL )
             return CE_Failure;
 
-        pszFieldPath = strchr(pszFieldPath,':') + 1;
+        pszFieldPath = strchr(pszFieldPath, ':') + 1;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we have the data and type for this node?  Try loading        */
-/*      from a file, or instantiating a new node.                       */
-/* -------------------------------------------------------------------- */
+    // Do we have the data and type for this node?  Try loading
+    // from a file, or instantiating a new node.
     LoadData();
-    if( MakeData() == NULL
-        || pabyData == NULL
-        || poType == NULL )
+    if( MakeData() == NULL || pabyData == NULL || poType == NULL )
     {
-        CPLAssert( FALSE );
         return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Extract the instance information.                               */
-/* -------------------------------------------------------------------- */
+    // Extract the instance information.
     MarkDirty();
 
-    return( poType->SetInstValue( pszFieldPath,
-                                  pabyData, nDataPos, nDataSize,
-                                  chReqType, pValue ) );
+    return poType->SetInstValue(pszFieldPath, pabyData, nDataPos, nDataSize,
+                                chReqType, pValue);
 }
 
 /************************************************************************/
 /*                           SetStringField()                           */
 /************************************************************************/
 
-CPLErr HFAEntry::SetStringField( const char * pszFieldPath,
-                                 const char * pszValue )
+CPLErr HFAEntry::SetStringField( const char *pszFieldPath,
+                                 const char *pszValue )
 
 {
     return SetFieldValue( pszFieldPath, 's', (void *) pszValue );
@@ -933,17 +896,17 @@ CPLErr HFAEntry::SetStringField( const char * pszFieldPath,
 /*                            SetIntField()                             */
 /************************************************************************/
 
-CPLErr HFAEntry::SetIntField( const char * pszFieldPath, int nValue )
+CPLErr HFAEntry::SetIntField( const char *pszFieldPath, int nValue )
 
 {
-    return SetFieldValue( pszFieldPath, 'i', &nValue );
+    return SetFieldValue(pszFieldPath, 'i', &nValue);
 }
 
 /************************************************************************/
 /*                           SetDoubleField()                           */
 /************************************************************************/
 
-CPLErr HFAEntry::SetDoubleField( const char * pszFieldPath,
+CPLErr HFAEntry::SetDoubleField( const char *pszFieldPath,
                                  double dfValue )
 
 {
@@ -961,22 +924,17 @@ CPLErr HFAEntry::SetDoubleField( const char * pszFieldPath,
 void HFAEntry::SetPosition()
 
 {
-/* -------------------------------------------------------------------- */
-/*      Establish the location of this entry, and it's data.            */
-/* -------------------------------------------------------------------- */
+    // Establish the location of this entry, and its data.
     if( nFilePos == 0 )
     {
-        nFilePos = HFAAllocateSpace( psHFA,
-                                     psHFA->nEntryHeaderLength
-                                     + nDataSize );
+        nFilePos =
+            HFAAllocateSpace(psHFA, psHFA->nEntryHeaderLength + nDataSize);
 
         if( nDataSize > 0 )
             nDataPos = nFilePos + psHFA->nEntryHeaderLength;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Force all children to set their position.                       */
-/* -------------------------------------------------------------------- */
+    // Force all children to set their position.
     for( HFAEntry *poThisChild = poChild;
          poThisChild != NULL;
          poThisChild = poThisChild->poNext )
@@ -988,82 +946,74 @@ void HFAEntry::SetPosition()
 /************************************************************************/
 /*                            FlushToDisk()                             */
 /*                                                                      */
-/*      Write this entry, and it's data to disk if the entries          */
+/*      Write this entry, and its data to disk if the entries           */
 /*      information is dirty.  Also force children to do the same.      */
 /************************************************************************/
 
 CPLErr HFAEntry::FlushToDisk()
 
 {
-/* -------------------------------------------------------------------- */
-/*      If we are the root node, call SetPosition() on the whole        */
-/*      tree to ensure that all entries have an allocated position.     */
-/* -------------------------------------------------------------------- */
+    // If we are the root node, call SetPosition() on the whole
+    // tree to ensure that all entries have an allocated position.
     if( poParent == NULL )
         SetPosition();
 
-/* ==================================================================== */
-/*      Only write this node out if it is dirty.                        */
-/* ==================================================================== */
+    // Only write this node out if it is dirty.
     if( bDirty )
     {
-/* -------------------------------------------------------------------- */
-/*      Ensure we know where the relative entries are located.          */
-/* -------------------------------------------------------------------- */
+        // Ensure we know where the relative entries are located.
         if( poNext != NULL )
             nNextPos = poNext->nFilePos;
 
         if( poChild != NULL )
             nChildPos = poChild->nFilePos;
 
-/* -------------------------------------------------------------------- */
-/*      Write the Ehfa_Entry fields.                                    */
-/* -------------------------------------------------------------------- */
+        // Write the Ehfa_Entry fields.
 
-        //VSIFFlushL( psHFA->fp );
-        if( VSIFSeekL( psHFA->fp, nFilePos, SEEK_SET ) != 0 )
+        // VSIFFlushL(psHFA->fp);
+        if( VSIFSeekL(psHFA->fp, nFilePos, SEEK_SET) != 0 )
         {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Failed to seek to %d for writing, out of disk space?",
-                      nFilePos );
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Failed to seek to %d for writing, out of disk space?",
+                     nFilePos);
             return CE_Failure;
         }
 
         GUInt32 nLong = nNextPos;
-        HFAStandard( 4, &nLong );
-        bool bOK = VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
+        HFAStandard(4, &nLong);
+        bool bOK = VSIFWriteL(&nLong, 4, 1, psHFA->fp) > 0;
 
         if( poPrev != NULL )
             nLong = poPrev->nFilePos;
         else
             nLong = 0;
-        HFAStandard( 4, &nLong );
-        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
+        HFAStandard(4, &nLong);
+        bOK &= VSIFWriteL(&nLong, 4, 1, psHFA->fp) > 0;
 
         if( poParent != NULL )
             nLong = poParent->nFilePos;
         else
             nLong = 0;
-        HFAStandard( 4, &nLong );
-        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
+        HFAStandard(4, &nLong);
+        bOK &= VSIFWriteL(&nLong, 4, 1, psHFA->fp) > 0;
 
         nLong = nChildPos;
-        HFAStandard( 4, &nLong );
-        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
+        HFAStandard(4, &nLong);
+        bOK &= VSIFWriteL(&nLong, 4, 1, psHFA->fp) > 0;
 
         nLong = nDataPos;
-        HFAStandard( 4, &nLong );
-        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
+        HFAStandard(4, &nLong);
+        bOK &= VSIFWriteL(&nLong, 4, 1, psHFA->fp) > 0;
 
         nLong = nDataSize;
-        HFAStandard( 4, &nLong );
-        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
+        HFAStandard(4, &nLong);
+        bOK &= VSIFWriteL(&nLong, 4, 1, psHFA->fp) > 0;
 
-        bOK &= VSIFWriteL( szName, 1, 64, psHFA->fp ) > 0;
-        bOK &= VSIFWriteL( szType, 1, 32, psHFA->fp ) > 0;
+        bOK &= VSIFWriteL(szName, 1, 64, psHFA->fp) > 0;
+        bOK &= VSIFWriteL(szType, 1, 32, psHFA->fp) > 0;
 
-        nLong = 0; /* Should we keep the time, or set it more reasonably? */
-        bOK &= VSIFWriteL( &nLong, 4, 1, psHFA->fp ) > 0;
+        nLong = 0;  // Should we keep the time, or set it more reasonably?
+        bOK &= VSIFWriteL(&nLong, 4, 1, psHFA->fp) > 0;
         if( !bOK )
         {
             CPLError( CE_Failure, CPLE_FileIO,
@@ -1072,29 +1022,25 @@ CPLErr HFAEntry::FlushToDisk()
             return CE_Failure;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Write out the data.                                             */
-/* -------------------------------------------------------------------- */
-        //VSIFFlushL( psHFA->fp );
+        // Write out the data.
+        // VSIFFlushL(psHFA->fp);
         if( nDataSize > 0 && pabyData != NULL )
         {
-            if( VSIFSeekL( psHFA->fp, nDataPos, SEEK_SET ) != 0
-                || VSIFWriteL( pabyData, nDataSize, 1, psHFA->fp ) != 1 )
+            if( VSIFSeekL(psHFA->fp, nDataPos, SEEK_SET) != 0 ||
+                VSIFWriteL(pabyData, nDataSize, 1, psHFA->fp) != 1 )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Failed to write %d bytes HFAEntry %s(%s) data,\n"
-                          "out of disk space?",
-                          nDataSize, szName, szType );
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Failed to write %d bytes HFAEntry %s(%s) data, "
+                         "out of disk space?",
+                         nDataSize, szName, szType);
                 return CE_Failure;
             }
         }
 
-        //VSIFFlushL( psHFA->fp );
+        // VSIFFlushL(psHFA->fp);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Process all the children of this node                           */
-/* -------------------------------------------------------------------- */
+    // Process all the children of this node.
     for( HFAEntry *poThisChild = poChild;
          poThisChild != NULL;
          poThisChild = poThisChild->poNext )
@@ -1104,7 +1050,7 @@ CPLErr HFAEntry::FlushToDisk()
             return eErr;
     }
 
-    bDirty = FALSE;
+    bDirty = false;
 
     return CE_None;
 }
@@ -1119,6 +1065,6 @@ CPLErr HFAEntry::FlushToDisk()
 void HFAEntry::MarkDirty()
 
 {
-    bDirty = TRUE;
-    psHFA->bTreeDirty = TRUE;
+    bDirty = true;
+    psHFA->bTreeDirty = true;
 }
diff --git a/frmts/hfa/hfafield.cpp b/frmts/hfa/hfafield.cpp
index 3a8eab9..34bc168 100644
--- a/frmts/hfa/hfafield.cpp
+++ b/frmts/hfa/hfafield.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfafield.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAField class for managing information
@@ -29,15 +28,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfafield.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <cerrno>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+#include <limits>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+
+CPL_CVSID("$Id: hfafield.cpp 37947 2017-04-10 19:20:23Z goatbar $");
 
-#define MAX_ENTRY_REPORT   16
+static const int MAX_ENTRY_REPORT = 16;
 
 /************************************************************************/
 /* ==================================================================== */
-/*		                HFAField				*/
+/*                              HFAField                                */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -54,7 +71,9 @@ HFAField::HFAField() :
     poItemObjectType(NULL),
     papszEnumNames(NULL),
     pszFieldName(NULL)
-{ }
+{
+    memset(szNumberString, 0, sizeof(szNumberString));
+}
 
 /************************************************************************/
 /*                             ~HFAField()                              */
@@ -63,21 +82,19 @@ HFAField::HFAField() :
 HFAField::~HFAField()
 
 {
-    CPLFree( pszItemObjectType );
-    CSLDestroy( papszEnumNames );
-    CPLFree( pszFieldName );
+    CPLFree(pszItemObjectType);
+    CSLDestroy(papszEnumNames);
+    CPLFree(pszFieldName);
 }
 
 /************************************************************************/
 /*                             Initialize()                             */
 /************************************************************************/
 
-const char *HFAField::Initialize( const char * pszInput )
+const char *HFAField::Initialize( const char *pszInput )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Read the number.                                                */
-/* -------------------------------------------------------------------- */
+    // Read the number.
     nItemCount = atoi(pszInput);
     if( nItemCount < 0 )
         return NULL;
@@ -90,53 +107,45 @@ const char *HFAField::Initialize( const char * pszInput )
 
     pszInput++;
 
-/* -------------------------------------------------------------------- */
-/*      Is this a pointer?                                              */
-/* -------------------------------------------------------------------- */
+    // Is this a pointer?
     if( *pszInput == 'p' || *pszInput == '*' )
         chPointer = *(pszInput++);
 
-/* -------------------------------------------------------------------- */
-/*      Get the general type                                            */
-/* -------------------------------------------------------------------- */
+    // Get the general type.
     if( *pszInput == '\0' )
         return NULL;
 
     chItemType = *(pszInput++);
 
-    if ( strchr( "124cCesStlLfdmMbox", chItemType) == NULL )
+    if( strchr("124cCesStlLfdmMbox", chItemType) == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Unrecognized item type : %c", chItemType);
+                 "Unrecognized item type: %c", chItemType);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If this is an object, we extract the type of the object.        */
-/* -------------------------------------------------------------------- */
-    int i;   // TODO: Describe why i needs to span chItemType blocks.
+    // If this is an object, we extract the type of the object.
+    int i = 0;  // TODO: Describe why i needs to span chItemType blocks.
 
     if( chItemType == 'o' )
     {
         for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
-        if (pszInput[i] == '\0')
+        if( pszInput[i] == '\0' )
             return NULL;
 
-        pszItemObjectType = (char *) CPLMalloc(i+1);
-        strncpy( pszItemObjectType, pszInput, i );
+        pszItemObjectType = static_cast<char *>(CPLMalloc(i + 1));
+        strncpy(pszItemObjectType, pszInput, i);
         pszItemObjectType[i] = '\0';
 
-        pszInput += i+1;
+        pszInput += i + 1;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If this is an inline object, we need to skip past the           */
-/*      definition, and then extract the object class name.             */
-/*                                                                      */
-/*      We ignore the actual definition, so if the object type isn't    */
-/*      already defined, things will not work properly.  See the        */
-/*      file lceugr250_00_pct.aux for an example of inline defs.        */
-/* -------------------------------------------------------------------- */
+    // If this is an inline object, we need to skip past the
+    // definition, and then extract the object class name.
+    //
+    // We ignore the actual definition, so if the object type isn't
+    // already defined, things will not work properly.  See the
+    // file lceugr250_00_pct.aux for an example of inline defs.
     if( chItemType == 'x' && *pszInput == '{' )
     {
         int nBraceDepth = 1;
@@ -152,42 +161,41 @@ const char *HFAField::Initialize( const char * pszInput )
 
             pszInput++;
         }
-        if (*pszInput == '\0')
+        if( *pszInput == '\0' )
             return NULL;
 
         chItemType = 'o';
 
-        // find the comma terminating the type name.
+        // Find the comma terminating the type name.
         for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
-        if (pszInput[i] == '\0')
+        if( pszInput[i] == '\0' )
             return NULL;
 
-        pszItemObjectType = (char *) CPLMalloc(i+1);
-        strncpy( pszItemObjectType, pszInput, i );
+        pszItemObjectType = static_cast<char *>(CPLMalloc(i + 1));
+        strncpy(pszItemObjectType, pszInput, i);
         pszItemObjectType[i] = '\0';
 
-        pszInput += i+1;
+        pszInput += i + 1;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If this is an enumeration we have to extract all the            */
-/*      enumeration values.                                             */
-/* -------------------------------------------------------------------- */
+    // If this is an enumeration we have to extract all the
+    // enumeration values.
     if( chItemType == 'e' )
     {
-        int	nEnumCount = atoi(pszInput);
+        const int nEnumCount = atoi(pszInput);
 
-        if (nEnumCount < 0 || nEnumCount > 100000)
+        if( nEnumCount < 0 || nEnumCount > 100000 )
             return NULL;
 
-        pszInput = strchr(pszInput,':');
+        pszInput = strchr(pszInput, ':');
         if( pszInput == NULL )
             return NULL;
 
         pszInput++;
 
-        papszEnumNames = (char **) VSICalloc(sizeof(char *), nEnumCount+1);
-        if (papszEnumNames == NULL)
+        papszEnumNames =
+            static_cast<char **>(VSICalloc(sizeof(char *), nEnumCount + 1));
+        if( papszEnumNames == NULL )
             return NULL;
 
         for( int iEnum = 0; iEnum < nEnumCount; iEnum++ )
@@ -197,30 +205,28 @@ const char *HFAField::Initialize( const char * pszInput )
             if( pszInput[i] != ',' )
                 return NULL;
 
-            char *pszToken = (char *) CPLMalloc(i+1);
-            strncpy( pszToken, pszInput, i );
+            char *pszToken = static_cast<char *>(CPLMalloc(i + 1));
+            strncpy(pszToken, pszInput, i);
             pszToken[i] = '\0';
 
             papszEnumNames[iEnum] = pszToken;
 
-            pszInput += i+1;
+            pszInput += i + 1;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Extract the field name.                                         */
-/* -------------------------------------------------------------------- */
+    // Extract the field name.
     for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
-    if (pszInput[i] == '\0')
+    if( pszInput[i] == '\0' )
         return NULL;
 
-    pszFieldName = (char *) CPLMalloc(i+1);
-    strncpy( pszFieldName, pszInput, i );
+    pszFieldName = static_cast<char *>(CPLMalloc(i + 1));
+    strncpy(pszFieldName, pszInput, i);
     pszFieldName[i] = '\0';
 
-    pszInput += i+1;
+    pszInput += i + 1;
 
-    return( pszInput );
+    return pszInput;
 }
 
 /************************************************************************/
@@ -229,26 +235,22 @@ const char *HFAField::Initialize( const char * pszInput )
 /*      Establish size, and pointers to component types.                */
 /************************************************************************/
 
-void HFAField::CompleteDefn( HFADictionary * poDict )
+void HFAField::CompleteDefn( HFADictionary *poDict )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Get a reference to the type object if we have a type name       */
-/*      for this field (not a built in).                                */
-/* -------------------------------------------------------------------- */
+    // Get a reference to the type object if we have a type name
+    // for this field (not a built in).
     if( pszItemObjectType != NULL )
-        poItemObjectType = poDict->FindType( pszItemObjectType );
+        poItemObjectType = poDict->FindType(pszItemObjectType);
 
-/* -------------------------------------------------------------------- */
-/*      Figure out the size.                                            */
-/* -------------------------------------------------------------------- */
+    // Figure out the size.
     if( chPointer == 'p' )
     {
-        nBytes = -1; /* we can't know the instance size */
+        nBytes = -1;  // We can't know the instance size.
     }
     else if( poItemObjectType != NULL )
     {
-        poItemObjectType->CompleteDefn( poDict );
+        poItemObjectType->CompleteDefn(poDict);
         if( poItemObjectType->nBytes == -1 )
             nBytes = -1;
         else if( poItemObjectType->nBytes != 0 &&
@@ -257,17 +259,18 @@ void HFAField::CompleteDefn( HFADictionary * poDict )
         else
             nBytes = poItemObjectType->nBytes * nItemCount;
 
+        // TODO(schwehr): What does the 8 represent?
         if( chPointer == '*' && nBytes != -1 )
         {
             if( nBytes > INT_MAX - 8 )
                 nBytes = -1;
             else
-                nBytes += 8; /* count, and offset */
+                nBytes += 8;  // Count, and offset.
         }
     }
     else
     {
-        const int nItemSize = poDict->GetItemSize( chItemType );
+        const int nItemSize = poDict->GetItemSize(chItemType);
         if( nItemSize != 0 && nItemCount > INT_MAX / nItemSize )
             nBytes = -1;
         else
@@ -279,101 +282,102 @@ void HFAField::CompleteDefn( HFADictionary * poDict )
 /*                                Dump()                                */
 /************************************************************************/
 
-void HFAField::Dump( FILE * fp )
+void HFAField::Dump( FILE *fp )
 
 {
-    const char	*pszTypeName;
+    const char *pszTypeName;
 
     switch( chItemType )
     {
-      case '1':
+    case '1':
         pszTypeName = "U1";
         break;
 
-      case '2':
+    case '2':
         pszTypeName = "U2";
         break;
 
-      case '4':
+    case '4':
         pszTypeName = "U4";
         break;
 
-      case 'c':
+    case 'c':
         pszTypeName = "UCHAR";
         break;
 
-      case 'C':
+    case 'C':
         pszTypeName = "CHAR";
         break;
 
-      case 'e':
+    case 'e':
         pszTypeName = "ENUM";
         break;
 
-      case 's':
+    case 's':
         pszTypeName = "USHORT";
         break;
 
-      case 'S':
+    case 'S':
         pszTypeName = "SHORT";
         break;
 
-      case 't':
+    case 't':
         pszTypeName = "TIME";
         break;
 
-      case 'l':
+    case 'l':
         pszTypeName = "ULONG";
         break;
 
-      case 'L':
+    case 'L':
         pszTypeName = "LONG";
         break;
 
-      case 'f':
+    case 'f':
         pszTypeName = "FLOAT";
         break;
 
-      case 'd':
+    case 'd':
         pszTypeName = "DOUBLE";
         break;
 
-      case 'm':
+    case 'm':
         pszTypeName = "COMPLEX";
         break;
 
-      case 'M':
+    case 'M':
         pszTypeName = "DCOMPLEX";
         break;
 
-      case 'b':
+    case 'b':
         pszTypeName = "BASEDATA";
         break;
 
-      case 'o':
+    case 'o':
         pszTypeName = pszItemObjectType;
         break;
 
-      case 'x':
+    case 'x':
         pszTypeName = "InlineType";
         break;
 
-      default:
-        CPLAssert( FALSE );
+    default:
+        CPLAssert(false);
         pszTypeName = "Unknown";
     }
 
-    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "    %-19s %c %s[%d];\n",
-                pszTypeName,
-                chPointer ? chPointer : ' ',
-                pszFieldName, nItemCount ));
+    CPL_IGNORE_RET_VAL(
+        VSIFPrintf(fp, "    %-19s %c %s[%d];\n",
+                   pszTypeName,
+                   chPointer ? chPointer : ' ',
+                   pszFieldName, nItemCount));
 
     if( papszEnumNames != NULL )
     {
         for( int i = 0; papszEnumNames[i] != NULL; i++ )
         {
-            CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "        %s=%d\n",
-                        papszEnumNames[i], i ));
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintf(fp, "        %s=%d\n", papszEnumNames[i], i));
         }
     }
 }
@@ -383,64 +387,63 @@ void HFAField::Dump( FILE * fp )
 /************************************************************************/
 
 CPLErr
-HFAField::SetInstValue( const char * pszField, int nIndexValue,
+HFAField::SetInstValue( const char *pszField, int nIndexValue,
                         GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
                         char chReqType, void *pValue )
 
 {
-/* -------------------------------------------------------------------- */
-/*	If this field contains a pointer, then we will adjust the	*/
-/*	data offset relative to it.    					*/
-/* -------------------------------------------------------------------- */
+    // If this field contains a pointer, then we will adjust the
+    // data offset relative to it.
     if( chPointer != '\0' )
     {
-        GUInt32		nCount;
+        GUInt32 nCount = 0;
 
         // The count returned for BASEDATA's are the contents,
         // but here we really want to mark it as one BASEDATA instance
-        // (see #2144)
+        // (see #2144).
         if( chItemType == 'b' )
+        {
             nCount = 1;
-
-        /* Set the size from string length */
+        }
+        // Set the size from string length.
         else if( chReqType == 's' && (chItemType == 'c' || chItemType == 'C'))
         {
-            if( pValue == NULL )
-                nCount = 0;
-            else
-                nCount = static_cast<GUInt32>(strlen((char *) pValue) + 1);
+            if( pValue != NULL )
+                nCount = static_cast<GUInt32>(strlen((char *)pValue) + 1);
         }
-
-        /* set size based on index ... assumes in-order setting of array */
+        // Set size based on index. Assumes in-order setting of array.
         else
-            nCount = nIndexValue+1;
+        {
+            nCount = nIndexValue + 1;
+        }
 
-        if( (int) nCount + 8 > nDataSize )
+        // TODO(schwehr): What does the 8 represent?
+        if( static_cast<int>(nCount) + 8 > nDataSize )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to extend field %s in node past end of data,\n"
-                      "not currently supported.",
-                      pszField );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Attempt to extend field %s in node past end of data, "
+                     "not currently supported.",
+                     pszField);
             return CE_Failure;
         }
 
-        // we will update the object count iff we are writing beyond the end
-        GUInt32		nOffset;
-        memcpy( &nOffset, pabyData, 4 );
-        HFAStandard( 4, &nOffset );
+        // We will update the object count iff we are writing beyond the end.
+        GUInt32 nOffset = 0;
+        memcpy(&nOffset, pabyData, 4);
+        HFAStandard(4, &nOffset);
         if( nOffset < nCount )
         {
             nOffset = nCount;
-            HFAStandard( 4, &nOffset );
-            memcpy( pabyData, &nOffset, 4 );
+            HFAStandard(4, &nOffset);
+            memcpy(pabyData, &nOffset, 4);
         }
 
         if( pValue == NULL )
             nOffset = 0;
         else
             nOffset = nDataOffset + 8;
-        HFAStandard( 4, &nOffset );
-        memcpy( pabyData+4, &nOffset, 4 );
+        HFAStandard(4, &nOffset);
+        memcpy(pabyData + 4, &nOffset, 4);
 
         pabyData += 8;
 
@@ -448,106 +451,103 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
         nDataSize -= 8;
     }
 
-/* -------------------------------------------------------------------- */
-/*      pointers to char or uchar arrays requested as strings are       */
-/*      handled as a special case.                                      */
-/* -------------------------------------------------------------------- */
+    // Pointers to char or uchar arrays requested as strings are
+    // handled as a special case.
     if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' )
     {
-        int	nBytesToCopy;
+        int nBytesToCopy = 0;
 
         if( nBytes == -1 )
         {
-            if( pValue == NULL )
-                nBytesToCopy = 0;
-            else
-                nBytesToCopy = static_cast<int>(strlen((char *) pValue) + 1);
+            if( pValue != NULL )
+                nBytesToCopy = static_cast<int>(strlen((char *)pValue) + 1);
         }
         else
+        {
             nBytesToCopy = nBytes;
+        }
 
         if( nBytesToCopy > nDataSize )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to extend field %s in node past end of data,\n"
-                      "not currently supported.",
-                      pszField );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Attempt to extend field %s in node past end of data "
+                     "not currently supported.",
+                     pszField);
             return CE_Failure;
         }
 
-        memset( pabyData, 0, nBytesToCopy );
+        memset(pabyData, 0, nBytesToCopy);
 
         if( pValue != NULL )
-            strncpy( (char *) pabyData, (char *) pValue, nBytesToCopy );
+            strncpy((char *)pabyData, (char *)pValue, nBytesToCopy);
 
         return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Translate the passed type into different representations.       */
-/* -------------------------------------------------------------------- */
-    int		nIntValue;
-    double      dfDoubleValue;
+    // Translate the passed type into different representations.
+    int nIntValue = 0;
+    double dfDoubleValue = 0.0;
 
     if( chReqType == 's' )
     {
-        CPLAssert( pValue != NULL );
-        nIntValue = atoi((char *) pValue);
-        dfDoubleValue = CPLAtof((char *) pValue);
+        CPLAssert(pValue != NULL);
+        nIntValue = atoi((char *)pValue);
+        dfDoubleValue = CPLAtof((char *)pValue);
     }
     else if( chReqType == 'd' )
     {
-        CPLAssert( pValue != NULL );
-        dfDoubleValue = *((double *) pValue);
+        CPLAssert(pValue != NULL);
+        dfDoubleValue = *((double *)pValue);
         if( dfDoubleValue > INT_MAX )
             nIntValue = INT_MAX;
         else if( dfDoubleValue < INT_MIN )
             nIntValue = INT_MIN;
         else
-            nIntValue = (int) dfDoubleValue;
+            nIntValue = static_cast<int>(dfDoubleValue);
     }
     else if( chReqType == 'i' )
     {
-        CPLAssert( pValue != NULL );
-        nIntValue = *((int *) pValue);
+        CPLAssert(pValue != NULL);
+        nIntValue = *((int *)pValue);
         dfDoubleValue = nIntValue;
     }
     else if( chReqType == 'p' )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-            "HFAField::SetInstValue() not supported yet for pointer values." );
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "HFAField::SetInstValue() not supported yet for pointer values.");
 
         return CE_Failure;
     }
     else
     {
-        CPLAssert( FALSE );
+        CPLAssert(false);
         return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Handle by type.                                                 */
-/* -------------------------------------------------------------------- */
+    // Handle by type.
     switch( chItemType )
     {
       case 'c':
       case 'C':
         if( nIndexValue + 1 > nDataSize )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to extend field %s in node past end of data,\n"
-                      "not currently supported.",
-                      pszField );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Attempt to extend field %s in node past end of data, "
+                     "not currently supported.",
+                     pszField);
               return CE_Failure;
         }
 
         if( chReqType == 's' )
         {
-            CPLAssert( pValue != NULL );
-            pabyData[nIndexValue] = ((char *) pValue)[0];
+            CPLAssert(pValue != NULL);
+            pabyData[nIndexValue] = ((char *)pValue)[0];
         }
         else
-            pabyData[nIndexValue] = (char) nIntValue;
+        {
+            pabyData[nIndexValue] = static_cast<char>(nIntValue);
+        }
         break;
 
       case 'e':
@@ -555,145 +555,146 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
       {
           if( chItemType == 'e' && chReqType == 's' )
           {
-              CPLAssert( pValue != NULL );
-              nIntValue = CSLFindString( papszEnumNames, (char *) pValue );
+              CPLAssert(pValue != NULL);
+              nIntValue = CSLFindString(papszEnumNames, (char *) pValue);
               if( nIntValue == -1 )
               {
-                  CPLError( CE_Failure, CPLE_AppDefined,
+                  CPLError(CE_Failure, CPLE_AppDefined,
                             "Attempt to set enumerated field with unknown"
                             " value `%s'.",
-                            (char *) pValue );
+                            (char *)pValue);
                   return CE_Failure;
               }
           }
 
-          unsigned short nNumber = (unsigned short) nIntValue;
-
           if( nIndexValue*2 + 2 > nDataSize )
           {
-              CPLError( CE_Failure, CPLE_AppDefined,
-                        "Attempt to extend field %s in node past end of data,\n"
-                        "not currently supported.",
-                        pszField );
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Attempt to extend field %s in node past end of data, "
+                       "not currently supported.",
+                       pszField);
               return CE_Failure;
           }
 
-          HFAStandard( 2, &nNumber );
-          memcpy( pabyData + nIndexValue*2, &nNumber, 2 );
+          // TODO(schwehr): Warn on clamping.
+          unsigned short nNumber = static_cast<unsigned short>(nIntValue);
+          // TODO(schwehr): What is this 2?
+          HFAStandard(2, &nNumber);
+          memcpy(pabyData + nIndexValue * 2, &nNumber, 2);
       }
       break;
 
       case 'S':
       {
-          short nNumber;
-
-          if( nIndexValue*2 + 2 > nDataSize )
+          if( nIndexValue * 2 + 2 > nDataSize )
           {
-              CPLError( CE_Failure, CPLE_AppDefined,
-                        "Attempt to extend field %s in node past end of data,\n"
-                        "not currently supported.",
-                        pszField );
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Attempt to extend field %s in node past end of data, "
+                       "not currently supported.",
+                       pszField);
               return CE_Failure;
           }
 
-          nNumber = (short) nIntValue;
-          HFAStandard( 2, &nNumber );
-          memcpy( pabyData + nIndexValue*2, &nNumber, 2 );
+          // TODO(schwehr): Warn on clamping.
+          short nNumber = static_cast<short>(nIntValue);
+          // TODO(schwehr): What is this 2?
+          HFAStandard(2, &nNumber);
+          memcpy(pabyData + nIndexValue * 2, &nNumber, 2);
       }
       break;
 
       case 't':
       case 'l':
       {
-          GUInt32	nNumber = nIntValue;
-
-          if( nIndexValue*4 + 4 > nDataSize )
+          if( nIndexValue * 4 + 4 > nDataSize )
           {
-              CPLError( CE_Failure, CPLE_AppDefined,
-                        "Attempt to extend field %s in node past end of data,\n"
-                        "not currently supported.",
-                        pszField );
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Attempt to extend field %s in node past end of data, "
+                       "not currently supported.",
+                       pszField);
               return CE_Failure;
           }
 
-          HFAStandard( 4, &nNumber );
-          memcpy( pabyData + nIndexValue*4, &nNumber, 4 );
+          GUInt32 nNumber = nIntValue;
+          // TODO(schwehr): What is this 4?
+          HFAStandard(4, &nNumber);
+          memcpy(pabyData + nIndexValue * 4, &nNumber, 4);
       }
       break;
 
       case 'L':
       {
-          GInt32	nNumber = nIntValue;
-
-          if( nIndexValue*4 + 4 > nDataSize )
+          if( nIndexValue * 4 + 4 > nDataSize )
           {
-              CPLError( CE_Failure, CPLE_AppDefined,
-                        "Attempt to extend field %s in node past end of data,\n"
-                        "not currently supported.",
-                        pszField );
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Attempt to extend field %s in node past end of data, "
+                       "not currently supported.",
+                       pszField);
               return CE_Failure;
           }
 
-          HFAStandard( 4, &nNumber );
-          memcpy( pabyData + nIndexValue*4, &nNumber, 4 );
+          GInt32 nNumber = nIntValue;
+          HFAStandard(4, &nNumber);
+          memcpy(pabyData + nIndexValue * 4, &nNumber, 4);
       }
       break;
 
       case 'f':
       {
-          float		fNumber = (float) dfDoubleValue;
-
-          if( nIndexValue*4 + 4 > nDataSize )
+          if( nIndexValue * 4 + 4 > nDataSize )
           {
-              CPLError( CE_Failure, CPLE_AppDefined,
-                        "Attempt to extend field %s in node past end of data,\n"
-                        "not currently supported.",
-                        pszField );
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Attempt to extend field %s in node past end of data, "
+                       "not currently supported.",
+                       pszField);
               return CE_Failure;
           }
 
-          HFAStandard( 4, &fNumber );
-          memcpy( pabyData + nIndexValue*4, &fNumber, 4 );
+          // TODO(schwehr): Warn on clamping.
+          float fNumber = static_cast<float>(dfDoubleValue);
+          // TODO(schwehr): 4 == sizeof(float)?
+          HFAStandard(4, &fNumber);
+          memcpy(pabyData + nIndexValue * 4, &fNumber, 4);
       }
       break;
 
       case 'd':
       {
-          double	dfNumber = dfDoubleValue;
-
-          if( nIndexValue*8 + 8 > nDataSize )
+          if( nIndexValue * 8 + 8 > nDataSize )
           {
-              CPLError( CE_Failure, CPLE_AppDefined,
-                        "Attempt to extend field %s in node past end of data,\n"
-                        "not currently supported.",
-                        pszField );
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Attempt to extend field %s in node past end of data, "
+                       "not currently supported.",
+                       pszField);
               return CE_Failure;
           }
 
-          HFAStandard( 8, &dfNumber );
-          memcpy( pabyData + nIndexValue*8, &dfNumber, 8 );
+          double dfNumber = dfDoubleValue;
+          HFAStandard(8, &dfNumber);
+          memcpy(pabyData + nIndexValue * 8, &dfNumber, 8);
       }
       break;
 
     case 'b':
     {
-        GInt32 nRows = 1;
-        GInt32 nColumns = 1;
-        GInt16 nBaseItemType;
-
         // Extract existing rows, columns, and datatype.
-        memcpy( &nRows, pabyData, 4 );
-        HFAStandard( 4, &nRows );
-        memcpy( &nColumns, pabyData+4, 4 );
-        HFAStandard( 4, &nColumns );
-        memcpy( &nBaseItemType, pabyData+8, 2 );
-        HFAStandard( 2, &nBaseItemType );
-
-        // Are we using special index values to update the rows, columnrs
+        GInt32 nRows = 1;  // TODO(schwehr): Why init to 1 instead of 0?
+        memcpy(&nRows, pabyData, 4);
+        HFAStandard(4, &nRows);
+
+        GInt32 nColumns = 1;  // TODO(schwehr): Why init to 1 instead of 0?
+        memcpy(&nColumns, pabyData + 4, 4);
+        HFAStandard(4, &nColumns);
+
+        GInt16 nBaseItemType = 0;
+        memcpy(&nBaseItemType, pabyData + 8, 2);
+        HFAStandard(2, &nBaseItemType);
+
+        // Are we using special index values to update the rows, columns
         // or type?
 
         if( nIndexValue == -3 )
-            nBaseItemType = (GInt16) nIntValue;
+            nBaseItemType = static_cast<GInt16>(nIntValue);
         else if( nIndexValue == -2 )
             nColumns = nIntValue;
         else if( nIndexValue == -1 )
@@ -703,17 +704,17 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
             return CE_Failure;
 
         // Write back the rows, columns and basedatatype.
-        HFAStandard( 4, &nRows );
-        memcpy( pabyData, &nRows, 4 );
-        HFAStandard( 4, &nColumns );
-        memcpy( pabyData+4, &nColumns, 4 );
-        HFAStandard( 2, &nBaseItemType );
-        memcpy ( pabyData + 8, &nBaseItemType, 2 );
-        HFAStandard( 2, &nBaseItemType ); // swap back for our use.
+        HFAStandard(4, &nRows);
+        memcpy(pabyData, &nRows, 4);
+        HFAStandard(4, &nColumns);
+        memcpy(pabyData + 4, &nColumns, 4);
+        HFAStandard(2, &nBaseItemType);
+        memcpy(pabyData + 8, &nBaseItemType, 2);
+        HFAStandard(2, &nBaseItemType);  // Swap back for our use.
 
         if( nBaseItemType < EPT_MIN || nBaseItemType > EPT_MAX )
             return CE_Failure;
-        EPTType eBaseItemType = static_cast<EPTType>(nBaseItemType);
+        const EPTType eBaseItemType = static_cast<EPTType>(nBaseItemType);
 
         // We ignore the 2 byte objecttype value.
 
@@ -721,13 +722,13 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
 
         if( nIndexValue >= 0 )
         {
-            if( (nIndexValue+1) * (HFAGetDataTypeBits(eBaseItemType)/8)
+            if( (nIndexValue + 1) * (HFAGetDataTypeBits(eBaseItemType) / 8)
                 > nDataSize )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Attempt to extend field %s in node past end of data,\n"
-                          "not currently supported.",
-                          pszField );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Attempt to extend field %s in node past end of "
+                         "data, not currently supported.",
+                         pszField);
                 return CE_Failure;
             }
 
@@ -735,19 +736,22 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
             {
                 double dfNumber = dfDoubleValue;
 
-                HFAStandard( 8, &dfNumber );
-                memcpy( pabyData + 12 + nIndexValue * 8, &dfNumber, 8 );
+                HFAStandard(8, &dfNumber);
+                memcpy(pabyData + 12 + nIndexValue * 8, &dfNumber, 8);
             }
-            else if (eBaseItemType == EPT_u8)
+            else if( eBaseItemType == EPT_u8 )
             {
-                unsigned char nNumber = (unsigned char)dfDoubleValue;
-                memcpy( pabyData + 12 + nIndexValue, &nNumber, 1);
+                // TODO(schwehr): Warn on clamping.
+                unsigned char nNumber =
+                    static_cast<unsigned char>(dfDoubleValue);
+                memcpy(pabyData + 12 + nIndexValue, &nNumber, 1);
             }
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Setting basedata field %s with type %s not currently supported.",
-                          pszField, HFAGetDataTypeName( eBaseItemType ) );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Setting basedata field %s with type %s "
+                         "not currently supported.",
+                         pszField, HFAGetDataTypeName(eBaseItemType));
                 return CE_Failure;
             }
         }
@@ -757,26 +761,31 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
       case 'o':
         if( poItemObjectType != NULL )
         {
-            int		nExtraOffset = 0;
-            int		iIndexCounter;
+            int nExtraOffset = 0;
 
             if( poItemObjectType->nBytes > 0 )
             {
-                if (nIndexValue != 0 && poItemObjectType->nBytes > INT_MAX / nIndexValue)
+                if( nIndexValue != 0 &&
+                    poItemObjectType->nBytes > INT_MAX / nIndexValue )
+                {
                     return CE_Failure;
+                }
                 nExtraOffset = poItemObjectType->nBytes * nIndexValue;
             }
             else
             {
-                for( iIndexCounter = 0;
+                for( int iIndexCounter = 0;
                      iIndexCounter < nIndexValue && nExtraOffset < nDataSize;
                      iIndexCounter++ )
                 {
-                    int nInc = poItemObjectType->GetInstBytes(pabyData + nExtraOffset,
-                                                              nDataSize - nExtraOffset);
-                    if (nInc < 0 || nExtraOffset > INT_MAX - nInc)
+                    const int nInc =
+                        poItemObjectType->
+                            GetInstBytes(pabyData + nExtraOffset,
+                                         nDataSize - nExtraOffset);
+                    if( nInc < 0 || nExtraOffset > INT_MAX - nInc )
                     {
-                        CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Invalid return value");
                         return CE_Failure;
                     }
 
@@ -784,27 +793,27 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
                 }
             }
 
-            if (nExtraOffset >= nDataSize)
+            if( nExtraOffset >= nDataSize )
                 return CE_Failure;
 
             if( pszField != NULL && strlen(pszField) > 0 )
             {
-                return( poItemObjectType->
-                            SetInstValue( pszField, pabyData + nExtraOffset,
-                                          nDataOffset + nExtraOffset,
-                                          nDataSize - nExtraOffset,
-                                          chReqType, pValue ) );
+                return poItemObjectType->
+                    SetInstValue(pszField, pabyData + nExtraOffset,
+                                 nDataOffset + nExtraOffset,
+                                 nDataSize - nExtraOffset,
+                                 chReqType, pValue);
             }
             else
             {
-                CPLAssert( FALSE );
+                CPLAssert(false);
                 return CE_Failure;
             }
         }
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert(false);
         return CE_Failure;
         break;
     }
@@ -821,90 +830,83 @@ HFAField::SetInstValue( const char * pszField, int nIndexValue,
 /*      substructure.                                                   */
 /************************************************************************/
 
-int
-HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
-                           GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
-                           char chReqType, void *pReqReturn, int *pnRemainingDataSize )
+bool
+HFAField::ExtractInstValue( const char *pszField, int nIndexValue,
+                            GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
+                            char chReqType, void *pReqReturn,
+                            int *pnRemainingDataSize )
 
 {
-    char		*pszStringRet = NULL;
-    int			nIntRet = 0;
-    double		dfDoubleRet = 0.0;
-    int			nInstItemCount = GetInstCount( pabyData, nDataSize );
-    GByte		*pabyRawData = NULL;
+    const int nInstItemCount = GetInstCount(pabyData, nDataSize);
 
-    if (pnRemainingDataSize)
+    if( pnRemainingDataSize )
         *pnRemainingDataSize = -1;
 
-/* -------------------------------------------------------------------- */
-/*      Check the index value is valid.                                 */
-/*                                                                      */
-/*      Eventually this will have to account for variable fields.       */
-/* -------------------------------------------------------------------- */
+    // Check the index value is valid.
+    // Eventually this will have to account for variable fields.
     if( nIndexValue < 0 || nIndexValue >= nInstItemCount )
     {
         if( chItemType == 'b' && nIndexValue >= -3 && nIndexValue < 0 )
             /* ok - special index values */;
         else
-            return FALSE;
+            return false;
     }
 
-/* -------------------------------------------------------------------- */
-/*	If this field contains a pointer, then we will adjust the	*/
-/*	data offset relative to it.    					*/
-/* -------------------------------------------------------------------- */
+    // If this field contains a pointer, then we will adjust the
+    // data offset relative to it.
     if( chPointer != '\0' )
     {
-        GUInt32		nOffset;
-
-        if (nDataSize < 8)
+        if( nDataSize < 8 )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-            return FALSE;
+            return false;
         }
 
-        memcpy( &nOffset, pabyData+4, 4 );
-        HFAStandard( 4, &nOffset );
+        GUInt32 nOffset = 0;
+        memcpy(&nOffset, pabyData + 4, 4);
+        HFAStandard(4, &nOffset);
 
-        if( nOffset != (GUInt32) (nDataOffset + 8) )
+#if DEBUG_VERBOSE
+        if( nOffset != static_cast<GUInt32>(nDataOffset + 8) )
         {
-#ifdef notdef
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "%s.%s points at %d, not %d as expected\n",
-                      pszFieldName, pszField ? pszField : "",
-                      nOffset, nDataOffset+8 );
-#endif
+            // TODO(schwehr): Debug why this is happening.
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "ExtractInstValue: "
+                     "%s.%s points at %d, not %d as expected",
+                     pszFieldName, pszField ? pszField : "",
+                     nOffset, nDataOffset + 8);
         }
+#endif
 
         pabyData += 8;
-
         nDataOffset += 8;
         nDataSize -= 8;
     }
 
-/* -------------------------------------------------------------------- */
-/*      pointers to char or uchar arrays requested as strings are       */
-/*      handled as a special case.                                      */
-/* -------------------------------------------------------------------- */
+    // Pointers to char or uchar arrays requested as strings are
+    // handled as a special case.
     if( (chItemType == 'c' || chItemType == 'C') && chReqType == 's' )
     {
         *((GByte **)pReqReturn) = pabyData;
-        if (pnRemainingDataSize)
+        if( pnRemainingDataSize )
             *pnRemainingDataSize = nDataSize;
-        return( pabyData != NULL );
+        return pabyData != NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Handle by type.                                                 */
-/* -------------------------------------------------------------------- */
+    // Handle by type.
+    char *pszStringRet = NULL;
+    int nIntRet = 0;
+    double dfDoubleRet = 0.0;
+    GByte *pabyRawData = NULL;
+
     switch( chItemType )
     {
       case 'c':
       case 'C':
-        if (nIndexValue >= nDataSize)
+        if( nIndexValue >= nDataSize )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-            return FALSE;
+            return false;
         }
         nIntRet = pabyData[nIndexValue];
         dfDoubleRet = nIntRet;
@@ -913,14 +915,14 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
       case 'e':
       case 's':
       {
-          unsigned short nNumber;
-          if (nIndexValue*2 + 2 > nDataSize)
+          if( nIndexValue * 2 + 2 > nDataSize )
           {
               CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-              return FALSE;
+              return false;
           }
-          memcpy( &nNumber, pabyData + nIndexValue*2, 2 );
-          HFAStandard( 2, &nNumber );
+          unsigned short nNumber = 0;
+          memcpy(&nNumber, pabyData + nIndexValue * 2, 2);
+          HFAStandard(2, &nNumber);
           nIntRet = nNumber;
           dfDoubleRet = nIntRet;
 
@@ -934,14 +936,14 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
 
       case 'S':
       {
-          short nNumber;
-          if (nIndexValue*2 + 2 > nDataSize)
+          if( nIndexValue * 2 + 2 > nDataSize )
           {
               CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-              return FALSE;
+              return false;
           }
-          memcpy( &nNumber, pabyData + nIndexValue*2, 2 );
-          HFAStandard( 2, &nNumber );
+          short nNumber = 0;
+          memcpy(&nNumber, pabyData + nIndexValue * 2, 2);
+          HFAStandard(2, &nNumber);
           nIntRet = nNumber;
           dfDoubleRet = nIntRet;
       }
@@ -950,14 +952,14 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
       case 't':
       case 'l':
       {
-          GUInt32	nNumber;
-          if (nIndexValue*4 + 4 > nDataSize)
+          if( nIndexValue * 4 + 4 > nDataSize )
           {
               CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-              return FALSE;
+              return false;
           }
-          memcpy( &nNumber, pabyData + nIndexValue*4, 4 );
-          HFAStandard( 4, &nNumber );
+          GUInt32 nNumber = 0;
+          memcpy(&nNumber, pabyData + nIndexValue * 4, 4);
+          HFAStandard(4, &nNumber);
           nIntRet = nNumber;
           dfDoubleRet = nIntRet;
       }
@@ -965,14 +967,15 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
 
       case 'L':
       {
-          GInt32	nNumber;
-          if (nIndexValue*4 + 4 > nDataSize)
+          if( nIndexValue * 4 + 4 > nDataSize )
           {
               CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-              return FALSE;
+              return false;
           }
-          memcpy( &nNumber, pabyData + nIndexValue*4, 4 );
-          HFAStandard( 4, &nNumber );
+          GInt32 nNumber = 0;
+          // TODO(schwehr): What is 4?
+          memcpy(&nNumber, pabyData + nIndexValue * 4, 4);
+          HFAStandard(4, &nNumber);
           nIntRet = nNumber;
           dfDoubleRet = nIntRet;
       }
@@ -980,48 +983,67 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
 
       case 'f':
       {
-          float		fNumber;
-          if (nIndexValue*4 + 4 > nDataSize)
+          if( nIndexValue * 4 + 4 > nDataSize )
           {
               CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-              return FALSE;
+              return false;
           }
-          memcpy( &fNumber, pabyData + nIndexValue*4, 4 );
-          HFAStandard( 4, &fNumber );
+          float fNumber = 0.0f;
+          // TODO(schwehr): What is 4?
+          memcpy(&fNumber, pabyData + nIndexValue * 4, 4);
+          HFAStandard(4, &fNumber);
           dfDoubleRet = fNumber;
-          nIntRet = (int) fNumber;
+          if( fNumber > std::numeric_limits<int>::max() ||
+              fNumber < std::numeric_limits<int>::min() ||
+              CPLIsNan(fNumber) )
+          {
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Too large for int: %f", fNumber);
+              return false;
+          }
+          nIntRet = static_cast<int>(fNumber);
       }
       break;
 
       case 'd':
       {
-          double	dfNumber;
-          if (nIndexValue*8 + 8 > nDataSize)
+          if( nIndexValue * 8 + 8 > nDataSize )
           {
               CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-              return FALSE;
+              return false;
           }
-          memcpy( &dfNumber, pabyData + nIndexValue*8, 8 );
-          HFAStandard( 8, &dfNumber );
+          double dfNumber = 0;
+          memcpy(&dfNumber, pabyData + nIndexValue * 8, 8);
+          HFAStandard(8, &dfNumber);
           dfDoubleRet = dfNumber;
-          nIntRet = (int) dfNumber;
+          if( dfNumber > std::numeric_limits<int>::max() ||
+              dfNumber < std::numeric_limits<int>::min() ||
+              CPLIsNan(dfNumber) )
+          {
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Too large for int: %f", dfNumber);
+              return false;
+          }
+          nIntRet = static_cast<int>(dfNumber);
       }
       break;
 
       case 'b':
       {
-          GInt32 nRows, nColumns;
-          GInt16 nBaseItemType;
-
           if( nDataSize < 12 )
-              return FALSE;
-
-          memcpy( &nRows, pabyData, 4 );
-          HFAStandard( 4, &nRows );
-          memcpy( &nColumns, pabyData+4, 4 );
-          HFAStandard( 4, &nColumns );
-          memcpy( &nBaseItemType, pabyData+8, 2 );
-          HFAStandard( 2, &nBaseItemType );
+              return false;
+
+          GInt32 nRows = 0;
+          memcpy(&nRows, pabyData, 4);
+          HFAStandard(4, &nRows);
+
+          GInt32 nColumns = 0;
+          memcpy(&nColumns, pabyData + 4, 4);
+          HFAStandard(4, &nColumns);
+
+          GInt16 nBaseItemType = 0;
+          memcpy(&nBaseItemType, pabyData + 8, 2);
+          HFAStandard(2, &nBaseItemType);
           // We ignore the 2 byte objecttype value.
 
           if( nIndexValue < -3 ||
@@ -1029,32 +1051,36 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
               nColumns <= 0 ||
               nRows > INT_MAX / nColumns ||
               nIndexValue >= nRows * nColumns )
-              return FALSE;
+              return false;
 
           pabyData += 12;
           nDataSize -= 12;
 
           if( nIndexValue == -3 )
           {
-              dfDoubleRet = nIntRet = nBaseItemType;
+              dfDoubleRet = nBaseItemType;
+              nIntRet = nBaseItemType;
           }
           else if( nIndexValue == -2 )
           {
-              dfDoubleRet = nIntRet = nColumns;
+              dfDoubleRet = nColumns;
+              nIntRet = nColumns;
           }
           else if( nIndexValue == -1 )
           {
-              dfDoubleRet = nIntRet = nRows;
+              dfDoubleRet = nRows;
+              nIntRet = nRows;
           }
           else if( nBaseItemType == EPT_u1 )
           {
-              if (nIndexValue*8 >= nDataSize)
+              // TODO(schwehr): What are these constants like 8 and 0x7?
+              if( nIndexValue * 8 >= nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
 
-              if( pabyData[nIndexValue>>3] & (1 << (nIndexValue & 0x7)) )
+              if( pabyData[nIndexValue >> 3] & (1 << (nIndexValue & 0x7)) )
               {
                   dfDoubleRet = 1;
                   nIntRet = 1;
@@ -1067,147 +1093,162 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
           }
           else if( nBaseItemType == EPT_u2 )
           {
-              int nBitOffset = nIndexValue & 0x3;
-              int nByteOffset = nIndexValue >> 2;
-              int nMask = 0x3;
+              const int nBitOffset = nIndexValue & 0x3;
+              const int nByteOffset = nIndexValue >> 2;
 
-              if (nByteOffset >= nDataSize)
+              if( nByteOffset >= nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
 
+              const int nMask = 0x3;
               nIntRet = (pabyData[nByteOffset] >> nBitOffset) & nMask;
               dfDoubleRet = nIntRet;
           }
           else if( nBaseItemType == EPT_u4 )
           {
-              int nBitOffset = nIndexValue & 0x7;
-              int nByteOffset = nIndexValue >> 3;
-              int nMask = 0x7;
+              const int nBitOffset = nIndexValue & 0x7;
+              const int nByteOffset = nIndexValue >> 3;
 
-              if (nByteOffset >= nDataSize)
+              if( nByteOffset >= nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
 
+              const int nMask = 0x7;
               nIntRet = (pabyData[nByteOffset] >> nBitOffset) & nMask;
               dfDoubleRet = nIntRet;
           }
           else if( nBaseItemType == EPT_u8 )
           {
-              if (nIndexValue >= nDataSize)
+              if( nIndexValue >= nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
               dfDoubleRet = pabyData[nIndexValue];
               nIntRet = pabyData[nIndexValue];
           }
           else if( nBaseItemType == EPT_s8 )
           {
-              if (nIndexValue >= nDataSize)
+              if( nIndexValue >= nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
               dfDoubleRet = ((signed char *)pabyData)[nIndexValue];
               nIntRet = ((signed char *)pabyData)[nIndexValue];
           }
           else if( nBaseItemType == EPT_s16 )
           {
-              GInt16  nValue;
-              if (nIndexValue*2 + 2 > nDataSize)
+              if( nIndexValue * 2 + 2 > nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
-              memcpy( &nValue, pabyData + 2*nIndexValue, 2 );
-              HFAStandard( 2, &nValue );
+              GInt16 nValue = 0;
+              memcpy(&nValue, pabyData + 2 * nIndexValue, 2);
+              HFAStandard(2, &nValue);
 
               dfDoubleRet = nValue;
               nIntRet = nValue;
           }
           else if( nBaseItemType == EPT_u16 )
           {
-              GUInt16  nValue;
-              if (nIndexValue*2 + 2 > nDataSize)
+              if( nIndexValue * 2 + 2 > nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
-              memcpy( &nValue, pabyData + 2*nIndexValue, 2 );
-              HFAStandard( 2, &nValue );
+              GUInt16 nValue = 0;
+              memcpy(&nValue, pabyData + 2 * nIndexValue, 2);
+              HFAStandard(2, &nValue);
 
               dfDoubleRet = nValue;
               nIntRet = nValue;
           }
           else if( nBaseItemType == EPT_s32 )
           {
-              GInt32  nValue;
-              if (nIndexValue*4 + 4 > nDataSize)
+              if( nIndexValue * 4 + 4 > nDataSize)
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
-              memcpy( &nValue, pabyData + 4*nIndexValue, 4 );
-              HFAStandard( 4, &nValue );
+              GInt32 nValue = 0;
+              memcpy(&nValue, pabyData + 4 * nIndexValue, 4);
+              HFAStandard(4, &nValue);
 
               dfDoubleRet = nValue;
               nIntRet = nValue;
           }
           else if( nBaseItemType == EPT_u32 )
           {
-              GUInt32  nValue;
-              if (nIndexValue*4 + 4 > nDataSize)
+              if( nIndexValue * 4 + 4 > nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
-              memcpy( &nValue, pabyData + 4*nIndexValue, 4 );
-              HFAStandard( 4, &nValue );
+              GUInt32 nValue = 0;
+              memcpy(&nValue, pabyData + 4 * nIndexValue, 4);
+              HFAStandard(4, &nValue);
 
               dfDoubleRet = nValue;
               nIntRet = nValue;
           }
           else if( nBaseItemType == EPT_f32 )
           {
-              float fValue;
-              if (nIndexValue*4 + 4 > nDataSize)
+              if( nIndexValue * 4 + 4 > nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
-              memcpy( &fValue, pabyData + 4*nIndexValue, 4 );
-              HFAStandard( 4, &fValue );
+              float fValue = 0.0f;
+              memcpy(&fValue, pabyData + 4 * nIndexValue, 4);
+              HFAStandard(4, &fValue);
 
               dfDoubleRet = fValue;
-              nIntRet = (int) fValue;
+              nIntRet = static_cast<int>(fValue);
           }
           else if( nBaseItemType == EPT_f64 )
           {
-              double dfValue;
-              if (nIndexValue*8 + 8 > nDataSize)
+              if( nIndexValue * 8 + 8 > nDataSize )
               {
                   CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
-                  return FALSE;
+                  return false;
               }
-              memcpy( &dfValue, pabyData+8*nIndexValue, 8 );
-              HFAStandard( 8, &dfValue );
+              double dfValue = 0.0;
+              memcpy(&dfValue, pabyData + 8 * nIndexValue, 8);
+              HFAStandard(8, &dfValue);
 
               dfDoubleRet = dfValue;
-              if( dfDoubleRet > INT_MAX )
-                  nIntRet = INT_MAX;
-              else if( dfDoubleRet < INT_MIN )
-                  nIntRet = INT_MIN;
+              const int nMax = std::numeric_limits<int>::max();
+              const int nMin = std::numeric_limits<int>::min();
+              if( dfDoubleRet >= nMax )
+              {
+                  nIntRet = nMax;
+              }
+              else if( dfDoubleRet <= nMin )
+              {
+                  nIntRet = nMin;
+              }
+              else if( CPLIsNan(dfDoubleRet) )
+              {
+                  CPLError(CE_Warning, CPLE_AppDefined,
+                           "NaN converted to INT_MAX.");
+                  nIntRet = nMax;
+              }
               else
-                  nIntRet = (int) dfDoubleRet;
+              {
+                  nIntRet = static_cast<int>(dfDoubleRet);
+              }
           }
           else
           {
-              CPLError(CE_Failure, CPLE_AppDefined, "Unknown base item type : %d", nBaseItemType);
-              return FALSE;
+              CPLError(CE_Failure, CPLE_AppDefined,
+                       "Unknown base item type: %d", nBaseItemType);
+              return false;
           }
       }
       break;
@@ -1215,92 +1256,99 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
       case 'o':
         if( poItemObjectType != NULL )
         {
-            int		nExtraOffset = 0;
-            int		iIndexCounter;
+            int nExtraOffset = 0;
 
             if( poItemObjectType->nBytes > 0 )
             {
-                if (nIndexValue != 0 && poItemObjectType->nBytes > INT_MAX / nIndexValue)
-                    return CE_Failure;
+                if( nIndexValue != 0 &&
+                    poItemObjectType->nBytes > INT_MAX / nIndexValue )
+                    // TODO(schwehr): Why was this CE_Failure when the others
+                    // are false?
+                    return false;
                 nExtraOffset = poItemObjectType->nBytes * nIndexValue;
             }
             else
             {
-                for( iIndexCounter = 0;
+                for( int iIndexCounter = 0;
                      iIndexCounter < nIndexValue && nExtraOffset < nDataSize;
                      iIndexCounter++ )
                 {
-                    int nInc = poItemObjectType->GetInstBytes(pabyData + nExtraOffset,
-                                                              nDataSize - nExtraOffset);
-                    if (nInc < 0 || nExtraOffset > INT_MAX - nInc)
+                    const int nInc =
+                        poItemObjectType->GetInstBytes(
+                            pabyData + nExtraOffset,
+                            nDataSize - nExtraOffset);
+                    if( nInc < 0 || nExtraOffset > INT_MAX - nInc )
                     {
-                        CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
-                        return CE_Failure;
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Invalid return value");
+                        // TODO(schwehr): Verify this false is okay.
+                        return false;
                     }
 
                     nExtraOffset += nInc;
                 }
             }
 
-            if (nExtraOffset >= nDataSize)
-                return CE_Failure;
+            if( nExtraOffset >= nDataSize )
+                return false;
 
             pabyRawData = pabyData + nExtraOffset;
 
             if( pszField != NULL && strlen(pszField) > 0 )
             {
-                return( poItemObjectType->
-                        ExtractInstValue( pszField, pabyRawData,
+                return
+                    poItemObjectType->
+                        ExtractInstValue(pszField, pabyRawData,
                                           nDataOffset + nExtraOffset,
                                           nDataSize - nExtraOffset,
-                                          chReqType, pReqReturn, pnRemainingDataSize ) );
+                                          chReqType, pReqReturn,
+                                          pnRemainingDataSize);
             }
         }
         break;
 
       default:
-        return FALSE;
+        return false;
         break;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Return the appropriate representation.                          */
-/* -------------------------------------------------------------------- */
+    // Return the appropriate representation.
     if( chReqType == 's' )
     {
         if( pszStringRet == NULL )
         {
-            /* HFAEntry:: BuildEntryFromMIFObject() expects to have always */
-            /* 8 bytes before the data. In normal situations, it should */
-            /* not go here, but that can happen if the file is corrupted */
-            /* so reserve the first 8 bytes before the string to contain null bytes */
+            // HFAEntry:: BuildEntryFromMIFObject() expects to have always 8
+            // bytes before the data. In normal situations, it should not go
+            // here, but that can happen if the file is corrupted so reserve the
+            // first 8 bytes before the string to contain null bytes.
             memset(szNumberString, 0, 8);
-            CPLsnprintf( szNumberString + 8, sizeof(szNumberString) - 8, "%.14g", dfDoubleRet );
+            CPLsnprintf(szNumberString + 8, sizeof(szNumberString) - 8,
+                        "%.14g", dfDoubleRet);
             pszStringRet = szNumberString + 8;
         }
 
-        *((char **) pReqReturn) = pszStringRet;
-        return( TRUE );
+        *((char **)pReqReturn) = pszStringRet;
+        return true;
     }
     else if( chReqType == 'd' )
     {
         *((double *)pReqReturn) = dfDoubleRet;
-        return( TRUE );
+        return true;
     }
     else if( chReqType == 'i' )
     {
-        *((int *) pReqReturn) = nIntRet;
-        return( TRUE );
+        *((int *)pReqReturn) = nIntRet;
+        return true;
     }
     else if( chReqType == 'p' )
     {
-        *((GByte **) pReqReturn) = pabyRawData;
-        return( TRUE );
+        *((GByte **)pReqReturn) = pabyRawData;
+        return true;
     }
     else
     {
-        CPLAssert( FALSE );
-        return FALSE;
+        CPLAssert(false);
+        return false;
     }
 }
 
@@ -1316,61 +1364,64 @@ HFAField::ExtractInstValue( const char * pszField, int nIndexValue,
 int HFAField::GetInstBytes( GByte *pabyData, int nDataSize )
 
 {
-    int		nCount;
-    int		nInstBytes = 0;
-
     if( nBytes > -1 )
         return nBytes;
 
+    int nCount = 1;
+    int nInstBytes = 0;
+
     if( chPointer != '\0' )
     {
-        if (nDataSize < 4)
+        if( nDataSize < 4 )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
             return -1;
         }
 
-        memcpy( &nCount, pabyData, 4 );
-        HFAStandard( 4, &nCount );
+        memcpy(&nCount, pabyData, 4);
+        HFAStandard(4, &nCount);
 
         pabyData += 8;
         nInstBytes += 8;
     }
-    else
-        nCount = 1;
 
-    if( chItemType == 'b' && nCount != 0 ) // BASEDATA
+    if( chItemType == 'b' && nCount != 0 )  // BASEDATA
     {
-        if (nDataSize - nInstBytes < 4+4+2)
+        if( nDataSize - nInstBytes < 4 + 4 + 2 )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Buffer too small");
             return -1;
         }
 
-        GInt32 nRows, nColumns;
-        GInt16 nBaseItemType;
-
-        memcpy( &nRows, pabyData, 4 );
-        HFAStandard( 4, &nRows );
-        memcpy( &nColumns, pabyData+4, 4 );
-        HFAStandard( 4, &nColumns );
-        memcpy( &nBaseItemType, pabyData+8, 2 );
-        HFAStandard( 2, &nBaseItemType );
+        GInt32 nRows = 0;
+        memcpy(&nRows, pabyData, 4);
+        HFAStandard(4, &nRows);
+        GInt32 nColumns = 0;
+        memcpy(&nColumns, pabyData + 4, 4);
+        HFAStandard(4, &nColumns);
+        GInt16 nBaseItemType = 0;
+        memcpy(&nBaseItemType, pabyData + 8, 2);
+        HFAStandard(2, &nBaseItemType);
         if( nBaseItemType < EPT_MIN || nBaseItemType > EPT_MAX )
             return -1;
+
         EPTType eBaseItemType = static_cast<EPTType>(nBaseItemType);
 
         nInstBytes += 12;
 
-        if (nRows < 0 || nColumns < 0)
+        if( nRows < 0 || nColumns < 0 )
             return -1;
-        if (nColumns != 0 && nRows > INT_MAX / nColumns)
+        if( nColumns != 0 && nRows > INT_MAX / nColumns )
             return -1;
-        if( nRows != 0 && ((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) > INT_MAX / nRows )
+        if( nRows != 0 &&
+            ((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) > INT_MAX / nRows )
             return -1;
-        if (nColumns != 0 && ((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) * nRows > INT_MAX / nColumns)
+        if( nColumns != 0 &&
+            ((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) * nRows >
+            INT_MAX / nColumns )
             return -1;
-        if (((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) * nRows * nColumns > INT_MAX - nInstBytes)
+        if( ((HFAGetDataTypeBits(eBaseItemType) + 7) / 8) * nRows * nColumns >
+            INT_MAX - nInstBytes )
             return -1;
 
         nInstBytes +=
@@ -1378,26 +1429,24 @@ int HFAField::GetInstBytes( GByte *pabyData, int nDataSize )
     }
     else if( poItemObjectType == NULL )
     {
-        if (nCount != 0 && HFADictionary::GetItemSize(chItemType) > INT_MAX / nCount)
+        if( nCount != 0 &&
+            HFADictionary::GetItemSize(chItemType) > INT_MAX / nCount )
             return -1;
-        if( nCount * HFADictionary::GetItemSize(chItemType) > INT_MAX - nInstBytes )
+        if( nCount * HFADictionary::GetItemSize(chItemType) >
+            INT_MAX - nInstBytes )
             return -1;
         nInstBytes += nCount * HFADictionary::GetItemSize(chItemType);
     }
     else
     {
-        int		i;
-
-        for( i = 0; i < nCount &&
-                    nInstBytes < nDataSize &&
-                    nInstBytes >= 0; i++ )
+        for( int i = 0;
+             i < nCount && nInstBytes < nDataSize && nInstBytes >= 0;
+             i++ )
         {
-            int	nThisBytes;
-
-            nThisBytes =
-                poItemObjectType->GetInstBytes( pabyData,
-                                                nDataSize - nInstBytes );
-            if (nThisBytes < 0 || nInstBytes > INT_MAX - nThisBytes)
+            const int nThisBytes =
+                poItemObjectType->GetInstBytes(pabyData,
+                                                nDataSize - nInstBytes);
+            if( nThisBytes < 0 || nInstBytes > INT_MAX - nThisBytes )
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
                 return -1;
@@ -1408,7 +1457,7 @@ int HFAField::GetInstBytes( GByte *pabyData, int nDataSize )
         }
     }
 
-    return( nInstBytes );
+    return nInstBytes;
 }
 
 /************************************************************************/
@@ -1424,36 +1473,34 @@ int HFAField::GetInstCount( GByte * pabyData, int nDataSize )
 {
     if( chPointer == '\0' )
         return nItemCount;
-    else if( chItemType == 'b' )
-    {
-        GInt32 nRows, nColumns;
 
+    if( chItemType == 'b' )
+    {
         if( nDataSize < 20 )
             return 0;
 
-        memcpy( &nRows, pabyData+8, 4 );
-        HFAStandard( 4, &nRows );
-        memcpy( &nColumns, pabyData+12, 4 );
-        HFAStandard( 4, &nColumns );
+        GInt32 nRows = 0;
+        memcpy(&nRows, pabyData + 8, 4);
+        HFAStandard(4, &nRows);
+        GInt32 nColumns = 0;
+        memcpy(&nColumns, pabyData + 12, 4);
+        HFAStandard(4, &nColumns);
 
-        if (nRows < 0 || nColumns < 0)
+        if( nRows < 0 || nColumns < 0 )
             return 0;
-        if (nColumns != 0 && nRows > INT_MAX / nColumns)
+        if( nColumns != 0 && nRows > INT_MAX / nColumns )
             return 0;
 
         return nRows * nColumns;
     }
-    else
-    {
-        GInt32 nCount;
 
-        if( nDataSize < 4 )
-            return 0;
+    if( nDataSize < 4 )
+        return 0;
 
-        memcpy( &nCount, pabyData, 4 );
-        HFAStandard( 4, &nCount );
-        return nCount;
-    }
+    GInt32 nCount = 0;
+    memcpy(&nCount, pabyData, 4);
+    HFAStandard(4, &nCount);
+    return nCount;
 }
 
 /************************************************************************/
@@ -1461,156 +1508,164 @@ int HFAField::GetInstCount( GByte * pabyData, int nDataSize )
 /************************************************************************/
 
 void HFAField::DumpInstValue( FILE *fpOut,
-                           GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
-                           const char *pszPrefix )
+                              GByte *pabyData,
+                              GUInt32 nDataOffset, int nDataSize,
+                              const char *pszPrefix )
 
 {
-    int		iEntry, nEntries;
-    void	*pReturn;
-    char	szLongFieldName[256];
-
-    nEntries = GetInstCount( pabyData, nDataSize );
+    const int nEntries = GetInstCount(pabyData, nDataSize);
 
-/* -------------------------------------------------------------------- */
-/*      Special case for arrays of chars or uchars which are printed    */
-/*      as a string.                                                    */
-/* -------------------------------------------------------------------- */
+    // Special case for arrays of chars or uchars which are printed
+    // as a string.
     if( (chItemType == 'c' || chItemType == 'C') && nEntries > 0 )
     {
-        if( ExtractInstValue( NULL, 0,
-                              pabyData, nDataOffset, nDataSize,
-                              's', &pReturn ) )
-            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s = `%s'\n",
-                        pszPrefix, pszFieldName,
-                        (char *) pReturn ));
+        void *pReturn = NULL;
+        if( ExtractInstValue(NULL, 0,
+                             pabyData, nDataOffset, nDataSize,
+                             's', &pReturn) )
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintf(fpOut, "%s%s = `%s'\n",
+                           pszPrefix, pszFieldName,
+                           static_cast<char *>(pReturn)));
         else
-            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s = (access failed)\n",
-                        pszPrefix, pszFieldName ));
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintf(fpOut, "%s%s = (access failed)\n",
+                           pszPrefix, pszFieldName));
 
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      For BASEDATA objects, we want to first dump their dimension     */
-/*      and type.                                                       */
-/* -------------------------------------------------------------------- */
+    // For BASEDATA objects, we want to first dump their dimension and type.
     if( chItemType == 'b' )
     {
-        int nDataType, nRows, nColumns;
-        int bSuccess = ExtractInstValue( NULL, -3, pabyData, nDataOffset,
-                          nDataSize, 'i', &nDataType );
-        if (bSuccess)
+        int nDataType = 0;
+        const bool bSuccess =
+            ExtractInstValue(NULL, -3, pabyData, nDataOffset,
+                             nDataSize, 'i', &nDataType);
+        if( bSuccess )
         {
-            ExtractInstValue( NULL, -2, pabyData, nDataOffset,
-                            nDataSize, 'i', &nColumns );
-            ExtractInstValue( NULL, -1, pabyData, nDataOffset,
-                            nDataSize, 'i', &nRows );
-            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%sBASEDATA(%s): %dx%d of %s\n",
-                        pszPrefix, pszFieldName,
-                        nColumns, nRows,
-                        (nDataType >= EPT_MIN && nDataType <= EPT_MAX) ?
-                            HFAGetDataTypeName( static_cast<EPTType>(nDataType) ): "invalid type" ));
+            int nColumns = 0;
+            ExtractInstValue(NULL, -2, pabyData, nDataOffset,
+                             nDataSize, 'i', &nColumns);
+            int nRows = 0;
+            ExtractInstValue(NULL, -1, pabyData, nDataOffset,
+                             nDataSize, 'i', &nRows);
+            CPL_IGNORE_RET_VAL(VSIFPrintf(
+                fpOut, "%sBASEDATA(%s): %dx%d of %s\n",
+                pszPrefix, pszFieldName,
+                nColumns, nRows,
+                (nDataType >= EPT_MIN && nDataType <= EPT_MAX)
+                ? HFAGetDataTypeName(static_cast<EPTType>(nDataType))
+                : "invalid type"));
         }
         else
         {
-            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%sBASEDATA(%s): empty\n",
-                        pszPrefix, pszFieldName ));
+            CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "%sBASEDATA(%s): empty\n",
+                                          pszPrefix, pszFieldName));
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Dump each entry in the field array.                             */
-/* -------------------------------------------------------------------- */
-    for( iEntry = 0; iEntry < MIN(MAX_ENTRY_REPORT,nEntries); iEntry++ )
+    // Dump each entry in the field array.
+    void *pReturn = NULL;
+
+    const int nMaxEntry = std::min(MAX_ENTRY_REPORT, nEntries);
+    for( int iEntry = 0; iEntry < nMaxEntry; iEntry++ )
     {
         if( nEntries == 1 )
-            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s = ", pszPrefix, pszFieldName ));
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintf(fpOut, "%s%s = ", pszPrefix, pszFieldName));
         else
-            CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s[%d] = ",
-                        pszPrefix, pszFieldName, iEntry ));
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintf(fpOut, "%s%s[%d] = ",
+                           pszPrefix, pszFieldName, iEntry));
 
         switch( chItemType )
         {
           case 'f':
           case 'd':
           {
-              double  dfValue;
-              if( ExtractInstValue( NULL, iEntry,
+              double dfValue = 0.0;
+              if( ExtractInstValue(NULL, iEntry,
                                     pabyData, nDataOffset, nDataSize,
-                                    'd', &dfValue ) )
-                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%f\n", dfValue ));
+                                    'd', &dfValue) )
+                  CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "%f\n", dfValue));
               else
-                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "(access failed)\n" ));
+                  CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "(access failed)\n"));
           }
           break;
 
           case 'b':
           {
-              double dfValue;
+              double dfValue = 0.0;
 
-              if( ExtractInstValue( NULL, iEntry,
+              if( ExtractInstValue(NULL, iEntry,
                                     pabyData, nDataOffset, nDataSize,
-                                    'd', &dfValue ) )
-                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%.15g\n", pszPrefix, dfValue ));
+                                    'd', &dfValue) )
+                  CPL_IGNORE_RET_VAL(
+                      VSIFPrintf(fpOut, "%s%.15g\n", pszPrefix, dfValue));
               else
-                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s(access failed)\n", pszPrefix ));
+                  CPL_IGNORE_RET_VAL(
+                      VSIFPrintf(fpOut, "%s(access failed)\n", pszPrefix));
           }
           break;
 
           case 'e':
-            if( ExtractInstValue( NULL, iEntry,
+            if( ExtractInstValue(NULL, iEntry,
                                   pabyData, nDataOffset, nDataSize,
-                                  's', &pReturn ) )
-                CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s\n", (char *) pReturn ));
+                                  's', &pReturn) )
+                CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "%s\n",
+                                               (char *) pReturn));
             else
-                CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "(access failed)\n" ));
+                CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "(access failed)\n"));
             break;
 
           case 'o':
-            if( !ExtractInstValue( NULL, iEntry,
+            if( !ExtractInstValue(NULL, iEntry,
                                    pabyData, nDataOffset, nDataSize,
-                                   'p', &pReturn ) )
+                                   'p', &pReturn) )
             {
-                CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "(access failed)\n" ));
+                CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "(access failed)\n"));
             }
             else
             {
-                int		nByteOffset;
-
-                CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "\n" ));
+                CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "\n"));
 
-                nByteOffset = static_cast<int>(((GByte *) pReturn) - pabyData);
+                const int nByteOffset =
+                    static_cast<int>(((GByte *) pReturn) - pabyData);
 
-                snprintf( szLongFieldName, sizeof(szLongFieldName), "%s    ", pszPrefix );
+                char szLongFieldName[256] = {};
+                snprintf(szLongFieldName, sizeof(szLongFieldName),
+                          "%s    ", pszPrefix);
 
                 if( poItemObjectType )
-                    poItemObjectType->DumpInstValue( fpOut,
-                                                     pabyData + nByteOffset,
-                                                     nDataOffset + nByteOffset,
-                                                     nDataSize - nByteOffset,
-                                                     szLongFieldName );
+                    poItemObjectType->DumpInstValue(fpOut,
+                                                    pabyData + nByteOffset,
+                                                    nDataOffset + nByteOffset,
+                                                    nDataSize - nByteOffset,
+                                                    szLongFieldName);
             }
             break;
 
           default:
           {
-              GInt32 nIntValue;
+              GInt32 nIntValue = 0;
 
-              if( ExtractInstValue( NULL, iEntry,
-                                    pabyData, nDataOffset, nDataSize,
-                                    'i', &nIntValue ) )
-                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%d\n", nIntValue ));
+              if( ExtractInstValue(NULL, iEntry,
+                                   pabyData, nDataOffset, nDataSize,
+                                   'i', &nIntValue) )
+                  CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "%d\n", nIntValue));
               else
-                  CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "(access failed)\n" ));
+                  CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "(access failed)\n"));
           }
           break;
         }
     }
 
     if( nEntries > MAX_ENTRY_REPORT )
-        printf( "%s ... remaining instances omitted ...\n", pszPrefix );
+        CPL_IGNORE_RET_VAL(VSIFPrintf(
+            fpOut, "%s ... remaining instances omitted ...\n", pszPrefix));
 
     if( nEntries == 0 )
-        CPL_IGNORE_RET_VAL(VSIFPrintf( fpOut, "%s%s = (no values)\n", pszPrefix, pszFieldName ));
-
+        CPL_IGNORE_RET_VAL(
+            VSIFPrintf(fpOut, "%s%s = (no values)\n", pszPrefix, pszFieldName));
 }
diff --git a/frmts/hfa/hfaopen.cpp b/frmts/hfa/hfaopen.cpp
index b114325..67d2451 100644
--- a/frmts/hfa/hfaopen.cpp
+++ b/frmts/hfa/hfaopen.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfaopen.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Supporting functions for HFA (.img) ... main (C callable) API
@@ -37,18 +36,34 @@
  *
  */
 
+#include "cpl_port.h"
 #include "hfa_p.h"
-#include "cpl_conv.h"
-#include <limits.h>
+
+#include <cerrno>
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+#include <memory>
+#include <string>
 #include <vector>
 
-CPL_CVSID("$Id: hfaopen.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "hfa.h"
 
+CPL_CVSID("$Id: hfaopen.cpp 37895 2017-04-04 06:02:17Z goatbar $");
 
 static const char * const apszAuxMetadataItems[] = {
-
 // node/entry            field_name                  metadata_key       type
-
  "Statistics",           "dminimum",              "STATISTICS_MINIMUM",     "Esta_Statistics",
  "Statistics",           "dmaximum",              "STATISTICS_MAXIMUM",     "Esta_Statistics",
  "Statistics",           "dmean",                 "STATISTICS_MEAN",        "Esta_Statistics",
@@ -62,16 +77,15 @@ static const char * const apszAuxMetadataItems[] = {
  "StatisticsParameters", "lSkipFactorY",          "STATISTICS_SKIPFACTORY", "",
  "StatisticsParameters", "dExcludedValues",       "STATISTICS_EXCLUDEDVALUES","",
  "",                     "elayerType",            "LAYER_TYPE",             "",
+ "RRDInfoList",          "salgorithm.string",     "OVERVIEWS_ALGORITHM",    "Emif_String",
  NULL
 };
 
-
 const char * const * GetHFAAuxMetaDataList()
 {
     return apszAuxMetadataItems;
 }
 
-
 /************************************************************************/
 /*                          HFAGetDictionary()                          */
 /************************************************************************/
@@ -79,11 +93,11 @@ const char * const * GetHFAAuxMetaDataList()
 static char * HFAGetDictionary( HFAHandle hHFA )
 
 {
-    int		nDictMax = 100;
-    char	*pszDictionary = (char *) CPLMalloc(nDictMax);
-    int		nDictSize = 0;
+    int nDictMax = 100;
+    char *pszDictionary = static_cast<char *>(CPLMalloc(nDictMax));
+    int nDictSize = 0;
 
-    if( VSIFSeekL( hHFA->fp, hHFA->nDictionaryPos, SEEK_SET ) < 0 )
+    if( VSIFSeekL(hHFA->fp, hHFA->nDictionaryPos, SEEK_SET) < 0 )
     {
         pszDictionary[nDictSize] = '\0';
         return pszDictionary;
@@ -91,16 +105,17 @@ static char * HFAGetDictionary( HFAHandle hHFA )
 
     while( true )
     {
-        if( nDictSize >= nDictMax-1 )
+        if( nDictSize >= nDictMax - 1 )
         {
             nDictMax = nDictSize * 2 + 100;
-            pszDictionary = (char *) CPLRealloc(pszDictionary, nDictMax );
+            pszDictionary =
+                static_cast<char *>(CPLRealloc(pszDictionary, nDictMax));
         }
 
-        if( VSIFReadL( pszDictionary + nDictSize, 1, 1, hHFA->fp ) < 1
-            || pszDictionary[nDictSize] == '\0'
-            || (nDictSize > 2 && pszDictionary[nDictSize-2] == ','
-                && pszDictionary[nDictSize-1] == '.') )
+        if( VSIFReadL(pszDictionary + nDictSize, 1, 1, hHFA->fp) < 1 ||
+            pszDictionary[nDictSize] == '\0' ||
+            (nDictSize > 2 && pszDictionary[nDictSize - 2] == ',' &&
+             pszDictionary[nDictSize-1] == '.') )
             break;
 
         nDictSize++;
@@ -108,134 +123,113 @@ static char * HFAGetDictionary( HFAHandle hHFA )
 
     pszDictionary[nDictSize] = '\0';
 
-
-    return( pszDictionary );
+    return pszDictionary;
 }
 
 /************************************************************************/
 /*                              HFAOpen()                               */
 /************************************************************************/
 
-HFAHandle HFAOpen( const char * pszFilename, const char * pszAccess )
+HFAHandle HFAOpen( const char *pszFilename, const char *pszAccess )
 
 {
-    VSILFILE *fp;
-    char	szHeader[16];
-    HFAInfo_t	*psInfo;
-    GUInt32	nHeaderPos;
+    VSILFILE *fp = VSIFOpenL(
+        pszFilename,
+        (EQUAL(pszAccess, "r") || EQUAL(pszAccess, "rb")) ? "rb" : "r+b");
 
-/* -------------------------------------------------------------------- */
-/*      Open the file.                                                  */
-/* -------------------------------------------------------------------- */
-    if( EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb" ) )
-        fp = VSIFOpenL( pszFilename, "rb" );
-    else
-        fp = VSIFOpenL( pszFilename, "r+b" );
-
-    /* should this be changed to use some sort of CPLFOpen() which will
-       set the error? */
+    // Should this be changed to use some sort of CPLFOpen() which will
+    // set the error?
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "File open of %s failed.",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed, "File open of %s failed.",
+                 pszFilename);
 
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read and verify the header.                                     */
-/* -------------------------------------------------------------------- */
-    if( VSIFReadL( szHeader, 16, 1, fp ) < 1 )
+    // Read and verify the header.
+    char szHeader[16] = {};
+    if( VSIFReadL(szHeader, 16, 1, fp) < 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to read 16 byte header failed for\n%s.",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Attempt to read 16 byte header failed for\n%s.", pszFilename);
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
 
     if( !STARTS_WITH_CI(szHeader, "EHFA_HEADER_TAG") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "File %s is not an Imagine HFA file ... header wrong.",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "File %s is not an Imagine HFA file ... header wrong.",
+                 pszFilename);
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the HFAInfo_t                                            */
-/* -------------------------------------------------------------------- */
-    psInfo = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1);
+    // Create the HFAInfo_t.
+    HFAInfo_t *psInfo =
+        static_cast<HFAInfo_t *>(CPLCalloc(sizeof(HFAInfo_t), 1));
 
     psInfo->pszFilename = CPLStrdup(CPLGetFilename(pszFilename));
     psInfo->pszPath = CPLStrdup(CPLGetPath(pszFilename));
     psInfo->fp = fp;
-    if( EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb" ) )
-	psInfo->eAccess = HFA_ReadOnly;
+    if( EQUAL(pszAccess, "r") || EQUAL(pszAccess, "rb") )
+        psInfo->eAccess = HFA_ReadOnly;
     else
-	psInfo->eAccess = HFA_Update;
-    psInfo->bTreeDirty = FALSE;
+        psInfo->eAccess = HFA_Update;
+    psInfo->bTreeDirty = false;
 
-/* -------------------------------------------------------------------- */
-/*	Where is the header?						*/
-/* -------------------------------------------------------------------- */
-    bool bRet = VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, fp ) > 0;
-    HFAStandard( 4, &nHeaderPos );
+    // Where is the header?
+    GUInt32 nHeaderPos = 0;
+    bool bRet = VSIFReadL(&nHeaderPos, sizeof(GInt32), 1, fp) > 0;
+    HFAStandard(4, &nHeaderPos);
 
-/* -------------------------------------------------------------------- */
-/*      Read the header.                                                */
-/* -------------------------------------------------------------------- */
-    bRet &= VSIFSeekL( fp, nHeaderPos, SEEK_SET ) >= 0;
+    // Read the header.
+    bRet &= VSIFSeekL(fp, nHeaderPos, SEEK_SET) >= 0;
 
-    bRet &= VSIFReadL( &(psInfo->nVersion), sizeof(GInt32), 1, fp ) > 0;
-    HFAStandard( 4, &(psInfo->nVersion) );
+    bRet &= VSIFReadL(&(psInfo->nVersion), sizeof(GInt32), 1, fp) > 0;
+    HFAStandard(4, &(psInfo->nVersion));
 
-    bRet &= VSIFReadL( szHeader, 4, 1, fp ) > 0; /* skip freeList */
+    bRet &= VSIFReadL(szHeader, 4, 1, fp) > 0;  // Skip freeList.
 
-    bRet &= VSIFReadL( &(psInfo->nRootPos), sizeof(GInt32), 1, fp ) > 0;
-    HFAStandard( 4, &(psInfo->nRootPos) );
+    bRet &= VSIFReadL(&(psInfo->nRootPos), sizeof(GInt32), 1, fp) > 0;
+    HFAStandard(4, &(psInfo->nRootPos));
 
-    bRet &= VSIFReadL( &(psInfo->nEntryHeaderLength), sizeof(GInt16), 1, fp ) > 0;
-    HFAStandard( 2, &(psInfo->nEntryHeaderLength) );
+    bRet &= VSIFReadL(&(psInfo->nEntryHeaderLength), sizeof(GInt16), 1, fp) > 0;
+    HFAStandard(2, &(psInfo->nEntryHeaderLength));
 
-    bRet &= VSIFReadL( &(psInfo->nDictionaryPos), sizeof(GInt32), 1, fp ) > 0;
-    HFAStandard( 4, &(psInfo->nDictionaryPos) );
+    bRet &= VSIFReadL(&(psInfo->nDictionaryPos), sizeof(GInt32), 1, fp) > 0;
+    HFAStandard(4, &(psInfo->nDictionaryPos));
 
-/* -------------------------------------------------------------------- */
-/*      Collect file size.                                              */
-/* -------------------------------------------------------------------- */
-    bRet &= VSIFSeekL( fp, 0, SEEK_END ) >= 0;
+    // Collect file size.
+    bRet &= VSIFSeekL(fp, 0, SEEK_END) >= 0;
     if( !bRet )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+        CPLFree(psInfo->pszFilename);
+        CPLFree(psInfo->pszPath);
         CPLFree(psInfo);
         return NULL;
     }
-    psInfo->nEndOfFile = (GUInt32) VSIFTellL( fp );
+    psInfo->nEndOfFile = static_cast<GUInt32>(VSIFTellL(fp));
 
-/* -------------------------------------------------------------------- */
-/*      Instantiate the root entry.                                     */
-/* -------------------------------------------------------------------- */
-    psInfo->poRoot = HFAEntry::New( psInfo, psInfo->nRootPos, NULL, NULL );
+    // Instantiate the root entry.
+    psInfo->poRoot = HFAEntry::New(psInfo, psInfo->nRootPos, NULL, NULL);
     if( psInfo->poRoot == NULL )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+        CPLFree(psInfo->pszFilename);
+        CPLFree(psInfo->pszPath);
         CPLFree(psInfo);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the dictionary                                             */
-/* -------------------------------------------------------------------- */
-    psInfo->pszDictionary = HFAGetDictionary( psInfo );
-    psInfo->poDictionary = new HFADictionary( psInfo->pszDictionary );
+    // Read the dictionary.
+    psInfo->pszDictionary = HFAGetDictionary(psInfo);
+    psInfo->poDictionary = new HFADictionary(psInfo->pszDictionary);
 
-/* -------------------------------------------------------------------- */
-/*      Collect band definitions.                                       */
-/* -------------------------------------------------------------------- */
-    HFAParseBandInfo( psInfo );
+    // Collect band definitions.
+    HFAParseBandInfo(psInfo);
 
     return psInfo;
 }
@@ -253,29 +247,23 @@ HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase )
     if( psBase->psDependent != NULL )
         return psBase->psDependent;
 
-/* -------------------------------------------------------------------- */
-/*      Create desired RRD filename.                                    */
-/* -------------------------------------------------------------------- */
-    CPLString oBasename = CPLGetBasename( psBase->pszFilename );
-    CPLString oRRDFilename =
-        CPLFormFilename( psBase->pszPath, oBasename, "rrd" );
+    // Create desired RRD filename.
+    const CPLString oBasename = CPLGetBasename(psBase->pszFilename);
+    const CPLString oRRDFilename =
+        CPLFormFilename(psBase->pszPath, oBasename, "rrd");
 
-/* -------------------------------------------------------------------- */
-/*      Does this file already exist?  If so, re-use it.                */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fp = VSIFOpenL( oRRDFilename, "rb" );
+    // Does this file already exist?  If so, re-use it.
+    VSILFILE *fp = VSIFOpenL(oRRDFilename, "rb");
     if( fp != NULL )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
-        psBase->psDependent = HFAOpen( oRRDFilename, "rb" );
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+        psBase->psDependent = HFAOpen(oRRDFilename, "rb");
         // FIXME? this is not going to be reused but recreated...
     }
 
-/* -------------------------------------------------------------------- */
-/*      Otherwise create it now.                                        */
-/* -------------------------------------------------------------------- */
-    HFAInfo_t *psDep;
-    psDep = psBase->psDependent = HFACreateLL( oRRDFilename );
+    // Otherwise create it now.
+    HFAInfo_t *psDep = HFACreateLL(oRRDFilename);
+    psBase->psDependent = psDep;
     if( psDep == NULL )
         return NULL;
 
@@ -284,19 +272,19 @@ HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase )
 /*      parent.  When working from an .aux file we really want the      */
 /*      .rrd to point back to the original file, not the .aux file.     */
 /* -------------------------------------------------------------------- */
-    HFAEntry  *poEntry = psBase->poRoot->GetNamedChild("DependentFile");
+    HFAEntry *poEntry = psBase->poRoot->GetNamedChild("DependentFile");
     const char *pszDependentFile = NULL;
     if( poEntry != NULL )
-        pszDependentFile = poEntry->GetStringField( "dependent.string" );
+        pszDependentFile = poEntry->GetStringField("dependent.string");
     if( pszDependentFile == NULL )
         pszDependentFile = psBase->pszFilename;
 
-    HFAEntry *poDF = HFAEntry::New( psDep, "DependentFile",
-                                   "Eimg_DependentFile", psDep->poRoot );
+    HFAEntry *poDF = HFAEntry::New(psDep, "DependentFile",
+                                   "Eimg_DependentFile", psDep->poRoot);
 
-    poDF->MakeData( static_cast<int>(strlen(pszDependentFile) + 50) );
+    poDF->MakeData(static_cast<int>(strlen(pszDependentFile) + 50));
     poDF->SetPosition();
-    poDF->SetStringField( "dependent.string", pszDependentFile );
+    poDF->SetStringField("dependent.string", pszDependentFile);
 
     return psDep;
 }
@@ -305,43 +293,38 @@ HFAInfo_t *HFACreateDependent( HFAInfo_t *psBase )
 /*                          HFAGetDependent()                           */
 /************************************************************************/
 
-HFAInfo_t *HFAGetDependent( HFAInfo_t *psBase, const char *pszFilename )
+HFAInfo_t *HFAGetDependent(HFAInfo_t *psBase, const char *pszFilename)
 
 {
-    if( EQUAL(pszFilename,psBase->pszFilename) )
+    if( EQUAL(pszFilename, psBase->pszFilename) )
         return psBase;
 
     if( psBase->psDependent != NULL )
     {
-        if( EQUAL(pszFilename,psBase->psDependent->pszFilename) )
+        if( EQUAL(pszFilename, psBase->psDependent->pszFilename) )
             return psBase->psDependent;
         else
             return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try to open the dependent file.                                 */
-/* -------------------------------------------------------------------- */
-    char	*pszDependent;
-    VSILFILE *fp;
-    const char* pszMode = psBase->eAccess == HFA_Update ? "r+b" : "rb";
+    // Try to open the dependent file.
+    const char *pszMode = psBase->eAccess == HFA_Update ? "r+b" : "rb";
 
-    pszDependent = CPLStrdup(
-        CPLFormFilename( psBase->pszPath, pszFilename, NULL ) );
+    char *pszDependent =
+        CPLStrdup(CPLFormFilename(psBase->pszPath, pszFilename, NULL));
 
-    fp = VSIFOpenL( pszDependent, pszMode );
+    VSILFILE *fp = VSIFOpenL(pszDependent, pszMode);
     if( fp != NULL )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
-        psBase->psDependent = HFAOpen( pszDependent, pszMode );
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
+        psBase->psDependent = HFAOpen(pszDependent, pszMode);
     }
 
-    CPLFree( pszDependent );
+    CPLFree(pszDependent);
 
     return psBase->psDependent;
 }
 
-
 /************************************************************************/
 /*                          HFAParseBandInfo()                          */
 /*                                                                      */
@@ -352,35 +335,30 @@ HFAInfo_t *HFAGetDependent( HFAInfo_t *psBase, const char *pszFilename )
 CPLErr HFAParseBandInfo( HFAInfo_t *psInfo )
 
 {
-    HFAEntry	*poNode;
-
-/* -------------------------------------------------------------------- */
-/*      Find the first band node.                                       */
-/* -------------------------------------------------------------------- */
+    // Find the first band node.
     psInfo->nBands = 0;
-    poNode = psInfo->poRoot->GetChild();
+    HFAEntry *poNode = psInfo->poRoot->GetChild();
     while( poNode != NULL )
     {
-        if( EQUAL(poNode->GetType(),"Eimg_Layer")
-            && poNode->GetIntField("width") > 0
-            && poNode->GetIntField("height") > 0 )
+        if( EQUAL(poNode->GetType(), "Eimg_Layer") &&
+            poNode->GetIntField("width") > 0 &&
+            poNode->GetIntField("height") > 0 )
         {
             if( psInfo->nBands == 0 )
             {
                 psInfo->nXSize = poNode->GetIntField("width");
                 psInfo->nYSize = poNode->GetIntField("height");
             }
-            else if( poNode->GetIntField("width") != psInfo->nXSize
-                     || poNode->GetIntField("height") != psInfo->nYSize )
+            else if( poNode->GetIntField("width") != psInfo->nXSize ||
+                     poNode->GetIntField("height") != psInfo->nYSize )
             {
                 return CE_Failure;
             }
 
-            psInfo->papoBand = (HFABand **)
-                CPLRealloc(psInfo->papoBand,
-                           sizeof(HFABand *) * (psInfo->nBands+1));
-            psInfo->papoBand[psInfo->nBands] = new HFABand( psInfo, poNode );
-            if (psInfo->papoBand[psInfo->nBands]->nWidth == 0)
+            psInfo->papoBand = static_cast<HFABand **>(CPLRealloc(
+                psInfo->papoBand, sizeof(HFABand *) * (psInfo->nBands + 1)));
+            psInfo->papoBand[psInfo->nBands] = new HFABand(psInfo, poNode);
+            if( psInfo->papoBand[psInfo->nBands]->nWidth == 0 )
             {
                 delete psInfo->papoBand[psInfo->nBands];
                 return CE_Failure;
@@ -401,66 +379,65 @@ CPLErr HFAParseBandInfo( HFAInfo_t *psInfo )
 int HFAClose( HFAHandle hHFA )
 
 {
-    int nRet = 0;
-    int		i;
-
     if( hHFA->eAccess == HFA_Update && (hHFA->bTreeDirty ||
-        (hHFA->poDictionary != NULL && hHFA->poDictionary->bDictionaryTextDirty)) )
-        HFAFlush( hHFA );
+        (hHFA->poDictionary != NULL &&
+         hHFA->poDictionary->bDictionaryTextDirty)) )
+        HFAFlush(hHFA);
 
+    int nRet = 0;
     if( hHFA->psDependent != NULL )
     {
-        if( HFAClose( hHFA->psDependent ) != 0 )
+        if( HFAClose(hHFA->psDependent) != 0 )
             nRet = -1;
     }
 
     delete hHFA->poRoot;
 
-    if( VSIFCloseL( hHFA->fp ) != 0 )
+    if( VSIFCloseL(hHFA->fp) != 0 )
         nRet = -1;
 
     if( hHFA->poDictionary != NULL )
         delete hHFA->poDictionary;
 
-    CPLFree( hHFA->pszDictionary );
-    CPLFree( hHFA->pszFilename );
-    CPLFree( hHFA->pszIGEFilename );
-    CPLFree( hHFA->pszPath );
+    CPLFree(hHFA->pszDictionary);
+    CPLFree(hHFA->pszFilename);
+    CPLFree(hHFA->pszIGEFilename);
+    CPLFree(hHFA->pszPath);
 
-    for( i = 0; i < hHFA->nBands; i++ )
+    for( int i = 0; i < hHFA->nBands; i++ )
     {
         delete hHFA->papoBand[i];
     }
 
-    CPLFree( hHFA->papoBand );
+    CPLFree(hHFA->papoBand);
 
     if( hHFA->pProParameters != NULL )
     {
         Eprj_ProParameters *psProParms = (Eprj_ProParameters *)
             hHFA->pProParameters;
 
-        CPLFree( psProParms->proExeName );
-        CPLFree( psProParms->proName );
-        CPLFree( psProParms->proSpheroid.sphereName );
+        CPLFree(psProParms->proExeName);
+        CPLFree(psProParms->proName);
+        CPLFree(psProParms->proSpheroid.sphereName);
 
-        CPLFree( psProParms );
+        CPLFree(psProParms);
     }
 
     if( hHFA->pDatum != NULL )
     {
-        CPLFree( ((Eprj_Datum *) hHFA->pDatum)->datumname );
-        CPLFree( ((Eprj_Datum *) hHFA->pDatum)->gridname );
-        CPLFree( hHFA->pDatum );
+        CPLFree(((Eprj_Datum *)hHFA->pDatum)->datumname);
+        CPLFree(((Eprj_Datum *)hHFA->pDatum)->gridname);
+        CPLFree(hHFA->pDatum);
     }
 
     if( hHFA->pMapInfo != NULL )
     {
-        CPLFree( ((Eprj_MapInfo *) hHFA->pMapInfo)->proName );
-        CPLFree( ((Eprj_MapInfo *) hHFA->pMapInfo)->units );
-        CPLFree( hHFA->pMapInfo );
+        CPLFree(((Eprj_MapInfo *)hHFA->pMapInfo)->proName);
+        CPLFree(((Eprj_MapInfo *)hHFA->pMapInfo)->units);
+        CPLFree(hHFA->pMapInfo);
     }
 
-    CPLFree( hHFA );
+    CPLFree(hHFA);
     return nRet;
 }
 
@@ -469,29 +446,26 @@ int HFAClose( HFAHandle hHFA )
 /*  Used from HFADelete() function.                                     */
 /************************************************************************/
 
-static
-CPLErr HFARemove( const char *pszFilename )
+static CPLErr HFARemove( const char *pszFilename )
 
 {
-    VSIStatBufL      sStat;
+    VSIStatBufL sStat;
 
-    if( VSIStatL( pszFilename, &sStat ) == 0 && VSI_ISREG( sStat.st_mode ) )
+    if( VSIStatL(pszFilename, &sStat) == 0 && VSI_ISREG(sStat.st_mode) )
     {
-        if( VSIUnlink( pszFilename ) == 0 )
+        if( VSIUnlink(pszFilename) == 0 )
             return CE_None;
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to unlink %s failed.\n", pszFilename );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Attempt to unlink %s failed.", pszFilename);
             return CE_Failure;
         }
     }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to delete %s, not a file.\n", pszFilename );
-        return CE_Failure;
-    }
+
+    CPLError(CE_Failure, CPLE_AppDefined, "Unable to delete %s, not a file.",
+             pszFilename);
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -501,17 +475,17 @@ CPLErr HFARemove( const char *pszFilename )
 CPLErr HFADelete( const char *pszFilename )
 
 {
-    HFAInfo_t   *psInfo = HFAOpen( pszFilename, "rb" );
-    HFAEntry    *poDMS = NULL;
-    HFAEntry    *poLayer = NULL;
-    HFAEntry    *poNode = NULL;
+    HFAInfo_t *psInfo = HFAOpen(pszFilename, "rb");
+    HFAEntry *poDMS = NULL;
+    HFAEntry *poLayer = NULL;
+    HFAEntry *poNode = NULL;
 
     if( psInfo != NULL )
     {
         poNode = psInfo->poRoot->GetChild();
-        while( ( poNode != NULL ) && ( poLayer == NULL ) )
+        while( (poNode != NULL) && (poLayer == NULL) )
         {
-            if( EQUAL(poNode->GetType(),"Eimg_Layer") )
+            if( EQUAL(poNode->GetType(), "Eimg_Layer") )
             {
                 poLayer = poNode;
             }
@@ -519,29 +493,29 @@ CPLErr HFADelete( const char *pszFilename )
         }
 
         if( poLayer != NULL )
-            poDMS = poLayer->GetNamedChild( "ExternalRasterDMS" );
+            poDMS = poLayer->GetNamedChild("ExternalRasterDMS");
 
-        if ( poDMS )
+        if( poDMS )
         {
             const char *pszRawFilename =
-                poDMS->GetStringField( "fileName.string" );
+                poDMS->GetStringField("fileName.string");
 
             if( pszRawFilename != NULL )
-                HFARemove( CPLFormFilename( psInfo->pszPath,
-                                            pszRawFilename, NULL ) );
+                HFARemove(
+                    CPLFormFilename(psInfo->pszPath, pszRawFilename, NULL));
         }
 
-        CPL_IGNORE_RET_VAL(HFAClose( psInfo ));
+        CPL_IGNORE_RET_VAL(HFAClose(psInfo));
     }
-    return HFARemove( pszFilename );
+    return HFARemove(pszFilename);
 }
 
 /************************************************************************/
 /*                          HFAGetRasterInfo()                          */
 /************************************************************************/
 
-CPLErr HFAGetRasterInfo( HFAHandle hHFA, int * pnXSize, int * pnYSize,
-                         int * pnBands )
+CPLErr HFAGetRasterInfo( HFAHandle hHFA, int *pnXSize, int *pnYSize,
+                         int *pnBands )
 
 {
     if( pnXSize != NULL )
@@ -557,18 +531,18 @@ CPLErr HFAGetRasterInfo( HFAHandle hHFA, int * pnXSize, int * pnYSize,
 /*                           HFAGetBandInfo()                           */
 /************************************************************************/
 
-CPLErr HFAGetBandInfo( HFAHandle hHFA, int nBand, EPTType * peDataType,
-                       int * pnBlockXSize, int * pnBlockYSize,
+CPLErr HFAGetBandInfo( HFAHandle hHFA, int nBand, EPTType *peDataType,
+                       int *pnBlockXSize, int *pnBlockYSize,
                        int *pnCompressionType )
 
 {
     if( nBand < 0 || nBand > hHFA->nBands )
     {
-        CPLAssert( FALSE );
+        CPLAssert(false);
         return CE_Failure;
     }
 
-    HFABand *poBand = hHFA->papoBand[nBand-1];
+    HFABand *poBand = hHFA->papoBand[nBand - 1];
 
     if( peDataType != NULL )
         *peDataType = poBand->eDataType;
@@ -579,22 +553,18 @@ CPLErr HFAGetBandInfo( HFAHandle hHFA, int nBand, EPTType * peDataType,
     if( pnBlockYSize != NULL )
         *pnBlockYSize = poBand->nBlockYSize;
 
-/* -------------------------------------------------------------------- */
-/*      Get compression code from RasterDMS.                            */
-/* -------------------------------------------------------------------- */
+    // Get compression code from RasterDMS.
     if( pnCompressionType != NULL )
     {
-        HFAEntry	*poDMS;
-
         *pnCompressionType = 0;
 
-        poDMS = poBand->poNode->GetNamedChild( "RasterDMS" );
+        HFAEntry *poDMS = poBand->poNode->GetNamedChild("RasterDMS");
 
         if( poDMS != NULL )
-            *pnCompressionType = poDMS->GetIntField( "compressionType" );
+            *pnCompressionType = poDMS->GetIntField("compressionType");
     }
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -608,17 +578,17 @@ int HFAGetBandNoData( HFAHandle hHFA, int nBand, double *pdfNoData )
 {
     if( nBand < 0 || nBand > hHFA->nBands )
     {
-        CPLAssert( FALSE );
+        CPLAssert(false);
         return CE_Failure;
     }
 
-    HFABand *poBand = hHFA->papoBand[nBand-1];
+    HFABand *poBand = hHFA->papoBand[nBand - 1];
 
     if( !poBand->bNoDataSet && poBand->nOverviews > 0 )
     {
-      poBand = poBand->papoOverviews[0];
-      if( poBand == NULL )
-          return FALSE;
+        poBand = poBand->papoOverviews[0];
+        if( poBand == NULL )
+            return FALSE;
     }
 
     *pdfNoData = poBand->dfNoData;
@@ -634,9 +604,9 @@ int HFAGetBandNoData( HFAHandle hHFA, int nBand, double *pdfNoData )
 CPLErr HFASetBandNoData( HFAHandle hHFA, int nBand, double dfValue )
 
 {
-    if ( nBand < 0 || nBand > hHFA->nBands )
+    if( nBand < 0 || nBand > hHFA->nBands )
     {
-        CPLAssert( FALSE );
+        CPLAssert(false);
         return CE_Failure;
     }
 
@@ -652,15 +622,13 @@ CPLErr HFASetBandNoData( HFAHandle hHFA, int nBand, double dfValue )
 int HFAGetOverviewCount( HFAHandle hHFA, int nBand )
 
 {
-    HFABand	*poBand;
-
     if( nBand < 0 || nBand > hHFA->nBands )
     {
-        CPLAssert( FALSE );
+        CPLAssert(false);
         return CE_Failure;
     }
 
-    poBand = hHFA->papoBand[nBand-1];
+    HFABand *poBand = hHFA->papoBand[nBand - 1];
     poBand->LoadOverviews();
 
     return poBand->nOverviews;
@@ -671,25 +639,23 @@ int HFAGetOverviewCount( HFAHandle hHFA, int nBand )
 /************************************************************************/
 
 CPLErr HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int iOverview,
-                           int * pnXSize, int * pnYSize,
-                           int * pnBlockXSize, int * pnBlockYSize,
-                           EPTType * peHFADataType )
+                           int *pnXSize, int *pnYSize,
+                           int *pnBlockXSize, int *pnBlockYSize,
+                           EPTType *peHFADataType )
 
 {
-    HFABand	*poBand;
-
     if( nBand < 0 || nBand > hHFA->nBands )
     {
-        CPLAssert( FALSE );
+        CPLAssert(false);
         return CE_Failure;
     }
 
-    poBand = hHFA->papoBand[nBand-1];
+    HFABand *poBand = hHFA->papoBand[nBand - 1];
     poBand->LoadOverviews();
 
     if( iOverview < 0 || iOverview >= poBand->nOverviews )
     {
-        CPLAssert( FALSE );
+        CPLAssert(false);
         return CE_Failure;
     }
     poBand = poBand->papoOverviews[iOverview];
@@ -713,7 +679,7 @@ CPLErr HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int iOverview,
     if( peHFADataType != NULL )
         *peHFADataType = poBand->eDataType;
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -721,7 +687,7 @@ CPLErr HFAGetOverviewInfo( HFAHandle hHFA, int nBand, int iOverview,
 /************************************************************************/
 
 CPLErr HFAGetRasterBlock( HFAHandle hHFA, int nBand,
-                          int nXBlock, int nYBlock, void * pData )
+                          int nXBlock, int nYBlock, void *pData )
 
 {
     return HFAGetRasterBlockEx(hHFA, nBand, nXBlock, nYBlock, pData, -1);
@@ -732,13 +698,15 @@ CPLErr HFAGetRasterBlock( HFAHandle hHFA, int nBand,
 /************************************************************************/
 
 CPLErr HFAGetRasterBlockEx( HFAHandle hHFA, int nBand,
-                            int nXBlock, int nYBlock, void * pData, int nDataSize )
+                            int nXBlock, int nYBlock, void *pData,
+                            int nDataSize )
 
 {
     if( nBand < 1 || nBand > hHFA->nBands )
         return CE_Failure;
 
-    return( hHFA->papoBand[nBand-1]->GetRasterBlock(nXBlock,nYBlock,pData,nDataSize) );
+    return hHFA->papoBand[nBand - 1]->
+        GetRasterBlock(nXBlock, nYBlock, pData,nDataSize);
 }
 
 /************************************************************************/
@@ -746,10 +714,11 @@ CPLErr HFAGetRasterBlockEx( HFAHandle hHFA, int nBand,
 /************************************************************************/
 
 CPLErr HFAGetOverviewRasterBlock( HFAHandle hHFA, int nBand, int iOverview,
-                                  int nXBlock, int nYBlock, void * pData )
+                                  int nXBlock, int nYBlock, void *pData )
 
 {
-    return HFAGetOverviewRasterBlockEx(hHFA, nBand, iOverview, nXBlock, nYBlock, pData, -1);
+    return HFAGetOverviewRasterBlockEx(hHFA, nBand, iOverview, nXBlock, nYBlock,
+                                       pData, -1);
 }
 
 /************************************************************************/
@@ -757,17 +726,18 @@ CPLErr HFAGetOverviewRasterBlock( HFAHandle hHFA, int nBand, int iOverview,
 /************************************************************************/
 
 CPLErr HFAGetOverviewRasterBlockEx( HFAHandle hHFA, int nBand, int iOverview,
-                                  int nXBlock, int nYBlock, void * pData, int nDataSize )
+                                    int nXBlock, int nYBlock, void *pData,
+                                    int nDataSize )
 
 {
     if( nBand < 1 || nBand > hHFA->nBands )
         return CE_Failure;
 
-    if( iOverview < 0 || iOverview >= hHFA->papoBand[nBand-1]->nOverviews )
+    if( iOverview < 0 || iOverview >= hHFA->papoBand[nBand - 1]->nOverviews )
         return CE_Failure;
 
-    return( hHFA->papoBand[nBand-1]->papoOverviews[iOverview]->
-            GetRasterBlock(nXBlock,nYBlock,pData, nDataSize) );
+    return hHFA->papoBand[nBand - 1]->papoOverviews[iOverview]->
+        GetRasterBlock(nXBlock, nYBlock, pData, nDataSize);
 }
 
 /************************************************************************/
@@ -775,13 +745,13 @@ CPLErr HFAGetOverviewRasterBlockEx( HFAHandle hHFA, int nBand, int iOverview,
 /************************************************************************/
 
 CPLErr HFASetRasterBlock( HFAHandle hHFA, int nBand,
-                          int nXBlock, int nYBlock, void * pData )
+                          int nXBlock, int nYBlock, void *pData )
 
 {
     if( nBand < 1 || nBand > hHFA->nBands )
         return CE_Failure;
 
-    return( hHFA->papoBand[nBand-1]->SetRasterBlock(nXBlock,nYBlock,pData) );
+    return hHFA->papoBand[nBand - 1]->SetRasterBlock(nXBlock, nYBlock, pData);
 }
 
 /************************************************************************/
@@ -789,29 +759,29 @@ CPLErr HFASetRasterBlock( HFAHandle hHFA, int nBand,
 /************************************************************************/
 
 CPLErr HFASetOverviewRasterBlock( HFAHandle hHFA, int nBand, int iOverview,
-                                  int nXBlock, int nYBlock, void * pData )
+                                  int nXBlock, int nYBlock, void *pData )
 
 {
     if( nBand < 1 || nBand > hHFA->nBands )
         return CE_Failure;
 
-    if( iOverview < 0 || iOverview >= hHFA->papoBand[nBand-1]->nOverviews )
+    if( iOverview < 0 || iOverview >= hHFA->papoBand[nBand - 1]->nOverviews )
         return CE_Failure;
 
-    return( hHFA->papoBand[nBand-1]->papoOverviews[iOverview]->
-            SetRasterBlock(nXBlock,nYBlock,pData) );
+    return hHFA->papoBand[nBand - 1]->papoOverviews[iOverview]->
+        SetRasterBlock(nXBlock, nYBlock, pData);
 }
 
 /************************************************************************/
 /*                         HFAGetBandName()                             */
 /************************************************************************/
 
-const char * HFAGetBandName( HFAHandle hHFA, int nBand )
+const char *HFAGetBandName( HFAHandle hHFA, int nBand )
 {
-  if( nBand < 1 || nBand > hHFA->nBands )
-    return "";
+    if( nBand < 1 || nBand > hHFA->nBands )
+        return "";
 
-  return( hHFA->papoBand[nBand-1]->GetBandName() );
+    return hHFA->papoBand[nBand - 1]->GetBandName();
 }
 
 /************************************************************************/
@@ -820,10 +790,10 @@ const char * HFAGetBandName( HFAHandle hHFA, int nBand )
 
 void HFASetBandName( HFAHandle hHFA, int nBand, const char *pszName )
 {
-  if( nBand < 1 || nBand > hHFA->nBands )
-    return;
+    if( nBand < 1 || nBand > hHFA->nBands )
+      return;
 
-  hHFA->papoBand[nBand-1]->SetBandName( pszName );
+    hHFA->papoBand[nBand - 1]->SetBandName(pszName);
 }
 
 /************************************************************************/
@@ -835,37 +805,37 @@ int HFAGetDataTypeBits( EPTType eDataType )
 {
     switch( eDataType )
     {
-      case EPT_u1:
+    case EPT_u1:
         return 1;
 
-      case EPT_u2:
+    case EPT_u2:
         return 2;
 
-      case EPT_u4:
+    case EPT_u4:
         return 4;
 
-      case EPT_u8:
-      case EPT_s8:
+    case EPT_u8:
+    case EPT_s8:
         return 8;
 
-      case EPT_u16:
-      case EPT_s16:
+    case EPT_u16:
+    case EPT_s16:
         return 16;
 
-      case EPT_u32:
-      case EPT_s32:
-      case EPT_f32:
+    case EPT_u32:
+    case EPT_s32:
+    case EPT_f32:
         return 32;
 
-      case EPT_f64:
-      case EPT_c64:
+    case EPT_f64:
+    case EPT_c64:
         return 64;
 
-      case EPT_c128:
+    case EPT_c128:
         return 128;
     }
 
-    CPLAssert(FALSE);
+    CPLAssert(false);
     return 1;
 }
 
@@ -878,47 +848,47 @@ const char *HFAGetDataTypeName( EPTType eDataType )
 {
     switch( eDataType )
     {
-      case EPT_u1:
+    case EPT_u1:
         return "u1";
 
-      case EPT_u2:
+    case EPT_u2:
         return "u2";
 
-      case EPT_u4:
+    case EPT_u4:
         return "u4";
 
-      case EPT_u8:
+    case EPT_u8:
         return "u8";
 
-      case EPT_s8:
+    case EPT_s8:
         return "s8";
 
-      case EPT_u16:
+    case EPT_u16:
         return "u16";
 
-      case EPT_s16:
+    case EPT_s16:
         return "s16";
 
-      case EPT_u32:
+    case EPT_u32:
         return "u32";
 
-      case EPT_s32:
+    case EPT_s32:
         return "s32";
 
-      case EPT_f32:
+    case EPT_f32:
         return "f32";
 
-      case EPT_f64:
+    case EPT_f64:
         return "f64";
 
-      case EPT_c64:
+    case EPT_c64:
         return "c64";
 
-      case EPT_c128:
+    case EPT_c128:
         return "c128";
 
-      default:
-        CPLAssert(FALSE);
+    default:
+        CPLAssert(false);
         return "unknown";
     }
 }
@@ -930,31 +900,23 @@ const char *HFAGetDataTypeName( EPTType eDataType )
 const Eprj_MapInfo *HFAGetMapInfo( HFAHandle hHFA )
 
 {
-    HFAEntry	*poMIEntry;
-    Eprj_MapInfo *psMapInfo;
-
     if( hHFA->nBands < 1 )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Do we already have it?                                          */
-/* -------------------------------------------------------------------- */
+    // Do we already have it?
     if( hHFA->pMapInfo != NULL )
-        return( (Eprj_MapInfo *) hHFA->pMapInfo );
+        return (Eprj_MapInfo *)hHFA->pMapInfo;
 
-/* -------------------------------------------------------------------- */
-/*      Get the HFA node.  If we don't find it under the usual name     */
-/*      we search for any node of the right type (#3338).               */
-/* -------------------------------------------------------------------- */
-    poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild( "Map_Info" );
+    // Get the HFA node.  If we don't find it under the usual name
+    // we search for any node of the right type (#3338).
+    HFAEntry *poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild("Map_Info");
     if( poMIEntry == NULL )
     {
-        HFAEntry *poChild;
-        for( poChild = hHFA->papoBand[0]->poNode->GetChild();
+        for( HFAEntry *poChild = hHFA->papoBand[0]->poNode->GetChild();
              poChild != NULL && poMIEntry == NULL;
              poChild = poChild->GetNext() )
         {
-            if( EQUAL(poChild->GetType(),"Eprj_MapInfo") )
+            if( EQUAL(poChild->GetType(), "Eprj_MapInfo") )
                 poMIEntry = poChild;
         }
     }
@@ -964,16 +926,11 @@ const Eprj_MapInfo *HFAGetMapInfo( HFAHandle hHFA )
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Allocate the structure.                                         */
-/* -------------------------------------------------------------------- */
-    psMapInfo = (Eprj_MapInfo *) CPLCalloc(sizeof(Eprj_MapInfo),1);
-
-/* -------------------------------------------------------------------- */
-/*      Fetch the fields.                                               */
-/* -------------------------------------------------------------------- */
-    CPLErr eErr;
+    // Allocate the structure.
+    Eprj_MapInfo *psMapInfo =
+        static_cast<Eprj_MapInfo *>(CPLCalloc(sizeof(Eprj_MapInfo), 1));
 
+    // Fetch the fields.
     psMapInfo->proName = CPLStrdup(poMIEntry->GetStringField("proName"));
 
     psMapInfo->upperLeftCenter.x =
@@ -986,50 +943,44 @@ const Eprj_MapInfo *HFAGetMapInfo( HFAHandle hHFA )
     psMapInfo->lowerRightCenter.y =
         poMIEntry->GetDoubleField("lowerRightCenter.y");
 
-   psMapInfo->pixelSize.width =
-       poMIEntry->GetDoubleField("pixelSize.width",&eErr);
-   psMapInfo->pixelSize.height =
-       poMIEntry->GetDoubleField("pixelSize.height",&eErr);
+    CPLErr eErr = CE_None;
+    psMapInfo->pixelSize.width =
+        poMIEntry->GetDoubleField("pixelSize.width", &eErr);
+    psMapInfo->pixelSize.height =
+        poMIEntry->GetDoubleField("pixelSize.height", &eErr);
 
-   // The following is basically a hack to get files with
-   // non-standard MapInfo's that misname the pixelSize fields. (#3338)
-   if( eErr != CE_None )
-   {
-       psMapInfo->pixelSize.width =
-           poMIEntry->GetDoubleField("pixelSize.x");
-       psMapInfo->pixelSize.height =
-           poMIEntry->GetDoubleField("pixelSize.y");
-   }
+    // The following is basically a hack to get files with
+    // non-standard MapInfo's that misname the pixelSize fields. (#3338)
+    if( eErr != CE_None )
+    {
+        psMapInfo->pixelSize.width = poMIEntry->GetDoubleField("pixelSize.x");
+        psMapInfo->pixelSize.height = poMIEntry->GetDoubleField("pixelSize.y");
+    }
 
-   psMapInfo->units = CPLStrdup(poMIEntry->GetStringField("units"));
+    psMapInfo->units = CPLStrdup(poMIEntry->GetStringField("units"));
 
-   hHFA->pMapInfo = (void *) psMapInfo;
+    hHFA->pMapInfo = (void *)psMapInfo;
 
-   return psMapInfo;
+    return psMapInfo;
 }
 
 /************************************************************************/
 /*                        HFAInvGeoTransform()                          */
 /************************************************************************/
 
-static int HFAInvGeoTransform( double *gt_in, double *gt_out )
+static bool HFAInvGeoTransform( const double *gt_in, double *gt_out )
 
 {
-    double det, inv_det;
-
-    /* we assume a 3rd row that is [1 0 0] */
+    // Assume a 3rd row that is [1 0 0].
+    // Compute determinate.
+    const double det = gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4];
 
-    /* Compute determinate */
+    if( fabs(det) < 1.0e-15 )
+        return false;
 
-    det = gt_in[1] * gt_in[5] - gt_in[2] * gt_in[4];
-
-    if( fabs(det) < 0.000000000000001 )
-        return 0;
-
-    inv_det = 1.0 / det;
-
-    /* compute adjoint, and divide by determinate */
+    const double inv_det = 1.0 / det;
 
+    // Compute adjoint, and divide by determinate.
     gt_out[1] =  gt_in[5] * inv_det;
     gt_out[4] = -gt_in[4] * inv_det;
 
@@ -1039,7 +990,7 @@ static int HFAInvGeoTransform( double *gt_in, double *gt_out )
     gt_out[0] = ( gt_in[2] * gt_in[3] - gt_in[0] * gt_in[5]) * inv_det;
     gt_out[3] = (-gt_in[1] * gt_in[3] + gt_in[0] * gt_in[4]) * inv_det;
 
-    return 1;
+    return true;
 }
 
 /************************************************************************/
@@ -1049,7 +1000,7 @@ static int HFAInvGeoTransform( double *gt_in, double *gt_out )
 int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
 
 {
-    const Eprj_MapInfo *psMapInfo = HFAGetMapInfo( hHFA );
+    const Eprj_MapInfo *psMapInfo = HFAGetMapInfo(hHFA);
 
     padfGeoTransform[0] = 0.0;
     padfGeoTransform[1] = 1.0;
@@ -1058,30 +1009,28 @@ int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
     padfGeoTransform[4] = 0.0;
     padfGeoTransform[5] = 1.0;
 
-/* -------------------------------------------------------------------- */
-/*      Simple (north up) MapInfo approach.                             */
-/* -------------------------------------------------------------------- */
+    // Simple (north up) MapInfo approach.
     if( psMapInfo != NULL )
     {
-        padfGeoTransform[0] = psMapInfo->upperLeftCenter.x
-            - psMapInfo->pixelSize.width*0.5;
+        padfGeoTransform[0] =
+            psMapInfo->upperLeftCenter.x - psMapInfo->pixelSize.width * 0.5;
         padfGeoTransform[1] = psMapInfo->pixelSize.width;
-        if(padfGeoTransform[1] == 0.0)
+        if( padfGeoTransform[1] == 0.0 )
             padfGeoTransform[1] = 1.0;
         padfGeoTransform[2] = 0.0;
         if( psMapInfo->upperLeftCenter.y >= psMapInfo->lowerRightCenter.y )
-            padfGeoTransform[5] = - psMapInfo->pixelSize.height;
+            padfGeoTransform[5] = -psMapInfo->pixelSize.height;
         else
             padfGeoTransform[5] = psMapInfo->pixelSize.height;
-        if(padfGeoTransform[5] == 0.0)
+        if( padfGeoTransform[5] == 0.0 )
             padfGeoTransform[5] = 1.0;
 
-        padfGeoTransform[3] = psMapInfo->upperLeftCenter.y
-            - padfGeoTransform[5]*0.5;
+        padfGeoTransform[3] =
+            psMapInfo->upperLeftCenter.y - padfGeoTransform[5] * 0.5;
         padfGeoTransform[4] = 0.0;
 
-        // special logic to fixup odd angular units.
-        if( EQUAL(psMapInfo->units,"ds") )
+        // Special logic to fixup odd angular units.
+        if( EQUAL(psMapInfo->units, "ds") )
         {
             padfGeoTransform[0] /= 3600.0;
             padfGeoTransform[1] /= 3600.0;
@@ -1094,51 +1043,48 @@ int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
         return TRUE;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try for a MapToPixelXForm affine polynomial supporting          */
-/*      rotated and sheared affine transformations.                     */
-/* -------------------------------------------------------------------- */
+    // Try for a MapToPixelXForm affine polynomial supporting
+    // rotated and sheared affine transformations.
     if( hHFA->nBands == 0 )
         return FALSE;
 
     HFAEntry *poXForm0 =
-        hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm0" );
+        hHFA->papoBand[0]->poNode->GetNamedChild("MapToPixelXForm.XForm0");
 
     if( poXForm0 == NULL )
         return FALSE;
 
-    if( poXForm0->GetIntField( "order" ) != 1
-        || poXForm0->GetIntField( "numdimtransform" ) != 2
-        || poXForm0->GetIntField( "numdimpolynomial" ) != 2
-        || poXForm0->GetIntField( "termcount" ) != 3 )
+    if( poXForm0->GetIntField("order") != 1 ||
+        poXForm0->GetIntField("numdimtransform") != 2 ||
+        poXForm0->GetIntField("numdimpolynomial") != 2 ||
+        poXForm0->GetIntField("termcount") != 3 )
         return FALSE;
 
     // Verify that there aren't any further xform steps.
-    if( hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm1" )
+    if( hHFA->papoBand[0]->poNode->GetNamedChild("MapToPixelXForm.XForm1")
         != NULL )
         return FALSE;
 
-    // we should check that the exponent list is 0 0 1 0 0 1 but
-    // we don't because we are lazy
-
-    // fetch geotransform values.
-    double adfXForm[6];
+    // We should check that the exponent list is 0 0 1 0 0 1, but
+    // we don't because we are lazy.
 
-    adfXForm[0] = poXForm0->GetDoubleField( "polycoefvector[0]" );
-    adfXForm[1] = poXForm0->GetDoubleField( "polycoefmtx[0]" );
-    adfXForm[4] = poXForm0->GetDoubleField( "polycoefmtx[1]" );
-    adfXForm[3] = poXForm0->GetDoubleField( "polycoefvector[1]" );
-    adfXForm[2] = poXForm0->GetDoubleField( "polycoefmtx[2]" );
-    adfXForm[5] = poXForm0->GetDoubleField( "polycoefmtx[3]" );
+    // Fetch geotransform values.
+    double adfXForm[6] = {
+        poXForm0->GetDoubleField("polycoefvector[0]"),
+        poXForm0->GetDoubleField("polycoefmtx[0]"),
+        poXForm0->GetDoubleField("polycoefmtx[2]"),
+        poXForm0->GetDoubleField("polycoefvector[1]"),
+        poXForm0->GetDoubleField("polycoefmtx[1]"),
+        poXForm0->GetDoubleField("polycoefmtx[3]")
+    };
 
-    // invert
+    // Invert.
 
-    if( !HFAInvGeoTransform( adfXForm, padfGeoTransform ) )
-        memset( padfGeoTransform, 0, 6 * sizeof(double) );
+    if( !HFAInvGeoTransform(adfXForm, padfGeoTransform) )
+        memset(padfGeoTransform, 0, 6 * sizeof(double));
 
     // Adjust origin from center of top left pixel to top left corner
     // of top left pixel.
-
     padfGeoTransform[0] -= padfGeoTransform[1] * 0.5;
     padfGeoTransform[0] -= padfGeoTransform[2] * 0.5;
     padfGeoTransform[3] -= padfGeoTransform[4] * 0.5;
@@ -1154,61 +1100,51 @@ int HFAGetGeoTransform( HFAHandle hHFA, double *padfGeoTransform )
 CPLErr HFASetMapInfo( HFAHandle hHFA, const Eprj_MapInfo *poMapInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Loop over bands, setting information on each one.               */
-/* -------------------------------------------------------------------- */
+    // Loop over bands, setting information on each one.
     for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
     {
-        HFAEntry	*poMIEntry;
-
-/* -------------------------------------------------------------------- */
-/*      Create a new Map_Info if there isn't one present already.       */
-/* -------------------------------------------------------------------- */
-        poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild( "Map_Info" );
+        // Create a new Map_Info if there isn't one present already.
+        HFAEntry *poMIEntry =
+            hHFA->papoBand[iBand]->poNode->GetNamedChild("Map_Info");
         if( poMIEntry == NULL )
         {
-            poMIEntry = HFAEntry::New( hHFA, "Map_Info", "Eprj_MapInfo",
-                                      hHFA->papoBand[iBand]->poNode );
+            poMIEntry = HFAEntry::New(hHFA, "Map_Info", "Eprj_MapInfo",
+                                      hHFA->papoBand[iBand]->poNode);
         }
 
         poMIEntry->MarkDirty();
 
-/* -------------------------------------------------------------------- */
-/*      Ensure we have enough space for all the data.                   */
-/* -------------------------------------------------------------------- */
-        int	nSize;
-        GByte   *pabyData;
-
-        nSize = static_cast<int>(48 + 40
+        // Ensure we have enough space for all the data.
+        // TODO(schwehr): Explain 48 and 40 constants.
+        const int nSize = static_cast<int>(
+            48 + 40
             + strlen(poMapInfo->proName) + 1
             + strlen(poMapInfo->units) + 1);
 
-        pabyData = poMIEntry->MakeData( nSize );
-        memset( pabyData, 0, nSize );
+        GByte *pabyData = poMIEntry->MakeData(nSize);
+        memset(pabyData, 0, nSize);
 
         poMIEntry->SetPosition();
 
-/* -------------------------------------------------------------------- */
-/*      Write the various fields.                                       */
-/* -------------------------------------------------------------------- */
-        poMIEntry->SetStringField( "proName", poMapInfo->proName );
+        // Write the various fields.
+        poMIEntry->SetStringField("proName", poMapInfo->proName);
 
-        poMIEntry->SetDoubleField( "upperLeftCenter.x",
-                                   poMapInfo->upperLeftCenter.x );
-        poMIEntry->SetDoubleField( "upperLeftCenter.y",
-                                   poMapInfo->upperLeftCenter.y );
+        poMIEntry->SetDoubleField("upperLeftCenter.x",
+                                  poMapInfo->upperLeftCenter.x);
+        poMIEntry->SetDoubleField("upperLeftCenter.y",
+                                  poMapInfo->upperLeftCenter.y);
 
-        poMIEntry->SetDoubleField( "lowerRightCenter.x",
-                                   poMapInfo->lowerRightCenter.x );
-        poMIEntry->SetDoubleField( "lowerRightCenter.y",
-                                   poMapInfo->lowerRightCenter.y );
+        poMIEntry->SetDoubleField("lowerRightCenter.x",
+                                  poMapInfo->lowerRightCenter.x);
+        poMIEntry->SetDoubleField("lowerRightCenter.y",
+                                  poMapInfo->lowerRightCenter.y);
 
-        poMIEntry->SetDoubleField( "pixelSize.width",
-                                   poMapInfo->pixelSize.width );
-        poMIEntry->SetDoubleField( "pixelSize.height",
-                                   poMapInfo->pixelSize.height );
+        poMIEntry->SetDoubleField("pixelSize.width",
+                                  poMapInfo->pixelSize.width);
+        poMIEntry->SetDoubleField("pixelSize.height",
+                                  poMapInfo->pixelSize.height);
 
-        poMIEntry->SetStringField( "units", poMapInfo->units );
+        poMIEntry->SetStringField("units", poMapInfo->units);
     }
 
     return CE_None;
@@ -1227,29 +1163,23 @@ char *HFAGetPEString( HFAHandle hHFA )
     if( hHFA->nBands == 0 )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Get the HFA node.                                               */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poProX;
-
-    poProX = hHFA->papoBand[0]->poNode->GetNamedChild( "ProjectionX" );
+    // Get the HFA node.
+    HFAEntry *poProX = hHFA->papoBand[0]->poNode->GetNamedChild("ProjectionX");
     if( poProX == NULL )
         return NULL;
 
-    const char *pszType = poProX->GetStringField( "projection.type.string" );
-    if( pszType == NULL || !EQUAL(pszType,"PE_COORDSYS") )
+    const char *pszType = poProX->GetStringField("projection.type.string");
+    if( pszType == NULL || !EQUAL(pszType, "PE_COORDSYS") )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Use a gross hack to scan ahead to the actual projection         */
-/*      string. We do it this way because we don't have general         */
-/*      handling for MIFObjects.                                        */
-/* -------------------------------------------------------------------- */
+    // Use a gross hack to scan ahead to the actual projection
+    // string. We do it this way because we don't have general
+    // handling for MIFObjects.
     GByte *pabyData = poProX->GetData();
-    int    nDataSize = poProX->GetDataSize();
+    int nDataSize = poProX->GetDataSize();
 
-    while( nDataSize > 10
-           && !STARTS_WITH_CI((const char *) pabyData, "PE_COORDSYS,.") ) {
+    while( nDataSize > 10 &&
+           !STARTS_WITH_CI((const char *)pabyData, "PE_COORDSYS,.") ) {
         pabyData++;
         nDataSize--;
     }
@@ -1257,13 +1187,11 @@ char *HFAGetPEString( HFAHandle hHFA )
     if( nDataSize < 31 )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Skip ahead to the actual string.                                */
-/* -------------------------------------------------------------------- */
+    // Skip ahead to the actual string.
     pabyData += 30;
-    /*nDataSize -= 30;*/
+    // nDataSize -= 30;
 
-    return CPLStrdup( (const char *) pabyData );
+    return CPLStrdup((const char *)pabyData);
 }
 
 /************************************************************************/
@@ -1273,111 +1201,91 @@ char *HFAGetPEString( HFAHandle hHFA )
 CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Loop over bands, setting information on each one.               */
-/* -------------------------------------------------------------------- */
-    int iBand;
-
-    for( iBand = 0; iBand < hHFA->nBands; iBand++ )
+    // Loop over bands, setting information on each one.
+    for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
     {
-        HFAEntry *poProX;
-
-/* -------------------------------------------------------------------- */
-/*      Verify we don't already have the node, since update-in-place    */
-/*      is likely to be more complicated.                               */
-/* -------------------------------------------------------------------- */
-        poProX = hHFA->papoBand[iBand]->poNode->GetNamedChild( "ProjectionX" );
+        // Verify we don't already have the node, since update-in-place
+        // is likely to be more complicated.
+        HFAEntry *poProX =
+            hHFA->papoBand[iBand]->poNode->GetNamedChild("ProjectionX");
 
-/* -------------------------------------------------------------------- */
-/*      If we are setting an empty string then a missing entry is       */
-/*      equivalent.                                                     */
-/* -------------------------------------------------------------------- */
+        // If we are setting an empty string then a missing entry is equivalent.
         if( strlen(pszPEString) == 0 && poProX == NULL )
             continue;
 
-/* -------------------------------------------------------------------- */
-/*      Create the node.                                                */
-/* -------------------------------------------------------------------- */
+        // Create the node.
         if( poProX == NULL )
         {
-            poProX = HFAEntry::New( hHFA, "ProjectionX","Eprj_MapProjection842",
-                                   hHFA->papoBand[iBand]->poNode );
+            poProX = HFAEntry::New(hHFA, "ProjectionX", "Eprj_MapProjection842",
+                                   hHFA->papoBand[iBand]->poNode);
             if( poProX->GetTypeObject() == NULL )
                 return CE_Failure;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Prepare the data area with some extra space just in case.       */
-/* -------------------------------------------------------------------- */
-        GByte *pabyData = poProX->MakeData( static_cast<int>(700 + strlen(pszPEString)) );
+        // Prepare the data area with some extra space just in case.
+        GByte *pabyData =
+            poProX->MakeData(static_cast<int>(700 + strlen(pszPEString)));
         if( !pabyData )
           return CE_Failure;
 
-        memset( pabyData, 0, 250+strlen(pszPEString) );
+        memset(pabyData, 0, 250 + strlen(pszPEString));
 
         poProX->SetPosition();
 
-        poProX->SetStringField( "projection.type.string", "PE_COORDSYS" );
-        poProX->SetStringField( "projection.MIFDictionary.string",
-                                "{0:pcstring,}Emif_String,{1:x{0:pcstring,}Emif_String,coordSys,}PE_COORDSYS,." );
+        poProX->SetStringField("projection.type.string", "PE_COORDSYS");
+        poProX->SetStringField("projection.MIFDictionary.string",
+                               "{0:pcstring,}Emif_String,{1:x{0:pcstring,}"
+                               "Emif_String,coordSys,}PE_COORDSYS,.");
 
-/* -------------------------------------------------------------------- */
-/*      Use a gross hack to scan ahead to the actual projection         */
-/*      string. We do it this way because we don't have general         */
-/*      handling for MIFObjects.                                        */
-/* -------------------------------------------------------------------- */
+        // Use a gross hack to scan ahead to the actual projection
+        // string. We do it this way because we don't have general
+        // handling for MIFObjects
         pabyData = poProX->GetData();
-        int    nDataSize = poProX->GetDataSize();
-        GUInt32   iOffset = poProX->GetDataPos();
-        GUInt32   nSize;
+        int nDataSize = poProX->GetDataSize();
+        GUInt32 iOffset = poProX->GetDataPos();
 
-        while( nDataSize > 10
-               && !STARTS_WITH_CI((const char *) pabyData, "PE_COORDSYS,.") ) {
+        while( nDataSize > 10 &&
+               !STARTS_WITH_CI((const char *) pabyData, "PE_COORDSYS,.") )
+        {
             pabyData++;
             nDataSize--;
             iOffset++;
         }
 
-        CPLAssert( nDataSize > (int) strlen(pszPEString) + 10 );
+        CPLAssert(nDataSize > static_cast<int>(strlen(pszPEString)) + 10);
 
         pabyData += 14;
         iOffset += 14;
 
-/* -------------------------------------------------------------------- */
-/*      Set the size and offset of the mifobject.                       */
-/* -------------------------------------------------------------------- */
+        // Set the size and offset of the mifobject.
         iOffset += 8;
 
-        nSize = static_cast<GUInt32>(strlen(pszPEString) + 9);
+        GUInt32 nSize = static_cast<GUInt32>(strlen(pszPEString) + 9);
 
-        HFAStandard( 4, &nSize );
-        memcpy( pabyData, &nSize, 4 );
+        HFAStandard(4, &nSize);
+        memcpy(pabyData, &nSize, 4);
         pabyData += 4;
 
-        HFAStandard( 4, &iOffset );
-        memcpy( pabyData, &iOffset, 4 );
+        HFAStandard(4, &iOffset);
+        memcpy(pabyData, &iOffset, 4);
         pabyData += 4;
 
-/* -------------------------------------------------------------------- */
-/*      Set the size and offset of the string value.                    */
-/* -------------------------------------------------------------------- */
+        // Set the size and offset of the string value.
         nSize = static_cast<GUInt32>(strlen(pszPEString) + 1);
 
-        HFAStandard( 4, &nSize );
-        memcpy( pabyData, &nSize, 4 );
+        HFAStandard(4, &nSize);
+        memcpy(pabyData, &nSize, 4);
         pabyData += 4;
 
         iOffset = 8;
-        HFAStandard( 4, &iOffset );
-        memcpy( pabyData, &iOffset, 4 );
+        HFAStandard(4, &iOffset);
+        memcpy(pabyData, &iOffset, 4);
         pabyData += 4;
 
-/* -------------------------------------------------------------------- */
-/*      Place the string itself.                                        */
-/* -------------------------------------------------------------------- */
-        memcpy( pabyData, pszPEString, strlen(pszPEString)+1 );
+        // Place the string itself.
+        memcpy(pabyData, pszPEString, strlen(pszPEString) + 1);
 
-        poProX->SetStringField( "title.string", "PE" );
+        poProX->SetStringField("title.string", "PE");
     }
 
     return CE_None;
@@ -1390,45 +1298,35 @@ CPLErr HFASetPEString( HFAHandle hHFA, const char *pszPEString )
 const Eprj_ProParameters *HFAGetProParameters( HFAHandle hHFA )
 
 {
-    HFAEntry	*poMIEntry;
-    Eprj_ProParameters *psProParms;
-    int		i;
-
     if( hHFA->nBands < 1 )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Do we already have it?                                          */
-/* -------------------------------------------------------------------- */
+    // Do we already have it?
     if( hHFA->pProParameters != NULL )
-        return( (Eprj_ProParameters *) hHFA->pProParameters );
+        return (Eprj_ProParameters *)hHFA->pProParameters;
 
-/* -------------------------------------------------------------------- */
-/*      Get the HFA node.                                               */
-/* -------------------------------------------------------------------- */
-    poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild( "Projection" );
+    // Get the HFA node.
+    HFAEntry *poMIEntry =
+        hHFA->papoBand[0]->poNode->GetNamedChild("Projection");
     if( poMIEntry == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Allocate the structure.                                         */
-/* -------------------------------------------------------------------- */
-    psProParms = (Eprj_ProParameters *)CPLCalloc(sizeof(Eprj_ProParameters),1);
+    // Allocate the structure.
+    Eprj_ProParameters *psProParms = static_cast<Eprj_ProParameters *>(
+        CPLCalloc(sizeof(Eprj_ProParameters), 1));
 
-/* -------------------------------------------------------------------- */
-/*      Fetch the fields.                                               */
-/* -------------------------------------------------------------------- */
-    psProParms->proType = (Eprj_ProType) poMIEntry->GetIntField("proType");
+    // Fetch the fields.
+    psProParms->proType = (Eprj_ProType)poMIEntry->GetIntField("proType");
     psProParms->proNumber = poMIEntry->GetIntField("proNumber");
-    psProParms->proExeName =CPLStrdup(poMIEntry->GetStringField("proExeName"));
+    psProParms->proExeName = CPLStrdup(poMIEntry->GetStringField("proExeName"));
     psProParms->proName = CPLStrdup(poMIEntry->GetStringField("proName"));
     psProParms->proZone = poMIEntry->GetIntField("proZone");
 
-    for( i = 0; i < 15; i++ )
+    for( int i = 0; i < 15; i++ )
     {
-        char	szFieldName[40];
+        char szFieldName[40] = {};
 
-        snprintf( szFieldName, sizeof(szFieldName), "proParams[%d]", i );
+        snprintf(szFieldName, sizeof(szFieldName), "proParams[%d]", i);
         psProParms->proParams[i] = poMIEntry->GetDoubleField(szFieldName);
     }
 
@@ -1441,7 +1339,7 @@ const Eprj_ProParameters *HFAGetProParameters( HFAHandle hHFA )
     psProParms->proSpheroid.radius =
         poMIEntry->GetDoubleField("proSpheroid.radius");
 
-    hHFA->pProParameters = (void *) psProParms;
+    hHFA->pProParameters = (void *)psProParms;
 
     return psProParms;
 }
@@ -1453,82 +1351,69 @@ const Eprj_ProParameters *HFAGetProParameters( HFAHandle hHFA )
 CPLErr HFASetProParameters( HFAHandle hHFA, const Eprj_ProParameters *poPro )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Loop over bands, setting information on each one.               */
-/* -------------------------------------------------------------------- */
+    // Loop over bands, setting information on each one.
     for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
     {
-        HFAEntry	*poMIEntry;
-
-/* -------------------------------------------------------------------- */
-/*      Create a new Projection if there isn't one present already.     */
-/* -------------------------------------------------------------------- */
-        poMIEntry = hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection");
+        // Create a new Projection if there isn't one present already.
+        HFAEntry *poMIEntry =
+            hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection");
         if( poMIEntry == NULL )
         {
-            poMIEntry = HFAEntry::New( hHFA, "Projection","Eprj_ProParameters",
-                                      hHFA->papoBand[iBand]->poNode );
+            poMIEntry = HFAEntry::New(hHFA, "Projection", "Eprj_ProParameters",
+                                      hHFA->papoBand[iBand]->poNode);
         }
 
         poMIEntry->MarkDirty();
 
-/* -------------------------------------------------------------------- */
-/*      Ensure we have enough space for all the data.                   */
-/* -------------------------------------------------------------------- */
-        int	nSize;
-        GByte   *pabyData;
-
-        nSize = static_cast<int>(34 + 15 * 8
-            + 8 + strlen(poPro->proName) + 1
-            + 32 + 8 + strlen(poPro->proSpheroid.sphereName) + 1);
+        // Ensure we have enough space for all the data.
+        // TODO(schwehr): Explain all these constants.
+        int nSize =
+            static_cast<int>(34 + 15 * 8 + 8 + strlen(poPro->proName) + 1 + 32 +
+                             8 + strlen(poPro->proSpheroid.sphereName) + 1);
 
         if( poPro->proExeName != NULL )
             nSize += static_cast<int>(strlen(poPro->proExeName) + 1);
 
-        pabyData = poMIEntry->MakeData( nSize );
-        if(!pabyData)
+        GByte *pabyData = poMIEntry->MakeData(nSize);
+        if( !pabyData )
             return CE_Failure;
 
         poMIEntry->SetPosition();
 
         // Initialize the whole thing to zeros for a clean start.
-        memset( poMIEntry->GetData(), 0, poMIEntry->GetDataSize() );
-
-/* -------------------------------------------------------------------- */
-/*      Write the various fields.                                       */
-/* -------------------------------------------------------------------- */
-        poMIEntry->SetIntField( "proType", poPro->proType );
-
-        poMIEntry->SetIntField( "proNumber", poPro->proNumber );
-
-        poMIEntry->SetStringField( "proExeName", poPro->proExeName );
-        poMIEntry->SetStringField( "proName", poPro->proName );
-        poMIEntry->SetIntField( "proZone", poPro->proZone );
-        poMIEntry->SetDoubleField( "proParams[0]", poPro->proParams[0] );
-        poMIEntry->SetDoubleField( "proParams[1]", poPro->proParams[1] );
-        poMIEntry->SetDoubleField( "proParams[2]", poPro->proParams[2] );
-        poMIEntry->SetDoubleField( "proParams[3]", poPro->proParams[3] );
-        poMIEntry->SetDoubleField( "proParams[4]", poPro->proParams[4] );
-        poMIEntry->SetDoubleField( "proParams[5]", poPro->proParams[5] );
-        poMIEntry->SetDoubleField( "proParams[6]", poPro->proParams[6] );
-        poMIEntry->SetDoubleField( "proParams[7]", poPro->proParams[7] );
-        poMIEntry->SetDoubleField( "proParams[8]", poPro->proParams[8] );
-        poMIEntry->SetDoubleField( "proParams[9]", poPro->proParams[9] );
-        poMIEntry->SetDoubleField( "proParams[10]", poPro->proParams[10] );
-        poMIEntry->SetDoubleField( "proParams[11]", poPro->proParams[11] );
-        poMIEntry->SetDoubleField( "proParams[12]", poPro->proParams[12] );
-        poMIEntry->SetDoubleField( "proParams[13]", poPro->proParams[13] );
-        poMIEntry->SetDoubleField( "proParams[14]", poPro->proParams[14] );
-        poMIEntry->SetStringField( "proSpheroid.sphereName",
-                                   poPro->proSpheroid.sphereName );
-        poMIEntry->SetDoubleField( "proSpheroid.a",
-                                   poPro->proSpheroid.a );
-        poMIEntry->SetDoubleField( "proSpheroid.b",
-                                   poPro->proSpheroid.b );
-        poMIEntry->SetDoubleField( "proSpheroid.eSquared",
-                                   poPro->proSpheroid.eSquared );
-        poMIEntry->SetDoubleField( "proSpheroid.radius",
-                                   poPro->proSpheroid.radius );
+        memset(poMIEntry->GetData(), 0, poMIEntry->GetDataSize());
+
+        // Write the various fields.
+        poMIEntry->SetIntField("proType", poPro->proType);
+
+        poMIEntry->SetIntField("proNumber", poPro->proNumber);
+
+        poMIEntry->SetStringField("proExeName", poPro->proExeName);
+        poMIEntry->SetStringField("proName", poPro->proName);
+        poMIEntry->SetIntField("proZone", poPro->proZone);
+        poMIEntry->SetDoubleField("proParams[0]", poPro->proParams[0]);
+        poMIEntry->SetDoubleField("proParams[1]", poPro->proParams[1]);
+        poMIEntry->SetDoubleField("proParams[2]", poPro->proParams[2]);
+        poMIEntry->SetDoubleField("proParams[3]", poPro->proParams[3]);
+        poMIEntry->SetDoubleField("proParams[4]", poPro->proParams[4]);
+        poMIEntry->SetDoubleField("proParams[5]", poPro->proParams[5]);
+        poMIEntry->SetDoubleField("proParams[6]", poPro->proParams[6]);
+        poMIEntry->SetDoubleField("proParams[7]", poPro->proParams[7]);
+        poMIEntry->SetDoubleField("proParams[8]", poPro->proParams[8]);
+        poMIEntry->SetDoubleField("proParams[9]", poPro->proParams[9]);
+        poMIEntry->SetDoubleField("proParams[10]", poPro->proParams[10]);
+        poMIEntry->SetDoubleField("proParams[11]", poPro->proParams[11]);
+        poMIEntry->SetDoubleField("proParams[12]", poPro->proParams[12]);
+        poMIEntry->SetDoubleField("proParams[13]", poPro->proParams[13]);
+        poMIEntry->SetDoubleField("proParams[14]", poPro->proParams[14]);
+        poMIEntry->SetStringField("proSpheroid.sphereName",
+                                  poPro->proSpheroid.sphereName);
+        poMIEntry->SetDoubleField("proSpheroid.a", poPro->proSpheroid.a);
+        poMIEntry->SetDoubleField("proSpheroid.b", poPro->proSpheroid.b);
+        poMIEntry->SetDoubleField("proSpheroid.eSquared",
+                                  poPro->proSpheroid.eSquared);
+        poMIEntry->SetDoubleField("proSpheroid.radius",
+                                  poPro->proSpheroid.radius);
     }
 
     return CE_None;
@@ -1541,36 +1426,26 @@ CPLErr HFASetProParameters( HFAHandle hHFA, const Eprj_ProParameters *poPro )
 const Eprj_Datum *HFAGetDatum( HFAHandle hHFA )
 
 {
-    HFAEntry	*poMIEntry;
-    Eprj_Datum	*psDatum;
-    int		i;
-
     if( hHFA->nBands < 1 )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Do we already have it?                                          */
-/* -------------------------------------------------------------------- */
+    // Do we already have it?
     if( hHFA->pDatum != NULL )
-        return( (Eprj_Datum *) hHFA->pDatum );
+        return (Eprj_Datum *)hHFA->pDatum;
 
-/* -------------------------------------------------------------------- */
-/*      Get the HFA node.                                               */
-/* -------------------------------------------------------------------- */
-    poMIEntry = hHFA->papoBand[0]->poNode->GetNamedChild( "Projection.Datum" );
+    // Get the HFA node.
+    HFAEntry *poMIEntry =
+        hHFA->papoBand[0]->poNode->GetNamedChild("Projection.Datum");
     if( poMIEntry == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Allocate the structure.                                         */
-/* -------------------------------------------------------------------- */
-    psDatum = (Eprj_Datum *) CPLCalloc(sizeof(Eprj_Datum),1);
+    // Allocate the structure.
+    Eprj_Datum *psDatum =
+        static_cast<Eprj_Datum *>(CPLCalloc(sizeof(Eprj_Datum), 1));
 
-/* -------------------------------------------------------------------- */
-/*      Fetch the fields.                                               */
-/* -------------------------------------------------------------------- */
+    // Fetch the fields.
     psDatum->datumname = CPLStrdup(poMIEntry->GetStringField("datumname"));
-    int nDatumType = poMIEntry->GetIntField("type");
+    const int nDatumType = poMIEntry->GetIntField("type");
     if( nDatumType < 0 || nDatumType > EPRJ_DATUM_NONE )
     {
         CPLDebug("HFA", "Invalid value for datum type: %d", nDatumType);
@@ -1579,17 +1454,16 @@ const Eprj_Datum *HFAGetDatum( HFAHandle hHFA )
     else
         psDatum->type = static_cast<Eprj_DatumType>(nDatumType);
 
-    for( i = 0; i < 7; i++ )
+    for( int i = 0; i < 7; i++ )
     {
-        char	szFieldName[30];
-
-        snprintf( szFieldName, sizeof(szFieldName), "params[%d]", i );
+        char szFieldName[30] = {};
+        snprintf(szFieldName, sizeof(szFieldName), "params[%d]", i);
         psDatum->params[i] = poMIEntry->GetDoubleField(szFieldName);
     }
 
     psDatum->gridname = CPLStrdup(poMIEntry->GetStringField("gridname"));
 
-    hHFA->pDatum = (void *) psDatum;
+    hHFA->pDatum = (void *)psDatum;
 
     return psDatum;
 }
@@ -1601,69 +1475,58 @@ const Eprj_Datum *HFAGetDatum( HFAHandle hHFA )
 CPLErr HFASetDatum( HFAHandle hHFA, const Eprj_Datum *poDatum )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Loop over bands, setting information on each one.               */
-/* -------------------------------------------------------------------- */
+    // Loop over bands, setting information on each one.
     for( int iBand = 0; iBand < hHFA->nBands; iBand++ )
     {
-        HFAEntry	*poDatumEntry=NULL, *poProParms;
-
-/* -------------------------------------------------------------------- */
-/*      Create a new Projection if there isn't one present already.     */
-/* -------------------------------------------------------------------- */
-        poProParms =
+        // Create a new Projection if there isn't one present already.
+        HFAEntry *poProParms =
             hHFA->papoBand[iBand]->poNode->GetNamedChild("Projection");
         if( poProParms == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Can't add Eprj_Datum with no Eprj_ProjParameters." );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Can't add Eprj_Datum with no Eprj_ProjParameters.");
             return CE_Failure;
         }
 
-        poDatumEntry = poProParms->GetNamedChild("Datum");
+        HFAEntry *poDatumEntry = poProParms->GetNamedChild("Datum");
         if( poDatumEntry == NULL )
         {
-            poDatumEntry = HFAEntry::New( hHFA, "Datum","Eprj_Datum",
-                                      poProParms );
+            poDatumEntry =
+                HFAEntry::New(hHFA, "Datum", "Eprj_Datum", poProParms);
         }
 
         poDatumEntry->MarkDirty();
 
-/* -------------------------------------------------------------------- */
-/*      Ensure we have enough space for all the data.                   */
-/* -------------------------------------------------------------------- */
-        int	nSize;
-        GByte   *pabyData;
-
-        nSize = static_cast<int>(26 + strlen(poDatum->datumname) + 1 + 7*8);
+        // Ensure we have enough space for all the data.
+        // TODO(schwehr): Explain constants.
+        int nSize =
+            static_cast<int>(26 + strlen(poDatum->datumname) + 1 + 7 * 8);
 
         if( poDatum->gridname != NULL )
             nSize += static_cast<int>(strlen(poDatum->gridname) + 1);
 
-        pabyData = poDatumEntry->MakeData( nSize );
-        if(!pabyData)
+        GByte *pabyData = poDatumEntry->MakeData(nSize);
+        if( !pabyData )
             return CE_Failure;
 
         poDatumEntry->SetPosition();
 
         // Initialize the whole thing to zeros for a clean start.
-        memset( poDatumEntry->GetData(), 0, poDatumEntry->GetDataSize() );
+        memset(poDatumEntry->GetData(), 0, poDatumEntry->GetDataSize());
 
-/* -------------------------------------------------------------------- */
-/*      Write the various fields.                                       */
-/* -------------------------------------------------------------------- */
-        poDatumEntry->SetStringField( "datumname", poDatum->datumname );
-        poDatumEntry->SetIntField( "type", poDatum->type );
+        // Write the various fields.
+        poDatumEntry->SetStringField("datumname", poDatum->datumname);
+        poDatumEntry->SetIntField("type", poDatum->type);
 
-        poDatumEntry->SetDoubleField( "params[0]", poDatum->params[0] );
-        poDatumEntry->SetDoubleField( "params[1]", poDatum->params[1] );
-        poDatumEntry->SetDoubleField( "params[2]", poDatum->params[2] );
-        poDatumEntry->SetDoubleField( "params[3]", poDatum->params[3] );
-        poDatumEntry->SetDoubleField( "params[4]", poDatum->params[4] );
-        poDatumEntry->SetDoubleField( "params[5]", poDatum->params[5] );
-        poDatumEntry->SetDoubleField( "params[6]", poDatum->params[6] );
+        poDatumEntry->SetDoubleField("params[0]", poDatum->params[0]);
+        poDatumEntry->SetDoubleField("params[1]", poDatum->params[1]);
+        poDatumEntry->SetDoubleField("params[2]", poDatum->params[2]);
+        poDatumEntry->SetDoubleField("params[3]", poDatum->params[3]);
+        poDatumEntry->SetDoubleField("params[4]", poDatum->params[4]);
+        poDatumEntry->SetDoubleField("params[5]", poDatum->params[5]);
+        poDatumEntry->SetDoubleField("params[6]", poDatum->params[6]);
 
-        poDatumEntry->SetStringField( "gridname", poDatum->gridname );
+        poDatumEntry->SetStringField("gridname", poDatum->gridname);
     }
 
     return CE_None;
@@ -1677,16 +1540,15 @@ CPLErr HFASetDatum( HFAHandle hHFA, const Eprj_Datum *poDatum )
 
 CPLErr HFAGetPCT( HFAHandle hHFA, int nBand, int *pnColors,
                   double **ppadfRed, double **ppadfGreen,
-		  double **ppadfBlue , double **ppadfAlpha,
+                  double **ppadfBlue, double **ppadfAlpha,
                   double **ppadfBins )
 
 {
     if( nBand < 1 || nBand > hHFA->nBands )
         return CE_Failure;
 
-    return( hHFA->papoBand[nBand-1]->GetPCT( pnColors, ppadfRed,
-                                             ppadfGreen, ppadfBlue,
-					     ppadfAlpha, ppadfBins ) );
+    return hHFA->papoBand[nBand - 1]->GetPCT(pnColors, ppadfRed, ppadfGreen,
+                                             ppadfBlue, ppadfAlpha, ppadfBins);
 }
 
 /************************************************************************/
@@ -1697,36 +1559,35 @@ CPLErr HFAGetPCT( HFAHandle hHFA, int nBand, int *pnColors,
 
 CPLErr HFASetPCT( HFAHandle hHFA, int nBand, int nColors,
                   double *padfRed, double *padfGreen, double *padfBlue,
-		  double *padfAlpha )
+                  double *padfAlpha )
 
 {
     if( nBand < 1 || nBand > hHFA->nBands )
         return CE_Failure;
 
-    return( hHFA->papoBand[nBand-1]->SetPCT( nColors, padfRed,
-                                             padfGreen, padfBlue, padfAlpha ) );
+    return hHFA->papoBand[nBand - 1]->SetPCT(nColors, padfRed, padfGreen,
+                                             padfBlue, padfAlpha);
 }
 
 /************************************************************************/
 /*                          HFAGetDataRange()                           */
 /************************************************************************/
 
-CPLErr	HFAGetDataRange( HFAHandle hHFA, int nBand,
-                         double * pdfMin, double *pdfMax )
+CPLErr HFAGetDataRange( HFAHandle hHFA, int nBand,
+                        double *pdfMin, double *pdfMax )
 
 {
-    HFAEntry	*poBinInfo;
-
     if( nBand < 1 || nBand > hHFA->nBands )
         return CE_Failure;
 
-    poBinInfo = hHFA->papoBand[nBand-1]->poNode->GetNamedChild("Statistics" );
+    HFAEntry *poBinInfo =
+        hHFA->papoBand[nBand-1]->poNode->GetNamedChild("Statistics" );
 
     if( poBinInfo == NULL )
-        return( CE_Failure );
+        return CE_Failure;
 
-    *pdfMin = poBinInfo->GetDoubleField( "minimum" );
-    *pdfMax = poBinInfo->GetDoubleField( "maximum" );
+    *pdfMin = poBinInfo->GetDoubleField("minimum");
+    *pdfMax = poBinInfo->GetDoubleField("maximum");
 
     if( *pdfMax > *pdfMin )
         return CE_None;
@@ -1738,34 +1599,29 @@ CPLErr	HFAGetDataRange( HFAHandle hHFA, int nBand,
 /*                            HFADumpNode()                             */
 /************************************************************************/
 
-static void	HFADumpNode( HFAEntry *poEntry, int nIndent, int bVerbose,
-                             FILE * fp )
+static void HFADumpNode( HFAEntry *poEntry, int nIndent, bool bVerbose,
+                         FILE *fp )
 
 {
-    char	szSpaces[256];
-    int		i;
-
-    for( i = 0; i < nIndent*2; i++ )
-        szSpaces[i] = ' ';
-    szSpaces[nIndent*2] = '\0';
+    std::string osSpaces(nIndent * 2, ' ');
 
-    fprintf( fp, "%s%s(%s) @ %d + %d @ %d\n", szSpaces,
-             poEntry->GetName(), poEntry->GetType(),
-             poEntry->GetFilePos(),
-             poEntry->GetDataSize(), poEntry->GetDataPos() );
+    fprintf(fp, "%s%s(%s) @ %u + %u @ %u\n", osSpaces.c_str(),
+            poEntry->GetName(), poEntry->GetType(),
+            poEntry->GetFilePos(),
+            poEntry->GetDataSize(), poEntry->GetDataPos());
 
     if( bVerbose )
     {
-        strcat( szSpaces, "+ " );
-        poEntry->DumpFieldValues( fp, szSpaces );
-        fprintf( fp, "\n" );
+        osSpaces += "+ ";
+        poEntry->DumpFieldValues(fp, osSpaces.c_str());
+        fprintf(fp, "\n");
     }
 
     if( poEntry->GetChild() != NULL )
-        HFADumpNode( poEntry->GetChild(), nIndent+1, bVerbose, fp );
+        HFADumpNode(poEntry->GetChild(), nIndent+1, bVerbose, fp);
 
     if( poEntry->GetNext() != NULL )
-        HFADumpNode( poEntry->GetNext(), nIndent, bVerbose, fp );
+        HFADumpNode(poEntry->GetNext(), nIndent, bVerbose, fp);
 }
 
 /************************************************************************/
@@ -1774,10 +1630,10 @@ static void	HFADumpNode( HFAEntry *poEntry, int nIndent, int bVerbose,
 /*      Dump the tree of information in a HFA file.                     */
 /************************************************************************/
 
-void HFADumpTree( HFAHandle hHFA, FILE * fpOut )
+void HFADumpTree( HFAHandle hHFA, FILE *fpOut )
 
 {
-    HFADumpNode( hHFA->poRoot, 0, TRUE, fpOut );
+    HFADumpNode(hHFA->poRoot, 0, true, fpOut);
 }
 
 /************************************************************************/
@@ -1787,12 +1643,12 @@ void HFADumpTree( HFAHandle hHFA, FILE * fpOut )
 /*      device.                                                         */
 /************************************************************************/
 
-void HFADumpDictionary( HFAHandle hHFA, FILE * fpOut )
+void HFADumpDictionary( HFAHandle hHFA, FILE *fpOut )
 
 {
-    fprintf( fpOut, "%s\n", hHFA->pszDictionary );
+    fprintf(fpOut, "%s\n", hHFA->pszDictionary);
 
-    hHFA->poDictionary->Dump( fpOut );
+    hHFA->poDictionary->Dump(fpOut);
 }
 
 /************************************************************************/
@@ -1802,19 +1658,16 @@ void HFADumpDictionary( HFAHandle hHFA, FILE * fpOut )
 /************************************************************************/
 
 #ifdef CPL_MSB
-void HFAStandard( int nBytes, void * pData )
+void HFAStandard( int nBytes, void *pData )
 
 {
-    int		i;
-    GByte	*pabyData = (GByte *) pData;
+    GByte *pabyData = static_cast<GByte *>(pData);
 
-    for( i = nBytes/2-1; i >= 0; i-- )
+    for( int i = nBytes / 2 - 1; i >= 0; i-- )
     {
-        GByte	byTemp;
-
-        byTemp = pabyData[i];
-        pabyData[i] = pabyData[nBytes-i-1];
-        pabyData[nBytes-i-1] = byTemp;
+        GByte byTemp = pabyData[i];
+        pabyData[i] = pabyData[nBytes - i - 1];
+        pabyData[nBytes - i - 1] = byTemp;
     }
 }
 #endif
@@ -1838,8 +1691,6 @@ static const char * const aszDefaultDD[] = {
 NULL
 };
 
-
-
 /************************************************************************/
 /*                            HFACreateLL()                             */
 /*                                                                      */
@@ -1847,28 +1698,21 @@ NULL
 /*      Ehfa_HeaderTag, dictionary and Ehfa_File.                       */
 /************************************************************************/
 
-HFAHandle HFACreateLL( const char * pszFilename )
+HFAHandle HFACreateLL( const char *pszFilename )
 
 {
-    VSILFILE *fp;
-    HFAInfo_t   *psInfo;
-
-/* -------------------------------------------------------------------- */
-/*      Create the file in the file system.                             */
-/* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszFilename, "w+b" );
+    // Create the file in the file system.
+    VSILFILE *fp = VSIFOpenL(pszFilename, "w+b");
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Creation of file %s failed.",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed, "Creation of file %s failed.",
+                 pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the HFAInfo_t                                            */
-/* -------------------------------------------------------------------- */
-    psInfo = (HFAInfo_t *) CPLCalloc(sizeof(HFAInfo_t),1);
+    // Create the HFAInfo_t.
+    HFAInfo_t *psInfo =
+        static_cast<HFAInfo_t *>(CPLCalloc(sizeof(HFAInfo_t), 1));
 
     psInfo->fp = fp;
     psInfo->eAccess = HFA_Update;
@@ -1879,98 +1723,88 @@ HFAHandle HFACreateLL( const char * pszFilename )
     psInfo->pMapInfo = NULL;
     psInfo->pDatum = NULL;
     psInfo->pProParameters = NULL;
-    psInfo->bTreeDirty = FALSE;
+    psInfo->bTreeDirty = false;
     psInfo->pszFilename = CPLStrdup(CPLGetFilename(pszFilename));
     psInfo->pszPath = CPLStrdup(CPLGetPath(pszFilename));
 
-/* -------------------------------------------------------------------- */
-/*      Write out the Ehfa_HeaderTag                                    */
-/* -------------------------------------------------------------------- */
-    GInt32	nHeaderPos;
-
-    bool bRet = VSIFWriteL( (void *) "EHFA_HEADER_TAG", 1, 16, fp ) > 0;
+    // Write out the Ehfa_HeaderTag.
+    bool bRet = VSIFWriteL((void *)"EHFA_HEADER_TAG", 1, 16, fp) > 0;
 
-    nHeaderPos = 20;
-    HFAStandard( 4, &nHeaderPos );
-    bRet &= VSIFWriteL( &nHeaderPos, 4, 1, fp ) > 0;
+    GInt32 nHeaderPos = 20;
+    HFAStandard(4, &nHeaderPos);
+    bRet &= VSIFWriteL(&nHeaderPos, 4, 1, fp) > 0;
 
-/* -------------------------------------------------------------------- */
-/*      Write the Ehfa_File node, locked in at offset 20.               */
-/* -------------------------------------------------------------------- */
-    GInt32	nVersion = 1, nFreeList = 0, nRootEntry = 0;
-    GInt16      nEntryHeaderLength = 128;
-    GInt32	nDictionaryPtr = 38;
+    // Write the Ehfa_File node, locked in at offset 20.
+    GInt32 nVersion = 1;
+    GInt32 nFreeList = 0;
+    GInt32 nRootEntry = 0;
+    GInt16 nEntryHeaderLength = 128;
+    GInt32 nDictionaryPtr = 38;
 
     psInfo->nEntryHeaderLength = nEntryHeaderLength;
     psInfo->nRootPos = 0;
     psInfo->nDictionaryPos = nDictionaryPtr;
     psInfo->nVersion = nVersion;
 
-    HFAStandard( 4, &nVersion );
-    HFAStandard( 4, &nFreeList );
-    HFAStandard( 4, &nRootEntry );
-    HFAStandard( 2, &nEntryHeaderLength );
-    HFAStandard( 4, &nDictionaryPtr );
-
-    bRet &= VSIFWriteL( &nVersion, 4, 1, fp ) > 0;
-    bRet &= VSIFWriteL( &nFreeList, 4, 1, fp ) > 0;
-    bRet &= VSIFWriteL( &nRootEntry, 4, 1, fp ) > 0;
-    bRet &= VSIFWriteL( &nEntryHeaderLength, 2, 1, fp ) > 0;
-    bRet &= VSIFWriteL( &nDictionaryPtr, 4, 1, fp ) > 0;
-
-/* -------------------------------------------------------------------- */
-/*      Write the dictionary, locked in at location 38.  Note that      */
-/*      we jump through a bunch of hoops to operate on the              */
-/*      dictionary in chunks because some compiles (such as VC++)       */
-/*      don't allow particularly large static strings.                  */
-/* -------------------------------------------------------------------- */
-    int      nDictLen = 0, iChunk;
-
-    for( iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
+    HFAStandard(4, &nVersion);
+    HFAStandard(4, &nFreeList);
+    HFAStandard(4, &nRootEntry);
+    HFAStandard(2, &nEntryHeaderLength);
+    HFAStandard(4, &nDictionaryPtr);
+
+    bRet &= VSIFWriteL(&nVersion, 4, 1, fp) > 0;
+    bRet &= VSIFWriteL(&nFreeList, 4, 1, fp) > 0;
+    bRet &= VSIFWriteL(&nRootEntry, 4, 1, fp) > 0;
+    bRet &= VSIFWriteL(&nEntryHeaderLength, 2, 1, fp) > 0;
+    bRet &= VSIFWriteL(&nDictionaryPtr, 4, 1, fp) > 0;
+
+    // Write the dictionary, locked in at location 38.  Note that
+    // we jump through a bunch of hoops to operate on the
+    // dictionary in chunks because some compiles (such as VC++)
+    // don't allow particularly large static strings.
+    int nDictLen = 0;
+
+    for( int iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
         nDictLen += static_cast<int>(strlen(aszDefaultDD[iChunk]));
 
-    psInfo->pszDictionary = (char *) CPLMalloc(nDictLen+1);
+    psInfo->pszDictionary = static_cast<char *>(CPLMalloc(nDictLen + 1));
     psInfo->pszDictionary[0] = '\0';
 
-    for( iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
-        strcat( psInfo->pszDictionary, aszDefaultDD[iChunk] );
+    for( int iChunk = 0; aszDefaultDD[iChunk] != NULL; iChunk++ )
+        strcat(psInfo->pszDictionary, aszDefaultDD[iChunk]);
 
-    bRet &= VSIFWriteL( (void *) psInfo->pszDictionary,
-                strlen(psInfo->pszDictionary)+1, 1, fp ) > 0;
+    bRet &= VSIFWriteL((void *)psInfo->pszDictionary,
+                       strlen(psInfo->pszDictionary) + 1, 1, fp) > 0;
     if( !bRet )
     {
-        CPL_IGNORE_RET_VAL(HFAClose( psInfo ));
+        CPL_IGNORE_RET_VAL(HFAClose(psInfo));
         return NULL;
     }
 
-    psInfo->poDictionary = new HFADictionary( psInfo->pszDictionary );
+    psInfo->poDictionary = new HFADictionary(psInfo->pszDictionary);
 
-    psInfo->nEndOfFile = (GUInt32) VSIFTellL( fp );
+    psInfo->nEndOfFile = static_cast<GUInt32>(VSIFTellL(fp));
 
-/* -------------------------------------------------------------------- */
-/*      Create a root entry.                                            */
-/* -------------------------------------------------------------------- */
-    psInfo->poRoot = new HFAEntry( psInfo, "root", "root", NULL );
+    // Create a root entry.
+    psInfo->poRoot = new HFAEntry(psInfo, "root", "root", NULL);
 
-/* -------------------------------------------------------------------- */
-/*      If an .ige or .rrd file exists with the same base name,         */
-/*      delete them.  (#1784)                                           */
-/* -------------------------------------------------------------------- */
+    // If an .ige or .rrd file exists with the same base name,
+    // delete them.  (#1784)
     CPLString osExtension = CPLGetExtension(pszFilename);
-    if( !EQUAL(osExtension,"rrd") && !EQUAL(osExtension,"aux") )
+    if( !EQUAL(osExtension, "rrd") && !EQUAL(osExtension, "aux") )
     {
-        CPLString osPath = CPLGetPath( pszFilename );
-        CPLString osBasename = CPLGetBasename( pszFilename );
+        CPLString osPath = CPLGetPath(pszFilename);
+        CPLString osBasename = CPLGetBasename(pszFilename);
         VSIStatBufL sStatBuf;
-        CPLString osSupFile = CPLFormCIFilename( osPath, osBasename, "rrd" );
+        CPLString osSupFile = CPLFormCIFilename(osPath, osBasename, "rrd");
 
-        if( VSIStatL( osSupFile, &sStatBuf ) == 0 )
-            VSIUnlink( osSupFile );
+        if( VSIStatL(osSupFile, &sStatBuf) == 0 )
+            VSIUnlink(osSupFile);
 
-        osSupFile = CPLFormCIFilename( osPath, osBasename, "ige" );
+        osSupFile = CPLFormCIFilename(osPath, osBasename, "ige");
 
-        if( VSIStatL( osSupFile, &sStatBuf ) == 0 )
-            VSIUnlink( osSupFile );
+        if( VSIStatL(osSupFile, &sStatBuf) == 0 )
+            VSIUnlink(osSupFile);
     }
 
     return psInfo;
@@ -1992,7 +1826,7 @@ HFAHandle HFACreateLL( const char * pszFilename )
 GUInt32 HFAAllocateSpace( HFAInfo_t *psInfo, GUInt32 nBytes )
 
 {
-    /* should check if this will wrap over 2GB limit */
+    // TODO(schwehr): Check if this will wrap over 2GB limit.
 
     psInfo->nEndOfFile += nBytes;
     return psInfo->nEndOfFile - nBytes;
@@ -2008,65 +1842,59 @@ GUInt32 HFAAllocateSpace( HFAInfo_t *psInfo, GUInt32 nBytes )
 CPLErr HFAFlush( HFAHandle hHFA )
 
 {
-    CPLErr	eErr;
-
     if( !hHFA->bTreeDirty && !hHFA->poDictionary->bDictionaryTextDirty )
         return CE_None;
 
-    CPLAssert( hHFA->poRoot != NULL );
+    CPLAssert(hHFA->poRoot != NULL);
 
-/* -------------------------------------------------------------------- */
-/*      Flush HFAEntry tree to disk.                                    */
-/* -------------------------------------------------------------------- */
+    // Flush HFAEntry tree to disk.
     if( hHFA->bTreeDirty )
     {
-        eErr = hHFA->poRoot->FlushToDisk();
+        const CPLErr eErr = hHFA->poRoot->FlushToDisk();
         if( eErr != CE_None )
             return eErr;
 
-        hHFA->bTreeDirty = FALSE;
+        hHFA->bTreeDirty = false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Flush Dictionary to disk.                                       */
-/* -------------------------------------------------------------------- */
+    // Flush Dictionary to disk.
     GUInt32 nNewDictionaryPos = hHFA->nDictionaryPos;
     bool bRet = true;
     if( hHFA->poDictionary->bDictionaryTextDirty )
     {
-        bRet &= VSIFSeekL( hHFA->fp, 0, SEEK_END ) >= 0;
-        nNewDictionaryPos = (GUInt32) VSIFTellL( hHFA->fp );
-        bRet &= VSIFWriteL( hHFA->poDictionary->osDictionaryText.c_str(),
-                    strlen(hHFA->poDictionary->osDictionaryText.c_str()) + 1,
-                    1, hHFA->fp ) > 0;
-        hHFA->poDictionary->bDictionaryTextDirty = FALSE;
+        bRet &= VSIFSeekL(hHFA->fp, 0, SEEK_END) >= 0;
+        nNewDictionaryPos = static_cast<GUInt32>(VSIFTellL(hHFA->fp));
+        bRet &=
+            VSIFWriteL(hHFA->poDictionary->osDictionaryText.c_str(),
+                       strlen(hHFA->poDictionary->osDictionaryText.c_str()) + 1,
+                       1, hHFA->fp) > 0;
+        hHFA->poDictionary->bDictionaryTextDirty = false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      do we need to update the Ehfa_File pointer to the root node?    */
-/* -------------------------------------------------------------------- */
-    if( hHFA->nRootPos != hHFA->poRoot->GetFilePos()
-        || nNewDictionaryPos != hHFA->nDictionaryPos )
+    // Do we need to update the Ehfa_File pointer to the root node?
+    if( hHFA->nRootPos != hHFA->poRoot->GetFilePos() ||
+        nNewDictionaryPos != hHFA->nDictionaryPos )
     {
-        GUInt32		nOffset;
-        GUInt32         nHeaderPos;
+        GUInt32 nHeaderPos = 0;
 
-        bRet &= VSIFSeekL( hHFA->fp, 16, SEEK_SET ) >= 0;
-        bRet &= VSIFReadL( &nHeaderPos, sizeof(GInt32), 1, hHFA->fp ) > 0;
-        HFAStandard( 4, &nHeaderPos );
+        bRet &= VSIFSeekL(hHFA->fp, 16, SEEK_SET) >= 0;
+        bRet &= VSIFReadL(&nHeaderPos, sizeof(GInt32), 1, hHFA->fp) > 0;
+        HFAStandard(4, &nHeaderPos);
 
-        nOffset = hHFA->nRootPos = hHFA->poRoot->GetFilePos();
-        HFAStandard( 4, &nOffset );
-        bRet &= VSIFSeekL( hHFA->fp, nHeaderPos+8, SEEK_SET ) >= 0;
-        bRet &= VSIFWriteL( &nOffset, 4, 1, hHFA->fp ) > 0;
+        GUInt32 nOffset = hHFA->poRoot->GetFilePos();
+        hHFA->nRootPos = nOffset;
+        HFAStandard(4, &nOffset);
+        bRet &= VSIFSeekL(hHFA->fp, nHeaderPos + 8, SEEK_SET) >= 0;
+        bRet &= VSIFWriteL(&nOffset, 4, 1, hHFA->fp) > 0;
 
-        nOffset = hHFA->nDictionaryPos = nNewDictionaryPos;
-        HFAStandard( 4, &nOffset );
-        bRet &= VSIFSeekL( hHFA->fp, nHeaderPos+14, SEEK_SET ) >= 0;
-        bRet &= VSIFWriteL( &nOffset, 4, 1, hHFA->fp ) > 0;
+        nOffset = nNewDictionaryPos;
+        hHFA->nDictionaryPos = nNewDictionaryPos;
+        HFAStandard(4, &nOffset);
+        bRet &= VSIFSeekL(hHFA->fp, nHeaderPos + 14, SEEK_SET) >= 0;
+        bRet &= VSIFWriteL(&nOffset, 4, 1, hHFA->fp) > 0;
     }
 
-    return (bRet) ? CE_None : CE_Failure;
+    return bRet ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
@@ -2083,411 +1911,366 @@ HFACreateLayer( HFAHandle psInfo, HFAEntry *poParent,
                 int bCreateCompressed, int bCreateLargeRaster,
                 int bDependentLayer,
                 int nXSize, int nYSize, EPTType eDataType,
-                CPL_UNUSED char **papszOptions,
-
-                // these are only related to external (large) files
+                char ** /* papszOptions */,
+                // These are only related to external (large) files.
                 GIntBig nStackValidFlagsOffset,
                 GIntBig nStackDataOffset,
                 int nStackCount, int nStackIndex )
 
 {
+    const char *pszLayerType =
+        bOverview ? "Eimg_Layer_SubSample" : "Eimg_Layer";
 
-    HFAEntry	*poEimg_Layer;
-    const char *pszLayerType;
-
-    if( bOverview )
-        pszLayerType = "Eimg_Layer_SubSample";
-    else
-        pszLayerType = "Eimg_Layer";
-
-    if (nBlockSize <= 0)
+    if( nBlockSize <= 0 )
     {
-        CPLError(CE_Failure, CPLE_IllegalArg, "HFACreateLayer : nBlockXSize < 0");
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "HFACreateLayer: nBlockXSize < 0");
         return FALSE;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Work out some details about the tiling scheme.                  */
-/* -------------------------------------------------------------------- */
-    int	nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock;
-
-    nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
-    nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
-    nBlocks = nBlocksPerRow * nBlocksPerColumn;
-    nBytesPerBlock = (nBlockSize * nBlockSize
-                      * HFAGetDataTypeBits(eDataType) + 7) / 8;
-
-/* -------------------------------------------------------------------- */
-/*      Create the Eimg_Layer for the band.                             */
-/* -------------------------------------------------------------------- */
-    poEimg_Layer =
-        HFAEntry::New( psInfo, pszLayerName, pszLayerType, poParent );
-
-    poEimg_Layer->SetIntField( "width", nXSize );
-    poEimg_Layer->SetIntField( "height", nYSize );
-    poEimg_Layer->SetStringField( "layerType", "athematic" );
-    poEimg_Layer->SetIntField( "pixelType", eDataType );
-    poEimg_Layer->SetIntField( "blockWidth", nBlockSize );
-    poEimg_Layer->SetIntField( "blockHeight", nBlockSize );
-
-/* -------------------------------------------------------------------- */
-/*      Create the RasterDMS (block list).  This is a complex type      */
-/*      with pointers, and variable size.  We set the superstructure    */
-/*      ourselves rather than trying to have the HFA type management    */
-/*      system do it for us (since this would be hard to implement).    */
-/* -------------------------------------------------------------------- */
-    if ( !bCreateLargeRaster && !bDependentLayer )
-    {
-        int	nDmsSize;
-        HFAEntry *poEdms_State;
-        GByte	*pabyData;
-
-        poEdms_State =
-            HFAEntry::New( psInfo, "RasterDMS", "Edms_State", poEimg_Layer );
-
-        nDmsSize = 14 * nBlocks + 38;
-        pabyData = poEdms_State->MakeData( nDmsSize );
-
-        /* set some simple values */
-        poEdms_State->SetIntField( "numvirtualblocks", nBlocks );
-        poEdms_State->SetIntField( "numobjectsperblock",
-                                   nBlockSize*nBlockSize );
-        poEdms_State->SetIntField( "nextobjectnum",
-                                   nBlockSize*nBlockSize*nBlocks );
-
-        /* Is file compressed or not? */
+    // Work out some details about the tiling scheme.
+    const int nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
+    const int nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
+    const int nBlocks = nBlocksPerRow * nBlocksPerColumn;
+    const int nBytesPerBlock =
+        (nBlockSize * nBlockSize * HFAGetDataTypeBits(eDataType) + 7) / 8;
+
+    // Create the Eimg_Layer for the band.
+    HFAEntry *poEimg_Layer =
+        HFAEntry::New(psInfo, pszLayerName, pszLayerType, poParent);
+
+    poEimg_Layer->SetIntField("width", nXSize);
+    poEimg_Layer->SetIntField("height", nYSize);
+    poEimg_Layer->SetStringField("layerType", "athematic");
+    poEimg_Layer->SetIntField("pixelType", eDataType);
+    poEimg_Layer->SetIntField("blockWidth", nBlockSize);
+    poEimg_Layer->SetIntField("blockHeight", nBlockSize);
+
+    // Create the RasterDMS (block list).  This is a complex type
+    // with pointers, and variable size.  We set the superstructure
+    // ourselves rather than trying to have the HFA type management
+    // system do it for us (since this would be hard to implement).
+    if( !bCreateLargeRaster && !bDependentLayer )
+    {
+        HFAEntry *poEdms_State =
+            HFAEntry::New(psInfo, "RasterDMS", "Edms_State", poEimg_Layer);
+
+        // TODO(schwehr): Explain constants.
+        const int nDmsSize = 14 * nBlocks + 38;
+        GByte *pabyData = poEdms_State->MakeData(nDmsSize);
+
+        // Set some simple values.
+        poEdms_State->SetIntField("numvirtualblocks", nBlocks);
+        poEdms_State->SetIntField("numobjectsperblock",
+                                  nBlockSize * nBlockSize);
+        poEdms_State->SetIntField("nextobjectnum",
+                                  nBlockSize * nBlockSize * nBlocks);
+
+        // Is file compressed or not?
         if( bCreateCompressed )
         {
-            poEdms_State->SetStringField( "compressionType", "RLC compression" );
+            poEdms_State->SetStringField("compressionType", "RLC compression");
         }
         else
         {
-            poEdms_State->SetStringField( "compressionType", "no compression" );
+            poEdms_State->SetStringField("compressionType", "no compression");
         }
 
-        /* we need to hardcode file offset into the data, so locate it now */
+        // We need to hardcode file offset into the data, so locate it now.
         poEdms_State->SetPosition();
 
-        /* Set block info headers */
-        GUInt32		nValue;
+        // Set block info headers.
 
-        /* blockinfo count */
-        nValue = nBlocks;
-        HFAStandard( 4, &nValue );
-        memcpy( pabyData + 14, &nValue, 4 );
+        // Blockinfo count.
+        GUInt32 nValue = nBlocks;
+        HFAStandard(4, &nValue);
+        memcpy(pabyData + 14, &nValue, 4);
 
-        /* blockinfo position */
+        // Blockinfo position.
         nValue = poEdms_State->GetDataPos() + 22;
-        HFAStandard( 4, &nValue );
-        memcpy( pabyData + 18, &nValue, 4 );
+        HFAStandard(4, &nValue);
+        memcpy(pabyData + 18, &nValue, 4);
 
-        /* Set each blockinfo */
+        // Set each blockinfo.
         for( int iBlock = 0; iBlock < nBlocks; iBlock++ )
         {
-            GInt16  nValue16;
-            int	    nOffset = 22 + 14 * iBlock;
+            int nOffset = 22 + 14 * iBlock;
 
-            /* fileCode */
-            nValue16 = 0;
-            HFAStandard( 2, &nValue16 );
-            memcpy( pabyData + nOffset, &nValue16, 2 );
+            // fileCode.
+            GInt16 nValue16 = 0;
+            HFAStandard(2, &nValue16);
+            memcpy(pabyData + nOffset, &nValue16, 2);
 
-            /* offset */
+            // Offset.
             if( bCreateCompressed )
             {
-                /* flag it with zero offset - will allocate space when we compress it */
+                // Flag it with zero offset. Allocate space when we compress it.
                 nValue = 0;
             }
             else
             {
-                nValue = HFAAllocateSpace( psInfo, nBytesPerBlock );
+                nValue = HFAAllocateSpace(psInfo, nBytesPerBlock);
             }
-            HFAStandard( 4, &nValue );
-            memcpy( pabyData + nOffset + 2, &nValue, 4 );
+            HFAStandard(4, &nValue);
+            memcpy(pabyData + nOffset + 2, &nValue, 4);
 
-            /* size */
+            // Size.
             if( bCreateCompressed )
             {
-                /* flag it with zero size - don't know until we compress it */
+                // Flag with zero size. Don't know until we compress it.
                 nValue = 0;
             }
             else
             {
                 nValue = nBytesPerBlock;
             }
-            HFAStandard( 4, &nValue );
-            memcpy( pabyData + nOffset + 6, &nValue, 4 );
+            HFAStandard(4, &nValue);
+            memcpy(pabyData + nOffset + 6, &nValue, 4);
 
-            /* logValid (false) */
+            // logValid (false).
             nValue16 = 0;
-            HFAStandard( 2, &nValue16 );
-            memcpy( pabyData + nOffset + 10, &nValue16, 2 );
+            HFAStandard(2, &nValue16);
+            memcpy(pabyData + nOffset + 10, &nValue16, 2);
 
-            /* compressionType */
+            // compressionType.
             if( bCreateCompressed )
                 nValue16 = 1;
             else
                 nValue16 = 0;
 
-            HFAStandard( 2, &nValue16 );
-            memcpy( pabyData + nOffset + 12, &nValue16, 2 );
+            HFAStandard(2, &nValue16);
+            memcpy(pabyData + nOffset + 12, &nValue16, 2);
         }
-
     }
-/* -------------------------------------------------------------------- */
-/*      Create ExternalRasterDMS object.                                */
-/* -------------------------------------------------------------------- */
+
+    // Create ExternalRasterDMS object.
     else if( bCreateLargeRaster )
     {
-        HFAEntry *poEdms_State;
-
-        poEdms_State =
-            HFAEntry::New( psInfo, "ExternalRasterDMS",
-                          "ImgExternalRaster", poEimg_Layer );
-        poEdms_State->MakeData( static_cast<int>(8 + strlen(psInfo->pszIGEFilename) + 1 + 6 * 4) );
-
-        poEdms_State->SetStringField( "fileName.string",
-                                      psInfo->pszIGEFilename );
-
-        poEdms_State->SetIntField( "layerStackValidFlagsOffset[0]",
-                                 (int) (nStackValidFlagsOffset & 0xFFFFFFFF));
-        poEdms_State->SetIntField( "layerStackValidFlagsOffset[1]",
-                                 (int) (nStackValidFlagsOffset >> 32) );
-
-        poEdms_State->SetIntField( "layerStackDataOffset[0]",
-                                   (int) (nStackDataOffset & 0xFFFFFFFF) );
-        poEdms_State->SetIntField( "layerStackDataOffset[1]",
-                                   (int) (nStackDataOffset >> 32 ) );
-        poEdms_State->SetIntField( "layerStackCount", nStackCount );
-        poEdms_State->SetIntField( "layerStackIndex", nStackIndex );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Dependent...                                                    */
-/* -------------------------------------------------------------------- */
+        HFAEntry *poEdms_State = HFAEntry::New(
+            psInfo, "ExternalRasterDMS", "ImgExternalRaster", poEimg_Layer);
+        poEdms_State->MakeData(
+            static_cast<int>(8 + strlen(psInfo->pszIGEFilename) + 1 + 6 * 4));
+
+        poEdms_State->SetStringField("fileName.string", psInfo->pszIGEFilename);
+
+        poEdms_State->SetIntField(
+            "layerStackValidFlagsOffset[0]",
+            static_cast<int>(nStackValidFlagsOffset & 0xFFFFFFFF));
+        poEdms_State->SetIntField(
+            "layerStackValidFlagsOffset[1]",
+            static_cast<int>(nStackValidFlagsOffset >> 32));
+
+        poEdms_State->SetIntField(
+            "layerStackDataOffset[0]",
+            static_cast<int>(nStackDataOffset & 0xFFFFFFFF));
+        poEdms_State->SetIntField("layerStackDataOffset[1]",
+                                  static_cast<int>(nStackDataOffset >> 32));
+        poEdms_State->SetIntField("layerStackCount", nStackCount);
+        poEdms_State->SetIntField("layerStackIndex", nStackIndex);
+    }
+    // Dependent...
     else if( bDependentLayer )
     {
-        HFAEntry *poDepLayerName;
-
-        poDepLayerName =
-            HFAEntry::New( psInfo, "DependentLayerName",
-                          "Eimg_DependentLayerName", poEimg_Layer );
-        poDepLayerName->MakeData( static_cast<int>(8 + strlen(pszLayerName) + 2) );
+        HFAEntry *poDepLayerName =
+            HFAEntry::New(psInfo, "DependentLayerName",
+                          "Eimg_DependentLayerName", poEimg_Layer);
+        poDepLayerName->MakeData(
+            static_cast<int>(8 + strlen(pszLayerName) + 2));
 
-        poDepLayerName->SetStringField( "ImageLayerName.string",
-                                        pszLayerName );
+        poDepLayerName->SetStringField("ImageLayerName.string", pszLayerName);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the Ehfa_Layer.                                          */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poEhfa_Layer;
-    GUInt32  nLDict;
-    char     szLDict[128], chBandType;
+    // Create the Ehfa_Layer.
+    char chBandType = '\0';
 
-    if( eDataType == EPT_u1 )
+    if(eDataType == EPT_u1)
         chBandType = '1';
-    else if( eDataType == EPT_u2 )
+    else if(eDataType == EPT_u2)
         chBandType = '2';
-    else if( eDataType == EPT_u4 )
+    else if(eDataType == EPT_u4)
         chBandType = '4';
-    else if( eDataType == EPT_u8 )
+    else if(eDataType == EPT_u8)
         chBandType = 'c';
-    else if( eDataType == EPT_s8 )
+    else if(eDataType == EPT_s8)
         chBandType = 'C';
-    else if( eDataType == EPT_u16 )
+    else if(eDataType == EPT_u16)
         chBandType = 's';
-    else if( eDataType == EPT_s16 )
+    else if(eDataType == EPT_s16)
         chBandType = 'S';
-    else if( eDataType == EPT_u32 )
-        // for some reason erdas imagine expects an L for unsigned 32 bit ints
-        // otherwise it gives strange "out of memory errors"
+    else if(eDataType == EPT_u32)
+        // For some reason erdas imagine expects an L for unsigned 32 bit ints
+        // otherwise it gives strange "out of memory errors".
         chBandType = 'L';
-    else if( eDataType == EPT_s32 )
+    else if(eDataType == EPT_s32)
         chBandType = 'L';
-    else if( eDataType == EPT_f32 )
+    else if(eDataType == EPT_f32)
         chBandType = 'f';
-    else if( eDataType == EPT_f64 )
+    else if(eDataType == EPT_f64)
         chBandType = 'd';
-    else if( eDataType == EPT_c64 )
+    else if(eDataType == EPT_c64)
         chBandType = 'm';
-    else if( eDataType == EPT_c128 )
+    else if(eDataType == EPT_c128)
         chBandType = 'M';
     else
     {
-        CPLAssert( FALSE );
+        CPLAssert(false);
         chBandType = 'c';
     }
 
-    // the first value in the entry below gives the number of pixels within a block
-    snprintf( szLDict, sizeof(szLDict), "{%d:%cdata,}RasterDMS,.", nBlockSize*nBlockSize, chBandType );
+    // The first value in the entry below gives the number of pixels
+    // within a block.
+    char szLDict[128] = {};
+    snprintf(szLDict, sizeof(szLDict), "{%d:%cdata,}RasterDMS,.",
+             nBlockSize * nBlockSize, chBandType);
 
-    poEhfa_Layer = HFAEntry::New( psInfo, "Ehfa_Layer", "Ehfa_Layer",
-                                 poEimg_Layer );
+    HFAEntry *poEhfa_Layer =
+        HFAEntry::New(psInfo, "Ehfa_Layer", "Ehfa_Layer", poEimg_Layer);
     poEhfa_Layer->MakeData();
     poEhfa_Layer->SetPosition();
-    nLDict = HFAAllocateSpace( psInfo, static_cast<GUInt32>(strlen(szLDict) + 1) );
+    const GUInt32 nLDict =
+        HFAAllocateSpace(psInfo, static_cast<GUInt32>(strlen(szLDict) + 1));
 
-    poEhfa_Layer->SetStringField( "type", "raster" );
-    poEhfa_Layer->SetIntField( "dictionaryPtr", nLDict );
+    poEhfa_Layer->SetStringField("type", "raster");
+    poEhfa_Layer->SetIntField("dictionaryPtr", nLDict);
 
-    bool bRet = VSIFSeekL( psInfo->fp, nLDict, SEEK_SET ) >= 0;
-    bRet &= VSIFWriteL( (void *) szLDict, strlen(szLDict) + 1, 1, psInfo->fp ) > 0;
+    bool bRet = VSIFSeekL(psInfo->fp, nLDict, SEEK_SET) >= 0;
+    bRet &= VSIFWriteL((void *)szLDict, strlen(szLDict) + 1, 1, psInfo->fp) > 0;
 
     return bRet;
 }
 
-
 /************************************************************************/
 /*                             HFACreate()                              */
 /************************************************************************/
 
-HFAHandle HFACreate( const char * pszFilename,
+HFAHandle HFACreate( const char *pszFilename,
                      int nXSize, int nYSize, int nBands,
-                     EPTType eDataType, char ** papszOptions )
+                     EPTType eDataType, char **papszOptions )
 
 {
-    HFAHandle	psInfo;
-    int		nBlockSize = 64;
-    const char * pszValue = CSLFetchNameValue( papszOptions, "BLOCKSIZE" );
+    int nBlockSize = 64;
+    const char *pszValue = CSLFetchNameValue(papszOptions, "BLOCKSIZE");
 
-    if ( pszValue != NULL )
+    if( pszValue != NULL )
     {
-        nBlockSize = atoi( pszValue );
-        // check for sane values
-        if ( nBlockSize == 0 ||
-            ((( nBlockSize < 32 ) || (nBlockSize > 2048))
-            && !CPLTestBool(CPLGetConfigOption("FORCE_BLOCKSIZE", "NO"))) )
+        nBlockSize = atoi(pszValue);
+        // Check for sane values.
+        if( nBlockSize == 0 ||
+            ((( nBlockSize < 32 ) || (nBlockSize > 2048)) &&
+            !CPLTestBool(CPLGetConfigOption("FORCE_BLOCKSIZE", "NO"))) )
         {
             nBlockSize = 64;
         }
     }
-    int bCreateLargeRaster = CSLFetchBoolean(papszOptions,"USE_SPILL",
-                                             FALSE);
-    int bCreateCompressed =
-        CSLFetchBoolean(papszOptions,"COMPRESS", FALSE)
-        || CSLFetchBoolean(papszOptions,"COMPRESSED", FALSE);
-    int bCreateAux = CSLFetchBoolean(papszOptions,"AUX", FALSE);
+    bool bCreateLargeRaster = CPLFetchBool(papszOptions, "USE_SPILL", false);
+    bool bCreateCompressed = CPLFetchBool(papszOptions, "COMPRESS", false) ||
+                             CPLFetchBool(papszOptions, "COMPRESSED", false);
+    const bool bCreateAux = CPLFetchBool(papszOptions, "AUX", false);
 
-    char *pszFullFilename = NULL, *pszRawFilename = NULL;
+    char *pszFullFilename = NULL;
+    char *pszRawFilename = NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Create the low level structure.                                 */
-/* -------------------------------------------------------------------- */
-    psInfo = HFACreateLL( pszFilename );
+    // Create the low level structure.
+    HFAHandle psInfo = HFACreateLL(pszFilename);
     if( psInfo == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Create the DependentFile node if requested.                     */
-/* -------------------------------------------------------------------- */
+    // Create the DependentFile node if requested.
     const char *pszDependentFile =
-        CSLFetchNameValue( papszOptions, "DEPENDENT_FILE" );
+        CSLFetchNameValue(papszOptions, "DEPENDENT_FILE");
 
     if( pszDependentFile != NULL )
     {
-        HFAEntry *poDF = HFAEntry::New( psInfo, "DependentFile",
-                                       "Eimg_DependentFile", psInfo->poRoot );
+        HFAEntry *poDF = HFAEntry::New(psInfo, "DependentFile",
+                                       "Eimg_DependentFile", psInfo->poRoot);
 
-        poDF->MakeData( static_cast<int>(strlen(pszDependentFile) + 50) );
+        poDF->MakeData(static_cast<int>(strlen(pszDependentFile) + 50));
         poDF->SetPosition();
-        poDF->SetStringField( "dependent.string", pszDependentFile );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Work out some details about the tiling scheme.                  */
-/* -------------------------------------------------------------------- */
-    int	nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock;
-
-    nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
-    nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
-    nBlocks = nBlocksPerRow * nBlocksPerColumn;
-    nBytesPerBlock = (nBlockSize * nBlockSize
-                      * HFAGetDataTypeBits(eDataType) + 7) / 8;
-
-    CPLDebug( "HFACreate", "Blocks per row %d, blocks per column %d, "
-	      "total number of blocks %d, bytes per block %d.",
-	      nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock );
-
-/* -------------------------------------------------------------------- */
-/*      Check whether we should create external large file with         */
-/*      image.  We create a spill file if the amount of imagery is      */
-/*      close to 2GB.  We don't check the amount of auxiliary            */
-/*      information, so in theory if there were an awful lot of         */
-/*      non-imagery data our approximate size could be smaller than     */
-/*      the file will actually we be.  We leave room for 10MB of        */
-/*      auxiliary data.                                                  */
-/*      We can also force spill file creation using option              */
-/*      SPILL_FILE=YES.                                                 */
-/* -------------------------------------------------------------------- */
-    double dfApproxSize = (double)nBytesPerBlock * (double)nBlocks *
-        (double)nBands + 10000000.0;
+        poDF->SetStringField("dependent.string", pszDependentFile);
+    }
+
+    // Work out some details about the tiling scheme.
+    const int nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
+    const int nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
+    const int nBlocks = nBlocksPerRow * nBlocksPerColumn;
+    const int nBytesPerBlock =
+        (nBlockSize * nBlockSize * HFAGetDataTypeBits(eDataType) + 7) / 8;
+
+    CPLDebug("HFACreate", "Blocks per row %d, blocks per column %d, "
+             "total number of blocks %d, bytes per block %d.",
+             nBlocksPerRow, nBlocksPerColumn, nBlocks, nBytesPerBlock);
+
+    // Check whether we should create external large file with
+    // image.  We create a spill file if the amount of imagery is
+    // close to 2GB.  We don't check the amount of auxiliary
+    // information, so in theory if there were an awful lot of
+    // non-imagery data our approximate size could be smaller than
+    // the file will actually we be.  We leave room for 10MB of
+    // auxiliary data.
+    // We can also force spill file creation using option
+    // SPILL_FILE=YES.
+    const double dfApproxSize =
+        static_cast<double>(nBytesPerBlock) * static_cast<double>(nBlocks) *
+        static_cast<double>(nBands) + 10000000.0;
 
     if( dfApproxSize > 2147483648.0 && !bCreateAux )
-        bCreateLargeRaster = TRUE;
+        bCreateLargeRaster = true;
 
-    // erdas imagine creates this entry even if an external spill file is used
+    // Erdas Imagine creates this entry even if an external spill file is used.
     if( !bCreateAux )
     {
-        HFAEntry *poImgFormat;
-        poImgFormat = HFAEntry::New( psInfo, "IMGFormatInfo",
-                                    "ImgFormatInfo831", psInfo->poRoot );
+        HFAEntry *poImgFormat = HFAEntry::New(
+            psInfo, "IMGFormatInfo", "ImgFormatInfo831", psInfo->poRoot);
         poImgFormat->MakeData();
-        if ( bCreateLargeRaster )
+        if( bCreateLargeRaster )
         {
-            poImgFormat->SetIntField( "spaceUsedForRasterData", 0 );
-            bCreateCompressed = FALSE;	// Can't be compressed if we are creating a spillfile
+            poImgFormat->SetIntField("spaceUsedForRasterData", 0);
+            // Can't be compressed if we are creating a spillfile.
+            bCreateCompressed = false;
         }
         else
         {
-            poImgFormat->SetIntField( "spaceUsedForRasterData",
-                                      nBytesPerBlock*nBlocks*nBands );
+            poImgFormat->SetIntField("spaceUsedForRasterData",
+                                     nBytesPerBlock * nBlocks * nBands);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create external file and write its header.                      */
-/* -------------------------------------------------------------------- */
-    GIntBig nValidFlagsOffset = 0, nDataOffset = 0;
+    // Create external file and write its header.
+    GIntBig nValidFlagsOffset = 0;
+    GIntBig nDataOffset = 0;
 
     if( bCreateLargeRaster )
     {
-        if( !HFACreateSpillStack( psInfo, nXSize, nYSize, nBands,
-                                  nBlockSize, eDataType,
-                                  &nValidFlagsOffset, &nDataOffset ) )
-	{
-	    CPLFree( pszRawFilename );
-	    CPLFree( pszFullFilename );
-	    return NULL;
-	}
+        if( !HFACreateSpillStack(psInfo, nXSize, nYSize, nBands,
+                                 nBlockSize, eDataType,
+                                 &nValidFlagsOffset, &nDataOffset) )
+        {
+            CPLFree(pszRawFilename);
+            CPLFree(pszFullFilename);
+            return NULL;
+        }
     }
 
-/* ==================================================================== */
-/*      Create each band (layer)                                        */
-/* ==================================================================== */
-    int		iBand;
-
-    for( iBand = 0; iBand < nBands; iBand++ )
+    // Create each band (layer).
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        char		szName[128];
+        char szName[128] = {};
 
-        snprintf( szName, sizeof(szName), "Layer_%d", iBand + 1 );
+        snprintf(szName, sizeof(szName), "Layer_%d", iBand + 1);
 
-        if( !HFACreateLayer( psInfo, psInfo->poRoot, szName, FALSE, nBlockSize,
-                             bCreateCompressed, bCreateLargeRaster, bCreateAux,
-                             nXSize, nYSize, eDataType, papszOptions,
-                             nValidFlagsOffset, nDataOffset,
-                             nBands, iBand ) )
+        if( !HFACreateLayer(psInfo, psInfo->poRoot, szName, FALSE, nBlockSize,
+                            bCreateCompressed, bCreateLargeRaster, bCreateAux,
+                            nXSize, nYSize, eDataType, papszOptions,
+                            nValidFlagsOffset, nDataOffset,
+                            nBands, iBand) )
         {
-            CPL_IGNORE_RET_VAL(HFAClose( psInfo ));
+            CPL_IGNORE_RET_VAL(HFAClose(psInfo));
             return NULL;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize the band information.                                */
-/* -------------------------------------------------------------------- */
-    HFAParseBandInfo( psInfo );
+    // Initialize the band information.
+    HFAParseBandInfo(psInfo);
 
     return psInfo;
 }
@@ -2504,11 +2287,9 @@ int HFACreateOverview( HFAHandle hHFA, int nBand, int nOverviewLevel,
 {
     if( nBand < 1 || nBand > hHFA->nBands )
         return -1;
-    else
-    {
-        HFABand *poBand = hHFA->papoBand[nBand-1];
-        return poBand->CreateOverview( nOverviewLevel, pszResampling );
-    }
+
+    HFABand *poBand = hHFA->papoBand[nBand - 1];
+    return poBand->CreateOverview(nOverviewLevel, pszResampling);
 }
 
 /************************************************************************/
@@ -2517,10 +2298,10 @@ int HFACreateOverview( HFAHandle hHFA, int nBand, int nOverviewLevel,
 /*      Read metadata structured in a table called GDAL_MetaData.       */
 /************************************************************************/
 
-char ** HFAGetMetadata( HFAHandle hHFA, int nBand )
+char **HFAGetMetadata( HFAHandle hHFA, int nBand )
 
 {
-    HFAEntry *poTable;
+    HFAEntry *poTable = NULL;
 
     if( nBand > 0 && nBand <= hHFA->nBands )
         poTable = hHFA->papoBand[nBand - 1]->poNode->GetChild();
@@ -2529,82 +2310,77 @@ char ** HFAGetMetadata( HFAHandle hHFA, int nBand )
     else
         return NULL;
 
-    for( ; poTable != NULL && !EQUAL(poTable->GetName(),"GDAL_MetaData");
+    for( ;
+         poTable != NULL && !EQUAL(poTable->GetName(), "GDAL_MetaData");
          poTable = poTable->GetNext() ) {}
 
-    if( poTable == NULL || !EQUAL(poTable->GetType(),"Edsc_Table") )
+    if( poTable == NULL || !EQUAL(poTable->GetType(), "Edsc_Table") )
         return NULL;
 
-    if( poTable->GetIntField( "numRows" ) != 1 )
+    if( poTable->GetIntField("numRows") != 1 )
     {
-        CPLDebug( "HFADataset", "GDAL_MetaData.numRows = %d, expected 1!",
-                  poTable->GetIntField( "numRows" ) );
+        CPLDebug("HFADataset", "GDAL_MetaData.numRows = %d, expected 1!",
+                 poTable->GetIntField("numRows"));
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Loop over each column.  Each column will be one metadata        */
-/*      entry, with the title being the key, and the row value being    */
-/*      the value.  There is only ever one row in GDAL_MetaData         */
-/*      tables.                                                         */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poColumn;
-    char    **papszMD = NULL;
+    // Loop over each column.  Each column will be one metadata
+    // entry, with the title being the key, and the row value being
+    // the value.  There is only ever one row in GDAL_MetaData tables.
+    char **papszMD = NULL;
 
-    for( poColumn = poTable->GetChild();
+    for( HFAEntry *poColumn = poTable->GetChild();
          poColumn != NULL;
          poColumn = poColumn->GetNext() )
     {
-        const char *pszValue;
-        int        columnDataPtr;
-
         // Skip the #Bin_Function# entry.
         if( STARTS_WITH_CI(poColumn->GetName(), "#") )
             continue;
 
-        pszValue = poColumn->GetStringField( "dataType" );
-        if( pszValue == NULL || !EQUAL(pszValue,"string") )
+        const char *pszValue = poColumn->GetStringField("dataType");
+        if( pszValue == NULL || !EQUAL(pszValue, "string") )
             continue;
 
-        columnDataPtr = poColumn->GetIntField( "columnDataPtr" );
-        if( columnDataPtr == 0 )
+        const int columnDataPtr = poColumn->GetIntField("columnDataPtr");
+        if( columnDataPtr <= 0 )
             continue;
 
-/* -------------------------------------------------------------------- */
-/*      Read up to nMaxNumChars bytes from the indicated location.      */
-/*      allocate required space temporarily                             */
-/*      nMaxNumChars should have been set by GDAL originally so we      */
-/*      should trust it, but who knows...                               */
-/* -------------------------------------------------------------------- */
-        int nMaxNumChars = poColumn->GetIntField( "maxNumChars" );
+        // Read up to nMaxNumChars bytes from the indicated location.
+        // allocate required space temporarily nMaxNumChars should have been
+        // set by GDAL originally so we should trust it, but who knows.
+        const int nMaxNumChars = poColumn->GetIntField("maxNumChars");
 
         if( nMaxNumChars <= 0 )
         {
-            papszMD = CSLSetNameValue( papszMD, poColumn->GetName(), "" );
+            papszMD = CSLSetNameValue(papszMD, poColumn->GetName(), "");
         }
         else
         {
-            char *pszMDValue = (char*) VSI_MALLOC_VERBOSE(nMaxNumChars);
-            if (pszMDValue == NULL)
+            char *pszMDValue =
+                static_cast<char *>(VSI_MALLOC_VERBOSE(nMaxNumChars));
+            if( pszMDValue == NULL )
             {
                 continue;
             }
 
-            if( VSIFSeekL( hHFA->fp, columnDataPtr, SEEK_SET ) != 0 )
+            if( VSIFSeekL(hHFA->fp, columnDataPtr, SEEK_SET) != 0 )
+            {
+                CPLFree(pszMDValue);
                 continue;
+            }
 
-            int nMDBytes = static_cast<int>(VSIFReadL( pszMDValue, 1, nMaxNumChars, hHFA->fp ));
+            const int nMDBytes = static_cast<int>(
+                VSIFReadL(pszMDValue, 1, nMaxNumChars, hHFA->fp));
             if( nMDBytes == 0 )
             {
-                CPLFree( pszMDValue );
+                CPLFree(pszMDValue);
                 continue;
             }
 
-            pszMDValue[nMaxNumChars-1] = '\0';
+            pszMDValue[nMaxNumChars - 1] = '\0';
 
-            papszMD = CSLSetNameValue( papszMD, poColumn->GetName(),
-                                       pszMDValue );
-            CPLFree( pszMDValue );
+            papszMD = CSLSetNameValue(papszMD, poColumn->GetName(), pszMDValue);
+            CPLFree(pszMDValue);
         }
     }
 
@@ -2627,7 +2403,7 @@ HFASetGDALMetadata( HFAHandle hHFA, int nBand, char **papszMD )
     if( papszMD == NULL )
         return CE_None;
 
-    HFAEntry  *poNode;
+    HFAEntry *poNode = NULL;
 
     if( nBand > 0 && nBand <= hHFA->nBands )
         poNode = hHFA->papoBand[nBand - 1]->poNode;
@@ -2636,82 +2412,71 @@ HFASetGDALMetadata( HFAHandle hHFA, int nBand, char **papszMD )
     else
         return CE_Failure;
 
-/* -------------------------------------------------------------------- */
-/*      Create the Descriptor table.                                    */
-/*      Check we have no table with this name already                   */
-/* -------------------------------------------------------------------- */
-    HFAEntry	*poEdsc_Table = poNode->GetNamedChild( "GDAL_MetaData" );
+    // Create the Descriptor table.
+    // Check we have no table with this name already.
+    HFAEntry *poEdsc_Table = poNode->GetNamedChild("GDAL_MetaData");
 
-    if( poEdsc_Table == NULL || !EQUAL(poEdsc_Table->GetType(),"Edsc_Table") )
-        poEdsc_Table = HFAEntry::New( hHFA, "GDAL_MetaData", "Edsc_Table",
-                                 poNode );
+    if( poEdsc_Table == NULL || !EQUAL(poEdsc_Table->GetType(), "Edsc_Table") )
+        poEdsc_Table =
+            HFAEntry::New(hHFA, "GDAL_MetaData", "Edsc_Table", poNode);
 
-    poEdsc_Table->SetIntField( "numrows", 1 );
+    poEdsc_Table->SetIntField("numrows", 1);
 
-/* -------------------------------------------------------------------- */
-/*      Create the Binning function node.  I am not sure that we        */
-/*      really need this though.                                        */
-/*      Check it doesn't exist already                                  */
-/* -------------------------------------------------------------------- */
-    HFAEntry       *poEdsc_BinFunction =
-        poEdsc_Table->GetNamedChild( "#Bin_Function#" );
+    // Create the Binning function node.  Do we really need this though?
+    // Check it doesn't exist already.
+    HFAEntry *poEdsc_BinFunction =
+        poEdsc_Table->GetNamedChild("#Bin_Function#");
 
-    if( poEdsc_BinFunction == NULL
-        || !EQUAL(poEdsc_BinFunction->GetType(),"Edsc_BinFunction") )
-        poEdsc_BinFunction = HFAEntry::New( hHFA, "#Bin_Function#",
-                                           "Edsc_BinFunction", poEdsc_Table );
+    if( poEdsc_BinFunction == NULL ||
+        !EQUAL(poEdsc_BinFunction->GetType(), "Edsc_BinFunction") )
+        poEdsc_BinFunction = HFAEntry::New(hHFA, "#Bin_Function#",
+                                           "Edsc_BinFunction", poEdsc_Table);
 
     // Because of the BaseData we have to hardcode the size.
     poEdsc_BinFunction->MakeData( 30 );
 
-    poEdsc_BinFunction->SetIntField( "numBins", 1 );
-    poEdsc_BinFunction->SetStringField( "binFunction", "direct" );
-    poEdsc_BinFunction->SetDoubleField( "minLimit", 0.0 );
-    poEdsc_BinFunction->SetDoubleField( "maxLimit", 0.0 );
+    poEdsc_BinFunction->SetIntField("numBins", 1);
+    poEdsc_BinFunction->SetStringField("binFunction", "direct");
+    poEdsc_BinFunction->SetDoubleField("minLimit", 0.0);
+    poEdsc_BinFunction->SetDoubleField("maxLimit", 0.0);
 
-/* -------------------------------------------------------------------- */
-/*      Process each metadata item as a separate column.		*/
-/* -------------------------------------------------------------------- */
+    // Process each metadata item as a separate column.
     bool bRet = true;
     for( int iColumn = 0; papszMD[iColumn] != NULL; iColumn++ )
     {
-        HFAEntry        *poEdsc_Column;
-        char            *pszKey = NULL;
-        const char      *pszValue;
-
-        pszValue = CPLParseNameValue( papszMD[iColumn], &pszKey );
+        char *pszKey = NULL;
+        const char *pszValue = CPLParseNameValue(papszMD[iColumn], &pszKey);
         if( pszValue == NULL )
             continue;
 
-/* -------------------------------------------------------------------- */
-/*      Create the Edsc_Column.                                         */
-/*      Check it doesn't exist already                                  */
-/* -------------------------------------------------------------------- */
-        poEdsc_Column = poEdsc_Table->GetNamedChild(pszKey);
+        // Create the Edsc_Column.
+        // Check it doesn't exist already.
+        HFAEntry *poEdsc_Column = poEdsc_Table->GetNamedChild(pszKey);
 
-        if( poEdsc_Column == NULL
-            || !EQUAL(poEdsc_Column->GetType(),"Edsc_Column") )
-            poEdsc_Column = HFAEntry::New( hHFA, pszKey, "Edsc_Column",
-                                          poEdsc_Table );
+        if( poEdsc_Column == NULL ||
+            !EQUAL(poEdsc_Column->GetType(), "Edsc_Column") )
+            poEdsc_Column =
+                HFAEntry::New(hHFA, pszKey, "Edsc_Column", poEdsc_Table);
 
-        poEdsc_Column->SetIntField( "numRows", 1 );
-        poEdsc_Column->SetStringField( "dataType", "string" );
-        poEdsc_Column->SetIntField( "maxNumChars", static_cast<GUInt32>(strlen(pszValue)+1) );
+        poEdsc_Column->SetIntField("numRows", 1);
+        poEdsc_Column->SetStringField("dataType", "string");
+        poEdsc_Column->SetIntField("maxNumChars",
+                                   static_cast<GUInt32>(strlen(pszValue) + 1));
 
-/* -------------------------------------------------------------------- */
-/*      Write the data out.                                             */
-/* -------------------------------------------------------------------- */
-        int      nOffset = HFAAllocateSpace( hHFA, static_cast<GUInt32>(strlen(pszValue)+1));
+        // Write the data out.
+        const int nOffset =
+            HFAAllocateSpace(hHFA, static_cast<GUInt32>(strlen(pszValue) + 1));
 
-        poEdsc_Column->SetIntField( "columnDataPtr", nOffset );
+        poEdsc_Column->SetIntField("columnDataPtr", nOffset);
 
-        bRet &= VSIFSeekL( hHFA->fp, nOffset, SEEK_SET ) >= 0;
-        bRet &= VSIFWriteL( (void *) pszValue, strlen(pszValue)+1, 1, hHFA->fp ) > 0;
+        bRet &= VSIFSeekL(hHFA->fp, nOffset, SEEK_SET) >= 0;
+        bRet &=
+            VSIFWriteL((void *)pszValue, strlen(pszValue) + 1, 1, hHFA->fp) > 0;
 
-        CPLFree( pszKey );
+        CPLFree(pszKey);
     }
 
-    return (bRet) ? CE_None : CE_Failure;
+    return bRet ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
@@ -2726,7 +2491,7 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
     if( CSLCount(papszMD) == 0 )
         return CE_None;
 
-    HFAEntry  *poNode;
+    HFAEntry *poNode = NULL;
 
     if( nBand > 0 && nBand <= hHFA->nBands )
         poNode = hHFA->papoBand[nBand - 1]->poNode;
@@ -2735,263 +2500,281 @@ CPLErr HFASetMetadata( HFAHandle hHFA, int nBand, char **papszMD )
     else
         return CE_Failure;
 #ifdef DEBUG
-    /* To please Clang Static Analyzer */
+    // To please Clang Static Analyzer (CSA).
     if( poNode == NULL )
     {
-        CPLAssert(FALSE);
+        CPLAssert(false);
         return CE_Failure;
     }
 #endif
-/* -------------------------------------------------------------------- */
-/*      Check if the Metadata is an "known" entity which should be      */
-/*      stored in a better place.                                       */
-/* -------------------------------------------------------------------- */
-    char * pszBinValues = NULL;
-    int bCreatedHistogramParameters = FALSE;
-    int bCreatedStatistics = FALSE;
-    const char * const * pszAuxMetaData = GetHFAAuxMetaDataList();
-    // check each metadata item
+
+    // Check if the Metadata is an "known" entity which should be
+    // stored in a better place.
+    char *pszBinValues = NULL;
+    bool bCreatedHistogramParameters = false;
+    bool bCreatedStatistics = false;
+    const char *const *pszAuxMetaData = GetHFAAuxMetaDataList();
+    // Check each metadata item.
     for( int iColumn = 0; papszMD[iColumn] != NULL; iColumn++ )
     {
-        char            *pszKey = NULL;
-        const char      *pszValue;
-
-        pszValue = CPLParseNameValue( papszMD[iColumn], &pszKey );
+        char *pszKey = NULL;
+        const char *pszValue = CPLParseNameValue(papszMD[iColumn], &pszKey);
         if( pszValue == NULL )
             continue;
 
-        // know look if its known
-        int i;
-        for( i = 0; pszAuxMetaData[i] != NULL; i += 4 )
+        // Know look if its known.
+        int i = 0;  // Used after for.
+        for( ; pszAuxMetaData[i] != NULL; i += 4 )
         {
-            if ( EQUALN( pszAuxMetaData[i + 2], pszKey, strlen(pszKey) ) )
+            if( EQUALN(pszAuxMetaData[i + 2], pszKey, strlen(pszKey)) )
                 break;
         }
-        if ( pszAuxMetaData[i] != NULL )
+        if( pszAuxMetaData[i] != NULL )
         {
-            // found one, get the right entry
-            HFAEntry *poEntry;
+            // Found one, get the right entry.
+            HFAEntry *poEntry = NULL;
 
             if( strlen(pszAuxMetaData[i]) > 0 )
-                poEntry = poNode->GetNamedChild( pszAuxMetaData[i] );
+                poEntry = poNode->GetNamedChild(pszAuxMetaData[i]);
             else
                 poEntry = poNode;
 
-            if( poEntry == NULL && strlen(pszAuxMetaData[i+3]) > 0 )
+            if( poEntry == NULL && strlen(pszAuxMetaData[i + 3]) > 0 )
             {
-                // child does not yet exist --> create it
-                poEntry = HFAEntry::New( hHFA, pszAuxMetaData[i], pszAuxMetaData[i+3],
-                                        poNode );
+                // Child does not yet exist --> create it,
+                poEntry = HFAEntry::New(hHFA, pszAuxMetaData[i],
+                                        pszAuxMetaData[i + 3], poNode);
 
-                if ( STARTS_WITH_CI(pszAuxMetaData[i], "Statistics") )
-                    bCreatedStatistics = TRUE;
+                if( STARTS_WITH_CI(pszAuxMetaData[i], "Statistics") )
+                    bCreatedStatistics = true;
 
                 if( STARTS_WITH_CI(pszAuxMetaData[i], "HistogramParameters") )
                 {
-                    // this is a bit nasty I need to set the string field for the object
-                    // first because the SetStringField sets the count for the object
-                    // BinFunction to the length of the string
-                    poEntry->MakeData( 70 );
-                    poEntry->SetStringField( "BinFunction.binFunctionType", "direct" );
-
-                    bCreatedHistogramParameters = TRUE;
+                    // A bit nasty.  Need to set the string field for the object
+                    // first because the SetStringField sets the count for the
+                    // object BinFunction to the length of the string.
+                    poEntry->MakeData(70);
+                    poEntry->SetStringField("BinFunction.binFunctionType",
+                                            "direct");
+
+                    bCreatedHistogramParameters = true;
                 }
             }
-            if ( poEntry == NULL )
+            if( poEntry == NULL )
             {
-                CPLFree( pszKey );
+                CPLFree(pszKey);
                 continue;
             }
 
-            const char *pszFieldName = pszAuxMetaData[i+1] + 1;
-            switch( pszAuxMetaData[i+1][0] )
+            const char *pszFieldName = pszAuxMetaData[i + 1] + 1;
+            switch( pszAuxMetaData[i + 1][0] )
             {
-              case 'd':
-              {
-                  double dfValue = CPLAtof( pszValue );
-                  poEntry->SetDoubleField( pszFieldName, dfValue );
-              }
-              break;
-              case 'i':
-              case 'l':
-              {
-                  int nValue = atoi( pszValue );
-                  poEntry->SetIntField( pszFieldName, nValue );
-              }
-              break;
-              case 's':
-              case 'e':
-              {
-                  poEntry->SetStringField( pszFieldName, pszValue );
-              }
-              break;
-              default:
-                CPLAssert( FALSE );
+            case 'd':
+            {
+                double dfValue = CPLAtof(pszValue);
+                poEntry->SetDoubleField(pszFieldName, dfValue);
+            }
+            break;
+            case 'i':
+            case 'l':
+            {
+                int nValue = atoi(pszValue);
+                poEntry->SetIntField(pszFieldName, nValue);
+            }
+            break;
+            case 's':
+            case 'e':
+            {
+                poEntry->SetStringField(pszFieldName, pszValue);
+            }
+            break;
+            default:
+                CPLAssert(false);
             }
         }
-        else if ( STARTS_WITH_CI( pszKey, "STATISTICS_HISTOBINVALUES" ) )
+        else if( STARTS_WITH_CI(pszKey, "STATISTICS_HISTOBINVALUES") )
         {
             CPLFree(pszBinValues);
-            pszBinValues = CPLStrdup( pszValue );
+            pszBinValues = CPLStrdup(pszValue);
         }
         else
-            papszGDALMD = CSLAddString( papszGDALMD, papszMD[iColumn] );
+        {
+            papszGDALMD = CSLAddString(papszGDALMD, papszMD[iColumn]);
+        }
 
-        CPLFree( pszKey );
+        CPLFree(pszKey);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Special case to write out the histogram.                        */
-/* -------------------------------------------------------------------- */
+    // Special case to write out the histogram.
     bool bRet = true;
-    if ( pszBinValues != NULL )
+    if( pszBinValues != NULL )
     {
-        HFAEntry * poEntry = poNode->GetNamedChild( "HistogramParameters" );
-        if ( poEntry != NULL && bCreatedHistogramParameters )
+        HFAEntry *poEntry = poNode->GetNamedChild("HistogramParameters");
+        if( poEntry != NULL && bCreatedHistogramParameters )
         {
-            // if this node exists we have added Histogram data -- complete with some defaults
-            poEntry->SetIntField( "SkipFactorX", 1 );
-            poEntry->SetIntField( "SkipFactorY", 1 );
-
-            int nNumBins = poEntry->GetIntField( "BinFunction.numBins" );
-            double dMinLimit = poEntry->GetDoubleField( "BinFunction.minLimit" );
-            double dMaxLimit = poEntry->GetDoubleField( "BinFunction.maxLimit" );
-
-            // fill the descriptor table - check it isn't there already
-            poEntry = poNode->GetNamedChild( "Descriptor_Table" );
-            if( poEntry == NULL || !EQUAL(poEntry->GetType(),"Edsc_Table") )
-                poEntry = HFAEntry::New( hHFA, "Descriptor_Table", "Edsc_Table", poNode );
-
-            poEntry->SetIntField( "numRows", nNumBins );
-
-            // bin function
-            HFAEntry * poBinFunc = poEntry->GetNamedChild( "#Bin_Function#" );
-            if( poBinFunc == NULL || !EQUAL(poBinFunc->GetType(),"Edsc_BinFunction") )
-                poBinFunc = HFAEntry::New( hHFA, "#Bin_Function#", "Edsc_BinFunction", poEntry );
-
-            poBinFunc->MakeData( 30 );
-            poBinFunc->SetIntField( "numBins", nNumBins );
-            poBinFunc->SetDoubleField( "minLimit", dMinLimit );
-            poBinFunc->SetDoubleField( "maxLimit", dMaxLimit );
-            // direct for thematic layers, linear otherwise
-            if ( STARTS_WITH_CI(poNode->GetStringField("layerType"), "thematic") )
-                poBinFunc->SetStringField( "binFunctionType", "direct" );
+            // If this node exists we have added Histogram data -- complete with
+            // some defaults.
+            poEntry->SetIntField("SkipFactorX", 1);
+            poEntry->SetIntField("SkipFactorY", 1);
+
+            const int nNumBins = poEntry->GetIntField("BinFunction.numBins");
+            const double dMinLimit =
+                poEntry->GetDoubleField("BinFunction.minLimit");
+            const double dMaxLimit =
+                poEntry->GetDoubleField("BinFunction.maxLimit");
+
+            // Fill the descriptor table - check it isn't there already.
+            poEntry = poNode->GetNamedChild("Descriptor_Table");
+            if( poEntry == NULL || !EQUAL(poEntry->GetType(), "Edsc_Table") )
+                poEntry =
+                    HFAEntry::New(hHFA, "Descriptor_Table",
+                                  "Edsc_Table", poNode);
+
+            poEntry->SetIntField("numRows", nNumBins);
+
+            // Bin function.
+            HFAEntry *poBinFunc = poEntry->GetNamedChild("#Bin_Function#");
+            if( poBinFunc == NULL ||
+                !EQUAL(poBinFunc->GetType(), "Edsc_BinFunction") )
+                poBinFunc =
+                    HFAEntry::New(hHFA, "#Bin_Function#",
+                                  "Edsc_BinFunction", poEntry);
+
+            poBinFunc->MakeData(30);
+            poBinFunc->SetIntField("numBins", nNumBins);
+            poBinFunc->SetDoubleField("minLimit", dMinLimit);
+            poBinFunc->SetDoubleField("maxLimit", dMaxLimit);
+            // Direct for thematic layers, linear otherwise.
+            if( STARTS_WITH_CI(poNode->GetStringField("layerType"),
+                               "thematic") )
+                poBinFunc->SetStringField("binFunctionType", "direct");
             else
-                poBinFunc->SetStringField( "binFunctionType", "linear" );
-
-            // we need a child named histogram
-            HFAEntry * poHisto = poEntry->GetNamedChild( "Histogram" );
-            if( poHisto == NULL || !EQUAL(poHisto->GetType(),"Edsc_Column") )
-                poHisto = HFAEntry::New( hHFA, "Histogram", "Edsc_Column", poEntry );
-
-            poHisto->SetIntField( "numRows", nNumBins );
-            // allocate space for the bin values
-            GUInt32 nOffset = HFAAllocateSpace( hHFA, nNumBins*8 );
-            poHisto->SetIntField( "columnDataPtr", nOffset );
-            poHisto->SetStringField( "dataType", "real" );
-            poHisto->SetIntField( "maxNumChars", 0 );
-            // write out histogram data
-            char * pszWork = pszBinValues;
-            for ( int nBin = 0; nBin < nNumBins; ++nBin )
+                poBinFunc->SetStringField("binFunctionType", "linear");
+
+            // We need a child named histogram.
+            HFAEntry *poHisto = poEntry->GetNamedChild("Histogram");
+            if( poHisto == NULL || !EQUAL(poHisto->GetType(), "Edsc_Column") )
+                poHisto =
+                    HFAEntry::New(hHFA, "Histogram", "Edsc_Column", poEntry);
+
+            poHisto->SetIntField("numRows", nNumBins);
+            // Allocate space for the bin values.
+            GUInt32 nOffset = HFAAllocateSpace(hHFA, nNumBins * 8);
+            poHisto->SetIntField("columnDataPtr", nOffset);
+            poHisto->SetStringField("dataType", "real");
+            poHisto->SetIntField("maxNumChars", 0);
+            // Write out histogram data.
+            char *pszWork = pszBinValues;
+            for( int nBin = 0; nBin < nNumBins; ++nBin )
             {
-                char * pszEnd = strchr( pszWork, '|' );
-                if ( pszEnd != NULL )
+                char *pszEnd = strchr(pszWork, '|');
+                if( pszEnd != NULL )
                 {
                     *pszEnd = 0;
-                    bRet &= VSIFSeekL( hHFA->fp, nOffset + 8*nBin, SEEK_SET ) >= 0;
-                    double nValue = CPLAtof( pszWork );
-                    HFAStandard( 8, &nValue );
+                    bRet &=
+                        VSIFSeekL(hHFA->fp, nOffset + 8 * nBin, SEEK_SET) >= 0;
+                    double nValue = CPLAtof(pszWork);
+                    HFAStandard(8, &nValue);
 
-                    bRet &= VSIFWriteL( (void *)&nValue, 8, 1, hHFA->fp ) > 0;
+                    bRet &= VSIFWriteL((void *)&nValue, 8, 1, hHFA->fp) > 0;
                     pszWork = pszEnd + 1;
                 }
             }
         }
-        else if ( poEntry != NULL )
+        else if( poEntry != NULL )
         {
-            // In this case, there are HistogramParameters present, but we did not
-            // create them. However, we might be modifying them, in the case where
-            // the data has changed and the histogram counts need to be updated. It could
-            // be worse than that, but that is all we are going to cope with for now.
-            // We are assuming that we did not change any of the other stuff, like
-            // skip factors and so forth. The main need for this case is for programs
-            // (such as Imagine itself) which will happily modify the pixel values
+            // In this case, there are HistogramParameters present, but we did
+            // not create them. However, we might be modifying them, in the case
+            // where the data has changed and the histogram counts need to be
+            // updated. It could be worse than that, but that is all we are
+            // going to cope with for now.  We are assuming that we did not
+            // change any of the other stuff, like skip factors and so
+            // forth. The main need for this case is for programs (such as
+            // Imagine itself) which will happily modify the pixel values
             // without re-calculating the histogram counts.
-            int nNumBins = poEntry->GetIntField( "BinFunction.numBins" );
-            HFAEntry *poEntryDescrTbl = poNode->GetNamedChild( "Descriptor_Table" );
+            int nNumBins = poEntry->GetIntField("BinFunction.numBins");
+            HFAEntry *poEntryDescrTbl =
+                poNode->GetNamedChild("Descriptor_Table");
             HFAEntry *poHisto = NULL;
-            if ( poEntryDescrTbl != NULL) {
-                poHisto = poEntryDescrTbl->GetNamedChild( "Histogram" );
+            if( poEntryDescrTbl != NULL)
+            {
+                poHisto = poEntryDescrTbl->GetNamedChild("Histogram");
             }
-            if ( poHisto != NULL ) {
-                int nOffset = poHisto->GetIntField( "columnDataPtr" );
-                // write out histogram data
-                char * pszWork = pszBinValues;
+            if( poHisto != NULL )
+            {
+                int nOffset = poHisto->GetIntField("columnDataPtr");
+                // Write out histogram data.
+                char *pszWork = pszBinValues;
 
                 // Check whether histogram counts were written as int or double
-                bool bCountIsInt = TRUE;
+                bool bCountIsInt = true;
                 const char *pszDataType = poHisto->GetStringField("dataType");
-                if ( STARTS_WITH_CI(pszDataType, "real") )
+                if( STARTS_WITH_CI(pszDataType, "real") )
                 {
-                    bCountIsInt = FALSE;
+                    bCountIsInt = false;
                 }
-                for ( int nBin = 0; nBin < nNumBins; ++nBin )
+                for( int nBin = 0; nBin < nNumBins; ++nBin )
                 {
-                    char * pszEnd = strchr( pszWork, '|' );
-                    if ( pszEnd != NULL )
+                    char *pszEnd = strchr(pszWork, '|');
+                    if( pszEnd != NULL )
                     {
                         *pszEnd = 0;
-                        if ( bCountIsInt ) {
-                            // Histogram counts were written as ints, so re-write them the same way
-                            bRet &= VSIFSeekL( hHFA->fp, nOffset + 4*nBin, SEEK_SET ) >= 0;
-                            int nValue = atoi( pszWork );
-                            HFAStandard( 4, &nValue );
-                            bRet &= VSIFWriteL( (void *)&nValue, 4, 1, hHFA->fp ) > 0;
-                        } else {
-                            // Histogram were written as doubles, as is now the default behaviour
-                            bRet &= VSIFSeekL( hHFA->fp, nOffset + 8*nBin, SEEK_SET ) >= 0;
-                            double nValue = CPLAtof( pszWork );
-                            HFAStandard( 8, &nValue );
-                            bRet &= VSIFWriteL( (void *)&nValue, 8, 1, hHFA->fp ) > 0;
+                        if( bCountIsInt )
+                        {
+                            // Histogram counts were written as ints, so
+                            // re-write them the same way.
+                            bRet &= VSIFSeekL(hHFA->fp, nOffset + 4 * nBin,
+                                              SEEK_SET) >= 0;
+                            int nValue = atoi(pszWork);
+                            HFAStandard(4, &nValue);
+                            bRet &=
+                                VSIFWriteL((void *)&nValue, 4, 1, hHFA->fp) > 0;
+                        }
+                        else
+                        {
+                            // Histogram were written as doubles, as is now the
+                            // default behaviour.
+                            bRet &= VSIFSeekL(hHFA->fp, nOffset + 8 * nBin,
+                                              SEEK_SET) >= 0;
+                            double nValue = CPLAtof(pszWork);
+                            HFAStandard(8, &nValue);
+                            bRet &=
+                                VSIFWriteL((void *)&nValue, 8, 1, hHFA->fp) > 0;
                         }
                         pszWork = pszEnd + 1;
                     }
                 }
             }
         }
-        CPLFree( pszBinValues );
+        CPLFree(pszBinValues);
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we created a statistics node then try to create a            */
-/*      StatisticsParameters node too.                                  */
-/* -------------------------------------------------------------------- */
+    // If we created a statistics node then try to create a
+    // StatisticsParameters node too.
     if( bCreatedStatistics )
     {
         HFAEntry *poEntry =
-            HFAEntry::New( hHFA, "StatisticsParameters",
-                          "Eimg_StatisticsParameters830", poNode );
+            HFAEntry::New(hHFA, "StatisticsParameters",
+                          "Eimg_StatisticsParameters830", poNode);
 
-        poEntry->MakeData( 70 );
-        //poEntry->SetStringField( "BinFunction.binFunctionType", "linear" );
+        poEntry->MakeData(70);
+        // poEntry->SetStringField( "BinFunction.binFunctionType", "linear" );
 
-        poEntry->SetIntField( "SkipFactorX", 1 );
-        poEntry->SetIntField( "SkipFactorY", 1 );
+        poEntry->SetIntField("SkipFactorX", 1);
+        poEntry->SetIntField("SkipFactorY", 1);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write out metadata items without a special place.               */
-/* -------------------------------------------------------------------- */
-    if( bRet && CSLCount( papszGDALMD) != 0 )
+    // Write out metadata items without a special place.
+    if( bRet && CSLCount(papszGDALMD) != 0 )
     {
-        CPLErr eErr = HFASetGDALMetadata( hHFA, nBand, papszGDALMD );
+        CPLErr eErr = HFASetGDALMetadata(hHFA, nBand, papszGDALMD);
 
-        CSLDestroy( papszGDALMD );
+        CSLDestroy(papszGDALMD);
         return eErr;
     }
     else
     {
-        CSLDestroy( papszGDALMD );
+        CSLDestroy(papszGDALMD);
         return CE_Failure;
     }
 }
@@ -3011,56 +2794,51 @@ const char *HFAGetIGEFilename( HFAHandle hHFA )
 {
     if( hHFA->pszIGEFilename == NULL )
     {
-        HFAEntry    *poDMS = NULL;
-        std::vector<HFAEntry*> apoDMSList =
-            hHFA->poRoot->FindChildren( NULL, "ImgExternalRaster" );
+        std::vector<HFAEntry *> apoDMSList =
+            hHFA->poRoot->FindChildren(NULL, "ImgExternalRaster");
 
-        if( apoDMSList.size() > 0 )
-            poDMS = apoDMSList[0];
+        HFAEntry *poDMS = apoDMSList.empty() ? NULL : apoDMSList[0];
 
-/* -------------------------------------------------------------------- */
-/*      Get the IGE filename from if we have an ExternalRasterDMS       */
-/* -------------------------------------------------------------------- */
+        // Get the IGE filename from if we have an ExternalRasterDMS.
         if( poDMS )
         {
             const char *pszRawFilename =
-                poDMS->GetStringField( "fileName.string" );
+                poDMS->GetStringField("fileName.string");
 
             if( pszRawFilename != NULL )
             {
                 VSIStatBufL sStatBuf;
                 CPLString osFullFilename =
-                    CPLFormFilename( hHFA->pszPath, pszRawFilename, NULL );
+                    CPLFormFilename(hHFA->pszPath, pszRawFilename, NULL);
 
-                if( VSIStatL( osFullFilename, &sStatBuf ) != 0 )
+                if( VSIStatL(osFullFilename, &sStatBuf) != 0 )
                 {
-                    CPLString osExtension = CPLGetExtension(pszRawFilename);
-                    CPLString osBasename = CPLGetBasename(hHFA->pszFilename);
+                    const CPLString osExtension =
+                        CPLGetExtension(pszRawFilename);
+                    const CPLString osBasename =
+                        CPLGetBasename(hHFA->pszFilename);
                     osFullFilename =
-                        CPLFormFilename( hHFA->pszPath, osBasename,
-                                         osExtension );
-
-                    if( VSIStatL( osFullFilename, &sStatBuf ) == 0 )
-                        hHFA->pszIGEFilename =
-                            CPLStrdup(
-                                CPLFormFilename( NULL, osBasename,
-                                                 osExtension ) );
+                        CPLFormFilename(hHFA->pszPath, osBasename, osExtension);
+
+                    if( VSIStatL(osFullFilename, &sStatBuf) == 0 )
+                        hHFA->pszIGEFilename = CPLStrdup(
+                            CPLFormFilename(NULL, osBasename, osExtension));
                     else
-                        hHFA->pszIGEFilename = CPLStrdup( pszRawFilename );
+                        hHFA->pszIGEFilename = CPLStrdup(pszRawFilename);
                 }
                 else
-                    hHFA->pszIGEFilename = CPLStrdup( pszRawFilename );
+                {
+                    hHFA->pszIGEFilename = CPLStrdup(pszRawFilename);
+                }
             }
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Return the full filename.                                       */
-/* -------------------------------------------------------------------- */
+    // Return the full filename.
     if( hHFA->pszIGEFilename )
-        return CPLFormFilename( hHFA->pszPath, hHFA->pszIGEFilename, NULL );
-    else
-        return NULL;
+        return CPLFormFilename(hHFA->pszPath, hHFA->pszIGEFilename, NULL);
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -3070,256 +2848,222 @@ const char *HFAGetIGEFilename( HFAHandle hHFA )
 /*      file.  Create the spill file if it didn't exist before.         */
 /************************************************************************/
 
-int HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
-                         int nLayers, int nBlockSize, EPTType eDataType,
-                         GIntBig *pnValidFlagsOffset,
-                         GIntBig *pnDataOffset )
+bool HFACreateSpillStack( HFAInfo_t *psInfo, int nXSize, int nYSize,
+                          int nLayers, int nBlockSize, EPTType eDataType,
+                          GIntBig *pnValidFlagsOffset,
+                          GIntBig *pnDataOffset )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Form .ige filename.                                             */
-/* -------------------------------------------------------------------- */
-    char *pszFullFilename;
-
-    if (nBlockSize <= 0)
+    // Form .ige filename.
+    if( nBlockSize <= 0 )
     {
-        CPLError(CE_Failure, CPLE_IllegalArg, "HFACreateSpillStack : nBlockXSize < 0");
-        return FALSE;
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "HFACreateSpillStack: nBlockXSize < 0");
+        return false;
     }
 
     if( psInfo->pszIGEFilename == NULL )
     {
-        if( EQUAL(CPLGetExtension(psInfo->pszFilename),"rrd") )
+        if( EQUAL(CPLGetExtension(psInfo->pszFilename), "rrd") )
             psInfo->pszIGEFilename =
-                CPLStrdup( CPLResetExtension( psInfo->pszFilename, "rde" ) );
-        else if( EQUAL(CPLGetExtension(psInfo->pszFilename),"aux") )
+                CPLStrdup( CPLResetExtension(psInfo->pszFilename, "rde") );
+        else if( EQUAL(CPLGetExtension(psInfo->pszFilename), "aux") )
             psInfo->pszIGEFilename =
-                CPLStrdup( CPLResetExtension( psInfo->pszFilename, "axe" ) );
+                CPLStrdup(CPLResetExtension(psInfo->pszFilename, "axe"));
         else
             psInfo->pszIGEFilename =
-                CPLStrdup( CPLResetExtension( psInfo->pszFilename, "ige" ) );
+                CPLStrdup(CPLResetExtension(psInfo->pszFilename, "ige"));
     }
 
-    pszFullFilename =
-        CPLStrdup( CPLFormFilename( psInfo->pszPath, psInfo->pszIGEFilename, NULL ) );
+    char *pszFullFilename = CPLStrdup(
+        CPLFormFilename(psInfo->pszPath, psInfo->pszIGEFilename, NULL));
 
-/* -------------------------------------------------------------------- */
-/*      Try and open it.  If we fail, create it and write the magic     */
-/*      header.                                                         */
-/* -------------------------------------------------------------------- */
-    static const char * const pszMagick = "ERDAS_IMG_EXTERNAL_RASTER";
-    VSILFILE *fpVSIL;
-    bool bRet = true;
+    // Try and open it.  If we fail, create it and write the magic header.
+    static const char *const pszMagick = "ERDAS_IMG_EXTERNAL_RASTER";
 
-    fpVSIL = VSIFOpenL( pszFullFilename, "r+b" );
+    bool bRet = true;
+    VSILFILE *fpVSIL = VSIFOpenL(pszFullFilename, "r+b");
     if( fpVSIL == NULL )
     {
-        fpVSIL = VSIFOpenL( pszFullFilename, "w+" );
+        fpVSIL = VSIFOpenL(pszFullFilename, "w+");
         if( fpVSIL == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Failed to create spill file %s.\n%s",
-                      psInfo->pszIGEFilename, VSIStrerror( errno ) );
-            return FALSE;
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Failed to create spill file %s.\n%s",
+                     psInfo->pszIGEFilename, VSIStrerror(errno));
+            return false;
         }
 
-        bRet &= VSIFWriteL( (void *) pszMagick, strlen(pszMagick)+1, 1, fpVSIL ) > 0;
+        bRet &=
+            VSIFWriteL((void *)pszMagick, strlen(pszMagick) + 1, 1, fpVSIL) > 0;
     }
 
-    CPLFree( pszFullFilename );
+    CPLFree(pszFullFilename);
 
-/* -------------------------------------------------------------------- */
-/*      Work out some details about the tiling scheme.                  */
-/* -------------------------------------------------------------------- */
-    int	nBlocksPerRow, nBlocksPerColumn, /* nBlocks, */ nBytesPerBlock;
-    int	nBytesPerRow, nBlockMapSize /* , iFlagsSize */;
+    // Work out some details about the tiling scheme.
+    const int nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
+    const int nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
+    // const int nBlocks = nBlocksPerRow * nBlocksPerColumn;
+    const int nBytesPerBlock =
+        (nBlockSize * nBlockSize * HFAGetDataTypeBits(eDataType) + 7) / 8;
 
-    nBlocksPerRow = (nXSize + nBlockSize - 1) / nBlockSize;
-    nBlocksPerColumn = (nYSize + nBlockSize - 1) / nBlockSize;
-    /* nBlocks = nBlocksPerRow * nBlocksPerColumn; */
-    nBytesPerBlock = (nBlockSize * nBlockSize
-                      * HFAGetDataTypeBits(eDataType) + 7) / 8;
+    const int nBytesPerRow = (nBlocksPerRow + 7) / 8;
+    const int nBlockMapSize = nBytesPerRow * nBlocksPerColumn;
+    // const int iFlagsSize = nBlockMapSize + 20;
 
-    nBytesPerRow = ( nBlocksPerRow + 7 ) / 8;
-    nBlockMapSize = nBytesPerRow * nBlocksPerColumn;
-    /* iFlagsSize = nBlockMapSize + 20; */
+    // Write stack prefix information.
+    bRet &= VSIFSeekL(fpVSIL, 0, SEEK_END) >= 0;
 
-/* -------------------------------------------------------------------- */
-/*      Write stack prefix information.                                 */
-/* -------------------------------------------------------------------- */
-    GByte bUnknown;
-    GInt32 nValue32;
-
-    bRet &= VSIFSeekL( fpVSIL, 0, SEEK_END ) >= 0;
+    GByte bUnknown = 1;
+    bRet &= VSIFWriteL(&bUnknown, 1, 1, fpVSIL) > 0;
 
-    bUnknown = 1;
-    bRet &= VSIFWriteL( &bUnknown, 1, 1, fpVSIL ) > 0;
-    nValue32 = nLayers;
-    HFAStandard( 4, &nValue32 );
-    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
+    GInt32 nValue32 = nLayers;
+    HFAStandard(4, &nValue32);
+    bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
     nValue32 = nXSize;
-    HFAStandard( 4, &nValue32 );
-    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
+    HFAStandard(4, &nValue32);
+    bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
     nValue32 = nYSize;
-    HFAStandard( 4, &nValue32 );
-    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
+    HFAStandard(4, &nValue32);
+    bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
     nValue32 = nBlockSize;
-    HFAStandard( 4, &nValue32 );
-    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
-    bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
+    HFAStandard(4, &nValue32);
+    bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
+    bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
     bUnknown = 3;
-    bRet &= VSIFWriteL( &bUnknown, 1, 1, fpVSIL ) > 0;
+    bRet &= VSIFWriteL(&bUnknown, 1, 1, fpVSIL) > 0;
     bUnknown = 0;
-    bRet &= VSIFWriteL( &bUnknown, 1, 1, fpVSIL ) > 0;
+    bRet &= VSIFWriteL(&bUnknown, 1, 1, fpVSIL) > 0;
 
-/* -------------------------------------------------------------------- */
-/*      Write out ValidFlags section(s).                                */
-/* -------------------------------------------------------------------- */
-    unsigned char   *pabyBlockMap;
-    int iBand;
-
-    *pnValidFlagsOffset = VSIFTellL( fpVSIL );
+    // Write out ValidFlags section(s).
+    *pnValidFlagsOffset = VSIFTellL(fpVSIL);
 
-    pabyBlockMap = (unsigned char *) VSI_MALLOC_VERBOSE( nBlockMapSize );
-    if (pabyBlockMap == NULL)
+    unsigned char *pabyBlockMap =
+        static_cast<unsigned char *>(VSI_MALLOC_VERBOSE(nBlockMapSize));
+    if( pabyBlockMap == NULL )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fpVSIL ));
-        return FALSE;
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpVSIL));
+        return false;
     }
 
-    memset( pabyBlockMap, 0xff, nBlockMapSize );
-    for ( iBand = 0; iBand < nLayers; iBand++ )
+    memset(pabyBlockMap, 0xff, nBlockMapSize);
+    for( int iBand = 0; iBand < nLayers; iBand++ )
     {
-        int		    i, iRemainder;
-
-        nValue32 = 1;	// Unknown
-        HFAStandard( 4, &nValue32 );
-        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
-        nValue32 = 0;	// Unknown
-        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
+        nValue32 = 1;  // Unknown
+        HFAStandard(4, &nValue32);
+        bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
+        nValue32 = 0;  // Unknown
+        bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
         nValue32 = nBlocksPerColumn;
-        HFAStandard( 4, &nValue32 );
-        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
+        HFAStandard(4, &nValue32);
+        bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
         nValue32 = nBlocksPerRow;
-        HFAStandard( 4, &nValue32 );
-        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
-        nValue32 = 0x30000;	// Unknown
-        HFAStandard( 4, &nValue32 );
-        bRet &= VSIFWriteL( &nValue32, 4, 1, fpVSIL ) > 0;
-
-        iRemainder = nBlocksPerRow % 8;
-        CPLDebug( "HFACreate",
-                  "Block map size %d, bytes per row %d, remainder %d.",
-                  nBlockMapSize, nBytesPerRow, iRemainder );
-        if ( iRemainder )
+        HFAStandard(4, &nValue32);
+        bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
+        nValue32 = 0x30000;  // Unknown
+        HFAStandard(4, &nValue32);
+        bRet &= VSIFWriteL(&nValue32, 4, 1, fpVSIL) > 0;
+
+        const int iRemainder = nBlocksPerRow % 8;
+        CPLDebug("HFACreate",
+                 "Block map size %d, bytes per row %d, remainder %d.",
+                 nBlockMapSize, nBytesPerRow, iRemainder);
+        if( iRemainder )
         {
-            for ( i = nBytesPerRow - 1; i < nBlockMapSize; i+=nBytesPerRow )
-                pabyBlockMap[i] = (GByte) ((1<<iRemainder) - 1);
+            for( int i = nBytesPerRow - 1; i < nBlockMapSize; i += nBytesPerRow )
+                pabyBlockMap[i] = static_cast<GByte>((1 << iRemainder) - 1);
         }
 
-        bRet &= VSIFWriteL( pabyBlockMap, nBlockMapSize, 1, fpVSIL ) > 0;
+        bRet &= VSIFWriteL(pabyBlockMap, nBlockMapSize, 1, fpVSIL) > 0;
     }
     CPLFree(pabyBlockMap);
     pabyBlockMap = NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Extend the file to account for all the imagery space.           */
-/* -------------------------------------------------------------------- */
-    GIntBig nTileDataSize = ((GIntBig) nBytesPerBlock)
-        * nBlocksPerRow * nBlocksPerColumn * nLayers;
+    // Extend the file to account for all the imagery space.
+    const GIntBig nTileDataSize = static_cast<GIntBig>(nBytesPerBlock) *
+                                  nBlocksPerRow * nBlocksPerColumn * nLayers;
 
-    *pnDataOffset = VSIFTellL( fpVSIL );
+    *pnDataOffset = VSIFTellL(fpVSIL);
 
     if( !bRet ||
-        VSIFSeekL( fpVSIL, nTileDataSize - 1 + *pnDataOffset, SEEK_SET ) != 0
-        || VSIFWriteL( (void *) "", 1, 1, fpVSIL ) != 1 )
+        VSIFTruncateL(fpVSIL, nTileDataSize + *pnDataOffset) != 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to extend %s to full size (%g bytes),\n"
-                  "likely out of disk space.\n%s",
-                  psInfo->pszIGEFilename,
-                  (double) nTileDataSize - 1 + *pnDataOffset,
-                  VSIStrerror( errno ) );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Failed to extend %s to full size (" CPL_FRMT_GIB " bytes), "
+                 "likely out of disk space.\n%s",
+                 psInfo->pszIGEFilename,
+                 nTileDataSize + *pnDataOffset,
+                 VSIStrerror(errno));
 
         CPL_IGNORE_RET_VAL(VSIFCloseL( fpVSIL ));
-        return FALSE;
+        return false;
     }
 
-    if( VSIFCloseL( fpVSIL ) != 0 )
-        return FALSE;
+    if( VSIFCloseL(fpVSIL) != 0 )
+        return false;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                       HFAReadAndValidatePoly()                       */
 /************************************************************************/
 
-static int HFAReadAndValidatePoly( HFAEntry *poTarget,
-                                   const char *pszName,
-                                   Efga_Polynomial *psRetPoly )
+static bool HFAReadAndValidatePoly( HFAEntry *poTarget,
+                                    const char *pszName,
+                                    Efga_Polynomial *psRetPoly )
 
 {
-    CPLString osFldName;
-
-    memset( psRetPoly, 0, sizeof(Efga_Polynomial) );
+    memset(psRetPoly, 0, sizeof(Efga_Polynomial));
 
-    osFldName.Printf( "%sorder", pszName );
+    CPLString osFldName;
+    osFldName.Printf("%sorder", pszName);
     psRetPoly->order = poTarget->GetIntField(osFldName);
 
     if( psRetPoly->order < 1 || psRetPoly->order > 3 )
-        return FALSE;
-
-/* -------------------------------------------------------------------- */
-/*      Validate that things are in a "well known" form.                */
-/* -------------------------------------------------------------------- */
-    int numdimtransform, numdimpolynomial, termcount;
+        return false;
 
-    osFldName.Printf( "%snumdimtransform", pszName );
-    numdimtransform = poTarget->GetIntField(osFldName);
+    // Validate that things are in a "well known" form.
+    osFldName.Printf("%snumdimtransform", pszName);
+    const int numdimtransform = poTarget->GetIntField(osFldName);
 
-    osFldName.Printf( "%snumdimpolynomial", pszName );
-    numdimpolynomial = poTarget->GetIntField(osFldName);
+    osFldName.Printf("%snumdimpolynomial", pszName);
+    const int numdimpolynomial = poTarget->GetIntField(osFldName);
 
-    osFldName.Printf( "%stermcount", pszName );
-    termcount = poTarget->GetIntField(osFldName);
+    osFldName.Printf("%stermcount", pszName);
+    const int termcount = poTarget->GetIntField(osFldName);
 
     if( numdimtransform != 2 || numdimpolynomial != 2 )
-        return FALSE;
+        return false;
 
-    if( (psRetPoly->order == 1 && termcount != 3)
-        || (psRetPoly->order == 2 && termcount != 6)
-        || (psRetPoly->order == 3 && termcount != 10) )
-        return FALSE;
+    if( (psRetPoly->order == 1 && termcount != 3) ||
+        (psRetPoly->order == 2 && termcount != 6) ||
+        (psRetPoly->order == 3 && termcount != 10) )
+        return false;
 
-    // we don't check the exponent organization for now.  Hopefully
+    // We don't check the exponent organization for now.  Hopefully
     // it is always standard.
 
-/* -------------------------------------------------------------------- */
-/*      Get coefficients.                                               */
-/* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; i < termcount*2 - 2; i++ )
+    // Get coefficients.
+    for( int i = 0; i < termcount*2 - 2; i++ )
     {
-        osFldName.Printf( "%spolycoefmtx[%d]", pszName, i );
+        osFldName.Printf("%spolycoefmtx[%d]", pszName, i);
         psRetPoly->polycoefmtx[i] = poTarget->GetDoubleField(osFldName);
     }
 
-    for( i = 0; i < 2; i++ )
+    for( int i = 0; i < 2; i++ )
     {
-        osFldName.Printf( "%spolycoefvector[%d]", pszName, i );
+        osFldName.Printf("%spolycoefvector[%d]", pszName, i);
         psRetPoly->polycoefvector[i] = poTarget->GetDoubleField(osFldName);
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                         HFAReadXFormStack()                          */
 /************************************************************************/
 
-
 int HFAReadXFormStack( HFAHandle hHFA,
                        Efga_Polynomial **ppasPolyListForward,
                        Efga_Polynomial **ppasPolyListReverse )
@@ -3328,83 +3072,75 @@ int HFAReadXFormStack( HFAHandle hHFA,
     if( hHFA->nBands == 0 )
         return 0;
 
-/* -------------------------------------------------------------------- */
-/*      Get the HFA node.                                               */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poXFormHeader;
-
-    poXFormHeader = hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm" );
+    // Get the HFA node.
+    HFAEntry *poXFormHeader =
+        hHFA->papoBand[0]->poNode->GetNamedChild("MapToPixelXForm");
     if( poXFormHeader == NULL )
         return 0;
 
-/* -------------------------------------------------------------------- */
-/*      Loop over children, collecting XForms.                          */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poXForm;
+    // Loop over children, collecting XForms.
     int nStepCount = 0;
     *ppasPolyListForward = NULL;
     *ppasPolyListReverse = NULL;
 
-    for( poXForm = poXFormHeader->GetChild();
+    for( HFAEntry *poXForm = poXFormHeader->GetChild();
          poXForm != NULL;
          poXForm = poXForm->GetNext() )
     {
-        int bSuccess = FALSE;
-        Efga_Polynomial sForward, sReverse;
-        memset( &sForward, 0, sizeof(sForward) );
-        memset( &sReverse, 0, sizeof(sReverse) );
+        bool bSuccess = false;
+        Efga_Polynomial sForward;
+        Efga_Polynomial sReverse;
+        memset(&sForward, 0, sizeof(sForward));
+        memset(&sReverse, 0, sizeof(sReverse));
 
-        if( EQUAL(poXForm->GetType(),"Efga_Polynomial") )
+        if( EQUAL(poXForm->GetType(), "Efga_Polynomial") )
         {
-            bSuccess =
-                HFAReadAndValidatePoly( poXForm, "", &sForward );
+            bSuccess = HFAReadAndValidatePoly(poXForm, "", &sForward);
 
             if( bSuccess )
             {
-                double adfGT[6], adfInvGT[6];
-
-                adfGT[0] = sForward.polycoefvector[0];
-                adfGT[1] = sForward.polycoefmtx[0];
-                adfGT[2] = sForward.polycoefmtx[2];
-                adfGT[3] = sForward.polycoefvector[1];
-                adfGT[4] = sForward.polycoefmtx[1];
-                adfGT[5] = sForward.polycoefmtx[3];
-
-                bSuccess = HFAInvGeoTransform( adfGT, adfInvGT );
+                double adfGT[6] = {
+                    sForward.polycoefvector[0],
+                    sForward.polycoefmtx[0],
+                    sForward.polycoefmtx[2],
+                    sForward.polycoefvector[1],
+                    sForward.polycoefmtx[1],
+                    sForward.polycoefmtx[3]
+                };
+
+                double adfInvGT[6] = {};
+                bSuccess = HFAInvGeoTransform(adfGT, adfInvGT);
                 if( !bSuccess )
-                    memset( adfInvGT, 0, sizeof(adfInvGT) );
+                    memset(adfInvGT, 0, sizeof(adfInvGT));
 
                 sReverse.order = sForward.order;
                 sReverse.polycoefvector[0] = adfInvGT[0];
-                sReverse.polycoefmtx[0]    = adfInvGT[1];
-                sReverse.polycoefmtx[2]    = adfInvGT[2];
+                sReverse.polycoefmtx[0] = adfInvGT[1];
+                sReverse.polycoefmtx[2] = adfInvGT[2];
                 sReverse.polycoefvector[1] = adfInvGT[3];
-                sReverse.polycoefmtx[1]    = adfInvGT[4];
-                sReverse.polycoefmtx[3]    = adfInvGT[5];
+                sReverse.polycoefmtx[1] = adfInvGT[4];
+                sReverse.polycoefmtx[3] = adfInvGT[5];
             }
         }
-        else if( EQUAL(poXForm->GetType(),"GM_PolyPair") )
+        else if( EQUAL(poXForm->GetType(), "GM_PolyPair") )
         {
             bSuccess =
-                HFAReadAndValidatePoly( poXForm, "forward.", &sForward );
-            bSuccess = bSuccess &&
-                HFAReadAndValidatePoly( poXForm, "reverse.", &sReverse );
+                HFAReadAndValidatePoly(poXForm, "forward.", &sForward) &&
+                HFAReadAndValidatePoly(poXForm, "reverse.", &sReverse);
         }
 
         if( bSuccess )
         {
             nStepCount++;
-            *ppasPolyListForward = (Efga_Polynomial *)
-                CPLRealloc( *ppasPolyListForward,
-                            sizeof(Efga_Polynomial) * nStepCount);
-            memcpy( *ppasPolyListForward + nStepCount - 1,
-                    &sForward, sizeof(sForward) );
-
-            *ppasPolyListReverse = (Efga_Polynomial *)
-                CPLRealloc( *ppasPolyListReverse,
-                            sizeof(Efga_Polynomial) * nStepCount);
-            memcpy( *ppasPolyListReverse + nStepCount - 1,
-                    &sReverse, sizeof(sReverse) );
+            *ppasPolyListForward = static_cast<Efga_Polynomial *>(CPLRealloc(
+                *ppasPolyListForward, sizeof(Efga_Polynomial) * nStepCount));
+            memcpy(*ppasPolyListForward + nStepCount - 1, &sForward,
+                   sizeof(sForward));
+
+            *ppasPolyListReverse = static_cast<Efga_Polynomial *>(CPLRealloc(
+                *ppasPolyListReverse, sizeof(Efga_Polynomial) * nStepCount));
+            memcpy(*ppasPolyListReverse + nStepCount - 1, &sReverse,
+                   sizeof(sReverse));
         }
     }
 
@@ -3420,71 +3156,67 @@ int HFAEvaluateXFormStack( int nStepCount, int bForward,
                            double *pdfX, double *pdfY )
 
 {
-    int iStep;
-
-    for( iStep = 0; iStep < nStepCount; iStep++ )
+    for( int iStep = 0; iStep < nStepCount; iStep++ )
     {
-        double dfXOut, dfYOut;
-        Efga_Polynomial *psStep;
-
-        if( bForward )
-            psStep = pasPolyList + iStep;
-        else
-            psStep = pasPolyList + nStepCount - iStep - 1;
+        const Efga_Polynomial *psStep =
+            bForward ? pasPolyList + iStep
+                     : pasPolyList + nStepCount - iStep - 1;
 
+        double dfXOut = 0.0;
+        double dfYOut = 0.0;
         if( psStep->order == 1 )
         {
-            dfXOut = psStep->polycoefvector[0]
-                + psStep->polycoefmtx[0] * *pdfX
-                + psStep->polycoefmtx[2] * *pdfY;
+            dfXOut = psStep->polycoefvector[0] +
+                     psStep->polycoefmtx[0] * *pdfX +
+                     psStep->polycoefmtx[2] * *pdfY;
 
-            dfYOut = psStep->polycoefvector[1]
-                + psStep->polycoefmtx[1] * *pdfX
-                + psStep->polycoefmtx[3] * *pdfY;
+            dfYOut = psStep->polycoefvector[1] +
+                     psStep->polycoefmtx[1] * *pdfX +
+                     psStep->polycoefmtx[3] * *pdfY;
 
             *pdfX = dfXOut;
             *pdfY = dfYOut;
         }
         else if( psStep->order == 2 )
         {
-            dfXOut = psStep->polycoefvector[0]
-                + psStep->polycoefmtx[0] * *pdfX
-                + psStep->polycoefmtx[2] * *pdfY
-                + psStep->polycoefmtx[4] * *pdfX * *pdfX
-                + psStep->polycoefmtx[6] * *pdfX * *pdfY
-                + psStep->polycoefmtx[8] * *pdfY * *pdfY;
-            dfYOut = psStep->polycoefvector[1]
-                + psStep->polycoefmtx[1] * *pdfX
-                + psStep->polycoefmtx[3] * *pdfY
-                + psStep->polycoefmtx[5] * *pdfX * *pdfX
-                + psStep->polycoefmtx[7] * *pdfX * *pdfY
-                + psStep->polycoefmtx[9] * *pdfY * *pdfY;
+            dfXOut = psStep->polycoefvector[0] +
+                     psStep->polycoefmtx[0] * *pdfX +
+                     psStep->polycoefmtx[2] * *pdfY +
+                     psStep->polycoefmtx[4] * *pdfX * *pdfX +
+                     psStep->polycoefmtx[6] * *pdfX * *pdfY +
+                     psStep->polycoefmtx[8] * *pdfY * *pdfY;
+            dfYOut = psStep->polycoefvector[1] +
+                     psStep->polycoefmtx[1] * *pdfX +
+                     psStep->polycoefmtx[3] * *pdfY +
+                     psStep->polycoefmtx[5] * *pdfX * *pdfX +
+                     psStep->polycoefmtx[7] * *pdfX * *pdfY +
+                     psStep->polycoefmtx[9] * *pdfY * *pdfY;
 
             *pdfX = dfXOut;
             *pdfY = dfYOut;
         }
         else if( psStep->order == 3 )
         {
-            dfXOut = psStep->polycoefvector[0]
-                + psStep->polycoefmtx[ 0] * *pdfX
-                + psStep->polycoefmtx[ 2] * *pdfY
-                + psStep->polycoefmtx[ 4] * *pdfX * *pdfX
-                + psStep->polycoefmtx[ 6] * *pdfX * *pdfY
-                + psStep->polycoefmtx[ 8] * *pdfY * *pdfY
-                + psStep->polycoefmtx[10] * *pdfX * *pdfX * *pdfX
-                + psStep->polycoefmtx[12] * *pdfX * *pdfX * *pdfY
-                + psStep->polycoefmtx[14] * *pdfX * *pdfY * *pdfY
-                + psStep->polycoefmtx[16] * *pdfY * *pdfY * *pdfY;
-            dfYOut = psStep->polycoefvector[1]
-                + psStep->polycoefmtx[ 1] * *pdfX
-                + psStep->polycoefmtx[ 3] * *pdfY
-                + psStep->polycoefmtx[ 5] * *pdfX * *pdfX
-                + psStep->polycoefmtx[ 7] * *pdfX * *pdfY
-                + psStep->polycoefmtx[ 9] * *pdfY * *pdfY
-                + psStep->polycoefmtx[11] * *pdfX * *pdfX * *pdfX
-                + psStep->polycoefmtx[13] * *pdfX * *pdfX * *pdfY
-                + psStep->polycoefmtx[15] * *pdfX * *pdfY * *pdfY
-                + psStep->polycoefmtx[17] * *pdfY * *pdfY * *pdfY;
+            dfXOut = psStep->polycoefvector[0] +
+                     psStep->polycoefmtx[0] * *pdfX +
+                     psStep->polycoefmtx[2] * *pdfY +
+                     psStep->polycoefmtx[4] * *pdfX * *pdfX +
+                     psStep->polycoefmtx[6] * *pdfX * *pdfY +
+                     psStep->polycoefmtx[8] * *pdfY * *pdfY +
+                     psStep->polycoefmtx[10] * *pdfX * *pdfX * *pdfX +
+                     psStep->polycoefmtx[12] * *pdfX * *pdfX * *pdfY +
+                     psStep->polycoefmtx[14] * *pdfX * *pdfY * *pdfY +
+                     psStep->polycoefmtx[16] * *pdfY * *pdfY * *pdfY;
+            dfYOut = psStep->polycoefvector[1] +
+                     psStep->polycoefmtx[1] * *pdfX +
+                     psStep->polycoefmtx[3] * *pdfY +
+                     psStep->polycoefmtx[5] * *pdfX * *pdfX +
+                     psStep->polycoefmtx[7] * *pdfX * *pdfY +
+                     psStep->polycoefmtx[9] * *pdfY * *pdfY +
+                     psStep->polycoefmtx[11] * *pdfX * *pdfX * *pdfX +
+                     psStep->polycoefmtx[13] * *pdfX * *pdfX * *pdfY +
+                     psStep->polycoefmtx[15] * *pdfX * *pdfY * *pdfY +
+                     psStep->polycoefmtx[17] * *pdfY * *pdfY * *pdfY;
 
             *pdfX = dfXOut;
             *pdfY = dfYOut;
@@ -3510,98 +3242,86 @@ CPLErr HFAWriteXFormStack( HFAHandle hHFA, int nBand, int nXFormCount,
 
     if( ppasPolyListForward[0]->order != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "For now HFAWriteXFormStack() only supports order 1 polynomials" );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "For now HFAWriteXFormStack() only supports order 1 polynomials");
         return CE_Failure;
     }
 
     if( nBand < 0 || nBand > hHFA->nBands )
         return CE_Failure;
 
-/* -------------------------------------------------------------------- */
-/*      If no band number is provided, operate on all bands.            */
-/* -------------------------------------------------------------------- */
+    // If no band number is provided, operate on all bands.
     if( nBand == 0 )
     {
-        CPLErr eErr = CE_None;
-
         for( nBand = 1; nBand <= hHFA->nBands; nBand++ )
         {
-            eErr = HFAWriteXFormStack( hHFA, nBand, nXFormCount,
-                                       ppasPolyListForward,
-                                       ppasPolyListReverse );
+            CPLErr eErr =
+                HFAWriteXFormStack(hHFA, nBand, nXFormCount,
+                                   ppasPolyListForward,
+                                   ppasPolyListReverse);
             if( eErr != CE_None )
                 return eErr;
         }
 
-        return eErr;
+        return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Fetch our band node.                                            */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poBandNode = hHFA->papoBand[nBand-1]->poNode;
-    HFAEntry *poXFormHeader;
-
-    poXFormHeader = poBandNode->GetNamedChild( "MapToPixelXForm" );
+    // Fetch our band node.
+    HFAEntry *poBandNode = hHFA->papoBand[nBand - 1]->poNode;
+    HFAEntry *poXFormHeader = poBandNode->GetNamedChild("MapToPixelXForm");
     if( poXFormHeader == NULL )
     {
-        poXFormHeader = HFAEntry::New( hHFA, "MapToPixelXForm",
-                                      "Exfr_GenericXFormHeader", poBandNode );
-        poXFormHeader->MakeData( 23 );
+        poXFormHeader = HFAEntry::New(hHFA, "MapToPixelXForm",
+                                      "Exfr_GenericXFormHeader", poBandNode);
+        poXFormHeader->MakeData(23);
         poXFormHeader->SetPosition();
-        poXFormHeader->SetStringField( "titleList.string", "Affine" );
+        poXFormHeader->SetStringField("titleList.string", "Affine");
     }
 
-/* -------------------------------------------------------------------- */
-/*      Loop over XForms.                                               */
-/* -------------------------------------------------------------------- */
+    // Loop over XForms.
     for( int iXForm = 0; iXForm < nXFormCount; iXForm++ )
     {
         Efga_Polynomial *psForward = *ppasPolyListForward + iXForm;
-        CPLString     osXFormName;
-        osXFormName.Printf( "XForm%d", iXForm );
+        CPLString osXFormName;
+        osXFormName.Printf("XForm%d", iXForm);
 
-        HFAEntry *poXForm = poXFormHeader->GetNamedChild( osXFormName );
+        HFAEntry *poXForm = poXFormHeader->GetNamedChild(osXFormName);
 
         if( poXForm == NULL )
         {
-            poXForm = HFAEntry::New( hHFA, osXFormName, "Efga_Polynomial",
-                                    poXFormHeader );
-            poXForm->MakeData( 136 );
+            poXForm = HFAEntry::New(hHFA, osXFormName, "Efga_Polynomial",
+                                    poXFormHeader);
+            poXForm->MakeData(136);
             poXForm->SetPosition();
         }
 
-        poXForm->SetIntField( "order", 1 );
-        poXForm->SetIntField( "numdimtransform", 2 );
-        poXForm->SetIntField( "numdimpolynomial", 2 );
-        poXForm->SetIntField( "termcount", 3 );
-        poXForm->SetIntField( "exponentlist[0]", 0 );
-        poXForm->SetIntField( "exponentlist[1]", 0 );
-        poXForm->SetIntField( "exponentlist[2]", 1 );
-        poXForm->SetIntField( "exponentlist[3]", 0 );
-        poXForm->SetIntField( "exponentlist[4]", 0 );
-        poXForm->SetIntField( "exponentlist[5]", 1 );
-
-        poXForm->SetIntField( "polycoefmtx[-3]", EPT_f64 );
-        poXForm->SetIntField( "polycoefmtx[-2]", 2 );
-        poXForm->SetIntField( "polycoefmtx[-1]", 2 );
-        poXForm->SetDoubleField( "polycoefmtx[0]",
-                                 psForward->polycoefmtx[0] );
-        poXForm->SetDoubleField( "polycoefmtx[1]",
-                                 psForward->polycoefmtx[1] );
-        poXForm->SetDoubleField( "polycoefmtx[2]",
-                                 psForward->polycoefmtx[2] );
-        poXForm->SetDoubleField( "polycoefmtx[3]",
-                                 psForward->polycoefmtx[3] );
-
-        poXForm->SetIntField( "polycoefvector[-3]", EPT_f64 );
-        poXForm->SetIntField( "polycoefvector[-2]", 1 );
-        poXForm->SetIntField( "polycoefvector[-1]", 2 );
-        poXForm->SetDoubleField( "polycoefvector[0]",
-                                 psForward->polycoefvector[0] );
-        poXForm->SetDoubleField( "polycoefvector[1]",
-                                 psForward->polycoefvector[1] );
+        poXForm->SetIntField("order", 1);
+        poXForm->SetIntField("numdimtransform", 2);
+        poXForm->SetIntField("numdimpolynomial", 2);
+        poXForm->SetIntField("termcount", 3);
+        poXForm->SetIntField("exponentlist[0]", 0);
+        poXForm->SetIntField("exponentlist[1]", 0);
+        poXForm->SetIntField("exponentlist[2]", 1);
+        poXForm->SetIntField("exponentlist[3]", 0);
+        poXForm->SetIntField("exponentlist[4]", 0);
+        poXForm->SetIntField("exponentlist[5]", 1);
+
+        poXForm->SetIntField("polycoefmtx[-3]", EPT_f64);
+        poXForm->SetIntField("polycoefmtx[-2]", 2);
+        poXForm->SetIntField("polycoefmtx[-1]", 2);
+        poXForm->SetDoubleField("polycoefmtx[0]", psForward->polycoefmtx[0]);
+        poXForm->SetDoubleField("polycoefmtx[1]", psForward->polycoefmtx[1]);
+        poXForm->SetDoubleField("polycoefmtx[2]", psForward->polycoefmtx[2]);
+        poXForm->SetDoubleField("polycoefmtx[3]", psForward->polycoefmtx[3]);
+
+        poXForm->SetIntField("polycoefvector[-3]", EPT_f64);
+        poXForm->SetIntField("polycoefvector[-2]", 1);
+        poXForm->SetIntField("polycoefvector[-1]", 2);
+        poXForm->SetDoubleField("polycoefvector[0]",
+                                psForward->polycoefvector[0]);
+        poXForm->SetDoubleField("polycoefvector[1]",
+                                psForward->polycoefvector[1]);
     }
 
     return CE_None;
@@ -3617,24 +3337,16 @@ char **HFAReadCameraModel( HFAHandle hHFA )
     if( hHFA->nBands == 0 )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Get the camera model node, and confirm it's type.               */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poXForm;
-
-    poXForm =
-        hHFA->papoBand[0]->poNode->GetNamedChild( "MapToPixelXForm.XForm0" );
+    // Get the camera model node, and confirm its type.
+    HFAEntry *poXForm =
+        hHFA->papoBand[0]->poNode->GetNamedChild("MapToPixelXForm.XForm0");
     if( poXForm == NULL )
         return NULL;
 
-    if( !EQUAL(poXForm->GetType(),"Camera_ModelX") )
+    if( !EQUAL(poXForm->GetType(), "Camera_ModelX") )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Convert the values to metadata.                                 */
-/* -------------------------------------------------------------------- */
-    const char *pszValue;
-    int i;
+    // Convert the values to metadata.
     char **papszMD = NULL;
     static const char * const apszFields[] = {
         "direction", "refType", "demsource", "PhotoDirection", "RotationSystem",
@@ -3654,137 +3366,132 @@ char **HFAReadCameraModel( HFAHandle hHFA )
         "LensDistortion[0]", "LensDistortion[1]", "LensDistortion[2]",
         NULL };
 
-    for( i = 0; apszFields[i] != NULL; i++ )
+    const char *pszValue = NULL;
+    for( int i = 0; apszFields[i] != NULL; i++ )
     {
-        pszValue = poXForm->GetStringField( apszFields[i] );
+        pszValue = poXForm->GetStringField(apszFields[i]);
         if( pszValue == NULL )
             pszValue = "";
 
-        papszMD = CSLSetNameValue( papszMD, apszFields[i], pszValue );
+        papszMD = CSLSetNameValue(papszMD, apszFields[i], pszValue);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create a pseudo-entry for the MIFObject with the                */
-/*      outputProjection.                                               */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poProjInfo = HFAEntry::BuildEntryFromMIFObject( poXForm, "outputProjection" );
-    if (poProjInfo)
+    // Create a pseudo-entry for the MIFObject with the outputProjection.
+    HFAEntry *poProjInfo =
+        HFAEntry::BuildEntryFromMIFObject(poXForm, "outputProjection");
+    if( poProjInfo )
     {
-    /* -------------------------------------------------------------------- */
-    /*      Fetch the datum.                                                */
-    /* -------------------------------------------------------------------- */
+        // Fetch the datum.
         Eprj_Datum sDatum;
 
-        memset( &sDatum, 0, sizeof(sDatum));
+        memset(&sDatum, 0, sizeof(sDatum));
 
         sDatum.datumname =
-            (char *) poProjInfo->GetStringField("earthModel.datum.datumname");
+            (char *)poProjInfo->GetStringField("earthModel.datum.datumname");
 
-        int nDatumType = poProjInfo->GetIntField("earthModel.datum.type");
+        const int nDatumType = poProjInfo->GetIntField("earthModel.datum.type");
         if( nDatumType < 0 || nDatumType > EPRJ_DATUM_NONE )
         {
             CPLDebug("HFA", "Invalid value for datum type: %d", nDatumType);
             sDatum.type = EPRJ_DATUM_NONE;
         }
         else
+        {
             sDatum.type = static_cast<Eprj_DatumType>(nDatumType);
+        }
 
-        for( i = 0; i < 7; i++ )
+        for( int i = 0; i < 7; i++ )
         {
-            char	szFieldName[60];
+            char szFieldName[60] = {};
 
-            snprintf( szFieldName, sizeof(szFieldName), "earthModel.datum.params[%d]", i );
+            snprintf(szFieldName, sizeof(szFieldName),
+                     "earthModel.datum.params[%d]", i);
             sDatum.params[i] = poProjInfo->GetDoubleField(szFieldName);
         }
 
-        sDatum.gridname = (char *)
-            poProjInfo->GetStringField("earthModel.datum.gridname");
+        sDatum.gridname =
+            (char *)poProjInfo->GetStringField("earthModel.datum.gridname");
 
-    /* -------------------------------------------------------------------- */
-    /*      Fetch the projection parameters.                                */
-    /* -------------------------------------------------------------------- */
+        // Fetch the projection parameters.
         Eprj_ProParameters sPro;
 
-        memset( &sPro, 0, sizeof(sPro) );
+        memset(&sPro, 0, sizeof(sPro));
 
-        sPro.proType = (Eprj_ProType) poProjInfo->GetIntField("projectionObject.proType");
+        sPro.proType =
+            (Eprj_ProType)poProjInfo->GetIntField("projectionObject.proType");
         sPro.proNumber = poProjInfo->GetIntField("projectionObject.proNumber");
-        sPro.proExeName = (char *) poProjInfo->GetStringField("projectionObject.proExeName");
-        sPro.proName = (char *) poProjInfo->GetStringField("projectionObject.proName");
+        sPro.proExeName =
+            (char *)poProjInfo->GetStringField("projectionObject.proExeName");
+        sPro.proName =
+            (char *)poProjInfo->GetStringField("projectionObject.proName");
         sPro.proZone = poProjInfo->GetIntField("projectionObject.proZone");
 
-        for( i = 0; i < 15; i++ )
+        for( int i = 0; i < 15; i++ )
         {
-            char	szFieldName[40];
+            char szFieldName[40] = {};
 
-            snprintf( szFieldName, sizeof(szFieldName), "projectionObject.proParams[%d]", i );
+            snprintf(szFieldName, sizeof(szFieldName),
+                     "projectionObject.proParams[%d]", i);
             sPro.proParams[i] = poProjInfo->GetDoubleField(szFieldName);
         }
 
-    /* -------------------------------------------------------------------- */
-    /*      Fetch the spheroid.                                             */
-    /* -------------------------------------------------------------------- */
-        sPro.proSpheroid.sphereName = (char *)
-            poProjInfo->GetStringField("earthModel.proSpheroid.sphereName");
-        sPro.proSpheroid.a = poProjInfo->GetDoubleField("earthModel.proSpheroid.a");
-        sPro.proSpheroid.b = poProjInfo->GetDoubleField("earthModel.proSpheroid.b");
+        // Fetch the spheroid.
+        sPro.proSpheroid.sphereName = (char *)poProjInfo->GetStringField(
+            "earthModel.proSpheroid.sphereName");
+        sPro.proSpheroid.a =
+            poProjInfo->GetDoubleField("earthModel.proSpheroid.a");
+        sPro.proSpheroid.b =
+            poProjInfo->GetDoubleField("earthModel.proSpheroid.b");
         sPro.proSpheroid.eSquared =
             poProjInfo->GetDoubleField("earthModel.proSpheroid.eSquared");
         sPro.proSpheroid.radius =
             poProjInfo->GetDoubleField("earthModel.proSpheroid.radius");
 
-    /* -------------------------------------------------------------------- */
-    /*      Fetch the projection info.                                      */
-    /* -------------------------------------------------------------------- */
-        char *pszProjection;
-
-    //    poProjInfo->DumpFieldValues( stdout, "" );
+        // Fetch the projection info.
+        // poProjInfo->DumpFieldValues( stdout, "" );
 
-        pszProjection = HFAPCSStructToWKT( &sDatum, &sPro, NULL, NULL );
+        char *pszProjection = HFAPCSStructToWKT(&sDatum, &sPro, NULL, NULL);
 
         if( pszProjection )
         {
             papszMD =
-                CSLSetNameValue( papszMD, "outputProjection", pszProjection );
-            CPLFree( pszProjection );
+                CSLSetNameValue(papszMD, "outputProjection", pszProjection);
+            CPLFree(pszProjection);
         }
 
         delete poProjInfo;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Fetch the horizontal units.                                     */
-/* -------------------------------------------------------------------- */
-    pszValue = poXForm->GetStringField( "outputHorizontalUnits.string" );
+    // Fetch the horizontal units.
+    pszValue = poXForm->GetStringField("outputHorizontalUnits.string");
     if( pszValue == NULL )
         pszValue = "";
 
-    papszMD = CSLSetNameValue( papszMD, "outputHorizontalUnits", pszValue );
+    papszMD = CSLSetNameValue(papszMD, "outputHorizontalUnits", pszValue);
 
-/* -------------------------------------------------------------------- */
-/*      Fetch the elevationinfo.                                        */
-/* -------------------------------------------------------------------- */
-    HFAEntry *poElevInfo = HFAEntry::BuildEntryFromMIFObject( poXForm, "outputElevationInfo" );
-    if ( poElevInfo )
+    // Fetch the elevationinfo.
+    HFAEntry *poElevInfo =
+        HFAEntry::BuildEntryFromMIFObject(poXForm, "outputElevationInfo");
+    if( poElevInfo )
     {
-        //poElevInfo->DumpFieldValues( stdout, "" );
+        // poElevInfo->DumpFieldValues( stdout, "" );
 
         if( poElevInfo->GetDataSize() != 0 )
         {
-            static const char * const apszEFields[] = {
+            static const char *const apszEFields[] = {
                 "verticalDatum.datumname",
                 "verticalDatum.type",
                 "elevationUnit",
                 "elevationType",
                 NULL };
 
-            for( i = 0; apszEFields[i] != NULL; i++ )
+            for( int i = 0; apszEFields[i] != NULL; i++ )
             {
-                pszValue = poElevInfo->GetStringField( apszEFields[i] );
+                pszValue = poElevInfo->GetStringField(apszEFields[i]);
                 if( pszValue == NULL )
                     pszValue = "";
 
-                papszMD = CSLSetNameValue( papszMD, apszEFields[i], pszValue );
+                papszMD = CSLSetNameValue(papszMD, apszEFields[i], pszValue);
             }
         }
 
@@ -3795,6 +3502,28 @@ char **HFAReadCameraModel( HFAHandle hHFA )
 }
 
 /************************************************************************/
+/*                         HFAReadElevationUnit()                       */
+/************************************************************************/
+
+const char *HFAReadElevationUnit( HFAHandle hHFA, int iBand )
+{
+    if( hHFA->nBands <= iBand )
+        return NULL;
+
+    HFABand *poBand(hHFA->papoBand[iBand]);
+    if( poBand == NULL || poBand->poNode == NULL )
+    {
+        return NULL;
+    }
+    HFAEntry *poElevInfo = poBand->poNode->GetNamedChild("Elevation_Info");
+    if( poElevInfo == NULL )
+    {
+        return NULL;
+    }
+    return poElevInfo->GetStringField("elevationUnit");
+}
+
+/************************************************************************/
 /*                         HFASetGeoTransform()                         */
 /*                                                                      */
 /*      Set a MapInformation and XForm block.  Allows for rotated       */
@@ -3807,60 +3536,58 @@ CPLErr HFASetGeoTransform( HFAHandle hHFA,
                            double *padfGeoTransform )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Write MapInformation.                                           */
-/* -------------------------------------------------------------------- */
-    int nBand;
-
-    for( nBand = 1; nBand <= hHFA->nBands; nBand++ )
+    // Write MapInformation.
+    for( int nBand = 1; nBand <= hHFA->nBands; nBand++ )
     {
-        HFAEntry *poBandNode = hHFA->papoBand[nBand-1]->poNode;
+        HFAEntry *poBandNode = hHFA->papoBand[nBand - 1]->poNode;
 
-        HFAEntry *poMI = poBandNode->GetNamedChild( "MapInformation" );
+        HFAEntry *poMI = poBandNode->GetNamedChild("MapInformation");
         if( poMI == NULL )
         {
-            poMI = HFAEntry::New( hHFA, "MapInformation",
-                                 "Eimg_MapInformation", poBandNode );
-            poMI->MakeData( static_cast<int>(18 + strlen(pszProName) + strlen(pszUnits)) );
+            poMI = HFAEntry::New(hHFA, "MapInformation", "Eimg_MapInformation",
+                                 poBandNode);
+            poMI->MakeData(
+                static_cast<int>(18 + strlen(pszProName) + strlen(pszUnits)));
             poMI->SetPosition();
         }
 
-        poMI->SetStringField( "projection.string", pszProName );
-        poMI->SetStringField( "units.string", pszUnits );
+        poMI->SetStringField("projection.string", pszProName);
+        poMI->SetStringField("units.string", pszUnits);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write XForm.                                                    */
-/* -------------------------------------------------------------------- */
-    Efga_Polynomial sForward, sReverse;
-    double          adfAdjTransform[6], adfRevTransform[6];
+    // Write XForm.
+    double adfAdjTransform[6] = {};
 
     // Offset by half pixel.
 
-    memcpy( adfAdjTransform, padfGeoTransform, sizeof(double) * 6 );
+    memcpy(adfAdjTransform, padfGeoTransform, sizeof(double) * 6);
     adfAdjTransform[0] += adfAdjTransform[1] * 0.5;
     adfAdjTransform[0] += adfAdjTransform[2] * 0.5;
     adfAdjTransform[3] += adfAdjTransform[4] * 0.5;
     adfAdjTransform[3] += adfAdjTransform[5] * 0.5;
 
-    // Invert
+    // Invert.
+    double adfRevTransform[6] = {};
     if( !HFAInvGeoTransform( adfAdjTransform, adfRevTransform ) )
         memset(adfRevTransform, 0, sizeof(adfRevTransform));
 
     // Assign to polynomial object.
 
+    Efga_Polynomial sForward;
+    memset(&sForward, 0, sizeof(sForward));
+    Efga_Polynomial *psForward = &sForward;
     sForward.order = 1;
     sForward.polycoefvector[0] = adfRevTransform[0];
-    sForward.polycoefmtx[0]    = adfRevTransform[1];
-    sForward.polycoefmtx[1]    = adfRevTransform[4];
+    sForward.polycoefmtx[0] = adfRevTransform[1];
+    sForward.polycoefmtx[1] = adfRevTransform[4];
     sForward.polycoefvector[1] = adfRevTransform[3];
-    sForward.polycoefmtx[2]    = adfRevTransform[2];
-    sForward.polycoefmtx[3]    = adfRevTransform[5];
+    sForward.polycoefmtx[2] = adfRevTransform[2];
+    sForward.polycoefmtx[3] = adfRevTransform[5];
 
-    sReverse = sForward;
-    Efga_Polynomial *psForward=&sForward, *psReverse=&sReverse;
+    Efga_Polynomial sReverse = sForward;
+    Efga_Polynomial *psReverse = &sReverse;
 
-    return HFAWriteXFormStack( hHFA, 0, 1, &psForward, &psReverse );
+    return HFAWriteXFormStack(hHFA, 0, 1, &psForward, &psReverse);
 }
 
 /************************************************************************/
@@ -3876,33 +3603,30 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
                             const char *pszOldBase )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Handle RRDNamesList updates.                                    */
-/* -------------------------------------------------------------------- */
-    size_t iNode;
-    std::vector<HFAEntry*> apoNodeList =
-        hHFA->poRoot->FindChildren( "RRDNamesList", NULL );
+    // Handle RRDNamesList updates.
+    std::vector<HFAEntry *> apoNodeList =
+        hHFA->poRoot->FindChildren("RRDNamesList", NULL);
 
-    for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
+    for( size_t iNode = 0; iNode < apoNodeList.size(); iNode++ )
     {
         HFAEntry *poRRDNL = apoNodeList[iNode];
         std::vector<CPLString> aosNL;
 
         // Collect all the existing names.
-        int i, nNameCount = poRRDNL->GetFieldCount( "nameList" );
+        const int nNameCount = poRRDNL->GetFieldCount("nameList");
 
         CPLString osAlgorithm = poRRDNL->GetStringField("algorithm.string");
-        for( i = 0; i < nNameCount; i++ )
+        for( int i = 0; i < nNameCount; i++ )
         {
             CPLString osFN;
-            osFN.Printf( "nameList[%d].string", i );
-            aosNL.push_back( poRRDNL->GetStringField(osFN) );
+            osFN.Printf("nameList[%d].string", i);
+            aosNL.push_back(poRRDNL->GetStringField(osFN));
         }
 
         // Adjust the names to the new form.
-        for( i = 0; i < nNameCount; i++ )
+        for( int i = 0; i < nNameCount; i++ )
         {
-            if( strncmp(aosNL[i],pszOldBase,strlen(pszOldBase)) == 0 )
+            if( strncmp(aosNL[i], pszOldBase, strlen(pszOldBase)) == 0 )
             {
                 CPLString osNew = pszNewBase;
                 osNew += aosNL[i].c_str() + strlen(pszOldBase);
@@ -3910,35 +3634,34 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
             }
         }
 
-        // try to make sure the RRDNamesList is big enough to hold the
+        // Try to make sure the RRDNamesList is big enough to hold the
         // adjusted name list.
         if( strlen(pszNewBase) > strlen(pszOldBase) )
         {
-            CPLDebug( "HFA", "Growing RRDNamesList to hold new names" );
-            poRRDNL->MakeData( static_cast<int>(poRRDNL->GetDataSize()
-                               + nNameCount * (strlen(pszNewBase) - strlen(pszOldBase))) );
+            CPLDebug("HFA", "Growing RRDNamesList to hold new names");
+            poRRDNL->MakeData(static_cast<int>(
+                poRRDNL->GetDataSize() +
+                nNameCount * (strlen(pszNewBase) - strlen(pszOldBase))));
         }
 
         // Initialize the whole thing to zeros for a clean start.
-        memset( poRRDNL->GetData(), 0, poRRDNL->GetDataSize() );
+        memset(poRRDNL->GetData(), 0, poRRDNL->GetDataSize());
 
         // Write the updates back to the file.
-        poRRDNL->SetStringField( "algorithm.string", osAlgorithm );
-        for( i = 0; i < nNameCount; i++ )
+        poRRDNL->SetStringField("algorithm.string", osAlgorithm);
+        for( int i = 0; i < nNameCount; i++ )
         {
             CPLString osFN;
-            osFN.Printf( "nameList[%d].string", i );
-            poRRDNL->SetStringField( osFN, aosNL[i] );
+            osFN.Printf("nameList[%d].string", i);
+            poRRDNL->SetStringField(osFN, aosNL[i]);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      spill file references.                                          */
-/* -------------------------------------------------------------------- */
+    // Spill file references.
     apoNodeList =
-        hHFA->poRoot->FindChildren( "ExternalRasterDMS", "ImgExternalRaster" );
+        hHFA->poRoot->FindChildren("ExternalRasterDMS", "ImgExternalRaster");
 
-    for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
+    for( size_t iNode = 0; iNode < apoNodeList.size(); iNode++ )
     {
         HFAEntry *poERDMS = apoNodeList[iNode];
 
@@ -3947,24 +3670,22 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
 
         // Fetch all existing values.
         CPLString osFileName = poERDMS->GetStringField("fileName.string");
-        GInt32 anValidFlagsOffset[2], anStackDataOffset[2];
-        GInt32 nStackCount, nStackIndex;
 
-        anValidFlagsOffset[0] =
-            poERDMS->GetIntField( "layerStackValidFlagsOffset[0]" );
-        anValidFlagsOffset[1] =
-            poERDMS->GetIntField( "layerStackValidFlagsOffset[1]" );
+        GInt32 anValidFlagsOffset[2] = {
+            poERDMS->GetIntField("layerStackValidFlagsOffset[0]"),
+            poERDMS->GetIntField("layerStackValidFlagsOffset[1]")
+        };
 
-        anStackDataOffset[0] =
-            poERDMS->GetIntField( "layerStackDataOffset[0]" );
-        anStackDataOffset[1] =
-            poERDMS->GetIntField( "layerStackDataOffset[1]" );
+        GInt32 anStackDataOffset[2] = {
+            poERDMS->GetIntField("layerStackDataOffset[0]"),
+            poERDMS->GetIntField("layerStackDataOffset[1]")
+        };
 
-        nStackCount = poERDMS->GetIntField( "layerStackCount" );
-        nStackIndex = poERDMS->GetIntField( "layerStackIndex" );
+        const GInt32 nStackCount = poERDMS->GetIntField("layerStackCount");
+        const GInt32 nStackIndex = poERDMS->GetIntField("layerStackIndex");
 
         // Update the filename.
-        if( strncmp(osFileName,pszOldBase,strlen(pszOldBase)) == 0 )
+        if( strncmp(osFileName, pszOldBase, strlen(pszOldBase)) == 0 )
         {
             CPLString osNew = pszNewBase;
             osNew += osFileName.c_str() + strlen(pszOldBase);
@@ -3974,59 +3695,56 @@ CPLErr HFARenameReferences( HFAHandle hHFA,
         // Grow the node if needed.
         if( strlen(pszNewBase) > strlen(pszOldBase) )
         {
-            CPLDebug( "HFA", "Growing ExternalRasterDMS to hold new names" );
-            poERDMS->MakeData( static_cast<int>(poERDMS->GetDataSize()
-                               + (strlen(pszNewBase) - strlen(pszOldBase))) );
+            CPLDebug("HFA", "Growing ExternalRasterDMS to hold new names");
+            poERDMS->MakeData(
+                static_cast<int>(poERDMS->GetDataSize() +
+                                 (strlen(pszNewBase) - strlen(pszOldBase))));
         }
 
         // Initialize the whole thing to zeros for a clean start.
-        memset( poERDMS->GetData(), 0, poERDMS->GetDataSize() );
+        memset(poERDMS->GetData(), 0, poERDMS->GetDataSize());
 
         // Write it all out again, this may change the size of the node.
-        poERDMS->SetStringField( "fileName.string", osFileName );
-        poERDMS->SetIntField( "layerStackValidFlagsOffset[0]",
-                              anValidFlagsOffset[0] );
-        poERDMS->SetIntField( "layerStackValidFlagsOffset[1]",
-                              anValidFlagsOffset[1] );
+        poERDMS->SetStringField("fileName.string", osFileName);
+        poERDMS->SetIntField("layerStackValidFlagsOffset[0]",
+                             anValidFlagsOffset[0]);
+        poERDMS->SetIntField("layerStackValidFlagsOffset[1]",
+                             anValidFlagsOffset[1]);
 
-        poERDMS->SetIntField( "layerStackDataOffset[0]",
-                              anStackDataOffset[0] );
-        poERDMS->SetIntField( "layerStackDataOffset[1]",
-                              anStackDataOffset[1] );
+        poERDMS->SetIntField("layerStackDataOffset[0]", anStackDataOffset[0]);
+        poERDMS->SetIntField("layerStackDataOffset[1]", anStackDataOffset[1]);
 
-        poERDMS->SetIntField( "layerStackCount", nStackCount );
-        poERDMS->SetIntField( "layerStackIndex", nStackIndex );
+        poERDMS->SetIntField("layerStackCount", nStackCount);
+        poERDMS->SetIntField("layerStackIndex", nStackIndex);
     }
 
-/* -------------------------------------------------------------------- */
-/*      DependentFile                                                   */
-/* -------------------------------------------------------------------- */
+    // DependentFile.
     apoNodeList =
-        hHFA->poRoot->FindChildren( "DependentFile", "Eimg_DependentFile" );
+        hHFA->poRoot->FindChildren("DependentFile", "Eimg_DependentFile");
 
-    for( iNode = 0; iNode < apoNodeList.size(); iNode++ )
+    for( size_t iNode = 0; iNode < apoNodeList.size(); iNode++ )
     {
-        CPLString osFileName = apoNodeList[iNode]->
-            GetStringField("dependent.string");
+        CPLString osFileName =
+            apoNodeList[iNode]->GetStringField("dependent.string");
 
         // Grow the node if needed.
         if( strlen(pszNewBase) > strlen(pszOldBase) )
         {
-            CPLDebug( "HFA", "Growing DependentFile to hold new names" );
-            apoNodeList[iNode]->MakeData( static_cast<int>(apoNodeList[iNode]->GetDataSize()
-                                          + (strlen(pszNewBase)
-                                             - strlen(pszOldBase))) );
+            CPLDebug("HFA", "Growing DependentFile to hold new names");
+            apoNodeList[iNode]->MakeData(
+                static_cast<int>(apoNodeList[iNode]->GetDataSize() +
+                                 (strlen(pszNewBase) - strlen(pszOldBase))));
         }
 
         // Update the filename.
-        if( strncmp(osFileName,pszOldBase,strlen(pszOldBase)) == 0 )
+        if( strncmp(osFileName, pszOldBase, strlen(pszOldBase)) == 0 )
         {
             CPLString osNew = pszNewBase;
             osNew += osFileName.c_str() + strlen(pszOldBase);
             osFileName = osNew;
         }
 
-        apoNodeList[iNode]->SetStringField( "dependent.string", osFileName );
+        apoNodeList[iNode]->SetStringField("dependent.string", osFileName);
     }
 
     return CE_None;
diff --git a/frmts/hfa/hfatest.cpp b/frmts/hfa/hfatest.cpp
index 5a55f46..3c3c0f2 100644
--- a/frmts/hfa/hfatest.cpp
+++ b/frmts/hfa/hfatest.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfatest.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Testing mainline for HFA services - transitory.
@@ -31,7 +30,7 @@
 #include "hfa_p.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: hfatest.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: hfatest.cpp 35929 2016-10-25 16:09:00Z goatbar $");
 
 /************************************************************************/
 /*                               Usage()                                */
@@ -75,14 +74,22 @@ int main( int argc, char ** argv )
 
     for( int i = 1; i < argc; i++ )
     {
-        if( EQUAL(argv[i],"-dd") )
-            bDumpDict = TRUE;
-        else if( EQUAL(argv[i],"-dt") )
-            bDumpTree = TRUE;
-        else if( EQUAL(argv[i],"-dr") )
-            bRastReport = TRUE;
+        if( EQUAL(argv[i], "-dd") )
+        {
+            bDumpDict = true;
+        }
+        else if( EQUAL(argv[i], "-dt") )
+        {
+            bDumpTree = true;
+        }
+        else if( EQUAL(argv[i], "-dr") )
+        {
+            bRastReport = true;
+        }
         else if( pszFilename == NULL )
+        {
             pszFilename = argv[i];
+        }
         else
         {
             Usage();
@@ -126,7 +133,9 @@ int main( int argc, char ** argv )
 /* -------------------------------------------------------------------- */
 /*      Dump indirectly collected data about bands.                     */
 /* -------------------------------------------------------------------- */
-    int nXSize, nYSize, nBands;
+    int nXSize = 0;
+    int nYSize = 0;
+    int nBands = 0;
     HFAGetRasterInfo( hHFA, &nXSize, &nYSize, &nBands );
 
     if( bRastReport )
@@ -136,13 +145,13 @@ int main( int argc, char ** argv )
         for( int i = 1; i <= nBands; i++ )
         {
             EPTType eDataType;
-            int nBlockXSize;
-            int nBlockYSize;
-            int nCompressionType;
+            int nBlockXSize = 0;
+            int nBlockYSize = 0;
+            int nCompressionType = 0;
 
             HFAGetBandInfo( hHFA, i, &eDataType, &nBlockXSize, &nBlockYSize,
                             &nCompressionType );
-            int nOverviews = HFAGetOverviewCount( hHFA, i );
+            const int nOverviews = HFAGetOverviewCount( hHFA, i );
 
             printf( "Band %d: %dx%d tiles, type = %d\n",
                     i, nBlockXSize, nBlockYSize, eDataType );
@@ -156,18 +165,24 @@ int main( int argc, char ** argv )
                         nXSize, nYSize, nBlockXSize, nBlockYSize );
             }
 
-            int nColors;
-            double *padfRed, *padfGreen, *padfBlue, *padfAlpha, *padfBins;
+            int nColors = 0;
+            double *padfRed = NULL;
+            double *padfGreen = NULL;
+            double *padfBlue = NULL;
+            double *padfAlpha = NULL;
+            double *padfBins = NULL;
             if( HFAGetPCT( hHFA, i, &nColors, &padfRed, &padfGreen,
-			   &padfBlue, &padfAlpha, &padfBins )
+                           &padfBlue, &padfAlpha, &padfBins )
                 == CE_None )
             {
                 for( int j = 0; j < nColors; j++ )
                 {
                     printf( "PCT[%d] = %f,%f,%f %f\n",
-                            (padfBins != NULL) ? (int) padfBins[j] : j,
+                            (padfBins != NULL)
+                            ? static_cast<int>(padfBins[j])
+                            : j,
                             padfRed[j], padfGreen[j],
-			    padfBlue[j], padfAlpha[j]);
+                            padfBlue[j], padfAlpha[j]);
                 }
             }
 
@@ -189,7 +204,9 @@ int main( int argc, char ** argv )
                         poStats->GetDoubleField( "stddev" ) );
             }
             else
+            {
                 printf( "   No Statistics found.\n" );
+            }
         }
 
 /* -------------------------------------------------------------------- */
@@ -209,10 +226,8 @@ int main( int argc, char ** argv )
         {
             printf( "No Map Info found\n" );
         }
-
     }
 
-
     // const Eprj_ProParameters *psProParameters;
     // psProParameters =
     HFAGetProParameters( hHFA );
diff --git a/frmts/hfa/hfatype.cpp b/frmts/hfa/hfatype.cpp
index 5ef0fe5..3174d89 100644
--- a/frmts/hfa/hfatype.cpp
+++ b/frmts/hfa/hfatype.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hfatype.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Erdas Imagine (.img) Translator
  * Purpose:  Implementation of the HFAType class, for managing one type
@@ -29,13 +28,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "hfa_p.h"
 
-CPL_CVSID("$Id: hfatype.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+
+CPL_CVSID("$Id: hfatype.cpp 37885 2017-04-01 21:08:40Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*      		       HFAType					*/
+/*                             HFAType                                  */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -44,12 +53,12 @@ CPL_CVSID("$Id: hfatype.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 /************************************************************************/
 
 HFAType::HFAType() :
-    bInCompleteDefn(FALSE),
+    bInCompleteDefn(false),
     nBytes(0),
     nFields(0),
     papoFields(NULL),
     pszTypeName(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                              ~HFAType()                              */
@@ -63,23 +72,23 @@ HFAType::~HFAType()
         delete papoFields[i];
     }
 
-    CPLFree( papoFields );
+    CPLFree(papoFields);
 
-    CPLFree( pszTypeName );
+    CPLFree(pszTypeName);
 }
 
 /************************************************************************/
 /*                             Initialize()                             */
 /************************************************************************/
 
-const char *HFAType::Initialize( const char * pszInput )
+const char *HFAType::Initialize( const char *pszInput )
 
 {
     if( *pszInput != '{' )
     {
         if( *pszInput != '\0' )
-            CPLDebug( "HFAType", "Initialize(%60.60s) - unexpected input.",
-                      pszInput );
+            CPLDebug("HFAType", "Initialize(%60.60s) - unexpected input.",
+                     pszInput);
 
         while( *pszInput != '{' && *pszInput != '\0' )
             pszInput++;
@@ -90,43 +99,41 @@ const char *HFAType::Initialize( const char * pszInput )
 
     pszInput++;
 
-/* -------------------------------------------------------------------- */
-/*      Read the field definitions.                                     */
-/* -------------------------------------------------------------------- */
+    // Read the field definitions.
     while( pszInput != NULL && *pszInput != '}' )
     {
-        HFAField	*poNewField = new HFAField();
+        HFAField *poNewField = new HFAField();
 
-        pszInput = poNewField->Initialize( pszInput );
+        pszInput = poNewField->Initialize(pszInput);
         if( pszInput != NULL )
         {
-            papoFields = (HFAField **)
-                CPLRealloc(papoFields, sizeof(void*) * (nFields+1) );
+            papoFields = static_cast<HFAField **>(
+                CPLRealloc(papoFields, sizeof(void *) * (nFields + 1)));
             papoFields[nFields++] = poNewField;
         }
         else
+        {
             delete poNewField;
+        }
     }
 
     if( pszInput == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Collect the name.                                               */
-/* -------------------------------------------------------------------- */
-    pszInput++; /* skip `}' */
-    int i = 0;
+    // Collect the name.
+    pszInput++;  // Skip `}'
+    int i = 0;  // Used after for.
     for( ; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
-    if (pszInput[i] == '\0')
+    if( pszInput[i] == '\0' )
         return NULL;
 
-    pszTypeName = (char *) CPLMalloc(i+1);
-    strncpy( pszTypeName, pszInput, i );
+    pszTypeName = static_cast<char *>(CPLMalloc(i + 1));
+    strncpy(pszTypeName, pszInput, i);
     pszTypeName[i] = '\0';
 
-    pszInput += i+1;
+    pszInput += i + 1;
 
-    return( pszInput );
+    return pszInput;
 }
 
 /************************************************************************/
@@ -136,31 +143,24 @@ const char *HFAType::Initialize( const char * pszInput )
 void HFAType::CompleteDefn( HFADictionary * poDict )
 
 {
-/* -------------------------------------------------------------------- */
-/*      This may already be done, if an earlier object required this    */
-/*      object (as a field), and forced an early computation of the     */
-/*      size.                                                           */
-/* -------------------------------------------------------------------- */
+    // This may already be done, if an earlier object required this
+    // object (as a field), and forced an early computation of the size.
     if( nBytes != 0 )
         return;
 
-
     if( bInCompleteDefn )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Recursion detected in HFAType::CompleteDefn()");
         return;
     }
-    bInCompleteDefn = TRUE;
+    bInCompleteDefn = true;
 
-/* -------------------------------------------------------------------- */
-/*      Complete each of the fields, totaling up the sizes.  This       */
-/*      isn't really accurate for object with variable sized            */
-/*      subobjects.                                                     */
-/* -------------------------------------------------------------------- */
+    // Complete each of the fields, totaling up the sizes.  This
+    // isn't really accurate for object with variable sized subobjects.
     for( int i = 0; i < nFields; i++ )
     {
-        papoFields[i]->CompleteDefn( poDict );
+        papoFields[i]->CompleteDefn(poDict);
         if( papoFields[i]->nBytes < 0 || nBytes == -1 )
             nBytes = -1;
         else if( nBytes < INT_MAX - papoFields[i]->nBytes )
@@ -169,7 +169,7 @@ void HFAType::CompleteDefn( HFADictionary * poDict )
             nBytes = -1;
     }
 
-    bInCompleteDefn = FALSE;
+    bInCompleteDefn = false;
 }
 
 /************************************************************************/
@@ -179,14 +179,15 @@ void HFAType::CompleteDefn( HFADictionary * poDict )
 void HFAType::Dump( FILE * fp )
 
 {
-    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "HFAType %s/%d bytes\n", pszTypeName, nBytes ));
+    CPL_IGNORE_RET_VAL(
+        VSIFPrintf(fp, "HFAType %s/%d bytes\n", pszTypeName, nBytes));
 
     for( int i = 0; i < nFields; i++ )
     {
-        papoFields[i]->Dump( fp );
+        papoFields[i]->Dump(fp);
     }
 
-    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "\n" ));
+    CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "\n"));
 }
 
 /************************************************************************/
@@ -194,63 +195,58 @@ void HFAType::Dump( FILE * fp )
 /************************************************************************/
 
 CPLErr
-HFAType::SetInstValue( const char * pszFieldPath,
+HFAType::SetInstValue( const char *pszFieldPath,
                        GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
                        char chReqType, void *pValue )
 
 {
     int nArrayIndex = 0;
-    int nNameLen;
-    const char *pszRemainder;
-
-/* -------------------------------------------------------------------- */
-/*      Parse end of field name, possible index value and               */
-/*      establish where the remaining fields (if any) would start.      */
-/* -------------------------------------------------------------------- */
-    if( strchr(pszFieldPath,'[') != NULL )
+    int nNameLen = 0;
+    const char *pszRemainder = NULL;
+
+    // Parse end of field name, possible index value and
+    // establish where the remaining fields (if any) would start.
+    if( strchr(pszFieldPath, '[') != NULL )
     {
-        const char	*pszEnd = strchr(pszFieldPath,'[');
+        const char *pszEnd = strchr(pszFieldPath, '[');
 
-        nArrayIndex = atoi(pszEnd+1);
+        nArrayIndex = atoi(pszEnd + 1);
         nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
-        pszRemainder = strchr(pszFieldPath,'.');
+        pszRemainder = strchr(pszFieldPath, '.');
         if( pszRemainder != NULL )
             pszRemainder++;
     }
-
-    else if( strchr(pszFieldPath,'.') != NULL )
+    else if( strchr(pszFieldPath, '.') != NULL )
     {
-        const char	*pszEnd = strchr(pszFieldPath,'.');
+        const char *pszEnd = strchr(pszFieldPath, '.');
 
         nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
         pszRemainder = pszEnd + 1;
     }
-
     else
     {
         nNameLen = static_cast<int>(strlen(pszFieldPath));
-        pszRemainder = pszFieldPath/*NULL*/;
+        pszRemainder = pszFieldPath /* NULL */;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Find this field within this type, if possible.                  */
-/* -------------------------------------------------------------------- */
+    // Find this field within this type, if possible.
     int nByteOffset = 0;
     int iField = 0;
     for( ; iField < nFields && nByteOffset < nDataSize; iField++ )
     {
-        if( EQUALN(pszFieldPath,papoFields[iField]->pszFieldName,nNameLen)
+        if( EQUALN(pszFieldPath, papoFields[iField]->pszFieldName, nNameLen)
             && papoFields[iField]->pszFieldName[nNameLen] == '\0' )
         {
             break;
         }
 
-        int nInc = papoFields[iField]->GetInstBytes( pabyData+nByteOffset,
-                                              nDataSize - nByteOffset );
+        const int nInc = papoFields[iField]->GetInstBytes(
+            pabyData + nByteOffset, nDataSize - nByteOffset);
 
-        if (nInc < 0 || nByteOffset > INT_MAX - nInc)
+        if( nInc < 0 ||
+            nByteOffset > INT_MAX - nInc )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
             return CE_Failure;
@@ -262,14 +258,12 @@ HFAType::SetInstValue( const char * pszFieldPath,
     if( iField == nFields || nByteOffset >= nDataSize )
         return CE_Failure;
 
-/* -------------------------------------------------------------------- */
-/*      Extract this field value, and return.                           */
-/* -------------------------------------------------------------------- */
-    return( papoFields[iField]->SetInstValue( pszRemainder, nArrayIndex,
-                                              pabyData + nByteOffset,
-                                              nDataOffset + nByteOffset,
-                                              nDataSize - nByteOffset,
-                                              chReqType, pValue ) );
+    // Extract this field value, and return.
+    return papoFields[iField]->SetInstValue(pszRemainder, nArrayIndex,
+                                            pabyData + nByteOffset,
+                                            nDataOffset + nByteOffset,
+                                            nDataSize - nByteOffset,
+                                            chReqType, pValue);
 }
 
 /************************************************************************/
@@ -277,63 +271,57 @@ HFAType::SetInstValue( const char * pszFieldPath,
 /************************************************************************/
 
 int
-HFAType::GetInstCount( const char * pszFieldPath,
+HFAType::GetInstCount( const char *pszFieldPath,
                        GByte *pabyData,
-                       CPL_UNUSED GUInt32 nDataOffset,
+                       GUInt32 /* nDataOffset */,
                        int nDataSize )
 {
-    /* int		nArrayIndex = 0; */
-    int		nNameLen;
-    /*const char	*pszRemainder;*/
-
-/* -------------------------------------------------------------------- */
-/*      Parse end of field name, possible index value and               */
-/*      establish where the remaining fields (if any) would start.      */
-/* -------------------------------------------------------------------- */
-    if( strchr(pszFieldPath,'[') != NULL )
+    // int nArrayIndex = 0;
+    int nNameLen = 0;
+    // const char *pszRemainder;
+
+    // Parse end of field name, possible index value and
+    // establish where the remaining fields (if any) would start.
+    if( strchr(pszFieldPath, '[') != NULL )
     {
-        const char	*pszEnd = strchr(pszFieldPath,'[');
+        const char *pszEnd = strchr(pszFieldPath, '[');
 
-        /* nArrayIndex = atoi(pszEnd+1); */
+        // nArrayIndex = atoi(pszEnd+1);
         nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
-        /*pszRemainder = strchr(pszFieldPath,'.');
-        if( pszRemainder != NULL )
-            pszRemainder++;*/
+        // pszRemainder = strchr(pszFieldPath, '.');
+        // if( pszRemainder != NULL )
+        //    pszRemainder++;
     }
-
-    else if( strchr(pszFieldPath,'.') != NULL )
+    else if( strchr(pszFieldPath, '.') != NULL )
     {
-        const char	*pszEnd = strchr(pszFieldPath,'.');
+        const char *pszEnd = strchr(pszFieldPath, '.');
 
         nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
-        /*pszRemainder = pszEnd + 1;*/
+        // pszRemainder = pszEnd + 1;
     }
-
     else
     {
         nNameLen = static_cast<int>(strlen(pszFieldPath));
-        /*pszRemainder = NULL;*/
+        // pszRemainder = NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Find this field within this type, if possible.                  */
-/* -------------------------------------------------------------------- */
+    // Find this field within this type, if possible.
     int nByteOffset = 0;
     int iField = 0;
     for( ; iField < nFields && nByteOffset < nDataSize; iField++ )
     {
-        if( EQUALN(pszFieldPath,papoFields[iField]->pszFieldName,nNameLen)
+        if( EQUALN(pszFieldPath, papoFields[iField]->pszFieldName,nNameLen)
             && papoFields[iField]->pszFieldName[nNameLen] == '\0' )
         {
             break;
         }
 
-        int nInc = papoFields[iField]->GetInstBytes( pabyData+nByteOffset,
-                                              nDataSize - nByteOffset );
+        const int nInc = papoFields[iField]->GetInstBytes(
+            pabyData + nByteOffset, nDataSize - nByteOffset);
 
-        if (nInc < 0 || nByteOffset > INT_MAX - nInc)
+        if( nInc < 0 || nByteOffset > INT_MAX - nInc )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
             return -1;
@@ -345,11 +333,9 @@ HFAType::GetInstCount( const char * pszFieldPath,
     if( iField == nFields || nByteOffset >= nDataSize )
         return -1;
 
-/* -------------------------------------------------------------------- */
-/*      Extract this field value, and return.                           */
-/* -------------------------------------------------------------------- */
-    return( papoFields[iField]->GetInstCount( pabyData + nByteOffset,
-                                              nDataSize - nByteOffset ) );
+    // Extract this field value, and return.
+    return papoFields[iField]->GetInstCount(pabyData + nByteOffset,
+                                            nDataSize - nByteOffset);
 }
 
 /************************************************************************/
@@ -370,111 +356,103 @@ HFAType::GetInstCount( const char * pszFieldPath,
 /*                                                the third abc struct. */
 /************************************************************************/
 
-int
-HFAType::ExtractInstValue( const char * pszFieldPath,
+bool
+HFAType::ExtractInstValue( const char *pszFieldPath,
                            GByte *pabyData, GUInt32 nDataOffset, int nDataSize,
-                           char chReqType, void *pReqReturn, int *pnRemainingDataSize )
+                           char chReqType, void *pReqReturn,
+                           int *pnRemainingDataSize )
 
 {
     int nArrayIndex = 0;
-    int nNameLen;
-    const char *pszRemainder;
+    int nNameLen = 0;
+    const char *pszRemainder = NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Parse end of field name, possible index value and               */
-/*      establish where the remaining fields (if any) would start.      */
-/* -------------------------------------------------------------------- */
-    const char *pszFirstArray = strchr(pszFieldPath,'[');
-    const char *pszFirstDot = strchr(pszFieldPath,'.');
+    // Parse end of field name, possible index value and
+    // establish where the remaining fields (if any) would start.
+    const char *pszFirstArray = strchr(pszFieldPath, '[');
+    const char *pszFirstDot = strchr(pszFieldPath, '.');
 
     if( pszFirstArray != NULL
         && (pszFirstDot == NULL
             || pszFirstDot > pszFirstArray) )
     {
-        const char	*pszEnd = pszFirstArray;
+        const char *pszEnd = pszFirstArray;
 
-        nArrayIndex = atoi(pszEnd+1);
+        nArrayIndex = atoi(pszEnd + 1);
         nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
-        pszRemainder = strchr(pszFieldPath,'.');
+        pszRemainder = strchr(pszFieldPath, '.');
         if( pszRemainder != NULL )
             pszRemainder++;
     }
-
     else if( pszFirstDot != NULL )
     {
-        const char	*pszEnd = pszFirstDot;
+        const char *pszEnd = pszFirstDot;
 
         nNameLen = static_cast<int>(pszEnd - pszFieldPath);
 
         pszRemainder = pszEnd + 1;
     }
-
     else
     {
         nNameLen = static_cast<int>(strlen(pszFieldPath));
         pszRemainder = NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Find this field within this type, if possible.                  */
-/* -------------------------------------------------------------------- */
+    // Find this field within this type, if possible.
     int nByteOffset = 0;
     int iField = 0;
     for( ; iField < nFields && nByteOffset < nDataSize; iField++ )
     {
-        if( EQUALN(pszFieldPath,papoFields[iField]->pszFieldName,nNameLen)
+        if( EQUALN(pszFieldPath, papoFields[iField]->pszFieldName, nNameLen)
             && papoFields[iField]->pszFieldName[nNameLen] == '\0' )
         {
             break;
         }
 
-        int nInc = papoFields[iField]->GetInstBytes( pabyData+nByteOffset,
-                                              nDataSize - nByteOffset );
+        const int nInc = papoFields[iField]->GetInstBytes(
+            pabyData + nByteOffset, nDataSize - nByteOffset);
 
-        if (nInc < 0 || nByteOffset > INT_MAX - nInc)
+        if( nInc < 0 || nByteOffset > INT_MAX - nInc )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
-            return FALSE;
+            return false;
         }
 
         nByteOffset += nInc;
     }
 
     if( iField == nFields || nByteOffset >= nDataSize )
-        return FALSE;
-
-/* -------------------------------------------------------------------- */
-/*      Extract this field value, and return.                           */
-/* -------------------------------------------------------------------- */
-    return( papoFields[iField]->
-            ExtractInstValue( pszRemainder, nArrayIndex,
-                              pabyData + nByteOffset,
-                              nDataOffset + nByteOffset,
-                              nDataSize - nByteOffset,
-                              chReqType, pReqReturn,
-                              pnRemainingDataSize) );
+        return false;
+
+    // Extract this field value, and return.
+    return papoFields[iField]->
+        ExtractInstValue(pszRemainder, nArrayIndex,
+                         pabyData + nByteOffset,
+                         nDataOffset + nByteOffset,
+                         nDataSize - nByteOffset,
+                         chReqType, pReqReturn,
+                         pnRemainingDataSize);
 }
 
-
 /************************************************************************/
 /*                           DumpInstValue()                            */
 /************************************************************************/
 
-void HFAType::DumpInstValue( FILE * fpOut,
+void HFAType::DumpInstValue( FILE *fpOut,
                              GByte *pabyData, GUInt32 nDataOffset,
-                             int nDataSize, const char * pszPrefix )
+                             int nDataSize, const char *pszPrefix )
 
 {
-    for ( int iField = 0; iField < nFields && nDataSize > 0; iField++ )
+    for( int iField = 0; iField < nFields && nDataSize > 0; iField++ )
     {
-        HFAField	*poField = papoFields[iField];
+        HFAField *poField = papoFields[iField];
 
-        poField->DumpInstValue( fpOut, pabyData, nDataOffset,
-                                nDataSize, pszPrefix );
+        poField->DumpInstValue(fpOut, pabyData, nDataOffset,
+                               nDataSize, pszPrefix);
 
-        const int nInstBytes = poField->GetInstBytes( pabyData, nDataSize );
-        if (nInstBytes < 0 || nDataOffset > UINT_MAX - nInstBytes)
+        const int nInstBytes = poField->GetInstBytes(pabyData, nDataSize);
+        if( nInstBytes < 0 || nDataOffset > UINT_MAX - nInstBytes )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
             return;
@@ -496,17 +474,17 @@ int HFAType::GetInstBytes( GByte *pabyData, int nDataSize )
 
 {
     if( nBytes >= 0 )
-        return( nBytes );
+        return nBytes;
 
-    int	nTotal = 0;
+    int nTotal = 0;
 
     for( int iField = 0; iField < nFields && nTotal < nDataSize; iField++ )
     {
-        HFAField	*poField = papoFields[iField];
+        HFAField *poField = papoFields[iField];
 
-        const int nInstBytes = poField->GetInstBytes( pabyData,
-                                                      nDataSize - nTotal );
-        if (nInstBytes < 0 || nTotal > INT_MAX - nInstBytes)
+        const int nInstBytes =
+            poField->GetInstBytes(pabyData, nDataSize - nTotal);
+        if( nInstBytes < 0 || nTotal > INT_MAX - nInstBytes )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Invalid return value");
             return -1;
@@ -516,5 +494,5 @@ int HFAType::GetInstBytes( GByte *pabyData, int nDataSize )
         nTotal += nInstBytes;
     }
 
-    return( nTotal );
+    return nTotal;
 }
diff --git a/frmts/idrisi/GNUmakefile b/frmts/idrisi/GNUmakefile
index 3258dec..7e9dcfa 100644
--- a/frmts/idrisi/GNUmakefile
+++ b/frmts/idrisi/GNUmakefile
@@ -2,7 +2,7 @@ GDAL_ROOT	=	../..
 
 include $(GDAL_ROOT)/GDALmake.opt
 
-OBJ	=	IdrisiDataset.o 
+OBJ	=	IdrisiDataset.o
 
 
 
diff --git a/frmts/idrisi/IdrisiDataset.cpp b/frmts/idrisi/IdrisiDataset.cpp
index 998feaa..469319f 100644
--- a/frmts/idrisi/IdrisiDataset.cpp
+++ b/frmts/idrisi/IdrisiDataset.cpp
@@ -1,5 +1,4 @@
 /*****************************************************************************
-* $Id: IdrisiDataset.cpp 36496 2016-11-25 13:09:32Z rouault $
 *
 * Project:  Idrisi Raster Image File Driver
 * Purpose:  Read/write Idrisi Raster Image Format RST
@@ -43,7 +42,9 @@
 #include "ogr_spatialref.h"
 #include "idrisi.h"
 
-CPL_CVSID( "$Id: IdrisiDataset.cpp 36496 2016-11-25 13:09:32Z rouault $" );
+#include <cmath>
+
+CPL_CVSID( "$Id: IdrisiDataset.cpp 36981 2016-12-20 19:46:41Z rouault $" );
 
 #ifdef WIN32
 #  define PATHDELIM       '\\'
@@ -198,162 +199,162 @@ static const ReferenceTab aoUSStateTable[] = {
 //---- The origin table for USA State Plane Systems
 struct OriginTab83 {
     double longitude;
-	double latitude;
-	const char *spcs;
+    double latitude;
+    const char *spcs;
 };
 
 static const int ORIGIN_COUNT = 148;
 
 //---- USA State plane coordinate system in IDRISI
 static const OriginTab83 SPCS83Origin[] = {
-	{85.83,   30.50,    "SPC83AL1"},
-	{87.50,   30.00,    "SPC83AL2"},
-	{176.00,  51.00,    "SPC83AK0"},
-	{142.00,  54.00,    "SPC83AK2"},
-	{146.00,  54.00,    "SPC83AK3"},
-	{150.00,  54.00,    "SPC83AK4"},
-	{154.00,  54.00,    "SPC83AK5"},
-	{158.00,  54.00,    "SPC83AK6"},
-	{162.00,  54.00,    "SPC83AK7"},
-	{166.00,  54.00,    "SPC83AK8"},
-	{170.00,  54.00,    "SPC83AK9"},
-	{110.17,  31.00,    "SPC83AZ1"},
-	{111.92,  31.00,    "SPC83AZ2"},
-	{113.75,  31.00,    "SPC83AZ3"},
-	{92.00,   34.33,    "SPC83AR1"},
-	{92.00,   32.67,    "SPC83AR2"},
-	{122.00,  39.33,    "SPC83CA1"},
-	{122.00,  37.67,    "SPC83CA2"},
-	{120.50,  36.50,    "SPC83CA3"},
-	{119.00,  35.33,    "SPC83CA4"},
-	{118.00,  33.50,    "SPC83CA5"},
-	{116.25,  32.17,    "SPC83CA6"},
-	{105.50,  39.33,    "SPC83CO1"},
-	{105.50,  37.83,    "SPC83CO2"},
-	{105.50,  36.67,    "SPC83CO3"},
-	{72.75,   40.83,    "SPC83CT1"},
-	{75.42,   38.00,    "SPC83DE1"},
-	{81.00,   24.33,    "SPC83FL1"},
-	{82.00,   24.33,    "SPC83FL2"},
-	{84.50,   29.00,    "SPC83FL3"},
-	{82.17,   30.00,    "SPC83GA1"},
-	{84.17,   30.00,    "SPC83GA2"},
-	{155.50,  18.83,    "SPC83HI1"},
-	{156.67,  20.33,    "SPC83HI2"},
-	{158.00,  21.17,    "SPC83HI3"},
-	{159.50,  21.83,    "SPC83HI4"},
-	{160.17,  21.67,    "SPC83HI5"},
-	{112.17,  41.67,    "SPC83ID1"},
-	{114.00,  41.67,    "SPC83ID2"},
-	{115.75,  41.67,    "SPC83ID3"},
-	{88.33,   36.67,    "SPC83IL1"},
-	{90.17,   36.67,    "SPC83IL1"},
-	{85.67,   37.50,    "SPC83IN1"},
-	{87.08,   37.50,    "SPC83IN2"},
-	{93.50,   41.50,    "SPC83IA1"},
-	{93.50,   40.00,    "SPC83IA1"},
-	{98.00,   38.33,    "SPC83KS1"},
-	{98.50,   36.67,    "SPC83KS2"},
-	{84.25,   37.50,    "SPC83KY1"},
-	{85.75,   36.33,    "SPC83KY2"},
-	{92.50,   30.50,    "SPC83LA1"},
-	{91.33,   28.50,    "SPC83LA2"},
-	{91.33,   25.50,    "SPC83LA3"},
-	{92.50,   30.67,    "SPC27LA1"},//NAD27 system
-	{91.33,   28.67,    "SPC27LA2"},
-	{91.33,   25.67,    "SPC27LA3"},//
-	{68.50,   43.67,    "SPC83ME1"},
-	{68.50,   43.83,    "SPC27ME1"},//NAD27
-	{70.17,   42.83,    "SPC83ME2"},
-	{77.00,   37.67,    "SPC83MD1"},//
-	{77.00,   37.83,    "SPC27MD1"},//NAD27
+        {85.83,   30.50,    "SPC83AL1"},
+        {87.50,   30.00,    "SPC83AL2"},
+        {176.00,  51.00,    "SPC83AK0"},
+        {142.00,  54.00,    "SPC83AK2"},
+        {146.00,  54.00,    "SPC83AK3"},
+        {150.00,  54.00,    "SPC83AK4"},
+        {154.00,  54.00,    "SPC83AK5"},
+        {158.00,  54.00,    "SPC83AK6"},
+        {162.00,  54.00,    "SPC83AK7"},
+        {166.00,  54.00,    "SPC83AK8"},
+        {170.00,  54.00,    "SPC83AK9"},
+        {110.17,  31.00,    "SPC83AZ1"},
+        {111.92,  31.00,    "SPC83AZ2"},
+        {113.75,  31.00,    "SPC83AZ3"},
+        {92.00,   34.33,    "SPC83AR1"},
+        {92.00,   32.67,    "SPC83AR2"},
+        {122.00,  39.33,    "SPC83CA1"},
+        {122.00,  37.67,    "SPC83CA2"},
+        {120.50,  36.50,    "SPC83CA3"},
+        {119.00,  35.33,    "SPC83CA4"},
+        {118.00,  33.50,    "SPC83CA5"},
+        {116.25,  32.17,    "SPC83CA6"},
+        {105.50,  39.33,    "SPC83CO1"},
+        {105.50,  37.83,    "SPC83CO2"},
+        {105.50,  36.67,    "SPC83CO3"},
+        {72.75,   40.83,    "SPC83CT1"},
+        {75.42,   38.00,    "SPC83DE1"},
+        {81.00,   24.33,    "SPC83FL1"},
+        {82.00,   24.33,    "SPC83FL2"},
+        {84.50,   29.00,    "SPC83FL3"},
+        {82.17,   30.00,    "SPC83GA1"},
+        {84.17,   30.00,    "SPC83GA2"},
+        {155.50,  18.83,    "SPC83HI1"},
+        {156.67,  20.33,    "SPC83HI2"},
+        {158.00,  21.17,    "SPC83HI3"},
+        {159.50,  21.83,    "SPC83HI4"},
+        {160.17,  21.67,    "SPC83HI5"},
+        {112.17,  41.67,    "SPC83ID1"},
+        {114.00,  41.67,    "SPC83ID2"},
+        {115.75,  41.67,    "SPC83ID3"},
+        {88.33,   36.67,    "SPC83IL1"},
+        {90.17,   36.67,    "SPC83IL1"},
+        {85.67,   37.50,    "SPC83IN1"},
+        {87.08,   37.50,    "SPC83IN2"},
+        {93.50,   41.50,    "SPC83IA1"},
+        {93.50,   40.00,    "SPC83IA1"},
+        {98.00,   38.33,    "SPC83KS1"},
+        {98.50,   36.67,    "SPC83KS2"},
+        {84.25,   37.50,    "SPC83KY1"},
+        {85.75,   36.33,    "SPC83KY2"},
+        {92.50,   30.50,    "SPC83LA1"},
+        {91.33,   28.50,    "SPC83LA2"},
+        {91.33,   25.50,    "SPC83LA3"},
+        {92.50,   30.67,    "SPC27LA1"},//NAD27 system
+        {91.33,   28.67,    "SPC27LA2"},
+        {91.33,   25.67,    "SPC27LA3"},//
+        {68.50,   43.67,    "SPC83ME1"},
+        {68.50,   43.83,    "SPC27ME1"},//NAD27
+        {70.17,   42.83,    "SPC83ME2"},
+        {77.00,   37.67,    "SPC83MD1"},//
+        {77.00,   37.83,    "SPC27MD1"},//NAD27
         {71.50,   41.00,    "SPC83MA1"},
         {70.50,   41.00,    "SPC83MA2"},
-	{87.00,   44.78,    "SPC83MI1"},
-	{84.37,   43.32,    "SPC83MI2"},
-	{84.37,   41.50,    "SPC83MI3"},
-	{84.33,   43.32,    "SPC27MI2"},//NAD27 L
-	{84.33,   41.50,    "SPC27MI3"},//NAD27 L
-	{83.67,   41.50,    "SPC27MI4"},//NAD27 TM
-	{85.75,   41.50,    "SPC27MI5"},//NAD27 TM
-	{88.75,   41.50,    "SPC27MI6"},//NAD27 TM
-	{93.10,   46.50,    "SPC83MN1"},
-	{94.25,   45.00,    "SPC83MN2"},
-	{94.00,   43.00,    "SPC83MN3"},
-	{88.83,   29.50,    "SPC83MS1"},
-	{90.33,   29.50,    "SPC83MS2"},
-	{88.83,   29.67,    "SPC83MS1"},//NAD27
-	{90.33,   30.50,    "SPC83MS2"},//
-	{90.50,   35.83,    "SPC83MO1"},
-	{92.50,   35.83,    "SPC83MO2"},
-	{94.50,   36.17,    "SPC83MO3"},
-	{109.50,  44.25,    "SPC83MT1"},
-	{109.50,  47.00,    "SPC27MT1"},//NAD27
-	{109.50,  45.83,    "SPC27MT2"},
-	{109.50,  44.00,    "SPC27MT3"},//
-	{100.00,  39.83,    "SPC83NE1"},
-	{115.58,  34.75,    "SPC83NV1"},
-	{116.67,  34.75,    "SPC83NV2"},
-	{118.58,  34.75,    "SPC83NV3"},
-	{71.67,   42.50,    "SPC83NH1"},
-	{74.50,   38.83,    "SPC83NJ1"},
-	{74.67,   38.83,    "SPC27NJ1"},//NAD27
-	{104.33,  31.00,    "SPC83NM1"},
-	{106.25,  31.00,    "SPC83NM2"},
-	{107.83,  31.00,    "SPC83NM3"},
-	{74.50,   38.83,    "SPC83NY1"},
-	{76.58,   40.00,    "SPC83NY2"},
-	{78.58,   40.00,    "SPC83NY3"},
-	{74.00,   40.17,    "SPC83NY4"},
-	{74.33,   40.00,    "SPC27NY1"},//NAD27
-	{74.00,   40.50,    "SPC27NY4"},//
-	{79.00,   33.75,    "SPC83NC1"},
-	{100.50,  47.00,    "SPC83ND1"},
-	{100.50,  45.67,    "SPC83ND2"},
-	{82.50,   39.67,    "SPC83OH1"},
-	{82.50,   38.00,    "SPC83OH2"},
-	{98.00,   35.00,    "SPC83OK1"},
-	{98.00,   33.33,    "SPC83OK2"},
-	{120.50,  43.67,    "SPC83OR1"},
-	{120.50,  41.67,    "SPC83OR2"},
-	{77.75,   40.17,    "SPC83PA1"},
-	{77.75,   39.33,    "SPC83PA2"},
-	{71.50,   41.08,    "SPC83RI1"},
-	{81.00,   31.83,    "SPC83SC1"},
-	{81.00,   33.00,    "SPC27SC1"},//NAD27
-	{81.00,   31.83,    "SPC27SC2"},//NAD27
-	{100.00,  43.83,    "SPC83SD1"},
-	{100.33,  42.33,    "SPC83SD2"},
-	{86.00,   34.33,    "SPC83TN1"},
-	{86.00,   34.67,    "SPC27TN1"},//NAD27
-	{101.50,  34.00,    "SPC83TX1"},//
-	{98.50,   31.67,    "SPC83TX2"},
-	{100.33,  29.67,    "SPC83TX3"},
-	{99.00,   27.83,    "SPC83TX4"},
-	{98.50,   25.67,    "SPC83TX5"},
-	{97.50,   31.67,    "SPC27TX2"},//NAD27
-	{111.50,  40.33,    "SPC83UT1"},
-	{111.50,  38.33,    "SPC83UT2"},
-	{111.50,  36.67,    "SPC83UT3"},
-	{72.50,   42.50,    "SPC83VT1"},
-	{78.50,   37.67,    "SPC83VA1"},
-	{78.50,   36.33,    "SPC83VA2"},
-	{120.83,  47.00,    "SPC83WA1"},
-	{120.50,  45.33,    "SPC83WA2"},
-	{79.50,   38.50,    "SPC83WV1"},
-	{81.00,   37.00,    "SPC83WV2"},
-	{90.00,   45.17,    "SPC83WI1"},
-	{90.00,   43.83,    "SPC83WI2"},
-	{90.00,   42.00,    "SPC83WI3"},
-	{105.17,  40.50,    "SPC83WY1"},
-	{107.33,  40.50,    "SPC83WY2"},
-	{108.75,  40.50,    "SPC83WY3"},
-	{110.08,  40.50,    "SPC83WY4"},
-	{105.17,  40.67,    "SPC27WY1"},//NAD27
-	{105.33,  40.67,    "SPC27WY2"},
-	{108.75,  40.67,    "SPC27WY3"},
-	{110.08,  40.67,    "SPC27WY4"},//
-	{66.43,   17.83,    "SPC83PR1"}
+        {87.00,   44.78,    "SPC83MI1"},
+        {84.37,   43.32,    "SPC83MI2"},
+        {84.37,   41.50,    "SPC83MI3"},
+        {84.33,   43.32,    "SPC27MI2"},//NAD27 L
+        {84.33,   41.50,    "SPC27MI3"},//NAD27 L
+        {83.67,   41.50,    "SPC27MI4"},//NAD27 TM
+        {85.75,   41.50,    "SPC27MI5"},//NAD27 TM
+        {88.75,   41.50,    "SPC27MI6"},//NAD27 TM
+        {93.10,   46.50,    "SPC83MN1"},
+        {94.25,   45.00,    "SPC83MN2"},
+        {94.00,   43.00,    "SPC83MN3"},
+        {88.83,   29.50,    "SPC83MS1"},
+        {90.33,   29.50,    "SPC83MS2"},
+        {88.83,   29.67,    "SPC83MS1"},//NAD27
+        {90.33,   30.50,    "SPC83MS2"},//
+        {90.50,   35.83,    "SPC83MO1"},
+        {92.50,   35.83,    "SPC83MO2"},
+        {94.50,   36.17,    "SPC83MO3"},
+        {109.50,  44.25,    "SPC83MT1"},
+        {109.50,  47.00,    "SPC27MT1"},//NAD27
+        {109.50,  45.83,    "SPC27MT2"},
+        {109.50,  44.00,    "SPC27MT3"},//
+        {100.00,  39.83,    "SPC83NE1"},
+        {115.58,  34.75,    "SPC83NV1"},
+        {116.67,  34.75,    "SPC83NV2"},
+        {118.58,  34.75,    "SPC83NV3"},
+        {71.67,   42.50,    "SPC83NH1"},
+        {74.50,   38.83,    "SPC83NJ1"},
+        {74.67,   38.83,    "SPC27NJ1"},//NAD27
+        {104.33,  31.00,    "SPC83NM1"},
+        {106.25,  31.00,    "SPC83NM2"},
+        {107.83,  31.00,    "SPC83NM3"},
+        {74.50,   38.83,    "SPC83NY1"},
+        {76.58,   40.00,    "SPC83NY2"},
+        {78.58,   40.00,    "SPC83NY3"},
+        {74.00,   40.17,    "SPC83NY4"},
+        {74.33,   40.00,    "SPC27NY1"},//NAD27
+        {74.00,   40.50,    "SPC27NY4"},//
+        {79.00,   33.75,    "SPC83NC1"},
+        {100.50,  47.00,    "SPC83ND1"},
+        {100.50,  45.67,    "SPC83ND2"},
+        {82.50,   39.67,    "SPC83OH1"},
+        {82.50,   38.00,    "SPC83OH2"},
+        {98.00,   35.00,    "SPC83OK1"},
+        {98.00,   33.33,    "SPC83OK2"},
+        {120.50,  43.67,    "SPC83OR1"},
+        {120.50,  41.67,    "SPC83OR2"},
+        {77.75,   40.17,    "SPC83PA1"},
+        {77.75,   39.33,    "SPC83PA2"},
+        {71.50,   41.08,    "SPC83RI1"},
+        {81.00,   31.83,    "SPC83SC1"},
+        {81.00,   33.00,    "SPC27SC1"},//NAD27
+        {81.00,   31.83,    "SPC27SC2"},//NAD27
+        {100.00,  43.83,    "SPC83SD1"},
+        {100.33,  42.33,    "SPC83SD2"},
+        {86.00,   34.33,    "SPC83TN1"},
+        {86.00,   34.67,    "SPC27TN1"},//NAD27
+        {101.50,  34.00,    "SPC83TX1"},//
+        {98.50,   31.67,    "SPC83TX2"},
+        {100.33,  29.67,    "SPC83TX3"},
+        {99.00,   27.83,    "SPC83TX4"},
+        {98.50,   25.67,    "SPC83TX5"},
+        {97.50,   31.67,    "SPC27TX2"},//NAD27
+        {111.50,  40.33,    "SPC83UT1"},
+        {111.50,  38.33,    "SPC83UT2"},
+        {111.50,  36.67,    "SPC83UT3"},
+        {72.50,   42.50,    "SPC83VT1"},
+        {78.50,   37.67,    "SPC83VA1"},
+        {78.50,   36.33,    "SPC83VA2"},
+        {120.83,  47.00,    "SPC83WA1"},
+        {120.50,  45.33,    "SPC83WA2"},
+        {79.50,   38.50,    "SPC83WV1"},
+        {81.00,   37.00,    "SPC83WV2"},
+        {90.00,   45.17,    "SPC83WI1"},
+        {90.00,   43.83,    "SPC83WI2"},
+        {90.00,   42.00,    "SPC83WI3"},
+        {105.17,  40.50,    "SPC83WY1"},
+        {107.33,  40.50,    "SPC83WY2"},
+        {108.75,  40.50,    "SPC83WY3"},
+        {110.08,  40.50,    "SPC83WY4"},
+        {105.17,  40.67,    "SPC27WY1"},//NAD27
+        {105.33,  40.67,    "SPC27WY2"},
+        {108.75,  40.67,    "SPC27WY3"},
+        {110.08,  40.67,    "SPC27WY4"},//
+        {66.43,   17.83,    "SPC83PR1"}
 };
 
 //Get IDRISI State Plane name by origin
@@ -423,7 +424,6 @@ int GetToMeterIndex( const char *pszToMeter );
 int  SaveAsCRLF(char **papszStrList, const char *pszFname);
 
 //----- Classes pre-definition:
-class IdrisiDataset;
 class IdrisiRasterBand;
 
 //  ----------------------------------------------------------------------------
@@ -455,7 +455,7 @@ protected:
 
 public:
     IdrisiDataset();
-    ~IdrisiDataset();
+    virtual ~IdrisiDataset();
 
     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
     static GDALDataset *Create( const char *pszFilename,
@@ -470,11 +470,11 @@ public:
         char **papszOptions,
         GDALProgressFunc pfnProgress,
         void * pProgressData );
-    virtual char **GetFileList(void);
-    virtual CPLErr GetGeoTransform( double *padfTransform );
-    virtual CPLErr SetGeoTransform( double *padfTransform );
-    virtual const char *GetProjectionRef( void );
-    virtual CPLErr SetProjection( const char *pszProjString );
+    virtual char **GetFileList(void) override;
+    virtual CPLErr GetGeoTransform( double *padfTransform ) override;
+    virtual CPLErr SetGeoTransform( double *padfTransform ) override;
+    virtual const char *GetProjectionRef( void ) override;
+    virtual CPLErr SetProjection( const char *pszProjString ) override;
 };
 
 //  ----------------------------------------------------------------------------
@@ -495,27 +495,27 @@ public:
     IdrisiRasterBand( IdrisiDataset *poDS,
         int nBand,
         GDALDataType eDataType );
-    ~IdrisiRasterBand();
-
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum( int *pbSuccess = NULL );
-    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
-    virtual CPLErr IWriteBlock( int nBlockXOff, int nBlockYOff, void *pImage );
-    virtual GDALColorTable *GetColorTable();
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual char **GetCategoryNames();
-    virtual const char *GetUnitType();
-
-    virtual CPLErr SetCategoryNames( char **papszCategoryNames );
-    virtual CPLErr SetNoDataValue( double dfNoDataValue );
-    virtual CPLErr SetColorTable( GDALColorTable *poColorTable );
-    virtual CPLErr SetUnitType( const char *pszUnitType );
+    virtual ~IdrisiRasterBand();
+
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum( int *pbSuccess = NULL ) override;
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
+    virtual CPLErr IWriteBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual char **GetCategoryNames() override;
+    virtual const char *GetUnitType() override;
+
+    virtual CPLErr SetCategoryNames( char **papszCategoryNames ) override;
+    virtual CPLErr SetNoDataValue( double dfNoDataValue ) override;
+    virtual CPLErr SetColorTable( GDALColorTable *poColorTable ) override;
+    virtual CPLErr SetUnitType( const char *pszUnitType ) override;
     virtual CPLErr SetStatistics( double dfMin, double dfMax,
-                                  double dfMean, double dfStdDev );
+                                  double dfMean, double dfStdDev ) override;
     CPLErr SetMinMax( double dfMin, double dfMax );
-    virtual GDALRasterAttributeTable *GetDefaultRAT();
-    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
+    virtual GDALRasterAttributeTable *GetDefaultRAT() override;
+    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * ) override;
 
     float  fMaximum;
     float  fMinimum;
@@ -537,9 +537,9 @@ IdrisiDataset::IdrisiDataset() :
     papszRDC(NULL),
     pszProjection(NULL),
     papszCategories(NULL),
-    pszUnitType(NULL)
+    pszUnitType(NULL),
+    poColorTable(new GDALColorTable())
 {
-    poColorTable = new GDALColorTable();
 
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -676,6 +676,11 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
 
     poDS->nRasterXSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcCOLUMNS ) );
     poDS->nRasterYSize = atoi_nz( CSLFetchNameValue( poDS->papszRDC, rdcROWS ) );
+    if( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) )
+    {
+        delete poDS;
+        return NULL;
+    }
 
     // --------------------------------------------------------------------
     //      Create band information
@@ -898,7 +903,7 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
 
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -906,10 +911,10 @@ GDALDataset *IdrisiDataset::Open( GDALOpenInfo *poOpenInfo )
 /************************************************************************/
 
 GDALDataset *IdrisiDataset::Create( const char *pszFilename,
-                                   int nXSize,
-                                   int nYSize,
-                                   int nBands,
-                                   GDALDataType eType,
+                                    int nXSize,
+                                    int nYSize,
+                                    int nBands,
+                                    GDALDataType eType,
                                     char ** /* papszOptions */ )
 {
     // --------------------------------------------------------------------
@@ -918,18 +923,18 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
 
     if( nBands != 1 && nBands != 3)
     {
-		CPLError( CE_Failure, CPLE_AppDefined,
+      CPLError( CE_Failure, CPLE_AppDefined,
                 "Attempt to create IDRISI dataset with an illegal number of bands(%d)."
                 " Try again by selecting a specific band if possible. \n", nBands);
-		return NULL;
+                return NULL;
     }
 
-	if( nBands == 3 && eType != GDT_Byte )
+    if( nBands == 3 && eType != GDT_Byte )
     {
-		CPLError( CE_Failure, CPLE_AppDefined,
-                "Attempt to create IDRISI dataset with an unsupported combination "
-                "of the number of bands(%d) and data type(%s). \n",
-                nBands, GDALGetDataTypeName( eType ) );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to create IDRISI dataset with an unsupported combination "
+                  "of the number of bands(%d) and data type(%s). \n",
+                  nBands, GDALGetDataTypeName( eType ) );
         return NULL;
     }
 
@@ -937,7 +942,7 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
     //  Create the header file with minimum information
     // ----------------------------------------------------------------
 
-    const char *pszLDataType;
+    const char *pszLDataType = NULL;
 
     switch( eType )
     {
@@ -953,35 +958,35 @@ GDALDataset *IdrisiDataset::Create( const char *pszFilename,
     case GDT_Float32:
         pszLDataType = rstREAL;
         break;
-	//--- process compatible data types
-	case (GDT_UInt16):
-		pszLDataType = rstINTEGER;
-		CPLError( CE_Warning, CPLE_AppDefined,
-			      "This process requires a conversion from %s to signed 16-bit %s, "
-				  "which may cause data loss.\n",
-				  GDALGetDataTypeName( eType ), rstINTEGER);
-		break;
-	case GDT_UInt32:
-		pszLDataType = rstINTEGER;
-		CPLError( CE_Warning, CPLE_AppDefined,
-			      "This process requires a conversion from %s to signed 16-bit %s, "
-				  "which may cause data loss.\n",
-				  GDALGetDataTypeName( eType ), rstINTEGER);
-		break;
-	case GDT_Int32:
-		pszLDataType = rstINTEGER;
-		CPLError( CE_Warning, CPLE_AppDefined,
-			      "This process requires a conversion from %s to signed 16-bit %s, "
-				  "which may cause data loss.\n",
-				  GDALGetDataTypeName( eType ), rstINTEGER);
-		break;
-	case GDT_Float64:
-		pszLDataType = rstREAL;
-		CPLError( CE_Warning, CPLE_AppDefined,
-			      "This process requires a conversion from %s to float 32-bit %s, "
-				  "which may cause data loss.\n",
-				  GDALGetDataTypeName( eType ), rstREAL);
-		break;
+        //--- process compatible data types
+        case (GDT_UInt16):
+                pszLDataType = rstINTEGER;
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "This process requires a conversion from %s to signed 16-bit %s, "
+                          "which may cause data loss.\n",
+                          GDALGetDataTypeName( eType ), rstINTEGER);
+                break;
+        case GDT_UInt32:
+                pszLDataType = rstINTEGER;
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "This process requires a conversion from %s to signed 16-bit %s, "
+                          "which may cause data loss.\n",
+                          GDALGetDataTypeName( eType ), rstINTEGER);
+                break;
+        case GDT_Int32:
+                pszLDataType = rstINTEGER;
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "This process requires a conversion from %s to signed 16-bit %s, "
+                          "which may cause data loss.\n",
+                          GDALGetDataTypeName( eType ), rstINTEGER);
+                break;
+        case GDT_Float64:
+                pszLDataType = rstREAL;
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "This process requires a conversion from %s to float 32-bit %s, "
+                          "which may cause data loss.\n",
+                          GDALGetDataTypeName( eType ), rstREAL);
+                break;
     default:
         CPLError( CE_Failure, CPLE_AppDefined,
             "Attempt to create IDRISI dataset with an illegal "
@@ -1065,17 +1070,16 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
             " Try again by selecting a specific band if possible.\n",
                             poSrcDS->GetRasterCount() );
             return NULL;
-
     }
     if ( ( poSrcDS->GetRasterCount() == 3 ) &&
          ( ( poSrcDS->GetRasterBand( 1 )->GetRasterDataType() != GDT_Byte ) ||
          ( poSrcDS->GetRasterBand( 2 )->GetRasterDataType() != GDT_Byte ) ||
          ( poSrcDS->GetRasterBand( 3 )->GetRasterDataType() != GDT_Byte ) ) )
     {
-		CPLError( CE_Failure, CPLE_AppDefined,
-                "Attempt to create IDRISI dataset with an unsupported "
-                "data type when there are three bands. Only BYTE allowed.\n"
-			    "Try again by selecting a specific band to convert if possible.\n");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to create IDRISI dataset with an unsupported "
+                  "data type when there are three bands. Only BYTE allowed.\n"
+                  "Try again by selecting a specific band to convert if possible.\n");
         return NULL;
     }
 
@@ -1111,7 +1115,7 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
                 eType != GDT_Float64 )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-					"Attempt to create IDRISI dataset with an illegal data type(%s).\n",
+                          "Attempt to create IDRISI dataset with an illegal data type(%s).\n",
                     GDALGetDataTypeName( eType ) );
                 return NULL;
             }
@@ -1191,7 +1195,6 @@ GDALDataset *IdrisiDataset::CreateCopy( const char *pszFilename,
     //      Copy information to the raster band(s)
     // --------------------------------------------------------------------
 
-
     for( int i = 1; i <= poDS->nBands; i++ )
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( i );
@@ -1321,7 +1324,7 @@ CPLErr  IdrisiDataset::GetGeoTransform( double * padfTransform )
     if( GDALPamDataset::GetGeoTransform( padfTransform ) != CE_None )
     {
         memcpy( padfTransform, adfGeoTransform, sizeof( double ) * 6 );
-		/*
+                /*
         if( adfGeoTransform[0] == 0.0
         &&  adfGeoTransform[1] == 1.0
         &&  adfGeoTransform[2] == 0.0
@@ -1329,7 +1332,7 @@ CPLErr  IdrisiDataset::GetGeoTransform( double * padfTransform )
         &&  adfGeoTransform[4] == 0.0
         &&  adfGeoTransform[5] == 1.0 )
             return CE_Failure;
-		*/
+                */
     }
 
     return CE_None;
@@ -1438,32 +1441,22 @@ CPLErr IdrisiDataset::SetProjection( const char *pszProjString )
 
 IdrisiRasterBand::IdrisiRasterBand( IdrisiDataset *poDSIn,
                                     int nBandIn,
-                                    GDALDataType eDataTypeIn )
+                                    GDALDataType eDataTypeIn ) :
+    poDefaultRAT(NULL),
+    nRecordSize(poDSIn->GetRasterXSize() * poDSIn->nBands *
+                GDALGetDataTypeSizeBytes(eDataTypeIn)),
+    pabyScanLine(static_cast<GByte *>(VSI_MALLOC2_VERBOSE(
+        poDSIn->GetRasterXSize() * GDALGetDataTypeSizeBytes(eDataTypeIn),
+        poDSIn->nBands))),
+    fMaximum(0.0),
+    fMinimum(0.0),
+    bFirstVal(true)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->eDataType = eDataTypeIn;
-    this->poDefaultRAT = NULL;
-    this->fMinimum = 0.0;
-    this->fMaximum = 0.0;
-    this->bFirstVal = true;
-
-    // --------------------------------------------------------------------
-    //      Set Dimension
-    // --------------------------------------------------------------------
-
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eDataType = eDataTypeIn;
     nBlockYSize = 1;
     nBlockXSize = poDS->GetRasterXSize();
-
-    // --------------------------------------------------------------------
-    //      Get ready for reading and writing
-    // --------------------------------------------------------------------
-
-    nRecordSize  = poDS->GetRasterXSize() * GDALGetDataTypeSize( eDataType ) / 8;
-
-    pabyScanLine = (GByte*) VSI_MALLOC2_VERBOSE( nRecordSize, poDSIn->nBands );
-
-    nRecordSize *= poDSIn->nBands;
 }
 
 /************************************************************************/
@@ -1594,7 +1587,8 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
             {
                 if( bFirstVal )
                 {
-                    fMinimum = fMaximum = fVal;
+                    fMinimum = fVal;
+                    fMaximum = fVal;
                     bFirstVal = false;
                 }
                 else
@@ -1614,7 +1608,8 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
             {
                 if( bFirstVal )
                 {
-                    fMinimum = fMaximum = fVal;
+                    fMinimum = fVal;
+                    fMaximum = fVal;
                     bFirstVal = false;
                 }
                 else
@@ -1634,7 +1629,8 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
             {
                 if( bFirstVal )
                 {
-                    fMinimum = fMaximum = fVal;
+                    fMinimum = fVal;
+                    fMaximum = fVal;
                     bFirstVal = false;
                 }
                 else
@@ -1654,7 +1650,8 @@ CPLErr IdrisiRasterBand::IWriteBlock( int nBlockXOff,
             {
                 if( bFirstVal )
                 {
-                    fMinimum = fMaximum = fVal;
+                    fMinimum = fVal;
+                    fMaximum = fVal;
                     bFirstVal = false;
                 }
                 else
@@ -2061,7 +2058,7 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
     {
         for( int i = 0; i < poRAT->GetColumnCount(); i++ )
         {
-            if STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Value")
+            if( STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Value") )
             {
                 iValue = i;
                 break;
@@ -2087,17 +2084,17 @@ CPLErr IdrisiRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
         {
             for( int i = 0; i < poRAT->GetColumnCount(); i++ )
             {
-                if STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Class_Name")
+                if( STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Class_Name") )
                 {
                     iName = i;
                     break;
                 }
-                else if STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Categor")
+                else if( STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Categor") )
                 {
                     iName = i;
                     break;
                 }
-                else if STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Name")
+                else if ( STARTS_WITH_CI(poRAT->GetNameOfCol( i ), "Name") )
                 {
                     iName = i;
                     break;
@@ -2287,7 +2284,7 @@ GDALRasterAttributeTable *IdrisiRasterBand::GetDefaultRAT()
 
     for( int iEntry = 0; iEntry < nEntryCount; iEntry++ )
     {
-        if EQUAL( poGDS->papszCategories[iEntry], "" )
+        if( EQUAL( poGDS->papszCategories[iEntry], "" ) )
         {
             continue; // Eliminate the empty ones
         }
@@ -2490,7 +2487,7 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     char **papszRef = CSLLoad( pszFName );
     CSLSetNameValueSeparator( papszRef, ":" );
 
-    char *pszGeorefName;
+    char *pszGeorefName = NULL;
 
     const char* pszREF_SYSTEM = CSLFetchNameValue( papszRef, refREF_SYSTEM );
     if( pszREF_SYSTEM != NULL && EQUAL( pszREF_SYSTEM, "" ) == FALSE )
@@ -2635,11 +2632,11 @@ CPLErr IdrisiGeoReference2Wkt( const char* pszFilename,
     {
         oSRS.SetMercator( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
     }
-    else if EQUAL( pszProjName, "Transverse Mercator" )
+    else if( EQUAL( pszProjName, "Transverse Mercator" ) )
     {
         oSRS.SetTM( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
     }
-    else if EQUAL( pszProjName, "Gauss-Kruger" )
+    else if( EQUAL( pszProjName, "Gauss-Kruger" ) )
     {
         oSRS.SetTM( dfCenterLat, dfCenterLong, dfScale, dfFalseEasting, dfFalseNorthing );
     }
@@ -2762,7 +2759,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     //  Plane with default "Meters"
     // -----------------------------------------------------
 
-    if EQUAL( pszProjString, "" )
+    if( EQUAL( pszProjString, "" ) )
             {
                 *pszRefSystem = CPLStrdup( rstPLANE );
                 *pszRefUnit   = CPLStrdup( rstMETER );
@@ -2794,7 +2791,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
         char *pszAuthName = CPLStrdup( oSRS.GetAuthorityName( "GEOGCS" ) );
         char *pszDatum    = CPLStrdup( oSRS.GetAttrValue( "DATUM" ) );
         int nGCSCode = -1;
-        if EQUAL( pszAuthName, "EPSG" )
+        if( EQUAL( pszAuthName, "EPSG" ) )
                 {
                     nGCSCode = atoi( oSRS.GetAuthorityCode( "GEOGCS" ) );
                 }
@@ -2861,9 +2858,9 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
             const char* pszPCSCode = CSVGetField( CSVFilename( "stateplane.csv" ),
                                                  "EPSG_PCS_CODE", pszID, CC_Integer, "ID" );
             osPCSCode = (pszPCSCode) ? pszPCSCode : "";
-            if( osPCSCode.size() )
+            if( !osPCSCode.empty() )
             {
-                int nZone      = osPCSCode[osPCSCode.size() - 1] - '0';
+                int nZone      = osPCSCode.back() - '0';
                 int nSPCode    = atoi_nz( osPCSCode );
 
                 if( nZone == 0 )
@@ -2903,7 +2900,8 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
             //strcpy(pszNAD, "27");
             bIsOldNAD = true;
 
-        if ( (oSRS.FindProjParm("central_meridian",NULL) != -1) && (oSRS.FindProjParm("central_meridian",NULL) != -1) )
+        if ( (oSRS.FindProjParm("central_meridian",NULL) != -1) &&
+             (oSRS.FindProjParm("latitude_of_origin",NULL) != -1) )
         {
             dfLon = oSRS.GetProjParm("central_meridian");
             dfLat = oSRS.GetProjParm("latitude_of_origin");
@@ -2924,7 +2922,6 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
             *pszRefUnit = GetUnitDefault( oSRS.GetAttrValue( "UNIT" ), CPLSPrintf( "%f", oSRS.GetLinearUnits() ) );
             return CE_None;
         }
-
     }
 
 #endif // GDAL_RST_PLUGIN
@@ -2937,23 +2934,23 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
         //  Check for supported projections
         // ---------------------------------------------------------
 
-        if EQUAL( pszProjName, SRS_PT_MERCATOR_1SP )
+        if( EQUAL( pszProjName, SRS_PT_MERCATOR_1SP ) )
                 {
                     pszProjectionOut =  "Mercator" ;
                 }
-        if EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR )
+        else if( EQUAL( pszProjName, SRS_PT_TRANSVERSE_MERCATOR ) )
                 {
                     pszProjectionOut =  "Transverse Mercator" ;
                 }
-        else if EQUAL( pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP )
+        else if( EQUAL( pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP ) )
                      {
                          pszProjectionOut =  "Lambert Conformal Conic" ;
                      }
-        else if EQUAL( pszProjName, SRS_PT_EQUIRECTANGULAR )
+        else if( EQUAL( pszProjName, SRS_PT_EQUIRECTANGULAR ) )
                      {
                          pszProjectionOut =  "Plate Carr" "\xE9" "e" ; /* 'eacute' in ISO-8859-1 */
                      }
-        else if EQUAL( pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA )
+        else if( EQUAL( pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA ) )
                      {
                          double dfCenterLat = oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL );
                          if( dfCenterLat == 0.0 )
@@ -2965,26 +2962,26 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
                          else
                              pszProjectionOut =  "Lambert South Oblique Azimuthal Equal Area" ;
                      }
-        else if EQUAL( pszProjName, SRS_PT_POLAR_STEREOGRAPHIC )
+        else if( EQUAL( pszProjName, SRS_PT_POLAR_STEREOGRAPHIC ) )
                      {
                          if( oSRS.GetProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0, NULL ) > 0 )
                              pszProjectionOut =  "North Polar Stereographic" ;
                          else
                              pszProjectionOut =  "South Polar Stereographic" ;
                      }
-        else if EQUAL( pszProjName, SRS_PT_STEREOGRAPHIC )
+        else if( EQUAL( pszProjName, SRS_PT_STEREOGRAPHIC ) )
                      {
                          pszProjectionOut =  "Transverse Stereographic" ;
                      }
-        else if EQUAL( pszProjName, SRS_PT_OBLIQUE_STEREOGRAPHIC )
+        else if( EQUAL( pszProjName, SRS_PT_OBLIQUE_STEREOGRAPHIC ) )
                      {
                          pszProjectionOut =  "Oblique Stereographic" ;
                      }
-        else if EQUAL( pszProjName, SRS_PT_SINUSOIDAL )
+        else if( EQUAL( pszProjName, SRS_PT_SINUSOIDAL ) )
                      {
                          pszProjectionOut =  "Sinusoidal" ;
                      }
-        else if EQUAL( pszProjName, SRS_PT_ALBERS_CONIC_EQUAL_AREA )
+        else if( EQUAL( pszProjName, SRS_PT_ALBERS_CONIC_EQUAL_AREA ) )
                      {
                          pszProjectionOut =  "Alber's Equal Area Conic" ;
                      }
@@ -3030,7 +3027,7 @@ CPLErr IdrisiDataset::Wkt2GeoReference( const char *pszProjString,
     double dfStdP1              = 0.0;
     double dfStdP2              = 0.0;
     char *pszAngularUnit        = CPLStrdup( oSRS.GetAttrValue( "GEOGCS|UNIT" ) );
-    char *pszLinearUnit;
+    char *pszLinearUnit = NULL;
 
     if( oSRS.IsProjected() )
     {
@@ -3116,7 +3113,7 @@ int GetStateCode( const char *pszState )
 {
     for( unsigned int i = 0; i < US_STATE_COUNT; i++ )
     {
-        if EQUAL( pszState, aoUSStateTable[i].pszName )
+        if( EQUAL( pszState, aoUSStateTable[i].pszName ) )
         {
             return aoUSStateTable[i].nCode;
         }
@@ -3140,7 +3137,6 @@ const char *GetStateName( int nCode )
     return NULL;
 }
 
-
 /************************************************************************/
 /*                            GetSpcs()                                 */
 /************************************************************************/
@@ -3183,7 +3179,7 @@ int GetUnitIndex( const char *pszUnitName )
 {
     for( int i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
     {
-        if EQUAL( pszUnitName, aoLinearUnitsConv[i].pszName )
+        if( EQUAL( pszUnitName, aoLinearUnitsConv[i].pszName ) )
         {
             return i;
         }
@@ -3203,7 +3199,7 @@ int GetToMeterIndex( const char *pszToMeter )
     {
         for( int i = 0; i < (int) LINEAR_UNITS_COUNT; i++ )
         {
-            if ( ABS( aoLinearUnitsConv[i].dfConv - dfToMeter ) < 0.00001 )
+            if ( std::abs( aoLinearUnitsConv[i].dfConv - dfToMeter ) < 0.00001 )
             {
                 return i;
             }
diff --git a/frmts/idrisi/rdc.txt b/frmts/idrisi/rdc.txt
index 1bee3d2..787af40 100644
--- a/frmts/idrisi/rdc.txt
+++ b/frmts/idrisi/rdc.txt
@@ -16,11 +16,11 @@ file title: A descriptive name of the file. It is this text that appears with th
 
 data type: The type of numbers stored in the file. Allowable entries are byte, integer, real, RGB8 and RGB24. (See the description for Image files.)
 
-file type: The format in which the Image file is stored. Allowable entries are ASCII, Binary and Packed Binary (See Image files.) 
+file type: The format in which the Image file is stored. Allowable entries are ASCII, Binary and Packed Binary (See Image files.)
 
 columns: The number of columns in the image. This is extremely important as it tells IDRISI modules how to construct the rectangular image from the stored values. (See Image files.)
 
-rows: The number of rows in the image. 
+rows: The number of rows in the image.
 
 
 Information about the georeferencing system of the file:
@@ -72,7 +72,7 @@ lineage: Description of the history by which the values were recorded/derived.
 completeness: The degree to which the values describe the subject matter indicated.
 consistency: The logical consistency of the file.
 
-Note that the lineage, consistency and completeness fields are intended to meet the recommendations of the U.S. National Committee for Digital Cartographic Data Standards (NCDCDS). Along with the pos'n error and value error fields, they provide a means of adhering to the proposed standards for reporting digital cartographic data quality. For further information about the NCDCDS standard, refer to the January 1988 issue of The American Cartographer, 15(1). 
+Note that the lineage, consistency and completeness fields are intended to meet the recommendations of the U.S. National Committee for Digital Cartographic Data Standards (NCDCDS). Along with the pos'n error and value error fields, they provide a means of adhering to the proposed standards for reporting digital cartographic data quality. For further information about the NCDCDS standard, refer to the January 1988 issue of The American Cartographer, 15(1).
 
 Creation
 
@@ -80,7 +80,7 @@ Documentation files may be created using the module METADATA. They are created a
 
 Structure
 
-Image Documentation files are stored in ASCII format. The first 14 characters of each line describe the contents of the line, while the remaining characters contain the actual information. 
+Image Documentation files are stored in ASCII format. The first 14 characters of each line describe the contents of the line, while the remaining characters contain the actual information.
 
 Example
 
@@ -118,7 +118,7 @@ code 3		: Gray-Brown Podzolic Soils
 lineage		: Soil polygons derived from 1:5000 scale color air photography
 lineage		: and ground truth, with the final compilation being adjusted to
 lineage		: the map base by hand.
-comment	: Value error determined by statistical accuracy assessment 
+comment	: Value error determined by statistical accuracy assessment
 comment	: based on a stratified random sample of 37 points.
 
 Note
diff --git a/frmts/idrisi/rst.txt b/frmts/idrisi/rst.txt
index fc1b406..3978ff5 100644
--- a/frmts/idrisi/rst.txt
+++ b/frmts/idrisi/rst.txt
@@ -2,7 +2,7 @@ Image File (.rst) -- File Structure
 
 Use
 
-Image files are the data files most commonly used in IDRISI. They store the raster data layers used in analyses. 
+Image files are the data files most commonly used in IDRISI. They store the raster data layers used in analyses.
 
 File Contents
 
@@ -40,16 +40,16 @@ has an image file that looks like this:
 
 The numbers in an image file may be integer, byte or real. This is termed the data type.
 
-1. Integers are whole numbers within the range  - 32768 to + 32767. 
-2. Byte values are positive integer numbers ranging from 0 to 255. 
-3. Real numbers have a fractional part, or are whole numbers outside the integer range. 
+1. Integers are whole numbers within the range  - 32768 to + 32767.
+2. Byte values are positive integer numbers ranging from 0 to 255.
+3. Real numbers have a fractional part, or are whole numbers outside the integer range.
 
-The real data types can store values within a range of ± 1 x 10 to the power of 38 with a precision of 7 significant figures. IDRISI supports the standard IEEE 4-byte real number format. 
+The real data types can store values within a range of ± 1 x 10 to the power of 38 with a precision of 7 significant figures. IDRISI supports the standard IEEE 4-byte real number format.
 Two other data types are supported by Idrisi32. These are RGB8 and RGB24. Both of these are produced by the COMPOSITE module. An RGB8 file has byte data values, but these values have special meaning. The RGB24 data type indicates a band-interleaved-by-pixel format that is displayed in true color. For more information on both RGB8 and RGB24 files, see COMPOSITE.
 
-Image files may be stored in ASCII, binary or packed binary file types. The module CONVERT may be used to change data or file type. However, most routines in IDRISI expect the binary format only. 
+Image files may be stored in ASCII, binary or packed binary file types. The module CONVERT may be used to change data or file type. However, most routines in IDRISI expect the binary format only.
 
-The packed binary format is a special data compression format for binary integer or byte data. The compression technique used is run-length encoding. The number of occurrences of a value is given, followed by that value, and so on. The run proceeds from left to right and may carry over from the last cell of one row to the first cell of the next row. Primarily, the packed binary format will only save space when there are several cells with identical values next to one another. If there ar [...]
+The packed binary format is a special data compression format for binary integer or byte data. The compression technique used is run-length encoding. The number of occurrences of a value is given, followed by that value, and so on. The run proceeds from left to right and may carry over from the last cell of one row to the first cell of the next row. Primarily, the packed binary format will only save space when there are several cells with identical values next to one another. If there ar [...]
 
 The following image would require 15 bytes if stored as a byte binary file.
 
@@ -63,7 +63,7 @@ Converting the file to packed binary would yield the following file, which would
 10
 2
 9
-1 
+1
 10
 2
 11
diff --git a/frmts/ilwis/ilwiscoordinatesystem.cpp b/frmts/ilwis/ilwiscoordinatesystem.cpp
index c34a9d5..3ea0a41 100644
--- a/frmts/ilwis/ilwiscoordinatesystem.cpp
+++ b/frmts/ilwis/ilwiscoordinatesystem.cpp
@@ -30,12 +30,14 @@
 
 #include <string>
 
-using std::string;
+CPL_CVSID("$Id: ilwiscoordinatesystem.cpp 36923 2016-12-16 23:24:27Z rouault $");
+
+namespace GDAL {
 
 typedef struct
 {
     const char  *pszIlwisDatum;
-		const char  *pszWKTDatum;
+    const char  *pszWKTDatum;
     int   nEPSGCode;
 } IlwisDatums;
 
@@ -43,163 +45,158 @@ typedef struct
 {
     const char  *pszIlwisEllips;
     int   nEPSGCode;
-		double semiMajor;
-		double invFlattening;
+    double semiMajor;
+    double invFlattening;
 } IlwisEllips;
 
-string ReadElement(string section, string entry, string filename);
-bool WriteElement(string sSection, string sEntry, string fn, string sValue);
-bool WriteElement(string sSection, string sEntry, string fn, int nValue);
-bool WriteElement(string sSection, string sEntry, string fn, double dValue);
-
 static const IlwisDatums iwDatums[] =
 {
     { "Adindan", "Adindan", 4201 },
     { "Afgooye", "Afgooye", 4205 },
-		//AGREF --- skipped
+    // AGREF --- skipped
     { "Ain el Abd 1970", "Ain_el_Abd_1970", 4204 },
-		{ "American Samoa 1962", "American_Samoa_1962", 4169 },
-		//Anna 1 Astro 1965 --- skipped
-		{ "Antigua Island Astro 1943", "Antigua_1943", 4601 },
-		{ "Arc 1950", "Arc_1950", 4209 },    //Arc 1950
-		{ "Arc 1960", "Arc_1960", 4210 },    //Arc 1960
-		//Ascension Island 1958
-		//Astro Beacon E 1945
-		//Astro DOS 71/4
-		//Astro Tern Island (FRIG) 1961
-		//Astronomical Station 1952
-		{ "Australian Geodetic 1966", "Australian_Geodetic_Datum_1966", 4202 },
-		{ "Australian Geodetic 1984", "Australian_Geodetic_Datum_1984", 4203 },
-		//Ayabelle Lighthouse
-		//Bellevue (IGN)
-		{ "Bermuda 1957", "Bermuda_1957", 4216 },
-		{ "Bissau", "Bissau", 4165 },
-		{ "Bogota Observatory  (1975)", "Bogota", 4218 },
-		{ "Bukit Rimpah", "Bukit_Rimpah", 4219 },
-		//Camp Area Astro
-		{ "Campo Inchauspe", "Campo_Inchauspe", 4221 },
-		//Canton Astro 1966
-		{ "Cape", "Cape", 4222 },
-		//Cape Canaveral
-		{ "Carthage", "Carthage", 4223 },
-		{ "CH1903", "CH1903", 4149 },
-		//Chatham Island Astro 1971
-		{ "Chua Astro", "Chua", 4224 },
-		{ "Corrego Alegre", "Corrego_Alegre", 4225 },
-		//Croatia
-		//D-PAF (Orbits)
-		{ "Dabola", "Dabola_1981", 4155 },
-		//Deception Island
-		//Djakarta (Batavia)
-		//DOS 1968
-		//Easter Island 1967
-		//Estonia 1937
-		{ "European 1950 (ED 50)", "European_Datum_1950", 4154 },
-		//European 1979 (ED 79
-		//Fort Thomas 1955
-		{ "Gan 1970", "Gandajika_1970", 4233 },
-		//Geodetic Datum 1949
-		//Graciosa Base SW 1948
-		//Guam 1963
-		{ "Gunung Segara", "Gunung_Segara", 4613 },
-		//GUX 1 Astro
-		{ "Herat North", "Herat_North", 4255 },
-		//Hermannskogel
-		//Hjorsey 1955
-		//Hong Kong 1963
-		{ "Hu-Tzu-Shan", "Hu_Tzu_Shan", 4236 },
-		//Indian (Bangladesh)
-		//Indian (India, Nepal)
-		//Indian (Pakistan)
-		{ "Indian 1954", "Indian_1954", 4239 },
-		{ "Indian 1960", "Indian_1960", 4131 },
-		{ "Indian 1975", "Indian_1975", 4240 },
-		{ "Indonesian 1974", "Indonesian_Datum_1974", 4238 },
-		//Ireland 1965
-		//ISTS 061 Astro 1968
-		//ISTS 073 Astro 1969
-		//Johnston Island 1961
-		{ "Kandawala", "Kandawala", 4244 },
-		//Kerguelen Island 1949
-		{ "Kertau 1948", "Kertau", 4245 },
-		//Kusaie Astro 1951
-		//L. C. 5 Astro 1961
-		{ "Leigon", "Leigon", 4250 },
-		{ "Liberia 1964", "Liberia_1964", 4251 },
-		{ "Luzon", "Luzon_1911", 4253 },
-		//M'Poraloko
-		{ "Mahe 1971", "Mahe_1971", 4256 },
-		{ "Massawa", "Massawa", 4262 },
-		{ "Merchich", "Merchich", 4261 },
-		{ "MGI (Hermannskogel)", "Militar_Geographische_Institute",4312 },
-		//Midway Astro 1961
-		{ "Minna", "Minna", 4263 },
-		{ "Montserrat Island Astro 1958", "Montserrat_1958", 4604 },
-		{ "Nahrwan", "Nahrwan_1967", 4270 },
-		{ "Naparima BWI", "Naparima_1955", 4158 },
-		{ "North American 1927 (NAD 27)", "North_American_Datum_1927", 4267 },
-		{ "North American 1983 (NAD 83)", "North_American_Datum_1983", 4269 },
-		//North Sahara 1959
-		{ "NTF (Nouvelle Triangulation de France)", "Nouvelle_Triangulation_Francaise", 4807 },
-		//Observatorio Meteorologico 1939
-		//Old Egyptian 1907
-		{ "Old Hawaiian", "Old_Hawaiian", 4135 },
-		//Oman
-		//Ordnance Survey Great Britain 1936
-		//Pico de las Nieves
-		//Pitcairn Astro 1967
-		//Point 58
-		{ "Pointe Noire 1948", "Pointe_Noire", 4282 },
-		{ "Porto Santo 1936", "Porto_Santo",4615 },
-		//Potsdam (Rauenburg)
-		{ "Potsdam (Rauenburg)", "Deutsches_Hauptdreiecksnetz", 4314 },
-		{ "Provisional South American 1956", "Provisional_South_American_Datum_1956", 4248 },
-		//Provisional South Chilean 1963
-		{ "Puerto Rico", "Puerto_Rico", 4139 },
-		{ "Pulkovo 1942", "Pulkovo_1942", 4178 },
-		//{ "Qatar National", "Qatar_National_Datum_1995", 4614 },
-		{ "Qornoq", "Qornoq", 4287 },
-		{ "Puerto Rico", "Puerto_Rico", 4139 },
-		//Reunion
-		{ "Rome 1940", "Monte_Mario", 4806 },
-		{ "RT90", "Rikets_koordinatsystem_1990", 4124 },
-		{ "Rijks Driehoeksmeting", "Amersfoort", 4289 },
-		{ "S-42 (Pulkovo 1942)", "Pulkovo_1942", 4178 },
-		//{ "S-JTSK", "Jednotne_Trigonometricke_Site_Katastralni", 4156 },
-		//Santo (DOS) 1965
-		//Sao Braz
-		{ "Sapper Hill 1943", "Sapper_Hill_1943", 4292 },
-		{ "Schwarzeck", "Schwarzeck", 4293 },
-		{ "Selvagem Grande 1938", "Selvagem_Grande", 4616 },
-		//vSGS 1985
-		//Sierra Leone 1960
-		{ "South American 1969", "South_American_Datum_1969", 4291 },
-		//South Asia
-		{ "Tananarive Observatory 1925", "Tananarive_1925", 4297 },
-		{ "Timbalai 1948", "Timbalai_1948", 4298 },
-		{ "Tokyo", "Tokyo", 4301 },
-		//Tristan Astro 1968
-		//Viti Levu 1916
-		{ "Voirol 1874", "Voirol_1875", 4304 },
-		//Voirol 1960
-		//Wake Island Astro 1952
-		//Wake-Eniwetok 1960
-		{ "WGS 1972", "WGS_1972", 4322 },
-		{ "WGS 1984", "WGS_1984", 4326 },
-		{ "Yacare", "Yacare", 4309 },
-		{ "Zanderij", "Zanderij", 4311 },
+    { "American Samoa 1962", "American_Samoa_1962", 4169 },
+    //Anna 1 Astro 1965 --- skipped
+    { "Antigua Island Astro 1943", "Antigua_1943", 4601 },
+    { "Arc 1950", "Arc_1950", 4209 },    //Arc 1950
+    { "Arc 1960", "Arc_1960", 4210 },    //Arc 1960
+    //Ascension Island 1958
+    //Astro Beacon E 1945
+    //Astro DOS 71/4
+    //Astro Tern Island (FRIG) 1961
+    //Astronomical Station 1952
+    { "Australian Geodetic 1966", "Australian_Geodetic_Datum_1966", 4202 },
+    { "Australian Geodetic 1984", "Australian_Geodetic_Datum_1984", 4203 },
+    //Ayabelle Lighthouse
+    //Bellevue (IGN)
+    { "Bermuda 1957", "Bermuda_1957", 4216 },
+    { "Bissau", "Bissau", 4165 },
+    { "Bogota Observatory  (1975)", "Bogota", 4218 },
+    { "Bukit Rimpah", "Bukit_Rimpah", 4219 },
+    //Camp Area Astro
+    { "Campo Inchauspe", "Campo_Inchauspe", 4221 },
+    //Canton Astro 1966
+    { "Cape", "Cape", 4222 },
+    //Cape Canaveral
+    { "Carthage", "Carthage", 4223 },
+    { "CH1903", "CH1903", 4149 },
+    //Chatham Island Astro 1971
+    { "Chua Astro", "Chua", 4224 },
+    { "Corrego Alegre", "Corrego_Alegre", 4225 },
+    //Croatia
+    //D-PAF (Orbits)
+    { "Dabola", "Dabola_1981", 4155 },
+    //Deception Island
+    //Djakarta (Batavia)
+    //DOS 1968
+    //Easter Island 1967
+    //Estonia 1937
+    { "European 1950 (ED 50)", "European_Datum_1950", 4154 },
+    //European 1979 (ED 79
+    //Fort Thomas 1955
+    { "Gan 1970", "Gandajika_1970", 4233 },
+    //Geodetic Datum 1949
+    //Graciosa Base SW 1948
+    //Guam 1963
+    { "Gunung Segara", "Gunung_Segara", 4613 },
+    //GUX 1 Astro
+    { "Herat North", "Herat_North", 4255 },
+    //Hermannskogel
+    //Hjorsey 1955
+    //Hong Kong 1963
+    { "Hu-Tzu-Shan", "Hu_Tzu_Shan", 4236 },
+    //Indian (Bangladesh)
+    //Indian (India, Nepal)
+    //Indian (Pakistan)
+    { "Indian 1954", "Indian_1954", 4239 },
+    { "Indian 1960", "Indian_1960", 4131 },
+    { "Indian 1975", "Indian_1975", 4240 },
+    { "Indonesian 1974", "Indonesian_Datum_1974", 4238 },
+    //Ireland 1965
+    //ISTS 061 Astro 1968
+    //ISTS 073 Astro 1969
+    //Johnston Island 1961
+    { "Kandawala", "Kandawala", 4244 },
+    //Kerguelen Island 1949
+    { "Kertau 1948", "Kertau", 4245 },
+    //Kusaie Astro 1951
+    //L. C. 5 Astro 1961
+    { "Leigon", "Leigon", 4250 },
+    { "Liberia 1964", "Liberia_1964", 4251 },
+    { "Luzon", "Luzon_1911", 4253 },
+    //M'Poraloko
+    { "Mahe 1971", "Mahe_1971", 4256 },
+    { "Massawa", "Massawa", 4262 },
+    { "Merchich", "Merchich", 4261 },
+    { "MGI (Hermannskogel)", "Militar_Geographische_Institute",4312 },
+    //Midway Astro 1961
+    { "Minna", "Minna", 4263 },
+    { "Montserrat Island Astro 1958", "Montserrat_1958", 4604 },
+    { "Nahrwan", "Nahrwan_1967", 4270 },
+    { "Naparima BWI", "Naparima_1955", 4158 },
+    { "North American 1927 (NAD 27)", "North_American_Datum_1927", 4267 },
+    { "North American 1983 (NAD 83)", "North_American_Datum_1983", 4269 },
+    //North Sahara 1959
+    { "NTF (Nouvelle Triangulation de France)", "Nouvelle_Triangulation_Francaise", 4807 },
+    //Observatorio Meteorologico 1939
+    //Old Egyptian 1907
+    { "Old Hawaiian", "Old_Hawaiian", 4135 },
+    //Oman
+    //Ordnance Survey Great Britain 1936
+    //Pico de las Nieves
+    //Pitcairn Astro 1967
+    //Point 58
+    { "Pointe Noire 1948", "Pointe_Noire", 4282 },
+    { "Porto Santo 1936", "Porto_Santo",4615 },
+    //Potsdam (Rauenburg)
+    { "Potsdam (Rauenburg)", "Deutsches_Hauptdreiecksnetz", 4314 },
+    { "Provisional South American 1956", "Provisional_South_American_Datum_1956", 4248 },
+    //Provisional South Chilean 1963
+    { "Puerto Rico", "Puerto_Rico", 4139 },
+    { "Pulkovo 1942", "Pulkovo_1942", 4178 },
+    //{ "Qatar National", "Qatar_National_Datum_1995", 4614 },
+    { "Qornoq", "Qornoq", 4287 },
+    { "Puerto Rico", "Puerto_Rico", 4139 },
+    //Reunion
+    { "Rome 1940", "Monte_Mario", 4806 },
+    { "RT90", "Rikets_koordinatsystem_1990", 4124 },
+    { "Rijks Driehoeksmeting", "Amersfoort", 4289 },
+    { "S-42 (Pulkovo 1942)", "Pulkovo_1942", 4178 },
+    //{ "S-JTSK", "Jednotne_Trigonometricke_Site_Katastralni", 4156 },
+    //Santo (DOS) 1965
+    //Sao Braz
+    { "Sapper Hill 1943", "Sapper_Hill_1943", 4292 },
+    { "Schwarzeck", "Schwarzeck", 4293 },
+    { "Selvagem Grande 1938", "Selvagem_Grande", 4616 },
+    //vSGS 1985
+    //Sierra Leone 1960
+    { "South American 1969", "South_American_Datum_1969", 4291 },
+    //South Asia
+    { "Tananarive Observatory 1925", "Tananarive_1925", 4297 },
+    { "Timbalai 1948", "Timbalai_1948", 4298 },
+    { "Tokyo", "Tokyo", 4301 },
+    //Tristan Astro 1968
+    //Viti Levu 1916
+    { "Voirol 1874", "Voirol_1875", 4304 },
+    //Voirol 1960
+    //Wake Island Astro 1952
+    //Wake-Eniwetok 1960
+    { "WGS 1972", "WGS_1972", 4322 },
+    { "WGS 1984", "WGS_1984", 4326 },
+    { "Yacare", "Yacare", 4309 },
+    { "Zanderij", "Zanderij", 4311 },
     { NULL, NULL, 0 }
 };
 
 static const IlwisEllips iwEllips[] =
 {
-    { "Sphere", 7035, 6371007, 0.0  },	//rad 6370997 m (normal sphere)
+    { "Sphere", 7035, 6371007, 0.0  },  //rad 6370997 m (normal sphere)
     { "Airy 1830", 7031, 6377563.396, 299.3249646 },
     { "Modified Airy", 7002, 6377340.189, 299.3249646 },
     { "ATS77", 7204, 6378135.0, 298.257000006 },
     { "Australian National", 7003, 6378160, 298.249997276 },
     { "Bessel 1841", 7042, 6377397.155, 299.1528128},
-		{ "Bessel 1841 (Japan By Law)", 7046 , 6377397.155, 299.152815351 },
+    { "Bessel 1841 (Japan By Law)", 7046 , 6377397.155, 299.152815351 },
     { "Bessel 1841 (Namibia)", 7006, 6377483.865, 299.1528128 },
     { "Clarke 1866", 7008, 6378206.4, 294.9786982 },
     { "Clarke 1880", 7034, 6378249.145, 293.465 },
@@ -209,69 +206,69 @@ static const IlwisEllips iwEllips[] =
     // FIXME: Du Plessis Reconstituted --- skipped
     { "Everest (India 1830)", 7015, 6377276.345, 300.8017 },
     // Everest (India 1956) --- skipped
-		// Everest (Malaysia 1969) --- skipped
+    // Everest (Malaysia 1969) --- skipped
     { "Everest (E. Malaysia and Brunei)", 7016, 6377298.556, 300.8017 },
     { "Everest (Malay. and Singapore 1948)", 7018, 6377304.063, 300.8017 },
-		{ "Everest (Pakistan)", 7044, 6377309.613, 300.8017 },
-		// Everest (Sabah Sarawak) --- skipped
-		// Fischer 1960 --- skipped
-		// Fischer 1960 (Modified) --- skipped
-		// Fischer 1968 --- skipped
-		{ "GRS 80", 7019, 6378137, 298.257222101  },
-		{ "Helmert 1906", 7020, 6378200, 298.3 },
-		// Hough 1960 --- skipped
-		{ "Indonesian 1974", 7021, 6378160, 298.247 },
-		{ "International 1924", 7022, 6378388, 297 },
-		{ "Krassovsky 1940", 7024, 6378245, 298.3 },
-		// New_International 1967
-		// SGS 85
-		// South American 1969
-		// WGS 60
-		// WGS 66
-		{ "WGS 72", 7020, 6378135.0, 298.259998590  },
-		{ "WGS 84", 7030, 6378137, 298.257223563 },
+    { "Everest (Pakistan)", 7044, 6377309.613, 300.8017 },
+    // Everest (Sabah Sarawak) --- skipped
+    // Fischer 1960 --- skipped
+    // Fischer 1960 (Modified) --- skipped
+    // Fischer 1968 --- skipped
+    { "GRS 80", 7019, 6378137, 298.257222101  },
+    { "Helmert 1906", 7020, 6378200, 298.3 },
+    // Hough 1960 --- skipped
+    { "Indonesian 1974", 7021, 6378160, 298.247 },
+    { "International 1924", 7022, 6378388, 297 },
+    { "Krassovsky 1940", 7024, 6378245, 298.3 },
+    // New_International 1967
+    // SGS 85
+    // South American 1969
+    // WGS 60
+    // WGS 66
+    { "WGS 72", 7020, 6378135.0, 298.259998590  },
+    { "WGS 84", 7030, 6378137, 298.257223563 },
     { NULL, 0, 0.0, 0.0 }
 };
 
 #ifndef R2D
-#  define R2D	(180/M_PI)
+#  define R2D (180/M_PI)
 #endif
 #ifndef D2R
-#  define D2R	(M_PI/180)
+#  define D2R (M_PI/180)
 #endif
 
 /* ==================================================================== */
-/*      Some "standard" strings.                                        */
+/*      Some "standard" std::strings.                                        */
 /* ==================================================================== */
 
-#define ILW_False_Easting "False Easting"
-#define ILW_False_Northing "False Northing"
-#define ILW_Central_Meridian "Central Meridian"
-#define ILW_Central_Parallel "Central Parallel"
-#define ILW_Standard_Parallel_1 "Standard Parallel 1"
-#define ILW_Standard_Parallel_2 "Standard Parallel 2"
-#define ILW_Scale_Factor "Scale Factor"
-#define ILW_Latitude_True_Scale "Latitude of True Scale"
-#define ILW_Height_Persp_Center "Height Persp. Center"
-
-static double ReadPrjParms(string section, string entry, string filename)
+static const char ILW_False_Easting[] = "False Easting";
+static const char ILW_False_Northing[] = "False Northing";
+static const char ILW_Central_Meridian[] = "Central Meridian";
+static const char ILW_Central_Parallel[] = "Central Parallel";
+static const char ILW_Standard_Parallel_1[] = "Standard Parallel 1";
+static const char ILW_Standard_Parallel_2[] = "Standard Parallel 2";
+static const char ILW_Scale_Factor[] = "Scale Factor";
+static const char ILW_Latitude_True_Scale[] = "Latitude of True Scale";
+static const char ILW_Height_Persp_Center[] = "Height Persp. Center";
+
+static double ReadPrjParms(const std::string& section, const std::string& entry, const std::string& filename)
 {
-    string str = ReadElement(section, entry, filename);
+    std::string str = ReadElement(section, entry, filename);
     //string str="";
-    if (str.length() != 0)
+    if (!str.empty())
         return CPLAtof(str.c_str());
 
     return 0.0;
 }
 
-static int fetchParms(string csyFileName, double * padfPrjParams)
+static int fetchParms(const std::string& csyFileName, double * padfPrjParams)
 {
     //Fill all projection parameters with zero
     for ( int i = 0; i < 13; i++ )
         padfPrjParams[i] = 0.0;
 
-    string pszProj = ReadElement("CoordSystem", "Projection", csyFileName);
-    string pszEllips = ReadElement("CoordSystem", "Ellipsoid", csyFileName);
+    //std::string pszProj = ReadElement("CoordSystem", "Projection", csyFileName);
+    std::string pszEllips = ReadElement("CoordSystem", "Ellipsoid", csyFileName);
 
     //fetch info about a custom ellipsoid
     if( STARTS_WITH_CI(pszEllips.c_str(), "User Defined") )
@@ -310,7 +307,7 @@ static int fetchParms(string csyFileName, double * padfPrjParams)
  * --- Gauss Colombia
  * --- Gauss-Boaga Italy
 **/
-static int mapTMParms(string sProj, double dfZone, double &dfFalseEasting, double &dfCentralMeridian)
+static int mapTMParms(std::string sProj, double dfZone, double &dfFalseEasting, double &dfCentralMeridian)
 {
     if( STARTS_WITH_CI(sProj.c_str(), "Gauss-Krueger Germany") )
     {
@@ -348,7 +345,7 @@ static int mapTMParms(string sProj, double dfZone, double &dfFalseEasting, doubl
  * Compute the scale factor from Latitude_Of_True_Scale parameter.
  *
 **/
-static void scaleFromLATTS( string sEllips, double phits, double &scale )
+static void scaleFromLATTS( std::string sEllips, double phits, double &scale )
 {
     if( STARTS_WITH_CI(sEllips.c_str(), "Sphere") )
     {
@@ -387,11 +384,11 @@ static void scaleFromLATTS( string sEllips, double phits, double &scale )
  * @param csyFileName Name of .csy file
 **/
 
-CPLErr ILWISDataset::ReadProjection( string csyFileName )
+CPLErr ILWISDataset::ReadProjection( const std::string& csyFileName )
 {
-    string pszEllips;
-    string pszDatum;
-    string pszProj;
+    std::string pszEllips;
+    std::string pszDatum;
+    std::string pszProj;
 
     //translate ILWIS pre-defined coordinate systems
     if( STARTS_WITH_CI(csyFileName.c_str(), "latlon.csy"))
@@ -519,17 +516,17 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
     {
         // should use 1.0 for scale factor in Ilwis definition
         oSRS.SetProjCS("Lambert Conformal Conic");
-        oSRS.SetLCC(	padfPrjParams[7], padfPrjParams[8],
-                        padfPrjParams[5], padfPrjParams[6],
-                        padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetLCC( padfPrjParams[7], padfPrjParams[8],
+                     padfPrjParams[5], padfPrjParams[6],
+                     padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Lambert Cylind EqualArea") )
     {
         // Latitude_Of_True_Scale used for dfStdP1 ?
         oSRS.SetProjCS("Lambert Conformal Conic");
-        oSRS.SetCEA(	padfPrjParams[10],
-                        padfPrjParams[6],
-                        padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetCEA( padfPrjParams[10],
+                     padfPrjParams[6],
+                     padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Mercator") )
     {
@@ -537,28 +534,28 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
         // Latitude_Of_True_Scale
         scaleFromLATTS( pszEllips, padfPrjParams[10], padfPrjParams[9] );
         oSRS.SetProjCS("Mercator");
-        oSRS.SetMercator(	0, padfPrjParams[6],
-                                padfPrjParams[9],
-                                padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetMercator( 0, padfPrjParams[6],
+                          padfPrjParams[9],
+                          padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Miller") )
     {
         // use 0 for CenterLat
         oSRS.SetProjCS("Miller");
-        oSRS.SetMC(	0, padfPrjParams[6],
-                        padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetMC( 0, padfPrjParams[6],
+                    padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Mollweide") )
     {
         oSRS.SetProjCS("Mollweide");
-        oSRS.SetMollweide(	padfPrjParams[6],
-                                padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetMollweide( padfPrjParams[6],
+                           padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Orthographic") )
     {
         oSRS.SetProjCS("Orthographic");
-        oSRS.SetOrthographic (	padfPrjParams[5], padfPrjParams[6],
-                                padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetOrthographic( padfPrjParams[5], padfPrjParams[6],
+                              padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Plate Carree") ||
              STARTS_WITH_CI(pszProj.c_str(), "Plate Rectangle"))
@@ -566,45 +563,45 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
         // set 0.0 for CenterLat for Plate Carree projection
         // skipp Latitude_Of_True_Scale for Plate Rectangle projection definition
         oSRS.SetProjCS(pszProj.c_str());
-        oSRS.SetEquirectangular(	padfPrjParams[5], padfPrjParams[6],
-                                        padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetEquirectangular( padfPrjParams[5], padfPrjParams[6],
+                                 padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "PolyConic") )
     {
         // skipp scale factor
         oSRS.SetProjCS("PolyConic");
-        oSRS.SetPolyconic(	padfPrjParams[5], padfPrjParams[6],
-                                padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetPolyconic( padfPrjParams[5], padfPrjParams[6],
+                           padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Robinson") )
     {
         oSRS.SetProjCS("Robinson");
-        oSRS.SetRobinson(	padfPrjParams[6],
-                                padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetRobinson( padfPrjParams[6],
+                          padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Sinusoidal") )
     {
         oSRS.SetProjCS("Sinusoidal");
-        oSRS.SetSinusoidal(	padfPrjParams[6],
-                                padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetSinusoidal( padfPrjParams[6],
+                            padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Stereographic") )
     {
         oSRS.SetProjCS("Stereographic");
-        oSRS.SetStereographic(	padfPrjParams[5], padfPrjParams[6],
-                                padfPrjParams[9],
+        oSRS.SetStereographic( padfPrjParams[5], padfPrjParams[6],
+                               padfPrjParams[9],
                                 padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "Transverse Mercator") )
     {
         oSRS.SetProjCS("Transverse Mercator");
-        oSRS.SetStereographic(	padfPrjParams[5], padfPrjParams[6],
-                                padfPrjParams[9],
-                                padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetStereographic( padfPrjParams[5], padfPrjParams[6],
+                               padfPrjParams[9],
+                               padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "UTM") )
     {
-        string pszNH = ReadElement("Projection", "Northern Hemisphere", csyFileName);
+        std::string pszNH = ReadElement("Projection", "Northern Hemisphere", csyFileName);
         oSRS.SetProjCS("UTM");
         if( STARTS_WITH_CI(pszNH.c_str(), "Yes") )
             oSRS.SetUTM( (int) padfPrjParams[11], 1);
@@ -613,8 +610,8 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "VanderGrinten") )
     {
-        oSRS.SetVDG(	padfPrjParams[6],
-                        padfPrjParams[3], padfPrjParams[4] );
+        oSRS.SetVDG( padfPrjParams[6],
+                     padfPrjParams[3], padfPrjParams[4] );
     }
     else if( STARTS_WITH_CI(pszProj.c_str(), "GeoStationary Satellite") )
     {
@@ -655,13 +652,12 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
             piwDatum++;
         } // End of searching for matching datum.
 
-
 /* -------------------------------------------------------------------- */
 /*      If no matching for datum definition, fetch info about an        */
 /*      ellipsoid.  semi major axis is always returned in meters        */
 /* -------------------------------------------------------------------- */
         const IlwisEllips *piwEllips =  iwEllips;
-        if (pszEllips.length() == 0)
+        if (pszEllips.empty())
             pszEllips="Sphere";
         if ( !piwDatum->pszIlwisDatum )
         {
@@ -694,7 +690,7 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
 
 /* -------------------------------------------------------------------- */
 /*      If no matching for ellipsoid definition, fetch info about an    */
-/*			user defined ellipsoid. If cannot find, default to WGS 84       */
+/*      user defined ellipsoid. If cannot find, default to WGS 84       */
 /* -------------------------------------------------------------------- */
         if ( !piwEllips->pszIlwisEllips )
         {
@@ -713,7 +709,6 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
                 oSRS.SetWellKnownGeogCS( "WGS84" );
             }
         }
-
     } // end of if ( !IsLocal() )
 
 /* -------------------------------------------------------------------- */
@@ -730,7 +725,7 @@ CPLErr ILWISDataset::ReadProjection( string csyFileName )
     return CE_None;
 }
 
-static void WriteFalseEastNorth(string csFileName, OGRSpatialReference oSRS)
+static void WriteFalseEastNorth(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteElement("Projection", ILW_False_Easting, csFileName,
                  oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0));
@@ -738,15 +733,15 @@ static void WriteFalseEastNorth(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
 }
 
-static void WriteProjectionName(string csFileName, string stProjection)
+static void WriteProjectionName(const std::string& csFileName, const std::string& stProjection)
 {
     WriteElement("CoordSystem", "Type", csFileName, "Projection");
     WriteElement("CoordSystem", "Projection", csFileName, stProjection);
 }
 
-static void WriteUTM(string csFileName, OGRSpatialReference oSRS)
+static void WriteUTM(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
-    int	bNorth;
+    int bNorth;
 
     int nZone = oSRS.GetUTMZone( &bNorth );
     WriteElement("CoordSystem", "Type", csFileName, "Projection");
@@ -758,7 +753,7 @@ static void WriteUTM(string csFileName, OGRSpatialReference oSRS)
     WriteElement("Projection", "Zone", csFileName, nZone);
 }
 
-static void WriteAlbersConicEqualArea(string csFileName, OGRSpatialReference oSRS)
+static void WriteAlbersConicEqualArea(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Albers EqualArea Conic");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -772,7 +767,7 @@ static void WriteAlbersConicEqualArea(string csFileName, OGRSpatialReference oSR
                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
 }
 
-static void WriteAzimuthalEquidistant(string csFileName, OGRSpatialReference oSRS)
+static void WriteAzimuthalEquidistant(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Azimuthal Equidistant");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -783,7 +778,7 @@ static void WriteAzimuthalEquidistant(string csFileName, OGRSpatialReference oSR
     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
 }
 
-static void WriteCylindricalEqualArea(string csFileName, OGRSpatialReference oSRS)
+static void WriteCylindricalEqualArea(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Central Cylindrical");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -791,7 +786,7 @@ static void WriteCylindricalEqualArea(string csFileName, OGRSpatialReference oSR
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-static void WriteCassiniSoldner(string csFileName, OGRSpatialReference oSRS)
+static void WriteCassiniSoldner(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Cassini");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -802,7 +797,7 @@ static void WriteCassiniSoldner(string csFileName, OGRSpatialReference oSRS)
     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
 }
 
-static void WriteStereographic(string csFileName, OGRSpatialReference oSRS)
+static void WriteStereographic(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Stereographic");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -814,7 +809,7 @@ static void WriteStereographic(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0));
 }
 
-static void WriteEquidistantConic(string csFileName, OGRSpatialReference oSRS)
+static void WriteEquidistantConic(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Equidistant Conic");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -828,7 +823,7 @@ static void WriteEquidistantConic(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
 }
 
-static void WriteTransverseMercator(string csFileName, OGRSpatialReference oSRS)
+static void WriteTransverseMercator(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Transverse Mercator");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -840,7 +835,7 @@ static void WriteTransverseMercator(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 0.0));
 }
 
-static void WriteGnomonic(string csFileName, OGRSpatialReference oSRS)
+static void WriteGnomonic(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Gnomonic");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -850,7 +845,7 @@ static void WriteGnomonic(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
 }
 
-static void WriteLambertConformalConic(string csFileName, OGRSpatialReference oSRS)
+static void WriteLambertConformalConic(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Lambert Conformal Conic");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -861,7 +856,7 @@ static void WriteLambertConformalConic(string csFileName, OGRSpatialReference oS
     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
 }
 
-static void WriteLambertConformalConic2SP(string csFileName, OGRSpatialReference oSRS)
+static void WriteLambertConformalConic2SP(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Lambert Conformal Conic");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -876,7 +871,7 @@ static void WriteLambertConformalConic2SP(string csFileName, OGRSpatialReference
                  oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0));
 }
 
-static void WriteLambertAzimuthalEqualArea(string csFileName, OGRSpatialReference oSRS)
+static void WriteLambertAzimuthalEqualArea(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Lambert Azimuthal EqualArea");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -886,7 +881,7 @@ static void WriteLambertAzimuthalEqualArea(string csFileName, OGRSpatialReferenc
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
 }
 
-static void WriteMercator_1SP(string csFileName, OGRSpatialReference oSRS)
+static void WriteMercator_1SP(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Mercator");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -896,7 +891,7 @@ static void WriteMercator_1SP(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
 }
 
-static void WriteMillerCylindrical(string csFileName, OGRSpatialReference oSRS)
+static void WriteMillerCylindrical(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Miller");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -904,7 +899,7 @@ static void WriteMillerCylindrical(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-static void WriteMolleweide(string csFileName, OGRSpatialReference oSRS)
+static void WriteMolleweide(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Mollweide");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -912,7 +907,7 @@ static void WriteMolleweide(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-static void WriteOrthographic(string csFileName, OGRSpatialReference oSRS)
+static void WriteOrthographic(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Orthographic");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -922,7 +917,7 @@ static void WriteOrthographic(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0));
 }
 
-static void WritePlateRectangle(string csFileName, OGRSpatialReference oSRS)
+static void WritePlateRectangle(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Plate Rectangle");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -933,7 +928,7 @@ static void WritePlateRectangle(string csFileName, OGRSpatialReference oSRS)
     WriteElement("Projection", ILW_Latitude_True_Scale, csFileName, "0.0000000000");
 }
 
-static void WritePolyConic(string csFileName, OGRSpatialReference oSRS)
+static void WritePolyConic(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "PolyConic");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -944,7 +939,7 @@ static void WritePolyConic(string csFileName, OGRSpatialReference oSRS)
     WriteElement("Projection", ILW_Scale_Factor, csFileName, "1.0000000000");
 }
 
-static void WriteRobinson(string csFileName, OGRSpatialReference oSRS)
+static void WriteRobinson(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Robinson");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -952,7 +947,7 @@ static void WriteRobinson(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-static void WriteSinusoidal(string csFileName, OGRSpatialReference oSRS)
+static void WriteSinusoidal(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "Sinusoidal");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -960,7 +955,7 @@ static void WriteSinusoidal(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-static void WriteVanderGrinten(string csFileName, OGRSpatialReference oSRS)
+static void WriteVanderGrinten(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "VanderGrinten");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -968,7 +963,7 @@ static void WriteVanderGrinten(string csFileName, OGRSpatialReference oSRS)
                  oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
 }
 
-static void WriteGeoStatSat(string csFileName, OGRSpatialReference oSRS)
+static void WriteGeoStatSat(const std::string& csFileName, const OGRSpatialReference& oSRS)
 {
     WriteProjectionName(csFileName, "GeoStationary Satellite");
     WriteFalseEastNorth(csFileName, oSRS);
@@ -993,11 +988,11 @@ CPLErr ILWISDataset::WriteProjection()
 {
     OGRSpatialReference oSRS;
     OGRSpatialReference *poGeogSRS = NULL;
-    char		*pszP = pszProjection;
+    char                *pszP = pszProjection;
 
-    string csFileName = CPLResetExtension(osFileName, "csy" );
-    string pszBaseName = string(CPLGetBasename( osFileName ));
-    string pszPath = string(CPLGetPath( osFileName ));
+    std::string csFileName = CPLResetExtension(osFileName, "csy" );
+    std::string pszBaseName = std::string(CPLGetBasename( osFileName ));
+    //std::string pszPath = std::string(CPLGetPath( osFileName ));
     bool bProjection = ((pszProjection != NULL) && (strlen(pszProjection)>0));
     bool bHaveSRS;
     if( bProjection && (oSRS.importFromWkt( &pszP ) == OGRERR_NONE) )
@@ -1008,9 +1003,9 @@ CPLErr ILWISDataset::WriteProjection()
         bHaveSRS = false;
 
     const IlwisDatums   *piwDatum = iwDatums;
-    string pszEllips;
-    string pszDatum;
-    string pszProj;
+    //std::string pszEllips;
+    std::string pszDatum;
+    //std::string pszProj;
 
 /* -------------------------------------------------------------------- */
 /*      Collect datum/ellips information.                                      */
@@ -1020,8 +1015,8 @@ CPLErr ILWISDataset::WriteProjection()
         poGeogSRS = oSRS.CloneGeogCS();
     }
 
-    string grFileName = CPLResetExtension(osFileName, "grf" );
-    string csy;
+    std::string grFileName = CPLResetExtension(osFileName, "grf" );
+    std::string csy;
     if( poGeogSRS )
     {
         csy = pszBaseName + ".csy";
@@ -1040,7 +1035,7 @@ CPLErr ILWISDataset::WriteProjection()
             piwDatum++;
         } // End of searching for matching datum.
         WriteElement("CoordSystem", "Width", csFileName, 28);
-        pszEllips = poGeogSRS->GetAttrValue( "GEOGCS|DATUM|SPHEROID" );
+       // pszEllips = poGeogSRS->GetAttrValue( "GEOGCS|DATUM|SPHEROID" );
         double a = poGeogSRS->GetSemiMajor();
         /* b = */ poGeogSRS->GetSemiMinor();
         double f = poGeogSRS->GetInvFlattening();
@@ -1052,7 +1047,7 @@ CPLErr ILWISDataset::WriteProjection()
         csy = "unknown.csy";
 
 /* -------------------------------------------------------------------- */
-/*	Determine to write a geo-referencing file for the dataset to create */
+/*  Determine to write a geo-referencing file for the dataset to create */
 /* -------------------------------------------------------------------- */
     if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
         || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
@@ -1179,3 +1174,5 @@ CPLErr ILWISDataset::WriteProjection()
 
     return CE_None;
 }
+
+} // namespace GDAL
diff --git a/frmts/ilwis/ilwisdataset.cpp b/frmts/ilwis/ilwisdataset.cpp
index 60ae880..76e99cf 100644
--- a/frmts/ilwis/ilwisdataset.cpp
+++ b/frmts/ilwis/ilwisdataset.cpp
@@ -27,77 +27,76 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
 #include "ilwisdataset.h"
 #include <cfloat>
 #include <climits>
 
+#include <algorithm>
 #include <string>
 
 #include "gdal_frmts.h"
 
-using std::string;
+CPL_CVSID("$Id: ilwisdataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
-/* used by ilwsicoordinatesystem.cpp */
-string ReadElement(string section, string entry, string filename);
-bool WriteElement(string sSection, string sEntry, string fn, string sValue);
-bool WriteElement(string sSection, string sEntry, string fn, int nValue);
-bool WriteElement(string sSection, string sEntry, string fn, double dValue);
+namespace GDAL
+{
 
 // IniFile.cpp: implementation of the IniFile class.
 //
 //////////////////////////////////////////////////////////////////////
-bool CompareAsNum::operator() (const string& s1, const string& s2) const
+bool CompareAsNum::operator() (const std::string& s1, const std::string& s2) const
 {
-    long Num1 = atoi(s1.c_str());
-    long Num2 = atoi(s2.c_str());
+    int Num1 = atoi(s1.c_str());
+    int Num2 = atoi(s2.c_str());
     return Num1 < Num2;
 }
 
-static string TrimSpaces(const string& input)
+static std::string TrimSpaces(const std::string& input)
 {
     // find first non space
     if ( input.empty() )
-        return string();
+        return std::string();
 
     const size_t iFirstNonSpace = input.find_first_not_of(' ');
     const size_t iFindLastSpace = input.find_last_not_of(' ');
-    if (iFirstNonSpace == string::npos || iFindLastSpace == string::npos)
-        return string();
+    if (iFirstNonSpace == std::string::npos || iFindLastSpace == std::string::npos)
+        return std::string();
 
     return input.substr(iFirstNonSpace, iFindLastSpace - iFirstNonSpace + 1);
 }
 
-static string GetLine(VSILFILE* fil)
+static std::string GetLine(VSILFILE* fil)
 {
     const char *p = CPLReadLineL( fil );
     if (p == NULL)
-        return string();
+        return std::string();
 
     CPLString osWrk = p;
     osWrk.Trim();
-    return string(osWrk);
+    return std::string(osWrk);
 }
 
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
-IniFile::IniFile(const string& filenam)
+IniFile::IniFile( const std::string& filenameIn ) :
+    filename(filenameIn),
+    bChanged(false)  // Start tracking changes.
 {
-    filename = filenam;
     Load();
-    bChanged = false; // Start tracking changes
 }
 
 IniFile::~IniFile()
 {
-    if (bChanged)
+    if( bChanged )
     {
         Store();
         bChanged = false;
     }
 
-    for (Sections::iterator iter = sections.begin(); iter != sections.end(); ++iter)
+    for( Sections::iterator iter = sections.begin();
+         iter != sections.end();
+         ++iter )
     {
         (*(*iter).second).clear();
         delete (*iter).second;
@@ -106,7 +105,7 @@ IniFile::~IniFile()
     sections.clear();
 }
 
-void IniFile::SetKeyValue(const string& section, const string& key, const string& value)
+void IniFile::SetKeyValue(const std::string& section, const std::string& key, const std::string& value)
 {
     Sections::iterator iterSect = sections.find(section);
     if (iterSect == sections.end())
@@ -125,21 +124,21 @@ void IniFile::SetKeyValue(const string& section, const string& key, const string
     bChanged = true;
 }
 
-string IniFile::GetKeyValue(const string& section, const string& key)
+std::string IniFile::GetKeyValue(const std::string& section, const std::string& key)
 {
-	Sections::iterator iterSect = sections.find(section);
-	if (iterSect != sections.end())
-	{
-		SectionEntries *entries = (*iterSect).second;
-		SectionEntries::iterator iterEntry = (*entries).find(key);
-		if (iterEntry != (*entries).end())
-			return (*iterEntry).second;
-	}
-
-	return string();
+    Sections::iterator iterSect = sections.find(section);
+    if (iterSect != sections.end())
+    {
+        SectionEntries *entries = (*iterSect).second;
+        SectionEntries::iterator iterEntry = (*entries).find(key);
+        if (iterEntry != (*entries).end())
+            return (*iterEntry).second;
+    }
+
+    return std::string();
 }
 
-void IniFile::RemoveKeyValue(const string& section, const string& key)
+void IniFile::RemoveKeyValue(const std::string& section, const std::string& key)
 {
     Sections::iterator iterSect = sections.find(section);
     if (iterSect != sections.end())
@@ -151,7 +150,7 @@ void IniFile::RemoveKeyValue(const string& section, const string& key)
     }
 }
 
-void IniFile::RemoveSection(const string& section)
+void IniFile::RemoveSection(const std::string& section)
 {
     Sections::iterator iterSect = sections.find(section);
     if (iterSect != sections.end())
@@ -170,10 +169,10 @@ void IniFile::Load()
     if (filIni == NULL)
         return;
 
-    string section, key, value;
+    std::string section, key, value;
     enum ParseState { FindSection, FindKey, ReadFindKey, StoreKey, None } state
         = FindSection;
-    string s;
+    std::string s;
     while (!VSIFEofL(filIni) || !s.empty() )
     {
         switch (state)
@@ -186,7 +185,7 @@ void IniFile::Load()
             if (s[0] == '[')
             {
                 size_t iLast = s.find_first_of(']');
-                if (iLast != string::npos)
+                if (iLast != std::string::npos)
                 {
                     section = s.substr(1, iLast - 1);
                     state = ReadFindKey;
@@ -197,10 +196,11 @@ void IniFile::Load()
             break;
           case ReadFindKey:
             s = GetLine(filIni); // fall through (no break)
+            CPL_FALLTHROUGH
           case FindKey:
           {
               size_t iEqu = s.find_first_of('=');
-              if (iEqu != string::npos)
+              if (iEqu != std::string::npos)
               {
                   key = s.substr(0, iEqu);
                   value = s.substr(iEqu + 1);
@@ -221,6 +221,8 @@ void IniFile::Load()
         }
     }
 
+    bChanged = false;
+
     VSIFCloseL(filIni);
 }
 
@@ -237,15 +239,15 @@ void IniFile::Store()
 
         // write the section name
         osLine.Printf( "[%s]\r\n", (*iterSect).first.c_str());
-        VSIFWriteL( osLine.c_str(), 1, strlen(osLine), filIni );
+        VSIFWriteL( osLine.c_str(), 1, osLine.size(), filIni );
         SectionEntries *entries = (*iterSect).second;
         SectionEntries::iterator iterEntry;
         for (iterEntry = (*entries).begin(); iterEntry != (*entries).end(); ++iterEntry)
         {
-            string key = (*iterEntry).first;
+            std::string key = (*iterEntry).first;
             osLine.Printf( "%s=%s\r\n",
                            TrimSpaces(key).c_str(), (*iterEntry).second.c_str());
-            VSIFWriteL( osLine.c_str(), 1, strlen(osLine), filIni );
+            VSIFWriteL( osLine.c_str(), 1, osLine.size(), filIni );
         }
 
         VSIFWriteL( "\r\n", 1, 2, filIni );
@@ -257,31 +259,31 @@ void IniFile::Store()
 // End of the implementation of IniFile class. ///////////////////////
 //////////////////////////////////////////////////////////////////////
 
-static long longConv(double x) {
-    if ((x == rUNDEF) || (x > LONG_MAX) || (x < LONG_MIN))
+static int intConv(double x) {
+    if ((x == rUNDEF) || (x > INT_MAX) || (x < INT_MIN))
         return iUNDEF;
 
-    return (long)floor(x + 0.5);
+    return (int)floor(x + 0.5);
 }
 
-string ReadElement(string section, string entry, string filename)
+std::string ReadElement(const std::string& section, const std::string& entry, const std::string& filename)
 {
-    if (section.length() == 0)
-        return string();
-    if (entry.length() == 0)
-        return string();
-    if (filename.length() == 0)
-        return string();
+    if (section.empty())
+        return std::string();
+    if (entry.empty())
+        return std::string();
+    if (filename.empty())
+        return std::string();
 
     IniFile MyIniFile (filename);
 
-    return MyIniFile.GetKeyValue(section, entry);;
+    return MyIniFile.GetKeyValue(section, entry);
 }
 
-bool WriteElement(string sSection, string sEntry,
-                             string fn, string sValue)
+bool WriteElement(const std::string& sSection, const std::string& sEntry,
+                  const std::string& fn, const std::string& sValue)
 {
-    if (0 == fn.length())
+    if (fn.empty())
         return false;
 
     IniFile MyIniFile (fn);
@@ -290,35 +292,35 @@ bool WriteElement(string sSection, string sEntry,
     return true;
 }
 
-bool WriteElement(string sSection, string sEntry,
-                             string fn, int nValue)
+bool WriteElement(const std::string& sSection, const std::string&sEntry,
+                  const std::string& fn, int nValue)
 {
-    if (0 == fn.length())
+    if (fn.empty())
         return false;
 
     char strdouble[45];
     snprintf(strdouble, sizeof(strdouble), "%d", nValue);
-    string sValue = string(strdouble);
+    std::string sValue = std::string(strdouble);
     return WriteElement(sSection, sEntry, fn, sValue);
 }
 
-bool WriteElement(string sSection, string sEntry,
-                             string fn, double dValue)
+bool WriteElement(const std::string& sSection, const std::string&sEntry,
+                  const std::string& fn, double dValue)
 {
-    if (0 == fn.length())
+    if (fn.empty())
         return false;
 
     char strdouble[45];
     CPLsnprintf(strdouble, sizeof(strdouble), "%.6f", dValue);
-    string sValue = string(strdouble);
+    std::string sValue = std::string(strdouble);
     return WriteElement(sSection, sEntry, fn, sValue);
 }
 
-static CPLErr GetRowCol(string str,int &Row, int &Col)
+static CPLErr GetRowCol(const std::string& str,int &Row, int &Col)
 {
-    string delimStr = " ,;";
+    std::string delimStr = " ,;";
     size_t iPos = str.find_first_of(delimStr);
-    if (iPos != string::npos)
+    if (iPos != std::string::npos)
     {
         Row = atoi(str.substr(0, iPos).c_str());
     }
@@ -329,7 +331,7 @@ static CPLErr GetRowCol(string str,int &Row, int &Col)
         return CE_Failure;
     }
     iPos = str.find_last_of(delimStr);
-    if (iPos != string::npos)
+    if (iPos != std::string::npos)
     {
         Col = atoi(str.substr(iPos+1, str.length()-iPos).c_str());
     }
@@ -371,9 +373,9 @@ static GDALDataType ILWIS2GDALType(ilwisStoreType stStoreType)
 }
 
 //Determine store type of ILWIS raster
-static string GDALType2ILWIS(GDALDataType type)
+static std::string GDALType2ILWIS(GDALDataType type)
 {
-    string sStoreType = "";
+    std::string sStoreType = "";
     switch( type )
     {
       case GDT_Byte:{
@@ -408,9 +410,9 @@ static string GDALType2ILWIS(GDALDataType type)
     return sStoreType;
 }
 
-static CPLErr GetStoreType(string pszFileName, ilwisStoreType &stStoreType)
+static CPLErr GetStoreType(std::string pszFileName, ilwisStoreType &stStoreType)
 {
-    string st = ReadElement("MapStore", "Type", pszFileName.c_str());
+    std::string st = ReadElement("MapStore", "Type", pszFileName.c_str());
 
     if( EQUAL(st.c_str(),"byte"))
     {
@@ -441,12 +443,11 @@ static CPLErr GetStoreType(string pszFileName, ilwisStoreType &stStoreType)
     return CE_None;
 }
 
-
 ILWISDataset::ILWISDataset() :
+    pszProjection(CPLStrdup("")),
     bGeoDirty(FALSE),
     bNewDataset(FALSE)
 {
-    pszProjection = CPLStrdup("");
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -475,11 +476,11 @@ ILWISDataset::~ILWISDataset()
 /*      the transform coefficients from the extent and pixelsize        */
 /************************************************************************/
 
-void ILWISDataset::CollectTransformCoef(string &pszRefName)
+void ILWISDataset::CollectTransformCoef(std::string& pszRefName)
 
 {
     pszRefName = "";
-    string georef;
+    std::string georef;
     if ( EQUAL(pszFileType.c_str(),"Map") )
         georef = ReadElement("Map", "GeoRef", osFileName);
     else
@@ -487,26 +488,26 @@ void ILWISDataset::CollectTransformCoef(string &pszRefName)
 
     //Capture the geotransform, only if the georef is not 'none',
     //otherwise, the default transform should be returned.
-    if( (georef.length() != 0) && !EQUAL(georef.c_str(),"none"))
+    if( !georef.empty() && !EQUAL(georef.c_str(),"none"))
     {
         //Form the geo-referencing name
-        string pszBaseName = string(CPLGetBasename(georef.c_str()) );
-        string pszPath = string(CPLGetPath( osFileName ));
-        pszRefName = string(CPLFormFilename(pszPath.c_str(),
+        std::string pszBaseName = std::string(CPLGetBasename(georef.c_str()) );
+        std::string pszPath = std::string(CPLGetPath( osFileName ));
+        pszRefName = std::string(CPLFormFilename(pszPath.c_str(),
                                             pszBaseName.c_str(),"grf" ));
 
         //Check the geo-reference type,support for the GeoRefCorners only
-        string georeftype = ReadElement("GeoRef", "Type", pszRefName);
+        std::string georeftype = ReadElement("GeoRef", "Type", pszRefName);
         if (EQUAL(georeftype.c_str(),"GeoRefCorners"))
         {
             //Center or top-left corner of the pixel approach?
-            string IsCorner = ReadElement("GeoRefCorners", "CornersOfCorners", pszRefName);
+            std::string IsCorner = ReadElement("GeoRefCorners", "CornersOfCorners", pszRefName);
 
             //Collect the extent of the coordinates
-            string sMinX = ReadElement("GeoRefCorners", "MinX", pszRefName);
-            string sMinY = ReadElement("GeoRefCorners", "MinY", pszRefName);
-            string sMaxX = ReadElement("GeoRefCorners", "MaxX", pszRefName);
-            string sMaxY = ReadElement("GeoRefCorners", "MaxY", pszRefName);
+            std::string sMinX = ReadElement("GeoRefCorners", "MinX", pszRefName);
+            std::string sMinY = ReadElement("GeoRefCorners", "MinY", pszRefName);
+            std::string sMaxX = ReadElement("GeoRefCorners", "MaxX", pszRefName);
+            std::string sMaxY = ReadElement("GeoRefCorners", "MaxY", pszRefName);
 
             //Calculate pixel size in X and Y direction from the extent
             double deltaX = CPLAtof(sMaxX.c_str()) - CPLAtof(sMinX.c_str());
@@ -531,9 +532,7 @@ void ILWISDataset::CollectTransformCoef(string &pszRefName)
             adfGeoTransform[4] = 0.0;
             adfGeoTransform[5] = -PixelSizeY;
         }
-
     }
-
 }
 
 /************************************************************************/
@@ -562,7 +561,7 @@ CPLErr ILWISDataset::WriteGeoReference()
             double dURLong = (adfGeoTransform[0]
                        + nXSize * adfGeoTransform[1] );
 
-            string grFileName = CPLResetExtension(osFileName, "grf" );
+            std::string grFileName = CPLResetExtension(osFileName, "grf" );
             WriteElement("Ilwis", "Type", grFileName, "GeoRef");
             WriteElement("GeoRef", "lines", grFileName, nYSize);
             WriteElement("GeoRef", "columns", grFileName, nXSize);
@@ -575,8 +574,8 @@ CPLErr ILWISDataset::WriteGeoReference()
 
             //Re-write the GeoRef property to raster ODF
             //Form band file name
-            string sBaseName = string(CPLGetBasename(osFileName) );
-            string sPath = string(CPLGetPath(osFileName));
+            std::string sBaseName = std::string(CPLGetBasename(osFileName) );
+            std::string sPath = std::string(CPLGetPath(osFileName));
             if (nBands == 1)
             {
                 WriteElement("Map", "GeoRef", osFileName, sBaseName + ".grf");
@@ -589,7 +588,7 @@ CPLErr ILWISDataset::WriteGeoReference()
                       WriteElement("MapList", "GeoRef", osFileName, sBaseName + ".grf");
                     char szName[100];
                     snprintf(szName, sizeof(szName), "%s_band_%d", sBaseName.c_str(),iBand + 1 );
-                    string pszODFName = string(CPLFormFilename(sPath.c_str(),szName,"mpr"));
+                    std::string pszODFName = std::string(CPLFormFilename(sPath.c_str(),szName,"mpr"));
                     WriteElement("Map", "GeoRef", pszODFName, sBaseName + ".grf");
                 }
             }
@@ -605,7 +604,7 @@ CPLErr ILWISDataset::WriteGeoReference()
 const char *ILWISDataset::GetProjectionRef()
 
 {
-   return ( pszProjection );
+   return pszProjection;
 }
 
 /************************************************************************/
@@ -630,7 +629,7 @@ CPLErr ILWISDataset::GetGeoTransform( double * padfTransform )
 
 {
     memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -650,13 +649,13 @@ CPLErr ILWISDataset::SetGeoTransform( double * padfTransform )
 
 static bool CheckASCII(unsigned char * buf, int size)
 {
-	for (int i = 0; i < size; ++i)
-        {
-            if (!isascii(buf[i]))
-                return false;
-        }
+    for (int i = 0; i < size; ++i)
+    {
+        if (!isascii(buf[i]))
+            return false;
+    }
 
-	return true;
+    return true;
 }
 /************************************************************************/
 /*                       Open()                                         */
@@ -671,29 +670,29 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 1 )
         return NULL;
 
-    string sExt = CPLGetExtension( poOpenInfo->pszFilename );
+    std::string sExt = CPLGetExtension( poOpenInfo->pszFilename );
     if (!EQUAL(sExt.c_str(),"mpr") && !EQUAL(sExt.c_str(),"mpl"))
         return NULL;
 
     if (!CheckASCII(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes))
         return NULL;
 
-    string ilwistype = ReadElement("Ilwis", "Type", poOpenInfo->pszFilename);
-    if( ilwistype.length() == 0)
+    std::string ilwistype = ReadElement("Ilwis", "Type", poOpenInfo->pszFilename);
+    if( ilwistype.empty())
         return NULL;
 
-    string sFileType;	//map or map list
+    std::string sFileType;  // map or map list
     int    iBandCount;
-    string mapsize;
-    const string maptype = ReadElement("BaseMap", "Type", poOpenInfo->pszFilename);
-    const string sBaseName = string(CPLGetBasename(poOpenInfo->pszFilename) );
-    const string sPath = string(CPLGetPath( poOpenInfo->pszFilename));
+    std::string mapsize;
+    const std::string maptype = ReadElement("BaseMap", "Type", poOpenInfo->pszFilename);
+    //const std::string sBaseName = std::string(CPLGetBasename(poOpenInfo->pszFilename) );
+    const std::string sPath = std::string(CPLGetPath( poOpenInfo->pszFilename));
 
     //Verify whether it is a map list or a map
     if( EQUAL(ilwistype.c_str(),"MapList") )
     {
-        sFileType = string("MapList");
-        string sMaps = ReadElement("MapList", "Maps", poOpenInfo->pszFilename);
+        sFileType = std::string("MapList");
+        std::string sMaps = ReadElement("MapList", "Maps", poOpenInfo->pszFilename);
         iBandCount = atoi(sMaps.c_str());
         mapsize = ReadElement("MapList", "Size", poOpenInfo->pszFilename);
         for (int iBand = 0; iBand < iBandCount; ++iBand )
@@ -701,19 +700,19 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
             //Form the band file name.
             char cBandName[45];
             snprintf( cBandName, sizeof(cBandName), "Map%d", iBand);
-            string sBandName = ReadElement("MapList", string(cBandName), poOpenInfo->pszFilename);
-            string pszBandBaseName = string(CPLGetBasename(sBandName.c_str()) );
-            string pszBandPath = string(CPLGetPath( sBandName.c_str()));
-            if ( 0 == pszBandPath.length() )
+            std::string sBandName = ReadElement("MapList", std::string(cBandName), poOpenInfo->pszFilename);
+            std::string pszBandBaseName = std::string(CPLGetBasename(sBandName.c_str()) );
+            std::string pszBandPath = std::string(CPLGetPath( sBandName.c_str()));
+            if ( pszBandPath.empty() )
             {
-                sBandName = string(CPLFormFilename(sPath.c_str(),
+                sBandName = std::string(CPLFormFilename(sPath.c_str(),
                                                    pszBandBaseName.c_str(),"mpr" ));
             }
             // Verify the file extension, it must be an ILWIS raw data file
             // with extension .mp#, otherwise, unsupported
             // This drive only supports a map list which stores a set
             // of ILWIS raster maps,
-            string sMapStoreName = ReadElement("MapStore", "Data", sBandName);
+            std::string sMapStoreName = ReadElement("MapStore", "Data", sBandName);
             sExt = CPLGetExtension( sMapStoreName.c_str() );
             if ( !STARTS_WITH_CI(sExt.c_str(), "mp#"))
             {
@@ -729,14 +728,14 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
         sFileType = "Map";
         iBandCount = 1;
         mapsize = ReadElement("Map", "Size", poOpenInfo->pszFilename);
-        string sMapType = ReadElement("Map", "Type", poOpenInfo->pszFilename);
+        //std::string sMapType = ReadElement("Map", "Type", poOpenInfo->pszFilename);
         ilwisStoreType stStoreType;
         if (
-            GetStoreType(string(poOpenInfo->pszFilename), stStoreType) != CE_None )
+            GetStoreType(std::string(poOpenInfo->pszFilename), stStoreType) != CE_None )
         {
             //CPLError( CE_Failure, CPLE_AppDefined,
-            //			"Unsupported ILWIS data file. \n"
-            //			"can't treat as raster.\n" );
+            //          "Unsupported ILWIS data file. \n"
+            //          "can't treat as raster.\n" );
             return NULL;
         }
     }
@@ -756,7 +755,8 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Capture raster size from ILWIS file (.mpr).                     */
 /* -------------------------------------------------------------------- */
-    int Row = 0, Col = 0;
+    int Row = 0;
+    int Col = 0;
     if ( GetRowCol(mapsize, Row, Col) != CE_None)
     {
         delete poDS;
@@ -784,32 +784,32 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Collect the geotransform coefficients                           */
 /* -------------------------------------------------------------------- */
-    string pszGeoRef;
+    std::string pszGeoRef;
     poDS->CollectTransformCoef(pszGeoRef);
 
 /* -------------------------------------------------------------------- */
 /*      Translation from ILWIS coordinate system definition             */
 /* -------------------------------------------------------------------- */
-    if( (pszGeoRef.length() != 0) && !EQUAL(pszGeoRef.c_str(),"none"))
+    if( !pszGeoRef.empty() && !EQUAL(pszGeoRef.c_str(),"none"))
     {
 
-        //	Fetch coordinate system
-        string csy = ReadElement("GeoRef", "CoordSystem", pszGeoRef);
-        string pszProj;
+        // Fetch coordinate system
+        std::string csy = ReadElement("GeoRef", "CoordSystem", pszGeoRef);
+        std::string pszProj;
 
-        if( (csy.length() != 0) && !EQUAL(csy.c_str(),"unknown.csy"))
+        if( !csy.empty() && !EQUAL(csy.c_str(),"unknown.csy"))
         {
 
             //Form the coordinate system file name
             if( !(STARTS_WITH_CI(csy.c_str(), "latlon.csy")) &&
                 !(STARTS_WITH_CI(csy.c_str(), "LatlonWGS84.csy")))
             {
-                string pszBaseName = string(CPLGetBasename(csy.c_str()) );
-                string pszPath = string(CPLGetPath( poDS->osFileName ));
-                csy = string(CPLFormFilename(pszPath.c_str(),
+                std::string pszBaseName = std::string(CPLGetBasename(csy.c_str()) );
+                std::string pszPath = std::string(CPLGetPath( poDS->osFileName ));
+                csy = std::string(CPLFormFilename(pszPath.c_str(),
                                              pszBaseName.c_str(),"csy" ));
                 pszProj = ReadElement("CoordSystem", "Type", csy);
-                if (pszProj.length() == 0 ) //default to projection
+                if (pszProj.empty() ) //default to projection
                     pszProj = "Projection";
             }
             else
@@ -834,7 +834,7 @@ GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -881,25 +881,25 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
 
 /* -------------------------------------------------------------------- */
 /*      Translate the data type.                                        */
-/*	Determine store type of ILWIS raster                            */
+/*      Determine store type of ILWIS raster                            */
 /* -------------------------------------------------------------------- */
-    string sDomain= "value.dom";
+    std::string sDomain= "value.dom";
     double stepsize = 1;
-    string sStoreType = GDALType2ILWIS(eType);
+    std::string sStoreType = GDALType2ILWIS(eType);
     if( EQUAL(sStoreType.c_str(),""))
         return NULL;
     else if( EQUAL(sStoreType.c_str(),"Real") || EQUAL(sStoreType.c_str(),"float"))
         stepsize = 0;
 
-    const string pszBaseName = string(CPLGetBasename( pszFilename ));
-    const string pszPath = string(CPLGetPath( pszFilename ));
+    const std::string pszBaseName = std::string(CPLGetBasename( pszFilename ));
+    const std::string pszPath = std::string(CPLGetPath( pszFilename ));
 
 /* -------------------------------------------------------------------- */
 /*      Write out object definition file for each band                  */
 /* -------------------------------------------------------------------- */
-    string pszODFName;
-    string pszDataBaseName;
-    string pszFileName;
+    std::string pszODFName;
+    std::string pszDataBaseName;
+    std::string pszFileName;
 
     char strsize[45];
     snprintf(strsize, sizeof(strsize), "%d %d", nYSize, nXSize);
@@ -907,17 +907,17 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
     //Form map/maplist name.
     if ( nBands == 1 )
     {
-        pszODFName = string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr"));
+        pszODFName = std::string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr"));
         pszDataBaseName = pszBaseName;
         pszFileName = CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr");
     }
     else
     {
         pszFileName = CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpl");
-        WriteElement("Ilwis", "Type", string(pszFileName), "MapList");
-        WriteElement("MapList", "GeoRef", string(pszFileName), "none.grf");
-        WriteElement("MapList", "Size", string(pszFileName), string(strsize));
-        WriteElement("MapList", "Maps", string(pszFileName), nBands);
+        WriteElement("Ilwis", "Type", std::string(pszFileName), "MapList");
+        WriteElement("MapList", "GeoRef", std::string(pszFileName), "none.grf");
+        WriteElement("MapList", "Size", std::string(pszFileName), std::string(strsize));
+        WriteElement("MapList", "Maps", std::string(pszFileName), nBands);
     }
 
     for( int iBand = 0; iBand < nBands; iBand++ )
@@ -926,10 +926,10 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
         {
             char szBandName[100];
             snprintf(szBandName, sizeof(szBandName), "%s_band_%d", pszBaseName.c_str(),iBand + 1 );
-            pszODFName = string(szBandName) + ".mpr";
-            pszDataBaseName = string(szBandName);
+            pszODFName = std::string(szBandName) + ".mpr";
+            pszDataBaseName = std::string(szBandName);
             snprintf(szBandName, sizeof(szBandName), "Map%d", iBand);
-            WriteElement("MapList", string(szBandName), string(pszFileName), pszODFName);
+            WriteElement("MapList", std::string(szBandName), std::string(pszFileName), pszODFName);
             pszODFName = CPLFormFilename(pszPath.c_str(),pszDataBaseName.c_str(),"mpr");
         }
 /* -------------------------------------------------------------------- */
@@ -941,7 +941,7 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
         WriteElement("Map", "Type", pszODFName, "MapStore");
 
         WriteElement("BaseMap", "Domain", pszODFName, sDomain);
-        string pszDataName = pszDataBaseName + ".mp#";
+        std::string pszDataName = pszDataBaseName + ".mp#";
         WriteElement("MapStore", "Data", pszODFName, pszDataName);
         WriteElement("MapStore", "Structure", pszODFName, "Line");
         // sStoreType is used by ILWISRasterBand constructor to determine eDataType
@@ -953,11 +953,11 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
         double adfMinMax[2] = {-9999999.9, 9999999.9};
         char strdouble[45];
         CPLsnprintf(strdouble, sizeof(strdouble), "%.3f:%.3f:%3f:offset=0", adfMinMax[0], adfMinMax[1],stepsize);
-        string range(strdouble);
+        std::string range(strdouble);
         WriteElement("BaseMap", "Range", pszODFName, range);
 
         WriteElement("Map", "GeoRef", pszODFName, "none.grf");
-        WriteElement("Map", "Size", pszODFName, string(strsize));
+        WriteElement("Map", "Size", pszODFName, std::string(strsize));
 
 /* -------------------------------------------------------------------- */
 /*      Try to create the data file.                                    */
@@ -982,7 +982,7 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
     poDS->bNewDataset = TRUE;
     poDS->SetDescription(pszFilename);
     poDS->osFileName = pszFileName;
-    poDS->pszIlwFileName = string(pszFileName);
+    poDS->pszIlwFileName = std::string(pszFileName);
     if ( nBands == 1 )
         poDS->pszFileType = "Map";
     else
@@ -998,7 +998,7 @@ GDALDataset *ILWISDataset::Create(const char* pszFilename,
     }
 
     return poDS;
-    //return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    // return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
 }
 
 /************************************************************************/
@@ -1036,14 +1036,14 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     if( poDS == NULL )
         return NULL;
-    const string pszBaseName = string(CPLGetBasename( pszFilename ));
-    const string pszPath = string(CPLGetPath( pszFilename ));
+    const std::string pszBaseName = std::string(CPLGetBasename( pszFilename ));
+    const std::string pszPath = std::string(CPLGetPath( pszFilename ));
 
 /* -------------------------------------------------------------------- */
 /*  Copy and geo-transform and projection information.                  */
 /* -------------------------------------------------------------------- */
     double adfGeoTransform[6];
-    string georef = "none.grf";
+    std::string georef = "none.grf";
 
     // Check whether we should create georeference file.
     // Source dataset must be north up.
@@ -1082,7 +1082,7 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         double dNoDataValue = poBand->GetNoDataValue(&bHasNoDataValue);
 
         //Determine store type of ILWIS raster
-        const string sStoreType = GDALType2ILWIS( eType );
+        const std::string sStoreType = GDALType2ILWIS( eType );
         double stepsize = 1;
         if( EQUAL(sStoreType.c_str(),""))
             return NULL;
@@ -1090,19 +1090,19 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             stepsize = 0;
 
         //Form the image file name, create the object definition file.
-        string pszODFName;
-        string pszDataBaseName;
+        std::string pszODFName;
+        //std::string pszDataBaseName;
         if (nBands == 1)
         {
-            pszODFName = string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr"));
-            pszDataBaseName = pszBaseName;
+            pszODFName = std::string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr"));
+            //pszDataBaseName = pszBaseName;
         }
         else
         {
             char szName[100];
             snprintf(szName, sizeof(szName), "%s_band_%d", pszBaseName.c_str(),iBand + 1 );
-            pszODFName = string(CPLFormFilename(pszPath.c_str(),szName,"mpr"));
-            pszDataBaseName = string(szName);
+            pszODFName = std::string(CPLFormFilename(pszPath.c_str(),szName,"mpr"));
+            //pszDataBaseName = std::string(szName);
         }
 /* -------------------------------------------------------------------- */
 /*      Write data definition file for each band (.mpr)                 */
@@ -1120,7 +1120,7 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             // only write a range if we got a correct one from the source dataset (otherwise ILWIS can't show the map properly)
             char strdouble[45];
             CPLsnprintf(strdouble, sizeof(strdouble), "%.3f:%.3f:%3f:offset=0", adfMinMax[0], adfMinMax[1],stepsize);
-            string range = string(strdouble);
+            std::string range = std::string(strdouble);
             WriteElement("BaseMap", "Range", pszODFName, range);
         }
         WriteElement("Map", "GeoRef", pszODFName, georef);
@@ -1129,7 +1129,7 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*      Loop over image, copy the image data.                           */
 /* -------------------------------------------------------------------- */
         //For file name for raw data, and create binary files.
-        string pszDataFileName = CPLResetExtension(pszODFName.c_str(), "mp#" );
+        //std::string pszDataFileName = CPLResetExtension(pszODFName.c_str(), "mp#" );
 
         fpData = desBand->fpRaw;
         if( fpData == NULL )
@@ -1225,31 +1225,34 @@ ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /*                       ILWISRasterBand()                              */
 /************************************************************************/
 
-ILWISRasterBand::ILWISRasterBand( ILWISDataset *poDSIn, int nBandIn )
-
+ILWISRasterBand::ILWISRasterBand( ILWISDataset *poDSIn, int nBandIn ) :
+    fpRaw(NULL),
+    nSizePerPixel(0)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
-    string sBandName;
-    if ( EQUAL(poDSIn->pszFileType.c_str(),"Map"))
-        sBandName = string(poDSIn->osFileName);
-    else //map list
+    std::string sBandName;
+    if( EQUAL(poDSIn->pszFileType.c_str(), "Map"))
     {
-        //Form the band name
+        sBandName = std::string(poDSIn->osFileName);
+    }
+    else  // Map list.
+    {
+        // Form the band name.
         char cBandName[45];
         snprintf( cBandName, sizeof(cBandName), "Map%d", nBand-1);
-        sBandName = ReadElement("MapList", string(cBandName), string(poDSIn->osFileName));
-        string sInputPath = string(CPLGetPath( poDSIn->osFileName));
-        string sBandPath = string(CPLGetPath( sBandName.c_str()));
-        string sBandBaseName = string(CPLGetBasename( sBandName.c_str()));
-        if ( 0==sBandPath.length() )
-            sBandName = string(CPLFormFilename(sInputPath.c_str(),sBandBaseName.c_str(),"mpr" ));
+        sBandName = ReadElement("MapList", std::string(cBandName), std::string(poDSIn->osFileName));
+        std::string sInputPath = std::string(CPLGetPath( poDSIn->osFileName));
+        std::string sBandPath = std::string(CPLGetPath( sBandName.c_str()));
+        std::string sBandBaseName = std::string(CPLGetBasename( sBandName.c_str()));
+        if ( sBandPath.empty() )
+            sBandName = std::string(CPLFormFilename(sInputPath.c_str(),sBandBaseName.c_str(),"mpr" ));
         else
-          sBandName = string(CPLFormFilename(sBandPath.c_str(),sBandBaseName.c_str(),"mpr" ));
+          sBandName = std::string(CPLFormFilename(sBandPath.c_str(),sBandBaseName.c_str(),"mpr" ));
     }
 
-    if (poDSIn->bNewDataset)
+    if( poDSIn->bNewDataset )
     {
       // Called from Create():
       // eDataType is defaulted to GDT_Byte by GDALRasterBand::GDALRasterBand
@@ -1260,26 +1263,28 @@ ILWISRasterBand::ILWISRasterBand( ILWISDataset *poDSIn, int nBandIn )
         eDataType = ILWIS2GDALType(psInfo.stStoreType);
     }
     else // Called from Open(), thus convert ILWIS type from ODF to eDataType
+    {
         GetILWISInfo(sBandName);
+    }
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
-    switch (psInfo.stStoreType)
+    switch( psInfo.stStoreType )
     {
       case stByte:
-        nSizePerPixel = GDALGetDataTypeSize(GDT_Byte) / 8;
+        nSizePerPixel = GDALGetDataTypeSizeBytes(GDT_Byte);
         break;
       case stInt:
-        nSizePerPixel = GDALGetDataTypeSize(GDT_Int16) / 8;
+        nSizePerPixel = GDALGetDataTypeSizeBytes(GDT_Int16) ;
         break;
       case stLong:
-        nSizePerPixel = GDALGetDataTypeSize(GDT_Int32) / 8;
+        nSizePerPixel = GDALGetDataTypeSizeBytes(GDT_Int32);
         break;
       case stFloat:
-        nSizePerPixel = GDALGetDataTypeSize(GDT_Float32) / 8;
+        nSizePerPixel = GDALGetDataTypeSizeBytes(GDT_Float32);
         break;
       case stReal:
-        nSizePerPixel = GDALGetDataTypeSize(GDT_Float64) / 8;
+        nSizePerPixel = GDALGetDataTypeSizeBytes(GDT_Float64);
         break;
     }
     ILWISOpen(sBandName);
@@ -1299,15 +1304,14 @@ ILWISRasterBand::~ILWISRasterBand()
     }
 }
 
-
 /************************************************************************/
 /*                             ILWISOpen()                             */
 /************************************************************************/
-void ILWISRasterBand::ILWISOpen( string pszFileName )
+void ILWISRasterBand::ILWISOpen( const std::string& pszFileName )
 {
     ILWISDataset* dataset = (ILWISDataset*) poDS;
-    string pszDataFile
-        = string(CPLResetExtension( pszFileName.c_str(), "mp#" ));
+    std::string pszDataFile
+        = std::string(CPLResetExtension( pszFileName.c_str(), "mp#" ));
 
     fpRaw = VSIFOpenL( pszDataFile.c_str(), (dataset->eAccess == GA_Update) ? "rb+" : "rb");
 }
@@ -1317,9 +1321,9 @@ void ILWISRasterBand::ILWISOpen( string pszFileName )
 /************************************************************************/
 // Helper function for GetILWISInfo, to avoid code-duplication
 // Unfortunately with side-effect (changes members psInfo and eDataType)
-void ILWISRasterBand::ReadValueDomainProperties(string pszFileName)
+void ILWISRasterBand::ReadValueDomainProperties(const std::string& pszFileName)
 {
-    string rangeString = ReadElement("BaseMap", "Range", pszFileName.c_str());
+    std::string rangeString = ReadElement("BaseMap", "Range", pszFileName.c_str());
     psInfo.vr = ValueRange(rangeString);
     double rStep = psInfo.vr.get_rStep();
     if ( rStep != 0 )
@@ -1327,7 +1331,7 @@ void ILWISRasterBand::ReadValueDomainProperties(string pszFileName)
         psInfo.bUseValueRange = true; // use ILWIS ValueRange object to convert from "raw" to "value"
         double rMin = psInfo.vr.get_rLo();
         double rMax = psInfo.vr.get_rHi();
-        if (rStep - (long)rStep == 0.0) // Integer values
+        if (rStep >= INT_MIN && rStep <= INT_MAX && rStep - (int)rStep == 0.0) // Integer values
         {
             if ( rMin >= 0 && rMax <= UCHAR_MAX)
               eDataType =  GDT_Byte;
@@ -1363,7 +1367,7 @@ void ILWISRasterBand::ReadValueDomainProperties(string pszFileName)
 /*                       GetILWISInfo()                                 */
 /************************************************************************/
 // Calculates members psInfo and eDataType
-CPLErr ILWISRasterBand::GetILWISInfo(string pszFileName)
+CPLErr ILWISRasterBand::GetILWISInfo(const std::string& pszFileName)
 {
     // Fill the psInfo struct with defaults.
     // Get the store type from the ODF
@@ -1384,9 +1388,9 @@ CPLErr ILWISRasterBand::GetILWISInfo(string pszFileName)
     // We have hardcoded the system domains here, because ILWIS may not be installed, and even if it is,
     // we don't know where (thus it is useless to attempt to read a system-domain-file).
 
-    string domName = ReadElement("BaseMap", "Domain", pszFileName.c_str());
-    string pszBaseName = string(CPLGetBasename( domName.c_str() ));
-    string pszPath = string(CPLGetPath( pszFileName.c_str() ));
+    std::string domName = ReadElement("BaseMap", "Domain", pszFileName.c_str());
+    std::string pszBaseName = std::string(CPLGetBasename( domName.c_str() ));
+    std::string pszPath = std::string(CPLGetPath( pszFileName.c_str() ));
 
     // Check against all "system-domains"
     if ( EQUAL(pszBaseName.c_str(),"value") // is it a system domain with Type=DomainValue?
@@ -1427,9 +1431,9 @@ CPLErr ILWISRasterBand::GetILWISInfo(string pszFileName)
     else
     {
         // No match found. Assume it is a self-created domain. Read its type and decide the GDAL type.
-        string pszDomainFileName = string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"dom" ));
-        string domType = ReadElement("Domain", "Type", pszDomainFileName.c_str());
-        if EQUAL(domType.c_str(),"domainvalue") // is it a self-created domain of type=DomainValue?
+        std::string pszDomainFileName = std::string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"dom" ));
+        std::string domType = ReadElement("Domain", "Type", pszDomainFileName.c_str());
+        if( EQUAL(domType.c_str(),"domainvalue") ) // is it a self-created domain of type=DomainValue?
         {
             ReadValueDomainProperties(pszFileName);
         }
@@ -1481,13 +1485,13 @@ CPLErr ILWISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Failed to open ILWIS data file.");
-        return( CE_Failure );
+        return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
-/*	Handle the case of a strip in a writable file that doesn't          */
-/*	exist yet, but that we want to read.  Just set to zeros and         */
-/*	return.                                                             */
+/*      Handle the case of a strip in a writable file that doesn't      */
+/*      exist yet, but that we want to read.  Just set to zeros and     */
+/*      return.                                                         */
 /* -------------------------------------------------------------------- */
     ILWISDataset* poIDS = (ILWISDataset*) poDS;
 
@@ -1555,7 +1559,7 @@ CPLErr ILWISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
           ((double *) pImage)[iCol] = ((double *) pData)[iCol];
         break;
       default:
-        CPLAssert(0);
+        CPLAssert(false);
     }
 
     // Officially we should also translate "nodata" values, but at this point
@@ -1590,7 +1594,7 @@ void ILWISRasterBand::SetValue(void *pImage, int i, double rV) {
       ((double *) pImage)[i] = rV;
       break;
     default:
-      CPLAssert(0);
+      CPLAssert(false);
     }
 }
 
@@ -1619,7 +1623,7 @@ double ILWISRasterBand::GetValue(void *pImage, int i) {
       rV = ((double *) pImage)[i];
       break;
     default:
-      CPLAssert(0);
+      CPLAssert(false);
     }
     return rV;
 }
@@ -1828,13 +1832,13 @@ static double doubleConv(const char* s)
     if (s == NULL) return rUNDEF;
     char *begin = const_cast<char*>(s);
 
-    // skip leading spaces; strtol will return 0 on a string with only spaces
+    // skip leading spaces; strtol will return 0 on a std::string with only spaces
     // which is not what we want
     while (isspace((unsigned char)*begin)) ++begin;
 
     if (strlen(begin) == 0) return rUNDEF;
     errno = 0;
-    char *endptr;
+    char *endptr = NULL;
     const double r = CPLStrtod(begin, &endptr);
     if ((0 == *endptr) && (errno==0))
         return r;
@@ -1846,17 +1850,23 @@ static double doubleConv(const char* s)
     return r;
 }
 
-ValueRange::ValueRange(string sRng) :
-    _rLo(0.0), _rHi(0.0), _rStep(0.0), _iDec(0), _r0(0.0), iRawUndef(0),
-    _iWidth(0), st(stByte)
+ValueRange::ValueRange( const std::string& sRng ) :
+    _rLo(0.0),
+    _rHi(0.0),
+    _rStep(0.0),
+    _iDec(0),
+    _r0(0.0),
+    iRawUndef(0),
+    _iWidth(0),
+    st(stByte)
 {
     char* sRange = new char[sRng.length() + 1];
-    for (unsigned int i = 0; i < sRng.length(); ++i)
+    for( unsigned int i = 0; i < sRng.length(); ++i )
         sRange[i] = sRng[i];
     sRange[sRng.length()] = 0;
 
     char *p1 = strchr(sRange, ':');
-    if (NULL == p1)
+    if( NULL == p1 )
     {
         delete[] sRange;
         init();
@@ -1864,27 +1874,31 @@ ValueRange::ValueRange(string sRng) :
     }
 
     char *p3 = strstr(sRange, ",offset=");
-    if (NULL == p3)
+    if( NULL == p3 )
         p3 = strstr(sRange, ":offset=");
     _r0 = rUNDEF;
-    if (NULL != p3) {
+    if( NULL != p3 )
+    {
         _r0 = doubleConv(p3+8);
         *p3 = 0;
     }
     char *p2 = strrchr(sRange, ':');
     _rStep = 1;
-    if (p1 != p2) { // step
+    if( p1 != p2 )
+    { // step
         _rStep = doubleConv(p2+1);
         *p2 = 0;
     }
 
     p2 = strchr(sRange, ':');
-    if (p2 != NULL) {
+    if( p2 != NULL )
+    {
         *p2 = 0;
         _rLo = CPLAtof(sRange);
         _rHi = CPLAtof(p2+1);
     }
-    else {
+    else
+    {
         _rLo = CPLAtof(sRange);
         _rHi = _rLo;
     }
@@ -1893,7 +1907,7 @@ ValueRange::ValueRange(string sRng) :
     delete [] sRange;
 }
 
-ValueRange::ValueRange(double min, double max)	// step = 1
+ValueRange::ValueRange( double min, double max )  // step = 1
 {
     _rLo = min;
     _rHi = max;
@@ -1901,7 +1915,7 @@ ValueRange::ValueRange(double min, double max)	// step = 1
     init();
 }
 
-ValueRange::ValueRange(double min, double max, double step)
+ValueRange::ValueRange( double min, double max, double step )
 {
     _rLo = min;
     _rHi = max;
@@ -1909,7 +1923,7 @@ ValueRange::ValueRange(double min, double max, double step)
     init();
 }
 
-static ilwisStoreType stNeeded(unsigned long iNr)
+static ilwisStoreType stNeeded(unsigned int iNr)
 {
     if (iNr <= 256)
         return stByte;
@@ -1923,7 +1937,7 @@ void ValueRange::init()
     init(rUNDEF);
 }
 
-void ValueRange::init(double rRaw0)
+void ValueRange::init( double rRaw0 )
 {
         _iDec = 0;
         if (_rStep < 0)
@@ -1939,7 +1953,7 @@ void ValueRange::init(double rRaw0)
         }
 
         short iBeforeDec = 1;
-        double rMax = MAX(fabs(get_rLo()), fabs(get_rHi()));
+        double rMax = std::max(fabs(get_rLo()), fabs(get_rHi()));
         if (rMax != 0)
             iBeforeDec = (short)floor(log10(rMax)) + 1;
         if (get_rLo() < 0)
@@ -1956,15 +1970,15 @@ void ValueRange::init(double rRaw0)
         }
         else {
             r = get_rHi() - get_rLo();
-            if (r <= ULONG_MAX) {
+            if (r <= UINT_MAX) {
                 r /= _rStep;
                 r += 1;
             }
             r += 1;
-            if (r > LONG_MAX)
+            if (r > INT_MAX)
                 st = stReal;
             else {
-                st = stNeeded((unsigned long)floor(r+0.5));
+                st = stNeeded((unsigned int)floor(r+0.5));
                 if (st < stByte)
                     st = stByte;
             }
@@ -1984,7 +1998,7 @@ void ValueRange::init(double rRaw0)
             iRawUndef = 0;
 }
 
-string ValueRange::ToString()
+std::string ValueRange::ToString()
 {
     char buffer[200];
     if (fabs(get_rLo()) > 1.0e20 || fabs(get_rHi()) > 1.0e20)
@@ -1993,7 +2007,7 @@ string ValueRange::ToString()
         CPLsnprintf(buffer, sizeof(buffer), "%.*f:%.*f:%.*f:offset=%.0f", get_iDec(), get_rLo(), get_iDec(), get_rHi(), get_iDec(), get_rStep(), get_rRaw0());
     else
         CPLsnprintf(buffer, sizeof(buffer), "%f:%f:%f:offset=%.0f", get_rLo(), get_rHi(), get_rStep(), get_rRaw0());
-    return string(buffer);
+    return std::string(buffer);
 }
 
 double ValueRange::rValue(int iRawIn)
@@ -2023,10 +2037,10 @@ int ValueRange::iRaw(double rValueIn)
     rValueIn /= _rStep;
     double rVal = floor(rValueIn+0.5);
     rVal -= _r0;
-    long iVal = longConv(rVal);
-    return static_cast<int>(iVal);
+    return intConv(rVal);
 }
 
+} // namespace GDAL
 
 /************************************************************************/
 /*                    GDALRegister_ILWIS()                              */
@@ -2048,9 +2062,9 @@ void GDALRegister_ILWIS()
                                "Byte Int16 Int32 Float64" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
-    poDriver->pfnOpen = ILWISDataset::Open;
-    poDriver->pfnCreate = ILWISDataset::Create;
-    poDriver->pfnCreateCopy = ILWISDataset::CreateCopy;
+    poDriver->pfnOpen = GDAL::ILWISDataset::Open;
+    poDriver->pfnCreate = GDAL::ILWISDataset::Create;
+    poDriver->pfnCreateCopy = GDAL::ILWISDataset::CreateCopy;
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/ilwis/ilwisdataset.h b/frmts/ilwis/ilwisdataset.h
index ab2db03..b96ac0e 100644
--- a/frmts/ilwis/ilwisdataset.h
+++ b/frmts/ilwis/ilwisdataset.h
@@ -26,33 +26,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifdef _MSC_VER
-#pragma warning(disable : 4786)
-#pragma warning(disable : 4503)
-#endif
+#ifndef ILWISDATASET_H_INCLUDED
+#define ILWISDATASET_H_INCLUDED
 
 #include "gdal_pam.h"
 #include "cpl_csv.h"
 #include "ogr_spatialref.h"
 
-#ifdef WIN32
-#include  <io.h>
-#endif
-
 #include <cstdio>
 #include <cstdlib>
 
 #include <map>
 #include <string>
 
-CPL_C_START
-void GDALRegister_ILWIS();
-CPL_C_END
-
-#define shUNDEF	-32767
+#define shUNDEF -32767
 #define iUNDEF  -2147483647
 #define flUNDEF ((float)-1e38)
-#define	rUNDEF  ((double)-1e308)
+#define rUNDEF  ((double)-1e308)
+
+namespace GDAL
+{
 
 enum ilwisStoreType
 {
@@ -66,9 +59,9 @@ enum ilwisStoreType
 class ValueRange
 {
 public:
-    ValueRange(double min, double max);	// step = 1
+    ValueRange(double min, double max);  // step = 1
     ValueRange(double min, double max, double step);
-    ValueRange(std::string str);
+    explicit ValueRange(const std::string& str);
     std::string ToString();
     ilwisStoreType get_NeededStoreType() { return st; }
     double get_rLo() { return _rLo; }
@@ -119,42 +112,42 @@ public:
     int nSizePerPixel;
 
     ILWISRasterBand( ILWISDataset *, int );
-    ~ILWISRasterBand();
-    CPLErr GetILWISInfo(std::string pszFileName);
-    void ILWISOpen( std::string pszFilename);
+    virtual ~ILWISRasterBand();
+    CPLErr GetILWISInfo(const std::string& pszFileName);
+    void ILWISOpen( const std::string& pszFilename);
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
-    virtual double GetNoDataValue( int *pbSuccess );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
+    virtual double GetNoDataValue( int *pbSuccess ) override;
 
 private:
     void FillWithNoData(void * pImage);
     void SetValue(void *pImage, int i, double rV);
     double GetValue(void *pImage, int i);
-    void ReadValueDomainProperties(std::string pszFileName);
+    void ReadValueDomainProperties(const std::string& pszFileName);
 };
 
 /************************************************************************/
-/*	                   ILWISDataset					*/
+/*                         ILWISDataset                                 */
 /************************************************************************/
 class ILWISDataset : public GDALPamDataset
 {
     friend class ILWISRasterBand;
     CPLString osFileName;
     std::string pszIlwFileName;
-    char	 *pszProjection;
+    char         *pszProjection;
     double adfGeoTransform[6];
     int    bGeoDirty;
-    int		 bNewDataset;            /* product of Create() */
+    int    bNewDataset;            /* product of Create() */
     std::string pszFileType; //indicating the input dataset: Map/MapList
-    CPLErr ReadProjection( std::string csyFileName);
+    CPLErr ReadProjection( const std::string& csyFileName);
     CPLErr WriteProjection();
     CPLErr WriteGeoReference();
-    void   CollectTransformCoef(std::string &pszRefFile );
+    void   CollectTransformCoef( std::string &pszRefFile );
 
 public:
     ILWISDataset();
-    ~ILWISDataset();
+    virtual ~ILWISDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
 
@@ -169,13 +162,13 @@ public:
                                int nBands, GDALDataType eType,
                                char** papszParmList);
 
-    virtual CPLErr 	GetGeoTransform( double * padfTransform );
-    virtual CPLErr  SetGeoTransform( double * );
+    virtual CPLErr  GetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr  SetGeoTransform( double * ) override;
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr SetProjection( const char * ) override;
 
-    virtual void   FlushCache( void );
+    virtual void   FlushCache() override;
 };
 
 // IniFile.h: interface for the IniFile class.
@@ -194,7 +187,7 @@ typedef std::map<std::string, SectionEntries*> Sections;
 class IniFile
 {
 public:
-    IniFile(const std::string& filename);
+    explicit IniFile(const std::string& filename);
     virtual ~IniFile();
 
     void SetKeyValue(const std::string& section, const std::string& key, const std::string& value);
@@ -211,3 +204,12 @@ private:
     void Load();
     void Store();
 };
+
+std::string ReadElement(const std::string& section, const std::string& entry, const std::string& filename);
+bool WriteElement(const std::string& sSection, const std::string& sEntry, const std::string& fn, const std::string& sValue);
+bool WriteElement(const std::string& sSection, const std::string& sEntry, const std::string& fn, int nValue);
+bool WriteElement(const std::string& sSection, const std::string& sEntry, const std::string& fn, double dValue);
+
+} // namespace GDAL
+
+#endif // ILWISDATASET_H_INCLUDED
diff --git a/frmts/ingr/IngrTypes.cpp b/frmts/ingr/IngrTypes.cpp
index c7d4c16..0eabab7 100644
--- a/frmts/ingr/IngrTypes.cpp
+++ b/frmts/ingr/IngrTypes.cpp
@@ -1,5 +1,4 @@
 /*****************************************************************************
- * $Id: IngrTypes.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Types support function
@@ -35,6 +34,8 @@
 #include "stdio.h"
 #endif
 
+CPL_CVSID("$Id: IngrTypes.cpp 36578 2016-11-30 15:05:11Z goatbar $");
+
 static const INGR_FormatDescription INGR_FormatTable[] = {
     {PackedBinary,            "Packed Binary",               GDT_Byte},
     {ByteInteger,             "Byte Integer",                GDT_Byte},
@@ -200,7 +201,7 @@ GDALDataType CPL_STDCALL INGR_GetDataType( uint16 eCode )
 {
     for( unsigned int i = 0; i < FORMAT_TAB_COUNT; i++ )
     {
-		if( eCode == INGR_FormatTable[i].eFormatCode )
+        if( eCode == INGR_FormatTable[i].eFormatCode )
         {
             return INGR_FormatTable[i].eDataType;
         }
@@ -636,7 +637,6 @@ void CPL_STDCALL INGR_GetEnvironVColors( VSILFILE *fp,
 
     CPLFree( pabyBuf );
 
-
 #if defined(CPL_MSB)
     for ( unsigned int i = 0; i < nEntries; i++)
     {
@@ -668,7 +668,7 @@ void CPL_STDCALL INGR_GetEnvironVColors( VSILFILE *fp,
 
     real32 fNormFactor  = ( fMaxRed > fMaxGreen ? fMaxRed : fMaxGreen );
     fNormFactor  = ( fNormFactor > fMaxBlues ? fNormFactor : fMaxBlues );
-    if (fNormFactor)
+    if (fNormFactor != 0.0f )
         fNormFactor = 255 / fNormFactor;
 
     // -------------------------------------------------------------
@@ -801,7 +801,7 @@ INGR_VirtualFile CPL_STDCALL INGR_CreateVirtualFile( const char *pszFilename,
     {
     case JPEGRGB:
         nJPGComponents = 3;
-        // fallthrough
+        CPL_FALLTHROUGH
     case JPEGGRAY:
         {
             GByte *pabyHeader = (GByte*) CPLCalloc( 1, 2048 );
@@ -920,7 +920,7 @@ int CPL_STDCALL INGR_ReadJpegQuality( VSILFILE *fp, uint32 nAppDataOfseet,
 // -----------------------------------------------------------------------------
 //                                                        INGR_Decode()
 //
-//	Decode the various RLE compression options.
+//  Decode the various RLE compression options.
 //
 //  Pass NULL as pabyDstData to obtain pnBytesConsumed and bypass decompression.
 // -----------------------------------------------------------------------------
@@ -985,7 +985,7 @@ int CPL_STDCALL INGR_DecodeRunLength( GByte *pabySrcData, GByte *pabyDstData,
         }
         else if( cAtomHead < 0 )
         {
-            const unsigned int nRun = abs( cAtomHead );
+            const unsigned int nRun = -cAtomHead;
 
             if (pabyDstData)
             {
@@ -1177,8 +1177,7 @@ INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
             bHeader = false;
 
         // Fall through. We have a valid scanline header... probably.
-
-    } while(0);
+    } while( false );
 
     if( bHeader )
         iInput+=4; // 0x5900 tag, line id, line data size, skip offset
@@ -1224,7 +1223,6 @@ INGR_DecodeRunLengthBitonal( GByte *pabySrcData, GByte *pabyDstData,
             iInput--;
     }
 
-
     if( pnBytesConsumed != NULL )
         *pnBytesConsumed = iInput * 2;
 
@@ -1255,7 +1253,6 @@ INGR_DecodeRunLengthBitonalTiled( GByte *pabySrcData, GByte *pabyDstData,
     unsigned char  nValue = 0;
     unsigned short previous = 0;
 
-
     if( CPL_LSBWORD16(pauiSrc[0]) != 0x5900 )
     {
         nRun     = 256;
@@ -1435,7 +1432,7 @@ void CPL_STDCALL INGR_HeaderOneDiskToMem(INGR_HeaderOne* pHeaderOne, const GByte
 void CPL_STDCALL INGR_HeaderOneMemToDisk(const INGR_HeaderOne* pHeaderOne, GByte *pabyBuf)
 {
     unsigned int n = 0;
-    INGR_HeaderOne* pLSBHeaderOne;
+    INGR_HeaderOne* pLSBHeaderOne = NULL;
 #if defined(CPL_MSB)
     pLSBHeaderOne = (INGR_HeaderOne* )CPLMalloc(sizeof(INGR_HeaderOne));
     memcpy(pLSBHeaderOne, pHeaderOne, sizeof(INGR_HeaderOne));
@@ -1553,7 +1550,7 @@ void CPL_STDCALL INGR_HeaderTwoADiskToMem(INGR_HeaderTwoA* pHeaderTwo, const GBy
 void CPL_STDCALL INGR_HeaderTwoAMemToDisk(const INGR_HeaderTwoA* pHeaderTwo, GByte *pabyBuf)
 {
     unsigned int n = 0;
-    INGR_HeaderTwoA* pLSBHeaderTwo;
+    INGR_HeaderTwoA* pLSBHeaderTwo = NULL;
 #if defined(CPL_MSB)
     pLSBHeaderTwo = (INGR_HeaderTwoA* )CPLMalloc(sizeof(INGR_HeaderTwoA));
     memcpy(pLSBHeaderTwo, pHeaderTwo, sizeof(INGR_HeaderTwoA));
diff --git a/frmts/ingr/IngrTypes.h b/frmts/ingr/IngrTypes.h
index 79ce8cf..fedc100 100644
--- a/frmts/ingr/IngrTypes.h
+++ b/frmts/ingr/IngrTypes.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: IngrTypes.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: IngrTypes.h 36458 2016-11-23 00:33:51Z rouault $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Types, constants and functions definition
@@ -196,7 +196,6 @@ typedef enum {
     // be decoded to find the end of a raster line.
 } INGR_IndexingMethod;
 
-
 //  ----------------------------------------------------------------------------
 //    Color Table Values ( CTV )
 //  ----------------------------------------------------------------------------
@@ -547,20 +546,22 @@ typedef     struct {
 //    Struct reading helpers
 //  ------------------------------------------------------------------
 
-#define BUF2STRC(bb, nn, ff)    \
-{                               \
-    int ss = sizeof(ff);        \
-    memcpy( &ff, &bb[nn], ss);  \
-    nn += ss;                   \
+static inline void BUF2STRC_fct( const GByte* bb, unsigned int& nn, void* pDest, size_t nSize )
+{
+    memcpy( pDest, &bb[nn], nSize );
+    nn += static_cast<unsigned int>(nSize);
 }
 
-#define STRC2BUF(bb, nn, ff)    \
-{                               \
-    int ss = sizeof(ff);        \
-    memcpy( &bb[nn], &ff, ss);  \
-    nn += ss;                   \
+#define BUF2STRC(bb, nn, ff)    BUF2STRC_fct(bb, nn, &ff, sizeof(ff))
+
+static inline void STRC2BUF_fct( GByte* bb, unsigned int& nn, const void* pSrc, size_t nSize )
+{
+    memcpy( &bb[nn], pSrc, nSize );
+    nn += static_cast<unsigned int>(nSize);
 }
 
+#define STRC2BUF(bb, nn, ff)    STRC2BUF_fct(bb, nn, &ff, sizeof(ff))
+
 //  ------------------------------------------------------------------
 //    Fix Endianness issues
 //  ------------------------------------------------------------------
diff --git a/frmts/ingr/IntergraphBand.cpp b/frmts/ingr/IntergraphBand.cpp
index ab53179..af0a7df 100644
--- a/frmts/ingr/IntergraphBand.cpp
+++ b/frmts/ingr/IntergraphBand.cpp
@@ -1,5 +1,4 @@
 /*****************************************************************************
- * $Id: IntergraphBand.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read/Write Intergraph Raster Format, band support
@@ -43,6 +42,8 @@
 
 #include <algorithm>
 
+CPL_CVSID("$Id: IntergraphBand.cpp 35929 2016-10-25 16:09:00Z goatbar $");
+
 using std::fill;
 
 //  ----------------------------------------------------------------------------
@@ -71,13 +72,13 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDSIn,
                                             int nBandIn,
                                             int nBandOffset,
                                             GDALDataType eType ) :
-    poColorTable(NULL),
+    poColorTable(new GDALColorTable()),
     nDataOffset(0),
     nBlockBufSize(0),
     nBandStart(nBandOffset),
     nRGBIndex(0),
     eFormat(IngrUnknownFrmt),
-    bTiled(FALSE),
+    bTiled(false),
     nFullBlocksX(0),
     nFullBlocksY(0),
     pabyBlockBuf(NULL),
@@ -85,15 +86,13 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDSIn,
     pahTiles(NULL),
     nRLEOffset(0)
 {
-    this->poColorTable  = new GDALColorTable();
-    this->poDS          = poDSIn;
-    this->nBand         = nBandIn != 0 ? nBandIn : poDSIn->nBands;
-    eDataType     = eType;
+    poDS = poDSIn;
+    nBand = nBandIn != 0 ? nBandIn : poDSIn->nBands;
+    eDataType = eType;
 
     // --------------------------------------------------------------------
     // Get Header Info
     // --------------------------------------------------------------------
-
     memcpy(&hHeaderOne, &poDSIn->hHeaderOne, sizeof(hHeaderOne));
     memcpy(&hHeaderTwo, &poDSIn->hHeaderTwo, sizeof(hHeaderTwo));
 
@@ -112,7 +111,6 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDSIn,
     // --------------------------------------------------------------------
     // Get Color Tabel from Color Table Type (CTV)
     // --------------------------------------------------------------------
-
     uint32 nEntries = hHeaderTwo.NumberOfCTEntries;
 
     if( nEntries > 0 )
@@ -151,7 +149,7 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDSIn,
 
     eFormat = (INGR_Format) hHeaderOne.DataTypeCode;
 
-    bTiled = (hHeaderOne.DataTypeCode == TiledRasterData);
+    bTiled = hHeaderOne.DataTypeCode == TiledRasterData;
 
     if( bTiled )
     {
@@ -183,26 +181,24 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDSIn,
     // --------------------------------------------------------------------
     // Incomplete tiles have Block Offset greater than:
     // --------------------------------------------------------------------
-
-    nFullBlocksX  = ( nRasterXSize / nBlockXSize );
-    nFullBlocksY  = ( nRasterYSize / nBlockYSize );
+    nFullBlocksX = nRasterXSize / nBlockXSize;
+    nFullBlocksY = nRasterYSize / nBlockYSize;
 
     // --------------------------------------------------------------------
     // Get the Data Type from Format
     // --------------------------------------------------------------------
-
-    eDataType = INGR_GetDataType( (uint16) eFormat );
+    eDataType = INGR_GetDataType( static_cast<uint16>(eFormat) );
 
     // --------------------------------------------------------------------
     // Allocate buffer for a Block of data
     // --------------------------------------------------------------------
-
     if( nBlockYSize == 0 ||
         nBlockXSize > INT_MAX / nBlockYSize ||
         nBlockXSize > INT_MAX / 4 - 2 ||
         GDALGetDataTypeSize( eDataType ) == 0 ||
         nBlockYSize > INT_MAX / (GDALGetDataTypeSize( eDataType ) / 8) ||
-        nBlockXSize > INT_MAX / (nBlockYSize * (GDALGetDataTypeSize( eDataType ) / 8)) )
+        nBlockXSize > INT_MAX / (nBlockYSize *
+                                 (GDALGetDataTypeSizeBytes( eDataType ))) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Too big block size");
         return;
@@ -213,25 +209,27 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDSIn,
 
     if (eFormat == RunLengthEncoded)
     {
-        pabyBlockBuf = (GByte*) VSIMalloc3( nBlockXSize*4+2, nBlockYSize,
-                                            GDALGetDataTypeSize( eDataType ) / 8);
+        pabyBlockBuf = (GByte*) VSIMalloc3(
+            nBlockXSize*4+2, nBlockYSize,
+            GDALGetDataTypeSizeBytes( eDataType ) );
     }
     else
     {
-        pabyBlockBuf = (GByte*) VSIMalloc3( nBlockXSize, nBlockYSize,
-                                            GDALGetDataTypeSize( eDataType ) / 8);
+        pabyBlockBuf = (GByte*) VSIMalloc3(
+            nBlockXSize, nBlockYSize,
+            GDALGetDataTypeSizeBytes( eDataType ) );
     }
 
     if (pabyBlockBuf == NULL)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nBlockBufSize);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot allocate %d bytes", nBlockBufSize);
         return;
     }
 
     // --------------------------------------------------------------------
     // More Metadata Information
     // --------------------------------------------------------------------
-
     SetMetadataItem( "FORMAT", INGR_GetFormatName( (uint16) eFormat ),
         "IMAGE_STRUCTURE" );
 
@@ -256,7 +254,7 @@ IntergraphRasterBand::IntergraphRasterBand( IntergraphDataset *poDSIn,
         SetMetadataItem( "NBITS", "1", "IMAGE_STRUCTURE" );
     }
 
-    this->nRLEOffset = 0;
+    nRLEOffset = 0;
 }
 
 //  ----------------------------------------------------------------------------
@@ -339,7 +337,6 @@ GDALColorInterp IntergraphRasterBand::GetColorInterpretation()
 
         return GCI_GrayIndex;
     }
-
 }
 
 //  ----------------------------------------------------------------------------
@@ -471,8 +468,6 @@ int IntergraphRasterBand::HandleUninstantiatedTile(int nBlockXOff,
                     (GDALGetDataTypeSize( eDataType ) / 8) );
         return TRUE;
     }
-
-
     return FALSE;
 }
 
@@ -481,15 +476,15 @@ int IntergraphRasterBand::HandleUninstantiatedTile(int nBlockXOff,
 //  ----------------------------------------------------------------------------
 
 IntergraphRGBBand::IntergraphRGBBand( IntergraphDataset *poDSIn,
-                                     int nBandIn,
-                                     int nBandOffset,
-                                     int nRGorB )
+                                      int nBandIn,
+                                      int nBandOffset,
+                                      int nRGorB )
     : IntergraphRasterBand( poDSIn, nBandIn, nBandOffset )
 {
-    if (pabyBlockBuf == NULL)
+    if( pabyBlockBuf == NULL )
         return;
 
-    nRGBIndex     = (uint8) nRGorB;
+    nRGBIndex = static_cast<uint8>(nRGorB);
 
     // --------------------------------------------------------------------
     // Reallocate buffer for a block of RGB Data
@@ -497,10 +492,11 @@ IntergraphRGBBand::IntergraphRGBBand( IntergraphDataset *poDSIn,
 
     nBlockBufSize *= 3;
     CPLFree( pabyBlockBuf );
-    pabyBlockBuf = (GByte*) VSIMalloc( nBlockBufSize );
-    if (pabyBlockBuf == NULL)
+    pabyBlockBuf = static_cast<GByte *>(VSIMalloc( nBlockBufSize ));
+    if( pabyBlockBuf == NULL )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nBlockBufSize);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot allocate %d bytes", nBlockBufSize);
     }
 }
 
@@ -538,18 +534,18 @@ CPLErr IntergraphRGBBand::IReadBlock( int nBlockXOff,
 //  ----------------------------------------------------------------------------
 
 IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDSIn,
-                                     int nBandIn,
-                                     int nBandOffset,
-                                     int nRGorB )
-    : IntergraphRasterBand( poDSIn, nBandIn, nBandOffset )
+                                      int nBandIn,
+                                      int nBandOffset,
+                                      int nRGorB ) :
+    IntergraphRasterBand( poDSIn, nBandIn, nBandOffset ),
+    pabyRLEBlock(NULL),
+    nRLESize(0),
+    bRLEBlockLoaded(FALSE),
+    panRLELineOffset(NULL)
 {
-    nRLESize         = 0;
-    nRGBIndex        = (uint8) nRGorB;
-    bRLEBlockLoaded  = FALSE;
-    pabyRLEBlock     = NULL;
-    panRLELineOffset = NULL;
+    nRGBIndex = static_cast<uint8>(nRGorB);
 
-    if (pabyBlockBuf == NULL)
+    if( pabyBlockBuf == NULL )
         return;
 
     if( !bTiled )
@@ -575,9 +571,9 @@ IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDSIn,
             nFullBlocksY = 1;
         }
 
-        nRLESize     = INGR_GetDataBlockSize( poDSIn->pszFilename,
-                          hHeaderTwo.CatenatedFilePointer,
-                          nDataOffset);
+        nRLESize = INGR_GetDataBlockSize( poDSIn->pszFilename,
+                                          hHeaderTwo.CatenatedFilePointer,
+                                          nDataOffset);
 
         if( nBlockYSize == 0 || nBlockXSize > INT_MAX / nBlockYSize )
         {
@@ -643,7 +639,6 @@ IntergraphRLEBand::IntergraphRLEBand( IntergraphDataset *poDSIn,
     {
         BlackWhiteCT( true );
     }
-
 }
 
 //  ----------------------------------------------------------------------------
@@ -702,7 +697,7 @@ CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
     }
 
     // ----------------------------------------------------------------
-	// Calculate the resulting image dimmention
+    // Calculate the resulting image dimmention
     // ----------------------------------------------------------------
 
     int nVirtualXSize = nBlockXSize;
@@ -842,14 +837,14 @@ CPLErr IntergraphRLEBand::IReadBlock( int nBlockXOff,
 IntergraphBitmapBand::IntergraphBitmapBand( IntergraphDataset *poDSIn,
                                             int nBandIn,
                                             int nBandOffset,
-                                            int nRGorB )
-    : IntergraphRasterBand( poDSIn, nBandIn, nBandOffset, GDT_Byte ),
-      pabyBMPBlock(NULL),
-      nBMPSize(0),
-      nQuality(0),
-      nRGBBand(nRGorB)
+                                            int nRGorB ) :
+    IntergraphRasterBand( poDSIn, nBandIn, nBandOffset, GDT_Byte ),
+    pabyBMPBlock(NULL),
+    nBMPSize(0),
+    nQuality(0),
+    nRGBBand(nRGorB)
 {
-    if (pabyBlockBuf == NULL)
+    if( pabyBlockBuf == NULL )
         return;
 
     if( !bTiled )
@@ -859,9 +854,9 @@ IntergraphBitmapBand::IntergraphBitmapBand( IntergraphDataset *poDSIn,
         // ------------------------------------------------------------
 
         nBlockYSize = nRasterYSize;
-        nBMPSize    = INGR_GetDataBlockSize( poDSIn->pszFilename,
-                                             hHeaderTwo.CatenatedFilePointer,
-                                             nDataOffset);
+        nBMPSize = INGR_GetDataBlockSize( poDSIn->pszFilename,
+                                          hHeaderTwo.CatenatedFilePointer,
+                                          nDataOffset );
     }
     else
     {
@@ -882,30 +877,31 @@ IntergraphBitmapBand::IntergraphBitmapBand( IntergraphDataset *poDSIn,
     pabyBMPBlock = (GByte*) VSIMalloc( nBMPSize );
     if (pabyBMPBlock == NULL)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate %d bytes", nBMPSize);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot allocate %d bytes", nBMPSize);
     }
 
     // ----------------------------------------------------------------
     // Set a black and white Color Table
     // ----------------------------------------------------------------
 
-	if( eFormat == CCITTGroup4 )
-	{
+    if( eFormat == CCITTGroup4 )
+    {
         BlackWhiteCT( true );
-	}
+    }
 
     // ----------------------------------------------------------------
     // Read JPEG Quality from Application Data
     // ----------------------------------------------------------------
 
-	if( eFormat == JPEGGRAY ||
-		eFormat == JPEGRGB  ||
-		eFormat == JPEGCMYK )
-	{
+    if( eFormat == JPEGGRAY ||
+        eFormat == JPEGRGB  ||
+        eFormat == JPEGCMYK )
+    {
         nQuality = INGR_ReadJpegQuality( poDSIn->fp,
-            hHeaderTwo.ApplicationPacketPointer,
-            nDataOffset );
-	}
+                                         hHeaderTwo.ApplicationPacketPointer,
+                                         nDataOffset );
+    }
 }
 
 //  ----------------------------------------------------------------------------
@@ -956,7 +952,7 @@ CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
     IntergraphDataset *poGDS = ( IntergraphDataset * ) poDS;
 
     // ----------------------------------------------------------------
-	// Load the block of a tile or a whole image
+    // Load the block of a tile or a whole image
     // ----------------------------------------------------------------
     if (HandleUninstantiatedTile( nBlockXOff, nBlockYOff, pImage ))
         return CE_None;
@@ -975,7 +971,7 @@ CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
     }
 
     // ----------------------------------------------------------------
-	// Calculate the resulting image dimmention
+    // Calculate the resulting image dimmention
     // ----------------------------------------------------------------
 
     int nVirtualXSize = nBlockXSize;
@@ -992,7 +988,7 @@ CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
     }
 
     // ----------------------------------------------------------------
-	// Create an in memory small tiff file (~400K)
+    // Create an in memory small tiff file (~400K)
     // ----------------------------------------------------------------
 
     poGDS->hVirtual = INGR_CreateVirtualFile( poGDS->pszFilename,
@@ -1010,13 +1006,13 @@ CPLErr IntergraphBitmapBand::IReadBlock( int nBlockXOff,
         memset( pImage, 0, nBlockXSize * nBlockYSize *
                     (GDALGetDataTypeSize( eDataType ) / 8) );
         CPLError( CE_Failure, CPLE_AppDefined,
-			"Unable to open virtual file.\n"
-			"Is the GTIFF and JPEG driver available?" );
+                  "Unable to open virtual file.\n"
+                  "Is the GTIFF and JPEG driver available?" );
         return CE_Failure;
     }
 
     // ----------------------------------------------------------------
-	// Read the unique block from the in memory file and release it
+    // Read the unique block from the in memory file and release it
     // ----------------------------------------------------------------
 
     if( poGDS->hVirtual.poBand->RasterIO( GF_Read, 0, 0,
@@ -1321,27 +1317,27 @@ void IntergraphRasterBand::FlushBandHeader( void )
 
 void IntergraphRasterBand::BlackWhiteCT( bool bReverse )
 {
-	GDALColorEntry oBlack;
-	GDALColorEntry oWhite;
+    GDALColorEntry oBlack;
+    GDALColorEntry oWhite;
 
     oWhite.c1 = (short) 255;
-	oWhite.c2 = (short) 255;
-	oWhite.c3 = (short) 255;
-	oWhite.c4 = (short) 255;
+    oWhite.c2 = (short) 255;
+    oWhite.c3 = (short) 255;
+    oWhite.c4 = (short) 255;
 
-	oBlack.c1 = (short) 0;
-	oBlack.c2 = (short) 0;
-	oBlack.c3 = (short) 0;
-	oBlack.c4 = (short) 255;
+    oBlack.c1 = (short) 0;
+    oBlack.c2 = (short) 0;
+    oBlack.c3 = (short) 0;
+    oBlack.c4 = (short) 255;
 
     if( bReverse )
     {
         poColorTable->SetColorEntry( 0, &oWhite );
-	    poColorTable->SetColorEntry( 1, &oBlack );
+        poColorTable->SetColorEntry( 1, &oBlack );
     }
     else
     {
         poColorTable->SetColorEntry( 0, &oBlack );
-	    poColorTable->SetColorEntry( 1, &oWhite );
+        poColorTable->SetColorEntry( 1, &oWhite );
     }
 }
diff --git a/frmts/ingr/IntergraphBand.h b/frmts/ingr/IntergraphBand.h
index 26043d9..f2b5f2c 100644
--- a/frmts/ingr/IntergraphBand.h
+++ b/frmts/ingr/IntergraphBand.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
-* $Id: IntergraphBand.h 33720 2016-03-15 00:39:53Z goatbar $
+* $Id: IntergraphBand.h 36501 2016-11-25 14:09:24Z rouault $
 *
 * Project:  Intergraph Raster Format support
 * Purpose:  Read selected types of Intergraph Raster Format
@@ -50,7 +50,7 @@ protected:
     int             nFullBlocksX;
     int             nFullBlocksY;
 
-    GByte	   *pabyBlockBuf;
+    GByte          *pabyBlockBuf;
     uint32          nTiles;
 
     INGR_TileItem  *pahTiles;
@@ -66,22 +66,22 @@ public:
         int nBand,
         int nBandOffset,
         GDALDataType eType = GDT_Unknown);
-    ~IntergraphRasterBand();
+    virtual ~IntergraphRasterBand();
 
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum( int *pbSuccess = NULL );
-    virtual GDALColorTable *GetColorTable();
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
-    virtual CPLErr IWriteBlock( int nBlockXOff, int nBlockYOff, void *pImage );
-    virtual CPLErr SetColorTable( GDALColorTable *poColorTable );
-    virtual CPLErr SetStatistics( double dfMin, double dfMax, double dfMean, double dfStdDev );
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum( int *pbSuccess = NULL ) override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
+    virtual CPLErr IWriteBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
+    virtual CPLErr SetColorTable( GDALColorTable *poColorTable ) override;
+    virtual CPLErr SetStatistics( double dfMin, double dfMax, double dfMean, double dfStdDev ) override;
 
 protected:
     int  HandleUninstantiatedTile( int nBlockXOff, int nBlockYOff, void* pImage);
     int  LoadBlockBuf( int nBlockXOff, int nBlockYOff, int nBlockBytes, GByte *pabyBlock );
     bool ReshapeBlock( int nBlockXOff, int nBlockYOff, int nBlockBytes, GByte *pabyBlock );
-    void FlushBandHeader( void );
+    void FlushBandHeader();
     void BlackWhiteCT( bool bReverse = false );
 };
 
@@ -93,11 +93,11 @@ class IntergraphRGBBand : public IntergraphRasterBand
 {
 public:
     IntergraphRGBBand( IntergraphDataset *poDS,
-        int nBand,
-        int nBandOffset,
-        int nRGorB );
+                       int nBand,
+                       int nBandOffset,
+                       int nRGorB );
 
-    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
 };
 
 //  ----------------------------------------------------------------------------
@@ -109,20 +109,20 @@ class IntergraphBitmapBand : public IntergraphRasterBand
     friend class IntergraphDataset;
 
 private:
-    GByte	       *pabyBMPBlock;
+    GByte          *pabyBMPBlock;
     uint32          nBMPSize;
     int             nQuality;
     int             nRGBBand;
 
 public:
     IntergraphBitmapBand( IntergraphDataset *poDS,
-        int nBand,
-        int nBandOffset,
-        int nRGorB = 1 );
-    ~IntergraphBitmapBand();
+                          int nBand,
+                          int nBandOffset,
+                          int nRGorB = 1 );
+    virtual ~IntergraphBitmapBand();
 
-    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
 //  ----------------------------------------------------------------------------
@@ -134,17 +134,17 @@ class IntergraphRLEBand : public IntergraphRasterBand
     friend class IntergraphDataset;
 
 private:
-    GByte	       *pabyRLEBlock;
+    GByte          *pabyRLEBlock;
     uint32          nRLESize;
     int             bRLEBlockLoaded;
     uint32         *panRLELineOffset;
 
 public:
     IntergraphRLEBand( IntergraphDataset *poDS,
-        int nBand,
-        int nBandOffset,
-        int nRGorB = 0);
-    ~IntergraphRLEBand();
+                       int nBand,
+                       int nBandOffset,
+                       int nRGorB = 0 );
+    virtual ~IntergraphRLEBand();
 
-    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
 };
diff --git a/frmts/ingr/IntergraphDataset.cpp b/frmts/ingr/IntergraphDataset.cpp
index 404182d..22296a7 100644
--- a/frmts/ingr/IntergraphDataset.cpp
+++ b/frmts/ingr/IntergraphDataset.cpp
@@ -1,5 +1,4 @@
 /*****************************************************************************
- * $Id: IntergraphDataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read/Write Intergraph Raster Format, dataset support
@@ -41,6 +40,8 @@
 #include "IntergraphBand.h"
 #include "IngrTypes.h"
 
+CPL_CVSID("$Id: IntergraphDataset.cpp 35670 2016-10-09 22:58:16Z goatbar $");
+
 //  ----------------------------------------------------------------------------
 //                                        IntergraphDataset::IntergraphDataset()
 //  ----------------------------------------------------------------------------
@@ -168,7 +169,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
     // We need to scan around the file, so we open it now.
     // --------------------------------------------------------------------
 
-    VSILFILE   *fp;
+    VSILFILE *fp = NULL;
 
     if( poOpenInfo->eAccess == GA_ReadOnly  )
     {
@@ -344,7 +345,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         case JPEGRGB:
         case JPEGCMYK:
         {
-            IntergraphBitmapBand* poBand;
+            IntergraphBitmapBand* poBand = NULL;
             nBands++;
             poDS->SetBand( nBands,
                 poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset, 1 ));
@@ -374,7 +375,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         case JPEGGRAY:
         case CCITTGroup4:
         {
-            IntergraphBitmapBand* poBand;
+            IntergraphBitmapBand* poBand = NULL;
             nBands++;
             poDS->SetBand( nBands,
                 poBand = new IntergraphBitmapBand( poDS, nBands, nBandOffset ));
@@ -389,7 +390,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         case RunLengthEncodedC:
         case AdaptiveGrayScale:
         {
-            IntergraphRLEBand* poBand;
+            IntergraphRLEBand* poBand = NULL;
             nBands++;
             poDS->SetBand( nBands,
                 poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset ));
@@ -403,7 +404,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         case AdaptiveRGB:
         case ContinuousTone:
         {
-            IntergraphRLEBand* poBand;
+            IntergraphRLEBand* poBand = NULL;
             nBands++;
             poDS->SetBand( nBands,
                 poBand = new IntergraphRLEBand( poDS, nBands, nBandOffset, 1 ));
@@ -432,7 +433,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         }
         case Uncompressed24bit:
         {
-            IntergraphRGBBand* poBand;
+            IntergraphRGBBand* poBand = NULL;
             nBands++;
             poDS->SetBand( nBands,
                 poBand = new IntergraphRGBBand( poDS, nBands, nBandOffset, 1 ));
@@ -461,7 +462,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
         }
         default:
         {
-            IntergraphRasterBand* poBand;
+            IntergraphRasterBand* poBand = NULL;
             nBands++;
             poDS->SetBand( nBands,
                 poBand = new IntergraphRasterBand( poDS, nBands, nBandOffset ));
@@ -496,7 +497,7 @@ GDALDataset *IntergraphDataset::Open( GDALOpenInfo *poOpenInfo )
 
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return ( poDS );
+    return poDS;
 }
 
 //  ----------------------------------------------------------------------------
diff --git a/frmts/ingr/IntergraphDataset.h b/frmts/ingr/IntergraphDataset.h
index 2532f28..fbbb42f 100644
--- a/frmts/ingr/IntergraphDataset.h
+++ b/frmts/ingr/IntergraphDataset.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: IntergraphDataset.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: IntergraphDataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Intergraph Raster Format support
  * Purpose:  Read selected types of Intergraph Raster Format
@@ -52,7 +52,7 @@ private:
 
 public:
     IntergraphDataset();
-    ~IntergraphDataset();
+    virtual ~IntergraphDataset();
 
     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
     static GDALDataset *Create( const char *pszFilename,
@@ -68,7 +68,7 @@ public:
         GDALProgressFunc pfnProgress,
         void * pProgressData );
 
-    virtual CPLErr GetGeoTransform( double *padfTransform );
-    virtual CPLErr SetGeoTransform( double *padfTransform );
-    virtual CPLErr SetProjection( const char *pszProjString );
+    virtual CPLErr GetGeoTransform( double *padfTransform ) override;
+    virtual CPLErr SetGeoTransform( double *padfTransform ) override;
+    virtual CPLErr SetProjection( const char *pszProjString ) override;
 };
diff --git a/frmts/ingr/JpegHelper.cpp b/frmts/ingr/JpegHelper.cpp
index a54eea6..149fe9c 100644
--- a/frmts/ingr/JpegHelper.cpp
+++ b/frmts/ingr/JpegHelper.cpp
@@ -1,5 +1,4 @@
 /*****************************************************************************
- * $Id:  $
  *
  * Project:  Creates a jpeg header
  * Purpose:  Abbreviated JPEG support
@@ -30,6 +29,8 @@
 
 #include "JpegHelper.h"
 
+CPL_CVSID("$Id: JpegHelper.cpp 34811 2016-07-28 15:15:05Z goatbar $");
+
 static const GByte JPGHLP_1DC_Codes[] = {
     0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
 };
diff --git a/frmts/ingr/JpegHelper.h b/frmts/ingr/JpegHelper.h
index cc80a93..7a7fc7a 100644
--- a/frmts/ingr/JpegHelper.h
+++ b/frmts/ingr/JpegHelper.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id:  $
+ * $Id: JpegHelper.h 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  Project:  Creates a jpeg header
  * Purpose:  Abbreviated JPEG support
diff --git a/frmts/iris/irisdataset.cpp b/frmts/iris/irisdataset.cpp
index 5d79e28..2dc9641 100644
--- a/frmts/iris/irisdataset.cpp
+++ b/frmts/iris/irisdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: irisdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  IRIS Reader
  * Purpose:  All code for IRIS format Reader
@@ -30,23 +29,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#ifndef DEG2RAD
-#  define DEG2RAD (M_PI/180.0)
-#endif
-
-#ifndef RAD2DEG
-#  define RAD2DEG (180.0/M_PI)
-#endif
-
+#include "cpl_port.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
+#include <algorithm>
 #include <sstream>
 
-CPL_CVSID("$Id: irisdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: irisdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
-#define ARRAY_ELEMENT_COUNT(x) ((sizeof(x))/sizeof(x[0]))
+static double DEG2RAD = M_PI / 180.0;
+static double RAD2DEG = 180.0 / M_PI;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -62,7 +56,7 @@ class IRISDataset : public GDALPamDataset
 
     VSILFILE              *fp;
     GByte                 abyHeader[640];
-    int                   bNoDataSet;
+    bool                  bNoDataSet;
     double                dfNoDataValue;
     static const char* const   aszProductNames[];
     static const char* const   aszDataTypeCodes[];
@@ -74,28 +68,30 @@ class IRISDataset : public GDALPamDataset
     float                 fNyquistVelocity;
     char*                 pszSRS_WKT;
     double                adfGeoTransform[6];
-    int                   bHasLoadedProjection;
+    bool                  bHasLoadedProjection;
     void                  LoadProjection();
-    std::pair <double,double> GeodesicCalculation(float fLat, float fLon, float fAngle, float fDist, float fEquatorialRadius, float fPolarRadius, float fFlattening);
+    static std::pair<double, double> GeodesicCalculation(
+        float fLat, float fLon, float fAngle, float fDist,
+        float fEquatorialRadius, float fPolarRadius, float fFlattening );
 
 public:
     IRISDataset();
-    ~IRISDataset();
+    virtual ~IRISDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
 
-    CPLErr 	GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
+    CPLErr GetGeoTransform( double * padfTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
-const char* const IRISDataset::aszProductNames[]= {
+const char* const IRISDataset::aszProductNames[] = {
     "", "PPI", "RHI", "CAPPI", "CROSS", "TOPS", "TRACK", "RAIN1", "RAINN",
     "VVP", "VIL", "SHEAR", "WARN", "CATCH", "RTI", "RAW", "MAX", "USER",
     "USERV", "OTHER", "STATUS", "SLINE", "WIND", "BEAM", "TEXT", "FCAST",
     "NDOP", "IMAGE", "COMP", "TDWR", "GAGE", "DWELL", "SRI", "BASE", "HMAX"};
 
-const char* const IRISDataset::aszDataTypeCodes[]={
+const char* const IRISDataset::aszDataTypeCodes[] = {
     "XHDR", "DBT" ,"dBZ", "VEL", "WIDTH", "ZDR", "ORAIN", "dBZC", "DBT2",
     "dBZ2", "VEL2", "WIDTH2", "ZDR2", "RAINRATE2", "KDP", "KDP2", "PHIDP",
     "VELC", "SQI", "RHOHV", "RHOHV2", "dBZC2", "VELC2", "SQI2", "PHIDP2",
@@ -105,11 +101,14 @@ const char* const IRISDataset::aszDataTypeCodes[]={
     "RHOV2", "PHIH", "PHIH2", "PHIV", "PHIV2", "USER2", "HCLASS", "HCLASS2",
     "ZDRC", "ZDRC2", "TEMPERATURE16", "VIR16", "DBTV8", "DBTV16", "DBZV8",
     "DBZV16", "SNR8", "SNR16", "ALBEDO8", "ALBEDO16", "VILD16", "TURB16"};
-const char* const IRISDataset::aszDataTypes[]={
-    "Extended Headers","Total H power (1 byte)","Clutter Corrected H reflectivity (1 byte)",
-    "Velocity (1 byte)","Width (1 byte)","Differential reflectivity (1 byte)",
-    "Old Rainfall rate (stored as dBZ)","Fully corrected reflectivity (1 byte)",
-    "Uncorrected reflectivity (2 byte)","Corrected reflectivity (2 byte)",
+
+const char* const IRISDataset::aszDataTypes[] = {
+    "Extended Headers", "Total H power (1 byte)",
+    "Clutter Corrected H reflectivity (1 byte)",
+    "Velocity (1 byte)", "Width (1 byte)", "Differential reflectivity (1 byte)",
+    "Old Rainfall rate (stored as dBZ)",
+    "Fully corrected reflectivity (1 byte)",
+    "Uncorrected reflectivity (2 byte)", "Corrected reflectivity (2 byte)",
     "Velocity (2 byte)","Width (2 byte)","Differential reflectivity (2 byte)",
     "Rainfall rate (2 byte)","Kdp (specific differential phase)(1 byte)",
     "Kdp (specific differential phase)(2 byte)","PHIdp (differential phase)(1 byte)",
@@ -132,11 +131,12 @@ const char* const IRISDataset::aszDataTypes[]={
     "Clutter Corrected V Reflectivity (1 byte)", "Clutter Corrected V Reflectivity (2 byte)",
     "Signal to Noise ratio (1 byte)", "Signal to Noise ratio (2 byte)", "Albedo (1 byte)",
     "Albedo (2 byte)", "VIL Density (2 byte)", "Turbulence (2 byte)"};
-const char* const IRISDataset::aszProjections[]={
-    "Azimutal equidistant","Mercator","Polar Stereographic","UTM",
+
+const char* const IRISDataset::aszProjections[] = {
+    "Azimutal equidistant","Mercator","Polar Stereographic", "UTM",
     // FIXME: is it a typo here or in IRIS itself: Perspective or Prespective ?
-    "Prespective from geosync","Equidistant cylindrical","Gnomonic",
-    "Gauss conformal","Lambert conformal conic"};
+    "Perspective from geosync", "Equidistant cylindrical", "Gnomonic",
+    "Gauss conformal", "Lambert conformal conic"};
 
 /************************************************************************/
 /* ==================================================================== */
@@ -149,32 +149,31 @@ class IRISRasterBand : public GDALPamRasterBand
     friend class IRISDataset;
 
     unsigned char*        pszRecord;
-    int                   bBufferAllocFailed;
+    bool                  bBufferAllocFailed;
 
 public:
     IRISRasterBand( IRISDataset *, int );
-    ~IRISRasterBand();
+    virtual ~IRISRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 
-    virtual double          GetNoDataValue( int * );
-    virtual CPLErr          SetNoDataValue( double );
+    virtual double          GetNoDataValue( int * ) override;
+    virtual CPLErr          SetNoDataValue( double ) override;
 };
 
-
 /************************************************************************/
 /*                           IRISRasterBand()                           */
 /************************************************************************/
 
-IRISRasterBand::IRISRasterBand( IRISDataset *poDSIn, int nBandIn )
+IRISRasterBand::IRISRasterBand( IRISDataset *poDSIn, int nBandIn ) :
+    pszRecord(NULL),
+    bBufferAllocFailed(false)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     eDataType = GDT_Float32;
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
-    pszRecord = NULL;
-    bBufferAllocFailed = FALSE;
 }
 
 IRISRasterBand::~IRISRasterBand()
@@ -186,139 +185,159 @@ IRISRasterBand::~IRISRasterBand()
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr IRISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+CPLErr IRISRasterBand::IReadBlock( int /* nBlockXOff */,
                                    int nBlockYOff,
                                    void * pImage )
 
 {
-    IRISDataset *poGDS = (IRISDataset *) poDS;
+    IRISDataset *poGDS = static_cast<IRISDataset *>(poDS);
 
-    //Every product type has it's own size. TODO: Move it like dataType
+    // Every product type has its own size. TODO: Move it like dataType.
     int nDataLength = 1;
-    if(poGDS->nDataTypeCode == 2){nDataLength=1;}
-    else if(poGDS->nDataTypeCode == 37){nDataLength=2;}
-    else if(poGDS->nDataTypeCode == 33){nDataLength=2;}
-    else if(poGDS->nDataTypeCode == 32){nDataLength=1;}
+    if( poGDS->nDataTypeCode == 2 ) nDataLength = 1;
+    else if( poGDS->nDataTypeCode == 37 ) nDataLength = 2;
+    else if( poGDS->nDataTypeCode == 33 ) nDataLength = 2;
+    else if( poGDS->nDataTypeCode == 32 ) nDataLength = 1;
 
-    int i;
-    //We allocate space for storing a record:
-    if (pszRecord == NULL)
+    // We allocate space for storing a record:
+    if( pszRecord == NULL )
     {
-        if (bBufferAllocFailed)
+        if( bBufferAllocFailed )
             return CE_Failure;
 
-        pszRecord = (unsigned char *) VSI_MALLOC_VERBOSE(nBlockXSize*nDataLength);
+        pszRecord = static_cast<unsigned char *>(
+            VSI_MALLOC_VERBOSE(nBlockXSize*nDataLength));
 
-        if (pszRecord == NULL)
+        if( pszRecord == NULL )
         {
-            bBufferAllocFailed = TRUE;
+            bBufferAllocFailed = true;
             return CE_Failure;
         }
     }
 
-    //Prepare to read (640 is the header size in bytes) and read (the y axis in the IRIS files in the inverse direction)
-    //The previous bands are also added as an offset
+    // Prepare to read (640 is the header size in bytes) and read (the
+    // y axis in the IRIS files in the inverse direction).  The
+    // previous bands are also added as an offset
 
-    VSIFSeekL( poGDS->fp, 640 + (vsi_l_offset)nDataLength*poGDS->GetRasterXSize()*poGDS->GetRasterYSize()*(this->nBand-1) +
-                                (vsi_l_offset)nBlockXSize*nDataLength*(poGDS->GetRasterYSize()-1-nBlockYOff), SEEK_SET );
+    VSIFSeekL( poGDS->fp,
+               640 +
+               static_cast<vsi_l_offset>(nDataLength)*poGDS->GetRasterXSize()*poGDS->GetRasterYSize()*(this->nBand-1) +
+               static_cast<vsi_l_offset>(nBlockXSize)*nDataLength*(poGDS->GetRasterYSize()-1-nBlockYOff), SEEK_SET );
 
-    if( (int)VSIFReadL( pszRecord, nBlockXSize*nDataLength, 1, poGDS->fp ) != 1 )
+    if( static_cast<int>(VSIFReadL( pszRecord, nBlockXSize*nDataLength, 1,
+                                    poGDS->fp )) != 1 )
         return CE_Failure;
 
-    //If datatype is dbZ or dBT:
-    //See point 3.3.3 at page 3.33 of the manual
-    if(poGDS->nDataTypeCode == 2 || poGDS->nDataTypeCode == 1){
-        float fVal;
-        for (i=0;i<nBlockXSize;i++){
-            fVal = (((float) *(pszRecord+i*nDataLength)) -64)/2.0f;
-            if (fVal == 95.5f)
+    // If datatype is dbZ or dBT:
+    // See point 3.3.3 at page 3.33 of the manual.
+    if( poGDS->nDataTypeCode == 2 || poGDS->nDataTypeCode == 1 )
+    {
+        for( int i = 0; i < nBlockXSize; i++)
+        {
+            float fVal = ((*(pszRecord + i * nDataLength)) - 64.0f) / 2.0f;
+            if( fVal == 95.5f )
                 fVal = -9999.0f;
             ((float *) pImage)[i] = fVal;
         }
-    //If datatype is dbZ2 or dBT2:
-    //See point 3.3.4 at page 3.33 of the manual
-    } else if(poGDS->nDataTypeCode == 8 || poGDS->nDataTypeCode == 9){
-        float fVal;
-        for (i=0;i<nBlockXSize;i++){
-            fVal = (((float) CPL_LSBUINT16PTR(pszRecord+i*nDataLength)) - 32768)/100.0f;
-            if (fVal == 327.67f)
+    // If datatype is dbZ2 or dBT2:
+    // See point 3.3.4 at page 3.33 of the manual.
+    }
+    else if( poGDS->nDataTypeCode == 8 || poGDS->nDataTypeCode == 9 )
+    {
+        for( int i = 0; i < nBlockXSize; i++)
+        {
+            float fVal =
+                (CPL_LSBUINT16PTR(pszRecord + i * nDataLength) - 32768.0f) /
+                100.0f;
+            if( fVal == 327.67f )
                 fVal = -9999.0f;
             ((float *) pImage)[i] = fVal;
         }
-    //Fliquid2 (Rain1 & Rainn products)
-    //See point 3.3.11 at page 3.43 of the manual
-    } else if(poGDS->nDataTypeCode == 37){
-        unsigned short nVal, nExp, nMantissa;
-        float fVal2=0;
-        for (i=0;i<nBlockXSize;i++){
-            nVal = CPL_LSBUINT16PTR(pszRecord+i*nDataLength);
-            nExp = nVal>>12;
-            nMantissa = nVal - (nExp<<12);
-            if (nVal == 65535)
+    // Fliquid2 (Rain1 & Rainn products)
+    // See point 3.3.11 at page 3.43 of the manual.
+    }
+    else if( poGDS->nDataTypeCode == 37 )
+    {
+        for( int i = 0; i < nBlockXSize; i++)
+        {
+            const unsigned short nVal =
+                CPL_LSBUINT16PTR(pszRecord+i*nDataLength);
+            const unsigned short nExp = nVal>>12;
+            const unsigned short nMantissa = nVal - (nExp<<12);
+            float fVal2 = 0.0f;
+            if( nVal == 65535 )
                 fVal2 = -9999.0f;
-            else if (nExp == 0)
-                fVal2 = (float) nMantissa / 1000.0f;
+            else if( nExp == 0 )
+                fVal2 = nMantissa / 1000.0f;
             else
-                fVal2 = (float)((nMantissa+4096)<<(nExp-1))/1000.0f;
+                fVal2 = ((nMantissa + 4096) << (nExp - 1)) / 1000.0f;
             ((float *) pImage)[i] = fVal2;
         }
-    //VIL2 (VIL products)
-    //See point 3.3.41 at page 3.54 of the manual
-    } else if(poGDS->nDataTypeCode == 33){
-        float fVal;
-        for (i=0;i<nBlockXSize;i++){
-            fVal = (float) CPL_LSBUINT16PTR(pszRecord+i*nDataLength);
-            if (fVal == 65535.0f)
+    // VIL2 (VIL products)
+    // See point 3.3.41 at page 3.54 of the manual.
+    }
+    else if( poGDS->nDataTypeCode == 33 )
+    {
+        for( int i = 0; i < nBlockXSize; i++)
+        {
+            float fVal =
+                static_cast<float>(CPL_LSBUINT16PTR(pszRecord+i*nDataLength));
+            if( fVal == 65535.0f )
                 ((float *) pImage)[i] = -9999.0f;
-            else if (fVal == 0)
+            else if( fVal == 0.0f )
                 ((float *) pImage)[i] = -1.0f;
             else
-                ((float *) pImage)[i] = (fVal-1)/1000.0f;
+                ((float *) pImage)[i] = (fVal-1) / 1000.0f;
         }
-    //HEIGHT (TOPS products)
-    //See point 3.3.14 at page 3.46 of the manual
-    } else if(poGDS->nDataTypeCode == 32){
-        unsigned char nVal;
-        for (i=0;i<nBlockXSize;i++){
-            nVal =  *(pszRecord+i*nDataLength) ;
-            if (nVal == 255)
+    // HEIGHT (TOPS products)
+    // See point 3.3.14 at page 3.46 of the manual.
+    }
+    else if( poGDS->nDataTypeCode == 32 )
+    {
+        for( int i = 0; i < nBlockXSize; i++)
+        {
+            unsigned char nVal = *(pszRecord+i*nDataLength);
+            if( nVal == 255 )
                 ((float *) pImage)[i] = -9999.0f;
-            else if (nVal == 0)
+            else if( nVal == 0 )
                 ((float *) pImage)[i] = -1.0f;
             else
-                ((float *) pImage)[i] = ((float) nVal - 1) / 10.0f;
+                ((float *) pImage)[i] = (nVal - 1.0f) / 10.0f;
         }
-    //VEL (Velocity 1-Byte in PPI & others)
-    //See point 3.3.37 at page 3.53 of the manual
-    } else if(poGDS->nDataTypeCode == 3){
-          float fVal;
-        for (i=0;i<nBlockXSize;i++){
-            fVal = (float) *(pszRecord+i*nDataLength);
-            if (fVal == 0.0f)
+    // VEL (Velocity 1-Byte in PPI & others)
+    // See point 3.3.37 at page 3.53 of the manual.
+    }
+    else if( poGDS->nDataTypeCode == 3 )
+    {
+        for( int i = 0; i < nBlockXSize; i++)
+        {
+            float fVal = static_cast<float>(*(pszRecord+i*nDataLength));
+            if( fVal == 0.0f )
                 fVal = -9997.0f;
-            else if(fVal == 1.0f)
+            else if( fVal == 1.0f )
                 fVal = -9998.0f;
-            else if(fVal == 255.0f)
+            else if( fVal == 255.0f )
                 fVal = -9999.0f;
             else
                 fVal = poGDS->fNyquistVelocity * (fVal - 128.0f)/127.0f;
             ((float *) pImage)[i] = fVal;
         }
-    //SHEAR (1-Byte Shear)
-    //See point 3.3.23 at page 3.39 of the manual
-    } else if(poGDS->nDataTypeCode == 35){
-        float fVal;
-        for (i=0;i<nBlockXSize;i++){
-            fVal = (float) *(pszRecord+i*nDataLength);
-            if (fVal == 0.0f)
+    // SHEAR (1-Byte Shear)
+    // See point 3.3.23 at page 3.39 of the manual.
+    }
+    else if( poGDS->nDataTypeCode == 35 )
+    {
+        for( int i = 0; i < nBlockXSize; i++)
+        {
+            float fVal = static_cast<float>(*(pszRecord+i*nDataLength));
+            if( fVal == 0.0f )
                 fVal = -9998.0f;
-            else if (fVal == 255.0f)
+            else if( fVal == 255.0f )
                 fVal = -9999.0f;
             else
                 fVal = (fVal - 128.0f) * 0.2f;
             ((float *) pImage)[i] = fVal;
         }
-
     }
 
     return CE_None;
@@ -331,12 +350,9 @@ CPLErr IRISRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 CPLErr IRISRasterBand::SetNoDataValue( double dfNoData )
 
 {
-    IRISDataset *poGDS = (IRISDataset *) poDS;
-   // if( poGDS->bNoDataSet && poGDS->dfNoDataValue == dfNoData )
-   //   return CE_None;
-
+    IRISDataset *poGDS = static_cast<IRISDataset *>(poDS);
 
-    poGDS->bNoDataSet = TRUE;
+    poGDS->bNoDataSet = true;
     poGDS->dfNoDataValue = dfNoData;
 
     return CE_None;
@@ -349,8 +365,7 @@ CPLErr IRISRasterBand::SetNoDataValue( double dfNoData )
 double IRISRasterBand::GetNoDataValue( int * pbSuccess )
 
 {
-    IRISDataset *poGDS = (IRISDataset *) poDS;
-
+    IRISDataset *poGDS = static_cast<IRISDataset *>(poDS);
 
     if( poGDS->bNoDataSet )
     {
@@ -363,7 +378,6 @@ double IRISRasterBand::GetNoDataValue( int * pbSuccess )
     return GDALPamRasterBand::GetNoDataValue( pbSuccess );
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                              IRISDataset                             */
@@ -374,11 +388,18 @@ double IRISRasterBand::GetNoDataValue( int * pbSuccess )
 /*                            IRISDataset()                             */
 /************************************************************************/
 
-IRISDataset::IRISDataset()
-    : fp(NULL), bNoDataSet(0), dfNoDataValue(0.0), nProductCode(0),
-      nDataTypeCode(0), nProjectionCode(0), fNyquistVelocity(0.0),
-      pszSRS_WKT(NULL), bHasLoadedProjection(FALSE)
+IRISDataset::IRISDataset() :
+    fp(NULL),
+    bNoDataSet(false),
+    dfNoDataValue(0.0),
+    nProductCode(0),
+    nDataTypeCode(0),
+    nProjectionCode(0),
+    fNyquistVelocity(0.0),
+    pszSRS_WKT(NULL),
+    bHasLoadedProjection(false)
 {
+    std::fill_n(abyHeader, CPL_ARRAYSIZE(abyHeader), 0);
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -405,86 +426,107 @@ IRISDataset::~IRISDataset()
 /************************************************************************/
 void IRISDataset::LoadProjection()
 {
-    bHasLoadedProjection = TRUE;
-    float fEquatorialRadius = float( (CPL_LSBUINT32PTR (abyHeader+220+320+12)))/100; //They give it in cm
-    float fInvFlattening = float( (CPL_LSBUINT32PTR (abyHeader+224+320+12)))/1000000; //Point 3.2.27 pag 3-15
-    float fFlattening;
-    float fPolarRadius;
-
-    if(fEquatorialRadius == 0){ // if Radius is 0, change to 6371000 Point 3.2.27 pag 3-15 (old IRIS versions)
-        fEquatorialRadius = 6371000;
+    bHasLoadedProjection = true;
+    // They give the radius in cm.
+    float fEquatorialRadius = CPL_LSBUINT32PTR(abyHeader+220+320+12) / 100.0f;
+    // Point 3.2.27 pag 3-15.
+    float fInvFlattening = CPL_LSBUINT32PTR(abyHeader+224+320+12) / 1000000.0f;
+    float fFlattening = 0.0f;
+    float fPolarRadius = 0.0f;
+
+    if( fEquatorialRadius == 0.0f )
+    {
+        // If Radius is 0, change to 6371000 Point 3.2.27 pag 3-15 (old IRIS
+        // versions).
+        fEquatorialRadius = 6371000.0f;
         fPolarRadius = fEquatorialRadius;
-        fInvFlattening = 0;
-        fFlattening = 0;
-    } else {
-        if (fInvFlattening == 0){ //When inverse flattening is infinite, they use 0
-            fFlattening = 0;
+        fInvFlattening = 0.0f;
+        fFlattening = 0.0f;
+    }
+    else
+    {
+        if( fInvFlattening == 0.0f )
+        {
+            // When inverse flattening is infinite, they use 0.
+            fFlattening = 0.0f;
             fPolarRadius = fEquatorialRadius;
-        } else {
-            fFlattening = 1/fInvFlattening;
-            fPolarRadius = fEquatorialRadius * (1-fFlattening);
+        }
+        else
+        {
+            fFlattening = 1.0f / fInvFlattening;
+            fPolarRadius = fEquatorialRadius * (1.0f - fFlattening);
         }
     }
 
-    float fCenterLon = 360 * float((CPL_LSBUINT32PTR (abyHeader+112+320+12))) / 4294967295LL;
-    float fCenterLat = 360 * float((CPL_LSBUINT32PTR (abyHeader+108+320+12))) / 4294967295LL;
-
-    float fProjRefLon = 360 * float((CPL_LSBUINT32PTR (abyHeader+244+320+12))) / 4294967295LL;
-    float fProjRefLat = 360 * float((CPL_LSBUINT32PTR (abyHeader+240+320+12))) / 4294967295LL;
+    // TODO(schwehr): Document 4294967295.
+    const float fCenterLon =
+        static_cast<float>(CPL_LSBUINT32PTR(abyHeader+112+320+12) * 360.0 / 4294967295UL);
+    const float fCenterLat =
+        static_cast<float>(CPL_LSBUINT32PTR(abyHeader+108+320+12) * 360.0 / 4294967295UL);
 
-    float fRadarLocX, fRadarLocY, fScaleX, fScaleY;
+    const float fProjRefLon =
+        static_cast<float>(CPL_LSBUINT32PTR(abyHeader+244+320+12) * 360.0 / 4294967295UL);
+    const float fProjRefLat =
+        static_cast<float>(CPL_LSBUINT32PTR(abyHeader+240+320+12) * 360.0 / 4294967295UL);
 
-    fRadarLocX = float (CPL_LSBSINT32PTR (abyHeader + 112 + 12 )) / 1000;
-    fRadarLocY = float (CPL_LSBSINT32PTR (abyHeader + 116 + 12 )) / 1000;
+    const float fRadarLocX = CPL_LSBSINT32PTR(abyHeader + 112 + 12 ) / 1000.0f;
+    const float fRadarLocY = CPL_LSBSINT32PTR(abyHeader + 116 + 12 ) / 1000.0f;
 
-    fScaleX = float (CPL_LSBSINT32PTR (abyHeader + 88 + 12 )) / 100;
-    fScaleY = float (CPL_LSBSINT32PTR (abyHeader + 92 + 12 )) / 100;
+    const float fScaleX = CPL_LSBSINT32PTR(abyHeader + 88 + 12 ) / 100.0f;
+    const float fScaleY = CPL_LSBSINT32PTR(abyHeader + 92 + 12 ) / 100.0f;
 
     OGRSpatialReference oSRSOut;
 
-    ////MERCATOR PROJECTION
-    if(EQUAL(aszProjections[nProjectionCode],"Mercator")){
-        OGRCoordinateTransformation *poTransform = NULL;
-        OGRSpatialReference oSRSLatLon;
+    // Mercator projection.
+    if( EQUAL(aszProjections[nProjectionCode],"Mercator") )
+    {
+        oSRSOut.SetGeogCS(
+            "unnamed ellipse",
+            "unknown",
+            "unnamed",
+            fEquatorialRadius, fInvFlattening,
+            "Greenwich", 0.0,
+            "degree", 0.0174532925199433);
 
-        oSRSOut.SetGeogCS("unnamed ellipse",
-                        "unknown",
-                        "unnamed",
-                        fEquatorialRadius, fInvFlattening,
-                        "Greenwich", 0.0,
-                        "degree", 0.0174532925199433);
-
-        oSRSOut.SetMercator(fProjRefLat,fProjRefLon,1,0,0);
-	oSRSOut.exportToWkt(&pszSRS_WKT);
-
-        //The center coordinates are given in LatLon on the defined ellipsoid. Necessary to calculate geotransform.
-
-        oSRSLatLon.SetGeogCS("unnamed ellipse",
-                        "unknown",
-                        "unnamed",
-                        fEquatorialRadius, fInvFlattening,
-                        "Greenwich", 0.0,
-                        "degree", 0.0174532925199433);
-
-        poTransform = OGRCreateCoordinateTransformation( &oSRSLatLon,
-                                                  &oSRSOut );
-        std::pair <double,double> oPositionX2 = GeodesicCalculation(fCenterLat, fCenterLon, 90, fScaleX, fEquatorialRadius, fPolarRadius, fFlattening);
-        std::pair <double,double> oPositionY2 = GeodesicCalculation(fCenterLat, fCenterLon, 0, fScaleY, fEquatorialRadius, fPolarRadius, fFlattening);
-
-        double dfLon2, dfLat2;
-        dfLon2 = oPositionX2.first;
-        dfLat2 = oPositionY2.second;
-        double dfX, dfY, dfX2, dfY2;
-        dfX = fCenterLon ;
-        dfY = fCenterLat ;
-        dfX2 = dfLon2;
-        dfY2 = dfLat2;
+        oSRSOut.SetMercator(fProjRefLat, fProjRefLon, 1.0, 0.0, 0.0);
+        oSRSOut.exportToWkt(&pszSRS_WKT);
 
+        // The center coordinates are given in LatLon on the defined
+        // ellipsoid. Necessary to calculate geotransform.
+
+        OGRSpatialReference oSRSLatLon;
+        oSRSLatLon.SetGeogCS(
+            "unnamed ellipse",
+            "unknown",
+            "unnamed",
+            fEquatorialRadius, fInvFlattening,
+            "Greenwich", 0.0,
+            "degree", 0.0174532925199433);
+
+        OGRCoordinateTransformation *poTransform =
+            OGRCreateCoordinateTransformation( &oSRSLatLon, &oSRSOut );
+
+        const std::pair<double, double> oPositionX2 =
+            GeodesicCalculation(
+                fCenterLat, fCenterLon, 90.0f, fScaleX,
+                fEquatorialRadius, fPolarRadius, fFlattening);
+        const std::pair<double, double> oPositionY2 =
+            GeodesicCalculation(
+                fCenterLat, fCenterLon, 0.0f, fScaleY,
+                fEquatorialRadius, fPolarRadius, fFlattening);
+
+        const double dfLon2 = oPositionX2.first;
+        const double dfLat2 = oPositionY2.second;
+
+        double dfX = fCenterLon ;
+        double dfY = fCenterLat ;
         if( poTransform == NULL || !poTransform->Transform( 1, &dfX, &dfY ) )
-             CPLError( CE_Failure, CPLE_None, "Transformation Failed\n" );
+             CPLError( CE_Failure, CPLE_None, "Transformation Failed" );
 
+        double dfX2 = dfLon2;
+        double dfY2 = dfLat2;
         if( poTransform == NULL || !poTransform->Transform( 1, &dfX2, &dfY2 ) )
-             CPLError( CE_Failure, CPLE_None, "Transformation Failed\n" );
+             CPLError( CE_Failure, CPLE_None, "Transformation Failed" );
 
         adfGeoTransform[0] = dfX - (fRadarLocX * (dfX2 - dfX));
         adfGeoTransform[1] = dfX2 - dfX;
@@ -494,16 +536,17 @@ void IRISDataset::LoadProjection()
         adfGeoTransform[5] = -1*(dfY2 - dfY);
 
         delete poTransform;
-
-    }else if(EQUAL(aszProjections[nProjectionCode],"Azimutal equidistant")){
-
-        oSRSOut.SetGeogCS("unnamed ellipse",
-                        "unknown",
-                        "unnamed",
-                        fEquatorialRadius, fInvFlattening,
-                        "Greenwich", 0.0,
-                        "degree", 0.0174532925199433);
-        oSRSOut.SetAE(fProjRefLat,fProjRefLon,0,0);
+    }
+    else if( EQUAL(aszProjections[nProjectionCode],"Azimutal equidistant") )
+    {
+        oSRSOut.SetGeogCS(
+            "unnamed ellipse",
+            "unknown",
+            "unnamed",
+            fEquatorialRadius, fInvFlattening,
+            "Greenwich", 0.0,
+            "degree", 0.0174532925199433);
+        oSRSOut.SetAE(fProjRefLat, fProjRefLon, 0.0, 0.0);
         oSRSOut.exportToWkt(&pszSRS_WKT) ;
         adfGeoTransform[0] = -1*(fRadarLocX*fScaleX);
         adfGeoTransform[1] = fScaleX;
@@ -511,8 +554,11 @@ void IRISDataset::LoadProjection()
         adfGeoTransform[3] = fRadarLocY*fScaleY;
         adfGeoTransform[4] = 0.0;
         adfGeoTransform[5] = -1*fScaleY;
-    //When the projection is different from Mercator or Azimutal equidistant, we set a standard geotransform
-    } else {
+        // When the projection is different from Mercator or Azimutal
+        // equidistant, we set a standard geotransform.
+    }
+    else
+    {
         adfGeoTransform[0] = -1*(fRadarLocX*fScaleX);
         adfGeoTransform[1] = fScaleX;
         adfGeoTransform[2] = 0.0;
@@ -539,23 +585,29 @@ void IRISDataset::LoadProjection()
 /*       http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf                                             */
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */
 
-std::pair <double,double> IRISDataset::GeodesicCalculation(float fLat, float fLon, float fAngle, float fDist, float fEquatorialRadius, float fPolarRadius, float fFlattening)
+std::pair<double, double>
+IRISDataset::GeodesicCalculation(
+    float fLat, float fLon, float fAngle, float fDist, float fEquatorialRadius,
+    float fPolarRadius, float fFlattening )
 {
-    std::pair <double,double> oOutput;
-    double dfAlpha1 = DEG2RAD * fAngle;
-    double dfSinAlpha1 = sin(dfAlpha1);
-    double dfCosAlpha1 = cos(dfAlpha1);
-
-    double dfTanU1 = (1-fFlattening) * tan(fLat*DEG2RAD);
-    double dfCosU1 = 1 / sqrt((1 + dfTanU1*dfTanU1));
-    double dfSinU1 = dfTanU1*dfCosU1;
-
-    double dfSigma1 = atan2(dfTanU1, dfCosAlpha1);
-    double dfSinAlpha = dfCosU1 * dfSinAlpha1;
-    double dfCosSqAlpha = 1 - dfSinAlpha*dfSinAlpha;
-    double dfUSq = dfCosSqAlpha * (fEquatorialRadius*fEquatorialRadius - fPolarRadius*fPolarRadius) / (fPolarRadius*fPolarRadius);
-    double dfA = 1 + dfUSq/16384*(4096+dfUSq*(-768+dfUSq*(320-175*dfUSq)));
-    double dfB = dfUSq/1024 * (256+dfUSq*(-128+dfUSq*(74-47*dfUSq)));
+    const double dfAlpha1 = DEG2RAD * fAngle;
+    const double dfSinAlpha1 = sin(dfAlpha1);
+    const double dfCosAlpha1 = cos(dfAlpha1);
+
+    const double dfTanU1 = (1-fFlattening) * tan(fLat*DEG2RAD);
+    const double dfCosU1 = 1 / sqrt((1 + dfTanU1*dfTanU1));
+    const double dfSinU1 = dfTanU1*dfCosU1;
+
+    const double dfSigma1 = atan2(dfTanU1, dfCosAlpha1);
+    const double dfSinAlpha = dfCosU1 * dfSinAlpha1;
+    const double dfCosSqAlpha = 1 - dfSinAlpha*dfSinAlpha;
+    const double dfUSq =
+        dfCosSqAlpha * (fEquatorialRadius*fEquatorialRadius -
+                        fPolarRadius*fPolarRadius) /
+        (fPolarRadius*fPolarRadius);
+    const double dfA =
+        1 + dfUSq/16384*(4096+dfUSq*(-768+dfUSq*(320-175*dfUSq)));
+    const double dfB = dfUSq/1024 * (256+dfUSq*(-128+dfUSq*(74-47*dfUSq)));
 
     double dfSigma = fDist / (fPolarRadius*dfA);
     double dfSigmaP = 2*M_PI;
@@ -563,32 +615,41 @@ std::pair <double,double> IRISDataset::GeodesicCalculation(float fLat, float fLo
     double dfSinSigma = 0.0;
     double dfCosSigma = 0.0;
     double dfCos2SigmaM = 0.0;
-    double dfDeltaSigma;
 
-    while (fabs(dfSigma-dfSigmaP) > 1e-12) {
+    while( fabs(dfSigma-dfSigmaP) > 1e-12 )
+    {
         dfCos2SigmaM = cos(2*dfSigma1 + dfSigma);
         dfSinSigma = sin(dfSigma);
         dfCosSigma = cos(dfSigma);
-        dfDeltaSigma = dfB*dfSinSigma*(dfCos2SigmaM+dfB/4*(dfCosSigma*(-1+2*dfCos2SigmaM*dfCos2SigmaM)-
-          dfB/6*dfCos2SigmaM*(-3+4*dfSinSigma*dfSinSigma)*(-3+4*dfCos2SigmaM*dfCos2SigmaM)));
+        const double dfDeltaSigma =
+            dfB*dfSinSigma*(dfCos2SigmaM+dfB/4*(
+                dfCosSigma*(-1+2*dfCos2SigmaM*dfCos2SigmaM) -
+                dfB/6*dfCos2SigmaM*(-3+4*dfSinSigma*dfSinSigma)*
+                (-3+4*dfCos2SigmaM*dfCos2SigmaM)));
         dfSigmaP = dfSigma;
         dfSigma = fDist / (fPolarRadius*dfA) + dfDeltaSigma;
     }
 
-    double dfTmp = dfSinU1*dfSinSigma - dfCosU1*dfCosSigma*dfCosAlpha1;
-    double dfLat2 = atan2(dfSinU1*dfCosSigma + dfCosU1*dfSinSigma*dfCosAlpha1,
-      (1-fFlattening)*sqrt(dfSinAlpha*dfSinAlpha + dfTmp*dfTmp));
-    double dfLambda = atan2(dfSinSigma*dfSinAlpha1, dfCosU1*dfCosSigma - dfSinU1*dfSinSigma*dfCosAlpha1);
-    double dfC = fFlattening/16*dfCosSqAlpha*(4+fFlattening*(4-3*dfCosSqAlpha));
-    double dfL = dfLambda - (1-dfC) * fFlattening * dfSinAlpha *
-      (dfSigma + dfC*dfSinSigma*(dfCos2SigmaM+dfC*dfCosSigma*(-1+2*dfCos2SigmaM*dfCos2SigmaM)));
+    const double dfTmp = dfSinU1*dfSinSigma - dfCosU1*dfCosSigma*dfCosAlpha1;
+    const double dfLat2 =
+        atan2(dfSinU1*dfCosSigma + dfCosU1*dfSinSigma*dfCosAlpha1,
+              (1-fFlattening)*sqrt(dfSinAlpha*dfSinAlpha + dfTmp*dfTmp));
+    const double dfLambda =
+        atan2(dfSinSigma*dfSinAlpha1,
+              dfCosU1*dfCosSigma - dfSinU1*dfSinSigma*dfCosAlpha1);
+    const double dfC =
+        fFlattening/16*dfCosSqAlpha*(4+fFlattening*(4-3*dfCosSqAlpha));
+    const double dfL = dfLambda - (1-dfC) * fFlattening * dfSinAlpha *
+        (dfSigma + dfC*dfSinSigma*(dfCos2SigmaM+dfC*dfCosSigma*
+                                   (-1+2*dfCos2SigmaM*dfCos2SigmaM)));
     double dfLon2 = fLon*DEG2RAD+dfL;
-    if (dfLon2 > M_PI)
-        dfLon2 = dfLon2 - 2*M_PI;
-    if (dfLon2 < -1*M_PI)
-        dfLon2 = dfLon2 + 2*M_PI;
-    oOutput.first = dfLon2*RAD2DEG;
-    oOutput.second = dfLat2*RAD2DEG;
+
+    if( dfLon2 > M_PI )
+        dfLon2 = dfLon2 - 2 * M_PI;
+    if( dfLon2 < -1*M_PI )
+        dfLon2 = dfLon2 + 2 * M_PI;
+
+    std::pair<double, double> oOutput(dfLon2 * RAD2DEG, dfLat2 * RAD2DEG);
 
     return oOutput;
 }
@@ -600,7 +661,7 @@ std::pair <double,double> IRISDataset::GeodesicCalculation(float fLat, float fLo
 CPLErr IRISDataset::GetGeoTransform( double * padfTransform )
 
 {
-    if (!bHasLoadedProjection)
+    if( !bHasLoadedProjection )
         LoadProjection();
     memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
     return CE_None;
@@ -610,8 +671,9 @@ CPLErr IRISDataset::GetGeoTransform( double * padfTransform )
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char *IRISDataset::GetProjectionRef(){
-    if (!bHasLoadedProjection)
+const char *IRISDataset::GetProjectionRef()
+{
+    if( !bHasLoadedProjection )
         LoadProjection();
     return pszSRS_WKT;
 }
@@ -623,21 +685,18 @@ const char *IRISDataset::GetProjectionRef(){
 int IRISDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-
 /* -------------------------------------------------------------------- */
 /*      Confirm that the file is an IRIS file                           */
 /* -------------------------------------------------------------------- */
-    // TODO: Translate to English.
-    //Si no el posem, peta al fer el translate, quan s'obre Identify des de GDALIdentifyDriver
     if( poOpenInfo->nHeaderBytes < 640 )
         return FALSE;
 
+    const short nId1 = CPL_LSBSINT16PTR(poOpenInfo->pabyHeader);
+    const short nId2 = CPL_LSBSINT16PTR(poOpenInfo->pabyHeader + 12);
+    unsigned short nType = CPL_LSBUINT16PTR(poOpenInfo->pabyHeader + 24);
 
-    short nId1 = CPL_LSBSINT16PTR(poOpenInfo->pabyHeader);
-    short nId2 = CPL_LSBSINT16PTR(poOpenInfo->pabyHeader+12);
-    unsigned short nType = CPL_LSBUINT16PTR (poOpenInfo->pabyHeader+24);
-
-    /*Check if the two headers are 27 (product hdr) & 26 (product configuration), and the product type is in the range 1 -> 34*/
+    // Check if the two headers are 27 (product hdr) & 26 (product
+    // configuration), and the product type is in the range 1 -> 34.
     if( !(nId1 == 27 && nId2 == 26 && nType > 0 && nType < 35) )
         return FALSE;
 
@@ -648,10 +707,10 @@ int IRISDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                             FillString()                             */
 /************************************************************************/
 
-static void FillString(char* szBuffer, size_t nBufferSize, void* pSrcBuffer)
+static void FillString( char* szBuffer, size_t nBufferSize, void* pSrcBuffer )
 {
-    for(size_t i = 0; i < nBufferSize - 1; i++)
-        szBuffer[i] = ((char*)pSrcBuffer)[i];
+    for( size_t i = 0; i < nBufferSize - 1; i++ )
+        szBuffer[i] = static_cast<char *>(pSrcBuffer)[i];
     szBuffer[nBufferSize-1] = '\0';
 }
 
@@ -662,7 +721,7 @@ static void FillString(char* szBuffer, size_t nBufferSize, void* pSrcBuffer)
 GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    if (!Identify(poOpenInfo))
+    if( !Identify(poOpenInfo) )
         return NULL;
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
@@ -671,7 +730,7 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "The IRIS driver does not support update access to existing"
-                  " datasets.\n" );
+                  " datasets." );
         return NULL;
     }
 
@@ -681,7 +740,7 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
     IRISDataset *poDS = new IRISDataset();
 
     poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
-    if (poDS->fp == NULL)
+    if( poDS->fp == NULL )
     {
         delete poDS;
         return NULL;
@@ -691,14 +750,14 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Read the header.                                                */
 /* -------------------------------------------------------------------- */
     VSIFReadL( poDS->abyHeader, 1, 640, poDS->fp );
-    int nXSize = CPL_LSBSINT32PTR(poDS->abyHeader+100+12);
-    int nYSize = CPL_LSBSINT32PTR(poDS->abyHeader+104+12);
-    int nNumBands = CPL_LSBSINT32PTR(poDS->abyHeader+108+12);
+    const int nXSize = CPL_LSBSINT32PTR(poDS->abyHeader+100+12);
+    const int nYSize = CPL_LSBSINT32PTR(poDS->abyHeader+104+12);
+    const int nNumBands = CPL_LSBSINT32PTR(poDS->abyHeader+108+12);
 
     poDS->nRasterXSize = nXSize;
 
     poDS->nRasterYSize = nYSize;
-    if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
+    if( poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid dimensions : %d x %d",
@@ -716,230 +775,336 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Setting the Metadata                                            */
 /* -------------------------------------------------------------------- */
-    //See point 3.2.26 at page 3.12 of the manual
-    poDS->nProductCode = CPL_LSBUINT16PTR (poDS->abyHeader+12+12);
-    poDS->SetMetadataItem( "PRODUCT_ID", CPLString().Printf("%d", poDS->nProductCode ));
-    if( poDS->nProductCode >= ARRAY_ELEMENT_COUNT(poDS->aszProductNames) )
+    // See point 3.2.26 at page 3.12 of the manual.
+    poDS->nProductCode = CPL_LSBUINT16PTR(poDS->abyHeader + 12 + 12);
+    poDS->SetMetadataItem( "PRODUCT_ID",
+                           CPLString().Printf("%d", poDS->nProductCode ));
+    if( poDS->nProductCode >= CPL_ARRAYSIZE(aszProductNames) )
     {
         delete poDS;
         return NULL;
     }
 
-    poDS->SetMetadataItem( "PRODUCT",poDS->aszProductNames[poDS->nProductCode]);
+    poDS->SetMetadataItem("PRODUCT", aszProductNames[poDS->nProductCode]);
 
-    poDS->nDataTypeCode = CPL_LSBUINT16PTR (poDS->abyHeader+130+12);
-    if( poDS->nDataTypeCode >= ARRAY_ELEMENT_COUNT(poDS->aszDataTypeCodes) )
+    poDS->nDataTypeCode = CPL_LSBUINT16PTR(poDS->abyHeader+130+12);
+    if( poDS->nDataTypeCode >= CPL_ARRAYSIZE(aszDataTypeCodes) )
     {
         delete poDS;
         return NULL;
     }
-    poDS->SetMetadataItem( "DATA_TYPE_CODE",poDS->aszDataTypeCodes[poDS->nDataTypeCode]);
+    poDS->SetMetadataItem("DATA_TYPE_CODE",
+                          aszDataTypeCodes[poDS->nDataTypeCode]);
 
-    if( poDS->nDataTypeCode >= ARRAY_ELEMENT_COUNT(poDS->aszDataTypes) )
+    if( poDS->nDataTypeCode >= CPL_ARRAYSIZE(aszDataTypes) )
     {
         delete poDS;
         return NULL;
     }
-    poDS->SetMetadataItem( "DATA_TYPE",poDS->aszDataTypes[poDS->nDataTypeCode]);
+    poDS->SetMetadataItem("DATA_TYPE",
+                          aszDataTypes[poDS->nDataTypeCode]);
 
-    unsigned short nDataTypeInputCode = CPL_LSBUINT16PTR (poDS->abyHeader+144+12);
-    if( nDataTypeInputCode >= ARRAY_ELEMENT_COUNT(poDS->aszDataTypeCodes) )
+    const unsigned short nDataTypeInputCode =
+        CPL_LSBUINT16PTR(poDS->abyHeader+144+12);
+    if( nDataTypeInputCode >= CPL_ARRAYSIZE(aszDataTypeCodes) )
     {
         delete poDS;
         return NULL;
     }
-    poDS->SetMetadataItem( "DATA_TYPE_INPUT_CODE",poDS->aszDataTypeCodes[nDataTypeInputCode]);
+    poDS->SetMetadataItem("DATA_TYPE_INPUT_CODE",
+                          aszDataTypeCodes[nDataTypeInputCode]);
 
-    unsigned short nDataTypeInput = CPL_LSBUINT16PTR (poDS->abyHeader+144+12);
-    if( nDataTypeInput >= ARRAY_ELEMENT_COUNT(poDS->aszDataTypes) )
+    const unsigned short nDataTypeInput =
+        CPL_LSBUINT16PTR(poDS->abyHeader+144+12);
+    if( nDataTypeInput >= CPL_ARRAYSIZE(aszDataTypes) )
     {
         delete poDS;
         return NULL;
     }
-    poDS->SetMetadataItem( "DATA_TYPE_INPUT",poDS->aszDataTypes[nDataTypeInput]);
+    poDS->SetMetadataItem("DATA_TYPE_INPUT",
+                          aszDataTypes[nDataTypeInput]);
 
-    poDS->nProjectionCode = * (unsigned char *) (poDS->abyHeader+146+12);
-    if( poDS->nProjectionCode >= ARRAY_ELEMENT_COUNT(poDS->aszProjections) )
+    poDS->nProjectionCode =
+        * static_cast<unsigned char *>(poDS->abyHeader+146+12);
+    if( poDS->nProjectionCode >= CPL_ARRAYSIZE(aszProjections) )
     {
         delete poDS;
         return NULL;
     }
 
-    ////TIMES
-    int nSeconds = CPL_LSBSINT32PTR(poDS->abyHeader+20+12);
+    // Times.
+    {
+        const int nSeconds = CPL_LSBSINT32PTR(poDS->abyHeader+20+12);
 
-    int nHour =  (nSeconds - (nSeconds%3600)) /3600;
-    int nMinute = ((nSeconds - nHour * 3600) - (nSeconds - nHour * 3600)%60)/ 60;
-    int nSecond = nSeconds - nHour * 3600 - nMinute * 60;
+        const int nHour = (nSeconds - (nSeconds % 3600)) / 3600;
+        const int nMinute =
+            ((nSeconds - nHour * 3600) - (nSeconds - nHour * 3600) % 60) / 60;
+        const int nSecond = nSeconds - nHour * 3600 - nMinute * 60;
 
-    short nYear = CPL_LSBSINT16PTR(poDS->abyHeader+26+12);
-    short nMonth = CPL_LSBSINT16PTR(poDS->abyHeader+28+12);
-    short nDay = CPL_LSBSINT16PTR(poDS->abyHeader+30+12);
+        const short nYear = CPL_LSBSINT16PTR(poDS->abyHeader+26+12);
+        const short nMonth = CPL_LSBSINT16PTR(poDS->abyHeader+28+12);
+        const short nDay = CPL_LSBSINT16PTR(poDS->abyHeader+30+12);
 
-    poDS->SetMetadataItem( "TIME_PRODUCT_GENERATED", CPLString().Printf("%d-%02d-%02d %02d:%02d:%02d", nYear, nMonth, nDay, nHour, nMinute, nSecond ) );
+        poDS->SetMetadataItem(
+            "TIME_PRODUCT_GENERATED",
+            CPLString().Printf("%d-%02d-%02d %02d:%02d:%02d",
+                               nYear, nMonth, nDay, nHour, nMinute, nSecond));
+    }
 
-    nSeconds = CPL_LSBSINT32PTR(poDS->abyHeader+32+12);
+    {
+        const int nSeconds = CPL_LSBSINT32PTR(poDS->abyHeader+32+12);
 
-    nHour =  (nSeconds - (nSeconds%3600)) /3600;
-    nMinute = ((nSeconds - nHour * 3600) - (nSeconds - nHour * 3600)%60)/ 60;
-    nSecond = nSeconds - nHour * 3600 - nMinute * 60;
+        const int nHour = (nSeconds - (nSeconds % 3600)) / 3600;
+        const int nMinute =
+            ((nSeconds - nHour * 3600) - (nSeconds - nHour * 3600) % 60) / 60;
+        const int nSecond = nSeconds - nHour * 3600 - nMinute * 60;
 
-    nYear = CPL_LSBSINT16PTR(poDS->abyHeader+26+12);
-    nMonth = CPL_LSBSINT16PTR(poDS->abyHeader+28+12);
-    nDay = CPL_LSBSINT16PTR(poDS->abyHeader+30+12);
+        const short nYear = CPL_LSBSINT16PTR(poDS->abyHeader+26+12);
+        const short nMonth = CPL_LSBSINT16PTR(poDS->abyHeader+28+12);
+        const short nDay = CPL_LSBSINT16PTR(poDS->abyHeader+30+12);
 
-    poDS->SetMetadataItem( "TIME_INPUT_INGEST_SWEEP", CPLString().Printf("%d-%02d-%02d %02d:%02d:%02d", nYear, nMonth, nDay, nHour, nMinute, nSecond ) );
+        poDS->SetMetadataItem(
+            "TIME_INPUT_INGEST_SWEEP",
+            CPLString().Printf("%d-%02d-%02d %02d:%02d:%02d",
+                               nYear, nMonth, nDay, nHour, nMinute, nSecond));
+    }
 
-    ///Site and task information
+    // Site and task information.
 
-    char szSiteName[17] = ""; //Must have one extra char for string end!
-    char szVersionName[9] = "";
+    char szSiteName[17] = {};  // Must have one extra char for string end.
+    char szVersionName[9] = {};
 
     FillString(szSiteName, sizeof(szSiteName), poDS->abyHeader+320+12);
     FillString(szVersionName, sizeof(szVersionName), poDS->abyHeader+16+320+12);
-    poDS->SetMetadataItem( "PRODUCT_SITE_NAME",szSiteName);
-    poDS->SetMetadataItem( "PRODUCT_SITE_IRIS_VERSION",szVersionName);
+    poDS->SetMetadataItem("PRODUCT_SITE_NAME", szSiteName);
+    poDS->SetMetadataItem("PRODUCT_SITE_IRIS_VERSION", szVersionName);
 
     FillString(szSiteName, sizeof(szSiteName), poDS->abyHeader+90+320+12);
     FillString(szVersionName, sizeof(szVersionName), poDS->abyHeader+24+320+12);
-    poDS->SetMetadataItem( "INGEST_SITE_NAME",szSiteName);
-    poDS->SetMetadataItem( "INGEST_SITE_IRIS_VERSION",szVersionName);
+    poDS->SetMetadataItem("INGEST_SITE_NAME", szSiteName);
+    poDS->SetMetadataItem("INGEST_SITE_IRIS_VERSION", szVersionName);
 
     FillString(szSiteName, sizeof(szSiteName), poDS->abyHeader+74+320+12);
-    poDS->SetMetadataItem( "INGEST_HARDWARE_NAME",szSiteName);
+    poDS->SetMetadataItem("INGEST_HARDWARE_NAME", szSiteName);
 
-    char szConfigFile[13] = "";
+    char szConfigFile[13] = {};
     FillString(szConfigFile, sizeof(szConfigFile), poDS->abyHeader+62+12);
-    poDS->SetMetadataItem( "PRODUCT_CONFIGURATION_NAME",szConfigFile);
+    poDS->SetMetadataItem("PRODUCT_CONFIGURATION_NAME", szConfigFile);
 
-    char szTaskName[13] = "";
+    char szTaskName[13] = {};
     FillString(szTaskName, sizeof(szTaskName), poDS->abyHeader+74+12);
-    poDS->SetMetadataItem( "TASK_NAME",szTaskName);
+    poDS->SetMetadataItem("TASK_NAME", szTaskName);
 
     const short nRadarHeight = CPL_LSBSINT16PTR(poDS->abyHeader+284+320+12);
-    poDS->SetMetadataItem( "RADAR_HEIGHT",CPLString().Printf("%d m",nRadarHeight));
+    poDS->SetMetadataItem("RADAR_HEIGHT",
+                          CPLString().Printf("%d m", nRadarHeight));
+    // Ground height over the sea level.
     const short nGroundHeight = CPL_LSBSINT16PTR(poDS->abyHeader+118+320+12);
-    poDS->SetMetadataItem( "GROUND_HEIGHT",CPLString().Printf("%d m",nRadarHeight-nGroundHeight)); //Ground height over the sea level
-
-    unsigned short nFlags = CPL_LSBUINT16PTR (poDS->abyHeader+86+12);
-    //Get eleventh bit
-    nFlags=nFlags<<4;
-    nFlags=nFlags>>15;
-    if (nFlags == 1){
-        poDS->SetMetadataItem( "COMPOSITED_PRODUCT","YES");
-        unsigned int compositedMask = CPL_LSBUINT32PTR (poDS->abyHeader+232+320+12);
-        poDS->SetMetadataItem( "COMPOSITED_PRODUCT_MASK",CPLString().Printf("0x%08x",compositedMask));
-    } else{
+    poDS->SetMetadataItem(
+        "GROUND_HEIGHT",
+        CPLString().Printf("%d m", nRadarHeight-nGroundHeight));
+
+    unsigned short nFlags = CPL_LSBUINT16PTR(poDS->abyHeader + 86 + 12);
+    // Get eleventh bit.
+    nFlags = nFlags << 4;
+    nFlags = nFlags >> 15;
+    if( nFlags == 1 )
+    {
+        poDS->SetMetadataItem("COMPOSITED_PRODUCT", "YES");
+        const unsigned int compositedMask =
+            CPL_LSBUINT32PTR(poDS->abyHeader + 232 + 320 + 12);
+        poDS->SetMetadataItem(
+            "COMPOSITED_PRODUCT_MASK",
+            CPLString().Printf("0x%08x", compositedMask));
+    }
+    else
+    {
         poDS->SetMetadataItem( "COMPOSITED_PRODUCT","NO");
     }
 
-    //Wave values
-    poDS->SetMetadataItem( "PRF",CPLString().Printf("%d Hz",CPL_LSBSINT32PTR(poDS->abyHeader+120+320+12)));
-    poDS->SetMetadataItem( "WAVELENGTH",CPLString().Printf("%4.2f cm",(float) CPL_LSBSINT32PTR(poDS->abyHeader+148+320+12)/100));
-    const unsigned short nPolarizationType = CPL_LSBUINT16PTR (poDS->abyHeader+172+320+12);
-    float fNyquist = (CPL_LSBSINT32PTR(poDS->abyHeader+120+320+12))*((float) CPL_LSBSINT32PTR(poDS->abyHeader+148+320+12)/10000)/4; //See section 3.3.37 & 3.2.54
-    if (nPolarizationType == 1)
-        fNyquist = fNyquist * 2;
-    else if(nPolarizationType == 2)
-        fNyquist = fNyquist * 3;
-    else if(nPolarizationType == 3)
-        fNyquist = fNyquist * 4;
+    // Wave values.
+    poDS->SetMetadataItem(
+        "PRF",
+        CPLString().Printf("%d Hz",
+                           CPL_LSBSINT32PTR(poDS->abyHeader+120+320+12)));
+    poDS->SetMetadataItem(
+        "WAVELENGTH",
+        CPLString().Printf(
+            "%4.2f cm", CPL_LSBSINT32PTR(poDS->abyHeader+148+320+12) / 100.0f));
+    const unsigned short nPolarizationType =
+        CPL_LSBUINT16PTR(poDS->abyHeader+172+320+12);
+
+    // See section 3.3.37 & 3.2.54.
+    float fNyquist =
+        (CPL_LSBSINT32PTR(poDS->abyHeader+120+320+12)) *
+        (static_cast<float>(CPL_LSBSINT32PTR(poDS->abyHeader+148+320+12))
+         / 10000.0f) / 4.0f;
+    if( nPolarizationType == 1 )
+        fNyquist = fNyquist * 2.0f;
+    else if( nPolarizationType == 2 )
+        fNyquist = fNyquist * 3.0f;
+    else if( nPolarizationType == 3 )
+        fNyquist = fNyquist * 4.0f;
     poDS->fNyquistVelocity = fNyquist;
-    poDS->SetMetadataItem( "NYQUIST_VELOCITY",CPLString().Printf("%.2f m/s",fNyquist));
+    poDS->SetMetadataItem("NYQUIST_VELOCITY",
+                          CPLString().Printf("%.2f m/s", fNyquist));
 
     // Product dependent metadata (stored in 80 bytes from 162 bytes
     // at the product header) See point 3.2.30 at page 3.19 of the
     // manual.
-    //See point 3.2.25 at page 3.12 of the manual.
-    if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"PPI")){
-        //Degrees = 360 * (Binary Angle)*2^N
-        //float fElevation = 360 * float((CPL_LSBUINT16PTR (poDS->abyHeader+164+12))) / 65536;
-        float fElevation = 360 * float((CPL_LSBSINT16PTR (poDS->abyHeader+164+12))) / 65536;
-
-        poDS->SetMetadataItem( "PPI_ELEVATION_ANGLE",CPLString().Printf("%f",fElevation));
-        if (EQUAL(poDS->aszDataTypeCodes[poDS->nDataTypeCode],"dBZ"))
-            poDS->SetMetadataItem( "DATA_TYPE_UNITS","dBZ");
+    // See point 3.2.25 at page 3.12 of the manual.
+    if( EQUAL(aszProductNames[poDS->nProductCode], "PPI") )
+    {
+        // Degrees = 360 * (Binary Angle)*2^N
+        const float fElevation =
+            CPL_LSBSINT16PTR(poDS->abyHeader+164+12) * 360.0f / 65536.0f;
+
+        poDS->SetMetadataItem("PPI_ELEVATION_ANGLE",
+                              CPLString().Printf("%f", fElevation));
+        if( EQUAL(aszDataTypeCodes[poDS->nDataTypeCode],"dBZ") )
+            poDS->SetMetadataItem( "DATA_TYPE_UNITS", "dBZ");
         else
-            poDS->SetMetadataItem( "DATA_TYPE_UNITS","m/s");
-        //See point 3.2.2 at page 3.2 of the manual
-    } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"CAPPI")){
-        const float fElevation = ((float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12))/100;
-        poDS->SetMetadataItem( "CAPPI_BOTTOM_HEIGHT",CPLString().Printf("%.1f m",fElevation));
-        const float fAzimuthSmoothingForShear = 360 * float((CPL_LSBUINT16PTR (poDS->abyHeader+10+164+12))) / 65536;
-        poDS->SetMetadataItem( "AZIMUTH_SMOOTHING_FOR_SHEAR" ,CPLString().Printf("%.1f", fAzimuthSmoothingForShear));
-        const unsigned int  nMaxAgeVVPCorrection = CPL_LSBUINT32PTR (poDS->abyHeader+24+164+12);
-        poDS->SetMetadataItem( "MAX_AGE_FOR_SHEAR_VVP_CORRECTION" ,CPLString().Printf("%d s", nMaxAgeVVPCorrection));
-        if (EQUAL(poDS->aszDataTypeCodes[poDS->nDataTypeCode],"dBZ"))
-            poDS->SetMetadataItem( "DATA_TYPE_UNITS","dBZ");
+            poDS->SetMetadataItem("DATA_TYPE_UNITS", "m/s");
+        // See point 3.2.2 at page 3.2 of the manual.
+    }
+    else if( EQUAL(aszProductNames[poDS->nProductCode], "CAPPI") )
+    {
+        const float fElevation =
+            CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12) / 100.0f;
+        poDS->SetMetadataItem("CAPPI_BOTTOM_HEIGHT",
+                              CPLString().Printf("%.1f m", fElevation));
+        const float fAzimuthSmoothingForShear =
+            CPL_LSBUINT16PTR(poDS->abyHeader+10+164+12) * 360.0f / 65536.0f;
+        poDS->SetMetadataItem(
+            "AZIMUTH_SMOOTHING_FOR_SHEAR",
+            CPLString().Printf("%.1f", fAzimuthSmoothingForShear));
+        const unsigned int nMaxAgeVVPCorrection =
+            CPL_LSBUINT32PTR(poDS->abyHeader+24+164+12);
+        poDS->SetMetadataItem(
+            "MAX_AGE_FOR_SHEAR_VVP_CORRECTION",
+            CPLString().Printf("%d s", nMaxAgeVVPCorrection));
+        if( EQUAL(aszDataTypeCodes[poDS->nDataTypeCode], "dBZ") )
+            poDS->SetMetadataItem( "DATA_TYPE_UNITS", "dBZ");
         else
-            poDS->SetMetadataItem( "DATA_TYPE_UNITS","m/s");
-        //See point 3.2.32 at page 3.19 of the manual
-    } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"RAIN1") || EQUAL(poDS->aszProductNames[poDS->nProductCode],"RAINN")){
+            poDS->SetMetadataItem( "DATA_TYPE_UNITS", "m/s");
+        // See point 3.2.32 at page 3.19 of the manual.
+    }
+    else if( EQUAL(aszProductNames[poDS->nProductCode],"RAIN1") ||
+             EQUAL(aszProductNames[poDS->nProductCode],"RAINN") )
+    {
         const short nNumProducts = CPL_LSBSINT16PTR(poDS->abyHeader+170+320+12);
-        poDS->SetMetadataItem( "NUM_FILES_USED",CPLString().Printf("%d",nNumProducts));
-
-        const float fMinZAcum= (float)((CPL_LSBUINT32PTR (poDS->abyHeader+164+12))-32768)/1000;
-        poDS->SetMetadataItem( "MINIMUM_Z_TO_ACUMULATE",CPLString().Printf("%f",fMinZAcum));
-
-        const unsigned short nSecondsOfAccumulation = CPL_LSBUINT16PTR (poDS->abyHeader+6+164+12);
-        poDS->SetMetadataItem( "SECONDS_OF_ACCUMULATION",CPLString().Printf("%d s",nSecondsOfAccumulation));
-
-        const unsigned int nSpanInputFiles = CPL_LSBUINT32PTR (poDS->abyHeader+24+164+12);
-        poDS->SetMetadataItem( "SPAN_OF_INPUT_FILES",CPLString().Printf("%d s",nSpanInputFiles));
-        poDS->SetMetadataItem( "DATA_TYPE_UNITS","mm");
+        poDS->SetMetadataItem("NUM_FILES_USED",
+                              CPLString().Printf("%d", nNumProducts));
+
+        const float fMinZAcum =
+            (CPL_LSBUINT32PTR(poDS->abyHeader+164+12) - 32768.0f) / 10000.0f;
+        poDS->SetMetadataItem("MINIMUM_Z_TO_ACUMULATE",
+                              CPLString().Printf("%f", fMinZAcum));
+
+        const unsigned short nSecondsOfAccumulation =
+            CPL_LSBUINT16PTR(poDS->abyHeader+6+164+12);
+        poDS->SetMetadataItem("SECONDS_OF_ACCUMULATION",
+                              CPLString().Printf("%d s",
+                                                 nSecondsOfAccumulation));
+
+        const unsigned int nSpanInputFiles =
+            CPL_LSBUINT32PTR(poDS->abyHeader+24+164+12);
+        poDS->SetMetadataItem("SPAN_OF_INPUT_FILES",
+                              CPLString().Printf("%d s", nSpanInputFiles));
+        poDS->SetMetadataItem("DATA_TYPE_UNITS", "mm");
 
         char szInputProductName[13] = "";
-        for(int k=0; k<12;k++)
-            szInputProductName[k] = * (char *) (poDS->abyHeader+k+12+164+12);
-        poDS->SetMetadataItem( "INPUT_PRODUCT_NAME",CPLString().Printf("%s",szInputProductName));
+        for( int k = 0; k < 12; k++ )
+            szInputProductName[k] = *reinterpret_cast<char *>(
+                poDS->abyHeader+k+12+164+12);
+
+        poDS->SetMetadataItem("INPUT_PRODUCT_NAME",
+                              CPLString().Printf("%s", szInputProductName));
 
-        if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"RAINN"))
-             poDS->SetMetadataItem( "NUM_HOURS_ACCUMULATE",CPLString().Printf("%d",CPL_LSBUINT16PTR (poDS->abyHeader+10+164+12)));
+        if( EQUAL(aszProductNames[poDS->nProductCode], "RAINN") )
+             poDS->SetMetadataItem(
+                 "NUM_HOURS_ACCUMULATE",
+                 CPLString().Printf(
+                     "%d", CPL_LSBUINT16PTR(poDS->abyHeader+10+164+12)));
 
-    //See point 3.2.73 at page 3.36 of the manual
-    } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"VIL")){
-        const float fBottomHeightInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12) / 100;
+    // See point 3.2.73 at page 3.36 of the manual.
+    }
+    else if( EQUAL(aszProductNames[poDS->nProductCode], "VIL") )
+    {
+        const float fBottomHeightInterval =
+            CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12) / 100.0f;
         // TYPO in metadata key: FIXME ?
-        poDS->SetMetadataItem( "BOTTOM_OF_HEIGTH_INTERVAL",CPLString().Printf("%.1f m",fBottomHeightInterval));
-        const float fTopHeightInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+8+164+12) / 100;
+        poDS->SetMetadataItem(
+            "BOTTOM_OF_HEIGTH_INTERVAL",
+            CPLString().Printf("%.1f m", fBottomHeightInterval));
+        const float fTopHeightInterval =
+            CPL_LSBSINT32PTR(poDS->abyHeader+8+164+12) / 100.0f;
         // TYPO in metadata key: FIXME ?
-        poDS->SetMetadataItem( "TOP_OF_HEIGTH_INTERVAL",CPLString().Printf("%.1f m",fTopHeightInterval));
-        poDS->SetMetadataItem( "VIL_DENSITY_NOT_AVAILABLE_VALUE","-1");
-        poDS->SetMetadataItem( "DATA_TYPE_UNITS","mm");
-    //See point 3.2.68 at page 3.36 of the manual
-    } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"TOPS")){
-        const float fZThreshold = (float) CPL_LSBSINT16PTR(poDS->abyHeader+4+164+12) / 16;
-        poDS->SetMetadataItem( "Z_THRESHOLD",CPLString().Printf("%.1f dBZ",fZThreshold));
-        poDS->SetMetadataItem( "ECHO_TOPS_NOT_AVAILABLE_VALUE","-1");
-        poDS->SetMetadataItem( "DATA_TYPE_UNITS","km");
-    //See point 3.2.20 at page 3.10 of the manual
-    } else if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"MAX")){
-        const float fBottomInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12) / 100;
-        poDS->SetMetadataItem( "BOTTOM_OF_INTERVAL",CPLString().Printf("%.1f m",fBottomInterval));
-        const float fTopInterval = (float) CPL_LSBSINT32PTR(poDS->abyHeader+8+164+12) / 100;
-        poDS->SetMetadataItem( "TOP_OF_INTERVAL",CPLString().Printf("%.1f m",fTopInterval));
-        const int nNumPixelsSidePanels = CPL_LSBSINT32PTR(poDS->abyHeader+12+164+12);
-        poDS->SetMetadataItem( "NUM_PIXELS_SIDE_PANELS",CPLString().Printf("%d",nNumPixelsSidePanels));
-        const short nHorizontalSmootherSidePanels = CPL_LSBSINT16PTR(poDS->abyHeader+16+164+12);
-        poDS->SetMetadataItem( "HORIZONTAL_SMOOTHER_SIDE_PANELS",CPLString().Printf("%d",nHorizontalSmootherSidePanels));
-        const short nVerticalSmootherSidePanels = CPL_LSBSINT16PTR(poDS->abyHeader+18+164+12);
-        poDS->SetMetadataItem( "VERTICAL_SMOOTHER_SIDE_PANELS",CPLString().Printf("%d",nVerticalSmootherSidePanels));
+        poDS->SetMetadataItem("TOP_OF_HEIGTH_INTERVAL",
+                              CPLString().Printf("%.1f m", fTopHeightInterval));
+        poDS->SetMetadataItem("VIL_DENSITY_NOT_AVAILABLE_VALUE", "-1");
+        poDS->SetMetadataItem("DATA_TYPE_UNITS","mm");
+    // See point 3.2.68 at page 3.36 of the manual
+    }
+    else if( EQUAL(aszProductNames[poDS->nProductCode], "TOPS") )
+    {
+        const float fZThreshold =
+            CPL_LSBSINT16PTR(poDS->abyHeader+4+164+12) / 16.0f;
+        poDS->SetMetadataItem("Z_THRESHOLD",
+                              CPLString().Printf("%.1f dBZ", fZThreshold));
+        poDS->SetMetadataItem("ECHO_TOPS_NOT_AVAILABLE_VALUE", "-1");
+        poDS->SetMetadataItem("DATA_TYPE_UNITS", "km");
+    // See point 3.2.20 at page 3.10 of the manual.
+    }
+    else if( EQUAL(aszProductNames[poDS->nProductCode], "MAX") )
+    {
+        const float fBottomInterval =
+            CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12) / 100.0f;
+        poDS->SetMetadataItem( "BOTTOM_OF_INTERVAL",
+                               CPLString().Printf("%.1f m", fBottomInterval));
+        const float fTopInterval =
+            CPL_LSBSINT32PTR(poDS->abyHeader+8+164+12) / 100.0f;
+        poDS->SetMetadataItem("TOP_OF_INTERVAL",
+                              CPLString().Printf("%.1f m", fTopInterval));
+        const int nNumPixelsSidePanels =
+            CPL_LSBSINT32PTR(poDS->abyHeader+12+164+12);
+        poDS->SetMetadataItem("NUM_PIXELS_SIDE_PANELS",
+                              CPLString().Printf("%d", nNumPixelsSidePanels));
+        const short nHorizontalSmootherSidePanels =
+            CPL_LSBSINT16PTR(poDS->abyHeader+16+164+12);
+        poDS->SetMetadataItem(
+            "HORIZONTAL_SMOOTHER_SIDE_PANELS",
+            CPLString().Printf("%d", nHorizontalSmootherSidePanels));
+        const short nVerticalSmootherSidePanels =
+            CPL_LSBSINT16PTR(poDS->abyHeader+18+164+12);
+        poDS->SetMetadataItem(
+            "VERTICAL_SMOOTHER_SIDE_PANELS",
+            CPLString().Printf("%d", nVerticalSmootherSidePanels));
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    /* coverity[tainted_data] */
-    for (int iBandNum = 1; iBandNum <= nNumBands; iBandNum++) {
+    // coverity[tainted_data]
+    for( int iBandNum = 1; iBandNum <= nNumBands; iBandNum++ )
+    {
         poDS->SetBand( iBandNum, new IRISRasterBand( poDS, iBandNum ));
 
         poDS->GetRasterBand(iBandNum)->SetNoDataValue(-9999);
-        //Calculating the band height to include it in the band metadata. Only for the CAPPI product
-        if (EQUAL(poDS->aszProductNames[poDS->nProductCode],"CAPPI")){
-            const float fScaleZ = float (CPL_LSBSINT32PTR (poDS->abyHeader + 96 + 12 )) / 100;
-            const float fOffset = ((float) CPL_LSBSINT32PTR(poDS->abyHeader+4+164+12))/100;
-
-            poDS->GetRasterBand(iBandNum)->SetMetadataItem("height",CPLString().Printf("%.0f m",fOffset + fScaleZ*(iBandNum-1)));
+        // Calculating the band height to include it in the band metadata.  Only
+        // for the CAPPI product.
+        if( EQUAL(aszProductNames[poDS->nProductCode],"CAPPI") )
+        {
+            const float fScaleZ =
+                CPL_LSBSINT32PTR(poDS->abyHeader + 96 + 12) / 100.0f;
+            const float fOffset =
+                CPL_LSBSINT32PTR(poDS->abyHeader + 4 + 164 + 12) / 100.0f;
+
+            poDS->GetRasterBand(iBandNum)->
+                SetMetadataItem(
+                    "height",
+                    CPLString().Printf("%.0f m",
+                                       fOffset + fScaleZ*(iBandNum-1)));
         }
     }
 /* -------------------------------------------------------------------- */
@@ -953,7 +1118,7 @@ GDALDataset *IRISDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/iso8211/8211createfromxml.cpp b/frmts/iso8211/8211createfromxml.cpp
index 67b7305..e3a3ea6 100644
--- a/frmts/iso8211/8211createfromxml.cpp
+++ b/frmts/iso8211/8211createfromxml.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: 8211createfromxml.cpp 33035 2016-01-17 22:05:23Z rouault $
  *
  * Project:  ISO8211 library
  * Purpose:  Create a 8211 file from a XML dump file generated by "8211dump -xml"
@@ -34,12 +33,12 @@
 #include <map>
 #include <string>
 
-CPL_CVSID("$Id: 8211createfromxml.cpp 33035 2016-01-17 22:05:23Z rouault $");
+CPL_CVSID("$Id: 8211createfromxml.cpp 35885 2016-10-24 06:23:09Z goatbar $");
 
 int main(int nArgc, char* papszArgv[])
 {
-    const char  *pszFilename = NULL, *pszOutFilename = NULL;
-    DDFModule  oModule;
+    const char *pszFilename = NULL;
+    const char *pszOutFilename = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Check arguments.                                                */
@@ -73,7 +72,8 @@ int main(int nArgc, char* papszArgv[])
     CPLXMLNode* poXMLDDFModule = CPLSearchXMLNode(poRoot, "=DDFModule");
     if( poXMLDDFModule == NULL )
     {
-        fprintf(stderr, "Cannot find DDFModule node in XML file '%s'\n", pszFilename);
+        fprintf(stderr, "Cannot find DDFModule node in XML file '%s'\n",
+                pszFilename);
         exit( 1 );
     }
 
@@ -98,26 +98,45 @@ int main(int nArgc, char* papszArgv[])
     }
 
     char chInterchangeLevel = '3';
+    chInterchangeLevel =
+        CPLGetXMLValue(poXMLDDFModule, "_interchangeLevel",
+                       CPLSPrintf("%c", chInterchangeLevel))[0];
+
     char chLeaderIden = 'L';
+    chLeaderIden =
+        CPLGetXMLValue(poXMLDDFModule, "_leaderIden",
+                       CPLSPrintf("%c", chLeaderIden))[0];
+
     char chCodeExtensionIndicator = 'E';
+    chCodeExtensionIndicator =
+        CPLGetXMLValue(poXMLDDFModule, "_inlineCodeExtensionIndicator",
+                       CPLSPrintf("%c", chCodeExtensionIndicator))[0];
+
     char chVersionNumber = '1';
+    chVersionNumber = CPLGetXMLValue(poXMLDDFModule, "_versionNumber",
+                                     CPLSPrintf("%c", chVersionNumber))[0];
+
     char chAppIndicator = ' ';
-    const char *pszExtendedCharSet = " ! ";
-    int nSizeFieldLength = 3;
-    int nSizeFieldPos = 4;
+    chAppIndicator = CPLGetXMLValue(poXMLDDFModule, "_appIndicator",
+                                    CPLSPrintf("%c", chAppIndicator))[0];
 
-    chInterchangeLevel = CPLGetXMLValue(poXMLDDFModule, "_interchangeLevel", CPLSPrintf("%c", chInterchangeLevel))[0];
-    chLeaderIden = CPLGetXMLValue(poXMLDDFModule, "_leaderIden", CPLSPrintf("%c", chLeaderIden))[0];
-    chCodeExtensionIndicator = CPLGetXMLValue(poXMLDDFModule, "_inlineCodeExtensionIndicator", CPLSPrintf("%c", chCodeExtensionIndicator))[0];
-    chVersionNumber = CPLGetXMLValue(poXMLDDFModule, "_versionNumber", CPLSPrintf("%c", chVersionNumber))[0];
-    chAppIndicator = CPLGetXMLValue(poXMLDDFModule, "_appIndicator", CPLSPrintf("%c", chAppIndicator))[0];
+    const char *pszExtendedCharSet = " ! ";
     char szExtendedCharSet[4];
-    snprintf(szExtendedCharSet, sizeof(szExtendedCharSet), "%s", CPLGetXMLValue(poXMLDDFModule, "_extendedCharSet", pszExtendedCharSet));
+    snprintf(szExtendedCharSet, sizeof(szExtendedCharSet), "%s",
+             CPLGetXMLValue(poXMLDDFModule, "_extendedCharSet",
+                            pszExtendedCharSet));
     pszExtendedCharSet = szExtendedCharSet;
-    nSizeFieldLength = atoi(CPLGetXMLValue(poXMLDDFModule, "_sizeFieldLength", CPLSPrintf("%d", nSizeFieldLength)));
-    nSizeFieldPos = atoi(CPLGetXMLValue(poXMLDDFModule, "_sizeFieldPos", CPLSPrintf("%d", nSizeFieldPos)));
-    nSizeFieldTag = atoi(CPLGetXMLValue(poXMLDDFModule, "_sizeFieldTag", CPLSPrintf("%d", nSizeFieldTag)));
+    int nSizeFieldLength = 3;
+    nSizeFieldLength = atoi(CPLGetXMLValue(poXMLDDFModule, "_sizeFieldLength",
+                                           CPLSPrintf("%d", nSizeFieldLength)));
 
+    int nSizeFieldPos = 4;
+    nSizeFieldPos = atoi(CPLGetXMLValue(poXMLDDFModule, "_sizeFieldPos",
+                                        CPLSPrintf("%d", nSizeFieldPos)));
+    nSizeFieldTag = atoi(CPLGetXMLValue(poXMLDDFModule, "_sizeFieldTag",
+                                        CPLSPrintf("%d", nSizeFieldTag)));
+
+    DDFModule oModule;
     oModule.Initialize(chInterchangeLevel,
                        chLeaderIden,
                        chCodeExtensionIndicator,
@@ -127,11 +146,13 @@ int main(int nArgc, char* papszArgv[])
                        nSizeFieldLength,
                        nSizeFieldPos,
                        nSizeFieldTag);
-    oModule.SetFieldControlLength(atoi(CPLGetXMLValue(poXMLDDFModule, "_fieldControlLength", CPLSPrintf("%d", oModule.GetFieldControlLength()))));
+    oModule.SetFieldControlLength(atoi(
+        CPLGetXMLValue(poXMLDDFModule, "_fieldControlLength",
+                       CPLSPrintf("%d", oModule.GetFieldControlLength()))));
 
-    int bCreated = FALSE;
+    bool bCreated = false;
 
-    /* Create DDFFieldDefn and DDFRecord elements */
+    // Create DDFFieldDefn and DDFRecord elements.
     psIter = poXMLDDFModule->psChild;
     while( psIter != NULL )
     {
@@ -141,27 +162,42 @@ int main(int nArgc, char* papszArgv[])
             DDFFieldDefn* poFDefn = new DDFFieldDefn();
 
             DDF_data_struct_code eStructCode = dsc_elementary;
-            const char* pszStructCode = CPLGetXMLValue(psIter, "dataStructCode", "");
-            if( strcmp(pszStructCode, "elementary") == 0 ) eStructCode = dsc_elementary;
-            else if( strcmp(pszStructCode, "vector") == 0 ) eStructCode = dsc_vector;
-            else if( strcmp(pszStructCode, "array") == 0 ) eStructCode = dsc_array;
-            else if( strcmp(pszStructCode, "concatenated") == 0 ) eStructCode = dsc_concatenated;
+            const char* pszStructCode =
+                CPLGetXMLValue(psIter, "dataStructCode", "");
+            if( strcmp(pszStructCode, "elementary") == 0 )
+                eStructCode = dsc_elementary;
+            else if( strcmp(pszStructCode, "vector") == 0 )
+                eStructCode = dsc_vector;
+            else if( strcmp(pszStructCode, "array") == 0 )
+                eStructCode = dsc_array;
+            else if( strcmp(pszStructCode, "concatenated") == 0 )
+                eStructCode = dsc_concatenated;
 
             DDF_data_type_code eTypeCode = dtc_char_string;
-            const char* pszTypeCode = CPLGetXMLValue(psIter, "dataTypeCode", "");
-            if( strcmp(pszTypeCode, "char_string") == 0 ) eTypeCode = dtc_char_string;
-            else if( strcmp(pszTypeCode, "implicit_point") == 0 ) eTypeCode = dtc_implicit_point;
-            else if( strcmp(pszTypeCode, "explicit_point") == 0 ) eTypeCode = dtc_explicit_point;
-            else if( strcmp(pszTypeCode, "explicit_point_scaled") == 0 ) eTypeCode = dtc_explicit_point_scaled;
-            else if( strcmp(pszTypeCode, "char_bit_string") == 0 ) eTypeCode = dtc_char_bit_string;
-            else if( strcmp(pszTypeCode, "bit_string") == 0 ) eTypeCode = dtc_bit_string;
-            else if( strcmp(pszTypeCode, "mixed_data_type") == 0 ) eTypeCode = dtc_mixed_data_type;
-
-            const char* pszFormatControls = CPLGetXMLValue(psIter, "formatControls", NULL);
+            const char* pszTypeCode =
+                CPLGetXMLValue(psIter, "dataTypeCode", "");
+            if( strcmp(pszTypeCode, "char_string") == 0 )
+                eTypeCode = dtc_char_string;
+            else if( strcmp(pszTypeCode, "implicit_point") == 0 )
+                eTypeCode = dtc_implicit_point;
+            else if( strcmp(pszTypeCode, "explicit_point") == 0 )
+                eTypeCode = dtc_explicit_point;
+            else if( strcmp(pszTypeCode, "explicit_point_scaled") == 0 )
+                eTypeCode = dtc_explicit_point_scaled;
+            else if( strcmp(pszTypeCode, "char_bit_string") == 0 )
+                eTypeCode = dtc_char_bit_string;
+            else if( strcmp(pszTypeCode, "bit_string") == 0 )
+                eTypeCode = dtc_bit_string;
+            else if( strcmp(pszTypeCode, "mixed_data_type") == 0 )
+                eTypeCode = dtc_mixed_data_type;
+
+            const char* pszFormatControls =
+                CPLGetXMLValue(psIter, "formatControls", NULL);
             if( eStructCode != dsc_elementary )
                 pszFormatControls = NULL;
 
-            const char* pszArrayDescr = CPLGetXMLValue(psIter, "arrayDescr", "");
+            const char* pszArrayDescr =
+                CPLGetXMLValue(psIter, "arrayDescr", "");
             if( eStructCode == dsc_vector )
                 pszArrayDescr = "";
             else if( eStructCode == dsc_array )
@@ -179,8 +215,9 @@ int main(int nArgc, char* papszArgv[])
                 if( psSubIter->eType == CXT_Element &&
                     strcmp(psSubIter->pszValue, "DDFSubfieldDefn") == 0 )
                 {
-                    poFDefn->AddSubfield( CPLGetXMLValue(psSubIter, "name", ""),
-                                          CPLGetXMLValue(psSubIter, "format", "") );
+                    poFDefn->AddSubfield(
+                        CPLGetXMLValue(psSubIter, "name", ""),
+                        CPLGetXMLValue(psSubIter, "format", "") );
                 }
                 psSubIter = psSubIter->psNext;
             }
@@ -194,21 +231,29 @@ int main(int nArgc, char* papszArgv[])
         else if( psIter->eType == CXT_Element &&
                  strcmp(psIter->pszValue, "DDFRecord") == 0 )
         {
-            //const bool bFirstRecord = !bCreated;
+            // const bool bFirstRecord = !bCreated;
             if( !bCreated )
             {
                 oModule.Create( pszOutFilename );
-                bCreated = TRUE;
+                bCreated = true;
             }
 
             DDFRecord *poRec = new DDFRecord( &oModule );
             std::map<std::string, int> oMapField;
 
-            //if( !bFirstRecord )
-            //    poRec->SetReuseHeader(atoi(CPLGetXMLValue(psIter, "reuseHeader", CPLSPrintf("%d", poRec->GetReuseHeader()))));
-            poRec->SetSizeFieldLength(atoi(CPLGetXMLValue(psIter, "_sizeFieldLength", CPLSPrintf("%d", poRec->GetSizeFieldLength()))));
-            poRec->SetSizeFieldPos(atoi(CPLGetXMLValue(psIter, "_sizeFieldPos", CPLSPrintf("%d", poRec->GetSizeFieldPos()))));
-            poRec->SetSizeFieldTag(atoi(CPLGetXMLValue(psIter, "_sizeFieldTag", CPLSPrintf("%d", poRec->GetSizeFieldTag()))));
+            // if( !bFirstRecord )
+            //     poRec->SetReuseHeader(atoi(
+            //         CPLGetXMLValue(psIter, "reuseHeader",
+            //         CPLSPrintf("%d", poRec->GetReuseHeader()))));
+            poRec->SetSizeFieldLength(atoi(
+                CPLGetXMLValue(psIter, "_sizeFieldLength",
+                               CPLSPrintf("%d", poRec->GetSizeFieldLength()))));
+            poRec->SetSizeFieldPos(atoi(
+                CPLGetXMLValue(psIter, "_sizeFieldPos",
+                               CPLSPrintf("%d", poRec->GetSizeFieldPos()))));
+            poRec->SetSizeFieldTag(atoi(
+                CPLGetXMLValue(psIter, "_sizeFieldTag",
+                               CPLSPrintf("%d", poRec->GetSizeFieldTag()))));
 
             CPLXMLNode* psSubIter = psIter->psChild;
             while( psSubIter != NULL )
@@ -216,24 +261,27 @@ int main(int nArgc, char* papszArgv[])
                 if( psSubIter->eType == CXT_Element &&
                     strcmp(psSubIter->pszValue, "DDFField") == 0 )
                 {
-                    DDFField *poField;
-                    const char* pszFieldName = CPLGetXMLValue(psSubIter, "name", "");
-                    DDFFieldDefn* poFieldDefn = oModule.FindFieldDefn( pszFieldName );
+                    const char* pszFieldName =
+                        CPLGetXMLValue(psSubIter, "name", "");
+                    DDFFieldDefn* poFieldDefn =
+                        oModule.FindFieldDefn( pszFieldName );
                     if( poFieldDefn == NULL )
                     {
-                        fprintf(stderr, "Can't find field '%s'\n", pszFieldName );
+                        fprintf(stderr, "Can't find field '%s'\n",
+                                pszFieldName );
                         exit(1);
                     }
 
                     int nFieldOcc = oMapField[pszFieldName];
                     oMapField[pszFieldName] ++ ;
 
-                    poField = poRec->AddField( poFieldDefn );
-                    const char* pszValue = CPLGetXMLValue(psSubIter, "value", NULL);
+                    DDFField *poField = poRec->AddField( poFieldDefn );
+                    const char* pszValue =
+                        CPLGetXMLValue(psSubIter, "value", NULL);
                     if( pszValue != NULL && STARTS_WITH(pszValue, "0x") )
                     {
                         pszValue += 2;
-                        int nDataLen = (int)strlen(pszValue)  / 2;
+                        int nDataLen = (int)strlen(pszValue) / 2;
                         char* pabyData = (char*) malloc(nDataLen);
                         for(int i=0;i<nDataLen;i++)
                         {
@@ -251,7 +299,8 @@ int main(int nArgc, char* papszArgv[])
                                 nLow = c - '0';
                             pabyData[i] = (nHigh << 4) + nLow;
                         }
-                        poRec->SetFieldRaw( poField, nFieldOcc, (const char *) pabyData, nDataLen );
+                        poRec->SetFieldRaw( poField, nFieldOcc,
+                                            (const char *) pabyData, nDataLen );
                         free(pabyData);
                     }
                     else
@@ -261,39 +310,53 @@ int main(int nArgc, char* papszArgv[])
                         while( psSubfieldIter != NULL )
                         {
                             if( psSubfieldIter->eType == CXT_Element &&
-                                strcmp(psSubfieldIter->pszValue, "DDFSubfield") == 0 )
+                                strcmp(psSubfieldIter->pszValue,
+                                       "DDFSubfield") == 0 )
                             {
-                                const char* pszSubfieldName = CPLGetXMLValue(psSubfieldIter, "name", "");
-                                const char* pszSubfieldType = CPLGetXMLValue(psSubfieldIter, "type", "");
-                                const char* pszSubfieldValue = CPLGetXMLValue(psSubfieldIter, NULL, "");
+                                const char* pszSubfieldName =
+                                    CPLGetXMLValue(psSubfieldIter, "name", "");
+                                const char* pszSubfieldType =
+                                    CPLGetXMLValue(psSubfieldIter, "type", "");
+                                const char* pszSubfieldValue =
+                                    CPLGetXMLValue(psSubfieldIter, NULL, "");
                                 int nOcc = oMapSubfield[pszSubfieldName];
                                 oMapSubfield[pszSubfieldName] ++ ;
                                 if( strcmp(pszSubfieldType, "float") == 0 )
                                 {
-                                    poRec->SetFloatSubfield( pszFieldName, nFieldOcc, pszSubfieldName, nOcc,
-                                                           CPLAtof(pszSubfieldValue) );
+                                    poRec->SetFloatSubfield(
+                                        pszFieldName, nFieldOcc,
+                                        pszSubfieldName, nOcc,
+                                        CPLAtof(pszSubfieldValue) );
                                 }
-                                else if( strcmp(pszSubfieldType, "integer") == 0 )
+                                else if( strcmp(pszSubfieldType,
+                                                "integer") == 0 )
                                 {
-                                    poRec->SetIntSubfield( pszFieldName, nFieldOcc, pszSubfieldName, nOcc,
-                                                           atoi(pszSubfieldValue) );
+                                    poRec->SetIntSubfield(
+                                        pszFieldName, nFieldOcc,
+                                        pszSubfieldName, nOcc,
+                                        atoi(pszSubfieldValue) );
                                 }
-                                else if( strcmp(pszSubfieldType, "string") == 0 )
+                                else if( strcmp(pszSubfieldType,
+                                                "string") == 0 )
                                 {
-                                    poRec->SetStringSubfield( pszFieldName, nFieldOcc, pszSubfieldName, nOcc,
-                                                              pszSubfieldValue );
+                                    poRec->SetStringSubfield(
+                                        pszFieldName, nFieldOcc,
+                                        pszSubfieldName, nOcc,
+                                        pszSubfieldValue );
                                 }
-                                else if( strcmp(pszSubfieldType, "binary") == 0 &&
+                                else if( strcmp(pszSubfieldType,
+                                                "binary") == 0 &&
                                          STARTS_WITH(pszSubfieldValue, "0x") )
                                 {
                                     pszSubfieldValue += 2;
-                                    int nDataLen = (int)strlen(pszSubfieldValue) / 2;
+                                    int nDataLen =
+                                        (int)strlen(pszSubfieldValue) / 2;
                                     char* pabyData = (char*) malloc(nDataLen);
                                     for(int i=0;i<nDataLen;i++)
                                     {
-                                        char c;
-                                        int nHigh, nLow;
-                                        c = pszSubfieldValue[2*i];
+                                        int nHigh;
+                                        int nLow;
+                                        char c = pszSubfieldValue[2*i];
                                         if( c >= 'A' && c <= 'F' )
                                             nHigh = 10 + c - 'A';
                                         else
@@ -305,8 +368,10 @@ int main(int nArgc, char* papszArgv[])
                                             nLow = c - '0';
                                         pabyData[i] = (nHigh << 4) + nLow;
                                     }
-                                    poRec->SetStringSubfield( pszFieldName, nFieldOcc, pszSubfieldName, nOcc,
-                                                              pabyData, nDataLen );
+                                    poRec->SetStringSubfield(
+                                        pszFieldName, nFieldOcc,
+                                        pszSubfieldName, nOcc,
+                                        pabyData, nDataLen );
                                     free(pabyData);
                                 }
                             }
diff --git a/frmts/iso8211/8211dump.cpp b/frmts/iso8211/8211dump.cpp
index e0e6e28..bf9d124 100644
--- a/frmts/iso8211/8211dump.cpp
+++ b/frmts/iso8211/8211dump.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: 8211dump.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Dump 8211 file in verbose form - just a junk program.
@@ -33,8 +32,7 @@
 #include "cpl_vsi.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: 8211dump.cpp 33717 2016-03-14 06:29:14Z goatbar $");
-
+CPL_CVSID("$Id: 8211dump.cpp 35929 2016-10-25 16:09:00Z goatbar $");
 
 int main( int nArgc, char ** papszArgv )
 
@@ -92,7 +90,6 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Dump header, and all records.                                   */
 /* -------------------------------------------------------------------- */
-    DDFRecord       *poRecord;
     if( bXML )
     {
         printf("<DDFModule");
@@ -115,7 +112,7 @@ int main( int nArgc, char ** papszArgv )
         for( int i = 0; i < nFieldDefnCount; i++ )
         {
             DDFFieldDefn* poFieldDefn = oModule.GetField(i);
-            const char* pszDataStructCode;
+            const char* pszDataStructCode = NULL;
             switch( poFieldDefn->GetDataStructCode() )
             {
                 case dsc_elementary:
@@ -139,7 +136,7 @@ int main( int nArgc, char ** papszArgv )
                     break;
             }
 
-            const char* pszDataTypeCode;
+            const char* pszDataTypeCode = NULL;
             switch( poFieldDefn->GetDataTypeCode() )
             {
                 case dtc_char_string:
@@ -197,8 +194,10 @@ int main( int nArgc, char ** papszArgv )
             printf("</DDFFieldDefn>\n");
         }
 
-        for( poRecord = oModule.ReadRecord();
-             poRecord != NULL; poRecord = oModule.ReadRecord() )
+        // DDFRecord       *poRecord;
+        for( DDFRecord *poRecord = oModule.ReadRecord();
+             poRecord != NULL;
+             poRecord = oModule.ReadRecord() )
         {
             printf("<DDFRecord");
             if( bAllDetails )
@@ -305,8 +304,9 @@ int main( int nArgc, char ** papszArgv )
         long nStartLoc;
 
         nStartLoc = VSIFTellL( oModule.GetFP() );
-        for( poRecord = oModule.ReadRecord();
-            poRecord != NULL; poRecord = oModule.ReadRecord() )
+        for( DDFRecord *poRecord = oModule.ReadRecord();
+             poRecord != NULL;
+             poRecord = oModule.ReadRecord() )
         {
             printf( "File Offset: %ld\n", nStartLoc );
             poRecord->Dump( stdout );
@@ -320,5 +320,4 @@ int main( int nArgc, char ** papszArgv )
 #ifdef DBMALLOC
     malloc_dump(1);
 #endif
-
 }
diff --git a/frmts/iso8211/8211view.cpp b/frmts/iso8211/8211view.cpp
index 216c5b7..85d5ee8 100644
--- a/frmts/iso8211/8211view.cpp
+++ b/frmts/iso8211/8211view.cpp
@@ -1,5 +1,4 @@
 /* ****************************************************************************
- * $Id: 8211view.cpp 10645 2007-01-18 02:22:39Z warmerdam $
  *
  * Project:  SDTS Translator
  * Purpose:  Example program dumping data in 8211 data to stdout.
@@ -30,7 +29,9 @@
 #include <stdio.h>
 #include "iso8211.h"
 
-CPL_CVSID("$Id: 8211view.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+#include <algorithm>
+
+CPL_CVSID("$Id: 8211view.cpp 36352 2016-11-20 22:31:49Z rouault $");
 
 static void ViewRecordField( DDFField * poField );
 static int ViewSubfield( DDFSubfieldDefn *poSFDefn,
@@ -85,8 +86,8 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Loop reading records till there are none left.                  */
 /* -------------------------------------------------------------------- */
-    DDFRecord   *poRecord;
-    int         iRecord = 0;
+    DDFRecord *poRecord = NULL;
+    int iRecord = 0;
 
     while( (poRecord = oModule.ReadRecord()) != NULL )
     {
@@ -114,8 +115,6 @@ int main( int nArgc, char ** papszArgv )
 static void ViewRecordField( DDFField * poField )
 
 {
-    int         nBytesRemaining;
-    const char  *pachFieldData;
     DDFFieldDefn *poFieldDefn = poField->GetFieldDefn();
 
     // Report general information about the field.
@@ -125,32 +124,26 @@ static void ViewRecordField( DDFField * poField )
     // Get pointer to this fields raw data.  We will move through
     // it consuming data as we report subfield values.
 
-    pachFieldData = poField->GetData();
-    nBytesRemaining = poField->GetDataSize();
+    const char  *pachFieldData = poField->GetData();
+    int nBytesRemaining = poField->GetDataSize();
 
     /* -------------------------------------------------------- */
     /*      Loop over the repeat count for this fields          */
     /*      subfields.  The repeat count will almost            */
     /*      always be one.                                      */
     /* -------------------------------------------------------- */
-    int         iRepeat;
-
-    for( iRepeat = 0; iRepeat < poField->GetRepeatCount(); iRepeat++ )
+    for( int iRepeat = 0; iRepeat < poField->GetRepeatCount(); iRepeat++ )
     {
 
         /* -------------------------------------------------------- */
         /*   Loop over all the subfields of this field, advancing   */
         /*   the data pointer as we consume data.                   */
         /* -------------------------------------------------------- */
-        int     iSF;
-
-        for( iSF = 0; iSF < poFieldDefn->GetSubfieldCount(); iSF++ )
+        for( int iSF = 0; iSF < poFieldDefn->GetSubfieldCount(); iSF++ )
         {
             DDFSubfieldDefn *poSFDefn = poFieldDefn->GetSubfield( iSF );
-            int         nBytesConsumed;
-
-            nBytesConsumed = ViewSubfield( poSFDefn, pachFieldData,
-                                           nBytesRemaining );
+            int nBytesConsumed =
+                ViewSubfield( poSFDefn, pachFieldData, nBytesRemaining );
 
             nBytesRemaining -= nBytesConsumed;
             pachFieldData += nBytesConsumed;
@@ -175,8 +168,9 @@ static int ViewSubfield( DDFSubfieldDefn *poSFDefn,
         if( poSFDefn->GetBinaryFormat() == DDFSubfieldDefn::UInt )
             printf( "        %s = %u\n",
                     poSFDefn->GetName(),
-                    poSFDefn->ExtractIntData( pachFieldData, nBytesRemaining,
-                                              &nBytesConsumed ) );
+                    static_cast<unsigned int>(
+                        poSFDefn->ExtractIntData( pachFieldData, nBytesRemaining,
+                                              &nBytesConsumed )) );
         else
             printf( "        %s = %d\n",
                     poSFDefn->GetName(),
@@ -213,7 +207,7 @@ static int ViewSubfield( DDFSubfieldDefn *poSFDefn,
                                            &nBytesConsumed );
 
           printf( "        %s = 0x", poSFDefn->GetName() );
-          for( i = 0; i < MIN(nBytesConsumed,24); i++ )
+          for( i = 0; i < std::min(nBytesConsumed, 24); i++ )
               printf( "%02X", pabyBString[i] );
 
           if( nBytesConsumed > 24 )
@@ -225,7 +219,7 @@ static int ViewSubfield( DDFSubfieldDefn *poSFDefn,
               vrid_rcnm=pabyBString[0];
               vrid_rcid=pabyBString[1] + (pabyBString[2]*256)+
                   (pabyBString[3]*65536)+ (pabyBString[4]*16777216);
-              printf("\tVRID RCNM = %d,RCID = %u",vrid_rcnm,vrid_rcid);
+              printf("\tVRID RCNM = %d,RCID = %d",vrid_rcnm,vrid_rcid);
           }
           else if ( EQUAL(poSFDefn->GetName(),"LNAM") )
           {
@@ -233,14 +227,13 @@ static int ViewSubfield( DDFSubfieldDefn *poSFDefn,
               foid_find=pabyBString[2] + (pabyBString[3]*256)+
                   (pabyBString[4]*65536)+ (pabyBString[5]*16777216);
               foid_fids=pabyBString[6] + (pabyBString[7]*256);
-              printf("\tFOID AGEN = %u,FIDN = %u,FIDS = %u",
+              printf("\tFOID AGEN = %d,FIDN = %d,FIDS = %d",
                      foid_agen,foid_find,foid_fids);
           }
 
           printf( "\n" );
       }
       break;
-
     }
 
     return nBytesConsumed;
diff --git a/frmts/iso8211/Doxyfile b/frmts/iso8211/Doxyfile
index 773cdd2..6cb7477 100644
--- a/frmts/iso8211/Doxyfile
+++ b/frmts/iso8211/Doxyfile
@@ -10,19 +10,19 @@
 #---------------------------------------------------------------------------
 
 # The PROJECT_NAME tag is a single word (or a sequence of word surrounded
-# by quotes) that should identify the project. 
+# by quotes) that should identify the project.
 
 PROJECT_NAME         =	ISO8211Lib
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or 
+# This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER       =	
+PROJECT_NUMBER       =
 
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
 # where doxygen was started. If left blank the current directory will be used.
 
 OUTPUT_DIRECTORY     =
@@ -39,14 +39,14 @@ HTML_OUTPUT          =
 
 LATEX_OUTPUT          =
 
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard header.
 
 HTML_HEADER          =
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard footer.
 
 HTML_FOOTER          =
@@ -94,7 +94,7 @@ GENERATE_LATEX       = NO
 GENERATE_HTML        = YES
 
 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in 
+# include brief member descriptions after the members that are listed in
 # the file and class documentation (similar to JavaDoc).
 # Set to NO to disable this.
 
@@ -110,22 +110,22 @@ FULL_PATH_NAMES = NO
 # configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag is used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
 INPUT            =	.
 
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
 # blank all files are included.
 
 FILE_PATTERNS    =	*.h *.cpp *.c *.dox
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
 # the \include command).
 
 EXAMPLE_PATH     = .
@@ -137,16 +137,16 @@ EXAMPLE_PATH     = .
 RECURSIVE        = NO
 
 # The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program 
+# invoke to filter for each input file. Doxygen will invoke the filter program
 # by executing (via popen()) the command <filter> <input-file>, where <filter>
 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an
 # input file. Doxygen will then use the output that the filter program writes
 # to standard output.
 
-INPUT_FILTER     = 
+INPUT_FILTER     =
 
 #---------------------------------------------------------------------------
-# Configuration options related to the preprocessor 
+# Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
 # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
@@ -156,7 +156,7 @@ INPUT_FILTER     =
 ENABLE_PREPROCESSING = YES
 
 # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional 
+# names in the source code. If set to NO (the default) only conditional
 # compilation will be performed.
 
 MACRO_EXPANSION = NO
@@ -187,10 +187,10 @@ PREDEFINED =
 EXPAND_ONLY_PREDEF = NO
 
 #---------------------------------------------------------------------------
-# Configuration options related to external references 
+# Configuration options related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES tag can be used to specify one or more tagfiles. 
+# The TAGFILES tag can be used to specify one or more tagfiles.
 
 TAGFILES         =
 
@@ -211,10 +211,10 @@ ALLEXTERNALS     = NO
 PERL_PATH        = /usr/local/bin/perl
 
 #---------------------------------------------------------------------------
-# Configuration options related to the search engine 
+# Configuration options related to the search engine
 #---------------------------------------------------------------------------
 
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# The SEARCHENGINE tag specifies whether or not a search engine should be
 # used. If set to NO the values of all tags below this one will be ignored.
 
 SEARCHENGINE     = NO
@@ -226,13 +226,13 @@ SEARCHENGINE     = NO
 CGI_NAME         = search.cgi
 
 # The CGI_URL tag should be the absolute URL to the directory where the
-# cgi binaries are located. See the documentation of your http daemon for 
+# cgi binaries are located. See the documentation of your http daemon for
 # details.
 
 CGI_URL          =
 
 # The DOC_URL tag should be the absolute URL to the directory where the
-# documentation is located. If left blank the absolute path to the 
+# documentation is located. If left blank the absolute path to the
 # documentation, with file:// prepended to it, will be used.
 
 DOC_URL          =
@@ -248,7 +248,7 @@ DOC_ABSPATH      =
 
 BIN_ABSPATH      = /usr/local/bin/
 
-# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
 # documentation generated for other projects. This allows doxysearch to search
 # the documentation for these projects as well.
 
diff --git a/frmts/iso8211/ddffield.cpp b/frmts/iso8211/ddffield.cpp
index b94eda2..01c361e 100644
--- a/frmts/iso8211/ddffield.cpp
+++ b/frmts/iso8211/ddffield.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ddffield.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFField class.
@@ -27,10 +26,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "iso8211.h"
+
+#include <cstdio>
+#include <cstdlib>
+
+#include <algorithm>
+
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddffield.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: ddffield.cpp 36552 2016-11-29 06:01:45Z goatbar $");
 
 // Note, we implement no constructor for this class to make instantiation
 // cheaper.  It is required that the Initialize() be called before anything
@@ -56,7 +62,7 @@ void DDFField::Initialize( DDFFieldDefn *poDefnIn, const char * pachDataIn,
 /**
  * Write out field contents to debugging file.
  *
- * A variety of information about this field, and all it's
+ * A variety of information about this field, and all its
  * subfields is written to the given debugging file handle.  Note that
  * field definition information (ala DDFFieldDefn) isn't written.
  *
@@ -66,7 +72,7 @@ void DDFField::Initialize( DDFFieldDefn *poDefnIn, const char * pachDataIn,
 void DDFField::Dump( FILE * fp )
 
 {
-    int         nMaxRepeat = 8;
+    int nMaxRepeat = 8;
 
     if( getenv("DDF_MAXDUMP") != NULL )
         nMaxRepeat = atoi(getenv("DDF_MAXDUMP"));
@@ -76,7 +82,7 @@ void DDFField::Dump( FILE * fp )
     fprintf( fp, "      DataSize = %d\n", nDataSize );
 
     fprintf( fp, "      Data = `" );
-    for( int i = 0; i < MIN(nDataSize,40); i++ )
+    for( int i = 0; i < std::min(nDataSize, 40); i++ )
     {
         if( pachData[i] < 32 || pachData[i] > 126 )
             fprintf( fp, "\\%02X", ((unsigned char *) pachData)[i] );
@@ -91,9 +97,9 @@ void DDFField::Dump( FILE * fp )
 /* -------------------------------------------------------------------- */
 /*      dump the data of the subfields.                                 */
 /* -------------------------------------------------------------------- */
-    int         iOffset = 0, nLoopCount;
+    int iOffset = 0;
 
-    for( nLoopCount = 0; nLoopCount < GetRepeatCount(); nLoopCount++ )
+    for( int nLoopCount = 0; nLoopCount < GetRepeatCount(); nLoopCount++ )
     {
         if( nLoopCount > nMaxRepeat )
         {
@@ -103,11 +109,10 @@ void DDFField::Dump( FILE * fp )
 
         for( int i = 0; i < poDefn->GetSubfieldCount(); i++ )
         {
-            int         nBytesConsumed;
-
             poDefn->GetSubfield(i)->DumpData( pachData + iOffset,
                                               nDataSize - iOffset, fp );
 
+            int nBytesConsumed = 0;
             poDefn->GetSubfield(i)->GetDataLength( pachData + iOffset,
                                                    nDataSize - iOffset,
                                                    &nBytesConsumed );
@@ -148,11 +153,10 @@ const char *DDFField::GetSubfieldData( DDFSubfieldDefn *poSFDefn,
                                        int *pnMaxBytes, int iSubfieldIndex )
 
 {
-    int         iOffset = 0;
-
     if( poSFDefn == NULL )
         return NULL;
 
+    int iOffset = 0;
     if( iSubfieldIndex > 0 && poDefn->GetFixedWidth() > 0 )
     {
         iOffset = poDefn->GetFixedWidth() * iSubfieldIndex;
@@ -163,7 +167,6 @@ const char *DDFField::GetSubfieldData( DDFSubfieldDefn *poSFDefn,
     {
         for( int iSF = 0; iSF < poDefn->GetSubfieldCount(); iSF++ )
         {
-            int nBytesConsumed;
             DDFSubfieldDefn * poThisSFDefn = poDefn->GetSubfield( iSF );
 
             if( nDataSize < iOffset )
@@ -182,6 +185,7 @@ const char *DDFField::GetSubfieldData( DDFSubfieldDefn *poSFDefn,
                 return pachData + iOffset;
             }
 
+            int nBytesConsumed = 0;
             poThisSFDefn->GetDataLength( pachData+iOffset, nDataSize - iOffset,
                                          &nBytesConsumed);
             iOffset += nBytesConsumed;
@@ -233,15 +237,16 @@ int DDFField::GetRepeatCount()
 /*      variable length field, but the count is one, so it isn't        */
 /*      much value for testing.                                         */
 /* -------------------------------------------------------------------- */
-    int         iOffset = 0, iRepeatCount = 1;
+    int iOffset = 0;
+    int iRepeatCount = 1;
 
     while( true )
     {
         for( int iSF = 0; iSF < poDefn->GetSubfieldCount(); iSF++ )
         {
-            int nBytesConsumed;
             DDFSubfieldDefn * poThisSFDefn = poDefn->GetSubfield( iSF );
 
+            int nBytesConsumed = 0;
             if( poThisSFDefn->GetWidth() > nDataSize - iOffset )
                 nBytesConsumed = poThisSFDefn->GetWidth();
             else
@@ -285,7 +290,6 @@ const char *DDFField::GetInstanceData( int nInstance,
 
 {
     int nRepeatCount = GetRepeatCount();
-    const char *pachWrkData;
 
     if( nInstance < 0 || nInstance >= nRepeatCount )
         return NULL;
@@ -296,7 +300,7 @@ const char *DDFField::GetInstanceData( int nInstance,
 /* -------------------------------------------------------------------- */
     if( poDefn->GetSubfieldCount() == 0 )
     {
-        pachWrkData = GetData();
+        const char *pachWrkData = GetData();
         if( pnInstanceSize != NULL )
             *pnInstanceSize = GetDataSize();
         return pachWrkData;
@@ -306,13 +310,12 @@ const char *DDFField::GetInstanceData( int nInstance,
 /*      Get a pointer to the start of the existing data for this        */
 /*      iteration of the field.                                         */
 /* -------------------------------------------------------------------- */
-    int         nBytesRemaining1 = 0, nBytesRemaining2 = 0;
-    DDFSubfieldDefn *poFirstSubfield;
-
-    poFirstSubfield = poDefn->GetSubfield(0);
+    int nBytesRemaining1 = 0;
+    int nBytesRemaining2 = 0;
+    DDFSubfieldDefn *poFirstSubfield = poDefn->GetSubfield(0);
 
-    pachWrkData = GetSubfieldData(poFirstSubfield, &nBytesRemaining1,
-                               nInstance);
+    const char *pachWrkData =
+        GetSubfieldData(poFirstSubfield, &nBytesRemaining1, nInstance);
     if( pachWrkData == NULL )
         return NULL;
 
@@ -322,17 +325,15 @@ const char *DDFField::GetInstanceData( int nInstance,
 /* -------------------------------------------------------------------- */
     if( pnInstanceSize != NULL )
     {
-        DDFSubfieldDefn *poLastSubfield;
-        int              nLastSubfieldWidth = 0;
-        const char          *pachLastData;
-
-        poLastSubfield = poDefn->GetSubfield(poDefn->GetSubfieldCount()-1);
+        DDFSubfieldDefn *poLastSubfield =
+            poDefn->GetSubfield(poDefn->GetSubfieldCount()-1);
 
-        pachLastData = GetSubfieldData( poLastSubfield, &nBytesRemaining2,
-                                        nInstance );
+        const char *pachLastData =
+            GetSubfieldData( poLastSubfield, &nBytesRemaining2, nInstance );
         if( pachLastData == NULL )
             return NULL;
 
+        int nLastSubfieldWidth = 0;
         poLastSubfield->GetDataLength( pachLastData, nBytesRemaining2,
                                        &nLastSubfieldWidth );
 
diff --git a/frmts/iso8211/ddffielddefn.cpp b/frmts/iso8211/ddffielddefn.cpp
index 2051478..82bc5d0 100644
--- a/frmts/iso8211/ddffielddefn.cpp
+++ b/frmts/iso8211/ddffielddefn.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ddffielddefn.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFFieldDefn class.
@@ -27,11 +26,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "iso8211.h"
+
+#include <cctype>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
-#include <ctype.h>
 
-CPL_CVSID("$Id: ddffielddefn.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: ddffielddefn.cpp 36552 2016-11-29 06:01:45Z goatbar $");
 
 #define CPLE_DiscardedFormat   1301
 
@@ -39,12 +47,19 @@ CPL_CVSID("$Id: ddffielddefn.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 /*                            DDFFieldDefn()                            */
 /************************************************************************/
 
-DDFFieldDefn::DDFFieldDefn()
-    : poModule(NULL), pszTag(NULL), _fieldName(NULL), _arrayDescr(NULL),
-      _formatControls(NULL), bRepeatingSubfields(FALSE), nFixedWidth(0),
-      _data_struct_code(dsc_elementary), _data_type_code(dtc_char_string),
-      nSubfieldCount(0), papoSubfields(NULL)
-{ }
+DDFFieldDefn::DDFFieldDefn() :
+    poModule(NULL),
+    pszTag(NULL),
+    _fieldName(NULL),
+    _arrayDescr(NULL),
+    _formatControls(NULL),
+    bRepeatingSubfields(FALSE),
+    nFixedWidth(0),
+    _data_struct_code(dsc_elementary),
+    _data_type_code(dtc_char_string),
+    nSubfieldCount(0),
+    papoSubfields(NULL)
+{}
 
 /************************************************************************/
 /*                           ~DDFFieldDefn()                            */
@@ -58,8 +73,7 @@ DDFFieldDefn::~DDFFieldDefn()
     CPLFree( _arrayDescr );
     CPLFree( _formatControls );
 
-    int i;
-    for( i = 0; i < nSubfieldCount; i++ )
+    for( int i = 0; i < nSubfieldCount; i++ )
         delete papoSubfields[i];
     CPLFree( papoSubfields );
 }
@@ -88,8 +102,8 @@ void DDFFieldDefn::AddSubfield( DDFSubfieldDefn *poNewSFDefn,
 
 {
     nSubfieldCount++;
-    papoSubfields = (DDFSubfieldDefn ** )
-        CPLRealloc( papoSubfields, sizeof(void*) * nSubfieldCount );
+    papoSubfields = static_cast<DDFSubfieldDefn **>(
+        CPLRealloc( papoSubfields, sizeof(void*) * nSubfieldCount ));
     papoSubfields[nSubfieldCount-1] = poNewSFDefn;
 
     if( bDontAddToFormat )
@@ -105,10 +119,10 @@ void DDFFieldDefn::AddSubfield( DDFSubfieldDefn *poNewSFDefn,
         _formatControls = CPLStrdup( "()" );
     }
 
-    int nOldLen = static_cast<int>(strlen(_formatControls));
+    const int nOldLen = static_cast<int>(strlen(_formatControls));
 
-    char *pszNewFormatControls = (char *)
-        CPLMalloc(nOldLen+3+strlen(poNewSFDefn->GetFormat()));
+    char *pszNewFormatControls = static_cast<char *>(
+        CPLMalloc(nOldLen+3+strlen(poNewSFDefn->GetFormat())));
 
     strcpy( pszNewFormatControls, _formatControls );
     pszNewFormatControls[nOldLen-1] = '\0';
@@ -150,9 +164,9 @@ int DDFFieldDefn::Create( const char *pszTagIn, const char *pszFieldName,
                           const char *pszFormat )
 
 {
-    CPLAssert( this->pszTag == NULL );
+    CPLAssert( pszTag == NULL );
     poModule = NULL;
-    this->pszTag = CPLStrdup( pszTagIn );
+    pszTag = CPLStrdup( pszTagIn );
     _fieldName = CPLStrdup( pszFieldName );
     _arrayDescr = CPLStrdup( pszDescription );
 
@@ -174,7 +188,7 @@ int DDFFieldDefn::Create( const char *pszTagIn, const char *pszFieldName,
 /*                         SetFormatControls()                          */
 /************************************************************************/
 
-void DDFFieldDefn::SetFormatControls(const char* pszVal)
+void DDFFieldDefn::SetFormatControls( const char* pszVal )
 {
     CPLFree(_formatControls);
     _formatControls = CPLStrdup(pszVal ? pszVal : "");
@@ -188,7 +202,7 @@ int DDFFieldDefn::GenerateDDREntry( DDFModule * poModuleIn, char **ppachData,
                                     int *pnLength )
 
 {
-    const int         iFDOffset = poModuleIn->GetFieldControlLength();
+    const int iFDOffset = poModuleIn->GetFieldControlLength();
     CPLAssert(iFDOffset >= 6 && iFDOffset <= 9);
     *pnLength = static_cast<int>(iFDOffset + strlen(_fieldName) + 1
         + strlen(_arrayDescr) + 1
@@ -202,7 +216,7 @@ int DDFFieldDefn::GenerateDDREntry( DDFModule * poModuleIn, char **ppachData,
     if( ppachData == NULL )
         return TRUE;
 
-    *ppachData = (char *) CPLMalloc( *pnLength+1 );
+    *ppachData = static_cast<char *>(CPLMalloc(*pnLength + 1));
 
     if( _data_struct_code == dsc_elementary )
         (*ppachData)[0] = '0';
@@ -267,8 +281,7 @@ int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
                               const char * pachFieldArea )
 
 {
-    int         iFDOffset = poModuleIn->GetFieldControlLength();
-    int         nCharsConsumed;
+    int iFDOffset = poModuleIn->GetFieldControlLength();
 
     poModule = poModuleIn;
 
@@ -348,6 +361,7 @@ int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
 /*      format statements.                                              */
 /* -------------------------------------------------------------------- */
 
+    int nCharsConsumed = 0;
     _fieldName =
         DDFFetchVariable( pachFieldArea + iFDOffset,
                           nFieldEntrySize - iFDOffset,
@@ -390,7 +404,7 @@ int DDFFieldDefn::Initialize( DDFModule * poModuleIn,
 /**
  * Write out field definition info to debugging file.
  *
- * A variety of information about this field definition, and all it's
+ * A variety of information about this field definition, and all its
  * subfields is written to the give debugging file handle.
  *
  * @param fp The standard IO file handle to write to.  i.e. stderr
@@ -426,7 +440,7 @@ void DDFFieldDefn::Dump( FILE * fp )
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         pszValue = "(unknown)";
     }
 
@@ -463,7 +477,7 @@ void DDFFieldDefn::Dump( FILE * fp )
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         pszValue = "(unknown)";
         break;
     }
@@ -483,8 +497,7 @@ void DDFFieldDefn::Dump( FILE * fp )
 int DDFFieldDefn::BuildSubfields()
 
 {
-    char        **papszSubfieldNames;
-    const char  *pszSublist = _arrayDescr;
+    const char *pszSublist = _arrayDescr;
 
 /* -------------------------------------------------------------------- */
 /*      It is valid to define a field with _arrayDesc                   */
@@ -500,7 +513,7 @@ int DDFFieldDefn::BuildSubfields()
 /*      '*' in the subfield list.                                       */
 /* -------------------------------------------------------------------- */
     if( strrchr(pszSublist, '*') != NULL )
-        pszSublist = strrchr(pszSublist,'*');
+        pszSublist = strrchr(pszSublist, '*');
 
 /* -------------------------------------------------------------------- */
 /*      Strip off the repeating marker, when it occurs, but mark our    */
@@ -515,13 +528,13 @@ int DDFFieldDefn::BuildSubfields()
 /* -------------------------------------------------------------------- */
 /*      split list of fields .                                          */
 /* -------------------------------------------------------------------- */
-    papszSubfieldNames = CSLTokenizeStringComplex( pszSublist, "!",
-                                                   FALSE, FALSE );
+    char **papszSubfieldNames =
+        CSLTokenizeStringComplex( pszSublist, "!", FALSE, FALSE );
 
 /* -------------------------------------------------------------------- */
 /*      minimally initialize the subfields.  More will be done later.   */
 /* -------------------------------------------------------------------- */
-    int nSFCount = CSLCount( papszSubfieldNames );
+    const int nSFCount = CSLCount( papszSubfieldNames );
     for( int iSF = 0; iSF < nSFCount; iSF++ )
     {
         DDFSubfieldDefn *poSFDefn = new DDFSubfieldDefn;
@@ -551,10 +564,9 @@ int DDFFieldDefn::BuildSubfields()
 char *DDFFieldDefn::ExtractSubstring( const char * pszSrc )
 
 {
-    int         nBracket=0, i;
-    char        *pszReturn;
-
-    for( i = 0;
+    int nBracket = 0;
+    int i = 0;  // Used after for.
+    for( ;
          pszSrc[i] != '\0' && (nBracket > 0 || pszSrc[i] != ',');
          i++ )
     {
@@ -564,6 +576,7 @@ char *DDFFieldDefn::ExtractSubstring( const char * pszSrc )
             nBracket--;
     }
 
+    char *pszReturn = NULL;
     if( pszSrc[0] == '(' )
     {
         pszReturn = CPLStrdup( pszSrc + 1 );
@@ -585,30 +598,29 @@ char *DDFFieldDefn::ExtractSubstring( const char * pszSrc )
 char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
 
 {
-    size_t      nDestMax = 32;
-    char       *pszDest = (char *) CPLMalloc(nDestMax+1);
-    size_t      iSrc, iDst;
-    int         nRepeat = 0;
+    size_t nDestMax = 32;
+    char *pszDest = static_cast<char *>(CPLMalloc(nDestMax + 1));
+    int nRepeat = 0;
 
-    iSrc = 0;
-    iDst = 0;
+    size_t iSrc = 0;
+    size_t iDst = 0;
     pszDest[0] = '\0';
 
     while( pszSrc[iSrc] != '\0' )
     {
-        /* This is presumably an extra level of brackets around some
-           binary stuff related to rescanning which we don't care to do
-           (see 6.4.3.3 of the standard.  We just strip off the extra
-           layer of brackets */
+        // This is presumably an extra level of brackets around some
+        // binary stuff related to rescanning which we don't care to do
+        // (see 6.4.3.3 of the standard.  We just strip off the extra
+        // layer of brackets.
         if( (iSrc == 0 || pszSrc[iSrc-1] == ',') && pszSrc[iSrc] == '(' )
         {
-            char       *pszContents = ExtractSubstring( pszSrc+iSrc );
-            char       *pszExpandedContents = ExpandFormat( pszContents );
+            char *pszContents = ExtractSubstring( pszSrc+iSrc );
+            char *pszExpandedContents = ExpandFormat( pszContents );
 
             if( strlen(pszExpandedContents) + strlen(pszDest) + 1 > nDestMax )
             {
                 nDestMax = 2 * (strlen(pszExpandedContents) + strlen(pszDest));
-                pszDest = (char *) CPLRealloc(pszDest,nDestMax+1);
+                pszDest = static_cast<char *>(CPLRealloc(pszDest,nDestMax + 1));
             }
 
             strcat( pszDest, pszExpandedContents );
@@ -620,27 +632,29 @@ char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
             CPLFree( pszExpandedContents );
         }
 
-        /* this is a repeated subclause */
+        // This is a repeated subclause.
         else if( (iSrc == 0 || pszSrc[iSrc-1] == ',')
                  && isdigit(pszSrc[iSrc]) )
         {
-            const char *pszNext;
             nRepeat = atoi(pszSrc+iSrc);
 
-            // skip over repeat count.
-            for( pszNext = pszSrc+iSrc; isdigit(*pszNext); pszNext++ )
+            // Skip over repeat count.
+            const char *pszNext = pszSrc + iSrc;  // Used after for.
+            for( ; isdigit(*pszNext); pszNext++ )
                 iSrc++;
 
-            char       *pszContents = ExtractSubstring( pszNext );
-            char       *pszExpandedContents = ExpandFormat( pszContents );
+            char *pszContents = ExtractSubstring( pszNext );
+            char *pszExpandedContents = ExpandFormat( pszContents );
 
             for( int i = 0; i < nRepeat; i++ )
             {
-                if( strlen(pszExpandedContents) + strlen(pszDest) + 1 + 1 > nDestMax )
+                if( strlen(pszExpandedContents) + strlen(pszDest) + 1 + 1 >
+                    nDestMax )
                 {
                     nDestMax =
                         2 * (strlen(pszExpandedContents) + strlen(pszDest) + 1);
-                    pszDest = (char *) CPLRealloc(pszDest,nDestMax+1);
+                    pszDest =
+                        static_cast<char *>(CPLRealloc(pszDest,nDestMax + 1));
                 }
 
                 strcat( pszDest, pszExpandedContents );
@@ -663,7 +677,7 @@ char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
             if( iDst+1 >= nDestMax )
             {
                 nDestMax = 2 * iDst;
-                pszDest = (char *) CPLRealloc(pszDest,nDestMax);
+                pszDest = static_cast<char *>(CPLRealloc(pszDest, nDestMax));
             }
 
             pszDest[iDst++] = pszSrc[iSrc++];
@@ -685,9 +699,6 @@ char *DDFFieldDefn::ExpandFormat( const char * pszSrc )
 int DDFFieldDefn::ApplyFormats()
 
 {
-    char        *pszFormatList;
-    char        **papszFormatItems;
-
 /* -------------------------------------------------------------------- */
 /*      Verify that the format string is contained within brackets.     */
 /* -------------------------------------------------------------------- */
@@ -695,7 +706,7 @@ int DDFFieldDefn::ApplyFormats()
         || _formatControls[0] != '('
         || _formatControls[strlen(_formatControls)-1] != ')' )
     {
-        CPLError( CE_Warning, (CPLErrorNum)CPLE_DiscardedFormat,
+        CPLError( CE_Warning, static_cast<CPLErrorNum>(CPLE_DiscardedFormat),
                   "Format controls for `%s' field missing brackets:%s",
                   pszTag, _formatControls );
 
@@ -706,12 +717,12 @@ int DDFFieldDefn::ApplyFormats()
 /*      Duplicate the string, and strip off the brackets.               */
 /* -------------------------------------------------------------------- */
 
-    pszFormatList = ExpandFormat( _formatControls );
+    char *pszFormatList = ExpandFormat( _formatControls );
 
 /* -------------------------------------------------------------------- */
 /*      Tokenize based on commas.                                       */
 /* -------------------------------------------------------------------- */
-    papszFormatItems =
+    char **papszFormatItems =
         CSLTokenizeStringComplex(pszFormatList, ",", FALSE, FALSE );
 
     CPLFree( pszFormatList );
@@ -719,15 +730,13 @@ int DDFFieldDefn::ApplyFormats()
 /* -------------------------------------------------------------------- */
 /*      Apply the format items to subfields.                            */
 /* -------------------------------------------------------------------- */
-    int iFormatItem;
+    int iFormatItem = 0;  // Used after for.
 
-    for( iFormatItem = 0;
+    for( ;
          papszFormatItems[iFormatItem] != NULL;
          iFormatItem++ )
     {
-        const char      *pszPastPrefix;
-
-        pszPastPrefix = papszFormatItems[iFormatItem];
+        const char *pszPastPrefix = papszFormatItems[iFormatItem];
         while( *pszPastPrefix >= '0' && *pszPastPrefix <= '9' )
             pszPastPrefix++;
 
@@ -739,7 +748,7 @@ int DDFFieldDefn::ApplyFormats()
 
         if( iFormatItem >= nSubfieldCount )
         {
-            CPLError( CE_Warning, (CPLErrorNum)CPLE_DiscardedFormat,
+          CPLError( CE_Warning, static_cast<CPLErrorNum>(CPLE_DiscardedFormat),
                       "Got more formats than subfields for field `%s'.",
                       pszTag );
             break;
@@ -759,7 +768,7 @@ int DDFFieldDefn::ApplyFormats()
 
     if( iFormatItem < nSubfieldCount )
     {
-        CPLError( CE_Warning, (CPLErrorNum)CPLE_DiscardedFormat,
+        CPLError( CE_Warning, static_cast<CPLErrorNum>(CPLE_DiscardedFormat),
                   "Got less formats than subfields for field `%s'.",
                   pszTag );
         return FALSE;
@@ -778,7 +787,9 @@ int DDFFieldDefn::ApplyFormats()
             break;
         }
         else
+        {
             nFixedWidth += papoSubfields[i]->GetWidth();
+        }
     }
 
     return TRUE;
@@ -789,14 +800,13 @@ int DDFFieldDefn::ApplyFormats()
 /************************************************************************/
 
 /**
- * Find a subfield definition by it's mnemonic tag.
+ * Find a subfield definition by its mnemonic tag.
  *
  * @param pszMnemonic The name of the field.
  *
  * @return The subfield pointer, or NULL if there isn't any such subfield.
  */
 
-
 DDFSubfieldDefn *DDFFieldDefn::FindSubfieldDefn( const char * pszMnemonic )
 
 {
@@ -812,7 +822,7 @@ DDFSubfieldDefn *DDFFieldDefn::FindSubfieldDefn( const char * pszMnemonic )
 /************************************************************************/
 /*                            GetSubfield()                             */
 /*                                                                      */
-/*      Fetch a subfield by it's index.                                 */
+/*      Fetch a subfield by its index.                                 */
 /************************************************************************/
 
 /**
@@ -828,7 +838,7 @@ DDFSubfieldDefn *DDFFieldDefn::GetSubfield( int i )
 {
     if( i < 0 || i >= nSubfieldCount )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return NULL;
     }
 
@@ -849,12 +859,11 @@ char *DDFFieldDefn::GetDefaultValue( int *pnSize )
 /* -------------------------------------------------------------------- */
 /*      Loop once collecting the sum of the subfield lengths.           */
 /* -------------------------------------------------------------------- */
-    int iSubfield;
     int nTotalSize = 0;
 
-    for( iSubfield = 0; iSubfield < nSubfieldCount; iSubfield++ )
+    for( int iSubfield = 0; iSubfield < nSubfieldCount; iSubfield++ )
     {
-        int nSubfieldSize;
+        int nSubfieldSize = 0;
 
         if( !papoSubfields[iSubfield]->GetDefaultValue( NULL, 0,
                                                         &nSubfieldSize ) )
@@ -865,7 +874,7 @@ char *DDFFieldDefn::GetDefaultValue( int *pnSize )
 /* -------------------------------------------------------------------- */
 /*      Allocate buffer.                                                */
 /* -------------------------------------------------------------------- */
-    char *pachData = (char *) CPLMalloc( nTotalSize );
+    char *pachData = static_cast<char *>(CPLMalloc( nTotalSize ));
 
     if( pnSize != NULL )
         *pnSize = nTotalSize;
@@ -874,14 +883,14 @@ char *DDFFieldDefn::GetDefaultValue( int *pnSize )
 /*      Loop again, collecting actual default values.                   */
 /* -------------------------------------------------------------------- */
     int nOffset = 0;
-    for( iSubfield = 0; iSubfield < nSubfieldCount; iSubfield++ )
+    for( int iSubfield = 0; iSubfield < nSubfieldCount; iSubfield++ )
     {
         int nSubfieldSize;
 
         if( !papoSubfields[iSubfield]->GetDefaultValue(
                 pachData + nOffset, nTotalSize - nOffset, &nSubfieldSize ) )
         {
-            CPLAssert( FALSE );
+            CPLAssert( false );
             return NULL;
         }
 
diff --git a/frmts/iso8211/ddfmodule.cpp b/frmts/iso8211/ddfmodule.cpp
index ec1b943..93fbee2 100644
--- a/frmts/iso8211/ddfmodule.cpp
+++ b/frmts/iso8211/ddfmodule.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ddfmodule.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFModule class.
@@ -28,10 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "iso8211.h"
+
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: ddfmodule.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: ddfmodule.cpp 36552 2016-11-29 06:01:45Z goatbar $");
 
 /************************************************************************/
 /*                             DDFModule()                              */
@@ -42,31 +51,28 @@ CPL_CVSID("$Id: ddfmodule.cpp 33717 2016-03-14 06:29:14Z goatbar $");
  */
 
 DDFModule::DDFModule() :
-    nFirstRecordOffset(0)
+    fpDDF(NULL),
+    bReadOnly(TRUE),
+    nFirstRecordOffset(0),
+    _interchangeLevel('\0'),
+    _inlineCodeExtensionIndicator('\0'),
+    _versionNumber('\0'),
+    _appIndicator('\0'),
+    _fieldControlLength(9),
+    _recLength(0),
+    _leaderIden('L'),
+    _fieldAreaStart(0),
+    _sizeFieldLength(0),
+    _sizeFieldPos(0),
+    _sizeFieldTag(0),
+    nFieldDefnCount(0),
+    papoFieldDefns(NULL),
+    poRecord(NULL),
+    nCloneCount(0),
+    nMaxCloneCount(0),
+    papoClones(NULL)
 {
-    nFieldDefnCount = 0;
-    papoFieldDefns = NULL;
-    poRecord = NULL;
-
-    papoClones = NULL;
-    nCloneCount = nMaxCloneCount = 0;
-
-    fpDDF = NULL;
-    bReadOnly = TRUE;
-
-    _interchangeLevel = '\0';
-    _inlineCodeExtensionIndicator = '\0';
-    _versionNumber = '\0';
-    _appIndicator = '\0';
-    _fieldControlLength = 9;
     strcpy( _extendedCharSet, " ! " );
-
-    _recLength = 0;
-    _leaderIden = 'L';
-    _fieldAreaStart = 0;
-    _sizeFieldLength = 0;
-    _sizeFieldPos = 0;
-    _sizeFieldTag = 0;
 }
 
 /************************************************************************/
@@ -271,9 +277,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
 /* -------------------------------------------------------------------- */
 /*      Read the whole record info memory.                              */
 /* -------------------------------------------------------------------- */
-    char        *pachRecord;
-
-    pachRecord = (char *) CPLMalloc(_recLength);
+    char *pachRecord = (char *) CPLMalloc(_recLength);
     memcpy( pachRecord, achLeader, nLeaderSize );
 
     if( (int)VSIFReadL( pachRecord+nLeaderSize, 1, _recLength-nLeaderSize, fpDDF )
@@ -310,7 +314,6 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
         char    szTag[128];
         int     nEntryOffset = nLeaderSize + i*nFieldEntryWidth;
         int     nFieldLength, nFieldPos;
-        DDFFieldDefn *poFDefn;
 
         strncpy( szTag, pachRecord+nEntryOffset, _sizeFieldTag );
         szTag[_sizeFieldTag] = '\0';
@@ -333,7 +336,7 @@ int DDFModule::Open( const char * pszFilename, int bFailQuietly )
             return FALSE;
         }
 
-        poFDefn = new DDFFieldDefn();
+        DDFFieldDefn *poFDefn = new DDFFieldDefn();
         if( poFDefn->Initialize( this, szTag, nFieldLength,
                                  pachRecord+_fieldAreaStart+nFieldPos ) )
             AddField( poFDefn );
@@ -476,10 +479,10 @@ int DDFModule::Create( const char *pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Write out the field descriptions themselves.                    */
 /* -------------------------------------------------------------------- */
-    for( iField=0; iField < nFieldDefnCount; iField++ )
+    for( iField = 0; iField < nFieldDefnCount; iField++ )
     {
-        char *pachData;
-        int nLength;
+        char *pachData = NULL;
+        int nLength = 0;
 
         papoFieldDefns[iField]->GenerateDDREntry( this, &pachData, &nLength );
         bRet &= VSIFWriteL( pachData, nLength, 1, fpDDF ) > 0;
@@ -694,7 +697,7 @@ void DDFModule::RemoveCloneRecord( DDFRecord * poRecordIn )
         }
     }
 
-    CPLAssert( FALSE );
+    CPLAssert( false );
 }
 
 /************************************************************************/
diff --git a/frmts/iso8211/ddfrecord.cpp b/frmts/iso8211/ddfrecord.cpp
index 1286175..11c62d5 100644
--- a/frmts/iso8211/ddfrecord.cpp
+++ b/frmts/iso8211/ddfrecord.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ddfrecord.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFRecord class.
@@ -28,10 +27,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "iso8211.h"
+
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: ddfrecord.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: ddfrecord.cpp 36552 2016-11-29 06:01:45Z goatbar $");
 
 static const int nLeaderSize = 24;
 
@@ -39,27 +49,19 @@ static const int nLeaderSize = 24;
 /*                             DDFRecord()                              */
 /************************************************************************/
 
-DDFRecord::DDFRecord( DDFModule * poModuleIn )
-
-{
-    poModule = poModuleIn;
-
-    nReuseHeader = FALSE;
-
-    nFieldOffset = 0;
-
-    nDataSize = 0;
-    pachData = NULL;
-
-    nFieldCount = 0;
-    paoFields = NULL;
-
-    bIsClone = FALSE;
-
-    _sizeFieldTag = poModuleIn->GetSizeFieldTag();
-    _sizeFieldPos = 5;
-    _sizeFieldLength = 5;
-}
+DDFRecord::DDFRecord( DDFModule * poModuleIn ) :
+    poModule(poModuleIn),
+    nReuseHeader(FALSE),
+    nFieldOffset(0),
+    _sizeFieldTag(poModuleIn->GetSizeFieldTag()),
+    _sizeFieldPos(5),
+    _sizeFieldLength(5),
+    nDataSize(0),
+    pachData(NULL),
+    nFieldCount(0),
+    paoFields(NULL),
+    bIsClone(FALSE)
+{}
 
 /************************************************************************/
 /*                             ~DDFRecord()                             */
@@ -81,7 +83,7 @@ DDFRecord::~DDFRecord()
 /**
  * Write out record contents to debugging file.
  *
- * A variety of information about this record, and all it's fields and
+ * A variety of information about this record, and all its fields and
  * subfields is written to the given debugging file handle.  Note that
  * field definition information (ala DDFFieldDefn) isn't written.
  *
@@ -125,7 +127,7 @@ int DDFRecord::Read()
 /* -------------------------------------------------------------------- */
     if( !nReuseHeader )
     {
-        return( ReadHeader() );
+        return ReadHeader();
     }
 
 /* -------------------------------------------------------------------- */
@@ -708,8 +710,7 @@ int DDFRecord::GetIntSubfield( const char * pszField, int iFieldIndex,
                                int * pnSuccess )
 
 {
-    DDFField    *poField;
-    int         nDummyErr;
+    int nDummyErr = FALSE;
 
     if( pnSuccess == NULL )
         pnSuccess = &nDummyErr;
@@ -719,16 +720,15 @@ int DDFRecord::GetIntSubfield( const char * pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
-    poField = FindField( pszField, iFieldIndex );
+    DDFField *poField = FindField( pszField, iFieldIndex );
     if( poField == NULL )
         return 0;
 
 /* -------------------------------------------------------------------- */
 /*      Get the subfield definition                                     */
 /* -------------------------------------------------------------------- */
-    DDFSubfieldDefn     *poSFDefn;
-
-    poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
+    DDFSubfieldDefn *poSFDefn =
+        poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
     if( poSFDefn == NULL )
         return 0;
 
@@ -779,12 +779,12 @@ int DDFRecord::GetIntSubfield( const char * pszField, int iFieldIndex,
  */
 
 double DDFRecord::GetFloatSubfield( const char * pszField, int iFieldIndex,
-                                 const char * pszSubfield, int iSubfieldIndex,
+                                    const char * pszSubfield,
+                                    int iSubfieldIndex,
                                     int * pnSuccess )
 
 {
-    DDFField    *poField;
-    int         nDummyErr;
+    int nDummyErr = FALSE;
 
     if( pnSuccess == NULL )
         pnSuccess = &nDummyErr;
@@ -794,16 +794,15 @@ double DDFRecord::GetFloatSubfield( const char * pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
-    poField = FindField( pszField, iFieldIndex );
+    DDFField *poField = FindField( pszField, iFieldIndex );
     if( poField == NULL )
         return 0;
 
 /* -------------------------------------------------------------------- */
 /*      Get the subfield definition                                     */
 /* -------------------------------------------------------------------- */
-    DDFSubfieldDefn     *poSFDefn;
-
-    poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
+    DDFSubfieldDefn *poSFDefn =
+        poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
     if( poSFDefn == NULL )
         return 0;
 
@@ -859,8 +858,7 @@ DDFRecord::GetStringSubfield( const char * pszField, int iFieldIndex,
                               int * pnSuccess )
 
 {
-    DDFField    *poField;
-    int         nDummyErr;
+    int nDummyErr = FALSE;
 
     if( pnSuccess == NULL )
         pnSuccess = &nDummyErr;
@@ -870,16 +868,15 @@ DDFRecord::GetStringSubfield( const char * pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
-    poField = FindField( pszField, iFieldIndex );
+    DDFField *poField = FindField( pszField, iFieldIndex );
     if( poField == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Get the subfield definition                                     */
 /* -------------------------------------------------------------------- */
-    DDFSubfieldDefn     *poSFDefn;
-
-    poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
+    DDFSubfieldDefn *poSFDefn =
+        poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
     if( poSFDefn == NULL )
         return NULL;
 
@@ -899,7 +896,7 @@ DDFRecord::GetStringSubfield( const char * pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
     *pnSuccess = TRUE;
 
-    return( poSFDefn->ExtractStringData( l_pachData, nBytesRemaining, NULL ) );
+    return poSFDefn->ExtractStringData( l_pachData, nBytesRemaining, NULL );
 }
 
 /************************************************************************/
@@ -911,7 +908,7 @@ DDFRecord::GetStringSubfield( const char * pszField, int iFieldIndex,
  *
  * This method is used to make a copy of a record that will become (mostly)
  * the properly of application.  However, it is automatically destroyed if
- * the DDFModule it was created relative to is destroyed, as it's field
+ * the DDFModule it was created relative to is destroyed, as its field
  * and subfield definitions relate to that DDFModule.  However, it does
  * persist even when the record returned by DDFModule::ReadRecord() is
  * invalidated, such as when reading a new record.  This allows an application
@@ -925,9 +922,7 @@ DDFRecord::GetStringSubfield( const char * pszField, int iFieldIndex,
 DDFRecord * DDFRecord::Clone()
 
 {
-    DDFRecord   *poNR;
-
-    poNR = new DDFRecord( poModule );
+    DDFRecord *poNR = new DDFRecord( poModule );
 
     poNR->nReuseHeader = FALSE;
     poNR->nFieldOffset = nFieldOffset;
@@ -985,9 +980,7 @@ DDFRecord *DDFRecord::CloneOn( DDFModule *poTargetModule )
 /*      Verify that all fields have a corresponding field definition    */
 /*      on the target module.                                           */
 /* -------------------------------------------------------------------- */
-    int         i;
-
-    for( i = 0; i < nFieldCount; i++ )
+    for( int i = 0; i < nFieldCount; i++ )
     {
         DDFFieldDefn    *poDefn = paoFields[i].GetFieldDefn();
 
@@ -998,20 +991,16 @@ DDFRecord *DDFRecord::CloneOn( DDFModule *poTargetModule )
 /* -------------------------------------------------------------------- */
 /*      Create a clone.                                                 */
 /* -------------------------------------------------------------------- */
-    DDFRecord   *poClone;
-
-    poClone = Clone();
+    DDFRecord *poClone = Clone();
 
 /* -------------------------------------------------------------------- */
 /*      Update all internal information to reference other module.      */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nFieldCount; i++ )
+    for( int i = 0; i < nFieldCount; i++ )
     {
-        DDFField        *poField = poClone->paoFields+i;
-        DDFFieldDefn    *poDefn;
-
-        poDefn = poTargetModule->FindFieldDefn(
-            poField->GetFieldDefn()->GetName() );
+        DDFField *poField = poClone->paoFields + i;
+        DDFFieldDefn *poDefn =
+            poTargetModule->FindFieldDefn( poField->GetFieldDefn()->GetName() );
 
         poField->Initialize( poDefn, poField->GetData(),
                              poField->GetDataSize() );
@@ -1024,7 +1013,6 @@ DDFRecord *DDFRecord::CloneOn( DDFModule *poTargetModule )
     return poClone;
 }
 
-
 /************************************************************************/
 /*                            DeleteField()                             */
 /************************************************************************/
@@ -1121,7 +1109,7 @@ int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
 
     if( iTarget == nFieldCount )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return FALSE;
     }
 
@@ -1179,9 +1167,7 @@ int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
     {
         for( i = iTarget+1; i < nFieldCount; i++ )
         {
-            char *pszOldDataLocation;
-
-            pszOldDataLocation = (char *) paoFields[i].GetData();
+            char *pszOldDataLocation = (char *) paoFields[i].GetData();
 
             paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
                                      pszOldDataLocation + nBytesToAdd,
@@ -1192,9 +1178,7 @@ int DDFRecord::ResizeField( DDFField *poField, int nNewDataSize )
     {
         for( i = nFieldCount-1; i > iTarget; i-- )
         {
-            char *pszOldDataLocation;
-
-            pszOldDataLocation = (char *) paoFields[i].GetData();
+            char *pszOldDataLocation = (char *) paoFields[i].GetData();
 
             paoFields[i].Initialize( paoFields[i].GetFieldDefn(),
                                      pszOldDataLocation + nBytesToAdd,
@@ -1233,9 +1217,7 @@ DDFField *DDFRecord::AddField( DDFFieldDefn *poDefn )
 /*      Reallocate the fields array larger by one, and initialize       */
 /*      the new field.                                                  */
 /* -------------------------------------------------------------------- */
-    DDFField    *paoNewFields;
-
-    paoNewFields = new DDFField[nFieldCount+1];
+    DDFField *paoNewFields = new DDFField[nFieldCount+1];
     if( nFieldCount > 0 )
     {
         memcpy( paoNewFields, paoFields, sizeof(DDFField) * nFieldCount );
@@ -1316,20 +1298,17 @@ DDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField,
     if( iIndexWithinField == nRepeatCount
         || !poField->GetFieldDefn()->IsRepeating() )
     {
-        char    *pachFieldData;
-        int     nOldSize;
-
         if( !poField->GetFieldDefn()->IsRepeating() && iIndexWithinField != 0 )
             return FALSE;
 
-        nOldSize = poField->GetDataSize();
+        int nOldSize = poField->GetDataSize();
         if( nOldSize == 0 )
             nOldSize++; // for added DDF_FIELD_TERMINATOR.
 
         if( !ResizeField( poField, nOldSize + nRawDataSize ) )
             return FALSE;
 
-        pachFieldData = (char *) poField->GetData();
+        char *pachFieldData = (char *) poField->GetData();
         memcpy( pachFieldData + nOldSize - 1,
                 pachRawData, nRawDataSize );
         pachFieldData[nOldSize+nRawDataSize-1] = DDF_FIELD_TERMINATOR;
@@ -1341,15 +1320,14 @@ DDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField,
 /*      Get a pointer to the start of the existing data for this        */
 /*      iteration of the field.                                         */
 /* -------------------------------------------------------------------- */
-    const char *pachWrkData;
-    int         nInstanceSize;
+    const char *pachWrkData = NULL;
+    int nInstanceSize = 0;
 
     // We special case this to avoid a lot of warnings when initializing
     // the field the first time.
     if( poField->GetDataSize() == 0 )
     {
         pachWrkData = poField->GetData();
-        nInstanceSize = 0;
     }
     else
     {
@@ -1360,15 +1338,12 @@ DDFRecord::SetFieldRaw( DDFField *poField, int iIndexWithinField,
 /* -------------------------------------------------------------------- */
 /*      Create new image of this whole field.                           */
 /* -------------------------------------------------------------------- */
-    char        *pachNewImage;
-    int         nPreBytes, nPostBytes, nNewFieldSize;
-
-    nNewFieldSize = poField->GetDataSize() - nInstanceSize + nRawDataSize;
+    int nNewFieldSize = poField->GetDataSize() - nInstanceSize + nRawDataSize;
 
-    pachNewImage = (char *) CPLMalloc(nNewFieldSize);
+    char *pachNewImage = (char *) CPLMalloc(nNewFieldSize);
 
-    nPreBytes = static_cast<int>(pachWrkData - poField->GetData());
-    nPostBytes = poField->GetDataSize() - nPreBytes - nInstanceSize;
+    int nPreBytes = static_cast<int>(pachWrkData - poField->GetData());
+    int nPostBytes = poField->GetDataSize() - nPreBytes - nInstanceSize;
 
     memcpy( pachNewImage, poField->GetData(), nPreBytes );
     memcpy( pachNewImage + nPreBytes + nRawDataSize,
@@ -1419,13 +1394,12 @@ DDFRecord::UpdateFieldRaw( DDFField *poField, int iIndexWithinField,
 /* -------------------------------------------------------------------- */
 /*      Figure out how much pre and post data there is.                 */
 /* -------------------------------------------------------------------- */
-    char *pachWrkData;
-    int         nInstanceSize, nPostBytes, nPreBytes;
+    int nInstanceSize = 0;
 
-    pachWrkData = (char *) poField->GetInstanceData( iIndexWithinField,
-                                                     &nInstanceSize );
-    nPreBytes = static_cast<int>(pachWrkData - poField->GetData() + nStartOffset);
-    nPostBytes = poField->GetDataSize() - nPreBytes - nOldSize;
+    char *pachWrkData = (char *) poField->GetInstanceData( iIndexWithinField,
+                                                           &nInstanceSize );
+    int nPreBytes = static_cast<int>(pachWrkData - poField->GetData() + nStartOffset);
+    int nPostBytes = poField->GetDataSize() - nPreBytes - nOldSize;
 
 /* -------------------------------------------------------------------- */
 /*      If we aren't changing the size, just copy over the existing     */
@@ -1503,11 +1477,8 @@ int DDFRecord::ResetDirectory()
 /* -------------------------------------------------------------------- */
     if( nDirSize != nFieldOffset )
     {
-        char *pachNewData;
-        int  nNewDataSize;
-
-        nNewDataSize = nDataSize - nFieldOffset + nDirSize;
-        pachNewData = (char *) CPLMalloc(nNewDataSize);
+        const int nNewDataSize = nDataSize - nFieldOffset + nDirSize;
+        char *pachNewData = (char *) CPLMalloc(nNewDataSize);
         memcpy( pachNewData + nDirSize,
                 pachData + nFieldOffset,
                 nNewDataSize - nDirSize );
@@ -1578,14 +1549,13 @@ int DDFRecord::CreateDefaultFieldInstance( DDFField *poField,
                                            int iIndexWithinField )
 
 {
-    int nRawSize, nSuccess;
-    char *pachRawData;
-
-    pachRawData = poField->GetFieldDefn()->GetDefaultValue( &nRawSize );
+    int nRawSize = 0;
+    char *pachRawData = poField->GetFieldDefn()->GetDefaultValue( &nRawSize );
     if( pachRawData == NULL )
         return FALSE;
 
-    nSuccess = SetFieldRaw( poField, iIndexWithinField, pachRawData, nRawSize);
+    const int nSuccess =
+        SetFieldRaw( poField, iIndexWithinField, pachRawData, nRawSize);
 
     CPLFree( pachRawData );
 
@@ -1622,18 +1592,15 @@ int DDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
-    DDFField *poField;
-
-    poField = FindField( pszField, iFieldIndex );
+    DDFField *poField = FindField( pszField, iFieldIndex );
     if( poField == NULL )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Get the subfield definition                                     */
 /* -------------------------------------------------------------------- */
-    DDFSubfieldDefn     *poSFDefn;
-
-    poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
+    DDFSubfieldDefn *poSFDefn =
+        poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
     if( poSFDefn == NULL )
         return FALSE;
 
@@ -1689,22 +1656,22 @@ int DDFRecord::SetStringSubfield( const char *pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      We will need to resize the raw data.                            */
 /* -------------------------------------------------------------------- */
-    const char *pachFieldInstData;
-    int         nInstanceSize, nStartOffset, nSuccess;
-    char *pachNewData;
+    int nInstanceSize = 0;
 
-    pachFieldInstData = poField->GetInstanceData( iFieldIndex,
-                                                  &nInstanceSize );
+    const char *pachFieldInstData = poField->GetInstanceData( iFieldIndex,
+                                                              &nInstanceSize );
 
-    nStartOffset = static_cast<int>(pachSubfieldData - pachFieldInstData);
+    const int nStartOffset =
+        static_cast<int>(pachSubfieldData - pachFieldInstData);
 
-    pachNewData = (char *) CPLMalloc(nFormattedLen);
+    char *pachNewData = (char *) CPLMalloc(nFormattedLen);
     poSFDefn->FormatStringValue( pachNewData, nFormattedLen, NULL,
                                  pszValue, nValueLength );
 
-    nSuccess = UpdateFieldRaw( poField, iFieldIndex,
-                               nStartOffset, nExistingLength,
-                               pachNewData, nFormattedLen );
+    const int nSuccess =
+        UpdateFieldRaw( poField, iFieldIndex,
+                        nStartOffset, nExistingLength,
+                        pachNewData, nFormattedLen );
 
     CPLFree( pachNewData );
 
@@ -1738,18 +1705,15 @@ int DDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
-    DDFField *poField;
-
-    poField = FindField( pszField, iFieldIndex );
+    DDFField *poField = FindField( pszField, iFieldIndex );
     if( poField == NULL )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Get the subfield definition                                     */
 /* -------------------------------------------------------------------- */
-    DDFSubfieldDefn     *poSFDefn;
-
-    poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
+    DDFSubfieldDefn *poSFDefn =
+        poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
     if( poSFDefn == NULL )
         return FALSE;
 
@@ -1804,22 +1768,22 @@ int DDFRecord::SetIntSubfield( const char *pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      We will need to resize the raw data.                            */
 /* -------------------------------------------------------------------- */
-    const char *pachFieldInstData;
-    int         nInstanceSize, nStartOffset, nSuccess;
-    char *pachNewData;
+    int nInstanceSize = 0;
 
-    pachFieldInstData = poField->GetInstanceData( iFieldIndex,
-                                                  &nInstanceSize );
+    const char *pachFieldInstData = poField->GetInstanceData( iFieldIndex,
+                                                              &nInstanceSize );
 
-    nStartOffset = static_cast<int>(pachSubfieldData - pachFieldInstData);
+    const int nStartOffset =
+        static_cast<int>(pachSubfieldData - pachFieldInstData);
 
-    pachNewData = (char *) CPLMalloc(nFormattedLen);
+    char *pachNewData = (char *) CPLMalloc(nFormattedLen);
     poSFDefn->FormatIntValue( pachNewData, nFormattedLen, NULL,
                               nNewValue );
 
-    nSuccess = UpdateFieldRaw( poField, iFieldIndex,
-                               nStartOffset, nExistingLength,
-                               pachNewData, nFormattedLen );
+    const int nSuccess =
+        UpdateFieldRaw( poField, iFieldIndex,
+                        nStartOffset, nExistingLength,
+                        pachNewData, nFormattedLen );
 
     CPLFree( pachNewData );
 
@@ -1853,18 +1817,15 @@ int DDFRecord::SetFloatSubfield( const char *pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      Fetch the field. If this fails, return zero.                    */
 /* -------------------------------------------------------------------- */
-    DDFField *poField;
-
-    poField = FindField( pszField, iFieldIndex );
+    DDFField *poField = FindField( pszField, iFieldIndex );
     if( poField == NULL )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Get the subfield definition                                     */
 /* -------------------------------------------------------------------- */
-    DDFSubfieldDefn     *poSFDefn;
-
-    poSFDefn = poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
+    DDFSubfieldDefn *poSFDefn =
+        poField->GetFieldDefn()->FindSubfieldDefn( pszSubfield );
     if( poSFDefn == NULL )
         return FALSE;
 
@@ -1919,22 +1880,21 @@ int DDFRecord::SetFloatSubfield( const char *pszField, int iFieldIndex,
 /* -------------------------------------------------------------------- */
 /*      We will need to resize the raw data.                            */
 /* -------------------------------------------------------------------- */
-    const char *pachFieldInstData;
-    int         nInstanceSize, nStartOffset, nSuccess;
-    char *pachNewData;
+    int nInstanceSize = 0;
 
-    pachFieldInstData = poField->GetInstanceData( iFieldIndex,
-                                                  &nInstanceSize );
+    const char *pachFieldInstData =
+        poField->GetInstanceData( iFieldIndex, &nInstanceSize );
 
-    nStartOffset = (int) (pachSubfieldData - pachFieldInstData);
+    const int nStartOffset = (int) (pachSubfieldData - pachFieldInstData);
 
-    pachNewData = (char *) CPLMalloc(nFormattedLen);
+    char *pachNewData = (char *) CPLMalloc(nFormattedLen);
     poSFDefn->FormatFloatValue( pachNewData, nFormattedLen, NULL,
                               dfNewValue );
 
-    nSuccess = UpdateFieldRaw( poField, iFieldIndex,
-                               nStartOffset, nExistingLength,
-                               pachNewData, nFormattedLen );
+    const int nSuccess =
+        UpdateFieldRaw( poField, iFieldIndex,
+                        nStartOffset, nExistingLength,
+                        pachNewData, nFormattedLen );
 
     CPLFree( pachNewData );
 
diff --git a/frmts/iso8211/ddfsubfielddefn.cpp b/frmts/iso8211/ddfsubfielddefn.cpp
index 40cc1c3..fb978d1 100644
--- a/frmts/iso8211/ddfsubfielddefn.cpp
+++ b/frmts/iso8211/ddfsubfielddefn.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ddfsubfielddefn.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Implements the DDFSubfieldDefn class.
@@ -28,32 +27,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "iso8211.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ddfsubfielddefn.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: ddfsubfielddefn.cpp 36552 2016-11-29 06:01:45Z goatbar $");
 
 /************************************************************************/
 /*                          DDFSubfieldDefn()                           */
 /************************************************************************/
 
-DDFSubfieldDefn::DDFSubfieldDefn()
-
-{
-    pszName = NULL;
-
-    bIsVariable = TRUE;
-    nFormatWidth = 0;
-    chFormatDelimiter = DDF_UNIT_TERMINATOR;
-    eBinaryFormat = NotBinary;
-    eType = DDFString;
-
-    pszFormatString = CPLStrdup("");
-
-    nMaxBufChars = 0;
-    pachBuffer = NULL;
-}
+DDFSubfieldDefn::DDFSubfieldDefn() :
+    pszName(NULL),
+    pszFormatString(CPLStrdup("")),
+    eType(DDFString),
+    eBinaryFormat(NotBinary),
+    bIsVariable(TRUE),
+    chFormatDelimiter(DDF_UNIT_TERMINATOR),
+    nFormatWidth(0),
+    nMaxBufChars(0),
+    pachBuffer(NULL)
+{}
 
 /************************************************************************/
 /*                          ~DDFSubfieldDefn()                          */
@@ -501,45 +504,45 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
           {
             case UInt:
               if( nFormatWidth == 1 )
-                  return( abyData[0] );
+                  return abyData[0];
               else if( nFormatWidth == 2 )
-                  return( *((GUInt16 *) pabyData) );
+                  return *((GUInt16 *) pabyData);
               else if( nFormatWidth == 4 )
-                  return( *((GUInt32 *) pabyData) );
+                  return *((GUInt32 *) pabyData);
               else
               {
-                  //CPLAssert( FALSE );
+                  // CPLAssert( false );
                   return 0.0;
               }
 
             case SInt:
               if( nFormatWidth == 1 )
-                  return( *((signed char *) abyData) );
+                  return *((signed char *) abyData);
               else if( nFormatWidth == 2 )
-                  return( *((GInt16 *) pabyData) );
+                  return *((GInt16 *) pabyData);
               else if( nFormatWidth == 4 )
-                  return( *((GInt32 *) pabyData) );
+                  return *((GInt32 *) pabyData);
               else
               {
-                  //CPLAssert( FALSE );
+                  // CPLAssert( false );
                   return 0.0;
               }
 
             case FloatReal:
               if( nFormatWidth == 4 )
-                  return( *((float *) pabyData) );
+                  return *((float *) pabyData);
               else if( nFormatWidth == 8 )
-                  return( *((double *) pabyData) );
+                  return *((double *) pabyData);
               else
               {
-                  //CPLAssert( FALSE );
+                  // CPLAssert( false );
                   return 0.0;
               }
 
             case NotBinary:
             case FPReal:
             case FloatComplex:
-              //CPLAssert( FALSE );
+              // CPLAssert( false );
               return 0.0;
           }
           break;
@@ -547,11 +550,11 @@ DDFSubfieldDefn::ExtractFloatData( const char * pachSourceData,
       }
 
       default:
-        //CPLAssert( FALSE );
+        // CPLAssert( false );
         return 0.0;
     }
 
-    //CPLAssert( FALSE );
+    // CPLAssert( false );
     return 0.0;
 }
 
@@ -605,10 +608,11 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
 
           if( nFormatWidth > nMaxBytes || nFormatWidth >= (int)sizeof(abyData) )
           {
-              CPLError( CE_Warning, CPLE_AppDefined,
-                        "Attempt to extract int subfield %s with format %s\n"
-                        "failed as only %d bytes available.  Using zero.",
-                        pszName, pszFormatString, MIN(nMaxBytes, (int)sizeof(abyData)) );
+              CPLError(CE_Warning, CPLE_AppDefined,
+                       "Attempt to extract int subfield %s with format %s\n"
+                       "failed as only %d bytes available.  Using zero.",
+                       pszName, pszFormatString,
+                       std::min(nMaxBytes, static_cast<int>(sizeof(abyData))));
               return 0;
           }
 
@@ -637,45 +641,45 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
           {
             case UInt:
               if( nFormatWidth == 4 )
-                  return( (int) *((GUInt32 *) pabyData) );
+                  return (int) *((GUInt32 *) pabyData);
               else if( nFormatWidth == 1 )
-                  return( abyData[0] );
+                  return abyData[0];
               else if( nFormatWidth == 2 )
-                  return( *((GUInt16 *) pabyData) );
+                  return *((GUInt16 *) pabyData);
               else
               {
-                  //CPLAssert( FALSE );
+                  // CPLAssert( false );
                   return 0;
               }
 
             case SInt:
               if( nFormatWidth == 4 )
-                  return( *((GInt32 *) pabyData) );
+                  return *((GInt32 *) pabyData);
               else if( nFormatWidth == 1 )
-                  return( *((signed char *) abyData) );
+                  return *((signed char *) abyData);
               else if( nFormatWidth == 2 )
-                  return( *((GInt16 *) pabyData) );
+                  return *((GInt16 *) pabyData);
               else
               {
-                  //CPLAssert( FALSE );
+                  // CPLAssert( false );
                   return 0;
               }
 
             case FloatReal:
               if( nFormatWidth == 4 )
-                  return( (int) *((float *) pabyData) );
+                  return (int) *((float *) pabyData);
               else if( nFormatWidth == 8 )
-                  return( (int) *((double *) pabyData) );
+                  return (int) *((double *) pabyData);
               else
               {
-                  //CPLAssert( FALSE );
+                  // CPLAssert( false );
                   return 0;
               }
 
             case NotBinary:
             case FPReal:
             case FloatComplex:
-              //CPLAssert( FALSE );
+              // CPLAssert( false );
               return 0;
           }
           break;
@@ -683,11 +687,11 @@ DDFSubfieldDefn::ExtractIntData( const char * pachSourceData,
       }
 
       default:
-        //CPLAssert( FALSE );
+        // CPLAssert( false );
         return 0;
     }
 
-    //CPLAssert( FALSE );
+    // CPLAssert( false );
     return 0;
 }
 
@@ -725,11 +729,12 @@ void DDFSubfieldDefn::DumpData( const char * pachData, int nMaxBytes,
                  ExtractIntData( pachData, nMaxBytes, NULL ) );
     else if( eType == DDFBinaryString )
     {
-        int     nBytes, i;
-        GByte   *pabyBString = (GByte *) ExtractStringData( pachData, nMaxBytes, &nBytes );
+        int nBytes = 0;
+        GByte *pabyBString =
+            (GByte *) ExtractStringData( pachData, nMaxBytes, &nBytes );
 
         fprintf( fp, "      Subfield `%s' = 0x", pszName );
-        for( i = 0; i < MIN(nBytes,24); i++ )
+        for( int i = 0; i < std::min(nBytes, 24); i++ )
             fprintf( fp, "%02X", pabyBString[i] );
 
         if( nBytes > 24 )
@@ -858,12 +863,14 @@ int DDFSubfieldDefn::FormatStringValue( char *pachData, int nBytesAvailable,
         if( GetBinaryFormat() == NotBinary )
         {
             memset( pachData, ' ', nSize );
-            memcpy( pachData, pszValue, MIN(nValueLength,nSize) );
+            // cppcheck-suppress redundantCopy
+            memcpy( pachData, pszValue, std::min(nValueLength, nSize) );
         }
         else
         {
             memset( pachData, 0, nSize );
-            memcpy( pachData, pszValue, MIN(nValueLength,nSize) );
+            // cppcheck-suppress redundantCopy
+            memcpy( pachData, pszValue, std::min(nValueLength, nSize) );
         }
     }
 
@@ -950,11 +957,11 @@ int DDFSubfieldDefn::FormatIntValue( char *pachData, int nBytesAvailable,
             break;
 
           case FloatReal:
-            CPLAssert( FALSE );
+            CPLAssert( false );
             break;
 
           default:
-            CPLAssert( FALSE );
+            CPLAssert( false );
             break;
         }
     }
@@ -1020,7 +1027,7 @@ int DDFSubfieldDefn::FormatFloatValue( char *pachData, int nBytesAvailable,
         }
         else
         {
-            CPLAssert( FALSE );
+            CPLAssert( false );
             /* implement me */
         }
     }
diff --git a/frmts/iso8211/ddfutils.cpp b/frmts/iso8211/ddfutils.cpp
index bd9265e..27fc4ea 100644
--- a/frmts/iso8211/ddfutils.cpp
+++ b/frmts/iso8211/ddfutils.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ddfutils.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Various utility functions.
@@ -27,10 +26,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "iso8211.h"
+
+#include <cstdlib>
+#include <cstring>
+
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ddfutils.cpp 32179 2015-12-14 16:22:34Z goatbar $");
+CPL_CVSID("$Id: ddfutils.cpp 36552 2016-11-29 06:01:45Z goatbar $");
 
 /************************************************************************/
 /*                             DDFScanInt()                             */
@@ -42,7 +46,7 @@ CPL_CVSID("$Id: ddfutils.cpp 32179 2015-12-14 16:22:34Z goatbar $");
 int DDFScanInt( const char * pszString, int nMaxChars )
 
 {
-    char        szWorking[33];
+    char szWorking[33] = {};
 
     if( nMaxChars > 32 || nMaxChars == 0 )
         nMaxChars = 32;
@@ -50,7 +54,7 @@ int DDFScanInt( const char * pszString, int nMaxChars )
     memcpy( szWorking, pszString, nMaxChars );
     szWorking[nMaxChars] = '\0';
 
-    return( atoi(szWorking) );
+    return atoi(szWorking);
 }
 
 /************************************************************************/
@@ -63,9 +67,9 @@ int DDFScanInt( const char * pszString, int nMaxChars )
 int DDFScanVariable( const char *pszRecord, int nMaxChars, int nDelimChar )
 
 {
-    int         i;
+    int i = 0;  // Used after for.
 
-    for( i = 0; i < nMaxChars-1 && pszRecord[i] != nDelimChar; i++ ) {}
+    for( ; i < nMaxChars - 1 && pszRecord[i] != nDelimChar; i++ ) {}
 
     return i;
 }
@@ -82,18 +86,19 @@ char * DDFFetchVariable( const char *pszRecord, int nMaxChars,
                          int *pnConsumedChars )
 
 {
-    int         i;
-    char        *pszReturn;
-
-    for( i = 0; i < nMaxChars-1 && pszRecord[i] != nDelimChar1
-                                && pszRecord[i] != nDelimChar2; i++ ) {}
+    int i = 0;  // Used after for.
+    for( ;
+         i < nMaxChars-1 && pszRecord[i] != nDelimChar1
+         && pszRecord[i] != nDelimChar2;
+         i++ )
+    {}
 
     *pnConsumedChars = i;
     if( i < nMaxChars
         && (pszRecord[i] == nDelimChar1 || pszRecord[i] == nDelimChar2) )
         (*pnConsumedChars)++;
 
-    pszReturn = (char *) CPLMalloc(i+1);
+    char *pszReturn = static_cast<char *>(CPLMalloc(i + 1));
     pszReturn[i] = '\0';
     strncpy( pszReturn, pszRecord, i );
 
diff --git a/frmts/iso8211/intro.dox b/frmts/iso8211/intro.dox
index 0c2cc72..4c18f61 100644
--- a/frmts/iso8211/intro.dox
+++ b/frmts/iso8211/intro.dox
@@ -13,33 +13,33 @@ FAQ</a> has some good background on ISO 8211 formatted files.  I will briefly
 introduce it here, with reference to the library classes representing
 the components.<p>
 
-An 8211 file (DDFModule) 
+An 8211 file (DDFModule)
 consists of a series of logical records.  The first record
 is special, and is called the DDR (Data Description Record).  It basically
-contains definitions of all the data objects (fields or DDFFieldDefn objects) 
+contains definitions of all the data objects (fields or DDFFieldDefn objects)
 that can occur on the following data records.<p>
 
 The remainder of the records are known as DRs (data records - DDFRecord).  They
-each contain one or more field (DDFField) instances.  What fields appear 
-on what records is not defined by ISO 8211, though more specific requirements 
+each contain one or more field (DDFField) instances.  What fields appear
+on what records is not defined by ISO 8211, though more specific requirements
 may be implied by a particular data standard such as SDTS or S-57.<p>
 
-Each field instance has a name, and consists of a series of subfields.  A 
-given 
+Each field instance has a name, and consists of a series of subfields.  A
+given
 field always has the same subfields in each field instance, and these subfields
-are defined in the DDR (DDFSubfieldDefn), in association with their 
+are defined in the DDR (DDFSubfieldDefn), in association with their
 field definition (DDFFieldDefn).  A field may appear 0, 1, or many times in a DR. <p>
 
-Each subfield has a name, format (from the DDFSubfieldDefn) and 
-actual subfield data for a particular DR.  
+Each subfield has a name, format (from the DDFSubfieldDefn) and
+actual subfield data for a particular DR.
 Some fields contain an <i>array</i> of their group of
-subfields.  For instance a <i>coordinate field</i> may have X and Y 
-subfields, and they may repeat many times within one coordinate field 
+subfields.  For instance a <i>coordinate field</i> may have X and Y
+subfields, and they may repeat many times within one coordinate field
 indicating a series of points.<p>
 
-<i>This would be a real good place for a UML diagram of ISO 8211, and 
+<i>This would be a real good place for a UML diagram of ISO 8211, and
 the corresponding library classes!</i><p>
- 
+
 <h2>Development Information</h2>
 
 The <b>iso8211.h</b> contains the definitions for all public ISO8211Lib
@@ -50,13 +50,13 @@ and then use the DDFModule::Open() method.  This will read the DDR, and
 establish all the DDFFieldDefn, and DDFSubfieldDefn objects which can be
 queried off the DDFModule.<p>
 
-The use DDFModule::ReadRecord() to fetch data records (DDFRecord).  When 
-a record is read, a list of field objects (DDFField) on that record are 
+The use DDFModule::ReadRecord() to fetch data records (DDFRecord).  When
+a record is read, a list of field objects (DDFField) on that record are
 created.  They can be queried with various DDFRecord methods.<P>
 
-Data pointers for individual subfields of a DDFField can be fetched with 
+Data pointers for individual subfields of a DDFField can be fetched with
 DDFField::GetSubfieldData().  The interpreted value can then be extracted
-with the appropriate one of DDFSubfieldDefn::ExtractIntValue(), 
+with the appropriate one of DDFSubfieldDefn::ExtractIntValue(),
 DDFSubfieldDefn::ExtractStringValue(), or DDFSubfieldDefn::ExtractFloatValue().
 Note that there is no object instantiated for individual subfields of a
 DDFField.  Instead the application extracts a pointer to the subfields
@@ -77,17 +77,17 @@ cleanup all records, definitions and related objects.<p>
 <li> DDFField class.
 </ul>
 
-A complete <a href="example.html">Example Reader</a> should clarify 
+A complete <a href="example.html">Example Reader</a> should clarify
 simple use of ISO8211Lib.<p>
 
 <h2>Related Information</h2>
 
 <ul>
 
-<li> The ISO 8211 standard can be ordered through 
+<li> The ISO 8211 standard can be ordered through
 <a href="http://www.iso.ch/">ISO</a>.  It cost me about $200CDN.<p>
 
-<li> The <a href="http://user.icx.net/~brooks/iso8211.html">ISO/IEC 8211/DDFS 
+<li> The <a href="http://user.icx.net/~brooks/iso8211.html">ISO/IEC 8211/DDFS
 Home Page</a> contains tutorials and some code by Dr. Alfred A.
 Brooks, one of the originators of the 8211 standard.<p>
 
@@ -96,13 +96,13 @@ ISO/IEC 8211 Home Page</a> has some python code for parsing 8211 files, and
 some other useful background.<p>
 
 <li> The <a href="http://mcmcweb.er.usgs.gov/sdts/sdtsxx/index.html">SDTS++</a>
-library from the USGS 
-includes support for ISO 8211.  It doesn't include some of the 
-1994 additions to ISO 8211, but it is sufficient for SDTS, and quite 
+library from the USGS
+includes support for ISO 8211.  It doesn't include some of the
+1994 additions to ISO 8211, but it is sufficient for SDTS, and quite
 elegantly done.  Also supports writing ISO 8211 files.<p>
 
-<li> The USGS also has an older 
-<a href="ftp://sdts.er.usgs.gov/pub/sdts/software/fips123/">FIPS123</a> 
+<li> The USGS also has an older
+<a href="ftp://sdts.er.usgs.gov/pub/sdts/software/fips123/">FIPS123</a>
 library which supports the older profile of ISO 8211 (to some extent).<p>
 
 </ul>
@@ -143,7 +143,7 @@ The precise license text is:<p>
 <ol>
 
 <li> First, fetch the source.  The most recent source should be accessible at
-an url such as 
+an url such as
 <a href="http://home.gdal.org/projects/iso8211/iso8211lib-1.4.zip">
 http://home.gdal.org/projects/iso8211/iso8211lib-1.4.zip</a>.<p>
 
@@ -152,7 +152,7 @@ http://home.gdal.org/projects/iso8211/iso8211lib-1.4.zip</a>.<p>
 % unzip iso8211lib-1.4.zip
 </code>
 
-<li> On unix you can now type ``configure'' to establish configuration 
+<li> On unix you can now type ``configure'' to establish configuration
 options.<p>
 
 <li> On unix you can now type make to build libiso8211.a, and the sample
@@ -163,15 +163,15 @@ mainline 8211view.<p>
 Windows developers will have to create their own makefile/project but
 can base it on the very simple Makefile.in provided.  As well, you would
 need to copy cpl_config.h.in to cpl_config.h, and modify as needed.  The
-default will likely work OK, but may result in some compiler warnings.  
-Let me know if you are having difficulties, and I will prepare a VC++ 
+default will likely work OK, but may result in some compiler warnings.
+Let me know if you are having difficulties, and I will prepare a VC++
 makefile.<p>
 
 <h2>Author and Acknowledgements</h2>
 
 The primary author of ISO8211Lib is <a href="http://pobox.com/~warmerdam">
-Frank Warmerdam</a>, and I can be reached at 
-<a href="mailto:warmerdam at pobox.com">warmerdam at pobox.com</a>.  I am eager to 
+Frank Warmerdam</a>, and I can be reached at
+<a href="mailto:warmerdam at pobox.com">warmerdam at pobox.com</a>.  I am eager to
 receive bug reports, and also open to praise or suggestions.<p>
 
 I would like to thank:<p>
@@ -181,7 +181,7 @@ I would like to thank:<p>
 who funded development of this library, and agreed for it to be Open Source.<p>
 
 <li> Mark Colletti, a primary author of SDTS++ from
-which I derived most of what I know about ISO 8211 and who was very 
+which I derived most of what I know about ISO 8211 and who was very
 supportive, answering a variety of questions.<p>
 
 <li> Tony J Ibbs, author of the ISO/IEC 8211 home page who answered
@@ -193,9 +193,9 @@ length fields (from S-57).<p>
 
 </ul>
 
-I would also like to dedicate this library to the memory of Sol Katz.  
+I would also like to dedicate this library to the memory of Sol Katz.
 Sol released a variety of SDTS (and hence ISO8211) translators, at substantial
-personal effort, to the GIS community along with the many other generous 
+personal effort, to the GIS community along with the many other generous
 contributions he made to the community.  His example has been an inspiration
 to me, and I hope similar efforts on my part will contribute to his memory.<p>
 
diff --git a/frmts/iso8211/iso8211.h b/frmts/iso8211/iso8211.h
index 92d933f..54203c9 100644
--- a/frmts/iso8211/iso8211.h
+++ b/frmts/iso8211/iso8211.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: iso8211.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: iso8211.h 36411 2016-11-21 22:03:48Z rouault $
  *
  * Project:  ISO 8211 Access
  * Purpose:  Main declarations for ISO 8211.
@@ -98,7 +98,7 @@ class CPL_ODLL DDFModule
 
     void        Dump( FILE * fp );
 
-    DDFRecord   *ReadRecord( void );
+    DDFRecord   *ReadRecord();
     void        Rewind( long nOffset = -1 );
 
     DDFFieldDefn *FindFieldDefn( const char * );
@@ -129,7 +129,6 @@ class CPL_ODLL DDFModule
     const char* GetExtendedCharSet() const { return _extendedCharSet; }
     void        SetFieldControlLength(int nVal) { _fieldControlLength = nVal; }
 
-
   private:
     VSILFILE    *fpDDF;
     int         bReadOnly;
@@ -352,11 +351,9 @@ typedef enum {
     FloatComplex=5
 } DDFBinaryFormat;
 
-    DDFBinaryFormat GetBinaryFormat(void) const { return eBinaryFormat; }
-
+    DDFBinaryFormat GetBinaryFormat() const { return eBinaryFormat; }
 
 private:
-
   char      *pszName;   // a.k.a. subfield mnemonic
   char      *pszFormatString;
 
@@ -396,7 +393,7 @@ private:
 class CPL_ODLL DDFRecord
 {
   public:
-                DDFRecord( DDFModule * );
+    explicit     DDFRecord( DDFModule * );
                 ~DDFRecord();
 
     DDFRecord  *Clone();
@@ -504,7 +501,7 @@ class CPL_ODLL DDFRecord
 
 /**
  * This object represents one field in a DDFRecord.  This
- * models an instance of the fields data, rather than it's data definition
+ * models an instance of the fields data, rather than its data definition,
  * which is handled by the DDFFieldDefn class.  Note that a DDFField
  * doesn't have DDFSubfield children as you would expect.  To extract
  * subfield values use GetSubfieldData() to find the right data pointer and
@@ -514,6 +511,8 @@ class CPL_ODLL DDFRecord
 class CPL_ODLL DDFField
 {
   public:
+    DDFField() : poDefn(NULL), nDataSize(0), pachData(NULL) {}
+
     void                Initialize( DDFFieldDefn *, const char *pszData,
                                     int nSize );
 
@@ -546,5 +545,4 @@ class CPL_ODLL DDFField
     const char          *pachData;
 };
 
-
 #endif /* ndef ISO8211_H_INCLUDED */
diff --git a/frmts/iso8211/makefile.vc b/frmts/iso8211/makefile.vc
index 0c7e26c..c57d348 100644
--- a/frmts/iso8211/makefile.vc
+++ b/frmts/iso8211/makefile.vc
@@ -6,6 +6,12 @@ GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
+!IFDEF ZLIB_EXTERNAL_LIB
+LINK_ZLIB = $(ZLIB_LIB)
+!ELSE
+LINK_ZLIB = ..\zlib\*.obj
+!ENDIF
+
 default:	$(OBJ)
 	lib /out:libiso8211.lib $(OBJ)
 	xcopy /D  /Y *.obj ..\o
@@ -21,22 +27,22 @@ clean:
 all:	default 8211view.exe 8211dump.exe 8211createfromxml.exe
 
 iso8211.dll: $(OBJ) $(CPLLIB) 
-	link /dll $(LDEBUG) $(OBJ) $(CPLLIB)  ../zlib/*.obj \
+	link /dll $(LDEBUG) $(OBJ) $(CPLLIB)  $(LINK_ZLIB) \
 		/out:iso8211.dll /implib:iso8211_i.lib
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1 
 
 8211view.exe:	8211view.obj $(OBJ) $(CPLLIB) 
-	$(CC) $(CFLAGS) 8211view.obj $(OBJ) $(CPLLIB) $(LIBICONV_LIBRARY) $(CURL_LIB) ../zlib/*.obj /link $(LINKER_FLAGS)
+	$(CC) $(CFLAGS) 8211view.obj $(OBJ) $(CPLLIB) $(LIBICONV_LIBRARY) $(CURL_LIB) $(LINK_ZLIB) /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1 
 	del 8211view.obj
 
 8211dump.exe:	8211dump.obj $(OBJ) $(CPLLIB) 
-	$(CC) $(CFLAGS) 8211dump.obj $(OBJ) $(CPLLIB) $(LIBICONV_LIBRARY) $(CURL_LIB) ../zlib/*.obj  /link $(LINKER_FLAGS)
+	$(CC) $(CFLAGS) 8211dump.obj $(OBJ) $(CPLLIB) $(LIBICONV_LIBRARY) $(CURL_LIB) $(LINK_ZLIB)  /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1 
 	del 8211dump.obj
 
 8211createfromxml.exe:	8211createfromxml.obj $(OBJ) $(CPLLIB) 
-	$(CC) $(CFLAGS) 8211createfromxml.obj $(OBJ) $(CPLLIB) $(LIBICONV_LIBRARY) $(CURL_LIB) ../zlib/*.obj  /link $(LINKER_FLAGS)
+	$(CC) $(CFLAGS) 8211createfromxml.obj $(OBJ) $(CPLLIB) $(LIBICONV_LIBRARY) $(CURL_LIB) $(LINK_ZLIB)  /link $(LINKER_FLAGS)
 	if exist $@.manifest mt -manifest $@.manifest -outputresource:$@;1 
 	del 8211createfromxml.obj
 
diff --git a/frmts/iso8211/mkcatalog.cpp b/frmts/iso8211/mkcatalog.cpp
index 33bae38..a7b39e2 100644
--- a/frmts/iso8211/mkcatalog.cpp
+++ b/frmts/iso8211/mkcatalog.cpp
@@ -1,5 +1,4 @@
 /* ****************************************************************************
- * $Id: mkcatalog.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  ISO8211 Library
  * Purpose:  Test ISO8211 writing capability.
@@ -29,25 +28,23 @@
 
 #include "iso8211.h"
 
-CPL_CVSID("$Id: mkcatalog.cpp 33717 2016-03-14 06:29:14Z goatbar $");
-
+CPL_CVSID("$Id: mkcatalog.cpp 36455 2016-11-22 23:11:35Z rouault $");
 
 /************************************************************************/
 /*                               mk_s57()                               */
 /************************************************************************/
 
-void mk_s57()
+static void mk_s57()
 
 {
     DDFModule  oModule;
-    DDFFieldDefn *poFDefn;
 
     oModule.Initialize();
 
 /* -------------------------------------------------------------------- */
 /*      Create the '0000' definition.                                   */
 /* -------------------------------------------------------------------- */
-    poFDefn = new DDFFieldDefn();
+    DDFFieldDefn *poFDefn = new DDFFieldDefn();
 
     poFDefn->Create( "0000", "", "0001DSIDDSIDDSSI0001DSPM0001VRIDVRIDATTVVRIDVRPCVRIDVRPTVRIDSGCCVRIDSG2DVRIDSG3D0001FRIDFRIDFOIDFRIDATTFFRIDNATFFRIDFFPCFRIDFFPTFRIDFSPCFRIDFSPT", dsc_elementary, dtc_char_string );
 
@@ -211,12 +208,10 @@ void mk_s57()
 /*      Create a record.                                                */
 /* -------------------------------------------------------------------- */
     DDFRecord *poRec = new DDFRecord( &oModule );
-    DDFField *poField;
-
-    poField = poRec->AddField( oModule.FindFieldDefn( "0001" ) );
+    DDFField *poField = poRec->AddField( oModule.FindFieldDefn( "0001" ) );
     poRec->SetFieldRaw( poField, 0, "\1\0\036", 3 );
 
-    poField = poRec->AddField( oModule.FindFieldDefn( "DSID" ) );
+    /*poField = */ poRec->AddField( oModule.FindFieldDefn( "DSID" ) );
 
     poRec->SetIntSubfield   ( "DSID", 0, "RCNM", 0, 10 );
     poRec->SetIntSubfield   ( "DSID", 0, "RCID", 0, 1 );
@@ -235,7 +230,7 @@ void mk_s57()
     poRec->SetIntSubfield   ( "DSID", 0, "AGEN", 0, 540 );
     poRec->SetStringSubfield( "DSID", 0, "COMT", 0, "" );
 
-    poField = poRec->AddField( oModule.FindFieldDefn( "DSSI" ) );
+    /*poField = */ poRec->AddField( oModule.FindFieldDefn( "DSSI" ) );
 
     poRec->SetIntSubfield   ( "DSSI", 0, "DSTR", 0, 2 );
     poRec->SetIntSubfield   ( "DSSI", 0, "AALL", 0, 1 );
@@ -260,7 +255,7 @@ void mk_s57()
     poField = poRec->AddField( oModule.FindFieldDefn( "0001" ) );
     poRec->SetFieldRaw( poField, 0, "\2\0\036", 3 );
 
-    poField = poRec->AddField( oModule.FindFieldDefn( "DSPM" ) );
+    /*poField = */ poRec->AddField( oModule.FindFieldDefn( "DSPM" ) );
 
     poRec->SetIntSubfield   ( "DSPM", 0, "RCNM", 0, 20 );
     poRec->SetIntSubfield   ( "DSPM", 0, "RCID", 0, 1 );
@@ -286,14 +281,14 @@ void mk_s57()
     poField = poRec->AddField( oModule.FindFieldDefn( "0001" ) );
     poRec->SetFieldRaw( poField, 0, "\3\0\036", 3 );
 
-    poField = poRec->AddField( oModule.FindFieldDefn( "VRID" ) );
+    /*poField = */ poRec->AddField( oModule.FindFieldDefn( "VRID" ) );
 
     poRec->SetIntSubfield   ( "VRID", 0, "RCNM", 0, 110 );
     poRec->SetIntSubfield   ( "VRID", 0, "RCID", 0, 518 );
     poRec->SetIntSubfield   ( "VRID", 0, "RVER", 0, 1 );
     poRec->SetIntSubfield   ( "VRID", 0, "RUIN", 0, 1 );
 
-    poField = poRec->AddField( oModule.FindFieldDefn( "SG3D" ) );
+    /*poField = */ poRec->AddField( oModule.FindFieldDefn( "SG3D" ) );
 
     poRec->SetIntSubfield   ( "SG3D", 0, "YCOO", 0, -325998702 );
     poRec->SetIntSubfield   ( "SG3D", 0, "XCOO", 0, 612175350 );
@@ -312,18 +307,18 @@ void mk_s57()
 /*                             mk_catalog()                             */
 /************************************************************************/
 
+#if 0
 void mk_catalog()
 
 {
     DDFModule  oModule;
-    DDFFieldDefn *poFDefn;
 
     oModule.Initialize();
 
 /* -------------------------------------------------------------------- */
 /*      Create the '0000' definition.                                   */
 /* -------------------------------------------------------------------- */
-    poFDefn = new DDFFieldDefn();
+    DDFFieldDefn *poFDefn = new DDFFieldDefn();
 
     poFDefn->Create( "0000", "", "0001CATD",
                      dsc_elementary,
@@ -373,9 +368,7 @@ void mk_catalog()
 /*      Create a record.                                                */
 /* -------------------------------------------------------------------- */
     DDFRecord *poRec = new DDFRecord( &oModule );
-    DDFField *poField;
-
-    poField = poRec->AddField( oModule.FindFieldDefn( "0001" ) );
+    DDFField *poField = poRec->AddField( oModule.FindFieldDefn( "0001" ) );
     poRec->SetFieldRaw( poField, 0, "\0\0\036", 3 );
 
     poField = poRec->AddField( oModule.FindFieldDefn( "CATD" ) );
@@ -411,12 +404,13 @@ void mk_catalog()
     poRec->Write();
     delete poRec;
 }
+#endif // mk_catalog not used.
 
 /* **********************************************************************/
 /*                                main()                                */
 /* **********************************************************************/
 
-int main( int nArgc, char ** papszArgv )
+int main( int /* nArgc */, char ** /* papszArgv */ )
 
 {
     mk_s57();
diff --git a/frmts/iso8211/timetest.cpp b/frmts/iso8211/timetest.cpp
index 11c321b..6610eb2 100644
--- a/frmts/iso8211/timetest.cpp
+++ b/frmts/iso8211/timetest.cpp
@@ -1,5 +1,4 @@
 /* ****************************************************************************
- * $Id: timetest.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Example program dumping data in 8211 data to stdout.
@@ -30,6 +29,8 @@
 #include <stdio.h>
 #include "iso8211.h"
 
+CPL_CVSID("$Id: timetest.cpp 34950 2016-08-07 17:17:12Z goatbar $");
+
 static void ViewRecordField( DDFField * poField );
 static int ViewSubfield( DDFSubfieldDefn *poSFDefn,
                          const char * pachFieldData,
@@ -42,19 +43,16 @@ static int ViewSubfield( DDFSubfieldDefn *poSFDefn,
 int main( int nArgc, char ** papszArgv )
 
 {
-    DDFModule   oModule;
-    const char  *pszFilename;
-    int         i;
-
-    if( nArgc > 1 )
-        pszFilename = papszArgv[1];
-    else
+    if( nArgc < 2 )
     {
         printf( "Usage: 8211view filename\n" );
         exit( 1 );
     }
 
-    for( i = 0; i < 40; i++ )
+    const char  *pszFilename = papszArgv[1];
+    DDFModule oModule;
+
+    for( int i = 0; i < 40; i++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Open the file.  Note that by default errors are reported to     */
@@ -68,9 +66,9 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      Loop reading records till there are none left.                  */
 /* -------------------------------------------------------------------- */
-        DDFRecord       *poRecord;
-        int             nRecordCount = 0;
-        int             nFieldCount = 0;
+        DDFRecord *poRecord = NULL;
+        int nRecordCount = 0;
+        int nFieldCount = 0;
 
         while( (poRecord = oModule.ReadRecord()) != NULL )
         {
@@ -79,7 +77,7 @@ int main( int nArgc, char ** papszArgv )
             /* ------------------------------------------------------------ */
             for( int iField = 0; iField < poRecord->GetFieldCount(); iField++ )
             {
-                DDFField        *poField = poRecord->GetField( iField );
+                DDFField *poField = poRecord->GetField( iField );
 
                 ViewRecordField( poField );
 
@@ -104,41 +102,34 @@ int main( int nArgc, char ** papszArgv )
 static void ViewRecordField( DDFField * poField )
 
 {
-    int         nBytesRemaining;
-    const char  *pachFieldData;
     DDFFieldDefn *poFieldDefn = poField->GetFieldDefn();
 
     // Get pointer to this fields raw data.  We will move through
     // it consuming data as we report subfield values.
 
-    pachFieldData = poField->GetData();
-    nBytesRemaining = poField->GetDataSize();
+    const char  *pachFieldData = poField->GetData();
+    int nBytesRemaining = poField->GetDataSize();
 
     /* -------------------------------------------------------- */
     /*      Loop over the repeat count for this fields          */
     /*      subfields.  The repeat count will almost            */
     /*      always be one.                                      */
     /* -------------------------------------------------------- */
-    int         iRepeat, nRepeatCount;
 
-    nRepeatCount = poField->GetRepeatCount();
+    int nRepeatCount = poField->GetRepeatCount();
 
-    for( iRepeat = 0; iRepeat < nRepeatCount; iRepeat++ )
+    for( int iRepeat = 0; iRepeat < nRepeatCount; iRepeat++ )
     {
 
         /* -------------------------------------------------------- */
         /*   Loop over all the subfields of this field, advancing   */
         /*   the data pointer as we consume data.                   */
         /* -------------------------------------------------------- */
-        int     iSF;
-
-        for( iSF = 0; iSF < poFieldDefn->GetSubfieldCount(); iSF++ )
+        for( int iSF = 0; iSF < poFieldDefn->GetSubfieldCount(); iSF++ )
         {
             DDFSubfieldDefn *poSFDefn = poFieldDefn->GetSubfield( iSF );
-            int         nBytesConsumed;
-
-            nBytesConsumed = ViewSubfield( poSFDefn, pachFieldData,
-                                           nBytesRemaining );
+            int nBytesConsumed =
+                ViewSubfield( poSFDefn, pachFieldData, nBytesRemaining );
 
             nBytesRemaining -= nBytesConsumed;
             pachFieldData += nBytesConsumed;
diff --git a/frmts/jaxapalsar/jaxapalsardataset.cpp b/frmts/jaxapalsar/jaxapalsardataset.cpp
index 01bb7b3..b0afe01 100644
--- a/frmts/jaxapalsar/jaxapalsardataset.cpp
+++ b/frmts/jaxapalsar/jaxapalsardataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: jaxapalsardataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  PALSAR JAXA imagery reader
  * Purpose:  Support for PALSAR L1.1/1.5 imagery and appropriate metadata from
@@ -33,7 +32,7 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: jaxapalsardataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: jaxapalsardataset.cpp 36574 2016-11-30 14:46:26Z goatbar $");
 
 #if defined(WIN32)
 #define SEP_STRING "\\"
@@ -44,47 +43,47 @@ CPL_CVSID("$Id: jaxapalsardataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 /* read binary fields */
 #ifdef CPL_LSB
 #define READ_WORD(f, x) \
-	do { \
-		VSIFReadL( &(x), 4, 1, (f) ); \
-		(x) = CPL_SWAP32( (x) ); \
-	} while (0);
+        do { \
+                VSIFReadL( &(x), 4, 1, (f) ); \
+                (x) = CPL_SWAP32( (x) ); \
+        } while ( false );
 #define READ_SHORT(f, x) \
-	do { \
-		VSIFReadL( &(x), 2, 1, (f) ); \
-		(x) = CPL_SWAP16( (x) ); \
-	} while (0);
+        do { \
+                VSIFReadL( &(x), 2, 1, (f) ); \
+                (x) = CPL_SWAP16( (x) ); \
+        } while ( false );
 #else
-#define READ_WORD(f, x) do { VSIFReadL( &(x), 4, 1, (f) ); } while (0);
-#define READ_SHORT(f, x) do { VSIFReadL( &(x), 2, 1, (f) ); } while (0);
+#define READ_WORD(f, x) do { VSIFReadL( &(x), 4, 1, (f) ); } while ( false);
+#define READ_SHORT(f, x) do { VSIFReadL( &(x), 2, 1, (f) ); } while ( false );
 #endif /* def CPL_LSB */
-#define READ_BYTE(f, x) do { VSIFReadL( &(x), 1, 1, (f) ); } while (0);
+#define READ_BYTE(f, x) do { VSIFReadL( &(x), 1, 1, (f) ); } while ( false );
 
 /* read floating point value stored as ASCII */
 #define READ_CHAR_FLOAT(n, l, f) \
-	do {\
-		char psBuf[(l+1)]; \
-		psBuf[(l)] = '\0'; \
-		VSIFReadL( &psBuf, (l), 1, (f) );\
-		(n) = CPLAtof( psBuf );\
-	} while (0);
+        do {\
+                char psBuf[(l+1)]; \
+                psBuf[(l)] = '\0'; \
+                VSIFReadL( &psBuf, (l), 1, (f) );\
+                (n) = CPLAtof( psBuf );\
+        } while( false );
 
 /* read numbers stored as ASCII */
 #define READ_CHAR_VAL(x, n, f) \
-	do { \
-		char psBuf[(n+1)]; \
-		psBuf[(n)] = '\0';\
-		VSIFReadL( &psBuf, (n), 1, (f) ); \
-		(x) = atoi(psBuf); \
-	} while (0);
+        do { \
+                char psBuf[(n+1)]; \
+                psBuf[(n)] = '\0';\
+                VSIFReadL( &psBuf, (n), 1, (f) ); \
+                (x) = atoi(psBuf); \
+        } while( false );
 
 /* read string fields
  * note: string must be size of field to be extracted + 1
  */
 #define READ_STRING(s, n, f) \
-	do { \
-		VSIFReadL( &(s), 1, (n), (f) ); \
-		(s)[(n)] = '\0'; \
-	} while (0);
+        do { \
+                VSIFReadL( &(s), 1, (n), (f) ); \
+                (s)[(n)] = '\0'; \
+        } while( false );
 
 /*************************************************************************/
 /* a few key offsets in the volume directory file */
@@ -135,17 +134,17 @@ CPL_CVSID("$Id: jaxapalsardataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
 
 /* a few useful enums */
 enum eFileType {
-	level_11 = 0,
-	level_15,
-        level_10,
-        level_unknown = 999,
+    level_11 = 0,
+    level_15,
+    level_10,
+    level_unknown = 999,
 };
 
 enum ePolarization {
-	hh = 0,
-	hv,
-	vh,
-	vv
+    hh = 0,
+    hv,
+    vh,
+    vv
 };
 
 /************************************************************************/
@@ -166,8 +165,8 @@ public:
     PALSARJaxaDataset();
     ~PALSARJaxaDataset();
 
-    int GetGCPCount();
-    const GDAL_GCP *GetGCPs();
+    int GetGCPCount() override;
+    const GDAL_GCP *GetGCPs() override;
 
     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
     static int Identify( GDALOpenInfo *poOpenInfo );
@@ -178,7 +177,7 @@ PALSARJaxaDataset::PALSARJaxaDataset() :
     pasGCPList(NULL),
     nGCPCount(0),
     nFileType(level_unknown)
-{ }
+{}
 
 PALSARJaxaDataset::~PALSARJaxaDataset()
 {
@@ -197,8 +196,6 @@ PALSARJaxaDataset::~PALSARJaxaDataset()
 
 class PALSARJaxaRasterBand : public GDALRasterBand {
     VSILFILE *fp;
-    int nRasterXSize;
-    int nRasterYSize;
     ePolarization nPolarization;
     eFileType nFileType;
     int nBitsPerSample;
@@ -209,7 +206,7 @@ public:
     PALSARJaxaRasterBand( PALSARJaxaDataset *poDS, int nBand, VSILFILE *fp );
     ~PALSARJaxaRasterBand();
 
-    CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
+    CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
 };
 
 /************************************************************************/
@@ -218,16 +215,17 @@ public:
 
 PALSARJaxaRasterBand::PALSARJaxaRasterBand( PALSARJaxaDataset *poDSIn,
                                             int nBandIn, VSILFILE *fpIn ) :
-    nPolarization(hh)
+    fp(fpIn),
+    nPolarization(hh),
+    nBitsPerSample(0),
+    nSamplesPerGroup(0),
+    nRecordSize(0)
 {
     poDS = poDSIn;
     nBand = nBandIn;
-    this->fp = fpIn;
 
     /* Read image options record to determine the type of data */
     VSIFSeekL( fp, BITS_PER_SAMPLE_OFFSET, SEEK_SET );
-    nBitsPerSample = 0;
-    nSamplesPerGroup = 0;
     READ_CHAR_VAL( nBitsPerSample, BITS_PER_SAMPLE_LENGTH, fp );
     READ_CHAR_VAL( nSamplesPerGroup, SAMPLES_PER_GROUP_LENGTH, fp );
 
@@ -251,19 +249,19 @@ PALSARJaxaRasterBand::PALSARJaxaRasterBand( PALSARJaxaDataset *poDSIn,
     READ_CHAR_VAL( nRasterYSize, NUMBER_LINES_LENGTH, fp );
     VSIFSeekL( fp, SAR_DATA_RECORD_LENGTH_OFFSET, SEEK_SET );
     READ_CHAR_VAL( nRecordSize, SAR_DATA_RECORD_LENGTH_LENGTH, fp );
-    int nDenom = ((nBitsPerSample / 8) * nSamplesPerGroup);
-    if( nDenom == 0 )
-        nRasterXSize = 0;
-    else
-        nRasterXSize = (nRecordSize -
-                    (nFileType != level_15 ? SIG_DAT_REC_OFFSET : PROC_DAT_REC_OFFSET))
-        / nDenom;
+    const int nDenom = ((nBitsPerSample / 8) * nSamplesPerGroup);
+    if( nDenom != 0 )
+        nRasterXSize =
+            (nRecordSize -
+             (nFileType != level_15 ? SIG_DAT_REC_OFFSET : PROC_DAT_REC_OFFSET))
+            / nDenom;
 
     poDSIn->nRasterXSize = nRasterXSize;
     poDSIn->nRasterYSize = nRasterYSize;
 
     /* Polarization */
-    switch (nBand) {
+    switch( nBand )
+    {
       case 0:
         nPolarization = hh;
         SetMetadataItem( "POLARIMETRIC_INTERP", "HH" );
@@ -333,10 +331,9 @@ CPLErr PALSARJaxaRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     return CE_None;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
-/* 			PALSARJaxaDataset			     	*/
+/*                      PALSARJaxaDataset                               */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -348,7 +345,6 @@ int PALSARJaxaDataset::GetGCPCount() {
     return nGCPCount;
 }
 
-
 /************************************************************************/
 /*                             GetGCPs()                                */
 /************************************************************************/
@@ -357,7 +353,6 @@ const GDAL_GCP *PALSARJaxaDataset::GetGCPs() {
     return pasGCPList;
 }
 
-
 /************************************************************************/
 /*                            ReadMetadata()                            */
 /************************************************************************/
@@ -469,7 +464,6 @@ void PALSARJaxaDataset::ReadMetadata( PALSARJaxaDataset *poDS, VSILFILE *fp ) {
         /* PALSAR data is only available from JAXA in Scattering Matrix form */
         poDS->SetMetadataItem( "MATRIX_REPRESENTATION", "SCATTERING" );
     }
-
 }
 
 /************************************************************************/
@@ -554,43 +548,39 @@ GDALDataset *PALSARJaxaDataset::Open( GDALOpenInfo * poOpenInfo ) {
     int nBandNum = 1;
 
     /* HH */
-    VSILFILE *fpHH;
     snprintf( pszImgFile, nImgFileLen, "%s%sIMG-HH%s",
              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix );
-    fpHH = VSIFOpenL( pszImgFile, "rb" );
+    VSILFILE *fpHH = VSIFOpenL( pszImgFile, "rb" );
     if (fpHH != NULL) {
         poDS->SetBand( nBandNum, new PALSARJaxaRasterBand( poDS, 0, fpHH ) );
         nBandNum++;
     }
 
     /* HV */
-    VSILFILE *fpHV;
     snprintf( pszImgFile, nImgFileLen, "%s%sIMG-HV%s",
              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix );
-    fpHV = VSIFOpenL( pszImgFile, "rb" );
+    VSILFILE *fpHV = VSIFOpenL( pszImgFile, "rb" );
     if (fpHV != NULL) {
         poDS->SetBand( nBandNum, new PALSARJaxaRasterBand( poDS, 1, fpHV ) );
         nBandNum++;
     }
 
     /* VH */
-    VSILFILE *fpVH;
     snprintf( pszImgFile, nImgFileLen, "%s%sIMG-VH%s",
              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix );
-    fpVH = VSIFOpenL( pszImgFile, "rb" );
+    VSILFILE *fpVH = VSIFOpenL( pszImgFile, "rb" );
     if (fpVH != NULL) {
         poDS->SetBand( nBandNum, new PALSARJaxaRasterBand( poDS, 2, fpVH ) );
         nBandNum++;
     }
 
     /* VV */
-    VSILFILE *fpVV;
     snprintf( pszImgFile, nImgFileLen, "%s%sIMG-VV%s",
              CPLGetDirname(poOpenInfo->pszFilename), SEP_STRING, pszSuffix );
-    fpVV = VSIFOpenL( pszImgFile, "rb" );
+    VSILFILE *fpVV = VSIFOpenL( pszImgFile, "rb" );
     if (fpVV != NULL) {
         poDS->SetBand( nBandNum, new PALSARJaxaRasterBand( poDS, 3, fpVV ) );
-        nBandNum++;
+        /* nBandNum++; */
     }
 
     VSIFree( pszImgFile );
diff --git a/frmts/jdem/jdemdataset.cpp b/frmts/jdem/jdemdataset.cpp
index 9de4534..3645cf2 100644
--- a/frmts/jdem/jdemdataset.cpp
+++ b/frmts/jdem/jdemdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: jdemdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  JDEM Reader
  * Purpose:  All code for Japanese DEM Reader
@@ -28,23 +27,25 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: jdemdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: jdemdataset.cpp 37555 2017-03-02 13:02:20Z goatbar $");
 
 /************************************************************************/
 /*                            JDEMGetField()                            */
 /************************************************************************/
 
-static int JDEMGetField( char *pszField, int nWidth )
+static int JDEMGetField( const char *pszField, int nWidth )
 
 {
-    char	szWork[32];
-
-    CPLAssert( nWidth < (int) sizeof(szWork) );
+    char szWork[32] = {};
+    CPLAssert(nWidth < static_cast<int>(sizeof(szWork)));
 
-    strncpy( szWork, pszField, nWidth );
+    strncpy(szWork, pszField, nWidth);
     szWork[nWidth] = '\0';
 
     return atoi(szWork);
@@ -54,10 +55,10 @@ static int JDEMGetField( char *pszField, int nWidth )
 /*                            JDEMGetAngle()                            */
 /************************************************************************/
 
-static double JDEMGetAngle( char *pszField )
+static double JDEMGetAngle( const char *pszField )
 
 {
-    int		nAngle = JDEMGetField( pszField, 7 );
+    const int nAngle = JDEMGetField(pszField, 7);
 
     // Note, this isn't very general purpose, but it would appear
     // from the field widths that angles are never negative.  Nice
@@ -72,7 +73,7 @@ static double JDEMGetAngle( char *pszField )
 
 /************************************************************************/
 /* ==================================================================== */
-/*				JDEMDataset				*/
+/*                              JDEMDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -82,8 +83,8 @@ class JDEMDataset : public GDALPamDataset
 {
     friend class JDEMRasterBand;
 
-    VSILFILE	*fp;
-    GByte	abyHeader[1012];
+    VSILFILE    *fp;
+    GByte       abyHeader[1012];
 
   public:
                      JDEMDataset();
@@ -92,8 +93,8 @@ class JDEMDataset : public GDALPamDataset
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
 
-    CPLErr 	GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
+    CPLErr GetGeoTransform( double * padfTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
 /************************************************************************/
@@ -107,46 +108,40 @@ class JDEMRasterBand : public GDALPamRasterBand
     friend class JDEMDataset;
 
     int          nRecordSize;
-    char*        pszRecord;
-    int          bBufferAllocFailed;
+    char        *pszRecord;
+    bool         bBufferAllocFailed;
 
   public:
+                JDEMRasterBand( JDEMDataset *, int );
+    virtual ~JDEMRasterBand();
 
-    		JDEMRasterBand( JDEMDataset *, int );
-                ~JDEMRasterBand();
-
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                           JDEMRasterBand()                            */
 /************************************************************************/
 
 JDEMRasterBand::JDEMRasterBand( JDEMDataset *poDSIn, int nBandIn ) :
+    // Cannot overflow as nBlockXSize <= 999.
+    nRecordSize(poDSIn->GetRasterXSize() * 5 + 9 + 2),
     pszRecord(NULL),
-    bBufferAllocFailed(FALSE)
+    bBufferAllocFailed(false)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Float32;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
-
-    /* Cannot overflow as nBlockXSize <= 999 */
-    nRecordSize = nBlockXSize*5 + 9 + 2;
 }
 
 /************************************************************************/
 /*                          ~JDEMRasterBand()                            */
 /************************************************************************/
 
-JDEMRasterBand::~JDEMRasterBand()
-{
-    VSIFree(pszRecord);
-}
+JDEMRasterBand::~JDEMRasterBand() { VSIFree(pszRecord); }
 
 /************************************************************************/
 /*                             IReadBlock()                             */
@@ -157,51 +152,52 @@ CPLErr JDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                    void * pImage )
 
 {
-    JDEMDataset *poGDS = (JDEMDataset *) poDS;
+    JDEMDataset *poGDS = static_cast<JDEMDataset *>(poDS);
 
     if (pszRecord == NULL)
     {
         if (bBufferAllocFailed)
             return CE_Failure;
 
-        pszRecord = (char *) VSI_MALLOC_VERBOSE(nRecordSize);
+        pszRecord = static_cast<char *>(VSI_MALLOC_VERBOSE(nRecordSize));
         if (pszRecord == NULL)
         {
-            bBufferAllocFailed = TRUE;
+            bBufferAllocFailed = true;
             return CE_Failure;
         }
     }
 
-    CPL_IGNORE_RET_VAL(VSIFSeekL( poGDS->fp, 1011 + nRecordSize*nBlockYOff, SEEK_SET ));
+    CPL_IGNORE_RET_VAL(
+        VSIFSeekL(poGDS->fp, 1011 + nRecordSize * nBlockYOff, SEEK_SET));
 
-    CPL_IGNORE_RET_VAL(VSIFReadL( pszRecord, 1, nRecordSize, poGDS->fp ));
+    CPL_IGNORE_RET_VAL(VSIFReadL(pszRecord, 1, nRecordSize, poGDS->fp));
 
-    if( !EQUALN((char *) poGDS->abyHeader,pszRecord,6) )
+    if( !EQUALN(reinterpret_cast<char *>(poGDS->abyHeader), pszRecord, 6) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "JDEM Scanline corrupt.  Perhaps file was not transferred\n"
-                  "in binary mode?" );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "JDEM Scanline corrupt.  Perhaps file was not transferred "
+                 "in binary mode?");
         return CE_Failure;
     }
 
-    if( JDEMGetField( pszRecord + 6, 3 ) != nBlockYOff + 1 )
+    if( JDEMGetField(pszRecord + 6, 3) != nBlockYOff + 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "JDEM scanline out of order, JDEM driver does not\n"
-                  "currently support partial datasets." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "JDEM scanline out of order, JDEM driver does not "
+                 "currently support partial datasets.");
         return CE_Failure;
     }
 
     for( int i = 0; i < nBlockXSize; i++ )
-        ((float *) pImage)[i] = (float)
-            (JDEMGetField( pszRecord + 9 + 5 * i, 5) * 0.1);
+        static_cast<float *>(pImage)[i] =
+            JDEMGetField(pszRecord + 9 + 5 * i, 5) * 0.1f;
 
     return CE_None;
 }
 
 /************************************************************************/
 /* ==================================================================== */
-/*				JDEMDataset				*/
+/*                              JDEMDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -211,7 +207,9 @@ CPLErr JDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
 JDEMDataset::JDEMDataset() :
     fp(NULL)
-{ }
+{
+    std::fill_n(abyHeader, CPL_ARRAYSIZE(abyHeader), 0);
+}
 
 /************************************************************************/
 /*                           ~JDEMDataset()                             */
@@ -222,20 +220,22 @@ JDEMDataset::~JDEMDataset()
 {
     FlushCache();
     if( fp != NULL )
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
 }
 
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr JDEMDataset::GetGeoTransform( double * padfTransform )
+CPLErr JDEMDataset::GetGeoTransform( double *padfTransform )
 
 {
-    const double dfLLLat = JDEMGetAngle( (char *) abyHeader + 29 );
-    const double dfLLLong = JDEMGetAngle( (char *) abyHeader + 36 );
-    const double dfURLat = JDEMGetAngle( (char *) abyHeader + 43 );
-    const double dfURLong = JDEMGetAngle( (char *) abyHeader + 50 );
+    const char *psHeader = reinterpret_cast<char *>(abyHeader);
+
+    const double dfLLLat = JDEMGetAngle(psHeader + 29);
+    const double dfLLLong = JDEMGetAngle(psHeader + 36);
+    const double dfURLat = JDEMGetAngle(psHeader + 43);
+    const double dfURLong = JDEMGetAngle(psHeader + 50);
 
     padfTransform[0] = dfLLLong;
     padfTransform[3] = dfURLat;
@@ -255,30 +255,35 @@ CPLErr JDEMDataset::GetGeoTransform( double * padfTransform )
 const char *JDEMDataset::GetProjectionRef()
 
 {
-    return( "GEOGCS[\"Tokyo\",DATUM[\"Tokyo\",SPHEROID[\"Bessel 1841\",6377397.155,299.1528128,AUTHORITY[\"EPSG\",7004]],TOWGS84[-148,507,685,0,0,0,0],AUTHORITY[\"EPSG\",6301]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],UNIT[\"DMSH\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4301]]" );
+    return
+        "GEOGCS[\"Tokyo\",DATUM[\"Tokyo\","
+        "SPHEROID[\"Bessel 1841\",6377397.155,299.1528128,"
+        "AUTHORITY[\"EPSG\",7004]],TOWGS84[-148,507,685,0,0,0,0],"
+        "AUTHORITY[\"EPSG\",6301]],PRIMEM[\"Greenwich\",0,"
+        "AUTHORITY[\"EPSG\",8901]],UNIT[\"DMSH\",0.0174532925199433,"
+        "AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4301]]";
 }
 
 /************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
 
-int JDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
+int JDEMDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Confirm that the header has what appears to be dates in the     */
-/*      expected locations.  Sadly this is a relatively weak test.      */
-/* -------------------------------------------------------------------- */
+    // Confirm that the header has what appears to be dates in the
+    // expected locations.  Sadly this is a relatively weak test.
     if( poOpenInfo->nHeaderBytes < 50 )
         return FALSE;
 
-    /* check if century values seem reasonable */
-    if( (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+11, "19")
-          && !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+11, "20"))
-        || (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+15, "19")
-             && !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+15, "20"))
-        || (!STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+19, "19")
-             && !STARTS_WITH_CI((char *)poOpenInfo->pabyHeader+19, "20")) )
+    // Check if century values seem reasonable.
+    const char *psHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
+    if( (!STARTS_WITH_CI(psHeader + 11, "19") &&
+         !STARTS_WITH_CI(psHeader + 11, "20")) ||
+        (!STARTS_WITH_CI(psHeader + 15, "19") &&
+         !STARTS_WITH_CI(psHeader + 15, "20")) ||
+        (!STARTS_WITH_CI(psHeader + 19, "19") &&
+         !STARTS_WITH_CI(psHeader + 19, "20")) )
     {
         return FALSE;
     }
@@ -290,74 +295,61 @@ int JDEMDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *JDEMDataset::Open( GDALOpenInfo *poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Confirm that the header is compatible with a JDEM dataset.      */
-/* -------------------------------------------------------------------- */
+    // Confirm that the header is compatible with a JDEM dataset.
     if (!Identify(poOpenInfo))
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
+    // Confirm the requested access is supported.
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "The JDEM driver does not support update access to existing"
-                  " datasets.\n" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The JDEM driver does not support update access to existing "
+                 "datasets.");
         return NULL;
     }
 
-    /* Check that the file pointer from GDALOpenInfo* is available */
+    // Check that the file pointer from GDALOpenInfo* is available.
     if( poOpenInfo->fpL == NULL )
     {
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
+    // Create a corresponding GDALDataset.
     JDEMDataset *poDS = new JDEMDataset();
 
-    /* Borrow the file pointer from GDALOpenInfo* */
+    // Borrow the file pointer from GDALOpenInfo*.
     poDS->fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Read the header.                                                */
-/* -------------------------------------------------------------------- */
-    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->abyHeader, 1, 1012, poDS->fp ));
+    // Read the header.
+    CPL_IGNORE_RET_VAL(VSIFReadL(poDS->abyHeader, 1, 1012, poDS->fp));
 
-    poDS->nRasterXSize = JDEMGetField( (char *) poDS->abyHeader + 23, 3 );
-    poDS->nRasterYSize = JDEMGetField( (char *) poDS->abyHeader + 26, 3 );
-    if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
+    const char *psHeader = reinterpret_cast<char *>(poDS->abyHeader);
+    poDS->nRasterXSize = JDEMGetField(psHeader + 23, 3);
+    poDS->nRasterYSize = JDEMGetField(psHeader + 26, 3);
+    if( poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Invalid dimensions : %d x %d",
-                  poDS->nRasterXSize, poDS->nRasterYSize);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid dimensions : %d x %d",
+                 poDS->nRasterXSize, poDS->nRasterYSize);
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
-    poDS->SetBand( 1, new JDEMRasterBand( poDS, 1 ));
+    // Create band information objects.
+    poDS->SetBand(1, new JDEMRasterBand(poDS, 1));
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    // Initialize any PAM information.
+    poDS->SetDescription(poOpenInfo->pszFilename);
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Check for overviews.                                            */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    // Check for overviews.
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -367,20 +359,20 @@ GDALDataset *JDEMDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_JDEM()
 
 {
-    if( GDALGetDriverByName( "JDEM" ) != NULL )
+    if( GDALGetDriverByName("JDEM") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "JDEM" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Japanese DEM (.mem)" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#JDEM" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mem" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription("JDEM");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Japanese DEM (.mem)");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#JDEM");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "mem");
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
 
     poDriver->pfnOpen = JDEMDataset::Open;
     poDriver->pfnIdentify = JDEMDataset::Identify;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/jp2kak/GNUmakefile b/frmts/jp2kak/GNUmakefile
index 94e610f..339a455 100644
--- a/frmts/jp2kak/GNUmakefile
+++ b/frmts/jp2kak/GNUmakefile
@@ -30,4 +30,4 @@ clean:
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
 	cp $(APPOBJ) ../o
 
-$(OBJ) $(O_OBJ):	subfile_source.h
+$(OBJ) $(O_OBJ): jp2kakdataset.h subfile_source.h
diff --git a/frmts/jp2kak/frmt_jp2kak.html b/frmts/jp2kak/frmt_jp2kak.html
index 44a46e6..3180fef 100644
--- a/frmts/jp2kak/frmt_jp2kak.html
+++ b/frmts/jp2kak/frmt_jp2kak.html
@@ -13,7 +13,7 @@ can be written.  Existing images cannot be updated in place.<p>
 
 The JPEG2000 file format supports lossy and lossless compression of
 8bit and 16bit images with 1 or more bands (components).  Via the
-<a href="http://www.mappingscience.com/msi.html">GeoJP2 (tm)</a> mechanism,
+<a href="https://web.archive.org/web/20151028081930/http://www.lizardtech.com/download/geo/geotiff_box.txt">GeoJP2 (tm)</a> mechanism,
 GeoTIFF style coordinate system and georeferencing information can be embedded
 within the JP2 file.  JPEG2000 files use a substantially different format and
 compression mechanism than the traditional JPEG compression and JPEG JFIF
@@ -41,7 +41,7 @@ stored as XML raw content in the xml:XMP metadata domain.<p>
 <h2>Configuration Options</h2>
 
 The JP2KAK driver supports the following
-<a href="http://trac.osgeo.org/gdal/ConfigOptions">Config Options</a>.
+<a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">Config Options</a>.
 These runtime options can be used to alter the behavior of the driver.
 
 <ul>
@@ -62,6 +62,30 @@ on.  Defaults to NO.<p>
 
 </ul>
 
+<h2><a name="georeferencing">Georeferencing</a></h2>
+
+<p>
+Georeferencing information can come from different sources : internal (GeoJP2
+or GMLJP2 boxes), worldfile .j2w/.wld sidecar files, or PAM (Persitant Auxiliary metadata)
+.aux.xml sidecar files.
+By default, information is fetched in following order (first listed is the most
+prioritary): PAM, GeoJP2, GMLJP2, WORLDFILE.
+</p>
+<p>Starting with GDAL 2.2, the allowed sources
+and their priority order can be changed with the GDAL_GEOREF_SOURCES
+configuration option (or GEOREF_SOURCES open option) whose value is a
+comma-separated list of the following keywords :
+PAM, GEOJP2, GMLJP2, INTERNAL (shortcut for GEOJP2,GMLJP2), WORLDFILE, NONE.
+First mentioned sources are the most prioritary over the next ones. A non mentioned
+source will be ignored.
+</p>
+<p>
+For example setting it to "WORLDFILE,PAM,INTERNAL" will make a geotransformation
+matrix from a potential worldfile prioritary over PAM or internal JP2 boxes.
+Setting it to "PAM,WORLDFILE,GEOJP2" will use the mentioned sources and
+ignore GMLJP2 boxes.
+</p>
+
 <h2>Option Options</h2>
 
 (GDAL >= 2.0 )
@@ -70,6 +94,8 @@ The following open option is available:
 <ul>
 <li><p><b>1BIT_ALPHA_PROMOTION=YES/NO</b>: Whether a 1-bit alpha channel should be promoted to 8-bit.
 Defaults to YES.</li>
+<li><p><b>GEOREF_SOURCES=string</b>: (GDAL > 2.2) Define which georeferencing sources are
+allowed and their priority order. See <a href="#georeferencing"><i>Georeferencing</i></a> paragraph.</li>
 </ul>
 
 <h2>Creation Issues</h2>
@@ -149,7 +175,29 @@ to better understand their meaning.<p>
 <li> <b>Rweight</b>: Kakadu library default used.
 </ul>
 
-See Also:<p>
+<h2>Known Kakadu Issues</h2>
+
+<h3>Alpha Channel Writing in v7.8</h3>
+
+Kakadu v7.8 has a bug in jp2_channels::set_opacity_mapping that can
+cause an error when writing images with an alpha channel.  Please
+upgrade to version 7.9.
+
+<pre>
+Error: GdalIO: Error in Kakadu File Format Support: Attempting to
+create a Component Mapping (cmap) box, one of whose channels refers to
+a non-existent image component or palette lookup table. (code = 1)
+</pre>
+
+<h3>kdu_get_num_processors always returns 0 for some platforms</h3>
+
+On non-windows / non-mac installs (e.g. Linux), Kakadu might not
+include unistd.h in kdu_arch.cpp.  This means that
+_SC_NPROCESSORS_ONLN and _SC_NPROCESSORS_CONF are not defined and
+kdu_get_num_processors will always return 0.  Therefore the jp2kak
+driver might not default to creating worker threads.
+
+<h2>See Also:</h2>
 
 <ul>
 
@@ -157,9 +205,6 @@ See Also:<p>
 
 <li> If you're using a Kakadu release before v7.5, configure & compile GDAL with eg. <code>CXXFLAGS="-DKDU_MAJOR_VERSION=7 -DKDU_MINOR_VERSION=3 -DKDU_PATCH_VERSION=2"</code> for Kakadu version 7.3.2.</li>
 
-<li> <a href="http://www.remotesensing.org/jpeg2000/">JPEG2000 for Geospatial
-Applications</a> page, includes GeoJP2(tm) discussion.</li>
-
 <li> Alternate <a href="frmt_jpeg2000.html">JPEG2000 driver</a>.</li>
 
 </ul>
diff --git a/frmts/jp2kak/jp2kak_headers.h b/frmts/jp2kak/jp2kak_headers.h
index ca698e3..c900696 100644
--- a/frmts/jp2kak/jp2kak_headers.h
+++ b/frmts/jp2kak/jp2kak_headers.h
@@ -55,8 +55,10 @@
 #include "kdu_image.h"
 #include "roi_sources.h"
 
+// From rouault:
 // I don't think JPIP support currently works due to changes in
 // classes like kdu_window ... some fixing required if someone wants it.
+
 // #define USE_JPIP
 
 #ifdef USE_JPIP
@@ -65,4 +67,4 @@
 #  define kdu_client void
 #endif
 
-#endif
+#endif  // JP2KAK_HEADERS_H
diff --git a/frmts/jp2kak/jp2kakdataset.cpp b/frmts/jp2kak/jp2kakdataset.cpp
index 6615ff5..5daf0c8 100644
--- a/frmts/jp2kak/jp2kakdataset.cpp
+++ b/frmts/jp2kak/jp2kakdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: jp2kakdataset.cpp 34399 2016-06-24 08:27:25Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Implementation of the ISO/IEC 15444-1 standard based on Kakadu.
@@ -32,6 +31,9 @@
 #define DO_NOT_USE_DEBUG_BOOL
 #endif
 
+#include "cpl_port.h"
+#include "jp2kakdataset.h"
+
 #include "cpl_multiproc.h"
 #include "cpl_string.h"
 #include "gdal_frmts.h"
@@ -45,7 +47,13 @@
 #include "subfile_source.h"
 #include "vsil_target.h"
 
-CPL_CVSID("$Id: jp2kakdataset.cpp 34399 2016-06-24 08:27:25Z rouault $");
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <cmath>
+#include <vector>
+
+CPL_CVSID("$Id: jp2kakdataset.cpp 37710 2017-03-14 19:12:48Z goatbar $");
 
 // Before v7.5 Kakadu does not advertise its version well
 // After v7.5 Kakadu has KDU_{MAJOR,MINOR,PATCH}_VERSION defines so it's easier
@@ -64,186 +72,15 @@ CPL_CVSID("$Id: jp2kakdataset.cpp 34399 2016-06-24 08:27:25Z rouault $");
 static bool kakadu_initialized = false;
 
 static const unsigned char jp2_header[] =
-    {0x00,0x00,0x00,0x0c,0x6a,0x50,0x20,0x20,0x0d,0x0a,0x87,0x0a};
+    {0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a};
 
-static const unsigned char jpc_header[] = {0xff,0x4f};
+static const unsigned char jpc_header[] = {0xff, 0x4f};
 
 /* -------------------------------------------------------------------- */
 /*      The number of tiles at a time we will push through the          */
 /*      encoder per flush when writing jpeg2000 streams.                */
 /* -------------------------------------------------------------------- */
-#define TILE_CHUNK_SIZE  1024
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            JP2KAKDataset                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class JP2KAKDataset : public GDALJP2AbstractDataset
-{
-    friend class JP2KAKRasterBand;
-
-    kdu_codestream oCodeStream;
-    kdu_compressed_source *poInput;
-    kdu_compressed_source *poRawInput;
-    jp2_family_src  *family;
-    kdu_client      *jpip_client;
-    kdu_dims dims;
-    int            nResCount;
-    bool           bPreferNPReads;
-    kdu_thread_env *poThreadEnv;
-
-    int            bCached;
-    int            bResilient;
-    int            bFussy;
-    bool           bUseYCC;
-
-    bool           bPromoteTo8Bit;
-
-    int         TestUseBlockIO( int, int, int, int, int, int,
-                                GDALDataType, int, int * );
-    CPLErr      DirectRasterIO( GDALRWFlag, int, int, int, int,
-                                void *, int, int, GDALDataType,
-                                int, int *,
-                                GSpacing nPixelSpace, GSpacing nLineSpace,
-                                GSpacing nBandSpace,
-                                GDALRasterIOExtraArg* psExtraArg);
-
-    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
-                              void *, int, int, GDALDataType,
-                              int, int *,
-                              GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
-
-
-  public:
-                JP2KAKDataset();
-    virtual ~JP2KAKDataset();
-
-    virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
-
-    static void KakaduInitialize();
-    static GDALDataset *Open( GDALOpenInfo * );
-    static int          Identify( GDALOpenInfo * );
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            JP2KAKRasterBand                          */
-/* ==================================================================== */
-/************************************************************************/
-
-class JP2KAKRasterBand : public GDALPamRasterBand
-{
-    friend class JP2KAKDataset;
-
-    JP2KAKDataset *poBaseDS;
-
-    int         nDiscardLevels;
-
-    kdu_dims    band_dims;
-
-    int         nOverviewCount;
-    JP2KAKRasterBand **papoOverviewBand;
-
-    kdu_client      *jpip_client;
-
-    kdu_codestream oCodeStream;
-
-    GDALColorTable oCT;
-
-    int         bYCbCrReported;
-
-    GDALColorInterp eInterp;
-
-    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
-                              void *, int, int, GDALDataType,
-                              GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
-
-    int            HasExternalOverviews()
-                   { return GDALPamRasterBand::GetOverviewCount() != 0; }
-
-  public:
-
-                JP2KAKRasterBand( int, int, kdu_codestream, int, kdu_client *,
-                                  jp2_channels, JP2KAKDataset * );
-    virtual ~JP2KAKRasterBand();
-
-    virtual CPLErr IReadBlock( int, int, void * );
-
-    virtual int    GetOverviewCount();
-    virtual GDALRasterBand *GetOverview( int );
-
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-
-    // internal
-
-    void        ApplyPalette( jp2_palette oJP2Palette );
-    void        ProcessYCbCrTile( kdu_tile tile, GByte *pabyBuffer,
-                                  int nBlockXOff, int nBlockYOff,
-                                  int nTileOffsetX, int nTileOffsetY );
-    void        ProcessTile(kdu_tile tile, GByte *pabyBuffer );
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                     Set up messaging services                        */
-/* ==================================================================== */
-/************************************************************************/
-
-class kdu_cpl_error_message : public kdu_thread_safe_message
-{
-public: // Member classes
-    using kdu_thread_safe_message::put_text;
-
-    kdu_cpl_error_message( CPLErr eErrClass )
-    {
-        m_eErrClass = eErrClass;
-        m_pszError = NULL;
-    }
-
-    void put_text(const char *string)
-    {
-        if( m_pszError == NULL )
-            m_pszError = CPLStrdup( string );
-        else
-        {
-            m_pszError = (char *)
-                CPLRealloc(m_pszError, strlen(m_pszError) + strlen(string)+1 );
-            strcat( m_pszError, string );
-        }
-    }
-
-    class JP2KAKException {};
-
-    void flush(bool end_of_message=false)
-    {
-        kdu_thread_safe_message::flush(end_of_message);
-
-        if( m_pszError == NULL )
-            return;
-        if( m_pszError[strlen(m_pszError)-1] == '\n' )
-            m_pszError[strlen(m_pszError)-1] = '\0';
-
-        CPLError( m_eErrClass, CPLE_AppDefined, "%s", m_pszError );
-        CPLFree( m_pszError );
-        m_pszError = NULL;
-
-        if( end_of_message && m_eErrClass == CE_Failure )
-        {
-            throw JP2KAKException();
-        }
-    }
-
-private:
-    CPLErr m_eErrClass;
-    char *m_pszError;
-};
+static const int TILE_CHUNK_SIZE = 1024;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -262,59 +99,47 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBandIn, int nDiscardLevelsIn,
                                     JP2KAKDataset *poBaseDSIn ) :
     poBaseDS(poBaseDSIn),
     nDiscardLevels(nDiscardLevelsIn),
+    nOverviewCount(0),
+    papoOverviewBand(NULL),
     jpip_client(jpip_clientIn),
     oCodeStream(oCodeStreamIn),
-    bYCbCrReported(FALSE)
+    eInterp(GCI_Undefined)
 {
     nBand = nBandIn;  // From GDALRasterBand.
 
-    if( oCodeStream.get_bit_depth(nBand-1) > 8
-        && oCodeStream.get_bit_depth(nBand-1) <= 16
-        && oCodeStream.get_signed(nBand-1) )
+    if( oCodeStream.get_bit_depth(nBand - 1) > 8 &&
+        oCodeStream.get_bit_depth(nBand - 1) <= 16 &&
+        oCodeStream.get_signed(nBand - 1) )
         eDataType = GDT_Int16;
-    else if( oCodeStream.get_bit_depth(nBand-1) > 8
-             && oCodeStream.get_bit_depth(nBand-1) <= 16
-             && !oCodeStream.get_signed(nBand-1) )
+    else if( oCodeStream.get_bit_depth(nBand - 1) > 8 &&
+             oCodeStream.get_bit_depth(nBand - 1) <= 16 &&
+             !oCodeStream.get_signed(nBand - 1) )
         eDataType = GDT_UInt16;
     else
         eDataType = GDT_Byte;
 
-    oCodeStream.apply_input_restrictions( 0, 0, nDiscardLevels, 0, NULL );
-    oCodeStream.get_dims( 0, band_dims );
+    oCodeStream.apply_input_restrictions(0, 0, nDiscardLevels, 0, NULL);
+    oCodeStream.get_dims(0, band_dims);
 
     nRasterXSize = band_dims.size.x;
     nRasterYSize = band_dims.size.y;
 
-/* -------------------------------------------------------------------- */
-/*      Capture some useful metadata.                                   */
-/* -------------------------------------------------------------------- */
-    if( oCodeStream.get_bit_depth(nBand-1) % 8 != 0 &&
+    // Capture some useful metadata.
+    if( oCodeStream.get_bit_depth(nBand - 1) % 8 != 0 &&
         !poBaseDSIn->bPromoteTo8Bit )
     {
-        SetMetadataItem( "NBITS",
-                         CPLString().Printf(
-                             "%d",oCodeStream.get_bit_depth(nBand-1)),
-                         "IMAGE_STRUCTURE" );
+        SetMetadataItem(
+            "NBITS",
+            CPLString().Printf("%d", oCodeStream.get_bit_depth(nBand - 1)),
+            "IMAGE_STRUCTURE");
     }
-    SetMetadataItem( "COMPRESSION", "JP2000", "IMAGE_STRUCTURE" );
+    SetMetadataItem("COMPRESSION", "JP2000", "IMAGE_STRUCTURE");
 
-/* -------------------------------------------------------------------- */
-/*      Use a 2048x128 "virtual" block size unless the file is small.    */
-/* -------------------------------------------------------------------- */
-    if( nRasterXSize >= 2048 )
-        nBlockXSize = 2048;
-    else
-        nBlockXSize = nRasterXSize;
-
-    if( nRasterYSize >= 256 )
-        nBlockYSize = 128;
-    else
-        nBlockYSize = nRasterYSize;
-
-/* -------------------------------------------------------------------- */
-/*      Figure out the color interpretation for this band.              */
-/* -------------------------------------------------------------------- */
+    // Use a 2048x128 "virtual" block size unless the file is small.
+    nBlockXSize = std::min(nRasterXSize, 2048);
+    nBlockYSize = std::min(nRasterYSize, 128);
 
+    // Figure out the color interpretation for this band.
     eInterp = GCI_Undefined;
 
     if( oJP2Channels.exists() )
@@ -324,46 +149,51 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBandIn, int nDiscardLevelsIn,
         int nBlueIndex = -1;
         int nLutIndex = 0;
         int nCSI = 0;
+
 #if KDU_MAJOR_VERSION > 7 || (KDU_MAJOR_VERSION == 7 && KDU_MINOR_VERSION >= 8)
         int nFMT = 0;
-#endif
-
         if( oJP2Channels.get_num_colours() == 3 )
         {
-#if KDU_MAJOR_VERSION > 7 || (KDU_MAJOR_VERSION == 7 && KDU_MINOR_VERSION >= 8)
-            oJP2Channels.get_colour_mapping( 0, nRedIndex, nLutIndex, nCSI, nFMT );
-            oJP2Channels.get_colour_mapping( 1, nGreenIndex, nLutIndex, nCSI, nFMT );
-            oJP2Channels.get_colour_mapping( 2, nBlueIndex, nLutIndex, nCSI, nFMT );
-#else
-            oJP2Channels.get_colour_mapping( 0, nRedIndex, nLutIndex, nCSI );
-            oJP2Channels.get_colour_mapping( 1, nGreenIndex, nLutIndex, nCSI );
-            oJP2Channels.get_colour_mapping( 2, nBlueIndex, nLutIndex, nCSI );
-#endif
+            oJP2Channels.get_colour_mapping(0, nRedIndex, nLutIndex, nCSI,
+                                            nFMT);
+            oJP2Channels.get_colour_mapping(1, nGreenIndex, nLutIndex, nCSI,
+                                            nFMT);
+            oJP2Channels.get_colour_mapping(2, nBlueIndex, nLutIndex, nCSI,
+                                            nFMT);
         }
         else
         {
-#if KDU_MAJOR_VERSION > 7 || (KDU_MAJOR_VERSION == 7 && KDU_MINOR_VERSION >= 8)
-            oJP2Channels.get_colour_mapping( 0, nRedIndex, nLutIndex, nCSI, nFMT );
+            oJP2Channels.get_colour_mapping(0, nRedIndex, nLutIndex, nCSI,
+                                            nFMT);
+            if( nBand == 1 )
+                eInterp = GCI_GrayIndex;
+        }
 #else
-            oJP2Channels.get_colour_mapping( 0, nRedIndex, nLutIndex, nCSI );
-#endif
+        if( oJP2Channels.get_num_colours() == 3 )
+        {
+            oJP2Channels.get_colour_mapping(0, nRedIndex, nLutIndex, nCSI);
+            oJP2Channels.get_colour_mapping(1, nGreenIndex, nLutIndex, nCSI);
+            oJP2Channels.get_colour_mapping(2, nBlueIndex, nLutIndex, nCSI);
+        }
+        else
+        {
+            oJP2Channels.get_colour_mapping(0, nRedIndex, nLutIndex, nCSI);
             if( nBand == 1 )
                 eInterp = GCI_GrayIndex;
         }
+#endif
 
         if( eInterp != GCI_Undefined )
             /* nothing to do */;
-
         // If we have LUT info, it is a palette image.
         else if( nLutIndex != -1 )
             eInterp = GCI_PaletteIndex;
-
         // Establish color band this is.
-        else if( nRedIndex == nBand-1 )
+        else if( nRedIndex == nBand - 1 )
             eInterp = GCI_RedBand;
-        else if( nGreenIndex == nBand-1 )
+        else if( nGreenIndex == nBand - 1 )
             eInterp = GCI_GreenBand;
-        else if( nBlueIndex == nBand-1 )
+        else if( nBlueIndex == nBand - 1 )
             eInterp = GCI_BlueBand;
         else
             eInterp = GCI_Undefined;
@@ -379,22 +209,22 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBandIn, int nDiscardLevelsIn,
 
                 // get_opacity_mapping sets that last 3 args by non-const refs.
 #if KDU_MAJOR_VERSION > 7 || (KDU_MAJOR_VERSION == 7 && KDU_MINOR_VERSION >= 8)
-                if( oJP2Channels.get_opacity_mapping( color_idx, opacity_idx,
-                                                      lut_idx, nCSI, nFMT ) )
+                if(oJP2Channels.get_opacity_mapping(color_idx, opacity_idx,
+                                                    lut_idx, nCSI, nFMT))
 #else
-                if( oJP2Channels.get_opacity_mapping( color_idx, opacity_idx,
-                                                      lut_idx, nCSI ) )
+                if(oJP2Channels.get_opacity_mapping(color_idx, opacity_idx,
+                                                    lut_idx, nCSI))
 #endif
                 {
                     if( opacity_idx == nBand - 1 )
                         eInterp = GCI_AlphaBand;
                 }
 #if KDU_MAJOR_VERSION > 7 || (KDU_MAJOR_VERSION == 7 && KDU_MINOR_VERSION >= 8)
-                if( oJP2Channels.get_premult_mapping( color_idx, opacity_idx,
-                                                      lut_idx, nCSI, nFMT ) )
+                if( oJP2Channels.get_premult_mapping(color_idx, opacity_idx,
+                                                     lut_idx, nCSI, nFMT) )
 #else
-                if( oJP2Channels.get_premult_mapping( color_idx, opacity_idx,
-                                                      lut_idx, nCSI ) )
+                if( oJP2Channels.get_premult_mapping(color_idx, opacity_idx,
+                                                     lut_idx, nCSI) )
 #endif
                 {
                     if( opacity_idx == nBand - 1 )
@@ -404,20 +234,23 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBandIn, int nDiscardLevelsIn,
         }
     }
     else if( nBand == 1 )
+    {
         eInterp = GCI_RedBand;
+    }
     else if( nBand == 2 )
+    {
         eInterp = GCI_GreenBand;
+    }
     else if( nBand == 3 )
+    {
         eInterp = GCI_BlueBand;
+    }
     else
+    {
         eInterp = GCI_GrayIndex;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Do we have any overviews?  Only check if we are the full res    */
-/*      image.                                                          */
-/* -------------------------------------------------------------------- */
-    nOverviewCount = 0;
-    papoOverviewBand = 0;
+    // Do we have any overviews?  Only check if we are the full res image.
     if( nDiscardLevels == 0 && GDALPamRasterBand::GetOverviewCount() == 0 )
     {
         int nXSize = nRasterXSize;
@@ -425,33 +258,31 @@ JP2KAKRasterBand::JP2KAKRasterBand( int nBandIn, int nDiscardLevelsIn,
 
         for( int nDiscard = 1; nDiscard < nResCount; nDiscard++ )
         {
-            nXSize = (nXSize+1) / 2;
-            nYSize = (nYSize+1) / 2;
+            nXSize = (nXSize + 1) / 2;
+            nYSize = (nYSize + 1) / 2;
 
-            if( (nXSize+nYSize) < 128 || nXSize < 4 || nYSize < 4 )
-                continue; /* skip super reduced resolution layers */
+            if( (nXSize + nYSize) < 128 || nXSize < 4 || nYSize < 4 )
+                continue;  // Skip super reduced resolution layers.
 
-            oCodeStream.apply_input_restrictions( 0, 0, nDiscard, 0, NULL );
-            kdu_dims dims;  // struct with default constructor.
-            oCodeStream.get_dims( 0, dims );
+            oCodeStream.apply_input_restrictions(0, 0, nDiscard, 0, NULL);
+            kdu_dims dims;  // Struct with default constructor.
+            oCodeStream.get_dims(0, dims);
 
-            if( (dims.size.x == nXSize || dims.size.x == nXSize-1)
-                && (dims.size.y == nYSize || dims.size.y == nYSize-1) )
+            if( (dims.size.x == nXSize || dims.size.x == nXSize - 1) &&
+                (dims.size.y == nYSize || dims.size.y == nYSize - 1) )
             {
                 nOverviewCount++;
-                papoOverviewBand = static_cast<JP2KAKRasterBand **>(
-                    CPLRealloc( papoOverviewBand,
-                                sizeof(void*) * nOverviewCount ) );
-                papoOverviewBand[nOverviewCount-1] =
-                    new JP2KAKRasterBand( nBand, nDiscard, oCodeStream, 0,
-                                          jpip_client, oJP2Channels,
-                                          poBaseDS );
+                papoOverviewBand = static_cast<JP2KAKRasterBand **>(CPLRealloc(
+                    papoOverviewBand, sizeof(void *) * nOverviewCount));
+                papoOverviewBand[nOverviewCount - 1] =
+                    new JP2KAKRasterBand(nBand, nDiscard, oCodeStream, 0,
+                                         jpip_client, oJP2Channels, poBaseDS);
             }
             else
             {
-                CPLDebug( "GDAL", "Discard %dx%d JPEG2000 overview layer,\n"
-                          "expected %dx%d.",
-                          dims.size.x, dims.size.y, nXSize, nYSize );
+                CPLDebug("GDAL", "Discard %dx%d JPEG2000 overview layer,\n"
+                         "expected %dx%d.",
+                         dims.size.x, dims.size.y, nXSize, nYSize);
             }
         }
     }
@@ -467,7 +298,7 @@ JP2KAKRasterBand::~JP2KAKRasterBand()
     for( int i = 0; i < nOverviewCount; i++ )
         delete papoOverviewBand[i];
 
-    CPLFree( papoOverviewBand );
+    CPLFree(papoOverviewBand);
 }
 
 /************************************************************************/
@@ -491,7 +322,7 @@ GDALRasterBand *JP2KAKRasterBand::GetOverview( int iOverviewIndex )
 
 {
     if( GDALPamRasterBand::GetOverviewCount() > 0 )
-        return GDALPamRasterBand::GetOverview( iOverviewIndex );
+        return GDALPamRasterBand::GetOverview(iOverviewIndex);
 
     if( iOverviewIndex < 0 || iOverviewIndex >= nOverviewCount )
         return NULL;
@@ -506,33 +337,29 @@ GDALRasterBand *JP2KAKRasterBand::GetOverview( int iOverviewIndex )
 CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                      void * pImage )
 {
-    const int nWordSize = GDALGetDataTypeSizeBytes( eDataType );
+    const int nWordSize = GDALGetDataTypeSizeBytes(eDataType);
     int nOvMult = 1;
     int nLevelsLeft = nDiscardLevels;
     while( nLevelsLeft-- > 0 )
         nOvMult *= 2;
 
-    CPLDebug( "JP2KAK", "IReadBlock(%d,%d) on band %d.",
-              nBlockXOff, nBlockYOff, nBand );
+    CPLDebug("JP2KAK", "IReadBlock(%d,%d) on band %d.",
+             nBlockXOff, nBlockYOff, nBand);
 
-/* -------------------------------------------------------------------- */
-/*      Compute the normal window, and buffer size.                     */
-/* -------------------------------------------------------------------- */
-    int nWXOff = nBlockXOff * nBlockXSize * nOvMult;
-    int nWYOff = nBlockYOff * nBlockYSize * nOvMult;
+    // Compute the normal window, and buffer size.
+    const int nWXOff = nBlockXOff * nBlockXSize * nOvMult;
+    const int nWYOff = nBlockYOff * nBlockYSize * nOvMult;
     int nWXSize = nBlockXSize * nOvMult;
     int nWYSize = nBlockYSize * nOvMult;
 
     int nXSize = nBlockXSize;
     int nYSize = nBlockYSize;
 
-/* -------------------------------------------------------------------- */
-/*      Adjust if we have a partial block on the right or bottom of     */
-/*      the image.  Unfortunately despite some care I can't seem to     */
-/*      always get partial tiles to come from the desired overview      */
-/*      level depending on how various things round - hopefully not     */
-/*      a big deal.                                                     */
-/* -------------------------------------------------------------------- */
+    // Adjust if we have a partial block on the right or bottom of
+    // the image.  Unfortunately despite some care I can't seem to
+    // always get partial tiles to come from the desired overview
+    // level depending on how various things round - hopefully not
+    // a big deal.
     if( nWXOff + nWXSize > poBaseDS->GetRasterXSize() )
     {
         nWXSize = poBaseDS->GetRasterXSize() - nWXOff;
@@ -546,55 +373,46 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     }
 
     if( nXSize != nBlockXSize || nYSize != nBlockYSize )
-        memset( pImage, 0, nBlockXSize * nBlockYSize * nWordSize );
+        memset(pImage, 0, nBlockXSize * nBlockYSize * nWordSize);
 
-/* -------------------------------------------------------------------- */
-/*      By default we invoke just for the requested band, directly      */
-/*      into the target buffer.                                         */
-/* -------------------------------------------------------------------- */
+    // By default we invoke just for the requested band, directly
+    // into the target buffer.
     GDALRasterIOExtraArg sExtraArg;
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
     if( !poBaseDS->bUseYCC )
     {
-        return poBaseDS->DirectRasterIO( GF_Read,
-                                         nWXOff, nWYOff, nWXSize, nWYSize,
-                                         pImage, nXSize, nYSize,
-                                         eDataType, 1, &nBand,
-                                         nWordSize, nWordSize*nBlockXSize,
-                                         0, &sExtraArg );
+        return poBaseDS->DirectRasterIO(GF_Read,
+                                        nWXOff, nWYOff, nWXSize, nWYSize,
+                                        pImage, nXSize, nYSize,
+                                        eDataType, 1, &nBand,
+                                        nWordSize, nWordSize*nBlockXSize,
+                                        0, &sExtraArg);
     }
 
-/* -------------------------------------------------------------------- */
-/*      But for YCC or possible other effectively pixel interleaved     */
-/*      products, we read all bands into a single buffer, fetch out     */
-/*      what we want, and push the rest into the block cache.           */
-/* -------------------------------------------------------------------- */
-    CPLErr eErr = CE_None;
+    // But for YCC or possible other effectively pixel interleaved
+    // products, we read all bands into a single buffer, fetch out
+    // what we want, and push the rest into the block cache.
     std::vector<int> anBands;
 
     for( int iBand = 0; iBand < poBaseDS->GetRasterCount(); iBand++ )
     {
-        GDALRasterBand* poBand = poBaseDS->GetRasterBand(iBand+1);
+        GDALRasterBand *poBand = poBaseDS->GetRasterBand(iBand + 1);
         if ( poBand->GetRasterDataType() != eDataType )
           continue;
-        anBands.push_back(iBand+1);
+        anBands.push_back(iBand + 1);
     }
 
     GByte *pabyWrkBuffer = static_cast<GByte *>(
-        VSIMalloc3( nWordSize * anBands.size(), nBlockXSize, nBlockYSize ) );
+        VSIMalloc3(nWordSize * anBands.size(), nBlockXSize, nBlockYSize));
     if( pabyWrkBuffer == NULL )
         return CE_Failure;
 
-    eErr = poBaseDS->DirectRasterIO( GF_Read,
-                                     nWXOff, nWYOff, nWXSize, nWYSize,
-                                     pabyWrkBuffer, nXSize, nYSize,
-                                     eDataType,
-                                     static_cast<int>(anBands.size()),
-                                     &anBands[0],
-                                     nWordSize, nWordSize*nBlockXSize,
-                                     nWordSize*nBlockXSize*nBlockYSize,
-                                     &sExtraArg );
+    const CPLErr eErr = poBaseDS->DirectRasterIO(
+        GF_Read, nWXOff, nWYOff, nWXSize, nWYSize, pabyWrkBuffer, nXSize,
+        nYSize, eDataType, static_cast<int>(anBands.size()), &anBands[0],
+        nWordSize, nWordSize * nBlockXSize,
+        nWordSize * nBlockXSize * nBlockYSize, &sExtraArg);
 
     if( eErr == CE_None )
     {
@@ -605,18 +423,26 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             if( anBands[iBand] == nBand )
             {
                 // Application requested band.
-                memcpy( pImage, pabyWrkBuffer + nBandStart,
-                        nWordSize * nBlockXSize * nBlockYSize );
+                memcpy(pImage, pabyWrkBuffer + nBandStart,
+                       nWordSize * nBlockXSize * nBlockYSize);
             }
             else
             {
-                // all others are pushed into cache.
+                // All others are pushed into cache.
                 GDALRasterBand *poBaseBand =
                     poBaseDS->GetRasterBand(anBands[iBand]);
                 JP2KAKRasterBand *poBand = NULL;
 
                 if( nDiscardLevels == 0 )
-                    poBand = (JP2KAKRasterBand *) poBaseBand;
+                {
+                    poBand = dynamic_cast<JP2KAKRasterBand *>(poBaseBand);
+                    if( poBand == NULL )
+                    {
+                        CPLError(CE_Fatal, CPLE_AssertionFailed,
+                                 "dynamic_cast failed.");
+                        return CE_Fatal;
+                    }
+                }
                 else
                 {
                     int iOver = 0;  // Used after for.
@@ -626,27 +452,27 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                         poBand = dynamic_cast<JP2KAKRasterBand *>(
                             poBaseBand->GetOverview( iOver ) );
                         if( poBand == NULL )
-                            CPLError( CE_Fatal, CPLE_AppDefined,
-                                      "Dynamic cast failed" );
-                        if( poBand->nDiscardLevels == nDiscardLevels )
+                            CPLError(CE_Fatal, CPLE_AppDefined,
+                                     "Dynamic cast failed");
+                        else if( poBand->nDiscardLevels == nDiscardLevels )
                             break;
                     }
                     if( iOver == poBaseBand->GetOverviewCount() )
                     {
-                        CPLAssert( FALSE );
+                        CPLAssert(false);
                     }
                 }
 
                 GDALRasterBlock *poBlock = NULL;
 
                 if( poBand != NULL )
-                    poBlock = poBand->GetLockedBlockRef(
-                        nBlockXOff, nBlockYOff, TRUE );
+                    poBlock =
+                        poBand->GetLockedBlockRef(nBlockXOff, nBlockYOff, TRUE);
 
                 if( poBlock )
                 {
-                    memcpy( poBlock->GetDataRef(), pabyWrkBuffer + nBandStart,
-                            nWordSize * nBlockXSize * nBlockYSize );
+                    memcpy(poBlock->GetDataRef(), pabyWrkBuffer + nBandStart,
+                           nWordSize * nBlockXSize * nBlockYSize);
                     poBlock->DropLock();
                 }
             }
@@ -655,7 +481,7 @@ CPLErr JP2KAKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         }
     }
 
-    VSIFree( pabyWrkBuffer );
+    VSIFree(pabyWrkBuffer);
     return eErr;
 }
 
@@ -672,9 +498,7 @@ JP2KAKRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                              GDALRasterIOExtraArg* psExtraArg)
 
 {
-/* -------------------------------------------------------------------- */
-/*      We need various criteria to skip out to block based methods.    */
-/* -------------------------------------------------------------------- */
+    // We need various criteria to skip out to block based methods.
     if( poBaseDS->TestUseBlockIO( nXOff, nYOff, nXSize, nYSize,
                                   nBufXSize, nBufYSize,
                                   eBufType, 1, &nBand ) )
@@ -682,37 +506,45 @@ JP2KAKRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
             pData, nBufXSize, nBufYSize, eBufType,
             nPixelSpace, nLineSpace, psExtraArg );
-    else
-    {
-        int nOverviewDiscard = nDiscardLevels;
 
-        // Adjust request for overview level.
-        while( nOverviewDiscard > 0 )
-        {
-            nXOff *= 2;
-            nYOff *= 2;
-            nXSize *= 2;
-            nYSize *= 2;
-            nOverviewDiscard--;
-        }
+    int nOverviewDiscard = nDiscardLevels;
 
-        return poBaseDS->DirectRasterIO(
-            eRWFlag, nXOff, nYOff, nXSize, nYSize,
-            pData, nBufXSize, nBufYSize, eBufType,
-            1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg );
+    // Adjust request for overview level.
+    while( nOverviewDiscard > 0 )
+    {
+        nXOff *= 2;
+        nYOff *= 2;
+        nXSize *= 2;
+        nYSize *= 2;
+        nOverviewDiscard--;
     }
+
+    return poBaseDS->DirectRasterIO(
+        eRWFlag, nXOff, nYOff, nXSize, nYSize,
+        pData, nBufXSize, nBufYSize, eBufType,
+        1, &nBand, nPixelSpace, nLineSpace, 0, psExtraArg );
 }
 
 /************************************************************************/
 /*                            ApplyPalette()                            */
 /************************************************************************/
 
+namespace {
+
+inline short GetColorValue(const float *pafLUT, int nPos)
+{
+    const short nVal = static_cast<short>(pafLUT[nPos] * 256.0f + 128.0f);
+    const short nMin = 0;
+    const short nMax = 255;
+    return std::max(nMin, std::min(nMax, nVal));
+}
+
+}  // namespace
+
 void JP2KAKRasterBand::ApplyPalette( jp2_palette oJP2Palette )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Do we have a reasonable LUT configuration?  RGB or RGBA?        */
-/* -------------------------------------------------------------------- */
+    // Do we have a reasonable LUT configuration?  RGB or RGBA?
     if( !oJP2Palette.exists() )
         return;
 
@@ -721,32 +553,29 @@ void JP2KAKRasterBand::ApplyPalette( jp2_palette oJP2Palette )
 
     if( oJP2Palette.get_num_luts() < 3 )
     {
-        CPLDebug( "JP2KAK", "JP2KAKRasterBand::ApplyPalette()\n"
-                  "Odd get_num_luts() value (%d)",
-                  oJP2Palette.get_num_luts() );
+        CPLDebug("JP2KAK", "JP2KAKRasterBand::ApplyPalette()\n"
+                 "Odd get_num_luts() value (%d)",
+                 oJP2Palette.get_num_luts());
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Fetch the lut entries.  Note that they are normalized in the    */
-/*      -0.5 to 0.5 range.                                              */
-/* -------------------------------------------------------------------- */
+    // Fetch lut entries.  They are normalized in the -0.5 to 0.5 range.                                              */
     const int nCount = oJP2Palette.get_num_entries();
 
-    float * const pafLUT =
-        static_cast<float *>( CPLCalloc(sizeof(float)*4, nCount) );
+    float *const pafLUT =
+        static_cast<float *>(CPLCalloc(sizeof(float) * 4, nCount));
 
-    const int nRed = 0;  // TODO(schwehr): Verify these constants are correct.
+    const int nRed = 0;
     const int nGreen = 1;
     const int nBlue = 2;
     const int nAlpha = 3;
     oJP2Palette.get_lut(nRed, pafLUT + 0);
     oJP2Palette.get_lut(nGreen, pafLUT + nCount);
-    oJP2Palette.get_lut(nBlue, pafLUT + nCount*2);
+    oJP2Palette.get_lut(nBlue, pafLUT + nCount * 2);
 
     if( oJP2Palette.get_num_luts() == 4 )
     {
-        oJP2Palette.get_lut( nAlpha, pafLUT + nCount * 3 );
+        oJP2Palette.get_lut(nAlpha, pafLUT + nCount * 3);
     }
     else
     {
@@ -756,26 +585,25 @@ void JP2KAKRasterBand::ApplyPalette( jp2_palette oJP2Palette )
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Apply to GDAL colortable.                                       */
-/* -------------------------------------------------------------------- */
-    for( int iColor=0; iColor < nCount; iColor++ )
-    {
-        GDALColorEntry sEntry = {
-            static_cast<short>(
-                MAX(0,MIN(255,pafLUT[iColor + nCount*0]*256+128))),
-            static_cast<short>(
-                MAX(0,MIN(255,pafLUT[iColor + nCount*1]*256+128))),
-            static_cast<short>(
-                MAX(0,MIN(255,pafLUT[iColor + nCount*2]*256+128))),
-            static_cast<short>(
-                MAX(0,MIN(255,pafLUT[iColor + nCount*3]*256+128)))
+    // Apply to GDAL colortable.
+    const int nRedOffset = nCount * nRed;
+    const int nGreenOffset = nCount * nGreen;
+    const int nBlueOffset = nCount * nBlue;
+    const int nAlphaOffset = nCount * nAlpha;
+
+    for( int iColor = 0; iColor < nCount; iColor++ )
+    {
+        const GDALColorEntry sEntry = {
+            GetColorValue(pafLUT, iColor + nRedOffset),
+            GetColorValue(pafLUT, iColor + nGreenOffset),
+            GetColorValue(pafLUT, iColor + nBlueOffset),
+            GetColorValue(pafLUT, iColor + nAlphaOffset)
         };
 
-        oCT.SetColorEntry( iColor, &sEntry );
+        oCT.SetColorEntry(iColor, &sEntry);
     }
 
-    CPLFree( pafLUT );
+    CPLFree(pafLUT);
 
     eInterp = GCI_PaletteIndex;
 }
@@ -784,11 +612,7 @@ void JP2KAKRasterBand::ApplyPalette( jp2_palette oJP2Palette )
 /*                       GetColorInterpretation()                       */
 /************************************************************************/
 
-GDALColorInterp JP2KAKRasterBand::GetColorInterpretation()
-
-{
-    return eInterp;
-}
+GDALColorInterp JP2KAKRasterBand::GetColorInterpretation() { return eInterp; }
 
 /************************************************************************/
 /*                           GetColorTable()                            */
@@ -820,10 +644,13 @@ JP2KAKDataset::JP2KAKDataset() :
     jpip_client(NULL),
     bPreferNPReads(false),
     poThreadEnv(NULL),
-    bCached(FALSE),  // TODO: bool.
+    bCached(false),
+    bResilient(false),
+    bFussy(false),
+    bUseYCC(false),
     bPromoteTo8Bit(false)
 {
-    poDriver = static_cast<GDALDriver *>( GDALGetDriverByName( "JP2KAK" ) );
+    poDriver = static_cast<GDALDriver *>(GDALGetDriverByName("JP2KAK"));
 }
 
 /************************************************************************/
@@ -858,7 +685,7 @@ JP2KAKDataset::~JP2KAKDataset()
 
     if( poThreadEnv != NULL )
     {
-        poThreadEnv->terminate(NULL,true);
+        poThreadEnv->terminate(NULL, true);
         poThreadEnv->destroy();
         delete poThreadEnv;
     }
@@ -875,29 +702,30 @@ CPLErr JP2KAKDataset::IBuildOverviews( const char *pszResampling,
                                        void *pProgressData )
 
 {
-/* -------------------------------------------------------------------- */
-/*      In order for building external overviews to work properly we    */
-/*      discard any concept of internal overviews when the user         */
-/*      first requests to build external overviews.                     */
-/* -------------------------------------------------------------------- */
+    // In order for building external overviews to work properly, we
+    // discard any concept of internal overviews when the user
+    // first requests to build external overviews.
     for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
     {
         JP2KAKRasterBand *poBand =
-            dynamic_cast<JP2KAKRasterBand *>( GetRasterBand( iBand+1 ) );
+            dynamic_cast<JP2KAKRasterBand *>(GetRasterBand(iBand + 1));
         if( poBand == NULL )
-            CPLError( CE_Fatal, CPLE_AppDefined, "Dynamic cast failed" );
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined, "Dynamic cast failed");
+            return CE_Failure;
+        }
         for( int i = 0; i < poBand->nOverviewCount; i++ )
             delete poBand->papoOverviewBand[i];
 
-        CPLFree( poBand->papoOverviewBand );
+        CPLFree(poBand->papoOverviewBand);
         poBand->papoOverviewBand = NULL;
         poBand->nOverviewCount = 0;
     }
 
-    return GDALPamDataset::IBuildOverviews( pszResampling,
-                                            nOverviews, panOverviewList,
-                                            nListBands, panBandList,
-                                            pfnProgress, pProgressData );
+    return GDALPamDataset::IBuildOverviews(pszResampling,
+                                           nOverviews, panOverviewList,
+                                           nListBands, panBandList,
+                                           pfnProgress, pProgressData);
 }
 
 /************************************************************************/
@@ -907,19 +735,17 @@ CPLErr JP2KAKDataset::IBuildOverviews( const char *pszResampling,
 void JP2KAKDataset::KakaduInitialize()
 
 {
-/* -------------------------------------------------------------------- */
-/*      Initialize Kakadu warning/error reporting subsystem.            */
-/* -------------------------------------------------------------------- */
-    if( !kakadu_initialized )
-    {
-        kakadu_initialized = true;
+    // Initialize Kakadu warning/error reporting subsystem.
+    if( kakadu_initialized )
+        return;
 
-        kdu_cpl_error_message oErrHandler( CE_Failure );
-        kdu_cpl_error_message oWarningHandler( CE_Warning );
+    kakadu_initialized = true;
 
-        kdu_customize_warnings(new kdu_cpl_error_message( CE_Warning ) );
-        kdu_customize_errors(new kdu_cpl_error_message( CE_Failure ) );
-    }
+    kdu_cpl_error_message oErrHandler(CE_Failure);
+    kdu_cpl_error_message oWarningHandler(CE_Warning);
+
+    kdu_customize_warnings(new kdu_cpl_error_message(CE_Warning));
+    kdu_customize_errors(new kdu_cpl_error_message(CE_Failure));
 }
 
 /************************************************************************/
@@ -929,10 +755,8 @@ void JP2KAKDataset::KakaduInitialize()
 int JP2KAKDataset::Identify( GDALOpenInfo * poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Check header                                                    */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < (int) sizeof(jp2_header) )
+    // Check header.
+    if( poOpenInfo->nHeaderBytes < static_cast<int>(sizeof(jp2_header)) )
     {
         if( (STARTS_WITH_CI(poOpenInfo->pszFilename, "http://")
              || STARTS_WITH_CI(poOpenInfo->pszFilename, "https://")
@@ -956,18 +780,18 @@ int JP2KAKDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*      extensions are supported for JPC files since the standard       */
 /*      prefix is so short (two bytes).                                 */
 /* -------------------------------------------------------------------- */
-    if( memcmp(poOpenInfo->pabyHeader,jp2_header,sizeof(jp2_header)) == 0 )
+    if( memcmp(poOpenInfo->pabyHeader, jp2_header, sizeof(jp2_header)) == 0 )
         return TRUE;
-    else if( memcmp( poOpenInfo->pabyHeader, jpc_header,
-                     sizeof(jpc_header) ) == 0 )
+    else if( memcmp(poOpenInfo->pabyHeader, jpc_header,
+                    sizeof(jpc_header)) == 0 )
     {
-        const char * const pszExtension =
-            CPLGetExtension( poOpenInfo->pszFilename );
+        const char *const pszExtension =
+            CPLGetExtension(poOpenInfo->pszFilename);
         if( EQUAL(pszExtension,"jpc")
-            || EQUAL(pszExtension,"j2k")
-            || EQUAL(pszExtension,"jp2")
-            || EQUAL(pszExtension,"jpx")
-            || EQUAL(pszExtension,"j2c") )
+            || EQUAL(pszExtension, "j2k")
+            || EQUAL(pszExtension, "jp2")
+            || EQUAL(pszExtension, "jpx")
+            || EQUAL(pszExtension, "j2c") )
            return TRUE;
 
         // We also want to handle jpc datastreams vis /vsisubfile.
@@ -985,54 +809,56 @@ int JP2KAKDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    if( !Identify( poOpenInfo ) )
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    // During fuzzing, do not use Identify to reject crazy content.
+    if( !Identify(poOpenInfo) )
         return NULL;
+#endif
 
     subfile_source *poRawInput = NULL;
     bool bIsJPIP = false;
     bool bIsSubfile = false;
     GByte *pabyHeader = NULL;
 
-    const bool bResilient = CPLTestBool(
-        CPLGetConfigOption( "JP2KAK_RESILIENT", "NO" ) );
+    const bool bResilient =
+        CPLTestBool(CPLGetConfigOption("JP2KAK_RESILIENT", "NO"));
 
-    /* Doesn't seem to bring any real performance gain on Linux */
-    const bool bBuffered = CPLTestBool(
-        CPLGetConfigOption( "JP2KAK_BUFFERED",
+    // Doesn't seem to bring any real performance gain on Linux.
+    const bool bBuffered = CPLTestBool(CPLGetConfigOption("JP2KAK_BUFFERED",
 #ifdef WIN32
-                            "YES"
+                                                          "YES"
 #else
-                            "NO"
+                                                          "NO"
 #endif
-                            ) );
+                                                          ));
 
-/* -------------------------------------------------------------------- */
-/*      Handle setting up datasource for JPIP.                          */
-/* -------------------------------------------------------------------- */
     KakaduInitialize();
 
-    const char *pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
+    // Handle setting up datasource for JPIP.
+    const char *pszExtension = CPLGetExtension(poOpenInfo->pszFilename);
     if( poOpenInfo->nHeaderBytes < 16 )
     {
         if( (STARTS_WITH_CI(poOpenInfo->pszFilename, "http://")
              || STARTS_WITH_CI(poOpenInfo->pszFilename, "https://")
              || STARTS_WITH_CI(poOpenInfo->pszFilename, "jpip://"))
-            && EQUAL(pszExtension,"jp2") )
+            && EQUAL(pszExtension, "jp2") )
         {
             bIsJPIP = true;
         }
         else if( STARTS_WITH_CI(poOpenInfo->pszFilename, "J2K_SUBFILE:") )
         {
-            static GByte abySubfileHeader[16] = { 0 };
+            // TODO(schwehr): Why was abySubfileHeader static in r6348?
+            GByte abySubfileHeader[16] = {};
 
             try
             {
                 poRawInput = new subfile_source;
-                poRawInput->open( poOpenInfo->pszFilename, bResilient, bBuffered );
-                poRawInput->seek( 0 );
+                poRawInput->open(poOpenInfo->pszFilename, bResilient,
+                                 bBuffered);
+                poRawInput->seek(0);
 
-                poRawInput->read( abySubfileHeader, 16 );
-                poRawInput->seek( 0 );
+                poRawInput->read(abySubfileHeader, 16);
+                poRawInput->seek(0);
             }
             catch( ... )
             {
@@ -1044,45 +870,41 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             bIsSubfile = true;
         }
         else
+        {
             return NULL;
+        }
     }
     else
     {
         pabyHeader = poOpenInfo->pabyHeader;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we think this should be access via vsil, then open it using  */
-/*      subfile_source.  We do this if it does not seem to open normally*/
-/*      or if we want to operate in resilient (sequential) mode.        */
-/* -------------------------------------------------------------------- */
+    // If we think this should be access via vsil, then open it using
+    // subfile_source.  We do this if it does not seem to open normally
+    // or if we want to operate in resilient (sequential) mode.
     VSIStatBuf sStat;
-    if( poRawInput == NULL
-        && !bIsJPIP
-        && (bBuffered || bResilient ||
-            VSIStat(poOpenInfo->pszFilename, &sStat) != 0) )
+    if( poRawInput == NULL && !bIsJPIP &&
+        (bBuffered || bResilient ||
+         VSIStat(poOpenInfo->pszFilename, &sStat) != 0) )
     {
         try
         {
             poRawInput = new subfile_source;
-            poRawInput->open( poOpenInfo->pszFilename, bResilient, bBuffered );
-            poRawInput->seek( 0 );
+            poRawInput->open(poOpenInfo->pszFilename, bResilient, bBuffered);
+            poRawInput->seek(0);
         }
         catch( ... )
         {
+            delete poRawInput;
             return NULL;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      If the header is a JP2 header, mark this as a JP2 dataset.      */
-/* -------------------------------------------------------------------- */
+    // If the header is a JP2 header, mark this as a JP2 dataset.
     if( pabyHeader && memcmp(pabyHeader, jp2_header, sizeof(jp2_header)) == 0 )
         pszExtension = "jp2";
 
-/* -------------------------------------------------------------------- */
-/*      Try to open the file in a manner depending on the extension.    */
-/* -------------------------------------------------------------------- */
+    // Try to open the file in a manner depending on the extension.
     kdu_compressed_source *poInput = NULL;
     kdu_client *jpip_client = NULL;
     jp2_palette oJP2Palette;
@@ -1095,52 +917,52 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
         if( bIsJPIP )
         {
 #ifdef USE_JPIP
-            char *pszWrk = CPLStrdup(strstr(poOpenInfo->pszFilename,"://")+3);
-            char *pszRequest = strstr(pszWrk,"/");
+            char *pszWrk =
+                CPLStrdup(strstr(poOpenInfo->pszFilename, "://") + 3);
+            char *pszRequest = strstr(pszWrk, "/");
 
             if( pszRequest == NULL )
             {
-                CPLDebug( "JP2KAK",
-                          "Failed to parse JPIP server and request." );
-                CPLFree( pszWrk );
+                CPLDebug("JP2KAK", "Failed to parse JPIP server and request.");
+                CPLFree(pszWrk);
                 return NULL;
             }
 
             *(pszRequest++) = '\0';
 
-            CPLDebug( "JP2KAK", "server=%s, request=%s",
-                      pszWrk, pszRequest );
+            CPLDebug("JP2KAK", "server=%s, request=%s", pszWrk, pszRequest);
 
-            CPLSleep( 15.0 );
+            CPLSleep(15.0);
             jpip_client = new kdu_client;
-            jpip_client->connect( pszWrk, NULL, pszRequest, "http-tcp",
-                                  "" );
+            jpip_client->connect(pszWrk, NULL, pszRequest, "http-tcp", "");
 
-            CPLDebug( "JP2KAK", "After connect()" );
+            CPLDebug("JP2KAK", "After connect()");
 
             bool bin0_complete = false;
 
-            while( jpip_client->get_databin_length(KDU_META_DATABIN,0,0,
+            while( jpip_client->get_databin_length(KDU_META_DATABIN, 0, 0,
                                                    &bin0_complete) <= 0
                    || !bin0_complete )
                 CPLSleep( 0.25 );
 
             family = new jp2_family_src;
-            family->open( jpip_client );
+            family->open(jpip_client);
 
             // TODO(schwehr): Check for memory leaks.
             jp2_source *jp2_src = new jp2_source;
-            jp2_src->open( family );
+            jp2_src->open(family);
             jp2_src->read_header();
 
             while( !jpip_client->is_idle() )
-                CPLSleep( 0.25 );
+                CPLSleep(0.25);
 
             if( jpip_client->is_alive() )
-                CPLDebug( "JP2KAK", "connect() seems to be complete." );
+            {
+                CPLDebug("JP2KAK", "connect() seems to be complete.");
+            }
             else
             {
-                CPLDebug( "JP2KAK", "connect() seems to have failed." );
+                CPLDebug("JP2KAK", "connect() seems to have failed.");
                 return NULL;
             }
 
@@ -1148,28 +970,27 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
             poInput = jp2_src;
 #else
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "JPIP Protocol not supported by GDAL with Kakadu 3.4 or on Unix." );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "JPIP Protocol not supported by GDAL with "
+                     "Kakadu 3.4 or on Unix.");
             return NULL;
 #endif
         }
-        else if( pszExtension != NULL
-                 && (EQUAL(pszExtension,"jp2") || EQUAL(pszExtension,"jpx")) )
+        else if( pszExtension != NULL &&
+                 (EQUAL(pszExtension, "jp2") || EQUAL(pszExtension, "jpx")) )
         {
-            jp2_source *jp2_src;
-
             family = new jp2_family_src;
             if( poRawInput != NULL )
-                family->open( poRawInput );
+                family->open(poRawInput);
             else
-                family->open( poOpenInfo->pszFilename, true );
-            jp2_src = new jp2_source;
-            if( !jp2_src->open( family ) ||
-                !jp2_src->read_header() )
+                family->open(poOpenInfo->pszFilename, true);
+            jp2_source *jp2_src = new jp2_source;
+            if( !jp2_src->open(family) || !jp2_src->read_header() )
             {
-                CPLDebug( "JP2KAK", "Cannot read JP2 boxes" );
+                CPLDebug("JP2KAK", "Cannot read JP2 boxes");
                 delete jp2_src;
                 delete family;
+                delete poRawInput;
                 return NULL;
             }
 
@@ -1179,17 +1000,17 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             oJP2Channels = jp2_src->access_channels();
 
             jp2_colour oColors = jp2_src->access_colour();
-            if( oColors.get_space() != JP2_sRGB_SPACE
-                && oColors.get_space() != JP2_sLUM_SPACE )
+            if( oColors.get_space() != JP2_sRGB_SPACE &&
+                oColors.get_space() != JP2_sLUM_SPACE )
             {
-                CPLDebug( "JP2KAK",
-                          "Unusual ColorSpace=%d, not further interpreted.",
-                          static_cast<int>( oColors.get_space() ) );
+                CPLDebug("JP2KAK",
+                         "Unusual ColorSpace=%d, not further interpreted.",
+                         static_cast<int>(oColors.get_space()));
             }
         }
         else if( poRawInput == NULL )
         {
-            poInput = new kdu_simple_file_source( poOpenInfo->pszFilename );
+            poInput = new kdu_simple_file_source(poOpenInfo->pszFilename);
         }
         else
         {
@@ -1199,13 +1020,14 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     catch( ... )
     {
-        CPLDebug( "JP2KAK", "Trapped Kakadu exception." );
+        CPLDebug("JP2KAK", "Trapped Kakadu exception.");
+        delete family;
+        delete poRawInput;
+        delete poInput;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
+    // Create a corresponding GDALDataset.
     JP2KAKDataset *poDS = NULL;
 
     try
@@ -1214,13 +1036,13 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
         poDS->poInput = poInput;
         poDS->poRawInput = poRawInput;
-        poDS->oCodeStream.create( poInput );
+        poDS->family = family;
+        poDS->oCodeStream.create(poInput);
         poDS->oCodeStream.set_persistent();
 
         poDS->bCached = bBuffered;
         poDS->bResilient = bResilient;
-        poDS->bFussy = CPLTestBool(
-            CPLGetConfigOption( "JP2KAK_FUSSY", "NO" ) );
+        poDS->bFussy = CPLTestBool(CPLGetConfigOption("JP2KAK_FUSSY", "NO"));
 
         if( poDS->bFussy )
             poDS->oCodeStream.set_fussy();
@@ -1229,20 +1051,14 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
         poDS->jpip_client = jpip_client;
 
-        poDS->family = family;
-
-/* -------------------------------------------------------------------- */
-/*      Get overall image size.                                         */
-/* -------------------------------------------------------------------- */
-        poDS->oCodeStream.get_dims( 0, poDS->dims );
+        // Get overall image size.
+        poDS->oCodeStream.get_dims(0, poDS->dims);
 
         poDS->nRasterXSize = poDS->dims.size.x;
         poDS->nRasterYSize = poDS->dims.size.y;
 
-/* -------------------------------------------------------------------- */
-/*      Ensure that all the components have the same dimensions.  If    */
-/*      not, just process the first dimension.                          */
-/* -------------------------------------------------------------------- */
+        // Ensure that all the components have the same dimensions.  If
+        // not, just process the first dimension.
         poDS->nBands = poDS->oCodeStream.get_num_components();
 
         if (poDS->nBands > 1 )
@@ -1255,21 +1071,20 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
 
                 if( dim_this_comp != poDS->dims )
                 {
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "Some components have mismatched dimensions, "
-                              "ignoring all but first." );
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Some components have mismatched dimensions, "
+                             "ignoring all but first.");
                     poDS->nBands = 1;
                     break;
                 }
             }
         }
 
-/* -------------------------------------------------------------------- */
-/*      Setup the thread environment.                                   */
-/* -------------------------------------------------------------------- */
-        int nNumThreads = atoi(CPLGetConfigOption("JP2KAK_THREADS","-1"));
+        // Setup the thread environment.
+
+        int nNumThreads = atoi(CPLGetConfigOption("JP2KAK_THREADS", "-1"));
         if( nNumThreads == -1 )
-            nNumThreads = kdu_get_num_processors()-1;
+            nNumThreads = kdu_get_num_processors() - 1;
 
         if( nNumThreads > 0 )
         {
@@ -1279,83 +1094,86 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             for( int iThread=0; iThread < nNumThreads; iThread++ )
             {
                 if( !poDS->poThreadEnv->add_thread() )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "JP2KAK_THREADS: Unable to create thread.");
                     break;
+                }
             }
-            CPLDebug( "JP2KAK", "Using %d threads.", nNumThreads );
+            CPLDebug("JP2KAK", "Using %d threads.", nNumThreads);
         }
         else
-            CPLDebug( "JP2KAK", "Operating in singlethreaded mode." );
+        {
+            CPLDebug("JP2KAK", "Operating in singlethreaded mode.");
+        }
 
-/* -------------------------------------------------------------------- */
-/*      Is this a file with poor internal navigation that will end      */
-/*      up using a great deal of memory if we use keep persistent       */
-/*      parsed information around?  (#3295)                             */
-/* -------------------------------------------------------------------- */
+        // Is this a file with poor internal navigation that will end
+        // up using a great deal of memory if we use keep persistent
+        // parsed information around?  (#3295)
         siz_params *siz = poDS->oCodeStream.access_siz();
         kdu_params *cod = siz->access_cluster(COD_params);
         bool use_precincts = false;
 
-        cod->get(Cuse_precincts,0,0,use_precincts);
+        cod->get(Cuse_precincts, 0, 0, use_precincts);
 
-        const char *pszPersist = CPLGetConfigOption( "JP2KAK_PERSIST", "AUTO");
-        if( EQUAL(pszPersist,"AUTO") )
+        const char *pszPersist = CPLGetConfigOption("JP2KAK_PERSIST", "AUTO");
+        if( EQUAL(pszPersist, "AUTO") )
         {
-            if( !use_precincts && !bIsJPIP
-                && (poDS->nRasterXSize * (double) poDS->nRasterYSize)
-                > 100000000.0 )
+            if( !use_precincts && !bIsJPIP &&
+                (poDS->nRasterXSize * static_cast<double>(poDS->nRasterYSize)) >
+                    100000000.0 )
                 poDS->bPreferNPReads = true;
         }
         else
+        {
             poDS->bPreferNPReads = !CPLTestBool(pszPersist);
+        }
 
-        CPLDebug( "JP2KAK", "Cuse_precincts=%d, PreferNonPersistentReads=%d",
-                  use_precincts ? 1 : 0, poDS->bPreferNPReads ? 1 : 0 );
+        CPLDebug("JP2KAK", "Cuse_precincts=%d, PreferNonPersistentReads=%d",
+                 use_precincts ? 1 : 0, poDS->bPreferNPReads ? 1 : 0);
 
-/* -------------------------------------------------------------------- */
-/*      Deduce some other info about the dataset.                       */
-/* -------------------------------------------------------------------- */
+        //  Deduce some other info about the dataset.
         int order = 0;
 
         cod->get(Corder, 0, 0, order);
 
+        // TODO(schwehr): Why not a switch statement?
         if( order == Corder_LRCP )
         {
-            CPLDebug( "JP2KAK", "order=LRCP" );
-            poDS->SetMetadataItem("Corder","LRCP");
+            CPLDebug("JP2KAK", "order=LRCP");
+            poDS->SetMetadataItem("Corder", "LRCP");
         }
         else if( order == Corder_RLCP )
         {
-            CPLDebug( "JP2KAK", "order=RLCP" );
-            poDS->SetMetadataItem("Corder","RLCP");
+            CPLDebug("JP2KAK", "order=RLCP");
+            poDS->SetMetadataItem("Corder", "RLCP");
         }
         else if( order == Corder_RPCL )
         {
-            CPLDebug( "JP2KAK", "order=RPCL" );
-            poDS->SetMetadataItem("Corder","RPCL");
+            CPLDebug("JP2KAK", "order=RPCL");
+            poDS->SetMetadataItem("Corder", "RPCL");
         }
         else if( order == Corder_PCRL )
         {
-            CPLDebug( "JP2KAK", "order=PCRL" );
-            poDS->SetMetadataItem("Corder","PCRL");
+            CPLDebug("JP2KAK", "order=PCRL");
+            poDS->SetMetadataItem("Corder", "PCRL");
         }
         else if( order == Corder_CPRL )
         {
-            CPLDebug( "JP2KAK", "order=CPRL" );
-            poDS->SetMetadataItem("Corder","CPRL");
+            CPLDebug("JP2KAK", "order=CPRL");
+            poDS->SetMetadataItem("Corder", "CPRL");
         }
         else
         {
-            CPLDebug( "JP2KAK", "order=%d, not recognized.", order );
+            CPLDebug("JP2KAK", "order=%d, not recognized.", order);
         }
 
         poDS->bUseYCC = false;
         cod->get(Cycc, 0, 0, poDS->bUseYCC);
         if( poDS->bUseYCC )
-            CPLDebug( "JP2KAK", "ycc=true" );
+            CPLDebug("JP2KAK", "ycc=true");
 
-/* -------------------------------------------------------------------- */
-/*      find out how many resolutions levels are available.             */
-/* -------------------------------------------------------------------- */
+        // Find out how many resolutions levels are available.
         kdu_dims tile_indices;
         poDS->oCodeStream.get_valid_tiles(tile_indices);
 
@@ -1363,30 +1181,27 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->nResCount = tile.access_component(0).get_num_resolutions();
         tile.close();
 
-        CPLDebug( "JP2KAK", "nResCount=%d", poDS->nResCount );
-
-/* -------------------------------------------------------------------- */
-/*      Should we promote alpha channel to 8 bits ?                     */
-/* -------------------------------------------------------------------- */
-        poDS->bPromoteTo8Bit = (poDS->nBands == 4 &&
-                                poDS->oCodeStream.get_bit_depth(0) == 8 &&
-                                poDS->oCodeStream.get_bit_depth(1) == 8 &&
-                                poDS->oCodeStream.get_bit_depth(2) == 8 &&
-                                poDS->oCodeStream.get_bit_depth(3) == 1 &&
-                                CSLFetchBoolean(poOpenInfo->papszOpenOptions,
-                                                "1BIT_ALPHA_PROMOTION", TRUE));
+        CPLDebug("JP2KAK", "nResCount=%d", poDS->nResCount);
+
+        // Should we promote alpha channel to 8 bits?
+        poDS->bPromoteTo8Bit =
+            poDS->nBands == 4 &&
+            poDS->oCodeStream.get_bit_depth(0) == 8 &&
+            poDS->oCodeStream.get_bit_depth(1) == 8 &&
+            poDS->oCodeStream.get_bit_depth(2) == 8 &&
+            poDS->oCodeStream.get_bit_depth(3) == 1 &&
+            CPLFetchBool(poOpenInfo->papszOpenOptions,
+                         "1BIT_ALPHA_PROMOTION", true);
         if( poDS->bPromoteTo8Bit )
-            CPLDebug( "JP2KAK",
-                      "Fourth (alpha) band is promoted from 1 bit to 8 bit");
+            CPLDebug("JP2KAK",
+                     "Fourth (alpha) band is promoted from 1 bit to 8 bit");
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
+        // Create band information objects.
         for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
         {
-            JP2KAKRasterBand *poBand =
-                new JP2KAKRasterBand(iBand,0,poDS->oCodeStream,poDS->nResCount,
-                                     jpip_client, oJP2Channels, poDS );
+            JP2KAKRasterBand *poBand = new JP2KAKRasterBand(
+                iBand, 0, poDS->oCodeStream, poDS->nResCount, jpip_client,
+                oJP2Channels, poDS);
 
             if( iBand == 1 && oJP2Palette.exists() )
                 poBand->ApplyPalette( oJP2Palette );
@@ -1394,64 +1209,53 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->SetBand( iBand, poBand );
         }
 
-/* -------------------------------------------------------------------- */
-/*      Look for supporting coordinate system information.              */
-/* -------------------------------------------------------------------- */
+        // Look for supporting coordinate system information.
         if( poOpenInfo->nHeaderBytes != 0 )
         {
             poDS->LoadJP2Metadata(poOpenInfo);
         }
 
-/* -------------------------------------------------------------------- */
-/*      Establish our corresponding physical file.                      */
-/* -------------------------------------------------------------------- */
+        // Establish our corresponding physical file.
         CPLString osPhysicalFilename = poOpenInfo->pszFilename;
 
         if( bIsSubfile ||
             STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsisubfile/") )
         {
-            if( strstr(poOpenInfo->pszFilename,",") != NULL )
-                osPhysicalFilename = strstr(poOpenInfo->pszFilename,",") + 1;
+            const char *comma = strstr(poOpenInfo->pszFilename, ",");
+            if( comma != NULL )
+                osPhysicalFilename = comma + 1;
         }
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
-        poDS->SetDescription( poOpenInfo->pszFilename );
+        poDS->SetDescription(poOpenInfo->pszFilename);
         if( !bIsSubfile )
             poDS->TryLoadXML();
         else
             poDS->nPamFlags |= GPF_NOSAVE;
 
-/* -------------------------------------------------------------------- */
-/*      Check for external overviews.                                   */
-/* -------------------------------------------------------------------- */
-        poDS->oOvManager.Initialize( poDS, osPhysicalFilename );
+        // Check for external overviews.
+        poDS->oOvManager.Initialize(poDS, osPhysicalFilename);
 
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
+        // Confirm the requested access is supported.
         if( poOpenInfo->eAccess == GA_Update )
         {
             delete poDS;
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "The JP2KAK driver does not support "
-                      "update access to existing"
-                      " datasets.\n" );
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "The JP2KAK driver does not support "
+                     "update access to existing datasets.");
             return NULL;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Vector layers                                                   */
-/* -------------------------------------------------------------------- */
+        // Vector layers.
         if( poOpenInfo->nOpenFlags & GDAL_OF_VECTOR )
         {
-            poDS->LoadVectorLayers(
-                CSLFetchBoolean( poOpenInfo->papszOpenOptions,
-                                 "OPEN_REMOTE_GML", FALSE ) );
+            poDS->LoadVectorLayers(CPLFetchBool(poOpenInfo->papszOpenOptions,
+                                                "OPEN_REMOTE_GML", false));
 
             // If file opened in vector-only mode and there's no vector,
-            // return
+            // return.
             if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) == 0 &&
                 poDS->GetLayerCount() == 0 )
             {
@@ -1460,15 +1264,11 @@ GDALDataset *JP2KAKDataset::Open( GDALOpenInfo * poOpenInfo )
             }
         }
 
-        return( poDS );
+        return poDS;
     }
-
-/* -------------------------------------------------------------------- */
-/*      Catch all fatal kakadu errors and cleanup a bit.                */
-/* -------------------------------------------------------------------- */
     catch( ... )
     {
-        CPLDebug( "JP2KAK", "JP2KAKDataset::Open() - caught exception." );
+        CPLDebug("JP2KAK", "JP2KAKDataset::Open() - caught exception.");
         if( poDS != NULL )
             delete poDS;
 
@@ -1491,17 +1291,14 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
                                GDALRasterIOExtraArg* psExtraArg)
 
 {
+    CPLAssert(eBufType == GDT_Byte || eBufType == GDT_Int16 ||
+              eBufType == GDT_UInt16);
+
     kdu_codestream *poCodeStream = &oCodeStream;
     const char *pszPersistency = "";
 
-    CPLAssert( eBufType == GDT_Byte
-               || eBufType == GDT_Int16
-               || eBufType == GDT_UInt16 );
-
-/* -------------------------------------------------------------------- */
-/*      Do we want to do this non-persistently?  If so, we need to      */
-/*      open the file, and establish a local codestream.                */
-/* -------------------------------------------------------------------- */
+    // Do we want to do this non-persistently?  If so, we need to
+    // open the file, and establish a local codestream.
     subfile_source subfile_src;
     jp2_source wrk_jp2_src;
     jp2_family_src wrk_family;
@@ -1509,19 +1306,19 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
 
     if( bPreferNPReads )
     {
-        subfile_src.open( GetDescription(), bResilient, bCached );
+        subfile_src.open(GetDescription(), bResilient, bCached);
 
         if( family != NULL )
         {
-            wrk_family.open( &subfile_src );
-            wrk_jp2_src.open( &wrk_family );
+            wrk_family.open(&subfile_src);
+            wrk_jp2_src.open(&wrk_family);
             wrk_jp2_src.read_header();
 
-            oWCodeStream.create( &wrk_jp2_src );
+            oWCodeStream.create(&wrk_jp2_src);
         }
         else
         {
-            oWCodeStream.create( &subfile_src );
+            oWCodeStream.create(&subfile_src);
         }
 
         if( bFussy )
@@ -1534,68 +1331,58 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
         pszPersistency = "(non-persistent)";
     }
 
-/* -------------------------------------------------------------------- */
-/*      Select optimal resolution level.                                */
-/* -------------------------------------------------------------------- */
+    // Select optimal resolution level.
     int nDiscardLevels = 0;
     int nResMult = 1;
 
-    while( nDiscardLevels < nResCount - 1
-           && nBufXSize * nResMult * 2 < nXSize * 1.01
-           && nBufYSize * nResMult * 2 < nYSize * 1.01 )
+    while( nDiscardLevels < nResCount - 1 &&
+           nBufXSize * nResMult * 2 < nXSize * 1.01 &&
+           nBufYSize * nResMult * 2 < nYSize * 1.01 )
     {
         nDiscardLevels++;
         nResMult *= 2;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Prepare component indices list.                                 */
-/* -------------------------------------------------------------------- */
+    // Prepare component indices list.
     CPLErr eErr = CE_None;
 
-    int *component_indices =
-        static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
-    int *stripe_heights =
-        static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
-    int *sample_offsets =
-        static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
-    int *sample_gaps =
-        static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
-    int *row_gaps = static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
-    int *precisions = static_cast<int *>( CPLMalloc(sizeof(int) * nBandCount) );
-    bool *is_signed =
-        static_cast<bool *>( CPLMalloc(sizeof(bool) * nBandCount) );
+    const size_t nBandSize = sizeof(int) * nBandCount;
+    int *component_indices = static_cast<int *>(CPLMalloc(nBandSize));
+    int *stripe_heights = static_cast<int *>(CPLMalloc(nBandSize));
+    int *sample_offsets = static_cast<int *>(CPLMalloc(nBandSize));
+    int *sample_gaps = static_cast<int *>(CPLMalloc(nBandSize));
+    int *row_gaps = static_cast<int *>(CPLMalloc(nBandSize));
+    int *precisions = static_cast<int *>(CPLMalloc(nBandSize));
+    bool *is_signed = static_cast<bool *>(CPLMalloc(nBandSize));
 
     for( int i = 0; i < nBandCount; i++ )
         component_indices[i] = panBandMap[i] - 1;
 
-/* -------------------------------------------------------------------- */
-/*      Setup a ROI matching the block requested, and select desired    */
-/*      bands (components).                                             */
-/* -------------------------------------------------------------------- */
+    // Setup a ROI matching the block requested, and select desired
+    // bands (components).
     try
     {
+        poCodeStream->apply_input_restrictions(0, 0, nDiscardLevels, 0, NULL);
         kdu_dims l_dims;
-        poCodeStream->apply_input_restrictions( 0, 0, nDiscardLevels, 0, NULL );
-        poCodeStream->get_dims( 0, l_dims );
-        int nOvrXSize = l_dims.size.x;
-        int nOvrYSize = l_dims.size.y;
-
-        l_dims.pos.x = l_dims.pos.x + nXOff/nResMult;
-        l_dims.pos.y = l_dims.pos.y + nYOff/nResMult;
-        l_dims.size.x = nXSize/nResMult;
-        l_dims.size.y = nYSize/nResMult;
-
-        // Check if rounding helps detecting when data is being requested exactly
-        // at the current resolution
+        poCodeStream->get_dims(0, l_dims);
+        const int nOvrXSize = l_dims.size.x;
+        const int nOvrYSize = l_dims.size.y;
+
+        l_dims.pos.x = l_dims.pos.x + nXOff / nResMult;
+        l_dims.pos.y = l_dims.pos.y + nYOff / nResMult;
+        l_dims.size.x = nXSize / nResMult;
+        l_dims.size.y = nYSize / nResMult;
+
+        // Check if rounding helps detecting when data is being requested
+        // exactly at the current resolution.
         if( nBufXSize != l_dims.size.x &&
-            static_cast<int>(0.5 + static_cast<double>(nXSize)/nResMult)
+            static_cast<int>(0.5 + static_cast<double>(nXSize) / nResMult)
             == nBufXSize )
         {
             l_dims.size.x = nBufXSize;
         }
         if( nBufYSize != l_dims.size.y &&
-            static_cast<int>(0.5 + static_cast<double>(nYSize)/nResMult)
+            static_cast<int>(0.5 + static_cast<double>(nYSize) / nResMult)
             == nBufYSize )
         {
             l_dims.size.y = nBufYSize;
@@ -1607,23 +1394,22 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
 
         kdu_dims l_dims_roi;
 
-        poCodeStream->map_region( 0, l_dims, l_dims_roi );
-        poCodeStream->apply_input_restrictions( nBandCount, component_indices,
-                                              nDiscardLevels, 0, &l_dims_roi,
-                                              KDU_WANT_OUTPUT_COMPONENTS);
+        poCodeStream->map_region(0, l_dims, l_dims_roi);
+        poCodeStream->apply_input_restrictions(nBandCount, component_indices,
+                                               nDiscardLevels, 0, &l_dims_roi,
+                                               KDU_WANT_OUTPUT_COMPONENTS);
 
-/* -------------------------------------------------------------------- */
-/*      Special case where the data is being requested exactly at       */
-/*      this resolution.  Avoid any extra sampling pass.                */
-/* -------------------------------------------------------------------- */
+        // Special case where the data is being requested exactly at
+        // this resolution.  Avoid any extra sampling pass.
         if( nBufXSize == l_dims.size.x && nBufYSize == l_dims.size.y )
         {
             kdu_stripe_decompressor decompressor;
-            decompressor.start(*poCodeStream,false,false,poThreadEnv);
+            decompressor.start(*poCodeStream, false, false, poThreadEnv);
 
-            CPLDebug( "JP2KAK", "DirectRasterIO() for %d,%d,%d,%d -> %dx%d (no intermediate) %s",
-                      nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
-                      pszPersistency );
+            CPLDebug("JP2KAK", "DirectRasterIO() for %d,%d,%d,%d -> %dx%d "
+                     "(no intermediate) %s",
+                     nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
+                     pszPersistency);
 
             for( int i = 0; i < nBandCount; i++ )
             {
@@ -1657,40 +1443,36 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
                       precisions[i] = 16;
                     }*/
                 }
-
             }
 
             if( eBufType == GDT_Byte )
-                decompressor.pull_stripe( (kdu_byte *) pData, stripe_heights,
-                                          sample_offsets, sample_gaps, row_gaps,
-                                          precisions );
+                decompressor.pull_stripe(
+                    static_cast<kdu_byte *>(pData), stripe_heights,
+                    sample_offsets, sample_gaps, row_gaps,
+                    precisions);
             else
-                decompressor.pull_stripe( (kdu_int16 *) pData, stripe_heights,
-                                          sample_offsets, sample_gaps,row_gaps,
-                                          precisions, is_signed );
+                decompressor.pull_stripe(
+                    static_cast<kdu_int16 *>(pData), stripe_heights,
+                    sample_offsets, sample_gaps, row_gaps,
+                    precisions, is_signed);
             decompressor.finish();
         }
-
-/* -------------------------------------------------------------------- */
-/*      More general case - first pull into working buffer.             */
-/* -------------------------------------------------------------------- */
         else
         {
-            const int nDataTypeSize = GDALGetDataTypeSize(eBufType) / 8;
-            GByte *pabyIntermediate = static_cast<GByte *>(
-                VSI_MALLOC3_VERBOSE( l_dims.size.x, l_dims.size.y,
-                                     nDataTypeSize*nBandCount ) );
+            // More general case - first pull into working buffer.
+
+            const int nDataTypeSize = GDALGetDataTypeSizeBytes(eBufType);
+            GByte *pabyIntermediate = static_cast<GByte *>(VSI_MALLOC3_VERBOSE(
+                l_dims.size.x, l_dims.size.y, nDataTypeSize * nBandCount));
             if( pabyIntermediate == NULL )
             {
                 return CE_Failure;
             }
 
-            CPLDebug( "JP2KAK",
-                      "DirectRasterIO() for %d,%d,%d,%d -> %dx%d -> %dx%d %s",
-                      nXOff, nYOff, nXSize, nYSize,
-                      l_dims.size.x, l_dims.size.y,
-                      nBufXSize, nBufYSize,
-                      pszPersistency );
+            CPLDebug("JP2KAK",
+                     "DirectRasterIO() for %d,%d,%d,%d -> %dx%d -> %dx%d %s",
+                     nXOff, nYOff, nXSize, nYSize, l_dims.size.x, l_dims.size.y,
+                     nBufXSize, nBufYSize, pszPersistency);
 
             kdu_stripe_decompressor decompressor;
             decompressor.start(*poCodeStream, false, false, poThreadEnv);
@@ -1702,52 +1484,45 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
 
                 if( eBufType == GDT_Int16 || eBufType == GDT_UInt16 )
                 {
-                    if( eBufType == GDT_Int16 )
-                        is_signed[i] = true;
-                    else
-                        is_signed[i] = false;
+                    is_signed[i] = eBufType == GDT_Int16;
                 }
             }
 
             if( eBufType == GDT_Byte )
                 decompressor.pull_stripe(
-                    reinterpret_cast<kdu_byte *>( pabyIntermediate ),
-                    stripe_heights, NULL, NULL, NULL,
-                    precisions );
+                    reinterpret_cast<kdu_byte *>(pabyIntermediate),
+                    stripe_heights, NULL, NULL, NULL, precisions);
             else
                 decompressor.pull_stripe(
-                    reinterpret_cast<kdu_int16 *>( pabyIntermediate ),
-                    stripe_heights, NULL, NULL, NULL,
-                    precisions, is_signed );
+                    reinterpret_cast<kdu_int16 *>(pabyIntermediate),
+                    stripe_heights, NULL, NULL, NULL, precisions, is_signed);
 
             decompressor.finish();
 
             if( psExtraArg->eResampleAlg == GRIORA_NearestNeighbour )
             {
-/* -------------------------------------------------------------------- */
-/*      Then resample (normally downsample) from the intermediate       */
-/*      buffer into the final buffer in the desired output layout.      */
-/* -------------------------------------------------------------------- */
+                // Then resample (normally downsample) from the intermediate
+                // buffer into the final buffer in the desired output layout.
                 const double dfYRatio =
-                    l_dims.size.y / static_cast<double>( nBufYSize );
+                    l_dims.size.y / static_cast<double>(nBufYSize);
                 const double dfXRatio =
-                    l_dims.size.x / static_cast<double>( nBufXSize );
+                    l_dims.size.x / static_cast<double>(nBufXSize);
 
                 for( int iY = 0; iY < nBufYSize; iY++ )
                 {
-                    int iSrcY = (int) floor( (iY + 0.5) * dfYRatio );
-
-                    iSrcY = MIN(iSrcY, l_dims.size.y-1);
+                    const int iSrcY = std::min(
+                        static_cast<int>(floor((iY + 0.5) * dfYRatio)),
+                        l_dims.size.y - 1);
 
                     for( int iX = 0; iX < nBufXSize; iX++ )
                     {
-                        int iSrcX =
-                            static_cast<int>( floor( (iX + 0.5) * dfXRatio ) );
-
-                        iSrcX = MIN(iSrcX, l_dims.size.x-1);
+                        const int iSrcX = std::min(
+                            static_cast<int>(floor((iX + 0.5) * dfXRatio)),
+                            l_dims.size.x - 1);
 
                         for( int i = 0; i < nBandCount; i++ )
                         {
+                            // TODO(schwehr): Cleanup this block.
                             if( eBufType == GDT_Byte )
                                 ((GByte *) pData)[iX*nPixelSpace
                                                 + iY*nLineSpace
@@ -1770,7 +1545,7 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
             }
             else
             {
-                /* Create a MEM dataset that wraps the input buffer */
+                // Create a MEM dataset that wraps the input buffer.
                 GDALDataset* poMEMDS = MEMDataset::Create( "", l_dims.size.x,
                                                            l_dims.size.y, 0,
                                                            eBufType, NULL);
@@ -1784,7 +1559,7 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
                         szBuffer, pabyIntermediate + i * nDataTypeSize,
                         sizeof(szBuffer) );
                     szBuffer[nRet] = 0;
-                    char** papszOptions =
+                    char **papszOptions =
                         CSLSetNameValue(NULL, "DATAPOINTER", szBuffer);
 
                     papszOptions = CSLSetNameValue(papszOptions, "PIXELOFFSET",
@@ -1801,12 +1576,12 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
                     poMEMDS->AddBand(eBufType, papszOptions);
                     CSLDestroy(papszOptions);
 
-                    const char* pszNBITS = GetRasterBand(i+1)->
-                        GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" );
+                    const char *pszNBITS =
+                        GetRasterBand(i + 1)
+                            ->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
                     if( pszNBITS )
-                        poMEMDS->GetRasterBand(i+1)->
-                            SetMetadataItem( "NBITS", pszNBITS,
-                                             "IMAGE_STRUCTURE");
+                        poMEMDS->GetRasterBand(i + 1)->SetMetadataItem(
+                            "NBITS", pszNBITS, "IMAGE_STRUCTURE");
                 }
 
                 GDALRasterIOExtraArg sExtraArgTmp;
@@ -1825,28 +1600,25 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
                 GDALClose(poMEMDS);
             }
 
-            CPLFree( pabyIntermediate );
+            CPLFree(pabyIntermediate);
         }
     }
-/* -------------------------------------------------------------------- */
-/*      Catch internal Kakadu errors.                                   */
-/* -------------------------------------------------------------------- */
     catch( ... )
     {
+        // Catch internal Kakadu errors.
         eErr = CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      1-bit alpha promotion.                                          */
-/* -------------------------------------------------------------------- */
+    // 1-bit alpha promotion.
     if( nBandCount == 4 && bPromoteTo8Bit )
     {
-        for( int j=0; j < nBufYSize; j++ )
+        for( int j = 0; j < nBufYSize; j++ )
         {
-            for( int i=0; i < nBufXSize; i++ )
+            for( int i = 0; i < nBufXSize; i++ )
             {
-                static_cast<GByte*>(
-                    pData)[j*nLineSpace+i*nPixelSpace+3*nBandSpace] *= 255;
+                static_cast<GByte *>(
+                    pData)[j * nLineSpace + i * nPixelSpace + 3 * nBandSpace] *=
+                    255;
             }
         }
     }
@@ -1861,13 +1633,13 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
         subfile_src.close();
     }
 
-    CPLFree( component_indices );
-    CPLFree( stripe_heights );
-    CPLFree( sample_offsets );
-    CPLFree( sample_gaps );
-    CPLFree( row_gaps );
-    CPLFree( precisions );
-    CPLFree( is_signed);
+    CPLFree(component_indices);
+    CPLFree(stripe_heights);
+    CPLFree(sample_offsets);
+    CPLFree(sample_gaps);
+    CPLFree(row_gaps);
+    CPLFree(precisions);
+    CPLFree(is_signed);
 
     return eErr;
 }
@@ -1879,61 +1651,55 @@ JP2KAKDataset::DirectRasterIO( GDALRWFlag /* eRWFlag */,
 /*      (FALSE) for a given request configuration and environment.      */
 /************************************************************************/
 
-int
+bool
 JP2KAKDataset::TestUseBlockIO( int nXOff, int nYOff, int nXSize, int nYSize,
                                int nBufXSize, int nBufYSize,
                                GDALDataType eDataType,
                                int nBandCount, int *panBandList )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Due to limitations in DirectRasterIO() we can only handle       */
-/*      8bit and with no duplicates in the band list.                   */
-/* -------------------------------------------------------------------- */
+    // Due to limitations in DirectRasterIO() we can only handle
+    // 8bit and with no duplicates in the band list.
     if( eDataType != GetRasterBand(1)->GetRasterDataType()
         || ( eDataType != GDT_Byte
              && eDataType != GDT_Int16
              && eDataType != GDT_UInt16 ) )
-        return TRUE;
+        return true;
 
     for( int i = 0; i < nBandCount; i++ )
     {
-        for( int j = i+1; j < nBandCount; j++ )
+        for( int j = i + 1; j < nBandCount; j++ )
             if( panBandList[j] == panBandList[i] )
-                return TRUE;
+                return true;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we have external overviews built, and they could be used     */
-/*      to satisfy this request, we will avoid DirectRasterIO()         */
-/*      which would ignore them.                                        */
-/* -------------------------------------------------------------------- */
+    // If we have external overviews built and they could be used to satisfy
+    // this request, we will avoid DirectRasterIO() which would ignore them.
     if( GetRasterCount() == 0 )
-        return TRUE;
+        return true;
 
     JP2KAKRasterBand *poWrkBand =
-        dynamic_cast<JP2KAKRasterBand *>( GetRasterBand(1) );
+        dynamic_cast<JP2KAKRasterBand *>(GetRasterBand(1));
     if( poWrkBand == NULL )
+    {
         CPLError( CE_Fatal, CPLE_AppDefined, "Dynamic cast failed" );
+        return false;
+    }
     if( poWrkBand->HasExternalOverviews() )
     {
-        int nXOff2=nXOff;
-        int nYOff2=nYOff;
-        int nXSize2=nXSize;
-        int nYSize2=nYSize;
+        int nXOff2 = nXOff;
+        int nYOff2 = nYOff;
+        int nXSize2 = nXSize;
+        int nYSize2 = nYSize;
 
         const int nOverview =
-            GDALBandGetBestOverviewLevel2( poWrkBand,
-                                           nXOff2, nYOff2, nXSize2, nYSize2,
-                                           nBufXSize, nBufYSize, NULL );
-        if (nOverview >= 0 )
-            return TRUE;
+            GDALBandGetBestOverviewLevel2(poWrkBand, nXOff2, nYOff2, nXSize2,
+                                          nYSize2, nBufXSize, nBufYSize, NULL);
+        if( nOverview >= 0 )
+            return true;
     }
 
-/* -------------------------------------------------------------------- */
-/*      The rest of the rules are io strategy stuff, and use            */
-/*      configuration checks.                                           */
-/* -------------------------------------------------------------------- */
+    // The rest of the rules are io strategy stuff and configuration checks.
     bool bUseBlockedIO = bForceCachedIO;
 
     if( nYSize == 1 || nXSize * static_cast<double>(nYSize) < 100.0 )
@@ -1942,9 +1708,9 @@ JP2KAKDataset::TestUseBlockIO( int nXOff, int nYOff, int nXSize, int nYSize,
     if( nBufYSize == 1 || nBufXSize * static_cast<double>(nBufYSize) < 100.0 )
         bUseBlockedIO = true;
 
-    if( strlen(CPLGetConfigOption( "GDAL_ONE_BIG_READ", "")) > 0 )
+    if( strlen(CPLGetConfigOption("GDAL_ONE_BIG_READ", "")) > 0 )
         bUseBlockedIO =
-            !CPLTestBool(CPLGetConfigOption( "GDAL_ONE_BIG_READ", ""));
+            !CPLTestBool(CPLGetConfigOption("GDAL_ONE_BIG_READ", ""));
 
     return bUseBlockedIO;
 }
@@ -1963,11 +1729,9 @@ CPLErr JP2KAKDataset::IRasterIO( GDALRWFlag eRWFlag,
                                  GDALRasterIOExtraArg* psExtraArg)
 
 {
-/* -------------------------------------------------------------------- */
-/*      We need various criteria to skip out to block based methods.    */
-/* -------------------------------------------------------------------- */
-    if( TestUseBlockIO( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
-                        eBufType, nBandCount, panBandMap ) )
+    // We need various criteria to skip out to block based methods.
+    if( TestUseBlockIO(nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
+                       eBufType, nBandCount, panBandMap) )
         return GDALPamDataset::IRasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize,
             pData, nBufXSize, nBufYSize, eBufType,
@@ -1993,16 +1757,14 @@ static void JP2KAKWriteBox( jp2_target *jp2_out, GDALJP2Box *poBox )
         return;
 
     GUInt32 nBoxType = 0;
-    memcpy( &nBoxType, poBox->GetType(), sizeof(nBoxType) );
-    CPL_MSBPTR32( &nBoxType );
+    memcpy(&nBoxType, poBox->GetType(), sizeof(nBoxType));
+    CPL_MSBPTR32(&nBoxType);
 
-/* -------------------------------------------------------------------- */
-/*      Write to a box on the JP2 file.                                 */
-/* -------------------------------------------------------------------- */
-    jp2_out->open_next( nBoxType );
+    // Write to a box on the JP2 file.
+    jp2_out->open_next(nBoxType);
 
-    jp2_out->write( const_cast<kdu_byte *>( poBox->GetWritableData() ),
-                    static_cast<int>( poBox->GetDataLength() ) );
+    jp2_out->write(const_cast<kdu_byte *>(poBox->GetWritableData()),
+                   static_cast<int>(poBox->GetDataLength()));
 
     jp2_out->close();
 
@@ -2013,7 +1775,7 @@ static void JP2KAKWriteBox( jp2_target *jp2_out, GDALJP2Box *poBox )
 /*                     JP2KAKCreateCopy_WriteTile()                     */
 /************************************************************************/
 
-static int
+static bool
 JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                             kdu_roi_image *poROIImage,
                             int nXOff, int nYOff, int nXSize, int nYSize,
@@ -2024,40 +1786,38 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                             bool bComseg )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Create one big tile, and a compressing engine, and line         */
-/*      buffer for each component.                                      */
-/* -------------------------------------------------------------------- */
-    int num_components = oTile.get_num_components();
+    // Create one big tile, a compressing engine, and a line buffer for each
+    // component.
+    const int num_components = oTile.get_num_components();
     kdu_push_ifc *engines = new kdu_push_ifc[num_components];
     kdu_line_buf *lines = new kdu_line_buf[num_components];
     kdu_sample_allocator allocator;
 
     // Ticket #4050 patch: Use a 32 bits kdu_line_buf for GDT_UInt16 reversible
     // compression.
-    // TODO: test for GDT_UInt16?
+    // TODO: Test for GDT_UInt16?
     bool bUseShorts = bReversible;
-    if( (eType == GDT_UInt16) && bReversible )
+    if( eType == GDT_UInt16 && bReversible )
         bUseShorts = false;
 
-    for( int c=0; c < num_components; c++ )
+    for( int c = 0; c < num_components; c++ )
     {
         kdu_resolution res = oTile.access_component(c).access_resolution();
         kdu_roi_node *roi_node = NULL;
 
         if( poROIImage != NULL )
         {
-            kdu_dims  dims;
+            kdu_dims dims;
 
             res.get_dims(dims);
-            roi_node = poROIImage->acquire_node(c,dims);
+            roi_node = poROIImage->acquire_node(c, dims);
         }
 #if KDU_MAJOR_VERSION >= 7
-        lines[c].pre_create(&allocator,nXSize,bReversible,bUseShorts,0,0);
+        lines[c].pre_create(&allocator, nXSize, bReversible, bUseShorts, 0, 0);
 #else
-        lines[c].pre_create(&allocator,nXSize,bReversible,bUseShorts);
+        lines[c].pre_create(&allocator, nXSize, bReversible, bUseShorts);
 #endif
-        engines[c] = kdu_analysis(res,&allocator,bUseShorts,1.0F,roi_node);
+        engines[c] = kdu_analysis(res, &allocator, bUseShorts, 1.0F, roi_node);
     }
 
     try
@@ -2068,40 +1828,38 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
         allocator.finalize();
 #endif
 
-        for( int c=0; c < num_components; c++ )
+        for( int c = 0; c < num_components; c++ )
             lines[c].create();
     }
     catch( ... )
     {
         // TODO(schwehr): Should this block do any cleanup?
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "allocate.finalize() failed, likely out of memory for "
-                  "compression information." );
-        return FALSE;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "allocate.finalize() failed, likely out of memory for "
+                 "compression information.");
+        return false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write whole image.  Write 1024 lines of each component, then    */
-/*      go back to the first, and do again.  This gives the rate        */
-/*      computing machine all components to make good estimates.        */
-/* -------------------------------------------------------------------- */
+    // Write whole image.  Write 1024 lines of each component, then
+    // go back to the first, and do again.  This gives the rate
+    // computing machine all components to make good estimates.
     int iLinesWritten = 0;
 
     // TODO(schwehr): Making pabyBuffer void* should simplify the casting below.
     GByte *pabyBuffer = static_cast<GByte *>(
-        CPLMalloc(nXSize * (GDALGetDataTypeSize(eType)/8) ) );
+        CPLMalloc(nXSize * GDALGetDataTypeSizeBytes(eType)));
 
-    CPLAssert( !oTile.get_ycc() );
+    CPLAssert(!oTile.get_ycc());
 
     bool bRet = true;
     for( int iLine = 0; iLine < nYSize && bRet; iLine += TILE_CHUNK_SIZE )
     {
-        for( int c=0; c < num_components && bRet; c++ )
+        for( int c = 0; c < num_components && bRet; c++ )
         {
-            GDALRasterBand *poBand = poSrcDS->GetRasterBand( c+1 );
+            GDALRasterBand *poBand = poSrcDS->GetRasterBand(c + 1);
 
             for( int iSubline = iLine;
-                 iSubline < iLine+TILE_CHUNK_SIZE && iSubline < nYSize;
+                 iSubline < iLine + TILE_CHUNK_SIZE && iSubline < nYSize;
                  iSubline++ )
             {
                 if( poBand->RasterIO( GF_Read,
@@ -2118,66 +1876,64 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
                     kdu_sample16 *dest = lines[c].get_buf16();
                     kdu_byte *sp = pabyBuffer;
 
-                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
+                    for( int n = nXSize; n > 0; n--, dest++, sp++ )
                         dest->ival = ((kdu_int16)(*sp)) - 128;
                 }
                 else if( bReversible && eType == GDT_Int16 )
                 {
                     kdu_sample16 *dest = lines[c].get_buf16();
-                    GInt16 *sp = reinterpret_cast<GInt16 *>( pabyBuffer );
+                    GInt16 *sp = reinterpret_cast<GInt16 *>(pabyBuffer);
 
-                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
+                    for( int n = nXSize; n > 0; n--, dest++, sp++ )
                         dest->ival = *sp;
                 }
                 else if( bReversible && eType == GDT_UInt16 )
                 {
                     // Ticket #4050 patch : use a 32 bits kdu_line_buf for
-                    // GDT_UInt16 reversible compression
+                    // GDT_UInt16 reversible compression.
                     kdu_sample32 *dest = lines[c].get_buf32();
-                    GUInt16 *sp = reinterpret_cast<GUInt16 *>( pabyBuffer );
+                    GUInt16 *sp = reinterpret_cast<GUInt16 *>(pabyBuffer);
 
                     for( int n=nXSize; n > 0; n--, dest++, sp++ )
-                        dest->ival = static_cast<kdu_int32>(*sp)-32768;
+                        dest->ival = static_cast<kdu_int32>(*sp) - 32768;
                 }
                 else if( eType == GDT_Byte )
                 {
                     kdu_sample32 *dest = lines[c].get_buf32();
                     kdu_byte *sp = pabyBuffer;
-                    const int nOffset = 1 << (nBits-1);
-                    const float fScale = static_cast<float>(1.0 / (1 << nBits));
+                    const int nOffset = 1 << (nBits - 1);
+                    const float fScale = 1.0f / (1 << nBits);
 
-                    for (int n=nXSize; n > 0; n--, dest++, sp++)
-                        dest->fval = static_cast<float>
-                            (((static_cast<kdu_int16>(*sp))-nOffset) * fScale);
+                    for (int n = nXSize; n > 0; n--, dest++, sp++)
+                        dest->fval =
+                            (static_cast<kdu_int16>(*sp) - nOffset) * fScale;
                 }
                 else if( eType == GDT_Int16 )
                 {
                     kdu_sample32 *dest = lines[c].get_buf32();
-                    GInt16 *sp = reinterpret_cast<GInt16 *>( pabyBuffer );
-                    const float fScale = static_cast<float>(1.0 / (1 << nBits));
+                    GInt16 *sp = reinterpret_cast<GInt16 *>(pabyBuffer);
+                    const float fScale = 1.0f / (1 << nBits);
 
-                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
-                        dest->fval = static_cast<float>
-                            ((static_cast<kdu_int16>(*sp)) * fScale);
+                    for( int n = nXSize; n > 0; n--, dest++, sp++ )
+                        dest->fval = static_cast<kdu_int16>(*sp) * fScale;
                 }
                 else if( eType == GDT_UInt16 )
                 {
                     kdu_sample32 *dest = lines[c].get_buf32();
                     GUInt16 *sp = reinterpret_cast<GUInt16 *>(pabyBuffer);
-                    const int nOffset = 1 << (nBits-1);
-                    const float fScale = static_cast<float>(1.0 / (1 << nBits));
+                    const int nOffset = 1 << (nBits - 1);
+                    const float fScale = 1.0f / (1 << nBits);
 
-                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
-                        dest->fval = static_cast<float>
-                            ((static_cast<int>(*sp) - nOffset) * fScale);
+                    for( int n = nXSize; n > 0; n--, dest++, sp++ )
+                        dest->fval = (static_cast<int>(*sp) - nOffset) * fScale;
                 }
                 else if( eType == GDT_Float32 )
                 {
                     kdu_sample32 *dest = lines[c].get_buf32();
-                    float *sp = reinterpret_cast<float *>( pabyBuffer );
+                    float *sp = reinterpret_cast<float *>(pabyBuffer);
 
-                    for( int n=nXSize; n > 0; n--, dest++, sp++ )
-                        dest->fval = *sp;  /* scale it? */
+                    for( int n = nXSize; n > 0; n--, dest++, sp++ )
+                        dest->fval = *sp;  // Scale it?
                 }
 
 #if KDU_MAJOR_VERSION >= 7
@@ -2187,10 +1943,9 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
 #endif
                 iLinesWritten++;
 
-                if( !pfnProgress(
-                    iLinesWritten /
-                    static_cast<double> (num_components * nYSize),
-                    NULL, pProgressData ) )
+                if( !pfnProgress(iLinesWritten / static_cast<double>(
+                                                     num_components * nYSize),
+                                 NULL, pProgressData) )
                 {
                     bRet = false;
                     break;
@@ -2202,13 +1957,12 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
 
         if( oCodeStream.ready_for_flush() && bFlushEnabled )
         {
-            CPLDebug( "JP2KAK",
-                      "Calling oCodeStream.flush() at line %d",
-                      MIN(nYSize,iLine+TILE_CHUNK_SIZE) );
+            CPLDebug("JP2KAK", "Calling oCodeStream.flush() at line %d",
+                     std::min(nYSize, iLine + TILE_CHUNK_SIZE));
             try
             {
-                oCodeStream.flush( layer_bytes, layer_count, NULL,
-                                   true, bComseg );
+                oCodeStream.flush(layer_bytes, layer_count, NULL,
+                                  true, bComseg);
             }
             catch(...)
             {
@@ -2216,26 +1970,25 @@ JP2KAKCreateCopy_WriteTile( GDALDataset *poSrcDS, kdu_tile &oTile,
             }
         }
         else if( bFlushEnabled )
-            CPLDebug( "JP2KAK",
-                      "read_for_flush() is false at line %d.",
-                      iLine );
+        {
+            CPLDebug("JP2KAK", "read_for_flush() is false at line %d.", iLine);
+        }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Cleanup resources.                                              */
-/* -------------------------------------------------------------------- */
     for( int c = 0; c < num_components; c++ )
         engines[c].destroy();
 
     delete[] engines;
     delete[] lines;
 
-    CPLFree( pabyBuffer );
+    CPLFree(pabyBuffer);
 
     if( poROIImage != NULL )
         delete poROIImage;
 
     return bRet;
+    // For some reason cppcheck thinks that engines and lines are leaking.
+    // cppcheck-suppress memleak
 }
 
 /************************************************************************/
@@ -2250,124 +2003,113 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 {
     if( poSrcDS->GetRasterCount() == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Creating zero band files not supported by JP2KAK driver." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Creating zero band files not supported by JP2KAK driver.");
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize Kakadu warning/error reporting subsystem.            */
-/* -------------------------------------------------------------------- */
+    // Initialize Kakadu warning/error reporting subsystem.
     if( !kakadu_initialized )
     {
         kakadu_initialized = true;
 
-        kdu_cpl_error_message oErrHandler( CE_Failure );
-        kdu_cpl_error_message oWarningHandler( CE_Warning );
+        kdu_cpl_error_message oErrHandler(CE_Failure);
+        kdu_cpl_error_message oWarningHandler(CE_Warning);
 
-        kdu_customize_warnings(new kdu_cpl_error_message( CE_Warning ) );
-        kdu_customize_errors(new kdu_cpl_error_message( CE_Failure ) );
+        kdu_customize_warnings(new kdu_cpl_error_message(CE_Warning));
+        kdu_customize_errors(new kdu_cpl_error_message(CE_Failure));
     }
 
-/* -------------------------------------------------------------------- */
-/*      What data type should we use?  We assume all datatypes match    */
-/*      the first band.                                                 */
-/* -------------------------------------------------------------------- */
+    // What data type should we use?  We assume all datatypes match
+    // the first band.
     GDALRasterBand *poPrototypeBand = poSrcDS->GetRasterBand(1);
 
     GDALDataType eType = poPrototypeBand->GetRasterDataType();
-    if( eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_UInt16
-        && eType != GDT_Float32 )
+    if( eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_UInt16 &&
+        eType != GDT_Float32 )
     {
         if( bStrict )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "JP2KAK (JPEG2000) driver does not support data type %s.",
-                      GDALGetDataTypeName( eType ) );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "JP2KAK (JPEG2000) driver does not support data type %s.",
+                     GDALGetDataTypeName(eType));
             return NULL;
         }
 
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "JP2KAK (JPEG2000) driver does not support data type %s, "
-                  "forcing to Float32.",
-                  GDALGetDataTypeName( eType ) );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "JP2KAK (JPEG2000) driver does not support data type %s, "
+                 "forcing to Float32.",
+                 GDALGetDataTypeName(eType));
 
         eType = GDT_Float32;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we want to write a pseudo-colored image?                     */
-/* -------------------------------------------------------------------- */
-    int bHaveCT = poPrototypeBand->GetColorTable() != NULL
-        && poSrcDS->GetRasterCount() == 1;
+    // Do we want to write a pseudo-colored image?
+    const int bHaveCT =
+        poPrototypeBand->GetColorTable() != NULL &&
+        poSrcDS->GetRasterCount() == 1;
 
-/* -------------------------------------------------------------------- */
-/*      How many layers?                                                */
-/* -------------------------------------------------------------------- */
+    // How many layers?
     int layer_count = 12;
 
     if( CSLFetchNameValue(papszOptions,"LAYERS") != NULL )
-        layer_count = atoi(CSLFetchNameValue(papszOptions,"LAYERS"));
+        layer_count = atoi(CSLFetchNameValue(papszOptions, "LAYERS"));
     else if( CSLFetchNameValue(papszOptions,"Clayers") != NULL )
-        layer_count = atoi(CSLFetchNameValue(papszOptions,"Clayers"));
-
-/* -------------------------------------------------------------------- */
-/*      Establish how many bytes of data we want for each layer.        */
-/*      We take the quality as a percentage, so if QUALITY of 50 is     */
-/*      selected, we will set the base layer to 50% the default size.   */
-/*      We let the other layers be computed internally.                 */
-/* -------------------------------------------------------------------- */
-    bool bReversible = false;
-    double dfQuality = 20.0;
+        layer_count = atoi(CSLFetchNameValue(papszOptions, "Clayers"));
 
-    kdu_long *layer_bytes = static_cast<kdu_long *>(
-        CPLCalloc(sizeof(kdu_long),layer_count) );
+    // Establish how many bytes of data we want for each layer.
+    // We take the quality as a percentage, so if QUALITY of 50 is
+    // selected, we will set the base layer to 50% the default size.
+    // We let the other layers be computed internally.
 
-    if( CSLFetchNameValue(papszOptions,"QUALITY") != NULL )
-    {
-        dfQuality = CPLAtof(CSLFetchNameValue(papszOptions,"QUALITY"));
-    }
+    const double dfQuality =
+        CSLFetchNameValue(papszOptions,"QUALITY") != NULL
+        ? CPLAtof(CSLFetchNameValue(papszOptions, "QUALITY"))
+        : 20.0;
 
     if( dfQuality < 0.01 || dfQuality > 100.0 )
     {
-        CPLError( CE_Failure, CPLE_IllegalArg,
-                  "QUALITY=%s is not a legal value in the range 0.01-100.",
-                  CSLFetchNameValue(papszOptions,"QUALITY") );
-        CPLFree(layer_bytes);
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "QUALITY=%s is not a legal value in the range 0.01-100.",
+                 CSLFetchNameValue(papszOptions, "QUALITY"));
         return NULL;
     }
 
+    kdu_long *layer_bytes =
+        static_cast<kdu_long *>(CPLCalloc(sizeof(kdu_long), layer_count));
+
     const int nXSize = poSrcDS->GetRasterXSize();
     const int nYSize = poSrcDS->GetRasterYSize();
 
+    bool bReversible = false;
+
     if( dfQuality < 99.5 )
     {
         double dfLayerBytes =
-            (nXSize * static_cast<double>(nYSize) * dfQuality / 100.0);
-
-        dfLayerBytes *= (GDALGetDataTypeSize(eType) / 8);
-        dfLayerBytes *= GDALGetRasterCount(poSrcDS);
+            (nXSize * static_cast<double>(nYSize) * dfQuality / 100.0)
+            * GDALGetDataTypeSizeBytes(eType)
+            * GDALGetRasterCount(poSrcDS);
 
         if( dfLayerBytes > 2000000000.0 && sizeof(kdu_long) == 4 )
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Trimmming maximum size of file 2GB from %.1fGB\n"
-                      "to avoid overflow of kdu_long layer size.",
-                      dfLayerBytes / 1000000000.0 );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Trimmming maximum size of file 2GB from %.1fGB\n"
+                     "to avoid overflow of kdu_long layer size.",
+                     dfLayerBytes / 1000000000.0);
             dfLayerBytes = 2000000000.0;
         }
 
-        layer_bytes[layer_count-1] = (kdu_long) dfLayerBytes;
+        layer_bytes[layer_count - 1] = static_cast<kdu_long>(dfLayerBytes);
 
-        CPLDebug( "JP2KAK", "layer_bytes[] = %g\n",
-                  (double) layer_bytes[layer_count-1] );
+        CPLDebug("JP2KAK", "layer_bytes[] = %g\n",
+                 static_cast<double>(layer_bytes[layer_count - 1]));
     }
     else
+    {
         bReversible = true;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Do we want to use more than one tile?                           */
-/* -------------------------------------------------------------------- */
+    // Do we want to use more than one tile?
     int nTileXSize = nXSize;
     int nTileYSize = nYSize;
 
@@ -2378,6 +2120,7 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         nTileXSize = 20000;
     }
 
+    // TODO(schwehr): Why 253 and not 255?
     if( (nTileYSize / TILE_CHUNK_SIZE) > 253)
     {
         // We don't want to process a tile in more than 255 chunks as there
@@ -2394,13 +2137,10 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( CSLFetchNameValue( papszOptions, "BLOCKYSIZE" ) != NULL )
         nTileYSize = atoi(CSLFetchNameValue( papszOptions, "BLOCKYSIZE"));
 
-/* -------------------------------------------------------------------- */
-/*      Avoid splitting into too many tiles - apparently limiting to    */
-/*      64K tiles.  There is a hard limit on the number of tiles        */
-/*      allowed in JPEG2000.                                            */
-/* -------------------------------------------------------------------- */
-    while( (double)nXSize*(double)nYSize
-           / (double)nTileXSize / (double)nTileYSize / 1024.0 >= 64.0 )
+    // Avoid splitting into too many tiles - apparently limiting to 64K tiles.
+    // There is a hard limit on the number of tiles allowed in JPEG2000.
+    const double dfXbyY = static_cast<double>(nXSize * nYSize) / (1024 * 64);
+    while( dfXbyY >= static_cast<double>(nTileXSize * nTileYSize) )
     {
         nTileXSize *= 2;
         nTileYSize *= 2;
@@ -2409,61 +2149,48 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( nTileXSize > nXSize ) nTileXSize = nXSize;
     if( nTileYSize > nYSize ) nTileYSize = nYSize;
 
-    CPLDebug( "JP2KAK", "Final JPEG2000 Tile Size is %dP x %dL.",
-              nTileXSize, nTileYSize );
+    CPLDebug("JP2KAK", "Final JPEG2000 Tile Size is %dP x %dL.",
+             nTileXSize, nTileYSize);
 
-/* -------------------------------------------------------------------- */
-/*      Do we want a comment segment emitted?                           */
-/* -------------------------------------------------------------------- */
-    bool bComseg = false;
+    // Do we want a comment segment emitted?
+    const bool bComseg = CPLFetchBool(papszOptions, "COMSEG", true);
 
-    if( CSLFetchBoolean( papszOptions, "COMSEG", TRUE ) )
-        bComseg = true;
-    else
-        bComseg = false;
-
-/* -------------------------------------------------------------------- */
-/*      Work out the precision.                                         */
-/* -------------------------------------------------------------------- */
+    // Work out the precision.
     int nBits = 0;
 
-  if( CSLFetchNameValue( papszOptions, "NBITS" ) != NULL )
-        nBits = atoi(CSLFetchNameValue(papszOptions,"NBITS"));
-    else if( poPrototypeBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" )
+    if( CSLFetchNameValue( papszOptions, "NBITS" ) != NULL )
+        nBits = atoi(CSLFetchNameValue(papszOptions, "NBITS"));
+    else if( poPrototypeBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE")
              != NULL )
-        nBits = atoi(poPrototypeBand->GetMetadataItem( "NBITS",
-                                                       "IMAGE_STRUCTURE" ));
+        nBits =
+            atoi(poPrototypeBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE"));
     else
         nBits = GDALGetDataTypeSize(eType);
 
-/* -------------------------------------------------------------------- */
-/*      Establish the general image parameters.                         */
-/* -------------------------------------------------------------------- */
+    // Establish the general image parameters.
     siz_params oSizeParams;
 
-    oSizeParams.set( Scomponents, 0, 0, poSrcDS->GetRasterCount() );
-    oSizeParams.set( Sdims, 0, 0, nYSize );
-    oSizeParams.set( Sdims, 0, 1, nXSize );
-    oSizeParams.set( Sprecision, 0, 0, nBits );
+    oSizeParams.set(Scomponents, 0, 0, poSrcDS->GetRasterCount());
+    oSizeParams.set(Sdims, 0, 0, nYSize);
+    oSizeParams.set(Sdims, 0, 1, nXSize);
+    oSizeParams.set(Sprecision, 0, 0, nBits);
     if( eType == GDT_UInt16 || eType == GDT_Byte )
-        oSizeParams.set( Ssigned, 0, 0, false );
+        oSizeParams.set(Ssigned, 0, 0, false);
     else
-        oSizeParams.set( Ssigned, 0, 0, true );
+        oSizeParams.set(Ssigned, 0, 0, true);
 
     if( nTileXSize != nXSize || nTileYSize != nYSize )
     {
-        oSizeParams.set( Stiles, 0, 0, nTileYSize );
-        oSizeParams.set( Stiles, 0, 1, nTileXSize );
+        oSizeParams.set(Stiles, 0, 0, nTileYSize);
+        oSizeParams.set(Stiles, 0, 1, nTileXSize);
 
-        CPLDebug( "JP2KAK", "Stiles=%d,%d", nTileYSize, nTileXSize );
+        CPLDebug("JP2KAK", "Stiles=%d,%d", nTileYSize, nTileXSize);
     }
 
     kdu_params *poSizeRef = &oSizeParams;
     poSizeRef->finalize();
 
-/* -------------------------------------------------------------------- */
-/*      Open output file, and setup codestream.                         */
-/* -------------------------------------------------------------------- */
+    // Open output file, and setup codestream.
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
         return NULL;
 
@@ -2471,85 +2198,82 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 #ifdef KAKADU_JPX
     jpx_family_tgt jpx_family;
     jpx_target jpx_out;
-    const bool bIsJPX = !EQUAL(CPLGetExtension(pszFilename),"jpf");
+    const bool bIsJPX = !EQUAL(CPLGetExtension(pszFilename), "jpf");
 #else
     const bool bIsJPX = false;
 #endif
 
     kdu_compressed_target *poOutputFile = NULL;
     jp2_target jp2_out;
-    const bool bIsJP2 = !EQUAL(CPLGetExtension(pszFilename),"jpc") && !bIsJPX;
+    const bool bIsJP2 = !EQUAL(CPLGetExtension(pszFilename), "jpc") && !bIsJPX;
     kdu_codestream oCodeStream;
 
     vsil_target oVSILTarget;
 
     try
     {
-        oVSILTarget.open( pszFilename, "w" );
+        oVSILTarget.open(pszFilename, "w");
 
         if( bIsJP2 )
         {
-            //family.open( pszFilename );
-            family.open( &oVSILTarget );
+            // family.open( pszFilename );
+            family.open(&oVSILTarget);
 
-            jp2_out.open( &family );
+            jp2_out.open(&family);
             poOutputFile = &jp2_out;
         }
 #ifdef KAKADU_JPX
         else if( bIsJPX )
         {
-            jpx_family.open( pszFilename );
+            jpx_family.open(pszFilename);
 
-            jpx_out.open( &jpx_family );
+            jpx_out.open(&jpx_family);
             jpx_out.add_codestream();
         }
 #endif
         else
+        {
             poOutputFile = &oVSILTarget;
+        }
 
-        oCodeStream.create(&oSizeParams, poOutputFile );
+        oCodeStream.create(&oSizeParams, poOutputFile);
     }
     catch( ... )
     {
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we have a high res region of interest?                       */
-/* -------------------------------------------------------------------- */
+    // Do we have a high res region of interest?
     kdu_roi_image *poROIImage = NULL;
-    char **papszROIDefs = CSLFetchNameValueMultiple( papszOptions, "ROI" );
+    char **papszROIDefs = CSLFetchNameValueMultiple(papszOptions, "ROI");
 
     for( int iROI = 0;
          papszROIDefs != NULL && papszROIDefs[iROI] != NULL;
          ++iROI )
     {
-        kdu_dims region;
-        char **papszTokens = CSLTokenizeStringComplex( papszROIDefs[iROI], ",",
-                                                       FALSE, FALSE );
+        char **papszTokens =
+            CSLTokenizeStringComplex(papszROIDefs[iROI], ",", FALSE, FALSE);
 
         if( CSLCount(papszTokens) != 4 )
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Skipping corrupt ROI def = \n%s",
-                      papszROIDefs[iROI] );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Skipping corrupt ROI def = \n%s", papszROIDefs[iROI]);
             continue;
         }
 
+        kdu_dims region;
         region.pos.x = atoi(papszTokens[0]);
         region.pos.y = atoi(papszTokens[1]);
         region.size.x = atoi(papszTokens[2]);
         region.size.y = atoi(papszTokens[3]);
 
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
 
-        poROIImage = new kdu_roi_rect(oCodeStream,region);
+        poROIImage = new kdu_roi_rect(oCodeStream, region);
     }
     CSLDestroy(papszROIDefs);
 
-/* -------------------------------------------------------------------- */
-/*      Set some particular parameters.                                 */
-/* -------------------------------------------------------------------- */
+    // Set some particular parameters.
     oCodeStream.access_siz()->parse_string(
         CPLString().Printf("Clayers=%d", layer_count).c_str());
     oCodeStream.access_siz()->parse_string("Cycc=no");
@@ -2561,9 +2285,7 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     else
         oCodeStream.access_siz()->parse_string("Creversible=no");
 
-/* -------------------------------------------------------------------- */
-/*      Set some user-overridable parameters.                           */
-/* -------------------------------------------------------------------- */
+    // Set some user-overridable parameters.
     const char *apszParms[] =
         { "Corder", "PCRL",
           "Cprecincts", "{512,512},{256,512},{128,512},{64,512},{32,512},"
@@ -2583,19 +2305,19 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     for( int iParm = 0; apszParms[iParm] != NULL; iParm += 2 )
     {
         const char *pszValue =
-            CSLFetchNameValue( papszOptions, apszParms[iParm] );
+            CSLFetchNameValue(papszOptions, apszParms[iParm]);
 
         if( pszValue == NULL )
-            pszValue = apszParms[iParm+1];
+            pszValue = apszParms[iParm + 1];
 
         if( pszValue != NULL )
         {
             CPLString osOpt;
 
-            osOpt.Printf( "%s=%s", apszParms[iParm], pszValue );
+            osOpt.Printf("%s=%s", apszParms[iParm], pszValue);
             try
             {
-                oCodeStream.access_siz()->parse_string( osOpt );
+                oCodeStream.access_siz()->parse_string(osOpt);
             }
             catch( ... )
             {
@@ -2612,15 +2334,13 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 return NULL;
             }
 
-            CPLDebug( "JP2KAK", "parse_string(%s)", osOpt.c_str() );
+            CPLDebug("JP2KAK", "parse_string(%s)", osOpt.c_str());
         }
     }
 
     oCodeStream.access_siz()->finalize_all();
 
-/* -------------------------------------------------------------------- */
-/*      Some JP2 specific parameters.                                   */
-/* -------------------------------------------------------------------- */
+    // Some JP2 specific parameters.
     if( bIsJP2 )
     {
         // Set dimensional information.
@@ -2632,33 +2352,37 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         jp2_colour colour = jp2_out.access_colour();
 
         if( bHaveCT || poSrcDS->GetRasterCount() == 3 )
+        {
             colour.init( JP2_sRGB_SPACE );
+        }
         else if( poSrcDS->GetRasterCount() >= 4
                  && poSrcDS->GetRasterBand(4)->GetColorInterpretation()
                  == GCI_AlphaBand )
         {
-            colour.init( JP2_sRGB_SPACE );
-            jp2_out.access_channels().init( 3 );
-            jp2_out.access_channels().set_colour_mapping(0,0);
-            jp2_out.access_channels().set_colour_mapping(1,1);
-            jp2_out.access_channels().set_colour_mapping(2,2);
-            jp2_out.access_channels().set_opacity_mapping(0,3);
-            jp2_out.access_channels().set_opacity_mapping(1,3);
-            jp2_out.access_channels().set_opacity_mapping(2,3);
+            colour.init(JP2_sRGB_SPACE);
+            jp2_out.access_channels().init(3);
+            jp2_out.access_channels().set_colour_mapping(0, 0);
+            jp2_out.access_channels().set_colour_mapping(1, 1);
+            jp2_out.access_channels().set_colour_mapping(2, 2);
+            jp2_out.access_channels().set_opacity_mapping(0, 3);
+            jp2_out.access_channels().set_opacity_mapping(1, 3);
+            jp2_out.access_channels().set_opacity_mapping(2, 3);
         }
         else if( poSrcDS->GetRasterCount() >= 2
                  && poSrcDS->GetRasterBand(2)->GetColorInterpretation()
                  == GCI_AlphaBand )
         {
-            colour.init( JP2_sLUM_SPACE );
-            jp2_out.access_channels().init( 1 );
-            jp2_out.access_channels().set_colour_mapping(0,0);
-            jp2_out.access_channels().set_opacity_mapping(0,1);
+            colour.init(JP2_sLUM_SPACE);
+            jp2_out.access_channels().init(1);
+            jp2_out.access_channels().set_colour_mapping(0, 0);
+            jp2_out.access_channels().set_opacity_mapping(0, 1);
         }
         else
+        {
             colour.init( JP2_sLUM_SPACE );
+        }
 
-        // Resolution
+        // Resolution.
         if( poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION") != NULL
             && poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION") != NULL
             && poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT") != NULL )
@@ -2678,68 +2402,74 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 dfYRes *= dfInchToCm;
             }
 
-            // convert to pixels per meter.
+            // Convert to pixels per meter.
             dfXRes *= 100.0;
             dfYRes *= 100.0;
 
             if( dfXRes != 0.0 && dfYRes != 0.0 )
             {
-                if( fabs(dfXRes/dfYRes - 1.0) > 0.00001 )
-                    res.init( dfYRes/dfXRes );
+                if( fabs(dfXRes / dfYRes - 1.0) > 0.00001 )
+                    res.init(static_cast<float>(dfYRes / dfXRes));
                 else
-                    res.init( 1.0 );
-                res.set_resolution( dfXRes, true );
+                    res.init(1.0);
+                res.set_resolution(static_cast<float>(dfXRes), true);
             }
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write JP2 pseudocolor table if available.                       */
-/* -------------------------------------------------------------------- */
+    // Write JP2 pseudocolor table if available.
     if( bIsJP2 && bHaveCT )
     {
-        GDALColorTable * const poCT = poPrototypeBand->GetColorTable();
+        GDALColorTable *const poCT = poPrototypeBand->GetColorTable();
         const int nCount = poCT->GetColorEntryCount();
-        kdu_int32 *panLUT = static_cast<kdu_int32 *>(
-            CPLMalloc(sizeof(kdu_int32) * nCount * 3) );
+        kdu_int32 *panLUT =
+            static_cast<kdu_int32 *>(CPLMalloc(sizeof(kdu_int32) * nCount * 3));
 
         jp2_palette oJP2Palette = jp2_out.access_palette();
-        oJP2Palette.init( 3, nCount );
+        oJP2Palette.init(3, nCount);
 
         for( int iColor = 0; iColor < nCount; iColor++ )
         {
             GDALColorEntry sEntry = { 0, 0, 0, 0 };
 
-            poCT->GetColorEntryAsRGB( iColor, &sEntry );
+            poCT->GetColorEntryAsRGB(iColor, &sEntry);
             panLUT[iColor + nCount * 0] = sEntry.c1;
             panLUT[iColor + nCount * 1] = sEntry.c2;
             panLUT[iColor + nCount * 2] = sEntry.c3;
         }
 
-        oJP2Palette.set_lut( 0, panLUT + nCount * 0, 8, false );
-        oJP2Palette.set_lut( 1, panLUT + nCount * 1, 8, false );
-        oJP2Palette.set_lut( 2, panLUT + nCount * 2, 8, false );
+        oJP2Palette.set_lut(0, panLUT + nCount * 0, 8, false);
+        oJP2Palette.set_lut(1, panLUT + nCount * 1, 8, false);
+        oJP2Palette.set_lut(2, panLUT + nCount * 2, 8, false);
 
-        CPLFree( panLUT );
+        CPLFree(panLUT);
 
         jp2_channels oJP2Channels = jp2_out.access_channels();
 
-        oJP2Channels.init( 3 );
-        oJP2Channels.set_colour_mapping( 0, 0, 0 );
-        oJP2Channels.set_colour_mapping( 1, 0, 1 );
-        oJP2Channels.set_colour_mapping( 2, 0, 2 );
+        oJP2Channels.init(3);
+        oJP2Channels.set_colour_mapping(0, 0, 0);
+        oJP2Channels.set_colour_mapping(1, 0, 1);
+        oJP2Channels.set_colour_mapping(2, 0, 2);
     }
 
     if( bIsJP2 )
     {
-        jp2_out.write_header();
+        try
+        {
+            jp2_out.write_header();
+        }
+        catch( ... )
+        {
+            CPLDebug("JP2KAK", "jp2_out.write_header() - caught exception.");
+            oCodeStream.destroy();
+            CPLFree(layer_bytes);
+            return NULL;
+        }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set the GeoTIFF and GML boxes if georeferencing is available,   */
-/*      and this is a JP2 file.                                         */
-/* -------------------------------------------------------------------- */
-    double adfGeoTransform[6] = { 0.0 };
+    // Set the GeoTIFF and GML boxes if georeferencing is available,
+    // and this is a JP2 file.
+    double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
     if( bIsJP2
         && ((poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None
              && (adfGeoTransform[0] != 0.0
@@ -2747,7 +2477,7 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                  || adfGeoTransform[2] != 0.0
                  || adfGeoTransform[3] != 0.0
                  || adfGeoTransform[4] != 0.0
-                 || ABS(adfGeoTransform[5]) != 1.0))
+                 || std::abs(adfGeoTransform[5]) != 1.0))
             || poSrcDS->GetGCPCount() > 0
             || poSrcDS->GetMetadata("RPC") != NULL) )
     {
@@ -2755,135 +2485,123 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
         if( poSrcDS->GetGCPCount() > 0 )
         {
-            oJP2MD.SetProjection( poSrcDS->GetGCPProjection() );
-            oJP2MD.SetGCPs( poSrcDS->GetGCPCount(), poSrcDS->GetGCPs() );
+            oJP2MD.SetProjection(poSrcDS->GetGCPProjection());
+            oJP2MD.SetGCPs(poSrcDS->GetGCPCount(), poSrcDS->GetGCPs());
         }
         else
         {
-            oJP2MD.SetProjection( poSrcDS->GetProjectionRef() );
-            oJP2MD.SetGeoTransform( adfGeoTransform );
+            oJP2MD.SetProjection(poSrcDS->GetProjectionRef());
+            oJP2MD.SetGeoTransform(adfGeoTransform);
         }
 
-        oJP2MD.SetRPCMD( poSrcDS->GetMetadata("RPC") );
+        oJP2MD.SetRPCMD(poSrcDS->GetMetadata("RPC"));
 
-        const char* const pszAreaOrPoint =
+        const char *const pszAreaOrPoint =
             poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
         oJP2MD.bPixelIsPoint =
             pszAreaOrPoint != NULL && EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
 
-        if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
+        if( CPLFetchBool(papszOptions, "GMLJP2", true) )
         {
-            const char* pszGMLJP2V2Def =
-                CSLFetchNameValue( papszOptions, "GMLJP2V2_DEF" );
+            const char *pszGMLJP2V2Def =
+                CSLFetchNameValue(papszOptions, "GMLJP2V2_DEF");
             if( pszGMLJP2V2Def != NULL )
                 JP2KAKWriteBox(
                     &jp2_out,
                     oJP2MD.CreateGMLJP2V2(
                         nXSize,nYSize,pszGMLJP2V2Def,poSrcDS) );
             else
-                JP2KAKWriteBox( &jp2_out, oJP2MD.CreateGMLJP2(nXSize,nYSize) );
+                JP2KAKWriteBox(&jp2_out, oJP2MD.CreateGMLJP2(nXSize, nYSize));
         }
-        if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) )
-            JP2KAKWriteBox( &jp2_out, oJP2MD.CreateJP2GeoTIFF() );
+        if( CPLFetchBool(papszOptions, "GeoJP2", true) )
+            JP2KAKWriteBox(&jp2_out, oJP2MD.CreateJP2GeoTIFF());
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we have any XML boxes we want to preserve?                   */
-/* -------------------------------------------------------------------- */
+    // Do we have any XML boxes we want to preserve?
 
     for( int iBox = 0; true; iBox++ )
     {
         CPLString oName;
-        oName.Printf( "xml:BOX_%d", iBox );
-        char **papszMD = poSrcDS->GetMetadata( oName );
+        oName.Printf("xml:BOX_%d", iBox);
+        char **papszMD = poSrcDS->GetMetadata(oName);
 
         if( papszMD == NULL || CSLCount(papszMD) != 1 )
             break;
 
         GDALJP2Box *poXMLBox = new GDALJP2Box();
 
-        poXMLBox->SetType( "xml " );
-        poXMLBox->SetWritableData( static_cast<int>(strlen(papszMD[0])+1),
-                                   reinterpret_cast<GByte *>( papszMD[0] ) );
-        JP2KAKWriteBox( &jp2_out, poXMLBox );
+        poXMLBox->SetType("xml ");
+        poXMLBox->SetWritableData(static_cast<int>(strlen(papszMD[0]) + 1),
+                                  reinterpret_cast<GByte *>(papszMD[0]));
+        JP2KAKWriteBox(&jp2_out, poXMLBox);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Open codestream box.                                            */
-/* -------------------------------------------------------------------- */
+    // Open codestream box.
     if( bIsJP2 )
         jp2_out.open_codestream();
 
-/* -------------------------------------------------------------------- */
-/*      Create one big tile, and a compressing engine, and line         */
-/*      buffer for each component.                                      */
-/* -------------------------------------------------------------------- */
+    // Create one big tile, and a compressing engine, and line
+    // buffer for each component.
     double dfPixelsDone = 0.0;
-    const double dfPixelsTotal = nXSize * static_cast<double>( nYSize );
-    const int bFlushEnabled = CSLFetchBoolean( papszOptions, "FLUSH", TRUE );
+    const double dfPixelsTotal = nXSize * static_cast<double>(nYSize);
+    const bool bFlushEnabled = CPLFetchBool(papszOptions, "FLUSH", true);
 
     for( int iTileYOff = 0; iTileYOff < nYSize; iTileYOff += nTileYSize )
     {
         for( int iTileXOff = 0; iTileXOff < nXSize; iTileXOff += nTileXSize )
         {
             kdu_tile oTile = oCodeStream.open_tile(
-                kdu_coords(iTileXOff/nTileXSize,iTileYOff/nTileYSize));
-            int nThisTileXSize = 0;
-            int nThisTileYSize = 0;
+                kdu_coords(iTileXOff / nTileXSize, iTileYOff / nTileYSize));
 
-            // ---------------------------------------------------------------
             // Is this a partial tile on the right or bottom?
-            if( iTileXOff + nTileXSize < nXSize )
-                nThisTileXSize = nTileXSize;
-            else
-                nThisTileXSize = nXSize - iTileXOff;
-
-            if( iTileYOff + nTileYSize < nYSize )
-                nThisTileYSize = nTileYSize;
-            else
-                nThisTileYSize = nYSize - iTileYOff;
-
-            // ---------------------------------------------------------------
-            // Setup scaled progress monitor
-
-            double dfPixelsDoneAfter =
-                dfPixelsDone + (nThisTileXSize * (double) nThisTileYSize);
-
-            void *pScaledProgressData =
-                GDALCreateScaledProgress( dfPixelsDone / dfPixelsTotal,
-                                          dfPixelsDoneAfter / dfPixelsTotal,
-                                          pfnProgress, pProgressData );
-            if( !JP2KAKCreateCopy_WriteTile( poSrcDS, oTile, poROIImage,
-                                             iTileXOff, iTileYOff,
-                                             nThisTileXSize, nThisTileYSize,
-                                             bReversible, nBits, eType,
-                                             oCodeStream, bFlushEnabled,
-                                             layer_bytes, layer_count,
-                                             GDALScaledProgress,
-                                             pScaledProgressData, bComseg ) )
+            const int nThisTileXSize =
+                iTileXOff + nTileXSize < nXSize
+                ? nTileXSize
+                : nXSize - iTileXOff;
+
+            const int nThisTileYSize =
+                iTileYOff + nTileYSize < nYSize
+                ? nTileYSize
+                : nYSize - iTileYOff;
+
+            // Setup scaled progress monitor.
+
+            const double dfPixelsDoneAfter =
+                dfPixelsDone + (nThisTileXSize * nThisTileYSize);
+
+            void *pScaledProgressData = GDALCreateScaledProgress(
+                dfPixelsDone / dfPixelsTotal, dfPixelsDoneAfter / dfPixelsTotal,
+                pfnProgress, pProgressData);
+
+            if( !JP2KAKCreateCopy_WriteTile(poSrcDS, oTile, poROIImage,
+                                            iTileXOff, iTileYOff,
+                                            nThisTileXSize, nThisTileYSize,
+                                            bReversible, nBits, eType,
+                                            oCodeStream, bFlushEnabled,
+                                            layer_bytes, layer_count,
+                                            GDALScaledProgress,
+                                            pScaledProgressData, bComseg) )
             {
-                GDALDestroyScaledProgress( pScaledProgressData );
+                GDALDestroyScaledProgress(pScaledProgressData);
 
                 oCodeStream.destroy();
                 poOutputFile->close();
-                VSIUnlink( pszFilename );
+                VSIUnlink(pszFilename);
                 return NULL;
             }
 
-            GDALDestroyScaledProgress( pScaledProgressData );
+            GDALDestroyScaledProgress(pScaledProgressData);
             dfPixelsDone = dfPixelsDoneAfter;
 
             oTile.close();
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Finish flushing out results.                                    */
-/* -------------------------------------------------------------------- */
-    oCodeStream.flush(layer_bytes, layer_count, NULL, true, bComseg );
+    // Finish flushing out results.
+    oCodeStream.flush(layer_bytes, layer_count, NULL, true, bComseg);
     oCodeStream.destroy();
 
-    CPLFree( layer_bytes );
+    CPLFree(layer_bytes);
 
     if( bIsJP2 )
     {
@@ -2897,17 +2615,16 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
     oVSILTarget.close();
 
-    if( !pfnProgress( 1.0, NULL, pProgressData ) )
+    if( !pfnProgress(1.0, NULL, pProgressData) )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Re-open dataset, and copy any auxiliary pam information.         */
-/* -------------------------------------------------------------------- */
+    // Re-open dataset, and copy any auxiliary pam information.
     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
-    GDALPamDataset *poDS = (GDALPamDataset*) JP2KAKDataset::Open(&oOpenInfo);
+    GDALPamDataset *poDS =
+        static_cast<GDALPamDataset *>(JP2KAKDataset::Open(&oOpenInfo));
 
     if( poDS )
-        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+        poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT);
 
     return poDS;
 }
@@ -2919,46 +2636,55 @@ JP2KAKCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 void GDALRegister_JP2KAK()
 
 {
-    if( !GDAL_CHECK_VERSION( "JP2KAK driver" ) )
+    if( !GDAL_CHECK_VERSION("JP2KAK driver") )
         return;
 
-    if( GDALGetDriverByName( "JP2KAK" ) != NULL )
+    if( GDALGetDriverByName("JP2KAK") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "JP2KAK" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                               "JPEG-2000 (based on Kakadu "
-                               KDU_CORE_VERSION ")" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jp2kak.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                               "Byte Int16 UInt16" );
-    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetDescription("JP2KAK");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
+    poDriver->SetMetadataItem(
+        GDAL_DMD_LONGNAME, "JPEG-2000 (based on Kakadu " KDU_CORE_VERSION ")");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_jp2kak.html");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte Int16 UInt16");
+    poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/jp2");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jp2");
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
+
+    poDriver->SetMetadataItem(GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
-"   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description='Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
-"   <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether to load remote vector layers referenced by a link in a GMLJP2 v2 box' default='NO'/>"
+"   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description="
+"'Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
+"   <Option name='OPEN_REMOTE_GML' type='boolean' description="
+"'Whether to load remote vector layers referenced by "
+"a link in a GMLJP2 v2 box' default='NO'/>"
+"   <Option name='GEOREF_SOURCES' type='string' description="
+"'Comma separated list made with values "
+"INTERNAL/GMLJP2/GEOJP2/WORLDFILE/PAM/NONE that describe the priority order "
+"for georeferencing' default='PAM,GEOJP2,GMLJP2,WORLDFILE'/>"
 "</OpenOptionList>" );
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
-"   <Option name='QUALITY' type='integer' description='0.01-100, 100 is lossless'/>"
+"   <Option name='QUALITY' type='integer' description="
+"'0.01-100, 100 is lossless'/>"
 "   <Option name='BLOCKXSIZE' type='int' description='Tile Width'/>"
 "   <Option name='BLOCKYSIZE' type='int' description='Tile Height'/>"
 "   <Option name='GeoJP2' type='boolean' description='defaults to ON'/>"
 "   <Option name='GMLJP2' type='boolean' description='defaults to ON'/>"
-"   <Option name='GMLJP2V2_DEF' type='string' description='Definition file to describe how a GMLJP2 v2 box should be generated. If set to YES, a minimal instance will be created'/>"
+"   <Option name='GMLJP2V2_DEF' type='string' description="
+"'Definition file to describe how a GMLJP2 v2 box should be generated. "
+"If set to YES, a minimal instance will be created'/>"
 "   <Option name='LAYERS' type='integer'/>"
 "   <Option name='ROI' type='string'/>"
 "   <Option name='COMSEG' type='boolean' />"
 "   <Option name='FLUSH' type='boolean' />"
-"   <Option name='NBITS' type='int' description='BITS (precision) for sub-byte files (1-7), sub-uint16 (9-15)'/>"
+"   <Option name='NBITS' type='int' description="
+"'BITS (precision) for sub-byte files (1-7), sub-uint16 (9-15)'/>"
 "   <Option name='Corder' type='string'/>"
 "   <Option name='Cprecincts' type='string'/>"
 "   <Option name='Cmodes' type='string'/>"
@@ -2976,5 +2702,5 @@ void GDALRegister_JP2KAK()
     poDriver->pfnIdentify = JP2KAKDataset::Identify;
     poDriver->pfnCreateCopy = JP2KAKCreateCopy;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/jp2kak/jp2kakdataset.h b/frmts/jp2kak/jp2kakdataset.h
new file mode 100644
index 0000000..1512e8f
--- /dev/null
+++ b/frmts/jp2kak/jp2kakdataset.h
@@ -0,0 +1,226 @@
+/******************************************************************************
+ *
+ * Project:  JPEG-2000
+ * Purpose:  Implementation of the ISO/IEC 15444-1 standard based on Kakadu.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// $Id: jp2kakdataset.h 37393 2017-02-16 21:07:25Z rouault $
+
+#ifdef DEBUG_BOOL
+#define DO_NOT_USE_DEBUG_BOOL
+#endif
+
+#include <cstring>
+#include <algorithm>
+#include <cmath>
+
+#include "../mem/memdataset.h"
+#include "cpl_multiproc.h"
+#include "cpl_port.h"
+#include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "gdaljp2abstractdataset.h"
+#include "gdaljp2metadata.h"
+#include "jp2kak_headers.h"
+#include "subfile_source.h"
+
+// Before v7.5 Kakadu does not advertise its version well
+// After v7.5 Kakadu has KDU_{MAJOR,MINOR,PATCH}_VERSION defines so it's easier
+// For older releases compile with them manually specified.  e.g.:
+// -DKDU_MAJOR_VERSION=7 -DKDU_MINOR_VERSION=3 -DKDU_PATCH_VERSION=2
+#ifndef KDU_MAJOR_VERSION
+#  error Compile with Kakadu library version.
+#endif
+
+#if KDU_MAJOR_VERSION > 7 || (KDU_MAJOR_VERSION == 7 && KDU_MINOR_VERSION >= 5)
+    using namespace kdu_core;
+    using namespace kdu_supp;
+#endif
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            JP2KAKDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class JP2KAKDataset : public GDALJP2AbstractDataset
+{
+    friend class JP2KAKRasterBand;
+
+    kdu_codestream oCodeStream;
+    kdu_compressed_source *poInput;
+    kdu_compressed_source *poRawInput;
+    jp2_family_src  *family;
+    kdu_client      *jpip_client;
+    kdu_dims dims;
+    int            nResCount;
+    bool           bPreferNPReads;
+    kdu_thread_env *poThreadEnv;
+
+    bool           bCached;
+    bool           bResilient;
+    bool           bFussy;
+    bool           bUseYCC;
+
+    bool           bPromoteTo8Bit;
+
+    bool        TestUseBlockIO( int, int, int, int, int, int,
+                                GDALDataType, int, int * );
+    CPLErr      DirectRasterIO( GDALRWFlag, int, int, int, int,
+                                void *, int, int, GDALDataType,
+                                int, int *,
+                                GSpacing nPixelSpace, GSpacing nLineSpace,
+                                GSpacing nBandSpace,
+                                GDALRasterIOExtraArg* psExtraArg);
+
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+                              int, int *,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GSpacing nBandSpace,
+                              GDALRasterIOExtraArg* psExtraArg) override;
+
+  public:
+             JP2KAKDataset();
+    virtual ~JP2KAKDataset() override;
+
+    virtual CPLErr IBuildOverviews( const char *, int, int *,
+                                    int, int *, GDALProgressFunc,
+                                    void * ) override;
+
+    static void KakaduInitialize();
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            JP2KAKRasterBand                          */
+/* ==================================================================== */
+/************************************************************************/
+
+class JP2KAKRasterBand : public GDALPamRasterBand
+{
+    friend class JP2KAKDataset;
+
+    JP2KAKDataset *poBaseDS;
+
+    int         nDiscardLevels;
+    kdu_dims    band_dims;
+    int         nOverviewCount;
+    JP2KAKRasterBand **papoOverviewBand;
+
+    kdu_client      *jpip_client;
+    kdu_codestream oCodeStream;
+
+    GDALColorTable oCT;
+    GDALColorInterp eInterp;
+
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GDALRasterIOExtraArg* psExtraArg) override;
+
+    bool           HasExternalOverviews()
+                   { return GDALPamRasterBand::GetOverviewCount() != 0; }
+
+  public:
+                JP2KAKRasterBand( int, int, kdu_codestream, int, kdu_client *,
+                                  jp2_channels, JP2KAKDataset * );
+    virtual ~JP2KAKRasterBand() override;
+
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+
+    virtual int    GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview( int ) override;
+
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+
+    // Internal.
+
+    void        ApplyPalette( jp2_palette oJP2Palette );
+    void        ProcessYCbCrTile( kdu_tile tile, GByte *pabyBuffer,
+                                  int nBlockXOff, int nBlockYOff,
+                                  int nTileOffsetX, int nTileOffsetY );
+    void        ProcessTile(kdu_tile tile, GByte *pabyBuffer );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                     Set up messaging services                        */
+/* ==================================================================== */
+/************************************************************************/
+
+class kdu_cpl_error_message : public kdu_thread_safe_message
+{
+  public:  // Member classes.
+    using kdu_thread_safe_message::put_text;
+
+    explicit kdu_cpl_error_message( CPLErr eErrClass ) :
+        m_eErrClass(eErrClass),
+        m_pszError(NULL)
+    {}
+
+    void put_text(const char *string) override
+    {
+        if( m_pszError == NULL )
+        {
+            m_pszError = CPLStrdup(string);
+        }
+        else
+        {
+            m_pszError = static_cast<char *>(CPLRealloc(
+                m_pszError, strlen(m_pszError) + strlen(string) + 1));
+            strcat(m_pszError, string);
+        }
+    }
+
+    class JP2KAKException {};
+
+    void flush(bool end_of_message = false) override
+    {
+        kdu_thread_safe_message::flush(end_of_message);
+
+        if( m_pszError == NULL )
+            return;
+        if( m_pszError[strlen(m_pszError) - 1] == '\n' )
+            m_pszError[strlen(m_pszError) - 1] = '\0';
+
+        CPLError(m_eErrClass, CPLE_AppDefined, "%s", m_pszError);
+        CPLFree(m_pszError);
+        m_pszError = NULL;
+
+        if( end_of_message && m_eErrClass == CE_Failure )
+        {
+            throw JP2KAKException();
+        }
+    }
+
+  private:
+    CPLErr m_eErrClass;
+    char *m_pszError;
+};
diff --git a/frmts/jp2kak/subfile_source.h b/frmts/jp2kak/subfile_source.h
index 5e50cd4..38be5f2 100644
--- a/frmts/jp2kak/subfile_source.h
+++ b/frmts/jp2kak/subfile_source.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: subfile_source.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: subfile_source.h 37076 2017-01-09 18:35:44Z goatbar $
  *
  * Project:  JPEG-2000
  * Purpose:  Implements read-only virtual io on a subregion of a file.
@@ -28,44 +28,59 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef JP2KAK_SUBFILE_SOURCE_H
+#define JP2KAK_SUBFILE_SOURCE_H
+
 #include "kdu_file_io.h"
 #include "cpl_error.h"
 #include "cpl_vsi_virtual.h"
 
+#include <assert.h>
+
 #if KDU_MAJOR_VERSION > 7 || (KDU_MAJOR_VERSION == 7 && KDU_MINOR_VERSION >= 5)
     using namespace kdu_core;
     using namespace kdu_supp;
 #endif
 
-#define IO_CHUNK_SIZE 65536L
-#define IO_BUFFER_SIZE 1048576L
+static const long IO_CHUNK_SIZE = 65536L;
+static const long IO_BUFFER_SIZE = 1048576L;
+
 /************************************************************************/
 /*                            subfile_source                            */
 /************************************************************************/
 
 class subfile_source : public kdu_compressed_source {
-
   public:
-    subfile_source() { file = NULL; }
-    ~subfile_source() { close(); }
+    subfile_source() :
+        capabilities(0),
+        subfile_offset(0),
+        subfile_size(0),
+        file(NULL)
+    {}
 
+    ~subfile_source() override { close(); }
 
-    bool exists() { return (file != NULL); }
+    bool exists() const { return (file != NULL); }
 
-    bool operator!() { return (file == NULL); }
+    bool operator!() const { return (file == NULL); }
 
     void open(const char *fname, int bSequential, int bCached )
       {
-          const char *real_filename;
           close();
 
+          const char *real_filename = NULL;
+
           if( EQUALN( fname, "J2K_SUBFILE:",12) )
           {
               char** papszTokens = CSLTokenizeString2(fname + 12, ",", 0);
               if (CSLCount(papszTokens) >= 2)
               {
-                  subfile_offset = (int) CPLScanUIntBig(papszTokens[0], static_cast<int>(strlen(papszTokens[0])));
-                  subfile_size = (int) CPLScanUIntBig(papszTokens[1], static_cast<int>(strlen(papszTokens[1])));
+                  subfile_offset = static_cast<int>(
+                      CPLScanUIntBig(papszTokens[0],
+                                     static_cast<int>(strlen(papszTokens[0]))));
+                  subfile_size = static_cast<int>(
+                      CPLScanUIntBig(papszTokens[1],
+                                     static_cast<int>(strlen(papszTokens[1]))));
               }
               else
               {
@@ -78,14 +93,19 @@ class subfile_source : public kdu_compressed_source {
 
               real_filename = strstr(fname,",");
               if( real_filename != NULL )
+              {
                   real_filename = strstr(real_filename+1,",");
+              }
               if( real_filename != NULL )
+              {
                   real_filename++;
+              }
               else
               {
                   kdu_error e;
 
-                  e << "Could not find filename in subfile definition." << fname;
+                  e << "Could not find filename in subfile definition."
+                      << fname;
                   return;
               }
           }
@@ -107,7 +127,10 @@ class subfile_source : public kdu_compressed_source {
 
           if ( bCached )
           {
-              file = (VSILFILE*)VSICreateCachedFile( (VSIVirtualHandle*)file, IO_CHUNK_SIZE, IO_BUFFER_SIZE );
+              file = reinterpret_cast<VSILFILE *>(
+                  VSICreateCachedFile(
+                      reinterpret_cast<VSIVirtualHandle *>(file),
+                      IO_CHUNK_SIZE, IO_BUFFER_SIZE));
               if( file == NULL )
               {
                   kdu_error e;
@@ -118,16 +141,17 @@ class subfile_source : public kdu_compressed_source {
           }
 
           if( bSequential )
-            capabilities = KDU_SOURCE_CAP_SEQUENTIAL;
+              capabilities = KDU_SOURCE_CAP_SEQUENTIAL;
           else
-            capabilities = KDU_SOURCE_CAP_SEQUENTIAL | KDU_SOURCE_CAP_SEEKABLE;
+              capabilities =
+                  KDU_SOURCE_CAP_SEQUENTIAL | KDU_SOURCE_CAP_SEEKABLE;
 
-          seek( 0 );
+          seek(0);
       }
 
-    int get_capabilities() { return capabilities; }
+    int get_capabilities() override { return capabilities; }
 
-    bool seek(kdu_long offset)
+    bool seek(kdu_long offset) override
       {
           assert(file != NULL);
           if( file == NULL )
@@ -142,26 +166,27 @@ class subfile_source : public kdu_compressed_source {
               return false;
       }
 
-    kdu_long get_pos()
+    kdu_long get_pos() override
       {
         if (file == NULL) return -1;
-        kdu_long result = VSIFTellL( file );
+        kdu_long result = VSIFTellL(file);
         result -= subfile_offset;
         return result;
       }
 
-    int read(kdu_byte *buf, int num_bytes)
+    int read(kdu_byte *buf, int num_bytes) override
       {
         assert(file != NULL);
 
-        num_bytes = static_cast<int>(VSIFReadL(buf,1,(size_t) num_bytes,file));
+        num_bytes = static_cast<int>(
+            VSIFReadL(buf, 1, static_cast<size_t>(num_bytes), file));
         return num_bytes;
       }
 
-    bool close()
+    bool close() override
       {
         if (file != NULL)
-            VSIFCloseL( file );
+            VSIFCloseL(file);
         file = NULL;
         return true;
       }
@@ -174,3 +199,5 @@ class subfile_source : public kdu_compressed_source {
 
     VSILFILE *file;
   };
+
+#endif  // JP2KAK_SUBFILE_SOURCE_H
diff --git a/frmts/jp2kak/vsil_target.h b/frmts/jp2kak/vsil_target.h
index d7929ee..92dd490 100644
--- a/frmts/jp2kak/vsil_target.h
+++ b/frmts/jp2kak/vsil_target.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: subfile_source.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: vsil_target.h 37393 2017-02-16 21:07:25Z rouault $
  *
  * Project:  JPEG-2000
  * Purpose:  Implements VSI*L based writer.
@@ -27,6 +27,9 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef VSIL_TARGET_H
+#define VSIL_TARGET_H
+
 #include "kdu_file_io.h"
 #include "cpl_error.h"
 #include "cpl_vsi.h"
@@ -54,7 +57,7 @@ public:
             }
         }
 
-    bool write(const kdu_byte *buf, int num_bytes)
+    bool write(const kdu_byte *buf, int num_bytes) override
         {
             if( file == NULL )
                 return false;
@@ -65,7 +68,7 @@ public:
                 return true;
         }
 
-    bool start_rewrite(kdu_long backtrack)
+    bool start_rewrite(kdu_long backtrack) override
         {
             if( file == NULL )
                 return false;
@@ -76,7 +79,7 @@ public:
                 return true;
         }
 
-    bool end_rewrite()
+    bool end_rewrite() override
         {
             if( file == NULL )
                 return false;
@@ -87,7 +90,7 @@ public:
                 return true;
         }
 
-    bool close()
+    bool close() override
         {
             if (file != NULL)
                 VSIFCloseL( file );
@@ -98,3 +101,5 @@ public:
 private: // Data
     VSILFILE *file;
 };
+
+#endif // VSIL_TARGET_H
diff --git a/frmts/jp2lura/GNUmakefile b/frmts/jp2lura/GNUmakefile
new file mode 100644
index 0000000..9fcb0ff
--- /dev/null
+++ b/frmts/jp2lura/GNUmakefile
@@ -0,0 +1,22 @@
+include ../../GDALmake.opt
+
+OBJ	=	jp2luracallbacks.o jp2lurarasterband.o jp2luradataset.o
+
+CPPFLAGS	:=	 -DFRMT_jp2lura -I.. $(CPPFLAGS) $(JP2LURA_INCLUDE) $(EXTRA_CFLAGS)
+
+PLUGIN_SO =	gdal_JP2Lura.so
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ) *.so
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+$(OBJ) $(O_OBJ):	jp2luracallbacks.h jp2lurarasterband.h jp2luradataset.h
+
+plugin: $(PLUGIN_SO)
+
+$(PLUGIN_SO):	$(OBJ)
+	$(LD_SHARED) $(LNK_FLAGS) $(OBJ) $(CONFIG_LIBS) $(EXTRA_LIBS) \
+		-o $(PLUGIN_SO)
diff --git a/frmts/jp2lura/frmt_jp2lura.html b/frmts/jp2lura/frmt_jp2lura.html
new file mode 100644
index 0000000..94e2f2d
--- /dev/null
+++ b/frmts/jp2lura/frmt_jp2lura.html
@@ -0,0 +1,291 @@
+<html>
+<head>
+<title>JP2Lura --- JPEG2000 driver based on Lurawave library</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>JP2Lura --- JPEG2000 driver based on Lurawave library</h1>
+
+<p>(GDAL >= 2.2.0)</p>
+
+<p>This driver is an implementation of a JPEG2000 reader/writer based on Lurawave library.</p>
+
+<p>The driver uses the VSI Virtual File API, so it can read JPEG2000 compressed NITF files.</p>
+
+<h2><a name="georeferencing">Georeferencing</a></h2>
+
+<p>
+Georeferencing information can come from different sources : internal (GeoJP2
+or GMLJP2 boxes), worldfile .j2w/.wld sidecar files, or PAM (Persitant Auxiliary metadata)
+.aux.xml sidecar files.
+By default, information is fetched in following order (first listed is the most
+prioritary): PAM, GeoJP2, GMLJP2, WORLDFILE.
+</p>
+<p>The allowed sources
+and their priority order can be changed with the GDAL_GEOREF_SOURCES
+configuration option (or GEOREF_SOURCES open option) whose value is a
+comma-separated list of the following keywords :
+PAM, GEOJP2, GMLJP2, INTERNAL (shortcut for GEOJP2,GMLJP2), WORLDFILE, NONE.
+First mentioned sources are the most prioritary over the next ones. A non mentioned
+source will be ignored.
+</p>
+<p>
+For example setting it to "WORLDFILE,PAM,INTERNAL" will make a geotransformation
+matrix from a potential worldfile prioritary over PAM or internal JP2 boxes.
+Setting it to "PAM,WORLDFILE,GEOJP2" will use the mentioned sources and
+ignore GMLJP2 boxes.
+</p>
+
+<h2>License number</h2>
+
+<p>
+The LURA_LICENSE_NUM_1 and LURA_LICENSE_NUM_2 configuration options / environment
+variables must be set with the 2 numbers that compose a license number.
+</p>
+
+<h2>Option Options</h2>
+
+The following open option is available:
+<ul>
+<li><p><b>GEOREF_SOURCES=string</b>: Define which georeferencing sources are
+allowed and their priority order. See <a href="#georeferencing"><i>Georeferencing</i></a> paragraph.</li>
+</ul>
+
+<h2>Creation Options</h2>
+
+<ul>
+<li><p><b>CODEC=JP2/Codestream</b> : JP2 will add JP2 boxes around the codestream data.
+The value is determined automatically from the file extension. If it's neither
+JP2 nor Codestream, JP2 codec is used.</p></li>
+
+<li> <b>GMLJP2=YES/NO</b>: Indicates whether a GML box
+ conforming to the OGC GML in JPEG2000 specification should be included in the
+file. Unless GMLJP2V2_DEF is used, the version of the GMLJP2 box will be
+version 1. Defaults to YES.<p>
+
+<li> <b>GMLJP2V2_DEF=filename</b>: Indicates whether a GML box
+conforming to the <a href="http://docs.opengeospatial.org/is/08-085r5/08-085r5.html">
+OGC GML in JPEG2000, version 2.0.1</a> specification should be included in the
+file. <i>filename</i> must point to a file with a JSon content that defines how
+the GMLJP2 v2 box should be built. See <a href="frmt_jp2openjpeg.html">JP2OpenJPEG page</a>
+for syntax of the JSon configuration file.
+It is also possible to directly pass the JSon content inlined as a string.
+If filename is just set to YES, a minimal instance will be built.
+<p>
+
+<li> <b>GeoJP2=YES/NO</b>: Indicates whether a
+UUID/GeoTIFF box conforming to the GeoJP2 (GeoTIFF in JPEG2000) specification
+should be included in the file.  Defaults to NO.<p>
+
+<li> <b>SPLIT_IEEE754=YES/NO</b>: Whether encoding of Float32 bands as 3 
+bands with values decomposed according to IEEE-754 struture: first band (1 bit,
+signed) with sign bit, second band (8 bits, unsigned) with exponent value and
+third band (23 bits, unsigned) with mantissa value. Default to NO.
+This is a non-standard extension to encode floating point values.
+By default, the sign bit and exponent will be encoded with the reversible
+wavelet (even with REVERSIBLE=NO), and the mantissa with the irreversible one.
+If specifying REVERSIBLE=YES, all 3 components will be encoded with the
+reversible wavelet.<p>
+
+<li> <b>NBITS=int_value</b> : Bits (precision) for sub-byte
+files (1-7), sub-uint16 (9-15), sub-uint32 (17-28).<p>
+
+<li> <b>QUALITY_STYLE=PSNR/XXSmall/XSmall/Small/Medium/Large/XLarge/XXLarge</b>:
+This property tag is used to set the quality mode to be used during
+lossy compression. For normal images and situations (1:1 pixel display,
+~50 cm viewing distance) we recommend Small or PSNR. For quality 
+measurement only PSNR should be used. Default is PSNR.<p>
+
+<li> <b>SPEED_MODE=Fast/Accurate</b>:
+This property tag is used to set the speed mode to be used
+during lossy compression. The following modes are defined. Default is Fast<p>
+
+<li> <b>RATE=int_value.</b>
+When specifyig this value, the target compressed file size will be 
+the uncompressed file size divided by RATE. In general the 
+achieved rate will be exactly the requested size or a few bytes 
+lower. Will force use of irreversible wavelet.
+Default value: 0 (maximum quality).<p>
+
+<li> <b>QUALITY=1 to 100</b>
+Compression to a particular quality is possible only when using
+the 9-7 filter with the standard expounded quantization and no regions
+of interest. A compression quality may be specified between 1 (low)
+and 100 (high). The size of the resulting JPEG2000 file will depend
+of the image content. Only used for irreversible compression.
+The compression quality cannot be used together
+the property RATE. Default value: 0 (maximum quality).
+When usin this option together with SPLIT_IEEE754=YES, the sign bit and
+exponent bands will have to be switched to irreversible encoding, which can
+lead to huge loss in the reconstructed floating-point value.<p>
+
+<li> <b>PRECISION=int_value</b>
+For improved efficiency, the library automatically, depending on the
+image depth, uses either 16 or 32 bit representation for wavelet
+coefficients. The precision property can be set to force the library
+to always use 32 bit representations. The use of 32 bit values may
+slightly improve image quality and the expense of speed and memory
+requirements. Default value: 0 (automatically select appropriate precision).<p>
+
+<li><p><b>REVERSIBLE=YES/NO</b> : YES means use of reversible 5x3 integer-only
+filter, NO use of the irreversible DWT 9-7. Defaults to NO.</p></li>
+
+<li><p><b>LEVELS=int_value</b> (0-16) :
+The number of wavelet transformation levels can be set using this
+property. Valid values are in the range 0 (no wavelet analysis) to
+16 (very fine analysis). The memory requirements and compression time
+increases with the number of transformation levels. A reasonable
+number of transformation levels is in the 4-6 range. Default is 5.</p></li>
+
+<li><p><b>QUANTIZATION_STYLE=DERIVED/EXPOUNDED</b> :
+This property may only be set when the irreversible filter (9_7) is
+used. The quantization steps can either be derived from a bases
+quantization step, DERIVED, or calculated for each image sub-band,
+EXPOUNDED. The EXPOUNDED style is recommended when using the
+irreversible filter. Default is EXPOUNDED.</p></li>
+
+<li><p><b>TILEXSIZE=int_value</b> : Tile width.
+An image can  be split into smaller tiles, with each
+tile independently compressed. The basic tile size and the offset to
+the first tile on the virtual compression reference grid can be set
+using these properties. The first tile must contain the first image
+pixel. The tiling of an image is recommended only for very large
+images. Default values: (0) One Tile containing the complete image.
+If the image dimension exceeds 15000x15000, it will be tiled with tiles
+of dimension 1024x1024.</p></li>
+
+<li><p><b>TILEYSIZE=int_value</b> : Tile height.
+An image can  be split into smaller tiles, with each
+tile independently compressed. The basic tile size and the offset to
+the first tile on the virtual compression reference grid can be set
+using these properties. The first tile must contain the first image
+pixel. The tiling of an image is recommended only for very large
+images. Default values: (0) One Tile containing the complete image.
+If the image dimension exceeds 15000x15000, it will be tiled with tiles
+of dimension 1024x1024.</p></li>
+
+<li><p><b>TLM=YES/NO</b>: (TiLe Marker)
+The efficiency of decoding regions in a tiled image may be improved by "
+the usage of a tile length marker. Tile length markers contain the "
+position of each tile in a JPEG2000 codestream, enabling faster access "
+to tiled data. Default is NO.</p></li>
+
+<li><p><b>PROGRESSION=LRCP/RLCP/RPCL/PCRL/CPRL</b> : The organization of the
+coded data in the file can be set by this  property tag. The following progression
+orders are defined: LRCP = Quality progressive, LCP = Resolution then quality
+progressive, RPCL = Resolution then position progressive,  PCRL = Position
+progressive, CPRL = Color/channel progressive. The setting LRCP (quality) is
+most useful when used with several layers. The PCRL (position) should be used
+with precincts. Defaults to LRCP.</p></li>
+
+<li><p><b>JPX=YES/NO</b>: Whether to advertize JPX features, and
+add a Reader requirement box, when a GMLJP2 box is written (for GMLJP2 v2,
+the branding will also be "jpx "). Defaults to YES.
+This option should not be used unless compatibility problems with a reader
+occur.</p></li>
+
+<li><p><b>CODEBLOCK_WIDTH=int_value</b>:
+Codeblock width: power of two value between 4 and 1024. Defaults to 64.
+Note that CODEBLOCK_WIDTH * CODEBLOCK_HEIGHT must not be greater than 4096.
+For PROFILE_1 compatibility, CODEBLOCK_WIDTH must not be greater than 64.
+</p></li>
+
+<li><p><b>CODEBLOCK_HEIGHT=int_value</b>:
+Codeblock height: power of two value between 4 and 1024. Defaults to 64.
+Note that CODEBLOCK_WIDTH * CODEBLOCK_HEIGHT must not be greater than 4096.
+For PROFILE_1 compatibility, CODEBLOCK_HEIGHT must not be greater than 64.
+</p></li>
+
+<li><p><b>ERROR_RESILIENCE=YES/NO</b>:
+This option improves error resilient in JPEG2000 streams or for
+special codecs (e.g. hardware coder) for a faster compression/
+decompression. This option will increase the file size slightly when
+generating a code stream with the same image quality. Default is NO.</p></li>
+
+<li><p><b>WRITE_METADATA=YES/NO</b>: Whether metadata should be
+written, in a dedicated JP2 'xml ' box. Defaults to NO.
+The content of the 'xml ' box will be like:
+<pre>
+<GDALMultiDomainMetadata>
+  <Metadata>
+    <MDI key="foo">bar</MDI>
+  </Metadata>
+  <Metadata domain='aux_domain'>
+    <MDI key="foo">bar</MDI>
+  </Metadata>
+  <Metadata domain='a_xml_domain' format='xml'>
+    <arbitrary_xml_content>
+    </arbitrary_xml_content>
+  </Metadata>
+</GDALMultiDomainMetadata>
+</pre>
+If there are metadata domain whose name starts with "xml:BOX_", they will be
+written each as separate JP2 'xml ' box.<p>
+If there is a metadata domain whose name is "xml:XMP", its content will be
+written as a JP2 'uuid' XMP box.<p>
+</p></li>
+
+<li><p><b>MAIN_MD_DOMAIN_ONLY=YES/NO</b>:
+(Only if WRITE_METADATA=YES) Whether only metadata from the main domain should
+be written. Defaults to NO.
+</p></li>
+
+<li><p><b>USE_SRC_CODESTREAM=YES/NO</b>:
+(EXPERIMENTAL!) When source dataset is JPEG2000, whether to reuse the codestream
+of the source dataset unmodified. Defaults to NO. Note that enabling that feature might result
+in inconsistent content of the JP2 boxes w.r.t. to the content of the source codestream.
+Most other creation options will be ignored in that mode. Can be useful in some
+use cases when adding/correcting georeferencing, metadata, ... 
+</p></li>
+
+</ul>
+
+<h3>Lossless compression</h3>
+
+Lossless compression can be achieved if REVERSIBLE=YES is used (and RATE is
+not specified).
+
+<h2>Vector information</h2>
+
+A JPEG2000 file containing a GMLJP2 v2 box with GML feature
+collections and/or KML annotations embedded can be opened as a vector file with
+the OGR API.
+
+For example:
+<pre>
+ogrinfo -ro my.jp2
+
+INFO: Open of my.jp2'
+      using driver `JP2Lura' successful.
+1: FC_GridCoverage_1_rivers (LineString)
+2: FC_GridCoverage_1_borders (LineString)
+3: Annotation_1_poly
+</pre>
+
+<p>Feature collections can be linked from the GMLJP2 v2 box to a remote location.
+By default, the link is not followed. It will be followed if the open option
+OPEN_REMOTE_GML is set to YES.</p>
+
+<h2>Bugs</h2>
+
+<p>Proper support of JPEG-2000 images with Int32/UInt32/Float32-IEEE754-split
+on Linux 64 bits require a v2.1.00.17 or later SDK.</p>
+
+<h2>See Also:</h2>
+
+<ul>
+<li><p> <a href="https://www.luratech.com/en/solutions/applications/data-compression-imaging-with-jpeg-2000/">LuraTech JPEG-2000 SDK<a></p></li>
+</ul>
+
+Other JPEG2000 GDAL drivers :
+<ul>
+<li><p> <a href="frmt_jp2openjpeg.html">JP2OpenJPEG: based on Openjpeg library (open source)</a></p></li>
+<li><p> <a href="frmt_jpeg2000.html">JPEG2000: based on Jasper library (open source)</a></p></li>
+<li><p> <a href="frmt_jp2ecw.html">JP2ECW: based on Erdas ECW library (proprietary)</a></p></li>
+<li><p> <a href="frmt_jp2mrsid.html">JP2MRSID: based on LizardTech MrSID library (proprietary)</a></p></li>
+<li><p> <a href="frmt_jp2kak.html">JP2KAK: based on Kakadu library (proprietary)</a></p></li>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/jp2lura/jp2luracallbacks.cpp b/frmts/jp2lura/jp2luracallbacks.cpp
new file mode 100644
index 0000000..0509ba6
--- /dev/null
+++ b/frmts/jp2lura/jp2luracallbacks.cpp
@@ -0,0 +1,502 @@
+/******************************************************************************
+ * Project:  GDAL
+ * Author:   Raul Alonso Reyes <raul dot alonsoreyes at satcen dot europa dot eu>
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ * Purpose:  JPEG-2000 driver based on Lurawave library, driver developed by SatCen
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, SatCen - European Union Satellite Centre
+ * Copyright (c) 2016, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_port.h"
+
+#include "lwf_jp2.h"
+
+#include "jp2luracallbacks.h"
+
+#ifdef ENABLE_MEMORY_REGISTRAR
+JP2LuraMemoryRegistrar::JP2LuraMemoryRegistrar()
+{
+}
+
+JP2LuraMemoryRegistrar::~JP2LuraMemoryRegistrar()
+{
+    CPLDebug("JP2Lura",
+             "JP2LuraMemoryRegistrar: %d block allocated leaked", 
+             static_cast<int>(oMap.size()));
+    std::map<void*, size_t>::const_iterator oIter = oMap.begin();
+    for( ; oIter != oMap.end(); ++oIter )
+    {
+        CPLDebug("JP2Lura", "force freeing %d bytes", 
+                 static_cast<int>(oIter->second));
+        VSIFree(oIter->first);
+    }
+}
+
+void JP2LuraMemoryRegistrar::Register(size_t nSize, void* ptr)
+{
+    CPLAssert( oMap.find(ptr) == oMap.end() );
+    oMap[ptr] = nSize;
+}
+
+void JP2LuraMemoryRegistrar::Unregister(void* ptr)
+{
+    CPLAssert( oMap.find(ptr) != oMap.end() );
+    oMap.erase(ptr);
+}
+#endif // ENABLE_MEMORY_REGISTRAR
+
+/************************************************************************/
+/*                    GDALJP2Lura_Callback_Malloc()                     */
+/************************************************************************/
+
+void *  JP2_Callback_Conv  GDALJP2Lura_Callback_Malloc(size_t size,
+                                            JP2_Callback_Param 
+#ifdef ENABLE_MEMORY_REGISTRAR
+                                                                lParam
+#endif
+                                                       )
+{
+    void* ptr = VSIMalloc(size);
+#ifdef ENABLE_MEMORY_REGISTRAR
+    if( lParam && ptr )
+    {
+        ((JP2LuraMemoryRegistrar*)lParam)->Register(size, ptr);
+    }
+#endif
+    return ptr;
+}
+
+
+/************************************************************************/
+/*                    GDALJP2Lura_Callback_Free()                       */
+/************************************************************************/
+
+JP2_Error  JP2_Callback_Conv  GDALJP2Lura_Callback_Free(void *ptr,
+                                            JP2_Callback_Param 
+#ifdef ENABLE_MEMORY_REGISTRAR
+                                                                lParam
+#endif
+                                                       )
+{
+#ifdef ENABLE_MEMORY_REGISTRAR
+    if( lParam && ptr )
+    {
+        ((JP2LuraMemoryRegistrar*)lParam)->Unregister(ptr);
+    }
+#endif
+    VSIFree(ptr);
+    return cJP2_Error_OK;
+}
+
+
+/************************************************************************/
+/*                  GDALJP2Lura_Callback_Decompress_Read()              */
+/************************************************************************/
+
+unsigned long  JP2_Callback_Conv  GDALJP2Lura_Callback_Decompress_Read(
+                                                    unsigned char  *pucData,
+                                                    unsigned long   ulPos,
+                                                    unsigned long   ulSize,
+                                                    JP2_Callback_Param lParam)
+{
+    VSILFILE* fp = reinterpret_cast<VSILFILE*>(lParam);
+
+    if (VSIFSeekL(fp, ulPos, SEEK_SET) != 0)
+    {
+        return 0;
+    }
+
+    return static_cast<unsigned long>(
+            VSIFReadL(pucData, 1, static_cast<size_t>(ulSize), fp));
+}
+
+/************************************************************************/
+/*                          splitIEEE754Float()                         */
+/************************************************************************/
+
+typedef union {
+    float f;
+    unsigned int ui;
+} float_uint_union;
+
+static void splitIEEE754Float(float f, unsigned int *mantissa, int *exponent,
+                              int *sign)
+{
+    float_uint_union x;
+    x.f = f;
+
+    if (x.ui & 0x80000000)
+        *sign = 1;
+    else
+        *sign = 0;
+
+    *mantissa = x.ui & 0x07FFFFF;
+
+    *exponent = (x.ui >> 23) & 0xFF;
+}
+
+/************************************************************************/
+/*                           setIIIE754Sign()                           */
+/************************************************************************/
+
+static void setIIIE754Sign(float_uint_union* f, unsigned char sign)
+{
+    if (!sign)
+        f->ui = (f->ui & 0x7FFFFFFFU);
+    else
+        f->ui = (f->ui & 0x7FFFFFFFU) | 0x80000000U;
+}
+
+/************************************************************************/
+/*                         setIIIE754Exponent()                         */
+/************************************************************************/
+
+static void setIIIE754Exponent(float_uint_union* f, unsigned char exponent)
+{
+    f->ui = (f->ui & 0x807fffffU) | (exponent << 23);
+}
+
+/************************************************************************/
+/*                         setIIIE754Mantissa()                         */
+/************************************************************************/
+
+static void setIIIE754Mantissa(float_uint_union* f, unsigned int mantissa)
+{
+    f->ui = (f->ui & (0xFF800000U)) | mantissa;
+}
+
+/************************************************************************/
+/*                 GDALJP2Lura_Callback_Decompress_Write()              */
+/************************************************************************/
+
+JP2_Error  JP2_Callback_Conv  GDALJP2Lura_Callback_Decompress_Write(
+                                    unsigned char*  pucData,
+                                    short           sComponent,
+                                    unsigned long   ulRow,
+                                    unsigned long   ulStart, // starting pixel
+                                    unsigned long   ulNum, // number of pixels
+                                    JP2_Callback_Param   lParam)
+{
+#ifdef DEBUG_VERBOSE
+    CPLDebug("JP2Lura", "Decompress(%d, %lu, %lu, %lu)",
+             sComponent, ulRow, ulStart, ulNum);
+#endif
+
+    GDALJP2Lura_Output_Data* pOutputData =
+                    reinterpret_cast<GDALJP2Lura_Output_Data*>(lParam);
+
+    CPLAssert(ulRow < static_cast<unsigned long>(pOutputData->nBufYSize));
+    CPLAssert(ulStart + ulNum <=
+                        static_cast<unsigned long>(pOutputData->nBufXSize));
+
+    long lBps = 0;
+    /****************************************************/
+    /*  convert from component index to channel index   */
+    /*  i.e. index after expanding any palette samples  */
+    /****************************************************/
+    if (pOutputData->lBps==0) //float
+    {
+        switch (sComponent)
+        {
+            case 0:
+            case 1:
+            case 2:
+            {
+                lBps = 32;
+                break;
+            }
+
+            default:
+                return cJP2_Error_Write_Callback_Undefined;
+        }
+    }
+    else
+    {
+        lBps = pOutputData->lBps;
+    }
+
+    unsigned char* pucImageData;  // buffer for decompressed image stripe
+
+    if (pOutputData->lBps == 0)
+        pucImageData = pOutputData->pimage;
+    else
+    {
+        if( sComponent >= pOutputData->nBands )
+        {
+            // Ignored component
+            return cJP2_Error_OK;
+        }
+        if (sComponent != pOutputData->nBand - 1)
+        {
+            pucImageData = pOutputData->pDatacache[sComponent];
+
+        }
+        else
+        {
+            pucImageData = pOutputData->pimage;
+        }
+    }
+
+
+    /***********************************/
+    /* number of bytes for each sample */
+    /***********************************/
+
+    unsigned long ulBytesFromLura = ((lBps + 7) >> 3);
+    unsigned long ulBytesrequest =
+                            GDALGetDataTypeSizeBytes(pOutputData->eBufType);
+
+    /* distance between samples of the same channel */
+
+    unsigned long ulSkip = ulBytesrequest;
+
+    unsigned long ulOffset = (pOutputData->nBufXSize * ulSkip) * ulRow +
+                ulStart * ulSkip;
+
+    unsigned char* pucStart = pucImageData + ulOffset;
+    if (pOutputData->lBps == 0)
+    {
+#ifdef DEBUG_VERBOSE
+        CPLString osLineValues;
+#endif
+        const unsigned int nSpaceMantissa = 4;
+        for (unsigned long i = 0; i < ulNum; i++)
+        {
+            float_uint_union* f = (float_uint_union*)(&pucStart[i*4]);
+            if (sComponent == 0)
+            {
+#ifdef DEBUG_VERBOSE
+                osLineValues += CPLSPrintf("%02X ", *pucData);
+#endif
+                setIIIE754Sign(f, (*pucData == 0) ? 0 : 1); 
+                pucData++;
+            }
+            else if (sComponent == 1)
+            {
+#ifdef DEBUG_VERBOSE
+                osLineValues += CPLSPrintf("%02X ", *pucData);
+#endif
+                setIIIE754Exponent(f, *pucData);
+                pucData++;
+            }
+            else if (sComponent == 2)
+            {
+                unsigned int mantissa = *(unsigned int*)pucData;
+#ifdef DEBUG_VERBOSE
+                osLineValues += CPLSPrintf("%02X ",mantissa);
+#endif
+                setIIIE754Mantissa(f, mantissa);
+                pucData += nSpaceMantissa;
+            }
+        }
+#ifdef DEBUG_VERBOSE
+        CPLDebug("JP2Lura", "Component %d: %s", sComponent,
+                 osLineValues.c_str());
+#endif
+    }
+    else
+    {
+        memcpy(pucStart, pucData, ulBytesFromLura * ulNum);
+    }
+
+
+    return cJP2_Error_OK;
+}
+
+
+/************************************************************************/
+/*                 GDALJP2Lura_Callback_Compress_Write()                */
+/************************************************************************/
+
+JP2_Error  JP2_Callback_Conv  GDALJP2Lura_Callback_Compress_Write(
+                                        unsigned char           *pucData,
+                                        unsigned long           ulPos,
+                                        unsigned long           ulSize,
+                                        JP2_Callback_Param      lParam)
+{
+    JP2_Gdal_Stream_Data* data =
+                            reinterpret_cast<JP2_Gdal_Stream_Data*>(lParam);
+
+    if (VSIFSeekL(data->fp, (vsi_l_offset)(ulPos + data->Position),
+                  SEEK_SET) != 0)
+    {
+        return cJP2_Error_Failure_Write;
+    }
+    if (VSIFWriteL(pucData, 1, (vsi_l_offset)ulSize, data->fp) != ulSize)
+    {
+        return cJP2_Error_Failure_Write;
+    }
+
+    return cJP2_Error_OK;
+}
+
+/************************************************************************/
+/*                 GDALJP2Lura_Callback_Compress_Read()                 */
+/************************************************************************/
+
+JP2_Error  JP2_Callback_Conv  GDALJP2Lura_Callback_Compress_Read(
+                                            unsigned char*      pucData,
+                                            short               sComponent,
+                                            unsigned long       ulRow,
+                                            unsigned long       ulStart,
+                                            unsigned long       ulNum,
+                                            JP2_Callback_Param  lParam)
+{
+    GDALJP2Lura_Input_Data* idata =
+                            reinterpret_cast<GDALJP2Lura_Input_Data*>(lParam);
+    GDALDataset* poSrcDS = idata->poSrcDS;
+    const int  nBands = poSrcDS->GetRasterCount();
+    const int  nYSize = poSrcDS->GetRasterYSize();
+
+    GDALProgressFunc pfnProgress = idata->pfnProgress;
+    void * pProgressData = idata->pProgressData;
+
+    if( ulStart == 0 && pfnProgress &&
+        !pfnProgress(static_cast<double>(ulRow+1)/nYSize, "", pProgressData) )
+    {
+        return cJP2_Error_Read_Callback_Undefined;
+    }
+
+    GDALRasterBand  *poBand;
+    if (nBands == 1 &&
+        poSrcDS->GetRasterBand(1)->GetRasterDataType() == GDT_Float32)
+    {
+        poBand = poSrcDS->GetRasterBand(1);
+    }
+    else
+    {
+        poBand = poSrcDS->GetRasterBand(sComponent + 1);
+    }
+    GDALDataType eDataType = poBand->GetRasterDataType();
+
+    unsigned long ulBpsRead = 0;
+    switch (eDataType)
+    {
+        case GDT_Byte:
+        {
+            ulBpsRead = 8;
+            //Signed = 0;
+            break;
+        }
+        case GDT_UInt16:
+        {
+            ulBpsRead = 16;
+            //Signed = 0;
+            break;
+        }
+        case GDT_Int16:
+        {
+            ulBpsRead = 16;
+            //Signed = 1;
+            break;
+        }
+        case GDT_UInt32:
+        {
+            ulBpsRead = 32;
+            //Signed = 0;
+            break;
+        }
+        case GDT_Int32:
+        {
+            ulBpsRead = 32;
+            //Signed = 1;
+            break;
+        }
+        case GDT_Float32:
+        {
+            ulBpsRead = 32;
+            //Signed = 1;
+            break;
+        }
+
+        default:
+            break;
+    }
+
+    unsigned long ulBytes = (ulBpsRead <= 8) ? 1 : ((ulBpsRead > 16) ? 4 : 2);
+    unsigned long ulRowBytes = ulBytes * ulNum;
+
+    /* malloc of the row*/
+    unsigned char *pucPos = reinterpret_cast<unsigned char*>(
+                                                        VSIMalloc(ulRowBytes));
+    if (pucPos == NULL)
+    {
+        return cJP2_Error_Failure_Malloc;
+    }
+
+    /* check scanlines already read */
+    CPLErr err = poBand->RasterIO(GF_Read,
+                                  static_cast<int>(ulStart),
+                                  static_cast<int>(ulRow),
+                                  static_cast<int>(ulNum), 1,
+                                  pucPos,
+                                  static_cast<int>(ulNum), 1,
+                                  eDataType, 0, 0, NULL);
+    if (err != CE_None)
+    {
+        VSIFree(pucPos);
+        return cJP2_Error_Read_Callback_Undefined;
+    }
+
+    /* deliver the requested pixels to the library */
+    if (nBands == 1 && eDataType == GDT_Float32 )
+    {
+        unsigned int mantissa;
+        int exponent;
+        int sign;
+
+        const unsigned long nSpaceMantissa = 4;
+        for (int i = 0; i < (int) ulNum; i++)
+        {
+            float *ptr = (float*)(&pucPos[i * 4]);
+            splitIEEE754Float(*ptr, &mantissa, &exponent, &sign);
+            switch (sComponent)
+            {
+                case 0:
+                {
+                    pucData[i] = (sign) ? 255 : 0;
+                    break;
+                }
+                case 1:
+                {
+                    pucData[i] = static_cast<unsigned char>(exponent);
+                    break;
+                }
+                case 2:
+                {
+                    *reinterpret_cast<unsigned int*>(
+                                pucData + i * nSpaceMantissa) = mantissa;
+                    break;
+                }
+            }
+        }
+    }
+    else
+    {
+        memcpy(pucData, pucPos, ulBytes * ulNum);
+    }
+
+    VSIFree(pucPos);
+
+    return cJP2_Error_OK;
+}
diff --git a/frmts/jp2lura/jp2luracallbacks.h b/frmts/jp2lura/jp2luracallbacks.h
new file mode 100644
index 0000000..c20b44b
--- /dev/null
+++ b/frmts/jp2lura/jp2luracallbacks.h
@@ -0,0 +1,127 @@
+/******************************************************************************
+ * Project:  GDAL
+ * Author:   Raul Alonso Reyes <raul dot alonsoreyes at satcen dot europa dot eu>
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ * Purpose:  JPEG-2000 driver based on Lurawave library, driver developed by SatCen
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, SatCen - European Union Satellite Centre
+ * Copyright (c) 2016, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef JP2LURACALLBACKS_H_INCLUDED
+#define JP2LURACALLBACKS_H_INCLUDED
+
+#include "gdal_priv.h"
+
+#include "lwf_jp2.h"
+
+#ifdef ENABLE_MEMORY_REGISTRAR
+#include <map>
+class JP2LuraMemoryRegistrar
+{
+    std::map<void*, size_t> oMap;
+public:
+    JP2LuraMemoryRegistrar();
+    ~JP2LuraMemoryRegistrar();
+
+    void Register(size_t nSize, void* ptr);
+    void Unregister(void* ptr);
+};
+#endif // ENABLE_MEMORY_REGISTRAR
+
+typedef struct
+{
+    JP2_Decomp_Handle   handle;     // JP2 decompression handle
+
+    long                lBps;       // bits for each sample
+    bool                bSigned;    // are the samples signed?
+
+    JP2_Palette_Params      *pPalette;  // pointer to optional palette. Not to be freed
+    JP2_Channel_Def_Params  *pChannelDefs; // pointer to channel def. Not to be freed
+    unsigned long       ulChannelDefs;   // number of channel def entries
+
+    // to preserve a cache
+    int              nBand; // starting at 1
+    int              nBands;
+    GDALDataType     eBufType;
+    int              nXOff;
+    int              nYOff;
+    int              nXSize;
+    int              nYSize;
+    unsigned char ** pDatacache;
+    int              nBufXSize;
+    int              nBufYSize;
+
+
+    unsigned char* pimage;
+} GDALJP2Lura_Output_Data;
+
+typedef struct
+{
+    GDALDataset *poSrcDS;
+    bool bLinux64Hack; // whether the Lura SDK use 8 bytes to space 32bit samples
+
+    GDALProgressFunc pfnProgress; // to progress report
+    void * pProgressData; // to progress report
+} GDALJP2Lura_Input_Data;
+
+typedef struct
+{
+    vsi_l_offset Position;
+    VSILFILE* fp;
+} JP2_Gdal_Stream_Data;
+
+void *  JP2_Callback_Conv  GDALJP2Lura_Callback_Malloc(size_t size,
+                                                    JP2_Callback_Param lParam);
+
+JP2_Error  JP2_Callback_Conv  GDALJP2Lura_Callback_Free(void *ptr,
+                                                    JP2_Callback_Param lParam);
+
+unsigned long  JP2_Callback_Conv  GDALJP2Lura_Callback_Decompress_Read(
+                                                    unsigned char  *pucData,
+                                                    unsigned long   ulPos,
+                                                    unsigned long   ulSize,
+                                                    JP2_Callback_Param lParam);
+
+extern JP2_Error JP2_Callback_Conv GDALJP2Lura_Callback_Decompress_Write(
+                                    unsigned char*  pucData,
+                                    short           sComponent,
+                                    unsigned long   ulRow,
+                                    unsigned long   ulStart, // starting pixel
+                                    unsigned long   ulNum, // number of pixels
+                                    JP2_Callback_Param   lParam);
+
+extern JP2_Error  JP2_Callback_Conv  GDALJP2Lura_Callback_Compress_Write(
+                                        unsigned char           *pucData,
+                                        unsigned long           ulPos,
+                                        unsigned long           ulSize,
+                                        JP2_Callback_Param      lParam);
+
+extern JP2_Error  JP2_Callback_Conv  GDALJP2Lura_Callback_Compress_Read(
+                                            unsigned char*      pucData,
+                                            short               sComponent,
+                                            unsigned long       ulRow,
+                                            unsigned long       ulStart,
+                                            unsigned long       ulNum,
+                                            JP2_Callback_Param  lParam);
+
+#endif
\ No newline at end of file
diff --git a/frmts/jp2lura/jp2luradataset.cpp b/frmts/jp2lura/jp2luradataset.cpp
new file mode 100644
index 0000000..ba29f21
--- /dev/null
+++ b/frmts/jp2lura/jp2luradataset.cpp
@@ -0,0 +1,2689 @@
+/******************************************************************************
+ * Project:  GDAL
+ * Author:   Raul Alonso Reyes <raul dot alonsoreyes at satcen dot europa dot eu>
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ * Purpose:  JPEG-2000 driver based on Lurawave library, driver developed by SatCen
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, SatCen - European Union Satellite Centre
+ * Copyright (c) 2014-2016, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_port.h"
+
+#include "lwf_jp2.h"
+#include "jp2luradataset.h"
+#include "jp2luracallbacks.h"
+#include "jp2lurarasterband.h"
+#include "gdaljp2abstractdataset.h"
+#include "cpl_string.h"
+#include "gdaljp2metadata.h"
+#include "vrt/vrtdataset.h"
+
+extern "C" CPL_DLL void GDALRegister_JP2Lura();
+
+static vsi_l_offset JP2LuraFindCodeStream(VSILFILE* fp,
+                                              vsi_l_offset* pnLength);
+
+/************************************************************************/
+/*                         FloorPowerOfTwo()                            */
+/************************************************************************/
+
+static int FloorPowerOfTwo(int nVal)
+{
+    int nBits = 0;
+    while( nVal > 1 )
+    {
+        nBits ++;
+        nVal >>= 1;
+    }
+    return 1 << nBits;
+}
+
+/************************************************************************/
+/*                         GetErrorMessage()                            */
+/************************************************************************/
+
+#define ERROR_TUPLE(x) { x, #x }
+
+static const struct
+{
+    int nErrorCode;
+    const char* szErrorText;
+}
+asErrorText[] =
+{
+    ERROR_TUPLE(cJP2_Error_Failure_Malloc),
+    ERROR_TUPLE(cJP2_Error_Failure_Read),
+    ERROR_TUPLE(cJP2_Error_Failure_Write),
+    ERROR_TUPLE(cJP2_Error_Invalid_Handle),
+    ERROR_TUPLE(cJP2_Error_Invalid_Pointer),
+    ERROR_TUPLE(cJP2_Error_Invalid_Number_Of_Components),
+    ERROR_TUPLE(cJP2_Error_Invalid_Component_Index),
+    ERROR_TUPLE(cJP2_Error_Invalid_Property_Value),
+    ERROR_TUPLE(cJP2_Error_Invalid_Property_Key),
+    ERROR_TUPLE(cJP2_Error_Invalid_Width),
+    ERROR_TUPLE(cJP2_Error_Invalid_Height),
+    ERROR_TUPLE(cJP2_Error_Invalid_Bits_Per_Sample),
+    ERROR_TUPLE(cJP2_Error_Invalid_Tile_Arrangement),
+    ERROR_TUPLE(cJP2_Error_Invalid_Colorspace),
+    ERROR_TUPLE(cJP2_Error_Invalid_Component_Dimensions),
+    ERROR_TUPLE(cJP2_Error_Invalid_Tile_Index),
+    ERROR_TUPLE(cJP2_Error_Invalid_Resolution_Level),
+    ERROR_TUPLE(cJP2_Error_Invalid_Wavelet_Filter_Combination),
+    ERROR_TUPLE(cJP2_Error_Invalid_Stream),
+    ERROR_TUPLE(cJP2_Error_Single_Value_For_All_Components),
+    ERROR_TUPLE(cJP2_Error_Single_Value_For_All_Tiles),
+    ERROR_TUPLE(cJP2_Error_Read_Only_Property),
+    ERROR_TUPLE(cJP2_Error_Set_Only_Property),
+    ERROR_TUPLE(cJP2_Error_Quality_Compression_Mode),
+    ERROR_TUPLE(cJP2_Error_Decompression_Only_Property),
+    ERROR_TUPLE(cJP2_Error_Compression_Only_Property),
+    ERROR_TUPLE(cJP2_Error_Bits_Per_Sample_Too_High),
+    ERROR_TUPLE(cJP2_Error_Input_Callback_Undefined),
+    ERROR_TUPLE(cJP2_Error_Write_Callback_Undefined),
+    ERROR_TUPLE(cJP2_Error_Read_Callback_Undefined),
+    ERROR_TUPLE(cJP2_Error_Cannot_Find_Suitable_Grid),
+    ERROR_TUPLE(cJP2_Error_Byte_Compression_Mode),
+    ERROR_TUPLE(cJP2_Error_Requested_File_Size_Too_Small),
+    ERROR_TUPLE(cJP2_Error_Invalid_Sample_Rate),
+    ERROR_TUPLE(cJP2_Error_Not_Yet_Supported),
+    ERROR_TUPLE(cJP2_Error_Trial_Time_Expired),
+    ERROR_TUPLE(cJP2_Error_Invalid_Quantization_Filter_Pair),
+    ERROR_TUPLE(cJP2_Error_Invalid_Precinct_Dimensions),
+    ERROR_TUPLE(cJP2_Error_ROI_Shift_Failed),
+    ERROR_TUPLE(cJP2_Error_Scale_Factor_Is_Too_Large),
+    ERROR_TUPLE(cJP2_Error_Invalid_Resolution),
+    ERROR_TUPLE(cJP2_Error_Invalid_Resolution_Unit),
+    ERROR_TUPLE(cJP2_Error_Invalid_Resolution_Type),
+    ERROR_TUPLE(cJP2_Error_Max_Number_Of_ROIs_Reached),
+    ERROR_TUPLE(cJP2_Error_More_Bytes_Required),
+    ERROR_TUPLE(cJP2_Error_Decompression_Cancelled),
+    ERROR_TUPLE(cJP2_Error_File_Format_Required),
+    ERROR_TUPLE(cJP2_Error_JPX_File_Format_Required),
+    ERROR_TUPLE(cJP2_Error_Invalid_Meta_Data_Box_Index),
+    ERROR_TUPLE(cJP2_Error_Invalid_Color_Spec_Index),
+    ERROR_TUPLE(cJP2_Error_Invalid_ICC_Profile),
+    ERROR_TUPLE(cJP2_Error_Use_SetICC_Function),
+    ERROR_TUPLE(cJP2_Error_Use_SetLAB_Function),
+    ERROR_TUPLE(cJP2_Error_Missing_Palette),
+    ERROR_TUPLE(cJP2_Error_Invalid_Palette),
+    ERROR_TUPLE(cJP2_Error_Missing_Component_Mapping),
+    ERROR_TUPLE(cJP2_Error_Invalid_Component_Mapping),
+    ERROR_TUPLE(cJP2_Error_Invalid_Channel_Definition),
+    ERROR_TUPLE(cJP2_Error_Use_SetPalette),
+    ERROR_TUPLE(cJP2_Error_Transcoding_Finished),
+    ERROR_TUPLE(cJP2_Error_Transcode_Scale_Palette_Images),
+    ERROR_TUPLE(cJP2_Error_Invalid_Region),
+    ERROR_TUPLE(cJP2_Error_Lossless_Compression_Mode),
+    ERROR_TUPLE(cJP2_Error_Maximum_Box_Size_Exceeded),
+    ERROR_TUPLE(cJP2_Error_Invalid_Label),
+    ERROR_TUPLE(cJP2_Error_Invalid_Header),
+    ERROR_TUPLE(cJP2_Error_Incompatible_Format),
+    ERROR_TUPLE(cJP2_Error_Invalid_Marker),
+    ERROR_TUPLE(cJP2_Error_Corrupt_Packet),
+    ERROR_TUPLE(cJP2_Error_Invalid_Marker_Segment),
+
+    ERROR_TUPLE(cJP2_Error_Invalid_License),
+    ERROR_TUPLE(cJP2_Error_License_Level_Too_Low),
+
+    ERROR_TUPLE(cJP2_Error_Fatal),
+
+    ERROR_TUPLE(cJP2_Warning_Unable_To_Read_All_Data),
+};
+
+const char* JP2LuraDataset::GetErrorMessage( long nErrorCode )
+{
+    for( size_t i = 0; i < CPL_ARRAYSIZE(asErrorText); ++i )
+    {
+        if( asErrorText[i].nErrorCode == nErrorCode )
+            return asErrorText[i].szErrorText;
+    }
+    return CPLSPrintf("unknown error %ld", nErrorCode);
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                           JP2LuraDataset                              */
+/* ==================================================================== */
+/************************************************************************/
+
+/************************************************************************/
+/*                        JP2LuraDataset()                              */
+/************************************************************************/
+
+JP2LuraDataset::JP2LuraDataset()
+{
+    fp = NULL;
+    iLevel = 0;
+    nOverviewCount = 0;
+    papoOverviewDS = NULL;
+    memset(&sOutputData, 0, sizeof(sOutputData));
+    poCT = NULL;
+    eColorspace = cJP2_Colorspace_Gray;
+    nRedIndex = -1;
+    nGreenIndex = -1;
+    nBlueIndex = -1;
+    nAlphaIndex = -1;
+}
+
+/************************************************************************/
+/*                         ~JP2LuraDataset()                            */
+/************************************************************************/
+
+JP2LuraDataset::~JP2LuraDataset()
+
+{
+    if (papoOverviewDS)
+    {
+            for (int i = 0; i < nOverviewCount; i++)
+                    delete papoOverviewDS[i];
+            CPLFree(papoOverviewDS);
+            papoOverviewDS = NULL;
+    }
+
+    if( sOutputData.pDatacache )
+    {
+        for( int i = 0; i < nBands; ++i )
+            VSIFree(sOutputData.pDatacache[i]);
+        CPLFree(sOutputData.pDatacache);
+    }
+
+    if (iLevel == 0)
+    {
+        if(sOutputData.handle)
+        {
+                JP2_Decompress_End(sOutputData.handle);
+                sOutputData.handle = NULL;
+        }
+
+        if (fp)
+        {
+            VSIFCloseL(fp);
+            fp = NULL;
+        }
+
+        delete poCT;
+    }
+}
+
+/************************************************************************/
+/*                            Identify()                                */
+/************************************************************************/
+
+static const unsigned char jpc_header[] = {0xff,0x4f};
+static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP  ' */
+
+int JP2LuraDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    if( poOpenInfo->nHeaderBytes >= 16 
+        && (memcmp( poOpenInfo->pabyHeader, jpc_header, 
+                    sizeof(jpc_header) ) == 0
+            || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp, 
+                    sizeof(jp2_box_jp) ) == 0
+           ) )
+        return TRUE;
+
+    else
+        return FALSE;
+}
+
+
+/************************************************************************/
+/*                          CreateCopy()                                */
+/************************************************************************/
+
+GDALDataset * JP2LuraDataset::CreateCopy(const char * pszFilename,
+                                         GDALDataset *poSrcDS,
+                                         int /* bStrict */,
+                                         char ** papszOptions,
+                                         GDALProgressFunc pfnProgress,
+                                         void * pProgressData)
+
+{
+    char                        pcMsg[255];
+    JP2_Comp_Handle             handle = NULL;
+    GDALJP2Metadata             oJP2MD;
+
+    int  nBands = poSrcDS->GetRasterCount();
+    int  nXSize = poSrcDS->GetRasterXSize();
+    int  nYSize = poSrcDS->GetRasterYSize();
+    if (nBands == 0 || nBands > 32767)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "Unable to export files with %d bands. "
+                "Must be >= 1 and <= 32767", nBands);
+        return NULL;
+    }
+    GDALColorTable* poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
+    if (poCT != NULL)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "JP2Lura driver does not support band with color table");
+        return NULL;
+    }
+
+    const GDALDataType eDataType =
+                            poSrcDS->GetRasterBand(1)->GetRasterDataType();
+    if (eDataType != GDT_Byte && eDataType != GDT_Int16 &&
+        eDataType != GDT_UInt16 && eDataType != GDT_UInt32 &&
+        eDataType != GDT_Int32 && eDataType != GDT_Float32)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "JP2Lura driver only supports creating Byte, Int16, "
+                "UInt16, Int32, UInt32 or Float32");
+        return NULL;
+    }
+    if( eDataType == GDT_Float32 && nBands != 1 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+            "JP2Lura driver only supports creating one single Float32 band");
+        return NULL;
+    }
+    if( eDataType == GDT_Float32 &&
+        !CPLFetchBool(papszOptions, "SPLIT_IEEE754", false) )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+            "Encoding of GDT_Float32 band is only supported if "
+            "SPLIT_IEEE754=YES is specified");
+        return NULL;
+    }
+
+    unsigned long ulBps = 0;
+    bool bSigned = false;
+
+    switch (eDataType)
+    {
+        case GDT_Byte:
+        {
+            ulBps = 8;
+            bSigned = false;
+            break;
+        }
+        case GDT_UInt16:
+        {
+            ulBps = 16;
+            bSigned = false;
+            break;
+        }
+        case GDT_Int16:
+        {
+            ulBps = 16;
+            bSigned = true;
+            break;
+        }
+        case GDT_UInt32:
+        {
+            ulBps = 28;
+            bSigned = false;
+            break;
+        }
+        case GDT_Int32:
+        {
+            ulBps = 28;
+            bSigned = true;
+            break;
+        }
+
+        default:
+                break;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Read creation options.                                          */
+    /* -------------------------------------------------------------------- */
+    bool bGeoJP2Option = CPLFetchBool(papszOptions, "GeoJP2", false);
+    bool bGMLJP2Option = CPLFetchBool(papszOptions, "GMLJP2", true);
+    const char* pszGMLJP2V2Def = CSLFetchNameValue(papszOptions,
+                                                   "GMLJP2V2_DEF");
+
+
+    const char* pszCodec = CSLFetchNameValue(papszOptions, "CODEC");
+    const char* QUALITY_STYLE = CSLFetchNameValueDef(papszOptions,
+                                                     "QUALITY_STYLE", "PSNR");
+    const char* SPEED_MODE = CSLFetchNameValueDef(papszOptions,
+                                                  "SPEED_MODE", "Fast");
+    int RATE = atoi(CSLFetchNameValueDef(papszOptions, "RATE", "0"));
+    int QUALITY = atoi(CSLFetchNameValueDef(papszOptions, "QUALITY", "0"));
+    int PRECISION = atoi(CSLFetchNameValueDef(papszOptions, "PRECISION", "0"));
+    const char* PROGRESSION = CSLFetchNameValueDef(papszOptions,
+                                                   "PROGRESSION", "LRCP");
+    bool REVERSIBLE = CPLFetchBool(papszOptions, "REVERSIBLE", false);
+    int LEVELS = atoi(CSLFetchNameValueDef(papszOptions, "LEVELS", "5"));
+    const char* QUANTIZATION_STYLE = CSLFetchNameValueDef(papszOptions,
+                                            "QUANTIZATION_STYLE", "EXPOUNDED");
+    int TILEXSIZE = atoi(CSLFetchNameValueDef(papszOptions, "TILEXSIZE", "0"));
+    int TILEYSIZE = atoi(CSLFetchNameValueDef(papszOptions, "TILEYSIZE", "0"));
+    bool TLM = CPLFetchBool(papszOptions, "TLM", false);
+    int CODEBLOCK_WIDTH = atoi(CSLFetchNameValueDef(papszOptions,
+                                               "CODEBLOCK_WIDTH", "64"));
+    int CODEBLOCK_HEIGHT = atoi(CSLFetchNameValueDef(papszOptions, 
+                                                "CODEBLOCK_HEIGHT", "64"));
+    bool ERROR_RESILIENCE = CPLFetchBool(papszOptions,
+                                           "ERROR_RESILIENCE", false);
+    bool WRITE_METADATA = CPLFetchBool(papszOptions, "WRITE_METADATA", false);
+    bool MAIN_MD_DOMAIN_ONLY = CPLFetchBool(papszOptions,
+                                                "MAIN_MD_DOMAIN_ONLY", false);
+    const bool USE_SRC_CODESTREAM = CPLFetchBool(papszOptions,
+                                             "USE_SRC_CODESTREAM", false);
+
+    int NBITS = atoi(CSLFetchNameValueDef(papszOptions, "NBITS", "0"));
+    if( NBITS )
+    {
+        if( eDataType == GDT_Byte && NBITS <= 8 )
+            ulBps = NBITS;
+        else if( (eDataType == GDT_Int16 || eDataType == GDT_UInt16) &&
+                 NBITS > 8 && NBITS <= 16 )
+            ulBps = NBITS;
+        else if( (eDataType == GDT_Int16 || eDataType == GDT_UInt16) &&
+                 NBITS > 16 && NBITS <= 28 )
+            ulBps = NBITS;
+        else
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Inconsistent value of NBITS for data type");
+    }
+    else if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS",
+                                                "IMAGE_STRUCTURE" ) != NULL )
+    {
+        ulBps = atoi(poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS",
+                                                        "IMAGE_STRUCTURE" ) );
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Analyze creation options.                                       */
+    /* -------------------------------------------------------------------- */
+
+    /* -------------------------------------------------------------------- */
+    /*      Deal with codestream PROFILE                                    */
+    /* -------------------------------------------------------------------- */
+    const char* pszProfile = CSLFetchNameValueDef(papszOptions, "PROFILE",
+                                                  "AUTO");
+    bool bProfile1 = false;
+    if (EQUAL(pszProfile, "UNRESTRICTED"))
+    {
+        bProfile1 = false;
+        /*if (bInspireTG)
+        {
+        CPLError(CE_Failure, CPLE_NotSupported,
+        "INSPIRE_TG=YES mandates PROFILE=PROFILE_1 (TG requirement 21)");
+        return NULL;
+        }*/
+    }
+    else if (EQUAL(pszProfile, "UNRESTRICTED_FORCED"))
+    {
+        bProfile1 = false;
+    }
+    else if (EQUAL(pszProfile, "PROFILE_1_FORCED"))
+            /* For debug only: can produce inconsistent codestream */
+    {
+        bProfile1 = true;
+    }
+    else
+    {
+        if (!(EQUAL(pszProfile, "PROFILE_1") || EQUAL(pszProfile, "AUTO")))
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "Unsupported value for PROFILE : %s. Defaulting to AUTO",
+                    pszProfile);
+            //pszProfile = "AUTO";
+        }
+
+        bProfile1 = true;
+        //const char* pszReq21OrEmpty = (bInspireTG) ?
+        //                                      " (TG requirement 21)" : "";
+        if (TILEXSIZE != 0 && TILEYSIZE != 0 &&
+            (TILEXSIZE != nXSize || TILEYSIZE != nYSize) &&
+            (TILEXSIZE != TILEYSIZE || TILEXSIZE > 1024 ||
+            TILEYSIZE > 1024))
+        {
+            bProfile1 = false;
+            /*if (bInspireTG || EQUAL(pszProfile, "PROFILE_1"))
+            {
+            CPLError(CE_Failure, CPLE_NotSupported,
+            "Tile dimensions incompatible with PROFILE_1%s. "
+            "Should be whole image or square with dimension <= 1024.",
+            pszReq21OrEmpty);
+            return NULL;
+            }*/
+        }
+
+        if (CODEBLOCK_WIDTH > 64 || CODEBLOCK_HEIGHT > 64)
+        {
+            bProfile1 = false;
+            /*if (bInspireTG || EQUAL(pszProfile, "PROFILE_1"))
+            {
+            CPLError(CE_Failure, CPLE_NotSupported,
+            "Codeblock width incompatible with PROFILE_1%s. "
+            "Codeblock width or height should be <= 64.",
+            pszReq21OrEmpty);
+            return NULL;
+            }*/
+        }
+    }
+
+    bool bIsJP2OrJPX = true;
+
+    if (pszCodec)
+    {
+        if (EQUAL(pszCodec, "Codestream") || EQUAL(pszCodec, "J2K"))
+            bIsJP2OrJPX = false;
+        else
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "Unsupported value for CODEC : %s. Defaulting to JP2",
+                    pszCodec);
+        }
+    }
+    else
+    {
+        // Codestream                   Part 1      .jpc .j2k
+        // JP2 File Format              Part 1      .jp2
+        // JPX File Format              Part 2      .jpf
+        if (strlen(pszFilename) > 4)
+        {
+            if (EQUAL(pszFilename + strlen(pszFilename) - 4, ".JPC") ||
+                EQUAL(pszFilename + strlen(pszFilename) - 4, ".J2K"))
+            {
+                bIsJP2OrJPX = false;
+            }
+        }
+    }
+
+    JP2_Property_Value cJP2_Quality = cJP2_Quality_PSNR;
+
+    if (QUALITY_STYLE)
+    {
+        if (EQUAL(QUALITY_STYLE, "PSNR"))
+            cJP2_Quality = cJP2_Quality_PSNR;
+        else if (EQUAL(QUALITY_STYLE, "XXSmall"))
+            cJP2_Quality = cJP2_Quality_Visual_XXSmall;
+        else if (EQUAL(QUALITY_STYLE, "XSmall"))
+            cJP2_Quality = cJP2_Quality_Visual_XSmall;
+        else if (EQUAL(QUALITY_STYLE, "Small"))
+            cJP2_Quality = cJP2_Quality_Visual_Small;
+        else if (EQUAL(QUALITY_STYLE, "Medium"))
+            cJP2_Quality = cJP2_Quality_Visual_Medium;
+        else if (EQUAL(QUALITY_STYLE, "Large"))
+            cJP2_Quality = cJP2_Quality_Visual_Large;
+        else if (EQUAL(QUALITY_STYLE, "XLarge"))
+            cJP2_Quality = cJP2_Quality_Visual_XLarge;
+        else if (EQUAL(QUALITY_STYLE, "XXLarge"))
+            cJP2_Quality = cJP2_Quality_Visual_XXLarge;
+        else
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "Unsupported value for QUALITY_STYLE : %s. "
+                    "Defaulting to PSNR",
+                    QUALITY_STYLE);
+        }
+    }
+
+    JP2_Property_Value cJP2_Speed = cJP2_Speed_Fast;
+    if (SPEED_MODE)
+    {
+        if (EQUAL(SPEED_MODE, "Fast"))
+            cJP2_Speed = cJP2_Speed_Fast;
+        else if (EQUAL(SPEED_MODE, "Accurate"))
+            cJP2_Speed = cJP2_Speed_Accurate;
+        else
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "Unsupported value for SPEED_MODE : %s. Defaulting to Fast",
+                    SPEED_MODE);
+        }
+    }
+    if (RATE < 0)
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported value for RATE : %d. "
+                "Defaulting to 0 (maximum quality).",
+                RATE);
+        RATE = 0;
+    }
+    if (QUALITY<0 || QUALITY>100)
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported value for QUALITY : %d. "
+                "Defaulting to 0 (maximum quality).",
+                QUALITY);
+        QUALITY = 0;
+    }
+    if (PRECISION != 32 && PRECISION != 16 && PRECISION != 0)
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported value for PRECISION : %d. "
+                "Defaulting to 0 (automatically select appropriate precision).",
+                PRECISION);
+        PRECISION = 0;
+    }
+    else if (PRECISION == 32)
+        PRECISION = 1;
+    else if (PRECISION == 16)
+        PRECISION = 0;
+
+    JP2_Property_Value cJP2_Progression = cJP2_Progression_LRCP;
+    if (PROGRESSION)
+    {
+        if (EQUAL(PROGRESSION, "LRCP"))
+            cJP2_Progression = cJP2_Progression_LRCP;
+        else if (EQUAL(PROGRESSION, "RLCP"))
+            cJP2_Progression = cJP2_Progression_RLCP;
+        else if (EQUAL(PROGRESSION, "RPCL"))
+            cJP2_Progression = cJP2_Progression_RPCL;
+        else if (EQUAL(PROGRESSION, "PCRL"))
+            cJP2_Progression = cJP2_Progression_PCRL;
+        else if (EQUAL(PROGRESSION, "CPRL"))
+            cJP2_Progression = cJP2_Progression_CPRL;
+        else
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "Unsupported value for PROGRESSION : %s. "
+                    "Defaulting to LRCP (quality)",
+                    PROGRESSION);
+        }
+    }
+    if (LEVELS<0 || LEVELS>16)
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported value for LEVELS : %d. Defaulting to 5.",
+                LEVELS);
+        LEVELS = 5;
+    }
+    JP2_Property_Value cJP2_Quant = cJP2_Quant_Expounded;
+    if (QUANTIZATION_STYLE)
+    {
+        if (EQUAL(QUANTIZATION_STYLE, "DERIVED"))
+            cJP2_Quant = cJP2_Quant_Derived;
+        else if (EQUAL(QUANTIZATION_STYLE, "EXPOUNDED"))
+            cJP2_Quant = cJP2_Quant_Expounded;
+        else
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                    "Unsupported value for QUANTIZATION_STYLE : %s. "
+                    "Defaulting to EXPOUNDED (quality)",
+                    QUANTIZATION_STYLE);
+        }
+    }
+    JP2_Property_Value cJP2_Wavelet =
+        (REVERSIBLE) ? cJP2_Wavelet_5_3 : cJP2_Wavelet_9_7;
+    if (TILEXSIZE<0 || TILEXSIZE>nXSize)
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported value for TILEXSIZE : %d. image_width is %d. "
+                "Defaulting to 0 (Image_Width).",
+                TILEXSIZE, nXSize);
+        TILEXSIZE = 0;
+    }
+    if (TILEYSIZE<0 || TILEYSIZE>nYSize)
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported value for TILEYSIZE : %d. Image_Height is %d. "
+                "Defaulting to 0 (Image_Height).",
+                TILEXSIZE, nYSize);
+        TILEYSIZE = 0;
+    }
+
+    if (CODEBLOCK_WIDTH<4 || CODEBLOCK_WIDTH>1024)
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported value for CODEBLOCK_WIDTH : %d. Defaulting to 64.",
+                CODEBLOCK_WIDTH);
+        CODEBLOCK_WIDTH = 64;
+    }
+    if (CODEBLOCK_HEIGHT<4 || CODEBLOCK_HEIGHT>1024)
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                "Unsupported value for CODEBLOCK_HEIGHT : %d. Defaulting to 64.",
+                CODEBLOCK_HEIGHT);
+        CODEBLOCK_HEIGHT = 64;
+    }
+    if( CODEBLOCK_WIDTH * CODEBLOCK_HEIGHT > 4096 )
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                 "Invalid values for codeblock size. "
+                 "CODEBLOCK_WIDTH * CODEBLOCK_HEIGHT should be <= 4096. "
+                 "Defaulting to 64x64");
+        CODEBLOCK_WIDTH = 64;
+        CODEBLOCK_HEIGHT = 64;
+    }
+    int nCblockW_po2 = FloorPowerOfTwo(CODEBLOCK_WIDTH);
+    int nCblockH_po2 = FloorPowerOfTwo(CODEBLOCK_HEIGHT);
+    if( nCblockW_po2 != CODEBLOCK_WIDTH || nCblockH_po2 != CODEBLOCK_HEIGHT )
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                 "Non power of two values used for codeblock size. "
+                 "Using to %dx%d",
+                 nCblockW_po2, nCblockH_po2);
+    }
+    CODEBLOCK_WIDTH = nCblockW_po2;
+    CODEBLOCK_HEIGHT = nCblockH_po2;
+
+    JP2_Property_Value ERROR_RESILIENCE_VALUE = 0;
+    if (ERROR_RESILIENCE)
+    {
+        ERROR_RESILIENCE_VALUE = cJP2_Coder_Context_Reset |
+                                 cJP2_Coder_All_Pass_Terminate |
+                                 cJP2_Coder_Vertical_Causal_Context |
+                                 cJP2_Coder_Segmentation_Symbols;
+    }
+    else
+    {
+        ERROR_RESILIENCE_VALUE = 0;
+    }
+
+
+    /* -------------------------------------------------------------------- */
+    /*      Georeferencing options                                          */
+    /* -------------------------------------------------------------------- */
+
+    int nGMLJP2Version = 1;
+    if (pszGMLJP2V2Def != NULL)
+    {
+        bGMLJP2Option = true;
+        nGMLJP2Version = 2;
+        /*if (bInspireTG)
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+            "INSPIRE_TG=YES is only compatible with GMLJP2 v1");
+            return NULL;
+        }*/
+    }
+
+    bool bGeoreferencingCompatOfGeoJP2 = false;
+    bool bGeoreferencingCompatOfGMLJP2 = false;
+
+    if (bIsJP2OrJPX && (bGMLJP2Option || bGeoJP2Option))
+    {
+        if (poSrcDS->GetGCPCount() > 0)
+        {
+            if( CSLFetchNameValue(papszOptions, "GeoJP2") == NULL )
+                bGeoJP2Option = true;
+            bGeoreferencingCompatOfGeoJP2 = true;
+            oJP2MD.SetGCPs(poSrcDS->GetGCPCount(),
+                    poSrcDS->GetGCPs());
+            oJP2MD.SetProjection(poSrcDS->GetGCPProjection());
+        }
+        else
+        {
+            const char* pszWKT = poSrcDS->GetProjectionRef();
+            if (pszWKT != NULL && pszWKT[0] != '\0')
+            {
+                    bGeoreferencingCompatOfGeoJP2 = true;
+                    oJP2MD.SetProjection(pszWKT);
+            }
+            double adfGeoTransform[6];
+            if (poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None)
+            {
+                    bGeoreferencingCompatOfGeoJP2 = true;
+                    oJP2MD.SetGeoTransform(adfGeoTransform);
+            }
+            bGeoreferencingCompatOfGMLJP2 =
+                    (pszWKT != NULL && pszWKT[0] != '\0') &&
+                    poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None;
+        }
+        if (poSrcDS->GetMetadata("RPC") != NULL)
+        {
+                oJP2MD.SetRPCMD(poSrcDS->GetMetadata("RPC"));
+                bGeoreferencingCompatOfGeoJP2 = true;
+        }
+
+        const char* pszAreaOrPoint =
+                            poSrcDS->GetMetadataItem(GDALMD_AREA_OR_POINT);
+        oJP2MD.bPixelIsPoint = pszAreaOrPoint != NULL &&
+                                EQUAL(pszAreaOrPoint, GDALMD_AOP_POINT);
+        if( oJP2MD.bPixelIsPoint &&
+            CSLFetchNameValue(papszOptions, "GeoJP2") == NULL )
+            bGeoJP2Option = true;
+
+        if (bGMLJP2Option &&
+            CPLGetConfigOption("GMLJP2OVERRIDE", NULL) != NULL)
+                bGeoreferencingCompatOfGMLJP2 = true;
+    }
+
+    if (CSLFetchNameValue(papszOptions, "GMLJP2") != NULL && bGMLJP2Option &&
+        !bGeoreferencingCompatOfGMLJP2 && nGMLJP2Version == 1)
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                "GMLJP2 box was explicitly required but cannot be written due "
+                "to lack of georeferencing and/or unsupported georeferencing "
+                "for GMLJP2");
+    }
+
+    if (CSLFetchNameValue(papszOptions, "GeoJP2") != NULL && bGeoJP2Option &&
+        !bGeoreferencingCompatOfGeoJP2)
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                "GeoJP2 box was explicitly required but cannot be written due "
+                "to lack of georeferencing");
+    }
+    /*bool bGeoBoxesAfter = CPLFetchBool(papszOptions, "GEOBOXES_AFTER_JP2C",
+            bInspireTG);*/
+    GDALJP2Box* poGMLJP2Box = NULL;
+    if (bIsJP2OrJPX && bGMLJP2Option && bGeoreferencingCompatOfGMLJP2)
+    {
+        if (nGMLJP2Version == 1)
+            poGMLJP2Box = oJP2MD.CreateGMLJP2(nXSize, nYSize);
+        else
+            poGMLJP2Box = oJP2MD.CreateGMLJP2V2(nXSize, nYSize,
+                                                pszGMLJP2V2Def, poSrcDS);
+        if (poGMLJP2Box == NULL)
+            return NULL;
+    }
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Start the compression process                    */
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    VSILFILE* fp = NULL;
+    bool bException = false;
+    try
+    {
+        const bool bSamePrecision = (eDataType != GDT_Float32);
+
+#ifdef ENABLE_MEMORY_REGISTRAR
+        JP2_Callback_Param mallocFreeParam =
+            reinterpret_cast<JP2_Callback_Param>(&(poDS->oMemoryRegistrar));
+#else
+        JP2_Callback_Param mallocFreeParam =
+            static_cast<JP2_Callback_Param>(NULL);
+#endif
+        JP2_Error error = JP2_Compress_Start(
+                &handle,
+                GDALJP2Lura_Callback_Malloc, mallocFreeParam,
+                GDALJP2Lura_Callback_Free, mallocFreeParam,
+                (eDataType == GDT_Float32) ? 3 : static_cast<short>(nBands) );
+        if( error )
+        {
+            snprintf(pcMsg, sizeof(pcMsg),
+                        "Internal library error (%s).",
+                        GetErrorMessage(error));
+
+            throw pcMsg;
+        }
+
+        /* ***** set license keys *************************** */
+
+        const char* pszNum1 = CPLGetConfigOption("LURA_LICENSE_NUM_1", "");
+        const char* pszNum2 = CPLGetConfigOption("LURA_LICENSE_NUM_2", "");
+        if ( !EQUAL(pszNum1, "") && !EQUAL(pszNum2, "") )
+        {
+            unsigned long license_num_1 =
+                static_cast<unsigned long>(CPLAtoGIntBig(pszNum1));
+            unsigned long license_num_2 =
+                static_cast<unsigned long>(CPLAtoGIntBig(pszNum2));
+
+            error = JP2_Compress_SetLicense(handle, license_num_1,
+                                                 license_num_2);
+            if( error )
+            {
+                switch (error)
+                {
+                    case cJP2_Error_Trial_Time_Expired:
+                        snprintf(pcMsg, sizeof(pcMsg),
+                            "The evaluation period for this software has expired.");
+                        break;
+
+                    case cJP2_Error_License_Level_Too_Low:
+                        snprintf(pcMsg, sizeof(pcMsg),
+                            "License cannot be used with this library version.");
+                        break;
+
+                    case cJP2_Error_Invalid_License:
+                        snprintf(pcMsg, sizeof(pcMsg),
+                            "Invalid license number.");
+                        break;
+
+                    default:
+                        snprintf(pcMsg, sizeof(pcMsg),
+                                 "Internal library error (%s).",
+                                 GetErrorMessage(error));
+                        break;
+                }
+
+                throw pcMsg;
+            }
+        }
+        else
+        {
+            snprintf(pcMsg, sizeof(pcMsg),
+                     "Environment variables LURA_LICENSE_NUM_1 and "
+                     "LURA_LICENSE_NUM_2 not configured.");
+            throw pcMsg;
+        }
+
+#define SetPropGeneral(prop,value) \
+        do { JP2_Error l_error = JP2_Compress_SetProp(handle, prop, \
+                        static_cast<JP2_Property_Value>(value), -1, -1); \
+          if( l_error ) \
+          { \
+                snprintf(pcMsg, sizeof(pcMsg), \
+                        "Internal library error (%s) while setting %s.", \
+                         GetErrorMessage(l_error), #prop); \
+                throw pcMsg; \
+          } \
+        } while(0);
+
+        /* Always ask Lurawave to do codestream only. We will take care */
+        /* of JP2 boxes */
+        SetPropGeneral(cJP2_Prop_File_Format, cJP2_Format_Codestream);
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the dataset.                                             */
+    /* -------------------------------------------------------------------- */
+
+        const char* pszAccess =
+                    EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
+        fp = VSIFOpenL(pszFilename, pszAccess);
+        if (fp == NULL)
+        {
+            throw "Cannot create file";
+        }
+
+
+        int nRedBandIndex = -1;
+        int nGreenBandIndex = -1;
+        int nBlueBandIndex = -1;
+        int nAlphaBandIndex = -1;
+        for(int i=0;i<nBands;i++)
+        {
+            GDALColorInterp eInterp =
+                    poSrcDS->GetRasterBand(i+1)->GetColorInterpretation();
+            if( eInterp == GCI_RedBand )
+                nRedBandIndex = i;
+            else if( eInterp == GCI_GreenBand )
+                nGreenBandIndex = i;
+            else if( eInterp == GCI_BlueBand )
+                nBlueBandIndex = i;
+            else if( eInterp == GCI_AlphaBand )
+                nAlphaBandIndex = i;
+        }
+        const JP2_Colorspace eColorspace =
+            ( (nBands == 3 || nBands == 4) &&
+            nRedBandIndex >= 0 && nGreenBandIndex >= 0 && nBlueBandIndex >= 0 ) ?
+            cJP2_Colorspace_RGBa : cJP2_Colorspace_Gray;
+
+    /* -------------------------------------------------------------------- */
+    /*      Add JP2 boxes.                                                  */
+    /* -------------------------------------------------------------------- */
+        //vsi_l_offset nStartJP2C = 0;
+        bool bUseXLBoxes = false;
+
+        if ( bIsJP2OrJPX)
+        {
+            GDALJP2Box jPBox(fp);
+            jPBox.SetType("jP  ");
+            jPBox.AppendWritableData(4, "\x0D\x0A\x87\x0A");
+            WriteBox(fp, &jPBox);
+
+            GDALJP2Box ftypBox(fp);
+            ftypBox.SetType("ftyp");
+            // http://docs.opengeospatial.org/is/08-085r5/08-085r5.html Req 19
+            const bool bJPXOption = CPLFetchBool( papszOptions, "JPX", true );
+            if( nGMLJP2Version == 2 && bJPXOption )
+                ftypBox.AppendWritableData(4, "jpx "); /* Branding */
+            else
+                ftypBox.AppendWritableData(4, "jp2 "); /* Branding */
+            ftypBox.AppendUInt32(0); /* minimum version */
+            ftypBox.AppendWritableData(4, "jp2 "); /* Compatibility list: first value */
+
+            /*
+            if (bInspireTG && poGMLJP2Box != NULL && !bJPXOption)
+            {
+            CPLError(CE_Warning, CPLE_AppDefined,
+            "INSPIRE_TG=YES implies following GMLJP2 specification which "
+            "recommends advertize reader requirement 67 feature, and thus JPX capability");
+            }
+            else */
+            if (poGMLJP2Box != NULL && bJPXOption)
+            {
+                /* GMLJP2 uses lbl and asoc boxes, which are JPEG2000 Part II spec */
+                /* advertizing jpx is required per 8.1 of 05-047r3 GMLJP2 */
+                ftypBox.AppendWritableData(4, "jpx "); /* Compatibility list: second value */
+            }
+            WriteBox(fp, &ftypBox);
+
+            const bool bIPR = poSrcDS->GetMetadata("xml:IPR") != NULL &&
+                        WRITE_METADATA;
+
+            /* Reader requirement box */
+            if (poGMLJP2Box != NULL && bJPXOption)
+            {
+                GDALJP2Box rreqBox(fp);
+                rreqBox.SetType("rreq");
+                rreqBox.AppendUInt8(1); /* ML = 1 byte for mask length */
+
+                rreqBox.AppendUInt8(0x80 | 0x40 | (bIPR ? 0x20 : 0)); /* FUAM */
+                rreqBox.AppendUInt8(0x80); /* DCM */
+
+                rreqBox.AppendUInt16(static_cast<GUInt16>(2 + (bIPR ? 1 : 0))); /* NSF: Number of standard features */
+
+                rreqBox.AppendUInt16((bProfile1) ? 4 : 5); /* SF0 : PROFILE 1 or PROFILE 2 */
+                rreqBox.AppendUInt8(0x80); /* SM0 */
+
+                rreqBox.AppendUInt16(67); /* SF1 : GMLJP2 box */
+                rreqBox.AppendUInt8(0x40); /* SM1 */
+
+                if (bIPR)
+                {
+                    rreqBox.AppendUInt16(35); /* SF2 : IPR metadata */
+                    rreqBox.AppendUInt8(0x20); /* SM2 */
+                }
+                rreqBox.AppendUInt16(0); /* NVF */
+                WriteBox(fp, &rreqBox);
+            }
+
+            GDALJP2Box ihdrBox(fp);
+            ihdrBox.SetType("ihdr");
+            ihdrBox.AppendUInt32(nYSize);
+            ihdrBox.AppendUInt32(nXSize);
+            if (nBands == 1 && eDataType == GDT_Float32)
+                ihdrBox.AppendUInt16(3);
+            else
+                ihdrBox.AppendUInt16(static_cast<GUInt16>(nBands));
+            GByte BPC;
+            if (bSamePrecision)
+                BPC = static_cast<GByte>((ulBps - 1) | (bSigned ? 0x80 : 0));
+            else
+                BPC = 255;
+            ihdrBox.AppendUInt8(BPC);
+            ihdrBox.AppendUInt8(7); /* C=Compression type: fixed value */
+            ihdrBox.AppendUInt8(0); /* UnkC: 0= colourspace of the image is known */
+            /*and correctly specified in the Colourspace Specification boxes within the file */
+            ihdrBox.AppendUInt8(bIPR ? 1 : 0); /* IPR: 0=no intellectual property, 1=IPR box */
+
+            GDALJP2Box bpccBox(fp);
+            if (!bSamePrecision)
+            {
+                bpccBox.SetType("bpcc");
+                bpccBox.AppendUInt8((1-1) | 0x80);
+                bpccBox.AppendUInt8(8-1);
+                bpccBox.AppendUInt8(23-1);
+            }
+
+            GDALJP2Box colrBox(fp);
+            colrBox.SetType("colr");
+            colrBox.AppendUInt8(1); /* METHOD: 1=Enumerated Colourspace */
+            colrBox.AppendUInt8(0); /* PREC: Precedence. 0=(field reserved for ISO use) */
+            colrBox.AppendUInt8(0); /* APPROX: Colourspace approximation. */
+            GUInt32 enumcs = ( eColorspace == cJP2_Colorspace_RGBa ) ? 16 : 17;
+            colrBox.AppendUInt32(enumcs); /* EnumCS: Enumerated colourspace */
+
+            GDALJP2Box cdefBox(fp);
+            if( ((nBands == 3 || nBands == 4) &&
+                (nRedBandIndex != 0 || nGreenBandIndex != 1 ||
+                 nBlueBandIndex != 2)) ||
+                nAlphaBandIndex >= 0)
+            {
+                cdefBox.SetType("cdef");
+                int nComponents = nBands;
+                cdefBox.AppendUInt16(static_cast<GUInt16>(nComponents));
+                for(int i=0;i<nComponents;i++)
+                {
+                    /* Component number */
+                    cdefBox.AppendUInt16(static_cast<GUInt16>(i));
+                    if( i != nAlphaBandIndex )
+                    {
+                        /* Signification: This channel is the colour image data 
+                           for the associated colour */
+                        cdefBox.AppendUInt16(0);
+                        if( enumcs == 17 && nComponents == 2)
+                        {
+                            /* Colour of the component: associated with a
+                             *particular colour */
+                            cdefBox.AppendUInt16(1);
+                        }
+                        else if ( enumcs == 16 &&
+                                        (nComponents == 3 || nComponents == 4) )
+                        {
+                            if( i == nRedBandIndex )
+                                cdefBox.AppendUInt16(1);
+                            else if( i == nGreenBandIndex )
+                                cdefBox.AppendUInt16(2);
+                            else if( i == nBlueBandIndex )
+                                cdefBox.AppendUInt16(3);
+                            else
+                            {
+                                CPLError(CE_Warning, CPLE_AppDefined,
+                                         "Could not associate band %d "
+                                         "with a red/green/blue channel",
+                                         i+1);
+                                cdefBox.AppendUInt16(65535);
+                            }
+                        }
+                        else
+                        {
+                            /* Colour of the component: not associated with
+                               any particular colour */
+                            cdefBox.AppendUInt16(65535); 
+                        }
+                    }
+                    else
+                    {
+                        /* Signification: Non pre-multiplied alpha */
+                        cdefBox.AppendUInt16(1);
+                        /* Colour of the component: This channel is 
+                         *  associated as the image as a whole */
+                        cdefBox.AppendUInt16(0);
+                    }
+                }
+            }
+
+            // Add res box if needed
+            double dfXRes = 0, dfYRes = 0;
+            int nResUnit = 0;
+            GDALJP2Box* poRes = NULL;
+            if (poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION") != NULL
+                && poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION") != NULL
+                && poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT") != NULL)
+            {
+                dfXRes =
+                    CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION"));
+                dfYRes =
+                    CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION"));
+                nResUnit =
+                    atoi(poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT"));
+#define PIXELS_PER_INCH 2
+#define PIXELS_PER_CM   3
+
+                if (nResUnit == PIXELS_PER_INCH)
+                {
+                    // convert pixels per inch to pixels per cm.
+                    dfXRes = dfXRes * 39.37 / 100.0;
+                    dfYRes = dfYRes * 39.37 / 100.0;
+                    nResUnit = PIXELS_PER_CM;
+                }
+
+                if (nResUnit == PIXELS_PER_CM &&
+                        dfXRes > 0 && dfYRes > 0 &&
+                        dfXRes < 65535 && dfYRes < 65535)
+                {
+                    /* Format a resd box and embed it inside a res box */
+                    GDALJP2Box oResd;
+                    oResd.SetType("resd");
+
+                    int nYDenom = 1;
+                    while (nYDenom < 32767 && dfYRes < 32767)
+                    {
+                            dfYRes *= 2;
+                            nYDenom *= 2;
+                    }
+                    int nXDenom = 1;
+                    while (nXDenom < 32767 && dfXRes < 32767)
+                    {
+                            dfXRes *= 2;
+                            nXDenom *= 2;
+                    }
+
+                    oResd.AppendUInt16((GUInt16)dfYRes);
+                    oResd.AppendUInt16((GUInt16)nYDenom);
+                    oResd.AppendUInt16((GUInt16)dfXRes);
+                    oResd.AppendUInt16((GUInt16)nXDenom);
+                    oResd.AppendUInt8(2); /* vertical exponent */
+                    oResd.AppendUInt8(2); /* horizontal exponent */
+
+                    GDALJP2Box* poResd = &oResd;
+                    poRes = GDALJP2Box::CreateAsocBox(1, &poResd);
+                    poRes->SetType("res ");
+                }
+            }
+
+            /* Build and write jp2h super box now */
+            GDALJP2Box* apoBoxes[7];
+            int nBoxes = 1;
+            apoBoxes[0] = &ihdrBox;
+            if (bpccBox.GetDataLength())
+                apoBoxes[nBoxes++] = &bpccBox;
+            apoBoxes[nBoxes++] = &colrBox;
+            //if (pclrBox.GetDataLength())
+            //  apoBoxes[nBoxes++] = &pclrBox;
+            //if (cmapBox.GetDataLength())
+            //  apoBoxes[nBoxes++] = &cmapBox;
+            if (cdefBox.GetDataLength())
+                apoBoxes[nBoxes++] = &cdefBox;
+            if (poRes)
+                apoBoxes[nBoxes++] = poRes;
+            GDALJP2Box* psJP2HBox = GDALJP2Box::CreateSuperBox("jp2h",
+                                                               nBoxes,
+                                                               apoBoxes);
+            WriteBox(fp, psJP2HBox);
+            delete psJP2HBox;
+            delete poRes;
+
+            if (bGeoJP2Option && bGeoreferencingCompatOfGeoJP2)
+            {
+                GDALJP2Box* poBox = oJP2MD.CreateJP2GeoTIFF();
+                WriteBox(fp, poBox);
+                delete poBox;
+            }
+
+            if (WRITE_METADATA &&
+                    !MAIN_MD_DOMAIN_ONLY)
+            {
+                WriteXMPBox(fp, poSrcDS, papszOptions);
+            }
+
+            if (WRITE_METADATA)
+            {
+                if (!MAIN_MD_DOMAIN_ONLY)
+                    WriteXMLBoxes(fp, poSrcDS, papszOptions);
+                WriteGDALMetadataBox(fp, poSrcDS, papszOptions);
+            }
+
+            if (poGMLJP2Box != NULL)
+            {
+                WriteBox(fp, poGMLJP2Box);
+            }
+        }
+
+    /* -------------------------------------------------------------------- */
+    /*      Try lossless reuse of an existing JPEG2000 codestream           */
+    /* -------------------------------------------------------------------- */
+        vsi_l_offset nCodeStreamLength = 0;
+        vsi_l_offset nCodeStreamStart = 0;
+        VSILFILE* fpSrc = NULL;
+        if( USE_SRC_CODESTREAM)
+        {
+            CPLString osSrcFilename(poSrcDS->GetDescription());
+            if (poSrcDS->GetDriver() != NULL &&
+                    poSrcDS->GetDriver() == GDALGetDriverByName("VRT"))
+            {
+                    VRTDataset* poVRTDS = (VRTDataset*)poSrcDS;
+                    GDALDataset* poSimpleSourceDS =
+                                            poVRTDS->GetSingleSimpleSource();
+                    if (poSimpleSourceDS)
+                            osSrcFilename = poSimpleSourceDS->GetDescription();
+            }
+
+            fpSrc = VSIFOpenL(osSrcFilename, "rb");
+            if (fpSrc)
+            {
+                nCodeStreamStart = JP2LuraFindCodeStream(fpSrc,
+                            &nCodeStreamLength);
+            }
+            if (nCodeStreamLength == 0)
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "USE_SRC_CODESTREAM=YES specified, "
+                         "but no codestream found");
+            }
+        }
+
+        if (bIsJP2OrJPX)
+        {
+            // Start codestream box
+            //nStartJP2C = VSIFTellL(fp);
+            if (nCodeStreamLength)
+                bUseXLBoxes = ((vsi_l_offset)(GUInt32)nCodeStreamLength !=
+                                                            nCodeStreamLength);
+            /*else
+                bUseXLBoxes =
+                    CSLFetchBoolean(papszOptions, "JP2C_XLBOX", FALSE) ||
+                    (GIntBig)nXSize * nYSize * nBands * nDataTypeSize /
+                                    dfRates.back() > 4e9;*/
+            GUInt32 nLBox = (bUseXLBoxes) ? 1 : 0;
+            CPL_MSBPTR32(&nLBox);
+            VSIFWriteL(&nLBox, 1, 4, fp);
+            VSIFWriteL("jp2c", 1, 4, fp);
+            if (bUseXLBoxes)
+            {
+                GUIntBig nXLBox = 0;
+                VSIFWriteL(&nXLBox, 1, 8, fp);
+            }
+        }
+
+    /* -------------------------------------------------------------------- */
+    /*      Do lossless reuse of an existing JPEG2000 codestream            */
+    /* -------------------------------------------------------------------- */
+        if (fpSrc)
+        {
+            const char* apszIgnoredOptions[] = {
+                    "TILEXSIZE", "TILEYSIZE", "QUALITY", "REVERSIBLE",
+                    "LAYERS", "PROGRESSION",
+                    "CODEBLOCK_WIDTH", "CODEBLOCK_HEIGHT", NULL };
+            for (int i = 0; apszIgnoredOptions[i]; i++)
+            {
+                if (CSLFetchNameValue(papszOptions, apszIgnoredOptions[i]))
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                            "Option %s ignored when USE_SRC_CODESTREAM=YES",
+                            apszIgnoredOptions[i]);
+                }
+            }
+            GByte abyBuffer[4096];
+            VSIFSeekL(fpSrc, nCodeStreamStart, SEEK_SET);
+            vsi_l_offset nRead = 0;
+            while (nRead < nCodeStreamLength)
+            {
+                int nToRead = (nCodeStreamLength - nRead > 4096) ? 4096 :
+                        (int)(nCodeStreamLength - nRead);
+                if ((int)VSIFReadL(abyBuffer, 1, nToRead, fpSrc) != nToRead)
+                {
+                    VSIFCloseL(fpSrc);
+
+                    throw "Cannot read source codestream";
+                }
+
+#ifdef disabled
+                if( nRead == 0 && (pszProfile /*|| bInspireTG*/) &&
+                    abyBuffer[2] == 0xFF && abyBuffer[3] == 0x51 )
+                {
+                    if( EQUAL(pszProfile, "UNRESTRICTED") )
+                    {
+                        abyBuffer[6] = 0;
+                        abyBuffer[7] = 0;
+                    }
+                    else if( EQUAL(pszProfile, "PROFILE_1") /*|| bInspireTG*/ )
+                    {
+                        // TODO: ultimately we should check that we can
+                        //really set Profile 1
+                        abyBuffer[6] = 0;
+                        abyBuffer[7] = 2;
+                    }
+                }
+#endif
+
+                if ((int)VSIFWriteL(abyBuffer, 1, nToRead, fp) != nToRead ||
+                        !pfnProgress((nRead + nToRead) * 1.0 / nCodeStreamLength,
+                        NULL, pProgressData))
+                {
+                    VSIFCloseL(fpSrc);
+
+                    throw "Cannot write source codestream";
+                }
+                nRead += nToRead;
+            }
+
+            VSIFCloseL(fpSrc);
+        }
+
+    /* -------------------------------------------------------------------- */
+    /*      Assign creation options.                                        */
+    /* -------------------------------------------------------------------- */
+        SetPropGeneral(cJP2_Prop_Write_TLM_Marker, TLM);
+        SetPropGeneral(cJP2_Prop_Height, nYSize);
+        SetPropGeneral(cJP2_Prop_Width, nXSize);
+
+        if (eDataType == GDT_Float32 && nBands == 1)
+        {
+            short channel = 0;
+            // 1, 8 and 23 bits to code IEEE754 floating value
+            JP2_Property_Value pvBps[3] = { 1, 8, 23 };
+            // signed, unsigned, unsigned to store values as IEEE754
+            JP2_Property_Value pvSpc[3] = { 1, 0, 0 };
+            // Lossless encoding of sign bit and exponent
+            JP2_Property_Value cJP2_Waveleta[3] =
+                { cJP2_Wavelet_5_3, cJP2_Wavelet_5_3, cJP2_Wavelet_9_7 };
+            JP2_Property_Value cJP2_Quanta[3] =
+                { cJP2_Quant_Expounded, cJP2_Quant_Expounded,
+                  cJP2_Quant_Expounded };
+
+            if (REVERSIBLE == 0)
+            {
+                if (RATE == 0 && QUALITY != 0)
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                        "Using QUALITY option will also affect the REVERSIBLE "
+                        "sign and exponent band, as the SDK can only apply "
+                        "the QUALITY parameter the whole image. Thus numeric "
+                        "Float pixels will be affected");
+                    SetPropGeneral(cJP2_Prop_Rate_Quality, QUALITY);
+                }
+                if (QUALITY == 0 && RATE != 0)
+                {
+
+                    GUIntBig ullTotalBytes =
+                                        ((GUIntBig)nXSize * nYSize * 32) >> 3;
+
+                    GUIntBig ulMaxBytes = ullTotalBytes / RATE;
+                    //This property can only be set for the complete image
+                    SetPropGeneral(cJP2_Prop_Rate_Bytes, ulMaxBytes);
+                }
+            }
+            else
+            {
+                if( RATE != 0 )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "RATE option is ignored");
+                }
+                if( QUALITY != 0 )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "QUALITY option is ignored");
+                }
+            }
+
+#define SetPropPerChannel(prop,value,channel) \
+        do { JP2_Error l_error = JP2_Compress_SetProp(handle, prop, \
+                        static_cast<JP2_Property_Value>(value), -1, channel); \
+          if( l_error ) \
+          { \
+                snprintf(pcMsg, sizeof(pcMsg), \
+                        "Internal library error (%s) while setting %s.", \
+                         GetErrorMessage(l_error), #prop); \
+                throw pcMsg; \
+          } \
+        } while(0);
+
+            for (channel = 2; channel >= 0; channel--)
+            {
+                SetPropPerChannel(cJP2_Prop_Bits_Per_Sample, pvBps[channel],
+                                  channel);
+
+                SetPropPerChannel(cJP2_Prop_Signed_Samples, pvSpc[channel], 
+                                  channel);
+
+                if (REVERSIBLE == 0)
+                {
+                    if(QUALITY==0 && RATE==0)
+                    {
+                        SetPropPerChannel(cJP2_Prop_Wavelet_Filter,
+                                        cJP2_Waveleta[channel], channel);
+                        if (cJP2_Waveleta[channel] == cJP2_Wavelet_9_7 )
+                        {
+                            SetPropPerChannel(cJP2_Prop_Quantization_Style,
+                                            cJP2_Quanta[channel], channel);
+                        }
+                    }
+                    else
+                    {
+                        SetPropPerChannel(cJP2_Prop_Wavelet_Filter,
+                                          cJP2_Wavelet_9_7, channel);
+                    }
+                }
+                else
+                {
+                    SetPropPerChannel(cJP2_Prop_Wavelet_Filter,
+                                      cJP2_Wavelet_5_3, channel);
+                }
+            }
+        }
+        else
+        {
+            SetPropGeneral(cJP2_Prop_Bits_Per_Sample, ulBps);
+            SetPropGeneral(cJP2_Prop_Signed_Samples, bSigned ? 1 : 0);
+            if (RATE != 0)
+            {
+                if( REVERSIBLE )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "RATE option is specified. "
+                            "Forcing irreversible wavelet");
+                }
+                cJP2_Wavelet = cJP2_Wavelet_9_7;
+
+                GUIntBig ullTotalBytes = ((GUIntBig)nXSize * nYSize *
+                                                nBands * ulBps + 7) >> 3;
+
+                GUIntBig ulMaxBytes = ullTotalBytes / RATE;
+                SetPropGeneral(cJP2_Prop_Rate_Bytes, ulMaxBytes);
+            }
+            SetPropGeneral(cJP2_Prop_Wavelet_Filter, cJP2_Wavelet);
+            if (REVERSIBLE == 0)
+            {
+                SetPropGeneral(cJP2_Prop_Quantization_Style, cJP2_Quant);
+            }
+            if (RATE == 0 && QUALITY != 0)
+            {
+                if( cJP2_Wavelet == cJP2_Wavelet_9_7 )
+                {
+                    SetPropGeneral(cJP2_Prop_Rate_Quality, QUALITY);
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "QUALITY option is ignored");
+                }
+            }
+        }
+
+        SetPropGeneral(cJP2_Prop_Extern_Colorspace, eColorspace);
+        SetPropGeneral(cJP2_Prop_Wavelet_Levels, LEVELS);
+        SetPropGeneral(cJP2_Prop_Precise, PRECISION);
+
+        // SetPropGeneral(cJP2_Prop_Layers, XXXX);
+
+        /* set progression order */
+        SetPropGeneral(cJP2_Prop_Progression, cJP2_Progression);
+
+        /* set visual weighting */
+        SetPropGeneral(cJP2_Prop_Quality_Style, cJP2_Quality);
+        SetPropGeneral(cJP2_Prop_Speed_Mode, cJP2_Speed);
+        SetPropGeneral(cJP2_Prop_Coder_Options, ERROR_RESILIENCE_VALUE);
+
+        /* Tile dimensions */
+        if (TILEXSIZE == 0 && TILEYSIZE == 0)
+        {
+            if (nXSize > 15000 && nYSize > 15000)
+            {
+                TILEXSIZE = 1024;
+                TILEYSIZE = 1024;
+                CPLDebug("JP2Lura", "Using 1024x1024 tiles");
+            }
+        }
+        SetPropGeneral(cJP2_Prop_Tile_Width, TILEXSIZE);
+        SetPropGeneral(cJP2_Prop_Tile_Height, TILEYSIZE);
+
+        /* Code block dimensions */
+        SetPropGeneral(cJP2_Prop_Codeblock_Width, CODEBLOCK_WIDTH);
+        SetPropGeneral(cJP2_Prop_Codeblock_Height, CODEBLOCK_HEIGHT);
+
+        JP2_Gdal_Stream_Data data;
+        data.fp = fp;
+        data.Position = VSIFTellL(fp);
+
+        SetPropGeneral(cJP2_Prop_Write_Parameter,
+                       reinterpret_cast<JP2_Property_Value>(&data));
+        SetPropGeneral(cJP2_Prop_Write_Function,
+                       reinterpret_cast<JP2_Property_Value>(
+                            GDALJP2Lura_Callback_Compress_Write));
+
+        GDALJP2Lura_Input_Data idata;
+        idata.poSrcDS = poSrcDS;
+        idata.pProgressData = pProgressData;
+        idata.pfnProgress = pfnProgress;
+
+        SetPropGeneral(cJP2_Prop_Input_Parameter,
+                       reinterpret_cast<JP2_Property_Value>(&idata));
+        SetPropGeneral(cJP2_Prop_Input_Function,
+                       reinterpret_cast<JP2_Property_Value>(
+                                    GDALJP2Lura_Callback_Compress_Read));
+
+        /*++++++++++++++++++++++++++++++++++++++++++++++++++*/
+        /* Compress                                         */
+        /*++++++++++++++++++++++++++++++++++++++++++++++++++*/
+        if ( !USE_SRC_CODESTREAM )
+        {
+            error = JP2_Compress_Image(handle);
+            if( error )
+            {
+                snprintf(pcMsg, sizeof(pcMsg),
+                         "Internal library error (%s) when compressing.",
+                         GetErrorMessage(error));
+
+                throw pcMsg;
+            }
+        }
+    }
+    catch( const char* msg )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s", msg);
+        bException = true;
+    }
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Tidy up and end process                          */
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    if (poGMLJP2Box != NULL)
+        delete poGMLJP2Box;
+    if (handle)
+    {
+        JP2_Compress_End(handle);
+    }
+    if (fp)
+    {
+        VSIFCloseL(fp);
+    }
+
+    if( bException )
+        return NULL;
+
+    GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
+    return Open(&oOpenInfo);
+}
+
+/************************************************************************/
+/*                        JP2LuraFindCodeStream()                       */
+/************************************************************************/
+
+static vsi_l_offset JP2LuraFindCodeStream(VSILFILE* fp,
+                                          vsi_l_offset* pnLength)
+{
+    vsi_l_offset nCodeStreamStart = 0;
+    vsi_l_offset nCodeStreamLength = 0;
+
+    VSIFSeekL(fp, 0, SEEK_SET);
+    GByte abyHeader[16];
+    VSIFReadL(abyHeader, 1, 16, fp);
+
+    if (memcmp(abyHeader, jpc_header, sizeof(jpc_header)) == 0)
+    {
+        VSIFSeekL(fp, 0, SEEK_END);
+        nCodeStreamLength = VSIFTellL(fp);
+    }
+    else if (memcmp(abyHeader + 4, jp2_box_jp, sizeof(jp2_box_jp)) == 0)
+    {
+        /* Find offset of first jp2c box */
+        GDALJP2Box oBox(fp);
+        if (oBox.ReadFirst())
+        {
+            while (strlen(oBox.GetType()) > 0)
+            {
+                if (EQUAL(oBox.GetType(), "jp2c"))
+                {
+                    nCodeStreamStart = VSIFTellL(fp);
+                    nCodeStreamLength = oBox.GetDataLength();
+                    break;
+                }
+
+                if (!oBox.ReadNext())
+                    break;
+            }
+        }
+    }
+    *pnLength = nCodeStreamLength;
+    return nCodeStreamStart;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *JP2LuraDataset::Open(GDALOpenInfo * poOpenInfo)
+
+{
+    JP2_Error          error;
+    JP2_Property_Value value;
+    short              sChannel, sIndex;
+
+    if (!Identify(poOpenInfo) || poOpenInfo->fpL == NULL)
+        return NULL;
+
+    // No thread-safety issue here
+    static bool bIsFirstTime = true;
+    if( bIsFirstTime )
+    {
+        bIsFirstTime = false;
+        unsigned long nMajor = 0;
+        unsigned long nMinor = 0;
+        char* pszVersionString = NULL;
+        unsigned char nLicenseLevel = 0;
+        JP2_Common_Get_Library_Version(&nMajor, &nMinor, &pszVersionString,
+                                       &nLicenseLevel);
+        CPLDebug("JP2Lura", "Runtime info: v%lu.%lu (%s), level=%u",
+                 nMajor, nMinor, pszVersionString ? pszVersionString : "",
+                 nLicenseLevel);
+        CPLDebug("JP2Lura", "Compile-time info: v%.02f (%s), level=%u",
+                 LWF_JP2_VERSION, LWF_JP2_VERSION_STRING,
+                 LWF_JP2_LICENSE_LEVEL);
+    }
+
+    JP2LuraDataset *poDS = new JP2LuraDataset();
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Start the decompression process              */
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+#ifdef ENABLE_MEMORY_REGISTRAR
+    JP2_Callback_Param mallocFreeParam =
+            reinterpret_cast<JP2_Callback_Param>(&(poDS->oMemoryRegistrar));
+#else
+    JP2_Callback_Param mallocFreeParam =
+            static_cast<JP2_Callback_Param>(NULL);
+#endif
+    error = JP2_Decompress_Start(
+                        &(poDS->sOutputData.handle),
+                        GDALJP2Lura_Callback_Malloc, mallocFreeParam,
+                        GDALJP2Lura_Callback_Free, mallocFreeParam,
+                        GDALJP2Lura_Callback_Decompress_Read,
+                        reinterpret_cast<JP2_Callback_Param>(poOpenInfo->fpL) );
+    if( error )
+    {
+        if (error == cJP2_Error_Not_Yet_Supported)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "File contains as yet unsupported JPEG 2000 features.");
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Internal library error (%s).", GetErrorMessage(error));
+        }
+
+        delete poDS;
+        return NULL;
+    }
+
+    const char* pszNum1 = CPLGetConfigOption("LURA_LICENSE_NUM_1", "");
+    const char* pszNum2 = CPLGetConfigOption("LURA_LICENSE_NUM_2", "");
+    if ( !EQUAL(pszNum1, "") && !EQUAL(pszNum2, "") )
+    {
+        unsigned long license_num_1 =
+            static_cast<unsigned long>(CPLAtoGIntBig(pszNum1));
+        unsigned long license_num_2 =
+            static_cast<unsigned long>(CPLAtoGIntBig(pszNum2));
+
+        static bool bFirstTimeLicenseInfo = true;
+        if( bFirstTimeLicenseInfo )
+        {
+            bFirstTimeLicenseInfo = false;
+            unsigned char nDay = 0;
+            unsigned char nMonth = 0;
+            unsigned short nYear = 0;
+            error = JP2_Common_Get_License_Expiry_Date(
+                    license_num_1, license_num_2, &nDay, &nMonth, &nYear);
+            if( !error )
+            {
+                CPLDebug("JP2Lura", "Licence expires on %04u/%02u/%02u",
+                         nYear, nMonth, nDay);
+            }
+
+            unsigned char nLicenseLevel = 0;
+            error = JP2_Common_Get_License_Level(license_num_1, license_num_2,
+                                                 &nLicenseLevel);
+            if( !error )
+            {
+                CPLDebug("JP2Lura", "Licence level is %u", nLicenseLevel);
+            }
+        }
+
+        error = JP2_Decompress_SetLicense(poDS->sOutputData.handle,
+                                          license_num_1, license_num_2);
+        if( error )
+        {
+            switch (error)
+            {
+                case cJP2_Error_Trial_Time_Expired:
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                        "The evaluation period for this software has expired.");
+                    break;
+
+                case cJP2_Error_License_Level_Too_Low:
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                        "License cannot be used with this library version.");
+                    break;
+
+                case cJP2_Error_Invalid_License:
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Invalid license number.");
+                    break;
+
+                default:
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Internal library error (%s).",
+                             GetErrorMessage(error));
+                    break;
+            }
+
+            delete poDS;
+            return NULL;
+        }
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Environment variables LURA_LICENSE_NUM_1 and "
+                "LURA_LICENSE_NUM_2 not configured.");
+        delete poDS;
+        return NULL;
+    }
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Get the number of components                 */
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                                        cJP2_Prop_Components, &value, 0, 0);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+
+    short sSpp = static_cast<short>(value);
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Get the colourspace                          */
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                                        cJP2_Prop_Extern_Colorspace, &value,
+                                        0, 0);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+
+    poDS->eColorspace = static_cast<JP2_Colorspace>(value);
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Get the channel definition structure         */
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    error = JP2_Decompress_GetChannelDefs(poDS->sOutputData.handle,
+                                        &(poDS->sOutputData.pChannelDefs),
+                                        &(poDS->sOutputData.ulChannelDefs));
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+
+    CPLDebug("JP2Lura", "components = %d", sSpp);
+    CPLDebug("JP2Lura", "ulChannelDefs = %lu", poDS->sOutputData.ulChannelDefs);
+    for( int i = 0;
+         i < static_cast<int>(poDS->sOutputData.ulChannelDefs); ++i )
+    {
+        if( poDS->eColorspace == cJP2_Colorspace_RGBa &&
+            poDS->sOutputData.pChannelDefs[i].ulType ==
+                                                cJP2_Channel_Type_Color )
+        {
+#ifdef DEBUG_VERBOSE
+            CPLDebug("JP2Lura", "associated[%d] = %lu",
+                    i, poDS->sOutputData.pChannelDefs[i].ulAssociated );
+#endif
+            switch( poDS->sOutputData.pChannelDefs[i].ulAssociated )
+            {
+                case 1:
+                    poDS->nRedIndex = i;
+                    break;
+                case 2:
+                    poDS->nGreenIndex = i;
+                    break;
+                case 3:
+                    poDS->nBlueIndex = i;
+                    break;
+                default:
+                    break;
+            }
+        }
+        else if( poDS->sOutputData.pChannelDefs[i].ulType ==
+                                                cJP2_Channel_Type_Opacity )
+        {
+            poDS->nAlphaIndex = i;
+        }
+    }
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Get the palette, if necessary                */
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    switch (poDS->eColorspace)
+    {
+        case cJP2_Colorspace_Palette_ICCa:
+        case cJP2_Colorspace_Palette_Gray:
+        case cJP2_Colorspace_Palette_RGBa:
+        case cJP2_Colorspace_Palette_RGB_YCCa:
+        case cJP2_Colorspace_Palette_CMYKa:
+        case cJP2_Colorspace_Palette_CIE_LABa:
+
+            if( sSpp != 1 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "Only one component handled for paletted datasets");
+                delete poDS;
+                return NULL;
+            }
+
+            error = JP2_Decompress_GetPalette(poDS->sOutputData.handle,
+                                            &(poDS->sOutputData.pPalette));
+            if( error )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "Internal library error (%s).", GetErrorMessage(error));
+                delete poDS;
+                return NULL;
+            }
+
+            if (!poDS->sOutputData.pPalette)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "Internal library error (%s).", GetErrorMessage(error));
+                delete poDS;
+                return NULL;
+            }
+
+            if( poDS->sOutputData.pPalette->ulChannels == 3 ||
+                poDS->sOutputData.pPalette->ulChannels == 4 )
+            {
+                poDS->poCT = new GDALColorTable();
+                for( unsigned long i=0;
+                            i< poDS->sOutputData.pPalette->ulEntries; ++i )
+                {
+                    GDALColorEntry sEntry;
+                    sEntry.c1 = static_cast<GInt16>(
+                        poDS->sOutputData.pPalette->ppulPalette[0][i]);
+                    sEntry.c2 = static_cast<GInt16>(
+                        poDS->sOutputData.pPalette->ppulPalette[1][i]);
+                    sEntry.c3 = static_cast<GInt16>(
+                        poDS->sOutputData.pPalette->ppulPalette[2][i]);
+                    sEntry.c4 = static_cast<GInt16>(
+                        (poDS->sOutputData.pPalette->ulChannels == 4) ?
+                        poDS->sOutputData.pPalette->ppulPalette[3][i] : 255);
+                    poDS->poCT->SetColorEntry(static_cast<int>(i), &sEntry);
+                }
+            }
+
+            break;
+
+        default:
+            poDS->sOutputData.pPalette = NULL;
+            break;
+    }
+
+    const short sStartChannel = 0;
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Get height, width, bpc                       */
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                                cJP2_Prop_Height, &value, 0,
+                                sStartChannel);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+
+    const unsigned long ulHeight = static_cast<unsigned long>(value);
+
+    error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                                cJP2_Prop_Width, &value, 0,
+                                sStartChannel);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+
+
+    const unsigned long ulWidth = static_cast<unsigned long>(value);
+
+    if (poDS->sOutputData.pPalette)
+    {
+        /* get the bit depth and sign of the first column of entries in */
+        /* the palette table */
+
+        poDS->sOutputData.lBps =
+            poDS->sOutputData.pPalette->pucBitsPerSample[0];
+        poDS->sOutputData.bSigned =
+            CPL_TO_BOOL(poDS->sOutputData.pPalette->pucSignedSample[0]);
+
+#ifdef unused
+        /* get the bit depth of the palette index component */
+
+        error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                                    cJP2_Prop_Bits_Per_Sample, &value, 0, 0);
+        if( error )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Internal library error (%s).", GetErrorMessage(error));
+            delete poDS;
+            return NULL;
+        }
+
+        poDS->sOutputData.lPaletteBps = static_cast<long>(value);
+#endif
+    }
+    else
+    {
+        error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                                cJP2_Prop_Bits_Per_Sample, &value, 0,
+                                sStartChannel);
+        if( error )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Internal library error (%s).", GetErrorMessage(error));
+            delete poDS;
+            return NULL;
+        }
+
+        poDS->sOutputData.lBps = static_cast<long>(value);
+
+        error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                                    cJP2_Prop_Signed_Samples, &value, 0,
+                                    sStartChannel);
+        if( error )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Internal library error (%s).", GetErrorMessage(error));
+            delete poDS;
+            return NULL;
+        }
+
+        poDS->sOutputData.bSigned = value != 0;
+
+        // Detect special case of IEEE754 split Float32
+        if (sSpp == 3)
+        {
+            //int isfloat = 0;
+            JP2_Property_Value avalue[3] = { 0, 0, 0 };
+            error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                    cJP2_Prop_Bits_Per_Sample, &(avalue[0]), 0, (short)0);
+            if( !error )
+                error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                    cJP2_Prop_Bits_Per_Sample, &(avalue[1]), 0, (short)1);
+            if( !error )
+                error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                        cJP2_Prop_Bits_Per_Sample, &(avalue[2]), 0, (short)2);
+            if( error )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                    "Internal library error (%s).", GetErrorMessage(error));
+                delete poDS;
+                return NULL;
+            }
+
+            if (avalue[0] == 1 && avalue[1] == 8 && avalue[2] == 23)
+            {
+                // flags special values for float prototype
+                poDS->sOutputData.lBps = 0;
+                poDS->sOutputData.bSigned = false;
+            }
+        }
+    }
+
+    if (poDS->sOutputData.lBps != 0)
+    {
+        /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+        /* Check that the width, height, bpps are the same for all components */
+        /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+        for (sIndex = sStartChannel + 1; sIndex <= sSpp - 1; sIndex++)
+        {
+            unsigned long ulCheckHeight, ulCheckWidth;
+            bool bCheckSigned;
+            long lCheckBps;
+
+            if (poDS->sOutputData.pPalette)
+            {
+                if (sIndex < (short)poDS->sOutputData.pPalette->ulChannels)
+                {
+                    /* checking one of the columns of the palette */
+
+                    lCheckBps =
+                        poDS->sOutputData.pPalette->pucBitsPerSample[sIndex];
+                    bCheckSigned = CPL_TO_BOOL(
+                        poDS->sOutputData.pPalette->pucSignedSample[sIndex]);
+
+                    sChannel = 0;
+                }
+                else
+                {
+                    sChannel = sIndex -
+                            (short)poDS->sOutputData.pPalette->ulChannels + 1;
+
+                    error = JP2_Decompress_GetProp(
+                        poDS->sOutputData.handle, cJP2_Prop_Bits_Per_Sample,
+                        &value, 0, sChannel);
+                    if( error )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                        "Internal library error (%s).", GetErrorMessage(error));
+                        delete poDS;
+                        return NULL;
+                    }
+
+                    lCheckBps = (long)value;
+
+                    error = JP2_Decompress_GetProp(
+                            poDS->sOutputData.handle, cJP2_Prop_Signed_Samples,
+                            &value, 0, sChannel);
+                    if( error )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                        "Internal library error (%s).", GetErrorMessage(error));
+                        return NULL;
+                    }
+
+                    bCheckSigned = value != 0;
+                }
+            }
+            else
+            {
+                sChannel = sIndex;
+
+                error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                        cJP2_Prop_Bits_Per_Sample, &value, 0, sChannel);
+                if( error )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                        "Internal library error (%s).", GetErrorMessage(error));
+                    delete poDS;
+                    return NULL;
+                }
+
+                lCheckBps = static_cast<long>(value);
+
+                error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                        cJP2_Prop_Signed_Samples, &value, 0, sChannel);
+                if( error )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                        "Internal library error (%s).", GetErrorMessage(error));
+                    delete poDS;
+                    return NULL;
+                }
+
+                bCheckSigned = value != 0;
+            }
+
+            error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                                    cJP2_Prop_Height, &value, 0, sChannel);
+            if( error )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                    "Internal library error (%s).", GetErrorMessage(error));
+                delete poDS;
+                return NULL;
+            }
+
+            ulCheckHeight = static_cast<unsigned long>(value);
+
+            error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                                    cJP2_Prop_Width, &value, 0, sChannel);
+            if( error )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                    "Internal library error (%s).", GetErrorMessage(error));
+                delete poDS;
+                return NULL;
+            }
+
+            ulCheckWidth = static_cast<unsigned long>(value);
+
+            if( ulCheckWidth == ulWidth / 2 &&
+                ulCheckHeight == ulHeight / 2 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot handle 4:2:0 resampling");
+                delete poDS;
+                return NULL;
+            }
+
+            if ((ulCheckHeight != ulHeight) ||
+                (ulCheckWidth != ulWidth) ||
+                (bCheckSigned != poDS->sOutputData.bSigned) ||
+                (lCheckBps != poDS->sOutputData.lBps))
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                    "Warning: Only the first %d channel(s) will be decoded.",
+                    sChannel);
+
+                sSpp = sChannel;
+                break;
+            }
+        }
+    }
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    /*  Decompress bitonal images as 8 bit grayscale            */
+    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    error = JP2_Decompress_SetProp(poDS->sOutputData.handle,
+                                        cJP2_Prop_Expand_Bitonal, 1);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* calculate height and width of the image tile buffer */
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                cJP2_Prop_Tile_Height, &value, (long)-1, (short)-1);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+    unsigned long ulTileH = static_cast<unsigned long>(value);
+
+    error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                cJP2_Prop_Tile_Width, &value, (long)-1, (short)-1);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+    unsigned long ulTileW = static_cast<unsigned long>(value);
+
+    error = JP2_Decompress_SetProp(poDS->sOutputData.handle,
+                        cJP2_Prop_InternalReadCache, cJP2_UseInternalCache);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create a corresponding GDALDataset.                             */
+    /* -------------------------------------------------------------------- */
+
+    GDALDataType eDataType = GDT_Byte;
+    if (poDS->sOutputData.lBps > 16)
+    {
+        if (poDS->sOutputData.bSigned)
+            eDataType = GDT_Int32;
+        else
+            eDataType = GDT_UInt32;
+    }
+    else if (poDS->sOutputData.lBps > 8)
+    {
+        if (poDS->sOutputData.bSigned)
+            eDataType = GDT_Int16;
+        else
+            eDataType = GDT_UInt16;
+    }
+    else if (poDS->sOutputData.lBps == 0) // case float
+    {
+        eDataType = GDT_Float32;
+    }
+
+    poDS->nRasterXSize = static_cast<int>(ulWidth);
+    poDS->nRasterYSize = static_cast<int>(ulHeight);
+
+    if (eDataType == GDT_Float32)
+    {
+        poDS->nBands = 1;
+    }
+    else
+    {
+        poDS->nBands = sSpp;
+    }
+
+    // do not generate tile sizes larger than the dataset
+    // dimensions
+    if (static_cast<unsigned long>(poDS->nRasterXSize) < ulTileW)
+    {
+        CPLDebug("JP2Lura", "Adjusting block width from %lu to %d",
+                    ulTileW, poDS->nRasterXSize);
+        ulTileW = poDS->nRasterXSize;
+    }
+    if (static_cast<unsigned long>(poDS->nRasterYSize) < ulTileH)
+    {
+        CPLDebug("JP2Lura", "Adjusting block width from %lu to %d",
+                    ulTileH, poDS->nRasterYSize);
+        ulTileH = poDS->nRasterYSize;
+    }
+
+    int nTileW = static_cast<int>(ulTileW);
+    int nTileH = static_cast<int>(ulTileH);
+    /* -------------------------------------------------------------------- */
+    /*      Create band information objects.                                */
+    /* -------------------------------------------------------------------- */
+    for (int iBand = 1; iBand <= poDS->nBands; iBand++)
+    {
+        JP2LuraRasterBand* poBand = new JP2LuraRasterBand(
+                poDS, iBand, eDataType,
+                static_cast<int>(poDS->sOutputData.lBps), nTileW, nTileH);
+        poDS->SetBand(iBand, poBand);
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create overview datasets.                                       */
+    /* -------------------------------------------------------------------- */
+
+    error = JP2_Decompress_GetProp(poDS->sOutputData.handle,
+                    cJP2_Prop_Wavelet_Levels, &value, (long)0, (short)0);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).", GetErrorMessage(error));
+        delete poDS;
+        return NULL;
+    }
+
+    int numResolutions = static_cast<int>(value);
+
+    /* Lower resolutions are not compatible with a color-table */
+    if( poDS->poCT != NULL )
+        numResolutions = 0;
+
+    int nW = poDS->nRasterXSize;
+    int nH = poDS->nRasterYSize;
+
+    while (poDS->nOverviewCount + 1 < numResolutions &&
+            (nW > 128 || nH > 128) )
+    {
+        nW = static_cast<int>(ceil(nW / 2.0));
+        nH = static_cast<int>(ceil(nH / 2.0));
+
+        JP2LuraDataset* poODS = new JP2LuraDataset();
+        poODS->bIsInternal = true;
+        poODS->SetDescription(poOpenInfo->pszFilename);
+        poODS->iLevel = poDS->nOverviewCount + 1;
+
+        if (nW < nTileW || nH < nTileH)
+        {
+            nTileW = nW;
+            nTileH = nH;
+        }
+        //else
+        //{
+        //    nTileW /= 2;
+        //    nTileH /= 2;
+        //}
+
+        poODS->nRasterXSize = nW;
+        poODS->nRasterYSize = nH;
+
+        poODS->nBands = poDS->nBands;
+        poODS->poCT = poDS->poCT;
+        poODS->eColorspace = poDS->eColorspace;
+        poODS->nRedIndex = poDS->nRedIndex;
+        poODS->nGreenIndex = poDS->nGreenIndex;
+        poODS->nBlueIndex = poDS->nBlueIndex;
+        poODS->nAlphaIndex = poDS->nAlphaIndex;
+
+        memcpy(&(poODS->sOutputData), &(poDS->sOutputData),
+               sizeof(GDALJP2Lura_Output_Data));
+        poODS->sOutputData.pDatacache = NULL;
+
+        for (int iBand = 1; iBand <= poODS->nBands; iBand++)
+        {
+            poODS->SetBand(iBand, new JP2LuraRasterBand(
+                    poODS, iBand, eDataType,
+                    static_cast<int>(poDS->sOutputData.lBps),
+                    nTileW, nTileH));
+        }
+
+        poDS->papoOverviewDS = (JP2LuraDataset**)CPLRealloc(
+                poDS->papoOverviewDS,
+                (poDS->nOverviewCount + 1) * sizeof(JP2LuraDataset*));
+
+        poDS->papoOverviewDS[poDS->nOverviewCount++] = poODS;
+
+    }
+
+    poDS->LoadJP2Metadata(poOpenInfo);
+
+    // Borrow fpL
+    poDS->fp = poOpenInfo->fpL;
+    poOpenInfo->fpL = NULL;
+
+    /* -------------------------------------------------------------------- */
+    /*      Vector layers                                                   */
+    /* -------------------------------------------------------------------- */
+    if (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR)
+    {
+        poDS->LoadVectorLayers(
+                CSLFetchBoolean(poOpenInfo->papszOpenOptions,
+                                "OPEN_REMOTE_GML", FALSE));
+
+        // If file opened in vector-only mode and there's no vector,
+        // return
+        if ((poOpenInfo->nOpenFlags & GDAL_OF_RASTER) == 0 &&
+                poDS->GetLayerCount() == 0)
+        {
+            delete poDS;
+                return NULL;
+        }
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Initialize any PAM information.                                 */
+    /* -------------------------------------------------------------------- */
+    poDS->SetDescription(poOpenInfo->pszFilename);
+    poDS->TryLoadXML();
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr  JP2LuraDataset::IRasterIO(GDALRWFlag eRWFlag,
+                                  int nXOff, int nYOff, int nXSize, int nYSize,
+                                  void * pData, int nBufXSize, int nBufYSize,
+                                  GDALDataType eBufType,
+                                  int nBandCount, int *panBandMap,
+                                  GSpacing nPixelSpace, GSpacing nLineSpace,
+                                  GSpacing nBandSpace,
+                                  GDALRasterIOExtraArg* psExtraArg)
+{
+    if (eRWFlag != GF_Read)
+        return CE_Failure;
+
+    if (nBandCount < 1)
+        return CE_Failure;
+
+    GDALRasterBand* poBand = GetRasterBand(panBandMap[0]);
+
+    /* ==================================================================== */
+    /*      Do we have overviews that would be appropriate to satisfy       */
+    /*      this request?                                                   */
+    /* ==================================================================== */
+
+    if ((nBufXSize < nXSize || nBufYSize < nYSize)
+            && poBand->GetOverviewCount() > 0 && eRWFlag == GF_Read)
+    {
+        int         nOverview;
+        GDALRasterIOExtraArg sExtraArg;
+
+        GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
+
+        nOverview =
+                GDALBandGetBestOverviewLevel2(poBand, nXOff, nYOff,
+                                              nXSize, nYSize,
+                                            nBufXSize, nBufYSize, &sExtraArg);
+        if (nOverview >= 0)
+        {
+            return papoOverviewDS[nOverview]->RasterIO(
+                    eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                    pData, nBufXSize, nBufYSize, eBufType,
+                    nBandCount, panBandMap,
+                    nPixelSpace, nLineSpace, nBandSpace,
+                    &sExtraArg);
+        }
+    }
+
+    CPLErr eErr = GDALPamDataset::IRasterIO(eRWFlag,
+            nXOff, nYOff, nXSize, nYSize,
+            pData, nBufXSize, nBufYSize,
+            eBufType,
+            nBandCount, panBandMap,
+            nPixelSpace, nLineSpace, nBandSpace,
+            psExtraArg);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                           WriteBox()                                 */
+/************************************************************************/
+
+void JP2LuraDataset::WriteBox(VSILFILE* fp, GDALJP2Box* poBox)
+{
+    GUInt32   nLBox;
+    GUInt32   nTBox;
+
+    if (poBox == NULL)
+        return;
+
+    nLBox = (int)poBox->GetDataLength() + 8;
+    nLBox = CPL_MSBWORD32(nLBox);
+
+    memcpy(&nTBox, poBox->GetType(), 4);
+
+    VSIFWriteL(&nLBox, 4, 1, fp);
+    VSIFWriteL(&nTBox, 4, 1, fp);
+    VSIFWriteL(poBox->GetWritableData(), 1, (int)poBox->GetDataLength(), fp);
+}
+
+/************************************************************************/
+/*                         WriteGDALMetadataBox()                       */
+/************************************************************************/
+
+void JP2LuraDataset::WriteGDALMetadataBox(VSILFILE* fp,
+                                          GDALDataset* poSrcDS,
+                                          char** papszOptions)
+{
+    GDALJP2Box* poBox = GDALJP2Metadata::CreateGDALMultiDomainMetadataXMLBox(
+        poSrcDS, CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE));
+    if (poBox)
+        WriteBox(fp, poBox);
+    delete poBox;
+}
+/************************************************************************/
+/*                           WriteXMPBox()                              */
+/************************************************************************/
+
+void JP2LuraDataset::WriteXMPBox(VSILFILE* fp, GDALDataset* poSrcDS,
+                                 char** /*papszOptions*/)
+{
+    GDALJP2Box* poBox = GDALJP2Metadata::CreateXMPBox(poSrcDS);
+    if (poBox)
+        WriteBox(fp, poBox);
+    delete poBox;
+}
+/************************************************************************/
+/*                         WriteXMLBoxes()                              */
+/************************************************************************/
+
+void JP2LuraDataset::WriteXMLBoxes(VSILFILE* fp, GDALDataset* poSrcDS,
+                                   char** /*papszOptions*/)
+{
+    int nBoxes = 0;
+    GDALJP2Box** papoBoxes = GDALJP2Metadata::CreateXMLBoxes(poSrcDS, &nBoxes);
+    for (int i = 0; i<nBoxes; i++)
+    {
+        WriteBox(fp, papoBoxes[i]);
+        delete papoBoxes[i];
+    }
+    CPLFree(papoBoxes);
+}
+/************************************************************************/
+/*                       GDALRegister_JP2Lura()                         */
+/************************************************************************/
+
+void GDALRegister_JP2Lura()
+
+{
+    GDALDriver  *poDriver;
+
+    if (! GDAL_CHECK_VERSION("JP2Lura driver"))
+        return;
+
+    if( GDALGetDriverByName( "JP2Lura" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+
+        poDriver->SetDescription( "JP2Lura" );
+        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
+                                "JPEG-2000 driver based on Lurawave library" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
+                                   "frmt_jp2lura.html" );
+        poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "jp2 j2f j2k" );
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
+                                   "Byte Int16 UInt16 Int32 UInt32 Float32");
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"   <Option name='OPEN_REMOTE_GML' type='boolean' description="
+        "'Whether to load remote vector layers referenced by a link in a "
+        "GMLJP2 v2 box' default='NO'/>"
+"   <Option name='GEOREF_SOURCES' type='string' description="
+        "'Comma separated list made with values INTERNAL/GMLJP2/GEOJP2/"
+        "WORLDFILE/PAM/NONE that describe the priority order for "
+        "georeferencing' default='PAM,GEOJP2,GMLJP2,WORLDFILE'/>"
+"</OpenOptionList>" );
+
+        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>"
+"   <Option name='CODEC' type='string-select' description="
+            "'Codec to use. Default according to file extension. "
+            "If unknown, default to JP2'>"
+"       <Value>JP2</Value>"
+"       <Value alias='J2K'>Codestream</Value>"
+"   </Option>"
+"   <Option name='JPX' type='boolean' description="
+        "'Whether to advertize JPX features when a GMLJP2 box is written "
+        "(or use JPX branding if GMLJP2 v2)' default='YES'/>"
+"   <Option name='GeoJP2' type='boolean' description="
+                        "'Whether to emit a GeoJP2 box' default='NO'/>"
+"   <Option name='GMLJP2' type='boolean' description="
+                        "'Whether to emit a GMLJP2 v1 box' default='YES'/>"
+"   <Option name='GMLJP2V2_DEF' type='string' description="
+        "'Definition file to describe how a GMLJP2 v2 box should be generated. "
+        "If set to YES, a minimal instance will be created'/>"
+"   <Option name='SPLIT_IEEE754' type='boolean' description="
+        "'Whether encoding of Float32 bands as 3 bands with IEEE754 sign bit, "
+        "exponent, mantissa values (non standard extension)' default='NO'/>"
+"   <Option name='QUALITY_STYLE' type='string-select' description="
+        "'This property tag is used to set the quality mode to be used during "
+        "lossy compression.For normal images and situations (1:1 pixel display,"
+        " ~50 cm viewing distance) we recommend Small or PSNR. For quality "
+        "measurement only PSNR should be used' default='PSNR'>"
+"       <Value>PSNR</Value>"
+"       <Value>XXSmall</Value>"
+"       <Value>XSmall</Value>"
+"       <Value>Small</Value>"
+"       <Value>Medium</Value>"
+"       <Value>Large</Value>"
+"       <Value>XLarge</Value>"
+"       <Value>XXLarge</Value>"
+"   </Option>"
+"   <Option name='SPEED_MODE' type='string-select' description="
+        "'This property tag is used to set the speed mode to be used "
+        "during lossy compression. The following modes are defined' "
+        "default='Fast'>"
+"       <Value>Fast</Value>"
+"       <Value>Accurate</Value>"
+"   </Option>"
+"   <Option name='RATE' type='int' description='"
+        "When specifyig this value, the target compressed file size will be "
+        "the uncompressed file size divided by RATE. In general the "
+        "achieved rate will be exactly the requested size or a few bytes "
+        "lower. Will force use of irreversible wavelet. "
+        "Default value: 0 (maximum quality).' default='0'/>"
+"   <Option name='QUALITY' type='int' description="
+        "'Compression to a particular quality is possible only when using "
+        "the 9-7 filter with the standard expounded quantization and no regions"
+        "of interest. A compression quality may be specified between 1 (low) "
+        "and 100 (high). The size of the resulting JPEG2000 file will depend "
+        "of the image content. Only used for irreversible compression. "
+        "The compression quality cannot be used together "
+        "the property RATE. Default value: 0 (maximum quality).' "
+        "min='0' max='100' default='0'/>"
+"   <Option name='PRECISION' type='int' description="
+        "'For improved efficiency, the library automatically, depending on the "
+        "image depth, uses either 16 or 32 bit representation for wavelet "
+        "coefficients. The precision property can be set to force the library "
+        "to always use 32 bit representations. The use of 32 bit values may "
+        "slightly improve image quality and the expense of speed and memory "
+        "requirements. Default value: 0 (automatically select appropriate "
+        "precision)' default='0'/>"
+"   <Option name='PROGRESSION' type='string-select' description="
+        "'The organization of the coded data in the file can be set by this "
+        "property tag. The following progression orders are defined: "
+        "LRCP = Quality progressive, "
+        "RLCP = Resolution then quality progressive, "
+        "RPCL = Resolution then position progressive, "
+        "PCRL = Position progressive, "
+        "CPRL = Color/channel progressive. "
+        "The setting LRCP (quality) is most useful when used with several "
+        "layers. The PCRL (position) should be used with precincts.' "
+        "default='LRCP'>"
+"       <Value>LRCP</Value>"
+"       <Value>RLCP</Value>"
+"       <Value>RPCL</Value>"
+"       <Value>PCRL</Value>"
+"       <Value>CPRL</Value>"
+"   </Option>"
+"   <Option name='REVERSIBLE' type='boolean' description="
+        "'The reversible (Filter 5_3) and irreversible (Filter 9_7), may be "
+        "selected using this property.' default='FALSE'/>"
+"   <Option name='LEVELS' type='int' description="
+        "'The number of wavelet transformation levels can be set using this "
+        "property. Valid values are in the range 0 (no wavelet analysis) to "
+        "16 (very fine analysis). The memory requirements and compression time "
+        "increases with the number of transformation levels. A reasonable "
+        "number of transformation levels is in the 4-6 range.' "
+        "min='0' max='16' default='5'/>"
+"   <Option name='QUANTIZATION_STYLE' type='string-select' description="
+        "'This property may only be set when the irreversible filter (9_7) is "
+        "used. The quantization steps can either be derived from a bases "
+        "quantization step, DERIVED, or calculated for each image sub-band, "
+        "EXPOUNDED.The EXPOUNDED style is recommended when using the "
+        "irreversible filter.' default='EXPOUNDED'>"
+"       <Value>DERIVED</Value>"
+"       <Value>EXPOUNDED</Value>"
+"   </Option>"
+"   <Option name='TILEXSIZE' type='int' description="
+        "'Tile Width. An image can  be split into smaller tiles, with each "
+        "tile independently compressed. The basic tile size and the offset to "
+        "the first tile on the virtual compression reference grid can be set "
+        "using these properties. The first tile must contain the first image "
+        "pixel. The tiling of an image is recommended only for very large "
+        "images. Default value: (0) One Tile containing the complete image."
+        "' default='0'/>"
+"   <Option name='TILEYSIZE' type='int' description="
+        "'Tile Height. An image can be split into smaller tiles, with each "
+        "tile independently compressed. The basic tile size and the offset to "
+        "the first tile on the virtual compression reference grid can be set "
+        "using these properties. The first tile must contain the first image "
+        "pixel. The tiling of an image is recommended only for very large "
+        "images. Default value: (0) One Tile containing the complete image."
+        "' default='0'/>"
+"   <Option name='TLM' type='boolean' description="
+    "'The efficiency of decoding regions in a tiled image may be improved by "
+    "the usage of a tile length marker. Tile length markers contain the "
+    "position of each tile in a JPEG2000 codestream, enabling faster access "
+    "to tiled data.' default='FALSE'/>"
+"   <Option name='CODEBLOCK_WIDTH' type='int' description="
+        "'The size of the blocks of data coded with the arithmetic entropy "
+        "coder may be set using these parameters. A codeblock may contain no "
+        "more than  4096 (result of CODEBLOCK_WIDTH x CODEBLOCK_HEIGHT) "
+        "samples. Smaller codeblocks can aid the decoding of regions of an "
+        "image and error resilience.' min='4' max='1024' default='64'/>"
+"   <Option name='CODEBLOCK_HEIGHT' type='int' description="
+        "'The size of the blocks of data coded with the arithmetic entropy "
+        "coder may be set using these parameters. A codeblock may contain no "
+        "more than  4096 (result of CODEBLOCK_WIDTH x CODEBLOCK_HEIGHT) "
+        "samples. Smaller codeblocks can aid the decoding of regions of an "
+        "image and error resilience.' min='4' max='1024' default='64'/>"
+"   <Option name='ERROR_RESILIENCE' type='boolean' description="
+        "'This option improves error resilient in JPEG2000 streams or for "
+        "special codecs (e.g. hardware coder) for a faster compression/"
+        "decompression. This option will increase the file size slightly when "
+        "generating a code stream with the same image quality.' default='NO'/>"
+"   <Option name='WRITE_METADATA' type='boolean' description="
+        "'Whether metadata should be written, in a dedicated JP2 XML box' "
+        "default='NO'/>"
+"   <Option name='MAIN_MD_DOMAIN_ONLY' type='boolean' description="
+        "'(Only if WRITE_METADATA=YES) Whether only metadata from the main "
+        "domain should be written' default='NO'/>"
+"   <Option name='USE_SRC_CODESTREAM' type='boolean' description="
+        "'When source dataset is JPEG2000, whether to reuse the codestream of "
+        "the source dataset unmodified' default='NO'/>"
+"   <Option name='NBITS' type='int' description="
+        "'Bits (precision) for sub-byte files (1-7), sub-uint16 (9-15), "
+        "sub-uint32 (17-28)'/>"
+"</CreationOptionList>"  );
+
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+        poDriver->pfnIdentify = JP2LuraDataset::Identify;
+        poDriver->pfnOpen = JP2LuraDataset::Open;
+        poDriver->pfnCreateCopy = JP2LuraDataset::CreateCopy;
+
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
+
diff --git a/frmts/jp2lura/jp2luradataset.h b/frmts/jp2lura/jp2luradataset.h
new file mode 100644
index 0000000..6ddb987
--- /dev/null
+++ b/frmts/jp2lura/jp2luradataset.h
@@ -0,0 +1,92 @@
+/******************************************************************************
+ * Project:  GDAL
+ * Author:   Raul Alonso Reyes <raul dot alonsoreyes at satcen dot europa dot eu>
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ * Purpose:  JPEG-2000 driver based on Lurawave library, driver developed by SatCen
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, SatCen - European Union Satellite Centre
+ * Copyright (c) 2016, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef JP2LURADATASET_H_INCLUDED
+#define JP2LURADATASET_H_INCLUDED
+
+#include "gdaljp2abstractdataset.h"
+#include "jp2luracallbacks.h"
+#include "gdaljp2metadata.h"
+
+class JP2LuraDataset : public GDALJP2AbstractDataset
+{
+    friend class JP2LuraRasterBand;
+
+    VSILFILE   *fp; // Large FILE API 
+
+    int         iLevel;
+    int         nOverviewCount;
+    JP2LuraDataset** papoOverviewDS;
+    GDALJP2Lura_Output_Data sOutputData;
+    GDALColorTable* poCT;
+    JP2_Colorspace eColorspace;
+    int            nRedIndex;
+    int            nGreenIndex;
+    int            nBlueIndex;
+    int            nAlphaIndex;
+
+#ifdef ENABLE_MEMORY_REGISTRAR
+    JP2LuraMemoryRegistrar oMemoryRegistrar;
+#endif
+
+public:
+    JP2LuraDataset();
+    ~JP2LuraDataset();
+
+    static int Identify(GDALOpenInfo * poOpenInfo);
+    static GDALDataset  *Open(GDALOpenInfo *);
+    static GDALDataset  *CreateCopy(const char * pszFilename,
+            GDALDataset *poSrcDS,
+            int bStrict, char ** papszOptions,
+            GDALProgressFunc pfnProgress,
+            void * pProgressData);
+
+
+    virtual CPLErr  IRasterIO(GDALRWFlag eRWFlag,
+            int nXOff, int nYOff, int nXSize, int nYSize,
+            void * pData, int nBufXSize, int nBufYSize,
+            GDALDataType eBufType,
+            int nBandCount, int *panBandMap,
+            GSpacing nPixelSpace, GSpacing nLineSpace,
+            GSpacing nBandSpace,
+            GDALRasterIOExtraArg* psExtraArg) override;
+
+
+    static void         WriteBox(VSILFILE* fp, GDALJP2Box* poBox);
+    static void         WriteGDALMetadataBox(VSILFILE* fp, GDALDataset* poSrcDS,
+                                             char** papszOptions);
+    static void         WriteXMLBoxes(VSILFILE* fp, GDALDataset* poSrcDS,
+                                      char** papszOptions);
+    static void         WriteXMPBox(VSILFILE* fp, GDALDataset* poSrcDS,
+                                    char** papszOptions);
+
+    static const char*  GetErrorMessage( long nErrorCode );
+};
+
+#endif
\ No newline at end of file
diff --git a/frmts/jp2lura/jp2lurarasterband.cpp b/frmts/jp2lura/jp2lurarasterband.cpp
new file mode 100644
index 0000000..50758a0
--- /dev/null
+++ b/frmts/jp2lura/jp2lurarasterband.cpp
@@ -0,0 +1,420 @@
+/******************************************************************************
+ * Project:  GDAL
+ * Author:   Raul Alonso Reyes <raul dot alonsoreyes at satcen dot europa dot eu>
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ * Purpose:  JPEG-2000 driver based on Lurawave library, driver developed by SatCen
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, SatCen - European Union Satellite Centre
+ * Copyright (c) 2016, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "jp2lurarasterband.h"
+#include "jp2luradataset.h"
+
+/************************************************************************/
+/*                        JP2LuraRasterBand()                           */
+/************************************************************************/
+
+JP2LuraRasterBand::JP2LuraRasterBand(JP2LuraDataset *poDSIn, int nBandIn,
+                                     GDALDataType eDataTypeIn,
+                                     int nBits,
+                                     int nBlockXSizeIn, int nBlockYSizeIn)
+
+{
+    eDataType = eDataTypeIn;
+    nBlockXSize = nBlockXSizeIn;
+    nBlockYSize = nBlockYSizeIn;
+    poDS = poDSIn;
+    nRasterXSize = poDSIn->nRasterXSize;
+    nRasterYSize = poDSIn->nRasterYSize;
+    nBand = nBandIn;
+
+    if (nRasterXSize == nBlockXSize && nRasterYSize == nBlockYSize)
+    {
+    /* -------------------------------------------------------------------- */
+    /*      Use a 2048x128 "virtual" block size unless the file is small.   */
+    /* -------------------------------------------------------------------- */
+        if (nRasterXSize >= 2048)
+        {
+            nBlockXSize = 2048;
+        }
+        else
+        {
+            nBlockXSize = nRasterXSize;
+        }
+
+        if (nRasterYSize >= 128)
+        {
+            nBlockYSize = 128;
+        }
+        else
+        {
+            nBlockYSize = nRasterYSize;
+        }
+    }
+
+    if( (nBits % 8) != 0 )
+    {
+        GDALRasterBand::SetMetadataItem("NBITS",
+                        CPLString().Printf("%d",nBits),
+                        "IMAGE_STRUCTURE" );
+    }
+    GDALRasterBand::SetMetadataItem("COMPRESSION", "JPEG2000",
+                    "IMAGE_STRUCTURE" );
+
+    bForceCachedIO = FALSE;
+}
+
+/************************************************************************/
+/*                      ~JP2OpenJPEGRasterBand()                        */
+/************************************************************************/
+
+JP2LuraRasterBand::~JP2LuraRasterBand()
+{
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr JP2LuraRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
+                                     void * pImage)
+{
+    JP2LuraDataset *poGDS = reinterpret_cast<JP2LuraDataset *>(poDS);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("JP2Lura", "IReadBlock(nBand=%d,nLevel=%d %d,%d)",
+             nBand, poGDS->iLevel, nBlockXOff, nBlockYOff);
+#endif
+    int nXOff = nBlockXOff * nBlockXSize;
+    int nYOff = nBlockYOff * nBlockYSize;
+    int nXSize = nBlockXSize;
+    int nYSize = nBlockYSize;
+    if( nXOff + nXSize > nRasterXSize )
+        nXSize = nRasterXSize - nXOff;
+    if( nYOff + nYSize > nRasterYSize )
+        nYSize = nRasterYSize - nYOff;
+    GDALRasterIOExtraArg sExtraArgs;
+    INIT_RASTERIO_EXTRA_ARG(sExtraArgs);
+    const int nDTSizeBytes = GDALGetDataTypeSizeBytes(eDataType);
+    CPLErr eErr = IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
+                            pImage, nXSize, nYSize,
+                            eDataType,
+                            nDTSizeBytes,
+                            nDTSizeBytes * nXSize,
+                            &sExtraArgs);
+
+    // Unpack previously packed buffer if needed
+    if( eErr == CE_None && nXSize < nBlockXSize )
+    {
+        GByte* pabyData = reinterpret_cast<GByte*>(pImage);
+        for( int j = nYSize - 1; j >= 0; --j )
+        {
+            memmove( pabyData + j * nBlockXSize * nDTSizeBytes,
+                     pabyData + j * nXSize * nDTSizeBytes,
+                     nXSize * nDTSizeBytes );
+        }
+    }
+
+    // Caching other bands while we have the cached buffer valid
+    for( int iBand = 1;eErr == CE_None && iBand <= poGDS->nBands; iBand++ )
+    {
+        if( iBand == nBand )
+            continue;
+        JP2LuraRasterBand* poOtherBand =
+            reinterpret_cast<JP2LuraRasterBand*>(poGDS->GetRasterBand(iBand));
+        GDALRasterBlock* poBlock = poOtherBand->
+                                TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
+        if (poBlock != NULL)
+        {
+            poBlock->DropLock();
+            continue;
+        }
+
+        poBlock = poOtherBand->
+                            GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
+        if (poBlock == NULL)
+        {
+            continue;
+        }
+
+        GByte* pabyData = reinterpret_cast<GByte*>(poBlock->GetDataRef());
+        eErr = poOtherBand->IRasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize,
+                        pabyData, nXSize, nYSize,
+                        eDataType,
+                        nDTSizeBytes,
+                        nDTSizeBytes * nXSize,
+                        &sExtraArgs);
+
+        // Unpack previously packed buffer if needed
+        if( eErr == CE_None && nXSize < nBlockXSize )
+        {
+            for( int j = nYSize - 1; j >= 0; --j )
+            {
+                memmove( pabyData + j * nBlockXSize * nDTSizeBytes,
+                        pabyData + j * nXSize * nDTSizeBytes,
+                        nXSize * nDTSizeBytes );
+            }
+        }
+
+        poBlock->DropLock();
+    }
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr JP2LuraRasterBand::IRasterIO(GDALRWFlag eRWFlag,
+                                    int nXOff, int nYOff, int nXSize, int nYSize,
+                                    void * pData, int nBufXSize, int nBufYSize,
+                                    GDALDataType eBufType,
+                                    GSpacing nPixelSpace, GSpacing nLineSpace,
+                                    GDALRasterIOExtraArg* psExtraArg)
+{
+    JP2LuraDataset *poGDS = reinterpret_cast<JP2LuraDataset *>(poDS);
+    const int nBufTypeSize = GDALGetDataTypeSizeBytes(eBufType);
+
+    if (eRWFlag != GF_Read)
+        return CE_Failure;
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("JP2Lura", "RasterIO(nBand=%d,nLevel=%d %d,%d,%dx%d -> %dx%d)",
+             nBand, poGDS->iLevel, nXOff, nYOff, nXSize, nYSize,
+             nBufXSize, nBufYSize);
+#endif
+    if( eBufType != eDataType ||
+        nPixelSpace != nBufTypeSize ||
+        nLineSpace != nPixelSpace * nBufXSize )
+    {
+        return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                        pData, nBufXSize, nBufYSize, eBufType,
+                                        nPixelSpace, nLineSpace, psExtraArg);
+    }
+
+    // Use cached data
+    if( poGDS->sOutputData.nXOff == nXOff &&
+        poGDS->sOutputData.nYOff == nYOff &&
+        poGDS->sOutputData.nXSize == nXSize &&
+        poGDS->sOutputData.nYSize == nYSize &&
+        poGDS->sOutputData.nBufXSize == nBufXSize &&
+        poGDS->sOutputData.nBufYSize == nBufYSize &&
+        poGDS->sOutputData.eBufType == eBufType )
+    {
+        if (poGDS->sOutputData.pDatacache[nBand - 1] != NULL)
+        {
+#ifdef DEBUG_VERBOSE
+            CPLDebug("JP2Lura", "Using cached data");
+#endif
+            memcpy(pData, poGDS->sOutputData.pDatacache[nBand - 1],
+                   static_cast<size_t>(nBufXSize)*nBufYSize*nBufTypeSize);
+            return CE_None;
+        }
+    }
+
+    /* ==================================================================== */
+    /*      Do we have overviews that would be appropriate to satisfy       */
+    /*      this request?                                                   */
+    /* ==================================================================== */
+    if ((nBufXSize < nXSize || nBufYSize < nYSize)
+            && GetOverviewCount() > 0 && eRWFlag == GF_Read)
+    {
+        int         nOverview;
+        GDALRasterIOExtraArg sExtraArg;
+
+        GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
+
+        nOverview = GDALBandGetBestOverviewLevel2(
+                                        this, nXOff, nYOff, nXSize, nYSize,
+                                        nBufXSize, nBufYSize, &sExtraArg);
+        if (nOverview >= 0)
+        {
+            GDALRasterBand* poOverviewBand = GetOverview(nOverview);
+            if (poOverviewBand == NULL)
+                    return CE_Failure;
+
+            return poOverviewBand->RasterIO(
+                                eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                pData, nBufXSize, nBufYSize, eBufType,
+                                nPixelSpace, nLineSpace, &sExtraArg);
+        }
+    }
+
+    if( nBufXSize != nXSize || nBufYSize != nYSize )
+    {
+        return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                        pData, nBufXSize, nBufYSize, eBufType,
+                                        nPixelSpace, nLineSpace, psExtraArg);
+    }
+
+    JP2_Error error = 0;
+    const short factor = 1 << poGDS->iLevel;
+
+    JP2_Rect comp_region;
+    comp_region.ulLeft = nXOff;
+    comp_region.ulRight = nXOff + nXSize;
+    comp_region.ulTop = nYOff;
+    comp_region.ulBottom = nYOff + nYSize;
+
+    error = JP2_Decompress_SetProp(poGDS->sOutputData.handle,
+                                   cJP2_Prop_Scale_Down, factor);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).",
+                 JP2LuraDataset::GetErrorMessage(error));
+        return CE_Failure;
+    }
+
+    poGDS->sOutputData.pimage = reinterpret_cast<unsigned char*>(pData);
+
+    poGDS->sOutputData.nXOff = nXOff;
+    poGDS->sOutputData.nYOff = nYOff;
+    poGDS->sOutputData.nXSize = nXSize;
+    poGDS->sOutputData.nYSize = nYSize;
+    poGDS->sOutputData.nBufXSize = nBufXSize;
+    poGDS->sOutputData.nBufYSize = nBufYSize;
+    poGDS->sOutputData.eBufType = eBufType;
+
+    poGDS->sOutputData.nBand = nBand;
+    poGDS->sOutputData.nBands = poGDS->nBands;
+    if( poGDS->sOutputData.pDatacache == NULL )
+    {
+        poGDS->sOutputData.pDatacache = reinterpret_cast<unsigned char**>
+                            (CPLCalloc( poGDS->nBands, sizeof(unsigned char*)));
+    }
+
+    for (int i = 0; i < poGDS->nBands; i++)
+    {
+        if (poGDS->sOutputData.pDatacache[i] != NULL)
+        {
+            VSIFree(poGDS->sOutputData.pDatacache[i]);
+            poGDS->sOutputData.pDatacache[i] = NULL;
+        }
+        if (i == nBand-1)
+            continue;
+        poGDS->sOutputData.pDatacache[i] =
+            reinterpret_cast<unsigned char*>(VSIMalloc(
+                        static_cast<size_t>(nBufXSize)*nBufYSize*nBufTypeSize));
+    }
+
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+    /* Set the callback function and parameter      */
+    /*++++++++++++++++++++++++++++++++++++++++++++++*/
+
+    error = JP2_Decompress_SetProp(poGDS->sOutputData.handle,
+                cJP2_Prop_Output_Parameter,
+                reinterpret_cast<JP2_Property_Value>(&(poGDS->sOutputData)));
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).",
+                 JP2LuraDataset::GetErrorMessage(error));
+        return CE_Failure;
+    }
+
+    error = JP2_Decompress_SetProp(poGDS->sOutputData.handle,
+                    cJP2_Prop_Output_Function,
+                    reinterpret_cast<JP2_Property_Value>(
+                                    GDALJP2Lura_Callback_Decompress_Write));
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error (%s).",
+                 JP2LuraDataset::GetErrorMessage(error));
+        return CE_Failure;
+    }
+
+    error = JP2_Decompress_Region(poGDS->sOutputData.handle, comp_region);
+    if( error )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Internal library error during decompress region (%s).",
+                 JP2LuraDataset::GetErrorMessage(error));
+        return CE_Failure;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                         GetOverviewCount()                           */
+/************************************************************************/
+
+int JP2LuraRasterBand::GetOverviewCount()
+{
+    JP2LuraDataset *poGDS = reinterpret_cast<JP2LuraDataset *>(poDS);
+    return poGDS->nOverviewCount;
+}
+
+/************************************************************************/
+/*                            GetOverview()                             */
+/************************************************************************/
+
+GDALRasterBand* JP2LuraRasterBand::GetOverview(int iOvrLevel)
+{
+    JP2LuraDataset *poGDS = reinterpret_cast<JP2LuraDataset *>(poDS);
+    if (iOvrLevel < 0 || iOvrLevel >= poGDS->nOverviewCount)
+        return NULL;
+
+    return poGDS->papoOverviewDS[iOvrLevel]->GetRasterBand(nBand);
+}
+
+/************************************************************************/
+/*                       GetColorInterpretation()                       */
+/************************************************************************/
+
+GDALColorInterp JP2LuraRasterBand::GetColorInterpretation()
+{
+    JP2LuraDataset *poGDS = reinterpret_cast<JP2LuraDataset *>(poDS);
+
+    if( poGDS->poCT )
+        return GCI_PaletteIndex;
+
+    if( nBand == poGDS->nAlphaIndex + 1 )
+        return GCI_AlphaBand;
+
+    if (poGDS->nBands <= 2 && poGDS->eColorspace == cJP2_Colorspace_Gray)
+        return GCI_GrayIndex;
+    else if (poGDS->eColorspace == cJP2_Colorspace_RGBa)
+    {
+        if( nBand == poGDS->nRedIndex + 1 )
+            return GCI_RedBand;
+        if( nBand == poGDS->nGreenIndex + 1 )
+            return GCI_GreenBand;
+        if( nBand == poGDS->nBlueIndex + 1 )
+            return GCI_BlueBand;
+    }
+
+    return GCI_Undefined;
+}
+
+/************************************************************************/
+/*                          GetColorTable()                             */
+/************************************************************************/
+
+GDALColorTable* JP2LuraRasterBand::GetColorTable()
+{
+    JP2LuraDataset *poGDS = reinterpret_cast<JP2LuraDataset *>(poDS);
+    return poGDS->poCT;
+}
diff --git a/frmts/jp2lura/jp2lurarasterband.h b/frmts/jp2lura/jp2lurarasterband.h
new file mode 100644
index 0000000..519b6ad
--- /dev/null
+++ b/frmts/jp2lura/jp2lurarasterband.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ * Project:  GDAL
+ * Author:   Raul Alonso Reyes <raul dot alonsoreyes at satcen dot europa dot eu>
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ * Purpose:  JPEG-2000 driver based on Lurawave library, driver developed by SatCen
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, SatCen - European Union Satellite Centre
+ * Copyright (c) 2016, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef JP2LURARASTERBAND_H_INCLUDED
+#define JP2LURARASTERBAND_H_INCLUDED
+
+#include "gdal_pam.h"
+
+class JP2LuraDataset;
+
+class JP2LuraRasterBand : public GDALPamRasterBand
+{
+        friend class JP2LuraDataset;
+
+
+public:
+
+        JP2LuraRasterBand(JP2LuraDataset * poDS, int nBand,
+                          GDALDataType eDataType,
+                          int nBits,
+                          int nBlockXSize, int nBlockYSize);
+        ~JP2LuraRasterBand();
+
+        virtual CPLErr          IReadBlock(int, int, void *) override;
+        virtual CPLErr          IRasterIO(GDALRWFlag eRWFlag,
+                int nXOff, int nYOff, int nXSize, int nYSize,
+                void * pData, int nBufXSize, int nBufYSize, GDALDataType eBufType,
+                GSpacing nPixelSpace, GSpacing nLineSpace,
+                GDALRasterIOExtraArg* psExtraArg) override;
+
+        virtual int             GetOverviewCount() override;
+        virtual GDALRasterBand* GetOverview(int iOvrLevel) override;
+
+        virtual GDALColorInterp GetColorInterpretation() override;
+        virtual GDALColorTable* GetColorTable() override;
+};
+
+#endif
\ No newline at end of file
diff --git a/frmts/jp2lura/makefile.vc b/frmts/jp2lura/makefile.vc
new file mode 100644
index 0000000..db274ac
--- /dev/null
+++ b/frmts/jp2lura/makefile.vc
@@ -0,0 +1,32 @@
+
+OBJ	=	jp2luracallbacks.obj jp2lurarasterband.obj jp2luradataset.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS = -I.. $(LURATECH_CFLAGS)
+
+PLUGIN_DLL =	gdal_JP2Lura.dll
+
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+    -del $(PLUGIN_DLL)
+	-del *.exp
+	-del *.manifest
+    -del *.lib
+
+plugin:	$(PLUGIN_DLL)
+
+$(PLUGIN_DLL): $(OBJ)
+	link /dll $(LDEBUG) /out:$(PLUGIN_DLL) $(OBJ) $(GDALLIB) $(LURATECH_LIB)
+	if exist $(PLUGIN_DLL).manifest mt -manifest $(PLUGIN_DLL).manifest -outputresource:$(PLUGIN_DLL);2
+
+plugin-install:
+	-mkdir $(PLUGINDIR)
+	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
+
diff --git a/frmts/jpeg/GNUmakefile b/frmts/jpeg/GNUmakefile
index 4cb2c31..7784c0b 100644
--- a/frmts/jpeg/GNUmakefile
+++ b/frmts/jpeg/GNUmakefile
@@ -16,7 +16,7 @@ OBJ	=	\
 XTRA_OPT	=	-Ilibjpeg -DDEFAULT_MAX_MEM=500000000L
 else
 OBJ	=	jpgdataset.o vsidataio.o
-XTRA_OPT	=	
+XTRA_OPT	=
 endif
 
 ifeq ($(JPEG12_ENABLED),yes)
@@ -33,7 +33,7 @@ OBJ :=	jcapimin12.o jcapistd12.o jccoefct12.o jccolor12.o jcdctmgr12.o jchuff12.
         $(OBJ) jpgdataset_12.o vsidataio_12.o
 endif
 
-CPPFLAGS	:=	$(XTRA_OPT)  $(CPPFLAGS) -I../mem -DENABLE_LIBJPEG_NO_RETURN
+CPPFLAGS	:=	-I../mem $(XTRA_OPT)  $(CPPFLAGS)  -DENABLE_LIBJPEG_NO_RETURN
 # # Enable this to compile with -Wextra -Werror and get around the jump complaint.
 # CPPFLAGS += -Wno-clobbered
 
diff --git a/frmts/jpeg/jpgdataset.cpp b/frmts/jpeg/jpgdataset.cpp
index b74b8b8..7f68967 100644
--- a/frmts/jpeg/jpgdataset.cpp
+++ b/frmts/jpeg/jpgdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: jpgdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
@@ -33,13 +32,44 @@
 
 #undef ENABLE_LIBJPEG_NO_RETURN
 
+#include "cpl_port.h"
+#include "jpgdataset.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <setjmp.h>
+
+#include <algorithm>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
 #include "gdalexif.h"
+CPL_C_START
+#ifdef LIBJPEG_12_PATH
+#  include LIBJPEG_12_PATH
+#else
+#  include "jpeglib.h"
+#endif
+CPL_C_END
 #include "memdataset.h"
+#include "vsidataio.h"
 
-#include <setjmp.h>
+CPL_CVSID("$Id: jpgdataset.cpp 37527 2017-02-28 23:13:34Z rouault $");
 
 static const int TIFF_VERSION = 42;
 
@@ -51,307 +81,26 @@ static const int JPEG_TIFF_IMAGEHEIGHT     = 0x101;
 static const int JPEG_TIFF_COMPRESSION     = 0x103;
 static const int JPEG_EXIF_JPEGIFOFSET     = 0x201;
 static const int JPEG_EXIF_JPEGIFBYTECOUNT = 0x202;
-/*
- * TIFF header.
- */
-typedef struct {
-        GUInt16  tiff_magic;     /* magic number (defines byte order) */
-        GUInt16  tiff_version;   /* TIFF version number */
-        GUInt32  tiff_diroff;    /* byte offset to first directory */
-} TIFFHeader;
-
-CPL_CVSID("$Id: jpgdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 
-CPL_C_START
-#ifdef LIBJPEG_12_PATH
-#  include LIBJPEG_12_PATH
-#else
-#  include "jpeglib.h"
-#endif
-CPL_C_END
-
-// we believe it is ok to use setjmp() in this situation.
+// Ok to use setjmp().
 #ifdef _MSC_VER
 #  pragma warning(disable:4611)
 #endif
 
-typedef struct
-{
-    const char* pszFilename;
-    VSILFILE* fpLin;
-    char** papszSiblingFiles;
-    int nScaleFactor;
-    int bDoPAMInitialize;
-    int bUseInternalOverviews;
-} JPGDatasetOpenArgs;
-
 
-#if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
-GDALDataset* JPEGDataset12Open(JPGDatasetOpenArgs* psArgs);
-GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
-                                    GDALDataset *poSrcDS,
-                                    int bStrict, char ** papszOptions,
-                                    GDALProgressFunc pfnProgress,
-                                    void * pProgressData );
-#endif
-
-#include "vsidataio.h"
 
-/*
-* Do we want to do special processing suitable for when JSAMPLE is a
-* 16bit value?
-*/
+// Do we want to do special processing suitable for when JSAMPLE is a
+// 16bit value?
 #if defined(JPEG_LIB_MK1)
 #  define JPEG_LIB_MK1_OR_12BIT 1
 #elif BITS_IN_JSAMPLE == 12
 #  define JPEG_LIB_MK1_OR_12BIT 1
 #endif
 
-class JPGDatasetCommon;
-GDALRasterBand* JPGCreateBand(JPGDatasetCommon* poDS, int nBand);
-
-typedef void (*my_jpeg_write_m_header) (void* cinfo, int marker, unsigned int datalen);
-typedef void (*my_jpeg_write_m_byte) (void* cinfo, int val);
-
-CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
-                      GDALProgressFunc pfnProgress, void * pProgressData );
-void   JPGAddEXIFOverview( GDALDataType eWorkDT,
-                           GDALDataset* poSrcDS, char** papszOptions,
-                           void* cinfo,
-                           my_jpeg_write_m_header p_jpeg_write_m_header,
-                           my_jpeg_write_m_byte p_jpeg_write_m_byte,
-                           GDALDataset *(pCreateCopy)( const char *, GDALDataset *,
-                                     int, char **,
-                                     GDALProgressFunc pfnProgress,
-                                     void * pProgressData ) );
-void JPGAddICCProfile( void *pInfo,
-                       const char *pszICCProfile,
-                       my_jpeg_write_m_header p_jpeg_write_m_header,
-                       my_jpeg_write_m_byte p_jpeg_write_m_byte);
-
-typedef struct GDALJPEGErrorStruct
-{
-    jmp_buf     setjmp_buffer;
-    int         bNonFatalErrorEncountered;
-    void      (*p_previous_emit_message)(j_common_ptr cinfo, int msg_level);
-    GDALJPEGErrorStruct() :
-        bNonFatalErrorEncountered(FALSE),
-        p_previous_emit_message(NULL)
-    {
-        memset(&setjmp_buffer, 0, sizeof(setjmp_buffer));
-    }
-} GDALJPEGErrorStruct;
-
-/************************************************************************/
-/* ==================================================================== */
-/*                         JPGDatasetCommon                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class JPGRasterBand;
-class JPGMaskBand;
-
-class JPGDatasetCommon : public GDALPamDataset
-{
-protected:
-    friend class JPGRasterBand;
-    friend class JPGMaskBand;
-
-    int           nScaleFactor;
-    int           bHasInitInternalOverviews;
-    int           nInternalOverviewsCurrent;
-    int           nInternalOverviewsToFree;
-    GDALDataset** papoInternalOverviews;
-    void          InitInternalOverviews();
-    GDALDataset*  InitEXIFOverview();
-
-    char   *pszProjection;
-    int    bGeoTransformValid;
-    double adfGeoTransform[6];
-    int    nGCPCount;
-    GDAL_GCP *pasGCPList;
-
-    VSILFILE   *fpImage;
-    GUIntBig nSubfileOffset;
-
-    int    nLoadedScanline;
-    GByte  *pabyScanline;
-
-    int    bHasReadEXIFMetadata;
-    int    bHasReadXMPMetadata;
-    int    bHasReadICCMetadata;
-    char   **papszMetadata;
-    char   **papszSubDatasets;
-    int    bigendian;
-    int    nExifOffset;
-    int    nInterOffset;
-    int    nGPSOffset;
-    int    bSwabflag;
-    int    nTiffDirStart;
-    int    nTIFFHEADER;
-    int    bHasDoneJpegCreateDecompress;
-    int    bHasDoneJpegStartDecompress;
-
-    virtual CPLErr LoadScanline(int) = 0;
-    virtual CPLErr Restart() = 0;
-
-    virtual int GetDataPrecision() = 0;
-    virtual int GetOutColorSpace() = 0;
-
-    int    EXIFInit(VSILFILE *);
-    void   ReadICCProfile();
-
-    void   CheckForMask();
-    void   DecompressMask();
-
-    void   ReadEXIFMetadata();
-    void   ReadXMPMetadata();
-
-    int    bHasCheckedForMask;
-    JPGMaskBand *poMaskBand;
-    GByte  *pabyBitMask;
-    int     bMaskLSBOrder;
-
-    GByte  *pabyCMask;
-    int    nCMaskSize;
-
-    // Color space exposed by GDAL.  Not necessarily the in_color_space nor
-    // the out_color_space of JPEG library.
-    J_COLOR_SPACE eGDALColorSpace;
-
-    int    bIsSubfile;
-    int    bHasTriedLoadWorldFileOrTab;
-    void   LoadWorldFileOrTab();
-    CPLString osWldFilename;
-
-    virtual int         CloseDependentDatasets();
-
-    virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
-
-  public:
-                 JPGDatasetCommon();
-    virtual ~JPGDatasetCommon();
-
-    virtual CPLErr      IRasterIO( GDALRWFlag, int, int, int, int,
-                                   void *, int, int, GDALDataType,
-                                   int, int *,
-                                   GSpacing nPixelSpace, GSpacing nLineSpace,
-                                   GSpacing nBandSpace,
-                                   GDALRasterIOExtraArg* psExtraArg );
-
-    virtual CPLErr GetGeoTransform( double * );
-
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-
-    virtual char      **GetMetadataDomainList();
-    virtual char  **GetMetadata( const char * pszDomain = "" );
-    virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
-
-    virtual char **GetFileList(void);
-
-    virtual void FlushCache(void);
-
-    static int          Identify( GDALOpenInfo * );
-    static GDALDataset *Open( GDALOpenInfo * );
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                              JPGDataset                              */
-/* ==================================================================== */
-/************************************************************************/
-
-class JPGDataset : public JPGDatasetCommon
-{
-    GDALJPEGErrorStruct sErrorStruct;
-
-    int           ErrorOutOnNonFatalError();
-
-    static void EmitMessage(j_common_ptr cinfo, int msg_level);
-
-    struct jpeg_decompress_struct sDInfo;
-    struct jpeg_error_mgr sJErr;
-
-    virtual CPLErr LoadScanline(int);
-    virtual CPLErr Restart();
-    virtual int GetDataPrecision() { return sDInfo.data_precision; }
-    virtual int GetOutColorSpace() { return sDInfo.out_color_space; }
-
-    int    nQLevel;
-#if !defined(JPGDataset)
-    void   LoadDefaultTables(int);
-#endif
-    void   SetScaleNumAndDenom();
-
-  public:
-                 JPGDataset();
-    virtual ~JPGDataset();
-
-    static GDALDataset *Open( JPGDatasetOpenArgs* psArgs );
-    static GDALDataset* CreateCopy( const char * pszFilename,
-                                    GDALDataset *poSrcDS,
-                                    int bStrict, char ** papszOptions,
-                                    GDALProgressFunc pfnProgress,
-                                    void * pProgressData );
-
-    static void ErrorExit(j_common_ptr cinfo);
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            JPGRasterBand                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class JPGRasterBand : public GDALPamRasterBand
-{
-    friend class JPGDatasetCommon;
-
-    /* We have to keep a pointer to the JPGDataset that this JPGRasterBand
-       belongs to. In some case, we may have this->poGDS != this->poDS
-       For example for a JPGRasterBand that is set to a NITFDataset...
-       In other words, this->poDS doesn't necessary point to a JPGDataset
-       See ticket #1807.
-    */
-    JPGDatasetCommon   *poGDS;
-
-  public:
-                   JPGRasterBand( JPGDatasetCommon *, int );
-    virtual ~JPGRasterBand() {}
-
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
-
-    virtual GDALRasterBand *GetMaskBand();
-    virtual int             GetMaskFlags();
-
-    virtual GDALRasterBand *GetOverview(int i);
-    virtual int             GetOverviewCount();
-};
 
 #if !defined(JPGDataset)
 
 /************************************************************************/
-/* ==================================================================== */
-/*                             JPGMaskBand                              */
-/* ==================================================================== */
-/************************************************************************/
-
-class JPGMaskBand : public GDALRasterBand
-{
-  protected:
-    virtual CPLErr IReadBlock( int, int, void * );
-
-  public:
-                JPGMaskBand( JPGDataset *poDS );
-    virtual ~JPGMaskBand() {}
-};
-
-/************************************************************************/
 /*                       ReadEXIFMetadata()                             */
 /************************************************************************/
 void JPGDatasetCommon::ReadEXIFMetadata()
@@ -361,10 +110,10 @@ void JPGDatasetCommon::ReadEXIFMetadata()
 
     CPLAssert(papszMetadata == NULL);
 
-    /* Save current position to avoid disturbing JPEG stream decoding */
-    vsi_l_offset nCurOffset = VSIFTellL(fpImage);
+    // Save current position to avoid disturbing JPEG stream decoding.
+    const vsi_l_offset nCurOffset = VSIFTellL(fpImage);
 
-    if( EXIFInit(fpImage) )
+    if(EXIFInit(fpImage))
     {
         EXIFExtractMetadata(papszMetadata,
                             fpImage, nTiffDirStart,
@@ -390,19 +139,19 @@ void JPGDatasetCommon::ReadEXIFMetadata()
                                 nExifOffset, nInterOffset, nGPSOffset);
         }
 
-        /* Avoid setting the PAM dirty bit just for that */
-        int nOldPamFlags = nPamFlags;
+        // Avoid setting the PAM dirty bit just for that.
+        const int nOldPamFlags = nPamFlags;
 
-        /* Append metadata from PAM after EXIF metadata */
+        // Append metadata from PAM after EXIF metadata.
         papszMetadata = CSLMerge(papszMetadata, GDALPamDataset::GetMetadata());
-        SetMetadata( papszMetadata );
+        SetMetadata(papszMetadata);
 
         nPamFlags = nOldPamFlags;
     }
 
-    VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
+    VSIFSeekL(fpImage, nCurOffset, SEEK_SET);
 
-    bHasReadEXIFMetadata = TRUE;
+    bHasReadEXIFMetadata = true;
 }
 
 /************************************************************************/
@@ -417,41 +166,38 @@ void JPGDatasetCommon::ReadXMPMetadata()
     if (bHasReadXMPMetadata)
         return;
 
-    /* Save current position to avoid disturbing JPEG stream decoding */
-    vsi_l_offset nCurOffset = VSIFTellL(fpImage);
+    // Save current position to avoid disturbing JPEG stream decoding.
+    const vsi_l_offset nCurOffset = VSIFTellL(fpImage);
 
-/* -------------------------------------------------------------------- */
-/*      Search for APP1 chunk.                                          */
-/* -------------------------------------------------------------------- */
+    // Search for APP1 chunk.
     // TODO(schwehr): What are these constants?
-    GByte abyChunkHeader[2+2+29] = { 0 };
+    GByte abyChunkHeader[2 + 2 + 29] = {};
     int nChunkLoc = 2;
-    int bFoundXMP = FALSE;
+    bool bFoundXMP = false;
 
     while(true)
     {
-        if( VSIFSeekL( fpImage, nChunkLoc, SEEK_SET ) != 0 )
+        if( VSIFSeekL(fpImage, nChunkLoc, SEEK_SET) != 0 )
             break;
 
-        if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage )
-            != 1 )
+        if( VSIFReadL(abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage) != 1 )
             break;
 
         nChunkLoc += 2 + abyChunkHeader[2] * 256 + abyChunkHeader[3];
-        // COM marker
+        // COM marker.
         if( abyChunkHeader[0] == 0xFF && abyChunkHeader[1] == 0xFE )
             continue;
 
         if( abyChunkHeader[0] != 0xFF
             || (abyChunkHeader[1] & 0xf0) != 0xe0 )
-            break; // Not an APP chunk.
+            break;  // Not an APP chunk.
 
-        if( abyChunkHeader[1] == 0xe1
-            && STARTS_WITH(reinterpret_cast<char *>(abyChunkHeader) + 4,
-                           "http://ns.adobe.com/xap/1.0/") )
+        if( abyChunkHeader[1] == 0xe1 &&
+            STARTS_WITH(reinterpret_cast<char *>(abyChunkHeader) + 4,
+                        "http://ns.adobe.com/xap/1.0/") )
         {
-            bFoundXMP = TRUE;
-            break; // APP1 - XMP
+            bFoundXMP = true;
+            break;  // APP1 - XMP.
         }
     }
 
@@ -460,15 +206,16 @@ void JPGDatasetCommon::ReadXMPMetadata()
         const int nXMPLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
         if (nXMPLength > 2 + 29)
         {
-          char* pszXMP = static_cast<char*>(VSIMalloc(nXMPLength - 2 - 29 + 1));
+            char *pszXMP =
+                static_cast<char *>(VSIMalloc(nXMPLength - 2 - 29 + 1));
             if (pszXMP)
             {
-                if (VSIFReadL( pszXMP, nXMPLength - 2 - 29, 1, fpImage ) == 1)
+                if (VSIFReadL(pszXMP, nXMPLength - 2 - 29, 1, fpImage) == 1)
                 {
                     pszXMP[nXMPLength - 2 - 29] = '\0';
 
-                    /* Avoid setting the PAM dirty bit just for that */
-                    int nOldPamFlags = nPamFlags;
+                    // Avoid setting the PAM dirty bit just for that.
+                    const int nOldPamFlags = nPamFlags;
 
                     char *apszMDList[2] = { pszXMP, NULL };
                     SetMetadata(apszMDList, "xml:XMP");
@@ -480,9 +227,9 @@ void JPGDatasetCommon::ReadXMPMetadata()
         }
     }
 
-    VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
+    VSIFSeekL(fpImage, nCurOffset, SEEK_SET);
 
-    bHasReadXMPMetadata = TRUE;
+    bHasReadXMPMetadata = true;
 }
 
 /************************************************************************/
@@ -499,7 +246,7 @@ char **JPGDatasetCommon::GetMetadataDomainList()
 /************************************************************************/
 /*                           GetMetadata()                              */
 /************************************************************************/
-char  **JPGDatasetCommon::GetMetadata( const char * pszDomain )
+char **JPGDatasetCommon::GetMetadata( const char *pszDomain )
 {
     if (fpImage == NULL)
         return NULL;
@@ -518,8 +265,8 @@ char  **JPGDatasetCommon::GetMetadata( const char * pszDomain )
 /************************************************************************/
 /*                       GetMetadataItem()                              */
 /************************************************************************/
-const char *JPGDatasetCommon::GetMetadataItem( const char * pszName,
-                                               const char * pszDomain )
+const char *JPGDatasetCommon::GetMetadataItem( const char *pszName,
+                                               const char *pszDomain )
 {
     if (fpImage == NULL)
         return NULL;
@@ -543,36 +290,33 @@ void JPGDatasetCommon::ReadICCProfile()
 {
     if (bHasReadICCMetadata)
         return;
-    bHasReadICCMetadata = TRUE;
+    bHasReadICCMetadata = true;
 
-    vsi_l_offset nCurOffset = VSIFTellL(fpImage);
+    const vsi_l_offset nCurOffset = VSIFTellL(fpImage);
 
     int nTotalSize = 0;
     int nChunkCount = -1;
-    int anChunkSize[256] = { 0 };
-    char *apChunk[256] = { NULL };
+    int anChunkSize[256] = {};
+    char *apChunk[256] = {};
 
-/* -------------------------------------------------------------------- */
-/*      Search for APP2 chunk.                                          */
-/* -------------------------------------------------------------------- */
-    GByte abyChunkHeader[18] = { 0 };
+    // Search for APP2 chunk.
+    GByte abyChunkHeader[18] = {};
     int nChunkLoc = 2;
     bool bOk = true;
 
     while(true)
     {
-        if( VSIFSeekL( fpImage, nChunkLoc, SEEK_SET ) != 0 )
+        if( VSIFSeekL(fpImage, nChunkLoc, SEEK_SET) != 0 )
             break;
 
-        if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage )
-            != 1 )
+        if( VSIFReadL(abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage) != 1 )
             break;
 
         if( abyChunkHeader[0] != 0xFF )
             break; // Not a valid tag
 
         if (abyChunkHeader[1] == 0xD9)
-            break; // End of image
+            break;  // End of image
 
         if ((abyChunkHeader[1] >= 0xD0) && (abyChunkHeader[1] <= 0xD8))
         {
@@ -581,19 +325,19 @@ void JPGDatasetCommon::ReadICCProfile()
             continue;
         }
 
-        int nChunkLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
+        const int nChunkLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
 
-        if( abyChunkHeader[1] == 0xe2
-            && memcmp( reinterpret_cast<char *>(abyChunkHeader) + 4,
-                       "ICC_PROFILE\0",12) == 0 )
+        if( abyChunkHeader[1] == 0xe2 &&
+            memcmp(reinterpret_cast<char *>(abyChunkHeader) + 4,
+                   "ICC_PROFILE\0", 12) == 0 )
         {
-            /* Get length and segment ID */
-            /* Header: */
-            /* APP2 tag: 2 bytes */
-            /* App Length: 2 bytes */
-            /* ICC_PROFILE\0 tag: 12 bytes */
-            /* Segment index: 1 bytes */
-            /* Total segments: 1 bytes */
+            // Get length and segment ID
+            // Header:
+            // APP2 tag: 2 bytes
+            // App Length: 2 bytes
+            // ICC_PROFILE\0 tag: 12 bytes
+            // Segment index: 1 bytes
+            // Total segments: 1 bytes
             const int nICCChunkLength = nChunkLength - 16;
             const int nICCChunkID = abyChunkHeader[16];
             const int nICCMaxChunkID = abyChunkHeader[17];
@@ -601,7 +345,7 @@ void JPGDatasetCommon::ReadICCProfile()
             if (nChunkCount == -1)
                 nChunkCount = nICCMaxChunkID;
 
-            /* Check that all max segment counts are the same */
+            // Check that all max segment counts are the same.
             if (nICCMaxChunkID != nChunkCount)
             {
                 bOk = false;
@@ -616,20 +360,20 @@ void JPGDatasetCommon::ReadICCProfile()
                 break;
             }
 
-            /* Check if ICC segment already loaded */
+            // Check if ICC segment already loaded.
             if (apChunk[nICCChunkID-1] != NULL)
             {
                 bOk = false;
                 break;
             }
 
-            /* Load it */
-            apChunk[nICCChunkID-1]
-                = static_cast<char*>(VSIMalloc(nICCChunkLength));
-            anChunkSize[nICCChunkID-1] = nICCChunkLength;
+            // Load it.
+            apChunk[nICCChunkID - 1] =
+                static_cast<char *>(VSIMalloc(nICCChunkLength));
+            anChunkSize[nICCChunkID - 1] = nICCChunkLength;
 
-            if( VSIFReadL( apChunk[nICCChunkID-1], nICCChunkLength, 1, fpImage )
-                != 1 )
+            if( VSIFReadL(apChunk[nICCChunkID - 1], nICCChunkLength, 1,
+                         fpImage) != 1 )
             {
                 bOk = false;
                 break;
@@ -639,14 +383,14 @@ void JPGDatasetCommon::ReadICCProfile()
         nChunkLoc += 2 + nChunkLength;
     }
 
-    /* Get total size and verify that there are no missing segments */
+    // Get total size and verify that there are no missing segments.
     if (bOk)
     {
         for(int i = 0; i < nChunkCount; i++)
         {
             if (apChunk[i] == NULL)
             {
-                /* Missing segment... abort */
+                // Missing segment - abort.
                 bOk = false;
                 break;
             }
@@ -654,10 +398,10 @@ void JPGDatasetCommon::ReadICCProfile()
         }
     }
 
-    /* Merge all segments together and set metadata */
+    // Merge all segments together and set metadata.
     if (bOk && nChunkCount > 0)
     {
-        char *pBuffer = static_cast<char*>(VSIMalloc(nTotalSize));
+        char *pBuffer = static_cast<char *>(VSIMalloc(nTotalSize));
         char *pBufferPtr = pBuffer;
         for(int i = 0; i < nChunkCount; i++)
         {
@@ -665,15 +409,16 @@ void JPGDatasetCommon::ReadICCProfile()
             pBufferPtr += anChunkSize[i];
         }
 
-        /* Escape the profile */
+        // Escape the profile.
         char *pszBase64Profile =
-            CPLBase64Encode( nTotalSize, reinterpret_cast<GByte *>(pBuffer) );
+            CPLBase64Encode(nTotalSize, reinterpret_cast<GByte *>(pBuffer));
 
-        /* Avoid setting the PAM dirty bit just for that */
-        int nOldPamFlags = nPamFlags;
+        // Avoid setting the PAM dirty bit just for that.
+        const int nOldPamFlags = nPamFlags;
 
-        /* Set ICC profile metadata */
-        SetMetadataItem( "SOURCE_ICC_PROFILE", pszBase64Profile, "COLOR_PROFILE" );
+        // Set ICC profile metadata.
+        SetMetadataItem("SOURCE_ICC_PROFILE", pszBase64Profile,
+                        "COLOR_PROFILE");
 
         nPamFlags = nOldPamFlags;
 
@@ -681,14 +426,13 @@ void JPGDatasetCommon::ReadICCProfile()
         CPLFree(pszBase64Profile);
     }
 
-    /* Cleanup */
     for(int i = 0; i < nChunkCount; i++)
     {
         if (apChunk[i] != NULL)
             VSIFree(apChunk[i]);
     }
 
-    VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
+    VSIFSeekL(fpImage, nCurOffset, SEEK_SET);
 }
 
 /************************************************************************/
@@ -696,60 +440,59 @@ void JPGDatasetCommon::ReadICCProfile()
 /*                                                                      */
 /*           Create Metadata from Information file directory APP1       */
 /************************************************************************/
-int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
+bool JPGDatasetCommon::EXIFInit(VSILFILE *fp)
 {
     if( nTiffDirStart == 0 )
-        return FALSE;
-    else if( nTiffDirStart > 0 )
-        return TRUE;
+        return false;
+    if( nTiffDirStart > 0 )
+        return true;
     nTiffDirStart = 0;
 
-    // TODO: Do a compile time endian check.
+    // TODO(schwehr): Do a compile time endian check.
     int one = 1;
-    bigendian = (*reinterpret_cast<char *>(&one) == 0);
+    bigendian = *reinterpret_cast<char *>(&one) == 0;
 
-/* -------------------------------------------------------------------- */
-/*      Search for APP1 chunk.                                          */
-/* -------------------------------------------------------------------- */
-    GByte abyChunkHeader[10] = { 0 };
+    // Search for APP1 chunk.
+    GByte abyChunkHeader[10] = {};
     int nChunkLoc = 2;
 
     while(true)
     {
-        if( VSIFSeekL( fp, nChunkLoc, SEEK_SET ) != 0 )
-            return FALSE;
+        if( VSIFSeekL(fp, nChunkLoc, SEEK_SET) != 0 )
+            return false;
 
-        if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fp ) != 1 )
-            return FALSE;
+        if( VSIFReadL(abyChunkHeader, sizeof(abyChunkHeader), 1, fp) != 1 )
+            return false;
 
-        int nChunkLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
+        const int nChunkLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
         // COM marker
         if( abyChunkHeader[0] == 0xFF && abyChunkHeader[1] == 0xFE &&
             nChunkLength >= 2 )
         {
-            char* pszComment =
-                static_cast<char*>(CPLMalloc(nChunkLength - 2 + 1));
+            char *pszComment =
+                static_cast<char *>(CPLMalloc(nChunkLength - 2 + 1));
             if( nChunkLength > 2 &&
-                VSIFSeekL( fp, nChunkLoc + 4, SEEK_SET ) == 0 &&
+                VSIFSeekL(fp, nChunkLoc + 4, SEEK_SET) == 0 &&
                 VSIFReadL(pszComment, nChunkLength - 2, 1, fp) == 1 )
             {
-                pszComment[nChunkLength-2] = 0;
-                /* Avoid setting the PAM dirty bit just for that */
+                pszComment[nChunkLength - 2] = 0;
+                // Avoid setting the PAM dirty bit just for that.
                 const int nOldPamFlags = nPamFlags;
-                /* Set ICC profile metadata */
-                SetMetadataItem( "COMMENT", pszComment );
+                // Set ICC profile metadata.
+                SetMetadataItem("COMMENT", pszComment);
                 nPamFlags = nOldPamFlags;
             }
             CPLFree(pszComment);
         }
         else
         {
-            if( abyChunkHeader[0] != 0xFF
-                || (abyChunkHeader[1] & 0xf0) != 0xe0 )
-                break; // Not an APP chunk.
+            if( abyChunkHeader[0] != 0xFF ||
+                (abyChunkHeader[1] & 0xf0) != 0xe0 )
+                break;  // Not an APP chunk.
 
-            if( abyChunkHeader[1] == 0xe1
-                && STARTS_WITH((const char *) abyChunkHeader + 4, "Exif") )
+            if( abyChunkHeader[1] == 0xe1 &&
+                STARTS_WITH(reinterpret_cast<char *>(abyChunkHeader) + 4,
+                            "Exif") )
             {
                 nTIFFHEADER = nChunkLoc + 10;
             }
@@ -759,28 +502,26 @@ int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
     }
 
     if( nTIFFHEADER < 0 )
-        return FALSE;
+        return false;
 
-/* -------------------------------------------------------------------- */
-/*      Read TIFF header                                                */
-/* -------------------------------------------------------------------- */
+    // Read TIFF header.
     TIFFHeader hdr = { 0, 0, 0 };
 
     VSIFSeekL(fp, nTIFFHEADER, SEEK_SET);
     if( VSIFReadL(&hdr, 1, sizeof(hdr), fp) != sizeof(hdr) )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read %d byte from image header.",
-                  static_cast<int>( sizeof(hdr) ) );
-                  return FALSE;
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Failed to read %d byte from image header.",
+                 static_cast<int>(sizeof(hdr)));
+        return false;
     }
 
     if (hdr.tiff_magic != TIFF_BIGENDIAN && hdr.tiff_magic != TIFF_LITTLEENDIAN)
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Not a TIFF file, bad magic number %u (%#x)",
-                  hdr.tiff_magic, hdr.tiff_magic );
-        return FALSE;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Not a TIFF file, bad magic number %u (%#x)",
+                 hdr.tiff_magic, hdr.tiff_magic);
+        return false;
     }
 
     if (hdr.tiff_magic == TIFF_BIGENDIAN)    bSwabflag = !bigendian;
@@ -793,19 +534,19 @@ int JPGDatasetCommon::EXIFInit(VSILFILE *fp)
 
     if (hdr.tiff_version != TIFF_VERSION)
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Not a TIFF file, bad version number %u (%#x)",
-                  hdr.tiff_version, hdr.tiff_version );
-        return FALSE;
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Not a TIFF file, bad version number %u (%#x)",
+                 hdr.tiff_version, hdr.tiff_version);
+        return false;
     }
     nTiffDirStart = hdr.tiff_diroff;
 
-    CPLDebug( "JPEG", "Magic: %#x <%s-endian> Version: %#x\n",
-              hdr.tiff_magic,
-              hdr.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
-              hdr.tiff_version );
+    CPLDebug("JPEG", "Magic: %#x <%s-endian> Version: %#x\n",
+             hdr.tiff_magic,
+             hdr.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
+             hdr.tiff_version );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -832,29 +573,26 @@ JPGMaskBand::JPGMaskBand( JPGDataset *poDSIn )
 
 CPLErr JPGMaskBand::IReadBlock( int /* nBlockX */, int nBlockY, void *pImage )
 {
-    JPGDataset *poJDS = static_cast<JPGDataset *>( poDS );
+    JPGDataset *poJDS = static_cast<JPGDataset *>(poDS);
 
-/* -------------------------------------------------------------------- */
-/*      Make sure the mask is loaded and decompressed.                  */
-/* -------------------------------------------------------------------- */
+    // Make sure the mask is loaded and decompressed.
     poJDS->DecompressMask();
     if( poJDS->pabyBitMask == NULL )
         return CE_Failure;
 
-/* -------------------------------------------------------------------- */
-/*      Set mask based on bitmask for this scanline.                    */
-/* -------------------------------------------------------------------- */
+    // Set mask based on bitmask for this scanline.
     GUInt32 iBit =
         static_cast<GUInt32>(nBlockY) * static_cast<GUInt32>(nBlockXSize);
 
+    GByte *const pbyImage = static_cast<GByte *>(pImage);
     if( poJDS->bMaskLSBOrder )
     {
         for( int iX = 0; iX < nBlockXSize; iX++ )
         {
-            if( poJDS->pabyBitMask[iBit>>3] & (0x1 << (iBit&7)) )
-                reinterpret_cast<GByte *>(pImage)[iX] = 255;
+            if( poJDS->pabyBitMask[iBit >> 3] & (0x1 << (iBit & 7)) )
+                pbyImage[iX] = 255;
             else
-                reinterpret_cast<GByte *>(pImage)[iX] = 0;
+                pbyImage[iX] = 0;
             iBit++;
         }
     }
@@ -862,10 +600,10 @@ CPLErr JPGMaskBand::IReadBlock( int /* nBlockX */, int nBlockY, void *pImage )
     {
         for( int iX = 0; iX < nBlockXSize; iX++ )
         {
-            if( poJDS->pabyBitMask[iBit>>3] & (0x1 << (7 - (iBit&7))) )
-                reinterpret_cast<GByte *>(pImage)[iX] = 255;
+            if( poJDS->pabyBitMask[iBit >> 3] & (0x1 << (7 - (iBit & 7))) )
+                pbyImage[iX] = 255;
             else
-                reinterpret_cast<GByte *>(pImage)[iX] = 0;
+                pbyImage[iX] = 0;
             iBit++;
         }
     }
@@ -898,7 +636,7 @@ JPGRasterBand::JPGRasterBand( JPGDatasetCommon *poDSIn, int nBandIn ) :
 /*                           JPGCreateBand()                            */
 /************************************************************************/
 
-GDALRasterBand* JPGCreateBand(JPGDatasetCommon* poDS, int nBand)
+GDALRasterBand *JPGCreateBand(JPGDatasetCommon *poDS, int nBand)
 {
     return new JPGRasterBand(poDS, nBand);
 }
@@ -908,101 +646,92 @@ GDALRasterBand* JPGCreateBand(JPGDatasetCommon* poDS, int nBand)
 /************************************************************************/
 
 CPLErr JPGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                  void * pImage )
+                                  void *pImage )
 
 {
-    CPLAssert( nBlockXOff == 0 );
+    CPLAssert(nBlockXOff == 0);
 
     const int nXSize = GetXSize();
-    const int nWordSize = GDALGetDataTypeSize(eDataType) / 8;
+    const int nWordSize = GDALGetDataTypeSizeBytes(eDataType);
     if (poGDS->fpImage == NULL)
     {
-        memset( pImage, 0, nXSize * nWordSize );
+        memset(pImage, 0, nXSize * nWordSize);
         return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Load the desired scanline into the working buffer.              */
-/* -------------------------------------------------------------------- */
-    CPLErr eErr = poGDS->LoadScanline( nBlockYOff );
+    // Load the desired scanline into the working buffer.
+    CPLErr eErr = poGDS->LoadScanline(nBlockYOff);
     if( eErr != CE_None )
         return eErr;
 
-/* -------------------------------------------------------------------- */
-/*      Transfer between the working buffer the callers buffer.         */
-/* -------------------------------------------------------------------- */
+    // Transfer between the working buffer the callers buffer.
     if( poGDS->GetRasterCount() == 1 )
     {
 #ifdef JPEG_LIB_MK1
-        GDALCopyWords( poGDS->pabyScanline, GDT_UInt16, 2,
-                       pImage, eDataType, nWordSize,
-                       nXSize );
+        GDALCopyWords(poGDS->pabyScanline, GDT_UInt16, 2,
+                      pImage, eDataType, nWordSize,
+                      nXSize);
 #else
-        memcpy( pImage, poGDS->pabyScanline, nXSize * nWordSize );
+        memcpy(pImage, poGDS->pabyScanline, nXSize * nWordSize);
 #endif
     }
     else
     {
 #ifdef JPEG_LIB_MK1
-        GDALCopyWords( poGDS->pabyScanline + (nBand-1) * 2,
-                       GDT_UInt16, 6,
-                       pImage, eDataType, nWordSize,
-                       nXSize );
+        GDALCopyWords(poGDS->pabyScanline + (nBand - 1) * 2,
+                      GDT_UInt16, 6,
+                      pImage, eDataType, nWordSize,
+                      nXSize);
 #else
         if (poGDS->eGDALColorSpace == JCS_RGB &&
             poGDS->GetOutColorSpace() == JCS_CMYK &&
             eDataType == GDT_Byte)
         {
+            GByte *const pbyImage = static_cast<GByte *>(pImage);
             if (nBand == 1)
             {
                 for( int i=0; i < nXSize; i++ )
                 {
                     const int C = poGDS->pabyScanline[i * 4 + 0];
                     const int K = poGDS->pabyScanline[i * 4 + 3];
-                    reinterpret_cast<GByte *>(pImage)[i] =
-                        static_cast<GByte>( (C * K) / 255 );
+                    pbyImage[i] = static_cast<GByte>((C * K) / 255);
                 }
             }
             else if (nBand == 2)
             {
-                for( int i=0; i < nXSize; i++ )
+                for( int i = 0; i < nXSize; i++ )
                 {
                     const int M = poGDS->pabyScanline[i * 4 + 1];
                     const int K = poGDS->pabyScanline[i * 4 + 3];
-                    reinterpret_cast<GByte*>(pImage)[i] =
-                        static_cast<GByte>( (M * K) / 255 );
+                    pbyImage[i] = static_cast<GByte>((M * K) / 255);
                 }
             }
             else if (nBand == 3)
             {
-                for( int i=0; i < nXSize; i++ )
+                for( int i = 0; i < nXSize; i++ )
                 {
                     const int Y = poGDS->pabyScanline[i * 4 + 2];
                     const int K = poGDS->pabyScanline[i * 4 + 3];
-                    reinterpret_cast<GByte *>(pImage)[i] =
-                        static_cast<GByte>( (Y * K) / 255 );
+                    pbyImage[i] = static_cast<GByte>((Y * K) / 255);
                 }
             }
         }
         else
         {
-            GDALCopyWords( poGDS->pabyScanline + (nBand-1) * nWordSize,
-                        eDataType, nWordSize * poGDS->GetRasterCount(),
-                        pImage, eDataType, nWordSize,
-                        nXSize );
+            GDALCopyWords(poGDS->pabyScanline + (nBand - 1) * nWordSize,
+                          eDataType, nWordSize * poGDS->GetRasterCount(),
+                          pImage, eDataType, nWordSize, nXSize);
         }
 #endif
     }
 
-/* -------------------------------------------------------------------- */
-/*      Forcibly load the other bands associated with this scanline.    */
-/* -------------------------------------------------------------------- */
+    // Forcibly load the other bands associated with this scanline.
     if( nBand == 1 )
     {
         for( int iBand = 2; iBand <= poGDS->GetRasterCount() ; iBand++ )
         {
-            GDALRasterBlock * const poBlock
-                = poGDS->GetRasterBand(iBand)->
+            GDALRasterBlock *const poBlock =
+                poGDS->GetRasterBand(iBand)->
                     GetLockedBlockRef(nBlockXOff, nBlockYOff);
             if( poBlock != NULL )
                 poBlock->DropLock();
@@ -1026,10 +755,8 @@ GDALColorInterp JPGRasterBand::GetColorInterpretation()
     {
         if ( nBand == 1 )
             return GCI_RedBand;
-
         else if( nBand == 2 )
             return GCI_GreenBand;
-
         else
             return GCI_BlueBand;
     }
@@ -1037,13 +764,10 @@ GDALColorInterp JPGRasterBand::GetColorInterpretation()
     {
         if ( nBand == 1 )
             return GCI_CyanBand;
-
         else if( nBand == 2 )
             return GCI_MagentaBand;
-
         else if ( nBand == 3 )
             return GCI_YellowBand;
-
         else
             return GCI_BlackBand;
     }
@@ -1052,18 +776,15 @@ GDALColorInterp JPGRasterBand::GetColorInterpretation()
     {
         if ( nBand == 1 )
             return GCI_YCbCr_YBand;
-
         else if( nBand == 2 )
             return GCI_YCbCr_CbBand;
-
         else if ( nBand == 3 )
             return GCI_YCbCr_CrBand;
-
         else
             return GCI_BlackBand;
     }
 
-    CPLAssert(0);
+    CPLAssert(false);
     return GCI_Undefined;
 }
 
@@ -1084,12 +805,13 @@ GDALRasterBand *JPGRasterBand::GetMaskBand()
     {
         if( CPLTestBool(CPLGetConfigOption("JPEG_READ_MASK", "YES")))
             poGDS->CheckForMask();
-        poGDS->bHasCheckedForMask = TRUE;
+        poGDS->bHasCheckedForMask = true;
     }
     if( poGDS->pabyCMask )
     {
         if( poGDS->poMaskBand == NULL )
-            poGDS->poMaskBand = new JPGMaskBand( (JPGDataset *) poDS );
+            poGDS->poMaskBand =
+                new JPGMaskBand(static_cast<JPGDataset *>(poDS));
 
         return poGDS->poMaskBand;
     }
@@ -1121,7 +843,7 @@ int JPGRasterBand::GetMaskFlags()
 /*                            GetOverview()                             */
 /************************************************************************/
 
-GDALRasterBand* JPGRasterBand::GetOverview(int i)
+GDALRasterBand *JPGRasterBand::GetOverview(int i)
 {
     poGDS->InitInternalOverviews();
 
@@ -1156,41 +878,41 @@ int JPGRasterBand::GetOverviewCount()
 
 JPGDatasetCommon::JPGDatasetCommon() :
     nScaleFactor(1),
-    bHasInitInternalOverviews(FALSE),
+    bHasInitInternalOverviews(false),
     nInternalOverviewsCurrent(0),
     nInternalOverviewsToFree(0),
     papoInternalOverviews(NULL),
     pszProjection(NULL),
-    bGeoTransformValid(FALSE),
+    bGeoTransformValid(false),
     nGCPCount(0),
     pasGCPList(NULL),
     fpImage(NULL),
     nSubfileOffset(0),
     nLoadedScanline(-1),
     pabyScanline(NULL),
-    bHasReadEXIFMetadata(FALSE),
-    bHasReadXMPMetadata(FALSE),
-    bHasReadICCMetadata(FALSE),
+    bHasReadEXIFMetadata(false),
+    bHasReadXMPMetadata(false),
+    bHasReadICCMetadata(false),
     papszMetadata(NULL),
     papszSubDatasets(NULL),
-    bigendian(1),
+    bigendian(true),
     nExifOffset(-1),
     nInterOffset(-1),
     nGPSOffset(-1),
-    bSwabflag(FALSE),
+    bSwabflag(false),
     nTiffDirStart(-1),
     nTIFFHEADER(-1),
-    bHasDoneJpegCreateDecompress(FALSE),
-    bHasDoneJpegStartDecompress(FALSE),
-    bHasCheckedForMask(FALSE),
+    bHasDoneJpegCreateDecompress(false),
+    bHasDoneJpegStartDecompress(false),
+    bHasCheckedForMask(false),
     poMaskBand(NULL),
     pabyBitMask(NULL),
-    bMaskLSBOrder(TRUE),
+    bMaskLSBOrder(true),
     pabyCMask(NULL),
     nCMaskSize(0),
     eGDALColorSpace(JCS_UNKNOWN),
-    bIsSubfile(FALSE),
-    bHasTriedLoadWorldFileOrTab(FALSE)
+    bIsSubfile(false),
+    bHasTriedLoadWorldFileOrTab(false)
 {
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -1208,24 +930,24 @@ JPGDatasetCommon::~JPGDatasetCommon()
 
 {
     if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+        VSIFCloseL(fpImage);
 
     if( pabyScanline != NULL )
-        CPLFree( pabyScanline );
+        CPLFree(pabyScanline);
     if( papszMetadata != NULL )
-      CSLDestroy( papszMetadata );
+        CSLDestroy(papszMetadata);
 
     if ( pszProjection )
-        CPLFree( pszProjection );
+        CPLFree(pszProjection);
 
     if ( nGCPCount > 0 )
     {
-        GDALDeinitGCPs( nGCPCount, pasGCPList );
-        CPLFree( pasGCPList );
+        GDALDeinitGCPs(nGCPCount, pasGCPList);
+        CPLFree(pasGCPList);
     }
 
-    CPLFree( pabyBitMask );
-    CPLFree( pabyCMask );
+    CPLFree(pabyBitMask);
+    CPLFree(pabyCMask);
     delete poMaskBand;
 
     CloseDependentDatasets();
@@ -1260,17 +982,16 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
     if( !EXIFInit(fpImage) )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Read number of entry in directory                               */
-/* -------------------------------------------------------------------- */
+    // Read number of entry in directory.
     GUInt16 nEntryCount = 0;
-    if( nTiffDirStart > INT_MAX - nTIFFHEADER ||
-        VSIFSeekL(fpImage, nTiffDirStart+nTIFFHEADER, SEEK_SET) != 0
-        || VSIFReadL(&nEntryCount,1,sizeof(GUInt16),fpImage) != sizeof(GUInt16) )
+    if( nTiffDirStart > (INT_MAX - nTIFFHEADER) ||
+        VSIFSeekL(fpImage, nTiffDirStart+nTIFFHEADER, SEEK_SET) != 0 ||
+        VSIFReadL(&nEntryCount, 1,
+                  sizeof(GUInt16), fpImage) != sizeof(GUInt16) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                "Error reading EXIF Directory count at " CPL_FRMT_GUIB,
-                 static_cast<vsi_l_offset>(nTiffDirStart) + nTIFFHEADER );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Error reading EXIF Directory count at " CPL_FRMT_GUIB,
+                 static_cast<vsi_l_offset>(nTiffDirStart) + nTIFFHEADER);
         return NULL;
     }
 
@@ -1280,16 +1001,16 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
     // Some files are corrupt, a large entry count is a sign of this.
     if( nEntryCount > 125 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Ignoring EXIF directory with unlikely entry count (%d).",
-                  nEntryCount );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Ignoring EXIF directory with unlikely entry count (%d).",
+                 nEntryCount);
         return NULL;
     }
 
-    // Skip EXIF entries
-    VSIFSeekL( fpImage, nEntryCount * sizeof(GDALEXIFTIFFDirEntry), SEEK_CUR );
+    // Skip EXIF entries.
+    VSIFSeekL(fpImage, nEntryCount * sizeof(GDALEXIFTIFFDirEntry), SEEK_CUR);
 
-    // Read offset of next directory (IFD1)
+    // Read offset of next directory (IFD1).
     GUInt32 nNextDirOff = 0;
     if( VSIFReadL(&nNextDirOff, 1, sizeof(GUInt32), fpImage) !=
         sizeof(GUInt32) )
@@ -1299,13 +1020,13 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
     if( nNextDirOff == 0 || nNextDirOff > 0xFFFFFFFFU - nTIFFHEADER )
         return NULL;
 
-    // Seek to IFD1
-    if( VSIFSeekL(fpImage, nTIFFHEADER+nNextDirOff, SEEK_SET) != 0 ||
-        VSIFReadL(&nEntryCount,1,sizeof(GUInt16),fpImage) != sizeof(GUInt16) )
+    // Seek to IFD1.
+    if( VSIFSeekL(fpImage, nTIFFHEADER + nNextDirOff, SEEK_SET) != 0 ||
+        VSIFReadL(&nEntryCount, 1, sizeof(GUInt16), fpImage) != sizeof(GUInt16) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Error reading IFD1 Directory count at %d.",
-                  nTIFFHEADER + nNextDirOff );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Error reading IFD1 Directory count at %d.",
+                 nTIFFHEADER + nNextDirOff);
         return NULL;
     }
 
@@ -1313,12 +1034,14 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
         TIFFSwabShort(&nEntryCount);
     if( nEntryCount > 125 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Ignoring IFD1 directory with unlikely entry count (%d).",
-                  nEntryCount );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Ignoring IFD1 directory with unlikely entry count (%d).",
+                 nEntryCount);
         return NULL;
     }
-    /* CPLDebug("JPEG", "IFD1 entry count = %d", nEntryCount); */
+#if DEBUG_VERBOSE
+    CPLDebug("JPEG", "IFD1 entry count = %d", nEntryCount);
+#endif
 
     int nImageWidth = 0;
     int nImageHeight = 0;
@@ -1328,26 +1051,24 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
     for( int i = 0; i < nEntryCount; i ++ )
     {
         GDALEXIFTIFFDirEntry sEntry;
-        if( VSIFReadL(&sEntry,1,sizeof(sEntry),fpImage) != sizeof(sEntry) )
+        if( VSIFReadL(&sEntry, 1, sizeof(sEntry), fpImage) != sizeof(sEntry) )
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Cannot read entry %d of IFD1",
-                      i );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Cannot read entry %d of IFD1", i);
             return NULL;
         }
         if (bSwabflag)
         {
             TIFFSwabShort(&sEntry.tdir_tag);
             TIFFSwabShort(&sEntry.tdir_type);
-            TIFFSwabLong (&sEntry.tdir_count);
-            TIFFSwabLong (&sEntry.tdir_offset);
+            TIFFSwabLong(&sEntry.tdir_count);
+            TIFFSwabLong(&sEntry.tdir_offset);
         }
 
 #ifdef DEBUG_VERBOSE
-        CPLDebug( "JPEG",
-                  "tag = %d (0x%4X), type = %d, count = %d, offset = %d",
-                  sEntry.tdir_tag, sEntry.tdir_tag, sEntry.tdir_type,
-                  sEntry.tdir_count, sEntry.tdir_offset );
+        CPLDebug("JPEG", "tag = %d (0x%4X), type = %d, count = %d, offset = %d",
+                 sEntry.tdir_tag, sEntry.tdir_tag, sEntry.tdir_type,
+                 sEntry.tdir_count, sEntry.tdir_offset);
 #endif
 
         if( (sEntry.tdir_type == TIFF_SHORT || sEntry.tdir_type == TIFF_LONG) &&
@@ -1355,23 +1076,23 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
         {
             switch( sEntry.tdir_tag )
             {
-                case JPEG_TIFF_IMAGEWIDTH:
-                    nImageWidth = sEntry.tdir_offset;
-                    break;
-                case JPEG_TIFF_IMAGEHEIGHT:
-                    nImageHeight = sEntry.tdir_offset;
-                    break;
-                case JPEG_TIFF_COMPRESSION:
-                    nCompression = sEntry.tdir_offset;
-                    break;
-                case JPEG_EXIF_JPEGIFOFSET:
-                    nJpegIFOffset = sEntry.tdir_offset;
-                    break;
-                case JPEG_EXIF_JPEGIFBYTECOUNT:
-                    nJpegIFByteCount = sEntry.tdir_offset;
-                    break;
-                default:
-                    break;
+            case JPEG_TIFF_IMAGEWIDTH:
+                nImageWidth = sEntry.tdir_offset;
+                break;
+            case JPEG_TIFF_IMAGEHEIGHT:
+                nImageHeight = sEntry.tdir_offset;
+                break;
+            case JPEG_TIFF_COMPRESSION:
+                nCompression = sEntry.tdir_offset;
+                break;
+            case JPEG_EXIF_JPEGIFOFSET:
+                nJpegIFOffset = sEntry.tdir_offset;
+                break;
+            case JPEG_EXIF_JPEGIFBYTECOUNT:
+                nJpegIFByteCount = sEntry.tdir_offset;
+                break;
+            default:
+                break;
             }
         }
     }
@@ -1386,17 +1107,17 @@ GDALDataset* JPGDatasetCommon::InitEXIFOverview()
     }
 
     const char* pszSubfile =
-        CPLSPrintf( "JPEG_SUBFILE:%u,%d,%s",
-                    nTIFFHEADER + nJpegIFOffset,
-                    nJpegIFByteCount,
-                    GetDescription() );
+        CPLSPrintf("JPEG_SUBFILE:%u,%d,%s",
+                   nTIFFHEADER + nJpegIFOffset,
+                   nJpegIFByteCount,
+                   GetDescription());
     JPGDatasetOpenArgs sArgs;
     sArgs.pszFilename = pszSubfile;
     sArgs.fpLin = NULL;
     sArgs.papszSiblingFiles = NULL;
     sArgs.nScaleFactor = 1;
-    sArgs.bDoPAMInitialize = FALSE;
-    sArgs.bUseInternalOverviews = FALSE;
+    sArgs.bDoPAMInitialize = false;
+    sArgs.bUseInternalOverviews = false;
     return JPGDataset::Open(&sArgs);
 }
 
@@ -1408,18 +1129,16 @@ void JPGDatasetCommon::InitInternalOverviews()
 {
     if( bHasInitInternalOverviews )
         return;
-    bHasInitInternalOverviews = TRUE;
+    bHasInitInternalOverviews = true;
 
-/* -------------------------------------------------------------------- */
-/*      Instantiate on-the-fly overviews (if no external ones).         */
-/* -------------------------------------------------------------------- */
+    // Instantiate on-the-fly overviews (if no external ones).
     if( nScaleFactor == 1 && GetRasterBand(1)->GetOverviewCount() == 0 )
     {
-        /* EXIF overview */
-        GDALDataset* poEXIFOverview = NULL;
+        // EXIF overview.
+        GDALDataset *poEXIFOverview = NULL;
         if( nRasterXSize > 512 || nRasterYSize > 512 )
         {
-            vsi_l_offset nCurOffset = VSIFTellL(fpImage);
+            const vsi_l_offset nCurOffset = VSIFTellL(fpImage);
             poEXIFOverview = InitEXIFOverview();
             if( poEXIFOverview != NULL )
             {
@@ -1432,23 +1151,25 @@ void JPGDatasetCommon::InitInternalOverviews()
                 }
                 else
                 {
-                    CPLDebug( "JPEG", "EXIF overview (%d x %d) detected",
-                              poEXIFOverview->GetRasterXSize(),
-                              poEXIFOverview->GetRasterYSize() );
+                    CPLDebug("JPEG", "EXIF overview (%d x %d) detected",
+                             poEXIFOverview->GetRasterXSize(),
+                             poEXIFOverview->GetRasterYSize());
                 }
             }
-            VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
+            VSIFSeekL(fpImage, nCurOffset, SEEK_SET);
         }
 
-        /* libjpeg-6b only supports 2, 4 and 8 scale denominators */
-        /* TODO: Later versions support more */
+        // libjpeg-6b only supports 2, 4 and 8 scale denominators.
+        // TODO: Later versions support more.
 
         int nImplicitOverviews = 0;
 
-        /* For the needs of the implicit JPEG-in-TIFF overview mechanism */
+        // For the needs of the implicit JPEG-in-TIFF overview mechanism.
         if( CPLTestBool(
                CPLGetConfigOption("JPEG_FORCE_INTERNAL_OVERVIEWS", "NO")) )
+        {
             nImplicitOverviews = 3;
+        }
         else
         {
             for( int i = 2; i >= 0; i--)
@@ -1464,9 +1185,8 @@ void JPGDatasetCommon::InitInternalOverviews()
         if( nImplicitOverviews > 0 )
         {
             papoInternalOverviews = static_cast<GDALDataset **>(
-                CPLMalloc(
-                    (nImplicitOverviews + (poEXIFOverview ? 1 : 0))
-                    * sizeof(GDALDataset*)) );
+                CPLMalloc((nImplicitOverviews + (poEXIFOverview ? 1 : 0)) *
+                          sizeof(GDALDataset *)));
             for( int i = 0; i < nImplicitOverviews; i++ )
             {
                 if( poEXIFOverview != NULL &&
@@ -1479,15 +1199,15 @@ void JPGDatasetCommon::InitInternalOverviews()
                 sArgs.fpLin = NULL;
                 sArgs.papszSiblingFiles = NULL;
                 sArgs.nScaleFactor = 1 << (i + 1);
-                sArgs.bDoPAMInitialize = FALSE;
-                sArgs.bUseInternalOverviews = FALSE;
-                GDALDataset* poImplicitOverview = JPGDataset::Open(&sArgs);
+                sArgs.bDoPAMInitialize = false;
+                sArgs.bUseInternalOverviews = false;
+                GDALDataset *poImplicitOverview = JPGDataset::Open(&sArgs);
                 if( poImplicitOverview == NULL )
                     break;
                 papoInternalOverviews[nInternalOverviewsCurrent] =
                     poImplicitOverview;
-                nInternalOverviewsCurrent ++;
-                nInternalOverviewsToFree ++;
+                nInternalOverviewsCurrent++;
+                nInternalOverviewsToFree++;
             }
             if( poEXIFOverview != NULL )
             {
@@ -1500,10 +1220,10 @@ void JPGDatasetCommon::InitInternalOverviews()
         else if( poEXIFOverview )
         {
             papoInternalOverviews =
-                static_cast<GDALDataset**>( CPLMalloc(sizeof(GDALDataset*)) );
+                static_cast<GDALDataset **>(CPLMalloc(sizeof(GDALDataset *)));
             papoInternalOverviews[0] = poEXIFOverview;
-            nInternalOverviewsCurrent ++;
-            nInternalOverviewsToFree ++;
+            nInternalOverviewsCurrent++;
+            nInternalOverviewsToFree++;
         }
     }
 }
@@ -1519,7 +1239,7 @@ CPLErr JPGDatasetCommon::IBuildOverviews( const char *pszResampling,
                                           GDALProgressFunc pfnProgress,
                                           void * pProgressData )
 {
-    bHasInitInternalOverviews = TRUE;
+    bHasInitInternalOverviews = true;
     nInternalOverviewsCurrent = 0;
 
     return GDALPamDataset::IBuildOverviews(pszResampling,
@@ -1543,19 +1263,18 @@ void JPGDatasetCommon::FlushCache()
         Restart();
     }
 
-    /* For the needs of the implicit JPEG-in-TIFF overview mechanism */
+    // For the needs of the implicit JPEG-in-TIFF overview mechanism.
     for(int i = 0; i < nInternalOverviewsCurrent; i++)
         papoInternalOverviews[i]->FlushCache();
 }
 
-#endif // !defined(JPGDataset)
+#endif  // !defined(JPGDataset)
 
 /************************************************************************/
 /*                            JPGDataset()                              */
 /************************************************************************/
 
-JPGDataset::JPGDataset() :
-    nQLevel(0)
+JPGDataset::JPGDataset() : nQLevel(0)
 {
     memset(&sDInfo, 0, sizeof(sDInfo));
     sDInfo.data_precision = 8;
@@ -1574,11 +1293,11 @@ JPGDataset::~JPGDataset()
 
     if (bHasDoneJpegStartDecompress)
     {
-        jpeg_abort_decompress( &sDInfo );
+        jpeg_abort_decompress(&sDInfo);
     }
     if (bHasDoneJpegCreateDecompress)
     {
-        jpeg_destroy_decompress( &sDInfo );
+        jpeg_destroy_decompress(&sDInfo);
     }
 }
 
@@ -1586,14 +1305,14 @@ JPGDataset::~JPGDataset()
 /*                      ErrorOutOnNonFatalError()                       */
 /************************************************************************/
 
-int JPGDataset::ErrorOutOnNonFatalError()
+bool JPGDataset::ErrorOutOnNonFatalError()
 {
     if( sErrorStruct.bNonFatalErrorEncountered )
     {
-        sErrorStruct.bNonFatalErrorEncountered = FALSE;
-        return TRUE;
+        sErrorStruct.bNonFatalErrorEncountered = false;
+        return true;
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -1612,8 +1331,8 @@ CPLErr JPGDataset::LoadScanline( int iLine )
 
     if (!bHasDoneJpegStartDecompress)
     {
-        jpeg_start_decompress( &sDInfo );
-        bHasDoneJpegStartDecompress = TRUE;
+        jpeg_start_decompress(&sDInfo);
+        bHasDoneJpegStartDecompress = true;
     }
 
     if( pabyScanline == NULL )
@@ -1621,24 +1340,24 @@ CPLErr JPGDataset::LoadScanline( int iLine )
         int nJPEGBands = 0;
         switch(sDInfo.out_color_space)
         {
-            case JCS_GRAYSCALE:
-                nJPEGBands = 1;
-                break;
-            case JCS_RGB:
-            case JCS_YCbCr:
-                nJPEGBands = 3;
-                break;
-            case JCS_CMYK:
-            case JCS_YCCK:
-                nJPEGBands = 4;
-                break;
+        case JCS_GRAYSCALE:
+            nJPEGBands = 1;
+            break;
+        case JCS_RGB:
+        case JCS_YCbCr:
+            nJPEGBands = 3;
+            break;
+        case JCS_CMYK:
+        case JCS_YCCK:
+            nJPEGBands = 4;
+            break;
 
-            default:
-                CPLAssert(0);
+        default:
+            CPLAssert(false);
         }
 
-        pabyScanline = static_cast<GByte *>(
-            CPLMalloc(nJPEGBands * GetRasterXSize() * 2) );
+        pabyScanline =
+            static_cast<GByte *>(CPLMalloc(nJPEGBands * GetRasterXSize() * 2));
     }
 
     if( iLine < nLoadedScanline )
@@ -1649,8 +1368,8 @@ CPLErr JPGDataset::LoadScanline( int iLine )
 
     while( nLoadedScanline < iLine )
     {
-        JSAMPLE *ppSamples = reinterpret_cast<JSAMPLE *>( pabyScanline );
-        jpeg_read_scanlines( &sDInfo, &ppSamples, 1 );
+        JSAMPLE *ppSamples = reinterpret_cast<JSAMPLE *>(pabyScanline);
+        jpeg_read_scanlines(&sDInfo, &ppSamples, 1);
         if( ErrorOutOnNonFatalError() )
             return CE_Failure;
         nLoadedScanline++;
@@ -1770,10 +1489,8 @@ void JPGDataset::LoadDefaultTables( int n )
     if( nQLevel < 1 )
         return;
 
-/* -------------------------------------------------------------------- */
-/*      Load quantization table                                         */
-/* -------------------------------------------------------------------- */
-    JQUANT_TBL  *quant_ptr = NULL;
+    // Load quantization table.
+    JQUANT_TBL *quant_ptr = NULL;
     const GByte *pabyQTable = NULL;
 
     if( nQLevel == 1 )
@@ -1791,55 +1508,51 @@ void JPGDataset::LoadDefaultTables( int n )
 
     if (sDInfo.quant_tbl_ptrs[n] == NULL)
         sDInfo.quant_tbl_ptrs[n] =
-            jpeg_alloc_quant_table(reinterpret_cast<j_common_ptr>( &(sDInfo) ) );
+            jpeg_alloc_quant_table(reinterpret_cast<j_common_ptr>(&sDInfo));
 
-    quant_ptr = sDInfo.quant_tbl_ptrs[n];  /* quant_ptr is JQUANT_TBL* */
+    quant_ptr = sDInfo.quant_tbl_ptrs[n];  // quant_ptr is JQUANT_TBL.
     for (int i = 0; i < 64; i++) {
-        /* Qtable[] is desired quantization table, in natural array order */
+        // Qtable[] is desired quantization table, in natural array order.
         quant_ptr->quantval[i] = pabyQTable[i];
     }
 
-/* -------------------------------------------------------------------- */
-/*      Load AC huffman table.                                          */
-/* -------------------------------------------------------------------- */
+    // Load AC huffman table.
     if (sDInfo.ac_huff_tbl_ptrs[n] == NULL)
         sDInfo.ac_huff_tbl_ptrs[n] =
-            jpeg_alloc_huff_table((j_common_ptr)&sDInfo);
+            jpeg_alloc_huff_table(reinterpret_cast<j_common_ptr>(&sDInfo));
 
-    /* huff_ptr is JHUFF_TBL* */
+    // huff_ptr is JHUFF_TBL*.
     JHUFF_TBL *huff_ptr = sDInfo.ac_huff_tbl_ptrs[n];
 
     for (int i = 1; i <= 16; i++) {
-        /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
+        // counts[i] is number of Huffman codes of length i bits, i=1..16
         huff_ptr->bits[i] = AC_BITS[i-1];
     }
 
     for (int i = 0; i < 256; i++) {
-        /* symbols[] is the list of Huffman symbols, in code-length order */
+        // symbols[] is the list of Huffman symbols, in code-length order.
         huff_ptr->huffval[i] = AC_HUFFVAL[i];
     }
 
-/* -------------------------------------------------------------------- */
-/*      Load DC huffman table.                                          */
-/* -------------------------------------------------------------------- */
+    // Load DC huffman table.
+    // TODO(schwehr): Revisit this "sideways" cast.
     if (sDInfo.dc_huff_tbl_ptrs[n] == NULL)
         sDInfo.dc_huff_tbl_ptrs[n] =
-            jpeg_alloc_huff_table((j_common_ptr)&sDInfo);
+            jpeg_alloc_huff_table(reinterpret_cast<j_common_ptr>(&sDInfo));
 
-    huff_ptr = sDInfo.dc_huff_tbl_ptrs[n];      /* huff_ptr is JHUFF_TBL* */
+    huff_ptr = sDInfo.dc_huff_tbl_ptrs[n];  // huff_ptr is JHUFF_TBL*
 
     for (int i = 1; i <= 16; i++) {
-        /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
+        // counts[i] is number of Huffman codes of length i bits, i=1..16
         huff_ptr->bits[i] = DC_BITS[i-1];
     }
 
     for (int i = 0; i < 256; i++) {
-        /* symbols[] is the list of Huffman symbols, in code-length order */
+        // symbols[] is the list of Huffman symbols, in code-length order.
         huff_ptr->huffval[i] = DC_HUFFVAL[i];
     }
-
 }
-#endif // !defined(JPGDataset)
+#endif  // !defined(JPGDataset)
 
 /************************************************************************/
 /*                       SetScaleNumAndDenom()                          */
@@ -1865,61 +1578,65 @@ void JPGDataset::SetScaleNumAndDenom()
 CPLErr JPGDataset::Restart()
 
 {
-    // setup to trap a fatal error.
+    // Setup to trap a fatal error.
     if (setjmp(sErrorStruct.setjmp_buffer))
         return CE_Failure;
 
     J_COLOR_SPACE colorSpace = sDInfo.out_color_space;
     J_COLOR_SPACE jpegColorSpace = sDInfo.jpeg_color_space;
 
-    jpeg_abort_decompress( &sDInfo );
-    jpeg_destroy_decompress( &sDInfo );
-    jpeg_create_decompress( &sDInfo );
-
+    jpeg_abort_decompress(&sDInfo);
+    jpeg_destroy_decompress(&sDInfo);
+    jpeg_create_decompress(&sDInfo);
 
 #if !defined(JPGDataset)
-    LoadDefaultTables( 0 );
-    LoadDefaultTables( 1 );
-    LoadDefaultTables( 2 );
-    LoadDefaultTables( 3 );
-#endif // !defined(JPGDataset)
+    LoadDefaultTables(0);
+    LoadDefaultTables(1);
+    LoadDefaultTables(2);
+    LoadDefaultTables(3);
+#endif  // !defined(JPGDataset)
 
-/* -------------------------------------------------------------------- */
-/*      restart io.                                                     */
-/* -------------------------------------------------------------------- */
-    VSIFSeekL( fpImage, nSubfileOffset, SEEK_SET );
+    // Restart IO.
+    VSIFSeekL(fpImage, nSubfileOffset, SEEK_SET);
 
-    jpeg_vsiio_src( &sDInfo, fpImage );
-    jpeg_read_header( &sDInfo, TRUE );
+    jpeg_vsiio_src(&sDInfo, fpImage);
+    jpeg_read_header(&sDInfo, TRUE);
 
     sDInfo.out_color_space = colorSpace;
     nLoadedScanline = -1;
     SetScaleNumAndDenom();
 
-    /* The following errors could happen when "recycling" an existing dataset */
-    /* particularly when triggered by the implicit overviews of JPEG-in-TIFF */
-    /* with a corrupted TIFF file */
-    if( nRasterXSize != (int)(sDInfo.image_width + nScaleFactor - 1) / nScaleFactor ||
-        nRasterYSize != (int)(sDInfo.image_height + nScaleFactor - 1) / nScaleFactor )
+    // The following errors could happen when "recycling" an existing dataset
+    // particularly when triggered by the implicit overviews of JPEG-in-TIFF
+    // with a corrupted TIFF file.
+    if( nRasterXSize !=
+           static_cast<int>(sDInfo.image_width + nScaleFactor - 1) /
+               nScaleFactor ||
+        nRasterYSize !=
+           static_cast<int>(sDInfo.image_height + nScaleFactor - 1) /
+               nScaleFactor )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Unexpected image dimension (%d x %d), where as (%d x %d) was expected",
-                 (int)(sDInfo.image_width + nScaleFactor - 1) / nScaleFactor,
-                 (int)(sDInfo.image_height + nScaleFactor - 1) / nScaleFactor,
+                 "Unexpected image dimension (%d x %d), "
+                 "where as (%d x %d) was expected",
+                 static_cast<int>(sDInfo.image_width + nScaleFactor - 1) /
+                     nScaleFactor,
+                 static_cast<int>(sDInfo.image_height + nScaleFactor - 1) /
+                     nScaleFactor,
                  nRasterXSize, nRasterYSize);
-        bHasDoneJpegStartDecompress = FALSE;
+        bHasDoneJpegStartDecompress = false;
     }
     else if( jpegColorSpace != sDInfo.jpeg_color_space )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Unexpected jpeg color space : %d",
                  sDInfo.jpeg_color_space);
-        bHasDoneJpegStartDecompress = FALSE;
+        bHasDoneJpegStartDecompress = false;
     }
     else
     {
-        jpeg_start_decompress( &sDInfo );
-        bHasDoneJpegStartDecompress = TRUE;
+        jpeg_start_decompress(&sDInfo);
+        bHasDoneJpegStartDecompress = true;
     }
 
     return CE_None;
@@ -1934,7 +1651,7 @@ CPLErr JPGDataset::Restart()
 CPLErr JPGDatasetCommon::GetGeoTransform( double * padfTransform )
 
 {
-    CPLErr eErr = GDALPamDataset::GetGeoTransform( padfTransform );
+    CPLErr eErr = GDALPamDataset::GetGeoTransform(padfTransform);
     if( eErr != CE_Failure )
         return eErr;
 
@@ -1942,7 +1659,7 @@ CPLErr JPGDatasetCommon::GetGeoTransform( double * padfTransform )
 
     if( bGeoTransformValid )
     {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
+        memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
 
         return CE_None;
     }
@@ -2010,13 +1727,14 @@ const GDAL_GCP *JPGDatasetCommon::GetGCPs()
 /************************************************************************/
 
 CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
-                                    int nXOff, int nYOff, int nXSize, int nYSize,
+                                    int nXOff, int nYOff,
+                                    int nXSize, int nYSize,
                                     void *pData, int nBufXSize, int nBufYSize,
                                     GDALDataType eBufType,
                                     int nBandCount, int *panBandMap,
                                     GSpacing nPixelSpace, GSpacing nLineSpace,
                                     GSpacing nBandSpace,
-                                    GDALRasterIOExtraArg* psExtraArg )
+                                    GDALRasterIOExtraArg *psExtraArg )
 
 {
     // Coverity says that we cannot pass a nullptr to IRasterIO.
@@ -2035,30 +1753,32 @@ CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
        (pData != NULL) &&
        (panBandMap != NULL) &&
        (panBandMap[0] == 1) && (panBandMap[1] == 2) && (panBandMap[2] == 3) &&
-       /* those color spaces need transformation to RGB */
+       // These color spaces need to be transformed to RGB.
        GetOutColorSpace() != JCS_YCCK && GetOutColorSpace() != JCS_CMYK )
     {
         Restart();
 
-        // Pixel interleaved case
+        // Pixel interleaved case.
         if( nBandSpace == 1 )
         {
             for(int y = 0; y < nYSize; ++y)
             {
                 CPLErr tmpError = LoadScanline(y);
-                if(tmpError != CE_None) return tmpError;
+                if(tmpError != CE_None)
+                    return tmpError;
 
                 if( nPixelSpace == 3 )
                 {
-                    memcpy(&(((GByte*)pData)[(y*nLineSpace)]),
-                           pabyScanline, 3 * nXSize);
+                    memcpy(&(((GByte *)pData)[(y * nLineSpace)]), pabyScanline,
+                           3 * nXSize);
                 }
                 else
                 {
                     for(int x = 0; x < nXSize; ++x)
                     {
-                        memcpy(&(((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace)]),
-                               (const GByte*)&(pabyScanline[x*3]), 3);
+                        memcpy(&(((GByte *)pData)[(y * nLineSpace) +
+                                                  (x * nPixelSpace)]),
+                               (const GByte *)&(pabyScanline[x * 3]), 3);
                     }
                 }
             }
@@ -2068,15 +1788,17 @@ CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
             for(int y = 0; y < nYSize; ++y)
             {
                 CPLErr tmpError = LoadScanline(y);
-                if(tmpError != CE_None) return tmpError;
+                if(tmpError != CE_None)
+                    return tmpError;
                 for(int x = 0; x < nXSize; ++x)
                 {
-                    static_cast<GByte*>(pData)[(y*nLineSpace) + (x*nPixelSpace)] =
-                        pabyScanline[x*3];
-                    ((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace) + nBandSpace] =
-                        pabyScanline[x*3+1];
-                    ((GByte*)pData)[(y*nLineSpace) + (x*nPixelSpace) + 2 * nBandSpace] =
-                        pabyScanline[x*3+2];
+                    static_cast<GByte *>(
+                        pData)[(y * nLineSpace) + (x * nPixelSpace)] =
+                        pabyScanline[x * 3];
+                    ((GByte *)pData)[(y * nLineSpace) + (x * nPixelSpace) +
+                                     nBandSpace] = pabyScanline[x * 3 + 1];
+                    ((GByte *)pData)[(y * nLineSpace) + (x * nPixelSpace) +
+                                     2 * nBandSpace] = pabyScanline[x * 3 + 2];
                 }
             }
         }
@@ -2099,14 +1821,13 @@ CPLErr JPGDatasetCommon::IRasterIO( GDALRWFlag eRWFlag,
 static int JPEGDatasetIsJPEGLS( GDALOpenInfo * poOpenInfo )
 
 {
-    GByte  *pabyHeader = poOpenInfo->pabyHeader;
-    int    nHeaderBytes = poOpenInfo->nHeaderBytes;
+    GByte *pabyHeader = poOpenInfo->pabyHeader;
+    int nHeaderBytes = poOpenInfo->nHeaderBytes;
 
     if( nHeaderBytes < 10 )
         return FALSE;
 
-    if( pabyHeader[0] != 0xff
-        || pabyHeader[1] != 0xd8 )
+    if( pabyHeader[0] != 0xff || pabyHeader[1] != 0xd8 )
         return FALSE;
 
     for (int nOffset = 2; nOffset + 4 < nHeaderBytes;)
@@ -2115,17 +1836,17 @@ static int JPEGDatasetIsJPEGLS( GDALOpenInfo * poOpenInfo )
             return FALSE;
 
         int nMarker = pabyHeader[nOffset + 1];
-        if (nMarker == 0xF7 /* JPEG Extension 7, JPEG-LS */)
+        if (nMarker == 0xF7)  // JPEG Extension 7, JPEG-LS.
             return TRUE;
-        if (nMarker == 0xF8 /* JPEG Extension 8, JPEG-LS Extension */)
+        if (nMarker == 0xF8)  // JPEG Extension 8, JPEG-LS Extension.
             return TRUE;
-        if (nMarker == 0xC3 /* Start of Frame 3 */)
+        if (nMarker == 0xC3)  // Start of Frame 3.
             return TRUE;
-        if (nMarker == 0xC7 /* Start of Frame 7 */)
+        if (nMarker == 0xC7)  // Start of Frame 7.
             return TRUE;
-        if (nMarker == 0xCB /* Start of Frame 11 */)
+        if (nMarker == 0xCB)  // Start of Frame 11.
             return TRUE;
-        if (nMarker == 0xCF /* Start of Frame 15 */)
+        if (nMarker == 0xCF)  // Start of Frame 15.
             return TRUE;
 
         nOffset += 2 + pabyHeader[nOffset + 2] * 256 + pabyHeader[nOffset + 3];
@@ -2139,28 +1860,23 @@ static int JPEGDatasetIsJPEGLS( GDALOpenInfo * poOpenInfo )
 /*                              Identify()                              */
 /************************************************************************/
 
-int JPGDatasetCommon::Identify( GDALOpenInfo * poOpenInfo )
+int JPGDatasetCommon::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      If it is a subfile, read the JPEG header.                       */
-/* -------------------------------------------------------------------- */
+    // If it is a subfile, read the JPEG header.
     if( STARTS_WITH_CI(poOpenInfo->pszFilename, "JPEG_SUBFILE:") )
         return TRUE;
 
-/* -------------------------------------------------------------------- */
-/*      First we check to see if the file has the expected header       */
-/*      bytes.                                                          */
-/* -------------------------------------------------------------------- */
+    // First we check to see if the file has the expected header bytes.
     const int nHeaderBytes = poOpenInfo->nHeaderBytes;
 
     if( nHeaderBytes < 10 )
         return FALSE;
 
     GByte * const pabyHeader = poOpenInfo->pabyHeader;
-    if( pabyHeader[0] != 0xff
-        || pabyHeader[1] != 0xd8
-        || pabyHeader[2] != 0xff )
+    if( pabyHeader[0] != 0xff ||
+        pabyHeader[1] != 0xd8 ||
+        pabyHeader[2] != 0xff )
         return FALSE;
 
 #if JPEG_LIB_VERSION_MAJOR < 9
@@ -2177,21 +1893,21 @@ int JPGDatasetCommon::Identify( GDALOpenInfo * poOpenInfo )
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *JPGDatasetCommon::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *JPGDatasetCommon::Open( GDALOpenInfo *poOpenInfo )
 
 {
-    if( !Identify( poOpenInfo ) )
+    if( !Identify(poOpenInfo) )
         return NULL;
 
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "The JPEG driver does not support update access to existing"
-                  " datasets." );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The JPEG driver does not support update access to existing"
+                 " datasets.");
         return NULL;
     }
 
-    VSILFILE* fpL = poOpenInfo->fpL;
+    VSILFILE *fpL = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
 
     JPGDatasetOpenArgs sArgs;
@@ -2199,10 +1915,10 @@ GDALDataset *JPGDatasetCommon::Open( GDALOpenInfo * poOpenInfo )
     sArgs.fpLin = fpL;
     sArgs.papszSiblingFiles = poOpenInfo->GetSiblingFiles();
     sArgs.nScaleFactor = 1;
-    sArgs.bDoPAMInitialize = TRUE;
+    sArgs.bDoPAMInitialize = true;
     sArgs.bUseInternalOverviews =
-        CSLFetchBoolean( poOpenInfo->papszOpenOptions, "USE_INTERNAL_OVERVIEWS",
-                         TRUE);
+        CPLFetchBool(poOpenInfo->papszOpenOptions,
+                     "USE_INTERNAL_OVERVIEWS", true);
 
     return JPGDataset::Open(&sArgs);
 }
@@ -2213,17 +1929,23 @@ GDALDataset *JPGDatasetCommon::Open( GDALOpenInfo * poOpenInfo )
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *JPGDataset::Open( JPGDatasetOpenArgs* psArgs )
+GDALDataset *JPGDataset::Open( JPGDatasetOpenArgs *psArgs )
 
 {
-    JPGDataset  *poDS = new JPGDataset();
-    /* Will detect mismatch between compile-time and run-time libjpeg versions */
+    JPGDataset *poDS = new JPGDataset();
+    return OpenStage2(psArgs, poDS);
+}
+
+GDALDataset *JPGDataset::OpenStage2( JPGDatasetOpenArgs *psArgs,
+                                     JPGDataset *&poDS )
+{
+    // Will detect mismatch between compile-time and run-time libjpeg versions.
     if (setjmp(poDS->sErrorStruct.setjmp_buffer))
     {
 #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
         if (poDS->sDInfo.data_precision == 12 && poDS->fpImage != NULL)
         {
-            VSILFILE* fpImage = poDS->fpImage;
+            VSILFILE *fpImage = poDS->fpImage;
             poDS->fpImage = NULL;
             delete poDS;
             psArgs->fpLin = fpImage;
@@ -2234,16 +1956,14 @@ GDALDataset *JPGDataset::Open( JPGDatasetOpenArgs* psArgs )
         return NULL;
     }
 
-    const char* pszFilename = psArgs->pszFilename;
-    VSILFILE* fpLin = psArgs->fpLin;
-    char** papszSiblingFiles = psArgs->papszSiblingFiles;
+    const char *pszFilename = psArgs->pszFilename;
+    VSILFILE *fpLin = psArgs->fpLin;
+    char **papszSiblingFiles = psArgs->papszSiblingFiles;
     const int nScaleFactor = psArgs->nScaleFactor;
-    const int bDoPAMInitialize = psArgs->bDoPAMInitialize;
-    const int bUseInternalOverviews = psArgs->bUseInternalOverviews;
+    const bool bDoPAMInitialize = psArgs->bDoPAMInitialize;
+    const bool bUseInternalOverviews = psArgs->bUseInternalOverviews;
 
-/* -------------------------------------------------------------------- */
-/*      If it is a subfile, read the JPEG header.                       */
-/* -------------------------------------------------------------------- */
+    // If it is a subfile, read the JPEG header.
     bool bIsSubfile = false;
     GUIntBig subfile_offset = 0;
     GUIntBig subfile_size = 0;
@@ -2256,31 +1976,27 @@ GDALDataset *JPGDataset::Open( JPGDatasetOpenArgs* psArgs )
 
         if( STARTS_WITH_CI(pszFilename, "JPEG_SUBFILE:Q") )
         {
-            char** papszTokens = CSLTokenizeString2(pszFilename + 14, ",", 0);
+            char **papszTokens = CSLTokenizeString2(pszFilename + 14, ",", 0);
             if (CSLCount(papszTokens) >= 3)
             {
                 nQLevel = atoi(papszTokens[0]);
-                subfile_offset =
-                    CPLScanUIntBig( papszTokens[1],
-                                    static_cast<int>(strlen(papszTokens[1])) );
-                subfile_size =
-                    CPLScanUIntBig( papszTokens[2],
-                                    static_cast<int>(strlen(papszTokens[2])) );
+                subfile_offset = CPLScanUIntBig(
+                    papszTokens[1], static_cast<int>(strlen(papszTokens[1])));
+                subfile_size = CPLScanUIntBig(
+                    papszTokens[2], static_cast<int>(strlen(papszTokens[2])));
                 bScan = true;
             }
             CSLDestroy(papszTokens);
         }
         else
         {
-            char** papszTokens = CSLTokenizeString2(pszFilename + 13, ",", 0);
+            char **papszTokens = CSLTokenizeString2(pszFilename + 13, ",", 0);
             if (CSLCount(papszTokens) >= 2)
             {
-                subfile_offset =
-                    CPLScanUIntBig( papszTokens[0],
-                                    static_cast<int>(strlen(papszTokens[0])));
-                subfile_size =
-                    CPLScanUIntBig( papszTokens[1],
-                                    static_cast<int>(strlen(papszTokens[1])) );
+                subfile_offset = CPLScanUIntBig(
+                    papszTokens[0], static_cast<int>(strlen(papszTokens[0])));
+                subfile_size = CPLScanUIntBig(
+                    papszTokens[1], static_cast<int>(strlen(papszTokens[1])));
                 bScan = true;
             }
             CSLDestroy(papszTokens);
@@ -2288,122 +2004,111 @@ GDALDataset *JPGDataset::Open( JPGDatasetOpenArgs* psArgs )
 
         if( !bScan )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Corrupt subfile definition: %s",
-                      pszFilename );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Corrupt subfile definition: %s",
+                     pszFilename);
             delete poDS;
             return NULL;
         }
 
-        real_filename = strstr(pszFilename,",");
+        real_filename = strstr(pszFilename, ",");
         if( real_filename != NULL )
-            real_filename = strstr(real_filename+1,",");
+            real_filename = strstr(real_filename + 1, ",");
         if( real_filename != NULL && nQLevel != -1 )
-            real_filename = strstr(real_filename+1,",");
+            real_filename = strstr(real_filename + 1, ",");
         if( real_filename != NULL )
             real_filename++;
         else
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Could not find filename in subfile definition." );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Could not find filename in subfile definition.");
             delete poDS;
             return NULL;
         }
 
-        CPLDebug( "JPG",
-                  "real_filename %s, offset=" CPL_FRMT_GUIB ", size="
-                  CPL_FRMT_GUIB "\n",
-                  real_filename, subfile_offset, subfile_size);
+        CPLDebug("JPG",
+                 "real_filename %s, offset=" CPL_FRMT_GUIB ", size="
+                 CPL_FRMT_GUIB "\n",
+                 real_filename, subfile_offset, subfile_size);
 
-        bIsSubfile = TRUE;
+        bIsSubfile = true;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Open the file using the large file api if necessary.            */
-/* -------------------------------------------------------------------- */
-    VSILFILE* fpImage = fpLin;
+    // Open the file using the large file api if necessary.
+    VSILFILE *fpImage = fpLin;
 
     if( fpImage == NULL )
     {
-        fpImage = VSIFOpenL( real_filename, "rb" );
+        fpImage = VSIFOpenL(real_filename, "rb");
 
         if( fpImage == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
-                      real_filename );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
+                     real_filename);
             delete poDS;
             return NULL;
         }
     }
     else
+    {
         fpImage = fpLin;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
+    // Create a corresponding GDALDataset.
     poDS->nQLevel = nQLevel;
     poDS->fpImage = fpImage;
 
-/* -------------------------------------------------------------------- */
-/*      Move to the start of jpeg data.                                 */
-/* -------------------------------------------------------------------- */
+    // Move to the start of jpeg data.
     poDS->nSubfileOffset = subfile_offset;
-    VSIFSeekL( poDS->fpImage, poDS->nSubfileOffset, SEEK_SET );
+    VSIFSeekL(poDS->fpImage, poDS->nSubfileOffset, SEEK_SET);
 
     poDS->eAccess = GA_ReadOnly;
 
-    poDS->sDInfo.err = jpeg_std_error( &(poDS->sJErr) );
+    poDS->sDInfo.err = jpeg_std_error(&poDS->sJErr);
     poDS->sJErr.error_exit = JPGDataset::ErrorExit;
     poDS->sErrorStruct.p_previous_emit_message = poDS->sJErr.emit_message;
     poDS->sJErr.emit_message = JPGDataset::EmitMessage;
-    poDS->sDInfo.client_data =
-        reinterpret_cast<void *>( &(poDS->sErrorStruct) );
+    poDS->sDInfo.client_data = &poDS->sErrorStruct;
 
-    jpeg_create_decompress( &(poDS->sDInfo) );
-    poDS->bHasDoneJpegCreateDecompress = TRUE;
+    jpeg_create_decompress(&poDS->sDInfo);
+    poDS->bHasDoneJpegCreateDecompress = true;
 
-    /* This is to address bug related in ticket #1795 */
+    // This is to address bug related in ticket #1795.
     if( CPLGetConfigOption("JPEGMEM", NULL) == NULL )
     {
         // If the user doesn't provide a value for JPEGMEM, we want to be sure
         // that at least 500 MB will be used before creating the temporary file.
+        const long nMinMemory = 500 * 1024 * 1024;
         poDS->sDInfo.mem->max_memory_to_use =
-            MAX(poDS->sDInfo.mem->max_memory_to_use, 500 * 1024 * 1024);
+            std::max(poDS->sDInfo.mem->max_memory_to_use, nMinMemory);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Preload default NITF JPEG quantization tables.                  */
-/* -------------------------------------------------------------------- */
-
 #if !defined(JPGDataset)
-    poDS->LoadDefaultTables( 0 );
-    poDS->LoadDefaultTables( 1 );
-    poDS->LoadDefaultTables( 2 );
-    poDS->LoadDefaultTables( 3 );
-#endif // !defined(JPGDataset)
+    // Preload default NITF JPEG quantization tables.
+    poDS->LoadDefaultTables(0);
+    poDS->LoadDefaultTables(1);
+    poDS->LoadDefaultTables(2);
+    poDS->LoadDefaultTables(3);
+#endif  // !defined(JPGDataset)
 
-/* -------------------------------------------------------------------- */
-/*      Read pre-image data after ensuring the file is rewound.         */
-/* -------------------------------------------------------------------- */
-    VSIFSeekL( poDS->fpImage, poDS->nSubfileOffset, SEEK_SET );
+    // Read pre-image data after ensuring the file is rewound.
+    VSIFSeekL(poDS->fpImage, poDS->nSubfileOffset, SEEK_SET);
 
-    jpeg_vsiio_src( &(poDS->sDInfo), poDS->fpImage );
-    jpeg_read_header( &(poDS->sDInfo), TRUE );
+    jpeg_vsiio_src(&poDS->sDInfo, poDS->fpImage);
+    jpeg_read_header(&poDS->sDInfo, TRUE);
 
     if( poDS->sDInfo.data_precision != 8
         && poDS->sDInfo.data_precision != 12 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "GDAL JPEG Driver doesn't support files with precision of "
-                  "other than 8 or 12 bits." );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "GDAL JPEG Driver doesn't support files with precision of "
+                 "other than 8 or 12 bits.");
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Capture some information from the file that is of interest.     */
-/* -------------------------------------------------------------------- */
+    // Capture some information from the file that is of interest.
 
     poDS->nScaleFactor = nScaleFactor;
     poDS->SetScaleNumAndDenom();
@@ -2459,8 +2164,8 @@ GDALDataset *JPGDataset::Open( JPGDatasetOpenArgs* psArgs )
             poDS->SetMetadataItem(
                 "SOURCE_COLOR_SPACE", "YCbCrK", "IMAGE_STRUCTURE" );
 
-            /* libjpeg does the translation from YCrCbK -> CMYK internally */
-            /* and we'll do the translation to RGB in IReadBlock() */
+            // libjpeg does the translation from YCrCbK -> CMYK internally
+            // and we'll do the translation to RGB in IReadBlock().
             poDS->sDInfo.out_color_space = JCS_CMYK;
         }
         else
@@ -2470,52 +2175,44 @@ GDALDataset *JPGDataset::Open( JPGDatasetOpenArgs* psArgs )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Unrecognized jpeg_color_space value of %d.\n",
-                  poDS->sDInfo.jpeg_color_space );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Unrecognized jpeg_color_space value of %d.\n",
+                 poDS->sDInfo.jpeg_color_space);
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
+    // Create band information objects.
     for( int iBand = 0; iBand < poDS->nBands; iBand++ )
-        poDS->SetBand( iBand+1, JPGCreateBand( poDS, iBand+1 ) );
+        poDS->SetBand(iBand + 1, JPGCreateBand(poDS, iBand + 1));
 
-/* -------------------------------------------------------------------- */
-/*      More metadata.                                                  */
-/* -------------------------------------------------------------------- */
-    if( poDS->nBands > 1 )
+    // More metadata.
+    if(poDS->nBands > 1)
     {
-        poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
-        poDS->SetMetadataItem( "COMPRESSION", "JPEG", "IMAGE_STRUCTURE" );
+        poDS->SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+        poDS->SetMetadataItem("COMPRESSION", "JPEG", "IMAGE_STRUCTURE");
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( pszFilename );
+    // Initialize any PAM information.
+    poDS->SetDescription(pszFilename);
 
     if( nScaleFactor == 1 && bDoPAMInitialize )
     {
         if( !bIsSubfile )
-            poDS->TryLoadXML( papszSiblingFiles );
+            poDS->TryLoadXML(papszSiblingFiles);
         else
             poDS->nPamFlags |= GPF_NOSAVE;
 
-/* -------------------------------------------------------------------- */
-/*      Open (external) overviews.                                      */
-/* -------------------------------------------------------------------- */
-        poDS->oOvManager.Initialize( poDS, real_filename, papszSiblingFiles );
+        // Open (external) overviews.
+        poDS->oOvManager.Initialize(poDS, real_filename, papszSiblingFiles);
 
         if( !bUseInternalOverviews )
-            poDS->bHasInitInternalOverviews = TRUE;
+            poDS->bHasInitInternalOverviews = true;
 
-        /* In the case of a file downloaded through the HTTP driver, this one */
-        /* will unlink the temporary /vsimem file just after GDALOpen(), so */
-        /* later VSIFOpenL() when reading internal overviews would fail. */
-        /* Initialize them now */
+        // In the case of a file downloaded through the HTTP driver, this one
+        // will unlink the temporary /vsimem file just after GDALOpen(), so
+        // later VSIFOpenL() when reading internal overviews would fail.
+        // Initialize them now.
         if( STARTS_WITH(real_filename, "/vsimem/http_") )
         {
             poDS->InitInternalOverviews();
@@ -2543,40 +2240,32 @@ void JPGDatasetCommon::LoadWorldFileOrTab()
         return;
     if (bHasTriedLoadWorldFileOrTab)
         return;
-    bHasTriedLoadWorldFileOrTab = TRUE;
+    bHasTriedLoadWorldFileOrTab = true;
 
-    char* pszWldFilename = NULL;
+    char *pszWldFilename = NULL;
 
-    /* TIROS3 JPEG files have a .wld extension, so don't look for .wld as */
-    /* as worldfile ! */
+    // TIROS3 JPEG files have a .wld extension, so don't look for .wld as
+    // as worldfile.
     const bool bEndsWithWld =
         strlen(GetDescription()) > 4 &&
-        EQUAL( GetDescription() + strlen(GetDescription()) - 4, ".wld");
+        EQUAL(GetDescription() + strlen(GetDescription()) - 4, ".wld");
     bGeoTransformValid =
-        GDALReadWorldFile2( GetDescription(), NULL,
-                            adfGeoTransform,
-                            oOvManager.GetSiblingFiles(), &pszWldFilename )
-        || GDALReadWorldFile2( GetDescription(), ".jpw",
-                                adfGeoTransform,
-                               oOvManager.GetSiblingFiles(), &pszWldFilename )
-        || ( !bEndsWithWld &&
-             GDALReadWorldFile2( GetDescription(), ".wld",
-                                 adfGeoTransform,
-                                 oOvManager.GetSiblingFiles(),
-                                 &pszWldFilename ));
+        GDALReadWorldFile2(GetDescription(), NULL, adfGeoTransform,
+                           oOvManager.GetSiblingFiles(), &pszWldFilename) ||
+        GDALReadWorldFile2(GetDescription(), ".jpw", adfGeoTransform,
+                           oOvManager.GetSiblingFiles(), &pszWldFilename) ||
+        (!bEndsWithWld &&
+         GDALReadWorldFile2(GetDescription(), ".wld", adfGeoTransform,
+                            oOvManager.GetSiblingFiles(), &pszWldFilename));
 
     if( !bGeoTransformValid )
     {
-        const bool bTabFileOK =
-            CPL_TO_BOOL(
-                GDALReadTabFile2( GetDescription(), adfGeoTransform,
-                                  &pszProjection,
-                                  &nGCPCount, &pasGCPList,
-                                  oOvManager.GetSiblingFiles(),
-                                  &pszWldFilename ));
+        const bool bTabFileOK = CPL_TO_BOOL(GDALReadTabFile2(
+            GetDescription(), adfGeoTransform, &pszProjection, &nGCPCount,
+            &pasGCPList, oOvManager.GetSiblingFiles(), &pszWldFilename));
 
         if( bTabFileOK && nGCPCount == 0 )
-            bGeoTransformValid = TRUE;
+            bGeoTransformValid = true;
     }
 
     if (pszWldFilename)
@@ -2597,10 +2286,10 @@ char **JPGDatasetCommon::GetFileList()
 
     LoadWorldFileOrTab();
 
-    if( osWldFilename.size() != 0 &&
+    if( !osWldFilename.empty() &&
         CSLFindString(papszFileList, osWldFilename) == -1 )
     {
-        papszFileList = CSLAddString( papszFileList, osWldFilename );
+        papszFileList = CSLAddString(papszFileList, osWldFilename);
     }
 
     return papszFileList;
@@ -2613,52 +2302,45 @@ char **JPGDatasetCommon::GetFileList()
 void JPGDatasetCommon::CheckForMask()
 
 {
-    /* Save current position to avoid disturbing JPEG stream decoding */
+    // Save current position to avoid disturbing JPEG stream decoding.
     const vsi_l_offset nCurOffset = VSIFTellL(fpImage);
 
-/* -------------------------------------------------------------------- */
-/*      Go to the end of the file, pull off four bytes, and see if      */
-/*      it is plausibly the size of the real image data.                */
-/* -------------------------------------------------------------------- */
-    VSIFSeekL( fpImage, 0, SEEK_END );
-    GIntBig nFileSize = VSIFTellL( fpImage );
-    VSIFSeekL( fpImage, nFileSize - 4, SEEK_SET );
+    // Go to the end of the file, pull off four bytes, and see if
+    // it is plausibly the size of the real image data.
+    VSIFSeekL(fpImage, 0, SEEK_END);
+    GIntBig nFileSize = VSIFTellL(fpImage);
+    VSIFSeekL(fpImage, nFileSize - 4, SEEK_SET);
 
     GUInt32 nImageSize = 0;
-    VSIFReadL( &nImageSize, 4, 1, fpImage );
-    CPL_LSBPTR32( &nImageSize );
+    VSIFReadL(&nImageSize, 4, 1, fpImage);
+    CPL_LSBPTR32(&nImageSize);
 
     GByte abyEOD[2] = { 0, 0 };
 
     if( nImageSize < nFileSize / 2 || nImageSize > nFileSize - 4 )
         goto end;
 
-/* -------------------------------------------------------------------- */
-/*      If that seems okay, seek back, and verify that just preceding   */
-/*      the bitmask is an apparent end-of-jpeg-data marker.             */
-/* -------------------------------------------------------------------- */
-    VSIFSeekL( fpImage, nImageSize - 2, SEEK_SET );
-    VSIFReadL( abyEOD, 2, 1, fpImage );
+    // If that seems okay, seek back, and verify that just preceding
+    // the bitmask is an apparent end-of-jpeg-data marker.
+    VSIFSeekL(fpImage, nImageSize - 2, SEEK_SET);
+    VSIFReadL(abyEOD, 2, 1, fpImage);
     if( abyEOD[0] != 0xff || abyEOD[1] != 0xd9 )
         goto end;
 
-/* -------------------------------------------------------------------- */
-/*      We seem to have a mask.  Read it in.                            */
-/* -------------------------------------------------------------------- */
+    // We seem to have a mask.  Read it in.
     nCMaskSize = static_cast<int>(nFileSize - nImageSize - 4);
-    pabyCMask = static_cast<GByte *>( VSI_MALLOC_VERBOSE(nCMaskSize) );
+    pabyCMask = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nCMaskSize));
     if (pabyCMask == NULL)
     {
         goto end;
     }
-    VSIFReadL( pabyCMask, nCMaskSize, 1, fpImage );
+    VSIFReadL(pabyCMask, nCMaskSize, 1, fpImage);
 
-    CPLDebug( "JPEG", "Got %d byte compressed bitmask.",
-              nCMaskSize );
+    CPLDebug("JPEG", "Got %d byte compressed bitmask.", nCMaskSize);
 
     // TODO(schwehr): Refactor to not use goto.
 end:
-    VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
+    VSIFSeekL(fpImage, nCurOffset, SEEK_SET);
 }
 
 /************************************************************************/
@@ -2671,11 +2353,9 @@ void JPGDatasetCommon::DecompressMask()
     if( pabyCMask == NULL || pabyBitMask != NULL )
         return;
 
-/* -------------------------------------------------------------------- */
-/*      Allocate 1bit buffer - may be slightly larger than needed.      */
-/* -------------------------------------------------------------------- */
+    // Allocate 1bit buffer - may be slightly larger than needed.
     const int nBufSize = nRasterYSize * ((nRasterXSize + 7) / 8);
-    pabyBitMask = static_cast<GByte *>( VSI_MALLOC_VERBOSE( nBufSize ) );
+    pabyBitMask = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBufSize));
     if (pabyBitMask == NULL)
     {
         CPLFree(pabyCMask);
@@ -2683,32 +2363,30 @@ void JPGDatasetCommon::DecompressMask()
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Decompress                                                      */
-/* -------------------------------------------------------------------- */
-    void* pOut = CPLZLibInflate( pabyCMask, nCMaskSize,
-                                 pabyBitMask, nBufSize, NULL );
-/* -------------------------------------------------------------------- */
-/*      Cleanup if an error occurs.                                     */
-/* -------------------------------------------------------------------- */
+    // Decompress.
+    void *pOut =
+        CPLZLibInflate(pabyCMask, nCMaskSize, pabyBitMask, nBufSize, NULL);
+
+    // Cleanup if an error occurs.
     if( pOut == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Failure decoding JPEG validity bitmask." );
-        CPLFree( pabyCMask );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failure decoding JPEG validity bitmask.");
+        CPLFree(pabyCMask);
         pabyCMask = NULL;
 
-        CPLFree( pabyBitMask );
+        CPLFree(pabyBitMask);
         pabyBitMask = NULL;
 
         return;
     }
 
-    const char* pszJPEGMaskBitOrder = CPLGetConfigOption("JPEG_MASK_BIT_ORDER", "AUTO");
+    const char *pszJPEGMaskBitOrder =
+        CPLGetConfigOption("JPEG_MASK_BIT_ORDER", "AUTO");
     if( EQUAL(pszJPEGMaskBitOrder, "LSB") )
-        bMaskLSBOrder = TRUE;
+        bMaskLSBOrder = true;
     else if( EQUAL(pszJPEGMaskBitOrder, "MSB") )
-        bMaskLSBOrder = FALSE;
+        bMaskLSBOrder = false;
     else if( nRasterXSize > 8 && nRasterYSize > 1 )
     {
         // Test MSB ordering hypothesis in a very restrictive case where it is
@@ -2724,24 +2402,25 @@ void JPGDatasetCommon::DecompressMask()
         // We can only be sure of this heuristics if the change of value occurs
         // in the middle of a byte, or if the raster width is not a multiple of
         // 8.
+        //
+        // TODO(schwehr): Check logic in this section that was added in r26063.
         int nPrevValBit = 0;
         int nChangedValBit = 0;
         int iX = 0;  // Used after for.
         for( ; iX < nRasterXSize; iX++ )
         {
             const int nValBit =
-                (pabyBitMask[iX>>3] & (0x1 << (7 - (iX&7)))) != 0;
+                (pabyBitMask[iX >> 3] & (0x1 << (7 - (iX & 7)))) != 0;
             if( iX == 0 )
                 nPrevValBit = nValBit;
             else if( nValBit != nPrevValBit )
             {
                 nPrevValBit = nValBit;
-                nChangedValBit ++;
+                nChangedValBit++;
                 if( nChangedValBit == 1 )
                 {
-                    const bool bValChangedOnByteBoundary = ((iX % 8) == 0);
-                    if( bValChangedOnByteBoundary &&
-                        ((nRasterXSize % 8) == 0 ) )
+                    const bool bValChangedOnByteBoundary = (iX % 8) == 0;
+                    if( bValChangedOnByteBoundary && (nRasterXSize % 8) == 0 )
                         break;
                 }
                 else
@@ -2750,29 +2429,30 @@ void JPGDatasetCommon::DecompressMask()
                 }
             }
             const int iNextLineX = iX + nRasterXSize;
-            const int nNextLineValBit =
-                (pabyBitMask[iNextLineX>>3] & (0x1 << (7 - (iNextLineX&7))))
-                != 0;
+            const int nNextLineValBit = (pabyBitMask[iNextLineX >> 3] &
+                                         (0x1 << (7 - (iNextLineX & 7)))) != 0;
             if( nValBit != nNextLineValBit )
                 break;
         }
 
         if( iX == nRasterXSize )
         {
-            CPLDebug(
-                "JPEG", "Bit ordering in mask is guessed to be msb (unusual)" );
-            bMaskLSBOrder = FALSE;
+            CPLDebug("JPEG",
+                     "Bit ordering in mask is guessed to be msb (unusual)");
+            bMaskLSBOrder = false;
         }
         else
-            bMaskLSBOrder = TRUE;
+        {
+            bMaskLSBOrder = true;
+        }
     }
     else
     {
-        bMaskLSBOrder = TRUE;
+        bMaskLSBOrder = true;
     }
 }
 
-#endif // !defined(JPGDataset)
+#endif  // !defined(JPGDataset)
 
 /************************************************************************/
 /*                             ErrorExit()                              */
@@ -2780,23 +2460,22 @@ void JPGDatasetCommon::DecompressMask()
 
 void JPGDataset::ErrorExit(j_common_ptr cinfo)
 {
-    GDALJPEGErrorStruct* psErrorStruct =
-        static_cast<GDALJPEGErrorStruct *>( cinfo->client_data );
-    char buffer[JMSG_LENGTH_MAX] = { '\0' };
+    GDALJPEGErrorStruct *psErrorStruct =
+        static_cast<GDALJPEGErrorStruct *>(cinfo->client_data);
+    char buffer[JMSG_LENGTH_MAX] = {};
 
-    /* Create the message */
-    (*cinfo->err->format_message) (cinfo, buffer);
+    // Create the message.
+    (*cinfo->err->format_message)(cinfo, buffer);
 
-/* Avoid error for a 12bit JPEG if reading from the 8bit JPEG driver and */
-/* we have JPEG_DUAL_MODE_8_12 support, as we'll try again with 12bit JPEG */
-/* driver */
+    // Avoid error for a 12bit JPEG if reading from the 8bit JPEG driver and
+    // we have JPEG_DUAL_MODE_8_12 support, as we'll try again with 12bit JPEG
+    // driver.
 #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
     if (strstr(buffer, "Unsupported JPEG data precision 12") == NULL)
 #endif
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "libjpeg: %s", buffer );
+    CPLError(CE_Failure, CPLE_AppDefined, "libjpeg: %s", buffer);
 
-    /* Return control to the setjmp point */
+    // Return control to the setjmp point.
     longjmp(psErrorStruct->setjmp_buffer, 1);
 }
 
@@ -2806,9 +2485,9 @@ void JPGDataset::ErrorExit(j_common_ptr cinfo)
 
 void JPGDataset::EmitMessage(j_common_ptr cinfo, int msg_level)
 {
-    GDALJPEGErrorStruct* psErrorStruct =
-        static_cast<GDALJPEGErrorStruct *>( cinfo->client_data );
-    if( msg_level >= 0 ) /* Trace message */
+    GDALJPEGErrorStruct *psErrorStruct =
+        static_cast<GDALJPEGErrorStruct *>(cinfo->client_data);
+    if( msg_level >= 0 )  // Trace message.
     {
         if( psErrorStruct->p_previous_emit_message != NULL )
             psErrorStruct->p_previous_emit_message(cinfo, msg_level);
@@ -2818,34 +2497,34 @@ void JPGDataset::EmitMessage(j_common_ptr cinfo, int msg_level)
         // Warning : libjpeg will try to recover but the image will be likely
         // corrupted.
 
-        struct jpeg_error_mgr * err = cinfo->err;
+        struct jpeg_error_mgr *err = cinfo->err;
 
         // It's a warning message.  Since corrupt files may generate many
         // warnings, the policy implemented here is to show only the first
         // warning, unless trace_level >= 3.
         if (err->num_warnings == 0 || err->trace_level >= 3)
         {
-            char buffer[JMSG_LENGTH_MAX] = { '\0' };
+            char buffer[JMSG_LENGTH_MAX] = {};
 
-            /* Create the message */
+            // Create the message.
             (*cinfo->err->format_message) (cinfo, buffer);
 
             if( CPLTestBool(
                    CPLGetConfigOption("GDAL_ERROR_ON_LIBJPEG_WARNING", "NO")) )
             {
-                psErrorStruct->bNonFatalErrorEncountered = TRUE;
-                CPLError( CE_Failure, CPLE_AppDefined, "libjpeg: %s", buffer );
+                psErrorStruct->bNonFatalErrorEncountered = true;
+                CPLError(CE_Failure, CPLE_AppDefined, "libjpeg: %s", buffer);
             }
             else
             {
-                CPLError( CE_Warning, CPLE_AppDefined,
-                          "libjpeg: %s (this warning can be turned as an error "
-                          "by setting GDAL_ERROR_ON_LIBJPEG_WARNING to TRUE)",
-                          buffer );
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "libjpeg: %s (this warning can be turned as an error "
+                         "by setting GDAL_ERROR_ON_LIBJPEG_WARNING to TRUE)",
+                         buffer);
             }
         }
 
-        /* Always count warnings in num_warnings. */
+        // Always count warnings in num_warnings.
         err->num_warnings++;
     }
 }
@@ -2866,34 +2545,34 @@ void JPGAddICCProfile( void *pInfo,
     if( pszICCProfile == NULL )
         return;
 
-    /* Write out each segment of the ICC profile */
+    // Write out each segment of the ICC profile.
     char *pEmbedBuffer = CPLStrdup(pszICCProfile);
-    GInt32 nEmbedLen = CPLBase64DecodeInPlace((GByte*)pEmbedBuffer);
+    GInt32 nEmbedLen = CPLBase64DecodeInPlace((GByte *)pEmbedBuffer);
     char *pEmbedPtr = pEmbedBuffer;
-    char const * const paHeader = "ICC_PROFILE";
+    char const *const paHeader = "ICC_PROFILE";
     int nSegments = (nEmbedLen + 65518) / 65519;
     int nSegmentID = 1;
 
     while( nEmbedLen != 0)
     {
-        /* 65535 - 16 bytes for header = 65519 */
+        // 65535 - 16 bytes for header = 65519
         const int nChunkLen = (nEmbedLen > 65519) ? 65519 : nEmbedLen;
         nEmbedLen -= nChunkLen;
 
-        /* write marker and length. */
+        // Write marker and length.
         p_jpeg_write_m_header(
             pInfo, JPEG_APP0 + 2,
-            static_cast<unsigned int>( nChunkLen + 14 ) );
+            static_cast<unsigned int>(nChunkLen + 14));
 
-        /* Write identifier */
+        // Write identifier.
         for( int i = 0; i < 12; i++ )
             p_jpeg_write_m_byte(pInfo, paHeader[i]);
 
-        /* Write ID and max ID */
+        // Write ID and max ID.
         p_jpeg_write_m_byte(pInfo, nSegmentID);
         p_jpeg_write_m_byte(pInfo, nSegments);
 
-        /* Write ICC Profile */
+        // Write ICC Profile.
         for(int i = 0; i < nChunkLen; i++)
             p_jpeg_write_m_byte(pInfo, pEmbedPtr[i]);
 
@@ -2926,34 +2605,29 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
     const int nBitBufSize = nYSize * ((nXSize + 7) / 8);
     CPLErr eErr = CE_None;
 
-/* -------------------------------------------------------------------- */
-/*      Allocate uncompressed bit buffer.                               */
-/* -------------------------------------------------------------------- */
+    // Allocate uncompressed bit buffer.
     GByte *pabyBitBuf =
-        static_cast<GByte *>( VSI_CALLOC_VERBOSE(1,nBitBufSize) );
+        static_cast<GByte *>(VSI_CALLOC_VERBOSE(1, nBitBufSize));
 
-    GByte *pabyMaskLine =
-        static_cast<GByte *>( VSI_MALLOC_VERBOSE(nXSize) );
+    GByte *pabyMaskLine = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize));
     if (pabyBitBuf == NULL || pabyMaskLine == NULL)
     {
         eErr = CE_Failure;
     }
 
-    /* No reason to set it to MSB, unless for debugging purposes */
-    /* to be able to generate a unusual LSB ordered mask (#5102) */
-    const char* pszJPEGMaskBitOrder =
+    // No reason to set it to MSB, unless for debugging purposes
+    // to be able to generate a unusual LSB ordered mask (#5102).
+    const char *pszJPEGMaskBitOrder =
         CPLGetConfigOption("JPEG_WRITE_MASK_BIT_ORDER", "LSB");
-    int bMaskLSBOrder = EQUAL(pszJPEGMaskBitOrder, "LSB");
+    const bool bMaskLSBOrder = EQUAL(pszJPEGMaskBitOrder, "LSB");
 
-/* -------------------------------------------------------------------- */
-/*      Set bit buffer from mask band, scanline by scanline.            */
-/* -------------------------------------------------------------------- */
+    // Set bit buffer from mask band, scanline by scanline.
     GUInt32 iBit = 0;
     for( int iY = 0; eErr == CE_None && iY < nYSize; iY++ )
     {
-        eErr = poMask->RasterIO( GF_Read, 0, iY, nXSize, 1,
-                                 pabyMaskLine, nXSize, 1, GDT_Byte,
-                                 0, 0, NULL );
+        eErr = poMask->RasterIO(GF_Read, 0, iY, nXSize, 1,
+                                pabyMaskLine, nXSize, 1, GDT_Byte,
+                                0, 0, NULL);
         if( eErr != CE_None )
             break;
 
@@ -2962,7 +2636,7 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
             for( int iX = 0; iX < nXSize; iX++ )
             {
                 if( pabyMaskLine[iX] != 0 )
-                    pabyBitBuf[iBit>>3] |= (0x1 << (iBit&7));
+                    pabyBitBuf[iBit >> 3] |= (0x1 << (iBit & 7));
 
                 iBit++;
             }
@@ -2972,33 +2646,30 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
             for( int iX = 0; iX < nXSize; iX++ )
             {
                 if( pabyMaskLine[iX] != 0 )
-                    pabyBitBuf[iBit>>3] |= (0x1 << (7 - (iBit&7)));
+                    pabyBitBuf[iBit >> 3] |= (0x1 << (7 - (iBit & 7)));
 
                 iBit++;
             }
         }
 
-        if( eErr == CE_None
-            && !pfnProgress( (iY + 1) / static_cast<double>( nYSize ),
-                             NULL, pProgressData ) )
+        if( eErr == CE_None &&
+            !pfnProgress((iY + 1) / static_cast<double>(nYSize),
+                         NULL, pProgressData) )
         {
             eErr = CE_Failure;
-            CPLError( CE_Failure, CPLE_UserInterrupt,
-                      "User terminated JPGAppendMask()" );
+            CPLError(CE_Failure, CPLE_UserInterrupt,
+                     "User terminated JPGAppendMask()");
         }
     }
 
-    CPLFree( pabyMaskLine );
+    CPLFree(pabyMaskLine);
 
-/* -------------------------------------------------------------------- */
-/*      Compress                                                        */
-/* -------------------------------------------------------------------- */
+    // Compress.
     GByte *pabyCMask = NULL;
 
     if( eErr == CE_None )
     {
-        pabyCMask =
-            static_cast<GByte *>( VSI_MALLOC_VERBOSE(nBitBufSize + 30) );
+        pabyCMask = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBitBufSize + 30));
         if (pabyCMask == NULL)
         {
             eErr = CE_Failure;
@@ -3008,52 +2679,51 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
     size_t nTotalOut = 0;
     if ( eErr == CE_None )
     {
-        if( CPLZLibDeflate( pabyBitBuf, nBitBufSize, 9,
-                            pabyCMask, nBitBufSize + 30,
-                            &nTotalOut ) == NULL )
+        if( CPLZLibDeflate(pabyBitBuf, nBitBufSize, 9,
+                           pabyCMask, nBitBufSize + 30,
+                           &nTotalOut) == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Deflate compression of jpeg bit mask failed." );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Deflate compression of jpeg bit mask failed.");
             eErr = CE_Failure;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write to disk, along with image file size.                      */
-/* -------------------------------------------------------------------- */
+    // Write to disk, along with image file size.
     if( eErr == CE_None )
     {
-        VSILFILE *fpOut = VSIFOpenL( pszJPGFilename, "r+" );
+        VSILFILE *fpOut = VSIFOpenL(pszJPGFilename, "r+");
         if( fpOut == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Failed to open jpeg to append bitmask." );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Failed to open jpeg to append bitmask.");
             eErr = CE_Failure;
         }
         else
         {
-            VSIFSeekL( fpOut, 0, SEEK_END );
+            VSIFSeekL(fpOut, 0, SEEK_END);
 
-            GUInt32 nImageSize = static_cast<GUInt32>( VSIFTellL( fpOut ) );
-            CPL_LSBPTR32( &nImageSize );
+            GUInt32 nImageSize = static_cast<GUInt32>(VSIFTellL(fpOut));
+            CPL_LSBPTR32(&nImageSize);
 
-            if( VSIFWriteL( pabyCMask, 1, nTotalOut, fpOut )
-                != nTotalOut )
+            if( VSIFWriteL(pabyCMask, 1, nTotalOut, fpOut) != nTotalOut )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Failure writing compressed bitmask.\n%s",
-                          VSIStrerror( errno ) );
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Failure writing compressed bitmask.\n%s",
+                         VSIStrerror(errno));
                 eErr = CE_Failure;
             }
             else
-                VSIFWriteL( &nImageSize, 4, 1, fpOut );
+            {
+                VSIFWriteL(&nImageSize, 4, 1, fpOut);
+            }
 
-            VSIFCloseL( fpOut );
+            VSIFCloseL(fpOut);
         }
     }
 
-    CPLFree( pabyBitBuf );
-    CPLFree( pabyCMask );
+    CPLFree(pabyBitBuf);
+    CPLFree(pabyCMask);
 
     return eErr;
 }
@@ -3063,14 +2733,15 @@ CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
 /************************************************************************/
 
 void   JPGAddEXIFOverview( GDALDataType eWorkDT,
-                           GDALDataset* poSrcDS, char** papszOptions,
-                           void* cinfo,
+                           GDALDataset *poSrcDS, char **papszOptions,
+                           void *cinfo,
                            my_jpeg_write_m_header p_jpeg_write_m_header,
                            my_jpeg_write_m_byte p_jpeg_write_m_byte,
-                           GDALDataset *(pCreateCopy)( const char *, GDALDataset *,
-                                     int, char **,
-                                     GDALProgressFunc pfnProgress,
-                                     void * pProgressData ))
+                           GDALDataset *(pCreateCopy)(
+                               const char *, GDALDataset *,
+                               int, char **,
+                               GDALProgressFunc pfnProgress,
+                               void *pProgressData ))
 {
     const int nBands = poSrcDS->GetRasterCount();
     const int nXSize = poSrcDS->GetRasterXSize();
@@ -3078,9 +2749,9 @@ void   JPGAddEXIFOverview( GDALDataType eWorkDT,
 
     bool bGenerateEXIFThumbnail =
         CPLTestBool(CSLFetchNameValueDef(papszOptions, "EXIF_THUMBNAIL", "NO"));
-    const char* pszThumbnailWidth =
+    const char *pszThumbnailWidth =
         CSLFetchNameValue(papszOptions, "THUMBNAIL_WIDTH");
-    const char* pszThumbnailHeight =
+    const char *pszThumbnailHeight =
         CSLFetchNameValue(papszOptions, "THUMBNAIL_HEIGHT");
     int nOvrWidth = 0;
     int nOvrHeight = 0;
@@ -3119,32 +2790,33 @@ void   JPGAddEXIFOverview( GDALDataType eWorkDT,
     }
     else if( nOvrHeight == 0 )
     {
-        nOvrHeight = static_cast<int>(
-            static_cast<GIntBig>(nOvrWidth) * nYSize / nXSize);
-        if( nOvrHeight == 0 ) nOvrHeight = 1;
+        nOvrHeight =
+            static_cast<int>(static_cast<GIntBig>(nOvrWidth) * nYSize / nXSize);
+        if( nOvrHeight == 0 )
+            nOvrHeight = 1;
     }
 
     if( bGenerateEXIFThumbnail && nXSize > nOvrWidth && nYSize > nOvrHeight )
     {
-        GDALDataset* poMemDS =
-            MEMDataset::Create( "", nOvrWidth, nOvrHeight, nBands,
-                                eWorkDT, NULL );
-        GDALRasterBand** papoSrcBands = static_cast<GDALRasterBand **>(
-            CPLMalloc(nBands * sizeof(GDALRasterBand*) ) );
-        GDALRasterBand*** papapoOverviewBands = static_cast<GDALRasterBand***>(
-            CPLMalloc(nBands * sizeof(GDALRasterBand**)) );
-        for(int i=0;i<nBands;i++)
+        GDALDataset *poMemDS =
+            MEMDataset::Create("", nOvrWidth, nOvrHeight, nBands,
+                               eWorkDT, NULL);
+        GDALRasterBand **papoSrcBands = static_cast<GDALRasterBand **>(
+            CPLMalloc(nBands * sizeof(GDALRasterBand *)));
+        GDALRasterBand ***papapoOverviewBands = static_cast<GDALRasterBand ***>(
+            CPLMalloc(nBands * sizeof(GDALRasterBand **)));
+        for(int i = 0; i < nBands; i++)
         {
-            papoSrcBands[i] = poSrcDS->GetRasterBand(i+1);
+            papoSrcBands[i] = poSrcDS->GetRasterBand(i + 1);
             papapoOverviewBands[i] = static_cast<GDALRasterBand **>(
-                CPLMalloc(sizeof(GDALRasterBand*)) );
-            papapoOverviewBands[i][0] = poMemDS->GetRasterBand(i+1);
+                CPLMalloc(sizeof(GDALRasterBand *)));
+            papapoOverviewBands[i][0] = poMemDS->GetRasterBand(i + 1);
         }
-        CPLErr eErr = GDALRegenerateOverviewsMultiBand( nBands, papoSrcBands,
-                                                        1, papapoOverviewBands,
-                                                        "AVERAGE", NULL, NULL );
+        CPLErr eErr = GDALRegenerateOverviewsMultiBand(nBands, papoSrcBands,
+                                                       1, papapoOverviewBands,
+                                                       "AVERAGE", NULL, NULL);
         CPLFree(papoSrcBands);
-        for(int i=0;i<nBands;i++)
+        for(int i = 0; i < nBands; i++)
         {
             CPLFree(papapoOverviewBands[i]);
         }
@@ -3156,184 +2828,182 @@ void   JPGAddEXIFOverview( GDALDataType eWorkDT,
             return;
         }
 
-        CPLString osTmpFile(CPLSPrintf("/vsimem/ovrjpg%p",poMemDS));
-        GDALDataset* poOutDS =
+        CPLString osTmpFile(CPLSPrintf("/vsimem/ovrjpg%p", poMemDS));
+        GDALDataset *poOutDS =
             pCreateCopy(osTmpFile, poMemDS, 0, NULL, GDALDummyProgress, NULL);
-        bool bExifOverviewSuccess = poOutDS != NULL;
+        const bool bExifOverviewSuccess = poOutDS != NULL;
         delete poOutDS;
         poOutDS = NULL;
         GDALClose(poMemDS);
         vsi_l_offset nJPEGIfByteCount = 0;
-        GByte* pabyOvr = NULL;
+        GByte *pabyOvr = NULL;
         if( bExifOverviewSuccess )
-            pabyOvr = VSIGetMemFileBuffer( osTmpFile, &nJPEGIfByteCount, TRUE );
+            pabyOvr = VSIGetMemFileBuffer(osTmpFile, &nJPEGIfByteCount, TRUE);
         VSIUnlink(osTmpFile);
 
         const unsigned int nMarkerSize =
             6 + 16 + 5 * 12 + 4 + static_cast<unsigned int>(nJPEGIfByteCount);
         if( pabyOvr == NULL )
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Could not generate EXIF overview" );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Could not generate EXIF overview");
         }
         else if( nMarkerSize < 65536 )
         {
-            p_jpeg_write_m_header( cinfo, JPEG_APP0 + 1, nMarkerSize );
-            p_jpeg_write_m_byte( cinfo, 'E' ); /* EXIF signature */
-            p_jpeg_write_m_byte( cinfo, 'x' );
-            p_jpeg_write_m_byte( cinfo, 'i' );
-            p_jpeg_write_m_byte( cinfo, 'f' );
-            p_jpeg_write_m_byte( cinfo, '\0' );
-            p_jpeg_write_m_byte( cinfo, '\0' );
+            p_jpeg_write_m_header(cinfo, JPEG_APP0 + 1, nMarkerSize);
+            p_jpeg_write_m_byte(cinfo, 'E');  // EXIF signature.
+            p_jpeg_write_m_byte(cinfo, 'x');
+            p_jpeg_write_m_byte(cinfo, 'i');
+            p_jpeg_write_m_byte(cinfo, 'f');
+            p_jpeg_write_m_byte(cinfo, '\0');
+            p_jpeg_write_m_byte(cinfo, '\0');
 
             // TIFF little-endian signature.
-            p_jpeg_write_m_byte( cinfo, TIFF_LITTLEENDIAN & 0xff );
-            p_jpeg_write_m_byte( cinfo, TIFF_LITTLEENDIAN >> 8 );
-            p_jpeg_write_m_byte( cinfo, TIFF_VERSION );
-            p_jpeg_write_m_byte( cinfo, 0x00 );
+            p_jpeg_write_m_byte(cinfo, TIFF_LITTLEENDIAN & 0xff);
+            p_jpeg_write_m_byte(cinfo, TIFF_LITTLEENDIAN >> 8);
+            p_jpeg_write_m_byte(cinfo, TIFF_VERSION);
+            p_jpeg_write_m_byte(cinfo, 0x00);
 
-            p_jpeg_write_m_byte( cinfo, 8 ); /* Offset of IFD0 */
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 8);  // Offset of IFD0.
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, 0 ); /* Number of entries of IFD0 */
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 0);  // Number of entries of IFD0.
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, 14 ); /* Offset of IFD1 */
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 14); // Offset of IFD1.
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, 5 ); /* Number of entries of IFD1 */
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 5);  // Number of entries of IFD1.
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, JPEG_TIFF_IMAGEWIDTH & 0xff );
-            p_jpeg_write_m_byte( cinfo, (JPEG_TIFF_IMAGEWIDTH >> 8) & 0xff );
+            p_jpeg_write_m_byte(cinfo, JPEG_TIFF_IMAGEWIDTH & 0xff);
+            p_jpeg_write_m_byte(cinfo, (JPEG_TIFF_IMAGEWIDTH >> 8) & 0xff);
 
-            p_jpeg_write_m_byte( cinfo, TIFF_LONG );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, TIFF_LONG);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, 1 ); /* 1 value */
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 1);  // 1 value.
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, nOvrWidth & 0xff );
-            p_jpeg_write_m_byte( cinfo, nOvrWidth >> 8 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, nOvrWidth & 0xff);
+            p_jpeg_write_m_byte(cinfo, nOvrWidth >> 8);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, JPEG_TIFF_IMAGEHEIGHT & 0xff );
-            p_jpeg_write_m_byte( cinfo, JPEG_TIFF_IMAGEHEIGHT >> 8 );
+            p_jpeg_write_m_byte(cinfo, JPEG_TIFF_IMAGEHEIGHT & 0xff);
+            p_jpeg_write_m_byte(cinfo, JPEG_TIFF_IMAGEHEIGHT >> 8);
 
-            p_jpeg_write_m_byte( cinfo, TIFF_LONG );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, TIFF_LONG);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, 1 ); /* 1 value */
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 1);  // 1 value.
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, nOvrHeight & 0xff );
-            p_jpeg_write_m_byte( cinfo, nOvrHeight >> 8 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, nOvrHeight & 0xff);
+            p_jpeg_write_m_byte(cinfo, nOvrHeight >> 8);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, JPEG_TIFF_COMPRESSION & 0xff );
-            p_jpeg_write_m_byte( cinfo, JPEG_TIFF_COMPRESSION >> 8 );
+            p_jpeg_write_m_byte(cinfo, JPEG_TIFF_COMPRESSION & 0xff);
+            p_jpeg_write_m_byte(cinfo, JPEG_TIFF_COMPRESSION >> 8);
 
-            p_jpeg_write_m_byte( cinfo, TIFF_SHORT );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, TIFF_SHORT);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, 1 ); /* 1 value */
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 1); // 1 value.
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, 6 ); /* JPEG compression */
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 6); // JPEG compression.
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, JPEG_EXIF_JPEGIFOFSET & 0xff );
-            p_jpeg_write_m_byte( cinfo, JPEG_EXIF_JPEGIFOFSET >> 8 );
+            p_jpeg_write_m_byte(cinfo, JPEG_EXIF_JPEGIFOFSET & 0xff);
+            p_jpeg_write_m_byte(cinfo, JPEG_EXIF_JPEGIFOFSET >> 8);
 
-            p_jpeg_write_m_byte( cinfo, TIFF_LONG );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, TIFF_LONG);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, 1 ); /* 1 value */
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 1); // 1 value.
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
             const unsigned int nJPEGIfOffset = 16 + 5 * 12 + 4;
-            p_jpeg_write_m_byte( cinfo, nJPEGIfOffset & 0xff );
-            p_jpeg_write_m_byte( cinfo, nJPEGIfOffset >> 8 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, nJPEGIfOffset & 0xff);
+            p_jpeg_write_m_byte(cinfo, nJPEGIfOffset >> 8);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, JPEG_EXIF_JPEGIFBYTECOUNT & 0xff );
-            p_jpeg_write_m_byte( cinfo, JPEG_EXIF_JPEGIFBYTECOUNT >> 8 );
+            p_jpeg_write_m_byte(cinfo, JPEG_EXIF_JPEGIFBYTECOUNT & 0xff);
+            p_jpeg_write_m_byte(cinfo, JPEG_EXIF_JPEGIFBYTECOUNT >> 8);
 
-            p_jpeg_write_m_byte( cinfo, TIFF_LONG );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, TIFF_LONG);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            p_jpeg_write_m_byte( cinfo, 1 ); /* 1 value */
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 1); // 1 value.
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
             p_jpeg_write_m_byte(
-                cinfo, static_cast<GByte>(nJPEGIfByteCount & 0xff) );
+                cinfo, static_cast<GByte>(nJPEGIfByteCount & 0xff));
             p_jpeg_write_m_byte(
-                cinfo, static_cast<GByte>(nJPEGIfByteCount >> 8) );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+                cinfo, static_cast<GByte>(nJPEGIfByteCount >> 8));
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
             // Offset of IFD2 == 0 ==> end of TIFF directory.
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
-            p_jpeg_write_m_byte( cinfo, 0 );
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
+            p_jpeg_write_m_byte(cinfo, 0);
 
-            for( int i=0; i < static_cast<int>(nJPEGIfByteCount); i++ )
-                p_jpeg_write_m_byte( cinfo, pabyOvr[i] );
+            for( int i = 0; i < static_cast<int>(nJPEGIfByteCount); i++ )
+                p_jpeg_write_m_byte(cinfo, pabyOvr[i]);
         }
         else
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Cannot write EXIF thumbnail. "
-                      "The size of the EXIF segment exceeds 65536 bytes" );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Cannot write EXIF thumbnail. "
+                     "The size of the EXIF segment exceeds 65536 bytes");
         }
         CPLFree(pabyOvr);
     }
 }
 
-#endif // !defined(JPGDataset)
+#endif  // !defined(JPGDataset)
 
 /************************************************************************/
 /*                              CreateCopy()                            */
 /************************************************************************/
 
 GDALDataset *
-JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+JPGDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS,
                         int bStrict, char ** papszOptions,
-                        GDALProgressFunc pfnProgress, void * pProgressData )
+                        GDALProgressFunc pfnProgress, void *pProgressData )
 
 {
-    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    if( !pfnProgress(0.0, NULL, pProgressData) )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Some some rudimentary checks                                    */
-/* -------------------------------------------------------------------- */
+    // Some some rudimentary checks.
     const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 && nBands != 3 && nBands != 4 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "JPEG driver doesn't support %d bands.  Must be 1 (grey), "
-                  "3 (RGB) or 4 bands.\n", nBands );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "JPEG driver doesn't support %d bands.  Must be 1 (grey), "
+                 "3 (RGB) or 4 bands.\n", nBands);
 
         return NULL;
     }
@@ -3341,36 +3011,28 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if (nBands == 1 &&
         poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
     {
-        CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_NotSupported,
-                  "JPEG driver ignores color table. "
-                  "The source raster band will be considered as grey level.\n"
-                  "Consider using color table expansion "
-                  "(-expand option in gdal_translate)" );
+        CPLError(bStrict ? CE_Failure : CE_Warning, CPLE_NotSupported,
+                 "JPEG driver ignores color table. "
+                 "The source raster band will be considered as grey level.\n"
+                 "Consider using color table expansion "
+                 "(-expand option in gdal_translate)");
         if (bStrict)
             return NULL;
     }
 
     VSILFILE *fpImage = NULL;
     GDALJPEGErrorStruct sErrorStruct;
-    sErrorStruct.bNonFatalErrorEncountered = FALSE;
-
-    if (setjmp(sErrorStruct.setjmp_buffer))
-    {
-        if( fpImage )
-            VSIFCloseL( fpImage );
-        return NULL;
-    }
-
+    sErrorStruct.bNonFatalErrorEncountered = false;
     GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
 
 #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
     if( eDT != GDT_Byte && eDT != GDT_UInt16 )
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
-                  "JPEG driver doesn't support data type %s. "
-                  "Only eight and twelve bit bands supported (Mk1 libjpeg).\n",
-                  GDALGetDataTypeName(
-                      poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
+        CPLError(bStrict ? CE_Failure : CE_Warning, CPLE_NotSupported,
+                 "JPEG driver doesn't support data type %s. "
+                 "Only eight and twelve bit bands supported (Mk1 libjpeg).\n",
+                 GDALGetDataTypeName(
+                     poSrcDS->GetRasterBand(1)->GetRasterDataType()));
 
         if( bStrict )
             return NULL;
@@ -3379,80 +3041,121 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( eDT == GDT_UInt16 || eDT == GDT_Int16 )
     {
 #if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
-        return JPEGDataset12CreateCopy( pszFilename, poSrcDS,
-                                        bStrict, papszOptions,
-                                        pfnProgress, pProgressData );
+        return JPEGDataset12CreateCopy(pszFilename, poSrcDS,
+                                       bStrict, papszOptions,
+                                       pfnProgress, pProgressData);
 #else
         eDT = GDT_UInt16;
-#endif
+#endif  // defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
     }
     else
     {
         eDT = GDT_Byte;
     }
 
-#else
+#else  // !(defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12))
     if( eDT != GDT_Byte )
     {
-        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
-                  "JPEG driver doesn't support data type %s. "
-                  "Only eight bit byte bands supported.\n",
-                  GDALGetDataTypeName(
-                      poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
+        CPLError(bStrict ? CE_Failure : CE_Warning, CPLE_NotSupported,
+                 "JPEG driver doesn't support data type %s. "
+                 "Only eight bit byte bands supported.\n",
+                 GDALGetDataTypeName(
+                     poSrcDS->GetRasterBand(1)->GetRasterDataType()));
 
         if( bStrict )
             return NULL;
     }
 
-    eDT = GDT_Byte; // force to 8bit.
-#endif
+    eDT = GDT_Byte;  // force to 8bit.
+#endif  // !(defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12))
 
-/* -------------------------------------------------------------------- */
-/*      What options has the user selected?                             */
-/* -------------------------------------------------------------------- */
+    // What options has the caller selected?
     int nQuality = 75;
     if( CSLFetchNameValue(papszOptions, "QUALITY") != NULL )
     {
         nQuality = atoi(CSLFetchNameValue(papszOptions, "QUALITY"));
         if( nQuality < 10 || nQuality > 100 )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg,
-                      "QUALITY=%s is not a legal value in the range 10-100.",
-                      CSLFetchNameValue(papszOptions, "QUALITY") );
+            CPLError(CE_Failure, CPLE_IllegalArg,
+                     "QUALITY=%s is not a legal value in the range 10-100.",
+                     CSLFetchNameValue(papszOptions, "QUALITY"));
             return NULL;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the dataset.                                             */
-/* -------------------------------------------------------------------- */
-    fpImage = VSIFOpenL( pszFilename, "wb" );
+    // Create the dataset.
+    fpImage = VSIFOpenL(pszFilename, "wb");
     if( fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unable to create jpeg file %s.\n",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Unable to create jpeg file %s.\n",
+                 pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize JPG access to the file.                              */
-/* -------------------------------------------------------------------- */
-
     struct jpeg_compress_struct sCInfo;
     struct jpeg_error_mgr sJErr;
-    sCInfo.err = jpeg_std_error( &sJErr );
+    GByte *pabyScanline;
+
+    // Does the source have a mask?  If so, we will append it to the
+    // jpeg file after the imagery.
+    const int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
+    const bool bAppendMask =
+        !(nMaskFlags & GMF_ALL_VALID) &&
+        (nBands == 1 || (nMaskFlags & GMF_PER_DATASET)) &&
+        CPLFetchBool(papszOptions, "INTERNAL_MASK", true);
+
+    // Nasty trick to avoid variable clobbering issues with setjmp/longjmp.
+    return CreateCopyStage2(pszFilename, poSrcDS, papszOptions,
+                            pfnProgress, pProgressData,
+                            fpImage, eDT, nQuality,
+                            bAppendMask,
+                            sErrorStruct, sCInfo, sJErr, pabyScanline);
+}
+
+GDALDataset *
+JPGDataset::CreateCopyStage2( const char *pszFilename, GDALDataset *poSrcDS,
+                              char **papszOptions,
+                              GDALProgressFunc pfnProgress,
+                              void * pProgressData,
+                              VSILFILE *fpImage,
+                              GDALDataType eDT,
+                              int nQuality,
+                              bool bAppendMask,
+                              GDALJPEGErrorStruct &sErrorStruct,
+                              struct jpeg_compress_struct &sCInfo,
+                              struct jpeg_error_mgr &sJErr,
+                              GByte *&pabyScanline)
+
+{
+    if (setjmp(sErrorStruct.setjmp_buffer))
+    {
+        if( fpImage )
+            VSIFCloseL(fpImage);
+        return NULL;
+    }
+
+    // Initialize JPG access to the file.
+    sCInfo.err = jpeg_std_error(&sJErr);
     sJErr.error_exit = JPGDataset::ErrorExit;
     sErrorStruct.p_previous_emit_message = sJErr.emit_message;
     sJErr.emit_message = JPGDataset::EmitMessage;
-    sCInfo.client_data = reinterpret_cast<void *>( &(sErrorStruct) );
+    sCInfo.client_data = &sErrorStruct;
 
-    jpeg_create_compress( &sCInfo );
+    jpeg_create_compress(&sCInfo);
+    if (setjmp(sErrorStruct.setjmp_buffer))
+    {
+        if( fpImage )
+            VSIFCloseL(fpImage);
+        jpeg_destroy_compress(&sCInfo);
+        return NULL;
+    }
 
-    jpeg_vsiio_dest( &sCInfo, fpImage );
+    jpeg_vsiio_dest(&sCInfo, fpImage);
 
     const int nXSize = poSrcDS->GetRasterXSize();
     const int nYSize = poSrcDS->GetRasterYSize();
+    const int nBands = poSrcDS->GetRasterCount();
     sCInfo.image_width = nXSize;
     sCInfo.image_height = nYSize;
     sCInfo.input_components = nBands;
@@ -3464,15 +3167,16 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     else
         sCInfo.in_color_space = JCS_UNKNOWN;
 
-    jpeg_set_defaults( &sCInfo );
+    jpeg_set_defaults(&sCInfo);
 
-    /* This is to address bug related in ticket #1795 */
+    // This is to address bug related in ticket #1795.
     if (CPLGetConfigOption("JPEGMEM", NULL) == NULL)
     {
         // If the user doesn't provide a value for JPEGMEM, we want to be sure
         // that at least 500 MB will be used before creating the temporary file.
+        const long nMinMemory = 500 * 1024 * 1024;
         sCInfo.mem->max_memory_to_use =
-                MAX(sCInfo.mem->max_memory_to_use, 500 * 1024 * 1024);
+            std::max(sCInfo.mem->max_memory_to_use, nMinMemory);
     }
 
     if( eDT == GDT_UInt16 )
@@ -3484,12 +3188,12 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         sCInfo.data_precision = 8;
     }
 
-    const char* pszVal = CSLFetchNameValue(papszOptions, "ARITHMETIC");
+    const char *pszVal = CSLFetchNameValue(papszOptions, "ARITHMETIC");
     if( pszVal )
         sCInfo.arith_code = CPLTestBool(pszVal);
 
-    /* Optimized Huffman coding. Supposedly slower according to libjpeg doc */
-    /* but no longer significant with today computer standards */
+    // Optimized Huffman coding. Supposedly slower according to libjpeg doc
+    // but no longer significant with today computer standards.
     if( !sCInfo.arith_code )
         sCInfo.optimize_coding = TRUE;
 
@@ -3511,7 +3215,7 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     else
 #endif
 
-    /* Mostly for debugging purposes */
+    // Mostly for debugging purposes.
     if( nBands == 3 && CPLTestBool(CPLGetConfigOption("JPEG_WRITE_RGB", "NO")) )
     {
         jpeg_set_colorspace(&sCInfo, JCS_RGB);
@@ -3525,78 +3229,67 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     const GDALDataType eWorkDT = eDT;
 #endif
 
-    jpeg_set_quality( &sCInfo, nQuality, TRUE );
+    jpeg_set_quality(&sCInfo, nQuality, TRUE);
 
-    const bool bProgressive
-        = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "PROGRESSIVE", FALSE ));
+    const bool bProgressive = CPLFetchBool(papszOptions, "PROGRESSIVE", false);
     if( bProgressive )
-        jpeg_simple_progression( &sCInfo );
+        jpeg_simple_progression(&sCInfo);
 
-    jpeg_start_compress( &sCInfo, TRUE );
+    jpeg_start_compress(&sCInfo, TRUE);
 
-    JPGAddEXIFOverview( eWorkDT, poSrcDS, papszOptions,
-                        &sCInfo,
-                        (my_jpeg_write_m_header)jpeg_write_m_header,
-                        (my_jpeg_write_m_byte)jpeg_write_m_byte,
-                        CreateCopy );
+    JPGAddEXIFOverview(eWorkDT, poSrcDS, papszOptions,
+                       &sCInfo,
+                       (my_jpeg_write_m_header)jpeg_write_m_header,
+                       (my_jpeg_write_m_byte)jpeg_write_m_byte,
+                       CreateCopy);
 
-/* -------------------------------------------------------------------- */
-/*      Add comment if available                                        */
-/* -------------------------------------------------------------------- */
+    // Add comment if available.
     const char *pszComment = CSLFetchNameValue(papszOptions, "COMMENT");
     if( pszComment )
-        jpeg_write_marker( &sCInfo, JPEG_COM,
-                           reinterpret_cast<const JOCTET*>(pszComment),
-                           static_cast<unsigned int>(strlen(pszComment) ) );
+        jpeg_write_marker(&sCInfo, JPEG_COM,
+                          reinterpret_cast<const JOCTET *>(pszComment),
+                          static_cast<unsigned int>(strlen(pszComment)));
 
-/* -------------------------------------------------------------------- */
-/*      Save ICC profile if available                                   */
-/* -------------------------------------------------------------------- */
+    // Save ICC profile if available.
     const char *pszICCProfile =
         CSLFetchNameValue(papszOptions, "SOURCE_ICC_PROFILE");
     if (pszICCProfile == NULL)
         pszICCProfile =
-            poSrcDS->GetMetadataItem( "SOURCE_ICC_PROFILE", "COLOR_PROFILE" );
+            poSrcDS->GetMetadataItem("SOURCE_ICC_PROFILE", "COLOR_PROFILE");
 
     if (pszICCProfile != NULL)
-        JPGAddICCProfile( &sCInfo, pszICCProfile,
-                          (my_jpeg_write_m_header)jpeg_write_m_header,
-                          (my_jpeg_write_m_byte)jpeg_write_m_byte );
-
-/* -------------------------------------------------------------------- */
-/*      Does the source have a mask?  If so, we will append it to the   */
-/*      jpeg file after the imagery.                                    */
-/* -------------------------------------------------------------------- */
-    const int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
-    const bool bAppendMask = !(nMaskFlags & GMF_ALL_VALID)
-        && (nBands == 1 || (nMaskFlags & GMF_PER_DATASET))
-        && CPL_TO_BOOL(
-            CSLFetchBoolean( papszOptions, "INTERNAL_MASK", TRUE ) );
-
-/* -------------------------------------------------------------------- */
-/*      Loop over image, copying image data.                            */
-/* -------------------------------------------------------------------- */
+        JPGAddICCProfile(&sCInfo, pszICCProfile,
+                         (my_jpeg_write_m_header)jpeg_write_m_header,
+                         (my_jpeg_write_m_byte)jpeg_write_m_byte);
+
+    // Loop over image, copying image data.
+    const int nWorkDTSize = GDALGetDataTypeSizeBytes(eWorkDT);
+    pabyScanline =
+        static_cast<GByte *>(CPLMalloc(nBands * nXSize * nWorkDTSize));
+
+    if (setjmp(sErrorStruct.setjmp_buffer))
+    {
+        VSIFCloseL(fpImage);
+        CPLFree(pabyScanline);
+        jpeg_destroy_compress(&sCInfo);
+        return NULL;
+    }
+
     CPLErr eErr = CE_None;
-    const int nWorkDTSize = GDALGetDataTypeSize(eWorkDT) / 8;
     bool bClipWarn = false;
-    GByte *pabyScanline
-        = static_cast<GByte *>( CPLMalloc( nBands * nXSize * nWorkDTSize ) );
-
     for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
     {
-        eErr = poSrcDS->RasterIO( GF_Read, 0, iLine, nXSize, 1,
-                                  pabyScanline, nXSize, 1, eWorkDT,
-                                  nBands, NULL,
-                                  nBands * nWorkDTSize,
-                                  nBands * nXSize * nWorkDTSize,
-                                  nWorkDTSize, NULL );
+        eErr = poSrcDS->RasterIO(
+            GF_Read, 0, iLine, nXSize, 1, pabyScanline, nXSize, 1, eWorkDT,
+            nBands, NULL, nBands * nWorkDTSize, nBands * nXSize * nWorkDTSize,
+            nWorkDTSize, NULL);
 
-        // clamp 16bit values to 12bit.
+        // Clamp 16bit values to 12bit.
         if( nWorkDTSize == 2 )
         {
-            GUInt16 *panScanline = reinterpret_cast<GUInt16 *>( pabyScanline );
+            GUInt16 *panScanline = reinterpret_cast<GUInt16 *>(pabyScanline);
 
-            for( int iPixel = 0; iPixel < nXSize*nBands; iPixel++ )
+            for( int iPixel = 0; iPixel < nXSize * nBands; iPixel++ )
             {
                 if( panScanline[iPixel] > 4095 )
                 {
@@ -3604,88 +3297,82 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                     if( !bClipWarn )
                     {
                         bClipWarn = true;
-                        CPLError( CE_Warning, CPLE_AppDefined,
-                                  "One or more pixels clipped to fit "
-                                  "12bit domain for jpeg output." );
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "One or more pixels clipped to fit "
+                                 "12bit domain for jpeg output.");
                     }
                 }
             }
         }
 
-        JSAMPLE  *ppSamples = reinterpret_cast<JSAMPLE *>( pabyScanline );
+        JSAMPLE *ppSamples = reinterpret_cast<JSAMPLE *>(pabyScanline);
 
         if( eErr == CE_None )
-            jpeg_write_scanlines( &sCInfo, &ppSamples, 1 );
+            jpeg_write_scanlines(&sCInfo, &ppSamples, 1);
 
         if( eErr == CE_None &&
             !pfnProgress(
-                (iLine + 1) / ( (bAppendMask ? 2 : 1) *
-                                static_cast<double>(nYSize) ),
-                NULL, pProgressData ) )
+                (iLine + 1) / ((bAppendMask ? 2 : 1) *
+                               static_cast<double>(nYSize)),
+                NULL, pProgressData) )
         {
             eErr = CE_Failure;
-            CPLError( CE_Failure, CPLE_UserInterrupt,
-                      "User terminated CreateCopy()" );
+            CPLError(CE_Failure, CPLE_UserInterrupt,
+                     "User terminated CreateCopy()");
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Cleanup and close.                                              */
-/* -------------------------------------------------------------------- */
-    CPLFree( pabyScanline );
-
+    // Cleanup and close.
     if( eErr == CE_None )
-        jpeg_finish_compress( &sCInfo );
-    jpeg_destroy_compress( &sCInfo );
+        jpeg_finish_compress(&sCInfo);
+    jpeg_destroy_compress(&sCInfo);
 
-    VSIFCloseL( fpImage );
+    // Free scanline and image after jpeg_finish_compress since this could
+    // cause a longjmp to occur.
+    CPLFree(pabyScanline);
+
+    VSIFCloseL(fpImage);
 
     if( eErr != CE_None )
     {
-        VSIUnlink( pszFilename );
+        VSIUnlink(pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Append masks to the jpeg file if necessary.                     */
-/* -------------------------------------------------------------------- */
+    // Append masks to the jpeg file if necessary.
     int nCloneFlags = GCIF_PAM_DEFAULT;
     if( bAppendMask )
     {
-        CPLDebug( "JPEG", "Appending Mask Bitmap" );
+        CPLDebug("JPEG", "Appending Mask Bitmap");
 
-        void* pScaledData =
-            GDALCreateScaledProgress( 0.5, 1, pfnProgress, pProgressData );
+        void *pScaledData =
+            GDALCreateScaledProgress(0.5, 1, pfnProgress, pProgressData);
         eErr = JPGAppendMask(
             pszFilename, poSrcDS->GetRasterBand(1)->GetMaskBand(),
             GDALScaledProgress, pScaledData );
-        GDALDestroyScaledProgress( pScaledData );
+        GDALDestroyScaledProgress(pScaledData);
         nCloneFlags &= (~GCIF_MASK);
 
         if( eErr != CE_None )
         {
-            VSIUnlink( pszFilename );
+            VSIUnlink(pszFilename);
             return NULL;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we need a world file?                                        */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
+    // Do we need a world file?
+    if( CPLFetchBool(papszOptions, "WORLDFILE", false) )
     {
-        double adfGeoTransform[6] = { 0.0 };
+        double adfGeoTransform[6] = {};
 
-        poSrcDS->GetGeoTransform( adfGeoTransform );
-        GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
+        poSrcDS->GetGeoTransform(adfGeoTransform);
+        GDALWriteWorldFile(pszFilename, "wld", adfGeoTransform);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Re-open dataset, and copy any auxiliary pam information.         */
-/* -------------------------------------------------------------------- */
+    // Re-open dataset, and copy any auxiliary pam information.
 
-    /* If writing to stdout, we can't reopen it, so return */
-    /* a fake dataset to make the caller happy */
+    // If writing to stdout, we can't reopen it, so return
+    // a fake dataset to make the caller happy.
     if( CPLTestBool(CPLGetConfigOption("GDAL_OPEN_AFTER_COPY", "YES")) )
     {
         CPLPushErrorHandler(CPLQuietErrorHandler);
@@ -3695,26 +3382,25 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         sArgs.fpLin = NULL;
         sArgs.papszSiblingFiles = NULL;
         sArgs.nScaleFactor = 1;
-        sArgs.bDoPAMInitialize = TRUE;
-        sArgs.bUseInternalOverviews = TRUE;
+        sArgs.bDoPAMInitialize = true;
+        sArgs.bUseInternalOverviews = true;
 
-        // TODO(schwehr): Dynamic cast?
-        JPGDataset *poDS = (JPGDataset*) Open( &sArgs );
+        JPGDataset *poDS = dynamic_cast<JPGDataset *>(Open(&sArgs));
         CPLPopErrorHandler();
         if( poDS )
         {
-            poDS->CloneInfo( poSrcDS, nCloneFlags );
+            poDS->CloneInfo(poSrcDS, nCloneFlags);
             return poDS;
         }
 
         CPLErrorReset();
     }
 
-    JPGDataset* poJPG_DS = new JPGDataset();
+    JPGDataset *poJPG_DS = new JPGDataset();
     poJPG_DS->nRasterXSize = nXSize;
     poJPG_DS->nRasterYSize = nYSize;
-    for(int i=0;i<nBands;i++)
-        poJPG_DS->SetBand( i+1, JPGCreateBand( poJPG_DS, i+1) );
+    for(int i = 0; i < nBands; i++)
+        poJPG_DS->SetBand(i + 1, JPGCreateBand(poJPG_DS, i + 1));
     return poJPG_DS;
 }
 
@@ -3724,18 +3410,7 @@ JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
 #if !defined(JPGDataset)
 
-class GDALJPGDriver: public GDALDriver
-{
-    public:
-        GDALJPGDriver() {}
-
-        char      **GetMetadata( const char * pszDomain = "" );
-        const char *GetMetadataItem( const char * pszName,
-                                      const char * pszDomain = "" );
-
-};
-
-char** GDALJPGDriver::GetMetadata( const char * pszDomain )
+char **GDALJPGDriver::GetMetadata( const char *pszDomain )
 {
     GetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST);
     return GDALDriver::GetMetadata(pszDomain);
@@ -3743,43 +3418,43 @@ char** GDALJPGDriver::GetMetadata( const char * pszDomain )
 
 static void GDALJPEGIsArithmeticCodingAvailableErrorExit(j_common_ptr cinfo)
 {
-    jmp_buf* p_setjmp_buffer = static_cast<jmp_buf *>( cinfo->client_data );
-    /* Return control to the setjmp point */
+    jmp_buf *p_setjmp_buffer = static_cast<jmp_buf *>(cinfo->client_data);
+    // Return control to the setjmp point.
     longjmp(*p_setjmp_buffer, 1);
 }
 
-/* Runtime check if arithmetic coding is available */
+// Runtime check if arithmetic coding is available.
 static bool GDALJPEGIsArithmeticCodingAvailable()
 {
     struct jpeg_compress_struct sCInfo;
     struct jpeg_error_mgr sJErr;
-    jmp_buf     setjmp_buffer;
+    jmp_buf setjmp_buffer;
     if (setjmp(setjmp_buffer))
     {
-        jpeg_destroy_compress( &sCInfo );
+        jpeg_destroy_compress(&sCInfo);
         return false;
     }
-    sCInfo.err = jpeg_std_error( &sJErr );
+    sCInfo.err = jpeg_std_error(&sJErr);
     sJErr.error_exit = GDALJPEGIsArithmeticCodingAvailableErrorExit;
-    sCInfo.client_data = reinterpret_cast<void *>( &(setjmp_buffer) );
-    jpeg_create_compress( &sCInfo );
-    /* Hopefully nothing will be written */
+    sCInfo.client_data = &setjmp_buffer;
+    jpeg_create_compress(&sCInfo);
+    // Hopefully nothing will be written.
     jpeg_stdio_dest(&sCInfo, stderr);
     sCInfo.image_width = 1;
     sCInfo.image_height = 1;
     sCInfo.input_components = 1;
     sCInfo.in_color_space = JCS_UNKNOWN;
-    jpeg_set_defaults( &sCInfo );
+    jpeg_set_defaults(&sCInfo);
     sCInfo.arith_code = TRUE;
-    jpeg_start_compress( &sCInfo, FALSE );
-    jpeg_abort_compress( &sCInfo );
-    jpeg_destroy_compress( &sCInfo );
+    jpeg_start_compress(&sCInfo, FALSE);
+    jpeg_abort_compress(&sCInfo);
+    jpeg_destroy_compress(&sCInfo);
 
     return true;
 }
 
-const char *GDALJPGDriver::GetMetadataItem( const char * pszName,
-                                            const char * pszDomain )
+const char *GDALJPGDriver::GetMetadataItem( const char *pszName,
+                                            const char *pszDomain )
 {
     if( pszName != NULL && EQUAL(pszName, GDAL_DMD_CREATIONOPTIONLIST) &&
         (pszDomain == NULL || EQUAL(pszDomain, "")) &&
@@ -3811,7 +3486,7 @@ const char *GDALJPGDriver::GetMetadataItem( const char * pszName,
 "   <Option name='THUMBNAIL_WIDTH' type='int' description='Forced thumbnail width' min='32' max='512'/>\n"
 "   <Option name='THUMBNAIL_HEIGHT' type='int' description='Forced thumbnail height' min='32' max='512'/>\n"
 "</CreationOptionList>\n";
-        SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, osCreationOptions );
+        SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST, osCreationOptions);
     }
     return GDALDriver::GetMetadataItem(pszName, pszDomain);
 }
@@ -3819,27 +3494,27 @@ const char *GDALJPGDriver::GetMetadataItem( const char * pszName,
 void GDALRegister_JPEG()
 
 {
-    if( GDALGetDriverByName( "JPEG" ) != NULL )
+    if( GDALGetDriverByName("JPEG") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALJPGDriver();
 
-    poDriver->SetDescription( "JPEG" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "JPEG JFIF" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_jpeg.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jpg" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "jpg jpeg" );
-    poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jpeg" );
+    poDriver->SetDescription("JPEG");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "JPEG JFIF");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_jpeg.html");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jpg");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "jpg jpeg");
+    poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/jpeg");
 
 #if defined(JPEG_LIB_MK1_OR_12BIT) || defined(JPEG_DUAL_MODE_8_12)
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte UInt16" );
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte UInt16");
 #else
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Byte");
 #endif
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
 
-    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+    poDriver->SetMetadataItem(GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>\n"
 "   <Option name='USE_INTERNAL_OVERVIEWS' type='boolean' description='whether to use implicit internal overviews' default='YES'/>\n"
 "</OpenOptionList>\n");
@@ -3848,6 +3523,6 @@ void GDALRegister_JPEG()
     poDriver->pfnOpen = JPGDatasetCommon::Open;
     poDriver->pfnCreateCopy = JPGDataset::CreateCopy;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
 #endif
diff --git a/frmts/jpeg/jpgdataset.h b/frmts/jpeg/jpgdataset.h
new file mode 100644
index 0000000..6bfe5f5
--- /dev/null
+++ b/frmts/jpeg/jpgdataset.h
@@ -0,0 +1,379 @@
+/******************************************************************************
+ * $Id: jpgdataset.cpp 37340 2017-02-11 18:28:02Z goatbar
+ *
+ * Project:  JPEG JFIF Driver
+ * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Frank Warmerdam
+ * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Portions Copyright (c) Her majesty the Queen in right of Canada as
+ * represented by the Minister of National Defence, 2006.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#undef ENABLE_LIBJPEG_NO_RETURN
+
+#include "cpl_port.h"
+
+// TODO(schwehr): Run IWYU.
+#include <cerrno>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <setjmp.h>
+
+#include <algorithm>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+CPL_C_START
+#ifdef LIBJPEG_12_PATH
+#  include LIBJPEG_12_PATH
+#else
+#  include "jpeglib.h"
+#endif
+CPL_C_END
+#include "memdataset.h"
+#include "vsidataio.h"
+
+// TIFF header.
+typedef struct
+{
+    GUInt16 tiff_magic;    // Magic number (defines byte order).
+    GUInt16 tiff_version;  // TIFF version number.
+    GUInt32 tiff_diroff;   // byte offset to first directory.
+} TIFFHeader;
+
+// Ok to use setjmp().
+#ifdef _MSC_VER
+#  pragma warning(disable:4611)
+#endif
+
+typedef struct
+{
+    const char *pszFilename;
+    VSILFILE *fpLin;
+    char **papszSiblingFiles;
+    int nScaleFactor;
+    bool bDoPAMInitialize;
+    bool bUseInternalOverviews;
+} JPGDatasetOpenArgs;
+
+#if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
+GDALDataset *JPEGDataset12Open(JPGDatasetOpenArgs *psArgs);
+GDALDataset *JPEGDataset12CreateCopy( const char *pszFilename,
+                                      GDALDataset *poSrcDS,
+                                      int bStrict, char **papszOptions,
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData );
+#endif
+
+// Do we want to do special processing suitable for when JSAMPLE is a
+// 16bit value?
+#if defined(JPEG_LIB_MK1)
+#  define JPEG_LIB_MK1_OR_12BIT 1
+#elif BITS_IN_JSAMPLE == 12
+#  define JPEG_LIB_MK1_OR_12BIT 1
+#endif
+
+class JPGDatasetCommon;
+GDALRasterBand *JPGCreateBand(JPGDatasetCommon *poDS, int nBand);
+
+typedef void (*my_jpeg_write_m_header)(void *cinfo, int marker,
+                                       unsigned int datalen);
+typedef void (*my_jpeg_write_m_byte)(void *cinfo, int val);
+
+CPLErr JPGAppendMask( const char *pszJPGFilename, GDALRasterBand *poMask,
+                      GDALProgressFunc pfnProgress, void *pProgressData );
+void   JPGAddEXIFOverview( GDALDataType eWorkDT,
+                           GDALDataset *poSrcDS, char** papszOptions,
+                           void *cinfo,
+                           my_jpeg_write_m_header p_jpeg_write_m_header,
+                           my_jpeg_write_m_byte p_jpeg_write_m_byte,
+                           GDALDataset *(pCreateCopy)(
+                               const char *, GDALDataset *,
+                               int, char **,
+                               GDALProgressFunc pfnProgress,
+                               void *pProgressData ) );
+void JPGAddICCProfile( void *pInfo,
+                       const char *pszICCProfile,
+                       my_jpeg_write_m_header p_jpeg_write_m_header,
+                       my_jpeg_write_m_byte p_jpeg_write_m_byte);
+
+typedef struct GDALJPEGErrorStruct
+{
+    jmp_buf     setjmp_buffer;
+    bool        bNonFatalErrorEncountered;
+    void      (*p_previous_emit_message)(j_common_ptr cinfo, int msg_level);
+    GDALJPEGErrorStruct() :
+        bNonFatalErrorEncountered(false),
+        p_previous_emit_message(NULL)
+    {
+        memset(&setjmp_buffer, 0, sizeof(setjmp_buffer));
+    }
+} GDALJPEGErrorStruct;
+
+/************************************************************************/
+/* ==================================================================== */
+/*                         JPGDatasetCommon                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class JPGRasterBand;
+class JPGMaskBand;
+
+class JPGDatasetCommon : public GDALPamDataset
+{
+  protected:
+    friend class JPGRasterBand;
+    friend class JPGMaskBand;
+
+    int           nScaleFactor;
+    bool          bHasInitInternalOverviews;
+    int           nInternalOverviewsCurrent;
+    int           nInternalOverviewsToFree;
+    GDALDataset **papoInternalOverviews;
+    void          InitInternalOverviews();
+    GDALDataset  *InitEXIFOverview();
+
+    char   *pszProjection;
+    bool   bGeoTransformValid;
+    double adfGeoTransform[6];
+    int    nGCPCount;
+    GDAL_GCP *pasGCPList;
+
+    VSILFILE   *fpImage;
+    GUIntBig nSubfileOffset;
+
+    int    nLoadedScanline;
+    GByte  *pabyScanline;
+
+    bool   bHasReadEXIFMetadata;
+    bool   bHasReadXMPMetadata;
+    bool   bHasReadICCMetadata;
+    char   **papszMetadata;
+    char   **papszSubDatasets;
+    bool   bigendian;
+    int    nExifOffset;
+    int    nInterOffset;
+    int    nGPSOffset;
+    bool   bSwabflag;
+    int    nTiffDirStart;
+    int    nTIFFHEADER;
+    bool   bHasDoneJpegCreateDecompress;
+    bool   bHasDoneJpegStartDecompress;
+
+    virtual CPLErr LoadScanline(int) = 0;
+    virtual CPLErr Restart() = 0;
+
+    virtual int GetDataPrecision() = 0;
+    virtual int GetOutColorSpace() = 0;
+
+    bool   EXIFInit(VSILFILE *);
+    void   ReadICCProfile();
+
+    void   CheckForMask();
+    void   DecompressMask();
+
+    void   ReadEXIFMetadata();
+    void   ReadXMPMetadata();
+
+    bool   bHasCheckedForMask;
+    JPGMaskBand *poMaskBand;
+    GByte  *pabyBitMask;
+    bool   bMaskLSBOrder;
+
+    GByte  *pabyCMask;
+    int    nCMaskSize;
+
+    // Color space exposed by GDAL.  Not necessarily the in_color_space nor
+    // the out_color_space of JPEG library.
+    J_COLOR_SPACE eGDALColorSpace;
+
+    bool   bIsSubfile;
+    bool   bHasTriedLoadWorldFileOrTab;
+    void   LoadWorldFileOrTab();
+    CPLString osWldFilename;
+
+    virtual int         CloseDependentDatasets() override;
+
+    virtual CPLErr IBuildOverviews( const char *, int, int *, int, int *,
+                                    GDALProgressFunc, void * ) override;
+
+  public:
+                 JPGDatasetCommon();
+    virtual ~JPGDatasetCommon();
+
+    virtual CPLErr      IRasterIO( GDALRWFlag, int, int, int, int,
+                                   void *, int, int, GDALDataType,
+                                   int, int *,
+                                   GSpacing nPixelSpace, GSpacing nLineSpace,
+                                   GSpacing nBandSpace,
+                                   GDALRasterIOExtraArg* psExtraArg ) override;
+
+    virtual CPLErr GetGeoTransform( double * ) override;
+
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
+
+    virtual char  **GetMetadataDomainList() override;
+    virtual char  **GetMetadata( const char *pszDomain = "" ) override;
+    virtual const char *GetMetadataItem( const char *pszName,
+                                         const char *pszDomain = "" ) override;
+
+    virtual char **GetFileList(void) override;
+
+    virtual void FlushCache(void) override;
+
+    static int          Identify( GDALOpenInfo * );
+    static GDALDataset *Open( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              JPGDataset                              */
+/* ==================================================================== */
+/************************************************************************/
+
+class JPGDataset : public JPGDatasetCommon
+{
+    GDALJPEGErrorStruct sErrorStruct;
+
+    bool ErrorOutOnNonFatalError();
+
+    static void EmitMessage(j_common_ptr cinfo, int msg_level);
+
+    struct jpeg_decompress_struct sDInfo;
+    struct jpeg_error_mgr sJErr;
+
+    virtual CPLErr LoadScanline(int) override;
+    virtual CPLErr Restart() override;
+    virtual int GetDataPrecision() override { return sDInfo.data_precision; }
+    virtual int GetOutColorSpace() override { return sDInfo.out_color_space; }
+
+    int    nQLevel;
+#if !defined(JPGDataset)
+    void   LoadDefaultTables(int);
+#endif
+    void   SetScaleNumAndDenom();
+
+    static GDALDataset *OpenStage2( JPGDatasetOpenArgs *psArgs,
+                                    JPGDataset *&poDS );
+
+  public:
+                 JPGDataset();
+    virtual ~JPGDataset();
+
+    static GDALDataset *Open( JPGDatasetOpenArgs *psArgs );
+    static GDALDataset *CreateCopy( const char *pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char ** papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void *pProgressData );
+    static GDALDataset *CreateCopyStage2(
+        const char *pszFilename, GDALDataset *poSrcDS, char **papszOptions,
+        GDALProgressFunc pfnProgress, void *pProgressData, VSILFILE *fpImage,
+        GDALDataType eDT, int nQuality, bool bAppendMask,
+        GDALJPEGErrorStruct &sErrorStruct, struct jpeg_compress_struct &sCInfo,
+        struct jpeg_error_mgr &sJErr, GByte *&pabyScanline);
+    static void ErrorExit(j_common_ptr cinfo);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            JPGRasterBand                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class JPGRasterBand : public GDALPamRasterBand
+{
+    friend class JPGDatasetCommon;
+
+    // We have to keep a pointer to the JPGDataset that this JPGRasterBand
+    // belongs to. In some case, we may have this->poGDS != this->poDS
+    // For example for a JPGRasterBand that is set to a NITFDataset.
+    // In other words, this->poDS doesn't necessary point to a JPGDataset
+    // See ticket #1807.
+    JPGDatasetCommon *poGDS;
+
+  public:
+    JPGRasterBand(JPGDatasetCommon *, int);
+    virtual ~JPGRasterBand() {}
+
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+
+    virtual GDALRasterBand *GetMaskBand() override;
+    virtual int             GetMaskFlags() override;
+
+    virtual GDALRasterBand *GetOverview(int i) override;
+    virtual int             GetOverviewCount() override;
+};
+
+#if !defined(JPGDataset)
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             JPGMaskBand                              */
+/* ==================================================================== */
+/************************************************************************/
+
+class JPGMaskBand : public GDALRasterBand
+{
+  protected:
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+
+  public:
+    explicit JPGMaskBand( JPGDataset *poDS );
+    virtual ~JPGMaskBand() {}
+};
+
+/************************************************************************/
+/*                         GDALRegister_JPEG()                          */
+/************************************************************************/
+
+class GDALJPGDriver: public GDALDriver
+{
+  public:
+    GDALJPGDriver() {}
+
+    char      **GetMetadata( const char *pszDomain = "" ) override;
+    const char *GetMetadataItem( const char *pszName,
+                                 const char *pszDomain = "" ) override;
+};
+
+#endif  // !defined(JPGDataset)
diff --git a/frmts/jpeg/libjpeg/jcmarker.c b/frmts/jpeg/libjpeg/jcmarker.c
index 6c86aa1..38c4d60 100644
--- a/frmts/jpeg/libjpeg/jcmarker.c
+++ b/frmts/jpeg/libjpeg/jcmarker.c
@@ -196,7 +196,10 @@ emit_dht (j_compress_ptr cinfo, int l_index, boolean is_ac)
   }
 
   if (htbl == NULL)
+  {
     ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, l_index);
+    return;
+  }
   
   if (! htbl->sent_table) {
     emit_marker(cinfo, M_DHT);
diff --git a/frmts/jpeg/libjpeg/jcmaster.c b/frmts/jpeg/libjpeg/jcmaster.c
index aab4020..aa9c272 100644
--- a/frmts/jpeg/libjpeg/jcmaster.c
+++ b/frmts/jpeg/libjpeg/jcmaster.c
@@ -446,6 +446,7 @@ prepare_for_pass (j_compress_ptr cinfo)
     master->pass_number++;
     /*FALLTHROUGH*/
 #endif
+    /*-fallthrough*/
   case output_pass:
     /* Do a data-output pass. */
     /* We need not repeat per-scan setup if prior optimization pass did it. */
diff --git a/frmts/jpeg/libjpeg/jdcoefct.c b/frmts/jpeg/libjpeg/jdcoefct.c
index 01fe5a5..0b04fc2 100644
--- a/frmts/jpeg/libjpeg/jdcoefct.c
+++ b/frmts/jpeg/libjpeg/jdcoefct.c
@@ -655,7 +655,9 @@ decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
 	DC1 = DC2; DC2 = DC3;
 	DC4 = DC5; DC5 = DC6;
 	DC7 = DC8; DC8 = DC9;
-	buffer_ptr++, prev_block_row++, next_block_row++;
+	buffer_ptr++;
+    prev_block_row++;
+    next_block_row++;
 	output_col += compptr->DCT_scaled_size;
       }
       output_ptr += compptr->DCT_scaled_size;
diff --git a/frmts/jpeg/libjpeg/jdphuff.c b/frmts/jpeg/libjpeg/jdphuff.c
index cf6fc20..95d9cb6 100644
--- a/frmts/jpeg/libjpeg/jdphuff.c
+++ b/frmts/jpeg/libjpeg/jdphuff.c
@@ -198,9 +198,11 @@ start_pass_phuff_decoder (j_decompress_ptr cinfo)
  * On some machines, a shift and add will be faster than a table lookup.
  */
 
+#define NEG_1 ((unsigned)-1)
+
 #ifdef AVOID_TABLES
 
-#define HUFF_EXTEND(x,s)  ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
+#define HUFF_EXTEND(x,s)  ((x) < (1<<((s)-1)) ? (x) + (((NEG_1)<<(s)) + 1) : (x))
 
 #else
 
@@ -490,7 +492,7 @@ decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy;
   int Se = cinfo->Se;
   int p1 = 1 << cinfo->Al;	/* 1 in the bit position being coded */
-  int m1 = (-1) << cinfo->Al;	/* -1 in the bit position being coded */
+  int m1 = (NEG_1) << cinfo->Al;	/* -1 in the bit position being coded */
   register int s, k, r;
   unsigned int EOBRUN;
   JBLOCKROW block;
diff --git a/frmts/jpeg/libjpeg/jmemmgr.c b/frmts/jpeg/libjpeg/jmemmgr.c
index 410098a..83ae1ad 100644
--- a/frmts/jpeg/libjpeg/jmemmgr.c
+++ b/frmts/jpeg/libjpeg/jmemmgr.c
@@ -1064,6 +1064,7 @@ jinit_memory_mgr (j_common_ptr cinfo)
   if (mem == NULL) {
     jpeg_mem_term(cinfo);	/* system-dependent cleanup */
     ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
+    return;
   }
 
   /* OK, fill in the method pointers */
diff --git a/frmts/jpeg/vsidataio.cpp b/frmts/jpeg/vsidataio.cpp
index cca3f62..65a93ab 100644
--- a/frmts/jpeg/vsidataio.cpp
+++ b/frmts/jpeg/vsidataio.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vsidataio.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement JPEG read/write io indirection through VSI.
@@ -28,143 +27,151 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "vsidataio.h"
 
-CPL_CVSID("$Id: vsidataio.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <cstddef>
+
+CPL_CVSID("$Id: vsidataio.cpp 37478 2017-02-26 03:05:44Z goatbar $");
 
 CPL_C_START
 #include "jerror.h"
 CPL_C_END
 
+// Expanded data source object for stdio input.
 
-/* Expanded data source object for stdio input */
-
-typedef struct {
-  struct jpeg_source_mgr pub;	/* public fields */
+typedef struct
+{
+    struct jpeg_source_mgr pub;  // public fields.
 
-  VSILFILE * infile;		/* source stream */
-  JOCTET * buffer;		/* start of buffer */
-  boolean start_of_file;	/* have we gotten any data yet? */
+    VSILFILE *infile;       // Source stream.
+    JOCTET *buffer;         // Start of buffer.
+    boolean start_of_file;  // Have we gotten any data yet?
 } my_source_mgr;
 
-typedef my_source_mgr * my_src_ptr;
+typedef my_source_mgr *my_src_ptr;
 
-static const size_t INPUT_BUF_SIZE = 4096; /* choose an efficiently fread'able size */
+// Choose an efficiently fread'able size.
+static const size_t INPUT_BUF_SIZE = 4096;
 
-/*
- * Initialize source --- called by jpeg_read_header
- * before any data is actually read.
- */
+// Initialize source --- called by jpeg_read_header
+// before any data is actually read.
 
 METHODDEF(void)
-init_source (j_decompress_ptr cinfo)
+init_source(j_decompress_ptr cinfo)
 {
-  my_src_ptr src = (my_src_ptr) cinfo->src;
+    my_src_ptr src = (my_src_ptr)cinfo->src;
 
-  /* We reset the empty-input-file flag for each image,
-   * but we don't clear the input buffer.
-   * This is correct behavior for reading a series of images from one source.
-   */
-  src->start_of_file = TRUE;
+    // We reset the empty-input-file flag for each image,
+    // but we don't clear the input buffer.
+    // This is correct behavior for reading a series of images from one source.
+    src->start_of_file = TRUE;
 }
 
-
-/*
- * Fill the input buffer --- called whenever buffer is emptied.
- *
- * In typical applications, this should read fresh data into the buffer
- * (ignoring the current state of next_input_byte & bytes_in_buffer),
- * reset the pointer & count to the start of the buffer, and return TRUE
- * indicating that the buffer has been reloaded.  It is not necessary to
- * fill the buffer entirely, only to obtain at least one more byte.
- *
- * There is no such thing as an EOF return.  If the end of the file has been
- * reached, the routine has a choice of ERREXIT() or inserting fake data into
- * the buffer.  In most cases, generating a warning message and inserting a
- * fake EOI marker is the best course of action --- this will allow the
- * decompressor to output however much of the image is there.  However,
- * the resulting error message is misleading if the real problem is an empty
- * input file, so we handle that case specially.
- *
- * In applications that need to be able to suspend compression due to input
- * not being available yet, a FALSE return indicates that no more data can be
- * obtained right now, but more may be forthcoming later.  In this situation,
- * the decompressor will return to its caller (with an indication of the
- * number of scanlines it has read, if any).  The application should resume
- * decompression after it has loaded more data into the input buffer.  Note
- * that there are substantial restrictions on the use of suspension --- see
- * the documentation.
- *
- * When suspending, the decompressor will back up to a convenient restart point
- * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
- * indicate where the restart point will be if the current call returns FALSE.
- * Data beyond this point must be rescanned after resumption, so move it to
- * the front of the buffer rather than discarding it.
- */
+// Fill the input buffer --- called whenever buffer is emptied.
+//
+// In typical applications, this should read fresh data into the buffer
+// (ignoring the current state of next_input_byte & bytes_in_buffer),
+// reset the pointer & count to the start of the buffer, and return TRUE
+// indicating that the buffer has been reloaded.  It is not necessary to
+// fill the buffer entirely, only to obtain at least one more byte.
+//
+// There is no such thing as an EOF return.  If the end of the file has been
+// reached, the routine has a choice of ERREXIT() or inserting fake data into
+// the buffer.  In most cases, generating a warning message and inserting a
+// fake EOI marker is the best course of action --- this will allow the
+// decompressor to output however much of the image is there.  However,
+// the resulting error message is misleading if the real problem is an empty
+// input file, so we handle that case specially.
+//
+// In applications that need to be able to suspend compression due to input
+// not being available yet, a FALSE return indicates that no more data can be
+// obtained right now, but more may be forthcoming later.  In this situation,
+// the decompressor will return to its caller (with an indication of the
+// number of scanlines it has read, if any).  The application should resume
+// decompression after it has loaded more data into the input buffer.  Note
+// that there are substantial restrictions on the use of suspension --- see
+// the documentation.
+//
+// When suspending, the decompressor will back up to a convenient restart point
+// (typically the start of the current MCU). next_input_byte & bytes_in_buffer
+// indicate where the restart point will be if the current call returns FALSE.
+// Data beyond this point must be rescanned after resumption, so move it to
+// the front of the buffer rather than discarding it.
 
 METHODDEF(boolean)
-fill_input_buffer (j_decompress_ptr cinfo)
+fill_input_buffer(j_decompress_ptr cinfo)
 {
-  my_src_ptr src = (my_src_ptr) cinfo->src;
-  size_t nbytes = VSIFReadL(src->buffer, 1, INPUT_BUF_SIZE, src->infile);
-
-  if (nbytes <= 0) {
-    if (src->start_of_file)	/* Treat empty input file as fatal error */
-      ERREXIT(cinfo, JERR_INPUT_EMPTY);
-    WARNMS(cinfo, JWRN_JPEG_EOF);
-    /* Insert a fake EOI marker */
-    src->buffer[0] = (JOCTET) 0xFF;
-    src->buffer[1] = (JOCTET) JPEG_EOI;
-    nbytes = 2;
-  }
-
-  src->pub.next_input_byte = src->buffer;
-  src->pub.bytes_in_buffer = nbytes;
-  src->start_of_file = FALSE;
-
-  return TRUE;
+    my_src_ptr src = (my_src_ptr)cinfo->src;
+    size_t nbytes = VSIFReadL(src->buffer, 1, INPUT_BUF_SIZE, src->infile);
+
+    if(nbytes == 0)
+    {
+        if(src->start_of_file)
+        {
+            // Treat empty input file as fatal error.
+            cinfo->err->msg_code = JERR_INPUT_EMPTY;
+            cinfo->err->error_exit((j_common_ptr)(cinfo));
+        }
+        WARNMS(cinfo, JWRN_JPEG_EOF);
+        // Insert a fake EOI marker.
+        src->buffer[0] = (JOCTET)0xFF;
+        src->buffer[1] = (JOCTET)JPEG_EOI;
+        nbytes = 2;
+    }
+
+    src->pub.next_input_byte = src->buffer;
+    src->pub.bytes_in_buffer = nbytes;
+    src->start_of_file = FALSE;
+
+    return TRUE;
 }
 
-/*
- * The Intel IPP performance libraries do not necessarily read the
- * entire contents of the buffer with each pass, so each re-fill
- * copies the remaining buffer bytes to the front of the buffer,
- * then fills up the rest with new data.
- */
+// The Intel IPP performance libraries do not necessarily read the
+// entire contents of the buffer with each pass, so each re-fill
+// copies the remaining buffer bytes to the front of the buffer,
+// then fills up the rest with new data.
 #ifdef IPPJ_HUFF
 METHODDEF(boolean)
-fill_input_buffer_ipp (j_decompress_ptr cinfo)
+fill_input_buffer_ipp(j_decompress_ptr cinfo)
 {
-  my_src_ptr src = (my_src_ptr) cinfo->src;
-  size_t bytes_left = src->pub.bytes_in_buffer;
-  size_t bytes_to_read = INPUT_BUF_SIZE - bytes_left;
-
-  if(src->start_of_file || cinfo->progressive_mode)
-  {
-    return fill_input_buffer(cinfo);
-  }
-
-  memmove(src->buffer,src->pub.next_input_byte,bytes_left);
+    my_src_ptr src = (my_src_ptr)cinfo->src;
+    size_t bytes_left = src->pub.bytes_in_buffer;
+    size_t bytes_to_read = INPUT_BUF_SIZE - bytes_left;
 
-  size_t nbytes
-      = VSIFReadL(src->buffer + bytes_left, 1, bytes_to_read, src->infile);
-
-  if(nbytes <= 0)
-  {
-    if(src->start_of_file)
+    if(src->start_of_file || cinfo->progressive_mode)
     {
-      /* Treat empty input file as fatal error */
-      ERREXIT(cinfo, JERR_INPUT_EMPTY);
+        return fill_input_buffer(cinfo);
     }
 
-    if(src->pub.bytes_in_buffer == 0 && cinfo->unread_marker == 0)
-    {
-      WARNMS(cinfo, JWRN_JPEG_EOF);
+    memmove(src->buffer, src->pub.next_input_byte, bytes_left);
+
+    size_t nbytes =
+        VSIFReadL(src->buffer + bytes_left, 1, bytes_to_read, src->infile);
 
-      /* Insert a fake EOI marker */
-      src->buffer[0] = (JOCTET)0xFF;
-      src->buffer[1] = (JOCTET)JPEG_EOI;
-      nbytes = 2;
+    if(nbytes <= 0)
+    {
+        if(src->start_of_file)
+        {
+            // Treat empty input file as fatal error.
+            ERREXIT(cinfo, JERR_INPUT_EMPTY);
+        }
+
+        if(src->pub.bytes_in_buffer == 0 && cinfo->unread_marker == 0)
+        {
+            WARNMS(cinfo, JWRN_JPEG_EOF);
+
+            // Insert a fake EOI marker.
+            src->buffer[0] = (JOCTET)0xFF;
+            src->buffer[1] = (JOCTET)JPEG_EOI;
+            nbytes = 2;
+        }
+
+        src->pub.next_input_byte = src->buffer;
+        src->pub.bytes_in_buffer = bytes_left + nbytes;
+        src->start_of_file = FALSE;
+
+        return TRUE;
     }
 
     src->pub.next_input_byte = src->buffer;
@@ -172,254 +179,236 @@ fill_input_buffer_ipp (j_decompress_ptr cinfo)
     src->start_of_file = FALSE;
 
     return TRUE;
-  }
-
-  src->pub.next_input_byte = src->buffer;
-  src->pub.bytes_in_buffer = bytes_left + nbytes;
-  src->start_of_file = FALSE;
-
-  return TRUE;
 }
-#endif /* IPPJ_HUFF */
-
-/*
- * Skip data --- used to skip over a potentially large amount of
- * uninteresting data (such as an APPn marker).
- *
- * Writers of suspendable-input applications must note that skip_input_data
- * is not granted the right to give a suspension return.  If the skip extends
- * beyond the data currently in the buffer, the buffer can be marked empty so
- * that the next read will cause a fill_input_buffer call that can suspend.
- * Arranging for additional bytes to be discarded before reloading the input
- * buffer is the application writer's problem.
- */
+#endif  // IPPJ_HUFF
+
+// Skip data --- used to skip over a potentially large amount of
+// uninteresting data (such as an APPn marker).
+//
+// Writers of suspendable-input applications must note that skip_input_data
+// is not granted the right to give a suspension return.  If the skip extends
+// beyond the data currently in the buffer, the buffer can be marked empty so
+// that the next read will cause a fill_input_buffer call that can suspend.
+// Arranging for additional bytes to be discarded before reloading the input
+// buffer is the application writer's problem.
 
 METHODDEF(void)
-skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+skip_input_data(j_decompress_ptr cinfo, long num_bytes)
 {
-  my_src_ptr src = (my_src_ptr) cinfo->src;
-
-  /* Just a dumb implementation for now.  Could use fseek() except
-   * it doesn't work on pipes.  Not clear that being smart is worth
-   * any trouble anyway --- large skips are infrequent.
-   */
-  if (num_bytes > 0) {
-    while (num_bytes > (long) src->pub.bytes_in_buffer) {
-      num_bytes -= (long) src->pub.bytes_in_buffer;
-      (void) fill_input_buffer(cinfo);
-      /* note we assume that fill_input_buffer will never return FALSE,
-       * so suspension need not be handled.
-       */
+    my_src_ptr src = (my_src_ptr)cinfo->src;
+
+    // Just a dumb implementation for now.  Could use fseek() except
+    // it doesn't work on pipes.  Not clear that being smart is worth
+    // any trouble anyway --- large skips are infrequent.
+    if(num_bytes > 0)
+    {
+        while(num_bytes > (long)src->pub.bytes_in_buffer)
+        {
+            num_bytes -= (long)src->pub.bytes_in_buffer;
+            (void)fill_input_buffer(cinfo);
+            // note we assume that fill_input_buffer will never return FALSE,
+            // so suspension need not be handled.
+        }
+        src->pub.next_input_byte += (size_t)num_bytes;
+        src->pub.bytes_in_buffer -= (size_t)num_bytes;
     }
-    src->pub.next_input_byte += (size_t) num_bytes;
-    src->pub.bytes_in_buffer -= (size_t) num_bytes;
-  }
 }
 
-/*
- * An additional method that can be provided by data source modules is the
- * resync_to_restart method for error recovery in the presence of RST markers.
- * For the moment, this source module just uses the default resync method
- * provided by the JPEG library.  That method assumes that no backtracking
- * is possible.
- */
-
-/*
- * Terminate source --- called by jpeg_finish_decompress
- * after all data has been read.  Often a no-op.
- *
- * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
- * application must deal with any cleanup that should happen even
- * for error exit.
- */
+// An additional method that can be provided by data source modules is the
+// resync_to_restart method for error recovery in the presence of RST markers.
+// For the moment, this source module just uses the default resync method
+// provided by the JPEG library.  That method assumes that no backtracking
+// is possible.
+
+// Terminate source --- called by jpeg_finish_decompress
+// after all data has been read.  Often a no-op.
+//
+// NB://not* called by jpeg_abort or jpeg_destroy; surrounding
+// application must deal with any cleanup that should happen even
+// for error exit.
 
 METHODDEF(void)
-term_source (CPL_UNUSED j_decompress_ptr cinfo)
+term_source(CPL_UNUSED j_decompress_ptr cinfo)
 {
-  /* no work necessary here */
+    // No work necessary here.
 }
 
-/*
- * Prepare for input from a stdio stream.
- * The caller must have already opened the stream, and is responsible
- * for closing it after finishing decompression.
- */
+// Prepare for input from a stdio stream.
+// The caller must have already opened the stream, and is responsible
+// for closing it after finishing decompression.
 
-void jpeg_vsiio_src (j_decompress_ptr cinfo, VSILFILE * infile)
+void jpeg_vsiio_src(j_decompress_ptr cinfo, VSILFILE *infile)
 {
-  my_src_ptr src;
-
-  /* The source object and input buffer are made permanent so that a series
-   * of JPEG images can be read from the same file by calling jpeg_stdio_src
-   * only before the first one.  (If we discarded the buffer at the end of
-   * one image, we'd likely lose the start of the next one.)
-   * This makes it unsafe to use this manager and a different source
-   * manager serially with the same JPEG object.  Caveat programmer.
-   */
-  if (cinfo->src == NULL) {	/* first time for this JPEG object? */
-    cinfo->src = (struct jpeg_source_mgr *)
-      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
-				  sizeof(my_source_mgr));
-    src = (my_src_ptr) cinfo->src;
-    src->buffer = (JOCTET *)
-      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
-				  INPUT_BUF_SIZE * sizeof(JOCTET));
-  }
-
-  src = (my_src_ptr) cinfo->src;
-  src->pub.init_source = init_source;
+    my_src_ptr src;
+
+    // The source object and input buffer are made permanent so that a series
+    // of JPEG images can be read from the same file by calling jpeg_stdio_src
+    // only before the first one.  (If we discarded the buffer at the end of
+    // one image, we'd likely lose the start of the next one.)
+    // This makes it unsafe to use this manager and a different source
+    // manager serially with the same JPEG object.  Caveat programmer.
+    if(cinfo->src == NULL)
+    {
+        // First time for this JPEG object?
+        cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)(
+            (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr));
+        src = (my_src_ptr)cinfo->src;
+        src->buffer = (JOCTET *)(*cinfo->mem->alloc_small)(
+            (j_common_ptr)cinfo, JPOOL_PERMANENT,
+            INPUT_BUF_SIZE * sizeof(JOCTET));
+    }
+
+    src = (my_src_ptr)cinfo->src;
+    src->pub.init_source = init_source;
 #ifdef IPPJ_HUFF
-  src->pub.fill_input_buffer = fill_input_buffer_ipp;
+    src->pub.fill_input_buffer = fill_input_buffer_ipp;
 #else
-  src->pub.fill_input_buffer = fill_input_buffer;
+    src->pub.fill_input_buffer = fill_input_buffer;
 #endif
-  src->pub.skip_input_data = skip_input_data;
-  src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
-  src->pub.term_source = term_source;
-  src->infile = infile;
-  src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
-  src->pub.next_input_byte = NULL; /* until buffer loaded */
+    src->pub.skip_input_data = skip_input_data;
+    src->pub.resync_to_restart = jpeg_resync_to_restart;  // Use default method.
+    src->pub.term_source = term_source;
+    src->infile = infile;
+    src->pub.bytes_in_buffer = 0;     // Forces fill_input_buffer on first read.
+    src->pub.next_input_byte = NULL;  // Until buffer loaded.
 }
 
-
 /* ==================================================================== */
 /*      The rest was derived from jdatadst.c                            */
 /* ==================================================================== */
 
-/* Expanded data destination object for stdio output */
+// Expanded data destination object for stdio output.
 
-typedef struct {
-  struct jpeg_destination_mgr pub; /* public fields */
+typedef struct
+{
+    struct jpeg_destination_mgr pub;  // Public fields.
 
-  VSILFILE * outfile;		/* target stream */
-  JOCTET * buffer;		/* start of buffer */
+    VSILFILE *outfile;  // Target stream.
+    JOCTET *buffer;     // Start of buffer.
 } my_destination_mgr;
 
-typedef my_destination_mgr * my_dest_ptr;
+typedef my_destination_mgr *my_dest_ptr;
 
-/* choose an efficiently fwrite'able size */
+// choose an efficiently fwrite'able size.
 static const size_t OUTPUT_BUF_SIZE = 4096;
 
-/*
- * Initialize destination --- called by jpeg_start_compress
- * before any data is actually written.
- */
+// Initialize destination --- called by jpeg_start_compress
+// before any data is actually written.
 
 METHODDEF(void)
-init_destination (j_compress_ptr cinfo)
+init_destination(j_compress_ptr cinfo)
 {
-  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+    my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
 
-  /* Allocate the output buffer --- it will be released when done with image */
-  dest->buffer = (JOCTET *)
-      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
-				  OUTPUT_BUF_SIZE * sizeof(JOCTET));
+    // Allocate the output buffer --- it will be released when done with image.
+    dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small)(
+        (j_common_ptr)cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof(JOCTET));
 
-  dest->pub.next_output_byte = dest->buffer;
-  dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+    dest->pub.next_output_byte = dest->buffer;
+    dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
 }
 
-
-/*
- * Empty the output buffer --- called whenever buffer fills up.
- *
- * In typical applications, this should write the entire output buffer
- * (ignoring the current state of next_output_byte & free_in_buffer),
- * reset the pointer & count to the start of the buffer, and return TRUE
- * indicating that the buffer has been dumped.
- *
- * In applications that need to be able to suspend compression due to output
- * overrun, a FALSE return indicates that the buffer cannot be emptied now.
- * In this situation, the compressor will return to its caller (possibly with
- * an indication that it has not accepted all the supplied scanlines).  The
- * application should resume compression after it has made more room in the
- * output buffer.  Note that there are substantial restrictions on the use of
- * suspension --- see the documentation.
- *
- * When suspending, the compressor will back up to a convenient restart point
- * (typically the start of the current MCU). next_output_byte & free_in_buffer
- * indicate where the restart point will be if the current call returns FALSE.
- * Data beyond this point will be regenerated after resumption, so do not
- * write it out when emptying the buffer externally.
- */
+// Empty the output buffer --- called whenever buffer fills up.
+//
+// In typical applications, this should write the entire output buffer
+// (ignoring the current state of next_output_byte & free_in_buffer),
+// reset the pointer & count to the start of the buffer, and return TRUE
+// indicating that the buffer has been dumped.
+//
+// In applications that need to be able to suspend compression due to output
+// overrun, a FALSE return indicates that the buffer cannot be emptied now.
+// In this situation, the compressor will return to its caller (possibly with
+// an indication that it has not accepted all the supplied scanlines).  The
+// application should resume compression after it has made more room in the
+// output buffer.  Note that there are substantial restrictions on the use of
+// suspension --- see the documentation.
+//
+// When suspending, the compressor will back up to a convenient restart point
+// (typically the start of the current MCU). next_output_byte & free_in_buffer
+// indicate where the restart point will be if the current call returns FALSE.
+// Data beyond this point will be regenerated after resumption, so do not
+// write it out when emptying the buffer externally.
 
 METHODDEF(boolean)
-empty_output_buffer (j_compress_ptr cinfo)
+empty_output_buffer(j_compress_ptr cinfo)
 {
-  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
-  size_t bytes_to_write = OUTPUT_BUF_SIZE;
+    my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
+    size_t bytes_to_write = OUTPUT_BUF_SIZE;
 
 #ifdef IPPJ_HUFF
-/*
- * The Intel IPP performance libraries do not necessarily fill up
- * the whole output buffer with each compression pass, so we only
- * want to write out the parts of the buffer that are full.
- */
-  if(! cinfo->progressive_mode) {
-    bytes_to_write -= dest->pub.free_in_buffer;
-  }
+    // The Intel IPP performance libraries do not necessarily fill up
+    // the whole output buffer with each compression pass, so we only
+    // want to write out the parts of the buffer that are full.
+    if(!cinfo->progressive_mode)
+    {
+        bytes_to_write -= dest->pub.free_in_buffer;
+    }
 #endif
 
-  if (VSIFWriteL(dest->buffer, 1, bytes_to_write, dest->outfile) != bytes_to_write)
-    ERREXIT(cinfo, JERR_FILE_WRITE);
+    if(VSIFWriteL(dest->buffer, 1, bytes_to_write, dest->outfile) !=
+       bytes_to_write)
+    {
+        cinfo->err->msg_code = JERR_FILE_WRITE;
+        cinfo->err->error_exit((j_common_ptr)(cinfo));
+    }
 
-  dest->pub.next_output_byte = dest->buffer;
-  dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+    dest->pub.next_output_byte = dest->buffer;
+    dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
 
-  return TRUE;
+    return TRUE;
 }
 
-/*
- * Terminate destination --- called by jpeg_finish_compress
- * after all data has been written.  Usually needs to flush buffer.
- *
- * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
- * application must deal with any cleanup that should happen even
- * for error exit.
- */
-
+// Terminate destination --- called by jpeg_finish_compress
+// after all data has been written.  Usually needs to flush buffer.
+//
+// NB://not* called by jpeg_abort or jpeg_destroy; surrounding
+// application must deal with any cleanup that should happen even
+// for error exit.
 METHODDEF(void)
-term_destination (j_compress_ptr cinfo)
+term_destination(j_compress_ptr cinfo)
 {
-  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
-  size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
-
-  /* Write any data remaining in the buffer */
-  if (datacount > 0) {
-    if (VSIFWriteL(dest->buffer, 1, datacount, dest->outfile) != datacount)
-      ERREXIT(cinfo, JERR_FILE_WRITE);
-  }
-  if( VSIFFlushL(dest->outfile) != 0 )
-    ERREXIT(cinfo, JERR_FILE_WRITE);
-}
+    my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
+    size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
 
+    // Write any data remaining in the buffer.
+    if(datacount > 0)
+    {
+        if(VSIFWriteL(dest->buffer, 1, datacount, dest->outfile) != datacount)
+        {
+            cinfo->err->msg_code = JERR_FILE_WRITE;
+            cinfo->err->error_exit((j_common_ptr)(cinfo));
+        }
+    }
+    if( VSIFFlushL(dest->outfile) != 0 )
+    {
+        cinfo->err->msg_code = JERR_FILE_WRITE;
+        cinfo->err->error_exit((j_common_ptr)(cinfo));
+    }
+}
 
-/*
- * Prepare for output to a stdio stream.
- * The caller must have already opened the stream, and is responsible
- * for closing it after finishing compression.
- */
+// Prepare for output to a stdio stream.
+// The caller must have already opened the stream, and is responsible
+// for closing it after finishing compression.
 
-void
-jpeg_vsiio_dest (j_compress_ptr cinfo, VSILFILE * outfile)
+void jpeg_vsiio_dest(j_compress_ptr cinfo, VSILFILE *outfile)
 {
-  my_dest_ptr dest;
-
-  /* The destination object is made permanent so that multiple JPEG images
-   * can be written to the same file without re-executing jpeg_stdio_dest.
-   * This makes it dangerous to use this manager and a different destination
-   * manager serially with the same JPEG object, because their private object
-   * sizes may be different.  Caveat programmer.
-   */
-  if (cinfo->dest == NULL) {	/* first time for this JPEG object? */
-    cinfo->dest = (struct jpeg_destination_mgr *)
-      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
-				  sizeof(my_destination_mgr));
-  }
-
-  dest = (my_dest_ptr) cinfo->dest;
-  dest->pub.init_destination = init_destination;
-  dest->pub.empty_output_buffer = empty_output_buffer;
-  dest->pub.term_destination = term_destination;
-  dest->outfile = outfile;
+    my_dest_ptr dest;
+
+    // The destination object is made permanent so that multiple JPEG images
+    // can be written to the same file without re-executing jpeg_stdio_dest.
+    // This makes it dangerous to use this manager and a different destination
+    // manager serially with the same JPEG object, because their private object
+    // sizes may be different.  Caveat programmer.
+    if(cinfo->dest == NULL)
+    {
+        // First time for this JPEG object?
+        cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small)(
+            (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(my_destination_mgr));
+    }
+
+    dest = (my_dest_ptr)cinfo->dest;
+    dest->pub.init_destination = init_destination;
+    dest->pub.empty_output_buffer = empty_output_buffer;
+    dest->pub.term_destination = term_destination;
+    dest->outfile = outfile;
 }
diff --git a/frmts/jpeg2000/frmt_jpeg2000.html b/frmts/jpeg2000/frmt_jpeg2000.html
index a3398ca..9cd1104 100644
--- a/frmts/jpeg2000/frmt_jpeg2000.html
+++ b/frmts/jpeg2000/frmt_jpeg2000.html
@@ -13,6 +13,30 @@ This implementation based on JasPer software (see below).<p>
 Starting with GDAL 1.9.0, XMP metadata can be extracted from JPEG2000 files, and will be
 stored as XML raw content in the xml:XMP metadata domain.<p>
 
+<h2><a name="georeferencing">Georeferencing</a></h2>
+
+<p>
+Georeferencing information can come from different sources : internal (GeoJP2
+or GMLJP2 boxes), worldfile .j2w/.wld sidecar files, or PAM (Persitant Auxiliary metadata)
+.aux.xml sidecar files.
+By default, information is fetched in following order (first listed is the most
+prioritary): PAM, GeoJP2, GMLJP2, WORLDFILE.
+</p>
+<p>Starting with GDAL 2.2, the allowed sources
+and their priority order can be changed with the GDAL_GEOREF_SOURCES
+configuration option (or GEOREF_SOURCES open option) whose value is a
+comma-separated list of the following keywords :
+PAM, GEOJP2, GMLJP2, INTERNAL (shortcut for GEOJP2,GMLJP2), WORLDFILE, NONE.
+First mentioned sources are the most prioritary over the next ones. A non mentioned
+source will be ignored.
+</p>
+<p>
+For example setting it to "WORLDFILE,PAM,INTERNAL" will make a geotransformation
+matrix from a potential worldfile prioritary over PAM or internal JP2 boxes.
+Setting it to "PAM,WORLDFILE,GEOJP2" will use the mentioned sources and
+ignore GMLJP2 boxes.
+</p>
+
 <h2>Option Options</h2>
 
 (GDAL >= 2.0 )
@@ -21,6 +45,8 @@ The following open option is available:
 <ul>
 <li><p><b>1BIT_ALPHA_PROMOTION=YES/NO</b>: Whether a 1-bit alpha channel should be promoted to 8-bit.
 Defaults to YES.</li>
+<li><p><b>GEOREF_SOURCES=string</b>: (GDAL > 2.2) Define which georeferencing sources are
+allowed and their priority order. See <a href="#georeferencing"><i>Georeferencing</i></a> paragraph.</li>
 </ul>
 
 <h2>Creation Options</h2>
diff --git a/frmts/jpeg2000/jpeg2000_vsil_io.cpp b/frmts/jpeg2000/jpeg2000_vsil_io.cpp
index 74f1e64..9ac7f19 100644
--- a/frmts/jpeg2000/jpeg2000_vsil_io.cpp
+++ b/frmts/jpeg2000/jpeg2000_vsil_io.cpp
@@ -1,291 +1,289 @@
-/******************************************************************************
- * $Id: jpeg2000_vsil_io.cpp 33123 2016-01-23 18:59:28Z rouault $
- *
- * Project:  JPEG-2000
- * Purpose:  Return a stream for a VSIL file
- * Author:   Even Rouault, even dot rouault at mines dash paris dot org
- *
- ******************************************************************************/
-
-/* Following code is mostly derived from jas_stream.c, which is licensed */
-/* under the below terms */
- 
-/*
- * Copyright (c) 1999-2000 Image Power, Inc. and the University of
- *   British Columbia.
- * Copyright (c) 2001-2003 Michael David Adams.
- * All rights reserved.
- * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
- */
-
-/* __START_OF_JASPER_LICENSE__
- * 
- * JasPer License Version 2.0
- * 
- * Copyright (c) 2001-2006 Michael David Adams
- * Copyright (c) 1999-2000 Image Power, Inc.
- * Copyright (c) 1999-2000 The University of British Columbia
- * 
- * All rights reserved.
- * 
- * Permission is hereby granted, free of charge, to any person (the
- * "User") obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, and/or sell copies of the Software, and to permit
- * persons to whom the Software is furnished to do so, subject to the
- * following conditions:
- * 
- * 1.  The above copyright notices and this permission notice (which
- * includes the disclaimer below) shall be included in all copies or
- * substantial portions of the Software.
- * 
- * 2.  The name of a copyright holder shall not be used to endorse or
- * promote products derived from the Software without specific prior
- * written permission.
- * 
- * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
- * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
- * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
- * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
- * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
- * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
- * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
- * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
- * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
- * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
- * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
- * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
- * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
- * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
- * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
- * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
- * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
- * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
- * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
- * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
- * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
- * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
- * 
- * __END_OF_JASPER_LICENSE__
- */
-
-#include "jpeg2000_vsil_io.h"
-#include "cpl_vsi.h"
-
-CPL_CVSID("$Id: jpeg2000_vsil_io.cpp 33123 2016-01-23 18:59:28Z rouault $");
-
-/*
- * File descriptor file object.
- */
-typedef struct {
-	VSILFILE* fp;
-} jas_stream_VSIFL_t;
-
-/******************************************************************************\
-* File stream object.
-\******************************************************************************/
-
-static int JPEG2000_VSIL_read(jas_stream_obj_t *obj, char *buf, int cnt)
-{
-	jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
-	return static_cast<int>(VSIFReadL(buf, 1, cnt, fileobj->fp));
-}
-
-static int JPEG2000_VSIL_write(jas_stream_obj_t *obj, char *buf, int cnt)
-{
-	jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
-	return static_cast<int>(VSIFWriteL(buf, 1, cnt, fileobj->fp));
-}
-
-static long JPEG2000_VSIL_seek(jas_stream_obj_t *obj, long offset, int origin)
-{
-	jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
-    if (offset < 0 && origin == SEEK_CUR)
-    {
-        origin = SEEK_SET;
-        offset += VSIFTellL(fileobj->fp);
-    }
-    else if (offset < 0 && origin == SEEK_END)
-    {
-        origin = SEEK_SET;
-        VSIFSeekL(fileobj->fp, 0, SEEK_END);
-        offset += VSIFTellL(fileobj->fp);
-    }
-	VSIFSeekL(fileobj->fp, offset, origin);
-    return VSIFTellL(fileobj->fp);
-}
-
-static int JPEG2000_VSIL_close(jas_stream_obj_t *obj)
-{
-	jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
-        if( fileobj->fp != NULL )
-        {
-            VSIFCloseL(fileobj->fp);
-            fileobj->fp = NULL;
-        }
-	jas_free(fileobj);
-	return 0;
-}
-
-static const jas_stream_ops_t JPEG2000_VSIL_stream_fileops = {
-	JPEG2000_VSIL_read,
-	JPEG2000_VSIL_write,
-	JPEG2000_VSIL_seek,
-	JPEG2000_VSIL_close
-};
-
-/******************************************************************************\
-* Code for opening and closing streams.
-\******************************************************************************/
-
-static jas_stream_t *JPEG2000_VSIL_jas_stream_create()
-{
-	jas_stream_t *stream;
-
-	if (!(stream = (jas_stream_t*) jas_malloc(sizeof(jas_stream_t)))) {
-		return NULL;
-	}
-	stream->openmode_ = 0;
-	stream->bufmode_ = 0;
-	stream->flags_ = 0;
-	stream->bufbase_ = NULL;
-	stream->bufstart_ = NULL;
-	stream->bufsize_ = 0;
-	stream->ptr_ = NULL;
-	stream->cnt_ = 0;
-	stream->ops_ = NULL;
-	stream->obj_ = NULL;
-	stream->rwcnt_ = 0;
-	stream->rwlimit_ = -1;
-
-	return stream;
-}
-
-static void JPEG2000_VSIL_jas_stream_destroy(jas_stream_t *stream)
-{
-	/* If the memory for the buffer was allocated with malloc, free
-	this memory. */
-	if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) {
-		jas_free(stream->bufbase_);
-		stream->bufbase_ = NULL;
-	}
-	jas_free(stream);
-}
-
-
-/******************************************************************************\
-* Buffer initialization code.
-\******************************************************************************/
-
-static void JPEG2000_VSIL_jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
-  int bufsize)
-{
-	/* If this function is being called, the buffer should not have been
-	  initialized yet. */
-	assert(!stream->bufbase_);
-
-	if (bufmode != JAS_STREAM_UNBUF) {
-		/* The full- or line-buffered mode is being employed. */
-		if (!buf) {
-			/* The caller has not specified a buffer to employ, so allocate
-			  one. */
-			if ((stream->bufbase_ = (unsigned char*)jas_malloc(JAS_STREAM_BUFSIZE +
-			  JAS_STREAM_MAXPUTBACK))) {
-				stream->bufmode_ |= JAS_STREAM_FREEBUF;
-				stream->bufsize_ = JAS_STREAM_BUFSIZE;
-			} else {
-				/* The buffer allocation has failed.  Resort to unbuffered
-				  operation. */
-				stream->bufbase_ = stream->tinybuf_;
-				stream->bufsize_ = 1;
-			}
-		} else {
-			/* The caller has specified a buffer to employ. */
-			/* The buffer must be large enough to accommodate maximum
-			  putback. */
-			assert(bufsize > JAS_STREAM_MAXPUTBACK);
-			stream->bufbase_ = JAS_CAST(uchar *, buf);
-			stream->bufsize_ = bufsize - JAS_STREAM_MAXPUTBACK;
-		}
-	} else {
-		/* The unbuffered mode is being employed. */
-		/* A buffer should not have been supplied by the caller. */
-		assert(!buf);
-		/* Use a trivial one-character buffer. */
-		stream->bufbase_ = stream->tinybuf_;
-		stream->bufsize_ = 1;
-	}
-	stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK];
-	stream->ptr_ = stream->bufstart_;
-	stream->cnt_ = 0;
-	stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK;
-}
-
-static int JPEG2000_VSIL_jas_strtoopenmode(const char *s)
-{
-	int openmode = 0;
-	while (*s != '\0') {
-		switch (*s) {
-		case 'r':
-			openmode |= JAS_STREAM_READ;
-			break;
-		case 'w':
-			openmode |= JAS_STREAM_WRITE | JAS_STREAM_CREATE;
-			break;
-		case 'b':
-			openmode |= JAS_STREAM_BINARY;
-			break;
-		case 'a':
-			openmode |= JAS_STREAM_APPEND;
-			break;
-		case '+':
-			openmode |= JAS_STREAM_READ | JAS_STREAM_WRITE;
-			break;
-		default:
-			break;
-		}
-		++s;
-	}
-	return openmode;
-}
-
-jas_stream_t *JPEG2000_VSIL_fopen(const char *filename, const char *mode)
-{
-	jas_stream_t *stream;
-	jas_stream_VSIFL_t *obj;
-
-	/* Allocate a stream object. */
-	if (!(stream = JPEG2000_VSIL_jas_stream_create())) {
-		return NULL;
-	}
-
-	/* Parse the mode string. */
-	stream->openmode_ = JPEG2000_VSIL_jas_strtoopenmode(mode);
-
-	/* Allocate space for the underlying file stream object. */
-	if (!(obj = (jas_stream_VSIFL_t*) jas_malloc(sizeof(jas_stream_VSIFL_t)))) {
-		JPEG2000_VSIL_jas_stream_destroy(stream);
-		return NULL;
-	}
-	obj->fp = NULL;
-	stream->obj_ = (void *) obj;
-
-	/* Select the operations for a file stream object. */
-	stream->ops_ = const_cast<jas_stream_ops_t*> (&JPEG2000_VSIL_stream_fileops);
-
-	/* Open the underlying file. */
-	if ((obj->fp = VSIFOpenL(filename, mode)) == NULL) {
-		jas_stream_close(stream);
-		return NULL;
-	}
-
-	/* By default, use full buffering for this type of stream. */
-	JPEG2000_VSIL_jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, NULL, 0);
-
-	return stream;
-}
+/******************************************************************************
+ *
+ * Project:  JPEG-2000
+ * Purpose:  Return a stream for a VSIL file
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************/
+
+/* Following code is mostly derived from jas_stream.c, which is licensed */
+/* under the below terms */
+
+/*
+ * Copyright (c) 1999-2000 Image Power, Inc. and the University of
+ *   British Columbia.
+ * Copyright (c) 2001-2003 Michael David Adams.
+ * All rights reserved.
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
+ */
+
+/* __START_OF_JASPER_LICENSE__
+ *
+ * JasPer License Version 2.0
+ *
+ * Copyright (c) 2001-2006 Michael David Adams
+ * Copyright (c) 1999-2000 Image Power, Inc.
+ * Copyright (c) 1999-2000 The University of British Columbia
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person (the
+ * "User") obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * 1.  The above copyright notices and this permission notice (which
+ * includes the disclaimer below) shall be included in all copies or
+ * substantial portions of the Software.
+ *
+ * 2.  The name of a copyright holder shall not be used to endorse or
+ * promote products derived from the Software without specific prior
+ * written permission.
+ *
+ * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
+ * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+ * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
+ * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
+ * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
+ * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
+ * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
+ * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
+ * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
+ * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
+ * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
+ * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
+ * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
+ * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
+ * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
+ * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
+ * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
+ * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
+ * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
+ *
+ * __END_OF_JASPER_LICENSE__
+ */
+
+#include "jpeg2000_vsil_io.h"
+#include "cpl_vsi.h"
+
+CPL_CVSID("$Id: jpeg2000_vsil_io.cpp 35897 2016-10-24 11:54:24Z goatbar $");
+
+/*
+ * File descriptor file object.
+ */
+typedef struct {
+    VSILFILE* fp;
+} jas_stream_VSIFL_t;
+
+/******************************************************************************\
+* File stream object.
+\******************************************************************************/
+
+static int JPEG2000_VSIL_read(jas_stream_obj_t *obj, char *buf, int cnt)
+{
+    jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
+    return static_cast<int>(VSIFReadL(buf, 1, cnt, fileobj->fp));
+}
+
+static int JPEG2000_VSIL_write(jas_stream_obj_t *obj, char *buf, int cnt)
+{
+    jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
+    return static_cast<int>(VSIFWriteL(buf, 1, cnt, fileobj->fp));
+}
+
+static long JPEG2000_VSIL_seek(jas_stream_obj_t *obj, long offset, int origin)
+{
+    jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
+    if (offset < 0 && origin == SEEK_CUR)
+    {
+        origin = SEEK_SET;
+        offset += VSIFTellL(fileobj->fp);
+    }
+    else if (offset < 0 && origin == SEEK_END)
+    {
+        origin = SEEK_SET;
+        VSIFSeekL(fileobj->fp, 0, SEEK_END);
+        offset += VSIFTellL(fileobj->fp);
+    }
+    VSIFSeekL(fileobj->fp, offset, origin);
+    return VSIFTellL(fileobj->fp);
+}
+
+static int JPEG2000_VSIL_close(jas_stream_obj_t *obj)
+{
+    jas_stream_VSIFL_t *fileobj = JAS_CAST(jas_stream_VSIFL_t *, obj);
+    if( fileobj->fp != NULL )
+    {
+        VSIFCloseL(fileobj->fp);
+        fileobj->fp = NULL;
+    }
+    jas_free(fileobj);
+    return 0;
+}
+
+static const jas_stream_ops_t JPEG2000_VSIL_stream_fileops = {
+    JPEG2000_VSIL_read,
+    JPEG2000_VSIL_write,
+    JPEG2000_VSIL_seek,
+    JPEG2000_VSIL_close
+};
+
+/******************************************************************************\
+* Code for opening and closing streams.
+\******************************************************************************/
+
+static jas_stream_t *JPEG2000_VSIL_jas_stream_create()
+{
+    jas_stream_t *stream;
+
+    if (!(stream = (jas_stream_t*) jas_malloc(sizeof(jas_stream_t)))) {
+        return NULL;
+    }
+    stream->openmode_ = 0;
+    stream->bufmode_ = 0;
+    stream->flags_ = 0;
+    stream->bufbase_ = NULL;
+    stream->bufstart_ = NULL;
+    stream->bufsize_ = 0;
+    stream->ptr_ = NULL;
+    stream->cnt_ = 0;
+    stream->ops_ = NULL;
+    stream->obj_ = NULL;
+    stream->rwcnt_ = 0;
+    stream->rwlimit_ = -1;
+
+    return stream;
+}
+
+static void JPEG2000_VSIL_jas_stream_destroy(jas_stream_t *stream)
+{
+    /* If the memory for the buffer was allocated with malloc, free
+       this memory. */
+    if ((stream->bufmode_ & JAS_STREAM_FREEBUF) && stream->bufbase_) {
+        jas_free(stream->bufbase_);
+        stream->bufbase_ = NULL;
+    }
+    jas_free(stream);
+}
+
+/******************************************************************************\
+* Buffer initialization code.
+\******************************************************************************/
+
+static void JPEG2000_VSIL_jas_stream_initbuf(jas_stream_t *stream, int bufmode, char *buf,
+  int bufsize)
+{
+    /* If this function is being called, the buffer should not have been
+       initialized yet. */
+    assert(!stream->bufbase_);
+
+    if (bufmode != JAS_STREAM_UNBUF) {
+        /* The full- or line-buffered mode is being employed. */
+        if (!buf) {
+            /* The caller has not specified a buffer to employ, so allocate
+               one. */
+            if ((stream->bufbase_ = (unsigned char*)jas_malloc(JAS_STREAM_BUFSIZE +
+                                                               JAS_STREAM_MAXPUTBACK))) {
+                stream->bufmode_ |= JAS_STREAM_FREEBUF;
+                stream->bufsize_ = JAS_STREAM_BUFSIZE;
+            } else {
+                /* The buffer allocation has failed.  Resort to unbuffered
+                   operation. */
+                stream->bufbase_ = stream->tinybuf_;
+                stream->bufsize_ = 1;
+            }
+        } else {
+            /* The caller has specified a buffer to employ. */
+            /* The buffer must be large enough to accommodate maximum
+               putback. */
+            assert(bufsize > JAS_STREAM_MAXPUTBACK);
+            stream->bufbase_ = JAS_CAST(uchar *, buf);
+            stream->bufsize_ = bufsize - JAS_STREAM_MAXPUTBACK;
+        }
+    } else {
+        /* The unbuffered mode is being employed. */
+        /* A buffer should not have been supplied by the caller. */
+        assert(!buf);
+        /* Use a trivial one-character buffer. */
+        stream->bufbase_ = stream->tinybuf_;
+        stream->bufsize_ = 1;
+    }
+    stream->bufstart_ = &stream->bufbase_[JAS_STREAM_MAXPUTBACK];
+    stream->ptr_ = stream->bufstart_;
+    stream->cnt_ = 0;
+    stream->bufmode_ |= bufmode & JAS_STREAM_BUFMODEMASK;
+}
+
+static int JPEG2000_VSIL_jas_strtoopenmode(const char *s)
+{
+    int openmode = 0;
+    while (*s != '\0') {
+        switch (*s) {
+          case 'r':
+              openmode |= JAS_STREAM_READ;
+              break;
+          case 'w':
+              openmode |= JAS_STREAM_WRITE | JAS_STREAM_CREATE;
+              break;
+          case 'b':
+              openmode |= JAS_STREAM_BINARY;
+              break;
+          case 'a':
+              openmode |= JAS_STREAM_APPEND;
+              break;
+          case '+':
+              openmode |= JAS_STREAM_READ | JAS_STREAM_WRITE;
+              break;
+          default:
+              break;
+        }
+        ++s;
+    }
+    return openmode;
+}
+
+jas_stream_t *JPEG2000_VSIL_fopen(const char *filename, const char *mode)
+{
+    jas_stream_t *stream;
+    jas_stream_VSIFL_t *obj;
+
+    /* Allocate a stream object. */
+    if (!(stream = JPEG2000_VSIL_jas_stream_create())) {
+        return NULL;
+    }
+
+    /* Parse the mode string. */
+    stream->openmode_ = JPEG2000_VSIL_jas_strtoopenmode(mode);
+
+    /* Allocate space for the underlying file stream object. */
+    if (!(obj = (jas_stream_VSIFL_t*) jas_malloc(sizeof(jas_stream_VSIFL_t)))) {
+        JPEG2000_VSIL_jas_stream_destroy(stream);
+        return NULL;
+    }
+    obj->fp = NULL;
+    stream->obj_ = (void *) obj;
+
+    /* Select the operations for a file stream object. */
+    stream->ops_ = const_cast<jas_stream_ops_t*> (&JPEG2000_VSIL_stream_fileops);
+
+    /* Open the underlying file. */
+    if ((obj->fp = VSIFOpenL(filename, mode)) == NULL) {
+        jas_stream_close(stream);
+        return NULL;
+    }
+
+    /* By default, use full buffering for this type of stream. */
+    JPEG2000_VSIL_jas_stream_initbuf(stream, JAS_STREAM_FULLBUF, NULL, 0);
+
+    return stream;
+}
diff --git a/frmts/jpeg2000/jpeg2000_vsil_io.h b/frmts/jpeg2000/jpeg2000_vsil_io.h
index 3af42cf..284604d 100644
--- a/frmts/jpeg2000/jpeg2000_vsil_io.h
+++ b/frmts/jpeg2000/jpeg2000_vsil_io.h
@@ -1,37 +1,37 @@
-/******************************************************************************
- * $Id: jpeg2000_vsil_io.h 29468 2015-07-04 11:39:50Z rouault $
- *
- * Project:  JPEG-2000
- * Purpose:  Return a stream for a VSIL file
- * Author:   Even Rouault, even dot rouault at mines dash paris dot org
- *
- ******************************************************************************
- * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef JPEG2000_VSIL_IO_H
-#define JPEG2000_VSIL_IO_H
- 
-#include <jasper/jasper.h>
-
-jas_stream_t *JPEG2000_VSIL_fopen(const char *filename, const char *mode);
-
-#endif
+/******************************************************************************
+ * $Id: jpeg2000_vsil_io.h 35222 2016-08-28 06:06:11Z goatbar $
+ *
+ * Project:  JPEG-2000
+ * Purpose:  Return a stream for a VSIL file
+ * Author:   Even Rouault, even dot rouault at mines dash paris dot org
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef JPEG2000_VSIL_IO_H
+#define JPEG2000_VSIL_IO_H
+
+#include <jasper/jasper.h>
+
+jas_stream_t *JPEG2000_VSIL_fopen(const char *filename, const char *mode);
+
+#endif
diff --git a/frmts/jpeg2000/jpeg2000dataset.cpp b/frmts/jpeg2000/jpeg2000dataset.cpp
index c88c234..8a265ed 100644
--- a/frmts/jpeg2000/jpeg2000dataset.cpp
+++ b/frmts/jpeg2000/jpeg2000dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: jpeg2000dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  JPEG-2000
  * Purpose:  Partial implementation of the ISO/IEC 15444-1 standard
@@ -36,16 +35,21 @@
 #include <jasper/jasper.h>
 #include "jpeg2000_vsil_io.h"
 
-CPL_CVSID("$Id: jpeg2000dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <cmath>
+
+#include <algorithm>
+
+CPL_CVSID("$Id: jpeg2000dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 // XXX: Part of code below extracted from the JasPer internal headers and
 // must be in sync with JasPer version (this one works with JasPer 1.900.1)
 #define JP2_FTYP_MAXCOMPATCODES 32
 #define JP2_BOX_IHDR    0x69686472      /* Image Header */
 #define JP2_BOX_BPCC    0x62706363      /* Bits Per Component */
-#define	JP2_BOX_PCLR	0x70636c72	/* Palette */
+#define JP2_BOX_PCLR    0x70636c72      /* Palette */
 #define JP2_BOX_UUID    0x75756964      /* UUID */
 extern "C" {
+#ifdef NOT_USED
 typedef struct {
         uint_fast32_t magic;
 } jp2_jp_t;
@@ -55,19 +59,24 @@ typedef struct {
         uint_fast32_t numcompatcodes;
         uint_fast32_t compatcodes[JP2_FTYP_MAXCOMPATCODES];
 } jp2_ftyp_t;
+#endif
 typedef struct {
         uint_fast32_t width;
         uint_fast32_t height;
         uint_fast16_t numcmpts;
         uint_fast8_t bpc;
+        // cppcheck-suppress unusedStructMember
         uint_fast8_t comptype;
+        // cppcheck-suppress unusedStructMember
         uint_fast8_t csunk;
+        // cppcheck-suppress unusedStructMember
         uint_fast8_t ipr;
 } jp2_ihdr_t;
 typedef struct {
         uint_fast16_t numcmpts;
         uint_fast8_t *bpcs;
 } jp2_bpcc_t;
+#ifdef NOT_USED
 typedef struct {
         uint_fast8_t method;
         uint_fast8_t pri;
@@ -76,9 +85,11 @@ typedef struct {
         uint_fast8_t *iccp;
         int iccplen;
 } jp2_colr_t;
+#endif
 typedef struct {
         uint_fast16_t numlutents;
         uint_fast8_t numchans;
+        // cppcheck-suppress unusedStructMember
         int_fast32_t *lutdata;
         uint_fast8_t *bpc;
 } jp2_pclr_t;
@@ -89,6 +100,7 @@ typedef struct {
 } jp2_cdefchan_t;
 typedef struct {
         uint_fast16_t numchans;
+        // cppcheck-suppress unusedStructMember
         jp2_cdefchan_t *ents;
 } jp2_cdef_t;
 typedef struct {
@@ -99,6 +111,7 @@ typedef struct {
 
 typedef struct {
         uint_fast16_t numchans;
+        // cppcheck-suppress unusedStructMember
         jp2_cmapent_t *ents;
 } jp2_cmap_t;
 
@@ -125,11 +138,15 @@ typedef struct {
         uint_fast32_t datalen;
 
         union {
+#ifdef NOT_USED
                 jp2_jp_t jp;
                 jp2_ftyp_t ftyp;
+#endif
                 jp2_ihdr_t ihdr;
                 jp2_bpcc_t bpcc;
+#ifdef NOT_USED
                 jp2_colr_t colr;
+#endif
                 jp2_pclr_t pclr;
                 jp2_cdef_t cdef;
                 jp2_cmap_t cmap;
@@ -140,6 +157,7 @@ typedef struct {
 
 } jp2_box_t;
 
+#ifdef NOT_USED
 typedef struct jp2_boxops_s {
         void (*init)(jp2_box_t *box);
         void (*destroy)(jp2_box_t *box);
@@ -147,6 +165,7 @@ typedef struct jp2_boxops_s {
         int (*putdata)(jp2_box_t *box, jas_stream_t *out);
         void (*dumpdata)(jp2_box_t *box, FILE *out);
 } jp2_boxops_t;
+#endif
 
 extern jp2_box_t *jp2_box_create(int type);
 extern void jp2_box_destroy(jp2_box_t *box);
@@ -206,26 +225,25 @@ class JPEG2000RasterBand : public GDALPamRasterBand
   public:
 
                 JPEG2000RasterBand( JPEG2000Dataset *, int, int, int );
-                ~JPEG2000RasterBand();
+    virtual ~JPEG2000RasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
-
 /************************************************************************/
 /*                           JPEG2000RasterBand()                       */
 /************************************************************************/
 
 JPEG2000RasterBand::JPEG2000RasterBand( JPEG2000Dataset *poDSIn, int nBandIn,
-                int iDepthIn, int bSignednessIn )
-
+                                        int iDepthIn, int bSignednessIn ) :
+    poGDS(poDSIn),
+    psMatrix(NULL),
+    iDepth(iDepthIn),
+    bSignedness(bSignednessIn)
 {
-    this->poDS = poDSIn;
-    poGDS = poDSIn;
-    this->nBand = nBandIn;
-    this->iDepth = iDepthIn;
-    this->bSignedness = bSignednessIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     // XXX: JasPer can't handle data with depth > 32 bits
     // Maximum possible depth for JPEG2000 is 38!
@@ -253,8 +271,8 @@ JPEG2000RasterBand::JPEG2000RasterBand( JPEG2000Dataset *poDSIn, int nBandIn,
     }
     // FIXME: Figure out optimal block size!
     // Should the block size be fixed or determined dynamically?
-    nBlockXSize = MIN(256, poDSIn->nRasterXSize);
-    nBlockYSize = MIN(256, poDSIn->nRasterYSize);
+    nBlockXSize = std::min(256, poDSIn->nRasterXSize);
+    nBlockYSize = std::min(256, poDSIn->nRasterYSize);
     psMatrix = jas_matrix_create(nBlockYSize, nBlockXSize);
 
     if( iDepth % 8 != 0 && !poDSIn->bPromoteTo8Bit )
@@ -297,8 +315,10 @@ CPLErr JPEG2000RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     /* In case the dimensions of the image are not multiple of the block dimensions */
     /* take care of not requesting more pixels than available for the blocks at the */
     /* right or bottom of the image */
-    int nWidthToRead = MIN(nBlockXSize, poGDS->nRasterXSize - nBlockXOff * nBlockXSize);
-    int nHeightToRead = MIN(nBlockYSize, poGDS->nRasterYSize - nBlockYOff * nBlockYSize);
+    const int nWidthToRead =
+        std::min(nBlockXSize, poGDS->nRasterXSize - nBlockXOff * nBlockXSize);
+    const int nHeightToRead =
+        std::min(nBlockYSize, poGDS->nRasterYSize - nBlockYOff * nBlockYSize);
 
     jas_image_readcmpt( poGDS->psImage, nBand - 1,
                         nBlockXOff * nBlockXSize, nBlockYOff * nBlockYSize,
@@ -413,13 +433,13 @@ GDALColorInterp JPEG2000RasterBand::GetColorInterpretation()
 /************************************************************************/
 
 JPEG2000Dataset::JPEG2000Dataset() :
-    iFormat(0)
+    psStream(NULL),
+    psImage(NULL),
+    iFormat(0),
+    bPromoteTo8Bit(FALSE),
+    bAlreadyDecoded(FALSE)
 {
-    psStream = NULL;
-    psImage = NULL;
     nBands = 0;
-    bAlreadyDecoded = FALSE;
-    bPromoteTo8Bit = FALSE;
 
     poDriver = (GDALDriver *)GDALGetDriverByName("JPEG2000");
 }
@@ -506,8 +526,8 @@ int JPEG2000Dataset::DecodeImage()
     if ( jas_clrspc_fam( jas_image_clrspc( psImage ) ) ==
               JAS_CLRSPC_FAM_YCBCR )
     {
-        jas_image_t *psRGBImage;
-        jas_cmprof_t *psRGBProf;
+        jas_image_t *psRGBImage = NULL;
+        jas_cmprof_t *psRGBProf = NULL;
         CPLDebug( "JPEG2000", "forcing conversion to sRGB");
         if (!(psRGBProf = jas_cmprof_createfromclrspc(JAS_CLRSPC_SRGB))) {
             CPLDebug( "JPEG2000", "cannot create sRGB profile");
@@ -571,13 +591,13 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
 {
     int         iFormat;
     char        *pszFormatName = NULL;
-    jas_stream_t *sS;
 
     if (!Identify(poOpenInfo))
         return NULL;
 
     JPEG2000Init();
-    if( !(sS = JPEG2000_VSIL_fopen( poOpenInfo->pszFilename, "rb" )) )
+    jas_stream_t *sS= JPEG2000_VSIL_fopen( poOpenInfo->pszFilename, "rb" );
+    if( !sS )
     {
         return NULL;
     }
@@ -613,11 +633,11 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    JPEG2000Dataset     *poDS;
-    int                 *paiDepth = NULL, *pabSignedness = NULL;
-    int                 iBand;
+    int *paiDepth = NULL;
+    int *pabSignedness = NULL;
+    int iBand;
 
-    poDS = new JPEG2000Dataset();
+    JPEG2000Dataset *poDS = new JPEG2000Dataset();
 
     poDS->psStream = sS;
     poDS->iFormat = iFormat;
@@ -753,12 +773,14 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Should we promote alpha channel to 8 bits ?                     */
 /* -------------------------------------------------------------------- */
-    poDS->bPromoteTo8Bit = (poDS->nBands == 4 &&
-                            paiDepth[0] == 8 &&
-                            paiDepth[1] == 8 &&
-                            paiDepth[2] == 8 &&
-                            paiDepth[3] == 1 &&
-                            CSLFetchBoolean(poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION", TRUE));
+    poDS->bPromoteTo8Bit =
+        poDS->nBands == 4 &&
+        paiDepth[0] == 8 &&
+        paiDepth[1] == 8 &&
+        paiDepth[2] == 8 &&
+        paiDepth[3] == 1 &&
+        CPLFetchBool(poOpenInfo->papszOpenOptions,
+                     "1BIT_ALPHA_PROMOTION", true);
     if( poDS->bPromoteTo8Bit )
         CPLDebug( "JPEG2000",  "Fourth (alpha) band is promoted from 1 bit to 8 bit");
 
@@ -767,12 +789,10 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
 
-
     for( iBand = 1; iBand <= poDS->nBands; iBand++ )
     {
         poDS->SetBand( iBand, new JPEG2000RasterBand( poDS, iBand,
             paiDepth[iBand - 1], pabSignedness[iBand - 1] ) );
-
     }
 
     CPLFree( paiDepth );
@@ -797,7 +817,8 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nOpenFlags & GDAL_OF_VECTOR )
     {
         poDS->LoadVectorLayers(
-            CSLFetchBoolean(poOpenInfo->papszOpenOptions, "OPEN_REMOTE_GML", FALSE));
+            CPLFetchBool(poOpenInfo->papszOpenOptions,
+                         "OPEN_REMOTE_GML", false));
 
         // If file opened in vector-only mode and there's no vector,
         // return
@@ -809,7 +830,7 @@ GDALDataset *JPEG2000Dataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -825,8 +846,6 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     int  nBands = poSrcDS->GetRasterCount();
     int  nXSize = poSrcDS->GetRasterXSize();
     int  nYSize = poSrcDS->GetRasterYSize();
-    int                 iBand;
-    GDALRasterBand      *poBand;
 
     if( nBands == 0 )
     {
@@ -845,6 +864,9 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             return NULL;
     }
 
+    // TODO(schwehr): Localize these vars.
+    int iBand;
+    GDALRasterBand  *poBand = NULL;
     for ( iBand = 0; iBand < nBands; iBand++ )
     {
         poBand = poSrcDS->GetRasterBand( iBand + 1);
@@ -875,19 +897,18 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    jas_stream_t        *psStream;
-    jas_image_t         *psImage;
-
     JPEG2000Init();
     const char* pszAccess = STARTS_WITH_CI(pszFilename, "/vsisubfile/") ? "r+b" : "w+b";
-    if( !(psStream = JPEG2000_VSIL_fopen( pszFilename, pszAccess) ) )
+    jas_stream_t *psStream = JPEG2000_VSIL_fopen( pszFilename, pszAccess);
+    if( !psStream )
     {
         CPLError( CE_Failure, CPLE_FileIO, "Unable to create file %s.\n",
                   pszFilename );
         return NULL;
     }
 
-    if ( !(psImage = jas_image_create0()) )
+    jas_image_t *psImage = jas_image_create0();
+    if ( !psImage )
     {
         CPLError( CE_Failure, CPLE_OutOfMemory, "Unable to create image %s.\n",
                   pszFilename );
@@ -901,13 +922,13 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     GUInt32             *paiScanline;
     int                 iLine, iPixel;
     CPLErr              eErr = CE_None;
-    jas_matrix_t        *psMatrix;
     jas_image_cmptparm_t *sComps; // Array of pointers to image components
 
     sComps = (jas_image_cmptparm_t*)
         CPLMalloc( nBands * sizeof(jas_image_cmptparm_t) );
 
-    if ( !(psMatrix = jas_matrix_create( 1, nXSize )) )
+    jas_matrix_t *psMatrix  = jas_matrix_create( 1, nXSize );
+    if ( !psMatrix )
     {
         CPLError( CE_Failure, CPLE_OutOfMemory,
                   "Unable to create matrix with size %dx%d.\n", 1, nYSize );
@@ -923,8 +944,10 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
         poBand = poSrcDS->GetRasterBand( iBand + 1);
 
-        sComps[iBand].tlx = sComps[iBand].tly = 0;
-        sComps[iBand].hstep = sComps[iBand].vstep = 1;
+        sComps[iBand].tlx = 0;
+        sComps[iBand].tly = 0;
+        sComps[iBand].hstep = 1;
+        sComps[iBand].vstep = 1;
         sComps[iBand].width = nXSize;
         sComps[iBand].height = nYSize;
         sComps[iBand].prec = GDALGetDataTypeSize( poBand->GetRasterDataType() );
@@ -982,11 +1005,6 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*       Read compression parameters and encode the image.              */
 /* -------------------------------------------------------------------- */
-    int             i, j;
-    const int       OPTSMAX = 4096;
-    const char      *pszFormatName;
-    char            pszOptionBuf[OPTSMAX + 1];
-
     const char  *apszComprOptions[]=
     {
         "imgareatlx",
@@ -1016,27 +1034,29 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         NULL
     };
 
-    pszFormatName = CSLFetchNameValue( papszOptions, "FORMAT" );
+    const char *pszFormatName = CSLFetchNameValue( papszOptions, "FORMAT" );
     if ( !pszFormatName ||
          (!STARTS_WITH_CI(pszFormatName, "jp2") &&
           !STARTS_WITH_CI(pszFormatName, "jpc") ) )
         pszFormatName = "jp2";
 
-    pszOptionBuf[0] = '\0';
+    // TODO(schwehr): Move pszOptionBuf off the stack.
+    const int OPTSMAX = 4096;
+    char pszOptionBuf[OPTSMAX + 1] = {};
+
     if ( papszOptions )
     {
         CPLDebug( "JPEG2000", "User supplied parameters:" );
-        for ( i = 0; papszOptions[i] != NULL; i++ )
+        for ( int i = 0; papszOptions[i] != NULL; i++ )
         {
             CPLDebug( "JPEG2000", "%s\n", papszOptions[i] );
-            for ( j = 0; apszComprOptions[j] != NULL; j++ )
+            for ( int j = 0; apszComprOptions[j] != NULL; j++ )
                 if( EQUALN( apszComprOptions[j], papszOptions[i],
                             strlen(apszComprOptions[j]) ) )
                 {
-                    int m, n;
-
-                    n = static_cast<int>(strlen( pszOptionBuf ));
-                    m = n + static_cast<int>(strlen( papszOptions[i] )) + 1;
+                    const int n = static_cast<int>(strlen( pszOptionBuf ));
+                    const int m =
+                        n + static_cast<int>(strlen( papszOptions[i] )) + 1;
                     if ( m > OPTSMAX )
                         break;
                     if ( n > 0 )
@@ -1105,14 +1125,14 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     {
 #ifdef HAVE_JASPER_UUID
         double  adfGeoTransform[6];
-        if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) &&
+        if( CPLFetchBool( papszOptions, "GeoJP2", true ) &&
             ((poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None
                  && (adfGeoTransform[0] != 0.0
                      || adfGeoTransform[1] != 1.0
                      || adfGeoTransform[2] != 0.0
                      || adfGeoTransform[3] != 0.0
                      || adfGeoTransform[4] != 0.0
-                     || ABS(adfGeoTransform[5]) != 1.0))
+                     || std::abs(adfGeoTransform[5]) != 1.0))
                 || poSrcDS->GetGCPCount() > 0
                 || poSrcDS->GetMetadata("RPC") != NULL ) )
         {
@@ -1211,7 +1231,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if ( STARTS_WITH_CI(pszFormatName, "jp2") )
     {
         double  adfGeoTransform[6];
-        if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) &&
+        if( CPLFetchBool( papszOptions, "GMLJP2", true ) &&
             poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None &&
             poSrcDS->GetProjectionRef() != NULL &&
             poSrcDS->GetProjectionRef()[0] != '\0' )
@@ -1273,7 +1293,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                         poBox = oJP2MD.CreateGMLJP2(nXSize,nYSize);
 
                     nLBox = (int) poBox->GetDataLength() + 8;
-                    nLBox = CPL_MSBWORD32( nLBox );
+                    CPL_MSBPTR32( &nLBox );
                     memcpy(&nTBox, poBox->GetType(), 4);
 
                     VSIFSeekL(fp, 0, SEEK_END);
@@ -1291,7 +1311,7 @@ JPEG2000CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Do we need a world file?                                        */
 /* -------------------------------------------------------------------- */
-    if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
+    if( CPLFetchBool( papszOptions, "WORLDFILE", false ) )
     {
         double      adfGeoTransform[6];
 
@@ -1374,6 +1394,7 @@ void GDALRegister_JPEG2000()
 "<OpenOptionList>"
 "   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description='Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
 "   <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether to load remote vector layers referenced by a link in a GMLJP2 v2 box' default='NO'/>"
+"   <Option name='GEOREF_SOURCES' type='string' description='Comma separated list made with values INTERNAL/GMLJP2/GEOJP2/WORLDFILE/PAM/NONE that describe the priority order for georeferencing' default='PAM,GEOJP2,GMLJP2,WORLDFILE'/>"
 "</OpenOptionList>" );
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
diff --git a/frmts/jpegls/frmt_jpegls.html b/frmts/jpegls/frmt_jpegls.html
index 9695e6f..8742172 100644
--- a/frmts/jpegls/frmt_jpegls.html
+++ b/frmts/jpegls/frmt_jpegls.html
@@ -11,7 +11,7 @@
 
 <p>This driver is an implementation of a JPEG-LS reader/writer based on the Open Source CharLS library (BSD style license).
 At the time of writing, the CharLS library in its 1.0 version has no "make install" target. Consequently, the integration of the driver in the
-GDAL build system is a big rough. On Unix, you have to edit the GDALmake.opt file and edit the lines related to CHARLS.</p>
+GDAL build system is a bit rough. On Unix, you have to edit the GDALmake.opt file and edit the lines related to CHARLS.</p>
 
 <p>The driver can read and write lossless or near-lossless images. Note that it is not aimed at dealing with too big images (unless
 enough virtual memory is available), since the whole image must be compressed/decompressed in a single operation.<p>
@@ -27,7 +27,7 @@ enough virtual memory is available), since the whole image must be compressed/de
 
 <ul>
 <li><p> Implemented as <tt>gdal/frmts/jpegls/jpeglsdataset.cpp</tt>.</p></li>
-<li><p> <a href="http://charls.codeplex.com/">Homepage of the CharLS library<a></p></li>
+<li><p> <a href="https://github.com/team-charls/charls">Homepage of the CharLS library<a></p></li>
 </ul>
 
 
diff --git a/frmts/jpegls/jpegls_header.h b/frmts/jpegls/jpegls_header.h
new file mode 100644
index 0000000..3abb689
--- /dev/null
+++ b/frmts/jpegls/jpegls_header.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes CharLS headers
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef JPEGLS_HEADER_H
+#define JPEGLS_HEADER_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+/* CharLS header */
+#include <interface.h>
+
+#endif // JPEGLS_HEADER_H
diff --git a/frmts/jpegls/jpeglsdataset.cpp b/frmts/jpegls/jpeglsdataset.cpp
index 499c174..8236845 100644
--- a/frmts/jpegls/jpeglsdataset.cpp
+++ b/frmts/jpegls/jpeglsdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: jpeglsdataset.cpp 33833 2016-03-31 17:31:52Z rouault $
  *
  * Project:  JPEGLS driver based on CharLS library
  * Purpose:  JPEGLS driver based on CharLS library
@@ -31,12 +30,11 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-/* CharLS header */
-#include <interface.h>
+#include "jpegls_header.h"
 
 /* g++ -Wall -g fmrts/jpegls/jpeglsdataset.cpp -shared -fPIC -o gdal_JPEGLS.so -Iport -Igcore -L. -lgdal -I/home/even/charls-1.0 -L/home/even/charls-1.0/build -lCharLS */
 
-CPL_CVSID("$Id: jpeglsdataset.cpp 33833 2016-03-31 17:31:52Z rouault $");
+CPL_CVSID("$Id: jpeglsdataset.cpp 37526 2017-02-28 23:13:08Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -49,6 +47,7 @@ class JPEGLSDataset : public GDALPamDataset
     friend class JPEGLSRasterBand;
 
     CPLString osFilename;
+    VSILFILE *fpL;
     GByte* pabyUncompressedData;
     int    bHasUncompressed;
     int    nBitsPerSample;
@@ -82,35 +81,31 @@ class JPEGLSRasterBand : public GDALPamRasterBand
   public:
 
                 JPEGLSRasterBand( JPEGLSDataset * poDS, int nBand);
-                ~JPEGLSRasterBand();
+    virtual ~JPEGLSRasterBand();
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
-
 /************************************************************************/
 /*                        JPEGLSRasterBand()                            */
 /************************************************************************/
 
-JPEGLSRasterBand::JPEGLSRasterBand( JPEGLSDataset *poDSIn, int nBandIn)
+JPEGLSRasterBand::JPEGLSRasterBand( JPEGLSDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->eDataType = (poDSIn->nBitsPerSample <= 8) ? GDT_Byte : GDT_Int16;
-    this->nBlockXSize = poDSIn->nRasterXSize;
-    this->nBlockYSize = poDSIn->nRasterYSize;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eDataType = (poDSIn->nBitsPerSample <= 8) ? GDT_Byte : GDT_Int16;
+    nBlockXSize = poDSIn->nRasterXSize;
+    nBlockYSize = poDSIn->nRasterYSize;
 }
 
 /************************************************************************/
 /*                      ~JPEGLSRasterBand()                             */
 /************************************************************************/
 
-JPEGLSRasterBand::~JPEGLSRasterBand()
-{
-}
-
+JPEGLSRasterBand::~JPEGLSRasterBand() {}
 
 /************************************************************************/
 /*                    JPEGLSGetErrorAsString()                          */
@@ -221,12 +216,13 @@ GDALColorInterp JPEGLSRasterBand::GetColorInterpretation()
 /*                        JPEGLSDataset()                          */
 /************************************************************************/
 
-JPEGLSDataset::JPEGLSDataset()
-{
-    pabyUncompressedData = NULL;
-    bHasUncompressed = FALSE;
-    nBitsPerSample = 0;
-}
+JPEGLSDataset::JPEGLSDataset() :
+    fpL(NULL),
+    pabyUncompressedData(NULL),
+    bHasUncompressed(FALSE),
+    nBitsPerSample(0),
+    nOffset(0)
+{}
 
 /************************************************************************/
 /*                         ~JPEGLSDataset()                        */
@@ -235,6 +231,8 @@ JPEGLSDataset::JPEGLSDataset()
 JPEGLSDataset::~JPEGLSDataset()
 
 {
+    if( fpL != NULL )
+        VSIFCloseL(fpL);
     VSIFree(pabyUncompressedData);
 }
 
@@ -249,28 +247,47 @@ CPLErr JPEGLSDataset::Uncompress()
 
     bHasUncompressed = TRUE;
 
-    VSILFILE* fp = VSIFOpenL(osFilename, "rb");
-    if (!fp)
+    CPLAssert( fpL != NULL );
+    VSIFSeekL(fpL, 0, SEEK_END);
+    const vsi_l_offset nFileSizeBig = VSIFTellL(fpL) - nOffset;
+    VSIFSeekL(fpL, 0, SEEK_SET);
+    const size_t nFileSize = static_cast<size_t>(nFileSizeBig);
+#if SIZEOF_VOIDP != 8
+    if( nFileSizeBig != nFileSize )
+    {
         return CE_Failure;
-
-    VSIFSeekL(fp, 0, SEEK_END);
-    int nFileSize = (int)VSIFTellL(fp) - nOffset;
-    VSIFSeekL(fp, 0, SEEK_SET);
+    }
+#endif
 
     GByte* pabyCompressedData = (GByte*)VSIMalloc(nFileSize);
     if (pabyCompressedData == NULL)
     {
-        VSIFCloseL(fp);
+        VSIFCloseL(fpL);
+        fpL = NULL;
         return CE_Failure;
     }
 
-    VSIFSeekL(fp, nOffset, SEEK_SET);
-    VSIFReadL(pabyCompressedData, 1, nFileSize, fp);
-    VSIFCloseL(fp);
-    fp = NULL;
-
-    int nUncompressedSize = nRasterXSize * nRasterYSize *
-                            nBands * (GDALGetDataTypeSize(GetRasterBand(1)->GetRasterDataType()) / 8);
+    VSIFSeekL(fpL, nOffset, SEEK_SET);
+    if( VSIFReadL(pabyCompressedData, 1, nFileSize, fpL) != nFileSize )
+    {
+        VSIFCloseL(fpL);
+        fpL = NULL;
+        return CE_Failure;
+    }
+    VSIFCloseL(fpL);
+    fpL = NULL;
+
+    const GUIntBig nUncompressedSizeBig = static_cast<GUIntBig>(nRasterXSize) *
+        nRasterYSize * nBands *
+        GDALGetDataTypeSizeBytes(GetRasterBand(1)->GetRasterDataType());
+    const size_t nUncompressedSize = static_cast<size_t>(nUncompressedSizeBig);
+#if SIZEOF_VOIDP != 8
+    if( nUncompressedSizeBig != nUncompressedSize )
+    {
+        VSIFree(pabyCompressedData);
+        return CE_Failure;
+    }
+#endif
     pabyUncompressedData = (GByte*)VSI_MALLOC_VERBOSE(nUncompressedSize);
     if (pabyUncompressedData == NULL)
     {
@@ -278,7 +295,6 @@ CPLErr JPEGLSDataset::Uncompress()
         return CE_Failure;
     }
 
-
     JLS_ERROR eError = JpegLsDecode( pabyUncompressedData, nUncompressedSize,
                                      pabyCompressedData, nFileSize, NULL);
     if (eError != OK)
@@ -304,12 +320,12 @@ CPLErr JPEGLSDataset::Uncompress()
 int JPEGLSDataset::Identify( GDALOpenInfo * poOpenInfo, int& bIsDCOM )
 
 {
-    GByte  *pabyHeader = poOpenInfo->pabyHeader;
+    const GByte  *pabyHeader = poOpenInfo->pabyHeader;
     int    nHeaderBytes = poOpenInfo->nHeaderBytes;
 
     bIsDCOM = FALSE;
 
-    if( nHeaderBytes < 10 )
+    if( poOpenInfo->fpL == NULL || nHeaderBytes < 10 )
         return FALSE;
 
     if( pabyHeader[0] != 0xff
@@ -392,11 +408,10 @@ GDALDataset *JPEGLSDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
-        if (fp == NULL)
-            return NULL;
+        VSILFILE* fp = poOpenInfo->fpL;
         GByte abyBuffer[1028];
         GByte abySignature[] = { 0xFF, 0xD8, 0xFF, 0xF7 };
+        VSIFSeekL(fp, 0, SEEK_SET);
         while( true )
         {
             if (VSIFReadL(abyBuffer, 1, 1028, fp) != 1028)
@@ -421,8 +436,8 @@ GDALDataset *JPEGLSDataset::Open( GDALOpenInfo * poOpenInfo )
 
         VSIFSeekL(fp, nOffset, SEEK_SET);
         VSIFReadL(abyBuffer, 1, 1024, fp);
+        VSIFSeekL(fp, 0, SEEK_SET);
         eError = JpegLsReadHeader(abyBuffer, 1024, &sParams);
-        VSIFCloseL(fp);
         if (eError == OK)
         {
             CPLDebug("JPEGLS", "JPEGLS image found at offset %d", nOffset);
@@ -447,21 +462,20 @@ GDALDataset *JPEGLSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    JPEGLSDataset     *poDS;
-    int                 iBand;
-
-    poDS = new JPEGLSDataset();
+    JPEGLSDataset *poDS = new JPEGLSDataset();
     poDS->osFilename = poOpenInfo->pszFilename;
     poDS->nRasterXSize = sParams.width;
     poDS->nRasterYSize = sParams.height;
     poDS->nBands = sParams.components;
     poDS->nBitsPerSample = sParams.bitspersample;
     poDS->nOffset = nOffset;
+    poDS->fpL = poOpenInfo->fpL;
+    poOpenInfo->fpL = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    for( iBand = 1; iBand <= poDS->nBands; iBand++ )
+    for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
     {
         poDS->SetBand( iBand, new JPEGLSRasterBand( poDS, iBand) );
 
@@ -484,7 +498,7 @@ GDALDataset *JPEGLSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -497,9 +511,9 @@ JPEGLSDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                 GDALProgressFunc /*pfnProgress*/, void * /*pProgressData*/ )
 
 {
-    int  nBands = poSrcDS->GetRasterCount();
-    int  nXSize = poSrcDS->GetRasterXSize();
-    int  nYSize = poSrcDS->GetRasterYSize();
+    const int  nBands = poSrcDS->GetRasterCount();
+    const int  nXSize = poSrcDS->GetRasterXSize();
+    const int  nYSize = poSrcDS->GetRasterYSize();
 
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
@@ -537,11 +551,21 @@ JPEGLSDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             return NULL;
     }
 
-    int nWordSize = GDALGetDataTypeSize(eDT) / 8;
-    int nUncompressedSize = nXSize * nYSize * nBands * nWordSize;
+    const int nWordSize = GDALGetDataTypeSizeBytes(eDT);
+    const GUIntBig nUncompressedSizeBig = static_cast<GUIntBig>(nXSize) *
+                                                nYSize * nBands * nWordSize;
+#if SIZEOF_VOIDP != 8
+    if( nUncompressedSizeBig + 256 !=
+                    static_cast<size_t>(nUncompressedSizeBig + 256) )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory, "Too big image");
+        return NULL;
+    }
+#endif
+    const size_t nUncompressedSize = static_cast<size_t>(nUncompressedSizeBig);
     // FIXME? bug in charls-1.0beta ?. I needed a "+ something" to
     // avoid errors on byte.tif.
-    int nCompressedSize = nUncompressedSize + 256;
+    const size_t nCompressedSize = nUncompressedSize + 256;
     GByte* pabyDataCompressed = (GByte*)VSI_MALLOC_VERBOSE(nCompressedSize);
     GByte* pabyDataUncompressed = (GByte*)VSI_MALLOC_VERBOSE(nUncompressedSize);
     if (pabyDataCompressed == NULL || pabyDataUncompressed == NULL)
@@ -626,6 +650,7 @@ JPEGLSDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
     if (fp == NULL)
     {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s", pszFilename);
         VSIFree(pabyDataCompressed);
         return NULL;
     }
@@ -675,7 +700,7 @@ void GDALRegister_JPEGLS()
 "       <Value>LINE</Value>"
 "       <Value>BAND</Value>"
 "   </Option>"
-"   <Option name='LOSS_FACTOR' type='int' default='0' description='0 = lossless, 1 = near lossless, > 1 lossless'/>"
+"   <Option name='LOSS_FACTOR' type='int' default='0' description='0 = lossless, 1 = near lossless, >1 = lossy'/>"
 "</CreationOptionList>\n" );
 
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
@@ -686,4 +711,3 @@ void GDALRegister_JPEGLS()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/frmts/jpipkak/GNUmakefile b/frmts/jpipkak/GNUmakefile
index 30298e1..032dcc3 100644
--- a/frmts/jpipkak/GNUmakefile
+++ b/frmts/jpipkak/GNUmakefile
@@ -18,8 +18,8 @@ CPPFLAGS	:=	 $(KAKINC) -I. $(CPPFLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
-# kdu_cache.cpp does not appear to be built by default by the Kakadu 
-# apps makefiles, so we copy it and build it ourselves.  Perhaps this 
+# kdu_cache.cpp does not appear to be built by default by the Kakadu
+# apps makefiles, so we copy it and build it ourselves.  Perhaps this
 # won't be needed with newer versions of Kakadu.  Tested with 6.2.
 kdu_cache.cpp:	  $(KAKDIR)/apps/caching_sources/kdu_cache.cpp
 	echo "#include \"cpl_port.h\"" > kdu_cache_wrapper.h
diff --git a/frmts/jpipkak/jpipkakdataset.cpp b/frmts/jpipkak/jpipkakdataset.cpp
index c47c038..bca20ee 100644
--- a/frmts/jpipkak/jpipkakdataset.cpp
+++ b/frmts/jpipkak/jpipkakdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: jpipkakdataset.cpp 2008-10-01 nbarker $
  *
  * Project:  jpip read driver
  * Purpose:  GDAL bindings for JPIP.
@@ -36,6 +35,8 @@
 #include "gdal_frmts.h"
 #include "jpipkakdataset.h"
 
+CPL_CVSID("$Id: jpipkakdataset.cpp 37431 2017-02-20 11:57:16Z rouault $");
+
 /*
 ** The following are for testing premature stream termination support.
 ** This is a mechanism to test handling of failed or incomplete reads
@@ -54,6 +55,8 @@ static int nPSTThisInstance = -1;
 static int nPSTTargetOffset = -1;
 #endif
 
+static bool kakadu_initialized = false;
+
 /************************************************************************/
 /* ==================================================================== */
 /*                     Set up messaging services                        */
@@ -65,13 +68,12 @@ class jpipkak_kdu_cpl_error_message : public kdu_message
 public: // Member classes
     using kdu_message::put_text;
 
-    jpipkak_kdu_cpl_error_message( CPLErr eErrClass )
-    {
-        m_eErrClass = eErrClass;
-        m_pszError = NULL;
-    }
+    explicit jpipkak_kdu_cpl_error_message( CPLErr eErrClass ) :
+        m_eErrClass ( eErrClass ),
+        m_pszError ( NULL )
+    {}
 
-    void put_text(const char *string)
+    void put_text(const char *string) override
     {
         if( m_pszError == NULL )
             m_pszError = CPLStrdup( string );
@@ -87,7 +89,7 @@ public: // Member classes
     {
     };
 
-    void flush(bool end_of_message=false)
+    void flush(bool end_of_message=false) override
     {
         if( m_pszError == NULL )
             return;
@@ -167,19 +169,20 @@ JPIPKAKRasterBand::JPIPKAKRasterBand( int nBandIn, int nDiscardLevelsIn,
 
     if( nDiscardLevels == 0 )
     {
-        int  nXSize = nRasterXSize, nYSize = nRasterYSize;
+        int nXSize = nRasterXSize;
+        int nYSize = nRasterYSize;
 
         for( int nDiscard = 1; nDiscard < nResCount; nDiscard++ )
         {
-            kdu_dims  dims;
 
-            nXSize = (nXSize+1) / 2;
-            nYSize = (nYSize+1) / 2;
+            nXSize = (nXSize + 1) / 2;
+            nYSize = (nYSize + 1) / 2;
 
             if( (nXSize+nYSize) < 128 || nXSize < 4 || nYSize < 4 )
                 continue; /* skip super reduced resolution layers */
 
             oCodeStream->apply_input_restrictions( 0, 0, nDiscard, 0, NULL );
+            kdu_dims dims;
             oCodeStream->get_dims( 0, dims );
 
             if( (dims.size.x == nXSize || dims.size.x == nXSize-1)
@@ -426,7 +429,11 @@ JPIPKAKDataset::JPIPKAKDataset()
 /*****************************************/
 JPIPKAKDataset::~JPIPKAKDataset()
 {
-    CPLHTTPCleanup();
+    char** papszOptions = NULL;
+    papszOptions = CSLSetNameValue(papszOptions,
+                        "CLOSE_PERSISTENT", CPLSPrintf("JPIPKAK:%p", this));
+    CPLHTTPFetch("", papszOptions);
+    CSLDestroy(papszOptions);
 
     Deinitialize();
 
@@ -472,16 +479,34 @@ void JPIPKAKDataset::Deinitialize()
     bNeedReinitialize = TRUE;
 }
 
+/************************************************************************/
+/*                          KakaduInitialize()                          */
+/************************************************************************/
+
+void JPIPKAKDataset::KakaduInitialize()
+
+{
+/* -------------------------------------------------------------------- */
+/*      Initialize Kakadu warning/error reporting subsystem.            */
+/* -------------------------------------------------------------------- */
+    if( !kakadu_initialized )
+    {
+        kakadu_initialized = true;
+
+        jpipkak_kdu_cpl_error_message oErrHandler( CE_Failure );
+        jpipkak_kdu_cpl_error_message oWarningHandler( CE_Warning );
+
+        kdu_customize_warnings(new jpipkak_kdu_cpl_error_message( CE_Warning ) );
+        kdu_customize_errors(new jpipkak_kdu_cpl_error_message( CE_Failure ) );
+    }
+}
+
 /*****************************************/
 /*         Initialize()                  */
 /*****************************************/
 int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
 {
-    // set up message handlers
-    jpipkak_kdu_cpl_error_message oErrHandler( CE_Failure );
-    jpipkak_kdu_cpl_error_message oWarningHandler( CE_Warning );
-    kdu_customize_warnings(new jpipkak_kdu_cpl_error_message( CE_Warning ) );
-    kdu_customize_errors(new jpipkak_kdu_cpl_error_message( CE_Failure ) );
+    KakaduInitialize();
 
     // create necessary http headers
     CPLString osHeaders = "HEADERS=Accept: jpp-stream";
@@ -676,7 +701,7 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
         else
             eDT = GDT_Byte;
 
-        if( poCodestream->get_bit_depth(0) % 8 != 8
+        if( (poCodestream->get_bit_depth(0) % 8) != 0
             && poCodestream->get_bit_depth(0) < 16 )
             SetMetadataItem(
                 "NBITS",
@@ -699,7 +724,6 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
 
         bYCC=TRUE;
         cod_in->get("Cycc", 0, 0, bYCC);
-
     }
     catch(...)
     {
@@ -826,7 +850,6 @@ int JPIPKAKDataset::Initialize(const char* pszDatasetName, int bReinitializing )
             // treat as cartesian, no geo metadata
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Parsed metadata boxes from jpip stream, geographic metadata not found - is the server using placeholders for this data?" );
-
         }
     }
     catch(...)
@@ -930,6 +953,7 @@ JPIPDataSegment* JPIPKAKDataset::ReadSegment(GByte* pabyData, int nLen,
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Invalid Bin-ID value format");
                 bError = TRUE;
+                delete segment;
                 return NULL;
             }
             else if (m >= 2) {
@@ -940,6 +964,7 @@ JPIPDataSegment* JPIPKAKDataset::ReadSegment(GByte* pabyData, int nLen,
                     if( nCodestream < 0 )
                     {
                         bError = TRUE;
+                        delete segment;
                         return NULL;
                     }
                 }
@@ -954,6 +979,7 @@ JPIPDataSegment* JPIPKAKDataset::ReadSegment(GByte* pabyData, int nLen,
             if( nNextVal == -1 )
             {
                 bError = TRUE;
+                delete segment;
                 return NULL;
             }
             else
@@ -963,6 +989,7 @@ JPIPDataSegment* JPIPKAKDataset::ReadSegment(GByte* pabyData, int nLen,
             if( nNextVal == -1 )
             {
                 bError = TRUE;
+                delete segment;
                 return NULL;
             }
             else
@@ -1082,7 +1109,6 @@ int JPIPKAKDataset::ReadFromInput(GByte* pabyData, int nLen, int &bError )
     return res;
 }
 
-
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
@@ -1091,7 +1117,7 @@ const char *JPIPKAKDataset::GetProjectionRef()
 
 {
     if( pszProjection && *pszProjection )
-        return( pszProjection );
+        return pszProjection;
     else
         return GDALPamDataset::GetProjectionRef();
 }
@@ -1356,9 +1382,14 @@ JPIPKAKDataset::BeginAsyncReader(int xOff, int yOff,
         ario->pBuf = pBuf;
         ario->pAppBuf = pBuf;
 
-        ario->nAppPixelSpace = ario->nPixelSpace = nPixelSpace;
-        ario->nAppLineSpace = ario->nLineSpace = nLineSpace;
-        ario->nAppBandSpace = ario->nBandSpace = nBandSpace;
+        ario->nAppPixelSpace = nPixelSpace;
+        ario->nPixelSpace = nPixelSpace;
+
+        ario->nAppLineSpace = nLineSpace;
+        ario->nLineSpace = nLineSpace;
+
+        ario->nAppBandSpace = nBandSpace;
+        ario->nBandSpace = nBandSpace;
     }
 
     // parse options
@@ -1393,7 +1424,8 @@ JPIPKAKDataset::BeginAsyncReader(int xOff, int yOff,
         ario->nLevel = atoi(pszLevel);
     else
     {
-        int nRXSize = xSize, nRYSize = ySize;
+        int nRXSize = xSize;
+        int nRYSize = ySize;
         ario->nLevel = 0;
 
         while( ario->nLevel < nResLevels
@@ -1419,7 +1451,6 @@ void JPIPKAKDataset::EndAsyncReader(GDALAsyncReader *poARIO)
     delete poARIO;
 }
 
-
 /*****************************************/
 /*             Open()                    */
 /*****************************************/
@@ -1434,8 +1465,7 @@ GDALDataset *JPIPKAKDataset::Open(GDALOpenInfo * poOpenInfo)
         // using cpl_http for the connection
         if  (CPLHTTPEnabled() == TRUE)
         {
-            JPIPKAKDataset *poDS;
-            poDS = new JPIPKAKDataset();
+            JPIPKAKDataset *poDS = new JPIPKAKDataset();
             if (poDS->Initialize(poOpenInfo->pszFilename,FALSE))
             {
                 poDS->SetDescription( poOpenInfo->pszFilename );
@@ -1489,8 +1519,16 @@ void GDALRegister_JPIPKAK()
 JPIPKAKAsyncReader::JPIPKAKAsyncReader()
 {
     panBandMap = NULL;
-    pAppBuf = pBuf = NULL;
+    pAppBuf = NULL;
+    pBuf = NULL;
     nDataRead = 0;
+    nAppPixelSpace = 0;
+    nAppLineSpace = 0;
+    nAppBandSpace = 0;
+    nLevel = 0;
+    nQualityLayers = 0;
+    bHighPriority = FALSE;
+    bComplete = FALSE;
 }
 
 /************************************************************************/
@@ -1909,7 +1947,6 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
 
             poJDS->poDecompressor->finish();
             CPLReleaseMutex(poJDS->pGlobalMutex);
-
         }
         catch(...)
         {
@@ -1920,7 +1957,6 @@ JPIPKAKAsyncReader::GetNextUpdatedRegion(double dfTimeout,
         }
     } // nBandsCompleted < nBandCount
 
-
 /* -------------------------------------------------------------------- */
 /*      If the application buffer is of a different type than our       */
 /*      band we need to copy into the application buffer at this        */
@@ -2087,7 +2123,6 @@ static void JPIPWorkerFunc(void *req)
         if ((nEnd - nStart) > 0)
             nCurrentTransmissionLength = (int) MAX(bytes / ((1.0 * (nEnd - nStart)) / CLOCKS_PER_SEC), nMinimumTransmissionLength);
 
-
         CPLAcquireMutex(poJDS->pGlobalMutex, 100.0);
 
         int bError;
diff --git a/frmts/jpipkak/jpipkakdataset.h b/frmts/jpipkak/jpipkakdataset.h
index 0ee7f83..5b99544 100644
--- a/frmts/jpipkak/jpipkakdataset.h
+++ b/frmts/jpipkak/jpipkakdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: jpipkakdataset.cpp 2008-10-01 nbarker $
+ * $Id: jpipkakdataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  jpip read driver
  * Purpose:  GDAL bindings for JPIP.
@@ -40,13 +40,11 @@
 
 #include <time.h>
 
-
 #if KDU_MAJOR_VERSION > 7 || (KDU_MAJOR_VERSION == 7 && KDU_MINOR_VERSION >= 5)
     using namespace kdu_core;
     using namespace kdu_supp;
 #endif
 
-
 static void JPIPWorkerFunc(void *);
 
 /************************************************************************/
@@ -135,7 +133,7 @@ private:
     JPIPDataSegment* ReadSegment(GByte* pabyData, int nLen, int& bError);
     int Initialize(const char* url, int bReinitializing );
     void Deinitialize();
-    int KakaduClassId(int nClassId);
+    static int KakaduClassId(int nClassId);
 
     CPLMutex *pGlobalMutex;
 
@@ -149,6 +147,8 @@ private:
     volatile long nHighThreadByteCount;
     volatile long nLowThreadByteCount;
 
+    static void KakaduInitialize();
+
 public:
     JPIPKAKDataset();
     virtual ~JPIPKAKDataset();
@@ -162,9 +162,9 @@ public:
                                               int nBandCount, int* bandMap,
                                               int nPixelSpace, int nLineSpace,
                                               int nBandSpace,
-                                              char **papszOptions);
+                                              char **papszOptions) override;
 
-    virtual void EndAsyncReader(GDALAsyncReader *);
+    virtual void EndAsyncReader(GDALAsyncReader *) override;
     int GetNQualityLayers(){return nQualityLayers;}
     int GetNResolutionLevels(){return nResLevels;}
     int GetNComponents(){return nComps;}
@@ -176,11 +176,11 @@ public:
                         int nBandCount, int *panBandList );
 
     //gdaldataset methods
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char *GetProjectionRef(void);
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char *GetProjectionRef() override;
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                               int nXOff, int nYOff, int nXSize, int nYSize,
                               void * pData, int nBufXSize, int nBufYSize,
@@ -188,7 +188,7 @@ public:
                               int nBandCount, int *panBandMap,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 
     static GDALDataset *Open(GDALOpenInfo *);
     static const GByte JPIP_EOR_IMAGE_DONE = 1;
@@ -218,9 +218,9 @@ class JPIPKAKRasterBand : public GDALPamRasterBand
 
     int         nDiscardLevels;
 
-    kdu_dims 	band_dims;
+    kdu_dims    band_dims;
 
-    int		nOverviewCount;
+    int         nOverviewCount;
     JPIPKAKRasterBand **papoOverviewBand;
 
     kdu_codestream *oCodeStream;
@@ -232,16 +232,16 @@ public:
 
     JPIPKAKRasterBand( int, int, kdu_codestream *, int,
                        JPIPKAKDataset * );
-    ~JPIPKAKRasterBand();
+    virtual ~JPIPKAKRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) override;
 
-    virtual int    GetOverviewCount();
-    virtual GDALRasterBand *GetOverview( int );
+    virtual int    GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview( int ) override;
 };
 
 /************************************************************************/
@@ -277,7 +277,7 @@ public:
                                                      int* pnxbufoff,
                                                      int* pnybufoff,
                                                      int* pnxbufsize,
-                                                     int* pnybufsize);
+                                                     int* pnybufsize) override;
     void SetComplete(int bFinished){this->bComplete = bFinished;};
 
     friend class JPIPKAKDataset;
diff --git a/frmts/kea/keaband.cpp b/frmts/kea/keaband.cpp
index c2b4024..3f5237b 100644
--- a/frmts/kea/keaband.cpp
+++ b/frmts/kea/keaband.cpp
@@ -1,5 +1,4 @@
 /*
- * $Id: keaband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keaband.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -40,6 +39,8 @@
 
 #include <limits.h>
 
+CPL_CVSID("$Id: keaband.cpp 37966 2017-04-11 19:34:57Z rouault $");
+
 // constructor
 KEARasterBand::KEARasterBand( KEADataset *pDataset, int nSrcBand, GDALAccess eAccessIn, kealib::KEAImageIO *pImageIO, int *pRefCount )
 {
@@ -326,15 +327,14 @@ CPLErr KEARasterBand::SetMetadata(char **papszMetadata, const char *pszDomain)
     if( ( pszDomain != NULL ) && ( *pszDomain != '\0' ) )
         return CE_Failure;
     int nIndex = 0;
-    char *pszName;
-    const char *pszValue;
     try
     {
         // iterate through each one
         while( papszMetadata[nIndex] != NULL )
         {
-            pszName = NULL;
-            pszValue = CPLParseNameValue( papszMetadata[nIndex], &pszName );
+            char *pszName = NULL;
+            const char *pszValue =
+                CPLParseNameValue( papszMetadata[nIndex], &pszName );
             if( pszValue == NULL )
                 pszValue = "";
             if( pszName != NULL )
@@ -459,7 +459,7 @@ GDALRasterAttributeTable *KEARasterBand::GetDefaultRAT()
         {
             // we assume this is never NULL - creates a new one if none exists
             kealib::KEAAttributeTable *pKEATable = this->m_pImageIO->getAttributeTable(kealib::kea_att_file, this->nBand);
-            this->m_pAttributeTable = new KEARasterAttributeTable(pKEATable);
+            this->m_pAttributeTable = new KEARasterAttributeTable(pKEATable, this);
         }
         catch(const kealib::KEAException &e)
         {
@@ -556,7 +556,6 @@ CPLErr KEARasterBand::SetDefaultRAT(const GDALRasterAttributeTable *poRAT)
                         CPLFree(papszStringData[n]);
                 }
                 CPLFree(papszStringData);
-
             }
         }
     }
diff --git a/frmts/kea/keaband.h b/frmts/kea/keaband.h
index 430cfeb..61bf15e 100644
--- a/frmts/kea/keaband.h
+++ b/frmts/kea/keaband.h
@@ -1,5 +1,5 @@
 /*
- * $Id: keaband.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: keaband.h 36501 2016-11-25 14:09:24Z rouault $
  *  keaband.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -60,39 +60,39 @@ public:
     ~KEARasterBand();
 
     // virtual methods for overview support
-    int GetOverviewCount();
-    GDALRasterBand* GetOverview(int nOverview);
+    int GetOverviewCount() override;
+    GDALRasterBand* GetOverview(int nOverview) override;
 
     // virtual methods for band names (aka description)
-    void SetDescription(const char *);
+    void SetDescription(const char *) override;
 
     // virtual methods for handling the metadata
-    CPLErr SetMetadataItem (const char *pszName, const char *pszValue, const char *pszDomain="");
-    const char *GetMetadataItem (const char *pszName, const char *pszDomain="");
-    char **GetMetadata(const char *pszDomain="");
-    CPLErr SetMetadata(char **papszMetadata, const char *pszDomain="");
+    CPLErr SetMetadataItem (const char *pszName, const char *pszValue, const char *pszDomain="") override;
+    const char *GetMetadataItem (const char *pszName, const char *pszDomain="") override;
+    char **GetMetadata(const char *pszDomain="") override;
+    CPLErr SetMetadata(char **papszMetadata, const char *pszDomain="") override;
 
     // virtual methods for the no data value
-    double GetNoDataValue(int *pbSuccess=NULL);
-    CPLErr SetNoDataValue(double dfNoData);
-    virtual CPLErr DeleteNoDataValue();
+    double GetNoDataValue(int *pbSuccess=NULL) override;
+    CPLErr SetNoDataValue(double dfNoData) override;
+    virtual CPLErr DeleteNoDataValue() override;
 
     // virtual methods for RATs
-    GDALRasterAttributeTable *GetDefaultRAT();
-    CPLErr SetDefaultRAT(const GDALRasterAttributeTable *poRAT);
+    GDALRasterAttributeTable *GetDefaultRAT() override;
+    CPLErr SetDefaultRAT(const GDALRasterAttributeTable *poRAT) override;
 
     // virtual methods for color tables
-    GDALColorTable *GetColorTable();
-    CPLErr SetColorTable(GDALColorTable *poCT);
+    GDALColorTable *GetColorTable() override;
+    CPLErr SetColorTable(GDALColorTable *poCT) override;
 
     // virtual methods for color interpretation
-    GDALColorInterp GetColorInterpretation();
-    CPLErr SetColorInterpretation(GDALColorInterp gdalinterp);
+    GDALColorInterp GetColorInterpretation() override;
+    CPLErr SetColorInterpretation(GDALColorInterp gdalinterp) override;
 
     // Virtual methods for band masks.
-    CPLErr CreateMaskBand(int nFlags);
-    GDALRasterBand* GetMaskBand();
-    int GetMaskFlags();
+    CPLErr CreateMaskBand(int nFlags) override;
+    GDALRasterBand* GetMaskBand() override;
+    int GetMaskFlags() override;
 
     // internal methods for overviews
     void readExistingOverviews();
@@ -102,8 +102,8 @@ public:
 
 protected:
     // methods for accessing data as blocks
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 
     // updates m_papszMetadataList
     void UpdateMetadataList();
@@ -113,5 +113,4 @@ protected:
     kealib::KEADataType  m_eKEADataType; // data type as KEA enum
 };
 
-
 #endif //KEABAND_H
diff --git a/frmts/kea/keacopy.cpp b/frmts/kea/keacopy.cpp
index 9fca903..24f3376 100644
--- a/frmts/kea/keacopy.cpp
+++ b/frmts/kea/keacopy.cpp
@@ -1,5 +1,4 @@
 /*
- * $Id: keacopy.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keacopy.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -34,6 +33,8 @@
 
 #include "keacopy.h"
 
+CPL_CVSID("$Id: keacopy.cpp 36418 2016-11-21 22:58:41Z rouault $");
+
 // Support functions for CreateCopy()
 
 // Copies GDAL Band to KEA Band if nOverview == -1
@@ -310,13 +311,12 @@ static void KEACopyMetadata( GDALMajorObject *pObject, kealib::KEAImageIO *pImag
     char **ppszMetadata = pObject->GetMetadata();
     if( ppszMetadata != NULL )
     {
-        char *pszName;
-        const char *pszValue;
         int nCount = 0;
         while( ppszMetadata[nCount] != NULL )
         {
-            pszName = NULL;
-            pszValue = CPLParseNameValue( ppszMetadata[nCount], &pszName );
+            char *pszName = NULL;
+            const char *pszValue =
+                CPLParseNameValue( ppszMetadata[nCount], &pszName );
             if( pszValue == NULL )
                 pszValue = "";
             if( pszName != NULL )
@@ -458,15 +458,13 @@ static void KEACopyGCPs(GDALDataset *pDataset, kealib::KEAImageIO *pImageIO)
         {
         }
 
-        for( std::vector<kealib::KEAImageGCP*>::iterator itr = KEAGCPs.begin(); itr != KEAGCPs.end(); itr++)
+        for( std::vector<kealib::KEAImageGCP*>::iterator itr = KEAGCPs.begin(); itr != KEAGCPs.end(); ++itr)
         {
             delete (*itr);
         }
     }
 }
 
-
-
 bool KEACopyFile( GDALDataset *pDataset, kealib::KEAImageIO *pImageIO,
                   GDALProgressFunc pfnProgress, void *pProgressData )
 {
diff --git a/frmts/kea/keadataset.cpp b/frmts/kea/keadataset.cpp
index 08bfba6..398519a 100644
--- a/frmts/kea/keadataset.cpp
+++ b/frmts/kea/keadataset.cpp
@@ -1,5 +1,4 @@
 /*
- * $Id: keadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keadataset.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -32,6 +31,8 @@
 #include "keaband.h"
 #include "keacopy.h"
 
+CPL_CVSID("$Id: keadataset.cpp 36418 2016-11-21 22:58:41Z rouault $");
+
 // Function for converting a libkea type into a GDAL type
 GDALDataType KEA_to_GDAL_Type( kealib::KEADataType ekeaType )
 {
@@ -172,7 +173,6 @@ int KEADataset::Identify( GDALOpenInfo * poOpenInfo )
         return 0;
 }
 
-
 // static function
 H5::H5File *KEADataset::CreateLL( const char * pszFilename,
                                   int nXSize, int nYSize, int nBands,
@@ -399,7 +399,6 @@ GDALDataset *KEADataset::CreateCopy( const char * pszFilename, GDALDataset *pSrc
                   pszFilename, e.what() );
         return NULL;
     }
-
 }
 
 // constructor
@@ -661,16 +660,15 @@ CPLErr KEADataset::SetMetadata(char **papszMetadata, const char *pszDomain)
         return CE_Failure;
 
     int nIndex = 0;
-    char *pszName;
-    const char *pszValue;
     try
     {
         // go through each item
         while( papszMetadata[nIndex] != NULL )
         {
             // get the value/name
-            pszName = NULL;
-            pszValue = CPLParseNameValue( papszMetadata[nIndex], &pszName );
+            char *pszName = NULL;
+            const char *pszValue =
+                CPLParseNameValue( papszMetadata[nIndex], &pszName );
             if( pszValue == NULL )
                 pszValue = "";
             if( pszName != NULL )
@@ -745,7 +743,6 @@ CPLErr KEADataset::AddBand(GDALDataType eType, char **papszOptions)
     return CE_None;
 }
 
-
 int KEADataset::GetGCPCount()
 {
     try
@@ -756,7 +753,6 @@ int KEADataset::GetGCPCount()
     {
         return 0;
     }
-
 }
 
 const char* KEADataset::GetGCPProjection()
@@ -844,7 +840,7 @@ CPLErr KEADataset::SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList, const char
         result = CE_Failure;
     }
 
-    for( std::vector<kealib::KEAImageGCP*>::iterator itr = pKEAGCPs->begin(); itr != pKEAGCPs->end(); itr++)
+    for( std::vector<kealib::KEAImageGCP*>::iterator itr = pKEAGCPs->begin(); itr != pKEAGCPs->end(); ++itr)
     {
         kealib::KEAImageGCP *pKEA = (*itr);
         delete pKEA;
diff --git a/frmts/kea/keadataset.h b/frmts/kea/keadataset.h
index 037f914..becc358 100644
--- a/frmts/kea/keadataset.h
+++ b/frmts/kea/keadataset.h
@@ -1,5 +1,5 @@
 /*
- * $Id: keadataset.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: keadataset.h 36501 2016-11-25 14:09:24Z rouault $
  *  keadataset.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -61,36 +61,36 @@ public:
                                 GDALProgressFunc pfnProgress, void *pProgressData );
 
     // virtual methods for dealing with transform and projection
-    CPLErr      GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
+    const char *GetProjectionRef() override;
 
-    CPLErr  SetGeoTransform (double *padfTransform );
-    CPLErr SetProjection( const char *pszWKT );
+    CPLErr  SetGeoTransform (double *padfTransform ) override;
+    CPLErr SetProjection( const char *pszWKT ) override;
 
     // method to get a pointer to the imageio class
-    void *GetInternalHandle (const char *);
+    void *GetInternalHandle (const char *) override;
 
     // virtual methods for dealing with metadata
-    CPLErr SetMetadataItem (const char *pszName, const char *pszValue, const char *pszDomain="");
-    const char *GetMetadataItem (const char *pszName, const char *pszDomain="");
+    CPLErr SetMetadataItem (const char *pszName, const char *pszValue, const char *pszDomain="") override;
+    const char *GetMetadataItem (const char *pszName, const char *pszDomain="") override;
 
-    char **GetMetadata(const char *pszDomain="");
-    CPLErr SetMetadata(char **papszMetadata, const char *pszDomain="");
+    char **GetMetadata(const char *pszDomain="") override;
+    CPLErr SetMetadata(char **papszMetadata, const char *pszDomain="") override;
 
     // virtual method for adding new image bands
-    CPLErr AddBand(GDALDataType eType, char **papszOptions = NULL);
+    CPLErr AddBand(GDALDataType eType, char **papszOptions = NULL) override;
 
     // GCPs
-    int GetGCPCount();
-    const char* GetGCPProjection();
-    const GDAL_GCP* GetGCPs();
-    CPLErr SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList, const char *pszGCPProjection);
+    int GetGCPCount() override;
+    const char* GetGCPProjection() override;
+    const GDAL_GCP* GetGCPs() override;
+    CPLErr SetGCPs(int nGCPCount, const GDAL_GCP *pasGCPList, const char *pszGCPProjection) override;
 
 protected:
     // this method builds overviews for the specified bands.
     virtual CPLErr IBuildOverviews(const char *pszResampling, int nOverviews, int *panOverviewList,
                                     int nListBands, int *panBandList, GDALProgressFunc pfnProgress,
-                                    void *pProgressData);
+                                    void *pProgressData) override;
 
     // internal method to update m_papszMetadataList
     void UpdateMetadataList();
diff --git a/frmts/kea/keadriver.cpp b/frmts/kea/keadriver.cpp
index 24208c6..00d552d 100644
--- a/frmts/kea/keadriver.cpp
+++ b/frmts/kea/keadriver.cpp
@@ -1,5 +1,4 @@
 /*
- * $Id: keadriver.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keadriver.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -31,6 +30,8 @@
 #include "gdal_frmts.h"
 #include "keadataset.h"
 
+CPL_CVSID("$Id: keadriver.cpp 34811 2016-07-28 15:15:05Z goatbar $");
+
 // method to register this driver
 void GDALRegister_KEA()
 {
diff --git a/frmts/kea/keamaskband.cpp b/frmts/kea/keamaskband.cpp
index bd8de99..713dc16 100644
--- a/frmts/kea/keamaskband.cpp
+++ b/frmts/kea/keamaskband.cpp
@@ -1,5 +1,4 @@
 /*
- * $Id: keamaskband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keamaskband.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -30,6 +29,8 @@
 
 #include "keamaskband.h"
 
+CPL_CVSID("$Id: keamaskband.cpp 34811 2016-07-28 15:15:05Z goatbar $");
+
 // constructor
 KEAMaskBand::KEAMaskBand(GDALRasterBand *pParent,
                 kealib::KEAImageIO *pImageIO, int *pRefCount)
diff --git a/frmts/kea/keamaskband.h b/frmts/kea/keamaskband.h
index 65e1bc2..6325f85 100644
--- a/frmts/kea/keamaskband.h
+++ b/frmts/kea/keamaskband.h
@@ -1,5 +1,5 @@
 /*
- * $Id: keamaskband.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: keamaskband.h 36501 2016-11-25 14:09:24Z rouault $
  *  keamaskband.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -46,9 +46,8 @@ public:
 
 protected:
     // we just override these functions from GDALRasterBand
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
-
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 };
 
 #endif //KEAMASKBAND_H
diff --git a/frmts/kea/keaoverview.cpp b/frmts/kea/keaoverview.cpp
index ca3d156..5d891d2 100644
--- a/frmts/kea/keaoverview.cpp
+++ b/frmts/kea/keaoverview.cpp
@@ -1,5 +1,4 @@
 /*
- * $Id: keaoverview.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  keaoverview.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -30,6 +29,8 @@
 
 #include "keaoverview.h"
 
+CPL_CVSID("$Id: keaoverview.cpp 35929 2016-10-25 16:09:00Z goatbar $");
+
 // constructor
 KEAOverview::KEAOverview(KEADataset *pDataset, int nSrcBand, GDALAccess eAccessIn,
                 kealib::KEAImageIO *pImageIO, int *pRefCount,
@@ -44,10 +45,7 @@ KEAOverview::KEAOverview(KEADataset *pDataset, int nSrcBand, GDALAccess eAccessI
     this->nRasterYSize = static_cast<int>(nYSize);
 }
 
-KEAOverview::~KEAOverview()
-{
-
-}
+KEAOverview::~KEAOverview() {}
 
 // overridden implementation - calls readFromOverview instead
 CPLErr KEAOverview::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage )
diff --git a/frmts/kea/keaoverview.h b/frmts/kea/keaoverview.h
index b2b5891..3f85b68 100644
--- a/frmts/kea/keaoverview.h
+++ b/frmts/kea/keaoverview.h
@@ -1,5 +1,5 @@
 /*
- * $Id: keaoverview.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: keaoverview.h 36501 2016-11-25 14:09:24Z rouault $
  *  keaoverview.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -46,17 +46,17 @@ public:
     ~KEAOverview();
 
     // virtual methods for RATs - not implemented for overviews
-    GDALRasterAttributeTable *GetDefaultRAT();
+    GDALRasterAttributeTable *GetDefaultRAT() override;
 
-    CPLErr SetDefaultRAT(const GDALRasterAttributeTable *poRAT);
+    CPLErr SetDefaultRAT(const GDALRasterAttributeTable *poRAT) override;
 
     // note that Color Table stuff implemented in base class
     // so could be some duplication if overview asked for color table
 
 protected:
     // we just override these functions from KEARasterBand
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 };
 
 #endif //KEAOVERVIEW_H
diff --git a/frmts/kea/kearat.cpp b/frmts/kea/kearat.cpp
index 41efa66..bab28c5 100644
--- a/frmts/kea/kearat.cpp
+++ b/frmts/kea/kearat.cpp
@@ -1,5 +1,4 @@
 /*
- * $Id: kearat.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *  kearat.cpp
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -30,7 +29,10 @@
 
 #include "kearat.h"
 
-KEARasterAttributeTable::KEARasterAttributeTable(kealib::KEAAttributeTable *poKEATable)
+CPL_CVSID("$Id: kearat.cpp 37966 2017-04-11 19:34:57Z rouault $");
+
+KEARasterAttributeTable::KEARasterAttributeTable(kealib::KEAAttributeTable *poKEATable,
+                            KEARasterBand *poBand)
 {
     for( size_t nColumnIndex = 0; nColumnIndex < poKEATable->getMaxGlobalColIdx(); nColumnIndex++ )
     {
@@ -47,6 +49,7 @@ KEARasterAttributeTable::KEARasterAttributeTable(kealib::KEAAttributeTable *poKE
         m_aoFields.push_back(sKEAField);
     }
     m_poKEATable = poKEATable;
+    m_poBand = poBand;
 }
 
 KEARasterAttributeTable::~KEARasterAttributeTable()
@@ -181,13 +184,11 @@ GDALDefaultRasterAttributeTable *KEARasterAttributeTable::Clone() const
     return poRAT;
 }
 
-
 int KEARasterAttributeTable::GetColumnCount() const
 {
     return (int)m_aoFields.size();
 }
 
-
 const char *KEARasterAttributeTable::GetNameOfCol(int nCol) const
 {
      if( ( nCol < 0 ) || ( nCol >= (int)m_aoFields.size() ) )
@@ -250,7 +251,6 @@ GDALRATFieldType KEARasterAttributeTable::GetTypeOfCol( int nCol ) const
     return eGDALType;
 }
 
-
 int KEARasterAttributeTable::GetColOfUsage( GDALRATFieldUsage eUsage ) const
 {
     unsigned int i;
@@ -577,7 +577,7 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
             }
             catch(kealib::KEAException &e)
             {
-                fprintf(stderr,"Failed to read/write attribute table: %s %d %d %ld\n", e.what(), iStartRow, iLength, m_poKEATable->getSize() );
+                //fprintf(stderr,"Failed to read/write attribute table: %s %d %d %ld\n", e.what(), iStartRow, iLength, m_poKEATable->getSize() );
                 CPLError( CE_Failure, CPLE_AppDefined, "Failed to read/write attribute table: %s", e.what() );
                 return CE_Failure;
             }
@@ -729,7 +729,6 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
                 return eVal;
             }
 
-
             if( eRWFlag == GF_Read )
             {
                 // convert ints back to strings
@@ -776,7 +775,6 @@ CPLErr KEARasterAttributeTable::ValuesIO(GDALRWFlag eRWFlag, int iField, int iSt
                 }
             }
             CPLFree(padfColData);
-
         }
         break;
         case kealib::kea_att_string:
@@ -909,6 +907,38 @@ CPLErr KEARasterAttributeTable::CreateColumn( const char *pszFieldName,
     return CE_None;
 }
 
+CPLErr KEARasterAttributeTable::SetLinearBinning( double dfRow0Min,
+                                            double dfBinSize )
+{
+    size_t nRows = m_poKEATable->getSize();
+
+    osWorkingResult.Printf( "%.16g", dfRow0Min);
+    m_poBand->SetMetadataItem("STATISTICS_HISTOMIN", osWorkingResult);
+    osWorkingResult.Printf( "%.16g", (nRows - 1) * dfBinSize + dfRow0Min);
+    m_poBand->SetMetadataItem("STATISTICS_HISTOMAX", osWorkingResult);
+    osWorkingResult.Printf( "%lu", (unsigned long)nRows);
+    m_poBand->SetMetadataItem("STATISTICS_HISTONUMBINS", osWorkingResult);
+
+    return CE_None;
+}
+
+int KEARasterAttributeTable::GetLinearBinning( double *pdfRow0Min,
+                                            double *pdfBinSize ) const
+{
+    const char *pszMin = m_poBand->GetMetadataItem("STATISTICS_HISTOMIN");
+    const char *pszMax = m_poBand->GetMetadataItem("STATISTICS_HISTOMAX");
+    const char *pszNumBins = m_poBand->GetMetadataItem("STATISTICS_HISTONUMBINS");
+    if( ( pszMin == NULL ) || ( pszMax == NULL ) || ( pszNumBins == NULL ) )
+    {
+        return FALSE;
+    } 
+    *pdfRow0Min = atof(pszMin);
+    long nRows = atol(pszNumBins);
+    *pdfBinSize = (atof(pszMax) - *pdfRow0Min) / (nRows - 1);
+
+    return TRUE;
+}
+
 CPLXMLNode *KEARasterAttributeTable::Serialize() const
 {
     if( ( GetRowCount() * GetColumnCount() ) > RAT_MAX_ELEM_FOR_CLONE )
diff --git a/frmts/kea/kearat.h b/frmts/kea/kearat.h
index 447d2e9..57c05a4 100644
--- a/frmts/kea/kearat.h
+++ b/frmts/kea/kearat.h
@@ -1,5 +1,5 @@
 /*
- * $Id: kearat.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: kearat.h 37966 2017-04-11 19:34:57Z rouault $
  *  kearat.h
  *
  *  Created by Pete Bunting on 01/08/2012.
@@ -42,44 +42,48 @@ private:
     kealib::KEAAttributeTable *m_poKEATable;
     std::vector<kealib::KEAATTField> m_aoFields;
     CPLString osWorkingResult;
+    KEARasterBand *m_poBand;
 
 public:
-    KEARasterAttributeTable(kealib::KEAAttributeTable *poKEATable);
+    KEARasterAttributeTable(kealib::KEAAttributeTable *poKEATable, KEARasterBand *poBand);
     ~KEARasterAttributeTable();
 
-    GDALDefaultRasterAttributeTable *Clone() const;
+    GDALDefaultRasterAttributeTable *Clone() const override;
 
-    virtual int           GetColumnCount() const;
+    virtual int           GetColumnCount() const override;
 
-    virtual const char   *GetNameOfCol( int ) const;
-    virtual GDALRATFieldUsage GetUsageOfCol( int ) const;
-    virtual GDALRATFieldType GetTypeOfCol( int ) const;
+    virtual const char   *GetNameOfCol( int ) const override;
+    virtual GDALRATFieldUsage GetUsageOfCol( int ) const override;
+    virtual GDALRATFieldType GetTypeOfCol( int ) const override;
 
-    virtual int           GetColOfUsage( GDALRATFieldUsage ) const;
+    virtual int           GetColOfUsage( GDALRATFieldUsage ) const override;
 
-    virtual int           GetRowCount() const;
+    virtual int           GetRowCount() const override;
 
-    virtual const char   *GetValueAsString( int iRow, int iField ) const;
-    virtual int           GetValueAsInt( int iRow, int iField ) const;
-    virtual double        GetValueAsDouble( int iRow, int iField ) const;
+    virtual const char   *GetValueAsString( int iRow, int iField ) const override;
+    virtual int           GetValueAsInt( int iRow, int iField ) const override;
+    virtual double        GetValueAsDouble( int iRow, int iField ) const override;
 
-    virtual void          SetValue( int iRow, int iField, const char *pszValue );
-    virtual void          SetValue( int iRow, int iField, double dfValue);
-    virtual void          SetValue( int iRow, int iField, int nValue );
+    virtual void          SetValue( int iRow, int iField, const char *pszValue ) override;
+    virtual void          SetValue( int iRow, int iField, double dfValue) override;
+    virtual void          SetValue( int iRow, int iField, int nValue ) override;
 
-    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData);
-    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData);
-    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList);
+    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, double *pdfData) override;
+    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, int *pnData) override;
+    virtual CPLErr        ValuesIO(GDALRWFlag eRWFlag, int iField, int iStartRow, int iLength, char **papszStrList) override;
 
-    virtual int           ChangesAreWrittenToFile();
-    virtual void          SetRowCount( int iCount );
+    virtual int           ChangesAreWrittenToFile() override;
+    virtual void          SetRowCount( int iCount ) override;
 
     virtual CPLErr        CreateColumn( const char *pszFieldName,
                                 GDALRATFieldType eFieldType,
-                                GDALRATFieldUsage eFieldUsage );
-
-    virtual CPLXMLNode   *Serialize() const;
+                                GDALRATFieldUsage eFieldUsage ) override;
+    virtual CPLErr        SetLinearBinning( double dfRow0Min,
+                                            double dfBinSize ) override;
+    virtual int           GetLinearBinning( double *pdfRow0Min,
+                                            double *pdfBinSize ) const override;
 
+    virtual CPLXMLNode   *Serialize() const override;
 };
 
 #endif //KEARAT_H
diff --git a/frmts/kea/libkea_headers.h b/frmts/kea/libkea_headers.h
index e373882..17e8d87 100644
--- a/frmts/kea/libkea_headers.h
+++ b/frmts/kea/libkea_headers.h
@@ -53,5 +53,4 @@
 #pragma warning( pop )
 #endif
 
-
 #endif /* GDAL_LIBKEA_HEADERS_H */
diff --git a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
index 4cd6979..caffcc1 100644
--- a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
+++ b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  KmlSuperOverlay
  * Purpose:  Implements write support for KML superoverlay - KMZ.
@@ -28,15 +27,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "kmlsuperoverlaydataset.h"
 
-#include <cmath>   /* fabs */
-#include <cstring> /* strdup */
-#include <iostream>
-#include <sstream>
-#include <math.h>
+#include <cmath>
+#include <cstring>
 #include <algorithm>
 #include <fstream>
+#include <iostream>
+#include <sstream>
 
 #include "cpl_conv.h"
 #include "cpl_error.h"
@@ -47,6 +46,8 @@
 #include "../vrt/gdal_vrt.h"
 #include "../vrt/vrtdataset.h"
 
+CPL_CVSID("$Id: kmlsuperoverlaydataset.cpp 37461 2017-02-26 02:12:35Z goatbar $");
+
 using namespace std;
 
 /************************************************************************/
@@ -68,7 +69,7 @@ static void GenerateTiles(std::string filename,
     GDALDataset* poTmpDataset = NULL;
     GDALRasterBand* alphaBand = NULL;
 
-    GByte* pafScanline = new GByte[dxsize];
+    GByte* pabyScanline = new GByte[dxsize];
     bool* hadnoData = new bool[dxsize];
 
     if (isJpegDriver && bands == 4)
@@ -107,7 +108,7 @@ static void GenerateTiles(std::string filename,
 
             int yOffset = ry + row * rowOffset;
             CPLErr errTest =
-                poBand->RasterIO( GF_Read, rx, yOffset, rxsize, rowOffset, pafScanline, dxsize, 1, GDT_Byte, 0, 0, NULL);
+                poBand->RasterIO( GF_Read, rx, yOffset, rxsize, rowOffset, pabyScanline, dxsize, 1, GDT_Byte, 0, 0, NULL);
 
             const bool bReadFailed = ( errTest == CE_Failure );
             if ( bReadFailed )
@@ -115,7 +116,6 @@ static void GenerateTiles(std::string filename,
                 hasNoData = 1;
             }
 
-
             //fill the true or false for hadnoData array if the source data has nodata value
             if (!isJpegDriver)
             {
@@ -123,7 +123,7 @@ static void GenerateTiles(std::string filename,
                 {
                     for (int j = 0; j < dxsize; j++)
                     {
-                        double v = pafScanline[j];
+                        double v = pabyScanline[j];
                         double tmpv = v;
                         if (isSigned)
                         {
@@ -140,7 +140,7 @@ static void GenerateTiles(std::string filename,
             if (!bReadFailed)
             {
                 GDALRasterBand* poBandtmp = poTmpDataset->GetRasterBand(band);
-                CPL_IGNORE_RET_VAL( poBandtmp->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte,
+                CPL_IGNORE_RET_VAL( poBandtmp->RasterIO(GF_Write, 0, row, dxsize, 1, pabyScanline, dxsize, 1, GDT_Byte,
                                     0, 0, NULL) );
             }
         }
@@ -154,21 +154,21 @@ static void GenerateTiles(std::string filename,
                 {
                     if (hadnoData[i])
                     {
-                        pafScanline[i] = 0;
+                        pabyScanline[i] = 0;
                     }
                     else
                     {
-                        pafScanline[i] = 255;
+                        pabyScanline[i] = 255;
                     }
                 }
 
-                CPL_IGNORE_RET_VAL( alphaBand->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte,
+                CPL_IGNORE_RET_VAL( alphaBand->RasterIO(GF_Write, 0, row, dxsize, 1, pabyScanline, dxsize, 1, GDT_Byte,
                                     0, 0, NULL) );
             }
         }
     }
 
-    delete [] pafScanline;
+    delete [] pabyScanline;
     delete [] hadnoData;
 
     CPLString osOpenAfterCopy = CPLGetConfigOption("GDAL_OPEN_AFTER_COPY", "");
@@ -177,7 +177,7 @@ static void GenerateTiles(std::string filename,
     char** papszOptions = CSLAddNameValue(NULL, "QUIET_DELETE_ON_CREATE_COPY", "NO");
     GDALDataset* outDs = poOutputTileDriver->CreateCopy(filename.c_str(), poTmpDataset, FALSE, papszOptions, NULL, NULL);
     CSLDestroy(papszOptions);
-    CPLSetThreadLocalConfigOption("GDAL_OPEN_AFTER_COPY", osOpenAfterCopy.size() ? osOpenAfterCopy.c_str() : NULL);
+    CPLSetThreadLocalConfigOption("GDAL_OPEN_AFTER_COPY", !osOpenAfterCopy.empty() ? osOpenAfterCopy.c_str() : NULL);
 
     GDALClose(poTmpDataset);
     if (outDs)
@@ -283,7 +283,8 @@ int  GenerateChildKml(std::string filename,
                       std::string fileExt,
                       bool fixAntiMeridian,
                       const char* pszAltitude,
-                      const char* pszAltitudeMode)
+                      const char* pszAltitudeMode,
+                      std::vector<std::pair<std::pair<int,int>,bool> > childTiles)
 {
     double tnorth = south + zoomypixel *((iy + 1)*dysize);
     double tsouth = south + zoomypixel *(iy*dysize);
@@ -349,6 +350,20 @@ int  GenerateChildKml(std::string filename,
             ychildern.push_back(iy*2+1);
         }
         maxLodPix = 2048;
+
+        bool hasChildKML = false;
+        for ( std::vector<std::pair<std::pair<int,int>,bool> >::iterator it=
+                            childTiles.begin() ; it < childTiles.end(); ++it )
+        {
+            if ((*it).second) {
+                hasChildKML = true;
+                break;
+            }
+        }
+        if (!hasChildKML){
+            // no child KML files, so don't expire this one at any zoom.
+            maxLodPix = -1;
+        }
     }
 
     VSILFILE* fp = VSIFOpenL(filename.c_str(), "wb");
@@ -430,50 +445,48 @@ int  GenerateChildKml(std::string filename,
     }
     VSIFPrintfL(fp, "\t\t</GroundOverlay>\n");
 
-    for (unsigned int i = 0; i < xchildren.size(); i++)
+    for ( std::vector<std::pair<std::pair<int,int>,bool> >::iterator it=
+                            childTiles.begin() ; it < childTiles.end(); ++it )
     {
-        int cx = xchildren[i];
-        for (unsigned int j = 0; j < ychildern.size(); j++)
-        {
-            int cy = ychildern[j];
+        int cx = (*it).first.first;
+        int cy = (*it).first.second;
 
-            double cnorth = south + zoomypixel/2 *((cy + 1)*dysize);
-            double csouth = south + zoomypixel/2 *(cy*dysize);
-            double ceast = west + zoomxpixel/2*((cx+1)*dxsize);
-            double cwest = west + zoomxpixel/2*cx*dxsize;
+        double cnorth = south + zoomypixel/2 *((cy + 1)*dysize);
+        double csouth = south + zoomypixel/2 *(cy*dysize);
+        double ceast = west + zoomxpixel/2*((cx+1)*dxsize);
+        double cwest = west + zoomxpixel/2*cx*dxsize;
 
-            if (poTransform)
-            {
-                poTransform->Transform(1, &cwest, &csouth);
-                poTransform->Transform(1, &ceast, &cnorth);
-            }
-
-            if ( fixAntiMeridian && ceast < cwest )
-            {
-                ceast += 360;
-            }
+        if (poTransform)
+        {
+            poTransform->Transform(1, &cwest, &csouth);
+            poTransform->Transform(1, &ceast, &cnorth);
+        }
 
-            VSIFPrintfL(fp, "\t\t<NetworkLink>\n");
-            VSIFPrintfL(fp, "\t\t\t<name>%d/%d/%d%s</name>\n", zoom+1, cx, cy, fileExt.c_str());
-            VSIFPrintfL(fp, "\t\t\t<Region>\n");
-            VSIFPrintfL(fp, "\t\t\t\t<LatLonAltBox>\n");
-            VSIFPrintfL(fp, "\t\t\t\t\t<north>%f</north>\n", cnorth);
-            VSIFPrintfL(fp, "\t\t\t\t\t<south>%f</south>\n", csouth);
-            VSIFPrintfL(fp, "\t\t\t\t\t<east>%f</east>\n", ceast);
-            VSIFPrintfL(fp, "\t\t\t\t\t<west>%f</west>\n", cwest);
-            VSIFPrintfL(fp, "\t\t\t\t</LatLonAltBox>\n");
-            VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
-            VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>128</minLodPixels>\n");
-            VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
-            VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
-            VSIFPrintfL(fp, "\t\t\t</Region>\n");
-            VSIFPrintfL(fp, "\t\t\t<Link>\n");
-            VSIFPrintfL(fp, "\t\t\t\t<href>../../%d/%d/%d.kml</href>\n", zoom+1, cx, cy);
-            VSIFPrintfL(fp, "\t\t\t\t<viewRefreshMode>onRegion</viewRefreshMode>\n");
-            VSIFPrintfL(fp, "\t\t\t\t<viewFormat/>\n");
-            VSIFPrintfL(fp, "\t\t\t</Link>\n");
-            VSIFPrintfL(fp, "\t\t</NetworkLink>\n");
+        if ( fixAntiMeridian && ceast < cwest )
+        {
+            ceast += 360;
         }
+
+        VSIFPrintfL(fp, "\t\t<NetworkLink>\n");
+        VSIFPrintfL(fp, "\t\t\t<name>%d/%d/%d%s</name>\n", zoom+1, cx, cy, fileExt.c_str());
+        VSIFPrintfL(fp, "\t\t\t<Region>\n");
+        VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
+        VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>128</minLodPixels>\n");
+        VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
+        VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
+        VSIFPrintfL(fp, "\t\t\t\t<LatLonAltBox>\n");
+        VSIFPrintfL(fp, "\t\t\t\t\t<north>%f</north>\n", cnorth);
+        VSIFPrintfL(fp, "\t\t\t\t\t<south>%f</south>\n", csouth);
+        VSIFPrintfL(fp, "\t\t\t\t\t<east>%f</east>\n", ceast);
+        VSIFPrintfL(fp, "\t\t\t\t\t<west>%f</west>\n", cwest);
+        VSIFPrintfL(fp, "\t\t\t\t</LatLonAltBox>\n");
+        VSIFPrintfL(fp, "\t\t\t</Region>\n");
+        VSIFPrintfL(fp, "\t\t\t<Link>\n");
+        VSIFPrintfL(fp, "\t\t\t\t<href>../../%d/%d/%d.kml</href>\n", zoom+1, cx, cy);
+        VSIFPrintfL(fp, "\t\t\t\t<viewRefreshMode>onRegion</viewRefreshMode>\n");
+        VSIFPrintfL(fp, "\t\t\t\t<viewFormat/>\n");
+        VSIFPrintfL(fp, "\t\t\t</Link>\n");
+        VSIFPrintfL(fp, "\t\t</NetworkLink>\n");
     }
 
     VSIFPrintfL(fp, "\t</Document>\n");
@@ -484,6 +497,78 @@ int  GenerateChildKml(std::string filename,
 }
 
 /************************************************************************/
+/*                         DetectTransparency()                         */
+/************************************************************************/
+int KmlSuperOverlayReadDataset::DetectTransparency( int rxsize, int rysize,
+                                                    int rx, int ry,
+                                                    int dxsize, int dysize,
+                                                    GDALDataset* poSrcDs )
+{
+    int bands = poSrcDs->GetRasterCount();
+    int rowOffset = rysize/dysize;
+    int loopCount = rysize/rowOffset;
+    int hasNoData = 0;
+    GByte* pabyScanline = new GByte[dxsize];
+
+    int flags = 0;
+    for (int band = 1; band <= bands; band++)
+    {
+        GDALRasterBand* poBand = poSrcDs->GetRasterBand(band);
+        int noDataValue = static_cast<int>(poBand->GetNoDataValue(&hasNoData));
+
+        if (band < 4 && hasNoData) {
+            for (int row = 0; row < loopCount; row++)
+            {
+                int yOffset = ry + row * rowOffset;
+                CPL_IGNORE_RET_VAL(
+                    poBand->RasterIO( GF_Read,
+                                      rx, yOffset, rxsize, rowOffset,
+                                      pabyScanline, dxsize, 1,
+                                      GDT_Byte, 0, 0, NULL) );
+                for (int i = 0; i < dxsize; i++)
+                {
+                    if (pabyScanline[i] == noDataValue)
+                    {
+                        flags |= KMLSO_ContainsTransparentPixels;
+                    } else {
+                        flags |= KMLSO_ContainsOpaquePixels;
+                    }
+                }
+                // shortcut - if there are both types of pixels, flags is as
+                // full as it's going to get.
+                // so no point continuing, skip to the next band
+                if ((flags & KMLSO_ContainsTransparentPixels) &&
+                    (flags & KMLSO_ContainsOpaquePixels)) {
+                    break;
+                }
+            }
+        } else if (band == 4) {
+            for (int row = 0; row < loopCount; row++)
+            {
+                int yOffset = ry + row * rowOffset;
+                CPL_IGNORE_RET_VAL(
+                    poBand->RasterIO( GF_Read, rx, yOffset, rxsize, rowOffset,
+                                      pabyScanline, dxsize, 1,
+                                      GDT_Byte, 0, 0, NULL) );
+                for (int i = 0; i < dxsize; i++)
+                {
+                    if (pabyScanline[i] == 255)
+                    {
+                        flags |= KMLSO_ContainsOpaquePixels;
+                    } else if (pabyScanline[i] == 0) {
+                        flags |= KMLSO_ContainsTransparentPixels;
+                    } else {
+                        flags |= KMLSO_ContainsPartiallyTransparentPixels;
+                    }
+                }
+            }
+        }
+    }
+    delete[] pabyScanline;
+    return flags;
+}
+
+/************************************************************************/
 /*                           CreateCopy()                               */
 /************************************************************************/
 
@@ -556,18 +641,33 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
     }
 
     GDALDriver* poOutputTileDriver = NULL;
-    bool isJpegDriver = true;
+    GDALDriver* poJpegOutputTileDriver = NULL;
+    GDALDriver* poPngOutputTileDriver = NULL;
+    bool isAutoDriver = false;
+    bool isJpegDriver = false;
 
     const char* pszFormat = CSLFetchNameValueDef(papszOptions, "FORMAT", "JPEG");
-    if (EQUAL(pszFormat, "PNG"))
+    if (EQUAL(pszFormat, "AUTO"))
+    {
+        isAutoDriver = true;
+        poJpegOutputTileDriver = GetGDALDriverManager()->GetDriverByName("JPEG");
+        poPngOutputTileDriver = GetGDALDriverManager()->GetDriverByName("PNG");
+    }
+    else
     {
-        isJpegDriver = false;
+        poOutputTileDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
+        if (EQUAL(pszFormat, "JPEG"))
+        {
+            isJpegDriver = true;
+        }
     }
 
     GDALDriver* poMemDriver = GetGDALDriverManager()->GetDriverByName("MEM");
-    poOutputTileDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
 
-    if( poMemDriver == NULL || poOutputTileDriver == NULL)
+    if ( poMemDriver == NULL
+         || ( !isAutoDriver && poOutputTileDriver == NULL )
+         || ( isAutoDriver && (poJpegOutputTileDriver == NULL || poPngOutputTileDriver == NULL) )
+    )
     {
         CPLError( CE_Failure, CPLE_None,
                   "Image export driver was not found.." );
@@ -587,7 +687,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
     double east = 0.0;
     double west = 0.0;
 
-    double	adfGeoTransform[6];
+    double adfGeoTransform[6];
 
     if( poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None )
     {
@@ -621,7 +721,7 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
         }
     }
 
-    bool fixAntiMeridian = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "FIX_ANTIMERIDIAN", FALSE ));
+    const bool fixAntiMeridian = CPLFetchBool( papszOptions, "FIX_ANTIMERIDIAN", false );
     if ( fixAntiMeridian && east < west )
     {
         east += 360;
@@ -745,6 +845,11 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
         nTotalTiles += xloop * yloop;
     }
 
+    // {(x, y): [((childx, childy), hasChildKML), ...], ...}
+    std::map<std::pair<int,int>,std::vector<std::pair<std::pair<int,int>,bool> > > childTiles;
+    std::map<std::pair<int,int>,std::vector<std::pair<std::pair<int,int>,bool> > > currentTiles;
+    std::pair<int,int> childXYKey;
+    std::pair<int,int> parentXYKey;
     for (zoom = maxzoom; zoom >= 0; --zoom)
     {
         int rmaxxsize = tilexsize * (1 << (maxzoom-zoom));
@@ -786,6 +891,25 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
                 std::stringstream iyStr;
                 iyStr << iy;
 
+                if (isAutoDriver)
+                {
+                    int flags = KmlSuperOverlayReadDataset::DetectTransparency(rxsize, rysize, rx, ry, dxsize, dysize, poSrcDS);
+                    if ( flags & (KmlSuperOverlayReadDataset::KMLSO_ContainsPartiallyTransparentPixels | KmlSuperOverlayReadDataset::KMLSO_ContainsTransparentPixels) )
+                    {
+                        if (!(flags & (KmlSuperOverlayReadDataset::KMLSO_ContainsPartiallyTransparentPixels | KmlSuperOverlayReadDataset::KMLSO_ContainsOpaquePixels))) {
+                            // don't bother creating empty tiles
+                            continue;
+                        }
+                        poOutputTileDriver = poPngOutputTileDriver;
+                        isJpegDriver = false;
+                    }
+                    else
+                    {
+                        poOutputTileDriver = poJpegOutputTileDriver;
+                        isJpegDriver = true;
+                    }
+                }
+
                 std::string fileExt = ".jpg";
                 if (isJpegDriver == false)
                 {
@@ -818,15 +942,26 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
                     zoomypix = 1;
                 }
 
+                childXYKey = std::make_pair(ix, iy);
+                parentXYKey = std::make_pair(ix / 2, iy / 2);
+
+                // only create child KML if there are child tiles
+                bool hasChildKML = !childTiles[childXYKey].empty();
+                if (!currentTiles.count(parentXYKey)) {
+                    currentTiles[parentXYKey] = std::vector<std::pair<std::pair<int,int>,bool> >();
+                }
+                currentTiles[parentXYKey].push_back(std::make_pair(std::make_pair(ix, iy), hasChildKML));
                 GenerateChildKml(childKmlfile, zoom, ix, iy, zoomxpix, zoomypix,
                                  dxsize, dysize, tmpSouth, adfGeoTransform[0],
                                  xsize, ysize, maxzoom, poTransform, fileExt, fixAntiMeridian,
-                                 pszAltitude, pszAltitudeMode);
+                                 pszAltitude, pszAltitudeMode, childTiles[childXYKey]);
 
                 nTileCount ++;
                 pfnProgress(1.0 * nTileCount / nTotalTiles, "", pProgressData);
             }
         }
+        childTiles = currentTiles;
+        currentTiles.clear();
     }
 
     OGRCoordinateTransformation::DestroyCT( poTransform );
@@ -844,7 +979,6 @@ GDALDataset *KmlSuperOverlayCreateCopy( const char * pszFilename,
     return poDS;
 }
 
-
 /************************************************************************/
 /*                            KMLRemoveSlash()                          */
 /************************************************************************/
@@ -876,27 +1010,24 @@ static CPLString KMLRemoveSlash(const char* pszPathIn)
 /*                      KmlSuperOverlayReadDataset()                    */
 /************************************************************************/
 
-KmlSuperOverlayReadDataset::KmlSuperOverlayReadDataset()
-
+KmlSuperOverlayReadDataset::KmlSuperOverlayReadDataset() :
+    nFactor(1),
+    psRoot(NULL),
+    psDocument(NULL),
+    poDSIcon(NULL),
+    nOverviewCount(0),
+    papoOverviewDS(NULL),
+    bIsOvr(FALSE),
+    poParent(NULL),
+    psFirstLink(NULL),
+    psLastLink(NULL)
 {
-    nFactor = 1;
-    psRoot = NULL;
-    psDocument = NULL;
-    poDSIcon = NULL;
-    adfGeoTransform[0] = 0;
-    adfGeoTransform[1] = 1;
-    adfGeoTransform[2] = 0;
-    adfGeoTransform[3] = 0;
-    adfGeoTransform[4] = 0;
-    adfGeoTransform[5] = 1;
-
-    nOverviewCount = 0;
-    papoOverviewDS = NULL;
-    bIsOvr = FALSE;
-
-    poParent = NULL;
-    psFirstLink = NULL;
-    psLastLink = NULL;
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 1.0;
 }
 
 /************************************************************************/
@@ -981,8 +1112,8 @@ CPLErr KmlSuperOverlayReadDataset::GetGeoTransform( double * padfGeoTransform )
 /*                        KmlSuperOverlayRasterBand()                   */
 /************************************************************************/
 
-KmlSuperOverlayRasterBand::KmlSuperOverlayRasterBand(KmlSuperOverlayReadDataset* poDSIn,
-                                                     int)
+KmlSuperOverlayRasterBand::KmlSuperOverlayRasterBand(
+    KmlSuperOverlayReadDataset* poDSIn, int /* nBand*/ )
 {
     nRasterXSize = poDSIn->nRasterXSize;
     nRasterYSize = poDSIn->nRasterYSize;
@@ -1228,7 +1359,8 @@ CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
                                 else
                                 {
                                     CPLAssert(psLinkDS == poRoot->psFirstLink);
-                                    poRoot->psFirstLink = poRoot->psLastLink = NULL;
+                                    poRoot->psFirstLink = NULL;
+                                    poRoot->psLastLink = NULL;
                                 }
                             }
                             else
@@ -1469,7 +1601,6 @@ CPLErr KmlSuperOverlayReadDataset::IRasterIO( GDALRWFlag eRWFlag,
     psExtraArg->pProgressData = pProgressDataGlobal;
 
     return eErr;
-
 }
 
 /************************************************************************/
@@ -1521,7 +1652,6 @@ int KmlSuperOverlayFindRegionStartInternal(CPLXMLNode* psNode,
     return FALSE;
 }
 
-
 static
 int KmlSuperOverlayFindRegionStart(CPLXMLNode* psNode,
                                    CPLXMLNode** ppsRegion,
@@ -1573,6 +1703,12 @@ int KmlSuperOverlayReadDataset::Identify(GDALOpenInfo * poOpenInfo)
             strstr((const char*)poOpenInfo->pabyHeader, "<GroundOverlay>") != NULL )
             return TRUE;
 
+        if( strstr((const char*)poOpenInfo->pabyHeader, "<GroundOverlay>") != NULL &&
+            strstr((const char*)poOpenInfo->pabyHeader, "<Icon>") != NULL &&
+            strstr((const char*)poOpenInfo->pabyHeader, "<href>") != NULL &&
+            strstr((const char*)poOpenInfo->pabyHeader, "<LatLonBox>") != NULL )
+            return TRUE;
+
         if( i == 0 && !poOpenInfo->TryToIngest(1024*10) )
             return FALSE;
     }
@@ -1650,7 +1786,6 @@ GDALDataset* KmlSuperOverlayLoadIcon(const char* pszBaseFilename, const char* ps
     return poDSIcon;
 }
 
-
 /************************************************************************/
 /*                    KmlSuperOverlayComputeDepth()                     */
 /************************************************************************/
@@ -1676,7 +1811,7 @@ static void KmlSuperOverlayComputeDepth(CPLString osFilename,
                     osSubFilename = CPLSPrintf("/vsicurl_streaming/%s", pszHref);
                 else
                 {
-                    osSubFilename = CPLFormFilename(CPLGetPath(osFilename), pszHref, NULL),
+                    osSubFilename = CPLFormFilename(CPLGetPath(osFilename), pszHref, NULL);
                     osSubFilename = KMLRemoveSlash(osSubFilename);
                 }
 
@@ -1751,19 +1886,19 @@ class KmlSingleDocRasterDataset: public GDALDataset
         int bLockOtherBands;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
     public:
                 KmlSingleDocRasterDataset();
-                ~KmlSingleDocRasterDataset();
+        virtual ~KmlSingleDocRasterDataset();
 
-        virtual CPLErr GetGeoTransform( double * padfGeoTransform )
+        virtual CPLErr GetGeoTransform( double * padfGeoTransform ) override
         {
             memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
             return CE_None;
         }
 
-        virtual const char *GetProjectionRef() { return SRS_WKT_WGS84; }
+        virtual const char *GetProjectionRef() override { return SRS_WKT_WGS84; }
 
         void BuildOverviews();
 
@@ -1782,11 +1917,11 @@ class KmlSingleDocRasterRasterBand: public GDALRasterBand
         KmlSingleDocRasterRasterBand(KmlSingleDocRasterDataset* poDS,
                                      int nBand);
 
-        virtual CPLErr IReadBlock( int, int, void * );
-        virtual GDALColorInterp GetColorInterpretation();
+        virtual CPLErr IReadBlock( int, int, void * ) override;
+        virtual GDALColorInterp GetColorInterpretation() override;
 
-        virtual int GetOverviewCount();
-        virtual GDALRasterBand *GetOverview(int);
+        virtual int GetOverviewCount() override;
+        virtual GDALRasterBand *GetOverview(int) override;
 };
 
 /************************************************************************/
@@ -1800,6 +1935,8 @@ KmlSingleDocRasterDataset::KmlSingleDocRasterDataset()
     nTileSize = 0;
     bHasBuiltOverviews = FALSE;
     bLockOtherBands = FALSE;
+    memset( adfGlobalExtents, 0, sizeof(adfGlobalExtents) );
+    memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
 }
 
 /************************************************************************/
@@ -1825,7 +1962,7 @@ int KmlSingleDocRasterDataset::CloseDependentDatasets()
         GDALClose((GDALDatasetH) poCurTileDS);
         poCurTileDS = NULL;
     }
-    if( apoOverviews.size() > 0 )
+    if( !apoOverviews.empty() )
     {
         bRet = TRUE;
         for(size_t i = 0; i < apoOverviews.size(); i++)
@@ -1903,10 +2040,14 @@ void KmlSingleDocRasterDataset::BuildOverviews()
     for(int k = 2; k <= (int)aosDescs.size(); k++)
     {
         const KmlSingleDocRasterTilesDesc& oDesc = aosDescs[aosDescs.size()-k];
-        int nXSize = 0, nYSize = 0, nTileBands = 0, bHasCT = FALSE;
-        if( !KmlSingleDocGetDimensions(osDirname, oDesc, (int)aosDescs.size() - k  + 1,
-                                       nTileSize,
-                                       nXSize, nYSize, nTileBands, bHasCT) )
+        int nXSize = 0;
+        int nYSize = 0;
+        int nTileBands = 0;
+        int bHasCT = FALSE;
+        if( !KmlSingleDocGetDimensions(
+                osDirname, oDesc, (int)aosDescs.size() - k  + 1,
+                nTileSize,
+                nXSize, nYSize, nTileBands, bHasCT) )
         {
             break;
         }
@@ -1936,11 +2077,11 @@ void KmlSingleDocRasterDataset::BuildOverviews()
 /*                      KmlSingleDocRasterRasterBand()                  */
 /************************************************************************/
 
-KmlSingleDocRasterRasterBand::KmlSingleDocRasterRasterBand(KmlSingleDocRasterDataset* poDSIn,
-                                                           int nBandIn)
+KmlSingleDocRasterRasterBand::KmlSingleDocRasterRasterBand(
+    KmlSingleDocRasterDataset* poDSIn, int nBandIn )
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     nBlockXSize = poDSIn->nTileSize;
     nBlockYSize = poDSIn->nTileSize;
     eDataType = GDT_Byte;
@@ -2212,7 +2353,7 @@ GDALDataset* KmlSingleDocRasterDataset::Open(const char* pszFilename,
     std::vector<KmlSingleDocRasterTilesDesc> aosDescs;
     CPLString osDirname = CPLGetPath(osFilename);
     KmlSingleDocCollectTiles(psRootFolder, aosDescs, osDirname);
-    if( aosDescs.size() == 0 )
+    if( aosDescs.empty() )
         return NULL;
     int k;
     for(k = 0; k < (int)aosDescs.size(); k++)
@@ -2222,7 +2363,7 @@ GDALDataset* KmlSingleDocRasterDataset::Open(const char* pszFilename,
     }
 
     const char* pszImageFilename = CPLFormFilename( osDirname,
-            CPLSPrintf("kml_image_L%d_%d_%d", (int)aosDescs.size(), 0, 0), aosDescs[aosDescs.size()-1].szExtI);
+            CPLSPrintf("kml_image_L%d_%d_%d", (int)aosDescs.size(), 0, 0), aosDescs.back().szExtI);
     GDALDataset* poImageDS = (GDALDataset*) GDALOpen(pszImageFilename, GA_ReadOnly);
     if( poImageDS == NULL )
     {
@@ -2235,10 +2376,14 @@ GDALDataset* KmlSingleDocRasterDataset::Open(const char* pszFilename,
     }
     GDALClose( (GDALDatasetH) poImageDS) ;
 
-    const KmlSingleDocRasterTilesDesc& oDesc = aosDescs[aosDescs.size()-1];
-    int nXSize = 0, nYSize = 0, nBands = 0, bHasCT = FALSE;
-    if( !KmlSingleDocGetDimensions(osDirname, oDesc, (int)aosDescs.size(), nTileSize,
-                                   nXSize, nYSize, nBands, bHasCT) )
+    const KmlSingleDocRasterTilesDesc& oDesc = aosDescs.back();
+    int nXSize = 0;
+    int nYSize = 0;
+    int nBands = 0;
+    int bHasCT = FALSE;
+    if( !KmlSingleDocGetDimensions(
+            osDirname, oDesc, (int)aosDescs.size(), nTileSize,
+            nXSize, nYSize, nBands, bHasCT) )
     {
         return NULL;
     }
@@ -2268,6 +2413,83 @@ GDALDataset* KmlSingleDocRasterDataset::Open(const char* pszFilename,
 }
 
 /************************************************************************/
+/*                   KmlSingleOverlayRasterDataset                      */
+/************************************************************************/
+
+class KmlSingleOverlayRasterDataset: public VRTDataset
+{
+    public:
+                KmlSingleOverlayRasterDataset(int nXSize, int nYSize) :
+                        VRTDataset(nXSize, nYSize) {}
+
+        static GDALDataset* Open(const char* pszFilename,
+                                 const CPLString& osFilename,
+                                 CPLXMLNode* psRoot);
+};
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+/* Read raster with a structure like https://trac.osgeo.org/gdal/ticket/6712 */
+/* i.e. made of a doc.kml that has a single GroundOverlay */
+GDALDataset* KmlSingleOverlayRasterDataset::Open(const char* pszFilename,
+                                                 const CPLString& osFilename,
+                                                 CPLXMLNode* psRoot)
+{
+    CPLXMLNode* psGO = CPLGetXMLNode(psRoot, "=kml.GroundOverlay");
+    if( psGO == NULL )
+        return NULL;
+    const char* pszHref = CPLGetXMLValue(psGO, "Icon.href", NULL);
+    if( pszHref == NULL )
+        return NULL;
+    double adfExtents[4] = { 0 };
+    if( !KmlSuperOverlayGetBoundingBox(psGO, adfExtents) )
+        return NULL;
+    const char* pszImageFilename = CPLFormFilename(
+                                        CPLGetPath(osFilename), pszHref, NULL );
+    GDALDataset* poImageDS = reinterpret_cast<GDALDataset*>(
+                                GDALOpenShared(pszImageFilename, GA_ReadOnly ));
+    if( poImageDS == NULL )
+        return NULL;
+
+    KmlSingleOverlayRasterDataset* poDS = new KmlSingleOverlayRasterDataset(
+            poImageDS->GetRasterXSize(), poImageDS->GetRasterYSize() );
+    for( int i = 1; i <= poImageDS->GetRasterCount(); ++i )
+    {
+        VRTAddBand( reinterpret_cast<VRTDatasetH> (poDS), GDT_Byte, NULL );
+
+        VRTAddSimpleSource(
+            reinterpret_cast<VRTSourcedRasterBandH>( poDS->GetRasterBand(i) ),
+            reinterpret_cast<GDALRasterBandH>( poImageDS->GetRasterBand(i) ),
+            0, 0,
+            poImageDS->GetRasterXSize(),
+            poImageDS->GetRasterYSize(),
+            0, 0,
+            poImageDS->GetRasterXSize(),
+            poImageDS->GetRasterYSize(),
+            NULL, VRT_NODATA_UNSET);
+
+        poDS->GetRasterBand(i)->SetColorInterpretation(
+                    poImageDS->GetRasterBand(i)->GetColorInterpretation() );
+    }
+    poImageDS->Dereference();
+    double adfGeoTransform[6] = {
+        adfExtents[0],
+        (adfExtents[2] - adfExtents[0]) / poImageDS->GetRasterXSize(),
+        0,
+        adfExtents[3],
+        0,
+        -(adfExtents[3] - adfExtents[1]) / poImageDS->GetRasterYSize() };
+    poDS->SetGeoTransform( adfGeoTransform );
+    poDS->SetProjection( SRS_WKT_WGS84 );
+    poDS->SetWritable( false );
+    poDS->SetDescription( pszFilename );
+
+    return poDS;
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
@@ -2327,6 +2549,15 @@ GDALDataset *KmlSuperOverlayReadDataset::Open(const char* pszFilename,
         return psSingleDocDS;
     }
 
+    GDALDataset* psSingleOverlayDS = KmlSingleOverlayRasterDataset::Open(pszFilename,
+                                                                 osFilename,
+                                                                 psNode);
+    if( psSingleOverlayDS != NULL )
+    {
+        CPLDestroyXMLNode(psNode);
+        return psSingleOverlayDS;
+    }
+
     CPLXMLNode* psRegion = NULL;
     CPLXMLNode* psDocument = NULL;
     CPLXMLNode* psGroundOverlay = NULL;
@@ -2381,11 +2612,11 @@ GDALDataset *KmlSuperOverlayReadDataset::Open(const char* pszFilename,
         {
             poDS->SetDescription(pszFilename);
 
-            if( osOverlayName.size() )
+            if( !osOverlayName.empty() )
             {
                 poDS->SetMetadataItem( "NAME", osOverlayName);
             }
-            if( osOverlayDescription.size() )
+            if( !osOverlayDescription.empty() )
             {
                 poDS->SetMetadataItem( "DESCRIPTION", osOverlayDescription);
             }
@@ -2519,6 +2750,7 @@ void CPL_DLL GDALRegister_KMLSUPEROVERLAY()
 "   <Option name='FORMAT' type='string-select' default='JPEG' description='Format of the tiles'>"
 "       <Value>PNG</Value>"
 "       <Value>JPEG</Value>"
+"       <Value>AUTO</Value>"
 "   </Option>"
 "   <Option name='FIX_ANTIMERIDIAN' type='boolean' description='Fix for images crossing the antimeridian causing errors in Google Earth' />"
 "</CreationOptionList>" );
diff --git a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h
index b5c0d80..1bf970b 100644
--- a/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h
+++ b/frmts/kmlsuperoverlay/kmlsuperoverlaydataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlsuperoverlaydataset.h
+ * $Id: kmlsuperoverlaydataset.h 37396 2017-02-17 09:49:36Z rouault $
  *
  * Project:  KmlSuperOverlay
  * Purpose:  Implements write support for KML superoverlay - KMZ.
@@ -31,14 +31,11 @@
 #ifndef KMLSUPEROVERLAYDATASET_H_INCLUDED
 #define KMLSUPEROVERLAYDATASET_H_INCLUDED
 
-#include "gdal_pam.h"
-#include "gdal_priv.h"
-#include "cpl_minixml.h"
 #include <map>
 
-CPL_C_START
-void CPL_DLL GDALRegister_KMLSUPEROVERLAY();
-CPL_C_END
+#include "cpl_minixml.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
 
 /************************************************************************/
 /*                    KmlSuperOverlayReadDataset                        */
@@ -78,7 +75,7 @@ class KmlSuperOverlayReadDataset : public GDALDataset
     LinkedDataset      *psLastLink;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
   public:
                   KmlSuperOverlayReadDataset();
@@ -87,9 +84,15 @@ class KmlSuperOverlayReadDataset : public GDALDataset
     static int          Identify(GDALOpenInfo *);
     static GDALDataset *Open(const char* pszFilename, KmlSuperOverlayReadDataset* poParent = NULL, int nRec = 0);
     static GDALDataset *Open(GDALOpenInfo *);
+ 
+    static const int KMLSO_ContainsOpaquePixels = 0x1;
+    static const int KMLSO_ContainsTransparentPixels = 0x2;
+    static const int KMLSO_ContainsPartiallyTransparentPixels = 0x4;
+
+    static int DetectTransparency( int rxsize, int rysize, int rx, int ry, int dxsize, int dysize, GDALDataset* poSrcDs );
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char *GetProjectionRef();
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char *GetProjectionRef() override;
 
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
@@ -98,7 +101,7 @@ class KmlSuperOverlayReadDataset : public GDALDataset
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg) override;
 };
 
 /************************************************************************/
@@ -108,18 +111,19 @@ class KmlSuperOverlayReadDataset : public GDALDataset
 class KmlSuperOverlayRasterBand: public GDALRasterBand
 {
     public:
-                    KmlSuperOverlayRasterBand(KmlSuperOverlayReadDataset* poDS, int nBand);
+                    KmlSuperOverlayRasterBand( KmlSuperOverlayReadDataset* poDS,
+                                               int nBand );
   protected:
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
-    virtual GDALColorInterp GetColorInterpretation();
+                              GDALRasterIOExtraArg* psExtraArg) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 
-    virtual int GetOverviewCount();
-    virtual GDALRasterBand *GetOverview(int);
+    virtual int GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview(int) override;
 };
 
 #endif /* ndef KMLSUPEROVERLAYDATASET_H_INCLUDED */
diff --git a/frmts/l1b/l1bdataset.cpp b/frmts/l1b/l1bdataset.cpp
index e246f6e..2719ce3 100644
--- a/frmts/l1b/l1bdataset.cpp
+++ b/frmts/l1b/l1bdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: l1bdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  NOAA Polar Orbiter Level 1b Dataset Reader (AVHRR)
  * Purpose:  Can read NOAA-9(F)-NOAA-17(M) AVHRR datasets
@@ -39,7 +38,9 @@
 #include "gdal_pam.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: l1bdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: l1bdataset.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 typedef enum {                  // File formats
     L1B_NONE,           // Not a L1B format
@@ -195,10 +196,13 @@ class TimeCode {
     long        lYear;
     long        lDay;
     long        lMillisecond;
-    char        pszString[L1B_TIMECODE_LENGTH];
+    char        szString[L1B_TIMECODE_LENGTH];
 
   public:
-    TimeCode() : lYear(0), lDay(0), lMillisecond(0) {}
+    TimeCode() : lYear(0), lDay(0), lMillisecond(0)
+    {
+        memset( szString, 0, sizeof(szString) );
+    }
 
     void SetYear(long year)
     {
@@ -217,10 +221,10 @@ class TimeCode {
     long GetMillisecond() { return lMillisecond; }
     char* PrintTime()
     {
-        snprintf(pszString, L1B_TIMECODE_LENGTH,
+        snprintf(szString, L1B_TIMECODE_LENGTH,
                  "year: %ld, day: %ld, millisecond: %ld",
                  lYear, lDay, lMillisecond);
-        return pszString;
+        return szString;
     }
 };
 #undef L1B_TIMECODE_LENGTH
@@ -265,7 +269,9 @@ class L1BDataset : public GDALPamDataset
     int         iGCPCodeOffset;
     int         iCLAVRStart;
     int         nGCPsPerLine;
-    int         eLocationIndicator, iGCPStart, iGCPStep;
+    int         eLocationIndicator;
+    int         iGCPStart;
+    int         iGCPStep;
 
     L1BFileFormat eL1BFormat;
     int         nBufferSize;
@@ -284,7 +290,6 @@ class L1BDataset : public GDALPamDataset
 
     VSILFILE   *fp;
 
-    int         bFetchGeolocation;
     int         bGuessDataFormat;
 
     int         bByteSwap;
@@ -294,7 +299,7 @@ class L1BDataset : public GDALPamDataset
 
     void        ProcessRecordHeaders();
     int         FetchGCPs( GDAL_GCP *, GByte *, int );
-    void        FetchNOAA9TimeCode(TimeCode *, const GByte *, int *);
+    static void        FetchNOAA9TimeCode(TimeCode *, const GByte *, int *);
     void        FetchNOAA15TimeCode(TimeCode *, const GByte *, int *);
     void        FetchTimeCode( TimeCode *psTime, const void *pRecordHeader,
                                int *peLocationIndicator );
@@ -315,16 +320,15 @@ class L1BDataset : public GDALPamDataset
                               const GByte* pabyHeader, int nHeaderBytes );
 
   public:
-                L1BDataset( L1BFileFormat );
-                ~L1BDataset();
+    explicit L1BDataset( L1BFileFormat );
+    virtual ~L1BDataset();
 
-    virtual int GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
     static int  Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
-
 };
 
 /************************************************************************/
@@ -342,9 +346,9 @@ class L1BRasterBand : public GDALPamRasterBand
                 L1BRasterBand( L1BDataset *, int );
 
 //    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALRasterBand *GetMaskBand();
-    virtual int             GetMaskFlags();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALRasterBand *GetMaskBand() override;
+    virtual int             GetMaskFlags() override;
 };
 
 /************************************************************************/
@@ -359,9 +363,9 @@ class L1BMaskBand: public GDALPamRasterBand
 
   public:
 
-                L1BMaskBand( L1BDataset * );
+    explicit       L1BMaskBand( L1BDataset * );
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -373,7 +377,7 @@ L1BMaskBand::L1BMaskBand( L1BDataset *poDSIn )
     CPLAssert(poDSIn->eL1BFormat == L1B_NOAA15 ||
               poDSIn->eL1BFormat == L1B_NOAA15_NOHDR);
 
-    this->poDS = poDSIn;
+    poDS = poDSIn;
     eDataType = GDT_Byte;
 
     nRasterXSize = poDS->GetRasterXSize();
@@ -413,8 +417,8 @@ CPLErr L1BMaskBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 L1BRasterBand::L1BRasterBand( L1BDataset *poDSIn, int nBandIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     eDataType = GDT_UInt16;
 
     nBlockXSize = poDS->GetRasterXSize();
@@ -550,43 +554,47 @@ CPLErr L1BRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                           L1BDataset()                               */
 /************************************************************************/
 
-L1BDataset::L1BDataset( L1BFileFormat eL1BFormatIn )
-
-{
-    eSource = UNKNOWN_STATION;
-    eProcCenter = UNKNOWN_CENTER;
+L1BDataset::L1BDataset( L1BFileFormat eL1BFormatIn ) :
+    eSource(UNKNOWN_STATION),
+    eProcCenter(UNKNOWN_CENTER),
     // sStartTime
     // sStopTime
-    bHighGCPDensityStrategy = CPLTestBool(CPLGetConfigOption("L1B_HIGH_GCP_DENSITY", "TRUE"));
-    pasGCPList = NULL;
-    nGCPCount = 0;
-    iGCPOffset = 0;
-    iGCPCodeOffset = 0;
-    iCLAVRStart = 0;
-    nGCPsPerLine = 0;
-    eLocationIndicator = DESCEND; // XXX: should be initialised
-    iGCPStart = 0;
-    iGCPStep = 0;
-    this->eL1BFormat = eL1BFormatIn;
-    nBufferSize = 0;
-    eSpacecraftID = TIROSN;
-    eProductType = HRPT;
-    iDataFormat = PACKED10BIT;
-    nRecordDataStart = 0;
-    nRecordDataEnd = 0;
-    nDataStartOffset = 0;
-    nRecordSize = 0;
-    nRecordSizeFromHeader = 0;
-    iInstrumentStatus = 0;
-    iChannelsMask = 0;
-    pszGCPProjection = CPLStrdup( "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26,AUTHORITY[\"EPSG\",7043]],TOWGS84[0,0,4.5,0,0,0.554,0.2263],AUTHORITY[\"EPSG\",6322]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],AUTHORITY[\"EPSG\",4322]]" );
-    fp = NULL;
-    bFetchGeolocation = FALSE;
-    bGuessDataFormat = FALSE;
-    bByteSwap = CPL_IS_LSB; /* L1B is normally big-endian ordered, so byte-swap on little-endian CPU */
-    bExposeMaskBand = FALSE;
-    poMaskBand = NULL;
-}
+    bHighGCPDensityStrategy(CPLTestBool(CPLGetConfigOption("L1B_HIGH_GCP_DENSITY", "TRUE"))),
+    pasGCPList(NULL),
+    nGCPCount(0),
+    iGCPOffset(0),
+    iGCPCodeOffset(0),
+    iCLAVRStart(0),
+    nGCPsPerLine(0),
+    eLocationIndicator(DESCEND), // XXX: should be initialised
+    iGCPStart(0),
+    iGCPStep(0),
+    eL1BFormat(eL1BFormatIn),
+    nBufferSize(0),
+    eSpacecraftID(TIROSN),
+    eProductType(HRPT),
+    iDataFormat(PACKED10BIT),
+    nRecordDataStart(0),
+    nRecordDataEnd(0),
+    nDataStartOffset(0),
+    nRecordSize(0),
+    nRecordSizeFromHeader(0),
+    iInstrumentStatus(0),
+    iChannelsMask(0),
+    pszGCPProjection(CPLStrdup(
+        "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\","
+        "SPHEROID[\"WGS 72\",6378135,298.26,AUTHORITY[\"EPSG\",7043]],"
+        "TOWGS84[0,0,4.5,0,0,0.554,0.2263],AUTHORITY[\"EPSG\",6322]],"
+        "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",8901]],"
+        "UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",9108]],"
+        "AUTHORITY[\"EPSG\",4322]]" )),
+    fp(NULL),
+    bGuessDataFormat(FALSE),
+    // L1B is normally big-endian ordered, so byte-swap on little-endian CPU.
+    bByteSwap(CPL_IS_LSB),
+    bExposeMaskBand(FALSE),
+    poMaskBand(NULL)
+{}
 
 /************************************************************************/
 /*                            ~L1BDataset()                             */
@@ -691,7 +699,6 @@ GInt32 L1BDataset::GetInt32(const void* pabyData)
     if( bByteSwap )
         return CPL_SWAP32(lTemp);
     return lTemp;
-
 }
 
 /************************************************************************/
@@ -879,7 +886,7 @@ void L1BDataset::ProcessRecordHeaders()
     }
     else
     {
-        nTargetLines = MIN(DESIRED_LINES_OF_GCPS, nRasterYSize);
+        nTargetLines = std::min(DESIRED_LINES_OF_GCPS, nRasterYSize);
     }
     dfLineStep = 1.0 * (nRasterYSize - 1) / ( nTargetLines - 1 );
 
@@ -927,8 +934,8 @@ void L1BDataset::ProcessRecordHeaders()
 /*      11 per line.                                                    */
 /* -------------------------------------------------------------------- */
 
-            int iGCP;
-            int nDesiredGCPsPerLine = MIN(DESIRED_GCPS_PER_LINE,nGCPsOnThisLine);
+            const int nDesiredGCPsPerLine =
+                std::min(DESIRED_GCPS_PER_LINE, nGCPsOnThisLine);
             int nGCPStep = ( nDesiredGCPsPerLine > 1 ) ?
                 ( nGCPsOnThisLine - 1 ) / ( nDesiredGCPsPerLine-1 ) : 1;
             int iSrcGCP = nGCPCount;
@@ -937,7 +944,7 @@ void L1BDataset::ProcessRecordHeaders()
             if( nGCPStep == 0 )
                 nGCPStep = 1;
 
-            for( iGCP = 0; iGCP < nDesiredGCPsPerLine; iGCP++ )
+            for( int iGCP = 0; iGCP < nDesiredGCPsPerLine; iGCP++ )
             {
                 if( iGCP == nDesiredGCPsPerLine - 1 )
                     iSrcGCP = nGCPCount + nGCPsOnThisLine - 1;
@@ -986,7 +993,6 @@ void L1BDataset::ProcessRecordHeaders()
             SetMetadataItem( "LOCATION", "Descending" );
             break;
     }
-
 }
 
 /************************************************************************/
@@ -1690,7 +1696,7 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
         }
 
         // Determine the spacecraft name
-		// See http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/klm/html/c8/sec83132-2.htm
+        // See http://www.ncdc.noaa.gov/oa/pod-guide/ncdc/docs/klm/html/c8/sec83132-2.htm
         int iWord = GetUInt16(abyRecHeader + L1B_NOAA15_HDR_REC_ID_OFF);
         switch ( iWord )
         {
@@ -1787,10 +1793,10 @@ CPLErr L1BDataset::ProcessDatasetHeader(const char* pszFilename)
 /* -------------------------------------------------------------------- */
 /*      Set fetched information as metadata records                     */
 /* -------------------------------------------------------------------- */
-    const char *pszText;
 
-    SetMetadataItem( "DATASET_NAME",  szDatasetName );
+    SetMetadataItem( "DATASET_NAME", szDatasetName );
 
+    const char *pszText = NULL;
     switch( eSpacecraftID )
     {
         case TIROSN:
@@ -2289,19 +2295,19 @@ class L1BGeolocRasterBand: public GDALRasterBand
     public:
             L1BGeolocRasterBand(L1BGeolocDataset* poDS, int nBand);
 
-            virtual CPLErr IReadBlock(int, int, void*);
-            virtual double GetNoDataValue( int *pbSuccess = NULL );
+            virtual CPLErr IReadBlock(int, int, void*) override;
+            virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 };
 
 /************************************************************************/
 /*                        L1BGeolocDataset()                            */
 /************************************************************************/
 
-L1BGeolocDataset::L1BGeolocDataset(L1BDataset* poL1BDSIn,
-                                   int bInterpolGeolocationDSIn)
+L1BGeolocDataset::L1BGeolocDataset( L1BDataset* poL1BDSIn,
+                                    int bInterpolGeolocationDSIn ) :
+    poL1BDS(poL1BDSIn),
+    bInterpolGeolocationDS(bInterpolGeolocationDSIn)
 {
-    this->poL1BDS = poL1BDSIn;
-    this->bInterpolGeolocationDS = bInterpolGeolocationDSIn;
     if( bInterpolGeolocationDS )
         nRasterXSize = poL1BDS->nRasterXSize;
     else
@@ -2324,8 +2330,8 @@ L1BGeolocDataset::~L1BGeolocDataset()
 
 L1BGeolocRasterBand::L1BGeolocRasterBand(L1BGeolocDataset* poDSIn, int nBandIn)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     nRasterXSize = poDSIn->nRasterXSize;
     nRasterYSize = poDSIn->nRasterYSize;
     eDataType = GDT_Float64;
@@ -2367,7 +2373,7 @@ static double LagrangeInterpol(const double x[],
         }
         y0 = y0 + L * y[i];
     }
-    return(y0);
+    return y0;
 }
 
 /************************************************************************/
@@ -2463,7 +2469,6 @@ CPLErr L1BGeolocRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
                                         sizeof(GDAL_GCP) );
     GDALInitGCPs( poL1BDS->nGCPsPerLine, pasGCPList );
 
-
     GByte* pabyRecordHeader = (GByte*)CPLMalloc(poL1BDS->nRecordSize);
 
 /* -------------------------------------------------------------------- */
@@ -2572,7 +2577,7 @@ class L1BSolarZenithAnglesDataset : public GDALDataset
     L1BDataset* poL1BDS;
 
     public:
-                L1BSolarZenithAnglesDataset(L1BDataset* poMainDS);
+       explicit L1BSolarZenithAnglesDataset(L1BDataset* poMainDS);
        virtual ~L1BSolarZenithAnglesDataset();
 
        static GDALDataset* CreateSolarZenithAnglesDS(L1BDataset* poL1BDS);
@@ -2585,19 +2590,21 @@ class L1BSolarZenithAnglesDataset : public GDALDataset
 class L1BSolarZenithAnglesRasterBand: public GDALRasterBand
 {
     public:
-            L1BSolarZenithAnglesRasterBand(L1BSolarZenithAnglesDataset* poDS, int nBand);
+        L1BSolarZenithAnglesRasterBand( L1BSolarZenithAnglesDataset* poDS,
+                                        int nBand );
 
-            virtual CPLErr IReadBlock(int, int, void*);
-            virtual double GetNoDataValue( int *pbSuccess = NULL );
+        virtual CPLErr IReadBlock(int, int, void*) override;
+        virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 };
 
 /************************************************************************/
 /*                  L1BSolarZenithAnglesDataset()                       */
 /************************************************************************/
 
-L1BSolarZenithAnglesDataset::L1BSolarZenithAnglesDataset(L1BDataset* poL1BDSIn)
+L1BSolarZenithAnglesDataset::L1BSolarZenithAnglesDataset(
+    L1BDataset* poL1BDSIn )
 {
-    this->poL1BDS = poL1BDSIn;
+    poL1BDS = poL1BDSIn;
     nRasterXSize = 51;
     nRasterYSize = poL1BDSIn->nRasterYSize;
 }
@@ -2615,10 +2622,11 @@ L1BSolarZenithAnglesDataset::~L1BSolarZenithAnglesDataset()
 /*                  L1BSolarZenithAnglesRasterBand()                    */
 /************************************************************************/
 
-L1BSolarZenithAnglesRasterBand::L1BSolarZenithAnglesRasterBand(L1BSolarZenithAnglesDataset* poDSIn, int nBandIn)
+L1BSolarZenithAnglesRasterBand::L1BSolarZenithAnglesRasterBand(
+    L1BSolarZenithAnglesDataset* poDSIn, int nBandIn )
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     nRasterXSize = poDSIn->nRasterXSize;
     nRasterYSize = poDSIn->nRasterYSize;
     eDataType = GDT_Float32;
@@ -2647,7 +2655,9 @@ CPLErr L1BSolarZenithAnglesRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
 
     CPL_IGNORE_RET_VAL(VSIFReadL( pabyRecordHeader, 1, poL1BDS->nRecordSize, poL1BDS->fp ));
 
-    int nValidValues = MIN(nRasterXSize, pabyRecordHeader[poL1BDS->iGCPCodeOffset]);
+    const int nValidValues =
+        std::min(nRasterXSize,
+                 static_cast<int>(pabyRecordHeader[poL1BDS->iGCPCodeOffset]));
     float* pafData = (float*)pData;
 
     int bHasFractional = ( poL1BDS->nRecordDataEnd + 20 <= poL1BDS->nRecordSize );
@@ -2659,10 +2669,10 @@ CPLErr L1BSolarZenithAnglesRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
         {
             GByte val = pabyRecordHeader[poL1BDS->nRecordDataEnd + i];
             for(int j=0;j<8;j++)
-                fprintf(stderr, "%c", ((val >> (7 -j)) & 1) ? '1' : '0');
-            fprintf(stderr, " ");
+                fprintf(stderr, "%c", ((val >> (7 -j)) & 1) ? '1' : '0');/*ok*/
+            fprintf(stderr, " ");/*ok*/
         }
-        fprintf(stderr, "\n");
+        fprintf(stderr, "\n");/*ok*/
     }
 #endif
 
@@ -2746,7 +2756,6 @@ GDALDataset* L1BSolarZenithAnglesDataset::CreateSolarZenithAnglesDS(L1BDataset*
     return poGeolocDS;
 }
 
-
 /************************************************************************/
 /*                     L1BNOAA15AnglesDataset                           */
 /************************************************************************/
@@ -2758,7 +2767,7 @@ class L1BNOAA15AnglesDataset : public GDALDataset
     L1BDataset* poL1BDS;
 
     public:
-                L1BNOAA15AnglesDataset(L1BDataset* poMainDS);
+       explicit L1BNOAA15AnglesDataset(L1BDataset* poMainDS);
        virtual ~L1BNOAA15AnglesDataset();
 
        static GDALDataset* CreateAnglesDS(L1BDataset* poL1BDS);
@@ -2773,16 +2782,16 @@ class L1BNOAA15AnglesRasterBand: public GDALRasterBand
     public:
             L1BNOAA15AnglesRasterBand(L1BNOAA15AnglesDataset* poDS, int nBand);
 
-            virtual CPLErr IReadBlock(int, int, void*);
+            virtual CPLErr IReadBlock(int, int, void*) override;
 };
 
 /************************************************************************/
 /*                       L1BNOAA15AnglesDataset()                       */
 /************************************************************************/
 
-L1BNOAA15AnglesDataset::L1BNOAA15AnglesDataset(L1BDataset* poL1BDSIn)
+L1BNOAA15AnglesDataset::L1BNOAA15AnglesDataset( L1BDataset* poL1BDSIn ) :
+    poL1BDS(poL1BDSIn)
 {
-    this->poL1BDS = poL1BDSIn;
     nRasterXSize = 51;
     nRasterYSize = poL1BDS->nRasterYSize;
 }
@@ -2800,10 +2809,11 @@ L1BNOAA15AnglesDataset::~L1BNOAA15AnglesDataset()
 /*                      L1BNOAA15AnglesRasterBand()                     */
 /************************************************************************/
 
-L1BNOAA15AnglesRasterBand::L1BNOAA15AnglesRasterBand(L1BNOAA15AnglesDataset* poDSIn, int nBandIn)
+L1BNOAA15AnglesRasterBand::L1BNOAA15AnglesRasterBand(
+    L1BNOAA15AnglesDataset* poDSIn, int nBandIn )
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     nRasterXSize = poDSIn->nRasterXSize;
     nRasterYSize = poDSIn->nRasterYSize;
     eDataType = GDT_Float32;
@@ -2886,7 +2896,7 @@ class L1BCloudsDataset : public GDALDataset
     L1BDataset* poL1BDS;
 
     public:
-                L1BCloudsDataset(L1BDataset* poMainDS);
+       explicit L1BCloudsDataset(L1BDataset* poMainDS);
        virtual ~L1BCloudsDataset();
 
        static GDALDataset* CreateCloudsDS(L1BDataset* poL1BDS);
@@ -2901,16 +2911,16 @@ class L1BCloudsRasterBand: public GDALRasterBand
     public:
             L1BCloudsRasterBand(L1BCloudsDataset* poDS, int nBand);
 
-            virtual CPLErr IReadBlock(int, int, void*);
+            virtual CPLErr IReadBlock(int, int, void*) override;
 };
 
 /************************************************************************/
 /*                         L1BCloudsDataset()                           */
 /************************************************************************/
 
-L1BCloudsDataset::L1BCloudsDataset(L1BDataset* poL1BDSIn)
+L1BCloudsDataset::L1BCloudsDataset( L1BDataset* poL1BDSIn ) :
+    poL1BDS(poL1BDSIn)
 {
-    this->poL1BDS = poL1BDSIn;
     nRasterXSize = poL1BDSIn->nRasterXSize;
     nRasterYSize = poL1BDSIn->nRasterYSize;
 }
@@ -2928,10 +2938,11 @@ L1BCloudsDataset::~L1BCloudsDataset()
 /*                         L1BCloudsRasterBand()                        */
 /************************************************************************/
 
-L1BCloudsRasterBand::L1BCloudsRasterBand(L1BCloudsDataset* poDSIn, int nBandIn)
+L1BCloudsRasterBand::L1BCloudsRasterBand( L1BCloudsDataset* poDSIn,
+                                          int nBandIn )
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     nRasterXSize = poDSIn->nRasterXSize;
     nRasterYSize = poDSIn->nRasterYSize;
     eDataType = GDT_Byte;
@@ -2996,7 +3007,6 @@ GDALDataset* L1BCloudsDataset::CreateCloudsDS(L1BDataset* poL1BDS)
     return poGeolocDS;
 }
 
-
 /************************************************************************/
 /*                           DetectFormat()                             */
 /************************************************************************/
@@ -3101,7 +3111,7 @@ int L1BDataset::Identify( GDALOpenInfo *poOpenInfo )
 GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    GDALDataset* poOutDS;
+    GDALDataset* poOutDS = NULL;
     VSILFILE* fp = NULL;
     CPLString osFilename = poOpenInfo->pszFilename;
     int bAskGeolocationDS = FALSE;
@@ -3118,7 +3128,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
          STARTS_WITH_CI(poOpenInfo->pszFilename, "L1B_CLOUDS:") )
     {
         GByte abyHeader[1024];
-        const char* pszFilename;
+        const char* pszFilename = NULL;
         if( STARTS_WITH_CI(poOpenInfo->pszFilename, "L1BGCPS_INTERPOL:") )
         {
             bAskGeolocationDS = TRUE;
@@ -3148,7 +3158,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
         if( pszFilename[0] == '"' )
             pszFilename ++;
         osFilename = pszFilename;
-        if( osFilename.size() > 0 && osFilename[osFilename.size()-1] == '"' )
+        if( !osFilename.empty() && osFilename.back() == '"' )
             osFilename.resize(osFilename.size()-1);
         fp = VSIFOpenL( osFilename, "rb" );
         if ( !fp )
@@ -3492,7 +3502,7 @@ GDALDataset *L1BDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->FetchMetadata();
     }
 
-    return( poDS );
+    return poDS;
 
 bad:
     delete poDS;
diff --git a/frmts/leveller/levellerdataset.cpp b/frmts/leveller/levellerdataset.cpp
index d16db53..82756d4 100644
--- a/frmts/leveller/levellerdataset.cpp
+++ b/frmts/leveller/levellerdataset.cpp
@@ -31,12 +31,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: levellerdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: levellerdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 static bool str_equal(const char *_s1, const char *_s2) {
     return 0 == strcmp(_s1, _s2);
@@ -49,7 +48,7 @@ static bool str_equal(const char *_s1, const char *_s2) {
 
 /************************************************************************/
 /* ==================================================================== */
-/*				LevellerDataset				*/
+/*                              LevellerDataset                         */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -57,96 +56,95 @@ static const size_t kMaxTagNameLen = 63;
 
 enum
 {
-	// Leveller coordsys types.
-	LEV_COORDSYS_RASTER = 0,
-	LEV_COORDSYS_LOCAL,
-	LEV_COORDSYS_GEO
+    // Leveller coordsys types.
+    LEV_COORDSYS_RASTER = 0,
+    LEV_COORDSYS_LOCAL,
+    LEV_COORDSYS_GEO
 };
 
 enum
 {
-	// Leveller digital axis extent styles.
-	LEV_DA_POSITIONED = 0,
-	LEV_DA_SIZED,
-	LEV_DA_PIXEL_SIZED
+    // Leveller digital axis extent styles.
+    LEV_DA_POSITIONED = 0,
+    LEV_DA_SIZED,
+    LEV_DA_PIXEL_SIZED
 };
 
 typedef enum
 {
-	// Measurement unit IDs, OEM version.
-	UNITLABEL_UNKNOWN	= 0x00000000,
-	UNITLABEL_PIXEL		= 0x70780000,
-	UNITLABEL_PERCENT	= 0x25000000,
-
-	UNITLABEL_RADIAN	= 0x72616400,
-	UNITLABEL_DEGREE	= 0x64656700,
-	UNITLABEL_ARCMINUTE	= 0x6172636D,
-	UNITLABEL_ARCSECOND	= 0x61726373,
-
-	UNITLABEL_YM		= 0x796D0000,
-	UNITLABEL_ZM		= 0x7A6D0000,
-	UNITLABEL_AM		= 0x616D0000,
-	UNITLABEL_FM		= 0x666D0000,
-	UNITLABEL_PM		= 0x706D0000,
-	UNITLABEL_A			= 0x41000000,
-	UNITLABEL_NM		= 0x6E6D0000,
-	UNITLABEL_U			= 0x75000000,
-	UNITLABEL_UM		= 0x756D0000,
-	UNITLABEL_PPT		= 0x70707400,
-	UNITLABEL_PT		= 0x70740000,
-	UNITLABEL_MM		= 0x6D6D0000,
-	UNITLABEL_P			= 0x70000000,
-	UNITLABEL_CM		= 0x636D0000,
-	UNITLABEL_IN		= 0x696E0000,
-	UNITLABEL_DFT		= 0x64667400,
-	UNITLABEL_DM		= 0x646D0000,
-	UNITLABEL_LI		= 0x6C690000,
-	UNITLABEL_SLI		= 0x736C6900,
-	UNITLABEL_SP		= 0x73700000,
-	UNITLABEL_FT		= 0x66740000,
-	UNITLABEL_SFT		= 0x73667400,
-	UNITLABEL_YD		= 0x79640000,
-	UNITLABEL_SYD		= 0x73796400,
-	UNITLABEL_M			= 0x6D000000,
-	UNITLABEL_FATH		= 0x66617468,
-	UNITLABEL_R			= 0x72000000,
-	UNITLABEL_RD		= UNITLABEL_R,
-	UNITLABEL_DAM		= 0x64416D00,
-	UNITLABEL_DKM		= UNITLABEL_DAM,
-	UNITLABEL_CH		= 0x63680000,
-	UNITLABEL_SCH		= 0x73636800,
-	UNITLABEL_HM		= 0x686D0000,
-	UNITLABEL_F			= 0x66000000,
-	UNITLABEL_KM		= 0x6B6D0000,
-	UNITLABEL_MI		= 0x6D690000,
-	UNITLABEL_SMI		= 0x736D6900,
-	UNITLABEL_NMI		= 0x6E6D6900,
-	UNITLABEL_MEGAM		= 0x4D6D0000,
-	UNITLABEL_LS		= 0x6C730000,
-	UNITLABEL_GM		= 0x476D0000,
-	UNITLABEL_LM		= 0x6C6D0000,
-	UNITLABEL_AU		= 0x41550000,
-	UNITLABEL_TM		= 0x546D0000,
-	UNITLABEL_LHR		= 0x6C687200,
-	UNITLABEL_LD		= 0x6C640000,
-	UNITLABEL_PETAM		= 0x506D0000,
-	UNITLABEL_LY		= 0x6C790000,
-	UNITLABEL_PC		= 0x70630000,
-	UNITLABEL_EXAM		= 0x456D0000,
-	UNITLABEL_KLY		= 0x6B6C7900,
-	UNITLABEL_KPC		= 0x6B706300,
-	UNITLABEL_ZETTAM	= 0x5A6D0000,
-	UNITLABEL_MLY		= 0x4D6C7900,
-	UNITLABEL_MPC		= 0x4D706300,
-	UNITLABEL_YOTTAM	= 0x596D0000
+    // Measurement unit IDs, OEM version.
+    UNITLABEL_UNKNOWN   = 0x00000000,
+    UNITLABEL_PIXEL     = 0x70780000,
+    UNITLABEL_PERCENT   = 0x25000000,
+
+    UNITLABEL_RADIAN    = 0x72616400,
+    UNITLABEL_DEGREE    = 0x64656700,
+    UNITLABEL_ARCMINUTE = 0x6172636D,
+    UNITLABEL_ARCSECOND = 0x61726373,
+
+    UNITLABEL_YM        = 0x796D0000,
+    UNITLABEL_ZM        = 0x7A6D0000,
+    UNITLABEL_AM        = 0x616D0000,
+    UNITLABEL_FM        = 0x666D0000,
+    UNITLABEL_PM        = 0x706D0000,
+    UNITLABEL_A         = 0x41000000,
+    UNITLABEL_NM        = 0x6E6D0000,
+    UNITLABEL_U         = 0x75000000,
+    UNITLABEL_UM        = 0x756D0000,
+    UNITLABEL_PPT       = 0x70707400,
+    UNITLABEL_PT        = 0x70740000,
+    UNITLABEL_MM        = 0x6D6D0000,
+    UNITLABEL_P         = 0x70000000,
+    UNITLABEL_CM        = 0x636D0000,
+    UNITLABEL_IN        = 0x696E0000,
+    UNITLABEL_DFT       = 0x64667400,
+    UNITLABEL_DM        = 0x646D0000,
+    UNITLABEL_LI        = 0x6C690000,
+    UNITLABEL_SLI       = 0x736C6900,
+    UNITLABEL_SP        = 0x73700000,
+    UNITLABEL_FT        = 0x66740000,
+    UNITLABEL_SFT       = 0x73667400,
+    UNITLABEL_YD        = 0x79640000,
+    UNITLABEL_SYD       = 0x73796400,
+    UNITLABEL_M         = 0x6D000000,
+    UNITLABEL_FATH      = 0x66617468,
+    UNITLABEL_R         = 0x72000000,
+    UNITLABEL_RD        = UNITLABEL_R,
+    UNITLABEL_DAM       = 0x64416D00,
+    UNITLABEL_DKM       = UNITLABEL_DAM,
+    UNITLABEL_CH        = 0x63680000,
+    UNITLABEL_SCH       = 0x73636800,
+    UNITLABEL_HM        = 0x686D0000,
+    UNITLABEL_F         = 0x66000000,
+    UNITLABEL_KM        = 0x6B6D0000,
+    UNITLABEL_MI        = 0x6D690000,
+    UNITLABEL_SMI       = 0x736D6900,
+    UNITLABEL_NMI       = 0x6E6D6900,
+    UNITLABEL_MEGAM     = 0x4D6D0000,
+    UNITLABEL_LS        = 0x6C730000,
+    UNITLABEL_GM        = 0x476D0000,
+    UNITLABEL_LM        = 0x6C6D0000,
+    UNITLABEL_AU        = 0x41550000,
+    UNITLABEL_TM        = 0x546D0000,
+    UNITLABEL_LHR       = 0x6C687200,
+    UNITLABEL_LD        = 0x6C640000,
+    UNITLABEL_PETAM     = 0x506D0000,
+    UNITLABEL_LY        = 0x6C790000,
+    UNITLABEL_PC        = 0x70630000,
+    UNITLABEL_EXAM      = 0x456D0000,
+    UNITLABEL_KLY       = 0x6B6C7900,
+    UNITLABEL_KPC       = 0x6B706300,
+    UNITLABEL_ZETTAM    = 0x5A6D0000,
+    UNITLABEL_MLY       = 0x4D6C7900,
+    UNITLABEL_MPC       = 0x4D706300,
+    UNITLABEL_YOTTAM    = 0x596D0000
 } UNITLABEL;
 
-
 typedef struct
 {
-	const char* pszID;
-	double		dScale;
-	UNITLABEL	oemCode;
+        const char* pszID;
+        double      dScale;
+        UNITLABEL   oemCode;
 } measurement_unit;
 
 static const double kdays_per_year = 365.25;
@@ -159,83 +157,82 @@ static const int kFirstLinearMeasureIdx = 9;
 
 static const measurement_unit kUnits[] =
 {
-	{ "", 1.0, UNITLABEL_UNKNOWN },
-	{ "px", 1.0, UNITLABEL_PIXEL },
-	{ "%", 1.0, UNITLABEL_PERCENT }, // not actually used
-
-	{ "rad", 1.0, UNITLABEL_RADIAN },
-	{ "\xB0", kPI / 180.0, UNITLABEL_DEGREE }, // \xB0 is Unicode degree symbol
-	{ "d", kPI / 180.0, UNITLABEL_DEGREE },
-	{ "deg", kPI / 180.0, UNITLABEL_DEGREE },
-	{ "'", kPI / (60.0 * 180.0), UNITLABEL_ARCMINUTE },
-	{ "\"", kPI / (3600.0 * 180.0), UNITLABEL_ARCSECOND },
-
-	{ "ym", 1.0e-24, UNITLABEL_YM },
-	{ "zm", 1.0e-21, UNITLABEL_ZM },
-	{ "am", 1.0e-18, UNITLABEL_AM },
-	{ "fm", 1.0e-15, UNITLABEL_FM },
-	{ "pm", 1.0e-12, UNITLABEL_PM },
-	{ "A",  1.0e-10, UNITLABEL_A },
-	{ "nm", 1.0e-9, UNITLABEL_NM },
-	{ "u",  1.0e-6, UNITLABEL_U },
-	{ "um", 1.0e-6, UNITLABEL_UM },
-	{ "ppt", kdInch / 72.27, UNITLABEL_PPT },
-	{ "pt", kdInch / 72.0, UNITLABEL_PT },
+    { "", 1.0, UNITLABEL_UNKNOWN },
+    { "px", 1.0, UNITLABEL_PIXEL },
+    { "%", 1.0, UNITLABEL_PERCENT }, // not actually used
+
+    { "rad", 1.0, UNITLABEL_RADIAN },
+    { "\xB0", kPI / 180.0, UNITLABEL_DEGREE }, // \xB0 is Unicode degree symbol
+    { "d", kPI / 180.0, UNITLABEL_DEGREE },
+    { "deg", kPI / 180.0, UNITLABEL_DEGREE },
+    { "'", kPI / (60.0 * 180.0), UNITLABEL_ARCMINUTE },
+    { "\"", kPI / (3600.0 * 180.0), UNITLABEL_ARCSECOND },
+
+    { "ym", 1.0e-24, UNITLABEL_YM },
+    { "zm", 1.0e-21, UNITLABEL_ZM },
+    { "am", 1.0e-18, UNITLABEL_AM },
+    { "fm", 1.0e-15, UNITLABEL_FM },
+    { "pm", 1.0e-12, UNITLABEL_PM },
+    { "A",  1.0e-10, UNITLABEL_A },
+    { "nm", 1.0e-9, UNITLABEL_NM },
+    { "u",  1.0e-6, UNITLABEL_U },
+    { "um", 1.0e-6, UNITLABEL_UM },
+    { "ppt", kdInch / 72.27, UNITLABEL_PPT },
+    { "pt", kdInch / 72.0, UNITLABEL_PT },
     { "mm", 1.0e-3, UNITLABEL_MM },
-	{ "p", kdInch / 6.0, UNITLABEL_P },
-	{ "cm", 1.0e-2, UNITLABEL_CM },
-	{ "in", kdInch, UNITLABEL_IN },
-	{ "dft", 0.03048, UNITLABEL_DFT },
-	{ "dm", 0.1, UNITLABEL_DM },
-	{ "li", 0.2011684 /* GDAL 0.20116684023368047 ? */, UNITLABEL_LI },
-	{ "sli", 0.201168402336805, UNITLABEL_SLI },
-	{ "sp", 0.2286, UNITLABEL_SP },
-	{ "ft", 0.3048, UNITLABEL_FT },
-	{ "sft", 1200.0 / 3937.0, UNITLABEL_SFT },
+    { "p", kdInch / 6.0, UNITLABEL_P },
+    { "cm", 1.0e-2, UNITLABEL_CM },
+    { "in", kdInch, UNITLABEL_IN },
+    { "dft", 0.03048, UNITLABEL_DFT },
+    { "dm", 0.1, UNITLABEL_DM },
+    { "li", 0.2011684 /* GDAL 0.20116684023368047 ? */, UNITLABEL_LI },
+    { "sli", 0.201168402336805, UNITLABEL_SLI },
+    { "sp", 0.2286, UNITLABEL_SP },
+    { "ft", 0.3048, UNITLABEL_FT },
+    { "sft", 1200.0 / 3937.0, UNITLABEL_SFT },
     { "yd", 0.9144, UNITLABEL_YD },
-	{ "syd", 0.914401828803658, UNITLABEL_SYD },
-	{ "m", 1.0, UNITLABEL_M },
-	{ "fath", 1.8288, UNITLABEL_FATH },
-	{ "rd", 5.02921, UNITLABEL_RD },
-	{ "dam", 10.0, UNITLABEL_DAM },
-	{ "dkm", 10.0, UNITLABEL_DKM },
-	{ "ch", 20.1168 /* GDAL: 2.0116684023368047 ? */, UNITLABEL_CH },
-	{ "sch", 20.1168402336805, UNITLABEL_SCH },
-	{ "hm", 100.0, UNITLABEL_HM },
-	{ "f", 201.168, UNITLABEL_F },
-	{ "km", 1000.0, UNITLABEL_KM },
-	{ "mi", 1609.344, UNITLABEL_MI },
-	{ "smi", 1609.34721869444, UNITLABEL_SMI },
-	{ "nmi", 1853.0, UNITLABEL_NMI },
-	{ "Mm", 1.0e+6, UNITLABEL_MEGAM },
+    { "syd", 0.914401828803658, UNITLABEL_SYD },
+    { "m", 1.0, UNITLABEL_M },
+    { "fath", 1.8288, UNITLABEL_FATH },
+    { "rd", 5.02921, UNITLABEL_RD },
+    { "dam", 10.0, UNITLABEL_DAM },
+    { "dkm", 10.0, UNITLABEL_DKM },
+    { "ch", 20.1168 /* GDAL: 2.0116684023368047 ? */, UNITLABEL_CH },
+    { "sch", 20.1168402336805, UNITLABEL_SCH },
+    { "hm", 100.0, UNITLABEL_HM },
+    { "f", 201.168, UNITLABEL_F },
+    { "km", 1000.0, UNITLABEL_KM },
+    { "mi", 1609.344, UNITLABEL_MI },
+    { "smi", 1609.34721869444, UNITLABEL_SMI },
+    { "nmi", 1853.0, UNITLABEL_NMI },
+    { "Mm", 1.0e+6, UNITLABEL_MEGAM },
     { "ls", kdLStoM, UNITLABEL_LS },
-	{ "Gm", 1.0e+9, UNITLABEL_GM },
-	{ "lm", kdLStoM * 60, UNITLABEL_LM },
-	{ "AU", 8.317 * kdLStoM * 60, UNITLABEL_AU },
-	{ "Tm", 1.0e+12, UNITLABEL_TM },
-	{ "lhr", 60.0 * 60.0 * kdLStoM, UNITLABEL_LHR },
-	{ "ld", 24 * 60.0 * 60.0 * kdLStoM, UNITLABEL_LD },
-	{ "Pm", 1.0e+15, UNITLABEL_PETAM },
-	{ "ly", kdLYtoM, UNITLABEL_LY },
-	{ "pc", 3.2616 * kdLYtoM, UNITLABEL_PC },
-	{ "Em", 1.0e+18, UNITLABEL_EXAM },
-	{ "kly", 1.0e+3 * kdLYtoM, UNITLABEL_KLY },
-	{ "kpc", 3.2616 * 1.0e+3 * kdLYtoM, UNITLABEL_KPC },
-	{ "Zm", 1.0e+21, UNITLABEL_ZETTAM },
-	{ "Mly", 1.0e+6 * kdLYtoM, UNITLABEL_MLY },
-	{ "Mpc", 3.2616 * 1.0e+6 * kdLYtoM, UNITLABEL_MPC },
-	{ "Ym", 1.0e+24, UNITLABEL_YOTTAM }
+    { "Gm", 1.0e+9, UNITLABEL_GM },
+    { "lm", kdLStoM * 60, UNITLABEL_LM },
+    { "AU", 8.317 * kdLStoM * 60, UNITLABEL_AU },
+    { "Tm", 1.0e+12, UNITLABEL_TM },
+    { "lhr", 60.0 * 60.0 * kdLStoM, UNITLABEL_LHR },
+    { "ld", 24 * 60.0 * 60.0 * kdLStoM, UNITLABEL_LD },
+    { "Pm", 1.0e+15, UNITLABEL_PETAM },
+    { "ly", kdLYtoM, UNITLABEL_LY },
+    { "pc", 3.2616 * kdLYtoM, UNITLABEL_PC },
+    { "Em", 1.0e+18, UNITLABEL_EXAM },
+    { "kly", 1.0e+3 * kdLYtoM, UNITLABEL_KLY },
+    { "kpc", 3.2616 * 1.0e+3 * kdLYtoM, UNITLABEL_KPC },
+    { "Zm", 1.0e+21, UNITLABEL_ZETTAM },
+    { "Mly", 1.0e+6 * kdLYtoM, UNITLABEL_MLY },
+    { "Mpc", 3.2616 * 1.0e+6 * kdLYtoM, UNITLABEL_MPC },
+    { "Ym", 1.0e+24, UNITLABEL_YOTTAM }
 };
 
 // ----------------------------------------------------------------
 
 static bool approx_equal(double a, double b)
 {
-	const double epsilon = 1e-5;
-	return (fabs(a-b) <= epsilon);
+    const double epsilon = 1e-5;
+    return fabs(a-b) <= epsilon;
 }
 
-
 // ----------------------------------------------------------------
 
 class LevellerRasterBand;
@@ -245,149 +242,148 @@ class LevellerDataset : public GDALPamDataset
     friend class LevellerRasterBand;
     friend class digital_axis;
 
-    int			m_version;
+    int                 m_version;
 
-    char*		m_pszFilename;
-    char*		m_pszProjection;
+    char*               m_pszFilename;
+    char*               m_pszProjection;
 
-    //char		m_szUnits[8];
-    char		m_szElevUnits[8];
-    double		m_dElevScale;	// physical-to-logical scaling.
-    double		m_dElevBase;	// logical offset.
-    double		m_adfTransform[6];
-    //double		m_dMeasurePerPixel;
-    double		m_dLogSpan[2];
+    //char              m_szUnits[8];
+    char                m_szElevUnits[8];
+    double              m_dElevScale;  // physical-to-logical scaling.
+    double              m_dElevBase;   // logical offset.
+    double              m_adfTransform[6];
+    //double            m_dMeasurePerPixel;
+    double              m_dLogSpan[2];
 
-    VSILFILE*			m_fp;
-    vsi_l_offset	m_nDataOffset;
+    VSILFILE*           m_fp;
+    vsi_l_offset        m_nDataOffset;
 
     bool load_from_file(VSILFILE*, const char*);
 
-
-    bool locate_data(vsi_l_offset&, size_t&, VSILFILE*, const char*);
+    static bool locate_data(vsi_l_offset&, size_t&, VSILFILE*, const char*);
     bool get(int&, VSILFILE*, const char*);
     bool get(size_t& n, VSILFILE* fp, const char* psz)
-		{ return this->get((int&)n, fp, psz); }
+        { return this->get((int&)n, fp, psz); }
     bool get(double&, VSILFILE*, const char*);
     bool get(char*, size_t, VSILFILE*, const char*);
 
-	bool write_header();
-	bool write_tag(const char*, int);
-	bool write_tag(const char*, size_t);
-	bool write_tag(const char*, double);
-	bool write_tag(const char*, const char*);
-	bool write_tag_start(const char*, size_t);
-	bool write(int);
-	bool write(size_t);
-	bool write(double);
-	bool write_byte(size_t);
-
-	const measurement_unit* get_uom(const char*) const;
-	const measurement_unit* get_uom(UNITLABEL) const;
-	const measurement_unit* get_uom(double) const;
-
-    bool convert_measure(double, double&, const char* pszUnitsFrom);
-	bool make_local_coordsys(const char* pszName, const char* pszUnits);
-	bool make_local_coordsys(const char* pszName, UNITLABEL);
-	const char* code_to_id(UNITLABEL) const;
-	UNITLABEL id_to_code(const char*) const;
-	UNITLABEL meter_measure_to_code(double) const;
-	bool compute_elev_scaling(const OGRSpatialReference&);
-	void raw_to_proj(double, double, double&, double&);
+    bool write_header();
+    bool write_tag(const char*, int);
+    bool write_tag(const char*, size_t);
+    bool write_tag(const char*, double);
+    bool write_tag(const char*, const char*);
+    bool write_tag_start(const char*, size_t);
+    bool write(int);
+    bool write(size_t);
+    bool write(double);
+    bool write_byte(size_t);
+
+    const measurement_unit* get_uom(const char*) const;
+    const measurement_unit* get_uom(UNITLABEL) const;
+    const measurement_unit* get_uom(double) const;
+
+    static bool convert_measure(double, double&, const char* pszUnitsFrom);
+    bool make_local_coordsys(const char* pszName, const char* pszUnits);
+    bool make_local_coordsys(const char* pszName, UNITLABEL);
+    const char* code_to_id(UNITLABEL) const;
+    UNITLABEL id_to_code(const char*) const;
+    UNITLABEL meter_measure_to_code(double) const;
+    bool compute_elev_scaling(const OGRSpatialReference&);
+    void raw_to_proj(double, double, double&, double&);
 
 public:
     LevellerDataset();
-    ~LevellerDataset();
+    virtual ~LevellerDataset();
 
     static GDALDataset* Open( GDALOpenInfo* );
-	static int Identify( GDALOpenInfo* );
+    static int Identify( GDALOpenInfo* );
     static GDALDataset* Create( const char* pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char** papszOptions );
 
-    virtual CPLErr 	GetGeoTransform( double* );
-    virtual const char*	GetProjectionRef(void);
+    virtual CPLErr      GetGeoTransform( double* ) override;
+    virtual const char* GetProjectionRef(void) override;
 
-    virtual CPLErr 	SetGeoTransform( double* );
-    virtual CPLErr	SetProjection(const char*);
+    virtual CPLErr      SetGeoTransform( double* ) override;
+    virtual CPLErr      SetProjection(const char*) override;
 };
 
-
 class digital_axis
 {
-	public:
-  digital_axis() : m_eStyle(LEV_DA_PIXEL_SIZED), m_fixedEnd(0) {}
-
-		bool get(LevellerDataset& ds, VSILFILE* fp, int n)
-		{
-			char szTag[32];
-			snprintf(szTag, sizeof(szTag), "coordsys_da%d_style", n);
-			if(!ds.get(m_eStyle, fp, szTag))
-				return false;
-			snprintf(szTag, sizeof(szTag), "coordsys_da%d_fixedend", n);
-			if(!ds.get(m_fixedEnd, fp, szTag))
-				return false;
-			snprintf(szTag, sizeof(szTag), "coordsys_da%d_v0", n);
-			if(!ds.get(m_d[0], fp, szTag))
-				return false;
-			snprintf(szTag, sizeof(szTag), "coordsys_da%d_v1", n);
-			if(!ds.get(m_d[1], fp, szTag))
-				return false;
-			return true;
-		}
-
-		double origin(size_t pixels) const
-		{
-			if(m_fixedEnd == 1)
-			{
-				switch(m_eStyle)
-				{
-					case LEV_DA_SIZED:
-						return m_d[1] + m_d[0];
-
-					case LEV_DA_PIXEL_SIZED:
-						return m_d[1] + (m_d[0] * (pixels-1));
-				}
-			}
-			return m_d[0];
-		}
-
-		double scaling(size_t pixels) const
-		{
-			CPLAssert(pixels > 1);
-			if(m_eStyle == LEV_DA_PIXEL_SIZED)
-				return m_d[1 - m_fixedEnd];
-
-			return this->length(static_cast<int>(pixels)) / (pixels - 1);
-		}
-
-		double length(int pixels) const
-		{
-			// Return the signed length of the axis.
-
-			switch(m_eStyle)
-			{
-				case LEV_DA_POSITIONED:
-					return m_d[1] - m_d[0];
-
-				case LEV_DA_SIZED:
-					return m_d[1 - m_fixedEnd];
-
-				case LEV_DA_PIXEL_SIZED:
-					return m_d[1 - m_fixedEnd] * (pixels-1);
-
-			}
-			CPLAssert(FALSE);
-			return 0.0;
-		}
-
-
-	protected:
-		int	m_eStyle;
-		size_t	m_fixedEnd;
-		double	m_d[2];
-};
+ public:
+    digital_axis() : m_eStyle(LEV_DA_PIXEL_SIZED), m_fixedEnd(0)
+    {
+        m_d[0] = 0.0;
+        m_d[1] = 0.0;
+    }
+
+    bool get(LevellerDataset& ds, VSILFILE* fp, int n)
+    {
+        char szTag[32];
+        snprintf(szTag, sizeof(szTag), "coordsys_da%d_style", n);
+        if(!ds.get(m_eStyle, fp, szTag))
+            return false;
+        snprintf(szTag, sizeof(szTag), "coordsys_da%d_fixedend", n);
+        if(!ds.get(m_fixedEnd, fp, szTag))
+            return false;
+        snprintf(szTag, sizeof(szTag), "coordsys_da%d_v0", n);
+        if(!ds.get(m_d[0], fp, szTag))
+            return false;
+        snprintf(szTag, sizeof(szTag), "coordsys_da%d_v1", n);
+        if(!ds.get(m_d[1], fp, szTag))
+            return false;
+        return true;
+    }
+
+    double origin(size_t pixels) const
+    {
+        if(m_fixedEnd == 1)
+        {
+            switch(m_eStyle)
+            {
+            case LEV_DA_SIZED:
+                return m_d[1] + m_d[0];
+
+            case LEV_DA_PIXEL_SIZED:
+                return m_d[1] + (m_d[0] * (pixels-1));
+            }
+        }
+        return m_d[0];
+    }
+
+    double scaling(size_t pixels) const
+    {
+        CPLAssert(pixels > 1);
+        if(m_eStyle == LEV_DA_PIXEL_SIZED)
+            return m_d[1 - m_fixedEnd];
 
+        return this->length(static_cast<int>(pixels)) / (pixels - 1);
+    }
+
+    double length(int pixels) const
+    {
+        // Return the signed length of the axis.
+
+        switch(m_eStyle)
+        {
+        case LEV_DA_POSITIONED:
+            return m_d[1] - m_d[0];
+
+        case LEV_DA_SIZED:
+            return m_d[1 - m_fixedEnd];
+
+        case LEV_DA_PIXEL_SIZED:
+            return m_d[1 - m_fixedEnd] * (pixels-1);
+        }
+        CPLAssert(false);
+        return 0.0;
+    }
+
+ protected:
+    int m_eStyle;
+    size_t m_fixedEnd;
+    double m_d[2];
+};
 
 /************************************************************************/
 /* ==================================================================== */
@@ -399,27 +395,26 @@ class LevellerRasterBand : public GDALPamRasterBand
 {
     friend class LevellerDataset;
 
-	float*	m_pLine;
-	bool	m_bFirstTime;
+    float*      m_pLine;
+    bool        m_bFirstTime;
 
 public:
 
     explicit LevellerRasterBand(LevellerDataset*);
-    ~LevellerRasterBand();
+    virtual ~LevellerRasterBand();
 
     bool        Init();
 
     // Geomeasure support.
-    virtual const char* GetUnitType();
-    virtual double GetScale(int* pbSuccess = NULL);
-    virtual double GetOffset(int* pbSuccess = NULL);
+    virtual const char* GetUnitType() override;
+    virtual double GetScale(int* pbSuccess = NULL) override;
+    virtual double GetOffset(int* pbSuccess = NULL) override;
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
-    virtual CPLErr SetUnitType( const char* );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
+    virtual CPLErr SetUnitType( const char* ) override;
 };
 
-
 /************************************************************************/
 /*                         LevellerRasterBand()                         */
 /************************************************************************/
@@ -428,8 +423,8 @@ LevellerRasterBand::LevellerRasterBand( LevellerDataset *poDSIn ) :
     m_pLine(NULL),
     m_bFirstTime(true)
 {
-    this->poDS = poDSIn;
-    this->nBand = 1;
+    poDS = poDSIn;
+    nBand = 1;
 
     eDataType = GDT_Float32;
 
@@ -437,7 +432,6 @@ LevellerRasterBand::LevellerRasterBand( LevellerDataset *poDSIn ) :
     nBlockYSize = 1; // poDS->GetRasterYSize();
 }
 
-
 /************************************************************************/
 /*                           Init()                                     */
 /************************************************************************/
@@ -467,60 +461,58 @@ CPLErr LevellerRasterBand::IWriteBlock
 {
     CPLAssert( nBlockXOff == 0  );
     CPLAssert( pImage != NULL );
-	CPLAssert( m_pLine != NULL );
+    CPLAssert( m_pLine != NULL );
 
-/*	#define sgn(_n) ((_n) < 0 ? -1 : ((_n) > 0 ? 1 : 0) )
-	#define sround(_f)	\
-		(int)((_f) + (0.5 * sgn(_f)))
+/*  #define sgn(_n) ((_n) < 0 ? -1 : ((_n) > 0 ? 1 : 0) )
+    #define sround(_f)                          \
+    (int)((_f) + (0.5 * sgn(_f)))
 */
-	const size_t pixelsize = sizeof(float);
-
-	LevellerDataset& ds = *reinterpret_cast<LevellerDataset*>( poDS );
-	if(m_bFirstTime)
-	{
-		m_bFirstTime = false;
-		if(!ds.write_header())
-			return CE_Failure;
-		ds.m_nDataOffset = VSIFTellL(ds.m_fp);
-	}
-	const size_t rowbytes = nBlockXSize * pixelsize;
-	const float* pfImage = reinterpret_cast<float *>( pImage );
-
-	if(0 == VSIFSeekL(
-               ds.m_fp, ds.m_nDataOffset + nBlockYOff * rowbytes,
+    const size_t pixelsize = sizeof(float);
+
+    LevellerDataset& ds = *reinterpret_cast<LevellerDataset*>( poDS );
+    if(m_bFirstTime)
+    {
+        m_bFirstTime = false;
+        if(!ds.write_header())
+            return CE_Failure;
+        ds.m_nDataOffset = VSIFTellL(ds.m_fp);
+    }
+    const size_t rowbytes = nBlockXSize * pixelsize;
+    const float* pfImage = reinterpret_cast<float *>( pImage );
+
+    if(0 == VSIFSeekL(
+           ds.m_fp, ds.m_nDataOffset + nBlockYOff * rowbytes,
                SEEK_SET))
-	{
-		for(size_t x = 0; x < (size_t)nBlockXSize; x++)
-		{
-			// Convert logical elevations to physical.
-                    m_pLine[x] = static_cast<float>(
-                        (pfImage[x] - ds.m_dElevBase) / ds.m_dElevScale );
-		}
+    {
+        for(size_t x = 0; x < (size_t)nBlockXSize; x++)
+        {
+            // Convert logical elevations to physical.
+            m_pLine[x] = static_cast<float>(
+                (pfImage[x] - ds.m_dElevBase) / ds.m_dElevScale );
+        }
 
 #ifdef CPL_MSB
-		GDALSwapWords( m_pLine, pixelsize, nBlockXSize, pixelsize );
+        GDALSwapWords( m_pLine, pixelsize, nBlockXSize, pixelsize );
 #endif
-		if(1 == VSIFWriteL(m_pLine, rowbytes, 1, ds.m_fp))
-			return CE_None;
-	}
+        if(1 == VSIFWriteL(m_pLine, rowbytes, 1, ds.m_fp))
+            return CE_None;
+    }
 
-	return CE_Failure;
+    return CE_Failure;
 }
 
-
 CPLErr LevellerRasterBand::SetUnitType( const char* psz )
 {
     LevellerDataset& ds = *reinterpret_cast<LevellerDataset *>( poDS );
 
-	if(strlen(psz) >= sizeof(ds.m_szElevUnits))
-		return CE_Failure;
+    if(strlen(psz) >= sizeof(ds.m_szElevUnits))
+        return CE_Failure;
 
-	strcpy(ds.m_szElevUnits, psz);
+    strcpy(ds.m_szElevUnits, psz);
 
-	return CE_None;
+    return CE_None;
 }
 
-
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
@@ -581,7 +573,6 @@ CPLErr LevellerRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             pf[i] = static_cast<float>( pi[i] ) / 65536;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Convert raw elevations to realworld elevs.                      */
 /* -------------------------------------------------------------------- */
@@ -612,9 +603,9 @@ const char *LevellerRasterBand::GetUnitType()
 double LevellerRasterBand::GetScale(int* pbSuccess)
 {
     LevellerDataset *poGDS = reinterpret_cast<LevellerDataset *>( poDS );
-	if(pbSuccess != NULL)
-		*pbSuccess = TRUE;
-	return poGDS->m_dElevScale;
+    if(pbSuccess != NULL)
+        *pbSuccess = TRUE;
+    return poGDS->m_dElevScale;
 }
 
 /************************************************************************/
@@ -624,14 +615,14 @@ double LevellerRasterBand::GetScale(int* pbSuccess)
 double LevellerRasterBand::GetOffset(int* pbSuccess)
 {
     LevellerDataset *poGDS = reinterpret_cast<LevellerDataset *>( poDS );
-	if(pbSuccess != NULL)
-		*pbSuccess = TRUE;
-	return poGDS->m_dElevBase;
+    if(pbSuccess != NULL)
+        *pbSuccess = TRUE;
+    return poGDS->m_dElevBase;
 }
 
 /************************************************************************/
 /* ==================================================================== */
-/*				LevellerDataset		                */
+/*                              LevellerDataset                         */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -640,9 +631,18 @@ double LevellerRasterBand::GetOffset(int* pbSuccess)
 /************************************************************************/
 
 LevellerDataset::LevellerDataset() :
-    m_version(0), m_pszFilename(NULL), m_pszProjection(NULL), m_dElevScale(),
-    m_dElevBase(), m_fp(NULL), m_nDataOffset()
-{ }
+    m_version(0),
+    m_pszFilename(NULL),
+    m_pszProjection(NULL),
+    m_dElevScale(),
+    m_dElevBase(),
+    m_fp(NULL),
+    m_nDataOffset()
+{
+    memset( m_szElevUnits, 0, sizeof(m_szElevUnits) );
+    memset( m_adfTransform, 0, sizeof(m_adfTransform) );
+    memset( m_dLogSpan, 0, sizeof(m_dLogSpan) );
+}
 
 /************************************************************************/
 /*                          ~LevellerDataset()                          */
@@ -661,86 +661,82 @@ LevellerDataset::~LevellerDataset()
 
 static double degrees_to_radians(double d)
 {
-	return (d * 0.017453292);
+    return d * 0.017453292;
 }
 
-
 static double average(double a, double b)
 {
-	return 0.5 * (a + b);
+    return 0.5 * (a + b);
 }
 
-
 void LevellerDataset::raw_to_proj(double x, double y, double& xp, double& yp)
 {
-	xp = x * m_adfTransform[1] + m_adfTransform[0];
-	yp = y * m_adfTransform[5] + m_adfTransform[3];
+    xp = x * m_adfTransform[1] + m_adfTransform[0];
+    yp = y * m_adfTransform[5] + m_adfTransform[3];
 }
 
-
 bool LevellerDataset::compute_elev_scaling
 (
-	const OGRSpatialReference& sr
+    const OGRSpatialReference& sr
 )
 {
-	const char* pszGroundUnits;
+    const char* pszGroundUnits = NULL;
 
-	if(!sr.IsGeographic())
-	{
-		// For projected or local CS, the elev scale is
-		// the average ground scale.
-		m_dElevScale = average(m_adfTransform[1], m_adfTransform[5]);
+    if(!sr.IsGeographic())
+    {
+        // For projected or local CS, the elev scale is
+        // the average ground scale.
+        m_dElevScale = average(m_adfTransform[1], m_adfTransform[5]);
 
-		const double dfLinear = sr.GetLinearUnits();
-		const measurement_unit* pu = this->get_uom(dfLinear);
-		if(pu == NULL)
-			return false;
+        const double dfLinear = sr.GetLinearUnits();
+        const measurement_unit* pu = this->get_uom(dfLinear);
+        if(pu == NULL)
+            return false;
 
-		pszGroundUnits = pu->pszID;
-	}
-	else
-	{
-		pszGroundUnits = "m";
+        pszGroundUnits = pu->pszID;
+    }
+    else
+    {
+        pszGroundUnits = "m";
 
-		const double kdEarthCircumPolar = 40007849;
-		const double kdEarthCircumEquat = 40075004;
+        const double kdEarthCircumPolar = 40007849;
+        const double kdEarthCircumEquat = 40075004;
 
-		const double xr = 0.5 * nRasterXSize;
-		const double yr = 0.5 * nRasterYSize;
+        const double xr = 0.5 * nRasterXSize;
+        const double yr = 0.5 * nRasterYSize;
 
-		double xg[2], yg[2];
-		raw_to_proj(xr, yr, xg[0], yg[0]);
-		raw_to_proj(xr+1, yr+1, xg[1], yg[1]);
+        double xg[2], yg[2];
+        raw_to_proj(xr, yr, xg[0], yg[0]);
+        raw_to_proj(xr+1, yr+1, xg[1], yg[1]);
 
-		// The earths' circumference shrinks using a sin()
-		// curve as we go up in latitude.
-		const double dLatCircum = kdEarthCircumEquat
-			* sin(degrees_to_radians(90.0 - yg[0]));
+        // The earths' circumference shrinks using a sin()
+        // curve as we go up in latitude.
+        const double dLatCircum = kdEarthCircumEquat
+            * sin(degrees_to_radians(90.0 - yg[0]));
 
-		// Derive meter distance between geolongitudes
-		// in xg[0] and xg[1].
-		const double dx = fabs(xg[1] - xg[0]) / 360.0 * dLatCircum;
-		const double dy = fabs(yg[1] - yg[0]) / 360.0 * kdEarthCircumPolar;
+        // Derive meter distance between geolongitudes
+        // in xg[0] and xg[1].
+        const double dx = fabs(xg[1] - xg[0]) / 360.0 * dLatCircum;
+        const double dy = fabs(yg[1] - yg[0]) / 360.0 * kdEarthCircumPolar;
 
-		m_dElevScale = average(dx, dy);
-	}
+        m_dElevScale = average(dx, dy);
+    }
 
-	m_dElevBase = m_dLogSpan[0];
+    m_dElevBase = m_dLogSpan[0];
 
-	// Convert from ground units to elev units.
-	const measurement_unit* puG = this->get_uom(pszGroundUnits);
-	const measurement_unit* puE = this->get_uom(m_szElevUnits);
+    // Convert from ground units to elev units.
+    const measurement_unit* puG = this->get_uom(pszGroundUnits);
+    const measurement_unit* puE = this->get_uom(m_szElevUnits);
 
-	if(puG == NULL || puE == NULL)
-		return false;
+    if(puG == NULL || puE == NULL)
+        return false;
 
-	const double g_to_e = puG->dScale / puE->dScale;
+    const double g_to_e = puG->dScale / puE->dScale;
 
-	m_dElevScale *= g_to_e;
-	return true;
+    m_dElevScale *= g_to_e;
+    return true;
 }
 
-
 bool LevellerDataset::write_header()
 {
     char szHeader[5];
@@ -770,7 +766,7 @@ bool LevellerDataset::write_header()
         const int bHasECS =
             (units_elev != UNITLABEL_PIXEL && units_elev != UNITLABEL_UNKNOWN);
 
-	write_tag("coordsys_haselevm", bHasECS);
+        write_tag("coordsys_haselevm", bHasECS);
 
         OGRSpatialReference sr(m_pszProjection);
 
@@ -787,7 +783,6 @@ bool LevellerDataset::write_header()
             write_tag("coordsys_em_units", units_elev);
         }
 
-
         if(sr.IsLocal())
         {
             write_tag("csclass", LEV_COORDSYS_LOCAL);
@@ -795,44 +790,42 @@ bool LevellerDataset::write_header()
             const double dfLinear = sr.GetLinearUnits();
             const int n = this->meter_measure_to_code(dfLinear);
             write_tag("coordsys_units", n);
-		}
-		else
-		{
+        }
+        else
+        {
             write_tag("csclass", LEV_COORDSYS_GEO);
-		}
-
-		if( m_adfTransform[2] != 0.0 || m_adfTransform[4] != 0.0)
-		{
-			CPLError( CE_Failure, CPLE_IllegalArg,
-				"Cannot handle rotated geotransform" );
-			return false;
-		}
-
-		// todo: GDAL gridpost spacing is based on extent / rastersize
-		// instead of extent / (rastersize-1) like Leveller.
-		// We need to look into this and adjust accordingly.
-
-		// Write north-south digital axis.
-	    write_tag("coordsys_da0_style", LEV_DA_PIXEL_SIZED);
-            write_tag("coordsys_da0_fixedend", 0);
-            write_tag("coordsys_da0_v0", m_adfTransform[3]);
-            write_tag("coordsys_da0_v1", m_adfTransform[5]);
+        }
 
-		// Write east-west digital axis.
-	    write_tag("coordsys_da1_style", LEV_DA_PIXEL_SIZED);
-            write_tag("coordsys_da1_fixedend", 0);
-            write_tag("coordsys_da1_v0", m_adfTransform[0]);
-            write_tag("coordsys_da1_v1", m_adfTransform[1]);
-	}
+        if( m_adfTransform[2] != 0.0 || m_adfTransform[4] != 0.0)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "Cannot handle rotated geotransform" );
+            return false;
+        }
 
+        // todo: GDAL gridpost spacing is based on extent / rastersize
+        // instead of extent / (rastersize-1) like Leveller.
+        // We need to look into this and adjust accordingly.
+
+        // Write north-south digital axis.
+        write_tag("coordsys_da0_style", LEV_DA_PIXEL_SIZED);
+        write_tag("coordsys_da0_fixedend", 0);
+        write_tag("coordsys_da0_v0", m_adfTransform[3]);
+        write_tag("coordsys_da0_v1", m_adfTransform[5]);
+
+        // Write east-west digital axis.
+        write_tag("coordsys_da1_style", LEV_DA_PIXEL_SIZED);
+        write_tag("coordsys_da1_fixedend", 0);
+        write_tag("coordsys_da1_v0", m_adfTransform[0]);
+        write_tag("coordsys_da1_v1", m_adfTransform[1]);
+    }
 
-	this->write_tag_start("hf_data",
-		sizeof(float) * nRasterXSize * nRasterYSize);
+    this->write_tag_start("hf_data",
+                          sizeof(float) * nRasterXSize * nRasterYSize);
 
-	return true;
+    return true;
 }
 
-
 /************************************************************************/
 /*                          SetGeoTransform()                           */
 /************************************************************************/
@@ -841,10 +834,9 @@ CPLErr LevellerDataset::SetGeoTransform( double *padfGeoTransform )
 {
     memcpy(m_adfTransform, padfGeoTransform, sizeof(m_adfTransform));
 
-	return CE_None;
+    return CE_None;
 }
 
-
 /************************************************************************/
 /*                           SetProjection()                            */
 /************************************************************************/
@@ -853,46 +845,44 @@ CPLErr LevellerDataset::SetProjection( const char * pszNewProjection )
 {
     CPLFree(m_pszProjection);
 
-	m_pszProjection = CPLStrdup(pszNewProjection);
+    m_pszProjection = CPLStrdup(pszNewProjection);
 
-	return CE_None;
+    return CE_None;
 }
 
-
 /************************************************************************/
 /*                           Create()                                   */
 /************************************************************************/
 GDALDataset* LevellerDataset::Create
 (
-	const char* pszFilename,
+    const char* pszFilename,
     int nXSize, int nYSize, int nBands,
     GDALDataType eType, char** papszOptions
 )
 {
-	if(nBands != 1)
-	{
-		CPLError( CE_Failure, CPLE_IllegalArg, "Band count must be 1" );
-		return NULL;
-	}
-
-	if(eType != GDT_Float32)
-	{
-		CPLError( CE_Failure, CPLE_IllegalArg, "Pixel type must be Float32" );
-		return NULL;
-	}
+    if(nBands != 1)
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "Band count must be 1" );
+        return NULL;
+    }
 
-	if(nXSize < 2 || nYSize < 2)
-	{
-		CPLError( CE_Failure, CPLE_IllegalArg, "One or more raster dimensions too small" );
-		return NULL;
-	}
+    if(eType != GDT_Float32)
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "Pixel type must be Float32" );
+        return NULL;
+    }
 
+    if(nXSize < 2 || nYSize < 2)
+    {
+        CPLError( CE_Failure, CPLE_IllegalArg, "One or more raster dimensions too small" );
+        return NULL;
+    }
 
-	LevellerDataset* poDS = new LevellerDataset;
+    LevellerDataset* poDS = new LevellerDataset;
 
     poDS->eAccess = GA_Update;
 
-	poDS->m_pszFilename = CPLStrdup(pszFilename);
+    poDS->m_pszFilename = CPLStrdup(pszFilename);
 
     poDS->m_fp = VSIFOpenL( pszFilename, "wb+" );
 
@@ -901,30 +891,30 @@ GDALDataset* LevellerDataset::Create
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Attempt to create file `%s' failed.",
                   pszFilename );
-		delete poDS;
+        delete poDS;
         return NULL;
     }
 
-	// Header will be written the first time IWriteBlock
-	// is called.
+    // Header will be written the first time IWriteBlock
+    // is called.
 
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
 
     const char* pszValue = CSLFetchNameValue(
-		papszOptions,"MINUSERPIXELVALUE");
+        papszOptions,"MINUSERPIXELVALUE");
     if( pszValue != NULL )
         poDS->m_dLogSpan[0] = CPLAtof( pszValue );
-	else
-	{
-		delete poDS;
-		CPLError( CE_Failure, CPLE_IllegalArg,
-			"MINUSERPIXELVALUE must be specified." );
-		return NULL;
-	}
+    else
+    {
+        delete poDS;
+        CPLError( CE_Failure, CPLE_IllegalArg,
+                  "MINUSERPIXELVALUE must be specified." );
+        return NULL;
+    }
 
     pszValue = CSLFetchNameValue(
-		papszOptions,"MAXUSERPIXELVALUE");
+        papszOptions,"MAXUSERPIXELVALUE");
     if( pszValue != NULL )
         poDS->m_dLogSpan[1] = CPLAtof( pszValue );
 
@@ -950,87 +940,76 @@ GDALDataset* LevellerDataset::Create
     return poDS;
 }
 
-
 bool LevellerDataset::write_byte(size_t n)
 {
     unsigned char uch = static_cast<unsigned char>( n );
     return 1 == VSIFWriteL(&uch, 1, 1, m_fp);
 }
 
-
 bool LevellerDataset::write(int n)
 {
-	CPL_LSBPTR32(&n);
+    CPL_LSBPTR32(&n);
     return 1 == VSIFWriteL(&n, sizeof(n), 1, m_fp);
 }
 
-
 bool LevellerDataset::write(size_t n)
 {
-        GUInt32 n32 = (GUInt32)n;
-	CPL_LSBPTR32(&n32);
-	return (1 == VSIFWriteL(&n32, sizeof(n32), 1, m_fp));
+    GUInt32 n32 = (GUInt32)n;
+    CPL_LSBPTR32(&n32);
+    return 1 == VSIFWriteL(&n32, sizeof(n32), 1, m_fp);
 }
 
-
 bool LevellerDataset::write(double d)
 {
-	CPL_LSBPTR64(&d);
-	return (1 == VSIFWriteL(&d, sizeof(d), 1, m_fp));
+    CPL_LSBPTR64(&d);
+    return 1 == VSIFWriteL(&d, sizeof(d), 1, m_fp);
 }
 
-
-
 bool LevellerDataset::write_tag_start(const char* pszTag, size_t n)
 {
-	if(this->write_byte(strlen(pszTag)))
-	{
-		return (1 == VSIFWriteL(pszTag, strlen(pszTag), 1, m_fp)
-			&& this->write(n));
-	}
+    if(this->write_byte(strlen(pszTag)))
+    {
+        return (1 == VSIFWriteL(pszTag, strlen(pszTag), 1, m_fp)
+                && this->write(n));
+    }
 
-	return false;
+    return false;
 }
 
-
 bool LevellerDataset::write_tag(const char* pszTag, int n)
 {
-	return (this->write_tag_start(pszTag, sizeof(n))
-			&& this->write(n));
+    return (this->write_tag_start(pszTag, sizeof(n))
+            && this->write(n));
 }
 
-
 bool LevellerDataset::write_tag(const char* pszTag, size_t n)
 {
-	return (this->write_tag_start(pszTag, sizeof(n))
-			&& this->write(n));
+    return (this->write_tag_start(pszTag, sizeof(n))
+            && this->write(n));
 }
 
-
 bool LevellerDataset::write_tag(const char* pszTag, double d)
 {
-	return (this->write_tag_start(pszTag, sizeof(d))
-			&& this->write(d));
+    return (this->write_tag_start(pszTag, sizeof(d))
+            && this->write(d));
 }
 
-
 bool LevellerDataset::write_tag(const char* pszTag, const char* psz)
 {
-	CPLAssert(strlen(pszTag) <= kMaxTagNameLen);
-
-	char sz[kMaxTagNameLen + 1];
-	snprintf(sz, sizeof(sz), "%sl", pszTag);
-	const size_t len = strlen(psz);
-
-	if(len > 0 && this->write_tag(sz, len))
-	{
-		snprintf(sz, sizeof(sz), "%sd", pszTag);
-		this->write_tag_start(sz, len);
-		return (1 == VSIFWriteL(psz, len, 1, m_fp));
-	}
-	return false;
-}
+    CPLAssert(strlen(pszTag) <= kMaxTagNameLen);
 
+    char sz[kMaxTagNameLen + 1];
+    snprintf(sz, sizeof(sz), "%sl", pszTag);
+    const size_t len = strlen(psz);
+
+    if(len > 0 && this->write_tag(sz, len))
+    {
+        snprintf(sz, sizeof(sz), "%sd", pszTag);
+        this->write_tag_start(sz, len);
+        return 1 == VSIFWriteL(psz, len, 1, m_fp);
+    }
+    return false;
+}
 
 bool LevellerDataset::locate_data(vsi_l_offset& offset, size_t& len, VSILFILE* fp, const char* pszTag)
 {
@@ -1085,7 +1064,7 @@ bool LevellerDataset::locate_data(vsi_l_offset& offset, size_t& len, VSILFILE* f
 bool LevellerDataset::get(int& n, VSILFILE* fp, const char* psz)
 {
     vsi_l_offset offset;
-    size_t		 len;
+    size_t len;
 
     if(this->locate_data(offset, len, fp, psz))
     {
@@ -1107,7 +1086,7 @@ bool LevellerDataset::get(int& n, VSILFILE* fp, const char* psz)
 bool LevellerDataset::get(double& d, VSILFILE* fp, const char* pszTag)
 {
     vsi_l_offset offset;
-    size_t		 len;
+    size_t len;
 
     if(this->locate_data(offset, len, fp, pszTag))
     {
@@ -1120,7 +1099,6 @@ bool LevellerDataset::get(double& d, VSILFILE* fp, const char* pszTag)
     return false;
 }
 
-
 /************************************************************************/
 /*                                get()                                 */
 /************************************************************************/
@@ -1133,7 +1111,7 @@ bool LevellerDataset::get(char* pszValue, size_t maxchars, VSILFILE* fp, const c
     snprintf(szTag, sizeof(szTag), "%sd", pszTag);
 
     vsi_l_offset offset;
-    size_t		 len;
+    size_t len;
 
     if(this->locate_data(offset, len, fp, szTag))
     {
@@ -1150,37 +1128,32 @@ bool LevellerDataset::get(char* pszValue, size_t maxchars, VSILFILE* fp, const c
     return false;
 }
 
-
-
 UNITLABEL LevellerDataset::meter_measure_to_code(double dM) const
 {
-	// Convert a meter conversion factor to its UOM OEM code.
-	// If the factor is close to the approximation margin, then
-	// require exact equality, otherwise be loose.
+    // Convert a meter conversion factor to its UOM OEM code.
+    // If the factor is close to the approximation margin, then
+    // require exact equality, otherwise be loose.
 
-	const measurement_unit* pu = this->get_uom(dM);
-	return (pu != NULL ? pu->oemCode : UNITLABEL_UNKNOWN);
+    const measurement_unit* pu = this->get_uom(dM);
+    return pu != NULL ? pu->oemCode : UNITLABEL_UNKNOWN;
 }
 
-
 UNITLABEL LevellerDataset::id_to_code(const char* pszUnits) const
 {
-	// Convert a readable UOM to its OEM code.
+    // Convert a readable UOM to its OEM code.
 
-	const measurement_unit* pu = this->get_uom(pszUnits);
-	return (pu != NULL ? pu->oemCode : UNITLABEL_UNKNOWN);
+    const measurement_unit* pu = this->get_uom(pszUnits);
+    return pu != NULL ? pu->oemCode : UNITLABEL_UNKNOWN;
 }
 
-
 const char* LevellerDataset::code_to_id(UNITLABEL code) const
 {
-	// Convert a measurement unit's OEM ID to its readable ID.
+    // Convert a measurement unit's OEM ID to its readable ID.
 
-	const measurement_unit* pu = this->get_uom(code);
-	return (pu != NULL ? pu->pszID : NULL);
+    const measurement_unit* pu = this->get_uom(code);
+    return pu != NULL ? pu->pszID : NULL;
 }
 
-
 const measurement_unit* LevellerDataset::get_uom(const char* pszUnits) const
 {
     for(size_t i = 0; i < CPL_ARRAYSIZE(kUnits); i++)
@@ -1193,7 +1166,6 @@ const measurement_unit* LevellerDataset::get_uom(const char* pszUnits) const
     return NULL;
 }
 
-
 const measurement_unit* LevellerDataset::get_uom(UNITLABEL code) const
 {
     for(size_t i = 0; i < CPL_ARRAYSIZE(kUnits); i++)
@@ -1206,18 +1178,17 @@ const measurement_unit* LevellerDataset::get_uom(UNITLABEL code) const
     return NULL;
 }
 
-
 const measurement_unit* LevellerDataset::get_uom(double dM) const
 {
     for(size_t i = kFirstLinearMeasureIdx; i < CPL_ARRAYSIZE(kUnits); i++)
     {
-		if(dM >= 1.0e-4)
-		{
-			if(approx_equal(dM, kUnits[i].dScale))
-				return &kUnits[i];
-		}
-		else if(dM == kUnits[i].dScale)
-			return &kUnits[i];
+        if(dM >= 1.0e-4)
+        {
+            if(approx_equal(dM, kUnits[i].dScale))
+                return &kUnits[i];
+        }
+        else if(dM == kUnits[i].dScale)
+            return &kUnits[i];
     }
     CPLError( CE_Failure, CPLE_AppDefined,
               "Unknown measurement conversion factor: %f", dM );
@@ -1228,12 +1199,11 @@ const measurement_unit* LevellerDataset::get_uom(double dM) const
 /*                          convert_measure()                           */
 /************************************************************************/
 
-
 bool LevellerDataset::convert_measure
 (
-	double d,
-	double& dResult,
-	const char* pszSpace
+      double d,
+      double& dResult,
+      const char* pszSpace
 )
 {
     // Convert a measure to meters.
@@ -1241,29 +1211,27 @@ bool LevellerDataset::convert_measure
     for(size_t i = kFirstLinearMeasureIdx; i < CPL_ARRAYSIZE(kUnits); i++)
     {
         if(str_equal(pszSpace, kUnits[i].pszID))
-		{
+        {
             dResult = d * kUnits[i].dScale;
-			return true;
-		}
+            return true;
+        }
     }
     CPLError( CE_Failure, CPLE_FileIO,
               "Unknown linear measurement unit: '%s'", pszSpace );
     return false;
 }
 
-
 bool LevellerDataset::make_local_coordsys(const char* pszName, const char* pszUnits)
 {
-	OGRSpatialReference sr;
+    OGRSpatialReference sr;
 
-	sr.SetLocalCS(pszName);
-	double d;
+    sr.SetLocalCS(pszName);
+    double d;
     return ( convert_measure(1.0, d, pszUnits)
              && OGRERR_NONE == sr.SetLinearUnits(pszUnits, d)
              && OGRERR_NONE == sr.exportToWkt(&m_pszProjection) );
 }
 
-
 bool LevellerDataset::make_local_coordsys(const char* pszName, UNITLABEL code)
 {
     const char* pszUnitID = code_to_id(code);
@@ -1278,45 +1246,44 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
 {
     // get hf dimensions
     if(!get(nRasterXSize, file, "hf_w"))
-	{
-		CPLError( CE_Failure, CPLE_OpenFailed,
-					  "Cannot determine heightfield width." );
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Cannot determine heightfield width." );
         return false;
-	}
+    }
 
     if(!get(nRasterYSize, file, "hf_b"))
-	{
-		CPLError( CE_Failure, CPLE_OpenFailed,
-					  "Cannot determine heightfield breadth." );
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Cannot determine heightfield breadth." );
         return false;
-	}
+    }
 
-	if(nRasterXSize < 2 || nRasterYSize < 2)
-	{
-		CPLError( CE_Failure, CPLE_OpenFailed,
-					  "Heightfield raster dimensions too small." );
+    if(nRasterXSize < 2 || nRasterYSize < 2)
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Heightfield raster dimensions too small." );
         return false;
-	}
+    }
 
     // Record start of pixel data
     size_t datalen;
     if(!locate_data(m_nDataOffset, datalen, file, "hf_data"))
-	{
-		CPLError( CE_Failure, CPLE_OpenFailed,
-					  "Cannot locate elevation data." );
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Cannot locate elevation data." );
         return false;
-	}
+    }
 
     // Sanity check: do we have enough pixels?
     if(static_cast<GUIntBig>(datalen) != static_cast<GUIntBig>(nRasterXSize) * static_cast<GUIntBig>(nRasterYSize) * sizeof(float))
-	{
-		CPLError( CE_Failure, CPLE_OpenFailed,
-					  "File does not have enough data." );
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "File does not have enough data." );
         return false;
-	}
-
+    }
 
-	// Defaults for raster coordsys.
+    // Defaults for raster coordsys.
     m_adfTransform[0] = 0.0;
     m_adfTransform[1] = 1.0;
     m_adfTransform[2] = 0.0;
@@ -1324,9 +1291,9 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
     m_adfTransform[4] = 0.0;
     m_adfTransform[5] = 1.0;
 
-	m_dElevScale = 1.0;
+    m_dElevScale = 1.0;
     m_dElevBase = 0.0;
-	strcpy(m_szElevUnits, "");
+    strcpy(m_szElevUnits, "");
 
     if(m_version >= 7)
     {
@@ -1388,86 +1355,86 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
             }
         }
 
-		// Get vertical (elev) coordsys.
-		int bHasVertCS = FALSE;
-		if(this->get(bHasVertCS, file, "coordsys_haselevm") && bHasVertCS)
-		{
-                    get(m_dElevScale, file, "coordsys_em_scale");
-                    get(m_dElevBase, file, "coordsys_em_base");
-			UNITLABEL unitcode;
-                        int unitcode_int;
-			if(get(unitcode_int, file, "coordsys_em_units"))
-			{
-                            unitcode = static_cast<UNITLABEL>( unitcode_int );
-                            const char* pszUnitID = code_to_id(unitcode);
-				if(pszUnitID != NULL)
-                                {
-                                    strncpy(m_szElevUnits, pszUnitID, sizeof(m_szElevUnits));
-                                    m_szElevUnits[sizeof(m_szElevUnits) - 1] = '\0';
-                                }
-				else
-				{
-					CPLError( CE_Failure, CPLE_OpenFailed,
-								  "Unknown OEM elevation unit of measure (%d)",
-									unitcode );
-					return false;
-				}
-			}
-			// datum and localcs are currently unused.
-		}
-	}
-	else
-	{
-            // Legacy files use world units.
-	    char szWorldUnits[32];
-            strcpy(szWorldUnits, "m");
-
-	    double dWorldscale = 1.0;
-
-            if(get(dWorldscale, file, "hf_worldspacing"))
+        // Get vertical (elev) coordsys.
+        int bHasVertCS = FALSE;
+        if(this->get(bHasVertCS, file, "coordsys_haselevm") && bHasVertCS)
+        {
+            get(m_dElevScale, file, "coordsys_em_scale");
+            get(m_dElevBase, file, "coordsys_em_base");
+            UNITLABEL unitcode;
+            int unitcode_int;
+            if(get(unitcode_int, file, "coordsys_em_units"))
             {
-			//m_bHasWorldscale = true;
-                    if(get(szWorldUnits, sizeof(szWorldUnits)-1, file,
-                           "hf_worldspacinglabel"))
-			{
-				// Drop long name, if present.
-				char* p = strchr(szWorldUnits, ' ');
-				if(p != NULL)
-					*p = 0;
-			}
+                unitcode = static_cast<UNITLABEL>( unitcode_int );
+                const char* pszUnitID = code_to_id(unitcode);
+                if(pszUnitID != NULL)
+                {
+                    strncpy(m_szElevUnits, pszUnitID, sizeof(m_szElevUnits));
+                    m_szElevUnits[sizeof(m_szElevUnits) - 1] = '\0';
+                }
+                else
+                {
+                    CPLError( CE_Failure, CPLE_OpenFailed,
+                              "Unknown OEM elevation unit of measure (%d)",
+                              unitcode );
+                    return false;
+                }
+            }
+            // datum and localcs are currently unused.
+        }
+    }
+    else
+    {
+        // Legacy files use world units.
+      char szWorldUnits[32];
+      strcpy(szWorldUnits, "m");
+
+      double dWorldscale = 1.0;
+
+      if(get(dWorldscale, file, "hf_worldspacing"))
+      {
+          //m_bHasWorldscale = true;
+          if(get(szWorldUnits, sizeof(szWorldUnits)-1, file,
+                 "hf_worldspacinglabel"))
+          {
+              // Drop long name, if present.
+              char* p = strchr(szWorldUnits, ' ');
+              if(p != NULL)
+                  *p = 0;
+          }
 
 #if 0
-			// If the units are something besides m/ft/sft,
-			// then convert them to meters.
-
-			if(!str_equal("m", szWorldUnits)
-			   && !str_equal("ft", szWorldUnits)
-			   && !str_equal("sft", szWorldUnits))
-			{
-				dWorldscale = this->convert_measure(dWorldscale, szWorldUnits);
-				strcpy(szWorldUnits, "m");
-			}
+          // If the units are something besides m/ft/sft,
+          // then convert them to meters.
+
+          if(!str_equal("m", szWorldUnits)
+             && !str_equal("ft", szWorldUnits)
+             && !str_equal("sft", szWorldUnits))
+          {
+              dWorldscale = this->convert_measure(dWorldscale, szWorldUnits);
+              strcpy(szWorldUnits, "m");
+          }
 #endif
 
-			// Our extents are such that the origin is at the
-			// center of the heightfield.
-			m_adfTransform[0] = -0.5 * dWorldscale * (nRasterXSize-1);
-			m_adfTransform[3] = -0.5 * dWorldscale * (nRasterYSize-1);
-			m_adfTransform[1] = dWorldscale;
-			m_adfTransform[5] = dWorldscale;
-		}
-		m_dElevScale = dWorldscale; // this was 1.0 before because
-		// we were converting to real elevs ourselves, but
-		// some callers may want both the raw pixels and the
-		// transform to get real elevs.
-
-        if(!make_local_coordsys("Leveller world space", szWorldUnits))
-		{
-			CPLError( CE_Failure, CPLE_OpenFailed,
-						  "Cannot define local coordinate system." );
-			return false;
-		}
-	}
+          // Our extents are such that the origin is at the
+          // center of the heightfield.
+          m_adfTransform[0] = -0.5 * dWorldscale * (nRasterXSize-1);
+          m_adfTransform[3] = -0.5 * dWorldscale * (nRasterYSize-1);
+          m_adfTransform[1] = dWorldscale;
+          m_adfTransform[5] = dWorldscale;
+      }
+      m_dElevScale = dWorldscale; // this was 1.0 before because
+      // we were converting to real elevs ourselves, but
+      // some callers may want both the raw pixels and the
+      // transform to get real elevs.
+
+      if(!make_local_coordsys("Leveller world space", szWorldUnits))
+      {
+          CPLError( CE_Failure, CPLE_OpenFailed,
+                    "Cannot define local coordinate system." );
+          return false;
+      }
+    }
 
     return true;
 }
@@ -1476,7 +1443,7 @@ bool LevellerDataset::load_from_file(VSILFILE* file, const char* pszFilename)
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char*	LevellerDataset::GetProjectionRef(void)
+const char* LevellerDataset::GetProjectionRef(void)
 {
     return m_pszProjection == NULL ? "" : m_pszProjection;
 }
@@ -1547,9 +1514,8 @@ GDALDataset *LevellerDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     poDS->eAccess = poOpenInfo->eAccess;
 
-
 /* -------------------------------------------------------------------- */
-/*	Read the file.                                                  */
+/*      Read the file.                                                  */
 /* -------------------------------------------------------------------- */
     if( !poDS->load_from_file( poDS->m_fp, poOpenInfo->pszFilename ) )
     {
@@ -1581,7 +1547,7 @@ GDALDataset *LevellerDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/makefile.vc b/frmts/makefile.vc
index f91ea2f..0b52e0a 100644
--- a/frmts/makefile.vc
+++ b/frmts/makefile.vc
@@ -15,7 +15,7 @@ EXTRAFLAGS =	-DFRMT_ceos -DFRMT_aigrid -DFRMT_elas -DFRMT_hfa -DFRMT_gtiff\
 		-DFRMT_r -DFRMT_northwood -DFRMT_saga -DFRMT_xyz -DFRMT_hf2 \
 		-DFRMT_kmlsuperoverlay -DFRMT_ozi -DFRMT_ctg -DFRMT_e00grid \
 		-DFRMT_zmap -DFRMT_ngsgeoid -DFRMT_iris -DFRMT_map -DFRMT_cals \
-		-DFRMT_safe -DFRMT_sentinel2
+		-DFRMT_safe -DFRMT_sentinel2 -DFRMT_derived -DFRMT_prf
 
 MOREEXTRA 	=	
 
@@ -42,8 +42,10 @@ EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_bsb
 !IFDEF OGDIDIR
 EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_ogdi
 !ELSE
+!IFNDEF ZLIB_EXTERNAL_LIB
 EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_zlib
 !ENDIF
+!ENDIF
 
 !IFDEF JASPER_DIR
 EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_jpeg2000
@@ -65,6 +67,14 @@ PLUGINFLAGS	=	$(PLUGINFLAGS) -DFRMT_ecw
 !ENDIF
 !ENDIF
 
+!IFDEF LURATECH_CFLAGS
+!IF "$(JP2LURA_PLUGIN)" != "YES"
+EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_jp2lura
+!ELSE
+PLUGINFLAGS	=	$(PLUGINFLAGS) -DFRMT_jp2lura
+!ENDIF
+!ENDIF
+
 !IFDEF HDF4_DIR
 !IF "$(HDF4_PLUGIN)" != "YES"
 EXTRAFLAGS	=	$(EXTRAFLAGS) -DFRMT_hdf4
diff --git a/frmts/map/mapdataset.cpp b/frmts/map/mapdataset.cpp
index c0a592c..4a60ae2 100644
--- a/frmts/map/mapdataset.cpp
+++ b/frmts/map/mapdataset.cpp
@@ -33,7 +33,7 @@
 #include "ogr_geometry.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: mapdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: mapdataset.cpp 37430 2017-02-20 10:43:33Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -46,10 +46,10 @@ class CPL_DLL MAPDataset : public GDALDataset
     GDALDataset *poImageDS;
 
     char        *pszWKT;
-    int	        bGeoTransformValid;
+    int         bGeoTransformValid;
     double      adfGeoTransform[6];
     int         nGCPCount;
-    GDAL_GCP	*pasGCPList;
+    GDAL_GCP    *pasGCPList;
     OGRPolygon  *poNeatLine;
     CPLString   osImgFilename;
 
@@ -57,14 +57,14 @@ class CPL_DLL MAPDataset : public GDALDataset
     MAPDataset();
     virtual ~MAPDataset();
 
-    virtual const char* GetProjectionRef();
-    virtual CPLErr      GetGeoTransform( double * );
-    virtual int GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-    virtual char **GetFileList();
+    virtual const char* GetProjectionRef() override;
+    virtual CPLErr      GetGeoTransform( double * ) override;
+    virtual int GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
+    virtual char **GetFileList() override;
 
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo *poOpenInfo );
@@ -80,7 +80,7 @@ class MAPWrapperRasterBand : public GDALProxyRasterBand
   GDALRasterBand* poBaseBand;
 
   protected:
-    virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
+    virtual GDALRasterBand* RefUnderlyingRasterBand() override { return poBaseBand; }
 
   public:
     explicit MAPWrapperRasterBand( GDALRasterBand* poBaseBandIn )
@@ -239,15 +239,16 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      details like the band count and types.                          */
 /* -------------------------------------------------------------------- */
     poDS->osImgFilename = papszLines[2];
-    VSIStatBufL sStat;
-    if (VSIStatL(poDS->osImgFilename, &sStat) != 0)
+
+    const CPLString osPath = CPLGetPath(poOpenInfo->pszFilename);
+    if (CPLIsFilenameRelative(poDS->osImgFilename))
     {
-        const CPLString osPath = CPLGetPath(poOpenInfo->pszFilename);
-        if (CPLIsFilenameRelative(poDS->osImgFilename))
-        {
-            poDS->osImgFilename = CPLFormCIFilename(osPath, poDS->osImgFilename, NULL);
-        }
-        else
+        poDS->osImgFilename = CPLFormCIFilename(osPath, poDS->osImgFilename, NULL);
+    }
+    else
+    {
+        VSIStatBufL sStat;
+        if (VSIStatL(poDS->osImgFilename, &sStat) != 0)
         {
             poDS->osImgFilename = CPLGetFilename(poDS->osImgFilename);
             poDS->osImgFilename = CPLFormCIFilename(osPath, poDS->osImgFilename, NULL);
@@ -318,7 +319,7 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
     /* Create and fill the neatline polygon */
     if (bNeatLine)
     {
-        poDS->poNeatLine = new OGRPolygon();	/* Create a polygon to store the neatline */
+        poDS->poNeatLine = new OGRPolygon();   /* Create a polygon to store the neatline */
         OGRLinearRing* poRing = new OGRLinearRing();
 
         if ( poDS->bGeoTransformValid )        /* Compute the projected coordinates of the corners */
@@ -410,7 +411,7 @@ GDALDataset *MAPDataset::Open( GDALOpenInfo * poOpenInfo )
 
     CSLDestroy(papszLines);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -434,7 +435,6 @@ CPLErr MAPDataset::GetGeoTransform( double * padfTransform )
     return (nGCPCount == 0) ? CE_None : CE_Failure;
 }
 
-
 /************************************************************************/
 /*                           GetGCPCount()                              */
 /************************************************************************/
diff --git a/frmts/mbtiles/GNUmakefile b/frmts/mbtiles/GNUmakefile
index 6aee9b1..09969f2 100644
--- a/frmts/mbtiles/GNUmakefile
+++ b/frmts/mbtiles/GNUmakefile
@@ -7,7 +7,7 @@ ifeq ($(LIBZ_SETTING),internal)
   XTRA_OPT :=   $(XTRA_OPT) -I../zlib
 endif
 
-CPPFLAGS	:=	$(JSON_INCLUDE) $(XTRA_OPT)  $(CPPFLAGS) -I../../ogr -I../../ogr/ogrsf_frmts/gpkg -I../../ogr/ogrsf_frmts/sqlite $(SQLITE_INC)
+CPPFLAGS	:=	-I../../ogr/ogrsf_frmts/geojson $(JSON_INCLUDE) $(XTRA_OPT)  $(CPPFLAGS) -I../../ogr -I../../ogr/ogrsf_frmts/gpkg -I../../ogr/ogrsf_frmts/sqlite $(SQLITE_INC)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/mbtiles/frmt_mbtiles.html b/frmts/mbtiles/frmt_mbtiles.html
index 2e1722e..7fe5ab5 100644
--- a/frmts/mbtiles/frmt_mbtiles.html
+++ b/frmts/mbtiles/frmt_mbtiles.html
@@ -53,7 +53,7 @@ Defaults to AUTO.</li>
 <li><b>MAXY</b>=value: Maximum northing (in EPSG:3857) of the area of interest.</li>
 <li><b>USE_BOUNDS</b>=YES/NO: Whether to use the bounds metadata, when available, to determine the AOI. Defaults to YES.</li>
 <li><b>TILE_FORMAT</b>=PNG/PNG8/JPEG: Format used to store tiles. See
-<a href="#tile_format">Tile format</a> section. Only used in update mode. Defaults to PNG.</li>
+<a href="#tile_formats">Tile formats</a> section. Only used in update mode. Defaults to PNG.</li>
 <li><b>QUALITY</b>=1-100: Quality setting for JPEG compression. Only used in update mode. Default to 75.</li>
 <li><b>ZLEVEL</b>=1-9: DEFLATE compression level for PNG tiles. Only used in update mode. Default to 6.</li>
 <li><b>DITHER</b>=YES/NO: Whether to use Floyd-Steinberg dithering (for TILE_FORMAT=PNG8).
diff --git a/frmts/mbtiles/makefile.vc b/frmts/mbtiles/makefile.vc
index bc82f8d..da7d106 100644
--- a/frmts/mbtiles/makefile.vc
+++ b/frmts/mbtiles/makefile.vc
@@ -1,12 +1,18 @@
 
 OBJ	=	mbtilesdataset.obj
 
-EXTRAFLAGS = -I../../ogr -I../../ogr/ogrsf_frmts/gpkg  -I../../ogr/ogrsf_frmts/sqlite $(SQLITE_INC) -I../../ogr/ogrsf_frmts/geojson -I../../ogr/ogrsf_frmts/geojson/libjson -I../zlib
+EXTRAFLAGS = -I../../ogr -I../../ogr/ogrsf_frmts/gpkg  -I../../ogr/ogrsf_frmts/sqlite $(SQLITE_INC) -I../../ogr/ogrsf_frmts/geojson -I../../ogr/ogrsf_frmts/geojson/libjson $(ZLIB_FLAGS)
 
 GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
+!IFDEF ZLIB_EXTERNAL_LIB
+ZLIB_FLAGS = $(ZLIB_INC)
+!ELSE
+ZLIB_FLAGS = -I..\zlib
+!ENDIF
+
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\o
 
diff --git a/frmts/mbtiles/mbtilesdataset.cpp b/frmts/mbtiles/mbtilesdataset.cpp
index 9ad9088..a1a3909 100644
--- a/frmts/mbtiles/mbtilesdataset.cpp
+++ b/frmts/mbtiles/mbtilesdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: mbtilesdataset.cpp 35569 2016-09-30 19:39:05Z rouault $
  *
  * Project:  GDAL MBTiles driver
  * Purpose:  Implement GDAL MBTiles support using OGR SQLite driver
@@ -35,11 +34,12 @@
 #include "gdalwarper.h"
 
 #include "zlib.h"
-#include "json.h"
+#include "ogrgeojsonreader.h"
 
 #include <math.h>
+#include <algorithm>
 
-CPL_CVSID("$Id: mbtilesdataset.cpp 35569 2016-09-30 19:39:05Z rouault $");
+CPL_CVSID("$Id: mbtilesdataset.cpp 37720 2017-03-16 16:34:39Z rouault $");
 
 static const char * const apszAllowedDrivers[] = {"JPEG", "PNG", NULL};
 
@@ -83,20 +83,20 @@ class MBTilesDataset : public GDALPamDataset, public GDALGPKGMBTilesLikePseudoDa
 
     virtual     ~MBTilesDataset();
 
-    virtual CPLErr GetGeoTransform(double* padfGeoTransform);
-    virtual CPLErr SetGeoTransform( double* padfGeoTransform );
-    virtual const char* GetProjectionRef();
-    virtual CPLErr SetProjection( const char* pszProjection );
+    virtual CPLErr GetGeoTransform(double* padfGeoTransform) override;
+    virtual CPLErr SetGeoTransform( double* padfGeoTransform ) override;
+    virtual const char* GetProjectionRef() override;
+    virtual CPLErr SetProjection( const char* pszProjection ) override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char      **GetMetadata( const char * pszDomain = "" );
-    virtual const char *GetMetadataItem( const char* pszName, const char * pszDomain = "" );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
+    virtual const char *GetMetadataItem( const char* pszName, const char * pszDomain = "" ) override;
 
     virtual CPLErr    IBuildOverviews(
                         const char * pszResampling,
                         int nOverviews, int * panOverviewList,
                         int nBandsIn, CPL_UNUSED int * panBandList,
-                        GDALProgressFunc pfnProgress, void * pProgressData );
+                        GDALProgressFunc pfnProgress, void * pProgressData ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -131,9 +131,7 @@ class MBTilesDataset : public GDALPamDataset, public GDALGPKGMBTilesLikePseudoDa
     OGRDataSourceH hDS;
     sqlite3* hDB;
 
-#ifdef HAVE_SQLITE_VFS
     sqlite3_vfs*        pMyVFS;
-#endif
 
     bool bFetchedMetadata;
     CPLStringList aosList;
@@ -163,17 +161,16 @@ class MBTilesDataset : public GDALPamDataset, public GDALGPKGMBTilesLikePseudoDa
     protected:
         // Coming from GDALGPKGMBTilesLikePseudoDataset
 
-        virtual CPLErr                  IFlushCacheWithErrCode();
-        virtual int                     IGetRasterCount() { return nBands; }
-        virtual GDALRasterBand*         IGetRasterBand(int nBand) { return GetRasterBand(nBand); }
-        virtual sqlite3                *IGetDB() { return hDB; }
-        virtual bool                    IGetUpdate() { return eAccess == GA_Update; }
-        virtual bool                    ICanIWriteBlock();
-        virtual OGRErr                  IStartTransaction();
-        virtual OGRErr                  ICommitTransaction();
-        virtual const char             *IGetFilename() { return GetDescription(); }
-        virtual int                     GetRowFromIntoTopConvention(int nRow);
-
+        virtual CPLErr                  IFlushCacheWithErrCode() override;
+        virtual int                     IGetRasterCount() override { return nBands; }
+        virtual GDALRasterBand*         IGetRasterBand(int nBand) override { return GetRasterBand(nBand); }
+        virtual sqlite3                *IGetDB() override { return hDB; }
+        virtual bool                    IGetUpdate() override { return eAccess == GA_Update; }
+        virtual bool                    ICanIWriteBlock() override;
+        virtual OGRErr                  IStartTransaction() override;
+        virtual OGRErr                  ICommitTransaction() override;
+        virtual const char             *IGetFilename() override { return GetDescription(); }
+        virtual int                     GetRowFromIntoTopConvention(int nRow) override;
 };
 
 /************************************************************************/
@@ -189,14 +186,14 @@ class MBTilesBand: public GDALGPKGMBTilesLikeRasterBand
     CPLString               osLocationInfo;
 
   public:
-                            MBTilesBand( MBTilesDataset* poDS );
+    explicit                MBTilesBand( MBTilesDataset* poDS );
 
-    virtual int             GetOverviewCount();
-    virtual GDALRasterBand* GetOverview(int nLevel);
+    virtual int             GetOverviewCount() override;
+    virtual GDALRasterBand* GetOverview(int nLevel) override;
 
-    virtual char      **GetMetadataDomainList();
+    virtual char      **GetMetadataDomainList() override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
 };
 
 /************************************************************************/
@@ -287,7 +284,6 @@ bool MBTilesDataset::HasNonEmptyGrids()
 {
     OGRLayerH hSQLLyr;
     OGRFeatureH hFeat;
-    const char* pszSQL;
 
     if (poMainDS)
         return poMainDS->HasNonEmptyGrids();
@@ -300,14 +296,14 @@ bool MBTilesDataset::HasNonEmptyGrids()
     if (OGR_DS_GetLayerByName(hDS, "grids") == NULL)
         return false;
 
-    pszSQL = "SELECT type FROM sqlite_master WHERE name = 'grids'";
+    const char* pszSQL = "SELECT type FROM sqlite_master WHERE name = 'grids'";
     CPLDebug("MBTILES", "%s", pszSQL);
     hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
     if (hSQLLyr == NULL)
         return false;
 
     hFeat = OGR_L_GetNextFeature(hSQLLyr);
-    if (hFeat == NULL || !OGR_F_IsFieldSet(hFeat, 0))
+    if (hFeat == NULL || !OGR_F_IsFieldSetAndNotNull(hFeat, 0))
     {
         OGR_F_Destroy(hFeat);
         OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
@@ -347,7 +343,8 @@ bool MBTilesDataset::HasNonEmptyGrids()
 
 char* MBTilesDataset::FindKey(int iPixel, int iLine)
 {
-    const int nBlockXSize = 256, nBlockYSize = 256;
+    const int nBlockXSize = 256;
+    const int nBlockYSize = 256;
 
     // Compute shift between GDAL origin and TileMatrixSet origin
     // Caution this is in GeoPackage / WMTS convention ! That is upper-left corner
@@ -367,23 +364,22 @@ char* MBTilesDataset::FindKey(int iPixel, int iLine)
 
     OGRLayerH hSQLLyr;
     OGRFeatureH hFeat;
-    const char* pszSQL;
     json_object* poGrid = NULL;
     int i;
 
     /* See https://github.com/mapbox/utfgrid-spec/blob/master/1.0/utfgrid.md */
     /* for the explanation of the following process */
-
-    pszSQL = CPLSPrintf("SELECT grid FROM grids WHERE "
-                        "zoom_level = %d AND tile_column = %d AND tile_row = %d",
-                        m_nZoomLevel, nTileColumn, nTileRow);
+    const char* pszSQL =
+        CPLSPrintf("SELECT grid FROM grids WHERE "
+                   "zoom_level = %d AND tile_column = %d AND tile_row = %d",
+                   m_nZoomLevel, nTileColumn, nTileRow);
     CPLDebug("MBTILES", "%s", pszSQL);
     hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
     if (hSQLLyr == NULL)
         return NULL;
 
     hFeat = OGR_L_GetNextFeature(hSQLLyr);
-    if (hFeat == NULL || !OGR_F_IsFieldSet(hFeat, 0))
+    if (hFeat == NULL || !OGR_F_IsFieldSetAndNotNull(hFeat, 0))
     {
         OGR_F_Destroy(hFeat);
         OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
@@ -450,7 +446,7 @@ char* MBTilesDataset::FindKey(int iPixel, int iLine)
 
     if (json_object_is_type(jsobj, json_type_object))
     {
-        poGrid = json_object_object_get(jsobj, "grid");
+        poGrid = CPL_json_object_object_get(jsobj, "grid");
     }
     if (poGrid != NULL && json_object_is_type(poGrid, json_type_array))
     {
@@ -520,7 +516,7 @@ char* MBTilesDataset::FindKey(int iPixel, int iLine)
             }
 
             /* Find key */
-            json_object* poKeys = json_object_object_get(jsobj, "keys");
+            json_object* poKeys = CPL_json_object_object_get(jsobj, "keys");
             if (nKey >= 0 && poKeys != NULL &&
                 json_object_is_type(poKeys, json_type_array) &&
                 nKey < json_object_array_length(poKeys))
@@ -640,19 +636,19 @@ const char *MBTilesBand::GetMetadataItem( const char * pszName,
             if (OGR_DS_GetLayerByName(poGDS->hDS, "grid_data") != NULL &&
                 strchr(pszKey, '\'') == NULL)
             {
-                const char* pszSQL;
                 OGRLayerH hSQLLyr;
                 OGRFeatureH hFeat;
 
-                pszSQL = CPLSPrintf("SELECT key_json FROM keymap WHERE "
-                                    "key_name = '%s'",
-                                    pszKey);
+                const char* pszSQL =
+                    CPLSPrintf("SELECT key_json FROM keymap WHERE "
+                               "key_name = '%s'",
+                               pszKey);
                 CPLDebug("MBTILES", "%s", pszSQL);
                 hSQLLyr = OGR_DS_ExecuteSQL(poGDS->hDS, pszSQL, NULL, NULL);
                 if (hSQLLyr)
                 {
                     hFeat = OGR_L_GetNextFeature(hSQLLyr);
-                    if (hFeat != NULL && OGR_F_IsFieldSet(hFeat, 0))
+                    if (hFeat != NULL && OGR_F_IsFieldSetAndNotNull(hFeat, 0))
                     {
                         const char* pszJSon = OGR_F_GetFieldAsString(hFeat, 0);
                         //CPLDebug("MBTILES", "JSon = %s", pszJSon);
@@ -735,9 +731,8 @@ MBTilesDataset::MBTilesDataset()
     bFetchedMetadata = false;
     nHasNonEmptyGrids = -1;
     hDB = NULL;
-#ifdef HAVE_SQLITE_VFS
     pMyVFS = NULL;
-#endif
+
     m_bGeoTransformValid = false;
     m_adfGeoTransform[0] = 0.0;
     m_adfGeoTransform[1] = 1.0;
@@ -777,14 +772,12 @@ MBTilesDataset::~MBTilesDataset()
         {
             sqlite3_close(hDB);
 
-#ifdef HAVE_SQLITE_VFS
             if (pMyVFS)
             {
                 sqlite3_vfs_unregister(pMyVFS);
                 CPLFree(pMyVFS->pAppData);
                 CPLFree(pMyVFS);
             }
-#endif
         }
     }
 }
@@ -956,7 +949,8 @@ CPLErr MBTilesDataset::SetGeoTransform( double* padfGeoTransform )
 
         // Clamp latitude so that when transformed back to EPSG:3857, we don't
         // have too big northings
-        double tmpx = 0, ok_maxy = MAX_GM;
+        double tmpx = 0.0;
+        double ok_maxy = MAX_GM;
         SphericalMercatorToLongLat(&tmpx, &ok_maxy);
         if( maxy > ok_maxy)
             maxy = ok_maxy;
@@ -1013,7 +1007,6 @@ void MBTilesDataset::ComputeTileAndPixelShifts()
     int nShiftYPixels = (int)floor(0.5 + (m_adfGeoTransform[3] - TMS_ORIGIN_Y) /  m_adfGeoTransform[5]);
     m_nShiftYTiles = (int)floor(1.0 * nShiftYPixels / nTileHeight);
     m_nShiftYPixelsMod = ((nShiftYPixels % nTileHeight) + nTileHeight) % nTileHeight;
-
 }
 
 /************************************************************************/
@@ -1191,7 +1184,7 @@ char** MBTilesDataset::GetMetadata( const char * pszDomain )
     aosList = CPLStringList(GDALPamDataset::GetMetadata(), FALSE);
 
     OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS,
-            "SELECT name, value FROM metadata", NULL, NULL);
+            "SELECT name, value FROM metadata LIMIT 1000", NULL, NULL);
     if (hSQLLyr == NULL)
         return NULL;
 
@@ -1204,7 +1197,7 @@ char** MBTilesDataset::GetMetadata( const char * pszDomain )
     OGRFeatureH hFeat;
     while( (hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL )
     {
-        if (OGR_F_IsFieldSet(hFeat, 0) && OGR_F_IsFieldSet(hFeat, 1))
+        if (OGR_F_IsFieldSetAndNotNull(hFeat, 0) && OGR_F_IsFieldSetAndNotNull(hFeat, 1))
         {
             const char* pszName = OGR_F_GetFieldAsString(hFeat, 0);
             const char* pszValue = OGR_F_GetFieldAsString(hFeat, 1);
@@ -1266,13 +1259,13 @@ static
 int MBTilesGetMinMaxZoomLevel(OGRDataSourceH hDS, int bHasMap,
                                 int &nMinLevel, int &nMaxLevel)
 {
-    const char* pszSQL;
     OGRLayerH hSQLLyr;
     OGRFeatureH hFeat;
     int bHasMinMaxLevel = FALSE;
 
-    pszSQL = "SELECT value FROM metadata WHERE name = 'minzoom' UNION ALL "
-             "SELECT value FROM metadata WHERE name = 'maxzoom'";
+    const char* pszSQL =
+        "SELECT value FROM metadata WHERE name = 'minzoom' UNION ALL "
+        "SELECT value FROM metadata WHERE name = 'maxzoom'";
     CPLDebug("MBTILES", "%s", pszSQL);
     hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
     if (hSQLLyr)
@@ -1281,7 +1274,7 @@ int MBTilesGetMinMaxZoomLevel(OGRDataSourceH hDS, int bHasMap,
         if (hFeat)
         {
             int bHasMinLevel = FALSE;
-            if (OGR_F_IsFieldSet(hFeat, 0))
+            if (OGR_F_IsFieldSetAndNotNull(hFeat, 0))
             {
                 nMinLevel = OGR_F_GetFieldAsInteger(hFeat, 0);
                 bHasMinLevel = TRUE;
@@ -1293,7 +1286,7 @@ int MBTilesGetMinMaxZoomLevel(OGRDataSourceH hDS, int bHasMap,
                 hFeat = OGR_L_GetNextFeature(hSQLLyr);
                 if (hFeat)
                 {
-                    if (OGR_F_IsFieldSet(hFeat, 0))
+                    if (OGR_F_IsFieldSetAndNotNull(hFeat, 0))
                     {
                         nMaxLevel = OGR_F_GetFieldAsInteger(hFeat, 0);
                         bHasMinMaxLevel = TRUE;
@@ -1368,7 +1361,7 @@ int MBTilesGetMinMaxZoomLevel(OGRDataSourceH hDS, int bHasMap,
             return FALSE;
         }
 
-        if (OGR_F_IsFieldSet(hFeat, 0) && OGR_F_IsFieldSet(hFeat, 1))
+        if (OGR_F_IsFieldSetAndNotNull(hFeat, 0) && OGR_F_IsFieldSetAndNotNull(hFeat, 1))
         {
             nMinLevel = OGR_F_GetFieldAsInteger(hFeat, 0);
             nMaxLevel = OGR_F_GetFieldAsInteger(hFeat, 1);
@@ -1411,14 +1404,13 @@ bool MBTilesGetBounds(OGRDataSourceH hDS, bool bUseBounds,
                      double& minX, double& minY,
                      double& maxX, double& maxY)
 {
-    const char* pszSQL;
     bool bHasBounds = false;
     OGRLayerH hSQLLyr;
     OGRFeatureH hFeat;
 
     if( bUseBounds )
     {
-        pszSQL = "SELECT value FROM metadata WHERE name = 'bounds'";
+        const char* pszSQL = "SELECT value FROM metadata WHERE name = 'bounds'";
         CPLDebug("MBTILES", "%s", pszSQL);
         hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
         if (hSQLLyr)
@@ -1466,9 +1458,10 @@ bool MBTilesGetBounds(OGRDataSourceH hDS, bool bUseBounds,
 
     if (!bHasBounds)
     {
-        pszSQL = CPLSPrintf("SELECT min(tile_column), max(tile_column), "
-                            "min(tile_row), max(tile_row) FROM tiles "
-                            "WHERE zoom_level = %d", nMaxLevel);
+        const char* pszSQL =
+            CPLSPrintf("SELECT min(tile_column), max(tile_column), "
+                       "min(tile_row), max(tile_row) FROM tiles "
+                       "WHERE zoom_level = %d", nMaxLevel);
         CPLDebug("MBTILES", "%s", pszSQL);
         hSQLLyr = OGR_DS_ExecuteSQL(hDS, pszSQL, NULL, NULL);
         if (hSQLLyr == NULL)
@@ -1483,10 +1476,10 @@ bool MBTilesGetBounds(OGRDataSourceH hDS, bool bUseBounds,
             return false;
         }
 
-        if (OGR_F_IsFieldSet(hFeat, 0) &&
-            OGR_F_IsFieldSet(hFeat, 1) &&
-            OGR_F_IsFieldSet(hFeat, 2) &&
-            OGR_F_IsFieldSet(hFeat, 3))
+        if (OGR_F_IsFieldSetAndNotNull(hFeat, 0) &&
+            OGR_F_IsFieldSetAndNotNull(hFeat, 1) &&
+            OGR_F_IsFieldSetAndNotNull(hFeat, 2) &&
+            OGR_F_IsFieldSetAndNotNull(hFeat, 3))
         {
             int nMinTileCol = OGR_F_GetFieldAsInteger(hFeat, 0);
             int nMaxTileCol = OGR_F_GetFieldAsInteger(hFeat, 1);
@@ -1627,7 +1620,6 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS,
 {
     OGRLayerH hSQLLyr;
     OGRFeatureH hFeat;
-    const char* pszSQL;
     VSILFILE* fpCURLOGR = NULL;
     int bFirstSelect = TRUE;
 
@@ -1648,7 +1640,7 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS,
             hFeat = OGR_L_GetNextFeature(hSQLLyr);
             if (hFeat)
             {
-                if (OGR_F_IsFieldSet(hFeat, 0))
+                if (OGR_F_IsFieldSetAndNotNull(hFeat, 0))
                 {
                     const char* pszPointer = OGR_F_GetFieldAsString(hFeat, 0);
                     fpCURLOGR = (VSILFILE* )CPLScanPointer( pszPointer, static_cast<int>(strlen(pszPointer)) );
@@ -1659,11 +1651,12 @@ int MBTilesGetBandCount(OGRDataSourceH &hDS,
         }
     }
 
-    pszSQL = CPLSPrintf("SELECT tile_data FROM tiles WHERE "
-                            "tile_column = %d AND tile_row = %d AND zoom_level = %d",
-                            (nMinTileCol  + nMaxTileCol) / 2,
-                            (nMinTileRow  + nMaxTileRow) / 2,
-                            nMaxLevel);
+    const char* pszSQL =
+        CPLSPrintf("SELECT tile_data FROM tiles WHERE "
+                   "tile_column = %d AND tile_row = %d AND zoom_level = %d",
+                   (nMinTileCol  + nMaxTileCol) / 2,
+                   (nMinTileRow  + nMaxTileRow) / 2,
+                   nMaxLevel);
     CPLDebug("MBTILES", "%s", pszSQL);
 
     if (fpCURLOGR)
@@ -1831,7 +1824,8 @@ GDALDataset* MBTilesDataset::Open(GDALOpenInfo* poOpenInfo)
         OGRFeatureH hFeat;
         int nBands;
         OGRLayerH hSQLLyr = NULL;
-        int nMinLevel = -1, nMaxLevel = -1;
+        int nMinLevel = -1;
+        int nMaxLevel = -1;
         int bHasMinMaxLevel = FALSE;
         int bHasMap;
 
@@ -1858,7 +1852,7 @@ GDALDataset* MBTilesDataset::Open(GDALOpenInfo* poOpenInfo)
                 hFeat = OGR_L_GetNextFeature(hSQLLyr);
                 if (hFeat)
                 {
-                    if (OGR_F_IsFieldSet(hFeat, 0))
+                    if (OGR_F_IsFieldSetAndNotNull(hFeat, 0))
                     {
                         bHasMap = strcmp(OGR_F_GetFieldAsString(hFeat, 0),
                                          "view") == 0;
@@ -1908,7 +1902,10 @@ GDALDataset* MBTilesDataset::Open(GDALOpenInfo* poOpenInfo)
 /* -------------------------------------------------------------------- */
 /*      Get bounds                                                      */
 /* -------------------------------------------------------------------- */
-        double dfMinX = 0.0, dfMinY = 0.0, dfMaxX = 0.0, dfMaxY = 0.0;
+        double dfMinX = 0.0;
+        double dfMinY = 0.0;
+        double dfMaxX = 0.0;
+        double dfMaxY = 0.0;
         bool bUseBounds = CPLFetchBool(const_cast<const char**>(poOpenInfo->papszOpenOptions),
                                       "USE_BOUNDS", true);
         const char* pszMinX = CSLFetchNameValue(poOpenInfo->papszOpenOptions, "MINX");
@@ -1953,7 +1950,8 @@ GDALDataset* MBTilesDataset::Open(GDALOpenInfo* poOpenInfo)
             nBands = MBTilesGetBandCount(hDS, nMaxLevel,
                                          nMinTileRow, nMaxTileRow,
                                          nMinTileCol, nMaxTileCol);
-            if (nBands < 0)
+            // Map RGB to RGBA since we can guess wrong (see #6836)
+            if (nBands < 0 || nBands == 3)
                 nBands = 4;
         }
 
@@ -2093,7 +2091,6 @@ bool MBTilesDataset::CreateInternal( const char * pszFilename,
     SetDescription( pszFilename );
 
     int rc;
-#ifdef HAVE_SQLITE_VFS
     if (STARTS_WITH(pszFilename, "/vsi"))
     {
         pMyVFS = OGRSQLiteCreateVFS(NULL, NULL);
@@ -2101,7 +2098,6 @@ bool MBTilesDataset::CreateInternal( const char * pszFilename,
         rc = sqlite3_open_v2( pszFilename, &hDB, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, pMyVFS->zName );
     }
     else
-#endif
     {
         rc = sqlite3_open( pszFilename, &hDB );
     }
@@ -2133,11 +2129,9 @@ bool MBTilesDataset::CreateInternal( const char * pszFilename,
         return false;
     }
 
-    char* pszSQL;
-
     const char* pszName = CSLFetchNameValueDef(papszOptions, "NAME",
                                                CPLGetBasename(pszFilename));
-    pszSQL = sqlite3_mprintf(
+    char* pszSQL = sqlite3_mprintf(
         "INSERT INTO metadata (name, value) VALUES ('name', '%q')", pszName );
     sqlite3_exec( hDB, pszSQL, NULL, NULL, NULL );
     sqlite3_free(pszSQL);
@@ -2257,7 +2251,7 @@ GDALDataset* MBTilesDataset::CreateCopy( const char *pszFilename,
     GDALDestroyGenImgProjTransformer( hTransformArg );
     hTransformArg = NULL;
 
-    // Hack to compensate for  GDALSuggestedWarpOutput2() failure when 
+    // Hack to compensate for  GDALSuggestedWarpOutput2() failure when
     // reprojection latitude = +/- 90 to EPSG:3857
     double adfSrcGeoTransform[6];
     if( poSrcDS->GetGeoTransform(adfSrcGeoTransform) == CE_None )
@@ -2269,8 +2263,16 @@ GDALDataset* MBTilesDataset::CreateCopy( const char *pszFilename,
             if( oSRS.SetFromUserInput( pszSrcWKT ) == OGRERR_NONE &&
                 oSRS.IsGeographic() )
             {
-                double minLat = MIN( adfSrcGeoTransform[3], adfSrcGeoTransform[3] + poSrcDS->GetRasterYSize() * adfSrcGeoTransform[5] );
-                double maxLat = MAX( adfSrcGeoTransform[3], adfSrcGeoTransform[3] + poSrcDS->GetRasterYSize() * adfSrcGeoTransform[5] );
+                const double minLat =
+                    std::min(
+                        adfSrcGeoTransform[3],
+                        adfSrcGeoTransform[3] +
+                        poSrcDS->GetRasterYSize() * adfSrcGeoTransform[5]);
+                const double maxLat =
+                    std::max(
+                         adfSrcGeoTransform[3],
+                         adfSrcGeoTransform[3] +
+                         poSrcDS->GetRasterYSize() * adfSrcGeoTransform[5]);
                 double maxNorthing = adfGeoTransform[3];
                 double minNorthing = adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
                 bool bChanged = false;
@@ -2297,7 +2299,8 @@ GDALDataset* MBTilesDataset::CreateCopy( const char *pszFilename,
 
     int nZoomLevel;
     double dfComputedRes = adfGeoTransform[1];
-    double dfPrevRes = 0, dfRes = 0;
+    double dfPrevRes = 0.0;
+    double dfRes = 0.0;
     const double dfPixelXSizeZoomLevel0 = 2 * MAX_GM / 256;
     for(nZoomLevel = 0; nZoomLevel < 25; nZoomLevel++)
     {
@@ -2558,7 +2561,8 @@ CPLErr MBTilesDataset::IBuildOverviews(
             return CE_Failure;
         }
 
-        int nRows = 0, nCols = 0;
+        int nRows = 0;
+        int nCols = 0;
         char** papszResult = NULL;
         sqlite3_get_table(hDB, "SELECT * FROM metadata WHERE name = 'minzoom'", &papszResult, &nRows, &nCols, NULL);
         sqlite3_free_table(papszResult);
@@ -2646,9 +2650,10 @@ CPLErr MBTilesDataset::IBuildOverviews(
 
     if( eErr == CE_None )
     {
-        int nRows = 0, nCols = 0;
+        int nRows = 0;
+        int nCols = 0;
         char** papszResult = NULL;
-        sqlite3_get_table(hDB, "SELECT * FROM metadata WHERE name = 'minzoom'", &papszResult, &nRows, &nCols, NULL);
+        sqlite3_get_table(hDB, "SELECT * FROM metadata WHERE name = 'minzoom' LIMIT 2", &papszResult, &nRows, &nCols, NULL);
         sqlite3_free_table(papszResult);
         if( nRows == 1 )
         {
diff --git a/frmts/mem/memdataset.cpp b/frmts/mem/memdataset.cpp
index 1c2e48f..3cfde05 100644
--- a/frmts/mem/memdataset.cpp
+++ b/frmts/mem/memdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: memdataset.cpp 33838 2016-03-31 20:42:32Z goatbar $
  *
  * Project:  Memory Array Translator
  * Purpose:  Complete implementation.
@@ -28,11 +27,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "memdataset.h"
+
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+
+#include <vector>
+
+#include "cpl_config.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
-#include "memdataset.h"
 
-CPL_CVSID("$Id: memdataset.cpp 33838 2016-03-31 20:42:32Z goatbar $");
+CPL_CVSID("$Id: memdataset.cpp 37462 2017-02-26 02:13:03Z goatbar $");
 
 /************************************************************************/
 /*                        MEMCreateRasterBand()                         */
@@ -69,13 +83,45 @@ GDALRasterBandH MEMCreateRasterBandEx( GDALDataset *poDS, int nBand,
 /*                           MEMRasterBand()                            */
 /************************************************************************/
 
+MEMRasterBand::MEMRasterBand( GByte *pabyDataIn, GDALDataType eTypeIn,
+                              int nXSizeIn, int nYSizeIn ) :
+    GDALPamRasterBand(FALSE),
+    pabyData(pabyDataIn),
+    nPixelOffset(0),
+    nLineOffset(0),
+    bOwnData(true),
+    bNoDataSet(FALSE),
+    dfNoData(0.0),
+    poColorTable(NULL),
+    eColorInterp(GCI_Undefined),
+    pszUnitType(NULL),
+    papszCategoryNames(NULL),
+    dfOffset(0.0),
+    dfScale(1.0),
+    psSavedHistograms(NULL)
+{
+    eAccess = GA_Update;
+    eDataType = eTypeIn;
+    nRasterXSize = nXSizeIn;
+    nRasterYSize = nYSizeIn;
+    nBlockXSize = nXSizeIn;
+    nBlockYSize = 1;
+    nPixelOffset = GDALGetDataTypeSizeBytes(eTypeIn);
+    nLineOffset = nPixelOffset * static_cast<size_t>(nBlockXSize);
+}
+
+/************************************************************************/
+/*                           MEMRasterBand()                            */
+/************************************************************************/
+
 MEMRasterBand::MEMRasterBand( GDALDataset *poDSIn, int nBandIn,
                               GByte *pabyDataIn, GDALDataType eTypeIn,
                               GSpacing nPixelOffsetIn, GSpacing nLineOffsetIn,
-                              int bAssumeOwnership, const char * pszPixelType) :
+                              int bAssumeOwnership, const char * pszPixelType ) :
     GDALPamRasterBand(FALSE),
     pabyData(pabyDataIn),
-    // Skip nPixelOffset and nLineOffset.
+    nPixelOffset(nPixelOffsetIn),
+    nLineOffset(nLineOffsetIn),
     bOwnData(bAssumeOwnership),
     bNoDataSet(FALSE),
     dfNoData(0.0),
@@ -98,14 +144,10 @@ MEMRasterBand::MEMRasterBand( GDALDataset *poDSIn, int nBandIn,
     nBlockYSize = 1;
 
     if( nPixelOffsetIn == 0 )
-        nPixelOffsetIn = GDALGetDataTypeSizeBytes(eTypeIn);
+        nPixelOffset = GDALGetDataTypeSizeBytes(eTypeIn);
 
     if( nLineOffsetIn == 0 )
-        nLineOffsetIn = nPixelOffsetIn * static_cast<size_t>(nBlockXSize);
-
-    nPixelOffset = nPixelOffsetIn;
-    nLineOffset = nLineOffsetIn;
-    bOwnData = bAssumeOwnership;
+        nLineOffset = nPixelOffset * static_cast<size_t>(nBlockXSize);
 
     if( pszPixelType && EQUAL(pszPixelType,"SIGNEDBYTE") )
         SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
@@ -133,7 +175,6 @@ MEMRasterBand::~MEMRasterBand()
         CPLDestroyXMLNode(psSavedHistograms);
 }
 
-
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
@@ -655,7 +696,8 @@ MEMRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
     if( psSavedHistograms != NULL )
     {
         for( CPLXMLNode *psXMLHist = psSavedHistograms->psChild;
-             psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
+             psXMLHist != NULL;
+             psXMLHist = psXMLHist->psNext )
         {
             if( psXMLHist->eType != CXT_Element
                 || !EQUAL(psXMLHist->pszValue,"HistItem") )
@@ -678,12 +720,79 @@ MEMRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
 }
 
 /************************************************************************/
+/*                          GetOverviewCount()                          */
+/************************************************************************/
+
+int MEMRasterBand::GetOverviewCount()
+{
+    MEMDataset* poMemDS = dynamic_cast<MEMDataset*>(poDS);
+    if( poMemDS == NULL )
+        return 0;
+    return poMemDS->m_nOverviewDSCount;
+}
+
+/************************************************************************/
+/*                            GetOverview()                             */
+/************************************************************************/
+
+GDALRasterBand * MEMRasterBand::GetOverview( int i )
+
+{
+    MEMDataset* poMemDS = dynamic_cast<MEMDataset*>(poDS);
+    if( poMemDS == NULL )
+        return NULL;
+    if( i < 0 || i >= poMemDS->m_nOverviewDSCount )
+        return NULL;
+    return poMemDS->m_papoOverviewDS[i]->GetRasterBand(nBand);
+}
+
+/************************************************************************/
+/*                         CreateMaskBand()                             */
+/************************************************************************/
+
+CPLErr MEMRasterBand::CreateMaskBand( int nFlagsIn )
+{
+    InvalidateMaskBand();
+
+    MEMDataset* poMemDS = dynamic_cast<MEMDataset*>(poDS);
+    if( (nFlagsIn & GMF_PER_DATASET) != 0 && nBand != 1 && poMemDS != NULL )
+    {
+        MEMRasterBand* poFirstBand =
+            reinterpret_cast<MEMRasterBand*>(poMemDS->GetRasterBand(1));
+        if( poFirstBand != NULL)
+            return poFirstBand->CreateMaskBand( nFlagsIn );
+    }
+
+    GByte* pabyMaskData = static_cast<GByte*>(VSI_CALLOC_VERBOSE(nRasterXSize,
+                                                                 nRasterYSize));
+    if( pabyMaskData == NULL )
+        return CE_Failure;
+
+    nMaskFlags = nFlagsIn;
+    bOwnMask = true;
+    poMask = new MEMRasterBand( pabyMaskData, GDT_Byte,
+                                nRasterXSize, nRasterYSize );
+    if( (nFlagsIn & GMF_PER_DATASET) != 0 && nBand == 1 && poMemDS != NULL )
+    {
+        for( int i = 2; i <= poMemDS->GetRasterCount(); ++i )
+        {
+            MEMRasterBand* poOtherBand =
+                reinterpret_cast<MEMRasterBand*>(poMemDS->GetRasterBand(i));
+            poOtherBand->InvalidateMaskBand();
+            poOtherBand->nMaskFlags = nFlagsIn;
+            poOtherBand->bOwnMask = false;
+            poOtherBand->poMask = poMask;
+        }
+    }
+    return CE_None;
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*      MEMDataset                                                     */
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            MEMDataset()                             */
 /************************************************************************/
@@ -693,7 +802,9 @@ MEMDataset::MEMDataset() :
     bGeoTransformSet(FALSE),
     pszProjection(NULL),
     nGCPCount(0),
-    pasGCPs(NULL)
+    pasGCPs(NULL),
+    m_nOverviewDSCount(0),
+    m_papoOverviewDS(NULL)
 {
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -701,6 +812,7 @@ MEMDataset::MEMDataset() :
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = -1.0;
+    DisableReadWriteMutex();
 }
 
 /************************************************************************/
@@ -715,6 +827,10 @@ MEMDataset::~MEMDataset()
 
     GDALDeinitGCPs( nGCPCount, pasGCPs );
     CPLFree( pasGCPs );
+
+    for(int i=0;i<m_nOverviewDSCount;++i)
+        delete m_papoOverviewDS[i];
+    CPLFree(m_papoOverviewDS);
 }
 
 #if 0
@@ -811,7 +927,7 @@ void *MEMDataset::GetInternalHandle( const char * pszRequest )
             if( RequestedRasterBand != NULL )
             {
                 // return the internal band data pointer
-                return(RequestedRasterBand->GetData());
+                return RequestedRasterBand->GetData();
             }
         }
     }
@@ -942,6 +1058,278 @@ CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions )
 }
 
 /************************************************************************/
+/*                          IBuildOverviews()                           */
+/************************************************************************/
+
+CPLErr MEMDataset::IBuildOverviews( const char *pszResampling,
+                                     int nOverviews, int *panOverviewList,
+                                     int nListBands, int *panBandList,
+                                     GDALProgressFunc pfnProgress,
+                                     void * pProgressData )
+{
+    if( nBands == 0 )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Dataset has zero bands." );
+        return CE_Failure;
+    }
+
+    if( nListBands != nBands )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Generation of overviews in MEM only"
+                  "supported when operating on all bands." );
+        return CE_Failure;
+    }
+
+    if( nOverviews == 0 )
+    {
+        // Cleanup existing overviews
+        for(int i=0;i<m_nOverviewDSCount;++i)
+            delete m_papoOverviewDS[i];
+        CPLFree(m_papoOverviewDS);
+        m_nOverviewDSCount = 0;
+        m_papoOverviewDS = NULL;
+        return CE_None;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Force cascading. Help to get accurate results when masks are    */
+/*      involved.                                                       */
+/* -------------------------------------------------------------------- */
+    if( nOverviews > 1 &&
+        (STARTS_WITH_CI(pszResampling, "AVER") |
+         STARTS_WITH_CI(pszResampling, "GAUSS") ||
+         EQUAL(pszResampling, "CUBIC") ||
+         EQUAL(pszResampling, "CUBICSPLINE") ||
+         EQUAL(pszResampling, "LANCZOS") ||
+         EQUAL(pszResampling, "BILINEAR")) )
+    {
+        double dfTotalPixels = 0;
+        for( int i = 0; i < nOverviews; i++ )
+        {
+            dfTotalPixels +=
+                static_cast<double>(nRasterXSize) * nRasterYSize /
+                    (panOverviewList[i] * panOverviewList[i]);
+        }
+
+        double dfAccPixels = 0;
+        for( int i = 0; i < nOverviews; i++ )
+        {
+            double dfPixels =
+                static_cast<double>(nRasterXSize) * nRasterYSize /
+                    (panOverviewList[i] * panOverviewList[i]);
+            void* pScaledProgress = GDALCreateScaledProgress(
+                    dfAccPixels / dfTotalPixels,
+                    (dfAccPixels + dfPixels) / dfTotalPixels,
+                    pfnProgress, pProgressData );
+            CPLErr eErr = IBuildOverviews(
+                                    pszResampling,
+                                    1, &panOverviewList[i],
+                                    nListBands, panBandList,
+                                    GDALScaledProgress,
+                                    pScaledProgress );
+            GDALDestroyScaledProgress( pScaledProgress );
+            dfAccPixels += dfPixels;
+            if( eErr == CE_Failure )
+                return eErr;
+        }
+        return CE_None;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Establish which of the overview levels we already have, and     */
+/*      which are new.                                                  */
+/* -------------------------------------------------------------------- */
+    GDALRasterBand *poBand = GetRasterBand( 1 );
+
+    for( int i = 0; i < nOverviews; i++ )
+    {
+        bool bExisting = false;
+        for( int j = 0; j < poBand->GetOverviewCount(); j++ )
+        {
+            GDALRasterBand * poOverview = poBand->GetOverview( j );
+            if( poOverview == NULL )
+                continue;
+
+            int nOvFactor =
+                GDALComputeOvFactor(poOverview->GetXSize(),
+                                    poBand->GetXSize(),
+                                    poOverview->GetYSize(),
+                                    poBand->GetYSize());
+
+            if( nOvFactor == panOverviewList[i]
+                || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
+                                                   poBand->GetXSize(),
+                                                   poBand->GetYSize() ) )
+            {
+                bExisting = true;
+                break;
+            }
+        }
+
+        // Create new overview dataset if needed.
+        if( !bExisting )
+        {
+            MEMDataset* poOvrDS = new MEMDataset();
+            poOvrDS->eAccess = GA_Update;
+            poOvrDS->nRasterXSize = (nRasterXSize + panOverviewList[i] - 1)
+                                            / panOverviewList[i];
+            poOvrDS->nRasterYSize = (nRasterYSize + panOverviewList[i] - 1)
+                                            / panOverviewList[i];
+            for( int iBand = 0; iBand < nBands; iBand ++ )
+            {
+                const GDALDataType eDT =
+                            GetRasterBand(iBand+1)->GetRasterDataType();
+                if( poOvrDS->AddBand( eDT, NULL ) != CE_None )
+                {
+                    delete poOvrDS;
+                    return CE_Failure;
+                }
+            }
+            m_nOverviewDSCount ++;
+            m_papoOverviewDS = (GDALDataset**) CPLRealloc(m_papoOverviewDS,
+                                    sizeof(GDALDataset*) * m_nOverviewDSCount );
+            m_papoOverviewDS[m_nOverviewDSCount-1] = poOvrDS;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Build band list.                                                */
+/* -------------------------------------------------------------------- */
+    GDALRasterBand **pahBands = static_cast<GDALRasterBand **>(
+        CPLCalloc(sizeof(GDALRasterBand *), nBands) );
+    for( int i = 0; i < nBands; i++ )
+        pahBands[i] = GetRasterBand( panBandList[i] );
+
+/* -------------------------------------------------------------------- */
+/*      Refresh overviews that were listed.                             */
+/* -------------------------------------------------------------------- */
+    GDALRasterBand **papoOverviewBands = static_cast<GDALRasterBand **>(
+        CPLCalloc(sizeof(void*), nOverviews) );
+    GDALRasterBand **papoMaskOverviewBands = static_cast<GDALRasterBand **>(
+        CPLCalloc(sizeof(void*), nOverviews) );
+
+    CPLErr eErr = CE_None;
+    for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
+    {
+        poBand = GetRasterBand( panBandList[iBand] );
+
+        int nNewOverviews = 0;
+        for( int i = 0; i < nOverviews; i++ )
+        {
+            for( int j = 0; j < poBand->GetOverviewCount(); j++ )
+            {
+                GDALRasterBand * poOverview = poBand->GetOverview( j );
+
+                int bHasNoData = FALSE;
+                double noDataValue = poBand->GetNoDataValue(&bHasNoData);
+
+                if( bHasNoData )
+                  poOverview->SetNoDataValue(noDataValue);
+
+                const int nOvFactor =
+                    GDALComputeOvFactor(poOverview->GetXSize(),
+                                        poBand->GetXSize(),
+                                        poOverview->GetYSize(),
+                                        poBand->GetYSize());
+
+                if( nOvFactor == panOverviewList[i]
+                    || nOvFactor == GDALOvLevelAdjust2(panOverviewList[i],
+                                                       poBand->GetXSize(),
+                                                       poBand->GetYSize() ) )
+                {
+                    papoOverviewBands[nNewOverviews++] = poOverview;
+                    break;
+                }
+            }
+        }
+
+        // If the band has an explicit mask, we need to create overviews
+        // for it
+        MEMRasterBand* poMEMBand = reinterpret_cast<MEMRasterBand*>(poBand);
+        const bool bMustGenerateMaskOvr =
+                ( (poMEMBand->bOwnMask && poMEMBand->poMask != NULL) ||
+        // Or if it is a per-dataset mask, in which case just do it for the
+        // first band
+                  ((poMEMBand->nMaskFlags & GMF_PER_DATASET) != 0 && iBand == 0) );
+
+        if( nNewOverviews > 0 && bMustGenerateMaskOvr )
+        {
+            for( int i = 0; i < nNewOverviews; i++ )
+            {
+                MEMRasterBand* poMEMOvrBand =
+                    reinterpret_cast<MEMRasterBand*>(papoOverviewBands[i]);
+                if( !(poMEMOvrBand->bOwnMask && poMEMOvrBand->poMask != NULL) &&
+                    (poMEMOvrBand->nMaskFlags & GMF_PER_DATASET) == 0 )
+                {
+                    poMEMOvrBand->CreateMaskBand( poMEMBand->nMaskFlags );
+                }
+                papoMaskOverviewBands[i] = poMEMOvrBand->GetMaskBand();
+            }
+
+            void* pScaledProgress = GDALCreateScaledProgress(
+                    1.0 * iBand / nBands,
+                    1.0 * (iBand+0.5) / nBands,
+                    pfnProgress, pProgressData );
+
+            MEMRasterBand* poMaskBand = reinterpret_cast<MEMRasterBand*>(
+                                                        poBand->GetMaskBand());
+            // Make the mask band to be its own mask, similarly to what is
+            // done for alpha bands in GDALRegenerateOverviews() (#5640)
+            poMaskBand->InvalidateMaskBand();
+            poMaskBand->bOwnMask = false;
+            poMaskBand->poMask = poMaskBand;
+            poMaskBand->nMaskFlags = 0;
+            eErr = GDALRegenerateOverviews(
+                                        (GDALRasterBandH) poMaskBand,
+                                        nNewOverviews,
+                                        (GDALRasterBandH*)papoMaskOverviewBands,
+                                        pszResampling,
+                                        GDALScaledProgress, pScaledProgress );
+            poMaskBand->InvalidateMaskBand();
+            GDALDestroyScaledProgress( pScaledProgress );
+        }
+
+        // Generate overview of bands *AFTER* mask overviews
+        if( nNewOverviews > 0 && eErr == CE_None  )
+        {
+            void* pScaledProgress = GDALCreateScaledProgress(
+                    1.0 * (iBand+(bMustGenerateMaskOvr ? 0.5 : 1)) / nBands,
+                    1.0 * (iBand+1)/ nBands,
+                    pfnProgress, pProgressData );
+            eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
+                                            nNewOverviews,
+                                            (GDALRasterBandH*)papoOverviewBands,
+                                            pszResampling,
+                                            GDALScaledProgress, pScaledProgress );
+            GDALDestroyScaledProgress( pScaledProgress );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    CPLFree( papoOverviewBands );
+    CPLFree( papoMaskOverviewBands );
+    CPLFree( pahBands );
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                         CreateMaskBand()                             */
+/************************************************************************/
+
+CPLErr MEMDataset::CreateMaskBand( int nFlagsIn )
+{
+    GDALRasterBand* poFirstBand = GetRasterBand(1);
+    if( poFirstBand == NULL )
+        return CE_Failure;
+    return poFirstBand->CreateMaskBand( nFlagsIn | GMF_PER_DATASET );
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
diff --git a/frmts/mem/memdataset.h b/frmts/mem/memdataset.h
index d11e7a7..b93f5f8 100644
--- a/frmts/mem/memdataset.h
+++ b/frmts/mem/memdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: memdataset.h 33838 2016-03-31 20:42:32Z goatbar $
+ * $Id: memdataset.h 37006 2016-12-23 16:31:02Z rouault $
  *
  * Project:  Memory Array Translator
  * Purpose:  Declaration of MEMDataset, and MEMRasterBand.
@@ -34,7 +34,6 @@
 #include "gdal_priv.h"
 
 CPL_C_START
-void GDALRegister_MEM();
 /* Caution: if changing this prototype, also change in swig/include/gdal_python.i
    where it is redefined */
 GDALRasterBandH CPL_DLL MEMCreateRasterBand( GDALDataset *, int, GByte *,
@@ -52,6 +51,8 @@ class MEMRasterBand;
 
 class CPL_DLL MEMDataset : public GDALDataset
 {
+    friend class MEMRasterBand;
+
     int         bGeoTransformSet;
     double      adfGeoTransform[6];
 
@@ -61,6 +62,9 @@ class CPL_DLL MEMDataset : public GDALDataset
     GDAL_GCP    *pasGCPs;
     CPLString    osGCPProjection;
 
+    int          m_nOverviewDSCount;
+    GDALDataset  **m_papoOverviewDS;
+
 #if 0
   protected:
     virtual int                 EnterReadWrite(GDALRWFlag eRWFlag);
@@ -71,22 +75,22 @@ class CPL_DLL MEMDataset : public GDALDataset
                  MEMDataset();
     virtual      ~MEMDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
+    virtual const char *GetProjectionRef() CPL_OVERRIDE;
+    virtual CPLErr SetProjection( const char * ) CPL_OVERRIDE;
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * ) CPL_OVERRIDE;
+    virtual CPLErr SetGeoTransform( double * ) CPL_OVERRIDE;
 
-    virtual void *GetInternalHandle( const char * );
+    virtual void *GetInternalHandle( const char * ) CPL_OVERRIDE;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() CPL_OVERRIDE;
+    virtual const char *GetGCPProjection() CPL_OVERRIDE;
+    virtual const GDAL_GCP *GetGCPs() CPL_OVERRIDE;
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) CPL_OVERRIDE;
 
     virtual CPLErr        AddBand( GDALDataType eType,
-                                   char **papszOptions=NULL );
+                                   char **papszOptions=NULL ) CPL_OVERRIDE;
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
@@ -95,7 +99,14 @@ class CPL_DLL MEMDataset : public GDALDataset
                                GSpacing nPixelSpaceBuf,
                                GSpacing nLineSpaceBuf,
                                GSpacing nBandSpaceBuf,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg) CPL_OVERRIDE;
+    virtual CPLErr  IBuildOverviews( const char *pszResampling,
+                                     int nOverviews, int *panOverviewList,
+                                     int nListBands, int *panBandList,
+                                     GDALProgressFunc pfnProgress,
+                                     void * pProgressData ) CPL_OVERRIDE;
+
+    virtual CPLErr          CreateMaskBand( int nFlagsIn ) CPL_OVERRIDE;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
@@ -109,6 +120,10 @@ class CPL_DLL MEMDataset : public GDALDataset
 
 class CPL_DLL MEMRasterBand : public GDALPamRasterBand
 {
+  private:
+                MEMRasterBand( GByte *pabyDataIn, GDALDataType eTypeIn,
+                               int nXSizeIn, int nYSizeIn );
+
   protected:
     friend      class MEMDataset;
 
@@ -139,46 +154,51 @@ class CPL_DLL MEMRasterBand : public GDALPamRasterBand
                                   const char * pszPixelType = NULL );
     virtual        ~MEMRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
+    virtual CPLErr IWriteBlock( int, int, void * ) CPL_OVERRIDE;
     virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                                   int nXOff, int nYOff, int nXSize, int nYSize,
                                   void * pData, int nBufXSize, int nBufYSize,
                                   GDALDataType eBufType,
                                   GSpacing nPixelSpaceBuf,
                                   GSpacing nLineSpaceBuf,
-                                  GDALRasterIOExtraArg* psExtraArg );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr SetNoDataValue( double );
-    virtual CPLErr DeleteNoDataValue();
+                                  GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    virtual CPLErr SetNoDataValue( double ) CPL_OVERRIDE;
+    virtual CPLErr DeleteNoDataValue() CPL_OVERRIDE;
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual CPLErr SetColorTable( GDALColorTable * );
+    virtual GDALColorInterp GetColorInterpretation() CPL_OVERRIDE;
+    virtual GDALColorTable *GetColorTable() CPL_OVERRIDE;
+    virtual CPLErr SetColorTable( GDALColorTable * ) CPL_OVERRIDE;
 
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) CPL_OVERRIDE;
 
-    virtual const char *GetUnitType();
-    CPLErr SetUnitType( const char * );
+    virtual const char *GetUnitType() CPL_OVERRIDE;
+    CPLErr SetUnitType( const char * ) CPL_OVERRIDE;
 
-    virtual char **GetCategoryNames();
-    virtual CPLErr SetCategoryNames( char ** );
+    virtual char **GetCategoryNames() CPL_OVERRIDE;
+    virtual CPLErr SetCategoryNames( char ** ) CPL_OVERRIDE;
 
-    virtual double GetOffset( int *pbSuccess = NULL );
-    CPLErr SetOffset( double );
-    virtual double GetScale( int *pbSuccess = NULL );
-    CPLErr SetScale( double );
+    virtual double GetOffset( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    CPLErr SetOffset( double ) CPL_OVERRIDE;
+    virtual double GetScale( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    CPLErr SetScale( double ) CPL_OVERRIDE;
 
     virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
-                                        int nBuckets, GUIntBig *panHistogram );
+                                        int nBuckets, GUIntBig *panHistogram ) CPL_OVERRIDE;
     virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                         int *pnBuckets,
                                         GUIntBig ** ppanHistogram,
                                         int bForce,
-                                        GDALProgressFunc, void *pProgressData);
+                                        GDALProgressFunc, void *pProgressData) CPL_OVERRIDE;
+
+    virtual int GetOverviewCount() CPL_OVERRIDE;
+    virtual GDALRasterBand *GetOverview(int) CPL_OVERRIDE;
+
+    virtual CPLErr          CreateMaskBand( int nFlagsIn ) CPL_OVERRIDE;
 
     // Allow access to MEM driver's private internal memory buffer.
-    GByte *GetData(void) const { return(pabyData); }
+    GByte *GetData() const { return(pabyData); }
 };
 
 #endif /* ndef MEMDATASET_H_INCLUDED */
diff --git a/frmts/mrf/GNUmakefile b/frmts/mrf/GNUmakefile
index 618e853..d4e1714 100644
--- a/frmts/mrf/GNUmakefile
+++ b/frmts/mrf/GNUmakefile
@@ -1,9 +1,9 @@
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
-# 
+#
 # http://www.apache.org/licenses/LICENSE-2.0
-# 
+#
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -27,15 +27,15 @@ FILES	:= $(FILES) JPEG12_band
 XTRA_OPT := $(XTRA_OPT) -DJPEG12_SUPPORTED
 endif
 
-ifeq ($(JPEG_SETTING),internal) 
+ifeq ($(JPEG_SETTING),internal)
 XTRA_OPT        :=      $(XTRA_OPT) -I../jpeg/libjpeg
 endif
 
-ifeq ($(PNG_SETTING),internal) 
+ifeq ($(PNG_SETTING),internal)
 XTRA_OPT        :=      $(XTRA_OPT) -I../png/libpng -DINTERNAL_PNG
 endif
 
-ifeq ($(LIBZ_SETTING),internal) 
+ifeq ($(LIBZ_SETTING),internal)
 XTRA_OPT        :=      $(XTRA_OPT) -I../zlib
 endif
 
diff --git a/frmts/mrf/JPEG_band.cpp b/frmts/mrf/JPEG_band.cpp
index 6b2c9ab..cfd3ae4 100644
--- a/frmts/mrf/JPEG_band.cpp
+++ b/frmts/mrf/JPEG_band.cpp
@@ -4,18 +4,18 @@
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-*   2. Redistributions in binary form must reproduce the above copyright notice, 
+*   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL), 
-*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to 
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
 *      endorse or promote products derived from this software without specific prior written permission.
 *
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
-* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
-* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
-* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Copyright 2014-2015 Esri
@@ -33,10 +33,7 @@
 * limitations under the License.
 */
 
-
-
 /*
- * $Id$
  * JPEG band
  * JPEG page compression and decompression functions, gets compiled twice
  * once directly and once through inclusion from JPEG12_band.cpp
@@ -51,6 +48,8 @@ CPL_C_START
 #include <jpeglib.h>
 CPL_C_END
 
+CPL_CVSID("$Id: JPEG_band.cpp 35897 2016-10-24 11:54:24Z goatbar $");
+
 NAMESPACE_MRF_START
 
 typedef struct MRFJPEGErrorStruct
@@ -92,14 +91,13 @@ static void errorExit(j_common_ptr cinfo)
     longjmp(psErrorStruct->setjmpBuffer, 1);
 }
 
-
 /**
-*\Brief Do nothing stub function for JPEG library, called
+*\brief Do nothing stub function for JPEG library, called
 */
 static void stub_source_dec(j_decompress_ptr /*cinfo*/) {}
 
 /**
-*\Brief: This function is supposed to do refilling of the input buffer,
+*\brief: This function is supposed to do refilling of the input buffer,
 * but as we provided everything at the beginning, if it is called, then
 * we have an error.
 */
@@ -112,7 +110,7 @@ static boolean fill_input_buffer_dec(j_decompress_ptr cinfo)
 }
 
 /**
-*\Brief: Do nothing stub function for JPEG library, not called
+*\brief: Do nothing stub function for JPEG library, not called
 */
 static void skip_input_data_dec(j_decompress_ptr /*cinfo*/, long /*l*/) {};
 
@@ -126,7 +124,7 @@ static boolean empty_output_buffer(j_compress_ptr /*cinfo*/) {
 }
 
 /*
-*\Brief Compress a JPEG page in memory
+*\brief Compress a JPEG page in memory
 *
 * It handles byte or 12 bit data, grayscale, RGB, CMYK, multispectral
 *
@@ -227,18 +225,17 @@ CPLErr JPEG_Codec::CompressJPEG(buf_mgr &dst, buf_mgr &src)
     return CE_None;
 }
 
-
 /**
 *\brief In memory decompression of JPEG file
 *
-* @param data pointer to output buffer 
+* @param data pointer to output buffer
 * @param png pointer to PNG in memory
 * @param sz if non-zero, test that uncompressed data fits in the buffer.
 */
 #if defined(JPEG12_ON)
 CPLErr JPEG_Codec::DecompressJPEG12(buf_mgr &dst, buf_mgr &isrc)
 #else
-CPLErr JPEG_Codec::DecompressJPEG(buf_mgr &dst, buf_mgr &isrc) 
+CPLErr JPEG_Codec::DecompressJPEG(buf_mgr &dst, buf_mgr &isrc)
 #endif
 
 {
@@ -259,7 +256,8 @@ CPLErr JPEG_Codec::DecompressJPEG(buf_mgr &dst, buf_mgr &isrc)
 
     src.next_input_byte = (JOCTET *)isrc.buffer;
     src.bytes_in_buffer = isrc.size;
-    src.term_source = src.init_source = stub_source_dec;
+    src.term_source = stub_source_dec;
+    src.init_source = stub_source_dec;
     src.skip_input_data = skip_input_data_dec;
     src.fill_input_buffer = fill_input_buffer_dec;
     src.resync_to_restart = jpeg_resync_to_restart;
@@ -282,7 +280,7 @@ CPLErr JPEG_Codec::DecompressJPEG(buf_mgr &dst, buf_mgr &isrc)
     // Gray and RGB for example
     // This also means that a RGB MRF can be read as grayscale and vice versa
     // If libJPEG can't convert it will throw an error
-    // 
+    //
     if (nbands == 3 && cinfo.num_components != nbands)
         cinfo.out_color_space = JCS_RGB;
     if (nbands == 1 && cinfo.num_components != nbands)
@@ -339,23 +337,29 @@ CPLErr JPEG_Band::Compress(buf_mgr &dst, buf_mgr &src)
 }
 
 // PHOTOMETRIC == MULTISPECTRAL turns off YCbCr conversion and downsampling
-JPEG_Band::JPEG_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level) :
-GDALMRFRasterBand(pDS, image, b, int(level)), codec(image)
+JPEG_Band::JPEG_Band( GDALMRFDataset *pDS, const ILImage &image,
+                      int b, int level ) :
+    GDALMRFRasterBand(pDS, image, b, int(level)),
+    codec(image)
 {
-    int nbands = image.pagesize.c;
+    const int nbands = image.pagesize.c;
     // Check behavior on signed 16bit.  Does the libjpeg sign extend?
 #if defined(LIBJPEG_12_H)
-    if (GDT_Byte != image.dt && GDT_UInt16 != image.dt) {
+    if (GDT_Byte != image.dt && GDT_UInt16 != image.dt)
 #else
-    if (GDT_Byte != image.dt) {
+    if (GDT_Byte != image.dt)
 #endif
-        CPLError(CE_Failure, CPLE_NotSupported, "Data type not supported by MRF JPEG");
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Data type not supported by MRF JPEG");
         return;
     }
 
-    if (nbands == 3) { // Only the 3 band JPEG has storage flavors
+    if( nbands == 3 )
+    { // Only the 3 band JPEG has storage flavors
         CPLString const &pm = pDS->GetPhotometricInterpretation();
-        if (pm == "RGB" || pm == "MULTISPECTRAL") { // Explicit RGB or MS
+        if (pm == "RGB" || pm == "MULTISPECTRAL")
+        { // Explicit RGB or MS
             codec.rgb = TRUE;
             codec.sameres = TRUE;
         }
@@ -363,7 +367,7 @@ GDALMRFRasterBand(pDS, image, b, int(level)), codec(image)
             codec.sameres = TRUE;
     }
 
-    if (GDT_Byte == image.dt)
+    if( GDT_Byte == image.dt )
         codec.optimize = GetOptlist().FetchBoolean("OPTIMIZE", FALSE) != FALSE;
     else
         codec.optimize = true; // Required for 12bit
diff --git a/frmts/mrf/JPNG_band.cpp b/frmts/mrf/JPNG_band.cpp
index faac8e8..851d5d3 100644
--- a/frmts/mrf/JPNG_band.cpp
+++ b/frmts/mrf/JPNG_band.cpp
@@ -21,6 +21,8 @@
 #include "marfa.h"
 #include <cassert>
 
+CPL_CVSID("$Id: JPNG_band.cpp 36455 2016-11-22 23:11:35Z rouault $");
+
 CPL_C_START
 #include <jpeglib.h>
 
@@ -34,13 +36,13 @@ CPL_C_END
 NAMESPACE_MRF_START
 
 // Test that all alpha values are equal to N
-template<int N> bool AllAlpha(const buf_mgr &src, const ILImage &img) {
+template<int N> static bool AllAlpha(const buf_mgr &src, const ILImage &img) {
     int stride = img.pagesize.c;
     char *s = src.buffer + img.pagesize.c - 1;
     char *stop = src.buffer + img.pageSizeBytes;
     while (s < stop && N == static_cast<unsigned char>(*s))
         s += stride;
-    return (s >= stop);
+    return s >= stop;
 }
 
 // Fully opaque
@@ -139,10 +141,9 @@ CPLErr JPNG_Band::Decompress(buf_mgr &dst, buf_mgr &src)
 CPLErr JPNG_Band::Compress(buf_mgr &dst, buf_mgr &src)
 {
     ILImage image(img);
-    CPLErr retval = CE_None;
 
     buf_mgr temp = { NULL, static_cast<size_t>(img.pageSizeBytes) };
-    retval = initBuffer(temp);
+    CPLErr retval = initBuffer(temp);
     if (retval != CE_None)
         return retval;
 
@@ -170,7 +171,7 @@ CPLErr JPNG_Band::Compress(buf_mgr &dst, buf_mgr &src)
             retval = codec.CompressPNG(dst, src);
         }
     }
-    catch (CPLErr err) {
+    catch (const CPLErr& err) {
         retval = err;
     }
 
@@ -179,27 +180,36 @@ CPLErr JPNG_Band::Compress(buf_mgr &dst, buf_mgr &src)
 }
 
 /**
-* \Brief For PPNG, builds the data structures needed to write the palette
+* \brief For PPNG, builds the data structures needed to write the palette
 * The presence of the PNGColors and PNGAlpha is used as a flag for PPNG only
 */
 
-JPNG_Band::JPNG_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level) :
-GDALMRFRasterBand(pDS, image, b, level), 
-rgb(FALSE), sameres(FALSE), optimize(false)
-
+JPNG_Band::JPNG_Band( GDALMRFDataset *pDS, const ILImage &image,
+                      int b, int level ) :
+    GDALMRFRasterBand(pDS, image, b, level),
+    rgb(FALSE),
+    sameres(FALSE),
+    optimize(false)
 {   // Check error conditions
-    if (image.dt != GDT_Byte) {
-	CPLError(CE_Failure, CPLE_NotSupported, "Data type not supported by MRF JPNG");
-	return;
+    if( image.dt != GDT_Byte )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Data type not supported by MRF JPNG");
+        return;
     }
-    if (image.order != IL_Interleaved || (image.pagesize.c != 4 && image.pagesize.c != 2)) {
-	CPLError(CE_Failure, CPLE_NotSupported, "MRF JPNG can only handle 2 or 4 interleaved bands");
-	return;
+    if( image.order != IL_Interleaved ||
+        (image.pagesize.c != 4 && image.pagesize.c != 2) )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "MRF JPNG can only handle 2 or 4 interleaved bands");
+        return;
     }
 
-    if (img.pagesize.c == 4) { // RGBA can have storage flavors
+    if( img.pagesize.c == 4 )
+    { // RGBA can have storage flavors
         CPLString const &pm = pDS->GetPhotometricInterpretation();
-        if (pm == "RGB" || pm == "MULTISPECTRAL") { // Explicit RGB or MS
+        if (pm == "RGB" || pm == "MULTISPECTRAL")
+        { // Explicit RGB or MS
             rgb = TRUE;
             sameres = TRUE;
         }
@@ -209,11 +219,11 @@ rgb(FALSE), sameres(FALSE), optimize(false)
 
     optimize = GetOptlist().FetchBoolean("OPTIMIZE", FALSE) != FALSE;
 
-    // PNGs and JPGs can be larger than the source, especially for small page size
+    // PNGs and JPGs can be larger than the source, especially for
+    // small page size.
     poDS->SetPBufferSize(image.pageSizeBytes + 100);
 }
 
-JPNG_Band::~JPNG_Band() {
-}
+JPNG_Band::~JPNG_Band() {}
 
 NAMESPACE_MRF_END
diff --git a/frmts/mrf/LERC_band.cpp b/frmts/mrf/LERC_band.cpp
index b886187..e88cb1c 100644
--- a/frmts/mrf/LERC_band.cpp
+++ b/frmts/mrf/LERC_band.cpp
@@ -24,12 +24,122 @@ Contributors:  Lucian Plesea
 #include <CntZImage.h>
 #include <Lerc2.h>
 
+CPL_CVSID("$Id: LERC_band.cpp 37475 2017-02-26 02:50:00Z goatbar $");
+
 USING_NAMESPACE_LERC
 
 NAMESPACE_MRF_START
 
+//
+// Check that a buffer contains a supported Lerc1 blob, the type supported by MRF
+// Can't really check everything without decoding, this just checks the main structure
+// returns actual size if it is Lerc1 with size < sz
+// returns 0 if format doesn't match
+// returns -1 if Lerc1 but size can't be determined
+//
+// returns -<actual size> if actual size > sz
+
+static int checkV1(const char *s, size_t sz)
+{
+    GInt32 nBytesMask, nBytesData;
+
+// Read an unaligned 4 byte little endian int from location p, advances pointer
+#define READ_GINT32(X, p) \
+            memcpy(&X, p, sizeof(GInt32));\
+            SWAP_4(X); \
+            p+= sizeof(GInt32)
+
+    // Header is 34 bytes
+    // band header is 16, first mask band then data band
+    if (sz < 66)
+        return 0;
+    // First ten bytes are ASCII signature
+    if (!STARTS_WITH(s, "CntZImage "))
+        return 0;
+    s += 10;
+
+    // A place to read an int or a float
+    union {
+        GInt32 i;
+        float val;
+    };
+
+    // Version
+    READ_GINT32(i, s);
+    if (i != 11) return 0;
+
+    // Type
+    READ_GINT32(i, s);
+    if (i != Image::CNT_Z) return 0;
+
+    // Height
+    READ_GINT32(i, s); // Arbitrary number in CntZImage::read()
+    if (i > 20000 || i <= 0) return 0;
+
+    // Width
+    READ_GINT32(i, s);
+    if (i > 20000 || i <= 0) return 0;
+
+    // Skip the max val stored as double
+    s += sizeof(double);
+
+    // First header should be the mask, which mean 0 blocks
+    // Height
+    READ_GINT32(i, s);
+    if (i != 0) return 0;
+
+    // WIDTH
+    READ_GINT32(i, s);
+    if (i != 0) return 0;
+
+    READ_GINT32(nBytesMask, s);
+    if (nBytesMask < 0) return 0;
+
+    // mask max value, 0 or 1 as float
+    READ_GINT32(i, s);
+    if (val != 0.0 && val != 1.0) return 0;
+
+    // If data header can't be read the actual size is unknown
+    if (static_cast<size_t>(66 + nBytesMask) >= sz) return -1;
+
+    s += nBytesMask;
+
+    // Data Band header
+    READ_GINT32(i, s); // number of full height blocks, never single pixel blocks
+    if (i <= 0 || i > 10000)
+        return 0;
+
+    READ_GINT32(i, s); // number of full width blocks, never single pixel blocks
+    if (i <= 0 || i > 10000)
+        return 0;
+
+    READ_GINT32(nBytesData, s);
+    if (nBytesData < 0) return 0;
+
+#undef READ_GINT32
+
+    // Actual LERC blob size
+    int size = static_cast<int>(66 + nBytesMask + nBytesData);
+    return (static_cast<size_t>(size) > sz) ? -size : size;
+}
+
+static GDALDataType GetL2DataType(Lerc2::DataType L2type) {
+    GDALDataType dt;
+    switch (L2type) {
+    case Lerc2::DT_Byte:  dt = GDT_Byte; break;
+    case Lerc2::DT_Short: dt = GDT_Int16; break;
+    case Lerc2::DT_UShort: dt = GDT_UInt16; break;
+    case Lerc2::DT_Int: dt = GDT_Int32; break;
+    case Lerc2::DT_UInt: dt = GDT_UInt32; break;
+    case Lerc2::DT_Float: dt = GDT_Float32; break;
+    case Lerc2::DT_Double: dt = GDT_Float64; break;
+    default: dt = GDT_Unknown;
+    }
+    return dt;
+}
+
 // Load a buffer into a zImg
-template <typename T> void CntZImgFill(CntZImage &zImg, T *src, const ILImage &img)
+template <typename T> static void CntZImgFill(CntZImage &zImg, T *src, const ILImage &img)
 {
     int w = img.pagesize.x;
     int h = img.pagesize.y;
@@ -42,25 +152,25 @@ template <typename T> void CntZImgFill(CntZImage &zImg, T *src, const ILImage &i
     if (!img.hasNoData) ndv = 0;
 
     for (int i = 0; i < h; i++)
-	for (int j = 0; j < w; j++) {
-	    zImg(i, j).z = float(*ptr++);
-	    zImg(i, j).cnt = !CPLIsEqual(zImg(i, j).z, ndv);
-	}
+        for (int j = 0; j < w; j++) {
+            zImg(i, j).z = float(*ptr++);
+            zImg(i, j).cnt = !CPLIsEqual(zImg(i, j).z, ndv);
+        }
     return;
 }
 
 // Unload a zImg into a buffer
-template <typename T> void CntZImgUFill(CntZImage &zImg, T *dst, const ILImage &img)
+template <typename T> static void CntZImgUFill(CntZImage &zImg, T *dst, const ILImage &img)
 {
     int h = static_cast<int>(zImg.getHeight());
     int w = static_cast<int>(zImg.getWidth());
     T *ptr = dst;
-    T ndv = (T)(img.NoDataValue);
+    T ndv = static_cast<T>(img.NoDataValue);
     // Use 0 if nodata is not defined
     if (!img.hasNoData) ndv = 0;
     for (int i = 0; i < h; i++)
-	for (int j = 0; j < w; j++)
-	    *ptr++ = (zImg(i, j).cnt == 0) ? ndv : (T)(zImg(i, j).z);
+        for (int j = 0; j < w; j++)
+            *ptr++ = (zImg(i, j).cnt == 0) ? ndv : static_cast<T>(zImg(i, j).z);
 }
 
 //  LERC 1 compression
@@ -68,15 +178,15 @@ static CPLErr CompressLERC(buf_mgr &dst, buf_mgr &src, const ILImage &img, doubl
 {
     CntZImage zImg;
     // Fill data into zImg
-#define FILL(T) CntZImgFill(zImg, (T *)(src.buffer), img)
+#define FILL(T) CntZImgFill(zImg, reinterpret_cast<T *>(src.buffer), img)
     switch (img.dt) {
-    case GDT_Byte:	FILL(GByte);	break;
-    case GDT_UInt16:	FILL(GUInt16);	break;
-    case GDT_Int16:	FILL(GInt16);	break;
-    case GDT_Int32:	FILL(GInt32);	break;
-    case GDT_UInt32:	FILL(GUInt32);	break;
-    case GDT_Float32:	FILL(float);	break;
-    case GDT_Float64:	FILL(double);	break;
+    case GDT_Byte:      FILL(GByte);    break;
+    case GDT_UInt16:    FILL(GUInt16);  break;
+    case GDT_Int16:     FILL(GInt16);   break;
+    case GDT_Int32:     FILL(GInt32);   break;
+    case GDT_UInt32:    FILL(GUInt32);  break;
+    case GDT_Float32:   FILL(float);    break;
+    case GDT_Float64:   FILL(double);   break;
     default: break;
     }
 #undef FILL
@@ -85,8 +195,8 @@ static CPLErr CompressLERC(buf_mgr &dst, buf_mgr &src, const ILImage &img, doubl
 
     // if it can't compress in output buffer it will crash
     if (!zImg.write(&ptr, precision)) {
-	CPLError(CE_Failure,CPLE_AppDefined,"MRF: Error during LERC compression");
-	return CE_Failure;
+        CPLError(CE_Failure,CPLE_AppDefined,"MRF: Error during LERC compression");
+        return CE_Failure;
     }
 
     // write changes the value of the pointer, we can find the size by testing how far it moved
@@ -99,22 +209,34 @@ static CPLErr DecompressLERC(buf_mgr &dst, buf_mgr &src, const ILImage &img)
 {
     CntZImage zImg;
     Byte *ptr = (Byte *)src.buffer;
+
+    // Check that input passes snicker test
+    int actual = checkV1(src.buffer, src.size);
+    if (actual == 0) {
+        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Not a supported LERC format");
+        return CE_Failure;
+    }
+    if (actual < 0) { // Negative return means buffer is too short
+            CPLError(CE_Failure, CPLE_AppDefined, "MRF: Lerc object too large");
+            return CE_Failure;
+    }
+
     if (!zImg.read(&ptr, 1e12))
     {
-	CPLError(CE_Failure,CPLE_AppDefined,"MRF: Error during LERC decompression");
-	return CE_Failure;
+        CPLError(CE_Failure,CPLE_AppDefined,"MRF: Error during LERC decompression");
+        return CE_Failure;
     }
 
 // Unpack from zImg to dst buffer, calling the right type
-#define UFILL(T) CntZImgUFill(zImg, (T *)(dst.buffer), img)
+#define UFILL(T) CntZImgUFill(zImg, reinterpret_cast<T *>(dst.buffer), img)
     switch (img.dt) {
-    case GDT_Byte:	UFILL(GByte);	break;
-    case GDT_UInt16:	UFILL(GUInt16); break;
-    case GDT_Int16:	UFILL(GInt16);	break;
-    case GDT_Int32:	UFILL(GInt32);	break;
-    case GDT_UInt32:	UFILL(GUInt32); break;
-    case GDT_Float32:	UFILL(float);	break;
-    case GDT_Float64:	UFILL(double);	break;
+    case GDT_Byte:      UFILL(GByte);   break;
+    case GDT_UInt16:    UFILL(GUInt16); break;
+    case GDT_Int16:     UFILL(GInt16);  break;
+    case GDT_Int32:     UFILL(GInt32);  break;
+    case GDT_UInt32:    UFILL(GUInt32); break;
+    case GDT_Float32:   UFILL(float);   break;
+    case GDT_Float64:   UFILL(double);  break;
     default: break;
     }
 #undef UFILL
@@ -124,7 +246,7 @@ static CPLErr DecompressLERC(buf_mgr &dst, buf_mgr &src, const ILImage &img)
 
 // Populate a bitmask based on comparison with the image no data value
 // Returns the number of NoData values found
-template <typename T> int MaskFill(BitMask2 &bitMask, T *src, const ILImage &img)
+template <typename T> static int MaskFill(BitMask2 &bitMask, T *src, const ILImage &img)
 {
     int w = img.pagesize.x;
     int h = img.pagesize.y;
@@ -132,18 +254,17 @@ template <typename T> int MaskFill(BitMask2 &bitMask, T *src, const ILImage &img
 
     bitMask.SetSize(w, h);
     bitMask.SetAllValid();
-    T *ptr = src;
 
     // No data value
-    T ndv = T(img.NoDataValue);
+    T ndv = static_cast<T>(img.NoDataValue);
     if (!img.hasNoData) ndv = 0; // It really doesn't get called when img doesn't have NoDataValue
 
     for (int i = 0; i < h; i++)
-	for (int j = 0; j < w; j++)
-	    if (ndv == *ptr++) {
-		bitMask.SetInvalid(i, j);
-		count++;
-	    }
+        for (int j = 0; j < w; j++)
+            if (ndv == *src++) {
+                bitMask.SetInvalid(i, j);
+                count++;
+            }
 
     return count;
 }
@@ -156,21 +277,21 @@ static CPLErr CompressLERC2(buf_mgr &dst, buf_mgr &src, const ILImage &img, doub
     BitMask2 bitMask;
     int ndv_count = 0;
     if (img.hasNoData) { // Only build a bitmask if no data value is defined
-	switch (img.dt) {
+        switch (img.dt) {
 
-#define MASK(T) ndv_count = MaskFill(bitMask, (T *)(src.buffer), img)
+#define MASK(T) ndv_count = MaskFill(bitMask, reinterpret_cast<T *>(src.buffer), img)
 
-	case GDT_Byte:		MASK(GByte);	break;
-	case GDT_UInt16:	MASK(GUInt16);	break;
-	case GDT_Int16:		MASK(GInt16);	break;
-	case GDT_Int32:		MASK(GInt32);	break;
-	case GDT_UInt32:	MASK(GUInt32);	break;
-	case GDT_Float32:	MASK(float);	break;
-	case GDT_Float64:	MASK(double);	break;
-        default:                CPLAssert(FALSE); break;
+        case GDT_Byte:          MASK(GByte);    break;
+        case GDT_UInt16:        MASK(GUInt16);  break;
+        case GDT_Int16:         MASK(GInt16);   break;
+        case GDT_Int32:         MASK(GInt32);   break;
+        case GDT_UInt32:        MASK(GUInt32);  break;
+        case GDT_Float32:       MASK(float);    break;
+        case GDT_Float64:       MASK(double);   break;
+        default:                CPLAssert(false); break;
 
 #undef MASK
-	}
+        }
     }
     // Set bitmask if it has some ndvs
     Lerc2 lerc2(w, h, (ndv_count == 0) ? NULL : bitMask.Bits());
@@ -181,18 +302,18 @@ static CPLErr CompressLERC2(buf_mgr &dst, buf_mgr &src, const ILImage &img, doub
     switch (img.dt) {
 
 #define ENCODE(T) if (true) { \
-    sz = lerc2.ComputeNumBytesNeededToWrite((T *)(src.buffer), precision, ndv_count != 0);\
-    success = lerc2.Encode((T *)(src.buffer), &ptr);\
+    sz = lerc2.ComputeNumBytesNeededToWrite(reinterpret_cast<T *>(src.buffer), precision, ndv_count != 0);\
+    success = lerc2.Encode(reinterpret_cast<T *>(src.buffer), &ptr);\
     }
 
-    case GDT_Byte:	ENCODE(GByte);	    break;
-    case GDT_UInt16:	ENCODE(GUInt16);    break;
-    case GDT_Int16:	ENCODE(GInt16);	    break;
-    case GDT_Int32:	ENCODE(GInt32);	    break;
-    case GDT_UInt32:	ENCODE(GUInt32);    break;
-    case GDT_Float32:	ENCODE(float);	    break;
-    case GDT_Float64:	ENCODE(double);	    break;
-    default:            CPLAssert(FALSE); break;
+    case GDT_Byte:      ENCODE(GByte);      break;
+    case GDT_UInt16:    ENCODE(GUInt16);    break;
+    case GDT_Int16:     ENCODE(GInt16);     break;
+    case GDT_Int32:     ENCODE(GInt32);     break;
+    case GDT_UInt32:    ENCODE(GUInt32);    break;
+    case GDT_Float32:   ENCODE(float);      break;
+    case GDT_Float64:   ENCODE(double);     break;
+    default:            CPLAssert(false); break;
 
 #undef ENCODE
     }
@@ -200,70 +321,90 @@ static CPLErr CompressLERC2(buf_mgr &dst, buf_mgr &src, const ILImage &img, doub
     // write changes the value of the pointer, we can find the size by testing how far it moved
     dst.size = (char *)ptr - dst.buffer;
     if (!success || sz != static_cast<long>(dst.size)) {
-	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error during LERC2 compression");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error during LERC2 compression");
+        return CE_Failure;
     }
     CPLDebug("MRF_LERC", "LERC2 Compressed to %d\n", (int)sz);
     return CE_None;
 }
 
 // Populate a bitmask based on comparison with the image no data value
-template <typename T> void UnMask(BitMask2 &bitMask, T *arr, const ILImage &img)
+template <typename T> static void UnMask(BitMask2 &bitMask, T *arr, const ILImage &img)
 {
     int w = img.pagesize.x;
     int h = img.pagesize.y;
     if (w * h == bitMask.CountValidBits())
-	return;
+        return;
     T *ptr = arr;
     T ndv = T(img.NoDataValue);
     if (!img.hasNoData) ndv = 0; // It doesn't get called when img doesn't have NoDataValue
     for (int i = 0; i < h; i++)
-	for (int j = 0; j < w; j++, ptr++)
-	    if (!bitMask.IsValid(i, j))
-		*ptr = ndv;
+        for (int j = 0; j < w; j++, ptr++)
+            if (!bitMask.IsValid(i, j))
+                *ptr = ndv;
     return;
 }
 
 CPLErr LERC_Band::Decompress(buf_mgr &dst, buf_mgr &src)
 {
-    const Byte *ptr = (Byte *)(src.buffer);
+    const Byte *ptr = reinterpret_cast<Byte *>(src.buffer);
     Lerc2::HeaderInfo hdInfo;
     Lerc2 lerc2;
+    if (src.size < Lerc2::ComputeNumBytesHeader()) {
+        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Invalid LERC");
+        return CE_Failure;
+    }
+
+    // If not Lerc2 switch to Lerc
     if (!lerc2.GetHeaderInfo(ptr, hdInfo))
-	return DecompressLERC(dst, src, img);
-    // It is lerc2 here
+        return DecompressLERC(dst, src, img);
+
+    // It is Lerc2 test that it looks reasonable
+    if (static_cast<size_t>(hdInfo.blobSize) > src.size) {
+        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Lerc2 object too large");
+        return CE_Failure;
+    }
+
+    if (img.pagesize.x != hdInfo.nCols
+        || img.pagesize.y != hdInfo.nRows
+        || img.dt != GetL2DataType(hdInfo.dt)
+        || dst.size < static_cast<size_t>(hdInfo.nCols * hdInfo.nRows * GDALGetDataTypeSizeBytes(img.dt))) {
+        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Lerc2 format");
+        return CE_Failure;
+    }
+
     bool success = false;
     BitMask2 bitMask(img.pagesize.x, img.pagesize.y);
     switch (img.dt) {
 #define DECODE(T) success = lerc2.Decode(&ptr, reinterpret_cast<T *>(dst.buffer), bitMask.Bits())
-    case GDT_Byte:	DECODE(GByte);	    break;
-    case GDT_UInt16:	DECODE(GUInt16);    break;
-    case GDT_Int16:	DECODE(GInt16);	    break;
-    case GDT_Int32:	DECODE(GInt32);	    break;
-    case GDT_UInt32:	DECODE(GUInt32);    break;
-    case GDT_Float32:	DECODE(float);	    break;
-    case GDT_Float64:	DECODE(double);	    break;
-    default:            CPLAssert(FALSE);   break;
+    case GDT_Byte:      DECODE(GByte);      break;
+    case GDT_UInt16:    DECODE(GUInt16);    break;
+    case GDT_Int16:     DECODE(GInt16);     break;
+    case GDT_Int32:     DECODE(GInt32);     break;
+    case GDT_UInt32:    DECODE(GUInt32);    break;
+    case GDT_Float32:   DECODE(float);      break;
+    case GDT_Float64:   DECODE(double);     break;
+    default:            CPLAssert(false);   break;
 #undef DECODE
     }
     if (!success) {
-	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error during LERC2 decompression");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Error during LERC2 decompression");
+        return CE_Failure;
     }
     if (!img.hasNoData)
-	return CE_None;
+        return CE_None;
 
     // Fill in no data values
     switch (img.dt) {
 #define UNMASK(T) UnMask(bitMask, reinterpret_cast<T *>(dst.buffer), img)
-    case GDT_Byte:	UNMASK(GByte);	    break;
-    case GDT_UInt16:	UNMASK(GUInt16);    break;
-    case GDT_Int16:	UNMASK(GInt16);	    break;
-    case GDT_Int32:	UNMASK(GInt32);	    break;
-    case GDT_UInt32:	UNMASK(GUInt32);    break;
-    case GDT_Float32:	UNMASK(float);	    break;
-    case GDT_Float64:	UNMASK(double);	    break;
-    default:            CPLAssert(FALSE);   break;
+    case GDT_Byte:      UNMASK(GByte);      break;
+    case GDT_UInt16:    UNMASK(GUInt16);    break;
+    case GDT_Int16:     UNMASK(GInt16);     break;
+    case GDT_Int32:     UNMASK(GInt32);     break;
+    case GDT_UInt32:    UNMASK(GUInt32);    break;
+    case GDT_Float32:   UNMASK(float);      break;
+    case GDT_Float64:   UNMASK(double);     break;
+    default:            CPLAssert(false);   break;
 #undef DECODE
     }
     return CE_None;
@@ -272,30 +413,105 @@ CPLErr LERC_Band::Decompress(buf_mgr &dst, buf_mgr &src)
 CPLErr LERC_Band::Compress(buf_mgr &dst, buf_mgr &src)
 {
     if (version == 2)
-	return CompressLERC2(dst, src, img, precision);
+        return CompressLERC2(dst, src, img, precision);
     else
-	return CompressLERC(dst, src, img, precision);
+        return CompressLERC(dst, src, img, precision);
 }
 
-LERC_Band::LERC_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level):
+CPLXMLNode *LERC_Band::GetMRFConfig(GDALOpenInfo *poOpenInfo)
+{
+    // Should have enough data pre-read
+    if(poOpenInfo->nHeaderBytes <
+        static_cast<int>(CntZImage::computeNumBytesNeededToWriteVoidImage()))
+    {
+        return NULL;
+    }
+
+    if (poOpenInfo->eAccess != GA_ReadOnly
+        || poOpenInfo->pszFilename == NULL
+        || poOpenInfo->pabyHeader == NULL
+        || strlen(poOpenInfo->pszFilename) < 2)
+        return NULL;
+
+    // Check the header too
+    char *psz = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
+    CPLString sHeader;
+    sHeader.assign(psz, psz + poOpenInfo->nHeaderBytes);
+    if (!IsLerc(sHeader))
+        return NULL;
+
+    // Get the desired type
+    const char *pszDataType = CSLFetchNameValue(poOpenInfo->papszOpenOptions, "DATATYPE");
+    GDALDataType dt = GDT_Unknown; // Use this as a validity flag
+    if (pszDataType)
+        dt = GDALGetDataTypeByName(pszDataType);
+
+
+    // Use this structure to fetch width and height
+    ILSize size(-1, -1, 1, 1, 1);
+
+    // Try lerc2
+    if (sHeader.size() >= Lerc2::ComputeNumBytesHeader()) {
+        Lerc2 l2;
+        Lerc2::HeaderInfo hinfo;
+        hinfo.RawInit();
+        if (l2.GetHeaderInfo(reinterpret_cast<Byte *>(psz), hinfo)) {
+            size.x = hinfo.nCols;
+            size.y = hinfo.nRows;
+            // Set the datatype, which marks it as valid
+            dt = GetL2DataType(hinfo.dt);
+        }
+    }
+
+    if (size.x <= 0 && sHeader.size() >= CntZImage::computeNumBytesNeededToWriteVoidImage()) {
+        CntZImage zImg;
+        Byte *pb = reinterpret_cast<Byte *>(psz);
+        // Read only the header, changes pb
+        if (zImg.read(&pb, 1e12, true))
+        {
+            size.x = zImg.getWidth();
+            size.y = zImg.getHeight();
+            // Read as byte by default, otherwise LERC can be read as anything
+            if (dt == GDT_Unknown)
+                dt = GDT_Byte;
+        }
+    }
+
+    if (size.x <=0 || size.y <=0 || dt == GDT_Unknown)
+        return NULL;
+
+    // Build and return the MRF configuration for a single tile reader
+    CPLXMLNode *config = CPLCreateXMLNode(NULL, CXT_Element, "MRF_META");
+    CPLXMLNode *raster = CPLCreateXMLNode(config, CXT_Element, "Raster");
+    XMLSetAttributeVal(raster, "Size", size, "%.0f");
+    XMLSetAttributeVal(raster, "PageSize", size, "%.0f");
+    CPLCreateXMLElementAndValue(raster, "Compression", CompName(IL_LERC));
+    CPLCreateXMLElementAndValue(raster, "DataType", GDALGetDataTypeName(dt));
+    CPLCreateXMLElementAndValue(raster, "DataFile", poOpenInfo->pszFilename);
+    // Set a magic index file name to prevent the driver from attempting to open itd
+    CPLCreateXMLElementAndValue(raster, "IndexFile", "(null)");
+
+    return config;
+}
+
+LERC_Band::LERC_Band(GDALMRFDataset *pDS, const ILImage &image,
+                      int b, int level ) :
     GDALMRFRasterBand(pDS, image, b, level)
 {
-    // Pick 1/1000 for floats and 0.5 losless for integers
+    // Pick 1/1000 for floats and 0.5 losless for integers.
     if (eDataType == GDT_Float32 || eDataType == GDT_Float64 )
-	precision = strtod(GetOptionValue( "LERC_PREC" , ".001" ),NULL);
+        precision = strtod(GetOptionValue( "LERC_PREC" , ".001" ),NULL);
     else
-	precision = std::max(0.5, strtod(GetOptionValue("LERC_PREC", ".5"), NULL));
+        precision =
+            std::max(0.5, strtod(GetOptionValue("LERC_PREC", ".5"), NULL));
 
-    // Encode in V2 by default
-    version = GetOptlist().FetchBoolean("V1", FALSE) ? 1:2;
+    // Encode in V2 by default.
+    version = GetOptlist().FetchBoolean("V1", FALSE) ? 1 : 2;
 
-    // Enlarge the page buffer in this case, LERC may expand data
+    // Enlarge the page buffer in this case, LERC may expand data.
     pDS->SetPBufferSize( 2 * image.pageSizeBytes);
 }
 
-LERC_Band::~LERC_Band()
-{
-}
-
+LERC_Band::~LERC_Band() {}
 
 NAMESPACE_MRF_END
diff --git a/frmts/mrf/PNG_band.cpp b/frmts/mrf/PNG_band.cpp
index d304b58..e1bb58b 100644
--- a/frmts/mrf/PNG_band.cpp
+++ b/frmts/mrf/PNG_band.cpp
@@ -33,10 +33,7 @@
 * limitations under the License.
 */
 
-
-
 /*
- * $Id$
  * PNG band
  * PNG page compression and decompression functions
  * These functions are not methods, they reside in the global space
@@ -54,6 +51,8 @@ CPL_C_START
 #endif
 CPL_C_END
 
+CPL_CVSID("$Id: PNG_band.cpp 35897 2016-10-24 11:54:24Z goatbar $");
+
 NAMESPACE_MRF_START
 
 // Do Nothing
@@ -174,7 +173,7 @@ CPLErr PNG_Codec::DecompressPNG(buf_mgr &dst, buf_mgr &src)
 }
 
 /**
-*\Brief Compress a page in PNG format
+*\brief Compress a page in PNG format
 * Returns the compressed size in dst.size
 *
 */
@@ -237,7 +236,7 @@ CPLErr PNG_Codec::CompressPNG(buf_mgr &dst, buf_mgr &src)
     png_set_asm_flags(pngp, flags | mask); // use flags &~mask to disable all
 
     // Test that the MMX is compiled into PNG
-    //	fprintf(stderr,"MMX support is %d\n", png_mmx_support());
+    // fprintf(stderr,"MMX support is %d\n", png_mmx_support());
 
 #endif
 
@@ -327,7 +326,7 @@ CPLErr PNG_Band::Decompress(buf_mgr &dst, buf_mgr &src)
 }
 
 CPLErr PNG_Band::Compress(buf_mgr &dst, buf_mgr &src)
-{   
+{
     if (!codec.PNGColors && img.comp == IL_PPNG) { // Late set PNG palette to conserve memory
         GDALColorTable *poCT = GetColorTable();
         if (!poCT) {
@@ -342,20 +341,25 @@ CPLErr PNG_Band::Compress(buf_mgr &dst, buf_mgr &src)
 }
 
 /**
- * \Brief For PPNG, builds the data structures needed to write the palette
+ * \brief For PPNG, builds the data structures needed to write the palette
  * The presence of the PNGColors and PNGAlpha is used as a flag for PPNG only
  */
 
-PNG_Band::PNG_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level) :
-GDALMRFRasterBand(pDS, image, b, level), codec(image)
-
+PNG_Band::PNG_Band( GDALMRFDataset *pDS, const ILImage &image,
+                    int b, int level ) :
+    GDALMRFRasterBand(pDS, image, b, level),
+    codec(image)
 {   // Check error conditions
-    if (image.dt != GDT_Byte && image.dt != GDT_Int16 && image.dt != GDT_UInt16) {
-        CPLError(CE_Failure, CPLE_NotSupported, "Data type not supported by MRF PNG");
+    if (image.dt != GDT_Byte && image.dt != GDT_Int16 && image.dt != GDT_UInt16)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Data type not supported by MRF PNG");
         return;
     }
-    if (image.pagesize.c > 4) {
-        CPLError(CE_Failure, CPLE_NotSupported, "MRF PNG can only handle up to 4 bands per page");
+    if (image.pagesize.c > 4)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "MRF PNG can only handle up to 4 bands per page");
         return;
     }
     // PNGs can be larger than the source, especially for small page size
diff --git a/frmts/mrf/Raw_band.cpp b/frmts/mrf/Raw_band.cpp
index a7f04ab..6debd31 100644
--- a/frmts/mrf/Raw_band.cpp
+++ b/frmts/mrf/Raw_band.cpp
@@ -34,7 +34,6 @@
 */
 
 /*
- * $Id$
  * raw band
  * raw page compression and decompression functions
  * Simple copy of data
@@ -43,6 +42,8 @@
 
 #include "marfa.h"
 
+CPL_CVSID("$Id: Raw_band.cpp 34811 2016-07-28 15:15:05Z goatbar $");
+
 NAMESPACE_MRF_START
 
 inline CPLErr NONE(buf_mgr &dst, buf_mgr &src)
diff --git a/frmts/mrf/Tif_band.cpp b/frmts/mrf/Tif_band.cpp
index 158795f..1666c9d 100644
--- a/frmts/mrf/Tif_band.cpp
+++ b/frmts/mrf/Tif_band.cpp
@@ -45,6 +45,8 @@
 
 #include "marfa.h"
 
+CPL_CVSID("$Id: Tif_band.cpp 35250 2016-08-30 04:20:18Z goatbar $");
+
 NAMESPACE_MRF_START
 
 // Returns a string in /vsimem/ + prefix + count that doesn't exist when this function gets called
@@ -78,44 +80,44 @@ static CPLErr CompressTIF(buf_mgr &dst, buf_mgr &src, const ILImage &img, char *
     CPLString fname = uniq_memfname("mrf_tif_write");
 
     GDALDataset *poTiff = poTiffDriver->Create(fname, img.pagesize.x, img.pagesize.y,
-	img.pagesize.c, img.dt, papszOptions );
+                                               img.pagesize.c, img.dt, papszOptions );
 
     // Read directly to avoid double caching in GDAL
     // Unfortunately not possible for multiple bands
     if (img.pagesize.c == 1) {
-	ret = poTiff->GetRasterBand(1)->WriteBlock(0,0,src.buffer);
+        ret = poTiff->GetRasterBand(1)->WriteBlock(0,0,src.buffer);
     } else {
-	ret = poTiff->RasterIO(GF_Write, 0,0,img.pagesize.x,img.pagesize.y,
-	    src.buffer, img.pagesize.x, img.pagesize.y, img.dt, img.pagesize.c,
-	    NULL, 0,0,0
+        ret = poTiff->RasterIO(GF_Write, 0,0,img.pagesize.x,img.pagesize.y,
+            src.buffer, img.pagesize.x, img.pagesize.y, img.dt, img.pagesize.c,
+            NULL, 0,0,0
 #if GDAL_VERSION_MAJOR >= 2
             ,NULL
 #endif
-	    );
+            );
     }
-    if (CE_None != ret)	return ret;
+    if (CE_None != ret) return ret;
     GDALClose(poTiff);
 
     // Check that we can read the file
     if (VSIStatL(fname, &statb))
     {
-	CPLError(CE_Failure,CPLE_AppDefined,
-	    "MRF: TIFF, can't stat %s", fname.c_str());
+        CPLError(CE_Failure,CPLE_AppDefined,
+            "MRF: TIFF, can't stat %s", fname.c_str());
         return CE_Failure;
     }
 
     if (size_t(statb.st_size) > dst.size)
     {
-	CPLError(CE_Failure,CPLE_AppDefined,
-	    "MRF: TIFF, Tiff generated is too large");
+        CPLError(CE_Failure,CPLE_AppDefined,
+            "MRF: TIFF, Tiff generated is too large");
         return CE_Failure;
     }
 
     VSILFILE *pf = VSIFOpenL(fname,"rb");
     if (pf == NULL)
     {
-	CPLError(CE_Failure,CPLE_AppDefined,
-	    "MRF: TIFF, can't open %s", fname.c_str());
+        CPLError(CE_Failure,CPLE_AppDefined,
+            "MRF: TIFF, can't open %s", fname.c_str());
         return CE_Failure;
     }
 
@@ -134,10 +136,10 @@ static CPLErr DecompressTIF(buf_mgr &dst, buf_mgr &src, const ILImage &img)
     VSILFILE *fp = VSIFileFromMemBuffer(fname, (GByte *)(src.buffer), src.size, false);
     // Comes back opened, but we can't use it
     if (fp)
-	VSIFCloseL(fp);
+        VSIFCloseL(fp);
     else {
-	CPLError(CE_Failure,CPLE_AppDefined,
-	    "MRF: TIFF, can't open %s as a temp file", fname.c_str());
+        CPLError(CE_Failure,CPLE_AppDefined,
+            "MRF: TIFF, can't open %s as a temp file", fname.c_str());
         return CE_Failure;
     }
 #if GDAL_VERSION_MAJOR >= 2
@@ -147,8 +149,8 @@ static CPLErr DecompressTIF(buf_mgr &dst, buf_mgr &src, const ILImage &img)
     GDALDataset *poTiff = reinterpret_cast<GDALDataset*>(GDALOpen(fname, GA_ReadOnly));
 #endif
     if (poTiff == NULL) {
-	CPLError(CE_Failure,CPLE_AppDefined,
-	    "MRF: TIFF, can't open page as a Tiff");
+        CPLError(CE_Failure,CPLE_AppDefined,
+            "MRF: TIFF, can't open page as a Tiff");
         VSIUnlink(fname);
         return CE_Failure;
     }
@@ -156,15 +158,15 @@ static CPLErr DecompressTIF(buf_mgr &dst, buf_mgr &src, const ILImage &img)
     CPLErr ret;
     // Bypass the GDAL caching
     if (img.pagesize.c == 1) {
-	ret = poTiff->GetRasterBand(1)->ReadBlock(0,0,dst.buffer);
+        ret = poTiff->GetRasterBand(1)->ReadBlock(0,0,dst.buffer);
     } else {
-	ret = poTiff->RasterIO(GF_Read,0,0,img.pagesize.x,img.pagesize.y,
-	    dst.buffer, img.pagesize.x, img.pagesize.y, img.dt, img.pagesize.c,
-	    NULL, 0,0,0
+        ret = poTiff->RasterIO(GF_Read,0,0,img.pagesize.x,img.pagesize.y,
+            dst.buffer, img.pagesize.x, img.pagesize.y, img.dt, img.pagesize.c,
+            NULL, 0,0,0
 #if GDAL_VERSION_MAJOR >= 2
             ,NULL
 #endif
-	    );
+            );
     }
     GDALClose(poTiff);
     VSIUnlink(fname);
@@ -182,8 +184,9 @@ CPLErr TIF_Band::Compress(buf_mgr &dst, buf_mgr &src)
     return CompressTIF(dst,src,img, papszOptions);
 }
 
-TIF_Band::TIF_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level):
-        GDALMRFRasterBand(pDS,image,b,int(level))
+TIF_Band::TIF_Band( GDALMRFDataset *pDS, const ILImage &image,
+                    int b, int level ):
+    GDALMRFRasterBand(pDS, image, b, int(level))
 {
     // Increase the page buffer by 1K in case Tiff expands data
     pDS->SetPBufferSize(image.pageSizeBytes + 1024);
@@ -191,12 +194,16 @@ TIF_Band::TIF_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level):
     // Static create options for TIFF tiles
     papszOptions = CSLAddNameValue(NULL, "COMPRESS", "DEFLATE");
     papszOptions = CSLAddNameValue(papszOptions, "TILED", "Yes");
-    papszOptions = CSLAddNameValue(papszOptions, "BLOCKXSIZE", CPLString().Printf("%d",img.pagesize.x));
-    papszOptions = CSLAddNameValue(papszOptions, "BLOCKYSIZE", CPLString().Printf("%d",img.pagesize.y));
+    papszOptions = CSLAddNameValue(papszOptions, "BLOCKXSIZE",
+                                   CPLString().Printf("%d",img.pagesize.x));
+    papszOptions = CSLAddNameValue(papszOptions, "BLOCKYSIZE",
+                                   CPLString().Printf("%d",img.pagesize.y));
     int q = img.quality / 10;
-    // Move down so the default 85 maps to 6.  This makes the maz ZLEVEL 8, which is OK
+    // Move down so the default 85 maps to 6.  This makes the maz
+    // ZLEVEL 8, which is OK.
     if (q >2) q-=2;
-    papszOptions = CSLAddNameValue(papszOptions, "ZLEVEL", CPLString().Printf("%d",q));
+    papszOptions = CSLAddNameValue(papszOptions, "ZLEVEL",
+                                   CPLString().Printf("%d", q));
 };
 
 TIF_Band::~TIF_Band()
diff --git a/frmts/mrf/libLERC/BitMask.cpp b/frmts/mrf/libLERC/BitMask.cpp
index 2053e42..c418705 100644
--- a/frmts/mrf/libLERC/BitMask.cpp
+++ b/frmts/mrf/libLERC/BitMask.cpp
@@ -50,17 +50,17 @@ bool BitMask::RLEdecompress(const Byte* src) {
 #define READ_COUNT if (true) { count = *src++; count += (*src++ << 8); }
 
     while (sz) { // One sequence per loop
-	READ_COUNT;
-	if (count < 0) { // negative count for repeats
-	    Byte b = *src++;
-	    sz += count;
-	    while (0 != count++)
-		*dst++ = b;
-	} else { // No repeats
-	    sz -= count;
-	    while (0 != count--)
-		*dst++ = *src++;
-	}
+        READ_COUNT;
+        if (count < 0) { // negative count for repeats
+            Byte b = *src++;
+            sz += count;
+            while (0 != count++)
+                *dst++ = b;
+        } else { // No repeats
+            sz -= count;
+            while (0 != count--)
+                *dst++ = *src++;
+        }
     }
     READ_COUNT;
     return (count == EOT);
@@ -73,11 +73,11 @@ inline static int run_length(const Byte *s, int max_count)
 {
     assert(max_count && s);
     if (max_count > MAX_RUN)
-	max_count = MAX_RUN;
+        max_count = MAX_RUN;
     const Byte c = *s++;
     for (int count = 1; count < max_count; count++)
-	if (c != *s++)
-	    return count;
+        if (c != *s++)
+            return count;
     return max_count;
 }
 
@@ -104,21 +104,22 @@ int BitMask::RLEcompress(Byte *dst) const {
 
     dst += 2; // Skip the space for the first count
     while (sz) {
-	int run = run_length(src, sz);
-	if (run < MIN_RUN) { // Use one byte
-	    *dst++ = *src++;
-	    sz--;
-	    if (MAX_RUN == ++oddrun)
-		FLUSH;
-	} else { // Found a run
-	    FLUSH;
-	    WRITE_COUNT(-run);
-	    *pCnt++ = *src;
-	    src += run;
-	    sz -= run;
-	    dst = pCnt + 2; // after the next marker
-	}
+        int run = run_length(src, sz);
+        if (run < MIN_RUN) { // Use one byte
+            *dst++ = *src++;
+            sz--;
+            if (MAX_RUN == ++oddrun)
+                FLUSH;
+        } else { // Found a run
+            FLUSH;
+            WRITE_COUNT(-run);
+            *pCnt++ = *src;
+            src += run;
+            sz -= run;
+            dst = pCnt + 2; // after the next marker
+        }
     }
+    // cppcheck-suppress uselessAssignmentPtrArg
     FLUSH;
     WRITE_COUNT(EOT); // End marker
     // return compressed output size
@@ -138,18 +139,18 @@ int BitMask::RLEsize() const {
     // output size, start with size of end marker
     int osz = 2;
     while (sz) {
-	int run = run_length(src, sz);
-	if (run < MIN_RUN) {
-	    src++;
-	    sz--;
-	    if (MAX_RUN == ++oddrun)
-		SIMFLUSH;
-	} else {
-	    SIMFLUSH;
-	    src += run;
-	    sz -= run;
-	    osz += 3; // Any run is 3 bytes
-	}
+        int run = run_length(src, sz);
+        if (run < MIN_RUN) {
+            src++;
+            sz--;
+            if (MAX_RUN == ++oddrun)
+                SIMFLUSH;
+        } else {
+            SIMFLUSH;
+            src += run;
+            sz -= run;
+            osz += 3; // Any run is 3 bytes
+        }
     }
     SIMFLUSH;
     return osz;
diff --git a/frmts/mrf/libLERC/BitMask.h b/frmts/mrf/libLERC/BitMask.h
index 7855643..2f3fa3c 100644
--- a/frmts/mrf/libLERC/BitMask.h
+++ b/frmts/mrf/libLERC/BitMask.h
@@ -13,7 +13,7 @@ A local copy of the license and additional notices are located with the
 source distribution at:
 http://github.com/Esri/lerc/
 Contributors:  Thomas Maurer
-	       Lucian Plesea
+               Lucian Plesea
 */
 
 #ifndef BITMASK_H
@@ -34,16 +34,16 @@ public:
   {
       m_pBits = new Byte[Size()];
       if (!m_pBits)
-	  m_nRows = m_nCols = 0;
+          m_nRows = m_nCols = 0;
       else
-	  m_pBits[Size() - 1] = 0; // Set potential pad bytes to zero
+           m_pBits[Size() - 1] = 0; // Set potential pad bytes to zero
   }
-  ~BitMask()				      { if (m_pBits) delete[] m_pBits; }
+  ~BitMask()                                  { if (m_pBits) delete[] m_pBits; }
 
   Byte  IsValid(int k) const                  { return (m_pBits[k >> 3] & Bit(k)) != 0; }
   void  SetValid(int k) const                 { m_pBits[k >> 3] |= Bit(k); }
   void  SetInvalid(int k) const               { m_pBits[k >> 3] &= ~Bit(k); }
-  int	Size() const			      { return (m_nCols * m_nRows - 1) / 8 + 1; }
+  int   Size() const                          { return (m_nCols * m_nRows - 1) / 8 + 1; }
 
   // max RLE compressed size is n + 4 + 2 * (n - 1) / 32767
   // Returns encoded size
@@ -58,7 +58,7 @@ private:
   Byte*  m_pBits;
   int   m_nRows, m_nCols;
 
-  Byte  Bit(int k) const                      { return (1 << 7) >> (k & 7); }
+  static Byte  Bit(int k)                      { return (1 << 7) >> (k & 7); }
 
   // Disable assignment op, default and copy constructor
   BitMask();
diff --git a/frmts/mrf/libLERC/BitMask2.h b/frmts/mrf/libLERC/BitMask2.h
index eba1b6d..345a417 100644
--- a/frmts/mrf/libLERC/BitMask2.h
+++ b/frmts/mrf/libLERC/BitMask2.h
@@ -57,7 +57,7 @@ public:
   int  Size() const                          { return (m_nCols * m_nRows + 7) >> 3; }
   const Byte* Bits() const                   { return m_pBits; }
   Byte* Bits()                               { return m_pBits; }
-  Byte  Bit(int k) const                     { return (1 << 7) >> (k & 7); }
+  static Byte  Bit(int k)                    { return (1 << 7) >> (k & 7); }
 
   int  CountValidBits() const;
   void  Clear();
diff --git a/frmts/mrf/libLERC/BitStuffer.cpp b/frmts/mrf/libLERC/BitStuffer.cpp
index ea7b30c..ed9f50f 100644
--- a/frmts/mrf/libLERC/BitStuffer.cpp
+++ b/frmts/mrf/libLERC/BitStuffer.cpp
@@ -35,7 +35,7 @@ NAMESPACE_LERC_START
 // see the old stream IO functions below on how to call.
 // if you change write(...) / read(...), don't forget to update computeNumBytesNeeded(...).
 
-bool BitStuffer::write(Byte** ppByte, const vector<unsigned int>& dataVec) const
+bool BitStuffer::write(Byte** ppByte, const vector<unsigned int>& dataVec)
 {
   if (!ppByte || dataVec.empty())
     return false;
@@ -117,6 +117,7 @@ bool BitStuffer::write(Byte** ppByte, const vector<unsigned int>& dataVec) const
     for (unsigned int i = 0; i < numUInts; i++)
     {
       SWAP_4(*dstPtr);
+      // cppcheck-suppress unreadVariable
       dstPtr++;
     }
 
@@ -128,7 +129,7 @@ bool BitStuffer::write(Byte** ppByte, const vector<unsigned int>& dataVec) const
 
 // -------------------------------------------------------------------------- ;
 
-bool BitStuffer::read(Byte** ppByte, vector<unsigned int>& dataVec) const
+bool BitStuffer::read(Byte** ppByte, vector<unsigned int>& dataVec)
 {
   if (!ppByte)
     return false;
@@ -192,6 +193,7 @@ bool BitStuffer::read(Byte** ppByte, vector<unsigned int>& dataVec) const
         unsigned int n3 = srcValue << bitPos;
         *dstPtr++ = n3 >> (32 - numBits);
         bitPos += numBits;
+        // cppcheck-suppress shiftTooManyBits
         if (bitPos == 32)    // shift >= 32 is undefined
         {
           bitPos = 0;
@@ -234,7 +236,7 @@ unsigned int BitStuffer::computeNumBytesNeeded(unsigned int numElem, unsigned in
 
 // -------------------------------------------------------------------------- ;
 // -------------------------------------------------------------------------- ;
-unsigned int BitStuffer::findMax(const vector<unsigned int>& dataVec) const
+unsigned int BitStuffer::findMax(const vector<unsigned int>& dataVec)
 {
   unsigned int maxElem = 0;
   for (size_t i = 0; i < dataVec.size(); i++)
@@ -244,7 +246,7 @@ unsigned int BitStuffer::findMax(const vector<unsigned int>& dataVec) const
 
 // -------------------------------------------------------------------------- ;
 
-bool BitStuffer::writeUInt(Byte** ppByte, unsigned int k, int numBytes) const
+bool BitStuffer::writeUInt(Byte** ppByte, unsigned int k, int numBytes)
 {
   Byte* ptr = *ppByte;
 
@@ -272,7 +274,7 @@ bool BitStuffer::writeUInt(Byte** ppByte, unsigned int k, int numBytes) const
 
 // -------------------------------------------------------------------------- ;
 
-bool BitStuffer::readUInt(Byte** ppByte, unsigned int& k, int numBytes) const
+bool BitStuffer::readUInt(Byte** ppByte, unsigned int& k, int numBytes)
 {
   Byte* ptr = *ppByte;
 
diff --git a/frmts/mrf/libLERC/BitStuffer.h b/frmts/mrf/libLERC/BitStuffer.h
index e7bb9f4..093826d 100644
--- a/frmts/mrf/libLERC/BitStuffer.h
+++ b/frmts/mrf/libLERC/BitStuffer.h
@@ -36,18 +36,18 @@ public:
   virtual ~BitStuffer()  {}
 
   // these 2 do not allocate memory. Byte ptr is moved like a file pointer.
-  bool write(Byte** ppByte, const std::vector<unsigned int>& dataVec) const;
-  bool read( Byte** ppByte, std::vector<unsigned int>& dataVec) const;
+  static bool write(Byte** ppByte, const std::vector<unsigned int>& dataVec);
+  static bool read( Byte** ppByte, std::vector<unsigned int>& dataVec);
 
   static unsigned int computeNumBytesNeeded(unsigned int numElem, unsigned int maxElem);
   static unsigned int numExtraBytesToAllocate()  { return 3; }
 
 protected:
-  unsigned int findMax(const std::vector<unsigned int>& dataVec) const;
+  static unsigned int findMax(const std::vector<unsigned int>& dataVec);
 
   // numBytes = 1, 2, or 4
-  bool writeUInt(Byte** ppByte, unsigned int k, int numBytes) const;
-  bool readUInt( Byte** ppByte, unsigned int& k, int numBytes) const;
+  static bool writeUInt(Byte** ppByte, unsigned int k, int numBytes);
+  static bool readUInt( Byte** ppByte, unsigned int& k, int numBytes);
 
   static int numBytesUInt(unsigned int k)  { return (k < 256) ? 1 : (k < (1 << 16)) ? 2 : 4; }
   static unsigned int numTailBytesNotNeeded(unsigned int numElem, int numBits);
diff --git a/frmts/mrf/libLERC/BitStuffer2.cpp b/frmts/mrf/libLERC/BitStuffer2.cpp
index 7aa9eee..4b21e57 100644
--- a/frmts/mrf/libLERC/BitStuffer2.cpp
+++ b/frmts/mrf/libLERC/BitStuffer2.cpp
@@ -33,7 +33,7 @@ NAMESPACE_LERC_START
 
 // if you change Encode(...) / Decode(...), don't forget to update ComputeNumBytesNeeded(...)
 
-bool BitStuffer2::EncodeSimple(Byte** ppByte, const vector<unsigned int>& dataVec) const
+bool BitStuffer2::EncodeSimple(Byte** ppByte, const vector<unsigned int>& dataVec)
 {
   if (!ppByte || dataVec.empty())
     return false;
@@ -198,7 +198,7 @@ bool BitStuffer2::Decode(const Byte** ppByte, vector<unsigned int>& dataVec) con
 // -------------------------------------------------------------------------- ;
 
 unsigned int BitStuffer2::ComputeNumBytesNeededLut(const vector<Quant >& sortedDataVec,
-                                                    bool& doLut) const
+                                                    bool& doLut)
 {
   unsigned int maxElem = static_cast<unsigned int>(sortedDataVec.back().first);
   unsigned int numElem = (unsigned int)sortedDataVec.size();
@@ -228,7 +228,7 @@ unsigned int BitStuffer2::ComputeNumBytesNeededLut(const vector<Quant >& sortedD
 // -------------------------------------------------------------------------- ;
 // -------------------------------------------------------------------------- ;
 
-void BitStuffer2::BitStuff(Byte** ppByte, const vector<unsigned int>& dataVec, int numBits) const
+void BitStuffer2::BitStuff(Byte** ppByte, const vector<unsigned int>& dataVec, int numBits)
 {
   unsigned int numElements = (unsigned int)dataVec.size();
   unsigned int numUInts = (numElements * numBits + 31) / 32;
@@ -328,6 +328,7 @@ void BitStuffer2::BitUnStuff(const Byte** ppByte, vector<unsigned int>& dataVec,
       unsigned int n2 = srcValue << bitPos;
       *dstPtr++ = n2 >> (32 - numBits);
       bitPos += numBits;
+      // cppcheck-suppress shiftTooManyBits
       if (bitPos == 32)    // shift >= 32 is undefined
       {
         bitPos = 0;
diff --git a/frmts/mrf/libLERC/BitStuffer2.h b/frmts/mrf/libLERC/BitStuffer2.h
index 527d6f5..761eadb 100644
--- a/frmts/mrf/libLERC/BitStuffer2.h
+++ b/frmts/mrf/libLERC/BitStuffer2.h
@@ -42,32 +42,34 @@ public:
   virtual ~BitStuffer2()  {}
 
   // these 3 do not allocate memory. Byte ptr is moved like a file pointer.
-  bool EncodeSimple(Byte** ppByte, const std::vector<unsigned int>& dataVec) const;
+  static bool EncodeSimple(Byte** ppByte, const std::vector<unsigned int>& dataVec);
+  // cppcheck-suppress functionStatic
   bool EncodeLut(Byte** ppByte, const std::vector<Quant>& sortedDataVec) const;
   bool Decode(const Byte** ppByte, std::vector<unsigned int>& dataVec) const;
 
-  unsigned int ComputeNumBytesNeededSimple(unsigned int numElem, unsigned int maxElem) const;
-  unsigned int ComputeNumBytesNeededLut(const std::vector<Quant>& sortedDataVec,
-                                         bool& doLut) const;
+  static unsigned int ComputeNumBytesNeededSimple(unsigned int numElem, unsigned int maxElem);
+  static unsigned int ComputeNumBytesNeededLut(const std::vector<Quant>& sortedDataVec,
+                                         bool& doLut);
 
   static unsigned int NumExtraBytesToAllocate()  { return 3; }
 
 private:
   mutable std::vector<unsigned int>  m_tmpLutVec, m_tmpIndexVec;
 
-  void BitStuff(Byte** ppByte, const std::vector<unsigned int>& dataVec, int numBits) const;
+  static void BitStuff(Byte** ppByte, const std::vector<unsigned int>& dataVec, int numBits);
+  // cppcheck-suppress functionStatic
   void BitUnStuff(const Byte** ppByte, std::vector<unsigned int>& dataVec, unsigned int numElements, int numBits) const;
-  bool EncodeUInt(Byte** ppByte, unsigned int k, int numBytes) const;     // numBytes = 1, 2, or 4
-  bool DecodeUInt(const Byte** ppByte, unsigned int& k, int numBytes) const;
-  int NumBytesUInt(unsigned int k) const  { return (k < 256) ? 1 : (k < (1 << 16)) ? 2 : 4; }
-  unsigned int NumTailBytesNotNeeded(unsigned int numElem, int numBits) const;
+  static bool EncodeUInt(Byte** ppByte, unsigned int k, int numBytes);     // numBytes = 1, 2, or 4
+  static bool DecodeUInt(const Byte** ppByte, unsigned int& k, int numBytes);
+  static int NumBytesUInt(unsigned int k) { return (k < 256) ? 1 : (k < (1 << 16)) ? 2 : 4; }
+  static unsigned int NumTailBytesNotNeeded(unsigned int numElem, int numBits);
 };
 
 // -------------------------------------------------------------------------- ;
 // -------------------------------------------------------------------------- ;
 
 inline
-unsigned int BitStuffer2::ComputeNumBytesNeededSimple(unsigned int numElem, unsigned int maxElem) const
+unsigned int BitStuffer2::ComputeNumBytesNeededSimple(unsigned int numElem, unsigned int maxElem)
 {
   int numBits = 0;
   while ((numBits < 32) && (maxElem >> numBits))
@@ -78,7 +80,7 @@ unsigned int BitStuffer2::ComputeNumBytesNeededSimple(unsigned int numElem, unsi
 // -------------------------------------------------------------------------- ;
 
 inline
-bool BitStuffer2::EncodeUInt(Byte** ppByte, unsigned int k, int numBytes) const
+bool BitStuffer2::EncodeUInt(Byte** ppByte, unsigned int k, int numBytes)
 {
   Byte* ptr = *ppByte;
 
@@ -104,7 +106,7 @@ bool BitStuffer2::EncodeUInt(Byte** ppByte, unsigned int k, int numBytes) const
 // -------------------------------------------------------------------------- ;
 
 inline
-bool BitStuffer2::DecodeUInt(const Byte** ppByte, unsigned int& k, int numBytes) const
+bool BitStuffer2::DecodeUInt(const Byte** ppByte, unsigned int& k, int numBytes)
 {
   const Byte* ptr = *ppByte;
 
@@ -130,7 +132,7 @@ bool BitStuffer2::DecodeUInt(const Byte** ppByte, unsigned int& k, int numBytes)
 // -------------------------------------------------------------------------- ;
 
 inline
-unsigned int BitStuffer2::NumTailBytesNotNeeded(unsigned int numElem, int numBits) const
+unsigned int BitStuffer2::NumTailBytesNotNeeded(unsigned int numElem, int numBits)
 {
   int numBitsTail = (numElem * numBits) & 31;
   int numBytesTail = (numBitsTail + 7) >> 3;
diff --git a/frmts/mrf/libLERC/CntZImage.cpp b/frmts/mrf/libLERC/CntZImage.cpp
index ba4b105..a2022e5 100644
--- a/frmts/mrf/libLERC/CntZImage.cpp
+++ b/frmts/mrf/libLERC/CntZImage.cpp
@@ -152,19 +152,19 @@ unsigned int CntZImage::computeNumBytesNeededToWrite(double maxZError,
       {
         // convert to bit mask
         BitMask bitMask(width_, height_);
-	// in case bitMask allocation fails
-	if (!bitMask.Size()) return 0;
+        // in case bitMask allocation fails
+        if (!bitMask.Size()) return 0;
         const CntZ* srcPtr = getData();
         for (int k = 0; k < width_ * height_ ; k++, srcPtr++)
         {
-          if (srcPtr->cnt <= 0)
+        if (srcPtr->cnt <= 0)
             bitMask.SetInvalid(k);
-	  else
-	    bitMask.SetValid(k);
+        else
+            bitMask.SetValid(k);
         }
 
         // determine numBytes needed to encode
-	numBytesOpt = static_cast<int>(bitMask.RLEsize());
+        numBytesOpt = static_cast<int>(bitMask.RLEsize());
       }
       else
       {
@@ -309,22 +309,22 @@ bool CntZImage::write(Byte** ppByte,
         const CntZ* srcPtr = getData();
         for (int k = 0; k < width_ * height_ ; k++, srcPtr++)
         {
-	  if (srcPtr->cnt <= 0)
-	    bitMask.SetInvalid(k);
-	  else
-	    bitMask.SetValid(k);
+        if (srcPtr->cnt <= 0)
+            bitMask.SetInvalid(k);
+        else
+            bitMask.SetValid(k);
         }
 
         // RLE encoding, update numBytesWritten
-	numBytesWritten = static_cast<int>(bitMask.RLEcompress(bArr));
-      }
+        numBytesWritten = static_cast<int>(bitMask.RLEcompress(bArr));
+    }
     }
     else
     {
       // encode tiles to buffer
       float maxVal;
       if (!writeTiles(zPart, maxZError, bCntsNoInt, numTilesVert, numTilesHori,
-	  bArr, numBytesWritten, maxVal))
+          bArr, numBytesWritten, maxVal))
         return false;
     }
 
@@ -386,8 +386,12 @@ bool CntZImage::read(Byte** ppByte,
   if (maxZErrorInFile > maxZError)
     return false;
 
-  if (onlyHeader)
-    return true;
+
+  if (onlyHeader) {
+      width_ = width;
+      height_ = height;
+      return true;
+  }
 
   if (!onlyZPart && !resizeFill0(width, height))
     return false;
@@ -433,12 +437,12 @@ bool CntZImage::read(Byte** ppByte,
       {
         // Read bit mask
         BitMask bitMask(width_, height_);
-	if (!bitMask.RLEdecompress(bArr))
-	    return false;
+        if (!bitMask.RLEdecompress(bArr))
+            return false;
 
-	CntZ* dstPtr = getData();
-	for (int k = 0; k < width_ * height_; k++, dstPtr++)
-	  dstPtr->cnt = bitMask.IsValid(k) ? 1.0f:0.0f;
+        CntZ* dstPtr = getData();
+        for (int k = 0; k < width_ * height_; k++, dstPtr++)
+            dstPtr->cnt = bitMask.IsValid(k) ? 1.0f:0.0f;
       }
     }
     else if (!readTiles(zPart, maxZErrorInFile, numTilesVert, numTilesHori, maxValInImg, bArr))
@@ -1119,7 +1123,7 @@ bool CntZImage::readZTile(Byte** ppByte, int i0, int i1, int j0, int j1,
 
 // -------------------------------------------------------------------------- ;
 
-int CntZImage::numBytesFlt(float z) const
+int CntZImage::numBytesFlt(float z)
 {
   short s = (short)z;
   signed char c = static_cast<signed char>(s);
@@ -1128,7 +1132,7 @@ int CntZImage::numBytesFlt(float z) const
 
 // -------------------------------------------------------------------------- ;
 
-bool CntZImage::writeFlt(Byte** ppByte, float z, int numBytes) const
+bool CntZImage::writeFlt(Byte** ppByte, float z, int numBytes)
 {
   Byte* ptr = *ppByte;
 
@@ -1157,7 +1161,7 @@ bool CntZImage::writeFlt(Byte** ppByte, float z, int numBytes) const
 
 // -------------------------------------------------------------------------- ;
 
-bool CntZImage::readFlt(Byte** ppByte, float& z, int numBytes) const
+bool CntZImage::readFlt(Byte** ppByte, float& z, int numBytes)
 {
   Byte* ptr = *ppByte;
 
@@ -1198,7 +1202,7 @@ bool CntZImage::readFlt(Byte** ppByte, float& z, int numBytes) const
 
 // endianness and alignment safe
 // returns the number of bytes it wrote, adjusts *ppByte
-int CntZImage::writeVal(Byte **ppByte, float z, int numBytes) const
+int CntZImage::writeVal(Byte **ppByte, float z, int numBytes)
 {
     assert(ppByte && *ppByte);
     assert(0 == numBytes || 1 == numBytes || 2 == numBytes || 4 == numBytes);
@@ -1206,27 +1210,27 @@ int CntZImage::writeVal(Byte **ppByte, float z, int numBytes) const
     short s = (short)z;
     // Calculate numBytes if needed
     if (0 == numBytes)
-	numBytes = (z != (float)s) ? 4 : (s != (signed char)s) ? 2 : 1;
+        numBytes = (z != (float)s) ? 4 : (s != (signed char)s) ? 2 : 1;
 
     if (4 == numBytes) {
-	// Store as floating point, 4 bytes in LSB order
-	Byte *fp = (Byte *)&z + POFFSET(float);
-	NEXTBYTE = *ADJUST(fp);
-	NEXTBYTE = *ADJUST(fp);
-	NEXTBYTE = *ADJUST(fp);
-	NEXTBYTE = *ADJUST(fp);
-	return 4;
+        // Store as floating point, 4 bytes in LSB order
+        Byte *fp = (Byte *)&z + POFFSET(float);
+        NEXTBYTE = *ADJUST(fp);
+        NEXTBYTE = *ADJUST(fp);
+        NEXTBYTE = *ADJUST(fp);
+        NEXTBYTE = *ADJUST(fp);
+        return 4;
     }
 
     // Int types, 2 or 1 bytes
     NEXTBYTE = (Byte)s; // Lower byte first
     if (2 == numBytes)
-	NEXTBYTE = (Byte)(s >> 8); // Second byte
+        NEXTBYTE = (Byte)(s >> 8); // Second byte
     return numBytes;
 }
 
 // endianness and alignment safe, not alliasing safe
-void CntZImage::readVal(Byte **ppByte, float &val, int numBytes) const
+void CntZImage::readVal(Byte **ppByte, float &val, int numBytes)
 {
     assert(numBytes == 4 || numBytes == 2 || numBytes == 1);
     assert(ppByte && *ppByte);
@@ -1234,17 +1238,18 @@ void CntZImage::readVal(Byte **ppByte, float &val, int numBytes) const
 
     // Floating point, read the 4 bytes in LSB first order
     if (4 == numBytes) {
-	Byte *vp = ((Byte*)&val) + POFFSET(float);
-	*ADJUST(vp) = NEXTBYTE;
-	*ADJUST(vp) = NEXTBYTE;
-	*ADJUST(vp) = NEXTBYTE;
-	*ADJUST(vp) = NEXTBYTE;
-	return;
+        // cppcheck-suppress unreadVariable
+        Byte *vp = ((Byte*)&val) + POFFSET(float);
+        *ADJUST(vp) = NEXTBYTE;
+        *ADJUST(vp) = NEXTBYTE;
+        *ADJUST(vp) = NEXTBYTE;
+        *ADJUST(vp) = NEXTBYTE;
+        return;
     }
 
     int v = (int)((signed char)NEXTBYTE); // Low byte, signed extended
     if (2 == numBytes)
-	v = (256 * (signed char)NEXTBYTE) | (v & 0xff);
+        v = (256 * (signed char)NEXTBYTE) | (v & 0xff);
     val = static_cast<float>(v);
 }
 
diff --git a/frmts/mrf/libLERC/CntZImage.h b/frmts/mrf/libLERC/CntZImage.h
index 0833e54..f6bb436 100644
--- a/frmts/mrf/libLERC/CntZImage.h
+++ b/frmts/mrf/libLERC/CntZImage.h
@@ -37,18 +37,17 @@ NAMESPACE_LERC_START
 
 // -------------------------------------------------------------------------- ;
 
-/**	count / z image
+/**     count / z image
  *
- *	count can also be a weight, therefore float;
- *	z can be elevation or intensity;
+ *      count can also be a weight, therefore float;
+ *      z can be elevation or intensity;
  */
 
-
 class CntZImage : public TImage< CntZ >
 {
 public:
   CntZImage();
-  const std::string getTypeString() const { return "CntZImage "; }
+  const std::string getTypeString() const override { return "CntZImage "; }
 
   bool resizeFill0(int width, int height);
   bool hasValidPixel() const;
@@ -85,11 +84,11 @@ public:
 
     for (int i = 0; i < height_*width_; i++)
     {
-      if (srcPtr->cnt > 0)
-	*dstPtr++ = (T)srcPtr->z;
-      else
-	*dstPtr++ = noDataValue;
-      srcPtr++;
+        if (srcPtr->cnt > 0)
+            *dstPtr++ = (T)srcPtr->z;
+        else
+            *dstPtr++ = noDataValue;
+        srcPtr++;
     }
 
     return true;
@@ -114,7 +113,6 @@ protected:
   unsigned int computeNumBytesNeededToWrite(double maxZError, bool onlyZPart,
     InfoFromComputeNumBytes& info) const;
 
-
   bool findTiling(bool zPart, double maxZError, bool cntsNoInt,
     int& numTilesVert, int& numTilesHori, int& numBytesOpt, float& maxValInImg) const;
 
@@ -140,20 +138,20 @@ protected:
   bool readCntTile(Byte** ppByte, int i0, int i1, int j0, int j1);
   bool readZTile(  Byte** ppByte, int i0, int i1, int j0, int j1, double maxZErrorInFile, float maxZInImg);
 
-  int numBytesFlt(float z) const;    // returns 1, 2, or 4
+  static int numBytesFlt(float z);    // returns 1, 2, or 4
   // These are not portable on architectures that enforce alignment
-  bool writeFlt(Byte** ppByte, float z, int numBytes) const;
-  bool readFlt( Byte** ppByte, float& z, int numBytes) const;
+  static bool writeFlt(Byte** ppByte, float z, int numBytes);
+  static bool readFlt( Byte** ppByte, float& z, int numBytes);
 
   // Portable versions of the above, endian independent if BIG_ENDIAN is defined when needed
 
   // Writes a floating point value as 1 or 2 byte LSB int or 4 byte LSB float
   // If numBytes is 0, it figures how many bytes to use
   // returns the number of bytes used
-  int writeVal(Byte** ppByte, float z, int numBytes = 0) const;
+  static int writeVal(Byte** ppByte, float z, int numBytes = 0);
   // Reads from an LSB int for 1, 2 bytes, or LSB float for 4
   // Not safe when alliased, cannot be used to read in place
-  void readVal(Byte** ppByte, float& z, int numBytes = 4) const;
+  static void readVal(Byte** ppByte, float& z, int numBytes = 4);
 
 protected:
 
diff --git a/frmts/mrf/libLERC/Defines.h b/frmts/mrf/libLERC/Defines.h
index 134ef85..0009aa3 100644
--- a/frmts/mrf/libLERC/Defines.h
+++ b/frmts/mrf/libLERC/Defines.h
@@ -32,6 +32,11 @@ Contributors:
 #include "cpl_port.h"
 #endif
 
+// Compatibility hack for non-C++11 compilers
+#if !(__cplusplus >= 201103L || _MSC_VER >= 1500)
+#define override
+#endif
+
 #define NAMESPACE_LERC_START namespace LercNS {
 #define NAMESPACE_LERC_END }
 #define USING_NAMESPACE_LERC using namespace LercNS;
@@ -45,7 +50,7 @@ struct Quant : public std::pair<unsigned int, unsigned int>
 {
     // This is default behavior in C++14, but not before
     bool operator<(const Quant& other) const {
-	return first < other.first;
+        return first < other.first;
     }
 };
 
diff --git a/frmts/mrf/libLERC/Huffman.cpp b/frmts/mrf/libLERC/Huffman.cpp
index dc6bd0b..9e26473 100644
--- a/frmts/mrf/libLERC/Huffman.cpp
+++ b/frmts/mrf/libLERC/Huffman.cpp
@@ -69,12 +69,12 @@ bool Huffman::ComputeCodes(const vector<int>& histo)
   Node nodeNonConst = pq.top();
   nodeNonConst.FreeTree(numNodes);
 
-  if (numNodes != 0)    // check the ref count
-    return false;
-
-  if (!ConvertCodesToCanonical())
-    return false;
-
+  if (numNodes != 0)    // check the ref count
+    return false;
+
+  if (!ConvertCodesToCanonical())
+    return false;
+
   return true;
 }
 
@@ -231,7 +231,8 @@ bool Huffman::BuildTreeFromCodes(int& numBitsLUT)
   numBitsLUT = min(maxLen, m_maxNumBitsLUT);
 
   m_decodeLUT.clear();
-  m_decodeLUT.assign(1 << numBitsLUT, pair<short, short>((short)-1, (short)-1));
+  const int lutMaxSize = 1 << numBitsLUT;
+  m_decodeLUT.assign(lutMaxSize, pair<short, short>((short)-1, (short)-1));
 
   for (int i = i0; i < i1; i++)
   {
@@ -266,7 +267,7 @@ bool Huffman::BuildTreeFromCodes(int& numBitsLUT)
     }
   }
 
-  int numNodesCreated = 1;
+  /* int numNodesCreated = 1; */
   Node emptyNode((short)-1, 0);
 
   if (!m_root)
@@ -290,7 +291,7 @@ bool Huffman::BuildTreeFromCodes(int& numBitsLUT)
           if (!node->child1)
           {
             node->child1 = new Node(emptyNode);
-            numNodesCreated++;
+            /* numNodesCreated++; */
           }
           node = node->child1;
         }
@@ -299,7 +300,7 @@ bool Huffman::BuildTreeFromCodes(int& numBitsLUT)
           if (!node->child0)
           {
             node->child0 = new Node(emptyNode);
-            numNodesCreated++;
+            /* numNodesCreated++; */
           }
           node = node->child0;
         }
@@ -484,6 +485,7 @@ bool Huffman::BitUnStuffCodes(const Byte** ppByte, int i0, int i1)
       if (32 - bitPos >= len)
       {
         bitPos += len;
+        // cppcheck-suppress shiftTooManyBits
         if (bitPos == 32)
         {
           bitPos = 0;
@@ -503,47 +505,47 @@ bool Huffman::BitUnStuffCodes(const Byte** ppByte, int i0, int i1)
   *ppByte += numUInts * sizeof(unsigned int);
   return true;
 }
-
-// -------------------------------------------------------------------------- ;
-
-struct MyLargerThanOp
-{
-  inline bool operator() (const pair<int, int>& p0, const pair<int, int>& p1)  { return p0.first > p1.first; }
-};
-
-// -------------------------------------------------------------------------- ;
-
-bool Huffman::ConvertCodesToCanonical()
-{
-  // from the non canonical code book, create an array to be sorted in descending order:
-  //   codeLength * tableSize - index
-
-  int tableSize = (int)m_codeTable.size();
-  vector<pair<int, int> > sortVec(tableSize);
-  memset(&sortVec[0], 0, tableSize * sizeof(pair<int, int>));
-
-  for (int i = 0; i < tableSize; i++)
-    if (m_codeTable[i].first > 0)
-      sortVec[i] = pair<int, int>(m_codeTable[i].first * tableSize - i, i);
-
-  // sort descending
-  std::sort(sortVec.begin(), sortVec.end(), MyLargerThanOp());
-
-  // create canonical codes and assign to orig code table
-  unsigned int codeCanonical = 0;
-  int index = sortVec[0].second;
-  short codeLen = m_codeTable[index].first;
-  int i = 0;
-  while (i < tableSize && sortVec[i].first > 0)
-  {
-    index = sortVec[i++].second;
-    short delta = codeLen - m_codeTable[index].first;
-    codeCanonical >>= delta;
-    codeLen -= delta;
-    m_codeTable[index].second = codeCanonical++;
-  }
-
-  return true;
+
+// -------------------------------------------------------------------------- ;
+
+struct MyLargerThanOp
+{
+  inline bool operator() (const pair<int, int>& p0, const pair<int, int>& p1)  { return p0.first > p1.first; }
+};
+
+// -------------------------------------------------------------------------- ;
+
+bool Huffman::ConvertCodesToCanonical()
+{
+  // from the non canonical code book, create an array to be sorted in descending order:
+  //   codeLength * tableSize - index
+
+  int tableSize = (int)m_codeTable.size();
+  vector<pair<int, int> > sortVec(tableSize);
+  memset(&sortVec[0], 0, tableSize * sizeof(pair<int, int>));
+
+  for (int i = 0; i < tableSize; i++)
+    if (m_codeTable[i].first > 0)
+      sortVec[i] = pair<int, int>(m_codeTable[i].first * tableSize - i, i);
+
+  // sort descending
+  std::sort(sortVec.begin(), sortVec.end(), MyLargerThanOp());
+
+  // create canonical codes and assign to orig code table
+  unsigned int codeCanonical = 0;
+  int index = sortVec[0].second;
+  short codeLen = m_codeTable[index].first;
+  int i = 0;
+  while (i < tableSize && sortVec[i].first > 0)
+  {
+    index = sortVec[i++].second;
+    short delta = codeLen - m_codeTable[index].first;
+    codeCanonical >>= delta;
+    codeLen -= delta;
+    m_codeTable[index].second = codeCanonical++;
+  }
+
+  return true;
 }
 
 // -------------------------------------------------------------------------- ;
diff --git a/frmts/mrf/libLERC/Huffman.h b/frmts/mrf/libLERC/Huffman.h
index 1249f88..f692d45 100644
--- a/frmts/mrf/libLERC/Huffman.h
+++ b/frmts/mrf/libLERC/Huffman.h
@@ -131,7 +131,7 @@ private:
   int m_numBitsToSkipInTree;
   Node* m_root;
 
-  int GetIndexWrapAround(int i, int size) const  { return i - (i < size ? 0 : size); }
+  static int GetIndexWrapAround(int i, int size)  { return i - (i < size ? 0 : size); }
   bool ComputeNumBytesCodeTable(int& numBytes) const;
   bool GetRange(int& i0, int& i1, int& maxCodeLength) const;
   bool BitStuffCodes(Byte** ppByte, int i0, int i1) const;
@@ -169,13 +169,13 @@ inline bool Huffman::DecodeOneValue(const unsigned int** ppSrc, int& bitPos, int
   if (!m_root)
     return false;
 
-  // skip leading 0 bits before entering the tree
-  bitPos += m_numBitsToSkipInTree;
-  if (bitPos >= 32)
-  {
-    bitPos -= 32;
-    (*ppSrc)++;
-  }
+  // skip leading 0 bits before entering the tree
+  bitPos += m_numBitsToSkipInTree;
+  if (bitPos >= 32)
+  {
+    bitPos -= 32;
+    (*ppSrc)++;
+  }
 
   const Node* node = m_root;
   value = -1;
diff --git a/frmts/mrf/libLERC/Image.h b/frmts/mrf/libLERC/Image.h
index 33d9ac4..8fa4907 100644
--- a/frmts/mrf/libLERC/Image.h
+++ b/frmts/mrf/libLERC/Image.h
@@ -30,7 +30,7 @@ Contributors:  Thomas Maurer
 
 NAMESPACE_LERC_START
 
-/**	Base class for all image classes
+/**     Base class for all image classes
  *
  */
 
@@ -55,7 +55,7 @@ public:
     Last_Type_
   };
 
-  bool isType(Type t) const	 { return t == type_; }
+  bool isType(Type t) const      { return t == type_; }
   Type getType() const           { return type_; }
   int getWidth() const          { return width_; }
   int getHeight() const         { return height_; }
@@ -77,11 +77,10 @@ protected:
   {
       return type_ == img.type_ && width_ == img.width_ && height_ == img.height_;
   }
-  bool operator != (const Image& img) const	{ return !operator==(img); };
+  bool operator != (const Image& img) const     { return !operator==(img); };
 
   Type type_;
   int width_, height_;
-
 };
 
 NAMESPACE_LERC_END
diff --git a/frmts/mrf/libLERC/Lerc2.cpp b/frmts/mrf/libLERC/Lerc2.cpp
index ad4ce6e..a5cfc59 100644
--- a/frmts/mrf/libLERC/Lerc2.cpp
+++ b/frmts/mrf/libLERC/Lerc2.cpp
@@ -103,7 +103,7 @@ bool Lerc2::Set(const BitMask2& bitMask)
 
 // -------------------------------------------------------------------------- ;
 
-unsigned int Lerc2::ComputeNumBytesHeader() const
+unsigned int Lerc2::ComputeNumBytesHeader()
 {
   // header
   unsigned int numBytes = (unsigned int)FileKey().length();
@@ -292,14 +292,14 @@ bool Lerc2::ReadMask(const Byte** ppByte)
 }
 
 void Lerc2::SortQuantArray(const vector<unsigned int>& quantVec,
-    vector<Quant>& sortedQuantVec) const
+    vector<Quant>& sortedQuantVec)
 {
     int numElem = (int)quantVec.size();
     sortedQuantVec.resize(numElem);
 
     for (int i = 0; i < numElem; i++) {
-	sortedQuantVec[i].first = quantVec[i];
-	sortedQuantVec[i].second = i;
+        sortedQuantVec[i].first = quantVec[i];
+        sortedQuantVec[i].second = i;
     }
     sort(sortedQuantVec.begin(), sortedQuantVec.end());
 }
diff --git a/frmts/mrf/libLERC/Lerc2.h b/frmts/mrf/libLERC/Lerc2.h
index 56558e0..61aadf6 100644
--- a/frmts/mrf/libLERC/Lerc2.h
+++ b/frmts/mrf/libLERC/Lerc2.h
@@ -66,7 +66,7 @@ public:
   template<class T>
   unsigned int ComputeNumBytesNeededToWrite(const T* arr, double maxZError, bool encodeMask);
 
-  unsigned int ComputeNumBytesHeader() const;
+  static unsigned int ComputeNumBytesHeader();
 
   static unsigned int NumExtraBytesToAllocate()  { return BitStuffer2::NumExtraBytesToAllocate(); }
 
@@ -112,7 +112,7 @@ private:
   mutable std::vector<std::pair<short, unsigned int> > m_huffmanCodes;    // <= 256 codes, 1.5 kB
 
 private:
-  std::string FileKey() const  { return "Lerc2 "; }
+  static std::string FileKey() { return "Lerc2 "; }
   void Init();
   bool WriteHeader(Byte** ppByte) const;
   bool ReadHeader(const Byte** ppByte, struct HeaderInfo& headerInfo) const;
@@ -135,7 +135,7 @@ private:
   bool ComputeStats(const T* data, int i0, int i1, int j0, int j1,
                     T& zMinA, T& zMaxA, int& numValidPixelA, bool& tryLutA) const;
 
-  double ComputeMaxVal(double zMin, double zMax, double maxZError) const;
+  static double ComputeMaxVal(double zMin, double zMax, double maxZError);
 
   template<class T>
   bool NeedToQuantize(int numValidPixel, T zMin, T zMax) const;
@@ -163,17 +163,17 @@ private:
 
   DataType GetDataTypeUsed(int typeCode) const;
 
-  bool WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed) const;
+  static bool WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed);
 
-  double ReadVariableDataType(const Byte** ppByte, DataType dtUsed) const;
+  static double ReadVariableDataType(const Byte** ppByte, DataType dtUsed);
 
-  template<class T>
-  DataType GetDataType(T z) const;
+  // cppcheck-suppress functionStatic
+  template<class T> DataType GetDataType(T z) const;
 
-  unsigned int GetMaxValToQuantize(DataType dt) const;
+  static unsigned int GetMaxValToQuantize(DataType dt);
 
-  void SortQuantArray(const std::vector<unsigned int>& quantVec,
-                      std::vector<Quant>& sortedQuantVec) const;
+  static void SortQuantArray(const std::vector<unsigned int>& quantVec,
+                      std::vector<Quant>& sortedQuantVec);
 
   template<class T>
   bool ComputeHistoForHuffman(const T* data, std::vector<int>& histo) const;
@@ -183,7 +183,6 @@ private:
 
   template<class T>
   bool DecodeHuffman(const Byte** ppByte, T* data) const;
-
 };
 
 // -------------------------------------------------------------------------- ;
@@ -517,7 +516,7 @@ bool Lerc2::WriteTiles(const T* data, Byte** ppByte, int& numBytes, double& zMin
       bool tryLut = false;
 
       if (!ComputeStats(data, i0, i0 + tileH, j0, j0 + tileW, zMin, zMax,
-	  numValidPixel, tryLut))
+            numValidPixel, tryLut))
         return false;
 
       if (numValidPixel > 0)
@@ -693,7 +692,7 @@ bool Lerc2::ComputeStats(const T* data, int i0, int i1, int j0, int j1,
 
 // -------------------------------------------------------------------------- ;
 
-inline double Lerc2::ComputeMaxVal(double zMin, double zMax, double maxZError) const
+inline double Lerc2::ComputeMaxVal(double zMin, double zMax, double maxZError)
 {
   double fac = 1 / (2 * maxZError);
   return (zMax - zMin) * fac;
@@ -1027,13 +1026,13 @@ int Lerc2::TypeCode(T z, DataType& dtUsed) const
       char c = (char)z;
       int tc = (T)c == z ? 2 : (T)b == z ? 1 : 0;
       dtUsed = (DataType)(dt - tc);
-		  return tc;
+      return tc;
     }
     case DT_UShort:
     {
       int tc = (T)b == z ? 1 : 0;
       dtUsed = (DataType)(dt - 2 * tc);
-		  return tc;
+      return tc;
     }
     case DT_Int:
     {
@@ -1096,7 +1095,7 @@ Lerc2::DataType Lerc2::GetDataTypeUsed(int tc) const
 // -------------------------------------------------------------------------- ;
 
 inline
-bool Lerc2::WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed) const
+bool Lerc2::WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed)
 {
   Byte* ptr = *ppByte;
 
@@ -1136,7 +1135,7 @@ bool Lerc2::WriteVariableDataType(Byte** ppByte, double z, DataType dtUsed) cons
 // -------------------------------------------------------------------------- ;
 
 inline
-double Lerc2::ReadVariableDataType(const Byte** ppByte, DataType dtUsed) const
+double Lerc2::ReadVariableDataType(const Byte** ppByte, DataType dtUsed)
 {
   const Byte* ptr = *ppByte;
 
@@ -1227,7 +1226,7 @@ Lerc2::DataType Lerc2::GetDataType(T z) const
 // -------------------------------------------------------------------------- ;
 
 inline
-unsigned int Lerc2::GetMaxValToQuantize(Lerc2::DataType dt) const
+unsigned int Lerc2::GetMaxValToQuantize(Lerc2::DataType dt)
 {
   switch (dt)
   {
@@ -1337,9 +1336,9 @@ bool Lerc2::EncodeHuffman(const T* data, Byte** ppByte, T& zMinA, T& zMaxA) cons
         T delta = val;
 
         if (val < zMinA)
-	    zMinA = val;
+            zMinA = val;
         if (val > zMaxA)
-	    zMaxA = val;
+            zMaxA = val;
 
         if (j > 0 && m_bitMask.IsValid(k - 1))
         {
@@ -1467,6 +1466,5 @@ bool Lerc2::DecodeHuffman(const Byte** ppByte, T* data) const
 
 // -------------------------------------------------------------------------- ;
 
-
 NAMESPACE_LERC_END
 #endif
diff --git a/frmts/mrf/libLERC/RLE.cpp b/frmts/mrf/libLERC/RLE.cpp
index f014660..0e06b10 100644
--- a/frmts/mrf/libLERC/RLE.cpp
+++ b/frmts/mrf/libLERC/RLE.cpp
@@ -49,7 +49,6 @@ size_t RLE::computeNumBytesRLE(const Byte* arr, size_t numBytes) const
       }
       else    // switch to odd mode
       {
-        cntEven++;
         sum += 2 + 1;
         bOdd = true;
         cntOdd = 0;
@@ -111,7 +110,7 @@ size_t RLE::computeNumBytesRLE(const Byte* arr, size_t numBytes) const
   }
   else
   {
-    cntEven++;
+    /* cntEven++; */
     sum += 2 + 1;
   }
 
@@ -276,7 +275,7 @@ bool RLE::decompress(const Byte* arrRLE, Byte** arr, size_t& numBytes) const
 
 // -------------------------------------------------------------------------- ;
 
-bool RLE::decompress(const Byte* arrRLE, Byte* arr) const
+bool RLE::decompress(const Byte* arrRLE, Byte* arr)
 {
   if (!arrRLE || !arr)
     return false;
@@ -302,7 +301,7 @@ bool RLE::decompress(const Byte* arrRLE, Byte* arr) const
 
 // -------------------------------------------------------------------------- ;
 
-void RLE::writeCount(short cnt, Byte** ppCnt, Byte** ppDst) const
+void RLE::writeCount(short cnt, Byte** ppCnt, Byte** ppDst)
 {
   SWAP_2(cnt);    // write short's in little endian byte order, always
   memcpy(*ppCnt, &cnt, sizeof(short));
@@ -312,7 +311,7 @@ void RLE::writeCount(short cnt, Byte** ppCnt, Byte** ppDst) const
 
 // -------------------------------------------------------------------------- ;
 
-short RLE::readCount(const Byte** ppCnt) const
+short RLE::readCount(const Byte** ppCnt)
 {
   short cnt;
   memcpy(&cnt, *ppCnt, sizeof(short));
diff --git a/frmts/mrf/libLERC/RLE.h b/frmts/mrf/libLERC/RLE.h
index 89168be..8f389fc 100644
--- a/frmts/mrf/libLERC/RLE.h
+++ b/frmts/mrf/libLERC/RLE.h
@@ -53,17 +53,17 @@ public:
 
   // when done, call
   // delete[] *arr;
+  // cppcheck-suppress functionStatic
   bool decompress(const Byte* arrRLE, Byte** arr, size_t& numBytes) const;
 
   // arr already allocated, just fill
-  bool decompress(const Byte* arrRLE, Byte* arr) const;
+  static bool decompress(const Byte* arrRLE, Byte* arr);
 
 protected:
   int m_minNumEven;
 
-  void writeCount(short cnt, Byte** ppCnt, Byte** ppDst) const;
-  short readCount(const Byte** ppCnt) const;
-
+  static void writeCount(short cnt, Byte** ppCnt, Byte** ppDst);
+  static short readCount(const Byte** ppCnt);
 };
 
 // -------------------------------------------------------------------------- ;
diff --git a/frmts/mrf/libLERC/TImage.hpp b/frmts/mrf/libLERC/TImage.hpp
index 34caa9c..766fe22 100644
--- a/frmts/mrf/libLERC/TImage.hpp
+++ b/frmts/mrf/libLERC/TImage.hpp
@@ -127,7 +127,7 @@ bool TImage< Element >::resize(int width, int height)
   if (width <= 0 || height <= 0)
     return false;
 
-  if (width == width_ && height == height_)
+  if (width == width_ && height == height_ && data_)
     return true;
 
   free(data_);
@@ -140,7 +140,7 @@ bool TImage< Element >::resize(int width, int height)
 
   width_ = width;
   height_ = height;
-  
+
   return true;
 }
 
@@ -173,7 +173,7 @@ TImage< Element >& TImage< Element >::operator = (const TImage& tImg)
   memcpy(getData(), tImg.getData(), getSize() * sizeof(Element));
 
   Image::operator=(tImg);
-  
+
   return *this;
 }
 
diff --git a/frmts/mrf/makefile.vc b/frmts/mrf/makefile.vc
index 0df509f..048d815 100644
--- a/frmts/mrf/makefile.vc
+++ b/frmts/mrf/makefile.vc
@@ -41,12 +41,20 @@ EXTRA_LINK_FLAGS =  $(EXTRA_LINK_FLAGS) ../jpeg/libjpeg12/libjpeg12.lib
 
 !ENDIF
 
+!IFDEF ZLIB_EXTERNAL_LIB
+EXTRAFLAGS = $(ZLIB_INC) $(EXTRAFLAGS)
+EXTRA_LINK_FLAGS = $(EXTRA_LINK_FLAGS) $(ZLIB_LIB)
+!ELSE
+EXTRAFLAGS = -I../zlib $(EXTRAFLAGS)
+EXTRA_LINK_FLAGS = $(EXTRA_LINK_FLAGS) ../zlib/libz.lib
+!ENDIF
+
 !IFDEF PNG_EXTERNAL_LIB
-EXTRAFLAGS = 	-I../zlib -I$(PNGDIR) $(EXTRAFLAGS)
+EXTRAFLAGS = 	 -I$(PNGDIR) $(EXTRAFLAGS)
 !ELSE
-EXTRAFLAGS = 	/wd4611 -I../zlib -I../png/libpng -DINTERNAL_PNG $(EXTRAFLAGS)
+EXTRAFLAGS = 	/wd4611 -I../png/libpng -DINTERNAL_PNG $(EXTRAFLAGS)
 !ENDIF
-EXTRA_LINK_FLAGS =  $(EXTRA_LINK_FLAGS) ../png/libpng/libpng.lib ../zlib/libz.lib
+EXTRA_LINK_FLAGS =  $(EXTRA_LINK_FLAGS) ../png/libpng/libpng.lib
 
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\o
diff --git a/frmts/mrf/marfa.h b/frmts/mrf/marfa.h
index c194524..7073408 100644
--- a/frmts/mrf/marfa.h
+++ b/frmts/mrf/marfa.h
@@ -34,7 +34,7 @@
 */
 
 /******************************************************************************
- * $Id$
+ * $Id: marfa.h 37669 2017-03-09 23:35:51Z lplesea $
  *
  * Project:  Meta Raster Format
  * Purpose:  MRF structures
@@ -58,15 +58,9 @@
 #include <iostream>
 #include <sstream>
 
-#ifdef GDAL_COMPILATION
 #define NAMESPACE_MRF_START namespace GDAL_MRF {
 #define NAMESPACE_MRF_END   }
 #define USING_NAMESPACE_MRF using namespace GDAL_MRF;
-#else
-#define NAMESPACE_MRF_START
-#define NAMESPACE_MRF_END
-#define USING_NAMESPACE_MRF
-#endif
 
 NAMESPACE_MRF_START
 
@@ -91,10 +85,10 @@ NAMESPACE_MRF_START
 // Force LERC to be included, normally off, detected in the makefile
 // #define LERC
 
-// These are a pain to maintain in sync.  They should be replaced with 
+// These are a pain to maintain in sync.  They should be replaced with
 // C++11 uniform initializers.  The externs reside in util.cpp
 enum ILCompression {
-    IL_PNG = 0, IL_PPNG, IL_JPEG, IL_JPNG, IL_NONE, IL_ZLIB, IL_TIF, 
+    IL_PNG = 0, IL_PPNG, IL_JPEG, IL_JPNG, IL_NONE, IL_ZLIB, IL_TIF,
 #if defined(LERC)
     IL_LERC,
 #endif
@@ -235,7 +229,7 @@ CPLString getFname(CPLXMLNode *, const char *, const CPLString &, const char *);
 CPLString getFname(const CPLString &, const char *);
 double getXMLNum(CPLXMLNode *, const char *, double);
 GIntBig IdxOffset(const ILSize &, const ILImage &);
-double logb(double val, double base);
+double logbase(double val, double base);
 int IsPower(double value, double base);
 CPLXMLNode *SearchXMLSiblings(CPLXMLNode *psRoot, const char *pszElement);
 CPLString PrintDouble(double d, const char *frmt = "%12.8f");
@@ -292,8 +286,6 @@ enum { SAMPLING_ERR, SAMPLING_Avg, SAMPLING_Near };
 GDALMRFRasterBand *newMRFRasterBand(GDALMRFDataset *, const ILImage &, int, int level = 0);
 
 class GDALMRFDataset : public GDALPamDataset {
-
-
     friend class GDALMRFRasterBand;
     friend GDALMRFRasterBand *newMRFRasterBand(GDALMRFDataset *, const ILImage &, int, int level);
 
@@ -318,8 +310,8 @@ public:
         return CE_None;
     }
 
-    virtual const char *GetProjectionRef() { return projection; }
-    virtual CPLErr SetProjection(const char *proj) {
+    virtual const char *GetProjectionRef() override { return projection; }
+    virtual CPLErr SetProjection(const char *proj) override {
         projection = proj;
         return CE_None;
     }
@@ -330,18 +322,10 @@ public:
         return CE_None;
     }
 
-    virtual CPLErr GetGeoTransform(double *gt);
-    virtual CPLErr SetGeoTransform(double *gt);
+    virtual CPLErr GetGeoTransform(double *gt) override;
+    virtual CPLErr SetGeoTransform(double *gt) override;
 
-#ifdef unused
-    virtual CPLErr AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
-        int nBufXSize, int nBufYSize,
-        GDALDataType eDT,
-        int nBandCount, int *panBandList,
-        char **papszOptions);
-#endif
-
-    virtual char **GetFileList();
+    virtual char **GetFileList() override;
 
     void SetColorTable(GDALColorTable *pct) { poColorTable = pct; };
     const GDALColorTable *GetColorTable() { return poColorTable; };
@@ -381,7 +365,9 @@ protected:
     CPLErr Initialize(CPLXMLNode *);
 
     // Do nothing, this is not possible in an MRF
-    CPLErr CleanOverviews(void) { return CE_None; }
+    CPLErr CleanOverviews() { return CE_None; }
+
+    bool IsSingleTile();
 
     // Add uniform scale overlays, returns the new size of the index file
     GIntBig AddOverviews(int scale);
@@ -397,7 +383,7 @@ protected:
 #if GDAL_VERSION_MAJOR >= 2
     virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int,
         void *, int, int, GDALDataType,
-        int, int *, GSpacing, GSpacing, GSpacing, GDALRasterIOExtraArg*);
+        int, int *, GSpacing, GSpacing, GSpacing, GDALRasterIOExtraArg*) override;
 #else
     virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int,
         void *, int, int, GDALDataType,
@@ -405,8 +391,9 @@ protected:
 #endif
 
     virtual CPLErr IBuildOverviews(const char*, int, int*, int, int*,
-        GDALProgressFunc, void*);
+        GDALProgressFunc, void*) override;
 
+    virtual int CloseDependentDatasets() override;
 
     // Write a tile, the infooffset is the relative position in the index file
     virtual CPLErr WriteTile(void *buff, GUIntBig infooffset, GUIntBig size = 0);
@@ -457,6 +444,7 @@ protected:
     int hasVersions;  // Does it support versions
     int verCount;     // The last version
     int bCrystalized; // Unset only during the create process
+    int spacing;      // How many spare bytes before each tile data
 
     // Freeform sticky dataset options, as a list of key-value pairs
     CPLStringList optlist;
@@ -503,22 +491,21 @@ class GDALMRFRasterBand : public GDALPamRasterBand {
 public:
     GDALMRFRasterBand(GDALMRFDataset *, const ILImage &, int, int);
     virtual ~GDALMRFRasterBand();
-    virtual CPLErr IReadBlock(int xblk, int yblk, void *buffer);
-    virtual CPLErr IWriteBlock(int xblk, int yblk, void *buffer);
+    virtual CPLErr IReadBlock(int xblk, int yblk, void *buffer) override;
+    virtual CPLErr IWriteBlock(int xblk, int yblk, void *buffer) override;
 
-    virtual GDALColorTable *GetColorTable() { return poDS->poColorTable; }
+    virtual GDALColorTable *GetColorTable() override { return poDS->poColorTable; }
 
-    CPLErr SetColorInterpretation(GDALColorInterp ci) { img.ci = ci; return CE_None; }
-    virtual GDALColorInterp GetColorInterpretation() { return img.ci; }
+    CPLErr SetColorInterpretation(GDALColorInterp ci) override { img.ci = ci; return CE_None; }
+    virtual GDALColorInterp GetColorInterpretation() override { return img.ci; }
 
     // Get works within MRF or with PAM
-    virtual double  GetNoDataValue(int *);
-    virtual CPLErr  SetNoDataValue(double);
-
-    // These get set with SetStatistics.  Let PAM handle it
-    virtual double  GetMinimum(int *);
-    virtual double  GetMaximum(int *);
+    virtual double  GetNoDataValue(int *) override;
+    virtual CPLErr  SetNoDataValue(double) override;
 
+    // These get set with SetStatistics
+    virtual double  GetMinimum(int *) override;
+    virtual double  GetMaximum(int *) override;
 
     // MRF specific, fetch is from a remote source
     CPLErr FetchBlock(int xblk, int yblk, void *buffer = NULL);
@@ -538,8 +525,7 @@ public:
 protected:
     // Pointer to the GDALMRFDataset
     GDALMRFDataset *poDS;
-    // 0 based
-    GInt32 m_band;
+    // Deflate page requested, named to avoid conflict with libz deflate()
     int deflatep;
     int deflate_flags;
     // Level count of this band
@@ -570,14 +556,14 @@ protected:
     //    virtual CPLErr ReadTileIdx(const ILSize &, ILIdx &, GIntBig bias = 0);
 
     GIntBig bandbit(int b) { return ((GIntBig)1) << b; }
-    GIntBig bandbit() { return bandbit(m_band); }
+    GIntBig bandbit() { return bandbit(nBand - 1); }
     GIntBig AllBandMask() { return bandbit(poDS->nBands) - 1; }
 
     // Overview Support
     // Inherited from GDALRasterBand
     // These are called only in the base level RasterBand
-    virtual int GetOverviewCount();
-    virtual GDALRasterBand *GetOverview(int n);
+    virtual int GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview(int n) override;
     void AddOverview(GDALMRFRasterBand *b) { overviews.push_back(b); }
 };
 
@@ -591,7 +577,7 @@ protected:
 
 class PNG_Codec {
 public:
-    PNG_Codec(const ILImage &image) : img(image), 
+    explicit PNG_Codec(const ILImage &image) : img(image),
         PNGColors(NULL), PNGAlpha(NULL), PalSize(0), TransSize(0), deflate_flags(0) {};
 
     virtual ~PNG_Codec() {
@@ -600,7 +586,7 @@ public:
     }
 
     CPLErr CompressPNG(buf_mgr &dst, buf_mgr &src);
-    CPLErr DecompressPNG(buf_mgr &dst, buf_mgr &src);
+    static CPLErr DecompressPNG(buf_mgr &dst, buf_mgr &src);
 
     const ILImage img;
 
@@ -610,7 +596,6 @@ public:
 
 private:
     PNG_Codec& operator= (const PNG_Codec& src); // not implemented. but suppress MSVC warning about 'assignment operator could not be generated'
-
 };
 
 class PNG_Band : public GDALMRFRasterBand {
@@ -619,19 +604,19 @@ public:
     PNG_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level);
 
 protected:
-    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
-    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src) override;
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src) override;
 
     PNG_Codec codec;
 };
 
-/* 
+/*
  * The JPEG Codec can be used outside of the JPEG_Band
 */
 
 class JPEG_Codec {
 public:
-    JPEG_Codec(const ILImage &image) : img(image), sameres(FALSE), rgb(FALSE), optimize(false) {};
+    explicit JPEG_Codec(const ILImage &image) : img(image), sameres(FALSE), rgb(FALSE), optimize(false) {};
 
     CPLErr CompressJPEG(buf_mgr &dst, buf_mgr &src);
     CPLErr DecompressJPEG(buf_mgr &dst, buf_mgr &src);
@@ -660,8 +645,8 @@ public:
     virtual ~JPEG_Band() {};
 
 protected:
-    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
-    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src) override;
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src) override;
 
     JPEG_Codec codec;
 };
@@ -673,8 +658,8 @@ public:
     JPNG_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level);
     virtual ~JPNG_Band();
 protected:
-    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
-    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src) override;
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src) override;
 
     CPLErr CompressJPNG(buf_mgr &dst, buf_mgr &src);
     CPLErr DecompressJPNG(buf_mgr &dst, buf_mgr &src);
@@ -688,8 +673,8 @@ public:
         GDALMRFRasterBand(pDS, image, b, int(level)) {};
     virtual ~Raw_Band() {};
 protected:
-    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
-    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src) override;
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src) override;
 };
 
 class TIF_Band : public GDALMRFRasterBand {
@@ -698,8 +683,8 @@ public:
     TIF_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level);
     virtual ~TIF_Band();
 protected:
-    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
-    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src) override;
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src) override;
 
     // Create options for TIF pages
     char **papszOptions;
@@ -712,10 +697,16 @@ public:
     LERC_Band(GDALMRFDataset *pDS, const ILImage &image, int b, int level);
     virtual ~LERC_Band();
 protected:
-    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src);
-    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src);
+    virtual CPLErr Decompress(buf_mgr &dst, buf_mgr &src) override;
+    virtual CPLErr Compress(buf_mgr &dst, buf_mgr &src) override;
     double precision;
     int version;
+    static bool IsLerc(CPLString &s) {
+        return (STARTS_WITH(s, "Lerc2 ") || STARTS_WITH(s, "CntZImage "));
+    }
+
+    // Build a MRF header for a single LERC tile
+    static CPLXMLNode *GetMRFConfig(GDALOpenInfo *poOpenInfo);
 };
 #endif
 
@@ -726,7 +717,7 @@ protected:
  */
 class GDALMRFLRasterBand : public GDALPamRasterBand {
 public:
-    GDALMRFLRasterBand(GDALMRFRasterBand *b) {
+    explicit GDALMRFLRasterBand(GDALMRFRasterBand *b) {
         pBand = b;
         eDataType = b->GetRasterDataType();
         b->GetBlockSize(&nBlockXSize, &nBlockYSize);
@@ -734,31 +725,31 @@ public:
         nRasterXSize = b->GetXSize();
         nRasterYSize = b->GetYSize();
     }
-    virtual CPLErr IReadBlock(int xblk, int yblk, void *buffer) {
+    virtual CPLErr IReadBlock(int xblk, int yblk, void *buffer) override {
         return pBand->IReadBlock(xblk, yblk, buffer);
     }
-    virtual CPLErr IWriteBlock(int xblk, int yblk, void *buffer) {
+    virtual CPLErr IWriteBlock(int xblk, int yblk, void *buffer) override {
         return pBand->IWriteBlock(xblk, yblk, buffer);
     }
-    virtual GDALColorTable *GetColorTable() {
+    virtual GDALColorTable *GetColorTable() override {
         return pBand->GetColorTable();
     }
-    virtual GDALColorInterp GetColorInterpretation() {
+    virtual GDALColorInterp GetColorInterpretation() override {
         return pBand->GetColorInterpretation();
     }
-    virtual double  GetNoDataValue(int * pbSuccess) {
+    virtual double  GetNoDataValue(int * pbSuccess) override {
         return pBand->GetNoDataValue(pbSuccess);
     }
-    virtual double  GetMinimum(int *b) {
+    virtual double  GetMinimum(int *b) override {
         return pBand->GetMinimum(b);
     }
-    virtual double  GetMaximum(int *b) {
+    virtual double  GetMaximum(int *b) override {
         return pBand->GetMaximum(b);
     }
 
 protected:
-    virtual int GetOverviewCount() { return 0; }
-    virtual GDALRasterBand *GetOverview(int ) { return NULL; }
+    virtual int GetOverviewCount() override { return 0; }
+    virtual GDALRasterBand *GetOverview(int ) override { return NULL; }
 
     GDALMRFRasterBand *pBand;
 };
@@ -766,4 +757,3 @@ protected:
 NAMESPACE_MRF_END
 
 #endif // GDAL_FRMTS_MRF_MARFA_H_INCLUDED
-
diff --git a/frmts/mrf/marfa_dataset.cpp b/frmts/mrf/marfa_dataset.cpp
index 15b52cb..99973f4 100644
--- a/frmts/mrf/marfa_dataset.cpp
+++ b/frmts/mrf/marfa_dataset.cpp
@@ -18,7 +18,7 @@
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
-* Copyright 2014-2015 Esri
+* Portions copyright 2014-2017 Esri
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -42,7 +42,7 @@
 *
 ******************************************************************************
 *
-*   Since the MRF dataset and the band are so closely tied together, they should be
+*   The MRF dataset and the band are closely tied together, they should be
 *   considered a single class, or a class (dataset) with extensions (bands).
 *
 *
@@ -53,41 +53,51 @@
 #include <gdal_priv.h>
 #include <assert.h>
 
+#include <algorithm>
 #include <vector>
 
+CPL_CVSID("$Id: marfa_dataset.cpp 37669 2017-03-09 23:35:51Z lplesea $");
+
 using std::vector;
 using std::string;
 
 NAMESPACE_MRF_START
 
+#if GDAL_VERSION_MAJOR >= 2
+#define BOOLTEST CPLTestBool
+#else
+#define BOOLTEST CSLTestBoolean
+#endif
+
 // Initialize as invalid
-GDALMRFDataset::GDALMRFDataset()
-{   //		     X0   Xx   Xy  Y0    Yx   Yy
+GDALMRFDataset::GDALMRFDataset() :
+    zslice(0),
+    idxSize(0),
+    clonedSource(FALSE),
+    bypass_cache(
+        BOOLTEST(CPLGetConfigOption("MRF_BYPASSCACHING", "FALSE"))),
+    mp_safe(FALSE),
+    hasVersions(FALSE),
+    verCount(0),
+    bCrystalized(TRUE), // Assume not in create mode
+    spacing(0),
+    poSrcDS(NULL),
+    level(-1),
+    cds(NULL),
+    scale(0.0),
+    pbuffer(NULL),
+    pbsize(0),
+    tile(ILSize()),
+    bdirty(0),
+    bGeoTransformValid(TRUE),
+    poColorTable(NULL),
+    Quality(0)
+{
+    //                X0   Xx   Xy  Y0    Yx   Yy
     double gt[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
 
-    ILImage img;
-
     memcpy(GeoTransform, gt, sizeof(gt));
-    bGeoTransformValid = TRUE;
     ifp.FP = dfp.FP = NULL;
-    pbuffer = NULL;
-    pbsize = 0;
-    bdirty = 0;
-    scale = 0;
-    zslice = 0;
-    hasVersions = FALSE;
-    clonedSource = FALSE;
-    mp_safe = FALSE;
-    level = -1;
-    tile = ILSize();
-    cds = NULL;
-    poSrcDS = NULL;
-    poColorTable = NULL;
-    bCrystalized = FALSE; // Assume not in create mode
-    bypass_cache = CSLTestBoolean(CPLGetConfigOption("MRF_BYPASSCACHING", "FALSE"));
-    idxSize = 0;
-    verCount = 0;
-    Quality = 0;
     dfp.acc = GF_Read;
     ifp.acc = GF_Read;
 }
@@ -95,8 +105,8 @@ GDALMRFDataset::GDALMRFDataset()
 bool GDALMRFDataset::SetPBuffer(unsigned int sz)
 {
     if (sz == 0) {
-	CPLFree(pbuffer);
-	pbuffer = NULL;
+        CPLFree(pbuffer);
+        pbuffer = NULL;
     }
     void* pbufferNew = VSIRealloc(pbuffer, sz);
     if( pbufferNew == NULL )
@@ -110,16 +120,42 @@ bool GDALMRFDataset::SetPBuffer(unsigned int sz)
     return true;
 }
 
+//
+// Called by dataset destructor or at GDAL termination, to avoid
+// closing datasets whose drivers have already been unloaded
+//
+int GDALMRFDataset::CloseDependentDatasets()
+{
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
+    if (poSrcDS)
+    {
+        bHasDroppedRef = TRUE;
+        GDALClose(reinterpret_cast<GDALDatasetH>(poSrcDS));
+        poSrcDS = NULL;
+    }
+
+    if (cds) {
+        bHasDroppedRef = TRUE;
+        GDALClose(reinterpret_cast<GDALDatasetH>(cds));
+        cds = NULL;
+    }
+
+    return bHasDroppedRef;
+}
+
 GDALMRFDataset::~GDALMRFDataset()
 
 {   // Make sure everything gets written
     FlushCache();
+
+    CloseDependentDatasets();
+
     if (ifp.FP)
-	VSIFCloseL(ifp.FP);
+        VSIFCloseL(ifp.FP);
     if (dfp.FP)
-	VSIFCloseL(dfp.FP);
-    delete cds;
-    delete poSrcDS;
+        VSIFCloseL(dfp.FP);
+
     delete poColorTable;
 
     // CPLFree ignores being called with NULL
@@ -141,7 +177,7 @@ CPLErr GDALMRFDataset::AdviseRead(int nXOff, int nYOff, int nXSize, int nYSize,
     char **papszOptions)
 {
     CPLDebug("MRF_IO", "AdviseRead %d, %d, %d, %d, bufsz %d,%d,%d\n",
-	nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, nBandCount);
+        nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, nBandCount);
     return CE_None;
 }
 #endif
@@ -164,27 +200,22 @@ CPLErr GDALMRFDataset::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff, int n
     )
 {
     CPLDebug("MRF_IO", "IRasterIO %s, %d, %d, %d, %d, bufsz %d,%d,%d strides P %d, L %d, B %d \n",
-	eRWFlag == GF_Write ? "Write" : "Read",
-	nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, nBandCount,
-	static_cast<int>(nPixelSpace), static_cast<int>(nLineSpace),
+        eRWFlag == GF_Write ? "Write" : "Read",
+        nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, nBandCount,
+        static_cast<int>(nPixelSpace), static_cast<int>(nLineSpace),
         static_cast<int>(nBandSpace));
 
-    // Finish the Create call
-    if (!bCrystalized)
-	Crystalize();
-
     //
     // Call the parent implementation, which splits it into bands and calls their IRasterIO
-    // 
+    //
     return GDALPamDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
-	eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace
+        eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace
 #if GDAL_VERSION_MAJOR >= 2
         ,psExtraArgs
 #endif
-	);
+        );
 }
 
-
 /**
 *\brief Build some overviews
 *
@@ -214,11 +245,11 @@ CPLErr GDALMRFDataset::IBuildOverviews(
     /* -------------------------------------------------------------------- */
     if (GetAccess() != GA_Update)
     {
-	CPLDebug("MRF", "File open read-only, creating overviews externally.");
+        CPLDebug("MRF", "File open read-only, creating overviews externally.");
 
-	return GDALDataset::IBuildOverviews(
-	    pszResampling, nOverviews, panOverviewList,
-	    nBands, panBandList, pfnProgress, pProgressData);
+        return GDALDataset::IBuildOverviews(
+            pszResampling, nOverviews, panOverviewList,
+            nBands, panBandList, pfnProgress, pProgressData);
     }
 
     /* -------------------------------------------------------------------- */
@@ -230,74 +261,75 @@ CPLErr GDALMRFDataset::IBuildOverviews(
 
     if (nOverviews == 0)
     {
-	if (current.size.l == 0)
-	    return GDALDataset::IBuildOverviews(pszResampling, 
-		nOverviews, panOverviewList,
-		nBands, panBandList, pfnProgress, pProgressData);
-	else
-	    return CleanOverviews();
+        if (current.size.l == 0)
+            return GDALDataset::IBuildOverviews(pszResampling,
+                nOverviews, panOverviewList,
+                nBands, panBandList, pfnProgress, pProgressData);
+        else
+            return CleanOverviews();
     }
 
     // Array of source bands
     GDALRasterBand **papoBandList =
-	(GDALRasterBand **)CPLCalloc(sizeof(void*), nBands);
+        (GDALRasterBand **)CPLCalloc(sizeof(void*), nBands);
     // Array of destination bands
     GDALRasterBand **papoOverviewBandList =
-	(GDALRasterBand **)CPLCalloc(sizeof(void*), nBands);
+        (GDALRasterBand **)CPLCalloc(sizeof(void*), nBands);
     // Triple level pointer, that's what GDAL ROMB wants
     GDALRasterBand ***papapoOverviewBands =
-	(GDALRasterBand ***)CPLCalloc(sizeof(void*), nBands);
+        (GDALRasterBand ***)CPLCalloc(sizeof(void*), nBands);
 
     int* panOverviewListNew = (int*)CPLMalloc( sizeof(int) * nOverviews );
     memcpy( panOverviewListNew, panOverviewList, sizeof(int) * nOverviews );
 
     try {  // Throw an error code, to make sure memory gets freed properly
-	// Modify the metadata file if it doesn't already have the Rset model set
-	if (0.0 == scale) {
-	    CPLXMLNode *config = ReadConfig();
-	    try {
-		const char* model = CPLGetXMLValue(config, "Rsets.model", "uniform");
-		if (!EQUAL(model, "uniform")) {
-		    CPLError(CE_Failure, CPLE_AppDefined,
-			"MRF:IBuildOverviews, Overviews not implemented for model %s", model);
-		    throw CE_Failure;
-		}
-
-		// The scale value is the same as first overview
-		scale = strtod(CPLGetXMLValue(config, "Rsets.scale",
-		    CPLString().Printf("%d", panOverviewList[0]).c_str()), NULL);
-
-		// Initialize the empty overlays, all of them for a given scale
-		// They could already exist, in which case they are not erased
-		idxSize = AddOverviews(int(scale));
-		if (!CheckFileSize(current.idxfname, idxSize, GA_Update)) {
-		    CPLError(CE_Failure, CPLE_AppDefined, "MRF: Can't extend index file");
-		    throw CE_Failure;
-		}
-
-		//  Set the uniform node, in case it was not set before, and save the new configuration
-		CPLSetXMLValue(config, "Rsets.#model", "uniform");
-		CPLSetXMLValue(config, "Rsets.#scale", CPLString().Printf("%g", scale).c_str());
-
-		if (!WriteConfig(config)) {
-		    CPLError(CE_Failure, CPLE_AppDefined, "MRF: Can't rewrite the metadata file");
-		    throw CE_Failure;
-		}
-		CPLDestroyXMLNode(config);
-		config = NULL;
-	    }
-	    catch (CPLErr e) {
-		if (config)
-		    CPLDestroyXMLNode(config);
-		throw e; // Rethrow
-	    }
+        // Modify the metadata file if it doesn't already have the Rset model set
+        if (0.0 == scale) {
+            CPLXMLNode *config = ReadConfig();
+            try {
+                const char* model = CPLGetXMLValue(config, "Rsets.model", "uniform");
+                if (!EQUAL(model, "uniform")) {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                        "MRF:IBuildOverviews, Overviews not implemented for model %s", model);
+                    throw CE_Failure;
+                }
+
+                // The scale value is the same as first overview
+                scale = strtod(CPLGetXMLValue(config, "Rsets.scale",
+                    CPLString().Printf("%d", panOverviewList[0]).c_str()), NULL);
+
+                // Initialize the empty overlays, all of them for a given scale
+                // They could already exist, in which case they are not erased
+                idxSize = AddOverviews(int(scale));
+                if (!CheckFileSize(current.idxfname, idxSize, GA_Update)) {
+                    CPLError(CE_Failure, CPLE_AppDefined, "MRF: Can't extend index file");
+                    throw CE_Failure;
+                }
+
+                //  Set the uniform node, in case it was not set before, and save the new configuration
+                CPLSetXMLValue(config, "Rsets.#model", "uniform");
+                CPLSetXMLValue(config, "Rsets.#scale", CPLString().Printf("%g", scale).c_str());
+
+                if (!WriteConfig(config)) {
+                    CPLError(CE_Failure, CPLE_AppDefined, "MRF: Can't rewrite the metadata file");
+                    throw CE_Failure;
+                }
+                CPLDestroyXMLNode(config);
+                config = NULL;
+            }
+            catch (const CPLErr& ) {
+                if (config)
+                    CPLDestroyXMLNode(config);
+                throw; // Rethrow
+            }
 
             // To avoid issues with blacks overviews, if the user asked to
             // generate overviews 2, 4, ..., we finish the sequence until the
             // last level that will be otherwised initialized to black
-	    if( !EQUAL(pszResampling, "NONE") &&
+            if( !EQUAL(pszResampling, "NONE") &&
                 nOverviews != GetRasterBand(1)->GetOverviewCount() &&
-                CSLTestBoolean(CPLGetConfigOption("MRF_ALL_OVERVIEW_LEVELS", "YES")) )
+                BOOLTEST(CPLGetConfigOption("MRF_ALL_OVERVIEW_LEVELS",
+                                               "YES")) )
             {
                 bool bIncreasingPowers = true;
                 for (int i = 1; i < nOverviews; i++) {
@@ -317,81 +349,81 @@ CPLErr GDALMRFDataset::IBuildOverviews(
                     }
                 }
             }
-	}
-
-	for (int i = 0; i < nOverviews; i++) {
-
-	    // Verify that scales are reasonable, val/scale has to be an integer
-	    if (!IsPower(panOverviewListNew[i], scale)) {
-		CPLError(CE_Warning, CPLE_AppDefined,
-		    "MRF:IBuildOverviews, overview factor %d is not a power of %f",
-		    panOverviewListNew[i], scale);
-		continue;
-	    };
-
-	    int srclevel = int(-0.5 + logb(panOverviewListNew[i], scale));
-	    GDALMRFRasterBand *b = static_cast<GDALMRFRasterBand *>(GetRasterBand(1));
-
-	    // Warn for requests for invalid levels
-	    if (srclevel >= b->GetOverviewCount()) {
-		CPLError(CE_Warning, CPLE_AppDefined,
-		    "MRF:IBuildOverviews, overview factor %d is not valid for this dataset",
-		    panOverviewListNew[i]);
-		continue;
-	    }
-
-	    // Generate the overview using the previous level as the source
-
-	    // Use "avg" flag to trigger the internal average sampling
-	    if (EQUALN("Avg", pszResampling, 3) || EQUALN("NearNb", pszResampling, 4)) {
-
-		int sampling = EQUALN("Avg", pszResampling, 3) ? SAMPLING_Avg : SAMPLING_Near;
-		// Internal, using PatchOverview
-		if (srclevel > 0)
-		    b = static_cast<GDALMRFRasterBand *>(b->GetOverview(srclevel - 1));
-
-		eErr = PatchOverview(0, 0, b->nBlocksPerRow, b->nBlocksPerColumn, srclevel, 
-		    0, sampling);
-		if (eErr == CE_Failure)
-		    throw eErr;
-
-	    }
-	    else {
-		//
-		// Use the GDAL method, which is slightly different for bilinear interpolation
-		// and also handles nearest mode
-		//
-		//
-		for (int iBand = 0; iBand < nBands; iBand++) {
-		    // This is the base level
-		    papoBandList[iBand] = GetRasterBand(panBandList[iBand]);
-		    // Set up the destination
-		    papoOverviewBandList[iBand] =
-			papoBandList[iBand]->GetOverview(srclevel);
-
-		    // Use the previous level as the source, the overviews are 0 based
-		    // thus an extra -1
-		    if (srclevel > 0)
-			papoBandList[iBand] = papoBandList[iBand]->GetOverview(srclevel - 1);
-
-		    // Hook it up, via triple pointer level
-		    papapoOverviewBands[iBand] = &(papoOverviewBandList[iBand]);
-		}
-
-		//
-		// Ready, generate this overview
-		// Note that this function has a bug in GDAL, the block stepping is incorect
-		// It can generate multiple overview in one call, 
-		// Could rewrite this loop so this function only gets called once
-		//
-		GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
-		    1, papapoOverviewBands,
-		    pszResampling, pfnProgress, pProgressData);
-	    }
-	}
-    }
-    catch (CPLErr e) {
-	eErr = e;
+        }
+
+        for (int i = 0; i < nOverviews; i++) {
+
+            // Verify that scales are reasonable, val/scale has to be an integer
+            if (!IsPower(panOverviewListNew[i], scale)) {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                    "MRF:IBuildOverviews, overview factor %d is not a power of %f",
+                    panOverviewListNew[i], scale);
+                continue;
+            };
+
+            int srclevel = int(logbase(panOverviewListNew[i], scale) - 0.5);
+            GDALMRFRasterBand *b = static_cast<GDALMRFRasterBand *>(GetRasterBand(1));
+
+            // Warn for requests for invalid levels
+            if (srclevel >= b->GetOverviewCount()) {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                    "MRF:IBuildOverviews, overview factor %d is not valid for this dataset",
+                    panOverviewListNew[i]);
+                continue;
+            }
+
+            // Generate the overview using the previous level as the source
+
+            // Use "avg" flag to trigger the internal average sampling
+            if (EQUALN("Avg", pszResampling, 3) || EQUALN("NearNb", pszResampling, 4)) {
+
+                int sampling = EQUALN("Avg", pszResampling, 3) ? SAMPLING_Avg : SAMPLING_Near;
+                // Internal, using PatchOverview
+                if (srclevel > 0)
+                    b = static_cast<GDALMRFRasterBand *>(b->GetOverview(srclevel - 1));
+
+                eErr = PatchOverview(0, 0, b->nBlocksPerRow, b->nBlocksPerColumn, srclevel,
+                    0, sampling);
+                if (eErr == CE_Failure)
+                    throw eErr;
+            }
+            else
+            {
+                //
+                // Use the GDAL method, which is slightly different for bilinear interpolation
+                // and also handles nearest mode
+                //
+                //
+                for (int iBand = 0; iBand < nBands; iBand++) {
+                    // This is the base level
+                    papoBandList[iBand] = GetRasterBand(panBandList[iBand]);
+                    // Set up the destination
+                    papoOverviewBandList[iBand] =
+                        papoBandList[iBand]->GetOverview(srclevel);
+
+                    // Use the previous level as the source, the overviews are 0 based
+                    // thus an extra -1
+                    if (srclevel > 0)
+                        papoBandList[iBand] = papoBandList[iBand]->GetOverview(srclevel - 1);
+
+                    // Hook it up, via triple pointer level
+                    papapoOverviewBands[iBand] = &(papoOverviewBandList[iBand]);
+                }
+
+                //
+                // Ready, generate this overview
+                // Note that this function has a bug in GDAL, the block stepping is incorect
+                // It can generate multiple overview in one call,
+                // Could rewrite this loop so this function only gets called once
+                //
+                GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
+                    1, papapoOverviewBands,
+                    pszResampling, pfnProgress, pProgressData);
+            }
+        }
+    }
+    catch (const CPLErr& e) {
+        eErr = e;
     }
 
     CPLFree(panOverviewListNew);
@@ -408,10 +440,10 @@ CPLErr GDALMRFDataset::IBuildOverviews(
 static void list2vec(std::vector<double> &v, const char *pszList) {
     if ((pszList == NULL) || (pszList[0] == 0)) return;
     char **papszTokens = CSLTokenizeString2(pszList, " \t\n\r",
-	CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
+        CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
     v.clear();
     for (int i = 0; i < CSLCount(papszTokens); i++)
-	v.push_back(CPLStrtod(papszTokens[i], NULL));
+        v.push_back(CPLStrtod(papszTokens[i], NULL));
     CSLDestroy(papszTokens);
 }
 
@@ -438,31 +470,42 @@ int GDALMRFDataset::Identify(GDALOpenInfo *poOpenInfo)
 {
     CPLString fn(poOpenInfo->pszFilename);
     if (fn.find(":MRF:") != string::npos)
-	return TRUE;
-    if (poOpenInfo->nHeaderBytes >= 10)
-	fn = (char *)poOpenInfo->pabyHeader;
-    return EQUALN(fn.c_str(), "<MRF_META>", 10);
+        return TRUE;
+
+    if (poOpenInfo->nHeaderBytes < 10)
+        return FALSE;
+
+    const char *pszHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
+    fn.assign(pszHeader, pszHeader + poOpenInfo->nHeaderBytes);
+    if (STARTS_WITH(fn, "<MRF_META>"))
+        return TRUE;
+
+#if defined(LERC) // Could be single LERC tile
+    if (LERC_Band::IsLerc(fn))
+        return TRUE;
+#endif
+
+    return FALSE;
 }
 
 /**
 *
-*\Brief Read the XML config tree, from file
+*\brief Read the XML config tree, from file
 *  Caller is responsible for freeing the memory
 *
-* @param pszFilename the file to open.
 * @return NULL on failure, or the document tree on success.
 *
 */
 CPLXMLNode *GDALMRFDataset::ReadConfig() const
 {
     if (fname[0] == '<')
-	return CPLParseXMLString(fname);
+        return CPLParseXMLString(fname);
     else
-	return CPLParseXMLFile(fname);
+        return CPLParseXMLFile(fname);
 }
 
 /**
-*\Brief Write the XML config tree
+*\brief Write the XML config tree
 * Caller is responsible for correctness of data
 * and for freeing the memory
 *
@@ -483,8 +526,8 @@ const  char theDelimiter = ' ')
 {
     size_t end = theString.find(theDelimiter, start);
     if (string::npos == end) {
-	theStringVector.push_back(theString.substr(start));
-	return;
+        theStringVector.push_back(theString.substr(start));
+        return;
     }
     theStringVector.push_back(theString.substr(start, end - start));
     stringSplit(theStringVector, theString, end + 1, theDelimiter);
@@ -494,18 +537,21 @@ const  char theDelimiter = ' ')
 // Otherwise it returns the default
 static int getnum(const vector<string> &theStringVector, const char prefix, int def) {
     for (unsigned int i = 0; i < theStringVector.size(); i++)
-	if (theStringVector[i][0] == prefix)
-	    return atoi(theStringVector[i].c_str() + 1);
+        if (theStringVector[i][0] == prefix)
+            return atoi(theStringVector[i].c_str() + 1);
     return def;
 }
 
 /**
-*\Brief Open a MRF file
+*\brief Open a MRF file
 *
 */
 GDALDataset *GDALMRFDataset::Open(GDALOpenInfo *poOpenInfo)
 
 {
+    if( !Identify(poOpenInfo) )
+        return NULL;
+
     CPLXMLNode *config = NULL;
     CPLErr ret = CE_None;
     const char* pszFileName = poOpenInfo->pszFilename;
@@ -515,32 +561,40 @@ GDALDataset *GDALMRFDataset::Open(GDALOpenInfo *poOpenInfo)
     int zslice = 0;
     string fn; // Used to parse and adjust the file name
 
-    // Different ways to open it
-    if (poOpenInfo->nHeaderBytes >= 10 &&
-	EQUALN((const char *)poOpenInfo->pabyHeader, "<MRF_META>", 10)) // Regular file name
-	config = CPLParseXMLFile(pszFileName);
+    // Different ways to open an MRF
+    if (poOpenInfo->nHeaderBytes >= 10) {
+
+        const char *pszHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
+        if (STARTS_WITH(pszHeader, "<MRF_META>")) // Regular file name
+            config = CPLParseXMLFile(pszFileName);
+#if defined(LERC)
+        else
+            config = LERC_Band::GetMRFConfig(poOpenInfo);
+#endif
+
+    }
     else {
-	if (EQUALN(pszFileName, "<MRF_META>", 10)) // Content as file name
-	    config = CPLParseXMLString(pszFileName);
-	else
-	{ // Try Ornate file name
-	    fn = pszFileName;
-	    size_t pos = fn.find(":MRF:");
-	    if (string::npos != pos) { // Tokenize and pick known options
-		vector<string> tokens;
-		stringSplit(tokens, fn, pos + 5, ':');
-		level = getnum(tokens, 'L', -1);
-		version = getnum(tokens, 'V', 0);
-		zslice = getnum(tokens, 'Z', 0);
-		fn.resize(pos); // Cut the ornamentations
-		pszFileName = fn.c_str();
-		config = CPLParseXMLFile(pszFileName);
-	    }
-	}
+        if (EQUALN(pszFileName, "<MRF_META>", 10)) // Content as file name
+            config = CPLParseXMLString(pszFileName);
+        else
+        { // Try Ornate file name
+            fn = pszFileName;
+            size_t pos = fn.find(":MRF:");
+            if (string::npos != pos) { // Tokenize and pick known options
+                vector<string> tokens;
+                stringSplit(tokens, fn, pos + 5, ':');
+                level = getnum(tokens, 'L', -1);
+                version = getnum(tokens, 'V', 0);
+                zslice = getnum(tokens, 'Z', 0);
+                fn.resize(pos); // Cut the ornamentations
+                pszFileName = fn.c_str();
+                config = CPLParseXMLFile(pszFileName);
+            }
+        }
     }
 
     if (!config)
-	return NULL;
+        return NULL;
 
     GDALMRFDataset *ds = new GDALMRFDataset();
     ds->fname = pszFileName;
@@ -549,33 +603,33 @@ GDALDataset *GDALMRFDataset::Open(GDALOpenInfo *poOpenInfo)
     ds->zslice = zslice;
 
     if (level != -1) {
-	// Open the whole dataset, then pick one level
-	ds->cds = new GDALMRFDataset();
-	ds->cds->fname = pszFileName;
-	ds->cds->eAccess = ds->eAccess;
-	ret = ds->cds->Initialize(config);
-	if (ret == CE_None)
-	    ret = ds->LevelInit(level);
+        // Open the whole dataset, then pick one level
+        ds->cds = new GDALMRFDataset();
+        ds->cds->fname = pszFileName;
+        ds->cds->eAccess = ds->eAccess;
+        ret = ds->cds->Initialize(config);
+        if (ret == CE_None)
+            ret = ds->LevelInit(level);
     }
     else
     {
-	ret = ds->Initialize(config);
+        ret = ds->Initialize(config);
     }
 
     CPLDestroyXMLNode(config);
 
     if (ret != CE_None) {
-	delete ds;
-	return NULL;
+        delete ds;
+        return NULL;
     }
 
     // Open a single version
     if (version != 0)
-	ret = ds->SetVersion(version);
+        ret = ds->SetVersion(version);
 
     if (ret != CE_None) {
-	delete ds;
-	return NULL;
+        delete ds;
+        return NULL;
     }
 
     // Tell PAM what our real file name is, to help it find the aux.xml
@@ -588,25 +642,24 @@ GDALDataset *GDALMRFDataset::Open(GDALOpenInfo *poOpenInfo)
 /* -------------------------------------------------------------------- */
     ds->oOvManager.Initialize( ds, pszFileName );
 
-
     return ds;
 }
 
 // Adjust the band images with the right offset, then adjust the sizes
 CPLErr GDALMRFDataset::SetVersion(int version) {
     if (!hasVersions || version > verCount) {
-	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Version number error!");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Version number error!");
+        return CE_Failure;
     }
     // Size of one version index
     for (int bcount = 1; bcount <= nBands; bcount++) {
-	GDALMRFRasterBand *srcband = (GDALMRFRasterBand *)GetRasterBand(bcount);
-	srcband->img.idxoffset += idxSize*verCount;
-	for (int l = 0; l < srcband->GetOverviewCount(); l++) {
-	    GDALMRFRasterBand *band = (GDALMRFRasterBand *)srcband->GetOverview(l);
+        GDALMRFRasterBand *srcband = reinterpret_cast<GDALMRFRasterBand *>(GetRasterBand(bcount));
+        srcband->img.idxoffset += idxSize*verCount;
+        for (int l = 0; l < srcband->GetOverviewCount(); l++) {
+            GDALMRFRasterBand *band = reinterpret_cast<GDALMRFRasterBand *>(srcband->GetOverview(l));
             if( band != NULL )
                 band->img.idxoffset += idxSize*verCount;
-	}
+        }
     }
     hasVersions = 0;
     return CE_None;
@@ -615,13 +668,16 @@ CPLErr GDALMRFDataset::SetVersion(int version) {
 CPLErr GDALMRFDataset::LevelInit(const int l) {
     // Test that this level does exist
     if (l < 0 || l >= cds->GetRasterBand(1)->GetOverviewCount()) {
-	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Overview not present!");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Overview not present!");
+        return CE_Failure;
     }
 
-    GDALMRFRasterBand *srcband = (GDALMRFRasterBand *)cds->GetRasterBand(1)->GetOverview(l);
+    GDALMRFRasterBand *srcband =
+        reinterpret_cast<GDALMRFRasterBand *>(cds->GetRasterBand(1)->GetOverview(l));
+
     // Copy the sizes from this level
-    current = full = srcband->img;
+    full = srcband->img;
+    current = srcband->img;
     current.size.c = cds->current.size.c;
     scale = cds->scale;
     SetProjection(cds->GetProjectionRef());
@@ -631,8 +687,8 @@ CPLErr GDALMRFDataset::LevelInit(const int l) {
 
     bGeoTransformValid = (CE_None == cds->GetGeoTransform(GeoTransform));
     for (int i = 0; i < l; i++) {
-	GeoTransform[1] /= scale;
-	GeoTransform[5] /= scale;
+        GeoTransform[1] /= scale;
+        GeoTransform[5] /= scale;
     }
 
     nRasterXSize = current.size.x;
@@ -640,27 +696,25 @@ CPLErr GDALMRFDataset::LevelInit(const int l) {
     nBands = current.size.c;
 
     // Add the bands, copy constructor so they can be closed independently
-    for (int i = 1; i <= nBands; i++) {
-	GDALMRFLRasterBand *band = new GDALMRFLRasterBand((GDALMRFRasterBand *)
-	    cds->GetRasterBand(i)->GetOverview(l));
-	SetBand(i, band);
-    }
+    for (int i = 1; i <= nBands; i++)
+        SetBand(i, new GDALMRFLRasterBand(reinterpret_cast<GDALMRFRasterBand *>
+                                            (cds->GetRasterBand(i)->GetOverview(l))));
     return CE_None;
 }
 
 // Is the string positive or not
 inline bool on(const char *pszValue) {
     if (!pszValue || pszValue[0] == 0)
-	return false;
-    return (EQUAL(pszValue, "ON") || EQUAL(pszValue, "TRUE") || EQUAL(pszValue, "YES"));
+        return false;
+    return EQUAL(pszValue, "ON") || EQUAL(pszValue, "TRUE") || EQUAL(pszValue, "YES");
 }
 
 /**
 *\brief Initialize the image structure and the dataset from the XML Raster node
 *
-* @param image, the structure to be initialized
-* @param config, the Raster node of the xml structure
-* @param ds, the parent dataset, some things get inherited
+* @param image the structure to be initialized
+* @param ds the parent dataset, some things get inherited
+* @param defimage defimage
 *
 * The structure should be initialized with the default values as much as possible
 *
@@ -670,44 +724,44 @@ static CPLErr Init_Raster(ILImage &image, GDALMRFDataset *ds, CPLXMLNode *defima
 {
     CPLXMLNode *node; // temporary
     if (!defimage) {
-	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Can't find raster info");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Can't find raster info");
+        return CE_Failure;
     }
 
     // Size is mandatory
     node = CPLGetXMLNode(defimage, "Size");
 
     if (node) {
-	image.size = ILSize(
-	    static_cast<int>(getXMLNum(node, "x", -1)),
-	    static_cast<int>(getXMLNum(node, "y", -1)),
-	    static_cast<int>(getXMLNum(node, "z", 1)),
-	    static_cast<int>(getXMLNum(node, "c", 1)),
-	    0);
+        image.size = ILSize(
+            static_cast<int>(getXMLNum(node, "x", -1)),
+            static_cast<int>(getXMLNum(node, "y", -1)),
+            static_cast<int>(getXMLNum(node, "z", 1)),
+            static_cast<int>(getXMLNum(node, "c", 1)),
+            0);
     }
 
     // Basic checks
     if (!node || image.size.x < 1 || image.size.y < 1 ||
         !GDALCheckBandCount(image.size.c, FALSE)) {
-	CPLError(CE_Failure, CPLE_AppDefined, "Raster size missing or invalid");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "Raster size missing or invalid");
+        return CE_Failure;
     }
 
     //  Pagesize, defaults to 512,512,1,c
     image.pagesize = ILSize(
-	MIN(512, image.size.x),
-	MIN(512, image.size.y),
-	1,
-	image.size.c);
+        std::min(512, image.size.x),
+        std::min(512, image.size.y),
+        1,
+        image.size.c);
 
     node = CPLGetXMLNode(defimage, "PageSize");
     if (node)
     {
-	image.pagesize = ILSize(
-	static_cast<int>(getXMLNum(node, "x", image.pagesize.x)),
-	static_cast<int>(getXMLNum(node, "y", image.pagesize.y)),
-	1, // One z at a time, forced
-	static_cast<int>(getXMLNum(node, "c", image.pagesize.c)));
+        image.pagesize = ILSize(
+        static_cast<int>(getXMLNum(node, "x", image.pagesize.x)),
+        static_cast<int>(getXMLNum(node, "y", image.pagesize.y)),
+        1, // One z at a time, forced
+        static_cast<int>(getXMLNum(node, "c", image.pagesize.c)));
         if( image.pagesize.x < 1 ||
             image.pagesize.y < 1 ||
             image.pagesize.c <= 0 )
@@ -717,7 +771,7 @@ static CPLErr Init_Raster(ILImage &image, GDALMRFDataset *ds, CPLXMLNode *defima
         }
     }
 
-    // Orientation, some other systems might support something 
+    // Orientation, some other systems might support something
     //   if (!EQUAL(CPLGetXMLValue(defimage,"Orientation","TL"), "TL")) {
     //// GDAL only handles Top Left Images
     //CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Only Top-Left orientation is supported");
@@ -728,10 +782,10 @@ static CPLErr Init_Raster(ILImage &image, GDALMRFDataset *ds, CPLXMLNode *defima
     image.comp = CompToken(CPLGetXMLValue(defimage, "Compression", "PNG"));
 
     if (image.comp == IL_ERR_COMP) {
-	CPLError(CE_Failure, CPLE_AppDefined,
-	    "GDAL MRF: Compression %s is unknown",
-	    CPLGetXMLValue(defimage, "Compression", NULL));
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "GDAL MRF: Compression %s is unknown",
+            CPLGetXMLValue(defimage, "Compression", NULL));
+        return CE_Failure;
     }
 
     // Is there a palette?
@@ -750,100 +804,97 @@ static CPLErr Init_Raster(ILImage &image, GDALMRFDataset *ds, CPLXMLNode *defima
     // The palette starts initialized with zeros
     // HSV and HLS are the similar, with c2 and c3 swapped
     // RGB or RGBA are same
-    // 
+    //
 
     if ((image.pagesize.c == 1) && (NULL != (node = CPLGetXMLNode(defimage, "Palette")))) {
-	int entries = static_cast<int>(getXMLNum(node, "Size", 255));
-	GDALPaletteInterp eInterp = GPI_RGB;
-	// A flag to convert from HLS to HSV
-	CPLString pModel = CPLGetXMLValue(node, "Model", "RGB");
-
-	if ((entries > 0) && (entries < 257)) {
-	    int start_idx, end_idx;
-	    GDALColorEntry ce_start = { 0, 0, 0, 255 }, ce_end = { 0, 0, 0, 255 };
-
-	    // Create it and initialize it to nothing
-	    GDALColorTable *poColorTable = new GDALColorTable(eInterp);
-	    poColorTable->CreateColorRamp(0, &ce_start, entries - 1, &ce_end);
-	    // Read the values
-	    CPLXMLNode *p = CPLGetXMLNode(node, "Entry");
-	    if (p) {
-		// Initialize the first entry
-		ce_start = GetXMLColorEntry(p);
-		start_idx = static_cast<int>(getXMLNum(p, "idx", 0));
-		if (start_idx < 0) {
-		    CPLError(CE_Failure, CPLE_AppDefined,
-			"GDAL MRF: Palette index %d not allowed", start_idx);
-		    delete poColorTable;
-		    return CE_Failure;
-		}
-		poColorTable->SetColorEntry(start_idx, &ce_start);
-		while (NULL != (p = SearchXMLSiblings(p, "Entry"))) {
-		    // For every entry, create a ramp
-		    ce_end = GetXMLColorEntry(p);
-		    end_idx = static_cast<int>(getXMLNum(p, "idx", start_idx + 1));
-		    if ((end_idx <= start_idx) || (start_idx >= entries)) {
-			CPLError(CE_Failure, CPLE_AppDefined,
-			    "GDAL MRF: Index Error at index %d", end_idx);
-			delete poColorTable;
-			return CE_Failure;
-		    }
-		    poColorTable->CreateColorRamp(start_idx, &ce_start,
-			end_idx, &ce_end);
-ce_start = ce_end;
-start_idx = end_idx;
-		}
-	    }
-
-	    ds->SetColorTable(poColorTable);
-	}
-	else {
-	    CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Palette definition error");
-	    return CE_Failure;
-	}
+        int entries = static_cast<int>(getXMLNum(node, "Size", 255));
+        GDALPaletteInterp eInterp = GPI_RGB;
+        // A flag to convert from HLS to HSV
+        CPLString pModel = CPLGetXMLValue(node, "Model", "RGB");
+
+        if ((entries > 0) && (entries < 257)) {
+            GDALColorEntry ce_start = { 0, 0, 0, 255 }, ce_end = { 0, 0, 0, 255 };
+
+            // Create it and initialize it to nothing
+            GDALColorTable *poColorTable = new GDALColorTable(eInterp);
+            poColorTable->CreateColorRamp(0, &ce_start, entries - 1, &ce_end);
+            // Read the values
+            CPLXMLNode *p = CPLGetXMLNode(node, "Entry");
+            if (p) {
+                // Initialize the first entry
+                ce_start = GetXMLColorEntry(p);
+                int start_idx = static_cast<int>(getXMLNum(p, "idx", 0));
+                if (start_idx < 0) {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                        "GDAL MRF: Palette index %d not allowed", start_idx);
+                    delete poColorTable;
+                    return CE_Failure;
+                }
+                poColorTable->SetColorEntry(start_idx, &ce_start);
+                while (NULL != (p = SearchXMLSiblings(p, "Entry"))) {
+                    // For every entry, create a ramp
+                    ce_end = GetXMLColorEntry(p);
+                    int end_idx = static_cast<int>(getXMLNum(p, "idx", start_idx + 1));
+                    if ((end_idx <= start_idx) || (start_idx >= entries)) {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                            "GDAL MRF: Index Error at index %d", end_idx);
+                        delete poColorTable;
+                        return CE_Failure;
+                    }
+                    poColorTable->CreateColorRamp(start_idx, &ce_start, end_idx, &ce_end);
+                    ce_start = ce_end;
+                    start_idx = end_idx;
+                }
+            }
+
+            ds->SetColorTable(poColorTable);
+        }
+        else {
+            CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Palette definition error");
+            return CE_Failure;
+        }
     }
 
     // Order of increment
     image.order = OrderToken(CPLGetXMLValue(defimage, "Order",
-	(image.pagesize.c != image.size.c) ? "BAND" : "PIXEL"));
+        (image.pagesize.c != image.size.c) ? "BAND" : "PIXEL"));
     if (image.order == IL_ERR_ORD) {
-	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Order %s is unknown",
-	    CPLGetXMLValue(defimage, "Order", NULL));
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Order %s is unknown",
+            CPLGetXMLValue(defimage, "Order", NULL));
+        return CE_Failure;
     }
 
     image.quality = atoi(CPLGetXMLValue(defimage, "Quality", "85"));
 
     const char * photo_val = CPLGetXMLValue(defimage, "Photometric", NULL);
     if (photo_val)
-	ds->SetPhotometricInterpretation(photo_val);
+        ds->SetPhotometricInterpretation(photo_val);
 
     if (image.quality < 0 || image.quality>99) {
-	CPLError(CE_Warning, CPLE_AppDefined, "GDAL MRF: Quality setting error, using default of 85");
-	image.quality = 85;
+        CPLError(CE_Warning, CPLE_AppDefined, "GDAL MRF: Quality setting error, using default of 85");
+        image.quality = 85;
     }
 
     // Data Type, use GDAL Names
     image.dt = GDALGetDataTypeByName(
-	CPLGetXMLValue(defimage, "DataType", GDALGetDataTypeName(image.dt)));
+        CPLGetXMLValue(defimage, "DataType", GDALGetDataTypeName(image.dt)));
     if (image.dt == GDT_Unknown || GDALGetDataTypeSize(image.dt) == 0 ) {
-	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Image has wrong type");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Image has wrong type");
+        return CE_Failure;
     }
 
     // Check the endianness if needed, assume host order
     if (is_Endianess_Dependent(image.dt, image.comp))
-	image.nbo = on(CPLGetXMLValue(defimage, "NetByteOrder", "No"));
+        image.nbo = on(CPLGetXMLValue(defimage, "NetByteOrder", "No"));
 
     CPLXMLNode *DataValues = CPLGetXMLNode(defimage, "DataValues");
     if (NULL != DataValues) {
-	const char *pszValue;
-	pszValue = CPLGetXMLValue(DataValues, "NoData", NULL);
-	if (pszValue) ds->SetNoDataValue(pszValue);
-	pszValue = CPLGetXMLValue(DataValues, "min", NULL);
-	if (pszValue) ds->SetMinValue(pszValue);
-	pszValue = CPLGetXMLValue(DataValues, "max", NULL);
-	if (pszValue) ds->SetMaxValue(pszValue);
+        const char *pszValue = CPLGetXMLValue(DataValues, "NoData", NULL);
+        if (pszValue) ds->SetNoDataValue(pszValue);
+        pszValue = CPLGetXMLValue(DataValues, "min", NULL);
+        if (pszValue) ds->SetMinValue(pszValue);
+        pszValue = CPLGetXMLValue(DataValues, "max", NULL);
+        if (pszValue) ds->SetMaxValue(pszValue);
     }
 
     // Calculate the page size in bytes
@@ -857,7 +908,7 @@ start_idx = end_idx;
         return CE_Failure;
     }
     image.pageSizeBytes = (GDALGetDataTypeSize(image.dt) / 8) *
-	image.pagesize.x * image.pagesize.y * image.pagesize.z * image.pagesize.c;
+        image.pagesize.x * image.pagesize.y * image.pagesize.z * image.pagesize.c;
 
     // Calculate the page count, including the total for the level
     image.pagecount = pcount(image.size, image.pagesize);
@@ -865,12 +916,12 @@ start_idx = end_idx;
     // Data File Name and base offset
     image.datfname = getFname(defimage, "DataFile", ds->GetFname(), ILComp_Ext[image.comp]);
     image.dataoffset = static_cast<int>(
-	getXMLNum(CPLGetXMLNode(defimage, "DataFile"), "offset", 0.0));
+        getXMLNum(CPLGetXMLNode(defimage, "DataFile"), "offset", 0.0));
 
     // Index File Name and base offset
     image.idxfname = getFname(defimage, "IndexFile", ds->GetFname(), ".idx");
     image.idxoffset = static_cast<int>(
-	getXMLNum(CPLGetXMLNode(defimage, "IndexFile"), "offset", 0.0));
+        getXMLNum(CPLGetXMLNode(defimage, "IndexFile"), "offset", 0.0));
 
     return CE_None;
 }
@@ -882,7 +933,7 @@ char      **GDALMRFDataset::GetFileList()
     // Add the header file name if it is real
     VSIStatBufL  sStat;
     if (VSIStatExL(fname, &sStat, VSI_STAT_EXISTS_FLAG) == 0)
-	papszFileList = CSLAddString(papszFileList, fname);
+        papszFileList = CSLAddString(papszFileList, fname);
 
     // These two should be real
     // We don't really want to add these files, since they will be erased when an mrf is overwritten
@@ -891,7 +942,7 @@ char      **GDALMRFDataset::GetFileList()
     //    papszFileList = CSLAddString( papszFileList, full.datfname);
     //    papszFileList = CSLAddString( papszFileList, full.idxfname);
     //    if (!source.empty())
-    //	papszFileList = CSLAddString( papszFileList, source);
+    // papszFileList = CSLAddString( papszFileList, source);
 
     return papszFileList;
 }
@@ -903,74 +954,82 @@ static void mkdir_r(string const &fname) {
         return;
     while (true) {
         ++ loc;
-	loc = fname.find_first_of("\\/", loc);
+        loc = fname.find_first_of("\\/", loc);
         if( loc == string::npos )
             break;
-	VSIMkdir(fname.substr(0, loc).c_str(), 0);
+        VSIMkdir(fname.substr(0, loc).c_str(), 0);
     }
 }
 
 // Returns the dataset index file or null
 VSILFILE *GDALMRFDataset::IdxFP() {
     if (ifp.FP != NULL)
-	return ifp.FP;
+        return ifp.FP;
+
+    // If name starts with '(' it is not a real file name
+    if (current.idxfname[0] == '(')
+        return NULL;
 
     const char *mode = "rb";
     ifp.acc = GF_Read;
 
     if (eAccess == GA_Update || !source.empty()) {
-	mode = "r+b";
-	ifp.acc = GF_Write;
+        mode = "r+b";
+        ifp.acc = GF_Write;
     }
 
     ifp.FP = VSIFOpenL(current.idxfname, mode);
 
     // need to create the index file
     if (ifp.FP == NULL && !bCrystalized && (eAccess == GA_Update || !source.empty())) {
-	mode = "w+b";
-	ifp.FP = VSIFOpenL(current.idxfname, mode);
+        mode = "w+b";
+        ifp.FP = VSIFOpenL(current.idxfname, mode);
     }
 
     if (NULL == ifp.FP && !source.empty()) {
-	// caching and cloning, try making the folder and attempt again
-	mkdir_r(current.idxfname);
-	ifp.FP = VSIFOpenL(current.idxfname, mode);
+        // caching and cloning, try making the folder and attempt again
+        mkdir_r(current.idxfname);
+        ifp.FP = VSIFOpenL(current.idxfname, mode);
     }
 
     GIntBig expected_size = idxSize;
     if (clonedSource) expected_size *= 2;
 
     if (NULL != ifp.FP) {
-	if (!bCrystalized && !CheckFileSize(current.idxfname, expected_size, GA_Update)) {
-	    CPLError(CE_Failure, CPLE_AppDefined, "Can't extend the cache index file %s",
-		current.idxfname.c_str());
-	    return NULL;
-	}
-
-	if (source.empty())
-	    return ifp.FP;
-
-	// Make sure the index is large enough before proceeding
-	// Timeout in .1 seconds, can't really guarantee the accuracy
-	// So this is about half second, should be sufficient
-	int timeout = 5;
-	do {
-	    if (CheckFileSize(current.idxfname, expected_size, GA_ReadOnly))
-		return ifp.FP;
-	    CPLSleep(0.100); /* 100 ms */
-	} while (--timeout);
-
-	// If we get here it is a time-out
-	CPLError(CE_Failure, CPLE_AppDefined,
-	    "GDAL MRF: Timeout on fetching cloned index file %s\n", current.idxfname.c_str());
-	return NULL;
+        if (!bCrystalized && !CheckFileSize(current.idxfname, expected_size, GA_Update)) {
+            CPLError(CE_Failure, CPLE_AppDefined, "Can't extend the cache index file %s",
+                current.idxfname.c_str());
+            return NULL;
+        }
+
+        if (source.empty())
+            return ifp.FP;
+
+        // Make sure the index is large enough before proceeding
+        // Timeout in .1 seconds, can't really guarantee the accuracy
+        // So this is about half second, should be sufficient
+        int timeout = 5;
+        do {
+            if (CheckFileSize(current.idxfname, expected_size, GA_ReadOnly))
+                return ifp.FP;
+            CPLSleep(0.100); /* 100 ms */
+        } while (--timeout);
+
+        // If we get here it is a time-out
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "GDAL MRF: Timeout on fetching cloned index file %s\n", current.idxfname.c_str());
+        return NULL;
     }
 
+    // If single tile, and no index file, let the caller figure it out
+    if (IsSingleTile())
+        return NULL;
+
     // Error if this is not a caching MRF
     if (source.empty()) {
-	CPLError(CE_Failure, CPLE_AppDefined,
-	    "GDAL MRF: Can't open index file %s\n", current.idxfname.c_str());
-	return NULL;
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "GDAL MRF: Can't open index file %s\n", current.idxfname.c_str());
+        return NULL;
     }
 
     // Caching/Cloning MRF and index could be read only
@@ -979,24 +1038,24 @@ VSILFILE *GDALMRFDataset::IdxFP() {
     ifp.acc = GF_Read;
     ifp.FP = VSIFOpenL(current.idxfname, mode);
     if (NULL != ifp.FP)
-	return ifp.FP;
+        return ifp.FP;
 
     // Caching and index file absent, create it
     // Due to a race, multiple processes might do this at the same time, but that is fine
     ifp.FP = VSIFOpenL(current.idxfname, "wb");
     if (NULL == ifp.FP) {
-	CPLError(CE_Failure, CPLE_AppDefined, "Can't create the MRF cache index file %s",
-	    current.idxfname.c_str());
-	return NULL;
+        CPLError(CE_Failure, CPLE_AppDefined, "Can't create the MRF cache index file %s",
+            current.idxfname.c_str());
+        return NULL;
     }
     VSIFCloseL(ifp.FP);
     ifp.FP = NULL;
 
     // Make it large enough for caching and for cloning
     if (!CheckFileSize(current.idxfname, expected_size, GA_Update)) {
-	CPLError(CE_Failure, CPLE_AppDefined, "Can't extend the cache index file %s",
-	    current.idxfname.c_str());
-	return NULL;
+        CPLError(CE_Failure, CPLE_AppDefined, "Can't extend the cache index file %s",
+            current.idxfname.c_str());
+        return NULL;
     }
 
     // Try opening it again in rw mode so we can read and write
@@ -1005,48 +1064,48 @@ VSILFILE *GDALMRFDataset::IdxFP() {
     ifp.FP = VSIFOpenL(current.idxfname.c_str(), mode);
 
     if (NULL == ifp.FP) {
-	CPLError(CE_Failure, CPLE_AppDefined,
-	    "GDAL MRF: Can't reopen cache index file %s\n", full.idxfname.c_str());
-	return NULL;
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "GDAL MRF: Can't reopen cache index file %s\n", full.idxfname.c_str());
+        return NULL;
     }
     return ifp.FP;
 }
 
 //
-// Returns the dataset data file or null 
+// Returns the dataset data file or null
 // Data file is opened either in Read or Append mode, never in straight write
 //
 VSILFILE *GDALMRFDataset::DataFP() {
     if (dfp.FP != NULL)
-	return dfp.FP;
+        return dfp.FP;
     const char *mode = "rb";
     dfp.acc = GF_Read;
 
     // Open it for writing if updating or if caching
     if (eAccess == GA_Update || !source.empty()) {
-	mode = "a+b";
-	dfp.acc = GF_Write;
+        mode = "a+b";
+        dfp.acc = GF_Write;
     }
 
     dfp.FP = VSIFOpenL(current.datfname, mode);
-    if (dfp.FP) 
-	return dfp.FP;
+    if (dfp.FP)
+        return dfp.FP;
 
     // It could be a caching MRF
-    if (source.empty()) 
-	goto io_error;
+    if (source.empty())
+        goto io_error;
 
     // Cloud be there but read only, remember that it was open that way
     mode = "rb";
     dfp.acc = GF_Read;
     dfp.FP = VSIFOpenL(current.datfname, mode);
     if (NULL != dfp.FP) {
-	CPLDebug("MRF_IO", "Opened %s RO mode %s\n", current.datfname.c_str(), mode);
-	return dfp.FP;
+        CPLDebug("MRF_IO", "Opened %s RO mode %s\n", current.datfname.c_str(), mode);
+        return dfp.FP;
     }
 
-    if (source.empty()) 
-	goto io_error;
+    if (source.empty())
+        goto io_error;
 
     // caching, maybe the folder didn't exist
     mkdir_r(current.datfname);
@@ -1054,12 +1113,12 @@ VSILFILE *GDALMRFDataset::DataFP() {
     dfp.acc = GF_Write;
     dfp.FP = VSIFOpenL(current.datfname, mode);
     if (dfp.FP)
-	return dfp.FP;
+        return dfp.FP;
 
 io_error:
     dfp.FP = NULL;
     CPLError(CE_Failure, CPLE_FileIO,
-	"GDAL MRF: %s : %s", strerror(errno), current.datfname.c_str());
+        "GDAL MRF: %s : %s", strerror(errno), current.datfname.c_str());
     return NULL;
 };
 
@@ -1069,109 +1128,117 @@ CPLXMLNode * GDALMRFDataset::BuildConfig()
     CPLXMLNode *config = CPLCreateXMLNode(NULL, CXT_Element, "MRF_META");
 
     if (!source.empty()) {
-	CPLXMLNode *psCachedSource = CPLCreateXMLNode(config, CXT_Element, "CachedSource");
-	// Should wrap the string in CDATA, in case it is XML
-	CPLXMLNode *psSource = CPLCreateXMLElementAndValue(psCachedSource, "Source", source);
-	if (clonedSource)
-	    CPLSetXMLValue(psSource, "#clone", "true");
+        CPLXMLNode *psCachedSource = CPLCreateXMLNode(config, CXT_Element, "CachedSource");
+        // Should wrap the string in CDATA, in case it is XML
+        CPLXMLNode *psSource = CPLCreateXMLElementAndValue(psCachedSource, "Source", source);
+        if (clonedSource)
+            CPLSetXMLValue(psSource, "#clone", "true");
     }
 
     // Use the full size
     CPLXMLNode *raster = CPLCreateXMLNode(config, CXT_Element, "Raster");
+
+    // Preserve the file names if not the default ones
+    if (full.datfname != getFname(GetFname(), ILComp_Ext[full.comp]))
+        CPLCreateXMLElementAndValue(raster, "DataFile", full.datfname.c_str());
+    if (full.idxfname != getFname(GetFname(), ".idx"))
+        CPLCreateXMLElementAndValue(raster, "IndexFile", full.idxfname.c_str());
+    if (spacing != 0)
+        XMLSetAttributeVal(raster, "Spacing", static_cast<double>(spacing), "%.0f");
+
     XMLSetAttributeVal(raster, "Size", full.size, "%.0f");
     XMLSetAttributeVal(raster, "PageSize", full.pagesize, "%.0f");
 
     if (full.comp != IL_PNG)
-	CPLCreateXMLElementAndValue(raster, "Compression", CompName(full.comp));
+        CPLCreateXMLElementAndValue(raster, "Compression", CompName(full.comp));
 
     if (full.dt != GDT_Byte)
-	CPLCreateXMLElementAndValue(raster, "DataType", GDALGetDataTypeName(full.dt));
+        CPLCreateXMLElementAndValue(raster, "DataType", GDALGetDataTypeName(full.dt));
 
     // special photometric interpretation
     if (!photometric.empty())
-	CPLCreateXMLElementAndValue(raster, "Photometric", photometric);
+        CPLCreateXMLElementAndValue(raster, "Photometric", photometric);
 
-    if (vNoData.size() || vMin.size() || vMax.size()) {
-	CPLXMLNode *values = CPLCreateXMLNode(raster, CXT_Element, "DataValues");
-	XMLSetAttributeVal(values, "NoData", vNoData);
-	XMLSetAttributeVal(values, "min", vMin);
-	XMLSetAttributeVal(values, "max", vMax);
+    if (!vNoData.empty() || !vMin.empty() || !vMax.empty() ) {
+        CPLXMLNode *values = CPLCreateXMLNode(raster, CXT_Element, "DataValues");
+        XMLSetAttributeVal(values, "NoData", vNoData);
+        XMLSetAttributeVal(values, "min", vMin);
+        XMLSetAttributeVal(values, "max", vMax);
     }
 
     // palette, if we have one
     if (poColorTable != NULL) {
-	const char *pfrmt = "%.0f";
-	CPLXMLNode *pal = CPLCreateXMLNode(raster, CXT_Element, "Palette");
-	int sz = poColorTable->GetColorEntryCount();
-	if (sz != 256)
-	    XMLSetAttributeVal(pal, "Size", poColorTable->GetColorEntryCount());
-	// RGB or RGBA for now
-	for (int i = 0; i < sz; i++) {
-	    CPLXMLNode *entry = CPLCreateXMLNode(pal, CXT_Element, "Entry");
-	    const GDALColorEntry *ent = poColorTable->GetColorEntry(i);
-	    // No need to set the index, it is always from 0 no size-1
-	    XMLSetAttributeVal(entry, "c1", ent->c1, pfrmt);
-	    XMLSetAttributeVal(entry, "c2", ent->c2, pfrmt);
-	    XMLSetAttributeVal(entry, "c3", ent->c3, pfrmt);
-	    if (ent->c4 != 255)
-		XMLSetAttributeVal(entry, "c4", ent->c4, pfrmt);
-	}
+        const char *pfrmt = "%.0f";
+        CPLXMLNode *pal = CPLCreateXMLNode(raster, CXT_Element, "Palette");
+        int sz = poColorTable->GetColorEntryCount();
+        if (sz != 256)
+            XMLSetAttributeVal(pal, "Size", poColorTable->GetColorEntryCount());
+        // RGB or RGBA for now
+        for (int i = 0; i < sz; i++) {
+            CPLXMLNode *entry = CPLCreateXMLNode(pal, CXT_Element, "Entry");
+            const GDALColorEntry *ent = poColorTable->GetColorEntry(i);
+            // No need to set the index, it is always from 0 no size-1
+            XMLSetAttributeVal(entry, "c1", ent->c1, pfrmt);
+            XMLSetAttributeVal(entry, "c2", ent->c2, pfrmt);
+            XMLSetAttributeVal(entry, "c3", ent->c3, pfrmt);
+            if (ent->c4 != 255)
+                XMLSetAttributeVal(entry, "c4", ent->c4, pfrmt);
+        }
     }
 
     if (is_Endianess_Dependent(full.dt, full.comp)) // Need to set the order
-	CPLCreateXMLElementAndValue(raster, "NetByteOrder",
-	(full.nbo || NET_ORDER) ? "TRUE" : "FALSE");
+        CPLCreateXMLElementAndValue(raster, "NetByteOrder",
+        (full.nbo || NET_ORDER) ? "TRUE" : "FALSE");
 
     if (full.quality > 0 && full.quality != 85)
-	CPLCreateXMLElementAndValue(raster, "Quality",
-	    CPLString().Printf("%d", full.quality));
+        CPLCreateXMLElementAndValue(raster, "Quality",
+            CPLString().Printf("%d", full.quality));
 
     // Done with the raster node
 
-    if (scale) {
-	CPLCreateXMLNode(config, CXT_Element, "Rsets");
-	CPLSetXMLValue(config, "Rsets.#model", "uniform");
-	CPLSetXMLValue(config, "Rsets.#scale", PrintDouble(scale));
+    if (scale != 0.0) {
+        CPLCreateXMLNode(config, CXT_Element, "Rsets");
+        CPLSetXMLValue(config, "Rsets.#model", "uniform");
+        CPLSetXMLValue(config, "Rsets.#scale", PrintDouble(scale));
     }
     CPLXMLNode *gtags = CPLCreateXMLNode(config, CXT_Element, "GeoTags");
 
     // Do we have an affine transform different from identity?
     double gt[6];
     if ((GetGeoTransform(gt) == CE_None) &&
-	(gt[0] != 0 || gt[1] != 1 || gt[2] != 0 ||
-	gt[3] != 0 || gt[4] != 0 || gt[5] != 1))
+        (gt[0] != 0 || gt[1] != 1 || gt[2] != 0 ||
+        gt[3] != 0 || gt[4] != 0 || gt[5] != 1))
     {
-	double minx = gt[0];
-	double maxx = gt[1] * full.size.x + minx;
-	double maxy = gt[3];
-	double miny = gt[5] * full.size.y + maxy;
-	CPLXMLNode *bbox = CPLCreateXMLNode(gtags, CXT_Element, "BoundingBox");
-	XMLSetAttributeVal(bbox, "minx", minx);
-	XMLSetAttributeVal(bbox, "miny", miny);
-	XMLSetAttributeVal(bbox, "maxx", maxx);
-	XMLSetAttributeVal(bbox, "maxy", maxy);
+        double minx = gt[0];
+        double maxx = gt[1] * full.size.x + minx;
+        double maxy = gt[3];
+        double miny = gt[5] * full.size.y + maxy;
+        CPLXMLNode *bbox = CPLCreateXMLNode(gtags, CXT_Element, "BoundingBox");
+        XMLSetAttributeVal(bbox, "minx", minx);
+        XMLSetAttributeVal(bbox, "miny", miny);
+        XMLSetAttributeVal(bbox, "maxx", maxx);
+        XMLSetAttributeVal(bbox, "maxy", maxy);
     }
 
     const char *pszProj = GetProjectionRef();
     if (pszProj && (!EQUAL(pszProj, "")))
-	CPLCreateXMLElementAndValue(gtags, "Projection", pszProj);
+        CPLCreateXMLElementAndValue(gtags, "Projection", pszProj);
 
-    if (optlist.size()) {
-	CPLString options;
-	for (int i = 0; i < optlist.size(); i++) {
-	    options += optlist[i];
-	    options += ' ';
-	}
-	options.resize(options.size() - 1);
-	CPLCreateXMLElementAndValue(config, "Options", options);
+    if ( optlist.Count() != 0 ) {
+        CPLString options;
+        for (int i = 0; i < optlist.size(); i++) {
+            options += optlist[i];
+            options += ' ';
+        }
+        options.resize(options.size() - 1);
+        CPLCreateXMLElementAndValue(config, "Options", options);
     }
 
     return config;
 }
 
-
 /**
-* \Brief Populates the dataset variables from the XML definition
+* \brief Populates the dataset variables from the XML definition
 *
 *
 */
@@ -1188,28 +1255,29 @@ CPLErr GDALMRFDataset::Initialize(CPLXMLNode *config)
 
     hasVersions = on(CPLGetXMLValue(config, "Raster.versioned", "no"));
     mp_safe = on(CPLGetXMLValue(config, "Raster.mp_safe", "no"));
+    spacing = atoi(CPLGetXMLValue(config, "Raster.Spacing", "0"));
 
     Quality = full.quality;
     if (CE_None != ret)
-	return ret;
+        return ret;
 
     // Bounding box
     CPLXMLNode *bbox = CPLGetXMLNode(config, "GeoTags.BoundingBox");
     if (NULL != bbox) {
-	double x0, x1, y0, y1;
+        double x0, x1, y0, y1;
 
-	x0 = atof(CPLGetXMLValue(bbox, "minx", "0"));
-	x1 = atof(CPLGetXMLValue(bbox, "maxx", "1"));
-	y1 = atof(CPLGetXMLValue(bbox, "maxy", "1"));
-	y0 = atof(CPLGetXMLValue(bbox, "miny", "0"));
+        x0 = atof(CPLGetXMLValue(bbox, "minx", "0"));
+        x1 = atof(CPLGetXMLValue(bbox, "maxx", "1"));
+        y1 = atof(CPLGetXMLValue(bbox, "maxy", "1"));
+        y0 = atof(CPLGetXMLValue(bbox, "miny", "0"));
 
-	GeoTransform[0] = x0;
-	GeoTransform[1] = (x1 - x0) / full.size.x;
-	GeoTransform[2] = 0;
-	GeoTransform[3] = y1;
-	GeoTransform[4] = 0;
-	GeoTransform[5] = (y0 - y1) / full.size.y;
-	bGeoTransformValid = TRUE;
+        GeoTransform[0] = x0;
+        GeoTransform[1] = (x1 - x0) / full.size.x;
+        GeoTransform[2] = 0;
+        GeoTransform[3] = y1;
+        GeoTransform[4] = 0;
+        GeoTransform[5] = (y0 - y1) / full.size.y;
+        bGeoTransformValid = TRUE;
     }
 
     SetProjection(CPLGetXMLValue(config, "GeoTags.Projection", ""));
@@ -1217,17 +1285,17 @@ CPLErr GDALMRFDataset::Initialize(CPLXMLNode *config)
     // Copy the full size to current, data and index are not yet open
     current = full;
     if (current.size.z != 1) {
-	SetMetadataItem("ZSIZE", CPLString().Printf("%d", current.size.z), "IMAGE_STRUCTURE");
-	SetMetadataItem("ZSLICE", CPLString().Printf("%d", zslice), "IMAGE_STRUCTURE");
-	// Capture the zslice in pagesize.l
-	current.pagesize.l = zslice; 
-	// Adjust offset for base image
+        SetMetadataItem("ZSIZE", CPLString().Printf("%d", current.size.z), "IMAGE_STRUCTURE");
+        SetMetadataItem("ZSLICE", CPLString().Printf("%d", zslice), "IMAGE_STRUCTURE");
+        // Capture the zslice in pagesize.l
+        current.pagesize.l = zslice;
+        // Adjust offset for base image
         if( full.size.z <= 0 )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Invalid Raster.z value");
             return CE_Failure;
         }
-	current.idxoffset += sizeof(ILIdx) * current.pagecount.l / full.size.z * zslice; 
+        current.idxoffset += sizeof(ILIdx) * current.pagecount.l / full.size.z * zslice;
     }
 
     // Dataset metadata setup
@@ -1235,7 +1303,7 @@ CPLErr GDALMRFDataset::Initialize(CPLXMLNode *config)
     SetMetadataItem("COMPRESSION", CompName(current.comp), "IMAGE_STRUCTURE");
 
     if (is_Endianess_Dependent(current.dt, current.comp))
-	SetMetadataItem("NETBYTEORDER", current.nbo ? "TRUE" : "FALSE", "IMAGE_STRUCTURE");
+        SetMetadataItem("NETBYTEORDER", current.nbo ? "TRUE" : "FALSE", "IMAGE_STRUCTURE");
 
     // Open the files for the current image, either RW or RO
     nRasterXSize = current.size.x;
@@ -1243,8 +1311,8 @@ CPLErr GDALMRFDataset::Initialize(CPLXMLNode *config)
     nBands = current.size.c;
 
     if (!nBands || !nRasterXSize || !nRasterYSize) {
-	CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Image size missing");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "GDAL MRF: Image size missing");
+        return CE_Failure;
     }
 
     // Pick up the source data image, if there is one
@@ -1253,11 +1321,11 @@ CPLErr GDALMRFDataset::Initialize(CPLXMLNode *config)
     clonedSource = on(CPLGetXMLValue(config, "CachedSource.Source.clone", "no"));
     // Pick up the options, if any
     optlist.Assign(CSLTokenizeString2(CPLGetXMLValue(config, "Options", NULL),
-	" \t\n\r", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES));
+        " \t\n\r", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES));
 
     // Load all the options in the IMAGE_STRUCTURE metadata
     for (int i = 0; i < optlist.Count(); i++) {
-	CPLString s(optlist[i]);
+        CPLString s(optlist[i]);
         size_t nSepPos = s.find_first_of(":=");
         if( nSepPos != std::string::npos )
         {
@@ -1269,63 +1337,62 @@ CPLErr GDALMRFDataset::Initialize(CPLXMLNode *config)
 
     // We have the options, so we can call rasterband
     for (int i = 1; i <= nBands; i++) {
-	// The overviews are low resolution copies of the current one.
-	GDALMRFRasterBand *band = newMRFRasterBand(this, current, i);
-	if (!band)
-	    return CE_Failure;
-
-	GDALColorInterp ci = GCI_Undefined;
-
-	// Default color interpretation
-	switch (nBands) {
-	case 1:
-	case 2:
-	    ci = (i == 1) ? GCI_GrayIndex : GCI_AlphaBand;
-	    break;
-	case 3:
-	case 4:
-	    if (i < 3)
-		ci = (i == 1) ? GCI_RedBand : GCI_GreenBand;
-	    else
-		ci = (i == 3) ? GCI_BlueBand : GCI_AlphaBand;
-	}
-
-	if (GetColorTable())
-	    ci = GCI_PaletteIndex;
-
-	// Legacy, deprecated
-	if (optlist.FetchBoolean("MULTISPECTRAL", FALSE))
-	    ci = GCI_Undefined;
-
-	// New style
-	if (photometric.size()) {
-	    if ("MULTISPECTRAL" == photometric)
-		ci = GCI_Undefined;
-	}
-
-	band->SetColorInterpretation(ci);
-	SetBand(i, band);
+        // The overviews are low resolution copies of the current one.
+        GDALMRFRasterBand *band = newMRFRasterBand(this, current, i);
+        if (!band)
+            return CE_Failure;
+
+        GDALColorInterp ci = GCI_Undefined;
+
+        // Default color interpretation
+        switch (nBands) {
+        case 1:
+        case 2:
+            ci = (i == 1) ? GCI_GrayIndex : GCI_AlphaBand;
+            break;
+        case 3:
+        case 4:
+            if (i < 3)
+                ci = (i == 1) ? GCI_RedBand : GCI_GreenBand;
+            else
+                ci = (i == 3) ? GCI_BlueBand : GCI_AlphaBand;
+        }
+
+        if (GetColorTable())
+            ci = GCI_PaletteIndex;
+
+        // Legacy, deprecated
+        if (optlist.FetchBoolean("MULTISPECTRAL", FALSE))
+            ci = GCI_Undefined;
+
+        // New style
+        if (!photometric.empty() ) {
+            if ("MULTISPECTRAL" == photometric)
+                ci = GCI_Undefined;
+        }
+
+        band->SetColorInterpretation(ci);
+        SetBand(i, band);
     }
 
     CPLXMLNode *rsets = CPLGetXMLNode(config, "Rsets");
     if (NULL != rsets && NULL != rsets->psChild) {
-	// We have rsets 
-
-	// Regular spaced overlays, until everything fits in a single tile
-	if (EQUAL("uniform", CPLGetXMLValue(rsets, "model", "uniform"))) {
-	    scale = getXMLNum(rsets, "scale", 2.0);
-	    if (scale <= 1) {
-		CPLError(CE_Failure, CPLE_AppDefined, "MRF: zoom factor less than unit not allowed");
-		return CE_Failure;
-	    }
-	    // Looks like there are overlays
-	    AddOverviews(int(scale));
-	}
-	else {
-	    CPLError(CE_Failure, CPLE_AppDefined, "Unknown Rset definition");
-	    return CE_Failure;
-	}
-
+        // We have rsets
+
+        // Regular spaced overlays, until everything fits in a single tile
+        if (EQUAL("uniform", CPLGetXMLValue(rsets, "model", "uniform"))) {
+            scale = getXMLNum(rsets, "scale", 2.0);
+            if (scale <= 1) {
+                CPLError(CE_Failure, CPLE_AppDefined, "MRF: zoom factor less than unit not allowed");
+                return CE_Failure;
+            }
+            // Looks like there are overlays
+            AddOverviews(int(scale));
+        }
+        else {
+            CPLError(CE_Failure, CPLE_AppDefined, "Unknown Rset definition");
+            return CE_Failure;
+        }
     }
 
     idxSize = IdxSize(full, int(scale));
@@ -1340,11 +1407,11 @@ CPLErr GDALMRFDataset::Initialize(CPLXMLNode *config)
     }
 
     if (hasVersions) { // It has versions, but how many?
-	verCount = 0; // Assume it only has one
-	VSIStatBufL statb;
-	//  If the file exists, compute the last version number
-	if (0 == VSIStatL(full.idxfname, &statb))
-	    verCount = int(statb.st_size / idxSize - 1);
+        verCount = 0; // Assume it only has one
+        VSIStatBufL statb;
+        //  If the file exists, compute the last version number
+        if (0 == VSIStatL(full.idxfname, &statb))
+            verCount = int(statb.st_size / idxSize - 1);
     }
 
     return CE_None;
@@ -1358,38 +1425,38 @@ static inline bool has_path(const CPLString &name)
 static inline bool is_absolute(const CPLString &name)
 {
     return (name.find_first_of("/\\") == 0) ||
-	(name[1] == ':' && isalpha(name[0])) ||
-	name.find("<MRF_META>") != string::npos;
+        (name[1] == ':' && isalpha(name[0])) ||
+        name.find("<MRF_META>") != string::npos;
 }
 
 // Add the folder part of path to the beginning of the source, if it is relative
 static inline void make_absolute(CPLString &name, const CPLString &path)
 {
     if (!is_absolute(path) && (path.find_first_of("/\\") != string::npos))
-	name = path.substr(0, path.find_last_of("/\\") + 1) + name;
+        name = path.substr(0, path.find_last_of("/\\") + 1) + name;
 }
 
 /**
-*\Brief Get the source dataset, open it if necessary
+*\brief Get the source dataset, open it if necessary
 */
 GDALDataset *GDALMRFDataset::GetSrcDS() {
     if (poSrcDS) return poSrcDS;
-    if (source.empty())	return NULL;
+    if (source.empty()) return NULL;
     // Make the source absolute path
     if (has_path(fname)) make_absolute(source, fname);
     poSrcDS = (GDALDataset *)GDALOpenShared(source.c_str(), GA_ReadOnly);
     if (0 == source.find("<MRF_META>") && has_path(fname))
     {// XML MRF source, might need to patch the file names with the current one
-	GDALMRFDataset *psDS = reinterpret_cast<GDALMRFDataset *>(poSrcDS);
-	make_absolute(psDS->current.datfname, fname);
-	make_absolute(psDS->current.idxfname, fname);
+        GDALMRFDataset *psDS = reinterpret_cast<GDALMRFDataset *>(poSrcDS);
+        make_absolute(psDS->current.datfname, fname);
+        make_absolute(psDS->current.idxfname, fname);
     }
     mp_safe = true; // Turn on MP safety
     return poSrcDS;
 }
 
 /**
-*\Brief Add or verify that all overlays exits
+*\brief Add or verify that all overlays exits
 *
 * @return size of the index file
 */
@@ -1399,32 +1466,32 @@ GIntBig GDALMRFDataset::AddOverviews(int scaleIn) {
     ILImage img = current;
     while (1 != img.pagecount.x*img.pagecount.y)
     {
-	// Adjust raster data for next level
-	// Adjust the offsets for indices left at this level
-	img.idxoffset += sizeof(ILIdx) * img.pagecount.l / img.size.z * (img.size.z - zslice);
-
-	// Next overview size
-	img.size.x = pcount(img.size.x, scaleIn);
-	img.size.y = pcount(img.size.y, scaleIn);
-	img.size.l++; // Increment the level
-	img.pagecount = pcount(img.size, img.pagesize);
-
-	// And adjust the offset again, within next level
-	img.idxoffset += sizeof(ILIdx) * img.pagecount.l / img.size.z * zslice;
-		
-	// Create and register the the overviews for each band
-	for (int i = 1; i <= nBands; i++) {
-	    GDALMRFRasterBand *b = (GDALMRFRasterBand *)GetRasterBand(i);
-	    if (!(b->GetOverview(static_cast<int>(img.size.l) - 1)))
-		b->AddOverview(newMRFRasterBand(this, img, i, static_cast<int>(img.size.l)));
-	}
+        // Adjust raster data for next level
+        // Adjust the offsets for indices left at this level
+        img.idxoffset += sizeof(ILIdx) * img.pagecount.l / img.size.z * (img.size.z - zslice);
+
+        // Next overview size
+        img.size.x = pcount(img.size.x, scaleIn);
+        img.size.y = pcount(img.size.y, scaleIn);
+        img.size.l++; // Increment the level
+        img.pagecount = pcount(img.size, img.pagesize);
+
+        // And adjust the offset again, within next level
+        img.idxoffset += sizeof(ILIdx) * img.pagecount.l / img.size.z * zslice;
+
+        // Create and register the the overviews for each band
+        for (int i = 1; i <= nBands; i++) {
+            GDALMRFRasterBand *b = reinterpret_cast<GDALMRFRasterBand *>(GetRasterBand(i));
+            if (!(b->GetOverview(static_cast<int>(img.size.l) - 1)))
+                b->AddOverview(newMRFRasterBand(this, img, i, static_cast<int>(img.size.l)));
+        }
     }
 
     // Last adjustment, should be a single set of c and leftover z tiles
     return img.idxoffset + sizeof(ILIdx) * img.pagecount.l / img.size.z * (img.size.z - zslice);
 }
 
-// Try to implement CreateCopy using Create
+// CreateCopy implemented based on Create
 GDALDataset *GDALMRFDataset::CreateCopy(const char *pszFilename,
     GDALDataset *poSrcDS, int /*bStrict*/, char **papszOptions,
     GDALProgressFunc pfnProgress, void *pProgressData)
@@ -1458,63 +1525,63 @@ GDALDataset *GDALMRFDataset::CreateCopy(const char *pszFilename,
 
     GDALMRFDataset *poDS = NULL;
     try {
-	poDS = reinterpret_cast<GDALMRFDataset *>(
-	    Create(pszFilename, x, y, nBands, dt, options));
-
-	if (poDS == NULL || poDS->bCrystalized)
-	    throw CPLString().Printf("Can't create %s",pszFilename);
-
-	img = poDS->current; // Deal with the current one here
-
-	// Copy data values from source
-	for (int i = 0; i < poDS->nBands; i++) {
-	    int bHas;
-	    double dfData;
-	    GDALRasterBand *srcBand = poSrcDS->GetRasterBand(i + 1);
-	    GDALRasterBand *mBand = poDS->GetRasterBand(i + 1);
-	    dfData = srcBand->GetNoDataValue(&bHas);
-	    if (bHas) {
-		poDS->vNoData.push_back(dfData);
-		mBand->SetNoDataValue(dfData);
-	    }
-	    dfData = srcBand->GetMinimum(&bHas);
-	    if (bHas)
-		poDS->vMin.push_back(dfData);
-	    dfData = srcBand->GetMaximum(&bHas);
-	    if (bHas)
-		poDS->vMax.push_back(dfData);
-
-	    // Copy the band metadata, PAM will handle it
-	    char **meta = srcBand->GetMetadata("IMAGE_STRUCTURE");
-	    if (CSLCount(meta))
-		mBand->SetMetadata(meta,"IMAGE_STRUCTURE");
-
-	    meta = srcBand->GetMetadata();
-	    if (CSLCount(meta))
-		mBand->SetMetadata(meta);
-	}
+        poDS = reinterpret_cast<GDALMRFDataset *>(
+            Create(pszFilename, x, y, nBands, dt, options));
+
+        if (poDS == NULL || poDS->bCrystalized)
+            throw CPLString().Printf("Can't create %s",pszFilename);
+
+        img = poDS->current; // Deal with the current one here
+
+        // Copy data values from source
+        for (int i = 0; i < poDS->nBands; i++) {
+            int bHas;
+            double dfData;
+            GDALRasterBand *srcBand = poSrcDS->GetRasterBand(i + 1);
+            GDALRasterBand *mBand = poDS->GetRasterBand(i + 1);
+            dfData = srcBand->GetNoDataValue(&bHas);
+            if (bHas) {
+                poDS->vNoData.push_back(dfData);
+                mBand->SetNoDataValue(dfData);
+            }
+            dfData = srcBand->GetMinimum(&bHas);
+            if (bHas)
+                poDS->vMin.push_back(dfData);
+            dfData = srcBand->GetMaximum(&bHas);
+            if (bHas)
+                poDS->vMax.push_back(dfData);
+
+            // Copy the band metadata, PAM will handle it
+            char **meta = srcBand->GetMetadata("IMAGE_STRUCTURE");
+            if (CSLCount(meta))
+                mBand->SetMetadata(meta,"IMAGE_STRUCTURE");
+
+            meta = srcBand->GetMetadata();
+            if (CSLCount(meta))
+                mBand->SetMetadata(meta);
+        }
 
         // Geotags
         double gt[6];
-	if (CE_None == poSrcDS->GetGeoTransform(gt))
-	    poDS->SetGeoTransform(gt);
+        if (CE_None == poSrcDS->GetGeoTransform(gt))
+            poDS->SetGeoTransform(gt);
 
-	const char *pszProj = poSrcDS->GetProjectionRef();
-	if (pszProj && pszProj[0])
-	    poDS->SetProjection(pszProj);
+        const char *pszProj = poSrcDS->GetProjectionRef();
+        if (pszProj && pszProj[0])
+            poDS->SetProjection(pszProj);
 
-	// Color palette if we only have one band
-	if (1 == nBands && GCI_PaletteIndex == poSrcBand1->GetColorInterpretation())
-	    poDS->SetColorTable(poSrcBand1->GetColorTable()->Clone());
+        // Color palette if we only have one band
+        if (1 == nBands && GCI_PaletteIndex == poSrcBand1->GetColorInterpretation())
+            poDS->SetColorTable(poSrcBand1->GetColorTable()->Clone());
 
-	// Finally write the XML in the right file name
-	poDS->Crystalize();
+        // Finally write the XML in the right file name
+        poDS->Crystalize();
     }
     catch (CPLString(e)) {
-	if (poDS)
-	    delete poDS;
-	CPLError(CE_Failure, CPLE_ObjectNull, "%s", e.c_str());
-	poDS = NULL;
+        if (poDS)
+            delete poDS;
+        CPLError(CE_Failure, CPLE_ObjectNull, "%s", e.c_str());
+        poDS = NULL;
     }
 
     CSLDestroy(options);
@@ -1533,7 +1600,7 @@ GDALDataset *GDALMRFDataset::CreateCopy(const char *pszFilename,
 
     // If copy is disabled, we're done, we just created an empty MRF
     if (!poDS || on(CSLFetchNameValue(papszOptions, "NOCOPY")))
-	return poDS;
+        return poDS;
 
     // Use the GDAL copy call
     // Need to flag the dataset as compressed (COMPRESSED=TRUE) to force block writes
@@ -1541,13 +1608,13 @@ GDALDataset *GDALMRFDataset::CreateCopy(const char *pszFilename,
     char **papszCWROptions = NULL;
     papszCWROptions = CSLAddNameValue(papszCWROptions, "COMPRESSED", "TRUE");
     CPLErr err = GDALDatasetCopyWholeRaster((GDALDatasetH)poSrcDS,
-	(GDALDatasetH)poDS, papszCWROptions, pfnProgress, pProgressData);
+        (GDALDatasetH)poDS, papszCWROptions, pfnProgress, pProgressData);
 
     CSLDestroy(papszCWROptions);
 
     if (CE_Failure == err) {
-	delete poDS;
-	return NULL;
+        delete poDS;
+        return NULL;
     }
 
     return poDS;
@@ -1560,15 +1627,13 @@ void GDALMRFDataset::ProcessCreateOptions(char **papszOptions)
     CPLStringList opt(papszOptions, FALSE);
     ILImage &img(full);
 
-    const char *val;
-
-    val = opt.FetchNameValue("COMPRESS");
+    const char *val = opt.FetchNameValue("COMPRESS");
     if (val && IL_ERR_COMP == (img.comp = CompToken(val)))
-	throw CPLString("GDAL MRF: Error setting compression");
+        throw CPLString("GDAL MRF: Error setting compression");
 
     val = opt.FetchNameValue("INTERLEAVE");
     if (val && IL_ERR_ORD == (img.order = OrderToken(val)))
-	throw CPLString("GDAL MRF: Error setting interleave");
+        throw CPLString("GDAL MRF: Error setting interleave");
 
     val = opt.FetchNameValue("QUALITY");
     if (val) img.quality = atoi(val);
@@ -1596,23 +1661,31 @@ void GDALMRFDataset::ProcessCreateOptions(char **papszOptions)
     val = opt.FetchNameValue("PHOTOMETRIC");
     if (val) photometric = val;
 
+    val = opt.FetchNameValue("DATANAME");
+    if (val) img.datfname = val;
+
+    val = opt.FetchNameValue("INDEXNAME");
+    if (val) img.idxfname = val;
+
+    val = opt.FetchNameValue("SPACING");
+    if (val) spacing = atoi(val);
+
     optlist.Assign(CSLTokenizeString2(opt.FetchNameValue("OPTIONS"),
-	" \t\n\r", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES));
+        " \t\n\r", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES));
 
     // General Fixups
     if (img.order == IL_Interleaved)
-	img.pagesize.c = img.size.c;
+        img.pagesize.c = img.size.c;
 
     // Compression dependent fixups
 #if defined(LERC)
     if (IL_LERC == img.comp)
-	img.pagesize.c = 1;
+        img.pagesize.c = 1;
 #endif
-
 }
 
 /**
- *\Brief Create an MRF dataset, some settings can be changed later
+ *\brief Create an MRF dataset, some settings can be changed later
  * papszOptions might be anything that an MRF might take
  * Still missing are the georeference ...
  *
@@ -1641,12 +1714,12 @@ GDALMRFDataset::Create(const char * pszName,
 
     size_t pos = poDS->fname.find(":MRF:");
     if (string::npos != pos) { // Tokenize and pick known options
-	vector<string> tokens;
-	stringSplit(tokens, poDS->fname, pos + 5, ':');
-	//level = getnum(tokens, 'L', -1);
-	//version = getnum(tokens, 'V', 0);
-	poDS->zslice = getnum(tokens, 'Z', 0);
-	poDS->fname.resize(pos); // Cut the ornamentations
+        vector<string> tokens;
+        stringSplit(tokens, poDS->fname, pos + 5, ':');
+        //level = getnum(tokens, 'L', -1);
+        //version = getnum(tokens, 'V', 0);
+        poDS->zslice = getnum(tokens, 'Z', 0);
+        poDS->fname.resize(pos); // Cut the ornamentations
     }
 
     // Use the full, set some initial parameters
@@ -1663,25 +1736,27 @@ GDALMRFDataset::Create(const char * pszName,
     img.nbo = FALSE;
 
     // Set the guard that tells us it needs saving before IO can take place
-    poDS->bCrystalized = 0;
+    poDS->bCrystalized = FALSE;
 
     // Process the options, anything that an MRF might take
 
     try {
-	// Adjust the dataset and the full image
-	poDS->ProcessCreateOptions(papszOptions);
+        // Adjust the dataset and the full image
+        poDS->ProcessCreateOptions(papszOptions);
 
-	// Set default file names
-	img.datfname = getFname(poDS->GetFname(), ILComp_Ext[img.comp]);
-	img.idxfname = getFname(poDS->GetFname(), ".idx");
+        // Set default file names
+        if (img.datfname.empty())
+            img.datfname = getFname(poDS->GetFname(), ILComp_Ext[img.comp]);
+        if (img.idxfname.empty())
+            img.idxfname = getFname(poDS->GetFname(), ".idx");
 
-	poDS->eAccess = GA_Update;
+        poDS->eAccess = GA_Update;
     }
 
-    catch (CPLString e) {
-	CPLError(CE_Failure, CPLE_OpenFailed, "%s", e.c_str());
-	delete poDS;
-	return NULL;
+    catch (const CPLString& e) {
+        CPLError(CE_Failure, CPLE_OpenFailed, "%s", e.c_str());
+        delete poDS;
+        return NULL;
     }
 
     poDS->current = poDS->full;
@@ -1693,8 +1768,8 @@ GDALMRFDataset::Create(const char * pszName,
     CPLDestroyXMLNode(config);
 
     if (CPLE_None != err) {
-	delete poDS;
-	return NULL;
+        delete poDS;
+        return NULL;
     }
 
     // If not set by the band, get a pageSizeBytes buffer
@@ -1717,19 +1792,19 @@ void GDALMRFDataset::Crystalize()
 
 {
     if (bCrystalized || eAccess != GA_Update)
-	return;
+        return;
 
-    // No need to write to disk if there is no filename.  This is a 
+    // No need to write to disk if there is no filename.  This is a
     // memory only dataset.
     if (strlen(GetDescription()) == 0
-	|| EQUALN(GetDescription(), "<MRF_META>", 10))
-	return;
+        || EQUALN(GetDescription(), "<MRF_META>", 10))
+        return;
 
     CPLXMLNode *config = BuildConfig();
     WriteConfig(config);
     CPLDestroyXMLNode(config);
     if (!IdxFP() || !DataFP())
-	throw CPLString().Printf("MRF: Can't create file %s", strerror(errno));
+        throw CPLString().Printf("MRF: Can't create file %s", strerror(errno));
 
     bCrystalized = TRUE;
 }
@@ -1752,7 +1827,7 @@ CPLErr GDALMRFDataset::AddVersion()
 //
 // Write a tile at the end of the data file
 // If buff and size are zero, it is equivalent to erasing the tile
-// If only size is zero, it is a special empty tile, 
+// If only size is zero, it is a special empty tile,
 // when used for caching, offset should be 1
 //
 // To make it multi-processor safe, open the file in append mode
@@ -1770,91 +1845,111 @@ CPLErr GDALMRFDataset::WriteTile(void *buff, GUIntBig infooffset, GUIntBig size)
     void *tbuff = NULL;
 
     if (l_ifp == NULL || l_dfp == NULL)
-	return CE_Failure;
+        return CE_Failure;
 
+    // If it has versions, might need to start a new one
     if (hasVersions) {
-	int new_version = false; // Assume no need to build new version
-	int new_tile = false;
-
-	// Read the current tile info
-	VSIFSeekL(l_ifp, infooffset, SEEK_SET);
-	VSIFReadL(&tinfo, 1, sizeof(ILIdx), l_ifp);
-
-	if (verCount != 0) { // We have at least two versions before we test buffers
-	    ILIdx prevtinfo = { 0, 0 };
-
-	    // Read the previous one
-	    VSIFSeekL(l_ifp, infooffset + verCount * idxSize, SEEK_SET);
-	    VSIFReadL(&prevtinfo, 1, sizeof(ILIdx), l_ifp);
-
-	    // current and previous tiles are different, might create version
-	    if (tinfo.size != prevtinfo.size || tinfo.offset != prevtinfo.offset)
-		new_version = true;
-	}
-	else
-	    new_version = true; // No previous, might create version
-
-	// tinfo contains the current info or 0,0
-	if (tinfo.size == GIntBig(net64(size))) { // Might be the same, read and compare
-	    if (size != 0) {
-		tbuff = CPLMalloc(static_cast<size_t>(size));
-		// Use the temporary buffer, we can't have a versioned cache !!
-		VSIFSeekL(l_dfp, infooffset, SEEK_SET);
-		VSIFReadL(tbuff, 1, static_cast<size_t>(size), l_dfp);
-		// Need to write it if not the same
-		new_tile = (0 != memcmp(buff, tbuff, static_cast<size_t>(size)));
-		CPLFree(tbuff);
+        int new_version = false; // Assume no need to build new version
+        int new_tile = false;
+
+        // Read the current tile info
+        VSIFSeekL(l_ifp, infooffset, SEEK_SET);
+        VSIFReadL(&tinfo, 1, sizeof(ILIdx), l_ifp);
+
+        if (verCount != 0) { // We need at least two versions before we test buffers
+            ILIdx prevtinfo = { 0, 0 };
+
+            // Read the previous one
+            VSIFSeekL(l_ifp, infooffset + verCount * idxSize, SEEK_SET);
+            VSIFReadL(&prevtinfo, 1, sizeof(ILIdx), l_ifp);
+
+            // current and previous tiles are different, might create version
+            if (tinfo.size != prevtinfo.size || tinfo.offset != prevtinfo.offset)
+                new_version = true;
+        }
+        else
+            new_version = true; // No previous, might create version
+
+        // tinfo contains the current info or 0,0
+        if (tinfo.size == GIntBig(net64(size))) { // Might be the same, read and compare
+            if (size != 0) {
+                tbuff = CPLMalloc(static_cast<size_t>(size));
+                // Use the temporary buffer, we can't have a versioned cache !!
+                VSIFSeekL(l_dfp, infooffset, SEEK_SET);
+                VSIFReadL(tbuff, 1, static_cast<size_t>(size), l_dfp);
+                // Need to write it if not the same
+                new_tile = (0 != memcmp(buff, tbuff, static_cast<size_t>(size)));
+                CPLFree(tbuff);
                 tbuff = NULL;
-	    }
-	    else {
-		// Writing a null tile on top of a null tile, does it count?
-		if (tinfo.offset != GIntBig(net64(GUIntBig(buff))))
-		    new_tile = true;
-	    }
-	}
-	else {
-	    new_tile = true; // Need to write it because it is different
-	    if (verCount == 0 && tinfo.size == 0)
-		new_version = false; // Don't create a version if current is empty and there is no previous
-	}
-
-	if (!new_tile)
-	    return CE_None; // No reason to write
-
-	// Do we need to start a new version before writing the tile?
-	if (new_version)
-	    AddVersion();
+            }
+            else {
+                // Writing a null tile on top of a null tile, does it count?
+                if (tinfo.offset != GIntBig(net64(GUIntBig(buff))))
+                    new_tile = true;
+            }
+        }
+        else {
+            new_tile = true; // Need to write it because it is different
+            if (verCount == 0 && tinfo.size == 0)
+                new_version = false; // Don't create a version if current is empty and there is no previous
+        }
+
+        if (!new_tile)
+            return CE_None; // No reason to write
+
+        // Do we need to start a new version before writing the tile?
+        if (new_version)
+            AddVersion();
     }
 
     // Convert to net format
     tinfo.size = net64(size);
 
     if (size) do {
-	// These statements are the critical MP section for the data file
-	VSIFSeekL(l_dfp, 0, SEEK_END);
-	GUIntBig offset = VSIFTellL(l_dfp);
-	if (static_cast<size_t>(size) != VSIFWriteL(buff, 1, static_cast<size_t>(size), l_dfp))
-	    ret = CE_Failure;
-
-	tinfo.offset = net64(offset);
-	//
-	// For MP ops, check that we can read it back properly, otherwise we're done
-	// This makes the caching MRF MP safe, without using explicit locks
-	//
-	if (mp_safe) {
-	    // Allocate the temp buffer if we haven't done so already
-	    if (!tbuff)
-		tbuff = CPLMalloc(static_cast<size_t>(size));
-	    VSIFSeekL(l_dfp, offset, SEEK_SET);
-	    VSIFReadL(tbuff, 1, static_cast<size_t>(size), l_dfp);
-	    // If memcmp returns zero, verify passed
-	    if (!memcmp(buff, tbuff, static_cast<size_t>(size))) {
-		CPLFree(tbuff);
-		tbuff = NULL; // Triggers the loop termination
-	    }
-	    // Otherwise the tbuf stays allocated and try to write again
-	    // This works only if the file is opened in append mode
-	}
+
+        // These statements are the critical MP section for the data file
+        VSIFSeekL(l_dfp, 0, SEEK_END);
+        GUIntBig offset = VSIFTellL(l_dfp);
+
+        if( spacing != 0 )
+        {
+            // This should not be true in MP safe mode.
+            // Use the same buffer, MRF doesn't care about the spacing content.
+            // TODO(lplesea): Make sure size doesn't overflow.
+            const int pad =
+                static_cast<int>(size) >= spacing
+                ? spacing
+                : static_cast<int>(size);
+            if( pad != spacing )
+                CPLError(CE_Warning, CPLE_FileIO,
+                         "MRF spacing failed, check the output");
+            offset += pad;
+            VSIFWriteL(buff, 1, spacing, l_dfp);
+        }
+
+        if (static_cast<size_t>(size) != VSIFWriteL(buff, 1, static_cast<size_t>(size), l_dfp))
+            ret = CE_Failure;
+        // End of critical section
+
+        tinfo.offset = net64(offset);
+        //
+        // For MP ops, check that we can read it back properly, otherwise we're done
+        // This makes the caching MRF MP safe, without using explicit locks
+        //
+        if (mp_safe) {
+            // Allocate the temp buffer if we haven't done so already
+            if (!tbuff)
+                tbuff = CPLMalloc(static_cast<size_t>(size));
+            VSIFSeekL(l_dfp, offset, SEEK_SET);
+            VSIFReadL(tbuff, 1, static_cast<size_t>(size), l_dfp);
+            // If memcmp returns zero, verify passed
+            if (!memcmp(buff, tbuff, static_cast<size_t>(size))) {
+                CPLFree(tbuff);
+                tbuff = NULL; // Triggers the loop termination
+            }
+            // Otherwise the tbuf stays allocated and try to write again
+            // This works only if the file is opened in append mode
+        }
     } while (tbuff);
 
     // At this point, the data is in the datafile
@@ -1862,11 +1957,11 @@ CPLErr GDALMRFDataset::WriteTile(void *buff, GUIntBig infooffset, GUIntBig size)
     // Special case
     // Any non-zero will do, use 1 to only consume one bit
     if (NULL != buff && 0 == size)
-	tinfo.offset = net64(GUIntBig(buff));
+        tinfo.offset = net64(GUIntBig(buff));
 
     VSIFSeekL(l_ifp, infooffset, SEEK_SET);
     if (sizeof(tinfo) != VSIFWriteL(&tinfo, 1, sizeof(tinfo), l_ifp))
-	ret = CE_Failure;
+        ret = CE_Failure;
 
     return ret;
 }
@@ -1876,22 +1971,29 @@ CPLErr GDALMRFDataset::SetGeoTransform(double *gt)
 {
     if (GetAccess() == GA_Update)
     {
-	memcpy(GeoTransform, gt, 6 * sizeof(double));
-	bGeoTransformValid = TRUE;
-	return CE_None;
+        memcpy(GeoTransform, gt, 6 * sizeof(double));
+        bGeoTransformValid = TRUE;
+        return CE_None;
     }
     CPLError(CE_Failure, CPLE_NotSupported,
-	"SetGeoTransform called on read only file");
+        "SetGeoTransform called on read only file");
     return CE_Failure;
 }
 
+bool GDALMRFDataset::IsSingleTile()
+{
+    if (current.pagecount.l != 1 || !source.empty() || NULL == DataFP())
+        return FALSE;
+    return 0 == reinterpret_cast<GDALMRFRasterBand *>(GetRasterBand(1))->GetOverviewCount();
+}
+
 /*
 *  Returns 0,1,0,0,0,1 even if it was not set
 */
 CPLErr GDALMRFDataset::GetGeoTransform(double *gt)
 {
     memcpy(gt, GeoTransform, 6 * sizeof(double));
-    if (GetMetadata("RPC") || GetGCPCount()) 
+    if (GetMetadata("RPC") || GetGCPCount())
         bGeoTransformValid = FALSE;
     if (!bGeoTransformValid) return CE_Failure;
     return CE_None;
@@ -1908,27 +2010,39 @@ CPLErr GDALMRFDataset::ReadTileIdx(ILIdx &tinfo, const ILSize &pos, const ILImag
 
 {
     VSILFILE *l_ifp = IdxFP();
+
     GIntBig offset = bias + IdxOffset(pos, img);
-    if (l_ifp == NULL && img.comp == IL_NONE) {
-	tinfo.size = current.pageSizeBytes;
-	tinfo.offset = offset * tinfo.size;
-	return CE_None;
+    if (l_ifp == NULL && img.comp == IL_NONE ) {
+        tinfo.size = current.pageSizeBytes;
+        tinfo.offset = offset * tinfo.size;
+        return CE_None;
+    }
+
+    if (l_ifp == NULL && IsSingleTile()) {
+        tinfo.offset = 0;
+        VSILFILE *l_dfp = DataFP(); // IsSingleTile() checks that fp is valid
+        VSIFSeekL(l_dfp, 0, SEEK_END);
+        tinfo.size = VSIFTellL(l_dfp);
+
+        // It should be less than the pagebuffer
+        tinfo.size = std::min(tinfo.size, static_cast<GIntBig>(pbsize));
+        return CE_None;
     }
 
     if (l_ifp == NULL) {
-	CPLError(CE_Failure, CPLE_FileIO, "Can't open index file");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_FileIO, "Can't open index file");
+        return CE_Failure;
     }
 
     VSIFSeekL(l_ifp, offset, SEEK_SET);
     if (1 != VSIFReadL(&tinfo, sizeof(ILIdx), 1, l_ifp))
-	return CE_Failure;
+        return CE_Failure;
     // Convert them to native form
     tinfo.offset = net64(tinfo.offset);
     tinfo.size = net64(tinfo.size);
 
     if (0 == bias || 0 != tinfo.size || 0 != tinfo.offset)
-	return CE_None;
+        return CE_None;
 
     // zero size and zero offset in sourced index means that this portion is un-initialized
 
@@ -1937,18 +2051,16 @@ CPLErr GDALMRFDataset::ReadTileIdx(ILIdx &tinfo, const ILSize &pos, const ILImag
     assert(offset < bias);
     assert(clonedSource);
 
-
     // Read this block from the remote index, prepare it and store it in the right place
     // The block size in bytes, should be a multiple of 16, to have full index entries
     const int CPYSZ = 32768;
     // Adjust offset to the start of the block
     offset = (offset / CPYSZ) * CPYSZ;
-    GIntBig size = MIN(size_t(CPYSZ), size_t(bias - offset));
+    GIntBig size = std::min(size_t(CPYSZ), size_t(bias - offset));
     size /= sizeof(ILIdx); // In records
     vector<ILIdx> buf(static_cast<size_t>(size));
     ILIdx *buffer = &buf[0]; // Buffer to copy the source to the clone index
 
-
     // Fetch the data from the cloned index
     GDALMRFDataset *pSrc = static_cast<GDALMRFDataset *>(GetSrcDS());
     if( pSrc == NULL )
@@ -1959,29 +2071,29 @@ CPLErr GDALMRFDataset::ReadTileIdx(ILIdx &tinfo, const ILSize &pos, const ILImag
 
     VSILFILE *srcidx = pSrc->IdxFP();
     if (!srcidx) {
-	CPLError(CE_Failure, CPLE_FileIO, "Can't open cloned source index");
-	return CE_Failure; // Source reported the error
+        CPLError(CE_Failure, CPLE_FileIO, "Can't open cloned source index");
+        return CE_Failure; // Source reported the error
     }
 
     VSIFSeekL(srcidx, offset, SEEK_SET);
     size = VSIFReadL(buffer, sizeof(ILIdx), static_cast<size_t>(size), srcidx);
     if (size != GIntBig(buf.size())) {
-	CPLError(CE_Failure, CPLE_FileIO, "Can't read cloned source index");
-	return CE_Failure; // Source reported the error
+        CPLError(CE_Failure, CPLE_FileIO, "Can't read cloned source index");
+        return CE_Failure; // Source reported the error
     }
 
     // Mark the empty records as checked, by making the offset non-zero
-    for (vector<ILIdx>::iterator it = buf.begin(); it != buf.end(); it++) {
-	if (it->offset == 0 && it->size == 0)
-	    it->offset = net64(1);
+    for (vector<ILIdx>::iterator it = buf.begin(); it != buf.end(); ++it) {
+        if (it->offset == 0 && it->size == 0)
+            it->offset = net64(1);
     }
 
     // Write it in the right place in the local index file
     VSIFSeekL(l_ifp, bias + offset, SEEK_SET);
     size = VSIFWriteL(&buf[0], sizeof(ILIdx), static_cast<size_t>(size), l_ifp);
     if (size != GIntBig(buf.size())) {
-	CPLError(CE_Failure, CPLE_FileIO, "Can't write to cloning MRF index");
-	return CE_Failure; // Source reported the error
+        CPLError(CE_Failure, CPLE_FileIO, "Can't write to cloning MRF index");
+        return CE_Failure; // Source reported the error
     }
 
     // Cloned index updated, restart this function, it will work now
diff --git a/frmts/mrf/mrf_band.cpp b/frmts/mrf/mrf_band.cpp
index af28cf1..c904aa4 100644
--- a/frmts/mrf/mrf_band.cpp
+++ b/frmts/mrf/mrf_band.cpp
@@ -4,18 +4,18 @@
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-*   2. Redistributions in binary form must reproduce the above copyright notice, 
+*   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL), 
-*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to 
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
 *      endorse or promote products derived from this software without specific prior written permission.
 *
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
-* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
-* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
-* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Copyright 2014-2015 Esri
@@ -33,21 +33,13 @@
 * limitations under the License.
 */
 
-
 /******************************************************************************
-* $Id$
 *
 * Project:  Meta Raster File Format Driver Implementation, RasterBand
 * Purpose:  Implementation of Pile of Tile Format
 *
 * Author:   Lucian Plesea, Lucian.Plesea at jpl.nasa.gov, lplesea at esri.com
 *
-******************************************************************************
-*
-*
-* 
-*
-* 
 ****************************************************************************/
 
 #include "marfa.h"
@@ -59,6 +51,8 @@
 #include <assert.h>
 #include "../zlib/zlib.h"
 
+CPL_CVSID("$Id: mrf_band.cpp 37663 2017-03-09 20:42:19Z lplesea $");
+
 using std::vector;
 using std::string;
 
@@ -68,27 +62,25 @@ NAMESPACE_MRF_START
 // Count is the number of items that need to be copied
 // These are separate to allow for optimization
 
-template <typename T> void cpy_stride_in(void *dst, 
-	const void *src, int c, int stride)
+template <typename T> static void cpy_stride_in(void *dst, void *src, int c, int stride)
 {
-    T *s=(T *)src;
-    T *d=(T *)dst;
+    T *s = reinterpret_cast<T *>(src);
+    T *d = reinterpret_cast<T *>(dst);
 
     while (c--) {
-	*d++=*s;
-	s+=stride;
+        *d++ = *s;
+        s += stride;
     }
 }
 
-template <typename T> void cpy_stride_out(void *dst, 
-	const void *src, int c, int stride)
+template <typename T> static void cpy_stride_out(void *dst, void *src, int c, int stride)
 {
-    T *s=(T *)src;
-    T *d=(T *)dst;
+    T *s = reinterpret_cast<T *>(src);
+    T *d = reinterpret_cast<T *>(dst);
 
     while (c--) {
-	*d=*s++;
-	d+=stride;
+        *d = *s++;
+        d += stride;
     }
 }
 
@@ -96,7 +88,7 @@ template <typename T> void cpy_stride_out(void *dst,
 template<typename T> inline int isAllVal(const T *b, size_t bytecount, double ndv)
 
 {
-    T val = (T)(ndv);
+    T val = static_cast<T>(ndv);
     size_t count = bytecount / sizeof(T);
     while (count--) {
         if (*(b++) != val) {
@@ -113,20 +105,20 @@ static int isAllVal(GDALDataType gt, void *b, size_t bytecount, double ndv)
     int isempty = false;
 
     // A case branch in a temporary macro, conversion from gdal enum to type
-#define TEST_T(GType, type)\
+#define TEST_T(GType, T)\
     case GType: \
-	isempty = isAllVal((type *)b, bytecount, ndv);\
-	break
+        isempty = isAllVal(reinterpret_cast<T *>(b), bytecount, ndv);\
+        break
 
     switch (gt) {
-	TEST_T(GDT_Byte, GByte);
-	TEST_T(GDT_UInt16, GUInt16);
-	TEST_T(GDT_Int16, GInt16);
-	TEST_T(GDT_UInt32, GUInt32);
-	TEST_T(GDT_Int32, GInt32);
-	TEST_T(GDT_Float32, float);
-	TEST_T(GDT_Float64, double);
-	default : break;
+        TEST_T(GDT_Byte, GByte);
+        TEST_T(GDT_UInt16, GUInt16);
+        TEST_T(GDT_Int16, GInt16);
+        TEST_T(GDT_UInt32, GUInt32);
+        TEST_T(GDT_Int32, GInt32);
+        TEST_T(GDT_Float32, float);
+        TEST_T(GDT_Float64, double);
+        default : break;
     }
 #undef TEST_T
 
@@ -139,22 +131,22 @@ static void swab_buff(buf_mgr &src, const ILImage &img)
     size_t i;
     switch (GDALGetDataTypeSize(img.dt)) {
     case 16: {
-	short int *b = (short int*)src.buffer;
-	for (i = src.size / 2; i; b++, i--)
-	    *b = swab16(*b);
-	break;
+        short int *b = (short int*)src.buffer;
+        for (i = src.size / 2; i; b++, i--)
+            *b = swab16(*b);
+        break;
     }
     case 32: {
-	int *b = (int*)src.buffer;
-	for (i = src.size / 4; i; b++, i--)
-	    *b = swab32(*b);
-	break;
+        int *b = (int*)src.buffer;
+        for (i = src.size / 4; i; b++, i--)
+            *b = swab32(*b);
+        break;
     }
     case 64: {
-	long long *b = (long long*)src.buffer;
-	for (i = src.size / 8; i; b++, i--)
-	    *b = swab64(*b);
-	break;
+        long long *b = (long long*)src.buffer;
+        for (i = src.size / 8; i; b++, i--)
+            *b = swab64(*b);
+        break;
     }
     }
 }
@@ -175,45 +167,48 @@ static void *DeflateBlock(buf_mgr &src, size_t extrasize, int flags) {
     // Allocate a temp buffer if there is not sufficient space,
     // We need to have a bit more than half the buffer available
     if (extrasize < (src.size + 64)) {
-	dst.size = src.size + 64;
+        dst.size = src.size + 64;
 
-	dbuff = VSIMalloc(dst.size);
-	dst.buffer = (char *)dbuff;
-	if (!dst.buffer)
-	    return NULL;
+        dbuff = VSIMalloc(dst.size);
+        dst.buffer = (char *)dbuff;
+        if (!dst.buffer)
+            return NULL;
     }
 
     if (!ZPack(src, dst, flags)) {
-	CPLFree(dbuff); // Safe to call with NULL
-	return NULL;
+        CPLFree(dbuff); // Safe to call with NULL
+        return NULL;
     }
 
     // source size is used to hold the output size
     src.size = dst.size;
     // If we didn't allocate a buffer, the receiver can use it already
-    if (!dbuff) 
-	return dst.buffer;
+    if (!dbuff)
+        return dst.buffer;
 
-    // If we allocated a buffer, we need to copy the data to the input buffer 
+    // If we allocated a buffer, we need to copy the data to the input buffer.
     memcpy(src.buffer, dbuff, src.size);
     CPLFree(dbuff);
     return src.buffer;
 }
 
 //
-// The deflate_flags are available in all bands even if the DEFLATE option 
+// The deflate_flags are available in all bands even if the DEFLATE option
 // itself is not set.  This allows for PNG features to be controlled, as well
 // as any other bands that use zlib by itself
 //
-GDALMRFRasterBand::GDALMRFRasterBand(GDALMRFDataset *parent_dataset,
-					const ILImage &image, int band, int ov)
+GDALMRFRasterBand::GDALMRFRasterBand( GDALMRFDataset *parent_dataset,
+                                      const ILImage &image, int band, int ov ) :
+    poDS(parent_dataset),
+    deflatep(GetOptlist().FetchBoolean("DEFLATE", FALSE)),
+    // Bring the quality to 0 to 9
+    deflate_flags(image.quality / 10),
+    m_l(ov),
+    img(image),
+    overview(0)
 {
-    poDS=parent_dataset;
-    nBand=band;
-    m_band=band-1;
-    m_l=ov;
-    img=image;
-    eDataType=parent_dataset->current.dt;
+    nBand = band;
+    eDataType = parent_dataset->current.dt;
     nRasterXSize = img.size.x;
     nRasterYSize = img.size.y;
     nBlockXSize = img.pagesize.x;
@@ -222,37 +217,35 @@ GDALMRFRasterBand::GDALMRFRasterBand(GDALMRFDataset *parent_dataset,
     nBlocksPerColumn = img.pagecount.y;
     img.NoDataValue = GetNoDataValue(&img.hasNoData);
 
-    deflatep = GetOptlist().FetchBoolean("DEFLATE", FALSE);
-    // Bring the quality to 0 to 9
-    deflate_flags = img.quality / 10;
     // Pick up the twists, aka GZ, RAWZ headers
-    if (GetOptlist().FetchBoolean("GZ", FALSE))
-	deflate_flags |= ZFLAG_GZ;
-    else if (GetOptlist().FetchBoolean("RAWZ", FALSE))
-	deflate_flags |= ZFLAG_RAW;
+    if( GetOptlist().FetchBoolean("GZ", FALSE) )
+        deflate_flags |= ZFLAG_GZ;
+    else if( GetOptlist().FetchBoolean("RAWZ", FALSE) )
+        deflate_flags |= ZFLAG_RAW;
     // And Pick up the ZLIB strategy, if any
     const char *zstrategy = GetOptlist().FetchNameValueDef("Z_STRATEGY", NULL);
-    if (zstrategy) {
-	int zv = Z_DEFAULT_STRATEGY;
-	if (EQUAL(zstrategy, "Z_HUFFMAN_ONLY"))
-	    zv = Z_HUFFMAN_ONLY;
-	else if (EQUAL(zstrategy, "Z_RLE"))
-	    zv = Z_RLE;
-	else if (EQUAL(zstrategy, "Z_FILTERED"))
-	    zv = Z_FILTERED;
-	else if (EQUAL(zstrategy, "Z_FIXED"))
-	    zv = Z_FIXED;
-	deflate_flags |= (zv << 6);
-    }
-    overview = 0;
+    if( zstrategy )
+    {
+        int zv = Z_DEFAULT_STRATEGY;
+        if (EQUAL(zstrategy, "Z_HUFFMAN_ONLY"))
+            zv = Z_HUFFMAN_ONLY;
+        else if (EQUAL(zstrategy, "Z_RLE"))
+            zv = Z_RLE;
+        else if (EQUAL(zstrategy, "Z_FILTERED"))
+            zv = Z_FILTERED;
+        else if (EQUAL(zstrategy, "Z_FIXED"))
+            zv = Z_FIXED;
+        deflate_flags |= (zv << 6);
+    }
 }
 
 // Clean up the overviews if they exist
 GDALMRFRasterBand::~GDALMRFRasterBand()
 {
-    while (0!=overviews.size()) {
-	delete overviews[overviews.size()-1];
-	overviews.pop_back();
+    while( !overviews.empty() )
+    {
+        delete overviews.back();
+        overviews.pop_back();
     };
 }
 
@@ -269,7 +262,7 @@ const char * GDALMRFRasterBand::GetOptionValue(const char *opt, const char *def)
 static double getBandValue(std::vector<double> &v,int idx)
 {
     if (static_cast<int>(v.size()) > idx)
-	return v[idx];
+        return v[idx];
     return v[0];
 }
 
@@ -280,12 +273,12 @@ static double getBandValue(std::vector<double> &v,int idx)
 CPLErr  GDALMRFRasterBand::SetNoDataValue(double val)
 {
     if (poDS->bCrystalized) {
-	CPLError(CE_Failure, CPLE_AssertionFailed, "MRF: NoData can be set only during file create");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AssertionFailed, "MRF: NoData can be set only during file create");
+        return CE_Failure;
     }
     if (GInt32(poDS->vNoData.size()) < nBand)
-	poDS->vNoData.resize(nBand);
-    poDS->vNoData[m_band] = val;
+        poDS->vNoData.resize(nBand);
+    poDS->vNoData[nBand - 1] = val;
     // We also need to set it for this band
     img.NoDataValue = val;
     img.hasNoData = true;
@@ -295,37 +288,37 @@ CPLErr  GDALMRFRasterBand::SetNoDataValue(double val)
 double GDALMRFRasterBand::GetNoDataValue(int *pbSuccess)
 {
     std::vector<double> &v=poDS->vNoData;
-    if (v.size() == 0)
-	return GDALPamRasterBand::GetNoDataValue(pbSuccess);
+    if (v.empty())
+        return GDALPamRasterBand::GetNoDataValue(pbSuccess);
     if (pbSuccess) *pbSuccess=TRUE;
-    return getBandValue(v, m_band);
+    return getBandValue(v, nBand - 1);
 }
 
 double GDALMRFRasterBand::GetMinimum(int *pbSuccess)
 {
     std::vector<double> &v=poDS->vMin;
-    if (v.size() == 0)
-	return GDALPamRasterBand::GetMinimum(pbSuccess);
+    if (v.empty())
+        return GDALPamRasterBand::GetMinimum(pbSuccess);
     if (pbSuccess) *pbSuccess=TRUE;
-    return getBandValue(v, m_band);
+    return getBandValue(v, nBand - 1);
 }
 
 double GDALMRFRasterBand::GetMaximum(int *pbSuccess)
 {
     std::vector<double> &v=poDS->vMax;
-    if (v.size() == 0)
-	return GDALPamRasterBand::GetMaximum(pbSuccess);
+    if (v.empty())
+        return GDALPamRasterBand::GetMaximum(pbSuccess);
     if (pbSuccess) *pbSuccess=TRUE;
-    return getBandValue(v, m_band);
+    return getBandValue(v, nBand - 1);
 }
 
-// Fill, with ndv
-template<typename T> CPLErr buff_fill(void *b, size_t count, const T ndv)
+// Fill with typed ndv, count is always in bytes
+template<typename T> static CPLErr buff_fill(void *b, size_t count, const T ndv)
 {
     T *buffer = static_cast<T*>(b);
     count /= sizeof(T);
     while (count--)
-	*buffer++ = ndv;
+        *buffer++ = ndv;
     return CE_None;
 }
 
@@ -343,19 +336,19 @@ CPLErr GDALMRFRasterBand::FillBlock(void *buffer)
 
     // use memset for speed for bytes, or if nodata is zeros
     if (eDataType == GDT_Byte || 0.0L == ndv ) {
-	memset(buffer, int(ndv), bsb);
-	return CE_None;
+        memset(buffer, int(ndv), bsb);
+        return CE_None;
     }
 
 #define bf(T) buff_fill<T>(buffer, bsb, T(ndv));
     switch(eDataType) {
-	case GDT_UInt16:    return bf(GUInt16);
-	case GDT_Int16:     return bf(GInt16);
-	case GDT_UInt32:    return bf(GUInt32);
-	case GDT_Int32:     return bf(GInt32);
-	case GDT_Float32:   return bf(float);
-	case GDT_Float64:   return bf(double);
-	default: break;
+        case GDT_UInt16:    return bf(GUInt16);
+        case GDT_Int16:     return bf(GInt16);
+        case GDT_UInt32:    return bf(GUInt32);
+        case GDT_Int32:     return bf(GInt32);
+        case GDT_Float32:   return bf(float);
+        case GDT_Float64:   return bf(double);
+        default: break;
     }
 #undef bf
     // Should exit before
@@ -372,77 +365,76 @@ CPLErr GDALMRFRasterBand::RB(int xblk, int yblk, buf_mgr /*src*/, void *buffer)
     vector<GDALRasterBlock *> blocks;
 
     for (int i = 0; i < poDS->nBands; i++) {
-	GDALRasterBand *b = poDS->GetRasterBand(i+1);
-	if (b->GetOverviewCount() && m_l)
-	    b = b->GetOverview(m_l-1);
-
-	void *ob = buffer;
-	// Get the other band blocks, keep them around until later
-	if (b != this)
-	{
-	    GDALRasterBlock *poBlock = b->GetLockedBlockRef(xblk, yblk, 1);
+        GDALRasterBand *b = poDS->GetRasterBand(i+1);
+        if (b->GetOverviewCount() && 0 != m_l)
+            b = b->GetOverview(m_l-1);
+
+        void *ob = buffer;
+        // Get the other band blocks, keep them around until later
+        if (b != this)
+        {
+            GDALRasterBlock *poBlock = b->GetLockedBlockRef(xblk, yblk, 1);
             if( poBlock == NULL )
                 break;
-	    ob = poBlock->GetDataRef();
-	    blocks.push_back(poBlock);
-	} 
+            ob = poBlock->GetDataRef();
+            blocks.push_back(poBlock);
+        }
 
 // Just the right mix of templates and macros make deinterleaving tidy
-#define CpySI(T) cpy_stride_in<T> (ob, (T *)poDS->GetPBuffer() + i,\
+#define CpySI(T) cpy_stride_in<T> (ob, reinterpret_cast<T *>(poDS->GetPBuffer()) + i,\
     blockSizeBytes()/sizeof(T), img.pagesize.c)
 
-	// Page is already in poDS->pbuffer, not empty
-	// There are only four cases, since only the real data type matters
-	switch (GDALGetDataTypeSize(eDataType)/8)
-	{
-	case 1: CpySI(GByte); break;
-	case 2: CpySI(GInt16); break;
-	case 4: CpySI(GInt32); break;
-	case 8: CpySI(GIntBig); break;
-	}
+        // Page is already in poDS->pbuffer, not empty
+        // There are only four cases, since only the data size matters
+        switch (GDALGetDataTypeSize(eDataType)/8)
+        {
+        case 1: CpySI(GByte); break;
+        case 2: CpySI(GInt16); break;
+        case 4: CpySI(GInt32); break;
+        case 8: CpySI(GIntBig); break;
+        }
     }
 
 #undef CpySI
 
     // Drop the locks we acquired
     for (int i=0; i < int(blocks.size()); i++)
-	blocks[i]->DropLock();
+        blocks[i]->DropLock();
 
     return CE_None;
 }
 
-
 /**
 *\brief Fetch a block from the backing store dataset and keep a copy in the cache
 *
-* @xblk The X block number, zero based
-* @yblk The Y block number, zero based
-* @param tinfo The return, updated tinfo for this specific tile
+* @param xblk The X block number, zero based
+* @param yblk The Y block number, zero based
+* @param buffer buffer
 *
 */
 CPLErr GDALMRFRasterBand::FetchBlock(int xblk, int yblk, void *buffer)
-
 {
     assert(!poDS->source.empty());
-    CPLDebug("MRF_IB", "FetchBlock %d,%d,0,%d, level  %d\n", xblk, yblk, m_band, m_l);
+    CPLDebug("MRF_IB", "FetchBlock %d,%d,0,%d, level  %d\n", xblk, yblk, nBand, m_l);
 
     if (poDS->clonedSource)  // This is a clone
-	return FetchClonedBlock(xblk, yblk, buffer);
+        return FetchClonedBlock(xblk, yblk, buffer);
 
-    GDALDataset *poSrcDS;
     const GInt32 cstride = img.pagesize.c; // 1 if band separate
-    ILSize req(xblk, yblk, 0, m_band / cstride, m_l);
+    ILSize req(xblk, yblk, 0, (nBand-1) / cstride, m_l);
     GUIntBig infooffset = IdxOffset(req, img);
 
+    GDALDataset *poSrcDS = NULL;
     if ( NULL == (poSrcDS = poDS->GetSrcDS())) {
-	CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't open source file %s", poDS->source.c_str());
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "MRF: Can't open source file %s", poDS->source.c_str());
+        return CE_Failure;
     }
 
     // Scale to base resolution
     double scl = pow(poDS->scale, m_l);
     if ( 0 == m_l )
-	scl = 1; // To allow for precision issues
+        scl = 1; // To allow for precision issues
 
     // Prepare parameters for RasterIO, they might be different from a full page
     int vsz = GDALGetDataTypeSize(eDataType)/8;
@@ -454,34 +446,34 @@ CPLErr GDALMRFRasterBand::FetchBlock(int xblk, int yblk, void *buffer)
     // Compare with the full size and clip to the right and bottom if needed
     int clip=0;
     if (Xoff + readszx > poDS->full.size.x) {
-	clip |= 1;
-	readszx = poDS->full.size.x - Xoff;
+        clip |= 1;
+        readszx = poDS->full.size.x - Xoff;
     }
     if (Yoff + readszy > poDS->full.size.y) {
-	clip |= 1;
-	readszy = poDS->full.size.y - Yoff;
+        clip |= 1;
+        readszy = poDS->full.size.y - Yoff;
     }
 
     // This is where the whole page fits
     void *ob = buffer;
-    if (cstride != 1) 
-	ob = poDS->GetPBuffer();
+    if (cstride != 1)
+        ob = poDS->GetPBuffer();
 
     // Fill buffer with NoData if clipping
     if (clip)
-	FillBlock(ob);
+        FillBlock(ob);
 
     // Use the dataset RasterIO to read one or all bands if interleaved
     CPLErr ret = poSrcDS->RasterIO(GF_Read, Xoff, Yoff, readszx, readszy,
-	ob, pcount(readszx, int(scl)), pcount(readszy, int(scl)),
-	eDataType, cstride, (1 == cstride)? &nBand: NULL,
-	vsz * cstride, 	// pixel, line, band stride
-	vsz * cstride * img.pagesize.x,
-	(cstride != 1) ? vsz : vsz * img.pagesize.x * img.pagesize.y
+        ob, pcount(readszx, int(scl)), pcount(readszy, int(scl)),
+        eDataType, cstride, (1 == cstride)? &nBand: NULL,
+        vsz * cstride,  // pixel, line, band stride
+        vsz * cstride * img.pagesize.x,
+        (cstride != 1) ? vsz : vsz * img.pagesize.x * img.pagesize.y
 #if GDAL_VERSION_MAJOR >= 2
-	,NULL
+        ,NULL
 #endif
-	);
+        );
 
     if (ret != CE_None) return ret;
 
@@ -492,9 +484,9 @@ CPLErr GDALMRFRasterBand::FetchBlock(int xblk, int yblk, void *buffer)
     filesrc.size = static_cast<size_t>(img.pageSizeBytes);
 
     if (poDS->bypass_cache) { // No local caching, just return the data
-	if (1 == cstride)
-	    return CE_None;
-	return RB(xblk, yblk, filesrc, buffer);
+        if (1 == cstride)
+            return CE_None;
+        return RB(xblk, yblk, filesrc, buffer);
     }
 
     // Test to see if it needs to be written, or just marked as checked
@@ -504,9 +496,9 @@ CPLErr GDALMRFRasterBand::FetchBlock(int xblk, int yblk, void *buffer)
 
     // TODO: test band by band if data is interleaved
     if (isAllVal(eDataType, ob, img.pageSizeBytes, val)) {
-	// Mark it empty and checked, ignore the possible write error
-	poDS->WriteTile((void *)1, infooffset, 0);
-	return CE_None;
+        // Mark it empty and checked, ignore the possible write error
+        poDS->WriteTile((void *)1, infooffset, 0);
+        return CE_None;
     }
 
     // Write the page in the local cache
@@ -515,10 +507,10 @@ CPLErr GDALMRFRasterBand::FetchBlock(int xblk, int yblk, void *buffer)
     void *outbuff = VSIMalloc(poDS->pbsize);
 
     if (!outbuff) {
-	CPLError(CE_Failure, CPLE_AppDefined, 
-	    "Can't get buffer for writing page");
-	// This is not really an error for a cache, the data is fine
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "Can't get buffer for writing page");
+        // This is not really an error for a cache, the data is fine
+        return CE_Failure;
     }
 
     buf_mgr filedst={(char *)outbuff, poDS->pbsize};
@@ -527,11 +519,11 @@ CPLErr GDALMRFRasterBand::FetchBlock(int xblk, int yblk, void *buffer)
     // Where the output is, in case we deflate
     void *usebuff = outbuff;
     if (deflatep) {
-	usebuff = DeflateBlock( filedst, poDS->pbsize - filedst.size, deflate_flags);
-	if (!usebuff) {
-	    CPLError(CE_Failure,CPLE_AppDefined, "MRF: Deflate error");
-	    return CE_Failure;
-	}
+        usebuff = DeflateBlock( filedst, poDS->pbsize - filedst.size, deflate_flags);
+        if (!usebuff) {
+            CPLError(CE_Failure,CPLE_AppDefined, "MRF: Deflate error");
+            return CE_Failure;
+        }
     }
 
     // Write and update the tile index
@@ -540,54 +532,53 @@ CPLErr GDALMRFRasterBand::FetchBlock(int xblk, int yblk, void *buffer)
 
     // If we hit an error or if unpaking is not needed
     if (ret != CE_None || cstride == 1)
-	return ret;
+        return ret;
 
     // data is already in filesrc buffer, deinterlace it in pixel blocks
     return RB(xblk, yblk, filesrc, buffer);
 }
 
-
 /**
 *\brief Fetch for a cloned MRF
 *
-* @xblk The X block number, zero based
-* @yblk The Y block number, zero based
-* @param tinfo The return, updated tinfo for this specific tile
+* @param xblk The X block number, zero based
+* @param yblk The Y block number, zero based
+* @param buffer buffer
 *
 */
 
 CPLErr GDALMRFRasterBand::FetchClonedBlock(int xblk, int yblk, void *buffer)
 {
-    CPLDebug("MRF_IB","FetchClonedBlock %d,%d,0,%d, level  %d\n", xblk, yblk, m_band, m_l);
+    CPLDebug("MRF_IB","FetchClonedBlock %d,%d,0,%d, level  %d\n", xblk, yblk, nBand, m_l);
 
-    VSILFILE *srcfd;
     // Paranoid check
     assert(poDS->clonedSource);
 
-    GDALMRFDataset *poSrc;
-    if ( NULL == (poSrc = static_cast<GDALMRFDataset *>(poDS->GetSrcDS()))) {
-	CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't open source file %s", poDS->source.c_str());
-	return CE_Failure;
+    GDALMRFDataset *poSrc = static_cast<GDALMRFDataset *>(poDS->GetSrcDS());
+    if( NULL == poSrc )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't open source file %s", poDS->source.c_str());
+        return CE_Failure;
     }
 
     if (poDS->bypass_cache || GF_Read == DataMode()) {
-	// Can't store, so just fetch from source, which is an MRF with identical structure
-	GDALMRFRasterBand *b = static_cast<GDALMRFRasterBand *>(poSrc->GetRasterBand(nBand));
-	if (b->GetOverviewCount() && m_l)
-	    b = static_cast<GDALMRFRasterBand *>(b->GetOverview(m_l-1));
+        // Can't store, so just fetch from source, which is an MRF with identical structure
+        GDALMRFRasterBand *b = static_cast<GDALMRFRasterBand *>(poSrc->GetRasterBand(nBand));
+        if (b->GetOverviewCount() && m_l)
+            b = static_cast<GDALMRFRasterBand *>(b->GetOverview(m_l-1));
         if( b == NULL )
             return CE_Failure;
-	return b->IReadBlock(xblk,yblk,buffer);
+        return b->IReadBlock(xblk,yblk,buffer);
     }
 
-    ILSize req(xblk, yblk, 0, m_band/img.pagesize.c , m_l);
+    ILSize req(xblk, yblk, 0, (nBand-1)/img.pagesize.c , m_l);
     ILIdx tinfo;
 
     // Get the cloned source tile info
     // The cloned source index is after the current one
     if (CE_None != poDS->ReadTileIdx(tinfo, req, img, poDS->idxSize)) {
-	CPLError(CE_Failure, CPLE_AppDefined, "MRF: Unable to read cloned index entry");
-	return CE_Failure;
+        CPLError(CE_Failure, CPLE_AppDefined, "MRF: Unable to read cloned index entry");
+        return CE_Failure;
     }
 
     GUIntBig infooffset = IdxOffset(req, img);
@@ -595,17 +586,17 @@ CPLErr GDALMRFRasterBand::FetchClonedBlock(int xblk, int yblk, void *buffer)
 
     // Does the source have this tile?
     if (tinfo.size == 0) { // Nope, mark it empty and return fill
-	err = poDS->WriteTile((void *)1, infooffset, 0);
-	if (CE_None != err)
-	    return err;
-	return FillBlock(buffer);
+        err = poDS->WriteTile((void *)1, infooffset, 0);
+        if (CE_None != err)
+            return err;
+        return FillBlock(buffer);
     }
 
-    srcfd = poSrc->DataFP();
+    VSILFILE *srcfd = poSrc->DataFP();
     if (NULL == srcfd) {
-	CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't open source data file %s", 
-	    poDS->source.c_str());
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't open source data file %s",
+            poDS->source.c_str());
+        return CE_Failure;
     }
 
     // Need to read the tile from the source
@@ -625,25 +616,24 @@ CPLErr GDALMRFRasterBand::FetchClonedBlock(int xblk, int yblk, void *buffer)
 
     VSIFSeekL(srcfd, tinfo.offset, SEEK_SET);
     if (tinfo.size != GIntBig(VSIFReadL( buf, 1, static_cast<size_t>(tinfo.size), srcfd))) {
-	CPLFree(buf);
-	CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't read data from source %s",
-	    poSrc->current.datfname.c_str() );
-	return CE_Failure;
+        CPLFree(buf);
+        CPLError( CE_Failure, CPLE_AppDefined, "MRF: Can't read data from source %s",
+            poSrc->current.datfname.c_str() );
+        return CE_Failure;
     }
 
     // Write it then reissue the read
     err = poDS->WriteTile(buf, infooffset, tinfo.size);
     CPLFree(buf);
     if ( CE_None != err )
-	return err;
+        return err;
     // Reissue read, it will work from the cloned data
     return IReadBlock(xblk, yblk, buffer);
 }
 
-
 /**
 *\brief read a block in the provided buffer
-* 
+*
 *  For separate band model, the DS buffer is not used, the read is direct in the buffer
 *  For pixel interleaved model, the DS buffer holds the temp copy
 *  and all the other bands are force read
@@ -654,30 +644,30 @@ CPLErr GDALMRFRasterBand::IReadBlock(int xblk, int yblk, void *buffer)
 {
     ILIdx tinfo;
     GInt32 cstride = img.pagesize.c;
-    ILSize req(xblk, yblk, 0, m_band / cstride, m_l);
-    CPLDebug("MRF_IB", "IReadBlock %d,%d,0,%d, level %d, idxoffset " CPL_FRMT_GIB "\n", 
-	xblk, yblk, m_band, m_l, IdxOffset(req,img));
+    ILSize req(xblk, yblk, 0, (nBand-1)/cstride, m_l);
+    CPLDebug("MRF_IB", "IReadBlock %d,%d,0,%d, level %d, idxoffset " CPL_FRMT_GIB "\n",
+        xblk, yblk, nBand-1, m_l, IdxOffset(req,img));
 
     // If this is a caching file and bypass is on, just do the fetch
     if (poDS->bypass_cache && !poDS->source.empty())
-	return FetchBlock(xblk, yblk, buffer);
+        return FetchBlock(xblk, yblk, buffer);
 
     if (CE_None != poDS->ReadTileIdx(tinfo, req, img)) {
-	CPLError( CE_Failure, CPLE_AppDefined,
-	    "MRF: Unable to read index at offset " CPL_FRMT_GIB, IdxOffset(req, img));
-	return CE_Failure;
+        CPLError( CE_Failure, CPLE_AppDefined,
+            "MRF: Unable to read index at offset " CPL_FRMT_GIB, IdxOffset(req, img));
+        return CE_Failure;
     }
 
     if (0 == tinfo.size) { // Could be missing or it could be caching
-	// Offset != 0 means no data, Update mode is for local MRFs only
-	// if caching index mode is RO don't try to fetch
-	// Also, caching MRFs can't be opened in update mode
-	if ( 0 != tinfo.offset || GA_Update == poDS->eAccess 
-	    || poDS->source.empty() || IdxMode() == GF_Read )
-	    return FillBlock(buffer);
+        // Offset != 0 means no data, Update mode is for local MRFs only
+        // if caching index mode is RO don't try to fetch
+        // Also, caching MRFs can't be opened in update mode
+        if ( 0 != tinfo.offset || GA_Update == poDS->eAccess
+            || poDS->source.empty() || IdxMode() == GF_Read )
+            return FillBlock(buffer);
 
-	// caching MRF, need to fetch a block
-	return FetchBlock(xblk, yblk, buffer);
+        // caching MRF, need to fetch a block
+        return FetchBlock(xblk, yblk, buffer);
     }
 
     CPLDebug("MRF_IB","Tinfo offset " CPL_FRMT_GIB ", size  " CPL_FRMT_GIB "\n", tinfo.offset, tinfo.size);
@@ -694,12 +684,15 @@ CPLErr GDALMRFRasterBand::IReadBlock(int xblk, int yblk, void *buffer)
     // valgrind gdalinfo -checksum out.mrf
     // Invalid read of size 4
     // at BitStuffer::read(unsigned char**, std::vector<unsigned int, std::allocator<unsigned int> >&) const (BitStuffer.cpp:153)
-    if( tinfo.size <= 0 || tinfo.size > INT_MAX - 3 )
+
+    // No stored tile should be larger than twice the raw size.
+    if( tinfo.size <= 0 || tinfo.size > poDS->pbsize * 2 )
     {
         CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Too big tile size: " CPL_FRMT_GIB, tinfo.size);
+                 "Stored tile is too large: " CPL_FRMT_GIB, tinfo.size);
         return CE_Failure;
     }
+
     void *data = VSIMalloc(static_cast<size_t>(tinfo.size + 3));
     if( data == NULL )
     {
@@ -714,16 +707,16 @@ CPLErr GDALMRFRasterBand::IReadBlock(int xblk, int yblk, void *buffer)
     if (dfp == NULL)
     {
         CPLFree(data);
-	return CE_Failure;
+        return CE_Failure;
     }
 
     // This part is not thread safe, but it is what GDAL expects
     VSIFSeekL(dfp, tinfo.offset, SEEK_SET);
     if (1 != VSIFReadL(data, static_cast<size_t>(tinfo.size), 1, dfp)) {
-	CPLFree(data);
-	CPLError(CE_Failure, CPLE_AppDefined, "Unable to read data page, %d@%x",
-	    int(tinfo.size), int(tinfo.offset));
-	return CE_Failure;
+        CPLFree(data);
+        CPLError(CE_Failure, CPLE_AppDefined, "Unable to read data page, %d@%x",
+            int(tinfo.size), int(tinfo.offset));
+        return CE_Failure;
     }
 
     /* initialize padding bytes */
@@ -741,8 +734,8 @@ CPLErr GDALMRFRasterBand::IReadBlock(int xblk, int yblk, void *buffer)
                      img.pageSizeBytes);
             return CE_Failure;
         }
-	dst.size = img.pageSizeBytes + 1440; // in case the packed page is a bit larger than the raw one
-	dst.buffer = (char *)VSIMalloc(dst.size);
+        dst.size = img.pageSizeBytes + 1440; // in case the packed page is a bit larger than the raw one
+        dst.buffer = (char *)VSIMalloc(dst.size);
         if( dst.buffer == NULL )
         {
             CPLFree(data);
@@ -751,15 +744,15 @@ CPLErr GDALMRFRasterBand::IReadBlock(int xblk, int yblk, void *buffer)
             return CE_Failure;
         }
 
-	if (ZUnPack(src, dst, deflate_flags)) {
-	    // Got it unpacked, update the pointers
-	    CPLFree(data);
-	    tinfo.size = dst.size;
-	    data = dst.buffer;
-	} else { // Warn and assume the data was not deflated
-	    CPLError(CE_Warning, CPLE_AppDefined, "Can't inflate page!");
-	    CPLFree(dst.buffer);
-	}
+        if (ZUnPack(src, dst, deflate_flags)) {
+            // Got it unpacked, update the pointers
+            CPLFree(data);
+            tinfo.size = dst.size;
+            data = dst.buffer;
+        } else { // Warn and assume the data was not deflated
+            CPLError(CE_Warning, CPLE_AppDefined, "Can't inflate page!");
+            CPLFree(dst.buffer);
+        }
     }
 
     src.buffer = (char *)data;
@@ -771,31 +764,30 @@ CPLErr GDALMRFRasterBand::IReadBlock(int xblk, int yblk, void *buffer)
 
     // If pages are interleaved, use the dataset page buffer instead
     if (1!=cstride)
-	dst.buffer = (char *)poDS->GetPBuffer();
+        dst.buffer = (char *)poDS->GetPBuffer();
 
     CPLErr ret = Decompress(dst, src);
     dst.size = img.pageSizeBytes; // In case the decompress failed, force it back
     CPLFree(data);
 
     // Swap whatever we decompressed if we need to
-    if (is_Endianess_Dependent(img.dt,img.comp) && (img.nbo != NET_ORDER) ) 
-	swab_buff(dst, img);
+    if (is_Endianess_Dependent(img.dt,img.comp) && (img.nbo != NET_ORDER) )
+        swab_buff(dst, img);
 
     // If pages are separate, we're done, the read was in the output buffer
     if ( 1 == cstride || CE_None != ret)
-	return ret;
+        return ret;
 
     // De-interleave page and return
     return RB(xblk, yblk, dst, buffer);
 }
 
-
 /**
 *\brief Write a block from the provided buffer
-* 
+*
 * Same trick as read, use a temporary tile buffer for pixel interleave
-* For band separate, use a 
-* Write the block once it has all the bands, report 
+* For band separate, use a
+* Write the block once it has all the bands, report
 * if a new block is started before the old one was completed
 *
 */
@@ -804,45 +796,49 @@ CPLErr GDALMRFRasterBand::IWriteBlock(int xblk, int yblk, void *buffer)
 
 {
     GInt32 cstride = img.pagesize.c;
-    ILSize req(xblk, yblk, 0, m_band/cstride, m_l);
+    ILSize req(xblk, yblk, 0, (nBand-1)/cstride, m_l);
     GUIntBig infooffset = IdxOffset(req, img);
 
-    CPLDebug("MRF_IB", "IWriteBlock %d,%d,0,%d, level  %d, stride %d\n", xblk, yblk, 
-	m_band, m_l, cstride);
+    CPLDebug("MRF_IB", "IWriteBlock %d,%d,0,%d, level  %d, stride %d\n", xblk, yblk,
+        nBand, m_l, cstride);
+
+    // Finish the Create call
+    if (!poDS->bCrystalized)
+        poDS->Crystalize();
 
     if (1 == cstride) {     // Separate bands, we can write it as is
-	// Empty page skip
+        // Empty page skip
 
-	int success;
-	double val = GetNoDataValue(&success);
-	if (!success) val = 0.0;
-	if (isAllVal(eDataType, buffer, img.pageSizeBytes, val))
-	    return poDS->WriteTile(NULL, infooffset, 0);
+        int success;
+        double val = GetNoDataValue(&success);
+        if (!success) val = 0.0;
+        if (isAllVal(eDataType, buffer, img.pageSizeBytes, val))
+            return poDS->WriteTile(NULL, infooffset, 0);
 
-	// Use the pbuffer to hold the compressed page before writing it
-	poDS->tile = ILSize(); // Mark it corrupt
+        // Use the pbuffer to hold the compressed page before writing it
+        poDS->tile = ILSize(); // Mark it corrupt
 
-	buf_mgr src;
+        buf_mgr src;
         src.buffer = (char *)buffer;
         src.size = static_cast<size_t>(img.pageSizeBytes);
-	buf_mgr dst = {(char *)poDS->GetPBuffer(), poDS->GetPBufferSize()};
-
-	// Swab the source before encoding if we need to 
-	if (is_Endianess_Dependent(img.dt, img.comp) && (img.nbo != NET_ORDER)) 
-	    swab_buff(src, img);
-
-	// Compress functions need to return the compressed size in
-	// the bytes in buffer field
-	Compress(dst, src);
-	void *usebuff = dst.buffer;
-	if (deflatep) {
-	    usebuff = DeflateBlock(dst, poDS->pbsize - dst.size, deflate_flags);
-	    if (!usebuff) {
-		CPLError(CE_Failure,CPLE_AppDefined, "MRF: Deflate error");
-		return CE_Failure;
-	    }
-	}
-	return poDS->WriteTile(usebuff, infooffset , dst.size);
+        buf_mgr dst = {(char *)poDS->GetPBuffer(), poDS->GetPBufferSize()};
+
+        // Swab the source before encoding if we need to
+        if (is_Endianess_Dependent(img.dt, img.comp) && (img.nbo != NET_ORDER))
+            swab_buff(src, img);
+
+        // Compress functions need to return the compressed size in
+        // the bytes in buffer field
+        Compress(dst, src);
+        void *usebuff = dst.buffer;
+        if (deflatep) {
+            usebuff = DeflateBlock(dst, poDS->pbsize - dst.size, deflate_flags);
+            if (!usebuff) {
+                CPLError(CE_Failure,CPLE_AppDefined, "MRF: Deflate error");
+                return CE_Failure;
+            }
+        }
+        return poDS->WriteTile(usebuff, infooffset , dst.size);
     }
 
     // Multiple bands per page, use a temporary to assemble the page
@@ -855,72 +851,70 @@ CPLErr GDALMRFRasterBand::IWriteBlock(int xblk, int yblk, void *buffer)
     void *tbuffer = VSIMalloc(img.pageSizeBytes + poDS->pbsize);
 
     if (!tbuffer) {
-	CPLError(CE_Failure,CPLE_AppDefined, "MRF: Can't allocate write buffer");
-	return CE_Failure;
+        CPLError(CE_Failure,CPLE_AppDefined, "MRF: Can't allocate write buffer");
+        return CE_Failure;
     }
-	
+
     // Get the other bands from the block cache
     for (int iBand=0; iBand < poDS->nBands; iBand++ )
     {
-	const char *pabyThisImage=NULL;
-	GDALRasterBlock *poBlock=NULL;
-
-	if (iBand == m_band)
-	{
-	    pabyThisImage = (char *) buffer;
-	    poDS->bdirty |= bandbit();
-	} else {
-	    GDALRasterBand *band = poDS->GetRasterBand(iBand +1);
-	    // Pick the right overview
-	    if (m_l) band = band->GetOverview(m_l -1);
-	    poBlock = ((GDALMRFRasterBand *)band)
-		->TryGetLockedBlockRef(xblk, yblk);
-	    if (NULL==poBlock) continue;
-	    // This is where the image data is for this band
-
-	    pabyThisImage = (char*) poBlock->GetDataRef();
-	    poDS->bdirty |= bandbit(iBand);
-	}
-
-	// Keep track of empty bands, but encode them anyhow, in case some are not empty
-	int success;
-	double val = GetNoDataValue(&success);
-	if (!success) val = 0.0;
-        if (isAllVal(eDataType, (char *)pabyThisImage, blockSizeBytes(), val))
-	    empties |= bandbit(iBand);
-
-	// Copy the data into the dataset buffer here
-	// Just the right mix of templates and macros make this real tidy
-#define CpySO(T) cpy_stride_out<T> (((T *)tbuffer)+iBand, pabyThisImage,\
-		blockSizeBytes()/sizeof(T), cstride)
-
-
-	// Build the page in tbuffer
-	switch (GDALGetDataTypeSize(eDataType)/8)
-	{
-	    case 1: CpySO(GByte); break;
-	    case 2: CpySO(GInt16); break;
-	    case 4: CpySO(GInt32); break;
-	    case 8: CpySO(GIntBig); break;
-	    default:
+        char *pabyThisImage = NULL;
+        GDALRasterBlock *poBlock = NULL;
+
+        if (iBand == nBand-1)
+        {
+            pabyThisImage = reinterpret_cast<char *>(buffer);
+            poDS->bdirty |= bandbit();
+        } else {
+            GDALRasterBand *band = poDS->GetRasterBand(iBand +1);
+            // Pick the right overview
+            if (m_l) band = band->GetOverview(m_l -1);
+            poBlock = (reinterpret_cast<GDALMRFRasterBand *>(band))->TryGetLockedBlockRef(xblk, yblk);
+            if (NULL==poBlock) continue;
+            // This is where the image data is for this band
+
+            pabyThisImage = reinterpret_cast<char*>(poBlock->GetDataRef());
+            poDS->bdirty |= bandbit(iBand);
+        }
+
+        // Keep track of empty bands, but encode them anyhow, in case some are not empty
+        int success;
+        double val = GetNoDataValue(&success);
+        if (!success) val = 0.0;
+        if (isAllVal(eDataType, pabyThisImage, blockSizeBytes(), val))
+            empties |= bandbit(iBand);
+
+        // Copy the data into the dataset buffer here
+        // Just the right mix of templates and macros make this real tidy
+#define CpySO(T) cpy_stride_out<T> ((reinterpret_cast<T *>(tbuffer))+iBand, pabyThisImage,\
+                blockSizeBytes()/sizeof(T), cstride)
+
+        // Build the page in tbuffer
+        switch (GDALGetDataTypeSize(eDataType)/8)
+        {
+            case 1: CpySO(GByte); break;
+            case 2: CpySO(GInt16); break;
+            case 4: CpySO(GInt32); break;
+            case 8: CpySO(GIntBig); break;
+            default:
             {
-		CPLError(CE_Failure,CPLE_AppDefined, "MRF: Write datatype of %d bytes "
-			"not implemented", GDALGetDataTypeSize(eDataType)/8);
+                CPLError(CE_Failure,CPLE_AppDefined, "MRF: Write datatype of %d bytes "
+                        "not implemented", GDALGetDataTypeSize(eDataType)/8);
                 if (poBlock != NULL)
                 {
                     poBlock->MarkClean();
                     poBlock->DropLock();
                 }
                 CPLFree(tbuffer);
-		return CE_Failure;
+                return CE_Failure;
             }
-	}
+        }
 
-	if (poBlock != NULL)
-	{
-	    poBlock->MarkClean();
-	    poBlock->DropLock();
-	}
+        if (poBlock != NULL)
+        {
+            poBlock->MarkClean();
+            poBlock->DropLock();
+        }
     }
 
     // Should keep track of the individual band buffers and only mix them if this is not
@@ -928,14 +922,14 @@ CPLErr GDALMRFRasterBand::IWriteBlock(int xblk, int yblk, void *buffer)
     // This way works fine, but it does work extra for empty pages
 
     if (GIntBig(empties) == AllBandMask()) {
-	CPLFree(tbuffer);
-	return poDS->WriteTile(NULL, infooffset, 0);
+        CPLFree(tbuffer);
+        return poDS->WriteTile(NULL, infooffset, 0);
     }
 
     if (poDS->bdirty != AllBandMask())
-	CPLError(CE_Warning, CPLE_AppDefined,
-	"MRF: IWrite, band dirty mask is " CPL_FRMT_GIB " instead of " CPL_FRMT_GIB,
-	poDS->bdirty, AllBandMask());
+        CPLError(CE_Warning, CPLE_AppDefined,
+        "MRF: IWrite, band dirty mask is " CPL_FRMT_GIB " instead of " CPL_FRMT_GIB,
+        poDS->bdirty, AllBandMask());
 
     buf_mgr src;
     src.buffer = (char *)tbuffer;
@@ -958,17 +952,17 @@ CPLErr GDALMRFRasterBand::IWriteBlock(int xblk, int yblk, void *buffer)
     // Where the output is, in case we deflate
     void *usebuff = outbuff;
     if (deflatep) {
-	// Move the packed part at the start of tbuffer, to make more space available
-	memcpy(tbuffer, outbuff, dst.size);
-	dst.buffer = (char *)tbuffer;
-	usebuff = DeflateBlock(dst, img.pageSizeBytes + poDS->pbsize - dst.size, deflate_flags);
-	if (!usebuff) {
-	    CPLError(CE_Failure,CPLE_AppDefined, "MRF: Deflate error");
-	    CPLFree(tbuffer);
+        // Move the packed part at the start of tbuffer, to make more space available
+        memcpy(tbuffer, outbuff, dst.size);
+        dst.buffer = (char *)tbuffer;
+        usebuff = DeflateBlock(dst, img.pageSizeBytes + poDS->pbsize - dst.size, deflate_flags);
+        if (!usebuff) {
+            CPLError(CE_Failure,CPLE_AppDefined, "MRF: Deflate error");
+            CPLFree(tbuffer);
             poDS->WriteTile(NULL, infooffset, 0);
             poDS->bdirty = 0;
-	    return CE_Failure;
-	}
+            return CE_Failure;
+        }
     }
 
     ret = poDS->WriteTile(usebuff, infooffset, dst.size);
diff --git a/frmts/mrf/mrf_overview.cpp b/frmts/mrf/mrf_overview.cpp
index 4db41bc..6f8aef3 100644
--- a/frmts/mrf/mrf_overview.cpp
+++ b/frmts/mrf/mrf_overview.cpp
@@ -14,7 +14,6 @@
 */
 
 /******************************************************************************
-* $Id$
 *
 * Project:  Meta Raster File Format Driver Implementation, overlay support
 * Purpose:  Implementation overlay support for MRF
@@ -29,16 +28,18 @@
 #include "marfa.h"
 #include <vector>
 
+CPL_CVSID("$Id: mrf_overview.cpp 35929 2016-10-25 16:09:00Z goatbar $");
+
 using std::vector;
 
 NAMESPACE_MRF_START
 
 // Count the values in a buffer that match a specific value
-template<typename T> int MatchCount(T *buff, int sz, T val) {
+template<typename T> static int MatchCount(T *buff, int sz, T val) {
     int ncount=0;
     for (int i=0; i < sz; i++)
-	if (buff[i] == val)
-	    ncount++;
+        if (buff[i] == val)
+            ncount++;
     return ncount;
 }
 
@@ -46,41 +47,41 @@ template<typename T> int MatchCount(T *buff, int sz, T val) {
 // Scales by 2x2 a buffer in place, using Nearest resampling
 // Always pick the top-left corner
 //
-template<typename T> void NearByFour(T *buff, int xsz, int ysz) {
+template<typename T> static void NearByFour(T *buff, int xsz, int ysz) {
     T *obuff = buff;
     for (int line = 0; line < ysz; line++) {
-		// Copy every other pixel
-		for (int col = 0; col < xsz; col++, buff++) {
-			*obuff++ = *buff++;
-		}
-		// Skip every other line
-		buff += xsz * 2;
+                // Copy every other pixel
+                for (int col = 0; col < xsz; col++, buff++) {
+                        *obuff++ = *buff++;
+                }
+                // Skip every other line
+                buff += xsz * 2;
     }
 }
 
 //
 // If the NoData value exists, pick a valid pixel if possible
 //
-template<typename T> void NearByFour(T *buff, int xsz, int ysz, T ndv) {
+template<typename T> static void NearByFour(T *buff, int xsz, int ysz, T ndv) {
     T *obuff = buff;
     T *evenline = buff;
 
     for (int line = 0; line<ysz; line++) {
-	T *oddline = evenline + xsz * 2;
-	for (int col = 0; col<xsz; col++) {
-
-	    if (evenline[0] != ndv)
-		*obuff++ = evenline[0];
-	    else if (evenline[1] != ndv)
-		*obuff++ = evenline[1];
-	    else if (oddline[0] != ndv)
-		*obuff++ = oddline[0];
-	    else
-		*obuff++ = oddline[1];
-
-	    evenline += 2; oddline += 2;
-	}
-	evenline += xsz * 2;  // Skips the other input line
+        T *oddline = evenline + xsz * 2;
+        for (int col = 0; col<xsz; col++) {
+
+            if (evenline[0] != ndv)
+                *obuff++ = evenline[0];
+            else if (evenline[1] != ndv)
+                *obuff++ = evenline[1];
+            else if (oddline[0] != ndv)
+                *obuff++ = oddline[0];
+            else
+                *obuff++ = oddline[1];
+
+            evenline += 2; oddline += 2;
+        }
+        evenline += xsz * 2;  // Skips the other input line
     }
 }
 
@@ -92,17 +93,17 @@ template<typename T> void NearByFour(T *buff, int xsz, int ysz, T ndv) {
 //
 
 // Integer data types shorter than 32 bit use integer math safely
-template<typename T> void AverageByFour(T *buff, int xsz, int ysz) {
+template<typename T> static void AverageByFour(T *buff, int xsz, int ysz) {
     T *obuff=buff;
     T *evenline=buff;
 
     for (int line=0; line<ysz; line++) {
-	T *oddline=evenline+xsz*2;
-	for (int col=0; col<xsz; col++) {
-	    *obuff++ = (2 + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4;
-	    evenline +=2; oddline +=2;
-	}
-	evenline += xsz*2;  // Skips the other line
+        T *oddline=evenline+xsz*2;
+        for (int col=0; col<xsz; col++) {
+            *obuff++ = (2 + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4;
+            evenline +=2; oddline +=2;
+        }
+        evenline += xsz*2;  // Skips the other line
     }
 }
 
@@ -112,12 +113,12 @@ template<> void AverageByFour<GInt32>(GInt32 *buff, int xsz, int ysz) {
     GInt32 *evenline=buff;
 
     for (int line=0; line<ysz; line++) {
-	GInt32 *oddline=evenline+xsz*2;
-	for (int col=0; col<xsz; col++) {
-	    *obuff++ = (GIntBig(2) + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4;
-	    evenline +=2; oddline +=2;
-	}
-	evenline += xsz*2;  // Skips the other line
+        GInt32 *oddline=evenline+xsz*2;
+        for (int col=0; col<xsz; col++) {
+            *obuff++ = (GIntBig(2) + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4;
+            evenline +=2; oddline +=2;
+        }
+        evenline += xsz*2;  // Skips the other line
     }
 }
 
@@ -127,12 +128,12 @@ template<> void AverageByFour<GUInt32>(GUInt32 *buff, int xsz, int ysz) {
     GUInt32 *evenline=buff;
 
     for (int line=0; line<ysz; line++) {
-	GUInt32 *oddline=evenline+xsz*2;
-	for (int col=0; col<xsz; col++) {
-	    *obuff++ = (GIntBig(2) + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4;
-	    evenline +=2; oddline +=2;
-	}
-	evenline += xsz*2;  // Skips the other line
+        GUInt32 *oddline=evenline+xsz*2;
+        for (int col=0; col<xsz; col++) {
+            *obuff++ = (GIntBig(2) + evenline[0] + evenline[1] + oddline[0] + oddline[1]) / 4;
+            evenline +=2; oddline +=2;
+        }
+        evenline += xsz*2;  // Skips the other line
     }
 }
 
@@ -142,12 +143,12 @@ template<> void AverageByFour<float>(float *buff, int xsz, int ysz) {
     float *evenline=buff;
 
     for (int line=0; line<ysz; line++) {
-	float *oddline = evenline + xsz*2;
-	for (int col=0; col<xsz; col++) {
-	    *obuff++ = (evenline[0] + evenline[1] + oddline[0] + oddline[1]) * 0.25f;
-	    evenline +=2; oddline +=2;
-	}
-	evenline += xsz*2;  // Skips the other line
+        float *oddline = evenline + xsz*2;
+        for (int col=0; col<xsz; col++) {
+            *obuff++ = (evenline[0] + evenline[1] + oddline[0] + oddline[1]) * 0.25f;
+            evenline +=2; oddline +=2;
+        }
+        evenline += xsz*2;  // Skips the other line
     }
 }
 
@@ -157,12 +158,12 @@ template<> void AverageByFour<double>(double *buff, int xsz, int ysz) {
     double *evenline=buff;
 
     for (int line=0; line<ysz; line++) {
-	double *oddline = evenline + xsz*2;
-	for (int col=0; col<xsz; col++) {
-	    *obuff++ = (evenline[0] + evenline[1] + oddline[0] + oddline[1]) * 0.25;
-	    evenline +=2; oddline +=2;
-	}
-	evenline += xsz*2;  // Skips the other line
+        double *oddline = evenline + xsz*2;
+        for (int col=0; col<xsz; col++) {
+            *obuff++ = (evenline[0] + evenline[1] + oddline[0] + oddline[1]) * 0.25;
+            evenline +=2; oddline +=2;
+        }
+        evenline += xsz*2;  // Skips the other line
     }
 }
 
@@ -171,26 +172,25 @@ template<> void AverageByFour<double>(double *buff, int xsz, int ysz) {
 // Speedup by specialization for smaller byte count int types is probably not worth much
 // since there are so many conditions here
 //
-template<typename T> void AverageByFour(T *buff, int xsz, int ysz, T ndv) {
+template<typename T> static void AverageByFour(T *buff, int xsz, int ysz, T ndv) {
     T *obuff=buff;
     T *evenline=buff;
 
     for (int line=0; line<ysz; line++) {
-	T *oddline=evenline+xsz*2;
-	for (int col=0; col<xsz; col++) {
-	    GIntBig acc = 0;
-	    int count = 0;
+        T *oddline=evenline+xsz*2;
+        for (int col=0; col<xsz; col++) {
+            GIntBig acc = 0;
+            int count = 0;
 
 // Temporary macro to accumulate the sum, uses the value, increments the pointer
 // Careful with this one, it has side effects
 #define use(valp) if (*valp != ndv) { acc += *valp; count++; }; valp++;
-	    use(evenline); use(evenline); use(oddline); use(oddline);
+            use(evenline); use(evenline); use(oddline); use(oddline);
 #undef use
-	    // The count/2 is the bias to obtain correct rounding
-	    *obuff++ = T((count != 0) ? ((acc + count/2) / count) : ndv);
-
-	}
-	evenline += xsz*2;  // Skips every other line
+            // The count/2 is the bias to obtain correct rounding
+            *obuff++ = T((count != 0) ? ((acc + count/2) / count) : ndv);
+        }
+        evenline += xsz*2;  // Skips every other line
     }
 }
 
@@ -200,20 +200,20 @@ template<> void AverageByFour<float>(float *buff, int xsz, int ysz, float ndv) {
     float *evenline=buff;
 
     for (int line=0; line<ysz; line++) {
-	float *oddline=evenline+xsz*2;
-	for (int col=0; col<xsz; col++) {
-	    double acc = 0;
-	    double count = 0;
+        float *oddline=evenline+xsz*2;
+        for (int col=0; col<xsz; col++) {
+            double acc = 0;
+            double count = 0;
 
 // Temporary macro to accumulate the sum, uses the value, increments the pointer
 // Careful with this one, it has side effects
 #define use(valp) if (*valp != ndv) { acc += *valp; count += 1.0; }; valp++;
-	    use(evenline); use(evenline); use(oddline); use(oddline);
+            use(evenline); use(evenline); use(oddline); use(oddline);
 #undef use
-	    // Output value is eiher accumulator divided by count or the NoDataValue
-	    *obuff++ = float((count != 0.0) ? acc/count : ndv);
-	}
-	evenline += xsz*2;  // Skips every other line
+            // Output value is eiher accumulator divided by count or the NoDataValue
+            *obuff++ = float((count != 0.0) ? acc/count : ndv);
+        }
+        evenline += xsz*2;  // Skips every other line
     }
 }
 
@@ -223,20 +223,20 @@ template<> void AverageByFour<double>(double *buff, int xsz, int ysz, double ndv
     double *evenline=buff;
 
     for (int line=0; line<ysz; line++) {
-	double *oddline=evenline+xsz*2;
-	for (int col=0; col<xsz; col++) {
-	    double acc = 0;
-	    double count = 0;
+        double *oddline=evenline+xsz*2;
+        for (int col=0; col<xsz; col++) {
+            double acc = 0;
+            double count = 0;
 
 // Temporary macro to accumulate the sum, uses the value, increments the pointer
 // Careful with this one, it has side effects
 #define use(valp) if (*valp != ndv) { acc += *valp; count += 1.0; }; valp++;
-	    use(evenline); use(evenline); use(oddline); use(oddline);
+            use(evenline); use(evenline); use(oddline); use(oddline);
 #undef use
-	    // Output value is eiher accumulator divided by count or the NoDataValue
-	    *obuff++ = ((count != 0.0) ? acc/count : ndv);
-	}
-	evenline += xsz*2;  // Skips every other line
+            // Output value is eiher accumulator divided by count or the NoDataValue
+            *obuff++ = ((count != 0.0) ? acc/count : ndv);
+        }
+        evenline += xsz*2;  // Skips every other line
     }
 }
 
@@ -248,13 +248,13 @@ template<> void AverageByFour<double>(double *buff, int xsz, int ysz, double ndv
  */
 
 CPLErr GDALMRFDataset::PatchOverview(int BlockX,int BlockY,
-				      int Width,int Height,
-				      int srcLevel, int recursive,
-				      int sampling_mode)
+                                     int Width,int Height,
+                                     int srcLevel, int recursive,
+                                     int sampling_mode)
 {
     GDALRasterBand *b0=GetRasterBand(1);
     if ( b0->GetOverviewCount() <= srcLevel)
-	return CE_None;
+        return CE_None;
 
     int BlockXOut = BlockX/2 ; // Round down
     Width += BlockX & 1; // Increment width if rounding down
@@ -278,11 +278,11 @@ CPLErr GDALMRFDataset::PatchOverview(int BlockX,int BlockY,
     vector<GDALRasterBand *> dst_b;
 
     for (int band=1; band<=bands; band++) {
-	if (srcLevel==0)
-	    src_b.push_back(GetRasterBand(band));
-	else
-	    src_b.push_back(GetRasterBand(band)->GetOverview(srcLevel-1));
-	dst_b.push_back(GetRasterBand(band)->GetOverview(srcLevel));
+        if (srcLevel==0)
+            src_b.push_back(GetRasterBand(band));
+        else
+            src_b.push_back(GetRasterBand(band)->GetOverview(srcLevel-1));
+        dst_b.push_back(GetRasterBand(band)->GetOverview(srcLevel));
     }
 
     // Allocate space for four blocks
@@ -293,137 +293,135 @@ CPLErr GDALMRFDataset::PatchOverview(int BlockX,int BlockY,
     // There is no penalty for separate bands either.
     //
     for (int y=0; y<HeightOut; y++) {
-	int dst_offset_y = BlockYOut+y;
-	int src_offset_y = dst_offset_y *2;
-	for (int x=0; x<WidthOut; x++) {
-	    int dst_offset_x = BlockXOut + x;
-	    int src_offset_x = dst_offset_x * 2;
-
-	    // Do it band at a time so we can work in grayscale
-	    for (int band=0; band<bands; band++) { // Counting from zero in a vector
-
-		int sz_x = 2*tsz_x ,sz_y = 2*tsz_y ;
-		GDALMRFRasterBand *bsrc = static_cast<GDALMRFRasterBand *>(src_b[band]);
-		GDALMRFRasterBand *bdst = static_cast<GDALMRFRasterBand *>(dst_b[band]);
-
-		//
-		// Clip to the size to the input image
-		// This is one of the worst features of GDAL, it doesn't tolerate any padding
-		//
-		bool adjusted = false;
-		if (bsrc->GetXSize() < (src_offset_x + 2) * tsz_x) {
-		    sz_x = bsrc->GetXSize() - src_offset_x * tsz_x;
-		    adjusted = true;
-		}
-		if (bsrc->GetYSize() < (src_offset_y + 2) * tsz_y) {
-		    sz_y = bsrc->GetYSize() - src_offset_y * tsz_y;
-		    adjusted = true;
-		}
-
-		if (adjusted) { // Fill with no data for partial buffer, instead of padding afterwards
-		    size_t bsb = bsrc->blockSizeBytes();
-		    char *b=static_cast<char *>(buffer);
-		    bsrc->FillBlock(b);
-		    bsrc->FillBlock(b + bsb);
-		    bsrc->FillBlock(b + 2*bsb);
-		    bsrc->FillBlock(b + 3*bsb);
-		}
-
-		int hasNoData = 0;
-		double ndv = bsrc->GetNoDataValue(&hasNoData);
-
-		CPLErr eErr = bsrc->RasterIO( GF_Read,
-		    src_offset_x*tsz_x, src_offset_y*tsz_y, // offset in input image
-		    sz_x, sz_y, // Size in output image
-		    buffer, sz_x, sz_y, // Buffer and size in buffer
-		    eDataType, // Requested type
-		    pixel_size, 2 * line_size
+        int dst_offset_y = BlockYOut+y;
+        int src_offset_y = dst_offset_y *2;
+        for (int x=0; x<WidthOut; x++) {
+            int dst_offset_x = BlockXOut + x;
+            int src_offset_x = dst_offset_x * 2;
+
+            // Do it band at a time so we can work in grayscale
+            for (int band=0; band<bands; band++) { // Counting from zero in a vector
+
+                int sz_x = 2*tsz_x ,sz_y = 2*tsz_y ;
+                GDALMRFRasterBand *bsrc = static_cast<GDALMRFRasterBand *>(src_b[band]);
+                GDALMRFRasterBand *bdst = static_cast<GDALMRFRasterBand *>(dst_b[band]);
+
+                //
+                // Clip to the size to the input image
+                // This is one of the worst features of GDAL, it doesn't tolerate any padding
+                //
+                bool adjusted = false;
+                if (bsrc->GetXSize() < (src_offset_x + 2) * tsz_x) {
+                    sz_x = bsrc->GetXSize() - src_offset_x * tsz_x;
+                    adjusted = true;
+                }
+                if (bsrc->GetYSize() < (src_offset_y + 2) * tsz_y) {
+                    sz_y = bsrc->GetYSize() - src_offset_y * tsz_y;
+                    adjusted = true;
+                }
+
+                if (adjusted) { // Fill with no data for partial buffer, instead of padding afterwards
+                    size_t bsb = bsrc->blockSizeBytes();
+                    char *b=static_cast<char *>(buffer);
+                    bsrc->FillBlock(b);
+                    bsrc->FillBlock(b + bsb);
+                    bsrc->FillBlock(b + 2*bsb);
+                    bsrc->FillBlock(b + 3*bsb);
+                }
+
+                int hasNoData = 0;
+                double ndv = bsrc->GetNoDataValue(&hasNoData);
+
+                CPLErr eErr = bsrc->RasterIO( GF_Read,
+                    src_offset_x*tsz_x, src_offset_y*tsz_y, // offset in input image
+                    sz_x, sz_y, // Size in output image
+                    buffer, sz_x, sz_y, // Buffer and size in buffer
+                    eDataType, // Requested type
+                    pixel_size, 2 * line_size
 #if GDAL_VERSION_MAJOR >= 2
-		    ,NULL
+                    ,NULL
 #endif
-		    ); // Pixel and line space
+                    ); // Pixel and line space
                 if( eErr != CE_None )
                 {
                     // TODO ?
                     CPLError(CE_Failure, CPLE_AppDefined, "RasterIO() failed");
                 }
 
-		// Count the NoData values
-		int count = 0; // Assume all points are data
-		if (sampling_mode == SAMPLING_Avg) {
+                // Count the NoData values
+                int count = 0; // Assume all points are data
+                if (sampling_mode == SAMPLING_Avg) {
 
 // Dispatch based on data type
 // Use an ugly temporary macro to make it look easy
 // Runs the optimized version if the page is full with data
 #define resample(T)\
     if (hasNoData) {\
-	count = MatchCount((T *)buffer, 4 * tsz_x * tsz_y, T(ndv));\
-	if (4 * tsz_x * tsz_y == count)\
-	    bdst->FillBlock(buffer);\
-	else if (0 != count)\
-	    AverageByFour((T *)buffer, tsz_x, tsz_y, T(ndv));\
-	}\
+        count = MatchCount((T *)buffer, 4 * tsz_x * tsz_y, T(ndv));\
+        if (4 * tsz_x * tsz_y == count)\
+            bdst->FillBlock(buffer);\
+        else if (0 != count)\
+            AverageByFour((T *)buffer, tsz_x, tsz_y, T(ndv));\
+        }\
     if (0 == count)\
-	AverageByFour((T *)buffer, tsz_x, tsz_y);\
+        AverageByFour((T *)buffer, tsz_x, tsz_y);\
     break;
 
-		    switch (eDataType) {
-		    case GDT_Byte:	resample(GByte);
-		    case GDT_UInt16:    resample(GUInt16);
-		    case GDT_Int16:     resample(GInt16);
-		    case GDT_UInt32:    resample(GUInt32);
-		    case GDT_Int32:     resample(GInt32);
-		    case GDT_Float32:   resample(float);
-		    case GDT_Float64:   resample(double);
-                    default: CPLAssert(FALSE); break;
-		    }
+                    switch (eDataType) {
+                    case GDT_Byte:      resample(GByte);
+                    case GDT_UInt16:    resample(GUInt16);
+                    case GDT_Int16:     resample(GInt16);
+                    case GDT_UInt32:    resample(GUInt32);
+                    case GDT_Int32:     resample(GInt32);
+                    case GDT_Float32:   resample(float);
+                    case GDT_Float64:   resample(double);
+                    default: CPLAssert(false); break;
+                    }
 #undef resample
-
-		}
-		else if (sampling_mode == SAMPLING_Near) {
+                }
+                else if (sampling_mode == SAMPLING_Near) {
 
 #define resample(T)\
     if (hasNoData) {\
-	count = MatchCount((T *)buffer, 4 * tsz_x * tsz_y, T(ndv));\
-	if (4 * tsz_x * tsz_y == count)\
-	    bdst->FillBlock(buffer);\
-	else if (0 != count)\
-	    NearByFour((T *)buffer, tsz_x, tsz_y, T(ndv));\
-    	}\
+        count = MatchCount((T *)buffer, 4 * tsz_x * tsz_y, T(ndv));\
+        if (4 * tsz_x * tsz_y == count)\
+            bdst->FillBlock(buffer);\
+        else if (0 != count)\
+            NearByFour((T *)buffer, tsz_x, tsz_y, T(ndv));\
+        }\
     if (0 == count)\
-	NearByFour((T *)buffer, tsz_x, tsz_y);\
+        NearByFour((T *)buffer, tsz_x, tsz_y);\
     break;
-		    switch (eDataType) {
-		    case GDT_Byte:	resample(GByte);
-		    case GDT_UInt16:    resample(GUInt16);
-		    case GDT_Int16:     resample(GInt16);
-		    case GDT_UInt32:    resample(GUInt32);
-		    case GDT_Int32:     resample(GInt32);
-		    case GDT_Float32:   resample(float);
-		    case GDT_Float64:   resample(double);
-                    default: CPLAssert(FALSE); break;
-		    }
+                    switch (eDataType) {
+                    case GDT_Byte:      resample(GByte);
+                    case GDT_UInt16:    resample(GUInt16);
+                    case GDT_Int16:     resample(GInt16);
+                    case GDT_UInt32:    resample(GUInt32);
+                    case GDT_Int32:     resample(GInt32);
+                    case GDT_Float32:   resample(float);
+                    case GDT_Float64:   resample(double);
+                    default: CPLAssert(false); break;
+                    }
 #undef resample
+                }
 
-		}
-
-		// Done filling the buffer
-		// Argh, still need to clip the output to the band size on the right and bottom
-		// The offset should be fine, just the size might need adjustments
-		sz_x = tsz_x;
-		sz_y = tsz_y ;
-
-		if ( bdst->GetXSize() < dst_offset_x * sz_x + sz_x )
-		    sz_x = bdst->GetXSize() - dst_offset_x * sz_x;
-		if ( bdst->GetYSize() < dst_offset_y * sz_y + sz_y )
-		    sz_y = bdst->GetYSize() - dst_offset_y * sz_y;
-
-		eErr = bdst->RasterIO( GF_Write,
-		    dst_offset_x*tsz_x, dst_offset_y*tsz_y, // offset in output image
-		    sz_x, sz_y, // Size in output image
-		    buffer, sz_x, sz_y, // Buffer and size in buffer
-		    eDataType, // Requested type
-		    pixel_size, line_size
+                // Done filling the buffer
+                // Argh, still need to clip the output to the band size on the right and bottom
+                // The offset should be fine, just the size might need adjustments
+                sz_x = tsz_x;
+                sz_y = tsz_y ;
+
+                if ( bdst->GetXSize() < dst_offset_x * sz_x + sz_x )
+                    sz_x = bdst->GetXSize() - dst_offset_x * sz_x;
+                if ( bdst->GetYSize() < dst_offset_y * sz_y + sz_y )
+                    sz_y = bdst->GetYSize() - dst_offset_y * sz_y;
+
+                eErr = bdst->RasterIO( GF_Write,
+                    dst_offset_x*tsz_x, dst_offset_y*tsz_y, // offset in output image
+                    sz_x, sz_y, // Size in output image
+                    buffer, sz_x, sz_y, // Buffer and size in buffer
+                    eDataType, // Requested type
+                    pixel_size, line_size
 #if GDAL_VERSION_MAJOR >= 2
                     ,NULL
 #endif
@@ -433,21 +431,21 @@ CPLErr GDALMRFDataset::PatchOverview(int BlockX,int BlockY,
                     // TODO ?
                     CPLError(CE_Failure, CPLE_AppDefined, "RasterIO() failed");
                 }
-	    }
+            }
 
-	    // Mark the input data as no longer needed, saves RAM
-	    for (int band=0; band<bands; band++)
-		src_b[band]->FlushCache();
-	}
+            // Mark the input data as no longer needed, saves RAM
+            for (int band=0; band<bands; band++)
+                src_b[band]->FlushCache();
+        }
     }
 
     CPLFree(buffer);
 
     for (int band=0; band<bands; band++)
-	dst_b[band]->FlushCache(); // Commit the output to disk
+        dst_b[band]->FlushCache(); // Commit the output to disk
 
     if (!recursive)
-	return CE_None;
+        return CE_None;
     return PatchOverview( BlockXOut, BlockYOut, WidthOut, HeightOut, srcLevel+1, true);
 }
 
diff --git a/frmts/mrf/mrf_util.cpp b/frmts/mrf/mrf_util.cpp
index ec12357..e558a68 100644
--- a/frmts/mrf/mrf_util.cpp
+++ b/frmts/mrf/mrf_util.cpp
@@ -4,18 +4,18 @@
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-*   2. Redistributions in binary form must reproduce the above copyright notice, 
+*   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL), 
-*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to 
+*   3. Neither the name of the California Institute of Technology (Caltech), its operating division the Jet Propulsion Laboratory (JPL),
+*      the National Aeronautics and Space Administration (NASA), nor the names of its contributors may be used to
 *      endorse or promote products derived from this software without specific prior written permission.
 *
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
-* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
-* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
-* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
-* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+* IN NO EVENT SHALL THE CALIFORNIA INSTITUTE OF TECHNOLOGY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Copyright 2014-2015 Esri
@@ -33,7 +33,6 @@
 * limitations under the License.
 */
 
-
 /**
  *
  *  Functions used by the driver, should have prototypes in the header file
@@ -45,6 +44,8 @@
 #include <zlib.h>
 #include <algorithm>
 
+CPL_CVSID("$Id: mrf_util.cpp 36776 2016-12-10 11:17:47Z rouault $");
+
 // LERC is not ready for big endian hosts for now
 #if defined(LERC) && defined(WORDS_BIGENDIAN)
 #undef LERC
@@ -59,15 +60,15 @@ NAMESPACE_MRF_START
 // These have to be positionally in sync with the enums in marfa.h
 static const char * const ILC_N[] = { "PNG", "PPNG", "JPEG", "JPNG", "NONE", "DEFLATE", "TIF",
 #if defined(LERC)
-	"LERC", 
+        "LERC",
 #endif
-	"Unknown" };
+        "Unknown" };
 
-static const char * const ILC_E[]={ ".ppg", ".ppg", ".pjg", ".pjp", ".til", ".pzp", ".ptf", 
+static const char * const ILC_E[]={ ".ppg", ".ppg", ".pjg", ".pjp", ".til", ".pzp", ".ptf",
 #if defined(LERC)
-	".lrc" ,
+        ".lrc" ,
 #endif
-	"" };
+        "" };
 
 static const char * const ILO_N[]={ "PIXEL", "BAND", "LINE", "Unknown" };
 
@@ -78,7 +79,7 @@ char const * const * ILOrder_Name=ILO_N;
 /**
  *  Get the string for a compression type
  */
-const char *CompName(ILCompression comp) 
+const char *CompName(ILCompression comp)
 {
     if (comp>=IL_ERR_COMP) return ILComp_Name[IL_ERR_COMP];
     return ILComp_Name[comp];
@@ -87,36 +88,36 @@ const char *CompName(ILCompression comp)
 /**
  *  Get the string for an order type
  */
-const char *OrderName(ILOrder val) 
+const char *OrderName(ILOrder val)
 {
     if (val>=IL_ERR_ORD) return ILOrder_Name[IL_ERR_ORD];
     return ILOrder_Name[val];
 }
 
-ILCompression CompToken(const char *opt, ILCompression def) 
+ILCompression CompToken(const char *opt, ILCompression def)
 {
     int i;
     if (NULL==opt) return def;
     for (i=0; ILCompression(i) < IL_ERR_COMP; i++)
-	if (EQUAL(opt,ILComp_Name[i]))
-	    break;
-    if (IL_ERR_COMP == ILCompression(i)) 
-	return def;
+        if (EQUAL(opt,ILComp_Name[i]))
+            break;
+    if (IL_ERR_COMP == ILCompression(i))
+        return def;
     return ILCompression(i);
 }
 
 /**
  *  Find a compression token
  */
-ILOrder OrderToken(const char *opt, ILOrder def) 
+ILOrder OrderToken(const char *opt, ILOrder def)
 {
     int i;
     if (NULL==opt) return def;
     for (i=0; ILOrder(i)<IL_ERR_ORD; i++)
-	if (EQUAL(opt,ILOrder_Name[i]))  
-	    break;
-    if (IL_ERR_ORD==ILOrder(i)) 
-	return def;
+        if (EQUAL(opt,ILOrder_Name[i]))
+            break;
+    if (IL_ERR_ORD==ILOrder(i))
+        return def;
     return ILOrder(i);
 }
 
@@ -125,8 +126,8 @@ ILOrder OrderToken(const char *opt, ILOrder def)
 //
 std::ostream& operator<<(std::ostream &out, const ILSize& sz)
 {
-    out << "X=" << sz.x << ",Y=" << sz.y << ",Z=" << sz.z 
-	<< ",C=" << sz.c << ",L=" << sz.l;
+    out << "X=" << sz.x << ",Y=" << sz.y << ",Z=" << sz.z
+        << ",C=" << sz.c << ",L=" << sz.l;
     return out;
 }
 
@@ -158,7 +159,7 @@ void ppmWrite(const char *fname, const char *data, const ILSize &sz) {
         fwrite(data,sz.x,sz.y,fp);
         break;
     default:
-        fprintf(stderr,"Can't write ppm file with %d bands\n",sz.c);
+        fprintf(stderr,"Can't write ppm file with %d bands\n",sz.c);/*ok*/
         return;
     }
     fclose(fp);
@@ -173,30 +174,30 @@ GIntBig IdxSize(const ILImage &full, const int scale) {
     GIntBig sz = img.pagecount.l;
     while (scale != 0 && 1 != img.pagecount.x * img.pagecount.y)
     {
-	img.size.x = pcount(img.size.x, scale);
-	img.size.y = pcount(img.size.y, scale);
-	img.pagecount = pcount(img.size, img.pagesize);
-	sz += img.pagecount.l;
+        img.size.x = pcount(img.size.x, scale);
+        img.size.y = pcount(img.size.y, scale);
+        img.pagecount = pcount(img.size, img.pagesize);
+        sz += img.pagecount.l;
     }
     return sz*sizeof(ILIdx);
 }
 
-ILImage::ILImage()
-{
-    dataoffset = idxoffset = 0;
-    quality = 85;
-    size = ILSize(1, 1, 1, 1, 0);
-    pagesize = ILSize(384, 384, 1, 1, 0);
-    pagecount = pcount(size, pagesize);
-    comp = IL_PNG;
-    order = IL_Interleaved;
-    ci = GCI_Undefined;
-    pageSizeBytes = 0;
-    nbo = 0;
-    hasNoData = FALSE;
-    NoDataValue = 0.0;
-    dt = GDT_Unknown;
-}
+ILImage::ILImage() :
+    dataoffset(0),
+    idxoffset(0),
+    quality(85),
+    pageSizeBytes(0),
+    size(ILSize(1, 1, 1, 1, 0)),
+    pagesize(ILSize(384, 384, 1, 1, 0)),
+    pagecount(pcount(size, pagesize)),
+    comp(IL_PNG),
+    order(IL_Interleaved),
+    nbo(0),
+    hasNoData(FALSE),
+    NoDataValue(0.0),
+    dt(GDT_Unknown),
+    ci(GCI_Undefined)
+{}
 
 /**
  *\brief Get a file name by replacing the extension.
@@ -206,56 +207,56 @@ ILImage::ILImage()
  * parameters are preserved.
  */
 
-CPLString getFname(const CPLString &in, const char *ext) 
+CPLString getFname(const CPLString &in, const char *ext)
 {
     if (strlen(in) < strlen(ext))
-	return CPLString(ext);
+        return CPLString(ext);
 
     CPLString ret(in);
     // Is it a web file with parameters?
     size_t extlen = strlen(ext);
     size_t qmark = ret.find_first_of('?');
     if (!(qmark != std::string::npos && 0 == in.find("/vsicurl/http") && qmark >= extlen))
-	qmark = ret.size();
+        qmark = ret.size();
     return ret.replace(qmark - extlen, extlen, ext);
 }
 
 /**
  *\brief Get a file name, either from the configuration or from the default file name
- * If the token is not defined by CPLGetXMLValue, if the extension of the in name is .xml, 
- * it returns the token with the extension changed to defext.  
+ * If the token is not defined by CPLGetXMLValue, if the extension of the in name is .xml,
+ * it returns the token with the extension changed to defext.
  * Otherwise it returns the token itself
  * It is pretty hard to separate local vs remote due to the gdal file name ornaments
  * Absolute file names start with: ?:/ or /
- * 
+ *
  */
 
-CPLString getFname(CPLXMLNode *node, const char *token, const CPLString &in, const char *def) 
+CPLString getFname(CPLXMLNode *node, const char *token, const CPLString &in, const char *def)
 {
     CPLString fn = CPLGetXMLValue(node, token, "");
-    if (fn.size() == 0) // Not provided
-	return getFname(in, def);
+    if (fn.empty()) // Not provided
+        return getFname(in, def);
     size_t slashPos = fn.find_first_of("\\/");
 
     // Does it look like an absolute path or we wont't find the basename of in
-    if (slashPos == 0				    // Starts with slash
-	|| (slashPos == 2 && fn[1] == ':')	    // Starts with disk letter column
-	|| !(slashPos == fn.find_first_not_of('.')) // Does not start with dots and then slash
-	|| in.find_first_of("\\/") == in.npos)      // We con't get a basename from in
-	return fn;
+    if (slashPos == 0                               // Starts with slash
+        || (slashPos == 2 && fn[1] == ':')          // Starts with disk letter column
+        || !(slashPos == fn.find_first_not_of('.')) // Does not start with dots and then slash
+        || EQUALN(in,"<MRF_META>",10)               // XML string input
+        || in.find_first_of("\\/") == in.npos)      // We can't get a basename from in
+        return fn;
 
     // Relative path, prepand the path from the in file name
     return in.substr(0, in.find_last_of("\\/")+1) + fn;
 }
 
-
 /**
- *\Brief Extracts a numerical value from a XML node
+ *\brief Extracts a numerical value from a XML node
  * It works like CPLGetXMLValue except for the default value being
  * a number instead of a string
  */
 
-double getXMLNum(CPLXMLNode *node, const char *pszPath, double def) 
+double getXMLNum(CPLXMLNode *node, const char *pszPath, double def)
 {
     const char *textval=CPLGetXMLValue(node,pszPath,NULL);
     if (textval) return atof(textval);
@@ -266,12 +267,12 @@ double getXMLNum(CPLXMLNode *node, const char *pszPath, double def)
 // Calculate offset of index, pos is in pages
 //
 
-GIntBig IdxOffset(const ILSize &pos, const ILImage &img) 
+GIntBig IdxOffset(const ILSize &pos, const ILImage &img)
 {
     return img.idxoffset + sizeof(ILIdx) *
-	(pos.c + img.pagecount.c * (
+        (pos.c + img.pagecount.c * (
          pos.x+img.pagecount.x * (
-         pos.y+img.pagecount.y * 
+         pos.y+img.pagecount.y *
          static_cast<GIntBig>(pos.z)
         )));
 }
@@ -280,15 +281,15 @@ GIntBig IdxOffset(const ILSize &pos, const ILImage &img)
 bool is_Endianess_Dependent(GDALDataType dt, ILCompression comp) {
     // Add here all endianness dependent compressions
     if (IL_ZLIB == comp || IL_NONE == comp)
-	if (GDALGetDataTypeSize( dt ) > 8)
-	    return true;
+        if (GDALGetDataTypeSize( dt ) > 8)
+            return true;
     return false;
 }
 
 GDALMRFRasterBand *newMRFRasterBand(GDALMRFDataset *pDS, const ILImage &image, int b, int level)
 
 {
-    GDALMRFRasterBand *bnd;
+    GDALMRFRasterBand *bnd = NULL;
     switch(pDS->current.comp)
     {
     case IL_PPNG: // Uses the PNG code, just has a palette in each PNG
@@ -303,13 +304,13 @@ GDALMRFRasterBand *newMRFRasterBand(GDALMRFDataset *pDS, const ILImage &image, i
     case IL_LERC: bnd = new LERC_Band(pDS, image, b, level); break;
 #endif
     default:
-	return NULL; 
+        return NULL;
     }
 
     // If something was flagged during band creation
     if (CPLGetLastErrorNo() != CE_None) {
-	delete bnd;
-	return NULL;
+        delete bnd;
+        return NULL;
     }
 
     // Copy the RW mode from the dataset
@@ -318,20 +319,20 @@ GDALMRFRasterBand *newMRFRasterBand(GDALMRFDataset *pDS, const ILImage &image, i
 }
 
 /**
- *\Brief log in a given base 
+ *\brief log in a given base
  */
-double logb(double val, double base) {
-    return log(val)/log(base);
+double logbase(double val, double base) {
+    return log(val) / log(base);
 }
 
 /**
- *\Brief Is logb(val) an integer?
+ *\brief Is logbase(val, base) an integer?
  *
  */
 
 int IsPower(double value, double base) {
-    double v=logb(value, base);
-    return CPLIsEqual(v, int(v+0.5));
+    double v = logbase(value, base);
+    return CPLIsEqual(v, int(v + 0.5));
 }
 
 /************************************************************************/
@@ -339,25 +340,25 @@ int IsPower(double value, double base) {
 /************************************************************************/
 
 /**
- *\Brief Search for a sibling of the root node with a given name.
+ *\brief Search for a sibling of the root node with a given name.
  *
  * Searches only the next siblings of the node passed in for the named element or attribute.
  * If the first character of the pszElement is '=', the search includes the psRoot node
- * 
+ *
  * @param psRoot the root node to search.  This should be a node of type
  * CXT_Element.  NULL is safe.
  *
  * @param pszElement the name of the element or attribute to search for.
  *
  *
- * @return The first matching node or NULL on failure. 
+ * @return The first matching node or NULL on failure.
  */
 
 CPLXMLNode *SearchXMLSiblings( CPLXMLNode *psRoot, const char *pszElement )
 
 {
     if( psRoot == NULL || pszElement == NULL )
-	return NULL;
+        return NULL;
 
     // If the strings starts with '=', skip it and test the root
     // If not, start testing with the next sibling
@@ -365,10 +366,10 @@ CPLXMLNode *SearchXMLSiblings( CPLXMLNode *psRoot, const char *pszElement )
     else psRoot=psRoot->psNext;
 
     for (;psRoot!=NULL;psRoot=psRoot->psNext)
-	if ((psRoot->eType == CXT_Element ||
-	     psRoot->eType == CXT_Attribute)
-	     && EQUAL(pszElement,psRoot->pszValue))
-	    return psRoot;
+        if ((psRoot->eType == CXT_Element ||
+             psRoot->eType == CXT_Attribute)
+             && EQUAL(pszElement,psRoot->pszValue))
+            return psRoot;
 
     return NULL;
 }
@@ -380,10 +381,10 @@ char **CSLAddIfMissing(char **papszList,
     const char *pszName, const char *pszValue)
 {
     if (CSLFetchNameValue(papszList, pszName))
-	return papszList;
+        return papszList;
     return CSLSetNameValue(papszList, pszName, pszValue);
 }
-    
+
 //
 // Print a double so it can be read with strod while preserving precision
 // Unfortunately this is not quite possible or portable enough at this time
@@ -415,7 +416,7 @@ void XMLSetAttributeVal(CPLXMLNode *parent, const char* pszName,
 
     //  Unfortunately the %a doesn't work in VisualStudio scanf or strtod
     //    if (strtod(sVal.c_str(),0) != val)
-    //	sVal.Printf("%a",val);
+    //  sVal.Printf("%a",val);
 }
 
 CPLXMLNode *XMLSetAttributeVal(CPLXMLNode *parent,
@@ -425,7 +426,7 @@ CPLXMLNode *XMLSetAttributeVal(CPLXMLNode *parent,
     XMLSetAttributeVal(node, "x", sz.x, frmt);
     XMLSetAttributeVal(node, "y", sz.y, frmt);
     if (sz.z != 1)
-	XMLSetAttributeVal(node, "z", sz.z, frmt);
+        XMLSetAttributeVal(node, "z", sz.z, frmt);
     XMLSetAttributeVal(node, "c", sz.c, frmt);
     return node;
 }
@@ -438,19 +439,19 @@ void XMLSetAttributeVal(CPLXMLNode *parent,
     const char*pszName, std::vector<double> const &values)
 {
     if (values.empty())
-	return;
+        return;
 
     CPLString value;
     double val = values[0];
     int single_val = true;
     for (int i = 0; i < int(values.size()); i++) {
-	if (val != values[i])
-	    single_val = false;
-	value.append(PrintDouble(values[i]) + " ");
-	value.resize(value.size() - 1); // Cut the last space
+        if (val != values[i])
+            single_val = false;
+        value.append(PrintDouble(values[i]) + " ");
+        value.resize(value.size() - 1); // Cut the last space
     }
     if (single_val)
-	value = PrintDouble(values[0]);
+        value = PrintDouble(values[0]);
     CPLCreateXMLNode(parent, CXT_Attribute, pszName);
     CPLSetXMLValue(parent, pszName, value);
 }
@@ -470,7 +471,7 @@ GDALColorEntry GetXMLColorEntry(CPLXMLNode *p) {
 }
 
 /**
- *\Brief Verify or make a file that big
+ *\brief Verify or make a file that big
  *
  * @return true if size is OK or if extend succeeded
  */
@@ -479,13 +480,13 @@ int CheckFileSize(const char *fname, GIntBig sz, GDALAccess eAccess) {
 
     VSIStatBufL statb;
     if (VSIStatL(fname, &statb))
-	return false;
+        return false;
     if (statb.st_size >= sz)
-	return true;
+        return true;
 
     // Don't change anything unless updating
     if (eAccess != GA_Update)
-	return false;
+        return false;
 
     // There is no ftruncate in VSI, only truncate()
     VSILFILE *ifp = VSIFOpenL(fname, "r+b");
@@ -530,8 +531,8 @@ int ZPack(const buf_mgr &src, buf_mgr &dst, int flags) {
 
     err = deflate(&stream, Z_FINISH);
     if (err != Z_STREAM_END) {
-	deflateEnd(&stream);
-	return false;
+        deflateEnd(&stream);
+        return false;
     }
     dst.size = stream.total_out;
     err = deflateEnd(&stream);
@@ -558,8 +559,8 @@ int ZUnPack(const buf_mgr &src, buf_mgr &dst, int flags) {
 
     err = inflate(&stream, Z_FINISH);
     if (err != Z_STREAM_END) {
-	inflateEnd(&stream);
-	return false;
+        inflateEnd(&stream);
+        return false;
     }
     dst.size = stream.total_out;
     err = inflateEnd(&stream);
@@ -574,62 +575,68 @@ NAMESPACE_MRF_END
 
 USING_NAMESPACE_MRF
 
-void GDALRegister_mrf(void)
+void GDALRegister_mrf()
 
 {
-    GDALDriver *driver;
+    if( GDALGetDriverByName("MRF") != NULL )
+        return;
 
-    if (GDALGetDriverByName("MRF") == NULL) {
-        driver = new GDALDriver();
-        driver->SetDescription("MRF");
-        driver->SetMetadataItem(GDAL_DMD_LONGNAME, "Meta Raster Format");
-        driver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_marfa.html");
-        driver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
+    GDALDriver *driver = new GDALDriver();
+    driver->SetDescription("MRF");
+    driver->SetMetadataItem(GDAL_DMD_LONGNAME, "Meta Raster Format");
+    driver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_marfa.html");
+    driver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
 
 #if GDAL_VERSION_MAJOR >= 2
-        driver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    driver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
 #endif
 
-        // These will need to be revisited, do we support complex data types too?
-        driver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
-            "Byte UInt16 Int16 Int32 UInt32 Float32 Float64");
+    // These will need to be revisited, do we support complex data types too?
+    driver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
+                            "Byte UInt16 Int16 Int32 UInt32 Float32 Float64");
 
-        driver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
-            "<CreationOptionList>"
-            "   <Option name='COMPRESS' type='string-select' default='PNG' description='PPNG = Palette PNG; DEFLATE = zlib '>"
-            "	    <Value>JPEG</Value><Value>PNG</Value><Value>PPNG</Value><Value>JPNG</Value>"
-            "	    <Value>TIF</Value><Value>DEFLATE</Value><Value>NONE</Value>"
+    driver->SetMetadataItem(
+        GDAL_DMD_CREATIONOPTIONLIST,
+        "<CreationOptionList>"
+        "   <Option name='COMPRESS' type='string-select' default='PNG' description='PPNG = Palette PNG; DEFLATE = zlib '>"
+        "       <Value>JPEG</Value><Value>PNG</Value><Value>PPNG</Value><Value>JPNG</Value>"
+        "       <Value>TIF</Value><Value>DEFLATE</Value><Value>NONE</Value>"
 #if defined(LERC)
-            "	    <Value>LERC</Value>"
+        "       <Value>LERC</Value>"
 #endif
-            "   </Option>"
-            "   <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
-            "       <Value>PIXEL</Value>"
-            "       <Value>BAND</Value>"
-            "   </Option>\n"
-            "	<Option name='ZSIZE' type='int' description='Third dimension size' default='1'/>"
-            "   <Option name='QUALITY' type='int' description='best=99, bad=0, default=85'/>\n"
-            "	<Option name='OPTIONS' type='string' description='Freeform dataset parameters'/>\n"
-            "   <Option name='BLOCKSIZE' type='int' description='Block size, both x and y, default 512'/>\n"
-            "   <Option name='BLOCKXSIZE' type='int' description='Block x size, default=512'/>\n"
-            "   <Option name='BLOCKYSIZE' type='int' description='Block y size, default=512'/>\n"
-            "   <Option name='NETBYTEORDER' type='boolean' description='Force endian for certain compress options, default is host order'/>\n"
-            "	<Option name='CACHEDSOURCE' type='string' description='The source raster, if this is a cache'/>\n"
-            "	<Option name='UNIFORM_SCALE' type='int' description='Scale of overlays in MRF, usually 2'/>\n"
-            "	<Option name='NOCOPY' type='boolean' description='Leave created MRF empty, default=no'/>\n"
-            "   <Option name='PHOTOMETRIC' type='string-select' default='DEFAULT' description='Band interpretation, may affect block encoding'>\n"
-            "	    <Value>MULTISPECTRAL</Value>"
-            "	    <Value>RGB</Value>"
-            "	    <Value>YCC</Value>"
-            "   </Option>\n"
-            "</CreationOptionList>\n"
-            );
-
-        driver->pfnOpen = GDALMRFDataset::Open;
-        driver->pfnIdentify = GDALMRFDataset::Identify;
-        driver->pfnCreateCopy = GDALMRFDataset::CreateCopy;
-        driver->pfnCreate = GDALMRFDataset::Create;
-        driver->pfnDelete = GDALMRFDataset::Delete;
-        GetGDALDriverManager()->RegisterDriver(driver);
-    }
+        "   </Option>"
+        "   <Option name='INTERLEAVE' type='string-select' default='PIXEL'>"
+        "       <Value>PIXEL</Value>"
+        "       <Value>BAND</Value>"
+        "   </Option>\n"
+        "   <Option name='ZSIZE' type='int' description='Third dimension size' default='1'/>"
+        "   <Option name='QUALITY' type='int' description='best=99, bad=0, default=85'/>\n"
+        "   <Option name='OPTIONS' type='string' description='Freeform dataset parameters'/>\n"
+        "   <Option name='BLOCKSIZE' type='int' description='Block size, both x and y, default 512'/>\n"
+        "   <Option name='BLOCKXSIZE' type='int' description='Block x size, default=512'/>\n"
+        "   <Option name='BLOCKYSIZE' type='int' description='Block y size, default=512'/>\n"
+        "   <Option name='NETBYTEORDER' type='boolean' "
+                    "description='Force endian for certain compress options, default is host order'/>\n"
+        "   <Option name='CACHEDSOURCE' type='string' "
+                    "description='The source raster, if this is a cache'/>\n"
+        "   <Option name='UNIFORM_SCALE' type='int' description='Scale of overlays in MRF, usually 2'/>\n"
+        "   <Option name='NOCOPY' type='boolean' description='Leave created MRF empty, default=no'/>\n"
+        "   <Option name='DATANAME' type='string' description='Data file name'/>\n"
+        "   <Option name='INDEXNAME' type='string' description='Index file name'/>\n"
+        "   <Option name='SPACING' type='int' "
+                    "description='Leave this many unused bytes before each tile, default=0'/>\n"
+        "   <Option name='PHOTOMETRIC' type='string-select' default='DEFAULT' "
+                    "description='Band interpretation, may affect block encoding'>\n"
+        "       <Value>MULTISPECTRAL</Value>"
+        "       <Value>RGB</Value>"
+        "       <Value>YCC</Value>"
+        "   </Option>\n"
+        "</CreationOptionList>\n");
+
+    driver->pfnOpen = GDALMRFDataset::Open;
+    driver->pfnIdentify = GDALMRFDataset::Identify;
+    driver->pfnCreateCopy = GDALMRFDataset::CreateCopy;
+    driver->pfnCreate = GDALMRFDataset::Create;
+    driver->pfnDelete = GDALMRFDataset::Delete;
+    GetGDALDriverManager()->RegisterDriver(driver);
 }
diff --git a/frmts/mrsid/frmt_jp2mrsid.html b/frmts/mrsid/frmt_jp2mrsid.html
index c95e756..f3e1322 100644
--- a/frmts/mrsid/frmt_jp2mrsid.html
+++ b/frmts/mrsid/frmt_jp2mrsid.html
@@ -13,6 +13,30 @@ is also supported for writing with the MrSID ESDK.<p>
 JPEG2000 MrSID support is only available with the version 5.x or newer
 DSDK and ESDK.<p>
 
+<h2><a name="georeferencing">Georeferencing</a></h2>
+
+<p>
+Georeferencing information can come from different sources : internal (GeoJP2
+or GMLJP2 boxes), worldfile .j2w/.wld sidecar files, or PAM (Persitant Auxiliary metadata)
+.aux.xml sidecar files.
+By default, information is fetched in following order (first listed is the most
+prioritary): PAM, GeoJP2, GMLJP2, WORLDFILE.
+</p>
+<p>Starting with GDAL 2.2, the allowed sources
+and their priority order can be changed with the GDAL_GEOREF_SOURCES
+configuration option (or GEOREF_SOURCES open option) whose value is a
+comma-separated list of the following keywords :
+PAM, GEOJP2, GMLJP2, INTERNAL (shortcut for GEOJP2,GMLJP2), WORLDFILE, NONE.
+First mentioned sources are the most prioritary over the next ones. A non mentioned
+source will be ignored.
+</p>
+<p>
+For example setting it to "WORLDFILE,PAM,INTERNAL" will make a geotransformation
+matrix from a potential worldfile prioritary over PAM or internal JP2 boxes.
+Setting it to "PAM,WORLDFILE,GEOJP2" will use the mentioned sources and
+ignore GMLJP2 boxes.
+</p>
+
 <h2>Creation Options</h2>
 
 If you have the MrSID ESDK (5.x or newer), it can be used to write JPEG2000
diff --git a/frmts/mrsid/mrsiddataset.cpp b/frmts/mrsid/mrsiddataset.cpp
index 0074a83..b62e4e7 100644
--- a/frmts/mrsid/mrsiddataset.cpp
+++ b/frmts/mrsid/mrsiddataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: mrsiddataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  Multi-resolution Seamless Image Database (MrSID)
  * Purpose:  Read/write LizardTech's MrSID file format - Version 4+ SDK.
@@ -44,7 +43,7 @@
 #include <geo_normalize.h>
 #include <geovalues.h>
 
-CPL_CVSID("$Id: mrsiddataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: mrsiddataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 CPL_C_START
 double GTIFAngleToDD( double dfAngle, int nUOMAngle );
@@ -55,6 +54,12 @@ CPL_C_END
 //   MRSID_ESDK: Means we have the encoding SDK (version 5 or newer required)
 //   MRSID_J2K: Means we are enabling MrSID SDK JPEG2000 support.
 
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
+
 #include "lt_types.h"
 #include "lt_base.h"
 #include "lt_fileSpec.h"
@@ -106,6 +111,10 @@ CPL_C_END
 # endif
 #endif /* MRSID_ESDK */
 
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
 #ifdef MRSID_POST5
 #  define MRSID_HAVE_GETWKT
 #endif
@@ -154,7 +163,7 @@ template <class T>
 class LTIDLLNavigator : public T
 {
 public:
-   LTIDLLNavigator(const LTIImage& image ) : T(image) {}
+   explicit LTIDLLNavigator(const LTIImage& image ) : T(image) {}
    virtual ~LTIDLLNavigator() {};
 };
 
@@ -173,7 +182,7 @@ template <class T>
 class LTIDLLCopy : public T
 {
 public:
-   LTIDLLCopy(const T& original) : T(original) {}
+   explicit LTIDLLCopy(const T& original) : T(original) {}
    virtual ~LTIDLLCopy() {};
 };
 
@@ -181,7 +190,7 @@ template <class T>
 class LTIDLLWriter : public T
 {
 public:
-    LTIDLLWriter(LTIImageStage *image) : T(image) {}
+    explicit LTIDLLWriter(LTIImageStage *image) : T(image) {}
     virtual ~LTIDLLWriter() {}
 };
 
@@ -275,21 +284,21 @@ class MrSIDDataset : public GDALJP2AbstractDataset
                                    int, int, GDALDataType, int, int *,
                                    GSpacing nPixelSpace, GSpacing nLineSpace,
                                    GSpacing nBandSpace,
-                                   GDALRasterIOExtraArg* psExtraArg);
+                                   GDALRasterIOExtraArg* psExtraArg) override;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
     virtual CPLErr      IBuildOverviews( const char *, int, int *,
-                                         int, int *, GDALProgressFunc, void * );
+                                         int, int *, GDALProgressFunc, void * ) override;
 
   public:
-                MrSIDDataset(int bIsJPEG2000);
+    explicit    MrSIDDataset(int bIsJPEG2000);
                 ~MrSIDDataset();
 
     static GDALDataset  *Open( GDALOpenInfo * poOpenInfo, int bIsJP2 );
 
-    virtual char      **GetFileList();
+    virtual char      **GetFileList() override;
 
 #ifdef MRSID_ESDK
     static GDALDataset  *Create( const char * pszFilename,
@@ -328,18 +337,18 @@ class MrSIDRasterBand : public GDALPamRasterBand
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
-    CPLErr                  SetColorInterpretation( GDALColorInterp eNewInterp );
-    virtual double          GetNoDataValue( int * );
-    virtual int             GetOverviewCount();
-    virtual GDALRasterBand  *GetOverview( int );
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    CPLErr                  SetColorInterpretation( GDALColorInterp eNewInterp ) override;
+    virtual double          GetNoDataValue( int * ) override;
+    virtual int             GetOverviewCount() override;
+    virtual GDALRasterBand  *GetOverview( int ) override;
 
     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
                                   double *pdfMin, double *pdfMax,
-                                  double *pdfMean, double *pdfStdDev );
+                                  double *pdfMean, double *pdfStdDev ) override;
 
 #ifdef MRSID_ESDK
     virtual CPLErr          IWriteBlock( int, int, void * );
@@ -376,7 +385,6 @@ MrSIDRasterBand::MrSIDRasterBand( MrSIDDataset *poDSIn, int nBandIn )
                                          static_cast<lt_uint16>(poDSIn->nBands),
                                          poDSIn->eSampleType );
 
-
 /* -------------------------------------------------------------------- */
 /*      Set NoData values.                                              */
 /*                                                                      */
@@ -421,7 +429,7 @@ MrSIDRasterBand::MrSIDRasterBand( MrSIDDataset *poDSIn, int nBandIn )
                  break;
 
              case LTI_DATATYPE_INVALID:
-                 CPLAssert( FALSE );
+                 CPLAssert( false );
                  break;
          }
          bNoDataSet = TRUE;
@@ -749,6 +757,8 @@ GDALRasterBand *MrSIDRasterBand::GetOverview( int i )
 MrSIDDataset::MrSIDDataset(int bIsJPEG2000) :
     nBlockXSize(0),
     nBlockYSize(0),
+    eSampleType(LTI_DATATYPE_UINT8),
+    eDataType(GDT_Byte),
     eColorSpace(LTI_COLORSPACE_INVALID)
 {
     poStream = NULL;
@@ -759,9 +769,7 @@ MrSIDDataset::MrSIDDataset(int bIsJPEG2000) :
     poLTINav = NULL;
     poMetadata = NULL;
     poNDPixel = NULL;
-    eSampleType = LTI_DATATYPE_UINT8;
     nBands = 0;
-    eDataType = GDT_Byte;
 
     poBuffer = NULL;
     bPrevBlockRead = FALSE;
@@ -987,15 +995,15 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
                 oLTIBuffer.myGetTotalBandData( static_cast<lt_uint16>(panBandMap[iBand] - 1) );
 
             for( int iLine = 0; iLine < nBufYSize; iLine++ )
-	    {
+            {
                 GDALCopyWords( pabySrcBand + iLine*nTmpPixelSize*sceneWidth,
                                eDataType, nTmpPixelSize,
                                ((GByte *)pData) + iLine*nLineSpace
                                + iBand * nBandSpace,
                                eBufType, static_cast<int>(nPixelSpace),
                                nBufXSize );
-	    }
-	}
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1004,16 +1012,16 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
     else
     {
         for( iBufLine = 0; iBufLine < nBufYSize; iBufLine++ )
-	{
+        {
             int iTmpLine = (int) floor(((iBufLine+0.5) / nBufYSize)*sceneHeight);
 
             for( iBufPixel = 0; iBufPixel < nBufXSize; iBufPixel++ )
-	    {
+            {
                 int iTmpPixel = (int)
                     floor(((iBufPixel+0.5) / nBufXSize) * sceneWidth);
 
                 for( int iBand = 0; iBand < nBandCount; iBand++ )
-		{
+                {
                     GByte *pabySrc, *pabyDst;
 
                     pabyDst = ((GByte *) pData)
@@ -1030,9 +1038,9 @@ CPLErr MrSIDDataset::IRasterIO( GDALRWFlag eRWFlag,
                     else
                         GDALCopyWords( pabySrc, eDataType, 0,
                                        pabyDst, eBufType, 0, 1 );
-		}
-	    }
-	}
+                }
+            }
+        }
     }
 
     return CE_None;
@@ -1046,11 +1054,11 @@ CPLErr MrSIDDataset::IBuildOverviews( const char *, int, int *,
                                       int, int *, GDALProgressFunc,
                                       void * )
 {
-	CPLError( CE_Warning, CPLE_AppDefined,
-			  "MrSID overviews are built-in, so building external "
-			  "overviews is unnecessary. Ignoring.\n" );
+        CPLError( CE_Warning, CPLE_AppDefined,
+                          "MrSID overviews are built-in, so building external "
+                          "overviews is unnecessary. Ignoring.\n" );
 
-	return CE_None;
+        return CE_None;
 }
 
 /************************************************************************/
@@ -1108,7 +1116,7 @@ char *MrSIDDataset::SerializeMetadataRec( const LTIMetadataRecord *poMetadataRec
                     break;
             }
 
-            iLength = static_cast<int>(strlen(pszMetadata) + strlen(osTemp) + 2);
+            iLength = static_cast<int>(strlen(pszMetadata) + osTemp.size() + 2);
 
             pszMetadata = (char *)CPLRealloc( pszMetadata, iLength );
             if ( !EQUAL( pszMetadata, "" ) )
@@ -1133,7 +1141,7 @@ int MrSIDDataset::GetMetadataElement( const char *pszKey, void *pValue,
     const LTIMetadataRecord *poMetadataRec = NULL;
     poMetadata->get( pszKey, poMetadataRec );
 
-    if ( !poMetadataRec->isScalar() )
+    if ( poMetadataRec == NULL || !poMetadataRec->isScalar() )
         return FALSE;
 
     // XXX: return FALSE if we have more than one element in metadata record
@@ -1184,7 +1192,7 @@ char** MrSIDDataset::GetFileList()
 {
     char** papszFileList = GDALPamDataset::GetFileList();
 
-    if (osMETFilename.size() != 0)
+    if (!osMETFilename.empty())
         papszFileList = CSLAddString(papszFileList, osMETFilename.c_str());
 
     return papszFileList;
@@ -1321,7 +1329,7 @@ CPLErr MrSIDDataset::OpenZoomLevel( lt_int32 iZoom )
         VSILFILE* fp = VSIFOpenL(pszMETFilename, "rb");
         if (fp)
         {
-            const char* pszLine;
+            const char* pszLine = NULL;
             int nCountLine = 0;
             int nUTMZone = 0;
             int bWGS84 = FALSE;
@@ -1412,7 +1420,6 @@ static GDALDataset* MrSIDOpen( GDALOpenInfo *poOpenInfo )
     return MrSIDDataset::Open( poOpenInfo, FALSE );
 }
 
-
 #ifdef MRSID_J2K
 
 static const unsigned char jpc_header[] =
@@ -1431,9 +1438,7 @@ static int JP2Identify( GDALOpenInfo *poOpenInfo )
 
     if( memcmp( poOpenInfo->pabyHeader, jpc_header, sizeof(jpc_header) ) == 0 )
     {
-        const char *pszExtension;
-
-        pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
+        const char *pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
 
         if( !EQUAL(pszExtension,"jpc") && !EQUAL(pszExtension,"j2k")
             && !EQUAL(pszExtension,"jp2") && !EQUAL(pszExtension,"jpx")
@@ -1482,10 +1487,9 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    MrSIDDataset    *poDS;
     LT_STATUS       eStat;
 
-    poDS = new MrSIDDataset(bIsJP2);
+    MrSIDDataset *poDS = new MrSIDDataset(bIsJP2);
 
     // try the LTIOFileStream first, since it uses filesystem caching
     eStat = poDS->oLTIStream.initialize( poOpenInfo->pszFilename, "rb" );
@@ -1685,7 +1689,7 @@ GDALDataset *MrSIDDataset::Open( GDALOpenInfo * poOpenInfo, int bIsJP2 )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1704,55 +1708,55 @@ static int EPSGProjMethodToCTProjMethod( int nEPSG )
     switch( nEPSG )
     {
       case 9801:
-        return( CT_LambertConfConic_1SP );
+        return CT_LambertConfConic_1SP;
 
       case 9802:
-        return( CT_LambertConfConic_2SP );
+        return CT_LambertConfConic_2SP;
 
       case 9803:
-        return( CT_LambertConfConic_2SP ); /* Belgian variant not supported */
+        return CT_LambertConfConic_2SP;  // Belgian variant not supported.
 
       case 9804:
-        return( CT_Mercator );  /* 1SP and 2SP not differentiated */
+        return CT_Mercator;  // 1SP and 2SP not differentiated.
 
       case 9805:
-        return( CT_Mercator );  /* 1SP and 2SP not differentiated */
+        return CT_Mercator;  // 1SP and 2SP not differentiated.
 
       case 9806:
-        return( CT_CassiniSoldner );
+        return CT_CassiniSoldner;
 
       case 9807:
-        return( CT_TransverseMercator );
+        return CT_TransverseMercator;
 
       case 9808:
-        return( CT_TransvMercator_SouthOriented );
+        return CT_TransvMercator_SouthOriented;
 
       case 9809:
-        return( CT_ObliqueStereographic );
+        return CT_ObliqueStereographic;
 
       case 9810:
-        return( CT_PolarStereographic );
+        return CT_PolarStereographic;
 
       case 9811:
-        return( CT_NewZealandMapGrid );
+        return CT_NewZealandMapGrid;
 
       case 9812:
-        return( CT_ObliqueMercator ); /* is hotine actually different? */
+        return CT_ObliqueMercator;  // Is hotine actually different?
 
       case 9813:
-        return( CT_ObliqueMercator_Laborde );
+        return CT_ObliqueMercator_Laborde;
 
       case 9814:
-        return( CT_ObliqueMercator_Rosenmund ); /* swiss  */
+        return CT_ObliqueMercator_Rosenmund;  // Swiss.
 
       case 9815:
-        return( CT_ObliqueMercator );
+        return CT_ObliqueMercator;
 
       case 9816: /* tunesia mining grid has no counterpart */
-        return( KvUserDefined );
+        return KvUserDefined;
     }
 
-    return( KvUserDefined );
+    return KvUserDefined;
 }
 
 /* EPSG Codes for projection parameters.  Unfortunately, these bear no
@@ -1903,7 +1907,7 @@ static int SetGTParmIds( int nCTProjection,
         return TRUE;
 
       default:
-        return( FALSE );
+        return FALSE;
     }
 }
 
@@ -2169,7 +2173,6 @@ void MrSIDDataset::FetchProjParms()
                                    &dfNatOriginLat ) == 0 )
             dfNatOriginLat = 0.0;
 
-
         if( GetMetadataElement( "GEOTIFF_NUM::3092::ProjScaleAtNatOriginGeoKey",
                                 &dfNatOriginScale ) == 0
             && GetMetadataElement( "GEOTIFF_NUM::3093::ProjScaleAtCenterGeoKey",
@@ -2285,7 +2288,7 @@ void MrSIDDataset::FetchProjParms()
         /* notdef: should transform to decimal degrees at this point */
 
         psDefn->ProjParm[0] = dfNatOriginLat;
-        psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;;
+        psDefn->ProjParmId[0] = ProjNatOriginLatGeoKey;
         psDefn->ProjParm[1] = dfNatOriginLong;
         psDefn->ProjParmId[1] = ProjStraightVertPoleLongGeoKey;
         psDefn->ProjParm[4] = dfNatOriginScale;
@@ -2660,7 +2663,6 @@ void MrSIDDataset::GetGTIFDefn()
     pszProjection = GetOGISDefn( psDefn );
 }
 
-
 /************************************************************************/
 /*                       GTIFToCPLRecyleString()                        */
 /*                                                                      */
@@ -2698,11 +2700,11 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefnIn )
 /* -------------------------------------------------------------------- */
     if( psDefnIn->Model == ModelTypeProjected )
     {
-        char    *pszPCSName;
         int     bPCSNameSet = FALSE;
 
         if( psDefnIn->PCS != KvUserDefined )
         {
+            char *pszPCSName = NULL;
 
             if( GTIFGetPCSInfo( psDefnIn->PCS, &pszPCSName, NULL, NULL, NULL ) )
                 bPCSNameSet = TRUE;
@@ -2969,10 +2971,9 @@ char *MrSIDDataset::GetOGISDefn( GTIFDefn *psDefnIn )
 /* -------------------------------------------------------------------- */
 /*      Return the WKT serialization of the object.                     */
 /* -------------------------------------------------------------------- */
-    char        *pszWKT;
-
     oSRS.FixupOrdering();
 
+    char *pszWKT = NULL;
     if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
         return pszWKT;
     else
diff --git a/frmts/mrsid/mrsidstream.cpp b/frmts/mrsid/mrsidstream.cpp
index b0dbedc..81a243a 100644
--- a/frmts/mrsid/mrsidstream.cpp
+++ b/frmts/mrsid/mrsidstream.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: mrsidstream.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  Multi-resolution Seamless Image Database (MrSID)
  * Purpose:  Input/output stream wrapper for usage with LizardTech's
@@ -36,7 +35,7 @@
 #include "cpl_error.h"
 #include "mrsidstream.h"
 
-CPL_CVSID("$Id: mrsidstream.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: mrsidstream.cpp 34811 2016-07-28 15:15:05Z goatbar $");
 
 LT_USE_NAMESPACE(LizardTech)
 
diff --git a/frmts/mrsid_lidar/gdal_MG4Lidar.cpp b/frmts/mrsid_lidar/gdal_MG4Lidar.cpp
index a9bb3db..fb76c52 100644
--- a/frmts/mrsid_lidar/gdal_MG4Lidar.cpp
+++ b/frmts/mrsid_lidar/gdal_MG4Lidar.cpp
@@ -48,9 +48,11 @@ LT_USE_LIDAR_NAMESPACE
 #include "gdal_pam.h"
 // #include "gdal_alg.h" // 1.6 and later have gridding algorithms
 
+CPL_CVSID("$Id: gdal_MG4Lidar.cpp 36501 2016-11-25 14:09:24Z rouault $");
+
 /************************************************************************/
 /* ==================================================================== */
-/*				MG4LidarDataset				*/
+/*                              MG4LidarDataset                         */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -83,8 +85,8 @@ public:
    MG4LidarDataset();
    ~MG4LidarDataset();
    static GDALDataset *Open( GDALOpenInfo * );
-   CPLErr 	GetGeoTransform( double * padfTransform );
-   const char *GetProjectionRef();
+   CPLErr         GetGeoTransform( double * padfTransform ) override;
+   const char *GetProjectionRef() override;
 
 protected:
    MG4PointReader *reader;
@@ -113,11 +115,11 @@ public:
    MG4LidarRasterBand( MG4LidarDataset *, int, CPLXMLNode *, const char * );
    ~MG4LidarRasterBand();
 
-   virtual CPLErr GetStatistics( int bApproxOK, int bForce, double *pdfMin, double *pdfMax, double *pdfMean, double *padfStdDev );
-   virtual int GetOverviewCount();
-   virtual GDALRasterBand * GetOverview( int i );
-   virtual CPLErr IReadBlock( int, int, void * );
-   virtual double GetNoDataValue( int *pbSuccess = NULL );
+   virtual CPLErr GetStatistics( int bApproxOK, int bForce, double *pdfMin, double *pdfMax, double *pdfMean, double *padfStdDev ) override;
+   virtual int GetOverviewCount() override;
+   virtual GDALRasterBand * GetOverview( int i ) override;
+   virtual CPLErr IReadBlock( int, int, void * ) override;
+   virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 
    protected:
    double getMaxValue();
@@ -132,17 +134,16 @@ public:
    CPLString ChannelName;
 };
 
-
 /************************************************************************/
 /*                           MG4LidarRasterBand()                            */
 /************************************************************************/
 
-MG4LidarRasterBand::MG4LidarRasterBand( MG4LidarDataset *pods, int nband, CPLXMLNode *xmlBand, const char * name )
+MG4LidarRasterBand::MG4LidarRasterBand( MG4LidarDataset *pods, int nband, CPLXMLNode *xmlBand, const char * name ) :
+    ChannelName( name )
 {
    this->poDS = pods;
    this->nBand = nband;
    this->poxmlBand = xmlBand;
-   this->ChannelName = name;
    this->Aggregation = NULL;
    nBlockXSize = pods->nBlockXSize;
    nBlockYSize = pods->nBlockYSize;
@@ -308,17 +309,15 @@ const DTYPE GetChannelElement(const ChannelData &channel, size_t idx)
    return retval;
 }
 
-
 bool MG4LidarRasterBand::ElementPassesFilter(const PointData &pointdata, size_t i)
 {
-   bool bClassificationOK = true;
    bool bReturnNumOK = true;
 
    // Check if classification code is ok:  it was requested and it does match one of the requested codes
    const int classcode = GetChannelElement<int>(*pointdata.getChannel(CHANNEL_NAME_ClassId), i);
    char bufCode[16];
    snprintf(bufCode, sizeof(bufCode), "%d", classcode);
-   bClassificationOK = (papszFilterClassCodes == NULL ? true :
+   bool bClassificationOK = (papszFilterClassCodes == NULL ? true :
       (CSLFindString(papszFilterClassCodes,bufCode)!=-1));
 
    if (bClassificationOK)
@@ -336,10 +335,8 @@ bool MG4LidarRasterBand::ElementPassesFilter(const PointData &pointdata, size_t
    }
 
    return bReturnNumOK && bClassificationOK;
-
 }
 
-
 template<typename DTYPE>
 CPLErr   MG4LidarRasterBand::doReadBlock(int nBlockXOff, int nBlockYOff, void * pImage)
 {
@@ -488,7 +485,6 @@ CPLErr MG4LidarRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
       default:
            return CE_Failure;
            break;
-
    }
    return CE_None;
 }
@@ -508,7 +504,6 @@ CPLErr MG4LidarRasterBand::GetStatistics( int bApproxOK, int bForce,
    return GDALPamRasterBand::GetStatistics( bApproxOK, bForce,
       pdfMin, pdfMax,
       pdfMean, pdfStdDev );
-
 }
 /************************************************************************/
 /*                           GetNoDataValue()                           */
@@ -588,7 +583,7 @@ const char *MG4LidarDataset::GetProjectionRef()
    const char * wkt = CPLGetXMLValue(poXMLPCView, "GeoReference", NULL);
    if (wkt == NULL)
       wkt = reader->getWKT();
-   return(wkt);
+   return wkt;
 }
 
 /************************************************************************/
@@ -621,8 +616,6 @@ CPLErr MG4LidarDataset::OpenZoomLevel( int iZoom )
    CPLDebug( "MG4Lidar", "Opened zoom level %d with size %dx%d.\n",
       iZoom, nRasterXSize, nRasterYSize );
 
-
-
    /* -------------------------------------------------------------------- */
    /*  Handle sample type and color space.                                 */
    /* -------------------------------------------------------------------- */
@@ -702,7 +695,7 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
    if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 32 )
       return NULL;
 
-   CPLXMLNode *pxmlPCView;
+   CPLXMLNode *pxmlPCView = NULL;
 
    // do something sensible for .sid files without a .view
    if( STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "msid") )
@@ -769,7 +762,7 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
    /* -------------------------------------------------------------------- */
    /*      Create a corresponding GDALDataset.                             */
    /* -------------------------------------------------------------------- */
-   MG4LidarDataset 	*poDS;
+   MG4LidarDataset *poDS;
 
    poDS = new MG4LidarDataset();
    poDS->poXMLPCView = pxmlPCView;
@@ -906,10 +899,10 @@ GDALDataset *MG4LidarDataset::Open( GDALOpenInfo * poOpenInfo )
       CPLDebug( "MG4Lidar",
          "Inappropriate number of bands (%d)", poDS->nBands );
       delete poDS;
-      return(NULL);
+      return NULL;
    }
 
-   return( poDS );
+   return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/msg/GNUmakefile b/frmts/msg/GNUmakefile
index fef39bc..76635de 100644
--- a/frmts/msg/GNUmakefile
+++ b/frmts/msg/GNUmakefile
@@ -1,20 +1,24 @@
-
-VPATH = PublicDecompWT/DISE/:PublicDecompWT/COMP/Src/:PublicDecompWT/COMP/WT/Src/
-
 include ../../GDALmake.opt
 
-OBJ1=$(patsubst %.cpp,%.o,$(wildcard PublicDecompWT/COMP/WT/Src/*.cpp))
-OBJ2=$(patsubst %.cpp,%.o,$(wildcard PublicDecompWT/COMP/Src/*.cpp))
-OBJ3=$(patsubst %.cpp,%.o,$(wildcard PublicDecompWT/DISE/*.cpp))
-WTOBJ=$(subst PublicDecompWT/COMP/WT/Src/, ,$(OBJ1)) $(subst PublicDecompWT/COMP/Src/, , $(OBJ2)) $(subst PublicDecompWT/DISE/, , $(OBJ3))
-
-OBJ	=	msgdataset.o xritheaderparser.o prologue.o msgcommand.o reflectancecalculator.o $(WTOBJ)
+OBJ	=	msgdataset.o xritheaderparser.o prologue.o msgcommand.o reflectancecalculator.o PublicDecompWT_all.o
 
-CPPFLAGS	=	 -I PublicDecompWT/DISE -I PublicDecompWT/COMP/WT/Inc -I PublicDecompWT/COMP/Inc -I.
+CPPFLAGS	:=	 -DDO_NOT_USE_DEBUG_BOOL -I PublicDecompWT/DISE -I PublicDecompWT/COMP/WT/Inc -I PublicDecompWT/COMP/Inc -I. $(CPPFLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
 clean:
-	rm -f *.o
+	rm -f *.o PublicDecompWT_all.h
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+PublicDecompWT_all.cpp: PublicDecompWT_all.h
 
-install-obj:	$(O_OBJ:.o=.$(OBJ_EXT)) 
+# Trick to avoid lots of warnings from the PublicDecompWT SDK
+PublicDecompWT_all.h:
+	@echo "// This is a generated file. Do not edit !" > PublicDecompWT_all.h
+	@echo "#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))" >> PublicDecompWT_all.h
+	@echo "#pragma GCC system_header" >> PublicDecompWT_all.h
+	@echo "#endif" >> PublicDecompWT_all.h
+	for x in $(wildcard PublicDecompWT/COMP/WT/Src/*.cpp) $(wildcard PublicDecompWT/COMP/Src/*.cpp) $(wildcard PublicDecompWT/DISE/*.cpp) ; do\
+		echo "#include \"$$x\"" >> PublicDecompWT_all.h; \
+	done
diff --git a/frmts/msg/PublicDecompWT_all.cpp b/frmts/msg/PublicDecompWT_all.cpp
new file mode 100644
index 0000000..1270baf
--- /dev/null
+++ b/frmts/msg/PublicDecompWT_all.cpp
@@ -0,0 +1 @@
+#include "PublicDecompWT_all.h"
diff --git a/frmts/msg/PublicDecompWT_headers.h b/frmts/msg/PublicDecompWT_headers.h
new file mode 100644
index 0000000..c54d8ff
--- /dev/null
+++ b/frmts/msg/PublicDecompWT_headers.h
@@ -0,0 +1,6 @@
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+#include "PublicDecompWT/COMP/WT/Inc/CWTDecoder.h"
+#include "PublicDecompWT/DISE/CDataField.h" // Util namespace
diff --git a/frmts/msg/msgcommand.cpp b/frmts/msg/msgcommand.cpp
index afc3aea..892ee82 100644
--- a/frmts/msg/msgcommand.cpp
+++ b/frmts/msg/msgcommand.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: msgcommand.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Purpose:  Implementation of MSGCommand class. Parse the src_dataset
  *           string that is meant for the MSG driver.
@@ -27,9 +26,14 @@
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************/
 
+ #include "cpl_port.h"  // Must be first.
+
 #include "msgcommand.h"
 #include <cstdlib>
 #include <cstdio>
+
+CPL_CVSID("$Id: msgcommand.cpp 35929 2016-10-25 16:09:00Z goatbar $");
+
 using namespace std;
 
 #ifdef _WIN32
@@ -56,10 +60,7 @@ MSGCommand::MSGCommand() :
     channel[i] = 0;
 }
 
-MSGCommand::~MSGCommand()
-{
-
-}
+MSGCommand::~MSGCommand() {}
 
 std::string MSGCommand::sTrimSpaces(std::string const& str)
 {
@@ -79,9 +80,10 @@ std::string MSGCommand::sTrimSpaces(std::string const& str)
 std::string MSGCommand::sNextTerm(std::string const& str, int & iPos)
 {
   std::string::size_type iOldPos = iPos;
-  iPos = str.find(',', iOldPos);
-  iPos = min(iPos, str.find(')', iOldPos));
-  if (iPos > iOldPos)
+  iPos = static_cast<int>(str.find(',', iOldPos));
+  // FIXME: the int vs size_t is messy !
+  iPos = static_cast<int>(min(static_cast<size_t>(iPos), str.find(')', iOldPos)));
+  if (static_cast<size_t>(iPos) > iOldPos)
   {
     std::string sRet = str.substr(iOldPos, iPos - iOldPos);
     if (str[iPos] != ')')
@@ -92,6 +94,7 @@ std::string MSGCommand::sNextTerm(std::string const& str, int & iPos)
     return "";
 }
 
+static
 bool fTimeStampCorrect(std::string const& sTimeStamp)
 {
   if (sTimeStamp.length() != 12)
@@ -131,38 +134,38 @@ std::string MSGCommand::parse(std::string const& command_line)
       {
         try // for eventual exceptions
         {
-          while ((iPos < command_line.length()) && (command_line[iPos] == ' '))
+          while ((iPos < static_cast<int>(command_line.length())) && (command_line[iPos] == ' '))
             ++iPos;
           if (command_line[iPos] == '(')
           {
             ++iPos; // skip the ( bracket
             int i = 1;
-            std::string sChannel = sNextTerm(command_line, iPos);
+            std::string l_sChannel = sNextTerm(command_line, iPos);
             while (command_line[iPos] != ')')
             {
-              int iChan = atoi(sChannel.c_str());
+              int iChan = atoi(l_sChannel.c_str());
               if (iChan >= 1 && iChan <= 12)
                 channel[iChan - 1] = i;
               else
                 sErr = "Channel numbers must be between 1 and 12";
-              sChannel = sNextTerm(command_line, iPos);
+              l_sChannel = sNextTerm(command_line, iPos);
               ++i;
             }
-            int iChan = atoi(sChannel.c_str());
+            int iChan = atoi(l_sChannel.c_str());
             if (iChan >= 1 && iChan <= 12)
               channel[iChan - 1] = i;
             else
               sErr = "Channel numbers must be between 1 and 12";
             ++iPos; // skip the ) bracket
-            while ((iPos < command_line.length()) && (command_line[iPos] == ' '))
+            while ((iPos < static_cast<int>(command_line.length())) && (command_line[iPos] == ' '))
               ++iPos;
             if (command_line[iPos] == ',')
               ++iPos;
           }
           else
           {
-            std::string sChannel = sNextTerm(command_line, iPos);
-            int iChan = atoi(sChannel.c_str());
+            std::string l_sChannel = sNextTerm(command_line, iPos);
+            int iChan = atoi(l_sChannel.c_str());
             if (iChan >= 1 && iChan <= 12)
               channel[iChan - 1] = 1;
             else
@@ -183,7 +186,7 @@ std::string MSGCommand::parse(std::string const& command_line)
           iStep = atoi(sStep.c_str());
           if (iStep < 1)
             iStep = 1;
-          while ((iPos < command_line.length()) && (command_line[iPos] == ' '))
+          while ((iPos < static_cast<int>(command_line.length())) && (command_line[iPos] == ' '))
             ++iPos;
           // additional correctness checks
           if (command_line[iPos] != ')')
@@ -206,9 +209,9 @@ std::string MSGCommand::parse(std::string const& command_line)
     else
       sErr = "A folder must be filled in indicating the root of the image data folders.";
   }
-  else if (command_line.find("H-000-MSG") >= 0)
+  else if (command_line.find("H-000-MSG") != std::string::npos)
   {
-    int iPos = command_line.find("H-000-MSG");
+    const size_t iPos = command_line.find("H-000-MSG");
     if ((command_line.length() - iPos) == 61)
     {
       fUseTimestampFolder = false;
@@ -262,7 +265,7 @@ int MSGCommand::iChannel(int iChannelNumber)
   }
 
   // will return a number between 1 and 12
-  return (iRet + 1);
+  return iRet + 1;
 }
 
 int MSGCommand::iNrStrips(int iChannel)
@@ -356,7 +359,7 @@ std::string MSGCommand::sTimeStampToFolder(std::string & sTimeStamp)
   std::string sYear (sTimeStamp.substr(0,4));
   std::string sMonth (sTimeStamp.substr(4, 2));
   std::string sDay (sTimeStamp.substr(6, 2));
-  return (sYear + PATH_SEP + sMonth + PATH_SEP + sDay + PATH_SEP);
+  return sYear + PATH_SEP + sMonth + PATH_SEP + sDay + PATH_SEP;
 }
 
 int MSGCommand::iDaysInMonth(int iMonth, int iYear)
@@ -440,7 +443,7 @@ std::string MSGCommand::sCycle(int iCycle)
 std::string MSGCommand::sFileName(int iSatellite, int iSequence, int iStrip)
 {
   int iNr = iNrChannels();
-  int iChannelNumber = 1 + (iSequence - 1) % iNr;;
+  int iChannelNumber = 1 + (iSequence - 1) % iNr;
   int iCycle = 1 + (iSequence - 1) / iNr;
   char sRet [4096];
   std::string siThCycle (sCycle(iCycle));
diff --git a/frmts/msg/msgcommand.h b/frmts/msg/msgcommand.h
index f8114fe..15b4c5d 100644
--- a/frmts/msg/msgcommand.h
+++ b/frmts/msg/msgcommand.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgcommand.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: msgcommand.h 36427 2016-11-22 12:56:01Z rouault $
  *
  * Purpose:  Interface of MSGCommand class. Parse the src_dataset string
  *           that is meant for the MSG driver.
@@ -52,9 +52,9 @@ public:
   int channel[12];
 
 private:
-  std::string sTrimSpaces(std::string const& str);
-  std::string sNextTerm(std::string const& str, int & iPos);
-  int iDaysInMonth(int iMonth, int iYear);
+  static std::string sTrimSpaces(std::string const& str);
+  static std::string sNextTerm(std::string const& str, int & iPos);
+  static int iDaysInMonth(int iMonth, int iYear);
   static std::string sChannel(int iChannel);
   static int iChannel(std::string const& sChannel);
   static std::string sTimeStampToFolder(std::string& sTimeStamp);
diff --git a/frmts/msg/msgdataset.cpp b/frmts/msg/msgdataset.cpp
index 70dff63..955d0ae 100644
--- a/frmts/msg/msgdataset.cpp
+++ b/frmts/msg/msgdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: msgdataset.cpp 33951 2016-04-12 14:51:31Z rouault $
  *
  * Project:  MSG Driver
  * Purpose:  GDALDataset driver for MSG translator for read support.
@@ -27,6 +26,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************/
+#include "cpl_port.h"  // Must be first.
 
 #include "gdal_frmts.h"
 #include "msgdataset.h"
@@ -34,9 +34,9 @@
 #include "xritheaderparser.h"
 #include "reflectancecalculator.h"
 
-#include "PublicDecompWT/COMP/WT/Inc/CWTDecoder.h"
-#include "PublicDecompWT/DISE/CDataField.h" // Util namespace
+#include "PublicDecompWT_headers.h"
 
+#include <memory>
 #include <vector>
 
 #if _MSC_VER > 1000
@@ -45,11 +45,16 @@
 #include <stdio.h>
 #endif
 
+CPL_CVSID("$Id: msgdataset.cpp 36450 2016-11-22 22:30:49Z rouault $");
+
 const double MSGDataset::rCentralWvl[12] = {0.635, 0.810, 1.640, 3.900, 6.250, 7.350, 8.701, 9.660, 10.800, 12.000, 13.400, 0.750};
 const double MSGDataset::rVc[12] = {-1, -1, -1, 2569.094, 1598.566, 1362.142, 1149.083, 1034.345, 930.659, 839.661, 752.381, -1};
 const double MSGDataset::rA[12] = {-1, -1, -1, 0.9959, 0.9963, 0.9991, 0.9996, 0.9999, 0.9983, 0.9988, 0.9981, -1};
 const double MSGDataset::rB[12] = {-1, -1, -1, 3.471, 2.219, 0.485, 0.181, 0.060, 0.627, 0.397, 0.576, -1};
+const int MSGDataset::iCentralPixelVIS_IR = 1856; // center pixel VIS and IR
+const int MSGDataset::iCentralPixelHRV = 5566; // center pixel HRV
 int MSGDataset::iCurrentSatellite = 1; // satellite number 1,2,3,4 for MSG1, MSG2, MSG3 and MSG4
+const char *MSGDataset::metadataDomain = "msg"; // the metadata domain
 
 #define MAX_SATELLITES 4
 
@@ -90,7 +95,7 @@ MSGDataset::~MSGDataset()
 const char *MSGDataset::GetProjectionRef()
 
 {
-  return ( pszProjection );
+  return pszProjection;
 }
 
 /************************************************************************/
@@ -103,7 +108,6 @@ CPLErr MSGDataset::SetProjection( const char * pszNewProjection )
     pszProjection = CPLStrdup( pszNewProjection );
 
     return CE_None;
-
 }
 
 /************************************************************************/
@@ -114,7 +118,7 @@ CPLErr MSGDataset::GetGeoTransform( double * padfTransform )
 
 {
     memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -181,21 +185,19 @@ GDALDataset *MSGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        std::string sErr = "The prologue of the data set could not be found at the location specified:\n" + sPrologueFileName + "\n";
+        std::string l_sErr = "The prologue of the data set could not be found at the location specified:\n" + sPrologueFileName + "\n";
         CPLError( CE_Failure, CPLE_AppDefined, "%s",
-                  sErr.c_str() );
+                  l_sErr.c_str() );
         return FALSE;
     }
 
-
 // We're confident the string is formatted as an MSG command_line
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
 
-    MSGDataset   *poDS;
-    poDS = new MSGDataset();
+    MSGDataset *poDS = new MSGDataset();
     poDS->command = command; // copy it
 
 /* -------------------------------------------------------------------- */
@@ -226,15 +228,17 @@ GDALDataset *MSGDataset::Open( GDALOpenInfo * poOpenInfo )
     {
       rPixelSizeX = 1000 * pp.idr()->ReferenceGridHRV->ColumnDirGridStep;
       rPixelSizeY = 1000 * pp.idr()->ReferenceGridHRV->LineDirGridStep;
-      rMinX = -rPixelSizeX * (pp.idr()->ReferenceGridHRV->NumberOfColumns / 2.0); // assumption: (0,0) falls in centre
-      rMaxY = rPixelSizeY * (pp.idr()->ReferenceGridHRV->NumberOfLines / 2.0);
+      // The MSG Level 1.5 Image Data Format Description (page 22f) defines the center of pixel (5566,5566) from SE as sub satellite point for the HRV channel (0°,0° for operational MSG).
+      rMinX = -rPixelSizeX * (pp.idr()->ReferenceGridHRV->NumberOfColumns - iCentralPixelHRV + 0.5);
+      rMaxY = rPixelSizeY * (pp.idr()->ReferenceGridHRV->NumberOfLines - iCentralPixelHRV + 0.5); //scan direction south -> north
     }
     else
     {
       rPixelSizeX = 1000 * pp.idr()->ReferenceGridVIS_IR->ColumnDirGridStep;
       rPixelSizeY = 1000 * pp.idr()->ReferenceGridVIS_IR->LineDirGridStep;
-      rMinX = -rPixelSizeX * (pp.idr()->ReferenceGridVIS_IR->NumberOfColumns / 2.0); // assumption: (0,0) falls in centre
-      rMaxY = rPixelSizeY * (pp.idr()->ReferenceGridVIS_IR->NumberOfLines / 2.0);
+      // The MSG Level 1.5 Image Data Format Description (page 22f) defines the center of pixel (1856,1856) from SE as sub satellite point for the VIS_IR channels (0°,0° for operational MSG).
+      rMinX = -rPixelSizeX * (pp.idr()->ReferenceGridVIS_IR->NumberOfColumns  - iCentralPixelVIS_IR + 0.5);
+      rMaxY = rPixelSizeY * (pp.idr()->ReferenceGridVIS_IR->NumberOfLines - iCentralPixelVIS_IR + 0.5); // The y scan direction is always south -> north
     }
     poDS->adfGeoTransform[0] = rMinX;
     poDS->adfGeoTransform[3] = rMaxY;
@@ -277,11 +281,10 @@ GDALDataset *MSGDataset::Open( GDALOpenInfo * poOpenInfo )
 /*   Create a transformer to LatLon (only for Reflectance calculation)  */
 /* -------------------------------------------------------------------- */
 
-    char *pszLLTemp;
-    char *pszLLTemp_bak;
+    char *pszLLTemp = NULL;
 
     (poDS->oSRS.GetAttrNode("GEOGCS"))->exportToWkt(&pszLLTemp);
-    pszLLTemp_bak = pszLLTemp; // importFromWkt() changes the pointer
+    char *pszLLTemp_bak = pszLLTemp; // importFromWkt() changes the pointer
     poDS->oLL.importFromWkt(&pszLLTemp);
     CPLFree( pszLLTemp_bak );
 
@@ -315,7 +318,14 @@ GDALDataset *MSGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    return( poDS );
+/* -------------------------------------------------------------------- */
+/*                 Set DataSet metadata information                    */
+/* -------------------------------------------------------------------- */
+    CPLString metadataValue;
+    metadataValue.Printf("%d", poDS->iCurrentSatellite);
+    poDS->SetMetadataItem("satellite_number", metadataValue.c_str(), metadataDomain);
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -324,58 +334,58 @@ GDALDataset *MSGDataset::Open( GDALOpenInfo * poOpenInfo )
 
 const double MSGRasterBand::rRTOA[12] = {20.76, 23.24, 19.85, -1, -1, -1, -1, -1, -1, -1, -1, 25.11};
 
-MSGRasterBand::MSGRasterBand( MSGDataset *poDS, int nBand )
+MSGRasterBand::MSGRasterBand( MSGDataset *poDSIn, int nBandIn )
 : fScanNorth(false)
 , iLowerShift(0)
 , iSplitLine(0)
 , iLowerWestColumnPlanned(0)
 
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
 
     // Find if we're dealing with MSG1, MSG2, MSG3 or MSG4
     // Doing this per band is the only way to guarantee time-series when the satellite is changed
 
-    std::string sPrologueFileName = poDS->command.sPrologueFileName(poDS->iCurrentSatellite, nBand);
+    std::string sPrologueFileName = poDSIn->command.sPrologueFileName(poDSIn->iCurrentSatellite, nBand);
     bool fPrologueExists = (access(sPrologueFileName.c_str(), 0) == 0);
 
     // Make sure we're testing for MSG1,2,3 or 4 exactly once, start with the most recently used, and remember it in the static member for the next round.
     if (!fPrologueExists)
     {
-      poDS->iCurrentSatellite = 1 + poDS->iCurrentSatellite % MAX_SATELLITES;
-      sPrologueFileName = poDS->command.sPrologueFileName(poDS->iCurrentSatellite, nBand);
+      poDSIn->iCurrentSatellite = 1 + poDSIn->iCurrentSatellite % MAX_SATELLITES;
+      sPrologueFileName = poDSIn->command.sPrologueFileName(poDSIn->iCurrentSatellite, nBand);
       fPrologueExists = (access(sPrologueFileName.c_str(), 0) == 0);
       int iTries = 2;
       while (!fPrologueExists && (iTries < MAX_SATELLITES))
       {
-        poDS->iCurrentSatellite = 1 + poDS->iCurrentSatellite % MAX_SATELLITES;
-        sPrologueFileName = poDS->command.sPrologueFileName(poDS->iCurrentSatellite, nBand);
+        poDSIn->iCurrentSatellite = 1 + poDSIn->iCurrentSatellite % MAX_SATELLITES;
+        sPrologueFileName = poDSIn->command.sPrologueFileName(poDSIn->iCurrentSatellite, nBand);
         fPrologueExists = (access(sPrologueFileName.c_str(), 0) == 0);
         ++iTries;
       }
       if (!fPrologueExists) // assume missing prologue file, keep original satellite number
       {
-        poDS->iCurrentSatellite = 1 + poDS->iCurrentSatellite % MAX_SATELLITES;
-        sPrologueFileName = poDS->command.sPrologueFileName(poDS->iCurrentSatellite, nBand);
+        poDSIn->iCurrentSatellite = 1 + poDSIn->iCurrentSatellite % MAX_SATELLITES;
+        sPrologueFileName = poDSIn->command.sPrologueFileName(poDSIn->iCurrentSatellite, nBand);
       }
     }
 
-    iSatellite = poDS->iCurrentSatellite; // From here on, the satellite that corresponds to this band is settled to the current satellite
+    iSatellite = poDSIn->iCurrentSatellite; // From here on, the satellite that corresponds to this band is settled to the current satellite
 
-    nBlockXSize = poDS->GetRasterXSize();
-    nBlockYSize = poDS->GetRasterYSize();
+    nBlockXSize = poDSIn->GetRasterXSize();
+    nBlockYSize = poDSIn->GetRasterYSize();
 
 /* -------------------------------------------------------------------- */
 /*      Open an input file and capture the header for the nr. of bits.  */
 /* -------------------------------------------------------------------- */
     int iStrip = 1;
-    int iChannel = poDS->command.iChannel(1 + ((nBand - 1) % poDS->command.iNrChannels()));
-    std::string input_file = poDS->command.sFileName(iSatellite, nBand, iStrip);
-    while ((access(input_file.c_str(), 0) != 0) && (iStrip <= poDS->command.iNrStrips(iChannel))) // compensate for missing strips
-      input_file = poDS->command.sFileName(iSatellite, nBand, ++iStrip);
+    int iChannel = poDSIn->command.iChannel(1 + ((nBand - 1) % poDSIn->command.iNrChannels()));
+    std::string input_file = poDSIn->command.sFileName(iSatellite, nBand, iStrip);
+    while ((access(input_file.c_str(), 0) != 0) && (iStrip <= poDSIn->command.iNrStrips(iChannel))) // compensate for missing strips
+      input_file = poDSIn->command.sFileName(iSatellite, nBand, ++iStrip);
 
-    if (iStrip <= poDS->command.iNrStrips(iChannel))
+    if (iStrip <= poDSIn->command.iNrStrips(iChannel))
     {
       std::ifstream i_file (input_file.c_str(), std::ios::in|std::ios::binary);
 
@@ -389,9 +399,9 @@ MSGRasterBand::MSGRasterBand( MSGDataset *poDS, int nBand )
           eDataType = GDT_Byte; // default .. always works
           if (xhp.nrBitsPerPixel() > 8)
           {
-            if (poDS->command.cDataConversion == 'N')
+            if (poDSIn->command.cDataConversion == 'N')
               eDataType = GDT_UInt16; // normal case: MSG 10 bits data
-            else if (poDS->command.cDataConversion == 'B')
+            else if (poDSIn->command.cDataConversion == 'B')
               eDataType = GDT_Byte; // output data type Byte
             else
               eDataType = GDT_Float32; // Radiometric calibration
@@ -411,7 +421,7 @@ MSGRasterBand::MSGRasterBand( MSGDataset *poDS, int nBand )
     else if (nBand > 1)
     {
       // missing entire band .. take data from first band
-      MSGRasterBand* pFirstRasterBand = (MSGRasterBand*)poDS->GetRasterBand(1);
+      MSGRasterBand* pFirstRasterBand = (MSGRasterBand*)poDSIn->GetRasterBand(1);
       eDataType = pFirstRasterBand->eDataType;
       nBlockYSize = pFirstRasterBand->nBlockYSize;
       fScanNorth = pFirstRasterBand->fScanNorth;
@@ -419,16 +429,15 @@ MSGRasterBand::MSGRasterBand( MSGDataset *poDS, int nBand )
     else // also first band is missing .. do something for fail-safety
     {
       eDataType = GDT_Byte; // default .. always works
-      if (poDS->command.cDataConversion == 'N')
+      if (poDSIn->command.cDataConversion == 'N')
         eDataType = GDT_UInt16; // normal case: MSG 10 bits data
-      else if (poDS->command.cDataConversion == 'B')
+      else if (poDSIn->command.cDataConversion == 'B')
         eDataType = GDT_Byte; // output data type Byte
       else
         eDataType = GDT_Float32; // Radiometric calibration
 
       // nBlockYSize : default
       // fScanNorth : default
-
     }
 /* -------------------------------------------------------------------- */
 /*      For the HRV band, read the prologue for shift and splitline.    */
@@ -455,10 +464,21 @@ MSGRasterBand::MSGRasterBand( MSGDataset *poDS, int nBand )
 /*  Initialize the ReflectanceCalculator with the band-dependent info.  */
 /* -------------------------------------------------------------------- */
 
-    int iCycle = 1 + (nBand - 1) / poDS->command.iNrChannels();
-    std::string sTimeStamp = poDS->command.sCycle(iCycle);
+    int iCycle = 1 + (nBand - 1) / poDSIn->command.iNrChannels();
+    std::string sTimeStamp = poDSIn->command.sCycle(iCycle);
 
     m_rc = new ReflectanceCalculator(sTimeStamp, rRTOA[iChannel-1]);
+
+/* -------------------------------------------------------------------- */
+/*  Set DataSet metadata information                                   */
+/* -------------------------------------------------------------------- */
+    CPLString metadataValue;
+    metadataValue.Printf("%.10f", poDSIn->rCalibrationOffset[iChannel - 1]);
+    SetMetadataItem("calibration_offset", metadataValue.c_str(), poDSIn->metadataDomain);
+    metadataValue.Printf("%.10f", poDSIn->rCalibrationSlope[iChannel - 1]);
+    SetMetadataItem("calibration_slope", metadataValue.c_str(), poDSIn->metadataDomain);
+    metadataValue.Printf("%d", iChannel);
+    SetMetadataItem("channel_number", metadataValue.c_str(), poDSIn->metadataDomain);
 }
 
 /************************************************************************/
@@ -472,7 +492,7 @@ MSGRasterBand::~MSGRasterBand()
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
-CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
+CPLErr MSGRasterBand::IReadBlock( int /*nBlockXOff*/, int nBlockYOff,
                                   void * pImage )
 
 {
@@ -516,7 +536,7 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
           unsigned short chunk_bpp = xhp.nrBitsPerPixel();
           unsigned short chunk_width = xhp.nrColumns();
           unsigned __int8 NR = (unsigned __int8)chunk_bpp;
-          unsigned int nb_ibytes = xhp.dataSize();
+          unsigned int nb_ibytes = static_cast<unsigned int>(xhp.dataSize());
           int iShift = 0;
           bool fSplitStrip = false; // in the split strip the "shift" only happens before the split "row"
           int iSplitRow = 0;
@@ -536,18 +556,17 @@ CPLErr MSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             // iShift > 0 means upper image moves to the right
           }
 
-          std::auto_ptr< unsigned char > ibuf( new unsigned char[nb_ibytes]);
-
-          if (ibuf.get() == 0)
+          unsigned char* ibuf = new (std::nothrow) unsigned char[nb_ibytes];
+          if (ibuf == NULL )
           {
              CPLError( CE_Failure, CPLE_AppDefined,
                   "Not enough memory to perform wavelet decompression\n");
             return CE_Failure;
           }
 
-          i_file.read( (char *)(ibuf.get()), nb_ibytes);
+          i_file.read( (char *)ibuf, nb_ibytes);
 
-          Util::CDataFieldCompressedImage  img_compressed(ibuf.release(),
+          Util::CDataFieldCompressedImage  img_compressed(ibuf,
                                   nb_ibytes*8,
                                   (unsigned char)chunk_bpp,
                                   chunk_width,
@@ -705,25 +724,27 @@ double MSGRasterBand::rRadiometricCorrection(unsigned int iDN, int iChannel, int
   {
     double rRadiance = rOffset + (iDN * rSlope);
 
-		if (iChannel >= 4 && iChannel <= 11) // Channels 4 to 11 (infrared): Temperature
-		{
-			const double rC1 = 1.19104e-5;
-			const double rC2 = 1.43877e+0;
-
-			double cc2 = rC2 * poGDS->rVc[iIndex];
-			double cc1 = rC1 * pow(poGDS->rVc[iIndex], 3) / rRadiance;
-			double rTemperature = ((cc2 / log(cc1 + 1)) - poGDS->rB[iIndex]) / poGDS->rA[iIndex];
-			return rTemperature;
-		}
-		else // Channels 1,2,3 and 12 (visual): Reflectance
-		{
+                if (iChannel >= 4 && iChannel <= 11) // Channels 4 to 11 (infrared): Temperature
+                {
+                        const double rC1 = 1.19104e-5;
+                        const double rC2 = 1.43877e+0;
+
+                        double cc2 = rC2 * poGDS->rVc[iIndex];
+                        double cc1 = rC1 * pow(poGDS->rVc[iIndex], 3) / rRadiance;
+                        // cppcheck suggests using log1p() but not sure how portable this would be
+                        // cppcheck-suppress unpreciseMathCall
+                        double rTemperature = ((cc2 / log(cc1 + 1)) - poGDS->rB[iIndex]) / poGDS->rA[iIndex];
+                        return rTemperature;
+                }
+                else // Channels 1,2,3 and 12 (visual): Reflectance
+                {
       double rLon = poGDS->adfGeoTransform[0] + iCol * poGDS->adfGeoTransform[1]; // X, in "geos" meters
       double rLat = poGDS->adfGeoTransform[3] + iRow * poGDS->adfGeoTransform[5]; // Y, in "geos" meters
       if ((poGDS->poTransform != NULL) && poGDS->poTransform->Transform( 1, &rLon, &rLat )) // transform it to latlon
-	      return m_rc->rGetReflectance(rRadiance, rLat, rLon);
-			else
-				return 0;
-		}
+              return m_rc->rGetReflectance(rRadiance, rLat, rLon);
+                        else
+                                return 0;
+                }
   }
   else // radiometric
   {
diff --git a/frmts/msg/msgdataset.h b/frmts/msg/msgdataset.h
index f892e99..c35a367 100644
--- a/frmts/msg/msgdataset.h
+++ b/frmts/msg/msgdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msgdataset.h 32190 2015-12-16 13:50:27Z goatbar $
+ * $Id: msgdataset.h 36562 2016-11-30 02:12:01Z goatbar $
  *
  * Project:  MSG Driver
  * Purpose:  GDALDataset driver for MSG translator for read support.
@@ -35,10 +35,6 @@
 #include <string>
 #include <fstream>
 
-CPL_C_START
-void GDALRegister_MSG();
-CPL_C_END
-
 /************************************************************************/
 /*                            MSGRasterBand                             */
 /************************************************************************/
@@ -53,7 +49,7 @@ class MSGRasterBand : public GDALRasterBand
   public:
     MSGRasterBand( MSGDataset *, int );
     virtual ~MSGRasterBand();
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 
   private:
     double rRadiometricCorrection(unsigned int iDN, int iChannel, int iRow, int iCol, MSGDataset* poGDS);
@@ -75,12 +71,12 @@ class MSGDataset : public GDALDataset
 
   public:
     MSGDataset();
-    ~MSGDataset();
+    virtual ~MSGDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr GetGeoTransform( double * padfTransform );
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
 
   private:
     MSGCommand command;
@@ -96,5 +92,7 @@ class MSGDataset : public GDALDataset
     static const double rVc[12];
     static const double rA[12];
     static const double rB[12];
+    static const int iCentralPixelVIS_IR;
+    static const int iCentralPixelHRV;
+    static const char *metadataDomain;
 };
-
diff --git a/frmts/msg/prologue.cpp b/frmts/msg/prologue.cpp
index 514b604..04e7ff6 100644
--- a/frmts/msg/prologue.cpp
+++ b/frmts/msg/prologue.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: prologue.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Purpose:  Implementation of Prologue class. Parse the prologue of one
  *           repeat cycle and keep the interesting info.
@@ -27,11 +26,16 @@
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************/
 
+ #include "cpl_port.h"  // Must be first.
+
 #include "prologue.h"
 
+CPL_CVSID("$Id: prologue.cpp 35929 2016-10-25 16:09:00Z goatbar $");
+
+static
 int size_SatelliteStatus()
 {
-  int iSizePrimary = 1+4+1+1+4+4+1+1+4+4+1;;
+  int iSizePrimary = 1+4+1+1+4+4+1+1+4+4+1;
 
   int iSizeOrbitCoef = 4 + 4 + 8*8 + 8*8 + 8*8 + 8*8 + 8*8 + 8*8;
   int iSizeOrbit = 4 + 4 + 100*iSizeOrbitCoef;
@@ -45,6 +49,7 @@ int size_SatelliteStatus()
   return iTotalSize;
 }
 
+static
 int size_ImageAcquisition()
 {
   // up to  DHSSSynchSelection
@@ -59,6 +64,7 @@ int size_ImageAcquisition()
   return iTotalSize;
 }
 
+static
 int size_CelestialEvents()
 {
   int iSizeCelestialBodies = 2 + 2 + 4 + 4 + 3*100*(2 + 2 + 8*8 + 8*8) + 100*(20*(2 + 2 + 2 + 8*8 + 8*8));
@@ -70,11 +76,13 @@ int size_CelestialEvents()
   return iTotalSize;
 }
 
+static
 int size_Correction()
 {
   return 19229;
 }
 
+static
 double iReadDouble(std::ifstream & ifile)
 {
   // will use 8 bytes from the file to read a DOUBLE (according to the MSG definition of DOUBLE)
@@ -94,6 +102,7 @@ double iReadDouble(std::ifstream & ifile)
     return rVal;
 }
 
+static
 double iReadReal(std::ifstream & ifile)
 {
   // will use 4 bytes from the file to read a REAL (according to the MSG definition of REAL)
@@ -109,6 +118,7 @@ double iReadReal(std::ifstream & ifile)
     return rVal;
 }
 
+static
 int iReadInt(std::ifstream & ifile)
 {
   // will use 4 bytes from the file to read an int (according to the MSG definition of int)
@@ -120,6 +130,7 @@ int iReadInt(std::ifstream & ifile)
     return iResult;
 }
 
+static
 unsigned char iReadByte (std::ifstream & ifile)
 {
   // will read 1 byte from the file
@@ -159,7 +170,6 @@ PlannedCoverageHRVRecord::PlannedCoverageHRVRecord(std::ifstream & ifile)
     UpperWestColumnPlanned = iReadInt(ifile);
 }
 
-
 ImageDescriptionRecord::ImageDescriptionRecord(std::ifstream & ifile)
 {
     TypeOfProjection = iReadByte(ifile);
@@ -201,12 +211,10 @@ RadiometricProcessingRecord::RadiometricProcessingRecord(std::ifstream & ifile)
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
 
-Prologue::Prologue()
-: m_idr(0)
-, m_rpr(0)
-{
-
-}
+Prologue::Prologue() :
+    m_idr(0),
+    m_rpr(0)
+{}
 
 Prologue::~Prologue()
 {
@@ -218,7 +226,7 @@ Prologue::~Prologue()
 
 void Prologue::read(std::ifstream & ifile)
 {
-  unsigned char version = iReadByte(ifile);
+  /*unsigned char version = */iReadByte(ifile);
 
   int iSkipHeadersSize = size_SatelliteStatus() + size_ImageAcquisition() + size_CelestialEvents() + size_Correction();
 
diff --git a/frmts/msg/prologue.h b/frmts/msg/prologue.h
index 1e2fe70..7ebd23b 100644
--- a/frmts/msg/prologue.h
+++ b/frmts/msg/prologue.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: prologue.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: prologue.h 36411 2016-11-21 22:03:48Z rouault $
  *
  * Purpose:  Interface of Prologue class. Parse the prologue of one repeat
  *           cycle and keep the interesting info.
@@ -39,7 +39,7 @@
 class ReferenceGridRecord
 {
 public:
-  ReferenceGridRecord(std::ifstream & ifile);
+  explicit ReferenceGridRecord(std::ifstream & ifile);
 
   int NumberOfLines;
   int NumberOfColumns;
@@ -51,7 +51,7 @@ public:
 class PlannedCoverageVIS_IRRecord
 {
 public:
-  PlannedCoverageVIS_IRRecord(std::ifstream & ifile);
+  explicit PlannedCoverageVIS_IRRecord(std::ifstream & ifile);
 
   int SouthernLinePlanned;
   int NorthernLinePlanned;
@@ -62,7 +62,7 @@ public:
 class PlannedCoverageHRVRecord
 {
 public:
-  PlannedCoverageHRVRecord(std::ifstream & ifile);
+  explicit PlannedCoverageHRVRecord(std::ifstream & ifile);
   int LowerSouthLinePlanned;
   int LowerNorthLinePlanned;
   int LowerEastColumnPlanned;
@@ -75,8 +75,10 @@ public:
 
 class ImageDescriptionRecord
 {
+  CPL_DISALLOW_COPY_ASSIGN( ImageDescriptionRecord )
+
 public:
-  ImageDescriptionRecord(std::ifstream & ifile);
+  explicit ImageDescriptionRecord(std::ifstream & ifile);
   virtual ~ImageDescriptionRecord();
 
   unsigned char TypeOfProjection; // 1 == Geostationary, Earth centered in grid
@@ -93,7 +95,7 @@ public:
 class RadiometricProcessingRecord
 {
 public:
-  RadiometricProcessingRecord(std::ifstream & ifile);
+  explicit RadiometricProcessingRecord(std::ifstream & ifile);
 
   double Cal_Slope [12];
   double Cal_Offset [12];
@@ -120,7 +122,6 @@ public:
 private:
   ImageDescriptionRecord * m_idr;
   RadiometricProcessingRecord * m_rpr;
-
 };
 
 #endif // !defined(AFX_PROLOGUE_H__777B5B86_04F4_4A01_86F6_24615DCD8446__INCLUDED_)
diff --git a/frmts/msg/reflectancecalculator.cpp b/frmts/msg/reflectancecalculator.cpp
index b2ed993..c52dac0 100644
--- a/frmts/msg/reflectancecalculator.cpp
+++ b/frmts/msg/reflectancecalculator.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: reflectancecalculator.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Purpose:  Implementation of ReflectanceCalculator class. Calculate
  *           reflectance values from radiance, for visual bands.
@@ -27,9 +26,14 @@
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************/
 
+ #include "cpl_port.h"  // Must be first.
+
 #include "reflectancecalculator.h"
 #include <cmath>
 #include <cstdlib>
+
+CPL_CVSID("$Id: reflectancecalculator.cpp 36427 2016-11-22 12:56:01Z rouault $");
+
 using namespace std;
 
 //////////////////////////////////////////////////////////////////////
@@ -48,23 +52,20 @@ ReflectanceCalculator::ReflectanceCalculator(std::string sTimeStamp, double rRTO
   m_iYear = atoi(sYear.c_str());
   int iMonth = atoi(sMonth.c_str());
   m_iDay = atoi(sDay.c_str());
-	for (int i = 1; i < iMonth; ++i)
-		m_iDay += iDaysInMonth(i, m_iYear);
+  for (int i = 1; i < iMonth; ++i)
+      m_iDay += iDaysInMonth(i, m_iYear);
   int iHours = atoi(sHours.c_str());
   int iMins = atoi(sMins.c_str());
 
-	m_rHours = iHours + iMins / 60.0;
+        m_rHours = iHours + iMins / 60.0;
 }
 
-ReflectanceCalculator::~ReflectanceCalculator()
-{
-
-}
+ReflectanceCalculator::~ReflectanceCalculator() {}
 
 double ReflectanceCalculator::rGetReflectance(double rRadiance, double rLat, double rLon) const
 {
   double phi = rLat * M_PI / 180;
-  double lam = rLon * M_PI / 180;
+  //double lam = rLon * M_PI / 180;
   double rSunDist = rSunDistance();
   double ReflectanceNumerator = rRadiance*rSunDist*rSunDist;
   double zenithAngle = rZenithAngle(phi, rDeclination(), rHourAngle(rLon));
@@ -73,15 +74,15 @@ double ReflectanceCalculator::rGetReflectance(double rRadiance, double rLat, dou
   return Reflectance;
 }
 
-double ReflectanceCalculator::rZenithAngle(double phi, double rDeclin, double rHourAngle) const
+double ReflectanceCalculator::rZenithAngle(double phi, double rDeclin, double l_rHourAngle)
 {
   double rCosZen = (sin(phi) * sin(rDeclin) + cos(phi)
-          * cos(rDeclin) * cos(rHourAngle));
+          * cos(rDeclin) * cos(l_rHourAngle));
   double zenithAngle = acos(rCosZen) * 180 / M_PI;
   return zenithAngle;
 }
 
-const double ReflectanceCalculator::rDeclination() const
+double ReflectanceCalculator::rDeclination() const
 {
   double rJulianDay = m_iDay - 1;
   double yearFraction = (rJulianDay + m_rHours / 24) / iDaysInYear(m_iYear);
@@ -113,17 +114,17 @@ double ReflectanceCalculator::rHourAngle(double rLon) const
   return hourAngle;
 }
 
-const double ReflectanceCalculator::rSunDistance() const
+double ReflectanceCalculator::rSunDistance() const
 {
   int iJulianDay = m_iDay - 1;
   double theta = 2*M_PI *(iJulianDay - 3) / 365.25;
-	// rE0 is the inverse of the square of the sun-distance ratio
-	double rE0 = 1.000110 + 0.034221*cos(theta)+0.00128*sin(theta) + 0.000719*cos(2*theta)+0.000077*sin(2*theta);
+        // rE0 is the inverse of the square of the sun-distance ratio
+        double rE0 = 1.000110 + 0.034221*cos(theta)+0.00128*sin(theta) + 0.000719*cos(2*theta)+0.000077*sin(2*theta);
   // The calculated distance is expressed as a factor of the "average sun-distance" (on 1 Jan approx. 0.98, on 1 Jul approx. 1.01)
   return 1 / sqrt(rE0);
 }
 
-int ReflectanceCalculator::iDaysInYear(int iYear) const
+int ReflectanceCalculator::iDaysInYear(int iYear)
 {
   bool fLeapYear = iDaysInMonth(2, iYear) == 29;
 
@@ -133,7 +134,7 @@ int ReflectanceCalculator::iDaysInYear(int iYear) const
       return 365;
 }
 
-int ReflectanceCalculator::iDaysInMonth(int iMonth, int iYear) const
+int ReflectanceCalculator::iDaysInMonth(int iMonth, int iYear)
 {
   int iDays;
 
diff --git a/frmts/msg/reflectancecalculator.h b/frmts/msg/reflectancecalculator.h
index d5a59bf..2804f3e 100644
--- a/frmts/msg/reflectancecalculator.h
+++ b/frmts/msg/reflectancecalculator.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reflectancecalculator.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: reflectancecalculator.h 36427 2016-11-22 12:56:01Z rouault $
  *
  * Purpose:  Interface of ReflectanceCalculator class. Calculate reflectance
  *           values from radiance, for visual bands.
@@ -39,21 +39,21 @@
 class ReflectanceCalculator
 {
 public:
-	ReflectanceCalculator(std::string sTimeStamp, double rRTOA);
-	virtual ~ReflectanceCalculator();
-	double rGetReflectance(double rRadiance, double rLat, double rLon) const;
+    ReflectanceCalculator(std::string sTimeStamp, double rRTOA);
+    virtual ~ReflectanceCalculator();
+    double rGetReflectance(double rRadiance, double rLat, double rLon) const;
 private:
-  double rZenithAngle(double phi, double rDeclin, double rHourAngle) const;
-	const double rDeclination() const;
+  static double rZenithAngle(double phi, double rDeclin, double rHourAngle);
+  double rDeclination() const;
   double rHourAngle(double lam) const;
-  const double rSunDistance() const;
-  int iDaysInYear(int iYear) const;
-	int iDaysInMonth(int iMonth, int iYear) const;
+  double rSunDistance() const;
+  static int iDaysInYear(int iYear);
+  static int iDaysInMonth(int iMonth, int iYear);
 
-	const double m_rRTOA; // solar irradiance on Top of Atmosphere
-	int m_iYear; // e.g. 2005
-	int m_iDay; // 1-365/366
-	double m_rHours; // 0-24
+    const double m_rRTOA; // solar irradiance on Top of Atmosphere
+    int m_iYear; // e.g. 2005
+    int m_iDay; // 1-365/366
+    double m_rHours; // 0-24
 };
 
 #endif // !defined(AFX_REFLECTANCECALCULATOR_H__C9960E01_2A1B_41F0_B903_7957F11618D2__INCLUDED_)
diff --git a/frmts/msg/xritheaderparser.cpp b/frmts/msg/xritheaderparser.cpp
index 94868c5..eddef12 100644
--- a/frmts/msg/xritheaderparser.cpp
+++ b/frmts/msg/xritheaderparser.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: xritheaderparser.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Purpose:  Implementation of XRITHeaderParser class. Parse the header
  *           of the combined XRIT header/data files.
@@ -27,10 +26,14 @@
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************/
 
+ #include "cpl_port.h"  // Must be first.
+
 #include "xritheaderparser.h"
 #include <cstdlib> // malloc, free
 #include <cstring> // memcpy
 
+CPL_CVSID("$Id: xritheaderparser.cpp 35929 2016-10-25 16:09:00Z goatbar $");
+
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //
@@ -77,10 +80,7 @@ XRITHeaderParser::XRITHeaderParser(std::ifstream & ifile)
   }
 }
 
-XRITHeaderParser::~XRITHeaderParser()
-{
-
-}
+XRITHeaderParser::~XRITHeaderParser() {}
 
 int XRITHeaderParser::parseInt16(unsigned char * num)
 {
@@ -94,7 +94,7 @@ long XRITHeaderParser::parseInt32(unsigned char * num)
 
 void XRITHeaderParser::parseHeader(unsigned char * buf, long totalHeaderLength)
 {
-  int remainingHeaderLength = totalHeaderLength;
+  int remainingHeaderLength = static_cast<int>(totalHeaderLength);
 
   while (remainingHeaderLength > 0)
   {
@@ -123,10 +123,10 @@ void XRITHeaderParser::parseHeader(unsigned char * buf, long totalHeaderLength)
         break;
       case 2: // image navigation
         {
-          long cfac = parseInt32(&buf[35]); // column scaling factor
+          /*long cfac =*/ parseInt32(&buf[35]); // column scaling factor
           long lfac = parseInt32(&buf[39]); // line scaling factor
-          long coff = parseInt32(&buf[43]); // column offset
-          long loff = parseInt32(&buf[47]); // line offset
+          /*long coff =*/ parseInt32(&buf[43]); // column offset
+          /*long loff =*/ parseInt32(&buf[47]); // line offset
           if (lfac >= 0)
             m_scanNorth = true;
           else
diff --git a/frmts/msg/xritheaderparser.h b/frmts/msg/xritheaderparser.h
index 18c5df5..918fc63 100644
--- a/frmts/msg/xritheaderparser.h
+++ b/frmts/msg/xritheaderparser.h
@@ -38,41 +38,41 @@
 class XRITHeaderParser
 {
 public:
-  XRITHeaderParser(std::ifstream & ifile);
+  explicit XRITHeaderParser(std::ifstream & ifile);
 
   virtual ~XRITHeaderParser();
 
-  const bool isValid() {
+  bool isValid() const {
     return m_isValid;
   }
 
-  const bool isPrologue() {
+  bool isPrologue() const {
     return m_isPrologue;
   }
 
-  const long dataSize() {
+  long dataSize() const {
     return m_dataSize;
   }
 
-  const int nrRows() {
+  int nrRows() const {
     return m_nrRows;
   }
 
-  const int nrColumns() {
+  int nrColumns() const {
     return m_nrColumns;
   }
 
-  const int nrBitsPerPixel() {
+  int nrBitsPerPixel() const {
     return m_nrBitsPerPixel;
   }
 
-  const bool isScannedNorth() {
+  bool isScannedNorth() const {
     return m_scanNorth;
   }
 
 private:
-  int parseInt16(unsigned char * num);
-  long parseInt32(unsigned char * num);
+  static int parseInt16(unsigned char * num);
+  static long parseInt32(unsigned char * num);
   void parseHeader(unsigned char * buf, long totalHeaderLength);
 
   bool m_isValid;
diff --git a/frmts/msgn/GNUmakefile b/frmts/msgn/GNUmakefile
index 9118d2e..7b5ed80 100644
--- a/frmts/msgn/GNUmakefile
+++ b/frmts/msgn/GNUmakefile
@@ -9,5 +9,5 @@ default:       $(OBJ:.o=.$(OBJ_EXT))
 
 clean:
 	rm -f *.o $(O_OBJ)
-       
+
 install-obj:   $(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/msgn/msg_basic_types.cpp b/frmts/msgn/msg_basic_types.cpp
index 339a1a8..f2cdebd 100644
--- a/frmts/msgn/msg_basic_types.cpp
+++ b/frmts/msgn/msg_basic_types.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: msg_basic_types.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  MSG Native Reader
  * Purpose:  Basic types implementation.
@@ -28,9 +27,10 @@
  ****************************************************************************/
 
 #include "cpl_port.h"
+#include "cpl_error.h"
 #include "msg_basic_types.h"
 
-CPL_CVSID("$Id: msg_basic_types.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: msg_basic_types.cpp 36776 2016-12-10 11:17:47Z rouault $");
 
 #include <stdio.h>
 
@@ -93,31 +93,33 @@ void to_string(PH_DATA& d) {
     d.value[49] = 0;
 }
 
+#ifdef notdef
 // unit tests on structures
 bool perform_type_size_check(void) {
     bool success = true;
     if (sizeof(MAIN_PROD_HEADER) != 3674) {
-        fprintf(stderr, "MAIN_PROD_HEADER size not 3674 (%lu)\n", (unsigned long)sizeof(MAIN_PROD_HEADER));
+        fprintf(stderr, "MAIN_PROD_HEADER size not 3674 (%lu)\n", (unsigned long)sizeof(MAIN_PROD_HEADER));/*ok*/
         success = false;
     }
     if (sizeof(SECONDARY_PROD_HEADER) != 1120) {
-        fprintf(stderr, "SECONDARY_PROD_HEADER size not 1120 (%lu)\n", (unsigned long)sizeof(SECONDARY_PROD_HEADER));
+        fprintf(stderr, "SECONDARY_PROD_HEADER size not 1120 (%lu)\n", (unsigned long)sizeof(SECONDARY_PROD_HEADER));/*ok*/
         success = false;
     }
     if (sizeof(SUB_VISIRLINE) != 27) {
-        fprintf(stderr, "SUB_VISIRLINE size not 17 (%lu)\n", (unsigned long)sizeof(SUB_VISIRLINE));
+        fprintf(stderr, "SUB_VISIRLINE size not 17 (%lu)\n", (unsigned long)sizeof(SUB_VISIRLINE));/*ok*/
         success = false;
     }
     if (sizeof(GP_PK_HEADER) != 22) {
-        fprintf(stderr, "GP_PK_HEADER size not 22 (%lu)\n", (unsigned long)sizeof(GP_PK_HEADER));
+        fprintf(stderr, "GP_PK_HEADER size not 22 (%lu)\n", (unsigned long)sizeof(GP_PK_HEADER));/*ok*/
         success = false;
     }
     if (sizeof(GP_PK_SH1) != 16) {
-        fprintf(stderr, "GP_PK_SH1 size not 16 (%lu)\n", (unsigned long)sizeof(GP_PK_SH1));
+        fprintf(stderr, "GP_PK_SH1 size not 16 (%lu)\n", (unsigned long)sizeof(GP_PK_SH1));/*ok*/
         success = false;
     }
     return success;
 }
+#endif
 
 const double Conversions::altitude      =   42164;          // from origin
 const double Conversions::req           =   6378.1690;       // earthequatorial radius
@@ -180,7 +182,7 @@ void Conversions::compute_pixel_xyz(double line, double column, double& x,double
         z = k * r;
     } else {
         x = y = z = 0;
-        fprintf(stderr, "Warning: pixel not visible\n");
+        CPLError(CE_Warning, CPLE_AppDefined, "Warning: pixel not visible");
     }
 }
 
diff --git a/frmts/msgn/msg_basic_types.h b/frmts/msgn/msg_basic_types.h
index acfe793..3315a37 100644
--- a/frmts/msgn/msg_basic_types.h
+++ b/frmts/msgn/msg_basic_types.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msg_basic_types.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: msg_basic_types.h 36776 2016-12-10 11:17:47Z rouault $
  *
  * Project:  MSG Native Reader
  * Purpose:  Basic types implementation.
@@ -212,7 +212,7 @@ void to_native(IMAGE_DESCRIPTION_RECORD& r);
 void to_string(PH_DATA& d);
 
 // unit tests on structures, returns true on success
-bool perform_type_size_check(void);
+//bool perform_type_size_check(void);
 
 class Conversions {
 public:
diff --git a/frmts/msgn/msg_reader_core.cpp b/frmts/msgn/msg_reader_core.cpp
index df75c47..56c9a79 100644
--- a/frmts/msgn/msg_reader_core.cpp
+++ b/frmts/msgn/msg_reader_core.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: msg_reader_core.cpp 33138 2016-01-24 11:18:11Z rouault $
  *
  * Project:  MSG Native Reader
  * Purpose:  Base class for reading in the headers of MSG native images
@@ -28,6 +27,7 @@
  ****************************************************************************/
 
 #include "cpl_port.h"
+#include "cpl_error.h"
 
 #include "msg_reader_core.h"
 #include "msg_basic_types.h"
@@ -44,7 +44,7 @@
 #ifdef GDAL_SUPPORT
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: msg_reader_core.cpp 33138 2016-01-24 11:18:11Z rouault $");
+CPL_CVSID("$Id: msg_reader_core.cpp 36776 2016-12-10 11:17:47Z rouault $");
 
 #else
 #define VSIFSeek(fp, pos, ref)    CPL_IGNORE_RET_VAL(fseek(fp, pos, ref))
@@ -95,7 +95,7 @@ void SecondaryProdHeaderInit(SECONDARY_PROD_HEADER *header)
   PhDataInit(&header->westColumnSelectedRectangle);
 }
 
-Msg_reader_core::Msg_reader_core(const char* fname) :
+Msg_reader_core::Msg_reader_core( const char* fname ) :
     _lines(0),
     _columns(0),
     _line_start(0),
@@ -126,15 +126,17 @@ Msg_reader_core::Msg_reader_core(const char* fname) :
     }
 
     FILE* fin = fopen(fname, "rb");
-    if (!fin) {
-        fprintf(stderr, "Could not open file %s\n", fname);
+    if( !fin )
+    {
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Could not open file %s", fname);
         return;
     }
     read_metadata_block(fin);
     fclose(fin);
 }
 
-Msg_reader_core::Msg_reader_core(FILE* fp) :
+Msg_reader_core::Msg_reader_core( FILE* fp ) :
     _lines(0),
     _columns(0),
     _line_start(0),
@@ -168,7 +170,6 @@ Msg_reader_core::Msg_reader_core(FILE* fp) :
     read_metadata_block(fp);
 }
 
-
 void Msg_reader_core::read_metadata_block(FILE* fin) {
     _open_success = true;
 
@@ -182,19 +183,19 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
     PH_DATA* hd = (PH_DATA*)&_main_header;
     for (int i=0; i < 6; i++) {
         to_string(*hd);
-        printf("[%02d] %s %s", i, hd->name, hd->value);
+        printf("[%02d] %s %s", i, hd->name, hd->value);/*ok*/
         hd++;
     }
     PH_DATA_ID* hdi = (PH_DATA_ID*)&_main_header.dataSetIdentification;
 
     for (i=0; i < 5; i++) {
-        printf("%s %s %s", hdi->name, hdi->size, hdi->address);
+        printf("%s %s %s", hdi->name, hdi->size, hdi->address);/*ok*/
         hdi++;
     }
     hd = (PH_DATA*)(&_main_header.totalFileSize);
     for (int i=0; i < 19; i++) {
         to_string(*hd);
-        printf("[%02d] %s %s", i, hd->name, hd->value);
+        printf("[%02d] %s %s", i, hd->name, hd->value);/*ok*/
         hd++;
     }
 #endif // DEBUG
@@ -213,8 +214,8 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
         }
     }
 #ifdef DEBUG
-    printf("Data: %d %d\n", _f_data_offset, _f_data_size);
-    printf("Header: %d %d\n", _f_header_offset, _f_header_size);
+    printf("Data: %u %u\n", _f_data_offset, _f_data_size);/*ok*/
+    printf("Header: %u %u\n", _f_header_offset, _f_header_size);/*ok*/
 #endif // DEBUG
 
     unsigned int lines;
@@ -230,7 +231,7 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
     _columns -= cols - 1;
 
 #ifdef DEBUG
-    printf("lines = %d, cols = %d\n", _lines, _columns);
+    printf("lines = %u, cols = %u\n", _lines, _columns);/*ok*/
 #endif // DEBUG
 
     int records_per_line = 0;
@@ -244,7 +245,7 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
     }
 
 #ifdef DEBUG
-    printf("reading a total of %d records per line\n", records_per_line);
+    printf("reading a total of %d records per line\n", records_per_line);/*ok*/
 #endif // DEBUG
 
     // extract time fields, assume that SNIT is the correct field:
@@ -264,12 +265,12 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
 
 #ifdef DEBUG
     for (unsigned int i=0; i < MSG_NUM_CHANNELS; i++) {
-        if (_calibration[i].cal_slope < 0 || _calibration[i].cal_slope > 0.4) {
-            printf("Warning: calibration slope (%f) out of nominal range. MSG reader probably broken\n", _calibration[i].cal_slope);
-
+        if (_calibration[i].cal_slope < 0 || _calibration[i].cal_slope > 0.4)
+        {
+            printf("Warning: calibration slope (%f) out of nominal range. MSG reader probably broken\n", _calibration[i].cal_slope);/*ok*/
         }
         if (_calibration[i].cal_offset > 0 || _calibration[i].cal_offset < -20) {
-            printf("Warning: calibration offset (%f) out of nominal range. MSG reader probably broken\n", _calibration[i].cal_offset);
+            printf("Warning: calibration offset (%f) out of nominal range. MSG reader probably broken\n",/*ok*/ _calibration[i].cal_offset);
         }
     }
 #endif
@@ -283,7 +284,6 @@ void Msg_reader_core::read_metadata_block(FILE* fin) {
     _line_dir_step = idr.referencegrid_visir.lineDirGridStep;
     _col_dir_step = idr.referencegrid_visir.columnDirGridStep;
 
-
     // Rather convoluted, but this code is required to compute the real data block sizes
     // It does this by reading in the first line of every band, to get to the packet size field
     GP_PK_HEADER gp_header;
diff --git a/frmts/msgn/msg_reader_core.h b/frmts/msgn/msg_reader_core.h
index d65a862..2e2ab7b 100644
--- a/frmts/msgn/msg_reader_core.h
+++ b/frmts/msgn/msg_reader_core.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: msg_reader_core.h 11698 2007-06-25 16:33:06Z warmerdam $
+ * $Id: msg_reader_core.h 36427 2016-11-22 12:56:01Z rouault $
  *
  * Project:  MSG Native Reader
  * Purpose:  Base class for reading in the headers of MSG native images
@@ -60,19 +60,19 @@ typedef enum {
 
 class Msg_reader_core {
 public:
-    Msg_reader_core(const char* fname);
-    Msg_reader_core(FILE* fp);
-    virtual ~Msg_reader_core(void) {};
+    explicit Msg_reader_core(const char* fname);
+    explicit Msg_reader_core(FILE* fp);
+    virtual ~Msg_reader_core() {};
 
-    bool get_open_success(void) { return _open_success; }
+    bool get_open_success() { return _open_success; }
 
     #ifndef GDAL_SUPPORT
     virtual void radiance_to_blackbody(int using_chan_no = 0) = 0;   // can override which channel's parameters to use
     virtual double* get_data(int chan_no=0) = 0;
     #endif
 
-    unsigned int get_lines(void) { return _lines; }
-    unsigned int get_columns(void) { return _columns; }
+    unsigned int get_lines() { return _lines; }
+    unsigned int get_columns() { return _columns; }
 
     void get_pixel_geo_coordinates(unsigned int line, unsigned int column, double& longitude, double& latitude); // x and y relative to this image, not full disc image
     void get_pixel_geo_coordinates(double line, double column, double& longitude, double& latitude); // x and y relative to this image, not full disc image
@@ -80,35 +80,35 @@ public:
 
     static const Blackbody_lut_type Blackbody_LUT[MSG_NUM_CHANNELS+1];
 
-    unsigned int get_year(void) { return _year; }
-    unsigned int get_month(void) { return _month; }
-    unsigned int get_day(void) { return _day; }
-    unsigned int get_hour(void) { return _hour; }
-    unsigned int get_minute(void) { return _minute; }
+    unsigned int get_year() { return _year; }
+    unsigned int get_month() { return _month; }
+    unsigned int get_day() { return _day; }
+    unsigned int get_hour() { return _hour; }
+    unsigned int get_minute() { return _minute; }
 
-    unsigned int get_line_start(void) { return _line_start; }
-    unsigned int get_col_start(void) { return _col_start; }
+    unsigned int get_line_start() { return _line_start; }
+    unsigned int get_col_start() { return _col_start; }
 
-    float get_col_dir_step(void) { return _col_dir_step; }
-    float get_line_dir_step(void) { return _line_dir_step; }
+    float get_col_dir_step() { return _col_dir_step; }
+    float get_line_dir_step() { return _line_dir_step; }
 
-    unsigned int get_f_data_offset(void) { return _f_data_offset; }
-    unsigned int get_visir_bytes_per_line(void) { return _visir_bytes_per_line; }
-    unsigned int get_visir_packet_size(void) { return _visir_packet_size; }
-    unsigned int get_hrv_bytes_per_line(void) { return _hrv_bytes_per_line; }
-    unsigned int get_hrv_packet_size(void) { return _hrv_packet_size; }
-    unsigned int get_interline_spacing(void) { return _interline_spacing; }
+    unsigned int get_f_data_offset() { return _f_data_offset; }
+    unsigned int get_visir_bytes_per_line() { return _visir_bytes_per_line; }
+    unsigned int get_visir_packet_size() { return _visir_packet_size; }
+    unsigned int get_hrv_bytes_per_line() { return _hrv_bytes_per_line; }
+    unsigned int get_hrv_packet_size() { return _hrv_packet_size; }
+    unsigned int get_interline_spacing() { return _interline_spacing; }
 
-    unsigned char* get_band_map(void) { return _bands; }
+    unsigned char* get_band_map() { return _bands; }
 
-    CALIBRATION*  get_calibration_parameters(void) { return _calibration; }
+    CALIBRATION*  get_calibration_parameters() { return _calibration; }
 
 private:
     void read_metadata_block(FILE* fp);
 
 protected:
 
-    int _chan_to_idx(Msg_channel_names channel);
+    static int _chan_to_idx(Msg_channel_names channel);
 
     unsigned int    _lines;
     unsigned int    _columns;
diff --git a/frmts/msgn/msgndataset.cpp b/frmts/msgn/msgndataset.cpp
index 7d05d2f..34bb04b 100644
--- a/frmts/msgn/msgndataset.cpp
+++ b/frmts/msgn/msgndataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: msgndataset.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  MSG Native Reader
  * Purpose:  All code for EUMETSAT Archive format reader
@@ -33,9 +32,12 @@
 #include "ogr_spatialref.h"
 
 #include "msg_reader_core.h"
+
+#include <algorithm>
+
 using namespace msg_native_format;
 
-CPL_CVSID("$Id: msgndataset.cpp 33105 2016-01-23 15:27:32Z rouault $");
+CPL_CVSID("$Id: msgndataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 typedef enum {
     MODE_VISIR,     // Visible and Infrared bands (1 through 11) in 10-bit raw mode
@@ -67,9 +69,8 @@ class MSGNDataset : public GDALDataset
 
     static GDALDataset *Open( GDALOpenInfo * );
 
-    CPLErr     GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
-
+    CPLErr     GetGeoTransform( double * padfTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
 /************************************************************************/
@@ -89,7 +90,7 @@ class MSGNRasterBand : public GDALRasterBand
     unsigned int band_in_file;      // The effective index of the band in the file
     open_mode_type open_mode;
 
-    double  GetNoDataValue (int *pbSuccess=NULL) {
+    double  GetNoDataValue (int *pbSuccess=NULL) override {
         if (pbSuccess) {
             *pbSuccess = 1;
         }
@@ -104,32 +105,39 @@ class MSGNRasterBand : public GDALRasterBand
 
         MSGNRasterBand( MSGNDataset *, int , open_mode_type mode, int orig_band_no, int band_in_file);
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum(int *pbSuccess = NULL );
-    virtual const char* GetDescription() const { return band_description; }
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum(int *pbSuccess = NULL ) override;
+    virtual const char* GetDescription() const override { return band_description; }
 };
 
-
 /************************************************************************/
 /*                           MSGNRasterBand()                            */
 /************************************************************************/
 
-MSGNRasterBand::MSGNRasterBand( MSGNDataset *poDSIn, int nBandIn , open_mode_type mode, int orig_band_noIn, int band_in_fileIn)
-
+MSGNRasterBand::MSGNRasterBand( MSGNDataset *poDSIn, int nBandIn,
+                                open_mode_type mode, int orig_band_noIn,
+                                int band_in_fileIn ) :
+    packet_size(0),
+    bytes_per_line(0),
+    interline_spacing(poDSIn->msg_reader_core->get_interline_spacing()),
+    orig_band_no(orig_band_noIn),
+    band_in_file(band_in_fileIn),
+    open_mode(mode)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;                // GDAL's band number, i.e. always starts at 1
-    this->open_mode = mode;
-    this->orig_band_no = orig_band_noIn;
-    this->band_in_file = band_in_fileIn;
+    poDS = poDSIn;
+    nBand = nBandIn;  // GDAL's band number, i.e. always starts at 1.
 
-    snprintf(band_description, sizeof(band_description), "band %02d", orig_band_no);
+    snprintf(band_description, sizeof(band_description),
+             "band %02u", orig_band_no);
 
-    if (mode != MODE_RAD) {
+    if( mode != MODE_RAD )
+    {
         eDataType = GDT_UInt16;
         MSGN_NODATA_VALUE = 0;
-    } else {
+    }
+    else
+    {
         eDataType = GDT_Float64;
         MSGN_NODATA_VALUE = -1000;
     }
@@ -137,15 +145,16 @@ MSGNRasterBand::MSGNRasterBand( MSGNDataset *poDSIn, int nBandIn , open_mode_typ
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 
-    if (mode != MODE_HRV) {
+    if( mode != MODE_HRV )
+    {
         packet_size = poDSIn->msg_reader_core->get_visir_packet_size();
         bytes_per_line = poDSIn->msg_reader_core->get_visir_bytes_per_line();
-    } else {
+    }
+    else
+    {
         packet_size = poDSIn->msg_reader_core->get_hrv_packet_size();
         bytes_per_line = poDSIn->msg_reader_core->get_hrv_bytes_per_line();
     }
-
-    interline_spacing = poDSIn->msg_reader_core->get_interline_spacing();
 }
 
 /************************************************************************/
@@ -162,8 +171,6 @@ CPLErr MSGNRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     // invert y position
     int i_nBlockYOff = poDS->GetRasterYSize() - 1 - nBlockYOff;
 
-    char       *pszRecord;
-
     unsigned int data_length =  bytes_per_line + (unsigned int)sizeof(SUB_VISIRLINE);
     unsigned int data_offset = 0;
 
@@ -180,7 +187,7 @@ CPLErr MSGNRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     if( VSIFSeek( poGDS->fp, data_offset, SEEK_SET ) != 0 )
         return CE_Failure;
 
-    pszRecord = (char *) CPLMalloc(data_length);
+    char *pszRecord = (char *) CPLMalloc(data_length);
     size_t nread = VSIFRead( pszRecord, 1, data_length, poGDS->fp );
 
     SUB_VISIRLINE* p = (SUB_VISIRLINE*) pszRecord;
@@ -283,10 +290,11 @@ double MSGNRasterBand::GetMaximum(int *pbSuccess ) {
 /************************************************************************/
 
 MSGNDataset::MSGNDataset() :
-    fp(NULL)
+    fp(NULL),
+    msg_reader_core(NULL),
+    pszProjection(CPLStrdup(""))
 {
-    pszProjection = CPLStrdup("");
-    msg_reader_core = NULL;
+    std::fill_n(adfGeoTransform, CPL_ARRAYSIZE(adfGeoTransform), 0);
 }
 
 /************************************************************************/
@@ -328,7 +336,7 @@ CPLErr MSGNDataset::GetGeoTransform( double * padfTransform )
 const char *MSGNDataset::GetProjectionRef()
 
 {
-    return ( pszProjection );
+    return pszProjection;
 }
 
 /************************************************************************/
@@ -390,7 +398,6 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    MSGNDataset        *poDS;
     FILE* fp = VSIFOpen( open_info->pszFilename, "rb" );
     if( fp == NULL ) {
         if (open_info != poOpenInfo) {
@@ -399,7 +406,7 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    poDS = new MSGNDataset();
+    MSGNDataset *poDS = new MSGNDataset();
 
     poDS->fp = fp;
 
@@ -427,7 +434,6 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->nRasterYSize *= 3;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
@@ -505,12 +511,12 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->SetMetadataItem("Radiometric parameters format", "offset slope");
     for (i=1; i < band_count; i++) {
-        snprintf(tagname, sizeof(tagname), "ch%02d_cal", band_map[i]);
+        snprintf(tagname, sizeof(tagname), "ch%02u_cal", band_map[i]);
         CPLsnprintf(field, sizeof(field), "%.12e %.12e", cal[band_map[i]-1].cal_offset, cal[band_map[i]-1].cal_slope);
         poDS->SetMetadataItem(tagname, field);
     }
 
-    snprintf(field, sizeof(field), "%04d%02d%02d/%02d:%02d",
+    snprintf(field, sizeof(field), "%04u%02u%02u/%02u:%02u",
         poDS->msg_reader_core->get_year(),
         poDS->msg_reader_core->get_month(),
         poDS->msg_reader_core->get_day(),
@@ -519,7 +525,7 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
     );
     poDS->SetMetadataItem("Date/Time", field);
 
-    snprintf(field, sizeof(field), "%d %d",
+    snprintf(field, sizeof(field), "%u %u",
          poDS->msg_reader_core->get_line_start(),
          poDS->msg_reader_core->get_col_start()
     );
@@ -529,7 +535,7 @@ GDALDataset *MSGNDataset::Open( GDALOpenInfo * poOpenInfo )
         delete open_info;
     }
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/netcdf/GNUmakefile b/frmts/netcdf/GNUmakefile
index 78614e2..19f6d1f 100644
--- a/frmts/netcdf/GNUmakefile
+++ b/frmts/netcdf/GNUmakefile
@@ -3,7 +3,7 @@ include ../../GDALmake.opt
 
 OBJ	=	netcdfdataset.o netcdflayer.o netcdfwriterconfig.o gmtdataset.o
 
-XTRA_OPT = 
+XTRA_OPT =
 ifeq ($(NETCDF_HAS_NC4),yes)
 XTRA_OPT := -DNETCDF_HAS_NC4  $(XTRA_OPT)
 endif
@@ -17,7 +17,7 @@ ifeq ($(HAVE_HDF5),yes)
 XTRA_OPT := -DHAVE_HDF5 $(XTRA_OPT)
 endif
 
-CPPFLAGS	:=	 $(CPPFLAGS) $(XTRA_OPT) 
+CPPFLAGS	:=	 $(CPPFLAGS) $(XTRA_OPT)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/netcdf/gmtdataset.cpp b/frmts/netcdf/gmtdataset.cpp
index 3b74888..282d110 100644
--- a/frmts/netcdf/gmtdataset.cpp
+++ b/frmts/netcdf/gmtdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gmtdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library for GMT Grids.
@@ -28,18 +27,30 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+
+#include <cstddef>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
+#include "cpl_progress.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
 #include "netcdf.h"
+#include "ogr_core.h"
 
-CPL_CVSID("$Id: gmtdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
+CPL_CVSID("$Id: gmtdataset.cpp 37956 2017-04-11 13:42:14Z goatbar $");
 
 extern CPLMutex *hNCMutex; /* shared with netcdf. See netcdfdataset.cpp */
 
 /************************************************************************/
 /* ==================================================================== */
-/*			     GMTDataset				        */
+/*                           GMTDataset                                 */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -53,12 +64,17 @@ class GMTDataset : public GDALPamDataset
   public:
     int         cdfid;
 
-                GMTDataset() : z_id(0), cdfid(0) { }
-		~GMTDataset();
+    GMTDataset() :
+        z_id(0),
+        cdfid(0)
+    {
+        std::fill_n(adfGeoTransform, CPL_ARRAYSIZE(adfGeoTransform), 0);
+    }
+    ~GMTDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
 
-    CPLErr 	GetGeoTransform( double * padfTransform );
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
 };
 
 /************************************************************************/
@@ -77,20 +93,19 @@ class GMTRasterBand : public GDALPamRasterBand
     GMTRasterBand( GMTDataset *poDS, int nZId, int nBand );
     virtual ~GMTRasterBand() {}
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                           GMTRasterBand()                            */
 /************************************************************************/
 
-GMTRasterBand::GMTRasterBand( GMTDataset *poDSIn, int nZIdIn, int nBandIn )
-
+GMTRasterBand::GMTRasterBand( GMTDataset *poDSIn, int nZIdIn, int nBandIn ) :
+    nc_datatype(NC_NAT),
+    nZId(nZIdIn)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->nZId = nZIdIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
@@ -133,7 +148,6 @@ GMTRasterBand::GMTRasterBand( GMTDataset *poDSIn, int nZIdIn, int nBandIn )
 CPLErr GMTRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
                                   void * pImage )
 {
-
     CPLMutexHolderD(&hNCMutex);
 
     size_t start[2] = {static_cast<size_t>(nBlockYOff * nBlockXSize), 0};
@@ -176,7 +190,7 @@ CPLErr GMTRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
 
 /************************************************************************/
 /* ==================================================================== */
-/*				GMTDataset				*/
+/*                              GMTDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -227,16 +241,16 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try opening the dataset.                                        */
 /* -------------------------------------------------------------------- */
-    int cdfid;
+    int cdfid = 0;
     if( nc_open( poOpenInfo->pszFilename, NC_NOWRITE, &cdfid ) != NC_NOERR )
         return NULL;
 
-    int nm_id;
-    int z_id;
+    int nm_id = 0;
+    int z_id = 0;
     if( nc_inq_varid( cdfid, "dimension", &nm_id ) != NC_NOERR
         || nc_inq_varid( cdfid, "z", &z_id ) != NC_NOERR )
     {
-#ifdef notdef
+#if DEBUG_VERBOSE
         CPLError( CE_Warning, CPLE_AppDefined,
                   "%s is a GMT file, but not in GMT configuration.",
                   poOpenInfo->pszFilename );
@@ -245,7 +259,7 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    int dim_count;
+    int dim_count = 0;
     if( nc_inq_ndims( cdfid, &dim_count ) != NC_NOERR || dim_count < 2 )
     {
         nc_close( cdfid );
@@ -268,9 +282,9 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Get dimensions.  If we can't find this, then this is a          */
 /*      GMT file, but not a normal grid product.                     */
 /* -------------------------------------------------------------------- */
-    int    nm[2];
-    size_t start[2] = {0, 0};
-    size_t edge[2] = {2, 0};
+    int nm[2] = { 0, 0 };
+    size_t start[2] = { 0, 0 };
+    size_t edge[2] = { 2, 0 };
 
     nc_get_vara_int(cdfid, nm_id, start, edge, nm);
     if( !GDALCheckDatasetDimensions(nm[0], nm[1]) )
@@ -282,9 +296,10 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    CPLReleaseMutex(hNCMutex);
 
-    GMTDataset 	*poDS = new GMTDataset();
+    GMTDataset *poDS = new GMTDataset();
     CPLAcquireMutex(hNCMutex, 1000.0);
 
     poDS->cdfid = cdfid;
@@ -297,10 +312,10 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Fetch "z" attributes scale_factor, add_offset, and              */
 /*      node_offset.                                                    */
 /* -------------------------------------------------------------------- */
-    double scale_factor=1.0;
+    double scale_factor = 1.0;
     nc_get_att_double( cdfid, z_id, "scale_factor", &scale_factor );
 
-    double add_offset=0.0;
+    double add_offset = 0.0;
     nc_get_att_double( cdfid, z_id, "add_offset", &add_offset );
 
     int node_offset = 1;
@@ -309,7 +324,8 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Get x/y range information.                                      */
 /* -------------------------------------------------------------------- */
-    int x_range_id, y_range_id;
+    int x_range_id = 0;
+    int y_range_id = 0;
 
     if( nc_inq_varid (cdfid, "x_range", &x_range_id) == NC_NOERR
         && nc_inq_varid (cdfid, "y_range", &y_range_id) == NC_NOERR )
@@ -375,16 +391,18 @@ GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->SetDescription( poOpenInfo->pszFilename );
 
-    CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    // Release mutex otherwise we'll deadlock with GDALDataset own mutex.
+    CPLReleaseMutex(hNCMutex);
     poDS->TryLoadXML();
 
 /* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
+    poDS->oOvManager.Initialize(
+        poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
     CPLAcquireMutex(hNCMutex, 1000.0);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -446,7 +464,7 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Establish bounds from geotransform.                             */
 /* -------------------------------------------------------------------- */
-    double adfGeoTransform[6];
+    double adfGeoTransform[6] = {};
 
     poSrcDS->GetGeoTransform( adfGeoTransform );
 
@@ -464,7 +482,7 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Create base file.                                               */
 /* -------------------------------------------------------------------- */
-    int cdfid;
+    int cdfid = 0;
 
     int err = nc_create (pszFilename, NC_CLOBBER, &cdfid);
     if( err != NC_NOERR )
@@ -478,7 +496,8 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Define the dimensions and so forth.                             */
 /* -------------------------------------------------------------------- */
-    int side_dim, xysize_dim;
+    int side_dim = 0;
+    int xysize_dim = 0;
 
     CPL_IGNORE_RET_VAL(nc_def_dim(cdfid, "side", 2, &side_dim));
     CPL_IGNORE_RET_VAL(nc_def_dim(cdfid, "xysize", (int) (nXSize * nYSize), &xysize_dim));
@@ -494,7 +513,7 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     CPL_IGNORE_RET_VAL(nc_def_var (cdfid, "spacing", NC_DOUBLE, 1, dims, &inc_id));
     CPL_IGNORE_RET_VAL(nc_def_var (cdfid, "dimension", NC_LONG, 1, dims, &nm_id));
 
-    dims[0]		= xysize_dim;
+    dims[0] = xysize_dim;
     CPL_IGNORE_RET_VAL(nc_def_var (cdfid, "z", nc_datatype, 1, dims, &z_id));
 
 /* -------------------------------------------------------------------- */
@@ -523,15 +542,15 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Get raster min/max.                                             */
 /* -------------------------------------------------------------------- */
-    double adfMinMax[2];
+    double adfMinMax[2] = { 0.0, 0.0 };
     GDALComputeRasterMinMax( (GDALRasterBandH) poBand, FALSE, adfMinMax );
 
 /* -------------------------------------------------------------------- */
 /*      Set range variables.                                            */
 /* -------------------------------------------------------------------- */
-    size_t start[2] = {0, 0};
-    size_t edge[2] = {2, 0};
-    double dummy[2] = {adfGeoTransform[0], dfXMax};
+    size_t start[2] = { 0, 0 };
+    size_t edge[2] = { 2, 0 };
+    double dummy[2] = { adfGeoTransform[0], dfXMax };
     nc_put_vara_double(cdfid, x_range_id, start, edge, dummy);
 
     dummy[0] = dfYMin;
@@ -561,7 +580,7 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         {
             nc_close (cdfid);
             CPLFree( padfData );
-            return( NULL );
+            return NULL;
         }
         err = nc_put_vara_double( cdfid, z_id, start, edge, padfData );
         if( err != NC_NOERR )
@@ -571,7 +590,7 @@ GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                       pszFilename, nc_strerror( err ) );
             nc_close (cdfid);
             CPLFree( padfData );
-            return( NULL );
+            return NULL;
         }
     }
 
diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp
index ae2f7b5..8977fd3 100644
--- a/frmts/netcdf/netcdfdataset.cpp
+++ b/frmts/netcdf/netcdfdataset.cpp
@@ -1,6 +1,4 @@
-
 /******************************************************************************
- * $Id: netcdfdataset.cpp 37032 2016-12-29 13:25:51Z rouault $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -31,57 +29,90 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "netcdfdataset.h"
+
+#include <cctype>
+#include <cerrno>
+#include <climits>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <algorithm>
+#include <limits>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cpl_conv.h"
 #include "cpl_error.h"
+#include "cpl_minixml.h"
 #include "cpl_multiproc.h"
+#include "cpl_progress.h"
 #include "cpl_time.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
-#include "netcdfdataset.h"
-
-#include <map> //for NCDFWriteProjAttribs()
-#include <limits>
+#include "gdal_version.h"
+#include "ogr_core.h"
+#include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: netcdfdataset.cpp 37032 2016-12-29 13:25:51Z rouault $");
+CPL_CVSID("$Id: netcdfdataset.cpp 37984 2017-04-13 19:03:32Z goatbar $");
 
-/* Internal function declarations */
+// Internal function declarations.
 
-static bool NCDFIsGDALVersionGTE(const char* pszVersion, int nTarget);
+static bool NCDFIsGDALVersionGTE(const char *pszVersion, int nTarget);
 
-static void NCDFAddGDALHistory( int fpImage,
-                         const char * pszFilename, const char *pszOldHist,
-                         const char * pszFunctionName,
-                         const char * pszCFVersion = NCDF_CONVENTIONS_CF_V1_5 );
+static void NCDFAddGDALHistory(
+    int fpImage,
+    const char *pszFilename, const char *pszOldHist,
+    const char *pszFunctionName,
+    const char *pszCFVersion = NCDF_CONVENTIONS_CF_V1_5 );
 
-static void NCDFAddHistory(int fpImage, const char *pszAddHist, const char *pszOldHist);
+static void NCDFAddHistory( int fpImage, const char *pszAddHist,
+                            const char *pszOldHist );
 
-static bool NCDFIsCfProjection( const char* pszProjection );
+static bool NCDFIsCfProjection( const char *pszProjection );
 
-static void NCDFWriteProjAttribs(const OGR_SRSNode *poPROJCS,
-                            const char* pszProjection,
-                            const int fpImage, const int NCDFVarID);
+static void NCDFWriteProjAttribs( const OGR_SRSNode *poPROJCS,
+                                  const char *pszProjection,
+                                  const int fpImage, const int NCDFVarID );
 
-static CPLErr NCDFSafeStrcat(char** ppszDest, const char* pszSrc, size_t* nDestSize);
+static CPLErr NCDFSafeStrcat( char **ppszDest, const char *pszSrc,
+                              size_t *nDestSize );
 
-/* var / attribute helper functions */
+// Var / attribute helper functions.
 static CPLErr NCDFPutAttr( int nCdfId, int nVarId,
-                    const char *pszAttrName, const char *pszValue );
-static CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue );//replace this where used
+                           const char *pszAttrName, const char *pszValue );
+
+// Replace this where used.
+static CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue );
 static CPLErr NCDFPut1DVar( int nCdfId, int nVarId, const char *pszValue );
 
 static double NCDFGetDefaultNoDataValue( int nVarType );
 
-/* dimension check functions */
-static bool NCDFIsVarLongitude(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
-static bool NCDFIsVarLatitude(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
-static bool NCDFIsVarProjectionX( int nCdfId, int nVarId=-1, const char * pszVarName=NULL );
-static bool NCDFIsVarProjectionY( int nCdfId, int nVarId=-1, const char * pszVarName=NULL );
-static bool NCDFIsVarVerticalCoord(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
-static bool NCDFIsVarTimeCoord(int nCdfId, int nVarId=-1, const char * nVarName=NULL );
-
-static char **NCDFTokenizeArray( const char *pszValue ); //replace this where used
+// Dimension check functions.
+static bool NCDFIsVarLongitude( int nCdfId, int nVarId=-1,
+                                const char *nVarName=NULL );
+static bool NCDFIsVarLatitude( int nCdfId, int nVarId=-1,
+                               const char *nVarName=NULL );
+static bool NCDFIsVarProjectionX( int nCdfId, int nVarId=-1,
+                                  const char *pszVarName=NULL );
+static bool NCDFIsVarProjectionY( int nCdfId, int nVarId=-1,
+                                  const char *pszVarName=NULL );
+static bool NCDFIsVarVerticalCoord( int nCdfId, int nVarId=-1,
+                                    const char *nVarName=NULL );
+static bool NCDFIsVarTimeCoord( int nCdfId, int nVarId=-1,
+                                const char *nVarName=NULL );
+
+// Replace this where used.
+static char **NCDFTokenizeArray( const char *pszValue );
 static void CopyMetadata( void  *poDS, int fpImage, int CDFVarID,
-                   const char *pszMatchPrefix=NULL, bool bIsBand=true );
+                          const char *pszMatchPrefix=NULL, bool bIsBand=true );
 
-// uncomment this for more debug output
+// Uncomment this for more debug output.
 // #define NCDF_DEBUG 1
 
 CPLMutex *hNCMutex = NULL;
@@ -105,24 +136,25 @@ class netCDFRasterBand : public GDALPamRasterBand
     int         nBandYPos;
     int         *panBandZPos;
     int         *panBandZLev;
-    int         bNoDataSet;
+    bool        bNoDataSet;
     double      dfNoDataValue;
     double      adfValidRange[2];
-    int         bHaveScale;
-    int         bHaveOffset;
+    bool        bHaveScale;
+    bool        bHaveOffset;
     double      dfScale;
     double      dfOffset;
     CPLString   osUnitType;
     bool        bSignedData;
     bool        bCheckLongitude;
 
-    CPLErr	    CreateBandMetadata( const int *paDimIds );
-    template <class T> void CheckData ( void * pImage, void * pImageNC,
-                                        size_t nTmpBlockXSize, size_t nTmpBlockYSize,
+    CPLErr          CreateBandMetadata( const int *paDimIds );
+    template <class T> void CheckData ( void *pImage, void *pImageNC,
+                                        size_t nTmpBlockXSize,
+                                        size_t nTmpBlockYSize,
                                         bool bCheckIsNan=false ) ;
 
   protected:
-    CPLXMLNode *SerializeToXML( const char *pszVRTPath );
+    CPLXMLNode *SerializeToXML( const char *pszVRTPath ) override;
 
   public:
     netCDFRasterBand( netCDFDataset *poDS,
@@ -147,17 +179,17 @@ class netCDFRasterBand : public GDALPamRasterBand
                       const int *paDimIds=NULL );
     virtual ~netCDFRasterBand();
 
-    virtual double GetNoDataValue( int * );
-    virtual CPLErr SetNoDataValue( double );
-    //virtual CPLErr DeleteNoDataValue();
-    virtual double GetOffset( int * );
-    virtual CPLErr SetOffset( double );
-    virtual double GetScale( int * );
-    virtual CPLErr SetScale( double );
-    virtual const char *GetUnitType();
-    virtual CPLErr SetUnitType( const char * );
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual double GetNoDataValue( int * ) override;
+    virtual CPLErr SetNoDataValue( double ) override;
+    // virtual CPLErr DeleteNoDataValue();
+    virtual double GetOffset( int * ) override;
+    virtual CPLErr SetOffset( double ) override;
+    virtual double GetScale( int * ) override;
+    virtual CPLErr SetScale( double ) override;
+    virtual const char *GetUnitType() override;
+    virtual CPLErr SetUnitType( const char * ) override;
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -172,9 +204,17 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
                                     const int *panBandZPosIn,
                                     const int *paDimIds,
                                     int nBandIn ) :
+    nc_datatype(NC_NAT),
     cdfid(poNCDFDS->GetCDFID()),
+    nZId(nZIdIn),
+    nZDim(nZDimIn),
+    nLevel(nLevelIn),
     nBandXPos(panBandZPosIn[0]),
     nBandYPos(panBandZPosIn[1]),
+    panBandZPos(NULL),
+    panBandZLev(NULL),
+    bNoDataSet(false),
+    dfNoDataValue(0.0),
     bHaveScale(false),
     bHaveOffset(false),
     dfScale(1.0),
@@ -182,44 +222,32 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
     bSignedData(true),   // Default signed, except for Byte.
     bCheckLongitude(false)
 {
-    this->poDS = poNCDFDS;
-    this->panBandZPos = NULL;
-    this->panBandZLev = NULL;
-    this->nBand = nBandIn;
-    this->nZId = nZIdIn;
-    this->nZDim = nZDimIn;
-    this->nLevel = nLevelIn;
-
-/* ------------------------------------------------------------------- */
-/*      Take care of all other dimensions                              */
-/* ------------------------------------------------------------------- */
-    if( nZDim > 2 ) {
-        this->panBandZPos =
-            (int *) CPLCalloc( nZDim-1, sizeof( int ) );
-        this->panBandZLev =
-            (int *) CPLCalloc( nZDim-1, sizeof( int ) );
-
-        for ( int i=0; i < nZDim - 2; i++ ){
-            this->panBandZPos[i] = panBandZPosIn[i+2];
-            this->panBandZLev[i] = panBandZLevIn[i];
-        }
-    }
-
-    this->dfNoDataValue = 0.0;
-    this->bNoDataSet = FALSE;
-
-    nRasterXSize  = poDS->GetRasterXSize( );
-    nRasterYSize  = poDS->GetRasterYSize( );
-    nBlockXSize   = poDS->GetRasterXSize( );
-    nBlockYSize   = 1;
-
-/* -------------------------------------------------------------------- */
-/*      Get the type of the "z" variable, our target raster array.      */
-/* -------------------------------------------------------------------- */
-    if( nc_inq_var( cdfid, nZId, NULL, &nc_datatype, NULL, NULL,
-                    NULL ) != NC_NOERR ){
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Error in nc_var_inq() on 'z'." );
+    poDS = poNCDFDS;
+    nBand = nBandIn;
+
+    // Take care of all other dimensions.
+    if( nZDim > 2 )
+    {
+        panBandZPos = static_cast<int *>(CPLCalloc(nZDim - 1, sizeof(int)));
+        panBandZLev = static_cast<int *>(CPLCalloc(nZDim - 1, sizeof(int)));
+
+        for( int i = 0; i < nZDim - 2; i++ )
+        {
+            panBandZPos[i] = panBandZPosIn[i+2];
+            panBandZLev[i] = panBandZLevIn[i];
+        }
+    }
+
+    nRasterXSize = poDS->GetRasterXSize();
+    nRasterYSize = poDS->GetRasterYSize();
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
+
+    // Get the type of the "z" variable, our target raster array.
+    if( nc_inq_var(cdfid, nZId, NULL, &nc_datatype, NULL, NULL,
+                    NULL) != NC_NOERR )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Error in nc_var_inq() on 'z'.");
         return;
     }
 
@@ -236,7 +264,7 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
     else if( nc_datatype == NC_DOUBLE )
         eDataType = GDT_Float64;
 #ifdef NETCDF_HAS_NC4
-    /* NC_UBYTE (unsigned byte) is only available for NC4 */
+    // NC_UBYTE (unsigned byte) is only available for NC4.
     else if( nc_datatype == NC_UBYTE )
         eDataType = GDT_Byte;
     else if( nc_datatype == NC_USHORT )
@@ -247,81 +275,86 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
     else
     {
         if( nBand == 1 )
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Unsupported netCDF datatype (%d), treat as Float32.",
-                      (int) nc_datatype );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Unsupported netCDF datatype (%d), treat as Float32.",
+                     static_cast<int>(nc_datatype));
         eDataType = GDT_Float32;
         nc_datatype = NC_FLOAT;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Find and set No Data for this variable                          */
-/* -------------------------------------------------------------------- */
-    nc_type atttype=NC_NAT;
-    size_t attlen;
-    const char* pszNoValueName = NULL;
+    // Find and set No Data for this variable.
+    nc_type atttype = NC_NAT;
+    size_t attlen = 0;
+    const char *pszNoValueName = NULL;
 
-    /* find attribute name, either _FillValue or missing_value */
-    int status = nc_inq_att( cdfid, nZId, _FillValue, &atttype, &attlen);
-    if( status == NC_NOERR ) {
+    // Find attribute name, either _FillValue or missing_value.
+    int status = nc_inq_att(cdfid, nZId, _FillValue, &atttype, &attlen);
+    if( status == NC_NOERR )
+    {
         pszNoValueName = _FillValue;
     }
-    else {
-        status = nc_inq_att( cdfid, nZId,
-                             "missing_value", &atttype, &attlen );
-        if( status == NC_NOERR ) {
+    else
+    {
+        status = nc_inq_att(cdfid, nZId, "missing_value", &atttype, &attlen);
+        if( status == NC_NOERR )
+        {
             pszNoValueName = "missing_value";
         }
     }
 
-    /* fetch missing value */
+    // Fetch missing value.
     double dfNoData = 0.0;
     bool bGotNoData = false;
-    if( status == NC_NOERR ) {
-        if ( NCDFGetAttr( cdfid, nZId, pszNoValueName,
-                          &dfNoData ) == CE_None )
+    if( status == NC_NOERR )
+    {
+        if( NCDFGetAttr(cdfid, nZId, pszNoValueName, &dfNoData) == CE_None )
         {
             bGotNoData = true;
         }
     }
 
-    /* if NoData was not found, use the default value */
-    nc_type vartype=NC_NAT;
-    if ( ! bGotNoData ) {
-        nc_inq_vartype( cdfid, nZId, &vartype );
-        dfNoData = NCDFGetDefaultNoDataValue( vartype );
-        /*bGotNoData = true;*/
-        CPLDebug( "GDAL_netCDF",
-                  "did not get nodata value for variable #%d, using default %f",
-                  nZId, dfNoData );
+    // If NoData was not found, use the default value.
+    nc_type vartype = NC_NAT;
+    if( !bGotNoData )
+    {
+        nc_inq_vartype(cdfid, nZId, &vartype);
+        dfNoData = NCDFGetDefaultNoDataValue(vartype);
+        // bGotNoData = true;
+        CPLDebug("GDAL_netCDF",
+                 "did not get nodata value for variable #%d, using default %f",
+                 nZId, dfNoData);
     }
 
-/* -------------------------------------------------------------------- */
-/*  Look for valid_range or valid_min/valid_max                         */
-/* -------------------------------------------------------------------- */
-    /* set valid_range to nodata, then check for actual values */
+    // Look for valid_range or valid_min/valid_max.
+
+    // Set valid_range to nodata, then check for actual values.
     adfValidRange[0] = dfNoData;
     adfValidRange[1] = dfNoData;
-    /* first look for valid_range */
+    // First look for valid_range.
     bool bGotValidRange = false;
-    status = nc_inq_att( cdfid, nZId, "valid_range", &atttype, &attlen);
-    if( (status == NC_NOERR) && (attlen == 2)) {
-        int vrange[2];
-        int vmin, vmax;
-        status = nc_get_att_int( cdfid, nZId, "valid_range", vrange );
-        if( status == NC_NOERR ) {
+    status = nc_inq_att(cdfid, nZId, "valid_range", &atttype, &attlen);
+    if( (status == NC_NOERR) && (attlen == 2))
+    {
+        int vrange[2] = { 0, 0 };
+        status = nc_get_att_int(cdfid, nZId, "valid_range", vrange);
+        if( status == NC_NOERR )
+        {
             bGotValidRange = true;
             adfValidRange[0] = vrange[0];
             adfValidRange[1] = vrange[1];
         }
-        /* if not found look for valid_min and valid_max */
-        else {
-            status = nc_get_att_int( cdfid, nZId, "valid_min", &vmin );
-            if( status == NC_NOERR ) {
+        // If not found look for valid_min and valid_max.
+        else
+        {
+            int vmin = 0;
+            status = nc_get_att_int(cdfid, nZId, "valid_min", &vmin);
+            if( status == NC_NOERR )
+            {
                 adfValidRange[0] = vmin;
-                status = nc_get_att_int( cdfid, nZId,
-                                         "valid_max", &vmax );
-                if( status == NC_NOERR ) {
+                int vmax = 0;
+                status = nc_get_att_int(cdfid, nZId, "valid_max", &vmax);
+                if( status == NC_NOERR )
+                {
                     adfValidRange[1] = vmax;
                     bGotValidRange = true;
                 }
@@ -329,157 +362,160 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*  Special For Byte Bands: check for signed/unsigned byte              */
-/* -------------------------------------------------------------------- */
-    if ( nc_datatype == NC_BYTE ) {
-
-        /* netcdf uses signed byte by default, but GDAL uses unsigned by default */
-        /* This may cause unexpected results, but is needed for back-compat */
-        if ( poNCDFDS->bIsGdalFile )
+    // Special For Byte Bands: check for signed/unsigned byte.
+    if( nc_datatype == NC_BYTE )
+    {
+        // netcdf uses signed byte by default, but GDAL uses unsigned by default
+        // This may cause unexpected results, but is needed for back-compat.
+        if( poNCDFDS->bIsGdalFile )
             bSignedData = false;
         else
             bSignedData = true;
 
-        /* For NC4 format NC_BYTE is signed, NC_UBYTE is unsigned */
-        if ( poNCDFDS->eFormat == NCDF_FORMAT_NC4 ) {
+        // For NC4 format NC_BYTE is signed, NC_UBYTE is unsigned.
+        if( poNCDFDS->eFormat == NCDF_FORMAT_NC4 )
+        {
             bSignedData = true;
         }
-        else  {
-            /* if we got valid_range, test for signed/unsigned range */
-            /* http://www.unidata.ucar.edu/software/netcdf/docs/netcdf/Attribute-Conventions.html */
-            if ( bGotValidRange ) {
-                /* If we got valid_range={0,255}, treat as unsigned */
-                if ( (adfValidRange[0] == 0) && (adfValidRange[1] == 255) ) {
+        else
+        {
+            // If we got valid_range, test for signed/unsigned range.
+            // http://www.unidata.ucar.edu/software/netcdf/docs/netcdf/Attribute-Conventions.html
+            if( bGotValidRange )
+            {
+                // If we got valid_range={0,255}, treat as unsigned.
+                if( (adfValidRange[0] == 0) && (adfValidRange[1] == 255) )
+                {
                     bSignedData = false;
-                    /* reset valid_range */
+                    // Reset valid_range.
                     adfValidRange[0] = dfNoData;
                     adfValidRange[1] = dfNoData;
                 }
-                /* If we got valid_range={-128,127}, treat as signed */
-                else if ( (adfValidRange[0] == -128) && (adfValidRange[1] == 127) ) {
+                // If we got valid_range={-128,127}, treat as signed.
+                else if( (adfValidRange[0] == -128) &&
+                         (adfValidRange[1] == 127) )
+                {
                     bSignedData = true;
-                    /* reset valid_range */
+                    // Reset valid_range.
                     adfValidRange[0] = dfNoData;
                     adfValidRange[1] = dfNoData;
                 }
             }
-            /* else test for _Unsigned */
-            /* http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html */
-            else {
+            // Else test for _Unsigned.
+            // http://www.unidata.ucar.edu/software/netcdf/docs/BestPractices.html
+            else
+            {
                 char *pszTemp = NULL;
-                if ( NCDFGetAttr( cdfid, nZId, "_Unsigned", &pszTemp )
-                     == CE_None ) {
-                    if ( EQUAL(pszTemp,"true"))
+                if( NCDFGetAttr(cdfid, nZId, "_Unsigned", &pszTemp) == CE_None )
+                {
+                    if( EQUAL(pszTemp, "true") )
                         bSignedData = false;
-                    else if ( EQUAL(pszTemp,"false"))
+                    else if( EQUAL(pszTemp, "false") )
                         bSignedData = true;
-                    CPLFree( pszTemp );
+                    CPLFree(pszTemp);
                 }
             }
         }
 
-        if ( bSignedData )
+        if( bSignedData )
         {
-            /* set PIXELTYPE=SIGNEDBYTE */
-            /* See http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure */
-            SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
+            // set PIXELTYPE=SIGNEDBYTE
+            // See http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure
+            SetMetadataItem("PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE");
         }
         else
         {
-            // Fix nodata value as it was stored signed
+            // Fix nodata value as it was stored signed.
             if( dfNoData < 0 )
                 dfNoData += 256;
         }
     }
 
 #ifdef NETCDF_HAS_NC4
-    if ( nc_datatype == NC_UBYTE
-         || nc_datatype == NC_USHORT
-         || nc_datatype == NC_UINT )
+    if( nc_datatype == NC_UBYTE ||
+        nc_datatype == NC_USHORT ||
+        nc_datatype == NC_UINT )
         bSignedData = false;
 #endif
 
-    CPLDebug( "GDAL_netCDF", "netcdf type=%d gdal type=%d signedByte=%d",
-              nc_datatype, eDataType, static_cast<int>(bSignedData) );
+    CPLDebug("GDAL_netCDF", "netcdf type=%d gdal type=%d signedByte=%d",
+             nc_datatype, eDataType, static_cast<int>(bSignedData));
 
-    /* set nodata value */
+    // Set nodata value.
 #ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "SetNoDataValue(%f) read", dfNoData );
+    CPLDebug("GDAL_netCDF", "SetNoDataValue(%f) read", dfNoData);
 #endif
-    SetNoDataValue( dfNoData );
+    SetNoDataValue(dfNoData);
 
-/* -------------------------------------------------------------------- */
-/*      Create Band Metadata                                            */
-/* -------------------------------------------------------------------- */
-    CreateBandMetadata( paDimIds );
+    // Create Band Metadata.
+    CreateBandMetadata(paDimIds);
 
-/* -------------------------------------------------------------------- */
-/* Attempt to fetch the scale_factor and add_offset attributes for the  */
-/* variable and set them.  If these values are not available, set       */
-/* offset to 0 and scale to 1                                           */
-/* -------------------------------------------------------------------- */
-    if ( nc_inq_attid ( cdfid, nZId, CF_ADD_OFFSET, NULL) == NC_NOERR ) {
-        status = nc_get_att_double( cdfid, nZId, CF_ADD_OFFSET, &dfOffset );
-        CPLDebug( "GDAL_netCDF", "got add_offset=%.16g, status=%d", dfOffset, status );
-        SetOffset( dfOffset );
+    // Attempt to fetch the scale_factor and add_offset attributes for the
+    // variable and set them.  If these values are not available, set
+    // offset to 0 and scale to 1.
+    if( nc_inq_attid (cdfid, nZId, CF_ADD_OFFSET, NULL) == NC_NOERR )
+    {
+        status = nc_get_att_double(cdfid, nZId, CF_ADD_OFFSET, &dfOffset);
+        CPLDebug("GDAL_netCDF", "got add_offset=%.16g, status=%d",
+                 dfOffset, status);
+        SetOffset(dfOffset);
     }
 
-    if ( nc_inq_attid ( cdfid, nZId,
-                        CF_SCALE_FACTOR, NULL) == NC_NOERR ) {
-        status = nc_get_att_double( cdfid, nZId, CF_SCALE_FACTOR, &dfScale );
-        CPLDebug( "GDAL_netCDF", "got scale_factor=%.16g, status=%d", dfScale, status );
-        SetScale( dfScale );
+    if( nc_inq_attid(cdfid, nZId, CF_SCALE_FACTOR, NULL) == NC_NOERR )
+    {
+        status = nc_get_att_double(cdfid, nZId, CF_SCALE_FACTOR, &dfScale);
+        CPLDebug("GDAL_netCDF", "got scale_factor=%.16g, status=%d",
+                 dfScale, status);
+        SetScale(dfScale);
     }
 
-    /* should we check for longitude values > 360 ? */
+    // Should we check for longitude values > 360?
     bCheckLongitude =
         CPLTestBool(CPLGetConfigOption("GDAL_NETCDF_CENTERLONG_180", "YES"))
-        && NCDFIsVarLongitude( cdfid, nZId, NULL );
+        && NCDFIsVarLongitude(cdfid, nZId, NULL);
 
-/* -------------------------------------------------------------------- */
-/* Attempt to fetch the units attribute for the variable and set it.    */
-/* -------------------------------------------------------------------- */
-    SetUnitType( GetMetadataItem( CF_UNITS ) );
+    // Attempt to fetch the units attribute for the variable and set it.
+    SetUnitType(GetMetadataItem(CF_UNITS));
 
-/* -------------------------------------------------------------------- */
-/*      Check for variable chunking (netcdf-4 only)                     */
-/*      GDAL block size should be set to hdf5 chunk size                */
-/* -------------------------------------------------------------------- */
+    // Check for variable chunking (netcdf-4 only).
+    // GDAL block size should be set to hdf5 chunk size.
 #ifdef NETCDF_HAS_NC4
     int nTmpFormat = 0;
-    size_t chunksize[ MAX_NC_DIMS ];
-    status = nc_inq_format( cdfid, &nTmpFormat);
+    status = nc_inq_format(cdfid, &nTmpFormat);
     NetCDFFormatEnum eTmpFormat = static_cast<NetCDFFormatEnum>(nTmpFormat);
-    if( ( status == NC_NOERR ) && ( ( eTmpFormat == NCDF_FORMAT_NC4 ) ||
-          ( eTmpFormat == NCDF_FORMAT_NC4C ) ) ) {
-        /* check for chunksize and set it as the blocksize (optimizes read) */
-        status = nc_inq_var_chunking( cdfid, nZId, &nTmpFormat, chunksize );
-        if( ( status == NC_NOERR ) && ( nTmpFormat == NC_CHUNKED ) ) {
-            CPLDebug( "GDAL_netCDF",
-                      "setting block size to chunk size : %ld x %ld\n",
-                      static_cast<long>(chunksize[nZDim-1]), static_cast<long>(chunksize[nZDim-2]));
-            nBlockXSize = (int) chunksize[nZDim-1];
-            nBlockYSize = (int) chunksize[nZDim-2];
-        }
-	}
+    if( (status == NC_NOERR) && ((eTmpFormat == NCDF_FORMAT_NC4) ||
+          (eTmpFormat == NCDF_FORMAT_NC4C)) )
+    {
+        size_t chunksize[MAX_NC_DIMS] = {};
+        // Check for chunksize and set it as the blocksize (optimizes read).
+        status = nc_inq_var_chunking(cdfid, nZId, &nTmpFormat, chunksize);
+        if( (status == NC_NOERR) && (nTmpFormat == NC_CHUNKED) )
+        {
+            CPLDebug("GDAL_netCDF",
+                     "setting block size to chunk size : %ld x %ld",
+                     static_cast<long>(chunksize[nZDim - 1]),
+                     static_cast<long>(chunksize[nZDim - 2]));
+            nBlockXSize = (int)chunksize[nZDim - 1];
+            nBlockYSize = (int)chunksize[nZDim - 2];
+        }
+    }
 #endif
 
-/* -------------------------------------------------------------------- */
-/*      Force block size to 1 scanline for bottom-up datasets if        */
-/*      nBlockYSize != 1                                                */
-/* -------------------------------------------------------------------- */
-    if( poNCDFDS->bBottomUp && nBlockYSize != 1 ) {
+    // Force block size to 1 scanline for bottom-up datasets if
+    // nBlockYSize != 1.
+    if( poNCDFDS->bBottomUp && nBlockYSize != 1 )
+    {
         nBlockXSize = nRasterXSize;
         nBlockYSize = 1;
     }
 }
 
-/* constructor in create mode */
-/* if nZId and following variables are not passed, the band will have 2 dimensions */
-/* TODO get metadata, missing val from band #1 if nZDim>2 */
+// Constructor in create mode.
+// If nZId and following variables are not passed, the band will have 2
+// dimensions.
+// TODO: Get metadata, missing val from band #1 if nZDim > 2.
 netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
-                                    GDALDataType eType,
+                                    const GDALDataType eTypeIn,
                                     int nBandIn,
                                     bool bSigned,
                                     const char *pszBandName,
@@ -492,9 +528,14 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
                                     const int *paDimIds ) :
     nc_datatype(NC_NAT),
     cdfid(poNCDFDS->GetCDFID()),
+    nZId(nZIdIn),
+    nZDim(nZDimIn),
+    nLevel(nLevelIn),
     nBandXPos(1),
     nBandYPos(0),
-    bNoDataSet(FALSE),
+    panBandZPos(NULL),
+    panBandZLev(NULL),
+    bNoDataSet(false),
     dfNoDataValue(0.0),
     bHaveScale(false),
     bHaveOffset(false),
@@ -503,53 +544,48 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
     bSignedData(bSigned),
     bCheckLongitude(false)
 {
-    this->poDS = poNCDFDS;
-    this->nBand = nBandIn;
-    this->nZId = nZIdIn;
-    this->nZDim = nZDimIn;
-    this->nLevel = nLevelIn;
-    this->panBandZPos = NULL;
-    this->panBandZLev = NULL;
-
-    nRasterXSize   = poDS->GetRasterXSize( );
-    nRasterYSize   = poDS->GetRasterYSize( );
-    nBlockXSize   = poDS->GetRasterXSize( );
-    nBlockYSize   = 1;
-
-    if ( poDS->GetAccess() != GA_Update ) {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Dataset is not in update mode, wrong netCDFRasterBand constructor" );
+    poDS = poNCDFDS;
+    nBand = nBandIn;
+
+    nRasterXSize = poDS->GetRasterXSize();
+    nRasterYSize = poDS->GetRasterYSize();
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
+
+    if( poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Dataset is not in update mode, "
+                 "wrong netCDFRasterBand constructor");
         return;
     }
 
-/* ------------------------------------------------------------------ */
-/*      Take care of all other dimensions                             */
-/* ------------------------------------------------------------------ */
-    if ( nZDim > 2 && paDimIds != NULL ) {
+    // Take care of all other dimensions.
+    if( nZDim > 2 && paDimIds != NULL )
+    {
         nBandXPos = panBandZPosIn[0];
         nBandYPos = panBandZPosIn[1];
 
-        this->panBandZPos = (int *) CPLCalloc( nZDim-1, sizeof( int ) );
-        this->panBandZLev = (int *) CPLCalloc( nZDim-1, sizeof( int ) );
+        panBandZPos = static_cast<int *>(CPLCalloc(nZDim - 1, sizeof(int)));
+        panBandZLev = static_cast<int *>(CPLCalloc(nZDim - 1, sizeof(int)));
 
-        for ( int i=0; i < nZDim - 2; i++ ){
-            this->panBandZPos[i] = panBandZPosIn[i+2];
-            this->panBandZLev[i] = panBandZLevIn[i];
+        for( int i = 0; i < nZDim - 2; i++ )
+        {
+            panBandZPos[i] = panBandZPosIn[i + 2];
+            panBandZLev[i] = panBandZLevIn[i];
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Get the type of the "z" variable, our target raster array.      */
-/* -------------------------------------------------------------------- */
-    eDataType = eType;
+    // Get the type of the "z" variable, our target raster array.
+    eDataType = eTypeIn;
 
-    switch ( eDataType )
+    switch( eDataType )
     {
         case GDT_Byte:
             nc_datatype = NC_BYTE;
 #ifdef NETCDF_HAS_NC4
-            /* NC_UBYTE (unsigned byte) is only available for NC4 */
-            if ( ! bSignedData && (poNCDFDS->eFormat == NCDF_FORMAT_NC4) )
+            // NC_UBYTE (unsigned byte) is only available for NC4.
+            if( !bSignedData && (poNCDFDS->eFormat == NCDF_FORMAT_NC4) )
                 nc_datatype = NC_UBYTE;
 #endif
             break;
@@ -567,116 +603,132 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
             break;
 #ifdef NETCDF_HAS_NC4
         case GDT_UInt16:
-            if ( poNCDFDS->eFormat == NCDF_FORMAT_NC4 ) {
+            if( poNCDFDS->eFormat == NCDF_FORMAT_NC4 )
+            {
                 nc_datatype = NC_USHORT;
                 break;
             }
+            CPL_FALLTHROUGH
         case GDT_UInt32:
-            if ( poNCDFDS->eFormat == NCDF_FORMAT_NC4 ) {
+            if( poNCDFDS->eFormat == NCDF_FORMAT_NC4 )
+            {
                 nc_datatype = NC_UINT;
                 break;
             }
+            CPL_FALLTHROUGH
 #endif
         default:
             if( nBand == 1 )
-                CPLError( CE_Warning, CPLE_AppDefined,
-                          "Unsupported GDAL datatype (%d), treat as NC_FLOAT.",
-                          (int) eDataType );
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Unsupported GDAL datatype (%d), treat as NC_FLOAT.",
+                         static_cast<int>(eDataType));
             nc_datatype = NC_FLOAT;
-            eDataType = eType = GDT_Float32;
+            eDataType = GDT_Float32;
             break;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Define the variable if necessary (if nZId==-1)                  */
-/* -------------------------------------------------------------------- */
+    // Define the variable if necessary (if nZId == -1).
     bool bDefineVar = false;
 
-    if ( nZId == -1 ) {
+    if( nZId == -1 )
+    {
         bDefineVar = true;
 
-        /* make sure we are in define mode */
-        ( ( netCDFDataset * ) poDS )->SetDefineMode( true );
+        // Make sure we are in define mode.
+        static_cast<netCDFDataset *>(poDS)->SetDefineMode(true);
 
-        char szTempPrivate[256+1];
-        const char* pszTemp;
-        if ( !pszBandName || EQUAL(pszBandName,"")  )
+        char szTempPrivate[256 + 1];
+        const char *pszTemp = NULL;
+        if( !pszBandName || EQUAL(pszBandName, "") )
         {
-            snprintf( szTempPrivate, sizeof(szTempPrivate), "Band%d", nBand );
+            snprintf(szTempPrivate, sizeof(szTempPrivate), "Band%d", nBand);
             pszTemp = szTempPrivate;
         }
         else
+        {
             pszTemp = pszBandName;
+        }
 
         int status;
-        if ( nZDim > 2 && paDimIds != NULL ) {
-            status = nc_def_var( cdfid, pszTemp, nc_datatype,
-                                 nZDim, paDimIds, &nZId );
+        if( nZDim > 2 && paDimIds != NULL )
+        {
+            status = nc_def_var(cdfid, pszTemp, nc_datatype,
+                                 nZDim, paDimIds, &nZId);
         }
-        else {
-            int anBandDims[2] = {poNCDFDS->nYDimID, poNCDFDS->nXDimID};
-            status = nc_def_var( cdfid, pszTemp, nc_datatype,
-                                 2, anBandDims, &nZId );
+        else
+        {
+            int anBandDims[2] = { poNCDFDS->nYDimID, poNCDFDS->nXDimID };
+            status =
+                nc_def_var(cdfid, pszTemp, nc_datatype, 2, anBandDims, &nZId);
         }
         NCDF_ERR(status);
-        CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d) id=%d",
-                  cdfid, pszTemp, nc_datatype, nZId );
+        CPLDebug("GDAL_netCDF", "nc_def_var(%d,%s,%d) id=%d",
+                 cdfid, pszTemp, nc_datatype, nZId);
 
-        if ( !pszLongName || EQUAL(pszLongName,"")  )
+        if( !pszLongName || EQUAL(pszLongName, "") )
         {
-            snprintf( szTempPrivate, sizeof(szTempPrivate), "GDAL Band Number %d", nBand );
+            snprintf(szTempPrivate, sizeof(szTempPrivate),
+                     "GDAL Band Number %d", nBand);
             pszTemp = szTempPrivate;
         }
         else
+        {
             pszTemp = pszLongName;
-        status =  nc_put_att_text( cdfid, nZId, CF_LNG_NAME,
-                                   strlen( pszTemp ), pszTemp );
+        }
+        status =
+            nc_put_att_text(cdfid, nZId, CF_LNG_NAME, strlen(pszTemp), pszTemp);
         NCDF_ERR(status);
 
         poNCDFDS->DefVarDeflate(nZId, true);
     }
 
-    /* for Byte data add signed/unsigned info */
-    if ( eDataType == GDT_Byte ) {
-
-        if ( bDefineVar ) { //only add attributes if creating variable
-          /* For unsigned NC_BYTE (except NC4 format) */
-          /* add valid_range and _Unsigned ( defined in CF-1 and NUG ) */
-          int status = NC_NOERR;
-          if ( (nc_datatype == NC_BYTE) && (poNCDFDS->eFormat != NCDF_FORMAT_NC4) ) {
-            CPLDebug( "GDAL_netCDF", "adding valid_range attributes for Byte Band" );
-            short l_adfValidRange[2];
-            if  ( bSignedData ) {
-                l_adfValidRange[0] = -128;
-                l_adfValidRange[1] = 127;
-                status = nc_put_att_text( cdfid,nZId,
-                                          "_Unsigned", 5, "false" );
-            }
-            else {
-                l_adfValidRange[0] = 0;
-                l_adfValidRange[1] = 255;
-                    status = nc_put_att_text( cdfid,nZId,
-                                              "_Unsigned", 4, "true" );
+    // For Byte data add signed/unsigned info.
+    if( eDataType == GDT_Byte )
+    {
+        if( bDefineVar )
+        {
+            // Only add attributes if creating variable.
+            // For unsigned NC_BYTE (except NC4 format),
+            // add valid_range and _Unsigned ( defined in CF-1 and NUG ).
+            int status = NC_NOERR;
+            if( nc_datatype == NC_BYTE &&
+                poNCDFDS->eFormat != NCDF_FORMAT_NC4 )
+            {
+                CPLDebug("GDAL_netCDF",
+                         "adding valid_range attributes for Byte Band");
+                short l_adfValidRange[2] = { 0, 0 };
+                if( bSignedData )
+                {
+                    l_adfValidRange[0] = -128;
+                    l_adfValidRange[1] = 127;
+                    status =
+                        nc_put_att_text(cdfid, nZId, "_Unsigned", 5, "false");
+                }
+                else
+                {
+                    l_adfValidRange[0] = 0;
+                    l_adfValidRange[1] = 255;
+                    status =
+                        nc_put_att_text(cdfid, nZId, "_Unsigned", 4, "true");
+                }
+                NCDF_ERR(status);
+                status = nc_put_att_short(cdfid, nZId, "valid_range",
+                                          NC_SHORT, 2, l_adfValidRange);
+                NCDF_ERR(status);
             }
-            NCDF_ERR(status);
-            status=nc_put_att_short( cdfid,nZId, "valid_range",
-                                     NC_SHORT, 2, l_adfValidRange );
-            NCDF_ERR(status);
-          }
         }
-        /* for unsigned byte set PIXELTYPE=SIGNEDBYTE */
-        /* See http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure */
-        if  ( bSignedData )
-            SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
-
+        // For unsigned byte set PIXELTYPE=SIGNEDBYTE.
+        // See http://trac.osgeo.org/gdal/wiki/rfc14_imagestructure
+        if( bSignedData )
+            SetMetadataItem("PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE");
     }
 
-    /* set default nodata */
-    double dfNoData = NCDFGetDefaultNoDataValue( nc_datatype );
+    // Set default nodata.
+    double dfNoData = NCDFGetDefaultNoDataValue(nc_datatype);
 #ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "SetNoDataValue(%f) default", dfNoData );
+    CPLDebug("GDAL_netCDF", "SetNoDataValue(%f) default", dfNoData);
 #endif
-    SetNoDataValue( dfNoData );
+    SetNoDataValue(dfNoData);
 }
 
 /************************************************************************/
@@ -686,8 +738,8 @@ netCDFRasterBand::netCDFRasterBand( netCDFDataset *poNCDFDS,
 netCDFRasterBand::~netCDFRasterBand()
 {
     FlushCache();
-    CPLFree( panBandZPos );
-    CPLFree( panBandZLev );
+    CPLFree(panBandZPos);
+    CPLFree(panBandZLev);
 }
 
 /************************************************************************/
@@ -696,7 +748,7 @@ netCDFRasterBand::~netCDFRasterBand()
 double netCDFRasterBand::GetOffset( int *pbSuccess )
 {
     if( pbSuccess != NULL )
-        *pbSuccess = bHaveOffset;
+        *pbSuccess = static_cast<int>(bHaveOffset);
 
     return dfOffset;
 }
@@ -711,17 +763,17 @@ CPLErr netCDFRasterBand::SetOffset( double dfNewOffset )
     dfOffset = dfNewOffset;
     bHaveOffset = true;
 
-    /* write value if in update mode */
-    if ( poDS->GetAccess() == GA_Update ) {
-
-        /* make sure we are in define mode */
-        ( ( netCDFDataset * ) poDS )->SetDefineMode( true );
+    // Write value if in update mode.
+    if( poDS->GetAccess() == GA_Update )
+    {
+        // Make sure we are in define mode.
+        static_cast<netCDFDataset *>(poDS)->SetDefineMode(true);
 
-        int status = nc_put_att_double( cdfid, nZId, CF_ADD_OFFSET,
-                                    NC_DOUBLE, 1, &dfOffset );
+        const int status = nc_put_att_double(cdfid, nZId, CF_ADD_OFFSET,
+                                             NC_DOUBLE, 1, &dfOffset);
 
         NCDF_ERR(status);
-        if ( status == NC_NOERR )
+        if( status == NC_NOERR )
             return CE_None;
 
         return CE_Failure;
@@ -736,7 +788,7 @@ CPLErr netCDFRasterBand::SetOffset( double dfNewOffset )
 double netCDFRasterBand::GetScale( int *pbSuccess )
 {
     if( pbSuccess != NULL )
-        *pbSuccess = bHaveScale;
+        *pbSuccess = static_cast<int>(bHaveScale);
 
     return dfScale;
 }
@@ -751,17 +803,17 @@ CPLErr netCDFRasterBand::SetScale( double dfNewScale )
     dfScale = dfNewScale;
     bHaveScale = true;
 
-    /* write value if in update mode */
-    if ( poDS->GetAccess() == GA_Update ) {
-
-        /* make sure we are in define mode */
-        ( ( netCDFDataset * ) poDS )->SetDefineMode( true );
+    // Write value if in update mode.
+    if( poDS->GetAccess() == GA_Update )
+    {
+        // Make sure we are in define mode.
+        static_cast<netCDFDataset *>(poDS)->SetDefineMode(true);
 
-        int status = nc_put_att_double( cdfid, nZId, CF_SCALE_FACTOR,
-                                    NC_DOUBLE, 1, &dfScale );
+        const int status = nc_put_att_double(cdfid, nZId, CF_SCALE_FACTOR,
+                                             NC_DOUBLE, 1, &dfScale);
 
         NCDF_ERR(status);
-        if ( status == NC_NOERR )
+        if( status == NC_NOERR )
             return CE_None;
 
         return CE_Failure;
@@ -777,36 +829,36 @@ CPLErr netCDFRasterBand::SetScale( double dfNewScale )
 const char *netCDFRasterBand::GetUnitType()
 
 {
-    if( osUnitType.size() > 0 )
+    if( !osUnitType.empty() )
         return osUnitType;
-    else
-        return GDALRasterBand::GetUnitType();
+
+    return GDALRasterBand::GetUnitType();
 }
 
 /************************************************************************/
 /*                           SetUnitType()                              */
 /************************************************************************/
 
-CPLErr netCDFRasterBand::SetUnitType( const char* pszNewValue )
+CPLErr netCDFRasterBand::SetUnitType( const char *pszNewValue )
 
 {
     CPLMutexHolderD(&hNCMutex);
 
     osUnitType = (pszNewValue != NULL ? pszNewValue : "");
 
-    if ( osUnitType.size() > 0 ) {
-        /* write value if in update mode */
-        if ( poDS->GetAccess() == GA_Update ) {
-
-            /* make sure we are in define mode */
-            ( ( netCDFDataset * ) poDS )->SetDefineMode( TRUE );
+    if( !osUnitType.empty() )
+    {
+        // Write value if in update mode.
+        if( poDS->GetAccess() == GA_Update )
+        {
+            // Make sure we are in define mode.
+            static_cast<netCDFDataset *>(poDS)->SetDefineMode(TRUE);
 
-            int status = nc_put_att_text( cdfid, nZId, CF_UNITS,
-                                          osUnitType.size(),
-                                          osUnitType.c_str() );
+            const int status = nc_put_att_text(
+                cdfid, nZId, CF_UNITS, osUnitType.size(), osUnitType.c_str());
 
             NCDF_ERR(status);
-            if ( status == NC_NOERR )
+            if( status == NC_NOERR )
                 return CE_None;
 
             return CE_Failure;
@@ -820,16 +872,16 @@ CPLErr netCDFRasterBand::SetUnitType( const char* pszNewValue )
 /*                           GetNoDataValue()                           */
 /************************************************************************/
 
-double netCDFRasterBand::GetNoDataValue( int * pbSuccess )
+double netCDFRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
     if( pbSuccess )
-        *pbSuccess = bNoDataSet;
+        *pbSuccess = static_cast<int>(bNoDataSet);
 
     if( bNoDataSet )
         return dfNoDataValue;
 
-    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+    return GDALPamRasterBand::GetNoDataValue(pbSuccess);
 }
 
 /************************************************************************/
@@ -841,92 +893,110 @@ CPLErr netCDFRasterBand::SetNoDataValue( double dfNoData )
 {
     CPLMutexHolderD(&hNCMutex);
 
-    /* If already set to new value, don't do anything */
-    if ( bNoDataSet && CPLIsEqual( dfNoData, dfNoDataValue ) )
+    // If already set to new value, don't do anything.
+    if( bNoDataSet && CPLIsEqual(dfNoData, dfNoDataValue) )
         return CE_None;
 
-    /* write value if in update mode */
-    if ( poDS->GetAccess() == GA_Update ) {
-
-        /* netcdf-4 does not allow to set _FillValue after leaving define mode */
-        /* but it's ok if variable has not been written to, so only print debug */
-        /* see bug #4484 */
-        if ( bNoDataSet && !reinterpret_cast<netCDFDataset *>(poDS)->GetDefineMode() ) {
-            CPLDebug( "GDAL_netCDF",
-                      "Setting NoDataValue to %.18g (previously set to %.18g) "
-                      "but file is no longer in define mode (id #%d, band #%d)",
-                      dfNoData, dfNoDataValue, cdfid, nBand );
+    // Write value if in update mode.
+    if( poDS->GetAccess() == GA_Update )
+    {
+        // netcdf-4 does not allow to set _FillValue after leaving define mode,
+        // but it's ok if variable has not been written to, so only print debug.
+        // See bug #4484.
+        if( bNoDataSet &&
+            !reinterpret_cast<netCDFDataset *>(poDS)->GetDefineMode() )
+        {
+            CPLDebug("GDAL_netCDF",
+                     "Setting NoDataValue to %.18g (previously set to %.18g) "
+                     "but file is no longer in define mode (id #%d, band #%d)",
+                     dfNoData, dfNoDataValue, cdfid, nBand);
         }
 #ifdef NCDF_DEBUG
-        else {
-            CPLDebug( "GDAL_netCDF", "Setting NoDataValue to %.18g (id #%d, band #%d)",
-                      dfNoData, cdfid, nBand );
+        else
+        {
+            CPLDebug("GDAL_netCDF",
+                     "Setting NoDataValue to %.18g (id #%d, band #%d)",
+                     dfNoData, cdfid, nBand);
         }
 #endif
-        /* make sure we are in define mode */
-        reinterpret_cast<netCDFDataset *>( poDS )->SetDefineMode( true );
+        // Make sure we are in define mode.
+        reinterpret_cast<netCDFDataset *>(poDS)->SetDefineMode(true);
 
         int status;
-        if ( eDataType == GDT_Byte) {
-            if ( bSignedData ) {
-                signed char cNoDataValue = (signed char) dfNoData;
-                status = nc_put_att_schar( cdfid, nZId, _FillValue,
-                                           nc_datatype, 1, &cNoDataValue );
+        if( eDataType == GDT_Byte)
+        {
+            if( bSignedData )
+            {
+                signed char cNoDataValue = static_cast<signed char>(dfNoData);
+                status = nc_put_att_schar(cdfid, nZId, _FillValue,
+                                          nc_datatype, 1, &cNoDataValue);
             }
-            else {
-                unsigned char ucNoDataValue = (unsigned char) dfNoData;
-                status = nc_put_att_uchar( cdfid, nZId, _FillValue,
-                                           nc_datatype, 1, &ucNoDataValue );
+            else
+            {
+                const unsigned char ucNoDataValue =
+                    static_cast<unsigned char>(dfNoData);
+                status = nc_put_att_uchar(cdfid, nZId, _FillValue,
+                                          nc_datatype, 1, &ucNoDataValue);
             }
         }
-        else if ( eDataType == GDT_Int16 ) {
-            short nsNoDataValue = (short) dfNoData;
-            status = nc_put_att_short( cdfid, nZId, _FillValue,
-                                       nc_datatype, 1, &nsNoDataValue );
+        else if( eDataType == GDT_Int16 )
+        {
+            short nsNoDataValue = static_cast<short>(dfNoData);
+            status = nc_put_att_short(cdfid, nZId, _FillValue,
+                                      nc_datatype, 1, &nsNoDataValue);
         }
-        else if ( eDataType == GDT_Int32) {
-            int nNoDataValue = (int) dfNoData;
-            status = nc_put_att_int( cdfid, nZId, _FillValue,
-                                     nc_datatype, 1, &nNoDataValue );
+        else if( eDataType == GDT_Int32)
+        {
+            int nNoDataValue = static_cast<int>(dfNoData);
+            status = nc_put_att_int(cdfid, nZId, _FillValue,
+                                     nc_datatype, 1, &nNoDataValue);
         }
-        else if ( eDataType == GDT_Float32) {
-            float fNoDataValue = (float) dfNoData;
-            status = nc_put_att_float( cdfid, nZId, _FillValue,
-                                       nc_datatype, 1, &fNoDataValue );
+        else if( eDataType == GDT_Float32)
+        {
+            float fNoDataValue = static_cast<float>(dfNoData);
+            status = nc_put_att_float(cdfid, nZId, _FillValue,
+                                      nc_datatype, 1, &fNoDataValue);
         }
 #ifdef NETCDF_HAS_NC4
-        else if ( eDataType == GDT_UInt16
-                  && reinterpret_cast<netCDFDataset *>( poDS )->eFormat == NCDF_FORMAT_NC4 ) {
-            unsigned short usNoDataValue = (unsigned short) dfNoData;
-            status = nc_put_att_ushort( cdfid, nZId, _FillValue,
-                                        nc_datatype, 1, &usNoDataValue );
-        }
-        else if ( eDataType == GDT_UInt32
-                  && reinterpret_cast<netCDFDataset *>( poDS )->eFormat == NCDF_FORMAT_NC4 ) {
-            unsigned int unNoDataValue = (unsigned int) dfNoData;
-            status = nc_put_att_uint( cdfid, nZId, _FillValue,
-                                      nc_datatype, 1, &unNoDataValue );
+        else if( eDataType == GDT_UInt16 &&
+                 reinterpret_cast<netCDFDataset *>(poDS)->eFormat ==
+                 NCDF_FORMAT_NC4 )
+        {
+            unsigned short usNoDataValue =
+                static_cast<unsigned short>(dfNoData);
+            status = nc_put_att_ushort(cdfid, nZId, _FillValue,
+                                       nc_datatype, 1, &usNoDataValue);
+        }
+        else if( eDataType == GDT_UInt32 &&
+                 reinterpret_cast<netCDFDataset *>(poDS)->eFormat ==
+                 NCDF_FORMAT_NC4 )
+        {
+            unsigned int unNoDataValue = static_cast<unsigned int>(dfNoData);
+            status = nc_put_att_uint(cdfid, nZId, _FillValue,
+                                     nc_datatype, 1, &unNoDataValue);
         }
 #endif
         else
-            status = nc_put_att_double( cdfid, nZId, _FillValue,
-                                        nc_datatype, 1, &dfNoData );
+        {
+            status = nc_put_att_double(cdfid, nZId, _FillValue,
+                                       nc_datatype, 1, &dfNoData);
+        }
 
         NCDF_ERR(status);
 
-        /* update status if write worked */
-        if ( status == NC_NOERR ) {
+        // Update status if write worked.
+        if( status == NC_NOERR )
+        {
             dfNoDataValue = dfNoData;
-            bNoDataSet = TRUE;
+            bNoDataSet = true;
             return CE_None;
         }
 
         return CE_Failure;
-
     }
 
     dfNoDataValue = dfNoData;
-    bNoDataSet = TRUE;
+    bNoDataSet = true;
     return CE_None;
 }
 
@@ -940,23 +1010,24 @@ CPLErr netCDFRasterBand::DeleteNoDataValue()
 {
     CPLMutexHolderD(&hNCMutex);
 
-    if ( !bNoDataSet )
+    if( !bNoDataSet )
         return CE_None;
 
-    /* write value if in update mode */
-    if ( poDS->GetAccess() == GA_Update ) {
-
-        /* make sure we are in define mode */
-        ( ( netCDFDataset * ) poDS )->SetDefineMode( true );
+    // Write value if in update mode.
+    if( poDS->GetAccess() == GA_Update )
+    {
+        // Make sure we are in define mode.
+        static_cast<netCDFDataset *>(poDS)->SetDefineMode(true);
 
-        status = nc_del_att( cdfid, nZId, _FillValue );
+        status = nc_del_att(cdfid, nZId, _FillValue);
 
         NCDF_ERR(status);
 
-        /* update status if write worked */
-        if ( status == NC_NOERR ) {
+        // Update status if write worked.
+        if( status == NC_NOERR )
+        {
             dfNoDataValue = 0.0;
-            bNoDataSet = FALSE;
+            bNoDataSet = false;
             return CE_None;
         }
 
@@ -964,7 +1035,7 @@ CPLErr netCDFRasterBand::DeleteNoDataValue()
     }
 
     dfNoDataValue = 0.0;
-    bNoDataSet = FALSE;
+    bNoDataSet = false;
     return CE_None;
 }
 #endif
@@ -973,61 +1044,51 @@ CPLErr netCDFRasterBand::DeleteNoDataValue()
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
-CPLXMLNode *netCDFRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused )
+CPLXMLNode *netCDFRasterBand::SerializeToXML( const char * /* pszUnused */ )
 {
-/* -------------------------------------------------------------------- */
-/*      Overridden from GDALPamDataset to add only band histogram        */
-/*      and statistics. See bug #4244.                                  */
-/* -------------------------------------------------------------------- */
+    // Overridden from GDALPamDataset to add only band histogram
+    // and statistics. See bug #4244.
     if( psPam == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Setup root node and attributes.                                 */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode *psTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMRasterBand" );
+    // Setup root node and attributes.
+    CPLXMLNode *psTree = CPLCreateXMLNode(NULL, CXT_Element, "PAMRasterBand");
 
     if( GetBand() > 0 )
     {
         CPLString oFmt;
-        CPLSetXMLValue( psTree, "#band", oFmt.Printf( "%d", GetBand() ) );
+        CPLSetXMLValue(psTree, "#band", oFmt.Printf("%d", GetBand()));
     }
 
-/* -------------------------------------------------------------------- */
-/*      Histograms.                                                     */
-/* -------------------------------------------------------------------- */
+    // Histograms.
     if( psPam->psSavedHistograms != NULL )
-        CPLAddXMLChild( psTree, CPLCloneXMLTree( psPam->psSavedHistograms ) );
+        CPLAddXMLChild(psTree, CPLCloneXMLTree(psPam->psSavedHistograms));
 
-/* -------------------------------------------------------------------- */
-/*      Metadata (statistics only).                                     */
-/* -------------------------------------------------------------------- */
+    // Metadata (statistics only).
     GDALMultiDomainMetadata oMDMDStats;
-    const char* papszMDStats[] = { "STATISTICS_MINIMUM", "STATISTICS_MAXIMUM",
+    const char *papszMDStats[] = { "STATISTICS_MINIMUM", "STATISTICS_MAXIMUM",
                                    "STATISTICS_MEAN", "STATISTICS_STDDEV",
                                    NULL };
-    for ( int i=0; i<CSLCount((char**)papszMDStats); i++ ) {
-        if ( GetMetadataItem( papszMDStats[i] ) != NULL )
-            oMDMDStats.SetMetadataItem( papszMDStats[i],
-                                       GetMetadataItem(papszMDStats[i]) );
+    for( int i = 0; i < CSLCount((char **)papszMDStats); i++ )
+    {
+        if( GetMetadataItem(papszMDStats[i]) != NULL )
+            oMDMDStats.SetMetadataItem(papszMDStats[i],
+                                       GetMetadataItem(papszMDStats[i]));
     }
     CPLXMLNode *psMD = oMDMDStats.Serialize();
 
     if( psMD != NULL )
     {
         if( psMD->psChild == NULL )
-            CPLDestroyXMLNode( psMD );
+            CPLDestroyXMLNode(psMD);
         else
-            CPLAddXMLChild( psTree, psMD );
+            CPLAddXMLChild(psTree, psMD);
     }
 
-/* -------------------------------------------------------------------- */
-/*      We don't want to return anything if we had no metadata to       */
-/*      attach.                                                         */
-/* -------------------------------------------------------------------- */
+    // We don't want to return anything if we had no metadata to attach.
     if( psTree->psChild == NULL || psTree->psChild->psNext == NULL )
     {
-        CPLDestroyXMLNode( psTree );
+        CPLDestroyXMLNode(psTree);
         psTree = NULL;
     }
 
@@ -1041,188 +1102,188 @@ CPLXMLNode *netCDFRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused )
 CPLErr netCDFRasterBand::CreateBandMetadata( const int *paDimIds )
 
 {
-    netCDFDataset *l_poDS = reinterpret_cast<netCDFDataset *>( this->poDS );
+    netCDFDataset *l_poDS = reinterpret_cast<netCDFDataset *>(poDS);
 
-/* -------------------------------------------------------------------- */
-/*      Compute all dimensions from Band number and save in Metadata    */
-/* -------------------------------------------------------------------- */
-    char szVarName[NC_MAX_NAME+1];
-    szVarName[0] = '\0';
-    int status = nc_inq_varname( cdfid, nZId, szVarName );
+    // Compute all dimensions from Band number and save in Metadata.
+    char szVarName[NC_MAX_NAME + 1] = {};
+    int status = nc_inq_varname(cdfid, nZId, szVarName);
     NCDF_ERR(status);
 
-    int nd;
-    nc_inq_varndims( cdfid, nZId, &nd );
-/* -------------------------------------------------------------------- */
-/*      Compute multidimention band position                            */
-/*                                                                      */
-/* BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)*/
-/* if Data[2,3,4,x,y]                                                   */
-/*                                                                      */
-/*  BandPos0 = (nBand ) / (3*4)                                         */
-/*  BandPos1 = (nBand - BandPos0*(3*4) ) / (4)                          */
-/*  BandPos2 = (nBand - BandPos0*(3*4) ) % (4)                          */
-/* -------------------------------------------------------------------- */
-
-    SetMetadataItem( "NETCDF_VARNAME", szVarName );
+    int nd = 0;
+    nc_inq_varndims(cdfid, nZId, &nd);
+    // Compute multidimention band position.
+    //
+    // BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)
+    // if Data[2,3,4,x,y]
+    //
+    //  BandPos0 = (nBand) / (3*4)
+    //  BandPos1 = (nBand - BandPos0*(3*4)) / (4)
+    //  BandPos2 = (nBand - BandPos0*(3*4)) % (4)
+
+    SetMetadataItem("NETCDF_VARNAME", szVarName);
     int Sum = 1;
-    if( nd == 3 ) {
+    if( nd == 3 )
+    {
         Sum *= panBandZLev[0];
     }
 
-/* -------------------------------------------------------------------- */
-/*      Loop over non-spatial dimensions                                */
-/* -------------------------------------------------------------------- */
+    // Loop over non-spatial dimensions.
     int nVarID = -1;
     int result = 0;
     int Taken = 0;
 
-    for( int i=0; i < nd-2 ; i++ ) {
-
-        if( i != nd - 2 -1 ) {
+    for( int i = 0; i < nd - 2; i++ )
+    {
+        if( i != nd - 2 - 1 )
+        {
             Sum = 1;
-            for( int j=i+1; j < nd-2; j++ ) {
+            for( int j = i + 1; j < nd - 2; j++ )
+            {
                 Sum *= panBandZLev[j];
             }
-            result = (int) ( ( nLevel-Taken) / Sum );
+            result = static_cast<int>((nLevel - Taken) / Sum);
         }
-        else {
-            result = (int) ( ( nLevel-Taken) % Sum );
+        else
+        {
+            result = static_cast<int>((nLevel - Taken) % Sum);
         }
 
-        snprintf(szVarName,sizeof(szVarName),"%s",
-               l_poDS->papszDimName[paDimIds[panBandZPos[i]]] );
+        snprintf(szVarName, sizeof(szVarName), "%s",
+                 l_poDS->papszDimName[paDimIds[panBandZPos[i]]]);
 
         // TODO: Make sure all the status checks make sense.
 
-        status = nc_inq_varid( cdfid, szVarName, &nVarID );
-        if( status != NC_NOERR ) {
-            /* Try to uppercase the first letter of the variable */
-            /* Note: why is this needed? leaving for safety */
-            szVarName[0] = (char) toupper(szVarName[0]);
-            /* status = */nc_inq_varid( cdfid, szVarName, &nVarID );
+        status = nc_inq_varid(cdfid, szVarName, &nVarID);
+        if( status != NC_NOERR )
+        {
+            // Try to uppercase the first letter of the variable.
+            // Note: Why is this needed?  Leaving for safety.
+            szVarName[0] = static_cast<char>(toupper(szVarName[0]));
+            /* status = */ nc_inq_varid(cdfid, szVarName, &nVarID);
         }
 
         nc_type nVarType = NC_NAT;
-        /* status = */ nc_inq_vartype( cdfid, nVarID, &nVarType );
+        /* status = */ nc_inq_vartype(cdfid, nVarID, &nVarType);
 
         int nDims = 0;
-        /* status = */ nc_inq_varndims( cdfid, nVarID, &nDims );
+        /* status = */ nc_inq_varndims(cdfid, nVarID, &nDims);
 
-        char szMetaTemp[256];
-        if( nDims == 1 ) {
-            size_t count[1] = {1};
-            size_t start[1] = {static_cast<size_t>(result)};
+        char szMetaTemp[256] = {};
+        if( nDims == 1 )
+        {
+            size_t count[1] = { 1 };
+            size_t start[1] = { static_cast<size_t>(result) };
 
-            switch( nVarType ) {
+            switch( nVarType )
+            {
                 case NC_BYTE:
-                    /* TODO: we should check for signed/unsigned byte */
+                    // TODO: Check for signed/unsigned byte.
                     signed char cData;
-                    /* status = */ nc_get_vara_schar( cdfid, nVarID,
+                    /* status = */ nc_get_vara_schar(cdfid, nVarID,
                                                  start,
                                                  count, &cData);
-                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%d", cData );
+                    snprintf(szMetaTemp, sizeof(szMetaTemp), "%d", cData);
                     break;
                 case NC_SHORT:
                     short sData;
-                    /* status = */ nc_get_vara_short( cdfid, nVarID,
+                    /* status = */ nc_get_vara_short(cdfid, nVarID,
                                                  start,
-                                                 count, &sData );
-                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%d", sData );
+                                                 count, &sData);
+                    snprintf(szMetaTemp, sizeof(szMetaTemp), "%d", sData);
                     break;
                 case NC_INT:
                     int nData;
-                    /* status = */ nc_get_vara_int( cdfid, nVarID,
+                    /* status = */ nc_get_vara_int(cdfid, nVarID,
                                                start,
-                                               count, &nData );
-                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%d", nData );
+                                               count, &nData);
+                    snprintf(szMetaTemp, sizeof(szMetaTemp), "%d", nData);
                     break;
                 case NC_FLOAT:
                     float fData;
-                    /* status = */ nc_get_vara_float( cdfid, nVarID,
+                    /* status = */ nc_get_vara_float(cdfid, nVarID,
                                                  start,
-                                                 count, &fData );
-                    CPLsnprintf( szMetaTemp, sizeof(szMetaTemp), "%.8g", fData );
+                                                 count, &fData);
+                    CPLsnprintf(szMetaTemp, sizeof(szMetaTemp),
+                                 "%.8g", fData);
                     break;
                 case NC_DOUBLE:
                     double dfData;
-                    /* status = */ nc_get_vara_double( cdfid, nVarID,
+                    /* status = */ nc_get_vara_double(cdfid, nVarID,
                                                   start,
                                                   count, &dfData);
-                    CPLsnprintf( szMetaTemp, sizeof(szMetaTemp), "%.16g", dfData );
+                    CPLsnprintf(szMetaTemp, sizeof(szMetaTemp),
+                                 "%.16g", dfData);
                     break;
 #ifdef NETCDF_HAS_NC4
                 case NC_UBYTE:
                     unsigned char ucData;
-                    /* status = */ nc_get_vara_uchar( cdfid, nVarID,
+                    /* status = */ nc_get_vara_uchar(cdfid, nVarID,
                                                  start,
                                                  count, &ucData);
-                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%u", ucData );
+                    snprintf(szMetaTemp, sizeof(szMetaTemp), "%u", ucData);
                     break;
                 case NC_USHORT:
                     unsigned short usData;
-                    /* status = */ nc_get_vara_ushort( cdfid, nVarID,
+                    /* status = */ nc_get_vara_ushort(cdfid, nVarID,
                                                   start,
                                                   count, &usData);
-                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%u", usData );
+                    snprintf(szMetaTemp, sizeof(szMetaTemp), "%u", usData);
                     break;
                 case NC_UINT:
                     unsigned int unData;
-                    /* status = */ nc_get_vara_uint( cdfid, nVarID,
+                    /* status = */ nc_get_vara_uint(cdfid, nVarID,
                                                 start,
                                                 count, &unData);
-                    snprintf( szMetaTemp, sizeof(szMetaTemp), "%u", unData );
+                    snprintf(szMetaTemp, sizeof(szMetaTemp), "%u", unData);
                     break;
 #endif
                 default:
-                    CPLDebug( "GDAL_netCDF", "invalid dim %s, type=%d",
-                              szMetaTemp, nVarType);
+                    CPLDebug("GDAL_netCDF", "invalid dim %s, type=%d",
+                             szMetaTemp, nVarType);
                     break;
             }
         }
         else
-            snprintf( szMetaTemp, sizeof(szMetaTemp), "%d", result+1);
+        {
+            snprintf(szMetaTemp, sizeof(szMetaTemp), "%d", result + 1);
+        }
 
-/* -------------------------------------------------------------------- */
-/*      Save dimension value                                            */
-/* -------------------------------------------------------------------- */
-        /* NOTE: removed #original_units as not part of CF-1 */
+        // Save dimension value.
+        // NOTE: removed #original_units as not part of CF-1.
 
-        char szMetaName[NC_MAX_NAME+1+32];
-        snprintf( szMetaName, sizeof(szMetaName), "NETCDF_DIM_%s",  szVarName );
-        SetMetadataItem( szMetaName, szMetaTemp );
+        char szMetaName[NC_MAX_NAME + 1 + 32];
+        snprintf(szMetaName, sizeof(szMetaName), "NETCDF_DIM_%s", szVarName);
+        SetMetadataItem(szMetaName, szMetaTemp);
 
         Taken += result * Sum;
+    }  // End loop non-spatial dimensions.
 
-    } // end loop non-spatial dimensions
-
-/* -------------------------------------------------------------------- */
-/*      Get all other metadata                                          */
-/* -------------------------------------------------------------------- */
-    int nAtt=0;
-    nc_inq_varnatts( cdfid, nZId, &nAtt );
+    // Get all other metadata.
+    int nAtt = 0;
+    nc_inq_varnatts(cdfid, nZId, &nAtt);
 
-    for( int i=0; i < nAtt ; i++ ) {
-
-        char szMetaName[NC_MAX_NAME+1];
-        szMetaName[0] = 0;
-        status = nc_inq_attname( cdfid, nZId, i, szMetaName);
-        if ( status != NC_NOERR )
+    for( int i = 0; i < nAtt; i++ )
+    {
+        char szMetaName[NC_MAX_NAME + 1] = {};
+        status = nc_inq_attname(cdfid, nZId, i, szMetaName);
+        if( status != NC_NOERR )
             continue;
 
         char *pszMetaValue = NULL;
-        if ( NCDFGetAttr( cdfid, nZId, szMetaName, &pszMetaValue) == CE_None ) {
-            SetMetadataItem( szMetaName, pszMetaValue );
+        if( NCDFGetAttr(cdfid, nZId, szMetaName, &pszMetaValue) == CE_None )
+        {
+            SetMetadataItem(szMetaName, pszMetaValue);
         }
-        else {
-            CPLDebug( "GDAL_netCDF", "invalid Band metadata %s", szMetaName );
+        else
+        {
+            CPLDebug("GDAL_netCDF", "invalid Band metadata %s", szMetaName);
         }
 
-        if ( pszMetaValue )  {
-            CPLFree( pszMetaValue );
+        if( pszMetaValue )
+        {
+            CPLFree(pszMetaValue);
             pszMetaValue = NULL;
         }
-
     }
 
     return CE_None;
@@ -1232,65 +1293,80 @@ CPLErr netCDFRasterBand::CreateBandMetadata( const int *paDimIds )
 /*                             CheckData()                              */
 /************************************************************************/
 template <class T>
-void  netCDFRasterBand::CheckData ( void * pImage, void * pImageNC,
-                                    size_t nTmpBlockXSize, size_t nTmpBlockYSize,
-                                    bool bCheckIsNan )
+void netCDFRasterBand::CheckData( void *pImage, void *pImageNC,
+                                  size_t nTmpBlockXSize, size_t nTmpBlockYSize,
+                                  bool bCheckIsNan )
 {
-  CPLAssert( pImage != NULL && pImageNC != NULL );
-
-  /* if this block is not a full block (in the x axis), we need to re-arrange the data
-     this is because partial blocks are not arranged the same way in netcdf and gdal */
-  if ( nTmpBlockXSize != static_cast<size_t>(nBlockXSize) ) {
-    T* ptrWrite = (T *) pImage;
-    T* ptrRead = (T *) pImageNC;
-    for( size_t j=0; j<nTmpBlockYSize; j++, ptrWrite += nBlockXSize, ptrRead += nTmpBlockXSize) {
-        memmove( ptrWrite, ptrRead, nTmpBlockXSize * sizeof(T) );
-    }
-  }
-
-  /* is valid data checking needed or requested? */
-  if ( (adfValidRange[0] != dfNoDataValue) ||
-       (adfValidRange[1] != dfNoDataValue) ||
-       bCheckIsNan ) {
-    for( size_t j=0; j<nTmpBlockYSize; j++) {
-      // k moves along the gdal block, skipping the out-of-range pixels
-      size_t k = j*nBlockXSize;
-      for( size_t i=0; i<nTmpBlockXSize; i++,k++) {
-        /* check for nodata and nan */
-        if ( CPLIsEqual( (double) ((T *)pImage)[k], dfNoDataValue ) )
-          continue;
-        if( bCheckIsNan && CPLIsNan( (double) (( (T *) pImage))[k] ) ) {
-          ( (T *)pImage )[k] = (T)dfNoDataValue;
-          continue;
-        }
-        /* check for valid_range */
-        if ( ( ( adfValidRange[0] != dfNoDataValue ) &&
-               ( ((T *)pImage)[k] < (T)adfValidRange[0] ) )
-             ||
-             ( ( adfValidRange[1] != dfNoDataValue ) &&
-               ( ((T *)pImage)[k] > (T)adfValidRange[1] ) ) ) {
-          ( (T *)pImage )[k] = (T)dfNoDataValue;
-        }
-      }
-    }
-  }
-
-  /* If minimum longitude is > 180, subtract 360 from all.
-     If not, disable checking for further calls (check just once).
-     Only check first and last block elements since lon must be monotonic. */
-  const bool bIsSigned = std::numeric_limits<T>::is_signed;
-  if ( bCheckLongitude && bIsSigned &&
-       MIN( ((T *)pImage)[0], ((T *)pImage)[nTmpBlockXSize-1] ) > 180.0 ) {
-    for( size_t j=0; j<nTmpBlockYSize; j++) {
-      size_t k = j*nBlockXSize;
-      for( size_t i=0; i<nTmpBlockXSize; i++,k++) {
-        if ( ! CPLIsEqual( (double) ((T *)pImage)[k], dfNoDataValue ) )
-          ((T *)pImage )[k] = static_cast<T>(((T *)pImage )[k] - 360);
-      }
-    }
-  }
-  else
-    bCheckLongitude = false;
+    CPLAssert(pImage != NULL && pImageNC != NULL);
+
+    // If this block is not a full block (in the x axis), we need to re-arrange
+    // the data this is because partial blocks are not arranged the same way in
+    // netcdf and gdal.
+    if( nTmpBlockXSize != static_cast<size_t>(nBlockXSize) )
+    {
+        T *ptrWrite = (T *)pImage;
+        T *ptrRead = (T *)pImageNC;
+        for( size_t j = 0;
+             j < nTmpBlockYSize;
+             j++, ptrWrite += nBlockXSize, ptrRead += nTmpBlockXSize)
+        {
+            memmove(ptrWrite, ptrRead, nTmpBlockXSize * sizeof(T));
+        }
+    }
+
+    // Is valid data checking needed or requested?
+    if( (adfValidRange[0] != dfNoDataValue) ||
+        (adfValidRange[1] != dfNoDataValue) ||
+        bCheckIsNan )
+    {
+        for( size_t j = 0; j < nTmpBlockYSize; j++ )
+        {
+            // k moves along the gdal block, skipping the out-of-range pixels.
+            size_t k = j * nBlockXSize;
+            for( size_t i = 0; i < nTmpBlockXSize; i++, k++ )
+            {
+                // Check for nodata and nan.
+                if( CPLIsEqual((double)((T *)pImage)[k], dfNoDataValue) )
+                    continue;
+                if( bCheckIsNan && CPLIsNan((double)(((T *)pImage))[k]) )
+                {
+                    ((T *)pImage)[k] = (T)dfNoDataValue;
+                    continue;
+                }
+                // Check for valid_range.
+                if( ((adfValidRange[0] != dfNoDataValue) &&
+                     (((T *)pImage)[k] < (T)adfValidRange[0]))
+                    ||
+                    ((adfValidRange[1] != dfNoDataValue) &&
+                     (((T *)pImage)[k] > (T)adfValidRange[1])) )
+                {
+                    ((T *)pImage)[k] = (T)dfNoDataValue;
+                }
+            }
+        }
+    }
+
+    // If minimum longitude is > 180, subtract 360 from all.
+    // If not, disable checking for further calls (check just once).
+    // Only check first and last block elements since lon must be monotonic.
+    const bool bIsSigned = std::numeric_limits<T>::is_signed;
+    if( bCheckLongitude && bIsSigned &&
+        std::min(((T *)pImage)[0], ((T *)pImage)[nTmpBlockXSize - 1]) > 180.0 )
+    {
+        for( size_t j = 0; j < nTmpBlockYSize; j++ )
+        {
+            size_t k = j * nBlockXSize;
+            for( size_t i = 0; i < nTmpBlockXSize; i++, k++ )
+            {
+                if( !CPLIsEqual((double)((T *)pImage)[k], dfNoDataValue) )
+                    ((T *)pImage)[k] = static_cast<T>(((T *)pImage)[k] - 360);
+            }
+        }
+    }
+    else
+    {
+        bCheckLongitude = false;
+    }
 }
 
 /************************************************************************/
@@ -1298,201 +1374,206 @@ void  netCDFRasterBand::CheckData ( void * pImage, void * pImageNC,
 /************************************************************************/
 
 CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                     void * pImage )
+                                     void *pImage )
 
 {
     CPLMutexHolderD(&hNCMutex);
 
     int nd = 0;
-    nc_inq_varndims ( cdfid, nZId, &nd );
+    nc_inq_varndims(cdfid, nZId, &nd);
 
 #ifdef NCDF_DEBUG
-    if ( (nBlockYOff == 0) || (nBlockYOff == nRasterYSize-1) )
-        CPLDebug( "GDAL_netCDF", "netCDFRasterBand::IReadBlock( %d, %d, ... ) nBand=%d nd=%d",
-                  nBlockXOff, nBlockYOff, nBand, nd );
+    if( (nBlockYOff == 0) || (nBlockYOff == nRasterYSize - 1) )
+        CPLDebug("GDAL_netCDF",
+                 "netCDFRasterBand::IReadBlock( %d, %d, ...) nBand=%d nd=%d",
+                 nBlockXOff, nBlockYOff, nBand, nd);
 #endif
 
-/* -------------------------------------------------------------------- */
-/*      Locate X, Y and Z position in the array                         */
-/* -------------------------------------------------------------------- */
+    // Locate X, Y and Z position in the array.
 
-    size_t start[ MAX_NC_DIMS ];
-    memset( start, 0, sizeof( start ) );
+    size_t start[MAX_NC_DIMS] = {};
     start[nBandXPos] = nBlockXOff * nBlockXSize;
 
-    // check y order
-    if( ( ( netCDFDataset *) poDS )->bBottomUp ) {
+    // Check y order.
+    if( static_cast<netCDFDataset *>(poDS)->bBottomUp )
+    {
 #ifdef NCDF_DEBUG
-      if ( (nBlockYOff == 0) || (nBlockYOff == nRasterYSize-1) )
-        CPLDebug( "GDAL_netCDF",
-                  "reading bottom-up dataset, nBlockYSize=%d nRasterYSize=%d",
-                  nBlockYSize, nRasterYSize );
+        if( (nBlockYOff == 0) || (nBlockYOff == nRasterYSize - 1) )
+            CPLDebug(
+                "GDAL_netCDF",
+                "reading bottom-up dataset, nBlockYSize=%d nRasterYSize=%d",
+                nBlockYSize, nRasterYSize);
 #endif
-      // check block size - return error if not 1
-      // reading upside-down rasters with nBlockYSize!=1 needs further development
-      // perhaps a simple solution is to invert geotransform and not use bottom-up
-      if ( nBlockYSize == 1 ) {
-        start[nBandYPos] = nRasterYSize - 1 - nBlockYOff;
-      }
-      else {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "nBlockYSize = %d, only 1 supported when reading bottom-up dataset", nBlockYSize );
-        return CE_Failure;
-      }
-    } else {
-      start[nBandYPos] = nBlockYOff * nBlockYSize;
+        // Check block size - return error if not 1.
+        // reading upside-down rasters with nBlockYSize!=1 needs further
+        // development.  perhaps a simple solution is to invert geotransform and
+        // not use bottom-up.
+        if( nBlockYSize == 1 )
+        {
+            start[nBandYPos] = nRasterYSize - 1 - nBlockYOff;
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "nBlockYSize = %d, only 1 supported when "
+                     "reading bottom-up dataset",
+                     nBlockYSize);
+            return CE_Failure;
+        }
+    }
+    else
+    {
+        start[nBandYPos] = nBlockYOff * nBlockYSize;
     }
 
-    size_t edge[ MAX_NC_DIMS ];
-    memset( edge,  0, sizeof( edge )  );
+    size_t edge[MAX_NC_DIMS] = {};
 
     edge[nBandXPos] = nBlockXSize;
-    if ( ( start[nBandXPos] + edge[nBandXPos] ) > (size_t)nRasterXSize )
-       edge[nBandXPos] = nRasterXSize - start[nBandXPos];
+    if( (start[nBandXPos] + edge[nBandXPos]) > (size_t)nRasterXSize )
+        edge[nBandXPos] = nRasterXSize - start[nBandXPos];
     edge[nBandYPos] = nBlockYSize;
-    if ( ( start[nBandYPos] + edge[nBandYPos] ) > (size_t)nRasterYSize )
-      edge[nBandYPos] = nRasterYSize - start[nBandYPos];
+    if( (start[nBandYPos] + edge[nBandYPos]) > (size_t)nRasterYSize )
+        edge[nBandYPos] = nRasterYSize - start[nBandYPos];
 
 #ifdef NCDF_DEBUG
-    if ( (nBlockYOff == 0) || (nBlockYOff == nRasterYSize-1) )
-      CPLDebug( "GDAL_netCDF", "start={%ld,%ld} edge={%ld,%ld} bBottomUp=%d",
-                start[nBandXPos], start[nBandYPos], edge[nBandXPos], edge[nBandYPos],
-                ( ( netCDFDataset *) poDS )->bBottomUp );
+    if( nBlockYOff == 0 || (nBlockYOff == nRasterYSize - 1) )
+        CPLDebug("GDAL_netCDF", "start={%ld,%ld} edge={%ld,%ld} bBottomUp=%d",
+                  start[nBandXPos], start[nBandYPos],
+                  edge[nBandXPos], edge[nBandYPos],
+                  ((netCDFDataset *)poDS)->bBottomUp);
 #endif
 
-    if( nd == 3 ) {
-        start[panBandZPos[0]]  = nLevel;     // z
-        edge [panBandZPos[0]]  = 1;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Compute multidimention band position                            */
-/*                                                                      */
-/* BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)*/
-/* if Data[2,3,4,x,y]                                                   */
-/*                                                                      */
-/*  BandPos0 = (nBand ) / (3*4)                                         */
-/*  BandPos1 = (nBand - (3*4) ) / (4)                                   */
-/*  BandPos2 = (nBand - (3*4) ) % (4)                                   */
-/* -------------------------------------------------------------------- */
-    if (nd > 3)
+    if( nd == 3 )
+    {
+        start[panBandZPos[0]] = nLevel;  // z
+        edge[panBandZPos[0]] = 1;
+    }
+
+    // Compute multidimention band position.
+    //
+    // BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)
+    // if Data[2,3,4,x,y]
+    //
+    //  BandPos0 = (nBand) / (3*4)
+    //  BandPos1 = (nBand - (3*4)) / (4)
+    //  BandPos2 = (nBand - (3*4)) % (4)
+    if( nd > 3 )
     {
         int Sum = -1;
         int Taken = 0;
-        for( int i=0; i < nd-2 ; i++ )
+        for( int i=0; i < nd - 2 ; i++ )
         {
-            if( i != nd - 2 -1 ) {
+            if( i != nd - 2 - 1 )
+            {
                 Sum = 1;
-                for( int j=i+1; j < nd-2; j++ ) {
+                for( int j = i + 1; j < nd - 2; j++ )
+                {
                     Sum *= panBandZLev[j];
                 }
-                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) / Sum );
+                start[panBandZPos[i]] = (int)((nLevel - Taken) / Sum);
                 edge[panBandZPos[i]] = 1;
-            } else {
-                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) % Sum );
+            }
+            else
+            {
+                start[panBandZPos[i]] = (int)((nLevel - Taken) % Sum);
                 edge[panBandZPos[i]] = 1;
             }
             Taken += static_cast<int>(start[panBandZPos[i]]) * Sum;
         }
     }
 
-    /* make sure we are in data mode */
-    ( ( netCDFDataset * ) poDS )->SetDefineMode( false );
+    // Make sure we are in data mode.
+    static_cast<netCDFDataset *>(poDS)->SetDefineMode(false);
 
-    /*
-     * If this block is not a full block in the x axis, we need to
-     * re-arrange the data because partial blocks are not arranged the
-     * same way in netcdf and gdal, so we first we read the netcdf data at
-     * the end of the gdal block buffer then re-arrange rows in CheckData().
-     */
+    // If this block is not a full block in the x axis, we need to
+    // re-arrange the data because partial blocks are not arranged the
+    // same way in netcdf and gdal, so we first we read the netcdf data at
+    // the end of the gdal block buffer then re-arrange rows in CheckData().
     void *pImageNC = pImage;
-    if( edge[nBandXPos] != (size_t) nBlockXSize )
+    if( edge[nBandXPos] != static_cast<size_t>(nBlockXSize) )
     {
-        pImageNC = (GByte *) pImage
-            + ( (nBlockXSize * nBlockYSize - edge[nBandXPos] * edge[nBandYPos])
-                * (GDALGetDataTypeSize(eDataType) / 8) );
+        pImageNC = (GByte *)pImage
+            + ((nBlockXSize * nBlockYSize - edge[nBandXPos] * edge[nBandYPos])
+                * (GDALGetDataTypeSize(eDataType) / 8));
     }
 
-    /* read data according to type */
+    // Read data according to type.
     int status;
     if( eDataType == GDT_Byte )
     {
-        if (this->bSignedData)
+        if( bSignedData )
         {
-            status = nc_get_vara_schar( cdfid, nZId, start, edge,
-                                        (signed char *) pImageNC );
-            if ( status == NC_NOERR )
-                CheckData<signed char>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
-                                        false );
+            status = nc_get_vara_schar(cdfid, nZId, start, edge,
+                                       (signed char *)pImageNC);
+            if( status == NC_NOERR )
+                CheckData<signed char>(pImage, pImageNC, edge[nBandXPos],
+                                       edge[nBandYPos], false);
         }
-        else {
-            status = nc_get_vara_uchar( cdfid, nZId, start, edge,
-                                        (unsigned char *) pImageNC );
-            if ( status == NC_NOERR )
-                CheckData<unsigned char>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
-                                          false );
+        else
+        {
+            status = nc_get_vara_uchar(cdfid, nZId, start, edge,
+                                       (unsigned char *)pImageNC);
+            if( status == NC_NOERR )
+                CheckData<unsigned char>(pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                         false);
         }
     }
-
     else if( eDataType == GDT_Int16 )
     {
-        status = nc_get_vara_short( cdfid, nZId, start, edge,
-                                    (short *) pImageNC );
-        if ( status == NC_NOERR )
-            CheckData<short>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
-                              false );
+        status = nc_get_vara_short(cdfid, nZId, start, edge, (short *)pImageNC);
+        if( status == NC_NOERR )
+            CheckData<short>(pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                             false);
     }
     else if( eDataType == GDT_Int32 )
     {
         if( sizeof(long) == 4 )
         {
-            status = nc_get_vara_long( cdfid, nZId, start, edge,
-                                       (long *) pImageNC );
-            if ( status == NC_NOERR )
-                CheckData<long>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
-                                 false );
+            status =
+                nc_get_vara_long(cdfid, nZId, start, edge, (long *)pImageNC);
+            if( status == NC_NOERR )
+                CheckData<long>(pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                false);
         }
         else
         {
-            status = nc_get_vara_int( cdfid, nZId, start, edge,
-                                      (int *) pImageNC );
-            if ( status == NC_NOERR )
-                CheckData<int>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
-                                false );
+            status = nc_get_vara_int(cdfid, nZId, start, edge, (int *)pImageNC);
+            if( status == NC_NOERR )
+                CheckData<int>(pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                               false);
         }
     }
     else if( eDataType == GDT_Float32 )
     {
-        status = nc_get_vara_float( cdfid, nZId, start, edge,
-                                    (float *) pImageNC );
-        if ( status == NC_NOERR )
-            CheckData<float>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
-                              true );
+        status = nc_get_vara_float(cdfid, nZId, start, edge, (float *)pImageNC);
+        if( status == NC_NOERR )
+            CheckData<float>(pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                             true);
     }
     else if( eDataType == GDT_Float64 )
     {
-        status = nc_get_vara_double( cdfid, nZId, start, edge,
-                                     (double *) pImageNC );
-        if ( status == NC_NOERR )
-            CheckData<double>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
-                               true );
+        status =
+            nc_get_vara_double(cdfid, nZId, start, edge, (double *)pImageNC);
+        if( status == NC_NOERR )
+            CheckData<double>(pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                               true);
     }
 #ifdef NETCDF_HAS_NC4
     else if( eDataType == GDT_UInt16 )
     {
-        status = nc_get_vara_ushort( cdfid, nZId, start, edge,
-                                    (unsigned short *) pImageNC );
-        if ( status == NC_NOERR )
-            CheckData<unsigned short>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
-                                       false );
+        status = nc_get_vara_ushort(cdfid, nZId, start, edge,
+                                    (unsigned short *)pImageNC);
+        if( status == NC_NOERR )
+            CheckData<unsigned short>(pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                      false);
     }
     else if( eDataType == GDT_UInt32 )
     {
-        status = nc_get_vara_uint( cdfid, nZId, start, edge,
-                                   (unsigned int *) pImageNC );
-        if ( status == NC_NOERR )
-            CheckData<unsigned int>( pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
-                                     false );
+        status = nc_get_vara_uint(cdfid, nZId, start, edge,
+                                  (unsigned int *)pImageNC);
+        if( status == NC_NOERR )
+            CheckData<unsigned int>(pImage, pImageNC, edge[nBandXPos], edge[nBandYPos],
+                                    false);
     }
 #endif
     else
@@ -1500,9 +1581,9 @@ CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     if( status != NC_NOERR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "netCDF scanline fetch failed: #%d (%s)",
-                  status, nc_strerror( status ) );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "netCDF scanline fetch failed: #%d (%s)", status,
+                 nc_strerror(status));
         return CE_Failure;
     }
 
@@ -1515,130 +1596,137 @@ CPLErr netCDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 CPLErr netCDFRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
                                       int nBlockYOff,
-                                      void * pImage )
+                                      void *pImage )
 {
     CPLMutexHolderD(&hNCMutex);
 
 #ifdef NCDF_DEBUG
-    if ( (nBlockYOff == 0) || (nBlockYOff == nRasterYSize-1) )
-        CPLDebug( "GDAL_netCDF", "netCDFRasterBand::IWriteBlock( %d, %d, ... ) nBand=%d",
-                  nBlockXOff, nBlockYOff, nBand );
+    if( nBlockYOff == 0 || (nBlockYOff == nRasterYSize - 1) )
+        CPLDebug("GDAL_netCDF",
+                 "netCDFRasterBand::IWriteBlock( %d, %d, ...) nBand=%d",
+                 nBlockXOff, nBlockYOff, nBand);
 #endif
 
-    int nd;
-    nc_inq_varndims ( cdfid, nZId, &nd );
+    int nd = 0;
+    nc_inq_varndims(cdfid, nZId, &nd);
 
-/* -------------------------------------------------------------------- */
-/*      Locate X, Y and Z position in the array                         */
-/* -------------------------------------------------------------------- */
+    // Locate X, Y and Z position in the array.
 
-    size_t start[ MAX_NC_DIMS];
-    memset( start, 0, sizeof( start ) );
+    size_t start[MAX_NC_DIMS];
+    memset(start, 0, sizeof(start));
 
-    start[nBandXPos] = 0;          // x dim can move around in array
-    // check y order
-    if( ( ( netCDFDataset *) poDS )->bBottomUp ) {
+    start[nBandXPos] = 0;  // x dim can move around in array.
+    // check y order.
+    if( static_cast<netCDFDataset *>(poDS)->bBottomUp )
+    {
         start[nBandYPos] = nRasterYSize - 1 - nBlockYOff;
-    } else {
-        start[nBandYPos] = nBlockYOff; // y
+    }
+    else
+    {
+        start[nBandYPos] = nBlockYOff;  // y
     }
 
-    size_t edge[ MAX_NC_DIMS ];
-    memset( edge,  0, sizeof( edge )  );
+    size_t edge[MAX_NC_DIMS] = {};
 
     edge[nBandXPos] = nBlockXSize;
     edge[nBandYPos] = 1;
 
-    if( nd == 3 ) {
-        start[panBandZPos[0]]  = nLevel;     // z
-        edge [panBandZPos[0]]  = 1;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Compute multidimention band position                            */
-/*                                                                      */
-/* BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)*/
-/* if Data[2,3,4,x,y]                                                   */
-/*                                                                      */
-/*  BandPos0 = (nBand ) / (3*4)                                         */
-/*  BandPos1 = (nBand - (3*4) ) / (4)                                   */
-/*  BandPos2 = (nBand - (3*4) ) % (4)                                   */
-/* -------------------------------------------------------------------- */
-    if (nd > 3)
+    if( nd == 3 )
+    {
+        start[panBandZPos[0]] = nLevel;  // z
+        edge[panBandZPos[0]] = 1;
+    }
+
+    // Compute multidimention band position.
+    //
+    // BandPosition = (Total - sum(PastBandLevels) - 1)/sum(remainingLevels)
+    // if Data[2,3,4,x,y]
+    //
+    //  BandPos0 = (nBand) / (3*4)
+    //  BandPos1 = (nBand - (3*4)) / (4)
+    //  BandPos2 = (nBand - (3*4)) % (4)
+    if( nd > 3 )
     {
         int Sum = -1;
         int Taken = 0;
-        for( int i=0; i < nd-2 ; i++ )
+        for( int i = 0; i < nd - 2 ; i++ )
         {
-            if( i != nd - 2 -1 ) {
+            if( i != nd - 2 -1 )
+            {
                 Sum = 1;
-                for( int j=i+1; j < nd-2; j++ ) {
+                for( int j = i + 1; j < nd - 2; j++ )
+                {
                     Sum *= panBandZLev[j];
                 }
-                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) / Sum );
+                start[panBandZPos[i]] = (int)((nLevel - Taken) / Sum);
                 edge[panBandZPos[i]] = 1;
-            } else {
-                start[panBandZPos[i]] = (int) ( ( nLevel-Taken) % Sum );
+            }
+            else
+            {
+                start[panBandZPos[i]] = (int)((nLevel - Taken) % Sum);
                 edge[panBandZPos[i]] = 1;
             }
             Taken += static_cast<int>(start[panBandZPos[i]]) * Sum;
         }
     }
 
-    /* make sure we are in data mode */
-    ( ( netCDFDataset * ) poDS )->SetDefineMode( false );
+    // Make sure we are in data mode.
+    static_cast<netCDFDataset *>(poDS)->SetDefineMode(false);
 
-    /* copy data according to type */
-    int status;
-    if( eDataType == GDT_Byte ) {
-        if ( this->bSignedData )
-            status = nc_put_vara_schar( cdfid, nZId, start, edge,
-                                         (signed char*) pImage);
+    // Copy data according to type.
+    int status = 0;
+    if( eDataType == GDT_Byte )
+    {
+        if( bSignedData )
+            status = nc_put_vara_schar(cdfid, nZId, start, edge,
+                                       (signed char *)pImage);
         else
-            status = nc_put_vara_uchar( cdfid, nZId, start, edge,
-                                         (unsigned char*) pImage);
+            status = nc_put_vara_uchar(cdfid, nZId, start, edge,
+                                       (unsigned char *)pImage);
     }
-    else if( eDataType == GDT_Int16 ) {
-        status = nc_put_vara_short( cdfid, nZId, start, edge,
-                                    (short *) pImage);
+    else if( eDataType == GDT_Int16 )
+    {
+        status = nc_put_vara_short(cdfid, nZId, start, edge, (short *)pImage);
     }
-    else if( eDataType == GDT_Int32 ) {
-        status = nc_put_vara_int( cdfid, nZId, start, edge,
-                                   (int *) pImage);
+    else if( eDataType == GDT_Int32 )
+    {
+        status = nc_put_vara_int(cdfid, nZId, start, edge, (int *)pImage);
     }
-    else if( eDataType == GDT_Float32 ) {
-        status = nc_put_vara_float( cdfid, nZId, start, edge,
-                                    (float *) pImage);
+    else if( eDataType == GDT_Float32 )
+    {
+        status = nc_put_vara_float(cdfid, nZId, start, edge, (float *)pImage);
     }
-    else if( eDataType == GDT_Float64 ) {
-        status = nc_put_vara_double( cdfid, nZId, start, edge,
-                                     (double *) pImage);
+    else if( eDataType == GDT_Float64 )
+    {
+        status = nc_put_vara_double(cdfid, nZId, start, edge, (double *)pImage);
     }
 #ifdef NETCDF_HAS_NC4
-    else if( eDataType == GDT_UInt16
-             && ((netCDFDataset *) poDS)->eFormat == NCDF_FORMAT_NC4 ) {
-        status = nc_put_vara_ushort( cdfid, nZId, start, edge,
-                                     (unsigned short *) pImage);
+    else if( eDataType == GDT_UInt16 &&
+             ((netCDFDataset *) poDS)->eFormat == NCDF_FORMAT_NC4 )
+    {
+        status = nc_put_vara_ushort(cdfid, nZId, start, edge,
+                                    (unsigned short *)pImage);
     }
-    else if( eDataType == GDT_UInt32
-             && ((netCDFDataset *) poDS)->eFormat == NCDF_FORMAT_NC4 ) {
-        status = nc_put_vara_uint( cdfid, nZId, start, edge,
-                                   (unsigned int *) pImage);
+    else if( eDataType == GDT_UInt32 &&
+             ((netCDFDataset *) poDS)->eFormat == NCDF_FORMAT_NC4 )
+    {
+        status =
+            nc_put_vara_uint(cdfid, nZId, start, edge, (unsigned int *)pImage);
     }
 #endif
-    else {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "The NetCDF driver does not support GDAL data type %d",
-                  eDataType );
+    else
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The NetCDF driver does not support GDAL data type %d",
+                 eDataType);
         status = NC_EBADTYPE;
     }
     NCDF_ERR(status);
 
     if( status != NC_NOERR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "netCDF scanline write failed: %s",
-                  nc_strerror( status ) );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "netCDF scanline write failed: %s", nc_strerror(status));
         return CE_Failure;
     }
 
@@ -1695,7 +1783,7 @@ netCDFDataset::netCDFDataset() :
     nLayers(0),
     papoLayers(NULL)
 {
-    /* projection/GT */
+    // Projection/GT.
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
@@ -1713,46 +1801,48 @@ netCDFDataset::~netCDFDataset()
 {
     CPLMutexHolderD(&hNCMutex);
 
-    #ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "netCDFDataset::~netCDFDataset(), cdfid=%d filename=%s",
-              cdfid, osFilename.c_str() );
-    #endif
-    /* make sure projection is written if GeoTransform OR Projection are missing */
-    if( (GetAccess() == GA_Update) && (! bAddedProjectionVars) ) {
-        if ( bSetProjection && ! bSetGeoTransform )
+#ifdef NCDF_DEBUG
+    CPLDebug("GDAL_netCDF",
+             "netCDFDataset::~netCDFDataset(), cdfid=%d filename=%s", cdfid,
+             osFilename.c_str());
+#endif
+
+    // Ensure projection is written if GeoTransform OR Projection are missing.
+    if( GetAccess() == GA_Update && !bAddedProjectionVars )
+    {
+        if( bSetProjection && !bSetGeoTransform )
             AddProjectionVars();
-        else if ( bSetGeoTransform && ! bSetProjection )
+        else if( bSetGeoTransform && !bSetProjection )
             AddProjectionVars();
-            // CPLError( CE_Warning, CPLE_AppDefined,
-            //           "netCDFDataset::~netCDFDataset() Projection was not defined, projection will be missing" );
     }
 
     FlushCache();
 
-    for(int i=0;i<nLayers;i++)
+    for(int i = 0; i < nLayers; i++)
         delete papoLayers[i];
     CPLFree(papoLayers);
 
-    for(size_t i=0; i<apoVectorDatasets.size();i++)
+    for(size_t i = 0; i < apoVectorDatasets.size(); i++)
         delete apoVectorDatasets[i];
 
-    /* make sure projection variable is written to band variable */
-    if( (GetAccess() == GA_Update) && ! bAddedGridMappingRef )
+    // Make sure projection variable is written to band variable.
+    if( GetAccess() == GA_Update && !bAddedGridMappingRef )
         AddGridMappingRef();
 
-    CSLDestroy( papszMetadata );
-    CSLDestroy( papszSubDatasets );
-    CSLDestroy( papszCreationOptions );
+    CSLDestroy(papszMetadata);
+    CSLDestroy(papszSubDatasets);
+    CSLDestroy(papszCreationOptions);
 
-    CPLFree( pszProjection );
-    CPLFree( pszCFProjection );
-    CPLFree( pszCFCoordinates );
+    CPLFree(pszProjection);
+    CPLFree(pszCFProjection);
+    CPLFree(pszCFCoordinates);
 
-    if( cdfid > 0 ) {
+    if( cdfid > 0 )
+    {
 #ifdef NCDF_DEBUG
-        CPLDebug( "GDAL_netCDF", "calling nc_close( %d )", cdfid );
+        CPLDebug("GDAL_netCDF", "calling nc_close( %d)", cdfid);
 #endif
-        int status = nc_close( cdfid );
+        int status = nc_close(cdfid);
         NCDF_ERR(status);
     }
 }
@@ -1762,25 +1852,24 @@ netCDFDataset::~netCDFDataset()
 /************************************************************************/
 bool netCDFDataset::SetDefineMode( bool bNewDefineMode )
 {
-    /* do nothing if already in new define mode
-       or if dataset is in read-only mode */
-    if ( ( bDefineMode == bNewDefineMode ) ||
-         ( GetAccess() == GA_ReadOnly ) )
+    // Do nothing if already in new define mode
+    // or if dataset is in read-only mode.
+    if( bDefineMode == bNewDefineMode || GetAccess() == GA_ReadOnly )
         return true;
 
-    CPLDebug( "GDAL_netCDF", "SetDefineMode(%d) old=%d",
-              static_cast<int>(bNewDefineMode), static_cast<int>(bDefineMode) );
+    CPLDebug("GDAL_netCDF", "SetDefineMode(%d) old=%d",
+             static_cast<int>(bNewDefineMode), static_cast<int>(bDefineMode));
 
     bDefineMode = bNewDefineMode;
 
     int status;
-    if ( bDefineMode )
-        status = nc_redef( cdfid );
+    if( bDefineMode )
+        status = nc_redef(cdfid);
     else
-        status = nc_enddef( cdfid );
+        status = nc_enddef(cdfid);
 
     NCDF_ERR(status);
-    return (status == NC_NOERR);
+    return status == NC_NOERR;
 }
 
 /************************************************************************/
@@ -1789,8 +1878,7 @@ bool netCDFDataset::SetDefineMode( bool bNewDefineMode )
 
 char **netCDFDataset::GetMetadataDomainList()
 {
-    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
-                                   TRUE,
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(), TRUE,
                                    "SUBDATASETS", NULL);
 }
 
@@ -1802,14 +1890,14 @@ char **netCDFDataset::GetMetadata( const char *pszDomain )
     if( pszDomain != NULL && STARTS_WITH_CI(pszDomain, "SUBDATASETS") )
         return papszSubDatasets;
 
-    return GDALDataset::GetMetadata( pszDomain );
+    return GDALDataset::GetMetadata(pszDomain);
 }
 
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char * netCDFDataset::GetProjectionRef()
+const char *netCDFDataset::GetProjectionRef()
 {
     if( bSetProjection )
         return pszProjection;
@@ -1824,43 +1912,34 @@ const char * netCDFDataset::GetProjectionRef()
 CPLXMLNode *netCDFDataset::SerializeToXML( const char *pszUnused )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Overridden from GDALPamDataset to add only band histogram        */
-/*      and statistics. See bug #4244.                                  */
-/* -------------------------------------------------------------------- */
+    // Overridden from GDALPamDataset to add only band histogram
+    // and statistics. See bug #4244.
 
     if( psPam == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Setup root node and attributes.                                 */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode *psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMDataset" );
+    // Setup root node and attributes.
+    CPLXMLNode *psDSTree = CPLCreateXMLNode(NULL, CXT_Element, "PAMDataset");
 
-/* -------------------------------------------------------------------- */
-/*      Process bands.                                                  */
-/* -------------------------------------------------------------------- */
+    // Process bands.
     for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
     {
-        netCDFRasterBand *poBand = (netCDFRasterBand *)
-            GetRasterBand(iBand+1);
+        netCDFRasterBand *poBand =
+            static_cast<netCDFRasterBand *>(GetRasterBand(iBand + 1));
 
         if( poBand == NULL || !(poBand->GetMOFlags() & GMO_PAM_CLASS) )
             continue;
 
-        CPLXMLNode *psBandTree = poBand->SerializeToXML( pszUnused );
+        CPLXMLNode *psBandTree = poBand->SerializeToXML(pszUnused);
 
         if( psBandTree != NULL )
-            CPLAddXMLChild( psDSTree, psBandTree );
+            CPLAddXMLChild(psDSTree, psBandTree);
     }
 
-/* -------------------------------------------------------------------- */
-/*      We don't want to return anything if we had no metadata to       */
-/*      attach.                                                         */
-/* -------------------------------------------------------------------- */
+    // We don't want to return anything if we had no metadata to attach.
     if( psDSTree->psChild == NULL )
     {
-        CPLDestroyXMLNode( psDSTree );
+        CPLDestroyXMLNode(psDSTree);
         psDSTree = NULL;
     }
 
@@ -1875,7 +1954,7 @@ double netCDFDataset::FetchCopyParm( const char *pszGridMappingValue,
                                      const char *pszParm, double dfDefault )
 
 {
-    char szTemp[ 256 ];
+    char szTemp[256] = {};
     snprintf(szTemp, sizeof(szTemp), "%s#%s", pszGridMappingValue, pszParm);
     const char *pszValue = CSLFetchNameValue(papszMetadata, szTemp);
 
@@ -1891,33 +1970,37 @@ double netCDFDataset::FetchCopyParm( const char *pszGridMappingValue,
 /*                           FetchStandardParallels()                   */
 /************************************************************************/
 
-char** netCDFDataset::FetchStandardParallels( const char *pszGridMappingValue )
+char **netCDFDataset::FetchStandardParallels( const char *pszGridMappingValue )
 {
-    char         szTemp[256 ];
-    //cf-1.0 tags
-    snprintf(szTemp, sizeof(szTemp), "%s#%s", pszGridMappingValue, CF_PP_STD_PARALLEL);
-    const char *pszValue = CSLFetchNameValue( papszMetadata, szTemp );
+    char szTemp[256] = {};
+    // cf-1.0 tags
+    snprintf(szTemp, sizeof(szTemp), "%s#%s", pszGridMappingValue,
+             CF_PP_STD_PARALLEL);
+    const char *pszValue = CSLFetchNameValue(papszMetadata, szTemp);
 
     char **papszValues = NULL;
-    if( pszValue != NULL ) {
-        papszValues = NCDFTokenizeArray( pszValue );
+    if( pszValue != NULL )
+    {
+        papszValues = NCDFTokenizeArray(pszValue);
     }
-    //try gdal tags
+    // Try gdal tags.
     else
     {
-        snprintf(szTemp, sizeof(szTemp), "%s#%s", pszGridMappingValue, CF_PP_STD_PARALLEL_1);
+        snprintf(szTemp, sizeof(szTemp),
+                 "%s#%s", pszGridMappingValue, CF_PP_STD_PARALLEL_1);
 
-        pszValue = CSLFetchNameValue( papszMetadata, szTemp );
+        pszValue = CSLFetchNameValue(papszMetadata, szTemp);
 
-        if ( pszValue != NULL )
-            papszValues = CSLAddString( papszValues, pszValue );
+        if( pszValue != NULL )
+            papszValues = CSLAddString(papszValues, pszValue);
 
-        snprintf(szTemp, sizeof(szTemp), "%s#%s", pszGridMappingValue, CF_PP_STD_PARALLEL_2);
+        snprintf(szTemp, sizeof(szTemp),
+                 "%s#%s", pszGridMappingValue, CF_PP_STD_PARALLEL_2);
 
-        pszValue = CSLFetchNameValue( papszMetadata, szTemp );
+        pszValue = CSLFetchNameValue(papszMetadata, szTemp);
 
         if( pszValue != NULL )
-            papszValues = CSLAddString( papszValues, pszValue );
+            papszValues = CSLAddString(papszValues, pszValue);
     }
 
     return papszValues;
@@ -1928,1380 +2011,1415 @@ char** netCDFDataset::FetchStandardParallels( const char *pszGridMappingValue )
 /************************************************************************/
 void netCDFDataset::SetProjectionFromVar( int nVarId, bool bReadSRSOnly )
 {
-    double       dfStdP1=0.0;
-    double       dfStdP2=0.0;
-    double       dfCenterLat=0.0;
-    double       dfCenterLon=0.0;
-    double       dfScale=1.0;
-    double       dfFalseEasting=0.0;
-    double       dfFalseNorthing=0.0;
-    double       dfCentralMeridian=0.0;
-    double       dfEarthRadius=0.0;
-    double       dfInverseFlattening=0.0;
-    double       dfLonPrimeMeridian=0.0;
-    const char   *pszPMName=NULL;
-    double       dfSemiMajorAxis=0.0;
-    double       dfSemiMinorAxis=0.0;
-
-    bool         bGotGeogCS = false;
-    bool         bGotCfSRS = false;
-    bool         bGotGdalSRS = false;
-    bool         bGotCfGT = false;
-    bool         bGotGdalGT = false;
-
-    /* These values from CF metadata */
+    bool bGotGeogCS = false;
+    bool bGotCfSRS = false;
+    bool bGotGdalSRS = false;
+    bool bGotCfGT = false;
+    bool bGotGdalGT = false;
+
+    // These values from CF metadata.
     OGRSpatialReference oSRS;
-    double       *pdfXCoord = NULL;
-    double       *pdfYCoord = NULL;
-    char         szDimNameX[ NC_MAX_NAME+1 ];
-    //char         szDimNameY[ NC_MAX_NAME+1 ];
-    int          nSpacingBegin=0;
-    int          nSpacingMiddle=0;
-    int          nSpacingLast=0;
-    bool         bLatSpacingOK=false;
-    bool         bLonSpacingOK=false;
-    size_t       xdim = nRasterXSize;
-    size_t       ydim = nRasterYSize;
-
-    const char  *pszUnits = NULL;
-
-    /* These values from GDAL metadata */
+    double *pdfXCoord = NULL;
+    double *pdfYCoord = NULL;
+    char szDimNameX[NC_MAX_NAME + 1];
+    // char szDimNameY[NC_MAX_NAME + 1];
+    size_t xdim = nRasterXSize;
+    size_t ydim = nRasterYSize;
+
+    // These values from GDAL metadata.
     const char *pszWKT = NULL;
     const char *pszGeoTransform = NULL;
 
-    netCDFDataset * poDS = this; /* perhaps this should be removed for clarity */
+    netCDFDataset *poDS = this;  // Perhaps this should be removed for clarity.
 
-    CPLDebug( "GDAL_netCDF", "\n=====\nSetProjectionFromVar( %d )\n", nVarId );
+    CPLDebug("GDAL_netCDF", "\n=====\nSetProjectionFromVar( %d)", nVarId);
 
-/* -------------------------------------------------------------------- */
-/*      Get x/y range information.                                      */
-/* -------------------------------------------------------------------- */
+    // Get x/y range information.
 
-    /* temp variables to use in SetGeoTransform() and SetProjection() */
-    double adfTempGeoTransform[6] = {0.0, 1.0, 0.0, 0.0, 0.0, 1.0};
+    // Temp variables to use in SetGeoTransform() and SetProjection().
+    double adfTempGeoTransform[6] = { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 };
 
     char *pszTempProjection = NULL;
 
-    if ( !bReadSRSOnly && (xdim == 1 || ydim == 1) ) {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "1-pixel width/height files not supported, xdim: %ld ydim: %ld",
-                  (long)xdim, (long)ydim );
+    if( !bReadSRSOnly && (xdim == 1 || ydim == 1) )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "1-pixel width/height files not supported, "
+                 "xdim: %ld ydim: %ld",
+                 static_cast<long>(xdim), static_cast<long>(ydim));
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Look for grid_mapping metadata                                  */
-/* -------------------------------------------------------------------- */
+    // Look for grid_mapping metadata.
 
-    char szGridMappingName[ NC_MAX_NAME+1 ];
-    strcpy( szGridMappingName, "" );
+    char szGridMappingName[NC_MAX_NAME + 1];
+    strcpy(szGridMappingName, "");
 
-    char szGridMappingValue[ NC_MAX_NAME+1 ];
-    strcpy( szGridMappingValue, "" );
+    char szGridMappingValue[NC_MAX_NAME + 1];
+    strcpy(szGridMappingValue, "");
 
-    char szVarName[ NC_MAX_NAME+1 ];
+    char szVarName[NC_MAX_NAME + 1];
     szVarName[0] = '\0';
     {
-    int status = nc_inq_varname( cdfid, nVarId, szVarName );
-    NCDF_ERR(status);
+        int status = nc_inq_varname(cdfid, nVarId, szVarName);
+        NCDF_ERR(status);
     }
-    char szTemp[ NC_MAX_NAME+1 ];
-    snprintf(szTemp,sizeof(szTemp), "%s#%s", szVarName,CF_GRD_MAPPING);
+    char szTemp[NC_MAX_NAME + 1];
+    snprintf(szTemp, sizeof(szTemp), "%s#%s", szVarName, CF_GRD_MAPPING);
 
     const char *pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
-    if( pszValue ) {
-        snprintf(szGridMappingName,sizeof(szGridMappingName), "%s", szTemp);
-        snprintf(szGridMappingValue,sizeof(szGridMappingValue), "%s", pszValue);
+    if( pszValue )
+    {
+        snprintf(szGridMappingName, sizeof(szGridMappingName), "%s", szTemp);
+        snprintf(szGridMappingValue, sizeof(szGridMappingValue),
+                 "%s", pszValue);
     }
 
-    if( !EQUAL( szGridMappingValue, "" )  ) {
-
-        /*  Read grid_mapping metadata */
+    if( !EQUAL(szGridMappingValue, "") )
+    {
+        // Read grid_mapping metadata.
         int nVarProjectionID = -1;
-        nc_inq_varid( cdfid, szGridMappingValue, &nVarProjectionID );
-        poDS->ReadAttributes( cdfid, nVarProjectionID );
+        nc_inq_varid(cdfid, szGridMappingValue, &nVarProjectionID);
+        poDS->ReadAttributes(cdfid, nVarProjectionID);
 
-/* -------------------------------------------------------------------- */
-/*      Look for GDAL spatial_ref and GeoTransform within grid_mapping  */
-/* -------------------------------------------------------------------- */
-        CPLDebug( "GDAL_netCDF", "got grid_mapping %s", szGridMappingValue );
-        snprintf(szTemp,sizeof(szTemp), "%s#%s", szGridMappingValue,NCDF_SPATIAL_REF);
+        // Look for GDAL spatial_ref and GeoTransform within grid_mapping.
+        CPLDebug("GDAL_netCDF", "got grid_mapping %s", szGridMappingValue);
+        snprintf(szTemp, sizeof(szTemp),
+                 "%s#%s", szGridMappingValue, NCDF_SPATIAL_REF);
 
         pszWKT = CSLFetchNameValue(poDS->papszMetadata, szTemp);
 
-        if( pszWKT != NULL ) {
-            snprintf(szTemp,sizeof(szTemp), "%s#%s", szGridMappingValue,NCDF_GEOTRANSFORM);
+        if( pszWKT != NULL )
+        {
+            snprintf(szTemp, sizeof(szTemp),
+                     "%s#%s", szGridMappingValue, NCDF_GEOTRANSFORM);
             pszGeoTransform = CSLFetchNameValue(poDS->papszMetadata, szTemp);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Get information about the file.                                 */
-/* -------------------------------------------------------------------- */
-/*      Was this file created by the GDAL netcdf driver?                */
-/*      Was this file created by the newer (CF-conformant) driver?      */
-/* -------------------------------------------------------------------- */
-/* 1) If GDAL netcdf metadata is set, and version >= 1.9,               */
-/*    it was created with the new driver                                */
-/* 2) Else, if spatial_ref and GeoTransform are present in the          */
-/*    grid_mapping variable, it was created by the old driver           */
-/* -------------------------------------------------------------------- */
+    // Get information about the file.
+    //
+    // Was this file created by the GDAL netcdf driver?
+    // Was this file created by the newer (CF-conformant) driver?
+    //
+    // 1) If GDAL netcdf metadata is set, and version >= 1.9,
+    //    it was created with the new driver
+    // 2) Else, if spatial_ref and GeoTransform are present in the
+    //    grid_mapping variable, it was created by the old driver
     pszValue = CSLFetchNameValue(poDS->papszMetadata, "NC_GLOBAL#GDAL");
 
-    if( pszValue && NCDFIsGDALVersionGTE(pszValue, 1900)) {
+    if( pszValue && NCDFIsGDALVersionGTE(pszValue, 1900))
+    {
         bIsGdalFile = true;
         bIsGdalCfFile = true;
     }
-    else  if( pszWKT != NULL && pszGeoTransform != NULL ) {
+    else if( pszWKT != NULL && pszGeoTransform != NULL )
+    {
         bIsGdalFile = true;
         bIsGdalCfFile = false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set default bottom-up default value                             */
-/*      Y axis dimension and absence of GT can modify this value        */
-/*      Override with Config option GDAL_NETCDF_BOTTOMUP                */
-/* -------------------------------------------------------------------- */
-   /* new driver is bottom-up by default */
-   if ( bIsGdalFile && ! bIsGdalCfFile )
-       poDS->bBottomUp = false;
-   else
-       poDS->bBottomUp = true;
+    // Set default bottom-up default value.
+    // Y axis dimension and absence of GT can modify this value.
+    // Override with Config option GDAL_NETCDF_BOTTOMUP.
 
-    CPLDebug( "GDAL_netCDF",
-              "bIsGdalFile=%d bIsGdalCfFile=%d bBottomUp=%d",
-              static_cast<int>(bIsGdalFile), static_cast<int>(bIsGdalCfFile),
-              static_cast<int>(bBottomUp) );
+    // New driver is bottom-up by default.
+    if( bIsGdalFile && !bIsGdalCfFile )
+        poDS->bBottomUp = false;
+    else
+        poDS->bBottomUp = true;
+
+    CPLDebug("GDAL_netCDF", "bIsGdalFile=%d bIsGdalCfFile=%d bBottomUp=%d",
+             static_cast<int>(bIsGdalFile), static_cast<int>(bIsGdalCfFile),
+             static_cast<int>(bBottomUp));
 
-/* -------------------------------------------------------------------- */
-/*      Look for dimension: lon                                         */
-/* -------------------------------------------------------------------- */
+    // Look for dimension: lon.
 
-    memset( szDimNameX, '\0', sizeof(szDimNameX) );
-    //memset( szDimNameY, '\0', sizeof(szDimNameY) );
+    memset(szDimNameX, '\0', sizeof(szDimNameX));
+    // memset(szDimNameY, '\0', sizeof(szDimNameY));
 
     if( !bReadSRSOnly )
     {
-        for( unsigned int i = 0; (i < strlen( poDS->papszDimName[ poDS->nXDimID ] )
-                                && i < 3 ); i++ ) {
-            szDimNameX[i]=(char)tolower( ( poDS->papszDimName[poDS->nXDimID] )[i] );
+        for( unsigned int i = 0;
+             i < strlen(poDS->papszDimName[poDS->nXDimID]) && i < 3;
+             i++ )
+        {
+            szDimNameX[i] =
+                (char)tolower((poDS->papszDimName[poDS->nXDimID])[i]);
         }
         szDimNameX[3] = '\0';
-        /*for( unsigned int i = 0; (i < strlen( poDS->papszDimName[ poDS->nYDimID ] )
-                                && i < 3 ); i++ ) {
-            szDimNameY[i]=(char)tolower( ( poDS->papszDimName[poDS->nYDimID] )[i] );
-        }
-        szDimNameY[3] = '\0';*/
+        // for( unsigned int i = 0;
+        //      (i < strlen(poDS->papszDimName[poDS->nYDimID])
+        //                        && i < 3 ); i++ ) {
+        //    szDimNameY[i]=(char)tolower((poDS->papszDimName[poDS->nYDimID])[i]);
+        // }
+        // szDimNameY[3] = '\0';
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read grid_mapping information and set projections               */
-/* -------------------------------------------------------------------- */
+    // Read grid_mapping information and set projections.
 
-    if( !( EQUAL(szGridMappingName,"" ) ) ) {
+    if( !EQUAL(szGridMappingName, "") )
+    {
 
-        snprintf(szTemp,sizeof(szTemp), "%s#%s", szGridMappingValue,CF_GRD_MAPPING_NAME);
+        snprintf(szTemp, sizeof(szTemp),
+                 "%s#%s", szGridMappingValue, CF_GRD_MAPPING_NAME);
         pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
 
-        if( pszValue != NULL ) {
-
-/* -------------------------------------------------------------------- */
-/*      Check for datum/spheroid information                            */
-/* -------------------------------------------------------------------- */
-            dfEarthRadius =
-                poDS->FetchCopyParm( szGridMappingValue,
-                                     CF_PP_EARTH_RADIUS,
-                                     -1.0 );
-
-            dfLonPrimeMeridian =
-                poDS->FetchCopyParm( szGridMappingValue,
-                                     CF_PP_LONG_PRIME_MERIDIAN,
-                                     0.0 );
-            // should try to find PM name from its value if not Greenwich
-            if ( ! CPLIsEqual(dfLonPrimeMeridian,0.0) )
+        if( pszValue != NULL )
+        {
+            // Check for datum/spheroid information.
+            double dfEarthRadius = poDS->FetchCopyParm(
+                szGridMappingValue, CF_PP_EARTH_RADIUS, -1.0);
+
+            const double dfLonPrimeMeridian = poDS->FetchCopyParm(
+                szGridMappingValue, CF_PP_LONG_PRIME_MERIDIAN, 0.0);
+
+            const char *pszPMName = NULL;
+
+            // Should try to find PM name from its value if not Greenwich.
+            if( !CPLIsEqual(dfLonPrimeMeridian, 0.0) )
                 pszPMName = "unknown";
 
-            dfInverseFlattening =
-                poDS->FetchCopyParm( szGridMappingValue,
-                                     CF_PP_INVERSE_FLATTENING,
-                                     -1.0 );
+            double dfInverseFlattening = poDS->FetchCopyParm(
+                szGridMappingValue, CF_PP_INVERSE_FLATTENING, -1.0);
 
-            dfSemiMajorAxis =
-                poDS->FetchCopyParm( szGridMappingValue,
-                                     CF_PP_SEMI_MAJOR_AXIS,
-                                     -1.0 );
+            double dfSemiMajorAxis = poDS->FetchCopyParm(
+                szGridMappingValue, CF_PP_SEMI_MAJOR_AXIS, -1.0);
 
-            dfSemiMinorAxis =
-                poDS->FetchCopyParm( szGridMappingValue,
-                                     CF_PP_SEMI_MINOR_AXIS,
-                                     -1.0 );
+            const double dfSemiMinorAxis = poDS->FetchCopyParm(
+                szGridMappingValue, CF_PP_SEMI_MINOR_AXIS, -1.0);
 
-            //see if semi-major exists if radius doesn't
+            // See if semi-major exists if radius doesn't.
             if( dfEarthRadius < 0.0 )
                 dfEarthRadius = dfSemiMajorAxis;
 
-            //if still no radius, check old tag
+            // If still no radius, check old tag.
             if( dfEarthRadius < 0.0 )
-                dfEarthRadius = poDS->FetchCopyParm( szGridMappingValue,
-                                                     CF_PP_EARTH_RADIUS_OLD,
-                                                     -1.0 );
-
-            //has radius value
-            if( dfEarthRadius > 0.0 ) {
-                //check for inv_flat tag
-                if( dfInverseFlattening < 0.0 ) {
-                    //no inv_flat tag, check for semi_minor
-                    if( dfSemiMinorAxis < 0.0 ) {
-                        //no way to get inv_flat, use sphere
-                        oSRS.SetGeogCS( "unknown",
+                dfEarthRadius = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_EARTH_RADIUS_OLD, -1.0);
+
+            // Has radius value.
+            if( dfEarthRadius > 0.0 )
+            {
+                // Check for inv_flat tag.
+                if( dfInverseFlattening < 0.0 )
+                {
+                    // No inv_flat tag, check for semi_minor.
+                    if( dfSemiMinorAxis < 0.0 )
+                    {
+                        // No way to get inv_flat, use sphere.
+                        oSRS.SetGeogCS("unknown",
                                         NULL,
                                         "Sphere",
                                         dfEarthRadius, 0.0,
-                                        pszPMName, dfLonPrimeMeridian );
+                                        pszPMName, dfLonPrimeMeridian);
                         bGotGeogCS = true;
                     }
-                    else {
+                    else
+                    {
                         if( dfSemiMajorAxis < 0.0 )
                             dfSemiMajorAxis = dfEarthRadius;
                         //set inv_flat using semi_minor/major
                         dfInverseFlattening = OSRCalcInvFlattening(dfSemiMajorAxis, dfSemiMinorAxis);
 
-                        oSRS.SetGeogCS( "unknown",
+                        oSRS.SetGeogCS("unknown",
                                         NULL,
                                         "Spheroid",
                                         dfEarthRadius, dfInverseFlattening,
-                                        pszPMName, dfLonPrimeMeridian );
+                                        pszPMName, dfLonPrimeMeridian);
                         bGotGeogCS = true;
                     }
                 }
-                else {
-                    oSRS.SetGeogCS( "unknown",
+                else
+                {
+                    oSRS.SetGeogCS("unknown",
                                     NULL,
                                     "Spheroid",
                                     dfEarthRadius, dfInverseFlattening,
-                                        pszPMName, dfLonPrimeMeridian );
+                                        pszPMName, dfLonPrimeMeridian);
                     bGotGeogCS = true;
                 }
 
-                if ( bGotGeogCS )
-                    CPLDebug( "GDAL_netCDF", "got spheroid from CF: (%f , %f)", dfEarthRadius, dfInverseFlattening );
-
+                if( bGotGeogCS )
+                    CPLDebug("GDAL_netCDF", "got spheroid from CF: (%f , %f)",
+                             dfEarthRadius, dfInverseFlattening);
             }
-            //no radius, set as wgs84 as default?
-            else {
+            // no radius, set as wgs84 as default?
+            else
+            {
                 // This would be too indiscriminate.  But we should set
                 // it if we know the data is geographic.
-                // oSRS.SetWellKnownGeogCS( "WGS84" );
+                // oSRS.SetWellKnownGeogCS("WGS84");
             }
 
-/* -------------------------------------------------------------------- */
-/*      Transverse Mercator                                             */
-/* -------------------------------------------------------------------- */
-
-            if( EQUAL( pszValue, CF_PT_TM ) ) {
+            // Transverse Mercator.
+            double dfCenterLat = 0.0;
+            double dfCenterLon = 0.0;
+            double dfScale = 1.0;
+            double dfFalseEasting = 0.0;
+            double dfFalseNorthing = 0.0;
 
-                dfScale =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_SCALE_FACTOR_MERIDIAN, 1.0 );
+            if( EQUAL(pszValue, CF_PT_TM) )
+            {
+                dfScale = poDS->FetchCopyParm(szGridMappingValue,
+                                              CF_PP_SCALE_FACTOR_MERIDIAN, 1.0);
 
-                dfCenterLon =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
+                dfCenterLon = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_LONG_CENTRAL_MERIDIAN, 0.0);
 
-                dfCenterLat =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+                dfCenterLat = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LAT_PROJ_ORIGIN, 0.0);
 
-                dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                dfFalseEasting = poDS->FetchCopyParm(szGridMappingValue,
+                                                     CF_PP_FALSE_EASTING, 0.0);
 
-                dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                dfFalseNorthing = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
                 bGotCfSRS = true;
-                oSRS.SetTM( dfCenterLat,
-                            dfCenterLon,
-                            dfScale,
-                            dfFalseEasting,
-                            dfFalseNorthing );
+                oSRS.SetTM(dfCenterLat,
+                           dfCenterLon,
+                           dfScale,
+                           dfFalseEasting,
+                           dfFalseNorthing);
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
             }
 
-/* -------------------------------------------------------------------- */
-/*      Albers Equal Area                                               */
-/* -------------------------------------------------------------------- */
-
-            if( EQUAL( pszValue, CF_PT_AEA ) ) {
+            // Albers Equal Area.
+            double dfStdP1 = 0.0;
+            double dfStdP2 = 0.0;
 
+            if( EQUAL(pszValue, CF_PT_AEA) )
+            {
                 char **papszStdParallels = NULL;
 
                 dfCenterLon =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
+                    poDS->FetchCopyParm(szGridMappingValue,
+                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0);
 
                 dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                    poDS->FetchCopyParm(szGridMappingValue,
+                                         CF_PP_FALSE_EASTING, 0.0);
 
                 dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                    poDS->FetchCopyParm(szGridMappingValue,
+                                         CF_PP_FALSE_NORTHING, 0.0);
 
                 papszStdParallels =
-                    FetchStandardParallels( szGridMappingValue );
-
-                if( papszStdParallels != NULL ) {
+                    FetchStandardParallels(szGridMappingValue);
 
-                    if ( CSLCount( papszStdParallels ) == 1 ) {
-                        /* TODO CF-1 standard says it allows AEA to be encoded with only 1 standard parallel */
-                        /* how should this actually map to a 2StdP OGC WKT version? */
-                        CPLError( CE_Warning, CPLE_NotSupported,
-                                  "NetCDF driver import of AEA-1SP is not tested, using identical std. parallels\n" );
-                        dfStdP1 = CPLAtofM( papszStdParallels[0] );
+                if( papszStdParallels != NULL )
+                {
+                    if( CSLCount(papszStdParallels) == 1 )
+                    {
+                        // TODO CF-1 standard says it allows AEA to be encoded
+                        // with only 1 standard parallel.  How should this
+                        // actually map to a 2StdP OGC WKT version?
+                        CPLError(
+                            CE_Warning, CPLE_NotSupported,
+                            "NetCDF driver import of AEA-1SP is not tested, "
+                            "using identical std. parallels.");
+                        dfStdP1 = CPLAtofM(papszStdParallels[0]);
                         dfStdP2 = dfStdP1;
-
                     }
-                    else if( CSLCount( papszStdParallels ) == 2 ) {
-                        dfStdP1 = CPLAtofM( papszStdParallels[0] );
-                        dfStdP2 = CPLAtofM( papszStdParallels[1] );
+                    else if( CSLCount(papszStdParallels) == 2 )
+                    {
+                        dfStdP1 = CPLAtofM(papszStdParallels[0]);
+                        dfStdP2 = CPLAtofM(papszStdParallels[1]);
                     }
                 }
-                //old default
-                else {
+                // Old default.
+                else
+                {
                     dfStdP1 =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_STD_PARALLEL_1, 0.0 );
+                        poDS->FetchCopyParm(szGridMappingValue,
+                                             CF_PP_STD_PARALLEL_1, 0.0);
 
                     dfStdP2 =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_STD_PARALLEL_2, 0.0 );
+                        poDS->FetchCopyParm(szGridMappingValue,
+                                             CF_PP_STD_PARALLEL_2, 0.0);
                 }
 
                 dfCenterLat =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+                    poDS->FetchCopyParm(szGridMappingValue,
+                                         CF_PP_LAT_PROJ_ORIGIN, 0.0);
 
                 bGotCfSRS = true;
-                oSRS.SetACEA( dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
-                              dfFalseEasting, dfFalseNorthing );
+                oSRS.SetACEA(dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
+                             dfFalseEasting, dfFalseNorthing);
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
 
-                CSLDestroy( papszStdParallels );
+                CSLDestroy(papszStdParallels);
             }
 
-/* -------------------------------------------------------------------- */
-/*      Cylindrical Equal Area                                          */
-/* -------------------------------------------------------------------- */
-
-            else if( EQUAL( pszValue, CF_PT_CEA ) || EQUAL( pszValue, CF_PT_LCEA ) ) {
-
-                char **papszStdParallels = NULL;
-
-                papszStdParallels =
-                    FetchStandardParallels( szGridMappingValue );
+            // Cylindrical Equal Area
+            else if( EQUAL(pszValue, CF_PT_CEA) || EQUAL(pszValue, CF_PT_LCEA) )
+            {
+                char **papszStdParallels =
+                    FetchStandardParallels(szGridMappingValue);
 
-                if( papszStdParallels != NULL ) {
-                    dfStdP1 = CPLAtofM( papszStdParallels[0] );
+                if( papszStdParallels != NULL )
+                {
+                    dfStdP1 = CPLAtofM(papszStdParallels[0]);
                 }
-                else {
-                    //TODO: add support for 'scale_factor_at_projection_origin' variant to standard parallel
-                    //Probably then need to calc a std parallel equivalent
-                    CPLError( CE_Failure, CPLE_NotSupported,
-                              "NetCDF driver does not support import of CF-1 LCEA "
-                              "'scale_factor_at_projection_origin' variant yet.\n" );
+                else
+                {
+                    // TODO: Add support for 'scale_factor_at_projection_origin'
+                    // variant to standard parallel.  Probably then need to calc
+                    // a std parallel equivalent.
+                    CPLError(
+                        CE_Failure, CPLE_NotSupported,
+                        "NetCDF driver does not support import of CF-1 LCEA "
+                        "'scale_factor_at_projection_origin' variant yet.");
                 }
 
-                dfCentralMeridian =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
+                const double dfCentralMeridian = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_LONG_CENTRAL_MERIDIAN, 0.0);
 
-                dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                dfFalseEasting = poDS->FetchCopyParm(szGridMappingValue,
+                                                     CF_PP_FALSE_EASTING, 0.0);
 
-                dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                dfFalseNorthing = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
                 bGotCfSRS = true;
-                oSRS.SetCEA( dfStdP1, dfCentralMeridian,
-                             dfFalseEasting, dfFalseNorthing );
+                oSRS.SetCEA(dfStdP1, dfCentralMeridian,
+                             dfFalseEasting, dfFalseNorthing);
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
 
-                CSLDestroy( papszStdParallels );
+                CSLDestroy(papszStdParallels);
             }
 
-/* -------------------------------------------------------------------- */
-/*      lambert_azimuthal_equal_area                                    */
-/* -------------------------------------------------------------------- */
-            else if( EQUAL( pszValue, CF_PT_LAEA ) ) {
-                dfCenterLon =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
-
-                dfCenterLat =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+            // lambert_azimuthal_equal_area.
+            else if( EQUAL(pszValue, CF_PT_LAEA) )
+            {
+                dfCenterLon = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LON_PROJ_ORIGIN, 0.0);
 
-                dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                dfCenterLat = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LAT_PROJ_ORIGIN, 0.0);
 
-                dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                dfFalseEasting = poDS->FetchCopyParm(szGridMappingValue,
+                                                     CF_PP_FALSE_EASTING, 0.0);
 
-                oSRS.SetProjCS( "LAEA (WGS84) " );
+                dfFalseNorthing = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
                 bGotCfSRS = true;
-                oSRS.SetLAEA( dfCenterLat, dfCenterLon,
-                              dfFalseEasting, dfFalseNorthing );
+                oSRS.SetLAEA(dfCenterLat, dfCenterLon,
+                              dfFalseEasting, dfFalseNorthing);
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
+
+                if( oSRS.GetAttrValue("DATUM") != NULL &&
+                    EQUAL(oSRS.GetAttrValue("DATUM"), "WGS_1984") )
+                {
+                    oSRS.SetProjCS("LAEA (WGS84)");
+                }
             }
 
-/* -------------------------------------------------------------------- */
-/*      Azimuthal Equidistant                                           */
-/* -------------------------------------------------------------------- */
-            else if( EQUAL( pszValue, CF_PT_AE ) ) {
-                dfCenterLon =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
+            // Azimuthal Equidistant.
+            else if( EQUAL(pszValue, CF_PT_AE) )
+            {
+                dfCenterLon = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LON_PROJ_ORIGIN, 0.0);
 
-                dfCenterLat =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+                dfCenterLat = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LAT_PROJ_ORIGIN, 0.0);
 
-                dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                dfFalseEasting = poDS->FetchCopyParm(szGridMappingValue,
+                                                     CF_PP_FALSE_EASTING, 0.0);
 
-                dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                dfFalseNorthing = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
                 bGotCfSRS = true;
                 oSRS.SetAE( dfCenterLat, dfCenterLon,
-                            dfFalseEasting, dfFalseNorthing );
+                            dfFalseEasting, dfFalseNorthing);
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
-
+                    oSRS.SetWellKnownGeogCS("WGS84");
             }
 
-/* -------------------------------------------------------------------- */
-/*      Lambert conformal conic                                         */
-/* -------------------------------------------------------------------- */
-            else if( EQUAL( pszValue, CF_PT_LCC ) ) {
-
+            // Lambert conformal conic.
+            else if( EQUAL(pszValue, CF_PT_LCC) )
+            {
                 char **papszStdParallels = NULL;
 
-                dfCenterLon =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LONG_CENTRAL_MERIDIAN, 0.0 );
-
-                dfCenterLat =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+                dfCenterLon = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_LONG_CENTRAL_MERIDIAN, 0.0);
 
-                dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                dfCenterLat = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LAT_PROJ_ORIGIN, 0.0);
 
-                dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                dfFalseEasting = poDS->FetchCopyParm(szGridMappingValue,
+                                                     CF_PP_FALSE_EASTING, 0.0);
 
-                papszStdParallels =
-                    FetchStandardParallels( szGridMappingValue );
-
-                /* 2SP variant */
-                if( CSLCount( papszStdParallels ) == 2 ) {
-                    dfStdP1 = CPLAtofM( papszStdParallels[0] );
-                    dfStdP2 = CPLAtofM( papszStdParallels[1] );
-                    oSRS.SetLCC( dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
-                                 dfFalseEasting, dfFalseNorthing );
-                }
-                /* 1SP variant (with standard_parallel or center lon) */
-                /* See comments in netcdfdataset.h for this projection. */
-                else {
+                dfFalseNorthing = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
-                    dfScale =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_SCALE_FACTOR_ORIGIN, -1.0 );
+                papszStdParallels = FetchStandardParallels(szGridMappingValue);
 
-                    /* CF definition, without scale factor */
-                    if( CPLIsEqual(dfScale, -1.0) ) {
+                // 2SP variant.
+                if( CSLCount(papszStdParallels) == 2 )
+                {
+                    dfStdP1 = CPLAtofM(papszStdParallels[0]);
+                    dfStdP2 = CPLAtofM(papszStdParallels[1]);
+                    oSRS.SetLCC(dfStdP1, dfStdP2, dfCenterLat, dfCenterLon,
+                                dfFalseEasting, dfFalseNorthing);
+                }
+                // 1SP variant (with standard_parallel or center lon).
+                // See comments in netcdfdataset.h for this projection.
+                else
+                {
+                    dfScale = poDS->FetchCopyParm(
+                        szGridMappingValue, CF_PP_SCALE_FACTOR_ORIGIN, -1.0);
 
-                        /* with standard_parallel */
-                        if( CSLCount( papszStdParallels ) == 1 )
-                            dfStdP1 = CPLAtofM( papszStdParallels[0] );
-                        /* with center lon instead */
+                    // CF definition, without scale factor.
+                    if( CPLIsEqual(dfScale, -1.0) )
+                    {
+                        // With standard_parallel.
+                        if( CSLCount(papszStdParallels) == 1 )
+                            dfStdP1 = CPLAtofM(papszStdParallels[0]);
+                        // With center lon instead.
                         else
                             dfStdP1 = dfCenterLat;
-                        /*dfStdP2 = dfStdP1;*/
-
-                        /* test if we should actually compute scale factor */
-                        if ( ! CPLIsEqual( dfStdP1, dfCenterLat ) ) {
-                            CPLError( CE_Warning, CPLE_NotSupported,
-                                      "NetCDF driver import of LCC-1SP with standard_parallel1 != latitude_of_projection_origin\n"
-                                      "(which forces a computation of scale_factor) is experimental (bug #3324)\n" );
-                            /* use Snyder eq. 15-4 to compute dfScale from dfStdP1 and dfCenterLat */
-                            /* only tested for dfStdP1=dfCenterLat and (25,26), needs more data for testing */
-                            /* other option: use the 2SP variant - how to compute new standard parallels? */
-                            dfScale = ( cos(dfStdP1) * pow( tan(M_PI/4 + dfStdP1/2), sin(dfStdP1) ) ) /
-                                ( cos(dfCenterLat) * pow( tan(M_PI/4 + dfCenterLat/2), sin(dfCenterLat) ) );
+                        // dfStdP2 = dfStdP1;
+
+                        // Test if we should actually compute scale factor.
+                        if( !CPLIsEqual(dfStdP1, dfCenterLat) )
+                        {
+                            CPLError(
+                                CE_Warning, CPLE_NotSupported,
+                                "NetCDF driver import of LCC-1SP with "
+                                "standard_parallel1 != "
+                                "latitude_of_projection_origin "
+                                "(which forces a computation of scale_factor) "
+                                "is experimental (bug #3324)");
+                            // Use Snyder eq. 15-4 to compute dfScale from
+                            // dfStdP1 and dfCenterLat.  Only tested for
+                            // dfStdP1=dfCenterLat and (25,26), needs more data
+                            // for testing.  Other option: use the 2SP variant -
+                            // how to compute new standard parallels?
+                            dfScale =
+                                (cos(dfStdP1) *
+                                 pow(tan(M_PI/4 + dfStdP1/2),
+                                     sin(dfStdP1))) /
+                                (cos(dfCenterLat) *
+                                 pow(tan(M_PI/4 + dfCenterLat/2),
+                                     sin(dfCenterLat)));
                         }
-                        /* default is 1.0 */
+                        // Default is 1.0.
                         else
+                        {
                             dfScale = 1.0;
+                        }
 
-                        oSRS.SetLCC1SP( dfCenterLat, dfCenterLon, dfScale,
-                                        dfFalseEasting, dfFalseNorthing );
-                        /* store dfStdP1 so we can output it to CF later */
-                        oSRS.SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
+                        oSRS.SetLCC1SP(dfCenterLat, dfCenterLon, dfScale,
+                                       dfFalseEasting, dfFalseNorthing);
+                        // Store dfStdP1 so we can output it to CF later.
+                        oSRS.SetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,
+                                             dfStdP1);
                     }
-                    /* OGC/PROJ.4 definition with scale factor */
-                    else {
-                        oSRS.SetLCC1SP( dfCenterLat, dfCenterLon, dfScale,
-                                        dfFalseEasting, dfFalseNorthing );
+                    // OGC/PROJ.4 definition with scale factor.
+                    else
+                    {
+                        oSRS.SetLCC1SP(dfCenterLat, dfCenterLon, dfScale,
+                                       dfFalseEasting, dfFalseNorthing);
                     }
                 }
 
                 bGotCfSRS = true;
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
 
-                CSLDestroy( papszStdParallels );
+                CSLDestroy(papszStdParallels);
             }
 
-/* -------------------------------------------------------------------- */
-/*      Is this Latitude/Longitude Grid explicitly                      */
-/* -------------------------------------------------------------------- */
+            // Is this Latitude/Longitude Grid explicitly?
 
-            else if ( EQUAL ( pszValue, CF_PT_LATITUDE_LONGITUDE ) ) {
+            else if( EQUAL(pszValue, CF_PT_LATITUDE_LONGITUDE) )
+            {
                 bGotCfSRS = true;
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
             }
-/* -------------------------------------------------------------------- */
-/*      Mercator                                                        */
-/* -------------------------------------------------------------------- */
 
-            else if ( EQUAL ( pszValue, CF_PT_MERCATOR ) ) {
+            // Mercator.
+            else if( EQUAL(pszValue, CF_PT_MERCATOR) )
+            {
 
                 char **papszStdParallels = NULL;
 
-                /* If there is a standard_parallel, know it is Mercator 2SP */
-                papszStdParallels =
-                    FetchStandardParallels( szGridMappingValue );
+                // If there is a standard_parallel, know it is Mercator 2SP.
+                papszStdParallels = FetchStandardParallels(szGridMappingValue);
 
-                if (NULL != papszStdParallels) {
-                    /* CF-1 Mercator 2SP always has lat centered at equator */
-                    dfStdP1 = CPLAtofM( papszStdParallels[0] );
+                if(NULL != papszStdParallels)
+                {
+                    // CF-1 Mercator 2SP always has lat centered at equator.
+                    dfStdP1 = CPLAtofM(papszStdParallels[0]);
 
                     dfCenterLat = 0.0;
 
-                    dfCenterLon =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_LON_PROJ_ORIGIN, 0.0 );
+                    dfCenterLon = poDS->FetchCopyParm(
+                        szGridMappingValue, CF_PP_LON_PROJ_ORIGIN, 0.0);
 
-                    dfFalseEasting =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_FALSE_EASTING, 0.0 );
+                    dfFalseEasting = poDS->FetchCopyParm(
+                        szGridMappingValue, CF_PP_FALSE_EASTING, 0.0);
 
-                    dfFalseNorthing =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_FALSE_NORTHING, 0.0 );
+                    dfFalseNorthing = poDS->FetchCopyParm(
+                        szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
-                    oSRS.SetMercator2SP( dfStdP1, dfCenterLat, dfCenterLon,
-                                      dfFalseEasting, dfFalseNorthing );
+                    oSRS.SetMercator2SP(dfStdP1, dfCenterLat, dfCenterLon,
+                                        dfFalseEasting, dfFalseNorthing);
                 }
-                else {
-                    dfCenterLon =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_LON_PROJ_ORIGIN, 0.0 );
-
-                    dfCenterLat =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_LAT_PROJ_ORIGIN, 0.0 );
-
-                    dfScale =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_SCALE_FACTOR_ORIGIN,
-                                             1.0 );
-
-                    dfFalseEasting =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_FALSE_EASTING, 0.0 );
-
-                    dfFalseNorthing =
-                        poDS->FetchCopyParm( szGridMappingValue,
-                                             CF_PP_FALSE_NORTHING, 0.0 );
-
-                    oSRS.SetMercator( dfCenterLat, dfCenterLon, dfScale,
-                                      dfFalseEasting, dfFalseNorthing );
+                else
+                {
+                    dfCenterLon = poDS->FetchCopyParm(
+                        szGridMappingValue, CF_PP_LON_PROJ_ORIGIN, 0.0);
+
+                    dfCenterLat = poDS->FetchCopyParm(
+                        szGridMappingValue, CF_PP_LAT_PROJ_ORIGIN, 0.0);
+
+                    dfScale = poDS->FetchCopyParm(
+                        szGridMappingValue, CF_PP_SCALE_FACTOR_ORIGIN, 1.0);
+
+                    dfFalseEasting = poDS->FetchCopyParm(
+                        szGridMappingValue, CF_PP_FALSE_EASTING, 0.0);
+
+                    dfFalseNorthing = poDS->FetchCopyParm(
+                        szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
+
+                    oSRS.SetMercator(dfCenterLat, dfCenterLon, dfScale,
+                                     dfFalseEasting, dfFalseNorthing);
                 }
 
                 bGotCfSRS = true;
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
 
-                CSLDestroy( papszStdParallels );
+                CSLDestroy(papszStdParallels);
             }
 
-/* -------------------------------------------------------------------- */
-/*      Orthographic                                                    */
-/* -------------------------------------------------------------------- */
-
-            else if ( EQUAL ( pszValue, CF_PT_ORTHOGRAPHIC ) ) {
-                dfCenterLon =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
+            // Orthographic.
+            else if( EQUAL (pszValue, CF_PT_ORTHOGRAPHIC) )
+            {
+                dfCenterLon = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LON_PROJ_ORIGIN, 0.0);
 
-                dfCenterLat =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+                dfCenterLat = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LAT_PROJ_ORIGIN, 0.0);
 
-                dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                dfFalseEasting = poDS->FetchCopyParm(szGridMappingValue,
+                                                     CF_PP_FALSE_EASTING, 0.0);
 
-                dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                dfFalseNorthing = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
                 bGotCfSRS = true;
 
-                oSRS.SetOrthographic( dfCenterLat, dfCenterLon,
-                                      dfFalseEasting, dfFalseNorthing );
+                oSRS.SetOrthographic(dfCenterLat, dfCenterLon,
+                                      dfFalseEasting, dfFalseNorthing);
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
             }
 
-/* -------------------------------------------------------------------- */
-/*      Polar Stereographic                                             */
-/* -------------------------------------------------------------------- */
-
-            else if ( EQUAL ( pszValue, CF_PT_POLAR_STEREO ) ) {
-
+            // Polar Stereographic.
+            else if( EQUAL(pszValue, CF_PT_POLAR_STEREO) )
+            {
                 char **papszStdParallels = NULL;
 
-                dfScale =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_SCALE_FACTOR_ORIGIN,
-                                         -1.0 );
+                dfScale = poDS->FetchCopyParm(szGridMappingValue,
+                                              CF_PP_SCALE_FACTOR_ORIGIN, -1.0);
 
-                papszStdParallels =
-                    FetchStandardParallels( szGridMappingValue );
-
-                /* CF allows the use of standard_parallel (lat_ts) OR scale_factor (k0),
-                   make sure we have standard_parallel, using Snyder eq. 22-7
-                   with k=1 and lat=standard_parallel */
-                if ( papszStdParallels != NULL ) {
-                    dfStdP1 = CPLAtofM( papszStdParallels[0] );
-                    /* compute scale_factor from standard_parallel */
-                    /* this creates WKT that is inconsistent, don't write for now
-                       also proj4 does not seem to use this parameter */
-                    // dfScale = ( 1.0 + fabs( sin( dfStdP1 * M_PI / 180.0 ) ) ) / 2.0;
+                papszStdParallels = FetchStandardParallels(szGridMappingValue);
+
+                // CF allows the use of standard_parallel (lat_ts) OR
+                // scale_factor (k0), make sure we have standard_parallel, using
+                // Snyder eq. 22-7 with k=1 and lat=standard_parallel.
+                if( papszStdParallels != NULL )
+                {
+                    dfStdP1 = CPLAtofM(papszStdParallels[0]);
+                    // Compute scale_factor from standard_parallel.
+                    // This creates WKT that is inconsistent, don't write for
+                    // now.  Also, proj4 does not seem to use this parameter.
+                    // dfScale =
+                    //     (1.0 + fabs(sin(dfStdP1 * M_PI / 180.0))) / 2.0;
                 }
-                else {
-                    if ( ! CPLIsEqual(dfScale,-1.0) ) {
-                        /* compute standard_parallel from scale_factor */
-                        dfStdP1 = asin( 2*dfScale - 1 ) * 180.0 / M_PI;
-
-                        /* fetch latitude_of_projection_origin (+90/-90)
-                           used here for the sign of standard_parallel */
-                        double dfLatProjOrigin =
-                            poDS->FetchCopyParm( szGridMappingValue,
-                                                 CF_PP_LAT_PROJ_ORIGIN,
-                                                 0.0 );
-                        if ( ! CPLIsEqual(dfLatProjOrigin,90.0)  &&
-                             ! CPLIsEqual(dfLatProjOrigin,-90.0) ) {
-                            CPLError( CE_Failure, CPLE_NotSupported,
-                                      "Polar Stereographic must have a %s parameter equal to +90 or -90\n.",
-                                      CF_PP_LAT_PROJ_ORIGIN );
+                else
+                {
+                    if( !CPLIsEqual(dfScale, -1.0) )
+                    {
+                        // Compute standard_parallel from scale_factor.
+                        dfStdP1 = asin(2 * dfScale - 1) * 180.0 / M_PI;
+
+                        // Fetch latitude_of_projection_origin (+90/-90).
+                        // Used here for the sign of standard_parallel.
+                        double dfLatProjOrigin = poDS->FetchCopyParm(
+                            szGridMappingValue, CF_PP_LAT_PROJ_ORIGIN, 0.0);
+                        if( !CPLIsEqual(dfLatProjOrigin, 90.0) &&
+                            !CPLIsEqual(dfLatProjOrigin, -90.0) )
+                        {
+                            CPLError(CE_Failure, CPLE_NotSupported,
+                                     "Polar Stereographic must have a %s "
+                                     "parameter equal to +90 or -90.",
+                                     CF_PP_LAT_PROJ_ORIGIN);
                             dfLatProjOrigin = 90.0;
                         }
-                        if ( CPLIsEqual(dfLatProjOrigin,-90.0) )
-                            dfStdP1 = - dfStdP1;
+                        if( CPLIsEqual(dfLatProjOrigin, -90.0) )
+                            dfStdP1 = -dfStdP1;
                     }
-                    else {
-                        dfStdP1 = 0.0; //just to avoid warning at compilation
-                        CPLError( CE_Failure, CPLE_NotSupported,
-                                  "The NetCDF driver does not support import of CF-1 Polar stereographic "
-                                  "without standard_parallel and scale_factor_at_projection_origin parameters.\n" );
+                    else
+                    {
+                        dfStdP1 = 0.0;  // Just to avoid warning at compilation.
+                        CPLError(
+                            CE_Failure, CPLE_NotSupported,
+                            "The NetCDF driver does not support import "
+                            "of CF-1 Polar stereographic "
+                            "without standard_parallel and "
+                            "scale_factor_at_projection_origin parameters.");
                     }
                 }
 
-                /* set scale to default value 1.0 if it was not set */
-                if ( CPLIsEqual(dfScale,-1.0) )
+                // Set scale to default value 1.0 if it was not set.
+                if( CPLIsEqual(dfScale, -1.0) )
                     dfScale = 1.0;
 
-                dfCenterLon =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_VERT_LONG_FROM_POLE, 0.0 );
+                dfCenterLon = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_VERT_LONG_FROM_POLE, 0.0);
 
-                dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                dfFalseEasting = poDS->FetchCopyParm(szGridMappingValue,
+                                                     CF_PP_FALSE_EASTING, 0.0);
 
-                dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                dfFalseNorthing = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
                 bGotCfSRS = true;
-                /* map CF CF_PP_STD_PARALLEL_1 to WKT SRS_PP_LATITUDE_OF_ORIGIN */
-                oSRS.SetPS( dfStdP1, dfCenterLon, dfScale,
-                            dfFalseEasting, dfFalseNorthing );
+                // Map CF CF_PP_STD_PARALLEL_1 to WKT SRS_PP_LATITUDE_OF_ORIGIN.
+                oSRS.SetPS(dfStdP1, dfCenterLon, dfScale,
+                            dfFalseEasting, dfFalseNorthing);
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
 
-                CSLDestroy( papszStdParallels );
+                CSLDestroy(papszStdParallels);
             }
 
-/* -------------------------------------------------------------------- */
-/*      Stereographic                                                   */
-/* -------------------------------------------------------------------- */
-
-            else if ( EQUAL ( pszValue, CF_PT_STEREO ) ) {
-
-                dfCenterLon =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
+            // Stereographic.
+            else if( EQUAL(pszValue, CF_PT_STEREO) )
+            {
+                dfCenterLon = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LON_PROJ_ORIGIN, 0.0);
 
-                dfCenterLat =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LAT_PROJ_ORIGIN, 0.0 );
+                dfCenterLat = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LAT_PROJ_ORIGIN, 0.0);
 
-                dfScale =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_SCALE_FACTOR_ORIGIN,
-                                         1.0 );
+                dfScale = poDS->FetchCopyParm(szGridMappingValue,
+                                              CF_PP_SCALE_FACTOR_ORIGIN, 1.0);
 
-                dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                dfFalseEasting = poDS->FetchCopyParm(szGridMappingValue,
+                                                     CF_PP_FALSE_EASTING, 0.0);
 
-                dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                dfFalseNorthing = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
                 bGotCfSRS = true;
-                oSRS.SetStereographic( dfCenterLat, dfCenterLon, dfScale,
-                                       dfFalseEasting, dfFalseNorthing );
+                oSRS.SetStereographic(dfCenterLat, dfCenterLon, dfScale,
+                                      dfFalseEasting, dfFalseNorthing);
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
             }
 
-/* -------------------------------------------------------------------- */
-/*      Geostationary                                                   */
-/* -------------------------------------------------------------------- */
-            else if( EQUAL( pszValue, CF_PT_GEOS ) ) {
-                dfCenterLon =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_LON_PROJ_ORIGIN, 0.0 );
+            // Geostationary.
+            else if( EQUAL(pszValue, CF_PT_GEOS) )
+            {
+                dfCenterLon = poDS->FetchCopyParm(szGridMappingValue,
+                                                  CF_PP_LON_PROJ_ORIGIN, 0.0);
 
                 double dfSatelliteHeight =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_PERSPECTIVE_POINT_HEIGHT, 35785831.0 );
+                    poDS->FetchCopyParm(szGridMappingValue,
+                                        CF_PP_PERSPECTIVE_POINT_HEIGHT, 35785831.0);
 
-                snprintf(szTemp, sizeof(szTemp), "%s#%s", szGridMappingValue, CF_PP_SWEEP_ANGLE_AXIS);
-                const char *pszSweepAxisAngle = CSLFetchNameValue(papszMetadata, szTemp);
+                snprintf(szTemp, sizeof(szTemp), "%s#%s", szGridMappingValue,
+                         CF_PP_SWEEP_ANGLE_AXIS);
+                const char *pszSweepAxisAngle =
+                    CSLFetchNameValue(papszMetadata, szTemp);
 
-                dfFalseEasting =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_EASTING, 0.0 );
+                dfFalseEasting = poDS->FetchCopyParm(szGridMappingValue,
+                                                     CF_PP_FALSE_EASTING, 0.0);
 
-                dfFalseNorthing =
-                    poDS->FetchCopyParm( szGridMappingValue,
-                                         CF_PP_FALSE_NORTHING, 0.0 );
+                dfFalseNorthing = poDS->FetchCopyParm(
+                    szGridMappingValue, CF_PP_FALSE_NORTHING, 0.0);
 
                 bGotCfSRS = true;
-                oSRS.SetGEOS( dfCenterLon, dfSatelliteHeight,
-                              dfFalseEasting, dfFalseNorthing );
+                oSRS.SetGEOS(dfCenterLon, dfSatelliteHeight,
+                              dfFalseEasting, dfFalseNorthing);
 
                 if( !bGotGeogCS )
-                    oSRS.SetWellKnownGeogCS( "WGS84" );
+                    oSRS.SetWellKnownGeogCS("WGS84");
 
                 if( pszSweepAxisAngle != NULL && EQUAL(pszSweepAxisAngle, "x") )
                 {
-                    char* pszProj4 = NULL;
+                    char *pszProj4 = NULL;
                     oSRS.exportToProj4(&pszProj4);
                     CPLString osProj4 = pszProj4;
                     osProj4 += " +sweep=x";
-                    oSRS.SetExtension( oSRS.GetRoot()->GetValue(), "PROJ4", osProj4 );
+                    oSRS.SetExtension(oSRS.GetRoot()->GetValue(),
+                                      "PROJ4", osProj4);
                     CPLFree(pszProj4);
                 }
-
             }
 
-/* -------------------------------------------------------------------- */
-/*      Is this Latitude/Longitude Grid, default                        */
-/* -------------------------------------------------------------------- */
-
-        } else if( EQUAL( szDimNameX, NCDF_DIMNAME_LON ) ) {
-            oSRS.SetWellKnownGeogCS( "WGS84" );
-
-        } else {
+        // Is this Latitude/Longitude Grid, default?
+        }
+        else if( EQUAL(szDimNameX, NCDF_DIMNAME_LON) )
+        {
+            oSRS.SetWellKnownGeogCS("WGS84");
+        }
+        else
+        {
             // This would be too indiscriminate.  But we should set
             // it if we know the data is geographic.
-            // oSRS.SetWellKnownGeogCS( "WGS84" );
+            // oSRS.SetWellKnownGeogCS("WGS84");
         }
     }
-/* -------------------------------------------------------------------- */
-/*      Read projection coordinates                                     */
-/* -------------------------------------------------------------------- */
+    // Read projection coordinates.
 
     int nVarDimXID = -1;
     int nVarDimYID = -1;
     if( !bReadSRSOnly )
     {
-        nc_inq_varid( cdfid, poDS->papszDimName[nXDimID], &nVarDimXID );
-        nc_inq_varid( cdfid, poDS->papszDimName[nYDimID], &nVarDimYID );
+        nc_inq_varid(cdfid, poDS->papszDimName[nXDimID], &nVarDimXID);
+        nc_inq_varid(cdfid, poDS->papszDimName[nYDimID], &nVarDimYID);
     }
 
-    size_t start[2], edge[2];
-    if( !bReadSRSOnly && ( nVarDimXID != -1 ) && ( nVarDimYID != -1 ) ) {
-        pdfXCoord = (double *) CPLCalloc( xdim, sizeof(double) );
-        pdfYCoord = (double *) CPLCalloc( ydim, sizeof(double) );
+    if( !bReadSRSOnly && (nVarDimXID != -1) && (nVarDimYID != -1) )
+    {
+        pdfXCoord = static_cast<double *>(CPLCalloc(xdim, sizeof(double)));
+        pdfYCoord = static_cast<double *>(CPLCalloc(ydim, sizeof(double)));
 
-        start[0] = 0;
-        edge[0]  = xdim;
-        int status = nc_get_vara_double( cdfid, nVarDimXID,
-                                     start, edge, pdfXCoord);
+        size_t start[2] = { 0, 0 };
+        size_t edge[2] = { xdim, 0 };
+        int status =
+            nc_get_vara_double(cdfid, nVarDimXID, start, edge, pdfXCoord);
         NCDF_ERR(status);
 
-        edge[0]  = ydim;
-        status = nc_get_vara_double( cdfid, nVarDimYID,
-                                     start, edge, pdfYCoord);
+        edge[0] = ydim;
+        status = nc_get_vara_double(cdfid, nVarDimYID, start, edge, pdfYCoord);
         NCDF_ERR(status);
 
-/* -------------------------------------------------------------------- */
-/*      Check for bottom-up from the Y-axis order                       */
-/*      see bugs #4284 and #4251                                        */
-/* -------------------------------------------------------------------- */
-
+        // Check for bottom-up from the Y-axis order.
+        // See bugs #4284 and #4251.
         poDS->bBottomUp = (pdfYCoord[0] <= pdfYCoord[1]);
 
-        CPLDebug( "GDAL_netCDF", "set bBottomUp = %d from Y axis",
-                  static_cast<int>(poDS->bBottomUp) );
-
-/* -------------------------------------------------------------------- */
-/*      convert ]180,360] longitude values to [-180,180]                */
-/* -------------------------------------------------------------------- */
+        CPLDebug("GDAL_netCDF", "set bBottomUp = %d from Y axis",
+                 static_cast<int>(poDS->bBottomUp));
 
-        if ( NCDFIsVarLongitude( cdfid, nVarDimXID, NULL ) &&
-             CPLTestBool(CPLGetConfigOption("GDAL_NETCDF_CENTERLONG_180", "YES"))) {
+        // Convert ]180,360] longitude values to [-180,180].
+        if( NCDFIsVarLongitude(cdfid, nVarDimXID, NULL) &&
+            CPLTestBool(CPLGetConfigOption("GDAL_NETCDF_CENTERLONG_180",
+                                           "YES")) )
+        {
             // If minimum longitude is > 180, subtract 360 from all.
-            if ( MIN( pdfXCoord[0], pdfXCoord[xdim-1] ) > 180.0 ) {
-                for ( size_t i=0; i<xdim ; i++ )
+            if( std::min(pdfXCoord[0], pdfXCoord[xdim - 1]) > 180.0 )
+            {
+                for( size_t i = 0; i < xdim; i++ )
                         pdfXCoord[i] -= 360;
             }
         }
 
-/* -------------------------------------------------------------------- */
-/*     Set Projection from CF                                           */
-/* -------------------------------------------------------------------- */
-    if ( bGotGeogCS || bGotCfSRS ) {
-        /* Set SRS Units */
-
-        /* check units for x and y */
-        if( oSRS.IsProjected( ) ) {
-            snprintf(szTemp,sizeof(szTemp), "%s#units", poDS->papszDimName[nXDimID]);
-            const char *pszUnitsX = CSLFetchNameValue( poDS->papszMetadata,
-                                          szTemp );
-
-            snprintf(szTemp,sizeof(szTemp), "%s#units", poDS->papszDimName[nYDimID]);
-            const char *pszUnitsY = CSLFetchNameValue( poDS->papszMetadata,
-                                          szTemp );
-
-            /* TODO: what to do if units are not equal in X and Y */
-            if ( (pszUnitsX != NULL) && (pszUnitsY != NULL) &&
-                 EQUAL(pszUnitsX,pszUnitsY) )
-                pszUnits = pszUnitsX;
-
-            /* add units to PROJCS */
-            if ( pszUnits != NULL && ! EQUAL(pszUnits,"") ) {
-                CPLDebug( "GDAL_netCDF",
-                          "units=%s", pszUnits );
-                if ( EQUAL(pszUnits,"m") ) {
-                    oSRS.SetLinearUnits( "metre", 1.0 );
-                    oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", 9001 );
-                }
-                else if ( EQUAL(pszUnits,"km") ) {
-                    oSRS.SetLinearUnits( "kilometre", 1000.0 );
-                    oSRS.SetAuthority( "PROJCS|UNIT", "EPSG", 9036 );
+        // Set Projection from CF.
+        if( bGotGeogCS || bGotCfSRS )
+        {
+            // Set SRS Units.
+
+            // Check units for x and y.
+            if( oSRS.IsProjected() )
+            {
+                snprintf(szTemp, sizeof(szTemp),
+                         "%s#units", poDS->papszDimName[nXDimID]);
+                const char *pszUnitsX =
+                    CSLFetchNameValue(poDS->papszMetadata, szTemp);
+
+                snprintf(szTemp, sizeof(szTemp),
+                         "%s#units", poDS->papszDimName[nYDimID]);
+                const char *pszUnitsY =
+                    CSLFetchNameValue(poDS->papszMetadata, szTemp);
+
+                const char *pszUnits = NULL;
+
+                // TODO: What to do if units are not equal in X and Y.
+                if( (pszUnitsX != NULL) && (pszUnitsY != NULL) &&
+                     EQUAL(pszUnitsX, pszUnitsY) )
+                    pszUnits = pszUnitsX;
+
+                // Add units to PROJCS.
+                if( pszUnits != NULL && !EQUAL(pszUnits, "") )
+                {
+                    CPLDebug("GDAL_netCDF", "units=%s", pszUnits);
+                    if( EQUAL(pszUnits, "m") )
+                    {
+                        oSRS.SetLinearUnits("metre", 1.0);
+                        oSRS.SetAuthority("PROJCS|UNIT", "EPSG", 9001);
+                    }
+                    else if( EQUAL(pszUnits, "km") )
+                    {
+                        oSRS.SetLinearUnits("kilometre", 1000.0);
+                        oSRS.SetAuthority("PROJCS|UNIT", "EPSG", 9036);
+                    }
+                    else if( EQUAL(pszUnits, "US_survey_foot") ||
+                             EQUAL(pszUnits, "US_survey_feet") )
+                    {
+                        oSRS.SetLinearUnits("US survey foot",
+                                            CPLAtof(SRS_UL_US_FOOT_CONV));
+                        oSRS.SetAuthority("PROJCS|UNIT", "EPSG", 9003);
+                    }
+                    // TODO: Check for other values.
+                    // else
+                    //     oSRS.SetLinearUnits(pszUnits, 1.0);
                 }
-                /* TODO check for other values */
-                // else
-                //     oSRS.SetLinearUnits(pszUnits, 1.0);
             }
-        }
-        else if ( oSRS.IsGeographic() ) {
-            oSRS.SetAngularUnits( CF_UNITS_D, CPLAtof(SRS_UA_DEGREE_CONV) );
-            oSRS.SetAuthority( "GEOGCS|UNIT", "EPSG", 9122 );
-        }
+            else if( oSRS.IsGeographic() )
+            {
+                oSRS.SetAngularUnits(CF_UNITS_D, CPLAtof(SRS_UA_DEGREE_CONV));
+                oSRS.SetAuthority("GEOGCS|UNIT", "EPSG", 9122);
+            }
 
-        /* Set Projection */
-        oSRS.exportToWkt( &(pszTempProjection) );
-        CPLDebug( "GDAL_netCDF", "setting WKT from CF" );
-        SetProjection( pszTempProjection );
-        CPLFree( pszTempProjection );
+            // Set projection.
+            oSRS.exportToWkt(&pszTempProjection);
+            CPLDebug("GDAL_netCDF", "setting WKT from CF");
+            SetProjection(pszTempProjection);
+            CPLFree(pszTempProjection);
 
-        if ( !bGotCfGT )
-            CPLDebug( "GDAL_netCDF", "got SRS but no geotransform from CF!");
-    }
+            if( !bGotCfGT )
+                CPLDebug("GDAL_netCDF", "got SRS but no geotransform from CF!");
+        }
+
+        // Is pixel spacing uniform across the map?
 
-/* -------------------------------------------------------------------- */
-/*      Is pixel spacing uniform across the map?                       */
-/* -------------------------------------------------------------------- */
+        // Check Longitude.
 
-/* -------------------------------------------------------------------- */
-/*      Check Longitude                                                 */
-/* -------------------------------------------------------------------- */
+        bool bLonSpacingOK = false;
+        int nSpacingBegin = 0;
+        int nSpacingMiddle = 0;
+        int nSpacingLast = 0;
 
-        if( xdim == 2 ) {
+        if( xdim == 2 )
+        {
             bLonSpacingOK = true;
         }
         else
         {
-            nSpacingBegin   = (int) poDS->rint((pdfXCoord[1] - pdfXCoord[0]) * 1000);
+            nSpacingBegin = static_cast<int>(
+                poDS->rint((pdfXCoord[1] - pdfXCoord[0]) * 1000));
 
-            nSpacingMiddle  = (int) poDS->rint((pdfXCoord[xdim/2+1] -
-                                                pdfXCoord[xdim/2]) * 1000);
+            nSpacingMiddle = static_cast<int>(poDS->rint(
+                (pdfXCoord[xdim / 2 + 1] - pdfXCoord[xdim / 2]) * 1000));
 
-            nSpacingLast    = (int) poDS->rint((pdfXCoord[xdim-1] -
-                                                pdfXCoord[xdim-2]) * 1000);
+            nSpacingLast = static_cast<int>(
+                poDS->rint((pdfXCoord[xdim - 1] - pdfXCoord[xdim - 2]) * 1000));
 
             CPLDebug("GDAL_netCDF",
-                     "xdim: %ld nSpacingBegin: %d nSpacingMiddle: %d nSpacingLast: %d",
-                     (long)xdim, nSpacingBegin, nSpacingMiddle, nSpacingLast );
+                     "xdim: %ld nSpacingBegin: %d nSpacingMiddle: %d "
+                     "nSpacingLast: %d",
+                     static_cast<long>(xdim),
+                     nSpacingBegin, nSpacingMiddle, nSpacingLast);
 #ifdef NCDF_DEBUG
             CPLDebug("GDAL_netCDF",
                      "xcoords: %f %f %f %f %f %f",
-                     pdfXCoord[0], pdfXCoord[1], pdfXCoord[xdim / 2], pdfXCoord[(xdim / 2) + 1],
-                     pdfXCoord[xdim - 2], pdfXCoord[xdim-1]);
+                     pdfXCoord[0], pdfXCoord[1],
+                     pdfXCoord[xdim / 2], pdfXCoord[(xdim / 2) + 1],
+                     pdfXCoord[xdim - 2], pdfXCoord[xdim - 1]);
 #endif
 
-            if( ( abs( abs( nSpacingBegin ) - abs( nSpacingLast ) )  <= 1   ) &&
-                ( abs( abs( nSpacingBegin ) - abs( nSpacingMiddle ) ) <= 1 ) &&
-                ( abs( abs( nSpacingMiddle ) - abs( nSpacingLast ) ) <= 1   ) ) {
+            if( (abs(abs(nSpacingBegin) - abs(nSpacingLast))  <= 1) &&
+                (abs(abs(nSpacingBegin) - abs(nSpacingMiddle)) <= 1) &&
+                (abs(abs(nSpacingMiddle) - abs(nSpacingLast)) <= 1) )
+            {
                 bLonSpacingOK = true;
             }
         }
 
-        if ( bLonSpacingOK == false ) {
-            CPLDebug( "GDAL_netCDF",
-                      "Longitude is not equally spaced." );
+        if( bLonSpacingOK == false )
+        {
+            CPLDebug("GDAL_netCDF", "Longitude is not equally spaced.");
         }
 
-/* -------------------------------------------------------------------- */
-/*      Check Latitude                                                  */
-/* -------------------------------------------------------------------- */
-        if( ydim == 2 ) {
+        // Check Latitude.
+        bool bLatSpacingOK = false;
+
+        if( ydim == 2 )
+        {
             bLatSpacingOK = true;
         }
         else
         {
-            nSpacingBegin   = (int) poDS->rint((pdfYCoord[1] - pdfYCoord[0]) *
-                                               1000);
+            nSpacingBegin = static_cast<int>(
+                poDS->rint((pdfYCoord[1] - pdfYCoord[0]) * 1000));
 
-            nSpacingMiddle  = (int) poDS->rint((pdfYCoord[ydim/2+1] -
-                                                pdfYCoord[ydim/2]) *
-                                               1000);
+            nSpacingMiddle = static_cast<int>(poDS->rint(
+                (pdfYCoord[ydim / 2 + 1] - pdfYCoord[ydim / 2]) * 1000));
 
-            nSpacingLast    = (int) poDS->rint((pdfYCoord[ydim-1] -
-                                                pdfYCoord[ydim-2]) *
-                                               1000);
+            nSpacingLast = static_cast<int>(
+                poDS->rint((pdfYCoord[ydim - 1] - pdfYCoord[ydim - 2]) * 1000));
 
             CPLDebug("GDAL_netCDF",
                      "ydim: %ld nSpacingBegin: %d nSpacingMiddle: %d nSpacingLast: %d",
-                     (long)ydim, nSpacingBegin, nSpacingMiddle, nSpacingLast );
+                     (long)ydim, nSpacingBegin, nSpacingMiddle, nSpacingLast);
 #ifdef NCDF_DEBUG
             CPLDebug("GDAL_netCDF",
                      "ycoords: %f %f %f %f %f %f",
                      pdfYCoord[0], pdfYCoord[1], pdfYCoord[ydim / 2], pdfYCoord[(ydim / 2) + 1],
-                     pdfYCoord[ydim - 2], pdfYCoord[ydim-1]);
+                     pdfYCoord[ydim - 2], pdfYCoord[ydim - 1]);
 #endif
 
-/* -------------------------------------------------------------------- */
-/*   For Latitude we allow an error of 0.1 degrees for gaussian         */
-/*   gridding (only if this is not a projected SRS)                     */
-/* -------------------------------------------------------------------- */
+            // For Latitude we allow an error of 0.1 degrees for gaussian
+            // gridding (only if this is not a projected SRS).
 
-            if( ( abs( abs( nSpacingBegin )  - abs( nSpacingLast ) )  <= 1   ) &&
-                ( abs( abs( nSpacingBegin )  - abs( nSpacingMiddle ) ) <= 1 ) &&
-                ( abs( abs( nSpacingMiddle ) - abs( nSpacingLast ) ) <= 1   ) ) {
+            if( (abs(abs(nSpacingBegin) - abs(nSpacingLast))  <= 1) &&
+                (abs(abs(nSpacingBegin) - abs(nSpacingMiddle)) <= 1) &&
+                (abs(abs(nSpacingMiddle) - abs(nSpacingLast)) <= 1) )
+            {
                 bLatSpacingOK = true;
             }
             else if( !oSRS.IsProjected() &&
-                     ( (( abs( abs(nSpacingBegin)  - abs(nSpacingLast) ) )   <= 100 ) &&
-                       (( abs( abs(nSpacingBegin)  - abs(nSpacingMiddle) ) ) <= 100 ) &&
-                       (( abs( abs(nSpacingMiddle) - abs(nSpacingLast) ) )   <= 100 ) ) ) {
+                     (((abs(abs(nSpacingBegin) - abs(nSpacingLast))) <= 100) &&
+                      ((abs(abs(nSpacingBegin) - abs(nSpacingMiddle))) <= 100) &&
+                      ((abs(abs(nSpacingMiddle) - abs(nSpacingLast))) <= 100)) )
+            {
                 bLatSpacingOK = true;
-                CPLError(CE_Warning, 1,"Latitude grid not spaced evenly.\nSetting projection for grid spacing is within 0.1 degrees threshold.\n");
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Latitude grid not spaced evenly.  "
+                         "Setting projection for grid spacing is "
+                         "within 0.1 degrees threshold.");
 
                 CPLDebug("GDAL_netCDF",
-                         "Latitude grid not spaced evenly, but within 0.1 degree threshold (probably a Gaussian grid).\n"
-                         "Saving original latitude values in Y_VALUES geolocation metadata" );
-                Set1DGeolocation( nVarDimYID, "Y" );
+                         "Latitude grid not spaced evenly, but within 0.1 "
+                         "degree threshold (probably a Gaussian grid).  "
+                         "Saving original latitude values in Y_VALUES "
+                         "geolocation metadata");
+                Set1DGeolocation(nVarDimYID, "Y");
             }
 
-            if ( bLatSpacingOK == false ) {
-                CPLDebug( "GDAL_netCDF",
-                          "Latitude is not equally spaced." );
+            if( bLatSpacingOK == false )
+            {
+                CPLDebug("GDAL_netCDF", "Latitude is not equally spaced.");
             }
         }
-        if ( ( bLonSpacingOK ) && ( bLatSpacingOK ) ) {
 
-/* -------------------------------------------------------------------- */
-/*      We have gridded data so we can set the Gereferencing info.      */
-/* -------------------------------------------------------------------- */
+        if( bLonSpacingOK && bLatSpacingOK )
+        {
+            // We have gridded data so we can set the Gereferencing info.
 
-/* -------------------------------------------------------------------- */
-/*      Enable GeoTransform                                             */
-/* -------------------------------------------------------------------- */
-                /* ----------------------------------------------------------*/
-                /*    In the following "actual_range" and "node_offset"      */
-                /*    are attributes used by netCDF files created by GMT.    */
-                /*    If we find them we know how to proceed. Else, use      */
-                /*    the original algorithm.                                */
-                /* --------------------------------------------------------- */
-                bGotCfGT = true;
+            // Enable GeoTransform.
 
-                int node_offset = 0;
-                nc_get_att_int (cdfid, NC_GLOBAL, "node_offset", &node_offset);
+            // In the following "actual_range" and "node_offset"
+            // are attributes used by netCDF files created by GMT.
+            // If we find them we know how to proceed. Else, use
+            // the original algorithm.
+            bGotCfGT = true;
 
-                double	dummy[2], xMinMax[2], yMinMax[2];
+            int node_offset = 0;
+            nc_get_att_int(cdfid, NC_GLOBAL, "node_offset", &node_offset);
 
-                if (!nc_get_att_double (cdfid, nVarDimXID, "actual_range", dummy)) {
-                    xMinMax[0] = dummy[0];
-                    xMinMax[1] = dummy[1];
-                }
-                else {
-                    xMinMax[0] = pdfXCoord[0];
-                    xMinMax[1] = pdfXCoord[xdim-1];
-                    node_offset = 0;
-                }
+            double adfActualRange[2] = { 0.0, 0.0 };
+            double xMinMax[2] = { 0.0, 0.0 };
+            double yMinMax[2] = { 0.0, 0.0 };
 
-                if (!nc_get_att_double (cdfid, nVarDimYID, "actual_range", dummy)) {
-                    yMinMax[0] = dummy[0];
-                    yMinMax[1] = dummy[1];
-                }
-                else {
-                    yMinMax[0] = pdfYCoord[0];
-                    yMinMax[1] = pdfYCoord[ydim-1];
-                    node_offset = 0;
-                }
+            if( !nc_get_att_double(cdfid, nVarDimXID,
+                                   "actual_range", adfActualRange) )
+            {
+                xMinMax[0] = adfActualRange[0];
+                xMinMax[1] = adfActualRange[1];
+            }
+            else
+            {
+                xMinMax[0] = pdfXCoord[0];
+                xMinMax[1] = pdfXCoord[xdim - 1];
+                node_offset = 0;
+            }
 
-                /* Check for reverse order of y-coordinate */
-                if ( yMinMax[0] > yMinMax[1] ) {
-                    dummy[0] = yMinMax[1];
-                    dummy[1] = yMinMax[0];
-                    yMinMax[0] = dummy[0];
-                    yMinMax[1] = dummy[1];
-                }
+            if( !nc_get_att_double(cdfid, nVarDimYID,
+                                   "actual_range", adfActualRange) )
+            {
+                yMinMax[0] = adfActualRange[0];
+                yMinMax[1] = adfActualRange[1];
+            }
+            else
+            {
+                yMinMax[0] = pdfYCoord[0];
+                yMinMax[1] = pdfYCoord[ydim - 1];
+                node_offset = 0;
+            }
 
-                adfTempGeoTransform[0] = xMinMax[0];
-                adfTempGeoTransform[2] = 0;
-                adfTempGeoTransform[3] = yMinMax[1];
-                adfTempGeoTransform[4] = 0;
-                adfTempGeoTransform[1] = ( xMinMax[1] - xMinMax[0] ) /
-                    ( poDS->nRasterXSize + (node_offset - 1) );
-                adfTempGeoTransform[5] = ( yMinMax[0] - yMinMax[1] ) /
-                    ( poDS->nRasterYSize + (node_offset - 1) );
-
-/* -------------------------------------------------------------------- */
-/*     Compute the center of the pixel                                  */
-/* -------------------------------------------------------------------- */
-                if ( !node_offset ) {	// Otherwise its already the pixel center
-                    adfTempGeoTransform[0] -= (adfTempGeoTransform[1] / 2);
-                    adfTempGeoTransform[3] -= (adfTempGeoTransform[5] / 2);
-                }
+            // Check for reverse order of y-coordinate.
+            if( yMinMax[0] > yMinMax[1] )
+            {
+                const double dfTmp = yMinMax[0];
+                yMinMax[0] = yMinMax[1];
+                yMinMax[1] = dfTmp;
+            }
 
-        }
+            double dfCoordOffset = 0.0;
+            double dfCoordScale = 1.0;
+            if( !nc_get_att_double(cdfid, nVarDimXID,
+                                   CF_ADD_OFFSET, &dfCoordOffset) &&
+                !nc_get_att_double(cdfid, nVarDimXID,
+                                   CF_SCALE_FACTOR, &dfCoordScale) )
+            {
+                xMinMax[0] = dfCoordOffset + xMinMax[0] * dfCoordScale;
+                xMinMax[1] = dfCoordOffset + xMinMax[1] * dfCoordScale;
+            }
+
+            if ( !nc_get_att_double(cdfid, nVarDimYID,
+                                    CF_ADD_OFFSET, &dfCoordOffset) &&
+                 !nc_get_att_double(cdfid, nVarDimYID,
+                                    CF_SCALE_FACTOR, &dfCoordScale) )
+            {
+                yMinMax[0] = dfCoordOffset + yMinMax[0] * dfCoordScale;
+                yMinMax[1] = dfCoordOffset + yMinMax[1] * dfCoordScale;
+            }
+
+            adfTempGeoTransform[0] = xMinMax[0];
+            adfTempGeoTransform[2] = 0;
+            adfTempGeoTransform[3] = yMinMax[1];
+            adfTempGeoTransform[4] = 0;
+            adfTempGeoTransform[1] = (xMinMax[1] - xMinMax[0]) /
+                                     (poDS->nRasterXSize + (node_offset - 1));
+            adfTempGeoTransform[5] = (yMinMax[0] - yMinMax[1]) /
+                                     (poDS->nRasterYSize + (node_offset - 1));
 
-        CPLFree( pdfXCoord );
-        CPLFree( pdfYCoord );
-    }// end if (has dims)
+            // Compute the center of the pixel.
+            if( !node_offset )
+            {
+                // Otherwise its already the pixel center.
+                adfTempGeoTransform[0] -= (adfTempGeoTransform[1] / 2);
+                adfTempGeoTransform[3] -= (adfTempGeoTransform[5] / 2);
+            }
+        }
 
-/* -------------------------------------------------------------------- */
-/*      Process custom GDAL values (spatial_ref, GeoTransform)          */
-/* -------------------------------------------------------------------- */
-    if( !EQUAL( szGridMappingValue, "" )  ) {
+        CPLFree(pdfXCoord);
+        CPLFree(pdfYCoord);
+    }  // end if(has dims)
 
-        if( pszWKT != NULL ) {
+    // Process custom GDAL values (spatial_ref, GeoTransform).
+    if( !EQUAL(szGridMappingValue, "") )
+    {
+        if( pszWKT != NULL )
+        {
+            // Compare SRS obtained from CF attributes and GDAL WKT.
+            // If possible use the more complete GDAL WKT.
 
-/* -------------------------------------------------------------------- */
-/*      Compare SRS obtained from CF attributes and GDAL WKT            */
-/*      If possible use the more complete GDAL WKT                      */
-/* -------------------------------------------------------------------- */
-            /* Set the SRS to the one written by GDAL */
-            if ( ! bGotCfSRS || poDS->pszProjection == NULL || ! bIsGdalCfFile ) {
+            // Set the SRS to the one written by GDAL.
+            if( !bGotCfSRS || poDS->pszProjection == NULL || ! bIsGdalCfFile )
+            {
                 bGotGdalSRS = true;
-                CPLDebug( "GDAL_netCDF", "setting WKT from GDAL" );
-                SetProjection( pszWKT );
+                CPLDebug("GDAL_netCDF", "setting WKT from GDAL");
+                SetProjection(pszWKT);
             }
-            else { /* use the SRS from GDAL if it doesn't conflict with the one from CF */
-                char *pszProjectionGDAL = (char*) pszWKT ;
+            else
+            {
+                // Use the SRS from GDAL if it doesn't conflict with the one
+                // from CF.
+                char *pszProjectionGDAL = (char *)pszWKT;
                 OGRSpatialReference oSRSGDAL;
-                oSRSGDAL.importFromWkt( &pszProjectionGDAL );
-                /* set datum to unknown or else datums will not match, see bug #4281 */
-                if ( oSRSGDAL.GetAttrNode( "DATUM" ) )
-                    oSRSGDAL.GetAttrNode( "DATUM" )->GetChild(0)->SetValue( "unknown" );
-                /* need this for setprojection autotest */
-                if ( oSRSGDAL.GetAttrNode( "PROJCS" ) )
-                    oSRSGDAL.GetAttrNode( "PROJCS" )->GetChild(0)->SetValue( "unnamed" );
-                if ( oSRSGDAL.GetAttrNode( "GEOGCS" ) )
-                    oSRSGDAL.GetAttrNode( "GEOGCS" )->GetChild(0)->SetValue( "unknown" );
-                oSRSGDAL.GetRoot()->StripNodes( "UNIT" );
-                if ( oSRS.IsSame(&oSRSGDAL) ) {
-                    // printf("ARE SAME, using GDAL WKT\n");
+                oSRSGDAL.importFromWkt(&pszProjectionGDAL);
+                // Set datum to unknown or else datums will not match, see bug
+                // #4281.
+                if( oSRSGDAL.GetAttrNode("DATUM") )
+                    oSRSGDAL.GetAttrNode("DATUM")->GetChild(0)->SetValue("unknown");
+                // Need this for setprojection autotest.
+                if( oSRSGDAL.GetAttrNode("PROJCS") )
+                    oSRSGDAL.GetAttrNode("PROJCS")->GetChild(0)->SetValue("unnamed");
+                if( oSRSGDAL.GetAttrNode("GEOGCS") )
+                    oSRSGDAL.GetAttrNode("GEOGCS")->GetChild(0)->SetValue("unknown");
+                oSRSGDAL.GetRoot()->StripNodes("UNIT");
+                OGRSpatialReference oSRSForComparison(oSRS);
+                oSRSForComparison.GetRoot()->StripNodes("UNIT");
+                if( oSRSForComparison.IsSame(&oSRSGDAL) )
+                {
+#ifdef NCDF_DEBUG
+                    CPLDebug("GDAL_netCDF", "ARE SAME, using GDAL WKT");
+#endif
                     bGotGdalSRS = true;
-                    CPLDebug( "GDAL_netCDF", "setting WKT from GDAL" );
-                    SetProjection( pszWKT );
+                    CPLDebug("GDAL_netCDF", "setting WKT from GDAL");
+                    SetProjection(pszWKT);
                 }
-                else {
-                    CPLDebug( "GDAL_netCDF",
-                              "got WKT from GDAL \n[%s]\nbut not using it because conflicts with CF\n[%s]\n",
-                              pszWKT, poDS->pszProjection );
+                else
+                {
+                    CPLDebug("GDAL_netCDF",
+                             "got WKT from GDAL \n[%s]\nbut not using it "
+                             "because conflicts with CF\n[%s]",
+                             pszWKT, poDS->pszProjection);
                 }
             }
 
-/* -------------------------------------------------------------------- */
-/*      Look for GeoTransform Array, if not found in CF                 */
-/* -------------------------------------------------------------------- */
-            if ( !bGotCfGT ) {
-
-                /* TODO read the GT values and detect for conflict with CF */
-                /* this could resolve the GT precision loss issue  */
-
-                if( pszGeoTransform != NULL ) {
+            // Look for GeoTransform Array, if not found in CF.
+            if( !bGotCfGT )
+            {
+                // TODO: Read the GT values and detect for conflict with CF.
+                // This could resolve the GT precision loss issue.
 
-                    char** papszGeoTransform = CSLTokenizeString2( pszGeoTransform,
-                                                            " ",
-                                                            CSLT_HONOURSTRINGS );
+                if( pszGeoTransform != NULL )
+                {
+                    char** papszGeoTransform =
+                        CSLTokenizeString2(pszGeoTransform,
+                                            " ",
+                                            CSLT_HONOURSTRINGS);
                     if( CSLCount(papszGeoTransform) == 6 )
                     {
                         bGotGdalGT = true;
-                        for(int i=0;i<6;i++)
-                            adfTempGeoTransform[i] = CPLAtof( papszGeoTransform[i] );
+                        for( int i = 0; i < 6; i++ )
+                            adfTempGeoTransform[i] =
+                                CPLAtof(papszGeoTransform[i]);
                     }
-                    CSLDestroy( papszGeoTransform );
-/* -------------------------------------------------------------------- */
-/*      Look for corner array values                                    */
-/* -------------------------------------------------------------------- */
-                } else {
-                    // CPLDebug( "GDAL_netCDF", "looking for geotransform corners\n" );
-
-                    snprintf(szTemp,sizeof(szTemp), "%s#Northernmost_Northing", szGridMappingValue);
+                    CSLDestroy(papszGeoTransform);
+                    // Look for corner array values.
+                }
+                else
+                {
+                    // CPLDebug("GDAL_netCDF",
+                    //           "looking for geotransform corners");
+
+                    snprintf(szTemp, sizeof(szTemp),
+                             "%s#Northernmost_Northing", szGridMappingValue);
                     pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
                     bool bGotNN = false;
                     double dfNN = 0.0;
-                    if( pszValue != NULL ) {
-                        dfNN = CPLAtof( pszValue );
+                    if( pszValue != NULL )
+                    {
+                        dfNN = CPLAtof(pszValue);
                         bGotNN = true;
                     }
 
-                    snprintf(szTemp,sizeof(szTemp), "%s#Southernmost_Northing", szGridMappingValue);
+                    snprintf(szTemp, sizeof(szTemp),
+                             "%s#Southernmost_Northing", szGridMappingValue);
                     pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
                     bool bGotSN = false;
                     double dfSN = 0.0;
-                    if( pszValue != NULL ) {
-                        dfSN = CPLAtof( pszValue );
+                    if( pszValue != NULL )
+                    {
+                        dfSN = CPLAtof(pszValue);
                         bGotSN = true;
                     }
 
-                    snprintf(szTemp,sizeof(szTemp), "%s#Easternmost_Easting", szGridMappingValue);
+                    snprintf(szTemp, sizeof(szTemp), "%s#Easternmost_Easting",
+                             szGridMappingValue);
                     pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
                     bool bGotEE = false;
                     double dfEE = 0.0;
-                    if( pszValue != NULL ) {
-                        dfEE = CPLAtof( pszValue );
+                    if( pszValue != NULL )
+                    {
+                        dfEE = CPLAtof(pszValue);
                         bGotEE = true;
                     }
 
-                    snprintf(szTemp,sizeof(szTemp), "%s#Westernmost_Easting", szGridMappingValue);
+                    snprintf(szTemp, sizeof(szTemp), "%s#Westernmost_Easting",
+                             szGridMappingValue);
                     pszValue = CSLFetchNameValue(poDS->papszMetadata, szTemp);
                     bool bGotWE = false;
                     double dfWE = 0.0;
-                    if( pszValue != NULL ) {
-                        dfWE = CPLAtof( pszValue );
+                    if( pszValue != NULL )
+                    {
+                        dfWE = CPLAtof(pszValue);
                         bGotWE = true;
                     }
 
-                    /* Only set the GeoTransform if we got all the values */
-                    if ( bGotNN && bGotSN && bGotEE && bGotWE ) {
-
+                    // Only set the GeoTransform if we got all the values.
+                    if( bGotNN && bGotSN && bGotEE && bGotWE )
+                    {
                         bGotGdalGT = true;
 
                         adfTempGeoTransform[0] = dfWE;
-                        adfTempGeoTransform[1] = (dfEE - dfWE) /
-                            ( poDS->GetRasterXSize() - 1 );
+                        adfTempGeoTransform[1] =
+                            (dfEE - dfWE) / (poDS->GetRasterXSize() - 1);
                         adfTempGeoTransform[2] = 0.0;
                         adfTempGeoTransform[3] = dfNN;
                         adfTempGeoTransform[4] = 0.0;
-                        adfTempGeoTransform[5] = (dfSN - dfNN) /
-                            ( poDS->GetRasterYSize() - 1 );
-                        /* compute the center of the pixel */
-                        adfTempGeoTransform[0] = dfWE
-                            - (adfTempGeoTransform[1] / 2);
-                        adfTempGeoTransform[3] = dfNN
-                            - (adfTempGeoTransform[5] / 2);
+                        adfTempGeoTransform[5] =
+                            (dfSN - dfNN) / (poDS->GetRasterYSize() - 1);
+                        // Compute the center of the pixel.
+                        adfTempGeoTransform[0] =
+                            dfWE - (adfTempGeoTransform[1] / 2);
+                        adfTempGeoTransform[3] =
+                            dfNN - (adfTempGeoTransform[5] / 2);
                     }
                 } // (pszGeoTransform != NULL)
 
-                if ( bGotGdalSRS && ! bGotGdalGT )
-                    CPLDebug( "GDAL_netCDF",
-                              "Got SRS but no geotransform from GDAL!");
-
-            } // if ( !bGotCfGT )
+                if( bGotGdalSRS && !bGotGdalGT )
+                    CPLDebug("GDAL_netCDF",
+                             "Got SRS but no geotransform from GDAL!");
+            }  // if( !bGotCfGT )
+        }
+    }
 
+    // Some netCDF files have a srid attribute (#6613) like
+    // urn:ogc:def:crs:EPSG::6931
+    snprintf(szTemp, sizeof(szTemp), "%s#%s", szGridMappingValue, "srid");
+    const char *pszSRID = CSLFetchNameValue(poDS->papszMetadata, szTemp);
+    if( pszSRID != NULL )
+    {
+        oSRS.Clear();
+        if( oSRS.SetFromUserInput(pszSRID) == OGRERR_NONE )
+        {
+            char *pszWKTExport = NULL;
+            CPLDebug("GDAL_netCDF", "Got SRS from %s", szTemp);
+            oSRS.exportToWkt(&pszWKTExport);
+            SetProjection(pszWKTExport);
+            CPLFree(pszWKTExport);
         }
     }
 
     // Set GeoTransform if we got a complete one - after projection has been set
-    if ( bGotCfGT || bGotGdalGT ) {
-        SetGeoTransform( adfTempGeoTransform );
+    if( bGotCfGT || bGotGdalGT )
+    {
+        SetGeoTransform(adfTempGeoTransform);
     }
 
     // Process geolocation arrays from CF "coordinates" attribute.
     // Perhaps we should only add if is not a (supported) CF projection
     // (bIsCfProjection).
-    ProcessCFGeolocation( nVarId );
+    ProcessCFGeolocation(nVarId);
 
     // Debugging reports.
-    CPLDebug( "GDAL_netCDF",
-              "bGotGeogCS=%d bGotCfSRS=%d bGotCfGT=%d bGotGdalSRS=%d "
-              "bGotGdalGT=%d",
-              static_cast<int>(bGotGeogCS), static_cast<int>(bGotCfSRS),
-              static_cast<int>(bGotCfGT), static_cast<int>(bGotGdalSRS),
-              static_cast<int>(bGotGdalGT) );
-
-    if ( !bGotCfGT && !bGotGdalGT )
-        CPLDebug( "GDAL_netCDF", "did not get geotransform from CF nor GDAL!");
-
-    if ( !bGotGeogCS && !bGotCfSRS && !bGotGdalSRS && !bGotCfGT)
-        CPLDebug( "GDAL_netCDF",  "did not get projection from CF nor GDAL!");
-
-/* -------------------------------------------------------------------- */
-/*     Search for Well-known GeogCS if got only CF WKT                  */
-/*     Disabled for now, as a named datum also include control points   */
-/*     (see mailing list and bug#4281                                   */
-/*     For example, WGS84 vs. GDA94 (EPSG:3577) - AEA in netcdf_cf.py   */
-/* -------------------------------------------------------------------- */
-    /* disabled for now, but could be set in a config option */
+    CPLDebug("GDAL_netCDF",
+             "bGotGeogCS=%d bGotCfSRS=%d bGotCfGT=%d bGotGdalSRS=%d "
+             "bGotGdalGT=%d",
+             static_cast<int>(bGotGeogCS), static_cast<int>(bGotCfSRS),
+             static_cast<int>(bGotCfGT), static_cast<int>(bGotGdalSRS),
+             static_cast<int>(bGotGdalGT));
+
+    if( !bGotCfGT && !bGotGdalGT )
+        CPLDebug("GDAL_netCDF", "did not get geotransform from CF nor GDAL!");
+
+    if( !bGotGeogCS && !bGotCfSRS && !bGotGdalSRS && !bGotCfGT )
+        CPLDebug("GDAL_netCDF", "did not get projection from CF nor GDAL!");
+
+    // Search for Well-known GeogCS if got only CF WKT
+    // Disabled for now, as a named datum also include control points
+    // (see mailing list and bug#4281
+    // For example, WGS84 vs. GDA94 (EPSG:3577) - AEA in netcdf_cf.py
+
+    // Disabled for now, but could be set in a config option.
 #if 0
     bool bLookForWellKnownGCS = false;  // This could be a Config Option.
 
-    if ( bLookForWellKnownGCS && bGotCfSRS && ! bGotGdalSRS ) {
-        /* ET - could use a more exhaustive method by scanning all EPSG codes in data/gcs.csv */
-        /* as proposed by Even in the gdal-dev mailing list "help for comparing two WKT" */
-        /* this code could be contributed to a new function */
-        /* OGRSpatialReference * OGRSpatialReference::FindMatchingGeogCS( const OGRSpatialReference *poOther ) */
-        CPLDebug( "GDAL_netCDF", "Searching for Well-known GeogCS" );
+    if( bLookForWellKnownGCS && bGotCfSRS && !bGotGdalSRS )
+    {
+        // ET - Could use a more exhaustive method by scanning all EPSG codes in
+        // data/gcs.csv as proposed by Even in the gdal-dev mailing list "help
+        // for comparing two WKT".
+        // This code could be contributed to a new function.
+        // OGRSpatialReference * OGRSpatialReference::FindMatchingGeogCS(
+        //     const OGRSpatialReference *poOther) */
+        CPLDebug("GDAL_netCDF", "Searching for Well-known GeogCS");
         const char *pszWKGCSList[] = { "WGS84", "WGS72", "NAD27", "NAD83" };
         char *pszWKGCS = NULL;
-        oSRS.exportToPrettyWkt( &pszWKGCS );
-        for( size_t i=0; i<sizeof(pszWKGCSList)/8; i++ ) {
-            pszWKGCS = CPLStrdup( pszWKGCSList[i] );
+        oSRS.exportToPrettyWkt(&pszWKGCS);
+        for( size_t i = 0; i < sizeof(pszWKGCSList) / 8; i++ )
+        {
+            pszWKGCS = CPLStrdup(pszWKGCSList[i]);
             OGRSpatialReference oSRSTmp;
-            oSRSTmp.SetWellKnownGeogCS( pszWKGCSList[i] );
-            /* set datum to unknown, bug #4281 */
-            if ( oSRSTmp.GetAttrNode( "DATUM" ) )
-                oSRSTmp.GetAttrNode( "DATUM" )->GetChild(0)->SetValue( "unknown" );
-            /* could use  OGRSpatialReference::StripCTParms() but let's keep TOWGS84 */
-            oSRSTmp.GetRoot()->StripNodes( "AXIS" );
-            oSRSTmp.GetRoot()->StripNodes( "AUTHORITY" );
-            oSRSTmp.GetRoot()->StripNodes( "EXTENSION" );
-
-            oSRSTmp.exportToPrettyWkt( &pszWKGCS );
-            if ( oSRS.IsSameGeogCS(&oSRSTmp) ) {
-                oSRS.SetWellKnownGeogCS( pszWKGCSList[i] );
-                oSRS.exportToWkt( &(pszTempProjection) );
-                SetProjection( pszTempProjection );
-                CPLFree( pszTempProjection );
+            oSRSTmp.SetWellKnownGeogCS(pszWKGCSList[i]);
+            // Set datum to unknown, bug #4281.
+            if( oSRSTmp.GetAttrNode("DATUM" ) )
+                oSRSTmp.GetAttrNode("DATUM")->GetChild(0)->SetValue("unknown");
+            // Could use OGRSpatialReference::StripCTParms(), but let's keep
+            // TOWGS84.
+            oSRSTmp.GetRoot()->StripNodes("AXIS");
+            oSRSTmp.GetRoot()->StripNodes("AUTHORITY");
+            oSRSTmp.GetRoot()->StripNodes("EXTENSION");
+
+            oSRSTmp.exportToPrettyWkt(&pszWKGCS);
+            if( oSRS.IsSameGeogCS(&oSRSTmp) )
+            {
+                oSRS.SetWellKnownGeogCS(pszWKGCSList[i]);
+                oSRS.exportToWkt(&(pszTempProjection));
+                SetProjection(pszTempProjection);
+                CPLFree(pszTempProjection);
             }
         }
     }
 #endif
 }
 
-
 int netCDFDataset::ProcessCFGeolocation( int nVarId )
 {
     bool bAddGeoloc = false;
     char *pszTemp = NULL;
 
-    if ( NCDFGetAttr( cdfid, nVarId, "coordinates", &pszTemp ) == CE_None ) {
-        /* get X and Y geolocation names from coordinates attribute */
-        char **papszTokens = CSLTokenizeString2( pszTemp, " ", 0 );
-        if ( CSLCount(papszTokens) >= 2 ) {
-
-            char szGeolocXName[NC_MAX_NAME+1];
-            char szGeolocYName[NC_MAX_NAME+1];
+    if( NCDFGetAttr(cdfid, nVarId, "coordinates", &pszTemp) == CE_None )
+    {
+        // Get X and Y geolocation names from coordinates attribute.
+        char **papszTokens = CSLTokenizeString2(pszTemp, " ", 0);
+        if( CSLCount(papszTokens) >= 2 )
+        {
+            char szGeolocXName[NC_MAX_NAME + 1];
+            char szGeolocYName[NC_MAX_NAME + 1];
             szGeolocXName[0] = '\0';
             szGeolocYName[0] = '\0';
 
-            /* test that each variable is longitude/latitude */
-            for ( int i=0; i<CSLCount(papszTokens); i++ ) {
-                if ( NCDFIsVarLongitude(cdfid, -1, papszTokens[i]) )
-                    snprintf(szGeolocXName,sizeof(szGeolocXName),"%s",papszTokens[i] );
-                else if ( NCDFIsVarLatitude(cdfid, -1, papszTokens[i]) )
-                    snprintf(szGeolocYName,sizeof(szGeolocYName),"%s",papszTokens[i] );
-            }
-            /* add GEOLOCATION metadata */
-            if ( !EQUAL(szGeolocXName,"") && !EQUAL(szGeolocYName,"") ) {
+            // Test that each variable is longitude/latitude.
+            for( int i = 0; i < CSLCount(papszTokens); i++ )
+            {
+                if( NCDFIsVarLongitude(cdfid, -1, papszTokens[i]) )
+                    snprintf(szGeolocXName, sizeof(szGeolocXName),
+                             "%s",papszTokens[i]);
+                else if( NCDFIsVarLatitude(cdfid, -1, papszTokens[i]) )
+                    snprintf(szGeolocYName, sizeof(szGeolocYName),
+                             "%s",papszTokens[i]);
+            }
+            // Add GEOLOCATION metadata.
+            if( !EQUAL(szGeolocXName, "") && !EQUAL(szGeolocYName, "") )
+            {
                 bAddGeoloc = true;
-                CPLDebug( "GDAL_netCDF",
-                          "using variables %s and %s for GEOLOCATION",
-                          szGeolocXName, szGeolocYName );
+                CPLDebug("GDAL_netCDF",
+                         "using variables %s and %s for GEOLOCATION",
+                         szGeolocXName, szGeolocYName);
 
-                SetMetadataItem( "SRS", SRS_WKT_WGS84, "GEOLOCATION" );
+                SetMetadataItem("SRS", SRS_WKT_WGS84, "GEOLOCATION");
 
                 CPLString osTMP;
-                osTMP.Printf( "NETCDF:\"%s\":%s",
-                              osFilename.c_str(), szGeolocXName );
-                SetMetadataItem( "X_DATASET", osTMP, "GEOLOCATION" );
-                SetMetadataItem( "X_BAND", "1" , "GEOLOCATION" );
-                osTMP.Printf( "NETCDF:\"%s\":%s",
-                              osFilename.c_str(), szGeolocYName );
-                SetMetadataItem( "Y_DATASET", osTMP, "GEOLOCATION" );
-                SetMetadataItem( "Y_BAND", "1" , "GEOLOCATION" );
-
-                SetMetadataItem( "PIXEL_OFFSET", "0", "GEOLOCATION" );
-                SetMetadataItem( "PIXEL_STEP", "1", "GEOLOCATION" );
-
-                SetMetadataItem( "LINE_OFFSET", "0", "GEOLOCATION" );
-                SetMetadataItem( "LINE_STEP", "1", "GEOLOCATION" );
+                osTMP.Printf("NETCDF:\"%s\":%s",
+                             osFilename.c_str(), szGeolocXName);
+                SetMetadataItem("X_DATASET", osTMP, "GEOLOCATION");
+                SetMetadataItem("X_BAND", "1" , "GEOLOCATION");
+                osTMP.Printf("NETCDF:\"%s\":%s",
+                             osFilename.c_str(), szGeolocYName);
+                SetMetadataItem("Y_DATASET", osTMP, "GEOLOCATION");
+                SetMetadataItem("Y_BAND", "1", "GEOLOCATION");
+
+                SetMetadataItem("PIXEL_OFFSET", "0", "GEOLOCATION");
+                SetMetadataItem("PIXEL_STEP", "1", "GEOLOCATION");
+
+                SetMetadataItem("LINE_OFFSET", "0", "GEOLOCATION");
+                SetMetadataItem("LINE_STEP", "1", "GEOLOCATION");
             }
-            else {
-                CPLDebug( "GDAL_netCDF",
-                          "coordinates attribute [%s] is unsupported",
-                          pszTemp );
+            else
+            {
+                CPLDebug("GDAL_netCDF",
+                         "coordinates attribute [%s] is unsupported", pszTemp);
             }
         }
-        else {
-            CPLDebug( "GDAL_netCDF",
-                      "coordinates attribute [%s] with %d element(s) is unsupported",
-                      pszTemp, CSLCount(papszTokens) );
+        else
+        {
+            CPLDebug("GDAL_netCDF",
+                     "coordinates attribute [%s] with %d element(s) is "
+                     "unsupported",
+                     pszTemp, CSLCount(papszTokens));
         }
-        if (papszTokens) CSLDestroy(papszTokens);
-        CPLFree( pszTemp );
+        if( papszTokens ) CSLDestroy(papszTokens);
+        CPLFree(pszTemp);
     }
 
     return bAddGeoloc;
@@ -3309,91 +3427,94 @@ int netCDFDataset::ProcessCFGeolocation( int nVarId )
 
 CPLErr netCDFDataset::Set1DGeolocation( int nVarId, const char *szDimName )
 {
-    /* get values */
-    char    *pszVarValues = NULL;
-    CPLErr eErr = NCDFGet1DVar( cdfid, nVarId, &pszVarValues );
-    if ( eErr != CE_None )
+    // Get values.
+    char *pszVarValues = NULL;
+    CPLErr eErr = NCDFGet1DVar(cdfid, nVarId, &pszVarValues);
+    if( eErr != CE_None )
         return eErr;
 
-    /* write metadata */
-    char szTemp[ NC_MAX_NAME + 1 + 32 ];
-    snprintf( szTemp, sizeof(szTemp), "%s_VALUES", szDimName );
-    SetMetadataItem( szTemp, pszVarValues, "GEOLOCATION2" );
+    // Write metadata.
+    char szTemp[ NC_MAX_NAME + 1 + 32 ] = {};
+    snprintf(szTemp, sizeof(szTemp), "%s_VALUES", szDimName);
+    SetMetadataItem(szTemp, pszVarValues, "GEOLOCATION2");
 
-    CPLFree( pszVarValues );
+    CPLFree(pszVarValues);
 
     return CE_None;
 }
 
-
-double *netCDFDataset::Get1DGeolocation( CPL_UNUSED const char *szDimName, int &nVarLen )
+double *netCDFDataset::Get1DGeolocation( CPL_UNUSED const char *szDimName,
+                                         int &nVarLen )
 {
     nVarLen = 0;
 
-    /* get Y_VALUES as tokens */
+    // Get Y_VALUES as tokens.
     char **papszValues
-        = NCDFTokenizeArray( GetMetadataItem( "Y_VALUES", "GEOLOCATION2" ) );
-    if ( papszValues == NULL )
+        = NCDFTokenizeArray(GetMetadataItem("Y_VALUES", "GEOLOCATION2"));
+    if( papszValues == NULL )
         return NULL;
 
-    /* initialize and fill array */
+    // Initialize and fill array.
     nVarLen = CSLCount(papszValues);
-    double *pdfVarValues = (double *) CPLCalloc( nVarLen, sizeof( double ) );
+    double *pdfVarValues =
+        static_cast<double *>(CPLCalloc(nVarLen, sizeof(double)));
 
-    for(int i=0, j=0; i < nVarLen; i++) {
-        if ( ! bBottomUp ) j=nVarLen - 1 - i;
-        else j=i; /* invert latitude values */
+    for( int i = 0, j = 0; i < nVarLen; i++ )
+    {
+        if( !bBottomUp ) j = nVarLen - 1 - i;
+        else j = i;  // Invert latitude values.
         char *pszTemp = NULL;
-        pdfVarValues[j] = CPLStrtod( papszValues[i], &pszTemp );
+        pdfVarValues[j] = CPLStrtod(papszValues[i], &pszTemp);
     }
-    CSLDestroy( papszValues );
+    CSLDestroy(papszValues);
 
     return pdfVarValues;
 }
 
-
 /************************************************************************/
 /*                          SetProjection()                           */
 /************************************************************************/
-CPLErr 	netCDFDataset::SetProjection( const char * pszNewProjection )
+CPLErr netCDFDataset::SetProjection( const char * pszNewProjection )
 {
     CPLMutexHolderD(&hNCMutex);
 
-/* TODO look if proj. already defined, like in geotiff */
+    // TODO: Look if proj. already defined, like in geotiff.
     if( pszNewProjection == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "NULL projection." );
+        CPLError(CE_Failure, CPLE_AppDefined, "NULL projection.");
         return CE_Failure;
     }
 
     if( bSetProjection && (GetAccess() == GA_Update) )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
+        CPLError(CE_Warning, CPLE_AppDefined,
                   "netCDFDataset::SetProjection() should only be called once "
                   "in update mode!\npszNewProjection=\n%s",
-                  pszNewProjection );
+                  pszNewProjection);
     }
 
-    CPLDebug( "GDAL_netCDF", "SetProjection, WKT = %s", pszNewProjection );
+    CPLDebug("GDAL_netCDF", "SetProjection, WKT = %s", pszNewProjection);
 
     if( !STARTS_WITH_CI(pszNewProjection, "GEOGCS")
         && !STARTS_WITH_CI(pszNewProjection, "PROJCS")
-        && !EQUAL(pszNewProjection,"") )
+        && !EQUAL(pszNewProjection, "") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Only OGC WKT GEOGCS and PROJCS Projections supported for writing to NetCDF.\n"
+        CPLError(CE_Failure, CPLE_AppDefined,
+                  "Only OGC WKT GEOGCS and PROJCS Projections supported "
+                  "for writing to NetCDF.  "
                   "%s not supported.",
-                  pszNewProjection );
+                  pszNewProjection);
 
         return CE_Failure;
     }
 
-    CPLFree( pszProjection );
-    pszProjection = CPLStrdup( pszNewProjection );
+    CPLFree(pszProjection);
+    pszProjection = CPLStrdup(pszNewProjection);
 
     if( GetAccess() == GA_Update )
     {
-        if ( bSetGeoTransform && ! bSetProjection ) {
+        if( bSetGeoTransform && !bSetProjection )
+        {
             bSetProjection = true;
             return AddProjectionVars();
         }
@@ -3408,22 +3529,23 @@ CPLErr 	netCDFDataset::SetProjection( const char * pszNewProjection )
 /*                          SetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr 	netCDFDataset::SetGeoTransform ( double * padfTransform )
+CPLErr netCDFDataset::SetGeoTransform ( double * padfTransform )
 {
     CPLMutexHolderD(&hNCMutex);
 
-    memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );
+    memcpy(adfGeoTransform, padfTransform, sizeof(double)*6);
     // bGeoTransformValid = TRUE;
     // bGeoTIFFInfoChanged = TRUE;
 
-    CPLDebug( "GDAL_netCDF",
+    CPLDebug("GDAL_netCDF",
               "SetGeoTransform(%f,%f,%f,%f,%f,%f)",
-              padfTransform[0],padfTransform[1],padfTransform[2],
-              padfTransform[3],padfTransform[4],padfTransform[5]);
+              padfTransform[0], padfTransform[1], padfTransform[2],
+              padfTransform[3], padfTransform[4], padfTransform[5]);
 
     if( GetAccess() == GA_Update )
     {
-        if ( bSetProjection && ! bSetGeoTransform ) {
+        if( bSetProjection && !bSetGeoTransform )
+        {
             bSetGeoTransform = true;
             return AddProjectionVars();
         }
@@ -3434,45 +3556,41 @@ CPLErr 	netCDFDataset::SetGeoTransform ( double * padfTransform )
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                         NCDFWriteSRSVariable()                       */
 /************************************************************************/
 
 int NCDFWriteSRSVariable(int cdfid, OGRSpatialReference* poSRS,
-                                char** ppszCFProjection, bool bWriteGDALTags)
+                                char **ppszCFProjection, bool bWriteGDALTags)
 {
     int status;
     int NCDFVarID = -1;
-    char* pszCFProjection = NULL;
+    char *pszCFProjection = NULL;
 
     *ppszCFProjection = NULL;
 
     if( poSRS->IsProjected() )
     {
-/* -------------------------------------------------------------------- */
-/*      Write CF-1.5 compliant Projected attributes                     */
-/* -------------------------------------------------------------------- */
+        // Write CF-1.5 compliant Projected attributes.
 
-        const OGR_SRSNode *poPROJCS = poSRS->GetAttrNode( "PROJCS" );
-        const char  *pszProjName;
-        pszProjName = poSRS->GetAttrValue( "PROJECTION" );
+        const OGR_SRSNode *poPROJCS = poSRS->GetAttrNode("PROJCS");
+        const char *pszProjName = poSRS->GetAttrValue("PROJECTION");
         if( pszProjName == NULL )
             return -1;
 
-        /* Basic Projection info (grid_mapping and datum) */
-        for( int i=0; poNetcdfSRS_PT[i].WKT_SRS != NULL; i++ ) {
-            if( EQUAL( poNetcdfSRS_PT[i].WKT_SRS, pszProjName ) ) {
-                CPLDebug( "GDAL_netCDF", "GDAL PROJECTION = %s , NCDF PROJECTION = %s",
+        // Basic Projection info (grid_mapping and datum).
+        for( int i = 0; poNetcdfSRS_PT[i].WKT_SRS != NULL; i++ )
+        {
+            if( EQUAL(poNetcdfSRS_PT[i].WKT_SRS, pszProjName) )
+            {
+                CPLDebug("GDAL_netCDF", "GDAL PROJECTION = %s , NCDF PROJECTION = %s",
                             poNetcdfSRS_PT[i].WKT_SRS,
                             poNetcdfSRS_PT[i].CF_SRS);
-                pszCFProjection = CPLStrdup( poNetcdfSRS_PT[i].CF_SRS );
-                CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
-                            cdfid, poNetcdfSRS_PT[i].CF_SRS, NC_CHAR );
-                status = nc_def_var( cdfid,
-                                        poNetcdfSRS_PT[i].CF_SRS,
-                                        NC_CHAR,
-                                        0, NULL, &NCDFVarID );
+                pszCFProjection = CPLStrdup(poNetcdfSRS_PT[i].CF_SRS);
+                CPLDebug("GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                         cdfid, poNetcdfSRS_PT[i].CF_SRS, NC_CHAR);
+                status = nc_def_var(cdfid, poNetcdfSRS_PT[i].CF_SRS, NC_CHAR, 0,
+                                    NULL, &NCDFVarID);
                 NCDF_ERR(status);
                 break;
             }
@@ -3480,73 +3598,68 @@ int NCDFWriteSRSVariable(int cdfid, OGRSpatialReference* poSRS,
         if( pszCFProjection == NULL )
             return -1;
 
-        status = nc_put_att_text( cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
-                                    strlen( pszCFProjection ),
-                                    pszCFProjection );
+        status = nc_put_att_text(cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
+                                 strlen(pszCFProjection), pszCFProjection);
         NCDF_ERR(status);
 
-        /* Various projection attributes */
+        // Various projection attributes.
         // PDS: keep in sync with SetProjection function
         NCDFWriteProjAttribs(poPROJCS, pszProjName, cdfid, NCDFVarID);
 
-        if( EQUAL( pszProjName, SRS_PT_GEOSTATIONARY_SATELLITE ) )
+        if( EQUAL(pszProjName, SRS_PT_GEOSTATIONARY_SATELLITE) )
         {
             const char *pszPredefProj4 = poSRS->GetExtension(
-                        poSRS->GetRoot()->GetValue(), "PROJ4", NULL );
-            const char* pszSweepAxisAngle =
-             ( pszPredefProj4 != NULL && strstr(pszPredefProj4, "+sweep=x") ) ? "x" : "y";
-            status = nc_put_att_text( cdfid, NCDFVarID, CF_PP_SWEEP_ANGLE_AXIS,
-                             strlen(pszSweepAxisAngle), pszSweepAxisAngle );
+                        poSRS->GetRoot()->GetValue(), "PROJ4", NULL);
+            const char *pszSweepAxisAngle =
+                (pszPredefProj4 != NULL && strstr(pszPredefProj4, "+sweep=x")) ? "x" : "y";
+            status =
+                nc_put_att_text(cdfid, NCDFVarID, CF_PP_SWEEP_ANGLE_AXIS,
+                                strlen(pszSweepAxisAngle), pszSweepAxisAngle);
             NCDF_ERR(status);
         }
     }
     else
     {
-/* -------------------------------------------------------------------- */
-/*      Write CF-1.5 compliant Geographics attributes                   */
-/*      Note: WKT information will not be preserved (e.g. WGS84)        */
-/* -------------------------------------------------------------------- */
-
-        pszCFProjection = CPLStrdup( "crs" );
-        CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
-                    cdfid, pszCFProjection, NC_CHAR );
-        status = nc_def_var( cdfid, pszCFProjection, NC_CHAR,
-                                0, NULL, &NCDFVarID );
+        // Write CF-1.5 compliant Geographics attributes.
+        // Note: WKT information will not be preserved (e.g. WGS84).
+
+        pszCFProjection = CPLStrdup("crs");
+        CPLDebug("GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                 cdfid, pszCFProjection, NC_CHAR);
+        status =
+            nc_def_var(cdfid, pszCFProjection, NC_CHAR, 0, NULL, &NCDFVarID);
         NCDF_ERR(status);
-        status = nc_put_att_text( cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
-                                    strlen(CF_PT_LATITUDE_LONGITUDE),
-                                    CF_PT_LATITUDE_LONGITUDE );
+        status = nc_put_att_text(cdfid, NCDFVarID, CF_GRD_MAPPING_NAME,
+                                 strlen(CF_PT_LATITUDE_LONGITUDE),
+                                 CF_PT_LATITUDE_LONGITUDE);
         NCDF_ERR(status);
     }
 
-    status = nc_put_att_text( cdfid, NCDFVarID, CF_LNG_NAME,
-                              strlen("CRS definition"),
-                             "CRS definition" );
+    status = nc_put_att_text(cdfid, NCDFVarID, CF_LNG_NAME,
+                             strlen("CRS definition"), "CRS definition");
     NCDF_ERR(status);
 
     *ppszCFProjection = pszCFProjection;
 
-/* -------------------------------------------------------------------- */
-/*      Write CF-1.5 compliant common attributes                        */
-/* -------------------------------------------------------------------- */
+    // Write CF-1.5 compliant common attributes.
 
-    /* DATUM information */
+    // DATUM information.
     double dfTemp = poSRS->GetPrimeMeridian();
-    nc_put_att_double( cdfid, NCDFVarID, CF_PP_LONG_PRIME_MERIDIAN,
-                        NC_DOUBLE, 1, &dfTemp );
+    nc_put_att_double(cdfid, NCDFVarID, CF_PP_LONG_PRIME_MERIDIAN,
+                      NC_DOUBLE, 1, &dfTemp);
     dfTemp = poSRS->GetSemiMajor();
-    nc_put_att_double( cdfid, NCDFVarID, CF_PP_SEMI_MAJOR_AXIS,
-                        NC_DOUBLE, 1, &dfTemp );
+    nc_put_att_double(cdfid, NCDFVarID, CF_PP_SEMI_MAJOR_AXIS,
+                      NC_DOUBLE, 1, &dfTemp);
     dfTemp = poSRS->GetInvFlattening();
-    nc_put_att_double( cdfid, NCDFVarID, CF_PP_INVERSE_FLATTENING,
-                        NC_DOUBLE, 1, &dfTemp );
+    nc_put_att_double(cdfid, NCDFVarID, CF_PP_INVERSE_FLATTENING,
+                      NC_DOUBLE, 1, &dfTemp);
 
     if( bWriteGDALTags )
     {
-        char* pszSpatialRef = NULL;
+        char *pszSpatialRef = NULL;
         poSRS->exportToWkt(&pszSpatialRef);
-        status = nc_put_att_text( cdfid, NCDFVarID, NCDF_SPATIAL_REF,
-                                  strlen( pszSpatialRef ), pszSpatialRef );
+        status = nc_put_att_text(cdfid, NCDFVarID, NCDF_SPATIAL_REF,
+                                 strlen(pszSpatialRef), pszSpatialRef);
         NCDF_ERR(status);
         CPLFree(pszSpatialRef);
     }
@@ -3558,34 +3671,34 @@ int NCDFWriteSRSVariable(int cdfid, OGRSpatialReference* poSRS,
 /*                   NCDFWriteLonLatVarsAttributes()                    */
 /************************************************************************/
 
-void NCDFWriteLonLatVarsAttributes(int cdfid,
-                                          int nVarLonID,
-                                          int nVarLatID)
+void NCDFWriteLonLatVarsAttributes(int cdfid, int nVarLonID, int nVarLatID)
 {
-    int status;
-
-    status = nc_put_att_text( cdfid, nVarLatID, CF_STD_NAME,
-                     strlen(CF_LATITUDE_STD_NAME), CF_LATITUDE_STD_NAME );
+    int status =
+        nc_put_att_text(cdfid, nVarLatID, CF_STD_NAME,
+                        strlen(CF_LATITUDE_STD_NAME), CF_LATITUDE_STD_NAME);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarLatID, CF_LNG_NAME,
-                     strlen(CF_LATITUDE_LNG_NAME), CF_LATITUDE_LNG_NAME );
+    status =
+        nc_put_att_text(cdfid, nVarLatID, CF_LNG_NAME,
+                        strlen(CF_LATITUDE_LNG_NAME), CF_LATITUDE_LNG_NAME);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarLatID, CF_UNITS,
-                     strlen(CF_DEGREES_NORTH), CF_DEGREES_NORTH );
+    status = nc_put_att_text(cdfid, nVarLatID, CF_UNITS,
+                             strlen(CF_DEGREES_NORTH), CF_DEGREES_NORTH);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarLonID, CF_STD_NAME,
-                     strlen(CF_LONGITUDE_STD_NAME), CF_LONGITUDE_STD_NAME );
+    status =
+        nc_put_att_text(cdfid, nVarLonID, CF_STD_NAME,
+                        strlen(CF_LONGITUDE_STD_NAME), CF_LONGITUDE_STD_NAME);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarLonID, CF_LNG_NAME,
-                     strlen(CF_LONGITUDE_LNG_NAME), CF_LONGITUDE_LNG_NAME );
+    status =
+        nc_put_att_text(cdfid, nVarLonID, CF_LNG_NAME,
+                        strlen(CF_LONGITUDE_LNG_NAME), CF_LONGITUDE_LNG_NAME);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarLonID, CF_UNITS,
-                     strlen(CF_DEGREES_EAST), CF_DEGREES_EAST );
+    status = nc_put_att_text(cdfid, nVarLonID, CF_UNITS,
+                             strlen(CF_DEGREES_EAST), CF_DEGREES_EAST);
     NCDF_ERR(status);
 }
 
@@ -3594,44 +3707,53 @@ void NCDFWriteLonLatVarsAttributes(int cdfid,
 /************************************************************************/
 
 void NCDFWriteXYVarsAttributes(int cdfid, int nVarXID, int nVarYID,
-                                      OGRSpatialReference* poSRS)
+                               OGRSpatialReference *poSRS)
 {
     int status;
-    const char *pszUnits = NULL;
+    char *pszUnits = NULL;
     const char *pszUnitsToWrite = "";
 
-    pszUnits = poSRS->GetAttrValue("PROJCS|UNIT",1);
-    if ( pszUnits == NULL || EQUAL(pszUnits,"1") )
+    const double dfUnits = poSRS->GetLinearUnits(&pszUnits);
+    if( fabs(dfUnits - 1.0) < 1e-15 || pszUnits == NULL ||
+        EQUAL(pszUnits, "m") || EQUAL(pszUnits, "metre") )
+    {
         pszUnitsToWrite = "m";
-    else if ( EQUAL(pszUnits,"1000") )
+    }
+    else if( fabs(dfUnits - 1000.0) < 1e-15 )
+    {
         pszUnitsToWrite = "km";
+    }
+    else if( fabs(dfUnits - CPLAtof(SRS_UL_US_FOOT_CONV)) < 1e-15 ||
+             EQUAL(pszUnits, SRS_UL_US_FOOT) ||
+             EQUAL(pszUnits, "US survey foot") )
+    {
+        pszUnitsToWrite = "US_survey_foot";
+    }
 
-    status = nc_put_att_text( cdfid, nVarXID, CF_STD_NAME,
-                        strlen(CF_PROJ_X_COORD),
-                        CF_PROJ_X_COORD );
+    status = nc_put_att_text(cdfid, nVarXID, CF_STD_NAME,
+                             strlen(CF_PROJ_X_COORD), CF_PROJ_X_COORD);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarXID, CF_LNG_NAME,
-                        strlen(CF_PROJ_X_COORD_LONG_NAME),
-                        CF_PROJ_X_COORD_LONG_NAME );
+    status = nc_put_att_text(cdfid, nVarXID, CF_LNG_NAME,
+                             strlen(CF_PROJ_X_COORD_LONG_NAME),
+                             CF_PROJ_X_COORD_LONG_NAME);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarXID, CF_UNITS,
-                        strlen(pszUnitsToWrite), pszUnitsToWrite );
+    status = nc_put_att_text(cdfid, nVarXID, CF_UNITS,
+                             strlen(pszUnitsToWrite), pszUnitsToWrite);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarYID, CF_STD_NAME,
-                        strlen(CF_PROJ_Y_COORD),
-                        CF_PROJ_Y_COORD );
+    status = nc_put_att_text(cdfid, nVarYID, CF_STD_NAME,
+                             strlen(CF_PROJ_Y_COORD), CF_PROJ_Y_COORD);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarYID, CF_LNG_NAME,
-                        strlen(CF_PROJ_Y_COORD_LONG_NAME),
-                        CF_PROJ_Y_COORD_LONG_NAME );
+    status = nc_put_att_text(cdfid, nVarYID, CF_LNG_NAME,
+                             strlen(CF_PROJ_Y_COORD_LONG_NAME),
+                             CF_PROJ_Y_COORD_LONG_NAME);
     NCDF_ERR(status);
 
-    status = nc_put_att_text( cdfid, nVarYID, CF_UNITS,
-                        strlen(pszUnitsToWrite), pszUnitsToWrite );
+    status = nc_put_att_text(cdfid, nVarYID, CF_UNITS, strlen(pszUnitsToWrite),
+                             pszUnitsToWrite);
     NCDF_ERR(status);
 }
 
@@ -3640,10 +3762,9 @@ void NCDFWriteXYVarsAttributes(int cdfid, int nVarXID, int nVarYID,
 /************************************************************************/
 
 CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
-                                         void * pProgressData )
+                                         void *pProgressData )
 {
-    int NCDFVarID = -1;
-    const char  *pszValue = NULL;
+    const char *pszValue = NULL;
     CPLErr eErr = CE_None;
 
     bool bWriteGridMapping = false;
@@ -3653,374 +3774,391 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
     bool bWriteGeoTransform = false;
 
     nc_type eLonLatType = NC_NAT;
-    int nVarLonID=-1, nVarLatID=-1;
-    int nVarXID=-1, nVarYID=-1;
+    int nVarLonID = -1;
+    int nVarLatID = -1;
+    int nVarXID = -1;
+    int nVarYID = -1;
 
-    /* For GEOLOCATION information */
-    const char *pszDSName = NULL;
-    GDALDatasetH     hDS_X = NULL;
-    GDALRasterBandH  hBand_X = NULL;
-    GDALDatasetH     hDS_Y = NULL;
-    GDALRasterBandH  hBand_Y = NULL;
-    int nBand;
+    // For GEOLOCATION information.
+    GDALDatasetH hDS_X = NULL;
+    GDALRasterBandH hBand_X = NULL;
+    GDALDatasetH hDS_Y = NULL;
+    GDALRasterBandH hBand_Y = NULL;
 
     bAddedProjectionVars = true;
 
-    char *pszWKT = (char *) pszProjection;
+    char *pszWKT = (char *)pszProjection;
     OGRSpatialReference oSRS;
-    oSRS.importFromWkt( &pszWKT );
+    oSRS.importFromWkt(&pszWKT);
 
     if( oSRS.IsProjected() )
         bIsProjected = true;
     else if( oSRS.IsGeographic() )
         bIsGeographic = true;
 
-    CPLDebug( "GDAL_netCDF", "SetProjection, WKT now = [%s]\nprojected: %d geographic: %d",
-              pszProjection ? pszProjection : "(null)",
-              static_cast<int>(bIsProjected),
-              static_cast<int>(bIsGeographic) );
+    CPLDebug("GDAL_netCDF",
+             "SetProjection, WKT now = [%s]\nprojected: %d geographic: %d",
+             pszProjection ? pszProjection : "(null)",
+             static_cast<int>(bIsProjected),
+             static_cast<int>(bIsGeographic));
 
-    if ( ! bSetGeoTransform )
-        CPLDebug( "GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
-                  "but GeoTransform has not yet been defined!" );
+    if( !bSetGeoTransform )
+        CPLDebug("GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
+                 "but GeoTransform has not yet been defined!");
 
-    if ( ! bSetProjection )
-        CPLDebug( "GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
-                  "but Projection has not yet been defined!" );
+    if( !bSetProjection )
+        CPLDebug("GDAL_netCDF", "netCDFDataset::AddProjectionVars() called, "
+                 "but Projection has not yet been defined!");
 
-    /* check GEOLOCATION information */
+    // Check GEOLOCATION information.
     char **papszGeolocationInfo = GetMetadata("GEOLOCATION");
-    if ( papszGeolocationInfo != NULL ) {
-
-        /* look for geolocation datasets */
-        pszDSName = CSLFetchNameValue( papszGeolocationInfo, "X_DATASET" );
+    if( papszGeolocationInfo != NULL )
+    {
+        // Look for geolocation datasets.
+        const char *pszDSName =
+            CSLFetchNameValue(papszGeolocationInfo, "X_DATASET");
         if( pszDSName != NULL )
-            hDS_X = GDALOpenShared( pszDSName, GA_ReadOnly );
-        pszDSName = CSLFetchNameValue( papszGeolocationInfo, "Y_DATASET" );
+            hDS_X = GDALOpenShared(pszDSName, GA_ReadOnly);
+        pszDSName = CSLFetchNameValue(papszGeolocationInfo, "Y_DATASET");
         if( pszDSName != NULL )
-            hDS_Y = GDALOpenShared( pszDSName, GA_ReadOnly );
+            hDS_Y = GDALOpenShared(pszDSName, GA_ReadOnly);
 
-        if ( hDS_X != NULL && hDS_Y != NULL ) {
-            nBand = MAX(1,atoi(CSLFetchNameValueDef( papszGeolocationInfo,
-                                                     "X_BAND", "0" )));
-            hBand_X = GDALGetRasterBand( hDS_X, nBand );
-            nBand = MAX(1,atoi(CSLFetchNameValueDef( papszGeolocationInfo,
-                                                     "Y_BAND", "0" )));
-            hBand_Y = GDALGetRasterBand( hDS_Y, nBand );
+        if( hDS_X != NULL && hDS_Y != NULL )
+        {
+            int nBand = std::max(1, atoi(CSLFetchNameValueDef(
+                                        papszGeolocationInfo, "X_BAND", "0")));
+            hBand_X = GDALGetRasterBand(hDS_X, nBand);
+            nBand = std::max(1, atoi(CSLFetchNameValueDef(papszGeolocationInfo,
+                                                          "Y_BAND", "0")));
+            hBand_Y = GDALGetRasterBand(hDS_Y, nBand);
 
             // If geoloc bands are found, do basic validation based on their
             // dimensions.
-            if ( hBand_X != NULL && hBand_Y != NULL ) {
-
-                int nXSize_XBand = GDALGetRasterXSize( hDS_X );
-                int nYSize_XBand = GDALGetRasterYSize( hDS_X );
-                int nXSize_YBand = GDALGetRasterXSize( hDS_Y );
-                int nYSize_YBand = GDALGetRasterYSize( hDS_Y );
+            if( hBand_X != NULL && hBand_Y != NULL )
+            {
+                int nXSize_XBand = GDALGetRasterXSize(hDS_X);
+                int nYSize_XBand = GDALGetRasterYSize(hDS_X);
+                int nXSize_YBand = GDALGetRasterXSize(hDS_Y);
+                int nYSize_YBand = GDALGetRasterYSize(hDS_Y);
 
-                /* TODO 1D geolocation arrays not implemented */
-                if ( (nYSize_XBand == 1) && (nYSize_YBand == 1) ) {
+                // TODO 1D geolocation arrays not implemented.
+                if( nYSize_XBand == 1 && nYSize_YBand == 1 )
+                {
                     bHasGeoloc = false;
-                    CPLDebug( "GDAL_netCDF",
-                              "1D GEOLOCATION arrays not supported yet" );
+                    CPLDebug("GDAL_netCDF",
+                              "1D GEOLOCATION arrays not supported yet");
                 }
-                /* 2D bands must have same sizes as the raster bands */
-                else if ( (nXSize_XBand != nRasterXSize) ||
-                          (nYSize_XBand != nRasterYSize) ||
-                          (nXSize_YBand != nRasterXSize) ||
-                          (nYSize_YBand != nRasterYSize) ) {
+                // 2D bands must have same sizes as the raster bands.
+                else if( nXSize_XBand != nRasterXSize ||
+                         nYSize_XBand != nRasterYSize ||
+                         nXSize_YBand != nRasterXSize ||
+                         nYSize_YBand != nRasterYSize )
+                {
                     bHasGeoloc = false;
-                    CPLDebug( "GDAL_netCDF",
-                              "GEOLOCATION array sizes (%dx%d %dx%d) differ "
-                              "from raster (%dx%d), not supported",
-                              nXSize_XBand, nYSize_XBand, nXSize_YBand, nYSize_YBand,
-                              nRasterXSize, nRasterYSize );
+                    CPLDebug("GDAL_netCDF",
+                             "GEOLOCATION array sizes (%dx%d %dx%d) differ "
+                             "from raster (%dx%d), not supported",
+                             nXSize_XBand, nYSize_XBand, nXSize_YBand,
+                             nYSize_YBand, nRasterXSize, nRasterYSize);
                 }
-                /* 2D bands are only supported for projected SRS (see CF 5.6) */
-                else if ( ! bIsProjected ) {
+                // 2D bands are only supported for projected SRS (see CF 5.6).
+                else if( !bIsProjected )
+                {
                     bHasGeoloc = false;
-                    CPLDebug( "GDAL_netCDF",
-                              "2D GEOLOCATION arrays only supported for projected SRS" );
+                    CPLDebug("GDAL_netCDF",
+                             "2D GEOLOCATION arrays only supported for projected SRS");
                 }
-                else {
+                else
+                {
                     bHasGeoloc = true;
-                    CPLDebug( "GDAL_netCDF",
-                              "dataset has GEOLOCATION information, will try to write it" );
+                    CPLDebug("GDAL_netCDF",
+                             "dataset has GEOLOCATION information, will try to write it");
                 }
             }
         }
     }
 
-    /* process projection options */
+    // Process projection options.
     if( bIsProjected )
     {
-        bool bIsCfProjection = NCDFIsCfProjection( oSRS.GetAttrValue( "PROJECTION" ) );
+        bool bIsCfProjection =
+            NCDFIsCfProjection(oSRS.GetAttrValue("PROJECTION"));
         bWriteGridMapping = true;
-        bWriteGDALTags = CPL_TO_BOOL(CSLFetchBoolean( papszCreationOptions, "WRITE_GDAL_TAGS", TRUE ));
-        /* force WRITE_GDAL_TAGS if is not a CF projection */
-        if ( ! bWriteGDALTags && ! bIsCfProjection )
+        bWriteGDALTags = CPL_TO_BOOL(
+            CSLFetchBoolean(papszCreationOptions, "WRITE_GDAL_TAGS", TRUE));
+        // Force WRITE_GDAL_TAGS if is not a CF projection.
+        if( !bWriteGDALTags && !bIsCfProjection )
             bWriteGDALTags = true;
-        if ( bWriteGDALTags )
+        if( bWriteGDALTags )
             bWriteGeoTransform = true;
 
-        /* write lon/lat : default is NO, except if has geolocation */
-        /* with IF_NEEDED : write if has geoloc or is not CF projection */
-        pszValue = CSLFetchNameValue( papszCreationOptions,"WRITE_LONLAT" );
-        if ( pszValue ) {
-            if ( EQUAL( pszValue, "IF_NEEDED" ) ) {
-                bWriteLonLat = ( bHasGeoloc || ! bIsCfProjection );
+        // Write lon/lat: default is NO, except if has geolocation.
+        // With IF_NEEDED: write if has geoloc or is not CF projection.
+        pszValue = CSLFetchNameValue(papszCreationOptions, "WRITE_LONLAT");
+        if( pszValue )
+        {
+            if( EQUAL(pszValue, "IF_NEEDED") )
+            {
+                bWriteLonLat = bHasGeoloc || !bIsCfProjection;
+            }
+            else
+            {
+                bWriteLonLat = CPLTestBool(pszValue);
             }
-            else bWriteLonLat = CPLTestBool( pszValue );
         }
         else
+        {
             bWriteLonLat = bHasGeoloc;
+        }
 
-        /* save value of pszCFCoordinates for later */
-        if ( bWriteLonLat ) {
-            pszCFCoordinates = CPLStrdup( NCDF_LONLAT );
+        // Save value of pszCFCoordinates for later.
+        if( bWriteLonLat )
+        {
+            pszCFCoordinates = CPLStrdup(NCDF_LONLAT);
         }
 
         eLonLatType = NC_FLOAT;
-        pszValue =  CSLFetchNameValueDef(papszCreationOptions,"TYPE_LONLAT", "FLOAT");
-        if ( EQUAL(pszValue, "DOUBLE" ) )
+        pszValue =
+            CSLFetchNameValueDef(papszCreationOptions, "TYPE_LONLAT", "FLOAT");
+        if( EQUAL(pszValue, "DOUBLE") )
             eLonLatType = NC_DOUBLE;
     }
     else
     {
-        /* files without a Datum will not have a grid_mapping variable and geographic information */
+        // Files without a Datum will not have a grid_mapping variable and
+        // geographic information.
         bWriteGridMapping = bIsGeographic;
 
-        bWriteGDALTags = CPL_TO_BOOL(CSLFetchBoolean( papszCreationOptions, "WRITE_GDAL_TAGS", bWriteGridMapping ));
-        if ( bWriteGDALTags )
+        bWriteGDALTags = CPL_TO_BOOL(CSLFetchBoolean(
+            papszCreationOptions, "WRITE_GDAL_TAGS", bWriteGridMapping));
+        if(bWriteGDALTags)
             bWriteGeoTransform = true;
 
-        pszValue =  CSLFetchNameValueDef(papszCreationOptions,"WRITE_LONLAT", "YES");
-        if ( EQUAL( pszValue, "IF_NEEDED" ) )
+        pszValue =
+            CSLFetchNameValueDef(papszCreationOptions, "WRITE_LONLAT", "YES");
+        if( EQUAL(pszValue, "IF_NEEDED") )
             bWriteLonLat = true;
         else
-            bWriteLonLat = CPLTestBool( pszValue );
-        /*  Don't write lon/lat if no source geotransform */
-        if ( ! bSetGeoTransform )
+            bWriteLonLat = CPLTestBool(pszValue);
+        //  Don't write lon/lat if no source geotransform.
+        if( !bSetGeoTransform )
             bWriteLonLat = false;
-        /* If we don't write lon/lat, set dimnames to X/Y and write gdal tags*/
-        if ( ! bWriteLonLat ) {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "creating geographic file without lon/lat values!");
-            if ( bSetGeoTransform ) {
-                bWriteGDALTags = true; // Not desirable if no geotransform.
+        // If we don't write lon/lat, set dimnames to X/Y and write gdal tags.
+        if( !bWriteLonLat )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "creating geographic file without lon/lat values!");
+            if( bSetGeoTransform )
+            {
+                bWriteGDALTags = true;  // Not desirable if no geotransform.
                 bWriteGeoTransform = true;
             }
         }
 
         eLonLatType = NC_DOUBLE;
-        pszValue
-            = CSLFetchNameValueDef(
-                papszCreationOptions, "TYPE_LONLAT", "DOUBLE");
-        if ( EQUAL(pszValue, "FLOAT" ) )
+        pszValue =
+            CSLFetchNameValueDef(papszCreationOptions, "TYPE_LONLAT", "DOUBLE");
+        if( EQUAL(pszValue, "FLOAT") )
             eLonLatType = NC_FLOAT;
     }
 
-    /* make sure we write grid_mapping if we need to write GDAL tags */
-    if ( bWriteGDALTags ) bWriteGridMapping = true;
+    // Make sure we write grid_mapping if we need to write GDAL tags.
+    if( bWriteGDALTags ) bWriteGridMapping = true;
 
-    /* bottom-up value: new driver is bottom-up by default */
-    /* override with WRITE_BOTTOMUP */
-    bBottomUp = CPL_TO_BOOL(CSLFetchBoolean( papszCreationOptions, "WRITE_BOTTOMUP", TRUE ));
+    // bottom-up value: new driver is bottom-up by default.
+    // Override with WRITE_BOTTOMUP.
+    bBottomUp = CPL_TO_BOOL(
+        CSLFetchBoolean(papszCreationOptions, "WRITE_BOTTOMUP", TRUE));
 
-    CPLDebug( "GDAL_netCDF",
-              "bIsProjected=%d bIsGeographic=%d bWriteGridMapping=%d "
-              "bWriteGDALTags=%d bWriteLonLat=%d bBottomUp=%d bHasGeoloc=%d",
-              static_cast<int>(bIsProjected),
-              static_cast<int>(bIsGeographic),
-              static_cast<int>(bWriteGridMapping),
-              static_cast<int>(bWriteGDALTags),
-              static_cast<int>(bWriteLonLat),
-              static_cast<int>(bBottomUp),
-              static_cast<int>(bHasGeoloc) );
+    CPLDebug("GDAL_netCDF",
+             "bIsProjected=%d bIsGeographic=%d bWriteGridMapping=%d "
+             "bWriteGDALTags=%d bWriteLonLat=%d bBottomUp=%d bHasGeoloc=%d",
+             static_cast<int>(bIsProjected),
+             static_cast<int>(bIsGeographic),
+             static_cast<int>(bWriteGridMapping),
+             static_cast<int>(bWriteGDALTags),
+             static_cast<int>(bWriteLonLat),
+             static_cast<int>(bBottomUp),
+             static_cast<int>(bHasGeoloc));
 
-    /* exit if nothing to do */
-    if ( !bIsProjected && !bWriteLonLat )
+    // Exit if nothing to do.
+    if( !bIsProjected && !bWriteLonLat )
         return CE_None;
 
-/* -------------------------------------------------------------------- */
-/*      Define dimension names                                          */
-/* -------------------------------------------------------------------- */
-    /* make sure we are in define mode */
-    SetDefineMode( true );
+    // Define dimension names.
 
+    // Make sure we are in define mode.
+    SetDefineMode(true);
 
-/* -------------------------------------------------------------------- */
-/*      Rename dimensions if lon/lat                                    */
-/* -------------------------------------------------------------------- */
-    if( ! bIsProjected )
+    // Rename dimensions if lon/lat.
+    if( !bIsProjected )
     {
-        /* rename dims to lat/lon */
-        papszDimName.Clear(); //if we add other dims one day, this has to change
-        papszDimName.AddString( NCDF_DIMNAME_LAT );
-        papszDimName.AddString( NCDF_DIMNAME_LON );
+        // Rename dims to lat/lon.
+        papszDimName.Clear();  // If we add other dims one day, this has to change
+        papszDimName.AddString(NCDF_DIMNAME_LAT);
+        papszDimName.AddString(NCDF_DIMNAME_LON);
 
-        int status = nc_rename_dim(cdfid, nYDimID, NCDF_DIMNAME_LAT );
+        int status = nc_rename_dim(cdfid, nYDimID, NCDF_DIMNAME_LAT);
         NCDF_ERR(status);
-        status = nc_rename_dim(cdfid, nXDimID, NCDF_DIMNAME_LON );
+        status = nc_rename_dim(cdfid, nXDimID, NCDF_DIMNAME_LON);
         NCDF_ERR(status);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write projection attributes                                     */
-/* -------------------------------------------------------------------- */
+    // Write projection attributes.
     if( bWriteGridMapping )
     {
-        NCDFVarID = NCDFWriteSRSVariable(cdfid, &oSRS, &pszCFProjection,
-                                         bWriteGDALTags);
+        const int NCDFVarID = NCDFWriteSRSVariable(
+            cdfid, &oSRS, &pszCFProjection, bWriteGDALTags);
         if( NCDFVarID < 0 )
             return CE_Failure;
 
-        /*  Optional GDAL custom projection tags */
-        if ( bWriteGDALTags ) {
+        // Optional GDAL custom projection tags.
+        if( bWriteGDALTags )
+        {
             CPLString osGeoTransform;
-            for( int i=0; i<6; i++ ) {
-                osGeoTransform += CPLSPrintf("%.16g ",
-                         adfGeoTransform[i] );
+            for( int i = 0; i < 6; i++ )
+            {
+                osGeoTransform += CPLSPrintf("%.16g ", adfGeoTransform[i]);
             }
-            CPLDebug( "GDAL_netCDF", "szGeoTransform = %s", osGeoTransform.c_str() );
+            CPLDebug("GDAL_netCDF", "szGeoTransform = %s",
+                     osGeoTransform.c_str());
 
-            // if ( strlen(pszProj4Defn) > 0 ) {
-            //     nc_put_att_text( cdfid, NCDFVarID, "proj4",
-            //                      strlen( pszProj4Defn ), pszProj4Defn );
+            // if( strlen(pszProj4Defn) > 0 ) {
+            //     nc_put_att_text(cdfid, NCDFVarID, "proj4",
+            //                      strlen(pszProj4Defn), pszProj4Defn);
             // }
 
-            /* for now write the geotransform for back-compat or else
-               the old (1.8.1) driver overrides the CF geotransform with
-               empty values from dfNN, dfSN, dfEE, dfWE; */
-            /* TODO: fix this in 1.8 branch, and then remove this here */
-            if ( bWriteGeoTransform && bSetGeoTransform ) {
-              {
-                int status = nc_put_att_text( cdfid, NCDFVarID, NCDF_GEOTRANSFORM,
-                                 osGeoTransform.size(),
-                                 osGeoTransform.c_str() );
-                NCDF_ERR(status);
-              }
+            // For now, write the geotransform for back-compat or else
+            // the old (1.8.1) driver overrides the CF geotransform with
+            // empty values from dfNN, dfSN, dfEE, dfWE;
+
+            // TODO: fix this in 1.8 branch, and then remove this here.
+            if( bWriteGeoTransform && bSetGeoTransform )
+            {
+                {
+                    const int status = nc_put_att_text(
+                        cdfid, NCDFVarID, NCDF_GEOTRANSFORM,
+                        osGeoTransform.size(), osGeoTransform.c_str());
+                    NCDF_ERR(status);
+                }
             }
         }
 
-        /* write projection variable to band variable */
-        /* need to call later if there are no bands */
+        // Write projection variable to band variable.
+        // Need to call later if there are no bands.
         AddGridMappingRef();
+    }  // end if( bWriteGridMapping )
 
-    }  /* end if( bWriteGridMapping ) */
-
-    pfnProgress( 0.10, NULL, pProgressData );
+    pfnProgress(0.10, NULL, pProgressData);
 
-/* -------------------------------------------------------------------- */
-/*      Write CF Projection vars                                        */
-/* -------------------------------------------------------------------- */
+    // Write CF Projection vars.
 
-/* -------------------------------------------------------------------- */
-/*      Write X/Y attributes                                            */
-/* -------------------------------------------------------------------- */
+    // Write X/Y attributes.
     if( bIsProjected )
     {
-        /* X */
+        // X
         int anXDims[1];
         anXDims[0] = nXDimID;
-        CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
-                  cdfid, CF_PROJ_X_VAR_NAME, NC_DOUBLE );
-        int status = nc_def_var( cdfid, CF_PROJ_X_VAR_NAME, NC_DOUBLE,
-                             1, anXDims, &nVarXID );
+        CPLDebug("GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                 cdfid, CF_PROJ_X_VAR_NAME, NC_DOUBLE);
+        int status = nc_def_var(cdfid, CF_PROJ_X_VAR_NAME, NC_DOUBLE,
+                                1, anXDims, &nVarXID);
         NCDF_ERR(status);
 
-        /* Y */
+        // Y
         int anYDims[1];
         anYDims[0] = nYDimID;
-        CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d)",
-                  cdfid, CF_PROJ_Y_VAR_NAME, NC_DOUBLE );
-        status = nc_def_var( cdfid, CF_PROJ_Y_VAR_NAME, NC_DOUBLE,
-                             1, anYDims, &nVarYID );
+        CPLDebug("GDAL_netCDF", "nc_def_var(%d,%s,%d)",
+                 cdfid, CF_PROJ_Y_VAR_NAME, NC_DOUBLE);
+        status = nc_def_var(cdfid, CF_PROJ_Y_VAR_NAME, NC_DOUBLE,
+                            1, anYDims, &nVarYID);
         NCDF_ERR(status);
 
         NCDFWriteXYVarsAttributes(cdfid, nVarXID, nVarYID, &oSRS);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write lat/lon attributes if needed                              */
-/* -------------------------------------------------------------------- */
-    if ( bWriteLonLat ) {
-        int *panLatDims=NULL;
-        int *panLonDims=NULL;
-        int nLatDims=-1;
-        int nLonDims=-1;
+    // Write lat/lon attributes if needed.
+    if( bWriteLonLat )
+    {
+        int *panLatDims = NULL;
+        int *panLonDims = NULL;
+        int nLatDims = -1;
+        int nLonDims = -1;
 
-        /* get information */
-        if ( bHasGeoloc ) { /* geoloc */
+        // Get information.
+        if( bHasGeoloc )
+        {
+            // Geoloc
             nLatDims = 2;
-            panLatDims = (int *) CPLCalloc( nLatDims, sizeof( int ) );
+            panLatDims = static_cast<int *>(CPLCalloc(nLatDims, sizeof(int)));
             panLatDims[0] = nYDimID;
             panLatDims[1] = nXDimID;
             nLonDims = 2;
-            panLonDims = (int *) CPLCalloc( nLonDims, sizeof( int ) );
+            panLonDims = static_cast<int *>(CPLCalloc(nLonDims, sizeof(int)));
             panLonDims[0] = nYDimID;
             panLonDims[1] = nXDimID;
         }
-        else if ( bIsProjected ) { /* projected */
+        else if( bIsProjected )
+        {
+            // Projected
             nLatDims = 2;
-            panLatDims = (int *) CPLCalloc( nLatDims, sizeof( int ) );
-            panLatDims[0] =  nYDimID;
-            panLatDims[1] =  nXDimID;
+            panLatDims = static_cast<int *>(CPLCalloc(nLatDims, sizeof(int)));
+            panLatDims[0] = nYDimID;
+            panLatDims[1] = nXDimID;
             nLonDims = 2;
-            panLonDims = (int *) CPLCalloc( nLonDims, sizeof( int ) );
-            panLonDims[0] =  nYDimID;
-            panLonDims[1] =  nXDimID;
+            panLonDims = static_cast<int *>(CPLCalloc(nLonDims, sizeof(int)));
+            panLonDims[0] = nYDimID;
+            panLonDims[1] = nXDimID;
         }
-        else {  /* geographic */
+        else
+        {
+            // Geographic
             nLatDims = 1;
-            panLatDims = (int *) CPLCalloc( nLatDims, sizeof( int ) );
+            panLatDims = static_cast<int *>(CPLCalloc(nLatDims, sizeof(int)));
             panLatDims[0] = nYDimID;
             nLonDims = 1;
-            panLonDims = (int *) CPLCalloc( nLonDims, sizeof( int ) );
+            panLonDims = static_cast<int *>(CPLCalloc(nLonDims, sizeof(int)));
             panLonDims[0] = nXDimID;
         }
 
-        /* def vars and attributes */
-        int status = nc_def_var( cdfid, CF_LATITUDE_VAR_NAME, eLonLatType,
-                             nLatDims, panLatDims, &nVarLatID );
-        CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d,%d,-,-) got id %d",
-                  cdfid, CF_LATITUDE_VAR_NAME, eLonLatType, nLatDims, nVarLatID );
+        // Def vars and attributes.
+        int status = nc_def_var(cdfid, CF_LATITUDE_VAR_NAME, eLonLatType,
+                                nLatDims, panLatDims, &nVarLatID);
+        CPLDebug("GDAL_netCDF", "nc_def_var(%d,%s,%d,%d,-,-) got id %d",
+                 cdfid, CF_LATITUDE_VAR_NAME, eLonLatType, nLatDims, nVarLatID);
         NCDF_ERR(status);
-        DefVarDeflate( nVarLatID, false ); // don't set chunking
+        DefVarDeflate(nVarLatID, false);  // Don't set chunking.
 
-        status = nc_def_var( cdfid, CF_LONGITUDE_VAR_NAME, eLonLatType,
-                             nLonDims, panLonDims, &nVarLonID );
-        CPLDebug( "GDAL_netCDF", "nc_def_var(%d,%s,%d,%d,-,-) got id %d",
-                  cdfid, CF_LONGITUDE_VAR_NAME, eLonLatType, nLatDims, nVarLonID );
+        status = nc_def_var(cdfid, CF_LONGITUDE_VAR_NAME, eLonLatType,
+                            nLonDims, panLonDims, &nVarLonID);
+        CPLDebug("GDAL_netCDF", "nc_def_var(%d,%s,%d,%d,-,-) got id %d",
+                 cdfid, CF_LONGITUDE_VAR_NAME, eLonLatType, nLatDims, nVarLonID);
         NCDF_ERR(status);
-        DefVarDeflate( nVarLonID, false ); // don't set chunking
+        DefVarDeflate(nVarLonID, false);  // Don't set chunking.
 
         NCDFWriteLonLatVarsAttributes(cdfid, nVarLonID, nVarLatID);
 
-        /* free data */
-        CPLFree( panLatDims );
-        CPLFree( panLonDims );
+        CPLFree(panLatDims);
+        CPLFree(panLonDims);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Get projection values                                           */
-/* -------------------------------------------------------------------- */
+    // Get projection values.
 
     double dfX0 = 0.0;
     double dfDX = 0.0;
     double dfY0 = 0.0;
     double dfDY = 0.0;
     double *padLonVal = NULL;
-    double *padLatVal = NULL; /* should use float for projected, save space */
+    double *padLatVal = NULL;
 
     if( bIsProjected )
     {
-        // const char  *pszProjection;
         OGRSpatialReference *poLatLonSRS = NULL;
         OGRCoordinateTransformation *poTransform = NULL;
 
-        char *pszWKT2 = (char *) pszProjection;
+        char *pszWKT2 = (char *)pszProjection;
         OGRSpatialReference oSRS2;
-        oSRS2.importFromWkt( &pszWKT2 );
+        oSRS2.importFromWkt(&pszWKT2);
 
         double *padYVal = NULL;
         double *padXVal = NULL;
@@ -4029,294 +4167,305 @@ CPLErr netCDFDataset::AddProjectionVars( GDALProgressFunc pfnProgress,
         size_t startY[1];
         size_t countY[1];
 
-        CPLDebug("GDAL_netCDF", "Getting (X,Y) values" );
+        CPLDebug("GDAL_netCDF", "Getting (X,Y) values");
 
-        padXVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
-        padYVal = (double *) CPLMalloc( nRasterYSize * sizeof( double ) );
+        padXVal =
+            static_cast<double *>(CPLMalloc(nRasterXSize * sizeof(double)));
+        padYVal =
+            static_cast<double *>(CPLMalloc(nRasterYSize * sizeof(double)));
 
-/* -------------------------------------------------------------------- */
-/*      Get Y values                                                    */
-/* -------------------------------------------------------------------- */
-        if ( ! bBottomUp )
+        // Get Y values.
+        if( !bBottomUp )
             dfY0 = adfGeoTransform[3];
-        else /* invert latitude values */
-            dfY0 = adfGeoTransform[3] + ( adfGeoTransform[5] * nRasterYSize );
+        else  // Invert latitude values.
+            dfY0 = adfGeoTransform[3] + (adfGeoTransform[5] * nRasterYSize);
         dfDY = adfGeoTransform[5];
 
-        for( int j=0; j<nRasterYSize; j++ ) {
-            /* The data point is centered inside the pixel */
-            if ( ! bBottomUp )
-                padYVal[j] = dfY0 + (j+0.5)*dfDY ;
-            else /* invert latitude values */
-                padYVal[j] = dfY0 - (j+0.5)*dfDY ;
+        for( int j = 0; j < nRasterYSize; j++ )
+        {
+            // The data point is centered inside the pixel.
+            if( !bBottomUp )
+                padYVal[j] = dfY0 + (j + 0.5) * dfDY;
+            else  // Invert latitude values.
+                padYVal[j] = dfY0 - (j + 0.5) * dfDY;
         }
         startX[0] = 0;
         countX[0] = nRasterXSize;
 
-/* -------------------------------------------------------------------- */
-/*      Get X values                                                    */
-/* -------------------------------------------------------------------- */
+        // Get X values.
         dfX0 = adfGeoTransform[0];
         dfDX = adfGeoTransform[1];
 
-        for( int i=0; i<nRasterXSize; i++ ) {
-            /* The data point is centered inside the pixel */
-            padXVal[i] = dfX0 + (i+0.5)*dfDX ;
+        for( int i = 0; i < nRasterXSize; i++ )
+        {
+            // The data point is centered inside the pixel.
+            padXVal[i] = dfX0 + (i + 0.5) * dfDX;
         }
         startY[0] = 0;
         countY[0] = nRasterYSize;
 
-/* -------------------------------------------------------------------- */
-/*      Write X/Y values                                                */
-/* -------------------------------------------------------------------- */
-        /* make sure we are in data mode */
-        SetDefineMode( false );
+        // Write X/Y values.
 
-        CPLDebug("GDAL_netCDF", "Writing X values" );
-        int status = nc_put_vara_double( cdfid, nVarXID, startX,
-                                     countX, padXVal);
-        NCDF_ERR(status);
+        // Make sure we are in data mode.
+        SetDefineMode(false);
 
-        CPLDebug("GDAL_netCDF", "Writing Y values" );
-        status = nc_put_vara_double( cdfid, nVarYID, startY,
-                                     countY, padYVal);
+        CPLDebug("GDAL_netCDF", "Writing X values");
+        int status =
+            nc_put_vara_double(cdfid, nVarXID, startX, countX, padXVal);
         NCDF_ERR(status);
 
-        pfnProgress( 0.20, NULL, pProgressData );
+        CPLDebug("GDAL_netCDF", "Writing Y values");
+        status = nc_put_vara_double(cdfid, nVarYID, startY, countY, padYVal);
+        NCDF_ERR(status);
 
+        pfnProgress(0.20, NULL, pProgressData);
 
-/* -------------------------------------------------------------------- */
-/*      Write lon/lat arrays (CF coordinates) if requested              */
-/* -------------------------------------------------------------------- */
+        // Write lon/lat arrays (CF coordinates) if requested.
 
-        /* Get OGR transform if GEOLOCATION is not available */
-        if ( bWriteLonLat && !bHasGeoloc ) {
+        // Get OGR transform if GEOLOCATION is not available.
+        if( bWriteLonLat && !bHasGeoloc )
+        {
             poLatLonSRS = oSRS2.CloneGeogCS();
-            if ( poLatLonSRS != NULL )
-                poTransform = OGRCreateCoordinateTransformation( &oSRS2, poLatLonSRS );
-            /* if no OGR transform, then don't write CF lon/lat */
-            if( poTransform == NULL ) {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Unable to get Coordinate Transform" );
+            if( poLatLonSRS != NULL )
+                poTransform =
+                    OGRCreateCoordinateTransformation(&oSRS2, poLatLonSRS);
+            // If no OGR transform, then don't write CF lon/lat.
+            if( poTransform == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Unable to get Coordinate Transform");
                 bWriteLonLat = false;
             }
         }
 
-        if ( bWriteLonLat )  {
-
-            if ( ! bHasGeoloc )
-                CPLDebug("GDAL_netCDF", "Transforming (X,Y)->(lon,lat)" );
+        if( bWriteLonLat )
+        {
+            if( !bHasGeoloc )
+                CPLDebug("GDAL_netCDF", "Transforming (X,Y)->(lon,lat)");
             else
-                CPLDebug("GDAL_netCDF", "writing (lon,lat) from GEOLOCATION arrays" );
+                CPLDebug("GDAL_netCDF",
+                         "Writing (lon,lat) from GEOLOCATION arrays");
 
             bool bOK = true;
             double dfProgress = 0.2;
 
-            size_t start[]={ 0, 0 };
-            size_t count[]={ 1, (size_t)nRasterXSize };
-            padLatVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
-            padLonVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
-
-            for( int j = 0; (j < nRasterYSize) && bOK && (status == NC_NOERR); j++ ) {
+            size_t start[] = { 0, 0 };
+            size_t count[] = { 1, (size_t)nRasterXSize };
+            padLatVal =
+                static_cast<double *>(CPLMalloc(nRasterXSize * sizeof(double)));
+            padLonVal =
+                static_cast<double *>(CPLMalloc(nRasterXSize * sizeof(double)));
 
+            for( int j = 0; j < nRasterYSize && bOK && status == NC_NOERR; j++ )
+            {
                 start[0] = j;
 
-                /* get values from geotransform */
-                if ( ! bHasGeoloc ) {
-                    /* fill values to transform */
-                    for( int i=0; i<nRasterXSize; i++ ) {
+                // Get values from geotransform.
+                if( !bHasGeoloc )
+                {
+                    // Fill values to transform.
+                    for( int i=0; i<nRasterXSize; i++ )
+                    {
                         padLatVal[i] = padYVal[j];
                         padLonVal[i] = padXVal[i];
                     }
 
-                    /* do the transform */
-                    bOK = CPL_TO_BOOL(poTransform->Transform( nRasterXSize,
-                                                  padLonVal, padLatVal, NULL ));
-                    if ( ! bOK ) {
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Unable to Transform (X,Y) to (lon,lat).\n" );
+                    // Do the transform.
+                    bOK = CPL_TO_BOOL(poTransform->Transform(
+                        nRasterXSize, padLonVal, padLatVal, NULL));
+                    if( !bOK )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                  "Unable to Transform (X,Y) to (lon,lat).");
                     }
                 }
-                /* get values from geoloc arrays */
-                else {
-                    eErr = GDALRasterIO( hBand_Y, GF_Read,
-                                         0, j, nRasterXSize, 1,
-                                         padLatVal, nRasterXSize, 1,
-                                         GDT_Float64, 0, 0 );
-                    if ( eErr == CE_None ) {
-                        eErr = GDALRasterIO( hBand_X, GF_Read,
-                                             0, j, nRasterXSize, 1,
-                                             padLonVal, nRasterXSize, 1,
-                                             GDT_Float64, 0, 0 );
+                // Get values from geoloc arrays.
+                else
+                {
+                    eErr = GDALRasterIO(hBand_Y, GF_Read,
+                                        0, j, nRasterXSize, 1,
+                                        padLatVal, nRasterXSize, 1,
+                                        GDT_Float64, 0, 0);
+                    if( eErr == CE_None )
+                    {
+                        eErr = GDALRasterIO(hBand_X, GF_Read,
+                                            0, j, nRasterXSize, 1,
+                                            padLonVal, nRasterXSize, 1,
+                                            GDT_Float64, 0, 0);
                     }
 
-                    if ( eErr == CE_None )
+                    if( eErr == CE_None )
+                    {
                         bOK = true;
-                    else {
+                    }
+                    else
+                    {
                         bOK = false;
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Unable to get scanline %d\n",j );
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Unable to get scanline %d", j);
                     }
                 }
 
-                /* write data */
-                if ( bOK ) {
-                    status = nc_put_vara_double( cdfid, nVarLatID, start,
-                                                 count, padLatVal);
+                // Write data.
+                if( bOK )
+                {
+                    status = nc_put_vara_double(cdfid, nVarLatID, start,
+                                                count, padLatVal);
                     NCDF_ERR(status);
-                    status = nc_put_vara_double( cdfid, nVarLonID, start,
-                                                 count, padLonVal);
+                    status = nc_put_vara_double(cdfid, nVarLonID, start,
+                                                count, padLonVal);
                     NCDF_ERR(status);
                 }
 
-                if ( (nRasterYSize/10) >0 && (j % (nRasterYSize/10) == 0) ) {
+                if( (nRasterYSize / 10) >0 && (j % (nRasterYSize / 10) == 0) )
+                {
                     dfProgress += 0.08;
-                    pfnProgress( dfProgress , NULL, pProgressData );
+                    pfnProgress(dfProgress, NULL, pProgressData);
                 }
             }
-
         }
 
-        /* Free the srs and transform objects */
-        if ( poLatLonSRS != NULL ) delete poLatLonSRS;
-        if ( poTransform != NULL ) delete poTransform;
-
-        /* Free data */
-        CPLFree( padXVal );
-        CPLFree( padYVal );
-        CPLFree( padLonVal );
-        CPLFree( padLatVal);
+        if( poLatLonSRS != NULL ) delete poLatLonSRS;
+        if( poTransform != NULL ) delete poTransform;
 
-    } // projected
+        CPLFree(padXVal);
+        CPLFree(padYVal);
+        CPLFree(padLonVal);
+        CPLFree(padLatVal);
+    }  // Projected
 
-    /* If not Projected assume Geographic to catch grids without Datum */
-    else if ( bWriteLonLat )  {
-
-/* -------------------------------------------------------------------- */
-/*      Get latitude values                                             */
-/* -------------------------------------------------------------------- */
-        if ( ! bBottomUp )
+    // If not projected, assume geographic to catch grids without Datum.
+    else if( bWriteLonLat )
+    {
+        // Get latitude values.
+        if( !bBottomUp )
             dfY0 = adfGeoTransform[3];
-        else /* invert latitude values */
-            dfY0 = adfGeoTransform[3] + ( adfGeoTransform[5] * nRasterYSize );
+        else  // Invert latitude values.
+            dfY0 = adfGeoTransform[3] + (adfGeoTransform[5] * nRasterYSize);
         dfDY = adfGeoTransform[5];
 
-        /* override lat values with the ones in GEOLOCATION/Y_VALUES */
-        if ( GetMetadataItem( "Y_VALUES", "GEOLOCATION" ) != NULL ) {
+        // Override lat values with the ones in GEOLOCATION/Y_VALUES.
+        if( GetMetadataItem("Y_VALUES", "GEOLOCATION") != NULL )
+        {
             int nTemp = 0;
-            padLatVal = Get1DGeolocation( "Y_VALUES", nTemp );
-            /* make sure we got the correct amount, if not fallback to GT */
-            /* could add test fabs( fabs(padLatVal[0]) - fabs(dfY0) ) <= 0.1 ) ) */
-            if ( nTemp == nRasterYSize ) {
-                CPLDebug("GDAL_netCDF", "Using Y_VALUES geolocation metadata for lat values" );
+            padLatVal = Get1DGeolocation("Y_VALUES", nTemp);
+            // Make sure we got the correct amount, if not fallback to GT */
+            // could add test fabs(fabs(padLatVal[0]) - fabs(dfY0)) <= 0.1))
+            if( nTemp == nRasterYSize )
+            {
+                CPLDebug("GDAL_netCDF",
+                         "Using Y_VALUES geolocation metadata for lat values");
             }
-            else {
+            else
+            {
                 CPLDebug("GDAL_netCDF",
                          "Got %d elements from Y_VALUES geolocation metadata, need %d",
-                         nTemp, nRasterYSize );
-                if ( padLatVal ) {
-                    CPLFree( padLatVal );
+                         nTemp, nRasterYSize);
+                if( padLatVal )
+                {
+                    CPLFree(padLatVal);
                     padLatVal = NULL;
                 }
             }
         }
 
-        if ( padLatVal == NULL ) {
-            padLatVal = (double *) CPLMalloc( nRasterYSize * sizeof( double ) );
-            for( int i=0; i<nRasterYSize; i++ ) {
-                /* The data point is centered inside the pixel */
-                if ( ! bBottomUp )
-                    padLatVal[i] = dfY0 + (i+0.5)*dfDY ;
-                else /* invert latitude values */
-                    padLatVal[i] = dfY0 - (i+0.5)*dfDY ;
+        if( padLatVal == NULL )
+        {
+            padLatVal =
+                static_cast<double *>(CPLMalloc(nRasterYSize * sizeof(double)));
+            for( int i = 0; i < nRasterYSize; i++ )
+            {
+                // The data point is centered inside the pixel.
+                if( !bBottomUp )
+                    padLatVal[i] = dfY0 + (i + 0.5) * dfDY;
+                else  // Invert latitude values.
+                    padLatVal[i] = dfY0 - (i + 0.5) * dfDY;
             }
         }
 
         size_t startLat[1] = {0};
         size_t countLat[1] = {static_cast<size_t>(nRasterYSize)};
 
-/* -------------------------------------------------------------------- */
-/*      Get longitude values                                            */
-/* -------------------------------------------------------------------- */
+        // Get longitude values.
         dfX0 = adfGeoTransform[0];
         dfDX = adfGeoTransform[1];
 
-        padLonVal = (double *) CPLMalloc( nRasterXSize * sizeof( double ) );
-        for( int i=0; i<nRasterXSize; i++ ) {
-            /* The data point is centered inside the pixel */
-            padLonVal[i] = dfX0 + (i+0.5)*dfDX ;
+        padLonVal =
+            static_cast<double *>(CPLMalloc(nRasterXSize * sizeof(double)));
+        for( int i = 0; i < nRasterXSize; i++ )
+        {
+            // The data point is centered inside the pixel.
+            padLonVal[i] = dfX0 + (i + 0.5) * dfDX;
         }
 
         size_t startLon[1] = {0};
         size_t countLon[1] = {static_cast<size_t>(nRasterXSize)};
 
-/* -------------------------------------------------------------------- */
-/*      Write latitude and longitude values                             */
-/* -------------------------------------------------------------------- */
-        /* make sure we are in data mode */
-        SetDefineMode( false );
+        // Write latitude and longitude values.
+
+        // Make sure we are in data mode.
+        SetDefineMode(false);
 
-        /* write values */
-        CPLDebug("GDAL_netCDF", "Writing lat values" );
+        // Write values.
+        CPLDebug("GDAL_netCDF", "Writing lat values");
 
-        int status = nc_put_vara_double( cdfid, nVarLatID, startLat,
-                                     countLat, padLatVal);
+        int status =
+            nc_put_vara_double(cdfid, nVarLatID, startLat, countLat, padLatVal);
         NCDF_ERR(status);
 
-        CPLDebug("GDAL_netCDF", "Writing lon values" );
-        status = nc_put_vara_double( cdfid, nVarLonID, startLon,
-                                     countLon, padLonVal);
+        CPLDebug("GDAL_netCDF", "Writing lon values");
+        status =
+            nc_put_vara_double(cdfid, nVarLonID, startLon, countLon, padLonVal);
         NCDF_ERR(status);
 
-        /* free values */
-        CPLFree( padLatVal );
-        CPLFree( padLonVal );
-    }// not projected
+        CPLFree(padLatVal);
+        CPLFree(padLonVal);
+    }  // Not projected.
 
-    /* close geoloc datasets */
-    if( hDS_X != NULL ) {
-        GDALClose( hDS_X );
+    if( hDS_X != NULL )
+    {
+        GDALClose(hDS_X);
     }
-    if( hDS_Y != NULL ) {
-        GDALClose( hDS_Y );
+    if( hDS_Y != NULL )
+    {
+        GDALClose(hDS_Y);
     }
 
-    pfnProgress( 1.00, NULL, pProgressData );
+    pfnProgress(1.00, NULL, pProgressData);
 
     return CE_None;
 }
 
-/* Write Projection variable to band variable */
-/* Moved from AddProjectionVars() for cases when bands are added after projection */
-void netCDFDataset::AddGridMappingRef( )
+// Write Projection variable to band variable.
+// Moved from AddProjectionVars() for cases when bands are added after
+// projection.
+void netCDFDataset::AddGridMappingRef()
 {
-    int nVarId = -1;
     bool bOldDefineMode = bDefineMode;
 
     if( (GetAccess() == GA_Update) &&
-        (nBands >= 1) && (GetRasterBand( 1 )) &&
-        pszCFProjection != NULL && ! EQUAL( pszCFProjection, "" ) ) {
-
-        nVarId = ( (netCDFRasterBand *) GetRasterBand( 1 ) )->nZId;
+        (nBands >= 1) && (GetRasterBand(1)) &&
+        pszCFProjection != NULL && !EQUAL(pszCFProjection, "") )
+    {
+        const int nVarId =
+            static_cast<netCDFRasterBand *>(GetRasterBand(1))->nZId;
         bAddedGridMappingRef = true;
 
-        /* make sure we are in define mode */
-        SetDefineMode( true );
-        int status = nc_put_att_text( cdfid, nVarId,
-                                  CF_GRD_MAPPING,
-                                  strlen( pszCFProjection ),
-                                  pszCFProjection );
+        // Make sure we are in define mode.
+        SetDefineMode(true);
+        int status = nc_put_att_text(cdfid, nVarId, CF_GRD_MAPPING,
+                                     strlen(pszCFProjection), pszCFProjection);
         NCDF_ERR(status);
-        if ( pszCFCoordinates != NULL && ! EQUAL( pszCFCoordinates, "" ) ) {
-            status = nc_put_att_text( cdfid, nVarId,
-                                      CF_COORDINATES,
-                                      strlen( pszCFCoordinates ),
-                                      pszCFCoordinates );
+        if( pszCFCoordinates != NULL && !EQUAL(pszCFCoordinates, "") )
+        {
+            status =
+                nc_put_att_text(cdfid, nVarId, CF_COORDINATES,
+                                strlen(pszCFCoordinates), pszCFCoordinates);
             NCDF_ERR(status);
         }
 
-        /* go back to previous define mode */
-        SetDefineMode( bOldDefineMode );
+        // Go back to previous define mode.
+        SetDefineMode(bOldDefineMode);
     }
 }
 
@@ -4324,40 +4473,53 @@ void netCDFDataset::AddGridMappingRef( )
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr netCDFDataset::GetGeoTransform( double * padfTransform )
+CPLErr netCDFDataset::GetGeoTransform( double *padfTransform )
 
 {
-    memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
+    memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
     if( bSetGeoTransform )
         return CE_None;
 
-    return GDALPamDataset::GetGeoTransform( padfTransform );
+    return GDALPamDataset::GetGeoTransform(padfTransform);
 }
 
 /************************************************************************/
 /*                                rint()                                */
 /************************************************************************/
 
+#ifdef HAVE_CXX11
+double netCDFDataset::rint( double dfX )
+{
+    return std::round(dfX);
+}
+#else
 double netCDFDataset::rint( double dfX)
 {
-    if( dfX > 0 ) {
-        int nX = (int) (dfX+0.5);
-        if( nX % 2 ) {
+    // rint has undefined behavior for values of dfX that exceed in int max.
+    if( dfX > 0 )
+    {
+        int nX = (int)(dfX + 0.5);
+        if( nX % 2 )
+        {
             double dfDiff = dfX - (double)nX;
             if( dfDiff == -0.5 )
-                return double( nX-1 );
+                return double(nX - 1);
         }
-        return double( nX );
-    } else {
-        int nX = (int) (dfX-0.5);
-        if( nX % 2 ) {
+        return double(nX);
+    }
+    else
+    {
+        int nX = (int)(dfX - 0.5);
+        if( nX % 2 )
+        {
             double dfDiff = dfX - (double)nX;
             if( dfDiff == 0.5 )
-                return double(nX+1);
+                return double(nX + 1);
         }
         return double(nX);
     }
 }
+#endif  // !HAVE_CXX11
 
 /************************************************************************/
 /*                        ReadAttributes()                              */
@@ -4365,158 +4527,160 @@ double netCDFDataset::rint( double dfX)
 CPLErr netCDFDataset::ReadAttributes( int cdfidIn, int var)
 
 {
-    char    szVarName [ NC_MAX_NAME+1 ];
-    int     nbAttr;
+    char szVarName[NC_MAX_NAME + 1];
+    int nbAttr;
 
-    nc_inq_varnatts( cdfidIn, var, &nbAttr );
-    if( var == NC_GLOBAL ) {
-        strcpy( szVarName, "NC_GLOBAL" );
+    nc_inq_varnatts(cdfidIn, var, &nbAttr);
+    if( var == NC_GLOBAL )
+    {
+        strcpy(szVarName, "NC_GLOBAL");
     }
-    else {
+    else
+    {
         szVarName[0] = '\0';
-        int status = nc_inq_varname( cdfidIn, var, szVarName );
+        int status = nc_inq_varname(cdfidIn, var, szVarName);
         NCDF_ERR(status);
     }
 
-    for( int l=0; l < nbAttr; l++) {
-        char szAttrName[ NC_MAX_NAME+1 ];
+    for( int l = 0; l < nbAttr; l++ )
+    {
+        char szAttrName[NC_MAX_NAME + 1];
         szAttrName[0] = 0;
-        int status = nc_inq_attname( cdfidIn, var, l, szAttrName);
+        int status = nc_inq_attname(cdfidIn, var, l, szAttrName);
         NCDF_ERR(status);
-        char szMetaName[ NC_MAX_NAME * 2 + 1 + 1 ];
-        snprintf( szMetaName, sizeof(szMetaName), "%s#%s", szVarName, szAttrName  );
+        char szMetaName[NC_MAX_NAME * 2 + 1 + 1];
+        snprintf(szMetaName, sizeof(szMetaName), "%s#%s", szVarName,
+                 szAttrName);
 
         char *pszMetaTemp = NULL;
-        if ( NCDFGetAttr( cdfidIn, var, szAttrName, &pszMetaTemp )
-             == CE_None ) {
-            papszMetadata = CSLSetNameValue(papszMetadata,
-                                            szMetaName,
-                                            pszMetaTemp);
+        if( NCDFGetAttr(cdfidIn, var, szAttrName, &pszMetaTemp) == CE_None )
+        {
+            papszMetadata =
+                CSLSetNameValue(papszMetadata, szMetaName, pszMetaTemp);
             CPLFree(pszMetaTemp);
             pszMetaTemp = NULL;
         }
-        else {
-            CPLDebug( "GDAL_netCDF", "invalid global metadata %s", szMetaName );
+        else
+        {
+            CPLDebug("GDAL_netCDF", "invalid global metadata %s", szMetaName);
         }
     }
 
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                netCDFDataset::CreateSubDatasetList()                 */
 /************************************************************************/
-void netCDFDataset::CreateSubDatasetList( )
+void netCDFDataset::CreateSubDatasetList()
 {
-    char         szName[ NC_MAX_NAME+1 ];
-    char         szVarStdName[ NC_MAX_NAME+1 ];
-    int          *ponDimIds;
-    nc_type      nAttype;
-    size_t       nAttlen;
+    char szName[NC_MAX_NAME + 1];
+    char szVarStdName[NC_MAX_NAME + 1];
+    int *ponDimIds = NULL;
+    nc_type nAttype;
+    size_t nAttlen;
 
     netCDFDataset *poDS = this;
 
     int nSub = 1;
     int nVarCount;
-    nc_inq_nvars ( cdfid, &nVarCount );
+    nc_inq_nvars(cdfid, &nVarCount);
 
-    for ( int nVar = 0; nVar < nVarCount; nVar++ ) {
+    for( int nVar = 0; nVar < nVarCount; nVar++ )
+    {
 
         int nDims;
-        nc_inq_varndims ( cdfid, nVar, &nDims );
+        nc_inq_varndims(cdfid, nVar, &nDims);
 
-        if( nDims >= 2 ) {
-            ponDimIds = (int *) CPLCalloc( nDims, sizeof( int ) );
-            nc_inq_vardimid ( cdfid, nVar, ponDimIds );
+        if( nDims >= 2 )
+        {
+            ponDimIds = static_cast<int *>(CPLCalloc(nDims, sizeof(int)));
+            nc_inq_vardimid(cdfid, nVar, ponDimIds);
 
-/* -------------------------------------------------------------------- */
-/*      Create Sub dataset list                                         */
-/* -------------------------------------------------------------------- */
+            // Create Sub dataset list.
             CPLString osDim;
-            for( int i = 0; i < nDims; i++ ) {
+            for( int i = 0; i < nDims; i++ )
+            {
                 size_t nDimLen;
-                nc_inq_dimlen ( cdfid, ponDimIds[i], &nDimLen );
-                osDim += CPLSPrintf("%dx", (int) nDimLen);
+                nc_inq_dimlen(cdfid, ponDimIds[i], &nDimLen);
+                osDim += CPLSPrintf("%dx", (int)nDimLen);
             }
 
             nc_type nVarType;
-            nc_inq_vartype( cdfid, nVar, &nVarType );
-/* -------------------------------------------------------------------- */
-/*      Get rid of the last "x" character                               */
-/* -------------------------------------------------------------------- */
-            osDim.resize(osDim.size()-1);
-            const char* pszType = "";
-            switch( nVarType ) {
-                case NC_BYTE:
-                    pszType = "8-bit integer";
-                    break;
-                case NC_CHAR:
-                    pszType = "8-bit character";
-                    break;
-                case NC_SHORT:
-                    pszType = "16-bit integer";
-                    break;
-                case NC_INT:
-                    pszType = "32-bit integer";
-                    break;
-                case NC_FLOAT:
-                    pszType = "32-bit floating-point";
-                    break;
-                case NC_DOUBLE:
-                    pszType = "64-bit floating-point";
-                    break;
+            nc_inq_vartype(cdfid, nVar, &nVarType);
+            // Get rid of the last "x" character.
+            osDim.resize(osDim.size() - 1);
+            const char *pszType = "";
+            switch( nVarType )
+            {
+            case NC_BYTE:
+                pszType = "8-bit integer";
+                break;
+            case NC_CHAR:
+                pszType = "8-bit character";
+                break;
+            case NC_SHORT:
+                pszType = "16-bit integer";
+                break;
+            case NC_INT:
+                pszType = "32-bit integer";
+                break;
+            case NC_FLOAT:
+                pszType = "32-bit floating-point";
+                break;
+            case NC_DOUBLE:
+                pszType = "64-bit floating-point";
+                break;
 #ifdef NETCDF_HAS_NC4
-                case NC_UBYTE:
-                    pszType = "8-bit unsigned integer";
-                    break;
-                case NC_USHORT:
-                    pszType = "16-bit unsigned integer";
-                    break;
-                case NC_UINT:
-                    pszType = "32-bit unsigned integer";
-                    break;
-                case NC_INT64:
-                    pszType = "64-bit integer";
-                    break;
-                case NC_UINT64:
-                    pszType = "64-bit unsigned integer";
-                    break;
+            case NC_UBYTE:
+                pszType = "8-bit unsigned integer";
+                break;
+            case NC_USHORT:
+                pszType = "16-bit unsigned integer";
+                break;
+            case NC_UINT:
+                pszType = "32-bit unsigned integer";
+                break;
+            case NC_INT64:
+                pszType = "64-bit integer";
+                break;
+            case NC_UINT64:
+                pszType = "64-bit unsigned integer";
+                break;
 #endif
-                default:
-                    break;
+            default:
+                break;
             }
             szName[0] = '\0';
-            int status = nc_inq_varname( cdfid, nVar, szName);
+            int status = nc_inq_varname(cdfid, nVar, szName);
             NCDF_ERR(status);
             nAttlen = 0;
-            nc_inq_att( cdfid, nVar, CF_STD_NAME, &nAttype, &nAttlen);
+            nc_inq_att(cdfid, nVar, CF_STD_NAME, &nAttype, &nAttlen);
             if( nAttlen < sizeof(szVarStdName) &&
-                nc_get_att_text ( cdfid, nVar, CF_STD_NAME,
-                                  szVarStdName ) == NC_NOERR ) {
+                nc_get_att_text(cdfid, nVar, CF_STD_NAME,
+                                szVarStdName) == NC_NOERR )
+            {
                 szVarStdName[nAttlen] = '\0';
             }
-            else {
-                snprintf( szVarStdName, sizeof(szVarStdName), "%s", szName );
+            else
+            {
+                snprintf(szVarStdName, sizeof(szVarStdName), "%s", szName);
             }
 
-            char szTemp[ NC_MAX_NAME+1 ];
-            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nSub);
+            char szTemp[NC_MAX_NAME + 1];
+            snprintf(szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nSub);
 
             poDS->papszSubDatasets =
-                CSLSetNameValue( poDS->papszSubDatasets, szTemp,
-                                 CPLSPrintf( "NETCDF:\"%s\":%s",
-                                             poDS->osFilename.c_str(),
-                                             szName)  ) ;
+                CSLSetNameValue(poDS->papszSubDatasets, szTemp,
+                                CPLSPrintf("NETCDF:\"%s\":%s",
+                                           poDS->osFilename.c_str(), szName));
 
-            snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nSub++ );
+            snprintf(szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nSub++);
 
             poDS->papszSubDatasets =
-                CSLSetNameValue( poDS->papszSubDatasets, szTemp,
-                                 CPLSPrintf( "[%s] %s (%s)",
-                                             osDim.c_str(),
-                                             szVarStdName,
-                                             pszType ) );
+                CSLSetNameValue(poDS->papszSubDatasets, szTemp,
+                                CPLSPrintf("[%s] %s (%s)", osDim.c_str(),
+                                           szVarStdName, pszType));
 
             CPLFree(ponDimIds);
         }
@@ -4527,38 +4691,37 @@ void netCDFDataset::CreateSubDatasetList( )
 /*                              IdentifyFormat()                      */
 /************************************************************************/
 
-NetCDFFormatEnum netCDFDataset::IdentifyFormat( GDALOpenInfo * poOpenInfo,
+NetCDFFormatEnum netCDFDataset::IdentifyFormat( GDALOpenInfo *poOpenInfo,
 #ifndef HAVE_HDF5
 CPL_UNUSED
 #endif
                                    bool bCheckExt = true )
 {
-/* -------------------------------------------------------------------- */
-/*      Does this appear to be a netcdf file? If so, which format?      */
-/*      http://www.unidata.ucar.edu/software/netcdf/docs/faq.html#fv1_5 */
-/* -------------------------------------------------------------------- */
+    // Does this appear to be a netcdf file? If so, which format?
+    // http://www.unidata.ucar.edu/software/netcdf/docs/faq.html#fv1_5
 
     if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") )
         return NCDF_FORMAT_UNKNOWN;
-    if ( poOpenInfo->nHeaderBytes < 4 )
+    if( poOpenInfo->nHeaderBytes < 4 )
         return NCDF_FORMAT_NONE;
-    if ( STARTS_WITH_CI((char*)poOpenInfo->pabyHeader, "CDF\001") )
+    if( STARTS_WITH_CI((char*)poOpenInfo->pabyHeader, "CDF\001") )
     {
-        /* In case the netCDF driver is registered before the GMT driver, */
-        /* avoid opening GMT files */
+        // In case the netCDF driver is registered before the GMT driver,
+        // avoid opening GMT files.
         if( GDALGetDriverByName("GMT") != NULL )
         {
             bool bFoundZ = false;
             bool bFoundDimension = false;
-            for(int i=0;i<poOpenInfo->nHeaderBytes - 11;i++)
+            for( int i = 0; i < poOpenInfo->nHeaderBytes - 11; i++ )
             {
                 if( poOpenInfo->pabyHeader[i] == 1 &&
-                    poOpenInfo->pabyHeader[i+1] == 'z' &&
-                    poOpenInfo->pabyHeader[i+2] == 0  )
+                    poOpenInfo->pabyHeader[i + 1] == 'z' &&
+                    poOpenInfo->pabyHeader[i + 2] == 0 )
                     bFoundZ = true;
                 else if( poOpenInfo->pabyHeader[i] == 9 &&
-                        memcmp((const char*)poOpenInfo->pabyHeader + i + 1, "dimension", 9) == 0 &&
-                        poOpenInfo->pabyHeader[i+10] == 0 )
+                         memcmp((const char *)poOpenInfo->pabyHeader + i + 1,
+                                "dimension", 9) == 0 &&
+                         poOpenInfo->pabyHeader[i + 10] == 0 )
                     bFoundDimension = true;
             }
             if( bFoundZ && bFoundDimension )
@@ -4567,48 +4730,57 @@ CPL_UNUSED
 
         return NCDF_FORMAT_NC;
     }
-    else if ( STARTS_WITH_CI((char*)poOpenInfo->pabyHeader, "CDF\002") )
+    else if( STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "CDF\002") )
+    {
         return NCDF_FORMAT_NC2;
-    else if ( STARTS_WITH_CI((char*)poOpenInfo->pabyHeader, "\211HDF\r\n\032\n") ) {
-        /* Requires netCDF-4/HDF5 support in libnetcdf (not just libnetcdf-v4).
-           If HDF5 is not supported in GDAL, this driver will try to open the file
-           Else, make sure this driver does not try to open HDF5 files
-           If user really wants to open with this driver, use NETCDF:file.h5 format.
-           This check should be relaxed, but there is no clear way to make a difference.
-        */
-
-        /* Check for HDF5 support in GDAL */
+    }
+    else if( STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "\211HDF\r\n\032\n") )
+    {
+        // Requires netCDF-4/HDF5 support in libnetcdf (not just libnetcdf-v4).
+        // If HDF5 is not supported in GDAL, this driver will try to open the
+        // file Else, make sure this driver does not try to open HDF5 files If
+        // user really wants to open with this driver, use NETCDF:file.h5
+        // format.  This check should be relaxed, but there is no clear way to
+        // make a difference.
+
+        // Check for HDF5 support in GDAL.
 #ifdef HAVE_HDF5
-        if ( bCheckExt ) { /* Check by default */
-            const char* pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
-            if ( ! ( EQUAL( pszExtension, "nc")  || EQUAL( pszExtension, "cdf")
-                     || EQUAL( pszExtension, "nc2") || EQUAL( pszExtension, "nc4")
-					 || EQUAL( pszExtension, "nc3") || EQUAL( pszExtension, "grd") ) )
+        if( bCheckExt )
+        {
+            // Check by default.
+            const char *pszExtension = CPLGetExtension(poOpenInfo->pszFilename);
+            if( !(EQUAL(pszExtension, "nc") || EQUAL(pszExtension, "cdf") ||
+                  EQUAL(pszExtension, "nc2") || EQUAL(pszExtension, "nc4") ||
+                  EQUAL(pszExtension, "nc3") || EQUAL(pszExtension, "grd")) )
                 return NCDF_FORMAT_HDF5;
         }
 #endif
 
-        /* Check for netcdf-4 support in libnetcdf */
+        // Check for netcdf-4 support in libnetcdf.
 #ifdef NETCDF_HAS_NC4
         return NCDF_FORMAT_NC4;
 #else
         return NCDF_FORMAT_HDF5;
 #endif
-
     }
-    else if ( STARTS_WITH_CI((char*)poOpenInfo->pabyHeader, "\016\003\023\001") ) {
-        /* Requires HDF4 support in libnetcdf, but if HF4 is supported by GDAL don't try to open. */
-        /* If user really wants to open with this driver, use NETCDF:file.hdf syntax. */
+    else if( STARTS_WITH_CI((char *)poOpenInfo->pabyHeader, "\016\003\023\001") )
+    {
+        // Requires HDF4 support in libnetcdf, but if HF4 is supported by GDAL
+        // don't try to open.
+        // If user really wants to open with this driver, use NETCDF:file.hdf
+        // syntax.
 
-        /* Check for HDF4 support in GDAL */
+        // Check for HDF4 support in GDAL.
 #ifdef HAVE_HDF4
-        if ( bCheckExt ) { /* Check by default */
-            /* Always treat as HDF4 file */
+        if( bCheckExt )
+        {
+            // Check by default.
+            // Always treat as HDF4 file.
             return NCDF_FORMAT_HDF4;
         }
 #endif
 
-        /* Check for HDF4 support in libnetcdf */
+        // Check for HDF4 support in libnetcdf.
 #ifdef NETCDF_HAS_HDF4
         return NCDF_FORMAT_NC4;
 #else
@@ -4623,7 +4795,7 @@ CPL_UNUSED
 /*                            TestCapability()                          */
 /************************************************************************/
 
-int netCDFDataset::TestCapability(const char* pszCap)
+int netCDFDataset::TestCapability(const char *pszCap)
 {
     if( EQUAL(pszCap, ODsCCreateLayer) )
     {
@@ -4637,7 +4809,7 @@ int netCDFDataset::TestCapability(const char* pszCap)
 /*                            GetLayer()                                */
 /************************************************************************/
 
-OGRLayer* netCDFDataset::GetLayer(int nIdx)
+OGRLayer *netCDFDataset::GetLayer(int nIdx)
 {
     if( nIdx < 0 || nIdx >= nLayers )
         return NULL;
@@ -4648,21 +4820,21 @@ OGRLayer* netCDFDataset::GetLayer(int nIdx)
 /*                            ICreateLayer()                            */
 /************************************************************************/
 
-OGRLayer* netCDFDataset::ICreateLayer( const char *pszName,
+OGRLayer *netCDFDataset::ICreateLayer( const char *pszName,
                                        OGRSpatialReference *poSpatialRef,
                                        OGRwkbGeometryType eGType,
-                                       char ** papszOptions )
+                                       char **papszOptions )
 {
     int nLayerCDFId = cdfid;
     if( !TestCapability(ODsCCreateLayer) )
         return NULL;
 
     CPLString osNetCDFLayerName(pszName);
-    const netCDFWriterConfigLayer* poLayerConfig = NULL;
+    const netCDFWriterConfigLayer *poLayerConfig = NULL;
     if( oWriterConfig.m_bIsValid )
     {
-        std::map<CPLString, netCDFWriterConfigLayer>::const_iterator oLayerIter =
-                                        oWriterConfig.m_oLayers.find(pszName);
+        std::map<CPLString, netCDFWriterConfigLayer>::const_iterator
+            oLayerIter = oWriterConfig.m_oLayers.find(pszName);
         if( oLayerIter != oWriterConfig.m_oLayers.end() )
         {
             poLayerConfig = &(oLayerIter->second);
@@ -4670,27 +4842,32 @@ OGRLayer* netCDFDataset::ICreateLayer( const char *pszName,
         }
     }
 
-    netCDFDataset* poLayerDataset = NULL;
+    netCDFDataset *poLayerDataset = NULL;
     if( eMultipleLayerBehaviour == SEPARATE_FILES )
     {
-        char** papszDatasetOptions = NULL;
-        papszDatasetOptions = CSLSetNameValue(papszDatasetOptions, "CONFIG_FILE",
-                                       CSLFetchNameValue(papszCreationOptions, "CONFIG_FILE"));
-        papszDatasetOptions = CSLSetNameValue(papszDatasetOptions, "FORMAT",
-                                       CSLFetchNameValue(papszCreationOptions, "FORMAT"));
-        papszDatasetOptions = CSLSetNameValue(papszDatasetOptions, "WRITE_GDAL_TAGS",
-                                       CSLFetchNameValue(papszCreationOptions, "WRITE_GDAL_TAGS"));
-        CPLString osLayerFilename(CPLFormFilename( osFilename, osNetCDFLayerName, "nc" ));
+        char **papszDatasetOptions = NULL;
+        papszDatasetOptions = CSLSetNameValue(
+            papszDatasetOptions, "CONFIG_FILE",
+            CSLFetchNameValue(papszCreationOptions, "CONFIG_FILE"));
+        papszDatasetOptions =
+            CSLSetNameValue(papszDatasetOptions, "FORMAT",
+                            CSLFetchNameValue(papszCreationOptions, "FORMAT"));
+        papszDatasetOptions = CSLSetNameValue(
+            papszDatasetOptions, "WRITE_GDAL_TAGS",
+            CSLFetchNameValue(papszCreationOptions, "WRITE_GDAL_TAGS"));
+        CPLString osLayerFilename(
+            CPLFormFilename(osFilename, osNetCDFLayerName, "nc"));
         CPLAcquireMutex(hNCMutex, 1000.0);
-        poLayerDataset = CreateLL( osLayerFilename, 0, 0, 0, papszDatasetOptions );
+        poLayerDataset =
+            CreateLL(osLayerFilename, 0, 0, 0, papszDatasetOptions);
         CPLReleaseMutex(hNCMutex);
         CSLDestroy(papszDatasetOptions);
         if( poLayerDataset == NULL )
             return NULL;
 
         nLayerCDFId = poLayerDataset->cdfid;
-        NCDFAddGDALHistory( nLayerCDFId, osLayerFilename, "", "Create",
-                            NCDF_CONVENTIONS_CF_V1_6 );
+        NCDFAddGDALHistory(nLayerCDFId, osLayerFilename, "", "Create",
+                           NCDF_CONVENTIONS_CF_V1_6);
     }
 #ifdef NETCDF_HAS_NC4
     else if( eMultipleLayerBehaviour == SEPARATE_GROUPS )
@@ -4698,43 +4875,45 @@ OGRLayer* netCDFDataset::ICreateLayer( const char *pszName,
         SetDefineMode(true);
 
         nLayerCDFId = -1;
-        int status = nc_def_grp (cdfid, osNetCDFLayerName, &nLayerCDFId);
+        int status = nc_def_grp(cdfid, osNetCDFLayerName, &nLayerCDFId);
         NCDF_ERR(status);
         if( status != NC_NOERR )
             return NULL;
 
-        NCDFAddGDALHistory( nLayerCDFId, osFilename, "", "Create",
-                            NCDF_CONVENTIONS_CF_V1_6 );
+        NCDFAddGDALHistory(nLayerCDFId, osFilename, "", "Create",
+                           NCDF_CONVENTIONS_CF_V1_6);
     }
 #endif
 
-    /* Make a clone to workaround a bug in released MapServer versions */
-    /* that destroys the passed SRS instead of releasing it */
-    OGRSpatialReference* poSRS = poSpatialRef;
+    // Make a clone to workaround a bug in released MapServer versions
+    // that destroys the passed SRS instead of releasing it .
+    OGRSpatialReference *poSRS = poSpatialRef;
     if( poSRS != NULL )
         poSRS = poSRS->Clone();
-    netCDFLayer* poLayer = new netCDFLayer( poLayerDataset ? poLayerDataset : this,
-                                            nLayerCDFId,
-                                            osNetCDFLayerName, eGType, poSRS );
+    netCDFLayer *poLayer =
+        new netCDFLayer(poLayerDataset ? poLayerDataset : this, nLayerCDFId,
+                        osNetCDFLayerName, eGType, poSRS);
     if( poSRS != NULL )
         poSRS->Release();
 
     // Fetch layer creation options coming from config file
-    char** papszNewOptions = CSLDuplicate(papszOptions);
+    char **papszNewOptions = CSLDuplicate(papszOptions);
     if( oWriterConfig.m_bIsValid )
     {
         std::map<CPLString, CPLString>::const_iterator oIter;
         for( oIter = oWriterConfig.m_oLayerCreationOptions.begin();
              oIter != oWriterConfig.m_oLayerCreationOptions.end(); ++oIter )
         {
-            papszNewOptions = CSLSetNameValue(papszNewOptions, oIter->first, oIter->second);
+            papszNewOptions =
+                CSLSetNameValue(papszNewOptions, oIter->first, oIter->second);
         }
         if( poLayerConfig != NULL )
         {
             for( oIter = poLayerConfig->m_oLayerCreationOptions.begin();
                  oIter != poLayerConfig->m_oLayerCreationOptions.end(); ++oIter )
             {
-                papszNewOptions = CSLSetNameValue(papszNewOptions, oIter->first, oIter->second);
+                papszNewOptions = CSLSetNameValue(papszNewOptions, oIter->first,
+                                                  oIter->second);
             }
         }
     }
@@ -4751,7 +4930,8 @@ OGRLayer* netCDFDataset::ICreateLayer( const char *pszName,
     if( poLayerDataset != NULL )
         apoVectorDatasets.push_back(poLayerDataset);
 
-    papoLayers = static_cast<netCDFLayer**>(CPLRealloc(papoLayers, (nLayers + 1) * sizeof(netCDFLayer*)));
+    papoLayers = static_cast<netCDFLayer **>(
+        CPLRealloc(papoLayers, (nLayers + 1) * sizeof(netCDFLayer *)));
     papoLayers[nLayers++] = poLayer;
     return poLayer;
 }
@@ -4760,20 +4940,22 @@ OGRLayer* netCDFDataset::ICreateLayer( const char *pszName,
 /*                           CloneAttributes()                          */
 /************************************************************************/
 
-bool netCDFDataset::CloneAttributes(int old_cdfid, int new_cdfid, int nSrcVarId, int nDstVarId)
+bool netCDFDataset::CloneAttributes(int old_cdfid, int new_cdfid, int nSrcVarId,
+                                    int nDstVarId)
 {
     int nAttCount = -1;
-    int status = nc_inq_varnatts( old_cdfid, nSrcVarId, &nAttCount);
+    int status = nc_inq_varnatts(old_cdfid, nSrcVarId, &nAttCount);
     NCDF_ERR(status);
 
-    for( int i=0; i < nAttCount; i++ )
+    for( int i = 0; i < nAttCount; i++ )
     {
-        char szName[ NC_MAX_NAME + 1 ];
+        char szName[NC_MAX_NAME + 1];
         szName[0] = 0;
         status = nc_inq_attname(old_cdfid, nSrcVarId, i, szName);
         NCDF_ERR(status);
 
-        status = nc_copy_att(old_cdfid, nSrcVarId, szName, new_cdfid, nDstVarId);
+        status =
+            nc_copy_att(old_cdfid, nSrcVarId, szName, new_cdfid, nDstVarId);
         NCDF_ERR(status);
         if( status != NC_NOERR )
             return false;
@@ -4786,67 +4968,68 @@ bool netCDFDataset::CloneAttributes(int old_cdfid, int new_cdfid, int nSrcVarId,
 /*                          CloneVariableContent()                      */
 /************************************************************************/
 
-bool netCDFDataset::CloneVariableContent(int old_cdfid, int new_cdfid, int nSrcVarId, int nDstVarId)
+bool netCDFDataset::CloneVariableContent(int old_cdfid, int new_cdfid,
+                                         int nSrcVarId, int nDstVarId)
 {
     int nVarDimCount = -1;
-    int status = nc_inq_varndims( old_cdfid, nSrcVarId, &nVarDimCount );
+    int status = nc_inq_varndims(old_cdfid, nSrcVarId, &nVarDimCount);
     NCDF_ERR(status);
     int anDimIds[] = { -1, 1 };
-    status = nc_inq_vardimid( old_cdfid, nSrcVarId, anDimIds );
+    status = nc_inq_vardimid(old_cdfid, nSrcVarId, anDimIds);
     NCDF_ERR(status);
     nc_type nc_datatype = NC_NAT;
-    status = nc_inq_vartype( old_cdfid, nSrcVarId, &nc_datatype );
+    status = nc_inq_vartype(old_cdfid, nSrcVarId, &nc_datatype);
     NCDF_ERR(status);
     size_t nTypeSize = 0;
-    switch (nc_datatype)
+    switch( nc_datatype )
     {
-        case NC_BYTE:
-        case NC_CHAR:
-            nTypeSize = 1;
-            break;
-        case NC_SHORT:
-            nTypeSize = 2;
-            break;
-        case NC_INT:
-            nTypeSize = 4;
-            break;
-        case NC_FLOAT:
-            nTypeSize = 4;
-            break;
-        case NC_DOUBLE:
-            nTypeSize = 8;
-            break;
+    case NC_BYTE:
+    case NC_CHAR:
+        nTypeSize = 1;
+        break;
+    case NC_SHORT:
+        nTypeSize = 2;
+        break;
+    case NC_INT:
+        nTypeSize = 4;
+        break;
+    case NC_FLOAT:
+        nTypeSize = 4;
+        break;
+    case NC_DOUBLE:
+        nTypeSize = 8;
+        break;
 #ifdef NETCDF_HAS_NC4
-        case NC_UBYTE:
-            nTypeSize = 1;
-            break;
-        case NC_USHORT:
-            nTypeSize = 2;
-            break;
-        case NC_UINT:
-            nTypeSize = 4;
-            break;
-        case NC_INT64:
-        case NC_UINT64:
-            nTypeSize = 8;
-            break;
-        case NC_STRING:
-            nTypeSize = sizeof(char*);
-            break;
+    case NC_UBYTE:
+        nTypeSize = 1;
+        break;
+    case NC_USHORT:
+        nTypeSize = 2;
+        break;
+    case NC_UINT:
+        nTypeSize = 4;
+        break;
+    case NC_INT64:
+    case NC_UINT64:
+        nTypeSize = 8;
+        break;
+    case NC_STRING:
+        nTypeSize = sizeof(char *);
+        break;
 #endif
-        default:
-        {
-            CPLError(CE_Failure, CPLE_NotSupported, "Unsupported data type: %d",
-                     nc_datatype);
-            return false;
-        }
+    default:
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported data type: %d",
+                 nc_datatype);
+        return false;
+    }
     }
 
     size_t nElems = 1;
     size_t anStart[NC_MAX_DIMS];
     size_t anCount[NC_MAX_DIMS];
     size_t nRecords = 1;
-    for( int i=0; i < nVarDimCount; i++)
+    for( int i = 0; i < nVarDimCount; i++)
     {
         anStart[i] = 0;
         if( i == 0 )
@@ -4864,108 +5047,111 @@ bool netCDFDataset::CloneVariableContent(int old_cdfid, int new_cdfid, int nSrcV
         }
     }
 
-    void* pBuffer = VSI_MALLOC2_VERBOSE( nElems, nTypeSize );
+    void *pBuffer = VSI_MALLOC2_VERBOSE(nElems, nTypeSize);
     if( pBuffer == NULL )
         return false;
 
-    for(size_t iRecord = 0; iRecord < nRecords; iRecord ++ )
+    for(size_t iRecord = 0; iRecord < nRecords; iRecord++ )
     {
         anStart[0] = iRecord;
 
-        switch (nc_datatype)
+        switch( nc_datatype )
         {
-            case NC_BYTE:
-                status = nc_get_vara_schar(old_cdfid, nSrcVarId, anStart, anCount,
-                                            (signed char *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_schar(new_cdfid, nDstVarId, anStart, anCount,
-                                                (const signed char *)pBuffer);
-                break;
-            case NC_CHAR:
-                status = nc_get_vara_text(old_cdfid, nSrcVarId, anStart, anCount,
-                                            (char *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_text(new_cdfid, nDstVarId, anStart, anCount,
-                                                (char *)pBuffer);
-                break;
-            case NC_SHORT:
-                status = nc_get_vara_short(old_cdfid, nSrcVarId, anStart, anCount,
-                                            (short *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_short(new_cdfid, nDstVarId, anStart, anCount,
-                                                (short *)pBuffer);
-                break;
-            case NC_INT:
-                status = nc_get_vara_int(old_cdfid, nSrcVarId, anStart, anCount,
-                                            (int *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_int(new_cdfid, nDstVarId, anStart, anCount,
-                                            (int *)pBuffer);
-                break;
-            case NC_FLOAT:
-                status = nc_get_vara_float(old_cdfid, nSrcVarId, anStart, anCount,
-                                            (float *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_float(new_cdfid, nDstVarId, anStart, anCount,
-                                                (float *)pBuffer);
-                break;
-            case NC_DOUBLE:
-                status = nc_get_vara_double(old_cdfid, nSrcVarId, anStart, anCount,
-                                            (double *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_double(new_cdfid, nDstVarId, anStart, anCount,
-                                                (double *)pBuffer);
+        case NC_BYTE:
+            status = nc_get_vara_schar(old_cdfid, nSrcVarId, anStart, anCount,
+                                       (signed char *)pBuffer);
+            if( !status )
+                status =
+                    nc_put_vara_schar(new_cdfid, nDstVarId, anStart, anCount,
+                                      (const signed char *)pBuffer);
+            break;
+        case NC_CHAR:
+            status = nc_get_vara_text(old_cdfid, nSrcVarId, anStart, anCount,
+                                      (char *)pBuffer);
+            if( !status )
+                status = nc_put_vara_text(new_cdfid, nDstVarId, anStart,
+                                          anCount, (char *)pBuffer);
+            break;
+        case NC_SHORT:
+            status = nc_get_vara_short(old_cdfid, nSrcVarId, anStart, anCount,
+                                       (short *)pBuffer);
+            if( !status )
+                status = nc_put_vara_short(new_cdfid, nDstVarId, anStart,
+                                           anCount, (short *)pBuffer);
+            break;
+        case NC_INT:
+            status = nc_get_vara_int(old_cdfid, nSrcVarId, anStart, anCount,
+                                     (int *)pBuffer);
+            if( !status )
+                status = nc_put_vara_int(new_cdfid, nDstVarId, anStart, anCount,
+                                         (int *)pBuffer);
+            break;
+        case NC_FLOAT:
+            status = nc_get_vara_float(old_cdfid, nSrcVarId, anStart, anCount,
+                                       (float *)pBuffer);
+            if( !status )
+                status = nc_put_vara_float(new_cdfid, nDstVarId, anStart,
+                                           anCount, (float *)pBuffer);
+            break;
+        case NC_DOUBLE:
+            status = nc_get_vara_double(old_cdfid, nSrcVarId, anStart, anCount,
+                                        (double *)pBuffer);
+            if( !status )
+                status = nc_put_vara_double(new_cdfid, nDstVarId, anStart,
+                                            anCount, (double *)pBuffer);
             break;
 #ifdef NETCDF_HAS_NC4
-            case NC_STRING:
-                status = nc_get_vara_string( old_cdfid, nSrcVarId, anStart, anCount,
-                                             (char**) pBuffer );
-                if( !status )
-                {
-                    status = nc_put_vara_string( new_cdfid, nDstVarId, anStart, anCount,
-                                                 (const char**) pBuffer );
-                    nc_free_string(nElems, (char**) pBuffer);
-                }
-                break;
+        case NC_STRING:
+            status = nc_get_vara_string(old_cdfid, nSrcVarId, anStart, anCount,
+                                        (char **)pBuffer);
+            if( !status )
+            {
+                status = nc_put_vara_string(new_cdfid, nDstVarId, anStart,
+                                            anCount, (const char **)pBuffer);
+                nc_free_string(nElems, (char **)pBuffer);
+            }
+            break;
 
-            case NC_UBYTE:
-                status = nc_get_vara_uchar(old_cdfid, nSrcVarId, anStart, anCount,
-                                            (unsigned char *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_uchar(new_cdfid, nDstVarId, anStart, anCount,
-                                                (unsigned char *)pBuffer);
-                break;
-            case NC_USHORT:
-                status = nc_get_vara_ushort(old_cdfid, nSrcVarId, anStart, anCount,
-                                            (unsigned short *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_ushort(new_cdfid, nDstVarId, anStart, anCount,
-                                                (unsigned short *)pBuffer);
-                break;
-            case NC_UINT:
-                status = nc_get_vara_uint(old_cdfid, nSrcVarId, anStart, anCount,
-                                            (unsigned int *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_uint(new_cdfid, nDstVarId, anStart, anCount,
-                                                (unsigned int *)pBuffer);
-                break;
-            case NC_INT64:
-                status = nc_get_vara_longlong(old_cdfid, nSrcVarId, anStart, anCount,
-                                                (long long *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_longlong(new_cdfid, nDstVarId, anStart, anCount,
-                                                    (long long *)pBuffer);
-                break;
-            case NC_UINT64:
-                status = nc_get_vara_ulonglong(old_cdfid, nSrcVarId, anStart, anCount,
-                                                (unsigned long long *)pBuffer);
-                if (!status)
-                    status = nc_put_vara_ulonglong(new_cdfid, nDstVarId, anStart, anCount,
-                                                    (unsigned long long *)pBuffer);
-                break;
+        case NC_UBYTE:
+            status = nc_get_vara_uchar(old_cdfid, nSrcVarId, anStart, anCount,
+                                       (unsigned char *)pBuffer);
+            if( !status )
+                status = nc_put_vara_uchar(new_cdfid, nDstVarId, anStart,
+                                           anCount, (unsigned char *)pBuffer);
+            break;
+        case NC_USHORT:
+            status = nc_get_vara_ushort(old_cdfid, nSrcVarId, anStart, anCount,
+                                        (unsigned short *)pBuffer);
+            if( !status )
+                status = nc_put_vara_ushort(new_cdfid, nDstVarId, anStart,
+                                            anCount, (unsigned short *)pBuffer);
+            break;
+        case NC_UINT:
+            status = nc_get_vara_uint(old_cdfid, nSrcVarId, anStart, anCount,
+                                      (unsigned int *)pBuffer);
+            if( !status )
+                status = nc_put_vara_uint(new_cdfid, nDstVarId, anStart,
+                                          anCount, (unsigned int *)pBuffer);
+            break;
+        case NC_INT64:
+            status = nc_get_vara_longlong(old_cdfid, nSrcVarId, anStart,
+                                          anCount, (long long *)pBuffer);
+            if(!status)
+                status = nc_put_vara_longlong(new_cdfid, nDstVarId, anStart,
+                                              anCount, (long long *)pBuffer);
+            break;
+        case NC_UINT64:
+            status =
+                nc_get_vara_ulonglong(old_cdfid, nSrcVarId, anStart, anCount,
+                                      (unsigned long long *)pBuffer);
+            if( !status )
+                status = nc_put_vara_ulonglong(new_cdfid, nDstVarId, anStart,
+                                               anCount,
+                                               (unsigned long long *)pBuffer);
+            break;
 #endif
-            default:
-                status = NC_EBADTYPE;
+        default:
+            status = NC_EBADTYPE;
         }
 
         NCDF_ERR(status);
@@ -4986,7 +5172,7 @@ bool netCDFDataset::CloneVariableContent(int old_cdfid, int new_cdfid, int nSrcV
 
 bool NCDFIsUnlimitedDim(bool
 #ifdef NETCDF_HAS_NC4
-                                            bIsNC4
+                            bIsNC4
 #endif
                             , int cdfid, int nDimId)
 {
@@ -4994,13 +5180,14 @@ bool NCDFIsUnlimitedDim(bool
     if( bIsNC4 )
     {
         int nUnlimitedDims = 0;
-        nc_inq_unlimdims( cdfid, &nUnlimitedDims, NULL );
+        nc_inq_unlimdims(cdfid, &nUnlimitedDims, NULL);
         bool bFound = false;
         if( nUnlimitedDims )
         {
-            int* panUnlimitedDimIds = static_cast<int*>(CPLMalloc(sizeof(int) * nUnlimitedDims));
-            nc_inq_unlimdims( cdfid, NULL, panUnlimitedDimIds );
-            for(int i=0;i<nUnlimitedDims;i++)
+            int *panUnlimitedDimIds =
+                static_cast<int *>(CPLMalloc(sizeof(int) * nUnlimitedDims));
+            nc_inq_unlimdims(cdfid, NULL, panUnlimitedDimIds);
+            for(int i = 0; i < nUnlimitedDims; i++)
             {
                 if( panUnlimitedDimIds[i] == nDimId )
                 {
@@ -5031,16 +5218,17 @@ bool netCDFDataset::CloneGrp(int nOldGrpId, int nNewGrpId,
 {
     // Clone dimensions
     int nDimCount = -1;
-    int status = nc_inq_ndims( nOldGrpId, &nDimCount );
+    int status = nc_inq_ndims(nOldGrpId, &nDimCount);
     NCDF_ERR(status)
-    int* panDimIds = static_cast<int*>(CPLMalloc(sizeof(int) * nDimCount));
+    int *panDimIds = static_cast<int *>(CPLMalloc(sizeof(int) * nDimCount));
     int nUnlimiDimID = -1;
-    status = nc_inq_unlimdim (nOldGrpId, &nUnlimiDimID);
+    status = nc_inq_unlimdim(nOldGrpId, &nUnlimiDimID);
     NCDF_ERR(status);
 #ifdef NETCDF_HAS_NC4
     if( bIsNC4 )
     {
-        // In NC4, the dimension ids of a group are not necessarily in [0,nDimCount-1] range
+        // In NC4, the dimension ids of a group are not necessarily in
+        // [0,nDimCount-1] range
         int nDimCount2 = -1;
         status = nc_inq_dimids(nOldGrpId, &nDimCount2, panDimIds, FALSE);
         NCDF_ERR(status);
@@ -5049,25 +5237,25 @@ bool netCDFDataset::CloneGrp(int nOldGrpId, int nNewGrpId,
     else
 #endif
     {
-        for( int i=0; i < nDimCount; i++ )
+        for( int i = 0; i < nDimCount; i++ )
             panDimIds[i] = i;
     }
-    for( int i=0; i < nDimCount; i++ )
+    for( int i = 0; i < nDimCount; i++ )
     {
-        char szDimName[ NC_MAX_NAME + 1 ];
+        char szDimName[NC_MAX_NAME + 1];
         szDimName[0] = 0;
         size_t nLen = 0;
         const int nDimId = panDimIds[i];
-        status = nc_inq_dim (nOldGrpId, nDimId, szDimName, &nLen);
+        status = nc_inq_dim(nOldGrpId, nDimId, szDimName, &nLen);
         NCDF_ERR(status);
         if( NCDFIsUnlimitedDim(bIsNC4, nOldGrpId, nDimId) )
             nLen = NC_UNLIMITED;
         else if( nDimId == nDimIdToGrow && nOldGrpId == nLayerId )
             nLen = nNewSize;
         int nNewDimId = -1;
-        status = nc_def_dim (nNewGrpId, szDimName, nLen, &nNewDimId);
+        status = nc_def_dim(nNewGrpId, szDimName, nLen, &nNewDimId);
         NCDF_ERR(status);
-        CPLAssert( nDimId == nNewDimId );
+        CPLAssert(nDimId == nNewDimId);
         if( status != NC_NOERR )
         {
             CPLFree(panDimIds);
@@ -5089,24 +5277,24 @@ bool netCDFDataset::CloneGrp(int nOldGrpId, int nNewGrpId,
 
     for( int i=0; i < nVarCount; i++ )
     {
-        char szVarName[ NC_MAX_NAME + 1 ];
+        char szVarName[NC_MAX_NAME + 1];
         szVarName[0] = 0;
-        status = nc_inq_varname( nOldGrpId, i, szVarName );
+        status = nc_inq_varname(nOldGrpId, i, szVarName);
         NCDF_ERR(status);
         nc_type nc_datatype = NC_NAT;
-        status = nc_inq_vartype( nOldGrpId, i, &nc_datatype );
+        status = nc_inq_vartype(nOldGrpId, i, &nc_datatype);
         NCDF_ERR(status);
         int nVarDimCount = -1;
-        status = nc_inq_varndims( nOldGrpId, i, &nVarDimCount );
+        status = nc_inq_varndims(nOldGrpId, i, &nVarDimCount);
         NCDF_ERR(status);
         int anDimIds[NC_MAX_DIMS];
-        status = nc_inq_vardimid( nOldGrpId, i, anDimIds );
+        status = nc_inq_vardimid(nOldGrpId, i, anDimIds);
         NCDF_ERR(status);
         int nNewVarId = -1;
-        status = nc_def_var( nNewGrpId, szVarName, nc_datatype,
-                             nVarDimCount, anDimIds, &nNewVarId );
+        status = nc_def_var(nNewGrpId, szVarName, nc_datatype,
+                            nVarDimCount, anDimIds, &nNewVarId);
         NCDF_ERR(status);
-        CPLAssert( i == nNewVarId );
+        CPLAssert(i == nNewVarId);
         if( status != NC_NOERR )
         {
             return false;
@@ -5118,7 +5306,7 @@ bool netCDFDataset::CloneGrp(int nOldGrpId, int nNewGrpId,
         }
     }
 
-    status = nc_enddef( nNewGrpId );
+    status = nc_enddef(nNewGrpId);
     NCDF_ERR(status);
     if( status != NC_NOERR )
     {
@@ -5126,7 +5314,7 @@ bool netCDFDataset::CloneGrp(int nOldGrpId, int nNewGrpId,
     }
 
     // Clone variable content
-    for( int i=0; i < nVarCount; i++ )
+    for( int i = 0; i < nVarCount; i++ )
     {
         if( !CloneVariableContent(nOldGrpId, nNewGrpId, i, i) )
         {
@@ -5144,30 +5332,31 @@ bool netCDFDataset::CloneGrp(int nOldGrpId, int nNewGrpId,
 bool netCDFDataset::GrowDim(int nLayerId, int nDimIdToGrow, size_t nNewSize)
 {
     int nCreationMode;
-    /* set nCreationMode based on eFormat */
-    switch ( eFormat ) {
+    // Set nCreationMode based on eFormat.
+    switch( eFormat )
+    {
 #ifdef NETCDF_HAS_NC2
-        case NCDF_FORMAT_NC2:
-            nCreationMode = NC_CLOBBER|NC_64BIT_OFFSET;
-            break;
+    case NCDF_FORMAT_NC2:
+        nCreationMode = NC_CLOBBER | NC_64BIT_OFFSET;
+        break;
 #endif
 #ifdef NETCDF_HAS_NC4
-        case NCDF_FORMAT_NC4:
-            nCreationMode = NC_CLOBBER|NC_NETCDF4;
-            break;
-        case NCDF_FORMAT_NC4C:
-            nCreationMode = NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL;
-            break;
+    case NCDF_FORMAT_NC4:
+        nCreationMode = NC_CLOBBER | NC_NETCDF4;
+        break;
+    case NCDF_FORMAT_NC4C:
+        nCreationMode = NC_CLOBBER | NC_NETCDF4 | NC_CLASSIC_MODEL;
+        break;
 #endif
-        case NCDF_FORMAT_NC:
-        default:
-            nCreationMode = NC_CLOBBER;
-            break;
+    case NCDF_FORMAT_NC:
+    default:
+        nCreationMode = NC_CLOBBER;
+        break;
     }
 
     int new_cdfid = -1;
-    CPLString osTmpFilename( osFilename + ".tmp" );
-    int status = nc_create( osTmpFilename, nCreationMode, &new_cdfid );
+    CPLString osTmpFilename(osFilename + ".tmp");
+    int status = nc_create(osTmpFilename, nCreationMode, &new_cdfid);
     NCDF_ERR(status)
     if( status != NC_NOERR )
         return false;
@@ -5187,10 +5376,11 @@ bool netCDFDataset::GrowDim(int nLayerId, int nDimIdToGrow, size_t nNewSize)
         nc_inq_grps(cdfid, &nGroupCount, NULL) == NC_NOERR &&
         nGroupCount > 0 )
     {
-        int* panGroupIds = static_cast<int*>(CPLMalloc(sizeof(int) * nGroupCount));
+        int *panGroupIds =
+            static_cast<int *>(CPLMalloc(sizeof(int) * nGroupCount));
         status = nc_inq_grps(cdfid, NULL, panGroupIds);
         NCDF_ERR(status)
-        for(int i=0;i<nGroupCount;i++)
+        for(int i = 0; i < nGroupCount; i++)
         {
             char szGroupName[NC_MAX_NAME + 1];
             szGroupName[0] = 0;
@@ -5215,7 +5405,7 @@ bool netCDFDataset::GrowDim(int nLayerId, int nDimIdToGrow, size_t nNewSize)
         }
         CPLFree(panGroupIds);
 
-        for(int i=0;i<nLayers;i++)
+        for(int i = 0; i < nLayers; i++)
         {
             char szGroupName[NC_MAX_NAME + 1];
             szGroupName[0] = 0;
@@ -5230,38 +5420,39 @@ bool netCDFDataset::GrowDim(int nLayerId, int nDimIdToGrow, size_t nNewSize)
     cdfid = -1;
     nc_close(new_cdfid);
 
-    CPLString osOriFilename( osFilename + ".ori" );
-    if( VSIRename( osFilename, osOriFilename ) != 0 ||
-        VSIRename( osTmpFilename, osFilename ) != 0 )
+    CPLString osOriFilename(osFilename + ".ori");
+    if( VSIRename(osFilename, osOriFilename) != 0 ||
+        VSIRename(osTmpFilename, osFilename) != 0 )
     {
         CPLError(CE_Failure, CPLE_FileIO, "Renaming of files failed");
         return false;
     }
-    VSIUnlink( osOriFilename );
+    VSIUnlink(osOriFilename);
 
-    status = nc_open( osFilename, NC_WRITE, &cdfid );
+    status = nc_open(osFilename, NC_WRITE, &cdfid);
     NCDF_ERR(status);
     if( status != NC_NOERR )
         return false;
     bDefineMode = false;
 
 #ifdef NETCDF_HAS_NC4
-    if( oListGrpName.size() )
+    if( !oListGrpName.empty() )
     {
-        for(int i=0;i<nLayers;i++)
+        for(int i = 0; i < nLayers; i++)
         {
             int nNewLayerCDFID = -1;
-            status = nc_inq_ncid(cdfid, oListGrpName[i].c_str(), &nNewLayerCDFID);
+            status =
+                nc_inq_ncid(cdfid, oListGrpName[i].c_str(), &nNewLayerCDFID);
             NCDF_ERR(status);
-            papoLayers[i]->SetCDFID( nNewLayerCDFID );
+            papoLayers[i]->SetCDFID(nNewLayerCDFID);
         }
     }
     else
 #endif
     {
-        for(int i=0;i<nLayers;i++)
+        for(int i = 0; i < nLayers; i++)
         {
-            papoLayers[i]->SetCDFID( cdfid );
+            papoLayers[i]->SetCDFID(cdfid);
         }
     }
 
@@ -5272,13 +5463,14 @@ bool netCDFDataset::GrowDim(int nLayerId, int nDimIdToGrow, size_t nNewSize)
 /*                              Identify()                              */
 /************************************************************************/
 
-int netCDFDataset::Identify( GDALOpenInfo * poOpenInfo )
+int netCDFDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 {
-    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") ) {
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") )
+    {
         return TRUE;
     }
-    const NetCDFFormatEnum eTmpFormat = IdentifyFormat( poOpenInfo );
+    const NetCDFFormatEnum eTmpFormat = IdentifyFormat(poOpenInfo);
     if( NCDF_FORMAT_NC == eTmpFormat ||
         NCDF_FORMAT_NC2 == eTmpFormat ||
         NCDF_FORMAT_NC4 == eTmpFormat ||
@@ -5292,96 +5484,97 @@ int netCDFDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *netCDFDataset::Open( GDALOpenInfo *poOpenInfo )
 
 {
 #ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "\n=====\nOpen(), filename=[%s]", poOpenInfo->pszFilename );
+    CPLDebug("GDAL_netCDF", "\n=====\nOpen(), filename=[%s]",
+             poOpenInfo->pszFilename);
 #endif
 
-/* -------------------------------------------------------------------- */
-/*      Does this appear to be a netcdf file?                           */
-/* -------------------------------------------------------------------- */
+    // Does this appear to be a netcdf file?
     NetCDFFormatEnum eTmpFormat = NCDF_FORMAT_NONE;
-    if( ! STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") ) {
-        eTmpFormat = IdentifyFormat( poOpenInfo );
+    if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") )
+    {
+        eTmpFormat = IdentifyFormat(poOpenInfo);
 #ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "identified format %d", eTmpFormat );
+        CPLDebug("GDAL_netCDF", "identified format %d", eTmpFormat);
 #endif
-        /* Note: not calling Identify() directly, because we want the file type */
-        /* Only support NCDF_FORMAT* formats */
-        if( ! ( NCDF_FORMAT_NC  == eTmpFormat ||
-                NCDF_FORMAT_NC2  == eTmpFormat ||
-                NCDF_FORMAT_NC4  == eTmpFormat ||
-                NCDF_FORMAT_NC4C  == eTmpFormat ) )
+        // Note: not calling Identify() directly, because we want the file type.
+        // Only support NCDF_FORMAT* formats.
+        if( !(NCDF_FORMAT_NC == eTmpFormat ||
+              NCDF_FORMAT_NC2 == eTmpFormat ||
+              NCDF_FORMAT_NC4 == eTmpFormat ||
+              NCDF_FORMAT_NC4C == eTmpFormat) )
             return NULL;
     }
 
     CPLMutexHolderD(&hNCMutex);
 
-    CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock with
+                                // GDALDataset own mutex.
     netCDFDataset *poDS = new netCDFDataset();
     CPLAcquireMutex(hNCMutex, 1000.0);
 
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->SetDescription(poOpenInfo->pszFilename);
 
-/* -------------------------------------------------------------------- */
-/*       Check if filename start with NETCDF: tag                       */
-/* -------------------------------------------------------------------- */
+    // Check if filename start with NETCDF: tag.
     bool bTreatAsSubdataset = false;
     CPLString osSubdatasetName;
 
     if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NETCDF:") )
     {
         char **papszName =
-            CSLTokenizeString2( poOpenInfo->pszFilename,
-                                ":", CSLT_HONOURSTRINGS|CSLT_PRESERVEESCAPES );
+            CSLTokenizeString2(poOpenInfo->pszFilename,
+                               ":", CSLT_HONOURSTRINGS|CSLT_PRESERVEESCAPES);
 
-        /* -------------------------------------------------------------------- */
-        /*    Check for drive name in windows NETCDF:"D:\...                    */
-        /* -------------------------------------------------------------------- */
-        if ( CSLCount(papszName) == 4 &&
-             strlen(papszName[1]) == 1 &&
-             (papszName[2][0] == '/' || papszName[2][0] == '\\') )
+        // Check for drive name in windows NETCDF:"D:\...
+        if( CSLCount(papszName) == 4 &&
+            strlen(papszName[1]) == 1 &&
+            (papszName[2][0] == '/' || papszName[2][0] == '\\') )
         {
             poDS->osFilename = papszName[1];
             poDS->osFilename += ':';
             poDS->osFilename += papszName[2];
             osSubdatasetName = papszName[3];
             bTreatAsSubdataset = true;
-            CSLDestroy( papszName );
+            CSLDestroy(papszName);
         }
         else if( CSLCount(papszName) == 3 )
         {
             poDS->osFilename = papszName[1];
             osSubdatasetName = papszName[2];
             bTreatAsSubdataset = true;
-            CSLDestroy( papszName );
-    	}
+            CSLDestroy(papszName);
+        }
         else if( CSLCount(papszName) == 2 )
         {
             poDS->osFilename = papszName[1];
             osSubdatasetName = "";
             bTreatAsSubdataset = false;
-            CSLDestroy( papszName );
-    	}
+            CSLDestroy(papszName);
+        }
         else
         {
-            CSLDestroy( papszName );
-            CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            CSLDestroy(papszName);
+            CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll
+                                        // deadlock with GDALDataset own mutex.
             delete poDS;
             CPLAcquireMutex(hNCMutex, 1000.0);
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Failed to parse NETCDF: prefix string into expected 2, 3 or 4 fields." );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Failed to parse NETCDF: prefix string into expected 2, 3 or 4 fields.");
             return NULL;
         }
-        /* Identify Format from real file, with bCheckExt=FALSE */
-        GDALOpenInfo* poOpenInfo2 = new GDALOpenInfo(poDS->osFilename.c_str(), GA_ReadOnly );
-        poDS->eFormat = IdentifyFormat( poOpenInfo2, FALSE );
+        // Identify Format from real file, with bCheckExt=FALSE.
+        GDALOpenInfo *poOpenInfo2 =
+            new GDALOpenInfo(poDS->osFilename.c_str(), GA_ReadOnly);
+        poDS->eFormat = IdentifyFormat(poOpenInfo2, FALSE);
         delete poOpenInfo2;
         if( NCDF_FORMAT_NONE == poDS->eFormat ||
-            NCDF_FORMAT_UNKNOWN == poDS->eFormat ) {
-            CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            NCDF_FORMAT_UNKNOWN == poDS->eFormat )
+        {
+            CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll
+                                        // deadlock with GDALDataset own mutex.
             delete poDS;
             CPLAcquireMutex(hNCMutex, 1000.0);
             return NULL;
@@ -5394,99 +5587,100 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->eFormat = eTmpFormat;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try opening the dataset.                                        */
-/* -------------------------------------------------------------------- */
+    // Try opening the dataset.
 #ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "calling nc_open( %s )", poDS->osFilename.c_str() );
+    CPLDebug("GDAL_netCDF", "calling nc_open(%s)", poDS->osFilename.c_str());
 #endif
     int cdfid;
     const int nMode = ((poOpenInfo->nOpenFlags & (GDAL_OF_UPDATE | GDAL_OF_VECTOR)) ==
                 (GDAL_OF_UPDATE | GDAL_OF_VECTOR)) ? NC_WRITE : NC_NOWRITE;
-    if( nc_open( poDS->osFilename, nMode, &cdfid ) != NC_NOERR ) {
+    if( nc_open(poDS->osFilename, nMode, &cdfid) != NC_NOERR )
+    {
 #ifdef NCDF_DEBUG
-        CPLDebug( "GDAL_netCDF", "error opening" );
+        CPLDebug("GDAL_netCDF", "error opening");
 #endif
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
 #ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "got cdfid=%d\n", cdfid );
+    CPLDebug("GDAL_netCDF", "got cdfid=%d", cdfid);
 #endif
 
-/* -------------------------------------------------------------------- */
-/*      Is this a real netCDF file?                                     */
-/* -------------------------------------------------------------------- */
+    // Is this a real netCDF file?
     int ndims;
     int ngatts;
     int nvars;
     int unlimdimid;
     int status = nc_inq(cdfid, &ndims, &nvars, &ngatts, &unlimdimid);
-    if( status != NC_NOERR ) {
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    if( status != NC_NOERR )
+    {
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Get file type from netcdf                                       */
-/* -------------------------------------------------------------------- */
+    // Get file type from netcdf.
     int nTmpFormat = NCDF_FORMAT_NONE;
-    status = nc_inq_format (cdfid, &nTmpFormat);
-    if ( status != NC_NOERR ) {
+    status = nc_inq_format(cdfid, &nTmpFormat);
+    if( status != NC_NOERR )
+    {
         NCDF_ERR(status);
     }
-    else {
-        CPLDebug( "GDAL_netCDF",
-                  "driver detected file type=%d, libnetcdf detected type=%d",
-                  poDS->eFormat, nTmpFormat );
-        if ( static_cast<NetCDFFormatEnum>(nTmpFormat) != poDS->eFormat ) {
-            /* warn if file detection conflicts with that from libnetcdf */
-            /* except for NC4C, which we have no way of detecting initially */
-            if ( nTmpFormat != NCDF_FORMAT_NC4C ) {
-                CPLError( CE_Warning, CPLE_AppDefined,
-                          "NetCDF driver detected file type=%d, but libnetcdf detected type=%d",
-                          poDS->eFormat, nTmpFormat );
+    else
+    {
+        CPLDebug("GDAL_netCDF",
+                 "driver detected file type=%d, libnetcdf detected type=%d",
+                 poDS->eFormat, nTmpFormat);
+        if( static_cast<NetCDFFormatEnum>(nTmpFormat) != poDS->eFormat )
+        {
+            // Warn if file detection conflicts with that from libnetcdf
+            // except for NC4C, which we have no way of detecting initially.
+            if( nTmpFormat != NCDF_FORMAT_NC4C )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "NetCDF driver detected file type=%d, but libnetcdf detected type=%d",
+                         poDS->eFormat, nTmpFormat);
             }
-            CPLDebug( "GDAL_netCDF", "setting file type to %d, was %d",
-                      nTmpFormat, poDS->eFormat );
+            CPLDebug("GDAL_netCDF", "setting file type to %d, was %d",
+                     nTmpFormat, poDS->eFormat);
             poDS->eFormat = static_cast<NetCDFFormatEnum>(nTmpFormat);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->eAccess == GA_Update && (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 )
+    // Confirm the requested access is supported.
+    if( poOpenInfo->eAccess == GA_Update &&
+        (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "The NETCDF driver does not support update access to existing"
-                  " datasets.\n" );
-        nc_close( cdfid );
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The NETCDF driver does not support update access to existing"
+                 " datasets.");
+        nc_close(cdfid);
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Does the request variable exist?                                */
-/* -------------------------------------------------------------------- */
+    // Does the request variable exist?
     if( bTreatAsSubdataset )
     {
         int var;
-        status = nc_inq_varid( cdfid, osSubdatasetName, &var);
-        if( status != NC_NOERR ) {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "%s is a netCDF file, but %s is not a variable.",
-                      poOpenInfo->pszFilename,
-                      osSubdatasetName.c_str() );
-
-            nc_close( cdfid );
-            CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        status = nc_inq_varid(cdfid, osSubdatasetName, &var);
+        if( status != NC_NOERR )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "%s is a netCDF file, but %s is not a variable.",
+                     poOpenInfo->pszFilename, osSubdatasetName.c_str());
+
+            nc_close(cdfid);
+            CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll
+                                        // deadlock with GDALDataset own mutex.
             delete poDS;
             CPLAcquireMutex(hNCMutex, 1000.0);
             return NULL;
@@ -5495,51 +5689,48 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( ndims < 2 && (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "%s is a netCDF file, but without any dimensions >= 2.",
-                  poOpenInfo->pszFilename );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "%s is a netCDF file, but without any dimensions >= 2.",
+                 poOpenInfo->pszFilename);
 
-        nc_close( cdfid );
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        nc_close(cdfid);
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
 
-    CPLDebug( "GDAL_netCDF", "dim_count = %d", ndims );
+    CPLDebug("GDAL_netCDF", "dim_count = %d", ndims);
 
-    char szConventions[NC_MAX_NAME+1];
+    char szConventions[NC_MAX_NAME + 1];
     szConventions[0] = '\0';
-    nc_type nAttype=NC_NAT;
+    nc_type nAttype = NC_NAT;
     size_t nAttlen = 0;
-    nc_inq_att( cdfid, NC_GLOBAL, "Conventions", &nAttype, &nAttlen);
+    nc_inq_att(cdfid, NC_GLOBAL, "Conventions", &nAttype, &nAttlen);
     if( nAttlen >= sizeof(szConventions) ||
-        (status = nc_get_att_text( cdfid, NC_GLOBAL, "Conventions",
-                                   szConventions )) != NC_NOERR ) {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "No UNIDATA NC_GLOBAL:Conventions attribute");
-        /* note that 'Conventions' is always capital 'C' in CF spec*/
+        (status = nc_get_att_text(cdfid, NC_GLOBAL, "Conventions",
+                                  szConventions)) != NC_NOERR )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "No UNIDATA NC_GLOBAL:Conventions attribute");
+        // Note that 'Conventions' is always capital 'C' in CF spec.
     }
     else
     {
         szConventions[nAttlen] = '\0';
     }
 
+    // Create band information objects.
+    CPLDebug("GDAL_netCDF", "var_count = %d", nvars);
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
-    CPLDebug( "GDAL_netCDF", "var_count = %d", nvars );
-
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/*      Create Netcdf Subdataset if filename as NETCDF tag              */
-/* -------------------------------------------------------------------- */
+    // Create a corresponding GDALDataset.
+    // Create Netcdf Subdataset if filename as NETCDF tag.
     poDS->cdfid = cdfid;
     poDS->eAccess = poOpenInfo->eAccess;
     poDS->bDefineMode = false;
 
-    poDS->ReadAttributes( cdfid, NC_GLOBAL );
+    poDS->ReadAttributes(cdfid, NC_GLOBAL);
 
     int nCount = 0;
     int nVarID = -1;
@@ -5551,7 +5742,7 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     // check if there are vector layers.
 #ifdef NETCDF_HAS_NC4
     int nGroupCount = 0;
-    int* panGroupIds = NULL;
+    int *panGroupIds = NULL;
     if( nvars == 0 &&
         poDS->eFormat == NCDF_FORMAT_NC4 &&
         (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) == 0 &&
@@ -5561,412 +5752,473 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     if( nGroupCount > 0 )
     {
-        panGroupIds = static_cast<int*>(CPLMalloc(sizeof(int) * nGroupCount));
+        panGroupIds = static_cast<int *>(CPLMalloc(sizeof(int) * nGroupCount));
         nc_inq_grps(cdfid, NULL, panGroupIds);
     }
     for( int iGrp = 0; iGrp < ((nGroupCount) ? nGroupCount : 1); iGrp ++ )
     {
-    char szGroupName[NC_MAX_NAME + 1];
-    szGroupName[0] = 0;
-    int iGrpId = (nGroupCount) ? panGroupIds[iGrp] : cdfid;
-    if( nGroupCount )
-    {
-        nc_inq_grpname (iGrpId, szGroupName);
-        ndims = 0;
-        ngatts = 0;
-        nvars = 0;
-        unlimdimid = -1;
-        status = nc_inq(iGrpId, &ndims, &nvars, &ngatts, &unlimdimid);
-        NCDF_ERR(status);
-
-        CSLDestroy(poDS->papszMetadata);
-        poDS->papszMetadata = NULL;
-        poDS->ReadAttributes( cdfid, NC_GLOBAL );
-        poDS->ReadAttributes( iGrpId, NC_GLOBAL );
+        char szGroupName[NC_MAX_NAME + 1];
+        szGroupName[0] = 0;
+        int iGrpId = (nGroupCount) ? panGroupIds[iGrp] : cdfid;
+        if( nGroupCount )
+        {
+            nc_inq_grpname(iGrpId, szGroupName);
+            ndims = 0;
+            ngatts = 0;
+            nvars = 0;
+            unlimdimid = -1;
+            status = nc_inq(iGrpId, &ndims, &nvars, &ngatts, &unlimdimid);
+            NCDF_ERR(status);
 
-    }
-    else
-        snprintf( szGroupName, sizeof(szGroupName), "%s", CPLGetBasename(poDS->osFilename) );
-    poDS->cdfid = iGrpId;
+            CSLDestroy(poDS->papszMetadata);
+            poDS->papszMetadata = NULL;
+            poDS->ReadAttributes(cdfid, NC_GLOBAL);
+            poDS->ReadAttributes(iGrpId, NC_GLOBAL);
+        }
+        else
+        {
+            snprintf(szGroupName, sizeof(szGroupName), "%s",
+                     CPLGetBasename(poDS->osFilename));
+        }
+        poDS->cdfid = iGrpId;
 #else
     char szGroupName[NC_MAX_NAME + 1];
-    snprintf( szGroupName, sizeof(szGroupName), "%s", CPLGetBasename(poDS->osFilename) );
+    snprintf(szGroupName, sizeof(szGroupName),
+             "%s", CPLGetBasename(poDS->osFilename));
 #endif
 
-/* -------------------------------------------------------------------- */
-/*  Identify variables that we should ignore as Raster Bands.           */
-/*  Variables that are identified in other variable's "coordinate" and  */
-/*  "bounds" attribute should not be treated as Raster Bands.           */
-/*  See CF sections 5.2, 5.6 and 7.1                                    */
-/* -------------------------------------------------------------------- */
+    // Identify variables that we should ignore as Raster Bands.
+    // Variables that are identified in other variable's "coordinate" and
+    // "bounds" attribute should not be treated as Raster Bands.
+    // See CF sections 5.2, 5.6 and 7.1.
     char **papszIgnoreVars = NULL;
 
-    for ( int j = 0; j < nvars; j++ ) {
-        char **papszTokens = NULL;
-        if ( NCDFGetAttr( poDS->cdfid, j, "coordinates", &pszTemp ) == CE_None ) {
-            papszTokens = CSLTokenizeString2( pszTemp, " ", 0 );
-            for ( int i=0; i<CSLCount(papszTokens); i++ ) {
-                papszIgnoreVars = CSLAddString( papszIgnoreVars, papszTokens[i] );
-            }
-            if ( papszTokens) CSLDestroy( papszTokens );
-            CPLFree( pszTemp );
-        }
-        if ( NCDFGetAttr( poDS->cdfid, j, "bounds", &pszTemp ) == CE_None &&
-             pszTemp != NULL ) {
-            if ( !EQUAL( pszTemp, "" ) )
-                papszIgnoreVars = CSLAddString( papszIgnoreVars, pszTemp );
-            CPLFree( pszTemp );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*  Filter variables (valid 2D raster bands and vector fields)          */
-/* -------------------------------------------------------------------- */
-    nIgnoredVars = 0;
-    std::vector<int> anPotentialVectorVarID;
-    // oMapDimIdToCount[x] = number of times dim x is the first dimension of potential vector variables
-    std::map<int, int> oMapDimIdToCount;
-    int nVarXId = -1;
-    int nVarYId = -1;
-    int nVarZId = -1;
-    bool bIsVectorOnly = true;
-    int nProfileDimId = -1;
-    int nParentIndexVarID = -1;
-
-    for ( int j = 0; j < nvars; j++ ) {
-        int ndimsForVar = -1;
-        char szTemp[NC_MAX_NAME+1];
-        nc_inq_varndims ( poDS->cdfid, j, &ndimsForVar );
-        /* should we ignore this variable ? */
-        szTemp[0] = '\0';
-        status = nc_inq_varname( poDS->cdfid, j, szTemp );
-        if ( status != NC_NOERR )
-            continue;
-
-        nc_type atttype=NC_NAT;
-        size_t attlen = 0;
-
-        if( ndimsForVar == 1 &&
-            (NCDFIsVarLongitude( poDS->cdfid, -1, szTemp) ||
-             NCDFIsVarProjectionX( poDS->cdfid, -1, szTemp)) )
-        {
-            nVarXId = j;
-        }
-        else if( ndimsForVar == 1 &&
-            (NCDFIsVarLatitude( poDS->cdfid, -1, szTemp) ||
-             NCDFIsVarProjectionY( poDS->cdfid, -1, szTemp)) )
+        for( int j = 0; j < nvars; j++ )
         {
-            nVarYId = j;
-        }
-        else if( ndimsForVar == 1 &&
-            NCDFIsVarVerticalCoord( poDS->cdfid, -1, szTemp) )
+            if( NCDFGetAttr(poDS->cdfid, j, "coordinates", &pszTemp) == CE_None )
+            {
+                char **papszTokens = CSLTokenizeString2(pszTemp, " ", 0);
+                for( int i = 0; i<CSLCount(papszTokens); i++ )
+                {
+                    papszIgnoreVars =
+                        CSLAddString(papszIgnoreVars, papszTokens[i]);
+                }
+                if( papszTokens ) CSLDestroy(papszTokens);
+                CPLFree(pszTemp);
+             }
+            if( NCDFGetAttr(poDS->cdfid, j, "bounds", &pszTemp) == CE_None &&
+                pszTemp != NULL )
+            {
+                if( !EQUAL(pszTemp, "") )
+                    papszIgnoreVars = CSLAddString(papszIgnoreVars, pszTemp);
+                CPLFree(pszTemp);
+            }
+        }
+
+        // Filter variables (valid 2D raster bands and vector fields).
+        nIgnoredVars = 0;
+        std::vector<int> anPotentialVectorVarID;
+        // oMapDimIdToCount[x] = number of times dim x is the first dimension of
+        // potential vector variables
+        std::map<int, int> oMapDimIdToCount;
+        int nVarXId = -1;
+        int nVarYId = -1;
+        int nVarZId = -1;
+        bool bIsVectorOnly = true;
+        int nProfileDimId = -1;
+        int nParentIndexVarID = -1;
+
+        for( int j = 0; j < nvars; j++ )
         {
-            nVarZId = j;
-        }
-        else if ( CSLFindString( papszIgnoreVars, szTemp ) != -1 ) {
-            nIgnoredVars++;
-            CPLDebug( "GDAL_netCDF", "variable #%d [%s] was ignored",j, szTemp);
-        }
-        /* only accept 2+D vars */
-        else if( ndimsForVar >= 2 ) {
+            int ndimsForVar = -1;
+            char szTemp[NC_MAX_NAME + 1];
+            nc_inq_varndims(poDS->cdfid, j, &ndimsForVar);
+            // Should we ignore this variable?
+            szTemp[0] = '\0';
+            status = nc_inq_varname(poDS->cdfid, j, szTemp);
+            if( status != NC_NOERR )
+                continue;
+
+            nc_type atttype = NC_NAT;
+            size_t attlen = 0;
 
-            // Identify variables that might be vector variables
-            if( ndimsForVar == 2 )
+            if( ndimsForVar == 1 &&
+                (NCDFIsVarLongitude(poDS->cdfid, -1, szTemp) ||
+                NCDFIsVarProjectionX(poDS->cdfid, -1, szTemp)) )
+            {
+                nVarXId = j;
+            }
+            else if( ndimsForVar == 1 &&
+                     (NCDFIsVarLatitude(poDS->cdfid, -1, szTemp) ||
+                      NCDFIsVarProjectionY(poDS->cdfid, -1, szTemp)) )
+            {
+                nVarYId = j;
+            }
+            else if( ndimsForVar == 1 &&
+                     NCDFIsVarVerticalCoord(poDS->cdfid, -1, szTemp) )
+            {
+                nVarZId = j;
+            }
+            else if( CSLFindString(papszIgnoreVars, szTemp) != -1 )
+            {
+                nIgnoredVars++;
+                CPLDebug("GDAL_netCDF", "variable #%d [%s] was ignored", j,
+                         szTemp);
+            }
+            // Only accept 2+D vars.
+            else if( ndimsForVar >= 2 )
             {
-                int anDimIds[2] = { -1, -1 };
-                nc_inq_vardimid( poDS->cdfid, j, anDimIds );
-                char szDimNameX[NC_MAX_NAME+1], szDimNameY[NC_MAX_NAME+1];
-                szDimNameX[0]='\0';
-                szDimNameY[0]='\0';
-                if ( nc_inq_dimname( poDS->cdfid, anDimIds[0], szDimNameY ) == NC_NOERR &&
-                     nc_inq_dimname( poDS->cdfid, anDimIds[1], szDimNameX ) == NC_NOERR &&
-                     NCDFIsVarLongitude( poDS->cdfid, -1, szDimNameX )==false &&
-                     NCDFIsVarProjectionX( poDS->cdfid, -1, szDimNameX )==false &&
-                     NCDFIsVarLatitude( poDS->cdfid, -1, szDimNameY )==false &&
-                     NCDFIsVarProjectionY( poDS->cdfid, -1, szDimNameY )==false )
+
+                // Identify variables that might be vector variables
+                if( ndimsForVar == 2 )
                 {
-                    anPotentialVectorVarID.push_back(j);
-                    oMapDimIdToCount[ anDimIds[0] ] ++;
+                    int anDimIds[2] = { -1, -1 };
+                    nc_inq_vardimid(poDS->cdfid, j, anDimIds);
+                    char szDimNameX[NC_MAX_NAME + 1];
+                    char szDimNameY[NC_MAX_NAME + 1];
+                    szDimNameX[0] = '\0';
+                    szDimNameY[0] = '\0';
+                    if( nc_inq_dimname(poDS->cdfid, anDimIds[0], szDimNameY) ==
+                           NC_NOERR &&
+                       nc_inq_dimname(poDS->cdfid, anDimIds[1], szDimNameX) ==
+                           NC_NOERR &&
+                       NCDFIsVarLongitude(poDS->cdfid, -1, szDimNameX) ==
+                           false &&
+                       NCDFIsVarProjectionX(poDS->cdfid, -1, szDimNameX) ==
+                           false &&
+                       NCDFIsVarLatitude(poDS->cdfid, -1, szDimNameY) ==
+                           false &&
+                       NCDFIsVarProjectionY(poDS->cdfid, -1, szDimNameY) ==
+                           false )
+                    {
+                        anPotentialVectorVarID.push_back(j);
+                        oMapDimIdToCount[anDimIds[0]]++;
+                    }
+                    else
+                    {
+                        bIsVectorOnly = false;
+                    }
                 }
                 else
+                {
                     bIsVectorOnly = false;
+                }
+                if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) != 0 )
+                {
+                    nVarID = j;
+                    nCount++;
+                }
             }
-            else
-                bIsVectorOnly = false;
-
-            if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) != 0 )
-            {
-                nVarID=j;
-                nCount++;
-            }
-        }
-        else if( ndimsForVar == 1 )
-        {
-            if( nc_inq_att( poDS->cdfid, j, "instance_dimension", &atttype, &attlen) == NC_NOERR &&
-                atttype == NC_CHAR && attlen < NC_MAX_NAME )
+            else if( ndimsForVar == 1 )
             {
-                char szInstanceDimension[NC_MAX_NAME+1];
-                if( nc_get_att_text ( poDS->cdfid, j, "instance_dimension",
-                                      szInstanceDimension ) == NC_NOERR )
+                if( nc_inq_att(poDS->cdfid, j, "instance_dimension", &atttype,
+                               &attlen) == NC_NOERR &&
+                    atttype == NC_CHAR && attlen < NC_MAX_NAME )
                 {
-                    szInstanceDimension[attlen] = 0;
-                    for(int idim = 0; idim < ndims; idim ++)
+                    char szInstanceDimension[NC_MAX_NAME + 1];
+                    if( nc_get_att_text(poDS->cdfid, j, "instance_dimension",
+                                        szInstanceDimension) == NC_NOERR )
                     {
-                        char szDimName[NC_MAX_NAME+1];
-                        szDimName[0] = 0;
-                        status = nc_inq_dimname( poDS->cdfid, idim, szDimName);
-                        NCDF_ERR(status);
+                        szInstanceDimension[attlen] = 0;
+                        for(int idim = 0; idim < ndims; idim++)
+                        {
+                            char szDimName[NC_MAX_NAME + 1];
+                            szDimName[0] = 0;
+                            status =
+                                nc_inq_dimname(poDS->cdfid, idim, szDimName);
+                            NCDF_ERR(status);
                         if( strcmp(szInstanceDimension, szDimName) == 0 )
+                            {
+                                nParentIndexVarID = j;
+                                nProfileDimId = idim;
+                                break;
+                            }
+                        }
+                        if( nProfileDimId < 0 )
                         {
-                            nParentIndexVarID = j;
-                            nProfileDimId = idim;
-                            break;
+                            CPLError(CE_Warning, CPLE_AppDefined,
+                                     "Attribute instance_dimension='%s' refers "
+                                     "to a non existing dimension",
+                                     szInstanceDimension);
                         }
                     }
-                    if( nProfileDimId < 0 )
-                    {
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                "Attribute instance_dimension='%s' refers to a non existing dimension",
-                                szInstanceDimension);
-                    }
                 }
-            }
-            if( j != nParentIndexVarID )
-            {
-                anPotentialVectorVarID.push_back(j);
-                int nDimId = -1;
-                nc_inq_vardimid( poDS->cdfid, j, &nDimId );
-                oMapDimIdToCount[ nDimId ] ++;
+                if( j != nParentIndexVarID )
+                {
+                    anPotentialVectorVarID.push_back(j);
+                    int nDimId = -1;
+                    nc_inq_vardimid(poDS->cdfid, j, &nDimId);
+                    oMapDimIdToCount[nDimId]++;
+                }
             }
         }
-    }
 
-    CSLDestroy( papszIgnoreVars );
+        CSLDestroy(papszIgnoreVars);
 
-    CPLString osFeatureType(
-        CSLFetchNameValueDef(poDS->papszMetadata, "NC_GLOBAL#featureType", ""));
+        CPLString osFeatureType(CSLFetchNameValueDef(
+            poDS->papszMetadata, "NC_GLOBAL#featureType", ""));
 
-    // If we are opened in raster-only mode and that there are only 1D or 2D
-    // variables and that the 2D variables have no X/Y dim, and all variables
-    // refer to the same main dimension (or 2 dimensions for featureType=profile),
-    // then it is a pure vector dataset
-    if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) != 0 &&
-        (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 &&
-        bIsVectorOnly && nCount > 0 &&
-        anPotentialVectorVarID.size() != 0 &&
-        (oMapDimIdToCount.size() == 1 ||
-         (EQUAL(osFeatureType, "profile") && oMapDimIdToCount.size() == 2 && nProfileDimId >= 0)) )
-    {
-        anPotentialVectorVarID.resize(0);
-        nCount = 0;
-    }
-
-    if( anPotentialVectorVarID.size() != 0 &&
-        (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) != 0 )
-    {
-        // Take the dimension that is referenced the most times
-        if( !(oMapDimIdToCount.size() == 1 ||
-              (EQUAL(osFeatureType, "profile") && oMapDimIdToCount.size() == 2 && nProfileDimId >= 0)) )
+        // If we are opened in raster-only mode and that there are only 1D or 2D
+        // variables and that the 2D variables have no X/Y dim, and all
+        // variables refer to the same main dimension (or 2 dimensions for
+        // featureType=profile), then it is a pure vector dataset
+        if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) != 0 &&
+            (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) == 0 &&
+            bIsVectorOnly && nCount > 0 &&
+            !anPotentialVectorVarID.empty() &&
+            (oMapDimIdToCount.size() == 1 ||
+             (EQUAL(osFeatureType, "profile") && oMapDimIdToCount.size() == 2 &&
+              nProfileDimId >= 0)) )
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "The dataset has several variables that could be identified "
-                     "as vector fields, but not all share the same primary dimension. "
-                     "Consequently they will be ignored.");
+            anPotentialVectorVarID.resize(0);
+            nCount = 0;
         }
-        else
-        {
-            OGRwkbGeometryType eGType = wkbUnknown;
-            CPLString osLayerName = CSLFetchNameValueDef(
-                poDS->papszMetadata, "NC_GLOBAL#ogr_layer_name", szGroupName);
-            poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#ogr_layer_name", NULL);
 
-            if( EQUAL(osFeatureType, "point") || EQUAL(osFeatureType, "profile") )
+        if( !anPotentialVectorVarID.empty() &&
+            (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) != 0 )
+        {
+            // Take the dimension that is referenced the most times
+            if( !(oMapDimIdToCount.size() == 1 ||
+              (EQUAL(osFeatureType, "profile") && oMapDimIdToCount.size() == 2 && nProfileDimId >= 0)) )
             {
-                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#featureType", NULL);
-                eGType = wkbPoint;
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "The dataset has several variables that could be identified "
+                         "as vector fields, but not all share the same primary dimension. "
+                         "Consequently they will be ignored.");
             }
-
-            const char* pszLayerType = CSLFetchNameValue(poDS->papszMetadata, "NC_GLOBAL#ogr_layer_type");
-            if( pszLayerType != NULL )
+            else
             {
-                eGType = OGRFromOGCGeomType(pszLayerType);
-                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#ogr_layer_type", NULL);
-            }
+                OGRwkbGeometryType eGType = wkbUnknown;
+                CPLString osLayerName = CSLFetchNameValueDef(
+                poDS->papszMetadata, "NC_GLOBAL#ogr_layer_name", szGroupName);
+                poDS->papszMetadata = CSLSetNameValue(
+                    poDS->papszMetadata, "NC_GLOBAL#ogr_layer_name", NULL);
 
-            CPLString osGeometryField = CSLFetchNameValueDef(poDS->papszMetadata, "NC_GLOBAL#ogr_geometry_field", "");
-            poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#ogr_geometry_field", NULL);
+                if( EQUAL(osFeatureType, "point") ||
+                    EQUAL(osFeatureType, "profile") )
+                {
+                    poDS->papszMetadata = CSLSetNameValue(
+                        poDS->papszMetadata, "NC_GLOBAL#featureType", NULL);
+                    eGType = wkbPoint;
+                }
 
-            int nFirstVarId = -1;
-            int nVectorDim = oMapDimIdToCount.rbegin()->first;
-            if( EQUAL(osFeatureType, "profile") && oMapDimIdToCount.size() == 2 )
-            {
-                if( nVectorDim == nProfileDimId )
-                    nVectorDim = oMapDimIdToCount.begin()->first;
-            }
-            else
-                nProfileDimId = -1;
-            for( size_t j = 0; j < anPotentialVectorVarID.size(); j++ )
-            {
-                int anDimIds[2] = { -1, -1 };
-                nc_inq_vardimid( poDS->cdfid, anPotentialVectorVarID[j], anDimIds );
-                if( nVectorDim == anDimIds[0] )
+                const char *pszLayerType = CSLFetchNameValue(
+                    poDS->papszMetadata, "NC_GLOBAL#ogr_layer_type");
+                if( pszLayerType != NULL )
                 {
-                    nFirstVarId = anPotentialVectorVarID[j];
-                    break;
+                    eGType = OGRFromOGCGeomType(pszLayerType);
+                    poDS->papszMetadata = CSLSetNameValue(
+                        poDS->papszMetadata, "NC_GLOBAL#ogr_layer_type", NULL);
                 }
-            }
 
-            // In case where coordinates are explicitly specified for one of the field/variable,
-            // use them in priority over the ones that might have been identified above
-            char* pszCoordinates = NULL;
-            if( NCDFGetAttr( poDS->cdfid, nFirstVarId, "coordinates", &pszCoordinates) == CE_None )
-            {
-                char** papszTokens = CSLTokenizeString2( pszCoordinates, " ", 0 );
-                for ( int i=0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
+                CPLString osGeometryField = CSLFetchNameValueDef(
+                    poDS->papszMetadata, "NC_GLOBAL#ogr_geometry_field", "");
+                poDS->papszMetadata = CSLSetNameValue(
+                    poDS->papszMetadata, "NC_GLOBAL#ogr_geometry_field", NULL);
+
+                int nFirstVarId = -1;
+                int nVectorDim = oMapDimIdToCount.rbegin()->first;
+                if( EQUAL(osFeatureType, "profile") &&
+                    oMapDimIdToCount.size() == 2 )
+                {
+                    if( nVectorDim == nProfileDimId )
+                        nVectorDim = oMapDimIdToCount.begin()->first;
+                }
+                else
+                {
+                    nProfileDimId = -1;
+                }
+                for( size_t j = 0; j < anPotentialVectorVarID.size(); j++ )
+                {
+                    int anDimIds[2] = { -1, -1 };
+                    nc_inq_vardimid(poDS->cdfid, anPotentialVectorVarID[j],
+                                    anDimIds);
+                    if( nVectorDim == anDimIds[0] )
+                    {
+                        nFirstVarId = anPotentialVectorVarID[j];
+                        break;
+                    }
+                }
+
+                // In case where coordinates are explicitly specified for one of
+                // the field/variable,
+                // use them in priority over the ones that might have been
+                // identified above.
+                char *pszCoordinates = NULL;
+                if( NCDFGetAttr(poDS->cdfid, nFirstVarId, "coordinates",
+                                &pszCoordinates) == CE_None )
                 {
-                    if( NCDFIsVarLongitude( poDS->cdfid, -1, papszTokens[i] ) ||
-                        NCDFIsVarProjectionX( poDS->cdfid, -1, papszTokens[i] ) )
+                    char **papszTokens =
+                        CSLTokenizeString2(pszCoordinates, " ", 0);
+                    for(int i = 0;
+                        papszTokens != NULL && papszTokens[i] != NULL; i++)
                     {
-                        nVarXId = -1;
-                        CPL_IGNORE_RET_VAL(nc_inq_varid(poDS->cdfid, papszTokens[i], &nVarXId));
+                        if( NCDFIsVarLongitude(poDS->cdfid, -1,
+                                               papszTokens[i]) ||
+                            NCDFIsVarProjectionX(poDS->cdfid, -1,
+                                                 papszTokens[i]) )
+                        {
+                            nVarXId = -1;
+                            CPL_IGNORE_RET_VAL(nc_inq_varid(
+                                poDS->cdfid, papszTokens[i], &nVarXId));
+                        }
+                        else if( NCDFIsVarLatitude(poDS->cdfid, -1,
+                                                   papszTokens[i]) ||
+                                 NCDFIsVarProjectionY(poDS->cdfid, -1,
+                                                      papszTokens[i]) )
+                        {
+                            nVarYId = -1;
+                            CPL_IGNORE_RET_VAL(nc_inq_varid(
+                                poDS->cdfid, papszTokens[i], &nVarYId));
+                        }
+                        else if( NCDFIsVarVerticalCoord(poDS->cdfid, -1,
+                                                       papszTokens[i]))
+                        {
+                            nVarZId = -1;
+                            CPL_IGNORE_RET_VAL(nc_inq_varid(
+                                poDS->cdfid, papszTokens[i], &nVarZId));
+                        }
                     }
-                    else if( NCDFIsVarLatitude( poDS->cdfid, -1, papszTokens[i] ) ||
-                             NCDFIsVarProjectionY( poDS->cdfid, -1, papszTokens[i] ) )
+                    CSLDestroy(papszTokens);
+                }
+                CPLFree(pszCoordinates);
+
+                // Check that the X,Y,Z vars share 1D and share the same
+                // dimension as attribute variables.
+                if( nVarXId >= 0 && nVarYId >= 0 )
+                {
+                    int nVarDimCount = -1;
+                    int nVarDimId = -1;
+                    if( nc_inq_varndims(poDS->cdfid, nVarXId, &nVarDimCount) != NC_NOERR ||
+                        nVarDimCount != 1 ||
+                        nc_inq_vardimid(poDS->cdfid, nVarXId, &nVarDimId) != NC_NOERR ||
+                        nVarDimId != ((nProfileDimId >= 0) ? nProfileDimId : nVectorDim) ||
+                        nc_inq_varndims(poDS->cdfid, nVarYId, &nVarDimCount) != NC_NOERR ||
+                        nVarDimCount != 1 ||
+                    nc_inq_vardimid(poDS->cdfid, nVarYId, &nVarDimId) != NC_NOERR ||
+                    nVarDimId != ((nProfileDimId >= 0) ? nProfileDimId : nVectorDim) )
                     {
-                        nVarYId = -1;
-                        CPL_IGNORE_RET_VAL(nc_inq_varid(poDS->cdfid, papszTokens[i], &nVarYId));
+                        nVarXId = nVarYId = -1;
                     }
-                    else if( NCDFIsVarVerticalCoord( poDS->cdfid, -1, papszTokens[i] ) )
+                    else if( nVarZId >= 0 &&
+                             (nc_inq_varndims(poDS->cdfid, nVarZId,
+                                              &nVarDimCount) != NC_NOERR ||
+                              nVarDimCount != 1 ||
+                              nc_inq_vardimid(poDS->cdfid, nVarZId,
+                                              &nVarDimId) != NC_NOERR ||
+                              nVarDimId != nVectorDim) )
                     {
                         nVarZId = -1;
-                        CPL_IGNORE_RET_VAL(nc_inq_varid(poDS->cdfid, papszTokens[i], &nVarZId));
                     }
                 }
-                CSLDestroy(papszTokens);
-            }
-            CPLFree(pszCoordinates);
 
-            // Check that the X,Y,Z vars share 1D and share the same dimension
-            // as attribute variables
-            if( nVarXId >= 0 && nVarYId >= 0 )
-            {
-                int nVarDimCount = -1, nVarDimId = -1;
-                if( nc_inq_varndims( poDS->cdfid, nVarXId, &nVarDimCount ) != NC_NOERR ||
-                    nVarDimCount != 1 ||
-                    nc_inq_vardimid( poDS->cdfid, nVarXId, &nVarDimId ) != NC_NOERR ||
-                    nVarDimId != ((nProfileDimId >= 0) ? nProfileDimId : nVectorDim) ||
-                    nc_inq_varndims( poDS->cdfid, nVarYId, &nVarDimCount ) != NC_NOERR ||
-                    nVarDimCount != 1 ||
-                    nc_inq_vardimid( poDS->cdfid, nVarYId, &nVarDimId ) != NC_NOERR ||
-                    nVarDimId != ((nProfileDimId >= 0) ? nProfileDimId : nVectorDim) )
+                if( eGType == wkbUnknown && nVarXId >= 0 && nVarYId >= 0 )
                 {
-                    nVarXId = nVarYId = -1;
+                    eGType = wkbPoint;
                 }
-                else if( nVarZId >= 0 &&
-                         (nc_inq_varndims( poDS->cdfid, nVarZId, &nVarDimCount ) != NC_NOERR ||
-                          nVarDimCount != 1 ||
-                          nc_inq_vardimid( poDS->cdfid, nVarZId, &nVarDimId ) != NC_NOERR ||
-                          nVarDimId != nVectorDim) )
+                if( eGType == wkbPoint && nVarXId >= 0 && nVarYId >= 0 &&
+                    nVarZId >= 0 )
                 {
-                    nVarZId = -1;
+                    eGType = wkbPoint25D;
+                }
+                if( eGType == wkbUnknown && osGeometryField.empty() )
+                {
+                    eGType = wkbNone;
                 }
-            }
-
-            if( eGType == wkbUnknown && nVarXId >= 0 && nVarYId >= 0 )
-            {
-                eGType = wkbPoint;
-            }
-            if( eGType == wkbPoint && nVarXId >= 0 && nVarYId >= 0 && nVarZId >= 0 )
-            {
-                eGType = wkbPoint25D;
-            }
-            if( eGType == wkbUnknown && osGeometryField.size() == 0 )
-            {
-                eGType = wkbNone;
-            }
-
-            // Read projection info
-            char** papszMetadataBackup = CSLDuplicate(poDS->papszMetadata);
-            poDS->ReadAttributes( poDS->cdfid, nFirstVarId );
-            poDS->SetProjectionFromVar( nFirstVarId, true );
-
-            char szVarName[ NC_MAX_NAME+1 ];
-            szVarName[0] = '\0';
-            CPL_IGNORE_RET_VAL(nc_inq_varname( poDS->cdfid, nFirstVarId, szVarName ));
-            char szTemp[ NC_MAX_NAME+1 ];
-            snprintf(szTemp,sizeof(szTemp), "%s#%s", szVarName,CF_GRD_MAPPING);
-            CPLString osGridMapping = CSLFetchNameValueDef(poDS->papszMetadata,
-                                                           szTemp, "");
-
-            CSLDestroy(poDS->papszMetadata);
-            poDS->papszMetadata = papszMetadataBackup;
 
-            OGRSpatialReference* poSRS = NULL;
-            if( poDS->pszProjection != NULL )
-            {
-                poSRS = new OGRSpatialReference();
-                char* pszWKT = poDS->pszProjection;
-                if( poSRS->importFromWkt(&pszWKT) != OGRERR_NONE )
+                // Read projection info
+                char **papszMetadataBackup = CSLDuplicate(poDS->papszMetadata);
+                poDS->ReadAttributes(poDS->cdfid, nFirstVarId);
+                poDS->SetProjectionFromVar(nFirstVarId, true);
+
+                char szVarName[NC_MAX_NAME + 1];
+                szVarName[0] = '\0';
+                CPL_IGNORE_RET_VAL(
+                    nc_inq_varname(poDS->cdfid, nFirstVarId, szVarName));
+                char szTemp[NC_MAX_NAME + 1];
+                snprintf(szTemp, sizeof(szTemp),
+                         "%s#%s", szVarName, CF_GRD_MAPPING);
+                CPLString osGridMapping =
+                    CSLFetchNameValueDef(poDS->papszMetadata, szTemp, "");
+
+                CSLDestroy(poDS->papszMetadata);
+                poDS->papszMetadata = papszMetadataBackup;
+
+                OGRSpatialReference *poSRS = NULL;
+                if( poDS->pszProjection != NULL )
                 {
-                    delete poSRS;
-                    poSRS = NULL;
+                    poSRS = new OGRSpatialReference();
+                    char *pszWKT = poDS->pszProjection;
+                    if( poSRS->importFromWkt(&pszWKT) != OGRERR_NONE )
+                    {
+                        delete poSRS;
+                        poSRS = NULL;
+                    }
+                    CPLFree(poDS->pszProjection);
+                    poDS->pszProjection = NULL;
                 }
-                CPLFree(poDS->pszProjection);
-                poDS->pszProjection = NULL;
-            }
-            // Reset if there's a 2D raster
-            poDS->bSetProjection = false;
-            poDS->bSetGeoTransform = false;
+                // Reset if there's a 2D raster
+                poDS->bSetProjection = false;
+                poDS->bSetGeoTransform = false;
 
             if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) == 0 )
-            {
-                // Strip out uninteresting metadata
-                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#Conventions", NULL);
-                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#GDAL", NULL);
-                poDS->papszMetadata = CSLSetNameValue(poDS->papszMetadata, "NC_GLOBAL#history", NULL);
-            }
+                {
+                    // Strip out uninteresting metadata.
+                    poDS->papszMetadata = CSLSetNameValue(
+                        poDS->papszMetadata, "NC_GLOBAL#Conventions", NULL);
+                    poDS->papszMetadata = CSLSetNameValue(
+                        poDS->papszMetadata, "NC_GLOBAL#GDAL", NULL);
+                    poDS->papszMetadata = CSLSetNameValue(
+                        poDS->papszMetadata, "NC_GLOBAL#history", NULL);
+                }
 
-            netCDFLayer* poLayer = new netCDFLayer(poDS, poDS->cdfid, osLayerName, eGType, poSRS);
-            if( poSRS != NULL )
-                poSRS->Release();
-            poLayer->SetRecordDimID(nVectorDim);
-            if( wkbFlatten(eGType) == wkbPoint && nVarXId >= 0 && nVarYId >= 0 )
-            {
-                poLayer->SetXYZVars( nVarXId, nVarYId, nVarZId );
-            }
-            else if( osGeometryField.size() )
-            {
-                poLayer->SetWKTGeometryField( osGeometryField );
-            }
-            if( osGridMapping.size() )
-            {
-                poLayer->SetGridMapping( osGridMapping );
-            }
-            poLayer->SetProfile( nProfileDimId, nParentIndexVarID );
-            poDS->papoLayers = static_cast<netCDFLayer**>(
-                CPLRealloc(poDS->papoLayers, (poDS->nLayers + 1) * sizeof(netCDFLayer*)));
-            poDS->papoLayers[poDS->nLayers++] = poLayer;
+                netCDFLayer *poLayer = new netCDFLayer(
+                    poDS, poDS->cdfid, osLayerName, eGType, poSRS);
+                if( poSRS != NULL )
+                    poSRS->Release();
+                poLayer->SetRecordDimID(nVectorDim);
+                if( wkbFlatten(eGType) == wkbPoint && nVarXId >= 0 &&
+                    nVarYId >= 0 )
+                {
+                    poLayer->SetXYZVars(nVarXId, nVarYId, nVarZId);
+                }
+                else if( !osGeometryField.empty() )
+                {
+                    poLayer->SetWKTGeometryField(osGeometryField);
+                }
+                if( !osGridMapping.empty() )
+                {
+                    poLayer->SetGridMapping(osGridMapping);
+                }
+                poLayer->SetProfile(nProfileDimId, nParentIndexVarID);
+                poDS->papoLayers = static_cast<netCDFLayer **>(
+                    CPLRealloc(poDS->papoLayers,
+                               (poDS->nLayers + 1) * sizeof(netCDFLayer *)));
+                poDS->papoLayers[poDS->nLayers++] = poLayer;
 
-            for( size_t j = 0; j < anPotentialVectorVarID.size(); j++ )
-            {
-                int anDimIds[2] = { -1, -1 };
-                nc_inq_vardimid( poDS->cdfid, anPotentialVectorVarID[j], anDimIds );
-                if( anDimIds[0] == nVectorDim || (nProfileDimId >= 0 &&  anDimIds[0] == nProfileDimId) )
+                for( size_t j = 0; j < anPotentialVectorVarID.size(); j++ )
                 {
+                    int anDimIds[2] = { -1, -1 };
+                    nc_inq_vardimid(poDS->cdfid, anPotentialVectorVarID[j],
+                                    anDimIds);
+                    if( anDimIds[0] == nVectorDim ||
+                        (nProfileDimId >= 0 && anDimIds[0] == nProfileDimId) )
+                    {
 #ifdef NCDF_DEBUG
-                    char szTemp[NC_MAX_NAME+1];
-                    szTemp[0] = '\0';
-                    CPL_IGNORE_RET_VAL(nc_inq_varname( poDS->cdfid, anPotentialVectorVarID[j], szTemp ));
-                    CPLDebug("GDAL_netCDF", "Variable %s is a vector field", szTemp);
+                        char szTemp2[NC_MAX_NAME + 1] = {};
+                        CPL_IGNORE_RET_VAL(nc_inq_varname(
+                            poDS->cdfid, anPotentialVectorVarID[j], szTemp2));
+                        CPLDebug("GDAL_netCDF", "Variable %s is a vector field",
+                                 szTemp2);
 #endif
-                    poLayer->AddField( anPotentialVectorVarID[j] );
+                        poLayer->AddField(anPotentialVectorVarID[j]);
+                    }
                 }
             }
         }
-    }
 
 #ifdef NETCDF_HAS_NC4
-    } /* end for group */
+    }  // End for group.
     CPLFree(panGroupIds);
     poDS->cdfid = cdfid;
 #endif
@@ -5974,8 +6226,9 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     // Case where there is no raster variable
     if( nCount == 0 && !bTreatAsSubdataset )
     {
-        poDS->SetMetadata( poDS->papszMetadata );
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        poDS->SetMetadata(poDS->papszMetadata);
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         poDS->TryLoadXML();
         // If the dataset has been opened in raster mode only, exit
         if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) != 0 &&
@@ -5994,165 +6247,155 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS = NULL;
         }
         CPLAcquireMutex(hNCMutex, 1000.0);
-        return( poDS );
+        return poDS;
     }
 
-/* -------------------------------------------------------------------- */
-/*      We have more than one variable with 2 dimensions in the         */
-/*      file, then treat this as a subdataset container dataset.        */
-/* -------------------------------------------------------------------- */
+    // We have more than one variable with 2 dimensions in the
+    // file, then treat this as a subdataset container dataset.
     if( (nCount > 1) && !bTreatAsSubdataset )
     {
         poDS->CreateSubDatasetList();
-        poDS->SetMetadata( poDS->papszMetadata );
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        poDS->SetMetadata(poDS->papszMetadata);
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         poDS->TryLoadXML();
         CPLAcquireMutex(hNCMutex, 1000.0);
-        return( poDS );
+        return poDS;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we are not treating things as a subdataset, then capture     */
-/*      the name of the single available variable as the subdataset.    */
-/* -------------------------------------------------------------------- */
+    // If we are not treating things as a subdataset, then capture
+    // the name of the single available variable as the subdataset.
     if( !bTreatAsSubdataset )
     {
-        char szVarName[NC_MAX_NAME+1];
+        char szVarName[NC_MAX_NAME + 1];
         szVarName[0] = '\0';
-        status = nc_inq_varname( cdfid, nVarID, szVarName);
+        status = nc_inq_varname(cdfid, nVarID, szVarName);
         NCDF_ERR(status);
         osSubdatasetName = szVarName;
     }
 
-/* -------------------------------------------------------------------- */
-/*      We have ignored at least one variable, so we should report them */
-/*      as subdatasets for reference.                                   */
-/* -------------------------------------------------------------------- */
-    if( (nIgnoredVars > 0) && !bTreatAsSubdataset )
+    // We have ignored at least one variable, so we should report them
+    // as subdatasets for reference.
+    if( nIgnoredVars > 0 && !bTreatAsSubdataset )
     {
-        CPLDebug( "GDAL_netCDF",
-                  "As %d variables were ignored, creating subdataset list "
-                  "for reference. Variable #%d [%s] is the main variable",
-                  nIgnoredVars, nVarID, osSubdatasetName.c_str() );
+        CPLDebug("GDAL_netCDF",
+                 "As %d variables were ignored, creating subdataset list "
+                 "for reference. Variable #%d [%s] is the main variable",
+                 nIgnoredVars, nVarID, osSubdatasetName.c_str());
         poDS->CreateSubDatasetList();
     }
 
-/* -------------------------------------------------------------------- */
-/*      Open the NETCDF subdataset NETCDF:"filename":subdataset         */
-/* -------------------------------------------------------------------- */
-    int var=-1;
-    nc_inq_varid( cdfid, osSubdatasetName, &var);
+    // Open the NETCDF subdataset NETCDF:"filename":subdataset.
+    int var = -1;
+    nc_inq_varid(cdfid, osSubdatasetName, &var);
     int nd = 0;
-    nc_inq_varndims ( cdfid, var, &nd );
+    nc_inq_varndims(cdfid, var, &nd);
 
-    int *paDimIds  = reinterpret_cast<int *>( CPLCalloc(nd, sizeof( int ) ) );
+    int *paDimIds = static_cast<int *>(CPLCalloc(nd, sizeof(int)));
 
     // X, Y, Z position in array
-    int *panBandDimPos
-        = reinterpret_cast<int *>( CPLCalloc( nd, sizeof( int ) ) );
-
-    nc_inq_vardimid( cdfid, var, paDimIds );
-
-/* -------------------------------------------------------------------- */
-/*      Check if somebody tried to pass a variable with less than 2D    */
-/* -------------------------------------------------------------------- */
-    if ( nd < 2 ) {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Variable has %d dimension(s) - not supported.", nd );
-        CPLFree( paDimIds );
-        CPLFree( panBandDimPos );
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    int *panBandDimPos = static_cast<int *>(CPLCalloc(nd, sizeof(int)));
+
+    nc_inq_vardimid(cdfid, var, paDimIds);
+
+    // Check if somebody tried to pass a variable with less than 2D.
+    if( nd < 2 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Variable has %d dimension(s) - not supported.", nd);
+        CPLFree(paDimIds);
+        CPLFree(panBandDimPos);
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      CF-1 Convention                                                 */
-/*      dimensions to appear in the relative order T, then Z, then Y,   */
-/*      then X  to the file. All other dimensions should, whenever      */
-/*      possible, be placed to the left of the spatiotemporal           */
-/*      dimensions.                                                     */
-/* -------------------------------------------------------------------- */
-
-/* -------------------------------------------------------------------- */
-/*      Verify that dimensions are in the {T,Z,Y,X} or {T,Z,Y,X} order  */
-/*      Ideally we should detect for other ordering and act accordingly */
-/*      Only done if file has Conventions=CF-* and only prints warning  */
-/*      To disable set GDAL_NETCDF_VERIFY_DIMS=NO and to use only       */
-/*      attributes (not varnames) set GDAL_NETCDF_VERIFY_DIMS=STRICT    */
-/* -------------------------------------------------------------------- */
-
-    bool bCheckDims =
-        CPLTestBool( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ) )
-        && STARTS_WITH_CI(szConventions, "CF");
-
-    char szDimName[NC_MAX_NAME+1];
-
-    if ( bCheckDims ) {
-        char szDimName1[NC_MAX_NAME+1], szDimName2[NC_MAX_NAME+1],
-            szDimName3[NC_MAX_NAME+1], szDimName4[NC_MAX_NAME+1];
-        szDimName1[0]='\0';
-        szDimName2[0]='\0';
-        szDimName3[0]='\0';
-        szDimName4[0]='\0';
-        status = nc_inq_dimname( cdfid, paDimIds[nd-1], szDimName1 );
+    // CF-1 Convention
+    //
+    // Dimensions to appear in the relative order T, then Z, then Y,
+    // then X  to the file. All other dimensions should, whenever
+    // possible, be placed to the left of the spatiotemporal
+    // dimensions.
+
+    // Verify that dimensions are in the {T,Z,Y,X} or {T,Z,Y,X} order
+    // Ideally we should detect for other ordering and act accordingly
+    // Only done if file has Conventions=CF-* and only prints warning
+    // To disable set GDAL_NETCDF_VERIFY_DIMS=NO and to use only
+    // attributes (not varnames) set GDAL_NETCDF_VERIFY_DIMS=STRICT
+    const bool bCheckDims =
+        CPLTestBool(CPLGetConfigOption("GDAL_NETCDF_VERIFY_DIMS", "YES")) &&
+        STARTS_WITH_CI(szConventions, "CF");
+
+    if( bCheckDims )
+    {
+        char szDimName1[NC_MAX_NAME + 1] = {};
+        char szDimName2[NC_MAX_NAME + 1] = {};
+        status = nc_inq_dimname(cdfid, paDimIds[nd - 1], szDimName1);
         NCDF_ERR(status);
-        status = nc_inq_dimname( cdfid, paDimIds[nd-2], szDimName2 );
+        status = nc_inq_dimname(cdfid, paDimIds[nd - 2], szDimName2);
         NCDF_ERR(status);
-        if (  NCDFIsVarLongitude( cdfid, -1, szDimName1 )==false &&
-              NCDFIsVarProjectionX( cdfid, -1, szDimName1 )==false ) {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "dimension #%d (%s) is not a Longitude/X dimension.",
-                      nd-1, szDimName1 );
-        }
-        if ( NCDFIsVarLatitude( cdfid, -1, szDimName2 )==false &&
-             NCDFIsVarProjectionY( cdfid, -1, szDimName2 )==false ) {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "dimension #%d (%s) is not a Latitude/Y dimension.",
-                      nd-2, szDimName2 );
-        }
-        if ( nd >= 3 ) {
-            status = nc_inq_dimname( cdfid, paDimIds[nd-3], szDimName3 );
+        if( NCDFIsVarLongitude(cdfid, -1, szDimName1) == false &&
+            NCDFIsVarProjectionX(cdfid, -1, szDimName1) == false )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "dimension #%d (%s) is not a Longitude/X dimension.",
+                     nd - 1, szDimName1);
+        }
+        if( NCDFIsVarLatitude(cdfid, -1, szDimName2) == false &&
+            NCDFIsVarProjectionY(cdfid, -1, szDimName2) == false )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "dimension #%d (%s) is not a Latitude/Y dimension.",
+                     nd - 2, szDimName2);
+        }
+        if( nd >= 3 )
+        {
+            char szDimName3[NC_MAX_NAME + 1] = {};
+            status = nc_inq_dimname(cdfid, paDimIds[nd - 3], szDimName3);
             NCDF_ERR(status);
-            if ( nd >= 4 ) {
-                status = nc_inq_dimname( cdfid, paDimIds[nd-4], szDimName4 );
+            if( nd >= 4 )
+            {
+                char szDimName4[NC_MAX_NAME + 1] = {};
+                status = nc_inq_dimname(cdfid, paDimIds[nd - 4], szDimName4);
                 NCDF_ERR(status);
-                if ( NCDFIsVarVerticalCoord( cdfid, -1, szDimName3 )==false ) {
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "dimension #%d (%s) is not a Time  dimension.",
-                              nd-3, szDimName3 );
+                if( NCDFIsVarVerticalCoord( cdfid, -1, szDimName3) == false )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "dimension #%d (%s) is not a Time dimension.",
+                             nd - 3, szDimName3);
                 }
-                if ( NCDFIsVarTimeCoord( cdfid, -1, szDimName4 )==false ) {
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "dimension #%d (%s) is not a Time  dimension.",
-                              nd-4, szDimName4 );
+                if( NCDFIsVarTimeCoord(cdfid, -1, szDimName4) == false )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "dimension #%d (%s) is not a Time dimension.",
+                             nd - 4, szDimName4);
                 }
             }
-            else {
-                if ( NCDFIsVarVerticalCoord( cdfid, -1, szDimName3 )==false &&
-                     NCDFIsVarTimeCoord( cdfid, -1, szDimName3 )==false ) {
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "dimension #%d (%s) is not a Time or Vertical dimension.",
-                              nd-3, szDimName3 );
+            else
+            {
+                if( NCDFIsVarVerticalCoord(cdfid, -1, szDimName3) == false &&
+                    NCDFIsVarTimeCoord(cdfid, -1, szDimName3) == false )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "dimension #%d (%s) is not a "
+                             "Time or Vertical dimension.",
+                             nd - 3, szDimName3);
                 }
             }
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Get X dimensions information                                    */
-/* -------------------------------------------------------------------- */
+    // Get X dimensions information.
     size_t xdim;
-    poDS->nXDimID = paDimIds[nd-1];
-    nc_inq_dimlen ( cdfid, poDS->nXDimID, &xdim );
+    poDS->nXDimID = paDimIds[nd - 1];
+    nc_inq_dimlen(cdfid, poDS->nXDimID, &xdim);
 
-/* -------------------------------------------------------------------- */
-/*      Get Y dimension information                                     */
-/* -------------------------------------------------------------------- */
+    // Get Y dimension information.
     size_t ydim;
-    poDS->nYDimID = paDimIds[nd-2];
-    nc_inq_dimlen ( cdfid, poDS->nYDimID, &ydim );
+    poDS->nYDimID = paDimIds[nd - 2];
+    nc_inq_dimlen(cdfid, poDS->nYDimID, &ydim);
 
     if( xdim > INT_MAX || ydim > INT_MAX )
     {
@@ -6160,9 +6403,10 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
                  "Invalid raster dimensions: " CPL_FRMT_GUIB "x" CPL_FRMT_GUIB,
                  static_cast<GUIntBig>(xdim),
                  static_cast<GUIntBig>(ydim));
-        CPLFree( paDimIds );
-        CPLFree( panBandDimPos );
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        CPLFree(paDimIds);
+        CPLFree(panBandDimPos);
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
@@ -6172,67 +6416,66 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterYSize = static_cast<int>(ydim);
 
     unsigned int k = 0;
-    for( int j=0; j < nd; j++ ){
-        if( paDimIds[j] == poDS->nXDimID ){
-            panBandDimPos[0] = j;         // Save Position of XDim
+    for( int j = 0; j < nd; j++ )
+    {
+        if( paDimIds[j] == poDS->nXDimID )
+        {
+            panBandDimPos[0] = j;  // Save Position of XDim
             k++;
         }
-        if( paDimIds[j] == poDS->nYDimID ){
-            panBandDimPos[1] = j;         // Save Position of YDim
+        if( paDimIds[j] == poDS->nYDimID )
+        {
+            panBandDimPos[1] = j;  // Save Position of YDim
             k++;
         }
     }
-/* -------------------------------------------------------------------- */
-/*      X and Y Dimension Ids were not found!                           */
-/* -------------------------------------------------------------------- */
-    if( k != 2 ) {
-        CPLFree( paDimIds );
-        CPLFree( panBandDimPos );
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    // X and Y Dimension Ids were not found!
+    if( k != 2 )
+    {
+        CPLFree(paDimIds);
+        CPLFree(panBandDimPos);
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read Metadata for this variable                                 */
-/* -------------------------------------------------------------------- */
-/* should disable as is also done at band level, except driver needs the
-   variables as metadata (e.g. projection) */
-    poDS->ReadAttributes( cdfid, var );
+    // Read Metadata for this variable.
+
+    // Should disable as is also done at band level, except driver needs the
+    // variables as metadata (e.g. projection).
+    poDS->ReadAttributes(cdfid, var);
 
-/* -------------------------------------------------------------------- */
-/*      Read Metadata for each dimension                                */
-/* -------------------------------------------------------------------- */
-    for( int j=0; j < ndims; j++ ){
-        char szTemp[NC_MAX_NAME+1];
-        status = nc_inq_dimname( cdfid, j, szTemp );
+    // Read Metadata for each dimension.
+    for( int j = 0; j < ndims; j++ )
+    {
+        char szTemp[NC_MAX_NAME + 1];
+        status = nc_inq_dimname(cdfid, j, szTemp);
         NCDF_ERR(status);
-        poDS->papszDimName.AddString( szTemp );
+        poDS->papszDimName.AddString(szTemp);
         int nDimID;
-        status = nc_inq_varid( cdfid, poDS->papszDimName[j], &nDimID );
-        if( status == NC_NOERR ) {
-            poDS->ReadAttributes( cdfid, nDimID );
+        status = nc_inq_varid(cdfid, poDS->papszDimName[j], &nDimID);
+        if( status == NC_NOERR )
+        {
+            poDS->ReadAttributes(cdfid, nDimID);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set projection info                                             */
-/* -------------------------------------------------------------------- */
-    poDS->SetProjectionFromVar( var, false );
+    // Set projection info.
+    poDS->SetProjectionFromVar(var, false);
 
-    /* override bottom-up with GDAL_NETCDF_BOTTOMUP config option */
-    const char *pszValue = CPLGetConfigOption( "GDAL_NETCDF_BOTTOMUP", NULL );
-    if ( pszValue ) {
-        poDS->bBottomUp = CPLTestBool( pszValue );
-        CPLDebug( "GDAL_netCDF",
-                  "set bBottomUp=%d because GDAL_NETCDF_BOTTOMUP=%s",
-                  static_cast<int>(poDS->bBottomUp), pszValue );
+    // Override bottom-up with GDAL_NETCDF_BOTTOMUP config option.
+    const char *pszValue = CPLGetConfigOption("GDAL_NETCDF_BOTTOMUP", NULL);
+    if( pszValue )
+    {
+        poDS->bBottomUp = CPLTestBool(pszValue);
+        CPLDebug("GDAL_netCDF",
+                 "set bBottomUp=%d because GDAL_NETCDF_BOTTOMUP=%s",
+                 static_cast<int>(poDS->bBottomUp), pszValue);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Save non-spatial dimension info                                 */
-/* -------------------------------------------------------------------- */
+    // Save non-spatial dimension info.
 
     int *panBandZLev = NULL;
     int nDim = 2;
@@ -6242,60 +6485,67 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     CPLString osExtraDimNames;
 
-    if ( nd > 2 ) {
-        nDim=2;
-        panBandZLev = (int *)CPLCalloc( nd-2, sizeof( int ) );
+    if( nd > 2 )
+    {
+        nDim = 2;
+        panBandZLev = static_cast<int *>(CPLCalloc(nd - 2, sizeof(int)));
 
         osExtraDimNames = "{";
 
-        for( int j=0; j < nd; j++ ){
-            if( ( paDimIds[j] != poDS->nXDimID ) &&
-                ( paDimIds[j] != poDS->nYDimID ) ){
-                nc_inq_dimlen ( cdfid, paDimIds[j], &lev_count );
+        char szDimName[NC_MAX_NAME + 1] = {};
+
+        for( int j = 0; j < nd; j++ )
+        {
+            if( (paDimIds[j] != poDS->nXDimID) &&
+                (paDimIds[j] != poDS->nYDimID) )
+            {
+                nc_inq_dimlen(cdfid, paDimIds[j], &lev_count);
                 nTotLevCount *= lev_count;
-                panBandZLev[ nDim-2 ] = static_cast<int>(lev_count);
-                panBandDimPos[ nDim++ ] = j; //Save Position of ZDim
-                //Save non-spatial dimension names
-                if ( nc_inq_dimname( cdfid, paDimIds[j], szDimName )
-                     == NC_NOERR ) {
+                panBandZLev[nDim - 2] = static_cast<int>(lev_count);
+                panBandDimPos[nDim++] = j;  // Save Position of ZDim
+                // Save non-spatial dimension names.
+                if( nc_inq_dimname(cdfid, paDimIds[j], szDimName)
+                    == NC_NOERR )
+                {
                     osExtraDimNames += szDimName;
-                    if ( j < nd-3 ) {
+                    if( j < nd-3 )
+                    {
                         osExtraDimNames += ",";
                     }
-                    nc_inq_varid( cdfid, szDimName, &nVarID );
-                    nc_inq_vartype( cdfid, nVarID, &nType );
-                    char szExtraDimDef[NC_MAX_NAME+1];
-                    snprintf( szExtraDimDef, sizeof(szExtraDimDef), "{%ld,%d}", (long)lev_count, nType );
-                    char szTemp[NC_MAX_NAME+32+1];
-                    snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_DEF", szDimName );
-                    poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata,
-                                                           szTemp, szExtraDimDef );
-                    if ( NCDFGet1DVar( cdfid, nVarID, &pszTemp ) == CE_None ) {
-                        snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_VALUES", szDimName );
-                        poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata,
-                                                              szTemp, pszTemp );
-                        CPLFree( pszTemp );
+                    nc_inq_varid(cdfid, szDimName, &nVarID);
+                    nc_inq_vartype(cdfid, nVarID, &nType);
+                    char szExtraDimDef[NC_MAX_NAME + 1];
+                    snprintf(szExtraDimDef, sizeof(szExtraDimDef), "{%ld,%d}",
+                             (long)lev_count, nType);
+                    char szTemp[NC_MAX_NAME + 32 + 1];
+                    snprintf(szTemp, sizeof(szTemp), "NETCDF_DIM_%s_DEF",
+                             szDimName);
+                    poDS->papszMetadata = CSLSetNameValue(
+                        poDS->papszMetadata, szTemp, szExtraDimDef);
+                    if( NCDFGet1DVar(cdfid, nVarID, &pszTemp) == CE_None )
+                    {
+                        snprintf(szTemp, sizeof(szTemp), "NETCDF_DIM_%s_VALUES",
+                                 szDimName);
+                        poDS->papszMetadata = CSLSetNameValue(
+                            poDS->papszMetadata, szTemp, pszTemp);
+                        CPLFree(pszTemp);
                     }
                 }
             }
         }
         osExtraDimNames += "}";
-        poDS->papszMetadata = CSLSetNameValue( poDS->papszMetadata,
-                                               "NETCDF_DIM_EXTRA",
-                                               osExtraDimNames );
+        poDS->papszMetadata = CSLSetNameValue(
+            poDS->papszMetadata, "NETCDF_DIM_EXTRA", osExtraDimNames);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Store Metadata                                                  */
-/* -------------------------------------------------------------------- */
-    poDS->SetMetadata( poDS->papszMetadata );
+    // Store Metadata.
+    poDS->SetMetadata(poDS->papszMetadata);
 
-/* -------------------------------------------------------------------- */
-/*      Create bands                                                    */
-/* -------------------------------------------------------------------- */
+    // Create bands.
 
-    /* Arbitrary threshold */
-    int nMaxBandCount = atoi(CPLGetConfigOption("GDAL_MAX_BAND_COUNT", "32768"));
+    // Arbitrary threshold.
+    int nMaxBandCount =
+        atoi(CPLGetConfigOption("GDAL_MAX_BAND_COUNT", "32768"));
     if( nMaxBandCount <= 0 )
         nMaxBandCount = 32768;
     if( nTotLevCount > static_cast<unsigned int>(nMaxBandCount) )
@@ -6306,40 +6556,39 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
                  static_cast<unsigned int>(nTotLevCount));
         nTotLevCount = static_cast<unsigned int>(nMaxBandCount);
     }
-    for ( unsigned int lev = 0; lev < nTotLevCount ; lev++ ) {
+    for( unsigned int lev = 0; lev < nTotLevCount ; lev++ )
+    {
         netCDFRasterBand *poBand =
-            new netCDFRasterBand(poDS, var, nDim, lev,
-                                 panBandZLev, panBandDimPos,
-                                 paDimIds, lev+1 );
-        poDS->SetBand( lev+1, poBand );
+            new netCDFRasterBand(poDS, var, nDim, lev, panBandZLev,
+                                 panBandDimPos, paDimIds, lev + 1);
+        poDS->SetBand(lev + 1, poBand);
     }
 
-    CPLFree( paDimIds );
-    CPLFree( panBandDimPos );
-    if ( panBandZLev )
-        CPLFree( panBandZLev );
+    CPLFree(paDimIds);
+    CPLFree(panBandDimPos);
+    if( panBandZLev )
+        CPLFree(panBandZLev);
     // Handle angular geographic coordinates here
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
+    // Initialize any PAM information.
     if( bTreatAsSubdataset )
     {
-        poDS->SetPhysicalFilename( poDS->osFilename );
-        poDS->SetSubdatasetName( osSubdatasetName );
+        poDS->SetPhysicalFilename(poDS->osFilename);
+        poDS->SetSubdatasetName(osSubdatasetName);
     }
 
-    CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock with
+                                // GDALDataset own mutex.
     poDS->TryLoadXML();
 
     if( bTreatAsSubdataset )
-        poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
+        poDS->oOvManager.Initialize(poDS, ":::VIRTUAL:::");
     else
-        poDS->oOvManager.Initialize( poDS, poDS->osFilename );
+        poDS->oOvManager.Initialize(poDS, poDS->osFilename);
 
     CPLAcquireMutex(hNCMutex, 1000.0);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -6348,12 +6597,12 @@ GDALDataset *netCDFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create a copy of metadata for NC_GLOBAL or a variable           */
 /************************************************************************/
 
-static void CopyMetadata( void  *poDS, int fpImage, int CDFVarID,
-                   const char *pszPrefix, bool bIsBand ) {
-
-    char       **papszFieldData=NULL;
+static void CopyMetadata( void *poDS, int fpImage, int CDFVarID,
+                          const char *pszPrefix, bool bIsBand )
+{
+    char **papszFieldData = NULL;
 
-    /* Remove the following band meta but set them later from band data */
+    // Remove the following band meta but set them later from band data.
     const char *papszIgnoreBand[] = { CF_ADD_OFFSET, CF_SCALE_FACTOR,
                                       "valid_range", "_Unsigned",
                                       _FillValue, "coordinates",
@@ -6361,112 +6610,128 @@ static void CopyMetadata( void  *poDS, int fpImage, int CDFVarID,
     const char *papszIgnoreGlobal[] = { "NETCDF_DIM_EXTRA", NULL };
 
     char **papszMetadata = NULL;
-    if( CDFVarID == NC_GLOBAL ) {
-        papszMetadata = GDALGetMetadata( (GDALDataset *) poDS,"");
-    } else {
-        papszMetadata = GDALGetMetadata( (GDALRasterBandH) poDS, NULL );
+    if( CDFVarID == NC_GLOBAL )
+    {
+        papszMetadata = GDALGetMetadata((GDALDataset *)poDS, "");
+    }
+    else
+    {
+        papszMetadata = GDALGetMetadata((GDALRasterBandH)poDS, NULL);
     }
 
-    const int nItems = CSLCount( papszMetadata );
-
-    for(int k=0; k < nItems; k++ ) {
-        const char *pszField = CSLGetField( papszMetadata, k );
-        if ( papszFieldData ) CSLDestroy( papszFieldData );
-        papszFieldData = CSLTokenizeString2 (pszField, "=",
-                                             CSLT_HONOURSTRINGS );
-        if( papszFieldData[1] != NULL ) {
+    const int nItems = CSLCount(papszMetadata);
 
+    for( int k = 0; k < nItems; k++ )
+    {
+        const char *pszField = CSLGetField(papszMetadata, k);
+        if( papszFieldData ) CSLDestroy(papszFieldData);
+        papszFieldData = CSLTokenizeString2(pszField, "=", CSLT_HONOURSTRINGS);
+        if( papszFieldData[1] != NULL )
+        {
 #ifdef NCDF_DEBUG
-            CPLDebug( "GDAL_netCDF", "copy metadata [%s]=[%s]",
-                      papszFieldData[ 0 ], papszFieldData[ 1 ] );
+            CPLDebug("GDAL_netCDF", "copy metadata [%s]=[%s]",
+                     papszFieldData[0], papszFieldData[1]);
 #endif
 
-            CPLString osMetaName(papszFieldData[ 0 ]);
-            CPLString osMetaValue(papszFieldData[ 1 ]);
+            CPLString osMetaName(papszFieldData[0]);
+            CPLString osMetaValue(papszFieldData[1]);
 
-            /* check for items that match pszPrefix if applicable */
-            if ( ( pszPrefix != NULL ) && ( !EQUAL( pszPrefix, "" ) ) ) {
-                    /* remove prefix */
-                    if ( EQUALN( osMetaName, pszPrefix, strlen(pszPrefix) ) ) {
-                        osMetaName = osMetaName.substr(strlen(pszPrefix));
-                    }
-                    /* only copy items that match prefix */
-                    else
-                        continue;
+            // Check for items that match pszPrefix if applicable.
+            if( pszPrefix != NULL && !EQUAL(pszPrefix, "") )
+            {
+                // Remove prefix.
+                if( EQUALN(osMetaName, pszPrefix, strlen(pszPrefix)) )
+                {
+                    osMetaName = osMetaName.substr(strlen(pszPrefix));
+                }
+                // Only copy items that match prefix.
+                else
+                {
+                    continue;
+                }
             }
 
-            /* Fix various issues with metadata translation */
-            if( CDFVarID == NC_GLOBAL ) {
-                /* Do not copy items in papszIgnoreGlobal and NETCDF_DIM_* */
-                if ( ( CSLFindString( (char **)papszIgnoreGlobal, osMetaName ) != -1 ) ||
-                     ( STARTS_WITH(osMetaName, "NETCDF_DIM_") ) )
+            // Fix various issues with metadata translation.
+            if( CDFVarID == NC_GLOBAL )
+            {
+                // Do not copy items in papszIgnoreGlobal and NETCDF_DIM_*.
+                if( (CSLFindString((char **)papszIgnoreGlobal, osMetaName) != -1) ||
+                    (STARTS_WITH(osMetaName, "NETCDF_DIM_")) )
                     continue;
-                /* Remove NC_GLOBAL prefix for netcdf global Metadata */
-                else if( STARTS_WITH(osMetaName, "NC_GLOBAL#") ) {
+                // Remove NC_GLOBAL prefix for netcdf global Metadata.
+                else if( STARTS_WITH(osMetaName, "NC_GLOBAL#") )
+                {
                     osMetaName = osMetaName.substr(strlen("NC_GLOBAL#"));
                 }
-                /* GDAL Metadata renamed as GDAL-[meta] */
-                else if ( strstr( osMetaName, "#" ) == NULL ) {
+                // GDAL Metadata renamed as GDAL-[meta].
+                else if( strstr(osMetaName, "#") == NULL )
+                {
                     osMetaName = "GDAL_" + osMetaName;
                 }
-                /* Keep time, lev and depth information for safe-keeping */
-                /* Time and vertical coordinate handling need improvements */
+                // Keep time, lev and depth information for safe-keeping.
+                // Time and vertical coordinate handling need improvements.
                 /*
-                else if( STARTS_WITH(szMetaName, "time#") ) {
+                else if( STARTS_WITH(szMetaName, "time#") )
+                {
                     szMetaName[4] = '-';
                 }
-                else if( STARTS_WITH(szMetaName, "lev#") ) {
+                else if( STARTS_WITH(szMetaName, "lev#") )
+                {
                     szMetaName[3] = '-';
                 }
-                else if( STARTS_WITH(szMetaName, "depth#") ) {
+                else if( STARTS_WITH(szMetaName, "depth#") )
+                {
                     szMetaName[5] = '-';
                 }
                 */
-                /* Only copy data without # (previously all data was copied)  */
-                if ( strstr( osMetaName, "#" ) != NULL )
+                // Only copy data without # (previously all data was copied).
+                if( strstr(osMetaName, "#") != NULL )
                     continue;
-                // /* netCDF attributes do not like the '#' character. */
-                // for( unsigned int h=0; h < strlen( szMetaName ) -1 ; h++ ) {
-                //     if( szMetaName[h] == '#' ) szMetaName[h] = '-';
+                // netCDF attributes do not like the '#' character.
+                // for( unsigned int h=0; h < strlen(szMetaName) -1 ; h++ ) {
+                //     if( szMetaName[h] == '#') szMetaName[h] = '-';
                 // }
             }
-            else {
-                /* Do not copy varname, stats, NETCDF_DIM_*, nodata
-                   and items in papszIgnoreBand */
-                if ( ( STARTS_WITH(osMetaName, "NETCDF_VARNAME") ) ||
-                     ( STARTS_WITH(osMetaName, "STATISTICS_") ) ||
-                     ( STARTS_WITH(osMetaName, "NETCDF_DIM_") ) ||
-                     ( STARTS_WITH(osMetaName, "missing_value") ) ||
-                     ( STARTS_WITH(osMetaName, "_FillValue") ) ||
-                     ( CSLFindString( (char **)papszIgnoreBand, osMetaName ) != -1 ) )
+            else
+            {
+                // Do not copy varname, stats, NETCDF_DIM_*, nodata
+                // and items in papszIgnoreBand.
+                if( (STARTS_WITH(osMetaName, "NETCDF_VARNAME")) ||
+                    (STARTS_WITH(osMetaName, "STATISTICS_")) ||
+                    (STARTS_WITH(osMetaName, "NETCDF_DIM_")) ||
+                    (STARTS_WITH(osMetaName, "missing_value")) ||
+                    (STARTS_WITH(osMetaName, "_FillValue")) ||
+                    (CSLFindString((char **)papszIgnoreBand, osMetaName) != -1) )
                     continue;
             }
 
 #ifdef NCDF_DEBUG
-            CPLDebug( "GDAL_netCDF", "copy name=[%s] value=[%s]",
-                      osMetaName.c_str(), osMetaValue.c_str() );
+            CPLDebug("GDAL_netCDF", "copy name=[%s] value=[%s]",
+                     osMetaName.c_str(), osMetaValue.c_str());
 #endif
-            if ( NCDFPutAttr( fpImage, CDFVarID,osMetaName,
-                              osMetaValue ) != CE_None )
-                CPLDebug( "GDAL_netCDF", "NCDFPutAttr(%d, %d, %s, %s) failed",
-                          fpImage, CDFVarID,osMetaName.c_str(), osMetaValue.c_str() );
+            if( NCDFPutAttr(fpImage, CDFVarID, osMetaName,
+                            osMetaValue) != CE_None )
+                CPLDebug("GDAL_netCDF", "NCDFPutAttr(%d, %d, %s, %s) failed",
+                         fpImage, CDFVarID,
+                         osMetaName.c_str(), osMetaValue.c_str());
         }
     }
 
-    if ( papszFieldData ) CSLDestroy( papszFieldData );
+    if( papszFieldData ) CSLDestroy(papszFieldData);
 
-    /* Set add_offset and scale_factor here if present */
-    if( ( CDFVarID != NC_GLOBAL ) && ( bIsBand ) ) {
+    // Set add_offset and scale_factor here if present.
+    if( CDFVarID != NC_GLOBAL && bIsBand )
+    {
 
         int bGotAddOffset, bGotScale;
-        GDALRasterBandH poRB = (GDALRasterBandH) poDS;
-        const double dfAddOffset = GDALGetRasterOffset( poRB , &bGotAddOffset );
-        const double dfScale = GDALGetRasterScale( poRB, &bGotScale );
+        GDALRasterBandH poRB = (GDALRasterBandH)poDS;
+        const double dfAddOffset = GDALGetRasterOffset(poRB, &bGotAddOffset);
+        const double dfScale = GDALGetRasterScale(poRB, &bGotScale);
 
-        if ( bGotAddOffset && dfAddOffset != 0.0 )
-            GDALSetRasterOffset( poRB, dfAddOffset );
-        if ( bGotScale && dfScale != 1.0 )
-            GDALSetRasterScale( poRB, dfScale );
+        if( bGotAddOffset && dfAddOffset != 0.0 )
+            GDALSetRasterOffset(poRB, dfAddOffset);
+        if( bGotScale && dfScale != 1.0 )
+            GDALSetRasterScale(poRB, dfScale);
     }
 }
 
@@ -6479,9 +6744,9 @@ static void CopyMetadata( void  *poDS, int fpImage, int CDFVarID,
 /************************************************************************/
 
 netCDFDataset *
-netCDFDataset::CreateLL( const char * pszFilename,
+netCDFDataset::CreateLL( const char *pszFilename,
                          int nXSize, int nYSize, int nBands,
-                         char ** papszOptions )
+                         char **papszOptions )
 {
     if( !((nXSize == 0 && nYSize == 0 && nBands == 0) ||
           (nXSize > 0 && nYSize > 0 && nBands > 0)) )
@@ -6489,7 +6754,8 @@ netCDFDataset::CreateLL( const char * pszFilename,
         return NULL;
     }
 
-    CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+    CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock with
+                                // GDALDataset own mutex.
     netCDFDataset *poDS = new netCDFDataset();
     CPLAcquireMutex(hNCMutex, 1000.0);
 
@@ -6498,7 +6764,7 @@ netCDFDataset::CreateLL( const char * pszFilename,
     poDS->eAccess = GA_Update;
     poDS->osFilename = pszFilename;
 
-    /* from gtiff driver, is this ok? */
+    // From gtiff driver, is this ok?
     /*
     poDS->nBlockXSize = nXSize;
     poDS->nBlockYSize = 1;
@@ -6507,30 +6773,34 @@ netCDFDataset::CreateLL( const char * pszFilename,
         * ((nXSize + poDS->nBlockXSize - 1) / poDS->nBlockXSize);
         */
 
-    /* process options */
-    poDS->papszCreationOptions = CSLDuplicate( papszOptions );
-    poDS->ProcessCreationOptions( );
+    // process options.
+    poDS->papszCreationOptions = CSLDuplicate(papszOptions);
+    poDS->ProcessCreationOptions();
 
     if( poDS->eMultipleLayerBehaviour == SEPARATE_FILES )
     {
         VSIStatBuf sStat;
-        if( VSIStat( pszFilename, &sStat ) == 0 )
+        if( VSIStat(pszFilename, &sStat) == 0 )
         {
             if( !VSI_ISDIR(sStat.st_mode) )
             {
-                CPLError(CE_Failure, CPLE_FileIO, "%s is an existing file, but not a directory",
-                        pszFilename);
-                CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "%s is an existing file, but not a directory",
+                         pszFilename);
+                CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll
+                                            // deadlock with GDALDataset own
+                                            // mutex.
                 delete poDS;
                 CPLAcquireMutex(hNCMutex, 1000.0);
                 return NULL;
             }
         }
-        else if( VSIMkdir( pszFilename, 0755 ) != 0 )
+        else if( VSIMkdir(pszFilename, 0755) != 0 )
         {
             CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s directory",
                      pszFilename);
-            CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+            CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll
+                                        // deadlock with GDALDataset own mutex.
             delete poDS;
             CPLAcquireMutex(hNCMutex, 1000.0);
             return NULL;
@@ -6539,43 +6809,40 @@ netCDFDataset::CreateLL( const char * pszFilename,
         return poDS;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the dataset.                                             */
-/* -------------------------------------------------------------------- */
-    int status = nc_create( pszFilename, poDS->nCreateMode,  &(poDS->cdfid) );
+    // Create the dataset.
+    int status = nc_create(pszFilename, poDS->nCreateMode, &(poDS->cdfid));
 
-    /* put into define mode */
+    // Put into define mode.
     poDS->SetDefineMode(true);
 
     if( status != NC_NOERR )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unable to create netCDF file %s (Error code %d): %s .\n",
-                  pszFilename, status, nc_strerror(status) );
-        CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Unable to create netCDF file %s (Error code %d): %s .",
+                 pszFilename, status, nc_strerror(status));
+        CPLReleaseMutex(hNCMutex);  // Release mutex otherwise we'll deadlock
+                                    // with GDALDataset own mutex.
         delete poDS;
         CPLAcquireMutex(hNCMutex, 1000.0);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Define dimensions                                               */
-/* -------------------------------------------------------------------- */
+    // Define dimensions.
     if( nXSize > 0 && nYSize > 0 )
     {
-        poDS->papszDimName.AddString( NCDF_DIMNAME_X );
-        status = nc_def_dim( poDS->cdfid, NCDF_DIMNAME_X, nXSize,
-                            &(poDS->nXDimID) );
+        poDS->papszDimName.AddString(NCDF_DIMNAME_X);
+        status =
+            nc_def_dim(poDS->cdfid, NCDF_DIMNAME_X, nXSize, &(poDS->nXDimID));
         NCDF_ERR(status);
-        CPLDebug( "GDAL_netCDF", "status nc_def_dim( %d, %s, %d, -) got id %d",
-                poDS->cdfid, NCDF_DIMNAME_X, nXSize, poDS->nXDimID );
+        CPLDebug("GDAL_netCDF", "status nc_def_dim(%d, %s, %d, -) got id %d",
+                 poDS->cdfid, NCDF_DIMNAME_X, nXSize, poDS->nXDimID);
 
-        poDS->papszDimName.AddString( NCDF_DIMNAME_Y );
-        status = nc_def_dim( poDS->cdfid, NCDF_DIMNAME_Y, nYSize,
-                            &(poDS->nYDimID) );
+        poDS->papszDimName.AddString(NCDF_DIMNAME_Y);
+        status =
+            nc_def_dim(poDS->cdfid, NCDF_DIMNAME_Y, nYSize, &(poDS->nYDimID));
         NCDF_ERR(status);
-        CPLDebug( "GDAL_netCDF", "status nc_def_dim( %d, %s, %d, -) got id %d",
-                poDS->cdfid, NCDF_DIMNAME_Y, nYSize, poDS->nYDimID );
+        CPLDebug("GDAL_netCDF", "status nc_def_dim(%d, %s, %d, -) got id %d",
+                 poDS->cdfid, NCDF_DIMNAME_Y, nYSize, poDS->nYDimID);
     }
 
     return poDS;
@@ -6586,99 +6853,94 @@ netCDFDataset::CreateLL( const char * pszFilename,
 /************************************************************************/
 
 GDALDataset *
-netCDFDataset::Create( const char * pszFilename,
+netCDFDataset::Create( const char *pszFilename,
                        int nXSize, int nYSize, int nBands,
                        GDALDataType eType,
-                       char ** papszOptions )
+                       char **papszOptions )
 {
-    CPLDebug( "GDAL_netCDF",
-              "\n=====\nnetCDFDataset::Create( %s, ... )\n",
-              pszFilename );
+    CPLDebug("GDAL_netCDF",
+              "\n=====\nnetCDFDataset::Create(%s, ...)",
+              pszFilename);
 
     CPLMutexHolderD(&hNCMutex);
 
-    netCDFDataset *poDS =  netCDFDataset::CreateLL( pszFilename,
-                                                    nXSize, nYSize, nBands,
-                                                    papszOptions );
-    if ( ! poDS )
+    netCDFDataset *poDS = netCDFDataset::CreateLL(pszFilename,
+                                                  nXSize, nYSize, nBands,
+                                                  papszOptions);
+    if( !poDS )
         return NULL;
 
-    /* should we write signed or unsigned byte? */
-    /* TODO should this only be done in Create() */
+    // Should we write signed or unsigned byte?
+    // TODO should this only be done in Create()
     poDS->bSignedData = true;
-    const char *pszValue  =
-        CSLFetchNameValueDef( papszOptions, "PIXELTYPE", "" );
-    if( eType == GDT_Byte && ( ! EQUAL(pszValue,"SIGNEDBYTE") ) )
+    const char *pszValue = CSLFetchNameValueDef(papszOptions, "PIXELTYPE", "");
+    if( eType == GDT_Byte && !EQUAL(pszValue, "SIGNEDBYTE") )
         poDS->bSignedData = false;
 
-/* -------------------------------------------------------------------- */
-/*      Add Conventions, GDAL info and history                          */
-/* -------------------------------------------------------------------- */
+    // Add Conventions, GDAL info and history.
     if( poDS->cdfid >= 0 )
     {
-        NCDFAddGDALHistory( poDS->cdfid, pszFilename, "", "Create",
-                            (nBands == 0) ? NCDF_CONVENTIONS_CF_V1_6 : NCDF_CONVENTIONS_CF_V1_5);
+        NCDFAddGDALHistory(poDS->cdfid, pszFilename, "", "Create",
+                           (nBands == 0) ? NCDF_CONVENTIONS_CF_V1_6
+                                         : NCDF_CONVENTIONS_CF_V1_5);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Define bands                                                    */
-/* -------------------------------------------------------------------- */
+    // Define bands.
     for( int iBand = 1; iBand <= nBands; iBand++ )
     {
-        poDS->SetBand( iBand, new netCDFRasterBand( poDS, eType, iBand,
-                                                    poDS->bSignedData ) );
+        poDS->SetBand(
+            iBand, new netCDFRasterBand(poDS, eType, iBand, poDS->bSignedData));
     }
 
-    CPLDebug( "GDAL_netCDF",
-              "netCDFDataset::Create( %s, ... ) done",
-              pszFilename );
-/* -------------------------------------------------------------------- */
-/*      Return same dataset                                             */
-/* -------------------------------------------------------------------- */
-     return( poDS );
+    CPLDebug("GDAL_netCDF", "netCDFDataset::Create(%s, ...) done", pszFilename);
+    // Return same dataset.
+    return poDS;
 }
 
-
 template <class T>
-static CPLErr  NCDFCopyBand( GDALRasterBand *poSrcBand, GDALRasterBand *poDstBand,
-                      int nXSize, int nYSize,
-                      GDALProgressFunc pfnProgress, void * pProgressData )
+static CPLErr NCDFCopyBand( GDALRasterBand *poSrcBand, GDALRasterBand *poDstBand,
+                            int nXSize, int nYSize,
+                            GDALProgressFunc pfnProgress, void *pProgressData )
 {
     GDALDataType eDT = poSrcBand->GetRasterDataType();
     CPLErr eErr = CE_None;
-    T *patScanline = (T *) CPLMalloc( nXSize * sizeof(T) );
-
-    for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )  {
-        eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
-                                    patScanline, nXSize, 1, eDT,
-                                    0,0, NULL);
-        if ( eErr != CE_None )
-            CPLDebug( "GDAL_netCDF",
-                      "NCDFCopyBand(), poSrcBand->RasterIO() returned error code %d",
-                      eErr );
-        else {
-            eErr = poDstBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
-                                        patScanline, nXSize, 1, eDT,
-                                        0,0, NULL);
-            if ( eErr != CE_None )
-                CPLDebug( "GDAL_netCDF",
-                          "NCDFCopyBand(), poDstBand->RasterIO() returned error code %d",
-                          eErr );
-        }
-
-        if ( ( nYSize>10 ) && ( iLine % (nYSize/10) == 1 ) ) {
-            if( !pfnProgress( 1.0*iLine/nYSize , NULL, pProgressData ) )
-            {
-                eErr = CE_Failure;
-                CPLError( CE_Failure, CPLE_UserInterrupt,
-                        "User terminated CreateCopy()" );
-            }
-        }
-    }
+    T *patScanline = static_cast<T *>(CPLMalloc(nXSize * sizeof(T)));
 
-    CPLFree( patScanline );
+    for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
+    {
+        eErr = poSrcBand->RasterIO(GF_Read, 0, iLine, nXSize, 1, patScanline,
+                                   nXSize, 1, eDT, 0, 0, NULL);
+        if( eErr != CE_None )
+        {
+            CPLDebug(
+                "GDAL_netCDF",
+                "NCDFCopyBand(), poSrcBand->RasterIO() returned error code %d",
+                eErr);
+        }
+        else
+        {
+            eErr = poDstBand->RasterIO(GF_Write, 0, iLine, nXSize, 1,
+                                       patScanline, nXSize, 1, eDT, 0, 0, NULL);
+            if( eErr != CE_None )
+                CPLDebug("GDAL_netCDF",
+                         "NCDFCopyBand(), poDstBand->RasterIO() returned error code %d",
+                         eErr);
+        }
+
+        if( nYSize > 10 && (iLine % (nYSize / 10) == 1) )
+        {
+            if( !pfnProgress(1.0 * iLine / nYSize, NULL, pProgressData) )
+            {
+                eErr = CE_Failure;
+                CPLError(CE_Failure, CPLE_UserInterrupt,
+                         "User terminated CreateCopy()");
+            }
+        }
+    }
 
-    pfnProgress( 1.0, NULL, pProgressData );
+    CPLFree(patScanline);
+
+    pfnProgress(1.0, NULL, pProgressData);
 
     return eErr;
 }
@@ -6688,481 +6950,495 @@ static CPLErr  NCDFCopyBand( GDALRasterBand *poSrcBand, GDALRasterBand *poDstBan
 /************************************************************************/
 
 GDALDataset*
-netCDFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
-                           CPL_UNUSED int bStrict, char ** papszOptions,
-                           GDALProgressFunc pfnProgress, void * pProgressData )
+netCDFDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS,
+                           CPL_UNUSED int bStrict, char **papszOptions,
+                           GDALProgressFunc pfnProgress, void *pProgressData )
 {
     CPLMutexHolderD(&hNCMutex);
 
-    CPLDebug( "GDAL_netCDF",
-              "\n=====\nnetCDFDataset::CreateCopy( %s, ... )\n",
-              pszFilename );
+    CPLDebug("GDAL_netCDF", "\n=====\nnetCDFDataset::CreateCopy(%s, ...)",
+             pszFilename);
 
     const int nBands = poSrcDS->GetRasterCount();
     const int nXSize = poSrcDS->GetRasterXSize();
     const int nYSize = poSrcDS->GetRasterYSize();
     const char *pszWKT = poSrcDS->GetProjectionRef();
 
-/* -------------------------------------------------------------------- */
-/*      Check input bands for errors                                    */
-/* -------------------------------------------------------------------- */
-
-    if (nBands == 0)
+    // Check input bands for errors.
+    if( nBands == 0 )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "NetCDF driver does not support source dataset with zero band.\n");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "NetCDF driver does not support "
+                 "source dataset with zero band.");
         return NULL;
     }
 
     GDALDataType eDT;
     GDALRasterBand *poSrcBand = NULL;
-    for( int iBand=1; iBand <= nBands; iBand++ )
+    for( int iBand = 1; iBand <= nBands; iBand++ )
     {
-        poSrcBand = poSrcDS->GetRasterBand( iBand );
+        poSrcBand = poSrcDS->GetRasterBand(iBand);
         eDT = poSrcBand->GetRasterDataType();
-        if (eDT == GDT_Unknown || GDALDataTypeIsComplex(eDT))
+        if( eDT == GDT_Unknown || GDALDataTypeIsComplex(eDT) )
         {
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "NetCDF driver does not support source dataset with band of complex type.");
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "NetCDF driver does not support source dataset with band "
+                     "of complex type.");
             return NULL;
         }
     }
 
-    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    if( !pfnProgress(0.0, NULL, pProgressData) )
         return NULL;
 
-    /* same as in Create() */
-    netCDFDataset *poDS = netCDFDataset::CreateLL( pszFilename,
+    // Same as in Create().
+    netCDFDataset *poDS = netCDFDataset::CreateLL(pszFilename,
                                                    nXSize, nYSize, nBands,
-                                                   papszOptions );
-    if ( ! poDS )
+                                                   papszOptions);
+    if( !poDS )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Copy global metadata                                            */
-/*      Add Conventions, GDAL info and history                          */
-/* -------------------------------------------------------------------- */
-    CopyMetadata((void *) poSrcDS, poDS->cdfid, NC_GLOBAL, NULL, false );
-    NCDFAddGDALHistory( poDS->cdfid, pszFilename,
-                        poSrcDS->GetMetadataItem("NC_GLOBAL#history",""),
-                        "CreateCopy" );
+    // Copy global metadata.
+    // Add Conventions, GDAL info and history.
+    CopyMetadata((void *)poSrcDS, poDS->cdfid, NC_GLOBAL, NULL, false);
+    NCDFAddGDALHistory(poDS->cdfid, pszFilename,
+                       poSrcDS->GetMetadataItem("NC_GLOBAL#history", ""),
+                       "CreateCopy");
 
-    pfnProgress( 0.1, NULL, pProgressData );
+    pfnProgress(0.1, NULL, pProgressData);
 
-/* -------------------------------------------------------------------- */
-/*      Check for extra dimensions                                      */
-/* -------------------------------------------------------------------- */
+    // Check for extra dimensions.
     int nDim = 2;
     char **papszExtraDimNames =
-        NCDFTokenizeArray( poSrcDS->GetMetadataItem("NETCDF_DIM_EXTRA","") );
+        NCDFTokenizeArray(poSrcDS->GetMetadataItem("NETCDF_DIM_EXTRA", ""));
     char **papszExtraDimValues = NULL;
 
-    if ( papszExtraDimNames != NULL && ( CSLCount( papszExtraDimNames )> 0 ) ) {
-        size_t nDimSize = 0;
+    if( papszExtraDimNames != NULL && CSLCount(papszExtraDimNames) > 0 )
+    {
         size_t nDimSizeTot = 1;
         // first make sure dimensions lengths compatible with band count
-        // for ( int i=0; i<CSLCount( papszExtraDimNames ); i++ ) {
-        for ( int i=CSLCount( papszExtraDimNames )-1; i>=0; i-- ) {
-            char szTemp[ NC_MAX_NAME + 32 + 1 ];
-            snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_DEF", papszExtraDimNames[i] );
-            papszExtraDimValues = NCDFTokenizeArray( poSrcDS->GetMetadataItem(szTemp,"") );
-            nDimSize = atol( papszExtraDimValues[0] );
-            CSLDestroy( papszExtraDimValues );
+        // for( int i=0; i<CSLCount(papszExtraDimNames ); i++ ) {
+        for( int i = CSLCount(papszExtraDimNames) - 1; i >= 0; i-- )
+        {
+            char szTemp[NC_MAX_NAME + 32 + 1];
+            snprintf(szTemp, sizeof(szTemp), "NETCDF_DIM_%s_DEF",
+                     papszExtraDimNames[i]);
+            papszExtraDimValues =
+                NCDFTokenizeArray(poSrcDS->GetMetadataItem(szTemp, ""));
+            const size_t nDimSize = atol(papszExtraDimValues[0]);
+            CSLDestroy(papszExtraDimValues);
             nDimSizeTot *= nDimSize;
         }
-        if ( nDimSizeTot == (size_t)nBands ) {
-            nDim = 2 + CSLCount( papszExtraDimNames );
+        if( nDimSizeTot == (size_t)nBands )
+        {
+            nDim = 2 + CSLCount(papszExtraDimNames);
         }
-        else {
+        else
+        {
             // if nBands != #bands computed raise a warning
             // just issue a debug message, because it was probably intentional
-            CPLDebug( "GDAL_netCDF",
-                      "Warning: Number of bands (%d) is not compatible with dimensions "
-                      "(total=%ld names=%s)", nBands, (long)nDimSizeTot,
-                      poSrcDS->GetMetadataItem("NETCDF_DIM_EXTRA","") );
-            CSLDestroy( papszExtraDimNames );
+            CPLDebug("GDAL_netCDF",
+                     "Warning: Number of bands (%d) is not compatible with dimensions "
+                     "(total=%ld names=%s)", nBands, (long)nDimSizeTot,
+                     poSrcDS->GetMetadataItem("NETCDF_DIM_EXTRA", ""));
+            CSLDestroy(papszExtraDimNames);
             papszExtraDimNames = NULL;
         }
     }
 
-    int *panDimIds = reinterpret_cast<int *>( CPLCalloc( nDim, sizeof( int ) ) );
-    int *panBandDimPos = reinterpret_cast<int *>( CPLCalloc( nDim, sizeof( int ) ) );
+    int *panDimIds = static_cast<int *>(CPLCalloc(nDim, sizeof(int)));
+    int *panBandDimPos = static_cast<int *>(CPLCalloc(nDim, sizeof(int)));
 
     nc_type nVarType;
     int status = NC_NOERR;
     int *panBandZLev = NULL;
     int *panDimVarIds = NULL;
 
-    if ( nDim > 2 ) {
-        panBandZLev = reinterpret_cast<int *>( CPLCalloc( nDim-2, sizeof( int ) ) );
-        panDimVarIds = reinterpret_cast<int *>( CPLCalloc( nDim-2, sizeof( int ) ) );
-
-        /* define all dims */
-        for ( int i=CSLCount( papszExtraDimNames )-1; i>=0; i-- ) {
-            poDS->papszDimName.AddString( papszExtraDimNames[i] );
-            char szTemp[ NC_MAX_NAME + 32 + 1 ];
-            snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_DEF", papszExtraDimNames[i] );
-            papszExtraDimValues = NCDFTokenizeArray( poSrcDS->GetMetadataItem(szTemp,"") );
-            int nDimSize = atoi( papszExtraDimValues[0] );
-            /* nc_type is an enum in netcdf-3, needs casting */
-            nVarType = (nc_type) atol( papszExtraDimValues[1] );
-            CSLDestroy( papszExtraDimValues );
-            panBandZLev[ i ] = nDimSize;
-            panBandDimPos[ i+2 ] = i; //Save Position of ZDim
-
-            /* define dim */
-            status = nc_def_dim( poDS->cdfid, papszExtraDimNames[i], nDimSize,
-                                 &(panDimIds[i]) );
+    if( nDim > 2 )
+    {
+        panBandZLev = static_cast<int *>(CPLCalloc(nDim - 2, sizeof(int)));
+        panDimVarIds = static_cast<int *>(CPLCalloc(nDim - 2, sizeof(int)));
+
+        // Define all dims.
+        for( int i = CSLCount(papszExtraDimNames) - 1; i >= 0; i-- )
+        {
+            poDS->papszDimName.AddString(papszExtraDimNames[i]);
+            char szTemp[NC_MAX_NAME + 32 + 1];
+            snprintf(szTemp, sizeof(szTemp), "NETCDF_DIM_%s_DEF",
+                     papszExtraDimNames[i]);
+            papszExtraDimValues =
+                NCDFTokenizeArray(poSrcDS->GetMetadataItem(szTemp, ""));
+            const int nDimSize = atoi(papszExtraDimValues[0]);
+            // nc_type is an enum in netcdf-3, needs casting.
+            nVarType = static_cast<nc_type>(atol(papszExtraDimValues[1]));
+            CSLDestroy(papszExtraDimValues);
+            panBandZLev[i] = nDimSize;
+            panBandDimPos[i + 2] = i;  // Save Position of ZDim.
+
+            // Define dim.
+            status = nc_def_dim(poDS->cdfid, papszExtraDimNames[i], nDimSize,
+                                &(panDimIds[i]));
             NCDF_ERR(status);
 
-            /* define dim var */
-            int anDim[1];
-            anDim[0] = panDimIds[i];
-            status = nc_def_var( poDS->cdfid, papszExtraDimNames[i],
-                                 nVarType, 1, anDim,
-                                 &(panDimVarIds[i]) );
+            // Define dim var.
+            int anDim[1] = {panDimIds[i]};
+            status = nc_def_var(poDS->cdfid, papszExtraDimNames[i], nVarType, 1,
+                                anDim, &(panDimVarIds[i]));
             NCDF_ERR(status);
 
-            /* add dim metadata, using global var# items */
-            snprintf( szTemp, sizeof(szTemp), "%s#", papszExtraDimNames[i] );
-            CopyMetadata((void *) poSrcDS, poDS->cdfid, panDimVarIds[i], szTemp, false );
+            // Add dim metadata, using global var# items.
+            snprintf(szTemp, sizeof(szTemp), "%s#", papszExtraDimNames[i]);
+            CopyMetadata(poSrcDS, poDS->cdfid, panDimVarIds[i], szTemp, false);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Copy GeoTransform and Projection                                */
-/* -------------------------------------------------------------------- */
-    /* copy geolocation info */
-    if ( poSrcDS->GetMetadata("GEOLOCATION") != NULL )
-        poDS->SetMetadata( poSrcDS->GetMetadata("GEOLOCATION"), "GEOLOCATION" );
+    // Copy GeoTransform and Projection.
 
-    /* copy geotransform */
+    // Copy geolocation info.
+    if( poSrcDS->GetMetadata("GEOLOCATION") != NULL )
+        poDS->SetMetadata(poSrcDS->GetMetadata("GEOLOCATION"), "GEOLOCATION");
+
+    // Copy geotransform.
     bool bGotGeoTransform = false;
     double adfGeoTransform[6];
-    CPLErr eErr = poSrcDS->GetGeoTransform( adfGeoTransform );
-    if ( eErr == CE_None ) {
-        poDS->SetGeoTransform( adfGeoTransform );
-        /* disable AddProjectionVars() from being called */
+    CPLErr eErr = poSrcDS->GetGeoTransform(adfGeoTransform);
+    if( eErr == CE_None )
+    {
+        poDS->SetGeoTransform(adfGeoTransform);
+        // Disable AddProjectionVars() from being called.
         bGotGeoTransform = true;
         poDS->bSetGeoTransform = false;
     }
 
-    /* copy projection */
-    void *pScaledProgress;
-    if ( pszWKT ) {
-        poDS->SetProjection( pszWKT );
-        /* now we can call AddProjectionVars() directly */
+    // Copy projection.
+    void *pScaledProgress = NULL;
+    if( pszWKT )
+    {
+        poDS->SetProjection(pszWKT);
+        // Now we can call AddProjectionVars() directly.
         poDS->bSetGeoTransform = bGotGeoTransform;
-        pScaledProgress = GDALCreateScaledProgress( 0.1, 0.25, pfnProgress,
-                                                    pProgressData );
-        poDS->AddProjectionVars( GDALScaledProgress, pScaledProgress );
-        /* save X,Y dim positions */
-        panDimIds[nDim-1] = poDS->nXDimID;
-        panBandDimPos[0] = nDim-1;
-        panDimIds[nDim-2] = poDS->nYDimID;
-        panBandDimPos[1] = nDim-2;
-        GDALDestroyScaledProgress( pScaledProgress );
-
-    }
-
-    /* write extra dim values - after projection for optimization */
-    if ( nDim > 2 ) {
-        /* make sure we are in data mode */
-        reinterpret_cast<netCDFDataset *>( poDS )->SetDefineMode( false );
-        for ( int i=CSLCount( papszExtraDimNames )-1; i>=0; i-- ) {
-            char szTemp[ NC_MAX_NAME + 32 + 1 ];
-            snprintf( szTemp, sizeof(szTemp), "NETCDF_DIM_%s_VALUES", papszExtraDimNames[i] );
-            if ( poSrcDS->GetMetadataItem( szTemp ) != NULL ) {
-                NCDFPut1DVar( poDS->cdfid, panDimVarIds[i],
-                              poSrcDS->GetMetadataItem( szTemp ) );
+        pScaledProgress =
+            GDALCreateScaledProgress(0.1, 0.25, pfnProgress, pProgressData);
+        poDS->AddProjectionVars(GDALScaledProgress, pScaledProgress);
+        // Save X,Y dim positions.
+        panDimIds[nDim - 1] = poDS->nXDimID;
+        panBandDimPos[0] = nDim - 1;
+        panDimIds[nDim - 2] = poDS->nYDimID;
+        panBandDimPos[1] = nDim - 2;
+        GDALDestroyScaledProgress(pScaledProgress);
+    }
+
+    // Write extra dim values - after projection for optimization.
+    if( nDim > 2 )
+    {
+        // Make sure we are in data mode.
+        static_cast<netCDFDataset *>(poDS)->SetDefineMode(false);
+        for( int i = CSLCount(papszExtraDimNames) - 1; i >= 0; i-- )
+        {
+            char szTemp[NC_MAX_NAME + 32 + 1];
+            snprintf(szTemp, sizeof(szTemp), "NETCDF_DIM_%s_VALUES",
+                     papszExtraDimNames[i]);
+            if( poSrcDS->GetMetadataItem(szTemp) != NULL )
+            {
+                NCDFPut1DVar(poDS->cdfid, panDimVarIds[i],
+                             poSrcDS->GetMetadataItem(szTemp));
             }
         }
     }
 
-    pfnProgress( 0.25, NULL, pProgressData );
-
-/* -------------------------------------------------------------------- */
-/*      Define Bands                                                    */
-/* -------------------------------------------------------------------- */
+    pfnProgress(0.25, NULL, pProgressData);
 
+    // Define Bands.
     netCDFRasterBand *poBand = NULL;
     int nBandID = -1;
 
-    for( int iBand=1; iBand <= nBands; iBand++ ) {
-        CPLDebug( "GDAL_netCDF", "creating band # %d/%d nDim = %d",
-                  iBand, nBands, nDim );
+    for( int iBand = 1; iBand <= nBands; iBand++ )
+    {
+        CPLDebug("GDAL_netCDF", "creating band # %d/%d nDim = %d",
+                 iBand, nBands, nDim);
 
-        poSrcBand = poSrcDS->GetRasterBand( iBand );
+        poSrcBand = poSrcDS->GetRasterBand(iBand);
         eDT = poSrcBand->GetRasterDataType();
 
-        /* Get var name from NETCDF_VARNAME */
+        // Get var name from NETCDF_VARNAME.
         const char *tmpMetadata = poSrcBand->GetMetadataItem("NETCDF_VARNAME");
-        char szBandName[ NC_MAX_NAME+1 ];
-        if( tmpMetadata != NULL)
+        char szBandName[NC_MAX_NAME + 1];
+        if( tmpMetadata != NULL )
         {
             if( nBands > 1 && papszExtraDimNames == NULL )
-                snprintf(szBandName,sizeof(szBandName),"%s%d",tmpMetadata,iBand);
+                snprintf(szBandName, sizeof(szBandName),
+                         "%s%d", tmpMetadata, iBand);
             else
-                snprintf(szBandName,sizeof(szBandName),"%s",tmpMetadata);
+                snprintf(szBandName, sizeof(szBandName), "%s", tmpMetadata);
         }
         else
-            szBandName[0]='\0';
+        {
+            szBandName[0] = '\0';
+}
 
-        /* Get long_name from <var>#long_name */
-        char szLongName[ NC_MAX_NAME+1 ];
-        snprintf(szLongName, sizeof(szLongName),"%s#%s",
-                poSrcBand->GetMetadataItem("NETCDF_VARNAME"),
-                CF_LNG_NAME);
+        // Get long_name from <var>#long_name.
+        char szLongName[NC_MAX_NAME + 1];
+        snprintf(szLongName, sizeof(szLongName), "%s#%s",
+                 poSrcBand->GetMetadataItem("NETCDF_VARNAME"), CF_LNG_NAME);
         tmpMetadata = poSrcDS->GetMetadataItem(szLongName);
         if( tmpMetadata != NULL)
-            snprintf( szLongName, sizeof(szLongName), "%s", tmpMetadata);
+            snprintf(szLongName, sizeof(szLongName), "%s", tmpMetadata);
         else
-            szLongName[0]='\0';
+            szLongName[0] = '\0';
 
         bool bSignedData = true;
-        if ( eDT == GDT_Byte ) {
-            /* GDAL defaults to unsigned bytes, but check if metadata says its
-               signed, as NetCDF can support this for certain formats. */
+        if( eDT == GDT_Byte )
+        {
+            // GDAL defaults to unsigned bytes, but check if metadata says its
+            // signed, as NetCDF can support this for certain formats.
             bSignedData = false;
-            tmpMetadata = poSrcBand->GetMetadataItem("PIXELTYPE",
-                                                     "IMAGE_STRUCTURE");
-            if ( tmpMetadata && EQUAL(tmpMetadata,"SIGNEDBYTE") )
+            tmpMetadata =
+                poSrcBand->GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
+            if( tmpMetadata && EQUAL(tmpMetadata, "SIGNEDBYTE") )
                 bSignedData = true;
         }
 
-        if ( nDim > 2 )
-            poBand = new netCDFRasterBand( poDS, eDT, iBand,
-                                           bSignedData,
-                                           szBandName, szLongName,
-                                           nBandID, nDim, iBand-1,
-                                           panBandZLev, panBandDimPos,
-                                           panDimIds );
+        if( nDim > 2 )
+            poBand = new netCDFRasterBand(
+                poDS, eDT, iBand, bSignedData, szBandName, szLongName, nBandID,
+                nDim, iBand - 1, panBandZLev, panBandDimPos, panDimIds);
         else
-            poBand = new netCDFRasterBand( poDS, eDT, iBand,
-                                           bSignedData,
-                                           szBandName, szLongName );
+            poBand = new netCDFRasterBand(poDS, eDT, iBand, bSignedData,
+                                          szBandName, szLongName);
 
-        poDS->SetBand( iBand, poBand );
+        poDS->SetBand(iBand, poBand);
 
-        /* set nodata value, if any */
-        // poBand->SetNoDataValue( poSrcBand->GetNoDataValue(0) );
-        int bNoDataSet;
-        double dfNoDataValue = poSrcBand->GetNoDataValue( &bNoDataSet );
-        if ( bNoDataSet ) {
-            CPLDebug( "GDAL_netCDF", "SetNoDataValue(%f) source", dfNoDataValue );
-            poBand->SetNoDataValue( dfNoDataValue );
+        // Set nodata value, if any.
+        // poBand->SetNoDataValue(poSrcBand->GetNoDataValue(0));
+        int bNoDataSet = FALSE;
+        double dfNoDataValue = poSrcBand->GetNoDataValue(&bNoDataSet);
+        if( bNoDataSet )
+        {
+            CPLDebug("GDAL_netCDF", "SetNoDataValue(%f) source", dfNoDataValue);
+            poBand->SetNoDataValue(dfNoDataValue);
         }
 
-        /* Copy Metadata for band */
-        CopyMetadata( (void *) GDALGetRasterBand( poSrcDS, iBand ),
-                      poDS->cdfid, poBand->nZId );
+        // Copy Metadata for band.
+        CopyMetadata((void *)GDALGetRasterBand(poSrcDS, iBand),
+                      poDS->cdfid, poBand->nZId);
 
-        /* if more than 2D pass the first band's netcdf var ID to subsequent bands */
-        if ( nDim > 2 )
+        // If more than 2D pass the first band's netcdf var ID to subsequent
+        // bands.
+        if( nDim > 2 )
             nBandID = poBand->nZId;
     }
 
-    /* write projection variable to band variable */
+    // Write projection variable to band variable.
     poDS->AddGridMappingRef();
 
-    pfnProgress( 0.5, NULL, pProgressData );
+    pfnProgress(0.5, NULL, pProgressData);
+
+    // Write bands.
 
-/* -------------------------------------------------------------------- */
-/*      Write Bands                                                     */
-/* -------------------------------------------------------------------- */
-    /* make sure we are in data mode */
-    poDS->SetDefineMode( false );
+    // Make sure we are in data mode.
+    poDS->SetDefineMode(false);
 
     double dfTemp = 0.5;
-    double dfTemp2 = 0.5;
 
     eErr = CE_None;
-    GDALRasterBand *poDstBand = NULL;
 
-    for( int iBand=1; iBand <= nBands && eErr == CE_None; iBand++ ) {
-        dfTemp2 = dfTemp + 0.4/nBands;
-        pScaledProgress =
-            GDALCreateScaledProgress( dfTemp, dfTemp2,
-                                      pfnProgress, pProgressData );
+    for( int iBand = 1; iBand <= nBands && eErr == CE_None; iBand++ )
+    {
+        const double dfTemp2 = dfTemp + 0.4 / nBands;
+        pScaledProgress = GDALCreateScaledProgress(dfTemp, dfTemp2, pfnProgress,
+                                                   pProgressData);
         dfTemp = dfTemp2;
 
-        CPLDebug( "GDAL_netCDF", "copying band data # %d/%d ",
-                  iBand,nBands );
+        CPLDebug("GDAL_netCDF", "copying band data # %d/%d ", iBand, nBands);
 
-        poSrcBand = poSrcDS->GetRasterBand( iBand );
+        poSrcBand = poSrcDS->GetRasterBand(iBand);
         eDT = poSrcBand->GetRasterDataType();
 
-        poDstBand = poDS->GetRasterBand( iBand );
-
-/* -------------------------------------------------------------------- */
-/*      Copy Band data                                                  */
-/* -------------------------------------------------------------------- */
-        if( eDT == GDT_Byte ) {
-            CPLDebug( "GDAL_netCDF", "GByte Band#%d", iBand );
-            eErr = NCDFCopyBand<GByte>( poSrcBand, poDstBand, nXSize, nYSize,
-                                 GDALScaledProgress, pScaledProgress );
-        }
-        else if( ( eDT == GDT_UInt16 ) || ( eDT == GDT_Int16 ) ) {
-            CPLDebug( "GDAL_netCDF", "GInt16 Band#%d", iBand );
-            eErr = NCDFCopyBand<GInt16>( poSrcBand, poDstBand, nXSize, nYSize,
-                                 GDALScaledProgress, pScaledProgress );
-        }
-        else if( (eDT == GDT_UInt32) || (eDT == GDT_Int32) ) {
-            CPLDebug( "GDAL_netCDF", "GInt16 Band#%d", iBand );
-            eErr = NCDFCopyBand<GInt32>( poSrcBand, poDstBand, nXSize, nYSize,
-                                 GDALScaledProgress, pScaledProgress );
-        }
-        else if( eDT == GDT_Float32 ) {
-            CPLDebug( "GDAL_netCDF", "float Band#%d", iBand);
-            eErr = NCDFCopyBand<float>( poSrcBand, poDstBand, nXSize, nYSize,
-                                 GDALScaledProgress, pScaledProgress );
-        }
-        else if( eDT == GDT_Float64 ) {
-            CPLDebug( "GDAL_netCDF", "double Band#%d", iBand);
-            eErr = NCDFCopyBand<double>( poSrcBand, poDstBand, nXSize, nYSize,
-                                 GDALScaledProgress, pScaledProgress );
-        }
-        else {
-            CPLError( CE_Failure, CPLE_NotSupported,
+        GDALRasterBand *poDstBand = poDS->GetRasterBand(iBand);
+
+        // Copy band data.
+        if( eDT == GDT_Byte )
+        {
+            CPLDebug("GDAL_netCDF", "GByte Band#%d", iBand);
+            eErr = NCDFCopyBand<GByte>(poSrcBand, poDstBand, nXSize, nYSize,
+                                       GDALScaledProgress, pScaledProgress);
+        }
+        else if( (eDT == GDT_UInt16) || (eDT == GDT_Int16) )
+        {
+            CPLDebug("GDAL_netCDF", "GInt16 Band#%d", iBand);
+            eErr = NCDFCopyBand<GInt16>(poSrcBand, poDstBand, nXSize, nYSize,
+                                        GDALScaledProgress, pScaledProgress);
+        }
+        else if( (eDT == GDT_UInt32) || (eDT == GDT_Int32) )
+        {
+            CPLDebug("GDAL_netCDF", "GInt16 Band#%d", iBand);
+            eErr = NCDFCopyBand<GInt32>(poSrcBand, poDstBand, nXSize, nYSize,
+                                        GDALScaledProgress, pScaledProgress);
+        }
+        else if( eDT == GDT_Float32 )
+        {
+            CPLDebug("GDAL_netCDF", "float Band#%d", iBand);
+            eErr = NCDFCopyBand<float>(poSrcBand, poDstBand, nXSize, nYSize,
+                                       GDALScaledProgress, pScaledProgress);
+        }
+        else if( eDT == GDT_Float64 )
+        {
+            CPLDebug("GDAL_netCDF", "double Band#%d", iBand);
+            eErr = NCDFCopyBand<double>(poSrcBand, poDstBand, nXSize, nYSize,
+                                        GDALScaledProgress, pScaledProgress);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
                       "The NetCDF driver does not support GDAL data type %d",
-                      eDT );
+                      eDT);
         }
 
-        GDALDestroyScaledProgress( pScaledProgress );
+        GDALDestroyScaledProgress(pScaledProgress);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Cleanup and close.                                              */
-/* -------------------------------------------------------------------- */
-    delete( poDS );
+    delete(poDS);
 
-    CPLFree( panDimIds );
-    CPLFree( panBandDimPos );
-    CPLFree( panBandZLev );
-    CPLFree( panDimVarIds );
-    if ( papszExtraDimNames )
-        CSLDestroy( papszExtraDimNames );
+    CPLFree(panDimIds);
+    CPLFree(panBandDimPos);
+    CPLFree(panBandZLev);
+    CPLFree(panDimVarIds);
+    if( papszExtraDimNames )
+        CSLDestroy(papszExtraDimNames);
 
-    if (eErr != CE_None)
+    if( eErr != CE_None )
         return NULL;
 
-    pfnProgress( 0.95, NULL, pProgressData );
+    pfnProgress(0.95, NULL, pProgressData);
 
-/* -------------------------------------------------------------------- */
-/*      Re-open dataset so we can return it.                            */
-/* -------------------------------------------------------------------- */
-    poDS = reinterpret_cast<netCDFDataset *>(
-        GDALOpen( pszFilename, GA_ReadOnly ) );
+    // Re-open dataset so we can return it.
+    poDS =
+        reinterpret_cast<netCDFDataset *>(GDALOpen(pszFilename, GA_ReadOnly));
 
-/* -------------------------------------------------------------------- */
-/*      PAM cloning is disabled. See bug #4244.                         */
-/* -------------------------------------------------------------------- */
+    // PAM cloning is disabled. See bug #4244.
     // if( poDS )
-    //     poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+    //     poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT);
 
-    pfnProgress( 1.0, NULL, pProgressData );
+    pfnProgress(1.0, NULL, pProgressData);
 
     return poDS;
 }
 
-/* note: some logic depends on bIsProjected and bIsGeoGraphic */
-/* which may not be known when Create() is called, see AddProjectionVars() */
-void
-netCDFDataset::ProcessCreationOptions( )
+// Note: some logic depends on bIsProjected and bIsGeoGraphic.
+// May not be known when Create() is called, see AddProjectionVars().
+void netCDFDataset::ProcessCreationOptions()
 {
-    const char* pszConfig = CSLFetchNameValue( papszCreationOptions, "CONFIG_FILE" );
+    const char *pszConfig =
+        CSLFetchNameValue(papszCreationOptions, "CONFIG_FILE");
     if( pszConfig != NULL )
     {
         if( oWriterConfig.Parse(pszConfig) )
         {
             // Override dataset creation options from the config file
-            std::map<CPLString,CPLString>::iterator oIter;
+            std::map<CPLString, CPLString>::iterator oIter;
             for( oIter = oWriterConfig.m_oDatasetCreationOptions.begin();
                  oIter != oWriterConfig.m_oDatasetCreationOptions.end();
                  ++ oIter )
             {
-                papszCreationOptions = CSLSetNameValue(papszCreationOptions,
-                                                       oIter->first,
-                                                       oIter->second);
+                papszCreationOptions = CSLSetNameValue(
+                    papszCreationOptions, oIter->first, oIter->second);
             }
         }
     }
 
-    /* File format */
+    // File format.
     eFormat = NCDF_FORMAT_NC;
-    const char *pszValue = CSLFetchNameValue( papszCreationOptions, "FORMAT" );
-    if ( pszValue != NULL ) {
-        if ( EQUAL( pszValue, "NC" ) ) {
+    const char *pszValue = CSLFetchNameValue(papszCreationOptions, "FORMAT");
+    if( pszValue != NULL )
+    {
+        if( EQUAL(pszValue, "NC") )
+        {
             eFormat = NCDF_FORMAT_NC;
         }
 #ifdef NETCDF_HAS_NC2
-        else if ( EQUAL( pszValue, "NC2" ) ) {
+        else if( EQUAL(pszValue, "NC2") )
+        {
             eFormat = NCDF_FORMAT_NC2;
         }
 #endif
 #ifdef NETCDF_HAS_NC4
-        else if ( EQUAL( pszValue, "NC4" ) ) {
+        else if( EQUAL(pszValue, "NC4") )
+        {
             eFormat = NCDF_FORMAT_NC4;
         }
-        else if ( EQUAL( pszValue, "NC4C" ) ) {
+        else if( EQUAL(pszValue, "NC4C") )
+        {
             eFormat = NCDF_FORMAT_NC4C;
         }
 #endif
-        else {
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "FORMAT=%s in not supported, using the default NC format.", pszValue );
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "FORMAT=%s in not supported, using the default NC format.",
+                     pszValue);
         }
     }
 
-    /* compression only available for NC4 */
+    // Compression only available for NC4.
 #ifdef NETCDF_HAS_NC4
 
-    /* COMPRESS option */
-    pszValue = CSLFetchNameValue( papszCreationOptions, "COMPRESS" );
-    if ( pszValue != NULL ) {
-        if ( EQUAL( pszValue, "NONE" ) ) {
+    // COMPRESS option.
+    pszValue = CSLFetchNameValue(papszCreationOptions, "COMPRESS");
+    if( pszValue != NULL )
+    {
+        if( EQUAL(pszValue, "NONE") )
+        {
             eCompress = NCDF_COMPRESS_NONE;
         }
-        else if ( EQUAL( pszValue, "DEFLATE" ) ) {
+        else if( EQUAL(pszValue, "DEFLATE") )
+        {
             eCompress = NCDF_COMPRESS_DEFLATE;
-            if ( !((eFormat == NCDF_FORMAT_NC4) || (eFormat == NCDF_FORMAT_NC4C)) ) {
-                CPLError( CE_Warning, CPLE_IllegalArg,
-                          "NOTICE: Format set to NC4C because compression is set to DEFLATE." );
+            if( !((eFormat == NCDF_FORMAT_NC4) ||
+                  (eFormat == NCDF_FORMAT_NC4C)) )
+            {
+                CPLError(CE_Warning, CPLE_IllegalArg,
+                         "NOTICE: Format set to NC4C because compression is "
+                         "set to DEFLATE.");
                 eFormat = NCDF_FORMAT_NC4C;
             }
         }
-        else {
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "COMPRESS=%s is not supported.", pszValue );
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                      "COMPRESS=%s is not supported.", pszValue);
         }
     }
 
-    /* ZLEVEL option */
-    pszValue = CSLFetchNameValue( papszCreationOptions, "ZLEVEL" );
+    // ZLEVEL option.
+    pszValue = CSLFetchNameValue(papszCreationOptions, "ZLEVEL");
     if( pszValue != NULL )
     {
-        nZLevel =  atoi( pszValue );
-        if (!(nZLevel >= 1 && nZLevel <= 9))
+        nZLevel = atoi(pszValue);
+        if( !(nZLevel >= 1 && nZLevel <= 9) )
         {
-            CPLError( CE_Warning, CPLE_IllegalArg,
-                    "ZLEVEL=%s value not recognised, ignoring.",
-                    pszValue );
+            CPLError(CE_Warning, CPLE_IllegalArg,
+                     "ZLEVEL=%s value not recognised, ignoring.", pszValue);
             nZLevel = NCDF_DEFLATE_LEVEL;
         }
     }
 
-    /* CHUNKING option */
-    bChunking = CPL_TO_BOOL(CSLFetchBoolean( papszCreationOptions, "CHUNKING", TRUE ));
+    // CHUNKING option.
+    bChunking =
+        CPL_TO_BOOL(CSLFetchBoolean(papszCreationOptions, "CHUNKING", TRUE));
 
 #endif
 
-    /* MULTIPLE_LAYERS option */
-    const char* pszMultipleLayerBehaviour = CSLFetchNameValueDef(
-                            papszCreationOptions, "MULTIPLE_LAYERS", "NO");
+    // MULTIPLE_LAYERS option.
+    const char *pszMultipleLayerBehaviour =
+        CSLFetchNameValueDef(papszCreationOptions, "MULTIPLE_LAYERS", "NO");
     if( EQUAL(pszMultipleLayerBehaviour, "NO") )
+    {
         eMultipleLayerBehaviour = SINGLE_LAYER;
+    }
     else if( EQUAL(pszMultipleLayerBehaviour, "SEPARATE_FILES") )
+    {
         eMultipleLayerBehaviour = SEPARATE_FILES;
+    }
 #ifdef NETCDF_HAS_NC4
     else if( EQUAL(pszMultipleLayerBehaviour, "SEPARATE_GROUPS") )
     {
@@ -7172,92 +7448,95 @@ netCDFDataset::ProcessCreationOptions( )
         }
         else
         {
-            CPLError( CE_Warning, CPLE_IllegalArg,
-                      "MULTIPLE_LAYERS=%s is recognised only with FORMAT=NC4",
-                      pszMultipleLayerBehaviour );
+            CPLError(CE_Warning, CPLE_IllegalArg,
+                     "MULTIPLE_LAYERS=%s is recognised only with FORMAT=NC4",
+                     pszMultipleLayerBehaviour);
         }
     }
 #endif
     else
     {
-        CPLError( CE_Warning, CPLE_IllegalArg, "MULTIPLE_LAYERS=%s not recognised",
-                  pszMultipleLayerBehaviour );
+        CPLError(CE_Warning, CPLE_IllegalArg,
+                 "MULTIPLE_LAYERS=%s not recognised",
+                 pszMultipleLayerBehaviour);
     }
 
-    /* set nCreateMode based on eFormat */
-    switch ( eFormat ) {
+    // Set nCreateMode based on eFormat.
+    switch( eFormat )
+    {
 #ifdef NETCDF_HAS_NC2
-        case NCDF_FORMAT_NC2:
-            nCreateMode = NC_CLOBBER|NC_64BIT_OFFSET;
-            break;
+    case NCDF_FORMAT_NC2:
+        nCreateMode = NC_CLOBBER | NC_64BIT_OFFSET;
+        break;
 #endif
 #ifdef NETCDF_HAS_NC4
-        case NCDF_FORMAT_NC4:
-            nCreateMode = NC_CLOBBER|NC_NETCDF4;
-            break;
-        case NCDF_FORMAT_NC4C:
-            nCreateMode = NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL;
-            break;
+    case NCDF_FORMAT_NC4:
+        nCreateMode = NC_CLOBBER | NC_NETCDF4;
+        break;
+    case NCDF_FORMAT_NC4C:
+        nCreateMode = NC_CLOBBER | NC_NETCDF4 | NC_CLASSIC_MODEL;
+        break;
 #endif
-        case NCDF_FORMAT_NC:
-        default:
-            nCreateMode = NC_CLOBBER;
-            break;
+    case NCDF_FORMAT_NC:
+    default:
+        nCreateMode = NC_CLOBBER;
+        break;
     }
 
-    CPLDebug( "GDAL_netCDF",
-              "file options: format=%d compress=%d zlevel=%d",
-              eFormat, eCompress, nZLevel );
+    CPLDebug("GDAL_netCDF", "file options: format=%d compress=%d zlevel=%d",
+             eFormat, eCompress, nZLevel);
 }
 
 int netCDFDataset::DefVarDeflate(
 #ifdef NETCDF_HAS_NC4
-            int nVarId, bool bChunkingArg
+    int nVarId, bool bChunkingArg
 #else
-            int /* nVarId */ , bool /* bChunkingArg */
+    int /* nVarId */, bool /* bChunkingArg */
 #endif
-            )
+    )
 {
 #ifdef NETCDF_HAS_NC4
-    if ( eCompress == NCDF_COMPRESS_DEFLATE ) {
-        // Must set chunk size to avoid huge performance hit (set bChunkingArg=TRUE)
+    if( eCompress == NCDF_COMPRESS_DEFLATE )
+    {
+        // Must set chunk size to avoid huge performance hit (set
+        // bChunkingArg=TRUE)
         // perhaps another solution it to change the chunk cache?
         // http://www.unidata.ucar.edu/software/netcdf/docs/netcdf.html#Chunk-Cache
         // TODO: make sure this is okay.
-        CPLDebug( "GDAL_netCDF",
-                  "DefVarDeflate( %d, %d ) nZlevel=%d",
-                  nVarId, static_cast<int>(bChunkingArg), nZLevel );
+        CPLDebug("GDAL_netCDF", "DefVarDeflate(%d, %d) nZlevel=%d", nVarId,
+                 static_cast<int>(bChunkingArg), nZLevel);
 
-        int status = nc_def_var_deflate(cdfid,nVarId,1,1,nZLevel);
+        int status = nc_def_var_deflate(cdfid, nVarId, 1, 1, nZLevel);
         NCDF_ERR(status);
 
-        if ( (status == NC_NOERR) && bChunkingArg && bChunking ) {
-
+        if( status == NC_NOERR && bChunkingArg && bChunking )
+        {
             // set chunking to be 1 for all dims, except X dim
             // size_t chunksize[] = { 1, (size_t)nRasterXSize };
-            size_t chunksize[ MAX_NC_DIMS ];
+            size_t chunksize[MAX_NC_DIMS];
             int nd;
-            nc_inq_varndims( cdfid, nVarId, &nd );
+            nc_inq_varndims(cdfid, nVarId, &nd);
             chunksize[0] = (size_t)1;
             chunksize[1] = (size_t)1;
-            for( int i=2; i<nd; i++ ) chunksize[i] = (size_t)1;
-            chunksize[nd-1] = (size_t)nRasterXSize;
+            for( int i = 2; i < nd; i++) chunksize[i] = (size_t)1;
+            chunksize[nd - 1] = (size_t)nRasterXSize;
 
-            CPLDebug( "GDAL_netCDF",
-                      "DefVarDeflate() chunksize={%ld, %ld} chunkX=%ld nd=%d",
-                      (long)chunksize[0], (long)chunksize[1], (long)chunksize[nd-1], nd );
+            CPLDebug("GDAL_netCDF",
+                     "DefVarDeflate() chunksize={%ld, %ld} chunkX=%ld nd=%d",
+                     (long)chunksize[0], (long)chunksize[1],
+                     (long)chunksize[nd - 1], nd);
 #ifdef NCDF_DEBUG
-            for( int i=0; i<nd; i++ )
-                CPLDebug( "GDAL_netCDF","DefVarDeflate() chunk[%d]=%ld", i, chunksize[i] );
+            for( int i = 0; i < nd; i++ )
+                CPLDebug("GDAL_netCDF", "DefVarDeflate() chunk[%d]=%ld",
+                         i, chunksize[i]);
 #endif
 
-            status = nc_def_var_chunking( cdfid, nVarId,
-                                          NC_CHUNKED, chunksize );
+            status = nc_def_var_chunking(cdfid, nVarId, NC_CHUNKED, chunksize);
             NCDF_ERR(status);
         }
-        else {
-            CPLDebug( "GDAL_netCDF",
-                      "chunksize not set" );
+        else
+        {
+            CPLDebug("GDAL_netCDF", "chunksize not set");
         }
         return status;
     }
@@ -7269,7 +7548,7 @@ int netCDFDataset::DefVarDeflate(
 /*                           NCDFUnloadDriver()                         */
 /************************************************************************/
 
-static void NCDFUnloadDriver(CPL_UNUSED GDALDriver* poDriver)
+static void NCDFUnloadDriver(CPL_UNUSED GDALDriver *poDriver)
 {
     if( hNCMutex != NULL )
         CPLDestroyMutex(hNCMutex);
@@ -7283,26 +7562,22 @@ static void NCDFUnloadDriver(CPL_UNUSED GDALDriver* poDriver)
 void GDALRegister_netCDF()
 
 {
-    if( !GDAL_CHECK_VERSION( "netCDF driver" ) )
+    if( !GDAL_CHECK_VERSION("netCDF driver") )
         return;
 
-    if( GDALGetDriverByName( "netCDF" ) != NULL )
+    if( GDALGetDriverByName("netCDF") != NULL )
         return;
 
-    GDALDriver *poDriver = new GDALDriver( );
-
-/* -------------------------------------------------------------------- */
-/*      Set the driver details.                                         */
-/* -------------------------------------------------------------------- */
-    poDriver->SetDescription( "netCDF" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                               "Network Common Data Format" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                               "frmt_netcdf.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    GDALDriver *poDriver = new GDALDriver();
+
+    // Set the driver details.
+    poDriver->SetDescription("netCDF");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Network Common Data Format");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_netcdf.html");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "nc");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='FORMAT' type='string-select' default='NC'>"
 "     <Value>NC</Value>"
@@ -7348,10 +7623,10 @@ void GDALRegister_netCDF()
 "   </Option>"
 "   <Option name='CONFIG_FILE' type='string' description='Path to a XML configuration file (or content inlined)'/>"
 "</CreationOptionList>"
-                               );
-    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+                              );
+    poDriver->SetMetadataItem(GDAL_DMD_SUBDATASETS, "YES");
 
-    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "   <Option name='RECORD_DIM_NAME' type='string' description='Name of the unlimited dimension' default='record'/>"
 "   <Option name='STRING_DEFAULT_WIDTH' type='int' description='"
@@ -7379,38 +7654,38 @@ void GDALRegister_netCDF()
 "   <Option name='PROFILE_DIM_NAME' type='string' description='Name of the profile dimension and variable' default='profile'/>"
 "   <Option name='PROFILE_DIM_INIT_SIZE' type='string' description='Initial size of profile dimension (default 100), or UNLIMITED for NC4 files'/>"
 "   <Option name='PROFILE_VARIABLES' type='string' description='Comma separated list of field names that must be indexed by the profile dimension'/>"
-"</LayerCreationOptionList>" );
+"</LayerCreationOptionList>");
 
-    /* make driver config and capabilities available */
-    poDriver->SetMetadataItem( "NETCDF_VERSION", nc_inq_libvers() );
-    poDriver->SetMetadataItem( "NETCDF_CONVENTIONS", NCDF_CONVENTIONS_CF_V1_5 );
+    // Make driver config and capabilities available.
+    poDriver->SetMetadataItem("NETCDF_VERSION", nc_inq_libvers());
+    poDriver->SetMetadataItem("NETCDF_CONVENTIONS", NCDF_CONVENTIONS_CF_V1_5);
 #ifdef NETCDF_HAS_NC2
-    poDriver->SetMetadataItem( "NETCDF_HAS_NC2", "YES" );
+    poDriver->SetMetadataItem("NETCDF_HAS_NC2", "YES");
 #endif
 #ifdef NETCDF_HAS_NC4
-    poDriver->SetMetadataItem( "NETCDF_HAS_NC4", "YES" );
+    poDriver->SetMetadataItem("NETCDF_HAS_NC4", "YES");
 #endif
 #ifdef NETCDF_HAS_HDF4
-    poDriver->SetMetadataItem( "NETCDF_HAS_HDF4", "YES" );
+    poDriver->SetMetadataItem("NETCDF_HAS_HDF4", "YES");
 #endif
 #ifdef HAVE_HDF4
-    poDriver->SetMetadataItem( "GDAL_HAS_HDF4", "YES" );
+    poDriver->SetMetadataItem("GDAL_HAS_HDF4", "YES");
 #endif
 #ifdef HAVE_HDF5
-    poDriver->SetMetadataItem( "GDAL_HAS_HDF5", "YES" );
+    poDriver->SetMetadataItem("GDAL_HAS_HDF5", "YES");
 #endif
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
-                               "Integer Integer64 Real String Date DateTime" );
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
+                              "Integer Integer64 Real String Date DateTime");
 
-    /* set pfns and register driver */
+    // Set pfns and register driver.
     poDriver->pfnOpen = netCDFDataset::Open;
     poDriver->pfnCreateCopy = netCDFDataset::CreateCopy;
     poDriver->pfnCreate = netCDFDataset::Create;
     poDriver->pfnIdentify = netCDFDataset::Identify;
     poDriver->pfnUnloadDriver = NCDFUnloadDriver;
 
-    GetGDALDriverManager( )->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 
 #ifdef NETCDF_PLUGIN
     GDALRegister_GMT();
@@ -7422,77 +7697,84 @@ void GDALRegister_netCDF()
 /************************************************************************/
 
 /* Test for GDAL version string >= target */
-static bool NCDFIsGDALVersionGTE(const char* pszVersion, int nTarget)
+static bool NCDFIsGDALVersionGTE(const char *pszVersion, int nTarget)
 {
 
-    /* Valid strings are "GDAL 1.9dev, released 2011/01/18" and "GDAL 1.8.1 " */
-    if ( pszVersion == NULL || EQUAL( pszVersion, "" ) )
+    // Valid strings are "GDAL 1.9dev, released 2011/01/18" and "GDAL 1.8.1 ".
+    if( pszVersion == NULL || EQUAL(pszVersion, "") )
         return false;
-    else if ( ! STARTS_WITH_CI(pszVersion, "GDAL ") )
+    else if( !STARTS_WITH_CI(pszVersion, "GDAL ") )
         return false;
-    /* 2.0dev of 2011/12/29 has been later renamed as 1.10dev */
-    else if ( EQUAL("GDAL 2.0dev, released 2011/12/29", pszVersion) )
-        return nTarget <= GDAL_COMPUTE_VERSION(1,10,0);
-    else if ( STARTS_WITH_CI(pszVersion, "GDAL 1.9dev") )
+    // 2.0dev of 2011/12/29 has been later renamed as 1.10dev.
+    else if( EQUAL("GDAL 2.0dev, released 2011/12/29", pszVersion) )
+        return nTarget <= GDAL_COMPUTE_VERSION(1, 10, 0);
+    else if( STARTS_WITH_CI(pszVersion, "GDAL 1.9dev") )
         return nTarget <= 1900;
-    else if ( STARTS_WITH_CI(pszVersion, "GDAL 1.8dev") )
+    else if( STARTS_WITH_CI(pszVersion, "GDAL 1.8dev") )
         return nTarget <= 1800;
 
-    char **papszTokens = CSLTokenizeString2( pszVersion+5, ".", 0 );
+    char **papszTokens = CSLTokenizeString2(pszVersion + 5, ".", 0);
 
-    int nVersions [] = {0, 0, 0, 0};
-    for ( int iToken = 0; papszTokens && iToken < 4 && papszTokens[iToken]; iToken++ )  {
-        nVersions[iToken] = atoi( papszTokens[iToken] );
+    int nVersions[] = {0, 0, 0, 0};
+    for( int iToken = 0;
+         papszTokens && iToken < 4 && papszTokens[iToken];
+         iToken++ )
+    {
+        nVersions[iToken] = atoi(papszTokens[iToken]);
     }
 
     int nVersion = 0;
     if( nVersions[0] > 1 || nVersions[1] >= 10 )
-        nVersion = GDAL_COMPUTE_VERSION( nVersions[0], nVersions[1], nVersions[2] );
+        nVersion =
+            GDAL_COMPUTE_VERSION(nVersions[0], nVersions[1], nVersions[2]);
     else
-        nVersion = nVersions[0]*1000 + nVersions[1]*100 +
-            nVersions[2]*10 + nVersions[3];
+        nVersion = nVersions[0] * 1000 + nVersions[1] * 100 +
+                   nVersions[2] * 10 + nVersions[3];
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
     return nTarget <= nVersion;
 }
 
-/* Add Conventions, GDAL version and history  */
+// Add Conventions, GDAL version and history.
 static void NCDFAddGDALHistory( int fpImage,
-                         const char * pszFilename, const char *pszOldHist,
-                         const char * pszFunctionName,
-                                const char * pszCFVersion )
+                                const char *pszFilename,
+                                const char *pszOldHist,
+                                const char *pszFunctionName,
+                                const char *pszCFVersion )
 {
-    int status = nc_put_att_text( fpImage, NC_GLOBAL, "Conventions",
-                     strlen(pszCFVersion),
-                     pszCFVersion );
+    int status = nc_put_att_text(fpImage, NC_GLOBAL, "Conventions",
+                                 strlen(pszCFVersion), pszCFVersion);
     NCDF_ERR(status);
 
-    const char* pszNCDF_GDAL = GDALVersionInfo("--version");
-    status = nc_put_att_text( fpImage, NC_GLOBAL, "GDAL",
-                     strlen(pszNCDF_GDAL), pszNCDF_GDAL );
+    const char *pszNCDF_GDAL = GDALVersionInfo("--version");
+    status = nc_put_att_text(fpImage, NC_GLOBAL, "GDAL",
+                             strlen(pszNCDF_GDAL), pszNCDF_GDAL);
     NCDF_ERR(status);
 
-    /* Add history */
+    // Add history.
     CPLString osTmp;
 #ifdef GDAL_SET_CMD_LINE_DEFINED_TMP
-    if ( ! EQUAL(GDALGetCmdLine(), "" ) )
+    if( !EQUAL(GDALGetCmdLine(), "") )
         osTmp = GDALGetCmdLine();
     else
-        osTmp = CPLSPrintf("GDAL %s( %s, ... )",pszFunctionName,pszFilename );
+        osTmp = CPLSPrintf("GDAL %s( %s, ... )", pszFunctionName, pszFilename);
 #else
-    osTmp = CPLSPrintf("GDAL %s( %s, ... )",pszFunctionName,pszFilename );
+    osTmp = CPLSPrintf("GDAL %s( %s, ... )", pszFunctionName, pszFilename);
 #endif
 
-    NCDFAddHistory( fpImage, osTmp.c_str(), pszOldHist );
+    NCDFAddHistory(fpImage, osTmp.c_str(), pszOldHist);
 }
 
-/* code taken from cdo and libcdi, used for writing the history attribute */
-//void cdoDefHistory(int fileID, char *histstring)
-static void NCDFAddHistory(int fpImage, const char *pszAddHist, const char *pszOldHist)
+// Code taken from cdo and libcdi, used for writing the history attribute.
+
+// void cdoDefHistory(int fileID, char *histstring)
+static void NCDFAddHistory(int fpImage, const char *pszAddHist,
+                           const char *pszOldHist)
 {
-    /* Check pszOldHist - as if there was no previous history, it will be
-       a null pointer - if so set as empty. */
-    if (NULL == pszOldHist) {
+    // Check pszOldHist - as if there was no previous history, it will be
+    // a null pointer - if so set as empty.
+    if( NULL == pszOldHist )
+    {
         pszOldHist = "";
     }
 
@@ -7500,53 +7782,57 @@ static void NCDFAddHistory(int fpImage, const char *pszAddHist, const char *pszO
     strtime[0] = '\0';
 
     time_t tp = time(NULL);
-    if ( tp != -1 )
+    if( tp != -1 )
     {
         struct tm *ltime = localtime(&tp);
-        (void) strftime(strtime, sizeof(strtime), "%a %b %d %H:%M:%S %Y: ", ltime);
+        (void)strftime(strtime, sizeof(strtime), "%a %b %d %H:%M:%S %Y: ",
+                       ltime);
     }
 
-    // status = nc_get_att_text( fpImage, NC_GLOBAL,
-    //                           "history", pszOldHist );
+    // status = nc_get_att_text(fpImage, NC_GLOBAL,
+    //                           "history", pszOldHist);
     // printf("status: %d pszOldHist: [%s]\n",status,pszOldHist);
 
-    size_t nNewHistSize
-        = strlen(pszOldHist)+strlen(strtime)+strlen(pszAddHist)+1+1;
-    char *pszNewHist
-        = reinterpret_cast<char *>( CPLMalloc(nNewHistSize * sizeof(char)) );
+    size_t nNewHistSize =
+        strlen(pszOldHist) + strlen(strtime) + strlen(pszAddHist) + 1 + 1;
+    char *pszNewHist =
+        static_cast<char *>(CPLMalloc(nNewHistSize * sizeof(char)));
 
     strcpy(pszNewHist, strtime);
     strcat(pszNewHist, pszAddHist);
 
     // int disableHistory = FALSE;
-    //if ( !disableHistory )
+    // if( !disableHistory )
     {
-        if ( ! EQUAL(pszOldHist,"") )
+        if( !EQUAL(pszOldHist, "") )
             strcat(pszNewHist, "\n");
         strcat(pszNewHist, pszOldHist);
     }
 
-    int status = nc_put_att_text( fpImage, NC_GLOBAL,
-                                  "history", strlen(pszNewHist),
-                                  pszNewHist );
+    const int status = nc_put_att_text(fpImage, NC_GLOBAL, "history",
+                                       strlen(pszNewHist), pszNewHist);
     NCDF_ERR(status);
 
     CPLFree(pszNewHist);
 }
 
-static bool NCDFIsCfProjection( const char* pszProjection )
+static bool NCDFIsCfProjection( const char *pszProjection )
 {
-    /* Find the appropriate mapping */
-    for (int iMap = 0; poNetcdfSRS_PT[iMap].WKT_SRS != NULL; iMap++ ) {
-        // printf("now at %d, proj=%s\n",i, poNetcdfSRS_PT[i].GDAL_SRS);
-        if ( EQUAL( pszProjection, poNetcdfSRS_PT[iMap].WKT_SRS ) )  {
+    // Find the appropriate mapping.
+    for( int iMap = 0; poNetcdfSRS_PT[iMap].WKT_SRS != NULL; iMap++ )
+    {
+#ifdef NCDF_DEBUG
+      CPLDebug("GDAL_netCDF", "now at %d, proj=%s",
+               iMap, poNetcdfSRS_PT[iMap].WKT_SRS);
+#endif
+      if( EQUAL(pszProjection, poNetcdfSRS_PT[iMap].WKT_SRS) )
+        {
             return poNetcdfSRS_PT[iMap].mappings != NULL;
         }
     }
     return false;
 }
 
-
 /* Write any needed projection attributes *
  * poPROJCS: ptr to proj crd system
  * pszProjection: name of projection system in GDAL WKT
@@ -7563,208 +7849,244 @@ static bool NCDFIsCfProjection( const char* pszProjection )
  * mappings and the associated value are saved in std::map objects.
  */
 
-/* NOTE modifications by ET to combine the specific and generic mappings */
+// NOTE: modifications by ET to combine the specific and generic mappings.
 
 static void NCDFWriteProjAttribs( const OGR_SRSNode *poPROJCS,
-                           const char* pszProjection,
-                           const int fpImage, const int NCDFVarID )
+                                  const char *pszProjection,
+                                  const int fpImage, const int NCDFVarID )
 {
     const oNetcdfSRS_PP *poMap = NULL;
     int nMapIndex = -1;
 
-    /* Find the appropriate mapping */
-    for (int iMap = 0; poNetcdfSRS_PT[iMap].WKT_SRS != NULL; iMap++ ) {
-        if ( EQUAL( pszProjection, poNetcdfSRS_PT[iMap].WKT_SRS ) ) {
+    // Find the appropriate mapping.
+    for( int iMap = 0; poNetcdfSRS_PT[iMap].WKT_SRS != NULL; iMap++ )
+    {
+        if( EQUAL(pszProjection, poNetcdfSRS_PT[iMap].WKT_SRS) )
+        {
             nMapIndex = iMap;
             poMap = poNetcdfSRS_PT[iMap].mappings;
             break;
         }
     }
 
-    //ET TODO if projection name is not found, should we do something special?
-    if ( nMapIndex == -1 ) {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "projection name %s not found in the lookup tables!!!",
-                  pszProjection);
+    // ET TODO if projection name is not found, should we do something special?
+    if( nMapIndex == -1 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "projection name %s not found in the lookup tables!",
+                 pszProjection);
     }
-    /* if no mapping was found or assigned, set the generic one */
-    if ( !poMap ) {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "projection name %s in not part of the CF standard, will not be supported by CF!",
-                  pszProjection);
+    // If no mapping was found or assigned, set the generic one.
+    if( !poMap )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "projection name %s in not part of the CF standard, "
+                 "will not be supported by CF!",
+                 pszProjection);
         poMap = poGenericMappings;
     }
 
-    /* initialize local map objects */
+    // Initialize local map objects.
 
     // Attribute <GDAL,NCDF> and Value <NCDF,value> mappings
-    std::map< std::string, std::string > oAttMap;
-    for ( int iMap = 0; poMap[iMap].WKT_ATT != NULL; iMap++ ) {
+    std::map<std::string, std::string> oAttMap;
+    for( int iMap = 0; poMap[iMap].WKT_ATT != NULL; iMap++ )
+    {
         oAttMap[poMap[iMap].WKT_ATT] = poMap[iMap].CF_ATT;
     }
 
-    const char *pszParamStr;
-    const char *pszParamVal;
-    std::map< std::string, double > oValMap;
-    for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ ) {
-
-        const OGR_SRSNode *poNode = poPROJCS->GetChild( iChild );
-        if( !EQUAL(poNode->GetValue(),"PARAMETER")
-            || poNode->GetChildCount() != 2 )
+    const char *pszParamVal = NULL;
+    std::map<std::string, double> oValMap;
+    for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
+    {
+        const OGR_SRSNode *poNode = poPROJCS->GetChild(iChild);
+        if( !EQUAL(poNode->GetValue(), "PARAMETER") ||
+            poNode->GetChildCount() != 2 )
             continue;
-        pszParamStr = poNode->GetChild(0)->GetValue();
+        const char *pszParamStr = poNode->GetChild(0)->GetValue();
         pszParamVal = poNode->GetChild(1)->GetValue();
 
         oValMap[pszParamStr] = CPLAtof(pszParamVal);
     }
 
     double dfValue = 0.0;
-    const std::string *posNCDFAtt;
     const std::string *posGDALAtt;
-    bool bWriteVal = false;
-    std::map< std::string, std::string >::iterator oAttIter;
-    std::map< std::string, double >::iterator oValIter, oValIter2;
+    std::map<std::string, std::string>::iterator oAttIter;
+    std::map<std::string, double>::iterator oValIter, oValIter2;
 
     // Results to write.
-    std::vector< std::pair<std::string,double> > oOutList;
-
-    /* Lookup mappings and fill output vector */
-    if ( poMap != poGenericMappings ) { /* specific mapping, loop over mapping values */
-
-        for ( oAttIter = oAttMap.begin(); oAttIter != oAttMap.end(); oAttIter++ ) {
+    std::vector<std::pair<std::string, double> > oOutList;
 
+    // Lookup mappings and fill output vector.
+    if(poMap != poGenericMappings)
+    {
+        // Specific mapping, loop over mapping values.
+        for( oAttIter = oAttMap.begin(); oAttIter != oAttMap.end(); ++oAttIter )
+        {
             posGDALAtt = &(oAttIter->first);
-            posNCDFAtt = &(oAttIter->second);
-            oValIter = oValMap.find( *posGDALAtt );
-
-            if ( oValIter != oValMap.end() ) {
+            const std::string *posNCDFAtt = &(oAttIter->second);
+            oValIter = oValMap.find(*posGDALAtt);
 
+            if( oValIter != oValMap.end() )
+            {
                 dfValue = oValIter->second;
-                bWriteVal = true;
+                bool bWriteVal = true;
 
-                /* special case for PS (Polar Stereographic) grid
-                   See comments in netcdfdataset.h for this projection. */
-                if ( EQUAL( SRS_PP_LATITUDE_OF_ORIGIN, posGDALAtt->c_str() ) &&
-                     EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) ) {
+                // special case for PS (Polar Stereographic) grid.
+                // See comments in netcdfdataset.h for this projection.
+                if( EQUAL(SRS_PP_LATITUDE_OF_ORIGIN, posGDALAtt->c_str()) &&
+                    EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) )
+                {
                     double dfLatPole = 0.0;
-                    if ( dfValue > 0.0) dfLatPole = 90.0;
+                    if( dfValue > 0.0 ) dfLatPole = 90.0;
                     else dfLatPole = -90.0;
-                        oOutList.push_back( std::make_pair( std::string(CF_PP_LAT_PROJ_ORIGIN),
-                                                            dfLatPole ) );
+                    oOutList.push_back(std::make_pair(
+                        std::string(CF_PP_LAT_PROJ_ORIGIN), dfLatPole));
                 }
 
-                /* special case for LCC-1SP
-                   See comments in netcdfdataset.h for this projection. */
-                else if ( EQUAL( SRS_PP_SCALE_FACTOR, posGDALAtt->c_str() ) &&
-                          EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) ) {
-                    /* default is to not write as it is not CF-1 */
+                // special case for LCC-1SP
+                //   See comments in netcdfdataset.h for this projection.
+                else if( EQUAL(SRS_PP_SCALE_FACTOR, posGDALAtt->c_str()) &&
+                         EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
+                {
+                    // Default is to not write as it is not CF-1.
                     bWriteVal = false;
-                    /* test if there is no standard_parallel1 */
-                    if ( oValMap.find( std::string(CF_PP_STD_PARALLEL_1) ) == oValMap.end() ) {
-                        /* if scale factor != 1.0  write value for GDAL, but this is not supported by CF-1 */
-                        if ( !CPLIsEqual(dfValue,1.0) ) {
-                            CPLError( CE_Failure, CPLE_NotSupported,
-                                      "NetCDF driver export of LCC-1SP with scale factor != 1.0 "
-                                      "and no standard_parallel1 is not CF-1 (bug #3324).\n"
-                                      "Use the 2SP variant which is supported by CF." );
+                    // Test if there is no standard_parallel1.
+                    if( oValMap.find(std::string(CF_PP_STD_PARALLEL_1)) == oValMap.end() )
+                    {
+                        // If scale factor != 1.0, write value for GDAL, but
+                        // this is not supported by CF-1.
+                        if( !CPLIsEqual(dfValue, 1.0) )
+                        {
+                            CPLError(
+                                CE_Failure, CPLE_NotSupported,
+                                "NetCDF driver export of LCC-1SP with scale "
+                                "factor != 1.0 and no standard_parallel1 is "
+                                "not CF-1 (bug #3324).  Use the 2SP variant "
+                                "which is supported by CF.");
                             bWriteVal = true;
                         }
-                        /* else copy standard_parallel1 from latitude_of_origin, because scale_factor=1.0 */
-                        else {
-                            oValIter2 = oValMap.find( std::string(SRS_PP_LATITUDE_OF_ORIGIN) );
-                            if (oValIter2 != oValMap.end() ) {
-                                oOutList.push_back( std::make_pair( std::string(CF_PP_STD_PARALLEL_1),
-                                                                    oValIter2->second) );
+                        // Else copy standard_parallel1 from
+                        // latitude_of_origin, because scale_factor=1.0.
+                        else
+                        {
+                            oValIter2 = oValMap.find(
+                                std::string(SRS_PP_LATITUDE_OF_ORIGIN));
+                            if( oValIter2 != oValMap.end() )
+                            {
+                                oOutList.push_back(std::make_pair(
+                                    std::string(CF_PP_STD_PARALLEL_1),
+                                    oValIter2->second));
                             }
-                            else {
-                                CPLError( CE_Failure, CPLE_NotSupported,
-                                          "NetCDF driver export of LCC-1SP with no standard_parallel1 "
-                                          "and no latitude_of_origin is not supported (bug #3324).");
+                            else
+                            {
+                                CPLError(CE_Failure, CPLE_NotSupported,
+                                         "NetCDF driver export of LCC-1SP with "
+                                         "no standard_parallel1 "
+                                         "and no latitude_of_origin is not "
+                                         "supported (bug #3324).");
                             }
                         }
                     }
                 }
-                if ( bWriteVal )
-                    oOutList.push_back( std::make_pair( *posNCDFAtt, dfValue ) );
-
+                if( bWriteVal )
+                    oOutList.push_back(std::make_pair(*posNCDFAtt, dfValue));
+            }
+#ifdef NCDF_DEBUG
+            else
+            {
+                CPLDebug("GDAL_netCDF", "NOT FOUND!");
             }
-            // else printf("NOT FOUND!!!\n");
+#endif
         }
-
     }
-    else { /* generic mapping, loop over projected values */
-
-        for ( oValIter = oValMap.begin(); oValIter != oValMap.end(); oValIter++ ) {
-
+    else
+    {
+        // Generic mapping, loop over projected values.
+        for( oValIter = oValMap.begin(); oValIter != oValMap.end(); ++oValIter )
+        {
             posGDALAtt = &(oValIter->first);
             dfValue = oValIter->second;
 
-            oAttIter = oAttMap.find( *posGDALAtt );
+            oAttIter = oAttMap.find(*posGDALAtt);
 
-            if ( oAttIter != oAttMap.end() ) {
-                oOutList.push_back( std::make_pair( oAttIter->second, dfValue ) );
+            if( oAttIter != oAttMap.end() )
+            {
+                oOutList.push_back(std::make_pair(oAttIter->second, dfValue));
             }
             /* for SRS_PP_SCALE_FACTOR write 2 mappings */
-            else if (  EQUAL(posGDALAtt->c_str(), SRS_PP_SCALE_FACTOR) ) {
-                oOutList.push_back( std::make_pair( std::string(CF_PP_SCALE_FACTOR_MERIDIAN),
-                                                    dfValue ) );
-                oOutList.push_back( std::make_pair( std::string(CF_PP_SCALE_FACTOR_ORIGIN),
-                                                    dfValue ) );
+            else if( EQUAL(posGDALAtt->c_str(), SRS_PP_SCALE_FACTOR) )
+            {
+                oOutList.push_back(std::make_pair(
+                    std::string(CF_PP_SCALE_FACTOR_MERIDIAN), dfValue));
+                oOutList.push_back(std::make_pair(
+                    std::string(CF_PP_SCALE_FACTOR_ORIGIN), dfValue));
             }
             /* if not found insert the GDAL name */
-            else {
-                oOutList.push_back( std::make_pair( *posGDALAtt, dfValue ) );
+            else
+            {
+                oOutList.push_back(std::make_pair(*posGDALAtt, dfValue));
             }
         }
     }
 
     /* Write all the values that were found */
-    // std::vector< std::pair<std::string,double> >::reverse_iterator it;
-    // for (it = oOutList.rbegin();  it != oOutList.rend(); it++ ) {
-    std::vector< std::pair<std::string,double> >::iterator it;
+    // std::vector< std::pair<std::string, double> >::reverse_iterator it;
+    // for( it = oOutList.rbegin();  it != oOutList.rend(); it++ ) {
+    std::vector< std::pair<std::string, double> >::iterator it;
     double dfStdP[2];
     bool bFoundStdP1 = false;
     bool bFoundStdP2 = false;
-    for (it = oOutList.begin();  it != oOutList.end(); it++ ) {
+    for( it = oOutList.begin(); it != oOutList.end(); ++it )
+    {
         pszParamVal = (it->first).c_str();
         dfValue = it->second;
         /* Handle the STD_PARALLEL attrib */
-        if( EQUAL( pszParamVal, CF_PP_STD_PARALLEL_1 ) ) {
+        if( EQUAL(pszParamVal, CF_PP_STD_PARALLEL_1) )
+        {
             bFoundStdP1 = true;
             dfStdP[0] = dfValue;
         }
-        else if( EQUAL( pszParamVal, CF_PP_STD_PARALLEL_2 ) ) {
+        else if( EQUAL(pszParamVal, CF_PP_STD_PARALLEL_2) )
+        {
             bFoundStdP2 = true;
             dfStdP[1] = dfValue;
         }
-        else {
-            nc_put_att_double( fpImage, NCDFVarID, pszParamVal,
-                               NC_DOUBLE, 1,&dfValue );
+        else
+        {
+            nc_put_att_double(fpImage, NCDFVarID, pszParamVal,
+                              NC_DOUBLE, 1, &dfValue);
         }
     }
     /* Now write the STD_PARALLEL attrib */
-    if ( bFoundStdP1 ) {
+    if( bFoundStdP1 )
+    {
         /* one value or equal values */
-        if ( !bFoundStdP2 || dfStdP[0] ==  dfStdP[1] ) {
-            nc_put_att_double( fpImage, NCDFVarID, CF_PP_STD_PARALLEL,
-                               NC_DOUBLE, 1, &dfStdP[0] );
+        if( !bFoundStdP2 || dfStdP[0] == dfStdP[1] )
+        {
+            nc_put_att_double(fpImage, NCDFVarID, CF_PP_STD_PARALLEL,
+                              NC_DOUBLE, 1, &dfStdP[0]);
         }
-        else { /* two values */
-            nc_put_att_double( fpImage, NCDFVarID, CF_PP_STD_PARALLEL,
-                               NC_DOUBLE, 2, dfStdP );
+        else
+        {
+            // Two values.
+            nc_put_att_double(fpImage, NCDFVarID, CF_PP_STD_PARALLEL,
+                              NC_DOUBLE, 2, dfStdP);
         }
     }
 }
 
-static CPLErr NCDFSafeStrcat(char** ppszDest, const char* pszSrc, size_t* nDestSize)
+static CPLErr NCDFSafeStrcat(char **ppszDest, const char *pszSrc, size_t *nDestSize)
 {
     /* Reallocate the data string until the content fits */
-    while(*nDestSize < (strlen(*ppszDest) + strlen(pszSrc) + 1)) {
+    while( *nDestSize < (strlen(*ppszDest) + strlen(pszSrc) + 1) )
+    {
         (*nDestSize) *= 2;
-        *ppszDest = reinterpret_cast<char *>(
-            CPLRealloc( reinterpret_cast<void *>( *ppszDest ), *nDestSize) );
+        *ppszDest = static_cast<char *>(
+            CPLRealloc(reinterpret_cast<void *>(*ppszDest), *nDestSize));
 #ifdef NCDF_DEBUG
-        CPLDebug( "GDAL_netCDF", "NCDFSafeStrcat() resized str from %ld to %ld", (*nDestSize)/2, *nDestSize );
+        CPLDebug("GDAL_netCDF", "NCDFSafeStrcat() resized str from %ld to %ld",
+                 (*nDestSize) / 2, *nDestSize);
 #endif
     }
     strcat(*ppszDest, pszSrc);
@@ -7777,234 +8099,240 @@ static CPLErr NCDFSafeStrcat(char** ppszDest, const char* pszSrc, size_t* nDestS
 /* and if bSetPszValue=True sets pszValue with all attribute values */
 /* pszValue is the responsibility of the caller and must be freed */
 static CPLErr NCDFGetAttr1( int nCdfId, int nVarId, const char *pszAttrName,
-                     double *pdfValue, char **pszValue, int bSetPszValue )
+                            double *pdfValue, char **pszValue, int bSetPszValue )
 {
     nc_type nAttrType = NC_NAT;
-    size_t  nAttrLen = 0;
+    size_t nAttrLen = 0;
 
-    int status = nc_inq_att( nCdfId, nVarId, pszAttrName, &nAttrType, &nAttrLen);
-    if ( status != NC_NOERR )
+    int status = nc_inq_att(nCdfId, nVarId, pszAttrName, &nAttrType, &nAttrLen);
+    if( status != NC_NOERR )
         return CE_Failure;
 
 #ifdef NCDF_DEBUG
-    CPLDebug( "GDAL_netCDF", "NCDFGetAttr1(%s) len=%ld type=%d", pszAttrName, nAttrLen, nAttrType );
+    CPLDebug("GDAL_netCDF", "NCDFGetAttr1(%s) len=%ld type=%d", pszAttrName,
+             nAttrLen, nAttrType);
 #endif
 
     /* Allocate guaranteed minimum size (use 10 or 20 if not a string) */
-    size_t  nAttrValueSize = nAttrLen + 1;
-    if ( nAttrType != NC_CHAR && nAttrValueSize < 10 )
+    size_t nAttrValueSize = nAttrLen + 1;
+    if( nAttrType != NC_CHAR && nAttrValueSize < 10 )
         nAttrValueSize = 10;
-    if ( nAttrType == NC_DOUBLE && nAttrValueSize < 20 )
+    if( nAttrType == NC_DOUBLE && nAttrValueSize < 20 )
         nAttrValueSize = 20;
 #ifdef NETCDF_HAS_NC4
-    if ( nAttrType == NC_INT64 && nAttrValueSize < 20 )
+    if( nAttrType == NC_INT64 && nAttrValueSize < 20 )
         nAttrValueSize = 22;
 #endif
-    char *pszAttrValue = (char *) CPLCalloc( nAttrValueSize, sizeof( char ));
+    char *pszAttrValue =
+        static_cast<char *>(CPLCalloc(nAttrValueSize, sizeof(char)));
     *pszAttrValue = '\0';
 
-    if ( nAttrLen > 1 && nAttrType != NC_CHAR )
+    if( nAttrLen > 1 && nAttrType != NC_CHAR )
         NCDFSafeStrcat(&pszAttrValue, "{", &nAttrValueSize);
 
     double dfValue = 0.0;
     size_t m;
-    char szTemp[ 256 ];
+    char szTemp[256];
 
-    switch (nAttrType) {
-        case NC_CHAR:
-            nc_get_att_text( nCdfId, nVarId, pszAttrName, pszAttrValue );
-            pszAttrValue[nAttrLen]='\0';
-            dfValue = 0.0;
-            break;
-        case NC_BYTE:
+    switch( nAttrType )
+    {
+    case NC_CHAR:
+        nc_get_att_text(nCdfId, nVarId, pszAttrName, pszAttrValue);
+        pszAttrValue[nAttrLen] = '\0';
+        dfValue = 0.0;
+        break;
+    case NC_BYTE:
+    {
+        signed char *pscTemp = static_cast<signed char *>(
+            CPLCalloc(nAttrLen, sizeof(signed char)));
+        nc_get_att_schar(nCdfId, nVarId, pszAttrName, pscTemp);
+        dfValue = static_cast<double>(pscTemp[0]);
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            signed char *pscTemp
-                = reinterpret_cast<signed char *>(
-                    CPLCalloc( nAttrLen, sizeof( signed char ) ) );
-            nc_get_att_schar( nCdfId, nVarId, pszAttrName, pscTemp );
-            dfValue = static_cast<double>( pscTemp[0] );
-            for(m=0; m < nAttrLen-1; m++) {
-                snprintf( szTemp, sizeof(szTemp), "%d,", pscTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            snprintf( szTemp, sizeof(szTemp), "%d", pscTemp[m] );
+            snprintf(szTemp, sizeof(szTemp), "%d,", pscTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(pscTemp);
-            break;
         }
-        case NC_SHORT:
+        snprintf(szTemp, sizeof(szTemp), "%d", pscTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(pscTemp);
+        break;
+    }
+    case NC_SHORT:
+    {
+        short *psTemp =
+            static_cast<short *>(CPLCalloc(nAttrLen, sizeof(short)));
+        nc_get_att_short(nCdfId, nVarId, pszAttrName, psTemp);
+        dfValue = static_cast<double>(psTemp[0]);
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            short *psTemp
-                = reinterpret_cast<short *>(
-                    CPLCalloc( nAttrLen, sizeof( short ) ) );
-            nc_get_att_short( nCdfId, nVarId, pszAttrName, psTemp );
-            dfValue = static_cast<double>( psTemp[0] );
-            for(m=0; m < nAttrLen-1; m++) {
-                snprintf( szTemp, sizeof(szTemp), "%d,", psTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            snprintf( szTemp, sizeof(szTemp), "%d", psTemp[m] );
+            snprintf(szTemp, sizeof(szTemp), "%d,", psTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(psTemp);
-            break;
         }
-        case NC_INT:
+        snprintf(szTemp, sizeof(szTemp), "%d", psTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(psTemp);
+        break;
+    }
+    case NC_INT:
+    {
+        int *pnTemp = static_cast<int *>(CPLCalloc(nAttrLen, sizeof(int)));
+        nc_get_att_int(nCdfId, nVarId, pszAttrName, pnTemp);
+        dfValue = static_cast<double>(pnTemp[0]);
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            int *pnTemp
-                = static_cast<int *>( CPLCalloc( nAttrLen, sizeof( int ) ) );
-            nc_get_att_int( nCdfId, nVarId, pszAttrName, pnTemp );
-            dfValue = static_cast<double>( pnTemp[0] );
-            for(m=0; m < nAttrLen-1; m++) {
-                snprintf( szTemp, sizeof(szTemp), "%d,", pnTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            snprintf( szTemp, sizeof(szTemp), "%d", pnTemp[m] );
+            snprintf(szTemp, sizeof(szTemp), "%d,", pnTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(pnTemp);
-            break;
         }
-        case NC_FLOAT:
+        snprintf(szTemp, sizeof(szTemp), "%d", pnTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(pnTemp);
+        break;
+    }
+    case NC_FLOAT:
+    {
+        float *pfTemp =
+            static_cast<float *>(CPLCalloc(nAttrLen, sizeof(float)));
+        nc_get_att_float(nCdfId, nVarId, pszAttrName, pfTemp);
+        dfValue = static_cast<double>(pfTemp[0]);
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            float *pfTemp
-                = reinterpret_cast<float *>(
-                    CPLCalloc( nAttrLen, sizeof( float ) ) );
-            nc_get_att_float( nCdfId, nVarId, pszAttrName, pfTemp );
-            dfValue = static_cast<double>( pfTemp[0] );
-            for(m=0; m < nAttrLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%.8g,", pfTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%.8g", pfTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), "%.8g,", pfTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(pfTemp);
-            break;
         }
-        case NC_DOUBLE:
+        CPLsnprintf(szTemp, sizeof(szTemp), "%.8g", pfTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(pfTemp);
+        break;
+    }
+    case NC_DOUBLE:
+    {
+        double *pdfTemp =
+            static_cast<double *>(CPLCalloc(nAttrLen, sizeof(double)));
+        nc_get_att_double(nCdfId, nVarId, pszAttrName, pdfTemp);
+        dfValue = pdfTemp[0];
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            double *pdfTemp
-                = reinterpret_cast<double *>(
-                    CPLCalloc( nAttrLen, sizeof(double) ) );
-            nc_get_att_double( nCdfId, nVarId, pszAttrName, pdfTemp );
-            dfValue = pdfTemp[0];
-            for(m=0; m < nAttrLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%.16g,", pdfTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%.16g", pdfTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), "%.16g,", pdfTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(pdfTemp);
-            break;
         }
+        CPLsnprintf(szTemp, sizeof(szTemp), "%.16g", pdfTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(pdfTemp);
+        break;
+    }
 #ifdef NETCDF_HAS_NC4
-        case NC_STRING:
+    case NC_STRING:
+    {
+        char **ppszTemp =
+            static_cast<char **>(CPLCalloc(nAttrLen, sizeof(char *)));
+        nc_get_att_string(nCdfId, nVarId, pszAttrName, ppszTemp);
+        dfValue = 0.0;
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            char **ppszTemp
-                = reinterpret_cast<char **>(
-                    CPLCalloc( nAttrLen, sizeof( char * ) ) );
-            nc_get_att_string( nCdfId, nVarId, pszAttrName, ppszTemp );
-            dfValue = 0.0;
-            for(m=0; m < nAttrLen-1; m++) {
-                NCDFSafeStrcat(&pszAttrValue, ppszTemp[m], &nAttrValueSize);
-                NCDFSafeStrcat(&pszAttrValue, ",", &nAttrValueSize);
-            }
             NCDFSafeStrcat(&pszAttrValue, ppszTemp[m], &nAttrValueSize);
-            nc_free_string(nAttrLen, ppszTemp);
-            CPLFree(ppszTemp);
-            break;
+            NCDFSafeStrcat(&pszAttrValue, ",", &nAttrValueSize);
         }
-        case NC_UBYTE:
+        NCDFSafeStrcat(&pszAttrValue, ppszTemp[m], &nAttrValueSize);
+        nc_free_string(nAttrLen, ppszTemp);
+        CPLFree(ppszTemp);
+        break;
+    }
+    case NC_UBYTE:
+    {
+        unsigned char *pucTemp = static_cast<unsigned char *>(
+            CPLCalloc(nAttrLen, sizeof(unsigned char)));
+        nc_get_att_uchar(nCdfId, nVarId, pszAttrName, pucTemp);
+        dfValue = static_cast<double>(pucTemp[0]);
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            unsigned char *pucTemp
-                = reinterpret_cast<unsigned char *>(
-                    CPLCalloc( nAttrLen, sizeof( unsigned char ) ) );
-            nc_get_att_uchar( nCdfId, nVarId, pszAttrName, pucTemp );
-            dfValue = static_cast<double>( pucTemp[0] );
-            for(m=0; m < nAttrLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", pucTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%u", pucTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), "%u,", pucTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(pucTemp);
-            break;
         }
-        case NC_USHORT:
+        CPLsnprintf(szTemp, sizeof(szTemp), "%u", pucTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(pucTemp);
+        break;
+    }
+    case NC_USHORT:
+    {
+        unsigned short *pusTemp;
+        pusTemp = static_cast<unsigned short *>(
+            CPLCalloc(nAttrLen, sizeof(unsigned short)));
+        nc_get_att_ushort(nCdfId, nVarId, pszAttrName, pusTemp);
+        dfValue = static_cast<double>(pusTemp[0]);
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            unsigned short *pusTemp;
-            pusTemp = reinterpret_cast<unsigned short *>(
-                    CPLCalloc( nAttrLen, sizeof( unsigned short ) ) );
-            nc_get_att_ushort( nCdfId, nVarId, pszAttrName, pusTemp );
-            dfValue = static_cast<double>(pusTemp[0]);
-            for(m=0; m < nAttrLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", pusTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%u", pusTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), "%u,", pusTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(pusTemp);
-            break;
         }
-        case NC_UINT:
+        CPLsnprintf(szTemp, sizeof(szTemp), "%u", pusTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(pusTemp);
+        break;
+    }
+    case NC_UINT:
+    {
+        unsigned int *punTemp =
+            static_cast<unsigned int *>(CPLCalloc(nAttrLen, sizeof(int)));
+        nc_get_att_uint(nCdfId, nVarId, pszAttrName, punTemp);
+        dfValue = static_cast<double>(punTemp[0]);
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            unsigned int *punTemp
-                = static_cast<unsigned int *>( CPLCalloc( nAttrLen, sizeof( int ) ) );
-            nc_get_att_uint( nCdfId, nVarId, pszAttrName, punTemp );
-            dfValue = static_cast<double>( punTemp[0] );
-            for(m=0; m < nAttrLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", punTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%u", punTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), "%u,", punTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(punTemp);
-            break;
         }
-        case NC_INT64:
+        CPLsnprintf(szTemp, sizeof(szTemp), "%u", punTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(punTemp);
+        break;
+    }
+    case NC_INT64:
+    {
+        GIntBig *panTemp =
+            static_cast<GIntBig *>(CPLCalloc(nAttrLen, sizeof(GIntBig)));
+        nc_get_att_longlong(nCdfId, nVarId, pszAttrName, panTemp);
+        dfValue = static_cast<double>(panTemp[0]);
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            GIntBig *panTemp
-                = reinterpret_cast<GIntBig *>(
-                    CPLCalloc( nAttrLen, sizeof( GIntBig ) ) );
-            nc_get_att_longlong( nCdfId, nVarId, pszAttrName, panTemp );
-            dfValue = static_cast<double>( panTemp[0] );
-            for(m=0; m < nAttrLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), CPL_FRMT_GIB ",", panTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), CPL_FRMT_GIB, panTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), CPL_FRMT_GIB ",", panTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(panTemp);
-            break;
         }
-        case NC_UINT64:
+        CPLsnprintf(szTemp, sizeof(szTemp), CPL_FRMT_GIB, panTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(panTemp);
+        break;
+    }
+    case NC_UINT64:
+    {
+        GUIntBig *panTemp =
+            static_cast<GUIntBig *>(CPLCalloc(nAttrLen, sizeof(GUIntBig)));
+        nc_get_att_ulonglong(nCdfId, nVarId, pszAttrName, panTemp);
+        dfValue = static_cast<double>(panTemp[0]);
+        for( m = 0; m < nAttrLen - 1; m++ )
         {
-            GUIntBig *panTemp
-                = reinterpret_cast<GUIntBig *>(
-                    CPLCalloc( nAttrLen, sizeof( GUIntBig ) ) );
-            nc_get_att_ulonglong( nCdfId, nVarId, pszAttrName, panTemp );
-            dfValue = static_cast<double>( panTemp[0] );
-            for(m=0; m < nAttrLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), CPL_FRMT_GUIB ",", panTemp[m] );
-                NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), CPL_FRMT_GUIB, panTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), CPL_FRMT_GUIB ",", panTemp[m]);
             NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
-            CPLFree(panTemp);
-            break;
         }
+        CPLsnprintf(szTemp, sizeof(szTemp), CPL_FRMT_GUIB, panTemp[m]);
+        NCDFSafeStrcat(&pszAttrValue, szTemp, &nAttrValueSize);
+        CPLFree(panTemp);
+        break;
+    }
 #endif
-        default:
-            CPLDebug( "GDAL_netCDF", "NCDFGetAttr unsupported type %d for attribute %s",
-                      nAttrType,pszAttrName);
-            break;
+    default:
+        CPLDebug("GDAL_netCDF",
+                 "NCDFGetAttr unsupported type %d for attribute %s",
+                  nAttrType, pszAttrName);
+        break;
     }
 
-    if ( nAttrLen > 1  && nAttrType!= NC_CHAR )
+    if( nAttrLen > 1 && nAttrType!= NC_CHAR )
         NCDFSafeStrcat(&pszAttrValue, "}", &nAttrValueSize);
 
     /* set return values */
-    if ( bSetPszValue ) *pszValue = pszAttrValue;
-    else CPLFree ( pszAttrValue );
-    if ( pdfValue ) *pdfValue = dfValue;
+    if( bSetPszValue ) *pszValue = pszAttrValue;
+    else CPLFree(pszAttrValue);
+    if( pdfValue ) *pdfValue = dfValue;
 
     return CE_None;
 }
@@ -8013,29 +8341,27 @@ static CPLErr NCDFGetAttr1( int nCdfId, int nVarId, const char *pszAttrName,
 CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName,
                     double *pdfValue )
 {
-    return NCDFGetAttr1( nCdfId, nVarId, pszAttrName, pdfValue, NULL, false );
+    return NCDFGetAttr1(nCdfId, nVarId, pszAttrName, pdfValue, NULL, false);
 }
 
-
 /* pszValue is the responsibility of the caller and must be freed */
 CPLErr NCDFGetAttr( int nCdfId, int nVarId, const char *pszAttrName,
                     char **pszValue )
 {
-    return NCDFGetAttr1( nCdfId, nVarId, pszAttrName, NULL, pszValue, true );
+    return NCDFGetAttr1(nCdfId, nVarId, pszAttrName, NULL, pszValue, true);
 }
 
-
 /* By default write NC_CHAR, but detect for int/float/double and */
 /* NC4 string arrays */
-static CPLErr NCDFPutAttr( int nCdfId, int nVarId,
-                 const char *pszAttrName, const char *pszValue )
+static CPLErr NCDFPutAttr( int nCdfId, int nVarId, const char *pszAttrName,
+                           const char *pszValue )
 {
-    int     status = 0;
-    char    *pszTemp = NULL;
+    int status = 0;
+    char *pszTemp = NULL;
 
     /* get the attribute values as tokens */
-    char **papszValues = NCDFTokenizeArray( pszValue );
-    if ( papszValues == NULL )
+    char **papszValues = NCDFTokenizeArray(pszValue);
+    if( papszValues == NULL )
         return CE_Failure;
 
     size_t nAttrLen = CSLCount(papszValues);
@@ -8043,51 +8369,58 @@ static CPLErr NCDFPutAttr( int nCdfId, int nVarId,
     /* first detect type */
     nc_type nAttrType = NC_CHAR;
     nc_type nTmpAttrType = NC_CHAR;
-    for ( size_t i=0; i<nAttrLen; i++ ) {
+    for( size_t i = 0; i < nAttrLen; i++ )
+    {
         nTmpAttrType = NC_CHAR;
         bool bFoundType = false;
         errno = 0;
-        int nValue = static_cast<int>(strtol( papszValues[i], &pszTemp, 10 ));
+        int nValue = static_cast<int>(strtol(papszValues[i], &pszTemp, 10));
         /* test for int */
         /* TODO test for Byte and short - can this be done safely? */
-        if ( (errno == 0) && (papszValues[i] != pszTemp) && (*pszTemp == 0) ) {
-            char    szTemp[ 256 ];
-            CPLsnprintf( szTemp, sizeof(szTemp), "%d", nValue );
-            if ( EQUAL( szTemp, papszValues[i] ) ) {
+        if( errno == 0 && papszValues[i] != pszTemp && *pszTemp == 0 )
+        {
+            char szTemp[256];
+            CPLsnprintf(szTemp, sizeof(szTemp), "%d", nValue);
+            if( EQUAL(szTemp, papszValues[i]) )
+            {
                 bFoundType = true;
                 nTmpAttrType = NC_INT;
             }
 #ifdef NETCDF_HAS_NC4
-            else {
+            else
+            {
                 unsigned int unValue = static_cast<unsigned int>(
-                    strtoul( papszValues[i], &pszTemp, 10 ));
-                CPLsnprintf( szTemp, sizeof(szTemp), "%u", unValue );
-                if ( EQUAL( szTemp, papszValues[i] ) ) {
+                    strtoul(papszValues[i], &pszTemp, 10));
+                CPLsnprintf(szTemp, sizeof(szTemp), "%u", unValue);
+                if( EQUAL(szTemp, papszValues[i]) )
+                {
                     bFoundType = true;
                     nTmpAttrType = NC_UINT;
                 }
             }
 #endif
         }
-        if ( ! bFoundType ) {
+        if( !bFoundType )
+        {
             /* test for double */
             errno = 0;
-            double dfValue = CPLStrtod( papszValues[i], &pszTemp );
-            if ( (errno == 0) && (papszValues[i] != pszTemp) && (*pszTemp == 0) ) {
-                /* test for float instead of double */
-                /* strtof() is C89, which is not available in MSVC */
-                /* see if we loose precision if we cast to float and write to char* */
+            double dfValue = CPLStrtod(papszValues[i], &pszTemp);
+            if( (errno == 0) && (papszValues[i] != pszTemp) && (*pszTemp == 0) )
+            {
+                // Test for float instead of double.
+                // strtof() is C89, which is not available in MSVC.
+                // See if we loose precision if we cast to float and write to char*.
                 float fValue = float(dfValue);
-                char    szTemp[ 256 ];
-                CPLsnprintf( szTemp, sizeof(szTemp), "%.8g", fValue );
-                if ( EQUAL( szTemp, papszValues[i] ) )
+                char szTemp[256];
+                CPLsnprintf(szTemp, sizeof(szTemp), "%.8g", fValue);
+                if( EQUAL(szTemp, papszValues[i]) )
                     nTmpAttrType = NC_FLOAT;
                 else
                     nTmpAttrType = NC_DOUBLE;
             }
         }
-        if ( (nTmpAttrType <= NC_DOUBLE && nAttrType <= NC_DOUBLE
-              && nTmpAttrType > nAttrType)
+        if( (nTmpAttrType <= NC_DOUBLE && nAttrType <= NC_DOUBLE
+             && nTmpAttrType > nAttrType)
 #ifdef NETCDF_HAS_NC4
              || (nTmpAttrType == NC_UINT && nAttrType < NC_FLOAT)
              || (nTmpAttrType >= NC_FLOAT && nAttrType == NC_UINT)
@@ -8097,110 +8430,120 @@ static CPLErr NCDFPutAttr( int nCdfId, int nVarId,
     }
 
     /* now write the data */
-    if ( nAttrType == NC_CHAR ) {
+    if( nAttrType == NC_CHAR )
+    {
 #ifdef NETCDF_HAS_NC4
         int nTmpFormat = 0;
-        if ( nAttrLen > 1 ) {
-            status = nc_inq_format( nCdfId, &nTmpFormat );
+        if( nAttrLen > 1 )
+        {
+            status = nc_inq_format(nCdfId, &nTmpFormat);
             NCDF_ERR(status);
         }
-        if ( nAttrLen > 1 && nTmpFormat == NCDF_FORMAT_NC4 )
-            status = nc_put_att_string( nCdfId, nVarId, pszAttrName,
-                                        nAttrLen, (const char **) papszValues );
+        if( nAttrLen > 1 && nTmpFormat == NCDF_FORMAT_NC4 )
+            status = nc_put_att_string(nCdfId, nVarId, pszAttrName, nAttrLen,
+                                       (const char **)papszValues);
         else
 #endif
-            status = nc_put_att_text( nCdfId, nVarId, pszAttrName,
-                                      strlen( pszValue ), pszValue );
+            status = nc_put_att_text(nCdfId, nVarId, pszAttrName,
+                                     strlen(pszValue), pszValue);
         NCDF_ERR(status);
     }
-    else {
-        switch( nAttrType ) {
-            case  NC_INT:
+    else
+    {
+        switch( nAttrType )
+        {
+        case NC_INT:
+        {
+            int *pnTemp =
+                static_cast<int *>(CPLCalloc(nAttrLen, sizeof(int)));
+            for( size_t i = 0; i < nAttrLen; i++ )
             {
-                int *pnTemp = reinterpret_cast<int *> (
-                    CPLCalloc( nAttrLen, sizeof( int ) ) );
-                for( size_t i=0; i < nAttrLen; i++) {
-                    pnTemp[i] = static_cast<int>(strtol( papszValues[i], &pszTemp, 10 ));
-                }
-                status = nc_put_att_int( nCdfId, nVarId, pszAttrName,
-                                         NC_INT, nAttrLen, pnTemp );
-                NCDF_ERR(status);
-                CPLFree(pnTemp);
-                break;
+                pnTemp[i] =
+                    static_cast<int>(strtol(papszValues[i], &pszTemp, 10));
             }
+            status = nc_put_att_int(nCdfId, nVarId, pszAttrName, NC_INT,
+                                    nAttrLen, pnTemp);
+            NCDF_ERR(status);
+            CPLFree(pnTemp);
+            break;
+        }
 #ifdef NETCDF_HAS_NC4
-            case  NC_UINT:
+        case NC_UINT:
+        {
+            unsigned int *punTemp = static_cast<unsigned int *>(
+                CPLCalloc(nAttrLen, sizeof(unsigned int)));
+            for( size_t i = 0; i < nAttrLen; i++ )
             {
-                unsigned int *punTemp = reinterpret_cast<unsigned int *> (
-                    CPLCalloc( nAttrLen, sizeof( unsigned int ) ) );
-                for( size_t i=0; i < nAttrLen; i++) {
-                    punTemp[i] = static_cast<unsigned int>(strtol( papszValues[i], &pszTemp, 10 ));
-                }
-                status = nc_put_att_uint( nCdfId, nVarId, pszAttrName,
-                                          NC_UINT, nAttrLen, punTemp );
-                NCDF_ERR(status);
-                CPLFree(punTemp);
-                break;
+                punTemp[i] = static_cast<unsigned int>(
+                    strtol(papszValues[i], &pszTemp, 10));
             }
+            status = nc_put_att_uint(nCdfId, nVarId, pszAttrName, NC_UINT,
+                                     nAttrLen, punTemp);
+            NCDF_ERR(status);
+            CPLFree(punTemp);
+            break;
+        }
 #endif
-            case  NC_FLOAT:
+        case NC_FLOAT:
+        {
+            float *pfTemp =
+                static_cast<float *>(CPLCalloc(nAttrLen, sizeof(float)));
+            for( size_t i = 0; i < nAttrLen; i++ )
             {
-                float *pfTemp = reinterpret_cast<float *> (
-                    CPLCalloc( nAttrLen, sizeof( float ) ) );
-                for( size_t i=0; i < nAttrLen; i++) {
-                    pfTemp[i] = (float)CPLStrtod( papszValues[i], &pszTemp );
-                }
-                status = nc_put_att_float( nCdfId, nVarId, pszAttrName,
-                                           NC_FLOAT, nAttrLen, pfTemp );
-                NCDF_ERR(status);
-                CPLFree(pfTemp);
-                break;
+                pfTemp[i] = (float)CPLStrtod(papszValues[i], &pszTemp);
             }
-            case  NC_DOUBLE:
+            status = nc_put_att_float(nCdfId, nVarId, pszAttrName, NC_FLOAT,
+                                      nAttrLen, pfTemp);
+            NCDF_ERR(status);
+            CPLFree(pfTemp);
+            break;
+        }
+        case NC_DOUBLE:
+        {
+            double *pdfTemp =
+                static_cast<double *>(CPLCalloc(nAttrLen, sizeof(double)));
+            for( size_t i = 0; i < nAttrLen; i++ )
             {
-                double *pdfTemp = reinterpret_cast<double *> (
-                    CPLCalloc( nAttrLen, sizeof( double ) ) );
-                for(size_t i=0; i < nAttrLen; i++) {
-                    pdfTemp[i] = CPLStrtod( papszValues[i], &pszTemp );
-                }
-                status = nc_put_att_double( nCdfId, nVarId, pszAttrName,
-                                            NC_DOUBLE, nAttrLen, pdfTemp );
-                NCDF_ERR(status);
-                CPLFree(pdfTemp);
-                break;
+                pdfTemp[i] = CPLStrtod(papszValues[i], &pszTemp);
             }
+            status = nc_put_att_double(nCdfId, nVarId, pszAttrName, NC_DOUBLE,
+                                       nAttrLen, pdfTemp);
+            NCDF_ERR(status);
+            CPLFree(pdfTemp);
+            break;
+        }
         default:
-            if ( papszValues ) CSLDestroy( papszValues );
+            if( papszValues ) CSLDestroy(papszValues);
             return CE_Failure;
             break;
         }
     }
 
-    if ( papszValues ) CSLDestroy( papszValues );
+    if( papszValues ) CSLDestroy(papszValues);
 
-     return CE_None;
+    return CE_None;
 }
 
 static CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue )
 {
     /* get var information */
     int nVarDimId = -1;
-    int status = nc_inq_varndims( nCdfId, nVarId, &nVarDimId );
-    if ( status != NC_NOERR || nVarDimId != 1)
+    int status = nc_inq_varndims(nCdfId, nVarId, &nVarDimId);
+    if( status != NC_NOERR || nVarDimId != 1 )
         return CE_Failure;
 
-    status = nc_inq_vardimid( nCdfId, nVarId, &nVarDimId );
-    if ( status != NC_NOERR )
+    status = nc_inq_vardimid(nCdfId, nVarId, &nVarDimId);
+    if( status != NC_NOERR )
         return CE_Failure;
 
     nc_type nVarType = NC_NAT;
-    status = nc_inq_vartype( nCdfId, nVarId, &nVarType );
-    if ( status != NC_NOERR )
+    status = nc_inq_vartype(nCdfId, nVarId, &nVarType);
+    if( status != NC_NOERR )
         return CE_Failure;
 
     size_t nVarLen = 0;
-    status = nc_inq_dimlen( nCdfId, nVarDimId, &nVarLen );
-    if ( status != NC_NOERR )
+    status = nc_inq_dimlen(nCdfId, nVarDimId, &nVarLen);
+    if( status != NC_NOERR )
         return CE_Failure;
 
     size_t start[1] = {0};
@@ -8208,11 +8551,11 @@ static CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue )
 
     /* Allocate guaranteed minimum size */
     size_t nVarValueSize = NCDF_MAX_STR_LEN;
-    char *pszVarValue = reinterpret_cast<char *> (
-        CPLCalloc( nVarValueSize, sizeof( char ) ) );
+    char *pszVarValue =
+        static_cast<char *>(CPLCalloc(nVarValueSize, sizeof(char)));
     *pszVarValue = '\0';
 
-    if ( nVarLen == 0 )
+    if( nVarLen == 0 )
     {
         /* set return values */
         *pszValue = pszVarValue;
@@ -8220,168 +8563,177 @@ static CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue )
         return CE_None;
     }
 
-    if ( nVarLen > 1 && nVarType != NC_CHAR )
+    if( nVarLen > 1 && nVarType != NC_CHAR )
         NCDFSafeStrcat(&pszVarValue, "{", &nVarValueSize);
 
-    switch (nVarType) {
-        case NC_CHAR:
-            nc_get_vara_text( nCdfId, nVarId, start, count, pszVarValue );
-            pszVarValue[nVarLen]='\0';
-            break;
-        case NC_BYTE:
+    switch (nVarType)
+    {
+    case NC_CHAR:
+        nc_get_vara_text(nCdfId, nVarId, start, count, pszVarValue);
+        pszVarValue[nVarLen] = '\0';
+        break;
+    case NC_BYTE:
+    {
+        signed char *pscTemp = static_cast<signed char *>(
+            CPLCalloc(nVarLen, sizeof(signed char)));
+        nc_get_vara_schar(nCdfId, nVarId, start, count, pscTemp);
+        char szTemp[256];
+        size_t m = 0;
+        for( ; m < nVarLen - 1; m++ )
         {
-            signed char *pscTemp = reinterpret_cast<signed char *> (
-                CPLCalloc( nVarLen, sizeof( signed char ) ) );
-            nc_get_vara_schar( nCdfId, nVarId, start, count, pscTemp );
-            char szTemp[ 256 ];
-            size_t m = 0;
-            for( ; m < nVarLen-1; m++) {
-                snprintf( szTemp, sizeof(szTemp), "%d,", pscTemp[m] );
-                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            }
-            snprintf( szTemp, sizeof(szTemp), "%d", pscTemp[m] );
+            snprintf(szTemp, sizeof(szTemp), "%d,", pscTemp[m]);
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            CPLFree(pscTemp);
-            break;
         }
-        case NC_SHORT:
+        snprintf(szTemp, sizeof(szTemp), "%d", pscTemp[m]);
+        NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+        CPLFree(pscTemp);
+        break;
+    }
+    case NC_SHORT:
+    {
+        short *psTemp = static_cast<short *>(CPLCalloc(nVarLen, sizeof(short)));
+        nc_get_vara_short(nCdfId, nVarId, start, count, psTemp);
+        char szTemp[256];
+        size_t m = 0;
+        for( ; m < nVarLen - 1; m++ )
         {
-            short *psTemp = reinterpret_cast<short *> (
-                CPLCalloc( nVarLen, sizeof( short ) ) );
-            nc_get_vara_short( nCdfId, nVarId, start, count, psTemp );
-            char szTemp[ 256 ];
-            size_t m = 0;
-            for( ; m < nVarLen-1; m++) {
-                snprintf( szTemp, sizeof(szTemp), "%d,", psTemp[m] );
-                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            }
-            snprintf( szTemp, sizeof(szTemp),  "%d", psTemp[m] );
+            snprintf(szTemp, sizeof(szTemp), "%d,", psTemp[m]);
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            CPLFree(psTemp);
-            break;
         }
-        case NC_INT:
+        snprintf(szTemp, sizeof(szTemp), "%d", psTemp[m]);
+        NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+        CPLFree(psTemp);
+        break;
+    }
+    case NC_INT:
+    {
+        int *pnTemp = static_cast<int *>(CPLCalloc(nVarLen, sizeof(int)));
+        nc_get_vara_int(nCdfId, nVarId, start, count, pnTemp);
+        char szTemp[256];
+        size_t m = 0;
+        for(; m < nVarLen - 1; m++)
         {
-            int *pnTemp = reinterpret_cast<int *> (
-                CPLCalloc( nVarLen, sizeof( int ) ) );
-            nc_get_vara_int( nCdfId, nVarId, start, count, pnTemp );
-            char szTemp[ 256 ];
-            size_t m = 0;
-            for( ; m < nVarLen-1; m++) {
-                snprintf( szTemp, sizeof(szTemp), "%d,", pnTemp[m] );
-                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            }
-            snprintf( szTemp, sizeof(szTemp), "%d", pnTemp[m] );
+            snprintf(szTemp, sizeof(szTemp), "%d,", pnTemp[m]);
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            CPLFree(pnTemp);
-            break;
         }
-        case NC_FLOAT:
+        snprintf(szTemp, sizeof(szTemp), "%d", pnTemp[m]);
+        NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+        CPLFree(pnTemp);
+        break;
+    }
+    case NC_FLOAT:
+    {
+        float *pfTemp = static_cast<float *>(CPLCalloc(nVarLen, sizeof(float)));
+        nc_get_vara_float(nCdfId, nVarId, start, count, pfTemp);
+        char szTemp[256];
+        size_t m = 0;
+        for( ; m < nVarLen - 1; m++ )
         {
-            float *pfTemp = reinterpret_cast<float *> (
-                CPLCalloc( nVarLen, sizeof( float ) ) );
-            nc_get_vara_float( nCdfId, nVarId, start, count, pfTemp );
-            char szTemp[ 256 ];
-            size_t m = 0;
-            for( ; m < nVarLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%.8g,", pfTemp[m] );
-                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%.8g", pfTemp[m] );
-            NCDFSafeStrcat(&pszVarValue,szTemp, &nVarValueSize);
-            CPLFree(pfTemp);
-            break;
+            CPLsnprintf(szTemp, sizeof(szTemp), "%.8g,", pfTemp[m]);
+            NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
         }
-        case NC_DOUBLE:
+        CPLsnprintf(szTemp, sizeof(szTemp), "%.8g", pfTemp[m]);
+        NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+        CPLFree(pfTemp);
+        break;
+    }
+    case NC_DOUBLE:
+    {
+        double *pdfTemp =
+            static_cast<double *>(CPLCalloc(nVarLen, sizeof(double)));
+        nc_get_vara_double(nCdfId, nVarId, start, count, pdfTemp);
+        char szTemp[256];
+        size_t m = 0;
+        for( ; m < nVarLen - 1; m++ )
         {
-            double *pdfTemp = reinterpret_cast<double *> (
-                CPLCalloc( nVarLen, sizeof(double) ) );
-            nc_get_vara_double( nCdfId, nVarId, start, count, pdfTemp );
-            char szTemp[ 256 ];
-            size_t m = 0;
-            for( ; m < nVarLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%.16g,", pdfTemp[m] );
-                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%.16g", pdfTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), "%.16g,", pdfTemp[m]);
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            CPLFree(pdfTemp);
-            break;
         }
+        CPLsnprintf(szTemp, sizeof(szTemp), "%.16g", pdfTemp[m]);
+        NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+        CPLFree(pdfTemp);
+        break;
+    }
 #ifdef NETCDF_HAS_NC4
-        case NC_STRING:
+    case NC_STRING:
+    {
+        char **ppszTemp =
+            static_cast<char **>(CPLCalloc(nVarLen, sizeof(char *)));
+        nc_get_vara_string(nCdfId, nVarId, start, count, ppszTemp);
+        size_t m = 0;
+        for( ; m < nVarLen - 1; m++ )
         {
-            char **ppszTemp = reinterpret_cast<char **> (
-                CPLCalloc( nVarLen, sizeof( char * ) ) );
-            nc_get_vara_string( nCdfId, nVarId, start, count, ppszTemp );
-            size_t m = 0;
-            for( ; m < nVarLen-1; m++) {
-                NCDFSafeStrcat(&pszVarValue, ppszTemp[m], &nVarValueSize);
-                NCDFSafeStrcat(&pszVarValue, ",", &nVarValueSize);
-            }
             NCDFSafeStrcat(&pszVarValue, ppszTemp[m], &nVarValueSize);
-            nc_free_string(nVarLen, ppszTemp);
-            CPLFree(ppszTemp);
-            break;
+            NCDFSafeStrcat(&pszVarValue, ",", &nVarValueSize);
         }
-        case NC_UBYTE:
+        NCDFSafeStrcat(&pszVarValue, ppszTemp[m], &nVarValueSize);
+        nc_free_string(nVarLen, ppszTemp);
+        CPLFree(ppszTemp);
+        break;
+    }
+    case NC_UBYTE:
+    {
+        unsigned char *pucTemp;
+        pucTemp = static_cast<unsigned char *>(
+            CPLCalloc(nVarLen, sizeof(unsigned char)));
+        nc_get_vara_uchar(nCdfId, nVarId, start, count, pucTemp);
+        char szTemp[256];
+        size_t m = 0;
+        for( ; m < nVarLen - 1; m++ )
         {
-            unsigned char *pucTemp;
-            pucTemp = (unsigned char *) CPLCalloc( nVarLen, sizeof( unsigned char ) );
-            nc_get_vara_uchar( nCdfId, nVarId, start, count, pucTemp );
-            char szTemp[ 256 ];
-            size_t m = 0;
-            for( ; m < nVarLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", pucTemp[m] );
-                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%u", pucTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), "%u,", pucTemp[m]);
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            CPLFree(pucTemp);
-            break;
         }
-        case NC_USHORT:
+        CPLsnprintf(szTemp, sizeof(szTemp), "%u", pucTemp[m]);
+        NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+        CPLFree(pucTemp);
+        break;
+    }
+    case NC_USHORT:
+    {
+        unsigned short *pusTemp;
+        pusTemp = static_cast<unsigned short *>(
+            CPLCalloc(nVarLen, sizeof(unsigned short)));
+        nc_get_vara_ushort(nCdfId, nVarId, start, count, pusTemp);
+        char szTemp[256];
+        size_t m = 0;
+        for( ; m < nVarLen - 1; m++ )
         {
-            unsigned short *pusTemp;
-            pusTemp = (unsigned short *) CPLCalloc( nVarLen, sizeof( unsigned short ) );
-            nc_get_vara_ushort( nCdfId, nVarId, start, count, pusTemp );
-            char szTemp[ 256 ];
-            size_t m = 0;
-            for( ; m < nVarLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", pusTemp[m] );
-                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%u", pusTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), "%u,", pusTemp[m]);
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            CPLFree(pusTemp);
-            break;
         }
-        case NC_UINT:
+        CPLsnprintf(szTemp, sizeof(szTemp), "%u", pusTemp[m]);
+        NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+        CPLFree(pusTemp);
+        break;
+    }
+    case NC_UINT:
+    {
+        unsigned int *punTemp;
+        punTemp = static_cast<unsigned int *>(
+            CPLCalloc(nVarLen, sizeof(unsigned int)));
+        nc_get_vara_uint(nCdfId, nVarId, start, count, punTemp);
+        char szTemp[256];
+        size_t m = 0;
+        for( ; m < nVarLen - 1; m++ )
         {
-            unsigned int *punTemp;
-            punTemp = (unsigned int *) CPLCalloc( nVarLen, sizeof( unsigned int ) );
-            nc_get_vara_uint( nCdfId, nVarId, start, count, punTemp );
-            char szTemp[ 256 ];
-            size_t m = 0;
-            for( ; m < nVarLen-1; m++) {
-                CPLsnprintf( szTemp, sizeof(szTemp), "%u,", punTemp[m] );
-                NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            }
-            CPLsnprintf( szTemp, sizeof(szTemp), "%u", punTemp[m] );
+            CPLsnprintf(szTemp, sizeof(szTemp), "%u,", punTemp[m]);
             NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
-            CPLFree(punTemp);
-            break;
         }
+        CPLsnprintf(szTemp, sizeof(szTemp), "%u", punTemp[m]);
+        NCDFSafeStrcat(&pszVarValue, szTemp, &nVarValueSize);
+        CPLFree(punTemp);
+        break;
+    }
 #endif
-        default:
-            CPLDebug( "GDAL_netCDF", "NCDFGetVar1D unsupported type %d",
-                      nVarType );
-            CPLFree( pszVarValue );
-            pszVarValue = NULL;
-            break;
+    default:
+        CPLDebug("GDAL_netCDF", "NCDFGetVar1D unsupported type %d", nVarType);
+        CPLFree(pszVarValue);
+        pszVarValue = NULL;
+        break;
     }
 
-    if ( nVarLen > 1  && nVarType!= NC_CHAR )
+    if( nVarLen > 1 && nVarType != NC_CHAR )
         NCDFSafeStrcat(&pszVarValue, "}", &nVarValueSize);
 
     /* set return values */
@@ -8392,173 +8744,192 @@ static CPLErr NCDFGet1DVar( int nCdfId, int nVarId, char **pszValue )
 
 static CPLErr NCDFPut1DVar( int nCdfId, int nVarId, const char *pszValue )
 {
-    if ( EQUAL( pszValue, "" ) )
+    if( EQUAL(pszValue, "") )
         return CE_Failure;
 
     /* get var information */
     int nVarDimId = -1;
-    int status = nc_inq_varndims( nCdfId, nVarId, &nVarDimId );
-    if ( status != NC_NOERR || nVarDimId != 1)
+    int status = nc_inq_varndims(nCdfId, nVarId, &nVarDimId);
+    if( status != NC_NOERR || nVarDimId != 1)
         return CE_Failure;
 
-    status = nc_inq_vardimid( nCdfId, nVarId, &nVarDimId );
-    if ( status != NC_NOERR )
+    status = nc_inq_vardimid(nCdfId, nVarId, &nVarDimId);
+    if( status != NC_NOERR )
         return CE_Failure;
 
     nc_type nVarType = NC_CHAR;
-    status = nc_inq_vartype( nCdfId, nVarId, &nVarType );
-    if ( status != NC_NOERR )
+    status = nc_inq_vartype(nCdfId, nVarId, &nVarType);
+    if( status != NC_NOERR )
         return CE_Failure;
 
-    size_t  nVarLen = 0;
-    status = nc_inq_dimlen( nCdfId, nVarDimId, &nVarLen );
-    if ( status != NC_NOERR )
+    size_t nVarLen = 0;
+    status = nc_inq_dimlen(nCdfId, nVarDimId, &nVarLen);
+    if( status != NC_NOERR )
         return CE_Failure;
 
     size_t start[1] = {0};
     size_t count[1] = {nVarLen};
 
     /* get the values as tokens */
-    char **papszValues = NCDFTokenizeArray( pszValue );
-    if ( papszValues == NULL )
+    char **papszValues = NCDFTokenizeArray(pszValue);
+    if( papszValues == NULL )
         return CE_Failure;
 
     nVarLen = CSLCount(papszValues);
 
     /* now write the data */
-    if ( nVarType == NC_CHAR ) {
-        status = nc_put_vara_text( nCdfId, nVarId, start, count,
-                                  pszValue );
+    if( nVarType == NC_CHAR )
+    {
+        status = nc_put_vara_text(nCdfId, nVarId, start, count, pszValue);
         NCDF_ERR(status);
     }
-    else {
-
-        switch( nVarType ) {
-            case  NC_BYTE:
+    else
+    {
+        switch( nVarType )
+        {
+        case NC_BYTE:
+        {
+            signed char *pscTemp = static_cast<signed char *>(
+                CPLCalloc(nVarLen, sizeof(signed char)));
+            for( size_t i = 0; i < nVarLen; i++ )
             {
-                signed char *pscTemp = reinterpret_cast<signed char *> (
-                    CPLCalloc( nVarLen, sizeof( signed char ) ) );
-                for(size_t i=0; i < nVarLen; i++) {
-                    char *pszTemp = NULL;
-                    pscTemp[i] = static_cast<signed char>(strtol( papszValues[i], &pszTemp, 10 ));
-                }
-                status = nc_put_vara_schar( nCdfId, nVarId, start, count, pscTemp );
-                NCDF_ERR(status);
-                CPLFree(pscTemp);
-                break;
+                char *pszTemp = NULL;
+                pscTemp[i] = static_cast<signed char>(
+                    strtol(papszValues[i], &pszTemp, 10));
             }
-            case  NC_SHORT:
+            status = nc_put_vara_schar(nCdfId, nVarId, start, count, pscTemp);
+            NCDF_ERR(status);
+            CPLFree(pscTemp);
+            break;
+        }
+        case NC_SHORT:
+        {
+            short *psTemp =
+                static_cast<short *>(CPLCalloc(nVarLen, sizeof(short)));
+            for( size_t i = 0; i < nVarLen; i++ )
             {
-                short *psTemp = reinterpret_cast<short *> (
-                    CPLCalloc( nVarLen, sizeof( short ) ) );
-                for(size_t i=0; i < nVarLen; i++) {
-                    char *pszTemp = NULL;
-                    psTemp[i] = static_cast<short>(strtol( papszValues[i], &pszTemp, 10 ));
-                }
-                status = nc_put_vara_short( nCdfId, nVarId, start, count, psTemp );
-                NCDF_ERR(status);
-                CPLFree(psTemp);
-                break;
+                char *pszTemp = NULL;
+                psTemp[i] =
+                    static_cast<short>(strtol(papszValues[i], &pszTemp, 10));
             }
-            case  NC_INT:
+            status = nc_put_vara_short(nCdfId, nVarId, start, count, psTemp);
+            NCDF_ERR(status);
+            CPLFree(psTemp);
+            break;
+        }
+        case NC_INT:
+        {
+            int *pnTemp = static_cast<int *>(CPLCalloc(nVarLen, sizeof(int)));
+            for( size_t i = 0; i < nVarLen; i++ )
             {
-                int *pnTemp = reinterpret_cast<int *> (
-                    CPLCalloc( nVarLen, sizeof( int ) ) );
-                for(size_t i=0; i < nVarLen; i++) {
-                    char *pszTemp = NULL;
-                    pnTemp[i] = static_cast<int>(strtol( papszValues[i], &pszTemp, 10 ));
-                }
-                status = nc_put_vara_int( nCdfId, nVarId, start, count, pnTemp );
-                NCDF_ERR(status);
-                CPLFree(pnTemp);
-                break;
+                char *pszTemp = NULL;
+                pnTemp[i] =
+                    static_cast<int>(strtol(papszValues[i], &pszTemp, 10));
             }
-            case  NC_FLOAT:
+            status = nc_put_vara_int(nCdfId, nVarId, start, count, pnTemp);
+            NCDF_ERR(status);
+            CPLFree(pnTemp);
+            break;
+        }
+        case NC_FLOAT:
+        {
+            float *pfTemp =
+                static_cast<float *>(CPLCalloc(nVarLen, sizeof(float)));
+            for(size_t i = 0; i < nVarLen; i++)
             {
-                float *pfTemp = reinterpret_cast<float *> (
-                    CPLCalloc( nVarLen, sizeof( float ) ) );
-                for(size_t i=0; i < nVarLen; i++) {
-                    char *pszTemp = NULL;
-                    pfTemp[i] = (float)CPLStrtod( papszValues[i], &pszTemp );
-                }
-                status = nc_put_vara_float( nCdfId, nVarId, start, count,
-                                            pfTemp );
-                NCDF_ERR(status);
-                CPLFree(pfTemp);
-                break;
+                char *pszTemp = NULL;
+                pfTemp[i] = (float)CPLStrtod(papszValues[i], &pszTemp);
             }
-            case  NC_DOUBLE:
+            status = nc_put_vara_float(nCdfId, nVarId, start, count, pfTemp);
+            NCDF_ERR(status);
+            CPLFree(pfTemp);
+            break;
+        }
+        case NC_DOUBLE:
+        {
+            double *pdfTemp =
+                static_cast<double *>(CPLCalloc(nVarLen, sizeof(double)));
+            for( size_t i = 0; i < nVarLen; i++ )
             {
-                double *pdfTemp = reinterpret_cast<double *> (
-                    CPLCalloc( nVarLen, sizeof( double ) ) );
-                for(size_t i=0; i < nVarLen; i++) {
-                    char *pszTemp = NULL;
-                    pdfTemp[i] = CPLStrtod( papszValues[i], &pszTemp );
-                }
-                status = nc_put_vara_double( nCdfId, nVarId, start, count,
-                                             pdfTemp );
-                NCDF_ERR(status);
-                CPLFree(pdfTemp);
-                break;
+                char *pszTemp = NULL;
+                pdfTemp[i] = CPLStrtod(papszValues[i], &pszTemp);
             }
+            status = nc_put_vara_double(nCdfId, nVarId, start, count, pdfTemp);
+            NCDF_ERR(status);
+            CPLFree(pdfTemp);
+            break;
+        }
         default:
 #ifdef NETCDF_HAS_NC4
             int nTmpFormat = 0;
-            status = nc_inq_format( nCdfId, &nTmpFormat );
+            status = nc_inq_format(nCdfId, &nTmpFormat);
             NCDF_ERR(status);
-            if ( nTmpFormat == NCDF_FORMAT_NC4 ) {
-                switch ( nVarType ) {
-                    case NC_STRING:
-                    {
-                        status = nc_put_vara_string( nCdfId, nVarId, start, count,
-                                                     (const char **) papszValues );
-                        NCDF_ERR(status);
-                        break;
-                    }
-                    case NC_UBYTE:
+            if( nTmpFormat == NCDF_FORMAT_NC4 )
+            {
+                switch ( nVarType )
+                {
+                case NC_STRING:
+                {
+                    status = nc_put_vara_string(nCdfId, nVarId, start, count,
+                                                (const char **)papszValues);
+                    NCDF_ERR(status);
+                    break;
+                }
+                case NC_UBYTE:
+                {
+                    unsigned char *pucTemp = static_cast<unsigned char *>(
+                        CPLCalloc(nVarLen, sizeof(unsigned char)));
+                    for( size_t i = 0; i < nVarLen; i++ )
                     {
-                        unsigned char *pucTemp = reinterpret_cast<unsigned char *> (
-                            CPLCalloc( nVarLen, sizeof( unsigned char ) ) );
-                        for(size_t i=0; i < nVarLen; i++) {
-                            char *pszTemp = NULL;
-                            pucTemp[i] = static_cast<unsigned char>(strtoul( papszValues[i], &pszTemp, 10 ));
-                        }
-                        status = nc_put_vara_uchar( nCdfId, nVarId, start, count, pucTemp );
-                        NCDF_ERR(status);
-                        CPLFree(pucTemp);
-                        break;
+                        char *pszTemp = NULL;
+                        pucTemp[i] = static_cast<unsigned char>(
+                            strtoul(papszValues[i], &pszTemp, 10));
                     }
-                    case NC_USHORT:
+                    status = nc_put_vara_uchar(nCdfId, nVarId, start, count,
+                                               pucTemp);
+                    NCDF_ERR(status);
+                    CPLFree(pucTemp);
+                    break;
+                }
+                case NC_USHORT:
+                {
+                    unsigned short *pusTemp =
+                        static_cast<unsigned short *>(
+                            CPLCalloc(nVarLen, sizeof(unsigned short)));
+                    for( size_t i = 0; i < nVarLen; i++ )
                     {
-                        unsigned short *pusTemp = reinterpret_cast<unsigned short *> (
-                            CPLCalloc( nVarLen, sizeof( unsigned short ) ) );
-                        for(size_t i=0; i < nVarLen; i++) {
-                            char *pszTemp = NULL;
-                            pusTemp[i] = static_cast<unsigned short>(strtoul( papszValues[i], &pszTemp, 10 ));
-                        }
-                        status = nc_put_vara_ushort( nCdfId, nVarId, start, count, pusTemp );
-                        NCDF_ERR(status);
-                        CPLFree(pusTemp);
-                        break;
+                        char *pszTemp = NULL;
+                        pusTemp[i] = static_cast<unsigned short>(
+                            strtoul(papszValues[i], &pszTemp, 10));
                     }
-                    case NC_UINT:
+                    status = nc_put_vara_ushort(nCdfId, nVarId, start, count,
+                                                pusTemp);
+                    NCDF_ERR(status);
+                    CPLFree(pusTemp);
+                    break;
+                }
+                case NC_UINT:
+                {
+                    unsigned int *punTemp = static_cast<unsigned int *>(
+                        CPLCalloc(nVarLen, sizeof(unsigned int)));
+                    for( size_t i = 0; i < nVarLen; i++ )
                     {
-                        unsigned int *punTemp = reinterpret_cast<unsigned int *> (
-                            CPLCalloc( nVarLen, sizeof( unsigned int ) ) );
-                        for(size_t i=0; i < nVarLen; i++) {
-                            char *pszTemp = NULL;
-                            punTemp[i] = static_cast<unsigned int>(strtoul( papszValues[i], &pszTemp, 10 ));
-                        }
-                        status = nc_put_vara_uint( nCdfId, nVarId, start, count, punTemp );
-                        NCDF_ERR(status);
-                        CPLFree(punTemp);
-                        break;
+                        char *pszTemp = NULL;
+                        punTemp[i] = static_cast<unsigned int>(
+                            strtoul(papszValues[i], &pszTemp, 10));
                     }
-                    default:
+                    status =
+                        nc_put_vara_uint(nCdfId, nVarId, start, count, punTemp);
+                    NCDF_ERR(status);
+                    CPLFree(punTemp);
+                    break;
+                }
+                default:
 #endif
-                        if ( papszValues ) CSLDestroy( papszValues );
-                        return CE_Failure;
-                        break;
+                    if( papszValues )
+                        CSLDestroy(papszValues);
+                    return CE_Failure;
+                    break;
 #ifdef NETCDF_HAS_NC4
                 }
             }
@@ -8566,13 +8937,12 @@ static CPLErr NCDFPut1DVar( int nCdfId, int nVarId, const char *pszValue )
         }
     }
 
-    if ( papszValues )
-        CSLDestroy( papszValues );
+    if( papszValues )
+        CSLDestroy(papszValues);
 
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                           GetDefaultNoDataValue()                    */
 /************************************************************************/
@@ -8582,240 +8952,256 @@ double NCDFGetDefaultNoDataValue( int nVarType )
 {
     double dfNoData = 0.0;
 
-    switch( nVarType ) {
-        case NC_BYTE:
+    switch( nVarType )
+    {
+    case NC_BYTE:
 #ifdef NETCDF_HAS_NC4
-        case NC_UBYTE:
+    case NC_UBYTE:
 #endif
-            /* don't do default fill-values for bytes, too risky */
-            dfNoData = 0.0;
-            break;
-        case NC_CHAR:
-            dfNoData = NC_FILL_CHAR;
-            break;
-        case NC_SHORT:
-            dfNoData = NC_FILL_SHORT;
-            break;
-        case NC_INT:
-            dfNoData = NC_FILL_INT;
-            break;
-        case NC_FLOAT:
-            dfNoData = NC_FILL_FLOAT;
-            break;
-        case NC_DOUBLE:
-            dfNoData = NC_FILL_DOUBLE;
-            break;
+        // Don't do default fill-values for bytes, too risky.
+        dfNoData = 0.0;
+        break;
+    case NC_CHAR:
+        dfNoData = NC_FILL_CHAR;
+        break;
+    case NC_SHORT:
+        dfNoData = NC_FILL_SHORT;
+        break;
+    case NC_INT:
+        dfNoData = NC_FILL_INT;
+        break;
+    case NC_FLOAT:
+        dfNoData = NC_FILL_FLOAT;
+        break;
+    case NC_DOUBLE:
+        dfNoData = NC_FILL_DOUBLE;
+        break;
 #ifdef NETCDF_HAS_NC4
-        case NC_USHORT:
-            dfNoData = NC_FILL_USHORT;
-            break;
-        case NC_UINT:
-            dfNoData = NC_FILL_UINT;
-            break;
+    case NC_USHORT:
+        dfNoData = NC_FILL_USHORT;
+        break;
+    case NC_UINT:
+        dfNoData = NC_FILL_UINT;
+        break;
 #endif
-        default:
-            dfNoData = 0.0;
-            break;
+    default:
+        dfNoData = 0.0;
+        break;
     }
 
     return dfNoData;
 }
 
-
 static int NCDFDoesVarContainAttribVal( int nCdfId,
-                                 const char * const* papszAttribNames,
-                                 const char * const* papszAttribValues,
-                                 int nVarId,
-                                 const char * pszVarName,
-                                 bool bStrict=true )
+                                        const char *const *papszAttribNames,
+                                        const char *const *papszAttribValues,
+                                        int nVarId,
+                                        const char *pszVarName,
+                                        bool bStrict = true )
 {
-    if ( (nVarId == -1) && (pszVarName != NULL) )
-        nc_inq_varid( nCdfId, pszVarName, &nVarId );
+    if( nVarId == -1 && pszVarName != NULL )
+        nc_inq_varid(nCdfId, pszVarName, &nVarId);
 
-    if ( nVarId == -1 ) return -1;
+    if( nVarId == -1 ) return -1;
 
     bool bFound = false;
-    for( int i=0; !bFound && i<CSLCount((char**)papszAttribNames); i++ ) {
+    for( int i = 0; !bFound && i < CSLCount((char **)papszAttribNames); i++ )
+    {
         char *pszTemp = NULL;
-        if ( NCDFGetAttr( nCdfId, nVarId, papszAttribNames[i], &pszTemp )
-             == CE_None && pszTemp != NULL ) {
-            if ( bStrict ) {
-                if ( EQUAL( pszTemp, papszAttribValues[i] ) )
+        if( NCDFGetAttr(nCdfId, nVarId, papszAttribNames[i], &pszTemp) ==
+               CE_None &&
+           pszTemp != NULL )
+        {
+            if( bStrict )
+            {
+                if( EQUAL(pszTemp, papszAttribValues[i]) )
                     bFound = true;
             }
-            else {
-                if ( EQUALN( pszTemp, papszAttribValues[i], strlen(papszAttribValues[i]) ) )
+            else
+            {
+                if( EQUALN(pszTemp, papszAttribValues[i],
+                           strlen(papszAttribValues[i])) )
                     bFound = true;
             }
-            CPLFree( pszTemp );
+            CPLFree(pszTemp);
         }
     }
     return bFound;
 }
 
 static int NCDFDoesVarContainAttribVal2( int nCdfId,
-                                  const char * papszAttribName,
-                                  const char * const* papszAttribValues,
-                                  int nVarId,
-                                  const char * pszVarName,
-                                  int bStrict=true )
+                                         const char *papszAttribName,
+                                         const char *const *papszAttribValues,
+                                         int nVarId,
+                                         const char *pszVarName,
+                                         int bStrict = true )
 {
-    if ( (nVarId == -1) && (pszVarName != NULL) )
-        nc_inq_varid( nCdfId, pszVarName, &nVarId );
+    if( nVarId == -1 && pszVarName != NULL )
+        nc_inq_varid(nCdfId, pszVarName, &nVarId);
 
-    if ( nVarId == -1 ) return -1;
+    if( nVarId == -1 ) return -1;
 
     bool bFound = false;
     char *pszTemp = NULL;
-    if ( NCDFGetAttr( nCdfId, nVarId, papszAttribName, &pszTemp )
-         != CE_None || pszTemp == NULL ) return FALSE;
+    if( NCDFGetAttr(nCdfId, nVarId, papszAttribName, &pszTemp) != CE_None ||
+        pszTemp == NULL )
+        return FALSE;
 
-    for( int i=0; !bFound && i<CSLCount((char**)papszAttribValues); i++ ) {
-        if ( bStrict ) {
-            if ( EQUAL( pszTemp, papszAttribValues[i] ) )
+    for( int i = 0; !bFound && i < CSLCount((char **)papszAttribValues); i++ )
+    {
+        if( bStrict )
+        {
+            if( EQUAL(pszTemp, papszAttribValues[i]) )
                 bFound = true;
         }
-        else {
-            if ( EQUALN( pszTemp, papszAttribValues[i], strlen(papszAttribValues[i]) ) )
+        else
+        {
+            if( EQUALN(pszTemp, papszAttribValues[i],
+                       strlen(papszAttribValues[i])) )
                 bFound = true;
         }
     }
 
-    CPLFree( pszTemp );
+    CPLFree(pszTemp);
 
     return bFound;
 }
 
-static bool NCDFEqual( const char * papszName, const char * const* papszValues )
+static bool NCDFEqual( const char *papszName, const char *const *papszValues )
 {
-    if ( papszName == NULL || EQUAL(papszName,"") )
+    if( papszName == NULL || EQUAL(papszName, "") )
         return false;
 
-    for( int i=0; i<CSLCount((char**)papszValues); ++i ) {
-        if( EQUAL( papszName, papszValues[i] ) )
+    for( int i = 0; i < CSLCount((char **)papszValues); ++i )
+    {
+        if( EQUAL(papszName, papszValues[i]) )
             return true;
     }
 
     return false;
 }
 
-/* test that a variable is longitude/latitude coordinate, following CF 4.1 and 4.2 */
+// Test that a variable is longitude/latitude coordinate,
+// following CF 4.1 and 4.2.
 static bool NCDFIsVarLongitude( int nCdfId, int nVarId,
-                        const char * pszVarName )
+                                const char *pszVarName )
 {
     /* check for matching attributes */
-    int bVal = NCDFDoesVarContainAttribVal( nCdfId,
-                                            papszCFLongitudeAttribNames,
-                                            papszCFLongitudeAttribValues,
-                                            nVarId, pszVarName );
+    int bVal = NCDFDoesVarContainAttribVal(nCdfId,
+                                           papszCFLongitudeAttribNames,
+                                           papszCFLongitudeAttribValues,
+                                           nVarId, pszVarName);
     /* if not found using attributes then check using var name */
     /* unless GDAL_NETCDF_VERIFY_DIMS=STRICT */
-    if ( bVal == -1 ) {
-        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ),
-                      "STRICT" ) )
-            bVal = NCDFEqual( pszVarName, papszCFLongitudeVarNames );
+    if( bVal == -1 )
+    {
+        if( !EQUAL(CPLGetConfigOption("GDAL_NETCDF_VERIFY_DIMS", "YES"),
+                   "STRICT") )
+            bVal = NCDFEqual(pszVarName, papszCFLongitudeVarNames);
         else
             bVal = FALSE;
     }
+    else if ( bVal )
+    {
+        // Check that the units is not 'm'. See #6759
+        char *pszTemp = NULL;
+        if( NCDFGetAttr(nCdfId, nVarId, "units", &pszTemp) == CE_None &&
+            pszTemp != NULL )
+        {
+            if( EQUAL(pszTemp, "m") )
+                bVal = false;
+            CPLFree(pszTemp);
+        }
+    }
+
     return CPL_TO_BOOL(bVal);
 }
 
 static bool NCDFIsVarLatitude( int nCdfId, int nVarId, const char * pszVarName )
 {
-    int bVal = NCDFDoesVarContainAttribVal( nCdfId,
-                                            papszCFLatitudeAttribNames,
-                                            papszCFLatitudeAttribValues,
-                                            nVarId, pszVarName );
-    if ( bVal == -1 ) {
-        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ),
-                      "STRICT" ) )
-            bVal = NCDFEqual( pszVarName, papszCFLatitudeVarNames );
+    int bVal = NCDFDoesVarContainAttribVal(nCdfId,
+                                           papszCFLatitudeAttribNames,
+                                           papszCFLatitudeAttribValues,
+                                           nVarId, pszVarName);
+    if( bVal == -1 )
+    {
+        if( !EQUAL(CPLGetConfigOption("GDAL_NETCDF_VERIFY_DIMS", "YES"),
+                   "STRICT") )
+            bVal = NCDFEqual(pszVarName, papszCFLatitudeVarNames);
         else
             bVal = FALSE;
     }
+    else if ( bVal )
+    {
+        // Check that the units is not 'm'. See #6759
+        char *pszTemp = NULL;
+        if( NCDFGetAttr(nCdfId, nVarId, "units", &pszTemp) == CE_None &&
+            pszTemp != NULL )
+        {
+            if( EQUAL(pszTemp, "m") )
+                bVal = false;
+            CPLFree(pszTemp);
+        }
+    }
+
     return CPL_TO_BOOL(bVal);
 }
 
 static bool NCDFIsVarProjectionX( int nCdfId, int nVarId, const char * pszVarName )
 {
-    int bVal = NCDFDoesVarContainAttribVal( nCdfId,
-                                            papszCFProjectionXAttribNames,
-                                            papszCFProjectionXAttribValues,
-                                            nVarId, pszVarName );
-    if ( bVal == -1 ) {
-        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ),
-                      "STRICT" ) )
-            bVal = NCDFEqual( pszVarName, papszCFProjectionXVarNames );
+    int bVal = NCDFDoesVarContainAttribVal(nCdfId,
+                                           papszCFProjectionXAttribNames,
+                                           papszCFProjectionXAttribValues,
+                                           nVarId, pszVarName);
+    if( bVal == -1 )
+    {
+        if( !EQUAL(CPLGetConfigOption("GDAL_NETCDF_VERIFY_DIMS", "YES"),
+                   "STRICT") )
+            bVal = NCDFEqual(pszVarName, papszCFProjectionXVarNames);
         else
             bVal = FALSE;
-
     }
     return CPL_TO_BOOL(bVal);
 }
 
-static bool NCDFIsVarProjectionY( int nCdfId, int nVarId, const char * pszVarName )
+static bool NCDFIsVarProjectionY( int nCdfId, int nVarId, const char *pszVarName )
 {
-    int bVal = NCDFDoesVarContainAttribVal( nCdfId,
-                                            papszCFProjectionYAttribNames,
-                                            papszCFProjectionYAttribValues,
-                                            nVarId, pszVarName );
-    if ( bVal == -1 ) {
-        if ( ! EQUAL( CPLGetConfigOption( "GDAL_NETCDF_VERIFY_DIMS", "YES" ),
-                      "STRICT" ) )
-            bVal = NCDFEqual( pszVarName, papszCFProjectionYVarNames );
+    int bVal = NCDFDoesVarContainAttribVal(nCdfId,
+                                           papszCFProjectionYAttribNames,
+                                           papszCFProjectionYAttribValues,
+                                           nVarId, pszVarName);
+    if( bVal == -1 )
+    {
+        if( !EQUAL(CPLGetConfigOption("GDAL_NETCDF_VERIFY_DIMS", "YES"),
+                   "STRICT") )
+            bVal = NCDFEqual(pszVarName, papszCFProjectionYVarNames);
         else
             bVal = FALSE;
     }
-    else if ( bVal )
-    {
-        // Check that the units is not 'm'. See #6759
-        char *pszTemp = NULL;
-        if( NCDFGetAttr( nCdfId, nVarId, "units", &pszTemp ) == CE_None &&
-            pszTemp != NULL )
-        {
-            if( EQUAL( pszTemp, "m") )
-                bVal = false;
-            CPLFree( pszTemp );
-        }
-    }
-
-    else if ( bVal )
-    {
-        // Check that the units is not 'm'. See #6759
-        char *pszTemp = NULL;
-        if( NCDFGetAttr( nCdfId, nVarId, "units", &pszTemp ) == CE_None &&
-            pszTemp != NULL )
-        {
-            if( EQUAL( pszTemp, "m") )
-                bVal = false;
-            CPLFree( pszTemp );
-        }
-    }
-
     return CPL_TO_BOOL(bVal);
 }
 
 /* test that a variable is a vertical coordinate, following CF 4.3 */
 static bool NCDFIsVarVerticalCoord( int nCdfId, int nVarId,
-                            const char * pszVarName )
+                                    const char *pszVarName )
 {
     /* check for matching attributes */
-    if ( NCDFDoesVarContainAttribVal( nCdfId,
-                                      papszCFVerticalAttribNames,
-                                      papszCFVerticalAttribValues,
-                                      nVarId, pszVarName ) )
+    if( NCDFDoesVarContainAttribVal(nCdfId,
+                                    papszCFVerticalAttribNames,
+                                    papszCFVerticalAttribValues,
+                                    nVarId, pszVarName) )
         return true;
     /* check for matching units */
-    else if ( NCDFDoesVarContainAttribVal2( nCdfId,
-                                            CF_UNITS,
-                                            papszCFVerticalUnitsValues,
-                                            nVarId, pszVarName ) )
+    else if( NCDFDoesVarContainAttribVal2(nCdfId,
+                                          CF_UNITS,
+                                          papszCFVerticalUnitsValues,
+                                          nVarId, pszVarName) )
         return true;
     /* check for matching standard name */
-    else if ( NCDFDoesVarContainAttribVal2( nCdfId,
-                                            CF_STD_NAME,
-                                            papszCFVerticalStandardNameValues,
-                                            nVarId, pszVarName ) )
+    else if( NCDFDoesVarContainAttribVal2(nCdfId,
+                                          CF_STD_NAME,
+                                          papszCFVerticalStandardNameValues,
+                                          nVarId, pszVarName) )
         return true;
     else
         return false;
@@ -8823,46 +9209,47 @@ static bool NCDFIsVarVerticalCoord( int nCdfId, int nVarId,
 
 /* test that a variable is a time coordinate, following CF 4.4 */
 static bool NCDFIsVarTimeCoord( int nCdfId, int nVarId,
-                        const char * pszVarName )
+                                const char *pszVarName )
 {
     /* check for matching attributes */
-    if ( NCDFDoesVarContainAttribVal( nCdfId,
-                                      papszCFTimeAttribNames,
-                                      papszCFTimeAttribValues,
-                                      nVarId, pszVarName ) )
+    if( NCDFDoesVarContainAttribVal(nCdfId,
+                                    papszCFTimeAttribNames,
+                                    papszCFTimeAttribValues,
+                                    nVarId, pszVarName) )
         return true;
     /* check for matching units */
-    else if ( NCDFDoesVarContainAttribVal2( nCdfId,
-                                            CF_UNITS,
-                                            papszCFTimeUnitsValues,
-                                            nVarId, pszVarName, false ) )
+    else if( NCDFDoesVarContainAttribVal2(nCdfId,
+                                          CF_UNITS,
+                                          papszCFTimeUnitsValues,
+                                          nVarId, pszVarName, false) )
         return true;
     else
         return false;
 }
 
-/* parse a string, and return as a string list */
-/* if it an array of the form {a,b} then tokenize it */
-/* else return a copy */
+// Parse a string, and return as a string list.
+// If it an array of the form {a,b}, then tokenize it.
+// Otherwise, return a copy.
 static char **NCDFTokenizeArray( const char *pszValue )
 {
-    if ( pszValue==NULL || EQUAL( pszValue, "" ) )
+    if( pszValue == NULL || EQUAL(pszValue, "") )
         return NULL;
 
     char **papszValues = NULL;
     const int nLen = static_cast<int>(strlen(pszValue));
 
-    if ( pszValue[0] == '{' && nLen > 2 && pszValue[nLen-1] == '}' ) {
-        char *pszTemp = reinterpret_cast<char *> (CPLMalloc( (nLen-2) + 1 ) );
-        strncpy( pszTemp, pszValue+1, nLen-2);
-        pszTemp[nLen-2] = '\0';
-        papszValues = CSLTokenizeString2( pszTemp, ",", CSLT_ALLOWEMPTYTOKENS );
-        CPLFree( pszTemp );
-    }
-    else {
-        papszValues = reinterpret_cast<char**> (
-            CPLCalloc( 2, sizeof(char*) ) );
-        papszValues[0] = CPLStrdup( pszValue );
+    if( pszValue[0] == '{' && nLen > 2 && pszValue[nLen - 1] == '}' )
+    {
+        char *pszTemp = static_cast<char *>(CPLMalloc((nLen - 2) + 1));
+        strncpy(pszTemp, pszValue + 1, nLen - 2);
+        pszTemp[nLen - 2] = '\0';
+        papszValues = CSLTokenizeString2(pszTemp, ",", CSLT_ALLOWEMPTYTOKENS);
+        CPLFree(pszTemp);
+    }
+    else
+    {
+        papszValues = reinterpret_cast<char **>(CPLCalloc(2, sizeof(char *)));
+        papszValues[0] = CPLStrdup(pszValue);
         papszValues[1] = NULL;
     }
 
diff --git a/frmts/netcdf/netcdfdataset.h b/frmts/netcdf/netcdfdataset.h
index 0eea212..3a5d7b0 100644
--- a/frmts/netcdf/netcdfdataset.h
+++ b/frmts/netcdf/netcdfdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: netcdfdataset.h 33794 2016-03-26 13:19:07Z goatbar $
+ * $Id: netcdfdataset.h 37958 2017-04-11 14:04:37Z goatbar $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -31,6 +31,8 @@
 #define NETCDFDATASET_H_INCLUDED_
 
 #include <cfloat>
+#include <map>
+#include <vector>
 
 #include "cpl_string.h"
 #include "gdal_frmts.h"
@@ -42,7 +44,7 @@
 
 /************************************************************************/
 /* ==================================================================== */
-/*			     defines    		                             		*/
+/*                           defines                                    */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -126,7 +128,6 @@ __FILE__, __FUNCTION__, __LINE__ ); }
 #endif
 #endif
 
-
 /* -------------------------------------------------------------------- */
 /*       CF-1 or NUG (NetCDF User's Guide) defs                         */
 /* -------------------------------------------------------------------- */
@@ -164,7 +165,6 @@ __FILE__, __FUNCTION__, __LINE__ ); }
 /* #define CF_BOUNDS          "bounds" */
 /* #define CF_ORIG_UNITS      "original_units" */
 
-
 /* -------------------------------------------------------------------- */
 /*      CF-1 convention standard variables related to                   */
 /*      mapping & projection - see http://cf-pcmdi.llnl.gov/            */
@@ -215,7 +215,6 @@ __FILE__, __FUNCTION__, __LINE__ ); }
 #define CF_PP_PERSPECTIVE_POINT_HEIGHT "perspective_point_height"
 #define CF_PP_SWEEP_ANGLE_AXIS        "sweep_angle_axis"
 
-
 /* -------------------------------------------------------------------- */
 /*         CF-1 Coordinate Type Naming (Chapter 4.  Coordinate Types )  */
 /* -------------------------------------------------------------------- */
@@ -268,7 +267,6 @@ static const char* const papszCFTimeUnitsValues[] = {
     "seconds since", "second since", "sec since", "s since",
     NULL };
 
-
 /* -------------------------------------------------------------------- */
 /*         CF-1 to GDAL mappings                                        */
 /* -------------------------------------------------------------------- */
@@ -454,7 +452,6 @@ static const oNetcdfSRS_PP poLCEAMappings[] = {
 //
 // NB: handled as a special case - !isProjected()
 
-
 // Mercator
 //
 // grid_mapping_name = mercator
@@ -481,9 +478,9 @@ static const oNetcdfSRS_PP poM1SPMappings[] = {
 static const oNetcdfSRS_PP poM2SPMappings[] = {
     {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
     {CF_PP_STD_PARALLEL_1, SRS_PP_STANDARD_PARALLEL_1},
-    //From best understanding of this projection, only
- 	// actually specify one SP - it is the same N/S of equator.
-    //{CF_PP_STD_PARALLEL_2, SRS_PP_LATITUDE_OF_ORIGIN},
+    // From best understanding of this projection, only
+    // actually specify one SP - it is the same N/S of equator.
+    // {CF_PP_STD_PARALLEL_2, SRS_PP_LATITUDE_OF_ORIGIN},
     {CF_PP_FALSE_EASTING, SRS_PP_FALSE_EASTING },
     {CF_PP_FALSE_NORTHING, SRS_PP_FALSE_NORTHING },
     {NULL, NULL}
@@ -625,7 +622,6 @@ static const oNetcdfSRS_PP poTMMappings[] = {
 //
 // TODO: see how to map this to OGR
 
-
 static const oNetcdfSRS_PP poGEOSMappings[] = {
     {CF_PP_LON_PROJ_ORIGIN, SRS_PP_CENTRAL_MERIDIAN},
     {CF_PP_PERSPECTIVE_POINT_HEIGHT, SRS_PP_SATELLITE_HEIGHT},
@@ -635,8 +631,6 @@ static const oNetcdfSRS_PP poGEOSMappings[] = {
     {NULL, NULL}
   };
 
-
-
 /* Mappings for various projections, including netcdf and GDAL projection names
    and corresponding oNetcdfSRS_PP mapping struct.
    A NULL mappings value means that the projection is not included in the CF
@@ -695,52 +689,52 @@ static const oNetcdfSRS_PT poNetcdfSRS_PT[] = {
 
 class netCDFWriterConfigAttribute
 {
-    public:
-        CPLString m_osName;
-        CPLString m_osType;
-        CPLString m_osValue;
+  public:
+    CPLString m_osName;
+    CPLString m_osType;
+    CPLString m_osValue;
 
-        bool Parse(CPLXMLNode* psNode);
+    bool Parse(CPLXMLNode *psNode);
 };
 
 class netCDFWriterConfigField
 {
-    public:
-        CPLString m_osName;
-        CPLString m_osNetCDFName;
-        CPLString m_osMainDim;
-        std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
+  public:
+    CPLString m_osName;
+    CPLString m_osNetCDFName;
+    CPLString m_osMainDim;
+    std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
 
-        bool Parse(CPLXMLNode* psNode);
+    bool Parse(CPLXMLNode *psNode);
 };
 
 class netCDFWriterConfigLayer
 {
-    public:
-        CPLString m_osName;
-        CPLString m_osNetCDFName;
-        std::map<CPLString, CPLString> m_oLayerCreationOptions;
-        std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
-        std::map<CPLString, netCDFWriterConfigField> m_oFields;
+  public:
+    CPLString m_osName;
+    CPLString m_osNetCDFName;
+    std::map<CPLString, CPLString> m_oLayerCreationOptions;
+    std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
+    std::map<CPLString, netCDFWriterConfigField> m_oFields;
 
-        bool Parse(CPLXMLNode* psNode);
+    bool Parse(CPLXMLNode *psNode);
 };
 
 class netCDFWriterConfiguration
 {
-    public:
-        bool m_bIsValid;
-        std::map<CPLString, CPLString> m_oDatasetCreationOptions;
-        std::map<CPLString, CPLString> m_oLayerCreationOptions;
-        std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
-        std::map<CPLString, netCDFWriterConfigField> m_oFields;
-        std::map<CPLString, netCDFWriterConfigLayer> m_oLayers;
-
-        netCDFWriterConfiguration() : m_bIsValid(false) {}
-
-        bool Parse(const char* pszFilename);
-        static bool SetNameValue(CPLXMLNode* psNode,
-                                 std::map<CPLString,CPLString>& oMap);
+  public:
+    bool m_bIsValid;
+    std::map<CPLString, CPLString> m_oDatasetCreationOptions;
+    std::map<CPLString, CPLString> m_oLayerCreationOptions;
+    std::vector<netCDFWriterConfigAttribute> m_aoAttributes;
+    std::map<CPLString, netCDFWriterConfigField> m_oFields;
+    std::map<CPLString, netCDFWriterConfigLayer> m_oLayers;
+
+    netCDFWriterConfiguration() : m_bIsValid(false) {}
+
+    bool Parse(const char *pszFilename);
+    static bool SetNameValue(CPLXMLNode *psNode,
+                             std::map<CPLString, CPLString> &oMap);
 };
 
 /************************************************************************/
@@ -843,12 +837,12 @@ class netCDFDataset : public GDALPamDataset
 
   protected:
 
-    CPLXMLNode *SerializeToXML( const char *pszVRTPath );
+    CPLXMLNode *SerializeToXML( const char *pszVRTPath ) override;
 
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef,
                                      OGRwkbGeometryType eGType,
-                                     char ** papszOptions );
+                                     char ** papszOptions ) override;
 
   public:
 
@@ -856,18 +850,18 @@ class netCDFDataset : public GDALPamDataset
     virtual ~netCDFDataset();
 
     /* Projection/GT */
-    CPLErr 	GetGeoTransform( double * );
-    CPLErr 	SetGeoTransform (double *);
-    const char * GetProjectionRef();
-    CPLErr 	SetProjection (const char *);
+    CPLErr      GetGeoTransform( double * ) override;
+    CPLErr      SetGeoTransform (double *) override;
+    const char * GetProjectionRef() override;
+    CPLErr      SetProjection (const char *) override;
 
-    virtual char      **GetMetadataDomainList();
-    char ** GetMetadata( const char * );
+    virtual char      **GetMetadataDomainList() override;
+    char ** GetMetadata( const char * ) override;
 
-    virtual int  TestCapability(const char* pszCap);
+    virtual int  TestCapability(const char* pszCap) override;
 
-    virtual int  GetLayerCount() { return nLayers; }
-    virtual OGRLayer* GetLayer(int nIdx);
+    virtual int  GetLayerCount() override { return nLayers; }
+    virtual OGRLayer* GetLayer(int nIdx) override;
 
     int GetCDFID() { return cdfid; }
 
@@ -987,17 +981,17 @@ class netCDFLayer: public OGRLayer
         int             GetCDFID() const { return m_nLayerCDFId; }
         void            SetCDFID(int nId) { m_nLayerCDFId = nId; }
 
-        virtual void ResetReading();
-        virtual OGRFeature* GetNextFeature();
+        virtual void ResetReading() override;
+        virtual OGRFeature* GetNextFeature() override;
 
-        virtual GIntBig GetFeatureCount(int bForce);
+        virtual GIntBig GetFeatureCount(int bForce) override;
 
-        virtual int  TestCapability(const char* pszCap);
+        virtual int  TestCapability(const char* pszCap) override;
 
-        virtual OGRFeatureDefn* GetLayerDefn();
+        virtual OGRFeatureDefn* GetLayerDefn() override;
 
-        virtual OGRErr ICreateFeature(OGRFeature* poFeature);
-        virtual OGRErr CreateField(OGRFieldDefn* poFieldDefn, int bApproxOK);
+        virtual OGRErr ICreateFeature(OGRFeature* poFeature) override;
+        virtual OGRErr CreateField(OGRFieldDefn* poFieldDefn, int bApproxOK) override;
 };
 
 void NCDFWriteLonLatVarsAttributes(int cdfid, int nVarLonID, int nVarLatID);
diff --git a/frmts/netcdf/netcdflayer.cpp b/frmts/netcdf/netcdflayer.cpp
index af438c9..3aa9ced 100644
--- a/frmts/netcdf/netcdflayer.cpp
+++ b/frmts/netcdf/netcdflayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: netcdflayer.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -30,17 +29,17 @@
 #include "netcdfdataset.h"
 #include "cpl_time.h"
 
-CPL_CVSID("$Id: netcdflayer.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: netcdflayer.cpp 37982 2017-04-13 17:30:17Z goatbar $");
 
 /************************************************************************/
 /*                            netCDFLayer()                             */
 /************************************************************************/
 
-netCDFLayer::netCDFLayer(netCDFDataset* poDS,
+netCDFLayer::netCDFLayer(netCDFDataset *poDS,
                          int nLayerCDFId,
-                         const char* pszName,
+                         const char *pszName,
                          OGRwkbGeometryType eGeomType,
-                         OGRSpatialReference* poSRS) :
+                         OGRSpatialReference *poSRS) :
         m_poDS(poDS),
         m_nLayerCDFId(nLayerCDFId),
         m_poFeatureDefn(new OGRFeatureDefn(pszName)),
@@ -84,47 +83,45 @@ netCDFLayer::netCDFLayer(netCDFDataset* poDS,
 /*                           ~netCDFLayer()                             */
 /************************************************************************/
 
-netCDFLayer::~netCDFLayer()
-{
-    m_poFeatureDefn->Release();
-}
+netCDFLayer::~netCDFLayer() { m_poFeatureDefn->Release(); }
 
 /************************************************************************/
 /*                   netCDFWriteAttributesFromConf()                    */
 /************************************************************************/
 
-static void netCDFWriteAttributesFromConf( int cdfid, int varid,
-                    const std::vector<netCDFWriterConfigAttribute>& aoAttributes)
+static void netCDFWriteAttributesFromConf(
+    int cdfid, int varid,
+    const std::vector<netCDFWriterConfigAttribute> &aoAttributes)
 {
-    for(size_t i=0; i < aoAttributes.size(); i++)
+    for(size_t i = 0; i < aoAttributes.size(); i++)
     {
-        const netCDFWriterConfigAttribute& oAtt = aoAttributes[i];
+        const netCDFWriterConfigAttribute &oAtt = aoAttributes[i];
         int status = NC_NOERR;
-        if( oAtt.m_osValue.size() == 0 )
+        if( oAtt.m_osValue.empty() )
         {
             int attid = -1;
-            status = nc_inq_attid( cdfid, varid, oAtt.m_osName, &attid );
+            status = nc_inq_attid(cdfid, varid, oAtt.m_osName, &attid);
             if( status == NC_NOERR )
-                status = nc_del_att( cdfid, varid, oAtt.m_osName );
+                status = nc_del_att(cdfid, varid, oAtt.m_osName);
             else
                 status = NC_NOERR;
         }
         else if( EQUAL(oAtt.m_osType, "string") )
         {
-            status = nc_put_att_text( cdfid, varid, oAtt.m_osName,
-                                        oAtt.m_osValue.size(), oAtt.m_osValue );
+            status = nc_put_att_text(cdfid, varid, oAtt.m_osName,
+                                     oAtt.m_osValue.size(), oAtt.m_osValue);
         }
         else if( EQUAL(oAtt.m_osType, "integer") )
         {
-            int nVal = atoi( oAtt.m_osValue );
-            status = nc_put_att_int( cdfid, varid, oAtt.m_osName,
-                                        NC_INT, 1, &nVal );
+            int nVal = atoi(oAtt.m_osValue);
+            status =
+                nc_put_att_int(cdfid, varid, oAtt.m_osName, NC_INT, 1, &nVal);
         }
         else if( EQUAL(oAtt.m_osType, "double") )
         {
-            double dfVal = CPLAtof( oAtt.m_osValue );
-            status = nc_put_att_double( cdfid, varid, oAtt.m_osName,
-                                        NC_DOUBLE, 1, &dfVal );
+            double dfVal = CPLAtof(oAtt.m_osValue);
+            status = nc_put_att_double(cdfid, varid, oAtt.m_osName,
+                                       NC_DOUBLE, 1, &dfVal);
         }
         NCDF_ERR(status);
     }
@@ -134,25 +131,27 @@ static void netCDFWriteAttributesFromConf( int cdfid, int varid,
 /*                               Create()                               */
 /************************************************************************/
 
-bool netCDFLayer::Create(char** papszOptions,
-                         const netCDFWriterConfigLayer* poLayerConfig)
+bool netCDFLayer::Create(char **papszOptions,
+                         const netCDFWriterConfigLayer *poLayerConfig)
 {
     m_osRecordDimName = CSLFetchNameValueDef(papszOptions, "RECORD_DIM_NAME",
                                              m_osRecordDimName.c_str());
-    m_bAutoGrowStrings = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "AUTOGROW_STRINGS", TRUE ));
-    m_nDefaultWidth = atoi(CSLFetchNameValueDef(papszOptions,
-                                                "STRING_DEFAULT_WIDTH",
-                                                CPLSPrintf("%d", m_bAutoGrowStrings ? 10 : 80)));
-    m_bWriteGDALTags = CPL_TO_BOOL(CSLFetchBoolean(
-                    m_poDS->papszCreationOptions, "WRITE_GDAL_TAGS", TRUE ));
-    m_bUseStringInNC4 = CPL_TO_BOOL(CSLFetchBoolean(
-                                papszOptions, "USE_STRING_IN_NC4", TRUE ));
-    m_bNCDumpCompat = CPL_TO_BOOL(CSLFetchBoolean(
-                                papszOptions, "NCDUMP_COMPAT", TRUE ));
-
-    std::vector< std::pair<CPLString, int> > aoAutoVariables;
-
-    const char* pszFeatureType = CSLFetchNameValue(papszOptions,"FEATURE_TYPE");
+    m_bAutoGrowStrings =
+        CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "AUTOGROW_STRINGS", TRUE));
+    m_nDefaultWidth = atoi(
+        CSLFetchNameValueDef(papszOptions, "STRING_DEFAULT_WIDTH",
+                             CPLSPrintf("%d", m_bAutoGrowStrings ? 10 : 80)));
+    m_bWriteGDALTags = CPL_TO_BOOL(
+        CSLFetchBoolean(m_poDS->papszCreationOptions, "WRITE_GDAL_TAGS", TRUE));
+    m_bUseStringInNC4 =
+        CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "USE_STRING_IN_NC4", TRUE));
+    m_bNCDumpCompat =
+        CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "NCDUMP_COMPAT", TRUE));
+
+    std::vector<std::pair<CPLString, int> > aoAutoVariables;
+
+    const char *pszFeatureType =
+        CSLFetchNameValue(papszOptions, "FEATURE_TYPE");
     if( pszFeatureType != NULL )
     {
         if( EQUAL(pszFeatureType, "POINT") )
@@ -160,7 +159,8 @@ bool netCDFLayer::Create(char** papszOptions,
             if( wkbFlatten(m_poFeatureDefn->GetGeomType()) != wkbPoint )
             {
                 CPLError(CE_Warning, CPLE_NotSupported,
-                         "FEATURE_TYPE=POINT only supported for Point layer geometry type.");
+                         "FEATURE_TYPE=POINT only supported for Point layer "
+                         "geometry type.");
             }
         }
         else if( EQUAL(pszFeatureType, "PROFILE") )
@@ -168,39 +168,44 @@ bool netCDFLayer::Create(char** papszOptions,
             if( wkbFlatten(m_poFeatureDefn->GetGeomType()) != wkbPoint )
             {
                 CPLError(CE_Warning, CPLE_NotSupported,
-                         "FEATURE_TYPE=PROFILE only supported for Point layer geometry type.");
+                         "FEATURE_TYPE=PROFILE only supported for Point layer "
+                         "geometry type.");
             }
             else
             {
-                /* Cf http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html#_indexed_ragged_array_representation_of_profiles */
+                // Cf http://cfconventions.org/cf-conventions/v1.6.0/cf-conventions.html#_indexed_ragged_array_representation_of_profiles
 
-                m_osProfileDimName = CSLFetchNameValueDef(papszOptions, "PROFILE_DIM_NAME", "profile");
-                m_osProfileVariables = CSLFetchNameValueDef(papszOptions, "PROFILE_VARIABLES", "");
+                m_osProfileDimName = CSLFetchNameValueDef(
+                    papszOptions, "PROFILE_DIM_NAME", "profile");
+                m_osProfileVariables =
+                    CSLFetchNameValueDef(papszOptions, "PROFILE_VARIABLES", "");
 
-                const char* pszProfileInitSize = CSLFetchNameValueDef(
-                        papszOptions, "PROFILE_DIM_INIT_SIZE",
-                        (m_poDS->eFormat == NCDF_FORMAT_NC4 ) ? "UNLIMITED" : "100");
+                const char *pszProfileInitSize = CSLFetchNameValueDef(
+                    papszOptions, "PROFILE_DIM_INIT_SIZE",
+                    (m_poDS->eFormat == NCDF_FORMAT_NC4) ? "UNLIMITED" : "100");
                 m_bProfileVarUnlimited = EQUAL(pszProfileInitSize, "UNLIMITED");
-                size_t nProfileInitSize = m_bProfileVarUnlimited ?
-                    NC_UNLIMITED : static_cast<size_t>(atoi(pszProfileInitSize));
-                int status = nc_def_dim( m_nLayerCDFId, m_osProfileDimName,
-                                         nProfileInitSize, &m_nProfileDimID );
+                size_t nProfileInitSize =
+                    m_bProfileVarUnlimited
+                        ? NC_UNLIMITED
+                        : static_cast<size_t>(atoi(pszProfileInitSize));
+                int status = nc_def_dim(m_nLayerCDFId, m_osProfileDimName,
+                                        nProfileInitSize, &m_nProfileDimID);
                 NCDF_ERR(status);
                 if( status != NC_NOERR )
                     return false;
 
-                status = nc_def_var( m_nLayerCDFId, m_osProfileDimName, NC_INT,
-                                     1, &m_nProfileDimID,
-                                     &m_nProfileVarID);
+                status = nc_def_var(m_nLayerCDFId, m_osProfileDimName, NC_INT,
+                                    1, &m_nProfileDimID, &m_nProfileVarID);
                 NCDF_ERR(status);
                 if( status != NC_NOERR )
                     return false;
 
-                aoAutoVariables.push_back(
-                    std::pair<CPLString,int>(m_osProfileDimName, m_nProfileVarID) );
+                aoAutoVariables.push_back(std::pair<CPLString, int>(
+                    m_osProfileDimName, m_nProfileVarID));
 
-                status = nc_put_att_text( m_nLayerCDFId, m_nProfileVarID, "cf_role",
-                                          strlen("profile_id"), "profile_id" );
+                status =
+                    nc_put_att_text(m_nLayerCDFId, m_nProfileVarID, "cf_role",
+                                    strlen("profile_id"), "profile_id");
                 NCDF_ERR(status);
             }
         }
@@ -214,67 +219,74 @@ bool netCDFLayer::Create(char** papszOptions,
     int status;
     if( m_bWriteGDALTags )
     {
-        status = nc_put_att_text( m_nLayerCDFId, NC_GLOBAL, "ogr_layer_name",
-                        strlen(m_poFeatureDefn->GetName()), m_poFeatureDefn->GetName());
+        status = nc_put_att_text(m_nLayerCDFId, NC_GLOBAL, "ogr_layer_name",
+                                 strlen(m_poFeatureDefn->GetName()),
+                                 m_poFeatureDefn->GetName());
         NCDF_ERR(status);
     }
 
-    status = nc_def_dim( m_nLayerCDFId, m_osRecordDimName,
-                             NC_UNLIMITED, &m_nRecordDimID );
+    status = nc_def_dim(m_nLayerCDFId, m_osRecordDimName,
+                        NC_UNLIMITED, &m_nRecordDimID);
     NCDF_ERR(status);
     if( status != NC_NOERR )
         return false;
 
-    if( m_osProfileDimName.size() )
+    if( !m_osProfileDimName.empty() )
     {
-        status = nc_def_var( m_nLayerCDFId, "parentIndex", NC_INT,
-                             1, &m_nRecordDimID, &m_nParentIndexVarID );
+        status = nc_def_var(m_nLayerCDFId, "parentIndex", NC_INT,
+                            1, &m_nRecordDimID, &m_nParentIndexVarID);
         NCDF_ERR(status);
         if( status != NC_NOERR )
             return false;
 
-        aoAutoVariables.push_back( std::pair<CPLString,int>("parentIndex", m_nParentIndexVarID) );
+        aoAutoVariables.push_back(
+            std::pair<CPLString, int>("parentIndex", m_nParentIndexVarID));
 
-        status = nc_put_att_text( m_nLayerCDFId, m_nParentIndexVarID, CF_LNG_NAME,
-                                  strlen("index of profile"), "index of profile" );
+        status =
+            nc_put_att_text(m_nLayerCDFId, m_nParentIndexVarID, CF_LNG_NAME,
+                            strlen("index of profile"), "index of profile");
         NCDF_ERR(status);
 
-        status = nc_put_att_text( m_nLayerCDFId, m_nParentIndexVarID, "instance_dimension",
-                                  m_osProfileDimName.size(), m_osProfileDimName.c_str() );
+        status = nc_put_att_text(
+            m_nLayerCDFId, m_nParentIndexVarID, "instance_dimension",
+            m_osProfileDimName.size(), m_osProfileDimName.c_str());
         NCDF_ERR(status);
     }
 
-    OGRSpatialReference* poSRS = NULL;
+    OGRSpatialReference *poSRS = NULL;
     if( m_poFeatureDefn->GetGeomFieldCount() )
         poSRS = m_poFeatureDefn->GetGeomFieldDefn(0)->GetSpatialRef();
 
     if( wkbFlatten(m_poFeatureDefn->GetGeomType()) == wkbPoint )
     {
-        const int nPointDim = m_osProfileDimName.size() ? m_nProfileDimID : m_nRecordDimID;
+        const int nPointDim =
+            !m_osProfileDimName.empty() ? m_nProfileDimID : m_nRecordDimID;
         const bool bIsGeographic = (poSRS == NULL || poSRS->IsGeographic());
 
-        const char* pszXVarName =
-                bIsGeographic ? CF_LONGITUDE_VAR_NAME : CF_PROJ_X_VAR_NAME;
-        status = nc_def_var( m_nLayerCDFId,
-                             pszXVarName,
-                             NC_DOUBLE, 1, &nPointDim, &m_nXVarID);
+        const char *pszXVarName =
+            bIsGeographic ? CF_LONGITUDE_VAR_NAME : CF_PROJ_X_VAR_NAME;
+        status = nc_def_var(m_nLayerCDFId, pszXVarName, NC_DOUBLE, 1,
+                            &nPointDim, &m_nXVarID);
         NCDF_ERR(status);
-        if ( status != NC_NOERR ) {
+        if( status != NC_NOERR )
+        {
             return false;
         }
 
-        const char* pszYVarName =
-                bIsGeographic ? CF_LATITUDE_VAR_NAME : CF_PROJ_Y_VAR_NAME;
-        status = nc_def_var( m_nLayerCDFId,
-                             pszYVarName,
-                             NC_DOUBLE, 1, &nPointDim, &m_nYVarID);
+        const char *pszYVarName =
+            bIsGeographic ? CF_LATITUDE_VAR_NAME : CF_PROJ_Y_VAR_NAME;
+        status = nc_def_var(m_nLayerCDFId, pszYVarName, NC_DOUBLE, 1,
+                            &nPointDim, &m_nYVarID);
         NCDF_ERR(status);
-        if ( status != NC_NOERR ) {
+        if( status != NC_NOERR )
+        {
             return false;
         }
 
-        aoAutoVariables.push_back( std::pair<CPLString,int>(pszXVarName, m_nXVarID) );
-        aoAutoVariables.push_back( std::pair<CPLString,int>(pszYVarName, m_nYVarID) );
+        aoAutoVariables.push_back(
+            std::pair<CPLString, int>(pszXVarName, m_nXVarID));
+        aoAutoVariables.push_back(
+            std::pair<CPLString, int>(pszYVarName, m_nYVarID));
 
         m_nXVarNCDFType = NC_DOUBLE;
         m_nYVarNCDFType = NC_DOUBLE;
@@ -285,55 +297,57 @@ bool netCDFLayer::Create(char** papszOptions,
         m_osCoordinatesValue += " ";
         m_osCoordinatesValue += pszYVarName;
 
-        if (poSRS == NULL || poSRS->IsGeographic() )
+        if( poSRS == NULL || poSRS->IsGeographic() )
         {
             NCDFWriteLonLatVarsAttributes(m_nLayerCDFId, m_nXVarID, m_nYVarID);
         }
         else if (poSRS != NULL && poSRS->IsProjected() )
         {
-            NCDFWriteXYVarsAttributes(m_nLayerCDFId, m_nXVarID, m_nYVarID, poSRS);
+            NCDFWriteXYVarsAttributes(m_nLayerCDFId, m_nXVarID, m_nYVarID,
+                                      poSRS);
         }
 
         if( m_poFeatureDefn->GetGeomType() == wkbPoint25D )
         {
-            const char* pszZVarName = "z";
-            status = nc_def_var( m_nLayerCDFId,
-                                 pszZVarName, NC_DOUBLE,
-                                 1, &m_nRecordDimID, &m_nZVarID);
+            const char *pszZVarName = "z";
+            status = nc_def_var(m_nLayerCDFId, pszZVarName, NC_DOUBLE, 1,
+                                &m_nRecordDimID, &m_nZVarID);
             NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
+            if( status != NC_NOERR )
+            {
                 return false;
             }
 
-            aoAutoVariables.push_back( std::pair<CPLString,int>(pszZVarName, m_nZVarID) );
+            aoAutoVariables.push_back(
+                std::pair<CPLString, int>(pszZVarName, m_nZVarID));
 
             m_nZVarNCDFType = NC_DOUBLE;
             m_uZVarNoData.dfVal = NC_FILL_DOUBLE;
 
-            status = nc_put_att_text( m_nLayerCDFId, m_nZVarID, CF_LNG_NAME,
-                             strlen("z coordinate"), "z coordinate");
+            status = nc_put_att_text(m_nLayerCDFId, m_nZVarID, CF_LNG_NAME,
+                                     strlen("z coordinate"), "z coordinate");
             NCDF_ERR(status);
 
-            status = nc_put_att_text( m_nLayerCDFId, m_nZVarID, CF_STD_NAME,
-                             strlen("height"), "height");
+            status = nc_put_att_text(m_nLayerCDFId, m_nZVarID, CF_STD_NAME,
+                                     strlen("height"), "height");
             NCDF_ERR(status);
 
-            status = nc_put_att_text( m_nLayerCDFId, m_nZVarID, CF_AXIS,
-                             strlen("Z"), "Z");
+            status = nc_put_att_text(m_nLayerCDFId, m_nZVarID, CF_AXIS,
+                                     strlen("Z"), "Z");
             NCDF_ERR(status);
 
-            status = nc_put_att_text( m_nLayerCDFId, m_nZVarID, CF_UNITS,
-                             strlen("m"), "m");
+            status = nc_put_att_text(m_nLayerCDFId, m_nZVarID, CF_UNITS,
+                                     strlen("m"), "m");
             NCDF_ERR(status);
 
             m_osCoordinatesValue += " ";
             m_osCoordinatesValue += pszZVarName;
-
         }
 
-        const char* pszFeatureTypeVal = m_osProfileDimName.size() ? "profile" : "point";
-        status = nc_put_att_text( m_nLayerCDFId, NC_GLOBAL, "featureType",
-                                  strlen(pszFeatureTypeVal), pszFeatureTypeVal);
+        const char *pszFeatureTypeVal =
+            !m_osProfileDimName.empty() ? "profile" : "point";
+        status = nc_put_att_text(m_nLayerCDFId, NC_GLOBAL, "featureType",
+                                 strlen(pszFeatureTypeVal), pszFeatureTypeVal);
         NCDF_ERR(status);
     }
     else if( m_poFeatureDefn->GetGeomType() != wkbNone )
@@ -342,79 +356,86 @@ bool netCDFLayer::Create(char** papszOptions,
         if( m_poDS->eFormat == NCDF_FORMAT_NC4 && m_bUseStringInNC4 )
         {
             m_nWKTNCDFType = NC_STRING;
-            status = nc_def_var( m_nLayerCDFId,
-                                 m_osWKTVarName.c_str(), NC_STRING, 1,
-                                 &m_nRecordDimID, &m_nWKTVarID);
+            status = nc_def_var(m_nLayerCDFId, m_osWKTVarName.c_str(),
+                                NC_STRING, 1, &m_nRecordDimID, &m_nWKTVarID);
         }
         else
 #endif
         {
             m_nWKTNCDFType = NC_CHAR;
-            m_nWKTMaxWidth = atoi(CSLFetchNameValueDef(papszOptions, "WKT_DEFAULT_WIDTH",
-                                        CPLSPrintf("%d", m_bAutoGrowStrings ? 1000 : 10000)));
-            status = nc_def_dim( m_nLayerCDFId,
-                                 CPLSPrintf("%s_max_width", m_osWKTVarName.c_str()),
-                                 m_nWKTMaxWidth,
-                                 &m_nWKTMaxWidthDimId );
+            m_nWKTMaxWidth = atoi(CSLFetchNameValueDef(
+                papszOptions, "WKT_DEFAULT_WIDTH",
+                CPLSPrintf("%d", m_bAutoGrowStrings ? 1000 : 10000)));
+            status =
+                nc_def_dim(m_nLayerCDFId,
+                           CPLSPrintf("%s_max_width", m_osWKTVarName.c_str()),
+                           m_nWKTMaxWidth, &m_nWKTMaxWidthDimId);
             NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
+            if( status != NC_NOERR )
+            {
                 return false;
             }
 
-            int anDims[] = { m_nRecordDimID, m_nWKTMaxWidthDimId };
-            status = nc_def_var( m_nLayerCDFId,
-                                 m_osWKTVarName.c_str(), NC_CHAR, 2,
-                                 anDims, &m_nWKTVarID );
+            int anDims[2] = { m_nRecordDimID, m_nWKTMaxWidthDimId };
+            status = nc_def_var(m_nLayerCDFId, m_osWKTVarName.c_str(), NC_CHAR,
+                                2, anDims, &m_nWKTVarID);
         }
         NCDF_ERR(status);
-        if ( status != NC_NOERR ) {
+        if( status != NC_NOERR )
+        {
             return false;
         }
 
-        aoAutoVariables.push_back( std::pair<CPLString,int>(m_osWKTVarName, m_nWKTVarID) );
+        aoAutoVariables.push_back(
+            std::pair<CPLString, int>(m_osWKTVarName, m_nWKTVarID));
 
-        status = nc_put_att_text( m_nLayerCDFId, m_nWKTVarID, CF_LNG_NAME,
-                         strlen("Geometry as ISO WKT"), "Geometry as ISO WKT" );
+        status = nc_put_att_text(m_nLayerCDFId, m_nWKTVarID, CF_LNG_NAME,
+                                 strlen("Geometry as ISO WKT"),
+                                 "Geometry as ISO WKT");
         NCDF_ERR(status);
 
-        //nc_put_att_text( m_nLayerCDFId, m_nWKTVarID, CF_UNITS,
-        //                 strlen("none"), "none" );
+        // nc_put_att_text(m_nLayerCDFId, m_nWKTVarID, CF_UNITS,
+        //                 strlen("none"), "none");
 
         if( m_bWriteGDALTags )
         {
-            status = nc_put_att_text( m_nLayerCDFId, NC_GLOBAL, "ogr_geometry_field",
-                             m_osWKTVarName.size(), m_osWKTVarName.c_str() );
+            status =
+                nc_put_att_text(m_nLayerCDFId, NC_GLOBAL, "ogr_geometry_field",
+                                m_osWKTVarName.size(), m_osWKTVarName.c_str());
             NCDF_ERR(status);
 
-            CPLString osGeometryType = OGRToOGCGeomType(m_poFeatureDefn->GetGeomType());
+            CPLString osGeometryType =
+                OGRToOGCGeomType(m_poFeatureDefn->GetGeomType());
             if( wkbHasZ(m_poFeatureDefn->GetGeomType()) )
                 osGeometryType += " Z";
-            status = nc_put_att_text( m_nLayerCDFId, NC_GLOBAL, "ogr_layer_type",
-                                      osGeometryType.size(), osGeometryType.c_str());
+            status =
+                nc_put_att_text(m_nLayerCDFId, NC_GLOBAL, "ogr_layer_type",
+                                osGeometryType.size(), osGeometryType.c_str());
             NCDF_ERR(status);
         }
     }
 
     if( poSRS != NULL )
     {
-        char* pszCFProjection = NULL;
-        int nSRSVarId = NCDFWriteSRSVariable(m_nLayerCDFId, poSRS,
-                                             &pszCFProjection,
-                                             m_bWriteGDALTags);
+        char *pszCFProjection = NULL;
+        int nSRSVarId = NCDFWriteSRSVariable(
+            m_nLayerCDFId, poSRS, &pszCFProjection, m_bWriteGDALTags);
         if( nSRSVarId < 0 )
             return false;
         if( pszCFProjection != NULL )
         {
-            aoAutoVariables.push_back( std::pair<CPLString,int>(pszCFProjection, nSRSVarId) );
+            aoAutoVariables.push_back(
+                std::pair<CPLString, int>(pszCFProjection, nSRSVarId));
 
             m_osGridMapping = pszCFProjection;
             CPLFree(pszCFProjection);
         }
 
-        if( m_nWKTVarID >= 0 && m_osGridMapping.size() != 0 )
+        if( m_nWKTVarID >= 0 && !m_osGridMapping.empty() )
         {
-            status = nc_put_att_text( m_nLayerCDFId, m_nWKTVarID, CF_GRD_MAPPING,
-                                      m_osGridMapping.size(), m_osGridMapping.c_str() );
+            status = nc_put_att_text(m_nLayerCDFId, m_nWKTVarID, CF_GRD_MAPPING,
+                                     m_osGridMapping.size(),
+                                     m_osGridMapping.c_str());
             NCDF_ERR(status);
         }
     }
@@ -431,26 +452,27 @@ bool netCDFLayer::Create(char** papszOptions,
                                           poLayerConfig->m_aoAttributes);
         }
 
-        for(size_t i=0; i<aoAutoVariables.size(); i++)
+        for( size_t i = 0; i < aoAutoVariables.size(); i++ )
         {
-            const netCDFWriterConfigField* poConfig = NULL;
+            const netCDFWriterConfigField *poConfig = NULL;
             CPLString osLookup = "__" + aoAutoVariables[i].first;
             std::map<CPLString, netCDFWriterConfigField>::const_iterator oIter;
             if( m_poLayerConfig != NULL &&
                 (oIter = m_poLayerConfig->m_oFields.find(osLookup)) !=
-                m_poLayerConfig->m_oFields.end() )
+                    m_poLayerConfig->m_oFields.end() )
             {
                 poConfig = &(oIter->second);
             }
             else if( (oIter = m_poDS->oWriterConfig.m_oFields.find(osLookup)) !=
-                    m_poDS->oWriterConfig.m_oFields.end() )
+                     m_poDS->oWriterConfig.m_oFields.end() )
             {
                 poConfig = &(oIter->second);
             }
 
             if( poConfig != NULL )
             {
-                netCDFWriteAttributesFromConf(m_nLayerCDFId, aoAutoVariables[i].second,
+                netCDFWriteAttributesFromConf(m_nLayerCDFId,
+                                              aoAutoVariables[i].second,
                                               poConfig->m_aoAttributes);
             }
         }
@@ -466,40 +488,39 @@ bool netCDFLayer::Create(char** papszOptions,
 void netCDFLayer::SetRecordDimID(int nRecordDimID)
 {
     m_nRecordDimID = nRecordDimID;
-    char szTemp[NC_MAX_NAME+1];
+    char szTemp[NC_MAX_NAME + 1];
     szTemp[0] = 0;
-    int status = nc_inq_dimname( m_nLayerCDFId, m_nRecordDimID, szTemp);
+    int status = nc_inq_dimname(m_nLayerCDFId, m_nRecordDimID, szTemp);
     NCDF_ERR(status);
     m_osRecordDimName = szTemp;
 }
 
-
 /************************************************************************/
 /*                            GetFillValue()                            */
 /************************************************************************/
 
 CPLErr netCDFLayer::GetFillValue( int nVarId, char **ppszValue )
 {
-    if( NCDFGetAttr( m_nLayerCDFId, nVarId, _FillValue, ppszValue) == CE_None )
+    if( NCDFGetAttr(m_nLayerCDFId, nVarId, _FillValue, ppszValue) == CE_None )
         return CE_None;
-    return NCDFGetAttr( m_nLayerCDFId, nVarId, "missing_value", ppszValue);
+    return NCDFGetAttr(m_nLayerCDFId, nVarId, "missing_value", ppszValue);
 }
 
 CPLErr netCDFLayer::GetFillValue( int nVarId, double *pdfValue )
 {
-    if( NCDFGetAttr( m_nLayerCDFId, nVarId, _FillValue, pdfValue) == CE_None )
+    if( NCDFGetAttr(m_nLayerCDFId, nVarId, _FillValue, pdfValue) == CE_None )
         return CE_None;
-    return NCDFGetAttr( m_nLayerCDFId, nVarId, "missing_value", pdfValue);
+    return NCDFGetAttr(m_nLayerCDFId, nVarId, "missing_value", pdfValue);
 }
 
 /************************************************************************/
 /*                         GetNoDataValueForFloat()                     */
 /************************************************************************/
 
-void netCDFLayer::GetNoDataValueForFloat( int nVarId, NCDFNoDataUnion* puNoData )
+void netCDFLayer::GetNoDataValueForFloat( int nVarId, NCDFNoDataUnion *puNoData )
 {
     double dfValue;
-    if( GetFillValue( nVarId, &dfValue) == CE_None )
+    if( GetFillValue(nVarId, &dfValue) == CE_None )
         puNoData->fVal = static_cast<float>(dfValue);
     else
         puNoData->fVal = NC_FILL_FLOAT;
@@ -509,10 +530,10 @@ void netCDFLayer::GetNoDataValueForFloat( int nVarId, NCDFNoDataUnion* puNoData
 /*                        GetNoDataValueForDouble()                     */
 /************************************************************************/
 
-void netCDFLayer::GetNoDataValueForDouble( int nVarId, NCDFNoDataUnion* puNoData )
+void netCDFLayer::GetNoDataValueForDouble( int nVarId, NCDFNoDataUnion *puNoData )
 {
     double dfValue;
-    if( GetFillValue( nVarId, &dfValue) == CE_None )
+    if( GetFillValue(nVarId, &dfValue) == CE_None )
         puNoData->dfVal = dfValue;
     else
         puNoData->dfVal = NC_FILL_DOUBLE;
@@ -522,12 +543,13 @@ void netCDFLayer::GetNoDataValueForDouble( int nVarId, NCDFNoDataUnion* puNoData
 /*                            GetNoDataValue()                          */
 /************************************************************************/
 
-void netCDFLayer::GetNoDataValue( int nVarId, nc_type nVarType, NCDFNoDataUnion* puNoData )
+void netCDFLayer::GetNoDataValue( int nVarId, nc_type nVarType,
+                                  NCDFNoDataUnion *puNoData )
 {
     if( nVarType == NC_DOUBLE )
-        GetNoDataValueForDouble( nVarId, puNoData );
+        GetNoDataValueForDouble(nVarId, puNoData);
     else if( nVarType == NC_FLOAT )
-        GetNoDataValueForFloat( nVarId, puNoData );
+        GetNoDataValueForFloat(nVarId, puNoData);
 }
 
 /************************************************************************/
@@ -540,8 +562,8 @@ void netCDFLayer::SetXYZVars(int nXVarId, int nYVarId, int nZVarId)
     m_nYVarID = nYVarId;
     m_nZVarID = nZVarId;
 
-    nc_inq_vartype( m_nLayerCDFId, m_nXVarID, &m_nXVarNCDFType );
-    nc_inq_vartype( m_nLayerCDFId, m_nYVarID, &m_nYVarNCDFType );
+    nc_inq_vartype(m_nLayerCDFId, m_nXVarID, &m_nXVarNCDFType);
+    nc_inq_vartype(m_nLayerCDFId, m_nYVarID, &m_nYVarNCDFType);
     if( (m_nXVarNCDFType != NC_FLOAT && m_nXVarNCDFType != NC_DOUBLE) ||
         (m_nYVarNCDFType != NC_FLOAT && m_nYVarNCDFType != NC_DOUBLE) )
     {
@@ -553,62 +575,63 @@ void netCDFLayer::SetXYZVars(int nXVarId, int nYVarId, int nZVarId)
     }
     if( m_nZVarID >= 0 )
     {
-        nc_inq_vartype( m_nLayerCDFId, m_nZVarID, &m_nZVarNCDFType );
+        nc_inq_vartype(m_nLayerCDFId, m_nZVarID, &m_nZVarNCDFType);
         if( m_nZVarNCDFType != NC_FLOAT && m_nZVarNCDFType != NC_DOUBLE )
         {
             CPLError(CE_Warning, CPLE_NotSupported,
-                      "Z variable of type %d not handled", m_nZVarNCDFType);
+                     "Z variable of type %d not handled", m_nZVarNCDFType);
             m_nZVarID = -1;
         }
     }
 
     if( m_nXVarID >= 0 && m_nYVarID >= 0 )
     {
-        char szVarName[NC_MAX_NAME+1];
+        char szVarName[NC_MAX_NAME + 1];
         szVarName[0] = '\0';
-        CPL_IGNORE_RET_VAL(nc_inq_varname( m_nLayerCDFId, m_nXVarID, szVarName ));
+        CPL_IGNORE_RET_VAL(nc_inq_varname(m_nLayerCDFId, m_nXVarID, szVarName));
         m_osCoordinatesValue = szVarName;
 
         szVarName[0] = '\0';
-        CPL_IGNORE_RET_VAL(nc_inq_varname( m_nLayerCDFId, m_nYVarID, szVarName ));
+        CPL_IGNORE_RET_VAL(nc_inq_varname(m_nLayerCDFId, m_nYVarID, szVarName));
         m_osCoordinatesValue += " ";
         m_osCoordinatesValue += szVarName;
 
         if( m_nZVarID >= 0 )
         {
             szVarName[0] = '\0';
-            CPL_IGNORE_RET_VAL(nc_inq_varname( m_nLayerCDFId, m_nZVarID, szVarName ));
+            CPL_IGNORE_RET_VAL(
+                nc_inq_varname(m_nLayerCDFId, m_nZVarID, szVarName));
             m_osCoordinatesValue += " ";
             m_osCoordinatesValue += szVarName;
         }
     }
 
     if( m_nXVarID >= 0 )
-        GetNoDataValue( m_nXVarID, m_nXVarNCDFType, &m_uXVarNoData);
+        GetNoDataValue(m_nXVarID, m_nXVarNCDFType, &m_uXVarNoData);
     if( m_nYVarID >= 0 )
-        GetNoDataValue( m_nYVarID, m_nYVarNCDFType, &m_uYVarNoData);
+        GetNoDataValue(m_nYVarID, m_nYVarNCDFType, &m_uYVarNoData);
     if( m_nZVarID >= 0 )
-        GetNoDataValue( m_nZVarID, m_nZVarNCDFType, &m_uZVarNoData);
+        GetNoDataValue(m_nZVarID, m_nZVarNCDFType, &m_uZVarNoData);
 }
 
 /************************************************************************/
 /*                       SetWKTGeometryField()                          */
 /************************************************************************/
 
-void netCDFLayer::SetWKTGeometryField(const char* pszWKTVarName)
+void netCDFLayer::SetWKTGeometryField(const char *pszWKTVarName)
 {
     m_nWKTVarID = -1;
-    nc_inq_varid( m_nLayerCDFId, pszWKTVarName, &m_nWKTVarID);
+    nc_inq_varid(m_nLayerCDFId, pszWKTVarName, &m_nWKTVarID);
     if( m_nWKTVarID < 0 )
         return;
     int nd;
-    nc_inq_varndims( m_nLayerCDFId, m_nWKTVarID, &nd );
-    nc_inq_vartype( m_nLayerCDFId, m_nWKTVarID, &m_nWKTNCDFType );
+    nc_inq_varndims(m_nLayerCDFId, m_nWKTVarID, &nd);
+    nc_inq_vartype(m_nLayerCDFId, m_nWKTVarID, &m_nWKTNCDFType);
 #ifdef NETCDF_HAS_NC4
     if( nd == 1 && m_nWKTNCDFType == NC_STRING )
     {
         int nDimID;
-        if( nc_inq_vardimid( m_nLayerCDFId, m_nWKTVarID, &nDimID ) != NC_NOERR ||
+        if( nc_inq_vardimid(m_nLayerCDFId, m_nWKTVarID, &nDimID ) != NC_NOERR ||
             nDimID != m_nRecordDimID )
         {
             m_nWKTVarID = -1;
@@ -619,11 +642,11 @@ void netCDFLayer::SetWKTGeometryField(const char* pszWKTVarName)
 #endif
     if (nd == 2 && m_nWKTNCDFType == NC_CHAR )
     {
-        int anDimIds [] = { -1, -1 };
+        int anDimIds [2] = { -1, -1 };
         size_t nLen = 0;
-        if( nc_inq_vardimid( m_nLayerCDFId, m_nWKTVarID, anDimIds ) != NC_NOERR ||
+        if( nc_inq_vardimid(m_nLayerCDFId, m_nWKTVarID, anDimIds) != NC_NOERR ||
             anDimIds[0] != m_nRecordDimID ||
-            nc_inq_dimlen( m_nLayerCDFId, anDimIds[1], &nLen ) != NC_NOERR )
+            nc_inq_dimlen(m_nLayerCDFId, anDimIds[1], &nLen) != NC_NOERR )
         {
             m_nWKTVarID = -1;
             return;
@@ -644,7 +667,7 @@ void netCDFLayer::SetWKTGeometryField(const char* pszWKTVarName)
 /*                          SetGridMapping()                            */
 /************************************************************************/
 
-void netCDFLayer::SetGridMapping(const char* pszGridMapping)
+void netCDFLayer::SetGridMapping(const char *pszGridMapping)
 {
     m_osGridMapping = pszGridMapping;
 }
@@ -659,15 +682,15 @@ void netCDFLayer::SetProfile(int nProfileDimID, int nParentIndexVarID)
     m_nParentIndexVarID = nParentIndexVarID;
     if( m_nProfileDimID >= 0 )
     {
-        char szTemp[NC_MAX_NAME+1];
+        char szTemp[NC_MAX_NAME + 1];
         szTemp[0] = 0;
-        int status = nc_inq_dimname( m_nLayerCDFId, m_nProfileDimID, szTemp);
+        int status = nc_inq_dimname(m_nLayerCDFId, m_nProfileDimID, szTemp);
         NCDF_ERR(status);
         m_osProfileDimName = szTemp;
 
-        nc_inq_varid( m_nLayerCDFId, m_osProfileDimName, &m_nProfileVarID);
-        m_bProfileVarUnlimited = NCDFIsUnlimitedDim(m_poDS->eFormat == NCDF_FORMAT_NC4,
-                                                m_nLayerCDFId, m_nProfileVarID);
+        nc_inq_varid(m_nLayerCDFId, m_osProfileDimName, &m_nProfileVarID);
+        m_bProfileVarUnlimited = NCDFIsUnlimitedDim(
+            m_poDS->eFormat == NCDF_FORMAT_NC4, m_nLayerCDFId, m_nProfileVarID);
     }
 }
 
@@ -675,36 +698,32 @@ void netCDFLayer::SetProfile(int nProfileDimID, int nParentIndexVarID)
 /*                            ResetReading()                            */
 /************************************************************************/
 
-void netCDFLayer::ResetReading()
-{
-    m_nCurFeatureId = 1;
-}
+void netCDFLayer::ResetReading() { m_nCurFeatureId = 1; }
 
 /************************************************************************/
 /*                           Get1DVarAsDouble()                         */
 /************************************************************************/
 
 double netCDFLayer::Get1DVarAsDouble( int nVarId, nc_type nVarType,
-                                      size_t nIndex,
-                                      NCDFNoDataUnion noDataVal,
-                                      bool* pbIsNoData )
+                                      size_t nIndex, NCDFNoDataUnion noDataVal,
+                                      bool *pbIsNoData )
 {
     double dfVal = 0;
     if( nVarType == NC_DOUBLE )
     {
-        nc_get_var1_double( m_nLayerCDFId, nVarId, &nIndex, &dfVal );
-        if( pbIsNoData)
-            *pbIsNoData = ( dfVal == noDataVal.dfVal );
+        nc_get_var1_double(m_nLayerCDFId, nVarId, &nIndex, &dfVal);
+        if( pbIsNoData )
+            *pbIsNoData = dfVal == noDataVal.dfVal;
     }
     else if( nVarType == NC_FLOAT )
     {
         float fVal = 0.f;
-        nc_get_var1_float( m_nLayerCDFId, nVarId, &nIndex, &fVal );
-        if( pbIsNoData)
-            *pbIsNoData = ( fVal == noDataVal.fVal );
+        nc_get_var1_float(m_nLayerCDFId, nVarId, &nIndex, &fVal);
+        if( pbIsNoData )
+            *pbIsNoData = fVal == noDataVal.fVal;
         dfVal = fVal;
     }
-    else if( pbIsNoData)
+    else if( pbIsNoData )
         *pbIsNoData = true;
     return dfVal;
 }
@@ -713,25 +732,25 @@ double netCDFLayer::Get1DVarAsDouble( int nVarId, nc_type nVarType,
 /*                        GetNextRawFeature()                           */
 /************************************************************************/
 
-OGRFeature* netCDFLayer::GetNextRawFeature()
+OGRFeature *netCDFLayer::GetNextRawFeature()
 {
     m_poDS->SetDefineMode(false);
 
     // In update mode, nc_get_varXXX() doesn't return error if we are
     // beyond the end of dimension
     size_t nDimLen = 0;
-    nc_inq_dimlen ( m_nLayerCDFId, m_nRecordDimID, &nDimLen );
+    nc_inq_dimlen(m_nLayerCDFId, m_nRecordDimID, &nDimLen);
     if( m_nCurFeatureId > static_cast<GIntBig>(nDimLen) )
         return NULL;
 
-    OGRFeature* poFeature = new OGRFeature(m_poFeatureDefn);
+    OGRFeature *poFeature = new OGRFeature(m_poFeatureDefn);
 
     if( m_nParentIndexVarID >= 0 )
     {
         int nProfileIdx = 0;
-        size_t nIdx = static_cast<size_t>(m_nCurFeatureId-1);
-        int status = nc_get_var1_int( m_nLayerCDFId, m_nParentIndexVarID,
-                                      &nIdx, &nProfileIdx );
+        size_t nIdx = static_cast<size_t>(m_nCurFeatureId - 1);
+        int status = nc_get_var1_int(m_nLayerCDFId, m_nParentIndexVarID,
+                                     &nIdx, &nProfileIdx);
         if( status == NC_NOERR && nProfileIdx >= 0 )
         {
             nIdx = static_cast<size_t>(nProfileIdx);
@@ -740,15 +759,15 @@ OGRFeature* netCDFLayer::GetNextRawFeature()
     }
 
     if( !FillFeatureFromVar(poFeature, m_nRecordDimID,
-                     static_cast<size_t>(m_nCurFeatureId-1)) )
+                            static_cast<size_t>(m_nCurFeatureId - 1)) )
     {
-        m_nCurFeatureId ++;
+        m_nCurFeatureId++;
         delete poFeature;
         return NULL;
     }
 
     poFeature->SetFID(m_nCurFeatureId);
-    m_nCurFeatureId ++;
+    m_nCurFeatureId++;
 
     return poFeature;
 }
@@ -757,320 +776,311 @@ OGRFeature* netCDFLayer::GetNextRawFeature()
 /*                           FillFeatureFromVar()                       */
 /************************************************************************/
 
-bool netCDFLayer::FillFeatureFromVar(OGRFeature* poFeature, int nMainDimId, size_t nIndex)
+bool netCDFLayer::FillFeatureFromVar(OGRFeature *poFeature, int nMainDimId,
+                                     size_t nIndex)
 {
     size_t anIndex[2];
     anIndex[0] = nIndex;
     anIndex[1] = 0;
 
-    for(int i=0;i<m_poFeatureDefn->GetFieldCount();i++)
+    for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
     {
         if( m_aoFieldDesc[i].nMainDimId != nMainDimId )
             continue;
 
         switch( m_aoFieldDesc[i].nType )
         {
-            case NC_CHAR:
-            {
-                if( m_aoFieldDesc[i].nDimCount == 1 )
-                {
-                    char szVal[] = {0,0};
-                    int status = nc_get_var1_text( m_nLayerCDFId,
-                                        m_aoFieldDesc[i].nVarId,
-                                        anIndex,
-                                        szVal );
-                    if( status != NC_NOERR )
-                    {
-                        NCDF_ERR(status);
-                        continue;
-                    }
-                    poFeature->SetField(i, szVal);
-                }
-                else
-                {
-                    size_t anCount[2];
-                    anCount[0] = 1;
-                    anCount[1] = 0;
-                    nc_inq_dimlen( m_nLayerCDFId, m_aoFieldDesc[i].nSecDimId, &(anCount[1]) );
-                    char* pszVal = (char*) CPLCalloc( 1, anCount[1] + 1 );
-                    int status = nc_get_vara_text( m_nLayerCDFId,
-                                        m_aoFieldDesc[i].nVarId,
-                                        anIndex, anCount,
-                                        pszVal );
-                    if( status != NC_NOERR )
-                    {
-                        NCDF_ERR(status);
-                        CPLFree(pszVal);
-                        continue;
-                    }
-                    poFeature->SetField(i, pszVal);
-                    CPLFree(pszVal);
-                }
-                break;
-            }
-
-#ifdef NETCDF_HAS_NC4
-            case NC_STRING:
+        case NC_CHAR:
+        {
+            if( m_aoFieldDesc[i].nDimCount == 1 )
             {
-                char* pszVal = NULL;
-                int status = nc_get_var1_string( m_nLayerCDFId,
-                                    m_aoFieldDesc[i].nVarId,
-                                    anIndex,
-                                    &pszVal );
+                char szVal[2] = { 0, 0 };
+                int status = nc_get_var1_text(
+                    m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, szVal);
                 if( status != NC_NOERR )
                 {
                     NCDF_ERR(status);
                     continue;
                 }
-                if( pszVal != NULL )
-                {
-                    poFeature->SetField(i, pszVal);
-                    nc_free_string(1, &pszVal);
-                }
-                break;
+                poFeature->SetField(i, szVal);
             }
-#endif
-
-            case NC_BYTE:
+            else
             {
-                signed char chVal = 0;
-                int status = nc_get_var1_schar( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                                anIndex, &chVal );
+                size_t anCount[2];
+                anCount[0] = 1;
+                anCount[1] = 0;
+                nc_inq_dimlen(m_nLayerCDFId, m_aoFieldDesc[i].nSecDimId,
+                              &(anCount[1]));
+                char *pszVal = (char *)CPLCalloc(1, anCount[1] + 1);
+                int status =
+                    nc_get_vara_text(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                     anIndex, anCount, pszVal);
                 if( status != NC_NOERR )
                 {
                     NCDF_ERR(status);
+                    CPLFree(pszVal);
                     continue;
                 }
-                if( chVal == m_aoFieldDesc[i].uNoData.chVal )
-                    continue;
-                poFeature->SetField(i, static_cast<int>(chVal));
-                break;
+                poFeature->SetField(i, pszVal);
+                CPLFree(pszVal);
             }
+            break;
+        }
 
 #ifdef NETCDF_HAS_NC4
-            case NC_UBYTE:
+        case NC_STRING:
+        {
+            char *pszVal = NULL;
+            int status = nc_get_var1_string(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &pszVal);
+            if( status != NC_NOERR )
             {
-                unsigned char uchVal = 0;
-                int status = nc_get_var1_uchar( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                                anIndex, &uchVal );
-                if( status != NC_NOERR )
-                {
-                    NCDF_ERR(status);
-                    continue;
-                }
-                if( uchVal == m_aoFieldDesc[i].uNoData.uchVal )
-                    continue;
-                poFeature->SetField(i, static_cast<int>(uchVal));
-                break;
+                NCDF_ERR(status);
+                continue;
+            }
+            if( pszVal != NULL )
+            {
+                poFeature->SetField(i, pszVal);
+                nc_free_string(1, &pszVal);
             }
+            break;
+        }
 #endif
 
-            case NC_SHORT:
+        case NC_BYTE:
+        {
+            signed char chVal = 0;
+            int status = nc_get_var1_schar(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &chVal);
+            if( status != NC_NOERR )
+            {
+                NCDF_ERR(status);
+                continue;
+            }
+            if( chVal == m_aoFieldDesc[i].uNoData.chVal )
+                continue;
+            poFeature->SetField(i, static_cast<int>(chVal));
+            break;
+        }
+
+#ifdef NETCDF_HAS_NC4
+        case NC_UBYTE:
+        {
+            unsigned char uchVal = 0;
+            int status = nc_get_var1_uchar(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &uchVal);
+            if( status != NC_NOERR )
             {
-                short sVal = 0;
-                int status = nc_get_var1_short( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                    anIndex, &sVal );
+                NCDF_ERR(status);
+                continue;
+            }
+            if( uchVal == m_aoFieldDesc[i].uNoData.uchVal )
+                continue;
+            poFeature->SetField(i, static_cast<int>(uchVal));
+            break;
+        }
+#endif
 
-                if( status != NC_NOERR )
-                {
-                    NCDF_ERR(status);
-                    continue;
-                }
-                if( sVal == m_aoFieldDesc[i].uNoData.sVal )
-                    continue;
-                poFeature->SetField(i, static_cast<int>(sVal));
-                break;
+        case NC_SHORT:
+        {
+            short sVal = 0;
+            int status = nc_get_var1_short(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &sVal);
+
+            if( status != NC_NOERR )
+            {
+                NCDF_ERR(status);
+                continue;
             }
+            if( sVal == m_aoFieldDesc[i].uNoData.sVal )
+                continue;
+            poFeature->SetField(i, static_cast<int>(sVal));
+            break;
+        }
 
 #ifdef NETCDF_HAS_NC4
-            case NC_USHORT:
+        case NC_USHORT:
+        {
+            unsigned short usVal = 0;
+            int status = nc_get_var1_ushort(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &usVal);
+            if( status != NC_NOERR )
             {
-                unsigned short usVal = 0;
-                int status = nc_get_var1_ushort( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                                 anIndex, &usVal );
-                if( status != NC_NOERR )
-                {
-                    NCDF_ERR(status);
-                    continue;
-                }
-                if( usVal == m_aoFieldDesc[i].uNoData.usVal )
-                    continue;
-                poFeature->SetField(i, static_cast<int>(usVal));
-                break;
+                NCDF_ERR(status);
+                continue;
             }
+            if( usVal == m_aoFieldDesc[i].uNoData.usVal )
+                continue;
+            poFeature->SetField(i, static_cast<int>(usVal));
+            break;
+        }
 #endif
 
-            case NC_INT:
+        case NC_INT:
+        {
+            int nVal = 0;
+            int status = nc_get_var1_int(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                         anIndex, &nVal);
+            if( status != NC_NOERR )
             {
-                int nVal = 0;
-                int status = nc_get_var1_int( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                    anIndex, &nVal );
-                if( status != NC_NOERR )
-                {
-                    NCDF_ERR(status);
-                    continue;
-                }
-                if( nVal == m_aoFieldDesc[i].uNoData.nVal )
-                    continue;
-                if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate ||
-                    m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
-                {
-                    struct tm brokendowntime;
-                    GIntBig nVal64 = static_cast<GIntBig>(nVal);
-                    if( m_aoFieldDesc[i].bIsDays )
-                        nVal64 *= 86400;
-                    CPLUnixTimeToYMDHMS( nVal64, &brokendowntime );
-                    poFeature->SetField( i,
-                                        brokendowntime.tm_year + 1900,
-                                        brokendowntime.tm_mon + 1,
-                                        brokendowntime.tm_mday,
-                                        brokendowntime.tm_hour,
-                                        brokendowntime.tm_min,
-                                        static_cast<float>(brokendowntime.tm_sec),
-                                        0);
-                }
-                else
-                {
-                    poFeature->SetField(i, nVal);
-                }
-                break;
+                NCDF_ERR(status);
+                continue;
+            }
+            if( nVal == m_aoFieldDesc[i].uNoData.nVal )
+                continue;
+            if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate ||
+                m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
+            {
+                struct tm brokendowntime;
+                GIntBig nVal64 = static_cast<GIntBig>(nVal);
+                if( m_aoFieldDesc[i].bIsDays )
+                    nVal64 *= 86400;
+                CPLUnixTimeToYMDHMS(nVal64, &brokendowntime);
+                poFeature->SetField(
+                    i, brokendowntime.tm_year + 1900, brokendowntime.tm_mon + 1,
+                    brokendowntime.tm_mday, brokendowntime.tm_hour,
+                    brokendowntime.tm_min,
+                    static_cast<float>(brokendowntime.tm_sec), 0);
+            }
+            else
+            {
+                poFeature->SetField(i, nVal);
             }
+            break;
+        }
 
 #ifdef NETCDF_HAS_NC4
-            case NC_UINT:
+        case NC_UINT:
+        {
+            unsigned int unVal = 0;
+            // nc_get_var1_uint() doesn't work on old netCDF version when
+            // the returned value is > INT_MAX
+            // https://bugtracking.unidata.ucar.edu/browse/NCF-226
+            // nc_get_vara_uint() has not this bug
+            size_t nCount = 1;
+            int status =
+                nc_get_vara_uint(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                 anIndex, &nCount, &unVal);
+            if( status != NC_NOERR )
             {
-                unsigned int unVal = 0;
-                // nc_get_var1_uint() doesn't work on old netCDF version when
-                // the returned value is > INT_MAX
-                // https://bugtracking.unidata.ucar.edu/browse/NCF-226
-                // nc_get_vara_uint() has not this bug
-                size_t nCount = 1;
-                int status = nc_get_vara_uint( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                               anIndex, &nCount, &unVal );
-                if( status != NC_NOERR )
-                {
-                    NCDF_ERR(status);
-                    continue;
-                }
-                if( unVal == m_aoFieldDesc[i].uNoData.unVal )
-                    continue;
-                poFeature->SetField(i, static_cast<GIntBig>(unVal));
-                break;
+                NCDF_ERR(status);
+                continue;
             }
+            if( unVal == m_aoFieldDesc[i].uNoData.unVal )
+                continue;
+            poFeature->SetField(i, static_cast<GIntBig>(unVal));
+            break;
+        }
 #endif
 
 #ifdef NETCDF_HAS_NC4
-            case NC_INT64:
+        case NC_INT64:
+        {
+            GIntBig nVal = 0;
+            int status = nc_get_var1_longlong(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &nVal);
+            if( status != NC_NOERR )
             {
-                GIntBig nVal = 0;
-                int status = nc_get_var1_longlong( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                        anIndex, &nVal );
-                if( status != NC_NOERR )
-                {
-                    NCDF_ERR(status);
-                    continue;
-                }
-                if( nVal == m_aoFieldDesc[i].uNoData.nVal64 )
-                    continue;
-                poFeature->SetField(i, nVal);
-                break;
+                NCDF_ERR(status);
+                continue;
             }
+            if( nVal == m_aoFieldDesc[i].uNoData.nVal64 )
+                continue;
+            poFeature->SetField(i, nVal);
+            break;
+        }
 
-            case NC_UINT64:
+        case NC_UINT64:
+        {
+            GUIntBig nVal = 0;
+            int status = nc_get_var1_ulonglong(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &nVal);
+            if( status != NC_NOERR )
             {
-                GUIntBig nVal = 0;
-                int status = nc_get_var1_ulonglong( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                        anIndex, &nVal );
-                if( status != NC_NOERR )
-                {
-                    NCDF_ERR(status);
-                    continue;
-                }
-                if( nVal == m_aoFieldDesc[i].uNoData.unVal64 )
-                    continue;
-                poFeature->SetField(i, static_cast<double>(nVal));
-                break;
+                NCDF_ERR(status);
+                continue;
             }
+            if( nVal == m_aoFieldDesc[i].uNoData.unVal64 )
+                continue;
+            poFeature->SetField(i, static_cast<double>(nVal));
+            break;
+        }
 #endif
 
-            case NC_FLOAT:
+        case NC_FLOAT:
+        {
+            float fVal = 0.f;
+            int status = nc_get_var1_float(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &fVal);
+            if( status != NC_NOERR )
             {
-                float fVal = 0.f;
-                int status = nc_get_var1_float( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                    anIndex, &fVal );
-                if( status != NC_NOERR )
-                {
-                    NCDF_ERR(status);
-                    continue;
-                }
-                if( fVal == m_aoFieldDesc[i].uNoData.fVal )
-                    continue;
-                poFeature->SetField(i, static_cast<double>(fVal));
-                break;
+                NCDF_ERR(status);
+                continue;
             }
+            if( fVal == m_aoFieldDesc[i].uNoData.fVal )
+                continue;
+            poFeature->SetField(i, static_cast<double>(fVal));
+            break;
+        }
 
-            case NC_DOUBLE:
+        case NC_DOUBLE:
+        {
+            double dfVal = 0.0;
+            int status = nc_get_var1_double(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &dfVal);
+            if( status != NC_NOERR )
             {
-                double dfVal = 0.0;
-                int status = nc_get_var1_double( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                    anIndex, &dfVal );
-                if( status != NC_NOERR )
-                {
-                    NCDF_ERR(status);
-                    continue;
-                }
-                if( dfVal == m_aoFieldDesc[i].uNoData.dfVal )
-                    continue;
-                if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate ||
-                    m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
-                {
-                    if( m_aoFieldDesc[i].bIsDays )
-                        dfVal *= 86400.0;
-                    struct tm brokendowntime;
-                    GIntBig nVal = static_cast<GIntBig>(floor(dfVal));
-                    CPLUnixTimeToYMDHMS( nVal, &brokendowntime );
-                    poFeature->SetField( i,
-                                        brokendowntime.tm_year + 1900,
-                                        brokendowntime.tm_mon + 1,
-                                        brokendowntime.tm_mday,
-                                        brokendowntime.tm_hour,
-                                        brokendowntime.tm_min,
-                                        static_cast<float>(brokendowntime.tm_sec + (dfVal - nVal)),
-                                     0 );
-                }
-                else
-                {
-                    poFeature->SetField(i, dfVal);
-                }
-                break;
+                NCDF_ERR(status);
+                continue;
+            }
+            if( dfVal == m_aoFieldDesc[i].uNoData.dfVal )
+                continue;
+            if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate ||
+                m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
+            {
+                if( m_aoFieldDesc[i].bIsDays )
+                    dfVal *= 86400.0;
+                struct tm brokendowntime;
+                GIntBig nVal = static_cast<GIntBig>(floor(dfVal));
+                CPLUnixTimeToYMDHMS(nVal, &brokendowntime);
+                poFeature->SetField(
+                    i, brokendowntime.tm_year + 1900, brokendowntime.tm_mon + 1,
+                    brokendowntime.tm_mday, brokendowntime.tm_hour,
+                    brokendowntime.tm_min,
+                    static_cast<float>(brokendowntime.tm_sec + (dfVal - nVal)),
+                    0);
             }
+            else
+            {
+                poFeature->SetField(i, dfVal);
+            }
+            break;
+        }
 
-            default:
-                break;
+        default:
+            break;
         }
     }
 
     if( m_nXVarID >= 0 && m_nYVarID >= 0 &&
-        ( m_osProfileDimName.size() == 0 || nMainDimId == m_nProfileDimID ) )
+        (m_osProfileDimName.empty() || nMainDimId == m_nProfileDimID) )
     {
         bool bXIsNoData = false;
-        const double dfX = Get1DVarAsDouble( m_nXVarID, m_nXVarNCDFType,
-                                             anIndex[0], m_uXVarNoData,
-                                             &bXIsNoData );
+        const double dfX = Get1DVarAsDouble(
+            m_nXVarID, m_nXVarNCDFType, anIndex[0], m_uXVarNoData, &bXIsNoData);
         bool bYIsNoData = false;
-        const double dfY = Get1DVarAsDouble( m_nYVarID, m_nYVarNCDFType,
-                                             anIndex[0], m_uYVarNoData,
-                                             &bYIsNoData );
+        const double dfY = Get1DVarAsDouble(
+            m_nYVarID, m_nYVarNCDFType, anIndex[0], m_uYVarNoData, &bYIsNoData);
 
         if( !bXIsNoData && !bYIsNoData )
         {
-            OGRPoint* poPoint;
-            if( m_nZVarID >= 0 && m_osProfileDimName.size() == 0 )
+            OGRPoint *poPoint = NULL;
+            if( m_nZVarID >= 0 && m_osProfileDimName.empty() )
             {
                 bool bZIsNoData = false;
-                const double dfZ = Get1DVarAsDouble( m_nZVarID, m_nZVarNCDFType,
-                                                    anIndex[0], m_uZVarNoData,
-                                                    &bZIsNoData );
+                const double dfZ =
+                    Get1DVarAsDouble(m_nZVarID, m_nZVarNCDFType, anIndex[0],
+                                     m_uZVarNoData, &bZIsNoData);
                 if( bZIsNoData )
                     poPoint = new OGRPoint(dfX, dfY);
                 else
@@ -1078,36 +1088,35 @@ bool netCDFLayer::FillFeatureFromVar(OGRFeature* poFeature, int nMainDimId, size
             }
             else
                 poPoint = new OGRPoint(dfX, dfY);
-            poPoint->assignSpatialReference( GetSpatialRef() );
+            poPoint->assignSpatialReference(GetSpatialRef());
             poFeature->SetGeometryDirectly(poPoint);
         }
     }
     else if( m_nXVarID >= 0 && m_nYVarID >= 0 && m_nZVarID >= 0 &&
-             m_osProfileDimName.size() &&
-             nMainDimId == m_nRecordDimID )
+             !m_osProfileDimName.empty() && nMainDimId == m_nRecordDimID )
     {
-        OGRGeometry* poGeom = poFeature->GetGeometryRef();
+        OGRGeometry *poGeom = poFeature->GetGeometryRef();
         if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
         {
             bool bZIsNoData = false;
-            const double dfZ = Get1DVarAsDouble( m_nZVarID, m_nZVarNCDFType,
-                                                anIndex[0], m_uZVarNoData,
-                                                &bZIsNoData );
+            const double dfZ =
+                Get1DVarAsDouble(m_nZVarID, m_nZVarNCDFType, anIndex[0],
+                                 m_uZVarNoData, &bZIsNoData);
             if( !bZIsNoData )
-                ((OGRPoint*)poGeom)->setZ( dfZ );
+                ((OGRPoint *)poGeom)->setZ(dfZ);
         }
     }
     else if( m_nWKTVarID >= 0 )
     {
-        char* pszWKT = NULL;
+        char *pszWKT = NULL;
         if( m_nWKTNCDFType == NC_CHAR )
         {
             size_t anCount[2];
             anCount[0] = 1;
             anCount[1] = m_nWKTMaxWidth;
-            pszWKT = (char*) CPLCalloc( 1, anCount[1] + 1 );
-            int status = nc_get_vara_text( m_nLayerCDFId, m_nWKTVarID,
-                                           anIndex, anCount, pszWKT );
+            pszWKT = (char *)CPLCalloc(1, anCount[1] + 1);
+            int status = nc_get_vara_text(m_nLayerCDFId, m_nWKTVarID,
+                                          anIndex, anCount, pszWKT);
             if( status == NC_EINVALCOORDS || status == NC_EEDGE )
             {
                 CPLFree(pszWKT);
@@ -1123,9 +1132,9 @@ bool netCDFLayer::FillFeatureFromVar(OGRFeature* poFeature, int nMainDimId, size
 #ifdef NETCDF_HAS_NC4
         else if( m_nWKTNCDFType == NC_STRING )
         {
-            char* pszVal = NULL;
-            int status = nc_get_var1_string( m_nLayerCDFId, m_nWKTVarID,
-                                             anIndex, &pszVal );
+            char *pszVal = NULL;
+            int status = nc_get_var1_string(m_nLayerCDFId, m_nWKTVarID,
+                                            anIndex, &pszVal);
             if( status == NC_EINVALCOORDS || status == NC_EEDGE )
             {
                 return false;
@@ -1143,12 +1152,13 @@ bool netCDFLayer::FillFeatureFromVar(OGRFeature* poFeature, int nMainDimId, size
 #endif
         if( pszWKT != NULL )
         {
-            char* pszWKTTmp = pszWKT;
-            OGRGeometry* poGeom = NULL;
-            CPL_IGNORE_RET_VAL( OGRGeometryFactory::createFromWkt( &pszWKTTmp, NULL, &poGeom ) );
+            char *pszWKTTmp = pszWKT;
+            OGRGeometry *poGeom = NULL;
+            CPL_IGNORE_RET_VAL(
+                OGRGeometryFactory::createFromWkt(&pszWKTTmp, NULL, &poGeom));
             if( poGeom != NULL )
             {
-                poGeom->assignSpatialReference( GetSpatialRef() );
+                poGeom->assignSpatialReference(GetSpatialRef());
                 poFeature->SetGeometryDirectly(poGeom);
             }
             CPLFree(pszWKT);
@@ -1162,20 +1172,18 @@ bool netCDFLayer::FillFeatureFromVar(OGRFeature* poFeature, int nMainDimId, size
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
-OGRFeature* netCDFLayer::GetNextFeature()
+OGRFeature *netCDFLayer::GetNextFeature()
 {
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
         if( (m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
+            || FilterGeometry(poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ))
             && (m_poAttrQuery == NULL
-                || m_poAttrQuery->Evaluate( poFeature )) )
+                || m_poAttrQuery->Evaluate(poFeature)) )
             return poFeature;
 
         delete poFeature;
@@ -1186,42 +1194,39 @@ OGRFeature* netCDFLayer::GetNextFeature()
 /*                            GetLayerDefn()                            */
 /************************************************************************/
 
-OGRFeatureDefn* netCDFLayer::GetLayerDefn()
-{
-    return m_poFeatureDefn;
-}
+OGRFeatureDefn *netCDFLayer::GetLayerDefn() { return m_poFeatureDefn; }
 
 /************************************************************************/
 /*                           ICreateFeature()                           */
 /************************************************************************/
 
-OGRErr netCDFLayer::ICreateFeature(OGRFeature* poFeature)
+OGRErr netCDFLayer::ICreateFeature(OGRFeature *poFeature)
 {
     m_poDS->SetDefineMode(false);
 
     size_t nFeatureIdx = 0;
-    nc_inq_dimlen ( m_nLayerCDFId, m_nRecordDimID, &nFeatureIdx );
+    nc_inq_dimlen(m_nLayerCDFId, m_nRecordDimID, &nFeatureIdx);
 
     if( m_nProfileDimID >= 0 )
     {
         size_t nProfileCount = 0;
-        nc_inq_dimlen ( m_nLayerCDFId, m_nProfileDimID, &nProfileCount );
+        nc_inq_dimlen(m_nLayerCDFId, m_nProfileDimID, &nProfileCount);
 
-        OGRFeature* poProfileToLookup = poFeature->Clone();
+        OGRFeature *poProfileToLookup = poFeature->Clone();
         poProfileToLookup->SetFID(-1);
-        for(int i=0;i<m_poFeatureDefn->GetFieldCount();i++)
+        for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
         {
-            if( !(poProfileToLookup->IsFieldSet(i)) ||
+            if( !(poProfileToLookup->IsFieldSetAndNotNull(i)) ||
                 m_aoFieldDesc[i].nMainDimId != m_nProfileDimID )
             {
                 poProfileToLookup->UnsetField(i);
                 continue;
             }
         }
-        OGRGeometry* poGeom = poProfileToLookup->GetGeometryRef();
+        OGRGeometry *poGeom = poProfileToLookup->GetGeometryRef();
         if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
         {
-            ((OGRPoint*)poGeom)->setZ(0);
+            ((OGRPoint *)poGeom)->setZ(0);
         }
 
         size_t nProfileIdx = 0;
@@ -1229,19 +1234,20 @@ OGRErr netCDFLayer::ICreateFeature(OGRFeature* poFeature)
         for( ; nProfileIdx < nProfileCount; nProfileIdx++ )
         {
             int nId = NC_FILL_INT;
-            int status = nc_get_var1_int( m_nLayerCDFId, m_nProfileVarID,
-                                          &nProfileIdx, &nId );
+            int status = nc_get_var1_int(m_nLayerCDFId, m_nProfileVarID,
+                                         &nProfileIdx, &nId);
             NCDF_ERR(status);
             if( nId == NC_FILL_INT )
                 break;
 
-            OGRFeature* poIterFeature = new OGRFeature(m_poFeatureDefn);
+            OGRFeature *poIterFeature = new OGRFeature(m_poFeatureDefn);
             if( FillFeatureFromVar(poIterFeature, m_nProfileDimID, nProfileIdx) )
             {
                 poGeom = poIterFeature->GetGeometryRef();
-                if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
+                if( poGeom != NULL &&
+                    wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
                 {
-                    ((OGRPoint*)poGeom)->setZ(0);
+                    ((OGRPoint *)poGeom)->setZ(0);
                 }
                 if( poIterFeature->Equal(poProfileToLookup) )
                 {
@@ -1258,29 +1264,31 @@ OGRErr netCDFLayer::ICreateFeature(OGRFeature* poFeature)
             if( !m_bProfileVarUnlimited && nProfileIdx == nProfileCount )
             {
                 size_t nNewSize = 1 + nProfileCount + nProfileCount / 3;
-                m_poDS->GrowDim( m_nLayerCDFId, m_nProfileDimID, nNewSize );
+                m_poDS->GrowDim(m_nLayerCDFId, m_nProfileDimID, nNewSize);
             }
 
-            if( !FillVarFromFeature(poProfileToLookup, m_nProfileDimID, nProfileIdx) )
+            if( !FillVarFromFeature(poProfileToLookup, m_nProfileDimID,
+                                    nProfileIdx) )
             {
                 delete poProfileToLookup;
                 return OGRERR_FAILURE;
             }
         }
 
-        int nProfileIdIdx = m_poFeatureDefn->GetFieldIndex( m_osProfileDimName );
+        int nProfileIdIdx = m_poFeatureDefn->GetFieldIndex(m_osProfileDimName);
         if( nProfileIdIdx < 0 ||
-            m_poFeatureDefn->GetFieldDefn(nProfileIdIdx)->GetType() != OFTInteger )
+            m_poFeatureDefn->GetFieldDefn(nProfileIdIdx)->GetType() !=
+                OFTInteger )
         {
             int nVal = static_cast<int>(nProfileIdx);
-            int status = nc_put_var1_int( m_nLayerCDFId, m_nProfileVarID,
-                                          &nProfileIdx, &nVal );
+            int status = nc_put_var1_int(m_nLayerCDFId, m_nProfileVarID,
+                                         &nProfileIdx, &nVal);
             NCDF_ERR(status);
         }
 
         int nVal = static_cast<int>(nProfileIdx);
-        int status = nc_put_var1_int( m_nLayerCDFId, m_nParentIndexVarID,
-                                      &nFeatureIdx, &nVal );
+        int status = nc_put_var1_int(m_nLayerCDFId, m_nParentIndexVarID,
+                                     &nFeatureIdx, &nVal);
         NCDF_ERR(status);
 
         delete poProfileToLookup;
@@ -1289,7 +1297,7 @@ OGRErr netCDFLayer::ICreateFeature(OGRFeature* poFeature)
     if( !FillVarFromFeature(poFeature, m_nRecordDimID, nFeatureIdx) )
         return OGRERR_FAILURE;
 
-    poFeature->SetFID( nFeatureIdx + 1 );
+    poFeature->SetFID(nFeatureIdx + 1);
 
     return OGRERR_NONE;
 }
@@ -1298,25 +1306,26 @@ OGRErr netCDFLayer::ICreateFeature(OGRFeature* poFeature)
 /*                           FillVarFromFeature()                       */
 /************************************************************************/
 
-bool netCDFLayer::FillVarFromFeature(OGRFeature* poFeature, int nMainDimId, size_t nIndex)
+bool netCDFLayer::FillVarFromFeature(OGRFeature *poFeature, int nMainDimId,
+                                     size_t nIndex)
 {
     size_t anIndex[2];
     anIndex[0] = nIndex;
     anIndex[1] = 0;
 
-    for(int i=0;i<m_poFeatureDefn->GetFieldCount();i++)
+    for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
     {
         if( m_aoFieldDesc[i].nMainDimId != nMainDimId )
             continue;
 
-        if( !(poFeature->IsFieldSet(i)) )
+        if( !(poFeature->IsFieldSetAndNotNull(i)) )
         {
 #ifdef NETCDF_HAS_NC4
             if( m_bNCDumpCompat && m_aoFieldDesc[i].nType == NC_STRING )
             {
-                const char* pszVal =  "";
-                int status = nc_put_var1_string( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                             anIndex, &pszVal );
+                const char *pszVal = "";
+                int status = nc_put_var1_string(
+                    m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &pszVal);
                 NCDF_ERR(status);
             }
 #endif
@@ -1326,282 +1335,299 @@ bool netCDFLayer::FillVarFromFeature(OGRFeature* poFeature, int nMainDimId, size
         int status = NC_NOERR;
         switch( m_aoFieldDesc[i].nType )
         {
-            case NC_CHAR:
+        case NC_CHAR:
+        {
+            const char *pszVal = poFeature->GetFieldAsString(i);
+            if( m_aoFieldDesc[i].nDimCount == 1 )
             {
-                const char* pszVal = poFeature->GetFieldAsString(i);
-                if( m_aoFieldDesc[i].nDimCount == 1 )
+                if( strlen(pszVal) > 1 &&
+                    !m_aoFieldDesc[i].bHasWarnedAboutTruncation )
                 {
-                    if( strlen(pszVal) > 1 && !m_aoFieldDesc[i].bHasWarnedAboutTruncation )
-                    {
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                "Content of field %s exceeded the 1 character limit and will be truncated",
-                                m_poFeatureDefn->GetFieldDefn(i)->GetNameRef());
-                        m_aoFieldDesc[i].bHasWarnedAboutTruncation = true;
-                    }
-                    status = nc_put_var1_text( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                               anIndex, pszVal );
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Content of field %s exceeded the 1 character "
+                             "limit and will be truncated",
+                             m_poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+                    m_aoFieldDesc[i].bHasWarnedAboutTruncation = true;
                 }
-                else
+                status = nc_put_var1_text(
+                    m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, pszVal);
+            }
+            else
+            {
+                size_t anCount[2];
+                anCount[0] = 1;
+                anCount[1] = strlen(pszVal);
+                size_t nWidth = 0;
+                nc_inq_dimlen(m_nLayerCDFId, m_aoFieldDesc[i].nSecDimId,
+                              &nWidth);
+                if( anCount[1] > nWidth )
                 {
-                    size_t anCount[2];
-                    anCount[0] = 1;
-                    anCount[1] = strlen(pszVal);
-                    size_t nWidth = 0;
-                    nc_inq_dimlen( m_nLayerCDFId, m_aoFieldDesc[i].nSecDimId, &nWidth );
-                    if( anCount[1] > nWidth )
+                    if( m_bAutoGrowStrings &&
+                        m_poFeatureDefn->GetFieldDefn(i)->GetWidth() == 0 )
                     {
-                        if( m_bAutoGrowStrings && m_poFeatureDefn->GetFieldDefn(i)->GetWidth() == 0 )
-                        {
-                            size_t nNewSize = anCount[1] + anCount[1] / 3;
+                        size_t nNewSize = anCount[1] + anCount[1] / 3;
 
-                            CPLDebug("GDAL_netCDF", "Growing %s from %u to %u",
-                                    m_poFeatureDefn->GetFieldDefn(i)->GetNameRef(),
-                                    static_cast<unsigned>(nWidth),
-                                    static_cast<unsigned>(nNewSize) );
-                            m_poDS->GrowDim( m_nLayerCDFId, m_aoFieldDesc[i].nSecDimId, nNewSize );
+                        CPLDebug("GDAL_netCDF", "Growing %s from %u to %u",
+                                 m_poFeatureDefn->GetFieldDefn(i)->GetNameRef(),
+                                 static_cast<unsigned>(nWidth),
+                                 static_cast<unsigned>(nNewSize));
+                        m_poDS->GrowDim(m_nLayerCDFId,
+                                        m_aoFieldDesc[i].nSecDimId, nNewSize);
 
-                            pszVal = poFeature->GetFieldAsString(i);
-                        }
-                        else
+                        pszVal = poFeature->GetFieldAsString(i);
+                    }
+                    else
+                    {
+                        anCount[1] = nWidth;
+                        if( !m_aoFieldDesc[i].bHasWarnedAboutTruncation )
                         {
-                            anCount[1] = nWidth;
-                            if( !m_aoFieldDesc[i].bHasWarnedAboutTruncation )
-                            {
-                                CPLError(CE_Warning, CPLE_AppDefined,
-                                         "Content of field %s exceeded the %u character limit and will be truncated",
-                                         m_poFeatureDefn->GetFieldDefn(i)->GetNameRef(),
-                                         static_cast<unsigned int>(nWidth));
-                                m_aoFieldDesc[i].bHasWarnedAboutTruncation = true;
-                            }
+                            CPLError(
+                                CE_Warning, CPLE_AppDefined,
+                                "Content of field %s exceeded the %u character "
+                                "limit and will be truncated",
+                                m_poFeatureDefn->GetFieldDefn(i)->GetNameRef(),
+                                static_cast<unsigned int>(nWidth));
+                            m_aoFieldDesc[i].bHasWarnedAboutTruncation = true;
                         }
                     }
-                    status = nc_put_vara_text( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                                anIndex, anCount, pszVal );
                 }
-                break;
+                status =
+                    nc_put_vara_text(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                     anIndex, anCount, pszVal);
             }
+            break;
+        }
 
 #ifdef NETCDF_HAS_NC4
-            case NC_STRING:
-            {
-                const char* pszVal = poFeature->GetFieldAsString(i);
-                status = nc_put_var1_string( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                             anIndex, &pszVal );
-                break;
-            }
-#endif
-
-            case NC_BYTE:
-            {
-                int nVal = poFeature->GetFieldAsInteger(i);
-                signed char chVal = static_cast<signed char>(nVal);
-                status = nc_put_var1_schar( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                            anIndex, &chVal );
-                break;
-            }
+        case NC_STRING:
+        {
+            const char *pszVal = poFeature->GetFieldAsString(i);
+            status = nc_put_var1_string(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                        anIndex, &pszVal);
+            break;
+        }
+#endif
+
+        case NC_BYTE:
+        {
+            int nVal = poFeature->GetFieldAsInteger(i);
+            signed char chVal = static_cast<signed char>(nVal);
+            status = nc_put_var1_schar(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                       anIndex, &chVal);
+            break;
+        }
 
 #ifdef NETCDF_HAS_NC4
-            case NC_UBYTE:
-            {
-                int nVal = poFeature->GetFieldAsInteger(i);
-                unsigned char uchVal = static_cast<unsigned char>(nVal);
-                status = nc_put_var1_uchar( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                            anIndex, &uchVal );
-                break;
-            }
+        case NC_UBYTE:
+        {
+            int nVal = poFeature->GetFieldAsInteger(i);
+            unsigned char uchVal = static_cast<unsigned char>(nVal);
+            status = nc_put_var1_uchar(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                       anIndex, &uchVal);
+            break;
+        }
 #endif
 
-            case NC_SHORT:
-            {
-                int nVal = poFeature->GetFieldAsInteger(i);
-                short sVal = static_cast<short>(nVal);
-                status = nc_put_var1_short( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                            anIndex, &sVal );
-                break;
-            }
+        case NC_SHORT:
+        {
+            int nVal = poFeature->GetFieldAsInteger(i);
+            short sVal = static_cast<short>(nVal);
+            status = nc_put_var1_short(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                       anIndex, &sVal);
+            break;
+        }
 
 #ifdef NETCDF_HAS_NC4
-            case NC_USHORT:
-            {
-                int nVal = poFeature->GetFieldAsInteger(i);
-                unsigned short usVal = static_cast<unsigned short>(nVal);
-                status = nc_put_var1_ushort( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                            anIndex, &usVal );
-                break;
-            }
+        case NC_USHORT:
+        {
+            int nVal = poFeature->GetFieldAsInteger(i);
+            unsigned short usVal = static_cast<unsigned short>(nVal);
+            status = nc_put_var1_ushort(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                        anIndex, &usVal);
+            break;
+        }
 #endif
 
-            case NC_INT:
+        case NC_INT:
+        {
+            int nVal;
+            if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate )
             {
-                int nVal;
-                if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate )
-                {
-                    int nYear;
-                    int nMonth;
-                    int nDay;
-                    int nHour;
-                    int nMinute;
-                    float fSecond;
-                    int nTZ;
-                    poFeature->GetFieldAsDateTime( i, &nYear, &nMonth, &nDay,
-                                                &nHour, &nMinute, &fSecond, &nTZ );
-                    struct tm brokendowntime;
-                    brokendowntime.tm_year = nYear - 1900;
-                    brokendowntime.tm_mon= nMonth - 1;
-                    brokendowntime.tm_mday = nDay;
-                    brokendowntime.tm_hour = 0;
-                    brokendowntime.tm_min = 0;
-                    brokendowntime.tm_sec = 0;
-                    GIntBig nVal64 = CPLYMDHMSToUnixTime(&brokendowntime);
-                    if( m_aoFieldDesc[i].bIsDays )
-                        nVal64 /= 86400;
-                    nVal = static_cast<int>(nVal64);
-                }
-                else
-                {
-                    nVal = poFeature->GetFieldAsInteger(i);
-                }
-                status = nc_put_var1_int( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                          anIndex, &nVal );
-                break;
+                int nYear;
+                int nMonth;
+                int nDay;
+                int nHour;
+                int nMinute;
+                float fSecond;
+                int nTZ;
+                poFeature->GetFieldAsDateTime(i, &nYear, &nMonth, &nDay,
+                                              &nHour, &nMinute, &fSecond, &nTZ);
+                struct tm brokendowntime;
+                brokendowntime.tm_year = nYear - 1900;
+                brokendowntime.tm_mon = nMonth - 1;
+                brokendowntime.tm_mday = nDay;
+                brokendowntime.tm_hour = 0;
+                brokendowntime.tm_min = 0;
+                brokendowntime.tm_sec = 0;
+                GIntBig nVal64 = CPLYMDHMSToUnixTime(&brokendowntime);
+                if( m_aoFieldDesc[i].bIsDays )
+                    nVal64 /= 86400;
+                nVal = static_cast<int>(nVal64);
             }
-
-#ifdef NETCDF_HAS_NC4
-            case NC_UINT:
+            else
             {
-                GIntBig nVal = poFeature->GetFieldAsInteger64(i);
-                unsigned int unVal = static_cast<unsigned int>(nVal);
-                status = nc_put_var1_uint( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                            anIndex, &unVal );
-                break;
+                nVal = poFeature->GetFieldAsInteger(i);
             }
+            status = nc_put_var1_int(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                     anIndex, &nVal);
+            break;
+        }
+
+#ifdef NETCDF_HAS_NC4
+        case NC_UINT:
+        {
+            GIntBig nVal = poFeature->GetFieldAsInteger64(i);
+            unsigned int unVal = static_cast<unsigned int>(nVal);
+            status = nc_put_var1_uint(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                      anIndex, &unVal);
+            break;
+        }
 #endif
 
 #ifdef NETCDF_HAS_NC4
-            case NC_INT64:
-            {
-                GIntBig nVal = poFeature->GetFieldAsInteger64(i);
-                status = nc_put_var1_longlong( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                               anIndex, &nVal );
-                break;
-            }
+        case NC_INT64:
+        {
+            GIntBig nVal = poFeature->GetFieldAsInteger64(i);
+            status = nc_put_var1_longlong(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &nVal);
+            break;
+        }
 
-            case NC_UINT64:
-            {
-                double dfVal = poFeature->GetFieldAsDouble(i);
-                GUIntBig nVal = static_cast<GUIntBig>(dfVal);
-                status = nc_put_var1_ulonglong( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                                anIndex, &nVal );
-                break;
-            }
+        case NC_UINT64:
+        {
+            double dfVal = poFeature->GetFieldAsDouble(i);
+            GUIntBig nVal = static_cast<GUIntBig>(dfVal);
+            status = nc_put_var1_ulonglong(
+                m_nLayerCDFId, m_aoFieldDesc[i].nVarId, anIndex, &nVal);
+            break;
+        }
 #endif
 
-            case NC_FLOAT:
+        case NC_FLOAT:
+        {
+            double dfVal = poFeature->GetFieldAsDouble(i);
+            float fVal = static_cast<float>(dfVal);
+            status = nc_put_var1_float(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                       anIndex, &fVal);
+            break;
+        }
+
+        case NC_DOUBLE:
+        {
+            double dfVal;
+            if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate ||
+                m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
             {
-                double dfVal = poFeature->GetFieldAsDouble(i);
-                float fVal = static_cast<float>(dfVal);
-                status = nc_put_var1_float( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                            anIndex, &fVal );
-                break;
+                int nYear;
+                int nMonth;
+                int nDay;
+                int nHour;
+                int nMinute;
+                float fSecond;
+                int nTZ;
+                poFeature->GetFieldAsDateTime(i, &nYear, &nMonth, &nDay,
+                                              &nHour, &nMinute, &fSecond, &nTZ);
+                struct tm brokendowntime;
+                brokendowntime.tm_year = nYear - 1900;
+                brokendowntime.tm_mon = nMonth - 1;
+                brokendowntime.tm_mday = nDay;
+                brokendowntime.tm_hour = nHour;
+                brokendowntime.tm_min = nMinute;
+                brokendowntime.tm_sec = static_cast<int>(fSecond);
+                GIntBig nVal = CPLYMDHMSToUnixTime(&brokendowntime);
+                dfVal = static_cast<double>(nVal) + fmod(fSecond, 1.0f);
+                if( m_aoFieldDesc[i].bIsDays )
+                    dfVal /= 86400.0;
             }
-
-            case NC_DOUBLE:
+            else
             {
-                double dfVal;
-                if( m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDate ||
-                    m_poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
-                {
-                    int nYear;
-                    int nMonth;
-                    int nDay;
-                    int nHour;
-                    int nMinute;
-                    float fSecond;
-                    int nTZ;
-                    poFeature->GetFieldAsDateTime( i, &nYear, &nMonth, &nDay,
-                                                &nHour, &nMinute, &fSecond, &nTZ );
-                    struct tm brokendowntime;
-                    brokendowntime.tm_year = nYear - 1900;
-                    brokendowntime.tm_mon= nMonth - 1;
-                    brokendowntime.tm_mday = nDay;
-                    brokendowntime.tm_hour = nHour;
-                    brokendowntime.tm_min = nMinute;
-                    brokendowntime.tm_sec = static_cast<int>(fSecond);
-                    GIntBig nVal = CPLYMDHMSToUnixTime(&brokendowntime);
-                    dfVal = static_cast<double>(nVal) + fmod(fSecond, 1.0f);
-                    if( m_aoFieldDesc[i].bIsDays )
-                        dfVal /= 86400.0;
-                }
-                else
-                {
-                    dfVal = poFeature->GetFieldAsDouble(i);
-                }
-                status = nc_put_var1_double( m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
-                                             anIndex, &dfVal );
-                break;
+                dfVal = poFeature->GetFieldAsDouble(i);
             }
+            status = nc_put_var1_double(m_nLayerCDFId, m_aoFieldDesc[i].nVarId,
+                                        anIndex, &dfVal);
+            break;
+        }
 
-            default:
-                break;
+        default:
+            break;
         }
 
         NCDF_ERR(status);
-        if ( status != NC_NOERR ) {
+        if( status != NC_NOERR )
+        {
             return false;
         }
     }
 
-    OGRGeometry* poGeom = poFeature->GetGeometryRef();
+    OGRGeometry *poGeom = poFeature->GetGeometryRef();
     if( wkbFlatten(m_poFeatureDefn->GetGeomType()) == wkbPoint &&
-        poGeom != NULL &&
-        wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
+        poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
     {
-        if( m_osProfileDimName.size() == 0 || nMainDimId == m_nProfileDimID )
+        if( m_osProfileDimName.empty() || nMainDimId == m_nProfileDimID )
         {
-            double dfX = static_cast<OGRPoint*>(poGeom)->getX();
-            double dfY = static_cast<OGRPoint*>(poGeom)->getY();
+            double dfX = static_cast<OGRPoint *>(poGeom)->getX();
+            double dfY = static_cast<OGRPoint *>(poGeom)->getY();
 
             int status;
 
             if( m_nXVarNCDFType == NC_DOUBLE )
-                status = nc_put_var1_double( m_nLayerCDFId, m_nXVarID, anIndex, &dfX );
+                status =
+                    nc_put_var1_double(m_nLayerCDFId, m_nXVarID, anIndex, &dfX);
             else
             {
                 float fX = static_cast<float>(dfX);
-                status = nc_put_var1_float( m_nLayerCDFId, m_nXVarID, anIndex, &fX );
+                status =
+                    nc_put_var1_float(m_nLayerCDFId, m_nXVarID, anIndex, &fX);
             }
             NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
+            if( status != NC_NOERR )
+            {
                 return false;
             }
 
             if( m_nYVarNCDFType == NC_DOUBLE )
-                status = nc_put_var1_double( m_nLayerCDFId, m_nYVarID, anIndex, &dfY );
+                status =
+                    nc_put_var1_double(m_nLayerCDFId, m_nYVarID, anIndex, &dfY);
             else
             {
                 float fY = static_cast<float>(dfY);
-                status = nc_put_var1_float( m_nLayerCDFId, m_nYVarID, anIndex, &fY );
+                status =
+                    nc_put_var1_float(m_nLayerCDFId, m_nYVarID, anIndex, &fY);
             }
             NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
+            if( status != NC_NOERR )
+            {
                 return false;
             }
         }
 
         if( m_poFeatureDefn->GetGeomType() == wkbPoint25D &&
-            (m_osProfileDimName.size() == 0 || nMainDimId == m_nRecordDimID) )
+            (m_osProfileDimName.empty() || nMainDimId == m_nRecordDimID) )
         {
             int status;
-            double dfZ = static_cast<OGRPoint*>(poGeom)->getZ();
+            double dfZ = static_cast<OGRPoint *>(poGeom)->getZ();
             if( m_nZVarNCDFType == NC_DOUBLE )
-                status = nc_put_var1_double( m_nLayerCDFId, m_nZVarID, anIndex, &dfZ );
+                status =
+                    nc_put_var1_double(m_nLayerCDFId, m_nZVarID, anIndex, &dfZ);
             else
             {
                 float fZ = static_cast<float>(dfZ);
-                status = nc_put_var1_float( m_nLayerCDFId, m_nZVarID, anIndex, &fZ );
+                status =
+                    nc_put_var1_float(m_nLayerCDFId, m_nZVarID, anIndex, &fZ);
             }
             NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
+            if( status != NC_NOERR )
+            {
                 return false;
             }
         }
@@ -1609,15 +1635,15 @@ bool netCDFLayer::FillVarFromFeature(OGRFeature* poFeature, int nMainDimId, size
     else if( m_poFeatureDefn->GetGeomType() != wkbNone && m_nWKTVarID >= 0 &&
              poGeom != NULL )
     {
-        char* pszWKT = NULL;
-        poGeom->exportToWkt( &pszWKT, wkbVariantIso );
+        char *pszWKT = NULL;
+        poGeom->exportToWkt(&pszWKT, wkbVariantIso);
         int status;
 #ifdef NETCDF_HAS_NC4
         if( m_nWKTNCDFType == NC_STRING )
         {
-            const char* pszWKTConst = pszWKT;
-            status = nc_put_var1_string( m_nLayerCDFId, m_nWKTVarID,
-                                         anIndex, &pszWKTConst );
+            const char *pszWKTConst = pszWKT;
+            status = nc_put_var1_string(m_nLayerCDFId, m_nWKTVarID,
+                                        anIndex, &pszWKTConst);
         }
         else
 #endif
@@ -1634,33 +1660,34 @@ bool netCDFLayer::FillVarFromFeature(OGRFeature* poFeature, int nMainDimId, size
                     CPLDebug("GDAL_netCDF", "Growing %s from %u to %u",
                              m_osWKTVarName.c_str(),
                              static_cast<unsigned>(m_nWKTMaxWidth),
-                             static_cast<unsigned>(nNewSize) );
-                    m_poDS->GrowDim( m_nLayerCDFId, m_nWKTMaxWidthDimId, nNewSize );
+                             static_cast<unsigned>(nNewSize));
+                    m_poDS->GrowDim(m_nLayerCDFId, m_nWKTMaxWidthDimId,
+                                    nNewSize);
 
                     m_nWKTMaxWidth = static_cast<int>(nNewSize);
 
-                    status = nc_put_vara_text( m_nLayerCDFId, m_nWKTVarID,
-                                               anIndex, anCount, pszWKT );
+                    status = nc_put_vara_text(m_nLayerCDFId, m_nWKTVarID,
+                                              anIndex, anCount, pszWKT);
                 }
                 else
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
-                            "Cannot write geometry as WKT. Would require %d "
-                            "characters but field width is %d",
-                            static_cast<int>(anCount[1]),
-                            m_nWKTMaxWidth);
+                             "Cannot write geometry as WKT. Would require %d "
+                             "characters but field width is %d",
+                             static_cast<int>(anCount[1]), m_nWKTMaxWidth);
                     status = NC_NOERR;
                 }
             }
             else
             {
-                status = nc_put_vara_text( m_nLayerCDFId, m_nWKTVarID,
-                                           anIndex, anCount, pszWKT );
+                status = nc_put_vara_text(m_nLayerCDFId, m_nWKTVarID,
+                                          anIndex, anCount, pszWKT);
             }
         }
         CPLFree(pszWKT);
         NCDF_ERR(status);
-        if ( status != NC_NOERR ) {
+        if( status != NC_NOERR )
+        {
             return false;
         }
     }
@@ -1668,9 +1695,9 @@ bool netCDFLayer::FillVarFromFeature(OGRFeature* poFeature, int nMainDimId, size
     else if( m_poFeatureDefn->GetGeomType() != wkbNone && m_nWKTVarID >= 0 &&
              poGeom == NULL && m_nWKTNCDFType == NC_STRING && m_bNCDumpCompat )
     {
-        const char* pszWKTConst = "";
-        int status = nc_put_var1_string( m_nLayerCDFId, m_nWKTVarID,
-                                     anIndex, &pszWKTConst );
+        const char *pszWKTConst = "";
+        int status = nc_put_var1_string(m_nLayerCDFId, m_nWKTVarID,
+                                        anIndex, &pszWKTConst);
         NCDF_ERR(status);
     }
 #endif
@@ -1687,12 +1714,12 @@ bool netCDFLayer::AddField(int nVarID)
     if( nVarID == m_nWKTVarID )
         return false;
 
-    char szName[NC_MAX_NAME+1];
+    char szName[NC_MAX_NAME + 1];
     szName[0] = '\0';
-    CPL_IGNORE_RET_VAL(nc_inq_varname( m_nLayerCDFId, nVarID, szName ));
+    CPL_IGNORE_RET_VAL(nc_inq_varname(m_nLayerCDFId, nVarID, szName));
 
-    nc_type vartype=NC_NAT;
-    nc_inq_vartype( m_nLayerCDFId, nVarID, &vartype );
+    nc_type vartype = NC_NAT;
+    nc_inq_vartype(m_nLayerCDFId, nVarID, &vartype);
 
     OGRFieldType eType = OFTString;
     OGRFieldSubType eSubType = OFSTNone;
@@ -1701,190 +1728,193 @@ bool netCDFLayer::AddField(int nVarID)
     NCDFNoDataUnion nodata;
     memset(&nodata, 0, sizeof(nodata));
     int nDimCount = 1;
-    nc_inq_varndims( m_nLayerCDFId, nVarID, &nDimCount );
+    nc_inq_varndims(m_nLayerCDFId, nVarID, &nDimCount);
     int anDimIds[2] = { -1, -1 };
     if( nDimCount <= 2 )
-        nc_inq_vardimid( m_nLayerCDFId, nVarID, anDimIds );
+        nc_inq_vardimid(m_nLayerCDFId, nVarID, anDimIds);
 
     switch( vartype )
     {
-        case NC_BYTE:
-        {
-            eType = OFTInteger;
-            char* pszValue = NULL;
-            if( GetFillValue( nVarID, &pszValue) == CE_None )
-                nodata.chVal = static_cast<signed char>(atoi(pszValue));
-            else
-                nodata.chVal = NC_FILL_BYTE;
-            CPLFree(pszValue);
-            break;
-        }
+    case NC_BYTE:
+    {
+        eType = OFTInteger;
+        char *pszValue = NULL;
+        if( GetFillValue(nVarID, &pszValue) == CE_None )
+            nodata.chVal = static_cast<signed char>(atoi(pszValue));
+        else
+            nodata.chVal = NC_FILL_BYTE;
+        CPLFree(pszValue);
+        break;
+    }
 
 #ifdef NETCDF_HAS_NC4
-        case NC_UBYTE:
-        {
-            eType = OFTInteger;
-            char* pszValue = NULL;
-            if( GetFillValue( nVarID, &pszValue) == CE_None )
-                nodata.uchVal = static_cast<unsigned char>(atoi(pszValue));
-            else
-                nodata.uchVal = NC_FILL_UBYTE;
-            CPLFree(pszValue);
-            break;
-        }
+    case NC_UBYTE:
+    {
+        eType = OFTInteger;
+        char *pszValue = NULL;
+        if( GetFillValue(nVarID, &pszValue) == CE_None )
+            nodata.uchVal = static_cast<unsigned char>(atoi(pszValue));
+        else
+            nodata.uchVal = NC_FILL_UBYTE;
+        CPLFree(pszValue);
+        break;
+    }
 #endif
 
-        case NC_CHAR:
+    case NC_CHAR:
+    {
+        eType = OFTString;
+        if( nDimCount == 1 )
         {
-            eType = OFTString;
-            if( nDimCount == 1 )
-            {
-                nWidth = 1;
-            }
-            else if( nDimCount == 2 )
-            {
-                size_t nDimLen = 0;
-                nc_inq_dimlen( m_nLayerCDFId, anDimIds[1], &nDimLen );
-                nWidth = static_cast<int>(nDimLen);
-            }
-            break;
+            nWidth = 1;
         }
-
-#ifdef NETCDF_HAS_NC4
-        case NC_STRING:
+        else if( nDimCount == 2 )
         {
-            eType = OFTString;
-            break;
+            size_t nDimLen = 0;
+            nc_inq_dimlen(m_nLayerCDFId, anDimIds[1], &nDimLen);
+            nWidth = static_cast<int>(nDimLen);
         }
+        break;
+    }
+
+#ifdef NETCDF_HAS_NC4
+    case NC_STRING:
+    {
+        eType = OFTString;
+        break;
+    }
 #endif
 
-        case NC_SHORT:
-        {
-            eType = OFTInteger;
-            eSubType = OFSTInt16;
-            char* pszValue = NULL;
-            if( GetFillValue( nVarID, &pszValue) == CE_None )
-                nodata.sVal = static_cast<short>(atoi(pszValue));
-            else
-                nodata.sVal = NC_FILL_SHORT;
-            CPLFree(pszValue);
-            break;
-        }
+    case NC_SHORT:
+    {
+        eType = OFTInteger;
+        eSubType = OFSTInt16;
+        char *pszValue = NULL;
+        if( GetFillValue(nVarID, &pszValue) == CE_None )
+            nodata.sVal = static_cast<short>(atoi(pszValue));
+        else
+            nodata.sVal = NC_FILL_SHORT;
+        CPLFree(pszValue);
+        break;
+    }
 
 #ifdef NETCDF_HAS_NC4
-        case NC_USHORT:
-        {
-            eType = OFTInteger;
-            char* pszValue = NULL;
-            if( GetFillValue( nVarID, &pszValue) == CE_None )
-                nodata.usVal = static_cast<unsigned short>(atoi(pszValue));
-            else
-                nodata.usVal = NC_FILL_USHORT;
-            CPLFree(pszValue);
-            break;
-        }
+    case NC_USHORT:
+    {
+        eType = OFTInteger;
+        char *pszValue = NULL;
+        if( GetFillValue(nVarID, &pszValue) == CE_None )
+            nodata.usVal = static_cast<unsigned short>(atoi(pszValue));
+        else
+            nodata.usVal = NC_FILL_USHORT;
+        CPLFree(pszValue);
+        break;
+    }
 #endif
 
-        case NC_INT:
-        {
-            eType = OFTInteger;
-            char* pszValue = NULL;
-            if( GetFillValue( nVarID, &pszValue) == CE_None )
-                nodata.nVal = atoi(pszValue);
-            else
-                nodata.nVal = NC_FILL_INT;
-            CPLFree(pszValue);
-            break;
-        }
+    case NC_INT:
+    {
+        eType = OFTInteger;
+        char *pszValue = NULL;
+        if( GetFillValue(nVarID, &pszValue) == CE_None )
+            nodata.nVal = atoi(pszValue);
+        else
+            nodata.nVal = NC_FILL_INT;
+        CPLFree(pszValue);
+        break;
+    }
 
 #ifdef NETCDF_HAS_NC4
-        case NC_UINT:
-        {
-            eType = OFTInteger64;
-            char* pszValue = NULL;
-            if( GetFillValue( nVarID, &pszValue) == CE_None )
-                nodata.unVal = static_cast<unsigned int>(CPLAtoGIntBig(pszValue));
-            else
-                nodata.unVal = NC_FILL_UINT;
-            CPLFree(pszValue);
-            break;
-        }
+    case NC_UINT:
+    {
+        eType = OFTInteger64;
+        char *pszValue = NULL;
+        if( GetFillValue(nVarID, &pszValue) == CE_None )
+            nodata.unVal = static_cast<unsigned int>(CPLAtoGIntBig(pszValue));
+        else
+            nodata.unVal = NC_FILL_UINT;
+        CPLFree(pszValue);
+        break;
+    }
 #endif
 
 #ifdef NETCDF_HAS_NC4
-        case NC_INT64:
-        {
-            eType = OFTInteger64;
-            char* pszValue = NULL;
-            if( GetFillValue( nVarID, &pszValue) == CE_None )
-                nodata.nVal64 = CPLAtoGIntBig(pszValue);
-            else
-                nodata.nVal64 = NC_FILL_INT64;
-            CPLFree(pszValue);
-            break;
-        }
+    case NC_INT64:
+    {
+        eType = OFTInteger64;
+        char *pszValue = NULL;
+        if( GetFillValue(nVarID, &pszValue) == CE_None )
+            nodata.nVal64 = CPLAtoGIntBig(pszValue);
+        else
+            nodata.nVal64 = NC_FILL_INT64;
+        CPLFree(pszValue);
+        break;
+    }
 
-        case NC_UINT64:
+    case NC_UINT64:
+    {
+        eType = OFTReal;
+        char *pszValue = NULL;
+        if( GetFillValue(nVarID, &pszValue) == CE_None )
         {
-            eType = OFTReal;
-            char* pszValue = NULL;
-            if( GetFillValue( nVarID, &pszValue) == CE_None )
+            nodata.unVal64 = 0;
+            for( int i = 0; pszValue[i] != '\0'; i++ )
             {
-                nodata.unVal64 = 0;
-                for(int i=0; pszValue[i] != '\0'; i++)
-                {
-                    nodata.unVal64 = nodata.unVal64 * 10 + (pszValue[i] - '0');
-                }
+                nodata.unVal64 = nodata.unVal64 * 10 + (pszValue[i] - '0');
             }
-            else
-                nodata.unVal64 = NC_FILL_UINT64;
-            CPLFree(pszValue);
-            break;
         }
+        else
+            nodata.unVal64 = NC_FILL_UINT64;
+        CPLFree(pszValue);
+        break;
+    }
 #endif
 
-        case NC_FLOAT:
-        {
-            eType = OFTReal;
-            eSubType = OFSTFloat32;
-            double dfValue;
-            if( GetFillValue( nVarID, &dfValue) == CE_None )
-                nodata.fVal = static_cast<float>(dfValue);
-            else
-                nodata.fVal = NC_FILL_FLOAT;
-            break;
-        }
+    case NC_FLOAT:
+    {
+        eType = OFTReal;
+        eSubType = OFSTFloat32;
+        double dfValue;
+        if( GetFillValue(nVarID, &dfValue) == CE_None )
+            nodata.fVal = static_cast<float>(dfValue);
+        else
+            nodata.fVal = NC_FILL_FLOAT;
+        break;
+    }
 
-        case NC_DOUBLE:
-        {
-            eType = OFTReal;
-            double dfValue;
-            if( GetFillValue( nVarID, &dfValue) == CE_None )
-                nodata.dfVal = dfValue;
-            else
-                nodata.dfVal = NC_FILL_DOUBLE;
-            break;
-        }
+    case NC_DOUBLE:
+    {
+        eType = OFTReal;
+        double dfValue;
+        if( GetFillValue(nVarID, &dfValue) == CE_None )
+            nodata.dfVal = dfValue;
+        else
+            nodata.dfVal = NC_FILL_DOUBLE;
+        break;
+    }
 
-        default:
-        {
-            CPLDebug("GDAL_netCDF", "Variable %s has type %d, which is unhandled",
-                     szName, vartype);
-            return false;
-        }
+    default:
+    {
+        CPLDebug("GDAL_netCDF", "Variable %s has type %d, which is unhandled",
+                 szName, vartype);
+        return false;
+    }
     }
 
     bool bIsDays = false;
 
-    char* pszValue = NULL;
-    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "ogr_field_type", &pszValue ) == CE_None )
+    char *pszValue = NULL;
+    if( NCDFGetAttr(m_nLayerCDFId, nVarID, "ogr_field_type", &pszValue) ==
+        CE_None )
     {
         if( (eType == OFTInteger || eType == OFTReal) && EQUAL(pszValue, "Date") )
         {
             eType = OFTDate;
+            // cppcheck-suppress knownConditionTrueFalse
             bIsDays = (eType == OFTInteger);
         }
-        else if( (eType == OFTInteger || eType == OFTReal) && EQUAL(pszValue, "DateTime") )
+        else if( (eType == OFTInteger || eType == OFTReal) &&
+                 EQUAL(pszValue, "DateTime") )
             eType = OFTDateTime;
         else if( eType == OFTReal && EQUAL(pszValue, "Integer64") )
             eType = OFTInteger64;
@@ -1894,19 +1924,19 @@ bool netCDFLayer::AddField(int nVarID)
     CPLFree(pszValue);
     pszValue = NULL;
 
-    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "units", &pszValue ) == CE_None )
+    if( NCDFGetAttr(m_nLayerCDFId, nVarID, "units", &pszValue) == CE_None )
     {
         if( (eType == OFTInteger || eType == OFTReal || eType == OFTDate) &&
-                                (EQUAL(pszValue, "seconds since 1970-1-1 0:0:0") ||
-                                 EQUAL(pszValue, "seconds since 1970-01-01 00:00:00")) )
+            (EQUAL(pszValue, "seconds since 1970-1-1 0:0:0") ||
+             EQUAL(pszValue, "seconds since 1970-01-01 00:00:00")) )
         {
             if( eType != OFTDate )
                 eType = OFTDateTime;
             bIsDays = false;
         }
         else if( (eType == OFTInteger || eType == OFTReal || eType == OFTDate) &&
-                    (EQUAL(pszValue, "days since 1970-1-1") ||
-                     EQUAL(pszValue, "days since 1970-01-01")) )
+                 (EQUAL(pszValue, "days since 1970-1-1") ||
+                  EQUAL(pszValue, "days since 1970-01-01")) )
         {
             eType = OFTDate;
             bIsDays = true;
@@ -1915,14 +1945,16 @@ bool netCDFLayer::AddField(int nVarID)
     CPLFree(pszValue);
     pszValue = NULL;
 
-    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "ogr_field_name", &pszValue ) == CE_None )
+    if( NCDFGetAttr(m_nLayerCDFId, nVarID, "ogr_field_name", &pszValue) ==
+        CE_None )
     {
         snprintf(szName, sizeof(szName), "%s", pszValue);
     }
     CPLFree(pszValue);
     pszValue = NULL;
 
-    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "ogr_field_width", &pszValue ) == CE_None )
+    if( NCDFGetAttr(m_nLayerCDFId, nVarID, "ogr_field_width", &pszValue) ==
+        CE_None )
     {
         nWidth = atoi(pszValue);
     }
@@ -1930,7 +1962,8 @@ bool netCDFLayer::AddField(int nVarID)
     pszValue = NULL;
 
     int nPrecision = 0;
-    if( NCDFGetAttr( m_nLayerCDFId, nVarID, "ogr_field_precision", &pszValue ) == CE_None )
+    if( NCDFGetAttr(m_nLayerCDFId, nVarID, "ogr_field_precision", &pszValue) ==
+        CE_None )
     {
         nPrecision = atoi(pszValue);
     }
@@ -1962,30 +1995,31 @@ bool netCDFLayer::AddField(int nVarID)
 /*                             CreateField()                            */
 /************************************************************************/
 
-OGRErr netCDFLayer::CreateField(OGRFieldDefn* poFieldDefn, int /* bApproxOK */)
+OGRErr netCDFLayer::CreateField(OGRFieldDefn *poFieldDefn, int /* bApproxOK */)
 {
     int nSecDimId = -1;
     int nVarID = -1;
     int status;
 
-    const netCDFWriterConfigField* poConfig = NULL;
+    const netCDFWriterConfigField *poConfig = NULL;
     if( m_poDS->oWriterConfig.m_bIsValid )
     {
         std::map<CPLString, netCDFWriterConfigField>::const_iterator oIter;
         if( m_poLayerConfig != NULL &&
-            (oIter = m_poLayerConfig->m_oFields.find( poFieldDefn->GetNameRef() )) !=
-            m_poLayerConfig->m_oFields.end() )
+            (oIter = m_poLayerConfig->m_oFields.find(
+                 poFieldDefn->GetNameRef())) != m_poLayerConfig->m_oFields.end() )
         {
             poConfig = &(oIter->second);
         }
-        else if( (oIter = m_poDS->oWriterConfig.m_oFields.find(  poFieldDefn->GetNameRef() )) !=
+        else if( (oIter = m_poDS->oWriterConfig.m_oFields.find(
+                      poFieldDefn->GetNameRef())) !=
                  m_poDS->oWriterConfig.m_oFields.end() )
         {
             poConfig = &(oIter->second);
         }
     }
 
-    if( m_osProfileDimName.size() &&
+    if( !m_osProfileDimName.empty() &&
         EQUAL(poFieldDefn->GetNameRef(), m_osProfileDimName) &&
         poFieldDefn->GetType() == OFTInteger )
     {
@@ -2006,16 +2040,17 @@ OGRErr netCDFLayer::CreateField(OGRFieldDefn* poFieldDefn, int /* bApproxOK */)
     m_poDS->SetDefineMode(true);
 
     // Try to use the field name as variable name, but detects conflict first
-    CPLString osVarName(( poConfig != NULL ) ? poConfig->m_osNetCDFName :
-                                        CPLString(poFieldDefn->GetNameRef()));
+    CPLString osVarName(poConfig != NULL
+                           ? poConfig->m_osNetCDFName
+                           : CPLString(poFieldDefn->GetNameRef()));
 
-    status = nc_inq_varid( m_nLayerCDFId, osVarName, &nVarID );
+    status = nc_inq_varid(m_nLayerCDFId, osVarName, &nVarID);
     if( status == NC_NOERR )
     {
-        for(int i=1;i<=100;i++)
+        for( int i = 1; i <= 100; i++ )
         {
             osVarName = CPLSPrintf("%s%d", poFieldDefn->GetNameRef(), i);
-            status = nc_inq_varid( m_nLayerCDFId, osVarName, &nVarID );
+            status = nc_inq_varid(m_nLayerCDFId, osVarName, &nVarID);
             if( status != NC_NOERR )
                 break;
         }
@@ -2023,7 +2058,7 @@ OGRErr netCDFLayer::CreateField(OGRFieldDefn* poFieldDefn, int /* bApproxOK */)
                  poFieldDefn->GetNameRef(), osVarName.c_str());
     }
 
-    const char* pszVarName = osVarName.c_str();
+    const char *pszVarName = osVarName.c_str();
 
     NCDFNoDataUnion nodata;
     memset(&nodata, 0, sizeof(nodata));
@@ -2035,25 +2070,25 @@ OGRErr netCDFLayer::CreateField(OGRFieldDefn* poFieldDefn, int /* bApproxOK */)
 
     // Find which is the dimension that this variable should be indexed against
     int nMainDimId = m_nRecordDimID;
-    if( m_osProfileVariables.size() )
+    if( !m_osProfileVariables.empty() )
     {
-        char** papszTokens = CSLTokenizeString2( m_osProfileVariables,",",
-                                                            CSLT_HONOURSTRINGS );
-        if( CSLFindString( papszTokens, poFieldDefn->GetNameRef() ) >= 0 )
+        char **papszTokens =
+            CSLTokenizeString2(m_osProfileVariables, ",", CSLT_HONOURSTRINGS);
+        if( CSLFindString(papszTokens, poFieldDefn->GetNameRef()) >= 0 )
             nMainDimId = m_nProfileDimID;
         CSLDestroy(papszTokens);
     }
-    if( poConfig != NULL && poConfig->m_osMainDim.size() )
+    if( poConfig != NULL && !poConfig->m_osMainDim.empty() )
     {
         int ndims = 0;
-        status = nc_inq_ndims( m_nLayerCDFId, &ndims );
+        status = nc_inq_ndims(m_nLayerCDFId, &ndims);
         NCDF_ERR(status);
         bool bFound = false;
-        for(int idim = 0; idim < ndims; idim ++)
+        for( int idim = 0; idim < ndims; idim++ )
         {
-            char szDimName[NC_MAX_NAME+1];
+            char szDimName[NC_MAX_NAME + 1];
             szDimName[0] = 0;
-            status = nc_inq_dimname( m_poDS->cdfid, idim, szDimName);
+            status = nc_inq_dimname(m_poDS->cdfid, idim, szDimName);
             NCDF_ERR(status);
             if( strcmp(poConfig->m_osMainDim, szDimName) == 0 )
             {
@@ -2064,193 +2099,193 @@ OGRErr netCDFLayer::CreateField(OGRFieldDefn* poFieldDefn, int /* bApproxOK */)
         }
         if( !bFound )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Dimension '%s' does not exist",
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Dimension '%s' does not exist",
                      poConfig->m_osMainDim.c_str());
         }
     }
 
     switch( eType )
     {
-        case OFTString:
-        case OFTStringList:
-        case OFTIntegerList:
-        case OFTRealList:
+    case OFTString:
+    case OFTStringList:
+    case OFTIntegerList:
+    case OFTRealList:
+    {
+        if( poFieldDefn->GetWidth() == 1 )
         {
-            if( poFieldDefn->GetWidth() == 1 )
-            {
-                nType = NC_CHAR;
-                status = nc_def_var( m_nLayerCDFId,
-                                    pszVarName,
-                                    nType, 1, &nMainDimId, &nVarID );
-            }
+            nType = NC_CHAR;
+            status = nc_def_var(m_nLayerCDFId, pszVarName, nType, 1,
+                                &nMainDimId, &nVarID);
+        }
 #ifdef NETCDF_HAS_NC4
-            else if( m_poDS->eFormat == NCDF_FORMAT_NC4 && m_bUseStringInNC4 )
-            {
-                nType = NC_STRING;
-                status = nc_def_var( m_nLayerCDFId,
-                                     pszVarName,
-                                     nType, 1, &nMainDimId, &nVarID );
-            }
+        else if( m_poDS->eFormat == NCDF_FORMAT_NC4 && m_bUseStringInNC4 )
+        {
+            nType = NC_STRING;
+            status = nc_def_var(m_nLayerCDFId, pszVarName, nType, 1,
+                                &nMainDimId, &nVarID);
+        }
 #endif
-            else
+        else
+        {
+            if( poFieldDefn->GetWidth() == 0 && !m_bAutoGrowStrings )
             {
-                if( poFieldDefn->GetWidth() == 0 && !m_bAutoGrowStrings )
-                {
-                    if( m_nDefaultMaxWidthDimId < 0 )
-                    {
-                        status = nc_def_dim( m_nLayerCDFId,
-                                            "string_default_max_width",
-                                            m_nDefaultWidth,
-                                            &m_nDefaultMaxWidthDimId );
-                        NCDF_ERR(status);
-                        if ( status != NC_NOERR ) {
-                            return OGRERR_FAILURE;
-                        }
-                    }
-                    nSecDimId = m_nDefaultMaxWidthDimId;
-                }
-                else
+                if( m_nDefaultMaxWidthDimId < 0 )
                 {
-                    size_t nDim = ( poFieldDefn->GetWidth() == 0 ) ?
-                                    m_nDefaultWidth : poFieldDefn->GetWidth();
-                    status = nc_def_dim( m_nLayerCDFId,
-                                        CPLSPrintf("%s_max_width", pszVarName),
-                                        nDim, &nSecDimId );
+                    status =
+                        nc_def_dim(m_nLayerCDFId, "string_default_max_width",
+                                   m_nDefaultWidth, &m_nDefaultMaxWidthDimId);
                     NCDF_ERR(status);
-                    if ( status != NC_NOERR ) {
+                    if( status != NC_NOERR )
+                    {
                         return OGRERR_FAILURE;
                     }
                 }
-
-                nDimCount = 2;
-                int anDims[] = { nMainDimId, nSecDimId };
-                nType = NC_CHAR;
-                status = nc_def_var( m_nLayerCDFId,
-                                    pszVarName,
-                                    nType, 2, anDims, &nVarID );
+                nSecDimId = m_nDefaultMaxWidthDimId;
             }
-            NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
-                return OGRERR_FAILURE;
+            else
+            {
+                size_t nDim = poFieldDefn->GetWidth() == 0
+                                  ? m_nDefaultWidth
+                                  : poFieldDefn->GetWidth();
+                status = nc_def_dim(m_nLayerCDFId,
+                                    CPLSPrintf("%s_max_width", pszVarName),
+                                    nDim, &nSecDimId);
+                NCDF_ERR(status);
+                if( status != NC_NOERR )
+                {
+                    return OGRERR_FAILURE;
+                }
             }
 
-            break;
+            nDimCount = 2;
+            int anDims[2] = {nMainDimId, nSecDimId};
+            nType = NC_CHAR;
+            status = nc_def_var(m_nLayerCDFId, pszVarName, nType, 2, anDims,
+                                &nVarID);
         }
-
-        case OFTInteger:
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
         {
-            nType = (eSubType == OFSTBoolean) ? NC_BYTE :
-                    (eSubType == OFSTInt16) ?   NC_SHORT :
-                                                NC_INT;
-
-            if( nType == NC_BYTE )
-                nodata.chVal = NC_FILL_BYTE;
-            else if( nType == NC_SHORT )
-                nodata.sVal = NC_FILL_SHORT;
-            else if( nType == NC_INT )
-                nodata.nVal = NC_FILL_INT;
+            return OGRERR_FAILURE;
+        }
 
-            status = nc_def_var( m_nLayerCDFId,
-                                 pszVarName,
-                                 nType, 1, &nMainDimId, &nVarID );
-            NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
-                return OGRERR_FAILURE;
-            }
+        break;
+    }
 
-            if( eSubType == OFSTBoolean )
-            {
-                signed char anRange[] = { 0, 1 };
-                nc_put_att_schar( m_nLayerCDFId,nVarID, "valid_range",
-                                  NC_BYTE, 2, anRange );
-            }
+    case OFTInteger:
+    {
+        nType = eSubType == OFSTBoolean
+                    ? NC_BYTE
+                    : (eSubType == OFSTInt16) ? NC_SHORT : NC_INT;
+
+        if( nType == NC_BYTE )
+            nodata.chVal = NC_FILL_BYTE;
+        else if( nType == NC_SHORT )
+            nodata.sVal = NC_FILL_SHORT;
+        else if( nType == NC_INT )
+            nodata.nVal = NC_FILL_INT;
 
-            break;
+        status = nc_def_var(m_nLayerCDFId, pszVarName, nType, 1, &nMainDimId,
+                            &nVarID);
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
+        {
+            return OGRERR_FAILURE;
         }
 
-        case OFTInteger64:
+        if( eSubType == OFSTBoolean )
         {
-            nType = NC_DOUBLE;
-            nodata.dfVal = NC_FILL_DOUBLE;
-#ifdef NETCDF_HAS_NC4
-            if( m_poDS->eFormat == NCDF_FORMAT_NC4 )
-            {
-                nType = NC_INT64;
-                nodata.nVal64 = NC_FILL_INT64;
-            }
-#endif
-            status = nc_def_var( m_nLayerCDFId,
-                                 pszVarName,
-                                 nType, 1, &nMainDimId, &nVarID );
-            NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
-                return OGRERR_FAILURE;
-            }
-            break;
+            signed char anRange[2] = { 0, 1 };
+            nc_put_att_schar(m_nLayerCDFId, nVarID, "valid_range", NC_BYTE, 2,
+                             anRange);
         }
 
-        case OFTReal:
-        {
-            nType = ( eSubType == OFSTFloat32 ) ? NC_FLOAT : NC_DOUBLE;
-            if( eSubType == OFSTFloat32 )
-                nodata.fVal = NC_FILL_FLOAT;
-            else
-                nodata.dfVal = NC_FILL_DOUBLE;
-            status = nc_def_var( m_nLayerCDFId,
-                                 pszVarName,
-                                 nType, 1, &nMainDimId, &nVarID );
-            NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
-                return OGRERR_FAILURE;
-            }
+        break;
+    }
 
-            break;
+    case OFTInteger64:
+    {
+        nType = NC_DOUBLE;
+        nodata.dfVal = NC_FILL_DOUBLE;
+#ifdef NETCDF_HAS_NC4
+        if( m_poDS->eFormat == NCDF_FORMAT_NC4 )
+        {
+            nType = NC_INT64;
+            nodata.nVal64 = NC_FILL_INT64;
+        }
+#endif
+        status = nc_def_var(m_nLayerCDFId, pszVarName, nType, 1, &nMainDimId,
+                            &nVarID);
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
+        {
+            return OGRERR_FAILURE;
         }
+        break;
+    }
 
-        case OFTDate:
+    case OFTReal:
+    {
+        nType = (eSubType == OFSTFloat32) ? NC_FLOAT : NC_DOUBLE;
+        if( eSubType == OFSTFloat32 )
+            nodata.fVal = NC_FILL_FLOAT;
+        else
+            nodata.dfVal = NC_FILL_DOUBLE;
+        status = nc_def_var(m_nLayerCDFId, pszVarName, nType, 1, &nMainDimId,
+                            &nVarID);
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
         {
-            nType = NC_INT;
-            status = nc_def_var( m_nLayerCDFId,
-                                 pszVarName,
-                                 nType, 1, &nMainDimId, &nVarID );
-            NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
-                return OGRERR_FAILURE;
-            }
-            nodata.nVal = NC_FILL_INT;
+            return OGRERR_FAILURE;
+        }
 
-            status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_UNITS,
-                                      strlen("days since 1970-1-1"),
-                                      "days since 1970-1-1" );
-            NCDF_ERR(status);
+        break;
+    }
 
-            break;
+    case OFTDate:
+    {
+        nType = NC_INT;
+        status = nc_def_var(m_nLayerCDFId, pszVarName, nType, 1, &nMainDimId,
+                            &nVarID);
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
+        {
+            return OGRERR_FAILURE;
         }
+        nodata.nVal = NC_FILL_INT;
 
-        case OFTDateTime:
-        {
-            nType = NC_DOUBLE;
-            status = nc_def_var( m_nLayerCDFId,
-                                 pszVarName,
-                                 nType, 1, &nMainDimId, &nVarID );
-            NCDF_ERR(status);
-            if ( status != NC_NOERR ) {
-                return OGRERR_FAILURE;
-            }
-            nodata.dfVal = NC_FILL_DOUBLE;
+        status = nc_put_att_text(m_nLayerCDFId, nVarID, CF_UNITS,
+                                 strlen("days since 1970-1-1"),
+                                 "days since 1970-1-1");
+        NCDF_ERR(status);
 
-            status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_UNITS,
-                             strlen("seconds since 1970-1-1 0:0:0"),
-                             "seconds since 1970-1-1 0:0:0" );
-            NCDF_ERR(status);
+        break;
+    }
 
-            break;
+    case OFTDateTime:
+    {
+        nType = NC_DOUBLE;
+        status = nc_def_var(m_nLayerCDFId, pszVarName, nType, 1, &nMainDimId,
+                            &nVarID);
+        NCDF_ERR(status);
+        if( status != NC_NOERR )
+        {
+            return OGRERR_FAILURE;
         }
+        nodata.dfVal = NC_FILL_DOUBLE;
 
-        default:
-            return OGRERR_FAILURE;
+        status = nc_put_att_text(m_nLayerCDFId, nVarID, CF_UNITS,
+                                 strlen("seconds since 1970-1-1 0:0:0"),
+                                 "seconds since 1970-1-1 0:0:0");
+        NCDF_ERR(status);
+
+        break;
     }
 
+    default:
+        return OGRERR_FAILURE;
+    }
 
     FieldDesc fieldDesc;
     fieldDesc.uNoData = nodata;
@@ -2263,58 +2298,62 @@ OGRErr netCDFLayer::CreateField(OGRFieldDefn* poFieldDefn, int /* bApproxOK */)
     fieldDesc.bIsDays = (eType == OFTDate);
     m_aoFieldDesc.push_back(fieldDesc);
 
-    const char* pszLongName = CPLSPrintf("Field %s", poFieldDefn->GetNameRef());
-    status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_LNG_NAME,
-                     strlen(pszLongName), pszLongName);
+    const char *pszLongName = CPLSPrintf("Field %s", poFieldDefn->GetNameRef());
+    status = nc_put_att_text(m_nLayerCDFId, nVarID, CF_LNG_NAME,
+                             strlen(pszLongName), pszLongName);
     NCDF_ERR(status);
 
     if( m_bWriteGDALTags )
     {
-        status = nc_put_att_text( m_nLayerCDFId, nVarID, "ogr_field_name",
-                        strlen(poFieldDefn->GetNameRef()), poFieldDefn->GetNameRef());
+        status = nc_put_att_text(m_nLayerCDFId, nVarID, "ogr_field_name",
+                                 strlen(poFieldDefn->GetNameRef()),
+                                 poFieldDefn->GetNameRef());
         NCDF_ERR(status);
 
-        const char* pszType = OGRFieldDefn::GetFieldTypeName(eType);
+        const char *pszType = OGRFieldDefn::GetFieldTypeName(eType);
         if( eSubType != OFSTNone )
         {
             pszType = CPLSPrintf("%s(%s)", pszType,
                                  OGRFieldDefn::GetFieldSubTypeName(eSubType));
         }
-        status = nc_put_att_text( m_nLayerCDFId, nVarID, "ogr_field_type",
-                         strlen(pszType), pszType );
+        status = nc_put_att_text(m_nLayerCDFId, nVarID, "ogr_field_type",
+                                 strlen(pszType), pszType);
         NCDF_ERR(status);
 
         const int nWidth = poFieldDefn->GetWidth();
-        if( nWidth || nType == NC_CHAR )
+        if(nWidth || nType == NC_CHAR)
         {
-            status = nc_put_att_int( m_nLayerCDFId, nVarID, "ogr_field_width",
-                            NC_INT, 1, &nWidth );
+            status = nc_put_att_int(m_nLayerCDFId, nVarID, "ogr_field_width",
+                                    NC_INT, 1, &nWidth);
             NCDF_ERR(status);
 
             const int nPrecision = poFieldDefn->GetPrecision();
             if( nPrecision )
             {
-                status = nc_put_att_int( m_nLayerCDFId, nVarID, "ogr_field_precision",
-                                NC_INT, 1, &nPrecision );
+                status =
+                    nc_put_att_int(m_nLayerCDFId, nVarID, "ogr_field_precision",
+                                   NC_INT, 1, &nPrecision);
                 NCDF_ERR(status);
             }
         }
     }
 
-    //nc_put_att_text( m_nLayerCDFId, nVarID, CF_UNITS,
+    // nc_put_att_text(m_nLayerCDFId, nVarID, CF_UNITS,
     //                 strlen("none"), "none");
 
-    if( m_osGridMapping.size() != 0 && nMainDimId == m_nRecordDimID )
+    if( !m_osGridMapping.empty() && nMainDimId == m_nRecordDimID )
     {
-        status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_GRD_MAPPING,
-                         m_osGridMapping.size(), m_osGridMapping.c_str() );
+        status =
+            nc_put_att_text(m_nLayerCDFId, nVarID, CF_GRD_MAPPING,
+                            m_osGridMapping.size(), m_osGridMapping.c_str());
         NCDF_ERR(status);
     }
 
-    if( m_osCoordinatesValue.size() && nMainDimId == m_nRecordDimID )
+    if( !m_osCoordinatesValue.empty() && nMainDimId == m_nRecordDimID )
     {
-        status = nc_put_att_text( m_nLayerCDFId, nVarID, CF_COORDINATES,
-                        m_osCoordinatesValue.size(), m_osCoordinatesValue.c_str() );
+        status = nc_put_att_text(m_nLayerCDFId, nVarID, CF_COORDINATES,
+                                 m_osCoordinatesValue.size(),
+                                 m_osCoordinatesValue.c_str());
         NCDF_ERR(status);
     }
 
@@ -2337,7 +2376,7 @@ GIntBig netCDFLayer::GetFeatureCount(int bForce)
     if( m_poFilterGeom == NULL && m_poAttrQuery == NULL )
     {
         size_t nDimLen;
-        nc_inq_dimlen ( m_nLayerCDFId, m_nRecordDimID, &nDimLen );
+        nc_inq_dimlen(m_nLayerCDFId, m_nRecordDimID, &nDimLen);
         return static_cast<GIntBig>(nDimLen);
     }
     return OGRLayer::GetFeatureCount(bForce);
@@ -2347,13 +2386,13 @@ GIntBig netCDFLayer::GetFeatureCount(int bForce)
 /*                          TestCapability()                            */
 /************************************************************************/
 
-int netCDFLayer::TestCapability(const char* pszCap)
+int netCDFLayer::TestCapability(const char *pszCap)
 {
     if( EQUAL(pszCap, OLCSequentialWrite) )
         return m_poDS->GetAccess() == GA_Update;
     if( EQUAL(pszCap, OLCCreateField) )
         return m_poDS->GetAccess() == GA_Update;
     if( EQUAL(pszCap, OLCFastFeatureCount) )
-        return( m_poFilterGeom == NULL && m_poAttrQuery == NULL );
+        return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
     return FALSE;
 }
diff --git a/frmts/netcdf/netcdfwriterconfig.cpp b/frmts/netcdf/netcdfwriterconfig.cpp
index a3a0c8c..015088c 100644
--- a/frmts/netcdf/netcdfwriterconfig.cpp
+++ b/frmts/netcdf/netcdfwriterconfig.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: netcdfwriterconfig.cpp 33500 2016-02-18 12:01:47Z rouault $
  *
  * Project:  netCDF read/write Driver
  * Purpose:  GDAL bindings over netCDF library.
@@ -29,13 +28,13 @@
 
 #include "netcdfdataset.h"
 
-CPL_CVSID("$Id: netcdfwriterconfig.cpp 33500 2016-02-18 12:01:47Z rouault $");
+CPL_CVSID("$Id: netcdfwriterconfig.cpp 37982 2017-04-13 17:30:17Z goatbar $");
 
-bool netCDFWriterConfiguration::SetNameValue(CPLXMLNode* psNode,
-                                             std::map<CPLString,CPLString>& oMap)
+bool netCDFWriterConfiguration::SetNameValue(
+    CPLXMLNode *psNode, std::map<CPLString, CPLString> &oMap)
 {
-    const char* pszName = CPLGetXMLValue(psNode, "name", NULL);
-    const char* pszValue = CPLGetXMLValue(psNode, "value", NULL);
+    const char *pszName = CPLGetXMLValue(psNode, "name", NULL);
+    const char *pszValue = CPLGetXMLValue(psNode, "value", NULL);
     if( pszName != NULL && pszValue != NULL )
     {
         oMap[pszName] = pszValue;
@@ -45,19 +44,18 @@ bool netCDFWriterConfiguration::SetNameValue(CPLXMLNode* psNode,
     return false;
 }
 
-bool netCDFWriterConfiguration::Parse(const char* pszFilename)
+bool netCDFWriterConfiguration::Parse(const char *pszFilename)
 {
-    CPLXMLNode* psRoot;
-    if( STARTS_WITH(pszFilename, "<Configuration") )
-        psRoot = CPLParseXMLString(pszFilename);
-    else
-        psRoot = CPLParseXMLFile(pszFilename);
+    CPLXMLNode *psRoot =
+        STARTS_WITH(pszFilename, "<Configuration")
+        ? CPLParseXMLString(pszFilename)
+        : CPLParseXMLFile(pszFilename);
     if( psRoot == NULL )
         return false;
     CPLXMLTreeCloser oCloser(psRoot);
 
-    for(CPLXMLNode* psIter = psRoot->psChild;
-                    psIter != NULL; psIter = psIter->psNext )
+    for( CPLXMLNode *psIter = psRoot->psChild; psIter != NULL;
+         psIter = psIter->psNext )
     {
         if( psIter->eType != CXT_Element )
             continue;
@@ -79,7 +77,10 @@ bool netCDFWriterConfiguration::Parse(const char* pszFilename)
         {
             netCDFWriterConfigField oField;
             if( oField.Parse(psIter) )
-                m_oFields[oField.m_osName.size() ? oField.m_osName : CPLString("__") +  oField.m_osNetCDFName] = oField;
+                m_oFields[!oField.m_osName.empty()
+                              ? oField.m_osName
+                              : CPLString("__") + oField.m_osNetCDFName] =
+                    oField;
         }
         else if( EQUAL(psIter->pszValue, "Layer") )
         {
@@ -88,7 +89,9 @@ bool netCDFWriterConfiguration::Parse(const char* pszFilename)
                 m_oLayers[oLayer.m_osName] = oLayer;
         }
         else
+        {
             CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
+        }
     }
 
     m_bIsValid = true;
@@ -96,14 +99,16 @@ bool netCDFWriterConfiguration::Parse(const char* pszFilename)
     return true;
 }
 
-bool netCDFWriterConfigAttribute::Parse(CPLXMLNode* psNode)
+bool netCDFWriterConfigAttribute::Parse(CPLXMLNode *psNode)
 {
-    const char* pszName = CPLGetXMLValue(psNode, "name", NULL);
-    const char* pszValue = CPLGetXMLValue(psNode, "value", NULL);
-    const char* pszType = CPLGetXMLValue(psNode, "type", "string");
-    if( !EQUAL(pszType, "string") && !EQUAL(pszType, "integer") && !EQUAL(pszType, "double") )
+    const char *pszName = CPLGetXMLValue(psNode, "name", NULL);
+    const char *pszValue = CPLGetXMLValue(psNode, "value", NULL);
+    const char *pszType = CPLGetXMLValue(psNode, "type", "string");
+    if( !EQUAL(pszType, "string") && !EQUAL(pszType, "integer") &&
+        !EQUAL(pszType, "double") )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "type='%s' unsupported", pszType);
+        CPLError(CE_Failure, CPLE_NotSupported, "type='%s' unsupported",
+                 pszType);
         return false;
     }
     if( pszName == NULL || pszValue == NULL )
@@ -117,14 +122,15 @@ bool netCDFWriterConfigAttribute::Parse(CPLXMLNode* psNode)
     return true;
 }
 
-bool netCDFWriterConfigField::Parse(CPLXMLNode* psNode)
+bool netCDFWriterConfigField::Parse(CPLXMLNode *psNode)
 {
-    const char* pszName = CPLGetXMLValue(psNode, "name", NULL);
-    const char* pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
-    const char* pszMainDim = CPLGetXMLValue(psNode, "main_dim", NULL);
+    const char *pszName = CPLGetXMLValue(psNode, "name", NULL);
+    const char *pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
+    const char *pszMainDim = CPLGetXMLValue(psNode, "main_dim", NULL);
     if( pszName == NULL && pszNetCDFName == NULL )
     {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Bot name and netcdf_name are missing");
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "Bot name and netcdf_name are missing");
         return false;
     }
     if( pszName != NULL )
@@ -134,8 +140,8 @@ bool netCDFWriterConfigField::Parse(CPLXMLNode* psNode)
     if( pszMainDim != NULL )
         m_osMainDim = pszMainDim;
 
-    for(CPLXMLNode* psIter = psNode->psChild;
-                    psIter != NULL; psIter = psIter->psNext )
+    for( CPLXMLNode *psIter = psNode->psChild; psIter != NULL;
+         psIter = psIter->psNext )
     {
         if( psIter->eType != CXT_Element )
             continue;
@@ -146,17 +152,19 @@ bool netCDFWriterConfigField::Parse(CPLXMLNode* psNode)
                 m_aoAttributes.push_back(oAtt);
         }
         else
+        {
             CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
+        }
     }
 
     return true;
 }
 
-bool netCDFWriterConfigLayer::Parse(CPLXMLNode* psNode)
+bool netCDFWriterConfigLayer::Parse(CPLXMLNode *psNode)
 {
-    const char* pszName = CPLGetXMLValue(psNode, "name", NULL);
-    const char* pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
-    if( pszName == NULL  )
+    const char *pszName = CPLGetXMLValue(psNode, "name", NULL);
+    const char *pszNetCDFName = CPLGetXMLValue(psNode, "netcdf_name", pszName);
+    if( pszName == NULL )
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Missing name");
         return false;
@@ -165,14 +173,15 @@ bool netCDFWriterConfigLayer::Parse(CPLXMLNode* psNode)
     if( pszNetCDFName != NULL )
         m_osNetCDFName = pszNetCDFName;
 
-    for(CPLXMLNode* psIter = psNode->psChild;
-                    psIter != NULL; psIter = psIter->psNext )
+    for( CPLXMLNode *psIter = psNode->psChild; psIter != NULL;
+         psIter = psIter->psNext )
     {
         if( psIter->eType != CXT_Element )
             continue;
         if( EQUAL(psIter->pszValue, "LayerCreationOption") )
         {
-            netCDFWriterConfiguration::SetNameValue(psIter, m_oLayerCreationOptions);
+            netCDFWriterConfiguration::SetNameValue(psIter,
+                                                    m_oLayerCreationOptions);
         }
         else if( EQUAL(psIter->pszValue, "Attribute") )
         {
@@ -184,10 +193,15 @@ bool netCDFWriterConfigLayer::Parse(CPLXMLNode* psNode)
         {
             netCDFWriterConfigField oField;
             if( oField.Parse(psIter) )
-                m_oFields[oField.m_osName.size() ? oField.m_osName : CPLString("__") +  oField.m_osNetCDFName] = oField;
+                m_oFields[!oField.m_osName.empty()
+                              ? oField.m_osName
+                              : CPLString("__") + oField.m_osNetCDFName] =
+                    oField;
         }
         else
+        {
             CPLDebug("GDAL_netCDF", "Ignoring %s", psIter->pszValue);
+        }
     }
 
     return true;
diff --git a/frmts/ngsgeoid/ngsgeoiddataset.cpp b/frmts/ngsgeoid/ngsgeoiddataset.cpp
index 429960e..e09e9ee 100644
--- a/frmts/ngsgeoid/ngsgeoiddataset.cpp
+++ b/frmts/ngsgeoid/ngsgeoiddataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ngsgeoiddataset.cpp 32538 2015-12-30 13:12:08Z rouault $
  *
  * Project:  NGSGEOID driver
  * Purpose:  GDALDataset driver for NGSGEOID dataset.
@@ -33,7 +32,7 @@
 #include "gdal_pam.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ngsgeoiddataset.cpp 32538 2015-12-30 13:12:08Z rouault $");
+CPL_CVSID("$Id: ngsgeoiddataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 #define HEADER_SIZE (4 * 8 + 3 * 4)
 
@@ -63,8 +62,8 @@ class NGSGEOIDDataset : public GDALPamDataset
                  NGSGEOIDDataset();
     virtual     ~NGSGEOIDDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char* GetProjectionRef();
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char* GetProjectionRef() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -81,15 +80,12 @@ class NGSGEOIDRasterBand : public GDALPamRasterBand
     friend class NGSGEOIDDataset;
 
   public:
-
                 explicit NGSGEOIDRasterBand( NGSGEOIDDataset * );
 
-    virtual CPLErr IReadBlock( int, int, void * );
-
-    virtual const char* GetUnitType() { return "m"; }
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual const char* GetUnitType() override { return "m"; }
 };
 
-
 /************************************************************************/
 /*                        NGSGEOIDRasterBand()                          */
 /************************************************************************/
@@ -97,8 +93,8 @@ class NGSGEOIDRasterBand : public GDALPamRasterBand
 NGSGEOIDRasterBand::NGSGEOIDRasterBand( NGSGEOIDDataset *poDSIn )
 
 {
-    this->poDS = poDSIn;
-    this->nBand = 1;
+    poDS = poDSIn;
+    nBand = 1;
 
     eDataType = GDT_Float32;
 
@@ -321,7 +317,6 @@ int NGSGEOIDDataset::Identify( GDALOpenInfo * poOpenInfo )
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -375,7 +370,7 @@ GDALDataset *NGSGEOIDDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Support overviews.                                              */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -387,7 +382,7 @@ CPLErr NGSGEOIDDataset::GetGeoTransform( double * padfTransform )
 {
     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
diff --git a/frmts/nitf/ecrgtocdataset.cpp b/frmts/nitf/ecrgtocdataset.cpp
index b461d0f..7c9d3e0 100644
--- a/frmts/nitf/ecrgtocdataset.cpp
+++ b/frmts/nitf/ecrgtocdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ecrgtocdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  ECRG TOC read Translator
  * Purpose:  Implementation of ECRGTOCDataset and ECRGTOCSubDataset.
@@ -29,15 +28,30 @@
 
 // g++ -g -Wall -fPIC frmts/nitf/ecrgtocdataset.cpp -shared -o gdal_ECRGTOC.so -Iport -Igcore -Iogr -Ifrmts/vrt -L. -lgdal
 
+#include "cpl_port.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
 #include "gdal_proxy.h"
 #include "ogr_srs_api.h"
 #include "vrtdataset.h"
 
-#include <vector>
-
-CPL_CVSID("$Id: ecrgtocdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
+CPL_CVSID("$Id: ecrgtocdataset.cpp 37346 2017-02-11 23:03:44Z goatbar $");
 
 /** Overview of used classes :
    - ECRGTOCDataset : lists the different subdatasets, listed in the .xml,
@@ -63,7 +77,7 @@ typedef struct
 
 class ECRGTOCDataset : public GDALPamDataset
 {
-  char	    **papszSubDatasets;
+  char      **papszSubDatasets;
   double      adfGeoTransform[6];
 
   char      **papszFileList;
@@ -73,6 +87,7 @@ class ECRGTOCDataset : public GDALPamDataset
     {
         papszSubDatasets = NULL;
         papszFileList = NULL;
+        memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
     }
 
     virtual ~ECRGTOCDataset()
@@ -81,22 +96,22 @@ class ECRGTOCDataset : public GDALPamDataset
         CSLDestroy(papszFileList);
     }
 
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
 
-    virtual char      **GetFileList() { return CSLDuplicate(papszFileList); }
+    virtual char      **GetFileList() override { return CSLDuplicate(papszFileList); }
 
     void                AddSubDataset(const char* pszFilename,
                                       const char* pszProductTitle,
                                       const char* pszDiscId,
                                       const char* pszScale);
 
-    virtual CPLErr GetGeoTransform( double * padfGeoTransform)
+    virtual CPLErr GetGeoTransform( double * padfGeoTransform) override
     {
         memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
         return CE_None;
     }
 
-    virtual const char *GetProjectionRef(void)
+    virtual const char *GetProjectionRef(void) override
     {
         return SRS_WKT_WGS84;
     }
@@ -141,7 +156,7 @@ class ECRGTOCSubDataset : public VRTDataset
         CSLDestroy(papszFileList);
     }
 
-    virtual char      **GetFileList() { return CSLDuplicate(papszFileList); }
+    virtual char      **GetFileList() override { return CSLDuplicate(papszFileList); }
 
     static GDALDataset* Build(  const char* pszProductTitle,
                                 const char* pszDiscId,
@@ -182,7 +197,7 @@ void ECRGTOCDataset::AddSubDataset( const char* pszFilename,
                                     const char* pszScale)
 
 {
-    char	szName[80];
+    char szName[80];
     const int nCount = CSLCount(papszSubDatasets ) / 2;
 
     snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
@@ -407,16 +422,15 @@ class ECRGTOCProxyRasterDataSet : public GDALProxyPoolDataset
     double dfMaxY;
     double dfPixelXSize;
     double dfPixelYSize;
-    ECRGTOCSubDataset* poSubDataset;
 
     public:
-        ECRGTOCProxyRasterDataSet(ECRGTOCSubDataset* poSubDataset,
-                                  const char* fileName,
-                                  int nXSize, int nYSize,
-                                  double dfMinX, double dfMaxY,
-                                  double dfPixelXSize, double dfPixelYSize);
+        ECRGTOCProxyRasterDataSet( ECRGTOCSubDataset* /* poSubDataset */,
+                                   const char* fileName,
+                                   int nXSize, int nYSize,
+                                   double dfMinX, double dfMaxY,
+                                   double dfPixelXSize, double dfPixelYSize );
 
-        GDALDataset* RefUnderlyingDataset()
+        GDALDataset* RefUnderlyingDataset() override
         {
             GDALDataset* poSourceDS = GDALProxyPoolDataset::RefUnderlyingDataset();
             if (poSourceDS)
@@ -432,7 +446,7 @@ class ECRGTOCProxyRasterDataSet : public GDALProxyPoolDataset
             return poSourceDS;
         }
 
-        void UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset)
+        void UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset) override
         {
             GDALProxyPoolDataset::UnrefUnderlyingDataset(poUnderlyingDataset);
         }
@@ -444,26 +458,28 @@ class ECRGTOCProxyRasterDataSet : public GDALProxyPoolDataset
 /*                    ECRGTOCProxyRasterDataSet()                       */
 /************************************************************************/
 
-ECRGTOCProxyRasterDataSet::ECRGTOCProxyRasterDataSet
-        (ECRGTOCSubDataset* poSubDatasetIn,
-         const char* fileNameIn,
-         int nXSizeIn, int nYSizeIn,
-         double dfMinXIn, double dfMaxYIn,
-         double dfPixelXSizeIn, double dfPixelYSizeIn) :
-    /* Mark as shared since the VRT will take several references if we are in RGBA mode (4 bands for this dataset) */
-    GDALProxyPoolDataset(fileNameIn, nXSizeIn, nYSizeIn, GA_ReadOnly, TRUE, SRS_WKT_WGS84),
+ECRGTOCProxyRasterDataSet::ECRGTOCProxyRasterDataSet(
+    ECRGTOCSubDataset* /* poSubDatasetIn */,
+    const char* fileNameIn,
+    int nXSizeIn, int nYSizeIn,
+    double dfMinXIn, double dfMaxYIn,
+    double dfPixelXSizeIn, double dfPixelYSizeIn ) :
+    // Mark as shared since the VRT will take several references if we are in
+    // RGBA mode (4 bands for this dataset).
+    GDALProxyPoolDataset(fileNameIn, nXSizeIn, nYSizeIn, GA_ReadOnly,
+                         TRUE, SRS_WKT_WGS84),
     checkDone(FALSE),
-    checkOK(FALSE)
+    checkOK(FALSE),
+    dfMinX(dfMinXIn),
+    dfMaxY(dfMaxYIn),
+    dfPixelXSize(dfPixelXSizeIn),
+    dfPixelYSize(dfPixelYSizeIn)
 {
-    this->poSubDataset = poSubDatasetIn;
-    this->dfMinX = dfMinXIn;
-    this->dfMaxY = dfMaxYIn;
-    this->dfPixelXSize = dfPixelXSizeIn;
-    this->dfPixelYSize = dfPixelYSizeIn;
 
-    for(int i=0;i<3;i++)
+    for( int i = 0; i < 3; i++ )
     {
-        SetBand(i + 1, new GDALProxyPoolRasterBand(this, i+1, GDT_Byte, nXSizeIn, 1));
+        SetBand(i + 1,
+                new GDALProxyPoolRasterBand(this, i+1, GDT_Byte, nXSizeIn, 1));
     }
 }
 
@@ -471,15 +487,19 @@ ECRGTOCProxyRasterDataSet::ECRGTOCProxyRasterDataSet
 /*                    SanityCheckOK()                                   */
 /************************************************************************/
 
-#define WARN_CHECK_DS(x) do { if (!(x)) { CPLError(CE_Warning, CPLE_AppDefined,\
-    "For %s, assert '" #x "' failed", GetDescription()); checkOK = FALSE; } } while(0)
+#define WARN_CHECK_DS(x) do { if (!(x)) { \
+    CPLError(CE_Warning, CPLE_AppDefined,                             \
+             "For %s, assert '" #x "' failed",                        \
+             GetDescription()); checkOK = FALSE; } } while( false )
 
-int ECRGTOCProxyRasterDataSet::SanityCheckOK(GDALDataset* poSourceDS)
+int ECRGTOCProxyRasterDataSet::SanityCheckOK( GDALDataset* poSourceDS )
 {
-    /*int nSrcBlockXSize, nSrcBlockYSize;
-    int nBlockXSize, nBlockYSize;*/
-    double l_adfGeoTransform[6];
-    if (checkDone)
+    // int nSrcBlockXSize;
+    // int nSrcBlockYSize;
+    // int nBlockXSize;
+    // int nBlockYSize;
+    double l_adfGeoTransform[6] = {};
+    if( checkDone )
         return checkOK;
 
     checkOK = TRUE;
@@ -491,16 +511,18 @@ int ECRGTOCProxyRasterDataSet::SanityCheckOK(GDALDataset* poSourceDS)
     WARN_CHECK_DS(fabs(l_adfGeoTransform[1] - dfPixelXSize) < 1e-10);
     WARN_CHECK_DS(fabs(l_adfGeoTransform[5] - (-dfPixelYSize)) < 1e-10);
     WARN_CHECK_DS(l_adfGeoTransform[2] == 0 &&
-                  l_adfGeoTransform[4] == 0); /* No rotation */
+                  l_adfGeoTransform[4] == 0);  // No rotation.
     WARN_CHECK_DS(poSourceDS->GetRasterCount() == 3);
     WARN_CHECK_DS(poSourceDS->GetRasterXSize() == nRasterXSize);
     WARN_CHECK_DS(poSourceDS->GetRasterYSize() == nRasterYSize);
     WARN_CHECK_DS(EQUAL(poSourceDS->GetProjectionRef(), SRS_WKT_WGS84));
-    /*poSourceDS->GetRasterBand(1)->GetBlockSize(&nSrcBlockXSize, &nSrcBlockYSize);
-    GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
-    WARN_CHECK_DS(nSrcBlockXSize == nBlockXSize);
-    WARN_CHECK_DS(nSrcBlockYSize == nBlockYSize);*/
-    WARN_CHECK_DS(poSourceDS->GetRasterBand(1)->GetRasterDataType() == GDT_Byte);
+    // poSourceDS->GetRasterBand(1)->GetBlockSize(&nSrcBlockXSize,
+    //                                            &nSrcBlockYSize);
+    // GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    // WARN_CHECK_DS(nSrcBlockXSize == nBlockXSize);
+    // WARN_CHECK_DS(nSrcBlockYSize == nBlockYSize);
+    WARN_CHECK_DS(
+        poSourceDS->GetRasterBand(1)->GetRasterDataType() == GDT_Byte);
 
     return checkOK;
 }
@@ -513,7 +535,7 @@ static const char* BuildFullName(const char* pszTOCFilename,
                                  const char* pszFramePath,
                                  const char* pszFrameName)
 {
-    char* pszPath;
+    char* pszPath = NULL;
     if (pszFramePath[0] == '.' &&
         (pszFramePath[1] == '/' ||pszFramePath[1] == '\\'))
         pszPath = CPLStrdup(pszFramePath + 2);
@@ -616,8 +638,12 @@ GDALDataset* ECRGTOCSubDataset::Build(  const char* pszProductTitle,
                                             aosFrameDesc[i].pszPath,
                                             aosFrameDesc[i].pszName);
 
-        double dfMinX = 0, dfMaxX = 0, dfMinY = 0, dfMaxY = 0,
-               dfPixelXSize = 0, dfPixelYSize = 0;
+        double dfMinX = 0.0;
+        double dfMaxX = 0.0;
+        double dfMinY = 0.0;
+        double dfMaxY = 0.0;
+        double dfPixelXSize = 0.0;
+        double dfPixelYSize = 0.0;
         GetExtent(aosFrameDesc[i].pszName,
                   aosFrameDesc[i].nScale, aosFrameDesc[i].nZone,
                   dfMinX, dfMaxX, dfMinY, dfMaxY, dfPixelXSize, dfPixelYSize);
@@ -684,14 +710,18 @@ GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename,
         return NULL;
     }
 
-    double dfGlobalMinX = 0, dfGlobalMinY = 0, dfGlobalMaxX = 0, dfGlobalMaxY= 0;
-    double dfGlobalPixelXSize = 0, dfGlobalPixelYSize = 0;
+    double dfGlobalMinX = 0.0;
+    double dfGlobalMinY = 0.0;
+    double dfGlobalMaxX = 0.0;
+    double dfGlobalMaxY = 0.0;
+    double dfGlobalPixelXSize = 0.0;
+    double dfGlobalPixelYSize = 0.0;
     bool bGlobalExtentValid = false;
 
     ECRGTOCDataset* poDS = new ECRGTOCDataset();
     int nSubDatasets = 0;
 
-    int bLookForSubDataset = osProduct.size() != 0 && osDiscId.size() != 0;
+    int bLookForSubDataset = !osProduct.empty() && !osDiscId.empty();
 
     int nCountSubDataset = 0;
 
@@ -772,7 +802,7 @@ GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename,
 
                 if( bLookForSubDataset )
                 {
-                    if( osScale.size() )
+                    if( !osScale.empty() )
                     {
                         if( strcmp(LaunderString(pszSize), osScale.c_str()) != 0 )
                         {
@@ -883,9 +913,12 @@ GDALDataset* ECRGTOCDataset::Build(const char* pszTOCFilename,
                         continue;
                     }
 
-                    double dfMinX = 0, dfMaxX = 0,
-                           dfMinY = 0, dfMaxY = 0,
-                           dfPixelXSize = 0, dfPixelYSize = 0;
+                    double dfMinX = 0.0;
+                    double dfMaxX = 0.0;
+                    double dfMinY = 0.0;
+                    double dfMaxY = 0.0;
+                    double dfPixelXSize = 0.0;
+                    double dfPixelYSize = 0.0;
                     if (!GetExtent(pszFrameName, nScale, nZone,
                                    dfMinX, dfMaxX, dfMinY, dfMaxY,
                                    dfPixelXSize, dfPixelYSize))
diff --git a/frmts/nitf/frmt_nitf.html b/frmts/nitf/frmt_nitf.html
index 8d79d3c..bfdf0e9 100644
--- a/frmts/nitf/frmt_nitf.html
+++ b/frmts/nitf/frmt_nitf.html
@@ -26,7 +26,11 @@ the higher precision coordinates of BLOCKA are used if the block data covers
 the complete image - that is the L_LINES field with the row count for that
 block is equal to the row count of the image. Additionally, all BLOCKA
 instances are returned as metadata. If GeoSDE TRE are available, they will be
-used to provide higher precision coordinates.
+used to provide higher precision coordinates. If the RPC00B (or RPC00A) TRE is
+available, it is used to report RPC metadata. Starting with GDAL 2.2, RPC
+information can be retrieved from _rpc.txt files, and they will be used in
+priority over internal RPC00B values, since the latter have less precision
+than the ones stored in external _rpc.txt.
 <p>
 
 Most file header and image header fields are returned as dataset level
@@ -105,9 +109,9 @@ two variations supported are "NITF02.10" (the default), and "NSIF01.00". <p>
 each output band. (Only needed for
 Create() method, not CreateCopy()).<p>
 
-<li> <b>IREPBAND</b>: (GDAL >= 1.9.0) Comma separated list of band IREPBANDs in band order.<p>
+<li> <b>IREPBAND</b>: (GDAL >= 1.9.0) Comma separated list of band IREPBANDs in band order.<p>
 
-<li> <b>ISUBCAT</b>: (GDAL >= 1.9.0) Comma separated list of band ISUBCATs in band order.<p>
+<li> <b>ISUBCAT</b>: (GDAL >= 1.9.0) Comma separated list of band ISUBCATs in band order.<p>
 
 <li> <b>LUT_SIZE</b>: Set to control the size of pseudocolor tables for
 RGB/LUT bands.  A value of 256 assumed if not present. (Only needed for
@@ -133,12 +137,22 @@ tre-name should be at most six characters, and the tre-contents should be
 "backslash escaped" if it contains backslashes or zero bytes.  The argument
 is the same format as returned in the TRE metadata domain when reading.<p>
 
-<li> <b>FILE_TRE=tre-name=tre-contents</b>: (GDAL >= 1.8.0) Similar to above options,
+<li> <b>FILE_TRE=tre-name=tre-contents</b>: (GDAL >= 1.8.0) Similar to above options,
 except that the TREs are written in the file header, instead of the image header.<p>
 
-<li> <b>SDE_TRE=YES/NO</b>: (GDAL >= 1.8.0) Write GEOLOB and GEOPSB TREs to get
+<li> <b>SDE_TRE=YES/NO</b>: (GDAL >= 1.8.0) Write GEOLOB and GEOPSB TREs to get
 more precise georeferencing. This is limited to geographic SRS, and to CreateCopy() for now.<p>
 
+<li> <b>RPC00B=YES/NO</b>: (GDAL >= 2.2.0) Write RPC00B TRE, from a source
+RPC00B TRE if it exists (NITF to NITF conversion), or from values found in the
+RPC metadata domain. This is only taken into account by CreateCopy() for now.
+Note that the NITF RPC00B format uses limited prevision ASCII encoded numbers.
+Default to YES.<p>
+
+<li> <b>RPCTXT=YES/NO</b>: (GDAL >= 2.2.0) Whether to write RPC metadata
+in a external _rpc.txt file. This may be useful since internal RPC00B TRE have
+limited precision. This is only taken into account by CreateCopy() for now.
+Default to NO.<p>
 </ul>
 
 
diff --git a/frmts/nitf/mgrs.c b/frmts/nitf/mgrs.c
index d0944e2..26dde50 100644
--- a/frmts/nitf/mgrs.c
+++ b/frmts/nitf/mgrs.c
@@ -1,5 +1,5 @@
 /***************************************************************************
- * $Id: mgrs.c 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: mgrs.c 36456 2016-11-22 23:34:00Z rouault $
  *
  * Project:  MGRS Converter
  * Purpose:  Geotrans code for MGRS translation (slightly adapted)
@@ -176,9 +176,12 @@ static const char* const BESSEL_1841_NAMIBIA = "BN";
 
 typedef struct Latitude_Band_Value
 {
+  /* cppcheck-suppress unusedStructMember */
   long letter;            /* letter representing latitude band  */
   double min_northing;    /* minimum northing for latitude band */
+  /* cppcheck-suppress unusedStructMember */
   double north;           /* upper latitude for latitude band   */
+  /* cppcheck-suppress unusedStructMember */
   double south;           /* lower latitude for latitude band   */
 } Latitude_Band;
 
@@ -207,6 +210,7 @@ static const Latitude_Band Latitude_Band_Table[20] =
 
 typedef struct UPS_Constant_Value
 {
+  /* cppcheck-suppress unusedStructMember */
   long letter;            /* letter representing latitude band      */
   long ltr2_low_value;    /* 2nd letter range - high number         */
   long ltr2_high_value;   /* 2nd letter range - low number          */
@@ -740,7 +744,7 @@ long Convert_UTM_To_MGRS (long Zone,
 { /* Convert_UTM_To_MGRS */
   double latitude;           /* Latitude of UTM point */
   double longitude;          /* Longitude of UTM point */
-  long temp_error = MGRS_NO_ERROR;
+  /*long temp_error = MGRS_NO_ERROR; */
   long error_code = MGRS_NO_ERROR;
 
   if ((Zone < 1) || (Zone > 60))
@@ -756,14 +760,14 @@ long Convert_UTM_To_MGRS (long Zone,
   if (!error_code)
   {
     Set_UTM_Parameters (MGRS_a, MGRS_f, 0);
-    temp_error = Convert_UTM_To_Geodetic (Zone, Hemisphere, Easting, Northing, &latitude, &longitude);
+    /*temp_error =*/ Convert_UTM_To_Geodetic (Zone, Hemisphere, Easting, Northing, &latitude, &longitude);
 
 	  /* Special check for rounding to (truncated) eastern edge of zone 31V */
 	  if ((Zone == 31) && (latitude >= 56.0 * DEG_TO_RAD) && (latitude < 64.0 * DEG_TO_RAD) &&
         (longitude >= 3.0 * DEG_TO_RAD))
 	  { /* Reconvert to UTM zone 32 */
       Set_UTM_Parameters (MGRS_a, MGRS_f, 32);
-      temp_error = Convert_Geodetic_To_UTM (latitude, longitude, &Zone, &Hemisphere, &Easting, &Northing);
+      /*temp_error =*/ Convert_Geodetic_To_UTM (latitude, longitude, &Zone, &Hemisphere, &Easting, &Northing);
 	  }
 
 	  error_code = UTM_To_MGRS (Zone, latitude, Easting, Northing, Precision, MGRS);
@@ -917,7 +921,7 @@ long Convert_UPS_To_MGRS (char   Hemisphere,
   double grid_easting;        /* Easting used to derive 2nd letter of MGRS    */
   double grid_northing;       /* Northing used to derive 3rd letter of MGRS   */
   long ltr2_low_value;        /* 2nd letter range - low number                */
-  int letters[MGRS_LETTERS];  /* Number location of 3 letters in alphabet     */
+  int letters[MGRS_LETTERS] = { 0 };  /* Number location of 3 letters in alphabet     */
   double divisor;
   int l_index = 0;
   long error_code = MGRS_NO_ERROR;
diff --git a/frmts/nitf/mgrs.h b/frmts/nitf/mgrs.h
index 31b82cd..1f3a8f2 100644
--- a/frmts/nitf/mgrs.h
+++ b/frmts/nitf/mgrs.h
@@ -2,7 +2,7 @@
   #define MGRS_H
 
 /***************************************************************************
- * $Id: mgrs.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: mgrs.h 35897 2016-10-24 11:54:24Z goatbar $
  *
  * Project:  MGRS Converter
  * Purpose:  Geotrans declarations for MGRS translation (slightly adapted)
@@ -35,7 +35,7 @@
  *                                    inclusive.
  *          MGRS_A_ERROR           : Semi-major axis less than or equal to zero
  *          MGRS_INV_F_ERROR       : Inverse flattening outside of valid range
- *									                  (250 to 350)
+ *                                    (250 to 350)
  *          MGRS_EASTING_ERROR     : Easting outside of valid range
  *                                    (100,000 to 900,000 meters for UTM)
  *                                    (0 to 4,000,000 meters for UPS)
@@ -82,7 +82,6 @@
  *
  */
 
-
 /***************************************************************************/
 /*
  *                              DEFINES
@@ -100,7 +99,6 @@
   #define MGRS_ZONE_ERROR              0x0100
   #define MGRS_HEMISPHERE_ERROR        0x0200
 
-
 /***************************************************************************/
 /*
  *                              FUNCTION PROTOTYPES
@@ -122,11 +120,10 @@ extern "C" {
  * are returned by the function, otherwise MGRS_NO_ERROR is returned.
  *
  *   a                : Semi-major axis of ellipsoid in meters (input)
- *   f                : Flattening of ellipsoid					       (input)
+ *   f                : Flattening of ellipsoid                (input)
  *   Ellipsoid_Code   : 2-letter code for ellipsoid            (input)
  */
 
-
   void Get_MGRS_Parameters(double *a,
                            double *f,
                            char   *Ellipsoid_Code);
@@ -135,11 +132,10 @@ extern "C" {
  * parameters.
  *
  *  a                : Semi-major axis of ellipsoid, in meters (output)
- *  f                : Flattening of ellipsoid					       (output)
+ *  f                : Flattening of ellipsoid                 (output)
  *  Ellipsoid_Code   : 2-letter code for ellipsoid             (output)
  */
 
-
   long Convert_Geodetic_To_MGRS (double Latitude,
                                  double Longitude,
                                  long   Precision,
@@ -157,7 +153,6 @@ extern "C" {
  *
  */
 
-
   long Convert_MGRS_To_Geodetic (char *MGRS,
                                  double *Latitude,
                                  double *Longitude);
@@ -172,7 +167,6 @@ extern "C" {
  *
  */
 
-
   long Convert_UTM_To_MGRS (long Zone,
                             char Hemisphere,
                             double Easting,
@@ -193,7 +187,6 @@ extern "C" {
  *    MGRS       : MGRS coordinate string           (output)
  */
 
-
   long Convert_MGRS_To_UTM (char   *MGRS,
                             long   *Zone,
                             char   *Hemisphere,
@@ -213,8 +206,6 @@ extern "C" {
  *    Northing   : Northing (Y) in meters           (output)
  */
 
-
-
   long Convert_UPS_To_MGRS ( char   Hemisphere,
                              double Easting,
                              double Northing,
@@ -235,7 +226,6 @@ extern "C" {
  *    MGRS          : MGRS coordinate string           (output)
  */
 
-
   long Convert_MGRS_To_UPS ( char   *MGRS,
                              char   *Hemisphere,
                              double *Easting,
@@ -252,8 +242,6 @@ extern "C" {
  *    Northing      : Northing/Y in meters             (output)
  */
 
-
-
   #ifdef __cplusplus
 }
   #endif
diff --git a/frmts/nitf/nitf_gcprpc.cpp b/frmts/nitf/nitf_gcprpc.cpp
index d950659..b6a1833 100644
--- a/frmts/nitf/nitf_gcprpc.cpp
+++ b/frmts/nitf/nitf_gcprpc.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: nitf_gcprpc.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  GCP / RPC Georeferencing Model (custom by/for ESRI)
@@ -27,10 +26,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_priv.h"
+#include "cpl_port.h"
 #include "nitflib.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: nitf_gcprpc.cpp 37346 2017-02-11 23:03:44Z goatbar $");
 
 /* Unused in normal builds. Caller code in nitfdataset.cpp is protected by #ifdef ESRI_BUILD */
 #ifdef ESRI_BUILD
@@ -105,7 +105,6 @@ void NITFDensifyGCPs( GDAL_GCP **psGCPs, int *pnGCPCount )
             psDensifiedGCPs[count+3].dfGCPY = yRightPt;
 
             count += *pnGCPCount;
-
         }
         catch (...)
         {
@@ -140,7 +139,8 @@ static bool RPCTransform( NITFRPC00BInfo *psRPCInfo,
                           int             nGCPCount )
 {
     if( (psRPCInfo == NULL) || (pGCPXCoord == NULL) ||
-        (pGCPYCoord == NULL) || (nGCPCount <= 0) ) return (false);
+        (pGCPYCoord == NULL) || (nGCPCount <= 0) )
+        return false;
 
     bool   ok = true;
     double H  = 0.0;
@@ -174,7 +174,7 @@ static bool RPCTransform( NITFRPC00BInfo *psRPCInfo,
         }
     }
 
-    return (ok);
+    return ok;
 }
 
 /************************************************************************/
diff --git a/frmts/nitf/nitfaridpcm.cpp b/frmts/nitf/nitfaridpcm.cpp
index aebfd2e..41508e8 100644
--- a/frmts/nitf/nitfaridpcm.cpp
+++ b/frmts/nitf/nitfaridpcm.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: nitfaridpcm.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  ARIDPCM reading code.
@@ -28,11 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_conv.h"
-#include "gdal.h"
+#include "cpl_port.h"
 #include "nitflib.h"
 
-CPL_CVSID("$Id: nitfaridpcm.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+#include <cstring>
+
+#include "gdal.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+
+CPL_CVSID("$Id: nitfaridpcm.cpp 37346 2017-02-11 23:03:44Z goatbar $");
 
 static const int neighbourhood_size_75[4] = { 23, 47, 74, 173 };
 static const int bits_per_level_by_busycode_75[4/*busy code*/][4/*level*/] = {
diff --git a/frmts/nitf/nitfbilevel.cpp b/frmts/nitf/nitfbilevel.cpp
index 7cc3bf8..986e649 100644
--- a/frmts/nitf/nitfbilevel.cpp
+++ b/frmts/nitf/nitfbilevel.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: nitfbilevel.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module implement BILEVEL (C1) compressed image reading.
@@ -28,19 +27,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "nitflib.h"
+
+#include <cstring>
+
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "gdal.h"
-#include "nitflib.h"
-
+// #include "tiff.h"
 CPL_C_START
 #include "tiffio.h"
 CPL_C_END
-
 #include "tifvsi.h"
 
-CPL_CVSID("$Id: nitfbilevel.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: nitfbilevel.cpp 37346 2017-02-11 23:03:44Z goatbar $");
 
 /************************************************************************/
 /*                       NITFUncompressBILEVEL()                        */
diff --git a/frmts/nitf/nitfdataset.cpp b/frmts/nitf/nitfdataset.cpp
index a9b103f..427ef1c 100644
--- a/frmts/nitf/nitfdataset.cpp
+++ b/frmts/nitf/nitfdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: nitfdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  NITFDataset and driver related implementations.
@@ -31,12 +30,38 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "nitfdataset.h"
+
+#include "gdal_mdreader.h"
+
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
-#include "nitfdataset.h"
+#include "gdal_priv.h"
+#include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: nitfdataset.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: nitfdataset.cpp 37346 2017-02-11 23:03:44Z goatbar $");
 
 static bool NITFPatchImageLength( const char *pszFilename,
                                   GUIntBig nImageOffset,
@@ -65,11 +90,22 @@ static void SetBandMetadata( NITFImage *psImage, GDALRasterBand *poBand, int nBa
 /************************************************************************/
 
 NITFDataset::NITFDataset() :
-    psFile(NULL), psImage(NULL), poJ2KDataset(NULL), bJP2Writing(FALSE),
-    poJPEGDataset(NULL), bGotGeoTransform(FALSE), nGCPCount(0),
-    pasGCPList(NULL), pszGCPProjection(NULL), panJPEGBlockOffset(NULL),
-    pabyJPEGBlock(NULL), nQLevel(0), nIMIndex(0), papszTextMDToWrite(NULL),
-    papszCgmMDToWrite(NULL), bInLoadXML(FALSE),
+    psFile(NULL),
+    psImage(NULL),
+    poJ2KDataset(NULL),
+    bJP2Writing(FALSE),
+    poJPEGDataset(NULL),
+    bGotGeoTransform(FALSE),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    pszGCPProjection(NULL),
+    panJPEGBlockOffset(NULL),
+    pabyJPEGBlock(NULL),
+    nQLevel(0),
+    nIMIndex(0),
+    papszTextMDToWrite(NULL),
+    papszCgmMDToWrite(NULL),
+    bInLoadXML(FALSE),
     bExposeUnderlyingJPEGDatasetOverviews(FALSE)
 {
     pszProjection = CPLStrdup("");
@@ -331,7 +367,7 @@ static char **ExtractEsriMD( char **papszMD )
         papszEsriMD = CSLAddNameValue( papszEsriMD, pEsriMDSunElevation,      pSunElevation );
     }
 
-    return (papszEsriMD);
+    return papszEsriMD;
 }
 
 /************************************************************************/
@@ -419,8 +455,8 @@ int NITFDataset::Identify( GDALOpenInfo * poOpenInfo )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
-/*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/
+/*      First we check to see if the file has the expected header       */
+/*      bytes.                                                          */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 4 )
         return FALSE;
@@ -900,7 +936,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
         CPLFree( poDS->pszProjection );
         poDS->pszProjection = NULL;
 
-        oSRSWork.SetUTM( ABS(psImage->nZone), psImage->nZone > 0 );
+        oSRSWork.SetUTM( std::abs(psImage->nZone), psImage->nZone > 0 );
         oSRSWork.SetWellKnownGeogCS( "WGS84" );
         oSRSWork.exportToWkt( &(poDS->pszProjection) );
     }
@@ -929,12 +965,10 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
             fpHDR = VSIFOpenL( pszHDR, "rt" );
         }
 
-        char **papszLines;
-
         if( fpHDR != NULL )
         {
             CPL_IGNORE_RET_VAL(VSIFCloseL( fpHDR ));
-            papszLines=CSLLoad2(pszHDR, 16, 200, NULL);
+            char **papszLines = CSLLoad2(pszHDR, 16, 200, NULL);
             if (CSLCount(papszLines) == 16)
             {
 
@@ -1121,8 +1155,8 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 
         if( psImage->bIsBoxCenterOfPixel )
         {
-            psGCPs[0].dfGCPPixel	= 0.5;
-            psGCPs[0].dfGCPLine		= 0.5;
+            psGCPs[0].dfGCPPixel = 0.5;
+            psGCPs[0].dfGCPLine = 0.5;
             psGCPs[1].dfGCPPixel = poDS->nRasterXSize-0.5;
             psGCPs[1].dfGCPLine = 0.5;
             psGCPs[2].dfGCPPixel = poDS->nRasterXSize-0.5;
@@ -1132,8 +1166,8 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
         }
         else
         {
-            psGCPs[0].dfGCPPixel	= 0.0;
-            psGCPs[0].dfGCPLine		= 0.0;
+            psGCPs[0].dfGCPPixel = 0.0;
+            psGCPs[0].dfGCPLine = 0.0;
             psGCPs[1].dfGCPPixel = poDS->nRasterXSize;
             psGCPs[1].dfGCPLine = 0.0;
             psGCPs[2].dfGCPPixel = poDS->nRasterXSize;
@@ -1142,17 +1176,17 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
             psGCPs[3].dfGCPLine = poDS->nRasterYSize;
         }
 
-        psGCPs[0].dfGCPX		= psImage->dfULX;
-        psGCPs[0].dfGCPY		= psImage->dfULY;
+        psGCPs[0].dfGCPX = psImage->dfULX;
+        psGCPs[0].dfGCPY = psImage->dfULY;
 
-        psGCPs[1].dfGCPX		= psImage->dfURX;
-        psGCPs[1].dfGCPY		= psImage->dfURY;
+        psGCPs[1].dfGCPX = psImage->dfURX;
+        psGCPs[1].dfGCPY = psImage->dfURY;
 
-        psGCPs[2].dfGCPX		= psImage->dfLRX;
-        psGCPs[2].dfGCPY		= psImage->dfLRY;
+        psGCPs[2].dfGCPX = psImage->dfLRX;
+        psGCPs[2].dfGCPY = psImage->dfLRY;
 
-        psGCPs[3].dfGCPX		= psImage->dfLLX;
-        psGCPs[3].dfGCPY		= psImage->dfLLY;
+        psGCPs[3].dfGCPX = psImage->dfLLX;
+        psGCPs[3].dfGCPY = psImage->dfLLY;
 
 /* -------------------------------------------------------------------- */
 /*      ESRI desires to use the RPCs to produce a denser and more       */
@@ -1348,7 +1382,44 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 /* -------------------------------------------------------------------- */
 /*      Do we have RPC info.                                            */
 /* -------------------------------------------------------------------- */
-    if( psImage && bHasRPC00 )
+
+    // get _rpc.txt file
+    const char* pszDirName = CPLGetDirname(pszFilename);
+    const char* pszBaseName = CPLGetBasename(pszFilename);
+    const char* pszRPCTXTFilename = CPLFormFilename( pszDirName,
+                                                        CPLSPrintf("%s_rpc",
+                                                        pszBaseName),
+                                                        "txt" );
+    if (CPLCheckForFile((char*)pszRPCTXTFilename, poOpenInfo->GetSiblingFiles()))
+    {
+        poDS->m_osRPCTXTFilename = pszRPCTXTFilename;
+    }
+    else
+    {
+        pszRPCTXTFilename = CPLFormFilename( pszDirName, CPLSPrintf("%s_RPC",
+                                                pszBaseName), "TXT" );
+        if (CPLCheckForFile((char*)pszRPCTXTFilename, poOpenInfo->GetSiblingFiles()))
+        {
+            poDS->m_osRPCTXTFilename = pszRPCTXTFilename;
+        }
+    }
+    bool bHasLoadedRPCTXT = false;
+    if( !poDS->m_osRPCTXTFilename.empty() )
+    {
+        char** papszMD = GDALLoadRPCFile( poDS->m_osRPCTXTFilename );
+        if( papszMD != NULL )
+        {
+            bHasLoadedRPCTXT = true;
+            poDS->SetMetadata( papszMD, "RPC" );
+            CSLDestroy(papszMD);
+        }
+        else
+        {
+            poDS->m_osRPCTXTFilename.clear();
+        }
+    }
+
+    if( psImage && bHasRPC00 && !bHasLoadedRPCTXT )
     {
         char szValue[1280];
         CPLsnprintf( szValue, sizeof(szValue), "%.16g", sRPCInfo.LINE_OFF );
@@ -1496,7 +1567,6 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
 
         snprintf( szValue, sizeof(szValue), "%d", sChipInfo.FI_COL );
         poDS->SetMetadataItem( "ICHIP_FI_COL", szValue );
-
     }
 
     const NITFSeries* series = NITFGetSeriesInfo(pszFilename);
@@ -1620,7 +1690,7 @@ GDALDataset *NITFDataset::OpenInternal( GDALOpenInfo * poOpenInfo,
             ( reinterpret_cast<GDALPamRasterBand *>( poDS->GetRasterBand(1) ) )->
             GDALPamRasterBand::GetOverviewCount() == 0;
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1662,7 +1732,7 @@ static OGRErr LoadDODDatum( OGRSpatialReference *poSRS,
 
     CPLString osDName = CSVGetField( pszGTDatum, "CODE", szExpanded,
                                      CC_ApproxString, "NAME" );
-    if( strlen(osDName) == 0 )
+    if( osDName.empty() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to find datum %s/%s in gt_datum.csv.",
@@ -1686,7 +1756,7 @@ static OGRErr LoadDODDatum( OGRSpatialReference *poSRS,
 
     CPLString osEName = CSVGetField( pszGTEllipse, "CODE", osEllipseCode,
                                      CC_ApproxString, "NAME" );
-    if( strlen(osEName) == 0 )
+    if( osEName.empty() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to find datum %s in gt_ellips.csv.",
@@ -1969,7 +2039,6 @@ CPLErr NITFDataset::IRasterIO( GDALRWFlag eRWFlag,
                                        nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 }
 
-
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
@@ -2045,7 +2114,10 @@ CPLErr NITFDataset::SetGCPs( int nGCPCountIn, const GDAL_GCP *pasGCPListIn,
     CPLFree(pszGCPProjection);
     pszGCPProjection = CPLStrdup(pszGCPProjectionIn);
 
-    int iUL = -1, iUR = -1, iLR = -1, iLL = -1;
+    int iUL = -1;
+    int iUR = -1;
+    int iLR = -1;
+    int iLL = -1;
 
 #define EPS_GCP 1e-5
     for(int i = 0; i < 4; i++ )
@@ -2256,7 +2328,6 @@ void NITFDataset::InitializeNITFDESMetadata()
     }
 }
 
-
 /************************************************************************/
 /*                       InitializeNITFDESs()                           */
 /************************************************************************/
@@ -2340,7 +2411,7 @@ void NITFDataset::InitializeNITFDESs()
         }
     }
 
-    if (aosList.size() > 0)
+    if (!aosList.empty())
         oSpecialMD.SetMetadata( aosList.List(), pszDESsDomain );
 }
 
@@ -2450,7 +2521,7 @@ void NITFDataset::InitializeNITFTREs()
             pszTREData += (nThisTRESize + 11);
         }
 
-        if (aosList.size() > 0)
+        if (!aosList.empty())
             oSpecialMD.SetMetadata( aosList.List(), pszTREsDomain );
     }
 }
@@ -2784,8 +2855,8 @@ void NITFDataset::InitializeTREMetadata()
 /* -------------------------------------------------------------------- */
     for( int nTRESrc = 0; nTRESrc < 2; nTRESrc++ )
     {
-        int nTREBytes;
-        char *pszTREData;
+        int nTREBytes = 0;
+        char *pszTREData = NULL;
 
         if( nTRESrc == 0 )
         {
@@ -3101,13 +3172,12 @@ const char *NITFDataset::GetMetadataItem(const char * pszName,
     }
 
     if( pszDomain != NULL && EQUAL(pszDomain,"OVERVIEWS")
-        && osRSetVRT.size() > 0 )
+        && !osRSetVRT.empty() )
         return osRSetVRT;
 
     return GDALPamDataset::GetMetadataItem( pszName, pszDomain );
 }
 
-
 /************************************************************************/
 /*                            GetGCPCount()                             */
 /************************************************************************/
@@ -3188,7 +3258,7 @@ int NITFDataset::CheckForRSets( const char *pszNITFFilename,
         aosRSetFilenames.push_back( osTarget );
     }
 
-    if( aosRSetFilenames.size() == 0 )
+    if( aosRSetFilenames.empty() )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -3244,7 +3314,7 @@ CPLErr NITFDataset::IBuildOverviews( const char *pszResampling,
 /* -------------------------------------------------------------------- */
 /*      If we have been using RSets we will need to clear them first.   */
 /* -------------------------------------------------------------------- */
-    if( osRSetVRT.size() > 0 )
+    if( !osRSetVRT.empty() )
     {
         oOvManager.CleanOverviews();
         osRSetVRT = "";
@@ -3397,7 +3467,9 @@ CPLErr NITFDataset::ScanJPEGBlocks()
 
     while( iSegOffset < iSegSize-1 )
     {
-        size_t nReadSize = MIN((size_t)sizeof(abyBlock),(size_t)(iSegSize - iSegOffset));
+        const size_t nReadSize =
+            std::min(sizeof(abyBlock),
+                     static_cast<size_t>(iSegSize - iSegOffset));
 
         if( VSIFSeekL( psFile->fp, panJPEGBlockOffset[0] + iSegOffset,
                        SEEK_SET ) != 0 )
@@ -3536,7 +3608,6 @@ CPLErr NITFDataset::ReadJPEGBlock( int iBlockX, int iBlockY )
         }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Read JPEG Chunk.                                                */
 /* -------------------------------------------------------------------- */
@@ -3611,6 +3682,10 @@ char **NITFDataset::GetFileList()
 {
     char **papszFileList = GDALPamDataset::GetFileList();
 
+    // Small optimization to avoid useless file probing.
+    if( CSLCount(papszFileList) == 0 )
+        return papszFileList;
+
 /* -------------------------------------------------------------------- */
 /*      Check for .imd file.                                            */
 /* -------------------------------------------------------------------- */
@@ -3621,6 +3696,9 @@ char **NITFDataset::GetFileList()
 /* -------------------------------------------------------------------- */
     papszFileList = AddFile( papszFileList, "RPB", "rpb" );
 
+    if( !m_osRPCTXTFilename.empty() )
+        papszFileList = CSLAddString(papszFileList, m_osRPCTXTFilename);
+
 /* -------------------------------------------------------------------- */
 /*      Check for other files.                                          */
 /* -------------------------------------------------------------------- */
@@ -3676,7 +3754,7 @@ char **NITFDataset::AddFile(char **papszFileList, const char* EXTENSION, const c
 static const char *GDALToNITFDataType( GDALDataType eType )
 
 {
-    const char *pszPVType;
+    const char *pszPVType = NULL;
 
     switch( eType )
     {
@@ -3776,8 +3854,6 @@ static char **NITFJP2KAKOptions( char **papszOptions )
     return papszKAKOptions;
 }
 
-
-
 /************************************************************************/
 /*              NITFExtractTEXTAndCGMCreationOption()                   */
 /************************************************************************/
@@ -3903,11 +3979,17 @@ NITFDataset::NITFDatasetCreate( const char *pszFilename, int nXSize, int nYSize,
         return NULL;
     }
 
-    const char* pszSDE_TRE = CSLFetchNameValue(papszOptions, "SDE_TRE");
-    if (pszSDE_TRE != NULL)
+    const char* const apszIgnoredOptions[] = { "SDE_TRE", "RPC00B", "RPCTXT",
+                                               NULL };
+    for( int i = 0; apszIgnoredOptions[i] != NULL; ++ i )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "SDE_TRE creation option ignored by Create() method (only valid in CreateCopy())" );
+        if( CSLFetchNameValue(papszOptions, apszIgnoredOptions[i]) )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "%s creation option ignored by Create() method "
+                      "(only valid in CreateCopy())",
+                      apszIgnoredOptions[i] );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -4302,7 +4384,6 @@ NITFDataset::NITFCreateCopy(
                 {
                     CPLDebug("NITF", "GEOPSB TRE was explicitly defined before. Keeping it.");
                 }
-
             }
             else
             {
@@ -4376,6 +4457,66 @@ NITFDataset::NITFCreateCopy(
     }
 
 /* -------------------------------------------------------------------- */
+/*      Do we have RPC information?                                     */
+/* -------------------------------------------------------------------- */
+    int nGCIFFlags = GCIF_PAM_DEFAULT;
+
+    char** papszRPC = poSrcDS->GetMetadata("RPC");
+    if( papszRPC != NULL &&
+        CPLFetchBool(papszFullOptions, "RPC00B", true))
+    {
+        if( CSLPartialFindString(papszFullOptions, "TRE=RPC00B=") >= 0 )
+        {
+            CPLDebug("NITF", "Both TRE=RPC00B and RPC metadata are available. "
+                     "Ignoring RPC metadata and re-using source TRE=RPC00B");
+        }
+        else
+        {
+            int bPrecisionLoss = FALSE;
+            char* pszRPC = NITFFormatRPC00BFromMetadata(papszRPC, &bPrecisionLoss);
+            if( pszRPC == NULL )
+            {
+                CPLError((bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
+                        "Cannot format a valid RPC00B TRE from the RPC metadata");
+                if(  bStrict )
+                {
+                    CSLDestroy(papszFullOptions);
+                    CSLDestroy(papszCgmMD);
+                    CSLDestroy(papszTextMD);
+                    return NULL;
+                }
+            }
+            else
+            {
+                CPLString osRPC00B("TRE=RPC00B=");
+                osRPC00B += pszRPC;
+                papszFullOptions = CSLAddString( papszFullOptions, osRPC00B ) ;
+
+                // If no precision loss occurred during RPC conversion, then
+                // we can suppress it from PAM
+                if( !bPrecisionLoss )
+                    nGCIFFlags &= ~GCIF_METADATA;
+            }
+            CPLFree(pszRPC);
+        }
+    }
+    else if( !CPLFetchBool(papszFullOptions, "RPC00B", true) )
+    {
+        int nIdx = CSLPartialFindString(papszFullOptions, "TRE=RPC00B=");
+        if( nIdx >= 0 )
+        {
+            papszFullOptions = CSLRemoveStrings(papszFullOptions,
+                                                nIdx, 1, NULL);
+        }
+    }
+
+    if( papszRPC != NULL &&
+        CPLFetchBool(papszFullOptions, "RPCTXT", false))
+    {
+        GDALWriteRPCTXTFile( pszFilename, papszRPC );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
     const int nXSize = poSrcDS->GetRasterXSize();
@@ -4564,8 +4705,18 @@ NITFDataset::NITFCreateCopy(
             return NULL;
         }
 
+        // Save error state to restore it afterwards since some operations
+        // in Open() might reset it.
+        CPLErr eLastErr = CPLGetLastErrorType();
+        int nLastErrNo = CPLGetLastErrorNo();
+        CPLString osLastErrorMsg = CPLGetLastErrorMsg();
+
         GDALOpenInfo oOpenInfo( pszFilename, GA_Update );
         poDstDS = reinterpret_cast<NITFDataset *>( Open( &oOpenInfo ) );
+
+        if( CPLGetLastErrorType() == CE_None && eLastErr != CE_None )
+            CPLErrorSetState( eLastErr, nLastErrNo, osLastErrorMsg.c_str() );
+
         if( poDstDS == NULL )
         {
             CSLDestroy(papszCgmMD);
@@ -4592,9 +4743,7 @@ NITFDataset::NITFCreateCopy(
 /* -------------------------------------------------------------------- */
 /*      Do we need to copy a colortable or other metadata?              */
 /* -------------------------------------------------------------------- */
-            GDALColorTable *poCT;
-
-            poCT = poSrcBand->GetColorTable();
+            GDALColorTable *poCT = poSrcBand->GetColorTable();
             if( poCT != NULL )
                 poDstBand->SetColorTable( poCT );
 
@@ -4653,7 +4802,20 @@ NITFDataset::NITFCreateCopy(
                           poSrcDS->GetGCPProjection() );
     }
 
-    poDstDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+    poDstDS->CloneInfo( poSrcDS, nGCIFFlags );
+
+    if( (nGCIFFlags & GCIF_METADATA) == 0 )
+    {
+        const int nSavedMOFlags = poDstDS->GetMOFlags();
+        if( poSrcDS->GetMetadata() != NULL )
+        {
+            if( CSLCount(poDstDS->GetMetadata()) != CSLCount(poSrcDS->GetMetadata()) )
+            {
+                poDstDS->SetMetadata( poSrcDS->GetMetadata() );
+            }
+        }
+        poDstDS->SetMOFlags(nSavedMOFlags);
+    }
 
     CSLDestroy(papszCgmMD);
     CSLDestroy(papszTextMD);
@@ -4786,7 +4948,7 @@ static bool NITFPatchImageLength( const char *pszFilename,
         {
             double dfRate = static_cast<GIntBig>(nFileLen-nImageOffset) * 8
                 / static_cast<double>( nPixelCount );
-            dfRate = MAX(0.01, MIN(99.99, dfRate));
+            dfRate = std::max(0.01, std::min(99.99, dfRate));
 
             // We emit in wxyz format with an implicit decimal place
             // between wx and yz as per spec for lossy compression.
@@ -4877,14 +5039,13 @@ static bool NITFWriteCGMSegments( const char *pszFilename, char **papszList)
         return false;
     }
 
-
     // allocate space for graphic header.
     // Size of LS = 4, size of LSSH = 6, and 1 for null character
     char *pachLS = reinterpret_cast<char *>(
         CPLCalloc(nNUMS * nCgmHdrEntrySz + 1, 1) );
 
     /* -------------------------------------------------------------------- */
-    /*	Assume no extended data such as SXSHDL, SXSHD						*/
+    /*  Assume no extended data such as SXSHDL, SXSHD                       */
     /* -------------------------------------------------------------------- */
 
     /* ==================================================================== */
@@ -4991,10 +5152,8 @@ static bool NITFWriteCGMSegments( const char *pszFilename, char **papszList)
                  static_cast<int>( sizeof(achGSH) ), nCGMSize );
 
         CPLFree(pszCgmToWrite);
-
     } // End For
 
-
     /* -------------------------------------------------------------------- */
     /*      Write out the graphic segment info.                             */
     /* -------------------------------------------------------------------- */
@@ -5156,7 +5315,7 @@ static bool NITFWriteTextSegments( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 
         const char *pszHeaderBuffer = NULL;
-        for( int iOpt2 = 0; papszList != NULL && papszList[iOpt2] != NULL; iOpt2++ ) {
+        for( int iOpt2 = 0; papszList[iOpt2] != NULL; iOpt2++ ) {
             if( !STARTS_WITH_CI(papszList[iOpt2], "HEADER_") )
                 continue;
 
@@ -5181,8 +5340,8 @@ static bool NITFWriteTextSegments( const char *pszFilename,
 
             // if ID matches, read the header information and exit the loop
             if (bIsSameId) {
-            	pszHeaderBuffer = CPLParseNameValue( papszList[iOpt2], NULL);
-            	break;
+                pszHeaderBuffer = CPLParseNameValue( papszList[iOpt2], NULL);
+                break;
             }
         }
 
@@ -5194,7 +5353,9 @@ static bool NITFWriteTextSegments( const char *pszFilename,
         bOK &= VSIFSeekL( fpVSIL, 0, SEEK_END ) == 0;
 
         if (pszHeaderBuffer!= NULL) {
-            memcpy( achTSH, pszHeaderBuffer, MIN(strlen(pszHeaderBuffer), sizeof(achTSH)) );
+            memcpy( achTSH,
+                    pszHeaderBuffer,
+                    std::min(strlen(pszHeaderBuffer), sizeof(achTSH)) );
 
             // Take care NITF2.0 date format changes
             const char chTimeZone = achTSH[20];
@@ -5239,8 +5400,7 @@ static bool NITFWriteTextSegments( const char *pszFilename,
                 else if (STARTS_WITH(pszOrigMonth, "NOV")) strncpy(pszNewMonth,"11",2);
                 else if (STARTS_WITH(pszOrigMonth, "DEC")) strncpy(pszNewMonth,"12",2);
 
-                PLACE( achTSH+ 12, TXTDT         , achNewDate          		);
-
+                PLACE( achTSH+ 12, TXTDT         , achNewDate                );
             }
         } else { // Use default value if header information is not found
             PLACE( achTSH+  0, TE            , "TE"                          );
@@ -5252,7 +5412,6 @@ static bool NITFWriteTextSegments( const char *pszFilename,
             PLACE( achTSH+277, TXSHDL        , "00000"                       );
         }
 
-
         bOK &= VSIFWriteL( achTSH, sizeof(achTSH), 1, fpVSIL ) == 1;
 
 /* -------------------------------------------------------------------- */
@@ -5273,7 +5432,7 @@ static bool NITFWriteTextSegments( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Update the subheader and data size info in the file header.     */
 /* -------------------------------------------------------------------- */
-        snprintf( pachLT + 9*iTextSeg+0, 9+1, "%04d%05d",
+        CPLsnprintf( pachLT + 9*iTextSeg+0, 9+1, "%04d%05d",
                  static_cast<int>( sizeof( achTSH ) ), nTextLength );
 
         iTextSeg++;
@@ -5408,7 +5567,7 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
         nRestartInterval = atoi(CSLFetchNameValue(papszOptions,"RESTART_INTERVAL"));
     }
 
-    int bProgressive = CSLFetchBoolean( papszOptions, "PROGRESSIVE", FALSE );
+    const bool bProgressive = CPLFetchBool( papszOptions, "PROGRESSIVE", false );
 
 /* -------------------------------------------------------------------- */
 /*      Compute blocking factors                                        */
@@ -5435,7 +5594,10 @@ NITFWriteJPEGImage( GDALDataset *poSrcDS, VSILFILE *fp, vsi_l_offset nStartOffse
 
     if( nNPPBH <= 0 || nNPPBV <= 0 ||
         nNPPBH > 9999 || nNPPBV > 9999  )
-        nNPPBH = nNPPBV = 256;
+    {
+        nNPPBH = 256;
+        nNPPBV = 256;
+    }
 
     const int nNBPR = (nXSize + nNPPBH - 1) / nNPPBH;
     const int nNBPC = (nYSize + nNPPBV - 1) / nNPPBV;
@@ -5776,7 +5938,9 @@ void GDALRegister_NITF()
         osCreationOptions += szFieldDescription;
     }
     osCreationOptions +=
-"   <Option name='SDE_TRE' type='boolean' description='Write GEOLOB and GEOPSB TREs (only geographic SRS for now)' default='NO'/>";
+"   <Option name='SDE_TRE' type='boolean' description='Write GEOLOB and GEOPSB TREs (only geographic SRS for now)' default='NO'/>"
+"   <Option name='RPC00B' type='boolean' description='Write RPC00B TRE (either from source TRE, or from RPC metadata)' default='YES'/>"
+"   <Option name='RPCTXT' type='boolean' description='Write out _RPC.TXT file' default='NO'/>";
     osCreationOptions += "</CreationOptionList>";
 
     GDALDriver *poDriver = new GDALDriver();
diff --git a/frmts/nitf/nitfdataset.h b/frmts/nitf/nitfdataset.h
index adeada9..23d6c78 100644
--- a/frmts/nitf/nitfdataset.h
+++ b/frmts/nitf/nitfdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdataset.h 33794 2016-03-26 13:19:07Z goatbar $
+ * $Id: nitfdataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  GDALDataset/GDALRasterBand declarations.
@@ -55,7 +55,7 @@ void NITFUpdateGCPsWithRPC( NITFRPC00BInfo *psRPCInfo,
 
 /************************************************************************/
 /* ==================================================================== */
-/*				NITFDataset				*/
+/*                              NITFDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -101,7 +101,7 @@ class NITFDataset : public GDALPamDataset
     int          nQLevel;
 
     int          ScanJPEGQLevel( GUIntBig *pnDataStart );
-    CPLErr       ScanJPEGBlocks( void );
+    CPLErr       ScanJPEGBlocks();
     CPLErr       ReadJPEGBlock( int, int );
     void         CheckGeoSDEInfo();
     char**       AddFile(char **papszFileList, const char* EXTENSION, const char* extension);
@@ -117,11 +117,13 @@ class NITFDataset : public GDALPamDataset
 
     int          bInLoadXML;
 
+    CPLString    m_osRPCTXTFilename;
+
     int          bExposeUnderlyingJPEGDatasetOverviews;
     int          ExposeUnderlyingJPEGDatasetOverviews() const { return bExposeUnderlyingJPEGDatasetOverviews; }
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
   public:
                  NITFDataset();
@@ -131,34 +133,34 @@ class NITFDataset : public GDALPamDataset
                                int nBufXSize, int nBufYSize,
                                GDALDataType eDT,
                                int nBandCount, int *panBandList,
-                               char **papszOptions );
+                               char **papszOptions ) override;
 
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               int, int *,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) override;
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) override;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
-    virtual char **GetFileList(void);
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
+    virtual char **GetFileList() override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
-    virtual void   FlushCache();
+                                         const char * pszDomain = "" ) override;
+    virtual void   FlushCache() override;
     virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
+                                    int, int *, GDALProgressFunc, void * ) override;
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *OpenInternal( GDALOpenInfo *, GDALDataset *poWritableJ2KDataset,
@@ -172,7 +174,6 @@ class NITFDataset : public GDALPamDataset
              NITFDatasetCreate( const char *pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char **papszOptions );
-
 };
 
 /************************************************************************/
@@ -197,14 +198,14 @@ class NITFRasterBand : public GDALPamRasterBand
                    NITFRasterBand( NITFDataset *, int );
     virtual ~NITFRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
-    virtual GDALColorTable *GetColorTable();
-    virtual CPLErr SetColorTable( GDALColorTable * );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual CPLErr SetColorTable( GDALColorTable * ) override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 
     void Unpack(GByte* pData);
 };
@@ -229,35 +230,35 @@ class NITFProxyPamRasterBand : public GDALPamRasterBand
         virtual GDALRasterBand* RefUnderlyingRasterBand() = 0;
         virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand);
 
-        virtual CPLErr IReadBlock( int, int, void * );
-        virtual CPLErr IWriteBlock( int, int, void * );
+        virtual CPLErr IReadBlock( int, int, void * ) override;
+        virtual CPLErr IWriteBlock( int, int, void * ) override;
         virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                                 void *, int, int, GDALDataType,
                                 GSpacing nPixelSpace, GSpacing nLineSpace,
-                                GDALRasterIOExtraArg* psExtraArg);
+                                GDALRasterIOExtraArg* psExtraArg) override;
 
     public:
         virtual ~NITFProxyPamRasterBand();
 
-        virtual char      **GetMetadata( const char * pszDomain = ""  );
+        virtual char      **GetMetadata( const char * pszDomain = ""  ) override;
         /*virtual CPLErr      SetMetadata( char ** papszMetadata,
                                         const char * pszDomain = ""  );*/
         virtual const char *GetMetadataItem( const char * pszName,
-                                            const char * pszDomain = "" );
+                                            const char * pszDomain = "" ) override;
         /*virtual CPLErr      SetMetadataItem( const char * pszName,
                                             const char * pszValue,
                                             const char * pszDomain = "" );*/
-        virtual CPLErr FlushCache();
+        virtual CPLErr FlushCache() override;
         /*virtual char **GetCategoryNames();*/
-        virtual double GetNoDataValue( int *pbSuccess = NULL );
-        virtual double GetMinimum( int *pbSuccess = NULL );
-        virtual double GetMaximum(int *pbSuccess = NULL );
+        virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+        virtual double GetMinimum( int *pbSuccess = NULL ) override;
+        virtual double GetMaximum(int *pbSuccess = NULL ) override;
         /*virtual double GetOffset( int *pbSuccess = NULL );
         virtual double GetScale( int *pbSuccess = NULL );*/
         /*virtual const char *GetUnitType();*/
-        virtual GDALColorInterp GetColorInterpretation();
-        virtual GDALColorTable *GetColorTable();
-        virtual CPLErr Fill(double dfRealValue, double dfImaginaryValue = 0);
+        virtual GDALColorInterp GetColorInterpretation() override;
+        virtual GDALColorTable *GetColorTable() override;
+        virtual CPLErr Fill(double dfRealValue, double dfImaginaryValue = 0) override;
 
         /*
         virtual CPLErr SetCategoryNames( char ** );
@@ -271,25 +272,25 @@ class NITFProxyPamRasterBand : public GDALPamRasterBand
 
         virtual CPLErr GetStatistics( int bApproxOK, int bForce,
                                     double *pdfMin, double *pdfMax,
-                                    double *pdfMean, double *padfStdDev );
+                                    double *pdfMean, double *padfStdDev ) override;
         virtual CPLErr ComputeStatistics( int bApproxOK,
                                         double *pdfMin, double *pdfMax,
                                         double *pdfMean, double *pdfStdDev,
-                                        GDALProgressFunc, void *pProgressData );
+                                        GDALProgressFunc, void *pProgressData ) override;
         /*virtual CPLErr SetStatistics( double dfMin, double dfMax,
                                     double dfMean, double dfStdDev );*/
-        virtual CPLErr ComputeRasterMinMax( int, double* );
+        virtual CPLErr ComputeRasterMinMax( int, double* ) override;
 
-        virtual int HasArbitraryOverviews();
-        virtual int GetOverviewCount();
-        virtual GDALRasterBand *GetOverview(int);
-        virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig );
+        virtual int HasArbitraryOverviews() override;
+        virtual int GetOverviewCount() override;
+        virtual GDALRasterBand *GetOverview(int) override;
+        virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig ) override;
         virtual CPLErr BuildOverviews( const char *, int, int *,
-                                    GDALProgressFunc, void * );
+                                    GDALProgressFunc, void * ) override;
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                 int nBufXSize, int nBufYSize,
-                                GDALDataType eDT, char **papszOptions );
+                                GDALDataType eDT, char **papszOptions ) override;
 
         /*virtual CPLErr  GetHistogram( double dfMin, double dfMax,
                             int nBuckets, GUIntBig * panHistogram,
@@ -306,9 +307,9 @@ class NITFProxyPamRasterBand : public GDALPamRasterBand
         /*virtual const GDALRasterAttributeTable *GetDefaultRAT();
         virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );*/
 
-        virtual GDALRasterBand *GetMaskBand();
-        virtual int             GetMaskFlags();
-        virtual CPLErr          CreateMaskBand( int nFlags );
+        virtual GDALRasterBand *GetMaskBand() override;
+        virtual int             GetMaskFlags() override;
+        virtual CPLErr          CreateMaskBand( int nFlags ) override;
 };
 
 /************************************************************************/
@@ -334,7 +335,7 @@ class NITFWrapperRasterBand : public NITFProxyPamRasterBand
 
   protected:
     /* Pure virtual method of the NITFProxyPamRasterBand */
-    virtual GDALRasterBand* RefUnderlyingRasterBand();
+    virtual GDALRasterBand* RefUnderlyingRasterBand() override;
 
   public:
                    NITFWrapperRasterBand( NITFDataset * poDS,
@@ -343,13 +344,13 @@ class NITFWrapperRasterBand : public NITFProxyPamRasterBand
     virtual ~NITFWrapperRasterBand();
 
     /* Methods from GDALRasterBand we want to override */
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr          SetColorInterpretation( GDALColorInterp );
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual CPLErr          SetColorInterpretation( GDALColorInterp ) override;
 
-    virtual GDALColorTable *GetColorTable();
+    virtual GDALColorTable *GetColorTable() override;
 
-    virtual int             GetOverviewCount();
-    virtual GDALRasterBand *GetOverview(int);
+    virtual int             GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview(int) override;
 
     /* Specific method */
     void                    SetColorTableFromNITFBandInfo();
diff --git a/frmts/nitf/nitfdes.c b/frmts/nitf/nitfdes.c
index e264853..a387cb4 100644
--- a/frmts/nitf/nitfdes.c
+++ b/frmts/nitf/nitfdes.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdes.c 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: nitfdes.c 36380 2016-11-21 10:21:20Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for implementation of DE segments.
@@ -33,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitfdes.c 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: nitfdes.c 36380 2016-11-21 10:21:20Z rouault $");
 
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
@@ -509,8 +509,8 @@ void NITFDESFreeTREData( char* pabyTREData )
 int NITFDESExtractShapefile(NITFDES* psDES, const char* pszRadixFileName)
 {
     NITFSegmentInfo* psSegInfo;
-    const char* apszExt[3];
-    int anOffset[4];
+    const char* apszExt[3] = { NULL };
+    int anOffset[4] = { 0 };
     int iShpFile;
     char* pszFilename;
     size_t nFilenameLen;
diff --git a/frmts/nitf/nitfdump.c b/frmts/nitf/nitfdump.c
index 30fe768..dc13bba 100644
--- a/frmts/nitf/nitfdump.c
+++ b/frmts/nitf/nitfdump.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfdump.c 33757 2016-03-20 20:22:33Z goatbar $
+ * $Id: nitfdump.c 36393 2016-11-21 14:25:42Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Simple test mainline to dump info about NITF file.
@@ -35,7 +35,7 @@
 
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: nitfdump.c 33757 2016-03-20 20:22:33Z goatbar $");
+CPL_CVSID("$Id: nitfdump.c 36393 2016-11-21 14:25:42Z rouault $");
 
 static void DumpRPC( NITFImage *psImage, NITFRPC00BInfo *psRPC );
 static void DumpMetadata( const char *, const char *, char ** );
@@ -456,7 +456,7 @@ int main( int nArgc, char ** papszArgv )
                 printf( "  Location Table\n" );
                 for( i = 0; i < psImage->nLocCount; i++ )
                 {
-                    printf( "    LocName=%s, LocId=%d, Offset=%d, Size=%d\n",
+                    printf( "    LocName=%s, LocId=%d, Offset=%u, Size=%u\n",
                             GetLocationNameFromId(psImage->pasLocations[i].nLocId),
                             psImage->pasLocations[i].nLocId,
                             psImage->pasLocations[i].nLocOffset,
@@ -682,7 +682,7 @@ int main( int nArgc, char ** papszArgv )
                     printf( "  Location Table\n" );
                     for( i = 0; i < nLocCount; i++ )
                     {
-                        printf( "    LocName=%s, LocId=%d, Offset=%d, Size=%d\n",
+                        printf( "    LocName=%s, LocId=%d, Offset=%u, Size=%u\n",
                                 GetLocationNameFromId(pasLocations[i].nLocId),
                                 pasLocations[i].nLocId,
                                 pasLocations[i].nLocOffset,
diff --git a/frmts/nitf/nitffile.c b/frmts/nitf/nitffile.c
index 75dc5f3..ba4ebec 100644
--- a/frmts/nitf/nitffile.c
+++ b/frmts/nitf/nitffile.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitffile.c 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: nitffile.c 36457 2016-11-23 00:18:37Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for opening NITF file, populating NITFFile
@@ -34,7 +34,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitffile.c 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: nitffile.c 36457 2016-11-23 00:18:37Z rouault $");
 
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
@@ -271,8 +271,8 @@ retry_read_header:
          EQUAL(szTemp, "999999999999"))
     {
         GUIntBig nFileSize;
-        GByte abyDELIM2_L2[12];
-        GByte abyL1_DELIM1[11];
+        GByte abyDELIM2_L2[12] = { 0 };
+        GByte abyL1_DELIM1[11] = { 0 };
         int bOK;
 
         bTriedStreamingFileHeader = TRUE;
@@ -2632,15 +2632,14 @@ char **NITFGenericMetadataReadTRE(char **papszMD,
                                   int nTRESize,
                                   CPLXMLNode* psTreNode)
 {
-    int nTreLength, nTreMinLength = -1 /*, nTreMaxLength = -1 */;
     int bError = FALSE;
     int nTreOffset = 0;
     const char* pszMDPrefix;
     int nMDSize, nMDAlloc;
 
-    nTreLength = atoi(CPLGetXMLValue(psTreNode, "length", "-1"));
-    nTreMinLength = atoi(CPLGetXMLValue(psTreNode, "minlength", "-1"));
-    /* nTreMaxLength = atoi(CPLGetXMLValue(psTreNode, "maxlength", "-1")); */
+    int nTreLength = atoi(CPLGetXMLValue(psTreNode, "length", "-1"));
+    int nTreMinLength = atoi(CPLGetXMLValue(psTreNode, "minlength", "-1"));
+    /* int nTreMaxLength = atoi(CPLGetXMLValue(psTreNode, "maxlength", "-1")); */
 
     if( (nTreLength > 0 && nTRESize != nTreLength) ||
         (nTreMinLength > 0 && nTRESize < nTreMinLength) )
@@ -2833,10 +2832,15 @@ char **NITFGenericMetadataRead( char **papszMD,
     CPLXMLNode* psTresNode = NULL;
     CPLXMLNode* psIter = NULL;
 
-    if (psFile == NULL && psImage == NULL)
-        return papszMD;
+    if (psFile == NULL)
+    {
+        if( psImage == NULL)
+            return papszMD;
+        psTreeNode = NITFLoadXMLSpec(psImage->psFile);
+    }
+    else
+        psTreeNode = NITFLoadXMLSpec(psFile);
 
-    psTreeNode = NITFLoadXMLSpec(psFile ? psFile : psImage->psFile);
     if (psTreeNode == NULL)
         return papszMD;
 
@@ -2855,8 +2859,14 @@ char **NITFGenericMetadataRead( char **papszMD,
         {
             const char* pszName = CPLGetXMLValue(psIter, "name", NULL);
             const char* pszMDPrefix = CPLGetXMLValue(psIter, "md_prefix", NULL);
-            if (pszName != NULL && ((pszSpecificTREName == NULL && pszMDPrefix != NULL) ||
-                                    (pszSpecificTREName != NULL && strcmp(pszName, pszSpecificTREName) == 0)))
+            int bHasRightPrefix = FALSE;
+            if( pszName == NULL )
+                continue;
+            if( pszSpecificTREName == NULL )
+                bHasRightPrefix = ( pszMDPrefix != NULL );
+            else
+                bHasRightPrefix = ( strcmp(pszName, pszSpecificTREName) == 0 );
+            if ( bHasRightPrefix )
             {
                 if (psFile != NULL)
                 {
diff --git a/frmts/nitf/nitfimage.c b/frmts/nitf/nitfimage.c
index fa4f9af..0b756bd 100644
--- a/frmts/nitf/nitfimage.c
+++ b/frmts/nitf/nitfimage.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitfimage.c 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: nitfimage.c 36380 2016-11-21 10:21:20Z rouault $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Module responsible for implementation of most NITFImage
@@ -36,7 +36,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: nitfimage.c 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: nitfimage.c 36380 2016-11-21 10:21:20Z rouault $");
 
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
 
@@ -733,15 +733,7 @@ NITFImage *NITFImageAccess( NITFFile *psFile, int iSegment )
         psImage->nLineOffset = psImage->nBandOffset * psImage->nBands;
         psImage->nBlockOffset = psImage->nLineOffset * psImage->nBlockHeight;
     }
-    else if( psImage->chIMODE == 'B' )
-    {
-        psImage->nPixelOffset = psImage->nWordSize;
-        psImage->nLineOffset =
-            ((GIntBig) psImage->nBlockWidth * psImage->nBitsPerSample) / 8;
-        psImage->nBandOffset = psImage->nBlockHeight * psImage->nLineOffset;
-        psImage->nBlockOffset = psImage->nBandOffset * psImage->nBands;
-    }
-    else
+    else /* if( psImage->chIMODE == 'B' ) */
     {
         psImage->nPixelOffset = psImage->nWordSize;
         psImage->nLineOffset =
@@ -2261,6 +2253,368 @@ char **NITFReadPIAIMC( NITFImage *psImage )
     return NITFGenericMetadataRead(NULL, NULL, psImage, "PIAIMC");
 }
 
+
+/************************************************************************/
+/*                    NITFFormatRPC00BCoefficient()                     */
+/*                                                                      */
+/*      Format coefficients like +X.XXXXXXE+X (12 bytes)                */
+/************************************************************************/
+static int NITFFormatRPC00BCoefficient( char* pszBuffer, double dfVal,
+                                        int* pbPrecisionLoss )
+{
+    // We need 12 bytes + 2=3-1 bytes for MSVC potentially outputting exponents
+    // with 3 digits + 1 terminating byte
+    char szTemp[12+2+1];
+#if defined(DEBUG) || defined(WIN32)
+    size_t nLen;
+#endif
+
+    if( fabs(dfVal) > 9.999999e9 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Coefficient out of range: %g",
+                 dfVal);
+        return FALSE;
+    }
+
+    CPLsnprintf( szTemp, sizeof(szTemp), "%+.6E", dfVal);
+#if defined(DEBUG) || defined(WIN32)
+    nLen = strlen(szTemp);
+#endif
+    CPLAssert( szTemp[9] == 'E' );
+#ifdef WIN32
+    if( nLen == 14 ) // Old MSVC versions: 3 digits for the exponent
+    {
+        if( szTemp[11] != '0' || szTemp[12] != '0' )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined, "%g rounded to 0", dfVal);
+            snprintf(pszBuffer, 12 + 1, "%s", "+0.000000E+0");
+            if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+            return TRUE;
+        }
+        szTemp[11] = szTemp[13];
+    }
+    else // behaviour of the standard: 2 digits for the exponent
+#endif
+    {
+        CPLAssert( nLen == 13 );
+        if( szTemp[11] != '0')
+        {
+            CPLError(CE_Warning, CPLE_AppDefined, "%g rounded to 0", dfVal);
+            snprintf(pszBuffer, 12 + 1, "%s", "+0.000000E+0");
+            if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+            return TRUE;
+        }
+        szTemp[11] = szTemp[12];
+    }
+    szTemp[12] = '\0';
+    snprintf(pszBuffer, 12 + 1, "%s", szTemp);
+    return TRUE;
+}
+
+
+/************************************************************************/
+/*                   NITFFormatRPC00BFromMetadata()                     */
+/*                                                                      */
+/*      Format the content of a RPC00B TRE from RPC metadata            */
+/************************************************************************/
+
+char* NITFFormatRPC00BFromMetadata( char** papszRPC, int* pbPrecisionLoss )
+{
+    GDALRPCInfo sRPC;
+    char* pszRPC00B;
+    double dfErrBIAS;
+    double dfErrRAND;
+    int nOffset;
+    int nLength;
+    int nRounded;
+    int i;
+    char szTemp[24];
+
+    if( pbPrecisionLoss ) *pbPrecisionLoss = FALSE;
+
+    if( !GDALExtractRPCInfo( papszRPC, &sRPC ) )
+        return NULL;
+
+    pszRPC00B = (char*) CPLMalloc(1041 + 1);
+    pszRPC00B[0] = '1'; /* success flag */
+    nOffset = 1;
+
+    dfErrBIAS = CPLAtof(CSLFetchNameValueDef(papszRPC, "ERR_BIAS", "0"));
+    if( dfErrBIAS < 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Correcting ERR_BIAS from %f to 0", dfErrBIAS);
+    }
+    else if( dfErrBIAS > 9999.99 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "ERR_BIAS out of range. Clamping to 9999.99");
+        dfErrBIAS = 9999.99;
+    }
+    nLength = 7;
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%07.2f", dfErrBIAS);
+    nOffset += nLength;
+
+    dfErrRAND = CPLAtof(CSLFetchNameValueDef(papszRPC, "ERR_RAND", "0"));
+    if( dfErrRAND < 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Correcting ERR_RAND from %f to 0", dfErrRAND);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    else if( dfErrRAND > 9999.99 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "ERR_RAND out of range. Clamping to 9999.99");
+        dfErrRAND = 9999.99;
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    nLength = 7;
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%07.2f", dfErrRAND);
+    nOffset += nLength;
+
+    nLength = 6;
+    if( sRPC.dfLINE_OFF < 0 || sRPC.dfLINE_OFF >= 1e6 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "LINE_OFF out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    nRounded = (int)floor( sRPC.dfLINE_OFF + 0.5 );
+    if( fabs(nRounded - sRPC.dfLINE_OFF) > 1e-2 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "LINE_OFF was rounded from %f to %d",
+                 sRPC.dfLINE_OFF, nRounded);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%06d", nRounded);
+    nOffset += nLength;
+
+    nLength = 5;
+    if( sRPC.dfSAMP_OFF < 0 || sRPC.dfSAMP_OFF >= 1e5 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "SAMP_OFF out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    nRounded = (int)floor( sRPC.dfSAMP_OFF + 0.5 );
+    if( fabs(nRounded - sRPC.dfSAMP_OFF) > 1e-2 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "SAMP_OFF was rounded from %f to %d",
+                 sRPC.dfSAMP_OFF, nRounded);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%05d", nRounded);
+    nOffset += nLength;
+
+    nLength = 8;
+    if( fabs(sRPC.dfLAT_OFF) > 90 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "LAT_OFF out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%+08.4f", sRPC.dfLAT_OFF);
+    if( fabs(sRPC.dfLAT_OFF - CPLAtof(NITFGetField(szTemp, pszRPC00B, nOffset, nLength ))) > 1e-8 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "LAT_OFF was rounded from %f to %s",
+                 sRPC.dfLAT_OFF, szTemp);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    nOffset += nLength;
+
+    nLength = 9;
+    if( fabs(sRPC.dfLONG_OFF) > 180 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "LONG_OFF out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%+09.4f", sRPC.dfLONG_OFF);
+    if( fabs(sRPC.dfLONG_OFF - CPLAtof(NITFGetField(szTemp, pszRPC00B, nOffset, nLength ))) > 1e-8 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "LONG_OFF was rounded from %f to %s",
+                 sRPC.dfLONG_OFF, szTemp);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    nOffset += nLength;
+
+    nLength = 5;
+    if( fabs(sRPC.dfHEIGHT_OFF) > 9999 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "HEIGHT_OFF out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    nRounded = (int)floor( sRPC.dfHEIGHT_OFF + 0.5 );
+    if( fabs(nRounded - sRPC.dfHEIGHT_OFF) > 1e-2 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "HEIGHT_OFF was rounded from %f to %d",
+                 sRPC.dfHEIGHT_OFF, nRounded);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%+05d", nRounded);
+    nOffset += nLength;
+
+    nLength = 6;
+    if( sRPC.dfLINE_SCALE < 1 || sRPC.dfLINE_SCALE >= 999999 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "LINE_SCALE out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    nRounded = (int)floor( sRPC.dfLINE_SCALE + 0.5 );
+    if( fabs(nRounded - sRPC.dfLINE_SCALE) > 1e-2 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "LINE_SCALE was rounded from %f to %d",
+                 sRPC.dfLINE_SCALE, nRounded);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%06d", nRounded);
+    nOffset += nLength;
+
+    nLength = 5;
+    if( sRPC.dfSAMP_SCALE < 1 || sRPC.dfSAMP_SCALE >= 99999 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "SAMP_SCALE out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    nRounded = (int)floor( sRPC.dfSAMP_SCALE + 0.5 );
+    if( fabs(nRounded - sRPC.dfSAMP_SCALE) > 1e-2 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "SAMP_SCALE was rounded from %f to %d",
+                 sRPC.dfSAMP_SCALE, nRounded);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%05d", nRounded);
+    nOffset += nLength;
+
+    nLength = 8;
+    if( fabs(sRPC.dfLAT_SCALE) > 90 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "LAT_SCALE out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%+08.4f", sRPC.dfLAT_SCALE);
+    if( fabs(sRPC.dfLAT_SCALE - CPLAtof(NITFGetField(szTemp, pszRPC00B, nOffset, nLength ))) > 1e-8 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "LAT_SCALE was rounded from %f to %s",
+                 sRPC.dfLAT_SCALE, szTemp);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    nOffset += nLength;
+
+    nLength = 9;
+    if( fabs(sRPC.dfLONG_SCALE) > 180 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "LONG_SCALE out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%+09.4f", sRPC.dfLONG_SCALE);
+    if( fabs(sRPC.dfLONG_SCALE - CPLAtof(NITFGetField(szTemp, pszRPC00B, nOffset, nLength ))) > 1e-8 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "LONG_SCALE was rounded from %f to %s",
+                 sRPC.dfLONG_SCALE, szTemp);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    nOffset += nLength;
+
+    nLength = 5;
+    if( fabs(sRPC.dfHEIGHT_SCALE) > 9999 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "HEIGHT_SCALE out of range.");
+        CPLFree(pszRPC00B);
+        return NULL;
+    }
+    nRounded = (int)floor( sRPC.dfHEIGHT_SCALE + 0.5 );
+    if( fabs(nRounded - sRPC.dfHEIGHT_SCALE) > 1e-2 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "HEIGHT_SCALE was rounded from %f to %d",
+                 sRPC.dfHEIGHT_SCALE, nRounded);
+        if( pbPrecisionLoss ) *pbPrecisionLoss = TRUE;
+    }
+    CPLsnprintf(pszRPC00B + nOffset, nLength + 1, "%+05d", nRounded);
+    nOffset += nLength;
+
+/* -------------------------------------------------------------------- */
+/*      Write coefficients.                                             */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < 20; i++ )
+    {
+        if( !NITFFormatRPC00BCoefficient(pszRPC00B + nOffset,
+                                         sRPC.adfLINE_NUM_COEFF[i],
+                                         pbPrecisionLoss) )
+        {
+            CPLFree(pszRPC00B);
+            return NULL;
+        }
+        nOffset += 12;
+    }
+    for( i = 0; i < 20; i++ )
+    {
+        if( !NITFFormatRPC00BCoefficient(pszRPC00B + nOffset,
+                                         sRPC.adfLINE_DEN_COEFF[i],
+                                         pbPrecisionLoss ) )
+        {
+            CPLFree(pszRPC00B);
+            return NULL;
+        }
+        nOffset += 12;
+    }
+    for( i = 0; i < 20; i++ )
+    {
+        if( !NITFFormatRPC00BCoefficient(pszRPC00B + nOffset,
+                                         sRPC.adfSAMP_NUM_COEFF[i],
+                                         pbPrecisionLoss ) )
+        {
+            CPLFree(pszRPC00B);
+            return NULL;
+        }
+        nOffset += 12;
+    }
+    for( i = 0; i < 20; i++ )
+    {
+        if( !NITFFormatRPC00BCoefficient(pszRPC00B + nOffset,
+                                         sRPC.adfSAMP_DEN_COEFF[i],
+                                         pbPrecisionLoss ) )
+        {
+            CPLFree(pszRPC00B);
+            return NULL;
+        }
+        nOffset += 12;
+    }
+
+    CPLAssert( nOffset == 1041 );
+    pszRPC00B[nOffset] = '\0';
+    CPLAssert( strlen(pszRPC00B) == 1041 );
+    CPLAssert( strchr(pszRPC00B, ' ') == NULL );
+
+    return pszRPC00B;
+}
+
 /************************************************************************/
 /*                           NITFReadRPC00B()                           */
 /*                                                                      */
@@ -2271,13 +2625,8 @@ char **NITFReadPIAIMC( NITFImage *psImage )
 int NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo *psRPC )
 
 {
-    static const int anRPC00AMap[] = /* See ticket #2040 */
-    {0, 1, 2, 3, 4, 5, 6 , 10, 7, 8, 9, 11, 14, 17, 12, 15, 18, 13, 16, 19};
-
-    const char *pachTRE;
-    char szTemp[100];
-    int  i;
-    int  bRPC00A = FALSE;
+    const char* pachTRE;
+    int  bIsRPC00A = FALSE;
     int  nTRESize;
 
     psRPC->SUCCESS = 0;
@@ -2293,7 +2642,7 @@ int NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo *psRPC )
         pachTRE = NITFFindTRE( psImage->pachTRE, psImage->nTREBytes,
                                "RPC00A", &nTRESize );
         if( pachTRE )
-            bRPC00A = TRUE;
+            bIsRPC00A = TRUE;
     }
 
     if( pachTRE == NULL )
@@ -2310,13 +2659,32 @@ int NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo *psRPC )
         return FALSE;
     }
 
+    return NITFDeserializeRPC00B( (const GByte*)pachTRE, psRPC, bIsRPC00A );
+}
+
+/************************************************************************/
+/*                          NITFDeserializeRPC00B()                     */
+/************************************************************************/
+
+int NITFDeserializeRPC00B( const GByte* pabyTRE, NITFRPC00BInfo *psRPC,
+                           int bIsRPC00A )
+{
+    const char* pachTRE = (const char*)pabyTRE;
+    char szTemp[100];
+    int i;
+    static const int anRPC00AMap[] = /* See ticket #2040 */
+    {0, 1, 2, 3, 4, 5, 6 , 10, 7, 8, 9, 11, 14, 17, 12, 15, 18, 13, 16, 19};
+
 /* -------------------------------------------------------------------- */
 /*      Parse out field values.                                         */
 /* -------------------------------------------------------------------- */
     psRPC->SUCCESS = atoi(NITFGetField(szTemp, pachTRE, 0, 1 ));
 
     if ( !psRPC->SUCCESS )
-	fprintf( stdout, "RPC Extension not Populated!\n");
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "RPC Extension not Populated!");
+    }
 
     psRPC->ERR_BIAS = CPLAtof(NITFGetField(szTemp, pachTRE, 1, 7 ));
     psRPC->ERR_RAND = CPLAtof(NITFGetField(szTemp, pachTRE, 8, 7 ));
@@ -2340,7 +2708,7 @@ int NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo *psRPC )
     {
         int iSrcCoef = i;
 
-        if( bRPC00A )
+        if( bIsRPC00A )
             iSrcCoef = anRPC00AMap[i];
 
         psRPC->LINE_NUM_COEFF[i] =
@@ -3406,7 +3774,7 @@ static int NITFLoadVQTables( NITFImage *psImage, int bTryGuessingOffset )
     int     i;
     GUInt32 nVQOffset=0 /*, nVQSize=0 */;
     GByte abyTestChunk[1000];
-    GByte abySignature[6];
+    const GByte abySignature[6] = { 0x00, 0x00, 0x00, 0x06, 0x00, 0x0E };
 
 /* -------------------------------------------------------------------- */
 /*      Do we already have the VQ tables?                               */
@@ -3432,13 +3800,6 @@ static int NITFLoadVQTables( NITFImage *psImage, int bTryGuessingOffset )
 /* -------------------------------------------------------------------- */
 /*      Does it look like we have the tables properly identified?       */
 /* -------------------------------------------------------------------- */
-    abySignature[0] = 0x00;
-    abySignature[1] = 0x00;
-    abySignature[2] = 0x00;
-    abySignature[3] = 0x06;
-    abySignature[4] = 0x00;
-    abySignature[5] = 0x0E;
-
     if( VSIFSeekL( psImage->psFile->fp, nVQOffset, SEEK_SET ) != 0 ||
         VSIFReadL( abyTestChunk, sizeof(abyTestChunk), 1, psImage->psFile->fp ) != 1 )
     {
@@ -3514,6 +3875,7 @@ int NITFRPCGeoToImage( NITFRPC00BInfo *psRPC,
     double dfLineNumerator, dfLineDenominator,
         dfPixelNumerator, dfPixelDenominator;
     double dfPolyTerm[20];
+    double* pdfPolyTerm = dfPolyTerm;
     int i;
 
 /* -------------------------------------------------------------------- */
@@ -3527,7 +3889,7 @@ int NITFRPCGeoToImage( NITFRPC00BInfo *psRPC,
 /*      Compute the 20 terms.                                           */
 /* -------------------------------------------------------------------- */
 
-    dfPolyTerm[0] = 1.0;
+    pdfPolyTerm[0] = 1.0; /* workaround cppcheck false positive */
     dfPolyTerm[1] = dfLong;
     dfPolyTerm[2] = dfLat;
     dfPolyTerm[3] = dfHeight;
@@ -3865,6 +4227,8 @@ static void NITFPossibleIGEOLOReorientation( NITFImage *psImage )
 /*      Read DPPDB IMRFCA TRE (and the associated IMASDA TRE) if it is  */
 /*      available. IMRFCA RPC coefficients are remapped into RPC00B     */
 /*      organization.                                                   */
+/*      See table 68 for IMASDA and table 69 for IMRFCA in              */
+/*      http://earth-info.nga.mil/publications/specs/printed/89034/89034DPPDB.pdf */
 /************************************************************************/
 int NITFReadIMRFCA( NITFImage *psImage, NITFRPC00BInfo *psRPC )
 {
diff --git a/frmts/nitf/nitflib.h b/frmts/nitf/nitflib.h
index 7464868..ce4c023 100644
--- a/frmts/nitf/nitflib.h
+++ b/frmts/nitf/nitflib.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nitflib.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: nitflib.h 35897 2016-10-24 11:54:24Z goatbar $
  *
  * Project:  NITF Read/Write Library
  * Purpose:  Main GDAL independent include file for NITF support.
@@ -126,7 +126,6 @@ typedef struct
   unsigned int     histogramTableOffset;
 } NITFColormapRecord;
 
-
 typedef struct {
     NITFFile  *psFile;
     int        iSegment;
@@ -310,9 +309,9 @@ typedef enum {
 /*      RPC structure, and function to fill it.                         */
 /* -------------------------------------------------------------------- */
 typedef struct  {
-    int			SUCCESS;
+    int         SUCCESS;
 
-    double		ERR_BIAS;
+    double      ERR_BIAS;
     double      ERR_RAND;
 
     double      LINE_OFF;
@@ -333,6 +332,10 @@ typedef struct  {
     double      SAMP_DEN_COEFF[20];
 } NITFRPC00BInfo;
 
+char* NITFFormatRPC00BFromMetadata( char** papszRPC, int* pbPrecisionLoss );
+int NITFDeserializeRPC00B( const GByte* pabyTRE, NITFRPC00BInfo *psRPC,
+                           int bIsRPC00A  );
+
 int CPL_DLL NITFReadRPC00B( NITFImage *psImage, NITFRPC00BInfo * );
 int CPL_DLL NITFRPCGeoToImage(NITFRPC00BInfo *, double, double, double,
                               double *, double *);
@@ -341,37 +344,37 @@ int CPL_DLL NITFRPCGeoToImage(NITFRPC00BInfo *, double, double, double,
 /*      ICHIP structure, and function to fill it.                         */
 /* -------------------------------------------------------------------- */
 typedef struct {
-	int		XFRM_FLAG;
-	double	SCALE_FACTOR;
-	int		ANAMORPH_CORR;
-	int		SCANBLK_NUM;
+        int     XFRM_FLAG;
+        double  SCALE_FACTOR;
+        int     ANAMORPH_CORR;
+        int     SCANBLK_NUM;
 
-	double	OP_ROW_11;
-	double	OP_COL_11;
+        double  OP_ROW_11;
+        double  OP_COL_11;
 
-	double	OP_ROW_12;
-	double	OP_COL_12;
+        double  OP_ROW_12;
+        double  OP_COL_12;
 
-	double	OP_ROW_21;
-	double	OP_COL_21;
+        double  OP_ROW_21;
+        double  OP_COL_21;
 
-	double	OP_ROW_22;
-	double	OP_COL_22;
+        double  OP_ROW_22;
+        double  OP_COL_22;
 
-	double	FI_ROW_11;
-	double	FI_COL_11;
+        double  FI_ROW_11;
+        double  FI_COL_11;
 
-	double	FI_ROW_12;
-	double	FI_COL_12;
+        double  FI_ROW_12;
+        double  FI_COL_12;
 
-	double	FI_ROW_21;
-	double	FI_COL_21;
+        double  FI_ROW_21;
+        double  FI_COL_21;
 
-	double	FI_ROW_22;
-	double	FI_COL_22;
+        double  FI_ROW_22;
+        double  FI_COL_22;
 
-	int		FI_ROW;
-	int		FI_COL;
+        int     FI_ROW;
+        int     FI_COL;
 } NITFICHIPBInfo;
 
 int CPL_DLL NITFReadICHIPB( NITFImage *psImage, NITFICHIPBInfo * );
@@ -379,9 +382,6 @@ int CPL_DLL NITFReadICHIPB( NITFImage *psImage, NITFICHIPBInfo * );
 double CPL_DLL
         NITF_WGS84_Geocentric_Latitude_To_Geodetic_Latitude( double dfLat );
 
-
-
-
 typedef struct
 {
     const char* code;
diff --git a/frmts/nitf/nitfrasterband.cpp b/frmts/nitf/nitfrasterband.cpp
index c487a17..4e2796f 100644
--- a/frmts/nitf/nitfrasterband.cpp
+++ b/frmts/nitf/nitfrasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: nitfrasterband.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  NITFRasterBand (and related proxy band) implementations.
@@ -31,11 +30,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "nitfdataset.h"
-#include "cpl_string.h"
+
+#include <climits>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+#include <map>
+#include <utility>
+
+#include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "nitflib.h"
+
 
-CPL_CVSID("$Id: nitfrasterband.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: nitfrasterband.cpp 37346 2017-02-11 23:03:44Z goatbar $");
 
 /************************************************************************/
 /*                       NITFMakeColorTable()                           */
@@ -62,8 +81,7 @@ static GDALColorTable* NITFMakeColorTable(NITFImage* psImage, NITFBandInfo *psBa
 
         if (psImage->bNoDataSet)
         {
-            GDALColorEntry sEntry;
-            sEntry.c1 = sEntry.c2 = sEntry.c3 = sEntry.c4 = 0;
+            GDALColorEntry sEntry = { 0, 0, 0, 0 };
             poColorTable->SetColorEntry( psImage->nNoDataValue, &sEntry );
         }
     }
@@ -104,12 +122,11 @@ NITFProxyPamRasterBand::~NITFProxyPamRasterBand()
     while(oIter != oMDMap.end())
     {
         CSLDestroy(oIter->second);
-        oIter ++;
+        ++oIter;
     }
 }
 
-
-char      **NITFProxyPamRasterBand::GetMetadata( const char * pszDomain  )
+char **NITFProxyPamRasterBand::GetMetadata( const char * pszDomain  )
 {
     GDALRasterBand* _poSrcBand = RefUnderlyingRasterBand();
     if (_poSrcBand)
@@ -134,7 +151,6 @@ char      **NITFProxyPamRasterBand::GetMetadata( const char * pszDomain  )
     return GDALPamRasterBand::GetMetadata(pszDomain);
 }
 
-
 const char *NITFProxyPamRasterBand::GetMetadataItem( const char * pszName,
                                                      const char * pszDomain )
 {
@@ -224,7 +240,6 @@ CPLErr NITFProxyPamRasterBand::ComputeStatistics( int bApproxOK,
     return CE_Failure;
 }
 
-
 #define RB_PROXY_METHOD_GET_DBL_WITH_SUCCESS(methodName) \
 double NITFProxyPamRasterBand::methodName( int *pbSuccess ) \
 { \
@@ -336,7 +351,6 @@ RB_PROXY_METHOD_WITH_RET(GDALRasterBand*, NULL, GetMaskBand, (), ())
 RB_PROXY_METHOD_WITH_RET(int, 0, GetMaskFlags, (), ())
 RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlagsIn ), (nFlagsIn))
 
-
 /************************************************************************/
 /*                 UnrefUnderlyingRasterBand()                        */
 /************************************************************************/
@@ -353,16 +367,17 @@ void NITFProxyPamRasterBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALRasterBand
 /*                           NITFRasterBand()                           */
 /************************************************************************/
 
-NITFRasterBand::NITFRasterBand( NITFDataset *poDSIn, int nBandIn )
-
+NITFRasterBand::NITFRasterBand( NITFDataset *poDSIn, int nBandIn ) :
+    psImage(poDSIn->psImage),
+    poColorTable(NULL),
+    pUnpackData(NULL),
+    bScanlineAccess(FALSE)
 {
     NITFBandInfo *psBandInfo = poDSIn->psImage->pasBandInfo + nBandIn - 1;
 
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-
+    poDS = poDSIn;
+    nBand = nBandIn;
     eAccess = poDSIn->eAccess;
-    psImage = poDSIn->psImage;
 
 /* -------------------------------------------------------------------- */
 /*      Translate data type(s).                                         */
@@ -445,7 +460,6 @@ NITFRasterBand::NITFRasterBand( NITFDataset *poDSIn, int nBandIn )
     ||  psImage->nBitsPerSample == 12 )
         SetMetadataItem( "NBITS", CPLString().Printf("%d", psImage->nBitsPerSample), "IMAGE_STRUCTURE" );
 
-    pUnpackData = NULL;
     if (psImage->nBitsPerSample == 3
     ||  psImage->nBitsPerSample == 5
     ||  psImage->nBitsPerSample == 6
@@ -730,7 +744,7 @@ CPLErr NITFRasterBand::SetColorTable( GDALColorTable *poNewCT )
     GByte abyNITFLUT[768];
     memset( abyNITFLUT, 0, 768 );
 
-    const int nCount = MIN(256,poNewCT->GetColorEntryCount());
+    const int nCount = std::min(256, poNewCT->GetColorEntryCount());
     for( int i = 0; i < nCount; i++ )
     {
         GDALColorEntry sEntry;
@@ -897,17 +911,18 @@ void NITFRasterBand::Unpack( GByte* pData )
 NITFWrapperRasterBand::NITFWrapperRasterBand( NITFDataset * poDSIn,
                                               GDALRasterBand* poBaseBandIn,
                                               int nBandIn) :
-    poColorTable(NULL)
+    poBaseBand(poBaseBandIn),
+    poColorTable(NULL),
+    eInterp(poBaseBandIn->GetColorInterpretation()),
+    bIsJPEG(poBaseBandIn->GetDataset() != NULL &&
+            poBaseBandIn->GetDataset()->GetDriver() != NULL &&
+            EQUAL(poBaseBandIn->GetDataset()->GetDriver()->GetDescription(),
+                  "JPEG"))
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->poBaseBand = poBaseBandIn;
-    eDataType = poBaseBand->GetRasterDataType();
+    poDS = poDSIn;
+    nBand = nBandIn;
     poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
-    eInterp = poBaseBand->GetColorInterpretation();
-    bIsJPEG = poBaseBand->GetDataset() != NULL &&
-              poBaseBand->GetDataset()->GetDriver() != NULL &&
-              EQUAL(poBaseBand->GetDataset()->GetDriver()->GetDescription(), "JPEG");
+    eDataType = poBaseBandIn->GetRasterDataType();
 }
 
 /************************************************************************/
diff --git a/frmts/nitf/nitfwritejpeg.cpp b/frmts/nitf/nitfwritejpeg.cpp
index 07532dd..08cec8d 100644
--- a/frmts/nitf/nitfwritejpeg.cpp
+++ b/frmts/nitf/nitfwritejpeg.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: nitfwritejpeg.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  NITF Read/Write Translator
  * Purpose:  GDALDataset/GDALRasterBand implementation on top of "nitflib".
@@ -36,6 +35,8 @@
 #include "cpl_port.h"
 #include "gdal_pam.h"
 
+CPL_CVSID("$Id: nitfwritejpeg.cpp 34811 2016-07-28 15:15:05Z goatbar $");
+
 CPL_C_START
 #ifdef LIBJPEG_12_PATH
 #  include LIBJPEG_12_PATH
diff --git a/frmts/nitf/rpftocdataset.cpp b/frmts/nitf/rpftocdataset.cpp
index 1002c36..8bbbf8b 100644
--- a/frmts/nitf/rpftocdataset.cpp
+++ b/frmts/nitf/rpftocdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rpftocdataset.cpp
  *
  * Project:  RPF TOC read Translator
  * Purpose:  Implementation of RPFTOCDataset and RPFTOCSubDataset.
@@ -27,16 +26,28 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "rpftoclib.h"
+
+#include <cmath>
+#include <cstdio>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
 #include "gdal_proxy.h"
 #include "ogr_spatialref.h"
-#include "rpftoclib.h"
+#include "nitflib.h"
 #include "vrtdataset.h"
 
-CPL_CVSID("$Id: rpftocdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
+CPL_CVSID("$Id: rpftocdataset.cpp 37346 2017-02-11 23:03:44Z goatbar $");
 
 static const int GEOTRSFRM_TOPLEFT_X = 0;
 static const int GEOTRSFRM_WE_RES = 1;
@@ -62,7 +73,7 @@ static const int GEOTRSFRM_NS_RES = 5;
 
 class RPFTOCDataset : public GDALPamDataset
 {
-  char	    **papszSubDatasets;
+  char      **papszSubDatasets;
   char       *pszProjection;
   int         bGotGeoTransform;
   double      adfGeoTransform[6];
@@ -75,7 +86,9 @@ class RPFTOCDataset : public GDALPamDataset
         pszProjection(NULL),
         bGotGeoTransform(FALSE),
         papszFileList(NULL)
-    {}
+    {
+        memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
+    }
 
     virtual ~RPFTOCDataset()
     {
@@ -84,9 +97,9 @@ class RPFTOCDataset : public GDALPamDataset
         CSLDestroy( papszFileList );
     }
 
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
 
-    virtual char      **GetFileList() { return CSLDuplicate(papszFileList); }
+    virtual char      **GetFileList() override { return CSLDuplicate(papszFileList); }
 
     void                AddSubDataset(const char* pszFilename, RPFTocEntry* tocEntry );
 
@@ -96,7 +109,7 @@ class RPFTOCDataset : public GDALPamDataset
         nRasterYSize = rasterYSize;
     }
 
-    virtual CPLErr GetGeoTransform( double * padfGeoTransform)
+    virtual CPLErr GetGeoTransform( double * padfGeoTransform) override
     {
         if (bGotGeoTransform)
         {
@@ -106,21 +119,21 @@ class RPFTOCDataset : public GDALPamDataset
         return CE_Failure;
     }
 
-    virtual CPLErr SetGeoTransform( double * padfGeoTransform)
+    virtual CPLErr SetGeoTransform( double * padfGeoTransform) override
     {
         bGotGeoTransform = TRUE;
         memcpy(adfGeoTransform, padfGeoTransform, 6 * sizeof(double));
         return CE_None;
     }
 
-    virtual CPLErr SetProjection( const char * projectionRef )
+    virtual CPLErr SetProjection( const char * projectionRef ) override
     {
         CPLFree(pszProjection);
         pszProjection = CPLStrdup(projectionRef);
         return CE_None;
     }
 
-    virtual const char *GetProjectionRef(void)
+    virtual const char *GetProjectionRef(void) override
     {
         return (pszProjection) ? pszProjection : "";
     }
@@ -177,7 +190,7 @@ class RPFTOCSubDataset : public VRTDataset
         CPLFree(cachedTileData);
     }
 
-    virtual char      **GetFileList() { return CSLDuplicate(papszFileList); }
+    virtual char      **GetFileList() override { return CSLDuplicate(papszFileList); }
 
     void* GetCachedTile(const char* tileFileName, int nBlockXOff, int nBlockYOff)
     {
@@ -222,7 +235,8 @@ class RPFTOCProxyRasterDataSet : public GDALProxyPoolDataset
     /* The following parameters are only for sanity checking */
     int checkDone;
     int checkOK;
-    double nwLong, nwLat;
+    double nwLong;
+    double nwLat;
     GDALColorTable* colorTableRef;
     int bHasNoDataValue;
     double noDataValue;
@@ -248,12 +262,12 @@ class RPFTOCProxyRasterDataSet : public GDALProxyPoolDataset
             return noDataValue;
         }
 
-        GDALDataset* RefUnderlyingDataset()
+        GDALDataset* RefUnderlyingDataset() override
         {
             return GDALProxyPoolDataset::RefUnderlyingDataset();
         }
 
-        void UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset)
+        void UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset) override
         {
             GDALProxyPoolDataset::UnrefUnderlyingDataset(poUnderlyingDataset);
         }
@@ -295,17 +309,18 @@ class RPFTOCProxyRasterBandRGBA : public GDALPamRasterBand
             eDataType = GDT_Byte;
             this->nBand = nBandIn;
             blockByteSize = nBlockXSize * nBlockYSize;
+            memset( colorTable, 0, sizeof(colorTable) );
         }
         virtual ~RPFTOCProxyRasterBandRGBA() {}
 
-        virtual GDALColorInterp GetColorInterpretation()
+        virtual GDALColorInterp GetColorInterpretation() override
         {
             return (GDALColorInterp)(GCI_RedBand + nBand - 1);
         }
 
     protected:
         virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff,
-                                   void * pImage );
+                                   void * pImage ) override;
 };
 
 /************************************************************************/
@@ -335,7 +350,6 @@ void  RPFTOCProxyRasterBandRGBA::Expand(void* pImage, const void* srcImage)
                     colorTable[four_pixels & 0xFF];
         }
     }
-
 }
 
 /************************************************************************/
@@ -427,10 +441,11 @@ CPLErr RPFTOCProxyRasterBandRGBA::IReadBlock( int nBlockXOff, int nBlockYOff,
             Expand(pImage, cachedImage);
             ret = CE_None;
         }
-
     }
     else
+    {
         ret = CE_Failure;
+    }
 
     proxyDS->UnrefUnderlyingDataset(ds);
 
@@ -464,19 +479,20 @@ class RPFTOCProxyRasterBandPalette : public GDALPamRasterBand
             this->nBlockYSize = nBlockYSizeIn;
             eDataType = GDT_Byte;
             this->nBand = nBandIn;
+            memset( remapLUT, 0, sizeof(remapLUT) );
         }
 
-        virtual GDALColorInterp GetColorInterpretation()
+        virtual GDALColorInterp GetColorInterpretation() override
         {
             return GCI_PaletteIndex;
         }
 
-        virtual double GetNoDataValue(int* bHasNoDataValue)
+        virtual double GetNoDataValue(int* bHasNoDataValue) override
         {
             return ( reinterpret_cast<RPFTOCProxyRasterDataSet *>( poDS ) )->GetNoDataValue(bHasNoDataValue);
         }
 
-        virtual GDALColorTable *GetColorTable()
+        virtual GDALColorTable *GetColorTable() override
         {
             // TODO: This casting is a bit scary.
             return const_cast<GDALColorTable *>(
@@ -485,7 +501,7 @@ class RPFTOCProxyRasterBandPalette : public GDALPamRasterBand
 
     protected:
         virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff,
-                                   void * pImage );
+                                   void * pImage ) override;
 };
 
 /************************************************************************/
@@ -530,7 +546,6 @@ CPLErr RPFTOCProxyRasterBandPalette::IReadBlock( int nBlockXOff, int nBlockYOff,
             initDone = TRUE;
         }
 
-
         if (samePalette == FALSE)
         {
             unsigned char* data = (unsigned char*)pImage;
@@ -539,10 +554,11 @@ CPLErr RPFTOCProxyRasterBandPalette::IReadBlock( int nBlockXOff, int nBlockYOff,
                 data[i] = remapLUT[data[i]];
             }
         }
-
     }
     else
+    {
         ret = CE_Failure;
+    }
 
     proxyDS->UnrefUnderlyingDataset(ds);
 
@@ -553,51 +569,69 @@ CPLErr RPFTOCProxyRasterBandPalette::IReadBlock( int nBlockXOff, int nBlockYOff,
 /*                    RPFTOCProxyRasterDataSet()                         */
 /************************************************************************/
 
-RPFTOCProxyRasterDataSet::RPFTOCProxyRasterDataSet
-        (RPFTOCSubDataset* subdatasetIn,
-         const char* fileNameIn,
-         int nRasterXSizeIn, int nRasterYSizeIn,
-         int nBlockXSizeIn, int nBlockYSizeIn,
-         const char* projectionRefIn, double nwLongIn, double nwLatIn,
-         int nBandsIn) :
-    /* Mark as shared since the VRT will take several references if we are in RGBA mode (4 bands for this dataset) */
-            GDALProxyPoolDataset(fileNameIn, nRasterXSizeIn, nRasterYSizeIn, GA_ReadOnly, TRUE, projectionRefIn),
+RPFTOCProxyRasterDataSet::RPFTOCProxyRasterDataSet(
+    RPFTOCSubDataset* subdatasetIn,
+    const char* fileNameIn,
+    int nRasterXSizeIn, int nRasterYSizeIn,
+    int nBlockXSizeIn, int nBlockYSizeIn,
+    const char* projectionRefIn, double nwLongIn, double nwLatIn,
+    int nBandsIn ) :
+    // Mark as shared since the VRT will take several references if we are in
+    // RGBA mode (4 bands for this dataset).
+    GDALProxyPoolDataset(fileNameIn, nRasterXSizeIn, nRasterYSizeIn,
+                         GA_ReadOnly, TRUE, projectionRefIn),
     checkDone(FALSE),
     checkOK(FALSE),
+    nwLong(nwLongIn),
+    nwLat(nwLatIn),
     colorTableRef(NULL),
     bHasNoDataValue(FALSE),
-    noDataValue(0)
+    noDataValue(0),
+    subdataset(subdatasetIn)
 {
-    this->subdataset = subdatasetIn;
-    this->nwLong = nwLongIn;
-    this->nwLat = nwLatIn;
-
     if (nBandsIn == 4)
     {
         for( int i = 0; i < 4; i++ )
         {
-            SetBand(i + 1, new RPFTOCProxyRasterBandRGBA(this, i+1, nBlockXSizeIn, nBlockYSizeIn));
+            SetBand(
+                i + 1,
+                new RPFTOCProxyRasterBandRGBA(this, i+1,
+                                              nBlockXSizeIn, nBlockYSizeIn));
         }
     }
     else
-        SetBand(1, new RPFTOCProxyRasterBandPalette(this, 1, nBlockXSizeIn, nBlockYSizeIn));
+    {
+        SetBand(
+            1,
+            new RPFTOCProxyRasterBandPalette(this, 1,
+                                             nBlockXSizeIn, nBlockYSizeIn));
+    }
 }
 
 /************************************************************************/
 /*                    SanityCheckOK()                                   */
 /************************************************************************/
 
-#define WARN_ON_FAIL(x) do { if (!(x)) { CPLError(CE_Warning, CPLE_AppDefined, "For %s, assert '" #x "' failed", GetDescription()); } } while(0)
-#define ERROR_ON_FAIL(x) do { if (!(x)) { CPLError(CE_Warning, CPLE_AppDefined, "For %s, assert '" #x "' failed", GetDescription()); checkOK = FALSE; } } while(0)
+#define WARN_ON_FAIL(x) do { if (!(x)) { \
+    CPLError(CE_Warning, CPLE_AppDefined, \
+             "For %s, assert '" #x "' failed", \
+             GetDescription()); } } while( false )
+#define ERROR_ON_FAIL(x) do { if (!(x)) { \
+    CPLError(CE_Warning, CPLE_AppDefined, \
+             "For %s, assert '" #x "' failed", \
+             GetDescription()); checkOK = FALSE; } } while( false )
 
 int RPFTOCProxyRasterDataSet::SanityCheckOK(GDALDataset* sourceDS)
 {
-    int src_nBlockXSize, src_nBlockYSize;
-    int nBlockXSize, nBlockYSize;
-    double l_adfGeoTransform[6];
     if (checkDone)
         return checkOK;
 
+    int src_nBlockXSize;
+    int src_nBlockYSize;
+    int nBlockXSize;
+    int nBlockYSize;
+    double l_adfGeoTransform[6] = {};
+
     checkOK = TRUE;
     checkDone = TRUE;
 
@@ -626,7 +660,7 @@ int RPFTOCProxyRasterDataSet::SanityCheckOK(GDALDataset* sourceDS)
 
 static const char* MakeTOCEntryName(RPFTocEntry* tocEntry )
 {
-    char* str;
+    char* str = NULL;
     if (tocEntry->seriesAbbreviation)
         str = const_cast<char *>(
             CPLSPrintf( "%s_%s_%s_%s_%d", tocEntry->type,
@@ -653,7 +687,7 @@ static const char* MakeTOCEntryName(RPFTocEntry* tocEntry )
 void RPFTOCDataset::AddSubDataset( const char* pszFilename,  RPFTocEntry* tocEntry )
 
 {
-    char	szName[80];
+    char szName[80];
     const int nCount = CSLCount(papszSubDatasets ) / 2;
 
     snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
@@ -689,14 +723,21 @@ char **RPFTOCDataset::GetMetadata( const char *pszDomain )
 /*                  NITFCreateVRTDataSetFromTocEntry()                  */
 /************************************************************************/
 
-
-#define ASSERT_CREATE_VRT(x) do { if (!(x)) { CPLError(CE_Failure, CPLE_AppDefined, "For %s, assert '" #x "' failed", entry->frameEntries[i].fullFilePath); if (poSrcDS) GDALClose(poSrcDS); CPLFree(projectionRef); return NULL;} } while(0)
+#define ASSERT_CREATE_VRT(x) do { if (!(x)) { \
+    CPLError(CE_Failure, CPLE_AppDefined, \
+             "For %s, assert '" #x "' failed", \
+             entry->frameEntries[i].fullFilePath); \
+    if (poSrcDS) GDALClose(poSrcDS); CPLFree(projectionRef); \
+    return NULL;} } while( false )
 
 /* Builds a RPFTOCSubDataset from the set of files of the toc entry */
-GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInformationName,
-                                                         const char* pszTOCFileName, int nEntry,
-                                                         const RPFTocEntry* entry, int isRGBA,
-                                                         char** papszMetadataRPFTOCFile)
+GDALDataset *
+RPFTOCSubDataset::CreateDataSetFromTocEntry( const char* openInformationName,
+                                             const char* pszTOCFileName,
+                                             int nEntry,
+                                             const RPFTocEntry* entry,
+                                             int isRGBA,
+                                             char** papszMetadataRPFTOCFile)
 {
     GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("VRT");
     if( poDriver == NULL )
@@ -713,8 +754,9 @@ GDALDataset* RPFTOCSubDataset::CreateDataSetFromTocEntry(const char* openInforma
         (entry->nwLat - entry->seLat)
         / (entry->nVertFrames * entry->vertInterval) + 0.5);
 
-    int nBlockXSize = 0, nBlockYSize = 0;
-    double geoTransf[6];
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
+    double geoTransf[6] = {};
     char* projectionRef = NULL;
     int index = 0;
 
@@ -1064,8 +1106,11 @@ GDALDataset* RPFTOCDataset::OpenFileTOC(NITFFile *psFile,
 
         bool ok = false;
         char* projectionRef = NULL;
-        double nwLong = 0, nwLat = 0, seLong = 0, seLat = 0;
-        double adfGeoTransform[6];
+        double nwLong = 0.0;
+        double nwLat = 0.0;
+        double seLong = 0.0;
+        double seLat = 0.0;
+        double adfGeoTransform[6] = {};
 
         ds->papszFileList = CSLAddString(ds->papszFileList, pszFilename);
 
@@ -1159,8 +1204,8 @@ int RPFTOCDataset::Identify( GDALOpenInfo * poOpenInfo )
         return TRUE;
 
 /* -------------------------------------------------------------------- */
-/*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/
+/*      First we check to see if the file has the expected header       */
+/*      bytes.                                                          */
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->nHeaderBytes < 48 )
         return FALSE;
@@ -1270,7 +1315,6 @@ GDALDataset *RPFTOCDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLFree(entryName);
         return NULL;
     }
-
 }
 
 /************************************************************************/
diff --git a/frmts/nitf/rpftocfile.cpp b/frmts/nitf/rpftocfile.cpp
index ffda506..f676014 100644
--- a/frmts/nitf/rpftocfile.cpp
+++ b/frmts/nitf/rpftocfile.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rpftocfile.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  RPF A.TOC read Library
  * Purpose:  Module responsible for opening a RPF TOC file, populating RPFToc
@@ -44,12 +43,22 @@
  ******************************************************************************
  */
 
+#include "cpl_port.h"
 #include "rpftoclib.h"
-#include "cpl_vsi.h"
+
+#include <climits>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "nitflib.h"
 
-CPL_CVSID("$Id: rpftocfile.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: rpftocfile.cpp 37346 2017-02-11 23:03:44Z goatbar $");
 
 /************************************************************************/
 /*                        RPFTOCTrim()                                    */
@@ -104,7 +113,6 @@ RPFToc* RPFTOCRead(const char* pszFilename, NITFFile* psFile)
     return  RPFTOCReadFromBuffer(pszFilename, psFile->fp, pachTRE);
 }
 
-
 /* This function is directly inspired by function parse_toc coming from ogdi/driver/rpf/utils.c */
 
 RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char* tocHeader)
@@ -557,7 +565,7 @@ RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char*
         {
             char* baseDir = CPLStrdup(CPLGetDirname(pszFilename));
             VSIStatBufL sStatBuf;
-            char* subdir;
+            char* subdir = NULL;
             if (CPLIsFilenameRelative(frameEntry->directory) == FALSE)
                 subdir = CPLStrdup(frameEntry->directory);
             else if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == 0)
diff --git a/frmts/nitf/rpftoclib.h b/frmts/nitf/rpftoclib.h
index 1566e4b..a77cd51 100644
--- a/frmts/nitf/rpftoclib.h
+++ b/frmts/nitf/rpftoclib.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rpftoclib.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: rpftoclib.h 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  RPF A.TOC read Library
  * Purpose:  Main GDAL independent include file for RPF TOC support.
diff --git a/frmts/northwood/frmt_nwtgrd.html b/frmts/northwood/frmt_nwtgrd.html
new file mode 100644
index 0000000..648e33c
--- /dev/null
+++ b/frmts/northwood/frmt_nwtgrd.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html lang=en>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>NWT_GRD -- Northwood/Vertical Mapper File Format</title>
+</head>
+
+<body>
+
+<h1>NWT_GRD/NWT_GRC -- Northwood/Vertical Mapper File Format</h1>
+
+<p>Support for reading & writing Northwood GRID raster formats. This format is also known as Vertical Mapper Grid or MapInfo Grid and
+is commonly used in MapInfo Pro software</p>
+<p>Full read/write support of *.grd (grid) files is available, read-only support is available for classified grids (*.grc).<p>
+<p>For writing, Float32 is the only supported band type.</p>
+
+<h2> Color Information </h2>
+<p> The grid formats have color information embedded in the grid file header. This describes how to
+scale data values to RGB values. When opening in read mode, the driver will report 4 bands - R, G, B and
+the data band. In reality there is 1 band and the RGB bands are 'virtual', made from scaling data. For this reason, when
+opening in write mode only 1 band is reported and the RGB bands are unavailable.</p>
+
+<h2>Metadata</h2>
+<p>GDAL Metadata items are stored in the PAM .aux.xml file</p>
+<p>Northwood Grid itself does not natively support arbritrary metadata</p>
+
+<h2>Nodata values</h2>
+<p>In write mode, it is possible to designate any value as the nodata value. These values are translated
+to the Vertical Mapper no data value when writing. Therefore, in read mode the nodata value is always reported
+as -1e37.</p>
+
+<h3>Creation Options</h3>
+
+<ul>
+<li><p><b>ZMIN=-2e37</b>: Set the minimum Z value. Data are scaled on disk to a 16 bit integer and the Z value range
+is used to scale data. If not set, it may cause incorrect data to be written when using 'Create()' or a full recalculation
+of the source dataset statistics when using 'CreateCopy'</p></li>
+<li><p><b>ZMAX=2e38</b>: Set the maximum Z value. Data are scaled on disk to a 16 bit integer and the Z value range
+is used to scale data. If not set, it may cause incorrect data to be written when using 'Create()' or a full recalculation
+of the source dataset statistics when using 'CreateCopy'</p></li>
+<li><p><b>BRIGHTNESS=50</b>: Set the brightness level. Only affects opening the file in MapInfo/Vertical Mapper</p></li>
+<li><p><b>CONTRAST=50</b>: Set the contrast level. Only affects opening the file in MapInfo/Vertical Mapper</p></li>
+<li><p><b>TRANSCOLOR=0</b>: Set a transparent color level. Only affects opening the file in MapInfo/Vertical Mapper</p></li>
+<li><p><b>TRANSLUCENCY=0</b>: Set the translucency level. Only affects opening the file in MapInfo/Vertical Mapper</p></li>
+</ul>
+
+
+</body>
+</html>
diff --git a/frmts/northwood/grcdataset.cpp b/frmts/northwood/grcdataset.cpp
index b3851a6..d13e82f 100644
--- a/frmts/northwood/grcdataset.cpp
+++ b/frmts/northwood/grcdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: grcdataset.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  GRC Reader
  * Purpose:  GDAL driver for Northwood Classified Format
@@ -38,6 +37,8 @@
 #include "../../ogr/ogrsf_frmts/mitab/mitab.h"
 #endif
 
+CPL_CVSID("$Id: grcdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+
 /************************************************************************/
 /* ==================================================================== */
 /*                             NWT_GRCDataset                           */
@@ -66,8 +67,8 @@ class NWT_GRCDataset : public GDALPamDataset
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * poOpenInfo );
 
-    CPLErr GetGeoTransform( double *padfTransform );
-    const char *GetProjectionRef();
+    CPLErr GetGeoTransform( double *padfTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
 /************************************************************************/
@@ -85,23 +86,22 @@ class NWT_GRCRasterBand : public GDALPamRasterBand
     NWT_GRCRasterBand( NWT_GRCDataset *, int );
     virtual ~NWT_GRCRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual double GetNoDataValue( int *pbSuccess );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual double GetNoDataValue( int *pbSuccess ) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual char **GetCategoryNames();
-    virtual GDALColorTable *GetColorTable();
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual char **GetCategoryNames() override;
+    virtual GDALColorTable *GetColorTable() override;
 };
 
-
 /************************************************************************/
 /*                           NWT_GRCRasterBand()                        */
 /************************************************************************/
 
 NWT_GRCRasterBand::NWT_GRCRasterBand( NWT_GRCDataset * poDSIn, int nBandIn )
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     NWT_GRCDataset *poGDS = reinterpret_cast<NWT_GRCDataset *>( poDS );
 
     if( poGDS->pGrd->nBitsPerPixel == 8 )
@@ -117,12 +117,9 @@ NWT_GRCRasterBand::NWT_GRCRasterBand( NWT_GRCDataset * poDSIn, int nBandIn )
     // load the color table and might as well to the ClassNames
     poGDS->poColorTable = new GDALColorTable();
 
-    GDALColorEntry oEntry;
+    GDALColorEntry oEntry = { 255, 255, 255, 255 };
     // null value = 0 is transparent
-    oEntry.c1 = 255;
-    oEntry.c2 = 255;
-    oEntry.c3 = 255;
-    oEntry.c4 = 255;                // alpha 255 = transparent
+    // alpha 255 = transparent
 
     poGDS->poColorTable->SetColorEntry( 0, &oEntry );
 
@@ -173,7 +170,6 @@ NWT_GRCRasterBand::NWT_GRCRasterBand( NWT_GRCDataset * poDSIn, int nBandIn )
         }
         if( i >= static_cast<int>( poGDS->pGrd->stClassDict->nNumClassifiedItems ) )
             poGDS->papszCategories = CSLAddString( poGDS->papszCategories, "" );
-
     }
 }
 
@@ -246,10 +242,14 @@ CPLErr NWT_GRCRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* ==================================================================== */
 /************************************************************************/
 NWT_GRCDataset::NWT_GRCDataset() :
-    fp(NULL), pGrd(NULL), papszCategories(NULL), pszProjection(NULL),
+    fp(NULL),
+    pGrd(NULL),
+    papszCategories(NULL),
+    pszProjection(NULL),
     poColorTable(NULL)
-{ }
-
+{
+    memset(abyHeader, 0, sizeof(abyHeader) );
+}
 
 /************************************************************************/
 /*                            ~NWT_GRCDataset()                         */
@@ -300,7 +300,7 @@ const char *NWT_GRCDataset::GetProjectionRef()
             poSpatialRef->Release();
         }
     }
-    return ( (const char *) pszProjection );
+    return (const char *) pszProjection;
 }
 
 /************************************************************************/
@@ -392,10 +392,9 @@ GDALDataset *NWT_GRCDataset::Open( GDALOpenInfo * poOpenInfo )
                                  poOpenInfo->pszFilename,
                                  poOpenInfo->GetSiblingFiles() );
 
-    return (poDS);
+    return poDS;
 }
 
-
 /************************************************************************/
 /*                          GDALRegister_GRC()                          */
 /************************************************************************/
diff --git a/frmts/northwood/grddataset.cpp b/frmts/northwood/grddataset.cpp
index 832770c..6bcd00a 100644
--- a/frmts/northwood/grddataset.cpp
+++ b/frmts/northwood/grddataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: grddataset.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  GRD Reader
  * Purpose:  GDAL driver for Northwood Grid Format
@@ -28,6 +27,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include <string>
+#include <cstring>
+#include <cstdio>
+#include <climits>
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 #include "northwood.h"
@@ -38,6 +41,25 @@
 #include "../../ogr/ogrsf_frmts/mitab/mitab.h"
 #endif
 
+CPL_CVSID("$Id: grddataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
+
+#define NODATA -1.e37f
+#define SCALE16BIT 65534.0
+#define SCALE32BIT 4294967294.0
+
+void replaceExt(std::string& s, const std::string& newExt);
+/************************************************************************/
+/* Replace the extension on a filepath with an alternative extension    */
+/************************************************************************/
+void replaceExt(std::string& s, const std::string& newExt) {
+
+    std::string::size_type i = s.rfind('.', s.length());
+
+    if (i != std::string::npos) {
+        s.replace(i + 1, newExt.length(), newExt);
+    }
+}
+
 /************************************************************************/
 /* ==================================================================== */
 /*                      NWT_GRDDataset                                  */
@@ -45,25 +67,37 @@
 /************************************************************************/
 class NWT_GRDRasterBand;
 
-class NWT_GRDDataset:public GDALPamDataset
-{
-  friend class NWT_GRDRasterBand;
+class NWT_GRDDataset: public GDALPamDataset {
+    friend class NWT_GRDRasterBand;
 
     VSILFILE *fp;
     GByte abyHeader[1024];
     NWT_GRID *pGrd;
     NWT_RGB ColorMap[4096];
-    char *pszProjection;
+    bool bUpdateHeader;
+    CPLString m_osProjection;
+
+    // Update the header data with latest changes
+    int UpdateHeader();
+    int WriteTab();
 
-  public:
+public:
     NWT_GRDDataset();
     ~NWT_GRDDataset();
 
-    static GDALDataset *Open( GDALOpenInfo * );
-    static int Identify( GDALOpenInfo * );
-
-    CPLErr GetGeoTransform( double *padfTransform );
-    const char *GetProjectionRef();
+    static GDALDataset *Open(GDALOpenInfo *);
+    static int Identify(GDALOpenInfo *);
+    static GDALDataset *Create(const char * pszFilename, int nXSize, int nYSize,
+            int nBands, GDALDataType eType, char ** papszParmList);
+    static GDALDataset *CreateCopy(const char * pszFilename,
+            GDALDataset * poSrcDS, int bStrict, char **papszOptions,
+            GDALProgressFunc pfnProgress, void * pProgressData);
+
+    CPLErr GetGeoTransform(double *padfTransform) override;
+    CPLErr SetGeoTransform(double *padfTransform) override;
+    void FlushCache() override;
+    const char *GetProjectionRef() override;
+    CPLErr SetProjection(const char *pszProjection) override;
 };
 
 /************************************************************************/
@@ -72,47 +106,56 @@ class NWT_GRDDataset:public GDALPamDataset
 /* ==================================================================== */
 /************************************************************************/
 
-class NWT_GRDRasterBand:public GDALPamRasterBand
-{
-  friend class NWT_GRDDataset;
+class NWT_GRDRasterBand: public GDALPamRasterBand {
+    friend class NWT_GRDDataset;
 
     int bHaveOffsetScale;
     double dfOffset;
     double dfScale;
+    double dfNoData;
 
-  public:
+public:
 
-    NWT_GRDRasterBand( NWT_GRDDataset *, int );
+    NWT_GRDRasterBand(NWT_GRDDataset *, int, int);
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual double GetNoDataValue( int *pbSuccess );
+    virtual CPLErr IReadBlock(int, int, void *) override;
+    virtual CPLErr IWriteBlock(int, int, void *) override;
+    virtual double GetNoDataValue(int *pbSuccess) override;
+    virtual CPLErr SetNoDataValue(double dfNoData) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
-
 /************************************************************************/
 /*                           NWT_GRDRasterBand()                        */
 /************************************************************************/
-NWT_GRDRasterBand::NWT_GRDRasterBand( NWT_GRDDataset * poDSIn, int nBandIn )
+NWT_GRDRasterBand::NWT_GRDRasterBand( NWT_GRDDataset * poDSIn, int nBandIn,
+                                      int nBands ) :
+    bHaveOffsetScale(FALSE),
+    dfOffset(0.0),
+    dfScale(1.0),
+    dfNoData(0.0)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-
-    if( nBand == 4 )
-    {
+    poDS = poDSIn;
+    nBand = nBandIn;
+
+    /*
+    * If nBand = 4 we have opened in read mode and have created the 3 'virtual' RGB bands.
+    * so the 4th band is the actual data
+    * Otherwise, if we have opened in update mode, there is only 1 band, which is the actual data
+    */
+    if (nBand == 4 || nBands == 1) {
         bHaveOffsetScale = TRUE;
         dfOffset = poDSIn->pGrd->fZMin;
 
-        if( poDSIn->pGrd->cFormat == 0x01 )
-        {
+        if (poDSIn->pGrd->cFormat == 0x00) {
             eDataType = GDT_Float32;
-            dfScale =( poDSIn->pGrd->fZMax - poDSIn->pGrd->fZMin ) / 4294967294.0;
-        }
-        else
-        {
+            dfScale = (poDSIn->pGrd->fZMax - poDSIn->pGrd->fZMin)
+                    / (double) SCALE16BIT;
+        } else {
             eDataType = GDT_Float32;
-            dfScale =( poDSIn->pGrd->fZMax - poDSIn->pGrd->fZMin ) / 65534.0;
+            dfScale = (poDSIn->pGrd->fZMax - poDSIn->pGrd->fZMin)
+                    / (double) SCALE32BIT;
         }
     }
     else
@@ -126,126 +169,208 @@ NWT_GRDRasterBand::NWT_GRDRasterBand( NWT_GRDDataset * poDSIn, int nBandIn )
     nBlockYSize = 1;
 }
 
-double NWT_GRDRasterBand::GetNoDataValue( int *pbSuccess )
-{
-    if (nBand == 4)
-    {
-        if( pbSuccess != NULL )
+double NWT_GRDRasterBand::GetNoDataValue(int *pbSuccess) {
+    NWT_GRDDataset *poGDS = reinterpret_cast<NWT_GRDDataset *>(poDS);
+    double dRetval;
+    if ((nBand == 4) || (poGDS->nBands == 1)) {
+        if (pbSuccess != NULL)
             *pbSuccess = TRUE;
+        if (dfNoData != 0.0) {
+            dRetval = dfNoData;
+        } else {
+            dRetval = (double) NODATA;
+        }
 
-        return -1.e37f;
+        return dRetval;
     }
 
-    if( pbSuccess != NULL )
+    if (pbSuccess != NULL)
         *pbSuccess = FALSE;
 
     return 0;
 }
 
-GDALColorInterp NWT_GRDRasterBand::GetColorInterpretation()
-{
+CPLErr NWT_GRDRasterBand::SetNoDataValue(double dfNoDataIn) {
+    // This is essentially a 'virtual' no data value.
+    // Once set, when writing an value == dfNoData will
+    // be converted to the no data value (0) on disk.
+    // If opened again; the no data value will always be the
+    // default (-1.e37f)
+    dfNoData = dfNoDataIn;
+    return CE_None;
+}
+
+GDALColorInterp NWT_GRDRasterBand::GetColorInterpretation() {
+    NWT_GRDDataset *poGDS = reinterpret_cast<NWT_GRDDataset *>(poDS);
     //return GCI_RGB;
-    if( nBand == 4 )
-        return GCI_Undefined;
-    else if( nBand == 1 )
+    if ((nBand == 4) || (poGDS->nBands == 1))
+        return GCI_GrayIndex;
+    else if (nBand == 1)
         return GCI_RedBand;
-    else if( nBand == 2 )
+    else if (nBand == 2)
         return GCI_GreenBand;
-    else if( nBand == 3 )
+    else if (nBand == 3)
         return GCI_BlueBand;
 
     return GCI_Undefined;
 }
 
 /************************************************************************/
+/*                             IWriteBlock()                            */
+/************************************************************************/
+CPLErr NWT_GRDRasterBand::IWriteBlock(CPL_UNUSED int nBlockXOff, int nBlockYOff,
+        void * pImage) {
+
+    // Each block is an entire row of the dataset, so the x offset should always be 0
+    CPLAssert(nBlockXOff == 0);
+    NWT_GRDDataset *poGDS = reinterpret_cast<NWT_GRDDataset *>(poDS);
+
+    // Ensure the blocksize is not beyond the system limits and
+    // initialise the size of the record
+    if (nBlockXSize > INT_MAX / 2) {
+        return CE_Failure;
+    }
+    const int nRecordSize = nBlockXSize * 2;
+
+    // Seek to the write position in the GRD file
+    VSIFSeekL(poGDS->fp,
+            1024 + nRecordSize * static_cast<vsi_l_offset>(nBlockYOff),
+            SEEK_SET);
+
+    // Cast pImage to float
+    float *pfImage = reinterpret_cast<float *>(pImage);
+
+    // Initialise output array
+    GByte *pabyRecord = reinterpret_cast<GByte *>(VSI_MALLOC_VERBOSE(
+                    nRecordSize));
+    if (pabyRecord == NULL)
+    return CE_Failure;
+
+    // We only ever write to band 4; RGB bands are basically 'virtual'
+    // (i.e. the RGB colour is computed from the raw data).
+    // For all intents and purposes, there is essentially 1 band on disk.
+    float fValue;// A single pixel value
+    unsigned short nWrite;// The stretched value to be written
+    if (nBand == 1) {
+        for (int i = 0; i < nBlockXSize; i++) {
+            fValue = pfImage[i];
+
+            // We allow data to be interpreted by a user-defined null value
+            // (a 'virtual' value, since it is always 0 on disk) or
+            // if not defined we default to the GRD standard of -1E37.
+            // We allow a little bit of flexibility in that if it is below -1E37
+            // it is in all probability still intended as a null value.
+            if ((fValue == dfNoData) || (fValue <= (double)NODATA)) {
+                nWrite = (unsigned short) 0;
+            }
+            else {
+                if (fValue < poGDS->pGrd->fZMin) {
+                    poGDS->pGrd->fZMin = fValue;
+                }
+                else if (fValue > poGDS->pGrd->fZMax) {
+                    poGDS->pGrd->fZMax = fValue;
+                }
+                // Data on disk is stretched within the unsigned short range so
+                // we must convert (the inverse of what is done in IReadBlock),
+                // based on the Z value range
+                nWrite = (unsigned short) (((fValue - dfOffset) / dfScale) + 1);
+            }
+            // Copy the result to the byte array (2 bytes per value)
+            memcpy(reinterpret_cast<void *>(pabyRecord + 2 * i),
+                    reinterpret_cast<void *>(&nWrite), 2);
+        }
+
+        // Write the buffer to disk
+        if (VSIFWriteL(pabyRecord, 1, nRecordSize, poGDS->fp)
+                != (size_t) (nRecordSize)) {
+            CPLError(CE_Failure, CPLE_FileIO,
+                    "Failed to write scanline %d to file.\n", nBlockYOff);
+            CPLFree(pabyRecord);
+            return CE_Failure;
+        }
+    } else {
+        CPLError(CE_Failure, CPLE_IllegalArg, "Writing to band %d is not valid",
+                nBand);
+        CPLFree(pabyRecord);
+        return CE_Failure;
+    }
+    CPLFree(pabyRecord);
+    return CE_None;
+}
+
+/************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
-CPLErr NWT_GRDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
-                                      int nBlockYOff,
-                                      void *pImage )
-{
-    NWT_GRDDataset *poGDS = reinterpret_cast<NWT_GRDDataset *>( poDS );
-    if( nBlockXSize > INT_MAX / 2 )
+CPLErr NWT_GRDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff, int nBlockYOff,
+        void *pImage) {
+    NWT_GRDDataset *poGDS = reinterpret_cast<NWT_GRDDataset *>(poDS);
+    if (nBlockXSize > INT_MAX / 2)
         return CE_Failure;
     const int nRecordSize = nBlockXSize * 2;
     unsigned short raw1;
 
-    VSIFSeekL( poGDS->fp,
-               1024 + nRecordSize
-               * static_cast<vsi_l_offset>( nBlockYOff ),
-               SEEK_SET );
+    // Seek to the data position
+    VSIFSeekL(poGDS->fp,
+            1024 + nRecordSize * static_cast<vsi_l_offset>(nBlockYOff),
+            SEEK_SET);
 
-    GByte *pabyRecord = reinterpret_cast<GByte *>( VSI_MALLOC_VERBOSE( nRecordSize ) );
-	if( pabyRecord == NULL )
-		return CE_Failure;
-    if( (int)VSIFReadL( pabyRecord, 1, nRecordSize, poGDS->fp ) != nRecordSize )
-    {
-        CPLFree( pabyRecord );
+    GByte *pabyRecord = reinterpret_cast<GByte *>(VSI_MALLOC_VERBOSE(
+                    nRecordSize));
+    if (pabyRecord == NULL)
+    return CE_Failure;
+
+    // Read the data
+    if ((int) VSIFReadL(pabyRecord, 1, nRecordSize, poGDS->fp) != nRecordSize) {
+        CPLFree(pabyRecord);
         return CE_Failure;
     }
 
-    if( nBand == 4 )                //Z values
+    if ((nBand == 4) || (poGDS->nBands == 1))            //Z values
     {
-        for( int i = 0; i < nBlockXSize; i++ )
-        {
-            memcpy( reinterpret_cast<void *>( &raw1 ),
-                    reinterpret_cast<void *>(pabyRecord + 2 * i), 2 );
+        int bSuccess;
+        double dNoData = GetNoDataValue(&bSuccess);
+        for (int i = 0; i < nBlockXSize; i++) {
+            memcpy(reinterpret_cast<void *>(&raw1),
+                    reinterpret_cast<void *>(pabyRecord + 2 * i), 2);
             CPL_LSBPTR16(&raw1);
-            if( raw1 == 0 )
-            {
-              reinterpret_cast<float *>( pImage )[i] = -1.e37f;    // null value
-            }
-            else
-            {
-                reinterpret_cast<float *>( pImage )[i]
-                  = static_cast<float>( dfOffset + ((raw1 - 1) * dfScale) );
+            if (raw1 == 0) {
+                reinterpret_cast<float *>(pImage)[i] = (float) dNoData; // null value
+            } else {
+                reinterpret_cast<float *>(pImage)[i] =
+                static_cast<float>(dfOffset + ((raw1 - 1) * dfScale));
             }
         }
-    }
-    else if( nBand == 1 )            // red values
+    } else if (nBand == 1)            // red values
     {
-        for( int i = 0; i < nBlockXSize; i++ )
-        {
-            memcpy( reinterpret_cast<void *>( &raw1 ),
-                    reinterpret_cast<void *>(pabyRecord + 2 * i),
-                    2 );
+        for (int i = 0; i < nBlockXSize; i++) {
+            memcpy(reinterpret_cast<void *>(&raw1),
+                    reinterpret_cast<void *>(pabyRecord + 2 * i), 2);
             CPL_LSBPTR16(&raw1);
-            reinterpret_cast<char *>( pImage )[i]
-                = poGDS->ColorMap[raw1 / 16].r;
+            reinterpret_cast<char *>(pImage)[i] = poGDS->ColorMap[raw1 / 16].r;
         }
-    }
-    else if( nBand == 2 )            // green
+    } else if (nBand == 2)            // green
     {
-        for( int i = 0; i < nBlockXSize; i++ )
-        {
-            memcpy( reinterpret_cast<void *> ( &raw1 ),
-                    reinterpret_cast<void *> ( pabyRecord + 2 * i ),
-                    2 );
+        for (int i = 0; i < nBlockXSize; i++) {
+            memcpy(reinterpret_cast<void *>(&raw1),
+                    reinterpret_cast<void *>(pabyRecord + 2 * i), 2);
             CPL_LSBPTR16(&raw1);
-            reinterpret_cast<char *>( pImage )[i] = poGDS->ColorMap[raw1 / 16].g;
+            reinterpret_cast<char *>(pImage)[i] = poGDS->ColorMap[raw1 / 16].g;
         }
-    }
-    else if( nBand == 3 )            // blue
+    } else if (nBand == 3)            // blue
     {
-        for( int i = 0; i < nBlockXSize; i++ )
-        {
-            memcpy( reinterpret_cast<void *>( &raw1 ),
-                    reinterpret_cast<void *>( pabyRecord + 2 * i ),
-                    2 );
+        for (int i = 0; i < nBlockXSize; i++) {
+            memcpy(reinterpret_cast<void *>(&raw1),
+                    reinterpret_cast<void *>(pabyRecord + 2 * i), 2);
             CPL_LSBPTR16(&raw1);
-            reinterpret_cast<char *>( pImage )[i] = poGDS->ColorMap[raw1 / 16].b;
+            reinterpret_cast<char *>(pImage)[i] = poGDS->ColorMap[raw1 / 16].b;
         }
-    }
-    else
-    {
-        CPLError( CE_Failure, CPLE_IllegalArg,
-                  "No band number %d",
-                  nBand );
-        CPLFree( pabyRecord );
+    } else {
+        CPLError(CE_Failure, CPLE_IllegalArg, "No band number %d", nBand);
+        CPLFree(pabyRecord);
         return CE_Failure;
     }
 
-    CPLFree( pabyRecord );
+    CPLFree(pabyRecord);
 
     return CE_None;
 }
@@ -259,10 +384,10 @@ CPLErr NWT_GRDRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 NWT_GRDDataset::NWT_GRDDataset() :
     fp(NULL),
     pGrd(NULL),
-    pszProjection(NULL)
+    bUpdateHeader(false)
 {
     //poCT = NULL;
-    for( size_t i=0; i < CPL_ARRAYSIZE(ColorMap); ++i )
+    for( size_t i = 0; i < CPL_ARRAYSIZE(ColorMap); ++i )
     {
         ColorMap[i].r = 0;
         ColorMap[i].g = 0;
@@ -270,36 +395,44 @@ NWT_GRDDataset::NWT_GRDDataset() :
     }
 }
 
-
 /************************************************************************/
 /*                            ~NWT_GRDDataset()                         */
 /************************************************************************/
 
-NWT_GRDDataset::~NWT_GRDDataset()
-{
-    FlushCache();
+NWT_GRDDataset::~NWT_GRDDataset() {
+
+    // Make sure any changes to the header etc are written
+    // if we are in update mode.
+    if (eAccess == GA_Update) {
+        FlushCache();
+    }
     pGrd->fp = NULL;       // this prevents nwtCloseGrid from closing the fp
-    nwtCloseGrid( pGrd );
+    nwtCloseGrid(pGrd);
 
-    if( fp != NULL )
-        VSIFCloseL( fp );
+    if (fp != NULL)
+        VSIFCloseL(fp);
+}
 
-    if( pszProjection != NULL )
-    {
-        CPLFree( pszProjection );
+/************************************************************************/
+/*                            ~FlushCache()                             */
+/************************************************************************/
+void NWT_GRDDataset::FlushCache() {
+    // Ensure the header and TAB file are up to date
+    if (bUpdateHeader) {
+        UpdateHeader();
     }
-    /*if( poCT != NULL )
-        delete poCT;*/
+
+    // Call the parent method
+    GDALPamDataset::FlushCache();
 }
 
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr NWT_GRDDataset::GetGeoTransform( double *padfTransform )
-{
-    padfTransform[0] = pGrd->dfMinX - ( pGrd->dfStepSize * 0.5 );
-    padfTransform[3] = pGrd->dfMaxY + ( pGrd->dfStepSize * 0.5 );
+CPLErr NWT_GRDDataset::GetGeoTransform(double *padfTransform) {
+    padfTransform[0] = pGrd->dfMinX - (pGrd->dfStepSize * 0.5);
+    padfTransform[3] = pGrd->dfMaxY + (pGrd->dfStepSize * 0.5);
     padfTransform[1] = pGrd->dfStepSize;
     padfTransform[2] = 0.0;
 
@@ -310,41 +443,97 @@ CPLErr NWT_GRDDataset::GetGeoTransform( double *padfTransform )
 }
 
 /************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr NWT_GRDDataset::SetGeoTransform(double *padfTransform) {
+    if (padfTransform[2] != 0.0 || padfTransform[4] != 0.0) {
+
+        CPLError(CE_Failure, CPLE_NotSupported,
+                "GRD datasets do not support skew/rotation");
+        return CE_Failure;
+    }
+    pGrd->dfStepSize = padfTransform[1];
+
+    // GRD format sets the min/max coordinates to the centre of the
+    // cell; We must account for this when copying the GDAL geotransform
+    // which references the top left corner
+    pGrd->dfMinX = padfTransform[0] + (pGrd->dfStepSize * 0.5);
+    pGrd->dfMaxY = padfTransform[3] - (pGrd->dfStepSize * 0.5);
+
+    // Now set the miny and maxx
+    pGrd->dfMaxX = pGrd->dfMinX + (pGrd->dfStepSize * (nRasterXSize - 1));
+    pGrd->dfMinY = pGrd->dfMaxY - (pGrd->dfStepSize * (nRasterYSize - 1));
+    bUpdateHeader = true;
+
+    return CE_None;
+}
+
+/************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
+const char *NWT_GRDDataset::GetProjectionRef() {
 
-const char *NWT_GRDDataset::GetProjectionRef()
-{
-    if (pszProjection == NULL)
+    // First try getting it from the PAM dataset
+    const char *pszProjection = GDALPamDataset::GetProjectionRef();
+
+    // If that isn't possible, read it from the GRD file. This may be a less
+    //  complete projection string.
+    if( strlen(pszProjection) == 0 )
     {
-        OGRSpatialReference *poSpatialRef;
-        poSpatialRef = MITABCoordSys2SpatialRef( pGrd->cMICoordSys );
-        if (poSpatialRef)
+        OGRSpatialReference *poSpatialRef =
+            MITABCoordSys2SpatialRef( pGrd->cMICoordSys );
+        if( poSpatialRef )
         {
-            poSpatialRef->exportToWkt( &pszProjection );
+            char* pszProjectionTmp = NULL;
+            poSpatialRef->exportToWkt( &pszProjectionTmp );
             poSpatialRef->Release();
+            if( pszProjectionTmp )
+                m_osProjection = pszProjectionTmp;
+            CPLFree(pszProjectionTmp);
+            return m_osProjection;
         }
     }
-    return reinterpret_cast<const char *>( pszProjection );
+    return pszProjection;
+}
+
+/************************************************************************/
+/*                          SetProjectionRef()                          */
+/************************************************************************/
+
+CPLErr NWT_GRDDataset::SetProjection( const char *pszProjection ) {
+    OGRSpatialReference oSpatialRef;
+    char *pszTmp = const_cast<char*>(pszProjection);
+    oSpatialRef.importFromWkt( &pszTmp );
+    char *psTABProj = MITABSpatialRef2CoordSys( &oSpatialRef );
+    strncpy( pGrd->cMICoordSys, psTABProj, sizeof(pGrd->cMICoordSys) -1 );
+    pGrd->cMICoordSys[255] = '\0';
+
+    // Free temp projection.
+    CPLFree(psTABProj);
+    // Set projection in PAM dataset, so that
+    // GDAL can always retrieve the complete projection.
+    GDALPamDataset::SetProjection( pszProjection );
+    bUpdateHeader = true;
+
+    return CE_None;
 }
 
 /************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
 
-int NWT_GRDDataset::Identify( GDALOpenInfo * poOpenInfo )
-{
-/* -------------------------------------------------------------------- */
-/*  Look for the header                                                 */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 1024 )
+int NWT_GRDDataset::Identify(GDALOpenInfo * poOpenInfo) {
+    /* -------------------------------------------------------------------- */
+    /*  Look for the header                                                 */
+    /* -------------------------------------------------------------------- */
+    if (poOpenInfo->nHeaderBytes < 1024)
         return FALSE;
 
-    if( poOpenInfo->pabyHeader[0] != 'H' ||
-        poOpenInfo->pabyHeader[1] != 'G' ||
-        poOpenInfo->pabyHeader[2] != 'P' ||
-        poOpenInfo->pabyHeader[3] != 'C' ||
-        poOpenInfo->pabyHeader[4] != '1' )
+    if (poOpenInfo->pabyHeader[0] != 'H' || poOpenInfo->pabyHeader[1] != 'G'
+            || poOpenInfo->pabyHeader[2] != 'P'
+            || poOpenInfo->pabyHeader[3] != 'C'
+            || poOpenInfo->pabyHeader[4] != '1')
         return FALSE;
 
     return TRUE;
@@ -353,37 +542,49 @@ int NWT_GRDDataset::Identify( GDALOpenInfo * poOpenInfo )
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
-GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
-{
-    if( !Identify(poOpenInfo) )
+GDALDataset *NWT_GRDDataset::Open(GDALOpenInfo * poOpenInfo) {
+    if (!Identify(poOpenInfo))
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
-    NWT_GRDDataset *poDS;
+    /* -------------------------------------------------------------------- */
+    /*      Create a corresponding GDALDataset.                             */
+    /* -------------------------------------------------------------------- */
+    int nBandsToCreate = 0;
 
-    poDS = new NWT_GRDDataset();
+    NWT_GRDDataset *poDS = new NWT_GRDDataset();
 
-    poDS->fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
-    if (poDS->fp == NULL)
-    {
+    if (poOpenInfo->eAccess == GA_Update) {
+        poDS->fp = VSIFOpenL(poOpenInfo->pszFilename, "rb+");
+        nBandsToCreate = 1;
+    } else {
+        poDS->fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
+        nBandsToCreate = atoi(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "BAND_COUNT", "4"));
+        if( nBandsToCreate != 1 && nBandsToCreate != 4 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Wrong value for BAND_COUNT");
+            delete poDS;
+            return NULL;
+        }
+    }
+    if (poDS->fp == NULL) {
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the header.                                                */
-/* -------------------------------------------------------------------- */
-    VSIFSeekL( poDS->fp, 0, SEEK_SET );
-    VSIFReadL( poDS->abyHeader, 1, 1024, poDS->fp );
-    poDS->pGrd = reinterpret_cast<NWT_GRID *>( malloc( sizeof( NWT_GRID ) ) );
+    poDS->eAccess = poOpenInfo->eAccess;
+
+    /* -------------------------------------------------------------------- */
+    /*      Read the header.                                                */
+    /* -------------------------------------------------------------------- */
+    VSIFSeekL(poDS->fp, 0, SEEK_SET);
+    VSIFReadL(poDS->abyHeader, 1, 1024, poDS->fp);
+    poDS->pGrd = reinterpret_cast<NWT_GRID *>(calloc(1, sizeof(NWT_GRID)));
 
     poDS->pGrd->fp = poDS->fp;
 
-    if (!nwt_ParseHeader( poDS->pGrd, reinterpret_cast<char *>( poDS->abyHeader ) ) ||
-        !GDALCheckDatasetDimensions(poDS->pGrd->nXSide, poDS->pGrd->nYSide) )
-    {
+    if (!nwt_ParseHeader(poDS->pGrd, reinterpret_cast<char *>(poDS->abyHeader))
+            || !GDALCheckDatasetDimensions(poDS->pGrd->nXSide,
+                    poDS->pGrd->nYSide)) {
         delete poDS;
         return NULL;
     }
@@ -394,51 +595,477 @@ GDALDataset *NWT_GRDDataset::Open( GDALOpenInfo * poOpenInfo )
     // create a colorTable
     // if( poDS->pGrd->iNumColorInflections > 0 )
     //   poDS->CreateColorTable();
-    nwt_LoadColors( poDS->ColorMap, 4096, poDS->pGrd );
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
-    poDS->SetBand( 1, new NWT_GRDRasterBand( poDS, 1 ) );    //r
-    poDS->SetBand( 2, new NWT_GRDRasterBand( poDS, 2 ) );    //g
-    poDS->SetBand( 3, new NWT_GRDRasterBand( poDS, 3 ) );    //b
-    poDS->SetBand( 4, new NWT_GRDRasterBand( poDS, 4 ) );    //z
-
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    nwt_LoadColors(poDS->ColorMap, 4096, poDS->pGrd);
+    /* -------------------------------------------------------------------- */
+    /*      Create band information objects.                                */
+    /* If opening in read-only mode, then we create 4 bands (RGBZ)          */
+    /* with data values being available in band 4. If opening in update mode*/
+    /* we create 1 band (the data values). This is because in reality, there*/
+    /* is only 1 band stored on disk. The RGB bands are 'virtual' - derived */
+    /* from the data values on the fly                                      */
+    /* -------------------------------------------------------------------- */
+    for (int i = 0; i < nBandsToCreate; ++i) {
+        poDS->SetBand(i + 1, new NWT_GRDRasterBand(poDS, i + 1, nBandsToCreate));
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Initialize any PAM information.                                 */
+    /* -------------------------------------------------------------------- */
+    poDS->SetDescription(poOpenInfo->pszFilename);
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Check for external overviews.                                   */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
-                                 poOpenInfo->GetSiblingFiles() );
+    /* -------------------------------------------------------------------- */
+    /*      Check for external overviews.                                   */
+    /* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename,
+            poOpenInfo->GetSiblingFiles());
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                                UpdateHeader()                        */
+/************************************************************************/
+int NWT_GRDDataset::UpdateHeader() {
+    int iStatus = 0;
+    TABRawBinBlock *poHeaderBlock = new TABRawBinBlock(TABReadWrite, TRUE);
+    poHeaderBlock->InitNewBlock(fp, 1024);
+
+    // Write the header string
+    poHeaderBlock->WriteBytes(5, (GByte *) "HGPC1\0");
+
+    // Version number
+    poHeaderBlock->WriteFloat(pGrd->fVersion);
+
+    // Dimensions
+    poHeaderBlock->WriteInt16(static_cast<GInt16>(pGrd->nXSide));
+    poHeaderBlock->WriteInt16(static_cast<GInt16>(pGrd->nYSide));
+
+    // Extents
+    poHeaderBlock->WriteDouble(pGrd->dfMinX);
+    poHeaderBlock->WriteDouble(pGrd->dfMaxX);
+    poHeaderBlock->WriteDouble(pGrd->dfMinY);
+    poHeaderBlock->WriteDouble(pGrd->dfMaxY);
+
+    // Z value range
+    poHeaderBlock->WriteFloat(pGrd->fZMin);
+    poHeaderBlock->WriteFloat(pGrd->fZMax);
+    poHeaderBlock->WriteFloat(pGrd->fZMinScale);
+    poHeaderBlock->WriteFloat(pGrd->fZMaxScale);
+
+    // Description String
+    int nChar = static_cast<int>(strlen(pGrd->cDescription));
+    poHeaderBlock->WriteBytes(nChar, (GByte*) pGrd->cDescription);
+    poHeaderBlock->WriteZeros(32 - nChar);
+
+    // Unit Name String
+    nChar = static_cast<int>(strlen(pGrd->cZUnits));
+    poHeaderBlock->WriteBytes(nChar, (GByte *) pGrd->cZUnits);
+    poHeaderBlock->WriteZeros(32 - nChar);
+
+    //Ignore 126 - 141 as unknown usage
+    poHeaderBlock->WriteZeros(15);
+
+    // Hill shading
+    poHeaderBlock->WriteInt16(pGrd->bHillShadeExists ? 1 : 0);
+    poHeaderBlock->WriteInt16((short) 0);
+
+    poHeaderBlock->WriteByte(pGrd->cHillShadeBrightness);
+    poHeaderBlock->WriteByte(pGrd->cHillShadeContrast);
+
+    //Ignore 147 - 257 as unknown usage
+    poHeaderBlock->WriteZeros(110);
+
+    // Write spatial reference
+    poHeaderBlock->WriteBytes((int) strlen(pGrd->cMICoordSys),
+            (GByte*) pGrd->cMICoordSys);
+    poHeaderBlock->WriteZeros(256 - (int) strlen(pGrd->cMICoordSys));
+
+    // Unit code
+    poHeaderBlock->WriteByte(static_cast<GByte>(pGrd->iZUnits));
+
+    // Info on shading
+    GByte byDisplayStatus = 0;
+    if (pGrd->bShowHillShade) {
+        byDisplayStatus |= 1 << 6;
+    }
+    if (pGrd->bShowGradient) {
+        byDisplayStatus |= 1 << 7;
+    }
+
+    poHeaderBlock->WriteByte(byDisplayStatus);
+    poHeaderBlock->WriteInt16((short) 0); //Data Type?
+
+    // Colour inflections
+    poHeaderBlock->WriteInt16(pGrd->iNumColorInflections);
+    for (int i = 0; i < pGrd->iNumColorInflections; i++) {
+        poHeaderBlock->WriteFloat(pGrd->stInflection[i].zVal);
+        poHeaderBlock->WriteByte(pGrd->stInflection[i].r);
+        poHeaderBlock->WriteByte(pGrd->stInflection[i].g);
+        poHeaderBlock->WriteByte(pGrd->stInflection[i].b);
+    }
+
+    // Fill in unused blanks
+    poHeaderBlock->WriteZeros((966 - poHeaderBlock->GetCurAddress()));
+
+    // Azimuth and Inclination
+    poHeaderBlock->WriteFloat(pGrd->fHillShadeAzimuth);
+    poHeaderBlock->WriteFloat(pGrd->fHillShadeAngle);
+
+    // Write to disk
+    iStatus = poHeaderBlock->CommitToFile();
 
-    return (poDS);
+    delete poHeaderBlock;
+
+    // Update the TAB file to catch any changes
+    if( WriteTab() != 0 )
+        iStatus = -1;
+
+    return iStatus;
 }
 
+int NWT_GRDDataset::WriteTab() {
+    // Create the filename for the .tab file.
+    const std::string sTabFile(CPLResetExtension(pGrd->szFileName, "tab"));
+
+    VSILFILE *tabfp = VSIFOpenL(sTabFile.c_str(), "wt");
+    if( tabfp == NULL)
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Failed to create file `%s'", sTabFile.c_str());
+        return -1;
+    }
+
+    bool bOK = true;
+    bOK &= VSIFPrintfL(tabfp, "!table\n") > 0;
+    bOK &= VSIFPrintfL(tabfp, "!version 500\n") > 0;
+    bOK &= VSIFPrintfL(tabfp, "!charset %s\n", "Neutral") > 0;
+    bOK &= VSIFPrintfL(tabfp, "\n") > 0;
+
+    bOK &= VSIFPrintfL(tabfp, "Definition Table\n") > 0;
+    const std::string path(pGrd->szFileName);
+    const std::string basename = path.substr(path.find_last_of("/\\") + 1);
+    bOK &= VSIFPrintfL(tabfp, "  File \"%s\"\n", basename.c_str()) > 0;
+    bOK &= VSIFPrintfL(tabfp, "  Type \"RASTER\"\n") > 0;
+
+    double dMapUnitsPerPixel =
+        (pGrd->dfMaxX - pGrd->dfMinX) /
+        (static_cast<double>(pGrd->nXSide) - 1);
+    double dShift = dMapUnitsPerPixel / 2.0;
+
+    bOK &= VSIFPrintfL(tabfp, "  (%f,%f) (%d,%d) Label \"Pt 1\",\n",
+                pGrd->dfMinX - dShift, pGrd->dfMaxY + dShift, 0, 0) > 0;
+    bOK &= VSIFPrintfL(tabfp, "  (%f,%f) (%d,%d) Label \"Pt 2\",\n",
+                pGrd->dfMaxX - dShift, pGrd->dfMinY + dShift, pGrd->nXSide - 1,
+                pGrd->nYSide - 1) > 0;
+    bOK &= VSIFPrintfL(tabfp, "  (%f,%f) (%d,%d) Label \"Pt 3\"\n",
+                pGrd->dfMinX - dShift, pGrd->dfMinY + dShift, 0,
+                pGrd->nYSide - 1) > 0;
+
+    bOK &= VSIFPrintfL(tabfp, "  CoordSys %s\n",pGrd->cMICoordSys) > 0;
+    bOK &= VSIFPrintfL(tabfp, "  Units \"m\"\n") > 0;
+
+    // Raster Styles.
+
+    // Raster is a grid, which is style 6.
+    bOK &= VSIFPrintfL(tabfp, "  RasterStyle 6 1\n") > 0;
+
+    // Brightness - style 1
+    if( pGrd->style.iBrightness > 0 )
+    {
+        bOK &= VSIFPrintfL(tabfp, "  RasterStyle 1 %d\n",pGrd->style.iBrightness) > 0;
+    }
+
+    // Contrast - style 2
+    if( pGrd->style.iContrast > 0 )
+    {
+        bOK &= VSIFPrintfL(tabfp, "  RasterStyle 2 %d\n",pGrd->style.iContrast) > 0;
+    }
+
+    // Greyscale - style 3; only need to write if TRUE
+    if( pGrd->style.bGreyscale == TRUE )
+    {
+        bOK &= VSIFPrintfL(tabfp, "  RasterStyle 3 1\n") > 0;
+    }
+
+    // Flag to render one colour transparent - style 4
+    if( pGrd->style.bTransparent == TRUE )
+    {
+        bOK &= VSIFPrintfL(tabfp, "  RasterStyle 4 1\n") > 0;
+        if( pGrd->style.iTransColour > 0 )
+        {
+            bOK &= VSIFPrintfL(tabfp, "  RasterStyle 7 %d\n",pGrd->style.iTransColour) > 0;
+        }
+    }
+
+    // Transparency of immage
+    if( pGrd->style.iTranslucency > 0 )
+    {
+        bOK &= VSIFPrintfL(tabfp, "  RasterStyle 8 %d\n",pGrd->style.iTranslucency) > 0;
+    }
+
+    bOK &= VSIFPrintfL(tabfp, "begin_metadata\n") > 0;
+    bOK &= VSIFPrintfL(tabfp, "\"\\MapInfo\" = \"\"\n") > 0;
+    bOK &= VSIFPrintfL(tabfp, "\"\\Vm\" = \"\"\n") > 0;
+    bOK &= VSIFPrintfL(tabfp, "\"\\Vm\\Grid\" = \"Numeric\"\n") > 0;
+    bOK &= VSIFPrintfL(tabfp, "\"\\Vm\\GridName\" = \"%s\"\n", basename.c_str()) > 0;
+    bOK &= VSIFPrintfL(tabfp, "\"\\IsReadOnly\" = \"FALSE\"\n") > 0;
+    bOK &= VSIFPrintfL(tabfp, "end_metadata\n") > 0;
+
+    if( VSIFCloseL(tabfp) != 0 )
+        bOK = false;
+
+    return (bOK) ? 0 : -1;
+}
+
+/************************************************************************/
+/*                                Create()                              */
+/************************************************************************/
+GDALDataset *NWT_GRDDataset::Create(const char * pszFilename, int nXSize,
+        int nYSize, int nBands, GDALDataType eType, char ** papszParmList) {
+    if (nBands != 1) {
+        CPLError(CE_Failure, CPLE_FileIO,
+                "Only single band datasets are supported for writing");
+        return NULL;
+    }
+    if (eType != GDT_Float32) {
+        CPLError(CE_Failure, CPLE_FileIO,
+                "Float32 is the only supported data type");
+        return NULL;
+    }
+    NWT_GRDDataset *poDS = new NWT_GRDDataset();
+    poDS->eAccess = GA_Update;
+    poDS->pGrd = reinterpret_cast<NWT_GRID *>(calloc(1, sizeof(NWT_GRID)));
+
+    // We currently only support GRD grid types (could potentially support GRC in the papszParmList).
+    // Also only support GDT_Float32 as the data type. GRD format allows for data to be stretched to
+    // 32bit or 16bit integers on disk, so it would be feasible to support other data types
+    poDS->pGrd->cFormat = 0x00;
+
+    // File version
+    poDS->pGrd->fVersion = 2.0;
+
+    // Dimensions
+    poDS->pGrd->nXSide = nXSize;
+    poDS->pGrd->nYSide = nYSize;
+    poDS->nRasterXSize = nXSize;
+    poDS->nRasterYSize = nYSize;
+
+    // Some default values to get started with. These will
+    // be altered when SetGeoTransform is called.
+    poDS->pGrd->dfMinX = -2E+307;
+    poDS->pGrd->dfMinY = -2E+307;
+    poDS->pGrd->dfMaxX = 2E+307;
+    poDS->pGrd->dfMaxY = 2E+307;
+
+    float fZMin, fZMax;
+    // See if the user passed the min/max values
+    if (CSLFetchNameValue(papszParmList, "ZMIN") == NULL) {
+        fZMin = (float) -2E+37;
+    } else {
+        fZMin = static_cast<float>(CPLAtof(CSLFetchNameValue(papszParmList, "ZMIN")));
+    }
+
+    if (CSLFetchNameValue(papszParmList, "ZMAX") == NULL) {
+        fZMax = (float) 2E+38;
+    } else {
+        fZMax = static_cast<float>(CPLAtof(CSLFetchNameValue(papszParmList, "ZMAX")));
+    }
+
+    poDS->pGrd->fZMin = fZMin;
+    poDS->pGrd->fZMax = fZMax;
+    //pGrd->dfStepSize = (pGrd->dfMaxX - pGrd->dfMinX) / (pGrd->nXSide - 1);
+    poDS->pGrd->fZMinScale = fZMin;
+    poDS->pGrd->fZMaxScale = fZMax;
+    //poDS->pGrd->iZUnits
+    memset(poDS->pGrd->cZUnits, 0, 32);
+    memset(poDS->pGrd->cMICoordSys, 0, 256);
+
+    // Some default colour inflections; Basic scale from blue to red
+    poDS->pGrd->iNumColorInflections = 3;
+
+    // Lowest inflection
+    poDS->pGrd->stInflection[0].zVal = poDS->pGrd->fZMin;
+    poDS->pGrd->stInflection[0].r = 0;
+    poDS->pGrd->stInflection[0].g = 0;
+    poDS->pGrd->stInflection[0].b = 255;
+
+    // Mean inflection
+    poDS->pGrd->stInflection[1].zVal = (poDS->pGrd->fZMax - poDS->pGrd->fZMin)
+            / 2;
+    poDS->pGrd->stInflection[1].r = 255;
+    poDS->pGrd->stInflection[1].g = 255;
+    poDS->pGrd->stInflection[1].b = 0;
+
+    // Highest inflection
+    poDS->pGrd->stInflection[2].zVal = poDS->pGrd->fZMax;
+    poDS->pGrd->stInflection[2].r = 255;
+    poDS->pGrd->stInflection[2].g = 0;
+    poDS->pGrd->stInflection[2].b = 0;
+
+    poDS->pGrd->bHillShadeExists = FALSE;
+    poDS->pGrd->bShowGradient = FALSE;
+    poDS->pGrd->bShowHillShade = FALSE;
+    poDS->pGrd->cHillShadeBrightness = 0;
+    poDS->pGrd->cHillShadeContrast = 0;
+    poDS->pGrd->fHillShadeAzimuth = 0;
+    poDS->pGrd->fHillShadeAngle = 0;
+
+    // Set the raster style settings. These aren't used anywhere other than to write the TAB file
+    if (CSLFetchNameValue(papszParmList, "BRIGHTNESS") == NULL) {
+        poDS->pGrd->style.iBrightness = 50;
+    } else {
+        poDS->pGrd->style.iBrightness = atoi(
+                CSLFetchNameValue(papszParmList, "BRIGHTNESS"));
+    }
+
+    if (CSLFetchNameValue(papszParmList, "CONTRAST") == NULL) {
+        poDS->pGrd->style.iContrast = 50;
+    } else {
+        poDS->pGrd->style.iContrast = atoi(
+                CSLFetchNameValue(papszParmList, "CONTRAST"));
+    }
+
+    if (CSLFetchNameValue(papszParmList, "TRANSCOLOR") == NULL) {
+        poDS->pGrd->style.iTransColour = 0;
+    } else {
+        poDS->pGrd->style.iTransColour = atoi(
+                CSLFetchNameValue(papszParmList, "TRANSCOLOR"));
+    }
+
+    if (CSLFetchNameValue(papszParmList, "TRANSLUCENCY") == NULL) {
+        poDS->pGrd->style.iTranslucency = 0;
+    } else {
+        poDS->pGrd->style.iTranslucency = atoi(
+                CSLFetchNameValue(papszParmList, "TRANSLUCENCY"));
+    }
+
+    poDS->pGrd->style.bGreyscale = FALSE;
+    poDS->pGrd->style.bGrey = FALSE;
+    poDS->pGrd->style.bColour = FALSE;
+    poDS->pGrd->style.bTransparent = FALSE;
+
+    // Open the grid file
+    poDS->fp = VSIFOpenL(pszFilename, "wb");
+    if (poDS->fp == NULL) {
+        CPLError(CE_Failure, CPLE_FileIO, "Failed to create GRD file");
+        delete poDS;
+        return NULL;
+    }
+
+    poDS->pGrd->fp = poDS->fp;
+    strncpy(poDS->pGrd->szFileName, pszFilename,
+            sizeof(poDS->pGrd->szFileName));
+    poDS->pGrd->szFileName[sizeof(poDS->pGrd->szFileName) - 1] = '\0';
+
+// Seek to the start of the file and enter the default header info
+    VSIFSeekL(poDS->fp, 0, SEEK_SET);
+    if (poDS->UpdateHeader() != 0) {
+        CPLError(CE_Failure, CPLE_FileIO, "Failed to create GRD file");
+        delete poDS;
+        return NULL;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create band information objects;                                */
+    /*      Only 1 band is allowed                                          */
+    /* -------------------------------------------------------------------- */
+    poDS->SetBand(1, new NWT_GRDRasterBand(poDS, 1, 1));    //z
+
+    poDS->oOvManager.Initialize(poDS, pszFilename);
+    poDS->FlushCache(); // Write the header to disk.
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                                CreateCopy()                          */
+/************************************************************************/
+GDALDataset * NWT_GRDDataset::CreateCopy(const char * pszFilename,
+        GDALDataset * poSrcDS, int bStrict, char **papszOptions,
+        GDALProgressFunc pfnProgress, void * pProgressData) {
+
+    if( poSrcDS->GetRasterCount() != 1 )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                "Only single band datasets are supported for writing");
+        return NULL;
+    }
+
+    char **tmpOptions = CSLDuplicate(papszOptions);
+
+    /*
+    * Compute the statistics if ZMAX and ZMIN are not provided
+    */
+    double dfMin = 0.0;
+    double dfMax = 0.0;
+    double dfMean = 0.0;
+    double dfStdDev = 0.0;
+    GDALRasterBand *pBand = poSrcDS->GetRasterBand(1);
+    char sMax[10] = {};
+    char sMin[10] = {};
+
+    if ((CSLFetchNameValue(papszOptions, "ZMAX") == NULL)
+            || (CSLFetchNameValue(papszOptions, "ZMIN") == NULL)) {
+        CPL_IGNORE_RET_VAL(pBand->GetStatistics(FALSE, TRUE, &dfMin, &dfMax, &dfMean,
+                &dfStdDev));
+    }
+
+    if (CSLFetchNameValue(papszOptions, "ZMAX") == NULL) {
+        CPLsnprintf(sMax, sizeof(sMax), "%f", dfMax);
+        tmpOptions = CSLSetNameValue(tmpOptions, "ZMAX", sMax);
+    }
+    if (CSLFetchNameValue(papszOptions, "ZMIN") == NULL) {
+        CPLsnprintf(sMin, sizeof(sMin), "%f", dfMin);
+        tmpOptions = CSLSetNameValue(tmpOptions, "ZMIN", sMin);
+    }
+
+    GDALDriver *poDriver = (GDALDriver *) GDALGetDriverByName("NWT_GRD");
+    GDALDataset *poDstDS = poDriver->DefaultCreateCopy(pszFilename, poSrcDS,
+            bStrict, tmpOptions, pfnProgress, pProgressData);
+
+    CSLDestroy(tmpOptions);
+
+    return poDstDS;
+}
 
 /************************************************************************/
 /*                          GDALRegister_GRD()                          */
 /************************************************************************/
-void GDALRegister_NWT_GRD()
-{
-    if( GDALGetDriverByName( "NWT_GRD" ) != NULL )
-      return;
+void GDALRegister_NWT_GRD() {
+    if (GDALGetDriverByName("NWT_GRD") != NULL)
+        return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "NWT_GRD" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                               "Northwood Numeric Grid Format .grd/.tab" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#grd");
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription("NWT_GRD");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
+            "Northwood Numeric Grid Format .grd/.tab");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_nwtgrd.html");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "grd");
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32");
+
+    poDriver->SetMetadataItem(GDAL_DMD_OPENOPTIONLIST,
+      "<OpenOptionList>"
+      "    <Option name='BAND_COUNT' type='int' description='1 (Z) or 4 (RGBZ). Only used in read-only mode' default='4'/>"
+      "</OpenOptionList>");
+
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
+      "<CreationOptionList>"
+      "    <Option name='ZMIN' type='float' description='Minimum cell value of raster for defining RGB scaling' default='-2E+37'/>"
+      "    <Option name='ZMAX' type='float' description='Maximum cell value of raster for defining RGB scaling' default='2E+38'/>"
+      "    <Option name='BRIGHTNESS' type='int' description='Brightness to be recorded in TAB file. Only affects reading with MapInfo' default='50'/>"
+      "    <Option name='CONTRAST' type='int' description='Contrast to be recorded in TAB file. Only affects reading with MapInfo' default='50'/>"
+      "    <Option name='TRANSCOLOR' type='int' description='Transparent color to be recorded in TAB file. Only affects reading with MapInfo' default='0'/>"
+      "    <Option name='TRANSLUCENCY' type='int' description='Level of translucency to be recorded in TAB file. Only affects reading with MapInfo' default='0'/>"
+      "</CreationOptionList>");
 
     poDriver->pfnOpen = NWT_GRDDataset::Open;
     poDriver->pfnIdentify = NWT_GRDDataset::Identify;
+    poDriver->pfnCreate = NWT_GRDDataset::Create;
+    poDriver->pfnCreateCopy = NWT_GRDDataset::CreateCopy;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/northwood/northwood.cpp b/frmts/northwood/northwood.cpp
index 798f88a..3f521d0 100644
--- a/frmts/northwood/northwood.cpp
+++ b/frmts/northwood/northwood.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: northwood.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GRC/GRD Reader
  * Purpose:  Northwood Format basic implementation
@@ -33,6 +32,9 @@
 #include "northwood.h"
 
 #include <algorithm>
+#include <string>
+
+CPL_CVSID("$Id: northwood.cpp 36776 2016-12-10 11:17:47Z rouault $");
 
 int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
 {
@@ -188,7 +190,6 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
 
     pGrd->cFormat += nwtHeader[1023];    // the msb for grd/grc was already set
 
-
     // there are more types than this - need to build other types for testing
     if( pGrd->cFormat & 0x80 )
     {
@@ -200,7 +201,6 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
     else
         pGrd->nBitsPerPixel = nwtHeader[1023] * 8;
 
-
     if( pGrd->cFormat & 0x80 )        // if is GRC load the Dictionary
     {
         VSIFSeekL( pGrd->fp,
@@ -272,7 +272,6 @@ int nwt_ParseHeader( NWT_GRID * pGrd, char *nwtHeader )
     return TRUE;
 }
 
-
 // Create a color gradient ranging from ZMin to Zmax using the color
 // inflections defined in grid
 int nwt_LoadColors( NWT_RGB * pMap, int mapSize, NWT_GRID * pGrd )
@@ -441,16 +440,14 @@ void nwt_HillShade( unsigned char *r, unsigned char *g, unsigned char *b,
     return;
 }
 
-
 NWT_GRID *nwtOpenGrid( char *filename )
 {
-    NWT_GRID *pGrd;
     char nwtHeader[1024];
-    VSILFILE *fp;
+    VSILFILE *fp = VSIFOpenL( filename, "rb" );
 
-    if( (fp = VSIFOpenL( filename, "rb" )) == NULL )
+    if( fp == NULL )
     {
-        fprintf( stderr, "\nCan't open %s\n", filename );
+        CPLError(CE_Failure, CPLE_OpenFailed, "Can't open %s", filename );
         return NULL;
     }
 
@@ -463,7 +460,7 @@ NWT_GRID *nwtOpenGrid( char *filename )
         nwtHeader[3] != 'C' )
           return NULL;
 
-    pGrd = reinterpret_cast<NWT_GRID *>(
+    NWT_GRID *pGrd = reinterpret_cast<NWT_GRID *>(
         calloc( sizeof(NWT_GRID), 1 ) );
 
     if( nwtHeader[4] == '1' )
@@ -472,7 +469,8 @@ NWT_GRID *nwtOpenGrid( char *filename )
         pGrd->cFormat = 0x80;        //  grc classified type
     else
     {
-        fprintf( stderr, "\nUnhandled Northwood format type = %0xd\n",
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Unhandled Northwood format type = %0xd",
                  nwtHeader[4] );
         if( pGrd )
             free( pGrd );
@@ -509,77 +507,77 @@ void nwtPrintGridHeader( NWT_GRID * pGrd )
 {
     if( pGrd->cFormat & 0x80 )
     {
-        printf( "\n%s\n\nGrid type is Classified ", pGrd->szFileName );
+        printf( "\n%s\n\nGrid type is Classified ", pGrd->szFileName );/*ok*/
         if( pGrd->cFormat == 0x81 )
-            printf( "4 bit (Less than 16 Classes)" );
+            printf( "4 bit (Less than 16 Classes)" );/*ok*/
         else if( pGrd->cFormat == 0x82 )
-            printf( "8 bit (Less than 256 Classes)" );
+            printf( "8 bit (Less than 256 Classes)" );/*ok*/
         else if( pGrd->cFormat == 0x84 )
-            printf( "16 bit (Less than 65536 Classes)" );
+            printf( "16 bit (Less than 65536 Classes)" );/*ok*/
         else
         {
-            printf( "GRC - Unhandled Format or Type %d", pGrd->cFormat );
+            printf( "GRC - Unhandled Format or Type %d", pGrd->cFormat );/*ok*/
             return;
         }
     }
     else
     {
-        printf( "\n%s\n\nGrid type is Numeric ", pGrd->szFileName );
+        printf( "\n%s\n\nGrid type is Numeric ", pGrd->szFileName );/*ok*/
         if( pGrd->cFormat == 0x00 )
-            printf( "16 bit (Standard Percision)" );
+            printf( "16 bit (Standard Precision)" );/*ok*/
         else if( pGrd->cFormat == 0x01 )
-            printf( "32 bit (High Percision)" );
+            printf( "32 bit (High Precision)" );/*ok*/
         else
         {
-            printf( "GRD - Unhandled Format or Type %d", pGrd->cFormat );
+            printf( "GRD - Unhandled Format or Type %d", pGrd->cFormat );/*ok*/
             return;
         }
     }
-    printf( "\nDim (x,y) = (%d,%d)", pGrd->nXSide, pGrd->nYSide );
-    printf( "\nStep Size = %f", pGrd->dfStepSize );
-    printf( "\nBounds = (%f,%f) (%f,%f)", pGrd->dfMinX, pGrd->dfMinY,
+    printf( "\nDim (x,y) = (%u,%u)", pGrd->nXSide, pGrd->nYSide );/*ok*/
+    printf( "\nStep Size = %f", pGrd->dfStepSize );/*ok*/
+    printf( "\nBounds = (%f,%f) (%f,%f)", pGrd->dfMinX, pGrd->dfMinY,/*ok*/
             pGrd->dfMaxX, pGrd->dfMaxY );
-    printf( "\nCoordinate System = %s", pGrd->cMICoordSys );
+    printf( "\nCoordinate System = %s", pGrd->cMICoordSys );/*ok*/
 
     if( !(pGrd->cFormat & 0x80) )    // print the numeric specific stuff
     {
-        printf( "\nMin Z = %f Max Z = %f Z Units = %d \"%s\"", pGrd->fZMin,
+        printf( "\nMin Z = %f Max Z = %f Z Units = %d \"%s\"", pGrd->fZMin,/*ok*/
                 pGrd->fZMax, pGrd->iZUnits, pGrd->cZUnits );
 
-        printf( "\n\nDisplay Mode =" );
+        printf( "\n\nDisplay Mode =" );/*ok*/
         if( pGrd->bShowGradient )
-            printf( " Color Gradient" );
+            printf( " Color Gradient" );/*ok*/
 
         if( pGrd->bShowGradient && pGrd->bShowHillShade )
-            printf( " and" );
+            printf( " and" );/*ok*/
 
         if( pGrd->bShowHillShade )
-            printf( " Hill Shading" );
+            printf( " Hill Shading" );/*ok*/
 
         for( int i = 0; i < pGrd->iNumColorInflections; i++ )
         {
-            printf( "\nColor Inflection %d - %f (%d,%d,%d)", i + 1,
+            printf( "\nColor Inflection %d - %f (%d,%d,%d)", i + 1,/*ok*/
                     pGrd->stInflection[i].zVal, pGrd->stInflection[i].r,
                     pGrd->stInflection[i].g, pGrd->stInflection[i].b );
         }
 
         if( pGrd->bHillShadeExists )
         {
-            printf("\n\nHill Shade Azumith = %.1f Inclination = %.1f "
+            printf("\n\nHill Shade Azumith = %.1f Inclination = %.1f "/*ok*/
                    "Brightness = %d Contrast = %d",
                    pGrd->fHillShadeAzimuth, pGrd->fHillShadeAngle,
                    pGrd->cHillShadeBrightness, pGrd->cHillShadeContrast );
         }
         else
-            printf( "\n\nNo Hill Shade Data" );
+            printf( "\n\nNo Hill Shade Data" );/*ok*/
     }
     else                            // print the classified specific stuff
     {
-        printf( "\nNumber of Classes defined = %d",
+        printf( "\nNumber of Classes defined = %u",/*ok*/
                 pGrd->stClassDict->nNumClassifiedItems );
         for( int i = 0; i < static_cast<int>( pGrd->stClassDict->nNumClassifiedItems ); i++ )
         {
-            printf( "\n%s - (%d,%d,%d)  Raw = %d  %d %d",
+            printf( "\n%s - (%d,%d,%d)  Raw = %d  %d %d",/*ok*/
                     pGrd->stClassDict->stClassifedItem[i]->szClassName,
                     pGrd->stClassDict->stClassifedItem[i]->r,
                     pGrd->stClassDict->stClassifedItem[i]->g,
@@ -643,7 +641,6 @@ HLS RGBtoHLS( NWT_RGB rgb )
     return hls;
 }
 
-
 /* utility routine for HLStoRGB */
 static short HueToRGB( short n1, short n2, short hue )
 {
@@ -656,15 +653,16 @@ static short HueToRGB( short n1, short n2, short hue )
 
     /* return r,g, or b value from this tridrant */
     if( hue < (HLSMAX / 6) )
-        return (n1 + (((n2 - n1) * hue + (HLSMAX / 12)) / (HLSMAX / 6)));
+        return n1 + (((n2 - n1) * hue + (HLSMAX / 12)) / (HLSMAX / 6));
     if( hue < (HLSMAX / 2) )
-        return (n2);
+        return n2;
     if( hue < ((HLSMAX * 2) / 3) )
-        return (n1 +
-                (((n2 - n1) * (((HLSMAX * 2) / 3) - hue) +
-                (HLSMAX / 12)) / (HLSMAX / 6)));
+        return
+            n1 +
+            (((n2 - n1) * (((HLSMAX * 2) / 3) - hue) +
+              (HLSMAX / 12)) / (HLSMAX / 6));
     else
-        return (n1);
+        return n1;
 }
 
 NWT_RGB HLStoRGB( HLS hls )
@@ -673,7 +671,9 @@ NWT_RGB HLStoRGB( HLS hls )
 
     if( hls.s == 0 )
     {                            /* achromatic case */
-        rgb.r = rgb.g = rgb.b = static_cast<unsigned char>( (hls.l * RGBMAX) / HLSMAX );
+        rgb.r = static_cast<unsigned char>( (hls.l * RGBMAX) / HLSMAX );
+        rgb.g = rgb.r;
+        rgb.b = rgb.r;
         if( hls.h != UNDEFINED )
         {
             /* ERROR */
diff --git a/frmts/northwood/northwood.h b/frmts/northwood/northwood.h
index d36b57b..122a629 100644
--- a/frmts/northwood/northwood.h
+++ b/frmts/northwood/northwood.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: northwood.h 31749 2015-11-25 02:32:55Z goatbar $
+ * $Id: northwood.h 35897 2016-10-24 11:54:24Z goatbar $
  *
  * Project:  GRC/GRD Reader
  * Purpose:  Northwood Technologies Grid format declarations
@@ -88,6 +88,17 @@ typedef struct
     NWT_CLASSIFIED_ITEM **stClassifedItem;    //hack - it could be up to 64K
 } NWT_CLASSIFIED_DICT;
 
+typedef struct {
+    int iBrightness;
+    int iContrast;
+    bool bGreyscale;
+    bool bGrey;
+    bool bColour;
+    bool bTransparent;
+    int iTransColour;
+    int iTranslucency;
+} RASTER_STYLE;
+
 typedef struct
 {
     char szFileName[256];
@@ -121,6 +132,7 @@ typedef struct
     float fHillShadeAngle;
     NWT_CLASSIFIED_DICT *stClassDict;
     NWT_RGB_ROW stRGBRow;
+    RASTER_STYLE style;
 } NWT_GRID;
 
 int nwt_ParseHeader( NWT_GRID * pGrd, char *nwHeader );
diff --git a/frmts/o/README.TXT b/frmts/o/README.TXT
index 2058412..84dd14c 100644
--- a/frmts/o/README.TXT
+++ b/frmts/o/README.TXT
@@ -4,4 +4,4 @@ gdal/frmts/o
 This directory is where object files are put from the various format
 drivers so they can be easily linked into GDAL.  This file is here to
 ensure that the "o" directory isn't lost when people do a cvs checkout
-with pruning. 
+with pruning.
diff --git a/frmts/ogdi/ogdidataset.cpp b/frmts/ogdi/ogdidataset.cpp
index 7c6273a..2af29c6 100644
--- a/frmts/ogdi/ogdidataset.cpp
+++ b/frmts/ogdi/ogdidataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogdidataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Name:     ogdidataset.cpp
  * Project:  OGDI Bridge
@@ -29,18 +28,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <math.h>
+#include <cmath>
 #include "ecs.h"
 #include "gdal_frmts.h"
 #include "gdal_priv.h"
 #include "cpl_string.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogdidataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ogdidataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*				OGDIDataset				*/
+/*                              OGDIDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -50,34 +51,34 @@ class CPL_DLL OGDIDataset : public GDALDataset
 {
     friend class OGDIRasterBand;
 
-    int		nClientID;
+    int         nClientID;
 
-    ecs_Region	sGlobalBounds;
+    ecs_Region  sGlobalBounds;
     ecs_Region  sCurrentBounds;
     int         nCurrentBand;
     int         nCurrentIndex;
 
-    char	*pszProjection;
+    char        *pszProjection;
 
     static CPLErr CollectLayers(int, char***,char***);
     static CPLErr OverrideGlobalInfo(OGDIDataset*,const char *);
 
     void        AddSubDataset( const char *pszType, const char *pszLayer );
-    char	**papszSubDatasets;
+    char        **papszSubDatasets;
 
   public:
     OGDIDataset();
-    ~OGDIDataset();
+    virtual ~OGDIDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
 
     int GetClientID() { return nClientID; }
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
-    virtual char **GetMetadataDomainList();
-    virtual char **GetMetadata( const char * pszDomain = "" );
+    virtual char **GetMetadataDomainList() override;
+    virtual char **GetMetadata( const char * pszDomain = "" ) override;
 };
 
 /************************************************************************/
@@ -92,10 +93,10 @@ class OGDIRasterBand : public GDALRasterBand
 
     int nOGDIImageType; /* i.e. 1 for RGB */
 
-    char	*pszLayerName;
+    char        *pszLayerName;
     ecs_Family  eFamily;
 
-    int		nComponent; /* varies only for RGB layers */
+    int         nComponent; /* varies only for RGB layers */
 
     GDALColorTable *poCT;
 
@@ -103,7 +104,7 @@ class OGDIRasterBand : public GDALRasterBand
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace,
                               GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) override;
 
     CPLErr         EstablishAccess( int nXOff, int nYOff,
                                     int nXSize, int nYSize,
@@ -113,17 +114,16 @@ class OGDIRasterBand : public GDALRasterBand
 
                    OGDIRasterBand( OGDIDataset *, int, const char *,
                                    ecs_Family, int );
-                   ~OGDIRasterBand();
+    virtual ~OGDIRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual int    HasArbitraryOverviews();
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual int    HasArbitraryOverviews() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                int nBufXSize, int nBufYSize,
-                               GDALDataType eDT, char **papszOptions );
-
+                               GDALDataType eDT, char **papszOptions ) override;
 };
 
 /************************************************************************/
@@ -132,16 +132,14 @@ class OGDIRasterBand : public GDALRasterBand
 
 OGDIRasterBand::OGDIRasterBand( OGDIDataset *poDSIn, int nBandIn,
                                 const char * pszName, ecs_Family eFamilyIn,
-                                int nComponentIn )
-
+                                int nComponentIn ) :
+    nOGDIImageType(0),
+    pszLayerName(CPLStrdup(pszName)),
+    eFamily(eFamilyIn),
+    nComponent(nComponentIn)
 {
-    ecs_Result	*psResult;
-
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->eFamily = eFamilyIn;
-    this->pszLayerName = CPLStrdup(pszName);
-    this->nComponent = nComponentIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     poCT = NULL;
 
 /* -------------------------------------------------------------------- */
@@ -154,7 +152,7 @@ OGDIRasterBand::OGDIRasterBand( OGDIDataset *poDSIn, int nBandIn,
 /* -------------------------------------------------------------------- */
 /*      Get the raster info.                                            */
 /* -------------------------------------------------------------------- */
-    psResult = cln_GetRasterInfo( poDSIn->nClientID );
+    ecs_Result *psResult = cln_GetRasterInfo( poDSIn->nClientID );
     if( ECSERROR(psResult) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -205,7 +203,7 @@ OGDIRasterBand::OGDIRasterBand( OGDIDataset *poDSIn, int nBandIn,
     nOGDIImageType = ECSRASTERINFO(psResult).width;
 
 /* -------------------------------------------------------------------- */
-/*	Currently only works for strips 				*/
+/*      Currently only works for strips                                 */
 /* -------------------------------------------------------------------- */
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
@@ -220,6 +218,7 @@ OGDIRasterBand::~OGDIRasterBand()
 {
     FlushCache();
     CPLFree( pszLayerName );
+    delete poCT;
 }
 
 /************************************************************************/
@@ -249,7 +248,7 @@ CPLErr OGDIRasterBand::IRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
                                   GSpacing nLineSpace,
                                   CPL_UNUSED GDALRasterIOExtraArg* psExtraArg )
 {
-    OGDIDataset	*poODS = (OGDIDataset *) poDS;
+    OGDIDataset *poODS = (OGDIDataset *) poDS;
     CPLErr    eErr;
 #ifdef notdef
     CPLDebug( "OGDIRasterBand",
@@ -272,18 +271,16 @@ CPLErr OGDIRasterBand::IRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 
     for( iScanline = 0; iScanline < nBufYSize; iScanline++ )
     {
-        ecs_Result	*psResult;
-        void		*pLineData;
-        pLineData = ((unsigned char *) pData) + iScanline * nLineSpace;
+        void *pLineData = ((unsigned char *) pData) + iScanline * nLineSpace;
 
         poODS->nCurrentIndex++;
-        psResult = cln_GetNextObject( poODS->nClientID );
+        ecs_Result *psResult = cln_GetNextObject( poODS->nClientID );
 
         if( ECSERROR(psResult) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s", psResult->message );
-            return( CE_Failure );
+            return CE_Failure;
         }
 
         if( eFamily == Matrix )
@@ -300,7 +297,7 @@ CPLErr OGDIRasterBand::IRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 
             if( nComponent == 3 )
             {
-                int	i;
+                int i;
 
                 for( i = 0; i < nBufXSize; i++ )
                 {
@@ -359,7 +356,7 @@ CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
                                         int nBufXSize, int nBufYSize )
 
 {
-    ecs_Result	 *psResult;
+    ecs_Result   *psResult = NULL;
     OGDIDataset  *poODS = (OGDIDataset *) poDS;
 
 /* -------------------------------------------------------------------- */
@@ -408,7 +405,7 @@ CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
                                 / sWin.ns_res);
 
         sWin.south = sWin.north - nWinYSize * sWin.ns_res;
-        dfNSTolerance = MAX(poODS->sCurrentBounds.ns_res,sWin.ns_res);
+        dfNSTolerance = std::max(poODS->sCurrentBounds.ns_res, sWin.ns_res);
     }
     else if( nBufYSize == 1 )
     {
@@ -418,7 +415,7 @@ CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
                                 / sWin.ns_res);
 
         sWin.south = sWin.north - nWinYSize * sWin.ns_res;
-        dfNSTolerance = MAX(poODS->sCurrentBounds.ns_res,sWin.ns_res);
+        dfNSTolerance = std::max(poODS->sCurrentBounds.ns_res, sWin.ns_res);
     }
     else
     {
@@ -429,11 +426,11 @@ CPLErr OGDIRasterBand::EstablishAccess( int nXOff, int nYOff,
     }
 
     if( poODS->nCurrentIndex != 0
-        || ABS(sWin.west - poODS->sCurrentBounds.west) > 0.0001
-        || ABS(sWin.east - poODS->sCurrentBounds.east) > 0.0001
-        || ABS(sWin.north - (poODS->sCurrentBounds.north - poODS->nCurrentIndex * poODS->sCurrentBounds.ns_res)) > dfNSTolerance
-        || ABS(sWin.ew_res/poODS->sCurrentBounds.ew_res - 1.0) > 0.0001
-        || ABS(sWin.ns_res - poODS->sCurrentBounds.ns_res) > dfNSTolerance )
+        || std::abs(sWin.west - poODS->sCurrentBounds.west) > 0.0001
+        || std::abs(sWin.east - poODS->sCurrentBounds.east) > 0.0001
+        || std::abs(sWin.north - (poODS->sCurrentBounds.north - poODS->nCurrentIndex * poODS->sCurrentBounds.ns_res)) > dfNSTolerance
+        || std::abs(sWin.ew_res/poODS->sCurrentBounds.ew_res - 1.0) > 0.0001
+        || std::abs(sWin.ns_res - poODS->sCurrentBounds.ns_res) > dfNSTolerance )
     {
         CPLDebug( "OGDIRasterBand",
                   "<EstablishAccess: Set Region(%d,%d,%d,%d,%d,%d>",
@@ -509,18 +506,30 @@ CPLErr OGDIRasterBand::AdviseRead( int nXOff, int nYOff,
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            OGDIDataset()                            */
 /************************************************************************/
 
-OGDIDataset::OGDIDataset()
-
+OGDIDataset::OGDIDataset() :
+    nClientID(-1),
+    nCurrentBand(-1),
+    nCurrentIndex(-1),
+    pszProjection(NULL),
+    papszSubDatasets(NULL)
 {
-    nClientID = -1;
-    nCurrentBand = -1;
-    nCurrentIndex = -1;
-    papszSubDatasets = NULL;
+    sGlobalBounds.north = 0.0;
+    sGlobalBounds.south = 0.0;
+    sGlobalBounds.east = 0.0;
+    sGlobalBounds.west = 0.0;
+    sGlobalBounds.ns_res = 0.0;
+    sGlobalBounds.ew_res = 0.0;
+
+    sCurrentBounds.north = 0.0;
+    sCurrentBounds.south = 0.0;
+    sCurrentBounds.east = 0.0;
+    sCurrentBounds.west = 0.0;
+    sCurrentBounds.ns_res = 0.0;
+    sCurrentBounds.ew_res = 0.0;
 }
 
 /************************************************************************/
@@ -566,12 +575,12 @@ char **OGDIDataset::GetMetadata( const char *pszDomain )
 GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-    ecs_Result *psResult;
     int nClientID;
-    char        **papszImages=NULL, **papszMatrices=NULL;
+    char **papszImages = NULL;
+    char **papszMatrices = NULL;
 
     if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "gltp:") )
-        return( NULL );
+        return NULL ;
 
 /* -------------------------------------------------------------------- */
 /*      Confirm the requested access is supported.                      */
@@ -589,8 +598,10 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Honour quoted strings for the layer name, since some layers     */
 /*      (i.e. RPF/CADRG) have embedded colons.                           */
 /* -------------------------------------------------------------------- */
-    int       nC1=-1, nC2=-1, bInQuotes = FALSE;
-    char      *pszURL = CPLStrdup(poOpenInfo->pszFilename);
+    int nC1 = -1;
+    int nC2 = -1;
+    int bInQuotes = FALSE;
+    char *pszURL = CPLStrdup(poOpenInfo->pszFilename);
 
     for( int i = static_cast<int>(strlen(pszURL))-1; i > 0; i-- )
     {
@@ -630,7 +641,7 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Open the client interface.                                      */
 /* -------------------------------------------------------------------- */
-    psResult = cln_CreateClient( &nClientID, pszURL );
+    ecs_Result *psResult = cln_CreateClient( &nClientID, pszURL );
 
     if( ECSERROR(psResult) )
     {
@@ -649,11 +660,11 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        char	*pszLayerName = CPLStrdup( pszURL+nC2+1 );
+        char *pszLayerName = CPLStrdup( pszURL+nC2+1 );
 
         if( pszLayerName[0] == '"' )
         {
-            int		nOut = 0;
+            int nOut = 0;
 
             for( int i = 1; pszLayerName[i] != '\0'; i++ )
             {
@@ -695,15 +706,15 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
                   "have any identifiable raster layers.  Perhaps it is a\n"
                   "vector datastore?" );
         cln_DestroyClient( nClientID );
+        CSLDestroy( papszImages );
+        CSLDestroy( papszMatrices );
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    OGDIDataset 	*poDS;
-
-    poDS = new OGDIDataset();
+    OGDIDataset *poDS = new OGDIDataset();
 
     poDS->nClientID = nClientID;
     poDS->SetDescription( poOpenInfo->pszFilename );
@@ -716,6 +727,9 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", psResult->message );
+        CSLDestroy( papszImages );
+        CSLDestroy( papszMatrices );
+        delete poDS;
         return NULL;
     }
 
@@ -726,6 +740,9 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", psResult->message );
+        CSLDestroy( papszImages );
+        CSLDestroy( papszMatrices );
+        delete poDS;
         return NULL;
     }
 
@@ -752,6 +769,9 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", psResult->message );
+        CSLDestroy( papszImages );
+        CSLDestroy( papszMatrices );
+        delete poDS;
         return NULL;
     }
 
@@ -775,7 +795,7 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     else
     {
-        int	i;
+        int i;
 
         for( i = 0; papszMatrices != NULL && papszMatrices[i] != NULL; i++ )
             poDS->AddSubDataset( "Matrix", papszMatrices[i] );
@@ -808,10 +828,9 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
 
     for( int i=0; papszImages != NULL && papszImages[i] != NULL; i++)
     {
-        OGDIRasterBand	*poBand;
-
-        poBand = new OGDIRasterBand( poDS, poDS->GetRasterCount()+1,
-                                     papszImages[i], Image, 0 );
+        OGDIRasterBand *poBand =
+            new OGDIRasterBand( poDS, poDS->GetRasterCount() + 1,
+                                papszImages[i], Image, 0 );
 
         poDS->SetBand( poDS->GetRasterCount()+1, poBand );
 
@@ -833,7 +852,7 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
     CSLDestroy( papszMatrices );
     CSLDestroy( papszImages );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -843,8 +862,8 @@ GDALDataset *OGDIDataset::Open( GDALOpenInfo * poOpenInfo )
 void OGDIDataset::AddSubDataset( const char *pszType, const char *pszLayer )
 
 {
-    char	szName[80];
-    int		nCount = CSLCount( papszSubDatasets ) / 2;
+    char szName[80];
+    int nCount = CSLCount( papszSubDatasets ) / 2;
 
     snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
     papszSubDatasets =
@@ -866,10 +885,9 @@ CPLErr OGDIDataset::CollectLayers( int nClientID,
                                    char ***ppapszMatrices )
 
 {
-    const ecs_LayerCapabilities	*psLayer;
-    int		iLayer;
+    const ecs_LayerCapabilities *psLayer = NULL;
 
-    for( iLayer = 0;
+    for( int iLayer = 0;
          (psLayer = cln_GetLayerCapabilities(nClientID,iLayer)) != NULL;
          iLayer++ )
     {
@@ -897,10 +915,9 @@ CPLErr OGDIDataset::OverrideGlobalInfo( OGDIDataset *poDS,
                                         const char *pszLayer )
 
 {
-    const ecs_LayerCapabilities	*psLayer;
-    int		iLayer;
+    const ecs_LayerCapabilities *psLayer = NULL;
 
-    for( iLayer = 0;
+    for( int iLayer = 0;
          (psLayer = cln_GetLayerCapabilities(poDS->nClientID,iLayer)) != NULL;
          iLayer++ )
     {
@@ -925,7 +942,7 @@ CPLErr OGDIDataset::OverrideGlobalInfo( OGDIDataset *poDS,
 const char *OGDIDataset::GetProjectionRef()
 
 {
-    return( pszProjection );
+    return pszProjection;
 }
 
 /************************************************************************/
@@ -943,7 +960,7 @@ CPLErr OGDIDataset::GetGeoTransform( double * padfTransform )
     padfTransform[4] = 0.0;
     padfTransform[5] = -sGlobalBounds.ns_res;
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
diff --git a/frmts/openjpeg/frmt_jp2openjpeg.html b/frmts/openjpeg/frmt_jp2openjpeg.html
index 7a1275f..20b069b 100644
--- a/frmts/openjpeg/frmt_jp2openjpeg.html
+++ b/frmts/openjpeg/frmt_jp2openjpeg.html
@@ -26,6 +26,30 @@ arbitrary band count, and adding/reading metadata. Update of georeferencing or
 metadata of existing file is also supported. Optional intellectual property
 metdata can be read/written in the xml:IPR box.</p>
 
+<h2><a name="georeferencing">Georeferencing</a></h2>
+
+<p>
+Georeferencing information can come from different sources : internal (GeoJP2
+or GMLJP2 boxes), worldfile .j2w/.wld sidecar files, or PAM (Persitant Auxiliary metadata)
+.aux.xml sidecar files.
+By default, information is fetched in following order (first listed is the most
+prioritary): PAM, GeoJP2, GMLJP2, WORLDFILE.
+</p>
+<p>Starting with GDAL 2.2, the allowed sources
+and their priority order can be changed with the GDAL_GEOREF_SOURCES
+configuration option (or GEOREF_SOURCES open option) whose value is a
+comma-separated list of the following keywords :
+PAM, GEOJP2, GMLJP2, INTERNAL (shortcut for GEOJP2,GMLJP2), WORLDFILE, NONE.
+First mentioned sources are the most prioritary over the next ones. A non mentioned
+source will be ignored.
+</p>
+<p>
+For example setting it to "WORLDFILE,PAM,INTERNAL" will make a geotransformation
+matrix from a potential worldfile prioritary over PAM or internal JP2 boxes.
+Setting it to "PAM,WORLDFILE,GEOJP2" will use the mentioned sources and
+ignore GMLJP2 boxes.
+</p>
+
 <h2>Option Options</h2>
 
 (GDAL >= 2.0 )
@@ -34,6 +58,12 @@ The following open option is available:
 <ul>
 <li><p><b>1BIT_ALPHA_PROMOTION=YES/NO</b>: Whether a 1-bit alpha channel should be promoted to 8-bit.
 Defaults to YES.</li>
+<li><p><b>GEOREF_SOURCES=string</b>: (GDAL > 2.2) Define which georeferencing sources are
+allowed and their priority order. See <a href="#georeferencing"><i>Georeferencing</i></a> paragraph.</li>
+<li><p><b>USE_TILE_AS_BLOCK=YES/NO</b>: (GDAL > 2.2) Whether to always use the JPEG-2000 block size as the GDAL block size
+Defaults to NO. Setting this option can be useful when doing whole image
+decompression and the image is single-tiled. Note however that the tile size
+must not exceed 2 GB since that's the limit supported by GDAL.</li>
 </ul>
 
 <h2>Creation Options</h2>
@@ -49,12 +79,17 @@ file. Unless GMLJP2V2_DEF is used, the version of the GMLJP2 box will be
 version 1. Defaults to YES.<p>
 
 <li> <b>GMLJP2V2_DEF=filename</b>: (Starting with GDAL 2.0) Indicates whether a GML box
-conforming to the <a href="http://docs.opengeospatial.org/is/08-085r4/08-085r4.html">
-OGC GML in JPEG2000, version 2</a> specification should be included in the
+conforming to the <a href="http://docs.opengeospatial.org/is/08-085r5/08-085r5.html">
+OGC GML in JPEG2000, version 2.0.1</a> specification should be included in the
 file. <i>filename</i> must point to a file with a JSon content that defines how
 the GMLJP2 v2 box should be built. See below section for the syntax of the JSon configuration file.
 It is also possible to directly pass the JSon content inlined as a string.
-If filename is just set to YES, a minimal instance will be built.<p>
+If filename is just set to YES, a minimal instance will be built.
+Note: GDAL 2.0 and 2.1 use the older <a href="http://docs.opengeospatial.org/is/08-085r4/08-085r4.html">
+OGC GML in JPEG2000, version 2.0</a> specification, that differ essentially
+by the content of the gml:domainSet, gml:rangeSet and gmlcov:rangeType elements
+of gmljp2:GMLJP2CoverageCollection.
+<p>
 
 <li> <b>GeoJP2=YES/NO</b>: (Starting with GDAL 1.10) Indicates whether a
 UUID/GeoTIFF box conforming to the GeoJP2 (GeoTIFF in JPEG2000) specification
@@ -248,6 +283,21 @@ the below syntax (elements starting with "#" are documentation, and can be omitt
             "If not specified, GDAL will auto-generate a GMLJP2RectifiedGridCoverage" ],
         "grid_coverage_file": "gmljp2gridcoverage.xml",
 
+        "#grid_coverage_range_type_field_predefined_name_doc": [
+            "New in GDAL 2.2",
+            "One of Color, Elevation_meter or Panchromatic ",
+            "to fill gmlcov:rangeType/swe:DataRecord/swe:field",
+            "Only used if grid_coverage_file is not defined.",
+            "Exclusive with grid_coverage_range_type_file" ],
+        "grid_coverage_range_type_field_predefined_name": "Color",
+
+        "#grid_coverage_range_type_file_doc": [
+            "New in GDAL 2.2",
+            "File that is XML content to put under gml:RectifiedGrid/gmlcov:rangeType",
+            "Only used if grid_coverage_file is not defined.",
+            "Exclusive with grid_coverage_range_type_field_predefined_name" ],
+        "grid_coverage_range_type_file": "grid_coverage_range_type.xml",
+
         "#crs_url_doc": [
             "true for http://www.opengis.net/def/crs/EPSG/0/XXXX CRS URL.",
             "If false, use CRS URN. Default value is true",
@@ -298,14 +348,17 @@ the below syntax (elements starting with "#" are documentation, and can be omitt
         ],
 
         "#gml_filelist_doc" :[
-            "An array of GML files. Can be either GML filenames, ",
+            "An array of GML files or vector files that will be on-the-fly converted",
+            "to GML 3.2. Can be either GML filenames (or other OGR datasource names), ",
             "or a more complete description" ],
         "gml_filelist": [
 
             "my.gml",
 
+            "my.shp",
+
             {
-                "#file_doc": "Can use relative or absolute paths. Exclusive of remote_resource",
+                "#file_doc": "OGR datasource. Can use relative or absolute paths. Exclusive of remote_resource",
                 "file": "converted/test_0.gml",
 
                 "#remote_resource_doc": "URL of a feature collection that must be referenced through a xlink:href",
@@ -333,7 +386,7 @@ the below syntax (elements starting with "#" are documentation, and can be omitt
         ],
 
 
-        "#styles_doc: [ "An array of styles. For example SLD files" ],
+        "#styles_doc": [ "An array of styles. For example SLD files" ],
         "styles" : [
             {
                 "#file_doc": "Can use relative or absolute paths.",
@@ -345,7 +398,7 @@ the below syntax (elements starting with "#" are documentation, and can be omitt
             }
         ],
 
-        "#extensions_doc: [ "An array of extensions." ],
+        "#extensions_doc": [ "An array of extensions." ],
         "extensions" : [
             {
                 "#file_doc": "Can use relative or absolute paths.",
@@ -418,6 +471,8 @@ OPEN_REMOTE_GML is set to YES.</p>
 <li><p> Implemented as <tt>gdal/frmts/openjpeg/openjpegdataset.cpp</tt>.</p></li>
 <li><p> <a href="http://www.jpeg.org/jpeg2000/index.html">Official JPEG-2000 page<a></p></li>
 <li><p> <a href="https://github.com/uclouvain/openjpeg">The OpenJPEG library home page</a></p></li>
+<li><p> <a href="http://docs.opengeospatial.org/is/08-085r4/08-085r4.html">OGC GML in JPEG2000, version 2.0</a> (GDAL 2.0 and 2.1)</p></li>
+<li><p> <a href="http://docs.opengeospatial.org/is/08-085r5/08-085r5.html">OGC GML in JPEG2000, version 2.0.1</a> (GDAL 2.2 and above)</p></li>
 <li><p> <a href="http://inspire.ec.europa.eu/documents/Data_Specifications/INSPIRE_DataSpecification_OI_v3.0.pdf">
 Inspire Data Specification on Orthoimagery - Technical Guidelines</a></p></li>
 </ul>
diff --git a/frmts/openjpeg/openjpegdataset.cpp b/frmts/openjpeg/openjpegdataset.cpp
index 2d6aaa9..69bed33 100644
--- a/frmts/openjpeg/openjpegdataset.cpp
+++ b/frmts/openjpeg/openjpegdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: openjpegdataset.cpp 36187 2016-11-09 15:20:50Z rouault $
  *
  * Project:  JPEG2000 driver based on OpenJPEG library
  * Purpose:  JPEG2000 driver based on OpenJPEG library
@@ -29,6 +28,11 @@
  ****************************************************************************/
 
 /* This file is to be used with openjpeg 2.0 */
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
 
 #if defined(OPENJPEG_VERSION) && OPENJPEG_VERSION >= 20100
 #include <openjpeg-2.1/openjpeg.h>
@@ -36,6 +40,11 @@
 #include <stdio.h> /* openjpeg.h needs FILE* */
 #include <openjpeg-2.0/openjpeg.h>
 #endif
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
 #include <vector>
 
 #include "cpl_atomic_ops.h"
@@ -46,7 +55,9 @@
 #include "gdaljp2metadata.h"
 #include "vrt/vrtdataset.h"
 
-CPL_CVSID("$Id: openjpegdataset.cpp 36187 2016-11-09 15:20:50Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: openjpegdataset.cpp 37373 2017-02-13 11:49:40Z rouault $");
 
 /************************************************************************/
 /*                  JP2OpenJPEGDataset_ErrorCallback()                  */
@@ -63,6 +74,17 @@ static void JP2OpenJPEGDataset_ErrorCallback(const char *pszMsg, CPL_UNUSED void
 
 static void JP2OpenJPEGDataset_WarningCallback(const char *pszMsg, CPL_UNUSED void *unused)
 {
+    if( strcmp(pszMsg, "No incltree created.\n") == 0 ||
+        strcmp(pszMsg, "No imsbtree created.\n") == 0 ||
+        strcmp(pszMsg,
+               "tgt_create tree->numnodes == 0, no tree created.\n") == 0 )
+    {
+        // Ignore warnings related to empty tag-trees. There's nothing wrong
+        // about that.
+        // Fixed submitted upstream with
+        // https://github.com/uclouvain/openjpeg/pull/893
+        return;
+    }
     if( strcmp(pszMsg, "Empty SOT marker detected: Psot=12.\n") == 0 )
     {
         static int bWarningEmitted = FALSE;
@@ -129,6 +151,8 @@ static OPJ_SIZE_T JP2OpenJPEGDataset_Write(void* pBuffer, OPJ_SIZE_T nBytes,
 #ifdef DEBUG_IO
     CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Write(%d) = %d", (int)nBytes, nRet);
 #endif
+    if( static_cast<OPJ_SIZE_T>(nRet) != nBytes )
+        return static_cast<OPJ_SIZE_T>(-1);
     return nRet;
 }
 
@@ -199,11 +223,11 @@ class JP2OpenJPEGDataset : public GDALJP2AbstractDataset
     int         bHasGeoreferencingAtOpening;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
   public:
                 JP2OpenJPEGDataset();
-                ~JP2OpenJPEGDataset();
+    virtual ~JP2OpenJPEGDataset();
 
     static int Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset  *Open( GDALOpenInfo * );
@@ -213,15 +237,15 @@ class JP2OpenJPEGDataset : public GDALJP2AbstractDataset
                                            GDALProgressFunc pfnProgress,
                                            void * pProgressData );
 
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr SetGeoTransform( double* );
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual CPLErr SetGeoTransform( double* ) override;
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) override;
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                             const char * pszDomain = "" );
+                             const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                  const char * pszValue,
-                                 const char * pszDomain = "" );
+                                 const char * pszDomain = "" ) override;
 
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
@@ -230,7 +254,7 @@ class JP2OpenJPEGDataset : public GDALJP2AbstractDataset
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg) override;
 
     static void         WriteBox(VSILFILE* fp, GDALJP2Box* poBox);
     static void         WriteGDALMetadataBox( VSILFILE* fp, GDALDataset* poSrcDS,
@@ -271,26 +295,25 @@ class JP2OpenJPEGRasterBand : public GDALPamRasterBand
                                        GDALDataType eDataType, int nBits,
                                        int bPromoteTo8Bit,
                                        int nBlockXSize, int nBlockYSize );
-                ~JP2OpenJPEGRasterBand();
+    virtual ~JP2OpenJPEGRasterBand();
 
-    virtual CPLErr          IReadBlock( int, int, void * );
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
     virtual CPLErr          IRasterIO( GDALRWFlag eRWFlag,
                                   int nXOff, int nYOff, int nXSize, int nYSize,
                                   void * pData, int nBufXSize, int nBufYSize,
                                   GDALDataType eBufType,
                                   GSpacing nPixelSpace, GSpacing nLineSpace,
-                                  GDALRasterIOExtraArg* psExtraArg);
+                                  GDALRasterIOExtraArg* psExtraArg) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable* GetColorTable() { return poCT; }
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable* GetColorTable() override { return poCT; }
 
-    virtual int             GetOverviewCount();
-    virtual GDALRasterBand* GetOverview(int iOvrLevel);
+    virtual int             GetOverviewCount() override;
+    virtual GDALRasterBand* GetOverview(int iOvrLevel) override;
 
-    virtual int HasArbitraryOverviews() { return poCT == NULL; }
+    virtual int HasArbitraryOverviews() override { return poCT == NULL; }
 };
 
-
 /************************************************************************/
 /*                        JP2OpenJPEGRasterBand()                       */
 /************************************************************************/
@@ -400,6 +423,7 @@ CPLErr JP2OpenJPEGRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                          pData, nBufXSize, nBufYSize, eBufType,
                                          nPixelSpace, nLineSpace, psExtraArg );
 
+    // cppcheck-suppress redundantAssignment
     poGDS->bEnoughMemoryToLoadOtherBands = TRUE;
     return eErr;
 }
@@ -447,14 +471,6 @@ void JP2OpenJPEGDataset::JP2OpenJPEGReadBlockInThread(void* userdata)
     int nPair;
     JobStruct* poJob = (JobStruct*) userdata;
 
-    /*void* pDummy = VSIMalloc(128*1024);
-    if( pDummy == NULL )
-    {
-        fprintf(stderr, "Out of memory in thread\n");
-        poJob->bSuccess = false;
-        return;
-    }*/
-
     JP2OpenJPEGDataset* poGDS = poJob->poGDS;
     int nBand = poJob->nBand;
     int nPairs = (int)poJob->oPairs.size();
@@ -547,7 +563,7 @@ int JP2OpenJPEGDataset::PreloadBlocks(JP2OpenJPEGRasterBand* poBand,
 
         if( nBlocksToLoad > 1 )
         {
-            int l_nThreads = MIN(nBlocksToLoad, nMaxThreads);
+            const int l_nThreads = std::min(nBlocksToLoad, nMaxThreads);
             CPLJoinableThread** pahThreads = (CPLJoinableThread**) VSI_CALLOC_VERBOSE( sizeof(CPLJoinableThread*), l_nThreads );
             if( pahThreads == NULL )
             {
@@ -709,8 +725,10 @@ CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fpIn,
     int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
 
     int nTileNumber = nBlockXOff + nBlockYOff * poBand->nBlocksPerRow;
-    int nWidthToRead = MIN(nBlockXSize, nRasterXSize - nBlockXOff * nBlockXSize);
-    int nHeightToRead = MIN(nBlockYSize, nRasterYSize - nBlockYOff * nBlockYSize);
+    const int nWidthToRead =
+        std::min(nBlockXSize, nRasterXSize - nBlockXOff * nBlockXSize);
+    const int nHeightToRead =
+        std::min(nBlockYSize, nRasterYSize - nBlockYOff * nBlockYSize);
 
     pCodec = opj_create_decompress(OPJ_CODEC_J2K);
     if( pCodec == NULL )
@@ -803,11 +821,11 @@ CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fpIn,
 
     for(int xBand = 0; xBand < nBandCount; xBand ++)
     {
-        void* pDstBuffer;
         GDALRasterBlock *poBlock = NULL;
         int iBand = (panBandMap) ? panBandMap[xBand] : xBand + 1;
         int bPromoteTo8Bit = ((JP2OpenJPEGRasterBand*)GetRasterBand(iBand))->bPromoteTo8Bit;
 
+        void* pDstBuffer = NULL;
         if (iBand == nBand)
             pDstBuffer = pImage;
         else
@@ -957,7 +975,6 @@ end:
     return eErr;
 }
 
-
 /************************************************************************/
 /*                         GetOverviewCount()                           */
 /************************************************************************/
@@ -1057,10 +1074,15 @@ JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
         if( bRewrite )
         {
             GDALJP2Box oBox( fp );
-            vsi_l_offset nOffsetJP2C = 0, nLengthJP2C = 0,
-                         nOffsetXML = 0, nOffsetASOC = 0, nOffsetUUID = 0,
-                         nOffsetIHDR = 0, nLengthIHDR = 0;
-            int bMSIBox = FALSE, bGMLData = FALSE;
+            vsi_l_offset nOffsetJP2C = 0;
+            vsi_l_offset nLengthJP2C = 0;
+            vsi_l_offset nOffsetXML = 0;
+            vsi_l_offset nOffsetASOC = 0;
+            vsi_l_offset nOffsetUUID = 0;
+            vsi_l_offset nOffsetIHDR = 0;
+            vsi_l_offset nLengthIHDR = 0;
+            int bMSIBox = FALSE;
+            int bGMLData = FALSE;
             int bUnsupportedConfiguration = FALSE;
             if( oBox.ReadFirst() )
             {
@@ -1376,6 +1398,11 @@ CPLErr JP2OpenJPEGDataset::SetMetadata( char ** papszMetadata,
     if( eAccess == GA_Update )
     {
         bRewrite = TRUE;
+        if( pszDomain == NULL || EQUAL(pszDomain, "") )
+        {
+            CSLDestroy(m_papszMainMD);
+            m_papszMainMD = CSLDuplicate(papszMetadata);
+        }
         return GDALDataset::SetMetadata(papszMetadata, pszDomain);
     }
     return GDALJP2AbstractDataset::SetMetadata(papszMetadata, pszDomain);
@@ -1392,6 +1419,10 @@ CPLErr JP2OpenJPEGDataset::SetMetadataItem( const char * pszName,
     if( eAccess == GA_Update )
     {
         bRewrite = TRUE;
+        if( pszDomain == NULL || EQUAL(pszDomain, "") )
+        {
+            m_papszMainMD = CSLSetNameValue( GetMetadata(), pszName, pszValue );
+        }
         return GDALDataset::SetMetadataItem(pszName, pszValue, pszDomain);
     }
     return GDALJP2AbstractDataset::SetMetadataItem(pszName, pszValue, pszDomain);
@@ -1485,10 +1516,7 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     OPJ_CODEC_FORMAT eCodecFormat = (nCodeStreamStart == 0) ? OPJ_CODEC_J2K : OPJ_CODEC_JP2;
 
-
-    opj_codec_t* pCodec;
-
-    pCodec = opj_create_decompress(OPJ_CODEC_J2K);
+    opj_codec_t* pCodec = opj_create_decompress(OPJ_CODEC_J2K);
     if( pCodec == NULL )
         return NULL;
 
@@ -1650,7 +1678,6 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
@@ -1670,37 +1697,44 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nCodeStreamLength = nCodeStreamLength;
     poDS->bIs420 = bIs420;
 
-    poDS->bUseSetDecodeArea =
-        (poDS->nRasterXSize == (int)nTileW &&
-         poDS->nRasterYSize == (int)nTileH &&
-         (poDS->nRasterXSize > 1024 ||
-          poDS->nRasterYSize > 1024));
-
-    /* Sentinel2 preview datasets are 343x343 and 60m are 1830x1830, but they */
-    /* are tiled with tile dimensions 2048x2048. It would be a waste of */
-    /* memory to allocate such big blocks */
-    if( poDS->nRasterXSize < (int)nTileW &&
-        poDS->nRasterYSize < (int)nTileH )
+    if( CPLFetchBool(poOpenInfo->papszOpenOptions, "USE_TILE_AS_BLOCK", false) )
     {
-        poDS->bUseSetDecodeArea = TRUE;
-        nTileW = poDS->nRasterXSize;
-        nTileH = poDS->nRasterYSize;
-        if (nTileW > 2048) nTileW = 2048;
-        if (nTileH > 2048) nTileH = 2048;
+        poDS->bUseSetDecodeArea = false;
     }
-    else if (poDS->bUseSetDecodeArea)
+    else
     {
-        // Arbitrary threshold... ~4 million at least needed for the GRIB2
-        // images mentionned below.
-        if( nTileH == 1 && nTileW < 20 * 1024 * 1024 )
-        {
-            // Some GRIB2 JPEG2000 compressed images are a 2D image organized
-            // as a single line image...
-        }
-        else
-        {
-            if (nTileW > 1024) nTileW = 1024;
-            if (nTileH > 1024) nTileH = 1024;
+        poDS->bUseSetDecodeArea =
+            (poDS->nRasterXSize == (int)nTileW &&
+            poDS->nRasterYSize == (int)nTileH &&
+            (poDS->nRasterXSize > 1024 ||
+            poDS->nRasterYSize > 1024));
+
+        /* Sentinel2 preview datasets are 343x343 and 60m are 1830x1830, but they */
+        /* are tiled with tile dimensions 2048x2048. It would be a waste of */
+        /* memory to allocate such big blocks */
+        if( poDS->nRasterXSize < (int)nTileW &&
+            poDS->nRasterYSize < (int)nTileH )
+        {
+            poDS->bUseSetDecodeArea = TRUE;
+            nTileW = poDS->nRasterXSize;
+            nTileH = poDS->nRasterYSize;
+            if (nTileW > 2048) nTileW = 2048;
+            if (nTileH > 2048) nTileH = 2048;
+        }
+        else if (poDS->bUseSetDecodeArea)
+        {
+            // Arbitrary threshold... ~4 million at least needed for the GRIB2
+            // images mentioned below.
+            if( nTileH == 1 && nTileW < 20 * 1024 * 1024 )
+            {
+                // Some GRIB2 JPEG2000 compressed images are a 2D image organized
+                // as a single line image...
+            }
+            else
+            {
+                if (nTileW > 1024) nTileW = 1024;
+                if (nTileH > 1024) nTileH = 1024;
+            }
         }
     }
 
@@ -1893,12 +1927,13 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     for( iBand = 1; iBand <= poDS->nBands; iBand++ )
     {
-        int bPromoteTo8Bit = (
+        const bool bPromoteTo8Bit =
             iBand == poDS->nAlphaIndex + 1 &&
             psImage->comps[(poDS->nAlphaIndex==0 && poDS->nBands > 1) ? 1 : 0].prec == 8 &&
             psImage->comps[poDS->nAlphaIndex ].prec == 1 &&
-            CSLFetchBoolean(poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION",
-                    CPLTestBool(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES"))) );
+            CPLFetchBool(
+                poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION",
+                CPLTestBool(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES")));
         if( bPromoteTo8Bit )
             CPLDebug("JP2OpenJPEG", "Alpha band is promoted from 1 bit to 8 bit");
 
@@ -1965,12 +2000,13 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
         poODS->bIs420 = bIs420;
         for( iBand = 1; iBand <= poDS->nBands; iBand++ )
         {
-            int bPromoteTo8Bit = (
+            const bool bPromoteTo8Bit =
                 iBand == poDS->nAlphaIndex + 1 &&
                 psImage->comps[(poDS->nAlphaIndex==0 && poDS->nBands > 1) ? 1 : 0].prec == 8 &&
                 psImage->comps[poDS->nAlphaIndex].prec == 1 &&
-                CSLFetchBoolean(poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION",
-                        CPLTestBool(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES"))) );
+                CPLFetchBool(
+                    poOpenInfo->papszOpenOptions, "1BIT_ALPHA_PROMOTION",
+                    CPLTestBool(CPLGetConfigOption("JP2OPENJPEG_PROMOTE_1BIT_ALPHA_AS_8BIT", "YES")));
 
             poODS->SetBand( iBand, new JP2OpenJPEGRasterBand( poODS, iBand, eDataType,
                                                               bPromoteTo8Bit ? 8: psImage->comps[iBand-1].prec,
@@ -1979,7 +2015,6 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
         }
 
         poDS->papoOverviewDS[poDS->nOverviewCount ++] = poODS;
-
     }
 
     opj_destroy_codec(pCodec);
@@ -2011,7 +2046,8 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nOpenFlags & GDAL_OF_VECTOR )
     {
         poDS->LoadVectorLayers(
-            CSLFetchBoolean(poOpenInfo->papszOpenOptions, "OPEN_REMOTE_GML", FALSE));
+            CPLFetchBool(poOpenInfo->papszOpenOptions,
+                         "OPEN_REMOTE_GML", false));
 
         // If file opened in vector-only mode and there's no vector,
         // return
@@ -2034,7 +2070,7 @@ GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     //poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -2068,7 +2104,7 @@ void JP2OpenJPEGDataset::WriteGDALMetadataBox( VSILFILE* fp,
                                                char** papszOptions )
 {
     GDALJP2Box* poBox = GDALJP2Metadata::CreateGDALMultiDomainMetadataXMLBox(
-        poSrcDS, CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE));
+        poSrcDS, CPLFetchBool(papszOptions, "MAIN_MD_DOMAIN_ONLY", false));
     if( poBox )
         WriteBox(fp, poBox);
     delete poBox;
@@ -2171,7 +2207,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         return NULL;
     }
 
-    int bInspireTG = CSLFetchBoolean(papszOptions, "INSPIRE_TG", FALSE);
+    const bool bInspireTG = CPLFetchBool(papszOptions, "INSPIRE_TG", false);
 
 /* -------------------------------------------------------------------- */
 /*      Analyze creation options.                                       */
@@ -2218,7 +2254,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
 
     // By default do not generate tile sizes larger than the dataset
     // dimensions
-    if( !CSLFetchBoolean(papszOptions, "BLOCKSIZE_STRICT", FALSE) )
+    if( !CPLFetchBool(papszOptions, "BLOCKSIZE_STRICT", false) )
     {
         if (nXSize < nBlockXSize)
         {
@@ -2254,8 +2290,8 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
                  pszPROGORDER);
     }
 
-    int bIsIrreversible =
-            ! (CSLFetchBoolean(papszOptions, "REVERSIBLE", poCT != NULL));
+    const bool bIsIrreversible =
+        !CPLFetchBool(papszOptions, "REVERSIBLE", poCT != NULL);
 
     std::vector<double> adfRates;
     const char* pszQuality = CSLFetchNameValueDef(papszOptions, "QUALITY", NULL);
@@ -2288,19 +2324,19 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         }
         CSLDestroy(papszTokens);
     }
-    if( adfRates.size() == 0 )
+    if( adfRates.empty() )
     {
         adfRates.push_back(100. / dfDefaultQuality);
     }
 
-    if( poCT != NULL && (bIsIrreversible || adfRates[adfRates.size()-1] != 100.0 / 100.0) )
+    if( poCT != NULL && (bIsIrreversible || adfRates.back() != 100.0 / 100.0) )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "Encoding a dataset with a color table with REVERSIBLE != YES "
                  "or QUALITY != 100 will likely lead to bad visual results");
     }
 
-    int nMaxTileDim = MAX(nBlockXSize, nBlockYSize);
+    const int nMaxTileDim = std::max(nBlockXSize, nBlockYSize);
     int nNumResolutions = 1;
     /* Pickup a reasonable value compatible with PROFILE_1 requirements */
     while( (nMaxTileDim >> (nNumResolutions-1)) > 128 )
@@ -2323,7 +2359,9 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
     int bSOP = CPLTestBool(CSLFetchNameValueDef(papszOptions, "SOP", "FALSE"));
     int bEPH = CPLTestBool(CSLFetchNameValueDef(papszOptions, "EPH", "FALSE"));
 
-    int nRedBandIndex = -1, nGreenBandIndex = -1, nBlueBandIndex = -1;
+    int nRedBandIndex = -1;
+    int nGreenBandIndex = -1;
+    int nBlueBandIndex = -1;
     int nAlphaBandIndex = -1;
     for(int i=0;i<nBands;i++)
     {
@@ -2464,7 +2502,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         }
 
         bProfile1 = TRUE;
-        const char* pszReq21OrEmpty = (bInspireTG) ? " (TG requirement 21)" : "";
+        const char* pszReq21OrEmpty = bInspireTG ? " (TG requirement 21)" : "";
         if( (nBlockXSize != nXSize || nBlockYSize != nYSize) &&
             (nBlockXSize != nBlockYSize || nBlockXSize > 1024 || nBlockYSize > 1024 ) )
         {
@@ -2552,12 +2590,12 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
 /*      Georeferencing options                                          */
 /* -------------------------------------------------------------------- */
 
-    int bGMLJP2Option = CSLFetchBoolean( papszOptions, "GMLJP2", TRUE );
+    bool bGMLJP2Option = CPLFetchBool( papszOptions, "GMLJP2", true );
     int nGMLJP2Version = 1;
     const char* pszGMLJP2V2Def = CSLFetchNameValue( papszOptions, "GMLJP2V2_DEF" );
     if( pszGMLJP2V2Def != NULL )
     {
-        bGMLJP2Option = TRUE;
+        bGMLJP2Option = true;
         nGMLJP2Version = 2;
         if( bInspireTG )
         {
@@ -2566,7 +2604,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
             return NULL;
         }
     }
-    int bGeoJP2Option = CSLFetchBoolean( papszOptions, "GeoJP2", TRUE );
+    const bool bGeoJP2Option = CPLFetchBool( papszOptions, "GeoJP2", true );
 
     GDALJP2Metadata oJP2MD;
 
@@ -2627,8 +2665,8 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
                  "GeoJP2 box was explicitly required but cannot be written due "
                  "to lack of georeferencing");
     }
-    int bGeoBoxesAfter = CSLFetchBoolean(papszOptions, "GEOBOXES_AFTER_JP2C",
-                                         bInspireTG);
+    const bool bGeoBoxesAfter =
+        CPLFetchBool(papszOptions, "GEOBOXES_AFTER_JP2C", bInspireTG);
     GDALJP2Box* poGMLJP2Box = NULL;
     if( eCodecFormat == OPJ_CODEC_JP2 && bGMLJP2Option && bGeoreferencingCompatOfGMLJP2 )
     {
@@ -2754,7 +2792,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         /* Recommendation 38 In the case of an opacity channel, the bit depth should be 1-bit. */
         if( iBand == nAlphaBandIndex &&
             ((pszNBits != NULL && EQUAL(pszNBits, "1")) ||
-              CSLFetchBoolean(papszOptions, "1BIT_ALPHA", bInspireTG)) )
+              CPLFetchBool(papszOptions, "1BIT_ALPHA", bInspireTG)) )
         {
             if( iBand != nBands - 1 && nBits != 1 )
             {
@@ -2877,11 +2915,15 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
 
         GDALJP2Box ftypBox(fp);
         ftypBox.SetType("ftyp");
-        ftypBox.AppendWritableData(4, "jp2 "); /* Branding */
+        // http://docs.opengeospatial.org/is/08-085r5/08-085r5.html Req 19
+        const bool bJPXOption = CPLFetchBool( papszOptions, "JPX", true );
+        if( nGMLJP2Version == 2 && bJPXOption )
+            ftypBox.AppendWritableData(4, "jpx "); /* Branding */
+        else
+            ftypBox.AppendWritableData(4, "jp2 "); /* Branding */
         ftypBox.AppendUInt32(0); /* minimum version */
         ftypBox.AppendWritableData(4, "jp2 "); /* Compatibility list: first value */
 
-        int bJPXOption = CSLFetchBoolean( papszOptions, "JPX", TRUE );
         if( bInspireTG && poGMLJP2Box != NULL && !bJPXOption )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
@@ -2896,8 +2938,9 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         }
         WriteBox(fp, &ftypBox);
 
-        const bool bIPR = poSrcDS->GetMetadata("xml:IPR") != NULL &&
-                   CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE);
+        const bool bIPR =
+            poSrcDS->GetMetadata("xml:IPR") != NULL &&
+            CPLFetchBool(papszOptions, "WRITE_METADATA", false);
 
         /* Reader requirement box */
         if( poGMLJP2Box != NULL && bJPXOption )
@@ -2970,7 +3013,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         if (poCT != NULL)
         {
             pclrBox.SetType("pclr");
-            int nEntries = MIN(256, poCT->GetColorEntryCount());
+            const int nEntries = std::min(256, poCT->GetColorEntryCount());
             nCTComponentCount = atoi(CSLFetchNameValueDef(papszOptions, "CT_COMPONENTS", "0"));
             if( bInspireTG )
             {
@@ -3072,7 +3115,8 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         }
 
         // Add res box if needed
-        double dfXRes = 0, dfYRes = 0;
+        double dfXRes = 0.0;
+        double dfYRes = 0.0;
         int nResUnit = 0;
         GDALJP2Box* poRes = NULL;
         if( poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION") != NULL
@@ -3160,15 +3204,15 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
                 delete poBox;
             }
 
-            if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) &&
-                !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
+            if( CPLFetchBool(papszOptions, "WRITE_METADATA", false) &&
+                !CPLFetchBool(papszOptions, "MAIN_MD_DOMAIN_ONLY", false) )
             {
                 WriteXMPBox(fp, poSrcDS, papszOptions);
             }
 
-            if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
+            if( CPLFetchBool(papszOptions, "WRITE_METADATA", false) )
             {
-                if( !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
+                if( !CPLFetchBool(papszOptions, "MAIN_MD_DOMAIN_ONLY", false) )
                     WriteXMLBoxes(fp, poSrcDS, papszOptions);
                 WriteGDALMetadataBox(fp, poSrcDS, papszOptions);
             }
@@ -3188,7 +3232,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
     vsi_l_offset nCodeStreamLength = 0;
     vsi_l_offset nCodeStreamStart = 0;
     VSILFILE* fpSrc = NULL;
-    if( CSLFetchBoolean(papszOptions, "USE_SRC_CODESTREAM", FALSE) )
+    if( CPLFetchBool(papszOptions, "USE_SRC_CODESTREAM", false) )
     {
         CPLString osSrcFilename( poSrcDS->GetDescription() );
         if( poSrcDS->GetDriver() != NULL &&
@@ -3220,8 +3264,8 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         if( nCodeStreamLength )
             bUseXLBoxes = ((vsi_l_offset)(GUInt32)nCodeStreamLength != nCodeStreamLength);
         else
-            bUseXLBoxes = CSLFetchBoolean(papszOptions, "JP2C_XLBOX", FALSE) || /* For debugging */
-                (GIntBig)nXSize * nYSize * nBands * nDataTypeSize / adfRates[adfRates.size()-1] > 4e9;
+            bUseXLBoxes = CPLFetchBool(papszOptions, "JP2C_XLBOX", false) || /* For debugging */
+                (GIntBig)nXSize * nYSize * nBands * nDataTypeSize / adfRates.back() > 4e9;
         GUInt32 nLBox = (bUseXLBoxes) ? 1 : 0;
         CPL_MSBPTR32(&nLBox);
         VSIFWriteL(&nLBox, 1, 4, fp);
@@ -3258,7 +3302,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         /* coverity[tainted_data] */
         while( nRead < nCodeStreamLength )
         {
-            int nToRead = ( nCodeStreamLength-nRead > 4096 ) ? 4049 :
+            int nToRead = ( nCodeStreamLength-nRead > 4096 ) ? 4096 :
                                         (int)(nCodeStreamLength-nRead);
             if( (int)VSIFReadL(abyBuffer, 1, nToRead, fpSrc) != nToRead )
             {
@@ -3302,11 +3346,10 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
     }
     else
     {
-        opj_stream_t * pStream;
         JP2OpenJPEGFile sJP2OpenJPEGFile;
         sJP2OpenJPEGFile.fp = fp;
         sJP2OpenJPEGFile.nBaseOffset = VSIFTellL(fp);
-        pStream = opj_stream_create(1024*1024, FALSE);
+        opj_stream_t * pStream = opj_stream_create(1024*1024, FALSE);
         opj_stream_set_write_function(pStream, JP2OpenJPEGDataset_Write);
         opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
         opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
@@ -3332,7 +3375,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         int nTilesY = (nYSize + nBlockYSize - 1) / nBlockYSize;
 
         GUIntBig nTileSize = (GUIntBig)nBlockXSize * nBlockYSize * nBands * nDataTypeSize;
-        GByte* pTempBuffer;
+        GByte* pTempBuffer = NULL;
         if( nTileSize > UINT_MAX )
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Tile size exceeds 4GB");
@@ -3381,8 +3424,10 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         {
             for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nTilesX;nBlockXOff++)
             {
-                int nWidthToRead = MIN(nBlockXSize, nXSize - nBlockXOff * nBlockXSize);
-                int nHeightToRead = MIN(nBlockYSize, nYSize - nBlockYOff * nBlockYSize);
+                const int nWidthToRead =
+                    std::min(nBlockXSize, nXSize - nBlockXOff * nBlockXSize);
+                const int nHeightToRead =
+                    std::min(nBlockYSize, nYSize - nBlockYOff * nBlockYSize);
                 eErr = poSrcDS->RasterIO(GF_Read,
                                         nBlockXOff * nBlockXSize,
                                         nBlockYOff * nBlockYSize,
@@ -3498,7 +3543,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
 /*      Patch JP2C box length and add trailing JP2 boxes                */
 /* -------------------------------------------------------------------- */
     if( eCodecFormat == OPJ_CODEC_JP2 &&
-        !CSLFetchBoolean(papszOptions, "JP2C_LENGTH_ZERO", FALSE) /* debug option */ )
+        !CPLFetchBool(papszOptions, "JP2C_LENGTH_ZERO", false) /* debug option */ )
     {
         vsi_l_offset nEndJP2C = VSIFTellL(fp);
         GUIntBig nBoxSize = nEndJP2C -nStartJP2C;
@@ -3532,7 +3577,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         }
         VSIFSeekL(fp, 0, SEEK_END);
 
-        if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
+        if( CPLFetchBool(papszOptions, "WRITE_METADATA", false) )
         {
             WriteIPRBox(fp, poSrcDS, papszOptions);
         }
@@ -3544,9 +3589,9 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
                 WriteBox(fp, poGMLJP2Box);
             }
 
-            if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
+            if( CPLFetchBool(papszOptions, "WRITE_METADATA", false) )
             {
-                if( !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
+                if( !CPLFetchBool(papszOptions, "MAIN_MD_DOMAIN_ONLY", false) )
                     WriteXMLBoxes(fp, poSrcDS, papszOptions);
                 WriteGDALMetadataBox(fp, poSrcDS, papszOptions);
             }
@@ -3558,8 +3603,8 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
                 delete poBox;
             }
 
-            if( CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) &&
-                !CSLFetchBoolean(papszOptions, "MAIN_MD_DOMAIN_ONLY", FALSE) )
+            if( CPLFetchBool(papszOptions, "WRITE_METADATA", false) &&
+                !CPLFetchBool(papszOptions, "MAIN_MD_DOMAIN_ONLY", false) )
             {
                 WriteXMPBox(fp, poSrcDS, papszOptions);
             }
@@ -3581,7 +3626,7 @@ GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT & (~GCIF_METADATA) );
 
         /* Only write relevant metadata to PAM, and if needed */
-        if( !CSLFetchBoolean(papszOptions, "WRITE_METADATA", FALSE) )
+        if( !CPLFetchBool(papszOptions, "WRITE_METADATA", false) )
         {
             char** papszSrcMD = CSLDuplicate(poSrcDS->GetMetadata());
             papszSrcMD = CSLSetNameValue(papszSrcMD, GDALMD_AREA_OR_POINT, NULL);
@@ -3646,6 +3691,8 @@ void GDALRegister_JP2OpenJPEG()
 "<OpenOptionList>"
 "   <Option name='1BIT_ALPHA_PROMOTION' type='boolean' description='Whether a 1-bit alpha channel should be promoted to 8-bit' default='YES'/>"
 "   <Option name='OPEN_REMOTE_GML' type='boolean' description='Whether to load remote vector layers referenced by a link in a GMLJP2 v2 box' default='NO'/>"
+"   <Option name='GEOREF_SOURCES' type='string' description='Comma separated list made with values INTERNAL/GMLJP2/GEOJP2/WORLDFILE/PAM/NONE that describe the priority order for georeferencing' default='PAM,GEOJP2,GMLJP2,WORLDFILE'/>"
+"   <Option name='USE_TILE_AS_BLOCK' type='boolean' description='Whether to always use the JPEG-2000 block size as the GDAL block size' default='NO'/>"
 "</OpenOptionList>" );
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
@@ -3682,7 +3729,7 @@ void GDALRegister_JP2OpenJPEG()
 "       <Value>PROFILE_1</Value>"
 "   </Option>"
 "   <Option name='INSPIRE_TG' type='boolean' description='Whether to use features that comply with Inspire Orthoimagery Technical Guidelines' default='NO'/>"
-"   <Option name='JPX' type='boolean' description='Whether to advertize JPX features when a GMLJP2 box is written' default='YES'/>"
+"   <Option name='JPX' type='boolean' description='Whether to advertize JPX features when a GMLJP2 box is written (or use JPX branding if GMLJP2 v2)' default='YES'/>"
 "   <Option name='GEOBOXES_AFTER_JP2C' type='boolean' description='Whether to place GeoJP2/GMLJP2 boxes after the code-stream' default='NO'/>"
 "   <Option name='PRECINCTS' type='string' description='Precincts size as a string of the form {w,h},{w,h},... with power-of-two values'/>"
 "   <Option name='TILEPARTS' type='string-select' description='Whether to generate tile-parts and according to which criterion' default='DISABLED'>"
diff --git a/frmts/ozi/makefile.vc b/frmts/ozi/makefile.vc
index 633fd14..abd4caa 100644
--- a/frmts/ozi/makefile.vc
+++ b/frmts/ozi/makefile.vc
@@ -5,7 +5,11 @@ GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS      =        -I..\zlib
+!IFDEF ZLIB_EXTERNAL_LIB
+EXTRAFLAGS = $(ZLIB_INC)
+!ELSE
+EXTRAFLAGS = -I..\zlib
+!ENDIF
 
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\o
diff --git a/frmts/ozi/ozidataset.cpp b/frmts/ozi/ozidataset.cpp
index e0cd02e..15eec7d 100644
--- a/frmts/ozi/ozidataset.cpp
+++ b/frmts/ozi/ozidataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ozidataset.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:   OZF2 and OZFx3 binary files driver
  * Purpose:  GDALDataset driver for OZF2 and OZFx3 binary files.
@@ -33,7 +32,7 @@
 
 /* g++ -fPIC -g -Wall frmts/ozi/ozidataset.cpp -shared -o gdal_OZI.so -Iport -Igcore -Iogr -L. -lgdal  */
 
-CPL_CVSID("$Id: ozidataset.cpp 33105 2016-01-23 15:27:32Z rouault $");
+CPL_CVSID("$Id: ozidataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -87,15 +86,14 @@ class OZIRasterBand : public GDALPamRasterBand
                                GDALColorTable* poColorTable);
     virtual    ~OZIRasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
 
-    virtual int         GetOverviewCount();
-    virtual GDALRasterBand* GetOverview(int nLevel);
+    virtual int         GetOverviewCount() override;
+    virtual GDALRasterBand* GetOverview(int nLevel) override;
 };
 
-
 /************************************************************************/
 /*                             I/O functions                            */
 /************************************************************************/
@@ -135,7 +133,7 @@ static short ReadShort(GByte**pptr)
     return nVal;
 }
 
-static int ReadInt(VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0)
+static int ReadInt( VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0 )
 {
     int nVal;
     VSIFReadL(&nVal, 1, 4, fp);
@@ -145,7 +143,7 @@ static int ReadInt(VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0)
     return nVal;
 }
 
-static short ReadShort(VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0)
+static short ReadShort( VSILFILE* fp, int bOzi3 = FALSE, int nKeyInit = 0 )
 {
     short nVal;
     VSIFReadL(&nVal, 1, 2, fp);
@@ -163,21 +161,21 @@ OZIRasterBand::OZIRasterBand( OZIDataset *poDSIn, int nZoomLevelIn,
                               int nRasterXSizeIn, int nRasterYSizeIn,
                               int nXBlocksIn,
                               GDALColorTable* poColorTableIn ) :
+    nXBlocks(nXBlocksIn),
+    nZoomLevel(nZoomLevelIn),
+    poColorTable(poColorTableIn),
     pabyTranslationTable(NULL)
 {
-    this->poDS = poDSIn;
-    this->nBand = 1;
+    poDS = poDSIn;
+    nBand = 1;
 
     eDataType = GDT_Byte;
 
     nBlockXSize = 64;
     nBlockYSize = 64;
 
-    this->nZoomLevel = nZoomLevelIn;
-    this->nRasterXSize = nRasterXSizeIn;
-    this->nRasterYSize = nRasterYSizeIn;
-    this->poColorTable = poColorTableIn;
-    this->nXBlocks = nXBlocksIn;
+    nRasterXSize = nRasterXSizeIn;
+    nRasterYSize = nRasterYSizeIn;
 }
 
 /************************************************************************/
@@ -190,7 +188,6 @@ OZIRasterBand::~OZIRasterBand()
     CPLFree(pabyTranslationTable);
 }
 
-
 /************************************************************************/
 /*                        GetColorInterpretation()                      */
 /************************************************************************/
@@ -648,7 +645,6 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->papoOvrBands[i]->poColorTable = poDS->papoOvrBands[0]->poColorTable->Clone();
             poDS->papoOvrBands[i]->pabyTranslationTable = pabyTranslationTable;
         }
-
     }
 
     poDS->SetBand(1, poDS->papoOvrBands[0]);
@@ -663,7 +659,7 @@ GDALDataset *OZIDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Support overviews.                                              */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/pcidsk/GNUmakefile b/frmts/pcidsk/GNUmakefile
index 86fa289..c409239 100644
--- a/frmts/pcidsk/GNUmakefile
+++ b/frmts/pcidsk/GNUmakefile
@@ -54,7 +54,7 @@ SDKOBJ 	=	\
 	cpcidskbinarysegment.o \
 	cpcidsk_array.o \
 	cpcidskephemerissegment.o \
-	cpcidskads40model.o 
+	cpcidskads40model.o
 
 else
 CPPFLAGS	:=	 $(PCIDSK_INCLUDE) $(CPPFLAGS)
diff --git a/frmts/pcidsk/gdal_edb.cpp b/frmts/pcidsk/gdal_edb.cpp
index 012d1f0..a71849f 100644
--- a/frmts/pcidsk/gdal_edb.cpp
+++ b/frmts/pcidsk/gdal_edb.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_edb.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PCIDSK Database File
  * Purpose:  External Database access interface implementation (EDBFile).
@@ -32,7 +31,7 @@
 #include "gdal_priv.h"
 #include "pcidsk.h"
 
-CPL_CVSID("$Id: gdal_edb.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: gdal_edb.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 using PCIDSK::EDBFile;
 using PCIDSK::eChanType;
@@ -44,7 +43,7 @@ using PCIDSK::CHN_32R;
 using PCIDSK::CHN_C16S;
 using PCIDSK::CHN_UNKNOWN;
 
-EDBFile *GDAL_EDBOpen( std::string osFilename, std::string osAccess );
+EDBFile *GDAL_EDBOpen( const std::string& osFilename, const std::string& osAccess );
 
 /************************************************************************/
 /* ==================================================================== */
@@ -61,28 +60,28 @@ public:
     explicit GDAL_EDBFile( GDALDataset *poDSIn ) { poDS = poDSIn; }
     ~GDAL_EDBFile() { if( poDS ) Close(); }
 
-    int Close() const;
-    int GetWidth() const;
-    int GetHeight() const;
-    int GetChannels() const;
-    int GetBlockWidth(int channel ) const;
-    int GetBlockHeight(int channel ) const;
-    eChanType GetType(int channel ) const;
+    int Close() const override;
+    int GetWidth() const override;
+    int GetHeight() const override;
+    int GetChannels() const override;
+    int GetBlockWidth(int channel ) const override;
+    int GetBlockHeight(int channel ) const override;
+    eChanType GetType(int channel ) const override;
     int ReadBlock(int channel,
                   int block_index, void *buffer,
                   int win_xoff, int win_yoff,
-                  int win_xsize, int win_ysize );
-    int WriteBlock( int channel, int block_index, void *buffer);
+                  int win_xsize, int win_ysize ) override;
+    int WriteBlock( int channel, int block_index, void *buffer) override;
 };
 
 /************************************************************************/
 /*                            GDAL_EDBOpen()                            */
 /************************************************************************/
 
-EDBFile *GDAL_EDBOpen( std::string osFilename, std::string osAccess )
+EDBFile *GDAL_EDBOpen( const std::string& osFilename, const std::string& osAccess )
 
 {
-    GDALDataset *poDS;
+    GDALDataset *poDS = NULL;
 
     if( osAccess == "r" )
         poDS = reinterpret_cast<GDALDataset *>( GDALOpen( osFilename.c_str(), GA_ReadOnly )) ;
diff --git a/frmts/pcidsk/notes.txt b/frmts/pcidsk/notes.txt
index ddcdbad..1328839 100644
--- a/frmts/pcidsk/notes.txt
+++ b/frmts/pcidsk/notes.txt
@@ -9,7 +9,7 @@ SysBMap:
 block map entries:
   - each is 28 bytes
   - 4 bytes for SysBData Segment - often 1023.
-  - 8 bytes for absolute block index (zero based, within SysBData). 
+  - 8 bytes for absolute block index (zero based, within SysBData).
   - 8 bytes for "image" number (-1 means unallocated)
   - 8 bytes for the next absolute block in this images block chain
     (-1 means end of chain)
@@ -28,17 +28,17 @@ Virtual tiled images:
  - 8 bytes: image width
  - 8 bytes: image height
  - 8 bytes: tile width
- - 8 bytes: tile height 
- - 3 bytes: tile pixel data type. 
+ - 8 bytes: tile height
+ - 3 bytes: tile pixel data type.
  - some spaces
  - compression type (normally NONE)
  - some spaces.
 
 Tilemap:
- - 12 bytes per tile containing offset within virtual file. 
+ - 12 bytes per tile containing offset within virtual file.
 
 Tile Size map:
- - 8 bytes per tile containing size of tile data. 
+ - 8 bytes per tile containing size of tile data.
 
 Tile Data:
- - Absolute data. 
+ - Absolute data.
diff --git a/frmts/pcidsk/ogrpcidsklayer.cpp b/frmts/pcidsk/ogrpcidsklayer.cpp
index a7515d7..ad8bfc1 100644
--- a/frmts/pcidsk/ogrpcidsklayer.cpp
+++ b/frmts/pcidsk/ogrpcidsklayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcsvlayer.cpp 17496 2009-08-02 11:54:23Z rouault $
  *
  * Project:  PCIDSK Translator
  * Purpose:  Implements OGRPCIDSKLayer class.
@@ -30,7 +29,9 @@
 
 #include "pcidskdataset2.h"
 
-CPL_CVSID("$Id$");
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrpcidsklayer.cpp 36353 2016-11-20 22:37:22Z rouault $");
 
 /************************************************************************/
 /*                           OGRPCIDSKLayer()                           */
@@ -68,7 +69,6 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
             poFeatureDefn->SetGeomType( wkbNone );
     } catch(...) {}
 
-
 /* -------------------------------------------------------------------- */
 /*      Build field definitions.                                        */
 /* -------------------------------------------------------------------- */
@@ -100,7 +100,7 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
                 break;
 
               default:
-                CPLAssert( FALSE );
+                CPLAssert( false );
                 break;
             }
 
@@ -151,7 +151,7 @@ OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn,
 /* -------------------------------------------------------------------- */
 /*      Trap pcidsk exceptions.                                         */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSK::PCIDSKException ex )
+    catch( const PCIDSK::PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "PCIDSK Exception while initializing layer, operation likely impaired.\n%s", ex.what() );
@@ -426,7 +426,7 @@ OGRFeature *OGRPCIDSKLayer::GetFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions and report as CPL errors.                       */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSK::PCIDSKException ex )
+    catch( const PCIDSK::PCIDSKException& ex )
     {
         delete poFeature;
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -521,16 +521,18 @@ OGRErr OGRPCIDSKLayer::GetExtent (OGREnvelope *psExtent, int bForce)
             {
                 if( !bHaveExtent )
                 {
-                    psExtent->MinX = psExtent->MaxX = asVertices[i].x;
-                    psExtent->MinY = psExtent->MaxY = asVertices[i].y;
+                    psExtent->MinX = asVertices[i].x;
+                    psExtent->MaxX = asVertices[i].x;
+                    psExtent->MinY = asVertices[i].y;
+                    psExtent->MaxY = asVertices[i].y;
                     bHaveExtent = true;
                 }
                 else
                 {
-                    psExtent->MinX = MIN(psExtent->MinX,asVertices[i].x);
-                    psExtent->MaxX = MAX(psExtent->MaxX,asVertices[i].x);
-                    psExtent->MinY = MIN(psExtent->MinY,asVertices[i].y);
-                    psExtent->MaxY = MAX(psExtent->MaxY,asVertices[i].y);
+                    psExtent->MinX = std::min(psExtent->MinX, asVertices[i].x);
+                    psExtent->MaxX = std::max(psExtent->MaxX, asVertices[i].x);
+                    psExtent->MinY = std::min(psExtent->MinY, asVertices[i].y);
+                    psExtent->MaxY = std::max(psExtent->MaxY, asVertices[i].y);
                 }
             }
         }
@@ -544,7 +546,7 @@ OGRErr OGRPCIDSKLayer::GetExtent (OGREnvelope *psExtent, int bForce)
 /* -------------------------------------------------------------------- */
 /*      Trap pcidsk exceptions.                                         */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSK::PCIDSKException ex )
+    catch( const PCIDSK::PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "PCIDSK Exception while initializing layer, operation likely impaired.\n%s", ex.what() );
@@ -574,7 +576,7 @@ OGRErr OGRPCIDSKLayer::DeleteFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions and report as CPL errors.                       */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSK::PCIDSKException ex )
+    catch( const PCIDSK::PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -606,7 +608,7 @@ OGRErr OGRPCIDSKLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions and report as CPL errors.                       */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSK::PCIDSKException ex )
+    catch( const PCIDSK::PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -681,7 +683,7 @@ OGRErr OGRPCIDSKLayer::ISetFeature( OGRFeature *poFeature )
               break;
 
               default:
-                CPLAssert( FALSE );
+                CPLAssert( false );
                 break;
             }
         }
@@ -732,13 +734,12 @@ OGRErr OGRPCIDSKLayer::ISetFeature( OGRFeature *poFeature )
         }
 
         poVecSeg->SetVertices( id, aoVertices );
-
     } /* try */
 
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions and report as CPL errors.                       */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSK::PCIDSKException ex )
+    catch( const PCIDSK::PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
@@ -812,7 +813,7 @@ OGRErr OGRPCIDSKLayer::CreateField( OGRFieldDefn *poFieldDefn,
 /* -------------------------------------------------------------------- */
 /*      Trap exceptions and report as CPL errors.                       */
 /* -------------------------------------------------------------------- */
-    catch( PCIDSK::PCIDSKException ex )
+    catch( const PCIDSK::PCIDSKException& ex )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "%s", ex.what() );
diff --git a/frmts/pcidsk/pcidskdataset2.cpp b/frmts/pcidsk/pcidskdataset2.cpp
index fe6f88d..16a5ee4 100644
--- a/frmts/pcidsk/pcidskdataset2.cpp
+++ b/frmts/pcidsk/pcidskdataset2.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pcidskdataset2.cpp 37163 2017-01-17 08:11:27Z rouault $
  *
  * Project:  PCIDSK Database File
  * Purpose:  Read/write PCIDSK Database File used by the PCI software, using
@@ -32,7 +31,9 @@
 #include "gdal_frmts.h"
 #include "pcidskdataset2.h"
 
-CPL_CVSID("$Id: pcidskdataset2.cpp 37163 2017-01-17 08:11:27Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: pcidskdataset2.cpp 37162 2017-01-17 08:11:16Z rouault $");
 
 const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces(void);
 
@@ -137,9 +138,9 @@ void PCIDSK2Band::Initialize()
 PCIDSK2Band::~PCIDSK2Band()
 
 {
-    while( apoOverviews.size() > 0 )
+    while( !apoOverviews.empty() )
     {
-        delete apoOverviews[apoOverviews.size()-1];
+        delete apoOverviews.back();
         apoOverviews.pop_back();
     }
     CSLDestroy( papszLastMDListValue );
@@ -270,7 +271,7 @@ bool PCIDSK2Band::CheckForColorTable()
 
         // If there is no metadata, assume a single PCT in a file with only
         // one raster band must be intended for it.
-        if( osDefaultPCT.size() == 0
+        if( osDefaultPCT.empty()
             && poDS != NULL
             && poDS->GetRasterCount() == 1 )
         {
@@ -281,7 +282,7 @@ bool PCIDSK2Band::CheckForColorTable()
                 poPCTSeg = NULL;
         }
         // Parse default PCT ref assuming an in file reference.
-        else if( osDefaultPCT.size() != 0
+        else if( !osDefaultPCT.empty()
                  && strstr(osDefaultPCT.c_str(),"PCT:") != NULL )
         {
             poPCTSeg = poFile->GetSegment(
@@ -447,7 +448,7 @@ CPLErr PCIDSK2Band::SetColorTable( GDALColorTable *poCT )
 /* -------------------------------------------------------------------- */
 /*      Write out the PCT.                                              */
 /* -------------------------------------------------------------------- */
-        const int nColorCount = MIN(256,poCT->GetColorEntryCount());
+        const int nColorCount = std::min(256, poCT->GetColorEntryCount());
 
         unsigned char abyPCT[768];
         memset( abyPCT, 0, 768 );
@@ -509,9 +510,9 @@ void PCIDSK2Band::RefreshOverviewList()
 /* -------------------------------------------------------------------- */
 /*      Clear existing overviews.                                       */
 /* -------------------------------------------------------------------- */
-    while( apoOverviews.size() > 0 )
+    while( !apoOverviews.empty() )
     {
-        delete apoOverviews[apoOverviews.size()-1];
+        delete apoOverviews.back();
         apoOverviews.pop_back();
     }
 
@@ -590,7 +591,7 @@ CPLErr PCIDSK2Band::IWriteBlock( int iBlockX, int iBlockY, void *pData )
 int PCIDSK2Band::GetOverviewCount()
 
 {
-    if( apoOverviews.size() > 0 )
+    if( !apoOverviews.empty() )
         return static_cast<int>( apoOverviews.size() );
 
     return GDALPamRasterBand::GetOverviewCount();
@@ -825,7 +826,7 @@ PCIDSK2Dataset::~PCIDSK2Dataset()
 {
     FlushCache();
 
-    while( apoLayers.size() > 0 )
+    while( !apoLayers.empty() )
     {
         delete apoLayers.back();
         apoLayers.pop_back();
@@ -1178,7 +1179,6 @@ const char *PCIDSK2Dataset::GetMetadataItem( const char *pszName,
         return NULL;
     }
 
-
     if( osLastMDValue == "" )
         return NULL;
 
@@ -1829,7 +1829,7 @@ GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
 /*      Create band objects for bitmap segments.                        */
 /* -------------------------------------------------------------------- */
         int nLastBitmapSegment = 0;
-        PCIDSKSegment *poBitSeg;
+        PCIDSKSegment *poBitSeg = NULL;
 
         while( (poBitSeg = poFile->GetSegment( SEG_BIT, "",
                                                nLastBitmapSegment)) != NULL )
@@ -1881,7 +1881,7 @@ GDALDataset *PCIDSK2Dataset::LLOpen( const char *pszFilename,
 /* -------------------------------------------------------------------- */
         poDS->oOvManager.Initialize( poDS, pszFilename, papszSiblingFiles );
 
-        return( poDS );
+        return poDS;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1922,17 +1922,17 @@ GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
     std::vector<eChanType> aeChanTypes;
 
     if( eType == GDT_Float32 )
-        aeChanTypes.resize( MAX(1,nBands), CHN_32R );
+      aeChanTypes.resize( std::max(1, nBands), CHN_32R );
     else if( eType == GDT_Int16 )
-        aeChanTypes.resize( MAX(1,nBands), CHN_16S );
+        aeChanTypes.resize( std::max(1, nBands), CHN_16S );
     else if( eType == GDT_UInt16 )
-        aeChanTypes.resize( MAX(1,nBands), CHN_16U );
+        aeChanTypes.resize( std::max(1, nBands), CHN_16U );
     else if( eType == GDT_CInt16 )
-        aeChanTypes.resize( MAX(1, nBands), CHN_C16S );
+        aeChanTypes.resize( std::max(1, nBands), CHN_C16S );
     else if( eType == GDT_CFloat32 )
-        aeChanTypes.resize( MAX(1, nBands), CHN_C32R );
+        aeChanTypes.resize( std::max(1, nBands), CHN_C32R );
     else
-        aeChanTypes.resize( MAX(1,nBands), CHN_8U );
+        aeChanTypes.resize( std::max(1, nBands), CHN_8U );
 
 /* -------------------------------------------------------------------- */
 /*      Reformat options.  Currently no support for jpeg compression    */
@@ -1965,7 +1965,10 @@ GDALDataset *PCIDSK2Dataset::Create( const char * pszFilename,
 
     try {
         if( nBands == 0 )
-            nXSize = nYSize = 512;
+        {
+            nXSize = 512;
+            nYSize = 512;
+        }
         PCIDSKFile *poFile = PCIDSK::Create( pszFilename, nXSize, nYSize, nBands,
                                              &(aeChanTypes[0]), osOptions,
                                              PCIDSK2GetInterfaces() );
@@ -2016,6 +2019,8 @@ int PCIDSK2Dataset::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return eAccess == GA_Update;
+    if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return eAccess == GA_Update;
 
     return FALSE;
 }
@@ -2150,7 +2155,7 @@ PCIDSK2Dataset::ICreateLayer( const char * pszLayerName,
 
     apoLayers.push_back( new OGRPCIDSKLayer( poSeg, poVecSeg, TRUE ) );
 
-    return apoLayers[apoLayers.size()-1];
+    return apoLayers.back();
 }
 
 /************************************************************************/
diff --git a/frmts/pcidsk/pcidskdataset2.h b/frmts/pcidsk/pcidskdataset2.h
index d88f440..fd00b55 100644
--- a/frmts/pcidsk/pcidskdataset2.h
+++ b/frmts/pcidsk/pcidskdataset2.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: pcidskdataset2.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  PCIDSK Database File
  * Purpose:  Read/write PCIDSK Database File used by the PCI software, using
@@ -67,7 +67,7 @@ class PCIDSK2Dataset : public GDALPamDataset
 
   public:
                 PCIDSK2Dataset();
-                ~PCIDSK2Dataset();
+    virtual ~PCIDSK2Dataset();
 
     static int           Identify( GDALOpenInfo * );
     static GDALDataset  *Open( GDALOpenInfo * );
@@ -79,30 +79,30 @@ class PCIDSK2Dataset : public GDALPamDataset
                                  GDALDataType eType,
                                  char **papszParmList );
 
-    char              **GetFileList(void);
-    CPLErr              GetGeoTransform( double * padfTransform );
-    CPLErr              SetGeoTransform( double * );
-    const char         *GetProjectionRef();
-    CPLErr              SetProjection( const char * );
+    char              **GetFileList() override;
+    CPLErr              GetGeoTransform( double * padfTransform ) override;
+    CPLErr              SetGeoTransform( double * ) override;
+    const char         *GetProjectionRef() override;
+    CPLErr              SetProjection( const char * ) override;
 
-    virtual char      **GetMetadataDomainList();
-    CPLErr              SetMetadata( char **, const char * );
-    char              **GetMetadata( const char* );
-    CPLErr              SetMetadataItem(const char*,const char*,const char*);
-    const char         *GetMetadataItem( const char*, const char*);
+    virtual char      **GetMetadataDomainList() override;
+    CPLErr              SetMetadata( char **, const char * ) override;
+    char              **GetMetadata( const char* ) override;
+    CPLErr              SetMetadataItem(const char*,const char*,const char*) override;
+    const char         *GetMetadataItem( const char*, const char*) override;
 
-    virtual void FlushCache(void);
+    virtual void FlushCache() override;
 
     virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
+                                    int, int *, GDALProgressFunc, void * ) override;
 
-    virtual int                 GetLayerCount() { return (int) apoLayers.size(); }
-    virtual OGRLayer            *GetLayer( int );
+    virtual int                 GetLayerCount() override { return (int) apoLayers.size(); }
+    virtual OGRLayer            *GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     virtual OGRLayer           *ICreateLayer( const char *, OGRSpatialReference *,
-                                     OGRwkbGeometryType, char ** );
+                                     OGRwkbGeometryType, char ** ) override;
 };
 
 /************************************************************************/
@@ -133,28 +133,28 @@ class PCIDSK2Band : public GDALPamRasterBand
 
   public:
                 PCIDSK2Band( PCIDSK2Dataset *, PCIDSK::PCIDSKFile *, int );
-                PCIDSK2Band( PCIDSK::PCIDSKChannel * );
-                ~PCIDSK2Band();
+    explicit    PCIDSK2Band( PCIDSK::PCIDSKChannel * );
+    virtual ~PCIDSK2Band();
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 
-    virtual int        GetOverviewCount();
-    virtual GDALRasterBand *GetOverview(int);
+    virtual int        GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview(int) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual CPLErr SetColorTable( GDALColorTable * );
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual CPLErr SetColorTable( GDALColorTable * ) override;
 
-    virtual void        SetDescription( const char * );
+    virtual void        SetDescription( const char * ) override;
 
-    virtual char      **GetMetadataDomainList();
-    CPLErr              SetMetadata( char **, const char * );
-    char              **GetMetadata( const char* );
-    CPLErr              SetMetadataItem(const char*,const char*,const char*);
-    const char         *GetMetadataItem( const char*, const char*);
+    virtual char      **GetMetadataDomainList() override;
+    CPLErr              SetMetadata( char **, const char * ) override;
+    char              **GetMetadata( const char* ) override;
+    CPLErr              SetMetadataItem(const char*,const char*,const char*) override;
+    const char         *GetMetadataItem( const char*, const char*) override;
 
-    virtual char      **GetCategoryNames();
+    virtual char      **GetCategoryNames() override;
 };
 
 /************************************************************************/
@@ -179,25 +179,25 @@ class OGRPCIDSKLayer : public OGRLayer
 
   public:
     OGRPCIDSKLayer( PCIDSK::PCIDSKSegment*, PCIDSK::PCIDSKVectorSegment *, bool bUpdate );
-    ~OGRPCIDSKLayer();
+    virtual ~OGRPCIDSKLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
-    OGRFeature         *GetFeature( GIntBig nFeatureId );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
-    OGRErr              DeleteFeature( GIntBig nFID );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    OGRErr              DeleteFeature( GIntBig nFID ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
-    GIntBig             GetFeatureCount( int );
-    OGRErr              GetExtent( OGREnvelope *psExtent, int bForce );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    GIntBig             GetFeatureCount( int ) override;
+    OGRErr              GetExtent( OGREnvelope *psExtent, int bForce ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
diff --git a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h
index 98af6b0..f09a1de 100644
--- a/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h
+++ b/frmts/pcidsk/sdk/channel/cbandinterleavedchannel.h
@@ -61,15 +61,15 @@ namespace PCIDSK
 
         virtual int ReadBlock( int block_index, void *buffer,
             int xoff=-1, int yoff=-1,
-            int xsize=-1, int ysize=-1 );
-        virtual int WriteBlock( int block_index, void *buffer );
+            int xsize=-1, int ysize=-1 ) override;
+        virtual int WriteBlock( int block_index, void *buffer ) override;
 
         virtual void GetChanInfo( std::string &filename, uint64 &image_offset, 
                                   uint64 &pixel_offset, uint64 &line_offset, 
-                                  bool &little_endian ) const;
+                                  bool &little_endian ) const override;
         virtual void SetChanInfo( std::string filename, uint64 image_offset, 
                                   uint64 pixel_offset, uint64 line_offset, 
-                                  bool little_endian );
+                                  bool little_endian ) override;
 
     private:
     // raw file layout - internal or external
diff --git a/frmts/pcidsk/sdk/channel/cexternalchannel.cpp b/frmts/pcidsk/sdk/channel/cexternalchannel.cpp
index 996139b..a44a03d 100644
--- a/frmts/pcidsk/sdk/channel/cexternalchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/cexternalchannel.cpp
@@ -186,7 +186,7 @@ int CExternalChannel::ReadBlock( int block_index, void *buffer,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Do a direct call for the simpliest case of 1:1 block mapping.   */
+/*      Do a direct call for the simplest case of 1:1 block mapping.   */
 /* -------------------------------------------------------------------- */
     if( exoff == 0 && eyoff == 0 
         && exsize == db->GetWidth()
diff --git a/frmts/pcidsk/sdk/channel/cexternalchannel.h b/frmts/pcidsk/sdk/channel/cexternalchannel.h
index d7d8f7a..325c736 100644
--- a/frmts/pcidsk/sdk/channel/cexternalchannel.h
+++ b/frmts/pcidsk/sdk/channel/cexternalchannel.h
@@ -58,19 +58,19 @@ namespace PCIDSK
             eChanType pixel_type );
         virtual ~CExternalChannel();
 
-        virtual int GetBlockWidth() const;
-        virtual int GetBlockHeight() const;
+        virtual int GetBlockWidth() const override;
+        virtual int GetBlockHeight() const override;
         virtual int ReadBlock( int block_index, void *buffer,
             int xoff=-1, int yoff=-1,
-            int xsize=-1, int ysize=-1 );
-        virtual int WriteBlock( int block_index, void *buffer );
+            int xsize=-1, int ysize=-1 ) override;
+        virtual int WriteBlock( int block_index, void *buffer ) override;
 
         virtual void GetEChanInfo( std::string &filename, int &echannel,
                                    int &exoff, int &eyoff, 
-                                   int &exsize, int &eysize ) const;
+                                   int &exsize, int &eysize ) const override;
         virtual void SetEChanInfo( std::string filename, int echannel,
                                    int exoff, int eyoff, 
-                                   int exsize, int eysize );
+                                   int exsize, int eysize ) override;
     private:
         int      exoff;
         int      eyoff;
diff --git a/frmts/pcidsk/sdk/channel/cpcidskchannel.h b/frmts/pcidsk/sdk/channel/cpcidskchannel.h
index 754c949..f1ee5f9 100644
--- a/frmts/pcidsk/sdk/channel/cpcidskchannel.h
+++ b/frmts/pcidsk/sdk/channel/cpcidskchannel.h
@@ -58,52 +58,52 @@ namespace PCIDSK
             int channel_number );
         virtual   ~CPCIDSKChannel();
 
-        virtual int GetBlockWidth() const { return block_width; }
-        virtual int GetBlockHeight() const { return block_height; }
-        virtual int GetBlockCount() const;
+        virtual int GetBlockWidth() const override { return block_width; }
+        virtual int GetBlockHeight() const override { return block_height; }
+        virtual int GetBlockCount() const override;
 
-        virtual int GetWidth() const { return width; }
-        virtual int GetHeight() const { return height; }
-        virtual eChanType GetType() const { return pixel_type; }
+        virtual int GetWidth() const override { return width; }
+        virtual int GetHeight() const override { return height; }
+        virtual eChanType GetType() const override { return pixel_type; }
 
-        int       GetOverviewCount();
-        PCIDSKChannel  *GetOverview( int i );
-        bool IsOverviewValid( int i );
-        void SetOverviewValidity( int i, bool validity );
-        std::string GetOverviewResampling( int i );
-        std::vector<int> GetOverviewLevelMapping() const;
+        int       GetOverviewCount() override;
+        PCIDSKChannel  *GetOverview( int i ) override;
+        bool IsOverviewValid( int i ) override;
+        void SetOverviewValidity( int i, bool validity ) override;
+        std::string GetOverviewResampling( int i ) override;
+        std::vector<int> GetOverviewLevelMapping() const override;
 
         int         GetChannelNumber() { return channel_number; }
 
-        std::string GetMetadataValue( const std::string &key ) const 
+        std::string GetMetadataValue( const std::string &key ) const override 
             { return metadata.GetMetadataValue(key); }
-        void        SetMetadataValue( const std::string &key, const std::string &value ) 
+        void        SetMetadataValue( const std::string &key, const std::string &value ) override 
             { metadata.SetMetadataValue(key,value); }
-        std::vector<std::string> GetMetadataKeys() const
+        std::vector<std::string> GetMetadataKeys() const override
             { return metadata.GetMetadataKeys(); }
 
-        virtual void Synchronize() {}
+        virtual void Synchronize() override {}
 
-        std::string GetDescription();
-        void SetDescription( const std::string &description );
+        std::string GetDescription() override;
+        void SetDescription( const std::string &description ) override;
 
-        virtual std::vector<std::string> GetHistoryEntries() const;
-        virtual void SetHistoryEntries( const std::vector<std::string> &entries );
+        virtual std::vector<std::string> GetHistoryEntries() const override;
+        virtual void SetHistoryEntries( const std::vector<std::string> &entries ) override;
         virtual void PushHistory(const std::string &app,
-                                 const std::string &message);
+                                 const std::string &message) override;
 
         virtual void GetChanInfo( std::string &filename, uint64 &image_offset, 
                                   uint64 &pixel_offset, uint64 &line_offset, 
-                                  bool &little_endian ) const;
+                                  bool &little_endian ) const override;
         virtual void SetChanInfo( std::string filename, uint64 image_offset, 
                                   uint64 pixel_offset, uint64 line_offset, 
-                                  bool little_endian );
+                                  bool little_endian ) override;
         virtual void GetEChanInfo( std::string &filename, int &echannel,
                                    int &exoff, int &eyoff, 
-                                   int &exsize, int &eysize ) const;
+                                   int &exsize, int &eysize ) const override;
         virtual void SetEChanInfo( std::string filename, int echannel,
                                    int exoff, int eyoff, 
-                                   int exsize, int eysize );
+                                   int exsize, int eysize ) override;
 
     // Just for CPCIDSKFile.
         void      InvalidateOverviewInfo();
diff --git a/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.h b/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.h
index 4ec652f..867391b 100644
--- a/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.h
+++ b/frmts/pcidsk/sdk/channel/cpixelinterleavedchannel.h
@@ -55,9 +55,9 @@ namespace PCIDSK
 
         virtual int ReadBlock( int block_index, void *buffer,
             int xoff=-1, int yoff=-1,
-            int xsize=-1, int ysize=-1 );
+            int xsize=-1, int ysize=-1 ) override;
 
-        virtual int WriteBlock( int block_index, void *buffer );
+        virtual int WriteBlock( int block_index, void *buffer ) override;
     private:
         int      image_offset;
     };
diff --git a/frmts/pcidsk/sdk/channel/ctiledchannel.cpp b/frmts/pcidsk/sdk/channel/ctiledchannel.cpp
index 11c299f..ead809f 100644
--- a/frmts/pcidsk/sdk/channel/ctiledchannel.cpp
+++ b/frmts/pcidsk/sdk/channel/ctiledchannel.cpp
@@ -182,7 +182,7 @@ void CTiledChannel::EstablishAccess() const
 void CTiledChannel::LoadTileInfoBlock( int block )
 
 {
-    assert( tile_offsets[block].size() == 0 );
+    assert( tile_offsets[block].empty() );
 
 /* -------------------------------------------------------------------- */
 /*      How many tiles in this block?                                   */
@@ -236,7 +236,7 @@ void CTiledChannel::LoadTileInfoBlock( int block )
 void CTiledChannel::SaveTileInfoBlock( int block )
 
 {
-    assert( tile_offsets[block].size() != 0 );
+    assert( !tile_offsets[block].empty() );
     int tiles_in_block = static_cast<int>(tile_offsets[block].size());
 
 /* -------------------------------------------------------------------- */
@@ -278,7 +278,7 @@ void CTiledChannel::GetTileInfo( int tile_index, uint64 &offset, int &size )
     int block = tile_index / tile_block_size;
     int index_within_block = tile_index - block * tile_block_size;
 
-    if( tile_offsets[block].size() == 0 )
+    if( tile_offsets[block].empty() )
         LoadTileInfoBlock( block );
 
     offset = tile_offsets[block][index_within_block];
@@ -295,7 +295,7 @@ void CTiledChannel::SetTileInfo( int tile_index, uint64 offset, int size )
     int block = tile_index / tile_block_size;
     int index_within_block = tile_index - block * tile_block_size;
 
-    if( tile_offsets[block].size() == 0 )
+    if( tile_offsets[block].empty() )
         LoadTileInfoBlock( block );
 
     if( offset != tile_offsets[block][index_within_block]
@@ -317,7 +317,7 @@ void CTiledChannel::SetTileInfo( int tile_index, uint64 offset, int size )
 void CTiledChannel::Synchronize()
 
 {
-    if( tile_info_dirty.size() == 0 )
+    if( tile_info_dirty.empty() )
         return;
 
     int i;
@@ -385,7 +385,7 @@ int CTiledChannel::ReadBlock( int block_index, void *buffer,
     }
 
 /* -------------------------------------------------------------------- */
-/*      The simpliest case it an uncompressed direct and complete       */
+/*      The simplest case it an uncompressed direct and complete       */
 /*      tile read into the destination buffer.                          */
 /* -------------------------------------------------------------------- */
     if( xoff == 0 && xsize == GetBlockWidth() 
@@ -537,7 +537,7 @@ int CTiledChannel::WriteBlock( int block_index, void *buffer )
     GetTileInfo( block_index, tile_offset, tile_size );
 
 /* -------------------------------------------------------------------- */
-/*      The simpliest case it an uncompressed direct and complete       */
+/*      The simplest case it an uncompressed direct and complete       */
 /*      tile read into the destination buffer.                          */
 /* -------------------------------------------------------------------- */
     if( compression == "NONE" 
@@ -783,19 +783,19 @@ void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
 /* -------------------------------------------------------------------- */
     while( src_offset < src_bytes )
     {
-        bool	bGotARun = false;
+        bool    bGotARun = false;
 
 /* -------------------------------------------------------------------- */
-/*	Establish the run length, and emit if greater than 3. 		*/
+/*      Establish the run length, and emit if greater than 3.           */
 /* -------------------------------------------------------------------- */
         if( src_offset + 3*pixel_size < src_bytes )
         {
-            int		count = 1;
+            int         count = 1;
 
             while( count < 127
                    && src_offset + count*pixel_size < src_bytes )
             {
-                bool	bWordMatch = true;
+                bool    bWordMatch = true;
 
                 for( i = 0; i < pixel_size; i++ )
                 {
@@ -829,18 +829,18 @@ void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
         }
         
 /* -------------------------------------------------------------------- */
-/*      Otherwise emit a literal till we encounter at least a three	*/
-/*	word series.							*/
+/*      Otherwise emit a literal till we encounter at least a three     */
+/*      word series.                                                    */
 /* -------------------------------------------------------------------- */
         if( !bGotARun )
         {
-            int		count = 1;
-            int		match_count = 0;
+            int         count = 1;
+            int         match_count = 0;
 
             while( count < 127
                    && src_offset + count*pixel_size < src_bytes )
             {
-                bool	bWordMatch = true;
+                bool    bWordMatch = true;
 
                 for( i = 0; i < pixel_size; i++ )
                 {
diff --git a/frmts/pcidsk/sdk/channel/ctiledchannel.h b/frmts/pcidsk/sdk/channel/ctiledchannel.h
index 3553081..ce9a2ff 100644
--- a/frmts/pcidsk/sdk/channel/ctiledchannel.h
+++ b/frmts/pcidsk/sdk/channel/ctiledchannel.h
@@ -57,18 +57,18 @@ namespace PCIDSK
                        eChanType pixel_type );
         virtual ~CTiledChannel();
 
-        virtual int GetBlockWidth() const;
-        virtual int GetBlockHeight() const;
-        virtual int GetWidth() const;
-        virtual int GetHeight() const;
-        virtual eChanType GetType() const;
+        virtual int GetBlockWidth() const override;
+        virtual int GetBlockHeight() const override;
+        virtual int GetWidth() const override;
+        virtual int GetHeight() const override;
+        virtual eChanType GetType() const override;
 
         virtual int ReadBlock( int block_index, void *buffer,
                                int xoff=-1, int yoff=-1,
-                               int xsize=-1, int ysize=-1 );
-        virtual int WriteBlock( int block_index, void *buffer );
+                               int xsize=-1, int ysize=-1 ) override;
+        virtual int WriteBlock( int block_index, void *buffer ) override;
 
-        virtual void Synchronize();
+        virtual void Synchronize() override;
         
         
         
diff --git a/frmts/pcidsk/sdk/core/clinksegment.h b/frmts/pcidsk/sdk/core/clinksegment.h
index 52cebf0..15979f3 100644
--- a/frmts/pcidsk/sdk/core/clinksegment.h
+++ b/frmts/pcidsk/sdk/core/clinksegment.h
@@ -45,7 +45,7 @@ namespace PCIDSK {
         void SetPath(const std::string& oPath);
 
         //synchronize the segment on disk.
-        void Synchronize();
+        void Synchronize() override;
     private:
         // Helper housekeeping functions
         void Load();
diff --git a/frmts/pcidsk/sdk/core/cpcidskfile.cpp b/frmts/pcidsk/sdk/core/cpcidskfile.cpp
index f4c5c4e..47605ff 100644
--- a/frmts/pcidsk/sdk/core/cpcidskfile.cpp
+++ b/frmts/pcidsk/sdk/core/cpcidskfile.cpp
@@ -368,8 +368,7 @@ PCIDSK::PCIDSKSegment *CPCIDSKFile::GetSegment( int type, std::string name,
     //see function BuildChildrenLayer in jtfile.cpp, the call on GDBSegNext
     //in the loop on gasTypeTable can create issue in PCIDSKSegNext 
     //(in pcic/gdbfrtms/pcidskopen.cpp)
-    snprintf( type_str, sizeof(type_str), "%03d", (type % 1000) );
-
+    CPLsnprintf( type_str, sizeof(type_str), "%03d", (type % 1000) );
     for( i = previous; i < segment_count; i++ )
     {
         if( type != SEG_UNKNOWN 
@@ -767,8 +766,8 @@ bool CPCIDSKFile::GetEDBFileDetails( EDBFile** file_p,
             new_file.file = interfaces.OpenEDB( filename, "r+" );
             new_file.writable = true;
         } 
-        catch( PCIDSK::PCIDSKException ex ) {}
-        catch( std::exception ex ) {}
+        catch( const PCIDSK::PCIDSKException& ) {}
+        catch( const std::exception& ) {}
     }
 
     if( new_file.file == NULL )
@@ -787,8 +786,8 @@ bool CPCIDSKFile::GetEDBFileDetails( EDBFile** file_p,
 
     edb_file_list.push_back( new_file );
 
-    *file_p = edb_file_list[edb_file_list.size()-1].file;
-    *io_mutex_p  = edb_file_list[edb_file_list.size()-1].io_mutex;
+    *file_p = edb_file_list.back().file;
+    *io_mutex_p  = edb_file_list.back().io_mutex;
 
     return new_file.writable;
 }
@@ -809,7 +808,7 @@ void CPCIDSKFile::GetIODetails( void ***io_handle_pp,
 /* -------------------------------------------------------------------- */
 /*      Does this reference the PCIDSK file itself?                     */
 /* -------------------------------------------------------------------- */
-    if( filename.size() == 0 )
+    if( filename.empty() )
     {
         *io_handle_pp = &io_handle;
         *io_mutex_pp = &io_mutex;
@@ -857,8 +856,8 @@ void CPCIDSKFile::GetIODetails( void ***io_handle_pp,
 
     file_list.push_back( new_file );
 
-    *io_handle_pp = &(file_list[file_list.size()-1].io_handle);
-    *io_mutex_pp  = &(file_list[file_list.size()-1].io_mutex);
+    *io_handle_pp = &(file_list.back().io_handle);
+    *io_mutex_pp  = &(file_list.back().io_mutex);
 }
 
 /************************************************************************/
@@ -913,36 +912,36 @@ int CPCIDSKFile::CreateSegment( std::string name, std::string description,
 
 {
 /* -------------------------------------------------------------------- */
-/*	Set the size of fixed length segments.				*/
+/*      Set the size of fixed length segments.                          */
 /* -------------------------------------------------------------------- */
     int expected_data_blocks = 0;
     bool prezero = false;
 
     switch( seg_type )
     {
-      case SEG_LUT:
-	expected_data_blocks = 2;
-	break;
+    case SEG_LUT:
+        expected_data_blocks = 2;
+        break;
 
-      case SEG_PCT:
-	expected_data_blocks = 6;
-	break;
+    case SEG_PCT:
+        expected_data_blocks = 6;
+        break;
 
-      case SEG_SIG:
-	expected_data_blocks = 12;
-	break;
+    case SEG_SIG:
+        expected_data_blocks = 12;
+        break;
 
-      case SEG_GCP2:
-	// expected_data_blocks = 67;
-	// Change seg type to new GCP segment type
-	expected_data_blocks = 129;
-	break;
-	
-      case SEG_GEO:
-	expected_data_blocks = 6;
-	break;
+    case SEG_GCP2:
+        // expected_data_blocks = 67;
+        // Change seg type to new GCP segment type
+        expected_data_blocks = 129;
+        break;
 
-      case SEG_TEX:
+    case SEG_GEO:
+        expected_data_blocks = 6;
+        break;
+
+    case SEG_TEX:
         expected_data_blocks = 64;
         prezero = true;
         break;
@@ -1218,7 +1217,7 @@ void CPCIDSKFile::MoveSegmentToEOF( int segment )
 /************************************************************************/
 /*
  const char *pszResampling;
- 	     Can be "NEAREST" for Nearest Neighbour resampling (the fastest),
+             Can be "NEAREST" for Nearest Neighbour resampling (the fastest),
              "AVERAGE" for block averaging or "MODE" for block mode.  This
              establishing the type of resampling to be applied when preparing
              the decimated overviews. Other methods can be set as well, but
diff --git a/frmts/pcidsk/sdk/core/cpcidskfile.h b/frmts/pcidsk/sdk/core/cpcidskfile.h
index d62fa20..e9eaebc 100644
--- a/frmts/pcidsk/sdk/core/cpcidskfile.h
+++ b/frmts/pcidsk/sdk/core/cpcidskfile.h
@@ -56,53 +56,53 @@ namespace PCIDSK
         CPCIDSKFile( std::string filename );
         virtual ~CPCIDSKFile();
 
-        virtual PCIDSKInterfaces *GetInterfaces() { return &interfaces; }
+        virtual PCIDSKInterfaces *GetInterfaces() override { return &interfaces; }
 
-        PCIDSKChannel  *GetChannel( int band );
-        PCIDSKSegment  *GetSegment( int segment );
-        std::vector<PCIDSKSegment *> GetSegments();
+        PCIDSKChannel  *GetChannel( int band ) override;
+        PCIDSKSegment  *GetSegment( int segment ) override;
+        std::vector<PCIDSKSegment *> GetSegments() override;
 
         PCIDSKSegment  *GetSegment( int type, std::string name,
-            int previous = 0 );
+            int previous = 0 ) override;
         int  CreateSegment( std::string name, std::string description,
-            eSegType seg_type, int data_blocks );
-        void DeleteSegment( int segment );
+            eSegType seg_type, int data_blocks ) override;
+        void DeleteSegment( int segment ) override;
         void CreateOverviews( int chan_count, int *chan_list, 
-            int factor, std::string resampling );
+            int factor, std::string resampling ) override;
 
-        int       GetWidth() const { return width; }
-        int       GetHeight() const { return height; }
-        int       GetChannels() const { return channel_count; }
-        std::string GetInterleaving() const { return interleaving; }
-        bool      GetUpdatable() const { return updatable; } 
-        uint64    GetFileSize() const { return file_size; }
+        int       GetWidth() const override { return width; }
+        int       GetHeight() const override { return height; }
+        int       GetChannels() const override { return channel_count; }
+        std::string GetInterleaving() const override { return interleaving; }
+        bool      GetUpdatable() const override { return updatable; } 
+        uint64    GetFileSize() const override { return file_size; }
 
         // the following are only for pixel interleaved IO
-        int       GetPixelGroupSize() const { return pixel_group_size; }
-        void     *ReadAndLockBlock( int block_index, int xoff=-1, int xsize=-1 );
-        void      UnlockBlock( bool mark_dirty = false );
+        int       GetPixelGroupSize() const override { return pixel_group_size; }
+        void     *ReadAndLockBlock( int block_index, int xoff=-1, int xsize=-1 ) override;
+        void      UnlockBlock( bool mark_dirty = false ) override;
         void      WriteBlock( int block_index, void *buffer );
         void      FlushBlock();
 
-        void      WriteToFile( const void *buffer, uint64 offset, uint64 size );
-        void      ReadFromFile( void *buffer, uint64 offset, uint64 size );
+        void      WriteToFile( const void *buffer, uint64 offset, uint64 size ) override;
+        void      ReadFromFile( void *buffer, uint64 offset, uint64 size ) override;
 
         std::string GetFilename() const { return base_filename; }
 
         void      GetIODetails( void ***io_handle_pp, Mutex ***io_mutex_pp,
-                                std::string filename="", bool writable=false );
+                                std::string filename="", bool writable=false ) override;
 
         bool      GetEDBFileDetails( EDBFile** file_p, Mutex **io_mutex_p,
                                      std::string filename );
 
-        std::string GetMetadataValue( const std::string& key ) 
+        std::string GetMetadataValue( const std::string& key ) override 
             { return metadata.GetMetadataValue(key); }
-        void        SetMetadataValue( const std::string& key, const std::string& value ) 
+        void        SetMetadataValue( const std::string& key, const std::string& value ) override 
             { metadata.SetMetadataValue(key,value); }
-        std::vector<std::string> GetMetadataKeys() 
+        std::vector<std::string> GetMetadataKeys() override 
             { return metadata.GetMetadataKeys(); }
 
-        void      Synchronize();
+        void      Synchronize() override;
 
     // not exposed to applications.
         void      ExtendFile( uint64 blocks_requested, bool prezero = false );
diff --git a/frmts/pcidsk/sdk/core/edb_pcidsk.cpp b/frmts/pcidsk/sdk/core/edb_pcidsk.cpp
index 50a82ad..7d58912 100644
--- a/frmts/pcidsk/sdk/core/edb_pcidsk.cpp
+++ b/frmts/pcidsk/sdk/core/edb_pcidsk.cpp
@@ -50,28 +50,28 @@ class PCIDSK_EDBFile : public EDBFile
     
 public:
 
-    PCIDSK_EDBFile( PCIDSKFile *file_in ) { file = file_in; }
+    explicit PCIDSK_EDBFile( PCIDSKFile *file_in ) { file = file_in; }
     ~PCIDSK_EDBFile() { Close(); }
 
-    int Close() const;
-    int GetWidth() const;
-    int GetHeight() const;
-    int GetChannels() const;
-    int GetBlockWidth(int channel ) const;
-    int GetBlockHeight(int channel ) const;
-    eChanType GetType(int channel ) const;
+    int Close() const override;
+    int GetWidth() const override;
+    int GetHeight() const override;
+    int GetChannels() const override;
+    int GetBlockWidth(int channel ) const override;
+    int GetBlockHeight(int channel ) const override;
+    eChanType GetType(int channel ) const override;
     int ReadBlock(int channel,
                   int block_index, void *buffer,
                   int win_xoff, int win_yoff,
-                  int win_xsize, int win_ysize );
-    int WriteBlock( int channel, int block_index, void *buffer);
+                  int win_xsize, int win_ysize ) override;
+    int WriteBlock( int channel, int block_index, void *buffer) override;
 };
 
 /************************************************************************/
 /*                           DefaultOpenEDB()                           */
 /************************************************************************/
 
-EDBFile *PCIDSK::DefaultOpenEDB( std::string filename, std::string access )
+EDBFile *PCIDSK::DefaultOpenEDB( const std::string& filename, const std::string& access )
 
 {
     // it would be nice to be able to pass in an appropriate PCIDSKInterface!
diff --git a/frmts/pcidsk/sdk/core/libjpeg_io.cpp b/frmts/pcidsk/sdk/core/libjpeg_io.cpp
index 16757f3..1c2bd1b 100644
--- a/frmts/pcidsk/sdk/core/libjpeg_io.cpp
+++ b/frmts/pcidsk/sdk/core/libjpeg_io.cpp
@@ -72,8 +72,8 @@ void PCIDSK::LibJPEG_DecompressBlock(
     int xsize, int ysize, eChanType CPL_UNUSED pixel_type )
 {
     struct jpeg_decompress_struct sJCompInfo;
-    struct jpeg_source_mgr	sSrcMgr;
-    struct jpeg_error_mgr	sErrMgr;
+    struct jpeg_source_mgr        sSrcMgr;
+    struct jpeg_error_mgr         sErrMgr;
 
     int i;
 
@@ -83,10 +83,8 @@ void PCIDSK::LibJPEG_DecompressBlock(
 /*      free it as soon as it is done so this should not hurt much.     */
 /* -------------------------------------------------------------------- */
     sSrcMgr.init_source = _DummySrcMgrMethod;
-    sSrcMgr.fill_input_buffer = (boolean (*)(j_decompress_ptr))
-        						_DummyMgrMethod;
-    sSrcMgr.skip_input_data = (void (*)(j_decompress_ptr, long))
-        						_DummyMgrMethod;
+    sSrcMgr.fill_input_buffer = (boolean (*)(j_decompress_ptr))_DummyMgrMethod;
+    sSrcMgr.skip_input_data = (void (*)(j_decompress_ptr, long))_DummyMgrMethod;
     sSrcMgr.resync_to_restart = jpeg_resync_to_restart;
     sSrcMgr.term_source = _DummySrcMgrMethod;
 
@@ -119,11 +117,11 @@ void PCIDSK::LibJPEG_DecompressBlock(
     jpeg_start_decompress(&sJCompInfo);
 
 /* -------------------------------------------------------------------- */
-/*	Read each of the scanlines.					*/
+/*      Read each of the scanlines.                                     */
 /* -------------------------------------------------------------------- */
     for( i = 0; i < ysize; i++ )
     {
-        uint8	*line_data = dst_data + i*xsize;
+        uint8   *line_data = dst_data + i*xsize;
         jpeg_read_scanlines( &sJCompInfo, (JSAMPARRAY) &line_data, 1 );
     }
 
@@ -142,11 +140,11 @@ void PCIDSK::LibJPEG_CompressBlock(
     uint8 *src_data, CPL_UNUSED int src_bytes, uint8 *dst_data, int &dst_bytes,
     int xsize, int ysize, CPL_UNUSED eChanType pixel_type, int quality )
 {
-    struct jpeg_compress_struct	sJCompInfo;
-    struct jpeg_destination_mgr	sDstMgr;
-    struct jpeg_error_mgr	sErrMgr;
+    struct jpeg_compress_struct sJCompInfo;
+    struct jpeg_destination_mgr sDstMgr;
+    struct jpeg_error_mgr       sErrMgr;
 
-    int		i;
+    int     i;
 
 /* -------------------------------------------------------------------- */
 /*      Setup the buffer we will compress into.                         */
@@ -155,7 +153,7 @@ void PCIDSK::LibJPEG_CompressBlock(
     sDstMgr.free_in_buffer = dst_bytes;
     sDstMgr.init_destination = _DummyMgrMethod;
     sDstMgr.empty_output_buffer = (boolean (*)(j_compress_ptr))
-        						_DummyMgrMethod;
+                                                            _DummyMgrMethod;
     sDstMgr.term_destination = _DummyMgrMethod;
 
 /* -------------------------------------------------------------------- */
@@ -177,17 +175,17 @@ void PCIDSK::LibJPEG_CompressBlock(
     jpeg_start_compress(&sJCompInfo, TRUE );
     
 /* -------------------------------------------------------------------- */
-/*	Write all the scanlines at once.				*/
+/*      Write all the scanlines at once.                                */
 /* -------------------------------------------------------------------- */
     for( i = 0; i < ysize; i++ )
     {
-        uint8	*pabyLine = src_data + i*xsize;
+        uint8   *pabyLine = src_data + i*xsize;
         
         jpeg_write_scanlines( &sJCompInfo, (JSAMPARRAY)&pabyLine, 1 );
     }
     
 /* -------------------------------------------------------------------- */
-/*	Cleanup.							*/
+/*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
     jpeg_finish_compress( &sJCompInfo );
 
diff --git a/frmts/pcidsk/sdk/core/metadataset.h b/frmts/pcidsk/sdk/core/metadataset.h
index fd3dad5..f23cee1 100644
--- a/frmts/pcidsk/sdk/core/metadataset.h
+++ b/frmts/pcidsk/sdk/core/metadataset.h
@@ -41,7 +41,7 @@ namespace PCIDSK
     /************************************************************************/
 
     class MetadataSet 
-    {									
+    {
     public:
         MetadataSet();
         ~MetadataSet();
diff --git a/frmts/pcidsk/sdk/core/metadataset_p.cpp b/frmts/pcidsk/sdk/core/metadataset_p.cpp
index a301621..31593d0 100644
--- a/frmts/pcidsk/sdk/core/metadataset_p.cpp
+++ b/frmts/pcidsk/sdk/core/metadataset_p.cpp
@@ -162,7 +162,7 @@ std::vector<std::string> MetadataSet::GetMetadataKeys()
     std::vector<std::string> keys;
     std::map<std::string,std::string>::iterator it;
 
-    for( it = md_set.begin(); it != md_set.end(); it++ )
+    for( it = md_set.begin(); it != md_set.end(); ++it )
     {
         keys.push_back( (*it).first );
     }
diff --git a/frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp b/frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp
index c5385c1..6624563 100644
--- a/frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp
+++ b/frmts/pcidsk/sdk/core/pcidsk_pubutils.cpp
@@ -125,7 +125,7 @@ std::string PCIDSK::DataTypeName( eChanType chan_type )
 /**
  * @brief Return the segment type code based on the contents of type_name
  * 
- * @param the type name, as a string
+ * @param type_name the type name, as a string
  *
  * @return the channel type code
  */
@@ -159,7 +159,7 @@ eChanType PCIDSK::GetDataTypeFromName(std::string const& type_name)
 /**
  * @brief Return whether or not the data type is complex
  * 
- * @param the type
+ * @param type the type
  *
  * @return true if the data type is complex, false otherwise
  */
diff --git a/frmts/pcidsk/sdk/core/pcidsk_utils.cpp b/frmts/pcidsk/sdk/core/pcidsk_utils.cpp
index 728bd6c..644aec6 100644
--- a/frmts/pcidsk/sdk/core/pcidsk_utils.cpp
+++ b/frmts/pcidsk/sdk/core/pcidsk_utils.cpp
@@ -52,10 +52,10 @@ using namespace PCIDSK;
 #include <time.h>
 #include <sys/types.h>
 
-void	PCIDSK::GetCurrentDateTime( char *out_time )
+void    PCIDSK::GetCurrentDateTime( char *out_time )
 
 {
-    time_t	    clock;
+    time_t          clock;
     char            ctime_out[25];
 
     time( &clock );
@@ -399,7 +399,7 @@ std::vector<double> PCIDSK::ProjParmsFromText( std::string geosys,
             next++;
 
         // move past white space.
-        while( *next != '\0' && *next == ' ' )
+        while( *next == ' ' )
             next++;
     }
 
@@ -507,7 +507,7 @@ std::string PCIDSK::MergeRelativePath( const PCIDSK::IOInterfaces *io_interfaces
 /* -------------------------------------------------------------------- */
 /*      Does src_filename appear to be absolute?                        */
 /* -------------------------------------------------------------------- */
-    if( src_filename.size() == 0 )
+    if( src_filename.empty() )
         return src_filename; // we can't do anything with a blank.
     else if( src_filename.size() > 2 && src_filename[1] == ':' )
         return src_filename; // has a drive letter?
@@ -637,14 +637,20 @@ static void vDebug( void (*pfnDebug)(const char *),
                || nPR == -1 )
         {
             nWorkBufferSize *= 4;
-            pszWorkBuffer = (char *) realloc(pszWorkBuffer, 
-                                             nWorkBufferSize );
+            char* pszWorkBufferNew = (char *) realloc(pszWorkBuffer, 
+                                                      nWorkBufferSize );
 #ifdef va_copy
             va_end( wrk_args );
             va_copy( wrk_args, args );
 #else
             wrk_args = args;
 #endif
+            if( pszWorkBufferNew == NULL )
+            {
+                strcpy( pszWorkBuffer, "(message too large)" );
+                break;
+            }
+            pszWorkBuffer = pszWorkBufferNew;
         }
         message = pszWorkBuffer;
         free( pszWorkBuffer );
diff --git a/frmts/pcidsk/sdk/core/pcidskcreate.cpp b/frmts/pcidsk/sdk/core/pcidskcreate.cpp
index 4d2eb75..fa2cb7f 100644
--- a/frmts/pcidsk/sdk/core/pcidskcreate.cpp
+++ b/frmts/pcidsk/sdk/core/pcidskcreate.cpp
@@ -153,376 +153,390 @@ PCIDSK::Create( std::string filename, int pixels, int lines,
     void *io_handle = interfaces->io->Open( filename, "w+" );
 
     assert( io_handle != NULL );
-
+    try
+    {
 /* ==================================================================== */
 /*      Establish some key file layout information.                     */
 /* ==================================================================== */
-    int image_header_start = 1;                    // in blocks
-    uint64 image_data_start, image_data_size=0;    // in blocks
-    uint64 segment_ptr_start, segment_ptr_size=64; // in blocks
-    int pixel_group_size, line_size;               // in bytes
-    int image_header_count = channel_count;
+        int image_header_start = 1;                    // in blocks
+        uint64 image_data_start, image_data_size=0;    // in blocks
+        uint64 segment_ptr_start, segment_ptr_size=64; // in blocks
+        int pixel_group_size, line_size;               // in bytes
+        int image_header_count = channel_count;
 
 /* -------------------------------------------------------------------- */
 /*      Pixel interleaved.                                              */
 /* -------------------------------------------------------------------- */
-    if( strcmp(interleaving,"PIXEL") == 0 )
-    {
-        pixel_group_size = 
-            channels[0] + // CHN_8U
-            channels[1] * DataTypeSize(CHN_16U) + 
-            channels[2] * DataTypeSize(CHN_16S) + 
-            channels[3] * DataTypeSize(CHN_32R) +
-            channels[4] * DataTypeSize(CHN_C16U) +
-            channels[5] * DataTypeSize(CHN_C16S) +
-            channels[6] * DataTypeSize(CHN_C32R);
-            //channels[0] + channels[1]*2 + channels[2]*2 + channels[3]*4;
-        line_size = ((pixel_group_size * pixels + 511) / 512) * 512;
-        image_data_size = (((uint64)line_size) * lines) / 512;
-
-        // TODO: Old code enforces a 1TB limit for some reason.
-    }
+        if( strcmp(interleaving,"PIXEL") == 0 )
+        {
+            pixel_group_size = 
+                channels[0] + // CHN_8U
+                channels[1] * DataTypeSize(CHN_16U) + 
+                channels[2] * DataTypeSize(CHN_16S) + 
+                channels[3] * DataTypeSize(CHN_32R) +
+                channels[4] * DataTypeSize(CHN_C16U) +
+                channels[5] * DataTypeSize(CHN_C16S) +
+                channels[6] * DataTypeSize(CHN_C32R);
+                //channels[0] + channels[1]*2 + channels[2]*2 + channels[3]*4;
+            line_size = ((pixel_group_size * pixels + 511) / 512) * 512;
+            image_data_size = (((uint64)line_size) * lines) / 512;
+
+            // TODO: Old code enforces a 1TB limit for some reason.
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Band interleaved.                                               */
 /* -------------------------------------------------------------------- */
-    else if( strcmp(interleaving,"BAND") == 0 )
-    {
-        pixel_group_size = 
-            channels[0] + // CHN_8U
-            channels[1] * DataTypeSize(CHN_16U) + 
-            channels[2] * DataTypeSize(CHN_16S) + 
-            channels[3] * DataTypeSize(CHN_32R) +
-            channels[4] * DataTypeSize(CHN_C16U) +
-            channels[5] * DataTypeSize(CHN_C16S) +
-            channels[6] * DataTypeSize(CHN_C32R);
-        // BAND interleaved bands are tightly packed.
-        image_data_size = 
-            (((uint64)pixel_group_size) * pixels * lines + 511) / 512;
-
-        // TODO: Old code enforces a 1TB limit for some reason.
-    }
+        else if( strcmp(interleaving,"BAND") == 0 )
+        {
+            pixel_group_size = 
+                channels[0] + // CHN_8U
+                channels[1] * DataTypeSize(CHN_16U) + 
+                channels[2] * DataTypeSize(CHN_16S) + 
+                channels[3] * DataTypeSize(CHN_32R) +
+                channels[4] * DataTypeSize(CHN_C16U) +
+                channels[5] * DataTypeSize(CHN_C16S) +
+                channels[6] * DataTypeSize(CHN_C32R);
+            // BAND interleaved bands are tightly packed.
+            image_data_size = 
+                (((uint64)pixel_group_size) * pixels * lines + 511) / 512;
+
+            // TODO: Old code enforces a 1TB limit for some reason.
+        }
 
 /* -------------------------------------------------------------------- */
 /*      FILE/Tiled.                                                     */
 /* -------------------------------------------------------------------- */
-    else if( strcmp(interleaving,"FILE") == 0 )
-    {
-        // For some reason we reserve extra space, but only for FILE.
-        if( channel_count < 64 )
-            image_header_count = 64;
+        else if( strcmp(interleaving,"FILE") == 0 )
+        {
+            // For some reason we reserve extra space, but only for FILE.
+            if( channel_count < 64 )
+                image_header_count = 64;
 
-        image_data_size = 0;
+            image_data_size = 0;
 
-        // TODO: Old code enforces a 1TB limit on the fattest band.
-    }
+            // TODO: Old code enforces a 1TB limit on the fattest band.
+        }
 
 /* -------------------------------------------------------------------- */
 /*      Place components.                                               */
 /* -------------------------------------------------------------------- */
-    segment_ptr_start = image_header_start + image_header_count*2;
-    image_data_start = segment_ptr_start + segment_ptr_size;
+        segment_ptr_start = image_header_start + image_header_count*2;
+        image_data_start = segment_ptr_start + segment_ptr_size;
 
 /* ==================================================================== */
 /*      Prepare the file header.                                        */
 /* ==================================================================== */
-    PCIDSKBuffer fh(512);
+        PCIDSKBuffer fh(512);
 
-    char current_time[17];
-    GetCurrentDateTime( current_time );
+        char current_time[17];
+        GetCurrentDateTime( current_time );
 
-    // Initialize everything to spaces.
-    fh.Put( "", 0, 512 );
+        // Initialize everything to spaces.
+        fh.Put( "", 0, 512 );
 
 /* -------------------------------------------------------------------- */
 /*      File Type, Version, and Size                                    */
-/* 	Notice: we get the first 4 characters from PCIVERSIONAME.	*/
+/*      Notice: we get the first 4 characters from PCIVERSIONAME.       */
 /* -------------------------------------------------------------------- */
-    // FH1 - magic format string.
-    fh.Put( "PCIDSK", 0, 8 );
+        // FH1 - magic format string.
+        fh.Put( "PCIDSK", 0, 8 );
 
-    // FH2 - TODO: Allow caller to pass this in.
-    fh.Put( "SDK V1.0", 8, 8 );
+        // FH2 - TODO: Allow caller to pass this in.
+        fh.Put( "SDK V1.0", 8, 8 );
 
-    // FH3 - file size later.
-    fh.Put( (image_data_start + image_data_size), 16, 16 );
-    
-    // FH4 - 16 characters reserved - spaces.
+        // FH3 - file size later.
+        fh.Put( (image_data_start + image_data_size), 16, 16 );
+        
+        // FH4 - 16 characters reserved - spaces.
 
-    // FH5 - Description
-    fh.Put( filename.c_str(), 48, 64 );
+        // FH5 - Description
+        fh.Put( filename.c_str(), 48, 64 );
 
-    // FH6 - Facility
-    fh.Put( "PCI Inc., Richmond Hill, Canada", 112, 32 );
+        // FH6 - Facility
+        fh.Put( "PCI Inc., Richmond Hill, Canada", 112, 32 );
 
-    // FH7.1 / FH7.2 - left blank (64+64 bytes @ 144)
+        // FH7.1 / FH7.2 - left blank (64+64 bytes @ 144)
 
-    // FH8 Creation date/time
-    fh.Put( current_time, 272, 16 );
+        // FH8 Creation date/time
+        fh.Put( current_time, 272, 16 );
 
-    // FH9 Update date/time
-    fh.Put( current_time, 288, 16 );
+        // FH9 Update date/time
+        fh.Put( current_time, 288, 16 );
 
 /* -------------------------------------------------------------------- */
 /*      Image Data                                                      */
 /* -------------------------------------------------------------------- */
-    // FH10 - start block of image data
-    fh.Put( image_data_start+1, 304, 16 );
+        // FH10 - start block of image data
+        fh.Put( image_data_start+1, 304, 16 );
 
-    // FH11 - number of blocks of image data.
-    fh.Put( image_data_size, 320, 16 );
+        // FH11 - number of blocks of image data.
+        fh.Put( image_data_size, 320, 16 );
 
-    // FH12 - start block of image headers.
-    fh.Put( image_header_start+1, 336, 16 );
+        // FH12 - start block of image headers.
+        fh.Put( image_header_start+1, 336, 16 );
 
-    // FH13 - number of blocks of image headers.
-    fh.Put( image_header_count*2, 352, 8);
+        // FH13 - number of blocks of image headers.
+        fh.Put( image_header_count*2, 352, 8);
 
-    // FH14 - interleaving.
-    fh.Put( interleaving, 360, 8);
+        // FH14 - interleaving.
+        fh.Put( interleaving, 360, 8);
 
-    // FH15 - reserved - MIXED is for some ancient backwards compatibility.
-    fh.Put( "MIXED", 368, 8);
+        // FH15 - reserved - MIXED is for some ancient backwards compatibility.
+        fh.Put( "MIXED", 368, 8);
 
-    // FH16 - number of image bands.
-    fh.Put( channel_count, 376, 8 );
+        // FH16 - number of image bands.
+        fh.Put( channel_count, 376, 8 );
 
-    // FH17 - width of image in pixels.
-    fh.Put( pixels, 384, 8 );
+        // FH17 - width of image in pixels.
+        fh.Put( pixels, 384, 8 );
 
-    // FH18 - height of image in pixels.
-    fh.Put( lines, 392, 8 );
+        // FH18 - height of image in pixels.
+        fh.Put( lines, 392, 8 );
 
-    // FH19 - pixel ground size interpretation.
-    fh.Put( "METRE", 400, 8 );
+        // FH19 - pixel ground size interpretation.
+        fh.Put( "METRE", 400, 8 );
 
-    // TODO:
-    //PrintDouble( fh->XPixelSize, "%16.9f", 1.0 );
-    //PrintDouble( fh->YPixelSize, "%16.9f", 1.0 );
-    fh.Put( "1.0", 408, 16 );
-    fh.Put( "1.0", 424, 16 );
+        // TODO:
+        //PrintDouble( fh->XPixelSize, "%16.9f", 1.0 );
+        //PrintDouble( fh->YPixelSize, "%16.9f", 1.0 );
+        fh.Put( "1.0", 408, 16 );
+        fh.Put( "1.0", 424, 16 );
 
 /* -------------------------------------------------------------------- */
 /*      Segment Pointers                                                */
 /* -------------------------------------------------------------------- */
-    // FH22 - start block of segment pointers.
-    fh.Put( segment_ptr_start+1, 440, 16 );
+        // FH22 - start block of segment pointers.
+        fh.Put( segment_ptr_start+1, 440, 16 );
 
-    // fH23 - number of blocks of segment pointers.
-    fh.Put( segment_ptr_size, 456, 8 );
+        // fH23 - number of blocks of segment pointers.
+        fh.Put( segment_ptr_size, 456, 8 );
 
 /* -------------------------------------------------------------------- */
 /*      Number of different types of Channels                           */
 /* -------------------------------------------------------------------- */
-    // FH24.1 - 8U bands.
-    fh.Put( channels[0], 464, 4 );
+        // FH24.1 - 8U bands.
+        fh.Put( channels[0], 464, 4 );
 
-    // FH24.2 - 16S bands.
-    fh.Put( channels[1], 468, 4 );
+        // FH24.2 - 16S bands.
+        fh.Put( channels[1], 468, 4 );
 
-    // FH24.3 - 16U bands.
-    fh.Put( channels[2], 472, 4 );
+        // FH24.3 - 16U bands.
+        fh.Put( channels[2], 472, 4 );
 
-    // FH24.4 - 32R bands.
-    fh.Put( channels[3], 476, 4 );
-    
-    // FH24.5 - C16U bands
-    fh.Put( channels[4], 480, 4 );
-    
-    // FH24.6 - C16S bands
-    fh.Put( channels[5], 484, 4 );
-    
-    // FH24.7 - C32R bands
-    fh.Put( channels[6], 488, 4 );
+        // FH24.4 - 32R bands.
+        fh.Put( channels[3], 476, 4 );
+        
+        // FH24.5 - C16U bands
+        fh.Put( channels[4], 480, 4 );
+        
+        // FH24.6 - C16S bands
+        fh.Put( channels[5], 484, 4 );
+        
+        // FH24.7 - C32R bands
+        fh.Put( channels[6], 488, 4 );
 
 /* -------------------------------------------------------------------- */
 /*      Write out the file header.                                      */
 /* -------------------------------------------------------------------- */
-    interfaces->io->Write( fh.buffer, 512, 1, io_handle );
+        interfaces->io->Write( fh.buffer, 512, 1, io_handle );
 
 /* ==================================================================== */
 /*      Write out the image headers.                                    */
 /* ==================================================================== */
-    PCIDSKBuffer ih( 1024 );
-
-    ih.Put( " ", 0, 1024 );
-
-    // IHi.1 - Text describing Channel Contents
-    ih.Put( "Contents Not Specified", 0, 64 );
-
-    // IHi.2 - Filename storing image.
-    if( STARTS_WITH(interleaving, "FILE") )
-        ih.Put( "<unintialized>", 64, 64 );  // TODO: Spelling?
-    
-    if( externallink )
-    {
-        // IHi.6.7 - IHi.6.10
-        ih.Put( 0, 250, 8 ); 
-        ih.Put( 0, 258, 8 );
-        ih.Put( pixels, 266, 8 );
-        ih.Put( lines, 274, 8 );
-    }
+        PCIDSKBuffer ih( 1024 );
 
-    // IHi.3 - Creation time and date.
-    ih.Put( current_time, 128, 16 );
+        ih.Put( " ", 0, 1024 );
 
-    // IHi.4 - Creation time and date.
-    ih.Put( current_time, 144, 16 );
+        // IHi.1 - Text describing Channel Contents
+        ih.Put( "Contents Not Specified", 0, 64 );
 
-    interfaces->io->Seek( io_handle, image_header_start*512, SEEK_SET );
-
-    for( chan_index = 0; chan_index < channel_count; chan_index++ )
-    {
-        ih.Put(DataTypeName(channel_types[chan_index]).c_str(), 160, 8);    
-
-        if( STARTS_WITH(options.c_str(), "TILED") )
+        // IHi.2 - Filename storing image.
+        if( STARTS_WITH(interleaving, "FILE") )
+            ih.Put( "<unintialized>", 64, 64 );  // TODO: Spelling?
+        
+        if( externallink )
         {
-            char sis_filename[65];
-            snprintf( sis_filename, sizeof(sis_filename), "/SIS=%d", chan_index );
-            ih.Put( sis_filename, 64, 64 );
-
             // IHi.6.7 - IHi.6.10
             ih.Put( 0, 250, 8 ); 
             ih.Put( 0, 258, 8 );
             ih.Put( pixels, 266, 8 );
             ih.Put( lines, 274, 8 );
-
-            // IHi.6.11
-            ih.Put( 1, 282, 8 );
         }
 
-        interfaces->io->Write( ih.buffer, 1024, 1, io_handle );
-    }
+        // IHi.3 - Creation time and date.
+        ih.Put( current_time, 128, 16 );
 
-    for( chan_index = channel_count; 
-         chan_index < image_header_count; 
-         chan_index++ )
-    {
-        ih.Put( "", 160, 8 );
-        ih.Put( "<unintialized>", 64, 64 );  // TODO: Spelling?
-        ih.Put( "", 250, 40 );
+        // IHi.4 - Creation time and date.
+        ih.Put( current_time, 144, 16 );
 
-        interfaces->io->Write( ih.buffer, 1024, 1, io_handle );
-    }
+        interfaces->io->Seek( io_handle, image_header_start*512, SEEK_SET );
+
+        for( chan_index = 0; chan_index < channel_count; chan_index++ )
+        {
+            ih.Put(DataTypeName(channel_types[chan_index]).c_str(), 160, 8);    
+
+            if( STARTS_WITH(options.c_str(), "TILED") )
+            {
+                char sis_filename[65];
+                snprintf( sis_filename, sizeof(sis_filename), "/SIS=%d", chan_index );
+                ih.Put( sis_filename, 64, 64 );
+
+                // IHi.6.7 - IHi.6.10
+                ih.Put( 0, 250, 8 ); 
+                ih.Put( 0, 258, 8 );
+                ih.Put( pixels, 266, 8 );
+                ih.Put( lines, 274, 8 );
+
+                // IHi.6.11
+                ih.Put( 1, 282, 8 );
+            }
+
+            interfaces->io->Write( ih.buffer, 1024, 1, io_handle );
+        }
+
+        for( chan_index = channel_count; 
+            chan_index < image_header_count; 
+            chan_index++ )
+        {
+            ih.Put( "", 160, 8 );
+            ih.Put( "<unintialized>", 64, 64 );  // TODO: Spelling?
+            ih.Put( "", 250, 40 );
+
+            interfaces->io->Write( ih.buffer, 1024, 1, io_handle );
+        }
 
 /* ==================================================================== */
 /*      Write out the segment pointers, all spaces.                     */
 /* ==================================================================== */
-    PCIDSKBuffer segment_pointers( (int) (segment_ptr_size*512) );
-    segment_pointers.Put( " ", 0, (int) (segment_ptr_size*512) );
+        PCIDSKBuffer segment_pointers( (int) (segment_ptr_size*512) );
+        segment_pointers.Put( " ", 0, (int) (segment_ptr_size*512) );
 
-    interfaces->io->Seek( io_handle, segment_ptr_start*512, SEEK_SET );
-    interfaces->io->Write( segment_pointers.buffer, segment_ptr_size, 512, 
-                           io_handle );
+        interfaces->io->Seek( io_handle, segment_ptr_start*512, SEEK_SET );
+        interfaces->io->Write( segment_pointers.buffer, segment_ptr_size, 512, 
+                            io_handle );
 
 /* -------------------------------------------------------------------- */
 /*      Ensure we write out something at the end of the image data      */
 /*      to force the file size.                                         */
 /* -------------------------------------------------------------------- */
-    if( image_data_size > 0 )
-    {
-        interfaces->io->Seek( io_handle, (image_data_start + image_data_size)*512-1,
-                              SEEK_SET );
-        interfaces->io->Write( "\0", 1, 1, io_handle );
-    }
+        if( image_data_size > 0 )
+        {
+            interfaces->io->Seek( io_handle, (image_data_start + image_data_size)*512-1,
+                                SEEK_SET );
+            interfaces->io->Write( "\0", 1, 1, io_handle );
+        }
     
 /* -------------------------------------------------------------------- */
 /*      Close the raw file, and reopen as a pcidsk file.                */
 /* -------------------------------------------------------------------- */
-    interfaces->io->Close( io_handle );
+        interfaces->io->Close( io_handle );
+    }
+    catch( const PCIDSKException& )
+    {
+        interfaces->io->Close( io_handle );
+        throw;
+    }
 
     PCIDSKFile *file = Open( filename, "r+", interfaces );
-
+    try
+    {
 /* -------------------------------------------------------------------- */
 /*      Create a default georeferencing segment.                        */
 /* -------------------------------------------------------------------- */
-    file->CreateSegment( "GEOref", 
-                         "Master Georeferencing Segment for File",
-                         SEG_GEO, 6 );
+        file->CreateSegment( "GEOref", 
+                            "Master Georeferencing Segment for File",
+                            SEG_GEO, 6 );
 
 /* -------------------------------------------------------------------- */
 /*      If the dataset is tiled, create the file band data.             */
 /* -------------------------------------------------------------------- */
-    if( STARTS_WITH(options.c_str(), "TILED") )
-    {
-        file->SetMetadataValue( "_DBLayout", options ); 
-
-        // For sizing the SysBMDir we want an approximate size of the
-        // the imagery.
-        uint64 rough_image_size = 
-            (channels[0] + // CHN_8U
-             channels[1] * DataTypeSize(CHN_16U) + 
-             channels[2] * DataTypeSize(CHN_16S) + 
-             channels[3] * DataTypeSize(CHN_32R) +
-             channels[4] * DataTypeSize(CHN_C16U) +
-             channels[5] * DataTypeSize(CHN_C16S) +
-             channels[6] * DataTypeSize(CHN_C32R)) 
-            * (pixels * (uint64) lines);
-        uint64 sysbmdir_size = ((rough_image_size / 8192) * 28) / 512;
-
-        sysbmdir_size = (int) (sysbmdir_size * 1.1 + 100);
-        int segment = file->CreateSegment( "SysBMDir", 
-                                           "System Block Map Directory - Do not modify.",
-                                           SEG_SYS, static_cast<int>(sysbmdir_size) );
-        
-        SysBlockMap *bm = 
-            dynamic_cast<SysBlockMap *>(file->GetSegment( segment ));
-
-        for( chan_index = 0; chan_index < channel_count; chan_index++ )
+        if( STARTS_WITH(options.c_str(), "TILED") )
         {
-            bm->CreateVirtualImageFile( pixels, lines, blocksize, blocksize,
-                                        channel_types[chan_index], 
-                                        compression );
+            file->SetMetadataValue( "_DBLayout", options ); 
+
+            // For sizing the SysBMDir we want an approximate size of the
+            // the imagery.
+            uint64 rough_image_size = 
+                (channels[0] + // CHN_8U
+                channels[1] * DataTypeSize(CHN_16U) + 
+                channels[2] * DataTypeSize(CHN_16S) + 
+                channels[3] * DataTypeSize(CHN_32R) +
+                channels[4] * DataTypeSize(CHN_C16U) +
+                channels[5] * DataTypeSize(CHN_C16S) +
+                channels[6] * DataTypeSize(CHN_C32R)) 
+                * (pixels * (uint64) lines);
+            uint64 sysbmdir_size = ((rough_image_size / 8192) * 28) / 512;
+
+            sysbmdir_size = (int) (sysbmdir_size * 1.1 + 100);
+            int segment = file->CreateSegment( "SysBMDir", 
+                                            "System Block Map Directory - Do not modify.",
+                                            SEG_SYS, static_cast<int>(sysbmdir_size) );
+            
+            SysBlockMap *bm = 
+                dynamic_cast<SysBlockMap *>(file->GetSegment( segment ));
+
+            for( chan_index = 0; chan_index < channel_count; chan_index++ )
+            {
+                bm->CreateVirtualImageFile( pixels, lines, blocksize, blocksize,
+                                            channel_types[chan_index], 
+                                            compression );
+            }
         }
-    }
 
 /* -------------------------------------------------------------------- */
 /*      If we have a non-tiled FILE interleaved file, should we         */
 /*      create external band files now?                                 */
 /* -------------------------------------------------------------------- */
-    if( STARTS_WITH(interleaving, "FILE") 
-        && !STARTS_WITH(options.c_str(), "TILED") 
-        && !nocreate )
-    {
-        for( chan_index = 0; chan_index < channel_count; chan_index++ )
+        if( STARTS_WITH(interleaving, "FILE") 
+            && !STARTS_WITH(options.c_str(), "TILED") 
+            && !nocreate )
         {
-            PCIDSKChannel *channel = file->GetChannel( chan_index + 1 );
-            int pixel_size = DataTypeSize(channel->GetType());
-
-            // build a band filename that uses the basename of the PCIDSK
-            // file, and adds ".nnn" based on the band. 
-            std::string band_filename = filename;
-            char ext[5];
-            snprintf( ext, sizeof(ext), ".%03d", chan_index+1 );
-            
-            size_t last_dot = band_filename.find_last_of(".");
-            if( last_dot != std::string::npos 
-                && (band_filename.find_last_of("/\\:") == std::string::npos
-                    || band_filename.find_last_of("/\\:") < last_dot) )
+            for( chan_index = 0; chan_index < channel_count; chan_index++ )
             {
-                band_filename.resize( last_dot );
+                PCIDSKChannel *channel = file->GetChannel( chan_index + 1 );
+                int pixel_size = DataTypeSize(channel->GetType());
+
+                // build a band filename that uses the basename of the PCIDSK
+                // file, and adds ".nnn" based on the band. 
+                std::string band_filename = filename;
+                char ext[5];
+                CPLsnprintf( ext, sizeof(ext), ".%03d", chan_index+1 );
+
+                size_t last_dot = band_filename.find_last_of(".");
+                if( last_dot != std::string::npos 
+                    && (band_filename.find_last_of("/\\:") == std::string::npos
+                        || band_filename.find_last_of("/\\:") < last_dot) )
+                {
+                    band_filename.resize( last_dot );
+                }
+
+                band_filename += ext;
+
+                // Now build a version without a path. 
+                std::string relative_band_filename;
+                size_t path_div = band_filename.find_last_of( "/\\:" );
+                if( path_div == std::string::npos )
+                    relative_band_filename = band_filename;
+                else
+                    relative_band_filename = band_filename.c_str() + path_div + 1;
+                
+                // create the file - ought we write the whole file?
+                void *band_io_handle = interfaces->io->Open( band_filename, "w" );
+                interfaces->io->Write( "\0", 1, 1, band_io_handle );
+                interfaces->io->Close( band_io_handle );
+
+                // Set the channel header information.
+                channel->SetChanInfo( relative_band_filename, 0, pixel_size, 
+                                    pixel_size * pixels, true );
             }
-
-            band_filename += ext;
-
-            // Now build a version without a path. 
-            std::string relative_band_filename;
-            size_t path_div = band_filename.find_last_of( "/\\:" );
-            if( path_div == std::string::npos )
-                relative_band_filename = band_filename;
-            else
-                relative_band_filename = band_filename.c_str() + path_div + 1;
-            
-            // create the file - ought we write the whole file?
-            void *band_io_handle = interfaces->io->Open( band_filename, "w" );
-            interfaces->io->Write( "\0", 1, 1, band_io_handle );
-            interfaces->io->Close( band_io_handle );
-
-            // Set the channel header information.
-            channel->SetChanInfo( relative_band_filename, 0, pixel_size, 
-                                  pixel_size * pixels, true );
         }
     }
+    catch( const PCIDSKException& )
+    {
+        delete file;
+        throw;
+    }
 
     return file;
 }
diff --git a/frmts/pcidsk/sdk/core/pcidskexception.cpp b/frmts/pcidsk/sdk/core/pcidskexception.cpp
index 6badee9..6e63773 100644
--- a/frmts/pcidsk/sdk/core/pcidskexception.cpp
+++ b/frmts/pcidsk/sdk/core/pcidskexception.cpp
@@ -67,6 +67,13 @@ should be caught like this:
 /*                          PCIDSKException()                           */
 /************************************************************************/
 
+#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
+
+
 /**
  * Create exception with formatted message.
  *
@@ -87,6 +94,10 @@ PCIDSKException::PCIDSKException( const char *fmt, ... )
     va_end( args );
 }
 
+#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
+#pragma clang diagnostic pop
+#endif
+
 /************************************************************************/
 /*                          ~PCIDSKException()                          */
 /************************************************************************/
@@ -167,14 +178,20 @@ void PCIDSKException::vPrintf( const char *fmt, std::va_list args )
                || nPR == -1 )
         {
             nWorkBufferSize *= 4;
-            pszWorkBuffer = (char *) realloc(pszWorkBuffer, 
-                                             nWorkBufferSize );
+            char* pszWorkBufferNew = (char *) realloc(pszWorkBuffer, 
+                                                      nWorkBufferSize );
 #ifdef va_copy
             va_end( wrk_args );
             va_copy( wrk_args, args );
 #else
             wrk_args = args;
 #endif
+            if( pszWorkBufferNew == NULL )
+            {
+                strcpy( pszWorkBuffer, "(message too large)" );
+                break;
+            }
+            pszWorkBuffer = pszWorkBufferNew;
         }
         message = pszWorkBuffer;
         free( pszWorkBuffer );
@@ -195,6 +212,12 @@ void PCIDSKException::vPrintf( const char *fmt, std::va_list args )
  * @return a pointer to the internal message associated with the exception.
  */ 
 
+#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
+
 /**
  * \brief throw a formatted exception.
  *
@@ -219,6 +242,11 @@ void PCIDSK::ThrowPCIDSKException( const char *fmt, ... )
     throw ex;
 }
 
+#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
+#pragma clang diagnostic pop
+#endif
+
+
 int PCIDSK::ThrowPCIDSKException( int /*ret_unused*/, const char *fmt, ... )
 
 {
diff --git a/frmts/pcidsk/sdk/core/sysvirtualfile.cpp b/frmts/pcidsk/sdk/core/sysvirtualfile.cpp
index c8e8f1f..442b3fc 100644
--- a/frmts/pcidsk/sdk/core/sysvirtualfile.cpp
+++ b/frmts/pcidsk/sdk/core/sysvirtualfile.cpp
@@ -116,7 +116,7 @@ uint16 SysVirtualFile::GetBlockSegment( int requested_block )
                               requested_block );
 
     if( requested_block >= blocks_loaded )
-        LoadBMEntrysTo( requested_block );
+        LoadBMEntriesTo( requested_block );
 
     if( regular_blocks )
         // regular blocks are all in one segment.
@@ -137,7 +137,7 @@ int SysVirtualFile::GetBlockIndexInSegment( int requested_block )
                               requested_block );
 
     if( requested_block >= blocks_loaded )
-        LoadBMEntrysTo( requested_block );
+        LoadBMEntriesTo( requested_block );
 
     if( regular_blocks )
         // regular blocks all follow the first block in order.
@@ -201,7 +201,7 @@ void SysVirtualFile::SetBlockInfo( int requested_block,
     while( (int) xblock_segment.size() < blocks_loaded )
     {
         xblock_segment.push_back( xblock_segment[0] );
-        xblock_index.push_back( xblock_index[xblock_index.size()-1]+1 );
+        xblock_index.push_back( xblock_index.back()+1 );
     }
 
     xblock_segment.push_back( new_block_segment );
@@ -274,7 +274,7 @@ void SysVirtualFile::ReadFromFile( void *buffer, uint64 offset, uint64 size )
 
     uint64 buffer_offset = 0;
 #if 0
-    printf("Requesting region at %llu of size %llu\n", offset, size);
+    printf("Requesting region at %llu of size %llu\n", offset, size);/*ok*/
 #endif
     while( buffer_offset < size )
     {
@@ -342,7 +342,7 @@ void SysVirtualFile::LoadBlock( int requested_block )
 /* -------------------------------------------------------------------- */
 /*      Load the requested block.                                       */
 /* -------------------------------------------------------------------- */
-    LoadBMEntrysTo( requested_block );
+    LoadBMEntriesTo( requested_block );
     PCIDSKSegment *data_seg_obj =
         file->GetSegment( GetBlockSegment( requested_block ) );
     if( data_seg_obj == NULL )
@@ -386,7 +386,7 @@ void SysVirtualFile::FlushDirtyBlock(void)
 /************************************************************************/
 void SysVirtualFile::GrowVirtualFile(std::ptrdiff_t requested_block)
 {
-    LoadBMEntrysTo( static_cast<int>(requested_block) );
+    LoadBMEntriesTo( static_cast<int>(requested_block) );
 
     if( requested_block == blocks_loaded )
     {
@@ -435,7 +435,7 @@ void SysVirtualFile::WriteBlocks(int first_block,
     std::size_t blocks_written = 0;
     std::size_t current_first_block = first_block;
     while (blocks_written < (std::size_t) block_count) {
-        LoadBMEntrysTo( static_cast<int>(current_first_block+1) );
+        LoadBMEntriesTo( static_cast<int>(current_first_block+1) );
 
         unsigned int cur_segment = GetBlockSegment( static_cast<int>(current_first_block) );
         unsigned int cur_block = static_cast<unsigned int>(current_first_block);
@@ -443,7 +443,7 @@ void SysVirtualFile::WriteBlocks(int first_block,
                (unsigned int) GetBlockSegment(cur_block + 1) == cur_segment)
         {
             cur_block++;
-            LoadBMEntrysTo( static_cast<int>(current_first_block+1) );
+            LoadBMEntriesTo( static_cast<int>(current_first_block+1) );
         }
         
         // Find largest span of contiguous blocks we can write
@@ -501,7 +501,7 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
     
     while (blocks_read < (unsigned int)requested_block_count) {
         // Coalesce blocks that are in the same segment
-        LoadBMEntrysTo( current_start+1 );
+        LoadBMEntriesTo( current_start+1 );
         unsigned int cur_segment = GetBlockSegment(current_start); // segment of current
                 // first block
         unsigned int cur_block = current_start; // starting block ID
@@ -510,7 +510,7 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
             // this block is in the same segment as the previous one we
             // wanted to read.
             cur_block++;
-            LoadBMEntrysTo( cur_block+1 );
+            LoadBMEntriesTo( cur_block+1 );
         }
         
         // now attempt to determine if the region of blocks (from current_start
@@ -533,7 +533,7 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
             GrowVirtualFile(i + current_start);
         }
 
-        printf("Coalescing the read of %d blocks\n", count_to_read);
+        printf("Coalescing the read of %d blocks\n", count_to_read);/*ok*/
 #endif
 
         // Perform the actual read
@@ -543,7 +543,7 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
         std::size_t data_size = block_size * count_to_read;
 
 #if 0
-        printf("Reading %d bytes at offset %d in buffer\n", data_size, buffer_off);
+        printf("Reading %d bytes at offset %d in buffer\n", data_size, buffer_off);/*ok*/
 #endif
 
         data_seg_obj->ReadFromFile( ((uint8*)buffer) + buffer_off,
@@ -568,7 +568,7 @@ void SysVirtualFile::LoadBlocks(int requested_block_start,
 /*      are available.                                                  */
 /************************************************************************/
 
-void SysVirtualFile::LoadBMEntrysTo( int target_index )
+void SysVirtualFile::LoadBMEntriesTo( int target_index )
 
 {
     if( target_index > 0 )
diff --git a/frmts/pcidsk/sdk/core/sysvirtualfile.h b/frmts/pcidsk/sdk/core/sysvirtualfile.h
index 7fbd059..23b873a 100644
--- a/frmts/pcidsk/sdk/core/sysvirtualfile.h
+++ b/frmts/pcidsk/sdk/core/sysvirtualfile.h
@@ -106,7 +106,7 @@ namespace PCIDSK
         void                   FlushDirtyBlock();
         void                   WriteBlocks(int first_block, int block_count,
                                            void* const buffer);
-        void                   LoadBMEntrysTo( int block_index );
+        void                   LoadBMEntriesTo( int block_index );
     };
 }
 
diff --git a/frmts/pcidsk/sdk/pcidsk_array.h b/frmts/pcidsk/sdk/pcidsk_array.h
index 75beab4..5d4fd07 100644
--- a/frmts/pcidsk/sdk/pcidsk_array.h
+++ b/frmts/pcidsk/sdk/pcidsk_array.h
@@ -41,15 +41,15 @@ namespace PCIDSK
     class PCIDSK_DLL PCIDSK_ARRAY
     {
     public:
-        virtual	~PCIDSK_ARRAY() {}
+        virtual ~PCIDSK_ARRAY() {}
 
         //ARRAY functions
-        virtual	unsigned char GetDimensionCount() const =0;
-        virtual	void SetDimensionCount(unsigned char nDim) =0;
-        virtual	const std::vector<unsigned int>& GetSizes() const =0;
-        virtual	void SetSizes(const std::vector<unsigned int>& oSizes) =0;
-        virtual	const std::vector<double>& GetArray() const =0;
-        virtual	void SetArray(const std::vector<double>& oArray) =0;
+        virtual unsigned char GetDimensionCount() const =0;
+        virtual void SetDimensionCount(unsigned char nDim) =0;
+        virtual const std::vector<unsigned int>& GetSizes() const =0;
+        virtual void SetSizes(const std::vector<unsigned int>& oSizes) =0;
+        virtual const std::vector<double>& GetArray() const =0;
+        virtual void SetArray(const std::vector<double>& oArray) =0;
     };
 } // end namespace PCIDSK
 
diff --git a/frmts/pcidsk/sdk/pcidsk_buffer.h b/frmts/pcidsk/sdk/pcidsk_buffer.h
index b96e96c..cc306be 100644
--- a/frmts/pcidsk/sdk/pcidsk_buffer.h
+++ b/frmts/pcidsk/sdk/pcidsk_buffer.h
@@ -48,7 +48,7 @@ namespace PCIDSK
         PCIDSKBuffer( const char *src, int size );
         ~PCIDSKBuffer();
 
-        char	*buffer;
+        char        *buffer;
         int         buffer_size;
 
         PCIDSKBuffer &operator=(const PCIDSKBuffer& src);
diff --git a/frmts/pcidsk/sdk/pcidsk_config.h b/frmts/pcidsk/sdk/pcidsk_config.h
index 1b387b9..b6d80a7 100644
--- a/frmts/pcidsk/sdk/pcidsk_config.h
+++ b/frmts/pcidsk/sdk/pcidsk_config.h
@@ -32,6 +32,12 @@
 #include "cpl_port.h"
 #endif
 
+// Compatibility hack for non-C++11 compilers
+#if !(__cplusplus >= 201103L || _MSC_VER >= 1500)
+#define override
+#endif
+
+
 namespace PCIDSK {
 
     typedef unsigned char  uint8;
@@ -93,7 +99,7 @@ namespace PCIDSK {
 #endif
 
 #ifndef GDAL_PCIDSK_DRIVER
-#ifdef PCIDSK_INTERNAL
+#if defined(PCIDSK_INTERNAL) && !defined(ALIAS_CPLSNPRINTF_AS_SNPRINTF)
 #include <stdlib.h>
 extern "C" double CPLAtof(const char*);
 extern "C" int CPLsprintf(char *str, const char* fmt, ...) PCIDSK_PRINT_FUNC_FORMAT(2,3);
diff --git a/frmts/pcidsk/sdk/pcidsk_edb.h b/frmts/pcidsk/sdk/pcidsk_edb.h
index 0a42a96..b32cdc5 100644
--- a/frmts/pcidsk/sdk/pcidsk_edb.h
+++ b/frmts/pcidsk/sdk/pcidsk_edb.h
@@ -59,8 +59,8 @@ namespace PCIDSK
         virtual int WriteBlock( int channel, int block_index, void *buffer) = 0;
     };
 
-    EDBFile PCIDSK_DLL *DefaultOpenEDB(std::string filename, 
-                                       std::string access);    
+    EDBFile PCIDSK_DLL *DefaultOpenEDB(const std::string& filename, 
+                                       const std::string& access);    
 } // end namespace PCIDSK
 
 #endif // INCLUDE_PCIDSK_EDB_H
diff --git a/frmts/pcidsk/sdk/pcidsk_exception.h b/frmts/pcidsk/sdk/pcidsk_exception.h
index b7cd8d0..90e6521 100644
--- a/frmts/pcidsk/sdk/pcidsk_exception.h
+++ b/frmts/pcidsk/sdk/pcidsk_exception.h
@@ -51,7 +51,7 @@ namespace PCIDSK
         virtual ~PCIDSKException() throw();
 
         void vPrintf( const char *fmt, std::va_list list );
-        virtual const char *what() const throw() { return message.c_str(); }
+        virtual const char *what() const throw() override { return message.c_str(); }
     private:
         std::string   message;
     };
diff --git a/frmts/pcidsk/sdk/pcidsk_georef.h b/frmts/pcidsk/sdk/pcidsk_georef.h
index f83e9c2..394c497 100644
--- a/frmts/pcidsk/sdk/pcidsk_georef.h
+++ b/frmts/pcidsk/sdk/pcidsk_georef.h
@@ -48,7 +48,7 @@ namespace PCIDSK
     class PCIDSK_DLL PCIDSKGeoref
     {
     public:
-        virtual	~PCIDSKGeoref() {}
+        virtual ~PCIDSKGeoref() {}
 
 /**
 \brief Get georeferencing transformation.
diff --git a/frmts/pcidsk/sdk/pcidsk_interfaces.h b/frmts/pcidsk/sdk/pcidsk_interfaces.h
index 71dc2b0..2071418 100644
--- a/frmts/pcidsk/sdk/pcidsk_interfaces.h
+++ b/frmts/pcidsk/sdk/pcidsk_interfaces.h
@@ -47,7 +47,7 @@ namespace PCIDSK
 
         const IOInterfaces *io;
 
-        EDBFile           *(*OpenEDB)(std::string filename, std::string access);
+        EDBFile           *(*OpenEDB)(const std::string& filename, const std::string& access);
 
         Mutex             *(*CreateMutex)(void);
 
diff --git a/frmts/pcidsk/sdk/pcidsk_pct.h b/frmts/pcidsk/sdk/pcidsk_pct.h
index d5d235f..7269207 100644
--- a/frmts/pcidsk/sdk/pcidsk_pct.h
+++ b/frmts/pcidsk/sdk/pcidsk_pct.h
@@ -41,12 +41,12 @@ namespace PCIDSK
     class PCIDSK_DLL PCIDSK_PCT
     {
     public:
-        virtual	~PCIDSK_PCT() {}
+        virtual ~PCIDSK_PCT() {}
 
 /**
 \brief Read a PCT Segment (SEG_PCT).
 
- at param pct	 Pseudo-Color Table buffer (768 entries) into which the
+ at param pct  Pseudo-Color Table buffer (768 entries) into which the
 pseudo-color table is read.  It consists of the red gun output
 values (pct[0-255]), followed by the green gun output values (pct[256-511]) 
 and ends with the blue gun output values (pct[512-767]).
@@ -57,7 +57,7 @@ and ends with the blue gun output values (pct[512-767]).
 /**
 \brief Write a PCT Segment.
 
- at param pct	 Pseudo-Color Table buffer (768 entries) from which the
+ at param pct  Pseudo-Color Table buffer (768 entries) from which the
 pseudo-color table is written.  It consists of the red gun output
 values (pct[0-255]), followed by the green gun output values (pct[256-511]) 
 and ends with the blue gun output values (pct[512-767]).
diff --git a/frmts/pcidsk/sdk/pcidsk_segment.h b/frmts/pcidsk/sdk/pcidsk_segment.h
index 585faa7..d964c22 100644
--- a/frmts/pcidsk/sdk/pcidsk_segment.h
+++ b/frmts/pcidsk/sdk/pcidsk_segment.h
@@ -44,7 +44,7 @@ namespace PCIDSK
     class PCIDSKSegment 
     {
     public:
-        virtual	~PCIDSKSegment() {}
+        virtual ~PCIDSKSegment() {}
 
         virtual void Initialize() {}
 
diff --git a/frmts/pcidsk/sdk/pcidsk_shape.h b/frmts/pcidsk/sdk/pcidsk_shape.h
index 9bd8f86..d9deb69 100644
--- a/frmts/pcidsk/sdk/pcidsk_shape.h
+++ b/frmts/pcidsk/sdk/pcidsk_shape.h
@@ -108,8 +108,8 @@ namespace PCIDSK
 
         union
         {
-            float	float_val;
-            double	double_val;
+            float       float_val;
+            double      double_val;
             char       *string_val;
             int32       integer_val;
             int32      *integer_list_val;
@@ -211,7 +211,7 @@ namespace PCIDSK
                 v.integer_list_val = (int32*)
                     malloc(sizeof(int32) * (val.size()+1) );
                 v.integer_list_val[0] = static_cast<int>(val.size());
-                if( val.size() > 0 )
+                if( !val.empty() )
                     memcpy( v.integer_list_val+1, &(val[0]), 
                             sizeof(int32) * val.size() ); 
             }
diff --git a/frmts/pcidsk/sdk/pcidsk_tex.h b/frmts/pcidsk/sdk/pcidsk_tex.h
index 4956a00..d11c183 100644
--- a/frmts/pcidsk/sdk/pcidsk_tex.h
+++ b/frmts/pcidsk/sdk/pcidsk_tex.h
@@ -41,7 +41,7 @@ namespace PCIDSK
     class PCIDSK_DLL PCIDSK_TEX
     {
     public:
-        virtual	~PCIDSK_TEX() {}
+        virtual ~PCIDSK_TEX() {}
 
 /**
 \brief Read a text segment (SEG_TEX).
diff --git a/frmts/pcidsk/sdk/pcidsk_vectorsegment.h b/frmts/pcidsk/sdk/pcidsk_vectorsegment.h
index 9cf8ae4..11d58bb 100644
--- a/frmts/pcidsk/sdk/pcidsk_vectorsegment.h
+++ b/frmts/pcidsk/sdk/pcidsk_vectorsegment.h
@@ -75,10 +75,10 @@ for large vector segments.
 
 */
 
-    class PCIDSK_DLL PCIDSKVectorSegment
-    {
+class PCIDSK_DLL PCIDSKVectorSegment
+{
     public:
-        virtual	~PCIDSKVectorSegment() {}
+        virtual ~PCIDSKVectorSegment() {}
 
 /**
 \brief Fetch RST. 
diff --git a/frmts/pcidsk/sdk/port/io_stdio.cpp b/frmts/pcidsk/sdk/port/io_stdio.cpp
index 6e8a113..ea9d2a6 100644
--- a/frmts/pcidsk/sdk/port/io_stdio.cpp
+++ b/frmts/pcidsk/sdk/port/io_stdio.cpp
@@ -36,14 +36,14 @@ using namespace PCIDSK;
 
 class StdioIOInterface : public IOInterfaces
 {
-    virtual void   *Open( std::string filename, std::string access ) const;
-    virtual uint64  Seek( void *io_handle, uint64 offset, int whence ) const;
-    virtual uint64  Tell( void *io_handle ) const;
-    virtual uint64  Read( void *buffer, uint64 size, uint64 nmemb, void *io_hanle ) const;
-    virtual uint64  Write( const void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const;
-    virtual int     Eof( void *io_handle ) const;
-    virtual int     Flush( void *io_handle ) const;
-    virtual int     Close( void *io_handle ) const;
+    virtual void   *Open( std::string filename, std::string access ) const override;
+    virtual uint64  Seek( void *io_handle, uint64 offset, int whence ) const override;
+    virtual uint64  Tell( void *io_handle ) const override;
+    virtual uint64  Read( void *buffer, uint64 size, uint64 nmemb, void *io_hanle ) const override;
+    virtual uint64  Write( const void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const override;
+    virtual int     Eof( void *io_handle ) const override;
+    virtual int     Flush( void *io_handle ) const override;
+    virtual int     Close( void *io_handle ) const override;
 
     const char     *LastError() const;
 };
diff --git a/frmts/pcidsk/sdk/port/io_win32.cpp b/frmts/pcidsk/sdk/port/io_win32.cpp
index d24c93d..10c8805 100644
--- a/frmts/pcidsk/sdk/port/io_win32.cpp
+++ b/frmts/pcidsk/sdk/port/io_win32.cpp
@@ -38,14 +38,14 @@ using namespace PCIDSK;
 
 class Win32IOInterface : public IOInterfaces
 {
-    virtual void   *Open( std::string filename, std::string access ) const;
-    virtual uint64  Seek( void *io_handle, uint64 offset, int whence ) const;
-    virtual uint64  Tell( void *io_handle ) const;
-    virtual uint64  Read( void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const;
-    virtual uint64  Write( const void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const;
-    virtual int     Eof( void *io_handle ) const;
-    virtual int     Flush( void *io_handle ) const;
-    virtual int     Close( void *io_handle ) const;
+    virtual void   *Open( std::string filename, std::string access ) const override;
+    virtual uint64  Seek( void *io_handle, uint64 offset, int whence ) const override;
+    virtual uint64  Tell( void *io_handle ) const override;
+    virtual uint64  Read( void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const override;
+    virtual uint64  Write( const void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const override;
+    virtual int     Eof( void *io_handle ) const override;
+    virtual int     Flush( void *io_handle ) const override;
+    virtual int     Close( void *io_handle ) const override;
 
     const char     *LastError() const;
 };
@@ -159,8 +159,8 @@ Win32IOInterface::Seek( void *io_handle, uint64 offset, int whence ) const
                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
                        (LPTSTR) &lpMsgBuf, 0, NULL );
  
-        printf( "[ERROR %d]\n %s\n", GetLastError(), (char *) lpMsgBuf );
-        printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n", 
+        printf( "[ERROR %d]\n %s\n", GetLastError(), (char *) lpMsgBuf );/*ok*/
+        printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n", /*ok*/
                 (GUInt32) nOffset, nMoveLow, dwMoveHigh );
 #endif
         ThrowPCIDSKException( "Seek(%d,%d): %s (%d)", 
@@ -276,7 +276,6 @@ uint64 Win32IOInterface::Write( const void *buffer, uint64 size, uint64 nmemb,
 int Win32IOInterface::Eof( void *io_handle ) const
 
 {
-    FileInfo *fi = (FileInfo *) io_handle;
     uint64       nCur, nEnd;
 
     nCur = Tell( io_handle );
diff --git a/frmts/pcidsk/sdk/port/pthread_mutex.cpp b/frmts/pcidsk/sdk/port/pthread_mutex.cpp
index d034cba..bcac448 100644
--- a/frmts/pcidsk/sdk/port/pthread_mutex.cpp
+++ b/frmts/pcidsk/sdk/port/pthread_mutex.cpp
@@ -45,8 +45,8 @@ public:
     PThreadMutex();
     ~PThreadMutex();
 
-    int Acquire(void);
-    int Release(void);
+    int Acquire(void) override;
+    int Release(void) override;
 };
 
 /************************************************************************/
diff --git a/frmts/pcidsk/sdk/port/win32_mutex.cpp b/frmts/pcidsk/sdk/port/win32_mutex.cpp
index 52c0a4a..561673b 100644
--- a/frmts/pcidsk/sdk/port/win32_mutex.cpp
+++ b/frmts/pcidsk/sdk/port/win32_mutex.cpp
@@ -45,8 +45,8 @@ public:
     Win32Mutex();
     ~Win32Mutex();
 
-    int Acquire(void);
-    int Release(void);
+    int Acquire(void) override;
+    int Release(void) override;
 };
 
 /************************************************************************/
diff --git a/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp b/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp
index 8ba560c..d3331be 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidsk_array.cpp
@@ -100,7 +100,7 @@ void CPCIDSK_ARRAY::Load()
             std::string oMsg = oStream.str();
             return ThrowPCIDSKException("%s", oMsg.c_str());
         }
-		moSizes.push_back( nSize );
+        moSizes.push_back( nSize );
     }
 
     //calculate the total number of elements in the array.
diff --git a/frmts/pcidsk/sdk/segment/cpcidsk_array.h b/frmts/pcidsk/sdk/segment/cpcidsk_array.h
index ec25673..8a59f38 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsk_array.h
+++ b/frmts/pcidsk/sdk/segment/cpcidsk_array.h
@@ -52,15 +52,15 @@ namespace PCIDSK
         virtual     ~CPCIDSK_ARRAY();
 
         // CPCIDSK_ARRAY
-        unsigned char GetDimensionCount() const ;
-        void SetDimensionCount(unsigned char nDim) ;
-        const std::vector<unsigned int>& GetSizes() const ;
-        void SetSizes(const std::vector<unsigned int>& oSizes) ;
-        const std::vector<double>& GetArray() const ;
-        void SetArray(const std::vector<double>& oArray) ;
+        unsigned char GetDimensionCount() const override ;
+        void SetDimensionCount(unsigned char nDim) override ;
+        const std::vector<unsigned int>& GetSizes() const override ;
+        void SetSizes(const std::vector<unsigned int>& oSizes) override ;
+        const std::vector<double>& GetArray() const override ;
+        void SetArray(const std::vector<double>& oArray) override ;
 
         //synchronize the segment on disk.
-        void Synchronize();
+        void Synchronize() override;
     private:
 
         //Headers are not supported by PCIDSK, we keep the function
diff --git a/frmts/pcidsk/sdk/segment/cpcidsk_tex.h b/frmts/pcidsk/sdk/segment/cpcidsk_tex.h
index a898f9b..9026ddf 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsk_tex.h
+++ b/frmts/pcidsk/sdk/segment/cpcidsk_tex.h
@@ -53,8 +53,8 @@ namespace PCIDSK
 
         // PCIDSK_TEX
 
-        std::string ReadText();
-        void WriteText( const std::string &text );
+        std::string ReadText() override;
+        void WriteText( const std::string &text ) override;
     };
 } // end namespace PCIDSK
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskads40model.h b/frmts/pcidsk/sdk/segment/cpcidskads40model.h
index b912346..b4b5912 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskads40model.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskads40model.h
@@ -41,12 +41,12 @@ namespace PCIDSK {
         ~CPCIDSKADS40ModelSegment();
         
         // Get path
-        std::string GetPath(void) const;
+        std::string GetPath(void) const override;
         // Set path
-        void SetPath(const std::string& oPath);
+        void SetPath(const std::string& oPath) override;
 
         //synchronize the segment on disk.
-        void Synchronize();
+        void Synchronize() override;
     private:
         // Helper housekeeping functions
         void Load();
diff --git a/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp b/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp
index 611d190..da09a3f 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskapmodel.cpp
@@ -291,8 +291,11 @@ std::vector<double> const& CPCIDSKAPModelSegment::GetProjParams(void) const
 }
 
 /************************************************************************/
-/*                        BinaryToAPInfo()                          	*/
+/*                        BinaryToAPInfo()                              */
 /************************************************************************/
+
+namespace {
+  
 /**
   * Convert the contents of the PCIDSKBuffer buf to a set of APModel
   * params
@@ -307,7 +310,6 @@ std::vector<double> const& CPCIDSKAPModelSegment::GetProjParams(void) const
   * @param map_units the map units/geosys string
   * @param utm_units the UTM units string
   */
-namespace {
     void BinaryToAPInfo(PCIDSKBuffer& buf,
                         PCIDSKAPModelEOParams*& eo_params,
                         PCIDSKAPModelIOParams*& io_params,
@@ -324,7 +326,7 @@ namespace {
         map_units.clear();
         utm_units.clear();
     /* -------------------------------------------------------------------- */
-    /*	Read the header block						    */
+    /*  Read the header block                                               */
     /* -------------------------------------------------------------------- */
     
         if(!STARTS_WITH(buf.buffer,"APMODEL "))
@@ -339,10 +341,9 @@ namespace {
     /* -------------------------------------------------------------------- */
 
         downsample = buf.GetInt(24, 3);
-        if (0 >= downsample) downsample = 0;
 
     /* -------------------------------------------------------------------- */
-    /*      Read the values					            */
+    /*      Read the values                                                 */
     /* -------------------------------------------------------------------- */
         pixels = buf.GetInt(0 * 22 + 512, 22);
         lines = buf.GetInt(1 * 22 + 512, 22);
@@ -462,7 +463,7 @@ namespace {
 
 
     /* -------------------------------------------------------------------- */
-    /*      Read the projection required					*/
+    /*      Read the projection required                                    */
     /* -------------------------------------------------------------------- */
         buf.Get(512 * 4, 16, map_units);
     
diff --git a/frmts/pcidsk/sdk/segment/cpcidskapmodel.h b/frmts/pcidsk/sdk/segment/cpcidskapmodel.h
index a29a142..1e533f0 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskapmodel.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskapmodel.h
@@ -44,22 +44,22 @@ namespace PCIDSK {
             
         ~CPCIDSKAPModelSegment();
 
-        unsigned int GetWidth(void) const;
-        unsigned int GetHeight(void) const;
-        unsigned int GetDownsampleFactor(void) const;
+        unsigned int GetWidth(void) const override;
+        unsigned int GetHeight(void) const override;
+        unsigned int GetDownsampleFactor(void) const override;
 
         // Interior Orientation Parameters
-        PCIDSKAPModelIOParams const& GetInteriorOrientationParams(void) const;
+        PCIDSKAPModelIOParams const& GetInteriorOrientationParams(void) const override;
         
         // Exterior Orientation Parameters
-        PCIDSKAPModelEOParams const& GetExteriorOrientationParams(void) const;
+        PCIDSKAPModelEOParams const& GetExteriorOrientationParams(void) const override;
 
         // ProjInfo
-        PCIDSKAPModelMiscParams const& GetAdditionalParams(void) const;
+        PCIDSKAPModelMiscParams const& GetAdditionalParams(void) const override;
         
-        std::string GetMapUnitsString(void) const;
-        std::string GetUTMUnitsString(void) const;
-        std::vector<double> const& GetProjParams(void) const;
+        std::string GetMapUnitsString(void) const override;
+        std::string GetUTMUnitsString(void) const override;
+        std::vector<double> const& GetProjParams(void) const override;
 
     private:
         void UpdateFromDisk();
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h
index 48a26e4..cf481ca 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskbinarysegment.h
@@ -41,20 +41,20 @@ namespace PCIDSK {
             const char *segment_pointer, bool bLoad=true);
         ~CPCIDSKBinarySegment();
 
-        const char* GetBuffer(void) const
+        const char* GetBuffer(void) const override
         {
             return seg_data.buffer;
         }
 
-        unsigned int GetBufferSize(void) const
+        unsigned int GetBufferSize(void) const override
         {
             return seg_data.buffer_size;
         }
         void SetBuffer(const char* pabyBuf, 
-            unsigned int nBufSize);
+            unsigned int nBufSize) override;
 
         //synchronize the segment on disk.
-        void Synchronize();
+        void Synchronize() override;
     private:
         
         // Helper housekeeping functions
diff --git a/frmts/pcidsk/sdk/segment/cpcidskbitmap.h b/frmts/pcidsk/sdk/segment/cpcidskbitmap.h
index 5f4494e..be5757b 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskbitmap.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskbitmap.h
@@ -51,52 +51,52 @@ namespace PCIDSK
         CPCIDSKBitmap(PCIDSKFile *file,int segment,const char*segment_pointer);
         virtual     ~CPCIDSKBitmap();
 
-        virtual void Initialize();
+        virtual void Initialize() override;
 
         // Channel interface
-        virtual int GetBlockWidth() const;
-        virtual int GetBlockHeight() const;
-        virtual int GetBlockCount() const;
-        virtual int GetWidth() const;
-        virtual int GetHeight() const;
-        virtual eChanType GetType() const;
+        virtual int GetBlockWidth() const override;
+        virtual int GetBlockHeight() const override;
+        virtual int GetBlockCount() const override;
+        virtual int GetWidth() const override;
+        virtual int GetHeight() const override;
+        virtual eChanType GetType() const override;
         virtual int ReadBlock( int block_index, void *buffer,
             int win_xoff=-1, int win_yoff=-1,
-            int win_xsize=-1, int win_ysize=-1 );
-        virtual int WriteBlock( int block_index, void *buffer );
-        virtual int GetOverviewCount();
-        virtual PCIDSKChannel *GetOverview( int i );
-        virtual bool IsOverviewValid( int i );
-        virtual std::string GetOverviewResampling( int i );
-        virtual void SetOverviewValidity( int i, bool validity );
-        virtual std::vector<int> GetOverviewLevelMapping() const;
-
-        virtual std::string GetMetadataValue( const std::string &key ) const;
-        virtual void SetMetadataValue( const std::string &key, const std::string &value );
-        virtual std::vector<std::string> GetMetadataKeys() const;
-
-        virtual void Synchronize();
-
-        virtual std::string GetDescription();
-        virtual void SetDescription( const std::string &description );
-
-        virtual std::vector<std::string> GetHistoryEntries() const;
-        virtual void SetHistoryEntries( const std::vector<std::string> &entries );
+            int win_xsize=-1, int win_ysize=-1 ) override;
+        virtual int WriteBlock( int block_index, void *buffer ) override;
+        virtual int GetOverviewCount() override;
+        virtual PCIDSKChannel *GetOverview( int i ) override;
+        virtual bool IsOverviewValid( int i ) override;
+        virtual std::string GetOverviewResampling( int i ) override;
+        virtual void SetOverviewValidity( int i, bool validity ) override;
+        virtual std::vector<int> GetOverviewLevelMapping() const override;
+
+        virtual std::string GetMetadataValue( const std::string &key ) const override;
+        virtual void SetMetadataValue( const std::string &key, const std::string &value ) override;
+        virtual std::vector<std::string> GetMetadataKeys() const override;
+
+        virtual void Synchronize() override;
+
+        virtual std::string GetDescription() override;
+        virtual void SetDescription( const std::string &description ) override;
+
+        virtual std::vector<std::string> GetHistoryEntries() const override;
+        virtual void SetHistoryEntries( const std::vector<std::string> &entries ) override;
         virtual void PushHistory(const std::string &app,
-                                 const std::string &message);
+                                 const std::string &message) override;
 
         virtual void GetChanInfo( std::string &filename, uint64 &image_offset, 
                                   uint64 &pixel_offset, uint64 &line_offset, 
-                                  bool &little_endian ) const;
+                                  bool &little_endian ) const override;
         virtual void SetChanInfo( std::string filename, uint64 image_offset, 
                                   uint64 pixel_offset, uint64 line_offset, 
-                                  bool little_endian );
+                                  bool little_endian ) override;
         virtual void GetEChanInfo( std::string &filename, int &echannel,
                                    int &exoff, int &eyoff, 
-                                   int &exsize, int &eysize ) const;
+                                   int &exsize, int &eysize ) const override;
         virtual void SetEChanInfo( std::string filename, int echannel,
                                    int exoff, int eyoff, 
-                                   int exsize, int eysize );
+                                   int exsize, int eysize ) override;
 
     private:
         bool      loaded;
diff --git a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp
index fdbc750..1be7704 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.cpp
@@ -142,9 +142,9 @@ void CPCIDSKEphemerisSegment::Synchronize()
 }
 
 /************************************************************************/
-/*			ConvertDeg()					*/
+/*                              ConvertDeg()                            */
 /************************************************************************/
-/**									
+/**
  * if mode is 0, convert angle from 0 to 360 to 0 to 180 and 0 to -180 
  * if mode is 1, convert angle from 0 to 180 and 0 to -180 to 0 to 360 
  *
@@ -158,28 +158,28 @@ double CPCIDSKEphemerisSegment::ConvertDeg(double degree, int mode)
     if (mode == 0)
     {
 /* -------------------------------------------------------------------- */
-/*	degree is in range of 0 to 360					*/
+/*      degree is in range of 0 to 360                                  */
 /* -------------------------------------------------------------------- */
-	if (degree > 180)
-	    result = degree - 360;
-	else
-	    result = degree;
+        if (degree > 180)
+            result = degree - 360;
+        else
+            result = degree;
     }
     else
     {
 /* -------------------------------------------------------------------- */
-/*	degree is in range of 0 to 180 and 0 to -180			*/
+/*      degree is in range of 0 to 180 and 0 to -180                    */
 /* -------------------------------------------------------------------- */
-	if (degree < 0)
-	    result = 360 + degree;
-	else
-	    result = degree;
+        if (degree < 0)
+            result = 360 + degree;
+        else
+            result = degree;
     }
     return (result);
 }
 
 /************************************************************************/
-/*		      ReadAvhrrEphemerisSegment()                       */
+/*                      ReadAvhrrEphemerisSegment()                     */
 /************************************************************************/
 /**
  *  Read the contents of blocks 9, 11, and onwards from the orbit
@@ -197,7 +197,7 @@ CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
 
     int nDataLength = seg_data.buffer_size;
 /* -------------------------------------------------------------------- */
-/*  Allocate the AVHRR segment portion of EphemerisSeg_t.		*/
+/*  Allocate the AVHRR segment portion of EphemerisSeg_t.               */
 /* -------------------------------------------------------------------- */
     psEphSegRec->AvhrrSeg = new AvhrrSeg_t();
     as = psEphSegRec->AvhrrSeg;
@@ -248,7 +248,7 @@ CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
     as->szSemiMajorAxis = seg_data.Get(nPos+464,16);
                                                                       
 /* -------------------------------------------------------------------- */
-/*  Skip the 10th block which is reserved for future use.		*/
+/*  Skip the 10th block which is reserved for future use.               */
 /* -------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------- */
@@ -274,7 +274,7 @@ CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
     nBlock = 12;
 
     if ( as->nNumRecordsPerBlock == 0 )
-	return;
+        return;
 
     for(nLine = 0; nLine < as->nNumScanlineRecords;
                    nLine += as->nNumRecordsPerBlock)
@@ -282,10 +282,10 @@ CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
         int nNumRecords = MinFunction(as->nNumRecordsPerBlock,
                                       as->nNumScanlineRecords - nLine);
         nPos = nStartBlock + 512*(nBlock-1);
-	if( nDataLength < 512*nBlock )
-	{
-	    break;
-	}
+        if( nDataLength < 512*nBlock )
+        {
+            break;
+        }
      
         for(int i = 0; i < nNumRecords; ++i)
         {
@@ -299,11 +299,11 @@ CPCIDSKEphemerisSegment::ReadAvhrrEphemerisSegment(int nStartBlock,
 }
 
 /************************************************************************/
-/*		        ReadAvhrrScanlineRecord()                       */
+/*                      ReadAvhrrScanlineRecord()                       */
 /************************************************************************/
 /**                                                                      
  *  Read from a byte buffer in order to set a scanline record.     
- * @param pbyBuf the buffer that contains the record to read.
+ * @param nPos position in buffer
  * @param psScanlineRecord the record to read.
  */
 void 
@@ -337,7 +337,7 @@ CPCIDSKEphemerisSegment::ReadAvhrrScanlineRecord(int nPos,
 }
 
 /************************************************************************/
-/*			   ReadAvhrrInt32()                             */
+/*                         ReadAvhrrInt32()                             */
 /************************************************************************/
 /**                                                                      
  * Read an integer from a given buffer of at least 4 bytes. 
@@ -355,7 +355,7 @@ CPCIDSKEphemerisSegment::ReadAvhrrInt32(unsigned char* pbyBuf)
 }
 
 /************************************************************************/
-/*		      WriteAvhrrEphemerisSegment()                      */
+/*                    WriteAvhrrEphemerisSegment()                      */
 /************************************************************************/
 /**
  *  Write the contents of blocks 9, 10, and onwards to the orbit
@@ -370,14 +370,14 @@ CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
     int  nBlock = 0, nLine = 0;
     int nPos = 0;
 /* -------------------------------------------------------------------- */
-/*  Check that the AvhrrSeg is not NULL.				*/
+/*  Check that the AvhrrSeg is not NULL.                                */
 /* -------------------------------------------------------------------- */
     AvhrrSeg_t *as = NULL;
     as = psEphSegRec->AvhrrSeg;
 
     if ( as == NULL)
     {
-	return ThrowPCIDSKException("The AvhrrSeg is NULL.");
+        return ThrowPCIDSKException("The AvhrrSeg is NULL.");
     }
 
 /* -------------------------------------------------------------------- */
@@ -394,7 +394,7 @@ CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
     memset(seg_data.buffer+nPos,' ',nToAdd);
 
 /* -------------------------------------------------------------------- */
-/*  Write the first avhrr Block.					*/
+/*  Write the first avhrr Block.                                        */
 /* -------------------------------------------------------------------- */
 
     seg_data.Put(as->szImageFormat.c_str(),nPos,16);
@@ -439,7 +439,7 @@ CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
     seg_data.Put(as->szSemiMajorAxis.c_str(),nPos+464,16,true);
 
 /* -------------------------------------------------------------------- */
-/*  second avhrr block is all zeros.					*/
+/*  second avhrr block is all zeros.                                    */
 /* -------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------- */
@@ -456,13 +456,13 @@ CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
 /* -------------------------------------------------------------------- */
 /*  Write the fourth avhrr block onwards.                               */
 /* -------------------------------------------------------------------- */
-    if ( as->Line.size() == 0 )
-	return;
+    if ( as->Line.empty() )
+        return;
 
     nBlock = 4;
 
     if ( as->nNumRecordsPerBlock == 0 )
-	return;
+        return;
 
     for(nLine = 0; nLine < as->nNumScanlineRecords;
                    nLine += as->nNumRecordsPerBlock)
@@ -481,12 +481,12 @@ CPCIDSKEphemerisSegment::WriteAvhrrEphemerisSegment(int nStartBlock,
 }
 
 /************************************************************************/
-/*  		   WriteAvhrrScanlineRecord()                           */
+/*                       WriteAvhrrScanlineRecord()                     */
 /************************************************************************/
 /**                                                                      
  * Write a scanline record to a byte buffer.  
  * @param psScanlineRecord the record to write
- * @param pbyBuf the buffer to write.
+ * @param nPos position in buffer
  */
 void 
 CPCIDSKEphemerisSegment::WriteAvhrrScanlineRecord(
@@ -522,7 +522,7 @@ CPCIDSKEphemerisSegment::WriteAvhrrScanlineRecord(
 }
 
 /************************************************************************/
-/*			   WriteAvhrrInt32()                            */
+/*                         WriteAvhrrInt32()                            */
 /************************************************************************/
 /**                                                                      
  * Write an integer into a given buffer of at least 4 bytes.            
@@ -555,20 +555,20 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
 
 {
     EphemerisSeg_t *l_segment;
-    int		i;
+    int             i;
     int nPos = nStartBlock;
 
     l_segment = new EphemerisSeg_t();
 
 /* -------------------------------------------------------------------- */
-/*	Process first block.						*/
+/*      Process first block.                                            */
 /* -------------------------------------------------------------------- */
 
     l_segment->SatelliteDesc = seg_data.Get(nPos+8,32);  
     l_segment->SceneID = seg_data.Get(nPos+40, 32);
 
 /* -------------------------------------------------------------------- */
-/*	Process the second block.					*/
+/*      Process the second block.                                       */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 512;
 
@@ -600,7 +600,7 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
     l_segment->TimeInterval = seg_data.GetDouble(nPos+242, 22);
     l_segment->NumLineCentre = seg_data.GetDouble(nPos+264, 22);
     l_segment->LongCentre = seg_data.GetDouble(nPos+286, 22);
-    l_segment->AngularSpd = seg_data.GetDouble(nPos+308, 22);		
+    l_segment->AngularSpd = seg_data.GetDouble(nPos+308, 22);
     l_segment->AscNodeLong = seg_data.GetDouble(nPos+330, 22);
     l_segment->ArgPerigee = seg_data.GetDouble(nPos+352, 22);
     l_segment->LatCentre = seg_data.GetDouble(nPos+374, 22);
@@ -613,7 +613,7 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
         l_segment->bDescending = false;
 
 /* -------------------------------------------------------------------- */
-/*	Process the third block.					*/
+/*      Process the third block.                                        */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 2*512;
 
@@ -714,8 +714,8 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
     }
 
 /* -------------------------------------------------------------------- */
-/*	6th and 7th block of ORBIT l_segment are blank.			*/
-/*	Read in the 8th block.						*/
+/*      6th and 7th block of ORBIT l_segment are blank.                 */
+/*      Read in the 8th block.                                          */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 7*512;
     
@@ -732,18 +732,18 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
                               seg_data.Get(nPos,8));
 
 /* -------------------------------------------------------------------- */
-/*	Orbit l_segment is a Satellite Attitude Segment(ATTITUDE) only	*/
-/*	for SPOT 1A.							*/
+/*      Orbit l_segment is a Satellite Attitude Segment(ATTITUDE) only  */
+/*      for SPOT 1A.                                                    */
 /* -------------------------------------------------------------------- */
     if (l_segment->Type == OrbAttitude)
     {
-        AttitudeSeg_t 	*AttitudeSeg;
-        int		nBlock, nData;
+        AttitudeSeg_t  *AttitudeSeg;
+        int             nBlock, nData;
 
         AttitudeSeg = l_segment->AttitudeSeg = new AttitudeSeg_t();  
-	
+
 /* -------------------------------------------------------------------- */
-/*	Read in the 9th block.						*/
+/*      Read in the 9th block.                                          */
 /* -------------------------------------------------------------------- */
         nPos = nStartBlock + 512*8;
         
@@ -759,22 +759,22 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
                 AttitudeSeg->NumberOfLine / ATT_SEG_LINE_PER_BLOCK;
 
 /* -------------------------------------------------------------------- */
-/*	Read in the line required.					*/
+/*      Read in the line required.                                      */
 /* -------------------------------------------------------------------- */
         for (nBlock=0, nData=0; nBlock<AttitudeSeg->NumberBlockData; 
              nBlock++)
         {
 /* -------------------------------------------------------------------- */
-/*	Read in 10+nBlock th block as required.				*/
+/*      Read in 10+nBlock th block as required.                         */
 /* -------------------------------------------------------------------- */
             nPos = nStartBlock + 512*(9+nBlock);
 
 /* -------------------------------------------------------------------- */
-/*	Fill in the lines as required.					*/
+/*      Fill in the lines as required.                                  */
 /* -------------------------------------------------------------------- */
             for (i=0; 
                  i<ATT_SEG_LINE_PER_BLOCK 
-		     && nData < AttitudeSeg->NumberOfLine; 
+                    && nData < AttitudeSeg->NumberOfLine; 
                  i++, nData++)
             {
                 AttitudeLine_t oAttitudeLine;
@@ -795,16 +795,16 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
         }
     }
 /* -------------------------------------------------------------------- */
-/*	Radar l_segment (LATLONG)						*/
+/*      Radar l_segment (LATLONG)                                       */
 /* -------------------------------------------------------------------- */
     else if (l_segment->Type == OrbLatLong)
     {
         RadarSeg_t *RadarSeg;
-        int	nBlock, nData;
+        int         nBlock, nData;
 
         RadarSeg = l_segment->RadarSeg = new RadarSeg_t(); 
 /* -------------------------------------------------------------------- */
-/*	Read in the 9th block.						*/
+/*      Read in the 9th block.                                          */
 /* -------------------------------------------------------------------- */
         nPos = nStartBlock + 512*8;
 
@@ -820,7 +820,7 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
         RadarSeg->ClockAngle = seg_data.GetDouble(nPos+128, 16);
 
 /* -------------------------------------------------------------------- */
-/*	Read in the 10th block.						*/
+/*      Read in the 10th block.                                         */
 /* -------------------------------------------------------------------- */
         nPos = nStartBlock + 9*512;
 
@@ -828,14 +828,14 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
         RadarSeg->NumberData = seg_data.GetInt(nPos+8, 8);
 
 /* -------------------------------------------------------------------- */
-/* 	Read in the 11-th through 11+RadarSeg->NumberBlockData th block	*/
-/*	for the ancillary data present.					*/
+/*      Read in the 11-th through 11+RadarSeg->NumberBlockData th block */
+/*      for the ancillary data present.                                 */
 /* -------------------------------------------------------------------- */
         for (nBlock = 0, nData = 0; 
              nBlock < RadarSeg->NumberBlockData; nBlock++)
         {
 /* -------------------------------------------------------------------- */
-/*	Read in one block of data.					*/
+/*      Read in one block of data.                                      */
 /* -------------------------------------------------------------------- */
             nPos = nStartBlock + 512*(10+nBlock);
 
@@ -843,15 +843,15 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
                  i<ANC_DATA_PER_BLK &&  nData < RadarSeg->NumberData; 
                  i++, nData++)
             {
-                int	offset;
-                char	*currentindex;
-                void	*currentptr;
-                double	tmp;
-                int32	tmpInt;
+                int     offset;
+                char   *currentindex;
+                void   *currentptr;
+                double  tmp;
+                int32   tmpInt;
                 const double million = 1000000.0;
                 
 /* -------------------------------------------------------------------- */
-/*	Reading in one ancillary data at a time.			*/
+/*      Reading in one ancillary data at a time.                        */
 /* -------------------------------------------------------------------- */
                 AncillaryData_t oData;
                 offset = i*ANC_DATA_SIZE;
@@ -923,13 +923,13 @@ CPCIDSKEphemerisSegment::BinaryToEphemeris( int nStartBlock )
         if (RadarSeg->NumberData != nData)
         {
             return (EphemerisSeg_t*)ThrowPCIDSKExceptionPtr("Number "
-		     "of data lines read (%d) does not match with"
+                     "of data lines read (%d) does not match with"
                      "\nwhat is specified in l_segment (%d).\n", nData, 
                      RadarSeg->NumberData);
         }
     }
 /* -------------------------------------------------------------------- */
-/*	AVHRR l_segment 							*/
+/*      AVHRR l_segment                                                 */
 /* -------------------------------------------------------------------- */
     else if (l_segment->Type == OrbAvhrr)
     {
@@ -954,7 +954,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
                                               int nStartBlock )
 
 {
-    int		i,j;
+    int i,j;
 
 /* -------------------------------------------------------------------- */
 /*      The binary data must be at least 8 blocks (4096 bytes) long     */
@@ -966,7 +966,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
     int nPos = nStartBlock;
 
 /* -------------------------------------------------------------------- */
-/*	Write the first block						*/
+/*      Write the first block                                           */
 /* -------------------------------------------------------------------- */
 
     seg_data.Put("ORBIT   ",nPos,8);
@@ -974,7 +974,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
     seg_data.Put(psOrbit->SceneID.c_str(), nPos+40,32,true);
 
 /* -------------------------------------------------------------------- */
-/*	Write the second block						*/
+/*      Write the second block                                          */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 1*512;
     
@@ -1012,7 +1012,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
         seg_data.Put("ASCENDING ",nPos+484,10);
 
 /* -------------------------------------------------------------------- */
-/*	Write the third block						*/
+/*      Write the third block                                           */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 512*2;
 
@@ -1048,7 +1048,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
     seg_data.Put(psOrbit->UtmYLL,nPos+479,22,"%22.14f");
 
 /* -------------------------------------------------------------------- */
-/*	Write the fourth block						*/
+/*      Write the fourth block                                          */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 512*3;
     
@@ -1069,7 +1069,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
     seg_data.Put(psOrbit->HtLL,nPos+224,22,"%16.7f");
 
 /* -------------------------------------------------------------------- */
-/*	Write the fifth block						*/
+/*      Write the fifth block                                           */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 512*4;
 
@@ -1081,36 +1081,36 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
     seg_data.Put(psOrbit->NumberSuffixBytes,nPos+80,16);
 
 /* -------------------------------------------------------------------- */
-/*	Write the sixth and seventh block (blanks)			*/
-/*	For SPOT it is not blank					*/
+/*      Write the sixth and seventh block (blanks)                      */
+/*      For SPOT it is not blank                                        */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 512*5;
 
     if (psOrbit->SPNCoeff > 0)
     {
         if (psOrbit->SPNCoeff == 20)
-	{
+        {
             seg_data.Put("SPOT1BOD",nPos,8);
             seg_data.Put(psOrbit->SPNCoeff,nPos+22,22);
 
-	    j = 44;
-	    for (i=0; i<20; i++)
-	    {
+            j = 44;
+            for (i=0; i<20; i++)
+            {
                 seg_data.Put(psOrbit->SPCoeff1B[i],
-                                     nPos+j,22,"%22.14f");
-		j += 22;
-	    }
-	}
-	else
-	{
+                                    nPos+j,22,"%22.14f");
+                j += 22;
+            }
+        }
+        else
+        {
             seg_data.Put("SPOT1BNW",nPos,8);
             seg_data.Put(psOrbit->SPNCoeff,nPos+22,22);
 
-	    j = 44;
+            j = 44;
             for (i=0; i<20; i++)
             {
                 seg_data.Put(psOrbit->SPCoeff1B[i],
-                                     nPos+j,22,"%22.14f");
+                                    nPos+j,22,"%22.14f");
                 j += 22;
             }
 
@@ -1132,7 +1132,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
     } 
 
 /* -------------------------------------------------------------------- */
-/*	Write the eighth block.						*/
+/*      Write the eighth block.                                         */
 /* -------------------------------------------------------------------- */
     nPos = nStartBlock + 512*7;
     
@@ -1150,13 +1150,13 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
     }
 
 /* ==================================================================== */
-/*	Orbit segment is a Satellite Attitude Segment(ATTITUDE) only	*/
-/*	for SPOT 1A.							*/
+/*      Orbit segment is a Satellite Attitude Segment(ATTITUDE) only    */
+/*      for SPOT 1A.                                                    */
 /* ==================================================================== */
     if (psOrbit->Type == OrbAttitude)
     {
         AttitudeSeg_t *AttitudeSeg;
-        int		nBlock, nData;
+        int            nBlock, nData;
 
         AttitudeSeg = psOrbit->AttitudeSeg;
 
@@ -1202,7 +1202,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
                512 * AttitudeSeg->NumberBlockData);
 
 /* -------------------------------------------------------------------- */
-/*	Write out the line required.					*/
+/*      rite out the line required.                                     */
 /* -------------------------------------------------------------------- */
         for (nBlock=0, nData=0; nBlock<AttitudeSeg->NumberBlockData; 
              nBlock++)
@@ -1210,12 +1210,12 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
             nPos = nStartBlock + 512*(nBlock + 9);
 
 /* -------------------------------------------------------------------- */
-/*	Fill in buffer as required.					*/
+/*      Fill in buffer as required.                                     */
 /* -------------------------------------------------------------------- */
             for (i=0; 
-                 i<ATT_SEG_LINE_PER_BLOCK 
-		     && nData < AttitudeSeg->NumberOfLine; 
-                 i++, nData++)
+                i<ATT_SEG_LINE_PER_BLOCK 
+                    && nData < AttitudeSeg->NumberOfLine; 
+                i++, nData++)
             {
                 seg_data.Put(
                     AttitudeSeg->Line[nData].ChangeInAttitude,
@@ -1229,19 +1229,19 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
         if (nData != AttitudeSeg->NumberOfLine)
         {
             return ThrowPCIDSKException("Number of data line written"
-		    " (%d) does not match with\nwhat is specified "
-		    " in the segment (%d).\n", 
-		    nData, AttitudeSeg->NumberOfLine);
+                    " (%d) does not match with\nwhat is specified "
+                    " in the segment (%d).\n", 
+                    nData, AttitudeSeg->NumberOfLine);
         }
     }
 
 /* ==================================================================== */
-/*	Radar segment (LATLONG)						*/
+/*      Radar segment (LATLONG)                                         */
 /* ==================================================================== */
     else if (psOrbit->Type == OrbLatLong)
     {
         RadarSeg_t *RadarSeg;
-        int	   nBlock, nData;
+        int         nBlock, nData;
 
         RadarSeg = psOrbit->RadarSeg;
 
@@ -1273,7 +1273,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
         seg_data.Put(RadarSeg->ClockAngle,nPos+128,16,"%16.7f");
 
 /* -------------------------------------------------------------------- */
-/*	Write out the tenth block.					*/
+/*      Write out the tenth block.                                      */
 /* -------------------------------------------------------------------- */
         nPos = nStartBlock + 512*9;
 
@@ -1291,8 +1291,8 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
                512 * RadarSeg->NumberBlockData);
         
 /* -------------------------------------------------------------------- */
-/* 	Write out the 11-th through 11+psOrbit->NumberBlockData  block	*/
-/*	for the ancillary data present.					*/
+/*      Write out the 11-th through 11+psOrbit->NumberBlockData  block  */
+/*      for the ancillary data present.                                 */
 /* -------------------------------------------------------------------- */
         for (nBlock = 0, nData = 0; 
              nBlock < RadarSeg->NumberBlockData; nBlock++)
@@ -1301,19 +1301,19 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
                  i<ANC_DATA_PER_BLK &&  nData < RadarSeg->NumberData;
                  i++, nData++)
             {
-                int		offset;
-                char		*currentptr, *currentindex;
-                double		tmp, tmpDouble;
+                int             offset;
+                char            *currentptr, *currentindex;
+                double          tmp, tmpDouble;
                 const double million = 1000000.0;
-                int32		tmpInt;
+                int32           tmpInt;
                 
 /* -------------------------------------------------------------------- */
-/*	Point to correct block						*/
+/*      Point to correct block                                          */
 /* -------------------------------------------------------------------- */
                 nPos = nStartBlock + 512*(10+nBlock);
             
 /* -------------------------------------------------------------------- */
-/*	Writing out one ancillary data at a time.			*/
+/*      Writing out one ancillary data at a time.                       */
 /* -------------------------------------------------------------------- */
                 offset = i*ANC_DATA_SIZE;
 
@@ -1381,7 +1381,7 @@ CPCIDSKEphemerisSegment::EphemerisToBinary( EphemerisSeg_t * psOrbit,
     }
 
 /* ==================================================================== */
-/*	AVHRR segment 							*/
+/*      AVHRR segment                                                   */
 /* ==================================================================== */
     else if ( psOrbit->Type == OrbAvhrr &&
               psOrbit->AvhrrSeg->nNumRecordsPerBlock > 0 )
diff --git a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h
index 00e51bf..7cf72a5 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskephemerissegment.h
@@ -40,11 +40,11 @@ namespace PCIDSK {
         CPCIDSKEphemerisSegment(PCIDSKFile *file, int segment,const char *segment_pointer,bool bLoad=true);
         ~CPCIDSKEphemerisSegment();
 
-        const EphemerisSeg_t& GetEphemeris() const
+        const EphemerisSeg_t& GetEphemeris() const override
         {
             return *mpoEphemeris;
         };
-        void SetEphemeris(const EphemerisSeg_t& oEph)
+        void SetEphemeris(const EphemerisSeg_t& oEph) override
         {
             if(mpoEphemeris)
             {
@@ -55,7 +55,7 @@ namespace PCIDSK {
         };
 
         //synchronize the segment on disk.
-        void Synchronize();
+        void Synchronize() override;
     private:
         
         // Helper housekeeping functions
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp
index a68fde2..cf67f22 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.cpp
@@ -190,7 +190,7 @@ void CPCIDSKGCP2Segment::RebuildSegmentData(void)
     
     // This will have to change when we have proper projections support
 
-    if (pimpl_->gcps.size() > 0)
+    if (!pimpl_->gcps.empty())
     {
         pimpl_->gcps[0].GetMapUnits(pimpl_->map_units, 
             pimpl_->proj_parms);
@@ -275,8 +275,8 @@ void CPCIDSKGCP2Segment::RebuildSegmentData(void)
         pimpl_->seg_data.Put((*iter).GetYErr(), offset + 136, 14, "%14.4e");
         pimpl_->seg_data.Put((*iter).GetIDString(), offset + 192, 64, true );
         
-        id++;
-        iter++;
+        ++id;
+        ++iter;
     }
     
     WriteToFile(pimpl_->seg_data.buffer, 0, pimpl_->seg_data.buffer_size);
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h
index b7cc2bf..82d782c 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskgcp2segment.h
@@ -40,17 +40,17 @@ namespace PCIDSK {
         ~CPCIDSKGCP2Segment();
 
         // Return all GCPs in the segment
-        std::vector<PCIDSK::GCP> const& GetGCPs(void) const;
+        std::vector<PCIDSK::GCP> const& GetGCPs(void) const override;
         
         // Write the given GCPs to the segment. If the segment already
         // exists, it will be replaced with this one.
-        void SetGCPs(std::vector<PCIDSK::GCP> const& gcps);
+        void SetGCPs(std::vector<PCIDSK::GCP> const& gcps) override;
         
         // Return the count of GCPs in the segment
-        unsigned int GetGCPCount(void) const;
+        unsigned int GetGCPCount(void) const override;
         
         // Clear a GCP Segment
-        void ClearGCPs(void);
+        void ClearGCPs(void) override;
     private:
         void Load();
         void RebuildSegmentData(void);
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp b/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp
index 05bb731..310e707 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskgeoref.cpp
@@ -411,9 +411,9 @@ std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosysIn )
 /*      Extract the earth model from the geosys string.                 */
 /* -------------------------------------------------------------------- */
     char earthmodel[5];
-    const char	*cp;
-    int		i;
-    char	last;
+    const char *cp;
+    int         i;
+    char        last;
 
     cp = local_buf;
     while( cp < local_buf + 16 && cp[1] != '\0' )
@@ -500,7 +500,7 @@ std::string CPCIDSKGeoref::ReformatGeosys( std::string const& geosysIn )
                      zone, zone_code, earthmodel );
         }
         else
-        {	
+        {
             snprintf( local_buf, sizeof(local_buf), 
                      "UTM         %4s", 
                      earthmodel );
@@ -820,7 +820,7 @@ C
 C
 C       EXAMPLE
 C
-C       double		degrees, packed, unpack 
+C       double              degrees, packed, unpack 
 C
 C       degrees = -125.425              ! Same as 125d 25' 30" W
 C       packed = PACK2PCI (degrees, 1)  ! PACKED will equal -125025030.000
@@ -837,22 +837,22 @@ static double PAK2PCI( double deg, int function )
         int       sign;
         double    result;
 
-	double	  degrees;
+        double    degrees;
         double    temp1, temp2, temp3;
         int       dd, mm;
-        double	  ss;
+        double    ss;
 
-        sign = (int)(1.0);
-	degrees = deg;
+        sign = 1;
+        degrees = deg;
 
         if ( degrees < 0 )
         {
-           sign = (int)(-1.0);
+           sign = -1;
            degrees = degrees * sign;
         }
 
 /* -------------------------------------------------------------------- */
-/*	Unpack the value.						*/
+/*      Unpack the value.                                               */
 /* -------------------------------------------------------------------- */
         if ( function == 0 )
         {
@@ -872,7 +872,7 @@ static double PAK2PCI( double deg, int function )
         else
         {
 /* -------------------------------------------------------------------- */
-/*	Procduce DDDMMMSSS.SSS from decimal degrees.			*/
+/*      Procduce DDDMMMSSS.SSS from decimal degrees.                    */
 /* -------------------------------------------------------------------- */
            new_deg = (double) ((int)degrees % 360);
            temp1 =  degrees - new_deg;
@@ -887,7 +887,7 @@ static double PAK2PCI( double deg, int function )
            result = (double) sign *
                 ( (new_deg * 1000000) + (mm * 1000) + ss);
         }
-	return result;
+        return result;
 }
 
 /************************************************************************/
@@ -1001,9 +1001,9 @@ void CPCIDSKGeoref::PrepareGCTPFields()
 
     for ( i = 0; i < 15; i++ )
         USGSParms[i] = 0;
-	
+
 /* -------------------------------------------------------------------- */
-/*	Projection 0: Geographic (no projection)			*/
+/*      Projection 0: Geographic (no projection)                        */
 /* -------------------------------------------------------------------- */
     if( STARTS_WITH(geosys_clean.c_str(), "LON") 
         || STARTS_WITH(geosys_clean.c_str(), "LAT") )
@@ -1013,7 +1013,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
     }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 1: Universal Transverse Mercator			*/
+/*      Projection 1: Universal Transverse Mercator                     */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "UTM ") )
     {
@@ -1027,9 +1027,9 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         }
 
 /* -------------------------------------------------------------------- */
-/*	Process UTM as TM.  The reason for this is the GCTP software	*/
-/*	does not provide for input of an Earth Model for UTM, but does	*/
-/*	for TM.								*/
+/*      Process UTM as TM.  The reason for this is the GCTP software    */
+/*      does not provide for input of an Earth Model for UTM, but does  */
+/*      for TM.                                                         */
 /* -------------------------------------------------------------------- */
         gsys = 9;
         USGSParms[0] = Dearth0;
@@ -1044,7 +1044,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
     }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 2: State Plane Coordinate System			*/
+/*      Projection 2: State Plane Coordinate System                     */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "SPCS ") )
     {
@@ -1074,7 +1074,7 @@ void CPCIDSKGeoref::PrepareGCTPFields()
     }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 3: Albers Conical Equal-Area 			*/
+/*      Projection 3: Albers Conical Equal-Area                         */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "ACEA ") )
     {
@@ -1087,10 +1087,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 4: Lambert Conformal Conic				*/ 
+/*      Projection 4: Lambert Conformal Conic                           */ 
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "LCC  ") )
     {
@@ -1103,10 +1103,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 5: Mercator						*/ 
+/*      Projection 5: Mercator                                          */ 
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "MER  ") )
     {
@@ -1118,10 +1118,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 6: Polar Stereographic		 		*/
+/*      Projection 6: Polar Stereographic                               */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "PS   ") )
     {
@@ -1133,10 +1133,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 7: Polyconic			 			*/
+/*      Projection 7: Polyconic                                         */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "PC   ") )
     {
@@ -1148,12 +1148,12 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 8: Equidistant Conic                     		*/
-/*	Format A, one standard parallel,  usgs_params[8] = 0		*/
-/*      Format B, two standard parallels, usgs_params[8] = not 0	*/
+/*      Projection 8: Equidistant Conic                                 */
+/*      Format A, one standard parallel,  usgs_params[8] = 0            */
+/*      Format B, two standard parallels, usgs_params[8] = not 0        */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "EC   ") )
     {
@@ -1171,10 +1171,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         {
             USGSParms[8] = 1;
         }
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 9: Transverse Mercator				*/ 
+/*      Projection 9: Transverse Mercator                               */ 
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "TM   ") )
     {
@@ -1187,10 +1187,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 10: Stereographic					*/
+/*      Projection 10: Stereographic                                    */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "SG   ") )
     {
@@ -1201,10 +1201,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
     
 /* -------------------------------------------------------------------- */
-/*	Projection 11: Lambert Azimuthal Equal-Area			*/
+/*      Projection 11: Lambert Azimuthal Equal-Area                     */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "LAEA ") )
     {
@@ -1216,10 +1216,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 12: Azimuthal Equidistant				*/
+/*      Projection 12: Azimuthal Equidistant                            */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "AE   ") )
     {
@@ -1230,10 +1230,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 13: Gnomonic						*/
+/*      Projection 13: Gnomonic                                         */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "GNO  ") )
     {
@@ -1244,10 +1244,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 14: Orthographic					*/ 
+/*      Projection 14: Orthographic                                     */ 
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "OG   ") )
     {
@@ -1258,10 +1258,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection  15: General Vertical Near-Side Perspective		*/
+/*      Projection  15: General Vertical Near-Side Perspective          */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "GVNP ") )
     {
@@ -1274,10 +1274,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-      }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 16: Sinusoidal 					*/
+/*      Projection 16: Sinusoidal                                       */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "SIN  ") )
     {
@@ -1286,10 +1286,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[4] = PAK2PCI(RefLong, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 17: Equirectangular					*/
+/*      Projection 17: Equirectangular                                  */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "ER   ") )
     {
@@ -1299,9 +1299,9 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         USGSParms[5] = PAK2PCI(RefLat, 1);
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 /* -------------------------------------------------------------------- */
-/*	Projection 18: Miller Cylindrical				*/
+/*      Projection 18: Miller Cylindrical                               */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "MC   ") )
     {
@@ -1312,10 +1312,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 19: Van der Grinten					*/
+/*      Projection 19: Van der Grinten                                  */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "VDG  ") )
     {
@@ -1326,14 +1326,14 @@ void CPCIDSKGeoref::PrepareGCTPFields()
         
         USGSParms[6] = FalseEasting * IOmultiply;
         USGSParms[7] = FalseNorthing * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 20:  Oblique Mercator (Hotine)			*/
-/*	  Format A, Azimuth and RefLong defined (Long1, Lat1,      	*/
-/*	     Long2, Lat2 not defined), usgs_params[12] = 0      	*/
-/*	  Format B, Long1, Lat1, Long2, Lat2 defined (Azimuth		*/
-/*	     and RefLong not defined), usgs_params[12] = not 0      	*/
+/*      Projection 20:  Oblique Mercator (Hotine)                       */
+/*        Format A, Azimuth and RefLong defined (Long1, Lat1,           */
+/*           Long2, Lat2 not defined), usgs_params[12] = 0              */
+/*        Format B, Long1, Lat1, Long2, Lat2 defined (Azimuth           */
+/*           and RefLong not defined), usgs_params[12] = not 0          */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "OM   ") )
     {
@@ -1357,9 +1357,9 @@ void CPCIDSKGeoref::PrepareGCTPFields()
             USGSParms[12] = 0.0;
         else
             USGSParms[12] = 1.0;
-    }	
+    }
 /* -------------------------------------------------------------------- */
-/*	Projection 21: Robinson						*/
+/*      Projection 21: Robinson                                         */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "ROB  ") )
     {
@@ -1372,9 +1372,9 @@ void CPCIDSKGeoref::PrepareGCTPFields()
           USGSParms[7] = FalseNorthing
               * IOmultiply;
 
-      }	
+      }
 /* -------------------------------------------------------------------- */
-/*	Projection 22: Space Oblique Mercator				*/
+/*      Projection 22: Space Oblique Mercator                           */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "SOM  ") )
     {
@@ -1387,9 +1387,9 @@ void CPCIDSKGeoref::PrepareGCTPFields()
               * IOmultiply;
           USGSParms[7] = FalseNorthing
               * IOmultiply;
-    }	
+    }
 /* -------------------------------------------------------------------- */
-/*	Projection 23: Modified Stereographic Conformal (Alaska)	*/ 
+/*      Projection 23: Modified Stereographic Conformal (Alaska)        */ 
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "MSC  ") )
     {
@@ -1400,11 +1400,11 @@ void CPCIDSKGeoref::PrepareGCTPFields()
               * IOmultiply;
           USGSParms[7] = FalseNorthing
               * IOmultiply;
-    }	
+    }
 
 /* -------------------------------------------------------------------- */
-/*	Projection 6: Universal Polar Stereographic is just Polar	*/
-/*	Stereographic with certain assumptions.				*/
+/*      Projection 6: Universal Polar Stereographic is just Polar       */
+/*      Stereographic with certain assumptions.                         */
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH(geosys_clean.c_str(), "UPS  ") )
     {
@@ -1437,10 +1437,10 @@ void CPCIDSKGeoref::PrepareGCTPFields()
               USGSParms[7] = FalseNorthing
                   * IOmultiply;
           }
-      }	
+      }
 
 /* -------------------------------------------------------------------- */
-/*	Unknown code.							*/
+/*      Unknown code.                                                   */
 /* -------------------------------------------------------------------- */
     else
     {
diff --git a/frmts/pcidsk/sdk/segment/cpcidskgeoref.h b/frmts/pcidsk/sdk/segment/cpcidskgeoref.h
index a9c9c59..ac3c89f 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskgeoref.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskgeoref.h
@@ -53,20 +53,20 @@ namespace PCIDSK
 
         // PCIDSKSegment 
 
-        void        Initialize();
+        void        Initialize() override;
 
         // PCIDSKGeoref
 
         void        GetTransform( double &a1, double &a2, double &xrot, 
-                                  double &b1, double &yrot, double &b3 );
-        std::string GetGeosys();
+                                  double &b1, double &yrot, double &b3 ) override;
+        std::string GetGeosys() override;
 
-        std::vector<double> GetParameters();
+        std::vector<double> GetParameters() override;
 
         void        WriteSimple( std::string const& geosys, 
                                  double a1, double a2, double xrot, 
-                                 double b1, double yrot, double b3 );
-        void        WriteParameters( std::vector<double> const& parameters );
+                                 double b1, double yrot, double b3 ) override;
+        void        WriteParameters( std::vector<double> const& parameters ) override;
 
         // special interface just for testing.
         std::vector<double> GetUSGSParameters();
diff --git a/frmts/pcidsk/sdk/segment/cpcidskpct.h b/frmts/pcidsk/sdk/segment/cpcidskpct.h
index 2e18a61..aa3f7f3 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskpct.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskpct.h
@@ -51,8 +51,8 @@ namespace PCIDSK
 
         virtual     ~CPCIDSK_PCT();
 
-        virtual void ReadPCT( unsigned char pct[768] );
-        virtual void WritePCT( unsigned char pct[768] );
+        virtual void ReadPCT( unsigned char pct[768] ) override;
+        virtual void WritePCT( unsigned char pct[768] ) override;
     };
 } // end namespace PCIDSK
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h b/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h
index e1db7c5..3c109fb 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskpolymodel.h
@@ -40,28 +40,28 @@ namespace PCIDSK {
         CPCIDSKPolyModelSegment(PCIDSKFile *file, int segment,const char *segment_pointer);
         ~CPCIDSKPolyModelSegment();
         
-        std::vector<double> GetXForwardCoefficients() const;
-        std::vector<double> GetYForwardCoefficients() const;
-        std::vector<double> GetXBackwardCoefficients() const;
-        std::vector<double> GetYBackwardCoefficients() const;
+        std::vector<double> GetXForwardCoefficients() const override;
+        std::vector<double> GetYForwardCoefficients() const override;
+        std::vector<double> GetXBackwardCoefficients() const override;
+        std::vector<double> GetYBackwardCoefficients() const override;
 
         void SetCoefficients(const std::vector<double>& oXForward,
                              const std::vector<double>& oYForward,
                              const std::vector<double>& oXBackward,
-                             const std::vector<double>& oYBackward) ;
+                             const std::vector<double>& oYBackward) override ;
 
-        unsigned int GetLines() const;
-        unsigned int GetPixels() const;
-        void SetRasterSize(unsigned int nLines,unsigned int nPixels) ;
+        unsigned int GetLines() const override;
+        unsigned int GetPixels() const override;
+        void SetRasterSize(unsigned int nLines,unsigned int nPixels) override ;
 
-        std::string GetGeosysString() const;
-        void SetGeosysString(const std::string& oGeosys) ;
+        std::string GetGeosysString() const override;
+        void SetGeosysString(const std::string& oGeosys) override ;
 
-        std::vector<double> GetProjParmInfo() const;
-        void SetProjParmInfo(const std::vector<double>& oInfo) ;
+        std::vector<double> GetProjParmInfo() const override;
+        void SetProjParmInfo(const std::vector<double>& oInfo) override ;
 
         //synchronize the segment on disk.
-        void Synchronize();
+        void Synchronize() override;
     private:
         // Helper housekeeping functions
         void Load();
diff --git a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h
index 2c077af..859c713 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskrpcmodel.h
@@ -42,20 +42,20 @@ namespace PCIDSK {
         
         // Implementation of PCIDSKRPCSegment
         // Get the X and Y RPC coefficients
-        std::vector<double> GetXNumerator(void) const;
-        std::vector<double> GetXDenominator(void) const;
-        std::vector<double> GetYNumerator(void) const;
-        std::vector<double> GetYDenominator(void) const;
+        std::vector<double> GetXNumerator(void) const override;
+        std::vector<double> GetXDenominator(void) const override;
+        std::vector<double> GetYNumerator(void) const override;
+        std::vector<double> GetYDenominator(void) const override;
         
         // Set the X and Y RPC Coefficients
         void SetCoefficients(const std::vector<double>& xnum,
             const std::vector<double>& xdenom, const std::vector<double>& ynum,
-            const std::vector<double>& ydenom);
+            const std::vector<double>& ydenom) override;
             
         // Get the RPC offset/scale Coefficients
         void GetRPCTranslationCoeffs(double& xoffset, double& xscale,
             double& yoffset, double& yscale, double& zoffset, double& zscale,
-            double& pixoffset, double& pixscale, double& lineoffset, double& linescale) const;
+            double& pixoffset, double& pixscale, double& lineoffset, double& linescale) const override;
             
         // Set the RPC offset/scale Coefficients
         void SetRPCTranslationCoeffs(
@@ -63,55 +63,55 @@ namespace PCIDSK {
             const double yoffset, const double yscale, 
             const double zoffset, const double zscale,
             const double pixoffset, const double pixscale, 
-            const double lineoffset, const double linescale);
+            const double lineoffset, const double linescale) override;
 
         // Get the adjusted X values
-        std::vector<double> GetAdjXValues(void) const;
+        std::vector<double> GetAdjXValues(void) const override;
         // Get the adjusted Y values
-        std::vector<double> GetAdjYValues(void) const;
+        std::vector<double> GetAdjYValues(void) const override;
         
         // Set the adjusted X/Y values
         void SetAdjCoordValues(const std::vector<double>& xcoord,
-            const std::vector<double>& ycoord);
+            const std::vector<double>& ycoord) override;
 
         // Get whether or not this is a user-generated RPC model
-        bool IsUserGenerated(void) const;
+        bool IsUserGenerated(void) const override;
         // Set whether or not this is a user-generated RPC model
-        void SetUserGenerated(bool usergen);
+        void SetUserGenerated(bool usergen) override;
         
         // Get whether the model has been adjusted
-        bool IsNominalModel(void) const;
+        bool IsNominalModel(void) const override;
         // Set whether the model has been adjusted
-        void SetIsNominalModel(bool nominal);
+        void SetIsNominalModel(bool nominal) override;
         
         // Get sensor name
-        std::string GetSensorName(void) const;
+        std::string GetSensorName(void) const override;
         // Set sensor name
-        void SetSensorName(const std::string& name);
+        void SetSensorName(const std::string& name) override;
         
         // Output projection information of RPC Model
         // Get the Geosys String
-        std::string GetGeosysString(void) const;
+        std::string GetGeosysString(void) const override;
         // Set the Geosys string
-        void SetGeosysString(const std::string& geosys);
+        void SetGeosysString(const std::string& geosys) override;
         
         // Get the number of lines
-        unsigned int GetLines(void) const;
+        unsigned int GetLines(void) const override;
         
         // Get the number of pixels
-        unsigned int GetPixels(void) const;
+        unsigned int GetPixels(void) const override;
         
         // Set the number of lines/pixels
-        void SetRasterSize(const unsigned int lines, const unsigned int pixels);
+        void SetRasterSize(const unsigned int lines, const unsigned int pixels) override;
 
         // Set the downsample factor
-        void SetDownsample(const unsigned int downsample);
+        void SetDownsample(const unsigned int downsample) override;
 
         // Get the downsample factor
-        unsigned int GetDownsample(void) const;
+        unsigned int GetDownsample(void) const override;
 
         //synchronize the segment on disk.
-        void Synchronize();
+        void Synchronize() override;
     private:
         // Helper housekeeping functions
         void Load();
diff --git a/frmts/pcidsk/sdk/segment/cpcidsksegment.h b/frmts/pcidsk/sdk/segment/cpcidsksegment.h
index c7557fd..fc6d0f9 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsksegment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidsksegment.h
@@ -54,7 +54,7 @@ namespace PCIDSK
     public:
         CPCIDSKSegment( PCIDSKFile *file, int segment,
             const char *segment_pointer );
-        virtual	~CPCIDSKSegment();
+        virtual ~CPCIDSKSegment();
 
         void        LoadSegmentPointer( const char *segment_pointer );
         void        LoadSegmentHeader();
@@ -62,30 +62,30 @@ namespace PCIDSK
         PCIDSKBuffer &GetHeader() { return header; }
         void        FlushHeader();
 
-        void      WriteToFile( const void *buffer, uint64 offset, uint64 size );
-        void      ReadFromFile( void *buffer, uint64 offset, uint64 size );
+        void      WriteToFile( const void *buffer, uint64 offset, uint64 size ) override;
+        void      ReadFromFile( void *buffer, uint64 offset, uint64 size ) override;
 
-        eSegType    GetSegmentType() { return segment_type; }
-        std::string GetName() { return segment_name; }
-        std::string GetDescription();
-        int         GetSegmentNumber() { return segment; }
-        uint64      GetContentSize() { return data_size - 1024; }
-        bool        IsAtEOF();
+        eSegType    GetSegmentType() override { return segment_type; }
+        std::string GetName() override { return segment_name; }
+        std::string GetDescription() override;
+        int         GetSegmentNumber() override { return segment; }
+        uint64      GetContentSize() override { return data_size - 1024; }
+        bool        IsAtEOF() override;
 
-        void        SetDescription( const std::string &description);
+        void        SetDescription( const std::string &description) override;
         
-        std::string GetMetadataValue( const std::string &key ) const;
-        void        SetMetadataValue( const std::string &key, const std::string &value );
-        std::vector<std::string> GetMetadataKeys() const;
+        std::string GetMetadataValue( const std::string &key ) const override;
+        void        SetMetadataValue( const std::string &key, const std::string &value ) override;
+        std::vector<std::string> GetMetadataKeys() const override;
             
-        virtual void Synchronize() {}
+        virtual void Synchronize() override {}
         
-        std::vector<std::string> GetHistoryEntries() const;
-        void SetHistoryEntries( const std::vector<std::string> &entries );
+        std::vector<std::string> GetHistoryEntries() const override;
+        void SetHistoryEntries( const std::vector<std::string> &entries ) override;
         void PushHistory(const std::string &app,
-                         const std::string &message);
+                         const std::string &message) override;
 
-        virtual std::string ConsistencyCheck() { return ""; }
+        virtual std::string ConsistencyCheck() override { return ""; }
 
     protected:
         PCIDSKFile *file;
@@ -96,7 +96,7 @@ namespace PCIDSK
         char        segment_flag;
         std::string segment_name;
 
-        uint64	    data_offset;     // includes 1024 byte segment header.
+        uint64      data_offset;     // includes 1024 byte segment header.
         uint64      data_size;
 
         PCIDSKBuffer header;
diff --git a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp
index 91647bb..ecb047c 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.cpp
@@ -167,13 +167,13 @@ void CPCIDSKToutinModelSegment::Synchronize()
 SRITInfo_t *
 CPCIDSKToutinModelSegment::BinaryToSRITInfo()
 {
-    int		i,j,k,l;
-    SRITInfo_t 	*SRITModel;
-    bool	bVersion9;
+    int             i,j,k,l;
+    SRITInfo_t     *SRITModel;
+    bool            bVersion9;
 
 /* -------------------------------------------------------------------- */
-/*	Read the header block						*/
-/* -------------------------------------------------------------------- */    
+/*      Read the header block                                           */
+/* -------------------------------------------------------------------- */
     // We test the name of the binary segment before starting to read 
     // the buffer.
     if (!STARTS_WITH(seg_data.buffer, "MODEL   ")) 
@@ -191,7 +191,7 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
     int nVersion = seg_data.GetInt(8,1);
     if (nVersion == 9)
     {
-	bVersion9 = true;
+        bVersion9 = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -203,7 +203,7 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
     SRITModel->nDownSample = 1;
     if(STARTS_WITH(seg_data.Get(22,2) , "DS"))
     {
-	SRITModel->nDownSample = seg_data.GetInt(24,3); 
+        SRITModel->nDownSample = seg_data.GetInt(24,3); 
     }
 
 /* -------------------------------------------------------------------- */
@@ -269,7 +269,7 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Read the GCPs							*/
+/*      Read the GCPs                                                   */
 /* -------------------------------------------------------------------- */
     l = 0;
     k = 4;
@@ -293,18 +293,18 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
     }
      
 /* -------------------------------------------------------------------- */
-/*      Call BinaryToEphemeris to get the orbital data		        */
+/*      Call BinaryToEphemeris to get the orbital data                  */
 /* -------------------------------------------------------------------- */
     SRITModel->OrbitPtr =
         BinaryToEphemeris( 512*21 );
     
 /* -------------------------------------------------------------------- */
-/*      Pass the sensor back to SRITModel				*/
+/*      Pass the sensor back to SRITModel                               */
 /* -------------------------------------------------------------------- */
     SRITModel->Sensor = SRITModel->OrbitPtr->SatelliteSensor;
 
 /* -------------------------------------------------------------------- */
-/*      Assign nSensor value						*/
+/*      Assign nSensor value                                            */
 /* -------------------------------------------------------------------- */
 
     SRITModel->nSensor = GetSensor (SRITModel->OrbitPtr);
@@ -322,7 +322,7 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Get the attitude data for SPOT					*/
+/*      Get the attitude data for SPOT                                  */
 /* -------------------------------------------------------------------- */
     if (SRITModel->OrbitPtr->AttitudeSeg != NULL ||
         SRITModel->OrbitPtr->RadarSeg != NULL)
@@ -367,16 +367,14 @@ CPCIDSKToutinModelSegment::BinaryToSRITInfo()
   * Translate a RFInfo_t into the corresponding block of binary data.
   *
   * @param  SRITModel        Satellite Model structure.
-  * @param  pnBinaryLength   Length of binary data.
-  * @return Binary data for a  Satellite Model structure.
   */
 void
 CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
 
 {
-    int		i,j,k,l;
-    double	dfminht,dfmaxht,dfmeanht;
-    int nPos = 0;
+    int         i,j,k,l;
+    double      dfminht,dfmaxht,dfmeanht;
+    int         nPos = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Create the data array.                                          */
@@ -387,7 +385,7 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
     memset( seg_data.buffer , ' ', 512 * 21 );
 
 /* -------------------------------------------------------------------- */
-/*	Initialize the header.						*/
+/*      Initialize the header.                                          */
 /* -------------------------------------------------------------------- */
     nPos = 512*0;
     seg_data.Put("MODEL   9.0",0,nPos+11);
@@ -443,8 +441,8 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
     }
     else
     {
-	dfminht = SRITModel->dfGCPMinHt;
-	dfmaxht = 0;
+        dfminht = SRITModel->dfGCPMinHt;
+        dfmaxht = 0;
     }
 
     dfmeanht = (dfminht + dfmaxht)/2.;
@@ -459,12 +457,12 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
     {
         if (SRITModel->OrbitPtr->Type == OrbAttitude &&
             SRITModel->OrbitPtr->AttitudeSeg != NULL) 
-	{
-	    if (SRITModel->OrbitPtr->AttitudeSeg->NumberOfLine != 0)
+        {
+            if (SRITModel->OrbitPtr->AttitudeSeg->NumberOfLine != 0)
                 seg_data.Put("3",nPos+20,1);
-	}
+        }
     }
-	
+
     seg_data.Put(SRITModel->GCPUnit.c_str(),nPos+30,16);
     seg_data.Put("M",nPos+49,1);
 
@@ -475,12 +473,12 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
     seg_data.Put("NEWGCP",nPos+116,6);
 
 /* -------------------------------------------------------------------- */
-/*      Write the projection parameter if necessary			*/
+/*      Write the projection parameter if necessary                     */
 /* -------------------------------------------------------------------- */
 
     seg_data.Put(SRITModel->utmunit.c_str(),nPos+225,16);
 
-    if(SRITModel->oProjectionInfo.size() > 0)
+    if(!SRITModel->oProjectionInfo.empty())
     {
         seg_data.Put("ProjInfo: ",nPos+245,10);
         seg_data.Put(SRITModel->oProjectionInfo.c_str(),
@@ -497,7 +495,7 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
     for (j=0; j<SRITModel->nGCPCount; j++)
     {
         if (j > 255)
-	    break;
+            break;
 
         seg_data.Put(SRITModel->nGCPIds[j],nPos+10*l,5);
         seg_data.Put((int)(SRITModel->nPixel[j]+0.5),
@@ -517,7 +515,7 @@ CPCIDSKToutinModelSegment::SRITInfoToBinary( SRITInfo_t *SRITModel )
     }
 
 /* -------------------------------------------------------------------- */
-/*	Add the serialized form of the EphemerisSeg_t.			*/
+/*      Add the serialized form of the EphemerisSeg_t.                  */
 /* -------------------------------------------------------------------- */
     EphemerisToBinary( SRITModel->OrbitPtr , 512*21 );
 }
@@ -619,20 +617,20 @@ int  CPCIDSKToutinModelSegment::GetSensor( EphemerisSeg_t *OrbitPtr)
             nSensor = OV5_MULTI_GEO;
     }
     else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_PAN_STD"))
-        nSensor = QBIRD_PAN_STD; 	// this checking must go first
+        nSensor = QBIRD_PAN_STD;    // this checking must go first
     else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_PAN_STH"))
         nSensor = QBIRD_PAN_STH;
     else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_PAN"))
         nSensor = QBIRD_PAN;
     else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_MULTI_STD"))
-        nSensor = QBIRD_MULTI_STD;	// this checking must go first
+        nSensor = QBIRD_MULTI_STD;  // this checking must go first
     else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_MULTI_STH"))
         nSensor = QBIRD_MULTI_STH;
     else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "QBIRD_MULTI"))
         nSensor = QBIRD_MULTI;
     else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW1_PAN_STD") ||
         STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW_PAN_STD"))
-        nSensor = WVIEW_PAN_STD; 	// this checking must go first
+        nSensor = WVIEW_PAN_STD;    // this checking must go first
     else if (STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW1_PAN") ||
         STARTS_WITH_CI(OrbitPtr->SatelliteSensor.c_str(), "WVIEW_PAN"))
         nSensor = WVIEW_PAN;
diff --git a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h
index 0257d02..51788da 100644
--- a/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h
+++ b/frmts/pcidsk/sdk/segment/cpcidsktoutinmodel.h
@@ -41,11 +41,11 @@ namespace PCIDSK {
         CPCIDSKToutinModelSegment(PCIDSKFile *file, int segment,const char *segment_pointer);
         ~CPCIDSKToutinModelSegment();
 
-        SRITInfo_t GetInfo() const;
-        void SetInfo(const SRITInfo_t& poInfo);
+        SRITInfo_t GetInfo() const override;
+        void SetInfo(const SRITInfo_t& poInfo) override;
 
         //synchronize the segment on disk.
-        void Synchronize();
+        void Synchronize() override;
     private:
         
         // Helper housekeeping functions
diff --git a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp
index 814266e..603a0b7 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.cpp
@@ -870,7 +870,7 @@ void CPCIDSKVectorSegment::PushLoadedIndexIntoMap()
 /* -------------------------------------------------------------------- */
     int loaded_page = shape_index_start / shapeid_page_size;
 
-    if( shapeid_map_active && shape_index_ids.size() > 0 )
+    if( shapeid_map_active && !shape_index_ids.empty() )
     {
         unsigned int i;
 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h
index 2ce8ae2..b884e8d 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h
+++ b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment.h
@@ -62,45 +62,45 @@ namespace PCIDSK
 
         virtual        ~CPCIDSKVectorSegment();
 
-        void            Initialize();
-        void            Synchronize();
+        void            Initialize() override;
+        void            Synchronize() override;
 
-        std::string     GetRst() { return ""; }
-        std::vector<double> GetProjection( std::string &geosys );
+        std::string     GetRst() override { return ""; }
+        std::vector<double> GetProjection( std::string &geosys ) override;
         void            SetProjection(std::string geosys, 
-                                      std::vector<double> parms);
+                                      std::vector<double> parms) override;
 
-        int             GetFieldCount();
-        std::string     GetFieldName(int);
-        std::string     GetFieldDescription(int);
-        ShapeFieldType  GetFieldType(int);
-        std::string     GetFieldFormat(int);
-        ShapeField      GetFieldDefault(int);
+        int             GetFieldCount() override;
+        std::string     GetFieldName(int) override;
+        std::string     GetFieldDescription(int) override;
+        ShapeFieldType  GetFieldType(int) override;
+        std::string     GetFieldFormat(int) override;
+        ShapeField      GetFieldDefault(int) override;
 
-        ShapeIterator   begin() { return ShapeIterator(this); }
-        ShapeIterator   end() { return ShapeIterator(this,NullShapeId); }
+        ShapeIterator   begin() override { return ShapeIterator(this); }
+        ShapeIterator   end() override { return ShapeIterator(this,NullShapeId); }
 
-        ShapeId         FindFirst();
-        ShapeId         FindNext(ShapeId);
+        ShapeId         FindFirst() override;
+        ShapeId         FindNext(ShapeId) override;
 
-        int             GetShapeCount();
+        int             GetShapeCount() override;
         
-        void            GetVertices( ShapeId, std::vector<ShapeVertex>& );
-        void            GetFields( ShapeId, std::vector<ShapeField>& );
+        void            GetVertices( ShapeId, std::vector<ShapeVertex>& ) override;
+        void            GetFields( ShapeId, std::vector<ShapeField>& ) override;
 
         void            AddField( std::string name, ShapeFieldType type,
                                   std::string description,
                                   std::string format,
-                                  ShapeField *default_value );
+                                  ShapeField *default_value ) override;
         
-        ShapeId         CreateShape( ShapeId id );
-        void            DeleteShape( ShapeId id );
+        ShapeId         CreateShape( ShapeId id ) override;
+        void            DeleteShape( ShapeId id ) override;
         void            SetVertices( ShapeId id, 
-                                     const std::vector<ShapeVertex>& list );
+                                     const std::vector<ShapeVertex>& list ) override;
         void            SetFields( ShapeId id, 
-                                   const std::vector<ShapeField>& list );
+                                   const std::vector<ShapeField>& list ) override;
 
-        std::string     ConsistencyCheck();
+        std::string     ConsistencyCheck() override;
 
         // Essentially internal stuff.
         char                *GetData( int section, uint32 offset, 
diff --git a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment_consistencycheck.cpp b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment_consistencycheck.cpp
index feddea9..bf9f5cc 100644
--- a/frmts/pcidsk/sdk/segment/cpcidskvectorsegment_consistencycheck.cpp
+++ b/frmts/pcidsk/sdk/segment/cpcidskvectorsegment_consistencycheck.cpp
@@ -61,7 +61,7 @@ public:
     // binary search for the offset closes to our target or earlier.
     uint32  FindPreceding( uint32 offset )
         {
-            if( offsets.size() == 0 )
+            if( offsets.empty() )
                 return 0;
 
             uint32 start=0, end=static_cast<uint32>(offsets.size())-1;
@@ -85,7 +85,7 @@ public:
             uint32 preceding = FindPreceding( offset );
 
             // special case for empty
-            if( offsets.size() == 0 )
+            if( offsets.empty() )
             {
                 offsets.push_back( offset );
                 sizes.push_back( size );
@@ -93,7 +93,7 @@ public:
             }
                     
             // special case for before first.
-            if( offsets.size() > 0 && offset < offsets[0] )
+            if( !offsets.empty() && offset < offsets[0] )
             {
                 if( offset+size > offsets[0] )
                     return true;
@@ -166,7 +166,7 @@ std::string CPCIDSKVectorSegment::ConsistencyCheck()
     report += ConsistencyCheck_ShapeIndices();
 
     if( report != "" )
-        fprintf( stderr, "ConsistencyCheck() Report:\n%s", report.c_str() );
+        fprintf( stderr, "ConsistencyCheck() Report:\n%s", report.c_str() );/*ok*/
 
     return report;
 }
@@ -218,13 +218,12 @@ std::string CPCIDSKVectorSegment::ConsistencyCheck_DataIndices()
 
 {
     std::string report;
-    unsigned int section;
 
     SpaceMap smap;
 
     CPL_IGNORE_RET_VAL(smap.AddChunk( 0, vh.header_blocks ));
 
-    for( section = 0; section < 2; section++ )
+    for( int section = 0; section < 2; section++ )
     {
         const std::vector<uint32> *map = di[section].GetIndex();
         unsigned int i;
@@ -275,7 +274,7 @@ std::string CPCIDSKVectorSegment::ConsistencyCheck_ShapeIndices()
             char msg[100];
 
             snprintf( msg, sizeof(msg),
-                      "ShapeID %d is used for shape %d and %d!\n", 
+                      "ShapeID %d is used for shape %u and %u!\n", 
                      shape_index_ids[toff], 
                      toff, id_map[shape_index_ids[toff]]);
             report += msg;
diff --git a/frmts/pcidsk/sdk/segment/metadatasegment.h b/frmts/pcidsk/sdk/segment/metadatasegment.h
index 3a47d07..d6244e9 100644
--- a/frmts/pcidsk/sdk/segment/metadatasegment.h
+++ b/frmts/pcidsk/sdk/segment/metadatasegment.h
@@ -58,7 +58,7 @@ namespace PCIDSK
         void         SetGroupMetadataValue( const char *group, int id,
                                             const std::string& key, const std::string& value );
 
-        void         Synchronize();
+        void         Synchronize() override;
                                    
     private:
        bool         loaded;
diff --git a/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp b/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp
index ef9e7f1..2efa617 100644
--- a/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp
+++ b/frmts/pcidsk/sdk/segment/metadatasegment_p.cpp
@@ -83,7 +83,7 @@ MetadataSegment::~MetadataSegment()
 
 void MetadataSegment::Synchronize()
 {
-    if( loaded && update_list.size() > 0 )
+    if( loaded && !update_list.empty() )
         Save();
 }
 
@@ -264,9 +264,9 @@ void MetadataSegment::Save()
 /* -------------------------------------------------------------------- */
     std::map<std::string,std::string>::iterator it;
 
-    for( it = update_list.begin(); it != update_list.end(); it++ )
+    for( it = update_list.begin(); it != update_list.end(); ++it )
     {
-        if( it->second.size() == 0 )
+        if( it->second.empty() )
             continue;
 
         std::string line;
diff --git a/frmts/pcidsk/sdk/segment/orbitstructures.h b/frmts/pcidsk/sdk/segment/orbitstructures.h
index d75d439..dd7cea1 100644
--- a/frmts/pcidsk/sdk/segment/orbitstructures.h
+++ b/frmts/pcidsk/sdk/segment/orbitstructures.h
@@ -34,16 +34,16 @@
 namespace PCIDSK
 {
 /* -------------------------------------------------------------------- */
-/*	Structure for ephemeris segment (ORBIT segment, type 160).	*/
+/*      Structure for ephemeris segment (ORBIT segment, type 160).      */
 /* -------------------------------------------------------------------- */
-#define EPHEMERIS_BLK		8
+#define EPHEMERIS_BLK           8
 #define EPHEMERIS_RADAR_BLK     10
-#define EPHEMERIS_ATT_BLK	9
+#define EPHEMERIS_ATT_BLK       9
 /* -------------------------------------------------------------------- */
-/*	Structure for Satellite Radar segment.				*/
+/*      Structure for Satellite Radar segment.                          */
 /* -------------------------------------------------------------------- */
-#define ANC_DATA_PER_BLK	16
-#define ANC_DATA_SIZE		32
+#define ANC_DATA_PER_BLK        16
+#define ANC_DATA_SIZE           32
     /**
      * Ancillary data structure.
      */
@@ -92,24 +92,24 @@ namespace PCIDSK
             {
                 return;
             }
-            SlantRangeFstPixel = oAD.SlantRangeFstPixel;	
-            SlantRangeLastPixel = oAD.SlantRangeLastPixel;	
-            FstPixelLat = oAD.FstPixelLat;		
-            MidPixelLat = oAD.MidPixelLat;		
-            LstPixelLat = oAD.LstPixelLat;		
-            FstPixelLong = oAD.FstPixelLong;		
-            MidPixelLong = oAD.MidPixelLong;		
-            LstPixelLong = oAD.LstPixelLong;	
+            SlantRangeFstPixel = oAD.SlantRangeFstPixel;
+            SlantRangeLastPixel = oAD.SlantRangeLastPixel;
+            FstPixelLat = oAD.FstPixelLat;
+            MidPixelLat = oAD.MidPixelLat;
+            LstPixelLat = oAD.LstPixelLat;
+            FstPixelLong = oAD.FstPixelLong;
+            MidPixelLong = oAD.MidPixelLong;
+            LstPixelLong = oAD.LstPixelLong;
         }
 
-        int   SlantRangeFstPixel;	/* Slant Range to First Pixel (m)	     */
-        int   SlantRangeLastPixel;	/* Slant Range to Last Pixel (m)	     */
-        float FstPixelLat;		/* First Pixel Latitude (millionths degrees) */
-        float MidPixelLat;		/* Mid Pixel Latitude (millionths degrees)   */
-        float LstPixelLat;		/* Last Pixel Latitude (millionths degrees)  */
-        float FstPixelLong;		/* First Pixel Longitude (millionths degrees)*/
-        float MidPixelLong;		/* Mid Pixel Longitude (millionths degrees)  */
-        float LstPixelLong;		/* Last Pixel Longitude (millionths degrees) */
+        int   SlantRangeFstPixel;   /* Slant Range to First Pixel (m) */
+        int   SlantRangeLastPixel;  /* Slant Range to Last Pixel (m) */
+        float FstPixelLat;          /* First Pixel Latitude (millionths degrees) */
+        float MidPixelLat;          /* Mid Pixel Latitude (millionths degrees)   */
+        float LstPixelLat;          /* Last Pixel Latitude (millionths degrees)  */
+        float FstPixelLong;         /* First Pixel Longitude (millionths degrees)*/
+        float MidPixelLong;         /* Mid Pixel Longitude (millionths degrees)  */
+        float LstPixelLong;         /* Last Pixel Longitude (millionths degrees) */
     } ;
 
     /**
@@ -160,24 +160,24 @@ namespace PCIDSK
             {
                 return;
             }
-            Identifier = oRS.Identifier;	
-            Facility = oRS.Facility;	
-            Ellipsoid = oRS.Ellipsoid;	
-            EquatorialRadius = oRS.EquatorialRadius;    
-            PolarRadius = oRS.PolarRadius;		
-            IncidenceAngle = oRS.IncidenceAngle;	
-            PixelSpacing = oRS.PixelSpacing;	
-            LineSpacing = oRS.LineSpacing;		
-            ClockAngle = oRS.ClockAngle;		
-
-            NumberBlockData = oRS.NumberBlockData;	
-            NumberData = oRS.NumberData;		
-
-            Line = oRS.Line;	
+            Identifier = oRS.Identifier;
+            Facility = oRS.Facility;
+            Ellipsoid = oRS.Ellipsoid;
+            EquatorialRadius = oRS.EquatorialRadius;
+            PolarRadius = oRS.PolarRadius;
+            IncidenceAngle = oRS.IncidenceAngle;
+            PixelSpacing = oRS.PixelSpacing;
+            LineSpacing = oRS.LineSpacing;
+            ClockAngle = oRS.ClockAngle;
+
+            NumberBlockData = oRS.NumberBlockData;
+            NumberData = oRS.NumberData;
+
+            Line = oRS.Line;
         }
 
         std::string   Identifier; /* Product identifier */
-        std::string   Facility;	/* Processing facility */
+        std::string   Facility; /* Processing facility */
         std::string   Ellipsoid; /* Ellipsoid designator */
         double EquatorialRadius; /* Equatorial radius of earth */
         double PolarRadius; /* Polar radius of earth */
@@ -186,17 +186,17 @@ namespace PCIDSK
         double LineSpacing; /* Nominal line spacing in metre */
         double ClockAngle; /* Clock angle in degree */
 
-        int    NumberBlockData;	/* Number of blocks of ancillary data */
+        int    NumberBlockData; /* Number of blocks of ancillary data */
         int  NumberData; /* Number of ancillary data */
 
         std::vector<AncillaryData_t> Line; /* Pointer to ancillary line */
     } ;
 
 /* -------------------------------------------------------------------- */
-/*	Structure for Satellite attitude segment.			*/
+/*       Structure for Satellite attitude segment.                      */
 /* -------------------------------------------------------------------- */
-#define ATT_SEG_BLK		604
-#define ATT_SEG_MAX_LINE	6000
+#define ATT_SEG_BLK             604
+#define ATT_SEG_MAX_LINE        6000
 #define ATT_SEG_LINE_PER_BLOCK  10
 
     /**
@@ -314,10 +314,10 @@ namespace PCIDSK
     } ;
 
 /* -------------------------------------------------------------------- */
-/*	AVHRR orbit segment. Composed of 11 blocks plus extra blocks	*/
-/*	for holding per-scanline information.				*/
+/*      AVHRR orbit segment. Composed of 11 blocks plus extra blocks    */
+/*      for holding per-scanline information.                           */
 /* -------------------------------------------------------------------- */
-#define AVH_SEG_BASE_NUM_BLK	11
+#define AVH_SEG_BASE_NUM_BLK    11
 
     /**
      * Avhrr line information
@@ -771,7 +771,7 @@ namespace PCIDSK
         /// Satellite sensor
         std::string SatelliteSensor;
         /// Satellite sensor no.
-        std::string SensorNo;		
+        std::string SensorNo;
         /// Date of image taken
         std::string DateImageTaken;
         /// Flag to indicate supplemental segment
@@ -899,19 +899,19 @@ namespace PCIDSK
         int    SPCoeffSg[4];
 
         /// Image record length
-        int	   ImageRecordLength;
+        int        ImageRecordLength;
         /// Number of image line
-        int	   NumberImageLine;
+        int        NumberImageLine;
         /// Number of bytes per pixel
-        int	   NumberBytePerPixel;
+        int        NumberBytePerPixel;
         /// Number of samples per line
-        int	   NumberSamplePerLine;
+        int        NumberSamplePerLine;
         /// Number of prefix bytes
-        int    NumberPrefixBytes;
+        int        NumberPrefixBytes;
         /// Number of suffix bytes
-        int	   NumberSuffixBytes;
+        int        NumberSuffixBytes;
         /// Number of coefficients for SPOT 1B
-        int	   SPNCoeff;
+        int        SPNCoeff;
 
         /// Flag to indicate ascending or descending
         bool  bDescending;
@@ -927,28 +927,28 @@ namespace PCIDSK
      * List of sensor type
      */
     typedef enum {PLA_1, MLA_1, PLA_2, MLA_2, PLA_3, MLA_3, PLA_4, MLA_4,
-		ASTER, SAR, LISS_1, LISS_2, LISS_3, LISS_L3, LISS_L3_L2,
-		LISS_L4, LISS_L4_L2, LISS_P3, LISS_P3_L2, LISS_W3, LISS_W3_L2,
-		LISS_AWF, LISS_AWF_L2, LISS_M3, EOC, IRS_1, RSAT_FIN, 
-		RSAT_STD, ERS_1, ERS_2, TM, ETM, IKO_PAN, IKO_MULTI, 
-		ORBVIEW_PAN, ORBVIEW_MULTI, OV3_PAN_BASIC, OV3_PAN_GEO, 
-		OV3_MULTI_BASIC, OV3_MULTI_GEO, OV5_PAN_BASIC, OV5_PAN_GEO, 
-		OV5_MULTI_BASIC, OV5_MULTI_GEO, QBIRD_PAN, QBIRD_PAN_STD, 
-		QBIRD_PAN_STH, QBIRD_MULTI, QBIRD_MULTI_STD, QBIRD_MULTI_STH, 
-		FORMOSAT_PAN, FORMOSAT_MULTI, FORMOSAT_PAN_L2,
-		FORMOSAT_MULTIL2, SPOT5_PAN_2_5, SPOT5_PAN_5, SPOT5_HRS,
-		SPOT5_MULTI, MERIS_FR, MERIS_RR, MERIS_LR, ASAR, EROS, 
-		MODIS_250, MODIS_500, MODIS_1000, CBERS_HRC, CBERS_HRC_L2,
-		CBERS_CCD, CBERS_CCD_L2, CBERS_IRM_80, CBERS_IRM_80_L2, 
-	        CBERS_IRM_160, CBERS_IRM_160_L2, CBERS_WFI, CBERS_WFI_L2, 
-	 	CARTOSAT1_L1, CARTOSAT1_L2, ALOS_PRISM_L1, ALOS_PRISM_L2, 
-		ALOS_AVNIR_L1, ALOS_AVNIR_L2, PALSAR, DMC_1R, DMC_1T, 
-		KOMPSAT2_PAN, KOMPSAT2_MULTI, TERRASAR, WVIEW_PAN,
-		WVIEW_PAN_STD, WVIEW_MULTI, WVIEW_MULTI_STD,
-		RAPIDEYE_L1B, THEOS_PAN_L1, THEOS_PAN_L2,
-		THEOS_MS_L1, THEOS_MS_L2, 
-		GOSAT_500_L1, GOSAT_500_L2, GOSAT_1500_L1, GOSAT_1500_L2, 
-		HJ_CCD_1A, HJ_CCD_1B, NEW, AVHRR} TypeDeCapteur;
+                    ASTER, SAR, LISS_1, LISS_2, LISS_3, LISS_L3, LISS_L3_L2,
+                    LISS_L4, LISS_L4_L2, LISS_P3, LISS_P3_L2, LISS_W3, LISS_W3_L2,
+                    LISS_AWF, LISS_AWF_L2, LISS_M3, EOC, IRS_1, RSAT_FIN, 
+                    RSAT_STD, ERS_1, ERS_2, TM, ETM, IKO_PAN, IKO_MULTI, 
+                    ORBVIEW_PAN, ORBVIEW_MULTI, OV3_PAN_BASIC, OV3_PAN_GEO, 
+                    OV3_MULTI_BASIC, OV3_MULTI_GEO, OV5_PAN_BASIC, OV5_PAN_GEO, 
+                    OV5_MULTI_BASIC, OV5_MULTI_GEO, QBIRD_PAN, QBIRD_PAN_STD, 
+                    QBIRD_PAN_STH, QBIRD_MULTI, QBIRD_MULTI_STD, QBIRD_MULTI_STH, 
+                    FORMOSAT_PAN, FORMOSAT_MULTI, FORMOSAT_PAN_L2,
+                    FORMOSAT_MULTIL2, SPOT5_PAN_2_5, SPOT5_PAN_5, SPOT5_HRS,
+                    SPOT5_MULTI, MERIS_FR, MERIS_RR, MERIS_LR, ASAR, EROS, 
+                    MODIS_250, MODIS_500, MODIS_1000, CBERS_HRC, CBERS_HRC_L2,
+                    CBERS_CCD, CBERS_CCD_L2, CBERS_IRM_80, CBERS_IRM_80_L2, 
+                    CBERS_IRM_160, CBERS_IRM_160_L2, CBERS_WFI, CBERS_WFI_L2, 
+                    CARTOSAT1_L1, CARTOSAT1_L2, ALOS_PRISM_L1, ALOS_PRISM_L2, 
+                    ALOS_AVNIR_L1, ALOS_AVNIR_L2, PALSAR, DMC_1R, DMC_1T, 
+                    KOMPSAT2_PAN, KOMPSAT2_MULTI, TERRASAR, WVIEW_PAN,
+                    WVIEW_PAN_STD, WVIEW_MULTI, WVIEW_MULTI_STD,
+                    RAPIDEYE_L1B, THEOS_PAN_L1, THEOS_PAN_L2,
+                    THEOS_MS_L1, THEOS_MS_L2, 
+                    GOSAT_500_L1, GOSAT_500_L2, GOSAT_1500_L1, GOSAT_1500_L2, 
+                    HJ_CCD_1A, HJ_CCD_1B, NEW, AVHRR} TypeDeCapteur;
 }
 
 #endif // INCLUDE_PCIDSK_ORBIT_INFORMATION_H
diff --git a/frmts/pcidsk/sdk/segment/sysblockmap.cpp b/frmts/pcidsk/sdk/segment/sysblockmap.cpp
index 78f19b3..a2bc9a3 100644
--- a/frmts/pcidsk/sdk/segment/sysblockmap.cpp
+++ b/frmts/pcidsk/sdk/segment/sysblockmap.cpp
@@ -86,7 +86,7 @@ SysBlockMap::~SysBlockMap()
     }
     catch( const PCIDSKException& e )
     {
-        fprintf(stderr, "Exception in SysBlockMap::~SysBlockMap(): %s\n",
+        fprintf(stderr, "Exception in SysBlockMap::~SysBlockMap(): %s\n",/*ok*/
                 e.what());
     }
 }
@@ -112,7 +112,7 @@ void SysBlockMap::Initialize()
     WriteToFile( init_data.buffer, 0, init_data.buffer_size );
 #ifdef notdef
     // arbitrarily grow the segment a bit to avoid having to move it too soon.
-    WriteToFile( "\0", 8191, 1 );				       
+    WriteToFile( "\0", 8191, 1 );
 #endif
 }
 
diff --git a/frmts/pcidsk/sdk/segment/sysblockmap.h b/frmts/pcidsk/sdk/segment/sysblockmap.h
index b7c08b5..990fcd9 100644
--- a/frmts/pcidsk/sdk/segment/sysblockmap.h
+++ b/frmts/pcidsk/sdk/segment/sysblockmap.h
@@ -56,8 +56,8 @@ namespace PCIDSK
 
         virtual        ~SysBlockMap();
 
-        virtual void    Synchronize();
-        virtual void    Initialize();
+        virtual void    Synchronize() override;
+        virtual void    Initialize() override;
 
         SysVirtualFile *GetVirtualFile( int image );
         int             CreateVirtualFile();
diff --git a/frmts/pcidsk/vsi_pcidsk_io.cpp b/frmts/pcidsk/vsi_pcidsk_io.cpp
index d8f22c7..0214f68 100644
--- a/frmts/pcidsk/vsi_pcidsk_io.cpp
+++ b/frmts/pcidsk/vsi_pcidsk_io.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vsi_pcidsk_io.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PCIDSK Database File
  * Purpose:  PCIDSK SDK compatible IO interface built on VSI.
@@ -37,21 +36,21 @@ using PCIDSK::PCIDSKInterfaces;
 using PCIDSK::ThrowPCIDSKException;
 using PCIDSK::uint64;
 
-CPL_CVSID("$Id: vsi_pcidsk_io.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: vsi_pcidsk_io.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
-PCIDSK::EDBFile *GDAL_EDBOpen( std::string osFilename, std::string osAccess );
+PCIDSK::EDBFile *GDAL_EDBOpen( const std::string& osFilename, const std::string& osAccess );
 const PCIDSK::PCIDSKInterfaces *PCIDSK2GetInterfaces();
 
 class VSI_IOInterface : public IOInterfaces
 {
-    virtual void   *Open( std::string filename, std::string access ) const;
-    virtual uint64  Seek( void *io_handle, uint64 offset, int whence ) const;
-    virtual uint64  Tell( void *io_handle ) const;
-    virtual uint64  Read( void *buffer, uint64 size, uint64 nmemb, void *io_hanle ) const;
-    virtual uint64  Write( const void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const;
-    virtual int     Eof( void *io_handle ) const;
-    virtual int     Flush( void *io_handle ) const;
-    virtual int     Close( void *io_handle ) const;
+    virtual void   *Open( std::string filename, std::string access ) const override;
+    virtual uint64  Seek( void *io_handle, uint64 offset, int whence ) const override;
+    virtual uint64  Tell( void *io_handle ) const override;
+    virtual uint64  Read( void *buffer, uint64 size, uint64 nmemb, void *io_hanle ) const override;
+    virtual uint64  Write( const void *buffer, uint64 size, uint64 nmemb, void *io_handle ) const override;
+    virtual int     Eof( void *io_handle ) const override;
+    virtual int     Flush( void *io_handle ) const override;
+    virtual int     Close( void *io_handle ) const override;
 
     const char     *LastError() const;
 };
@@ -236,8 +235,8 @@ public:
     CPLThreadMutex();
     ~CPLThreadMutex();
 
-    int Acquire(void);
-    int Release(void);
+    int Acquire(void) override;
+    int Release(void) override;
 };
 
 /************************************************************************/
diff --git a/frmts/pcraster/doxygen.cfg b/frmts/pcraster/doxygen.cfg
index df6c961..8e24f76 100644
--- a/frmts/pcraster/doxygen.cfg
+++ b/frmts/pcraster/doxygen.cfg
@@ -14,191 +14,191 @@
 # Project related configuration options
 #---------------------------------------------------------------------------
 
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
 # by quotes) that should identify the project.
 
-PROJECT_NAME           = 
+PROJECT_NAME           =
 
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
-# This could be handy for archiving the generated documentation or 
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 
+PROJECT_NUMBER         =
 
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
 # where doxygen was started. If left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = 
+OUTPUT_DIRECTORY       =
 
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
-# 4096 sub-directories (in 2 levels) under the output directory of each output 
-# format and will distribute the generated files over these directories. 
-# Enabling this option can be useful when feeding doxygen a huge amount of source 
-# files, where putting all generated files in the same directory would otherwise 
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of source
+# files, where putting all generated files in the same directory would otherwise
 # cause performance problems for the file system.
 
 CREATE_SUBDIRS         = NO
 
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
-# documentation generated by doxygen is written. Doxygen will use this 
-# information to generate all constant output in the proper language. 
-# The default language is English, other supported languages are: 
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
-# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
-# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
-# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
 # Swedish, and Ukrainian.
 
 OUTPUT_LANGUAGE        = English
 
-# This tag can be used to specify the encoding used in the generated output. 
-# The encoding is not always determined by the language that is chosen, 
-# but also whether or not the output is meant for Windows or non-Windows users. 
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
-# forces the Windows encoding (this is the default for the Windows binary), 
-# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
 # all platforms other than Windows).
 
 USE_WINDOWS_ENCODING   = NO
 
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
-# include brief member descriptions after the members that are listed in 
-# the file and class documentation (similar to JavaDoc). 
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
 # Set to NO to disable this.
 
 BRIEF_MEMBER_DESC      = YES
 
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
-# the brief description of a member or function before the detailed description. 
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
 # brief descriptions will be completely suppressed.
 
 REPEAT_BRIEF           = YES
 
-# This tag implements a quasi-intelligent brief description abbreviator 
-# that is used to form the text in various listings. Each string 
-# in this list, if found as the leading text of the brief description, will be 
-# stripped from the text and the result after processing the whole list, is used 
-# as the annotated text. Otherwise, the brief description is used as-is. If left 
-# blank, the following values are used ("$name" is automatically replaced with the 
-# name of the entity): "The $name class" "The $name widget" "The $name file" 
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is used
+# as the annotated text. Otherwise, the brief description is used as-is. If left
+# blank, the following values are used ("$name" is automatically replaced with the
+# name of the entity): "The $name class" "The $name widget" "The $name file"
 # "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
 
-ABBREVIATE_BRIEF       = 
+ABBREVIATE_BRIEF       =
 
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
-# Doxygen will generate a detailed section even if there is only a brief 
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
 # description.
 
 ALWAYS_DETAILED_SEC    = NO
 
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
-# members of a class in the documentation of that class as if those members were 
-# ordinary class members. Constructors, destructors and assignment operators of 
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
 # the base classes will not be shown.
 
 INLINE_INHERITED_MEMB  = NO
 
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
-# path before files name in the file list and in the header files. If set 
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
 # to NO the shortest path that makes the file name unique will be used.
 
 FULL_PATH_NAMES        = YES
 
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
-# can be used to strip a user-defined part of the path. Stripping is 
-# only done if one of the specified strings matches the left-hand part of 
-# the path. The tag can be used to show relative paths in the file list. 
-# If left blank the directory from which doxygen is run is used as the 
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
 # path to strip.
 
-STRIP_FROM_PATH        = 
+STRIP_FROM_PATH        =
 
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
-# the path mentioned in the documentation of a class, which tells 
-# the reader which header file to include in order to use a class. 
-# If left blank only the name of the header file containing the class 
-# definition is used. Otherwise one should specify the include paths that 
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
 # are normally passed to the compiler using the -I flag.
 
-STRIP_FROM_INC_PATH    = 
+STRIP_FROM_INC_PATH    =
 
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
-# (but less readable) file names. This can be useful is your file systems 
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
 # doesn't support long names like on DOS, Mac, or CD-ROM.
 
 SHORT_NAMES            = NO
 
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
-# will interpret the first line (until the first dot) of a JavaDoc-style 
-# comment as the brief description. If set to NO, the JavaDoc 
-# comments will behave just like the Qt-style comments (thus requiring an 
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
 # explicit @brief command for a brief description.
 
 JAVADOC_AUTOBRIEF      = NO
 
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
-# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
-# comments) as a brief description. This used to be the default behaviour. 
-# The new default is to treat a multi-line C++ comment block as a detailed 
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
 # description. Set this tag to YES if you prefer the old behaviour instead.
 
 MULTILINE_CPP_IS_BRIEF = NO
 
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
 # will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member 
+# If set to NO, the detailed description appears after the member
 # documentation.
 
 DETAILS_AT_TOP         = NO
 
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
-# member inherits the documentation from any documented member that it 
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
 # re-implements.
 
 INHERIT_DOCS           = YES
 
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
 # all members of a group must be documented explicitly.
 
 DISTRIBUTE_GROUP_DOC   = NO
 
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
 # Doxygen uses this value to replace tabs by spaces in code fragments.
 
 TAB_SIZE               = 8
 
-# This tag can be used to specify a number of aliases that acts 
-# as commands in the documentation. An alias has the form "name=value". 
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
-# put the command \sideeffect (or @sideeffect) in the documentation, which 
-# will result in a user-defined paragraph with heading "Side Effects:". 
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
 # You can put \n's in the value part of an alias to insert newlines.
 
-ALIASES                = 
+ALIASES                =
 
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
-# only. Doxygen will then generate output that is more tailored for C. 
-# For instance, some of the names that are used will be different. The list 
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
 # of all members will be omitted, etc.
 
 OPTIMIZE_OUTPUT_FOR_C  = NO
 
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
-# only. Doxygen will then generate output that is more tailored for Java. 
-# For instance, namespaces will be presented as packages, qualified scopes 
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
 # will look different, etc.
 
 OPTIMIZE_OUTPUT_JAVA   = NO
 
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
-# the same type (for instance a group of public functions) to be put as a 
-# subgroup of that type (e.g. under the Public Functions section). Set it to 
-# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
 # the \nosubgrouping command.
 
 SUBGROUPING            = YES
@@ -207,168 +207,168 @@ SUBGROUPING            = YES
 # Build related configuration options
 #---------------------------------------------------------------------------
 
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
-# documentation are documented, even if no documentation was available. 
-# Private class members and static file members will be hidden unless 
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
 # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
 
 EXTRACT_ALL            = NO
 
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
 # will be included in the documentation.
 
 EXTRACT_PRIVATE        = YES
 
-# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
 # will be included in the documentation.
 
 EXTRACT_STATIC         = YES
 
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
-# defined locally in source files will be included in the documentation. 
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
 # If set to NO only classes defined in header files are included.
 
 EXTRACT_LOCAL_CLASSES  = YES
 
-# This flag is only useful for Objective-C code. When set to YES local 
-# methods, which are defined in the implementation section but not in 
-# the interface are included in the documentation. 
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
 # If set to NO (the default) only methods in the interface are included.
 
 EXTRACT_LOCAL_METHODS  = NO
 
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
-# undocumented members of documented classes, files or namespaces. 
-# If set to NO (the default) these members will be included in the 
-# various overviews, but no documentation section is generated. 
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
 # This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_MEMBERS     = NO
 
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
-# undocumented classes that are normally visible in the class hierarchy. 
-# If set to NO (the default) these classes will be included in the various 
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
 # overviews. This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_CLASSES     = NO
 
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
-# friend (class|struct|union) declarations. 
-# If set to NO (the default) these declarations will be included in the 
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
 # documentation.
 
 HIDE_FRIEND_COMPOUNDS  = NO
 
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
-# documentation blocks found inside the body of a function. 
-# If set to NO (the default) these blocks will be appended to the 
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
 # function's detailed documentation block.
 
 HIDE_IN_BODY_DOCS      = NO
 
-# The INTERNAL_DOCS tag determines if documentation 
-# that is typed after a \internal command is included. If the tag is set 
-# to NO (the default) then the documentation will be excluded. 
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
 # Set it to YES to include the internal documentation.
 
 INTERNAL_DOCS          = NO
 
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
-# file names in lower-case letters. If set to YES upper-case letters are also 
-# allowed. This is useful if you have classes or files whose names only differ 
-# in case and if your file system supports case sensitive file names. Windows 
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
 # and Mac users are advised to set this option to NO.
 
 CASE_SENSE_NAMES       = YES
 
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
-# will show members with their full class and namespace scopes in the 
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
 # documentation. If set to YES the scope will be hidden.
 
 HIDE_SCOPE_NAMES       = NO
 
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
-# will put a list of the files that are included by a file in the documentation 
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
 # of that file.
 
 SHOW_INCLUDE_FILES     = YES
 
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
 # is inserted in the documentation for inline members.
 
 INLINE_INFO            = YES
 
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
-# will sort the (detailed) documentation of file and class members 
-# alphabetically by member name. If set to NO the members will appear in 
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
 # declaration order.
 
 SORT_MEMBER_DOCS       = YES
 
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
-# brief documentation of file, namespace and class members alphabetically 
-# by member name. If set to NO (the default) the members will appear in 
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
 # declaration order.
 
 SORT_BRIEF_DOCS        = NO
 
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
-# sorted by fully-qualified names, including namespaces. If set to 
-# NO (the default), the class list will be sorted only by class name, 
-# not including the namespace part. 
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
 # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the 
+# Note: This option applies only to the class list, not to the
 # alphabetical list.
 
 SORT_BY_SCOPE_NAME     = NO
 
-# The GENERATE_TODOLIST tag can be used to enable (YES) or 
-# disable (NO) the todo list. This list is created by putting \todo 
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
 # commands in the documentation.
 
 GENERATE_TODOLIST      = YES
 
-# The GENERATE_TESTLIST tag can be used to enable (YES) or 
-# disable (NO) the test list. This list is created by putting \test 
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
 # commands in the documentation.
 
 GENERATE_TESTLIST      = YES
 
-# The GENERATE_BUGLIST tag can be used to enable (YES) or 
-# disable (NO) the bug list. This list is created by putting \bug 
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
 # commands in the documentation.
 
 GENERATE_BUGLIST       = YES
 
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
-# disable (NO) the deprecated list. This list is created by putting 
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
 # \deprecated commands in the documentation.
 
 GENERATE_DEPRECATEDLIST= YES
 
-# The ENABLED_SECTIONS tag can be used to enable conditional 
+# The ENABLED_SECTIONS tag can be used to enable conditional
 # documentation sections, marked by \if sectionname ... \endif.
 
-ENABLED_SECTIONS       = 
+ENABLED_SECTIONS       =
 
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
-# the initial value of a variable or define consists of for it to appear in 
-# the documentation. If the initializer consists of more lines than specified 
-# here it will be hidden. Use a value of 0 to hide initializers completely. 
-# The appearance of the initializer of individual variables and defines in the 
-# documentation can be controlled using \showinitializer or \hideinitializer 
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
 # command in the documentation regardless of this setting.
 
 MAX_INITIALIZER_LINES  = 30
 
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
-# at the bottom of the documentation of classes and structs. If set to YES the 
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
 # list will mention the files that were used to generate the documentation.
 
 SHOW_USED_FILES        = YES
 
-# If the sources in your project are distributed over multiple directories 
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
 # in the documentation.
 
 SHOW_DIRECTORIES       = YES
@@ -377,133 +377,133 @@ SHOW_DIRECTORIES       = YES
 # configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
 
-# The QUIET tag can be used to turn on/off the messages that are generated 
+# The QUIET tag can be used to turn on/off the messages that are generated
 # by doxygen. Possible values are YES and NO. If left blank NO is used.
 
 QUIET                  = NO
 
-# The WARNINGS tag can be used to turn on/off the warning messages that are 
-# generated by doxygen. Possible values are YES and NO. If left blank 
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
 # NO is used.
 
 WARNINGS               = YES
 
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
 # automatically be disabled.
 
 WARN_IF_UNDOCUMENTED   = YES
 
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
-# potential errors in the documentation, such as not documenting some 
-# parameters in a documented function, or documenting parameters that 
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
 # don't exist or using markup commands wrongly.
 
 WARN_IF_DOC_ERROR      = YES
 
-# The WARN_FORMAT tag determines the format of the warning messages that 
-# doxygen can produce. The string should contain the $file, $line, and $text 
-# tags, which will be replaced by the file and line number from which the 
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
 # warning originated and the warning text.
 
 WARN_FORMAT            = "$file:$line: $text"
 
-# The WARN_LOGFILE tag can be used to specify a file to which warning 
-# and error messages should be written. If left blank the output is written 
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
 # to stderr.
 
-WARN_LOGFILE           = 
+WARN_LOGFILE           =
 
 #---------------------------------------------------------------------------
 # configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag can be used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = 
+INPUT                  =
 
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank the following patterns are tested: 
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
 # *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
 
-FILE_PATTERNS          = 
+FILE_PATTERNS          =
 
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
-# should be searched for input files as well. Possible values are YES and NO. 
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
 # If left blank NO is used.
 
 RECURSIVE              = NO
 
-# The EXCLUDE tag can be used to specify files and/or directories that should 
-# excluded from the INPUT source files. This way you can easily exclude a 
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
 # subdirectory from a directory tree whose root is specified with the INPUT tag.
 
-EXCLUDE                = 
+EXCLUDE                =
 
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
 # that are symbolic links (a Unix filesystem feature) are excluded from the input.
 
 EXCLUDE_SYMLINKS       = NO
 
-# If the value of the INPUT tag contains directories, you can use the 
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
 # certain files from those directories.
 
-EXCLUDE_PATTERNS       = 
+EXCLUDE_PATTERNS       =
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
 # the \include command).
 
-EXAMPLE_PATH           = 
+EXAMPLE_PATH           =
 
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
 # blank all files are included.
 
-EXAMPLE_PATTERNS       = 
+EXAMPLE_PATTERNS       =
 
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
-# searched for input files to be used with the \include or \dontinclude 
-# commands irrespective of the value of the RECURSIVE tag. 
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
 # Possible values are YES and NO. If left blank NO is used.
 
 EXAMPLE_RECURSIVE      = NO
 
-# The IMAGE_PATH tag can be used to specify one or more files or 
-# directories that contain image that are included in the documentation (see 
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
 # the \image command).
 
-IMAGE_PATH             = 
+IMAGE_PATH             =
 
-# The INPUT_FILTER tag can be used to specify a program that doxygen should 
-# invoke to filter for each input file. Doxygen will invoke the filter program 
-# by executing (via popen()) the command <filter> <input-file>, where <filter> 
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
-# input file. Doxygen will then use the output that the filter program writes 
-# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
 # ignored.
 
-INPUT_FILTER           = 
+INPUT_FILTER           =
 
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
-# basis.  Doxygen will compare the file name with each pattern and apply the 
-# filter if there is a match.  The filters are a list of the form: 
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.  Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.  The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
 # is applied to all files.
 
-FILTER_PATTERNS        = 
+FILTER_PATTERNS        =
 
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
-# INPUT_FILTER) will be used to filter the input files when producing source 
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
 # files to browse (i.e. when SOURCE_BROWSER is set to YES).
 
 FILTER_SOURCE_FILES    = NO
@@ -512,38 +512,38 @@ FILTER_SOURCE_FILES    = NO
 # configuration options related to source browsing
 #---------------------------------------------------------------------------
 
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-# Note: To get rid of all source code in the generated output, make sure also 
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
 # VERBATIM_HEADERS is set to NO.
 
 SOURCE_BROWSER         = YES
 
-# Setting the INLINE_SOURCES tag to YES will include the body 
+# Setting the INLINE_SOURCES tag to YES will include the body
 # of functions and classes directly in the documentation.
 
 INLINE_SOURCES         = NO
 
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
-# doxygen to hide any special comment blocks from generated source code 
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
 # fragments. Normal C and C++ comments will always remain visible.
 
 STRIP_CODE_COMMENTS    = YES
 
-# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
-# then for each documented function all documented 
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
 # functions referencing it will be listed.
 
 REFERENCED_BY_RELATION = YES
 
-# If the REFERENCES_RELATION tag is set to YES (the default) 
-# then for each documented function all documented entities 
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
 # called/used by that function will be listed.
 
 REFERENCES_RELATION    = YES
 
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
-# will generate a verbatim copy of the header file for each class for 
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
 # which an include is specified. Set to NO to disable this.
 
 VERBATIM_HEADERS       = YES
@@ -552,133 +552,133 @@ VERBATIM_HEADERS       = YES
 # configuration options related to the alphabetical class index
 #---------------------------------------------------------------------------
 
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
-# of all compounds will be generated. Enable this if the project 
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
 # contains a lot of classes, structs, unions or interfaces.
 
 ALPHABETICAL_INDEX     = YES
 
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
 # in which this list will be split (can be a number in the range [1..20])
 
 COLS_IN_ALPHA_INDEX    = 4
 
-# In case all classes in a project start with a common prefix, all 
-# classes will be put under the same header in the alphabetical index. 
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
 # should be ignored while generating the index headers.
 
-IGNORE_PREFIX          = 
+IGNORE_PREFIX          =
 
 #---------------------------------------------------------------------------
 # configuration options related to the HTML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
 # generate HTML output.
 
 GENERATE_HTML          = YES
 
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `html' will be used as the default path.
 
 HTML_OUTPUT            = html
 
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
 # doxygen will generate files with .html extension.
 
 HTML_FILE_EXTENSION    = .html
 
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard header.
 
-HTML_HEADER            = 
+HTML_HEADER            =
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard footer.
 
-HTML_FOOTER            = 
+HTML_FOOTER            =
 
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
-# style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet. Note that doxygen will try to copy 
-# the style sheet file to the HTML output directory, so don't put your own 
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
 # stylesheet in the HTML output directory as well, or it will be erased!
 
-HTML_STYLESHEET        = 
+HTML_STYLESHEET        =
 
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
 # NO a bullet list will be used.
 
 HTML_ALIGN_MEMBERS     = YES
 
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
-# will be generated that can be used as input for tools like the 
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
 # of the generated HTML documentation.
 
 GENERATE_HTMLHELP      = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
-# be used to specify the file name of the resulting .chm file. You 
-# can add a path in front of the file if the result should not be 
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
 # written to the html output directory.
 
-CHM_FILE               = 
+CHM_FILE               =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
-# be used to specify the location (absolute path including file name) of 
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
 # the HTML help compiler on the generated index.hhp.
 
-HHC_LOCATION           = 
+HHC_LOCATION           =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
-# controls if a separate .chi index file is generated (YES) or that 
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
 # it should be included in the master .chm file (NO).
 
 GENERATE_CHI           = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
-# controls whether a binary table of contents is generated (YES) or a 
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
 # normal table of contents (NO) in the .chm file.
 
 BINARY_TOC             = NO
 
-# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
 # to the contents of the HTML help documentation and to the tree view.
 
 TOC_EXPAND             = NO
 
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
 # the value YES disables it.
 
 DISABLE_INDEX          = NO
 
-# This tag can be used to set the number of enum values (range [1..20]) 
+# This tag can be used to set the number of enum values (range [1..20])
 # that doxygen will group on one line in the generated HTML documentation.
 
 ENUM_VALUES_PER_LINE   = 4
 
 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that 
-# is generated for HTML Help). For this to work a browser that supports 
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
 # probably better off using the HTML help feature.
 
 GENERATE_TREEVIEW      = NO
 
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
-# used to set the initial width (in pixels) of the frame in which the tree 
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
 # is shown.
 
 TREEVIEW_WIDTH         = 250
@@ -687,74 +687,74 @@ TREEVIEW_WIDTH         = 250
 # configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
 # generate Latex output.
 
 GENERATE_LATEX         = NO
 
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `latex' will be used as the default path.
 
 LATEX_OUTPUT           = latex
 
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
 # invoked. If left blank `latex' will be used as the default command name.
 
 LATEX_CMD_NAME         = latex
 
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
-# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
 # default command name.
 
 MAKEINDEX_CMD_NAME     = makeindex
 
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
-# LaTeX documents. This may be useful for small projects and may help to 
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
 # save some trees in general.
 
 COMPACT_LATEX          = NO
 
-# The PAPER_TYPE tag can be used to set the paper type that is used 
-# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
 # executive. If left blank a4wide will be used.
 
 PAPER_TYPE             = a4wide
 
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
 # packages that should be included in the LaTeX output.
 
-EXTRA_PACKAGES         = 
+EXTRA_PACKAGES         =
 
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
-# the generated latex document. The header should contain everything until 
-# the first chapter. If it is left blank doxygen will generate a 
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
 # standard header. Notice: only use this tag if you know what you are doing!
 
-LATEX_HEADER           = 
+LATEX_HEADER           =
 
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
-# contain links (just like the HTML output) instead of page references 
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
 # This makes the output suitable for online browsing using a pdf viewer.
 
 PDF_HYPERLINKS         = NO
 
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
-# plain latex in the generated Makefile. Set this option to YES to get a 
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
 # higher quality PDF documentation.
 
 USE_PDFLATEX           = NO
 
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
-# command to the generated LaTeX files. This will instruct LaTeX to keep 
-# running if errors occur, instead of asking the user for help. 
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
 # This option is also used when generating formulas in HTML.
 
 LATEX_BATCHMODE        = NO
 
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
-# include the index chapters (such as File Index, Compound Index, etc.) 
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
 # in the output.
 
 LATEX_HIDE_INDICES     = NO
@@ -763,68 +763,68 @@ LATEX_HIDE_INDICES     = NO
 # configuration options related to the RTF output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
-# The RTF output is optimized for Word 97 and may not look very pretty with 
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
 # other RTF readers or editors.
 
 GENERATE_RTF           = NO
 
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `rtf' will be used as the default path.
 
 RTF_OUTPUT             = rtf
 
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
-# RTF documents. This may be useful for small projects and may help to 
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
 # save some trees in general.
 
 COMPACT_RTF            = NO
 
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
-# will contain hyperlink fields. The RTF file will 
-# contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using WORD or other 
-# programs which support those fields. 
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
 # Note: wordpad (write) and others do not support links.
 
 RTF_HYPERLINKS         = NO
 
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
-# config file, i.e. a series of assignments. You only have to provide 
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
 # replacements, missing definitions are set to their default value.
 
-RTF_STYLESHEET_FILE    = 
+RTF_STYLESHEET_FILE    =
 
-# Set optional variables used in the generation of an rtf document. 
+# Set optional variables used in the generation of an rtf document.
 # Syntax is similar to doxygen's config file.
 
-RTF_EXTENSIONS_FILE    = 
+RTF_EXTENSIONS_FILE    =
 
 #---------------------------------------------------------------------------
 # configuration options related to the man page output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
 # generate man pages
 
 GENERATE_MAN           = NO
 
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `man' will be used as the default path.
 
 MAN_OUTPUT             = man
 
-# The MAN_EXTENSION tag determines the extension that is added to 
+# The MAN_EXTENSION tag determines the extension that is added to
 # the generated man pages (default is the subroutine's section .3)
 
 MAN_EXTENSION          = .3
 
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
-# then it will generate one additional man file for each entity 
-# documented in the real man page(s). These additional files 
-# only source the real man page, but without them the man command 
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
 # would be unable to find the correct page. The default is NO.
 
 MAN_LINKS              = NO
@@ -833,33 +833,33 @@ MAN_LINKS              = NO
 # configuration options related to the XML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_XML tag is set to YES Doxygen will 
-# generate an XML file that captures the structure of 
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
 # the code including all documentation.
 
 GENERATE_XML           = NO
 
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `xml' will be used as the default path.
 
 XML_OUTPUT             = xml
 
-# The XML_SCHEMA tag can be used to specify an XML schema, 
-# which can be used by a validating XML parser to check the 
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
 # syntax of the XML files.
 
-XML_SCHEMA             = 
+XML_SCHEMA             =
 
-# The XML_DTD tag can be used to specify an XML DTD, 
-# which can be used by a validating XML parser to check the 
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
 # syntax of the XML files.
 
-XML_DTD                = 
+XML_DTD                =
 
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
-# dump the program listings (including syntax highlighting 
-# and cross-referencing information) to the XML output. Note that 
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
 # enabling this will significantly increase the size of the XML output.
 
 XML_PROGRAMLISTING     = YES
@@ -868,10 +868,10 @@ XML_PROGRAMLISTING     = YES
 # configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
-# generate an AutoGen Definitions (see autogen.sf.net) file 
-# that captures the structure of the code including all 
-# documentation. Note that this feature is still experimental 
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
 # and incomplete at the moment.
 
 GENERATE_AUTOGEN_DEF   = NO
@@ -880,282 +880,282 @@ GENERATE_AUTOGEN_DEF   = NO
 # configuration options related to the Perl module output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
-# generate a Perl module file that captures the structure of 
-# the code including all documentation. Note that this 
-# feature is still experimental and incomplete at the 
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
 # moment.
 
 GENERATE_PERLMOD       = NO
 
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
 # to generate PDF and DVI output from the Perl module output.
 
 PERLMOD_LATEX          = NO
 
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
-# nicely formatted so it can be parsed by a human reader.  This is useful 
-# if you want to understand what is going on.  On the other hand, if this 
-# tag is set to NO the size of the Perl module output will be much smaller 
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
 # and Perl will parse it just the same.
 
 PERLMOD_PRETTY         = YES
 
-# The names of the make variables in the generated doxyrules.make file 
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
-# This is useful so different doxyrules.make files included by the same 
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
 # Makefile don't overwrite each other's variables.
 
-PERLMOD_MAKEVAR_PREFIX = 
+PERLMOD_MAKEVAR_PREFIX =
 
 #---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
+# Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
-# evaluate all C-preprocessor directives found in the sources and include 
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
 # files.
 
 ENABLE_PREPROCESSING   = YES
 
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
-# names in the source code. If set to NO (the default) only conditional 
-# compilation will be performed. Macro expansion can be done in a controlled 
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
 # way by setting EXPAND_ONLY_PREDEF to YES.
 
 MACRO_EXPANSION        = NO
 
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
-# then the macro expansion is limited to the macros specified with the 
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
 # PREDEFINED and EXPAND_AS_PREDEFINED tags.
 
 EXPAND_ONLY_PREDEF     = NO
 
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
 # in the INCLUDE_PATH (see below) will be search if a #include is found.
 
 SEARCH_INCLUDES        = YES
 
-# The INCLUDE_PATH tag can be used to specify one or more directories that 
-# contain include files that are not input files but should be processed by 
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
 # the preprocessor.
 
-INCLUDE_PATH           = 
+INCLUDE_PATH           =
 
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
-# patterns (like *.h and *.hpp) to filter out the header-files in the 
-# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
 # be used.
 
-INCLUDE_FILE_PATTERNS  = 
+INCLUDE_FILE_PATTERNS  =
 
-# The PREDEFINED tag can be used to specify one or more macro names that 
-# are defined before the preprocessor is started (similar to the -D option of 
-# gcc). The argument of the tag is a list of macros of the form: name 
-# or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed. To prevent a macro definition from being 
-# undefined via #undef or recursively expanded use the := operator 
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
 # instead of the = operator.
 
-PREDEFINED             = 
+PREDEFINED             =
 
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
-# this tag can be used to specify a list of macro names that should be expanded. 
-# The macro definition that is found in the sources will be used. 
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
 # Use the PREDEFINED tag if you want to use a different macro definition.
 
-EXPAND_AS_DEFINED      = 
+EXPAND_AS_DEFINED      =
 
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
-# doxygen's preprocessor will remove all function-like macros that are alone 
-# on a line, have an all uppercase name, and do not end with a semicolon. Such 
-# function macros are typically used for boiler-plate code, and will confuse the 
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
 # parser if not removed.
 
 SKIP_FUNCTION_MACROS   = YES
 
 #---------------------------------------------------------------------------
-# Configuration::additions related to external references   
+# Configuration::additions related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES option can be used to specify one or more tagfiles. 
-# Optionally an initial location of the external documentation 
-# can be added for each tagfile. The format of a tag file without 
-# this location is as follows: 
-#   TAGFILES = file1 file2 ... 
-# Adding location for the tag files is done as follows: 
-#   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool 
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
 # does not have to be run to correct the links.
 # Note that each tag file must have a unique name
 # (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen 
+# If a tag file is not located in the directory in which doxygen
 # is run, you must also specify the path to the tagfile here.
 
-TAGFILES               = 
+TAGFILES               =
 
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
 # a tag file that is based on the input files it reads.
 
-GENERATE_TAGFILE       = 
+GENERATE_TAGFILE       =
 
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
-# in the class index. If set to NO only the inherited external classes 
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
 # will be listed.
 
 ALLEXTERNALS           = NO
 
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
-# in the modules index. If set to NO, only the current project's groups will 
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
 # be listed.
 
 EXTERNAL_GROUPS        = YES
 
-# The PERL_PATH should be the absolute path and name of the perl script 
+# The PERL_PATH should be the absolute path and name of the perl script
 # interpreter (i.e. the result of `which perl').
 
 PERL_PATH              = /usr/bin/perl
 
 #---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
+# Configuration options related to the dot tool
 #---------------------------------------------------------------------------
 
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or 
-# super classes. Setting the tag to NO turns the diagrams off. Note that this 
-# option is superseded by the HAVE_DOT option below. This is only a fallback. It is 
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is
 # recommended to install and use dot, since it yields more powerful graphs.
 
 CLASS_DIAGRAMS         = YES
 
-# If set to YES, the inheritance and collaboration graphs will hide 
-# inheritance and usage relations if the target is undocumented 
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
 # or is not a class.
 
 HIDE_UNDOC_RELATIONS   = YES
 
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
-# available from the path. This tool is part of Graphviz, a graph visualization 
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
 # have no effect if this option is set to NO (the default)
 
 HAVE_DOT               = YES
 
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect inheritance relations. Setting this tag to YES will force the 
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
 # the CLASS_DIAGRAMS tag to NO.
 
 CLASS_GRAPH            = YES
 
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect implementation dependencies (inheritance, containment, and 
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
 # class references variables) of the class with other documented classes.
 
 COLLABORATION_GRAPH    = YES
 
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
-# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
 # Language.
 
 UML_LOOK               = YES
 
-# If set to YES, the inheritance and collaboration graphs will show the 
+# If set to YES, the inheritance and collaboration graphs will show the
 # relations between templates and their instances.
 
 TEMPLATE_RELATIONS     = NO
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
-# tags are set to YES then doxygen will generate a graph for each documented 
-# file showing the direct and indirect include dependencies of the file with 
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
 # other documented files.
 
 INCLUDE_GRAPH          = YES
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
-# documented header file showing the documented files that directly or 
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
 # indirectly include this file.
 
 INCLUDED_BY_GRAPH      = YES
 
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
-# generate a call dependency graph for every global function or class method. 
-# Note that enabling this option will significantly increase the time of a run. 
-# So in most cases it will be better to enable call graphs for selected 
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
 # functions only using the \callgraph command.
 
 CALL_GRAPH             = NO
 
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
 # will graphical hierarchy of all classes instead of a textual one.
 
 GRAPHICAL_HIERARCHY    = YES
 
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
 # generated by dot. Possible values are png, jpg, or gif
 # If left blank png will be used.
 
 DOT_IMAGE_FORMAT       = png
 
-# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
 # found. If left blank, it is assumed the dot tool can be found on the path.
 
-DOT_PATH               = 
+DOT_PATH               =
 
-# The DOTFILE_DIRS tag can be used to specify one or more directories that 
-# contain dot files that are included in the documentation (see the 
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
 # \dotfile command).
 
-DOTFILE_DIRS           = 
+DOTFILE_DIRS           =
 
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
 # large images.
 
 MAX_DOT_GRAPH_WIDTH    = 1024
 
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
 # large images.
 
 MAX_DOT_GRAPH_HEIGHT   = 1024
 
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
-# graphs generated by dot. A depth value of 3 means that only nodes reachable 
-# from the root by following a path via at most 3 edges will be shown. Nodes that 
-# lay further from the root node will be omitted. Note that setting this option to 
-# 1 or 2 may greatly reduce the computation time needed for large code bases. Also 
-# note that a graph may be further truncated if the graph's image dimensions are 
-# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). 
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
 # If 0 is used for the depth value (the default), the graph is not depth-constrained.
 
 MAX_DOT_GRAPH_DEPTH    = 0
 
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
-# generate a legend page explaining the meaning of the various boxes and 
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
 # arrows in the dot generated graphs.
 
 GENERATE_LEGEND        = YES
 
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
-# remove the intermediate dot files that are used to generate 
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
 # the various graphs.
 
 DOT_CLEANUP            = YES
 
 #---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
+# Configuration::additions related to the search engine
 #---------------------------------------------------------------------------
 
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# The SEARCHENGINE tag specifies whether or not a search engine should be
 # used. If set to NO the values of all tags below this one will be ignored.
 
 SEARCHENGINE           = NO
diff --git a/frmts/pcraster/libcsf/getattr.c b/frmts/pcraster/libcsf/getattr.c
index 9e99b04..f809573 100644
--- a/frmts/pcraster/libcsf/getattr.c
+++ b/frmts/pcraster/libcsf/getattr.c
@@ -4,7 +4,7 @@
 /* read an attribute (LIBRARY_INTERNAL)
  * MgetAttribute reads an attribute if it is available.
  * Be aware that you can't pass a simple pointer to some 
- * (array of) structure(s) due to allignment en endian problems.
+ * (array of) structure(s) due to alignment en endian problems.
  * At some time there will be a separate get function for each attribute
  * returns 0 if the attribute is not found, arg id if
  * the attribute is found.
diff --git a/frmts/pcraster/libcsf/kernlcsf.c b/frmts/pcraster/libcsf/kernlcsf.c
index 481d423..572f63a 100644
--- a/frmts/pcraster/libcsf/kernlcsf.c
+++ b/frmts/pcraster/libcsf/kernlcsf.c
@@ -87,20 +87,22 @@ void CsfRegisterMap(
 {
   size_t i=0;
 
-  while (mapList[i] != NULL && i < mapListLen)
+  while (i < mapListLen && mapList[i] != NULL)
     i++;
 
   if(i == mapListLen)
   {
     size_t j;
+    MAP** mapListNew;
     /* double size */
     /* +1 to make clang static analyzer not warn about realloc(0) */
     mapListLen = 2 * mapListLen + 1;
-    mapList=realloc(mapList,sizeof(MAP *)*mapListLen);
-    if (mapList == NULL) {
+    mapListNew=realloc(mapList,sizeof(MAP *)*mapListLen);
+    if (mapListNew == NULL) {
      (void)fprintf(stderr,"CSF_INTERNAL_ERROR: Not enough memory to use CSF-files\n");
       exit(1);
     }
+    mapList = mapListNew;
     /* initialize new part, i at begin */
     for(j=i; j < mapListLen; ++j)
       mapList[j]=0;
diff --git a/frmts/pcraster/libcsf/mperror.c b/frmts/pcraster/libcsf/mperror.c
index 8a49332..58cc14f 100644
--- a/frmts/pcraster/libcsf/mperror.c
+++ b/frmts/pcraster/libcsf/mperror.c
@@ -12,7 +12,7 @@ static const char * const errolist[ERRORNO]={
 "Illegal cell representation constant",
 "Access denied",
 "Row number to big",
-"Collumn number to big",
+"Column number to big",
 "Map is not a raster file",
 "Illegal conversion",
 "No space on device to write",
diff --git a/frmts/pcraster/libcsf/rextend.c b/frmts/pcraster/libcsf/rextend.c
index 4927338..cf60176 100644
--- a/frmts/pcraster/libcsf/rextend.c
+++ b/frmts/pcraster/libcsf/rextend.c
@@ -63,7 +63,7 @@ void RcomputeExtend(
 	double y_2,      /* second y-coordinate */
 	CSF_PT projection, /* required projection */
 	REAL8 cellSize, /* required cellsize, > 0 */
-	double rounding) /* assure that (xUL/rounding), (yUL/rouding)
+	double rounding) /* assure that (xUL/rounding), (yUL/rounding)
 	                  * (xLL/rounding) and (yLL/rounding) will
 	                 * will all be an integers values > 0 
 	                 */
diff --git a/frmts/pcraster/pcrasterdataset.cpp b/frmts/pcraster/pcrasterdataset.cpp
index 070e12d..24624dc 100644
--- a/frmts/pcraster/pcrasterdataset.cpp
+++ b/frmts/pcraster/pcrasterdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pcrasterdataset.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster CSF 2.0 raster file driver
@@ -34,16 +33,13 @@
 #include "pcrasterdataset.h"
 #include "pcrasterutil.h"
 
-CPL_CVSID("$Id: pcrasterdataset.cpp 33105 2016-01-23 15:27:32Z rouault $");
-
+CPL_CVSID("$Id: pcrasterdataset.cpp 36455 2016-11-22 23:11:35Z rouault $");
 
 /*!
   \file
   This file contains the implementation of the PCRasterDataset class.
 */
 
-
-
 //------------------------------------------------------------------------------
 // DEFINITION OF STATIC PCRDATASET MEMBERS
 //------------------------------------------------------------------------------
@@ -93,8 +89,6 @@ GDALDataset* PCRasterDataset::open(
   return dataset;
 }
 
-
-
 //! Writes a raster to \a filename as a PCRaster raster file.
 /*!
   \warning   The source raster must have only 1 band. Currently, the values in
@@ -171,8 +165,7 @@ GDALDataset* PCRasterDataset::createCopy(
   }
 
   // The in-memory type of the cells.
-  CSF_CR appCellRepresentation = CR_UNDEFINED;
-  appCellRepresentation = GDALType2CellRepresentation(
+  CSF_CR appCellRepresentation = GDALType2CellRepresentation(
          raster->GetRasterDataType(), true);
 
   if(appCellRepresentation == CR_UNDEFINED) {
@@ -285,15 +278,13 @@ GDALDataset* PCRasterDataset::createCopy(
   return poDS;
 }
 
-
-
 //------------------------------------------------------------------------------
 // DEFINITION OF PCRDATASET MEMBERS
 //------------------------------------------------------------------------------
 
 //! Constructor.
 /*!
-  \param     map PCRaster map handle. It is ours to close.
+  \param     mapIn PCRaster map handle. It is ours to close.
 */
 PCRasterDataset::PCRasterDataset( MAP* mapIn) :
     GDALPamDataset(),
@@ -329,8 +320,6 @@ PCRasterDataset::PCRasterDataset( MAP* mapIn) :
          d_valueScale).c_str());
 }
 
-
-
 //! Destructor.
 /*!
   \warning   The map given in the constructor is closed.
@@ -341,8 +330,6 @@ PCRasterDataset::~PCRasterDataset()
     Mclose(d_map);
 }
 
-
-
 //! Sets projections info.
 /*!
   \param     transform Array to fill.
@@ -367,8 +354,6 @@ CPLErr PCRasterDataset::GetGeoTransform(double* transform)
   return CE_None;
 }
 
-
-
 //! Returns the map handle.
 /*!
   \return    Map handle.
@@ -378,8 +363,6 @@ MAP* PCRasterDataset::map() const
   return d_map;
 }
 
-
-
 //! Returns the in-app cell representation.
 /*!
   \return    cell representation
@@ -391,8 +374,6 @@ CSF_CR PCRasterDataset::cellRepresentation() const
   return d_cellRepresentation;
 }
 
-
-
 //! Returns the value scale of the data.
 /*!
   \return    Value scale
@@ -403,8 +384,6 @@ CSF_VS PCRasterDataset::valueScale() const
   return d_valueScale;
 }
 
-
-
 //! Returns the value of the missing value.
 /*!
   \return    Missing value
@@ -414,7 +393,6 @@ double PCRasterDataset::defaultNoDataValue() const
   return d_defaultNoDataValue;
 }
 
-
 GDALDataset* PCRasterDataset::create(
      const char* filename,
      int nr_cols,
@@ -472,7 +450,6 @@ GDALDataset* PCRasterDataset::create(
     return NULL;
   }
 
-
   CSF_VS csf_value_scale = string2ValueScale(valueScale);
 
   if(csf_value_scale == VS_UNDEFINED){
@@ -515,7 +492,6 @@ GDALDataset* PCRasterDataset::create(
   return poDS;
 }
 
-
 CPLErr PCRasterDataset::SetGeoTransform(double* transform)
 {
   if((transform[2] != 0.0) || (transform[4] != 0.0)) {
@@ -540,7 +516,6 @@ CPLErr PCRasterDataset::SetGeoTransform(double* transform)
   return CE_None;
 }
 
-
 bool PCRasterDataset::location_changed() const {
   return d_location_changed;
 }
diff --git a/frmts/pcraster/pcrasterdataset.h b/frmts/pcraster/pcrasterdataset.h
index 2abcf97..58466ed 100644
--- a/frmts/pcraster/pcrasterdataset.h
+++ b/frmts/pcraster/pcrasterdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterdataset.h 31137 2015-10-26 12:58:08Z goatbar $
+ * $Id: pcrasterdataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster CSF 2.0 raster file driver declarations.
@@ -40,12 +40,8 @@ namespace gdal {
   class PCRasterDatasetTest;
 }
 
-
-
 // namespace {
 
-
-
 //! This class specialises the GDALDataset class for PCRaster datasets.
 /*!
   PCRaster raster datasets are currently formatted by the CSF 2.0 data format.
@@ -117,7 +113,7 @@ public:
   // CREATORS
   //----------------------------------------------------------------------------
 
-                   PCRasterDataset     (MAP* map);
+  explicit          PCRasterDataset     (MAP* map);
 
   /* virtual */    ~PCRasterDataset    ();
 
@@ -125,24 +121,18 @@ public:
   // MANIPULATORS
   //----------------------------------------------------------------------------
 
-  CPLErr           SetGeoTransform     (double* transform);
+  CPLErr           SetGeoTransform     (double* transform) override;
 
   //----------------------------------------------------------------------------
   // ACCESSORS
   //----------------------------------------------------------------------------
 
   MAP*             map                 () const;
-
-  CPLErr           GetGeoTransform     (double* transform);
-
+  CPLErr           GetGeoTransform     (double* transform) override;
   CSF_CR           cellRepresentation  () const;
-
   CSF_VS           valueScale          () const;
-
   double           defaultNoDataValue  () const;
-
   bool             location_changed    () const;
-
 };
 // } // namespace
 
diff --git a/frmts/pcraster/pcrastermisc.cpp b/frmts/pcraster/pcrastermisc.cpp
index 7f8c055..4ab3984 100644
--- a/frmts/pcraster/pcrastermisc.cpp
+++ b/frmts/pcraster/pcrastermisc.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pcrastermisc.cpp 32215 2015-12-18 06:30:54Z goatbar $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster driver support functions.
@@ -31,6 +30,8 @@
 #include "gdal_pam.h"
 #include "pcrasterdataset.h"
 
+CPL_CVSID("$Id: pcrastermisc.cpp 34811 2016-07-28 15:15:05Z goatbar $");
+
 void GDALRegister_PCRaster()
 {
     if( !GDAL_CHECK_VERSION( "PCRaster driver" ) )
diff --git a/frmts/pcraster/pcrasterrasterband.cpp b/frmts/pcraster/pcrasterrasterband.cpp
index 88bdd44..359aec8 100644
--- a/frmts/pcraster/pcrasterrasterband.cpp
+++ b/frmts/pcraster/pcrasterrasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pcrasterrasterband.cpp 31680 2015-11-21 13:44:47Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster raster band implementation.
@@ -33,6 +32,8 @@
 #include "pcrasterrasterband.h"
 #include "pcrasterutil.h"
 
+CPL_CVSID("$Id: pcrasterrasterband.cpp 35929 2016-10-25 16:09:00Z goatbar $");
+
 /*!
   \file
   This file contains the implementation of the PCRasterRasterBand class.
@@ -146,8 +147,6 @@ double PCRasterRasterBand::GetMinimum(
   return result;
 }
 
-
-
 double PCRasterRasterBand::GetMaximum(
          int* success)
 {
@@ -212,8 +211,6 @@ double PCRasterRasterBand::GetMaximum(
   return result;
 }
 
-
-
 CPLErr PCRasterRasterBand::IReadBlock(
     CPL_UNUSED int nBlockXoff,
     int nBlockYoff,
@@ -233,7 +230,6 @@ CPLErr PCRasterRasterBand::IReadBlock(
   return CE_None;
 }
 
-
 CPLErr PCRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag,
                                      int nXOff, int nYOff, int nXSize,
                                      int nYSize, void * pData,
@@ -249,7 +245,8 @@ CPLErr PCRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag,
                                      pData, nBufXSize, nBufYSize, eBufType,
                                      nPixelSpace, nLineSpace, psExtraArg);
   }
-  else{
+  else
+  {
     // the datatype of the incoming data can be of different type than the
     // cell representation used in the raster
     // 'remember' the GDAL type to distinguish it later on in iWriteBlock
@@ -257,12 +254,9 @@ CPLErr PCRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag,
     return GDALRasterBand::IRasterIO(GF_Write, nXOff, nYOff, nXSize, nYSize,
                                      pData, nBufXSize, nBufYSize, eBufType,
                                      nPixelSpace, nLineSpace, psExtraArg);
-
   }
 }
 
-
-
 CPLErr PCRasterRasterBand::IWriteBlock(
     CPL_UNUSED int nBlockXoff,
     int nBlockYoff,
@@ -358,7 +352,6 @@ CPLErr PCRasterRasterBand::IWriteBlock(
   return CE_None;
 }
 
-
 CPLErr PCRasterRasterBand::SetNoDataValue(double nodata)
 {
   d_noDataValue = nodata;
diff --git a/frmts/pcraster/pcrasterrasterband.h b/frmts/pcraster/pcrasterrasterband.h
index abda85d..ba16db6 100644
--- a/frmts/pcraster/pcrasterrasterband.h
+++ b/frmts/pcraster/pcrasterrasterband.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterrasterband.h 31137 2015-10-26 12:58:08Z goatbar $
+ * $Id: pcrasterrasterband.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster raster band declaration.
@@ -58,7 +58,7 @@ private:
                                         void *, int, int, GDALDataType,
                                         GSpacing nPixelSpace,
                                         GSpacing nLineSpace,
-                                        GDALRasterIOExtraArg* psExtraArg);
+                                        GDALRasterIOExtraArg* psExtraArg) override;
 
   //! Assignment operator. NOT IMPLEMENTED.
   PCRasterRasterBand& operator=        (const PCRasterRasterBand&);
@@ -67,12 +67,12 @@ private:
                    PCRasterRasterBand  (const PCRasterRasterBand&);
 
 protected:
-  double           GetNoDataValue      (int* success=NULL);
-  double           GetMinimum          (int* success);
-  double           GetMaximum          (int* success);
+  double           GetNoDataValue      (int* success=NULL) override;
+  double           GetMinimum          (int* success) override;
+  double           GetMaximum          (int* success) override;
 
 public:
-                   PCRasterRasterBand  (PCRasterDataset* dataset);
+  explicit          PCRasterRasterBand  (PCRasterDataset* dataset);
   /* virtual */    ~PCRasterRasterBand ();
 
   //----------------------------------------------------------------------------
@@ -81,9 +81,9 @@ public:
 
   CPLErr           IWriteBlock         (CPL_UNUSED int nBlockXoff,
                                         int nBlockYoff,
-                                        void* buffer);
+                                        void* buffer) override;
 
-  CPLErr           SetNoDataValue      (double no_data);
+  CPLErr           SetNoDataValue      (double no_data) override;
 
   //----------------------------------------------------------------------------
   // ACCESSORS
@@ -91,7 +91,7 @@ public:
 
   CPLErr           IReadBlock          (int nBlockXoff,
                                         int nBlockYoff,
-                                        void* buffer);
+                                        void* buffer) override;
 };
 // } // namespace
 
diff --git a/frmts/pcraster/pcrasterutil.cpp b/frmts/pcraster/pcrasterutil.cpp
index 45ebc91..00a4c9a 100644
--- a/frmts/pcraster/pcrasterutil.cpp
+++ b/frmts/pcraster/pcrasterutil.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pcrasterutil.cpp 32957 2016-01-12 18:53:43Z rouault $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster driver support functions.
@@ -34,6 +33,7 @@
 #include "pcrasterutil.h"
 #include "pcrtypes.h"
 
+CPL_CVSID("$Id: pcrasterutil.cpp 35897 2016-10-24 11:54:24Z goatbar $");
 
 //! Converts PCRaster data type to GDAL data type.
 /*!
@@ -88,7 +88,6 @@ GDALDataType cellRepresentation2GDALType(
   return type;
 }
 
-
 CSF_VS string2ValueScale(
          std::string const& string)
 {
@@ -127,7 +126,6 @@ CSF_VS string2ValueScale(
   return valueScale;
 }
 
-
 std::string valueScale2String(
          CSF_VS valueScale)
 {
@@ -180,7 +178,6 @@ std::string valueScale2String(
   return result;
 }
 
-
 std::string cellRepresentation2String(
          CSF_CR cellRepresentation)
 {
@@ -230,7 +227,6 @@ std::string cellRepresentation2String(
   return result;
 }
 
-
 //! Converts GDAL data type to PCRaster value scale.
 /*!
   \param     type GDAL data type.
@@ -279,7 +275,6 @@ CSF_VS GDALType2ValueScale(
   return valueScale;
 }
 
-
 //! Converts a GDAL type to a PCRaster cell representation.
 /*!
   \param     type GDAL type.
@@ -339,7 +334,6 @@ CSF_CR GDALType2CellRepresentation(
   return cellRepresentation;
 }
 
-
 //! Determines a missing value to use for data of \a cellRepresentation.
 /*!
   \param     cellRepresentation Cell representation of the data.
@@ -404,7 +398,6 @@ double missingValue(
   return missingValue;
 }
 
-
 //! Opens the raster in \a filename using mode \a mode.
 /*!
   \param     filename Filename of raster to open.
@@ -422,7 +415,6 @@ MAP* mapOpen(
   return map;
 }
 
-
 void alterFromStdMV(
          void* buffer,
          size_t size,
@@ -487,7 +479,6 @@ void alterFromStdMV(
   }
 }
 
-
 void alterToStdMV(
          void* buffer,
          size_t size,
@@ -552,7 +543,6 @@ void alterToStdMV(
   }
 }
 
-
 CSF_VS fitValueScale(
          CSF_VS valueScale,
          CSF_CR cellRepresentation)
@@ -619,7 +609,6 @@ CSF_VS fitValueScale(
   return result;
 }
 
-
 void castValuesToBooleanRange(
          void* buffer,
          size_t size,
@@ -683,7 +672,6 @@ void castValuesToBooleanRange(
   }
 }
 
-
 void castValuesToDirectionRange(
          void* buffer,
          size_t size)
@@ -693,7 +681,6 @@ void castValuesToDirectionRange(
        CastToDirection());
 }
 
-
 void castValuesToLddRange(
          void* buffer,
          size_t size)
diff --git a/frmts/pcraster/pcrasterutil.h b/frmts/pcraster/pcrasterutil.h
index fefeeee..dc9cba8 100644
--- a/frmts/pcraster/pcrasterutil.h
+++ b/frmts/pcraster/pcrasterutil.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pcrasterutil.h 31687 2015-11-21 16:35:21Z rouault $
+ * $Id: pcrasterutil.h 35897 2016-10-24 11:54:24Z goatbar $
  *
  * Project:  PCRaster Integration
  * Purpose:  PCRaster driver support declarations.
@@ -34,7 +34,6 @@
 #include "gdal_priv.h"
 #include "pcrtypes.h"
 
-
 GDALDataType       cellRepresentation2GDALType(CSF_CR cellRepresentation);
 
 CSF_VS             string2ValueScale   (const std::string& string);
@@ -107,7 +106,6 @@ struct CastToBooleanRange
   }
 };
 
-
 template<>
 struct CastToBooleanRange<UINT1>
 {
@@ -118,7 +116,6 @@ struct CastToBooleanRange<UINT1>
   }
 };
 
-
 template<>
 struct CastToBooleanRange<UINT2>
 {
@@ -129,7 +126,6 @@ struct CastToBooleanRange<UINT2>
   }
 };
 
-
 template<>
 struct CastToBooleanRange<UINT4>
 {
@@ -140,7 +136,6 @@ struct CastToBooleanRange<UINT4>
   }
 };
 
-
 struct CastToDirection
 {
   void operator()(REAL4& value) {
@@ -151,7 +146,6 @@ struct CastToDirection
   }
 };
 
-
 struct CastToLdd
 {
   void operator()(UINT1& value) {
diff --git a/frmts/pdf/GNUmakefile b/frmts/pdf/GNUmakefile
index f5b7f41..a032455 100644
--- a/frmts/pdf/GNUmakefile
+++ b/frmts/pdf/GNUmakefile
@@ -37,6 +37,13 @@ endif
 
 ifeq ($(HAVE_PDFIUM),yes)
 CPPFLAGS +=  -DHAVE_PDFIUM
+# -Wzero-as-null-pointer-constant -DNULL_AS_NULLPTR isn't compatible of pdfium headers
+# /home/even/pdfium/install/include/pdfium/third_party/base/numerics/safe_conversions.h: In instantiation of ‘Dst pdfium::base::checked_cast(Src) [with Dst = int; Src = long unsigned int]’:
+# /home/even/pdfium/install/include/pdfium/core/include/fxcrt/fx_string.h:43:26:   required from here
+# /home/even/pdfium/install/include/pdfium/third_party/base/numerics/safe_conversions.h:29:3: erreur: invalid cast from type ‘std::nullptr_t’ to type ‘volatile char*’
+#    CHECK(IsValueInRangeForNumericType<Dst>(value));
+CXX := $(subst -Wzero-as-null-pointer-constant,,${CXX})
+CXX := $(subst -DNULL_AS_NULLPTR,,${CXX})
 endif
 
 $(O_OBJ):       pdfobject.h pdfio.h pdfcreatecopy.h gdal_pdf.h ../../ogr/ogrsf_frmts/mem/ogr_mem.h
diff --git a/frmts/pdf/frmt_pdf.html b/frmts/pdf/frmt_pdf.html
index 2dc3ac4..90d4ccc 100644
--- a/frmts/pdf/frmt_pdf.html
+++ b/frmts/pdf/frmt_pdf.html
@@ -28,7 +28,10 @@ Starting with GDAL 1.10, this driver can read and write geospatial PDF with vect
 Vector read support requires linking to one of the above mentioned dependent libraries, but write support does not.
 
 The driver can read vector features encoded according to PDF's logical structure facilities (as described by "§10.6 - Logical Structure" of PDF spec),
-or retrieve only vector geometries for other vector PDF files.<p>
+or retrieve only vector geometries for other vector PDF files.</p>
+
+<p>If there is no such logical structure, the driver will not try to interpret the vector
+content of the PDF, unless you defined the OGR_PDF_READ_NON_STRUCTURED configuration option to YES.</p>
 
 <h2>Feature style support</h2>
 
@@ -185,6 +188,17 @@ Set the DPI to use. Default to 72. May be automatically adjusted to higher value
 so that page dimension does not exceed the 14400 maximum value (in user units)
 allowed by Acrobat.</p></li>
 
+<li><p><b>WRITE_USERUNIT=YES/NO</b>: (GDAL >= 2.2)
+Whether the UserUnit setting computed from the DPI (UserUnit = DPI / 72.0)
+should be recorded in the file. When UserUnit is recorded, the raster size in
+pixels recognized by GDAL on reading remains identical to the source raster.
+When UserUnit is not recorded, the printed size will depends on the DPI value.
+If this parameter is not set, but DPI is specified, then it will default to NO
+(so that the printed size depends on the DPI value). If this parameter is not
+set and DPI is not specified, then UserUnit will be recorded (so that the
+raster size in pixels recognized by GDAL on reading remain identical to the
+source raster).</p></li>
+
 <li><p><b>PREDICTOR=[1/2]</b>:
 Only for DEFLATE compression. Might be set to 2 to use horizontal predictor that can make files smaller (but not always!).
 1 is the default.</p></li>
@@ -426,8 +440,11 @@ Libraries :
 Samples :
 
 <ul>
+<!--
 <li><a href="http://acrobatusers.com/gallery/geospatial">A few Geospatial PDF samples</a></li>
 <li><a href="http://www.agc.army.mil/geopdf_gallery.html">Another set of Geospatial PDF samples</a></li>
+-->
+<li><a href="https://www.terragotech.com/learn-more/sample-geopdfs">A few Geospatial PDF samples</a></li>
 <li><a href="http://latuviitta.org/documents/Geospatial_PDF_maps_from_OSM_with_GDAL.pdf">Tutorial to generate Geospatial PDF maps from OSM data</a></li>
 </ul>
 
diff --git a/frmts/pdf/gdal_pdf.h b/frmts/pdf/gdal_pdf.h
index c9ec186..a083cb7 100644
--- a/frmts/pdf/gdal_pdf.h
+++ b/frmts/pdf/gdal_pdf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gdal_pdf.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  PDF Translator
  * Purpose:  Definition of classes for OGR .pdf driver.
@@ -69,14 +69,14 @@ class OGRPDFLayer : public OGRMemLayer
     int               bGeomTypeMixed;
 
 public:
-        OGRPDFLayer(PDFDataset* poDS,
-                    const char * pszName,
-                    OGRSpatialReference *poSRS,
-                    OGRwkbGeometryType eGeomType);
+        OGRPDFLayer( PDFDataset* poDS,
+                     const char * pszName,
+                     OGRSpatialReference *poSRS,
+                     OGRwkbGeometryType eGeomType );
 
     void                Fill( GDALPDFArray* poArray );
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 #endif
@@ -97,8 +97,8 @@ public:
                     OGRSpatialReference *poSRS,
                     OGRwkbGeometryType eGeomType);
 
-    virtual int                 TestCapability( const char * );
-    virtual OGRErr              ICreateFeature( OGRFeature *poFeature );
+    virtual int                 TestCapability( const char * ) override;
+    virtual OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
 };
 
 /************************************************************************/
@@ -226,7 +226,8 @@ class PDFDataset : public GDALPamDataset
 
     int          bTried;
     GByte       *pabyCachedData;
-    int          nLastBlockXOff, nLastBlockYOff;
+    int          nLastBlockXOff;
+    int          nLastBlockYOff;
 
     OGRPolygon*  poNeatLine;
 
@@ -343,34 +344,34 @@ private:
                  PDFDataset(PDFDataset* poParentDS = NULL, int nXSize = 0, int nYSize = 0);
     virtual     ~PDFDataset();
 
-    virtual const char* GetProjectionRef();
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char* GetProjectionRef() override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
-    virtual CPLErr      SetProjection(const char* pszWKTIn);
-    virtual CPLErr      SetGeoTransform(double* padfGeoTransform);
+    virtual CPLErr      SetProjection(const char* pszWKTIn) override;
+    virtual CPLErr      SetGeoTransform(double* padfGeoTransform) override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                          const char * pszValue,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
 
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               int, int *,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) override;
 
     CPLErr ReadPixels( int nReqXOff, int nReqYOff,
                        int nReqXSize, int nReqYSize,
@@ -379,10 +380,10 @@ private:
                        GSpacing nBandSpace,
                        GByte* pabyData );
 
-    virtual int                 GetLayerCount();
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override;
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     OGRGeometry        *GetGeometryFromMCID(int nMCID);
 
@@ -391,7 +392,7 @@ private:
 
 #ifdef HAVE_PDFIUM
     virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
+                                    int, int *, GDALProgressFunc, void * ) override;
 
     static int bPdfiumInit;
 #endif
@@ -414,21 +415,21 @@ class PDFRasterBand : public GDALPamRasterBand
   public:
 
                 PDFRasterBand( PDFDataset *, int, int );
-                ~PDFRasterBand();
+    virtual ~PDFRasterBand();
 
 #ifdef HAVE_PDFIUM
-    virtual int    GetOverviewCount();
-    virtual GDALRasterBand *GetOverview( int );
+    virtual int    GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview( int ) override;
 #endif  // ~ HAVE_PDFIUM
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 
 #ifdef notdef
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 #endif
 };
 
@@ -449,19 +450,19 @@ class PDFWritableVectorDataset : public GDALDataset
 
     public:
                             PDFWritableVectorDataset();
-                           ~PDFWritableVectorDataset();
+        virtual ~PDFWritableVectorDataset();
 
         virtual OGRLayer*           ICreateLayer( const char * pszLayerName,
                                                 OGRSpatialReference *poSRS,
                                                 OGRwkbGeometryType eType,
-                                                char ** papszOptions );
+                                                char ** papszOptions ) override;
 
         virtual OGRErr              SyncToDisk();
 
-        virtual int                 GetLayerCount();
-        virtual OGRLayer*           GetLayer( int );
+        virtual int                 GetLayerCount() override;
+        virtual OGRLayer*           GetLayer( int ) override;
 
-        virtual int                 TestCapability( const char * );
+        virtual int                 TestCapability( const char * ) override;
 
         static GDALDataset* Create( const char * pszName,
                                  int nXSize, int nYSize, int nBands,
diff --git a/frmts/pdf/ogrpdflayer.cpp b/frmts/pdf/ogrpdflayer.cpp
index 86c44a3..4a56715 100644
--- a/frmts/pdf/ogrpdflayer.cpp
+++ b/frmts/pdf/ogrpdflayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  PDF Translator
  * Purpose:  Implements OGRPDFDataSource class
@@ -29,7 +28,7 @@
 
 #include "gdal_pdf.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogrpdflayer.cpp 35261 2016-08-31 05:17:08Z goatbar $");
 
 #if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
 
@@ -41,12 +40,11 @@ OGRPDFLayer::OGRPDFLayer( PDFDataset* poDSIn,
                           const char * pszName,
                           OGRSpatialReference *poSRS,
                           OGRwkbGeometryType eGeomType ) :
-                                OGRMemLayer(pszName, poSRS, eGeomType )
-{
-    this->poDS = poDSIn;
-    bGeomTypeSet = FALSE;
-    bGeomTypeMixed = FALSE;
-}
+    OGRMemLayer(pszName, poSRS, eGeomType ),
+    poDS(poDSIn),
+    bGeomTypeSet(FALSE),
+    bGeomTypeMixed(FALSE)
+{}
 
 /************************************************************************/
 /*                              Fill()                                  */
@@ -177,13 +175,12 @@ int OGRPDFLayer::TestCapability( const char * pszCap )
 /************************************************************************/
 
 OGRPDFWritableLayer::OGRPDFWritableLayer( PDFWritableVectorDataset* poDSIn,
-                          const char * pszName,
-                          OGRSpatialReference *poSRS,
-                          OGRwkbGeometryType eGeomType ) :
-                                OGRMemLayer(pszName, poSRS, eGeomType )
-{
-    this->poDS = poDSIn;
-}
+                                          const char * pszName,
+                                          OGRSpatialReference *poSRS,
+                                          OGRwkbGeometryType eGeomType ) :
+    OGRMemLayer(pszName, poSRS, eGeomType ),
+    poDS(poDSIn)
+{}
 
 /************************************************************************/
 /*                           ICreateFeature()                           */
diff --git a/frmts/pdf/pdfcreatecopy.cpp b/frmts/pdf/pdfcreatecopy.cpp
index 3215ec3..43c2849 100644
--- a/frmts/pdf/pdfcreatecopy.cpp
+++ b/frmts/pdf/pdfcreatecopy.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pdfcreatecopy.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -39,10 +38,14 @@
 
 #include "pdfobject.h"
 
+#include <cmath>
+
+#include <algorithm>
+
 /* Cf PDF reference v1.7, Appendix C, page 993 */
 #define MAXIMUM_SIZE_IN_UNITS   14400
 
-CPL_CVSID("$Id: pdfcreatecopy.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+CPL_CVSID("$Id: pdfcreatecopy.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 #define PIXEL_TO_GEO_X(x,y) adfGeoTransform[0] + x * adfGeoTransform[1] + y * adfGeoTransform[2]
 #define PIXEL_TO_GEO_Y(x,y) adfGeoTransform[3] + x * adfGeoTransform[4] + y * adfGeoTransform[5]
@@ -54,37 +57,31 @@ class GDALFakePDFDataset : public GDALDataset
 };
 
 /************************************************************************/
-/*                             Init()                                   */
-/************************************************************************/
-
-void GDALPDFWriter::Init()
-{
-    nPageResourceId = 0;
-    nStructTreeRootId = 0;
-    nCatalogId = nCatalogGen = 0;
-    bInWriteObj = FALSE;
-    nInfoId = nInfoGen = 0;
-    nXMPId = nXMPGen = 0;
-    nNamesId = 0;
-
-    nLastStartXRef = 0;
-    nLastXRefSize = 0;
-    bCanUpdate = FALSE;
-}
-
-/************************************************************************/
 /*                         GDALPDFWriter()                              */
 /************************************************************************/
 
-GDALPDFWriter::GDALPDFWriter(VSILFILE* fpIn, int bAppend) : fp(fpIn)
+GDALPDFWriter::GDALPDFWriter( VSILFILE* fpIn, int bAppend ) :
+    fp(fpIn),
+    nInfoId(0),
+    nInfoGen(0),
+    nPageResourceId(0),
+    nStructTreeRootId(0),
+    nCatalogId(0),
+    nCatalogGen(0),
+    nXMPId(0),
+    nXMPGen(0),
+    nNamesId(0),
+    bInWriteObj(FALSE),
+    nLastStartXRef(0),
+    nLastXRefSize(0),
+    bCanUpdate(FALSE)
 {
-    Init();
-
-    if (!bAppend)
+    if( !bAppend )
     {
         VSIFPrintfL(fp, "%%PDF-1.6\n");
 
-        /* See PDF 1.7 reference, page 92. Write 4 non-ASCII bytes to indicate that the content will be binary */
+        // See PDF 1.7 reference, page 92. Write 4 non-ASCII bytes to indicate
+        // that the content will be binary.
         VSIFPrintfL(fp, "%%%c%c%c%c\n", 0xFF, 0xFF, 0xFF, 0xFF);
 
         nPageResourceId = AllocNewObject();
@@ -183,7 +180,7 @@ int GDALPDFWriter::ParseTrailerAndXRef()
     VSIFSeekL(fp, nLastStartXRef, SEEK_SET);
 
     /* And skip to trailer */
-    const char* pszLine;
+    const char* pszLine = NULL;
     while( (pszLine = CPLReadLineL(fp)) != NULL)
     {
         if (STARTS_WITH(pszLine, "trailer"))
@@ -240,7 +237,8 @@ int GDALPDFWriter::ParseTrailerAndXRef()
         if (!ParseIndirectRef(pszInfo, nInfoId, nInfoGen))
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot parse trailer /Info");
-            nInfoId = nInfoGen = 0;
+            nInfoId = 0;
+            nInfoGen = 0;
         }
     }
 
@@ -509,7 +507,6 @@ void GDALPDFWriter::EndObj()
     bInWriteObj = FALSE;
 }
 
-
 /************************************************************************/
 /*                         GDALPDFFind4Corners()                        */
 /************************************************************************/
@@ -518,7 +515,8 @@ static
 void GDALPDFFind4Corners(const GDAL_GCP* pasGCPList,
                          int& iUL, int& iUR, int& iLR, int& iLL)
 {
-    double dfMeanX = 0, dfMeanY = 0;
+    double dfMeanX = 0.0;
+    double dfMeanY = 0.0;
     int i;
 
     iUL = 0;
@@ -603,15 +601,26 @@ int  GDALPDFWriter::WriteSRS_ISO32000(GDALDataset* poSrcDS,
             {
                 for(int i=0;i<4;i++)
                 {
-                    double X = asNeatLineGCPs[i].dfGCPX = poLS->getX(i);
-                    double Y = asNeatLineGCPs[i].dfGCPY = poLS->getY(i);
-                    double x = adfGeoTransformInv[0] + X * adfGeoTransformInv[1] + Y * adfGeoTransformInv[2];
-                    double y = adfGeoTransformInv[3] + X * adfGeoTransformInv[4] + Y * adfGeoTransformInv[5];
+                    const double X = poLS->getX(i);
+                    const double Y = poLS->getY(i);
+                    asNeatLineGCPs[i].dfGCPX = X;
+                    asNeatLineGCPs[i].dfGCPY = Y;
+                    const double x =
+                        adfGeoTransformInv[0] +
+                        X * adfGeoTransformInv[1] +
+                        Y * adfGeoTransformInv[2];
+                    const double y =
+                        adfGeoTransformInv[3] +
+                        X * adfGeoTransformInv[4] +
+                        Y * adfGeoTransformInv[5];
                     asNeatLineGCPs[i].dfGCPPixel = x;
                     asNeatLineGCPs[i].dfGCPLine = y;
                 }
 
-                int iUL = 0, iUR = 0, iLR = 0, iLL = 0;
+                int iUL = 0;
+                int iUR = 0;
+                int iLR = 0;
+                int iLL = 0;
                 GDALPDFFind4Corners(asNeatLineGCPs,
                                     iUL,iUR, iLR, iLL);
 
@@ -640,7 +649,10 @@ int  GDALPDFWriter::WriteSRS_ISO32000(GDALDataset* poSrcDS,
 
     if( pasGCPList )
     {
-        int iUL = 0, iUR = 0, iLR = 0, iLL = 0;
+        int iUL = 0;
+        int iUR = 0;
+        int iLR = 0;
+        int iLL = 0;
         GDALPDFFind4Corners(pasGCPList,
                             iUL,iUR, iLR, iLL);
 
@@ -792,7 +804,6 @@ int  GDALPDFWriter::WriteSRS_ISO32000(GDALDataset* poSrcDS,
     VSIFPrintfL(fp, "%s\n", oMeasureDict.Serialize().c_str());
     EndObj();
 
-
     StartObj(nGCSId);
     GDALPDFDictionaryRW oGCSDict;
     oGCSDict.Add("Type", GDALPDFObjectRW::CreateName(bIsGeographic ? "GEOGCS" : "PROJCS"))
@@ -853,97 +864,97 @@ static GDALPDFObject* GDALPDFBuildOGC_BP_Datum(const OGRSpatialReference* poSRS)
 
 #ifdef disabled_because_terrago_toolbar_does_not_like_it
                 const char* pszEllipsoidCode = NULL;
-                if( ABS(dfSemiMajor-6378249.145) < 0.01
-                    && ABS(dfInvFlattening-293.465) < 0.0001 )
+                if( std::abs(dfSemiMajor - 6378249.145) < 0.01
+                    && std::abs(dfInvFlattening-293.465) < 0.0001 )
                 {
                     pszEllipsoidCode = "CD";     /* Clark 1880 */
                 }
-                else if( ABS(dfSemiMajor-6378245.0) < 0.01
-                         && ABS(dfInvFlattening-298.3) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378245.0) < 0.01
+                         x&& std::abs(dfInvFlattening-298.3) < 0.0001 )
                 {
                     pszEllipsoidCode = "KA";      /* Krassovsky */
                 }
-                else if( ABS(dfSemiMajor-6378388.0) < 0.01
-                         && ABS(dfInvFlattening-297.0) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378388.0) < 0.01
+                         && std::abs(dfInvFlattening-297.0) < 0.0001 )
                 {
                     pszEllipsoidCode = "IN";       /* International 1924 */
                 }
-                else if( ABS(dfSemiMajor-6378160.0) < 0.01
-                         && ABS(dfInvFlattening-298.25) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378160.0) < 0.01
+                         && std::abs(dfInvFlattening-298.25) < 0.0001 )
                 {
                     pszEllipsoidCode = "AN";    /* Australian */
                 }
-                else if( ABS(dfSemiMajor-6377397.155) < 0.01
-                         && ABS(dfInvFlattening-299.1528128) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6377397.155) < 0.01
+                         && std::abs(dfInvFlattening-299.1528128) < 0.0001 )
                 {
                     pszEllipsoidCode = "BR";     /* Bessel 1841 */
                 }
-                else if( ABS(dfSemiMajor-6377483.865) < 0.01
-                         && ABS(dfInvFlattening-299.1528128) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6377483.865) < 0.01
+                         && std::abs(dfInvFlattening-299.1528128) < 0.0001 )
                 {
                     pszEllipsoidCode = "BN";   /* Bessel 1841 (Namibia / Schwarzeck)*/
                 }
 #if 0
-                else if( ABS(dfSemiMajor-6378160.0) < 0.01
-                         && ABS(dfInvFlattening-298.247167427) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378160.0) < 0.01
+                         && std::abs(dfInvFlattening-298.247167427) < 0.0001 )
                 {
                     pszEllipsoidCode = "GRS67";      /* GRS 1967 */
                 }
 #endif
-                else if( ABS(dfSemiMajor-6378137) < 0.01
-                         && ABS(dfInvFlattening-298.257222101) < 0.000001 )
+                else if( std::abs(dfSemiMajor-6378137) < 0.01
+                         && std::abs(dfInvFlattening-298.257222101) < 0.000001 )
                 {
                     pszEllipsoidCode = "RF";      /* GRS 1980 */
                 }
-                else if( ABS(dfSemiMajor-6378206.4) < 0.01
-                         && ABS(dfInvFlattening-294.9786982) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378206.4) < 0.01
+                         && std::abs(dfInvFlattening-294.9786982) < 0.0001 )
                 {
                     pszEllipsoidCode = "CC";     /* Clarke 1866 */
                 }
-                else if( ABS(dfSemiMajor-6377340.189) < 0.01
-                         && ABS(dfInvFlattening-299.3249646) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6377340.189) < 0.01
+                         && std::abs(dfInvFlattening-299.3249646) < 0.0001 )
                 {
                     pszEllipsoidCode = "AM";   /* Modified Airy */
                 }
-                else if( ABS(dfSemiMajor-6377563.396) < 0.01
-                         && ABS(dfInvFlattening-299.3249646) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6377563.396) < 0.01
+                         && std::abs(dfInvFlattening-299.3249646) < 0.0001 )
                 {
                     pszEllipsoidCode = "AA";       /* Airy */
                 }
-                else if( ABS(dfSemiMajor-6378200) < 0.01
-                         && ABS(dfInvFlattening-298.3) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378200) < 0.01
+                         && std::abs(dfInvFlattening-298.3) < 0.0001 )
                 {
                     pszEllipsoidCode = "HE";    /* Helmert 1906 */
                 }
-                else if( ABS(dfSemiMajor-6378155) < 0.01
-                         && ABS(dfInvFlattening-298.3) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378155) < 0.01
+                         && std::abs(dfInvFlattening-298.3) < 0.0001 )
                 {
                     pszEllipsoidCode = "FA";   /* Modified Fischer 1960 */
                 }
 #if 0
-                else if( ABS(dfSemiMajor-6377298.556) < 0.01
-                         && ABS(dfInvFlattening-300.8017) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6377298.556) < 0.01
+                         && std::abs(dfInvFlattening-300.8017) < 0.0001 )
                 {
                     pszEllipsoidCode = "evrstSS";    /* Everest (Sabah & Sarawak) */
                 }
-                else if( ABS(dfSemiMajor-6378165.0) < 0.01
-                         && ABS(dfInvFlattening-298.3) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378165.0) < 0.01
+                         && std::abs(dfInvFlattening-298.3) < 0.0001 )
                 {
                     pszEllipsoidCode = "WGS60";
                 }
-                else if( ABS(dfSemiMajor-6378145.0) < 0.01
-                         && ABS(dfInvFlattening-298.25) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378145.0) < 0.01
+                         && std::abs(dfInvFlattening-298.25) < 0.0001 )
                 {
                     pszEllipsoidCode = "WGS66";
                 }
 #endif
-                else if( ABS(dfSemiMajor-6378135.0) < 0.01
-                         && ABS(dfInvFlattening-298.26) < 0.0001 )
+                else if( std::abs(dfSemiMajor-6378135.0) < 0.01
+                         && std::abs(dfInvFlattening-298.26) < 0.0001 )
                 {
                     pszEllipsoidCode = "WD";
                 }
-                else if( ABS(dfSemiMajor-6378137.0) < 0.01
-                         && ABS(dfInvFlattening-298.257223563) < 0.000001 )
+                else if( std::abs(dfSemiMajor-6378137.0) < 0.01
+                         && std::abs(dfInvFlattening-298.257223563) < 0.000001 )
                 {
                     pszEllipsoidCode = "WE";
                 }
@@ -1255,7 +1266,10 @@ int GDALPDFWriter::WriteSRS_OGC_BP(GDALDataset* poSrcDS,
     {
         if (nGCPCount == 4)
         {
-            int iUL = 0, iUR = 0, iLR = 0, iLL = 0;
+            int iUL = 0;
+            int iUR = 0;
+            int iLR = 0;
+            int iLL = 0;
             GDALPDFFind4Corners(pasGCPList,
                                 iUL,iUR, iLR, iLL);
 
@@ -1293,10 +1307,10 @@ int GDALPDFWriter::WriteSRS_OGC_BP(GDALDataset* poSrcDS,
         poNeatLineArray->Add((nHeight - 0) / dfUserUnit + psMargins->nBottom, TRUE);
 
         poNeatLineArray->Add(0 / dfUserUnit + psMargins->nLeft, TRUE);
-        poNeatLineArray->Add((nHeight -nHeight) / dfUserUnit + psMargins->nBottom, TRUE);
+        poNeatLineArray->Add((/*nHeight -nHeight*/ 0) / dfUserUnit + psMargins->nBottom, TRUE);
 
         poNeatLineArray->Add(nWidth / dfUserUnit + psMargins->nLeft, TRUE);
-        poNeatLineArray->Add((nHeight -nHeight) / dfUserUnit + psMargins->nBottom, TRUE);
+        poNeatLineArray->Add((/*nHeight -nHeight*/ 0) / dfUserUnit + psMargins->nBottom, TRUE);
 
         poNeatLineArray->Add(nWidth / dfUserUnit + psMargins->nLeft, TRUE);
         poNeatLineArray->Add((nHeight - 0) / dfUserUnit + psMargins->nBottom, TRUE);
@@ -1502,6 +1516,7 @@ int GDALPDFWriter::WriteOCG(const char* pszLayerName, int nParentId)
 
 int GDALPDFWriter::StartPage(GDALDataset* poClippingDS,
                              double dfDPI,
+                             bool bWriteUserUnit,
                              const char* pszGEO_ENCODING,
                              const char* pszNEATLINE,
                              PDFMargins* psMargins,
@@ -1542,9 +1557,10 @@ int GDALPDFWriter::StartPage(GDALDataset* poClippingDS,
     oDictPage.Add("Type", GDALPDFObjectRW::CreateName("Page"))
              .Add("Parent", nPageResourceId, 0)
              .Add("MediaBox", &((new GDALPDFArrayRW())
-                               ->Add(0).Add(0).Add(dfWidthInUserUnit).Add(dfHeightInUserUnit)))
-             .Add("UserUnit", dfUserUnit)
-             .Add("Contents", nContentId, 0)
+                               ->Add(0).Add(0).Add(dfWidthInUserUnit).Add(dfHeightInUserUnit)));
+    if( bWriteUserUnit )
+      oDictPage.Add("UserUnit", dfUserUnit);
+    oDictPage.Add("Contents", nContentId, 0)
              .Add("Resources", nResourcesId, 0)
              .Add("Annots", nAnnotsId, 0);
 
@@ -1675,8 +1691,10 @@ int GDALPDFWriter::WriteImagery(GDALDataset* poDS,
     {
         for(nBlockXOff = 0; nBlockXOff < nXBlocks; nBlockXOff ++)
         {
-            int nReqWidth = MIN(nBlockXSize, nWidth - nBlockXOff * nBlockXSize);
-            int nReqHeight = MIN(nBlockYSize, nHeight - nBlockYOff * nBlockYSize);
+            const int nReqWidth =
+                std::min(nBlockXSize, nWidth - nBlockXOff * nBlockXSize);
+            const int nReqHeight =
+                std::min(nBlockYSize, nHeight - nBlockYOff * nBlockYSize);
             int iImage = nBlockYOff * nXBlocks + nBlockXOff;
 
             void* pScaledData = GDALCreateScaledProgress( iImage / (double)nBlocks,
@@ -1788,8 +1806,10 @@ int GDALPDFWriter::WriteClippedImagery(
     {
         for(nBlockXOff = 0; nBlockXOff < nXBlocks; nBlockXOff ++)
         {
-            int nReqWidth = MIN(nBlockXSize, nWidth - nBlockXOff * nBlockXSize);
-            int nReqHeight = MIN(nBlockYSize, nHeight - nBlockYOff * nBlockYSize);
+            int nReqWidth =
+                std::min(nBlockXSize, nWidth - nBlockXOff * nBlockXSize);
+            int nReqHeight =
+                std::min(nBlockYSize, nHeight - nBlockYOff * nBlockYSize);
             int iImage = nBlockYOff * nXBlocks + nBlockXOff;
 
             void* pScaledData = GDALCreateScaledProgress( iImage / (double)nBlocks,
@@ -1812,11 +1832,15 @@ int GDALPDFWriter::WriteClippedImagery(
                 dfBlockMaxY = dfTmp;
             }
 
-            /* Clip the extent of the block with the extent of the main raster */
-            double dfIntersectMinX = MAX(dfBlockMinX, dfClippingMinX);
-            double dfIntersectMinY = MAX(dfBlockMinY, dfClippingMinY);
-            double dfIntersectMaxX = MIN(dfBlockMaxX, dfClippingMaxX);
-            double dfIntersectMaxY = MIN(dfBlockMaxY, dfClippingMaxY);
+            // Clip the extent of the block with the extent of the main raster.
+            const double dfIntersectMinX =
+                std::max(dfBlockMinX, dfClippingMinX);
+            const double dfIntersectMinY =
+                std::max(dfBlockMinY, dfClippingMinY);
+            const double dfIntersectMaxX =
+                std::min(dfBlockMaxX, dfClippingMaxX);
+            const double dfIntersectMaxY =
+                std::min(dfBlockMaxY, dfClippingMaxY);
 
             if( dfIntersectMinX < dfIntersectMaxX &&
                 dfIntersectMinY < dfIntersectMaxY )
@@ -1889,7 +1913,6 @@ int GDALPDFWriter::WriteClippedImagery(
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                          WriteOGRDataSource()                        */
 /************************************************************************/
@@ -2205,18 +2228,35 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
     /* -------------------------------------------------------------- */
     /*  Get style                                                     */
     /* -------------------------------------------------------------- */
-    int nPenR = 0, nPenG = 0, nPenB = 0, nPenA = 255;
-    int nBrushR = 127, nBrushG = 127, nBrushB = 127, nBrushA = 127;
-    int nTextR = 0, nTextG = 0, nTextB = 0, nTextA = 255;
+    unsigned int nPenR = 0;
+    unsigned int nPenG = 0;
+    unsigned int nPenB = 0;
+    unsigned int nPenA = 255;
+    unsigned int nBrushR = 127;
+    unsigned int nBrushG = 127;
+    unsigned int nBrushB = 127;
+    unsigned int nBrushA = 127;
+    unsigned int nTextR = 0;
+    unsigned int nTextG = 0;
+    unsigned int nTextB = 0;
+    unsigned int nTextA = 255;
     int bSymbolColorDefined = FALSE;
-    int nSymbolR = 0, nSymbolG = 0, nSymbolB = 0, nSymbolA = 255;
-    double dfTextSize = 12, dfTextAngle = 0, dfTextDx = 0, dfTextDy = 0;
-    double dfPenWidth = 1;
-    double dfSymbolSize = 5;
+    unsigned int nSymbolR = 0;
+    unsigned int nSymbolG = 0;
+    unsigned int nSymbolB = 0;
+    unsigned int nSymbolA = 255;
+    double dfTextSize = 12.0;
+    double dfTextAngle = 0.0;
+    double dfTextDx = 0.0;
+    double dfTextDy = 0.0;
+    double dfPenWidth = 1.0;
+    double dfSymbolSize = 5.0;
     CPLString osDashArray;
     CPLString osLabelText;
     CPLString osSymbolId;
-    int nImageSymbolId = 0, nImageWidth = 0, nImageHeight = 0;
+    int nImageSymbolId = 0;
+    int nImageWidth = 0;
+    int nImageHeight = 0;
 
     OGRStyleMgrH hSM = OGR_SM_Create(NULL);
     OGR_SM_InitFromFeature(hSM, hFeat);
@@ -2232,7 +2272,10 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
                 const char* pszColor = OGR_ST_GetParamStr(hTool, OGRSTPenColor, &bIsNull);
                 if (pszColor && !bIsNull)
                 {
-                    int nRed = 0, nGreen = 0, nBlue = 0, nAlpha = 255;
+                    unsigned int nRed = 0;
+                    unsigned int nGreen = 0;
+                    unsigned int nBlue = 0;
+                    unsigned int nAlpha = 255;
                     int nVals = sscanf(pszColor,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue,&nAlpha);
                     if (nVals >= 3)
                     {
@@ -2270,7 +2313,10 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
                 const char* pszColor = OGR_ST_GetParamStr(hTool, OGRSTBrushFColor, &bIsNull);
                 if (pszColor)
                 {
-                    int nRed = 0, nGreen = 0, nBlue = 0, nAlpha = 255;
+                    unsigned int nRed = 0;
+                    unsigned int nGreen = 0;
+                    unsigned int nBlue = 0;
+                    unsigned int nAlpha = 255;
                     int nVals = sscanf(pszColor,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue,&nAlpha);
                     if (nVals >= 3)
                     {
@@ -2292,8 +2338,8 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
 
                     /* If the text is of the form {stuff}, then it means we want to fetch */
                     /* the value of the field "stuff" in the feature */
-                    if( osLabelText.size() && osLabelText[0] == '{' &&
-                        osLabelText[osLabelText.size() - 1] == '}' )
+                    if( !osLabelText.empty() && osLabelText[0] == '{' &&
+                        osLabelText.back() == '}' )
                     {
                         osLabelText = pszStr + 1;
                         osLabelText.resize(osLabelText.size() - 1);
@@ -2309,7 +2355,10 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
                 const char* pszColor = OGR_ST_GetParamStr(hTool, OGRSTLabelFColor, &bIsNull);
                 if (pszColor && !bIsNull)
                 {
-                    int nRed = 0, nGreen = 0, nBlue = 0, nAlpha = 255;
+                    unsigned int nRed = 0;
+                    unsigned int nGreen = 0;
+                    unsigned int nBlue = 0;
+                    unsigned int nAlpha = 255;
                     int nVals = sscanf(pszColor,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue,&nAlpha);
                     if (nVals >= 3)
                     {
@@ -2344,7 +2393,6 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
                 {
                     dfTextDy = dfVal;
                 }
-
             }
             else if (OGR_ST_GetType(hTool) == OGRSTCSymbol)
             {
@@ -2407,7 +2455,10 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
                 const char* pszColor = OGR_ST_GetParamStr(hTool, OGRSTSymbolColor, &bIsNull);
                 if (pszColor && !bIsNull)
                 {
-                    int nRed = 0, nGreen = 0, nBlue = 0, nAlpha = 255;
+                    unsigned int nRed = 0;
+                    unsigned int nGreen = 0;
+                    unsigned int nBlue = 0;
+                    unsigned int nAlpha = 255;
                     int nVals = sscanf(pszColor,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue,&nAlpha);
                     if (nVals >= 3)
                     {
@@ -2480,7 +2531,7 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
     const char* pszLinkVal = NULL;
     if (pszOGRLinkField != NULL &&
         (iField = OGR_FD_GetFieldIndex(OGR_F_GetDefnRef(hFeat), pszOGRLinkField)) >= 0 &&
-        OGR_F_IsFieldSet(hFeat, iField) &&
+        OGR_F_IsFieldSetAndNotNull(hFeat, iField) &&
         strcmp((pszLinkVal = OGR_F_GetFieldAsString(hFeat, iField)), "") != 0)
     {
         int nAnnotId = AllocNewObject();
@@ -2753,7 +2804,7 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
     /* -------------------------------------------------------------- */
     /*  Write label                                                   */
     /* -------------------------------------------------------------- */
-    if (osLabelText.size() && wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPoint)
+    if (!osLabelText.empty() && wkbFlatten(OGR_G_GetGeometryType(hGeom)) == wkbPoint)
     {
         if (osVectorDesc.nOCGTextId == 0)
             osVectorDesc.nOCGTextId = WriteOCG("Text", osVectorDesc.nOGCId);
@@ -2798,16 +2849,14 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
                 poResources->Add("ExtGState", poExtGState);
             }
 
-            GDALPDFDictionaryRW* poDictFTimesRoman = NULL;
-            poDictFTimesRoman = new GDALPDFDictionaryRW();
+            GDALPDFDictionaryRW* poDictFTimesRoman = new GDALPDFDictionaryRW();
             poDictFTimesRoman->Add("Type", GDALPDFObjectRW::CreateName("Font"));
             poDictFTimesRoman->Add("BaseFont", GDALPDFObjectRW::CreateName("Times-Roman"));
             poDictFTimesRoman->Add("Encoding", GDALPDFObjectRW::CreateName("WinAnsiEncoding"));
             poDictFTimesRoman->Add("Subtype", GDALPDFObjectRW::CreateName("Type1"));
 
             GDALPDFDictionaryRW* poDictFont = new GDALPDFDictionaryRW();
-            if (poDictFTimesRoman)
-                poDictFont->Add("FTimesRoman", poDictFTimesRoman);
+            poDictFont->Add("FTimesRoman", poDictFTimesRoman);
             poResources->Add("Font", poDictFont);
 
             oDict.Add("Resources", poResources);
@@ -2920,7 +2969,7 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
         GDALPDFArrayRW* poArray = new GDALPDFArrayRW();
         for(int i = 0; i < nFields; i++)
         {
-            if (OGR_F_IsFieldSet(hFeat, i))
+            if (OGR_F_IsFieldSetAndNotNull(hFeat, i))
             {
                 OGRFieldDefnH hFDefn = OGR_F_GetFieldDefnRef( hFeat, i );
                 GDALPDFDictionaryRW* poKV = new GDALPDFDictionaryRW();
@@ -2957,7 +3006,6 @@ int GDALPDFWriter::WriteOGRFeature(GDALPDFLayerDesc& osVectorDesc,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                               EndPage()                              */
 /************************************************************************/
@@ -3141,7 +3189,7 @@ int GDALPDFWriter::EndPage(const char* pszExtraImages,
         for(size_t iVector = 0; iVector < oLayerDesc.aIds.size(); iVector ++)
         {
             CPLString osName = oLayerDesc.aFeatureNames[iVector];
-            if (osName.size())
+            if (!osName.empty() )
             {
                 VSIFPrintfL(fp, "/feature <</MCID %d>> BDC\n",
                             iObj);
@@ -3151,7 +3199,7 @@ int GDALPDFWriter::EndPage(const char* pszExtraImages,
 
             VSIFPrintfL(fp, "/Vector%d Do\n", oLayerDesc.aIds[iVector]);
 
-            if (osName.size())
+            if (!osName.empty() )
             {
                 VSIFPrintfL(fp, "EMC\n");
             }
@@ -3177,7 +3225,7 @@ int GDALPDFWriter::EndPage(const char* pszExtraImages,
                 if (oLayerDesc.aIdsText[iVector])
                 {
                     CPLString osName = oLayerDesc.aFeatureNames[iVector];
-                    if (osName.size())
+                    if (!osName.empty() )
                     {
                         VSIFPrintfL(fp, "/feature <</MCID %d>> BDC\n",
                                     iObj);
@@ -3185,7 +3233,7 @@ int GDALPDFWriter::EndPage(const char* pszExtraImages,
 
                     VSIFPrintfL(fp, "/Text%d Do\n", oLayerDesc.aIdsText[iVector]);
 
-                    if (osName.size())
+                    if (!osName.empty() )
                     {
                         VSIFPrintfL(fp, "EMC\n");
                     }
@@ -3204,7 +3252,7 @@ int GDALPDFWriter::EndPage(const char* pszExtraImages,
     /* -------------------------------------------------------------- */
     /*  Write drawing instructions for extra content.                 */
     /* -------------------------------------------------------------- */
-    if (pszExtraStream || asExtraImageDesc.size())
+    if (pszExtraStream || !asExtraImageDesc.empty() )
     {
         if (nLayerExtraId)
             VSIFPrintfL(fp, "/OC /Lyr%d BDC\n", nLayerExtraId);
@@ -3359,7 +3407,7 @@ int GDALPDFWriter::EndPage(const char* pszExtraImages,
             oDict.Add("Font", poDictFont);
         }
 
-        if (asOCGs.size())
+        if (!asOCGs.empty() )
         {
             GDALPDFDictionaryRW* poDictProperties = new GDALPDFDictionaryRW();
             for(size_t i=0; i<asOCGs.size(); i++)
@@ -4053,7 +4101,7 @@ void GDALPDFWriter::WritePages()
              .Add("Pages", nPageResourceId, 0);
         if (nXMPId)
             oDict.Add("Metadata", nXMPId, 0);
-        if (asOCGs.size())
+        if (!asOCGs.empty() )
         {
             GDALPDFDictionaryRW* poDictOCProperties = new GDALPDFDictionaryRW();
             oDict.Add("OCProperties", poDictOCProperties);
@@ -4077,7 +4125,7 @@ void GDALPDFWriter::WritePages()
             poDictD->Add("Order", poArrayOrder);
 
             /* Build "OFF" array of D dict */
-            if( osOffLayers.size() )
+            if( !osOffLayers.empty() )
             {
                 GDALPDFArrayRW* poArrayOFF = new GDALPDFArrayRW();
                 char** papszTokens = CSLTokenizeString2(osOffLayers, ",", 0);
@@ -4110,7 +4158,7 @@ void GDALPDFWriter::WritePages()
             }
 
             /* Build "RBGroups" array of D dict */
-            if( osExclusiveLayers.size() )
+            if( !osExclusiveLayers.empty() )
             {
                 GDALPDFArrayRW* poArrayRBGroups = new GDALPDFArrayRW();
                 char** papszTokens = CSLTokenizeString2(osExclusiveLayers, ",", 0);
@@ -4218,13 +4266,13 @@ class GDALPDFClippingDataset: public GDALDataset
             nRasterYSize = (int)((adfClippingExtent[3] - adfClippingExtent[1]) / fabs(adfSrcGeoTransform[5]));
         }
 
-        virtual CPLErr GetGeoTransform( double * padfGeoTransform )
+        virtual CPLErr GetGeoTransform( double * padfGeoTransform ) override
         {
             memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
             return CE_None;
         }
 
-        virtual const char* GetProjectionRef()
+        virtual const char* GetProjectionRef() override
         {
             return poSrcDS->GetProjectionRef();
         }
@@ -4325,16 +4373,17 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
                   "You should rather consider using color table expansion (-expand option in gdal_translate)");
     }
 
-
     int nBlockXSize = nWidth;
     int nBlockYSize = nHeight;
-    const char* pszValue;
 
-    int bTiled = CSLFetchBoolean( papszOptions, "TILED", FALSE );
+    const bool bTiled = CPLFetchBool( papszOptions, "TILED", false );
     if( bTiled )
-        nBlockXSize = nBlockYSize = 256;
+    {
+        nBlockXSize = 256;
+        nBlockYSize = 256;
+    }
 
-    pszValue = CSLFetchNameValue(papszOptions, "BLOCKXSIZE");
+    const char* pszValue = CSLFetchNameValue(papszOptions, "BLOCKXSIZE");
     if( pszValue != NULL )
     {
         nBlockXSize = atoi( pszValue );
@@ -4410,6 +4459,13 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
     if( pszDPI != NULL )
         dfDPI = CPLAtof(pszDPI);
 
+    const char* pszWriteUserUnit = CSLFetchNameValue(papszOptions, "WRITE_USERUNIT");
+    bool bWriteUserUnit;
+    if( pszWriteUserUnit != NULL )
+        bWriteUserUnit = CPLTestBool( pszWriteUserUnit );
+    else
+        bWriteUserUnit = ( pszDPI == NULL );
+
     double dfUserUnit = dfDPI * USER_UNIT_IN_INCH;
     double dfWidthInUserUnit = nWidth / dfUserUnit + sMargins.nLeft + sMargins.nRight;
     double dfHeightInUserUnit = nHeight / dfUserUnit + sMargins.nBottom + sMargins.nTop;
@@ -4510,7 +4566,8 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
     const char* pszOGRDisplayField = CSLFetchNameValue(papszOptions, "OGR_DISPLAY_FIELD");
     const char* pszOGRDisplayLayerNames = CSLFetchNameValue(papszOptions, "OGR_DISPLAY_LAYER_NAMES");
     const char* pszOGRLinkField = CSLFetchNameValue(papszOptions, "OGR_LINK_FIELD");
-    int bWriteOGRAttributes = CSLFetchBoolean(papszOptions, "OGR_WRITE_ATTRIBUTES", TRUE);
+    const bool bWriteOGRAttributes =
+        CPLFetchBool(papszOptions, "OGR_WRITE_ATTRIBUTES", true);
 
     const char* pszExtraRasters = CSLFetchNameValue(papszOptions, "EXTRA_RASTERS");
     const char* pszExtraRastersLayerName = CSLFetchNameValue(papszOptions, "EXTRA_RASTERS_LAYER_NAME");
@@ -4533,19 +4590,19 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
         return NULL;
     }
 
-
     GDALPDFWriter oWriter(fp);
 
     GDALDataset* poClippingDS = poSrcDS;
     if( bUseClippingExtent )
         poClippingDS = new GDALPDFClippingDataset(poSrcDS, adfClippingExtent);
 
-    if( CSLFetchBoolean(papszOptions, "WRITE_INFO", TRUE) )
+    if( CPLFetchBool(papszOptions, "WRITE_INFO", true) )
         oWriter.SetInfo(poSrcDS, papszOptions);
     oWriter.SetXMP(poClippingDS, pszXMP);
 
     oWriter.StartPage(poClippingDS,
                       dfDPI,
+                      bWriteUserUnit,
                       pszGEO_ENCODING,
                       pszNEATLINE,
                       &sMargins,
@@ -4720,7 +4777,30 @@ GDALDataset *GDALPDFCreateCopy( const char * pszFilename,
     else
     {
 #if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
-        return GDALPDFOpen(pszFilename, GA_ReadOnly);
+        GDALDataset* poDS = GDALPDFOpen(pszFilename, GA_ReadOnly);
+        if( poDS == NULL )
+            return NULL;
+        char** papszMD = CSLDuplicate( poSrcDS->GetMetadata() );
+        papszMD = CSLMerge( papszMD, poDS->GetMetadata() );
+        const char* pszAOP = CSLFetchNameValue(papszMD, GDALMD_AREA_OR_POINT);
+        if( pszAOP != NULL && EQUAL(pszAOP, GDALMD_AOP_AREA) )
+            papszMD = CSLSetNameValue(papszMD, GDALMD_AREA_OR_POINT, NULL);
+        poDS->SetMetadata( papszMD );
+        if( EQUAL(pszGEO_ENCODING, "NONE") )
+        {
+            double adfGeoTransform[6];
+            if( poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None )
+            {
+                poDS->SetGeoTransform( adfGeoTransform );
+            }
+            const char* pszProjectionRef = poSrcDS->GetProjectionRef();
+            if( pszProjectionRef != NULL && pszProjectionRef[0] != '\0' )
+            {
+                poDS->SetProjection( pszProjectionRef );
+            }
+        }
+        CSLDestroy(papszMD);
+        return poDS;
 #else
         return new GDALFakePDFDataset();
 #endif
diff --git a/frmts/pdf/pdfcreatecopy.h b/frmts/pdf/pdfcreatecopy.h
index 140e96b..9faa550 100644
--- a/frmts/pdf/pdfcreatecopy.h
+++ b/frmts/pdf/pdfcreatecopy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdfcreatecopy.h 33757 2016-03-20 20:22:33Z goatbar $
+ * $Id: pdfcreatecopy.h 36347 2016-11-20 20:43:39Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -116,6 +116,21 @@ class GDALPDFPageContext
         std::vector<GDALPDFRasterDesc> asRasterDesc;
         int          nAnnotsId;
         std::vector<int> anAnnotationsId;
+
+        GDALPDFPageContext() :
+            poClippingDS( NULL ),
+            eStreamCompressMethod( COMPRESS_NONE ),
+            dfDPI( 0.0 ),
+            nPageId( 0 ),
+            nContentId( 0 ),
+            nResourcesId( 0 ),
+            nAnnotsId( 0 )
+        {
+            sMargins.nLeft = 0;
+            sMargins.nRight = 0;
+            sMargins.nTop = 0;
+            sMargins.nBottom = 0;
+        }
 };
 
 class GDALPDFOCGDesc
@@ -154,8 +169,6 @@ class GDALPDFWriter
     CPLString    osOffLayers;
     CPLString    osExclusiveLayers;
 
-    void    Init();
-
     void    StartObj(int nObjectId, int nGen = 0);
     void    EndObj();
     void    WriteXRefTableAndTrailer();
@@ -179,7 +192,7 @@ class GDALPDFWriter
     int     AllocNewObject();
 
     public:
-        GDALPDFWriter(VSILFILE* fpIn, int bAppend = FALSE);
+        GDALPDFWriter( VSILFILE* fpIn, int bAppend = FALSE );
        ~GDALPDFWriter();
 
        void Close();
@@ -208,6 +221,7 @@ class GDALPDFWriter
 
        int  StartPage(GDALDataset* poSrcDS,
                       double dfDPI,
+                      bool bWriteUserUnit,
                       const char* pszGEO_ENCODING,
                       const char* pszNEATLINE,
                       PDFMargins* psMargins,
diff --git a/frmts/pdf/pdfdataset.cpp b/frmts/pdf/pdfdataset.cpp
index 4bee2d8..7d7c526 100644
--- a/frmts/pdf/pdfdataset.cpp
+++ b/frmts/pdf/pdfdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pdfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -49,13 +48,15 @@
 #endif // HAVE_POPPLER
 
 #include "pdfcreatecopy.h"
+
+#include <algorithm>
 #include <set>
 
 #define GDAL_DEFAULT_DPI 150.0
 
 /* g++ -fPIC -g -Wall frmts/pdf/pdfdataset.cpp -shared -o gdal_PDF.so -Iport -Igcore -Iogr -L. -lgdal -lpoppler -I/usr/include/poppler */
 
-CPL_CVSID("$Id: pdfdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: pdfdataset.cpp 36776 2016-12-10 11:17:47Z rouault $");
 
 #if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
 
@@ -133,7 +134,6 @@ public:
     Object* getObj() { return &obj; }
 };
 
-
 /************************************************************************/
 /*                         GDALPDFOutputDev                             */
 /************************************************************************/
@@ -176,7 +176,7 @@ class GDALPDFOutputDev : public SplashOutputDev
 #ifdef POPPLER_0_23_OR_LATER
                                ,XRef* xrefIn
 #endif
-        )
+        ) override
         {
             SplashOutputDev::startPage(pageNum, state
 #ifdef POPPLER_0_23_OR_LATER
@@ -187,19 +187,19 @@ class GDALPDFOutputDev : public SplashOutputDev
             memset(poBitmap->getDataPtr(), 255, poBitmap->getRowSize() * poBitmap->getHeight());
         }
 
-        virtual void stroke(GfxState * state)
+        virtual void stroke(GfxState * state) override
         {
             if (bEnableVector)
                 SplashOutputDev::stroke(state);
         }
 
-        virtual void fill(GfxState * state)
+        virtual void fill(GfxState * state) override
         {
             if (bEnableVector)
                 SplashOutputDev::fill(state);
         }
 
-        virtual void eoFill(GfxState * state)
+        virtual void eoFill(GfxState * state) override
         {
             if (bEnableVector)
                 SplashOutputDev::eoFill(state);
@@ -208,7 +208,7 @@ class GDALPDFOutputDev : public SplashOutputDev
         virtual void drawChar(GfxState *state, double x, double y,
                               double dx, double dy,
                               double originX, double originY,
-                              CharCode code, int nBytes, Unicode *u, int uLen)
+                              CharCode code, int nBytes, Unicode *u, int uLen) override
         {
             if (bEnableText)
                 SplashOutputDev::drawChar(state, x, y, dx, dy,
@@ -216,14 +216,14 @@ class GDALPDFOutputDev : public SplashOutputDev
                                           code, nBytes, u, uLen);
         }
 
-        virtual void beginTextObject(GfxState *state)
+        virtual void beginTextObject(GfxState *state) override
         {
             if (bEnableText)
                 SplashOutputDev::beginTextObject(state);
         }
 
 #ifndef POPPLER_0_23_OR_LATER
-        virtual GBool deviceHasTextClip(GfxState *state)
+        virtual GBool deviceHasTextClip(GfxState *state) override
         {
             if (bEnableText)
                 return SplashOutputDev::deviceHasTextClip(state);
@@ -231,7 +231,7 @@ class GDALPDFOutputDev : public SplashOutputDev
         }
 #endif
 
-        virtual void endTextObject(GfxState *state)
+        virtual void endTextObject(GfxState *state) override
         {
             if (bEnableText)
                 SplashOutputDev::endTextObject(state);
@@ -239,7 +239,7 @@ class GDALPDFOutputDev : public SplashOutputDev
 
         virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
                                    int width, int height, GBool invert,
-                                   GBool interpolate, GBool inlineImg)
+                                   GBool interpolate, GBool inlineImg) override
         {
             if (bEnableBitmap)
                 SplashOutputDev::drawImageMask(state, ref, str,
@@ -260,7 +260,7 @@ class GDALPDFOutputDev : public SplashOutputDev
         virtual void setSoftMaskFromImageMask(GfxState *state,
                             Object *ref, Stream *str,
                             int width, int height, GBool invert,
-                            GBool inlineImg, double *baseMatrix)
+                            GBool inlineImg, double *baseMatrix) override
         {
             if (bEnableBitmap)
                 SplashOutputDev::setSoftMaskFromImageMask(state, ref, str,
@@ -270,7 +270,7 @@ class GDALPDFOutputDev : public SplashOutputDev
                 str->close();
         }
 
-        virtual void unsetSoftMaskFromImageMask(GfxState *state, double *baseMatrix)
+        virtual void unsetSoftMaskFromImageMask(GfxState *state, double *baseMatrix) override
         {
             if (bEnableBitmap)
                 SplashOutputDev::unsetSoftMaskFromImageMask(state, baseMatrix);
@@ -279,7 +279,7 @@ class GDALPDFOutputDev : public SplashOutputDev
 
         virtual void drawImage(GfxState *state, Object *ref, Stream *str,
                                int width, int height, GfxImageColorMap *colorMap,
-                               GBool interpolate, int *maskColors, GBool inlineImg)
+                               GBool interpolate, int *maskColors, GBool inlineImg) override
         {
             if (bEnableBitmap)
                 SplashOutputDev::drawImage(state, ref, str,
@@ -303,7 +303,7 @@ class GDALPDFOutputDev : public SplashOutputDev
                                      GfxImageColorMap *colorMap,
                                      GBool interpolate,
                                      Stream *maskStr, int maskWidth, int maskHeight,
-                                     GBool maskInvert, GBool maskInterpolate)
+                                     GBool maskInvert, GBool maskInterpolate) override
         {
             if (bEnableBitmap)
                 SplashOutputDev::drawMaskedImage(state, ref, str,
@@ -322,7 +322,7 @@ class GDALPDFOutputDev : public SplashOutputDev
                                          Stream *maskStr,
                                          int maskWidth, int maskHeight,
                                          GfxImageColorMap *maskColorMap,
-                                         GBool maskInterpolate)
+                                         GBool maskInterpolate) override
         {
             if (bEnableBitmap)
             {
@@ -563,12 +563,12 @@ void GDALPDFDumper::Dump(GDALPDFDictionary* poDict, int nDepth)
 /*                         PDFRasterBand()                              */
 /************************************************************************/
 
-PDFRasterBand::PDFRasterBand( PDFDataset *poDSIn, int nBandIn, int nResolutionLevelIn )
-
+PDFRasterBand::PDFRasterBand( PDFDataset *poDSIn, int nBandIn,
+                              int nResolutionLevelIn ) :
+    nResolutionLevel(nResolutionLevelIn)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->nResolutionLevel = nResolutionLevelIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = GDT_Byte;
 
@@ -590,8 +590,8 @@ PDFRasterBand::PDFRasterBand( PDFDataset *poDSIn, int nBandIn, int nResolutionLe
     }
     else
     {
-        nBlockXSize = MIN(1024, poDSIn->GetRasterXSize());
-        nBlockYSize = MIN(1024, poDSIn->GetRasterYSize());
+        nBlockXSize = std::min(1024, poDSIn->GetRasterXSize());
+        nBlockYSize = std::min(1024, poDSIn->GetRasterYSize());
         poDSIn->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
     }
 }
@@ -608,7 +608,8 @@ void PDFDataset::InitOverviews()
     if(bUseLib.test(PDFLIB_PDFIUM) &&
        ((GDALPamRasterBand*)GetRasterBand(1))->GDALPamRasterBand::GetOverviewCount() == 0)
     {
-        int nXSize = nRasterXSize, nYSize = nRasterYSize;
+        int nXSize = nRasterXSize;
+        int nYSize = nRasterYSize;
         int blockXSize = 256;
         int blockYSize = 256;
         int nDiscard = 1;
@@ -869,7 +870,7 @@ CPLErr PDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 {
     PDFDataset *poGDS = (PDFDataset *) poDS;
 
-    if (poGDS->aiTiles.size() )
+    if (!poGDS->aiTiles.empty() )
     {
         if ( IReadBlockFromTile(nBlockXOff, nBlockYOff,
                                 pImage) == CE_None )
@@ -900,9 +901,13 @@ CPLErr PDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     {
         poGDS->bTried = TRUE;
         if( nBlockYSize == 1 )
-            poGDS->pabyCachedData = (GByte*)VSIMalloc3(MAX(3, poGDS->nBands), nRasterXSize, nRasterYSize);
+            poGDS->pabyCachedData = static_cast<GByte *>(
+                VSIMalloc3(std::max(3, poGDS->nBands),
+                           nRasterXSize, nRasterYSize));
         else
-            poGDS->pabyCachedData = (GByte*)VSIMalloc3(MAX(3, poGDS->nBands), nBlockXSize, nBlockYSize);
+          poGDS->pabyCachedData = static_cast<GByte *>(
+              VSIMalloc3(std::max(3, poGDS->nBands),
+                         nBlockXSize, nBlockYSize));
     }
     if (poGDS->pabyCachedData == NULL)
         return CE_Failure;
@@ -950,7 +955,6 @@ CPLErr PDFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             CPLFree(poGDS->pabyCachedData);
             poGDS->pabyCachedData = NULL;
         }
-
     }
     if (poGDS->pabyCachedData == NULL)
         return CE_Failure;
@@ -976,10 +980,10 @@ static const char* PDFEnterPasswordFromConsoleIfNeeded(const char* pszUserPwd)
     if (EQUAL(pszUserPwd, "ASK_INTERACTIVE"))
     {
         static char szPassword[81];
-        printf( "Enter password (will be echo'ed in the console): " );
+        printf( "Enter password (will be echo'ed in the console): " );/*ok*/
         if (NULL == fgets( szPassword, sizeof(szPassword), stdin ))
         {
-            fprintf(stderr, "WARNING: Error getting password.\n");
+            fprintf(stderr, "WARNING: Error getting password.\n");/*ok*/
         }
         szPassword[sizeof(szPassword)-1] = 0;
         char* sz10 = strchr(szPassword, '\n');
@@ -1033,12 +1037,11 @@ static TMapPdfiumDatasets g_mPdfiumDatasets;
  */
 
 static
-int LoadPdfiumDocumentPage(const char* pszFilename, const char* pszUserPwd,
-    int pageNum, TPdfiumDocumentStruct** doc, TPdfiumPageStruct** page, int *pnPageCount)
+int LoadPdfiumDocumentPage(
+    const char* pszFilename, const char* pszUserPwd,
+    int pageNum, TPdfiumDocumentStruct** doc, TPdfiumPageStruct** page,
+    int *pnPageCount )
 {
-  TPdfiumDocumentStruct *poDoc;
-  TPdfiumPageStruct *poPage;
-
   // Prepare NULL for error returning
   if(doc)
     *doc = NULL;
@@ -1058,10 +1061,10 @@ int LoadPdfiumDocumentPage(const char* pszFilename, const char* pszUserPwd,
 
   TMapPdfiumDatasets::iterator it;
   it = g_mPdfiumDatasets.find((char*)pszFilename);
+  TPdfiumDocumentStruct *poDoc = NULL;
   // Load new document if missing
   if(it == g_mPdfiumDatasets.end() ) {
     // Try without password (if PDF not requires password it can fail)
-    CPDF_Document* docPdfium;
 
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     if( fp == NULL )
@@ -1082,7 +1085,8 @@ int LoadPdfiumDocumentPage(const char* pszFilename, const char* pszUserPwd,
     psFileAccess->m_Param = fp;
     psFileAccess->m_FileLen = nFileLen;
     psFileAccess->m_GetBlock = GDALPdfiumGetBlock;
-    docPdfium = reinterpret_cast<CPDF_Document*>(FPDF_LoadCustomDocument(psFileAccess, NULL));
+    CPDF_Document* docPdfium = reinterpret_cast<CPDF_Document*>(
+        FPDF_LoadCustomDocument(psFileAccess, NULL));
     if(docPdfium == NULL)
     {
       unsigned long err = FPDF_GetLastError();
@@ -1170,6 +1174,7 @@ int LoadPdfiumDocumentPage(const char* pszFilename, const char* pszUserPwd,
 
   TMapPdfiumPages::iterator itPage;
   itPage = poDoc->pages.find(pageNum);
+  TPdfiumPageStruct *poPage = NULL;
   // Page not loaded
   if(itPage == poDoc->pages.end()) {
     CPDF_Dictionary* pDict = poDoc->doc->GetPage(pageNum - 1);
@@ -1264,7 +1269,7 @@ int UnloadPdfiumDocumentPage(TPdfiumDocumentStruct** doc, TPdfiumPageStruct** pa
       pDoc->pages.size());
 #endif
   // Another page is used
-  if(pDoc->pages.size() != 0) {
+  if(!pDoc->pages.empty()) {
     CPLReleaseMutex(g_oPdfiumLoadDocMutex);
     return TRUE;
   }
@@ -1283,7 +1288,7 @@ int UnloadPdfiumDocumentPage(TPdfiumDocumentStruct** doc, TPdfiumPageStruct** pa
       g_mPdfiumDatasets.size());
 #endif
   // Another document is used
-  if(g_mPdfiumDatasets.size() != 0) {
+  if(!g_mPdfiumDatasets.empty()) {
     CPLReleaseMutex(g_oPdfiumLoadDocMutex);
     return TRUE;
   }
@@ -1397,7 +1402,7 @@ public:
                                                         bEnableText(TRUE),
                                                         bEnableBitmap(TRUE),
                                                         bTemporaryEnableVectorForTextStroking(FALSE) {}
-    ~GDALPDFiumRenderDeviceDriver() { delete m_poParent; }
+    virtual ~GDALPDFiumRenderDeviceDriver() { delete m_poParent; }
 
     void SetEnableVector(int bFlag) { bEnableVector = bFlag; }
     void SetEnableText(int bFlag) { bEnableText = bFlag; }
@@ -1711,10 +1716,11 @@ CPLErr PDFDataset::ReadPixels( int nReqXOff, int nReqYOff,
         sColor[0] = 255;
         sColor[1] = 255;
         sColor[2] = 255;
-        GDALPDFOutputDev *poSplashOut;
-        poSplashOut = new GDALPDFOutputDev((nBands < 4) ? splashModeRGB8 : splashModeXBGR8,
-                                            4, gFalse,
-                                            (nBands < 4) ? sColor : NULL);
+        GDALPDFOutputDev *poSplashOut =
+            new GDALPDFOutputDev(
+                (nBands < 4) ? splashModeRGB8 : splashModeXBGR8,
+                4, gFalse,
+                (nBands < 4) ? sColor : NULL);
 
         if (pszRenderingOptions != NULL)
         {
@@ -1850,7 +1856,7 @@ CPLErr PDFDataset::ReadPixels( int nReqXOff, int nReqYOff,
                     iPage, iPage,
                     osFilename.c_str());
 
-            if (osUserPwd.size() != 0)
+            if (!osUserPwd.empty())
             {
                 osCmd += " -upw \"";
                 osCmd += osUserPwd;
@@ -1885,7 +1891,7 @@ CPLErr PDFDataset::ReadPixels( int nReqXOff, int nReqYOff,
             papszArgs = CSLAddString(papszArgs, CPLSPrintf("%d", iPage));
             papszArgs = CSLAddString(papszArgs, "-l");
             papszArgs = CSLAddString(papszArgs, CPLSPrintf("%d", iPage));
-            if (osUserPwd.size() != 0)
+            if (!osUserPwd.empty())
             {
                 papszArgs = CSLAddString(papszArgs, "-upw");
                 papszArgs = CSLAddString(papszArgs, osUserPwd.c_str());
@@ -2076,18 +2082,16 @@ class PDFImageRasterBand : public PDFRasterBand
 
                 PDFImageRasterBand( PDFDataset *, int );
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                        PDFImageRasterBand()                          */
 /************************************************************************/
 
-PDFImageRasterBand::PDFImageRasterBand( PDFDataset *poDSIn, int nBandIn ) : PDFRasterBand(poDSIn, nBandIn, 0)
-
-{
-}
+PDFImageRasterBand::PDFImageRasterBand( PDFDataset *poDSIn, int nBandIn ) :
+    PDFRasterBand(poDSIn, nBandIn, 0)
+{}
 
 /************************************************************************/
 /*                             IReadBlock()                             */
@@ -2154,66 +2158,64 @@ CPLErr PDFImageRasterBand::IReadBlock( int CPL_UNUSED nBlockXOff, int nBlockYOff
 /*                            PDFDataset()                              */
 /************************************************************************/
 
-PDFDataset::PDFDataset(PDFDataset* poParentDSIn, int nXSize, int nYSize)
-{
-    poParentDS = poParentDSIn;
-    nRasterXSize = nXSize;
-    nRasterYSize = nYSize;
-    bUseLib.reset();
-    if( poParentDSIn )
-        bUseLib = poParentDS->bUseLib;
+PDFDataset::PDFDataset( PDFDataset* poParentDSIn, int nXSize, int nYSize ) :
+    poParentDS(poParentDSIn),
+    pszWKT(NULL),
+    dfDPI(GDAL_DEFAULT_DPI),
+    bHasCTM(FALSE),
+    bGeoTransformValid(FALSE),
+    nGCPCount(0),
+    pasGCPList(NULL),
+    bProjDirty(FALSE),
+    bNeatLineDirty(FALSE),
+    bInfoDirty(FALSE),
+    bXMPDirty(FALSE),
 #ifdef HAVE_POPPLER
-    poDocPoppler = NULL;
+    poDocPoppler(NULL),
 #endif
 #ifdef HAVE_PODOFO
-    poDocPodofo = NULL;
-    bPdfToPpmFailed = FALSE;
+    poDocPodofo(NULL),
+    bPdfToPpmFailed(FALSE),
 #endif
 #ifdef HAVE_PDFIUM
-    poDocPdfium = poParentDSIn ? poParentDSIn->poDocPdfium: NULL;
-    poPagePdfium = poParentDSIn ? poParentDSIn->poPagePdfium: NULL;
+    poDocPdfium(poParentDSIn ? poParentDSIn->poDocPdfium : NULL),
+    poPagePdfium(poParentDSIn ? poParentDSIn->poPagePdfium : NULL),
 #endif
-    poPageObj = NULL;
-    poImageObj = NULL;
-    pszWKT = NULL;
-    dfDPI = GDAL_DEFAULT_DPI;
-    dfMaxArea = 0;
+    poPageObj(NULL),
+    iPage(-1),
+    poImageObj(NULL),
+    dfMaxArea(0),
+    bTried(FALSE),
+    pabyCachedData(NULL),
+    nLastBlockXOff(-1),
+    nLastBlockYOff(-1),
+    poNeatLine(NULL),
+#ifdef HAVE_POPPLER
+    poCatalogObjectPoppler(NULL),
+#endif
+    poCatalogObject(NULL),
+    bUseOCG(FALSE),
+    papszOpenOptions(NULL),
+    bHasLoadedLayers(FALSE),
+    nLayers(0),
+    papoLayers(NULL),
+    dfPageWidth(0),
+    dfPageHeight(0),
+    bSetStyle(CPLTestBool(CPLGetConfigOption("OGR_PDF_SET_STYLE", "YES")))
+{
+    nRasterXSize = nXSize;
+    nRasterYSize = nYSize;
+    bUseLib.reset();
+    if( poParentDSIn )
+        bUseLib = poParentDS->bUseLib;
     adfGeoTransform[0] = 0;
     adfGeoTransform[1] = 1;
     adfGeoTransform[2] = 0;
     adfGeoTransform[3] = 0;
     adfGeoTransform[4] = 0;
     adfGeoTransform[5] = 1;
-    bHasCTM = FALSE;
-    bGeoTransformValid = FALSE;
-    nGCPCount = 0;
-    pasGCPList = NULL;
-    bProjDirty = FALSE;
-    bNeatLineDirty = FALSE;
-    bInfoDirty = FALSE;
-    bXMPDirty = FALSE;
-    bTried = FALSE;
-    pabyCachedData = NULL;
-    nLastBlockXOff = -1;
-    nLastBlockYOff = -1;
-    iPage = -1;
-    poNeatLine = NULL;
-    bUseOCG = FALSE;
-    poCatalogObject = NULL;
-#ifdef HAVE_POPPLER
-    poCatalogObjectPoppler = NULL;
-#endif
     nBlockXSize = 0;
     nBlockYSize = 0;
-    papszOpenOptions = NULL;
-
-    bHasLoadedLayers = FALSE;
-    nLayers = 0;
-    papoLayers = NULL;
-
-    dfPageWidth = dfPageHeight = 0;
-
-    bSetStyle = CPLTestBool(CPLGetConfigOption("OGR_PDF_SET_STYLE", "YES"));
 
     InitMapOperators();
 }
@@ -2236,7 +2238,7 @@ CPLErr PDFDataset::IBuildOverviews( const char *pszResampling,
 /*      discard any concept of internal overviews when the user         */
 /*      first requests to build external overviews.                     */
 /* -------------------------------------------------------------------- */
-    if( apoOvrDS.size() )
+    if( !apoOvrDS.empty() )
     {
         apoOvrDSBackup = apoOvrDS;
         apoOvrDS.clear();
@@ -2292,7 +2294,8 @@ GDALPDFObject* PDFDataset::GetCatalog()
 #ifdef HAVE_PODOFO
     if (bUseLib.test(PDFLIB_PODOFO))
     {
-        int nCatalogNum = 0, nCatalogGen = 0;
+        int nCatalogNum = 0;
+        int nCatalogGen = 0;
         VSILFILE* fp = VSIFOpenL(osFilename.c_str(), "rb");
         if (fp != NULL)
         {
@@ -2452,7 +2455,6 @@ PDFDataset::~PDFDataset()
     CPLFree( papoLayers );
 }
 
-
 /************************************************************************/
 /*                            IRasterIO()                               */
 /************************************************************************/
@@ -2469,7 +2471,7 @@ CPLErr PDFDataset::IRasterIO( GDALRWFlag eRWFlag,
     int nBandBlockXSize, nBandBlockYSize;
     int bReadPixels = FALSE;
     GetRasterBand(1)->GetBlockSize(&nBandBlockXSize, &nBandBlockYSize);
-    if( aiTiles.size() == 0 &&
+    if( aiTiles.empty() &&
         eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize &&
         (nBufXSize > nBandBlockXSize || nBufYSize > nBandBlockYSize) &&
         eBufType == GDT_Byte && nBandCount == nBands &&
@@ -2511,7 +2513,7 @@ CPLErr PDFRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 {
     PDFDataset *poGDS = (PDFDataset *) poDS;
     int bReadPixels = FALSE;
-    if( poGDS->aiTiles.size() == 0 &&
+    if( poGDS->aiTiles.empty() &&
         eRWFlag == GF_Read && nXSize == nBufXSize && nYSize == nBufYSize &&
         (nBufXSize > nBlockXSize || nBufYSize > nBlockYSize) &&
         eBufType == GDT_Byte )
@@ -2527,12 +2529,8 @@ CPLErr PDFRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
     if( bReadPixels )
     {
-        CPLErr eErr = ReadPixels(nXOff, nYOff, nXSize, nYSize,
-                                 nPixelSpace, nLineSpace, 0, NULL);
-        if( eErr == CE_None )
-        {
-
-        }
+        const CPLErr eErr = ReadPixels(nXOff, nYOff, nXSize, nYSize,
+                                       nPixelSpace, nLineSpace, 0, NULL);
         return eErr;
     }
 
@@ -2640,7 +2638,7 @@ CPLString GDALPDFParseStreamContentOnlyDrawForm(const char* pszContent)
         }
         else if (ch == ' ' || ch == '\r' || ch == '\n')
         {
-            if (osToken.size())
+            if (!osToken.empty() )
             {
                 if (nCurIdx == 0 && osToken[0] == '/')
                 {
@@ -2724,7 +2722,7 @@ int GDALPDFParseStreamContent(const char* pszContent,
         }
         else if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')
         {
-            if (osToken.size())
+            if (!osToken.empty() )
             {
                 if (nState == STATE_INIT)
                 {
@@ -2847,7 +2845,8 @@ int GDALPDFParseStreamContent(const char* pszContent,
 int PDFDataset::CheckTiledRaster()
 {
     size_t i;
-    int l_nBlockXSize = 0, l_nBlockYSize = 0;
+    int l_nBlockXSize = 0;
+    int l_nBlockYSize = 0;
     const double dfUserUnit = dfDPI * USER_UNIT_IN_INCH;
 
     /* First pass : check that all tiles have same DPI, */
@@ -3030,7 +3029,7 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
                         }
 #endif // DEBUG
                         osForm = GDALPDFParseStreamContentOnlyDrawForm(pszContent);
-                        if (osForm.size() == 0)
+                        if (osForm.empty())
                         {
                             /* Special case for USGS Topo PDF, like CA_Hollywood_20090811_OM_geo.pdf */
                             const char* pszOGCDo = strstr(pszContent, " /XO1 Do");
@@ -3059,7 +3058,8 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
                                         CPLString oscm(pszIter);
                                         oscm.resize(pszcm - pszIter);
                                         char** papszTokens = CSLTokenizeString(oscm);
-                                        double dfScaleX = -1, dfScaleY = -2;
+                                        double dfScaleX = -1.0;
+                                        double dfScaleY = -2.0;
                                         if( CSLCount(papszTokens) == 6 )
                                         {
                                             dfScaleX = CPLAtof(papszTokens[0]);
@@ -3084,7 +3084,7 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
                             else
                             {
                                 CPLString osOCG = FindLayerOCG(poPageDict, "Orthoimage");
-                                if( osOCG.size() )
+                                if( !osOCG.empty() )
                                 {
                                     const char* pszBDCLookup = CPLSPrintf("/OC /%s BDC", osOCG.c_str());
                                     const char* pszBDC = strstr(pszContent, pszBDCLookup);
@@ -3118,7 +3118,7 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
                         }
                     }
 
-                    if (osForm.size())
+                    if (!osForm.empty() )
                     {
                         CPLFree(pszContent);
                         pszContent = NULL;
@@ -3129,10 +3129,11 @@ void PDFDataset::GuessDPI(GDALPDFDictionary* poPageDict, int* pnBands)
                             (poPageStream = poObjForm->GetStream()) != NULL)
                         {
                             GDALPDFDictionary* poObjFormDict = poObjForm->GetDictionary();
-                            GDALPDFObject* poSubtype;
-                            if ((poSubtype = poObjFormDict->Get("Subtype")) != NULL &&
+                            GDALPDFObject* poSubtype =
+                                poObjFormDict->Get("Subtype");
+                            if( poSubtype != NULL &&
                                 poSubtype->GetType() == PDFObjectType_Name &&
-                                poSubtype->GetName() == "Form")
+                                poSubtype->GetName() == "Form" )
                             {
                                 nLength = poPageStream->GetLength();
                                 if( nLength < 100000 )
@@ -3339,7 +3340,6 @@ void PDFDataset::AddLayer(const char* pszLayerName)
 
     osLayerList.AddNameValue(CPLSPrintf(szFormatName, nNewIndex),
                              pszLayerName);
-
 }
 
 #endif//  defined(HAVE_POPPLER) || defined(HAVE_PDFIUM)
@@ -3365,7 +3365,7 @@ void PDFDataset::ExploreLayersPoppler(GDALPDFArray* poArray,
         if (i == 0 && poObj->GetType() == PDFObjectType_String)
         {
             CPLString osName = PDFSanitizeLayerName(poObj->GetString().c_str());
-            if (osTopLayer.size())
+            if (!osTopLayer.empty() )
                 osTopLayer = osTopLayer + "." + osName;
             else
                 osTopLayer = osName;
@@ -3385,7 +3385,7 @@ void PDFDataset::ExploreLayersPoppler(GDALPDFArray* poArray,
             {
                 CPLString osName = PDFSanitizeLayerName(poName->GetString().c_str());
                 /* coverity[copy_paste_error] */
-                if (osTopLayer.size())
+                if (!osTopLayer.empty() )
                     osCurLayer = osTopLayer + "." + osName;
                 else
                     osCurLayer = osName;
@@ -3517,7 +3517,7 @@ void PDFDataset::TurnLayersOnOffPoppler()
                 }
 
                 // Turn parent layers on too
-                char* pszLastDot;
+                char* pszLastDot = NULL;
                 while( (pszLastDot = strrchr(papszLayers[i], '.')) != NULL)
                 {
                     *pszLastDot = '\0';
@@ -3612,7 +3612,7 @@ void PDFDataset::ExploreLayersPdfium(GDALPDFArray* poArray,
         if (i == 0 && poObj->GetType() == PDFObjectType_String)
         {
             CPLString osName = PDFSanitizeLayerName(poObj->GetString().c_str());
-            if (osTopLayer.size())
+            if (!osTopLayer.empty() )
                 osTopLayer = osTopLayer + "." + osName;
             else
                 osTopLayer = osName;
@@ -3632,7 +3632,7 @@ void PDFDataset::ExploreLayersPdfium(GDALPDFArray* poArray,
             if (poName != NULL && poName->GetType() == PDFObjectType_String)
             {
                 CPLString osName = PDFSanitizeLayerName(poName->GetString().c_str());
-                if (osTopLayer.size())
+                if (!osTopLayer.empty() )
                     osCurLayer = osTopLayer + "." + osName;
                 else
                     osCurLayer = osName;
@@ -3685,7 +3685,6 @@ void PDFDataset::FindLayersPdfium()
     oMDMD.SetMetadata(osLayerList.List(), "LAYERS");
 }
 
-
 /************************************************************************/
 /*                       TurnLayersOnOffPdfium()                       */
 /************************************************************************/
@@ -3766,7 +3765,7 @@ void PDFDataset::TurnLayersOnOffPdfium()
                 }
 
                 // Turn parent layers on too
-                char* pszLastDot;
+                char* pszLastDot = NULL;
                 while( (pszLastDot = strrchr(papszLayers[i], '.')) != NULL)
                 {
                     *pszLastDot = '\0';
@@ -4402,7 +4401,10 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-    double dfX1 = 0.0, dfY1 = 0.0, dfX2 = 0.0, dfY2 = 0.0;
+    double dfX1 = 0.0;
+    double dfY1 = 0.0;
+    double dfX2 = 0.0;
+    double dfY2 = 0.0;
 
 #ifdef HAVE_POPPLER
     if (bUseLib.test(PDFLIB_POPPLER))
@@ -4493,11 +4495,11 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
     /* Check if the PDF is only made of regularly tiled images */
     /* (like some USGS GeoPDF production) */
-    if( dfRotation == 0.0 && poDS->asTiles.size() &&
+    if( dfRotation == 0.0 && !poDS->asTiles.empty() &&
         EQUAL(GetOption(poOpenInfo->papszOpenOptions, "LAYERS", "ALL"), "ALL") )
     {
         poDS->CheckTiledRaster();
-        if (poDS->aiTiles.size() )
+        if (!poDS->aiTiles.empty() )
             poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
     }
 
@@ -4739,7 +4741,6 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLFree(pszNeatLineWkt);
     }
 
-
 #ifdef HAVE_POPPLER
   if (bUseLib.test(PDFLIB_POPPLER))
   {
@@ -4862,7 +4863,7 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 #ifdef HAVE_PODOFO
-    if (bUseLib.test(PDFLIB_PODOFO) && nBands == 4 && poDS->aiTiles.size() == 0)
+    if (bUseLib.test(PDFLIB_PODOFO) && nBands == 4 && poDS->aiTiles.empty())
     {
         CPLError(CE_Warning, CPLE_NotSupported,
                  "GDAL_PDF_BANDS=4 not supported when PDF driver is compiled against Podofo. "
@@ -4927,15 +4928,14 @@ GDALDataset *PDFDataset::Open( GDALOpenInfo * poOpenInfo )
 
 int PDFDataset::ParseLGIDictObject(GDALPDFObject* poLGIDict)
 {
-    int i;
-    int bOK = FALSE;
+    bool bOK = false;
     if (poLGIDict->GetType() == PDFObjectType_Array)
     {
         GDALPDFArray* poArray = poLGIDict->GetArray();
         int nArrayLength = poArray->GetLength();
         int iMax = -1;
-        GDALPDFObject* poArrayElt;
-        for (i=0; i<nArrayLength; i++)
+        GDALPDFObject* poArrayElt = NULL;
+        for( int i = 0; i<nArrayLength; i++ )
         {
             if ( (poArrayElt = poArray->Get(i)) == NULL ||
                  poArrayElt->GetType() != PDFObjectType_Dictionary )
@@ -4957,7 +4957,8 @@ int PDFDataset::ParseLGIDictObject(GDALPDFObject* poLGIDict)
             return FALSE;
 
         poArrayElt = poArray->Get(iMax);
-        bOK = ParseLGIDictDictSecondPass(poArrayElt->GetDictionary());
+        bOK = CPL_TO_BOOL(
+            ParseLGIDictDictSecondPass(poArrayElt->GetDictionary()));
     }
     else if (poLGIDict->GetType() == PDFObjectType_Dictionary)
     {
@@ -4999,7 +5000,8 @@ static double Get(GDALPDFObject* poObj, int nIndice)
         if (chLast == 'W' || chLast == 'E' || chLast == 'N' || chLast == 'S')
         {
             double dfDeg = CPLAtof(pszStr);
-            double dfMin = 0, dfSec = 0;
+            double dfMin = 0.0;
+            double dfSec = 0.0;
             const char* pszNext = strchr(pszStr, ' ');
             if (pszNext)
                 pszNext ++;
@@ -5033,8 +5035,8 @@ static double Get(GDALPDFObject* poObj, int nIndice)
 
 static double Get(GDALPDFDictionary* poDict, const char* pszName)
 {
-    GDALPDFObject* poObj;
-    if ( (poObj = poDict->Get(pszName)) != NULL )
+    GDALPDFObject* poObj = poDict->Get(pszName);
+    if( poObj != NULL )
         return Get(poObj);
     CPLError(CE_Failure, CPLE_AppDefined,
              "Cannot find parameter %s", pszName);
@@ -5048,8 +5050,6 @@ static double Get(GDALPDFDictionary* poDict, const char* pszName)
 int PDFDataset::ParseLGIDictDictFirstPass(GDALPDFDictionary* poLGIDict,
                                           int* pbIsBestCandidate)
 {
-    int i;
-
     if (pbIsBestCandidate)
         *pbIsBestCandidate = FALSE;
 
@@ -5059,8 +5059,8 @@ int PDFDataset::ParseLGIDictDictFirstPass(GDALPDFDictionary* poLGIDict,
 /* -------------------------------------------------------------------- */
 /*      Extract Type attribute                                          */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poType;
-    if ((poType = poLGIDict->Get("Type")) == NULL)
+    GDALPDFObject* poType = poLGIDict->Get("Type");
+    if( poType == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find Type of LGIDict object");
@@ -5085,8 +5085,8 @@ int PDFDataset::ParseLGIDictDictFirstPass(GDALPDFDictionary* poLGIDict,
 /* -------------------------------------------------------------------- */
 /*      Extract Version attribute                                       */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poVersion;
-    if ((poVersion = poLGIDict->Get("Version")) == NULL)
+    GDALPDFObject* poVersion = poLGIDict->Get("Version");
+    if( poVersion == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find Version of LGIDict object");
@@ -5114,9 +5114,9 @@ int PDFDataset::ParseLGIDictDictFirstPass(GDALPDFDictionary* poLGIDict,
 /* -------------------------------------------------------------------- */
 /*      Extract Neatline attribute                                      */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poNeatline;
-    if ((poNeatline = poLGIDict->Get("Neatline")) != NULL &&
-        poNeatline->GetType() == PDFObjectType_Array)
+    GDALPDFObject* poNeatline = poLGIDict->Get("Neatline");
+    if( poNeatline != NULL &&
+        poNeatline->GetType() == PDFObjectType_Array )
     {
         int nLength = poNeatline->GetArray()->GetLength();
         if ( (nLength % 2) != 0 || nLength < 4 )
@@ -5126,9 +5126,9 @@ int PDFDataset::ParseLGIDictDictFirstPass(GDALPDFDictionary* poLGIDict,
             return FALSE;
         }
 
-        GDALPDFObject* poDescription;
-        int bIsAskedNeatline = FALSE;
-        if ( (poDescription = poLGIDict->Get("Description")) != NULL &&
+        GDALPDFObject* poDescription = poLGIDict->Get("Description");
+        bool bIsAskedNeatline = false;
+        if( poDescription != NULL &&
             poDescription->GetType() == PDFObjectType_String )
         {
             CPLDebug("PDF", "Description = %s", poDescription->GetString().c_str());
@@ -5136,14 +5136,17 @@ int PDFDataset::ParseLGIDictDictFirstPass(GDALPDFDictionary* poLGIDict,
             if( EQUAL(poDescription->GetString().c_str(), pszNeatlineToSelect) )
             {
                 dfMaxArea = 1e300;
-                bIsAskedNeatline = TRUE;
+                bIsAskedNeatline = true;
             }
         }
 
         if( !bIsAskedNeatline )
         {
-            double dfMinX = 0, dfMinY = 0, dfMaxX = 0, dfMaxY = 0;
-            for(i=0;i<nLength;i+=2)
+            double dfMinX = 0.0;
+            double dfMinY = 0.0;
+            double dfMaxX = 0.0;
+            double dfMaxY = 0.0;
+            for( int i = 0; i < nLength; i += 2 )
             {
                 double dfX = Get(poNeatline, i);
                 double dfY = Get(poNeatline, i + 1);
@@ -5186,7 +5189,7 @@ int PDFDataset::ParseLGIDictDictFirstPass(GDALPDFDictionary* poLGIDict,
         }
         else
         {
-            for(i=0;i<nLength;i+=2)
+            for( int i = 0; i < nLength; i+=2 )
             {
                 double dfX = Get(poNeatline, i);
                 double dfY = Get(poNeatline, i + 1);
@@ -5210,9 +5213,9 @@ int PDFDataset::ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict)
 /* -------------------------------------------------------------------- */
 /*      Extract Description attribute                                   */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poDescription;
-    if ( (poDescription = poLGIDict->Get("Description")) != NULL &&
-         poDescription->GetType() == PDFObjectType_String )
+    GDALPDFObject* poDescription = poLGIDict->Get("Description");
+    if( poDescription != NULL &&
+        poDescription->GetType() == PDFObjectType_String )
     {
         CPLDebug("PDF", "Description = %s", poDescription->GetString().c_str());
     }
@@ -5220,9 +5223,9 @@ int PDFDataset::ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict)
 /* -------------------------------------------------------------------- */
 /*      Extract CTM attribute                                           */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poCTM;
+    GDALPDFObject* poCTM = poLGIDict->Get("CTM");
     bHasCTM = FALSE;
-    if ((poCTM = poLGIDict->Get("CTM")) != NULL &&
+    if( poCTM != NULL &&
         poCTM->GetType() == PDFObjectType_Array &&
         CPLTestBool(CPLGetConfigOption("PDF_USE_CTM", "YES")) )
     {
@@ -5249,9 +5252,9 @@ int PDFDataset::ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict)
 /* -------------------------------------------------------------------- */
 /*      Extract Registration attribute                                  */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poRegistration;
-    if ((poRegistration = poLGIDict->Get("Registration")) != NULL &&
-        poRegistration->GetType() == PDFObjectType_Array)
+    GDALPDFObject* poRegistration = poLGIDict->Get("Registration");
+    if( poRegistration != NULL &&
+        poRegistration->GetType() == PDFObjectType_Array )
     {
         GDALPDFArray* poRegistrationArray = poRegistration->GetArray();
         int nLength = poRegistrationArray->GetLength();
@@ -5300,9 +5303,9 @@ int PDFDataset::ParseLGIDictDictSecondPass(GDALPDFDictionary* poLGIDict)
 /* -------------------------------------------------------------------- */
 /*      Extract Projection attribute                                    */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poProjection;
-    if ((poProjection = poLGIDict->Get("Projection")) == NULL ||
-        poProjection->GetType() != PDFObjectType_Dictionary)
+    GDALPDFObject* poProjection = poLGIDict->Get("Projection");
+    if( poProjection == NULL ||
+        poProjection->GetType() != PDFObjectType_Dictionary )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Could not find Projection");
         return FALSE;
@@ -5324,10 +5327,10 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
 /* -------------------------------------------------------------------- */
 /*      Extract WKT attribute (GDAL extension)                          */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poWKT;
-    if ( (poWKT = poProjDict->Get("WKT")) != NULL &&
-         poWKT->GetType() == PDFObjectType_String &&
-         CPLTestBool( CPLGetConfigOption("GDAL_PDF_OGC_BP_READ_WKT", "TRUE") ) )
+    GDALPDFObject* poWKT = poProjDict->Get("WKT");
+    if( poWKT != NULL &&
+        poWKT->GetType() == PDFObjectType_String &&
+        CPLTestBool( CPLGetConfigOption("GDAL_PDF_OGC_BP_READ_WKT", "TRUE") ) )
     {
         CPLDebug("PDF", "Found WKT attribute (GDAL extension). Using it");
         const char* pszWKTRead = poWKT->GetString().c_str();
@@ -5339,8 +5342,8 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
 /* -------------------------------------------------------------------- */
 /*      Extract Type attribute                                          */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poType;
-    if ((poType = poProjDict->Get("Type")) == NULL)
+    GDALPDFObject* poType = poProjDict->Get("Type");
+    if( poType == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find Type of Projection object");
@@ -5369,8 +5372,8 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
     int bIsNAD83 = FALSE;
     /* int bIsNAD27 = FALSE; */
 
-    GDALPDFObject* poDatum;
-    if ((poDatum = poProjDict->Get("Datum")) != NULL)
+    GDALPDFObject* poDatum = poProjDict->Get("Datum");
+    if( poDatum != NULL )
     {
         if (poDatum->GetType() == PDFObjectType_String)
         {
@@ -5559,9 +5562,9 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
 /*      Extract Hemisphere attribute                                    */
 /* -------------------------------------------------------------------- */
     CPLString osHemisphere;
-    GDALPDFObject* poHemisphere;
-    if ((poHemisphere = poProjDict->Get("Hemisphere")) != NULL &&
-        poHemisphere->GetType() == PDFObjectType_String)
+    GDALPDFObject* poHemisphere = poProjDict->Get("Hemisphere");
+    if( poHemisphere != NULL &&
+        poHemisphere->GetType() == PDFObjectType_String )
     {
         osHemisphere = poHemisphere->GetString();
     }
@@ -5569,9 +5572,9 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
 /* -------------------------------------------------------------------- */
 /*      Extract ProjectionType attribute                                */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poProjectionType;
-    if ((poProjectionType = poProjDict->Get("ProjectionType")) == NULL ||
-        poProjectionType->GetType() != PDFObjectType_String)
+    GDALPDFObject* poProjectionType = poProjDict->Get("ProjectionType");
+    if( poProjectionType == NULL ||
+        poProjectionType->GetType() != PDFObjectType_String )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find ProjectionType of Projection object");
@@ -5902,8 +5905,8 @@ int PDFDataset::ParseProjDict(GDALPDFDictionary* poProjDict)
 /*      Extract Units attribute                                         */
 /* -------------------------------------------------------------------- */
     CPLString osUnits;
-    GDALPDFObject* poUnits;
-    if( (poUnits = poProjDict->Get("Units")) != NULL &&
+    GDALPDFObject* poUnits = poProjDict->Get("Units");
+    if( poUnits != NULL &&
         poUnits->GetType() == PDFObjectType_String &&
         !EQUAL(osProjectionType, "GEOGRAPHIC") )
     {
@@ -5978,8 +5981,8 @@ int PDFDataset::ParseVP(GDALPDFObject* poVP, double dfMediaBoxWidth, double dfMe
 
         GDALPDFDictionary* poVPEltDict = poVPElt->GetDictionary();
 
-        GDALPDFObject* poBBox;
-        if( (poBBox = poVPEltDict->Get("BBox")) == NULL ||
+        GDALPDFObject* poBBox = poVPEltDict->Get("BBox");
+        if( poBBox == NULL ||
             poBBox->GetType() != PDFObjectType_Array )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -6013,7 +6016,6 @@ int PDFDataset::ParseVP(GDALPDFObject* poVP, double dfMediaBoxWidth, double dfMe
         CPLDebug("PDF", "Largest BBox in VP array is element %d", iLargest);
     }
 
-
     GDALPDFObject* poVPElt = poVPArray->Get(iLargest);
     if (poVPElt == NULL || poVPElt->GetType() != PDFObjectType_Dictionary)
     {
@@ -6022,8 +6024,8 @@ int PDFDataset::ParseVP(GDALPDFObject* poVP, double dfMediaBoxWidth, double dfMe
 
     GDALPDFDictionary* poVPEltDict = poVPElt->GetDictionary();
 
-    GDALPDFObject* poBBox;
-    if( (poBBox = poVPEltDict->Get("BBox")) == NULL ||
+    GDALPDFObject* poBBox = poVPEltDict->Get("BBox");
+    if( poBBox == NULL ||
         poBBox->GetType() != PDFObjectType_Array )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -6047,8 +6049,8 @@ int PDFDataset::ParseVP(GDALPDFObject* poVP, double dfMediaBoxWidth, double dfMe
 /* -------------------------------------------------------------------- */
 /*      Extract Measure attribute                                       */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poMeasure;
-    if( (poMeasure = poVPEltDict->Get("Measure")) == NULL ||
+    GDALPDFObject* poMeasure = poVPEltDict->Get("Measure");
+    if( poMeasure == NULL ||
         poMeasure->GetType() != PDFObjectType_Dictionary )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -6062,8 +6064,8 @@ int PDFDataset::ParseVP(GDALPDFObject* poVP, double dfMediaBoxWidth, double dfMe
 /* -------------------------------------------------------------------- */
 /*      Extract PointData attribute                                     */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poPointData;
-    if( (poPointData = poVPEltDict->Get("PtData")) != NULL &&
+    GDALPDFObject* poPointData = poVPEltDict->Get("PtData");
+    if( poPointData != NULL &&
         poPointData->GetType() == PDFObjectType_Dictionary )
     {
         CPLDebug("PDF", "Found PointData");
@@ -6086,8 +6088,8 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
 /* -------------------------------------------------------------------- */
 /*      Extract Subtype attribute                                       */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poSubtype;
-    if( (poSubtype = poMeasureDict->Get("Subtype")) == NULL ||
+    GDALPDFObject* poSubtype = poMeasureDict->Get("Subtype");
+    if( poSubtype == NULL ||
         poSubtype->GetType() != PDFObjectType_Name )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -6105,8 +6107,8 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
     /* has lgit:LPTS, lgit:GPTS and lgit:Bounds that have more precision than */
     /* LPTS, GPTS and Bounds. Use those ones */
 
-    GDALPDFObject* poBounds;
-    if( (poBounds = poMeasureDict->Get("lgit:Bounds")) != NULL &&
+    GDALPDFObject* poBounds = poMeasureDict->Get("lgit:Bounds");
+    if( poBounds != NULL &&
         poBounds->GetType() == PDFObjectType_Array )
     {
         CPLDebug("PDF", "Using lgit:Bounds");
@@ -6138,8 +6140,8 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
 /* -------------------------------------------------------------------- */
 /*      Extract GPTS attribute                                          */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poGPTS;
-    if( (poGPTS = poMeasureDict->Get("lgit:GPTS")) != NULL &&
+    GDALPDFObject* poGPTS = poMeasureDict->Get("lgit:GPTS");
+    if( poGPTS != NULL &&
         poGPTS->GetType() == PDFObjectType_Array )
     {
         CPLDebug("PDF", "Using lgit:GPTS");
@@ -6170,9 +6172,8 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
 /* -------------------------------------------------------------------- */
 /*      Extract LPTS attribute                                          */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poLPTS;
-    if( (poLPTS = poMeasureDict->Get("lgit:LPTS")) != NULL &&
-        poLPTS->GetType() == PDFObjectType_Array )
+    GDALPDFObject* poLPTS = poMeasureDict->Get("lgit:LPTS");
+    if( poLPTS != NULL && poLPTS->GetType() == PDFObjectType_Array )
     {
         CPLDebug("PDF", "Using lgit:LPTS");
     }
@@ -6202,9 +6203,8 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
 /* -------------------------------------------------------------------- */
 /*      Extract GCS attribute                                           */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poGCS;
-    if( (poGCS = poMeasureDict->Get("GCS")) == NULL ||
-        poGCS->GetType() != PDFObjectType_Dictionary )
+    GDALPDFObject* poGCS = poMeasureDict->Get("GCS");
+    if( poGCS == NULL || poGCS->GetType() != PDFObjectType_Dictionary )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find GCS object");
@@ -6216,9 +6216,8 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
 /* -------------------------------------------------------------------- */
 /*      Extract GCS.Type attribute                                      */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poGCSType;
-    if( (poGCSType = poGCSDict->Get("Type")) == NULL ||
-        poGCSType->GetType() != PDFObjectType_Name )
+    GDALPDFObject* poGCSType = poGCSDict->Get("Type");
+    if( poGCSType == NULL || poGCSType->GetType() != PDFObjectType_Name )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find GCS.Type object");
@@ -6230,10 +6229,9 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
 /* -------------------------------------------------------------------- */
 /*      Extract EPSG attribute                                          */
 /* -------------------------------------------------------------------- */
-    GDALPDFObject* poEPSG;
+    GDALPDFObject* poEPSG = poGCSDict->Get("EPSG");
     int nEPSGCode = 0;
-    if( (poEPSG = poGCSDict->Get("EPSG")) != NULL &&
-        poEPSG->GetType() == PDFObjectType_Int )
+    if( poEPSG != NULL && poEPSG->GetType() == PDFObjectType_Int )
     {
         nEPSGCode = poEPSG->GetInt();
         CPLDebug("PDF", "GCS.EPSG = %d", nEPSGCode);
@@ -6358,8 +6356,10 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
         asGCPS[i].dfGCPPixel = (dfULX * (1 - adfLPTS[2*i+0]) + dfLRX * adfLPTS[2*i+0]) / dfMediaBoxWidth * nRasterXSize;
         asGCPS[i].dfGCPLine  = (dfULY * (1 - adfLPTS[2*i+1]) + dfLRY * adfLPTS[2*i+1]) / dfMediaBoxHeight * nRasterYSize;
 
-        double lat = adfGPTS[2*i], lon = adfGPTS[2*i+1];
-        double x = lon, y = lat;
+        double lat = adfGPTS[2*i];
+        double lon = adfGPTS[2*i+1];
+        double x = lon;
+        double y = lat;
         if (bReproject)
         {
             if (!poCT->Transform(1, &x, &y, NULL))
@@ -6403,10 +6403,14 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
     // If the non scaling terms of the geotransform are significantly smaller
     // than the pixel size, then nullify them as being just artifacts of
     //  reprojection and GDALGCPsToGeoTransform() numerical imprecisions.
-    double dfPixelSize = MIN(fabs(adfGeoTransform[1]), fabs(adfGeoTransform[5]));
-    double dfRotationShearTerm = MAX(fabs(adfGeoTransform[2]), fabs(adfGeoTransform[4]));
-    if (dfRotationShearTerm < 1e-5 * dfPixelSize ||
-        (bUseLib.test(PDFLIB_PDFIUM) && MIN(fabs(adfGeoTransform[2]), fabs(adfGeoTransform[4])) < 1e-5 * dfPixelSize))
+    const double dfPixelSize =
+        std::min(fabs(adfGeoTransform[1]), fabs(adfGeoTransform[5]));
+    const double dfRotationShearTerm =
+        std::max(fabs(adfGeoTransform[2]), fabs(adfGeoTransform[4]));
+    if( dfRotationShearTerm < 1e-5 * dfPixelSize ||
+        (bUseLib.test(PDFLIB_PDFIUM) &&
+         std::min(fabs(adfGeoTransform[2]),
+                  fabs(adfGeoTransform[4])) < 1e-5 * dfPixelSize) )
     {
         dfLRX = adfGeoTransform[0] + nRasterXSize * adfGeoTransform[1] + nRasterYSize * adfGeoTransform[2];
         dfLRY = adfGeoTransform[3] + nRasterXSize * adfGeoTransform[4] + nRasterYSize * adfGeoTransform[5];
@@ -6424,6 +6428,10 @@ int PDFDataset::ParseMeasure(GDALPDFObject* poMeasure,
 
 const char* PDFDataset::GetProjectionRef()
 {
+    const char* pszPAMProjection = GDALPamDataset::GetProjectionRef();
+    if( pszPAMProjection != NULL && pszPAMProjection[0] != '\0' )
+        return pszPAMProjection;
+
     if (pszWKT && bGeoTransformValid)
         return pszWKT;
     return "";
@@ -6436,6 +6444,11 @@ const char* PDFDataset::GetProjectionRef()
 CPLErr PDFDataset::GetGeoTransform( double * padfTransform )
 
 {
+    if( GDALPamDataset::GetGeoTransform( padfTransform ) == CE_None )
+    {
+        return CE_None;
+    }
+
     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
 
     return( (bGeoTransformValid) ? CE_None : CE_Failure );
@@ -6447,6 +6460,9 @@ CPLErr PDFDataset::GetGeoTransform( double * padfTransform )
 
 CPLErr PDFDataset::SetProjection(const char* pszWKTIn)
 {
+    if( eAccess == GA_ReadOnly )
+        GDALPamDataset::SetProjection(pszWKTIn);
+
     CPLFree(pszWKT);
     pszWKT = pszWKTIn ? CPLStrdup(pszWKTIn) : CPLStrdup("");
     bProjDirty = TRUE;
@@ -6459,6 +6475,9 @@ CPLErr PDFDataset::SetProjection(const char* pszWKTIn)
 
 CPLErr PDFDataset::SetGeoTransform(double* padfGeoTransform)
 {
+    if( eAccess == GA_ReadOnly )
+        GDALPamDataset::SetGeoTransform(padfGeoTransform);
+
     memcpy(adfGeoTransform, padfGeoTransform, 6 * sizeof(double));
     bGeoTransformValid = TRUE;
     bProjDirty = TRUE;
@@ -6511,9 +6530,33 @@ char      **PDFDataset::GetMetadata( const char * pszDomain )
         apszMetadata[0] = poStream->GetBytes();
         oMDMD.SetMetadata(apszMetadata, pszDomain);
         VSIFree(apszMetadata[0]);
+        return oMDMD.GetMetadata(pszDomain);
     }
-
-    return oMDMD.GetMetadata(pszDomain);
+    if( pszDomain == NULL || EQUAL(pszDomain, "") )
+    {
+        char** papszPAMMD = GDALPamDataset::GetMetadata(pszDomain);
+        for(char** papszIter = papszPAMMD;
+            papszIter && *papszIter;
+            ++papszIter )
+        {
+            char* pszKey = NULL;
+            const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
+            if( pszKey && pszValue )
+            {
+                if( oMDMD.GetMetadataItem( pszKey, pszDomain ) == NULL )
+                    oMDMD.SetMetadataItem( pszKey, pszValue, pszDomain );
+            }
+            CPLFree(pszKey);
+        }
+        return oMDMD.GetMetadata(pszDomain);
+    }
+    if( EQUAL(pszDomain, "LAYERS") ||
+        EQUAL(pszDomain, "xml:XMP") ||
+        EQUAL(pszDomain, "SUBDATASETS") )
+    {
+        return oMDMD.GetMetadata(pszDomain);
+    }
+    return GDALPamDataset::GetMetadata(pszDomain);
 }
 
 /************************************************************************/
@@ -6525,16 +6568,37 @@ CPLErr      PDFDataset::SetMetadata( char ** papszMetadata,
 {
     if (pszDomain == NULL || EQUAL(pszDomain, ""))
     {
-        if (CSLFindString(papszMetadata, "NEATLINE") != -1)
+        char** papszMetadataDup = CSLDuplicate(papszMetadata);
+        oMDMD.SetMetadata(NULL, pszDomain);
+
+        for(char** papszIter = papszMetadataDup;
+            papszIter && *papszIter;
+            ++papszIter )
         {
-            bProjDirty = TRUE;
-            bNeatLineDirty = TRUE;
+            char* pszKey = NULL;
+            const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
+            if( pszKey && pszValue )
+            {
+                SetMetadataItem( pszKey, pszValue, pszDomain );
+            }
+            CPLFree(pszKey);
         }
-        bInfoDirty = TRUE;
+        CSLDestroy(papszMetadataDup);
+        return CE_None;
     }
     else if (EQUAL(pszDomain, "xml:XMP"))
+    {
         bXMPDirty = TRUE;
-    return oMDMD.SetMetadata(papszMetadata, pszDomain);
+        return oMDMD.SetMetadata(papszMetadata, pszDomain);
+    }
+    else if (EQUAL(pszDomain, "SUBDATASETS") )
+    {
+        return oMDMD.SetMetadata(papszMetadata, pszDomain);
+    }
+    else
+    {
+        return GDALPamDataset::SetMetadata(papszMetadata, pszDomain);
+    }
 }
 
 /************************************************************************/
@@ -6554,7 +6618,7 @@ const char *PDFDataset::GetMetadataItem( const char * pszName,
         if(bUseLib.test(PDFLIB_PDFIUM))
             return "PDFIUM";
     }
-    return oMDMD.GetMetadataItem(pszName, pszDomain);
+    return CSLFetchNameValue( GetMetadata(pszDomain), pszName );
 }
 
 /************************************************************************/
@@ -6569,19 +6633,61 @@ CPLErr      PDFDataset::SetMetadataItem( const char * pszName,
     {
         if (EQUAL(pszName, "NEATLINE"))
         {
-            bProjDirty = TRUE;
-            bNeatLineDirty = TRUE;
+            const char* pszOldValue = oMDMD.GetMetadataItem(pszName, pszDomain);
+            if( (pszValue == NULL && pszOldValue != NULL) ||
+                (pszValue != NULL && pszOldValue == NULL) ||
+                (pszValue != NULL && pszOldValue != NULL &&
+                 strcmp(pszValue, pszOldValue) != 0) )
+            {
+                bProjDirty = TRUE;
+                bNeatLineDirty = TRUE;
+            }
+            return oMDMD.SetMetadataItem(pszName, pszValue, pszDomain);
         }
         else
         {
-            if (pszValue == NULL)
-                pszValue = "";
-            bInfoDirty = TRUE;
+            if( EQUAL(pszName, "AUTHOR") ||
+                EQUAL(pszName, "PRODUCER") ||
+                EQUAL(pszName, "CREATOR") ||
+                EQUAL(pszName, "CREATION_DATE") ||
+                EQUAL(pszName, "SUBJECT") ||
+                EQUAL(pszName, "TITLE") ||
+                EQUAL(pszName, "KEYWORDS") )
+            {
+                if (pszValue == NULL)
+                    pszValue = "";
+                const char* pszOldValue = oMDMD.GetMetadataItem(pszName, pszDomain);
+                if( pszOldValue == NULL ||
+                    strcmp(pszValue, pszOldValue) != 0 )
+                {
+                    bInfoDirty = TRUE;
+                }
+                return oMDMD.SetMetadataItem(pszName, pszValue, pszDomain);
+            }
+            else if( EQUAL(pszName, "DPI") )
+            {
+                return oMDMD.SetMetadataItem(pszName, pszValue, pszDomain);
+            }
+            else
+            {
+                oMDMD.SetMetadataItem(pszName, pszValue, pszDomain);
+                return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain);
+            }
         }
     }
     else if (EQUAL(pszDomain, "xml:XMP"))
+    {
         bXMPDirty = TRUE;
-    return oMDMD.SetMetadataItem(pszName, pszValue, pszDomain);
+        return oMDMD.SetMetadataItem(pszName, pszValue, pszDomain);
+    }
+    else if (EQUAL(pszDomain, "SUBDATASETS"))
+    {
+        return oMDMD.SetMetadataItem(pszName, pszValue, pszDomain);
+    }
+    else
+    {
+        return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain);
+    }
 }
 
 /************************************************************************/
@@ -6779,6 +6885,9 @@ void GDALRegister_PDF()
     poDriver->SetMetadataItem( "HAVE_PDFIUM", "YES" );
 #endif // HAVE_PDFIUM
 
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+"<LayerCreationOptionList/>" );
+
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>\n"
 "   <Option name='COMPRESS' type='string-select' description='Compression method for raster data' default='DEFLATE'>\n"
@@ -6799,6 +6908,7 @@ void GDALRegister_PDF()
 "   </Option>\n"
 "   <Option name='NEATLINE' type='string' description='Neatline'/>\n"
 "   <Option name='DPI' type='float' description='DPI' default='72'/>\n"
+"   <Option name='WRITE_USERUNIT' type='boolean' description='Whether the UserUnit parameter must be written'/>\n"
 "   <Option name='PREDICTOR' type='int' description='Predictor Type (for DEFLATE compression)'/>\n"
 "   <Option name='JPEG_QUALITY' type='int' description='JPEG quality 1-100' default='75'/>\n"
 "   <Option name='JPEG2000_DRIVER' type='string'/>\n"
diff --git a/frmts/pdf/pdfio.cpp b/frmts/pdf/pdfio.cpp
index 3baeac0..9be6189 100644
--- a/frmts/pdf/pdfio.cpp
+++ b/frmts/pdf/pdfio.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -35,8 +34,7 @@
 
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: pdfio.cpp 31977 2015-12-03 11:42:22Z rouault $");
-
+CPL_CVSID("$Id: pdfio.cpp 35897 2016-10-24 11:54:24Z goatbar $");
 
 #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
 /* Poppler 0.31.0 is the first one that needs to know the file size */
@@ -53,49 +51,50 @@ static vsi_l_offset VSIPDFFileStreamGetSize(VSILFILE* f)
 /*                         VSIPDFFileStream()                           */
 /************************************************************************/
 
-VSIPDFFileStream::VSIPDFFileStream(VSILFILE* fIn, const char* pszFilename, Object *dictA):
+VSIPDFFileStream::VSIPDFFileStream(
+    VSILFILE* fIn, const char* pszFilename, Object *dictA) :
 #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
-                                                        BaseStream(dictA, (setPos_offset_type)VSIPDFFileStreamGetSize(fIn))
+    BaseStream(dictA, (setPos_offset_type)VSIPDFFileStreamGetSize(fIn)),
 #else
-                                                        BaseStream(dictA)
+    BaseStream(dictA),
 #endif
-{
-    poParent = NULL;
-    poFilename = new GooString(pszFilename);
-    this->f = fIn;
-    nStart = 0;
-    bLimited = gFalse;
-    nLength = 0;
-    nCurrentPos = VSI_L_OFFSET_MAX;
-    bHasSavedPos = FALSE;
-    nSavedPos = 0;
-    nPosInBuffer = nBufferLength = -1;
-}
+    poParent(NULL),
+    poFilename(new GooString(pszFilename)),
+    f(fIn),
+    nStart(0),
+    bLimited(gFalse),
+    nLength(0),
+    nCurrentPos(VSI_L_OFFSET_MAX),
+    bHasSavedPos(FALSE),
+    nSavedPos(0),
+    nPosInBuffer(-1),
+    nBufferLength(-1)
+{}
 
 /************************************************************************/
 /*                         VSIPDFFileStream()                           */
 /************************************************************************/
 
-VSIPDFFileStream::VSIPDFFileStream(VSIPDFFileStream* poParentIn,
-                                   vsi_l_offset startA, GBool limitedA,
-                                   vsi_l_offset lengthA, Object *dictA):
+VSIPDFFileStream::VSIPDFFileStream( VSIPDFFileStream* poParentIn,
+                                    vsi_l_offset startA, GBool limitedA,
+                                    vsi_l_offset lengthA, Object *dictA ) :
 #ifdef POPPLER_BASE_STREAM_HAS_TWO_ARGS
-                                                        BaseStream(dictA, (makeSubStream_offset_type)lengthA)
+    BaseStream(dictA, (makeSubStream_offset_type)lengthA),
 #else
-                                                        BaseStream(dictA)
+    BaseStream(dictA),
 #endif
-{
-    this->poParent = poParentIn;
-    poFilename = poParent->poFilename;
-    f = poParent->f;
-    nStart = startA;
-    bLimited = limitedA;
-    nLength = lengthA;
-    nCurrentPos = VSI_L_OFFSET_MAX;
-    bHasSavedPos = FALSE;
-    nSavedPos = 0;
-    nPosInBuffer = nBufferLength = -1;
-}
+    poParent(poParentIn),
+    poFilename(poParentIn->poFilename),
+    f(poParentIn->f),
+    nStart(startA),
+    bLimited(limitedA),
+    nLength(lengthA),
+    nCurrentPos(VSI_L_OFFSET_MAX),
+    bHasSavedPos(FALSE),
+    nSavedPos(0),
+    nPosInBuffer(-1),
+    nBufferLength(-1)
+{}
 
 /************************************************************************/
 /*                        ~VSIPDFFileStream()                           */
@@ -149,7 +148,6 @@ getPos_ret_type VSIPDFFileStream::getPos()
 /*                                getStart()                            */
 /************************************************************************/
 
-
 getStart_ret_type VSIPDFFileStream::getStart()
 {
     return (getStart_ret_type) nStart;
@@ -293,7 +291,8 @@ void VSIPDFFileStream::reset()
     nSavedPos = VSIFTellL(f);
     bHasSavedPos = TRUE;
     VSIFSeekL(f, nCurrentPos = nStart, SEEK_SET);
-    nPosInBuffer = nBufferLength = -1;
+    nPosInBuffer = -1;
+    nBufferLength = -1;
 }
 
 /************************************************************************/
@@ -343,7 +342,8 @@ void VSIPDFFileStream::setPos(setPos_offset_type pos, int dir)
             newpos = size;
         VSIFSeekL(f, nCurrentPos = size - newpos, SEEK_SET);
     }
-    nPosInBuffer = nBufferLength = -1;
+    nPosInBuffer = -1;
+    nBufferLength = -1;
 }
 
 /************************************************************************/
@@ -354,7 +354,8 @@ void VSIPDFFileStream::moveStart(moveStart_delta_type delta)
 {
     nStart += delta;
     VSIFSeekL(f, nCurrentPos = nStart, SEEK_SET);
-    nPosInBuffer = nBufferLength = -1;
+    nPosInBuffer = -1;
+    nBufferLength = -1;
 }
 
 /************************************************************************/
@@ -381,7 +382,8 @@ int VSIPDFFileStream::getChars(int nChars, Guchar *buffer)
             if (!bLimited && nToRead > BUFFER_SIZE)
             {
                 int nJustRead = (int) VSIFReadL(buffer + nRead, 1, nToRead, f);
-                nPosInBuffer = nBufferLength = -1;
+                nPosInBuffer = -1;
+                nBufferLength = -1;
                 nCurrentPos += nJustRead;
                 nRead += nJustRead;
                 break;
diff --git a/frmts/pdf/pdfio.h b/frmts/pdf/pdfio.h
index 13b36a0..20dbfb3 100644
--- a/frmts/pdf/pdfio.h
+++ b/frmts/pdf/pdfio.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdfio.h 33338 2016-02-03 10:24:38Z rouault $
+ * $Id: pdfio.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -38,7 +38,6 @@
 
 #define BUFFER_SIZE 1024
 
-
 #ifdef POPPLER_0_23_OR_LATER
 #define getPos_ret_type Goffset
 #define getStart_ret_type Goffset
@@ -53,7 +52,6 @@
 #define moveStart_delta_type int
 #endif
 
-
 class VSIPDFFileStream: public BaseStream
 {
     public:
@@ -64,32 +62,32 @@ class VSIPDFFileStream: public BaseStream
         virtual ~VSIPDFFileStream();
 
 #ifdef POPPLER_0_23_OR_LATER
-        virtual BaseStream* copy();
+        virtual BaseStream* copy() override;
 #endif
 
         virtual Stream *   makeSubStream(makeSubStream_offset_type startA, GBool limitedA,
-                                         makeSubStream_offset_type lengthA, Object *dictA);
-        virtual getPos_ret_type      getPos();
-        virtual getStart_ret_type    getStart();
+                                         makeSubStream_offset_type lengthA, Object *dictA) override;
+        virtual getPos_ret_type      getPos() override;
+        virtual getStart_ret_type    getStart() override;
 
-        virtual void       setPos(setPos_offset_type pos, int dir = 0);
-        virtual void       moveStart(moveStart_delta_type delta);
+        virtual void       setPos(setPos_offset_type pos, int dir = 0) override;
+        virtual void       moveStart(moveStart_delta_type delta) override;
 
-        virtual StreamKind getKind();
-        virtual GooString *getFileName();
+        virtual StreamKind getKind() override;
+        virtual GooString *getFileName() override;
 
-        virtual int        getChar();
-        virtual int        getUnfilteredChar ();
-        virtual int        lookChar();
+        virtual int        getChar() override;
+        virtual int        getUnfilteredChar () override;
+        virtual int        lookChar() override;
 
-        virtual void       reset();
-        virtual void       unfilteredReset ();
-        virtual void       close();
+        virtual void       reset() override;
+        virtual void       unfilteredReset () override;
+        virtual void       close() override;
 
     private:
         /* Added in poppler 0.15.0 */
-        virtual GBool hasGetChars();
-        virtual int getChars(int nChars, Guchar *buffer);
+        virtual GBool hasGetChars() override;
+        virtual int getChars(int nChars, Guchar *buffer) override;
 
         VSIPDFFileStream  *poParent;
         GooString         *poFilename;
diff --git a/frmts/pdf/pdfobject.cpp b/frmts/pdf/pdfobject.cpp
index e1f11a9..bb345a2 100644
--- a/frmts/pdf/pdfobject.cpp
+++ b/frmts/pdf/pdfobject.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pdfobject.cpp 32179 2015-12-14 16:22:34Z goatbar $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -39,7 +38,7 @@
 #include <vector>
 #include "pdfobject.h"
 
-CPL_CVSID("$Id: pdfobject.cpp 32179 2015-12-14 16:22:34Z goatbar $");
+CPL_CVSID("$Id: pdfobject.cpp 36776 2016-12-10 11:17:47Z rouault $");
 
 /************************************************************************/
 /*                        ROUND_TO_INT_IF_CLOSE()                       */
@@ -302,7 +301,8 @@ void GDALPDFObject::Serialize(CPLString& osStr)
         case PDFObjectType_Array: GetArray()->Serialize(osStr); return;
         case PDFObjectType_Dictionary: GetDictionary()->Serialize(osStr); return;
         case PDFObjectType_Unknown:
-        default: fprintf(stderr, "Serializing unknown object !\n"); return;
+        default: CPLError(CE_Warning, CPLE_AppDefined,
+                          "Serializing unknown object !"); return;
     }
 }
 
@@ -330,7 +330,8 @@ GDALPDFObjectRW* GDALPDFObject::Clone()
         case PDFObjectType_Array: return GDALPDFObjectRW::CreateArray(GetArray()->Clone());
         case PDFObjectType_Dictionary: return GDALPDFObjectRW::CreateDictionary(GetDictionary()->Clone());
         case PDFObjectType_Unknown:
-        default: fprintf(stderr, "Cloning unknown object !\n"); return NULL;
+        default: CPLError(CE_Warning, CPLE_AppDefined,
+                          "Cloning unknown object !"); return NULL;
     }
 }
 
@@ -514,18 +515,17 @@ GDALPDFStream::~GDALPDFStream()
 /*                           GDALPDFObjectRW()                          */
 /************************************************************************/
 
-GDALPDFObjectRW::GDALPDFObjectRW(GDALPDFObjectType eType)
-{
-    m_eType = eType;
-    m_nVal = 0;
-    m_dfVal = 0.0;
-    //m_osVal;
-    m_poDict = NULL;
-    m_poArray = NULL;
-    m_nNum = 0;
-    m_nGen = 0;
-    m_bCanRepresentRealAsString = FALSE;
-}
+GDALPDFObjectRW::GDALPDFObjectRW(GDALPDFObjectType eType) :
+    m_eType(eType),
+    m_nVal(0),
+    m_dfVal(0.0),
+    // m_osVal
+    m_poDict(NULL),
+    m_poArray(NULL),
+    m_nNum(0),
+    m_nGen(0),
+    m_bCanRepresentRealAsString(FALSE)
+{}
 
 /************************************************************************/
 /*                             ~GDALPDFObjectRW()                       */
@@ -645,7 +645,7 @@ GDALPDFObjectRW* GDALPDFObjectRW::CreateArray(GDALPDFArrayRW* poArray)
 
 const char* GDALPDFObjectRW::GetTypeNameNative()
 {
-    fprintf(stderr, "Should not go here");
+    CPLError(CE_Failure, CPLE_AppDefined, "Should not go here");
     return "";
 }
 
@@ -764,9 +764,7 @@ int GDALPDFObjectRW::GetRefGen()
 /*                           GDALPDFDictionaryRW()                      */
 /************************************************************************/
 
-GDALPDFDictionaryRW::GDALPDFDictionaryRW()
-{
-}
+GDALPDFDictionaryRW::GDALPDFDictionaryRW() {}
 
 /************************************************************************/
 /*                          ~GDALPDFDictionaryRW()                      */
@@ -845,9 +843,7 @@ GDALPDFDictionaryRW& GDALPDFDictionaryRW::Remove(const char* pszKey)
 /*                             GDALPDFArrayRW()                         */
 /************************************************************************/
 
-GDALPDFArrayRW::GDALPDFArrayRW()
-{
-}
+GDALPDFArrayRW::GDALPDFArrayRW() {}
 
 /************************************************************************/
 /*                            ~GDALPDFArrayRW()                         */
@@ -855,7 +851,7 @@ GDALPDFArrayRW::GDALPDFArrayRW()
 
 GDALPDFArrayRW::~GDALPDFArrayRW()
 {
-    for(size_t i=0; i < m_array.size(); i++)
+    for( size_t i = 0; i < m_array.size(); i++ )
         delete m_array[i];
 }
 
@@ -919,8 +915,8 @@ class GDALPDFDictionaryPoppler: public GDALPDFDictionary
         GDALPDFDictionaryPoppler(Dict* poDict) : m_poDict(poDict) {}
         virtual ~GDALPDFDictionaryPoppler();
 
-        virtual GDALPDFObject* Get(const char* pszKey);
-        virtual std::map<CPLString, GDALPDFObject*>& GetValues();
+        virtual GDALPDFObject* Get(const char* pszKey) override;
+        virtual std::map<CPLString, GDALPDFObject*>& GetValues() override;
 };
 
 /************************************************************************/
@@ -939,8 +935,8 @@ class GDALPDFArrayPoppler : public GDALPDFArray
         GDALPDFArrayPoppler(Array* poArray) : m_poArray(poArray) {}
         virtual ~GDALPDFArrayPoppler();
 
-        virtual int GetLength();
-        virtual GDALPDFObject* Get(int nIndex);
+        virtual int GetLength() override;
+        virtual GDALPDFObject* Get(int nIndex) override;
 };
 
 /************************************************************************/
@@ -959,8 +955,8 @@ class GDALPDFStreamPoppler : public GDALPDFStream
         GDALPDFStreamPoppler(Stream* poStream) : m_nLength(-1), m_poStream(poStream) {}
         virtual ~GDALPDFStreamPoppler() {}
 
-        virtual int GetLength();
-        virtual char* GetBytes();
+        virtual int GetLength() override;
+        virtual char* GetBytes() override;
 };
 
 /************************************************************************/
@@ -1189,7 +1185,8 @@ GDALPDFObject* GDALPDFDictionaryPoppler::Get(const char* pszKey)
     Object* po = new Object;
     if (m_poDict->lookupNF((char*)pszKey, po) && !po->isNull())
     {
-        int nRefNum = 0, nRefGen = 0;
+        int nRefNum = 0;
+        int nRefGen = 0;
         if( po->isRef())
         {
             nRefNum = po->getRefNum();
@@ -1292,7 +1289,8 @@ GDALPDFObject* GDALPDFArrayPoppler::Get(int nIndex)
     Object* po = new Object;
     if (m_poArray->getNF(nIndex, po))
     {
-        int nRefNum = 0, nRefGen = 0;
+        int nRefNum = 0;
+        int nRefGen = 0;
         if( po->isRef())
         {
             nRefNum = po->getRefNum();
@@ -1426,8 +1424,8 @@ class GDALPDFDictionaryPodofo: public GDALPDFDictionary
         GDALPDFDictionaryPodofo(PoDoFo::PdfDictionary* poDict, PoDoFo::PdfVecObjects& poObjects) : m_poDict(poDict), m_poObjects(poObjects) {}
         virtual ~GDALPDFDictionaryPodofo();
 
-        virtual GDALPDFObject* Get(const char* pszKey);
-        virtual std::map<CPLString, GDALPDFObject*>& GetValues();
+        virtual GDALPDFObject* Get(const char* pszKey) override;
+        virtual std::map<CPLString, GDALPDFObject*>& GetValues() override;
 };
 
 /************************************************************************/
@@ -1447,8 +1445,8 @@ class GDALPDFArrayPodofo : public GDALPDFArray
         GDALPDFArrayPodofo(PoDoFo::PdfArray* poArray, PoDoFo::PdfVecObjects& poObjects) : m_poArray(poArray), m_poObjects(poObjects) {}
         virtual ~GDALPDFArrayPodofo();
 
-        virtual int GetLength();
-        virtual GDALPDFObject* Get(int nIndex);
+        virtual int GetLength() override;
+        virtual GDALPDFObject* Get(int nIndex) override;
 };
 
 /************************************************************************/
@@ -1466,8 +1464,8 @@ class GDALPDFStreamPodofo : public GDALPDFStream
         GDALPDFStreamPodofo(PoDoFo::PdfStream* pStream) : m_pStream(pStream) { }
         virtual ~GDALPDFStreamPodofo() { }
 
-        virtual int GetLength();
-        virtual char* GetBytes();
+        virtual int GetLength() override;
+        virtual char* GetBytes() override;
 };
 
 /************************************************************************/
@@ -1480,8 +1478,13 @@ class GDALPDFStreamPodofo : public GDALPDFStream
 /*                          GDALPDFObjectPodofo()                       */
 /************************************************************************/
 
-GDALPDFObjectPodofo::GDALPDFObjectPodofo(PoDoFo::PdfObject* po, PoDoFo::PdfVecObjects& poObjects) :
-        m_po(po), m_poObjects(poObjects), m_poDict(NULL), m_poArray(NULL), m_poStream(NULL)
+GDALPDFObjectPodofo::GDALPDFObjectPodofo(PoDoFo::PdfObject* po,
+                                         PoDoFo::PdfVecObjects& poObjects) :
+    m_po(po),
+    m_poObjects(poObjects),
+    m_poDict(NULL),
+    m_poArray(NULL),
+    m_poStream(NULL)
 {
     try
     {
@@ -1875,8 +1878,8 @@ class GDALPDFDictionaryPdfium: public GDALPDFDictionary
         GDALPDFDictionaryPdfium(CPDF_Dictionary* poDict) : m_poDict(poDict) {}
         virtual ~GDALPDFDictionaryPdfium();
 
-        virtual GDALPDFObject* Get(const char* pszKey);
-        virtual std::map<CPLString, GDALPDFObject*>& GetValues();
+        virtual GDALPDFObject* Get(const char* pszKey) override;
+        virtual std::map<CPLString, GDALPDFObject*>& GetValues() override;
 };
 
 /************************************************************************/
@@ -1895,8 +1898,8 @@ class GDALPDFArrayPdfium : public GDALPDFArray
         GDALPDFArrayPdfium(CPDF_Array* poArray) : m_poArray(poArray) {}
         virtual ~GDALPDFArrayPdfium();
 
-        virtual int GetLength();
-        virtual GDALPDFObject* Get(int nIndex);
+        virtual int GetLength() override;
+        virtual GDALPDFObject* Get(int nIndex) override;
 };
 
 /************************************************************************/
@@ -1915,11 +1918,12 @@ class GDALPDFStreamPdfium : public GDALPDFStream
         void Decompress();
 
     public:
-        GDALPDFStreamPdfium(CPDF_Stream* pStream) : m_pStream(pStream), m_nSize(0), m_pData(NULL) { }
+        GDALPDFStreamPdfium( CPDF_Stream* pStream ) :
+            m_pStream(pStream), m_nSize(0), m_pData(NULL) {}
         virtual ~GDALPDFStreamPdfium() { FX_Free(m_pData); }
 
-        virtual int GetLength();
-        virtual char* GetBytes();
+        virtual int GetLength() override;
+        virtual char* GetBytes() override;
 };
 
 /************************************************************************/
@@ -1932,8 +1936,11 @@ class GDALPDFStreamPdfium : public GDALPDFStream
 /*                          GDALPDFObjectPdfium()                       */
 /************************************************************************/
 
-GDALPDFObjectPdfium::GDALPDFObjectPdfium(CPDF_Object *po) :
-        m_po(po), m_poDict(NULL), m_poArray(NULL), m_poStream(NULL)
+GDALPDFObjectPdfium::GDALPDFObjectPdfium( CPDF_Object *po ) :
+    m_po(po),
+    m_poDict(NULL),
+    m_poArray(NULL),
+    m_poStream(NULL)
 {
     CPLAssert(m_po != NULL);
 }
@@ -1989,7 +1996,7 @@ GDALPDFObjectType GDALPDFObjectPdfium::GetType()
         case PDFOBJ_DICTIONARY:               return PDFObjectType_Dictionary;
         case PDFOBJ_STREAM:                   return PDFObjectType_Dictionary;
         default:
-          CPLAssert(FALSE);
+          CPLAssert(false);
           return PDFObjectType_Unknown;
     }
 }
@@ -2024,7 +2031,6 @@ int GDALPDFObjectPdfium::GetInt()
     return m_po->GetInteger();
 }
 
-
 /************************************************************************/
 /*                       CPLRoundToMoreLikelyDouble()                   */
 /************************************************************************/
diff --git a/frmts/pdf/pdfobject.h b/frmts/pdf/pdfobject.h
index d7ba21f..cba228e 100644
--- a/frmts/pdf/pdfobject.h
+++ b/frmts/pdf/pdfobject.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: pdfobject.h 31213 2015-10-29 00:02:45Z rouault $
+ * $Id: pdfobject.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset.
@@ -148,10 +148,10 @@ class GDALPDFObjectRW : public GDALPDFObject
         int                   m_nGen;
         int                   m_bCanRepresentRealAsString;
 
-                              GDALPDFObjectRW(GDALPDFObjectType eType);
+        explicit              GDALPDFObjectRW(GDALPDFObjectType eType);
 
     protected:
-        virtual const char*       GetTypeNameNative();
+        virtual const char*       GetTypeNameNative() override;
 
     public:
 
@@ -166,18 +166,18 @@ class GDALPDFObjectRW : public GDALPDFObject
         static GDALPDFObjectRW* CreateArray(GDALPDFArrayRW* poArray);
         virtual ~GDALPDFObjectRW();
 
-        virtual GDALPDFObjectType GetType();
-        virtual int               GetBool();
-        virtual int               GetInt();
-        virtual double            GetReal();
-        virtual int               CanRepresentRealAsString() { return m_bCanRepresentRealAsString; }
-        virtual const CPLString&  GetString();
-        virtual const CPLString&  GetName();
-        virtual GDALPDFDictionary*  GetDictionary();
-        virtual GDALPDFArray*       GetArray();
-        virtual GDALPDFStream*      GetStream();
-        virtual int                 GetRefNum();
-        virtual int                 GetRefGen();
+        virtual GDALPDFObjectType GetType() override;
+        virtual int               GetBool() override;
+        virtual int               GetInt() override;
+        virtual double            GetReal() override;
+        virtual int               CanRepresentRealAsString() override { return m_bCanRepresentRealAsString; }
+        virtual const CPLString&  GetString() override;
+        virtual const CPLString&  GetName() override;
+        virtual GDALPDFDictionary*  GetDictionary() override;
+        virtual GDALPDFArray*       GetArray() override;
+        virtual GDALPDFStream*      GetStream() override;
+        virtual int                 GetRefNum() override;
+        virtual int                 GetRefGen() override;
 };
 
 class GDALPDFDictionaryRW : public GDALPDFDictionary
@@ -189,8 +189,8 @@ class GDALPDFDictionaryRW : public GDALPDFDictionary
                                GDALPDFDictionaryRW();
         virtual               ~GDALPDFDictionaryRW();
 
-        virtual GDALPDFObject*                       Get(const char* pszKey);
-        virtual std::map<CPLString, GDALPDFObject*>& GetValues();
+        virtual GDALPDFObject*                       Get(const char* pszKey) override;
+        virtual std::map<CPLString, GDALPDFObject*>& GetValues() override;
 
         GDALPDFDictionaryRW&   Add(const char* pszKey, GDALPDFObject* poVal);
         GDALPDFDictionaryRW&   Remove(const char* pszKey);
@@ -212,8 +212,8 @@ class GDALPDFArrayRW : public GDALPDFArray
                                GDALPDFArrayRW();
         virtual               ~GDALPDFArrayRW();
 
-        virtual int            GetLength();
-        virtual GDALPDFObject* Get(int nIndex);
+        virtual int            GetLength() override;
+        virtual GDALPDFObject* Get(int nIndex) override;
 
         GDALPDFArrayRW&        Add(GDALPDFObject* poObj);
 
@@ -241,7 +241,7 @@ class GDALPDFObjectPoppler : public GDALPDFObject
         int m_nRefGen;
 
     protected:
-        virtual const char*       GetTypeNameNative();
+        virtual const char*       GetTypeNameNative() override;
 
     public:
         GDALPDFObjectPoppler(Object* po, int bDestroy) :
@@ -253,17 +253,17 @@ class GDALPDFObjectPoppler : public GDALPDFObject
 
         virtual ~GDALPDFObjectPoppler();
 
-        virtual GDALPDFObjectType GetType();
-        virtual int               GetBool();
-        virtual int               GetInt();
-        virtual double            GetReal();
-        virtual const CPLString&  GetString();
-        virtual const CPLString&  GetName();
-        virtual GDALPDFDictionary*  GetDictionary();
-        virtual GDALPDFArray*       GetArray();
-        virtual GDALPDFStream*      GetStream();
-        virtual int                 GetRefNum();
-        virtual int                 GetRefGen();
+        virtual GDALPDFObjectType GetType() override;
+        virtual int               GetBool() override;
+        virtual int               GetInt() override;
+        virtual double            GetReal() override;
+        virtual const CPLString&  GetString() override;
+        virtual const CPLString&  GetName() override;
+        virtual GDALPDFDictionary*  GetDictionary() override;
+        virtual GDALPDFArray*       GetArray() override;
+        virtual GDALPDFStream*      GetStream() override;
+        virtual int                 GetRefNum() override;
+        virtual int                 GetRefGen() override;
 };
 
 GDALPDFArray* GDALPDFCreateArray(Array* array);
@@ -283,24 +283,24 @@ class GDALPDFObjectPodofo : public GDALPDFObject
         CPLString osStr;
 
     protected:
-        virtual const char*       GetTypeNameNative();
+        virtual const char*       GetTypeNameNative() override;
 
     public:
         GDALPDFObjectPodofo(PoDoFo::PdfObject* po, PoDoFo::PdfVecObjects& poObjects);
 
         virtual ~GDALPDFObjectPodofo();
 
-        virtual GDALPDFObjectType GetType();
-        virtual int               GetBool();
-        virtual int               GetInt();
-        virtual double            GetReal();
-        virtual const CPLString&  GetString();
-        virtual const CPLString&  GetName();
-        virtual GDALPDFDictionary*  GetDictionary();
-        virtual GDALPDFArray*       GetArray();
-        virtual GDALPDFStream*      GetStream();
-        virtual int                 GetRefNum();
-        virtual int                 GetRefGen();
+        virtual GDALPDFObjectType GetType() override;
+        virtual int               GetBool() override;
+        virtual int               GetInt() override;
+        virtual double            GetReal() override;
+        virtual const CPLString&  GetString() override;
+        virtual const CPLString&  GetName() override;
+        virtual GDALPDFDictionary*  GetDictionary() override;
+        virtual GDALPDFArray*       GetArray() override;
+        virtual GDALPDFStream*      GetStream() override;
+        virtual int                 GetRefNum() override;
+        virtual int                 GetRefGen() override;
 };
 
 #endif // HAVE_PODOFO
@@ -319,25 +319,24 @@ class GDALPDFObjectPdfium : public GDALPDFObject
                 GDALPDFObjectPdfium(CPDF_Object *po);
 
     protected:
-        virtual const char*       GetTypeNameNative();
+        virtual const char*       GetTypeNameNative() override;
 
     public:
         static GDALPDFObjectPdfium* Build(CPDF_Object *po);
 
         virtual ~GDALPDFObjectPdfium();
 
-        virtual GDALPDFObjectType GetType();
-        virtual int               GetBool();
-        virtual int               GetInt();
-        virtual double            GetReal();
-        virtual const CPLString&  GetString();
-        virtual const CPLString&  GetName();
-        virtual GDALPDFDictionary*  GetDictionary();
-        virtual GDALPDFArray*       GetArray();
-        virtual GDALPDFStream*      GetStream();
-        virtual int                 GetRefNum();
-        virtual int                 GetRefGen();
-
+        virtual GDALPDFObjectType GetType() override;
+        virtual int               GetBool() override;
+        virtual int               GetInt() override;
+        virtual double            GetReal() override;
+        virtual const CPLString&  GetString() override;
+        virtual const CPLString&  GetName() override;
+        virtual GDALPDFDictionary*  GetDictionary() override;
+        virtual GDALPDFArray*       GetArray() override;
+        virtual GDALPDFStream*      GetStream() override;
+        virtual int                 GetRefNum() override;
+        virtual int                 GetRefGen() override;
 };
 
 #endif // HAVE_PDFIUM
diff --git a/frmts/pdf/pdfreadvectors.cpp b/frmts/pdf/pdfreadvectors.cpp
index 07fb87d..9020854 100644
--- a/frmts/pdf/pdfreadvectors.cpp
+++ b/frmts/pdf/pdfreadvectors.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pdfreadvectors.cpp 33123 2016-01-23 18:59:28Z rouault $
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset (read vector features)
@@ -32,7 +31,7 @@
 #define SQUARE(x) ((x)*(x))
 #define EPSILON 1e-5
 
-CPL_CVSID("$Id: pdfreadvectors.cpp 33123 2016-01-23 18:59:28Z rouault $");
+CPL_CVSID("$Id: pdfreadvectors.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 #if defined(HAVE_POPPLER) || defined(HAVE_PODOFO) || defined(HAVE_PDFIUM)
 
@@ -275,11 +274,11 @@ void PDFDataset::ExploreTree(GDALPDFObject* poObj, int nRecLevel)
             poArray->Get(0)->GetDictionary()->Get("K")->GetType() == PDFObjectType_Int)
         {
             CPLString osLayerName;
-            if (osT.size())
+            if (!osT.empty() )
                 osLayerName = osT;
             else
             {
-                if (osS.size())
+                if (!osS.empty() )
                     osLayerName = osS;
                 else
                     osLayerName = CPLSPrintf("Layer%d", nLayers + 1);
@@ -574,10 +573,11 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
             memcpy(aszTokenStack[nTokenStackSize ++], str, strlen + 1); \
         else \
         { \
-            CPLError(CE_Failure, CPLE_AppDefined, "Max token stack size reached");\
+            CPLError(CE_Failure, CPLE_AppDefined, \
+                     "Max token stack size reached"); \
             return NULL; \
         }; \
-    } while(0)
+    } while( false )
 
 #define ADD_CHAR(szToken, c) \
     do \
@@ -592,7 +592,7 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
             CPLError(CE_Failure, CPLE_AppDefined, "Max token size reached");\
             return NULL; \
         }; \
-    } while(0)
+    } while( false )
 
     char szToken[MAX_TOKEN_SIZE];
     int nTokenSize = 0;
@@ -851,9 +851,9 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
                 else if (EQUAL1(szToken, "b") || /* closepath, fill, stroke */
                          EQUAL2(szToken, "b*")   /* closepath, eofill, stroke */)
                 {
-                    if (!(oCoords.size() > 0 &&
+                    if (!(!oCoords.empty() &&
                           oCoords[oCoords.size() - 2] == CLOSE_SUBPATH &&
-                          oCoords[oCoords.size() - 1] == CLOSE_SUBPATH))
+                          oCoords.back() == CLOSE_SUBPATH))
                     {
                         oCoords.push_back(CLOSE_SUBPATH);
                         oCoords.push_back(CLOSE_SUBPATH);
@@ -878,9 +878,9 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
                 }
                 else if (EQUAL1(szToken, "h")) /* close subpath */
                 {
-                    if (!(oCoords.size() > 0 &&
+                    if (!(!oCoords.empty() &&
                           oCoords[oCoords.size() - 2] == CLOSE_SUBPATH &&
-                          oCoords[oCoords.size() - 1] == CLOSE_SUBPATH))
+                          oCoords.back() == CLOSE_SUBPATH))
                     {
                         oCoords.push_back(CLOSE_SUBPATH);
                         oCoords.push_back(CLOSE_SUBPATH);
@@ -892,9 +892,9 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
                 }
                 else if (EQUAL1(szToken, "s")) /* close and stroke */
                 {
-                    if (!(oCoords.size() > 0 &&
+                    if (!(!oCoords.empty() &&
                           oCoords[oCoords.size() - 2] == CLOSE_SUBPATH &&
-                          oCoords[oCoords.size() - 1] == CLOSE_SUBPATH))
+                          oCoords.back() == CLOSE_SUBPATH))
                     {
                         oCoords.push_back(CLOSE_SUBPATH);
                         oCoords.push_back(CLOSE_SUBPATH);
@@ -917,7 +917,7 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
 
                     if (EQUAL1(szToken, "m"))
                     {
-                        if (oCoords.size() != 0)
+                        if (!oCoords.empty())
                             bHasMultiPart = TRUE;
                         oCoords.push_back(NEW_SUBPATH);
                         oCoords.push_back(NEW_SUBPATH);
@@ -968,7 +968,7 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
                     oGS.ApplyMatrix(adfCoords);
                     oGS.ApplyMatrix(adfCoords + 2);
 
-                    if (oCoords.size() != 0)
+                    if (!oCoords.empty())
                         bHasMultiPart = TRUE;
                     oCoords.push_back(NEW_SUBPATH);
                     oCoords.push_back(NEW_SUBPATH);
@@ -1120,7 +1120,8 @@ OGRGeometry* PDFDataset::ParseContent(const char* pszContent,
                 if( bEmitFeature && poCurLayer != NULL)
                 {
                     OGRGeometry* poGeom = BuildGeometry(oCoords, bHasFoundFill, bHasMultiPart);
-                    bHasFoundFill = bHasMultiPart = FALSE;
+                    bHasFoundFill = FALSE;
+                    bHasMultiPart = FALSE;
                     if (poGeom)
                     {
                         OGRFeature* poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
diff --git a/frmts/pdf/pdfwritabledataset.cpp b/frmts/pdf/pdfwritabledataset.cpp
index d3ef602..7162c01 100644
--- a/frmts/pdf/pdfwritabledataset.cpp
+++ b/frmts/pdf/pdfwritabledataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  PDF driver
  * Purpose:  GDALDataset driver for PDF dataset (writable vector dataset)
@@ -31,19 +30,18 @@
 #include "pdfcreatecopy.h"
 #include "memdataset.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: pdfwritabledataset.cpp 35262 2016-08-31 12:48:10Z goatbar $");
 
 /************************************************************************/
 /*                      PDFWritableVectorDataset()                      */
 /************************************************************************/
 
-PDFWritableVectorDataset::PDFWritableVectorDataset()
-{
-    papszOptions = NULL;
-    nLayers = 0;
-    papoLayers = NULL;
-    bModified = FALSE;
-}
+PDFWritableVectorDataset::PDFWritableVectorDataset() :
+    papszOptions(NULL),
+    nLayers(0),
+    papoLayers(NULL),
+    bModified(FALSE)
+{}
 
 /************************************************************************/
 /*                      ~PDFWritableVectorDataset()                     */
@@ -54,7 +52,7 @@ PDFWritableVectorDataset::~PDFWritableVectorDataset()
     SyncToDisk();
 
     CSLDestroy(papszOptions);
-    for(int i=0;i<nLayers;i++)
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
     CPLFree( papoLayers );
 }
@@ -191,9 +189,25 @@ OGRErr PDFWritableVectorDataset::SyncToDisk()
     const char* pszGEO_ENCODING =
         CSLFetchNameValueDef(papszOptions, "GEO_ENCODING", "ISO32000");
 
-    double dfDPI = CPLAtof(CSLFetchNameValueDef(papszOptions, "DPI", "72"));
-    if (dfDPI < 72.0)
-        dfDPI = 72.0;
+    const char* pszDPI = CSLFetchNameValue(papszOptions, "DPI");
+    double dfDPI = DEFAULT_DPI;
+    if( pszDPI != NULL )
+    {
+        dfDPI = CPLAtof(pszDPI);
+        if (dfDPI < DEFAULT_DPI)
+            dfDPI = DEFAULT_DPI;
+    }
+    else
+    {
+        dfDPI = DEFAULT_DPI;
+    }
+
+    const char* pszWriteUserUnit = CSLFetchNameValue(papszOptions, "WRITE_USERUNIT");
+    bool bWriteUserUnit;
+    if( pszWriteUserUnit != NULL )
+        bWriteUserUnit = CPLTestBool( pszWriteUserUnit );
+    else
+        bWriteUserUnit = ( pszDPI == NULL );
 
     const char* pszNEATLINE = CSLFetchNameValue(papszOptions, "NEATLINE");
 
@@ -223,7 +237,8 @@ OGRErr PDFWritableVectorDataset::SyncToDisk()
 
     const char* pszOGRDisplayField = CSLFetchNameValue(papszOptions, "OGR_DISPLAY_FIELD");
     const char* pszOGRDisplayLayerNames = CSLFetchNameValue(papszOptions, "OGR_DISPLAY_LAYER_NAMES");
-    int bWriteOGRAttributes = CSLFetchBoolean(papszOptions, "OGR_WRITE_ATTRIBUTES", TRUE);
+    const bool bWriteOGRAttributes =
+        CPLFetchBool(papszOptions, "OGR_WRITE_ATTRIBUTES", true);
     const char* pszOGRLinkField = CSLFetchNameValue(papszOptions, "OGR_LINK_FIELD");
 
     const char* pszOffLayers = CSLFetchNameValue(papszOptions, "OFF_LAYERS");
@@ -286,6 +301,7 @@ OGRErr PDFWritableVectorDataset::SyncToDisk()
 
     oWriter.StartPage(poSrcDS,
                       dfDPI,
+                      bWriteUserUnit,
                       pszGEO_ENCODING,
                       pszNEATLINE,
                       &sMargins,
diff --git a/frmts/pds/GNUmakefile b/frmts/pds/GNUmakefile
index a7e08b3..9e41063 100644
--- a/frmts/pds/GNUmakefile
+++ b/frmts/pds/GNUmakefile
@@ -3,11 +3,11 @@ include ../../GDALmake.opt
 
 OBJ	=	pdsdataset.o isis2dataset.o isis3dataset.o vicardataset.o nasakeywordhandler.o vicarkeywordhandler.o
 
-CPPFLAGS	:=	-I../raw  $(CPPFLAGS)
+CPPFLAGS	:=	-I../raw -I../vrt -I../../ogr/ogrsf_frmts/geojson $(JSON_INCLUDE) $(CPPFLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
-$(O_OBJ):       nasakeywordhandler.h vicarkeywordhandler.h ../raw/rawdataset.h
+$(O_OBJ):       nasakeywordhandler.h vicarkeywordhandler.h ../raw/rawdataset.h ../vrt/vrtdataset.h
 
 clean:
 	rm -f *.o $(O_OBJ)
diff --git a/frmts/pds/frmt_isis3.html b/frmts/pds/frmt_isis3.html
index 95c028b..9eb3de8 100644
--- a/frmts/pds/frmt_isis3.html
+++ b/frmts/pds/frmt_isis3.html
@@ -9,25 +9,254 @@
 
 ISIS3 is a format used by the USGS Planetary Cartography group
 to store and distribute planetary imagery data.  GDAL provides
-read-only access to ISIS3 formatted imagery data.<p>
+read/creation/update access to ISIS3 formatted imagery data.<p>
 
 ISIS3 files often have the extension .cub, sometimes with an associated
 .lbl (label) file.  When a .lbl file exists it should be used as
-the dataset name rather than the .cub file.<p>
+the dataset name rather than the .cub file. Since GDAL 2.2, the driver also
+supports imagery stored in a separate GeoTIFF file.<p>
 
 In addition to support for most ISIS3 imagery configurations, this
 driver also reads georeferencing and coordinate system information
 as well as selected other header metadata.<p>
 
+Starting with GDAL 2.2, a mask band is attached to each source band. The
+value of this mask band is 0 when the pixel value is the NULL value or one of
+the low/high on-intstrument/processed saturation value, or 255 when the pixel
+value is valid.<p>
+
 Implementation of this driver was supported by the United States
 Geological Survey.<p>
 
 ISIS3 is part of a family of related formats including PDS and ISIS2.<p>
 
+<h2>Metadata</h2>
+
+<p>Starting with GDAL 2.2, the ISIS3 label can be retrieved as JSon-serialized
+content in the json:ISIS3 metadata domain.</p>
+
+<p>For example:</p>
+
+<pre>
+$ python
+from osgeo import gdal
+ds = gdal.Open('../autotest/gdrivers/data/isis3_detached.lbl')
+print(ds.GetMetadata_List('json:ISIS3')[0])
+{
+  "IsisCube":{
+    "_type":"object",
+    "Core":{
+      "_type":"object",
+      "StartByte":1,
+      "^Core":"isis3_detached.cub",
+      "Format":"BandSequential",
+      "Dimensions":{
+        "_type":"group",
+        "Samples":317,
+        "Lines":30,
+        "Bands":1
+      },
+      "Pixels":{
+        "_type":"group",
+        "Type":"UnsignedByte",
+        "ByteOrder":"Lsb",
+        "Base":0.000000,
+        "Multiplier":1.000000
+      }
+    },
+    "Instrument":{
+      "_type":"group",
+      "TargetName":"Mars"
+    },
+    "BandBin":{
+      "_type":"group",
+      "Center":1.000000,
+      "OriginalBand":1
+    },
+    "Mapping":{
+      "_type":"group",
+      "ProjectionName":"Equirectangular",
+      "CenterLongitude":184.412994,
+      "TargetName":"Mars",
+      "EquatorialRadius":{
+        "value":3396190.000000,
+        "unit":"meters"
+      },
+      "PolarRadius":{
+        "value":3376200.000000,
+        "unit":"meters"
+      },
+      "LatitudeType":"Planetographic",
+      "LongitudeDirection":"PositiveWest",
+      "LongitudeDomain":360,
+      "MinimumLatitude":-14.822815,
+      "MaximumLatitude":-14.727503,
+      "MinimumLongitude":184.441132,
+      "MaximumLongitude":184.496521,
+      "UpperLeftCornerX":-4766.964984,
+      "UpperLeftCornerY":-872623.628822,
+      "PixelResolution":{
+        "value":10.102500,
+        "unit":"meters\/pixel"
+      },
+      "Scale":{
+        "value":5864.945312,
+        "unit":"pixels\/degree"
+      },
+      "CenterLatitude":-15.147000,
+      "CenterLatitudeRadius":3394813.857978
+    }
+  },
+  "Label":{
+    "_type":"object",
+    "Bytes":65536,
+  },
+  "History":{
+    "_type":"object",
+    "Name":"IsisCube",
+    "StartByte":1,
+    "Bytes":957,
+    "^History":"r0200357_10m_Jul20_o_i3_detatched.History.IsisCube"
+  },
+  "OriginalLabel":{
+    "_type":"object",
+    "Name":"IsisCube",
+    "StartByte":1,
+    "Bytes":2482,
+    "^OriginalLabel":"r0200357_10m_Jul20_o_i3_detatched.OriginalLabel.IsisCube"
+  }
+}
+</pre>
+
+or
+<pre>
+$ gdalinfo -json ../autotest/gdrivers/data/isis3_detached.lbl -mdd all
+</pre>
+
+<p>On creation, a source template label can be passed to the SetMetadata()
+interface in the "json:ISIS3" metadata domain.</p>
+
+<h2>Creation support</h2>
+
+<p>Starting with GDAL 2.2, the ISIS3 driver supports updating imagery of
+existing datasets, creating new datasets through the CreateCopy() and Create()
+interfaces.</p>
+
+<p>When using CreateCopy(), gdal_translate or gdalwarp, an effort is made to
+preserve as much as possible of the original label when doing ISIS3 to ISIS3
+conversions. This can be disabled with the USE_SRC_LABEL=NO creation option.
+</p>
+
+<p>The available creation options are:</p>
+<ul>
+<li> <b>DATA_LOCATION</b>=LABEL/EXTERNAL/GEOTIFF. To specify the location of
+pixel data. The default value is LABEL, ie imagery immediately follows the
+label.
+If using EXTERNAL, the imagery is put in a raw file whose filename is the main
+filename with a .cub extension. If using GEOTIFF, the imagery is put in a
+separate GeoTIFF file, whose filename is the main filename with a .tif
+extension.</li>
+<li> <b>GEOTIFF_AS_REGULAR_EXTERNAL</b>=YES/NO. Whether the GeoTIFF file, if
+uncompressed, should be registered as a regular raw file. Defaults to YES, so
+as to maximimze the compatibility with earlier version of the ISIS3 driver.</li>
+<li> <b>GEOTIFF_OPTIONS</b>=string. Comma separated list of KEY=VALUE tuples to 
+forward to the GeoTIFF driver. e.g. GEOTIFF_OPTIONS=COMPRESS=LZW.</li>
+<li> <b>EXTERNAL_FILENAME</b>=filename. Override default external filename.
+Only for DATA_LOCATION=EXTERNAL or GEOTIFF.</li>
+<li> <b>TILED</b>=YES/NO. Whether the pixel data should be tiled. Default is NO
+(ie band sequential organization).</li>
+<li> <b>BLOCKXSIZE</b>=int_value. Tile width in pixels. Only used if TILED=YES.
+Defaults to 256.</li>
+<li> <b>BLOCKYSIZE</b>=int_value. Tile height in pixels. Only used if TILED=YES.
+Defaults to 256.</li>
+<li> <b>COMMENT</b>=string. Comment to add into the label.</li>
+<li> <b>LATITUDE_TYPE</b>=Planetocentric/Planetographic. Value of
+Mapping.LatitudeType. Defaults to Planetographic. If specified, and
+USE_SRC_MAPPING is in effect, this will be taken into account to override the
+source LatitudeType.</li>
+<li> <b>LONGITUDE_DIRECTION</b>=PositiveEast/PositiveWest.
+Value of Mapping.LongitudeDirection. Defaults to PositiveEast. If specified,
+and USE_SRC_MAPPING is in effect, this will be taken into account to override
+the source LongitudeDirection.</li>
+<li> <b>TARGET_NAME</b>=string.
+Value of Mapping.TargetName. This is normally deduced from the SRS datum name.
+If specified, and USE_SRC_MAPPING is in effect, this will be taken into account
+to override the source TargetName.</li>
+<li> <b>FORCE_360</b>=YES/NO. Whether to force longitudes in the [0, 360]
+range. Defaults to NO.</li>
+<li> <b>WRITE_BOUNDING_DEGREES</b>=YES/NO. Whether to write Min/MaximumLong/
+Latitude values. Defaults to YES.</li>
+<li> <b>BOUNDING_DEGREES</b>=min_long,min_lat,max_long,max_lat. Manually set
+bounding box (values will not be modified by LONGITUDE_DIRECTION or
+FORCE_360 options).</li>
+<li> <b>USE_SRC_LABEL</b>=YES/NO. Whether to use source label in ISIS3 to
+ISIS3 conversions. Defaults to YES.</li>
+<li> <b>USE_SRC_MAPPING</b>=YES/NO. Whether to use Mapping group from source
+label in ISIS3 to ISIS3 conversions. Defaults to NO (that is to say that the
+content of Mapping group will be created from new dataset geotransform and
+projection). Only used if USE_SRC_LABEL=YES</li>
+<li> <b>USE_SRC_HISTORY</b>=YES/NO. Whether to use the content pointed by the
+source History object in ISIS3 to ISIS3 conversions, and write it to the new
+dataset. Defaults to YES. Only used if USE_SRC_LABEL=YES. If ADD_GDAL_HISTORY
+and USE_SRC_HISTORY are set to YES (or unspecified), a new history section will
+be appended to the existing history.</li>
+<li> <b>ADD_GDAL_HISTORY</b>=YES/NO. Whether to add GDAL specific history in
+the content pointed by the History object in ISIS3 to ISIS3 conversions.
+Defaults to YES. Only used if USE_SRC_LABEL=YES. If ADD_GDAL_HISTORY
+and USE_SRC_HISTORY are set to YES (or unspecified), a new history section will
+be appended to the existing history. When ADD_GDAL_HISTORY=YES, the
+history is normally composed from current GDAL version, binary name and path,
+host name, user name and source and target filenames. It is possible to
+completely override it by specifying the GDAL_HISTORY option.</li>
+<li> <b>GDAL_HISTORY</b>=string. Manually defined GDAL history. Must be
+formatted as ISIS3 PDL. If not specified, it is automatically composed. Only
+used if ADD_GDAL_HISTORY=YES (or unspecified).</li>
+</ul>
+
+<h2>Examples</h2>
+
+How to create a copy of a source ISIS3 dataset to another ISIS3 dataset while
+modifying a parameter of IsisCube.Mapping group, by using GDAL Python :
+
+<pre>
+import json
+from osgeo import gdal
+
+src_ds = gdal.Open('in.lbl')
+# Load source label as JSon
+label = json.loads( src_ds.GetMetadata_List('json:ISIS3')[0] )
+# Update parameter
+label["IsisCube"]["Mapping"]["TargetName"] = "Moon"
+
+# Instantiate new raster
+# Note the USE_SRC_MAPPING=YES creation option, since we modified the
+# IsisCube.Mapping section, which otherwise is completely rewritten from
+# the geotransform and projection attached to the output dataset.
+out_ds = gdal.GetDriverByName('ISIS3').Create('out.lbl',
+                                              src_ds.RasterXSize,
+                                              src_ds.RasterYSize,
+                                              src_ds.RasterCount,
+                                              src_ds.GetRasterBand(1).DataType,
+                                              options = ['USE_SRC_MAPPING=YES'])
+# Attach the modified label
+out_ds.SetMetadata( [json.dumps(label)], 'json:ISIS3' )
+
+# Copy imagery (assumes that each band fits into memory, otherwise a line-by
+# line or block-per-block strategy would be more appropriate )
+for i in range(src_ds.RasterCount):
+    out_ds.GetRasterBand(1).WriteRaster( 0, 0,
+                                        src_ds.RasterXSize,
+                                        src_ds.RasterYSize,
+                                        src_ds.GetRasterBand(1).ReadRaster() )
+out_ds = None
+src_ds = None
+</pre>
+
+
 <h2>See Also:</h2>
 
 <ul>
-<li> Implemented as <tt>gdal/frmts/pds/isis2dataset.cpp</tt>.
+<li> Implemented as <tt>gdal/frmts/pds/isis3dataset.cpp</tt>.
 <li> <a href="frmt_pds.html">GDAL PDS Driver</a>
 <li> <a href="frmt_isis2.html">GDAL ISIS2 Driver</a>
 </ul>
diff --git a/frmts/pds/frmt_pds.html b/frmts/pds/frmt_pds.html
index 8eb7be7..fa7c462 100644
--- a/frmts/pds/frmt_pds.html
+++ b/frmts/pds/frmt_pds.html
@@ -5,7 +5,7 @@
 
 <body bgcolor="#ffffff">
 
-<h1>PDS -- Planetary Data System</h1>
+<h1>PDS -- Planetary Data System v3</h1>
 
 PDS is a format used primarily by NASA to store and distribute
 solar, lunar and planetary imagery data.  GDAL provides read-only
@@ -19,41 +19,46 @@ In addition to support for most PDS imagery configurations, this
 driver also reads georeferencing and coordinate system information
 as well as selected other header metadata.<p>
 
-Implementation of this driver was supported by the United States
-Geological Survey.<p>
+Implementation of this driver was supported by the United States Geological Survey.<p>
 
 <hr>
 
 Due to ambiguities in the PDS specification, the georeferencing of
 some products is subtly or grossly incorrect.  There are configuration
 variables which may be set for these products to correct the interpretation
-of the georeferencing.  Some details are available in
-<a href="http://trac.osgeo.org/gdal/ticket/3940">ticket #3940</a>.<p>
+of the georeferencing.  Some details are available in <a href="http://trac.osgeo.org/gdal/ticket/5941">ticket #5941</a> and <a href="http://trac.osgeo.org/gdal/ticket/3940">ticket #3940</a>. 
+Due to corrections made in <a href="http://trac.osgeo.org/gdal/ticket/5941">ticket #5941</a> it is recommended to GDAL 1.11.4 or higher.
 
-For example, the MOLA labels currently contain a one pixel offset. Once
-<a href="http://trac.osgeo.org/gdal/ticket/5941">ticket #5941</a> is applied (should be available post 1.11.3),
-which corrects the PDS offset defaults, here is how you can correctly read in
-a MOLA label using the --config options in the PDS reader.
 <p>
-$ gdalinfo  --config PDS_SampleProjOffset_Shift -0.5 --config PDS_LineProjOffset_Shift -0.5  mola.lbl
-<p>
-For LOLA global PDS files the center should be perfectly 0.0, 0.0 meters in Cartesian space.
 
-example conversion:<p>
-$ gdal_translate --config PDS_SampleProjOffset_Shift -0.5 --config PDS_LineProjOffset_Shift -0.5  mola.lbl out.tif
+As a test (for GDAL versions 1.11.4 and higher), download both the label and image for the lunar <a href="http://pds-geosciences.wustl.edu/missions/lro/lola.htm">LOLA DEM</a> (digital elevation file)
+<a href="http://pds-geosciences.wustl.edu/lro/lro-l-lola-3-rdr-v1/lrolol_1xxx/data/lola_gdr/cylindrical/img/ldem_4.lbl">LOLA PDS label</a> and 
+<a href="http://pds-geosciences.wustl.edu/lro/lro-l-lola-3-rdr-v1/lrolol_1xxx/data/lola_gdr/cylindrical/img/ldem_4.img">LOLA PDS v3 image</a>.
+  Using gdalinfo, the reported centered should be perfectly at 0.0, 0.0 meters in Cartesian space without any configuration options.<p>
+$ gdalinfo  ldem_4.lbl
 <p>
-example conversion and applying offset and multiplier values as defined in some PDS labels:<p>
-$ gdal_translate -ot Float32 -unscale  --config PDS_SampleProjOffset_Shift -0.5 --config PDS_LineProjOffset_Shift -0.5  mola.lbl out_32bit.tif
+Example conversion to GeoTiff:<p>
+$ gdal_translate ldem_4.lbl out_LOLA.tif
 <p>
-As a test, this lunar
-<a href="http://pds-geosciences.wustl.edu/lro/lro-l-lola-3-rdr-v1/lrolol_1xxx/data/lola_gdr/cylindrical/img/ldem_4.lbl">LOLA PDS label</a>
-should be perfectly centered at 0.0, 0.0 meters in Cartesian space without any configuration options. Remember you will need a GDAL version post 1.11.3.<p>
-$ gdalinfo  ldem_4.lbl
+Example conversion and applying offset and multiplier values as defined in some PDS labels:<p>
+$ gdal_translate -ot Float32 -unscale  ldem_4.lbl out_LOLA_32bit.tif
+<p>
+<hr>
+To show an example to correct an offset issue we can use the <a href="http://pds-geosciences.wustl.edu/missions/mgs/megdr.html">MOLA DEM</a> from the PDS. Download both the
+<a href="http://pds-geosciences.wustl.edu/mgs/mgs-m-mola-5-megdr-l3-v1/mgsl_300x/meg004/megt90n000cb.lbl">MOLA PDS label</a> and 
+<a href="http://pds-geosciences.wustl.edu/mgs/mgs-m-mola-5-megdr-l3-v1/mgsl_300x/meg004/megt90n000cb.img">MOLA PDS v3 image</a>.
+The MOLA labels currently contain a one pixel offset. To read this file in correctly using GDAL (versions 1.11.4 and higher) set these options.
 <p>
-To test the --config keyword above, this Mars <a href="http://pds-geosciences.wustl.edu/mgs/mgs-m-mola-5-megdr-l3-v1/mgsl_300x/meg004/megt90n000cb.lbl">MOLA PDS label</a>
-should be perfectly centered at 0.0, 0.0 meters in Cartesian space with the following configuration options. Remember you will need a GDAL version post 1.11.3.<p>
 $ gdalinfo  --config PDS_SampleProjOffset_Shift -0.5 --config PDS_LineProjOffset_Shift -0.5  megt90n000cb.lbl
 <p>
+Again with these optional parameters, the center should be perfectly 0.0, 0.0 meters in Cartesian space.
+
+<p>
+Example conversion for MOLA:<p>
+$ gdal_translate --config PDS_SampleProjOffset_Shift -0.5 --config PDS_LineProjOffset_Shift -0.5  megt90n000cb.lbl out_MOLA_4ppd.tif
+<p>
+Example conversion and applying offset and multiplier values as defined in some PDS labels:<p>
+$ gdal_translate -ot Float32 -unscale  --config PDS_SampleProjOffset_Shift -0.5 --config PDS_LineProjOffset_Shift -0.5  megt90n000cb.lbl out_MOLA_4ppd_32bit.tif
 
 <p>
 <hr>
diff --git a/frmts/pds/isis2dataset.cpp b/frmts/pds/isis2dataset.cpp
index c5cc84c..b373722 100644
--- a/frmts/pds/isis2dataset.cpp
+++ b/frmts/pds/isis2dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: isis2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ISIS Version 2 Driver
  * Purpose:  Implementation of ISIS2Dataset
@@ -47,17 +46,17 @@ static const int RECORD_SIZE = 512;
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: isis2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: isis2dataset.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*			ISISDataset	version2	                */
+/*                      ISISDataset     version2                        */
 /* ==================================================================== */
 /************************************************************************/
 
 class ISIS2Dataset : public RawDataset
 {
-    VSILFILE	*fpImage;	// image data file.
+    VSILFILE     *fpImage;      // image data file.
     CPLString    osExternalCube;
 
     NASAKeywordHandler  oKeywords;
@@ -82,12 +81,12 @@ class ISIS2Dataset : public RawDataset
 
 public:
     ISIS2Dataset();
-    ~ISIS2Dataset();
+    virtual ~ISIS2Dataset();
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef(void);
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef(void) override;
 
-    virtual char **GetFileList();
+    virtual char **GetFileList() override;
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
@@ -99,7 +98,7 @@ public:
     static int WriteRaster(CPLString osFilename, bool includeLabel, GUIntBig iRecord, GUIntBig iLabelRecords, GDALDataType eType, const char * pszInterleaving);
 
     static int WriteLabel(CPLString osFilename, CPLString osRasterFile, CPLString sObjectTag, unsigned int nXSize, unsigned int nYSize, unsigned int nBands, GDALDataType eType,
-    						GUIntBig iRecords, const char * pszInterleaving, GUIntBig & iLabelRecords, bool bRelaunch=false);
+                          GUIntBig iRecords, const char * pszInterleaving, GUIntBig & iLabelRecords, bool bRelaunch=false);
     static int WriteQUBE_Information(VSILFILE *fpLabel, unsigned int iLevel, unsigned int & nWritingBytes,
                                      unsigned int nXSize, unsigned int nYSize, unsigned int nBands, GDALDataType eType, const char * pszInterleaving);
 
@@ -145,7 +144,7 @@ char **ISIS2Dataset::GetFileList()
 {
     char **papszFileList = GDALPamDataset::GetFileList();
 
-    if( strlen(osExternalCube) > 0 )
+    if( !osExternalCube.empty() )
         papszFileList = CSLAddString( papszFileList, osExternalCube );
 
     return papszFileList;
@@ -158,7 +157,7 @@ char **ISIS2Dataset::GetFileList()
 const char *ISIS2Dataset::GetProjectionRef()
 
 {
-    if( strlen(osProjection) > 0 )
+    if( !osProjection.empty() )
         return osProjection;
 
     return GDALPamDataset::GetProjectionRef();
@@ -184,7 +183,6 @@ CPLErr ISIS2Dataset::GetGeoTransform( double * padfTransform )
 /*                              Identify()                              */
 /************************************************************************/
 
-
 int ISIS2Dataset::Identify( GDALOpenInfo * poOpenInfo )
 {
     if( poOpenInfo->pabyHeader == NULL )
@@ -649,7 +647,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    poDS->nBands = nBands;;
+    poDS->nBands = nBands;
     for( int i = 0; i < poDS->nBands; i++ )
     {
         RawRasterBand *poBand =
@@ -733,7 +731,7 @@ GDALDataset *ISIS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -789,8 +787,8 @@ void ISIS2Dataset::CleanString( CPLString &osInput )
 
 {
    if(  ( osInput.size() < 2 ) ||
-        ((osInput.at(0) != '"'   || osInput.at(osInput.size()-1) != '"' ) &&
-        ( osInput.at(0) != '\'' || osInput.at(osInput.size()-1) != '\'')) )
+        ((osInput.at(0) != '"'   || osInput.back() != '"' ) &&
+        ( osInput.at(0) != '\'' || osInput.back() != '\'')) )
         return;
 
     char *pszWrk = CPLStrdup(osInput.c_str() + 1);
@@ -921,7 +919,6 @@ GDALDataset *ISIS2Dataset::Create(const char* pszFilename,
     return reinterpret_cast<GDALDataset *>( GDALOpen( osOutFile, GA_Update ) );
 }
 
-
 /************************************************************************/
 /*                            WriteRaster()                             */
 /************************************************************************/
diff --git a/frmts/pds/isis3dataset.cpp b/frmts/pds/isis3dataset.cpp
index e7da2c2..714661f 100644
--- a/frmts/pds/isis3dataset.cpp
+++ b/frmts/pds/isis3dataset.cpp
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: isis3dataset.cpp 10646 2007-01-18 02:38:10Z warmerdam $
  *
  * Project:  ISIS Version 3 Driver
  * Purpose:  Implementation of ISIS3Dataset
  * Author:   Trent Hare (thare at usgs.gov)
  *           Frank Warmerdam (warmerdam at pobox.com)
+ *           Even Rouault (even.rouault at spatialys.com)
  *
  * NOTE: Original code authored by Trent and placed in the public domain as
  * per US government policy.  I have (within my rights) appropriated it and
@@ -12,7 +12,8 @@
  * Trents contribution.
  ******************************************************************************
  * Copyright (c) 2007, Frank Warmerdam <warmerdam at pobox.com>
- * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2009-2010, Even Rouault <even.rouault at spatialys.com>
+ * Copyright (c) 2017 Hobu Inc
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -33,36 +34,632 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-static const int NULL1 = 0;
-static const int NULL2 = -32768;
-//#define NULL3 0xFF7FFFFB //in hex
-//Same as ESRI_GRID_FLOAT_NO_DATA
-//#define NULL3 -340282346638528859811704183484516925440.0
-static const double NULL3 = -3.4028226550889044521e+38;
-
 #include "cpl_string.h"
+#include "cpl_time.h"
+#include "cpl_vsi_error.h"
 #include "gdal_frmts.h"
+#include "gdal_proxy.h"
 #include "nasakeywordhandler.h"
+#include "ogrgeojsonreader.h"
+#include "ogr_json_header.h"
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
+#include "vrtdataset.h"
+
+// For gethostname()
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+#include <unistd.h>
+#endif
+
+#include <algorithm>
+#include <map>
+#include <utility> // pair
+#include <vector>
+
+// Constants coming from ISIS3 source code
+// in isis/src/base/objs/SpecialPixel/SpecialPixel.h
+
+//There are several types of special pixels
+//   *   Isis::Null Pixel has no data available
+//   *   Isis::Lis Pixel was saturated on the instrument
+//   *   Isis::His Pixel was saturated on the instrument
+//   *   Isis::Lrs Pixel was saturated during a computation
+//   *   Isis::Hrs Pixel was saturated during a computation
+
+// 1-byte special pixel values
+const unsigned char NULL1           = 0;
+const unsigned char LOW_REPR_SAT1   = 0;
+const unsigned char LOW_INSTR_SAT1  = 0;
+const unsigned char HIGH_INSTR_SAT1 = 255;
+const unsigned char HIGH_REPR_SAT1  = 255;
+
+// 2-byte unsigned special pixel values
+const unsigned short NULLU2           = 0;
+const unsigned short LOW_REPR_SATU2   = 1;
+const unsigned short LOW_INSTR_SATU2  = 2;
+const unsigned short HIGH_INSTR_SATU2 = 65534;
+const unsigned short HIGH_REPR_SATU2  = 65535;
+
+// 2-byte signed special pixel values
+const short NULL2           = -32768;
+const short LOW_REPR_SAT2   = -32767;
+const short LOW_INSTR_SAT2  = -32766;
+const short HIGH_INSTR_SAT2 = -32765;
+const short HIGH_REPR_SAT2  = -32764;
+
+// Define 4-byte special pixel values for IEEE floating point
+const float NULL4           = -3.4028226550889045e+38f; // 0xFF7FFFFB;
+const float LOW_REPR_SAT4   = -3.4028228579130005e+38f; // 0xFF7FFFFC;
+const float LOW_INSTR_SAT4  = -3.4028230607370965e+38f; // 0xFF7FFFFD;
+const float HIGH_INSTR_SAT4 = -3.4028232635611926e+38f; // 0xFF7FFFFE;
+const float HIGH_REPR_SAT4  = -3.4028234663852886e+38f; // 0xFF7FFFFF;
+
+// Must be large enough to hold an integer
+static const char* const pszSTARTBYTE_PLACEHOLDER = "!*^STARTBYTE^*!";
+// Must be large enough to hold an integer
+static const char* const pszLABEL_BYTES_PLACEHOLDER = "!*^LABEL_BYTES^*!";
+// Must be large enough to hold an integer
+static const char* const pszHISTORY_STARTBYTE_PLACEHOLDER =
+                                                    "!*^HISTORY_STARTBYTE^*!";
+
+CPL_CVSID("$Id: isis3dataset.cpp 37708 2017-03-14 10:56:35Z rouault $");
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             CPLJsonObject                            */
+/* ==================================================================== */
+/************************************************************************/
+
+// This class is intended to be general purpose
+
+class CPLJsonObject
+{
+    public:
+        enum Type
+        {
+            UNINIT,
+            JSON_NULL,
+            INT,
+            BOOLEAN,
+            DOUBLE,
+            STRING,
+            OBJECT,
+            ARRAY
+        };
+
+    private:
+        static const CPLJsonObject m_gUninitObject;
+
+        Type m_eType;
+        // Maintain both a list and a map to keep insertion order
+        std::vector< std::pair< CPLString, CPLJsonObject* > > m_oList;
+        std::map< CPLString, int> m_oMap;
+        GIntBig m_nVal;
+        double m_dfVal;
+        CPLString m_osVal;
+
+        void add( json_object* poObj )
+        {
+            CPLAssert( m_eType == UNINIT || m_eType == ARRAY );
+            m_eType = ARRAY;
+            m_oList.push_back( std::pair<CPLString,CPLJsonObject*>(
+                                CPLString(), new CPLJsonObject(poObj)) );
+        }
+
+    public:
+
+        static const CPLJsonObject JSON_NULL_CST;
+
+        CPLJsonObject() : m_eType(UNINIT), m_nVal(0), m_dfVal(0) {}
+
+        ~CPLJsonObject()
+        {
+            clear();
+        }
+
+        CPLJsonObject(const CPLJsonObject& other) :
+            m_eType(other.m_eType),
+            m_oList(other.m_oList),
+            m_oMap(other.m_oMap),
+            m_nVal(other.m_nVal),
+            m_dfVal(other.m_dfVal),
+            m_osVal(other.m_osVal)
+        {
+            for(size_t i=0;i<m_oList.size();++i)
+                m_oList[i].second = new CPLJsonObject( *m_oList[i].second );
+        }
+
+        explicit CPLJsonObject(int nVal) :
+            m_eType(INT), m_nVal(nVal), m_dfVal(0.0) {}
+
+        explicit CPLJsonObject(GIntBig nVal) :
+            m_eType(INT), m_nVal(nVal), m_dfVal(0.0) {}
+
+        explicit CPLJsonObject(bool bVal) :
+            m_eType(BOOLEAN), m_nVal(bVal), m_dfVal(0.0) {}
+
+        explicit CPLJsonObject(double dfVal) :
+            m_eType(DOUBLE), m_nVal(0), m_dfVal(dfVal) {}
+
+        explicit CPLJsonObject(const char* pszVal) :
+            m_eType(STRING), m_nVal(0), m_dfVal(0.0), m_osVal(pszVal) {}
+
+        explicit CPLJsonObject(Type eType):
+            m_eType(eType), m_nVal(0), m_dfVal(0) {}
+
+        explicit CPLJsonObject(json_object* poObj):
+            m_eType(UNINIT), m_nVal(0), m_dfVal(0.0)
+        {
+            *this = poObj;
+        }
+
+        void clear()
+        {
+            if( m_eType != UNINIT )
+            {
+                m_eType = UNINIT;
+                for(size_t i=0;i<m_oList.size();++i)
+                    delete m_oList[i].second;
+                m_oList.clear();
+                m_oMap.clear();
+                m_nVal = 0;
+                m_dfVal = 0.0;
+                m_osVal.clear();
+            }
+        }
+
+        Type getType() const { return m_eType; }
+        bool getBool() const { return m_nVal == 1; }
+        GIntBig getInt() const { return m_nVal; }
+        double getDouble() const { return m_dfVal; }
+        const char* getString() const { return m_osVal.c_str(); }
+
+        json_object* asLibJsonObj() const
+        {
+            json_object* obj = NULL;
+            if( m_eType == INT )
+                obj = json_object_new_int64(m_nVal);
+            else if( m_eType == BOOLEAN )
+                obj = json_object_new_boolean( m_nVal == 1 );
+            else if( m_eType == DOUBLE )
+                obj = json_object_new_double(m_dfVal);
+            else if( m_eType == STRING )
+                obj = json_object_new_string(m_osVal);
+            else if( m_eType == OBJECT )
+            {
+                obj = json_object_new_object();
+                for( size_t i=0; i < m_oList.size(); ++i )
+                {
+                    json_object_object_add(obj,
+                                           m_oList[i].first.c_str(),
+                                           m_oList[i].second->asLibJsonObj());
+                }
+            }
+            else if( m_eType == ARRAY )
+            {
+                obj = json_object_new_array();
+                for( size_t i=0; i < m_oList.size(); ++i )
+                {
+                    json_object_array_add(obj,
+                                          m_oList[i].second->asLibJsonObj());
+                }
+            }
+            return obj;
+        }
+
+        // Non-const accessor. Creates then entry if needed
+        CPLJsonObject& operator[](const CPLString& osKey)
+        {
+            CPLAssert( m_eType == UNINIT || m_eType == OBJECT );
+            m_eType = OBJECT;
+            std::map<CPLString,int>::const_iterator oIter =
+                                                    m_oMap.find(osKey);
+            if( oIter != m_oMap.end() )
+                return *(m_oList[ oIter->second ].second);
+            m_oList.push_back( std::pair<CPLString,CPLJsonObject*>(
+                                                osKey, new CPLJsonObject()) );
+            m_oMap[osKey] = static_cast<int>(m_oList.size()) - 1;
+            return *(m_oList.back().second);
+        }
+
+        void insert(size_t nPos, const CPLString& osKey, const CPLJsonObject& obj )
+        {
+            CPLAssert( m_eType == OBJECT );
+            CPLAssert( nPos <= m_oList.size() );
+            del(osKey);
+            std::map<CPLString,int>::iterator oIter = m_oMap.begin();
+            for( ; oIter != m_oMap.end(); ++oIter )
+            {
+                if( oIter->second >= static_cast<int>(nPos) )
+                    oIter->second ++;
+            }
+            m_oList.insert( m_oList.begin() + nPos,
+                            std::pair<CPLString,CPLJsonObject*>(
+                                            osKey, new CPLJsonObject(obj)) );
+            m_oMap[osKey] = static_cast<int>(nPos);
+        }
+
+        bool has(const CPLString& osKey) const
+        {
+            CPLAssert( m_eType == OBJECT );
+            std::map<CPLString,int>::const_iterator oIter =
+                                                    m_oMap.find(osKey);
+            return oIter != m_oMap.end();
+        }
+
+        void del(const CPLString& osKey)
+        {
+            CPLAssert( m_eType == OBJECT );
+            std::map<CPLString,int>::iterator oIter = m_oMap.find(osKey);
+            if( oIter != m_oMap.end() )
+            {
+                const int nIdx = oIter->second;
+                delete m_oList[nIdx].second;
+                m_oList.erase( m_oList.begin() + nIdx );
+                m_oMap.erase(oIter);
+
+                oIter = m_oMap.begin();
+                for( ; oIter != m_oMap.end(); ++oIter )
+                {
+                    if( oIter->second > nIdx )
+                        oIter->second --;
+                }
+            }
+        }
+
+        const CPLJsonObject& operator[](const CPLString& osKey) const
+        {
+            CPLAssert( m_eType == OBJECT );
+            std::map<CPLString,int>::const_iterator oIter =
+                                                    m_oMap.find(osKey);
+            if( oIter != m_oMap.end() )
+                return *(m_oList[ oIter->second ].second);
+            return m_gUninitObject;
+        }
+
+        CPLJsonObject& operator[](int i)
+        {
+            CPLAssert( m_eType == ARRAY || m_eType == OBJECT );
+            CPLAssert( i >= 0 && static_cast<size_t>(i) < m_oList.size() );
+            return *(m_oList[i].second);
+        }
+
+        CPLJsonObject& operator[](size_t i)
+        {
+            CPLAssert( m_eType == ARRAY || m_eType == OBJECT );
+            CPLAssert( i < m_oList.size() );
+            return *(m_oList[i].second);
+        }
+
+        const CPLJsonObject& operator[](int i) const
+        {
+            CPLAssert( m_eType == ARRAY || m_eType == OBJECT );
+            CPLAssert( i >= 0 && static_cast<size_t>(i) < m_oList.size() );
+            return *(m_oList[i].second);
+        }
+
+        const CPLJsonObject& operator[](size_t i) const
+        {
+            CPLAssert( m_eType == ARRAY || m_eType == OBJECT );
+            CPLAssert( i < m_oList.size() );
+            return *(m_oList[i].second);
+        }
+
+        const CPLString& getKey(int i) const
+        {
+            CPLAssert( m_eType == OBJECT );
+            CPLAssert( i >= 0 && static_cast<size_t>(i) < m_oList.size() );
+            return m_oList[i].first;
+        }
+
+        const CPLString& getKey(size_t i) const
+        {
+            CPLAssert( m_eType == OBJECT );
+            CPLAssert( i < m_oList.size() );
+            return m_oList[i].first;
+        }
+
+        void add( const CPLJsonObject& newChild )
+        {
+            CPLAssert( m_eType == UNINIT || m_eType == ARRAY );
+            m_eType = ARRAY;
+            m_oList.push_back( std::pair<CPLString,CPLJsonObject*>(
+                                CPLString(), new CPLJsonObject(newChild)) );
+        }
+
+        size_t size() const
+        {
+            CPLAssert( m_eType == OBJECT || m_eType == ARRAY );
+            return m_oList.size();
+        }
+
+        CPLJsonObject& operator= (int nVal)
+        {
+            m_eType = INT;
+            m_nVal = nVal;
+            return *this;
+        }
+
+        CPLJsonObject& operator= (GIntBig nVal)
+        {
+            m_eType = INT;
+            m_nVal = nVal;
+            return *this;
+        }
+
+        CPLJsonObject& operator= (bool bVal)
+        {
+            m_eType = BOOLEAN;
+            m_nVal = bVal;
+            return *this;
+        }
+        CPLJsonObject& operator= (double dfVal)
+        {
+            m_eType = DOUBLE;
+            m_dfVal = dfVal;
+            return *this;
+        }
+
+        CPLJsonObject& operator= (const char* pszVal)
+        {
+            m_eType = STRING;
+            m_osVal = pszVal;
+            return *this;
+        }
+
+        CPLJsonObject& operator= (const CPLJsonObject& other)
+        {
+            if( &other != this )
+            {
+                clear();
+                m_eType = other.m_eType;
+                m_oList = other.m_oList;
+                m_oMap = other.m_oMap;
+                m_nVal = other.m_nVal;
+                m_dfVal = other.m_dfVal;
+                m_osVal = other.m_osVal;
+                for(size_t i=0;i<m_oList.size();++i)
+                    m_oList[i].second = new CPLJsonObject(*m_oList[i].second);
+            }
+            return *this;
+        }
+
+        CPLJsonObject& operator= (json_object* poObj)
+        {
+            clear();
+            if( poObj == NULL )
+            {
+                m_eType = JSON_NULL;
+                return *this;
+            }
+            int eType = json_object_get_type(poObj);
+            if( eType == json_type_boolean)
+            {
+                m_eType = BOOLEAN;
+                m_nVal = json_object_get_boolean(poObj);
+                return *this;
+            }
+            if( eType == json_type_int )
+            {
+                m_eType = INT;
+                m_nVal = json_object_get_int64(poObj);
+                return *this;
+            }
+            if( eType == json_type_double )
+            {
+                m_eType = DOUBLE;
+                m_dfVal = json_object_get_double(poObj);
+                return *this;
+            }
+            if( eType == json_type_string )
+            {
+                m_eType = STRING;
+                m_osVal = json_object_get_string(poObj);
+                return *this;
+            }
+            if( eType == json_type_object )
+            {
+                m_eType = OBJECT;
+                json_object_iter it;
+                it.key = NULL;
+                it.val = NULL;
+                it.entry = NULL;
+                json_object_object_foreachC( poObj, it )
+                {
+                    (*this)[it.key] = it.val;
+                }
+                return *this;
+            }
+            if( eType == json_type_array )
+            {
+                m_eType = ARRAY;
+                const int nLength = json_object_array_length(poObj);
+                for( int i = 0; i < nLength; i++ )
+                {
+                    add( json_object_array_get_idx(poObj, i) );
+                }
+                return *this;
+            }
+            CPLAssert(false);
+            return *this;
+        }
+
+        bool operator== (const CPLJsonObject& other) const
+        {
+            if( m_eType != other.m_eType )
+                return false;
+
+            if( m_eType == INT || m_eType == BOOLEAN )
+                return m_nVal == other.m_nVal;
+            if( m_eType == DOUBLE )
+                return m_dfVal == other.m_dfVal;
+            if( m_eType == STRING )
+                return m_osVal == other.m_osVal;
+            if( m_eType == OBJECT )
+            {
+                if( m_oList.size() != other.m_oList.size() )
+                    return false;
+                for(size_t i=0;i<m_oList.size();++i)
+                {
+                    if( *m_oList[i].second != other[m_oList[i].first] )
+                        return false;
+                }
+            }
+            if( m_eType == ARRAY )
+            {
+                if( m_oList.size() != other.m_oList.size() )
+                    return false;
+                for(size_t i=0;i<m_oList.size();++i)
+                {
+                    if( *m_oList[i].second != *other.m_oList[i].second )
+                        return false;
+                }
+            }
+            return true;
+        }
+
+        bool operator!= (const CPLJsonObject& other) const
+        {
+            return !((*this) == other);
+        }
+};
+
+const CPLJsonObject CPLJsonObject::m_gUninitObject;
+const CPLJsonObject CPLJsonObject::JSON_NULL_CST(CPLJsonObject::JSON_NULL);
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             ISISDataset                              */
+/* ==================================================================== */
+/************************************************************************/
 
-CPL_CVSID("$Id: isis3dataset.cpp 10646 2007-09-18 02:38:10Z xxxx $");
+class ISIS3Dataset : public RawDataset
+{
+    friend class ISIS3RawRasterBand;
+    friend class ISISTiledBand;
+    friend class ISIS3WrapperRasterBand;
+
+    class NonPixelSection
+    {
+        public:
+            CPLString    osSrcFilename;
+            CPLString    osDstFilename; // empty for same file
+            vsi_l_offset nSrcOffset;
+            vsi_l_offset nSize;
+            CPLString    osPlaceHolder; // empty if not same file
+    };
+
+    VSILFILE    *m_fpLabel;  // label file (only used for writing)
+    VSILFILE    *m_fpImage;  // image data file. May be == fpLabel
+    GDALDataset *m_poExternalDS; // external dataset (GeoTIFF)
+    bool         m_bGeoTIFFAsRegularExternal; // creation only
+    bool         m_bGeoTIFFInitDone; // creation only
+
+    CPLString    m_osExternalFilename;
+    bool         m_bIsLabelWritten; // creation only
+
+    bool         m_bIsTiled;
+    bool         m_bInitToNodata; // creation only
+
+    NASAKeywordHandler m_oKeywords;
+
+    bool        m_bGotTransform;
+    double      m_adfGeoTransform[6];
+
+    bool        m_bHasSrcNoData; // creation only
+    double      m_dfSrcNoData; // creation only
+
+    CPLString   m_osProjection;
+
+    // creation only variables
+    CPLString   m_osComment;
+    CPLString   m_osLatitudeType;
+    CPLString   m_osLongitudeDirection;
+    CPLString   m_osTargetName;
+    bool        m_bForce360;
+    bool        m_bWriteBoundingDegrees;
+    CPLString   m_osBoundingDegrees;
+
+    json_object  *m_poJSonLabel;
+    CPLString     m_osHistory; // creation only
+    bool          m_bUseSrcLabel; // creation only
+    bool          m_bUseSrcMapping; // creation only
+    bool          m_bUseSrcHistory; // creation only
+    bool          m_bAddGDALHistory; // creation only
+    CPLString     m_osGDALHistory; // creation only
+    std::vector<NonPixelSection> m_aoNonPixelSections; // creation only
+    json_object  *m_poSrcJSonLabel; // creation only
+    CPLStringList m_aosISIS3MD;
+    CPLStringList m_aosAdditionalFiles;
+    CPLString     m_osFromFilename; // creation only
+
+    const char *GetKeyword( const char *pszPath,
+                            const char *pszDefault = "");
+
+    double       FixLong( double dfLong );
+    void         BuildLabel();
+    void         BuildHistory();
+    void         WriteLabel();
+    void         InvalidateLabel();
+
+    static CPLString SerializeAsPDL( json_object* poObj );
+    static void SerializeAsPDL( VSILFILE* fp, json_object* poObj,
+                                int nDepth = 0 );
+
+public:
+    ISIS3Dataset();
+    virtual ~ISIS3Dataset();
+
+    virtual int CloseDependentDatasets() override;
+
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr SetGeoTransform( double * padfTransform ) override;
+
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr SetProjection( const char* pszProjection ) override;
+
+    virtual char **GetFileList() override;
 
-class ISIS3Dataset;
+    virtual char **GetMetadataDomainList() override;
+    virtual char **GetMetadata( const char* pszDomain = "" ) override;
+    virtual CPLErr SetMetadata( char** papszMD, const char* pszDomain = "" )
+                                                                     override;
+
+    static int          Identify( GDALOpenInfo * );
+    static GDALDataset *Open( GDALOpenInfo * );
+    static GDALDataset *Create( const char * pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType, char ** papszOptions );
+    static GDALDataset* CreateCopy( const char *pszFilename,
+                                       GDALDataset *poSrcDS,
+                                       int bStrict,
+                                       char ** papszOptions,
+                                       GDALProgressFunc pfnProgress,
+                                       void * pProgressData );
+};
 
 /************************************************************************/
 /* ==================================================================== */
-/*			       ISISTiledBand		                */
+/*                             ISISTiledBand                            */
 /* ==================================================================== */
 /************************************************************************/
 
 class ISISTiledBand : public GDALPamRasterBand
 {
-    VSILFILE      *fpVSIL;
-    GIntBig   nFirstTileOffset;
-    GIntBig   nXTileOffset;
-    GIntBig   nYTileOffset;
-    int       bNativeOrder;
+        friend class ISIS3Dataset;
+
+        VSILFILE *m_fpVSIL;
+        GIntBig   m_nFirstTileOffset;
+        GIntBig   m_nXTileOffset;
+        GIntBig   m_nYTileOffset;
+        int       m_bNativeOrder;
+        bool      m_bHasOffset;
+        bool      m_bHasScale;
+        double    m_dfOffset;
+        double    m_dfScale;
+        double    m_dfNoData;
 
   public:
 
@@ -73,9 +670,131 @@ class ISISTiledBand : public GDALPamRasterBand
                                GIntBig nXTileOffset,
                                GIntBig nYTileOffset,
                                int bNativeOrder );
-    virtual     ~ISISTiledBand() {}
+        virtual     ~ISISTiledBand() {}
+
+        virtual CPLErr          IReadBlock( int, int, void * ) override;
+        virtual CPLErr          IWriteBlock( int, int, void * ) override;
+
+        virtual double GetOffset( int *pbSuccess = NULL ) override;
+        virtual double GetScale( int *pbSuccess = NULL ) override;
+        virtual CPLErr SetOffset( double dfNewOffset ) override;
+        virtual CPLErr SetScale( double dfNewScale ) override;
+        virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+        virtual CPLErr SetNoDataValue( double dfNewNoData ) override;
+
+        void    SetMaskBand(GDALRasterBand* poMaskBand);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                        ISIS3RawRasterBand                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class ISIS3RawRasterBand: public RawRasterBand
+{
+        friend class ISIS3Dataset;
+
+        bool      m_bHasOffset;
+        bool      m_bHasScale;
+        double    m_dfOffset;
+        double    m_dfScale;
+        double    m_dfNoData;
+
+    public:
+                 ISIS3RawRasterBand( GDALDataset *l_poDS, int l_nBand,
+                                     void * l_fpRaw,
+                                     vsi_l_offset l_nImgOffset,
+                                     int l_nPixelOffset,
+                                     int l_nLineOffset,
+                                     GDALDataType l_eDataType,
+                                     int l_bNativeOrder,
+                                     int l_bIsVSIL = FALSE,
+                                     int l_bOwnsFP = FALSE );
+        virtual ~ISIS3RawRasterBand() {}
+
+        virtual CPLErr          IReadBlock( int, int, void * ) override;
+        virtual CPLErr          IWriteBlock( int, int, void * ) override;
+
+        virtual CPLErr  IRasterIO( GDALRWFlag, int, int, int, int,
+                                void *, int, int, GDALDataType,
+                                GSpacing nPixelSpace, GSpacing nLineSpace,
+                                GDALRasterIOExtraArg* psExtraArg ) override;
+
+        virtual double GetOffset( int *pbSuccess = NULL ) override;
+        virtual double GetScale( int *pbSuccess = NULL ) override;
+        virtual CPLErr SetOffset( double dfNewOffset ) override;
+        virtual CPLErr SetScale( double dfNewScale ) override;
+        virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+        virtual CPLErr SetNoDataValue( double dfNewNoData ) override;
+
+        void    SetMaskBand(GDALRasterBand* poMaskBand);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                         ISIS3WrapperRasterBand                       */
+/*                                                                      */
+/*      proxy for bands stored in other formats.                        */
+/* ==================================================================== */
+/************************************************************************/
+class ISIS3WrapperRasterBand : public GDALProxyRasterBand
+{
+        friend class ISIS3Dataset;
+
+        GDALRasterBand* m_poBaseBand;
+        bool      m_bHasOffset;
+        bool      m_bHasScale;
+        double    m_dfOffset;
+        double    m_dfScale;
+        double    m_dfNoData;
+
+  protected:
+    virtual GDALRasterBand* RefUnderlyingRasterBand() override
+                                                    { return m_poBaseBand; }
+
+  public:
+            explicit ISIS3WrapperRasterBand( GDALRasterBand* poBaseBandIn );
+            ~ISIS3WrapperRasterBand() {}
+
+        void    InitFile();
+
+        virtual CPLErr          IWriteBlock( int, int, void * ) override;
+
+        virtual CPLErr  IRasterIO( GDALRWFlag, int, int, int, int,
+                                void *, int, int, GDALDataType,
+                                GSpacing nPixelSpace, GSpacing nLineSpace,
+                                GDALRasterIOExtraArg* psExtraArg ) override;
+
+        virtual double GetOffset( int *pbSuccess = NULL ) override;
+        virtual double GetScale( int *pbSuccess = NULL ) override;
+        virtual CPLErr SetOffset( double dfNewOffset ) override;
+        virtual CPLErr SetScale( double dfNewScale ) override;
+        virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+        virtual CPLErr SetNoDataValue( double dfNewNoData ) override;
+
+        int             GetMaskFlags() override { return nMaskFlags; }
+        GDALRasterBand* GetMaskBand() override { return poMask; }
+        void            SetMaskBand(GDALRasterBand* poMaskBand);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                             ISISMaskBand                             */
+/* ==================================================================== */
+
+class ISISMaskBand : public GDALRasterBand
+{
+    GDALRasterBand  *m_poBaseBand;
+    void            *m_pBuffer;
+
+  public:
+
+                            explicit ISISMaskBand( GDALRasterBand* poBaseBand );
+                           ~ISISMaskBand();
+
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
 
-    virtual CPLErr          IReadBlock( int, int, void * );
 };
 
 /************************************************************************/
@@ -88,33 +807,39 @@ ISISTiledBand::ISISTiledBand( GDALDataset *poDSIn, VSILFILE *fpVSILIn,
                               GIntBig nFirstTileOffsetIn,
                               GIntBig nXTileOffsetIn,
                               GIntBig nYTileOffsetIn,
-                              int bNativeOrderIn )
-
+                              int bNativeOrderIn ) :
+    m_fpVSIL(fpVSILIn),
+    m_nFirstTileOffset(0),
+    m_nXTileOffset(nXTileOffsetIn),
+    m_nYTileOffset(nYTileOffsetIn),
+    m_bNativeOrder(bNativeOrderIn),
+    m_bHasOffset(false),
+    m_bHasScale(false),
+    m_dfOffset(0.0),
+    m_dfScale(1.0),
+    m_dfNoData(0.0)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->fpVSIL = fpVSILIn;
-    this->bNativeOrder = bNativeOrderIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     eDataType = eDT;
     nBlockXSize = nTileXSize;
     nBlockYSize = nTileYSize;
-    this->nXTileOffset = nXTileOffsetIn;
-    this->nYTileOffset = nYTileOffsetIn;
+    nRasterXSize = poDSIn->GetRasterXSize();
+    nRasterYSize = poDSIn->GetRasterYSize();
 
-    const int l_nBlocksPerRow =
-            (poDS->GetRasterXSize() + nTileXSize - 1) / nTileXSize;
-    const int l_nBlocksPerColumn =
-            (poDS->GetRasterYSize() + nTileYSize - 1) / nTileYSize;
+    const int l_nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+    const int l_nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
 
-    if( nXTileOffset == 0 && nYTileOffset == 0 )
+    if( m_nXTileOffset == 0 && m_nYTileOffset == 0 )
     {
-        nXTileOffset = static_cast<GIntBig>(GDALGetDataTypeSize(eDT)/8) * nTileXSize * nTileYSize;
-        nYTileOffset = nXTileOffset * l_nBlocksPerRow;
+        m_nXTileOffset =
+            static_cast<GIntBig>(GDALGetDataTypeSizeBytes(eDT)) *
+            nTileXSize * nTileYSize;
+        m_nYTileOffset = m_nXTileOffset * l_nBlocksPerRow;
     }
 
-    this->nFirstTileOffset = nFirstTileOffsetIn
-        + (nBand-1) * nYTileOffset * l_nBlocksPerColumn;
-
+    m_nFirstTileOffset = nFirstTileOffsetIn
+        + (nBand-1) * m_nYTileOffset * l_nBlocksPerColumn;
 }
 
 /************************************************************************/
@@ -124,12 +849,20 @@ ISISTiledBand::ISISTiledBand( GDALDataset *poDSIn, VSILFILE *fpVSILIn,
 CPLErr ISISTiledBand::IReadBlock( int nXBlock, int nYBlock, void *pImage )
 
 {
-    const GIntBig  nOffset = nFirstTileOffset +
-        nXBlock * nXTileOffset + nYBlock * nYTileOffset;
-    const size_t nBlockSize =
-        (GDALGetDataTypeSize(eDataType)/8) * nBlockXSize * nBlockYSize;
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_osExternalFilename.empty() )
+    {
+        if( !poGDS->m_bIsLabelWritten )
+            poGDS->WriteLabel();
+    }
 
-    if( VSIFSeekL( fpVSIL, nOffset, SEEK_SET ) != 0 )
+    const GIntBig  nOffset = m_nFirstTileOffset +
+        nXBlock * m_nXTileOffset + nYBlock * m_nYTileOffset;
+    const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
+    const size_t nBlockSize = static_cast<size_t>(nDTSize)
+                                            * nBlockXSize * nBlockYSize;
+
+    if( VSIFSeekL( m_fpVSIL, nOffset, SEEK_SET ) != 0 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to seek to offset %d to read tile %d,%d.",
@@ -137,7 +870,7 @@ CPLErr ISISTiledBand::IReadBlock( int nXBlock, int nYBlock, void *pImage )
         return CE_Failure;
     }
 
-    if( VSIFReadL( pImage, 1, nBlockSize, fpVSIL ) != nBlockSize )
+    if( VSIFReadL( pImage, 1, nBlockSize, m_fpVSIL ) != nBlockSize )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to read %d bytes for tile %d,%d.",
@@ -145,725 +878,3549 @@ CPLErr ISISTiledBand::IReadBlock( int nXBlock, int nYBlock, void *pImage )
         return CE_Failure;
     }
 
-    if( !bNativeOrder )
-        GDALSwapWords( pImage, GDALGetDataTypeSize(eDataType)/8,
+    if( !m_bNativeOrder && eDataType != GDT_Byte )
+        GDALSwapWords( pImage, nDTSize,
                        nBlockXSize*nBlockYSize,
-                       GDALGetDataTypeSize(eDataType)/8 );
+                       nDTSize );
 
     return CE_None;
 }
 
 /************************************************************************/
-/* ==================================================================== */
-/*			       ISISDataset		                */
-/* ==================================================================== */
+/*                           RemapNoDataT()                             */
 /************************************************************************/
 
-class ISIS3Dataset : public RawDataset
+template<class T> static void RemapNoDataT( T* pBuffer, int nItems,
+                                            T srcNoData, T dstNoData )
 {
-    VSILFILE	*fpImage;	// image data file.
+    for( int i = 0; i < nItems; i++ )
+    {
+        if( pBuffer[i] == srcNoData )
+            pBuffer[i] = dstNoData;
+    }
+}
 
-    CPLString   osExternalCube;
+/************************************************************************/
+/*                            RemapNoData()                             */
+/************************************************************************/
 
-    NASAKeywordHandler  oKeywords;
+static void RemapNoData( GDALDataType eDataType,
+                         void* pBuffer, int nItems, double dfSrcNoData,
+                         double dfDstNoData )
+{
+    if( eDataType == GDT_Byte )
+    {
+        RemapNoDataT( reinterpret_cast<GByte*>(pBuffer),
+                      nItems,
+                      static_cast<GByte>(dfSrcNoData),
+                      static_cast<GByte>(dfDstNoData) );
+    }
+    else if( eDataType == GDT_UInt16 )
+    {
+        RemapNoDataT( reinterpret_cast<GUInt16*>(pBuffer),
+                      nItems,
+                      static_cast<GUInt16>(dfSrcNoData),
+                      static_cast<GUInt16>(dfDstNoData) );
+    }
+    else if( eDataType == GDT_Int16)
+    {
+        RemapNoDataT( reinterpret_cast<GInt16*>(pBuffer),
+                      nItems,
+                      static_cast<GInt16>(dfSrcNoData),
+                      static_cast<GInt16>(dfDstNoData) );
+    }
+    else
+    {
+        CPLAssert( eDataType == GDT_Float32 );
+        RemapNoDataT( reinterpret_cast<float*>(pBuffer),
+                      nItems,
+                      static_cast<float>(dfSrcNoData),
+                      static_cast<float>(dfDstNoData) );
+    }
+}
 
-    int         bGotTransform;
-    double      adfGeoTransform[6];
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
 
-    CPLString   osProjection;
+CPLErr ISISTiledBand::IWriteBlock( int nXBlock, int nYBlock, void *pImage )
 
-    int parse_label(const char *file, char *keyword, char *value);
-    int strstrip(char instr[], char outstr[], int position);
+{
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_osExternalFilename.empty() )
+    {
+        if( !poGDS->m_bIsLabelWritten )
+            poGDS->WriteLabel();
+    }
 
-    CPLString   oTempResult;
+    if( poGDS->m_bHasSrcNoData && poGDS->m_dfSrcNoData != m_dfNoData )
+    {
+        RemapNoData( eDataType, pImage, nBlockXSize * nBlockYSize,
+                     poGDS->m_dfSrcNoData, m_dfNoData );
+    }
 
-    const char *GetKeyword( const char *pszPath,
-                            const char *pszDefault = "");
-    const char *GetKeywordSub( const char *pszPath,
-                               int iSubscript,
-                               const char *pszDefault = "");
+    const GIntBig  nOffset = m_nFirstTileOffset +
+        nXBlock * m_nXTileOffset + nYBlock * m_nYTileOffset;
+    const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
+    const size_t nBlockSize = static_cast<size_t>(nDTSize)
+                                            * nBlockXSize * nBlockYSize;
 
-public:
-    ISIS3Dataset();
-    ~ISIS3Dataset();
+    const int l_nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+    const int l_nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef(void);
+    // Pad partial blocks to nodata value
+    if( nXBlock == l_nBlocksPerRow - 1 && (nRasterXSize % nBlockXSize) != 0 )
+    {
+        GByte* pabyImage = static_cast<GByte*>(pImage);
+        int nXStart = nRasterXSize % nBlockXSize;
+        for( int iY = 0; iY < nBlockYSize; iY++ )
+        {
+            GDALCopyWords( &m_dfNoData, GDT_Float64, 0,
+                           pabyImage + (iY * nBlockXSize + nXStart) * nDTSize,
+                           eDataType, nDTSize,
+                           nBlockXSize - nXStart );
+        }
+    }
+    if( nYBlock == l_nBlocksPerColumn - 1 &&
+        (nRasterYSize % nBlockYSize) != 0 )
+    {
+        GByte* pabyImage = static_cast<GByte*>(pImage);
+        for( int iY = nRasterYSize % nBlockYSize; iY < nBlockYSize; iY++ )
+        {
+            GDALCopyWords( &m_dfNoData, GDT_Float64, 0,
+                           pabyImage + iY * nBlockXSize * nDTSize,
+                           eDataType, nDTSize,
+                           nBlockXSize );
+        }
+    }
 
-    virtual char **GetFileList();
+    if( VSIFSeekL( m_fpVSIL, nOffset, SEEK_SET ) != 0 )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to seek to offset %d to read tile %d,%d.",
+                  static_cast<int>( nOffset ), nXBlock, nYBlock );
+        return CE_Failure;
+    }
 
-    static int          Identify( GDALOpenInfo * );
-    static GDALDataset *Open( GDALOpenInfo * );
-    static GDALDataset *Create( const char * pszFilename,
-                                int nXSize, int nYSize, int nBands,
-                                GDALDataType eType, char ** papszParmList );
-};
+    if( !m_bNativeOrder && eDataType != GDT_Byte )
+        GDALSwapWords( pImage, nDTSize,
+                       nBlockXSize*nBlockYSize,
+                       nDTSize );
+
+    if( VSIFWriteL( pImage, 1, nBlockSize, m_fpVSIL ) != nBlockSize )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Failed to write %d bytes for tile %d,%d.",
+                  static_cast<int>( nBlockSize ), nXBlock, nYBlock );
+        return CE_Failure;
+    }
+
+    if( !m_bNativeOrder && eDataType != GDT_Byte )
+        GDALSwapWords( pImage, nDTSize,
+                       nBlockXSize*nBlockYSize,
+                       nDTSize );
 
+    return CE_None;
+}
 
 /************************************************************************/
-/*                            ISIS3Dataset()                            */
+/*                             SetMaskBand()                            */
 /************************************************************************/
 
-ISIS3Dataset::ISIS3Dataset() :
-    fpImage(NULL),
-    bGotTransform(FALSE)
+void ISISTiledBand::SetMaskBand(GDALRasterBand* poMaskBand)
 {
-    adfGeoTransform[0] = 0.0;
-    adfGeoTransform[1] = 1.0;
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[3] = 0.0;
-    adfGeoTransform[4] = 0.0;
-    adfGeoTransform[5] = 1.0;
+    bOwnMask = true;
+    poMask = poMaskBand;
+    nMaskFlags = 0;
 }
 
 /************************************************************************/
-/*                            ~ISIS3Dataset()                            */
+/*                              GetOffset()                             */
 /************************************************************************/
 
-ISIS3Dataset::~ISIS3Dataset()
-
+double ISISTiledBand::GetOffset( int *pbSuccess )
 {
-    FlushCache();
-    if( fpImage != NULL )
-        VSIFCloseL( fpImage );
+    if( pbSuccess )
+        *pbSuccess = m_bHasOffset;
+    return m_dfOffset;
 }
 
 /************************************************************************/
-/*                            GetFileList()                             */
+/*                              GetScale()                              */
 /************************************************************************/
 
-char **ISIS3Dataset::GetFileList()
-
+double ISISTiledBand::GetScale( int *pbSuccess )
 {
-    char **papszFileList = GDALPamDataset::GetFileList();
+    if( pbSuccess )
+        *pbSuccess = m_bHasScale;
+    return m_dfScale;
+}
 
-    if( strlen(osExternalCube) > 0 )
-        papszFileList = CSLAddString( papszFileList, osExternalCube );
+/************************************************************************/
+/*                              SetOffset()                             */
+/************************************************************************/
 
-    return papszFileList;
+CPLErr ISISTiledBand::SetOffset( double dfNewOffset )
+{
+    m_dfOffset = dfNewOffset;
+    m_bHasOffset = true;
+    return CE_None;
 }
 
 /************************************************************************/
-/*                          GetProjectionRef()                          */
+/*                              SetScale()                              */
 /************************************************************************/
 
-const char *ISIS3Dataset::GetProjectionRef()
-
+CPLErr ISISTiledBand::SetScale( double dfNewScale )
 {
-    if( strlen(osProjection) > 0 )
-        return osProjection;
-
-    return GDALPamDataset::GetProjectionRef();
+    m_dfScale = dfNewScale;
+    m_bHasScale = true;
+    return CE_None;
 }
 
 /************************************************************************/
-/*                          GetGeoTransform()                           */
+/*                           GetNoDataValue()                           */
 /************************************************************************/
 
-CPLErr ISIS3Dataset::GetGeoTransform( double * padfTransform )
-
+double ISISTiledBand::GetNoDataValue( int *pbSuccess )
 {
-    if( bGotTransform )
-    {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
-        return CE_None;
-    }
-
-    return GDALPamDataset::GetGeoTransform( padfTransform );
+    if( pbSuccess )
+        *pbSuccess = true;
+    return m_dfNoData;
 }
 
 /************************************************************************/
-/*                              Identify()                              */
+/*                           SetNoDataValue()                           */
 /************************************************************************/
-int ISIS3Dataset::Identify( GDALOpenInfo * poOpenInfo )
 
+CPLErr ISISTiledBand::SetNoDataValue( double dfNewNoData )
 {
-    if( poOpenInfo->pabyHeader != NULL
-        && strstr((const char *)poOpenInfo->pabyHeader,"IsisCube") != NULL )
-        return TRUE;
-
-    return FALSE;
+    m_dfNoData = dfNewNoData;
+    return CE_None;
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                       ISIS3RawRasterBand()                           */
 /************************************************************************/
 
-GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
+ISIS3RawRasterBand::ISIS3RawRasterBand( GDALDataset *l_poDS, int l_nBand,
+                                        void * l_fpRaw,
+                                        vsi_l_offset l_nImgOffset,
+                                        int l_nPixelOffset,
+                                        int l_nLineOffset,
+                                        GDALDataType l_eDataType,
+                                        int l_bNativeOrder,
+                                        int l_bIsVSIL, int l_bOwnsFP )
+    : RawRasterBand(l_poDS, l_nBand, l_fpRaw, l_nImgOffset, l_nPixelOffset,
+                    l_nLineOffset,
+                    l_eDataType, l_bNativeOrder, l_bIsVSIL, l_bOwnsFP),
+    m_bHasOffset(false),
+    m_bHasScale(false),
+    m_dfOffset(0.0),
+    m_dfScale(1.0),
+    m_dfNoData(0.0)
 {
-/* -------------------------------------------------------------------- */
-/*      Does this look like a CUBE dataset?                             */
-/* -------------------------------------------------------------------- */
-    if( !Identify( poOpenInfo ) )
-        return NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Open the file using the large file API.                         */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fpQube = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+}
 
-    if( fpQube == NULL )
-        return NULL;
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
 
-    ISIS3Dataset *poDS = new ISIS3Dataset();
+CPLErr ISIS3RawRasterBand::IReadBlock( int nXBlock, int nYBlock, void *pImage )
 
-    if( ! poDS->oKeywords.Ingest( fpQube, 0 ) )
+{
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_osExternalFilename.empty() )
     {
-        VSIFCloseL( fpQube );
-        delete poDS;
-        return NULL;
+        if( !poGDS->m_bIsLabelWritten )
+            poGDS->WriteLabel();
     }
+    return RawRasterBand::IReadBlock( nXBlock, nYBlock, pImage );
+}
 
-    VSIFCloseL( fpQube );
-
-/* -------------------------------------------------------------------- */
-/* Assume user is pointing to label (i.e. .lbl) file for detached option */
-/* -------------------------------------------------------------------- */
-    //  Image can be inline or detached and point to an image name
-    //  the Format can be Tiled or Raw
-    //  Object = Core
-    //      StartByte   = 65537
-    //      Format      = Tile
-    //      TileSamples = 128
-    //      TileLines   = 128
-    //OR-----
-    //  Object = Core
-    //      StartByte = 1
-    //      ^Core     = r0200357_detatched.cub
-    //      Format    = BandSequential
-    //OR-----
-    //  Object = Core
-    //      StartByte = 1
-    //      ^Core     = r0200357_detached_tiled.cub
-    //      Format      = Tile
-    //      TileSamples = 128
-    //      TileLines   = 128
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
 
-/* -------------------------------------------------------------------- */
-/*      What file contains the actual data?                             */
-/* -------------------------------------------------------------------- */
-    const char *pszCore = poDS->GetKeyword( "IsisCube.Core.^Core" );
-    CPLString osQubeFile;
+CPLErr ISIS3RawRasterBand::IWriteBlock( int nXBlock, int nYBlock,
+                                        void *pImage )
 
-    if( EQUAL(pszCore,"") )
-        osQubeFile = poOpenInfo->pszFilename;
-    else
+{
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_osExternalFilename.empty() )
     {
-        CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
-        osQubeFile = CPLFormFilename( osPath, pszCore, NULL );
-        poDS->osExternalCube = osQubeFile;
+        if( !poGDS->m_bIsLabelWritten )
+            poGDS->WriteLabel();
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check if file an ISIS3 header file?  Read a few lines of text   */
-/*      searching for something starting with nrows or ncols.           */
-/* -------------------------------------------------------------------- */
+    if( poGDS->m_bHasSrcNoData && poGDS->m_dfSrcNoData != m_dfNoData )
+    {
+        RemapNoData( eDataType, pImage, nBlockXSize * nBlockYSize,
+                     poGDS->m_dfSrcNoData, m_dfNoData );
+    }
 
-    /*************   Skipbytes     *****************************/
-    const int nSkipBytes = atoi(poDS->GetKeyword("IsisCube.Core.StartByte","")) - 1;
+    return RawRasterBand::IWriteBlock( nXBlock, nYBlock, pImage );
+}
 
-    /*******   Grab format type (BandSequential, Tiled)  *******/
-    const char *value = poDS->GetKeyword( "IsisCube.Core.Format", "" );
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
 
-    char szLayout[32] = "BandSequential";
-    int tileSizeX = 0;
-    int tileSizeY = 0;
+CPLErr ISIS3RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
+                                 int nXOff, int nYOff, int nXSize, int nYSize,
+                                 void * pData, int nBufXSize, int nBufYSize,
+                                 GDALDataType eBufType,
+                                 GSpacing nPixelSpace, GSpacing nLineSpace,
+                                 GDALRasterIOExtraArg* psExtraArg )
 
-    if (EQUAL(value,"Tile") )  { //Todo
-        strcpy(szLayout,"Tiled");
-       /******* Get Tile Sizes *********/
-       tileSizeX = atoi(poDS->GetKeyword("IsisCube.Core.TileSamples",""));
-       tileSizeY = atoi(poDS->GetKeyword("IsisCube.Core.TileLines",""));
-       if (tileSizeX <= 0 || tileSizeY <= 0)
-       {
-           CPLError( CE_Failure, CPLE_OpenFailed, "Wrong tile dimensions : %d x %d",
-                     tileSizeX, tileSizeY);
-           delete poDS;
-           return NULL;
-       }
+{
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_osExternalFilename.empty() )
+    {
+        if( !poGDS->m_bIsLabelWritten )
+            poGDS->WriteLabel();
     }
-    else if (EQUAL(value,"BandSequential") )
-        strcpy(szLayout,"BSQ");
-    else {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "%s layout not supported. Abort\n\n", value);
-        delete poDS;
-        return NULL;
+    if( eRWFlag == GF_Write && 
+        poGDS->m_bHasSrcNoData && poGDS->m_dfSrcNoData != m_dfNoData )
+    {
+        const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
+        if( eBufType == eDataType && nPixelSpace == nDTSize &&
+            nLineSpace == nPixelSpace * nBufXSize )
+        {
+            RemapNoData( eDataType, pData, nBufXSize * nBufYSize,
+                         poGDS->m_dfSrcNoData, m_dfNoData );
+        }
+        else
+        {
+            const GByte* pabySrc = reinterpret_cast<GByte*>(pData);
+            GByte* pabyTemp = reinterpret_cast<GByte*>(
+                VSI_MALLOC3_VERBOSE(nDTSize, nBufXSize, nBufYSize));
+            for( int i = 0; i < nBufYSize; i++ )
+            {
+                GDALCopyWords( pabySrc + i * nLineSpace, eBufType,
+                               static_cast<int>(nPixelSpace),
+                               pabyTemp + i * nBufXSize * nDTSize,
+                               eDataType, nDTSize,
+                               nBufXSize );
+            }
+            RemapNoData( eDataType, pabyTemp, nBufXSize * nBufYSize,
+                         poGDS->m_dfSrcNoData, m_dfNoData );
+            CPLErr eErr = RawRasterBand::IRasterIO( eRWFlag,
+                                     nXOff, nYOff, nXSize, nYSize,
+                                     pabyTemp, nBufXSize, nBufYSize,
+                                     eDataType,
+                                     nDTSize, nDTSize*nBufXSize,
+                                     psExtraArg );
+            VSIFree(pabyTemp);
+            return eErr;
+        }
     }
+    return RawRasterBand::IRasterIO( eRWFlag,
+                                     nXOff, nYOff, nXSize, nYSize,
+                                     pData, nBufXSize, nBufYSize,
+                                     eBufType,
+                                     nPixelSpace, nLineSpace,
+                                     psExtraArg );
+}
 
-    /***********   Grab samples lines band ************/
-    const int nCols = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Samples",""));
-    const int nRows = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Lines",""));
-    const int nBands = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Bands",""));
+/************************************************************************/
+/*                             SetMaskBand()                            */
+/************************************************************************/
 
-    /****** Grab format type - ISIS3 only supports 8,U16,S16,32 *****/
-    GDALDataType eDataType = GDT_Byte;
-    double dfNoData = 0.0;
-    bool bNoDataSet = false;
+void ISIS3RawRasterBand::SetMaskBand(GDALRasterBand* poMaskBand)
+{
+    bOwnMask = true;
+    poMask = poMaskBand;
+    nMaskFlags = 0;
+}
 
-    const char *itype = poDS->GetKeyword( "IsisCube.Core.Pixels.Type" );
-    if (EQUAL(itype,"UnsignedByte") ) {
-        eDataType = GDT_Byte;
-        dfNoData = NULL1;
-        bNoDataSet = true;
-    }
-    else if (EQUAL(itype,"UnsignedWord") ) {
-        eDataType = GDT_UInt16;
-        dfNoData = NULL1;
-        bNoDataSet = true;
-    }
-    else if (EQUAL(itype,"SignedWord") ) {
-        eDataType = GDT_Int16;
-        dfNoData = NULL2;
-        bNoDataSet = true;
-    }
-    else if (EQUAL(itype,"Real") || EQUAL(value,"") ) {
-        eDataType = GDT_Float32;
-        dfNoData = NULL3;
-        bNoDataSet = true;
-    }
-    else {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "%s layout type not supported. Abort\n\n", itype);
-        delete poDS;
-        return NULL;
-    }
+/************************************************************************/
+/*                              GetOffset()                             */
+/************************************************************************/
 
-    /***********   Grab samples lines band ************/
-    char chByteOrder = 'M';  //default to MSB
+double ISIS3RawRasterBand::GetOffset( int *pbSuccess )
+{
+    if( pbSuccess )
+        *pbSuccess = m_bHasOffset;
+    return m_dfOffset;
+}
 
-    value = poDS->GetKeyword( "IsisCube.Core.Pixels.ByteOrder");
-    if (EQUAL(value,"Lsb"))
-        chByteOrder = 'I';
+/************************************************************************/
+/*                              GetScale()                              */
+/************************************************************************/
 
-    /***********   Grab Cellsize ************/
-    double dfXDim = 1.0;
-    double dfYDim = 1.0;
+double ISIS3RawRasterBand::GetScale( int *pbSuccess )
+{
+    if( pbSuccess )
+        *pbSuccess = m_bHasScale;
+    return m_dfScale;
+}
 
-    value = poDS->GetKeyword("IsisCube.Mapping.PixelResolution");
-    if (strlen(value) > 0 ) {
-        dfXDim = CPLAtof(value); /* values are in meters */
-        dfYDim = -CPLAtof(value);
-    }
+/************************************************************************/
+/*                              SetOffset()                             */
+/************************************************************************/
 
-    /***********   Grab UpperLeftCornerY ************/
-    double dfULYMap = 0.5;
+CPLErr ISIS3RawRasterBand::SetOffset( double dfNewOffset )
+{
+    m_dfOffset = dfNewOffset;
+    m_bHasOffset = true;
+    return CE_None;
+}
 
-    value = poDS->GetKeyword("IsisCube.Mapping.UpperLeftCornerY");
-    if (strlen(value) > 0) {
-        dfULYMap = CPLAtof(value);
-    }
+/************************************************************************/
+/*                              SetScale()                              */
+/************************************************************************/
 
-    /***********   Grab UpperLeftCornerX ************/
-    double dfULXMap = 0.5;
+CPLErr ISIS3RawRasterBand::SetScale( double dfNewScale )
+{
+    m_dfScale = dfNewScale;
+    m_bHasScale = true;
+    return CE_None;
+}
 
-    value = poDS->GetKeyword("IsisCube.Mapping.UpperLeftCornerX");
-    if( strlen(value) > 0 ) {
-        dfULXMap = CPLAtof(value);
-    }
+/************************************************************************/
+/*                           GetNoDataValue()                           */
+/************************************************************************/
 
-    /***********  Grab TARGET_NAME  ************/
-    /**** This is the planets name i.e. Mars ***/
-    const char *target_name = poDS->GetKeyword("IsisCube.Mapping.TargetName");
+double ISIS3RawRasterBand::GetNoDataValue( int *pbSuccess )
+{
+    if( pbSuccess )
+        *pbSuccess = true;
+    return m_dfNoData;
+}
 
-    /***********   Grab MAP_PROJECTION_TYPE ************/
-     const char *map_proj_name =
-        poDS->GetKeyword( "IsisCube.Mapping.ProjectionName");
+/************************************************************************/
+/*                           SetNoDataValue()                           */
+/************************************************************************/
 
-    /***********   Grab SEMI-MAJOR ************/
-    const double semi_major =
-        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.EquatorialRadius"));
+CPLErr ISIS3RawRasterBand::SetNoDataValue( double dfNewNoData )
+{
+    m_dfNoData = dfNewNoData;
+    return CE_None;
+}
 
-    /***********   Grab semi-minor ************/
-    const double semi_minor =
-        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.PolarRadius"));
+/************************************************************************/
+/*                        ISIS3WrapperRasterBand()                      */
+/************************************************************************/
 
-    /***********   Grab CENTER_LAT ************/
-    const double center_lat =
-        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.CenterLatitude"));
+ISIS3WrapperRasterBand::ISIS3WrapperRasterBand( GDALRasterBand* poBaseBandIn ) :
+    m_poBaseBand(poBaseBandIn),
+    m_bHasOffset(false),
+    m_bHasScale(false),
+    m_dfOffset(0.0),
+    m_dfScale(1.0),
+    m_dfNoData(0.0)
+{
+    eDataType = m_poBaseBand->GetRasterDataType();
+    m_poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+}
 
-    /***********   Grab CENTER_LON ************/
-    const double center_lon =
-        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.CenterLongitude"));
+/************************************************************************/
+/*                             SetMaskBand()                            */
+/************************************************************************/
 
-    /***********   Grab 1st std parallel ************/
-    const double first_std_parallel =
-        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.FirstStandardParallel"));
+void ISIS3WrapperRasterBand::SetMaskBand(GDALRasterBand* poMaskBand)
+{
+    bOwnMask = true;
+    poMask = poMaskBand;
+    nMaskFlags = 0;
+}
 
-    /***********   Grab 2nd std parallel ************/
-    const double second_std_parallel =
-        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.SecondStandardParallel"));
+/************************************************************************/
+/*                              GetOffset()                             */
+/************************************************************************/
 
-    /***********   Grab scaleFactor ************/
-    const double scaleFactor =
-        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.scaleFactor", "1.0"));
+double ISIS3WrapperRasterBand::GetOffset( int *pbSuccess )
+{
+    if( pbSuccess )
+        *pbSuccess = m_bHasOffset;
+    return m_dfOffset;
+}
 
-    /*** grab      LatitudeType = Planetographic ****/
-    // Need to further study how ocentric/ographic will effect the gdal library
-    // So far we will use this fact to define a sphere or ellipse for some
-    // projections
+/************************************************************************/
+/*                              GetScale()                              */
+/************************************************************************/
 
-    // Frank - may need to talk this over
-    value = poDS->GetKeyword("IsisCube.Mapping.LatitudeType");
-    bool bIsGeographic = true;
-    if (EQUAL( value, "Planetocentric" ))
-        bIsGeographic = false;
+double ISIS3WrapperRasterBand::GetScale( int *pbSuccess )
+{
+    if( pbSuccess )
+        *pbSuccess = m_bHasScale;
+    return m_dfScale;
+}
 
-    //Set oSRS projection and parameters
-    //############################################################
-    //ISIS3 Projection types
-    //  Equirectangular
-    //  LambertConformal
-    //  Mercator
-    //  ObliqueCylindrical //Todo
-    //  Orthographic
-    //  PolarStereographic
-    //  SimpleCylindrical
-    //  Sinusoidal
-    //  TransverseMercator
+/************************************************************************/
+/*                              SetOffset()                             */
+/************************************************************************/
 
-#ifdef DEBUG
+CPLErr ISIS3WrapperRasterBand::SetOffset( double dfNewOffset )
+{
+    m_dfOffset = dfNewOffset;
+    m_bHasOffset = true;
+
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_poExternalDS && eAccess == GA_Update )
+        poGDS->m_poExternalDS->GetRasterBand(nBand)->SetOffset(dfNewOffset);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                              SetScale()                              */
+/************************************************************************/
+
+CPLErr ISIS3WrapperRasterBand::SetScale( double dfNewScale )
+{
+    m_dfScale = dfNewScale;
+    m_bHasScale = true;
+
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_poExternalDS && eAccess == GA_Update )
+        poGDS->m_poExternalDS->GetRasterBand(nBand)->SetScale(dfNewScale);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           GetNoDataValue()                           */
+/************************************************************************/
+
+double ISIS3WrapperRasterBand::GetNoDataValue( int *pbSuccess )
+{
+    if( pbSuccess )
+        *pbSuccess = true;
+    return m_dfNoData;
+}
+
+/************************************************************************/
+/*                           SetNoDataValue()                           */
+/************************************************************************/
+
+CPLErr ISIS3WrapperRasterBand::SetNoDataValue( double dfNewNoData )
+{
+    m_dfNoData = dfNewNoData;
+
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_poExternalDS && eAccess == GA_Update )
+        poGDS->m_poExternalDS->GetRasterBand(nBand)->SetNoDataValue(dfNewNoData);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                              InitFile()                              */
+/************************************************************************/
+
+void ISIS3WrapperRasterBand::InitFile()
+{
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_bGeoTIFFAsRegularExternal && !poGDS->m_bGeoTIFFInitDone )
+    {
+        poGDS->m_bGeoTIFFInitDone = true;
+
+        const int nBands = poGDS->GetRasterCount();
+        // We need to make sure that blocks are written in the right order
+        for( int i = 0; i < nBands; i++ )
+        {
+            poGDS->m_poExternalDS->GetRasterBand(i+1)->Fill(m_dfNoData);
+        }
+        poGDS->m_poExternalDS->FlushCache();
+
+        // Check that blocks are effectively written in expected order.
+        const int nBlockSizeBytes = nBlockXSize * nBlockYSize *
+                                        GDALGetDataTypeSizeBytes(eDataType);
+
+        GIntBig nLastOffset = 0;
+        bool bGoOn = true;
+        const int l_nBlocksPerRow = DIV_ROUND_UP(nRasterXSize, nBlockXSize);
+        const int l_nBlocksPerColumn = DIV_ROUND_UP(nRasterYSize, nBlockYSize);
+        for( int i = 0; i < nBands && bGoOn; i++ )
+        {
+            for( int y = 0; y < l_nBlocksPerColumn && bGoOn; y++ )
+            {
+                for( int x = 0; x < l_nBlocksPerRow && bGoOn; x++ )
+                {
+                    const char* pszBlockOffset =  poGDS->m_poExternalDS->
+                        GetRasterBand(i+1)->GetMetadataItem(
+                            CPLSPrintf("BLOCK_OFFSET_%d_%d", x, y), "TIFF");
+                    if( pszBlockOffset )
+                    {
+                        GIntBig nOffset = CPLAtoGIntBig(pszBlockOffset);
+                        if( i != 0 || x != 0 || y != 0 )
+                        {
+                            if( nOffset != nLastOffset + nBlockSizeBytes )
+                            {
+                                CPLError(CE_Warning, CPLE_AppDefined,
+                                         "Block %d,%d band %d not at expected "
+                                         "offset",
+                                         x, y, i+1);
+                                bGoOn = false;
+                                poGDS->m_bGeoTIFFAsRegularExternal = false;
+                            }
+                        }
+                        nLastOffset = nOffset;
+                    }
+                    else
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                         "Block %d,%d band %d not at expected "
+                                         "offset",
+                                         x, y, i+1);
+                        bGoOn = false;
+                        poGDS->m_bGeoTIFFAsRegularExternal = false;
+                    }
+                }
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                             IWriteBlock()                             */
+/************************************************************************/
+
+CPLErr ISIS3WrapperRasterBand::IWriteBlock( int nXBlock, int nYBlock,
+                                            void *pImage )
+
+{
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( poGDS->m_bHasSrcNoData && poGDS->m_dfSrcNoData != m_dfNoData )
+    {
+        RemapNoData( eDataType, pImage, nBlockXSize * nBlockYSize,
+                     poGDS->m_dfSrcNoData, m_dfNoData );
+    }
+    if( poGDS->m_bGeoTIFFAsRegularExternal && poGDS->m_bGeoTIFFInitDone )
+    {
+        InitFile();
+    }
+
+    return GDALProxyRasterBand::IWriteBlock( nXBlock, nYBlock, pImage );
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr ISIS3WrapperRasterBand::IRasterIO( GDALRWFlag eRWFlag,
+                                 int nXOff, int nYOff, int nXSize, int nYSize,
+                                 void * pData, int nBufXSize, int nBufYSize,
+                                 GDALDataType eBufType,
+                                 GSpacing nPixelSpace, GSpacing nLineSpace,
+                                 GDALRasterIOExtraArg* psExtraArg )
+
+{
+    ISIS3Dataset* poGDS = reinterpret_cast<ISIS3Dataset*>(poDS);
+    if( eRWFlag == GF_Write && poGDS->m_bGeoTIFFAsRegularExternal &&
+        !poGDS->m_bGeoTIFFInitDone )
+    {
+        InitFile();
+    }
+    if( eRWFlag == GF_Write && 
+        poGDS->m_bHasSrcNoData && poGDS->m_dfSrcNoData != m_dfNoData )
+    {
+        const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
+        if( eBufType == eDataType && nPixelSpace == nDTSize &&
+            nLineSpace == nPixelSpace * nBufXSize )
+        {
+            RemapNoData( eDataType, pData, nBufXSize * nBufYSize,
+                         poGDS->m_dfSrcNoData, m_dfNoData );
+        }
+        else
+        {
+            const GByte* pabySrc = reinterpret_cast<GByte*>(pData);
+            GByte* pabyTemp = reinterpret_cast<GByte*>(
+                VSI_MALLOC3_VERBOSE(nDTSize, nBufXSize, nBufYSize));
+            for( int i = 0; i < nBufYSize; i++ )
+            {
+                GDALCopyWords( pabySrc + i * nLineSpace, eBufType,
+                               static_cast<int>(nPixelSpace),
+                               pabyTemp + i * nBufXSize * nDTSize,
+                               eDataType, nDTSize,
+                               nBufXSize );
+            }
+            RemapNoData( eDataType, pabyTemp, nBufXSize * nBufYSize,
+                         poGDS->m_dfSrcNoData, m_dfNoData );
+            CPLErr eErr = GDALProxyRasterBand::IRasterIO( eRWFlag,
+                                     nXOff, nYOff, nXSize, nYSize,
+                                     pabyTemp, nBufXSize, nBufYSize,
+                                     eDataType,
+                                     nDTSize, nDTSize*nBufXSize,
+                                     psExtraArg );
+            VSIFree(pabyTemp);
+            return eErr;
+        }
+    }
+    return GDALProxyRasterBand::IRasterIO( eRWFlag,
+                                     nXOff, nYOff, nXSize, nYSize,
+                                     pData, nBufXSize, nBufYSize,
+                                     eBufType,
+                                     nPixelSpace, nLineSpace,
+                                     psExtraArg );
+}
+
+/************************************************************************/
+/*                            ISISMaskBand()                            */
+/************************************************************************/
+
+ISISMaskBand::ISISMaskBand( GDALRasterBand* poBaseBand )
+    : m_poBaseBand(poBaseBand)
+    , m_pBuffer(NULL)
+{
+    eDataType = GDT_Byte;
+    poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    nRasterXSize = poBaseBand->GetXSize();
+    nRasterYSize = poBaseBand->GetYSize();
+}
+
+/************************************************************************/
+/*                           ~ISISMaskBand()                            */
+/************************************************************************/
+
+ISISMaskBand::~ISISMaskBand()
+{
+    VSIFree(m_pBuffer);
+}
+
+/************************************************************************/
+/*                             FillMask()                               */
+/************************************************************************/
+
+template<class T>
+static void FillMask      (void* pvBuffer,
+                           GByte* pabyDst,
+                           int nReqXSize, int nReqYSize,
+                           int nBlockXSize,
+                           T NULL_VAL, T LOW_REPR_SAT, T LOW_INSTR_SAT,
+                           T HIGH_INSTR_SAT, T HIGH_REPR_SAT)
+{
+    const T* pSrc = static_cast<T*>(pvBuffer);
+    for( int y = 0; y < nReqYSize; y++ )
+    {
+        for( int x = 0; x < nReqXSize; x++ )
+        {
+            const T nSrc = pSrc[y * nBlockXSize + x];
+            if( nSrc == NULL_VAL ||
+                nSrc == LOW_REPR_SAT ||
+                nSrc == LOW_INSTR_SAT ||
+                nSrc == HIGH_INSTR_SAT ||
+                nSrc == HIGH_REPR_SAT )
+            {
+                pabyDst[y * nBlockXSize + x] = 0;
+            }
+            else
+            {
+                pabyDst[y * nBlockXSize + x] = 255;
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                           IReadBlock()                               */
+/************************************************************************/
+
+CPLErr ISISMaskBand::IReadBlock( int nXBlock, int nYBlock, void *pImage )
+
+{
+    const GDALDataType eSrcDT = m_poBaseBand->GetRasterDataType();
+    const int nSrcDTSize = GDALGetDataTypeSizeBytes(eSrcDT);
+    if( m_pBuffer == NULL )
+    {
+        m_pBuffer = VSI_MALLOC3_VERBOSE(nBlockXSize, nBlockYSize, nSrcDTSize);
+        if( m_pBuffer == NULL )
+            return CE_Failure;
+    }
+
+    int nXOff = nXBlock * nBlockXSize;
+    int nReqXSize = nBlockXSize;
+    if( nXOff + nReqXSize > nRasterXSize )
+        nReqXSize = nRasterXSize - nXOff;
+    int nYOff = nYBlock * nBlockYSize;
+    int nReqYSize = nBlockYSize;
+    if( nYOff + nReqYSize > nRasterYSize )
+        nReqYSize = nRasterYSize - nYOff;
+
+    if( m_poBaseBand->RasterIO( GF_Read,
+                                nXOff, nYOff, nReqXSize, nReqYSize,
+                                m_pBuffer,
+                                nReqXSize, nReqYSize,
+                                eSrcDT,
+                                nSrcDTSize,
+                                nSrcDTSize * nBlockXSize,
+                                NULL ) != CE_None )
+    {
+        return CE_Failure;
+    }
+
+    GByte* pabyDst = static_cast<GByte*>(pImage);
+    if( eSrcDT == GDT_Byte )
+    {
+        FillMask<GByte>(m_pBuffer, pabyDst, nReqXSize, nReqYSize, nBlockXSize,
+                        NULL1, LOW_REPR_SAT1, LOW_INSTR_SAT1,
+                        HIGH_INSTR_SAT1, HIGH_REPR_SAT1);
+    }
+    else if( eSrcDT == GDT_UInt16 )
+    {
+        FillMask<GUInt16>(m_pBuffer, pabyDst, nReqXSize, nReqYSize, nBlockXSize,
+                        NULLU2, LOW_REPR_SATU2, LOW_INSTR_SATU2,
+                        HIGH_INSTR_SATU2, HIGH_REPR_SATU2);
+    }
+    else if( eSrcDT == GDT_Int16 )
+    {
+        FillMask<GInt16>(m_pBuffer, pabyDst, nReqXSize, nReqYSize, nBlockXSize,
+                        NULL2, LOW_REPR_SAT2, LOW_INSTR_SAT2,
+                        HIGH_INSTR_SAT2, HIGH_REPR_SAT2);
+    }
+    else
+    {
+        CPLAssert( eSrcDT == GDT_Float32 );
+        FillMask<float>(m_pBuffer, pabyDst, nReqXSize, nReqYSize, nBlockXSize,
+                        NULL4, LOW_REPR_SAT4, LOW_INSTR_SAT4,
+                        HIGH_INSTR_SAT4, HIGH_REPR_SAT4);
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            ISIS3Dataset()                            */
+/************************************************************************/
+
+ISIS3Dataset::ISIS3Dataset() :
+    m_fpLabel(NULL),
+    m_fpImage(NULL),
+    m_poExternalDS(NULL),
+    m_bGeoTIFFAsRegularExternal(false),
+    m_bGeoTIFFInitDone(true),
+    m_bIsLabelWritten(true),
+    m_bIsTiled(false),
+    m_bInitToNodata(false),
+    m_bGotTransform(false),
+    m_bHasSrcNoData(false),
+    m_dfSrcNoData(0.0),
+    m_bForce360(false),
+    m_bWriteBoundingDegrees(true),
+    m_poJSonLabel(NULL),
+    m_bUseSrcLabel(true),
+    m_bUseSrcMapping(false),
+    m_bUseSrcHistory(true),
+    m_bAddGDALHistory(true),
+    m_poSrcJSonLabel(NULL)
+{
+    m_oKeywords.SetStripSurroundingQuotes(true);
+    m_adfGeoTransform[0] = 0.0;
+    m_adfGeoTransform[1] = 1.0;
+    m_adfGeoTransform[2] = 0.0;
+    m_adfGeoTransform[3] = 0.0;
+    m_adfGeoTransform[4] = 0.0;
+    m_adfGeoTransform[5] = 1.0;
+}
+
+/************************************************************************/
+/*                           ~ISIS3Dataset()                            */
+/************************************************************************/
+
+ISIS3Dataset::~ISIS3Dataset()
+
+{
+    if( !m_bIsLabelWritten )
+        WriteLabel();
+    if( m_poExternalDS && m_bGeoTIFFAsRegularExternal && !m_bGeoTIFFInitDone )
+    {
+        reinterpret_cast<ISIS3WrapperRasterBand*>(GetRasterBand(1))->
+            InitFile();
+    }
+    FlushCache();
+    if( m_fpLabel != NULL )
+        VSIFCloseL( m_fpLabel );
+    if( m_fpImage != NULL && m_fpImage != m_fpLabel )
+        VSIFCloseL( m_fpImage );
+    if( m_poJSonLabel != NULL )
+        json_object_put(m_poJSonLabel);
+    if( m_poSrcJSonLabel != NULL )
+        json_object_put(m_poSrcJSonLabel);
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                        CloseDependentDatasets()                      */
+/************************************************************************/
+
+int ISIS3Dataset::CloseDependentDatasets()
+{
+    int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
+
+    if( m_poExternalDS )
+    {
+        bHasDroppedRef = FALSE;
+        delete m_poExternalDS;
+        m_poExternalDS = NULL;
+    }
+
+    for( int iBand = 0; iBand < nBands; iBand++ )
+    {
+       delete papoBands[iBand];
+    }
+    nBands = 0;
+
+    return bHasDroppedRef;
+}
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **ISIS3Dataset::GetFileList()
+
+{
+    char **papszFileList = GDALPamDataset::GetFileList();
+
+    if( !m_osExternalFilename.empty() )
+        papszFileList = CSLAddString( papszFileList, m_osExternalFilename );
+    for( int i = 0; i < m_aosAdditionalFiles.Count(); ++i )
+    {
+        if( CSLFindString(papszFileList, m_aosAdditionalFiles[i]) < 0 )
+        {
+            papszFileList = CSLAddString( papszFileList,
+                                          m_aosAdditionalFiles[i] );
+        }
+    }
+
+    return papszFileList;
+}
+
+/************************************************************************/
+/*                          GetProjectionRef()                          */
+/************************************************************************/
+
+const char *ISIS3Dataset::GetProjectionRef()
+
+{
+    if( !m_osProjection.empty() )
+        return m_osProjection;
+
+    return GDALPamDataset::GetProjectionRef();
+}
+
+/************************************************************************/
+/*                           SetProjection()                            */
+/************************************************************************/
+
+CPLErr ISIS3Dataset::SetProjection( const char* pszProjection )
+{
+    if( eAccess == GA_ReadOnly )
+        return GDALPamDataset::SetProjection( pszProjection );
+    m_osProjection = pszProjection ? pszProjection : "";
+    if( m_poExternalDS )
+        m_poExternalDS->SetProjection(pszProjection);
+    InvalidateLabel();
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr ISIS3Dataset::GetGeoTransform( double * padfTransform )
+
+{
+    if( m_bGotTransform )
+    {
+        memcpy( padfTransform, m_adfGeoTransform, sizeof(double) * 6 );
+        return CE_None;
+    }
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
+}
+
+/************************************************************************/
+/*                          SetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr ISIS3Dataset::SetGeoTransform( double * padfTransform )
+
+{
+    if( eAccess == GA_ReadOnly )
+        return GDALPamDataset::SetGeoTransform( padfTransform );
+    if( padfTransform[1] <= 0.0 || padfTransform[1] != -padfTransform[5] ||
+        padfTransform[2] != 0.0 || padfTransform[4] != 0.0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only north-up geotransform with square pixels supported");
+        return CE_Failure;
+    }
+    m_bGotTransform = true;
+    memcpy( m_adfGeoTransform, padfTransform, sizeof(double) * 6 );
+    if( m_poExternalDS )
+        m_poExternalDS->SetGeoTransform(padfTransform);
+    InvalidateLabel();
+    return CE_None;
+}
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **ISIS3Dataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(
+        NULL, FALSE, "", "json:ISIS3", NULL);
+}
+
+/************************************************************************/
+/*                             GetMetadata()                            */
+/************************************************************************/
+
+char **ISIS3Dataset::GetMetadata( const char* pszDomain )
+{
+    if( pszDomain != NULL && EQUAL( pszDomain, "json:ISIS3" ) )
+    {
+        if( m_aosISIS3MD.empty() )
+        {
+            if( eAccess == GA_Update && m_poJSonLabel == NULL )
+            {
+                BuildLabel();
+            }
+            CPLAssert( m_poJSonLabel != NULL );
+            const char* pszJSon = json_object_to_json_string_ext(
+                m_poJSonLabel, JSON_C_TO_STRING_PRETTY);
+            m_aosISIS3MD.InsertString(0, pszJSon);
+        }
+        return m_aosISIS3MD.List();
+    }
+    return GDALPamDataset::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                           InvalidateLabel()                          */
+/************************************************************************/
+
+void ISIS3Dataset::InvalidateLabel()
+{
+    if( m_poJSonLabel )
+            json_object_put(m_poJSonLabel);
+        m_poJSonLabel = NULL;
+    m_aosISIS3MD.Clear();
+}
+
+/************************************************************************/
+/*                             SetMetadata()                            */
+/************************************************************************/
+
+CPLErr ISIS3Dataset::SetMetadata( char** papszMD, const char* pszDomain )
+{
+    if( m_bUseSrcLabel && eAccess == GA_Update && pszDomain != NULL &&
+        EQUAL( pszDomain, "json:ISIS3" ) )
+    {
+        if( m_poSrcJSonLabel )
+            json_object_put(m_poSrcJSonLabel);
+        m_poSrcJSonLabel = NULL;
+        InvalidateLabel();
+        if( papszMD != NULL && papszMD[0] != NULL )
+        {
+            if( !OGRJSonParse( papszMD[0], &m_poSrcJSonLabel, true ) )
+            {
+                return CE_Failure;
+            }
+        }
+        return CE_None;
+    }
+    return GDALPamDataset::SetMetadata(papszMD, pszDomain);
+}
+
+/************************************************************************/
+/*                              Identify()                              */
+/************************************************************************/
+int ISIS3Dataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    if( poOpenInfo->fpL != NULL &&
+        poOpenInfo->pabyHeader != NULL &&
+        strstr((const char *)poOpenInfo->pabyHeader,"IsisCube") != NULL )
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *ISIS3Dataset::Open( GDALOpenInfo * poOpenInfo )
+{
+/* -------------------------------------------------------------------- */
+/*      Does this look like a CUBE dataset?                             */
+/* -------------------------------------------------------------------- */
+    if( !Identify( poOpenInfo ) )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Open the file using the large file API.                         */
+/* -------------------------------------------------------------------- */
+    ISIS3Dataset *poDS = new ISIS3Dataset();
+
+    if( ! poDS->m_oKeywords.Ingest( poOpenInfo->fpL, 0 ) )
+    {
+        VSIFCloseL( poOpenInfo->fpL );
+        poOpenInfo->fpL = NULL;
+        delete poDS;
+        return NULL;
+    }
+    poDS->m_poJSonLabel = poDS->m_oKeywords.StealJSon();
+    json_object_object_add(poDS->m_poJSonLabel, "_filename",
+                           json_object_new_string(poOpenInfo->pszFilename));
+
+    // Find additional files from the label
+    CPLJsonObject oObjLabel(poDS->m_poJSonLabel);
+    if( oObjLabel.getType() == CPLJsonObject::OBJECT )
+    {
+        const size_t nSize = oObjLabel.size();
+        for( size_t i = 0; i < nSize; ++i )
+        {
+            const CPLJsonObject& oObj(oObjLabel[i]);
+            if( oObj.getType() == CPLJsonObject::OBJECT )
+            {
+                const CPLString& osKey = oObjLabel.getKey(i);
+
+                CPLString osContainerName(osKey);
+                if( oObj.has( "_container_name" ) )
+                {
+                    const CPLJsonObject& oContainerName(
+                        oObj["_container_name"]);
+                    if( oContainerName.getType() ==
+                                    CPLJsonObject::STRING )
+                    {
+                        osContainerName = oContainerName.getString();
+                    }
+                }
+
+                if( oObj.has( "^" + osContainerName ) )
+                {
+                    const CPLJsonObject& oFilename(
+                                        oObj["^" + osContainerName]);
+                    if( oFilename.getType() == CPLJsonObject::STRING )
+                    {
+                        VSIStatBufL sStat;
+                        CPLString osFilename( CPLFormFilename(
+                            CPLGetPath(poOpenInfo->pszFilename),
+                            oFilename.getString(),
+                            NULL ) );
+                        if( VSIStatL( osFilename, &sStat ) == 0 )
+                        {
+                            poDS->m_aosAdditionalFiles.AddString(
+                                osFilename);
+                        }
+                        else
+                        {
+                            CPLDebug("ISIS3",
+                                        "File %s referenced but not foud",
+                                        osFilename.c_str());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    VSIFCloseL( poOpenInfo->fpL );
+    poOpenInfo->fpL = NULL;
+
+/* -------------------------------------------------------------------- */
+/* Assume user is pointing to label (i.e. .lbl) file for detached option */
+/* -------------------------------------------------------------------- */
+    //  Image can be inline or detached and point to an image name
+    //  the Format can be Tiled or Raw
+    //  Object = Core
+    //      StartByte   = 65537
+    //      Format      = Tile
+    //      TileSamples = 128
+    //      TileLines   = 128
+    //OR-----
+    //  Object = Core
+    //      StartByte = 1
+    //      ^Core     = r0200357_detatched.cub
+    //      Format    = BandSequential
+    //OR-----
+    //  Object = Core
+    //      StartByte = 1
+    //      ^Core     = r0200357_detached_tiled.cub
+    //      Format      = Tile
+    //      TileSamples = 128
+    //      TileLines   = 128
+    //OR-----
+    //  Object = Core
+    //      StartByte = 1
+    //      ^Core     = some.tif
+    //      Format    = GeoTIFF
+
+/* -------------------------------------------------------------------- */
+/*      What file contains the actual data?                             */
+/* -------------------------------------------------------------------- */
+    const char *pszCore = poDS->GetKeyword( "IsisCube.Core.^Core" );
+    CPLString osQubeFile;
+
+    if( EQUAL(pszCore,"") )
+        osQubeFile = poOpenInfo->pszFilename;
+    else
+    {
+        CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+        osQubeFile = CPLFormFilename( osPath, pszCore, NULL );
+        poDS->m_osExternalFilename = osQubeFile;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check if file an ISIS3 header file?  Read a few lines of text   */
+/*      searching for something starting with nrows or ncols.           */
+/* -------------------------------------------------------------------- */
+
+    /*************   Skipbytes     *****************************/
+    const int nSkipBytes =
+            atoi(poDS->GetKeyword("IsisCube.Core.StartByte", "1")) - 1;
+
+    /*******   Grab format type (BandSequential, Tiled)  *******/
+    CPLString osFormat = poDS->GetKeyword( "IsisCube.Core.Format" );
+
+    int tileSizeX = 0;
+    int tileSizeY = 0;
+
+    if (EQUAL(osFormat,"Tile") ) 
+    {
+       poDS->m_bIsTiled = true;
+       /******* Get Tile Sizes *********/
+       tileSizeX = atoi(poDS->GetKeyword("IsisCube.Core.TileSamples"));
+       tileSizeY = atoi(poDS->GetKeyword("IsisCube.Core.TileLines"));
+       if (tileSizeX <= 0 || tileSizeY <= 0)
+       {
+           CPLError( CE_Failure, CPLE_OpenFailed,
+                     "Wrong tile dimensions : %d x %d",
+                     tileSizeX, tileSizeY);
+           delete poDS;
+           return NULL;
+       }
+    }
+    else if (!EQUAL(osFormat,"BandSequential") &&
+             !EQUAL(osFormat,"GeoTIFF") )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "%s format not supported.", osFormat.c_str());
+        delete poDS;
+        return NULL;
+    }
+
+    /***********   Grab samples lines band ************/
+    const int nCols = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Samples"));
+    const int nRows = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Lines"));
+    const int nBands = atoi(poDS->GetKeyword("IsisCube.Core.Dimensions.Bands"));
+
+    /****** Grab format type - ISIS3 only supports 8,U16,S16,32 *****/
+    GDALDataType eDataType = GDT_Byte;
+    double dfNoData = 0.0;
+
+    const char *itype = poDS->GetKeyword( "IsisCube.Core.Pixels.Type" );
+    if (EQUAL(itype,"UnsignedByte") ) {
+        eDataType = GDT_Byte;
+        dfNoData = NULL1;
+    }
+    else if (EQUAL(itype,"UnsignedWord") ) {
+        eDataType = GDT_UInt16;
+        dfNoData = NULLU2;
+    }
+    else if (EQUAL(itype,"SignedWord") ) {
+        eDataType = GDT_Int16;
+        dfNoData = NULL2;
+    }
+    else if (EQUAL(itype,"Real") || EQUAL(itype,"") ) {
+        eDataType = GDT_Float32;
+        dfNoData = NULL4;
+    }
+    else {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "%s pixel type not supported.", itype);
+        delete poDS;
+        return NULL;
+    }
+
+    /***********   Grab samples lines band ************/
+
+    //default to MSB
+    const bool bIsLSB = EQUAL(
+            poDS->GetKeyword( "IsisCube.Core.Pixels.ByteOrder"),"Lsb");
+
+    /***********   Grab Cellsize ************/
+    double dfXDim = 1.0;
+    double dfYDim = 1.0;
+
+    const char* pszRes = poDS->GetKeyword("IsisCube.Mapping.PixelResolution");
+    if (strlen(pszRes) > 0 ) {
+        dfXDim = CPLAtof(pszRes); /* values are in meters */
+        dfYDim = -CPLAtof(pszRes);
+    }
+
+    /***********   Grab UpperLeftCornerY ************/
+    double dfULYMap = 0.5;
+
+    const char* pszULY = poDS->GetKeyword("IsisCube.Mapping.UpperLeftCornerY");
+    if (strlen(pszULY) > 0) {
+        dfULYMap = CPLAtof(pszULY);
+    }
+
+    /***********   Grab UpperLeftCornerX ************/
+    double dfULXMap = 0.5;
+
+    const char* pszULX = poDS->GetKeyword("IsisCube.Mapping.UpperLeftCornerX");
+    if( strlen(pszULX) > 0 ) {
+        dfULXMap = CPLAtof(pszULX);
+    }
+
+    /***********  Grab TARGET_NAME  ************/
+    /**** This is the planets name i.e. Mars ***/
+    const char *target_name = poDS->GetKeyword("IsisCube.Mapping.TargetName");
+
+    /***********   Grab MAP_PROJECTION_TYPE ************/
+     const char *map_proj_name =
+        poDS->GetKeyword( "IsisCube.Mapping.ProjectionName");
+
+    /***********   Grab SEMI-MAJOR ************/
+    const double semi_major =
+        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.EquatorialRadius"));
+
+    /***********   Grab semi-minor ************/
+    const double semi_minor =
+        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.PolarRadius"));
+
+    /***********   Grab CENTER_LAT ************/
+    const double center_lat =
+        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.CenterLatitude"));
+
+    /***********   Grab CENTER_LON ************/
+    const double center_lon =
+        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.CenterLongitude"));
+
+    /***********   Grab 1st std parallel ************/
+    const double first_std_parallel =
+        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.FirstStandardParallel"));
+
+    /***********   Grab 2nd std parallel ************/
+    const double second_std_parallel =
+        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.SecondStandardParallel"));
+
+    /***********   Grab scaleFactor ************/
+    const double scaleFactor =
+        CPLAtof(poDS->GetKeyword( "IsisCube.Mapping.scaleFactor", "1.0"));
+
+    /*** grab      LatitudeType = Planetographic ****/
+    // Need to further study how ocentric/ographic will effect the gdal library
+    // So far we will use this fact to define a sphere or ellipse for some
+    // projections
+
+    // Frank - may need to talk this over
+    bool bIsGeographic = true;
+    if (EQUAL( poDS->GetKeyword("IsisCube.Mapping.LatitudeType"),
+               "Planetocentric" ))
+        bIsGeographic = false;
+
+    //Set oSRS projection and parameters
+    //############################################################
+    //ISIS3 Projection types
+    //  Equirectangular
+    //  LambertConformal
+    //  Mercator
+    //  ObliqueCylindrical //Todo
+    //  Orthographic
+    //  PolarStereographic
+    //  SimpleCylindrical
+    //  Sinusoidal
+    //  TransverseMercator
+
+#ifdef DEBUG
     CPLDebug( "ISIS3", "using projection %s", map_proj_name);
 #endif
 
     OGRSpatialReference oSRS;
-    bool bProjectionSet = true;
+    bool bProjectionSet = true;
+
+    if ((EQUAL( map_proj_name, "Equirectangular" )) ||
+        (EQUAL( map_proj_name, "SimpleCylindrical" )) )  {
+        oSRS.OGRSpatialReference::SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 );
+    } else if (EQUAL( map_proj_name, "Orthographic" )) {
+        oSRS.OGRSpatialReference::SetOrthographic ( center_lat, center_lon, 0, 0 );
+    } else if (EQUAL( map_proj_name, "Sinusoidal" )) {
+        oSRS.OGRSpatialReference::SetSinusoidal ( center_lon, 0, 0 );
+    } else if (EQUAL( map_proj_name, "Mercator" )) {
+        oSRS.OGRSpatialReference::SetMercator ( center_lat, center_lon, scaleFactor, 0, 0 );
+    } else if (EQUAL( map_proj_name, "PolarStereographic" )) {
+        oSRS.OGRSpatialReference::SetPS ( center_lat, center_lon, scaleFactor, 0, 0 );
+    } else if (EQUAL( map_proj_name, "TransverseMercator" )) {
+        oSRS.OGRSpatialReference::SetTM ( center_lat, center_lon, scaleFactor, 0, 0 );
+    } else if (EQUAL( map_proj_name, "LambertConformal" )) {
+        oSRS.OGRSpatialReference::SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 );
+    } else {
+        CPLDebug( "ISIS3",
+                  "Dataset projection %s is not supported. Continuing...",
+                  map_proj_name );
+        bProjectionSet = false;
+    }
+
+    if (bProjectionSet) {
+        //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword
+        CPLString osProjTargetName(map_proj_name);
+        osProjTargetName += " ";
+        osProjTargetName += target_name;
+        oSRS.SetProjCS(osProjTargetName); //set ProjCS keyword
+
+        //The geographic/geocentric name will be the same basic name as the body name
+        //'GCS' = Geographic/Geocentric Coordinate System
+        CPLString osGeogName("GCS_");
+        osGeogName += target_name;
+
+        //The datum name will be the same basic name as the planet
+        CPLString osDatumName("D_");
+        osDatumName += target_name;
+
+        CPLString osSphereName(target_name);
+        //strcat(osSphereName, "_IAU_IAG");  //Might not be IAU defined so don't add
+
+        //calculate inverse flattening from major and minor axis: 1/f = a/(a-b)
+        double iflattening = 0.0;
+        if ((semi_major - semi_minor) < 0.0000001)
+           iflattening = 0;
+        else
+           iflattening = semi_major / (semi_major - semi_minor);
+
+        //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility
+        //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally
+        if ( ( (EQUAL( map_proj_name, "Stereographic" ) && (fabs(center_lat) == 90)) ) ||
+             (EQUAL( map_proj_name, "PolarStereographic" )) )
+         {
+            if (bIsGeographic) {
+                //Geograpraphic, so set an ellipse
+                oSRS.SetGeogCS( osGeogName, osDatumName, osSphereName,
+                                semi_major, iflattening,
+                               "Reference_Meridian", 0.0 );
+            } else {
+              //Geocentric, so force a sphere using the semi-minor axis. I hope...
+              osSphereName += "_polarRadius";
+              oSRS.SetGeogCS( osGeogName, osDatumName, osSphereName,
+                              semi_minor, 0.0,
+                              "Reference_Meridian", 0.0 );
+            }
+        }
+        else if ( (EQUAL( map_proj_name, "SimpleCylindrical" )) ||
+                  (EQUAL( map_proj_name, "Orthographic" )) ||
+                  (EQUAL( map_proj_name, "Stereographic" )) ||
+                  (EQUAL( map_proj_name, "Sinusoidal" )) ) {
+            // ISIS uses the spherical equation for these projections
+            // so force a sphere.
+            oSRS.SetGeogCS( osGeogName, osDatumName, osSphereName,
+                            semi_major, 0.0,
+                            "Reference_Meridian", 0.0 );
+        }
+        else if  (EQUAL( map_proj_name, "Equirectangular" )) {
+            //Calculate localRadius using ISIS3 simple elliptical method
+            //  not the more standard Radius of Curvature method
+            //PI = 4 * atan(1);
+            const double radLat = center_lat * M_PI / 180;  // in radians
+            const double localRadius
+                = semi_major * semi_minor
+                / sqrt( pow( semi_minor * cos( radLat ), 2)
+                       + pow( semi_major * sin( radLat ), 2) );
+            osSphereName += "_localRadius";
+            oSRS.SetGeogCS( osGeogName, osDatumName, osSphereName,
+                            localRadius, 0.0,
+                            "Reference_Meridian", 0.0 );
+        }
+        else {
+            //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc.
+            //Geographic, so set an ellipse
+            if (bIsGeographic) {
+                oSRS.SetGeogCS( osGeogName, osDatumName, osSphereName,
+                                semi_major, iflattening,
+                                "Reference_Meridian", 0.0 );
+            } else {
+                //Geocentric, so force a sphere. I hope...
+                oSRS.SetGeogCS( osGeogName, osDatumName, osSphereName,
+                                semi_major, 0.0,
+                                "Reference_Meridian", 0.0 );
+            }
+        }
+
+        // translate back into a projection string.
+        char *pszResult = NULL;
+        oSRS.exportToWkt( &pszResult );
+        poDS->m_osProjection = pszResult;
+        CPLFree( pszResult );
+    }
+
+/* END ISIS3 Label Read */
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+/* -------------------------------------------------------------------- */
+/*      Did we get the required keywords?  If not we return with        */
+/*      this never having been considered to be a match. This isn't     */
+/*      an error!                                                       */
+/* -------------------------------------------------------------------- */
+    if( !GDALCheckDatasetDimensions(nCols, nRows) ||
+        !GDALCheckBandCount(nBands, false) )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Capture some information from the file that is of interest.     */
+/* -------------------------------------------------------------------- */
+    poDS->nRasterXSize = nCols;
+    poDS->nRasterYSize = nRows;
+
+/* -------------------------------------------------------------------- */
+/*      Open target binary file.                                        */
+/* -------------------------------------------------------------------- */
+    if( EQUAL(osFormat,"GeoTIFF") )
+    {
+        if( nSkipBytes != 0 )
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "Ignoring StartByte=%d for format=GeoTIFF",
+                     1+nSkipBytes);
+        }
+        poDS->m_poExternalDS = reinterpret_cast<GDALDataset *>(
+                                GDALOpen( osQubeFile, poOpenInfo->eAccess ) );
+        if( poDS->m_poExternalDS == NULL )
+        {
+            delete poDS;
+            return NULL;
+        }
+        if( poDS->m_poExternalDS->GetRasterXSize() != poDS->nRasterXSize ||
+            poDS->m_poExternalDS->GetRasterYSize() != poDS->nRasterYSize ||
+            poDS->m_poExternalDS->GetRasterCount() != nBands ||
+            poDS->m_poExternalDS->GetRasterBand(1)->GetRasterDataType() != 
+                                                                    eDataType )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "%s has incompatible characteristics with the ones "
+                      "declared in the label.",
+                      osQubeFile.c_str() );
+            delete poDS;
+            return NULL;
+        }
+    }
+    else
+    {
+        if( poOpenInfo->eAccess == GA_ReadOnly )
+            poDS->m_fpImage = VSIFOpenL( osQubeFile, "r" );
+        else
+            poDS->m_fpImage = VSIFOpenL( osQubeFile, "r+" );
+
+        if( poDS->m_fpImage == NULL )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                    "Failed to open %s: %s.",
+                    osQubeFile.c_str(),
+                    VSIStrerror( errno ) );
+            delete poDS;
+            return NULL;
+        }
+
+        // Sanity checks in case the external raw file appears to be a
+        // TIFF file
+        if( EQUAL(CPLGetExtension(osQubeFile), "tif") )
+        {
+            GDALDataset* poTIF_DS = reinterpret_cast<GDALDataset*>(
+                GDALOpen(osQubeFile, GA_ReadOnly));
+            if( poTIF_DS )
+            {
+                bool bWarned = false;
+                if( poTIF_DS->GetRasterXSize() != poDS->nRasterXSize ||
+                    poTIF_DS->GetRasterYSize() != poDS->nRasterYSize ||
+                    poTIF_DS->GetRasterCount() != nBands ||
+                    poTIF_DS->GetRasterBand(1)->GetRasterDataType() != 
+                                                                eDataType ||
+                    poTIF_DS->GetMetadataItem("COMPRESSION",
+                                              "IMAGE_STRUCTURE") != NULL )
+                {
+                    bWarned = true;
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                        "%s has incompatible characteristics with the ones "
+                        "declared in the label.",
+                        osQubeFile.c_str() );
+                }
+                int nBlockXSize = 1, nBlockYSize = 1;
+                poTIF_DS->GetRasterBand(1)->GetBlockSize(&nBlockXSize,
+                                                         &nBlockYSize);
+                if( (poDS->m_bIsTiled && (nBlockXSize != tileSizeX ||
+                                          nBlockYSize != tileSizeY) ) ||
+                    (!poDS->m_bIsTiled && (nBlockXSize != nCols ||
+                                        (nBands > 1 && nBlockYSize != 1))) )
+                {
+                    if( !bWarned )
+                    {
+                        bWarned = true;
+                        CPLError( CE_Warning, CPLE_AppDefined,
+                            "%s has incompatible characteristics with the ones "
+                            "declared in the label.",
+                            osQubeFile.c_str() );
+                    }
+                }
+
+                // Check that blocks are effectively written in expected order.
+                const int nBlockSizeBytes = nBlockXSize * nBlockYSize *
+                                        GDALGetDataTypeSizeBytes(eDataType);
+                bool bGoOn = !bWarned;
+                const int l_nBlocksPerRow =
+                        DIV_ROUND_UP(nCols, nBlockXSize);
+                const int l_nBlocksPerColumn =
+                        DIV_ROUND_UP(nRows, nBlockYSize);
+                int nBlockNo = 0;
+                for( int i = 0; i < nBands && bGoOn; i++ )
+                {
+                    for( int y = 0; y < l_nBlocksPerColumn && bGoOn; y++ )
+                    {
+                        for( int x = 0; x < l_nBlocksPerRow && bGoOn; x++ )
+                        {
+                            const char* pszBlockOffset =  poTIF_DS->
+                                GetRasterBand(i+1)->GetMetadataItem(
+                                    CPLSPrintf("BLOCK_OFFSET_%d_%d", x, y),
+                                    "TIFF");
+                            if( pszBlockOffset )
+                            {
+                                GIntBig nOffset = CPLAtoGIntBig(pszBlockOffset);
+                                if( nOffset != nSkipBytes + nBlockNo *
+                                                            nBlockSizeBytes )
+                                {
+                                    //bWarned = true;
+                                    CPLError( CE_Warning, CPLE_AppDefined,
+                                        "%s has incompatible "
+                                        "characteristics with the ones "
+                                        "declared in the label.",
+                                        osQubeFile.c_str() );
+                                    bGoOn = false;
+                                }
+                            }
+                            nBlockNo ++;
+                        }
+                    }
+                }
+
+                delete poTIF_DS;
+            }
+        }
+    }
+
+    poDS->eAccess = poOpenInfo->eAccess;
+
+/* -------------------------------------------------------------------- */
+/*      Compute the line offset.                                        */
+/* -------------------------------------------------------------------- */
+    int nLineOffset = 0;
+    int nPixelOffset = 0;
+    vsi_l_offset nBandOffset = 0;
+
+    if( EQUAL(osFormat,"BandSequential") )
+    {
+        const int nItemSize = GDALGetDataTypeSizeBytes(eDataType);
+        nPixelOffset = nItemSize;
+        nLineOffset = nPixelOffset * nCols;
+        nBandOffset = static_cast<vsi_l_offset>(nLineOffset) * nRows;
+    }
+    /* else Tiled or external */
+
+/* -------------------------------------------------------------------- */
+/*      Create band information objects.                                */
+/* -------------------------------------------------------------------- */
+#ifdef CPL_LSB
+    const bool bNativeOrder = bIsLSB;
+#else
+    const bool bNativeOrder = !bIsLSB;
+#endif
+
+    for( int i = 0; i < nBands; i++ )
+    {
+        GDALRasterBand *poBand = NULL;
+
+        if( poDS->m_poExternalDS != NULL )
+        {
+            ISIS3WrapperRasterBand* poISISBand =
+                new ISIS3WrapperRasterBand(
+                            poDS->m_poExternalDS->GetRasterBand( i+1 ) );
+            poBand = poISISBand;
+            poDS->SetBand( i+1, poBand );
+
+            poISISBand->SetMaskBand( new ISISMaskBand(poISISBand) );
+        }
+        else if( poDS->m_bIsTiled )
+        {
+            ISISTiledBand* poISISBand =
+                new ISISTiledBand( poDS, poDS->m_fpImage, i+1, eDataType,
+                                        tileSizeX, tileSizeY,
+                                        nSkipBytes, 0, 0,
+                                        bNativeOrder );
+
+            poBand = poISISBand;
+            poDS->SetBand( i+1, poBand );
+
+            poISISBand->SetMaskBand( new ISISMaskBand(poISISBand) );
+        }
+        else
+        {
+            ISIS3RawRasterBand* poISISBand =
+                new ISIS3RawRasterBand( poDS, i+1, poDS->m_fpImage,
+                                   nSkipBytes + nBandOffset * i,
+                                   nPixelOffset, nLineOffset, eDataType,
+                                   bNativeOrder,
+                                   TRUE );
+
+            poBand = poISISBand;
+            poDS->SetBand( i+1, poBand );
+
+            poISISBand->SetMaskBand( new ISISMaskBand(poISISBand) );
+        }
+
+        poBand->SetNoDataValue( dfNoData );
+
+        // Set offset/scale values.
+        const double dfOffset =
+            CPLAtofM(poDS->GetKeyword("IsisCube.Core.Pixels.Base","0.0"));
+        const double dfScale =
+            CPLAtofM(poDS->GetKeyword("IsisCube.Core.Pixels.Multiplier","1.0"));
+        if( dfOffset != 0.0 || dfScale != 1.0 )
+        {
+            poBand->SetOffset(dfOffset);
+            poBand->SetScale(dfScale);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check for a .prj file. For ISIS3 I would like to keep this in   */
+/* -------------------------------------------------------------------- */
+    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+    const CPLString osName = CPLGetBasename(poOpenInfo->pszFilename);
+    const char  *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" );
+
+    VSILFILE *fp = VSIFOpenL( pszPrjFile, "r" );
+    if( fp != NULL )
+    {
+        VSIFCloseL( fp );
+
+        char **papszLines = CSLLoad( pszPrjFile );
+
+        OGRSpatialReference oSRS2;
+        if( oSRS2.importFromESRI( papszLines ) == OGRERR_NONE )
+        {
+            poDS->m_aosAdditionalFiles.AddString( pszPrjFile );
+            char *pszResult = NULL;
+            oSRS2.exportToWkt( &pszResult );
+            poDS->m_osProjection = pszResult;
+            CPLFree( pszResult );
+        }
+
+        CSLDestroy( papszLines );
+    }
+
+    if( dfULXMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
+    {
+        poDS->m_bGotTransform = true;
+        poDS->m_adfGeoTransform[0] = dfULXMap;
+        poDS->m_adfGeoTransform[1] = dfXDim;
+        poDS->m_adfGeoTransform[2] = 0.0;
+        poDS->m_adfGeoTransform[3] = dfULYMap;
+        poDS->m_adfGeoTransform[4] = 0.0;
+        poDS->m_adfGeoTransform[5] = dfYDim;
+    }
+
+    if( !poDS->m_bGotTransform )
+    {
+        poDS->m_bGotTransform =
+            CPL_TO_BOOL(GDALReadWorldFile( poOpenInfo->pszFilename, "cbw",
+                               poDS->m_adfGeoTransform ));
+        if( poDS->m_bGotTransform )
+        {
+            poDS->m_aosAdditionalFiles.AddString(
+                        CPLResetExtension(poOpenInfo->pszFilename, "cbw") );
+        }
+    }
+
+    if( !poDS->m_bGotTransform )
+    {
+        poDS->m_bGotTransform =
+            CPL_TO_BOOL(GDALReadWorldFile( poOpenInfo->pszFilename, "wld",
+                               poDS->m_adfGeoTransform ));
+        if( poDS->m_bGotTransform )
+        {
+            poDS->m_aosAdditionalFiles.AddString(
+                        CPLResetExtension(poOpenInfo->pszFilename, "wld") );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize any PAM information.                                 */
+/* -------------------------------------------------------------------- */
+    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->TryLoadXML();
+
+/* -------------------------------------------------------------------- */
+/*      Check for overviews.                                            */
+/* -------------------------------------------------------------------- */
+    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                             GetKeyword()                             */
+/************************************************************************/
+
+const char *ISIS3Dataset::GetKeyword( const char *pszPath,
+                                      const char *pszDefault )
+
+{
+    return m_oKeywords.GetKeyword( pszPath, pszDefault );
+}
+
+/************************************************************************/
+/*                              FixLong()                               */
+/************************************************************************/
+
+double ISIS3Dataset::FixLong( double dfLong )
+{
+    if( m_osLongitudeDirection == "PositiveWest" )
+        dfLong = -dfLong;
+    if( m_bForce360 && dfLong < 0 )
+        dfLong += 360.0;
+    return dfLong;
+}
+
+/************************************************************************/
+/*                           BuildLabel()                               */
+/************************************************************************/
+
+void ISIS3Dataset::BuildLabel()
+{
+    // If we have a source label, then edit it directly
+    CPLJsonObject oLabel( m_poSrcJSonLabel );
+    if( m_poSrcJSonLabel == NULL )
+        oLabel.clear();
+
+    CPLJsonObject& oIsisCube = oLabel["IsisCube"];
+    if( oIsisCube.getType() != CPLJsonObject::OBJECT )
+        oIsisCube.clear();
+    oIsisCube["_type"] = "object";
+
+    if( !m_osComment.empty() )
+        oIsisCube.insert(0, "_comment", CPLJsonObject(m_osComment));
+
+    CPLJsonObject& oCore = oIsisCube["Core"];
+    if( oCore.getType() != CPLJsonObject::OBJECT )
+        oCore.clear();
+    oCore["_type"] = "object";
+
+    if( !m_osExternalFilename.empty() )
+    {
+        if( m_poExternalDS && m_bGeoTIFFAsRegularExternal )
+        {
+            if( !m_bGeoTIFFInitDone )
+            {
+                reinterpret_cast<ISIS3WrapperRasterBand*>(GetRasterBand(1))->
+                    InitFile();
+            }
+
+            const char* pszOffset = m_poExternalDS->GetRasterBand(1)->
+                                GetMetadataItem("BLOCK_OFFSET_0_0", "TIFF");
+            if( pszOffset )
+            {
+                oCore["StartByte"] = 1 + atoi(pszOffset);
+            }
+            else
+            {
+                // Shouldn't happen normally
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Missing BLOCK_OFFSET_0_0");
+                m_bGeoTIFFAsRegularExternal = false;
+                oCore["StartByte"] = 1;
+            }
+        }
+        else
+        {
+            oCore["StartByte"] = 1;
+        }
+        oCore["^Core"] = CPLGetFilename(m_osExternalFilename);
+    }
+    else
+    {
+        oCore["StartByte"] = pszSTARTBYTE_PLACEHOLDER;
+        oCore.del("^Core");
+    }
+
+    if( m_poExternalDS && !m_bGeoTIFFAsRegularExternal )
+    {
+        oCore["Format"] = "GeoTIFF";
+        oCore.del("TileSamples");
+        oCore.del("TileLines");
+    }
+    else if( m_bIsTiled )
+    {
+        oCore["Format"] = "Tile";
+        int nBlockXSize = 1, nBlockYSize = 1;
+        GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+        oCore["TileSamples"] = nBlockXSize;
+        oCore["TileLines"] = nBlockYSize;
+    }
+    else
+    {
+        oCore["Format"] = "BandSequential";
+        oCore.del("TileSamples");
+        oCore.del("TileLines");
+    }
+
+    CPLJsonObject& oDimensions = oCore["Dimensions"];
+    if( oDimensions.getType() != CPLJsonObject::OBJECT )
+        oDimensions.clear();
+    oDimensions["_type"] = "group";
+    oDimensions["Samples"] = nRasterXSize;
+    oDimensions["Lines"] = nRasterYSize;
+    oDimensions["Bands"] = nBands;
+
+    CPLJsonObject& oPixels = oCore["Pixels"];
+    if( oPixels.getType() != CPLJsonObject::OBJECT )
+        oPixels.clear();
+    oPixels["_type"] = "group";
+        const GDALDataType eDT = GetRasterBand(1)->GetRasterDataType();
+    oPixels["Type"] =
+        (eDT == GDT_Byte) ?   "UnsignedByte" :
+        (eDT == GDT_UInt16) ? "UnsignedWord" :
+        (eDT == GDT_Int16) ?  "SignedWord" :
+                                "Real";
+
+    oPixels["ByteOrder"] = "Lsb";
+    oPixels["Base"] = GetRasterBand(1)->GetOffset();
+    oPixels["Multiplier"] = GetRasterBand(1)->GetScale();
+
+    OGRSpatialReference oSRS;
 
-    if ((EQUAL( map_proj_name, "Equirectangular" )) ||
-        (EQUAL( map_proj_name, "SimpleCylindrical" )) )  {
-        oSRS.OGRSpatialReference::SetEquirectangular2 ( 0.0, center_lon, center_lat, 0, 0 );
-    } else if (EQUAL( map_proj_name, "Orthographic" )) {
-        oSRS.OGRSpatialReference::SetOrthographic ( center_lat, center_lon, 0, 0 );
-    } else if (EQUAL( map_proj_name, "Sinusoidal" )) {
-        oSRS.OGRSpatialReference::SetSinusoidal ( center_lon, 0, 0 );
-    } else if (EQUAL( map_proj_name, "Mercator" )) {
-        oSRS.OGRSpatialReference::SetMercator ( center_lat, center_lon, scaleFactor, 0, 0 );
-    } else if (EQUAL( map_proj_name, "PolarStereographic" )) {
-        oSRS.OGRSpatialReference::SetPS ( center_lat, center_lon, scaleFactor, 0, 0 );
-    } else if (EQUAL( map_proj_name, "TransverseMercator" )) {
-        oSRS.OGRSpatialReference::SetTM ( center_lat, center_lon, scaleFactor, 0, 0 );
-    } else if (EQUAL( map_proj_name, "LambertConformal" )) {
-        oSRS.OGRSpatialReference::SetLCC ( first_std_parallel, second_std_parallel, center_lat, center_lon, 0, 0 );
-    } else {
-        CPLDebug( "ISIS3",
-                  "Dataset projection %s is not supported. Continuing...",
-                  map_proj_name );
-        bProjectionSet = false;
+    if( !m_bUseSrcMapping && oIsisCube.has("Mapping") )
+        oIsisCube["Mapping"].clear();
+
+    if( m_bUseSrcMapping && oIsisCube.has("Mapping") &&
+        oIsisCube["Mapping"].getType() == CPLJsonObject::OBJECT)
+    {
+        CPLJsonObject& oMapping = oIsisCube["Mapping"];
+        if( !m_osTargetName.empty() )
+            oMapping["TargetName"] = m_osTargetName;
+        if( !m_osLatitudeType.empty() )
+            oMapping["LatitudeType"] = m_osLatitudeType;
+        if( !m_osLongitudeDirection.empty() )
+            oMapping["LongitudeDirection"] = m_osLongitudeDirection;
     }
+    else if( !m_bUseSrcMapping && !m_osProjection.empty() )
+    {
+        CPLJsonObject& oMapping = oIsisCube["Mapping"];
+        oMapping["_type"] = "group";
 
-    if (bProjectionSet) {
-        char proj_target_name[200];
+        oSRS.SetFromUserInput(m_osProjection);
+        if( oSRS.IsProjected() || oSRS.IsGeographic() )
+        {
+            const char* pszDatum = oSRS.GetAttrValue("DATUM");
+            CPLString osTargetName( m_osTargetName );
+            if( osTargetName.empty() )
+            {
+                if( pszDatum && STARTS_WITH(pszDatum, "D_") )
+                {
+                    osTargetName = pszDatum + 2;
+                }
+                else if( pszDatum )
+                {
+                    osTargetName = pszDatum;
+                }
+            }
+            if( !osTargetName.empty() )
+                oMapping["TargetName"] = osTargetName;
+
+            oMapping["EquatorialRadius"]["value"] = oSRS.GetSemiMajor();
+            oMapping["EquatorialRadius"]["unit"] = "meters";
+            oMapping["PolarRadius"]["value"] = oSRS.GetSemiMinor();
+            oMapping["PolarRadius"]["unit"] = "meters";
+
+            if( !m_osLatitudeType.empty() )
+                oMapping["LatitudeType"] = m_osLatitudeType;
+            else
+                oMapping["LatitudeType"] = "Planetocentric";
+
+            if( !m_osLongitudeDirection.empty() )
+                oMapping["LongitudeDirection"] = m_osLongitudeDirection;
+            else
+                oMapping["LongitudeDirection"] = "PositiveEast";
+
+            double adfX[4] = {0};
+            double adfY[4] = {0};
+            bool bLongLatCorners = false;
+            if( m_bGotTransform )
+            {
+                for( int i = 0; i < 4; i++ )
+                {
+                    adfX[i] = m_adfGeoTransform[0] + (i%2) *
+                                    nRasterXSize * m_adfGeoTransform[1];
+                    adfY[i] = m_adfGeoTransform[3] +
+                            ( (i == 0 || i == 3) ? 0 : 1 ) *
+                            nRasterYSize * m_adfGeoTransform[5];
+                }
+                if( oSRS.IsGeographic() )
+                {
+                    bLongLatCorners = true;
+                }
+                else
+                {
+                    OGRSpatialReference* poSRSLongLat = oSRS.CloneGeogCS();
+                    OGRCoordinateTransformation* poCT =
+                        OGRCreateCoordinateTransformation(&oSRS, poSRSLongLat);
+                    if( poCT )
+                    {
+                        if( poCT->Transform(4, adfX, adfY) )
+                        {
+                            bLongLatCorners = true;
+                        }
+                        delete poCT;
+                    }
+                    delete poSRSLongLat;
+                }
+            }
+            if( bLongLatCorners )
+            {
+                for( int i = 0; i < 4; i++ )
+                {
+                    adfX[i] = FixLong(adfX[i]);
+                }
+            }
 
-        //Create projection name, i.e. MERCATOR MARS and set as ProjCS keyword
-        strcpy(proj_target_name, map_proj_name);
-        strcat(proj_target_name, " ");
-        strcat(proj_target_name, target_name);
-        oSRS.SetProjCS(proj_target_name); //set ProjCS keyword
+            if( bLongLatCorners && (
+                    m_bForce360 || adfX[0] <- 180.0 || adfX[3] > 180.0) )
+            {
+                oMapping["LongitudeDomain"] = 360;
+            }
+            else
+            {
+                oMapping["LongitudeDomain"] = 180;
+            }
 
-        //The geographic/geocentric name will be the same basic name as the body name
-        //'GCS' = Geographic/Geocentric Coordinate System
-        char geog_name[60];
-        strcpy(geog_name, "GCS_");
-        strcat(geog_name, target_name);
+            if( m_bWriteBoundingDegrees && !m_osBoundingDegrees.empty() )
+            {
+                char** papszTokens =
+                        CSLTokenizeString2(m_osBoundingDegrees, ",", 0);
+                if( CSLCount(papszTokens) == 4 )
+                {
+                    oMapping["MinimumLatitude"]  = CPLAtof(papszTokens[1]);
+                    oMapping["MinimumLongitude"] = CPLAtof(papszTokens[0]);
+                    oMapping["MaximumLatitude"]  = CPLAtof(papszTokens[3]);
+                    oMapping["MaximumLongitude"] = CPLAtof(papszTokens[2]);
+                }
+                CSLDestroy(papszTokens);
+            }
+            else if( m_bWriteBoundingDegrees && bLongLatCorners )
+            {
+                oMapping["MinimumLatitude"] = std::min(
+                    std::min(adfY[0], adfY[1]), std::min(adfY[2],adfY[3]));
+                oMapping["MinimumLongitude"] = std::min(
+                    std::min(adfX[0], adfX[1]), std::min(adfX[2],adfX[3]));
+                oMapping["MaximumLatitude"] = std::max(
+                    std::max(adfY[0], adfY[1]), std::max(adfY[2],adfY[3]));
+                oMapping["MaximumLongitude"] = std::max(
+                    std::max(adfX[0], adfX[1]), std::max(adfX[2],adfX[3]));
+            }
 
-        //The datum name will be the same basic name as the planet
-        char datum_name[60];
-        strcpy(datum_name, "D_");
-        strcat(datum_name, target_name);
+            const char* pszProjection = oSRS.GetAttrValue("PROJECTION");
+            if( pszProjection == NULL )
+            {
+                oMapping["ProjectionName"] = "SimpleCylindrical";
+                oMapping["CenterLongitude"] = 0.0;
+                oMapping["CenterLatitude"] = 0.0;
+                oMapping["CenterLatitudeRadius"] = oSRS.GetSemiMajor();
+            }
+            else if( EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR) )
+            {
+                oMapping["ProjectionName"] = "Equirectangular";
+                if( oSRS.GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 )
+                                                                    != 0.0 )
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                             "Ignoring %s. Only 0 value supported",
+                             SRS_PP_LATITUDE_OF_ORIGIN);
+                }
+                oMapping["CenterLongitude"] =
+                    FixLong(oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
+                const double dfCenterLat =
+                        oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
+                oMapping["CenterLatitude"] = dfCenterLat;
+
+                  // in radians
+                const double radLat = dfCenterLat * M_PI / 180;
+                const double semi_major = oSRS.GetSemiMajor();
+                const double semi_minor = oSRS.GetSemiMinor();
+                const double localRadius
+                        = semi_major * semi_minor
+                        / sqrt( pow( semi_minor * cos( radLat ), 2)
+                            + pow( semi_major * sin( radLat ), 2) );
+                oMapping["CenterLatitudeRadius"] = localRadius;
+            }
+
+            else if( EQUAL(pszProjection, SRS_PT_ORTHOGRAPHIC) )
+            {
+                oMapping["ProjectionName"] = "Orthographic";
+                oMapping["CenterLongitude"] = FixLong(
+                    oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
+                oMapping["CenterLatitude"] =
+                        oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
+            }
 
-        char sphere_name[60];
-        strcpy(sphere_name, target_name);
-        //strcat(sphere_name, "_IAU_IAG");  //Might not be IAU defined so don't add
+            else if( EQUAL(pszProjection, SRS_PT_SINUSOIDAL) )
+            {
+                oMapping["ProjectionName"] = "Sinusoidal";
+                oMapping["CenterLongitude"] = FixLong(
+                    oSRS.GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0));
+            }
 
-        //calculate inverse flattening from major and minor axis: 1/f = a/(a-b)
-        double iflattening = 0.0;
-        if ((semi_major - semi_minor) < 0.0000001)
-           iflattening = 0;
+            else if( EQUAL(pszProjection, SRS_PT_MERCATOR_1SP) )
+            {
+                oMapping["ProjectionName"] = "Mercator";
+                oMapping["CenterLongitude"] = FixLong(
+                        oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
+                oMapping["CenterLatitude"] =
+                        oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
+                oMapping["scaleFactor"] =
+                        oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+            }
+
+            else if( EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) )
+            {
+                oMapping["ProjectionName"] = "PolarStereographic";
+                oMapping["CenterLongitude"] = FixLong(
+                        oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
+                oMapping["CenterLatitude"] =
+                        oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
+                oMapping["scaleFactor"] =
+                        oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+            }
+
+            else if( EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR) )
+            {
+                oMapping["ProjectionName"] = "TransverseMercator";
+                oMapping["CenterLongitude"] = FixLong(
+                        oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
+                oMapping["CenterLatitude"] =
+                        oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
+                oMapping["scaleFactor"] =
+                        oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+            }
+
+            else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
+            {
+                oMapping["ProjectionName"] = "LambertConformal";
+                oMapping["CenterLongitude"] = FixLong(
+                        oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0));
+                oMapping["CenterLatitude"] =
+                        oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
+                oMapping["FirstStandardParallel"] =
+                        oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0);
+                oMapping["SecondStandardParallel"] =
+                        oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0);
+            }
+
+            else
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "Projection %s not supported",
+                         pszProjection);
+            }
+
+            if( oMapping.has("ProjectionName") )
+            {
+                if( oSRS.GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 ) != 0.0 )
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                             "Ignoring %s. Only 0 value supported",
+                             SRS_PP_FALSE_EASTING);
+                }
+                if( oSRS.GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 ) != 0.0 )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "Ignoring %s. Only 0 value supported",
+                             SRS_PP_FALSE_NORTHING);
+                }
+            }
+        }
         else
-           iflattening = semi_major / (semi_major - semi_minor);
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "SRS not supported");
+        }
+    }
 
-        //Set the body size but take into consideration which proj is being used to help w/ proj4 compatibility
-        //The use of a Sphere, polar radius or ellipse here is based on how ISIS does it internally
-        if ( ( (EQUAL( map_proj_name, "Stereographic" ) && (fabs(center_lat) == 90)) ) ||
-	           (EQUAL( map_proj_name, "PolarStereographic" )) )
-         {
-            if (bIsGeographic) {
-                //Geograpraphic, so set an ellipse
-                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening,
-                               "Reference_Meridian", 0.0 );
-            } else {
-              //Geocentric, so force a sphere using the semi-minor axis. I hope...
-              strcat(sphere_name, "_polarRadius");
-              oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                              semi_minor, 0.0,
-                              "Reference_Meridian", 0.0 );
+    if( !m_bUseSrcMapping && m_bGotTransform )
+    {
+        CPLJsonObject& oMapping = oIsisCube["Mapping"];
+        oMapping["_type"] = "group";
+
+        const double dfDegToMeter = oSRS.GetSemiMajor() * M_PI / 180.0;
+        if( !m_osProjection.empty() && oSRS.IsProjected() )
+        {
+            const double dfLinearUnits = oSRS.GetLinearUnits();
+            // Maybe we should deal differently with non meter units ?
+            const double dfRes = m_adfGeoTransform[1] * dfLinearUnits;
+            const double dfScale = dfDegToMeter / dfRes;
+            oMapping["UpperLeftCornerX"] = m_adfGeoTransform[0];
+            oMapping["UpperLeftCornerY"] = m_adfGeoTransform[3];
+            oMapping["PixelResolution"]["value"] = dfRes;
+            oMapping["PixelResolution"]["unit"] = "meters/pixel";
+            oMapping["Scale"]["value"] = dfScale;
+            oMapping["Scale"]["unit"] = "pixels/degree";
+        }
+        else if( !m_osProjection.empty() && oSRS.IsGeographic() )
+        {
+            const double dfScale = 1.0 / m_adfGeoTransform[1];
+            const double dfRes = m_adfGeoTransform[1] * dfDegToMeter;
+            oMapping["UpperLeftCornerX"] = m_adfGeoTransform[0] * dfDegToMeter;
+            oMapping["UpperLeftCornerY"] = m_adfGeoTransform[3] * dfDegToMeter;
+            oMapping["PixelResolution"]["value"] = dfRes;
+            oMapping["PixelResolution"]["unit"] = "meters/pixel";
+            oMapping["Scale"]["value"] = dfScale;
+            oMapping["Scale"]["unit"] = "pixels/degree";
+        }
+        else
+        {
+            oMapping["UpperLeftCornerX"] = m_adfGeoTransform[0];
+            oMapping["UpperLeftCornerY"] = m_adfGeoTransform[3];
+            oMapping["PixelResolution"] = m_adfGeoTransform[1];
+        }
+    }
+
+    CPLJsonObject& oLabelLabel = oLabel["Label"];
+    if( oLabelLabel.getType() != CPLJsonObject::OBJECT )
+        oLabelLabel.clear();
+    oLabelLabel["_type"] = "object";
+    oLabelLabel["Bytes"] = pszLABEL_BYTES_PLACEHOLDER;
+
+    // Deal with History object
+    BuildHistory();
+
+    CPLJsonObject& oHistory = oLabel["History"];
+    oHistory.clear();
+    oHistory["_type"] = "object";
+    oHistory["Name"] = "IsisCube";
+    if( m_osExternalFilename.empty() )
+        oHistory["StartByte"] = pszHISTORY_STARTBYTE_PLACEHOLDER;
+    else
+        oHistory["StartByte"] = 1;
+    oHistory["Bytes"] = static_cast<GIntBig>(m_osHistory.size());
+    if( !m_osExternalFilename.empty() )
+    {
+        CPLString osFilename(CPLGetBasename(GetDescription()));
+        osFilename += ".History.IsisCube";
+        oHistory["^History"] = osFilename;
+    }
+
+    // Deal with other objects that have StartByte & Bytes
+    m_aoNonPixelSections.clear();
+    if( m_poSrcJSonLabel )
+    {
+        CPLString osLabelSrcFilename;
+        if( oLabel.has("_filename") )
+        {
+            const CPLJsonObject& oFilename = oLabel["_filename"];
+            if( oFilename.getType() == CPLJsonObject::STRING )
+            {
+                osLabelSrcFilename = oFilename.getString();
             }
         }
-        else if ( (EQUAL( map_proj_name, "SimpleCylindrical" )) ||
-  	               (EQUAL( map_proj_name, "Orthographic" )) ||
-	               (EQUAL( map_proj_name, "Stereographic" )) ||
-	               (EQUAL( map_proj_name, "Sinusoidal" )) ) {
-            // ISIS uses the spherical equation for these projections
-            // so force a sphere.
-            oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                            semi_major, 0.0,
-                            "Reference_Meridian", 0.0 );
+
+        for( size_t i = 0; i < oLabel.size(); )
+        {
+            if( oLabel[i].getType() == CPLJsonObject::OBJECT )
+            {
+                const CPLString& osKey = oLabel.getKey(i);
+                if( osKey == "History" )
+                {
+                    ++i;
+                    continue;
+                }
+
+                CPLJsonObject& oObj(oLabel[i]);
+                if( oObj.getType() != CPLJsonObject::OBJECT ||
+                    !oObj.has("Bytes") ||
+                    oObj["Bytes"].getType() != CPLJsonObject::INT ||
+                    oObj["Bytes"].getInt() <= 0 ||
+                    !oObj.has("StartByte") ||
+                    oObj["StartByte"].getType() != CPLJsonObject::INT ||
+                    oObj["StartByte"].getInt() <= 0 )
+                {
+                    ++i;
+                    continue;
+                }
+
+                if( osLabelSrcFilename.empty() )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "Cannot find _filename attribute in "
+                            "source ISIS3 metadata. Removing object "
+                            "%s from the label.",
+                            osKey.c_str());
+                    oLabel.del( osKey );
+                    // Do not increment i due to deletion.
+                    continue;
+                }
+
+                NonPixelSection oSection;
+                oSection.osSrcFilename = osLabelSrcFilename;
+                oSection.nSrcOffset = static_cast<vsi_l_offset>(
+                    oObj["StartByte"].getInt()) - 1U;
+                oSection.nSize = static_cast<vsi_l_offset>(
+                    oObj["Bytes"].getInt());
+
+                CPLString osName;
+                if( oObj.has( "Name" ) )
+                {
+                    const CPLJsonObject& oName(oObj["Name"]);
+                    if( oName.getType() ==
+                                    CPLJsonObject::STRING )
+                    {
+                        osName = oName.getString();
+                    }
+                }
+
+                CPLString osContainerName(osKey);
+                if( oObj.has( "_container_name" ) )
+                {
+                    const CPLJsonObject& oContainerName(
+                        oObj["_container_name"]);
+                    if( oContainerName.getType() ==
+                                    CPLJsonObject::STRING )
+                    {
+                        osContainerName = oContainerName.getString();
+                    }
+                }
+
+                const CPLString osKeyFilename( "^" + osContainerName );
+                if( oObj.has( osKeyFilename ) )
+                {
+                    const CPLJsonObject& oFilename(oObj[osKeyFilename]);
+                    if( oFilename.getType() == CPLJsonObject::STRING )
+                    {
+                        VSIStatBufL sStat;
+                        const CPLString osSrcFilename( CPLFormFilename(
+                            CPLGetPath(osLabelSrcFilename),
+                            oFilename.getString(),
+                            NULL ) );
+                        if( VSIStatL( osSrcFilename, &sStat ) == 0 )
+                        {
+                            oSection.osSrcFilename = osSrcFilename;
+                        }
+                        else
+                        {
+                            CPLError(CE_Warning, CPLE_AppDefined,
+                                     "Object %s points to %s, which does "
+                                     "not exist. Removing this section "
+                                     "from the label",
+                                     osKey.c_str(),
+                                     osSrcFilename.c_str());
+                            oLabel.del( osKey );
+                            // Do not increment i due to deletion.
+                            continue;
+                        }
+                    }
+                }
+
+                if( !m_osExternalFilename.empty() )
+                {
+                    oObj["StartByte"] = 1;
+                }
+                else
+                {
+                    CPLString osPlaceHolder;
+                    osPlaceHolder.Printf(
+                        "!*^PLACEHOLDER_%d_STARTBYTE^*!",
+                        static_cast<int>(m_aoNonPixelSections.size()) + 1);
+                    oObj["StartByte"] = osPlaceHolder;
+                    oSection.osPlaceHolder = osPlaceHolder;
+                }
+
+                if( !m_osExternalFilename.empty() )
+                {
+                    CPLString osDstFilename(
+                            CPLGetBasename(GetDescription()));
+                    osDstFilename += ".";
+                    osDstFilename += osContainerName;
+                    if( !osName.empty() )
+                    {
+                        osDstFilename += ".";
+                        osDstFilename += osName;
+                    }
+
+                    oSection.osDstFilename = CPLFormFilename(
+                        CPLGetPath( GetDescription() ),
+                        osDstFilename,
+                        NULL );
+
+                    if( oObj.has(osKeyFilename) )
+                        oObj[osKeyFilename] = osDstFilename;
+                    else
+                    {
+                        // Insert before first sub-group/object if there's one
+                        size_t j = 0;
+                        for(;  j < oObj.size(); ++j )
+                        {
+                            if( oObj[j].getType() == CPLJsonObject::OBJECT )
+                            {
+                                break;
+                            }
+                        }
+                        oObj.insert( j, osKeyFilename,
+                                     CPLJsonObject(osDstFilename) );
+                    }
+                }
+                else
+                {
+                    oObj.del(osKeyFilename);
+                }
+
+                m_aoNonPixelSections.push_back(oSection);
+            }
+
+            // Do not move that in for() loop.
+            ++i;
         }
-        else if  (EQUAL( map_proj_name, "Equirectangular" )) {
-            //Calculate localRadius using ISIS3 simple elliptical method
-            //  not the more standard Radius of Curvature method
-            //PI = 4 * atan(1);
-            const double radLat = center_lat * M_PI / 180;  // in radians
-            const double localRadius
-                = semi_major * semi_minor
-                / sqrt( pow( semi_minor * cos( radLat ), 2)
-                       + pow( semi_major * sin( radLat ), 2) );
-            strcat(sphere_name, "_localRadius");
-            oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                            localRadius, 0.0,
-                            "Reference_Meridian", 0.0 );
+    }
+
+    if( m_poJSonLabel )
+        json_object_put(m_poJSonLabel);
+    m_poJSonLabel = oLabel.asLibJsonObj();
+}
+
+/************************************************************************/
+/*                         BuildHistory()                               */
+/************************************************************************/
+
+void ISIS3Dataset::BuildHistory()
+{
+    CPLString osHistory;
+
+    if( m_poSrcJSonLabel != NULL && m_bUseSrcHistory )
+    {
+        CPLJsonObject oLabel( m_poSrcJSonLabel );
+        vsi_l_offset nHistoryOffset = 0;
+        int nHistorySize = 0;
+        CPLString osSrcFilename;
+        if( oLabel.has("_filename") )
+        {
+            const CPLJsonObject& oFilename = oLabel["_filename"];
+            if( oFilename.getType() == CPLJsonObject::STRING )
+            {
+                osSrcFilename = oFilename.getString();
+            }
         }
-        else {
-            //All other projections: Mercator, Transverse Mercator, Lambert Conformal, etc.
-            //Geographic, so set an ellipse
-            if (bIsGeographic) {
-                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, iflattening,
-                                "Reference_Meridian", 0.0 );
-            } else {
-                //Geocentric, so force a sphere. I hope...
-                oSRS.SetGeogCS( geog_name, datum_name, sphere_name,
-                                semi_major, 0.0,
-                                "Reference_Meridian", 0.0 );
+        CPLString osHistoryFilename(osSrcFilename);
+        if( oLabel.has("History") )
+        {
+            const CPLJsonObject& oHistory = oLabel["History"];
+            if( oHistory.getType() == CPLJsonObject::OBJECT )
+            {
+                if( oHistory.has("^History") )
+                {
+                    const CPLJsonObject& oHistoryFilename =
+                                                    oHistory["^History"];
+                    if( oHistoryFilename.getType() == CPLJsonObject::STRING )
+                    {
+                        osHistoryFilename = 
+                            CPLFormFilename( CPLGetPath(osSrcFilename),
+                                             oHistoryFilename.getString(),
+                                             NULL );
+                    }
+                }
+
+                if( oHistory.has("StartByte") )
+                {
+                    const CPLJsonObject& oStartByte = oHistory["StartByte"];
+                    if( oStartByte.getType() == CPLJsonObject::INT &&
+                        oStartByte.getInt() > 0 )
+                    {
+                        nHistoryOffset = static_cast<vsi_l_offset>(
+                            oStartByte.getInt()) - 1U;
+                    }
+                }
+
+                if( oHistory.has("Bytes") )
+                {
+                    const CPLJsonObject& oBytes = oHistory["Bytes"];
+                    if( oBytes.getType() == CPLJsonObject::INT )
+                    {
+                        nHistorySize = static_cast<int>(
+                            oBytes.getInt());
+                    }
+                }
+            }
+        }
+        if( osHistoryFilename.empty() )
+        {
+            CPLDebug("ISIS3", "Cannot find filename for source history");
+        }
+        else if( nHistorySize <= 0 || nHistorySize > 1000000 )
+        {
+            CPLDebug("ISIS3",
+                     "Invalid or missing value for History.Bytes "
+                     "for source history");
+        }
+        else
+        {
+            VSILFILE* fpHistory = VSIFOpenL(osHistoryFilename, "rb");
+            if( fpHistory != NULL )
+            {
+                VSIFSeekL(fpHistory, nHistoryOffset, SEEK_SET);
+                osHistory.resize( nHistorySize );
+                if( VSIFReadL( &osHistory[0], nHistorySize, 1,
+                              fpHistory ) != 1 )
+                {
+                    CPLError(CE_Warning, CPLE_FileIO,
+                             "Cannot read %d bytes at offset " CPL_FRMT_GUIB
+                             "of %s: history will not be preserved",
+                             nHistorySize, nHistoryOffset,
+                             osHistoryFilename.c_str());
+                    osHistory.clear();
+                }
+                VSIFCloseL(fpHistory);
             }
+            else
+            {
+                CPLError(CE_Warning, CPLE_FileIO,
+                         "Cannot open %s: history will not be preserved",
+                         osHistoryFilename.c_str());
+            }
+        }
+    }
+
+    if( m_bAddGDALHistory && !m_osGDALHistory.empty() )
+    {
+        if( !osHistory.empty() )
+            osHistory += "\n";
+        osHistory += m_osGDALHistory;
+    }
+    else if( m_bAddGDALHistory )
+    {
+        if( !osHistory.empty() )
+            osHistory += "\n";
+
+        CPLJsonObject oHistoryObj;
+        char szFullFilename[2048] = { 0 };
+        if( !CPLGetExecPath(szFullFilename, sizeof(szFullFilename) - 1) )
+            strcpy(szFullFilename, "unknown_program");
+        const CPLString osProgram(CPLGetBasename(szFullFilename));
+        const CPLString osPath(CPLGetPath(szFullFilename));
+        CPLJsonObject& oObj = oHistoryObj[osProgram];
+        oObj["_type"] = "object";
+        oObj["GdalVersion"] = GDALVersionInfo("RELEASE_NAME");
+        if( osPath != "." )
+            oObj["ProgramPath"] = osPath;
+        time_t nCurTime = time(NULL);
+        if( nCurTime != -1 )
+        {
+            struct tm mytm;
+            CPLUnixTimeToYMDHMS(nCurTime, &mytm);
+            oObj["ExecutionDateTime"] =
+                CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
+                            mytm.tm_year + 1900,
+                            mytm.tm_mon + 1,
+                            mytm.tm_mday,
+                            mytm.tm_hour,
+                            mytm.tm_min,
+                            mytm.tm_sec);
+        }
+        char szHostname[256] = { 0 };
+        if( gethostname(szHostname, sizeof(szHostname)-1) == 0 )
+        {
+            oObj["HostName"] = szHostname;
         }
-
-        // translate back into a projection string.
-        char *pszResult = NULL;
-        oSRS.exportToWkt( &pszResult );
-        poDS->osProjection = pszResult;
-        CPLFree( pszResult );
+        const char* pszUsername = CPLGetConfigOption("USERNAME", NULL);
+        if( pszUsername == NULL )
+            pszUsername = CPLGetConfigOption("USER", NULL);
+        if( pszUsername != NULL )
+        {
+            oObj["UserName"] = pszUsername;
+        }
+        oObj["Description"] = "GDAL conversion";
+
+        CPLJsonObject& oUserParameters = oObj["UserParameters"];
+        oUserParameters["_type"] = "group";
+        if( !m_osFromFilename.empty() )
+            oUserParameters["FROM"] = CPLGetFilename( m_osFromFilename );
+        oUserParameters["TO"] = CPLGetFilename( GetDescription() );
+        if( m_bForce360 )
+            oUserParameters["Force_360"] = "true";
+
+        json_object* poObj = oHistoryObj.asLibJsonObj();
+        osHistory += SerializeAsPDL( poObj );
+        json_object_put(poObj);
     }
 
-/* END ISIS3 Label Read */
-/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+    if( osHistory.empty() )
+        osHistory = " ";
 
-/* -------------------------------------------------------------------- */
-/*     Is the CUB detached - if so, reset name to binary file?          */
-/* -------------------------------------------------------------------- */
-#ifdef notdef
-    // Frank - is this correct?
-    //The extension already added on so don't add another. But is this needed?
-    char *pszPath = CPLStrdup( CPLGetPath( poOpenInfo->pszFilename ) );
-    char *pszName = CPLStrdup( CPLGetBasename( poOpenInfo->pszFilename ) );
-    if (bIsDetached)
-        pszCUBFilename = CPLFormCIFilename( pszPath, detachedCub, "" );
-#endif
+    m_osHistory = osHistory;
+}
 
-/* -------------------------------------------------------------------- */
-/*      Did we get the required keywords?  If not we return with        */
-/*      this never having been considered to be a match. This isn't     */
-/*      an error!                                                       */
-/* -------------------------------------------------------------------- */
-    if( nRows < 1 || nCols < 1 || nBands < 1 )
+/************************************************************************/
+/*                           WriteLabel()                               */
+/************************************************************************/
+
+void ISIS3Dataset::WriteLabel()
+{
+    m_bIsLabelWritten = true;
+
+    if( m_poJSonLabel == NULL )
+        BuildLabel();
+
+    // Serialize label
+    CPLString osLabel( SerializeAsPDL(m_poJSonLabel) );
+    osLabel += "End\n";
+    char *pszLabel = &osLabel[0];
+    const int nLabelSize = static_cast<int>(osLabel.size());
+
+    // Hack back StartByte value
     {
-        delete poDS;
-        return NULL;
+        char *pszStartByte = strstr(pszLabel, pszSTARTBYTE_PLACEHOLDER);
+        if( pszStartByte != NULL )
+        {
+            const char* pszOffset = CPLSPrintf("%d", 1 + nLabelSize);
+            memcpy(pszStartByte, pszOffset, strlen(pszOffset));
+            memset(pszStartByte + strlen(pszOffset), ' ',
+                    strlen(pszSTARTBYTE_PLACEHOLDER) - strlen(pszOffset));
+        }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Capture some information from the file that is of interest.     */
-/* -------------------------------------------------------------------- */
-    poDS->nRasterXSize = nCols;
-    poDS->nRasterYSize = nRows;
+    // Hack back Label.Bytes value
+    {
+        char* pszLabelBytes = strstr(pszLabel, pszLABEL_BYTES_PLACEHOLDER);
+        if( pszLabelBytes != NULL )
+        {
+            const char* pszBytes = CPLSPrintf("%d", nLabelSize);
+            memcpy(pszLabelBytes, pszBytes, strlen(pszBytes));
+            memset(pszLabelBytes + strlen(pszBytes), ' ',
+                    strlen(pszLABEL_BYTES_PLACEHOLDER) - strlen(pszBytes));
+        }
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Open target binary file.                                        */
-/* -------------------------------------------------------------------- */
-    if( poOpenInfo->eAccess == GA_ReadOnly )
-        poDS->fpImage = VSIFOpenL( osQubeFile, "r" );
-    else
-        poDS->fpImage = VSIFOpenL( osQubeFile, "r+" );
+    const GDALDataType eType = GetRasterBand(1)->GetRasterDataType();
+    const int nDTSize = GDALGetDataTypeSizeBytes(eType);
+    vsi_l_offset nImagePixels = 0;
+    if( m_poExternalDS == NULL )
+    {
+        if( m_bIsTiled )
+        {
+            int nBlockXSize = 1, nBlockYSize = 1;
+            GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+            nImagePixels = static_cast<vsi_l_offset>(nBlockXSize) *
+                            nBlockYSize * nBands *
+                            DIV_ROUND_UP(nRasterXSize, nBlockXSize) *
+                            DIV_ROUND_UP(nRasterYSize, nBlockYSize);
+        }
+        else
+        {
+            nImagePixels = static_cast<vsi_l_offset>(nRasterXSize) *
+                            nRasterYSize * nBands;
+        }
+    }
+
+    // Hack back History.StartBytes value
+    char* pszHistoryStartBytes = strstr(pszLabel,
+                                        pszHISTORY_STARTBYTE_PLACEHOLDER);
 
-    if( poDS->fpImage == NULL )
+    vsi_l_offset nHistoryOffset = 0;
+    vsi_l_offset nLastOffset = 0;
+    if( pszHistoryStartBytes != NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to open %s with write permission.\n%s",
-                  osQubeFile.c_str(),
-                  VSIStrerror( errno ) );
-        delete poDS;
-        return NULL;
+        CPLAssert( m_osExternalFilename.empty() );
+        nHistoryOffset = nLabelSize + nImagePixels * nDTSize;
+        nLastOffset = nHistoryOffset + m_osHistory.size();
+        const char* pszStartByte = CPLSPrintf(CPL_FRMT_GUIB,
+                                              nHistoryOffset + 1);
+        CPLAssert(strlen(pszStartByte) <
+                                    strlen(pszHISTORY_STARTBYTE_PLACEHOLDER));
+        memcpy(pszHistoryStartBytes, pszStartByte, strlen(pszStartByte));
+        memset(pszHistoryStartBytes + strlen(pszStartByte), ' ',
+               strlen(pszHISTORY_STARTBYTE_PLACEHOLDER) -
+                                                        strlen(pszStartByte));
     }
 
-    poDS->eAccess = poOpenInfo->eAccess;
+    // Replace placeholders in other sections
+    for( size_t i = 0; i < m_aoNonPixelSections.size(); ++i )
+    {
+        if( !m_aoNonPixelSections[i].osPlaceHolder.empty() )
+        {
+            char* pszPlaceHolder = strstr(pszLabel,
+                            m_aoNonPixelSections[i].osPlaceHolder.c_str());
+            CPLAssert( pszPlaceHolder != NULL );
+            const char* pszStartByte = CPLSPrintf(CPL_FRMT_GUIB,
+                                                  nLastOffset + 1);
+            nLastOffset += m_aoNonPixelSections[i].nSize;
+            CPLAssert(strlen(pszStartByte) <
+                            m_aoNonPixelSections[i].osPlaceHolder.size() );
+
+            memcpy(pszPlaceHolder, pszStartByte, strlen(pszStartByte));
+            memset(pszPlaceHolder + strlen(pszStartByte), ' ',
+                m_aoNonPixelSections[i].osPlaceHolder.size() -
+                                                            strlen(pszStartByte));
+        }
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Compute the line offset.                                        */
-/* -------------------------------------------------------------------- */
-    const int nItemSize = GDALGetDataTypeSize(eDataType)/8;
-    int nLineOffset=0, nPixelOffset=0, nBandOffset=0;
+    // Write to final file
+    VSIFSeekL( m_fpLabel, 0, SEEK_SET );
+    VSIFWriteL( pszLabel, 1, osLabel.size(), m_fpLabel);
 
-    if( EQUAL(szLayout,"BSQ") )
+    if( m_osExternalFilename.empty() )
     {
-        nPixelOffset = nItemSize;
-        nLineOffset = nPixelOffset * nCols;
-        nBandOffset = nLineOffset * nRows;
+        // Update image offset in bands
+        if( m_bIsTiled )
+        {
+            for(int i=0;i<nBands;i++)
+            {
+                ISISTiledBand* poBand =
+                    reinterpret_cast<ISISTiledBand*>(GetRasterBand(i+1));
+                poBand->m_nFirstTileOffset += nLabelSize;
+            }
+        }
+        else
+        {
+            for(int i=0;i<nBands;i++)
+            {
+                ISIS3RawRasterBand* poBand =
+                    reinterpret_cast<ISIS3RawRasterBand*>(GetRasterBand(i+1));
+                poBand->nImgOffset += nLabelSize;
+            }
+        }
     }
-    /* else Tiled */
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
-#ifdef CPL_LSB
-    int bNativeOrder = !(chByteOrder == 'M');
-#else
-    int bNativeOrder = (chByteOrder == 'M');
+    if( m_bInitToNodata )
+    {
+        // Initialize the image to nodata
+        const double dfNoData = GetRasterBand(1)->GetNoDataValue();
+        if( dfNoData == 0.0 )
+        {
+            VSIFTruncateL( m_fpImage, VSIFTellL(m_fpImage) + 
+                                                nImagePixels * nDTSize );
+        }
+        else if( nDTSize != 0 ) // to make Coverity not warn about div by 0
+        {
+            const int nPageSize = 4096; // Must be multiple of 4 since
+                                        // Float32 is the largest type
+            CPLAssert( (nPageSize % nDTSize) == 0 );
+            const int nMaxPerPage = nPageSize / nDTSize;
+            GByte* pabyTemp = static_cast<GByte*>(CPLMalloc(nPageSize));
+            GDALCopyWords( &dfNoData, GDT_Float64, 0,
+                           pabyTemp, eType, nDTSize,
+                           nMaxPerPage );
+#ifdef CPL_MSB
+            GDALSwapWords( pabyTemp, nDTSize, nMaxPerPage, nDTSize );
 #endif
+            for( vsi_l_offset i = 0; i < nImagePixels; i += nMaxPerPage )
+            {
+                int n;
+                if( i + nMaxPerPage <= nImagePixels )
+                    n = nMaxPerPage;
+                else
+                    n = static_cast<int>(nImagePixels - i);
+                if( VSIFWriteL( pabyTemp, n * nDTSize, 1, m_fpImage ) != 1 )
+                {
+                    CPLError(CE_Failure, CPLE_FileIO,
+                            "Cannot initialize imagery to null");
+                    break;
+                }
+            }
 
+            CPLFree( pabyTemp );
+        }
+    }
 
-    for( int i = 0; i < nBands; i++ )
+    // Write history
+    if( !m_osHistory.empty() )
     {
-        GDALRasterBand	*poBand;
-
-        if( EQUAL(szLayout,"Tiled") )
+        if( m_osExternalFilename.empty() )
         {
-            poBand = new ISISTiledBand( poDS, poDS->fpImage, i+1, eDataType,
-                                        tileSizeX, tileSizeY,
-                                        nSkipBytes, 0, 0,
-                                        bNativeOrder );
+            VSIFSeekL( m_fpLabel, nHistoryOffset, SEEK_SET );
+            VSIFWriteL( m_osHistory.c_str(), 1, m_osHistory.size(), m_fpLabel);
         }
         else
         {
-            poBand =
-                new RawRasterBand( poDS, i+1, poDS->fpImage,
-                                   nSkipBytes + nBandOffset * i,
-                                   nPixelOffset, nLineOffset, eDataType,
-#ifdef CPL_LSB
-                                   chByteOrder == 'I' || chByteOrder == 'L',
-#else
-                                   chByteOrder == 'M',
-#endif
-                                   TRUE );
+            CPLString osFilename(CPLGetBasename(GetDescription()));
+            osFilename += ".History.IsisCube";
+            osFilename = 
+              CPLFormFilename(CPLGetPath(GetDescription()), osFilename, NULL);
+            VSILFILE* fp = VSIFOpenL(osFilename, "wb");
+            if( fp )
+            {
+                m_aosAdditionalFiles.AddString(osFilename);
+
+                VSIFWriteL( m_osHistory.c_str(), 1,
+                            m_osHistory.size(), fp );
+                VSIFCloseL(fp);
+            }
+            else
+            {
+                CPLError(CE_Warning, CPLE_FileIO,
+                         "Cannot write %s", osFilename.c_str());
+            }
+        }
+    }
+
+    // Write other non pixel sections
+    for( size_t i = 0; i < m_aoNonPixelSections.size(); ++i )
+    {
+        VSILFILE* fpSrc = VSIFOpenL(
+                        m_aoNonPixelSections[i].osSrcFilename, "rb");
+        if( fpSrc == NULL )
+        {
+            CPLError(CE_Warning, CPLE_FileIO,
+                        "Cannot open %s",
+                        m_aoNonPixelSections[i].osSrcFilename.c_str());
+            continue;
         }
 
-        poDS->SetBand( i+1, poBand );
+        VSILFILE* fpDest = m_fpLabel;
+        if( !m_aoNonPixelSections[i].osDstFilename.empty() )
+        {
+            fpDest = VSIFOpenL(m_aoNonPixelSections[i].osDstFilename, "wb");
+            if( fpDest == NULL )
+            {
+                CPLError(CE_Warning, CPLE_FileIO,
+                         "Cannot create %s",
+                         m_aoNonPixelSections[i].osDstFilename.c_str());
+                VSIFCloseL(fpSrc);
+                continue;
+            }
+
+            m_aosAdditionalFiles.AddString(
+                                m_aoNonPixelSections[i].osDstFilename);
+        }
 
-        if( bNoDataSet )
-            reinterpret_cast<GDALPamRasterBand *>(
-                poBand )->SetNoDataValue( dfNoData );
+        VSIFSeekL(fpSrc, m_aoNonPixelSections[i].nSrcOffset, SEEK_SET);
+        GByte abyBuffer[4096];
+        vsi_l_offset nRemaining = m_aoNonPixelSections[i].nSize;
+        while( nRemaining )
+        {
+            size_t nToRead = 4096;
+            if( nRemaining < nToRead )
+                nToRead = static_cast<size_t>(nRemaining);
+            size_t nRead = VSIFReadL( abyBuffer, 1, nToRead, fpSrc );
+            if( nRead != nToRead )
+            {
+                CPLError(CE_Warning, CPLE_FileIO,
+                         "Could not read " CPL_FRMT_GUIB " bytes from %s",
+                         m_aoNonPixelSections[i].nSize,
+                         m_aoNonPixelSections[i].osSrcFilename.c_str());
+                break;
+            }
+            VSIFWriteL( abyBuffer, 1, nRead, fpDest );
+            nRemaining -= nRead;
+        }
 
-        // Set offset/scale values at the PAM level.
-        poBand->SetOffset(
-            CPLAtofM(poDS->GetKeyword("IsisCube.Core.Pixels.Base","0.0")));
-        poBand->SetScale(
-          CPLAtofM(poDS->GetKeyword("IsisCube.Core.Pixels.Multiplier","1.0")));
+        VSIFCloseL( fpSrc );
+        if( fpDest != m_fpLabel )
+            VSIFCloseL(fpDest);
     }
+}
 
-/* -------------------------------------------------------------------- */
-/*      Check for a .prj file. For ISIS3 I would like to keep this in   */
-/* -------------------------------------------------------------------- */
-    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
-    const CPLString osName = CPLGetBasename(poOpenInfo->pszFilename);
-    const char  *pszPrjFile = CPLFormCIFilename( osPath, osName, "prj" );
+/************************************************************************/
+/*                      SerializeAsPDL()                                */
+/************************************************************************/
 
-    VSILFILE *fp = VSIFOpenL( pszPrjFile, "r" );
-    if( fp != NULL )
-    {
-        VSIFCloseL( fp );
+CPLString ISIS3Dataset::SerializeAsPDL( json_object* poObj )
+{
+    CPLString osTmpFile( CPLSPrintf("/vsimem/isis3_%p", poObj) );
+    VSILFILE* fpTmp = VSIFOpenL( osTmpFile, "wb+" );
+    SerializeAsPDL( fpTmp, poObj );
+    VSIFCloseL( fpTmp );
+    CPLString osContent( reinterpret_cast<char*>(
+                            VSIGetMemFileBuffer( osTmpFile, NULL, FALSE )) );
+    VSIUnlink(osTmpFile);
+    return osContent;
+}
 
-        char **papszLines = CSLLoad( pszPrjFile );
+/************************************************************************/
+/*                      SerializeAsPDL()                                */
+/************************************************************************/
 
-        OGRSpatialReference oSRS2;
-        if( oSRS2.importFromESRI( papszLines ) == OGRERR_NONE )
+void ISIS3Dataset::SerializeAsPDL( VSILFILE* fp, json_object* poObj,
+                                   int nDepth )
+{
+    CPLString osIndentation;
+    for( int i = 0; i < nDepth; i++ )
+        osIndentation += "  ";
+    const size_t WIDTH = 79;
+
+    json_object_iter it;
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    size_t nMaxKeyLength = 0;
+    json_object_object_foreachC( poObj, it )
+    {
+        if( it.val == NULL ||
+            strcmp(it.key, "_type") == 0 ||
+            strcmp(it.key, "_container_name") == 0 ||
+            strcmp(it.key, "_filename") == 0 )
         {
-            char *pszResult = NULL;
-            oSRS2.exportToWkt( &pszResult );
-            poDS->osProjection = pszResult;
-            CPLFree( pszResult );
+            continue;
+        }
+        const int nValType = json_object_get_type(it.val);
+        if( nValType == json_type_string ||
+            nValType == json_type_int ||
+            nValType == json_type_double ||
+            nValType == json_type_array )
+        {
+            if( strlen(it.key) > nMaxKeyLength )
+                nMaxKeyLength = strlen(it.key);
+        }
+        else if( nValType == json_type_object )
+        {
+            json_object* poValue = CPL_json_object_object_get(it.val,
+                                                                  "value");
+            json_object* poUnit = CPL_json_object_object_get(it.val,
+                                                                "unit");
+            if( poValue && poUnit &&
+                json_object_get_type(poUnit) == json_type_string )
+            {
+                if( strlen(it.key) > nMaxKeyLength )
+                    nMaxKeyLength = strlen(it.key);
+            }
         }
+    }
 
-        CSLDestroy( papszLines );
+    it.key = NULL;
+    it.val = NULL;
+    it.entry = NULL;
+    json_object_object_foreachC( poObj, it )
+    {
+        if( it.val == NULL ||
+            strcmp(it.key, "_type") == 0 ||
+            strcmp(it.key, "_container_name") == 0 ||
+            strcmp(it.key, "_filename") == 0 )
+        {
+            continue;
+        }
+        if( STARTS_WITH(it.key, "_comment") )
+        {
+            if(json_object_get_type(it.val) == json_type_string )
+            {
+                VSIFPrintfL(fp, "#%s\n", 
+                            json_object_get_string(it.val));
+            }
+            continue;
+        }
+        std::string osPadding;
+        if( strlen(it.key) < nMaxKeyLength )
+            osPadding.append( nMaxKeyLength - strlen(it.key), ' ' );
+        const int nValType = json_object_get_type(it.val);
+        if( nValType == json_type_object )
+        {
+            json_object* poType = CPL_json_object_object_get(it.val, "_type");
+            json_object* poContainerName =
+                CPL_json_object_object_get(it.val, "_container_name");
+            const char* pszContainerName = it.key;
+            if( poContainerName &&
+                json_object_get_type(poContainerName) == json_type_string )
+            {
+                pszContainerName = json_object_get_string(poContainerName);
+            }
+            if( poType && json_object_get_type(poType) == json_type_string )
+            {
+                const char* pszType = json_object_get_string(poType);
+                if( EQUAL(pszType, "Object") )
+                {
+                    if( nDepth == 0 && VSIFTellL(fp) != 0 )
+                        VSIFPrintfL(fp, "\n");
+                    VSIFPrintfL(fp, "%sObject = %s\n",
+                                osIndentation.c_str(), pszContainerName);
+                    SerializeAsPDL( fp, it.val, nDepth + 1 );
+                    VSIFPrintfL(fp, "%sEnd_Object\n",
+                                osIndentation.c_str());
+                }
+                else if( EQUAL(pszType, "Group") )
+                {
+                    VSIFPrintfL(fp, "\n");
+                    VSIFPrintfL(fp, "%sGroup = %s\n",
+                                osIndentation.c_str(), pszContainerName);
+                    SerializeAsPDL( fp, it.val, nDepth + 1 );
+                    VSIFPrintfL(fp, "%sEnd_Group\n",
+                                osIndentation.c_str());
+                }
+            }
+            else
+            {
+                json_object* poValue = CPL_json_object_object_get(it.val,
+                                                                  "value");
+                json_object* poUnit = CPL_json_object_object_get(it.val,
+                                                                 "unit");
+                if( poValue && poUnit &&
+                    json_object_get_type(poUnit) == json_type_string )
+                {
+                    const char* pszUnit = json_object_get_string(poUnit);
+                    const int nValueType = json_object_get_type(poValue);
+                    if( nValueType == json_type_int )
+                    {
+                        const int nVal = json_object_get_int(poValue);
+                        VSIFPrintfL(fp, "%s%s%s = %d <%s>\n",
+                                    osIndentation.c_str(), it.key,
+                                    osPadding.c_str(),
+                                    nVal, pszUnit);
+                    }
+                    else if( nValueType == json_type_double )
+                    {
+                        const double dfVal = json_object_get_double(poValue);
+                        if( dfVal >= INT_MIN && dfVal <= INT_MAX &&
+                            static_cast<int>(dfVal) == dfVal )
+                        {
+                            VSIFPrintfL(fp, "%s%s%s = %d.0 <%s>\n",
+                                        osIndentation.c_str(), it.key,
+                                        osPadding.c_str(),
+                                        static_cast<int>(dfVal), pszUnit);
+                        }
+                        else
+                        {
+                            VSIFPrintfL(fp, "%s%s%s = %.18g <%s>\n",
+                                        osIndentation.c_str(), it.key,
+                                        osPadding.c_str(),
+                                        dfVal, pszUnit);
+                        }
+                    }
+                }
+            }
+        }
+        else if( nValType == json_type_string )
+        {
+            const char* pszVal = json_object_get_string(it.val);
+            if( pszVal[0] == '\0' ||
+                strchr(pszVal, ' ') || strstr(pszVal, "\\n") ||
+                strstr(pszVal, "\\r") )
+            {
+                CPLString osVal(pszVal);
+                osVal.replaceAll("\\n", "\n");
+                osVal.replaceAll("\\r", "\r");
+                VSIFPrintfL(fp, "%s%s%s = \"%s\"\n",
+                            osIndentation.c_str(), it.key,
+                            osPadding.c_str(), osVal.c_str());
+            }
+            else
+            {
+                if( osIndentation.size() + strlen(it.key) + osPadding.size() +
+                    strlen(" = ") + strlen(pszVal) > WIDTH &&
+                    osIndentation.size() + strlen(it.key) + osPadding.size() +
+                    strlen(" = ") < WIDTH )
+                {
+                    size_t nFirstPos = osIndentation.size() + strlen(it.key) +
+                                     osPadding.size() + strlen(" = ");
+                    VSIFPrintfL(fp, "%s%s%s = ",
+                                osIndentation.c_str(), it.key,
+                                osPadding.c_str());
+                    size_t nCurPos = nFirstPos;
+                    for( int i = 0; pszVal[i] != '\0'; i++ )
+                    {
+                        nCurPos ++;
+                        if( nCurPos == WIDTH && pszVal[i+1] != '\0' )
+                        {
+                            VSIFPrintfL( fp, "-\n" );
+                            for( size_t j=0;j<nFirstPos;j++ )
+                            {
+                                const char chSpace = ' ';
+                                VSIFWriteL(&chSpace, 1, 1, fp);
+                            }
+                            nCurPos = nFirstPos + 1;
+                        }
+                        VSIFWriteL( &pszVal[i], 1, 1, fp );
+                    }
+                    VSIFPrintfL(fp, "\n");
+                }
+                else
+                {
+                    VSIFPrintfL(fp, "%s%s%s = %s\n",
+                                osIndentation.c_str(), it.key,
+                                osPadding.c_str(), pszVal);
+                }
+            }
+        }
+        else if( nValType == json_type_int )
+        {
+            const int nVal = json_object_get_int(it.val);
+            VSIFPrintfL(fp, "%s%s%s = %d\n",
+                        osIndentation.c_str(), it.key,
+                        osPadding.c_str(), nVal);
+        }
+        else if( nValType == json_type_double )
+        {
+            const double dfVal = json_object_get_double(it.val);
+            if( dfVal >= INT_MIN && dfVal <= INT_MAX &&
+                static_cast<int>(dfVal) == dfVal )
+            {
+                VSIFPrintfL(fp, "%s%s%s = %d.0\n",
+                        osIndentation.c_str(), it.key,
+                        osPadding.c_str(), static_cast<int>(dfVal));
+            }
+            else
+            {
+                VSIFPrintfL(fp, "%s%s%s = %.18g\n",
+                            osIndentation.c_str(), it.key,
+                            osPadding.c_str(), dfVal);
+            }
+        }
+        else if( nValType == json_type_array )
+        {
+            const int nLength = json_object_array_length(it.val);
+            size_t nFirstPos = osIndentation.size() + strlen(it.key) +
+                                     osPadding.size() + strlen(" = (");
+            VSIFPrintfL(fp, "%s%s%s = (",
+                        osIndentation.c_str(), it.key,
+                        osPadding.c_str());
+            size_t nCurPos = nFirstPos;
+            for( int idx = 0; idx < nLength; idx++ )
+            {
+                json_object* poItem = json_object_array_get_idx(it.val, idx);
+                const int nItemType = json_object_get_type(poItem);
+                if( nItemType == json_type_string )
+                {
+                    const char* pszVal = json_object_get_string(poItem);
+                    if( nFirstPos < WIDTH && nCurPos + strlen(pszVal) > WIDTH )
+                    {
+                        if( idx > 0 )
+                        {
+                            VSIFPrintfL( fp, "\n" );
+                            for( size_t j=0;j<nFirstPos;j++ )
+                            {
+                                const char chSpace = ' ';
+                                VSIFWriteL(&chSpace, 1, 1, fp);
+                            }
+                            nCurPos = nFirstPos;
+                        }
+
+                        for( int i = 0; pszVal[i] != '\0'; i++ )
+                        {
+                            nCurPos ++;
+                            if( nCurPos == WIDTH && pszVal[i+1] != '\0' )
+                            {
+                                VSIFPrintfL( fp, "-\n" );
+                                for( size_t j=0;j<nFirstPos;j++ )
+                                {
+                                    const char chSpace = ' ';
+                                    VSIFWriteL(&chSpace, 1, 1, fp);
+                                }
+                                nCurPos = nFirstPos + 1;
+                            }
+                            VSIFWriteL( &pszVal[i], 1, 1, fp );
+                        }
+                    }
+                    else
+                    {
+                        VSIFPrintfL( fp, "%s", pszVal );
+                        nCurPos += strlen(pszVal);
+                    }
+                }
+                else if( nItemType == json_type_int )
+                {
+                    const int nVal = json_object_get_int(poItem);
+                    const char* pszVal = CPLSPrintf("%d", nVal);
+                    const size_t nValLen = strlen(pszVal);
+                    if( nFirstPos < WIDTH && idx > 0 &&
+                        nCurPos + nValLen > WIDTH )
+                    {
+                        VSIFPrintfL( fp, "\n" );
+                        for( size_t j=0;j<nFirstPos;j++ )
+                        {
+                            const char chSpace = ' ';
+                            VSIFWriteL(&chSpace, 1, 1, fp);
+                        }
+                        nCurPos = nFirstPos;
+                    }
+                    VSIFPrintfL( fp, "%d", nVal );
+                    nCurPos += nValLen;
+                }
+                else if( nItemType == json_type_double )
+                {
+                    const double dfVal = json_object_get_double(poItem);
+                    CPLString osVal;
+                    if( dfVal >= INT_MIN && dfVal <= INT_MAX &&
+                        static_cast<int>(dfVal) == dfVal )
+                    {
+                        osVal = CPLSPrintf("%d.0", static_cast<int>(dfVal));
+                    }
+                    else
+                    {
+                        osVal = CPLSPrintf("%.18g", dfVal);
+                    }
+                    const size_t nValLen = osVal.size();
+                    if( nFirstPos < WIDTH && idx > 0 &&
+                        nCurPos + nValLen > WIDTH )
+                    {
+                        VSIFPrintfL( fp, "\n" );
+                        for( size_t j=0;j<nFirstPos;j++ )
+                        {
+                            const char chSpace = ' ';
+                            VSIFWriteL(&chSpace, 1, 1, fp);
+                        }
+                        nCurPos = nFirstPos;
+                    }
+                    VSIFPrintfL( fp, "%s", osVal.c_str() );
+                    nCurPos += nValLen;
+                }
+                if( idx < nLength - 1 )
+                {
+                    VSIFPrintfL( fp, ", " );
+                    nCurPos += 2;
+                }
+            }
+            VSIFPrintfL(fp, ")\n" );
+        }
     }
+}
 
-    if( dfULXMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
+
+/************************************************************************/
+/*                           Create()                                   */
+/************************************************************************/
+
+GDALDataset *ISIS3Dataset::Create(const char* pszFilename,
+                                  int nXSize, int nYSize, int nBands,
+                                  GDALDataType eType,
+                                  char** papszOptions)
+{
+    if( eType != GDT_Byte && eType != GDT_UInt16 && eType != GDT_Int16 &&
+        eType != GDT_Float32 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported data type");
+        return NULL;
+    }
+    if( nBands == 0 || nBands > 32767 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported band count");
+        return NULL;
+    }
+
+    const char* pszDataLocation = CSLFetchNameValueDef(papszOptions,
+                                                       "DATA_LOCATION",
+                                                       "LABEL");
+    const bool bIsTiled = CPLFetchBool(papszOptions, "TILED", false);
+    const int nBlockXSize = std::max(1,
+            atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256")));
+    const int nBlockYSize = std::max(1,
+            atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256")));
+    if( !EQUAL(pszDataLocation, "LABEL") &&
+        !EQUAL( CPLGetExtension(pszFilename), "LBL") )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "For DATA_LOCATION=%s, "
+                    "the main filename should have a .lbl extension",
+                    pszDataLocation);
+        return NULL;
+    }
+
+    VSILFILE* fp = VSIFOpenExL(pszFilename, "wb", true);
+    if( fp == NULL )
+    {
+        CPLError( CE_Failure, CPLE_FileIO,
+                  "Cannot create %s: %s",
+                  pszFilename, VSIGetLastErrorMsg() );
+        return NULL;
+    }
+    VSILFILE* fpImage = NULL;
+    CPLString osExternalFilename;
+    GDALDataset* poExternalDS = NULL;
+    bool bGeoTIFFAsRegularExternal = false;
+    if( EQUAL(pszDataLocation, "EXTERNAL") )
+    {
+        osExternalFilename = CSLFetchNameValueDef(papszOptions,
+                                        "EXTERNAL_FILENAME",
+                                        CPLResetExtension(pszFilename, "cub"));
+        fpImage = VSIFOpenExL(osExternalFilename, "wb", true);
+        if( fpImage == NULL )
+        {
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Cannot create %s: %s",
+                      osExternalFilename.c_str(), VSIGetLastErrorMsg() );
+            VSIFCloseL(fp);
+            return NULL;
+        }
+    }
+    else if( EQUAL(pszDataLocation, "GEOTIFF") )
     {
-        poDS->bGotTransform = TRUE;
-        poDS->adfGeoTransform[0] = dfULXMap;
-        poDS->adfGeoTransform[1] = dfXDim;
-        poDS->adfGeoTransform[2] = 0.0;
-        poDS->adfGeoTransform[3] = dfULYMap;
-        poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = dfYDim;
+        osExternalFilename = CSLFetchNameValueDef(papszOptions,
+                                        "EXTERNAL_FILENAME",
+                                        CPLResetExtension(pszFilename, "tif"));
+        GDALDriver* poDrv = static_cast<GDALDriver*>(
+                                            GDALGetDriverByName("GTiff"));
+        if( poDrv == NULL )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Cannot find GTiff driver" );
+            VSIFCloseL(fp);
+            return NULL;
+        }
+        char** papszGTiffOptions = NULL;
+        papszGTiffOptions = CSLSetNameValue(papszGTiffOptions,
+                                            "ENDIANNESS", "LITTLE");
+        if( bIsTiled )
+        {
+            papszGTiffOptions = CSLSetNameValue(papszGTiffOptions,
+                                                "TILED", "YES");
+            papszGTiffOptions = CSLSetNameValue(papszGTiffOptions,
+                                                "BLOCKXSIZE",
+                                                CPLSPrintf("%d", nBlockXSize));
+            papszGTiffOptions = CSLSetNameValue(papszGTiffOptions,
+                                                "BLOCKYSIZE",
+                                                CPLSPrintf("%d", nBlockYSize));
+        }
+        const char* pszGTiffOptions = CSLFetchNameValueDef(papszOptions,
+                                                    "GEOTIFF_OPTIONS", "");
+        char** papszTokens = CSLTokenizeString2( pszGTiffOptions, ",", 0 );
+        for( int i = 0; papszTokens[i] != NULL; i++ )
+        {
+            papszGTiffOptions = CSLAddString(papszGTiffOptions,
+                                             papszTokens[i]);
+        }
+        CSLDestroy(papszTokens);
+
+        // If the user didn't specify any compression and
+        // GEOTIFF_AS_REGULAR_EXTERNAL is set (or unspecified), then the
+        // GeoTIFF file can be seen as a regular external raw file, provided
+        // we make some provision on its organization.
+        if( CSLFetchNameValue(papszGTiffOptions, "COMPRESS") == NULL &&
+            CPLFetchBool(papszOptions, "GEOTIFF_AS_REGULAR_EXTERNAL", true) )
+        {
+            bGeoTIFFAsRegularExternal = true;
+            papszGTiffOptions = CSLSetNameValue(papszGTiffOptions,
+                                                "INTERLEAVE", "BAND");
+            // Will make sure that our blocks at nodata are not optimized
+            // away but indeed well written
+            papszGTiffOptions = CSLSetNameValue(papszGTiffOptions,
+                                    "@WRITE_EMPTY_TILES_SYNCHRONOUSLY", "YES");
+            if( !bIsTiled && nBands > 1 )
+            {
+                papszGTiffOptions = CSLSetNameValue(papszGTiffOptions,
+                                                    "BLOCKYSIZE", "1");
+            }
+        }
+
+        poExternalDS = poDrv->Create( osExternalFilename, nXSize, nYSize,
+                                      nBands,
+                                      eType, papszGTiffOptions );
+        CSLDestroy(papszGTiffOptions);
+        if( poExternalDS == NULL )
+        {
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Cannot create %s",
+                      osExternalFilename.c_str() );
+            VSIFCloseL(fp);
+            return NULL;
+        }
     }
 
-    if( !poDS->bGotTransform )
-        poDS->bGotTransform =
-            GDALReadWorldFile( poOpenInfo->pszFilename, "cbw",
-                               poDS->adfGeoTransform );
+    ISIS3Dataset* poDS = new ISIS3Dataset();
+    poDS->SetDescription( pszFilename );
+    poDS->eAccess = GA_Update;
+    poDS->nRasterXSize = nXSize;
+    poDS->nRasterYSize = nYSize;
+    poDS->m_osExternalFilename = osExternalFilename;
+    poDS->m_poExternalDS = poExternalDS;
+    poDS->m_bGeoTIFFAsRegularExternal = bGeoTIFFAsRegularExternal;
+    if( bGeoTIFFAsRegularExternal )
+        poDS->m_bGeoTIFFInitDone = false;
+    poDS->m_fpLabel = fp;
+    poDS->m_fpImage = fpImage ? fpImage: fp;
+    poDS->m_bIsLabelWritten = false;
+    poDS->m_bIsTiled = bIsTiled;
+    poDS->m_bInitToNodata = (poDS->m_poExternalDS == NULL);
+    poDS->m_osComment = CSLFetchNameValueDef(papszOptions, "COMMENT", "");
+    poDS->m_osLatitudeType = CSLFetchNameValueDef(papszOptions,
+                                                  "LATITUDE_TYPE", "");
+    poDS->m_osLongitudeDirection = CSLFetchNameValueDef(papszOptions,
+                                                  "LONGITUDE_DIRECTION", "");
+    poDS->m_osTargetName = CSLFetchNameValueDef(papszOptions,
+                                                  "TARGET_NAME", "");
+    poDS->m_bForce360 = CPLFetchBool(papszOptions, "FORCE_360", false);
+    poDS->m_bWriteBoundingDegrees = CPLFetchBool(papszOptions,
+                                                 "WRITE_BOUNDING_DEGREES",
+                                                 true);
+    poDS->m_osBoundingDegrees = CSLFetchNameValueDef(papszOptions,
+                                                     "BOUNDING_DEGREES", "");
+    poDS->m_bUseSrcLabel = CPLFetchBool(papszOptions, "USE_SRC_LABEL", true);
+    poDS->m_bUseSrcMapping =
+                        CPLFetchBool(papszOptions, "USE_SRC_MAPPING", false);
+    poDS->m_bUseSrcHistory =
+                        CPLFetchBool(papszOptions, "USE_SRC_HISTORY", true);
+    poDS->m_bAddGDALHistory =
+                        CPLFetchBool(papszOptions, "ADD_GDAL_HISTORY", true);
+    if( poDS->m_bAddGDALHistory )
+    {
+        poDS->m_osGDALHistory = CSLFetchNameValueDef(papszOptions,
+                                                     "GDAL_HISTORY", "");
+    }
+    const double dfNoData = (eType == GDT_Byte)    ? NULL1:
+                            (eType == GDT_UInt16)  ? NULLU2:
+                            (eType == GDT_Int16)   ? NULL2:
+                            /*(eType == GDT_Float32) ?*/ NULL4;
 
-    if( !poDS->bGotTransform )
-        poDS->bGotTransform =
-            GDALReadWorldFile( poOpenInfo->pszFilename, "wld",
-                               poDS->adfGeoTransform );
+    for( int i = 0; i < nBands; i++ )
+    {
+        GDALRasterBand *poBand = NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
-    poDS->TryLoadXML();
+        if( poDS->m_poExternalDS != NULL )
+        {
+            ISIS3WrapperRasterBand* poISISBand =
+                new ISIS3WrapperRasterBand(
+                            poDS->m_poExternalDS->GetRasterBand( i+1 ) );
+            poBand = poISISBand;
+        }
+        else if( bIsTiled  )
+        {
+            ISISTiledBand* poISISBand =
+                new ISISTiledBand( poDS, poDS->m_fpImage, i+1, eType,
+                                   nBlockXSize, nBlockYSize,
+                                   0, //nSkipBytes, to be hacked
+                                   // afterwards for in-label imagery
+                                   0, 0,
+                                   CPL_IS_LSB );
+
+            poBand = poISISBand;
+        }
+        else
+        {
+            const int nPixelOffset = GDALGetDataTypeSizeBytes(eType);
+            const int nLineOffset = nPixelOffset * nXSize;
+            const vsi_l_offset nBandOffset = 
+                static_cast<vsi_l_offset>(nLineOffset) * nYSize;
+            ISIS3RawRasterBand* poISISBand =
+                new ISIS3RawRasterBand( poDS, i+1, poDS->m_fpImage,
+                                   nBandOffset * i, // nImgOffset, to be
+                                   //hacked afterwards for in-label imagery
+                                   nPixelOffset, nLineOffset, eType,
+                                   CPL_IS_LSB,
+                                   TRUE );
 
-/* -------------------------------------------------------------------- */
-/*      Check for overviews.                                            */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+            poBand = poISISBand;
+        }
+        poDS->SetBand( i+1, poBand );
+        poBand->SetNoDataValue(dfNoData);
+    }
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
-/*                             GetKeyword()                             */
+/*                      GetUnderlyingDataset()                          */
 /************************************************************************/
 
-const char *ISIS3Dataset::GetKeyword( const char *pszPath,
-                                      const char *pszDefault )
-
+static GDALDataset* GetUnderlyingDataset( GDALDataset* poSrcDS )
 {
-    return oKeywords.GetKeyword( pszPath, pszDefault );
+    if( poSrcDS->GetDriver() != NULL &&
+        poSrcDS->GetDriver() == GDALGetDriverByName("VRT") )
+    {
+        VRTDataset* poVRTDS = reinterpret_cast<VRTDataset* >(poSrcDS);
+        poSrcDS = poVRTDS->GetSingleSimpleSource();
+    }
+
+    return poSrcDS;
 }
 
 /************************************************************************/
-/*                            GetKeywordSub()                           */
+/*                            CreateCopy()                              */
 /************************************************************************/
 
-const char *ISIS3Dataset::GetKeywordSub( const char *pszPath,
-                                         int iSubscript,
-                                         const char *pszDefault )
-
+GDALDataset* ISIS3Dataset::CreateCopy( const char *pszFilename,
+                                       GDALDataset *poSrcDS,
+                                       int /*bStrict*/,
+                                       char ** papszOptions,
+                                       GDALProgressFunc pfnProgress,
+                                       void * pProgressData )
 {
-    const char *pszResult = oKeywords.GetKeyword( pszPath, NULL );
+    const char* pszDataLocation = CSLFetchNameValueDef(papszOptions,
+                                                       "DATA_LOCATION",
+                                                       "LABEL");
+    GDALDataset* poSrcUnderlyingDS = GetUnderlyingDataset(poSrcDS);
+    if( poSrcUnderlyingDS == NULL )
+        poSrcUnderlyingDS = poSrcDS;
+    if( EQUAL(pszDataLocation, "GEOTIFF") &&
+        strcmp(poSrcUnderlyingDS->GetDescription(),
+               CSLFetchNameValueDef(papszOptions, "EXTERNAL_FILENAME",
+                                    CPLResetExtension(pszFilename, "tif"))
+              ) == 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Output file has same name as input file");
+        return NULL;
+    }
+    if( poSrcDS->GetRasterCount() == 0 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported band count");
+        return NULL;
+    }
+
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+    const int nBands = poSrcDS->GetRasterCount();
+    GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
+    ISIS3Dataset *poDS = reinterpret_cast<ISIS3Dataset*>(
+        Create( pszFilename, nXSize, nYSize, nBands, eType, papszOptions ));
+    if( poDS == NULL )
+        return NULL;
+    poDS->m_osFromFilename = poSrcUnderlyingDS->GetDescription();
+
+    double adfGeoTransform[6] = { 0.0 };
+    if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
+        && (adfGeoTransform[0] != 0.0
+            || adfGeoTransform[1] != 1.0
+            || adfGeoTransform[2] != 0.0
+            || adfGeoTransform[3] != 0.0
+            || adfGeoTransform[4] != 0.0
+            || adfGeoTransform[5] != 1.0) )
+    {
+        poDS->SetGeoTransform( adfGeoTransform );
+    }
+
+    if( poSrcDS->GetProjectionRef() != NULL
+        && strlen(poSrcDS->GetProjectionRef()) > 0 )
+    {
+        poDS->SetProjection( poSrcDS->GetProjectionRef() );
+    }
+
+    for(int i=1;i<=nBands;i++)
+    {
+        const double dfOffset = poSrcDS->GetRasterBand(i)->GetOffset();
+        if( dfOffset != 0.0 )
+            poDS->GetRasterBand(i)->SetOffset(dfOffset);
 
-    if( pszResult == NULL )
-        return pszDefault;
+        const double dfScale = poSrcDS->GetRasterBand(i)->GetScale();
+        if( dfScale != 1.0 )
+            poDS->GetRasterBand(i)->SetScale(dfScale);
+    }
 
-    if( pszResult[0] != '(' )
-        return pszDefault;
+    // Do we need to remap nodata ?
+    int bHasNoData = FALSE;
+    poDS->m_dfSrcNoData =
+        poSrcDS->GetRasterBand(1)->GetNoDataValue(&bHasNoData);
+    poDS->m_bHasSrcNoData = CPL_TO_BOOL(bHasNoData);
 
-    char **papszTokens = CSLTokenizeString2( pszResult, "(,)",
-                                             CSLT_HONOURSTRINGS );
+    if( poDS->m_bUseSrcLabel )
+    {
+        char** papszMD_ISIS3 = poSrcDS->GetMetadata("json:ISIS3");
+        if( papszMD_ISIS3 != NULL )
+        {
+            poDS->SetMetadata( papszMD_ISIS3, "json:ISIS3" );
+        }
+    }
 
-    if( iSubscript <= CSLCount(papszTokens) )
+    // We don't need to initialize the imagery as we are going to copy it
+    // completely
+    poDS->m_bInitToNodata = false;
+    CPLErr eErr = GDALDatasetCopyWholeRaster( poSrcDS, poDS,
+                                           NULL, pfnProgress, pProgressData );
+    poDS->FlushCache();
+    poDS->m_bHasSrcNoData = false;
+    if( eErr != CE_None )
     {
-        oTempResult = papszTokens[iSubscript-1];
-        CSLDestroy( papszTokens );
-        return oTempResult.c_str();
+        delete poDS;
+        return NULL;
     }
 
-    CSLDestroy( papszTokens );
-    return pszDefault;
+    return poDS;
 }
 
-
 /************************************************************************/
 /*                         GDALRegister_ISIS3()                         */
 /************************************************************************/
@@ -883,9 +4440,82 @@ void GDALRegister_ISIS3()
     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
                                "frmt_isis3.html" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "lbl cub" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 Float32" );
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList/>");
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>"
+"  <Option name='DATA_LOCATION' type='string-select' "
+                "description='Location of pixel data' default='LABEL'>"
+"     <Value>LABEL</Value>"
+"     <Value>EXTERNAL</Value>"
+"     <Value>GEOTIFF</Value>"
+"  </Option>"
+"  <Option name='GEOTIFF_AS_REGULAR_EXTERNAL' type='boolean'"
+    "description='Whether the GeoTIFF file, if uncompressed, should be "
+    "registered as a regular raw file' default='YES'/>"
+"  <Option name='GEOTIFF_OPTIONS' type='string' "
+    "description='Comma separated list of KEY=VALUE tuples to forward "
+    "to the GeoTIFF driver'/>"
+"  <Option name='EXTERNAL_FILENAME' type='string' "
+                "description='Override default external filename. "
+                "Only for DATA_LOCATION=EXTERNAL or GEOTIFF'/>"
+"  <Option name='TILED' type='boolean' "
+        "description='Whether the pixel data should be tiled' default='NO'/>"
+"  <Option name='BLOCKXSIZE' type='int' "
+                            "description='Tile width' default='256'/>"
+"  <Option name='BLOCKYSIZE' type='int' "
+                            "description='Tile height' default='256'/>"
+"  <Option name='COMMENT' type='string' "
+    "description='Comment to add into the label'/>"
+"  <Option name='LATITUDE_TYPE' type='string-select' "
+    "description='Value of Mapping.LatitudeType' default='Planetocentric'>"
+"     <Value>Planetocentric</Value>"
+"     <Value>Planetographic</Value>"
+"  </Option>"
+"  <Option name='LONGITUDE_DIRECTION' type='string-select' "
+    "description='Value of Mapping.LongitudeDirection' "
+    "default='PositiveEast'>"
+"     <Value>PositiveEast</Value>"
+"     <Value>PositiveWest</Value>"
+"  </Option>"
+"  <Option name='TARGET_NAME' type='string' description='Value of "
+    "Mapping.TargetName'/>"
+"  <Option name='FORCE_360' type='boolean' "
+    "description='Whether to force longitudes in [0,360] range' default='NO'/>"
+"  <Option name='WRITE_BOUNDING_DEGREES' type='boolean'"
+    "description='Whether to write Min/MaximumLong/Latitude values' "
+    "default='YES'/>"
+"  <Option name='BOUNDING_DEGREES' type='string'"
+    "description='Manually set bounding box with the syntax "
+    "min_long,min_lat,max_long,max_lat'/>"
+"  <Option name='USE_SRC_LABEL' type='boolean'"
+    "description='Whether to use source label in ISIS3 to ISIS3 conversions' "
+    "default='YES'/>"
+"  <Option name='USE_SRC_MAPPING' type='boolean'"
+    "description='Whether to use Mapping group from source label in "
+                 "ISIS3 to ISIS3 conversions' "
+    "default='NO'/>"
+"  <Option name='USE_SRC_HISTORY' type='boolean'"
+    "description='Whether to use content pointed by the History object in "
+                 "ISIS3 to ISIS3 conversions' "
+    "default='YES'/>"
+"  <Option name='ADD_GDAL_HISTORY' type='boolean'"
+    "description='Whether to add GDAL specific history in the content pointed "
+                 "by the History object in "
+                 "ISIS3 to ISIS3 conversions' "
+    "default='YES'/>"
+"  <Option name='GDAL_HISTORY' type='string'"
+    "description='Manually defined GDAL history. Must be formatted as ISIS3 "
+    "PDL. If not specified, it is automatically composed.'/>"
+"</CreationOptionList>"
+    );
 
     poDriver->pfnOpen = ISIS3Dataset::Open;
     poDriver->pfnIdentify = ISIS3Dataset::Identify;
+    poDriver->pfnCreate = ISIS3Dataset::Create;
+    poDriver->pfnCreateCopy = ISIS3Dataset::CreateCopy;
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/frmts/pds/makefile.vc b/frmts/pds/makefile.vc
index 0a34a1f..5775634 100644
--- a/frmts/pds/makefile.vc
+++ b/frmts/pds/makefile.vc
@@ -4,7 +4,7 @@ OBJ	=	pdsdataset.obj isis2dataset.obj isis3dataset.obj \
 
 GDAL_ROOT	=	..\..
 
-EXTRAFLAGS = 	-I..\raw
+EXTRAFLAGS = 	-I..\raw -I..\vrt -I..\..\ogr\ogrsf_frmts\geojson -I..\..\ogr\ogrsf_frmts\geojson\libjson
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
diff --git a/frmts/pds/nasakeywordhandler.cpp b/frmts/pds/nasakeywordhandler.cpp
index f3cea30..0da3374 100644
--- a/frmts/pds/nasakeywordhandler.cpp
+++ b/frmts/pds/nasakeywordhandler.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pdsdataset.cpp 12658 2007-11-07 23:14:33Z warmerdam $
  *
  * Project:  PDS Driver; Planetary Data System Format
  * Purpose:  Implementation of NASAKeywordHandler - a class to read
@@ -9,6 +8,7 @@
  ******************************************************************************
  * Copyright (c) 2006, Frank Warmerdam <warmerdam at pobox.com>
  * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2017 Hobu Inc
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -52,6 +52,10 @@
 
 #include "cpl_string.h"
 #include "nasakeywordhandler.h"
+#include "ogrgeojsonreader.h"
+#include "ogr_json_header.h"
+
+CPL_CVSID("$Id: nasakeywordhandler.cpp 37651 2017-03-08 18:26:09Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -65,9 +69,10 @@
 
 NASAKeywordHandler::NASAKeywordHandler() :
     papszKeywordList(NULL),
-    pszHeaderNext(NULL)
-{
-}
+    pszHeaderNext(NULL),
+    poJSon(NULL),
+    m_bStripSurroundingQuotes(false)
+{}
 
 /************************************************************************/
 /*                        ~NASAKeywordHandler()                         */
@@ -78,6 +83,8 @@ NASAKeywordHandler::~NASAKeywordHandler()
 {
     CSLDestroy( papszKeywordList );
     papszKeywordList = NULL;
+    if( poJSon )
+        json_object_put(poJSon);
 }
 
 /************************************************************************/
@@ -88,7 +95,7 @@ int NASAKeywordHandler::Ingest( VSILFILE *fp, int nOffset )
 
 {
 /* -------------------------------------------------------------------- */
-/*      Read in buffer till we find END all on it's own line.           */
+/*      Read in buffer till we find END all on its own line.            */
 /* -------------------------------------------------------------------- */
     if( VSIFSeekL( fp, nOffset, SEEK_SET ) != 0 )
         return FALSE;
@@ -105,7 +112,7 @@ int NASAKeywordHandler::Ingest( VSILFILE *fp, int nOffset )
         if( nBytesRead < 512 )
             break;
 
-        const char *pszCheck;
+        const char *pszCheck = NULL;
         if( osHeaderText.size() > 520 )
             pszCheck = osHeaderText.c_str() + (osHeaderText.size() - 520);
         else
@@ -120,29 +127,68 @@ int NASAKeywordHandler::Ingest( VSILFILE *fp, int nOffset )
 
     pszHeaderNext = osHeaderText.c_str();
 
+    poJSon = json_object_new_object();
+
 /* -------------------------------------------------------------------- */
 /*      Process name/value pairs, keeping track of a "path stack".      */
 /* -------------------------------------------------------------------- */
-    return ReadGroup( "" );
+    return ReadGroup( "", poJSon );
 }
 
 /************************************************************************/
 /*                             ReadGroup()                              */
 /************************************************************************/
 
-int NASAKeywordHandler::ReadGroup( const char *pszPathPrefix )
+int NASAKeywordHandler::ReadGroup( const char *pszPathPrefix, json_object* poCur )
 
 {
     for( ; true; )
     {
         CPLString osName, osValue;
-        if( !ReadPair( osName, osValue ) )
+        if( !ReadPair( osName, osValue, poCur ) )
             return FALSE;
 
         if( EQUAL(osName,"OBJECT") || EQUAL(osName,"GROUP") )
         {
-            if( !ReadGroup( (CPLString(pszPathPrefix) + osValue + ".").c_str() ) )
+            json_object* poNewGroup = json_object_new_object();
+            json_object_object_add(poNewGroup, "_type",
+                json_object_new_string( EQUAL(osName,"OBJECT") ?
+                                                    "object" : "group" ) );
+            if( !ReadGroup( (CPLString(pszPathPrefix) + osValue + ".").c_str(),
+                            poNewGroup ) )
+            {
+                json_object_put(poNewGroup);
                 return FALSE;
+            }
+            json_object* poName = NULL;
+            if( (osValue == "Table" || osValue == "Field") &&
+                (poName = CPL_json_object_object_get(poNewGroup, "Name")) != NULL &&
+                json_object_get_type(poName) == json_type_string )
+            {
+                json_object_object_add(poCur,
+                    (osValue + "_" + json_object_get_string(poName)).c_str(),
+                    poNewGroup);
+                json_object_object_add(poNewGroup, "_container_name",
+                                       json_object_new_string(osValue));
+            }
+            else if( CPL_json_object_object_get(poCur, osValue) != NULL )
+            {
+                int nIter = 2;
+                while( CPL_json_object_object_get(poCur,
+                        (osValue + CPLSPrintf("_%d", nIter)).c_str()) != NULL )
+                {
+                    nIter ++;
+                }
+                json_object_object_add(poCur,
+                    (osValue + CPLSPrintf("_%d", nIter)).c_str(),
+                    poNewGroup);
+                json_object_object_add(poNewGroup, "_container_name",
+                                       json_object_new_string(osValue));
+            }
+            else
+            {
+                json_object_object_add(poCur, osValue.c_str(), poNewGroup);
+            }
         }
         else if( EQUAL(osName,"END")
                  || EQUAL(osName,"END_GROUP" )
@@ -167,7 +213,8 @@ int NASAKeywordHandler::ReadGroup( const char *pszPathPrefix )
 /*      Returns TRUE on success.                                        */
 /************************************************************************/
 
-int NASAKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue )
+int NASAKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue,
+                                  json_object* poCur )
 
 {
     osName = "";
@@ -195,40 +242,59 @@ int NASAKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue )
     SkipWhite();
 
     osValue = "";
+    bool bIsString = true;
 
-    // Handle value lists like:     Name   = (Red, Red)
-    if( *pszHeaderNext == '(' )
+    // Handle value lists like:     Name   = (Red, Red) or  {Red, Red}
+    json_object* poArray = NULL;
+    if( *pszHeaderNext == '(' || *pszHeaderNext == '{' )
     {
+        const char chBeginList = *pszHeaderNext;
+        const char chEndList = *pszHeaderNext == '(' ? ')' : '}';
         CPLString osWord;
 
-        while( ReadWord( osWord ) )
-        {
-            SkipWhite();
+        poArray = json_object_new_array();
 
-            osValue += osWord;
-            if( osWord[strlen(osWord)-1] == ')' )
-                break;
-        }
-    }
-
-    // Handle value lists like:     Name   = {Red, Red}
-    else if( *pszHeaderNext == '{' )
-    {
-        CPLString osWord;
-
-        while( ReadWord( osWord ) )
+        bool bFirst = true;
+        bool bEndOfList = false;
+        pszHeaderNext ++; // skip ( or {
+        while( ReadWord( osWord, m_bStripSurroundingQuotes,
+                         true, &bIsString, &bEndOfList,
+                         chEndList ) )
         {
             SkipWhite();
 
+            if( bIsString )
+            {
+                json_object_array_add( poArray,
+                                json_object_new_string( osWord.c_str() ) );
+            }
+            else  if( CPLGetValueType(osWord) == CPL_VALUE_INTEGER )
+            {
+                json_object_array_add( poArray,
+                    json_object_new_int(atoi(osWord.c_str())) );
+            }
+            else
+            {
+                json_object_array_add( poArray,
+                    json_object_new_double(CPLAtof(osWord.c_str())));
+            }
+
+            if( bFirst )
+                osValue += chBeginList;
             osValue += osWord;
-            if( osWord[strlen(osWord)-1] == '}' )
+            bFirst = false;
+            if( bEndOfList )
+            {
+                osValue += chEndList;
                 break;
+            }
+            osValue += ",";
         }
     }
 
     else // Handle more normal "single word" values.
     {
-        if( !ReadWord( osValue ) )
+        if( !ReadWord( osValue, m_bStripSurroundingQuotes, false, &bIsString ) )
             return FALSE;
     }
 
@@ -236,23 +302,90 @@ int NASAKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue )
 
     // No units keyword?
     if( *pszHeaderNext != '<' )
+    {
+        if( !EQUAL(osName, "OBJECT") && !EQUAL(osName, "GROUP") )
+        {
+            if( poArray )
+            {
+                json_object_object_add( poCur, osName.c_str(), poArray );
+            }
+            else
+            {
+                if( bIsString )
+                {
+                    json_object_object_add( poCur, osName.c_str(),
+                        json_object_new_string(osValue.c_str()) );
+                }
+                else if( CPLGetValueType(osValue) == CPL_VALUE_INTEGER )
+                {
+                    json_object_object_add( poCur, osName.c_str(),
+                        json_object_new_int(atoi(osValue.c_str())) );
+                }
+                else
+                {
+                    json_object_object_add( poCur, osName.c_str(),
+                        json_object_new_double(CPLAtof(osValue.c_str())));
+                }
+            }
+        }
+        else if ( poArray )
+        {
+            json_object_put( poArray );
+        }
         return TRUE;
+    }
 
+    CPLString osValueNoUnit(osValue);
     // Append units keyword.  For lines that like like this:
     //  MAP_RESOLUTION               = 4.0 <PIXEL/DEGREE>
 
     osValue += " ";
 
     CPLString osWord;
+    CPLString osUnit;
     while( ReadWord( osWord ) )
     {
         SkipWhite();
 
         osValue += osWord;
-        if( osWord[strlen(osWord)-1] == '>' )
+        osUnit = osWord;
+        if( osWord.back() == '>' )
             break;
     }
 
+    if( osUnit[0] == '<' )
+        osUnit = osUnit.substr(1);
+    if( !osUnit.empty() && osUnit.back() == '>' )
+        osUnit = osUnit.substr(0, osUnit.size() - 1);
+
+    json_object* poNew = json_object_new_object();
+    json_object_object_add( poCur, osName.c_str(), poNew);
+
+    if( poArray )
+    {
+        json_object_object_add(poNew, "value", poArray);
+    }
+    else
+    {
+        if( bIsString )
+        {
+            json_object_object_add(poNew, "value",
+                               json_object_new_string(osValueNoUnit.c_str()) );
+        }
+        else if( CPLGetValueType(osValueNoUnit) == CPL_VALUE_INTEGER )
+        {
+            json_object_object_add(poNew, "value",
+                            json_object_new_int(atoi(osValueNoUnit.c_str())) );
+        }
+        else
+        {
+            json_object_object_add(poNew, "value",
+                    json_object_new_double(CPLAtof(osValueNoUnit.c_str())) );
+        }
+    }
+    json_object_object_add(poNew, "unit",
+                               json_object_new_string(osUnit.c_str()) );
+
     return TRUE;
 }
 
@@ -261,9 +394,16 @@ int NASAKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue )
 /*  Returns TRUE on success                                             */
 /************************************************************************/
 
-int NASAKeywordHandler::ReadWord( CPLString &osWord )
+int NASAKeywordHandler::ReadWord( CPLString &osWord,
+                                  bool bStripSurroundingQuotes,
+                                  bool bParseList,
+                                  bool* pbIsString,
+                                  bool* pbEndOfList,
+                                  char chEndList )
 
 {
+    if( pbIsString )
+        *pbIsString = false;
     osWord = "";
 
     SkipWhite();
@@ -278,7 +418,11 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
        support them as per ODL, the keyword list doesn't want them */
     if( *pszHeaderNext == '"' )
     {
-        osWord += *(pszHeaderNext++);
+        if( pbIsString )
+            *pbIsString = true;
+        if( !bStripSurroundingQuotes )
+            osWord += *(pszHeaderNext);
+        pszHeaderNext ++;
         while( *pszHeaderNext != '"' )
         {
             if( *pszHeaderNext == '\0' )
@@ -297,7 +441,17 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
             }
             osWord += *(pszHeaderNext++);
         }
-        osWord += *(pszHeaderNext++);
+        if( !bStripSurroundingQuotes )
+            osWord += *(pszHeaderNext);
+        pszHeaderNext ++;
+
+        if( bParseList )
+        {
+            if( pbEndOfList )
+                *pbEndOfList = (*pszHeaderNext == chEndList );
+            if (*pszHeaderNext == ',' || *pszHeaderNext == chEndList )
+                pszHeaderNext ++;
+        }
         return TRUE;
     }
 
@@ -309,7 +463,11 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
     */
     if( *pszHeaderNext == '\'' )
     {
-        osWord += *(pszHeaderNext++);
+        if( pbIsString )
+            *pbIsString = true;
+        if( !bStripSurroundingQuotes )
+            osWord += *(pszHeaderNext);
+        pszHeaderNext ++;
         while( *pszHeaderNext != '\'' )
         {
             if( *pszHeaderNext == '\0' )
@@ -317,7 +475,9 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
 
             osWord += *(pszHeaderNext++);
         }
-        osWord += *(pszHeaderNext++);
+        if( !bStripSurroundingQuotes )
+            osWord += *(pszHeaderNext);
+        pszHeaderNext ++;
         return TRUE;
     }
 
@@ -330,7 +490,8 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
      */
     while( *pszHeaderNext != '\0'
            && *pszHeaderNext != '='
-           && !isspace(static_cast<unsigned char>( *pszHeaderNext ) ) )
+           && ((bParseList && *pszHeaderNext != ',' && *pszHeaderNext != chEndList) ||
+               (!bParseList && !isspace(static_cast<unsigned char>( *pszHeaderNext ) ))) )
     {
         osWord += *pszHeaderNext;
         pszHeaderNext++;
@@ -342,6 +503,15 @@ int NASAKeywordHandler::ReadWord( CPLString &osWord )
             SkipWhite();
         }
     }
+    if( bParseList )
+    {
+        if( pbEndOfList )
+            *pbEndOfList = (*pszHeaderNext == chEndList );
+        if (*pszHeaderNext == ',' || *pszHeaderNext == chEndList )
+            pszHeaderNext ++;
+    }
+    if( pbIsString )
+        *pbIsString = CPLGetValueType(osWord) == CPL_VALUE_STRING;
 
     return TRUE;
 }
@@ -373,17 +543,17 @@ void NASAKeywordHandler::SkipWhite()
             // consume till end of line.
             // reduce sensibility to a label error
             while( *pszHeaderNext != '\0'
-            		&& *pszHeaderNext != 10
-            		&& *pszHeaderNext != 13 )
+                   && *pszHeaderNext != 10
+                   && *pszHeaderNext != 13 )
             {
-            	pszHeaderNext++;
+                pszHeaderNext++;
             }
             continue;
         }
 
         // Skip # style comments
         if( (*pszHeaderNext == 10 || *pszHeaderNext == 13 ||
- 	     *pszHeaderNext == ' ' || *pszHeaderNext == '\t' )
+             *pszHeaderNext == ' ' || *pszHeaderNext == '\t' )
               && pszHeaderNext[1] == '#' )
         {
             pszHeaderNext += 2;
@@ -434,3 +604,14 @@ char **NASAKeywordHandler::GetKeywordList()
 {
     return papszKeywordList;
 }
+
+/************************************************************************/
+/*                               StealJSon()                            */
+/************************************************************************/
+
+json_object* NASAKeywordHandler::StealJSon()
+{
+    json_object* poTmp = poJSon;
+    poJSon = NULL;
+    return poTmp;
+}
diff --git a/frmts/pds/nasakeywordhandler.h b/frmts/pds/nasakeywordhandler.h
index 75af271..249842c 100644
--- a/frmts/pds/nasakeywordhandler.h
+++ b/frmts/pds/nasakeywordhandler.h
@@ -1,27 +1,82 @@
+/******************************************************************************
+ *
+ * Project:  PDS Driver; Planetary Data System Format
+ * Purpose:  Implementation of NASAKeywordHandler - a class to read
+ *           keyword data from PDS, ISIS2 and ISIS3 data products.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2006, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2008-2010, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2017 Hobu Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef NASAKEYWORDHANDLER_H
+#define NASAKEYWORDHANDLER_H
+
+#include "cpl_string.h"
+
+typedef struct json_object json_object;
+
 /************************************************************************/
 /* ==================================================================== */
 /*                          NASAKeywordHandler                          */
 /* ==================================================================== */
 /************************************************************************/
 
-class NASAKeywordHandler
+// Only exported for HDF4 plugin needs. Do not use outside of GDAL please.
+
+class CPL_DLL NASAKeywordHandler
 {
     char     **papszKeywordList;
 
     CPLString osHeaderText;
     const char *pszHeaderNext;
 
+    json_object *poJSon;
+
+    bool m_bStripSurroundingQuotes;
+
     void    SkipWhite();
-    int     ReadWord( CPLString &osWord );
-    int     ReadPair( CPLString &osName, CPLString &osValue );
-    int     ReadGroup( const char *pszPathPrefix );
+    int     ReadWord( CPLString &osWord,
+                      bool bStripSurroundingQuotes = false,
+                      bool bParseList = false,
+                      bool* pbIsString = NULL,
+                      bool* pbEndOfList = NULL,
+                      char chEndList = '\0' );
+    int     ReadPair( CPLString &osName, CPLString &osValue, json_object* poCur );
+    int     ReadGroup( const char *pszPathPrefix, json_object* poCur );
 
 public:
     NASAKeywordHandler();
     ~NASAKeywordHandler();
 
+    void SetStripSurroundingQuotes( bool bStripSurroundingQuotes )
+                { m_bStripSurroundingQuotes = bStripSurroundingQuotes; }
+
     int     Ingest( VSILFILE *fp, int nOffset );
 
     const char *GetKeyword( const char *pszPath, const char *pszDefault );
     char **GetKeywordList();
+    json_object* StealJSon();
 };
+
+#endif //  NASAKEYWORDHANDLER_H
diff --git a/frmts/pds/pdsdataset.cpp b/frmts/pds/pdsdataset.cpp
index fe213ad..8a93b42 100644
--- a/frmts/pds/pdsdataset.cpp
+++ b/frmts/pds/pdsdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pdsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PDS Driver; Planetary Data System Format
  * Purpose:  Implementation of PDSDataset
@@ -48,7 +47,7 @@ static const double NULL3 = -3.4028226550889044521e+38;
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: pdsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: pdsdataset.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 enum PDSLayout
 {
@@ -59,13 +58,13 @@ enum PDSLayout
 
 /************************************************************************/
 /* ==================================================================== */
-/*			       PDSDataset	                        */
+/*                             PDSDataset                               */
 /* ==================================================================== */
 /************************************************************************/
 
 class PDSDataset : public RawDataset
 {
-    VSILFILE	*fpImage;	// image data file.
+    VSILFILE    *fpImage;  // image data file.
     GDALDataset *poCompressedDS;
 
     NASAKeywordHandler  oKeywords;
@@ -81,7 +80,7 @@ class PDSDataset : public RawDataset
 
     void        ParseSRS();
     int         ParseCompressedImage();
-    int	        ParseImage( CPLString osPrefix, CPLString osFilenamePrefix );
+    int         ParseImage( CPLString osPrefix, CPLString osFilenamePrefix );
     static void        CleanString( CPLString &osInput );
 
     const char *GetKeyword( std::string osPath,
@@ -94,26 +93,26 @@ class PDSDataset : public RawDataset
                                const char *pszDefault = "");
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
 public:
     PDSDataset();
-    ~PDSDataset();
+    virtual ~PDSDataset();
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef(void);
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef(void) override;
 
-    virtual char      **GetFileList(void);
+    virtual char      **GetFileList(void) override;
 
     virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
+                                    int, int *, GDALProgressFunc, void * ) override;
 
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               int, int *,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
@@ -261,7 +260,7 @@ CPLErr PDSDataset::IRasterIO( GDALRWFlag eRWFlag,
 const char *PDSDataset::GetProjectionRef()
 
 {
-    if( strlen(osProjection) > 0 )
+    if( !osProjection.empty() )
         return osProjection;
 
     return GDALPamDataset::GetProjectionRef();
@@ -624,7 +623,6 @@ void PDSDataset::ParseSRS()
         bGotTransform =
             GDALReadWorldFile( pszFilename, "wld",
                                adfGeoTransform );
-
 }
 
 /************************************************************************/
@@ -666,9 +664,9 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
     // ^IMAGE = 3
     // ^IMAGE             = "GLOBAL_ALBEDO_8PPD.IMG"
     // ^IMAGE             = "MEGT90N000CB.IMG"
-    // ^IMAGE		  = ("BLAH.IMG",1)	 -- start at record 1 (1 based)
-    // ^IMAGE		  = ("BLAH.IMG")	 -- still start at record 1 (equiv of "BLAH.IMG")
-    // ^IMAGE		  = ("BLAH.IMG", 5 <BYTES>) -- start at byte 5 (the fifth byte in the file)
+    // ^IMAGE             = ("BLAH.IMG",1)       -- start at record 1 (1 based)
+    // ^IMAGE             = ("BLAH.IMG")         -- still start at record 1 (equiv of "BLAH.IMG")
+    // ^IMAGE             = ("BLAH.IMG", 5 <BYTES>) -- start at byte 5 (the fifth byte in the file)
     // ^IMAGE             = 10851 <BYTES>
     // ^SPECTRAL_QUBE = 5  for multi-band images
 
@@ -685,7 +683,7 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
     int nDetachedOffset = 0;
     bool bDetachedOffsetInBytes = false;
 
-    if( osQube.size() && osQube[0] == '(' )
+    if( !osQube.empty() && osQube[0] == '(' )
     {
         osQube = "\"";
         osQube += GetKeywordSub( osPrefix + "^" + osImageKeyword, 1 );
@@ -698,11 +696,11 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
             bDetachedOffsetInBytes = true;
     }
 
-    if( osQube.size() && osQube[0] == '"' )
+    if( !osQube.empty() && osQube[0] == '"' )
     {
         CPLString osFilename = osQube;
         CleanString( osFilename );
-        if( osFilenamePrefix.size() )
+        if( !osFilenamePrefix.empty() )
         {
             osTargetFile = osFilenamePrefix + osFilename;
         }
@@ -740,7 +738,7 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
     /** if not NULL then CORE_ITEMS keyword i.e. (234,322,2)  **/
     /***********************************************************/
     int eLayout = PDS_BSQ; //default to band seq.
-    int	nRows, nCols, l_nBands = 1;
+    int nRows, nCols, l_nBands = 1;
 
     CPLString value = GetKeyword( osPrefix+osImageKeyword+".AXIS_NAME", "" );
     if (EQUAL(value,"(SAMPLE,LINE,BAND)") ) {
@@ -803,18 +801,18 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
     /** if keyword not found leave as "M" or "MSB" **/
 
     CPLString osST = GetKeyword( osPrefix+"IMAGE.SAMPLE_TYPE" );
-    if( osST.size() >= 2 && osST[0] == '"' && osST[osST.size()-1] == '"' )
+    if( osST.size() >= 2 && osST[0] == '"' && osST.back() == '"' )
         osST = osST.substr( 1, osST.size() - 2 );
 
     char chByteOrder = 'M';  //default to MSB
     if( (EQUAL(osST,"LSB_INTEGER")) ||
-        (EQUAL(osST,"LSB")) || // just incase
+        (EQUAL(osST,"LSB")) || // just in case
         (EQUAL(osST,"LSB_UNSIGNED_INTEGER")) ||
         (EQUAL(osST,"LSB_SIGNED_INTEGER")) ||
         (EQUAL(osST,"UNSIGNED_INTEGER")) ||
         (EQUAL(osST,"VAX_REAL")) ||
         (EQUAL(osST,"VAX_INTEGER")) ||
-        (EQUAL(osST,"PC_INTEGER")) ||  //just incase
+        (EQUAL(osST,"PC_INTEGER")) ||  //just in case
         (EQUAL(osST,"PC_REAL")) ) {
         chByteOrder = 'I';
     }
@@ -822,7 +820,8 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
     /**** Grab format type - pds supports 1,2,4,8,16,32,64 (in theory) **/
     /**** I have only seen 8, 16, 32 (float) in released datasets      **/
     GDALDataType eDataType = GDT_Byte;
-    int nSuffixItems = 0, nSuffixLines = 0;
+    int nSuffixItems = 0;
+    int nSuffixLines = 0;
     int nSuffixBytes = 4; // Default as per PDS specification
     double dfNoData = 0.0;
     double dfScale = 1.0;
@@ -831,7 +830,7 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
     const char *pszDesc = NULL;
 
     CPLString osSB = GetKeyword(osPrefix+"IMAGE.SAMPLE_BITS","");
-    if ( osSB.size() > 0 )
+    if ( !osSB.empty() )
     {
         const int itype = atoi(osSB);
         switch(itype) {
@@ -895,10 +894,10 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
 
         /* Parse suffix dimensions if defined. */
         value = GetKeyword( osPrefix + "SPECTRAL_QUBE.SUFFIX_ITEMS", "" );
-        if ( value.size() > 0 )
+        if ( !value.empty() )
         {
             value = GetKeyword(osPrefix + "SPECTRAL_QUBE.SUFFIX_BYTES", "");
-            if ( value.size() > 0 )
+            if ( !value.empty() )
                 nSuffixBytes = atoi( value );
 
             nSuffixItems = atoi(
@@ -908,7 +907,7 @@ int PDSDataset::ParseImage( CPLString osPrefix, CPLString osFilenamePrefix )
         }
 
         value = GetKeyword( osPrefix + "SPECTRAL_QUBE.CORE_NULL", "" );
-        if ( value.size() > 0 )
+        if ( !value.empty() )
             dfNoData = CPLAtofM( value );
 
         dfOffset = CPLAtofM(
@@ -1085,7 +1084,7 @@ class PDSWrapperRasterBand : public GDALProxyRasterBand
   GDALRasterBand* poBaseBand;
 
   protected:
-    virtual GDALRasterBand* RefUnderlyingRasterBand() { return poBaseBand; }
+    virtual GDALRasterBand* RefUnderlyingRasterBand() override { return poBaseBand; }
 
   public:
     explicit PDSWrapperRasterBand( GDALRasterBand* poBaseBandIn )
@@ -1199,7 +1198,7 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
     CleanString( osCompressedFilename );
 
     CPLString osUncompressedFilename = poDS->GetKeyword( "UNCOMPRESSED_FILE.IMAGE.NAME", "");
-    if( osUncompressedFilename.size() == 0 )
+    if( osUncompressedFilename.empty() )
         osUncompressedFilename = poDS->GetKeyword( "UNCOMPRESSED_FILE.FILE_NAME", "");
     CleanString( osUncompressedFilename );
 
@@ -1207,8 +1206,8 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLString osFilenamePrefix;
 
     if( EQUAL(osEncodingType, "ZIP") &&
-        osCompressedFilename.size() != 0 &&
-        osUncompressedFilename.size() != 0 )
+        !osCompressedFilename.empty() &&
+        !osUncompressedFilename.empty() )
     {
         const CPLString osPath = CPLGetPath(poDS->GetDescription());
         osCompressedFilename = CPLFormFilename( osPath, osCompressedFilename, NULL );
@@ -1222,7 +1221,7 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
         osEncodingType = "";
     }
 
-    if( osEncodingType.size() != 0 )
+    if( !osEncodingType.empty() )
     {
         if( !poDS->ParseCompressedImage() )
         {
@@ -1278,7 +1277,7 @@ GDALDataset *PDSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1362,8 +1361,8 @@ void PDSDataset::CleanString( CPLString &osInput )
 
 {
    if(  ( osInput.size() < 2 ) ||
-        ((osInput.at(0) != '"'   || osInput.at(osInput.size()-1) != '"' ) &&
-        ( osInput.at(0) != '\'' || osInput.at(osInput.size()-1) != '\'')) )
+        ((osInput.at(0) != '"'   || osInput.back() != '"' ) &&
+        ( osInput.at(0) != '\'' || osInput.back() != '\'')) )
         return;
 
     char *pszWrk = CPLStrdup(osInput.c_str() + 1);
diff --git a/frmts/pds/vicardataset.cpp b/frmts/pds/vicardataset.cpp
index 2ddc557..547eeb4 100644
--- a/frmts/pds/vicardataset.cpp
+++ b/frmts/pds/vicardataset.cpp
@@ -40,19 +40,19 @@ static const double NULL3 = -32768.0;
 
 #include <string>
 
-CPL_CVSID("$Id: vicardataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: vicardataset.cpp 37007 2016-12-24 14:04:10Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*			       VICARDataset		                */
+/*                             VICARDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
 class VICARDataset : public RawDataset
 {
-    VSILFILE	*fpImage;
+    VSILFILE    *fpImage;
 
-    GByte	abyHeader[10000];
+    GByte       abyHeader[10000];
     CPLString   osExternalCube;
 
     VICARKeywordHandler  oKeywords;
@@ -67,19 +67,18 @@ class VICARDataset : public RawDataset
 
 public:
     VICARDataset();
-    ~VICARDataset();
+    virtual ~VICARDataset();
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef(void);
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef(void) override;
 
-    virtual char **GetFileList();
+    virtual char **GetFileList() override;
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszParmList );
-
 };
 
 /************************************************************************/
@@ -96,6 +95,7 @@ VICARDataset::VICARDataset() :
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+    memset( abyHeader, 0, sizeof(abyHeader) );
 }
 
 /************************************************************************/
@@ -119,7 +119,7 @@ char **VICARDataset::GetFileList()
 {
     char **papszFileList = GDALPamDataset::GetFileList();
 
-    if( strlen(osExternalCube) > 0 )
+    if( !osExternalCube.empty() )
         papszFileList = CSLAddString( papszFileList, osExternalCube );
 
     return papszFileList;
@@ -132,7 +132,7 @@ char **VICARDataset::GetFileList()
 const char *VICARDataset::GetProjectionRef()
 
 {
-    if( strlen(osProjection) > 0 )
+    if( !osProjection.empty() )
         return osProjection;
 
     return GDALPamDataset::GetProjectionRef();
@@ -164,12 +164,13 @@ int VICARDataset::Identify( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->pabyHeader == NULL )
         return FALSE;
 
+    char *pszHeader = reinterpret_cast<char *>(poOpenInfo->pabyHeader);
     return
-        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "LBLSIZE" ) != NULL &&
-        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "FORMAT" ) != NULL &&
-        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "NL" ) != NULL &&
-        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "NS" ) != NULL &&
-        strstr(reinterpret_cast<char *>( poOpenInfo->pabyHeader ), "NB" ) != NULL;
+        strstr(pszHeader, "LBLSIZE") != NULL &&
+        strstr(pszHeader, "FORMAT") != NULL &&
+        strstr(pszHeader, "NL") != NULL &&
+        strstr(pszHeader, "NS") != NULL &&
+        strstr(pszHeader, "NB") != NULL;
 }
 
 /************************************************************************/
@@ -179,7 +180,7 @@ int VICARDataset::Identify( GDALOpenInfo * poOpenInfo )
 GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
 {
 /* -------------------------------------------------------------------- */
-/*      Does this look like a VICAR dataset?                             */
+/*      Does this look like a VICAR dataset?                            */
 /* -------------------------------------------------------------------- */
     if( !Identify( poOpenInfo ) )
         return NULL;
@@ -593,7 +594,7 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     for( int i = 0; i < nBands; i++ )
     {
-        GDALRasterBand	*poBand
+        GDALRasterBand *poBand
             = new RawRasterBand( poDS, i+1, poDS->fpImage, nSkipBytes + nBandOffset * i,
                                  static_cast<int>(nPixelOffset), static_cast<int>(nLineOffset), eDataType,
 #ifdef CPL_LSB
@@ -637,7 +638,6 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
                 poBand->SetStatistics(CPLAtofM(pszMin),CPLAtofM(pszMax),CPLAtofM(pszMean),CPLAtofM(pszStdDev));
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Instrument-specific keywords as metadata.                       */
 /* -------------------------------------------------------------------- */
@@ -700,7 +700,6 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-
 /******************   DAWN   ******************************/
     else if (EQUAL( poDS->GetKeyword( "INSTRUMENT_ID"), "FC2" )) {
         poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" );
@@ -725,9 +724,9 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
             if( pszKeywordValue != NULL )
                 poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
         }
-
     }
-    else if (bIsDTM && EQUAL( poDS->GetKeyword( "TARGET_NAME"), "VESTA" )) {
+    else if (bIsDTM && EQUAL( poDS->GetKeyword( "TARGET_NAME"), "VESTA" ))
+    {
         poDS->SetMetadataItem( "SPACECRAFT_NAME", "DAWN" );
         poDS->SetMetadataItem( "PRODUCT_TYPE", "DTM");
         static const char * const apszKeywords[] = {
@@ -737,14 +736,14 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
             "POSITIVE_LONGITUDE_DIRECTION", "MAP_SCALE",
             "CENTER_LONGITUDE", "LINE_PROJECTION_OFFSET", "SAMPLE_PROJECTION_OFFSET",
             NULL };
-        for( int i = 0; apszKeywords[i] != NULL; i++ ) {
+        for( int i = 0; apszKeywords[i] != NULL; i++ )
+        {
             const char *pszKeywordValue = poDS->GetKeyword( apszKeywords[i] );
             if( pszKeywordValue != NULL )
                 poDS->SetMetadataItem( apszKeywords[i], pszKeywordValue );
         }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      END Instrument-specific keywords as metadata.                   */
 /* -------------------------------------------------------------------- */
@@ -764,7 +763,7 @@ GDALDataset *VICARDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/pds/vicarkeywordhandler.cpp b/frmts/pds/vicarkeywordhandler.cpp
index 991e4c5..de7a9ce 100644
--- a/frmts/pds/vicarkeywordhandler.cpp
+++ b/frmts/pds/vicarkeywordhandler.cpp
@@ -29,10 +29,13 @@
 * DEALINGS IN THE SOFTWARE.
 ****************************************************************************/
 
-
 #include "cpl_string.h"
 #include "vicarkeywordhandler.h"
 
+#include <algorithm>
+
+CPL_CVSID("$Id: vicarkeywordhandler.cpp 36981 2016-12-20 19:46:41Z rouault $");
+
 /************************************************************************/
 /* ==================================================================== */
 /*                          VICARKeywordHandler                         */
@@ -47,7 +50,7 @@ VICARKeywordHandler::VICARKeywordHandler() :
     papszKeywordList(NULL),
     pszHeaderNext(NULL),
     LabelSize(0)
-{ }
+{}
 
 /************************************************************************/
 /*                        ~VICARKeywordHandler()                        */
@@ -67,7 +70,7 @@ int VICARKeywordHandler::Ingest( VSILFILE *fp, GByte *pabyHeader )
 
 {
 /* -------------------------------------------------------------------- */
-/*      Read in buffer till we find END all on it's own line.           */
+/*      Read in buffer till we find END all on its own line.            */
 /* -------------------------------------------------------------------- */
     if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
         return FALSE;
@@ -89,8 +92,10 @@ int VICARKeywordHandler::Ingest( VSILFILE *fp, GByte *pabyHeader )
         return FALSE;
 
     char keyval[100];
-    strncpy( keyval, pch1, MIN( static_cast<size_t>(pch2-pch1), sizeof(keyval)-1 ) );
-    keyval[MIN( static_cast<size_t>(pch2-pch1), sizeof(keyval)-1 )] = '\0';
+    strncpy( keyval, pch1, std::min(static_cast<size_t>(pch2 - pch1),
+                                    sizeof(keyval) - 1) );
+    keyval[std::min(static_cast<size_t>(pch2 - pch1),
+                    sizeof(keyval) - 1)] = '\0';
     LabelSize = atoi( keyval );
     if( LabelSize <= 0 || LabelSize > 10 * 1024 * 124 )
         return FALSE;
@@ -114,9 +119,7 @@ int VICARKeywordHandler::Ingest( VSILFILE *fp, GByte *pabyHeader )
 /* -------------------------------------------------------------------- */
 /*      Now check for the Vicar End-of-Dataset Label...                 */
 /* -------------------------------------------------------------------- */
-    const char *pszResult;
-
-    pszResult = CSLFetchNameValue( papszKeywordList, "EOL" );
+    const char *pszResult = CSLFetchNameValue( papszKeywordList, "EOL" );
 
     if( pszResult == NULL )
     {
@@ -183,8 +186,9 @@ int VICARKeywordHandler::Ingest( VSILFILE *fp, GByte *pabyHeader )
         CPLError(CE_Failure, CPLE_AppDefined, "END-OF-DATASET LABEL NOT FOUND!");
         return FALSE;
     }
-    strncpy( keyval, pch1, MIN( static_cast<size_t>(pch2-pch1), sizeof(keyval)-1 ) );
-    keyval[MIN( static_cast<size_t>(pch2-pch1), sizeof(keyval)-1 )] = '\0';
+    strncpy( keyval, pch1, std::min(static_cast<size_t>(pch2 - pch1),
+                                    sizeof(keyval) - 1 ) );
+    keyval[std::min( static_cast<size_t>(pch2-pch1), sizeof(keyval)-1 )] = '\0';
 
     int EOLabelSize = atoi( keyval );
     if( EOLabelSize <= 0 || EOLabelSize > 100 * 1024 * 1024 )
@@ -229,7 +233,6 @@ int VICARKeywordHandler::ReadGroup( CPL_UNUSED const char *pszPathPrefix ) {
     }
 }
 
-
 /************************************************************************/
 /*                              ReadPair()                              */
 /*                                                                      */
@@ -265,7 +268,7 @@ int VICARKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue ) {
         {
             osValue += osWord;
             if ( osWord.size() < 2 ) continue;
-            if( osWord[osWord.size()-1] == ')' && osWord[osWord.size()-2] == '\'' ) break;
+            if( osWord.back() == ')' && osWord[osWord.size()-2] == '\'' ) break;
         }
     }
 
@@ -278,15 +281,13 @@ int VICARKeywordHandler::ReadPair( CPLString &osName, CPLString &osValue ) {
             SkipWhite();
 
             osValue += osWord;
-            if( osWord.size() && osWord[osWord.size()-1] == ')'  ) break;
+            if( !osWord.empty() && osWord.back() == ')'  ) break;
         }
     }
-
     else
     {
         if( !ReadWord( osValue ) )
             return FALSE;
-
     }
 
     SkipWhite();
diff --git a/frmts/plmosaic/GNUmakefile b/frmts/plmosaic/GNUmakefile
index 0cc74c5..8c098ad 100644
--- a/frmts/plmosaic/GNUmakefile
+++ b/frmts/plmosaic/GNUmakefile
@@ -3,7 +3,7 @@ include ../../GDALmake.opt
 
 OBJ	=	plmosaicdataset.o
 
-CPPFLAGS	:=	 $(JSON_INCLUDE) $(CPPFLAGS) 
+CPPFLAGS	:=	  -I../../ogr/ogrsf_frmts/geojson $(JSON_INCLUDE) $(CPPFLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/plmosaic/plmosaicdataset.cpp b/frmts/plmosaic/plmosaicdataset.cpp
index 701b264..511a97c 100644
--- a/frmts/plmosaic/plmosaicdataset.cpp
+++ b/frmts/plmosaic/plmosaicdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: plmosaicdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  PLMosaic driver
  * Purpose:  PLMosaic driver
@@ -35,9 +34,9 @@
 #include "ogr_spatialref.h"
 #include "ogrsf_frmts.h"
 
-#include <json.h>
+#include "ogrgeojsonreader.h"
 
-CPL_CVSID("$Id: plmosaicdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: plmosaicdataset.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 // g++ -fPIC -g -Wall frmts/plmosaic/*.cpp -shared -o gdal_PLMOSAIC.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/geojson/libjson -L. -lgdal
 
@@ -114,7 +113,7 @@ class PLMosaicDataset : public GDALPamDataset
 
   public:
                 PLMosaicDataset();
-                ~PLMosaicDataset();
+    virtual  ~PLMosaicDataset();
 
     static int Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset  *Open( GDALOpenInfo * );
@@ -126,12 +125,12 @@ class PLMosaicDataset : public GDALPamDataset
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg) override;
 
-    virtual void FlushCache(void);
+    virtual void FlushCache(void) override;
 
-    virtual const char *GetProjectionRef();
-    virtual CPLErr      GetGeoTransform(double* padfGeoTransform);
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr      GetGeoTransform(double* padfGeoTransform) override;
 
     GDALDataset        *GetMetaTile(int tile_x, int tile_y);
 };
@@ -151,24 +150,23 @@ class PLMosaicRasterBand : public GDALRasterBand
                 PLMosaicRasterBand( PLMosaicDataset * poDS, int nBand,
                                     GDALDataType eDataType );
 
-    virtual CPLErr          IReadBlock( int, int, void * );
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
     virtual CPLErr          IRasterIO( GDALRWFlag eRWFlag,
                                   int nXOff, int nYOff, int nXSize, int nYSize,
                                   void * pData, int nBufXSize, int nBufYSize,
                                   GDALDataType eBufType,
                                   GSpacing nPixelSpace, GSpacing nLineSpace,
-                                  GDALRasterIOExtraArg* psExtraArg);
+                                  GDALRasterIOExtraArg* psExtraArg) override;
 
     virtual const char     *GetMetadataItem( const char* pszName,
-                                             const char * pszDomain = "" );
+                                             const char * pszDomain = "" ) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual GDALColorInterp GetColorInterpretation() override;
 
-    virtual int             GetOverviewCount();
-    virtual GDALRasterBand* GetOverview(int iOvrLevel);
+    virtual int             GetOverviewCount() override;
+    virtual GDALRasterBand* GetOverview(int iOvrLevel) override;
 };
 
-
 /************************************************************************/
 /*                        PLMosaicRasterBand()                          */
 /************************************************************************/
@@ -177,12 +175,12 @@ PLMosaicRasterBand::PLMosaicRasterBand( PLMosaicDataset *poDSIn, int nBandIn,
                                         GDALDataType eDataTypeIn )
 
 {
-    this->eDataType = eDataTypeIn;
+    eDataType = eDataTypeIn;
     nBlockXSize = 256;
     nBlockYSize = 256;
 
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     if( eDataType == GDT_UInt16 )
     {
@@ -275,7 +273,6 @@ const char* PLMosaicRasterBand::GetMetadataItem( const char* pszName,
     return GDALRasterBand::GetMetadataItem(pszName, pszDomain);
 }
 
-
 /************************************************************************/
 /*                         GetOverviewCount()                           */
 /************************************************************************/
@@ -321,7 +318,7 @@ GDALColorInterp PLMosaicRasterBand::GetColorInterpretation()
         case 4:
             return GCI_AlphaBand;
         default:
-            CPLAssert(FALSE);
+            CPLAssert(false);
             return GCI_GrayIndex;
     }
 }
@@ -452,7 +449,7 @@ CPLHTTPResult* PLMosaicDataset::Download(const char* pszURL,
                                          int bQuiet404Error)
 {
     char** papszOptions = CSLAddString(GetBaseHTTPOptions(), NULL);
-    CPLHTTPResult * psResult;
+    CPLHTTPResult *psResult = NULL;
     if( STARTS_WITH(osBaseURL, "/vsimem/") &&
         STARTS_WITH(pszURL, "/vsimem/") )
     {
@@ -461,7 +458,7 @@ CPLHTTPResult* PLMosaicDataset::Download(const char* pszURL,
             CPLCalloc( 1, sizeof( CPLHTTPResult ) ) );
         vsi_l_offset nDataLength = 0;
         CPLString osURL(pszURL);
-        if( osURL[osURL.size()-1 ] == '/' )
+        if( osURL.back() == '/' )
             osURL.resize(osURL.size()-1);
         GByte* pabyBuf = VSIGetMemFileBuffer(osURL, &nDataLength, FALSE);
         if( pabyBuf )
@@ -585,7 +582,7 @@ GDALDataset *PLMosaicDataset::Open( GDALOpenInfo * poOpenInfo )
             poOpenInfo->pszFilename+strlen("PLMosaic:"), ",", TRUE, FALSE );
     for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
     {
-        char* pszKey;
+        char* pszKey = NULL;
         const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
         if( pszValue != NULL )
         {
@@ -608,7 +605,7 @@ GDALDataset *PLMosaicDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->osAPIKey = PLMosaicGetParameter(poOpenInfo, papszOptions, "api_key",
                                           CPLGetConfigOption("PL_API_KEY",""));
 
-    if( poDS->osAPIKey.size() == 0 )
+    if( poDS->osAPIKey.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Missing PL_API_KEY configuration option or API_KEY open option");
@@ -631,7 +628,7 @@ GDALDataset *PLMosaicDataset::Open( GDALOpenInfo * poOpenInfo )
     CSLDestroy(papszOptions);
     papszOptions = NULL;
 
-    if( poDS->osMosaic.size() )
+    if( !poDS->osMosaic.empty() )
     {
         if( !poDS->OpenMosaic() )
         {
@@ -667,7 +664,7 @@ GDALDataset *PLMosaicDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS )
         poDS->SetPamFlags(0);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -693,7 +690,7 @@ static void ReplaceSubString(CPLString &osTarget,
 
 CPLString PLMosaicDataset::GetMosaicCachePath()
 {
-    if( osCachePathRoot.size() )
+    if( !osCachePathRoot.empty() )
     {
         const CPLString osCachePath(
             CPLFormFilename(osCachePathRoot, "plmosaic_cache", NULL));
@@ -711,7 +708,7 @@ CPLString PLMosaicDataset::GetMosaicCachePath()
 
 void PLMosaicDataset::CreateMosaicCachePathIfNecessary()
 {
-    if( osCachePathRoot.size() )
+    if( !osCachePathRoot.empty() )
     {
         const CPLString osCachePath(
             CPLFormFilename(osCachePathRoot, "plmosaic_cache", NULL));
@@ -737,7 +734,7 @@ void PLMosaicDataset::CreateMosaicCachePathIfNecessary()
 int PLMosaicDataset::OpenMosaic()
 {
     CPLString osURL(osBaseURL);
-    if( osURL[osURL.size()-1] != '/' )
+    if( osURL.back() != '/' )
         osURL += '/';
     osURL += osMosaic;
     json_object* poObj = RunRequest(osURL);
@@ -746,18 +743,18 @@ int PLMosaicDataset::OpenMosaic()
         return FALSE;
     }
 
-    json_object* poCoordinateSystem = json_object_object_get(poObj, "coordinate_system");
-    json_object* poDataType = json_object_object_get(poObj, "datatype");
-    json_object* poQuadPattern = json_object_object_get(poObj, "quad_pattern");
-    json_object* poQuadSize = json_object_object_get(poObj, "quad_size");
-    json_object* poResolution = json_object_object_get(poObj, "resolution");
-    json_object* poLinks = json_object_object_get(poObj, "links");
+    json_object* poCoordinateSystem = CPL_json_object_object_get(poObj, "coordinate_system");
+    json_object* poDataType = CPL_json_object_object_get(poObj, "datatype");
+    json_object* poQuadPattern = CPL_json_object_object_get(poObj, "quad_pattern");
+    json_object* poQuadSize = CPL_json_object_object_get(poObj, "quad_size");
+    json_object* poResolution = CPL_json_object_object_get(poObj, "resolution");
+    json_object* poLinks = CPL_json_object_object_get(poObj, "links");
     json_object* poLinksQuads = NULL;
     json_object* poLinksTiles = NULL;
     if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object )
     {
-        poLinksQuads = json_object_object_get(poLinks, "quads");
-        poLinksTiles = json_object_object_get(poLinks, "tiles");
+        poLinksQuads = CPL_json_object_object_get(poLinks, "quads");
+        poLinksTiles = CPL_json_object_object_get(poLinks, "tiles");
     }
     if( poCoordinateSystem == NULL || json_object_get_type(poCoordinateSystem) != json_type_string ||
         poDataType == NULL || json_object_get_type(poDataType) != json_type_string ||
@@ -866,7 +863,7 @@ int PLMosaicDataset::OpenMosaic()
         else
         {
             CPLString osCacheStr;
-            if( osCachePathRoot.size() )
+            if( !osCachePathRoot.empty() )
             {
                 osCacheStr = "    <Cache><Path>";
                 osCacheStr += GetMosaicCachePath();
@@ -934,25 +931,24 @@ int PLMosaicDataset::OpenMosaic()
     for(int i=0;i<4;i++)
         SetBand(i + 1, new PLMosaicRasterBand(this, i + 1, eDT));
 
-    json_object* poFirstAcquired = json_object_object_get(poObj, "first_acquired");
+    json_object* poFirstAcquired = CPL_json_object_object_get(poObj, "first_acquired");
     if( poFirstAcquired != NULL && json_object_get_type(poFirstAcquired) == json_type_string )
     {
         SetMetadataItem("FIRST_ACQUIRED",
                                  json_object_get_string(poFirstAcquired));
     }
-    json_object* poLastAcquired = json_object_object_get(poObj, "last_acquired");
+    json_object* poLastAcquired = CPL_json_object_object_get(poObj, "last_acquired");
     if( poLastAcquired != NULL && json_object_get_type(poLastAcquired) == json_type_string )
     {
         SetMetadataItem("LAST_ACQUIRED",
                                  json_object_get_string(poLastAcquired));
     }
-    json_object* poTitle = json_object_object_get(poObj, "title");
+    json_object* poTitle = CPL_json_object_object_get(poObj, "title");
     if( poTitle != NULL && json_object_get_type(poTitle) == json_type_string )
     {
         SetMetadataItem("TITLE", json_object_get_string(poTitle));
     }
 
-
     json_object_put(poObj);
     return TRUE;
 }
@@ -974,17 +970,17 @@ int PLMosaicDataset::ListSubdatasets()
         }
 
         osURL = "";
-        json_object* poLinks = json_object_object_get(poObj, "links");
+        json_object* poLinks = CPL_json_object_object_get(poObj, "links");
         if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object )
         {
-            json_object* poNext = json_object_object_get(poLinks, "next");
+            json_object* poNext = CPL_json_object_object_get(poLinks, "next");
             if( poNext != NULL && json_object_get_type(poNext) == json_type_string )
             {
                 osURL = json_object_get_string(poNext);
             }
         }
 
-        json_object* poMosaics = json_object_object_get(poObj, "mosaics");
+        json_object* poMosaics = CPL_json_object_object_get(poObj, "mosaics");
         if( poMosaics == NULL || json_object_get_type(poMosaics) != json_type_array )
         {
             json_object_put(poObj);
@@ -1001,26 +997,26 @@ int PLMosaicDataset::ListSubdatasets()
             json_object* poMosaic = json_object_array_get_idx(poMosaics, i);
             if( poMosaic && json_object_get_type(poMosaic) == json_type_object )
             {
-                json_object* poName = json_object_object_get(poMosaic, "name");
+                json_object* poName = CPL_json_object_object_get(poMosaic, "name");
                 if( poName != NULL && json_object_get_type(poName) == json_type_string )
                 {
                     pszName = json_object_get_string(poName);
                 }
-                json_object* poTitle = json_object_object_get(poMosaic, "title");
+                json_object* poTitle = CPL_json_object_object_get(poMosaic, "title");
                 if( poTitle != NULL && json_object_get_type(poTitle) == json_type_string )
                 {
                     pszTitle = json_object_get_string(poTitle);
                 }
-                poLinks = json_object_object_get(poMosaic, "links");
+                poLinks = CPL_json_object_object_get(poMosaic, "links");
                 if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object )
                 {
-                    json_object* poSelf = json_object_object_get(poLinks, "self");
+                    json_object* poSelf = CPL_json_object_object_get(poLinks, "self");
                     if( poSelf != NULL && json_object_get_type(poSelf) == json_type_string )
                     {
                         pszSelf = json_object_get_string(poSelf);
                     }
                 }
-                json_object* poCoordinateSystem = json_object_object_get(poMosaic, "coordinate_system");
+                json_object* poCoordinateSystem = CPL_json_object_object_get(poMosaic, "coordinate_system");
                 if( poCoordinateSystem && json_object_get_type(poCoordinateSystem) == json_type_string )
                 {
                     pszCoordinateSystem = json_object_get_string(poCoordinateSystem);
@@ -1188,7 +1184,7 @@ GDALDataset* PLMosaicDataset::GetMetaTile(int tile_x, int tile_y)
         osTmpFilename = CPLFormFilename(osMosaicPath,
                 CPLSPrintf("%s_%s.tif", osMosaic.c_str(), CPLGetFilename(osTilename)), NULL);
         VSIStatBufL sStatBuf;
-        if( osCachePathRoot.size() && VSIStatL(osTmpFilename, &sStatBuf) == 0 )
+        if( !osCachePathRoot.empty() && VSIStatL(osTmpFilename, &sStatBuf) == 0 )
         {
             if( bTrustCache )
             {
@@ -1211,10 +1207,10 @@ GDALDataset* PLMosaicDataset::GetMetaTile(int tile_x, int tile_y)
             // to cause a change in filesize. Use of a signature would be better
             // though if available in the metadata
             int nFileSize = 0;
-            json_object* poProperties = json_object_object_get(poObj, "properties");
+            json_object* poProperties = CPL_json_object_object_get(poObj, "properties");
             if( poProperties && json_object_get_type(poProperties) == json_type_object )
             {
-                json_object* poFileSize = json_object_object_get(poProperties, "file_size");
+                json_object* poFileSize = CPL_json_object_object_get(poProperties, "file_size");
                 nFileSize = json_object_get_int(poFileSize);
             }
             json_object_put(poObj);
@@ -1254,7 +1250,7 @@ GDALDataset* PLMosaicDataset::GetMetaTile(int tile_x, int tile_y)
         {
             // In case there's no temporary path or it is not writable
             // use a in-memory dataset, and limit the cache to only one
-            if( osCachePathRoot.size() && nCacheMaxSize > 1 )
+            if( !osCachePathRoot.empty() && nCacheMaxSize > 1 )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Cannot write into %s. Using /vsimem and reduce cache to 1 entry",
@@ -1347,7 +1343,7 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
 
     CPLXMLNode* psRoot = CPLCreateXMLNode(NULL, CXT_Element, "LocationInfo");
 
-    if( osLastQuadInformation.size() )
+    if( !osLastQuadInformation.empty() )
     {
         const char* const apszAllowedDrivers[2] = { "GeoJSON", NULL };
         const char* const apszOptions[2] = { "FLATTEN_NESTED_ATTRIBUTES=YES", NULL };
@@ -1369,12 +1365,12 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
         {
             CPLXMLNode* psQuad = CPLCreateXMLNode(psRoot, CXT_Element, "Quad");
             OGRLayer* poLayer = poDS->GetLayer(0);
-            OGRFeature* poFeat;
+            OGRFeature* poFeat = NULL;
             while( (poFeat = poLayer->GetNextFeature()) != NULL )
             {
                 for(int i=0;i<poFeat->GetFieldCount();i++)
                 {
-                    if( poFeat->IsFieldSet(i) )
+                    if( poFeat->IsFieldSetAndNotNull(i) )
                     {
                         CPLXMLNode* psItem = CPLCreateXMLNode(psQuad,
                             CXT_Element, poFeat->GetFieldDefnRef(i)->GetNameRef());
@@ -1397,7 +1393,7 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
         }
     }
 
-    if( osLastQuadSceneInformation.size() && pszWKT != NULL )
+    if( !osLastQuadSceneInformation.empty() && pszWKT != NULL )
     {
         const char* const apszAllowedDrivers[2] = { "GeoJSON", NULL };
         const char* const apszOptions[2] = { "FLATTEN_NESTED_ATTRIBUTES=YES", NULL };
@@ -1427,7 +1423,7 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
             CPLXMLNode* psScenes = NULL;
             OGRLayer* poLayer = poDS->GetLayer(0);
             poLayer->SetSpatialFilterRect(x,y,x,y);
-            OGRFeature* poFeat;
+            OGRFeature* poFeat = NULL;
             while( (poFeat = poLayer->GetNextFeature()) != NULL )
             {
                 OGRGeometry* poGeom = poFeat->GetGeometryRef();
@@ -1438,7 +1434,7 @@ const char* PLMosaicDataset::GetLocationInfo(int nPixel, int nLine)
                     CPLXMLNode* psScene = CPLCreateXMLNode(psScenes, CXT_Element, "Scene");
                     for(int i=0;i<poFeat->GetFieldCount();i++)
                     {
-                        if( poFeat->IsFieldSet(i) )
+                        if( poFeat->IsFieldSetAndNotNull(i) )
                         {
                             CPLXMLNode* psItem = CPLCreateXMLNode(psScene,
                                 CXT_Element, poFeat->GetFieldDefnRef(i)->GetNameRef());
diff --git a/frmts/png/GNUmakefile b/frmts/png/GNUmakefile
index 6e25d93..9cd70d0 100644
--- a/frmts/png/GNUmakefile
+++ b/frmts/png/GNUmakefile
@@ -1,4 +1,4 @@
-# $Id: GNUmakefile 31315 2015-11-02 15:10:52Z rouault $
+# $Id: GNUmakefile 35922 2016-10-25 05:46:08Z goatbar $
 #
 # Makefile to build libpng using GNU Make and GCC.
 #
@@ -31,7 +31,7 @@ else
 OBJ	=	pngdataset.o
 endif
 
-ifeq ($(LIBZ_SETTING),internal) 
+ifeq ($(LIBZ_SETTING),internal)
 XTRA_OPT	:=	$(XTRA_OPT) -I../zlib
 endif
 
diff --git a/frmts/png/libpng/README b/frmts/png/libpng/README
index 496f2b5..bc6f3dd 100644
--- a/frmts/png/libpng/README
+++ b/frmts/png/libpng/README
@@ -1,17 +1,17 @@
-$Id$
-
-*** IMPORTANT ***
-Updating libpng in GDAL tree should follow update of zlib library in frmts/zlib.
-*****************
-
-libpng 1.2.56 is the official PNG reference library.
-It supports almost all PNG features, is extensible,
-and has been extensively tested for over 15 years.
-
-http://www.libpng.org
-
-
-GDAL changes (stored in libpng_gdal.patch)
-------------
-
-* Make screwy MSPaint "zero chunks" only a warning, not error. See r18808 and #3416
+$Id$
+
+*** IMPORTANT ***
+Updating libpng in GDAL tree should follow update of zlib library in frmts/zlib.
+*****************
+
+libpng 1.2.56 is the official PNG reference library.
+It supports almost all PNG features, is extensible,
+and has been extensively tested for over 15 years.
+
+http://www.libpng.org
+
+
+GDAL changes (stored in libpng_gdal.patch)
+------------
+
+* Make screwy MSPaint "zero chunks" only a warning, not error. See r18808 and #3416
diff --git a/frmts/png/libpng/makefile.vc b/frmts/png/libpng/makefile.vc
index 7af6480..ab8cf49 100644
--- a/frmts/png/libpng/makefile.vc
+++ b/frmts/png/libpng/makefile.vc
@@ -1,4 +1,4 @@
-# $Id: makefile.vc 31687 2015-11-21 16:35:21Z rouault $
+# $Id: makefile.vc 36434 2016-11-22 18:16:07Z rouault $
 #
 # Makefile to build libpng using NMAKE and Visual C++ compiler.
 #
@@ -23,10 +23,16 @@ OBJ = \
 
 GDAL_ROOT	=	..\..\..
 
-EXTRAFLAGS = 	-I..\..\zlib /wd4267 /wd4310 
-
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
+!IFDEF ZLIB_EXTERNAL_LIB
+ZLIB_FLAGS = $(ZLIB_INC)
+!ELSE
+ZLIB_FLAGS = -I..\..\zlib
+!ENDIF
+
+EXTRAFLAGS = 	$(ZLIB_FLAGS) /wd4267 /wd4310 
+
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\..\o
 
diff --git a/frmts/png/libpng/pngerror.c b/frmts/png/libpng/pngerror.c
index 0ce1744..85aade5 100644
--- a/frmts/png/libpng/pngerror.c
+++ b/frmts/png/libpng/pngerror.c
@@ -318,7 +318,7 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message)
    if (*warning_message == PNG_LITERAL_SHARP)
    {
      int offset;
-     char warning_number[16];
+     char warning_number[16] = { 0 };
      for (offset = 0; offset < 15; offset++)
      {
         warning_number[offset] = warning_message[offset + 1];
diff --git a/frmts/png/makefile.vc b/frmts/png/makefile.vc
index 6c6943a..390c246 100644
--- a/frmts/png/makefile.vc
+++ b/frmts/png/makefile.vc
@@ -4,12 +4,17 @@ GDAL_ROOT	=	..\..
 OBJ	=	\
 	pngdataset.obj
 
+!IFDEF ZLIB_EXTERNAL_LIB
+ZLIB_FLAGS = $(ZLIB_INC)
+!ELSE
+ZLIB_FLAGS = -I..\zlib
+!ENDIF
 
-#EXTRAFLAGS = 	-I..\zlib -Ilibpng
+#EXTRAFLAGS = 	$(ZLIB_FLAGS) -Ilibpng
 !IFDEF PNG_EXTERNAL_LIB
-EXTRAFLAGS = 	-I..\zlib -I$(PNGDIR)
+EXTRAFLAGS = 	$(ZLIB_FLAGS) -I$(PNGDIR)
 !ELSE
-EXTRAFLAGS = 	-I..\zlib -Ilibpng
+EXTRAFLAGS = 	$(ZLIB_FLAGS) -Ilibpng
 !ENDIF
 
 default:	$(OBJ)
diff --git a/frmts/png/pngdataset.cpp b/frmts/png/pngdataset.cpp
index 768c526..5360e2e 100644
--- a/frmts/png/pngdataset.cpp
+++ b/frmts/png/pngdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pngdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $
  *
  * Project:  PNG Driver
  * Purpose:  Implement GDAL PNG Support
@@ -49,18 +48,17 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: pngdataset.cpp 33794 2016-03-26 13:19:07Z goatbar $");
+CPL_CVSID("$Id: pngdataset.cpp 37784 2017-03-18 23:29:45Z rouault $");
 
-// Define SUPPORT_CREATE if you want Create() call supported.
-// Note: callers must provide blocks in increasing Y order.
+// Note: Callers must provide blocks in increasing Y order.
+// Disclaimer (E. Rouault): this code is not production ready at all. A lot of
+// issues remain: uninitialized variables, unclosed files, lack of proper
+// multiband handling, and an inability to read and write at the same time. Do
+// not use it unless you're ready to fix it.
 
-// Disclaimer (E. Rouault) : this code is NOT production ready at all.
-// A lot of issues remains : uninitialized variables, unclosed file,
-// inability to handle properly multiband case, inability to read&write
-// at the same time. Do NOT use it unless you're ready to fix it
+// Define SUPPORT_CREATE to enable use of the Create() call.
 // #define SUPPORT_CREATE
 
-// we believe it is ok to use setjmp() in this situation.
 #ifdef _MSC_VER
 #  pragma warning(disable:4611)
 #endif
@@ -78,16 +76,17 @@ static void png_gdal_warning( png_structp png_ptr, const char *error_message );
 
 /************************************************************************/
 /* ==================================================================== */
-/*				PNGDataset				*/
+/*                              PNGDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
 class PNGRasterBand;
 
-
 #ifdef _MSC_VER
 #pragma warning( push )
-#pragma warning( disable : 4324 ) /* 'PNGDataset' : structure was padded due to __declspec(align()) at line where we use jmp_buf */
+// 'PNGDataset': structure was padded due to __declspec(align()) at line where
+// we use `jmp_buf`.
+#pragma warning( disable : 4324 )
 #endif
 
 class PNGDataset : public GDALPamDataset
@@ -98,7 +97,7 @@ class PNGDataset : public GDALPamDataset
     png_structp hPNG;
     png_infop   psPNGInfo;
     int         nBitDepth;
-    int         nColorType; /* PNG_COLOR_TYPE_* */
+    int         nColorType;  // PNG_COLOR_TYPE_*
     int         bInterlaced;
 
     int         nBufferStartLine;
@@ -108,10 +107,9 @@ class PNGDataset : public GDALPamDataset
 
     GDALColorTable *poColorTable;
 
-    int	   bGeoTransformValid;
+    int    bGeoTransformValid;
     double adfGeoTransform[6];
 
-
     void        CollectMetadata();
 
     int         bHasReadXMPMetadata;
@@ -130,6 +128,7 @@ class PNGDataset : public GDALPamDataset
 
     static void WriteMetadataAsText(png_structp hPNG, png_infop psPNGInfo,
                                     const char* pszKey, const char* pszValue);
+    static GDALDataset *OpenStage2( GDALOpenInfo *, PNGDataset*& );
 
   public:
                  PNGDataset();
@@ -143,46 +142,45 @@ class PNGDataset : public GDALPamDataset
                                     GDALProgressFunc pfnProgress,
                                     void * pProgressData );
 
-    virtual char **GetFileList(void);
+    virtual char **GetFileList(void) override;
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual void FlushCache( void );
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual void FlushCache( void ) override;
 
-    virtual char      **GetMetadataDomainList();
+    virtual char      **GetMetadataDomainList() override;
 
-    virtual char  **GetMetadata( const char * pszDomain = "" );
+    virtual char  **GetMetadata( const char * pszDomain = "" ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = NULL );
+                                         const char * pszDomain = NULL ) override;
 
     virtual CPLErr      IRasterIO( GDALRWFlag, int, int, int, int,
                                    void *, int, int, GDALDataType,
                                    int, int *,
                                    GSpacing, GSpacing,
                                    GSpacing,
-                                   GDALRasterIOExtraArg* psExtraArg );
+                                   GDALRasterIOExtraArg* psExtraArg ) override;
 
-    // semi-private.
-    jmp_buf     sSetJmpContext;
+    jmp_buf     sSetJmpContext;  // Semi-private.
 
 #ifdef SUPPORT_CREATE
     int        m_nBitDepth;
     GByte      *m_pabyBuffer;
-    png_byte	*m_pabyAlpha;
+    png_byte    *m_pabyAlpha;
     png_structp m_hPNG;
     png_infop   m_psPNGInfo;
-    png_color	*m_pasPNGColors;
+    png_color   *m_pasPNGColors;
     VSILFILE        *m_fpImage;
-    int	   m_bGeoTransformValid;
+    int    m_bGeoTransformValid;
     double m_adfGeoTransform[6];
     char        *m_pszFilename;
-    int         m_nColorType; /* PNG_COLOR_TYPE_* */
+    int         m_nColorType;  // PNG_COLOR_TYPE_*
 
     virtual CPLErr SetGeoTransform( double * );
     static GDALDataset  *Create( const char* pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType, char** papszParmList );
   protected:
-	CPLErr write_png_header();
+        CPLErr write_png_header();
 
 #endif
 };
@@ -206,34 +204,32 @@ class PNGRasterBand : public GDALPamRasterBand
                    PNGRasterBand( PNGDataset *, int );
     virtual ~PNGRasterBand() {}
 
-    virtual CPLErr IReadBlock( int, int, void * );
-
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    CPLErr SetNoDataValue( double dfNewValue );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 
-    int		bHaveNoData;
-    double 	dfNoDataValue;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+    CPLErr SetNoDataValue( double dfNewValue ) override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 
+    int         bHaveNoData;
+    double      dfNoDataValue;
 
 #ifdef SUPPORT_CREATE
     virtual CPLErr SetColorTable(GDALColorTable*);
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 
   protected:
-	int m_bBandProvided[5];
-	void reset_band_provision_flags()
-	{
+        int m_bBandProvided[5];
+        void reset_band_provision_flags()
+        {
             PNGDataset& ds = *reinterpret_cast<PNGDataset *>( poDS );
 
             for(size_t i = 0; i < static_cast<size_t>( ds.nBands ); i++)
                 m_bBandProvided[i] = FALSE;
-	}
+        }
 #endif
 };
 
-
 /************************************************************************/
 /*                           PNGRasterBand()                            */
 /************************************************************************/
@@ -242,8 +238,8 @@ PNGRasterBand::PNGRasterBand( PNGDataset *poDSIn, int nBandIn ) :
     bHaveNoData(FALSE),
     dfNoDataValue(-1)
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     if( poDSIn->nBitDepth == 16 )
         eDataType = GDT_UInt16;
@@ -254,7 +250,7 @@ PNGRasterBand::PNGRasterBand( PNGDataset *poDSIn, int nBandIn ) :
     nBlockYSize = 1;
 
 #ifdef SUPPORT_CREATE
-	this->reset_band_provision_flags();
+    reset_band_provision_flags();
 #endif
 }
 
@@ -276,7 +272,6 @@ CPLErr PNGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     else
         nPixelSize = 1;
 
-
     const int nXSize = GetXSize();
     if (poGDS->fpImage == NULL)
     {
@@ -284,9 +279,7 @@ CPLErr PNGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Load the desired scanline into the working buffer.              */
-/* -------------------------------------------------------------------- */
+    // Load the desired scanline into the working buffer.
     CPLErr eErr = poGDS->LoadScanline( nBlockYOff );
     if( eErr != CE_None )
         return eErr;
@@ -297,9 +290,7 @@ CPLErr PNGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         + (nBlockYOff - poGDS->nBufferStartLine) * nPixelOffset * nXSize
         + nPixelSize * (nBand - 1);
 
-/* -------------------------------------------------------------------- */
-/*      Transfer between the working buffer and the callers buffer.     */
-/* -------------------------------------------------------------------- */
+    // Transfer between the working buffer and the caller's buffer.
     if( nPixelSize == nPixelOffset )
         memcpy( pImage, pabyScanline, nPixelSize * nXSize );
     else if( nPixelSize == 1 )
@@ -317,9 +308,7 @@ CPLErr PNGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Forcibly load the other bands associated with this scanline.    */
-/* -------------------------------------------------------------------- */
+    // Forcibly load the other bands associated with this scanline.
     for(int iBand = 1; iBand < poGDS->GetRasterCount(); iBand++)
     {
         GDALRasterBlock *poBlock =
@@ -421,9 +410,8 @@ double PNGRasterBand::GetNoDataValue( int *pbSuccess )
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
-/*                            PNGDataset()                            */
+/*                             PNGDataset()                             */
 /************************************************************************/
 
 PNGDataset::PNGDataset() :
@@ -454,7 +442,7 @@ PNGDataset::PNGDataset() :
 }
 
 /************************************************************************/
-/*                           ~PNGDataset()                            */
+/*                            ~PNGDataset()                             */
 /************************************************************************/
 
 PNGDataset::~PNGDataset()
@@ -516,15 +504,14 @@ CPLErr PNGDataset::IRasterIO( GDALRWFlag eRWFlag,
        (pData != NULL) &&
        (panBandMap != NULL) && IsFullBandMap(panBandMap, nBands))
     {
-
-        // Pixel interleaved case
+        // Pixel interleaved case.
         if( nBandSpace == 1 )
         {
             for(int y = 0; y < nYSize; ++y)
             {
                 CPLErr tmpError = LoadScanline(y);
                 if(tmpError != CE_None) return tmpError;
-                GByte* pabyScanline = pabyBuffer
+                const GByte* pabyScanline = pabyBuffer
                     + (y - nBufferStartLine) * nBands * nXSize;
                 if( nPixelSpace == nBandSpace * nBandCount )
                 {
@@ -547,12 +534,34 @@ CPLErr PNGDataset::IRasterIO( GDALRWFlag eRWFlag,
             {
                 CPLErr tmpError = LoadScanline(y);
                 if(tmpError != CE_None) return tmpError;
-                GByte* pabyScanline = pabyBuffer
+                const GByte* pabyScanline = pabyBuffer
                     + (y - nBufferStartLine) * nBands * nXSize;
-                for(int x = 0; x < nXSize; ++x)
+                GByte* pabyDest = reinterpret_cast<GByte *>( pData ) +
+                                                            y*nLineSpace;
+                if( nPixelSpace <= nBands && nBandSpace > nBands )
                 {
+                    // Cache friendly way for typical band interleaved case.
                     for(int iBand=0;iBand<nBands;iBand++)
-                         reinterpret_cast<GByte *>( pData )[(y*nLineSpace) + (x*nPixelSpace) + iBand * nBandSpace] = pabyScanline[x*nBands+iBand];
+                    {
+                        GByte* pabyDest2 = pabyDest + iBand * nBandSpace;
+                        const GByte* pabyScanline2 = pabyScanline + iBand;
+                        GDALCopyWords( pabyScanline2, GDT_Byte, nBands,
+                                       pabyDest2, GDT_Byte,
+                                       static_cast<int>(nPixelSpace),
+                                       nXSize );
+                    }
+                }
+                else
+                {
+                    // Generic method
+                    for(int x = 0; x < nXSize; ++x)
+                    {
+                        for(int iBand=0;iBand<nBands;iBand++)
+                        {
+                            pabyDest[(x*nPixelSpace) + iBand * nBandSpace] =
+                                pabyScanline[x*nBands+iBand];
+                        }
+                    }
                 }
             }
         }
@@ -588,7 +597,7 @@ CPLErr PNGDataset::GetGeoTransform( double * padfTransform )
 /************************************************************************/
 /*                             FlushCache()                             */
 /*                                                                      */
-/*      We override this so we can also flush out local tiff strip      */
+/*      We override this so we can also flush out local TIFF strip      */
 /*      cache if need be.                                               */
 /************************************************************************/
 
@@ -663,9 +672,7 @@ CPLErr PNGDataset::LoadInterlacedChunk( int iLine )
     else
         nPixelOffset = 1 * GetRasterCount();
 
-/* -------------------------------------------------------------------- */
-/*      Was is the biggest chunk we can safely operate on?              */
-/* -------------------------------------------------------------------- */
+    // What is the biggest chunk we can safely operate on?
     static const int MAX_PNG_CHUNK_BYTES = 100000000;
 
     int nMaxChunkLines =
@@ -674,10 +681,8 @@ CPLErr PNGDataset::LoadInterlacedChunk( int iLine )
     if( nMaxChunkLines > GetRasterYSize() )
         nMaxChunkLines = GetRasterYSize();
 
-/* -------------------------------------------------------------------- */
-/*      Allocate chunk buffer, if we don't already have it from a       */
-/*      previous request.                                               */
-/* -------------------------------------------------------------------- */
+    // Allocate chunk buffer if we don't already have it from a previous
+    // request.
     nBufferLines = nMaxChunkLines;
     if( nMaxChunkLines + iLine > GetRasterYSize() )
         nBufferStartLine = GetRasterYSize() - nMaxChunkLines;
@@ -702,20 +707,15 @@ CPLErr PNGDataset::LoadInterlacedChunk( int iLine )
 #endif
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we need to restart reading?  We do this if we aren't on      */
-/*      the first attempt to read the image.                            */
-/* -------------------------------------------------------------------- */
+    // Do we need to restart reading? We do this if we aren't on the first
+    // attempt to read the image.
     if( nLastLineRead != -1 )
     {
         Restart();
     }
 
-/* -------------------------------------------------------------------- */
-/*      Allocate and populate rows array.  We create a row for each     */
-/*      row in the image, but use our dummy line for rows not in the    */
-/*      target window.                                                  */
-/* -------------------------------------------------------------------- */
+    // Allocate and populate rows array. We create a row for each row in the
+    // image but use our dummy line for rows not in the target window.
     png_bytep dummy_row = reinterpret_cast<png_bytep>(
         CPLMalloc(nPixelOffset*GetRasterXSize()) );
     png_bytep *png_rows
@@ -756,6 +756,7 @@ static bool safe_png_read_rows(png_structp hPNG,
     png_read_rows( hPNG, &row, NULL, 1 );
     return true;
 }
+
 /************************************************************************/
 /*                            LoadScanline()                            */
 /************************************************************************/
@@ -774,32 +775,24 @@ CPLErr PNGDataset::LoadScanline( int nLine )
     else
         nPixelOffset = 1 * GetRasterCount();
 
-/* -------------------------------------------------------------------- */
-/*      If the file is interlaced, we will load the entire image        */
-/*      into memory using the high level API.                           */
-/* -------------------------------------------------------------------- */
+    // If the file is interlaced, we load the entire image into memory using the
+    // high-level API.
     if( bInterlaced )
         return LoadInterlacedChunk( nLine );
 
-/* -------------------------------------------------------------------- */
-/*      Ensure we have space allocated for one scanline                 */
-/* -------------------------------------------------------------------- */
+    // Ensure we have space allocated for one scanline.
     if( pabyBuffer == NULL )
         pabyBuffer = reinterpret_cast<GByte *>(
             CPLMalloc(nPixelOffset * GetRasterXSize() ) );
 
-/* -------------------------------------------------------------------- */
-/*      Otherwise we just try to read the requested row.  Do we need    */
-/*      to rewind and start over?                                       */
-/* -------------------------------------------------------------------- */
+    // Otherwise we just try to read the requested row. Do we need to rewind and
+    // start over?
     if( nLine <= nLastLineRead )
     {
         Restart();
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read till we get the desired row.                               */
-/* -------------------------------------------------------------------- */
+    // Read till we get the desired row.
     png_bytep row = pabyBuffer;
     while( nLine > nLastLineRead )
     {
@@ -811,10 +804,7 @@ CPLErr PNGDataset::LoadScanline( int nLine )
     nBufferStartLine = nLine;
     nBufferLines = 1;
 
-/* -------------------------------------------------------------------- */
-/*      Do swap on LSB machines.  16bit PNG data is stored in MSB       */
-/*      format.                                                         */
-/* -------------------------------------------------------------------- */
+     // Do swap on LSB machines. 16-bit PNG data is stored in MSB format.
 #ifdef CPL_LSB
     if( nBitDepth == 16 )
         GDALSwapWords( row, 2, GetRasterXSize() * GetRasterCount(), 2 );
@@ -827,7 +817,7 @@ CPLErr PNGDataset::LoadScanline( int nLine )
 /*                          CollectMetadata()                           */
 /*                                                                      */
 /*      We normally do this after reading up to the image, but be       */
-/*      forewarned ... we can missing text chunks this way.             */
+/*      forewarned: we can miss text chunks this way.                   */
 /*                                                                      */
 /*      We turn each PNG text chunk into one metadata item.  It         */
 /*      might be nice to preserve language information though we        */
@@ -871,7 +861,8 @@ void PNGDataset::CollectMetadata()
 /*                       CollectXMPMetadata()                           */
 /************************************************************************/
 
-// See §2.1.5 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf
+// See §2.1.5 of
+// http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf.
 
 void PNGDataset::CollectXMPMetadata()
 
@@ -879,13 +870,13 @@ void PNGDataset::CollectXMPMetadata()
     if (fpImage == NULL || bHasReadXMPMetadata)
         return;
 
-    /* Save current position to avoid disturbing PNG stream decoding */
+    // Save current position to avoid disturbing PNG stream decoding.
     const vsi_l_offset nCurOffset = VSIFTellL(fpImage);
 
     vsi_l_offset nOffset = 8;
     VSIFSeekL( fpImage, nOffset, SEEK_SET );
 
-    /* Loop over chunks */
+    // Loop over chunks.
     while( true )
     {
         int nLength;
@@ -918,7 +909,7 @@ void PNGDataset::CollectXMPMetadata()
             pszContent[nLength] = '\0';
             if (memcmp(pszContent, "XML:com.adobe.xmp\0\0\0\0\0", 22) == 0)
             {
-                /* Avoid setting the PAM dirty bit just for that */
+                // Avoid setting the PAM dirty bit just for that.
                 int nOldPamFlags = nPamFlags;
 
                 char *apszMDList[2] = { pszContent + 22, NULL };
@@ -971,17 +962,17 @@ void PNGDataset::LoadICCProfile()
 #endif
     int nCompressionType;
 
-    /* Avoid setting the PAM dirty bit just for that */
+    // Avoid setting the PAM dirty bit just for that.
     int nOldPamFlags = nPamFlags;
 
     if (png_get_iCCP(hPNG, psPNGInfo, &pszProfileName,
        &nCompressionType, &pProfileData, &nProfileLength) != 0)
     {
-        /* Escape the profile */
+        // Escape the profile.
         char *pszBase64Profile = CPLBase64Encode(
             static_cast<int>(nProfileLength), reinterpret_cast<const GByte *>( pProfileData ) );
 
-        /* Set ICC profile metadata */
+        // Set ICC profile metadata.
         SetMetadataItem( "SOURCE_ICC_PROFILE", pszBase64Profile, "COLOR_PROFILE" );
         SetMetadataItem( "SOURCE_ICC_PROFILE_NAME", pszProfileName, "COLOR_PROFILE" );
 
@@ -1014,7 +1005,7 @@ void PNGDataset::LoadICCProfile()
             CPLString().Printf( "%.9f", dfGamma ) , "COLOR_PROFILE" );
     }
 
-    // Check if both cHRM and gAMA available
+    // Check that both cHRM and gAMA are available.
     if (bGammaAvailable && png_get_valid(hPNG, psPNGInfo, PNG_INFO_cHRM))
     {
         double dfaWhitepoint[2];
@@ -1036,7 +1027,6 @@ void PNGDataset::LoadICCProfile()
 
         SetMetadataItem( "SOURCE_WHITEPOINT",
             CPLString().Printf( "%.9f, %.9f, 1.0", dfaWhitepoint[0], dfaWhitepoint[1] ) , "COLOR_PROFILE" );
-
     }
 
     nPamFlags = nOldPamFlags;
@@ -1117,11 +1107,14 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
-    PNGDataset 	*poDS = new PNGDataset();
+    // Create a corresponding GDALDataset.
+    PNGDataset *poDS = new PNGDataset();
+    return OpenStage2( poOpenInfo, poDS );
+}
+
+GDALDataset *PNGDataset::OpenStage2( GDALOpenInfo * poOpenInfo, PNGDataset*& poDS )
 
+{
     poDS->fpImage = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
     poDS->eAccess = poOpenInfo->eAccess;
@@ -1147,9 +1140,7 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->psPNGInfo = png_create_info_struct( poDS->hPNG );
 
-/* -------------------------------------------------------------------- */
-/*      Setup error handling.                                           */
-/* -------------------------------------------------------------------- */
+    // Set up error handling.
     png_set_error_fn( poDS->hPNG, &poDS->sSetJmpContext, png_gdal_error, png_gdal_warning );
 
     if( setjmp( poDS->sSetJmpContext ) != 0 )
@@ -1158,17 +1149,13 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*	Read pre-image data after ensuring the file is rewound.         */
-/* -------------------------------------------------------------------- */
-    /* we should likely do a setjmp() here */
+    // Read pre-image data after ensuring the file is rewound.
+    // We should likely do a setjmp() here.
 
     png_set_read_fn( poDS->hPNG, poDS->fpImage, png_vsi_read_data );
     png_read_info( poDS->hPNG, poDS->psPNGInfo );
 
-/* -------------------------------------------------------------------- */
-/*      Capture some information from the file that is of interest.     */
-/* -------------------------------------------------------------------- */
+    // Capture some information from the file that is of interest.
     poDS->nRasterXSize = static_cast<int>(png_get_image_width( poDS->hPNG, poDS->psPNGInfo));
     poDS->nRasterYSize = static_cast<int>(png_get_image_height( poDS->hPNG,poDS->psPNGInfo));
 
@@ -1189,27 +1176,21 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->nBands = 1;
     }
 
-/* -------------------------------------------------------------------- */
-/*      We want to treat 1,2,4 bit images as eight bit.  This call      */
-/*      causes libpng to unpack the image.                              */
-/* -------------------------------------------------------------------- */
+    // We want to treat 1-, 2-, and 4-bit images as eight bit. This call causes
+    // libpng to unpack the image.
     if( poDS->nBitDepth < 8 )
         png_set_packing( poDS->hPNG );
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
+    // Create band information objects.
     for( int iBand = 0; iBand < poDS->nBands; iBand++ )
         poDS->SetBand( iBand+1, new PNGRasterBand( poDS, iBand+1 ) );
 
-/* -------------------------------------------------------------------- */
-/*      Is there a palette?  Note: we should also read back and         */
-/*      apply transparency values if available.                         */
-/* -------------------------------------------------------------------- */
+    // Is there a palette?  Note: we should also read back and apply
+    // transparency values if available.
     if( poDS->nColorType == PNG_COLOR_TYPE_PALETTE )
     {
-        png_color *pasPNGPalette;
-        int nColorCount;
+        png_color *pasPNGPalette = NULL;
+        int nColorCount = 0;
 
         if( png_get_PLTE( poDS->hPNG, poDS->psPNGInfo,
                           &pasPNGPalette, &nColorCount ) == 0 )
@@ -1248,19 +1229,15 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->poColorTable->SetColorEntry( iColor, &oEntry );
         }
 
-        /*
-        ** Special hack to an index as the no data value, as long as it
-        ** is the _only_ transparent color in the palette.
-        */
+        // Special hack to use an index as the no data value, as long as it is
+        // the only transparent color in the palette.
         if( nNoDataIndex > -1 )
         {
             poDS->GetRasterBand(1)->SetNoDataValue(nNoDataIndex);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check for transparency values in greyscale images.              */
-/* -------------------------------------------------------------------- */
+    // Check for transparency values in greyscale images.
     if( poDS->nColorType == PNG_COLOR_TYPE_GRAY )
     {
         png_color_16 *trans_values = NULL;
@@ -1275,9 +1252,7 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check for nodata color for RGB images.                          */
-/* -------------------------------------------------------------------- */
+    // Check for nodata color for RGB images.
     if( poDS->nColorType == PNG_COLOR_TYPE_RGB )
     {
         png_color_16 *trans_values = NULL;
@@ -1302,28 +1277,20 @@ GDALDataset *PNGDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Extract any text chunks as "metadata".                          */
-/* -------------------------------------------------------------------- */
+    // Extract any text chunks as "metadata."
     poDS->CollectMetadata();
 
-/* -------------------------------------------------------------------- */
-/*      More metadata.                                                  */
-/* -------------------------------------------------------------------- */
+    // More metadata.
     if( poDS->nBands > 1 )
     {
         poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
+    // Initialize any PAM information.
     poDS->SetDescription( poOpenInfo->pszFilename );
     poDS->TryLoadXML( poOpenInfo->GetSiblingFiles() );
 
-/* -------------------------------------------------------------------- */
-/*      Open overviews.                                                 */
-/* -------------------------------------------------------------------- */
+    // Open overviews.
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename,
                                  poOpenInfo->GetSiblingFiles() );
 
@@ -1370,7 +1337,7 @@ char **PNGDataset::GetFileList()
 
     LoadWorldFile();
 
-    if (osWldFilename.size() != 0 &&
+    if (!osWldFilename.empty() &&
         CSLFindString(papszFileList, osWldFilename) == -1)
     {
         papszFileList = CSLAddString( papszFileList, osWldFilename );
@@ -1409,7 +1376,7 @@ void PNGDataset::WriteMetadataAsText(png_structp hPNG, png_infop psPNGInfo,
     sText.key = (png_charp) pszKey;
     sText.text = (png_charp) pszValue;
 #ifdef HAVE_ITXT_SUPPORT
-    // UTF-8 values should be written in iTXt, whereas TEXT should be LATIN-1
+    // UTF-8 values should be written in iTXt, whereas TEXT should be LATIN-1.
     if( !IsASCII(pszValue) && CPLIsUTF8(pszValue, -1) )
         sText.compression = PNG_ITXT_COMPRESSION_NONE;
 #endif
@@ -1426,9 +1393,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Some some rudimentary checks                                    */
-/* -------------------------------------------------------------------- */
+    // Perform some rudimentary checks.
     const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 && nBands != 2 && nBands != 3 && nBands != 4 )
     {
@@ -1454,9 +1419,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the dataset.                                             */
-/* -------------------------------------------------------------------- */
+    // Create the dataset.
     VSILFILE *fpImage = VSIFOpenL( pszFilename, "wb" );
     if( fpImage == NULL )
     {
@@ -1466,9 +1429,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize PNG access to the file.                              */
-/* -------------------------------------------------------------------- */
+    // Initialize PNG access to the file.
     jmp_buf     sSetJmpContext;
 
     png_structp hPNG = png_create_write_struct(
@@ -1482,9 +1443,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Setup some parameters.                                          */
-/* -------------------------------------------------------------------- */
+    // Set up some parameters.
     int  nColorType=0;
 
     if( nBands == 1 && poSrcDS->GetRasterBand(1)->GetColorTable() == NULL )
@@ -1542,9 +1501,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                   nBitDepth, nColorType, PNG_INTERLACE_NONE,
                   PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE );
 
-/* -------------------------------------------------------------------- */
-/*      Do we want to control the compression level?                    */
-/* -------------------------------------------------------------------- */
+    // Do we want to control the compression level?
     const char *pszLevel = CSLFetchNameValue( papszOptions, "ZLEVEL" );
 
     if( pszLevel )
@@ -1561,11 +1518,8 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         png_set_compression_level( hPNG, nLevel );
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try to handle nodata values as a tRNS block (note for           */
-/*      paletted images, we save the effect to apply as part of         */
-/*      palette).                                                       */
-/* -------------------------------------------------------------------- */
+    // Try to handle nodata values as a tRNS block (note that for paletted
+    // images, we save the effect to apply as part of palette).
     png_color_16 sTRNSColor;
 
     // Gray nodata.
@@ -1628,9 +1582,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
        }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Copy colour profile data                                        */
-/* -------------------------------------------------------------------- */
+    // Copy color profile data.
     const char *pszICCProfile = CSLFetchNameValue(papszOptions, "SOURCE_ICC_PROFILE");
     const char *pszICCProfileName = CSLFetchNameValue(papszOptions, "SOURCE_ICC_PROFILE_NAME");
     if (pszICCProfileName == NULL)
@@ -1671,7 +1623,7 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     }
     else if ((pszICCProfileName == NULL) || !EQUAL(pszICCProfileName, "sRGB"))
     {
-        // Output gamma, primaries and whitepoint
+        // Output gamma, primaries and whitepoint.
         const char *pszGamma = CSLFetchNameValue(papszOptions, "PNG_GAMMA");
         if (pszGamma == NULL)
             pszGamma = poSrcDS->GetMetadataItem( "PNG_GAMMA", "COLOR_PROFILE" );
@@ -1699,8 +1651,8 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             (pszWhitepoint != NULL))
         {
             bool bOk = true;
-            double faColour[8];
-            char** apapszTokenList[4];
+            double faColour[8] = { 0.0 };
+            char** apapszTokenList[4] = { NULL };
 
             apapszTokenList[0] = CSLTokenizeString2( pszWhitepoint, ",",
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
@@ -1747,7 +1699,6 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                         faColour[2], faColour[3],
                         faColour[4], faColour[5],
                         faColour[6], faColour[7]);
-
                 }
             }
 
@@ -1756,14 +1707,10 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
             CSLDestroy( apapszTokenList[2] );
             CSLDestroy( apapszTokenList[3] );
         }
-
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write palette if there is one.  Technically, I think it is      */
-/*      possible to write 16bit palettes for PNG, but we will omit      */
-/*      this for now.                                                   */
-/* -------------------------------------------------------------------- */
+    // Write the palette if there is one. Technically, it may be possible to
+    // write 16-bit palettes for PNG, but for now, this is omitted.
     if( nColorType == PNG_COLOR_TYPE_PALETTE )
     {
         int bHaveNoData = FALSE;
@@ -1798,10 +1745,8 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
 
         CPLFree( pasPNGColors );
 
-/* -------------------------------------------------------------------- */
-/*      If we have transparent elements in the palette we need to       */
-/*      write a transparency block.                                     */
-/* -------------------------------------------------------------------- */
+        // If we have transparent elements in the palette, we need to write a
+        // transparency block.
         if( bFoundTrans || bHaveNoData )
         {
             unsigned char *pabyAlpha
@@ -1824,11 +1769,9 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Add text info                                                   */
-/* -------------------------------------------------------------------- */
-    // Predefined keywords. See "4.2.7 tEXt Textual data" of
-    // http://www.w3.org/TR/PNG-Chunks.html
+    // Add text info.
+    // These are predefined keywords. See "4.2.7 tEXt Textual data" of
+    // http://www.w3.org/TR/PNG-Chunks.html for more information.
     const char* apszKeywords[] = { "Title", "Author", "Description", "Copyright",
                                    "Creation Time", "Software", "Disclaimer",
                                    "Warning", "Source", "Comment", NULL };
@@ -1864,17 +1807,13 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write infos                                                     */
-/* -------------------------------------------------------------------- */
+    // Write the PNG info.
     png_write_info( hPNG, psPNGInfo );
 
     if( nBitDepth < 8 )
         png_set_packing( hPNG );
 
-/* -------------------------------------------------------------------- */
-/*      Loop over image, copying image data.                            */
-/* -------------------------------------------------------------------- */
+    // Loop over the image, copying image data.
     CPLErr      eErr = CE_None;
     const int nWordSize = GDALGetDataTypeSize(eType) / 8;
 
@@ -1921,20 +1860,16 @@ PNGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     if( eErr != CE_None )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Do we need a world file?                                          */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
+    // Do we need a world file?
+    if( CPLFetchBool( papszOptions, "WORLDFILE", false ) )
     {
-    	double      adfGeoTransform[6];
+      double adfGeoTransform[6];
 
-	if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
-            GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
+      if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
+        GDALWriteWorldFile( pszFilename, "wld", adfGeoTransform );
     }
 
-/* -------------------------------------------------------------------- */
-/*      Re-open dataset, and copy any auxiliary pam information.         */
-/* -------------------------------------------------------------------- */
+    // Re-open dataset and copy any auxiliary PAM information.
 
     /* If writing to stdout, we can't reopen it, so return */
     /* a fake dataset to make the caller happy */
@@ -2017,9 +1952,8 @@ static void png_gdal_error( png_structp png_ptr, const char *error_message )
     CPLError( CE_Failure, CPLE_AppDefined,
               "libpng: %s", error_message );
 
-    // We have to use longjmp instead of a C++ exception because
-    // libpng is generally not built as C++ and so will not honour unwind
-    // semantics.  Ugh.
+    // Use longjmp instead of a C++ exception, because libpng is generally not
+    // built as C++ and so will not honor unwind semantics.
 
     jmp_buf* psSetJmpContext = reinterpret_cast<jmp_buf *>(
         png_get_error_ptr( png_ptr ) );
@@ -2041,7 +1975,7 @@ static void png_gdal_warning( CPL_UNUSED png_structp png_ptr,
 }
 
 /************************************************************************/
-/*                          GDALRegister_PNG()                        */
+/*                          GDALRegister_PNG()                          */
 /************************************************************************/
 
 void GDALRegister_PNG()
@@ -2101,11 +2035,9 @@ void GDALRegister_PNG()
 
 CPLErr PNGRasterBand::IWriteBlock(int x, int y, void* pvData)
 {
-    // rcg, added to support Create().
     PNGDataset& ds = *reinterpret_cast<PNGDataset*>( poDS );
 
-    // Write the block (or consolidate into multichannel block)
-    // and then write.
+    // Write the block (or consolidate into multichannel block) and then write.
 
     const GDALDataType dt = GetRasterDataType();
     const size_t wordsize = ds.m_nBitDepth / 8;
@@ -2114,7 +2046,7 @@ CPLErr PNGRasterBand::IWriteBlock(int x, int y, void* pvData)
                    dt, ds.nBands * wordsize,
                    nBlockXSize );
 
-    // See if we got all the bands.
+    // See if we have all the bands.
     m_bBandProvided[nBand - 1] = TRUE;
     for( size_t i = 0; i < static_cast<size_t>( ds.nBands ); i++ )
     {
@@ -2122,12 +2054,10 @@ CPLErr PNGRasterBand::IWriteBlock(int x, int y, void* pvData)
             return CE_None;
     }
 
-    // We received all the bands, so
-    // reset band flags and write pixels out.
+    // We received all the bands, so reset band flags and write pixels out.
     this->reset_band_provision_flags();
 
-
-    // If first block, write out file header.
+    // If it's the first block, write out the file header.
     if(x == 0 && y == 0)
     {
         CPLErr err = ds.write_png_header();
@@ -2144,14 +2074,12 @@ CPLErr PNGRasterBand::IWriteBlock(int x, int y, void* pvData)
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                          SetGeoTransform()                           */
 /************************************************************************/
 
 CPLErr PNGDataset::SetGeoTransform( double * padfTransform )
 {
-    // rcg, added to support Create().
     memcpy( m_adfGeoTransform, padfTransform, sizeof(double) * 6 );
 
     if ( m_pszFilename )
@@ -2167,7 +2095,6 @@ CPLErr PNGDataset::SetGeoTransform( double * padfTransform )
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                           SetColorTable()                            */
 /************************************************************************/
@@ -2177,10 +2104,8 @@ CPLErr PNGRasterBand::SetColorTable(GDALColorTable* poCT)
     if( poCT == NULL )
         return CE_Failure;
 
-    // rcg, added to support Create().
-    // We get called even for grayscale files, since some
-    // formats need a palette even then. PNG doesn't, so
-    // if a gray palette is given, just ignore it.
+    // We get called even for grayscale files, since some formats need a palette
+    // even then. PNG doesn't, so if a gray palette is given, just ignore it.
 
     GDALColorEntry sEntry;
     for( size_t i = 0; i < static_cast<size_t>( poCT->GetColorEntryCount() ); i++ )
@@ -2195,8 +2120,8 @@ CPLErr PNGRasterBand::SetColorTable(GDALColorTable* poCT)
             PNGDataset& ds = *reinterpret_cast<PNGDataset *>( poDS );
             ds.m_nColorType = PNG_COLOR_TYPE_PALETTE;
             break;
-            // band::IWriteBlock will emit color table as part of
-            // header preceding first block write.
+            // band::IWriteBlock will emit color table as part of the header
+            // preceding the first block write.
         }
     }
 
@@ -2209,9 +2134,7 @@ CPLErr PNGRasterBand::SetColorTable(GDALColorTable* poCT)
 
 CPLErr PNGDataset::write_png_header()
 {
-/* -------------------------------------------------------------------- */
-/*      Initialize PNG access to the file.                              */
-/* -------------------------------------------------------------------- */
+    // Initialize PNG access to the file.
     m_hPNG = png_create_write_struct(
         PNG_LIBPNG_VER_STRING, NULL,
         png_gdal_error, png_gdal_warning );
@@ -2226,13 +2149,10 @@ CPLErr PNGDataset::write_png_header()
 
     png_set_compression_level(m_hPNG, Z_BEST_COMPRESSION);
 
-    //png_set_swap_alpha(m_hPNG); // Use RGBA order, not ARGB.
+    // png_set_swap_alpha(m_hPNG); // Use RGBA order, not ARGB.
 
-/* -------------------------------------------------------------------- */
-/*      Try to handle nodata values as a tRNS block (note for           */
-/*      paletted images, we save the effect to apply as part of         */
-/*      palette).                                                       */
-/* -------------------------------------------------------------------- */
+    // Try to handle nodata values as a tRNS block (note that for paletted
+    // images, we save the effect to apply as part of the palette).
     //m_bHaveNoData = FALSE;
     //m_dfNoDataValue = -1;
     png_color_16 sTRNSColor;
@@ -2254,7 +2174,7 @@ CPLErr PNGDataset::write_png_header()
     // RGB nodata.
     if( nColorType == PNG_COLOR_TYPE_RGB )
     {
-        // First try to use the NODATA_VALUES metadata item.
+        // First, try to use the NODATA_VALUES metadata item.
         if ( GetMetadataItem( "NODATA_VALUES" ) != NULL )
         {
             char **papszValues = CSLTokenizeString(
@@ -2297,18 +2217,14 @@ CPLErr PNGDataset::write_png_header()
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write palette if there is one.  Technically, I think it is      */
-/*      possible to write 16bit palettes for PNG, but we will omit      */
-/*      this for now.                                                   */
-/* -------------------------------------------------------------------- */
-
+    // Write the palette if there is one. Technically, it may be possible
+    // to write 16-bit palettes for PNG, but for now, doing so is omitted.
     if( nColorType == PNG_COLOR_TYPE_PALETTE )
     {
         GDALColorTable *poCT = GetRasterBand(1)->GetColorTable();
 
         int bHaveNoData = FALSE;
-        double	dfNoDataValue = GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
+        double dfNoDataValue = GetRasterBand(1)->GetNoDataValue( &bHaveNoData );
 
         m_pasPNGColors = reinterpret_cast<png_color *>(
             CPLMalloc( sizeof(png_color) * poCT->GetColorEntryCount() ) );
@@ -2329,10 +2245,8 @@ CPLErr PNGDataset::write_png_header()
         png_set_PLTE( m_hPNG, m_psPNGInfo, m_pasPNGColors,
                       poCT->GetColorEntryCount() );
 
-/* -------------------------------------------------------------------- */
-/*      If we have transparent elements in the palette we need to       */
-/*      write a transparency block.                                     */
-/* -------------------------------------------------------------------- */
+        // If we have transparent elements in the palette, we need to write a
+        // transparency block.
         if( bFoundTrans || bHaveNoData )
         {
             m_pabyAlpha = reinterpret_cast<unsigned char *>(
@@ -2356,12 +2270,10 @@ CPLErr PNGDataset::write_png_header()
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
 
-// static
 GDALDataset *PNGDataset::Create
 (
     const char* pszFilename,
@@ -2393,10 +2305,10 @@ GDALDataset *PNGDataset::Create
     }
 
     // Bands are:
-    // 1: grayscale or indexed color
-    // 2: gray plus alpha
-    // 3: rgb
-    // 4: rgb plus alpha
+    // 1: Grayscale or indexed color.
+    // 2: Gray plus alpha.
+    // 3: RGB.
+    // 4: RGB plus alpha.
 
     if(nXSize < 1 || nYSize < 1)
     {
@@ -2405,9 +2317,7 @@ GDALDataset *PNGDataset::Create
                   nXSize, nYSize );
     }
 
-/* -------------------------------------------------------------------- */
-/*      Setup some parameters.                                          */
-/* -------------------------------------------------------------------- */
+    // Set up some parameters.
     PNGDataset* poDS = new PNGDataset();
 
     poDS->nRasterXSize = nXSize;
@@ -2419,7 +2329,7 @@ GDALDataset *PNGDataset::Create
     {
       case 1:
         poDS->m_nColorType = PNG_COLOR_TYPE_GRAY;
-        break;// if a non-gray palette is set, we'll change this.
+        break;  // If a non-gray palette is set, we'll change this.
 
       case 2:
         poDS->m_nColorType = PNG_COLOR_TYPE_GRAY_ALPHA;
@@ -2439,21 +2349,15 @@ GDALDataset *PNGDataset::Create
     poDS->m_pabyBuffer = reinterpret_cast<GByte *>(
         CPLMalloc( nBands * nXSize * poDS->m_nBitDepth / 8 ) );
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
+    // Create band information objects.
     for( int iBand = 1; iBand <= poDS->nBands; iBand++ )
         poDS->SetBand( iBand, new PNGRasterBand( poDS, iBand ) );
 
-/* -------------------------------------------------------------------- */
-/*      Do we need a world file?                                        */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchBoolean( papszOptions, "WORLDFILE", FALSE ) )
+    // Do we need a world file?
+    if( CPLFetchBool( papszOptions, "WORLDFILE", false ) )
         poDS->m_bGeoTransformValid = TRUE;
 
-/* -------------------------------------------------------------------- */
-/*      Create the file.                                                */
-/* -------------------------------------------------------------------- */
+    // Create the file.
 
     poDS->m_fpImage = VSIFOpenL( pszFilename, "wb" );
     if( poDS->m_fpImage == NULL )
diff --git a/frmts/postgisraster/GNUmakefile b/frmts/postgisraster/GNUmakefile
index 8a62ff3..f716be2 100644
--- a/frmts/postgisraster/GNUmakefile
+++ b/frmts/postgisraster/GNUmakefile
@@ -1,6 +1,5 @@
 # USER CONFIGURATION
-# END OF USER CONFIGURATION 
-
+# END OF USER CONFIGURATION
 
 include ../../GDALmake.opt
 
@@ -12,7 +11,7 @@ CPPFLAGS	:= -I ../mem -I ../vrt $(XTRA_OPT) $(PG_INC)  $(CPPFLAGS)
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
 $(O_OBJ):       postgisraster.h ../vrt/vrtdataset.h ../mem/memdataset.h
- 
+
 clean:
 	rm -f *.o $(O_OBJ)
 
diff --git a/frmts/postgisraster/postgisraster.h b/frmts/postgisraster/postgisraster.h
index 3bbab65..a4c34f8 100644
--- a/frmts/postgisraster/postgisraster.h
+++ b/frmts/postgisraster/postgisraster.h
@@ -3,11 +3,11 @@
  * Project:  PostGIS Raster driver
  * Purpose:  Main header file for PostGIS Raster Driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
- * 							jorgearevalo at libregis.org
+ *                          jorgearevalo at libregis.org
  *
- * Author:	 David Zwarg, dzwarg at azavea.com
+ * Author:   David Zwarg, dzwarg at azavea.com
  *
- * Last changes: $Id: $
+ * Last changes: $Id: postgisraster.h 36501 2016-11-25 14:09:24Z rouault $
  *
  ***********************************************************************
  * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
@@ -56,8 +56,7 @@
  * size from sources and this value. So, please keep it at 2048 or
  * lower
  **/
-#define MAX_BLOCK_SIZE	2048
-
+#define MAX_BLOCK_SIZE 2048
 
 #define NO_VALID_RES "-1234.56"
 
@@ -85,7 +84,7 @@
 #define ELEMENTS_OF_METADATA_RECORD 10
 
 // Positions of elements of ST_Metadata PostGIS function
-#define POS_UPPERLEFTX	    0
+#define POS_UPPERLEFTX      0
 #define POS_UPPERLEFTY      1
 #define POS_WIDTH           2
 #define POS_HEIGHT          3
@@ -114,31 +113,30 @@ typedef enum
     AVERAGE_APPROX_RESOLUTION
 } ResolutionStrategy;
 
-
 /**
  * The driver can work in these modes:
  * - NO_MODE: Error case
  * - ONE_RASTER_PER_ROW: Each row of the requested table is considered
- * 	 	as a separated raster object. This is the default mode, if
- * 		database and table name are provided, and no mode is specified.
+ *              as a separated raster object. This is the default mode, if
+ *              database and table name are provided, and no mode is specified.
  * - ONE_RASTER_PER_TABLE: All the rows of the requested table are
- * 		considered as tiles of a bigger raster coverage (the whole
- * 		table). If database and table name are specified and mode = 2
- * 		is present in the connection string, this is the selected mode.
+ *              considered as tiles of a bigger raster coverage (the whole
+ *              table). If database and table name are specified and mode = 2
+ *              is present in the connection string, this is the selected mode.
  * - BROWSE_SCHEMA: If no table name is specified, just database and
- * 		schema names, the driver will yell of the schema's raster tables
- * 		as possible datasets.
+ *              schema names, the driver will yell of the schema's raster tables
+ *              as possible datasets.
  * - BROWSE_DATABASE: If no table name is specified, just database name,
- * 		the driver will yell of the database's raster tables as possible
- * 		datasets.
+ *              the driver will yell of the database's raster tables as possible
+ *              datasets.
  **/
 typedef enum
 {
-	NO_MODE,
-	ONE_RASTER_PER_ROW,
-	ONE_RASTER_PER_TABLE,
-	BROWSE_SCHEMA,
-	BROWSE_DATABASE
+    NO_MODE,
+    ONE_RASTER_PER_ROW,
+    ONE_RASTER_PER_TABLE,
+    BROWSE_SCHEMA,
+    BROWSE_DATABASE
 } WorkingMode;
 
 /**
@@ -155,13 +153,12 @@ typedef struct {
 } BandMetadata;
 
 typedef struct {
-	char * pszSchema;
-	char * pszTable;
-	char * pszColumn;
-	int nFactor;
+    char * pszSchema;
+    char * pszTable;
+    char * pszColumn;
+    int nFactor;
 } PROverview;
 
-
 // Some tools definitions
 char * ReplaceQuotes(const char *, int);
 char * ReplaceSingleQuotes(const char *, int);
@@ -187,7 +184,6 @@ public:
         const char * pszDbnameIn, const char * pszHostIn, const char * pszPortIn, const char * pszUserIn);
 };
 
-
 /***********************************************************************
  * PostGISRasterDataset: extends VRTDataset to support PostGIS Raster
  * datasets
@@ -216,7 +212,10 @@ private:
     ResolutionStrategy resolutionStrategy;
     WorkingMode nMode;
     int m_nTiles;
-    double xmin, ymin, xmax, ymax;
+    double xmin;
+    double ymin;
+    double xmax;
+    double ymax;
     PostGISRasterTileDataset ** papoSourcesHolders;
     CPLQuadTree * hQuadTree;
 
@@ -249,7 +248,7 @@ private:
     GBool BrowseDatabase(const char *, const char *);
     GBool AddComplexSource(PostGISRasterTileDataset* poRTDS);
     GBool GetDstWin(PostGISRasterTileDataset *, int *, int *, int *,
-		int *);
+                    int *);
     BandMetadata * GetBandsMetadata(int *);
     PROverview * GetOverviewTables(int *);
 
@@ -266,7 +265,7 @@ private:
     PostGISRasterTileDataset * GetMatchingSourceRef(double dfUpperLeftX, double dfUpperLeftY);
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
 public:
     PostGISRasterDataset();
@@ -278,13 +277,13 @@ public:
     static GBool InsertRaster(PGconn *, PostGISRasterDataset *,
         const char *, const char *, const char *);
     static CPLErr Delete(const char*);
-    virtual char      **GetMetadataDomainList();
-    char ** GetMetadata(const char *);
-    const char* GetProjectionRef();
-    CPLErr SetProjection(const char*);
-    CPLErr SetGeoTransform(double *);
-    CPLErr GetGeoTransform(double *);
-    char **GetFileList();
+    virtual char      **GetMetadataDomainList() override;
+    char ** GetMetadata(const char *) override;
+    const char* GetProjectionRef() override;
+    CPLErr SetProjection(const char*) override;
+    CPLErr SetGeoTransform(double *) override;
+    CPLErr GetGeoTransform(double *) override;
+    char **GetFileList() override;
 
     int    GetOverviewCount();
     PostGISRasterDataset* GetOverviewDS(int iOvr);
@@ -324,51 +323,49 @@ protected:
                                          int nLineSpace);
 public:
 
-    PostGISRasterRasterBand(PostGISRasterDataset *, int ,
-		GDALDataType, GBool, double, GBool);
+    PostGISRasterRasterBand( PostGISRasterDataset *, int ,
+                             GDALDataType, GBool, double, GBool );
 
     virtual ~PostGISRasterRasterBand();
 
-    virtual double GetNoDataValue(int *pbSuccess = NULL);
-    virtual CPLErr SetNoDataValue(double);
+    virtual double GetNoDataValue(int *pbSuccess = NULL) override;
+    virtual CPLErr SetNoDataValue(double) override;
     virtual CPLErr IRasterIO(GDALRWFlag, int, int, int, int, void *,
-		int, int, GDALDataType,
-        GSpacing nPixelSpace, GSpacing nLineSpace,
-        GDALRasterIOExtraArg* psExtraArg);
+                             int, int, GDALDataType,
+                             GSpacing nPixelSpace, GSpacing nLineSpace,
+                             GDALRasterIOExtraArg* psExtraArg) override;
 #ifdef notdef
     virtual CPLErr IReadBlock(int, int, void *);
 #endif
-    virtual int GetOverviewCount();
-    virtual GDALRasterBand * GetOverview(int);
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual int GetOverviewCount() override;
+    virtual GDALRasterBand * GetOverview(int) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 
-    virtual double GetMinimum( int *pbSuccess );
-    virtual double GetMaximum( int *pbSuccess );
-    virtual CPLErr ComputeRasterMinMax( int bApproxOK, double* adfMinMax );
+    virtual double GetMinimum( int *pbSuccess ) override;
+    virtual double GetMaximum( int *pbSuccess ) override;
+    virtual CPLErr ComputeRasterMinMax( int bApproxOK, double* adfMinMax ) override;
 };
 
-
-
 /***********************************************************************
  * PostGISRasterTileDataset: it holds just a raster tile
  **********************************************************************/
 class PostGISRasterTileRasterBand;
 
 class PostGISRasterTileDataset : public GDALDataset {
-	friend class PostGISRasterDataset;
-	friend class PostGISRasterRasterBand;
-	friend class PostGISRasterTileRasterBand;
+    friend class PostGISRasterDataset;
+    friend class PostGISRasterRasterBand;
+    friend class PostGISRasterTileRasterBand;
 private:
     PostGISRasterDataset* poRDS;
     char * pszPKID;
     double adfGeoTransform[6];
 
 public:
-	PostGISRasterTileDataset(PostGISRasterDataset* poRDS,
+    PostGISRasterTileDataset(PostGISRasterDataset* poRDS,
                              int nXSize,
                              int nYSize);
-	~PostGISRasterTileDataset();
-    CPLErr GetGeoTransform(double *);
+    ~PostGISRasterTileDataset();
+    CPLErr GetGeoTransform(double *) override;
     void   GetExtent(double* pdfMinX, double* pdfMinY, double* pdfMaxX, double* pdfMaxY);
     const char* GetPKID() const { return pszPKID; }
 };
@@ -378,7 +375,7 @@ public:
  * be used as a source for PostGISRasterRasterBand
  **********************************************************************/
 class PostGISRasterTileRasterBand : public GDALRasterBand {
-	friend class PostGISRasterRasterBand;
+    friend class PostGISRasterRasterBand;
     friend class PostGISRasterDataset;
 private:
     GBool bIsOffline;
@@ -388,12 +385,12 @@ private:
     VRTSource* poSource;
 
 public:
-	PostGISRasterTileRasterBand(
+    PostGISRasterTileRasterBand(
         PostGISRasterTileDataset * poRTDS, int nBand,
         GDALDataType eDataType,
         GBool bIsOffline = false);
-	~PostGISRasterTileRasterBand();
-	virtual CPLErr IReadBlock(int, int, void *);
+    virtual ~PostGISRasterTileRasterBand();
+    virtual CPLErr IReadBlock(int, int, void *) override;
 };
 
 #endif // POSTGISRASTER_H_INCLUDED
diff --git a/frmts/postgisraster/postgisrasterdataset.cpp b/frmts/postgisraster/postgisrasterdataset.cpp
index 50528ad..4fd17c5 100644
--- a/frmts/postgisraster/postgisrasterdataset.cpp
+++ b/frmts/postgisraster/postgisrasterdataset.cpp
@@ -5,9 +5,9 @@
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *                          jorgearevalo at libregis.org
  *
- * Author:	 David Zwarg, dzwarg at azavea.com
+ * Author:       David Zwarg, dzwarg at azavea.com
  *
- * Last changes: $Id: $
+ * Last changes: $Id: postgisrasterdataset.cpp 36682 2016-12-04 20:34:45Z rouault $
  *
  ***********************************************************************
  * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
@@ -38,6 +38,10 @@
 #include "postgisraster.h"
 #include <math.h>
 
+#include <algorithm>
+
+CPL_CVSID("$Id: postgisrasterdataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 #ifdef _WIN32
 #define rint(x) floor((x) + 0.5)
 #endif
@@ -92,41 +96,62 @@
 /************************
  * \brief Constructor
  ************************/
-PostGISRasterDataset::PostGISRasterDataset():VRTDataset(0, 0) {
-
-    papszSubdatasets = NULL;
-    nSrid = -1;
-    nOverviewFactor = 1;
-    nBandsToCreate = 0;
-    poConn = NULL;
-    bRegularBlocking = false;
-    bAllTilesSnapToSameGrid = false;
-
-    bCheckAllTiles = CPLTestBool(
-        CPLGetConfigOption("PR_ALLOW_WHOLE_TABLE_SCAN", "YES"));
-
-    pszSchema = NULL;
-    pszTable = NULL;
-    pszColumn = NULL;
-    pszWhere = NULL;
-    pszProjection = NULL;
+PostGISRasterDataset::PostGISRasterDataset() :
+    VRTDataset(0, 0),
+    papszSubdatasets(NULL),
+    nSrid(-1),
+    nOverviewFactor(1),
+    nBandsToCreate(0),
+    poConn(NULL),
+    bRegularBlocking(false),
+    bAllTilesSnapToSameGrid(false),
+    bCheckAllTiles(CPLTestBool(
+        CPLGetConfigOption("PR_ALLOW_WHOLE_TABLE_SCAN", "YES"))),
+    pszSchema(NULL),
+    pszTable(NULL),
+    pszColumn(NULL),
+    pszWhere(NULL),
+    pszPrimaryKeyName(NULL),
+    bIsFastPK(false),
+    bHasTriedFetchingPrimaryKeyName(false),
+    pszProjection(NULL),
+    // Default
+    resolutionStrategy(AVERAGE_APPROX_RESOLUTION),
+    nMode(NO_MODE),
+    m_nTiles(0),
+    xmin(0.0),
+    ymin(0.0),
+    xmax(0.0),
+    ymax(0.0),
+    papoSourcesHolders(NULL),
+    hQuadTree(NULL),
+    bHasBuiltOverviews(false),
+    nOverviewCount(0),
+    poParentDS(NULL),
+    papoOverviewDS(NULL),
+    bAssumeMultiBandReadPattern(true),
+    nNextExpectedBand(1),
+    nXOffPrev(0),
+    nYOffPrev(0),
+    nXSizePrev(0),
+    nYSizePrev(0),
+    bHasTriedHasSpatialIndex(false),
+    bHasSpatialIndex(false),
+    bBuildQuadTreeDynamically(false),
+    bTilesSameDimension(false),
+    nTileWidth(0),
+  nTileHeight(0)
+{
 
     adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = 0.0;
     adfGeoTransform[GEOTRSFRM_ROTATION_PARAM1] = 0.0;
     adfGeoTransform[GEOTRSFRM_TOPLEFT_Y] = 0.0;
     adfGeoTransform[GEOTRSFRM_ROTATION_PARAM2] = 0.0;
-    adfGeoTransform[GEOTRSFRM_WE_RES] = 0;
-    adfGeoTransform[GEOTRSFRM_NS_RES] = 0;
-
     adfGeoTransform[GEOTRSFRM_WE_RES] =
         CPLAtof(CPLGetConfigOption("PR_WE_RES", NO_VALID_RES));
-
     adfGeoTransform[GEOTRSFRM_NS_RES] =
         CPLAtof(CPLGetConfigOption("PR_NS_RES", NO_VALID_RES));
 
-    // Default
-    resolutionStrategy = AVERAGE_APPROX_RESOLUTION;
-
     const char * pszTmp = NULL;
     // We ignore this option if we provided the desired resolution
     if (CPLIsEqual(adfGeoTransform[GEOTRSFRM_WE_RES], CPLAtof(NO_VALID_RES)) ||
@@ -150,10 +175,9 @@ PostGISRasterDataset::PostGISRasterDataset():VRTDataset(0, 0) {
 
         else if (EQUAL(pszTmp, "AVERAGE"))
             resolutionStrategy = AVERAGE_RESOLUTION;
-
     }
-
-    else {
+    else
+    {
         resolutionStrategy = USER_RESOLUTION;
 #ifdef DEBUG_VERBOSE
         pszTmp = "USER";
@@ -165,50 +189,18 @@ PostGISRasterDataset::PostGISRasterDataset():VRTDataset(0, 0) {
                 "STRATEGY = %s", pszTmp);
 #endif
 
-    m_nTiles = 0;
-    nMode = NO_MODE;
     poDriver = NULL;
 
-    nRasterXSize = nRasterYSize = 0;
-    pszPrimaryKeyName = NULL;
-    bIsFastPK = false;
-    bHasTriedFetchingPrimaryKeyName = false;
-
-    papoSourcesHolders = NULL;
-    hQuadTree = NULL;
-
-    bHasBuiltOverviews = false;
-    nOverviewCount = 0;
-    papoOverviewDS = NULL;
-    poParentDS = NULL;
-
-    bAssumeMultiBandReadPattern = true;
-    nNextExpectedBand = 1;
-    nXOffPrev = 0;
-    nYOffPrev = 0;
-    nXSizePrev = 0;
-    nYSizePrev = 0;
-
-    bHasTriedHasSpatialIndex = false;
-    bHasSpatialIndex = false;
-
-    bBuildQuadTreeDynamically = false;
-
-    bTilesSameDimension = false;
-    nTileWidth = 0;
-    nTileHeight = 0;
+    nRasterXSize = 0;
+    nRasterYSize = 0;
 
     SetWritable(false);
 
-
-    /**
-     * TODO: Parametrize bAllTilesSnapToSameGrid. It controls if all the
-     * raster rows, in ONE_RASTER_PER_TABLE mode, must be checked to
-     * test if they snap to the same grid and have the same SRID. It can
-     * be the user decision, if he/she's sure all the rows pass the
-     * test and want more speed.
-     **/
-
+    // TODO: Parametrize bAllTilesSnapToSameGrid. It controls if all the
+    // raster rows, in ONE_RASTER_PER_TABLE mode, must be checked to
+    // test if they snap to the same grid and have the same SRID. It can
+    // be the user decision, if he/she's sure all the rows pass the
+    // test and want more speed.
 }
 
 /************************
@@ -263,12 +255,13 @@ PostGISRasterDataset::~PostGISRasterDataset() {
     // of the deleting the source holders just below.
     CloseDependentDatasets();
 
-    if (papoSourcesHolders) {
+    if (papoSourcesHolders)
+    {
         int i;
-        for(i = 0; i < m_nTiles; i++) {
+        for(i = 0; i < m_nTiles; i++)
+        {
             if (papoSourcesHolders[i])
                 delete papoSourcesHolders[i];
-
         }
 
         VSIFree(papoSourcesHolders);
@@ -439,13 +432,11 @@ const char * PostGISRasterDataset::GetPrimaryKeyRef()
             pszSchema, pszTable);
 
             pszPrimaryKeyName = NULL; // Just in case
-
         }
-
-        else {
+        else
+        {
             pszPrimaryKeyName = CPLStrdup(PQgetvalue(poResult, 0, 0));
         }
-
     }
 
     // Ok, get the primary key
@@ -459,7 +450,6 @@ const char * PostGISRasterDataset::GetPrimaryKeyRef()
     return pszPrimaryKeyName;
 }
 
-
 /***********************************************************************
  * \brief Look for raster tables in database and store them as
  * subdatasets
@@ -486,7 +476,6 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
     PGresult * poResult = NULL;
     CPLString osCommand;
 
-
     /*************************************************************
      * Fetch all the raster tables and store them as subdatasets
      *************************************************************/
@@ -513,7 +502,6 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
             return false;
         }
 
-
         nTuples = PQntuples(poResult);
         for (i = 0; i < nTuples; i++) {
             l_pszSchema = PQgetvalue(poResult, i, 0);
@@ -533,13 +521,13 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
         }
 
         PQclear(poResult);
-
     }
         /***************************************************************
          * Fetch all the schema's raster tables and store them as
          * subdatasets
          **************************************************************/
-    else {
+    else
+    {
         osCommand.Printf("select pg_class.relname as table, "
             "pg_attribute.attname as column from pg_class, "
             "pg_namespace,pg_attribute, pg_type where "
@@ -564,7 +552,6 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
             return false;
         }
 
-
         nTuples = PQntuples(poResult);
         for (i = 0; i < nTuples; i++) {
             l_pszTable = PQgetvalue(poResult, i, 0);
@@ -588,7 +575,6 @@ GBool PostGISRasterDataset::BrowseDatabase(const char* pszCurrentSchema,
     return true;
 }
 
-
 /***********************************************************************
  * \brief Look for overview tables for the bands of the current dataset
  **********************************************************************/
@@ -662,7 +648,6 @@ PROverview * PostGISRasterDataset::GetOverviewTables(int * pnOverviews)
 
         poOV[iOVerview].nFactor =
             atoi(PQgetvalue(poResult, iOVerview, 1));
-
     }
 
     if (pnOverviews)
@@ -995,7 +980,6 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
     CPLString osCommand;
     CPLString osSpatialFilter;
     CPLString osIDsToFetch;
-    PGresult * poResult;
 
     int bFetchAll = FALSE;
     if( nXOff == 0 && nYOff == 0 && nXSize == nRasterXSize && nYSize == nRasterYSize )
@@ -1026,6 +1010,7 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
     int bLoadRasters = FALSE;
     int bAllBandCaching = FALSE;
 
+    PGresult *poResult = NULL;
     if( m_nTiles > 0 && !bFetchAll )
     {
         osCommand.Printf("SELECT %s FROM %s.%s",
@@ -1090,7 +1075,7 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
             }
             if( bFetchTile )
             {
-                if( osIDsToFetch.size() != 0 )
+                if( !osIDsToFetch.empty() )
                     osIDsToFetch += ",";
                 osIDsToFetch += "'";
                 osIDsToFetch += pszPKID;
@@ -1101,7 +1086,7 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
         PQclear(poResult);
     }
 
-    if( bFetchAll || osIDsToFetch.size() != 0 || osSpatialFilter.size() != 0 )
+    if( bFetchAll || !osIDsToFetch.empty() || !osSpatialFilter.empty() )
     {
         osCommand.Printf("SELECT %s, ST_Metadata(%s)",
                          pszPrimaryKeyName, pszColumn);
@@ -1114,7 +1099,7 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
         }
         osCommand += CPLSPrintf(" FROM %s.%s",
                                 pszSchema, pszTable);
-        if( osIDsToFetch.size() != 0 )
+        if( !osIDsToFetch.empty() )
         {
             osCommand += " WHERE ";
             osCommand += pszPrimaryKeyName;
@@ -1122,7 +1107,7 @@ GBool PostGISRasterDataset::LoadSources(int nXOff, int nYOff, int nXSize, int nY
             osCommand += osIDsToFetch;
             osCommand += ")";
         }
-        else if ( osSpatialFilter.size() != 0 )
+        else if ( !osSpatialFilter.empty() )
         {
             osCommand += " WHERE ";
             osCommand += osSpatialFilter;
@@ -1252,7 +1237,6 @@ BandMetadata * PostGISRasterDataset::GetBandsMetadata(int * pnBands)
         return NULL;
     }
 
-
     int iBand = 0;
 
     for(iBand = 0; iBand < nTuples; iBand++) {
@@ -1307,7 +1291,6 @@ BandMetadata * PostGISRasterDataset::GetBandsMetadata(int * pnBands)
     PQclear(poResult);
 
     return poBMD;
-
 }
 
 /***********************************************************************
@@ -1453,7 +1436,6 @@ PostGISRasterTileDataset* PostGISRasterDataset::BuildRasterTileDataset(const cha
     return poRTDS;
 }
 
-
 /********************************************************
  * \brief Updates components GEOTRSFRM_WE_RES and GEOTRSFRM_NS_RES
  *        of dataset adfGeoTransform
@@ -1470,7 +1452,7 @@ void PostGISRasterDataset::UpdateGlobalResolutionWithTileResolution(
 
     else if (resolutionStrategy == HIGHEST_RESOLUTION)  {
         adfGeoTransform[GEOTRSFRM_WE_RES] =
-            MIN(adfGeoTransform[GEOTRSFRM_WE_RES],
+            std::min(adfGeoTransform[GEOTRSFRM_WE_RES],
                 tilePixelSizeX);
 
         /**
@@ -1488,29 +1470,28 @@ void PostGISRasterDataset::UpdateGlobalResolutionWithTileResolution(
             **/
         if (tilePixelSizeY < 0.0)
             adfGeoTransform[GEOTRSFRM_NS_RES] =
-                MAX(adfGeoTransform[GEOTRSFRM_NS_RES],
+                std::max(adfGeoTransform[GEOTRSFRM_NS_RES],
                 tilePixelSizeY);
         else
             adfGeoTransform[GEOTRSFRM_NS_RES] =
-                MIN(adfGeoTransform[GEOTRSFRM_NS_RES],
+                std::min(adfGeoTransform[GEOTRSFRM_NS_RES],
                 tilePixelSizeY);
     }
 
     else if (resolutionStrategy == LOWEST_RESOLUTION) {
         adfGeoTransform[GEOTRSFRM_WE_RES] =
-            MAX(adfGeoTransform[GEOTRSFRM_WE_RES],
+            std::max(adfGeoTransform[GEOTRSFRM_WE_RES],
                 tilePixelSizeX);
 
         if (tilePixelSizeY < 0.0)
             adfGeoTransform[GEOTRSFRM_NS_RES] =
-                MIN(adfGeoTransform[GEOTRSFRM_NS_RES],
+                std::min(adfGeoTransform[GEOTRSFRM_NS_RES],
                 tilePixelSizeY);
         else
             adfGeoTransform[GEOTRSFRM_NS_RES] =
-                MAX(adfGeoTransform[GEOTRSFRM_NS_RES],
+                std::max(adfGeoTransform[GEOTRSFRM_NS_RES],
                 tilePixelSizeY);
     }
-
 }
 
 /***********************************************************************
@@ -1674,7 +1655,6 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
             CPLAtof(papszParams[POS_SCALEY]);
 
         CSLDestroy(papszParams);
-
     }
 
     /**
@@ -1731,7 +1711,6 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
             }
 
             papoSourcesHolders[nValidTiles++] = poRTDS;
-
         } // end for
 
         l_nTiles = nValidTiles;
@@ -1746,7 +1725,6 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
             adfGeoTransform[GEOTRSFRM_WE_RES] /= l_nTiles;
             adfGeoTransform[GEOTRSFRM_NS_RES] /= l_nTiles;
         }
-
     } // end else
 
     /**
@@ -1831,8 +1809,6 @@ GBool PostGISRasterDataset::ConstructOneDatasetFromTiles(
     return true;
 }
 
-
-
 /***********************************************************************
  * \brief Construct subdatasets and show them.
  *
@@ -1879,23 +1855,18 @@ const char * pszValidConnectionString)
 
     // Subdatasets identified by upper left pixel
     else {
-
-        char * pszRes;
-        char * pszFilteredRes;
-        char ** papszParams;
-
-        for(i = 0; i < l_nTiles; i++) {
-
-            pszRes = CPLStrdup(PQgetvalue(poResult, i, 0));
+        for(i = 0; i < l_nTiles; i++)
+        {
+            char * pszRes = CPLStrdup(PQgetvalue(poResult, i, 0));
 
             // Skip first "("
-            pszFilteredRes = pszRes + 1;
+            char * pszFilteredRes = pszRes + 1;
 
             // Skip last ")"
             pszFilteredRes[strlen(pszFilteredRes)-1] = '\0';
 
             // Tokenize
-            papszParams =
+            char ** papszParams =
                 CSLTokenizeString2(pszFilteredRes, ",",
                     CSLT_HONOURSTRINGS);
 
@@ -1936,8 +1907,6 @@ const char * pszValidConnectionString)
     return true;
 }
 
-
-
 /***********************************************************************
  * \brief Set the general raster properties.
  *
@@ -2028,13 +1997,12 @@ GBool PostGISRasterDataset::SetRasterProperties
         // Query execution error
         if(poResult == NULL ||
             PQresultStatus(poResult) != PGRES_TUPLES_OK ||
-            PQntuples(poResult) < 0) {
-
+            PQntuples(poResult) < 0)
+        {
             bNeedToCheckWholeTable = true;
 
             if (poResult)
                 PQclear(poResult);
-
         }
 
         /**
@@ -2076,7 +2044,8 @@ GBool PostGISRasterDataset::SetRasterProperties
         }
 
         // We should check whole table but we can't
-        if (bNeedToCheckWholeTable && !bCheckAllTiles) {
+        if (bNeedToCheckWholeTable && !bCheckAllTiles)
+        {
             ReportError(CE_Failure, CPLE_AppDefined, "Cannot find "
             "information about %s.%s table in raster_columns view. "
             "Please, execute AddRasterConstraints PostGIS function to "
@@ -2091,7 +2060,6 @@ GBool PostGISRasterDataset::SetRasterProperties
             PQclear(poResult);
 
             return false;
-
         }
 
         // We should check the whole table and we can
@@ -2144,7 +2112,6 @@ GBool PostGISRasterDataset::SetRasterProperties
         return false;
     }
 
-
     /**
      * Found more than one SRID value in the table. Not allowed.
      *
@@ -2415,7 +2382,6 @@ GBool PostGISRasterDataset::SetRasterProperties
         return res;
     }
 
-
     /***************************************************************
      * One raster per row: collect subdatasets
      **************************************************************/
@@ -2506,7 +2472,6 @@ GetConnectionInfo(const char * pszFilename,
             *nMode = ONE_RASTER_PER_TABLE;
         }
 
-
         /* Remove the mode from connection string */
         papszParams = CSLRemoveStrings(papszParams, nPos, 1, NULL);
     }
@@ -2737,7 +2702,6 @@ GetConnection(const char * pszFilename, char ** ppszConnectionString,
     char ** ppszSchema, char ** ppszTable, char ** ppszColumn,
     char ** ppszWhere, WorkingMode * nMode, GBool * bBrowseDatabase)
 {
-    PostGISRasterDriver * poDriver;
     PGconn * poConn = NULL;
     char * pszDbname = NULL;
     char * pszHost = NULL;
@@ -2752,7 +2716,7 @@ GetConnection(const char * pszFilename, char ** ppszConnectionString,
         /**************************************************************
          * Open a new database connection
          **************************************************************/
-        poDriver =
+        PostGISRasterDriver * poDriver =
             (PostGISRasterDriver *)GDALGetDriverByName("PostGISRaster");
 
         poConn = poDriver->GetConnection(*ppszConnectionString,
@@ -2800,11 +2764,11 @@ int PostGISRasterDataset::Identify(GDALOpenInfo* poOpenInfo)
 /***********************************************************************
  * \brief Open a connection with PostgreSQL. The connection string will
  * have the PostgreSQL accepted format, plus the next key=value pairs:
- *  schema = <schema_name>
- *  table = <table_name>
- *  column = <column_name>
- *  where = <SQL where>
- *  mode = <working mode> (1 or 2)
+ *  schema = <schema_name>
+ *  table = <table_name>
+ *  column = <column_name>
+ *  where = <SQL where>
+ *  mode = <working mode> (1 or 2)
  *
  * These pairs are used for selecting the right raster table.
  **********************************************************************/
@@ -2838,7 +2802,6 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
         return NULL;
     }
 
-
     /*******************************************************************
      * No table will be read. Only shows information about the existent
      * raster tables
@@ -2915,7 +2878,6 @@ GDALDataset* PostGISRasterDataset::Open(GDALOpenInfo* poOpenInfo) {
 
     CPLFree(pszConnectionString);
     return poDS;
-
 }
 
 /************************************************************************/
@@ -2949,7 +2911,6 @@ char** PostGISRasterDataset::GetMetadata(const char *pszDomain) {
  *****************************************************/
 const char* PostGISRasterDataset::GetProjectionRef() {
     CPLString osCommand;
-    PGresult* poResult;
 
     if (nSrid == -1)
         return "";
@@ -2962,7 +2923,7 @@ const char* PostGISRasterDataset::GetProjectionRef() {
      ********************************************************/
     osCommand.Printf("SELECT srtext FROM spatial_ref_sys where SRID=%d",
             nSrid);
-    poResult = PQexec(this->poConn, osCommand.c_str());
+    PGresult* poResult = PQexec(this->poConn, osCommand.c_str());
     if (poResult && PQresultStatus(poResult) == PGRES_TUPLES_OK
             && PQntuples(poResult) > 0) {
         pszProjection = CPLStrdup(PQgetvalue(poResult, 0, 0));
@@ -2982,10 +2943,8 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef) {
     VALIDATE_POINTER1(pszProjectionRef, "SetProjection", CE_Failure);
 
     CPLString osCommand;
-    PGresult * poResult;
     int nFetchedSrid = -1;
 
-
     /*****************************************************************
      * Check if the dataset allows updating
      *****************************************************************/
@@ -3002,7 +2961,7 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef) {
     // First, WKT text
     osCommand.Printf("SELECT srid FROM spatial_ref_sys where srtext='%s'",
             pszProjectionRef);
-    poResult = PQexec(poConn, osCommand.c_str());
+    PGresult * poResult = PQexec(poConn, osCommand.c_str());
 
     if (poResult && PQresultStatus(poResult) == PGRES_TUPLES_OK
             && PQntuples(poResult) > 0) {
@@ -3012,7 +2971,6 @@ CPLErr PostGISRasterDataset::SetProjection(const char * pszProjectionRef) {
         // update class attribute
         nSrid = nFetchedSrid;
 
-
         // update raster_columns table
         osCommand.Printf("UPDATE raster_columns SET srid=%d WHERE \
                     r_table_name = '%s' AND r_column = '%s'",
@@ -3108,7 +3066,6 @@ CPLErr PostGISRasterDataset::GetGeoTransform(double * padfGeoTransform) {
     return CE_None;
 }
 
-
 /*********************************************************
  * \brief Fetch files forming dataset.
  *
@@ -3118,7 +3075,7 @@ CPLErr PostGISRasterDataset::GetGeoTransform(double * padfGeoTransform) {
  *********************************************************/
 char **PostGISRasterDataset::GetFileList()
 {
-	return NULL;
+    return NULL;
 }
 
 /********************************************************
@@ -3139,7 +3096,6 @@ PostGISRasterDataset::CreateCopy( CPL_UNUSED const char * pszFilename,
     GBool bBrowseDatabase = false;
     WorkingMode nMode;
     char* pszConnectionString = NULL;
-    const char* pszSubdatasetName;
     PGconn * poConn = NULL;
     PGresult * poResult = NULL;
     CPLString osCommand;
@@ -3155,7 +3111,6 @@ PostGISRasterDataset::CreateCopy( CPL_UNUSED const char * pszFilename,
 
     // Now we can do the cast
     PostGISRasterDataset *poSrcDS = (PostGISRasterDataset *)poGSrcDS;
-    PostGISRasterDataset *poSubDS;
 
     // Check connection string
     if (pszFilename == NULL ||
@@ -3295,6 +3250,8 @@ PostGISRasterDataset::CreateCopy( CPL_UNUSED const char * pszFilename,
 
     PQclear(poResult);
 
+    const char* pszSubdatasetName = NULL;
+    PostGISRasterDataset *poSubDS = NULL;
     if (poSrcDS->nMode == ONE_RASTER_PER_TABLE) {
         // one raster per table
 
diff --git a/frmts/postgisraster/postgisrasterdriver.cpp b/frmts/postgisraster/postgisrasterdriver.cpp
index 81999ba..a4e8d55 100644
--- a/frmts/postgisraster/postgisrasterdriver.cpp
+++ b/frmts/postgisraster/postgisrasterdriver.cpp
@@ -4,7 +4,7 @@
  * Purpose:  Implements PostGIS Raster driver class methods
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *
- * Last changes: $Id: $
+ * Last changes: $Id: postgisrasterdriver.cpp 35897 2016-10-24 11:54:24Z goatbar $
  *
  ******************************************************************************
  * Copyright (c) 2010, Jorge Arevalo, jorge.arevalo at deimos-space.com
@@ -31,13 +31,14 @@
 #include "postgisraster.h"
 #include "cpl_multiproc.h"
 
+CPL_CVSID("$Id: postgisrasterdriver.cpp 35897 2016-10-24 11:54:24Z goatbar $");
+
 /************************
  * \brief Constructor
  ************************/
-PostGISRasterDriver::PostGISRasterDriver()
-{
-    hMutex = NULL;
-}
+PostGISRasterDriver::PostGISRasterDriver() :
+    hMutex(NULL)
+{}
 
 /************************
  * \brief Destructor
@@ -93,7 +94,6 @@ PGconn* PostGISRasterDriver::GetConnection(const char* pszConnectionString,
     if( oIter != oMapConnection.end() )
         return oIter->second;
 
-
     /**
      * There's no existing connection. Create a new one.
      **/
diff --git a/frmts/postgisraster/postgisrasterrasterband.cpp b/frmts/postgisraster/postgisrasterrasterband.cpp
index b682c17..a10b007 100644
--- a/frmts/postgisraster/postgisrasterrasterband.cpp
+++ b/frmts/postgisraster/postgisrasterrasterband.cpp
@@ -5,9 +5,9 @@
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *                          jorgearevalo at libregis.org
  *
- * Author:	 David Zwarg, dzwarg at azavea.com
+ * Author:       David Zwarg, dzwarg at azavea.com
  *
- * Last changes: $Id: $
+ * Last changes: $Id: postgisrasterrasterband.cpp 36682 2016-12-04 20:34:45Z rouault $
  *
  ***********************************************************************
  * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
@@ -35,6 +35,8 @@
  **********************************************************************/
 #include "postgisraster.h"
 
+CPL_CVSID("$Id: postgisrasterrasterband.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 /**
  * \brief Constructor.
  *
@@ -44,20 +46,19 @@ PostGISRasterRasterBand::PostGISRasterRasterBand(
     PostGISRasterDataset * poDSIn, int nBandIn,
     GDALDataType eDataTypeIn, GBool bNoDataValueSetIn, double dfNodata,
     GBool bIsOfflineIn = false) :
-    VRTSourcedRasterBand(poDSIn, nBandIn)
+    VRTSourcedRasterBand(poDSIn, nBandIn),
+    bIsOffline(bIsOfflineIn),
+    pszSchema(poDSIn->pszSchema),
+    pszTable(poDSIn->pszTable),
+    pszColumn(poDSIn->pszColumn)
 {
     /* Basic properties */
-    this->poDS = poDSIn;
-    this->bIsOffline = bIsOfflineIn;
-    this->nBand = nBandIn;
-
-    this->eDataType = eDataTypeIn;
-    this->m_bNoDataValueSet = bNoDataValueSetIn;
-    this->m_dfNoDataValue = dfNodata;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
-    this->pszSchema = poDSIn->pszSchema;
-    this->pszTable = poDSIn->pszTable;
-    this->pszColumn = poDSIn->pszColumn;
+    eDataType = eDataTypeIn;
+    m_bNoDataValueSet = bNoDataValueSetIn;
+    m_dfNoDataValue = dfNodata;
 
     nRasterXSize = poDS->GetRasterXSize();
     nRasterYSize = poDS->GetRasterYSize();
@@ -73,8 +74,8 @@ PostGISRasterRasterBand::PostGISRasterRasterBand(
      * table. Otherwise, the reading operations are performed by the
      * sources, not the PostGISRasterBand object itself.
      ******************************************************************/
-    this->nBlockXSize = MIN(MAX_BLOCK_SIZE, this->nRasterXSize);
-    this->nBlockYSize = MIN(MAX_BLOCK_SIZE, this->nRasterYSize);
+    nBlockXSize = MIN(MAX_BLOCK_SIZE, this->nRasterXSize);
+    nBlockYSize = MIN(MAX_BLOCK_SIZE, this->nRasterYSize);
 
 #ifdef DEBUG_VERBOSE
     CPLDebug("PostGIS_Raster",
@@ -93,9 +94,7 @@ PostGISRasterRasterBand::PostGISRasterRasterBand(
 /***********************************************
  * \brief: Band destructor
  ***********************************************/
-PostGISRasterRasterBand::~PostGISRasterRasterBand()
-{
-}
+PostGISRasterRasterBand::~PostGISRasterRasterBand() {}
 
 #ifdef notdef
 /***********************************************************************
@@ -108,7 +107,7 @@ PostGISRasterRasterBand::~PostGISRasterRasterBand()
 void PostGISRasterRasterBand::NullBlock(void *pData)
 {
     int nWords = nBlockXSize * nBlockYSize;
-    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
+    int nDataTypeSize = GDALGetDataTypeSizeBytes(eDataType);
 
     int bNoDataSet;
     double dfNoData = GetNoDataValue(&bNoDataSet);
@@ -257,7 +256,6 @@ void PostGISRasterRasterBand::NullBuffer(void* pData,
     }
 }
 
-
 /********************************************************
  * \brief SortTilesByPKID
  ********************************************************/
@@ -508,7 +506,7 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
             // If we have a PKID, add the tile PKID to the list
             if (poTile->pszPKID != NULL)
             {
-                if( osIDsToFetch.size() != 0 )
+                if( !osIDsToFetch.empty() )
                     osIDsToFetch += ",";
                 osIDsToFetch += "'";
                 osIDsToFetch += poTile->pszPKID;
@@ -611,7 +609,6 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
          * index exist.
          **/
         CPLString osCommand;
-        PGresult * poResult;
 
         CPLString osRasterToFetch;
         if (bAllBandCaching)
@@ -620,7 +617,7 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
             osRasterToFetch.Printf("ST_Band(%s, %d)", pszColumn, nBand);
 
         int bHasWhere = FALSE;
-        if (osIDsToFetch.size() && (poRDS->bIsFastPK || !(poRDS->HasSpatialIndex())) ) {
+        if (!osIDsToFetch.empty() && (poRDS->bIsFastPK || !(poRDS->HasSpatialIndex())) ) {
             osCommand.Printf("SELECT %s, "
                 "ST_Metadata(%s), %s FROM %s.%s",
                 osRasterToFetch.c_str(), pszColumn,
@@ -673,7 +670,7 @@ CPLErr PostGISRasterRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff,
             osCommand += ")";
         }
 
-        poResult = PQexec(poRDS->poConn, osCommand.c_str());
+        PGresult * poResult = PQexec(poRDS->poConn, osCommand.c_str());
 
 #ifdef DEBUG_QUERY
         CPLDebug("PostGIS_Raster",
diff --git a/frmts/postgisraster/postgisrastertiledataset.cpp b/frmts/postgisraster/postgisrastertiledataset.cpp
index abc3038..19d17ff 100644
--- a/frmts/postgisraster/postgisrastertiledataset.cpp
+++ b/frmts/postgisraster/postgisrastertiledataset.cpp
@@ -5,7 +5,7 @@
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *                          jorgearevalo at libregis.org
  *
- * Last changes: $Id: $
+ * Last changes: $Id: postgisrastertiledataset.cpp 35897 2016-10-24 11:54:24Z goatbar $
  *
  ***********************************************************************
  * Copyright (c) 2013, Jorge Arevalo
@@ -33,17 +33,19 @@
  ************************************************************************/
 #include "postgisraster.h"
 
+CPL_CVSID("$Id: postgisrastertiledataset.cpp 35897 2016-10-24 11:54:24Z goatbar $");
+
 /************************
  * \brief Constructor
  ************************/
-PostGISRasterTileDataset::PostGISRasterTileDataset(PostGISRasterDataset* poRDSIn,
-                                                   int nXSize,
-                                                   int nYSize)
+PostGISRasterTileDataset::PostGISRasterTileDataset( PostGISRasterDataset* poRDSIn,
+                                                    int nXSize,
+                                                    int nYSize ) :
+    poRDS(poRDSIn),
+    pszPKID(NULL)
 {
-    this->poRDS = poRDSIn;
-    this->pszPKID = NULL;
-    this->nRasterXSize = nXSize;
-    this->nRasterYSize = nYSize;
+    nRasterXSize = nXSize;
+    nRasterYSize = nYSize;
 
     adfGeoTransform[GEOTRSFRM_TOPLEFT_X] = 0;
     adfGeoTransform[GEOTRSFRM_WE_RES] = 1;
@@ -53,7 +55,6 @@ PostGISRasterTileDataset::PostGISRasterTileDataset(PostGISRasterDataset* poRDSIn
     adfGeoTransform[GEOTRSFRM_NS_RES] = 1;
 }
 
-
 /************************
  * \brief Destructor
  ************************/
diff --git a/frmts/postgisraster/postgisrastertilerasterband.cpp b/frmts/postgisraster/postgisrastertilerasterband.cpp
index 1c1f5cd..7583ea1 100644
--- a/frmts/postgisraster/postgisrastertilerasterband.cpp
+++ b/frmts/postgisraster/postgisrastertilerasterband.cpp
@@ -5,7 +5,7 @@
  * driver
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *                          jorgearevalo at libregis.org
- * Last changes: $Id: $
+ * Last changes: $Id: postgisrastertilerasterband.cpp 35929 2016-10-25 16:09:00Z goatbar $
  *
  ***********************************************************************
  * Copyright (c) 2009 - 2013, Jorge Arevalo
@@ -33,17 +33,20 @@
  **********************************************************************/
 #include "postgisraster.h"
 
+CPL_CVSID("$Id: postgisrastertilerasterband.cpp 35929 2016-10-25 16:09:00Z goatbar $");
+
 /************************
  * \brief Constructor
  ************************/
 PostGISRasterTileRasterBand::PostGISRasterTileRasterBand(
     PostGISRasterTileDataset * poRTDSIn, int nBandIn,
-    GDALDataType eDataTypeIn, GBool bIsOfflineIn)
+    GDALDataType eDataTypeIn, GBool bIsOfflineIn) :
+    bIsOffline(bIsOfflineIn),
+    poSource(NULL)
 {
-    /* Basic properties */
-    this->poDS = poRTDSIn;
-    this->bIsOffline = bIsOfflineIn;
-    this->nBand = nBandIn;
+    // Basic properties.
+    poDS = poRTDSIn;
+    nBand = nBandIn;
 
 #if 0
     CPLDebug("PostGIS_Raster",
@@ -52,17 +55,15 @@ PostGISRasterTileRasterBand::PostGISRasterTileRasterBand(
         poRTDS->GetRasterYSize());
 #endif
 
-    this->eDataType = eDataTypeIn;
+    eDataType = eDataTypeIn;
 
     nRasterXSize = poRTDSIn->GetRasterXSize();
     nRasterYSize = poRTDSIn->GetRasterYSize();
 
     nBlockXSize = nRasterXSize;
     nBlockYSize = nRasterYSize;
-    poSource = NULL;
 }
 
-
 /************************
  * \brief Destructor
  ************************/
@@ -101,12 +102,12 @@ CPLErr PostGISRasterTileRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
         (PostGISRasterTileDataset *)poDS;
 
     // Get by PKID
-    if (poRTDS->poRDS->pszPrimaryKeyName) {
+    if (poRTDS->poRDS->pszPrimaryKeyName)
+    {
         //osCommand.Printf("select ST_AsBinary(st_band(%s, %d),TRUE) from %s.%s where "
         osCommand.Printf("select st_band(%s, %d) from %s.%s where "
             "%s = '%s'", poRTDS->poRDS->pszColumn, nBand, poRTDS->poRDS->pszSchema, poRTDS->poRDS->pszTable,
             poRTDS->poRDS->pszPrimaryKeyName, poRTDS->pszPKID);
-
     }
 
     // Get by upperleft
@@ -141,7 +142,6 @@ CPLErr PostGISRasterTileRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
         return CE_Failure;
     }
 
-
     // TODO: Check this
     if (bIsOffline) {
         CPLError(CE_Failure, CPLE_AppDefined, "This raster has outdb "
diff --git a/frmts/postgisraster/postgisrastertools.cpp b/frmts/postgisraster/postgisrastertools.cpp
index c409cca..61e6ab9 100644
--- a/frmts/postgisraster/postgisrastertools.cpp
+++ b/frmts/postgisraster/postgisrastertools.cpp
@@ -5,9 +5,9 @@
  * Author:   Jorge Arevalo, jorge.arevalo at deimos-space.com
  *                          jorgearevalo at libregis.org
  *
- * Author:	 David Zwarg, dzwarg at azavea.com
+ * Author:       David Zwarg, dzwarg at azavea.com
  *
- * Last changes: $Id: $
+ * Last changes: $Id: postgisrastertools.cpp 35929 2016-10-25 16:09:00Z goatbar $
  *
  ***********************************************************************
  * Copyright (c) 2009 - 2013, Jorge Arevalo, David Zwarg
@@ -34,6 +34,8 @@
  **********************************************************************/
  #include "postgisraster.h"
 
+CPL_CVSID("$Id: postgisrastertools.cpp 35929 2016-10-25 16:09:00Z goatbar $");
+
  /**********************************************************************
  * \brief Replace the quotes by single quotes in the input string
  *
@@ -72,18 +74,17 @@ char * ReplaceSingleQuotes(const char * pszInput, int nLength) {
 
     pszOutput = (char*) CPLCalloc(nLength + 1, sizeof (char));
 
-    for (i = 0; i < nLength; i++) {
+    for (i = 0; i < nLength; i++)
+    {
         if (pszInput[i] == '\'')
             pszOutput[i] = '"';
         else
             pszOutput[i] = pszInput[i];
-
     }
 
     return pszOutput;
 }
 
-
 /***********************************************************************
  * \brief Split connection string into user, password, host, database...
  *
diff --git a/frmts/postgisraster/readme b/frmts/postgisraster/readme
index d1118fd..8cc1467 100644
--- a/frmts/postgisraster/readme
+++ b/frmts/postgisraster/readme
@@ -16,5 +16,5 @@ Author information:
 Important links:
 	PostGIS Raster extension information: http://trac.osgeo.org/postgis/wiki/WKTRaster
 	GDAL PostGIS Raster driver page: http://trac.osgeo.org/gdal/wiki/frmts_wtkraster.html
-   
+
 Last update: 2013-01-05
diff --git a/frmts/prf/GNUmakefile b/frmts/prf/GNUmakefile
new file mode 100644
index 0000000..f7f74ad
--- /dev/null
+++ b/frmts/prf/GNUmakefile
@@ -0,0 +1,10 @@
+include ../../GDALmake.opt
+
+OBJ := phprfdataset.o
+
+default: $(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/prf/frmt_prf.html b/frmts/prf/frmt_prf.html
new file mode 100644
index 0000000..9c6981b
--- /dev/null
+++ b/frmts/prf/frmt_prf.html
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<html>
+
+<head>
+<title>PHOTOMOD Raster File</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>PHOTOMOD Raster File</h1>
+
+<p>
+PRF or MegaTIFF is an internal format of PHOTOMOD software for storing large
+images.
+</p>
+
+<p>
+This format was developed to store images larger than 4 GB.
+As a basis for storing data used TIFF or JPEG2000 format.
+
+Raster is split into fragments (tiles) such that each fragment
+does not exceeded a predefined size (e.g., less than 1 GB).
+An overview file also added to process raster data on a small scales.
+</p>
+
+<p>
+PRF files has two variations: 'prf' for imagery data and 'x-dem' for elevation
+data.  Files can be georeferenced, but projection information can be stored only
+in external files (*.prj).
+</p>
+
+<p>
+Image format has the following structure:
+<ul>
+<li>the header XML file 'image_name.prf'/'image_name.x-dem'
+<li>folder 'image_name' with raster subtiles
+<li>files *.tif/*.jp2/*.demtif inside folder 'image_name', containing raster
+fragments and the overview image
+</ul>
+</p>
+
+<p>
+The driver support the data type among
+Byte, UInt16, UInt32, Float32 or Float64.
+<p>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="http://www.racurs.ru">Racurs company home page</a>
+<li> <a href="http://www.racurs.ru/index.php?page=453">PHOTOMOD Lite home page</a>
+</ul>
+
+</body>
+</html>
diff --git a/frmts/prf/makefile.vc b/frmts/prf/makefile.vc
new file mode 100644
index 0000000..6bf1b6a
--- /dev/null
+++ b/frmts/prf/makefile.vc
@@ -0,0 +1,13 @@
+
+OBJ	=	phprfdataset.obj
+
+GDAL_ROOT	=	..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	xcopy /D  /Y *.obj ..\o
+
+clean:
+	-del *.obj
+
diff --git a/frmts/prf/phprfdataset.cpp b/frmts/prf/phprfdataset.cpp
new file mode 100644
index 0000000..0a76768
--- /dev/null
+++ b/frmts/prf/phprfdataset.cpp
@@ -0,0 +1,665 @@
+/******************************************************************************
+ * Purpose:  Racurs PHOTOMOD tiled format reader (http://www.racurs.ru)
+ * Author:   Andrew Sudorgin (drons [a] list dot ru)
+ ******************************************************************************
+ * Copyright (c) 2016, Andrew Sudorgin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <cpl_minixml.h>
+#include <gdal.h>
+#include <gdal_priv.h>
+#include <gdal_proxy.h>
+#include "../vrt/vrtdataset.h"
+
+enum ph_format
+{
+    ph_megatiff,
+    ph_xdem
+};
+
+#define PH_PRF_DRIVER       "PRF"
+#define PH_PRF_EXT          "prf"
+#define PH_DEM_EXT          "x-dem"
+#define PH_GEOREF_SHIFT_Y   (1.0)
+
+class PhPrfBand : public VRTSourcedRasterBand
+{
+    std::vector<GDALRasterBand*> osOverview;
+public:
+    PhPrfBand( GDALDataset* poDataset, int nBandCount, GDALDataType eType,
+               int nXSize, int nYSize ) :
+        VRTSourcedRasterBand( poDataset, nBandCount, eType, nXSize, nYSize )
+    {}
+
+    void AddOverview( GDALRasterBand* ov )
+    {
+        osOverview.push_back( ov );
+    }
+
+    int GetOverviewCount() override
+    {
+        if( !osOverview.empty() )
+        {
+            return static_cast<int>( osOverview.size() );
+        }
+        else
+        {
+            return VRTSourcedRasterBand::GetOverviewCount();
+        }
+    }
+
+    GDALRasterBand* GetOverview( int i ) override
+    {
+        size_t n = static_cast<size_t>( i );
+        if( n < osOverview.size() )
+        {
+            return osOverview[ n ];
+        }
+        else
+        {
+            return VRTSourcedRasterBand::GetOverview( i );
+        }
+    }
+};
+
+class PhPrfDataset : public VRTDataset
+{
+    std::vector<GDALDataset*>    osSubTiles;
+public:
+    PhPrfDataset( GDALAccess eAccess, int nSizeX, int nSizeY, int nBandCount,
+                  GDALDataType eType, const char* pszName );
+    ~PhPrfDataset();
+    bool AddTile( const char* pszPartName, GDALAccess eAccess, int nWidth,
+                  int nHeight, int nOffsetX, int nOffsetY, int nScale );
+    int CloseDependentDatasets() override;
+    static int Identify( GDALOpenInfo* poOpenInfo );
+    static GDALDataset* Open( GDALOpenInfo* poOpenInfo );
+};
+
+PhPrfDataset::PhPrfDataset( GDALAccess _eAccess, int nSizeX, int nSizeY,
+                            int nBandCount, GDALDataType eType,
+                            const char* pszName ) :
+    VRTDataset( nSizeX, nSizeY )
+{
+    poDriver = (GDALDriver*)GDALGetDriverByName( PH_PRF_DRIVER );
+    eAccess = _eAccess;
+    SetWritable( FALSE );   //Avoid rewrite of *.prf file with 'vrt' file
+    SetDescription( pszName );
+
+    for( int i = 0; i != nBandCount; ++i )
+    {
+        PhPrfBand* poBand = new PhPrfBand( this, i + 1, eType, nSizeX, nSizeY );
+        SetBand( i + 1, poBand );
+    }
+}
+
+PhPrfDataset::~PhPrfDataset()
+{
+    CloseDependentDatasets();
+}
+
+bool PhPrfDataset::AddTile( const char* pszPartName, GDALAccess eAccessType,
+                            int nWidth, int nHeight
+                            , int nOffsetX, int nOffsetY, int nScale )
+{
+    GDALProxyPoolDataset*   poTileDataset;
+    poTileDataset = new GDALProxyPoolDataset( pszPartName, nWidth, nHeight,
+                                              eAccessType, FALSE );
+
+    for( int nBand = 1; nBand != GetRasterCount() + 1; ++nBand )
+    {
+        PhPrfBand* poBand = dynamic_cast<PhPrfBand*>( GetRasterBand( nBand ) );
+
+        if( poBand == NULL )
+        {
+            delete poTileDataset;
+            return false;
+        }
+
+        //! \todo What reason for nBlockXSize&nBlockYSize passed to AddSrcBandDescription
+        poTileDataset->AddSrcBandDescription(poBand->GetRasterDataType(), 0, 0);
+        GDALRasterBand* poTileBand = poTileDataset->GetRasterBand( nBand );
+
+        if( 0 == nScale )
+        {
+            poBand->AddSimpleSource( poTileBand, 0, 0, nWidth, nHeight,
+                                     nOffsetX, nOffsetY, nWidth, nHeight );
+        }
+        else
+        {
+            poBand->AddOverview( poTileBand );
+        }
+    }
+
+    osSubTiles.push_back( poTileDataset );
+
+    return true;
+}
+
+int PhPrfDataset::CloseDependentDatasets()
+{
+    int bDroppedRef = VRTDataset::CloseDependentDatasets();
+    for( std::vector<GDALDataset*>::iterator ii( osSubTiles.begin() );
+         ii != osSubTiles.end();
+         ++ii )
+    {
+        delete (*ii);
+        bDroppedRef = TRUE;
+    }
+    osSubTiles.clear();
+    return bDroppedRef;
+}
+
+int PhPrfDataset::Identify( GDALOpenInfo* poOpenInfo )
+{
+    if( poOpenInfo->pabyHeader == NULL ||
+        poOpenInfo->nHeaderBytes < 20 )
+    {
+        return FALSE;
+    }
+
+    if( strstr( reinterpret_cast<char *>( poOpenInfo->pabyHeader ),
+                "phini" ) == NULL )
+    {
+        return FALSE;
+    }
+
+    if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), PH_PRF_EXT ) )
+    {
+        return TRUE;
+    }
+    else
+    if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), PH_DEM_EXT ) )
+    {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+static void GetXmlNameValuePair( const CPLXMLNode* psElt, CPLString& osName,
+                                 CPLString& osValue )
+{
+    for( const CPLXMLNode* psAttr = psElt->psChild;
+         psAttr != NULL;
+         psAttr = psAttr->psNext )
+    {
+        if( psAttr->eType != CXT_Attribute ||
+            psAttr->pszValue == NULL ||
+            psAttr->psChild == NULL ||
+            psAttr->psChild->pszValue == NULL )
+        {
+            continue;
+        }
+        if( EQUAL( psAttr->pszValue, "n" ) )
+        {
+            osName = psAttr->psChild->pszValue;
+        }
+        else
+        if( EQUAL( psAttr->pszValue, "v" ) )
+        {
+            osValue = psAttr->psChild->pszValue;
+        }
+    }
+}
+
+static CPLString GetXmlAttribute( const CPLXMLNode* psElt,
+                                  const CPLString& osAttrName,
+                                  const CPLString& osDef = CPLString() )
+{
+    for( const CPLXMLNode* psAttr = psElt->psChild;
+         psAttr != NULL;
+         psAttr = psAttr->psNext )
+    {
+        if( psAttr->eType != CXT_Attribute ||
+            psAttr->pszValue == NULL ||
+            psAttr->psChild == NULL ||
+            psAttr->psChild->pszValue == NULL )
+        {
+            continue;
+        }
+        if( EQUAL( psAttr->pszValue, osAttrName ) )
+        {
+            return psAttr->psChild->pszValue;
+        }
+    }
+    return osDef;
+}
+
+static bool ParseGeoref( const CPLXMLNode* psGeorefElt, double* padfGeoTrans )
+{
+    bool abOk[6] = { false, false, false, false, false, false };
+    static const char* const apszGeoKeys[6] = { "A_0", "A_1", "A_2",
+                                                "B_0", "B_1", "B_2" };
+    for( const CPLXMLNode* elt = psGeorefElt->psChild;
+         elt != NULL;
+         elt = elt->psNext )
+    {
+        CPLString osName;
+        CPLString osValue;
+        GetXmlNameValuePair( elt, osName, osValue );
+        for( int k = 0; k != 6; ++k )
+        {
+            if( EQUAL( osName, apszGeoKeys[k] ) )
+            {
+                padfGeoTrans[k] = CPLAtof( osValue );
+                abOk[k] = true;
+            }
+        }
+    }
+
+    for( int k = 0; k != 6; ++k )
+    {
+        if( !abOk[k] )
+        {
+            break;
+        }
+        if( k == 5 )
+        {
+            padfGeoTrans[3] -= PH_GEOREF_SHIFT_Y * padfGeoTrans[4];
+            padfGeoTrans[3] -= PH_GEOREF_SHIFT_Y * padfGeoTrans[5];
+            return true;
+        }
+    }
+    return false;
+}
+
+static bool ParseDemShift( const CPLXMLNode* psDemShiftElt,
+                           double* padfDemShift )
+{
+    bool abOk[6] = { false,false,false, false, false, false };
+    static const char* const apszDemShiftKeys[6] =
+        { "x", "y", "z", "", "", "" };
+
+    for( const CPLXMLNode* elt = psDemShiftElt->psChild;
+         elt != NULL;
+         elt = elt->psNext )
+    {
+        CPLString osName;
+        CPLString osValue;
+        GetXmlNameValuePair( elt, osName, osValue );
+        for( int k = 0; k != 3; ++k )
+        {
+            if( EQUAL( osName, apszDemShiftKeys[k] ) )
+            {
+                padfDemShift[k] = CPLAtof( osValue );
+                abOk[k] = true;
+            }
+        }
+    }
+    return abOk[0] && abOk[1] && abOk[2];
+}
+
+static GDALDataType ParseChannelsInfo( const CPLXMLNode* psElt )
+{
+    CPLString osType;
+    CPLString osBytesPS;
+    CPLString osChannels;
+
+    for( const CPLXMLNode* psChild = psElt->psChild;
+         psChild != NULL;
+         psChild = psChild->psNext )
+    {
+        if( psChild->eType != CXT_Element )
+        {
+            continue;
+        }
+
+        CPLString osName;
+        CPLString osValue;
+
+        GetXmlNameValuePair( psChild, osName, osValue );
+
+        if( EQUAL( osName, "type" ) )
+        {
+            osType = osValue;
+        }
+        else if( EQUAL( osName, "bytes_ps" ) )
+        {
+            osBytesPS = osValue;
+        }
+        else if( EQUAL( osName, "channels" ) )
+        {
+            osChannels = osValue;
+        }
+    }
+
+    const int nDataTypeSize = atoi( osBytesPS );
+    if( osType == "U" )
+    {
+        switch( nDataTypeSize )
+        {
+        case 1:
+            return GDT_Byte;
+        case 2:
+            return GDT_UInt16;
+        case 4:
+            return GDT_UInt32;
+        default:
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Unsupported datatype size %d", nDataTypeSize );
+            return GDT_Unknown;
+        }
+    }
+    else if( osType == "F" )
+    {
+        switch( nDataTypeSize )
+        {
+        case 4:
+            return GDT_Float32;
+        case 8:
+            return GDT_Float64;
+        default:
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Unsupported datatype size %d", nDataTypeSize );
+            return GDT_Unknown;
+        }
+    }
+
+    return GDT_Unknown;
+}
+
+GDALDataset* PhPrfDataset::Open( GDALOpenInfo* poOpenInfo )
+{
+    ph_format eFormat;
+
+    if( EQUAL( CPLGetExtension(poOpenInfo->pszFilename), PH_PRF_EXT ) )
+    {
+        eFormat = ph_megatiff;
+    }
+    else if( EQUAL( CPLGetExtension(poOpenInfo->pszFilename), PH_DEM_EXT ) )
+    {
+        eFormat = ph_xdem;
+    }
+    else
+    {
+        return NULL;
+    }
+
+    CPLXMLTreeCloser oDoc( CPLParseXMLFile( poOpenInfo->pszFilename ) );
+
+    if( oDoc.get() == NULL )
+    {
+        return NULL;
+    }
+
+    const CPLXMLNode* psPhIni( CPLSearchXMLNode( oDoc.get(), "=phini" ) );
+    if( psPhIni == NULL )
+    {
+        return NULL;
+    }
+
+    int          nSizeX = 0;
+    int          nSizeY = 0;
+    int          nBandCount = 0;
+    GDALDataType eResultDatatype = GDT_Unknown;
+    CPLString    osPartsBasePath( CPLGetPath( poOpenInfo->pszFilename ) );
+    CPLString    osPartsPath( osPartsBasePath + "/" +
+                              CPLGetBasename( poOpenInfo->pszFilename ) );
+    CPLString    osPartsExt;
+    double       adfGeoTrans[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+    bool         bGeoTransOk = false;
+
+    double       adfDemShift[3] = { 0.0, 0.0, 0.0 };
+    bool         bDemShiftOk = false;
+    const int    nDemMDCount = 7;
+    bool         abDemMetadataOk[nDemMDCount] =
+        { false, false, false, false, false, false, false };
+    double       adfDemMetadata[nDemMDCount] =
+        { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+    static const char* const apszDemKeys[nDemMDCount] = { "XR_0", "XR_1",
+                                                          "YR_0", "YR_1",
+                                                          "ZR_0", "ZR_1",
+                                                          "BadZ" };
+    if( eFormat == ph_megatiff )
+    {
+        osPartsExt = ".tif";
+    }
+    else if( eFormat == ph_xdem )
+    {
+        osPartsExt = ".demtif";
+    }
+
+    for( const CPLXMLNode* psElt = psPhIni->psChild;
+         psElt != NULL;
+         psElt = psElt->psNext )
+    {
+        if( !EQUAL(psElt->pszValue,"s") ||
+            psElt->eType != CXT_Element )
+        {
+            continue;
+        }
+
+        CPLString osName;
+        CPLString osValue;
+
+        GetXmlNameValuePair( psElt, osName, osValue );
+
+        if( EQUAL( osName, "parts_ext" ) )
+        {
+            osPartsExt = "." + osValue;
+        }
+    }
+
+    for( const CPLXMLNode* psElt = psPhIni->psChild;
+         psElt != NULL;
+         psElt = psElt->psNext )
+    {
+        CPLString osName;
+        CPLString osValue;
+
+        GetXmlNameValuePair( psElt, osName, osValue );
+
+        if( EQUAL( osName, "ChannelsInfo" ) )
+        {
+            eResultDatatype = ParseChannelsInfo( psElt );
+        }
+        else if( EQUAL( osName, "Width" ) )
+        {
+            nSizeX = atoi( osValue );
+        }
+        else if( EQUAL( osName, "Height" ) )
+        {
+            nSizeY = atoi( osValue );
+        }
+        else if( EQUAL( osName, "QChans" ) )
+        {
+            nBandCount = atoi( osValue );
+        }
+        else if( EQUAL( osName, "GeoRef" ) )
+        {
+            bGeoTransOk = ParseGeoref( psElt, adfGeoTrans );
+        }
+        else if( EQUAL( osName, "DemShift" ) )
+        {
+            bDemShiftOk = ParseDemShift( psElt, adfDemShift );
+        }
+        else
+        {
+            for( int n = 0; n != nDemMDCount; ++n )
+            {
+                if( EQUAL( osName, apszDemKeys[n] ) )
+                {
+                    adfDemMetadata[n] = CPLAtof( osValue );
+                    abDemMetadataOk[n] = true;
+                }
+            }
+        }
+    }
+
+    if( eResultDatatype == GDT_Unknown )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "GDAL Dataset datatype not found" );
+        return NULL;
+    }
+
+    if( nSizeX <= 0 || nSizeY <= 0 || nBandCount <= 0 )
+    {
+        return NULL;
+    }
+
+    PhPrfDataset* poDataset =
+        new PhPrfDataset( GA_ReadOnly, nSizeX, nSizeY, nBandCount,
+                          eResultDatatype, poOpenInfo->pszFilename );
+
+    if( !GDALCheckDatasetDimensions( poDataset->GetRasterXSize(),
+                                     poDataset->GetRasterYSize() ) )
+    {
+        delete poDataset;
+        return NULL;
+    }
+
+    for( const CPLXMLNode* psElt = psPhIni->psChild;
+         psElt != NULL;
+         psElt = psElt->psNext )
+    {
+        int nWidth = 0;
+        int nHeight = 0;
+        int nOffsetX = 0;
+        int nOffsetY = 0;
+        int nScale = 0;
+
+        for( const CPLXMLNode* psItem = psElt->psChild;
+             psItem != NULL;
+             psItem = psItem->psNext )
+        {
+            CPLString osName;
+            CPLString osValue;
+
+            GetXmlNameValuePair( psItem, osName, osValue );
+
+            if( EQUAL( osName, "Width" ) )
+            {
+                nWidth = atoi( osValue );
+            }
+            else
+            if( EQUAL( osName, "Height" ) )
+            {
+                nHeight = atoi( osValue );
+            }
+            else
+            if( EQUAL( osName, "DispX" ) )
+            {
+                nOffsetX = atoi( osValue );
+            }
+            else
+            if( EQUAL( osName, "DispY" ) )
+            {
+                nOffsetY = atoi( osValue );
+            }
+            else
+            if( EQUAL( osName, "Scale" ) )
+            {
+                nScale = atoi( osValue );
+            }
+        }
+
+        if( nWidth == 0 || nHeight == 0 )
+        {
+            continue;
+        }
+
+        CPLString osPartName( osPartsPath + "/" +
+                              GetXmlAttribute( psElt, "n" ) +
+                              osPartsExt );
+
+        if( !poDataset->AddTile( osPartName, GA_ReadOnly, nWidth, nHeight,
+                                 nOffsetX, nOffsetY, nScale ) )
+        {
+            delete poDataset;
+            return NULL;
+        }
+    }
+
+    if( eFormat == ph_megatiff && bGeoTransOk )
+    {
+        poDataset->SetGeoTransform( adfGeoTrans );
+    }
+
+    if( eFormat == ph_xdem )
+    {
+        GDALRasterBand* poFirstBand = poDataset->GetRasterBand( 1 );
+
+        if( poFirstBand != NULL )
+        {
+            poFirstBand->SetUnitType( "m" );  // Always meters.
+        }
+
+        if( abDemMetadataOk[0] && abDemMetadataOk[1] &&
+            abDemMetadataOk[2] && abDemMetadataOk[3] )
+        {
+            adfGeoTrans[0] = adfDemMetadata[0];
+            adfGeoTrans[1] = (adfDemMetadata[1] - adfDemMetadata[0])/nSizeX;
+            adfGeoTrans[2] = 0;
+            adfGeoTrans[3] = adfDemMetadata[3];
+            adfGeoTrans[4] = 0;
+            adfGeoTrans[5] = (adfDemMetadata[2] - adfDemMetadata[3])/nSizeY;
+
+            if( bDemShiftOk )
+            {
+                adfGeoTrans[0] += adfDemShift[0];
+                adfGeoTrans[3] += adfDemShift[1];
+            }
+
+            poDataset->SetGeoTransform( adfGeoTrans );
+        }
+
+        if( abDemMetadataOk[4] && abDemMetadataOk[5] )
+        {
+            poFirstBand->SetMetadataItem(
+                "STATISTICS_MINIMUM", CPLSPrintf( "%f", adfDemMetadata[4] ) );
+            poFirstBand->SetMetadataItem(
+                "STATISTICS_MAXIMUM", CPLSPrintf( "%f", adfDemMetadata[5] ) );
+        }
+
+        if( abDemMetadataOk[6] )
+        {
+            poFirstBand->SetNoDataValue( adfDemMetadata[6] );
+        }
+
+        if( bDemShiftOk )
+        {
+            poFirstBand->SetOffset( adfDemShift[2] );
+        }
+    }
+
+    return poDataset;
+}
+
+void GDALRegister_PRF()
+{
+    if( GDALGetDriverByName( PH_PRF_DRIVER ) != NULL )
+        return;
+
+    GDALDriver* poDriver = new GDALDriver;
+
+    poDriver->SetDescription( PH_PRF_DRIVER );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Racurs PHOTOMOD PRF" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "prf" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_prf.html" );
+    poDriver->pfnIdentify = PhPrfDataset::Identify;
+    poDriver->pfnOpen = PhPrfDataset::Open;
+    GDALRegisterDriver( (GDALDriverH)poDriver );
+}
+
diff --git a/frmts/r/rcreatecopy.cpp b/frmts/r/rcreatecopy.cpp
index 67db898..11da622 100644
--- a/frmts/r/rcreatecopy.cpp
+++ b/frmts/r/rcreatecopy.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rcreatecopy.cpp 33841 2016-04-01 01:16:15Z goatbar $
  *
  * Project:  R Format Driver
  * Purpose:  CreateCopy() implementation for R stats package object format.
@@ -27,11 +26,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "rdataset.h"
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: rcreatecopy.cpp 33841 2016-04-01 01:16:15Z goatbar $");
-
+CPL_CVSID("$Id: rcreatecopy.cpp 37583 2017-03-03 18:35:20Z goatbar $");
 
 GDALDataset *
 RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
@@ -54,13 +65,13 @@ static void RWriteInteger( VSILFILE *fp, int bASCII, int nValue )
     if( bASCII )
     {
         char szOutput[50] = { '\0' };
-        snprintf( szOutput, sizeof(szOutput), "%d\n", nValue );
-        VSIFWriteL( szOutput, 1, strlen(szOutput), fp );
+        snprintf(szOutput, sizeof(szOutput), "%d\n", nValue);
+        VSIFWriteL(szOutput, 1, strlen(szOutput), fp);
     }
     else
     {
-        CPL_MSBPTR32( &nValue );
-        VSIFWriteL( &nValue, 4, 1, fp );
+        CPL_MSBPTR32(&nValue);
+        VSIFWriteL(&nValue, 4, 1, fp);
     }
 }
 
@@ -71,17 +82,17 @@ static void RWriteInteger( VSILFILE *fp, int bASCII, int nValue )
 static void RWriteString( VSILFILE *fp, int bASCII, const char *pszValue )
 
 {
-    RWriteInteger( fp, bASCII, 4105 );
-    RWriteInteger( fp, bASCII, (int) strlen(pszValue) );
+    RWriteInteger(fp, bASCII, 4105);
+    RWriteInteger(fp, bASCII, static_cast<int>(strlen(pszValue)));
 
     if( bASCII )
     {
-        VSIFWriteL( pszValue, 1, strlen(pszValue), fp );
-        VSIFWriteL( "\n", 1, 1, fp );
+        VSIFWriteL(pszValue, 1, strlen(pszValue), fp);
+        VSIFWriteL("\n", 1, 1, fp);
     }
     else
     {
-        VSIFWriteL( pszValue, 1, (int) strlen(pszValue), fp );
+        VSIFWriteL(pszValue, 1, static_cast<int>(strlen(pszValue)), fp);
     }
 }
 
@@ -100,163 +111,130 @@ RCreateCopy( const char * pszFilename,
     const int nBands = poSrcDS->GetRasterCount();
     const int nXSize = poSrcDS->GetRasterXSize();
     const int nYSize = poSrcDS->GetRasterYSize();
-    const int bASCII = CSLFetchBoolean( papszOptions, "ASCII", FALSE );
-    const bool bCompressed =
-        CPL_TO_BOOL( CSLFetchBoolean( papszOptions, "COMPRESS", !bASCII ) );
-
-/* -------------------------------------------------------------------- */
-/*      Some some rudimentary checks                                    */
-/* -------------------------------------------------------------------- */
-
-/* -------------------------------------------------------------------- */
-/*      Setup the filename to actually use.  We prefix with             */
-/*      /vsigzip/ if we want compressed output.                         */
-/* -------------------------------------------------------------------- */
-    CPLString osAdjustedFilename;
+    const bool bASCII = CPLFetchBool(papszOptions, "ASCII", false);
+    const bool bCompressed = CPLFetchBool(papszOptions, "COMPRESS", !bASCII);
 
-    if( bCompressed )
-        osAdjustedFilename = "/vsigzip/";
+    // Some some rudimentary checks.
 
-    osAdjustedFilename += pszFilename;
+    // Setup the filename to actually use.  We prefix with
+    // /vsigzip/ if we want compressed output.
+    const CPLString osAdjustedFilename =
+        std::string(bCompressed ? "/vsigzip/" : "") + pszFilename;
 
-/* -------------------------------------------------------------------- */
-/*      Create the file.                                                */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fp = VSIFOpenL( osAdjustedFilename, "wb" );
+    // Create the file.
+    VSILFILE *fp = VSIFOpenL(osAdjustedFilename, "wb");
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unable to create file %s.",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Unable to create file %s.",
+                 pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write header with version, etc.                                 */
-/* -------------------------------------------------------------------- */
+    // Write header with version, etc.
     if( bASCII )
     {
         const char *pszHeader = "RDA2\nA\n";
-        VSIFWriteL( pszHeader, 1, strlen(pszHeader), fp );
+        VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp);
     }
     else
     {
         const char *pszHeader = "RDX2\nX\n";
-        VSIFWriteL( pszHeader, 1, strlen(pszHeader), fp );
+        VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp);
     }
 
-    RWriteInteger( fp, bASCII, 2 );
-    RWriteInteger( fp, bASCII, 133377 );
-    RWriteInteger( fp, bASCII, 131840 );
-
-/* -------------------------------------------------------------------- */
-/*      Establish the primary pairlist with one component object.       */
-/* -------------------------------------------------------------------- */
-    RWriteInteger( fp, bASCII, 1026 );
-    RWriteInteger( fp, bASCII, 1 );
-
-/* -------------------------------------------------------------------- */
-/*      Write the object name.  Eventually we should derive this        */
-/*      from the filename, possible with override by a creation         */
-/*      option.                                                         */
-/* -------------------------------------------------------------------- */
-    RWriteString( fp, bASCII, "gg" );
-
-/* -------------------------------------------------------------------- */
-/*      For now we write the raster as a numeric array with             */
-/*      attributes (526).                                               */
-/* -------------------------------------------------------------------- */
-    RWriteInteger( fp, bASCII, 526 );
-    RWriteInteger( fp, bASCII, nXSize * nYSize * nBands );
-
-/* -------------------------------------------------------------------- */
-/*      Write the raster data.                                          */
-/* -------------------------------------------------------------------- */
+    RWriteInteger(fp, bASCII, 2);
+    RWriteInteger(fp, bASCII, 133377);
+    RWriteInteger(fp, bASCII, 131840);
+
+    // Establish the primary pairlist with one component object.
+    RWriteInteger(fp, bASCII, 1026);
+    RWriteInteger(fp, bASCII, 1);
+
+    // Write the object name.  Eventually we should derive this
+    // from the filename, possible with override by a creation option.
+    RWriteString(fp, bASCII, "gg");
+
+    // For now we write the raster as a numeric array with attributes (526).
+    RWriteInteger(fp, bASCII, 526);
+    RWriteInteger(fp, bASCII, nXSize * nYSize * nBands);
+
+    // Write the raster data.
     CPLErr eErr = CE_None;
 
     double *padfScanline =
-        static_cast<double *>( CPLMalloc( nXSize * sizeof(double) ) );
+        static_cast<double *>(CPLMalloc(nXSize * sizeof(double)));
 
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
+        GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1);
 
         for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
         {
-            int iValue;
-
-            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
-                                     padfScanline, nXSize, 1, GDT_Float64,
-                                     sizeof(double), 0, NULL );
+            eErr = poBand->RasterIO(GF_Read, 0, iLine, nXSize, 1,
+                                    padfScanline, nXSize, 1, GDT_Float64,
+                                    sizeof(double), 0, NULL);
 
             if( bASCII )
             {
-                for( iValue = 0; iValue < nXSize; iValue++ )
+                for( int iValue = 0; iValue < nXSize; iValue++ )
                 {
                     char szValue[128] = { '\0' };
-                    CPLsnprintf( szValue, sizeof(szValue), "%.16g\n",
-                                 padfScanline[iValue] );
-                    VSIFWriteL( szValue, 1, strlen(szValue), fp );
+                    CPLsnprintf(szValue, sizeof(szValue), "%.16g\n",
+                                padfScanline[iValue]);
+                    VSIFWriteL(szValue, 1, strlen(szValue), fp);
                 }
             }
             else
             {
-                for( iValue = 0; iValue < nXSize; iValue++ )
-                    CPL_MSBPTR64( padfScanline + iValue );
+                for( int iValue = 0; iValue < nXSize; iValue++ )
+                    CPL_MSBPTR64(padfScanline + iValue);
 
-                VSIFWriteL( padfScanline, 8, nXSize, fp );
+                VSIFWriteL(padfScanline, 8, nXSize, fp);
             }
 
-            if( eErr == CE_None
-                && !pfnProgress( (iLine+1) / (double) nYSize,
-                                 NULL, pProgressData ) )
+            if( eErr == CE_None &&
+                !pfnProgress((iLine + 1) / static_cast<double>(nYSize),
+                             NULL, pProgressData) )
             {
                 eErr = CE_Failure;
-                CPLError( CE_Failure, CPLE_UserInterrupt,
-                          "User terminated CreateCopy()" );
+                CPLError(CE_Failure, CPLE_UserInterrupt,
+                         "User terminated CreateCopy()");
             }
         }
     }
 
-    CPLFree( padfScanline );
+    CPLFree(padfScanline);
 
-/* -------------------------------------------------------------------- */
-/*      Write out the dims attribute.                                   */
-/* -------------------------------------------------------------------- */
-    RWriteInteger( fp, bASCII, 1026 );
-    RWriteInteger( fp, bASCII, 1 );
+    // Write out the dims attribute.
+    RWriteInteger(fp, bASCII, 1026);
+    RWriteInteger(fp, bASCII, 1);
 
-    RWriteString( fp, bASCII, "dim" );
+    RWriteString(fp, bASCII, "dim");
 
-    RWriteInteger( fp, bASCII, 13 );
-    RWriteInteger( fp, bASCII, 3 );
-    RWriteInteger( fp, bASCII, nXSize );
-    RWriteInteger( fp, bASCII, nYSize );
-    RWriteInteger( fp, bASCII, nBands );
+    RWriteInteger(fp, bASCII, 13);
+    RWriteInteger(fp, bASCII, 3);
+    RWriteInteger(fp, bASCII, nXSize);
+    RWriteInteger(fp, bASCII, nYSize);
+    RWriteInteger(fp, bASCII, nBands);
 
-    RWriteInteger( fp, bASCII, 254 );
+    RWriteInteger(fp, bASCII, 254);
 
-/* -------------------------------------------------------------------- */
-/*      Terminate overall pairlist.                                     */
-/* -------------------------------------------------------------------- */
-    RWriteInteger( fp, bASCII, 254 );
+    // Terminate overall pairlist.
+    RWriteInteger(fp, bASCII, 254);
 
-/* -------------------------------------------------------------------- */
-/*      Cleanup.                                                        */
-/* -------------------------------------------------------------------- */
-    VSIFCloseL( fp );
+    // Cleanup.
+    VSIFCloseL(fp);
 
     if( eErr != CE_None )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Re-open dataset, and copy any auxiliary pam information.         */
-/* -------------------------------------------------------------------- */
+    // Re-open dataset, and copy any auxiliary pam information.
     GDALPamDataset *poDS =
-        static_cast<GDALPamDataset *>( GDALOpen( pszFilename, GA_ReadOnly ) );
+        static_cast<GDALPamDataset *>(GDALOpen(pszFilename, GA_ReadOnly));
 
     if( poDS )
-        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
+        poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT);
 
     return poDS;
 }
diff --git a/frmts/r/rdataset.cpp b/frmts/r/rdataset.cpp
index 869c9d3..ce2bf3c 100644
--- a/frmts/r/rdataset.cpp
+++ b/frmts/r/rdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rdataset.cpp 33841 2016-04-01 01:16:15Z goatbar $
  *
  * Project:  R Format Driver
  * Purpose:  Read/write R stats package object format.
@@ -28,17 +27,29 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "rdataset.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
 #include "../raw/rawdataset.h"
 
-CPL_CVSID("$Id: rdataset.cpp 33841 2016-04-01 01:16:15Z goatbar $");
-
-GDALDataset *
-RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
-             int bStrict, char ** papszOptions,
-             GDALProgressFunc pfnProgress, void * pProgressData );
+CPL_CVSID("$Id: rdataset.cpp 37864 2017-03-30 20:06:47Z goatbar $");
 
 // static const int R_NILSXP = 0;
 static const int R_LISTSXP = 2;
@@ -48,56 +59,6 @@ static const int R_REALSXP = 14;
 static const int R_STRSXP = 16;
 
 /************************************************************************/
-/* ==================================================================== */
-/*                               RDataset                               */
-/* ==================================================================== */
-/************************************************************************/
-
-class RDataset : public GDALPamDataset
-{
-    friend class RRasterBand;
-    VSILFILE   *fp;
-    int         bASCII;
-    CPLString   osLastStringRead;
-
-    vsi_l_offset nStartOfData;
-
-    double     *padfMatrixValues;
-
-    const char *ASCIIFGets();
-    int         ReadInteger();
-    double      ReadFloat();
-    const char *ReadString();
-    int         ReadPair( CPLString &osItemName, int &nItemType );
-
-  public:
-                RDataset();
-                ~RDataset();
-
-    static GDALDataset  *Open( GDALOpenInfo * );
-    static int          Identify( GDALOpenInfo * );
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            RRasterBand                               */
-/* ==================================================================== */
-/************************************************************************/
-
-class RRasterBand : public GDALPamRasterBand
-{
-    friend class RDataset;
-
-    const double *padfMatrixValues;
-
-  public:
-                RRasterBand( RDataset *, int, const double * );
-    virtual ~RRasterBand() {}
-
-    virtual CPLErr          IReadBlock( int, int, void * );
-};
-
-/************************************************************************/
 /*                            RRasterBand()                             */
 /************************************************************************/
 
@@ -122,8 +83,8 @@ CPLErr RRasterBand::IReadBlock( int /* nBlockXOff */,
                                 int nBlockYOff,
                                 void * pImage )
 {
-    memcpy( pImage, padfMatrixValues + nBlockYOff * nBlockXSize,
-            nBlockXSize * 8 );
+    memcpy(pImage, padfMatrixValues + nBlockYOff * nBlockXSize,
+           nBlockXSize * 8);
     return CE_None;
 }
 
@@ -142,7 +103,7 @@ RDataset::RDataset() :
     bASCII(FALSE),
     nStartOfData(0),
     padfMatrixValues(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                             ~RDataset()                              */
@@ -154,7 +115,7 @@ RDataset::~RDataset()
     CPLFree(padfMatrixValues);
 
     if( fp )
-        VSIFCloseL( fp );
+        VSIFCloseL(fp);
 }
 
 /************************************************************************/
@@ -173,7 +134,7 @@ const char *RDataset::ASCIIFGets()
     do
     {
         chNextChar = '\n';
-        VSIFReadL( &chNextChar, 1, 1, fp );
+        VSIFReadL(&chNextChar, 1, 1, fp);
         if( chNextChar != '\n' )
             osLastStringRead += chNextChar;
     } while( chNextChar != '\n' && chNextChar != '\0' );
@@ -192,16 +153,14 @@ int RDataset::ReadInteger()
     {
         return atoi(ASCIIFGets());
     }
-    else
-    {
-        GInt32  nValue;
 
-        if( VSIFReadL( &nValue, 4, 1, fp ) != 1 )
-            return -1;
-        CPL_MSBPTR32( &nValue );
+    GInt32 nValue = 0;
 
-        return nValue;
-    }
+    if( VSIFReadL(&nValue, 4, 1, fp) != 1 )
+        return -1;
+    CPL_MSBPTR32(&nValue);
+
+    return nValue;
 }
 
 /************************************************************************/
@@ -215,16 +174,14 @@ double RDataset::ReadFloat()
     {
         return CPLAtof(ASCIIFGets());
     }
-    else
-    {
-        double dfValue = 0.0;
 
-        if( VSIFReadL( &dfValue, 8, 1, fp ) != 1 )
-            return -1;
-        CPL_MSBPTR64( &dfValue );
+    double dfValue = 0.0;
 
-        return dfValue;
-    }
+    if( VSIFReadL(&dfValue, 8, 1, fp) != 1 )
+        return -1;
+    CPL_MSBPTR64(&dfValue);
+
+    return dfValue;
 }
 
 /************************************************************************/
@@ -248,16 +205,16 @@ const char *RDataset::ReadString()
     }
     const size_t nLen = static_cast<size_t>(nLenSigned);
 
-    char *pachWrkBuf = static_cast<char *>( VSIMalloc(nLen) );
+    char *pachWrkBuf = static_cast<char *>(VSIMalloc(nLen));
     if (pachWrkBuf == NULL)
     {
         osLastStringRead = "";
         return "";
     }
-    if( VSIFReadL( pachWrkBuf, 1, nLen, fp ) != nLen )
+    if( VSIFReadL(pachWrkBuf, 1, nLen, fp) != nLen )
     {
         osLastStringRead = "";
-        CPLFree( pachWrkBuf );
+        CPLFree(pachWrkBuf);
         return "";
     }
 
@@ -267,8 +224,8 @@ const char *RDataset::ReadString()
         ASCIIFGets();
     }
 
-    osLastStringRead.assign( pachWrkBuf, nLen );
-    CPLFree( pachWrkBuf );
+    osLastStringRead.assign(pachWrkBuf, nLen);
+    CPLFree(pachWrkBuf);
 
     return osLastStringRead;
 }
@@ -277,43 +234,39 @@ const char *RDataset::ReadString()
 /*                              ReadPair()                              */
 /************************************************************************/
 
-int RDataset::ReadPair( CPLString &osObjName, int &nObjCode )
+bool RDataset::ReadPair( CPLString &osObjName, int &nObjCode )
 
 {
     nObjCode = ReadInteger();
     if( nObjCode == 254 )
-        return TRUE;
+        return true;
 
     if( (nObjCode % 256) != R_LISTSXP )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Did not find expected object pair object." );
-        return FALSE;
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Did not find expected object pair object.");
+        return false;
     }
 
     int nPairCount = ReadInteger();
     if( nPairCount != 1 )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Did not find expected pair count of 1." );
-        return FALSE;
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Did not find expected pair count of 1.");
+        return false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the object name.                                           */
-/* -------------------------------------------------------------------- */
+    // Read the object name.
     const char *pszName = ReadString();
     if( pszName == NULL || pszName[0] == '\0' )
-        return FALSE;
+        return false;
 
     osObjName = pszName;
 
-/* -------------------------------------------------------------------- */
-/*      Confirm that we have a numeric matrix object.                   */
-/* -------------------------------------------------------------------- */
+    // Confirm that we have a numeric matrix object.
     nObjCode = ReadInteger();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -325,19 +278,15 @@ int RDataset::Identify( GDALOpenInfo *poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 50 )
         return FALSE;
 
-/* -------------------------------------------------------------------- */
-/*      If the extension is .rda and the file type is gzip              */
-/*      compressed we assume it is a gzipped R binary file.              */
-/* -------------------------------------------------------------------- */
-    if( memcmp(poOpenInfo->pabyHeader,"\037\213\b",3) == 0
-        && EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"rda") )
+    // If the extension is .rda and the file type is gzip
+    // compressed we assume it is a gzipped R binary file.
+    if( memcmp(poOpenInfo->pabyHeader, "\037\213\b", 3) == 0 &&
+        EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "rda") )
         return TRUE;
 
-/* -------------------------------------------------------------------- */
-/*      Is this an ASCII or XDR binary R file?                          */
-/* -------------------------------------------------------------------- */
-    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDA2\nA\n")
-        && !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDX2\nX\n") )
+    // Is this an ASCII or XDR binary R file?
+    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDA2\nA\n") &&
+        !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDX2\nX\n") )
         return FALSE;
 
     return TRUE;
@@ -349,72 +298,60 @@ int RDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
 {
-    if( !Identify( poOpenInfo ) )
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+    // During fuzzing, do not use Identify to reject crazy content.
+    if( !Identify(poOpenInfo) )
         return NULL;
+#endif
 
-/* -------------------------------------------------------------------- */
-/*      Confirm the requested access is supported.                      */
-/* -------------------------------------------------------------------- */
+    // Confirm the requested access is supported.
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "The R driver does not support update access to existing"
-                  " datasets.\n" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "The R driver does not support update access to existing"
+                 " datasets.");
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Do we need to route the file through the decompression          */
-/*      machinery?                                                      */
-/* -------------------------------------------------------------------- */
-    CPLString osAdjustedFilename;
+    // Do we need to route the file through the decompression machinery?
+    const bool bCompressed =
+        memcmp(poOpenInfo->pabyHeader, "\037\213\b", 3) == 0;
+    const CPLString osAdjustedFilename =
+        std::string(bCompressed ? "/vsigzip/" : "") + poOpenInfo->pszFilename;
 
-    if( memcmp(poOpenInfo->pabyHeader,"\037\213\b",3) == 0 )
-        osAdjustedFilename = "/vsigzip/";
-
-    osAdjustedFilename += poOpenInfo->pszFilename;
-
-/* -------------------------------------------------------------------- */
-/*      Establish this as a dataset and open the file using VSI*L.      */
-/* -------------------------------------------------------------------- */
+    // Establish this as a dataset and open the file using VSI*L.
     RDataset *poDS = new RDataset();
 
-    poDS->fp = VSIFOpenL( osAdjustedFilename, "r" );
+    poDS->fp = VSIFOpenL(osAdjustedFilename, "r");
     if( poDS->fp == NULL )
     {
         delete poDS;
         return NULL;
     }
 
-    poDS->bASCII =
-        STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "RDA2\nA\n");
+    poDS->bASCII = STARTS_WITH_CI(
+        reinterpret_cast<char *>(poOpenInfo->pabyHeader), "RDA2\nA\n");
 
-/* -------------------------------------------------------------------- */
-/*      Confirm this is a version 2 file.                               */
-/* -------------------------------------------------------------------- */
-    VSIFSeekL( poDS->fp, 7, SEEK_SET );
+    // Confirm this is a version 2 file.
+    VSIFSeekL(poDS->fp, 7, SEEK_SET);
     if( poDS->ReadInteger() != R_LISTSXP )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "It appears %s is not a version 2 R object file after all!",
-                  poOpenInfo->pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "It appears %s is not a version 2 R object file after all!",
+                 poOpenInfo->pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Skip the version values.                                        */
-/* -------------------------------------------------------------------- */
+    // Skip the version values.
     poDS->ReadInteger();
     poDS->ReadInteger();
 
-/* -------------------------------------------------------------------- */
-/*      Confirm we have a numeric vector object in a pairlist.          */
-/* -------------------------------------------------------------------- */
+    // Confirm we have a numeric vector object in a pairlist.
     CPLString osObjName;
-    int nObjCode;
+    int nObjCode = 0;
 
-    if( !poDS->ReadPair( osObjName, nObjCode ) )
+    if( !poDS->ReadPair(osObjName, nObjCode) )
     {
         delete poDS;
         return NULL;
@@ -423,26 +360,49 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
     if( nObjCode % 256 != R_REALSXP )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to find expected numeric vector object." );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Failed to find expected numeric vector object.");
         return NULL;
     }
 
-    poDS->SetMetadataItem( "R_OBJECT_NAME", osObjName );
+    poDS->SetMetadataItem("R_OBJECT_NAME", osObjName);
+
+    // Read the count.
+    const int nValueCount = poDS->ReadInteger();
+    if( nValueCount < 0 )
+    {
+        CPLError(
+            CE_Failure, CPLE_AppDefined, "nValueCount < 0: %d", nValueCount);
+        delete poDS;
+        return NULL;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Read the count.                                                 */
-/* -------------------------------------------------------------------- */
-    int nValueCount = poDS->ReadInteger();
+    poDS->nStartOfData = VSIFTellL(poDS->fp);
 
-    poDS->nStartOfData = VSIFTellL( poDS->fp );
+    // TODO(schwehr): Factor in the size of doubles.
+    VSIStatBufL stat;
+    const int dStatSuccess =
+        VSIStatExL(osAdjustedFilename, &stat, VSI_STAT_SIZE_FLAG);
+    if( dStatSuccess != 0 ||
+        static_cast<vsi_l_offset>(nValueCount) >
+        stat.st_size - poDS->nStartOfData )
+    {
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Corrupt file.  "
+            "Object claims to be larger than available bytes. "
+            "%d > " CPL_FRMT_GUIB,
+            nValueCount,
+            stat.st_size - poDS->nStartOfData);
+        delete poDS;
+        return NULL;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Read/Skip ahead to attributes.                                  */
-/* -------------------------------------------------------------------- */
+    // Read/Skip ahead to attributes.
     if( poDS->bASCII )
     {
-        poDS->padfMatrixValues = (double*) VSIMalloc2( nValueCount, sizeof(double) );
+        poDS->padfMatrixValues =
+            static_cast<double *>(VSIMalloc2(nValueCount, sizeof(double)));
         if (poDS->padfMatrixValues == NULL)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -455,21 +415,20 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        VSIFSeekL( poDS->fp, 8 * nValueCount, SEEK_CUR );
+        VSIFSeekL(poDS->fp, 8 * nValueCount, SEEK_CUR);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read pairs till we run out, trying to find a few items that     */
-/*      have special meaning to us.                                     */
-/* -------------------------------------------------------------------- */
-    poDS->nRasterXSize = poDS->nRasterYSize = 0;
+    // Read pairs till we run out, trying to find a few items that
+    // have special meaning to us.
+    poDS->nRasterXSize = 0;
+    poDS->nRasterYSize = 0;
     int nBandCount = 0;
 
-    while( poDS->ReadPair( osObjName, nObjCode ) && nObjCode != 254 )
+    while( poDS->ReadPair(osObjName, nObjCode) && nObjCode != 254 )
     {
         if( osObjName == "dim" && nObjCode % 256 == R_INTSXP )
         {
-            int nCount = poDS->ReadInteger();
+            const int nCount = poDS->ReadInteger();
             if( nCount == 2 )
             {
                 poDS->nRasterXSize = poDS->ReadInteger();
@@ -484,8 +443,8 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
             }
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "R 'dim' dimension wrong." );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "R 'dim' dimension wrong.");
                 delete poDS;
                 return NULL;
             }
@@ -517,8 +476,8 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS->nRasterXSize == 0 )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Failed to find dim dimension information for R dataset." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failed to find dim dimension information for R dataset.");
         return NULL;
     }
 
@@ -529,48 +488,44 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    if( nValueCount
-        < ((GIntBig) nBandCount) * poDS->nRasterXSize * poDS->nRasterYSize )
+    if( nValueCount < static_cast<GIntBig>(nBandCount) * poDS->nRasterXSize *
+                          poDS->nRasterYSize )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Not enough pixel data." );
+        CPLError(CE_Failure, CPLE_AppDefined, "Not enough pixel data.");
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the raster band object(s).                               */
-/* -------------------------------------------------------------------- */
+    // Create the raster band object(s).
     for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
-        GDALRasterBand *poBand;
+        GDALRasterBand *poBand = NULL;
 
         if( poDS->bASCII )
-            poBand = new RRasterBand( poDS, iBand+1,
-                                      poDS->padfMatrixValues + iBand * poDS->nRasterXSize * poDS->nRasterYSize );
+            poBand = new RRasterBand(
+                poDS, iBand + 1,
+                poDS->padfMatrixValues +
+                    iBand * poDS->nRasterXSize * poDS->nRasterYSize);
         else
-            poBand = new RawRasterBand( poDS, iBand+1, poDS->fp,
-                                        poDS->nStartOfData
-                                        + poDS->nRasterXSize*poDS->nRasterYSize*8*iBand,
-                                        8, poDS->nRasterXSize * 8,
-                                        GDT_Float64, !CPL_IS_LSB,
-                                        TRUE, FALSE );
-
-        poDS->SetBand( iBand+1, poBand );
+            poBand = new RawRasterBand(
+                poDS, iBand + 1, poDS->fp,
+                poDS->nStartOfData +
+                    poDS->nRasterXSize * poDS->nRasterYSize * 8 * iBand,
+                8, poDS->nRasterXSize * 8,
+                GDT_Float64, !CPL_IS_LSB,
+                TRUE, FALSE);
+
+        poDS->SetBand(iBand + 1, poBand);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    // Initialize any PAM information.
+    poDS->SetDescription(poOpenInfo->pszFilename);
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Check for overviews.                                            */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    // Check for overviews.
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -580,28 +535,28 @@ GDALDataset *RDataset::Open( GDALOpenInfo * poOpenInfo )
 void GDALRegister_R()
 
 {
-    if( GDALGetDriverByName( "R" ) != NULL )
+    if( GDALGetDriverByName("R") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "R" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "R Object Data Store" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_r.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rda" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Float32" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetDescription("R");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "R Object Data Store");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_r.html");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "rda");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES, "Float32");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='ASCII' type='boolean' description='For ASCII output, default NO'/>"
 "   <Option name='COMPRESS' type='boolean' description='Produced Compressed output, default YES'/>"
-"</CreationOptionList>" );
+"</CreationOptionList>");
 
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
 
     poDriver->pfnOpen = RDataset::Open;
     poDriver->pfnIdentify = RDataset::Identify;
     poDriver->pfnCreateCopy = RCreateCopy;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/r/rdataset.h b/frmts/r/rdataset.h
new file mode 100644
index 0000000..9140a0f
--- /dev/null
+++ b/frmts/r/rdataset.h
@@ -0,0 +1,104 @@
+/******************************************************************************
+ * $Id: rdataset.h 37583 2017-03-03 18:35:20Z goatbar $
+ *
+ * Project:  R Format Driver
+ * Purpose:  Read/write R stats package object format.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2009-2010, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_port.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "../raw/rawdataset.h"
+
+GDALDataset *
+RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+             int bStrict, char ** papszOptions,
+             GDALProgressFunc pfnProgress, void * pProgressData );
+
+/************************************************************************/
+/* ==================================================================== */
+/*                               RDataset                               */
+/* ==================================================================== */
+/************************************************************************/
+
+class RDataset : public GDALPamDataset
+{
+    friend class RRasterBand;
+    VSILFILE   *fp;
+    int         bASCII;
+    CPLString   osLastStringRead;
+
+    vsi_l_offset nStartOfData;
+
+    double     *padfMatrixValues;
+
+    const char *ASCIIFGets();
+    int         ReadInteger();
+    double      ReadFloat();
+    const char *ReadString();
+    bool        ReadPair( CPLString &osItemName, int &nItemType );
+
+  public:
+                RDataset();
+                ~RDataset();
+
+    static GDALDataset  *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            RRasterBand                               */
+/* ==================================================================== */
+/************************************************************************/
+
+class RRasterBand : public GDALPamRasterBand
+{
+    friend class RDataset;
+
+    const double *padfMatrixValues;
+
+  public:
+                RRasterBand( RDataset *, int, const double * );
+    virtual ~RRasterBand() {}
+
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+};
diff --git a/frmts/rasdaman/rasdamandataset.cpp b/frmts/rasdaman/rasdamandataset.cpp
index 4c23c37..ea21694 100644
--- a/frmts/rasdaman/rasdamandataset.cpp
+++ b/frmts/rasdaman/rasdamandataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rasdamandataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  * Project:  rasdaman Driver
  * Purpose:  Implement Rasdaman GDAL driver
  * Author:   Constantin Jucovschi, jucovschi at yahoo.com
@@ -41,8 +40,7 @@
 
 void CPL_DLL CPL_STDCALL GDALRegister_RASDAMAN();
 
-CPL_CVSID("$Id: rasdamandataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
-
+CPL_CVSID("$Id: rasdamandataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 class Subset
 {
@@ -69,11 +67,15 @@ public:
     return other.contains(*this);
   }
 
-  void operator = (const Subset& rhs) {
-    m_x_lo = rhs.m_x_lo;
-    m_x_hi = rhs.m_x_hi;
-    m_y_lo = rhs.m_y_lo;
-    m_y_hi = rhs.m_y_hi;
+  Subset& operator = (const Subset& rhs) {
+    if( &rhs != this )
+    {
+        m_x_lo = rhs.m_x_lo;
+        m_x_hi = rhs.m_x_hi;
+        m_y_lo = rhs.m_y_lo;
+        m_y_hi = rhs.m_y_hi;
+    }
+    return *this;
   }
 
   int x_lo() const { return m_x_lo; }
@@ -88,7 +90,6 @@ private:
   int m_y_hi;
 };
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*        RasdamanDataset                                               */
@@ -117,7 +118,7 @@ protected:
                             int, int *,
                             GSpacing nPixelSpace, GSpacing nLineSpace,
                             GSpacing nBandSpace,
-                            GDALRasterIOExtraArg* psExtraArg);
+                            GDALRasterIOExtraArg* psExtraArg) override;
 
 private:
 
@@ -128,7 +129,7 @@ private:
 
   void clear_array_cache();
 
-  r_Set<r_Ref_Any> execute(const char* string);
+  static r_Set<r_Ref_Any> execute(const char* string);
 
   void getTypes(const r_Base_Type* baseType, int &counter, int pos);
   void createBands(const char* queryString);
@@ -175,7 +176,6 @@ RasdamanDataset::~RasdamanDataset()
   FlushCache();
 }
 
-
 CPLErr RasdamanDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
@@ -211,7 +211,6 @@ CPLErr RasdamanDataset::IRasterIO( GDALRWFlag eRWFlag,
   return ret;
 }
 
-
 r_Ref<r_GMarray>& RasdamanDataset::request_array(int x_lo, int x_hi, int y_lo, int y_hi, int& offsetX, int& offsetY)
 {
   return request_array(Subset(x_lo, x_hi, y_lo, y_hi), offsetX, offsetY);
@@ -219,8 +218,8 @@ r_Ref<r_GMarray>& RasdamanDataset::request_array(int x_lo, int x_hi, int y_lo, i
 
 r_Ref<r_GMarray>& RasdamanDataset::request_array(const Subset& subset, int& offsetX, int& offsetY)
 {
-  // set the offsets to 0
-  offsetX = 0; offsetY = 0;
+  offsetX = 0;
+  offsetY = 0;
 
   // check whether or not the subset was already requested
   ArrayCache::iterator it = m_array_cache.find(subset);
@@ -285,7 +284,6 @@ r_Ref<r_GMarray>& RasdamanDataset::request_array(const Subset& subset, int& offs
   return inserted.first->second;//*(ptr);
 };
 
-
 void RasdamanDataset::clear_array_cache() {
   m_array_cache.clear();
 };
@@ -309,7 +307,7 @@ public:
   RasdamanRasterBand( RasdamanDataset *, int, GDALDataType type, int offset, int size, int nBlockXSize, int nBlockYSize );
   ~RasdamanRasterBand();
 
-  virtual CPLErr IReadBlock( int, int, void * );
+  virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -329,7 +327,6 @@ public:
   const char *password;
 };*/
 
-
 /************************************************************************/
 /*                           RasdamanRasterBand()                       */
 /************************************************************************/
@@ -368,11 +365,12 @@ CPLErr RasdamanRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
   memset(pImage, 0, nRecordSize);
 
   try {
-    int x_lo = nBlockXOff * nBlockXSize,
-        x_hi = MIN(poGDS->nRasterXSize, (nBlockXOff + 1) * nBlockXSize),
-        y_lo = nBlockYOff * nBlockYSize,
-        y_hi = MIN(poGDS->nRasterYSize, (nBlockYOff + 1) * nBlockYSize),
-        offsetX = 0, offsetY = 0;
+    int x_lo = nBlockXOff * nBlockXSize;
+    int x_hi = MIN(poGDS->nRasterXSize, (nBlockXOff + 1) * nBlockXSize);
+    int y_lo = nBlockYOff * nBlockYSize;
+    int y_hi = MIN(poGDS->nRasterYSize, (nBlockYOff + 1) * nBlockYSize);
+    int offsetX = 0;
+    int offsetY = 0;
 
     r_Ref<r_GMarray>& gmdd = poGDS->request_array(x_lo, x_hi, y_lo, y_hi, offsetX, offsetY);
 
@@ -389,11 +387,13 @@ CPLErr RasdamanRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     CPLDebug("rasdaman", "Extents (%d, %d).", extentX, extentY);
 
     r_Point access = base;
-    char *resultPtr;
 
-    for(int y = y_lo; y < y_hi; ++y) {
-      for(int x = x_lo; x < x_hi; ++x) {
-        resultPtr = (char*)pImage + ((y - y_lo) * nBlockXSize + x - x_lo) * typeSize;
+    for( int y = y_lo; y < y_hi; ++y )
+    {
+      for( int x = x_lo; x < x_hi; ++x )
+      {
+        char *resultPtr =
+            (char*)pImage + ((y - y_lo) * nBlockXSize + x - x_lo) * typeSize;
         //resultPtr = (char*) pImage
         access[xPos] = x;// base[xPos] + offsetX; TODO: check if required
         access[yPos] = y;// base[yPos] + offsetY;
@@ -402,7 +402,7 @@ CPLErr RasdamanRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
       }
     }
   }
-  catch (r_Error error) {
+  catch (const r_Error& error) {
     CPLError(CE_Failure, CPLE_AppDefined, "%s", error.what());
     return CPLGetLastErrorType();
   }
@@ -448,7 +448,6 @@ static void replace(CPLString& str, const char *from, const char *to) {
   }
 }
 
-
 static CPLString getQuery(const char *templateString, const char* x_lo, const char* x_hi, const char* y_lo, const char* y_hi) {
   CPLString result(templateString);
 
@@ -487,14 +486,15 @@ static GDALDataType mapRasdamanTypesToGDAL(r_Type::r_Type_Id typeId) {
 }
 
 void RasdamanDataset::getTypes(const r_Base_Type* baseType, int &counter, int pos) {
-  if (baseType->isStructType()) {
+  if (baseType->isStructType())
+  {
     r_Structure_Type* tp = (r_Structure_Type*) baseType;
     int elem = tp->count_elements();
-    for (int i = 0; i < elem; ++i) {
+    for (int i = 0; i < elem; ++i)
+    {
       r_Attribute attr = (*tp)[i];
       getTypes(&attr.type_of(), counter, attr.global_offset());
     }
-
   }
   if (baseType->isPrimitiveType()) {
     r_Primitive_Type *primType = (r_Primitive_Type*)baseType;
@@ -525,7 +525,6 @@ r_Set<r_Ref_Any> RasdamanDataset::execute(const char* string) {
   return result_set;
 }
 
-
 static int getExtent(const char *queryString, int &pos) {
   r_Set<r_Ref_Any> result_set;
   r_OQL_Query query (queryString);
@@ -552,7 +551,6 @@ static int getExtent(const char *queryString, int &pos) {
     return -1;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -618,7 +616,6 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
 
   regfree(&optionRegEx);
 
-
   // checking if the whole expressions was matches, if not give an error where
   // the matching stopped and exit
   if (size_t(matches[0].rm_eo) < strlen(connString)) {
@@ -687,7 +684,7 @@ GDALDataset *RasdamanDataset::Open( GDALOpenInfo * poOpenInfo )
     rasDataset->databasename = databasename;
 
     return rasDataset;
-  } catch (r_Error error) {
+  } catch (const r_Error& error) {
     CPLError(CE_Failure, CPLE_AppDefined, "%s", error.what());
     delete rasDataset;
     return NULL;
diff --git a/frmts/rasterlite/rasterlitecreatecopy.cpp b/frmts/rasterlite/rasterlitecreatecopy.cpp
index 0a47428..ce9b883 100644
--- a/frmts/rasterlite/rasterlitecreatecopy.cpp
+++ b/frmts/rasterlite/rasterlitecreatecopy.cpp
@@ -1,735 +1,735 @@
-/******************************************************************************
- * $Id: rasterlitecreatecopy.cpp 32984 2016-01-14 19:08:12Z goatbar $
- *
- * Project:  GDAL Rasterlite driver
- * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- **********************************************************************
- * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_string.h"
-#include "ogr_api.h"
-#include "ogr_srs_api.h"
-
-#include "rasterlitedataset.h"
-
-CPL_CVSID("$Id: rasterlitecreatecopy.cpp 32984 2016-01-14 19:08:12Z goatbar $");
-
-/************************************************************************/
-/*                  RasterliteGetTileDriverOptions ()                   */
-/************************************************************************/
-
-static char** RasterliteAddTileDriverOptionsForDriver(char** papszOptions,
-                                                    char** papszTileDriverOptions,
-                                                    const char* pszOptionName,
-                                                    const char* pszExpectedDriverName)
-{
-    const char* pszVal = CSLFetchNameValue(papszOptions, pszOptionName);
-    if (pszVal)
-    {
-        const char* pszDriverName =
-            CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
-        if (EQUAL(pszDriverName, pszExpectedDriverName))
-        {
-            papszTileDriverOptions =
-                CSLSetNameValue(papszTileDriverOptions, pszOptionName, pszVal);
-        }
-        else
-        {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                     "Unexpected option '%s' for driver '%s'",
-                     pszOptionName, pszDriverName);
-        }
-    }
-    return papszTileDriverOptions;
-}
-
-char** RasterliteGetTileDriverOptions(char** papszOptions)
-{
-    const char* pszDriverName =
-        CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
-
-    char** papszTileDriverOptions = NULL;
-    if (EQUAL(pszDriverName, "EPSILON"))
-    {
-        papszTileDriverOptions = CSLSetNameValue(papszTileDriverOptions,
-                                                "RASTERLITE_OUTPUT", "YES");
-    }
-
-    const char* pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
-    if (pszQuality)
-    {
-        if (EQUAL(pszDriverName, "GTiff"))
-        {
-            papszTileDriverOptions =
-                CSLSetNameValue(papszTileDriverOptions, "JPEG_QUALITY", pszQuality);
-        }
-        else if (EQUAL(pszDriverName, "JPEG") || EQUAL(pszDriverName, "WEBP"))
-        {
-            papszTileDriverOptions =
-                CSLSetNameValue(papszTileDriverOptions, "QUALITY", pszQuality);
-        }
-        else
-        {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                     "Unexpected option '%s' for driver '%s'",
-                     "QUALITY", pszDriverName);
-        }
-    }
-
-    papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
-                papszOptions, papszTileDriverOptions, "COMPRESS", "GTiff");
-    papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
-                papszOptions, papszTileDriverOptions, "PHOTOMETRIC", "GTiff");
-    papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
-                papszOptions, papszTileDriverOptions, "TARGET", "EPSILON");
-    papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
-                papszOptions, papszTileDriverOptions, "FILTER", "EPSILON");
-
-    return papszTileDriverOptions;
-}
-
-/************************************************************************/
-/*                      RasterliteInsertSRID ()                         */
-/************************************************************************/
-
-static int RasterliteInsertSRID(OGRDataSourceH hDS, const char* pszWKT)
-{
-    int nAuthorityCode = 0;
-    CPLString osAuthorityName, osProjCS, osProj4;
-    if (pszWKT != NULL && strlen(pszWKT) != 0)
-    {
-        OGRSpatialReferenceH hSRS = OSRNewSpatialReference(pszWKT);
-        if (hSRS)
-        {
-            const char* pszAuthorityName = OSRGetAuthorityName(hSRS, NULL);
-            if (pszAuthorityName) osAuthorityName = pszAuthorityName;
-
-            const char* pszProjCS = OSRGetAttrValue(hSRS, "PROJCS", 0);
-            if (pszProjCS) osProjCS = pszProjCS;
-
-            const char* pszAuthorityCode = OSRGetAuthorityCode(hSRS, NULL);
-            if (pszAuthorityCode) nAuthorityCode = atoi(pszAuthorityCode);
-
-            char    *pszProj4 = NULL;
-            if( OSRExportToProj4( hSRS, &pszProj4 ) != OGRERR_NONE )
-            {
-                CPLFree(pszProj4);
-                pszProj4 = CPLStrdup("");
-            }
-            osProj4 = pszProj4;
-            CPLFree(pszProj4);
-        }
-        OSRDestroySpatialReference(hSRS);
-    }
-
-    CPLString osSQL;
-    int nSRSId = -1;
-    if (nAuthorityCode != 0 && osAuthorityName.size() != 0)
-    {
-        osSQL.Printf   ("SELECT srid FROM spatial_ref_sys WHERE auth_srid = %d", nAuthorityCode);
-        OGRLayerH hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-        if (hLyr == NULL)
-        {
-            nSRSId = nAuthorityCode;
-
-            if ( osProjCS.size() != 0 )
-                osSQL.Printf(
-                    "INSERT INTO spatial_ref_sys "
-                    "(srid, auth_name, auth_srid, ref_sys_name, proj4text) "
-                    "VALUES (%d, '%s', '%d', '%s', '%s')",
-                    nSRSId, osAuthorityName.c_str(),
-                    nAuthorityCode, osProjCS.c_str(), osProj4.c_str() );
-            else
-                osSQL.Printf(
-                    "INSERT INTO spatial_ref_sys "
-                    "(srid, auth_name, auth_srid, proj4text) "
-                    "VALUES (%d, '%s', '%d', '%s')",
-                    nSRSId, osAuthorityName.c_str(),
-                    nAuthorityCode, osProj4.c_str() );
-
-            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-        }
-        else
-        {
-            OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
-            if (hFeat)
-            {
-                nSRSId = OGR_F_GetFieldAsInteger(hFeat, 0);
-                OGR_F_Destroy(hFeat);
-            }
-            OGR_DS_ReleaseResultSet(hDS, hLyr);
-        }
-    }
-
-    return nSRSId;
-}
-
-/************************************************************************/
-/*                     RasterliteCreateTables ()                        */
-/************************************************************************/
-
-static 
-OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableName,
-                                      int nSRSId, int bWipeExistingData)
-{
-    CPLString osSQL;
-
-    const CPLString osDBName = OGR_DS_GetName(hDS);
-
-    CPLString osRasterLayer;
-    osRasterLayer.Printf("%s_rasters", pszTableName);
-
-    CPLString osMetadataLayer;
-    osMetadataLayer.Printf("%s_metadata", pszTableName);
-
-    OGRLayerH hLyr;
-
-    if (OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str()) == NULL)
-    {
-/* -------------------------------------------------------------------- */
-/*      The table don't exist. Create them                              */
-/* -------------------------------------------------------------------- */
-
-        /* Create _rasters table */
-        osSQL.Printf   ("CREATE TABLE \"%s\" ("
-                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
-                        "raster BLOB NOT NULL)", osRasterLayer.c_str());
-        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-        /* Create _metadata table */
-        osSQL.Printf   ("CREATE TABLE \"%s\" ("
-                        "id INTEGER NOT NULL PRIMARY KEY,"
-                        "source_name TEXT NOT NULL,"
-                        "tile_id INTEGER NOT NULL,"
-                        "width INTEGER NOT NULL,"
-                        "height INTEGER NOT NULL,"
-                        "pixel_x_size DOUBLE NOT NULL,"
-                        "pixel_y_size DOUBLE NOT NULL)",
-                        osMetadataLayer.c_str());
-        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-        /* Add geometry column to _metadata table */
-        osSQL.Printf("SELECT AddGeometryColumn('%s', 'geometry', %d, 'POLYGON', 2)",
-                      osMetadataLayer.c_str(), nSRSId);
-        if ((hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL)) == NULL)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Check that the OGR SQLite driver has Spatialite support");
-            OGRReleaseDataSource(hDS);
-            return NULL;
-        }
-        OGR_DS_ReleaseResultSet(hDS, hLyr);
-
-        /* Create spatial index on _metadata table */
-        osSQL.Printf("SELECT CreateSpatialIndex('%s', 'geometry')",
-                      osMetadataLayer.c_str());
-        if ((hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL)) == NULL)
-        {
-            OGRReleaseDataSource(hDS);
-            return NULL;
-        }
-        OGR_DS_ReleaseResultSet(hDS, hLyr);
-
-        /* Create statistics tables */
-        osSQL.Printf("SELECT UpdateLayerStatistics()");
-        CPLPushErrorHandler(CPLQuietErrorHandler);
-        hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-        CPLPopErrorHandler();
-        OGR_DS_ReleaseResultSet(hDS, hLyr);
-
-        /* Re-open the DB to take into account the new tables*/
-        OGRReleaseDataSource(hDS);
-
-        hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
-    }
-    else
-    {
-        /* Check that the existing SRS is consistent with the one of the new */
-        /* data to be inserted */
-        osSQL.Printf("SELECT srid FROM geometry_columns WHERE f_table_name = '%s'",
-                     osMetadataLayer.c_str());
-        hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-        if (hLyr)
-        {
-            int nExistingSRID = -1;
-            OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
-            if (hFeat)
-            {
-                nExistingSRID = OGR_F_GetFieldAsInteger(hFeat, 0);
-                OGR_F_Destroy(hFeat);
-            }
-            OGR_DS_ReleaseResultSet(hDS, hLyr);
-
-            if (nExistingSRID != nSRSId)
-            {
-                if (bWipeExistingData)
-                {
-                    osSQL.Printf("UPDATE geometry_columns SET srid = %d "
-                                 "WHERE f_table_name = \"%s\"",
-                                 nSRSId, osMetadataLayer.c_str());
-                    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-                    /* Re-open the DB to take into account the change of SRS */
-                    OGRReleaseDataSource(hDS);
-
-                    hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
-                }
-                else
-                {
-                    CPLError(CE_Failure, CPLE_NotSupported,
-                             "New data has not the same SRS as existing data");
-                    OGRReleaseDataSource(hDS);
-                    return NULL;
-                }
-            }
-        }
-
-        if (bWipeExistingData)
-        {
-            osSQL.Printf("DELETE FROM \"%s\"", osRasterLayer.c_str());
-            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-            osSQL.Printf("DELETE FROM \"%s\"", osMetadataLayer.c_str());
-            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-        }
-    }
-
-    return hDS;
-}
-
-/************************************************************************/
-/*                       RasterliteCreateCopy ()                        */
-/************************************************************************/
-
-GDALDataset *
-RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
-                      CPL_UNUSED int bStrict,
-                      char ** papszOptions,
-                      GDALProgressFunc pfnProgress, void * pProgressData )
-{
-    const int nBands = poSrcDS->GetRasterCount();
-    if (nBands == 0)
-    {
-        CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0");
-        return NULL;
-    }
-
-    const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
-    if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "GDAL %s driver cannot be used as underlying driver",
-                 pszDriverName);
-        return NULL;
-    }
-
-    GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
-    if ( hTileDriver == NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
-        return NULL;
-    }
-
-    GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
-    if (hMemDriver == NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
-        return NULL;
-    }
-
-    const int nXSize = GDALGetRasterXSize(poSrcDS);
-    const int nYSize = GDALGetRasterYSize(poSrcDS);
-
-    double adfGeoTransform[6];
-    if (poSrcDS->GetGeoTransform(adfGeoTransform) != CE_None)
-    {
-        adfGeoTransform[0] = 0;
-        adfGeoTransform[1] = 1;
-        adfGeoTransform[2] = 0;
-        adfGeoTransform[3] = 0;
-        adfGeoTransform[4] = 0;
-        adfGeoTransform[5] = -1;
-    }
-    else if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot use geotransform with rotational terms");
-        return NULL;
-    }
-
-    const bool bTiled = CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
-    int nBlockXSize, nBlockYSize;
-    if (bTiled)
-    {
-        nBlockXSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
-        nBlockYSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
-        if (nBlockXSize < 64) nBlockXSize = 64;
-        else if (nBlockXSize > 4096)  nBlockXSize = 4096;
-        if (nBlockYSize < 64) nBlockYSize = 64;
-        else if (nBlockYSize > 4096)  nBlockYSize = 4096;
-    }
-    else
-    {
-        nBlockXSize = nXSize;
-        nBlockYSize = nYSize;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Analyze arguments                                               */
-/* -------------------------------------------------------------------- */
-
-    /* Skip optional RASTERLITE: prefix */
-    const char* pszFilenameWithoutPrefix = pszFilename;
-    if (STARTS_WITH_CI(pszFilename, "RASTERLITE:"))
-        pszFilenameWithoutPrefix += 11;
-
-    char** papszTokens = CSLTokenizeStringComplex(
-                pszFilenameWithoutPrefix, ",", FALSE, FALSE );
-    const int nTokens = CSLCount(papszTokens);
-    CPLString osDBName;
-    CPLString osTableName;
-    if (nTokens == 0)
-    {
-        osDBName = pszFilenameWithoutPrefix;
-        osTableName = CPLGetBasename(pszFilenameWithoutPrefix);
-    }
-    else
-    {
-        osDBName = papszTokens[0];
-
-        int i;
-        for(i=1;i<nTokens;i++)
-        {
-            if (STARTS_WITH_CI(papszTokens[i], "table="))
-                osTableName = papszTokens[i] + 6;
-            else
-            {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "Invalid option : %s", papszTokens[i]);
-            }
-        }
-    }
-
-    CSLDestroy(papszTokens);
-    papszTokens = NULL;
-
-    VSIStatBuf sBuf;
-    const bool bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0);
-
-    if (osTableName.size() == 0)
-    {
-        if (bExists)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Database already exists. Explicit table name must be specified");
-            return NULL;
-        }
-        osTableName = CPLGetBasename(osDBName.c_str());
-    }
-
-    CPLString osRasterLayer;
-    osRasterLayer.Printf("%s_rasters", osTableName.c_str());
-
-    CPLString osMetadataLayer;
-    osMetadataLayer.Printf("%s_metadata", osTableName.c_str());
-
-/* -------------------------------------------------------------------- */
-/*      Create or open the SQLite DB                                    */
-/* -------------------------------------------------------------------- */
-
-    if (OGRGetDriverCount() == 0)
-        OGRRegisterAll();
-
-    OGRSFDriverH hSQLiteDriver = OGRGetDriverByName("SQLite");
-    if (hSQLiteDriver == NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load OGR SQLite driver");
-        return NULL;
-    }
-
-    OGRDataSourceH hDS;
-
-    if (!bExists)
-    {
-        char** papszOGROptions = CSLAddString(NULL, "SPATIALITE=YES");
-        hDS = OGR_Dr_CreateDataSource(hSQLiteDriver,
-                                      osDBName.c_str(), papszOGROptions);
-        CSLDestroy(papszOGROptions);
-    }
-    else
-    {
-        hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
-    }
-
-    if (hDS == NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot load or create SQLite database");
-        return NULL;
-    }
-
-    CPLString osSQL;
-
-/* -------------------------------------------------------------------- */
-/*      Get the SRID for the SRS                                        */
-/* -------------------------------------------------------------------- */
-    int nSRSId = RasterliteInsertSRID(hDS, poSrcDS->GetProjectionRef());
-
-/* -------------------------------------------------------------------- */
-/*      Create or wipe existing tables                                  */
-/* -------------------------------------------------------------------- */
-    const int bWipeExistingData =
-        CPLTestBool(CSLFetchNameValueDef(papszOptions, "WIPE", "NO"));
-
-    hDS = RasterliteCreateTables(hDS, osTableName.c_str(),
-                                 nSRSId, bWipeExistingData);
-    if (hDS == NULL)
-        return NULL;
-
-    OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
-    OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetadataLayer.c_str());
-    if (hRasterLayer == NULL || hMetadataLayer == NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot find metadata and/or raster tables");
-        OGRReleaseDataSource(hDS);
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Check if there is overlapping data and warn the user            */
-/* -------------------------------------------------------------------- */
-    double minx = adfGeoTransform[0];
-    double maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1];
-    double maxy = adfGeoTransform[3];
-    double miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5];
-
-    osSQL.Printf("SELECT COUNT(geometry) FROM \"%s\" "
-                 "WHERE rowid IN "
-                 "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
-                  "WHERE %s) AND %s",
-                  osMetadataLayer.c_str(),
-                  osTableName.c_str(),
-                  RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(),
-                  RasterliteGetPixelSizeCond(adfGeoTransform[1], -adfGeoTransform[5]).c_str());
-
-    int nOverlappingGeoms = 0;
-    OGRLayerH hCountLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    if (hCountLyr)
-    {
-        OGRFeatureH hFeat = OGR_L_GetNextFeature(hCountLyr);
-        if (hFeat)
-        {
-            nOverlappingGeoms = OGR_F_GetFieldAsInteger(hFeat, 0);
-            OGR_F_Destroy(hFeat);
-        }
-        OGR_DS_ReleaseResultSet(hDS, hCountLyr);
-    }
-
-    if (nOverlappingGeoms != 0)
-    {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                 "Raster tiles already exist in the %s table within "
-                 "the extent of the data to be inserted in",
-                 osTableName.c_str());
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Iterate over blocks to add data into raster and metadata tables */
-/* -------------------------------------------------------------------- */
-    int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize;
-    int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize;
-
-    GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
-    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
-    GByte* pabyMEMDSBuffer =
-        reinterpret_cast<GByte *>(
-            VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize) );
-    if (pabyMEMDSBuffer == NULL)
-    {
-        OGRReleaseDataSource(hDS);
-        return NULL;
-    }
-
-    CPLString osTempFileName;
-    osTempFileName.Printf("/vsimem/%p", hDS);
-
-    int nTileId = 0;
-    int nBlocks = 0;
-    int nTotalBlocks = nXBlocks * nYBlocks;
-
-    char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
-
-    OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
-
-    CPLErr eErr = CE_None;
-    for(int nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
-    {
-        for(int nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
-        {
-/* -------------------------------------------------------------------- */
-/*      Create in-memory tile                                           */
-/* -------------------------------------------------------------------- */
-            int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
-            if ((nBlockXOff+1) * nBlockXSize > nXSize)
-                nReqXSize = nXSize - nBlockXOff * nBlockXSize;
-            if ((nBlockYOff+1) * nBlockYSize > nYSize)
-                nReqYSize = nYSize - nBlockYOff * nBlockYSize;
-
-            eErr = poSrcDS->RasterIO(GF_Read,
-                                     nBlockXOff * nBlockXSize,
-                                     nBlockYOff * nBlockYSize,
-                                     nReqXSize, nReqYSize,
-                                     pabyMEMDSBuffer, nReqXSize, nReqYSize,
-                                     eDataType, nBands, NULL,
-                                     0, 0, 0, NULL);
-            if (eErr != CE_None)
-            {
-                break;
-            }
-
-            GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
-                                              nReqXSize, nReqYSize, 0, 
-                                              eDataType, NULL);
-            if (hMemDS == NULL)
-            {
-                eErr = CE_Failure;
-                break;
-            }
-
-            for( int iBand = 0; iBand < nBands; iBand ++)
-            {
-                char szTmp[64];
-                memset(szTmp, 0, sizeof(szTmp));
-                CPLPrintPointer(szTmp,
-                                pabyMEMDSBuffer + iBand * nDataTypeSize *
-                                nReqXSize * nReqYSize, sizeof(szTmp));
-                char** papszMEMDSOptions
-                    = CSLSetNameValue(NULL, "DATAPOINTER", szTmp);
-                GDALAddBand(hMemDS, eDataType, papszMEMDSOptions);
-                CSLDestroy(papszMEMDSOptions);
-            }
-
-            GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
-                                        osTempFileName.c_str(), hMemDS, FALSE,
-                                        papszTileDriverOptions, NULL, NULL);
-
-            GDALClose(hMemDS);
-            if ( !hOutDS )
-            {
-                eErr = CE_Failure;
-                break;
-            }
-            GDALClose(hOutDS);
-
-/* -------------------------------------------------------------------- */
-/*      Insert new entry into raster table                              */
-/* -------------------------------------------------------------------- */
-            vsi_l_offset nDataLength = 0;
-            GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
-                                                   &nDataLength, FALSE);
-
-            OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
-            OGR_F_SetFieldBinary(
-                hFeat, 0, static_cast<int>( nDataLength ), pabyData);
-
-            if( OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE )
-                eErr = CE_Failure;
-            /* Query raster ID to set it as the ID of the associated metadata */
-            int nRasterID = static_cast<int>( OGR_F_GetFID( hFeat ) );
-
-            OGR_F_Destroy(hFeat);
-
-            VSIUnlink(osTempFileName.c_str());
-            if( eErr == CE_Failure )
-                break;
-
-/* -------------------------------------------------------------------- */
-/*      Insert new entry into metadata table                            */
-/* -------------------------------------------------------------------- */
-
-            hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
-            OGR_F_SetFID(hFeat, nRasterID);
-            OGR_F_SetFieldString(hFeat, 0, GDALGetDescription(poSrcDS));
-            OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
-            OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
-            OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
-            OGR_F_SetFieldDouble(hFeat, 4, adfGeoTransform[1]);
-            OGR_F_SetFieldDouble(hFeat, 5, -adfGeoTransform[5]);
-
-            minx = adfGeoTransform[0] +
-                (nBlockXSize * nBlockXOff) * adfGeoTransform[1];
-            maxx = adfGeoTransform[0] +
-                (nBlockXSize * nBlockXOff + nReqXSize) * adfGeoTransform[1];
-            maxy = adfGeoTransform[3] +
-                (nBlockYSize * nBlockYOff) * adfGeoTransform[5];
-            miny = adfGeoTransform[3] +
-                (nBlockYSize * nBlockYOff + nReqYSize) * adfGeoTransform[5];
-
-            OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
-            OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
-            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
-            OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
-            OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
-            OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
-            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
-            OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
-
-            OGR_F_SetGeometryDirectly(hFeat, hRectangle);
-
-            if( OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE )
-                eErr = CE_Failure;
-            OGR_F_Destroy(hFeat);
-
-            nBlocks++;
-            if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
-                                            NULL, pProgressData))
-                eErr = CE_Failure;
-        }
-    }
-
-    if (eErr == CE_None)
-        OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
-    else
-        OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
-
-    CSLDestroy(papszTileDriverOptions);
-
-    VSIFree(pabyMEMDSBuffer);
-
-    OGRReleaseDataSource(hDS);
-
-    if( eErr == CE_Failure )
-        return NULL;
-
-    return reinterpret_cast<GDALDataset *>(
-        GDALOpen( pszFilename, GA_Update ) );
-}
-
-/************************************************************************/
-/*                         RasterliteDelete ()                          */
-/************************************************************************/
-
-CPLErr RasterliteDelete(CPL_UNUSED const char* pszFilename)
-{
-    return CE_None;
-}
+/******************************************************************************
+ *
+ * Project:  GDAL Rasterlite driver
+ * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "ogr_api.h"
+#include "ogr_srs_api.h"
+
+#include "rasterlitedataset.h"
+
+CPL_CVSID("$Id: rasterlitecreatecopy.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+/************************************************************************/
+/*                  RasterliteGetTileDriverOptions ()                   */
+/************************************************************************/
+
+static char** RasterliteAddTileDriverOptionsForDriver(char** papszOptions,
+                                                    char** papszTileDriverOptions,
+                                                    const char* pszOptionName,
+                                                    const char* pszExpectedDriverName)
+{
+    const char* pszVal = CSLFetchNameValue(papszOptions, pszOptionName);
+    if (pszVal)
+    {
+        const char* pszDriverName =
+            CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
+        if (EQUAL(pszDriverName, pszExpectedDriverName))
+        {
+            papszTileDriverOptions =
+                CSLSetNameValue(papszTileDriverOptions, pszOptionName, pszVal);
+        }
+        else
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "Unexpected option '%s' for driver '%s'",
+                     pszOptionName, pszDriverName);
+        }
+    }
+    return papszTileDriverOptions;
+}
+
+char** RasterliteGetTileDriverOptions(char** papszOptions)
+{
+    const char* pszDriverName =
+        CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
+
+    char** papszTileDriverOptions = NULL;
+    if (EQUAL(pszDriverName, "EPSILON"))
+    {
+        papszTileDriverOptions = CSLSetNameValue(papszTileDriverOptions,
+                                                "RASTERLITE_OUTPUT", "YES");
+    }
+
+    const char* pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
+    if (pszQuality)
+    {
+        if (EQUAL(pszDriverName, "GTiff"))
+        {
+            papszTileDriverOptions =
+                CSLSetNameValue(papszTileDriverOptions, "JPEG_QUALITY", pszQuality);
+        }
+        else if (EQUAL(pszDriverName, "JPEG") || EQUAL(pszDriverName, "WEBP"))
+        {
+            papszTileDriverOptions =
+                CSLSetNameValue(papszTileDriverOptions, "QUALITY", pszQuality);
+        }
+        else
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "Unexpected option '%s' for driver '%s'",
+                     "QUALITY", pszDriverName);
+        }
+    }
+
+    papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
+                papszOptions, papszTileDriverOptions, "COMPRESS", "GTiff");
+    papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
+                papszOptions, papszTileDriverOptions, "PHOTOMETRIC", "GTiff");
+    papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
+                papszOptions, papszTileDriverOptions, "TARGET", "EPSILON");
+    papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
+                papszOptions, papszTileDriverOptions, "FILTER", "EPSILON");
+
+    return papszTileDriverOptions;
+}
+
+/************************************************************************/
+/*                      RasterliteInsertSRID ()                         */
+/************************************************************************/
+
+static int RasterliteInsertSRID(OGRDataSourceH hDS, const char* pszWKT)
+{
+    int nAuthorityCode = 0;
+    CPLString osAuthorityName, osProjCS, osProj4;
+    if (pszWKT != NULL && strlen(pszWKT) != 0)
+    {
+        OGRSpatialReferenceH hSRS = OSRNewSpatialReference(pszWKT);
+        if (hSRS)
+        {
+            const char* pszAuthorityName = OSRGetAuthorityName(hSRS, NULL);
+            if (pszAuthorityName) osAuthorityName = pszAuthorityName;
+
+            const char* pszProjCS = OSRGetAttrValue(hSRS, "PROJCS", 0);
+            if (pszProjCS) osProjCS = pszProjCS;
+
+            const char* pszAuthorityCode = OSRGetAuthorityCode(hSRS, NULL);
+            if (pszAuthorityCode) nAuthorityCode = atoi(pszAuthorityCode);
+
+            char    *pszProj4 = NULL;
+            if( OSRExportToProj4( hSRS, &pszProj4 ) != OGRERR_NONE )
+            {
+                CPLFree(pszProj4);
+                pszProj4 = CPLStrdup("");
+            }
+            osProj4 = pszProj4;
+            CPLFree(pszProj4);
+        }
+        OSRDestroySpatialReference(hSRS);
+    }
+
+    CPLString osSQL;
+    int nSRSId = -1;
+    if (nAuthorityCode != 0 && !osAuthorityName.empty())
+    {
+        osSQL.Printf   ("SELECT srid FROM spatial_ref_sys WHERE auth_srid = %d", nAuthorityCode);
+        OGRLayerH hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+        if (hLyr == NULL)
+        {
+            nSRSId = nAuthorityCode;
+
+            if ( !osProjCS.empty() )
+                osSQL.Printf(
+                    "INSERT INTO spatial_ref_sys "
+                    "(srid, auth_name, auth_srid, ref_sys_name, proj4text) "
+                    "VALUES (%d, '%s', '%d', '%s', '%s')",
+                    nSRSId, osAuthorityName.c_str(),
+                    nAuthorityCode, osProjCS.c_str(), osProj4.c_str() );
+            else
+                osSQL.Printf(
+                    "INSERT INTO spatial_ref_sys "
+                    "(srid, auth_name, auth_srid, proj4text) "
+                    "VALUES (%d, '%s', '%d', '%s')",
+                    nSRSId, osAuthorityName.c_str(),
+                    nAuthorityCode, osProj4.c_str() );
+
+            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+        }
+        else
+        {
+            OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
+            if (hFeat)
+            {
+                nSRSId = OGR_F_GetFieldAsInteger(hFeat, 0);
+                OGR_F_Destroy(hFeat);
+            }
+            OGR_DS_ReleaseResultSet(hDS, hLyr);
+        }
+    }
+
+    return nSRSId;
+}
+
+/************************************************************************/
+/*                     RasterliteCreateTables ()                        */
+/************************************************************************/
+
+static
+OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableName,
+                                      int nSRSId, int bWipeExistingData)
+{
+    CPLString osSQL;
+
+    const CPLString osDBName = OGR_DS_GetName(hDS);
+
+    CPLString osRasterLayer;
+    osRasterLayer.Printf("%s_rasters", pszTableName);
+
+    CPLString osMetadataLayer;
+    osMetadataLayer.Printf("%s_metadata", pszTableName);
+
+    OGRLayerH hLyr;
+
+    if (OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str()) == NULL)
+    {
+/* -------------------------------------------------------------------- */
+/*      The table don't exist. Create them                              */
+/* -------------------------------------------------------------------- */
+
+        /* Create _rasters table */
+        osSQL.Printf   ("CREATE TABLE \"%s\" ("
+                        "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
+                        "raster BLOB NOT NULL)", osRasterLayer.c_str());
+        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+        /* Create _metadata table */
+        osSQL.Printf   ("CREATE TABLE \"%s\" ("
+                        "id INTEGER NOT NULL PRIMARY KEY,"
+                        "source_name TEXT NOT NULL,"
+                        "tile_id INTEGER NOT NULL,"
+                        "width INTEGER NOT NULL,"
+                        "height INTEGER NOT NULL,"
+                        "pixel_x_size DOUBLE NOT NULL,"
+                        "pixel_y_size DOUBLE NOT NULL)",
+                        osMetadataLayer.c_str());
+        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+        /* Add geometry column to _metadata table */
+        osSQL.Printf("SELECT AddGeometryColumn('%s', 'geometry', %d, 'POLYGON', 2)",
+                      osMetadataLayer.c_str(), nSRSId);
+        if ((hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL)) == NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Check that the OGR SQLite driver has Spatialite support");
+            OGRReleaseDataSource(hDS);
+            return NULL;
+        }
+        OGR_DS_ReleaseResultSet(hDS, hLyr);
+
+        /* Create spatial index on _metadata table */
+        osSQL.Printf("SELECT CreateSpatialIndex('%s', 'geometry')",
+                      osMetadataLayer.c_str());
+        if ((hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL)) == NULL)
+        {
+            OGRReleaseDataSource(hDS);
+            return NULL;
+        }
+        OGR_DS_ReleaseResultSet(hDS, hLyr);
+
+        /* Create statistics tables */
+        osSQL.Printf("SELECT UpdateLayerStatistics()");
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+        CPLPopErrorHandler();
+        OGR_DS_ReleaseResultSet(hDS, hLyr);
+
+        /* Re-open the DB to take into account the new tables*/
+        OGRReleaseDataSource(hDS);
+
+        hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
+    }
+    else
+    {
+        /* Check that the existing SRS is consistent with the one of the new */
+        /* data to be inserted */
+        osSQL.Printf("SELECT srid FROM geometry_columns WHERE f_table_name = '%s'",
+                     osMetadataLayer.c_str());
+        hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+        if (hLyr)
+        {
+            int nExistingSRID = -1;
+            OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
+            if (hFeat)
+            {
+                nExistingSRID = OGR_F_GetFieldAsInteger(hFeat, 0);
+                OGR_F_Destroy(hFeat);
+            }
+            OGR_DS_ReleaseResultSet(hDS, hLyr);
+
+            if (nExistingSRID != nSRSId)
+            {
+                if (bWipeExistingData)
+                {
+                    osSQL.Printf("UPDATE geometry_columns SET srid = %d "
+                                 "WHERE f_table_name = \"%s\"",
+                                 nSRSId, osMetadataLayer.c_str());
+                    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+                    /* Re-open the DB to take into account the change of SRS */
+                    OGRReleaseDataSource(hDS);
+
+                    hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
+                }
+                else
+                {
+                    CPLError(CE_Failure, CPLE_NotSupported,
+                             "New data has not the same SRS as existing data");
+                    OGRReleaseDataSource(hDS);
+                    return NULL;
+                }
+            }
+        }
+
+        if (bWipeExistingData)
+        {
+            osSQL.Printf("DELETE FROM \"%s\"", osRasterLayer.c_str());
+            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+            osSQL.Printf("DELETE FROM \"%s\"", osMetadataLayer.c_str());
+            OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+        }
+    }
+
+    return hDS;
+}
+
+/************************************************************************/
+/*                       RasterliteCreateCopy ()                        */
+/************************************************************************/
+
+GDALDataset *
+RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                      CPL_UNUSED int bStrict,
+                      char ** papszOptions,
+                      GDALProgressFunc pfnProgress, void * pProgressData )
+{
+    const int nBands = poSrcDS->GetRasterCount();
+    if (nBands == 0)
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0");
+        return NULL;
+    }
+
+    const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
+    if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDAL %s driver cannot be used as underlying driver",
+                 pszDriverName);
+        return NULL;
+    }
+
+    GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
+    if ( hTileDriver == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
+        return NULL;
+    }
+
+    GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
+    if (hMemDriver == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
+        return NULL;
+    }
+
+    const int nXSize = GDALGetRasterXSize(poSrcDS);
+    const int nYSize = GDALGetRasterYSize(poSrcDS);
+
+    double adfGeoTransform[6];
+    if (poSrcDS->GetGeoTransform(adfGeoTransform) != CE_None)
+    {
+        adfGeoTransform[0] = 0;
+        adfGeoTransform[1] = 1;
+        adfGeoTransform[2] = 0;
+        adfGeoTransform[3] = 0;
+        adfGeoTransform[4] = 0;
+        adfGeoTransform[5] = -1;
+    }
+    else if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot use geotransform with rotational terms");
+        return NULL;
+    }
+
+    const bool bTiled = CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
+    int nBlockXSize, nBlockYSize;
+    if (bTiled)
+    {
+        nBlockXSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
+        nBlockYSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
+        if (nBlockXSize < 64) nBlockXSize = 64;
+        else if (nBlockXSize > 4096)  nBlockXSize = 4096;
+        if (nBlockYSize < 64) nBlockYSize = 64;
+        else if (nBlockYSize > 4096)  nBlockYSize = 4096;
+    }
+    else
+    {
+        nBlockXSize = nXSize;
+        nBlockYSize = nYSize;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Analyze arguments                                               */
+/* -------------------------------------------------------------------- */
+
+    /* Skip optional RASTERLITE: prefix */
+    const char* pszFilenameWithoutPrefix = pszFilename;
+    if (STARTS_WITH_CI(pszFilename, "RASTERLITE:"))
+        pszFilenameWithoutPrefix += 11;
+
+    char** papszTokens = CSLTokenizeStringComplex(
+                pszFilenameWithoutPrefix, ",", FALSE, FALSE );
+    const int nTokens = CSLCount(papszTokens);
+    CPLString osDBName;
+    CPLString osTableName;
+    if (nTokens == 0)
+    {
+        osDBName = pszFilenameWithoutPrefix;
+        osTableName = CPLGetBasename(pszFilenameWithoutPrefix);
+    }
+    else
+    {
+        osDBName = papszTokens[0];
+
+        int i;
+        for(i=1;i<nTokens;i++)
+        {
+            if (STARTS_WITH_CI(papszTokens[i], "table="))
+                osTableName = papszTokens[i] + 6;
+            else
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Invalid option : %s", papszTokens[i]);
+            }
+        }
+    }
+
+    CSLDestroy(papszTokens);
+    papszTokens = NULL;
+
+    VSIStatBuf sBuf;
+    const bool bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0);
+
+    if (osTableName.empty())
+    {
+        if (bExists)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Database already exists. Explicit table name must be specified");
+            return NULL;
+        }
+        osTableName = CPLGetBasename(osDBName.c_str());
+    }
+
+    CPLString osRasterLayer;
+    osRasterLayer.Printf("%s_rasters", osTableName.c_str());
+
+    CPLString osMetadataLayer;
+    osMetadataLayer.Printf("%s_metadata", osTableName.c_str());
+
+/* -------------------------------------------------------------------- */
+/*      Create or open the SQLite DB                                    */
+/* -------------------------------------------------------------------- */
+
+    if (OGRGetDriverCount() == 0)
+        OGRRegisterAll();
+
+    OGRSFDriverH hSQLiteDriver = OGRGetDriverByName("SQLite");
+    if (hSQLiteDriver == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load OGR SQLite driver");
+        return NULL;
+    }
+
+    OGRDataSourceH hDS;
+
+    if (!bExists)
+    {
+        char** papszOGROptions = CSLAddString(NULL, "SPATIALITE=YES");
+        hDS = OGR_Dr_CreateDataSource(hSQLiteDriver,
+                                      osDBName.c_str(), papszOGROptions);
+        CSLDestroy(papszOGROptions);
+    }
+    else
+    {
+        hDS = RasterliteOpenSQLiteDB(osDBName.c_str(), GA_Update);
+    }
+
+    if (hDS == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot load or create SQLite database");
+        return NULL;
+    }
+
+    CPLString osSQL;
+
+/* -------------------------------------------------------------------- */
+/*      Get the SRID for the SRS                                        */
+/* -------------------------------------------------------------------- */
+    int nSRSId = RasterliteInsertSRID(hDS, poSrcDS->GetProjectionRef());
+
+/* -------------------------------------------------------------------- */
+/*      Create or wipe existing tables                                  */
+/* -------------------------------------------------------------------- */
+    const int bWipeExistingData =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions, "WIPE", "NO"));
+
+    hDS = RasterliteCreateTables(hDS, osTableName.c_str(),
+                                 nSRSId, bWipeExistingData);
+    if (hDS == NULL)
+        return NULL;
+
+    OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
+    OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetadataLayer.c_str());
+    if (hRasterLayer == NULL || hMetadataLayer == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find metadata and/or raster tables");
+        OGRReleaseDataSource(hDS);
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Check if there is overlapping data and warn the user            */
+/* -------------------------------------------------------------------- */
+    double minx = adfGeoTransform[0];
+    double maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1];
+    double maxy = adfGeoTransform[3];
+    double miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5];
+
+    osSQL.Printf("SELECT COUNT(geometry) FROM \"%s\" "
+                 "WHERE rowid IN "
+                 "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
+                  "WHERE %s) AND %s",
+                  osMetadataLayer.c_str(),
+                  osTableName.c_str(),
+                  RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(),
+                  RasterliteGetPixelSizeCond(adfGeoTransform[1], -adfGeoTransform[5]).c_str());
+
+    int nOverlappingGeoms = 0;
+    OGRLayerH hCountLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+    if (hCountLyr)
+    {
+        OGRFeatureH hFeat = OGR_L_GetNextFeature(hCountLyr);
+        if (hFeat)
+        {
+            nOverlappingGeoms = OGR_F_GetFieldAsInteger(hFeat, 0);
+            OGR_F_Destroy(hFeat);
+        }
+        OGR_DS_ReleaseResultSet(hDS, hCountLyr);
+    }
+
+    if (nOverlappingGeoms != 0)
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Raster tiles already exist in the %s table within "
+                 "the extent of the data to be inserted in",
+                 osTableName.c_str());
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Iterate over blocks to add data into raster and metadata tables */
+/* -------------------------------------------------------------------- */
+    int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize;
+    int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize;
+
+    GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
+    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
+    GByte* pabyMEMDSBuffer =
+        reinterpret_cast<GByte *>(
+            VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize) );
+    if (pabyMEMDSBuffer == NULL)
+    {
+        OGRReleaseDataSource(hDS);
+        return NULL;
+    }
+
+    CPLString osTempFileName;
+    osTempFileName.Printf("/vsimem/%p", hDS);
+
+    int nTileId = 0;
+    int nBlocks = 0;
+    int nTotalBlocks = nXBlocks * nYBlocks;
+
+    char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
+
+    OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
+
+    CPLErr eErr = CE_None;
+    for(int nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
+    {
+        for(int nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
+        {
+/* -------------------------------------------------------------------- */
+/*      Create in-memory tile                                           */
+/* -------------------------------------------------------------------- */
+            int nReqXSize = nBlockXSize;
+            int nReqYSize = nBlockYSize;
+            if ((nBlockXOff+1) * nBlockXSize > nXSize)
+                nReqXSize = nXSize - nBlockXOff * nBlockXSize;
+            if ((nBlockYOff+1) * nBlockYSize > nYSize)
+                nReqYSize = nYSize - nBlockYOff * nBlockYSize;
+
+            eErr = poSrcDS->RasterIO(GF_Read,
+                                     nBlockXOff * nBlockXSize,
+                                     nBlockYOff * nBlockYSize,
+                                     nReqXSize, nReqYSize,
+                                     pabyMEMDSBuffer, nReqXSize, nReqYSize,
+                                     eDataType, nBands, NULL,
+                                     0, 0, 0, NULL);
+            if (eErr != CE_None)
+            {
+                break;
+            }
+
+            GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
+                                              nReqXSize, nReqYSize, 0,
+                                              eDataType, NULL);
+            if (hMemDS == NULL)
+            {
+                eErr = CE_Failure;
+                break;
+            }
+
+            for( int iBand = 0; iBand < nBands; iBand ++)
+            {
+                char szTmp[64];
+                memset(szTmp, 0, sizeof(szTmp));
+                CPLPrintPointer(szTmp,
+                                pabyMEMDSBuffer + iBand * nDataTypeSize *
+                                nReqXSize * nReqYSize, sizeof(szTmp));
+                char** papszMEMDSOptions
+                    = CSLSetNameValue(NULL, "DATAPOINTER", szTmp);
+                GDALAddBand(hMemDS, eDataType, papszMEMDSOptions);
+                CSLDestroy(papszMEMDSOptions);
+            }
+
+            GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
+                                        osTempFileName.c_str(), hMemDS, FALSE,
+                                        papszTileDriverOptions, NULL, NULL);
+
+            GDALClose(hMemDS);
+            if ( !hOutDS )
+            {
+                eErr = CE_Failure;
+                break;
+            }
+            GDALClose(hOutDS);
+
+/* -------------------------------------------------------------------- */
+/*      Insert new entry into raster table                              */
+/* -------------------------------------------------------------------- */
+            vsi_l_offset nDataLength = 0;
+            GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
+                                                   &nDataLength, FALSE);
+
+            OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
+            OGR_F_SetFieldBinary(
+                hFeat, 0, static_cast<int>( nDataLength ), pabyData);
+
+            if( OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE )
+                eErr = CE_Failure;
+            /* Query raster ID to set it as the ID of the associated metadata */
+            int nRasterID = static_cast<int>( OGR_F_GetFID( hFeat ) );
+
+            OGR_F_Destroy(hFeat);
+
+            VSIUnlink(osTempFileName.c_str());
+            if( eErr == CE_Failure )
+                break;
+
+/* -------------------------------------------------------------------- */
+/*      Insert new entry into metadata table                            */
+/* -------------------------------------------------------------------- */
+
+            hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
+            OGR_F_SetFID(hFeat, nRasterID);
+            OGR_F_SetFieldString(hFeat, 0, GDALGetDescription(poSrcDS));
+            OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
+            OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
+            OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
+            OGR_F_SetFieldDouble(hFeat, 4, adfGeoTransform[1]);
+            OGR_F_SetFieldDouble(hFeat, 5, -adfGeoTransform[5]);
+
+            minx = adfGeoTransform[0] +
+                (nBlockXSize * nBlockXOff) * adfGeoTransform[1];
+            maxx = adfGeoTransform[0] +
+                (nBlockXSize * nBlockXOff + nReqXSize) * adfGeoTransform[1];
+            maxy = adfGeoTransform[3] +
+                (nBlockYSize * nBlockYOff) * adfGeoTransform[5];
+            miny = adfGeoTransform[3] +
+                (nBlockYSize * nBlockYOff + nReqYSize) * adfGeoTransform[5];
+
+            OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
+            OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
+            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
+            OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
+            OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
+            OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
+            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
+            OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
+
+            OGR_F_SetGeometryDirectly(hFeat, hRectangle);
+
+            if( OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE )
+                eErr = CE_Failure;
+            OGR_F_Destroy(hFeat);
+
+            nBlocks++;
+            if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
+                                            NULL, pProgressData))
+                eErr = CE_Failure;
+        }
+    }
+
+    if (eErr == CE_None)
+        OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
+    else
+        OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
+
+    CSLDestroy(papszTileDriverOptions);
+
+    VSIFree(pabyMEMDSBuffer);
+
+    OGRReleaseDataSource(hDS);
+
+    if( eErr == CE_Failure )
+        return NULL;
+
+    return reinterpret_cast<GDALDataset *>(
+        GDALOpen( pszFilename, GA_Update ) );
+}
+
+/************************************************************************/
+/*                         RasterliteDelete ()                          */
+/************************************************************************/
+
+CPLErr RasterliteDelete(CPL_UNUSED const char* pszFilename)
+{
+    return CE_None;
+}
diff --git a/frmts/rasterlite/rasterlitedataset.cpp b/frmts/rasterlite/rasterlitedataset.cpp
index f36e25f..5736e4d 100644
--- a/frmts/rasterlite/rasterlitedataset.cpp
+++ b/frmts/rasterlite/rasterlitedataset.cpp
@@ -1,1462 +1,1465 @@
-/******************************************************************************
- * $Id: rasterlitedataset.cpp 33869 2016-04-02 16:53:28Z rouault $
- *
- * Project:  GDAL Rasterlite driver
- * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- **********************************************************************
- * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_string.h"
-#include "gdal_frmts.h"
-#include "ogr_api.h"
-#include "ogr_srs_api.h"
-
-#include "rasterlitedataset.h"
-
-#include <algorithm>
-
-CPL_CVSID("$Id: rasterlitedataset.cpp 33869 2016-04-02 16:53:28Z rouault $");
-
-
-/************************************************************************/
-/*                        RasterliteOpenSQLiteDB()                      */
-/************************************************************************/
-
-OGRDataSourceH RasterliteOpenSQLiteDB(const char* pszFilename,
-                                      GDALAccess eAccess)
-{
-    const char* const apszAllowedDrivers[] = { "SQLITE", NULL };
-    return reinterpret_cast<OGRDataSourceH>(
-        GDALOpenEx( pszFilename,
-                    GDAL_OF_VECTOR |
-                    ((eAccess == GA_Update) ? GDAL_OF_UPDATE : 0),
-                    apszAllowedDrivers, NULL, NULL ));
-}
-
-/************************************************************************/
-/*                       RasterliteGetPixelSizeCond()                   */
-/************************************************************************/
-
-CPLString RasterliteGetPixelSizeCond(double dfPixelXSize,
-                                     double dfPixelYSize,
-                                     const char* pszTablePrefixWithDot)
-{
-    CPLString osCond;
-    osCond.Printf("((%spixel_x_size >= %s AND %spixel_x_size <= %s) AND "
-                   "(%spixel_y_size >= %s AND %spixel_y_size <= %s))",
-                  pszTablePrefixWithDot,
-                  CPLString().FormatC(dfPixelXSize - 1e-15,"%.15f").c_str(),
-                  pszTablePrefixWithDot,
-                  CPLString().FormatC(dfPixelXSize + 1e-15,"%.15f").c_str(),
-                  pszTablePrefixWithDot,
-                  CPLString().FormatC(dfPixelYSize - 1e-15,"%.15f").c_str(),
-                  pszTablePrefixWithDot,
-                  CPLString().FormatC(dfPixelYSize + 1e-15,"%.15f").c_str());
-    return osCond;
-}
-/************************************************************************/
-/*                     RasterliteGetSpatialFilterCond()                 */
-/************************************************************************/
-
-CPLString RasterliteGetSpatialFilterCond(double minx, double miny,
-                                         double maxx, double maxy)
-{
-    CPLString osCond;
-    osCond.Printf("(xmin < %s AND xmax > %s AND ymin < %s AND ymax > %s)",
-                  CPLString().FormatC(maxx,"%.15f").c_str(),
-                  CPLString().FormatC(minx,"%.15f").c_str(),
-                  CPLString().FormatC(maxy,"%.15f").c_str(),
-                  CPLString().FormatC(miny,"%.15f").c_str());
-    return osCond;
-}
-
-/************************************************************************/
-/*                            RasterliteBand()                          */
-/************************************************************************/
-
-RasterliteBand::RasterliteBand(RasterliteDataset* poDSIn, int nBandIn,
-                                GDALDataType eDataTypeIn,
-                                int nBlockXSizeIn, int nBlockYSizeIn)
-{
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->eDataType = eDataTypeIn;
-    this->nBlockXSize = nBlockXSizeIn;
-    this->nBlockYSize = nBlockYSizeIn;
-}
-
-/************************************************************************/
-/*                            IReadBlock()                              */
-/************************************************************************/
-
-//#define RASTERLITE_DEBUG
-
-CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage)
-{
-    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
-
-    double minx = poGDS->adfGeoTransform[0] +
-                  nBlockXOff * nBlockXSize * poGDS->adfGeoTransform[1];
-    double maxx = poGDS->adfGeoTransform[0] +
-                  (nBlockXOff + 1) * nBlockXSize * poGDS->adfGeoTransform[1];
-    double maxy = poGDS->adfGeoTransform[3] +
-                  nBlockYOff * nBlockYSize * poGDS->adfGeoTransform[5];
-    double miny = poGDS->adfGeoTransform[3] +
-                  (nBlockYOff + 1) * nBlockYSize * poGDS->adfGeoTransform[5];
-    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
-
-#ifdef RASTERLITE_DEBUG
-    if (nBand == 1)
-    {
-        printf("nBlockXOff = %d, nBlockYOff = %d, nBlockXSize = %d, nBlockYSize = %d\n"
-               "minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n",
-                nBlockXOff, nBlockYOff, nBlockXSize, nBlockYSize, minx, miny, maxx, maxy);
-    }
-#endif
-
-    CPLString osSQL;
-    osSQL.Printf("SELECT m.geometry, r.raster, m.id, m.width, m.height FROM \"%s_metadata\" AS m, "
-                 "\"%s_rasters\" AS r WHERE m.rowid IN "
-                 "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
-                  "WHERE %s) AND %s AND r.id = m.id",
-                 poGDS->osTableName.c_str(),
-                 poGDS->osTableName.c_str(),
-                 poGDS->osTableName.c_str(),
-                 RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(),
-                 RasterliteGetPixelSizeCond(poGDS->adfGeoTransform[1], -poGDS->adfGeoTransform[5], "m.").c_str());
-
-    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(poGDS->hDS, osSQL.c_str(), NULL, NULL);
-    if (hSQLLyr == NULL)
-    {
-        memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
-        return CE_None;
-    }
-
-    CPLString osMemFileName;
-    osMemFileName.Printf("/vsimem/%p", this);
-
-#ifdef RASTERLITE_DEBUG
-    if (nBand == 1)
-    {
-        printf("nTiles = %d\n", static_cast<int>(
-            OGR_L_GetFeatureCount(hSQLLyr, TRUE) ));
-    }
-#endif
-
-    bool bHasFoundTile = false;
-    bool bHasMemsetTile = false;
-
-    OGRFeatureH hFeat;
-    CPLErr eErr = CE_None;
-    while( (hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL && eErr == CE_None )
-    {
-        OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat);
-        if (hGeom == NULL)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "null geometry found");
-            OGR_F_Destroy(hFeat);
-            OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
-            return CE_Failure;
-        }
-
-        OGREnvelope oEnvelope;
-        OGR_G_GetEnvelope(hGeom, &oEnvelope);
-
-        const int nTileId = OGR_F_GetFieldAsInteger(hFeat, 1);
-        const int nTileXSize = OGR_F_GetFieldAsInteger(hFeat, 2);
-        const int nTileYSize = OGR_F_GetFieldAsInteger(hFeat, 3);
-
-        int nDstXOff = static_cast<int>(
-            ( oEnvelope.MinX - minx ) / poGDS->adfGeoTransform[1] + 0.5 );
-        int nDstYOff = static_cast<int>(
-            ( maxy - oEnvelope.MaxY ) / ( -poGDS->adfGeoTransform[5] ) + 0.5 );
-
-        int nReqXSize = nTileXSize;
-        int nReqYSize = nTileYSize;
-
-        int nSrcXOff, nSrcYOff;
-
-        if (nDstXOff >= 0)
-        {
-            nSrcXOff = 0;
-        }
-        else
-        {
-            nSrcXOff = -nDstXOff;
-            nReqXSize += nDstXOff;
-            nDstXOff = 0;
-        }
-
-        if (nDstYOff >= 0)
-        {
-            nSrcYOff = 0;
-        }
-        else
-        {
-            nSrcYOff = -nDstYOff;
-            nReqYSize += nDstYOff;
-            nDstYOff = 0;
-        }
-
-        if (nDstXOff + nReqXSize > nBlockXSize)
-            nReqXSize = nBlockXSize - nDstXOff;
-
-        if (nDstYOff + nReqYSize > nBlockYSize)
-            nReqYSize = nBlockYSize - nDstYOff;
-
-#ifdef RASTERLITE_DEBUG
-        if (nBand == 1)
-        {
-            printf("id = %d, minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n"
-                   "nDstXOff = %d, nDstYOff = %d, nSrcXOff = %d, nSrcYOff = %d, "
-                   "nReqXSize=%d, nReqYSize=%d\n",
-                   nTileId,
-                   oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY,
-                   nDstXOff, nDstYOff,
-                   nSrcXOff, nSrcYOff, nReqXSize, nReqYSize);
-        }
-#endif
-
-        if (nReqXSize > 0 && nReqYSize > 0 &&
-            nSrcXOff < nTileXSize && nSrcYOff < nTileYSize)
-        {
-
-#ifdef RASTERLITE_DEBUG
-            if (nBand == 1)
-            {
-                printf("id = %d, selected !\n",  nTileId);
-            }
-#endif
-            int nDataSize = 0;
-            GByte* pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize);
-
-            VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
-                                              nDataSize, FALSE);
-            VSIFCloseL(fp);
-
-            GDALDatasetH hDSTile = GDALOpenEx(osMemFileName.c_str(),
-                                              GDAL_OF_RASTER | GDAL_OF_INTERNAL,
-                                              NULL, NULL, NULL);
-            int nTileBands = 0;
-            if (hDSTile && (nTileBands = GDALGetRasterCount(hDSTile)) == 0)
-            {
-                GDALClose(hDSTile);
-                hDSTile = NULL;
-            }
-            if (hDSTile == NULL)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d", 
-                         nTileId);
-            }
-
-            int nReqBand = 1;
-            if (nTileBands == poGDS->nBands)
-                nReqBand = nBand;
-            else if (eDataType == GDT_Byte && nTileBands == 1 && poGDS->nBands == 3)
-                nReqBand = 1;
-            else
-            {
-                GDALClose(hDSTile);
-                hDSTile = NULL;
-            }
-            
-            if( hDSTile )
-            {
-                if( GDALGetRasterXSize(hDSTile) != nTileXSize ||
-                    GDALGetRasterYSize(hDSTile) != nTileYSize )
-                {
-                    CPLError(CE_Failure, CPLE_AppDefined, "Invalid dimensions for tile %d", 
-                             nTileId);
-                    GDALClose(hDSTile);
-                    hDSTile = NULL;
-                }
-            }
-
-            if (hDSTile)
-            {
-                bHasFoundTile = true;
-
-                bool bHasJustMemsetTileBand1 = false;
-
-                /* If the source tile doesn't fit the entire block size, then */
-                /* we memset 0 before */
-                if (!(nDstXOff == 0 && nDstYOff == 0 &&
-                      nReqXSize == nBlockXSize && nReqYSize == nBlockYSize) &&
-                    !bHasMemsetTile)
-                {
-                    memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
-                    bHasMemsetTile = true;
-                    bHasJustMemsetTileBand1 = true;
-                }
-
-                GDALColorTable* poTileCT =
-                    reinterpret_cast<GDALColorTable *>(
-                        GDALGetRasterColorTable(
-                            GDALGetRasterBand( hDSTile, 1 ) ) );
-                unsigned char* pabyTranslationTable = NULL;
-                if (poGDS->nBands == 1 && poGDS->poCT != NULL && poTileCT != NULL)
-                {
-                    pabyTranslationTable =
-                        reinterpret_cast<GDALRasterBand *>(
-                            GDALGetRasterBand( hDSTile, 1 ) )->
-                                GetIndexColorTranslationTo(this, NULL, NULL);
-                }
-
-/* -------------------------------------------------------------------- */
-/*      Read tile data                                                  */
-/* -------------------------------------------------------------------- */
-                eErr = GDALRasterIO(
-                    GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
-                    nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
-                    reinterpret_cast<char*>( pImage )
-                    + (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
-                    nReqXSize, nReqYSize,
-                    eDataType, nDataTypeSize, nBlockXSize * nDataTypeSize);
-
-                if (eDataType == GDT_Byte && pabyTranslationTable)
-                {
-/* -------------------------------------------------------------------- */
-/*      Convert from tile CT to band CT                                 */
-/* -------------------------------------------------------------------- */
-                    for( int j = nDstYOff; j < nDstYOff + nReqYSize; j++ )
-                    {
-                        for( int i = nDstXOff; i < nDstXOff + nReqXSize; i++ )
-                        {
-                            GByte* pPixel = reinterpret_cast<GByte *>( pImage )
-                                + i + j * nBlockXSize;
-                            *pPixel = pabyTranslationTable[*pPixel];
-                        }
-                    }
-                    CPLFree(pabyTranslationTable);
-                    pabyTranslationTable = NULL;
-                }
-                else if (eDataType == GDT_Byte && nTileBands == 1 &&
-                         poGDS->nBands == 3 && poTileCT != NULL)
-                {
-/* -------------------------------------------------------------------- */
-/*      Expand from PCT to RGB                                          */
-/* -------------------------------------------------------------------- */
-                    GByte abyCT[256];
-                    const int nEntries = std::min(256, poTileCT->GetColorEntryCount());
-                    for( int i = 0; i < nEntries; i++ )
-                    {
-                        const GDALColorEntry* psEntry = poTileCT->GetColorEntry(i);
-                        if (nBand == 1)
-                            abyCT[i] = static_cast<GByte>( psEntry->c1 );
-                        else if (nBand == 2)
-                            abyCT[i] = static_cast<GByte>( psEntry->c2 );
-                        else
-                            abyCT[i] = static_cast<GByte>( psEntry->c3 );
-                    }
-                    for( int i = nEntries; i < 256; i++ )
-                        abyCT[i] = 0;
-
-                    for( int j = nDstYOff; j < nDstYOff + nReqYSize; j++ )
-                    {
-                        for( int i = nDstXOff; i < nDstXOff + nReqXSize; i++ )
-                        {
-                            GByte* pPixel = reinterpret_cast<GByte *>( pImage )
-                                + i + j * nBlockXSize;
-                            *pPixel = abyCT[*pPixel];
-                        }
-                    }
-                }
-
-/* -------------------------------------------------------------------- */
-/*      Put in the block cache the data for this block into other bands */
-/*      while the underlying dataset is opened                          */
-/* -------------------------------------------------------------------- */
-                if (nBand == 1 && poGDS->nBands > 1)
-                {
-                    for( int iOtherBand = 2;
-                         iOtherBand<=poGDS->nBands && eErr == CE_None;
-                         iOtherBand++ )
-                    {
-                        GDALRasterBlock *poBlock
-                            = poGDS->GetRasterBand(iOtherBand)->
-                            GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
-                        if (poBlock == NULL)
-                            break;
-
-                        GByte* pabySrcBlock = reinterpret_cast<GByte *>(
-                            poBlock->GetDataRef() );
-                        if( pabySrcBlock == NULL )
-                        {
-                            poBlock->DropLock();
-                            break;
-                        }
-
-                        if (nTileBands == 1)
-                            nReqBand = 1;
-                        else
-                            nReqBand = iOtherBand;
-
-                        if (bHasJustMemsetTileBand1)
-                            memset(pabySrcBlock, 0,
-                                   nBlockXSize * nBlockYSize * nDataTypeSize);
-
-/* -------------------------------------------------------------------- */
-/*      Read tile data                                                  */
-/* -------------------------------------------------------------------- */
-                        eErr = GDALRasterIO(
-                            GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
-                            nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
-                            reinterpret_cast<char *>( pabySrcBlock ) +
-                            (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
-                            nReqXSize, nReqYSize,
-                            eDataType, nDataTypeSize,
-                            nBlockXSize * nDataTypeSize);
-
-                        if (eDataType == GDT_Byte && nTileBands == 1 &&
-                            poGDS->nBands == 3 && poTileCT != NULL)
-                        {
-/* -------------------------------------------------------------------- */
-/*      Expand from PCT to RGB                                          */
-/* -------------------------------------------------------------------- */
-
-                            GByte abyCT[256];
-                            const int nEntries
-                                = std::min(256, poTileCT->GetColorEntryCount());
-                            for( int i=0; i < nEntries; i++ )
-                            {
-                                const GDALColorEntry* psEntry = poTileCT->GetColorEntry(i);
-                                if (iOtherBand == 1)
-                                    abyCT[i] = static_cast<GByte>( psEntry->c1 );
-                                else if (iOtherBand == 2)
-                                    abyCT[i] = static_cast<GByte>( psEntry->c2 );
-                                else
-                                    abyCT[i] = static_cast<GByte>( psEntry->c3 );
-                            }
-                            for( int i = nEntries; i < 256; i++ )
-                                abyCT[i] = 0;
-
-                            for( int j = nDstYOff; j < nDstYOff + nReqYSize; j++ )
-                            {
-                                for( int i = nDstXOff; i < nDstXOff + nReqXSize; i++ )
-                                {
-                                  GByte* pPixel
-                                      = reinterpret_cast<GByte*>( pabySrcBlock )
-                                      + i + j * nBlockXSize;
-                                    *pPixel = abyCT[*pPixel];
-                                }
-                            }
-                        }
-
-                        poBlock->DropLock();
-                    }
-
-                }
-                GDALClose(hDSTile);
-            }
-
-            VSIUnlink(osMemFileName.c_str());
-        }
-        else
-        {
-#ifdef RASTERLITE_DEBUG
-            if (nBand == 1)
-            {
-                printf("id = %d, NOT selected !\n",  nTileId);
-            }
-#endif
-        }
-        OGR_F_Destroy(hFeat);
-    }
-
-    if (!bHasFoundTile)
-    {
-        memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
-    }
-
-    OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
-
-#ifdef RASTERLITE_DEBUG
-    if (nBand == 1)
-        printf("\n");
-#endif
-
-    return eErr;
-}
-
-/************************************************************************/
-/*                         GetOverviewCount()                           */
-/************************************************************************/
-
-int RasterliteBand::GetOverviewCount()
-{
-    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
-
-    if (poGDS->nLimitOvrCount >= 0)
-        return poGDS->nLimitOvrCount;
-    else if (poGDS->nResolutions > 1)
-        return poGDS->nResolutions - 1;
-    else
-        return GDALPamRasterBand::GetOverviewCount();
-}
-
-/************************************************************************/
-/*                              GetOverview()                           */
-/************************************************************************/
-
-GDALRasterBand* RasterliteBand::GetOverview(int nLevel)
-{
-    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
-
-    if (poGDS->nLimitOvrCount >= 0)
-    {
-        if (nLevel < 0 || nLevel >= poGDS->nLimitOvrCount)
-            return NULL;
-    }
-
-    if (poGDS->nResolutions == 1)
-        return GDALPamRasterBand::GetOverview(nLevel);
-
-    if (nLevel < 0 || nLevel >= poGDS->nResolutions - 1)
-        return NULL;
-
-    GDALDataset* poOvrDS = poGDS->papoOverviews[nLevel];
-    if (poOvrDS)
-        return poOvrDS->GetRasterBand(nBand);
-
-    return NULL;
-}
-
-/************************************************************************/
-/*                   GetColorInterpretation()                           */
-/************************************************************************/
-
-GDALColorInterp RasterliteBand::GetColorInterpretation()
-{
-    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
-    if (poGDS->nBands == 1)
-    {
-        if (poGDS->poCT != NULL)
-            return GCI_PaletteIndex;
-
-        return GCI_GrayIndex;
-    }
-    else if (poGDS->nBands == 3)
-    {
-        if (nBand == 1)
-            return GCI_RedBand;
-        else if (nBand == 2)
-            return GCI_GreenBand;
-        else if (nBand == 3)
-            return GCI_BlueBand;
-    }
-
-    return GCI_Undefined;
-}
-
-/************************************************************************/
-/*                        GetColorTable()                               */
-/************************************************************************/
-
-GDALColorTable* RasterliteBand::GetColorTable()
-{
-    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
-    if (poGDS->nBands == 1)
-        return poGDS->poCT;
-
-    return NULL;
-}
-
-/************************************************************************/
-/*                         RasterliteDataset()                          */
-/************************************************************************/
-
-RasterliteDataset::RasterliteDataset() :
-    bMustFree(FALSE),
-    poMainDS(NULL),
-    nLevel(0),
-    papszMetadata(NULL),
-    papszSubDatasets(NULL),
-    nResolutions(0),
-    padfXResolutions(NULL),
-    padfYResolutions(NULL),
-    papoOverviews(NULL),
-    nLimitOvrCount(-1),
-    bValidGeoTransform(FALSE),
-    pszSRS(NULL),
-    poCT(NULL),
-    bCheckForExistingOverview(TRUE),
-    hDS(NULL)
-{
-    papszImageStructure =
-        CSLAddString(NULL, "INTERLEAVE=PIXEL");
-}
-
-/************************************************************************/
-/*                         RasterliteDataset()                          */
-/************************************************************************/
-
-RasterliteDataset::RasterliteDataset(RasterliteDataset* poMainDSIn, int nLevelIn) :
-    bMustFree(FALSE),
-    poMainDS(poMainDSIn),
-    nLevel(nLevelIn),
-    papszMetadata(poMainDSIn->papszMetadata),
-    papszImageStructure(poMainDSIn->papszImageStructure),
-    papszSubDatasets(poMainDS->papszSubDatasets),
-    nResolutions(poMainDSIn->nResolutions - nLevelIn),
-    padfXResolutions(poMainDSIn->padfXResolutions + nLevelIn),
-    padfYResolutions(poMainDSIn->padfYResolutions + nLevelIn),
-    papoOverviews(poMainDSIn->papoOverviews + nLevelIn),
-    nLimitOvrCount(-1),
-    bValidGeoTransform(TRUE),
-    pszSRS(poMainDSIn->pszSRS),
-    poCT(poMainDSIn->poCT),
-    osTableName(poMainDSIn->osTableName),
-    osFileName(poMainDSIn->osFileName),
-    bCheckForExistingOverview(TRUE),
-    // TODO: osOvrFileName?
-    hDS(poMainDSIn->hDS)
-{
-    nRasterXSize = static_cast<int>(poMainDS->nRasterXSize *
-        (poMainDS->padfXResolutions[0] / padfXResolutions[0]) + 0.5);
-    nRasterYSize = static_cast<int>(poMainDS->nRasterYSize *
-        (poMainDS->padfYResolutions[0] / padfYResolutions[0]) + 0.5);
-
-    memcpy(adfGeoTransform, poMainDS->adfGeoTransform, 6 * sizeof(double));
-    adfGeoTransform[1] = padfXResolutions[0];
-    adfGeoTransform[5] = - padfYResolutions[0];
-}
-
-/************************************************************************/
-/*                        ~RasterliteDataset()                          */
-/************************************************************************/
-
-RasterliteDataset::~RasterliteDataset()
-{
-    CloseDependentDatasets();
-}
-
-/************************************************************************/
-/*                      CloseDependentDatasets()                        */
-/************************************************************************/
-
-int RasterliteDataset::CloseDependentDatasets()
-{
-    int bRet = GDALPamDataset::CloseDependentDatasets();
-
-    if (poMainDS == NULL && !bMustFree)
-    {
-        CSLDestroy(papszMetadata);
-        papszMetadata = NULL;
-        CSLDestroy(papszSubDatasets);
-        papszSubDatasets = NULL;
-        CSLDestroy(papszImageStructure);
-        papszImageStructure = NULL;
-        CPLFree(pszSRS);
-        pszSRS = NULL;
-
-        if (papoOverviews)
-        {
-            for( int i = 1; i < nResolutions; i++ )
-            {
-                if (papoOverviews[i-1] != NULL &&
-                    papoOverviews[i-1]->bMustFree)
-                {
-                    papoOverviews[i-1]->poMainDS = NULL;
-                }
-                delete papoOverviews[i-1];
-            }
-            CPLFree(papoOverviews);
-            papoOverviews = NULL;
-            nResolutions = 0;
-            bRet = TRUE;
-        }
-
-        if (hDS != NULL)
-            OGRReleaseDataSource(hDS);
-        hDS = NULL;
-
-        CPLFree(padfXResolutions);
-        CPLFree(padfYResolutions);
-        padfXResolutions = padfYResolutions = NULL;
-
-        delete poCT;
-        poCT = NULL;
-    }
-    else if (poMainDS != NULL && bMustFree)
-    {
-        poMainDS->papoOverviews[nLevel-1] = NULL;
-        delete poMainDS;
-        poMainDS = NULL;
-        bRet = TRUE;
-    }
-
-    return bRet;
-}
-
-/************************************************************************/
-/*                           AddSubDataset()                            */
-/************************************************************************/
-
-void RasterliteDataset::AddSubDataset( const char* pszDSName)
-{
-    char	szName[80];
-    const int nCount = CSLCount(papszSubDatasets ) / 2;
-
-    snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
-    papszSubDatasets = 
-        CSLSetNameValue( papszSubDatasets, szName, pszDSName);
-
-    snprintf( szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount+1 );
-    papszSubDatasets = 
-        CSLSetNameValue( papszSubDatasets, szName, pszDSName);
-}
-
-/************************************************************************/
-/*                      GetMetadataDomainList()                         */
-/************************************************************************/
-
-char **RasterliteDataset::GetMetadataDomainList()
-{
-    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
-                                   TRUE,
-                                   "SUBDATASETS", "IMAGE_STRUCTURE", NULL);
-}
-
-/************************************************************************/
-/*                            GetMetadata()                             */
-/************************************************************************/
-
-char **RasterliteDataset::GetMetadata( const char *pszDomain )
-
-{
-    if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
-        return papszSubDatasets;
-
-    if( CSLCount(papszSubDatasets) < 2 &&
-        pszDomain != NULL && EQUAL(pszDomain,"IMAGE_STRUCTURE") )
-        return papszImageStructure;
-
-    if ( pszDomain == NULL || EQUAL(pszDomain, "") )
-        return papszMetadata;
-
-    return GDALPamDataset::GetMetadata( pszDomain );
-}
-
-/************************************************************************/
-/*                          GetMetadataItem()                           */
-/************************************************************************/
-
-const char *RasterliteDataset::GetMetadataItem( const char *pszName, 
-                                                const char *pszDomain )
-{
-    if (pszDomain != NULL &&EQUAL(pszDomain,"OVERVIEWS") )
-    {
-        if (nResolutions > 1 || CSLCount(papszSubDatasets) > 2)
-            return NULL;
-
-        osOvrFileName.Printf("%s_%s", osFileName.c_str(), osTableName.c_str());
-        if (bCheckForExistingOverview == FALSE ||
-            CPLCheckForFile(const_cast<char *>( osOvrFileName.c_str() ), NULL))
-            return osOvrFileName.c_str();
-
-        return NULL;
-    }
-
-    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
-}
-
-/************************************************************************/
-/*                          GetGeoTransform()                           */
-/************************************************************************/
-
-CPLErr RasterliteDataset::GetGeoTransform( double* padfGeoTransform )
-{
-    if (bValidGeoTransform)
-    {
-        memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
-        return CE_None;
-    }
-
-    return CE_Failure;
-}
-
-/************************************************************************/
-/*                         GetProjectionRef()                           */
-/************************************************************************/
-
-const char* RasterliteDataset::GetProjectionRef()
-{
-    if (pszSRS)
-        return pszSRS;
-
-    return "";
-}
-
-/************************************************************************/
-/*                           GetFileList()                              */
-/************************************************************************/
-
-char** RasterliteDataset::GetFileList()
-{
-    char** papszFileList
-        = CSLAddString(NULL, osFileName);
-    return papszFileList;
-}
-
-/************************************************************************/
-/*                         GetBlockParams()                             */
-/************************************************************************/
-
-int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevelIn,
-                                      int* pnBands, GDALDataType* peDataType,
-                                      int* pnBlockXSize, int* pnBlockYSize)
-{
-    CPLString osSQL;
-    osSQL.Printf("SELECT m.geometry, r.raster, m.id "
-                 "FROM \"%s_metadata\" AS m, \"%s_rasters\" AS r "
-                 "WHERE %s AND r.id = m.id",
-                 osTableName.c_str(), osTableName.c_str(),
-                 RasterliteGetPixelSizeCond(padfXResolutions[nLevelIn],padfYResolutions[nLevelIn], "m.").c_str());
-
-    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    if (hSQLLyr == NULL)
-    {
-        return FALSE;
-    }
-
-    OGRFeatureH hFeat = OGR_L_GetNextFeature(hRasterLyr);
-    if (hFeat == NULL)
-    {
-        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-        return FALSE;
-    }
-
-    int nDataSize;
-    GByte* pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize);
-
-    if (nDataSize > 32 &&
-        STARTS_WITH_CI(reinterpret_cast<const char *>(pabyData),
-                       "StartWaveletsImage$$"))
-    {
-        if (GDALGetDriverByName("EPSILON") == NULL)
-        {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "Rasterlite driver doesn't support WAVELET compressed "
-                     "images if EPSILON driver is not compiled");
-            OGR_F_Destroy(hFeat);
-            OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-            return FALSE;
-        }
-    }
-
-    CPLString osMemFileName;
-    osMemFileName.Printf("/vsimem/%p", this);
-    VSILFILE *fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
-                                         nDataSize, FALSE);
-    VSIFCloseL(fp);
-
-    GDALDatasetH hDSTile = GDALOpen(osMemFileName.c_str(), GA_ReadOnly);
-    if (hDSTile)
-    {
-        *pnBands = GDALGetRasterCount(hDSTile);
-        if (*pnBands == 0)
-        {
-            GDALClose(hDSTile);
-            hDSTile = NULL;
-        }
-    }
-    else
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d", 
-                 OGR_F_GetFieldAsInteger(hFeat, 1));
-    }
-
-    if (hDSTile)
-    {
-        *peDataType = GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1));
-
-        for( int iBand = 2; iBand <= *pnBands; iBand++ )
-        {
-            if (*peDataType != GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1)))
-            {
-                CPLError(CE_Failure, CPLE_NotSupported, "Band types must be identical");
-                GDALClose(hDSTile);
-                hDSTile = NULL;
-                goto end;
-            }
-        }
-
-        *pnBlockXSize = GDALGetRasterXSize(hDSTile);
-        *pnBlockYSize = GDALGetRasterYSize(hDSTile);
-        if (CSLFindName(papszImageStructure, "COMPRESSION") == -1)
-        {
-            const char* pszCompression =
-                GDALGetMetadataItem(hDSTile, "COMPRESSION", "IMAGE_STRUCTURE");
-            if (pszCompression != NULL && EQUAL(pszCompression, "JPEG"))
-                papszImageStructure =
-                    CSLAddString(papszImageStructure, "COMPRESSION=JPEG");
-        }
-
-        if (CSLFindName(papszMetadata, "TILE_FORMAT") == -1)
-        {
-            papszMetadata =
-                CSLSetNameValue(papszMetadata, "TILE_FORMAT",
-                           GDALGetDriverShortName(GDALGetDatasetDriver(hDSTile)));
-        }
-
-        if (*pnBands == 1 && this->poCT == NULL)
-        {
-            GDALColorTable* l_poCT =
-                reinterpret_cast<GDALColorTable *>(
-                    GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1) ) );
-            if (l_poCT)
-                this->poCT = l_poCT->Clone();
-        }
-
-        GDALClose(hDSTile);
-    }
-end:
-    VSIUnlink(osMemFileName.c_str());
-
-    OGR_F_Destroy(hFeat);
-
-    OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-
-    return hDSTile != NULL;
-}
-
-/************************************************************************/
-/*                             Identify()                               */
-/************************************************************************/
-
-int RasterliteDataset::Identify(GDALOpenInfo* poOpenInfo)
-{
-    if (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MBTILES") &&
-        !EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "GPKG") &&
-        poOpenInfo->nHeaderBytes >= 1024 &&
-        STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "SQLite Format 3") &&
-        // Do not match direct Amazon S3 signed URLs that contains .mbtiles in the middle of the URL
-        strstr(poOpenInfo->pszFilename, ".mbtiles") == NULL)
-    {
-        // Could be a SQLite/Spatialite file as well
-        return -1;
-    }
-    else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:"))
-    {
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
-{
-    if( Identify(poOpenInfo) == FALSE )
-        return NULL;
-
-    CPLString osFileName;
-    CPLString osTableName;
-    char **papszTokens = NULL;
-    int nLevel = 0;
-    double minx = 0, miny = 0, maxx = 0, maxy = 0;
-    int bMinXSet = FALSE, bMinYSet = FALSE, bMaxXSet = FALSE, bMaxYSet = FALSE;
-    int nReqBands = 0;
-
-
-/* -------------------------------------------------------------------- */
-/*      Parse "file name"                                               */
-/* -------------------------------------------------------------------- */
-    if (poOpenInfo->nHeaderBytes >= 1024 &&
-        STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "SQLite Format 3"))
-    {
-        osFileName = poOpenInfo->pszFilename;
-    }
-    else
-    {
-        papszTokens = CSLTokenizeStringComplex( 
-                poOpenInfo->pszFilename + 11, ",", FALSE, FALSE );
-        int nTokens = CSLCount(papszTokens);
-        if (nTokens == 0)
-        {
-            CSLDestroy(papszTokens);
-            return NULL;
-        }
-
-        osFileName = papszTokens[0];
-
-        for( int i=1; i < nTokens; i++)
-        {
-            if (STARTS_WITH_CI(papszTokens[i], "table="))
-                osTableName = papszTokens[i] + 6;
-            else if (STARTS_WITH_CI(papszTokens[i], "level="))
-                nLevel = atoi(papszTokens[i] + 6);
-            else if (STARTS_WITH_CI(papszTokens[i], "minx="))
-            {
-                bMinXSet = TRUE;
-                minx = CPLAtof(papszTokens[i] + 5);
-            }
-            else if (STARTS_WITH_CI(papszTokens[i], "miny="))
-            {
-                bMinYSet = TRUE;
-                miny = CPLAtof(papszTokens[i] + 5);
-            }
-            else if (STARTS_WITH_CI(papszTokens[i], "maxx="))
-            {
-                bMaxXSet = TRUE;
-                maxx = CPLAtof(papszTokens[i] + 5);
-            }
-            else if (STARTS_WITH_CI(papszTokens[i], "maxy="))
-            {
-                bMaxYSet = TRUE;
-                maxy = CPLAtof(papszTokens[i] + 5);
-            }
-            else if (STARTS_WITH_CI(papszTokens[i], "bands="))
-            {
-                nReqBands = atoi(papszTokens[i] + 6);
-            }
-            else
-            {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "Invalid option : %s", papszTokens[i]);
-            }
-        }
-    }
-
-    if (OGRGetDriverCount() == 0)
-        OGRRegisterAll();
-
-/* -------------------------------------------------------------------- */
-/*      Open underlying OGR DB                                          */
-/* -------------------------------------------------------------------- */
-
-    OGRDataSourceH hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), poOpenInfo->eAccess);
-    CPLDebug("RASTERLITE", "SQLite DB Open");
-
-    RasterliteDataset* poDS = NULL;
-
-    if (hDS == NULL)
-        goto end;
-
-    if (strlen(osTableName) == 0)
-    {
-        int nCountSubdataset = 0;
-        int nLayers = OGR_DS_GetLayerCount(hDS);
-/* -------------------------------------------------------------------- */
-/*      Add raster layers as subdatasets                                */
-/* -------------------------------------------------------------------- */
-        for( int i=0; i < nLayers; i++ )
-        {
-            OGRLayerH hLyr = OGR_DS_GetLayer(hDS, i);
-            const char* pszLayerName = OGR_FD_GetName(OGR_L_GetLayerDefn(hLyr));
-            if (strstr(pszLayerName, "_metadata"))
-            {
-                char* pszShortName = CPLStrdup(pszLayerName);
-                *strstr(pszShortName, "_metadata") = '\0';
-
-                CPLString osRasterTableName = pszShortName;
-                osRasterTableName += "_rasters";
-
-                if (OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str()) != NULL)
-                {
-                    if (poDS == NULL)
-                    {
-                        poDS = new RasterliteDataset();
-                        osTableName = pszShortName;
-                    }
-
-                    CPLString osSubdatasetName;
-                    if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:"))
-                        osSubdatasetName += "RASTERLITE:";
-                    osSubdatasetName += poOpenInfo->pszFilename;
-                    osSubdatasetName += ",table=";
-                    osSubdatasetName += pszShortName;
-                    poDS->AddSubDataset(osSubdatasetName.c_str());
-
-                    nCountSubdataset++;
-                }
-
-                CPLFree(pszShortName);
-            }
-        }
-
-        if (nCountSubdataset == 0)
-        {
-            goto end;
-        }
-        else if (nCountSubdataset != 1)
-        {
-            poDS->SetDescription( poOpenInfo->pszFilename );
-            goto end;
-        }
-
-/* -------------------------------------------------------------------- */
-/*      If just one subdataset, then open it                            */
-/* -------------------------------------------------------------------- */
-        delete poDS;
-        poDS = NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Build dataset                                                   */
-/* -------------------------------------------------------------------- */
-    {
-        GDALDataType eDataType;
-
-        const CPLString osMetadataTableName = osTableName + "_metadata";
-
-        OGRLayerH hMetadataLyr
-            = OGR_DS_GetLayerByName(hDS, osMetadataTableName.c_str());
-        if (hMetadataLyr == NULL)
-            goto end;
-
-        const CPLString osRasterTableName = osTableName + "_rasters";
-
-        OGRLayerH hRasterLyr
-            = OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
-        if (hRasterLyr == NULL)
-            goto end;
-
-/* -------------------------------------------------------------------- */
-/*      Fetch resolutions                                               */
-/* -------------------------------------------------------------------- */
-        CPLString osSQL;
-        OGRLayerH hSQLLyr;
-        int nResolutions = 0;
-
-        OGRLayerH hRasterPyramidsLyr
-            = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
-        if (hRasterPyramidsLyr)
-        {
-            osSQL.Printf("SELECT pixel_x_size, pixel_y_size "
-                         "FROM raster_pyramids WHERE table_prefix = '%s' "
-                         "ORDER BY pixel_x_size ASC",
-                         osTableName.c_str());
-
-            hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-            if (hSQLLyr != NULL)
-            {
-                nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
-                if( nResolutions == 0 )
-                {
-                    OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-                    hSQLLyr = NULL;
-                }
-            }
-        }
-        else
-            hSQLLyr = NULL;
-
-        if( hSQLLyr == NULL )
-        {
-            osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
-                         "FROM \"%s_metadata\" WHERE pixel_x_size != 0  "
-                         "ORDER BY pixel_x_size ASC",
-                         osTableName.c_str());
-
-            hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-            if (hSQLLyr == NULL)
-                goto end;
-
-            nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
-
-            if (nResolutions == 0)
-            {
-                OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-                goto end;
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Set dataset attributes                                          */
-/* -------------------------------------------------------------------- */
-
-        poDS = new RasterliteDataset();
-        poDS->SetDescription( poOpenInfo->pszFilename );
-        poDS->eAccess = poOpenInfo->eAccess;
-        poDS->osTableName = osTableName;
-        poDS->osFileName = osFileName;
-        poDS->hDS = hDS;
-
-        /* poDS will release it from now */
-        hDS = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Fetch spatial extent or use the one provided by the user        */
-/* -------------------------------------------------------------------- */
-        OGREnvelope oEnvelope;
-        if (bMinXSet && bMinYSet && bMaxXSet && bMaxYSet)
-        {
-            oEnvelope.MinX = minx;
-            oEnvelope.MinY = miny;
-            oEnvelope.MaxX = maxx;
-            oEnvelope.MaxY = maxy;
-        }
-        else
-        {
-            CPLString osOldVal = CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO");
-            CPLSetThreadLocalConfigOption("OGR_SQLITE_EXACT_EXTENT", "YES");
-            OGR_L_GetExtent(hMetadataLyr, &oEnvelope, TRUE);
-            CPLSetThreadLocalConfigOption("OGR_SQLITE_EXACT_EXTENT", osOldVal.c_str());
-            //printf("minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n",
-            //       oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY);
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Store resolutions                                               */
-/* -------------------------------------------------------------------- */
-        poDS->nResolutions = nResolutions;
-        poDS->padfXResolutions = reinterpret_cast<double *>(
-            CPLMalloc( sizeof(double) * poDS->nResolutions ) );
-        poDS->padfYResolutions = reinterpret_cast<double *>(
-            CPLMalloc( sizeof(double) * poDS->nResolutions ) );
-
-        {
-          // Add a scope for i.
-          OGRFeatureH hFeat;
-          int i = 0;
-          while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
-          {
-            poDS->padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
-            poDS->padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
-
-            OGR_F_Destroy(hFeat);
-
-#ifdef RASTERLITE_DEBUG
-            printf("[%d] xres=%.15f yres=%.15f\n", i,
-                   poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
-#endif
-
-            if (poDS->padfXResolutions[i] <= 0 || poDS->padfYResolutions[i] <= 0)
-            {
-                CPLError(CE_Failure, CPLE_NotSupported,
-                         "res=%d, xres=%.15f, yres=%.15f",
-                         i, poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
-                OGR_DS_ReleaseResultSet(poDS->hDS, hSQLLyr);
-                delete poDS;
-                poDS = NULL;
-                goto end;
-            }
-            i++;
-          }
-        }
-
-        OGR_DS_ReleaseResultSet(poDS->hDS, hSQLLyr);
-        hSQLLyr = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Compute raster size, geotransform and projection                */
-/* -------------------------------------------------------------------- */
-        poDS->nRasterXSize = static_cast<int>(
-            (oEnvelope.MaxX - oEnvelope.MinX) / poDS->padfXResolutions[0] + 0.5 );
-        poDS->nRasterYSize = static_cast<int>(
-            (oEnvelope.MaxY - oEnvelope.MinY) / poDS->padfYResolutions[0] + 0.5 );
-
-        poDS->bValidGeoTransform = TRUE;
-        poDS->adfGeoTransform[0] = oEnvelope.MinX;
-        poDS->adfGeoTransform[1] = poDS->padfXResolutions[0];
-        poDS->adfGeoTransform[2] = 0;
-        poDS->adfGeoTransform[3] = oEnvelope.MaxY;
-        poDS->adfGeoTransform[4] = 0;
-        poDS->adfGeoTransform[5] = - poDS->padfYResolutions[0];
-
-        OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef(hMetadataLyr);
-        if (hSRS)
-        {
-            OSRExportToWkt(hSRS, &poDS->pszSRS);
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Get number of bands and block size                              */
-/* -------------------------------------------------------------------- */
-
-        int nBands;
-        int nBlockXSize, nBlockYSize;
-        if (poDS->GetBlockParams(hRasterLyr, 0, &nBands, &eDataType,
-                                 &nBlockXSize, &nBlockYSize) == FALSE)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "Cannot find block characteristics");
-            delete poDS;
-            poDS = NULL;
-            goto end;
-        }
-
-        if (eDataType == GDT_Byte && nBands == 1 && nReqBands == 3)
-            nBands = 3;
-        else if (nReqBands != 0)
-        {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                     "Parameters bands=%d ignored", nReqBands);
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Add bands                                                       */
-/* -------------------------------------------------------------------- */
-
-        for( int iBand=0; iBand < nBands; iBand++ )
-            poDS->SetBand(iBand+1, new RasterliteBand(poDS, iBand+1, eDataType,
-                                                      nBlockXSize, nBlockYSize));
-
-/* -------------------------------------------------------------------- */
-/*      Add overview levels as internal datasets                        */
-/* -------------------------------------------------------------------- */
-        if (nResolutions > 1)
-        {
-            poDS->papoOverviews = reinterpret_cast<RasterliteDataset **>(
-                CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset*)) );
-            for( int nLev = 1; nLev < nResolutions; nLev++ )
-            {
-                int nOvrBands;
-                GDALDataType eOvrDataType;
-                if (poDS->GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType,
-                                         &nBlockXSize, &nBlockYSize) == FALSE)
-                {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Cannot find block characteristics for overview %d", nLev);
-                    delete poDS;
-                    poDS = NULL;
-                    goto end;
-                }
-
-                if (eDataType == GDT_Byte && nOvrBands == 1 && nReqBands == 3)
-                    nOvrBands = 3;
-
-                if (nBands != nOvrBands || eDataType != eOvrDataType)
-                {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Overview %d has not the same number characteristics as main band", nLev);
-                    delete poDS;
-                    poDS = NULL;
-                    goto end;
-                }
-
-                poDS->papoOverviews[nLev-1] = new RasterliteDataset(poDS, nLev);
-
-                for( int iBand = 0; iBand < nBands; iBand++ )
-                {
-                    poDS->papoOverviews[nLev-1]->SetBand(iBand+1,
-                        new RasterliteBand(poDS->papoOverviews[nLev-1], iBand+1, eDataType,
-                                           nBlockXSize, nBlockYSize));
-                }
-            }
-        }
-
-/* -------------------------------------------------------------------- */
-/*      Select an overview if the user has requested so                 */
-/* -------------------------------------------------------------------- */
-        if (nLevel == 0)
-        {
-        }
-        else if (nLevel >= 1 && nLevel <= nResolutions - 1)
-        {
-            poDS->papoOverviews[nLevel-1]->bMustFree = TRUE;
-            poDS = poDS->papoOverviews[nLevel-1];
-        }
-        else
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                      "Invalid requested level : %d. Must be >= 0 and <= %d",
-                      nLevel, nResolutions - 1);
-            delete poDS;
-            poDS = NULL;
-        }
-
-    }
-
-    if (poDS)
-    {
-/* -------------------------------------------------------------------- */
-/*      Setup PAM info for this subdatasets                             */
-/* -------------------------------------------------------------------- */
-        poDS->SetPhysicalFilename( osFileName.c_str() );
-
-        CPLString osSubdatasetName;
-        osSubdatasetName.Printf("RASTERLITE:%s:table=%s",
-                                osFileName.c_str(), osTableName.c_str());
-        poDS->SetSubdatasetName( osSubdatasetName.c_str() );
-        poDS->TryLoadXML();
-        poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
-    }
-
-end:
-    if (hDS)
-        OGRReleaseDataSource(hDS);
-    CSLDestroy(papszTokens);
-
-    return poDS;
-}
-
-/************************************************************************/
-/*                     GDALRegister_Rasterlite()                        */
-/************************************************************************/
-
-void GDALRegister_Rasterlite()
-
-{
-    if( !GDAL_CHECK_VERSION("Rasterlite driver") )
-        return;
-
-    if( GDALGetDriverByName( "Rasterlite" ) != NULL )
-        return;
-
-    GDALDriver *poDriver = new GDALDriver();
-
-    poDriver->SetDescription( "Rasterlite" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Rasterlite" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rasterlite.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sqlite" );
-    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                               "Byte UInt16 Int16 UInt32 Int32 Float32 "
-                               "Float64 CInt16 CInt32 CFloat32 CFloat64" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-"<CreationOptionList>"
-"   <Option name='WIPE' type='boolean' default='NO' description='Erase all preexisting data in the specified table'/>"
-"   <Option name='TILED' type='boolean' default='YES' description='Use tiling'/>"
-"   <Option name='BLOCKXSIZE' type='int' default='256' description='Tile Width'/>"
-"   <Option name='BLOCKYSIZE' type='int' default='256' description='Tile Height'/>"
-"   <Option name='DRIVER' type='string' default='GTiff' description='GDAL driver to use for storing tiles' default='GTiff'/>"
-"   <Option name='COMPRESS' type='string' default='(GTiff driver) Compression method' default='NONE'/>"
-"   <Option name='QUALITY' type='int' description='(JPEG-compressed GTiff, JPEG and WEBP drivers) JPEG/WEBP Quality 1-100' default='75'/>"
-"   <Option name='PHOTOMETRIC' type='string-select' description='(GTiff driver) Photometric interpretation'>"
-"       <Value>MINISBLACK</Value>"
-"       <Value>MINISWHITE</Value>"
-"       <Value>PALETTE</Value>"
-"       <Value>RGB</Value>"
-"       <Value>CMYK</Value>"
-"       <Value>YCBCR</Value>"
-"       <Value>CIELAB</Value>"
-"       <Value>ICCLAB</Value>"
-"       <Value>ITULAB</Value>"
-"   </Option>"
-"   <Option name='TARGET' type='int' description='(EPSILON driver) target size reduction as a percentage of the original (0-100)' default='96'/>"
-"   <Option name='FILTER' type='string' description='(EPSILON driver) Filter ID' default='daub97lift'/>"
-"</CreationOptionList>" );
-
-    poDriver->pfnOpen = RasterliteDataset::Open;
-    poDriver->pfnIdentify = RasterliteDataset::Identify;
-    poDriver->pfnCreateCopy = RasterliteCreateCopy;
-    poDriver->pfnDelete = RasterliteDelete;
-
-    GetGDALDriverManager()->RegisterDriver( poDriver );
-}
+/******************************************************************************
+ *
+ * Project:  GDAL Rasterlite driver
+ * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "gdal_frmts.h"
+#include "ogr_api.h"
+#include "ogr_srs_api.h"
+
+#include "rasterlitedataset.h"
+
+#include <algorithm>
+
+CPL_CVSID("$Id: rasterlitedataset.cpp 37600 2017-03-04 18:11:13Z rouault $");
+
+/************************************************************************/
+/*                        RasterliteOpenSQLiteDB()                      */
+/************************************************************************/
+
+OGRDataSourceH RasterliteOpenSQLiteDB(const char* pszFilename,
+                                      GDALAccess eAccess)
+{
+    const char* const apszAllowedDrivers[] = { "SQLITE", NULL };
+    return reinterpret_cast<OGRDataSourceH>(
+        GDALOpenEx( pszFilename,
+                    GDAL_OF_VECTOR |
+                    ((eAccess == GA_Update) ? GDAL_OF_UPDATE : 0),
+                    apszAllowedDrivers, NULL, NULL ));
+}
+
+/************************************************************************/
+/*                       RasterliteGetPixelSizeCond()                   */
+/************************************************************************/
+
+CPLString RasterliteGetPixelSizeCond(double dfPixelXSize,
+                                     double dfPixelYSize,
+                                     const char* pszTablePrefixWithDot)
+{
+    CPLString osCond;
+    osCond.Printf("((%spixel_x_size >= %s AND %spixel_x_size <= %s) AND "
+                   "(%spixel_y_size >= %s AND %spixel_y_size <= %s))",
+                  pszTablePrefixWithDot,
+                  CPLString().FormatC(dfPixelXSize - 1e-15,"%.15f").c_str(),
+                  pszTablePrefixWithDot,
+                  CPLString().FormatC(dfPixelXSize + 1e-15,"%.15f").c_str(),
+                  pszTablePrefixWithDot,
+                  CPLString().FormatC(dfPixelYSize - 1e-15,"%.15f").c_str(),
+                  pszTablePrefixWithDot,
+                  CPLString().FormatC(dfPixelYSize + 1e-15,"%.15f").c_str());
+    return osCond;
+}
+/************************************************************************/
+/*                     RasterliteGetSpatialFilterCond()                 */
+/************************************************************************/
+
+CPLString RasterliteGetSpatialFilterCond(double minx, double miny,
+                                         double maxx, double maxy)
+{
+    CPLString osCond;
+    osCond.Printf("(xmin < %s AND xmax > %s AND ymin < %s AND ymax > %s)",
+                  CPLString().FormatC(maxx,"%.15f").c_str(),
+                  CPLString().FormatC(minx,"%.15f").c_str(),
+                  CPLString().FormatC(maxy,"%.15f").c_str(),
+                  CPLString().FormatC(miny,"%.15f").c_str());
+    return osCond;
+}
+
+/************************************************************************/
+/*                            RasterliteBand()                          */
+/************************************************************************/
+
+RasterliteBand::RasterliteBand( RasterliteDataset* poDSIn, int nBandIn,
+                                GDALDataType eDataTypeIn,
+                                int nBlockXSizeIn, int nBlockYSizeIn )
+{
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eDataType = eDataTypeIn;
+    nBlockXSize = nBlockXSizeIn;
+    nBlockYSize = nBlockYSizeIn;
+}
+
+/************************************************************************/
+/*                            IReadBlock()                              */
+/************************************************************************/
+
+//#define RASTERLITE_DEBUG
+
+CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage)
+{
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
+
+    double minx = poGDS->adfGeoTransform[0] +
+                  nBlockXOff * nBlockXSize * poGDS->adfGeoTransform[1];
+    double maxx = poGDS->adfGeoTransform[0] +
+                  (nBlockXOff + 1) * nBlockXSize * poGDS->adfGeoTransform[1];
+    double maxy = poGDS->adfGeoTransform[3] +
+                  nBlockYOff * nBlockYSize * poGDS->adfGeoTransform[5];
+    double miny = poGDS->adfGeoTransform[3] +
+                  (nBlockYOff + 1) * nBlockYSize * poGDS->adfGeoTransform[5];
+    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
+
+#ifdef RASTERLITE_DEBUG
+    if (nBand == 1)
+    {
+        printf("nBlockXOff = %d, nBlockYOff = %d, nBlockXSize = %d, nBlockYSize = %d\n" /*ok*/
+               "minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n",
+                nBlockXOff, nBlockYOff, nBlockXSize, nBlockYSize, minx, miny, maxx, maxy);
+    }
+#endif
+
+    CPLString osSQL;
+    osSQL.Printf("SELECT m.geometry, r.raster, m.id, m.width, m.height FROM \"%s_metadata\" AS m, "
+                 "\"%s_rasters\" AS r WHERE m.rowid IN "
+                 "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
+                  "WHERE %s) AND %s AND r.id = m.id",
+                 poGDS->osTableName.c_str(),
+                 poGDS->osTableName.c_str(),
+                 poGDS->osTableName.c_str(),
+                 RasterliteGetSpatialFilterCond(minx, miny, maxx, maxy).c_str(),
+                 RasterliteGetPixelSizeCond(poGDS->adfGeoTransform[1], -poGDS->adfGeoTransform[5], "m.").c_str());
+
+    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(poGDS->hDS, osSQL.c_str(), NULL, NULL);
+    if (hSQLLyr == NULL)
+    {
+        memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
+        return CE_None;
+    }
+
+    CPLString osMemFileName;
+    osMemFileName.Printf("/vsimem/%p", this);
+
+#ifdef RASTERLITE_DEBUG
+    if (nBand == 1)
+    {
+        printf("nTiles = %d\n", static_cast<int>(/*ok*/
+            OGR_L_GetFeatureCount(hSQLLyr, TRUE) ));
+    }
+#endif
+
+    bool bHasFoundTile = false;
+    bool bHasMemsetTile = false;
+
+    OGRFeatureH hFeat;
+    CPLErr eErr = CE_None;
+    while( (hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL && eErr == CE_None )
+    {
+        OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat);
+        if (hGeom == NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "null geometry found");
+            OGR_F_Destroy(hFeat);
+            OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
+            return CE_Failure;
+        }
+
+        OGREnvelope oEnvelope;
+        OGR_G_GetEnvelope(hGeom, &oEnvelope);
+
+        const int nTileId = OGR_F_GetFieldAsInteger(hFeat, 1);
+        const int nTileXSize = OGR_F_GetFieldAsInteger(hFeat, 2);
+        const int nTileYSize = OGR_F_GetFieldAsInteger(hFeat, 3);
+
+        int nDstXOff = static_cast<int>(
+            ( oEnvelope.MinX - minx ) / poGDS->adfGeoTransform[1] + 0.5 );
+        int nDstYOff = static_cast<int>(
+            ( maxy - oEnvelope.MaxY ) / ( -poGDS->adfGeoTransform[5] ) + 0.5 );
+
+        int nReqXSize = nTileXSize;
+        int nReqYSize = nTileYSize;
+
+        int nSrcXOff, nSrcYOff;
+
+        if (nDstXOff >= 0)
+        {
+            nSrcXOff = 0;
+        }
+        else
+        {
+            nSrcXOff = -nDstXOff;
+            nReqXSize += nDstXOff;
+            nDstXOff = 0;
+        }
+
+        if (nDstYOff >= 0)
+        {
+            nSrcYOff = 0;
+        }
+        else
+        {
+            nSrcYOff = -nDstYOff;
+            nReqYSize += nDstYOff;
+            nDstYOff = 0;
+        }
+
+        if (nDstXOff + nReqXSize > nBlockXSize)
+            nReqXSize = nBlockXSize - nDstXOff;
+
+        if (nDstYOff + nReqYSize > nBlockYSize)
+            nReqYSize = nBlockYSize - nDstYOff;
+
+#ifdef RASTERLITE_DEBUG
+        if (nBand == 1)
+        {
+            printf("id = %d, minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n"/*ok*/
+                   "nDstXOff = %d, nDstYOff = %d, nSrcXOff = %d, nSrcYOff = %d, "
+                   "nReqXSize=%d, nReqYSize=%d\n",
+                   nTileId,
+                   oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY,
+                   nDstXOff, nDstYOff,
+                   nSrcXOff, nSrcYOff, nReqXSize, nReqYSize);
+        }
+#endif
+
+        if (nReqXSize > 0 && nReqYSize > 0 &&
+            nSrcXOff < nTileXSize && nSrcYOff < nTileYSize)
+        {
+
+#ifdef RASTERLITE_DEBUG
+            if (nBand == 1)
+            {
+                printf("id = %d, selected !\n",  nTileId);/*ok*/
+            }
+#endif
+            int nDataSize = 0;
+            GByte* pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize);
+
+            VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
+                                              nDataSize, FALSE);
+            VSIFCloseL(fp);
+
+            GDALDatasetH hDSTile = GDALOpenEx(osMemFileName.c_str(),
+                                              GDAL_OF_RASTER | GDAL_OF_INTERNAL,
+                                              NULL, NULL, NULL);
+            int nTileBands = 0;
+            if (hDSTile && (nTileBands = GDALGetRasterCount(hDSTile)) == 0)
+            {
+                GDALClose(hDSTile);
+                hDSTile = NULL;
+            }
+            if (hDSTile == NULL)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d",
+                         nTileId);
+            }
+
+            int nReqBand = 1;
+            if (nTileBands == poGDS->nBands)
+                nReqBand = nBand;
+            else if (eDataType == GDT_Byte && nTileBands == 1 && poGDS->nBands == 3)
+                nReqBand = 1;
+            else
+            {
+                GDALClose(hDSTile);
+                hDSTile = NULL;
+            }
+
+            if( hDSTile )
+            {
+                if( GDALGetRasterXSize(hDSTile) != nTileXSize ||
+                    GDALGetRasterYSize(hDSTile) != nTileYSize )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Invalid dimensions for tile %d",
+                             nTileId);
+                    GDALClose(hDSTile);
+                    hDSTile = NULL;
+                }
+            }
+
+            if (hDSTile)
+            {
+                bHasFoundTile = true;
+
+                bool bHasJustMemsetTileBand1 = false;
+
+                /* If the source tile doesn't fit the entire block size, then */
+                /* we memset 0 before */
+                if (!(nDstXOff == 0 && nDstYOff == 0 &&
+                      nReqXSize == nBlockXSize && nReqYSize == nBlockYSize) &&
+                    !bHasMemsetTile)
+                {
+                    memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
+                    bHasMemsetTile = true;
+                    bHasJustMemsetTileBand1 = true;
+                }
+
+                GDALColorTable* poTileCT =
+                    reinterpret_cast<GDALColorTable *>(
+                        GDALGetRasterColorTable(
+                            GDALGetRasterBand( hDSTile, 1 ) ) );
+                unsigned char* pabyTranslationTable = NULL;
+                if (poGDS->nBands == 1 && poGDS->poCT != NULL && poTileCT != NULL)
+                {
+                    pabyTranslationTable =
+                        reinterpret_cast<GDALRasterBand *>(
+                            GDALGetRasterBand( hDSTile, 1 ) )->
+                                GetIndexColorTranslationTo(this, NULL, NULL);
+                }
+
+/* -------------------------------------------------------------------- */
+/*      Read tile data                                                  */
+/* -------------------------------------------------------------------- */
+                eErr = GDALRasterIO(
+                    GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
+                    nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
+                    reinterpret_cast<char*>( pImage )
+                    + (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
+                    nReqXSize, nReqYSize,
+                    eDataType, nDataTypeSize, nBlockXSize * nDataTypeSize);
+
+                if (eDataType == GDT_Byte && pabyTranslationTable)
+                {
+/* -------------------------------------------------------------------- */
+/*      Convert from tile CT to band CT                                 */
+/* -------------------------------------------------------------------- */
+                    for( int j = nDstYOff; j < nDstYOff + nReqYSize; j++ )
+                    {
+                        for( int i = nDstXOff; i < nDstXOff + nReqXSize; i++ )
+                        {
+                            GByte* pPixel = reinterpret_cast<GByte *>( pImage )
+                                + i + j * nBlockXSize;
+                            *pPixel = pabyTranslationTable[*pPixel];
+                        }
+                    }
+                    CPLFree(pabyTranslationTable);
+                    pabyTranslationTable = NULL;
+                }
+                else if (eDataType == GDT_Byte && nTileBands == 1 &&
+                         poGDS->nBands == 3 && poTileCT != NULL)
+                {
+/* -------------------------------------------------------------------- */
+/*      Expand from PCT to RGB                                          */
+/* -------------------------------------------------------------------- */
+                    GByte abyCT[256];
+                    const int nEntries = std::min(256, poTileCT->GetColorEntryCount());
+                    for( int i = 0; i < nEntries; i++ )
+                    {
+                        const GDALColorEntry* psEntry = poTileCT->GetColorEntry(i);
+                        if (nBand == 1)
+                            abyCT[i] = static_cast<GByte>( psEntry->c1 );
+                        else if (nBand == 2)
+                            abyCT[i] = static_cast<GByte>( psEntry->c2 );
+                        else
+                            abyCT[i] = static_cast<GByte>( psEntry->c3 );
+                    }
+                    for( int i = nEntries; i < 256; i++ )
+                        abyCT[i] = 0;
+
+                    for( int j = nDstYOff; j < nDstYOff + nReqYSize; j++ )
+                    {
+                        for( int i = nDstXOff; i < nDstXOff + nReqXSize; i++ )
+                        {
+                            GByte* pPixel = reinterpret_cast<GByte *>( pImage )
+                                + i + j * nBlockXSize;
+                            *pPixel = abyCT[*pPixel];
+                        }
+                    }
+                }
+
+/* -------------------------------------------------------------------- */
+/*      Put in the block cache the data for this block into other bands */
+/*      while the underlying dataset is opened                          */
+/* -------------------------------------------------------------------- */
+                if (nBand == 1 && poGDS->nBands > 1)
+                {
+                    for( int iOtherBand = 2;
+                         iOtherBand<=poGDS->nBands && eErr == CE_None;
+                         iOtherBand++ )
+                    {
+                        GDALRasterBlock *poBlock
+                            = poGDS->GetRasterBand(iOtherBand)->
+                            GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
+                        if (poBlock == NULL)
+                            break;
+
+                        GByte* pabySrcBlock = reinterpret_cast<GByte *>(
+                            poBlock->GetDataRef() );
+                        if( pabySrcBlock == NULL )
+                        {
+                            poBlock->DropLock();
+                            break;
+                        }
+
+                        if (nTileBands == 1)
+                            nReqBand = 1;
+                        else
+                            nReqBand = iOtherBand;
+
+                        if (bHasJustMemsetTileBand1)
+                            memset(pabySrcBlock, 0,
+                                   nBlockXSize * nBlockYSize * nDataTypeSize);
+
+/* -------------------------------------------------------------------- */
+/*      Read tile data                                                  */
+/* -------------------------------------------------------------------- */
+                        eErr = GDALRasterIO(
+                            GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
+                            nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
+                            reinterpret_cast<char *>( pabySrcBlock ) +
+                            (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
+                            nReqXSize, nReqYSize,
+                            eDataType, nDataTypeSize,
+                            nBlockXSize * nDataTypeSize);
+
+                        if (eDataType == GDT_Byte && nTileBands == 1 &&
+                            poGDS->nBands == 3 && poTileCT != NULL)
+                        {
+/* -------------------------------------------------------------------- */
+/*      Expand from PCT to RGB                                          */
+/* -------------------------------------------------------------------- */
+
+                            GByte abyCT[256];
+                            const int nEntries
+                                = std::min(256, poTileCT->GetColorEntryCount());
+                            for( int i=0; i < nEntries; i++ )
+                            {
+                                const GDALColorEntry* psEntry = poTileCT->GetColorEntry(i);
+                                if (iOtherBand == 1)
+                                    abyCT[i] = static_cast<GByte>( psEntry->c1 );
+                                else if (iOtherBand == 2)
+                                    abyCT[i] = static_cast<GByte>( psEntry->c2 );
+                                else
+                                    abyCT[i] = static_cast<GByte>( psEntry->c3 );
+                            }
+                            for( int i = nEntries; i < 256; i++ )
+                                abyCT[i] = 0;
+
+                            for( int j = nDstYOff; j < nDstYOff + nReqYSize; j++ )
+                            {
+                                for( int i = nDstXOff; i < nDstXOff + nReqXSize; i++ )
+                                {
+                                  GByte* pPixel
+                                      = reinterpret_cast<GByte*>( pabySrcBlock )
+                                      + i + j * nBlockXSize;
+                                    *pPixel = abyCT[*pPixel];
+                                }
+                            }
+                        }
+
+                        poBlock->DropLock();
+                    }
+                }
+                GDALClose(hDSTile);
+            }
+
+            VSIUnlink(osMemFileName.c_str());
+        }
+        else
+        {
+#ifdef RASTERLITE_DEBUG
+            if (nBand == 1)
+            {
+                printf("id = %d, NOT selected !\n",  nTileId);/*ok*/
+            }
+#endif
+        }
+        OGR_F_Destroy(hFeat);
+    }
+
+    if (!bHasFoundTile)
+    {
+        memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
+    }
+
+    OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
+
+#ifdef RASTERLITE_DEBUG
+    if (nBand == 1)
+        printf("\n");/*ok*/
+#endif
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                         GetOverviewCount()                           */
+/************************************************************************/
+
+int RasterliteBand::GetOverviewCount()
+{
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
+
+    if (poGDS->nLimitOvrCount >= 0)
+        return poGDS->nLimitOvrCount;
+    else if (poGDS->nResolutions > 1)
+        return poGDS->nResolutions - 1;
+    else
+        return GDALPamRasterBand::GetOverviewCount();
+}
+
+/************************************************************************/
+/*                              GetOverview()                           */
+/************************************************************************/
+
+GDALRasterBand* RasterliteBand::GetOverview(int nLevel)
+{
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
+
+    if (poGDS->nLimitOvrCount >= 0)
+    {
+        if (nLevel < 0 || nLevel >= poGDS->nLimitOvrCount)
+            return NULL;
+    }
+
+    if (poGDS->nResolutions == 1)
+        return GDALPamRasterBand::GetOverview(nLevel);
+
+    if (nLevel < 0 || nLevel >= poGDS->nResolutions - 1)
+        return NULL;
+
+    GDALDataset* poOvrDS = poGDS->papoOverviews[nLevel];
+    if (poOvrDS)
+        return poOvrDS->GetRasterBand(nBand);
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                   GetColorInterpretation()                           */
+/************************************************************************/
+
+GDALColorInterp RasterliteBand::GetColorInterpretation()
+{
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
+    if (poGDS->nBands == 1)
+    {
+        if (poGDS->poCT != NULL)
+            return GCI_PaletteIndex;
+
+        return GCI_GrayIndex;
+    }
+    else if (poGDS->nBands == 3)
+    {
+        if (nBand == 1)
+            return GCI_RedBand;
+        else if (nBand == 2)
+            return GCI_GreenBand;
+        else if (nBand == 3)
+            return GCI_BlueBand;
+    }
+
+    return GCI_Undefined;
+}
+
+/************************************************************************/
+/*                        GetColorTable()                               */
+/************************************************************************/
+
+GDALColorTable* RasterliteBand::GetColorTable()
+{
+    RasterliteDataset* poGDS = reinterpret_cast<RasterliteDataset *>( poDS );
+    if (poGDS->nBands == 1)
+        return poGDS->poCT;
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                         RasterliteDataset()                          */
+/************************************************************************/
+
+RasterliteDataset::RasterliteDataset() :
+    bMustFree(FALSE),
+    poMainDS(NULL),
+    nLevel(0),
+    papszMetadata(NULL),
+    papszImageStructure(CSLAddString(NULL, "INTERLEAVE=PIXEL")),
+    papszSubDatasets(NULL),
+    nResolutions(0),
+    padfXResolutions(NULL),
+    padfYResolutions(NULL),
+    papoOverviews(NULL),
+    nLimitOvrCount(-1),
+    bValidGeoTransform(FALSE),
+    pszSRS(NULL),
+    poCT(NULL),
+    bCheckForExistingOverview(TRUE),
+    hDS(NULL)
+{
+    memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
+}
+
+/************************************************************************/
+/*                         RasterliteDataset()                          */
+/************************************************************************/
+
+RasterliteDataset::RasterliteDataset( RasterliteDataset* poMainDSIn,
+                                      int nLevelIn ) :
+    bMustFree(FALSE),
+    poMainDS(poMainDSIn),
+    nLevel(nLevelIn),
+    papszMetadata(poMainDSIn->papszMetadata),
+    papszImageStructure(poMainDSIn->papszImageStructure),
+    papszSubDatasets(poMainDS->papszSubDatasets),
+    nResolutions(poMainDSIn->nResolutions - nLevelIn),
+    padfXResolutions(poMainDSIn->padfXResolutions + nLevelIn),
+    padfYResolutions(poMainDSIn->padfYResolutions + nLevelIn),
+    papoOverviews(poMainDSIn->papoOverviews + nLevelIn),
+    nLimitOvrCount(-1),
+    bValidGeoTransform(TRUE),
+    pszSRS(poMainDSIn->pszSRS),
+    poCT(poMainDSIn->poCT),
+    osTableName(poMainDSIn->osTableName),
+    osFileName(poMainDSIn->osFileName),
+    bCheckForExistingOverview(TRUE),
+    // TODO: osOvrFileName?
+    hDS(poMainDSIn->hDS)
+{
+    nRasterXSize = static_cast<int>(poMainDS->nRasterXSize *
+        (poMainDS->padfXResolutions[0] / padfXResolutions[0]) + 0.5);
+    nRasterYSize = static_cast<int>(poMainDS->nRasterYSize *
+        (poMainDS->padfYResolutions[0] / padfYResolutions[0]) + 0.5);
+
+    memcpy(adfGeoTransform, poMainDS->adfGeoTransform, 6 * sizeof(double));
+    adfGeoTransform[1] = padfXResolutions[0];
+    adfGeoTransform[5] = - padfYResolutions[0];
+}
+
+/************************************************************************/
+/*                        ~RasterliteDataset()                          */
+/************************************************************************/
+
+RasterliteDataset::~RasterliteDataset()
+{
+    CloseDependentDatasets();
+}
+
+/************************************************************************/
+/*                      CloseDependentDatasets()                        */
+/************************************************************************/
+
+int RasterliteDataset::CloseDependentDatasets()
+{
+    int bRet = GDALPamDataset::CloseDependentDatasets();
+
+    if (poMainDS == NULL && !bMustFree)
+    {
+        CSLDestroy(papszMetadata);
+        papszMetadata = NULL;
+        CSLDestroy(papszSubDatasets);
+        papszSubDatasets = NULL;
+        CSLDestroy(papszImageStructure);
+        papszImageStructure = NULL;
+        CPLFree(pszSRS);
+        pszSRS = NULL;
+
+        if (papoOverviews)
+        {
+            for( int i = 1; i < nResolutions; i++ )
+            {
+                if (papoOverviews[i-1] != NULL &&
+                    papoOverviews[i-1]->bMustFree)
+                {
+                    papoOverviews[i-1]->poMainDS = NULL;
+                }
+                delete papoOverviews[i-1];
+            }
+            CPLFree(papoOverviews);
+            papoOverviews = NULL;
+            nResolutions = 0;
+            bRet = TRUE;
+        }
+
+        if (hDS != NULL)
+            OGRReleaseDataSource(hDS);
+        hDS = NULL;
+
+        CPLFree(padfXResolutions);
+        CPLFree(padfYResolutions);
+        padfXResolutions = NULL;
+        padfYResolutions = NULL;
+
+        delete poCT;
+        poCT = NULL;
+    }
+    else if (poMainDS != NULL && bMustFree)
+    {
+        poMainDS->papoOverviews[nLevel-1] = NULL;
+        delete poMainDS;
+        poMainDS = NULL;
+        bRet = TRUE;
+    }
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                           AddSubDataset()                            */
+/************************************************************************/
+
+void RasterliteDataset::AddSubDataset( const char* pszDSName)
+{
+    char szName[80];
+    const int nCount = CSLCount(papszSubDatasets ) / 2;
+
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_NAME", nCount+1 );
+    papszSubDatasets =
+        CSLSetNameValue( papszSubDatasets, szName, pszDSName);
+
+    snprintf( szName, sizeof(szName), "SUBDATASET_%d_DESC", nCount+1 );
+    papszSubDatasets =
+        CSLSetNameValue( papszSubDatasets, szName, pszDSName);
+}
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **RasterliteDataset::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "SUBDATASETS", "IMAGE_STRUCTURE", NULL);
+}
+
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char **RasterliteDataset::GetMetadata( const char *pszDomain )
+
+{
+    if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
+        return papszSubDatasets;
+
+    if( CSLCount(papszSubDatasets) < 2 &&
+        pszDomain != NULL && EQUAL(pszDomain,"IMAGE_STRUCTURE") )
+        return papszImageStructure;
+
+    if ( pszDomain == NULL || EQUAL(pszDomain, "") )
+        return papszMetadata;
+
+    return GDALPamDataset::GetMetadata( pszDomain );
+}
+
+/************************************************************************/
+/*                          GetMetadataItem()                           */
+/************************************************************************/
+
+const char *RasterliteDataset::GetMetadataItem( const char *pszName,
+                                                const char *pszDomain )
+{
+    if (pszDomain != NULL &&EQUAL(pszDomain,"OVERVIEWS") )
+    {
+        if (nResolutions > 1 || CSLCount(papszSubDatasets) > 2)
+            return NULL;
+
+        osOvrFileName.Printf("%s_%s", osFileName.c_str(), osTableName.c_str());
+        if (bCheckForExistingOverview == FALSE ||
+            CPLCheckForFile(const_cast<char *>( osOvrFileName.c_str() ), NULL))
+            return osOvrFileName.c_str();
+
+        return NULL;
+    }
+
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr RasterliteDataset::GetGeoTransform( double* padfGeoTransform )
+{
+    if (bValidGeoTransform)
+    {
+        memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
+        return CE_None;
+    }
+
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                         GetProjectionRef()                           */
+/************************************************************************/
+
+const char* RasterliteDataset::GetProjectionRef()
+{
+    if (pszSRS)
+        return pszSRS;
+
+    return "";
+}
+
+/************************************************************************/
+/*                           GetFileList()                              */
+/************************************************************************/
+
+char** RasterliteDataset::GetFileList()
+{
+    char** papszFileList
+        = CSLAddString(NULL, osFileName);
+    return papszFileList;
+}
+
+/************************************************************************/
+/*                         GetBlockParams()                             */
+/************************************************************************/
+
+int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevelIn,
+                                      int* pnBands, GDALDataType* peDataType,
+                                      int* pnBlockXSize, int* pnBlockYSize)
+{
+    CPLString osSQL;
+    osSQL.Printf("SELECT m.geometry, r.raster, m.id "
+                 "FROM \"%s_metadata\" AS m, \"%s_rasters\" AS r "
+                 "WHERE %s AND r.id = m.id",
+                 osTableName.c_str(), osTableName.c_str(),
+                 RasterliteGetPixelSizeCond(padfXResolutions[nLevelIn],padfYResolutions[nLevelIn], "m.").c_str());
+
+    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+    if (hSQLLyr == NULL)
+    {
+        return FALSE;
+    }
+
+    OGRFeatureH hFeat = OGR_L_GetNextFeature(hRasterLyr);
+    if (hFeat == NULL)
+    {
+        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+        return FALSE;
+    }
+
+    int nDataSize;
+    GByte* pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize);
+
+    if (nDataSize > 32 &&
+        STARTS_WITH_CI(reinterpret_cast<const char *>(pabyData),
+                       "StartWaveletsImage$$"))
+    {
+        if (GDALGetDriverByName("EPSILON") == NULL)
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Rasterlite driver doesn't support WAVELET compressed "
+                     "images if EPSILON driver is not compiled");
+            OGR_F_Destroy(hFeat);
+            OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+            return FALSE;
+        }
+    }
+
+    CPLString osMemFileName;
+    osMemFileName.Printf("/vsimem/%p", this);
+    VSILFILE *fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
+                                         nDataSize, FALSE);
+    VSIFCloseL(fp);
+
+    GDALDatasetH hDSTile = GDALOpen(osMemFileName.c_str(), GA_ReadOnly);
+    if (hDSTile)
+    {
+        *pnBands = GDALGetRasterCount(hDSTile);
+        if (*pnBands == 0)
+        {
+            GDALClose(hDSTile);
+            hDSTile = NULL;
+        }
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d",
+                 OGR_F_GetFieldAsInteger(hFeat, 1));
+    }
+
+    if (hDSTile)
+    {
+        *peDataType = GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1));
+
+        for( int iBand = 2; iBand <= *pnBands; iBand++ )
+        {
+            if (*peDataType != GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1)))
+            {
+                CPLError(CE_Failure, CPLE_NotSupported, "Band types must be identical");
+                GDALClose(hDSTile);
+                hDSTile = NULL;
+                goto end;
+            }
+        }
+
+        *pnBlockXSize = GDALGetRasterXSize(hDSTile);
+        *pnBlockYSize = GDALGetRasterYSize(hDSTile);
+        if (CSLFindName(papszImageStructure, "COMPRESSION") == -1)
+        {
+            const char* pszCompression =
+                GDALGetMetadataItem(hDSTile, "COMPRESSION", "IMAGE_STRUCTURE");
+            if (pszCompression != NULL && EQUAL(pszCompression, "JPEG"))
+                papszImageStructure =
+                    CSLAddString(papszImageStructure, "COMPRESSION=JPEG");
+        }
+
+        if (CSLFindName(papszMetadata, "TILE_FORMAT") == -1)
+        {
+            papszMetadata =
+                CSLSetNameValue(papszMetadata, "TILE_FORMAT",
+                           GDALGetDriverShortName(GDALGetDatasetDriver(hDSTile)));
+        }
+
+        if (*pnBands == 1 && this->poCT == NULL)
+        {
+            GDALColorTable* l_poCT =
+                reinterpret_cast<GDALColorTable *>(
+                    GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1) ) );
+            if (l_poCT)
+                this->poCT = l_poCT->Clone();
+        }
+
+        GDALClose(hDSTile);
+    }
+end:
+    VSIUnlink(osMemFileName.c_str());
+
+    OGR_F_Destroy(hFeat);
+
+    OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+
+    return hDSTile != NULL;
+}
+
+/************************************************************************/
+/*                             Identify()                               */
+/************************************************************************/
+
+int RasterliteDataset::Identify(GDALOpenInfo* poOpenInfo)
+{
+    if (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MBTILES") &&
+        !EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "GPKG") &&
+        poOpenInfo->nHeaderBytes >= 1024 &&
+        STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "SQLite Format 3") &&
+        // Do not match direct Amazon S3 signed URLs that contains .mbtiles in the middle of the URL
+        strstr(poOpenInfo->pszFilename, ".mbtiles") == NULL)
+    {
+        // Could be a SQLite/Spatialite file as well
+        return -1;
+    }
+    else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:"))
+    {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
+{
+    if( Identify(poOpenInfo) == FALSE )
+        return NULL;
+
+    CPLString osFileName;
+    CPLString osTableName;
+    char **papszTokens = NULL;
+    int nLevel = 0;
+    double minx = 0.0;
+    double miny = 0.0;
+    double maxx = 0.0;
+    double maxy = 0.0;
+    int bMinXSet = FALSE;
+    int bMinYSet = FALSE;
+    int bMaxXSet = FALSE;
+    int bMaxYSet = FALSE;
+    int nReqBands = 0;
+
+/* -------------------------------------------------------------------- */
+/*      Parse "file name"                                               */
+/* -------------------------------------------------------------------- */
+    if (poOpenInfo->nHeaderBytes >= 1024 &&
+        STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "SQLite Format 3"))
+    {
+        osFileName = poOpenInfo->pszFilename;
+    }
+    else
+    {
+        papszTokens = CSLTokenizeStringComplex(
+                poOpenInfo->pszFilename + 11, ",", FALSE, FALSE );
+        int nTokens = CSLCount(papszTokens);
+        if (nTokens == 0)
+        {
+            CSLDestroy(papszTokens);
+            return NULL;
+        }
+
+        osFileName = papszTokens[0];
+
+        for( int i=1; i < nTokens; i++)
+        {
+            if (STARTS_WITH_CI(papszTokens[i], "table="))
+                osTableName = papszTokens[i] + 6;
+            else if (STARTS_WITH_CI(papszTokens[i], "level="))
+                nLevel = atoi(papszTokens[i] + 6);
+            else if (STARTS_WITH_CI(papszTokens[i], "minx="))
+            {
+                bMinXSet = TRUE;
+                minx = CPLAtof(papszTokens[i] + 5);
+            }
+            else if (STARTS_WITH_CI(papszTokens[i], "miny="))
+            {
+                bMinYSet = TRUE;
+                miny = CPLAtof(papszTokens[i] + 5);
+            }
+            else if (STARTS_WITH_CI(papszTokens[i], "maxx="))
+            {
+                bMaxXSet = TRUE;
+                maxx = CPLAtof(papszTokens[i] + 5);
+            }
+            else if (STARTS_WITH_CI(papszTokens[i], "maxy="))
+            {
+                bMaxYSet = TRUE;
+                maxy = CPLAtof(papszTokens[i] + 5);
+            }
+            else if (STARTS_WITH_CI(papszTokens[i], "bands="))
+            {
+                nReqBands = atoi(papszTokens[i] + 6);
+            }
+            else
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Invalid option : %s", papszTokens[i]);
+            }
+        }
+    }
+
+    if (OGRGetDriverCount() == 0)
+        OGRRegisterAll();
+
+/* -------------------------------------------------------------------- */
+/*      Open underlying OGR DB                                          */
+/* -------------------------------------------------------------------- */
+
+    OGRDataSourceH hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), poOpenInfo->eAccess);
+    CPLDebug("RASTERLITE", "SQLite DB Open");
+
+    RasterliteDataset* poDS = NULL;
+
+    if (hDS == NULL)
+        goto end;
+
+    if (osTableName.empty())
+    {
+        int nCountSubdataset = 0;
+        int nLayers = OGR_DS_GetLayerCount(hDS);
+/* -------------------------------------------------------------------- */
+/*      Add raster layers as subdatasets                                */
+/* -------------------------------------------------------------------- */
+        for( int i=0; i < nLayers; i++ )
+        {
+            OGRLayerH hLyr = OGR_DS_GetLayer(hDS, i);
+            const char* pszLayerName = OGR_L_GetName(hLyr);
+            if (strstr(pszLayerName, "_metadata"))
+            {
+                char* pszShortName = CPLStrdup(pszLayerName);
+                *strstr(pszShortName, "_metadata") = '\0';
+
+                CPLString osRasterTableName = pszShortName;
+                osRasterTableName += "_rasters";
+
+                if (OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str()) != NULL)
+                {
+                    if (poDS == NULL)
+                    {
+                        poDS = new RasterliteDataset();
+                        osTableName = pszShortName;
+                    }
+
+                    CPLString osSubdatasetName;
+                    if (!STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE:"))
+                        osSubdatasetName += "RASTERLITE:";
+                    osSubdatasetName += poOpenInfo->pszFilename;
+                    osSubdatasetName += ",table=";
+                    osSubdatasetName += pszShortName;
+                    poDS->AddSubDataset(osSubdatasetName.c_str());
+
+                    nCountSubdataset++;
+                }
+
+                CPLFree(pszShortName);
+            }
+        }
+
+        if (nCountSubdataset == 0)
+        {
+            goto end;
+        }
+        else if (nCountSubdataset != 1)
+        {
+            poDS->SetDescription( poOpenInfo->pszFilename );
+            goto end;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If just one subdataset, then open it                            */
+/* -------------------------------------------------------------------- */
+        delete poDS;
+        poDS = NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Build dataset                                                   */
+/* -------------------------------------------------------------------- */
+    {
+        GDALDataType eDataType;
+
+        const CPLString osMetadataTableName = osTableName + "_metadata";
+
+        OGRLayerH hMetadataLyr
+            = OGR_DS_GetLayerByName(hDS, osMetadataTableName.c_str());
+        if (hMetadataLyr == NULL)
+            goto end;
+
+        const CPLString osRasterTableName = osTableName + "_rasters";
+
+        OGRLayerH hRasterLyr
+            = OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
+        if (hRasterLyr == NULL)
+            goto end;
+
+/* -------------------------------------------------------------------- */
+/*      Fetch resolutions                                               */
+/* -------------------------------------------------------------------- */
+        CPLString osSQL;
+        OGRLayerH hSQLLyr;
+        int nResolutions = 0;
+
+        OGRLayerH hRasterPyramidsLyr
+            = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
+        if (hRasterPyramidsLyr)
+        {
+            osSQL.Printf("SELECT pixel_x_size, pixel_y_size "
+                         "FROM raster_pyramids WHERE table_prefix = '%s' "
+                         "ORDER BY pixel_x_size ASC",
+                         osTableName.c_str());
+
+            hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+            if (hSQLLyr != NULL)
+            {
+                nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
+                if( nResolutions == 0 )
+                {
+                    OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+                    hSQLLyr = NULL;
+                }
+            }
+        }
+        else
+            hSQLLyr = NULL;
+
+        if( hSQLLyr == NULL )
+        {
+            osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
+                         "FROM \"%s_metadata\" WHERE pixel_x_size != 0  "
+                         "ORDER BY pixel_x_size ASC",
+                         osTableName.c_str());
+
+            hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+            if (hSQLLyr == NULL)
+                goto end;
+
+            nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
+
+            if (nResolutions == 0)
+            {
+                OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+                goto end;
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Set dataset attributes                                          */
+/* -------------------------------------------------------------------- */
+
+        poDS = new RasterliteDataset();
+        poDS->SetDescription( poOpenInfo->pszFilename );
+        poDS->eAccess = poOpenInfo->eAccess;
+        poDS->osTableName = osTableName;
+        poDS->osFileName = osFileName;
+        poDS->hDS = hDS;
+
+        /* poDS will release it from now */
+        hDS = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Fetch spatial extent or use the one provided by the user        */
+/* -------------------------------------------------------------------- */
+        OGREnvelope oEnvelope;
+        if (bMinXSet && bMinYSet && bMaxXSet && bMaxYSet)
+        {
+            oEnvelope.MinX = minx;
+            oEnvelope.MinY = miny;
+            oEnvelope.MaxX = maxx;
+            oEnvelope.MaxY = maxy;
+        }
+        else
+        {
+            CPLString osOldVal = CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO");
+            CPLSetThreadLocalConfigOption("OGR_SQLITE_EXACT_EXTENT", "YES");
+            OGR_L_GetExtent(hMetadataLyr, &oEnvelope, TRUE);
+            CPLSetThreadLocalConfigOption("OGR_SQLITE_EXACT_EXTENT", osOldVal.c_str());
+            //printf("minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n",
+            //       oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY);
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Store resolutions                                               */
+/* -------------------------------------------------------------------- */
+        poDS->nResolutions = nResolutions;
+        poDS->padfXResolutions = reinterpret_cast<double *>(
+            CPLMalloc( sizeof(double) * poDS->nResolutions ) );
+        poDS->padfYResolutions = reinterpret_cast<double *>(
+            CPLMalloc( sizeof(double) * poDS->nResolutions ) );
+
+        {
+          // Add a scope for i.
+          OGRFeatureH hFeat;
+          int i = 0;
+          while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
+          {
+            poDS->padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
+            poDS->padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
+
+            OGR_F_Destroy(hFeat);
+
+#ifdef RASTERLITE_DEBUG
+            printf("[%d] xres=%.15f yres=%.15f\n", i,/*ok*/
+                   poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
+#endif
+
+            if (poDS->padfXResolutions[i] <= 0 || poDS->padfYResolutions[i] <= 0)
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "res=%d, xres=%.15f, yres=%.15f",
+                         i, poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
+                OGR_DS_ReleaseResultSet(poDS->hDS, hSQLLyr);
+                delete poDS;
+                poDS = NULL;
+                goto end;
+            }
+            i++;
+          }
+        }
+
+        OGR_DS_ReleaseResultSet(poDS->hDS, hSQLLyr);
+        hSQLLyr = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Compute raster size, geotransform and projection                */
+/* -------------------------------------------------------------------- */
+        poDS->nRasterXSize = static_cast<int>(
+            (oEnvelope.MaxX - oEnvelope.MinX) / poDS->padfXResolutions[0] + 0.5 );
+        poDS->nRasterYSize = static_cast<int>(
+            (oEnvelope.MaxY - oEnvelope.MinY) / poDS->padfYResolutions[0] + 0.5 );
+
+        poDS->bValidGeoTransform = TRUE;
+        poDS->adfGeoTransform[0] = oEnvelope.MinX;
+        poDS->adfGeoTransform[1] = poDS->padfXResolutions[0];
+        poDS->adfGeoTransform[2] = 0;
+        poDS->adfGeoTransform[3] = oEnvelope.MaxY;
+        poDS->adfGeoTransform[4] = 0;
+        poDS->adfGeoTransform[5] = - poDS->padfYResolutions[0];
+
+        OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef(hMetadataLyr);
+        if (hSRS)
+        {
+            OSRExportToWkt(hSRS, &poDS->pszSRS);
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Get number of bands and block size                              */
+/* -------------------------------------------------------------------- */
+
+        int nBands;
+        int nBlockXSize, nBlockYSize;
+        if (poDS->GetBlockParams(hRasterLyr, 0, &nBands, &eDataType,
+                                 &nBlockXSize, &nBlockYSize) == FALSE)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot find block characteristics");
+            delete poDS;
+            poDS = NULL;
+            goto end;
+        }
+
+        if (eDataType == GDT_Byte && nBands == 1 && nReqBands == 3)
+            nBands = 3;
+        else if (nReqBands != 0)
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "Parameters bands=%d ignored", nReqBands);
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Add bands                                                       */
+/* -------------------------------------------------------------------- */
+
+        for( int iBand=0; iBand < nBands; iBand++ )
+            poDS->SetBand(iBand+1, new RasterliteBand(poDS, iBand+1, eDataType,
+                                                      nBlockXSize, nBlockYSize));
+
+/* -------------------------------------------------------------------- */
+/*      Add overview levels as internal datasets                        */
+/* -------------------------------------------------------------------- */
+        if (nResolutions > 1)
+        {
+            poDS->papoOverviews = reinterpret_cast<RasterliteDataset **>(
+                CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset*)) );
+            for( int nLev = 1; nLev < nResolutions; nLev++ )
+            {
+                int nOvrBands;
+                GDALDataType eOvrDataType;
+                if (poDS->GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType,
+                                         &nBlockXSize, &nBlockYSize) == FALSE)
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot find block characteristics for overview %d", nLev);
+                    delete poDS;
+                    poDS = NULL;
+                    goto end;
+                }
+
+                if (eDataType == GDT_Byte && nOvrBands == 1 && nReqBands == 3)
+                    nOvrBands = 3;
+
+                if (nBands != nOvrBands || eDataType != eOvrDataType)
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Overview %d has not the same number characteristics as main band", nLev);
+                    delete poDS;
+                    poDS = NULL;
+                    goto end;
+                }
+
+                poDS->papoOverviews[nLev-1] = new RasterliteDataset(poDS, nLev);
+
+                for( int iBand = 0; iBand < nBands; iBand++ )
+                {
+                    poDS->papoOverviews[nLev-1]->SetBand(iBand+1,
+                        new RasterliteBand(poDS->papoOverviews[nLev-1], iBand+1, eDataType,
+                                           nBlockXSize, nBlockYSize));
+                }
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Select an overview if the user has requested so                 */
+/* -------------------------------------------------------------------- */
+        if (nLevel == 0)
+        {
+        }
+        else if (nLevel >= 1 && nLevel <= nResolutions - 1)
+        {
+            poDS->papoOverviews[nLevel-1]->bMustFree = TRUE;
+            poDS = poDS->papoOverviews[nLevel-1];
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                      "Invalid requested level : %d. Must be >= 0 and <= %d",
+                      nLevel, nResolutions - 1);
+            delete poDS;
+            poDS = NULL;
+        }
+    }
+
+    if (poDS)
+    {
+/* -------------------------------------------------------------------- */
+/*      Setup PAM info for this subdatasets                             */
+/* -------------------------------------------------------------------- */
+        poDS->SetPhysicalFilename( osFileName.c_str() );
+
+        CPLString osSubdatasetName;
+        osSubdatasetName.Printf("RASTERLITE:%s:table=%s",
+                                osFileName.c_str(), osTableName.c_str());
+        poDS->SetSubdatasetName( osSubdatasetName.c_str() );
+        poDS->TryLoadXML();
+        poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
+    }
+
+end:
+    if (hDS)
+        OGRReleaseDataSource(hDS);
+    CSLDestroy(papszTokens);
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                     GDALRegister_Rasterlite()                        */
+/************************************************************************/
+
+void GDALRegister_Rasterlite()
+
+{
+    if( !GDAL_CHECK_VERSION("Rasterlite driver") )
+        return;
+
+    if( GDALGetDriverByName( "Rasterlite" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "Rasterlite" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Rasterlite" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_rasterlite.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sqlite" );
+    poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 UInt32 Int32 Float32 "
+                               "Float64 CInt16 CInt32 CFloat32 CFloat64" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>"
+"   <Option name='WIPE' type='boolean' default='NO' description='Erase all preexisting data in the specified table'/>"
+"   <Option name='TILED' type='boolean' default='YES' description='Use tiling'/>"
+"   <Option name='BLOCKXSIZE' type='int' default='256' description='Tile Width'/>"
+"   <Option name='BLOCKYSIZE' type='int' default='256' description='Tile Height'/>"
+"   <Option name='DRIVER' type='string' default='GTiff' description='GDAL driver to use for storing tiles' default='GTiff'/>"
+"   <Option name='COMPRESS' type='string' default='(GTiff driver) Compression method' default='NONE'/>"
+"   <Option name='QUALITY' type='int' description='(JPEG-compressed GTiff, JPEG and WEBP drivers) JPEG/WEBP Quality 1-100' default='75'/>"
+"   <Option name='PHOTOMETRIC' type='string-select' description='(GTiff driver) Photometric interpretation'>"
+"       <Value>MINISBLACK</Value>"
+"       <Value>MINISWHITE</Value>"
+"       <Value>PALETTE</Value>"
+"       <Value>RGB</Value>"
+"       <Value>CMYK</Value>"
+"       <Value>YCBCR</Value>"
+"       <Value>CIELAB</Value>"
+"       <Value>ICCLAB</Value>"
+"       <Value>ITULAB</Value>"
+"   </Option>"
+"   <Option name='TARGET' type='int' description='(EPSILON driver) target size reduction as a percentage of the original (0-100)' default='96'/>"
+"   <Option name='FILTER' type='string' description='(EPSILON driver) Filter ID' default='daub97lift'/>"
+"</CreationOptionList>" );
+
+    poDriver->pfnOpen = RasterliteDataset::Open;
+    poDriver->pfnIdentify = RasterliteDataset::Identify;
+    poDriver->pfnCreateCopy = RasterliteCreateCopy;
+    poDriver->pfnDelete = RasterliteDelete;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/rasterlite/rasterlitedataset.h b/frmts/rasterlite/rasterlitedataset.h
index f7430f5..18e5763 100644
--- a/frmts/rasterlite/rasterlitedataset.h
+++ b/frmts/rasterlite/rasterlitedataset.h
@@ -1,158 +1,158 @@
-/******************************************************************************
- * $Id: rasterlitedataset.h 31167 2015-10-27 21:33:35Z goatbar $
- *
- * Project:  GDAL Rasterlite driver
- * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- **********************************************************************
- * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
- 
-#ifndef RASTERLITE_DATASET_INCLUDED
-#define RASTERLITE_DATASET_INCLUDED
-
-#include "gdal_pam.h"
-#include "ogr_api.h"
-
-char** RasterliteGetTileDriverOptions(char** papszOptions);
-
-OGRDataSourceH RasterliteOpenSQLiteDB(const char* pszFilename,
-                                      GDALAccess eAccess);
-CPLString RasterliteGetPixelSizeCond(double dfPixelXSize,
-                                     double dfPixelYSize,
-                                     const char* pszTablePrefixWithDot = "");
-CPLString RasterliteGetSpatialFilterCond(double minx, double miny,
-                                         double maxx, double maxy);
-
-class RasterliteBand;
-
-/************************************************************************/
-/* ==================================================================== */
-/*                              RasterliteDataset                       */
-/* ==================================================================== */
-/************************************************************************/
-
-class RasterliteDataset : public GDALPamDataset
-{
-    friend class RasterliteBand;
-
-  public:
-                 RasterliteDataset();
-                 RasterliteDataset(RasterliteDataset* poMainDS, int nLevel);
-
-    virtual     ~RasterliteDataset();
-
-    virtual char      **GetMetadataDomainList();
-    virtual char **GetMetadata( const char *pszDomain );
-    virtual const char *GetMetadataItem( const char *pszName, 
-                                         const char *pszDomain );
-    virtual CPLErr GetGeoTransform( double* padfGeoTransform );
-    virtual const char* GetProjectionRef();
-
-    virtual char** GetFileList();
-
-    virtual CPLErr IBuildOverviews( const char * pszResampling, 
-                                    int nOverviews, int * panOverviewList,
-                                    int nBands, int * panBandList,
-                                    GDALProgressFunc pfnProgress, void * pProgressData );
-
-    static GDALDataset *Open( GDALOpenInfo * );
-    static int          Identify( GDALOpenInfo * );
-
-  protected:
-    virtual int         CloseDependentDatasets();
-
-  private:
-    int bMustFree;
-    RasterliteDataset* poMainDS;
-    int nLevel;
-
-    char** papszMetadata;
-    char** papszImageStructure;
-    char** papszSubDatasets;
-
-    int nResolutions;
-    double *padfXResolutions;
-    double *padfYResolutions;
-    RasterliteDataset** papoOverviews;
-    int nLimitOvrCount;
-
-    int bValidGeoTransform;
-    double adfGeoTransform[6];
-    char* pszSRS;
-
-    GDALColorTable* poCT;
-
-    CPLString osTableName;
-    CPLString osFileName;
-
-    int bCheckForExistingOverview;
-    CPLString osOvrFileName;
-
-    OGRDataSourceH hDS;
-
-    void AddSubDataset( const char* pszDSName);
-    int  GetBlockParams(OGRLayerH hRasterLyr, int nLevel, int* pnBands,
-                        GDALDataType* peDataType,
-                        int* pnBlockXSize, int* pnBlockYSize);
-    CPLErr CleanOverviews();
-    CPLErr CleanOverviewLevel(int nOvrFactor);
-    CPLErr ReloadOverviews();
-    CPLErr CreateOverviewLevel(const char * pszResampling,
-                               int nOvrFactor,
-                               char** papszOptions,
-                               GDALProgressFunc pfnProgress,
-                               void * pProgressData);
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                              RasterliteBand                          */
-/* ==================================================================== */
-/************************************************************************/
-
-class RasterliteBand: public GDALPamRasterBand
-{
-    friend class RasterliteDataset;
-
-  public:
-                            RasterliteBand( RasterliteDataset* poDS, int nBand,
-                                            GDALDataType eDataType,
-                                            int nBlockXSize, int nBlockYSize);
-
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable* GetColorTable();
-
-    virtual int             GetOverviewCount();
-    virtual GDALRasterBand* GetOverview(int nLevel);
-
-    virtual CPLErr          IReadBlock( int, int, void * );
-};
-
-GDALDataset *
-RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
-                       int bStrict, char ** papszOptions, 
-                       GDALProgressFunc pfnProgress, void * pProgressData );
-
-CPLErr RasterliteDelete(const char* pszFilename);
-
-#endif // RASTERLITE_DATASET_INCLUDED
+/******************************************************************************
+ * $Id: rasterlitedataset.h 36501 2016-11-25 14:09:24Z rouault $
+ *
+ * Project:  GDAL Rasterlite driver
+ * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef RASTERLITE_DATASET_INCLUDED
+#define RASTERLITE_DATASET_INCLUDED
+
+#include "gdal_pam.h"
+#include "ogr_api.h"
+
+char** RasterliteGetTileDriverOptions(char** papszOptions);
+
+OGRDataSourceH RasterliteOpenSQLiteDB(const char* pszFilename,
+                                      GDALAccess eAccess);
+CPLString RasterliteGetPixelSizeCond(double dfPixelXSize,
+                                     double dfPixelYSize,
+                                     const char* pszTablePrefixWithDot = "");
+CPLString RasterliteGetSpatialFilterCond(double minx, double miny,
+                                         double maxx, double maxy);
+
+class RasterliteBand;
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              RasterliteDataset                       */
+/* ==================================================================== */
+/************************************************************************/
+
+class RasterliteDataset : public GDALPamDataset
+{
+    friend class RasterliteBand;
+
+  public:
+                 RasterliteDataset();
+                 RasterliteDataset(RasterliteDataset* poMainDS, int nLevel);
+
+    virtual     ~RasterliteDataset();
+
+    virtual char      **GetMetadataDomainList() override;
+    virtual char **GetMetadata( const char *pszDomain ) override;
+    virtual const char *GetMetadataItem( const char *pszName,
+                                         const char *pszDomain ) override;
+    virtual CPLErr GetGeoTransform( double* padfGeoTransform ) override;
+    virtual const char* GetProjectionRef() override;
+
+    virtual char** GetFileList() override;
+
+    virtual CPLErr IBuildOverviews( const char * pszResampling,
+                                    int nOverviews, int * panOverviewList,
+                                    int nBands, int * panBandList,
+                                    GDALProgressFunc pfnProgress, void * pProgressData ) override;
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+
+  protected:
+    virtual int         CloseDependentDatasets() override;
+
+  private:
+    int bMustFree;
+    RasterliteDataset* poMainDS;
+    int nLevel;
+
+    char** papszMetadata;
+    char** papszImageStructure;
+    char** papszSubDatasets;
+
+    int nResolutions;
+    double *padfXResolutions;
+    double *padfYResolutions;
+    RasterliteDataset** papoOverviews;
+    int nLimitOvrCount;
+
+    int bValidGeoTransform;
+    double adfGeoTransform[6];
+    char* pszSRS;
+
+    GDALColorTable* poCT;
+
+    CPLString osTableName;
+    CPLString osFileName;
+
+    int bCheckForExistingOverview;
+    CPLString osOvrFileName;
+
+    OGRDataSourceH hDS;
+
+    void AddSubDataset( const char* pszDSName);
+    int  GetBlockParams(OGRLayerH hRasterLyr, int nLevel, int* pnBands,
+                        GDALDataType* peDataType,
+                        int* pnBlockXSize, int* pnBlockYSize);
+    CPLErr CleanOverviews();
+    CPLErr CleanOverviewLevel(int nOvrFactor);
+    CPLErr ReloadOverviews();
+    CPLErr CreateOverviewLevel(const char * pszResampling,
+                               int nOvrFactor,
+                               char** papszOptions,
+                               GDALProgressFunc pfnProgress,
+                               void * pProgressData);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                              RasterliteBand                          */
+/* ==================================================================== */
+/************************************************************************/
+
+class RasterliteBand: public GDALPamRasterBand
+{
+    friend class RasterliteDataset;
+
+  public:
+                            RasterliteBand( RasterliteDataset* poDS, int nBand,
+                                            GDALDataType eDataType,
+                                            int nBlockXSize, int nBlockYSize );
+
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable* GetColorTable() override;
+
+    virtual int             GetOverviewCount() override;
+    virtual GDALRasterBand* GetOverview(int nLevel) override;
+
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+};
+
+GDALDataset *
+RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
+                       int bStrict, char ** papszOptions,
+                       GDALProgressFunc pfnProgress, void * pProgressData );
+
+CPLErr RasterliteDelete(const char* pszFilename);
+
+#endif // RASTERLITE_DATASET_INCLUDED
diff --git a/frmts/rasterlite/rasterliteoverviews.cpp b/frmts/rasterlite/rasterliteoverviews.cpp
index ef98363..2514bc7 100644
--- a/frmts/rasterlite/rasterliteoverviews.cpp
+++ b/frmts/rasterlite/rasterliteoverviews.cpp
@@ -1,802 +1,800 @@
-/******************************************************************************
- * $Id: rasterliteoverviews.cpp 32984 2016-01-14 19:08:12Z goatbar $
- *
- * Project:  GDAL Rasterlite driver
- * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- **********************************************************************
- * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_string.h"
-#include "ogr_api.h"
-#include "ogr_srs_api.h"
-
-#include "rasterlitedataset.h"
-
-CPL_CVSID("$Id: rasterliteoverviews.cpp 32984 2016-01-14 19:08:12Z goatbar $");
-
-/************************************************************************/
-/*                         ReloadOverviews()                            */
-/************************************************************************/
-
-CPLErr RasterliteDataset::ReloadOverviews()
-{
-    if (nLevel != 0)
-        return CE_Failure;
-
-/* -------------------------------------------------------------------- */
-/*      Fetch resolutions                                               */
-/* -------------------------------------------------------------------- */
-
-    CPLString osSQL;
-    OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
-    if (hRasterPyramidsLyr)
-    {
-        osSQL.Printf("SELECT pixel_x_size, pixel_y_size "
-                     "FROM raster_pyramids WHERE table_prefix = '%s' "
-                     "ORDER BY pixel_x_size ASC",
-                     osTableName.c_str());
-     }
-     else
-     {
-        osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
-                     "FROM \"%s_metadata\" WHERE pixel_x_size != 0  "
-                     "ORDER BY pixel_x_size ASC",
-                     osTableName.c_str());
-     }
-
-    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    if (hSQLLyr == NULL)
-    {
-        if (hRasterPyramidsLyr == NULL)
-            return CE_Failure;
-
-        osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
-                     "FROM \"%s_metadata\" WHERE pixel_x_size != 0  "
-                     "ORDER BY pixel_x_size ASC",
-                     osTableName.c_str());
-
-        hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-        if (hSQLLyr == NULL)
-            return CE_Failure;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-    for( int i = 1; i < nResolutions; i++ )
-        delete papoOverviews[i-1];
-    CPLFree(papoOverviews);
-    papoOverviews = NULL;
-    CPLFree(padfXResolutions);
-    padfXResolutions = NULL;
-    CPLFree(padfYResolutions);
-    padfYResolutions = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Rebuild arrays                                                  */
-/* -------------------------------------------------------------------- */
-
-    nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
-
-    padfXResolutions =
-        reinterpret_cast<double *>( CPLMalloc(sizeof(double) * nResolutions) );
-    padfYResolutions =
-        reinterpret_cast<double *>( CPLMalloc(sizeof(double) * nResolutions) );
-
-    {
-        // Exstra scope for i.
-        int i = 0;
-        OGRFeatureH hFeat;
-        while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
-        {
-            padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
-            padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
-
-            OGR_F_Destroy(hFeat);
-
-            i++;
-        }
-    }
-
-    OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-    hSQLLyr = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Add overview levels as internal datasets                        */
-/* -------------------------------------------------------------------- */
-    if (nResolutions > 1)
-    {
-        CPLString osRasterTableName = osTableName;
-        osRasterTableName += "_rasters";
-
-        OGRLayerH hRasterLyr = OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
-
-        papoOverviews = reinterpret_cast<RasterliteDataset **>(
-            CPLCalloc( nResolutions - 1, sizeof(RasterliteDataset*) ) );
-        for( int nLev = 1; nLev < nResolutions; nLev++ )
-        {
-            int nOvrBands;
-            GDALDataType eOvrDataType;
-            int nBlockXSize, nBlockYSize;
-            if (GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType,
-                               &nBlockXSize, &nBlockYSize))
-            {
-                if (eOvrDataType == GDT_Byte && nOvrBands == 1 && nBands == 3)
-                    nOvrBands = 3;
-
-                papoOverviews[nLev-1] = new RasterliteDataset(this, nLev);
-
-                for( int iBand = 0; iBand < nBands; iBand++ )
-                {
-                    papoOverviews[nLev-1]->SetBand(iBand+1,
-                        new RasterliteBand(papoOverviews[nLev-1], iBand+1, eOvrDataType,
-                                           nBlockXSize, nBlockYSize));
-                }
-            }
-            else
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "Cannot find block characteristics for overview %d", nLev);
-                papoOverviews[nLev-1] = NULL;
-            }
-        }
-    }
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                          CleanOverviews()                            */
-/************************************************************************/
-
-CPLErr RasterliteDataset::CleanOverviews()
-{
-    if (nLevel != 0)
-        return CE_Failure;
-
-    CPLString osSQL("BEGIN");;
-    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-    const CPLString osResolutionCond =
-        "NOT " + RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]);
-
-    osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
-                 "IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
-                  osTableName.c_str(), osTableName.c_str(),
-                  osResolutionCond.c_str());
-    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-    osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s",
-                  osTableName.c_str(), osResolutionCond.c_str());
-    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-    OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
-    if (hRasterPyramidsLyr)
-    {
-        osSQL.Printf("DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
-                      osTableName.c_str(), osResolutionCond.c_str());
-        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    }
-
-    osSQL = "COMMIT";
-    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-    for( int i = 1; i < nResolutions; i++ )
-        delete papoOverviews[i-1];
-    CPLFree(papoOverviews);
-    papoOverviews = NULL;
-    nResolutions = 1;
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                       CleanOverviewLevel()                           */
-/************************************************************************/
-
-CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor)
-{
-    if (nLevel != 0)
-        return CE_Failure;
-
-/* -------------------------------------------------------------------- */
-/*      Find the index of the overview matching the overview factor     */
-/* -------------------------------------------------------------------- */
-    int iLev = 1;
-    for( ; iLev < nResolutions; iLev++ )
-    {
-        if (fabs(padfXResolutions[0] * nOvrFactor - padfXResolutions[iLev]) < 1e-15 &&
-            fabs(padfYResolutions[0] * nOvrFactor - padfYResolutions[iLev]) < 1e-15)
-            break;
-    }
-
-    if (iLev == nResolutions)
-        return CE_None;
-
-/* -------------------------------------------------------------------- */
-/*      Now clean existing overviews at that resolution                 */
-/* -------------------------------------------------------------------- */
-
-    CPLString osSQL("BEGIN");
-    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-    CPLString osResolutionCond =
-        RasterliteGetPixelSizeCond(padfXResolutions[iLev], padfYResolutions[iLev]);
-
-    osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
-                 "IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
-                  osTableName.c_str(), osTableName.c_str(),
-                  osResolutionCond.c_str());
-    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-    osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s",
-                  osTableName.c_str(), osResolutionCond.c_str());
-    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-    OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
-    if (hRasterPyramidsLyr)
-    {
-        osSQL.Printf("DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
-                      osTableName.c_str(), osResolutionCond.c_str());
-        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    }
-
-    osSQL = "COMMIT";
-    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                       CleanOverviewLevel()                           */
-/************************************************************************/
-
-CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
-                                              int nOvrFactor,
-                                              char** papszOptions,
-                                              GDALProgressFunc pfnProgress,
-                                              void * pProgressData)
-{
-    const int nOvrXSize = nRasterXSize / nOvrFactor;
-    const int nOvrYSize = nRasterYSize / nOvrFactor;
-
-    if (nOvrXSize == 0 || nOvrYSize == 0)
-        return CE_Failure;
-
-    const bool bTiled
-        = CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
-    int nBlockXSize, nBlockYSize;
-    if (bTiled)
-    {
-        nBlockXSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
-        nBlockYSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
-        if (nBlockXSize < 64) nBlockXSize = 64;
-        else if (nBlockXSize > 4096)  nBlockXSize = 4096;
-        if (nBlockYSize < 64) nBlockYSize = 64;
-        else if (nBlockYSize > 4096)  nBlockYSize = 4096;
-    }
-    else
-    {
-        nBlockXSize = nOvrXSize;
-        nBlockYSize = nOvrYSize;
-    }
-
-    const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
-    if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "GDAL %s driver cannot be used as underlying driver",
-                 pszDriverName);
-        return CE_Failure;
-    }
-    GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
-    if (hTileDriver == NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
-        return CE_Failure;
-    }
-
-    GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
-    if (hMemDriver == NULL)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
-        return CE_Failure;
-    }
-
-    const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
-    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
-    GByte* pabyMEMDSBuffer = reinterpret_cast<GByte *>(
-        VSIMalloc3( nBlockXSize, nBlockYSize, nBands * nDataTypeSize ) );
-    if (pabyMEMDSBuffer == NULL)
-    {
-        return CE_Failure;
-    }
-
-    CPLString osTempFileName;
-    osTempFileName.Printf("/vsimem/%p", hDS);
-
-    int nTileId = 0;
-    int nBlocks = 0;
-
-    const int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize;
-    const int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize;
-    int nTotalBlocks = nXBlocks * nYBlocks;
-
-    CPLString osRasterLayer;
-    osRasterLayer.Printf("%s_rasters", osTableName.c_str());
-
-    CPLString osMetatadataLayer;
-    osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
-
-    OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
-    OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
-
-    CPLString osSourceName = "unknown";
-
-    const double dfXResolution = padfXResolutions[0] * nOvrFactor;
-    const double dfYResolution = padfXResolutions[0] * nOvrFactor;
-
-    CPLString osSQL;
-    osSQL.Printf("SELECT source_name FROM \"%s\" WHERE "
-                 "%s LIMIT 1",
-                 osMetatadataLayer.c_str(),
-                 RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
-    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    if (hSQLLyr)
-    {
-        OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
-        if (hFeat)
-        {
-            const char* pszVal = OGR_F_GetFieldAsString(hFeat, 0);
-            if (pszVal)
-                osSourceName = pszVal;
-            OGR_F_Destroy(hFeat);
-        }
-        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Compute up to which existing overview level we can use for      */
-/*      computing the requested overview                                */
-/* -------------------------------------------------------------------- */
-    nLimitOvrCount = 0;
-    int iLev = 1;
-    for( ; iLev < nResolutions; iLev++ )
-    {
-        if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 &&
-              padfYResolutions[iLev] < dfYResolution - 1e-10))
-        {
-            break;
-        }
-        nLimitOvrCount++;
-    }
-/* -------------------------------------------------------------------- */
-/*      Allocate buffer for tile of previous overview level             */
-/* -------------------------------------------------------------------- */
-
-    GDALDataset* poPrevOvrLevel =
-        (papoOverviews != NULL && iLev >= 2 && iLev <= nResolutions && papoOverviews[iLev-2]) ?
-            papoOverviews[iLev-2] : this;
-    const double dfRatioPrevOvr = static_cast<double>(poPrevOvrLevel->GetRasterBand(1)->GetXSize()) / nOvrXSize;
-    const int nPrevOvrBlockXSize = static_cast<int>( nBlockXSize * dfRatioPrevOvr + 0.5 );
-    const int nPrevOvrBlockYSize = static_cast<int>(nBlockYSize * dfRatioPrevOvr + 0.5 );
-    GByte* pabyPrevOvrMEMDSBuffer = NULL;
-
-    if( !STARTS_WITH_CI(pszResampling, "NEAR"))
-    {
-        pabyPrevOvrMEMDSBuffer = reinterpret_cast<GByte*>(
-            VSIMalloc3( nPrevOvrBlockXSize, nPrevOvrBlockYSize, nBands * nDataTypeSize ) );
-        if (pabyPrevOvrMEMDSBuffer == NULL)
-        {
-            VSIFree(pabyMEMDSBuffer);
-            return CE_Failure;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Iterate over blocks to add data into raster and metadata tables */
-/* -------------------------------------------------------------------- */
-
-    char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
-
-    OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
-
-    CPLErr eErr = CE_None;
-    for( int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks; nBlockYOff++ )
-    {
-        for( int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks; nBlockXOff++ )
-        {
-            GDALDatasetH hPrevOvrMemDS = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Create in-memory tile                                           */
-/* -------------------------------------------------------------------- */
-            int nReqXSize = nBlockXSize;
-            int nReqYSize = nBlockYSize;
-            if ((nBlockXOff+1) * nBlockXSize > nOvrXSize)
-                nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize;
-            if ((nBlockYOff+1) * nBlockYSize > nOvrYSize)
-                nReqYSize = nOvrYSize - nBlockYOff * nBlockYSize;
-
-            if( pabyPrevOvrMEMDSBuffer != NULL )
-            {
-                int nPrevOvrReqXSize =
-                    static_cast<int>( nReqXSize * dfRatioPrevOvr + 0.5 );
-                int nPrevOvrReqYSize =
-                    static_cast<int>(nReqYSize * dfRatioPrevOvr + 0.5 );
-
-                eErr = RasterIO(GF_Read,
-                                nBlockXOff * nBlockXSize * nOvrFactor,
-                                nBlockYOff * nBlockYSize * nOvrFactor,
-                                nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
-                                pabyPrevOvrMEMDSBuffer, nPrevOvrReqXSize, nPrevOvrReqYSize,
-                                eDataType, nBands, NULL,
-                                0, 0, 0, NULL);
-
-                if (eErr != CE_None)
-                {
-                    break;
-                }
-
-                hPrevOvrMemDS = GDALCreate(hMemDriver, "MEM:::",
-                                           nPrevOvrReqXSize, nPrevOvrReqYSize, 0,
-                                           eDataType, NULL);
-
-                if (hPrevOvrMemDS == NULL)
-                {
-                    eErr = CE_Failure;
-                    break;
-                }
-
-                for( int iBand = 0; iBand < nBands; iBand++ )
-                {
-                    char szTmp[64];
-                    memset(szTmp, 0, sizeof(szTmp));
-                    CPLPrintPointer(szTmp,
-                                    pabyPrevOvrMEMDSBuffer + iBand * nDataTypeSize *
-                                    nPrevOvrReqXSize * nPrevOvrReqYSize, sizeof(szTmp));
-                    char** l_papszOptions
-                        = CSLSetNameValue(NULL, "DATAPOINTER", szTmp);
-                    GDALAddBand(hPrevOvrMemDS, eDataType, l_papszOptions);
-                    CSLDestroy(l_papszOptions);
-                }
-            }
-            else
-            {
-                eErr = RasterIO(GF_Read,
-                                nBlockXOff * nBlockXSize * nOvrFactor,
-                                nBlockYOff * nBlockYSize * nOvrFactor,
-                                nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
-                                pabyMEMDSBuffer, nReqXSize, nReqYSize,
-                                eDataType, nBands, NULL,
-                                0, 0, 0, NULL);
-                if (eErr != CE_None)
-                {
-                    break;
-                }
-            }
-
-            GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
-                                              nReqXSize, nReqYSize, 0, 
-                                              eDataType, NULL);
-            if (hMemDS == NULL)
-            {
-                eErr = CE_Failure;
-                break;
-            }
-
-
-            for(int iBand = 0; iBand < nBands; iBand ++)
-            {
-                char szTmp[64];
-                memset(szTmp, 0, sizeof(szTmp));
-                CPLPrintPointer(szTmp,
-                                pabyMEMDSBuffer + iBand * nDataTypeSize *
-                                nReqXSize * nReqYSize, sizeof(szTmp));
-                char** l_papszOptions
-                    = CSLSetNameValue(NULL, "DATAPOINTER", szTmp);
-                GDALAddBand(hMemDS, eDataType, l_papszOptions);
-                CSLDestroy(l_papszOptions);
-            }
-
-            if( hPrevOvrMemDS != NULL )
-            {
-                for(int iBand = 0; iBand < nBands; iBand ++)
-                {
-                    GDALRasterBandH hDstOvrBand = GDALGetRasterBand(hMemDS, iBand+1);
-
-                    eErr = GDALRegenerateOverviews( GDALGetRasterBand(hPrevOvrMemDS, iBand+1),
-                                                    1, &hDstOvrBand,
-                                                    pszResampling,
-                                                    NULL, NULL );
-                    if( eErr != CE_None )
-                        break;
-                }
-
-                GDALClose(hPrevOvrMemDS);
-            }
-
-            GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
-                                        osTempFileName.c_str(), hMemDS, FALSE,
-                                        papszTileDriverOptions, NULL, NULL);
-
-            GDALClose(hMemDS);
-            if (! hOutDS)
-            {
-                eErr = CE_Failure;
-                break;
-            }
-
-            GDALClose(hOutDS);
-
-/* -------------------------------------------------------------------- */
-/*      Insert new entry into raster table                              */
-/* -------------------------------------------------------------------- */
-
-            vsi_l_offset nDataLength;
-            GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
-                                                   &nDataLength, FALSE);
-
-            OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
-            OGR_F_SetFieldBinary(hFeat, 0, static_cast<int>( nDataLength ), pabyData);
-
-            if( OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE )
-                eErr = CE_Failure;
-            /* Query raster ID to set it as the ID of the associated metadata */
-            const int nRasterID = static_cast<int>( OGR_F_GetFID(hFeat) );
-
-            OGR_F_Destroy(hFeat);
-
-            VSIUnlink(osTempFileName.c_str());
-            if( eErr == CE_Failure )
-                break;
-
-/* -------------------------------------------------------------------- */
-/*      Insert new entry into metadata table                            */
-/* -------------------------------------------------------------------- */
-
-            hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
-            OGR_F_SetFID(hFeat, nRasterID);
-            OGR_F_SetFieldString(hFeat, 0, osSourceName);
-            OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
-            OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
-            OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
-            OGR_F_SetFieldDouble(hFeat, 4, dfXResolution);
-            OGR_F_SetFieldDouble(hFeat, 5, dfYResolution);
-
-            const double minx = adfGeoTransform[0] +
-                (nBlockXSize * nBlockXOff) * dfXResolution;
-            const double maxx = adfGeoTransform[0] +
-                (nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution;
-            const double maxy = adfGeoTransform[3] +
-                (nBlockYSize * nBlockYOff) * (-dfYResolution);
-            const double miny = adfGeoTransform[3] +
-                (nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution);
-
-            OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
-            OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
-            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
-            OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
-            OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
-            OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
-            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
-            OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
-
-            OGR_F_SetGeometryDirectly(hFeat, hRectangle);
-
-            if( OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE )
-                eErr = CE_Failure;
-            OGR_F_Destroy(hFeat);
-
-            nBlocks++;
-            if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
-                                            NULL, pProgressData))
-                eErr = CE_Failure;
-        }
-    }
-
-    nLimitOvrCount = -1;
-
-    if (eErr == CE_None)
-        OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
-    else
-        OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
-
-    VSIFree(pabyMEMDSBuffer);
-    VSIFree(pabyPrevOvrMEMDSBuffer);
-
-    CSLDestroy(papszTileDriverOptions);
-    papszTileDriverOptions = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Update raster_pyramids table                                    */
-/* -------------------------------------------------------------------- */
-    if (eErr != CE_None)
-        return eErr;
-
-    OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
-    if (hRasterPyramidsLyr == NULL)
-    {
-        osSQL.Printf   ("CREATE TABLE raster_pyramids ("
-                        "table_prefix TEXT NOT NULL,"
-                        "pixel_x_size DOUBLE NOT NULL,"
-                        "pixel_y_size DOUBLE NOT NULL,"
-                        "tile_count INTEGER NOT NULL)");
-        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-
-        /* Re-open the DB to take into account the new tables*/
-        OGRReleaseDataSource(hDS);
-
-        hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update);
-
-        hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
-        if (hRasterPyramidsLyr == NULL)
-            return CE_Failure;
-    }
-    OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr);
-
-    /* Insert base resolution into raster_pyramids if not already done */
-    bool bHasBaseResolution = false;
-    osSQL.Printf("SELECT * FROM raster_pyramids WHERE "
-                 "table_prefix = '%s' AND %s",
-                 osTableName.c_str(),
-                 RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
-    hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-    if (hSQLLyr)
-    {
-        OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
-        if (hFeat)
-        {
-            bHasBaseResolution = true;
-            OGR_F_Destroy(hFeat);
-        }
-        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-    }
-
-    if (!bHasBaseResolution)
-    {
-        osSQL.Printf("SELECT COUNT(*) FROM \"%s\" WHERE %s",
-                      osMetatadataLayer.c_str(),
-                      RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
-
-        int nBlocksMainRes = 0;
-
-        hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
-        if (hSQLLyr)
-        {
-            OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
-            if (hFeat)
-            {
-                nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0);
-                OGR_F_Destroy(hFeat);
-            }
-            OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
-        }
-
-        OGRFeatureH hFeat = OGR_F_Create( hFDefn );
-        OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
-        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), padfXResolutions[0]);
-        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), padfYResolutions[0]);
-        OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nBlocksMainRes);
-        if( OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE )
-            eErr = CE_Failure;
-        OGR_F_Destroy(hFeat);
-    }
-
-    OGRFeatureH hFeat = OGR_F_Create( hFDefn );
-    OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
-    OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), dfXResolution);
-    OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), dfYResolution);
-    OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nTotalBlocks);
-    if( OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE )
-        eErr = CE_Failure;
-    OGR_F_Destroy(hFeat);
-
-    return eErr;
-}
-
-/************************************************************************/
-/*                          IBuildOverviews()                           */
-/************************************************************************/
-
-CPLErr RasterliteDataset::IBuildOverviews( const char * pszResampling, 
-                                           int nOverviews, int * panOverviewList,
-                                           int nBandsIn, int * panBandList,
-                                           GDALProgressFunc pfnProgress,
-                                           void * pProgressData )
-{
-    if (nLevel != 0)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Overviews can only be computed on the base dataset");
-        return CE_Failure;
-    }
-
-    if (osTableName.size() == 0)
-        return CE_Failure;
-
-/* -------------------------------------------------------------------- */
-/*      If we don't have read access, then create the overviews         */
-/*      externally.                                                     */
-/* -------------------------------------------------------------------- */
-    if( GetAccess() != GA_Update )
-    {
-        CPLDebug( "Rasterlite",
-                  "File open for read-only accessing, "
-                  "creating overviews externally." );
-
-        if (nResolutions != 1)
-        {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "Cannot add external overviews to a "
-                     "dataset with internal overviews");
-            return CE_Failure;
-        }
-
-        bCheckForExistingOverview = FALSE;
-        CPLErr eErr = GDALDataset::IBuildOverviews( 
-                            pszResampling, nOverviews, panOverviewList, 
-                            nBandsIn, panBandList, pfnProgress, pProgressData );
-        bCheckForExistingOverview = TRUE;
-        return eErr;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      If zero overviews were requested, we need to clear all          */
-/*      existing overviews.                                             */
-/* -------------------------------------------------------------------- */
-    if (nOverviews == 0)
-    {
-        return CleanOverviews();
-    }
-
-    if( nBandsIn != GetRasterCount() )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Generation of overviews in RASTERLITE only"
-                  " supported when operating on all bands.\n" 
-                  "Operation failed.\n" );
-        return CE_Failure;
-    }
-
-    const char* pszOvrOptions = CPLGetConfigOption("RASTERLITE_OVR_OPTIONS", NULL);
-    char** papszOptions = (pszOvrOptions) ? CSLTokenizeString2( pszOvrOptions, ",", 0) : NULL;
-    GDALValidateCreationOptions( GetDriver(), papszOptions);
-
-    CPLErr eErr = CE_None;
-    for( int i = 0; i < nOverviews && eErr == CE_None; i++)
-    {
-        if (panOverviewList[i] <= 1)
-            continue;
-
-        eErr = CleanOverviewLevel(panOverviewList[i]);
-        if (eErr == CE_None)
-            eErr = CreateOverviewLevel(pszResampling, panOverviewList[i], papszOptions, pfnProgress, pProgressData);
-
-        ReloadOverviews();
-    }
-
-    CSLDestroy(papszOptions);
-
-    return eErr;
-}
+/******************************************************************************
+ *
+ * Project:  GDAL Rasterlite driver
+ * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ **********************************************************************
+ * Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_string.h"
+#include "ogr_api.h"
+#include "ogr_srs_api.h"
+
+#include "rasterlitedataset.h"
+
+CPL_CVSID("$Id: rasterliteoverviews.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+/************************************************************************/
+/*                         ReloadOverviews()                            */
+/************************************************************************/
+
+CPLErr RasterliteDataset::ReloadOverviews()
+{
+    if (nLevel != 0)
+        return CE_Failure;
+
+/* -------------------------------------------------------------------- */
+/*      Fetch resolutions                                               */
+/* -------------------------------------------------------------------- */
+
+    CPLString osSQL;
+    OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
+    if (hRasterPyramidsLyr)
+    {
+        osSQL.Printf("SELECT pixel_x_size, pixel_y_size "
+                     "FROM raster_pyramids WHERE table_prefix = '%s' "
+                     "ORDER BY pixel_x_size ASC",
+                     osTableName.c_str());
+     }
+     else
+     {
+        osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
+                     "FROM \"%s_metadata\" WHERE pixel_x_size != 0  "
+                     "ORDER BY pixel_x_size ASC",
+                     osTableName.c_str());
+     }
+
+    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+    if (hSQLLyr == NULL)
+    {
+        if (hRasterPyramidsLyr == NULL)
+            return CE_Failure;
+
+        osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
+                     "FROM \"%s_metadata\" WHERE pixel_x_size != 0  "
+                     "ORDER BY pixel_x_size ASC",
+                     osTableName.c_str());
+
+        hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+        if (hSQLLyr == NULL)
+            return CE_Failure;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    for( int i = 1; i < nResolutions; i++ )
+        delete papoOverviews[i-1];
+    CPLFree(papoOverviews);
+    papoOverviews = NULL;
+    CPLFree(padfXResolutions);
+    padfXResolutions = NULL;
+    CPLFree(padfYResolutions);
+    padfYResolutions = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Rebuild arrays                                                  */
+/* -------------------------------------------------------------------- */
+
+    nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
+
+    padfXResolutions =
+        reinterpret_cast<double *>( CPLMalloc(sizeof(double) * nResolutions) );
+    padfYResolutions =
+        reinterpret_cast<double *>( CPLMalloc(sizeof(double) * nResolutions) );
+
+    {
+        // Exstra scope for i.
+        int i = 0;
+        OGRFeatureH hFeat;
+        while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
+        {
+            padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
+            padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
+
+            OGR_F_Destroy(hFeat);
+
+            i++;
+        }
+    }
+
+    OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+    hSQLLyr = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Add overview levels as internal datasets                        */
+/* -------------------------------------------------------------------- */
+    if (nResolutions > 1)
+    {
+        CPLString osRasterTableName = osTableName;
+        osRasterTableName += "_rasters";
+
+        OGRLayerH hRasterLyr = OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
+
+        papoOverviews = reinterpret_cast<RasterliteDataset **>(
+            CPLCalloc( nResolutions - 1, sizeof(RasterliteDataset*) ) );
+        for( int nLev = 1; nLev < nResolutions; nLev++ )
+        {
+            int nOvrBands;
+            GDALDataType eOvrDataType;
+            int nBlockXSize, nBlockYSize;
+            if (GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType,
+                               &nBlockXSize, &nBlockYSize))
+            {
+                if (eOvrDataType == GDT_Byte && nOvrBands == 1 && nBands == 3)
+                    nOvrBands = 3;
+
+                papoOverviews[nLev-1] = new RasterliteDataset(this, nLev);
+
+                for( int iBand = 0; iBand < nBands; iBand++ )
+                {
+                    papoOverviews[nLev-1]->SetBand(iBand+1,
+                        new RasterliteBand(papoOverviews[nLev-1], iBand+1, eOvrDataType,
+                                           nBlockXSize, nBlockYSize));
+                }
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot find block characteristics for overview %d", nLev);
+                papoOverviews[nLev-1] = NULL;
+            }
+        }
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          CleanOverviews()                            */
+/************************************************************************/
+
+CPLErr RasterliteDataset::CleanOverviews()
+{
+    if (nLevel != 0)
+        return CE_Failure;
+
+    CPLString osSQL("BEGIN");
+    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+    const CPLString osResolutionCond =
+        "NOT " + RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]);
+
+    osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
+                 "IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
+                  osTableName.c_str(), osTableName.c_str(),
+                  osResolutionCond.c_str());
+    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+    osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s",
+                  osTableName.c_str(), osResolutionCond.c_str());
+    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+    OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
+    if (hRasterPyramidsLyr)
+    {
+        osSQL.Printf("DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
+                      osTableName.c_str(), osResolutionCond.c_str());
+        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+    }
+
+    osSQL = "COMMIT";
+    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+    for( int i = 1; i < nResolutions; i++ )
+        delete papoOverviews[i-1];
+    CPLFree(papoOverviews);
+    papoOverviews = NULL;
+    nResolutions = 1;
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                       CleanOverviewLevel()                           */
+/************************************************************************/
+
+CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor)
+{
+    if (nLevel != 0)
+        return CE_Failure;
+
+/* -------------------------------------------------------------------- */
+/*      Find the index of the overview matching the overview factor     */
+/* -------------------------------------------------------------------- */
+    int iLev = 1;
+    for( ; iLev < nResolutions; iLev++ )
+    {
+        if (fabs(padfXResolutions[0] * nOvrFactor - padfXResolutions[iLev]) < 1e-15 &&
+            fabs(padfYResolutions[0] * nOvrFactor - padfYResolutions[iLev]) < 1e-15)
+            break;
+    }
+
+    if (iLev == nResolutions)
+        return CE_None;
+
+/* -------------------------------------------------------------------- */
+/*      Now clean existing overviews at that resolution                 */
+/* -------------------------------------------------------------------- */
+
+    CPLString osSQL("BEGIN");
+    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+    CPLString osResolutionCond =
+        RasterliteGetPixelSizeCond(padfXResolutions[iLev], padfYResolutions[iLev]);
+
+    osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
+                 "IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
+                  osTableName.c_str(), osTableName.c_str(),
+                  osResolutionCond.c_str());
+    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+    osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s",
+                  osTableName.c_str(), osResolutionCond.c_str());
+    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+    OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
+    if (hRasterPyramidsLyr)
+    {
+        osSQL.Printf("DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
+                      osTableName.c_str(), osResolutionCond.c_str());
+        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+    }
+
+    osSQL = "COMMIT";
+    OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                       CleanOverviewLevel()                           */
+/************************************************************************/
+
+CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
+                                              int nOvrFactor,
+                                              char** papszOptions,
+                                              GDALProgressFunc pfnProgress,
+                                              void * pProgressData)
+{
+    const int nOvrXSize = nRasterXSize / nOvrFactor;
+    const int nOvrYSize = nRasterYSize / nOvrFactor;
+
+    if (nOvrXSize == 0 || nOvrYSize == 0)
+        return CE_Failure;
+
+    const bool bTiled
+        = CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
+    int nBlockXSize, nBlockYSize;
+    if (bTiled)
+    {
+        nBlockXSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
+        nBlockYSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
+        if (nBlockXSize < 64) nBlockXSize = 64;
+        else if (nBlockXSize > 4096)  nBlockXSize = 4096;
+        if (nBlockYSize < 64) nBlockYSize = 64;
+        else if (nBlockYSize > 4096)  nBlockYSize = 4096;
+    }
+    else
+    {
+        nBlockXSize = nOvrXSize;
+        nBlockYSize = nOvrYSize;
+    }
+
+    const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
+    if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDAL %s driver cannot be used as underlying driver",
+                 pszDriverName);
+        return CE_Failure;
+    }
+    GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
+    if (hTileDriver == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
+        return CE_Failure;
+    }
+
+    GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
+    if (hMemDriver == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
+        return CE_Failure;
+    }
+
+    const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
+    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
+    GByte* pabyMEMDSBuffer = reinterpret_cast<GByte *>(
+        VSIMalloc3( nBlockXSize, nBlockYSize, nBands * nDataTypeSize ) );
+    if (pabyMEMDSBuffer == NULL)
+    {
+        return CE_Failure;
+    }
+
+    CPLString osTempFileName;
+    osTempFileName.Printf("/vsimem/%p", hDS);
+
+    int nTileId = 0;
+    int nBlocks = 0;
+
+    const int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize;
+    const int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize;
+    int nTotalBlocks = nXBlocks * nYBlocks;
+
+    CPLString osRasterLayer;
+    osRasterLayer.Printf("%s_rasters", osTableName.c_str());
+
+    CPLString osMetatadataLayer;
+    osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
+
+    OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
+    OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
+
+    CPLString osSourceName = "unknown";
+
+    const double dfXResolution = padfXResolutions[0] * nOvrFactor;
+    const double dfYResolution = padfXResolutions[0] * nOvrFactor;
+
+    CPLString osSQL;
+    osSQL.Printf("SELECT source_name FROM \"%s\" WHERE "
+                 "%s LIMIT 1",
+                 osMetatadataLayer.c_str(),
+                 RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
+    OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+    if (hSQLLyr)
+    {
+        OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
+        if (hFeat)
+        {
+            const char* pszVal = OGR_F_GetFieldAsString(hFeat, 0);
+            if (pszVal)
+                osSourceName = pszVal;
+            OGR_F_Destroy(hFeat);
+        }
+        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Compute up to which existing overview level we can use for      */
+/*      computing the requested overview                                */
+/* -------------------------------------------------------------------- */
+    nLimitOvrCount = 0;
+    int iLev = 1;
+    for( ; iLev < nResolutions; iLev++ )
+    {
+        if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 &&
+              padfYResolutions[iLev] < dfYResolution - 1e-10))
+        {
+            break;
+        }
+        nLimitOvrCount++;
+    }
+/* -------------------------------------------------------------------- */
+/*      Allocate buffer for tile of previous overview level             */
+/* -------------------------------------------------------------------- */
+
+    GDALDataset* poPrevOvrLevel =
+        (papoOverviews != NULL && iLev >= 2 && iLev <= nResolutions && papoOverviews[iLev-2]) ?
+            papoOverviews[iLev-2] : this;
+    const double dfRatioPrevOvr = static_cast<double>(poPrevOvrLevel->GetRasterBand(1)->GetXSize()) / nOvrXSize;
+    const int nPrevOvrBlockXSize = static_cast<int>( nBlockXSize * dfRatioPrevOvr + 0.5 );
+    const int nPrevOvrBlockYSize = static_cast<int>(nBlockYSize * dfRatioPrevOvr + 0.5 );
+    GByte* pabyPrevOvrMEMDSBuffer = NULL;
+
+    if( !STARTS_WITH_CI(pszResampling, "NEAR"))
+    {
+        pabyPrevOvrMEMDSBuffer = reinterpret_cast<GByte*>(
+            VSIMalloc3( nPrevOvrBlockXSize, nPrevOvrBlockYSize, nBands * nDataTypeSize ) );
+        if (pabyPrevOvrMEMDSBuffer == NULL)
+        {
+            VSIFree(pabyMEMDSBuffer);
+            return CE_Failure;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Iterate over blocks to add data into raster and metadata tables */
+/* -------------------------------------------------------------------- */
+
+    char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
+
+    OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
+
+    CPLErr eErr = CE_None;
+    for( int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks; nBlockYOff++ )
+    {
+        for( int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks; nBlockXOff++ )
+        {
+            GDALDatasetH hPrevOvrMemDS = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Create in-memory tile                                           */
+/* -------------------------------------------------------------------- */
+            int nReqXSize = nBlockXSize;
+            int nReqYSize = nBlockYSize;
+            if ((nBlockXOff+1) * nBlockXSize > nOvrXSize)
+                nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize;
+            if ((nBlockYOff+1) * nBlockYSize > nOvrYSize)
+                nReqYSize = nOvrYSize - nBlockYOff * nBlockYSize;
+
+            if( pabyPrevOvrMEMDSBuffer != NULL )
+            {
+                int nPrevOvrReqXSize =
+                    static_cast<int>( nReqXSize * dfRatioPrevOvr + 0.5 );
+                int nPrevOvrReqYSize =
+                    static_cast<int>(nReqYSize * dfRatioPrevOvr + 0.5 );
+
+                eErr = RasterIO(GF_Read,
+                                nBlockXOff * nBlockXSize * nOvrFactor,
+                                nBlockYOff * nBlockYSize * nOvrFactor,
+                                nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
+                                pabyPrevOvrMEMDSBuffer, nPrevOvrReqXSize, nPrevOvrReqYSize,
+                                eDataType, nBands, NULL,
+                                0, 0, 0, NULL);
+
+                if (eErr != CE_None)
+                {
+                    break;
+                }
+
+                hPrevOvrMemDS = GDALCreate(hMemDriver, "MEM:::",
+                                           nPrevOvrReqXSize, nPrevOvrReqYSize, 0,
+                                           eDataType, NULL);
+
+                if (hPrevOvrMemDS == NULL)
+                {
+                    eErr = CE_Failure;
+                    break;
+                }
+
+                for( int iBand = 0; iBand < nBands; iBand++ )
+                {
+                    char szTmp[64];
+                    memset(szTmp, 0, sizeof(szTmp));
+                    CPLPrintPointer(szTmp,
+                                    pabyPrevOvrMEMDSBuffer + iBand * nDataTypeSize *
+                                    nPrevOvrReqXSize * nPrevOvrReqYSize, sizeof(szTmp));
+                    char** l_papszOptions
+                        = CSLSetNameValue(NULL, "DATAPOINTER", szTmp);
+                    GDALAddBand(hPrevOvrMemDS, eDataType, l_papszOptions);
+                    CSLDestroy(l_papszOptions);
+                }
+            }
+            else
+            {
+                eErr = RasterIO(GF_Read,
+                                nBlockXOff * nBlockXSize * nOvrFactor,
+                                nBlockYOff * nBlockYSize * nOvrFactor,
+                                nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
+                                pabyMEMDSBuffer, nReqXSize, nReqYSize,
+                                eDataType, nBands, NULL,
+                                0, 0, 0, NULL);
+                if (eErr != CE_None)
+                {
+                    break;
+                }
+            }
+
+            GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
+                                              nReqXSize, nReqYSize, 0,
+                                              eDataType, NULL);
+            if (hMemDS == NULL)
+            {
+                eErr = CE_Failure;
+                break;
+            }
+
+            for(int iBand = 0; iBand < nBands; iBand ++)
+            {
+                char szTmp[64];
+                memset(szTmp, 0, sizeof(szTmp));
+                CPLPrintPointer(szTmp,
+                                pabyMEMDSBuffer + iBand * nDataTypeSize *
+                                nReqXSize * nReqYSize, sizeof(szTmp));
+                char** l_papszOptions
+                    = CSLSetNameValue(NULL, "DATAPOINTER", szTmp);
+                GDALAddBand(hMemDS, eDataType, l_papszOptions);
+                CSLDestroy(l_papszOptions);
+            }
+
+            if( hPrevOvrMemDS != NULL )
+            {
+                for(int iBand = 0; iBand < nBands; iBand ++)
+                {
+                    GDALRasterBandH hDstOvrBand = GDALGetRasterBand(hMemDS, iBand+1);
+
+                    eErr = GDALRegenerateOverviews( GDALGetRasterBand(hPrevOvrMemDS, iBand+1),
+                                                    1, &hDstOvrBand,
+                                                    pszResampling,
+                                                    NULL, NULL );
+                    if( eErr != CE_None )
+                        break;
+                }
+
+                GDALClose(hPrevOvrMemDS);
+            }
+
+            GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
+                                        osTempFileName.c_str(), hMemDS, FALSE,
+                                        papszTileDriverOptions, NULL, NULL);
+
+            GDALClose(hMemDS);
+            if (! hOutDS)
+            {
+                eErr = CE_Failure;
+                break;
+            }
+
+            GDALClose(hOutDS);
+
+/* -------------------------------------------------------------------- */
+/*      Insert new entry into raster table                              */
+/* -------------------------------------------------------------------- */
+
+            vsi_l_offset nDataLength;
+            GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
+                                                   &nDataLength, FALSE);
+
+            OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
+            OGR_F_SetFieldBinary(hFeat, 0, static_cast<int>( nDataLength ), pabyData);
+
+            if( OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE )
+                eErr = CE_Failure;
+            /* Query raster ID to set it as the ID of the associated metadata */
+            const int nRasterID = static_cast<int>( OGR_F_GetFID(hFeat) );
+
+            OGR_F_Destroy(hFeat);
+
+            VSIUnlink(osTempFileName.c_str());
+            if( eErr == CE_Failure )
+                break;
+
+/* -------------------------------------------------------------------- */
+/*      Insert new entry into metadata table                            */
+/* -------------------------------------------------------------------- */
+
+            hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
+            OGR_F_SetFID(hFeat, nRasterID);
+            OGR_F_SetFieldString(hFeat, 0, osSourceName);
+            OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
+            OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
+            OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
+            OGR_F_SetFieldDouble(hFeat, 4, dfXResolution);
+            OGR_F_SetFieldDouble(hFeat, 5, dfYResolution);
+
+            const double minx = adfGeoTransform[0] +
+                (nBlockXSize * nBlockXOff) * dfXResolution;
+            const double maxx = adfGeoTransform[0] +
+                (nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution;
+            const double maxy = adfGeoTransform[3] +
+                (nBlockYSize * nBlockYOff) * (-dfYResolution);
+            const double miny = adfGeoTransform[3] +
+                (nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution);
+
+            OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
+            OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
+            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
+            OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
+            OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
+            OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
+            OGR_G_AddPoint_2D(hLinearRing, minx, miny);
+            OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
+
+            OGR_F_SetGeometryDirectly(hFeat, hRectangle);
+
+            if( OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE )
+                eErr = CE_Failure;
+            OGR_F_Destroy(hFeat);
+
+            nBlocks++;
+            if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
+                                            NULL, pProgressData))
+                eErr = CE_Failure;
+        }
+    }
+
+    nLimitOvrCount = -1;
+
+    if (eErr == CE_None)
+        OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
+    else
+        OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
+
+    VSIFree(pabyMEMDSBuffer);
+    VSIFree(pabyPrevOvrMEMDSBuffer);
+
+    CSLDestroy(papszTileDriverOptions);
+    papszTileDriverOptions = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Update raster_pyramids table                                    */
+/* -------------------------------------------------------------------- */
+    if (eErr != CE_None)
+        return eErr;
+
+    OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
+    if (hRasterPyramidsLyr == NULL)
+    {
+        osSQL.Printf   ("CREATE TABLE raster_pyramids ("
+                        "table_prefix TEXT NOT NULL,"
+                        "pixel_x_size DOUBLE NOT NULL,"
+                        "pixel_y_size DOUBLE NOT NULL,"
+                        "tile_count INTEGER NOT NULL)");
+        OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+
+        /* Re-open the DB to take into account the new tables*/
+        OGRReleaseDataSource(hDS);
+
+        hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update);
+
+        hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
+        if (hRasterPyramidsLyr == NULL)
+            return CE_Failure;
+    }
+    OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr);
+
+    /* Insert base resolution into raster_pyramids if not already done */
+    bool bHasBaseResolution = false;
+    osSQL.Printf("SELECT * FROM raster_pyramids WHERE "
+                 "table_prefix = '%s' AND %s",
+                 osTableName.c_str(),
+                 RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
+    hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+    if (hSQLLyr)
+    {
+        OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
+        if (hFeat)
+        {
+            bHasBaseResolution = true;
+            OGR_F_Destroy(hFeat);
+        }
+        OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+    }
+
+    if (!bHasBaseResolution)
+    {
+        osSQL.Printf("SELECT COUNT(*) FROM \"%s\" WHERE %s",
+                      osMetatadataLayer.c_str(),
+                      RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
+
+        int nBlocksMainRes = 0;
+
+        hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
+        if (hSQLLyr)
+        {
+            OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
+            if (hFeat)
+            {
+                nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0);
+                OGR_F_Destroy(hFeat);
+            }
+            OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
+        }
+
+        OGRFeatureH hFeat = OGR_F_Create( hFDefn );
+        OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
+        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), padfXResolutions[0]);
+        OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), padfYResolutions[0]);
+        OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nBlocksMainRes);
+        if( OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE )
+            eErr = CE_Failure;
+        OGR_F_Destroy(hFeat);
+    }
+
+    OGRFeatureH hFeat = OGR_F_Create( hFDefn );
+    OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
+    OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), dfXResolution);
+    OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), dfYResolution);
+    OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nTotalBlocks);
+    if( OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE )
+        eErr = CE_Failure;
+    OGR_F_Destroy(hFeat);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                          IBuildOverviews()                           */
+/************************************************************************/
+
+CPLErr RasterliteDataset::IBuildOverviews( const char * pszResampling,
+                                           int nOverviews, int * panOverviewList,
+                                           int nBandsIn, int * panBandList,
+                                           GDALProgressFunc pfnProgress,
+                                           void * pProgressData )
+{
+    if (nLevel != 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Overviews can only be computed on the base dataset");
+        return CE_Failure;
+    }
+
+    if (osTableName.empty())
+        return CE_Failure;
+
+/* -------------------------------------------------------------------- */
+/*      If we don't have read access, then create the overviews         */
+/*      externally.                                                     */
+/* -------------------------------------------------------------------- */
+    if( GetAccess() != GA_Update )
+    {
+        CPLDebug( "Rasterlite",
+                  "File open for read-only accessing, "
+                  "creating overviews externally." );
+
+        if (nResolutions != 1)
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Cannot add external overviews to a "
+                     "dataset with internal overviews");
+            return CE_Failure;
+        }
+
+        bCheckForExistingOverview = FALSE;
+        CPLErr eErr = GDALDataset::IBuildOverviews(
+                            pszResampling, nOverviews, panOverviewList,
+                            nBandsIn, panBandList, pfnProgress, pProgressData );
+        bCheckForExistingOverview = TRUE;
+        return eErr;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If zero overviews were requested, we need to clear all          */
+/*      existing overviews.                                             */
+/* -------------------------------------------------------------------- */
+    if (nOverviews == 0)
+    {
+        return CleanOverviews();
+    }
+
+    if( nBandsIn != GetRasterCount() )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Generation of overviews in RASTERLITE only"
+                  " supported when operating on all bands.\n"
+                  "Operation failed.\n" );
+        return CE_Failure;
+    }
+
+    const char* pszOvrOptions = CPLGetConfigOption("RASTERLITE_OVR_OPTIONS", NULL);
+    char** papszOptions = (pszOvrOptions) ? CSLTokenizeString2( pszOvrOptions, ",", 0) : NULL;
+    GDALValidateCreationOptions( GetDriver(), papszOptions);
+
+    CPLErr eErr = CE_None;
+    for( int i = 0; i < nOverviews && eErr == CE_None; i++)
+    {
+        if (panOverviewList[i] <= 1)
+            continue;
+
+        eErr = CleanOverviewLevel(panOverviewList[i]);
+        if (eErr == CE_None)
+            eErr = CreateOverviewLevel(pszResampling, panOverviewList[i], papszOptions, pfnProgress, pProgressData);
+
+        ReloadOverviews();
+    }
+
+    CSLDestroy(papszOptions);
+
+    return eErr;
+}
diff --git a/frmts/raw/GNUmakefile b/frmts/raw/GNUmakefile
index e00be7c..31eef38 100644
--- a/frmts/raw/GNUmakefile
+++ b/frmts/raw/GNUmakefile
@@ -7,7 +7,7 @@ OBJ	=	rawdataset.o ehdrdataset.o pauxdataset.o doq1dataset.o \
 		idadataset.o ndfdataset.o dipxdataset.o genbindataset.o \
 		lcpdataset.o eirdataset.o gtxdataset.o loslasdataset.o \
 		ntv2dataset.o ace2dataset.o snodasdataset.o ctable2dataset.o \
-		krodataset.o roipacdataset.o iscedataset.o
+		krodataset.o roipacdataset.o iscedataset.o rrasterdataset.o
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/raw/ace2dataset.cpp b/frmts/raw/ace2dataset.cpp
index 5354a83..8c632a9 100644
--- a/frmts/raw/ace2dataset.cpp
+++ b/frmts/raw/ace2dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ace2dataset.cpp 33925 2016-04-09 19:10:47Z goatbar $
  *
  * Project:  ACE2 Driver
  * Purpose:  Implementation of ACE2 elevation format read support.
@@ -32,7 +31,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: ace2dataset.cpp 33925 2016-04-09 19:10:47Z goatbar $");
+CPL_CVSID("$Id: ace2dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 static const char * const apszCategorySource[] =
 {
@@ -102,8 +101,8 @@ class ACE2Dataset : public GDALPamDataset
                 ACE2Dataset();
     virtual ~ACE2Dataset() {}
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
@@ -123,8 +122,8 @@ class ACE2RasterBand : public RawRasterBand
                            int nXSize, int nYSize);
     virtual ~ACE2RasterBand() {}
 
-    virtual const char *GetUnitType();
-    virtual char **GetCategoryNames();
+    virtual const char *GetUnitType() override;
+    virtual char **GetCategoryNames() override;
 };
 
 /************************************************************************/
@@ -172,14 +171,13 @@ const char *ACE2Dataset::GetProjectionRef()
 /*                          ACE2RasterBand()                            */
 /************************************************************************/
 
-ACE2RasterBand::ACE2RasterBand(VSILFILE* fpRawIn,
-                               GDALDataType eDataTypeIn,
-                               int nXSize, int nYSize) :
-    RawRasterBand( fpRawIn, 0, GDALGetDataTypeSize(eDataTypeIn) / 8,
-                   nXSize * GDALGetDataTypeSize(eDataTypeIn) / 8, eDataTypeIn,
-                   CPL_IS_LSB, nXSize, nYSize, TRUE, TRUE)
-{
-}
+ACE2RasterBand::ACE2RasterBand( VSILFILE* fpRawIn,
+                                GDALDataType eDataTypeIn,
+                                int nXSize, int nYSize) :
+    RawRasterBand( fpRawIn, 0, GDALGetDataTypeSizeBytes(eDataTypeIn),
+                   nXSize * GDALGetDataTypeSizeBytes(eDataTypeIn), eDataTypeIn,
+                   CPL_IS_LSB, nXSize, nYSize, TRUE, TRUE )
+{}
 
 /************************************************************************/
 /*                             GetUnitType()                            */
@@ -240,7 +238,6 @@ GDALDataset *ACE2Dataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
 
     const char* pszBasename = CPLGetBasename(poOpenInfo->pszFilename);
-    int nXSize = 0, nYSize = 0;
 
     if (strlen(pszBasename) < 7)
         return NULL;
@@ -250,9 +247,11 @@ GDALDataset *ACE2Dataset::Open( GDALOpenInfo * poOpenInfo )
     /* e.g. 30S120W_5M.ACE2 */
     char pszLatLonValueString[4] = { '\0' };
     memset(pszLatLonValueString, 0, 4);
+    // cppcheck-suppress redundantCopy
     strncpy(pszLatLonValueString, &pszBasename[0], 2);
     int southWestLat = atoi(pszLatLonValueString);
     memset(pszLatLonValueString, 0, 4);
+    // cppcheck-suppress redundantCopy
     strncpy(pszLatLonValueString, &pszBasename[3], 3);
     int southWestLon = atoi(pszLatLonValueString);
 
@@ -294,30 +293,37 @@ GDALDataset *ACE2Dataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
+    int nXSize = 0;
+    int nYSize = 0;
+
     double dfPixelSize = 0;
     if (sStat.st_size == 180 * 180 * nWordSize)
     {
         /* 5 minute */
-        nXSize = nYSize = 180;
-        dfPixelSize = 5. / 60;
+        nXSize = 180;
+        nYSize = 180;
+        dfPixelSize = 5.0 / 60;
     }
     else if (sStat.st_size == 1800 * 1800 * nWordSize)
     {
         /* 30 s */
-        nXSize = nYSize = 1800;
-        dfPixelSize = 30. / 3600;
+        nXSize = 1800;
+        nYSize = 1800;
+        dfPixelSize = 30.0 / 3600;
     }
     else if (sStat.st_size == 6000 * 6000 * nWordSize)
     {
         /* 9 s */
-        nXSize = nYSize = 6000;
-        dfPixelSize = 9. / 3600;
+        nXSize = 6000;
+        nYSize = 6000;
+        dfPixelSize = 9.0 / 3600;
     }
     else if (sStat.st_size == 18000 * 18000 * nWordSize)
     {
         /* 3 s */
-        nXSize = nYSize = 18000;
-        dfPixelSize = 3. / 3600;
+        nXSize = 18000;
+        nYSize = 18000;
+        dfPixelSize = 3.0 / 3600;
     }
     else
         return NULL;
diff --git a/frmts/raw/atlsci_spheroid.cpp b/frmts/raw/atlsci_spheroid.cpp
index e70cd9d..97c7c1f 100644
--- a/frmts/raw/atlsci_spheroid.cpp
+++ b/frmts/raw/atlsci_spheroid.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: atlsci_spheroid.cpp 33673 2016-03-07 20:40:54Z goatbar $
  *
  * Project:  Spheroid classes
  * Purpose:  Provide spheroid lookup table base classes.
@@ -30,7 +29,7 @@
 #include "atlsci_spheroid.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: atlsci_spheroid.cpp 33673 2016-03-07 20:40:54Z goatbar $");
+CPL_CVSID("$Id: atlsci_spheroid.cpp 34642 2016-07-12 13:05:02Z goatbar $");
 
 /**********************************************************************/
 /* ================================================================== */
@@ -38,116 +37,115 @@ CPL_CVSID("$Id: atlsci_spheroid.cpp 33673 2016-03-07 20:40:54Z goatbar $");
 /* ================================================================== */
 /**********************************************************************/
 
+SpheroidItem::SpheroidItem() :
+    spheroid_name(NULL),
+    equitorial_radius(-1.0),
+    polar_radius(-1.0),
+    inverse_flattening(-1.0)
+{}
 
-void SpheroidItem :: SetValuesByRadii(const char *spheroidname, double eq_radius, double p_radius)
+SpheroidItem::~SpheroidItem()
 {
-    spheroid_name = CPLStrdup(spheroidname);
-    equitorial_radius=eq_radius;
-    polar_radius=p_radius;
-    inverse_flattening=(eq_radius == polar_radius) ? 0 : eq_radius/(eq_radius - polar_radius);
+    CPLFree(spheroid_name);
 }
 
-void SpheroidItem :: SetValuesByEqRadiusAndInvFlattening(const char *spheroidname, double eq_radius, double inverseflattening)
+void SpheroidItem::SetValuesByRadii( const char *spheroidname, double eq_radius,
+                                     double p_radius )
 {
     spheroid_name = CPLStrdup(spheroidname);
-    equitorial_radius=eq_radius;
-    inverse_flattening=inverseflattening;
-    polar_radius=(inverse_flattening == 0) ? eq_radius : eq_radius*(1.0 - (1.0/inverse_flattening));
-}
-SpheroidItem :: SpheroidItem()
-{
-  spheroid_name=NULL;
-  equitorial_radius=-1.0;
-  polar_radius=-1.0;
-  inverse_flattening=-1.0;
+    equitorial_radius = eq_radius;
+    polar_radius = p_radius;
+    inverse_flattening =
+        eq_radius == polar_radius ? 0 : eq_radius/(eq_radius - polar_radius);
 }
 
-SpheroidItem :: ~SpheroidItem()
+void SpheroidItem::SetValuesByEqRadiusAndInvFlattening(
+    const char *spheroidname, double eq_radius, double inverseflattening )
 {
-  if (spheroid_name != NULL)
-      CPLFree(spheroid_name);
+    spheroid_name = CPLStrdup(spheroidname);
+    equitorial_radius = eq_radius;
+    inverse_flattening = inverseflattening;
+    polar_radius =
+        inverse_flattening == 0 ?
+        eq_radius : eq_radius * ( 1.0 - ( 1.0 / inverse_flattening ) );
 }
 
-SpheroidList :: SpheroidList() :
+SpheroidList::SpheroidList() :
     num_spheroids(0),
     epsilonR(0.0),
     epsilonI(0.0)
-{
-}
+{}
 
-SpheroidList :: ~SpheroidList()
-{
-}
+SpheroidList::~SpheroidList() {}
 
-char *SpheroidList :: GetSpheroidNameByRadii( double eq_radius, double polar_radius )
+char *SpheroidList::GetSpheroidNameByRadii( double eq_radius, double polar_radius )
 {
   for( int index = 0; index < num_spheroids; index++ )
   {
     const double er = spheroids[index].equitorial_radius;
     const double pr = spheroids[index].polar_radius;
-    if ((fabs(er - eq_radius) < epsilonR) && (fabs(pr - polar_radius) < epsilonR))
+    if( (fabs(er - eq_radius) < epsilonR) &&
+        (fabs(pr - polar_radius) < epsilonR) )
       return CPLStrdup(spheroids[index].spheroid_name);
   }
 
   return NULL;
-
 }
 
-char *SpheroidList :: GetSpheroidNameByEqRadiusAndInvFlattening( double eq_radius, double inverse_flattening )
+char *SpheroidList::GetSpheroidNameByEqRadiusAndInvFlattening(
+    double eq_radius, double inverse_flattening )
 {
   for( int index = 0; index < num_spheroids; index++ )
   {
     const double er = spheroids[index].equitorial_radius;
     const double invf = spheroids[index].inverse_flattening;
-    if ((fabs(er - eq_radius) < epsilonR) && (fabs(invf - inverse_flattening) < epsilonI))
+    if( (fabs(er - eq_radius) < epsilonR) &&
+        (fabs(invf - inverse_flattening) < epsilonI) )
       return CPLStrdup(spheroids[index].spheroid_name);
   }
 
   return NULL;
 }
 
-double SpheroidList :: GetSpheroidEqRadius( const char *spheroid_name )
+double SpheroidList::GetSpheroidEqRadius( const char *spheroid_name )
 {
   for( int index = 0; index < num_spheroids; index++ )
   {
-    if EQUAL(spheroids[index].spheroid_name,spheroid_name)
+    if( EQUAL(spheroids[index].spheroid_name, spheroid_name) )
       return spheroids[index].equitorial_radius;
   }
 
   return -1.0;
 }
 
-int SpheroidList :: SpheroidInList( const char *spheroid_name )
+int SpheroidList::SpheroidInList( const char *spheroid_name )
 {
   /* Return 1 if the spheroid name is recognized; 0 otherwise */
-  for( int index = 0; index < num_spheroids; index++)
+  for( int index = 0; index < num_spheroids; index++ )
   {
-    if EQUAL(spheroids[index].spheroid_name,spheroid_name)
+    if( EQUAL(spheroids[index].spheroid_name, spheroid_name) )
       return 1;
   }
 
   return 0;
 }
 
-double SpheroidList :: GetSpheroidInverseFlattening( const char *spheroid_name )
+double SpheroidList::GetSpheroidInverseFlattening( const char *spheroid_name )
 {
   for( int index = 0; index < num_spheroids; index++ )
   {
-    if  EQUAL(spheroids[index].spheroid_name,spheroid_name)
+    if( EQUAL(spheroids[index].spheroid_name, spheroid_name) )
       return spheroids[index].inverse_flattening;
   }
 
   return -1.0;
-
 }
 
-double SpheroidList :: GetSpheroidPolarRadius( const char *spheroid_name )
+double SpheroidList::GetSpheroidPolarRadius( const char *spheroid_name )
 {
-  int index=0;
-
-  for(index=0;index<num_spheroids;index++)
+  for( int index = 0; index < num_spheroids; index++ )
   {
-    if (strcmp(spheroids[index].spheroid_name,spheroid_name) == 0)
+    if( strcmp(spheroids[index].spheroid_name, spheroid_name) == 0 )
       return spheroids[index].polar_radius;
   }
 
diff --git a/frmts/raw/atlsci_spheroid.h b/frmts/raw/atlsci_spheroid.h
index 2fa6c20..fb5205b 100644
--- a/frmts/raw/atlsci_spheroid.h
+++ b/frmts/raw/atlsci_spheroid.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: atlsci_spheroid.h 33673 2016-03-07 20:40:54Z goatbar $
+ * $Id: atlsci_spheroid.h 34521 2016-07-02 21:26:43Z goatbar $
  *
  * Project:  Spheroid classes
  * Purpose:  Provide spheroid lookup table base classes.
@@ -33,42 +33,46 @@
 /* ================================================================== */
 /**********************************************************************/
 
-
-/* Maximum number of expected spheroids */
-# define MAX_RECOGNIZED_SPHEROIDS 256
-
 class SpheroidItem
 {
-
-public:
+ public:
    SpheroidItem();
    ~SpheroidItem();
 
    char *spheroid_name;
-   double equitorial_radius;  // TODO: Spelling.
+   double equitorial_radius;  // TODO(schwehr): Spelling.
    double polar_radius;
    double inverse_flattening;
 
-   void SetValuesByRadii(const char *spheroidname, double eq_radius, double p_radius);
-   void SetValuesByEqRadiusAndInvFlattening(const char *spheroidname, double eq_radius, double inverseflattening);
+   void SetValuesByRadii( const char *spheroidname, double eq_radius,
+                          double p_radius);
+   void SetValuesByEqRadiusAndInvFlattening( const char *spheroidname,
+                                             double eq_radius,
+                                             double inverseflattening);
 };
 
 class SpheroidList
 {
-
-public:
+ public:
   int num_spheroids;
-  // Acceptable errors for radii, inverse flattening
+  // Acceptable errors for radii, inverse flattening.
   double epsilonR;
   double epsilonI;
 
+// Maximum number of expected spheroids.
+#define MAX_RECOGNIZED_SPHEROIDS 256
+
+  // TODO(schwehr): Make this a vector.
   SpheroidItem spheroids[MAX_RECOGNIZED_SPHEROIDS];
 
+#undef MAX_RECOGNIZED_SPHEROIDS
+
   SpheroidList();
   ~SpheroidList();
 
   char* GetSpheroidNameByRadii( double eq_radius, double polar_radius );
-  char* GetSpheroidNameByEqRadiusAndInvFlattening( double eq_radius, double inverse_flatting );
+  char* GetSpheroidNameByEqRadiusAndInvFlattening( double eq_radius,
+                                                   double inverse_flatting );
 
   int SpheroidInList( const char *spheroid_name );
   double GetSpheroidEqRadius( const char *spheroid_name );
diff --git a/frmts/raw/btdataset.cpp b/frmts/raw/btdataset.cpp
index c7fb2e8..ebbccf9 100644
--- a/frmts/raw/btdataset.cpp
+++ b/frmts/raw/btdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: btdataset.cpp 34979 2016-08-08 09:30:34Z rouault $
  *
  * Project:  VTP .bt Driver
  * Purpose:  Implementation of VTP .bt elevation format read/write support.
@@ -32,8 +31,10 @@
 #include "gdal_frmts.h"
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
+#include <cmath>
+#include <cstdlib>
 
-CPL_CVSID("$Id: btdataset.cpp 34979 2016-08-08 09:30:34Z rouault $");
+CPL_CVSID("$Id: btdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -60,16 +61,15 @@ class BTDataset : public GDALPamDataset
     float        m_fVscale;
 
   public:
-
-                BTDataset();
+             BTDataset();
     virtual ~BTDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
 
-    virtual void   FlushCache();
+    virtual void   FlushCache() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
@@ -92,13 +92,13 @@ class BTRasterBand : public GDALPamRasterBand
                                  GDALDataType eType );
     virtual ~BTRasterBand() {}
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
 
-    virtual const char* GetUnitType();
-    virtual CPLErr SetUnitType(const char*);
-    virtual double GetNoDataValue( int* = NULL );
-    virtual CPLErr SetNoDataValue( double );
+    virtual const char* GetUnitType() override;
+    virtual CPLErr SetUnitType(const char*) override;
+    virtual double GetNoDataValue( int* = NULL ) override;
+    virtual CPLErr SetNoDataValue( double ) override;
 };
 
 /************************************************************************/
@@ -248,7 +248,6 @@ CPLErr BTRasterBand::IWriteBlock( int nBlockXOff,
     return CE_None;
 }
 
-
 double BTRasterBand::GetNoDataValue( int* pbSuccess /*= NULL */ )
 {
     if(pbSuccess != NULL)
@@ -267,10 +266,10 @@ CPLErr BTRasterBand::SetNoDataValue( double )
 /*                            GetUnitType()                             */
 /************************************************************************/
 
-static bool approx_equals(float a, float b)
+static bool approx_equals( float a, float b )
 {
-    const float epsilon = (float)1e-5;
-    return fabs(a-b) <= epsilon;
+    const float epsilon = 1e-5f;
+    return fabs(a - b) <= epsilon;
 }
 
 const char* BTRasterBand::GetUnitType(void)
@@ -309,7 +308,6 @@ CPLErr BTRasterBand::SetUnitType(const char* psz)
     else
         return CE_Failure;
 
-
     float fScale = ds.m_fVscale;
 
     CPL_LSBPTR32(&fScale);
@@ -345,6 +343,7 @@ BTDataset::BTDataset() :
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+    memset( abyHeader, 0, sizeof(abyHeader) );
 }
 
 /************************************************************************/
@@ -413,19 +412,18 @@ CPLErr BTDataset::SetGeoTransform( double *padfTransform )
     if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  ".bt format does not support rotational coefficients in geotransform, ignoring." );
+                  ".bt format does not support rotational coefficients "
+                  "in geotransform, ignoring." );
         eErr = CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Compute bounds, and update header info.                         */
 /* -------------------------------------------------------------------- */
-    double dfLeft, dfRight, dfTop, dfBottom;
-
-    dfLeft = adfGeoTransform[0];
-    dfRight = dfLeft + adfGeoTransform[1] * nRasterXSize;
-    dfTop = adfGeoTransform[3];
-    dfBottom = dfTop + adfGeoTransform[5] * nRasterYSize;
+    const double dfLeft = adfGeoTransform[0];
+    const double dfRight = dfLeft + adfGeoTransform[1] * nRasterXSize;
+    const double dfTop = adfGeoTransform[3];
+    const double dfBottom = dfTop + adfGeoTransform[5] * nRasterYSize;
 
     memcpy( abyHeader + 28, &dfLeft, 8 );
     memcpy( abyHeader + 36, &dfRight, 8 );
@@ -473,20 +471,23 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
 /*      Parse projection.                                               */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oSRS( pszProjection );
-    GInt16  nShortTemp;
+    GInt16  nShortTemp = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Linear units.                                                   */
 /* -------------------------------------------------------------------- */
     if( oSRS.IsGeographic() )
-        nShortTemp = 0;
+    {
+        // nShortTemp = 0;
+    }
     else
     {
-        double dfLinear = oSRS.GetLinearUnits();
+        const double dfLinear = oSRS.GetLinearUnits();
 
-        if( ABS(dfLinear - 0.3048) < 0.0000001 )
+        if( std::abs(dfLinear - 0.3048) < 0.0000001 )
             nShortTemp = 2;
-        else if( ABS(dfLinear - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 )
+        else if( std::abs(dfLinear - CPLAtof(SRS_UL_US_FOOT_CONV))
+                 < 0.00000001 )
             nShortTemp = 3;
         else
             nShortTemp = 1;
@@ -498,7 +499,7 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
 /* -------------------------------------------------------------------- */
 /*      UTM Zone                                                        */
 /* -------------------------------------------------------------------- */
-    int bNorth;
+    int bNorth = FALSE;
 
     nShortTemp = (GInt16) oSRS.GetUTMZone( &bNorth );
     if( bNorth )
@@ -512,7 +513,8 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
 /* -------------------------------------------------------------------- */
     if( oSRS.GetAuthorityName( "GEOGCS|DATUM" ) != NULL
         && EQUAL(oSRS.GetAuthorityName( "GEOGCS|DATUM" ),"EPSG") )
-        nShortTemp = (GInt16) (atoi(oSRS.GetAuthorityCode( "GEOGCS|DATUM" )) + 2000);
+        nShortTemp = static_cast<GInt16>(
+            atoi(oSRS.GetAuthorityCode( "GEOGCS|DATUM" )) + 2000);
     else
         nShortTemp = -2;
     nShortTemp = CPL_LSBWORD16( nShortTemp ); /* datum unknown */
@@ -539,7 +541,6 @@ CPLErr BTDataset::SetProjection( const char *pszNewProjection )
     return eErr;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -559,42 +560,42 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create the dataset.                                             */
 /* -------------------------------------------------------------------- */
-    BTDataset  *poDS = new BTDataset();
+    BTDataset *poDS = new BTDataset();
 
     memcpy( poDS->abyHeader, poOpenInfo->pabyHeader, 256 );
 
 /* -------------------------------------------------------------------- */
 /*      Get the version.                                                */
 /* -------------------------------------------------------------------- */
-    char szVersion[4];
+    char szVersion[4] = {};
 
     strncpy( szVersion, (char *) (poDS->abyHeader + 7), 3 );
     szVersion[3] = '\0';
-    poDS->nVersionCode = (int) (CPLAtof(szVersion) * 10);
+    poDS->nVersionCode = static_cast<int>(CPLAtof(szVersion) * 10);
 
 /* -------------------------------------------------------------------- */
 /*      Extract core header information, being careful about the        */
 /*      version.                                                        */
 /* -------------------------------------------------------------------- */
-    GInt32 nIntTemp;
-    GInt16 nDataSize;
-    GDALDataType eType;
 
+    GInt32 nIntTemp = 0;
     memcpy( &nIntTemp, poDS->abyHeader + 10, 4 );
     poDS->nRasterXSize = CPL_LSBWORD32( nIntTemp );
 
     memcpy( &nIntTemp, poDS->abyHeader + 14, 4 );
     poDS->nRasterYSize = CPL_LSBWORD32( nIntTemp );
 
-    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
+    if( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) )
     {
         delete poDS;
         return NULL;
     }
 
+    GInt16 nDataSize = 0;
     memcpy( &nDataSize, poDS->abyHeader+18, 2 );
     nDataSize = CPL_LSBWORD16( nDataSize );
 
+    GDALDataType eType = GDT_Unknown;
     if( poDS->abyHeader[20] != 0 && nDataSize == 4 )
         eType = GDT_Float32;
     else if( poDS->abyHeader[20] == 0 && nDataSize == 4 )
@@ -629,26 +630,24 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         const char  *pszPrjFile = CPLResetExtension( poOpenInfo->pszFilename,
                                                      "prj" );
-        VSILFILE *fp;
-
-        fp = VSIFOpenL( pszPrjFile, "rt" );
+        VSILFILE *fp = VSIFOpenL( pszPrjFile, "rt" );
         if( fp != NULL )
         {
-            char *pszBuffer, *pszBufPtr;
-            int  nBufMax = 10000;
-            int nBytes;
+            const int nBufMax = 10000;
 
-            pszBuffer = (char *) CPLMalloc(nBufMax);
-            nBytes = static_cast<int>(VSIFReadL( pszBuffer, 1, nBufMax-1, fp ));
+            char *pszBuffer = static_cast<char *>(CPLMalloc(nBufMax));
+            const int nBytes =
+                static_cast<int>(VSIFReadL( pszBuffer, 1, nBufMax-1, fp ));
             CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
             pszBuffer[nBytes] = '\0';
 
-            pszBufPtr = pszBuffer;
+            char *pszBufPtr = pszBuffer;
             if( oSRS.importFromWkt( &pszBufPtr ) != OGRERR_NONE )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                          "Unable to parse .prj file, coordinate system missing." );
+                          "Unable to parse .prj file, "
+                          "coordinate system missing." );
             }
             CPLFree( pszBuffer );
         }
@@ -659,19 +658,20 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( oSRS.GetRoot() == NULL )
     {
-        GInt16 nUTMZone, nDatum, nHUnits;
-
+        GInt16 nUTMZone = 0;
         memcpy( &nUTMZone, poDS->abyHeader + 24, 2 );
         nUTMZone = CPL_LSBWORD16( nUTMZone );
 
+        GInt16 nDatum = 0;
         memcpy( &nDatum, poDS->abyHeader + 26, 2 );
         nDatum = CPL_LSBWORD16( nDatum );
 
+        GInt16 nHUnits = 0;
         memcpy( &nHUnits, poDS->abyHeader + 22, 2 );
         nHUnits = CPL_LSBWORD16( nHUnits );
 
         if( nUTMZone != 0 )
-            oSRS.SetUTM( ABS(nUTMZone), nUTMZone > 0 );
+            oSRS.SetUTM( std::abs(static_cast<int>(nUTMZone)), nUTMZone > 0 );
         else if( nHUnits != 0 )
             oSRS.SetLocalCS( "Unknown" );
 
@@ -736,17 +736,19 @@ GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poDS->nVersionCode >= 11 )
     {
-        double dfLeft, dfRight, dfTop, dfBottom;
-
+        double dfLeft = 0.0;
         memcpy( &dfLeft, poDS->abyHeader + 28, 8 );
         CPL_LSBPTR64( &dfLeft );
 
+        double dfRight = 0.0;
         memcpy( &dfRight, poDS->abyHeader + 36, 8 );
         CPL_LSBPTR64( &dfRight );
 
+        double dfBottom = 0.0;
         memcpy( &dfBottom, poDS->abyHeader + 44, 8 );
         CPL_LSBPTR64( &dfBottom );
 
+        double dfTop = 0.0;
         memcpy( &dfTop, poDS->abyHeader + 52, 8 );
         CPL_LSBPTR64( &dfTop );
 
@@ -822,8 +824,8 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
     if( eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_Float32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create .bt dataset with an illegal\n"
-              "data type (%s), only Int16, Int32 and Float32 supported.\n",
+              "Attempt to create .bt dataset with an illegal "
+              "data type (%s), only Int16, Int32 and Float32 supported.",
               GDALGetDataTypeName(eType) );
 
         return NULL;
@@ -831,9 +833,10 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
 
     if( nBands != 1 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-               "Attempt to create .bt dataset with %d bands, only 1 supported",
-                  nBands );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Attempt to create .bt dataset with %d bands, only 1 supported",
+            nBands );
 
         return NULL;
     }
@@ -846,7 +849,7 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
+                  "Attempt to create file `%s' failed.",
                   pszFilename );
         return NULL;
     }
@@ -854,20 +857,18 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Setup base header.                                              */
 /* -------------------------------------------------------------------- */
-    unsigned char abyHeader[256];
-    GInt32 nTemp;
-    GInt16 nShortTemp;
+    unsigned char abyHeader[256] = {};
 
-    memset( abyHeader, 0, 256 );
     memcpy( abyHeader, "binterr1.3", 10 );
 
-    nTemp = CPL_LSBWORD32( nXSize );
+    GInt32 nTemp = CPL_LSBWORD32( nXSize );
     memcpy( abyHeader+10, &nTemp, 4 );
 
     nTemp = CPL_LSBWORD32( nYSize );
     memcpy( abyHeader+14, &nTemp, 4 );
 
-    nShortTemp = (GInt16) (CPL_LSBWORD16( (GInt16)(GDALGetDataTypeSize( eType ) / 8 )) );
+    GInt16 nShortTemp = static_cast<GInt16>(
+         CPL_LSBWORD16( (GInt16)(GDALGetDataTypeSize( eType ) / 8 )) );
     memcpy( abyHeader + 18, &nShortTemp, 2 );
 
     if( eType == GDT_Float32 )
@@ -887,7 +888,10 @@ GDALDataset *BTDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Set dummy extents.                                              */
 /* -------------------------------------------------------------------- */
-    double dfLeft=0, dfRight=nXSize, dfTop=nYSize, dfBottom=0;
+    double dfLeft = 0.0;
+    double dfRight = nXSize;
+    double dfTop = nYSize;
+    double dfBottom = 0.0;
 
     memcpy( abyHeader + 28, &dfLeft, 8 );
     memcpy( abyHeader + 36, &dfRight, 8 );
diff --git a/frmts/raw/cpgdataset.cpp b/frmts/raw/cpgdataset.cpp
index 43a4f78..832639d 100644
--- a/frmts/raw/cpgdataset.cpp
+++ b/frmts/raw/cpgdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpgdataset.cpp 33928 2016-04-09 19:15:33Z goatbar $
  *
  * Project:  Polarimetric Workstation
  * Purpose:  Convair PolGASP data (.img/.hdr format).
@@ -33,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: cpgdataset.cpp 33928 2016-04-09 19:15:33Z goatbar $");
+CPL_CVSID("$Id: cpgdataset.cpp 36763 2016-12-09 22:10:55Z rouault $");
 
 enum Interleave { BSQ, BIL, BIP };
 
@@ -67,7 +66,9 @@ class CPGDataset : public RawDataset
     static int  AdjustFilename( char **, const char *, const char * );
     static int FindType1( const char *pszWorkname );
     static int FindType2( const char *pszWorkname );
+#ifdef notdef
     static int FindType3( const char *pszWorkname );
+#endif
     static GDALDataset *InitializeType1Or2Dataset( const char *pszWorkname );
 #ifdef notdef
     static GDALDataset *InitializeType3Dataset( const char *pszWorkname );
@@ -78,12 +79,12 @@ class CPGDataset : public RawDataset
                 CPGDataset();
     virtual ~CPGDataset();
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -152,7 +153,7 @@ class SIRC_QSLCRasterBand : public GDALRasterBand
                    SIRC_QSLCRasterBand( CPGDataset *, int, GDALDataType );
     virtual ~SIRC_QSLCRasterBand() {}
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 static const int M11 = 0;
@@ -182,16 +183,15 @@ class CPG_STOKESRasterBand : public GDALRasterBand
 {
     friend class CPGDataset;
 
-    int nBand;
     int bNativeOrder;
 
   public:
-                   CPG_STOKESRasterBand( GDALDataset *poDS, int nBand,
+                   CPG_STOKESRasterBand( GDALDataset *poDS,
                                          GDALDataType eType,
                                          int bNativeOrder );
     virtual ~CPG_STOKESRasterBand() {};
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -208,14 +208,12 @@ int CPGDataset::AdjustFilename( char **pszFilename,
                                 const char *pszExtension )
 
 {
-    const char *pszNewName;
-
-    /* eventually we should handle upper/lower case ... */
-
+    // TODO: Eventually we should handle upper/lower case.
     if ( EQUAL(pszPolarization,"stokes") )
     {
-        pszNewName = CPLResetExtension((const char *) *pszFilename,
-                                     (const char *) pszExtension);
+        const char *pszNewName =
+            CPLResetExtension((const char *) *pszFilename,
+                              (const char *) pszExtension);
         CPLFree(*pszFilename);
         *pszFilename = CPLStrdup(pszNewName);
     }
@@ -232,15 +230,17 @@ int CPGDataset::AdjustFilename( char **pszFilename,
           return FALSE;
 
         strncpy( subptr, pszPolarization, 2);
-        pszNewName = CPLResetExtension((const char *) *pszFilename,
-                                                (const char *) pszExtension);
+        const char *pszNewName =
+            CPLResetExtension((const char *) *pszFilename,
+                              (const char *) pszExtension);
         CPLFree(*pszFilename);
         *pszFilename = CPLStrdup(pszNewName);
     }
     else
     {
-        pszNewName = CPLResetExtension((const char *) *pszFilename,
-                                        (const char *) pszExtension);
+        const char *pszNewName =
+            CPLResetExtension((const char *) *pszFilename,
+                              (const char *) pszExtension);
         CPLFree(*pszFilename);
         *pszFilename = CPLStrdup(pszNewName);
     }
@@ -299,6 +299,7 @@ int CPGDataset::FindType2( const char *pszFilename )
   return !bNotFound;
 }
 
+#ifdef notdef
 int CPGDataset::FindType3( const char *pszFilename )
 {
   const int nNameLen = static_cast<int>(strlen( pszFilename ));
@@ -319,6 +320,7 @@ int CPGDataset::FindType3( const char *pszFilename )
 
   return !bNotFound;
 }
+#endif
 
 /************************************************************************/
 /*                        LoadStokesLine()                              */
@@ -385,7 +387,6 @@ CPLErr CPGDataset::LoadStokesLine( int iLine, int bNativeOrder )
                 padfStokesMatrix = NULL;
                 nLoadedStokesLine = -1;
                 return CE_Failure;
-
             }
         }
     }
@@ -411,7 +412,6 @@ CPLErr CPGDataset::LoadStokesLine( int iLine, int bNativeOrder )
                 padfStokesMatrix = NULL;
                 nLoadedStokesLine = -1;
                 return CE_Failure;
-
             }
         }
     }
@@ -443,13 +443,19 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
 
     /* Parameters required for pseudo-geocoding.  GCPs map */
     /* slant range to ground range at 16 points.           */
-    int iGeoParamsFound = 0, itransposed = 0;
-    double dfaltitude = 0.0, dfnear_srd = 0.0;
-    double dfsample_size = 0.0, dfsample_size_az = 0.0;
+    int iGeoParamsFound = 0;
+    int itransposed = 0;
+    double dfaltitude = 0.0;
+    double dfnear_srd = 0.0;
+    double dfsample_size = 0.0;
+    double dfsample_size_az = 0.0;
 
     /* Parameters in geogratis geocoded images */
-    int iUTMParamsFound = 0, iUTMZone=0 /* , iCorner=0 */;
-    double dfnorth = 0.0, dfeast = 0.0;
+    int iUTMParamsFound = 0;
+    int iUTMZone = 0;
+    // int iCorner = 0;
+    double dfnorth = 0.0;
+    double dfeast = 0.0;
 
     char* pszWorkname = CPLStrdup(pszFilename);
     AdjustFilename( &pszWorkname, "hh", "hdr" );
@@ -603,9 +609,8 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
         }
         for( int iBand = 0; iBand < 4; iBand++ )
         {
-            SIRC_QSLCRasterBand *poBand;
-
-            poBand = new SIRC_QSLCRasterBand( poDS, iBand+1, GDT_CFloat32 );
+            SIRC_QSLCRasterBand *poBand =
+                new SIRC_QSLCRasterBand( poDS, iBand+1, GDT_CFloat32 );
             poDS->SetBand( iBand+1, poBand );
             poBand->SetMetadataItem( "POLARIMETRIC_INTERP",
                                  apszPolarizations[iBand] );
@@ -657,7 +662,8 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
         double dfnorth_center;
         if (itransposed == 1)
         {
-            printf( "Warning: did not have a convair SIRC-style test dataset\n"
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Did not have a convair SIRC-style test dataset\n"
                     "with transposed=1 for testing.  Georeferencing may be "
                     "wrong.\n" );
             dfnorth_center = dfnorth - nSamples*dfsample_size/2.0;
@@ -718,7 +724,6 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
                 /* -1 so that 0,0 maps to largest Y */
                 dfgcpY = -1*sqrt( dftemp*dftemp - dfaltitude*dfaltitude );
                 dfgcpX = dfgcpPixel*dfsample_size_az;
-
             }
             else
             {
@@ -736,7 +741,6 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
                 dftemp = dfnear_srd + (dfsample_size*dfgcpPixel);
                 dfgcpX = sqrt( dftemp*dftemp - dfaltitude*dfaltitude );
                 dfgcpY = (nLines - dfgcpLine)*dfsample_size_az;
-
             }
             poDS->pasGCPList[ngcp].dfGCPX = dfgcpX;
             poDS->pasGCPList[ngcp].dfGCPY = dfgcpY;
@@ -747,14 +751,12 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
 
             CPLFree(poDS->pasGCPList[ngcp].pszId);
             poDS->pasGCPList[ngcp].pszId = CPLStrdup( szID );
-
         }
 
         CPLFree(poDS->pszGCPProjection);
         poDS->pszGCPProjection = CPLStrdup(
             "LOCAL_CS[\"Ground range view / unreferenced meters\","
             "UNIT[\"Meter\",1.0]]");
-
     }
 
     CPLFree(pszWorkname);
@@ -765,14 +767,22 @@ GDALDataset* CPGDataset::InitializeType1Or2Dataset( const char *pszFilename )
 #ifdef notdef
 GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
 {
-    int iBytesPerPixel = 0, iInterleave=-1;
-    int nLines = 0, nSamples = 0, nBands = 0;
+    int iBytesPerPixel = 0;
+    int iInterleave = -1;
+    int nLines = 0;
+    int nSamples = 0;
+    int nBands = 0;
     int nError = 0;
 
     /* Parameters in geogratis geocoded images */
-    int iUTMParamsFound = 0, iUTMZone=0;
-    double dfnorth = 0.0, dfeast = 0.0, dfOffsetX = 0.0, dfOffsetY = 0.0;
-    double dfxsize = 0.0, dfysize = 0.0;
+    int iUTMParamsFound = 0;
+    int iUTMZone = 0;
+    double dfnorth = 0.0;
+    double dfeast = 0.0;
+    double dfOffsetX = 0.0;
+    double dfOffsetY = 0.0;
+    double dfxsize = 0.0;
+    double dfysize = 0.0;
 
     char* pszWorkname = CPLStrdup(pszFilename);
     AdjustFilename( &pszWorkname, "stokes", "img_def" );
@@ -976,7 +986,7 @@ GDALDataset *CPGDataset::InitializeType3Dataset( const char *pszFilename )
     for( int iBand = 0; iBand < 16; iBand++ )
     {
         CPG_STOKESRasterBand *poBand
-            = new CPG_STOKESRasterBand( poDS, iBand+1, GDT_CFloat32,
+            = new CPG_STOKESRasterBand( poDS, GDT_CFloat32,
                                         !CPL_IS_LSB );
         poDS->SetBand( iBand+1, poBand );
     }
@@ -1096,7 +1106,7 @@ GDALDataset *CPGDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     /* Read the header info and create the dataset */
-    CPGDataset *poDS;
+    CPGDataset *poDS = NULL;
 
 #ifdef notdef
     if ( CPGType < 3 )
@@ -1107,11 +1117,10 @@ GDALDataset *CPGDataset::Open( GDALOpenInfo * poOpenInfo )
     else
       poDS = reinterpret_cast<CPGDataset *>(
           InitializeType3Dataset( poOpenInfo->pszFilename ) );
-    if (poDS == NULL)
+    if( poDS == NULL )
         return NULL;
 #endif
 
-
 /* -------------------------------------------------------------------- */
 /*      Check for overviews.                                            */
 /* -------------------------------------------------------------------- */
@@ -1325,28 +1334,28 @@ CPLErr SIRC_QSLCRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /*                        CPG_STOKESRasterBand()                        */
 /************************************************************************/
 
-CPG_STOKESRasterBand::CPG_STOKESRasterBand( GDALDataset *poDSIn, int nBandIn,
+CPG_STOKESRasterBand::CPG_STOKESRasterBand( GDALDataset *poDSIn,
                                             GDALDataType eType,
                                             int bNativeOrderIn ) :
-    nBand(nBandIn),
     bNativeOrder(bNativeOrderIn)
 {
-    static const char * const apszPolarizations[16] = { "Covariance_11",
-                                                 "Covariance_12",
-                                                 "Covariance_13",
-                                                 "Covariance_14",
-                                                 "Covariance_21",
-                                                 "Covariance_22",
-                                                 "Covariance_23",
-                                                 "Covariance_24",
-                                                 "Covariance_31",
-                                                 "Covariance_32",
-                                                 "Covariance_33",
-                                                 "Covariance_34",
-                                                 "Covariance_41",
-                                                 "Covariance_42",
-                                                 "Covariance_43",
-                                                 "Covariance_44" };
+    static const char * const apszPolarizations[16] = {
+        "Covariance_11",
+        "Covariance_12",
+        "Covariance_13",
+        "Covariance_14",
+        "Covariance_21",
+        "Covariance_22",
+        "Covariance_23",
+        "Covariance_24",
+        "Covariance_31",
+        "Covariance_32",
+        "Covariance_33",
+        "Covariance_34",
+        "Covariance_41",
+        "Covariance_42",
+        "Covariance_43",
+        "Covariance_44" };
 
     poDS = poDSIn;
     eDataType = eType;
@@ -1553,7 +1562,6 @@ CPLErr CPG_STOKESRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             m33 += step;
             m44 += step;
         }
-
     }
     else if ( nBand == 12 ) /* C34 */
     {
diff --git a/frmts/raw/ctable2dataset.cpp b/frmts/raw/ctable2dataset.cpp
index d73b73c..9ad84c9 100644
--- a/frmts/raw/ctable2dataset.cpp
+++ b/frmts/raw/ctable2dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  Horizontal Datum Formats
  * Purpose:  Implementation of the CTable2 format, a PROJ.4 specific format
@@ -33,7 +32,7 @@
 #include "ogr_srs_api.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ctable2dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -52,10 +51,10 @@ class CTable2Dataset : public RawDataset
                 CTable2Dataset();
     virtual ~CTable2Dataset();
 
-    virtual CPLErr SetGeoTransform( double * padfTransform );
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef();
-    virtual void   FlushCache(void);
+    virtual CPLErr SetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef() override;
+    virtual void   FlushCache(void) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -76,7 +75,9 @@ class CTable2Dataset : public RawDataset
 
 CTable2Dataset::CTable2Dataset() :
     fpImage(NULL)
-{}
+{
+    memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
+}
 
 /************************************************************************/
 /*                            ~CTable2Dataset()                          */
@@ -315,7 +316,6 @@ CPLErr CTable2Dataset::SetGeoTransform( double * padfTransform )
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
diff --git a/frmts/raw/dipxdataset.cpp b/frmts/raw/dipxdataset.cpp
index 7f16c20..f8c4580 100644
--- a/frmts/raw/dipxdataset.cpp
+++ b/frmts/raw/dipxdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dipxdataset.cpp 33930 2016-04-09 19:28:36Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implementation for ELAS DIPEx format variant.
@@ -33,11 +32,12 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
+#include <cmath>
 #include <algorithm>
 
 using std::fill;
 
-CPL_CVSID("$Id: dipxdataset.cpp 33930 2016-04-09 19:28:36Z goatbar $");
+CPL_CVSID("$Id: dipxdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 typedef struct {
     GInt32      NBIH;   /* bytes in header, normally 1024 */
@@ -88,9 +88,9 @@ class DIPExDataset : public GDALPamDataset
                  DIPExDataset();
     virtual ~DIPExDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * ) override;
 
-    virtual const char *GetProjectionRef( void );
+    virtual const char *GetProjectionRef( void ) override;
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
@@ -100,12 +100,10 @@ class DIPExDataset : public GDALPamDataset
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            DIPExDataset()                             */
 /************************************************************************/
 
-
 DIPExDataset::DIPExDataset() :
     fp(NULL),
     eRasterDataType(GDT_Unknown)
@@ -311,7 +309,7 @@ GDALDataset *DIPExDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[2] = 0.0;
         poDS->adfGeoTransform[3] = poDS->sHeader.YOffset;
         poDS->adfGeoTransform[4] = 0.0;
-        poDS->adfGeoTransform[5] = -1.0 * ABS(poDS->sHeader.YPixSize);
+        poDS->adfGeoTransform[5] = -1.0 * std::abs(poDS->sHeader.YPixSize);
 
         poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5;
         poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5;
diff --git a/frmts/raw/doq1dataset.cpp b/frmts/raw/doq1dataset.cpp
index 08b2b75..7344cef 100644
--- a/frmts/raw/doq1dataset.cpp
+++ b/frmts/raw/doq1dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: doq1dataset.cpp 33931 2016-04-09 19:44:09Z goatbar $
  *
  * Project:  USGS DOQ Driver (First Generation Format)
  * Purpose:  Implementation of DOQ1Dataset
@@ -32,7 +31,7 @@
 #include "cpl_string.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: doq1dataset.cpp 33931 2016-04-09 19:44:09Z goatbar $");
+CPL_CVSID("$Id: doq1dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 static const char UTM_FORMAT[] =
     "PROJCS[\"%s / UTM zone %dN\",GEOGCS[%s,PRIMEM[\"Greenwich\",0],"
@@ -113,8 +112,10 @@ class DOQ1Dataset : public RawDataset
 {
     VSILFILE    *fpImage;       // image data file.
 
-    double      dfULX, dfULY;
-    double      dfXPixelSize, dfYPixelSize;
+    double      dfULX;
+    double      dfULY;
+    double      dfXPixelSize;
+    double      dfYPixelSize;
 
     char        *pszProjection;
 
@@ -122,8 +123,8 @@ class DOQ1Dataset : public RawDataset
                 DOQ1Dataset();
                 ~DOQ1Dataset();
 
-    CPLErr      GetGeoTransform( double * padfTransform );
-    const char  *GetProjectionRef( void );
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
+    const char  *GetProjectionRef( void ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -139,7 +140,7 @@ DOQ1Dataset::DOQ1Dataset() :
     dfXPixelSize(0.0),
     dfYPixelSize(0.0),
     pszProjection(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                            ~DOQ1Dataset()                            */
diff --git a/frmts/raw/doq2dataset.cpp b/frmts/raw/doq2dataset.cpp
index c9eb7bc..5c250c8 100644
--- a/frmts/raw/doq2dataset.cpp
+++ b/frmts/raw/doq2dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: doq2dataset.cpp 33932 2016-04-09 20:01:39Z goatbar $
  *
  * Project:  USGS DOQ Driver (Second Generation Format)
  * Purpose:  Implementation of DOQ2Dataset
@@ -32,7 +31,7 @@
 #include "gdal_frmts.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: doq2dataset.cpp 33932 2016-04-09 20:01:39Z goatbar $");
+CPL_CVSID("$Id: doq2dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 static const char UTM_FORMAT[] =
     "PROJCS[\"%s / UTM zone %dN\",GEOGCS[%s,PRIMEM[\"Greenwich\",0],"
@@ -76,8 +75,8 @@ class DOQ2Dataset : public RawDataset
                 DOQ2Dataset();
                 ~DOQ2Dataset();
 
-    CPLErr      GetGeoTransform( double * padfTransform );
-    const char  *GetProjectionRef( void );
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
+    const char  *GetProjectionRef( void ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -169,7 +168,8 @@ GDALDataset *DOQ2Dataset::Open( GDALOpenInfo * poOpenInfo )
     char *pszQuadname = NULL;
     char *pszQuadquad = NULL;
     char *pszState = NULL;
-    int nZone=0, nProjType=0;
+    int nZone = 0;
+    int nProjType = 0;
     int nSkipBytes = 0;
     int nBandCount = 0;
     double dfULXMap=0.0;
diff --git a/frmts/raw/ehdrdataset.cpp b/frmts/raw/ehdrdataset.cpp
index 33cb5d5..d69afc4 100644
--- a/frmts/raw/ehdrdataset.cpp
+++ b/frmts/raw/ehdrdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ehdrdataset.cpp 33862 2016-04-02 11:17:23Z goatbar $
  *
  * Project:  ESRI .hdr Driver
  * Purpose:  Implementation of EHdrDataset
@@ -28,12 +27,37 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ehdrdataset.h"
+#include "rawdataset.h"
+
+#include <cctype>
+#include <cerrno>
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <limits>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
 #include "ogr_spatialref.h"
-#include "rawdataset.h"
 
-CPL_CVSID("$Id: ehdrdataset.cpp 33862 2016-04-02 11:17:23Z goatbar $");
+CPL_CVSID("$Id: ehdrdataset.cpp 37531 2017-03-01 04:56:18Z goatbar $");
 
 static const int HAS_MIN_FLAG = 0x1;
 static const int HAS_MAX_FLAG = 0x2;
@@ -43,125 +67,17 @@ static const int HAS_ALL_FLAGS =
     HAS_MIN_FLAG | HAS_MAX_FLAG | HAS_MEAN_FLAG | HAS_STDDEV_FLAG;
 
 /************************************************************************/
-/* ==================================================================== */
-/*                       EHdrDataset                                    */
-/* ==================================================================== */
-/************************************************************************/
-
-class EHdrRasterBand;
-
-class EHdrDataset : public RawDataset
-{
-    friend class EHdrRasterBand;
-
-    VSILFILE   *fpImage;  // image data file.
-
-    CPLString   osHeaderExt;
-
-    int         bGotTransform;
-    double      adfGeoTransform[6];
-    char       *pszProjection;
-
-    int         bHDRDirty;
-    char      **papszHDR;
-
-    int         bCLRDirty;
-
-    CPLErr      ReadSTX();
-    CPLErr      RewriteSTX();
-    CPLErr      RewriteHDR();
-    void        ResetKeyValue( const char *pszKey, const char *pszValue );
-    const char *GetKeyValue( const char *pszKey, const char *pszDefault = "" );
-    void        RewriteColorTable( GDALColorTable * );
-
-  public:
-    EHdrDataset();
-    virtual ~EHdrDataset();
-
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual CPLErr SetGeoTransform( double *padfTransform );
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-
-    virtual char **GetFileList();
-
-    static GDALDataset *Open( GDALOpenInfo * );
-    static GDALDataset *Create( const char * pszFilename,
-                                int nXSize, int nYSize, int nBands,
-                                GDALDataType eType, char ** papszParmList );
-    static GDALDataset *CreateCopy( const char * pszFilename,
-                                    GDALDataset * poSrcDS,
-                                    int bStrict, char ** papszOptions,
-                                    GDALProgressFunc pfnProgress,
-                                    void * pProgressData );
-    static CPLString GetImageRepFilename(const char* pszFilename);
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                          EHdrRasterBand                              */
-/* ==================================================================== */
-/************************************************************************/
-
-class EHdrRasterBand : public RawRasterBand
-{
-   friend class EHdrDataset;
-
-    int            nBits;
-    vsi_l_offset   nStartBit;
-    int            nPixelOffsetBits;
-    vsi_l_offset   nLineOffsetBits;
-
-    int            bNoDataSet;
-    double         dfNoData;
-    double         dfMin;
-    double         dfMax;
-    double         dfMean;
-    double         dfStdDev;
-
-    int            minmaxmeanstddev;
-
-    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
-                              void *, int, int, GDALDataType,
-                              GSpacing nPixelSpace,
-                              GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
-
-  public:
-    EHdrRasterBand( GDALDataset *poDS, int nBand, VSILFILE * fpRaw,
-                    vsi_l_offset nImgOffset, int nPixelOffset,
-                    int nLineOffset,
-                    GDALDataType eDataType, int bNativeOrder,
-                    int nBits);
-    virtual ~EHdrRasterBand() {}
-
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
-
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum(int *pbSuccess = NULL );
-    virtual CPLErr GetStatistics( int bApproxOK, int bForce,
-                                  double *pdfMin, double *pdfMax,
-                                  double *pdfMean, double *pdfStdDev );
-    virtual CPLErr SetStatistics( double dfMin, double dfMax,
-                                  double dfMean, double dfStdDev );
-    virtual CPLErr SetColorTable( GDALColorTable *poNewCT );
-
-};
-
-/************************************************************************/
 /*                           EHdrRasterBand()                           */
 /************************************************************************/
 
 EHdrRasterBand::EHdrRasterBand( GDALDataset *poDSIn,
-                                int nBandIn, VSILFILE * fpRawIn,
+                                int nBandIn, VSILFILE *fpRawIn,
                                 vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
                                 int nLineOffsetIn,
                                 GDALDataType eDataTypeIn, int bNativeOrderIn,
                                 int nBitsIn) :
-  RawRasterBand( poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
-                 nLineOffsetIn, eDataTypeIn, bNativeOrderIn, TRUE ),
+  RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                nLineOffsetIn, eDataTypeIn, bNativeOrderIn, TRUE),
   nBits(nBitsIn),
   nStartBit(0),
   nPixelOffsetBits(0),
@@ -174,15 +90,16 @@ EHdrRasterBand::EHdrRasterBand( GDALDataset *poDSIn,
   dfStdDev(0.0),
   minmaxmeanstddev(0)
 {
-    EHdrDataset* poEDS = reinterpret_cast<EHdrDataset *>( poDS );
+    EHdrDataset *poEDS = reinterpret_cast<EHdrDataset *>(poDS);
 
     if (nBits < 8)
     {
         int nSkipBytes = atoi(poEDS->GetKeyValue("SKIPBYTES"));
-        if( nSkipBytes < 0 || nSkipBytes > INT_MAX / 8 )
+        if( nSkipBytes < 0 ||
+            nSkipBytes > std::numeric_limits<int>::max() / 8 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Invalid SKIPBYTES: %d", nSkipBytes);
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid SKIPBYTES: %d", nSkipBytes);
             nStartBit = 0;
         }
         else
@@ -195,9 +112,9 @@ EHdrRasterBand::EHdrRasterBand( GDALDataset *poDSIn,
                 CPLAtoGIntBig(poEDS->GetKeyValue("BANDROWBYTES"));
             if( nBandRowBytes < 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Invalid BANDROWBYTES: " CPL_FRMT_GIB,
-                          nBandRowBytes );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Invalid BANDROWBYTES: " CPL_FRMT_GIB,
+                         nBandRowBytes);
                 nBandRowBytes = 0;
             }
             vsi_l_offset nRowBytes = 0;
@@ -208,7 +125,7 @@ EHdrRasterBand::EHdrRasterBand( GDALDataset *poDSIn,
             else
                 nRowBytes = static_cast<vsi_l_offset>(nBandRowBytes);
 
-            nStartBit += nRowBytes * (nBand-1) * 8;
+            nStartBit += nRowBytes * (nBand - 1) * 8;
         }
 
         nPixelOffsetBits = nBits;
@@ -216,29 +133,26 @@ EHdrRasterBand::EHdrRasterBand( GDALDataset *poDSIn,
             CPLAtoGIntBig(poEDS->GetKeyValue("TOTALROWBYTES"));
         if( nTotalRowBytes < 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Invalid TOTALROWBYTES: " CPL_FRMT_GIB, nTotalRowBytes);
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid TOTALROWBYTES: " CPL_FRMT_GIB, nTotalRowBytes);
             nTotalRowBytes = 0;
         }
         if( nTotalRowBytes > 0 )
             nLineOffsetBits = static_cast<vsi_l_offset>(nTotalRowBytes * 8);
         else
-            nLineOffsetBits =
-                static_cast<vsi_l_offset>(nPixelOffsetBits) *
-                poDS->GetRasterXSize();
+            nLineOffsetBits = static_cast<vsi_l_offset>(nPixelOffsetBits) *
+                              poDS->GetRasterXSize();
 
         nBlockXSize = poDS->GetRasterXSize();
         nBlockYSize = 1;
 
-        SetMetadataItem( "NBITS",
-                         CPLString().Printf( "%d", nBits ),
-                         "IMAGE_STRUCTURE" );
+        SetMetadataItem("NBITS", CPLString().Printf("%d", nBits),
+                        "IMAGE_STRUCTURE");
     }
 
-    if( eDataType == GDT_Byte
-        && EQUAL(poEDS->GetKeyValue("PIXELTYPE",""),"SIGNEDINT") )
-        SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE",
-                         "IMAGE_STRUCTURE" );
+    if( eDataType == GDT_Byte &&
+        EQUAL(poEDS->GetKeyValue("PIXELTYPE", ""), "SIGNEDINT") )
+        SetMetadataItem("PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE");
 }
 
 /************************************************************************/
@@ -250,61 +164,55 @@ CPLErr EHdrRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
 {
     if (nBits >= 8)
-      return RawRasterBand::IReadBlock(nBlockXOff, nBlockYOff, pImage);
+        return RawRasterBand::IReadBlock(nBlockXOff, nBlockYOff, pImage);
 
-/* -------------------------------------------------------------------- */
-/*      Establish desired position.                                     */
-/* -------------------------------------------------------------------- */
+    // Establish desired position.
     const vsi_l_offset nLineBytesBig =
-        (static_cast<vsi_l_offset>(nPixelOffsetBits)*nBlockXSize + 7) / 8;
-    if( nLineBytesBig > INT_MAX )
+        (static_cast<vsi_l_offset>(nPixelOffsetBits) * nBlockXSize + 7) / 8;
+    if( nLineBytesBig >
+        static_cast<vsi_l_offset>(std::numeric_limits<int>::max()) )
         return CE_Failure;
     const unsigned int nLineBytes = static_cast<unsigned int>(nLineBytesBig);
     const vsi_l_offset nLineStart =
         (nStartBit + nLineOffsetBits * nBlockYOff) / 8;
-    int iBitOffset = static_cast<int>(
-        (nStartBit + nLineOffsetBits * nBlockYOff) % 8);
+    int iBitOffset =
+        static_cast<int>((nStartBit + nLineOffsetBits * nBlockYOff) % 8);
 
-/* -------------------------------------------------------------------- */
-/*      Read data into buffer.                                          */
-/* -------------------------------------------------------------------- */
-    GByte *pabyBuffer =
-        static_cast<GByte *>( VSI_MALLOC_VERBOSE(nLineBytes) );
+    // Read data into buffer.
+    GByte *pabyBuffer = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nLineBytes));
     if( pabyBuffer == NULL )
         return CE_Failure;
 
-    if( VSIFSeekL( GetFPL(), nLineStart, SEEK_SET ) != 0
-        || VSIFReadL( pabyBuffer, 1, nLineBytes, GetFPL() ) != nLineBytes )
+    if( VSIFSeekL(GetFPL(), nLineStart, SEEK_SET) != 0 ||
+        VSIFReadL(pabyBuffer, 1, nLineBytes, GetFPL()) != nLineBytes )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read %u bytes at offset %lu.\n%s",
-                  nLineBytes, static_cast<unsigned long>(nLineStart),
-                  VSIStrerror( errno ) );
-        CPLFree( pabyBuffer );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Failed to read %u bytes at offset %lu.\n%s",
+                 nLineBytes, static_cast<unsigned long>(nLineStart),
+                 VSIStrerror(errno));
+        CPLFree(pabyBuffer);
         return CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Copy data, promoting to 8bit.                                   */
-/* -------------------------------------------------------------------- */
+    // Copy data, promoting to 8bit.
     for( int iX = 0, iPixel = 0; iX < nBlockXSize; iX++ )
     {
         int nOutWord = 0;
 
         for( int iBit = 0; iBit < nBits; iBit++ )
         {
-            if( pabyBuffer[iBitOffset>>3]  & (0x80 >>(iBitOffset & 7)) )
+            if( pabyBuffer[iBitOffset >> 3] & (0x80 >>(iBitOffset & 7)) )
                 nOutWord |= (1 << (nBits - 1 - iBit));
             iBitOffset++;
         }
 
         iBitOffset = iBitOffset + nPixelOffsetBits - nBits;
 
-        reinterpret_cast<GByte *>( pImage )[iPixel++]
-            = static_cast<GByte>( nOutWord );
+        reinterpret_cast<GByte *>(pImage)[iPixel++] =
+            static_cast<GByte>(nOutWord);
     }
 
-    CPLFree( pabyBuffer );
+    CPLFree(pabyBuffer);
 
     return CE_None;
 }
@@ -318,54 +226,49 @@ CPLErr EHdrRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 
 {
     if (nBits >= 8)
-      return RawRasterBand::IWriteBlock(nBlockXOff, nBlockYOff, pImage);
+        return RawRasterBand::IWriteBlock(nBlockXOff, nBlockYOff, pImage);
 
-/* -------------------------------------------------------------------- */
-/*      Establish desired position.                                     */
-/* -------------------------------------------------------------------- */
+    // Establish desired position.
     const vsi_l_offset nLineBytesBig =
-        (static_cast<vsi_l_offset>(nPixelOffsetBits)*nBlockXSize + 7) / 8;
-    if( nLineBytesBig > INT_MAX )
+        (static_cast<vsi_l_offset>(nPixelOffsetBits) * nBlockXSize + 7) / 8;
+    if( nLineBytesBig >
+        static_cast<vsi_l_offset>(std::numeric_limits<int>::max()) )
         return CE_Failure;
     const unsigned int nLineBytes = static_cast<unsigned int>(nLineBytesBig);
     const vsi_l_offset nLineStart =
         (nStartBit + nLineOffsetBits * nBlockYOff) / 8;
-    int iBitOffset = static_cast<int>(
-        (nStartBit + nLineOffsetBits * nBlockYOff) % 8 );
+    int iBitOffset =
+        static_cast<int>((nStartBit + nLineOffsetBits * nBlockYOff) % 8);
 
-/* -------------------------------------------------------------------- */
-/*      Read data into buffer.                                          */
-/* -------------------------------------------------------------------- */
+    // Read data into buffer.
     GByte *pabyBuffer =
-        static_cast<GByte *>( VSI_CALLOC_VERBOSE(nLineBytes, 1) );
+        static_cast<GByte *>(VSI_CALLOC_VERBOSE(nLineBytes, 1));
     if( pabyBuffer == NULL )
         return CE_Failure;
 
-    if( VSIFSeekL( GetFPL(), nLineStart, SEEK_SET ) != 0 )
+    if( VSIFSeekL(GetFPL(), nLineStart, SEEK_SET) != 0 )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to read %u bytes at offset %lu.\n%s",
-                  nLineBytes, static_cast<unsigned long>(nLineStart),
-                  VSIStrerror( errno ) );
-        CPLFree( pabyBuffer );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Failed to read %u bytes at offset %lu.\n%s",
+                 nLineBytes, static_cast<unsigned long>(nLineStart),
+                 VSIStrerror(errno));
+        CPLFree(pabyBuffer);
         return CE_Failure;
     }
 
-    CPL_IGNORE_RET_VAL(VSIFReadL( pabyBuffer, nLineBytes, 1, GetFPL() ));
+    CPL_IGNORE_RET_VAL(VSIFReadL(pabyBuffer, nLineBytes, 1, GetFPL()));
 
-/* -------------------------------------------------------------------- */
-/*      Copy data, promoting to 8bit.                                   */
-/* -------------------------------------------------------------------- */
+    // Copy data, promoting to 8bit.
     for( int iX = 0, iPixel = 0; iX < nBlockXSize; iX++ )
     {
-        const int nOutWord = reinterpret_cast<GByte *>( pImage )[iPixel++];
+        const int nOutWord = reinterpret_cast<GByte *>(pImage)[iPixel++];
 
         for( int iBit = 0; iBit < nBits; iBit++ )
         {
             if( nOutWord & (1 << (nBits - 1 - iBit)) )
-                pabyBuffer[iBitOffset>>3] |= (0x80 >>(iBitOffset & 7));
+                pabyBuffer[iBitOffset >> 3] |= (0x80 >> (iBitOffset & 7));
             else
-                pabyBuffer[iBitOffset>>3] &= ~((0x80 >>(iBitOffset & 7)));
+                pabyBuffer[iBitOffset >> 3] &= ~((0x80 >> (iBitOffset & 7)));
 
             iBitOffset++;
         }
@@ -373,20 +276,18 @@ CPLErr EHdrRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         iBitOffset = iBitOffset + nPixelOffsetBits - nBits;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write the data back out.                                        */
-/* -------------------------------------------------------------------- */
-    if( VSIFSeekL( GetFPL(), nLineStart, SEEK_SET ) != 0
-        || VSIFWriteL( pabyBuffer, 1, nLineBytes, GetFPL() ) != nLineBytes )
+    // Write the data back out.
+    if( VSIFSeekL(GetFPL(), nLineStart, SEEK_SET) != 0 ||
+        VSIFWriteL(pabyBuffer, 1, nLineBytes, GetFPL()) != nLineBytes )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to write %u bytes at offset %lu.\n%s",
-                  nLineBytes, static_cast<unsigned long>(nLineStart),
-                  VSIStrerror( errno ) );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Failed to write %u bytes at offset %lu.\n%s",
+                 nLineBytes, static_cast<unsigned long>(nLineStart),
+                 VSIStrerror(errno));
         return CE_Failure;
     }
 
-    CPLFree( pabyBuffer );
+    CPLFree(pabyBuffer);
 
     return CE_None;
 }
@@ -406,18 +307,18 @@ CPLErr EHdrRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 {
     // Defer to RawRasterBand
     if (nBits >= 8)
-        return RawRasterBand::IRasterIO( eRWFlag,
-                                         nXOff, nYOff, nXSize, nYSize,
-                                         pData, nBufXSize, nBufYSize,
-                                         eBufType, nPixelSpace, nLineSpace,
-                                         psExtraArg );
+        return RawRasterBand::IRasterIO(eRWFlag,
+                                        nXOff, nYOff, nXSize, nYSize,
+                                        pData, nBufXSize, nBufYSize,
+                                        eBufType, nPixelSpace, nLineSpace,
+                                        psExtraArg);
 
     // Force use of IReadBlock() and IWriteBlock()
-    return GDALRasterBand::IRasterIO( eRWFlag,
-                                      nXOff, nYOff, nXSize, nYSize,
-                                      pData, nBufXSize, nBufYSize,
-                                      eBufType, nPixelSpace, nLineSpace,
-                                      psExtraArg );
+    return GDALRasterBand::IRasterIO(eRWFlag,
+                                     nXOff, nYOff, nXSize, nYSize,
+                                     pData, nBufXSize, nBufYSize,
+                                     eBufType, nPixelSpace, nLineSpace,
+                                     psExtraArg);
 }
 
 /************************************************************************/
@@ -435,7 +336,7 @@ static const char*OSR_GDS( char* pszResult, int nResultLen,
     int iLine = 0;  // Used after for.
     for( ;
          papszNV[iLine] != NULL &&
-             !EQUALN(papszNV[iLine],pszField,strlen(pszField));
+             !EQUALN(papszNV[iLine], pszField, strlen(pszField));
          iLine++ ) {}
 
     if( papszNV[iLine] == NULL )
@@ -444,16 +345,15 @@ static const char*OSR_GDS( char* pszResult, int nResultLen,
     char **papszTokens = CSLTokenizeString(papszNV[iLine]);
 
     if( CSLCount(papszTokens) > 1 )
-        strncpy( pszResult, papszTokens[1], nResultLen);
+        strncpy(pszResult, papszTokens[1], nResultLen);
     else
-        strncpy( pszResult, pszDefaultValue, nResultLen);
-    pszResult[nResultLen-1] = '\0';
+        strncpy(pszResult, pszDefaultValue, nResultLen);
+    pszResult[nResultLen - 1] = '\0';
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
     return pszResult;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                            EHdrDataset                               */
@@ -467,11 +367,11 @@ static const char*OSR_GDS( char* pszResult, int nResultLen,
 EHdrDataset::EHdrDataset() :
     fpImage(NULL),
     osHeaderExt("hdr"),
-    bGotTransform(FALSE),
+    bGotTransform(false),
     pszProjection(CPLStrdup("")),
-    bHDRDirty(FALSE),
+    bHDRDirty(false),
     papszHDR(NULL),
-    bCLRDirty(FALSE)
+    bCLRDirty(false)
 {
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -493,19 +393,17 @@ EHdrDataset::~EHdrDataset()
     if( nBands > 0 && GetAccess() == GA_Update )
     {
         int bNoDataSet;
-        RawRasterBand *poBand
-            = reinterpret_cast<RawRasterBand *>( GetRasterBand( 1 ) );
+        RawRasterBand *poBand =
+            reinterpret_cast<RawRasterBand *>(GetRasterBand(1));
 
-        const double dfNoData
-            = poBand->GetNoDataValue(&bNoDataSet);
+        const double dfNoData = poBand->GetNoDataValue(&bNoDataSet);
         if( bNoDataSet )
         {
-            ResetKeyValue( "NODATA",
-                           CPLString().Printf( "%.8g", dfNoData ) );
+            ResetKeyValue("NODATA", CPLString().Printf("%.8g", dfNoData));
         }
 
         if( bCLRDirty )
-            RewriteColorTable( poBand->GetColorTable() );
+            RewriteColorTable(poBand->GetColorTable());
 
         if( bHDRDirty )
             RewriteHDR();
@@ -513,14 +411,14 @@ EHdrDataset::~EHdrDataset()
 
     if( fpImage != NULL )
     {
-        if( VSIFCloseL( fpImage ) != 0 )
+        if( VSIFCloseL(fpImage) != 0 )
         {
             CPLError(CE_Failure, CPLE_FileIO, "I/O error");
         }
     }
 
-    CPLFree( pszProjection );
-    CSLDestroy( papszHDR );
+    CPLFree(pszProjection);
+    CSLDestroy(papszHDR);
 }
 
 /************************************************************************/
@@ -533,8 +431,8 @@ const char *EHdrDataset::GetKeyValue( const char *pszKey,
 {
     for( int i = 0; papszHDR[i] != NULL; i++ )
     {
-        if( EQUALN(pszKey,papszHDR[i],strlen(pszKey))
-            && isspace((unsigned char)papszHDR[i][strlen(pszKey)]) )
+        if( EQUALN(pszKey,papszHDR[i],strlen(pszKey)) &&
+            isspace((unsigned char)papszHDR[i][strlen(pszKey)]) )
         {
             const char *pszValue = papszHDR[i] + strlen(pszKey);
             while( isspace((unsigned char)*pszValue) )
@@ -559,29 +457,29 @@ void EHdrDataset::ResetKeyValue( const char *pszKey, const char *pszValue )
 {
     if( strlen(pszValue) > 65 )
     {
-        CPLAssert( strlen(pszValue) <= 65 );
+        CPLAssert(strlen(pszValue) <= 65);
         return;
     }
 
-  char szNewLine[82] = { '\0' };
-    snprintf( szNewLine, sizeof(szNewLine), "%-15s%s", pszKey, pszValue );
+    char szNewLine[82] = { '\0' };
+    snprintf(szNewLine, sizeof(szNewLine), "%-15s%s", pszKey, pszValue);
 
     for( int i = CSLCount(papszHDR)-1; i >= 0; i-- )
     {
-        if( EQUALN(papszHDR[i], szNewLine, strlen(pszKey) + 1 ) )
+        if( EQUALN(papszHDR[i], szNewLine, strlen(pszKey) + 1) )
         {
             if( strcmp(papszHDR[i],szNewLine) != 0 )
             {
-                CPLFree( papszHDR[i] );
-                papszHDR[i] = CPLStrdup( szNewLine );
-                bHDRDirty = TRUE;
+                CPLFree(papszHDR[i]);
+                papszHDR[i] = CPLStrdup(szNewLine);
+                bHDRDirty = true;
             }
             return;
         }
     }
 
-    bHDRDirty = TRUE;
-    papszHDR = CSLAddString( papszHDR, szNewLine );
+    bHDRDirty = true;
+    papszHDR = CSLAddString(papszHDR, szNewLine);
 }
 
 /************************************************************************/
@@ -591,10 +489,10 @@ void EHdrDataset::ResetKeyValue( const char *pszKey, const char *pszValue )
 void EHdrDataset::RewriteColorTable( GDALColorTable *poTable )
 
 {
-    CPLString osCLRFilename = CPLResetExtension( GetDescription(), "clr" );
+    CPLString osCLRFilename = CPLResetExtension(GetDescription(), "clr");
     if( poTable )
     {
-        VSILFILE *fp = VSIFOpenL( osCLRFilename, "wt" );
+        VSILFILE *fp = VSIFOpenL(osCLRFilename, "wt");
         if( fp != NULL )
         {
             for( int iColor = 0;
@@ -602,37 +500,40 @@ void EHdrDataset::RewriteColorTable( GDALColorTable *poTable )
                  iColor++ )
             {
                 GDALColorEntry sEntry;
-                poTable->GetColorEntryAsRGB( iColor, &sEntry );
+                poTable->GetColorEntryAsRGB(iColor, &sEntry);
 
                 // I wish we had a way to mark transparency.
                 CPLString oLine;
-                oLine.Printf( "%3d %3d %3d %3d\n",
-                              iColor, sEntry.c1, sEntry.c2, sEntry.c3 );
+                oLine.Printf("%3d %3d %3d %3d\n",
+                             iColor, sEntry.c1, sEntry.c2, sEntry.c3);
                 if( VSIFWriteL(
                     reinterpret_cast<void *>(
                         const_cast<char *>( oLine.c_str() ) ),
                     strlen(oLine), 1, fp ) != 1 )
                 {
-                    CPLError( CE_Failure, CPLE_FileIO,
-                              "Error while write color table");
-                    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+                    CPLError(CE_Failure, CPLE_FileIO,
+                             "Error while write color table");
+                    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                     return;
                 }
             }
-            if( VSIFCloseL( fp ) != 0 )
+            if( VSIFCloseL(fp) != 0 )
             {
-                CPLError(CE_Failure, CPLE_FileIO, "Error while write color table");
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Error while write color table");
             }
         }
         else
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Unable to create color file %s.",
-                      osCLRFilename.c_str() );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Unable to create color file %s.",
+                     osCLRFilename.c_str());
         }
     }
     else
-        VSIUnlink( osCLRFilename );
+    {
+        VSIUnlink(osCLRFilename);
+    }
 }
 
 /************************************************************************/
@@ -655,44 +556,35 @@ const char *EHdrDataset::GetProjectionRef()
 CPLErr EHdrDataset::SetProjection( const char *pszSRS )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Reset coordinate system on the dataset.                         */
-/* -------------------------------------------------------------------- */
-    CPLFree( pszProjection );
-    pszProjection = CPLStrdup( pszSRS );
+    // Reset coordinate system on the dataset.
+    CPLFree(pszProjection);
+    pszProjection = CPLStrdup(pszSRS);
 
     if( strlen(pszSRS) == 0 )
         return CE_None;
 
-/* -------------------------------------------------------------------- */
-/*      Convert to ESRI WKT.                                            */
-/* -------------------------------------------------------------------- */
-    OGRSpatialReference oSRS( pszSRS );
+    // Convert to ESRI WKT.
+    OGRSpatialReference oSRS(pszSRS);
     oSRS.morphToESRI();
 
     char *pszESRI_SRS = NULL;
-    oSRS.exportToWkt( &pszESRI_SRS );
+    oSRS.exportToWkt(&pszESRI_SRS);
 
-/* -------------------------------------------------------------------- */
-/*      Write to .prj file.                                             */
-/* -------------------------------------------------------------------- */
-    CPLString osPrjFilename = CPLResetExtension( GetDescription(), "prj" );
-    VSILFILE *fp = VSIFOpenL( osPrjFilename.c_str(), "wt" );
+    // Write to .prj file.
+    CPLString osPrjFilename = CPLResetExtension(GetDescription(), "prj");
+    VSILFILE *fp = VSIFOpenL(osPrjFilename.c_str(), "wt");
     if( fp != NULL )
     {
-        size_t nCount = VSIFWriteL( pszESRI_SRS, strlen(pszESRI_SRS), 1, fp );
-        nCount += VSIFWriteL(
-            reinterpret_cast<void *>( const_cast<char *>( "\n" ) ),
-            1, 1, fp );
-        if( VSIFCloseL( fp ) != 0 ||
-            nCount != 2 )
+        size_t nCount = VSIFWriteL(pszESRI_SRS, strlen(pszESRI_SRS), 1, fp);
+        nCount += VSIFWriteL("\n", 1, 1, fp);
+        if( VSIFCloseL(fp) != 0 || nCount != 2 )
         {
-            CPLFree( pszESRI_SRS );
+            CPLFree(pszESRI_SRS);
             return CE_Failure;
         }
     }
 
-    CPLFree( pszESRI_SRS );
+    CPLFree(pszESRI_SRS);
 
     return CE_None;
 }
@@ -706,11 +598,11 @@ CPLErr EHdrDataset::GetGeoTransform( double * padfTransform )
 {
     if( bGotTransform )
     {
-        memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
+        memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
         return CE_None;
     }
 
-    return GDALPamDataset::GetGeoTransform( padfTransform );
+    return GDALPamDataset::GetGeoTransform(padfTransform);
 }
 
 /************************************************************************/
@@ -720,50 +612,42 @@ CPLErr EHdrDataset::GetGeoTransform( double * padfTransform )
 CPLErr EHdrDataset::SetGeoTransform( double *padfGeoTransform )
 
 {
-/* -------------------------------------------------------------------- */
-/*      We only support non-rotated images with info in the .HDR file.  */
-/* -------------------------------------------------------------------- */
+    // We only support non-rotated images with info in the .HDR file.
     if( padfGeoTransform[2] != 0.0 || padfGeoTransform[4] != 0.0 )
     {
-        return GDALPamDataset::SetGeoTransform( padfGeoTransform );
+        return GDALPamDataset::SetGeoTransform(padfGeoTransform);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Record new geotransform.                                        */
-/* -------------------------------------------------------------------- */
-    bGotTransform = TRUE;
-    memcpy( adfGeoTransform, padfGeoTransform, sizeof(double) * 6 );
+    // Record new geotransform.
+    bGotTransform = true;
+    memcpy(adfGeoTransform, padfGeoTransform, sizeof(double) * 6);
 
-/* -------------------------------------------------------------------- */
-/*      Strip out all old geotransform keywords from HDR records.       */
-/* -------------------------------------------------------------------- */
-    for( int i = CSLCount(papszHDR)-1; i >= 0; i-- )
+    // Strip out all old geotransform keywords from HDR records.
+    for( int i = CSLCount(papszHDR) - 1; i >= 0; i-- )
     {
-        if( STARTS_WITH_CI(papszHDR[i], "ul")
-            || STARTS_WITH_CI(papszHDR[i]+1, "ll")
-            || STARTS_WITH_CI(papszHDR[i], "cell")
-            || STARTS_WITH_CI(papszHDR[i]+1, "dim") )
+        if( STARTS_WITH_CI(papszHDR[i], "ul") ||
+            STARTS_WITH_CI(papszHDR[i] + 1, "ll") ||
+            STARTS_WITH_CI(papszHDR[i], "cell") ||
+            STARTS_WITH_CI(papszHDR[i] + 1, "dim") )
         {
-            papszHDR = CSLRemoveStrings( papszHDR, i, 1, NULL );
+            papszHDR = CSLRemoveStrings(papszHDR, i, 1, NULL);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set the transformation information.                             */
-/* -------------------------------------------------------------------- */
+    // Set the transformation information.
     CPLString  oValue;
 
-    oValue.Printf( "%.15g", adfGeoTransform[0] + adfGeoTransform[1] * 0.5 );
-    ResetKeyValue( "ULXMAP", oValue );
+    oValue.Printf("%.15g", adfGeoTransform[0] + adfGeoTransform[1] * 0.5);
+    ResetKeyValue("ULXMAP", oValue);
 
-    oValue.Printf( "%.15g", adfGeoTransform[3] + adfGeoTransform[5] * 0.5 );
-    ResetKeyValue( "ULYMAP", oValue );
+    oValue.Printf("%.15g", adfGeoTransform[3] + adfGeoTransform[5] * 0.5);
+    ResetKeyValue("ULYMAP", oValue);
 
-    oValue.Printf( "%.15g", adfGeoTransform[1] );
-    ResetKeyValue( "XDIM", oValue );
+    oValue.Printf("%.15g", adfGeoTransform[1]);
+    ResetKeyValue("XDIM", oValue);
 
-    oValue.Printf( "%.15g", fabs(adfGeoTransform[5]) );
-    ResetKeyValue( "YDIM", oValue );
+    oValue.Printf("%.15g", fabs(adfGeoTransform[5]));
+    ResetKeyValue("YDIM", oValue);
 
     return CE_None;
 }
@@ -775,39 +659,36 @@ CPLErr EHdrDataset::SetGeoTransform( double *padfGeoTransform )
 CPLErr EHdrDataset::RewriteHDR()
 
 {
-    const CPLString osPath = CPLGetPath( GetDescription() );
-    const CPLString osName = CPLGetBasename( GetDescription() );
-    const CPLString osHDRFilename = CPLFormCIFilename( osPath, osName, osHeaderExt );
+    const CPLString osPath = CPLGetPath(GetDescription());
+    const CPLString osName = CPLGetBasename(GetDescription());
+    const CPLString osHDRFilename =
+        CPLFormCIFilename(osPath, osName, osHeaderExt);
 
-/* -------------------------------------------------------------------- */
-/*      Write .hdr file.                                                */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fp = VSIFOpenL( osHDRFilename, "wt" );
+    // Write .hdr file.
+    VSILFILE *fp = VSIFOpenL(osHDRFilename, "wt");
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to rewrite .hdr file %s.",
-                  osHDRFilename.c_str() );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Failed to rewrite .hdr file %s.",
+                 osHDRFilename.c_str());
         return CE_Failure;
     }
 
     for( int i = 0; papszHDR[i] != NULL; i++ )
     {
-        size_t nCount = VSIFWriteL( papszHDR[i], strlen(papszHDR[i]), 1, fp );
-        nCount += VSIFWriteL(
-            reinterpret_cast<void *>( const_cast<char *>( "\n" ) ),
-            1, 1, fp );
+        size_t nCount = VSIFWriteL(papszHDR[i], strlen(papszHDR[i]), 1, fp);
+        nCount += VSIFWriteL("\n", 1, 1, fp);
         if( nCount != 2 )
         {
-            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
             return CE_Failure;
         }
     }
 
-    bHDRDirty = FALSE;
+    bHDRDirty = false;
 
-    if( VSIFCloseL( fp ) != 0 )
+    if( VSIFCloseL(fp) != 0 )
         return CE_Failure;
 
     return CE_None;
@@ -819,40 +700,37 @@ CPLErr EHdrDataset::RewriteHDR()
 
 CPLErr EHdrDataset::RewriteSTX()
 {
-    const CPLString osPath = CPLGetPath( GetDescription() );
-    const CPLString osName = CPLGetBasename( GetDescription() );
-    const CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
-
-/* -------------------------------------------------------------------- */
-/*      Write .stx file.                                                */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fp = VSIFOpenL( osSTXFilename, "wt" );
+    const CPLString osPath = CPLGetPath(GetDescription());
+    const CPLString osName = CPLGetBasename(GetDescription());
+    const CPLString osSTXFilename = CPLFormCIFilename(osPath, osName, "stx");
+
+    VSILFILE *fp = VSIFOpenL(osSTXFilename, "wt");
     if( fp == NULL )
     {
-        CPLDebug( "EHDR", "Failed to rewrite .stx file %s.",
-                  osSTXFilename.c_str() );
+        CPLDebug("EHDR", "Failed to rewrite .stx file %s.",
+                 osSTXFilename.c_str());
         return CE_Failure;
     }
 
     bool bOK = true;
     for ( int i = 0; bOK && i < nBands; ++i )
     {
-        EHdrRasterBand* poBand
-            = reinterpret_cast<EHdrRasterBand *>( papoBands[i] );
-        bOK &= VSIFPrintfL( fp, "%d %.10f %.10f ", i+1,
-                            poBand->dfMin, poBand->dfMax ) >= 0;
+        EHdrRasterBand* poBand =
+            reinterpret_cast<EHdrRasterBand *>(papoBands[i]);
+        bOK &= VSIFPrintfL(fp, "%d %.10f %.10f ", i + 1,
+                           poBand->dfMin, poBand->dfMax) >= 0;
         if ( poBand->minmaxmeanstddev & HAS_MEAN_FLAG )
-            bOK &= VSIFPrintfL( fp, "%.10f ", poBand->dfMean) >= 0;
+            bOK &= VSIFPrintfL(fp, "%.10f ", poBand->dfMean) >= 0;
         else
-            bOK &= VSIFPrintfL( fp, "# ") >= 0;
+            bOK &= VSIFPrintfL(fp, "# ") >= 0;
 
         if ( poBand->minmaxmeanstddev & HAS_STDDEV_FLAG )
-            bOK &= VSIFPrintfL( fp, "%.10f\n", poBand->dfStdDev) >= 0;
+            bOK &= VSIFPrintfL(fp, "%.10f\n", poBand->dfStdDev) >= 0;
         else
-            bOK &= VSIFPrintfL( fp, "#\n") >= 0;
+            bOK &= VSIFPrintfL(fp, "#\n") >= 0;
     }
 
-    if( VSIFCloseL( fp ) != 0 )
+    if( VSIFCloseL(fp) != 0 )
         bOK = false;
 
     return bOK ? CE_None : CE_Failure;
@@ -864,116 +742,111 @@ CPLErr EHdrDataset::RewriteSTX()
 
 CPLErr EHdrDataset::ReadSTX()
 {
-    const CPLString osPath = CPLGetPath( GetDescription() );
-    const CPLString osName = CPLGetBasename( GetDescription() );
-    const CPLString osSTXFilename = CPLFormCIFilename( osPath, osName, "stx" );
-
-/* -------------------------------------------------------------------- */
-/*      Read .stx file.                                                 */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fp = VSIFOpenL( osSTXFilename, "rt" );
+    const CPLString osPath = CPLGetPath(GetDescription());
+    const CPLString osName = CPLGetBasename(GetDescription());
+    const CPLString osSTXFilename = CPLFormCIFilename(osPath, osName, "stx");
+
+    VSILFILE *fp = VSIFOpenL(osSTXFilename, "rt");
     if (fp == NULL)
         return CE_None;
 
     const char *pszLine = NULL;
-    while( (pszLine = CPLReadLineL( fp )) != NULL )
+    while( (pszLine = CPLReadLineL(fp)) != NULL )
     {
         char **papszTokens =
-            CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
-        const int nTokens = CSLCount( papszTokens );
+            CSLTokenizeStringComplex(pszLine, " \t", TRUE, FALSE);
+        const int nTokens = CSLCount(papszTokens);
         if( nTokens >= 5 )
         {
             const int i = atoi(papszTokens[0]);
             if (i > 0 && i <= nBands)
             {
-              EHdrRasterBand* poBand
-                  = reinterpret_cast<EHdrRasterBand *>( papoBands[i-1] );
-              poBand->dfMin = CPLAtof(papszTokens[1]);
-              poBand->dfMax = CPLAtof(papszTokens[2]);
-
-              int bNoDataSet = FALSE;
-              const double dfNoData = poBand->GetNoDataValue(&bNoDataSet);
-              if (bNoDataSet && dfNoData == poBand->dfMin)
-              {
-                  // Triggered by
-                  // /vsicurl/http://eros.usgs.gov/archive/nslrsda/GeoTowns/HongKong/srtm/n22e113.zip/n22e113.bil
-                  CPLDebug( "EHDr", "Ignoring .stx file where min == nodata. "
-                            "The nodata value should not be taken into account "
-                            "in minimum value computation.");
-                  CSLDestroy( papszTokens );
-                  papszTokens = NULL;
-                  break;
-              }
-
-              poBand->minmaxmeanstddev = HAS_MIN_FLAG | HAS_MAX_FLAG;
-              // Reads optional mean and stddev.
-              if ( !EQUAL(papszTokens[3], "#") )
-              {
-                poBand->dfMean   = CPLAtof(papszTokens[3]);
-                poBand->minmaxmeanstddev |= HAS_MEAN_FLAG;
-              }
-              if ( !EQUAL(papszTokens[4], "#") )
-              {
-                poBand->dfStdDev = CPLAtof(papszTokens[4]);
-                poBand->minmaxmeanstddev |= HAS_STDDEV_FLAG;
-              }
-
-              if( nTokens >= 6 && !EQUAL(papszTokens[5], "#") )
-                poBand->SetMetadataItem(
-                  "STRETCHMIN", papszTokens[5], "RENDERING_HINTS" );
-
-              if( nTokens >= 7 && !EQUAL(papszTokens[6], "#") )
-                poBand->SetMetadataItem(
-                  "STRETCHMAX", papszTokens[6], "RENDERING_HINTS" );
+                EHdrRasterBand *poBand =
+                    reinterpret_cast<EHdrRasterBand *>(papoBands[i - 1]);
+                poBand->dfMin = CPLAtof(papszTokens[1]);
+                poBand->dfMax = CPLAtof(papszTokens[2]);
+
+                int bNoDataSet = FALSE;
+                const double dfNoData = poBand->GetNoDataValue(&bNoDataSet);
+                if (bNoDataSet && dfNoData == poBand->dfMin)
+                {
+                    // Triggered by
+                    // /vsicurl/http://eros.usgs.gov/archive/nslrsda/GeoTowns/HongKong/srtm/n22e113.zip/n22e113.bil
+                    CPLDebug(
+                        "EHDr",
+                        "Ignoring .stx file where min == nodata. "
+                        "The nodata value should not be taken into account "
+                        "in minimum value computation.");
+                    CSLDestroy(papszTokens);
+                    papszTokens = NULL;
+                    break;
+                }
+
+                poBand->minmaxmeanstddev = HAS_MIN_FLAG | HAS_MAX_FLAG;
+                // Reads optional mean and stddev.
+                if (!EQUAL(papszTokens[3], "#") )
+                {
+                    poBand->dfMean = CPLAtof(papszTokens[3]);
+                    poBand->minmaxmeanstddev |= HAS_MEAN_FLAG;
+                }
+                if ( !EQUAL(papszTokens[4], "#") )
+                {
+                    poBand->dfStdDev = CPLAtof(papszTokens[4]);
+                    poBand->minmaxmeanstddev |= HAS_STDDEV_FLAG;
+                }
+
+                if( nTokens >= 6 && !EQUAL(papszTokens[5], "#") )
+                    poBand->SetMetadataItem("STRETCHMIN", papszTokens[5],
+                                            "RENDERING_HINTS");
+
+                if( nTokens >= 7 && !EQUAL(papszTokens[6], "#") )
+                    poBand->SetMetadataItem("STRETCHMAX", papszTokens[6],
+                                            "RENDERING_HINTS");
             }
-          }
+        }
 
-          CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
     }
 
-    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
 
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                      GetImageRepFilename()                           */
 /************************************************************************/
 
-/* -------------------------------------------------------------------- */
-/*  Check for IMAGE.REP (Spatiocarte Defense 1.0) or name_of_image.rep  */
-/*  if it's a GIS-GeoSPOT image                                         */
-/*  For the specification of SPDF (in French),                          */
-/*   see http://eden.ign.fr/download/pub/doc/emabgi/spdf10.pdf/download */
-/* -------------------------------------------------------------------- */
+// Check for IMAGE.REP (Spatiocarte Defense 1.0) or name_of_image.rep
+// if it's a GIS-GeoSPOT image.
+// For the specification of SPDF (in French), see
+//   http://eden.ign.fr/download/pub/doc/emabgi/spdf10.pdf/download
 
-CPLString EHdrDataset::GetImageRepFilename(const char* pszFilename)
+CPLString EHdrDataset::GetImageRepFilename(const char *pszFilename)
 {
 
-    const CPLString osPath = CPLGetPath( pszFilename );
-    const CPLString osName = CPLGetBasename( pszFilename );
-    const CPLString osREPFilename =
-        CPLFormCIFilename( osPath, osName, "rep" );
+    const CPLString osPath = CPLGetPath(pszFilename);
+    const CPLString osName = CPLGetBasename(pszFilename);
+    const CPLString osREPFilename = CPLFormCIFilename(osPath, osName, "rep");
 
     VSIStatBufL sStatBuf;
     if( VSIStatExL(
-            osREPFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+            osREPFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG) == 0 )
         return osREPFilename;
 
     if (EQUAL(CPLGetFilename(pszFilename), "imspatio.bil") ||
         EQUAL(CPLGetFilename(pszFilename), "haspatio.bil"))
     {
-        CPLString osImageRepFilename(CPLFormCIFilename( osPath, "image", "rep" ));
+        CPLString osImageRepFilename(CPLFormCIFilename(osPath, "image", "rep"));
         if( VSIStatExL(
-                osImageRepFilename.c_str(), &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+                osImageRepFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG) == 0 )
             return osImageRepFilename;
 
-        /* Try in the upper directories if not found in the BIL image directory */
+        // Try in the upper directories if not found in the BIL image directory.
         CPLString dirName(CPLGetDirname(osPath));
         if (CPLIsFilenameRelative(osPath.c_str()))
         {
-            char* cwd = CPLGetCurrentDir();
+            char *cwd = CPLGetCurrentDir();
             if (cwd)
             {
                 dirName = CPLFormFilename(cwd, dirName.c_str(), NULL);
@@ -984,13 +857,13 @@ CPLString EHdrDataset::GetImageRepFilename(const char* pszFilename)
                EQUAL(dirName, "/") == FALSE )
         {
             osImageRepFilename =
-                CPLFormCIFilename( dirName.c_str(), "image", "rep" );
+                CPLFormCIFilename(dirName.c_str(), "image", "rep");
             if( VSIStatExL(
                     osImageRepFilename.c_str(), &sStatBuf,
-                    VSI_STAT_EXISTS_FLAG ) == 0 )
+                    VSI_STAT_EXISTS_FLAG) == 0 )
                 return osImageRepFilename;
 
-            /* Don't try to recurse above the 'image' subdirectory */
+            // Don't try to recurse above the 'image' subdirectory.
             if( EQUAL(dirName, "image") )
             {
                 break;
@@ -1008,35 +881,35 @@ CPLString EHdrDataset::GetImageRepFilename(const char* pszFilename)
 char **EHdrDataset::GetFileList()
 
 {
-    const CPLString osPath = CPLGetPath( GetDescription() );
-    const CPLString osName = CPLGetBasename( GetDescription() );
+    const CPLString osPath = CPLGetPath(GetDescription());
+    const CPLString osName = CPLGetBasename(GetDescription());
 
     // Main data file, etc.
     char **papszFileList = GDALPamDataset::GetFileList();
 
     // Header file.
-    CPLString osFilename = CPLFormCIFilename( osPath, osName, osHeaderExt );
-    papszFileList = CSLAddString( papszFileList, osFilename );
+    CPLString osFilename = CPLFormCIFilename(osPath, osName, osHeaderExt);
+    papszFileList = CSLAddString(papszFileList, osFilename);
 
     // Statistics file
-    osFilename = CPLFormCIFilename( osPath, osName, "stx" );
+    osFilename = CPLFormCIFilename(osPath, osName, "stx");
     VSIStatBufL sStatBuf;
-    if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
-        papszFileList = CSLAddString( papszFileList, osFilename );
+    if( VSIStatExL(osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG) == 0 )
+        papszFileList = CSLAddString(papszFileList, osFilename);
 
     // color table file.
-    osFilename = CPLFormCIFilename( osPath, osName, "clr" );
-    if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
-        papszFileList = CSLAddString( papszFileList, osFilename );
+    osFilename = CPLFormCIFilename(osPath, osName, "clr");
+    if( VSIStatExL(osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG) == 0 )
+        papszFileList = CSLAddString(papszFileList, osFilename);
 
     // projections file.
-    osFilename = CPLFormCIFilename( osPath, osName, "prj" );
-    if( VSIStatExL( osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
-        papszFileList = CSLAddString( papszFileList, osFilename );
+    osFilename = CPLFormCIFilename(osPath, osName, "prj");
+    if( VSIStatExL(osFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG) == 0 )
+        papszFileList = CSLAddString(papszFileList, osFilename);
 
-    const CPLString imageRepFilename = GetImageRepFilename( GetDescription() );
+    const CPLString imageRepFilename = GetImageRepFilename(GetDescription());
     if (!imageRepFilename.empty())
-        papszFileList = CSLAddString( papszFileList, imageRepFilename.c_str() );
+        papszFileList = CSLAddString(papszFileList, imageRepFilename.c_str());
 
     return papszFileList;
 }
@@ -1048,21 +921,16 @@ char **EHdrDataset::GetFileList()
 GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      We assume the user is pointing to the binary (i.e. .bil) file.  */
-/* -------------------------------------------------------------------- */
+    // Assume the caller is pointing to the binary (i.e. .bil) file.
     if( poOpenInfo->nHeaderBytes < 2 )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Now we need to tear apart the filename to form a .HDR           */
-/*      filename.                                                       */
-/* -------------------------------------------------------------------- */
-    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
-    const CPLString osName = CPLGetBasename( poOpenInfo->pszFilename );
+    // Tear apart the filename to form a .HDR filename.
+    const CPLString osPath = CPLGetPath(poOpenInfo->pszFilename);
+    const CPLString osName = CPLGetBasename(poOpenInfo->pszFilename);
 
-    const char* pszHeaderExt = "hdr";
-    if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "SRC" ) &&
+    const char *pszHeaderExt = "hdr";
+    if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "SRC") &&
         osName.size() == 7 &&
         (osName[0] == 'e' || osName[0] == 'E' ||
          osName[0] == 'w' || osName[0] == 'W') &&
@@ -1074,40 +942,33 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         pszHeaderExt = "sch";
     }
 
-    char** papszSiblingFiles = poOpenInfo->GetSiblingFiles();
+    char **papszSiblingFiles = poOpenInfo->GetSiblingFiles();
     CPLString osHDRFilename;
     if( papszSiblingFiles )
     {
-        const int iFile =
-            CSLFindString( papszSiblingFiles,
-                           CPLFormFilename( NULL, osName, pszHeaderExt ) );
+        const int iFile = CSLFindString(
+            papszSiblingFiles, CPLFormFilename(NULL, osName, pszHeaderExt));
         if( iFile < 0 )  // Return if there is no corresponding .hdr file.
             return NULL;
 
-        osHDRFilename =
-            CPLFormFilename( osPath, papszSiblingFiles[iFile],
-                             NULL );
+        osHDRFilename = CPLFormFilename(osPath, papszSiblingFiles[iFile], NULL);
     }
     else
     {
-        osHDRFilename = CPLFormCIFilename( osPath, osName, pszHeaderExt );
+        osHDRFilename = CPLFormCIFilename(osPath, osName, pszHeaderExt);
     }
 
-    const bool bSelectedHDR = EQUAL( osHDRFilename, poOpenInfo->pszFilename );
+    const bool bSelectedHDR = EQUAL(osHDRFilename, poOpenInfo->pszFilename);
 
-/* -------------------------------------------------------------------- */
-/*      Do we have a .hdr file?                                         */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fp = VSIFOpenL( osHDRFilename, "r" );
+    // Do we have a .hdr file?
+    VSILFILE *fp = VSIFOpenL(osHDRFilename, "r");
     if( fp == NULL )
     {
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Is this file an ESRI header file?  Read a few lines of text     */
-/*      searching for something starting with nrows or ncols.           */
-/* -------------------------------------------------------------------- */
+    // Is this file an ESRI header file?  Read a few lines of text
+    // searching for something starting with nrows or ncols.
     int nRows = -1;
     int nCols = -1;
     int nBands = 1;
@@ -1124,7 +985,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
     GDALDataType eDataType = GDT_Byte;
     int nBits = -1;
     char chByteOrder = 'M';
-    char chPixelType = 'N'; // not defined
+    char chPixelType = 'N';  // Not defined.
     char szLayout[10] = "BIL";
     char **papszHDR = NULL;
     int bHasInternalProjection = FALSE;
@@ -1133,164 +994,156 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
     double dfMin = 0;
     double dfMax = 0;
 
-    const char *pszLine;
-    while( (pszLine = CPLReadLineL( fp )) != NULL )
+    const char *pszLine = NULL;
+    while( (pszLine = CPLReadLineL(fp)) != NULL )
     {
         nLineCount++;
 
         if( nLineCount > 50 || strlen(pszLine) > 1000 )
             break;
 
-        papszHDR = CSLAddString( papszHDR, pszLine );
+        papszHDR = CSLAddString(papszHDR, pszLine);
 
-        char **papszTokens
-            = CSLTokenizeStringComplex( pszLine, " \t", TRUE, FALSE );
-        if( CSLCount( papszTokens ) < 2 )
+        char **papszTokens =
+            CSLTokenizeStringComplex(pszLine, " \t", TRUE, FALSE);
+        if( CSLCount(papszTokens) < 2 )
         {
-            CSLDestroy( papszTokens );
+            CSLDestroy(papszTokens);
             continue;
         }
 
-        if( EQUAL(papszTokens[0],"ncols") )
+        if( EQUAL(papszTokens[0], "ncols") )
         {
             nCols = atoi(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"nrows") )
+        else if( EQUAL(papszTokens[0], "nrows") )
         {
             nRows = atoi(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"skipbytes") )
+        else if( EQUAL(papszTokens[0], "skipbytes") )
         {
             nSkipBytes = atoi(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"ulxmap")
-                 || EQUAL(papszTokens[0],"xllcorner")
-                 || EQUAL(papszTokens[0],"xllcenter") )
+        else if( EQUAL(papszTokens[0], "ulxmap") ||
+                 EQUAL(papszTokens[0], "xllcorner") ||
+                 EQUAL(papszTokens[0], "xllcenter") )
         {
             dfULXMap = CPLAtofM(papszTokens[1]);
-            if( EQUAL(papszTokens[0],"xllcorner") )
+            if( EQUAL(papszTokens[0], "xllcorner") )
                 bCenter = FALSE;
         }
-        else if( EQUAL(papszTokens[0],"ulymap") )
+        else if( EQUAL(papszTokens[0], "ulymap") )
         {
             dfULYMap = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"yllcorner")
-                 || EQUAL(papszTokens[0],"yllcenter") )
+        else if( EQUAL(papszTokens[0], "yllcorner") ||
+                 EQUAL(papszTokens[0], "yllcenter") )
         {
             dfYLLCorner = CPLAtofM(papszTokens[1]);
-            if( EQUAL(papszTokens[0],"yllcorner") )
+            if( EQUAL(papszTokens[0], "yllcorner") )
                 bCenter = FALSE;
         }
-        else if( EQUAL(papszTokens[0],"xdim") )
+        else if( EQUAL(papszTokens[0], "xdim") )
         {
             dfXDim = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"ydim") )
+        else if( EQUAL(papszTokens[0], "ydim") )
         {
             dfYDim = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"cellsize") )
+        else if( EQUAL(papszTokens[0], "cellsize") )
         {
-            dfXDim = dfYDim = CPLAtofM(papszTokens[1]);
+            dfXDim = CPLAtofM(papszTokens[1]);
+            dfYDim = dfXDim;
         }
-        else if( EQUAL(papszTokens[0],"nbands") )
+        else if( EQUAL(papszTokens[0], "nbands") )
         {
             nBands = atoi(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"layout") )
+        else if( EQUAL(papszTokens[0], "layout") )
         {
-            strncpy( szLayout, papszTokens[1], sizeof(szLayout) );
-            szLayout[sizeof(szLayout)-1] = '\0';
+            snprintf( szLayout, sizeof(szLayout), "%s", papszTokens[1] );
         }
-        else if( EQUAL(papszTokens[0],"NODATA_value")
-                 || EQUAL(papszTokens[0],"NODATA") )
+        else if( EQUAL(papszTokens[0], "NODATA_value") ||
+                 EQUAL(papszTokens[0], "NODATA") )
         {
             dfNoData = CPLAtofM(papszTokens[1]);
             bNoDataSet = TRUE;
         }
-        else if( EQUAL(papszTokens[0],"NBITS") )
+        else if( EQUAL(papszTokens[0], "NBITS") )
         {
             nBits = atoi(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"PIXELTYPE") )
+        else if( EQUAL(papszTokens[0], "PIXELTYPE") )
         {
-            chPixelType = static_cast<char>( toupper(papszTokens[1][0]) );
+            chPixelType = static_cast<char>(toupper(papszTokens[1][0]));
         }
-        else if( EQUAL(papszTokens[0],"byteorder") )
+        else if( EQUAL(papszTokens[0], "byteorder") )
         {
-            chByteOrder = static_cast<char>( toupper(papszTokens[1][0]) );
+            chByteOrder = static_cast<char>(toupper(papszTokens[1][0]));
         }
 
-        /* http://www.worldclim.org/futdown.htm have the projection extensions */
-        else if( EQUAL(papszTokens[0],"Projection") )
+        // http://www.worldclim.org/futdown.htm have the projection extensions
+        else if( EQUAL(papszTokens[0], "Projection") )
         {
             bHasInternalProjection = TRUE;
         }
-        else if( EQUAL(papszTokens[0],"MinValue") ||
-                 EQUAL(papszTokens[0],"MIN_VALUE") )
+        else if( EQUAL(papszTokens[0], "MinValue") ||
+                 EQUAL(papszTokens[0], "MIN_VALUE") )
         {
             dfMin = CPLAtofM(papszTokens[1]);
             bHasMin = TRUE;
         }
-        else if( EQUAL(papszTokens[0],"MaxValue") ||
-                 EQUAL(papszTokens[0],"MAX_VALUE") )
+        else if( EQUAL(papszTokens[0], "MaxValue") ||
+                 EQUAL(papszTokens[0], "MAX_VALUE") )
         {
             dfMax = CPLAtofM(papszTokens[1]);
             bHasMax = TRUE;
         }
 
-        CSLDestroy( papszTokens );
+        CSLDestroy(papszTokens);
     }
 
-    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
 
-/* -------------------------------------------------------------------- */
-/*      Did we get the required keywords?  If not we return with        */
-/*      this never having been considered to be a match. This isn't     */
-/*      an error!                                                       */
-/* -------------------------------------------------------------------- */
+    // Did we get the required keywords?  If not, return with this never having
+    // been considered to be a match. This isn't an error!
     if( nRows == -1 || nCols == -1 )
     {
-        CSLDestroy( papszHDR );
+        CSLDestroy(papszHDR);
         return NULL;
     }
 
     if (!GDALCheckDatasetDimensions(nCols, nRows) ||
         !GDALCheckBandCount(nBands, FALSE))
     {
-        CSLDestroy( papszHDR );
+        CSLDestroy(papszHDR);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Has the user selected the .hdr file to open?                    */
-/* -------------------------------------------------------------------- */
+    // Has the caller selected the .hdr file to open?
     if( bSelectedHDR )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "The selected file is an ESRI BIL header file, but to "
-                  "open ESRI BIL datasets, the data file should be selected "
-                  "instead of the .hdr file.  Please try again selecting "
-                  "the data file (often with the extension .bil) corresponding "
-                  "to the header file: %s",
-                  poOpenInfo->pszFilename );
-        CSLDestroy( papszHDR );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The selected file is an ESRI BIL header file, but to "
+                 "open ESRI BIL datasets, the data file should be selected "
+                 "instead of the .hdr file.  Please try again selecting "
+                 "the data file (often with the extension .bil) corresponding "
+                 "to the header file: %s",
+                 poOpenInfo->pszFilename);
+        CSLDestroy(papszHDR);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we aren't sure of the file type, check the data file         */
-/*      size.  If it is 4 bytes or more per pixel then we assume it     */
-/*      is floating point data.                                         */
-/* -------------------------------------------------------------------- */
+    // If we aren't sure of the file type, check the data file size.  If it is 4
+    // bytes or more per pixel then we assume it is floating point data.
     if( nBits == -1 && chPixelType == 'N' )
     {
         VSIStatBufL sStatBuf;
-        if( VSIStatL( poOpenInfo->pszFilename, &sStatBuf ) == 0 )
+        if( VSIStatL(poOpenInfo->pszFilename, &sStatBuf) == 0 )
         {
-            const size_t nBytes
-                = static_cast<size_t>( sStatBuf.st_size/nCols/nRows/nBands );
+            const size_t nBytes =
+                static_cast<size_t>(sStatBuf.st_size/nCols/nRows/nBands);
             if( nBytes > 0 && nBytes != 3 )
                 nBits = static_cast<int>(nBytes * 8);
 
@@ -1299,67 +1152,54 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      If the extension is FLT it is likely a floating point file.     */
-/* -------------------------------------------------------------------- */
+    // If the extension is FLT it is likely a floating point file.
     if( chPixelType == 'N' )
     {
-        if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "FLT" ) )
+        if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "FLT") )
             chPixelType = 'F';
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we have a negative nodata value, let's assume that the       */
-/*      pixel type is signed. This is necessary for datasets from       */
-/*      http://www.worldclim.org/futdown.htm                            */
-/* -------------------------------------------------------------------- */
+    // If we have a negative nodata value, assume that the
+    // pixel type is signed. This is necessary for datasets from
+    // http://www.worldclim.org/futdown.htm
+
     if( bNoDataSet && dfNoData < 0 && chPixelType == 'N' )
     {
         chPixelType = 'S';
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
     EHdrDataset *poDS = new EHdrDataset();
 
     poDS->osHeaderExt = pszHeaderExt;
 
-/* -------------------------------------------------------------------- */
-/*      Capture some information from the file that is of interest.     */
-/* -------------------------------------------------------------------- */
     poDS->nRasterXSize = nCols;
     poDS->nRasterYSize = nRows;
     poDS->papszHDR = papszHDR;
 
-/* -------------------------------------------------------------------- */
-/*      Open target binary file.                                        */
-/* -------------------------------------------------------------------- */
+    // Open target binary file.
     if( poOpenInfo->eAccess == GA_ReadOnly )
-        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+        poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
     else
-        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
+        poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "r+b");
 
     if( poDS->fpImage == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to open %s with write permission.\n%s",
-                  osName.c_str(), VSIStrerror( errno ) );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Failed to open %s with write permission.\n%s",
+                 osName.c_str(), VSIStrerror(errno));
         delete poDS;
         return NULL;
     }
 
     poDS->eAccess = poOpenInfo->eAccess;
 
-/* -------------------------------------------------------------------- */
-/*      Figure out the data type.                                       */
-/* -------------------------------------------------------------------- */
+    // Figure out the data type.
     if( nBits == 16 )
     {
         if ( chPixelType == 'S' )
             eDataType = GDT_Int16;
         else
-            eDataType = GDT_UInt16; // default
+            eDataType = GDT_UInt16;  // Default
     }
     else if( nBits == 32 )
     {
@@ -1368,7 +1208,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         else if( chPixelType == 'F' )
             eDataType = GDT_Float32;
         else
-            eDataType = GDT_UInt32; // default
+            eDataType = GDT_UInt32;  // Default
     }
     else if( nBits == 8 )
     {
@@ -1376,7 +1216,9 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
         nBits = 8;
     }
     else if( nBits < 8 && nBits >= 1 )
+    {
         eDataType = GDT_Byte;
+    }
     else if( nBits == -1 )
     {
         if( chPixelType == 'F' )
@@ -1392,87 +1234,81 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "EHdr driver does not support %d NBITS value.",
-                  nBits );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "EHdr driver does not support %d NBITS value.",
+                 nBits);
         delete poDS;
         poDS = NULL;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Compute the line offset.                                        */
-/* -------------------------------------------------------------------- */
+    // Compute the line offset.
     const int nItemSize = GDALGetDataTypeSizeBytes(eDataType);
-    int nPixelOffset = 0;
-    int nLineOffset = 0;
-    vsi_l_offset    nBandOffset;
     CPLAssert(nItemSize != 0);
     CPLAssert(nBands != 0);
 
+    int nPixelOffset = 0;
+    int nLineOffset = 0;
+    vsi_l_offset nBandOffset = 0;
+
     if( EQUAL(szLayout, "BIP") )
     {
-        if (nCols > INT_MAX / (nItemSize * nBands))
+        if (nCols > std::numeric_limits<int>::max() / (nItemSize * nBands))
         {
             delete poDS;
             poDS = NULL;
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Int overflow occurred.");
+            CPLError(CE_Failure, CPLE_AppDefined, "Int overflow occurred.");
             return NULL;
         }
         nPixelOffset = nItemSize * nBands;
         nLineOffset = nPixelOffset * nCols;
-        nBandOffset = (vsi_l_offset)nItemSize;
+        nBandOffset = static_cast<vsi_l_offset>(nItemSize);
     }
-    else if( EQUAL(szLayout,"BSQ") )
+    else if( EQUAL(szLayout, "BSQ") )
     {
-        if (nCols > INT_MAX / nItemSize)
+        if (nCols > std::numeric_limits<int>::max() / nItemSize)
         {
             delete poDS;
             poDS = NULL;
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Int overflow occurred.");
+            CPLError(CE_Failure, CPLE_AppDefined, "Int overflow occurred.");
             return NULL;
         }
         nPixelOffset = nItemSize;
         nLineOffset = nPixelOffset * nCols;
-        nBandOffset = (vsi_l_offset)nLineOffset * nRows;
+        nBandOffset = static_cast<vsi_l_offset>(nLineOffset) * nRows;
     }
-    else /* assume BIL */
+    else
     {
-        if (nCols > INT_MAX / (nItemSize * nBands))
+        // Assume BIL.
+        if (nCols > std::numeric_limits<int>::max() / (nItemSize * nBands))
         {
             delete poDS;
             poDS = NULL;
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Int overflow occurred.");
+            CPLError(CE_Failure, CPLE_AppDefined, "Int overflow occurred.");
             return NULL;
         }
         nPixelOffset = nItemSize;
         nLineOffset = nItemSize * nBands * nCols;
-        nBandOffset = (vsi_l_offset)nItemSize * nCols;
+        nBandOffset = static_cast<vsi_l_offset>(nItemSize) * nCols;
     }
 
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    poDS->SetDescription(poOpenInfo->pszFilename);
     poDS->PamInitialize();
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
+    // Create band information objects.
     poDS->nBands = nBands;
     CPLErrorReset();
     for( int i = 0; i < poDS->nBands; i++ )
     {
-        EHdrRasterBand *poBand =
-            new EHdrRasterBand( poDS, i+1, poDS->fpImage,
-                                nSkipBytes + nBandOffset * i,
-                                nPixelOffset, nLineOffset, eDataType,
+        EHdrRasterBand *poBand = new EHdrRasterBand(
+            poDS, i + 1, poDS->fpImage, nSkipBytes + nBandOffset * i,
+            nPixelOffset, nLineOffset, eDataType,
 #ifdef CPL_LSB
-                                chByteOrder == 'I' || chByteOrder == 'L',
+            chByteOrder == 'I' || chByteOrder == 'L',
 #else
-                                chByteOrder == 'M',
+            chByteOrder == 'M',
 #endif
-                                nBits );
+            nBits);
 
         poBand->bNoDataSet = bNoDataSet;
         poBand->dfNoData = dfNoData;
@@ -1484,18 +1320,16 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
             poBand->minmaxmeanstddev = HAS_MIN_FLAG | HAS_MAX_FLAG;
         }
 
-        poDS->SetBand( i+1, poBand );
+        poDS->SetBand(i + 1, poBand);
         if( CPLGetLastErrorType() != CE_None )
         {
-            poDS->nBands = i+1;
+            poDS->nBands = i + 1;
             delete poDS;
             return NULL;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      If we didn't get bounds in the .hdr, look for a worldfile.      */
-/* -------------------------------------------------------------------- */
+    // If we didn't get bounds in the .hdr, look for a worldfile.
     if( dfYLLCorner != -123.456 )
     {
         if( bCenter )
@@ -1506,7 +1340,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( dfULXMap != 0.5 || dfULYMap != 0.5 || dfXDim != 1.0 || dfYDim != 1.0 )
     {
-        poDS->bGotTransform = TRUE;
+        poDS->bGotTransform = true;
 
         if( bCenter )
         {
@@ -1529,46 +1363,44 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     if( !poDS->bGotTransform )
-        poDS->bGotTransform =
-            GDALReadWorldFile( poOpenInfo->pszFilename, NULL,
-                               poDS->adfGeoTransform );
+        poDS->bGotTransform = CPL_TO_BOOL(
+            GDALReadWorldFile(poOpenInfo->pszFilename, NULL,
+                              poDS->adfGeoTransform));
 
     if( !poDS->bGotTransform )
-        poDS->bGotTransform =
-            GDALReadWorldFile( poOpenInfo->pszFilename, "wld",
-                               poDS->adfGeoTransform );
+        poDS->bGotTransform = CPL_TO_BOOL(
+            GDALReadWorldFile(poOpenInfo->pszFilename, "wld",
+                              poDS->adfGeoTransform));
 
-/* -------------------------------------------------------------------- */
-/*      Check for a .prj file.                                          */
-/* -------------------------------------------------------------------- */
-    const char *pszPrjFilename = CPLFormCIFilename( osPath, osName, "prj" );
+    // Check for a .prj file.
+    const char *pszPrjFilename = CPLFormCIFilename(osPath, osName, "prj");
 
-    fp = VSIFOpenL( pszPrjFilename, "r" );
+    fp = VSIFOpenL(pszPrjFilename, "r");
 
     // .hdr files from http://www.worldclim.org/futdown.htm have the projection
     // info in the .hdr file itself.
     if (fp == NULL && bHasInternalProjection)
     {
         pszPrjFilename = osHDRFilename;
-        fp = VSIFOpenL( pszPrjFilename, "r" );
+        fp = VSIFOpenL(pszPrjFilename, "r");
     }
 
     if( fp != NULL )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         fp = NULL;
 
-        char **papszLines = CSLLoad( pszPrjFilename );
+        char **papszLines = CSLLoad(pszPrjFilename);
 
         OGRSpatialReference oSRS;
-        if( oSRS.importFromESRI( papszLines ) == OGRERR_NONE )
+        if( oSRS.importFromESRI(papszLines) == OGRERR_NONE )
         {
             // If geographic values are in seconds, we must transform.
             // Is there a code for minutes too?
             char szResult[80] = { '\0' };
             if( oSRS.IsGeographic()
-                && EQUAL(OSR_GDS( szResult, sizeof(szResult),
-                                  papszLines, "Units", ""), "DS") )
+                && EQUAL(OSR_GDS(szResult, sizeof(szResult),
+                                 papszLines, "Units", ""), "DS") )
             {
                 poDS->adfGeoTransform[0] /= 3600.0;
                 poDS->adfGeoTransform[1] /= 3600.0;
@@ -1578,25 +1410,23 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
                 poDS->adfGeoTransform[5] /= 3600.0;
             }
 
-            CPLFree( poDS->pszProjection );
-            oSRS.exportToWkt( &(poDS->pszProjection) );
+            CPLFree(poDS->pszProjection);
+            oSRS.exportToWkt(&(poDS->pszProjection));
         }
 
-        CSLDestroy( papszLines );
+        CSLDestroy(papszLines);
     }
     else
     {
-/* -------------------------------------------------------------------- */
-/*  Check for IMAGE.REP (Spatiocarte Defense 1.0) or name_of_image.rep  */
-/*  if it's a GIS-GeoSPOT image                                         */
-/*  For the specification of SPDF (in French),                          */
-/*   see http://eden.ign.fr/download/pub/doc/emabgi/spdf10.pdf/download */
-/* -------------------------------------------------------------------- */
+        // Check for IMAGE.REP (Spatiocarte Defense 1.0) or name_of_image.rep
+        // if it's a GIS-GeoSPOT image
+        // For the specification of SPDF (in French), see
+        //   http://eden.ign.fr/download/pub/doc/emabgi/spdf10.pdf/download
         const CPLString szImageRepFilename =
-            GetImageRepFilename(poOpenInfo->pszFilename );
+            GetImageRepFilename(poOpenInfo->pszFilename);
         if (!szImageRepFilename.empty())
         {
-            fp = VSIFOpenL( szImageRepFilename.c_str(), "r" );
+            fp = VSIFOpenL(szImageRepFilename.c_str(), "r");
         }
         if (fp != NULL)
         {
@@ -1606,7 +1436,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
             bool bSouth = false;
             int utmZone = 0;
 
-            while( (pszLine = CPLReadLineL( fp )) != NULL )
+            while( (pszLine = CPLReadLineL(fp)) != NULL )
             {
                 if (STARTS_WITH(pszLine, "PROJ_ID") &&
                     strstr(pszLine, "UTM"))
@@ -1615,7 +1445,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
                 else if (STARTS_WITH(pszLine, "PROJ_ZONE"))
                 {
-                    const char* c = strchr(pszLine, '"');
+                    const char *c = strchr(pszLine, '"');
                     if (c)
                     {
                         c++;
@@ -1641,7 +1471,7 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
                 else if (STARTS_WITH(pszLine, "PROJ_CODE") &&
                          strstr(pszLine, "FR-MINDEF"))
                 {
-                    const char* c = strchr(pszLine, 'A');
+                    const char *c = strchr(pszLine, 'A');
                     if (c)
                     {
                         c++;
@@ -1672,63 +1502,62 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
                 else if(STARTS_WITH(pszLine, "MAP_NUMBER") )
                 {
-                    const char* c = strchr(pszLine, '"');
+                    const char *c = strchr(pszLine, '"');
                     if (c)
                     {
-                        char* pszMapNumber = CPLStrdup(c+1);
-                        char* c2 = strchr(pszMapNumber, '"');
-                        if (c2) *c2 = 0;
+                        char *pszMapNumber = CPLStrdup(c + 1);
+                        char *c2 = strchr(pszMapNumber, '"');
+                        if (c2)
+                            *c2 = 0;
                         poDS->SetMetadataItem("SPDF_MAP_NUMBER", pszMapNumber);
                         CPLFree(pszMapNumber);
                     }
                 }
                 else if (STARTS_WITH(pszLine, "PRODUCTION_DATE"))
                 {
-                    const char* c = pszLine + strlen("PRODUCTION_DATE");
+                    const char *c = pszLine + strlen("PRODUCTION_DATE");
                     while(*c == ' ')
                         c++;
                     if (*c)
                     {
-                        poDS->SetMetadataItem("SPDF_PRODUCTION_DATE", c );
+                        poDS->SetMetadataItem("SPDF_PRODUCTION_DATE", c);
                     }
                 }
             }
 
-            CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+            CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
 
             if (utmZone != 0 && bUTM && bWGS84 && (bNorth || bSouth))
             {
                 char projCSStr[64] = { '\0' };
                 snprintf(projCSStr, sizeof(projCSStr), "WGS 84 / UTM zone %d%c",
-                        utmZone, (bNorth) ? 'N' : 'S');
+                         utmZone, (bNorth) ? 'N' : 'S');
 
                 OGRSpatialReference oSRS;
                 oSRS.SetProjCS(projCSStr);
-                oSRS.SetWellKnownGeogCS( "WGS84" );
+                oSRS.SetWellKnownGeogCS("WGS84");
                 oSRS.SetUTM(utmZone, bNorth);
                 oSRS.SetAuthority("PROJCS", "EPSG",
                                   (bNorth ? 32600 : 32700) + utmZone);
                 oSRS.AutoIdentifyEPSG();
 
-                CPLFree( poDS->pszProjection );
-                oSRS.exportToWkt( &(poDS->pszProjection) );
+                CPLFree(poDS->pszProjection);
+                oSRS.exportToWkt(&(poDS->pszProjection));
             }
             else
             {
-                CPLError( CE_Warning, CPLE_NotSupported,
-                          "Cannot retrieve projection from IMAGE.REP" );
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "Cannot retrieve projection from IMAGE.REP");
             }
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check for a color table.                                        */
-/* -------------------------------------------------------------------- */
-    const char  *pszCLRFilename = CPLFormCIFilename( osPath, osName, "clr" );
+    // Check for a color table.
+    const char *pszCLRFilename = CPLFormCIFilename(osPath, osName, "clr");
 
-    /* Only read the .clr for byte, int16 or uint16 bands */
+    // Only read the .clr for byte, int16 or uint16 bands.
     if (nItemSize <= 2)
-        fp = VSIFOpenL( pszCLRFilename, "r" );
+        fp = VSIFOpenL(pszCLRFilename, "r");
     else
         fp = NULL;
 
@@ -1739,74 +1568,67 @@ GDALDataset *EHdrDataset::Open( GDALOpenInfo * poOpenInfo )
 
         while( true )
         {
-            pszLine =  CPLReadLineL(fp);
+            pszLine = CPLReadLineL(fp);
             if ( !pszLine )
                 break;
 
             if( *pszLine == '#' || *pszLine == '!' )
                 continue;
 
-            char **papszValues = CSLTokenizeString2(pszLine, "\t ",
-                                                    CSLT_HONOURSTRINGS);
-
+            char **papszValues =
+                CSLTokenizeString2(pszLine, "\t ", CSLT_HONOURSTRINGS);
 
             if ( CSLCount(papszValues) >= 4 )
             {
-                int nIndex = atoi( papszValues[0] ); // Index
+                const int nIndex = atoi(papszValues[0]);
                 if (nIndex >= 0 && nIndex < 65536)
                 {
-                    GDALColorEntry oEntry;
-                    oEntry.c1 =
-                        static_cast<short>( atoi( papszValues[1] ) ); // Red
-                    oEntry.c2 =
-                        static_cast<short>( atoi( papszValues[2] ) ); // Green
-                    oEntry.c3 =
-                        static_cast<short>( atoi( papszValues[3] ) ); // Blue
-                    oEntry.c4 = 255;
-
-                    oColorTable.SetColorEntry( nIndex, &oEntry );
+                    const GDALColorEntry oEntry =
+                    {
+                        static_cast<short>(atoi(papszValues[1])),  // Red
+                        static_cast<short>(atoi(papszValues[2])),  // Green
+                        static_cast<short>(atoi(papszValues[3])),  // Blue
+                        255
+                    };
+
+                    oColorTable.SetColorEntry(nIndex, &oEntry);
                 }
                 else
                 {
                     // Negative values are valid. At least we can find use of
-                    // them here: http://www.ngdc.noaa.gov/mgg/topo/elev/esri/clr/
-                    // but there's no way of representing them with GDAL color
+                    // them here:
+                    //   http://www.ngdc.noaa.gov/mgg/topo/elev/esri/clr/
+                    // But, there's no way of representing them with GDAL color
                     // table model.
                     if (!bHasWarned)
-                        CPLDebug( "EHdr", "Ignoring color index : %d", nIndex );
+                        CPLDebug("EHdr", "Ignoring color index : %d", nIndex);
                     bHasWarned = TRUE;
                 }
             }
 
-            CSLDestroy( papszValues );
+            CSLDestroy(papszValues);
         }
 
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
 
         for( int i = 1; i <= poDS->nBands; i++ )
         {
-            GDALRasterBand *poBand = poDS->GetRasterBand( i );
-            poBand->SetColorTable( &oColorTable );
-            poBand->SetColorInterpretation( GCI_PaletteIndex );
+            GDALRasterBand *poBand = poDS->GetRasterBand(i);
+            poBand->SetColorTable(&oColorTable);
+            poBand->SetColorInterpretation(GCI_PaletteIndex);
         }
 
-        poDS->bCLRDirty = FALSE;
+        poDS->bCLRDirty = false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read statistics (.STX)                                          */
-/* -------------------------------------------------------------------- */
+    // Read statistics (.STX).
     poDS->ReadSTX();
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
+    // Initialize any PAM information.
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Check for overviews.                                            */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    // Check for overviews.
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
 
     return poDS;
 }
@@ -1821,123 +1643,103 @@ GDALDataset *EHdrDataset::Create( const char * pszFilename,
                                   char **papszParmList )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Verify input options.                                           */
-/* -------------------------------------------------------------------- */
+    // Verify input options.
     if (nBands <= 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "EHdr driver does not support %d bands.\n", nBands);
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "EHdr driver does not support %d bands.", nBands);
         return NULL;
     }
 
-    if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16
-        && eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_UInt32 )
+    if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16 &&
+        eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_UInt32 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to create ESRI .hdr labelled dataset with an illegal"
-                  "data type (%s).",
-                  GDALGetDataTypeName(eType) );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Attempt to create ESRI .hdr labelled dataset with an illegal"
+                 "data type (%s).",
+                 GDALGetDataTypeName(eType));
 
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try to create the file.                                         */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
+    // Try to create the file.
+    VSILFILE *fp = VSIFOpenL(pszFilename, "wb");
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Attempt to create file `%s' failed.",
+                 pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Just write out a couple of bytes to establish the binary        */
-/*      file, and then close it.                                        */
-/* -------------------------------------------------------------------- */
-    bool bOK =
-        VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "\0\0" ) ),
-                    2, 1, fp ) == 1;
-    if( VSIFCloseL( fp ) != 0 )
+    // Just write out a couple of bytes to establish the binary
+    // file, and then close it.
+    bool bOK = VSIFWriteL(reinterpret_cast<void *>(const_cast<char *>("\0\0")),
+                          2, 1, fp) == 1;
+    if( VSIFCloseL(fp) != 0 )
         bOK = false;
     fp = NULL;
     if( !bOK )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Create the hdr filename.                                        */
-/* -------------------------------------------------------------------- */
-    char * const pszHdrFilename
-        = CPLStrdup( CPLResetExtension( pszFilename, "hdr" ) );
+    // Create the hdr filename.
+    char *const pszHdrFilename =
+        CPLStrdup(CPLResetExtension(pszFilename, "hdr"));
 
-/* -------------------------------------------------------------------- */
-/*      Open the file.                                                  */
-/* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszHdrFilename, "wt" );
+    // Open the file.
+    fp = VSIFOpenL(pszHdrFilename, "wt");
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
-                  pszHdrFilename );
-        CPLFree( pszHdrFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Attempt to create file `%s' failed.",
+                 pszHdrFilename);
+        CPLFree(pszHdrFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Decide how many bits the file should have.                      */
-/* -------------------------------------------------------------------- */
+    // Decide how many bits the file should have.
     int nBits = GDALGetDataTypeSize(eType);
 
-    if( CSLFetchNameValue( papszParmList, "NBITS" ) != NULL )
-        nBits = atoi(CSLFetchNameValue( papszParmList, "NBITS" ));
+    if( CSLFetchNameValue(papszParmList, "NBITS") != NULL )
+        nBits = atoi(CSLFetchNameValue(papszParmList, "NBITS"));
 
     const int nRowBytes = (nBits * nXSize + 7) / 8;
 
-/* -------------------------------------------------------------------- */
-/*      Check for signed byte.                                          */
-/* -------------------------------------------------------------------- */
-    const char *pszPixelType = CSLFetchNameValue( papszParmList, "PIXELTYPE" );
+    // Check for signed byte.
+    const char *pszPixelType = CSLFetchNameValue(papszParmList, "PIXELTYPE");
     if( pszPixelType == NULL )
         pszPixelType = "";
 
-/* -------------------------------------------------------------------- */
-/*      Write out the raw definition for the dataset as a whole.        */
-/* -------------------------------------------------------------------- */
-    bOK &= VSIFPrintfL( fp, "BYTEORDER      I\n" ) >= 0;
-    bOK &= VSIFPrintfL( fp, "LAYOUT         BIL\n" ) >= 0;
-    bOK &= VSIFPrintfL( fp, "NROWS          %d\n", nYSize ) >= 0;
-    bOK &= VSIFPrintfL( fp, "NCOLS          %d\n", nXSize ) >= 0;
-    bOK &= VSIFPrintfL( fp, "NBANDS         %d\n", nBands ) >= 0;
-    bOK &= VSIFPrintfL( fp, "NBITS          %d\n", nBits ) >= 0;
-    bOK &= VSIFPrintfL( fp, "BANDROWBYTES   %d\n", nRowBytes ) >= 0;
-    bOK &= VSIFPrintfL( fp, "TOTALROWBYTES  %d\n", nRowBytes * nBands ) >= 0;
+    // Write out the raw definition for the dataset as a whole.
+    bOK &= VSIFPrintfL(fp, "BYTEORDER      I\n") >= 0;
+    bOK &= VSIFPrintfL(fp, "LAYOUT         BIL\n") >= 0;
+    bOK &= VSIFPrintfL(fp, "NROWS          %d\n", nYSize) >= 0;
+    bOK &= VSIFPrintfL(fp, "NCOLS          %d\n", nXSize) >= 0;
+    bOK &= VSIFPrintfL(fp, "NBANDS         %d\n", nBands) >= 0;
+    bOK &= VSIFPrintfL(fp, "NBITS          %d\n", nBits) >= 0;
+    bOK &= VSIFPrintfL(fp, "BANDROWBYTES   %d\n", nRowBytes) >= 0;
+    bOK &= VSIFPrintfL(fp, "TOTALROWBYTES  %d\n", nRowBytes * nBands) >= 0;
 
     if( eType == GDT_Float32 )
-        bOK &= VSIFPrintfL( fp, "PIXELTYPE      FLOAT\n") >= 0;
+        bOK &= VSIFPrintfL(fp, "PIXELTYPE      FLOAT\n") >= 0;
     else if( eType == GDT_Int16 || eType == GDT_Int32 )
-        bOK &= VSIFPrintfL( fp, "PIXELTYPE      SIGNEDINT\n") >= 0;
-    else if( eType == GDT_Byte && EQUAL(pszPixelType,"SIGNEDBYTE") )
-        bOK &= VSIFPrintfL( fp, "PIXELTYPE      SIGNEDINT\n") >= 0;
+        bOK &= VSIFPrintfL(fp, "PIXELTYPE      SIGNEDINT\n") >= 0;
+    else if( eType == GDT_Byte && EQUAL(pszPixelType, "SIGNEDBYTE") )
+        bOK &= VSIFPrintfL(fp, "PIXELTYPE      SIGNEDINT\n") >= 0;
     else
-        bOK &= VSIFPrintfL( fp, "PIXELTYPE      UNSIGNEDINT\n") >= 0;
+        bOK &= VSIFPrintfL(fp, "PIXELTYPE      UNSIGNEDINT\n") >= 0;
 
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-    if( VSIFCloseL( fp ) != 0 )
+    if( VSIFCloseL(fp) != 0 )
         bOK = false;
 
-    CPLFree( pszHdrFilename );
+    CPLFree(pszHdrFilename);
 
     if( !bOK )
         return NULL;
 
     return
-        reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
+        reinterpret_cast<GDALDataset *>(GDALOpen(pszFilename, GA_Update));
 }
 
 /************************************************************************/
@@ -1954,53 +1756,43 @@ GDALDataset *EHdrDataset::CreateCopy( const char * pszFilename,
     const int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "EHdr driver does not support source dataset without any "
-                  "bands.\n" );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "EHdr driver does not support source dataset without any "
+                 "bands.");
         return NULL;
     }
 
-    char **papszAdjustedOptions = CSLDuplicate( papszOptions );
+    char **papszAdjustedOptions = CSLDuplicate(papszOptions);
 
-/* -------------------------------------------------------------------- */
-/*      Ensure we pass on NBITS and PIXELTYPE structure information.    */
-/* -------------------------------------------------------------------- */
-    if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS",
-                                                    "IMAGE_STRUCTURE" ) !=NULL
-        && CSLFetchNameValue( papszOptions, "NBITS" ) == NULL )
+    // Ensure we pass on NBITS and PIXELTYPE structure information.
+    if( poSrcDS->GetRasterBand(1)->GetMetadataItem("NBITS",
+                                                   "IMAGE_STRUCTURE") != NULL
+        && CSLFetchNameValue(papszOptions, "NBITS") == NULL )
     {
         papszAdjustedOptions =
-            CSLSetNameValue(
-                papszAdjustedOptions,
-                "NBITS",
-                poSrcDS->GetRasterBand(1)->
-                    GetMetadataItem("NBITS","IMAGE_STRUCTURE") );
+            CSLSetNameValue(papszAdjustedOptions, "NBITS",
+                            poSrcDS->GetRasterBand(1)->GetMetadataItem(
+                                "NBITS", "IMAGE_STRUCTURE"));
     }
 
-    if( poSrcDS->GetRasterBand(1)->GetMetadataItem( "PIXELTYPE",
-                                                    "IMAGE_STRUCTURE" ) !=NULL
-        && CSLFetchNameValue( papszOptions, "PIXELTYPE" ) == NULL )
+    if( poSrcDS->GetRasterBand(1)->GetMetadataItem("PIXELTYPE",
+                                                   "IMAGE_STRUCTURE") != NULL
+        && CSLFetchNameValue(papszOptions, "PIXELTYPE") == NULL )
     {
         papszAdjustedOptions =
-            CSLSetNameValue(
-                papszAdjustedOptions,
-                "PIXELTYPE",
-                poSrcDS->GetRasterBand(1)->
-                    GetMetadataItem("PIXELTYPE","IMAGE_STRUCTURE") );
+            CSLSetNameValue(papszAdjustedOptions, "PIXELTYPE",
+                            poSrcDS->GetRasterBand(1)->GetMetadataItem(
+                                "PIXELTYPE", "IMAGE_STRUCTURE"));
     }
 
-/* -------------------------------------------------------------------- */
-/*      Proceed with normal copying using the default createcopy        */
-/*      operators.                                                      */
-/* -------------------------------------------------------------------- */
-    GDALDriver *poDriver = reinterpret_cast<GDALDriver *>(
-        GDALGetDriverByName( "EHdr" ) );
+    // Proceed with normal copying using the default createcopy  operators.
+    GDALDriver *poDriver =
+        reinterpret_cast<GDALDriver *>(GDALGetDriverByName("EHdr"));
 
-    GDALDataset *poOutDS
-        = poDriver->DefaultCreateCopy( pszFilename, poSrcDS, bStrict,
-                                       papszAdjustedOptions,
-                                       pfnProgress, pProgressData );
-    CSLDestroy( papszAdjustedOptions );
+    GDALDataset *poOutDS = poDriver->DefaultCreateCopy(
+        pszFilename, poSrcDS, bStrict, papszAdjustedOptions, pfnProgress,
+        pProgressData);
+    CSLDestroy(papszAdjustedOptions);
 
     if( poOutDS != NULL )
         poOutDS->FlushCache();
@@ -2020,7 +1812,7 @@ double EHdrRasterBand::GetNoDataValue( int *pbSuccess )
     if( bNoDataSet )
         return dfNoData;
 
-    return RawRasterBand::GetNoDataValue( pbSuccess );
+    return RawRasterBand::GetNoDataValue(pbSuccess);
 }
 
 /************************************************************************/
@@ -2033,9 +1825,9 @@ double EHdrRasterBand::GetMinimum( int *pbSuccess )
         *pbSuccess = (minmaxmeanstddev & HAS_MIN_FLAG) != 0;
 
     if( minmaxmeanstddev & HAS_MIN_FLAG )
-      return dfMin;
+        return dfMin;
 
-    return RawRasterBand::GetMinimum( pbSuccess );
+    return RawRasterBand::GetMinimum(pbSuccess);
 }
 
 /************************************************************************/
@@ -2050,7 +1842,7 @@ double EHdrRasterBand::GetMaximum( int *pbSuccess )
     if( minmaxmeanstddev & HAS_MAX_FLAG )
       return dfMax;
 
-    return RawRasterBand::GetMaximum( pbSuccess );
+    return RawRasterBand::GetMaximum(pbSuccess);
 }
 
 /************************************************************************/
@@ -2071,18 +1863,18 @@ CPLErr EHdrRasterBand::GetStatistics(
         return CE_None;
     }
 
-    const CPLErr eErr = RawRasterBand::GetStatistics( bApproxOK, bForce,
-                                                &dfMin, &dfMax,
-                                                &dfMean, &dfStdDev );
+    const CPLErr eErr = RawRasterBand::GetStatistics(bApproxOK, bForce,
+                                                     &dfMin, &dfMax,
+                                                     &dfMean, &dfStdDev);
     if( eErr != CE_None )
         return eErr;
 
-    EHdrDataset* poEDS = reinterpret_cast<EHdrDataset *>( poDS );
+    EHdrDataset *poEDS = reinterpret_cast<EHdrDataset *>(poDS);
 
     minmaxmeanstddev = HAS_ALL_FLAGS;
 
     if( poEDS->RewriteSTX() != CE_None )
-        RawRasterBand::SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
+        RawRasterBand::SetStatistics(dfMin, dfMax, dfMean, dfStdDev);
 
     if( pdfMin )
         *pdfMin = dfMin;
@@ -2103,7 +1895,7 @@ CPLErr EHdrRasterBand::GetStatistics(
 CPLErr EHdrRasterBand::SetStatistics( double dfMinIn, double dfMaxIn,
                                       double dfMeanIn, double dfStdDevIn )
 {
-    // avoid churn if nothing is changing.
+    // Avoid churn if nothing is changing.
     if( dfMin == dfMinIn
         && dfMax == dfMaxIn
         && dfMean == dfMeanIn
@@ -2118,11 +1910,11 @@ CPLErr EHdrRasterBand::SetStatistics( double dfMinIn, double dfMaxIn,
     // marks stats valid
     minmaxmeanstddev = HAS_ALL_FLAGS;
 
-    EHdrDataset* poEDS = reinterpret_cast<EHdrDataset *>( poDS );
+    EHdrDataset *poEDS = reinterpret_cast<EHdrDataset *>(poDS);
 
     if( poEDS->RewriteSTX() != CE_None )
         return RawRasterBand::SetStatistics(
-            dfMinIn, dfMaxIn, dfMeanIn, dfStdDevIn );
+            dfMinIn, dfMaxIn, dfMeanIn, dfStdDevIn);
 
     return CE_None;
 }
@@ -2133,11 +1925,11 @@ CPLErr EHdrRasterBand::SetStatistics( double dfMinIn, double dfMaxIn,
 
 CPLErr EHdrRasterBand::SetColorTable( GDALColorTable *poNewCT )
 {
-    const CPLErr err = RawRasterBand::SetColorTable( poNewCT );
+    const CPLErr err = RawRasterBand::SetColorTable(poNewCT);
     if( err != CE_None )
         return err;
 
-    reinterpret_cast<EHdrDataset *>( poDS )->bCLRDirty = TRUE;
+    reinterpret_cast<EHdrDataset *>(poDS)->bCLRDirty = true;
 
     return CE_None;
 }
@@ -2149,28 +1941,28 @@ CPLErr EHdrRasterBand::SetColorTable( GDALColorTable *poNewCT )
 void GDALRegister_EHdr()
 
 {
-    if( GDALGetDriverByName( "EHdr" ) != NULL )
+    if( GDALGetDriverByName("EHdr") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "EHdr" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ESRI .hdr Labelled" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#EHdr" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                               "Byte Int16 UInt16 Int32 UInt32 Float32" );
+    poDriver->SetDescription("EHdr");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "ESRI .hdr Labelled");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#EHdr");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
+                              "Byte Int16 UInt16 Int32 UInt32 Float32");
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "   <Option name='NBITS' type='int' description='Special pixel bits (1-7)'/>"
 "   <Option name='PIXELTYPE' type='string' description='By setting this to SIGNEDBYTE, a new Byte file can be forced to be written as signed byte'/>"
 "</CreationOptionList>" );
 
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     poDriver->pfnOpen = EHdrDataset::Open;
     poDriver->pfnCreate = EHdrDataset::Create;
     poDriver->pfnCreateCopy = EHdrDataset::CreateCopy;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/raw/ehdrdataset.h b/frmts/raw/ehdrdataset.h
new file mode 100644
index 0000000..9308492
--- /dev/null
+++ b/frmts/raw/ehdrdataset.h
@@ -0,0 +1,169 @@
+/******************************************************************************
+ *
+ * Project:  ESRI .hdr Driver
+ * Purpose:  Implementation of EHdrDataset
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam <warmerdam at pobox.com>
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDAL_FRMTS_RAW_EHDRDATASET_H_INCLUDED
+#define GDAL_FRMTS_RAW_EHDRDATASET_H_INCLUDED
+
+#include "cpl_port.h"
+#include "rawdataset.h"
+
+#include <cctype>
+#include <cerrno>
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <limits>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_frmts.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
+#include "ogr_spatialref.h"
+
+/************************************************************************/
+/* ==================================================================== */
+/*                       EHdrDataset                                    */
+/* ==================================================================== */
+/************************************************************************/
+
+class EHdrRasterBand;
+
+class EHdrDataset : public RawDataset
+{
+    friend class EHdrRasterBand;
+
+    VSILFILE   *fpImage;  // image data file.
+
+    CPLString   osHeaderExt;
+
+    bool        bGotTransform;
+    double      adfGeoTransform[6];
+    char       *pszProjection;
+
+    bool        bHDRDirty;
+    char      **papszHDR;
+
+    bool        bCLRDirty;
+
+    CPLErr      ReadSTX();
+    CPLErr      RewriteSTX();
+    CPLErr      RewriteHDR();
+    void        ResetKeyValue( const char *pszKey, const char *pszValue );
+    const char *GetKeyValue( const char *pszKey, const char *pszDefault = "" );
+    void        RewriteColorTable( GDALColorTable * );
+
+  public:
+    EHdrDataset();
+    virtual ~EHdrDataset();
+
+    virtual CPLErr GetGeoTransform( double *padfTransform ) override;
+    virtual CPLErr SetGeoTransform( double *padfTransform ) override;
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr SetProjection( const char * ) override;
+
+    virtual char **GetFileList() override;
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static GDALDataset *Create( const char *pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType, char **papszParmList );
+    static GDALDataset *CreateCopy( const char *pszFilename,
+                                    GDALDataset *poSrcDS,
+                                    int bStrict, char **papszOptions,
+                                    GDALProgressFunc pfnProgress,
+                                    void *pProgressData );
+    static CPLString GetImageRepFilename(const char *pszFilename);
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                          EHdrRasterBand                              */
+/* ==================================================================== */
+/************************************************************************/
+
+class EHdrRasterBand : public RawRasterBand
+{
+   friend class EHdrDataset;
+
+    int            nBits;
+    vsi_l_offset   nStartBit;
+    int            nPixelOffsetBits;
+    vsi_l_offset   nLineOffsetBits;
+
+    int            bNoDataSet;  // TODO(schwehr): Convert to bool.
+    double         dfNoData;
+    double         dfMin;
+    double         dfMax;
+    double         dfMean;
+    double         dfStdDev;
+
+    int            minmaxmeanstddev;
+
+    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
+                              void *, int, int, GDALDataType,
+                              GSpacing nPixelSpace,
+                              GSpacing nLineSpace,
+                              GDALRasterIOExtraArg *psExtraArg ) override;
+
+  public:
+    EHdrRasterBand( GDALDataset *poDS, int nBand, VSILFILE *fpRaw,
+                    vsi_l_offset nImgOffset, int nPixelOffset,
+                    int nLineOffset,
+                    GDALDataType eDataType, int bNativeOrder,
+                    int nBits);
+    virtual ~EHdrRasterBand() {}
+
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
+
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum(int *pbSuccess = NULL ) override;
+    virtual CPLErr GetStatistics( int bApproxOK, int bForce,
+                                  double *pdfMin, double *pdfMax,
+                                  double *pdfMean, double *pdfStdDev ) override;
+    virtual CPLErr SetStatistics( double dfMin, double dfMax,
+                                  double dfMean, double dfStdDev ) override;
+    virtual CPLErr SetColorTable( GDALColorTable *poNewCT ) override;
+};
+
+#endif  // GDAL_FRMTS_RAW_EHDRDATASET_H_INCLUDED
diff --git a/frmts/raw/eirdataset.cpp b/frmts/raw/eirdataset.cpp
index 8fc8de2..864ba38 100644
--- a/frmts/raw/eirdataset.cpp
+++ b/frmts/raw/eirdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id:  $
  *
  * Project:  Erdas EIR Raw Driver
  * Purpose:  Implementation of EIRDataset
@@ -33,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id:  $");
+CPL_CVSID("$Id: eirdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -59,15 +58,14 @@ class EIRDataset : public RawDataset
     EIRDataset();
     virtual ~EIRDataset();
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
 
-    virtual char **GetFileList();
+    virtual char **GetFileList() override;
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                            EIRDataset                                */
@@ -84,7 +82,9 @@ EIRDataset::EIRDataset() :
     bHDRDirty(false),
     papszHDR(NULL),
     papszExtraFiles(NULL)
-{}
+{
+    memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
+}
 
 /************************************************************************/
 /*                            ~EIRDataset()                            */
@@ -177,7 +177,6 @@ void EIRDataset::ResetKeyValue( const char *pszKey, const char *pszValue )
     papszHDR = CSLAddString( papszHDR, szNewLine );
 }
 
-
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
@@ -334,8 +333,7 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         else if( EQUAL(papszTokens[0], "FORMAT") )
         {
-            strncpy( szLayout, papszTokens[1], sizeof(szLayout) );
-            szLayout[sizeof(szLayout)-1] = '\0';
+            snprintf( szLayout, sizeof(szLayout), "%s", papszTokens[1] );
         }
         else if( EQUAL(papszTokens[0], "DATATYPE")
                  || EQUAL(papszTokens[0], "DATA_TYPE") )
@@ -533,7 +531,6 @@ GDALDataset *EIRDataset::Open( GDALOpenInfo * poOpenInfo )
     return poDS;
 }
 
-
 /************************************************************************/
 /*                         GDALRegister_EIR()                           */
 /************************************************************************/
diff --git a/frmts/raw/envidataset.cpp b/frmts/raw/envidataset.cpp
index 331635f..7bd412d 100644
--- a/frmts/raw/envidataset.cpp
+++ b/frmts/raw/envidataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: envidataset.cpp 35524 2016-09-27 13:21:23Z rouault $
  *
  * Project:  ENVI .hdr Driver
  * Purpose:  Implementation of ENVI .hdr labelled raw raster support.
@@ -29,13 +28,38 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "envidataset.h"
+#include "rawdataset.h"
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
+#include <limits>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_frmts.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
 #include "ogr_spatialref.h"
-#include "rawdataset.h"
-#include <algorithm>
+#include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: envidataset.cpp 35524 2016-09-27 13:21:23Z rouault $");
+CPL_CVSID("$Id: envidataset.cpp 37530 2017-02-28 23:18:19Z goatbar $");
+
+// TODO(schwehr): This really should be defined in port/somewhere.h.
+static const double kdfDegToRad = M_PI / 180.0;
+static const double kdfRadToDeg = 180.0 / M_PI;
 
 static const int anUsgsEsriZones[] =
 {
@@ -192,14 +216,15 @@ static const int anUsgsEsriZones[] =
 static int ITTVISToUSGSZone( int nITTVISZone )
 
 {
+    // TODO(schwehr): int anUsgsEsriZones[] -> a std::set and std::map.
     const int nPairs = sizeof(anUsgsEsriZones) / (2 * sizeof(int));
 
     // Default is to use the zone as-is, as long as it is in the
     // available list
     for( int i = 0; i < nPairs; i++ )
     {
-        if( anUsgsEsriZones[i*2] == nITTVISZone )
-            return anUsgsEsriZones[i*2];
+        if( anUsgsEsriZones[i * 2] == nITTVISZone )
+            return anUsgsEsriZones[i * 2];
     }
 
     // If not found in the new style, see if it is present in the
@@ -207,112 +232,14 @@ static int ITTVISToUSGSZone( int nITTVISZone )
     // often, but older files allowed it and may still exist.
     for( int i = 0; i < nPairs; i++ )
     {
-        if( anUsgsEsriZones[i*2+1] == nITTVISZone )
-            return anUsgsEsriZones[i*2];
+        if( anUsgsEsriZones[i * 2 + 1] == nITTVISZone )
+            return anUsgsEsriZones[i * 2];
     }
 
-    return nITTVISZone; // Perhaps it *is* the USGS zone?
+    return nITTVISZone;  // Perhaps it *is* the USGS zone?
 }
 
 /************************************************************************/
-/* ==================================================================== */
-/*                              ENVIDataset                             */
-/* ==================================================================== */
-/************************************************************************/
-
-class ENVIRasterBand;
-
-class ENVIDataset : public RawDataset
-{
-    friend class ENVIRasterBand;
-
-    VSILFILE   *fpImage;  // image data file.
-    VSILFILE   *fp;  // header file
-    char       *pszHDRFilename;
-
-    bool        bFoundMapinfo;
-    bool        bHeaderDirty;
-    bool        bFillFile;
-
-    double      adfGeoTransform[6];
-
-    char       *pszProjection;
-
-    char        **papszHeader;
-
-    CPLString   osStaFilename;
-
-    int         ReadHeader( VSILFILE * );
-    int         ProcessMapinfo( const char * );
-    void        ProcessRPCinfo( const char * ,int ,int);
-    void        ProcessStatsFile();
-    int         byteSwapInt(int);
-    float       byteSwapFloat(float);
-    double      byteSwapDouble(double);
-    void        SetENVIDatum( OGRSpatialReference *, const char * );
-    void        SetENVIEllipse( OGRSpatialReference *, char ** );
-    void        WriteProjectionInfo();
-    int         ParseRpcCoeffsMetaDataString( const char *psName,
-                                              char *papszVal[], int& idx );
-    int         WriteRpcInfo();
-    int         WritePseudoGcpInfo();
-
-    void        SetFillFile() { bFillFile = true; }
-
-    char        **SplitList( const char * );
-
-    enum Interleave { BSQ, BIL, BIP } interleave;
-    static int GetEnviType(GDALDataType eType);
-
-  public:
-            ENVIDataset();
-    virtual ~ENVIDataset();
-
-    virtual void    FlushCache( void );
-    virtual CPLErr  GetGeoTransform( double * padfTransform );
-    virtual CPLErr  SetGeoTransform( double * );
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr  SetProjection( const char * );
-    virtual char  **GetFileList(void);
-
-    virtual void        SetDescription( const char * );
-
-    virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
-    virtual CPLErr      SetMetadataItem( const char * pszName,
-                                         const char * pszValue,
-                                         const char * pszDomain = "" );
-    virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
-
-    static GDALDataset *Open( GDALOpenInfo * );
-    static GDALDataset *Create( const char * pszFilename,
-                                int nXSize, int nYSize, int nBands,
-                                GDALDataType eType, char ** papszOptions );
-};
-
-/************************************************************************/
-/* ==================================================================== */
-/*                            ENVIRasterBand                            */
-/* ==================================================================== */
-/************************************************************************/
-
-class ENVIRasterBand : public RawRasterBand
-{
-    public:
-                ENVIRasterBand( GDALDataset *poDS, int nBand, void * fpRaw,
-                                vsi_l_offset nImgOffset, int nPixelOffset,
-                                int nLineOffset,
-                                GDALDataType eDataType, int bNativeOrder,
-                                int bIsVSIL = FALSE, int bOwnsFP = FALSE );
-    virtual ~ENVIRasterBand() {}
-
-    virtual void        SetDescription( const char * );
-
-    virtual CPLErr SetCategoryNames( char ** );
-};
-
-/************************************************************************/
 /*                            ENVIDataset()                             */
 /************************************************************************/
 
@@ -350,37 +277,37 @@ ENVIDataset::~ENVIDataset()
         {
             const int nDataSize =
                 GDALGetDataTypeSizeBytes(GetRasterBand(1)->GetRasterDataType());
-            vsi_l_offset nExpectedFileSize =
+            const vsi_l_offset nExpectedFileSize =
                 static_cast<vsi_l_offset>(nRasterXSize) *
                 nRasterYSize * nBands * nDataSize;
-            if( VSIFSeekL( fpImage, 0, SEEK_END ) != 0 )
+            if( VSIFSeekL(fpImage, 0, SEEK_END) != 0 )
             {
                 CPLError(CE_Failure, CPLE_FileIO, "I/O error");
             }
             if( VSIFTellL(fpImage) < nExpectedFileSize)
             {
                 GByte byVal = 0;
-                if( VSIFSeekL( fpImage, nExpectedFileSize - 1, SEEK_SET ) != 0 ||
-                    VSIFWriteL( &byVal, 1, 1, fpImage ) == 0 )
+                if( VSIFSeekL(fpImage, nExpectedFileSize - 1, SEEK_SET) != 0 ||
+                    VSIFWriteL(&byVal, 1, 1, fpImage) == 0 )
                 {
                     CPLError(CE_Failure, CPLE_FileIO, "I/O error");
                 }
             }
         }
-        if( VSIFCloseL( fpImage ) != 0 )
+        if( VSIFCloseL(fpImage) != 0 )
         {
             CPLError(CE_Failure, CPLE_FileIO, "I/O error");
         }
     }
     if( fp )
     {
-        if( VSIFCloseL( fp ) != 0 )
+        if( VSIFCloseL(fp) != 0 )
         {
             CPLError(CE_Failure, CPLE_FileIO, "I/O error");
         }
     }
-    CPLFree( pszProjection );
-    CSLDestroy( papszHeader );
+    CPLFree(pszProjection);
+    CSLDestroy(papszHeader);
     CPLFree(pszHDRFilename);
 }
 
@@ -393,7 +320,7 @@ void ENVIDataset::FlushCache()
 {
     RawDataset::FlushCache();
 
-    GDALRasterBand* band = GetRasterCount() > 0 ? GetRasterBand(1) : NULL;
+    GDALRasterBand *band = GetRasterCount() > 0 ? GetRasterBand(1) : NULL;
 
     if ( band == NULL || !bHeaderDirty )
         return;
@@ -401,61 +328,56 @@ void ENVIDataset::FlushCache()
     // If opening an existing file in Update mode (i.e. "r+") we need to make
     // sure any existing content is cleared, otherwise the file may contain
     // trailing content from the previous write.
-    if( VSIFTruncateL( fp, 0 ) != 0 )
+    if( VSIFTruncateL(fp, 0) != 0 )
         return;
 
-    if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
+    if( VSIFSeekL(fp, 0, SEEK_SET) != 0 )
         return;
-/* -------------------------------------------------------------------- */
-/*      Rewrite out the header.                                           */
-/* -------------------------------------------------------------------- */
-    const int iBigEndian =
+
+    // Rewrite out the header.
 #ifdef CPL_LSB
-    0
+    const int iBigEndian = 0;
 #else
-    1
+    const int iBigEndian = 1;
 #endif
-        ;
 
-    bool bOK = VSIFPrintfL( fp, "ENVI\n" ) >= 0;
+    bool bOK = VSIFPrintfL(fp, "ENVI\n") >= 0;
     if ("" != sDescription)
-        bOK &= VSIFPrintfL( fp, "description = {\n%s}\n",
-                            sDescription.c_str()) >= 0;
-    bOK &= VSIFPrintfL( fp, "samples = %d\nlines   = %d\nbands   = %d\n",
-                        nRasterXSize, nRasterYSize, nBands ) >= 0;
+        bOK &= VSIFPrintfL(fp, "description = {\n%s}\n",
+                           sDescription.c_str()) >= 0;
+    bOK &= VSIFPrintfL(fp, "samples = %d\nlines   = %d\nbands   = %d\n",
+                       nRasterXSize, nRasterYSize, nBands) >= 0;
 
-    char** catNames = band->GetCategoryNames();
+    char **catNames = band->GetCategoryNames();
 
-    bOK &= VSIFPrintfL( fp, "header offset = 0\n") >= 0;
+    bOK &= VSIFPrintfL(fp, "header offset = 0\n") >= 0;
     if (NULL == catNames)
-        bOK &= VSIFPrintfL( fp, "file type = ENVI Standard\n" ) >= 0;
+        bOK &= VSIFPrintfL(fp, "file type = ENVI Standard\n") >= 0;
     else
-        bOK &= VSIFPrintfL( fp, "file type = ENVI Classification\n" ) >= 0;
+        bOK &= VSIFPrintfL(fp, "file type = ENVI Classification\n") >= 0;
 
     const int iENVIType = GetEnviType(band->GetRasterDataType());
-    bOK &= VSIFPrintfL( fp, "data type = %d\n", iENVIType ) >= 0;
+    bOK &= VSIFPrintfL(fp, "data type = %d\n", iENVIType) >= 0;
     const char *pszInterleaving = NULL;
     switch( interleave )
     {
-      case BIP:
-        pszInterleaving = "bip";  // Interleaved by pixel
+    case BIP:
+        pszInterleaving = "bip";  // Interleaved by pixel.
         break;
-      case BIL:
-        pszInterleaving = "bil";  // Interleaved by line
+    case BIL:
+        pszInterleaving = "bil";  // Interleaved by line.
         break;
-      case BSQ:
-        pszInterleaving = "bsq";  // Band sequential by default
+    case BSQ:
+        pszInterleaving = "bsq";  // Band sequential by default.
         break;
-      default:
+    default:
         pszInterleaving = "bsq";
         break;
     }
-    bOK &= VSIFPrintfL( fp, "interleave = %s\n", pszInterleaving) >= 0;
-    bOK &= VSIFPrintfL( fp, "byte order = %d\n", iBigEndian ) >= 0;
+    bOK &= VSIFPrintfL(fp, "interleave = %s\n", pszInterleaving) >= 0;
+    bOK &= VSIFPrintfL(fp, "byte order = %d\n", iBigEndian) >= 0;
 
-/* -------------------------------------------------------------------- */
-/*      Write class and color information                               */
-/* -------------------------------------------------------------------- */
+    // Write class and color information.
     catNames = band->GetCategoryNames();
     if (NULL != catNames)
     {
@@ -465,24 +387,23 @@ void ENVIDataset::FlushCache()
 
         if (nrClasses > 0)
         {
-            bOK &= VSIFPrintfL( fp, "classes = %d\n", nrClasses ) >= 0;
+            bOK &= VSIFPrintfL(fp, "classes = %d\n", nrClasses) >= 0;
 
-            GDALColorTable* colorTable = band->GetColorTable();
+            GDALColorTable *colorTable = band->GetColorTable();
             if (NULL != colorTable)
             {
-                int nrColors = colorTable->GetColorEntryCount();
-                if (nrColors > nrClasses)
-                    nrColors = nrClasses;
-                bOK &= VSIFPrintfL( fp, "class lookup = {\n") >= 0;
+                const int nrColors =
+                    std::min(nrClasses, colorTable->GetColorEntryCount());
+                bOK &= VSIFPrintfL(fp, "class lookup = {\n") >= 0;
                 for (int i = 0; i < nrColors; ++i)
                 {
-                    const GDALColorEntry* color = colorTable->GetColorEntry(i);
-                    bOK &= VSIFPrintfL( fp, "%d, %d, %d",
-                                        color->c1, color->c2, color->c3) >= 0;
+                    const GDALColorEntry *color = colorTable->GetColorEntry(i);
+                    bOK &= VSIFPrintfL(fp, "%d, %d, %d",
+                                       color->c1, color->c2, color->c3) >= 0;
                     if (i < nrColors - 1)
                     {
                         bOK &= VSIFPrintfL(fp, ", ") >= 0;
-                        if( 0 == (i+1) % 5 )
+                        if( 0 == (i + 1) % 5 )
                             bOK &= VSIFPrintfL(fp, "\n") >= 0;
                     }
                 }
@@ -492,72 +413,68 @@ void ENVIDataset::FlushCache()
             catNames = band->GetCategoryNames();
             if (NULL != *catNames)
             {
-                bOK &= VSIFPrintfL( fp, "class names = {\n%s", *catNames) >= 0;
-                catNames ++;
+                bOK &= VSIFPrintfL(fp, "class names = {\n%s", *catNames) >= 0;
+                catNames++;
                 int i = 0;
-                while (*catNames) {
-                    bOK &= VSIFPrintfL( fp, ",") >= 0;
+                while (*catNames)
+                {
+                    bOK &= VSIFPrintfL(fp, ",") >= 0;
                     if (0 == (++i) % 5)
                         bOK &= VSIFPrintfL(fp, "\n") >= 0;
-                    bOK &= VSIFPrintfL( fp, " %s", *catNames) >= 0;
-                    catNames ++;
+                    bOK &= VSIFPrintfL(fp, " %s", *catNames) >= 0;
+                    catNames++;
                 }
-                bOK &= VSIFPrintfL( fp, "}\n") >= 0;
+                bOK &= VSIFPrintfL(fp, "}\n") >= 0;
             }
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write the rest of header.                                       */
-/* -------------------------------------------------------------------- */
+    // Write the rest of header.
 
     // Only one map info type should be set:
     //     - rpc
     //     - pseudo/gcp
     //     - standard
-    if ( !WriteRpcInfo() ) // are rpcs in the metadata
+    if ( !WriteRpcInfo() )  // Are rpcs in the metadata?
     {
-        if ( !WritePseudoGcpInfo() ) // are gcps in the metadata
+        if ( !WritePseudoGcpInfo() )  // are gcps in the metadata
         {
-            WriteProjectionInfo(); // standard - affine xform/coord sys str
+            WriteProjectionInfo();  // standard - affine xform/coord sys str
         }
     }
 
-    bOK &= VSIFPrintfL( fp, "band names = {\n" ) >= 0;
+    bOK &= VSIFPrintfL(fp, "band names = {\n") >= 0;
     for ( int i = 1; i <= nBands; i++ )
     {
-        CPLString sBandDesc = GetRasterBand( i )->GetDescription();
+        CPLString sBandDesc = GetRasterBand(i)->GetDescription();
 
         if ( sBandDesc == "" )
-            sBandDesc = CPLSPrintf( "Band %d", i );
-        bOK &= VSIFPrintfL( fp, "%s", sBandDesc.c_str() ) >= 0;
+            sBandDesc = CPLSPrintf("Band %d", i);
+        bOK &= VSIFPrintfL(fp, "%s", sBandDesc.c_str()) >= 0;
         if ( i != nBands )
-            bOK &= VSIFPrintfL( fp, ",\n" ) >= 0;
+            bOK &= VSIFPrintfL(fp, ",\n") >= 0;
     }
-    bOK &= VSIFPrintfL( fp, "}\n" ) >= 0;
+    bOK &= VSIFPrintfL(fp, "}\n") >= 0;
 
-/* -------------------------------------------------------------------- */
-/*      Write the metadata that was read into the ENVI domain           */
-/* -------------------------------------------------------------------- */
-    char** papszENVIMetadata = GetMetadata("ENVI");
+    // Write the metadata that was read into the ENVI domain.
+    char **papszENVIMetadata = GetMetadata("ENVI");
 
     const int count = CSLCount(papszENVIMetadata);
 
-    // For every item of metadata in the ENVI domain
+    // For every item of metadata in the ENVI domain.
     for (int i = 0; i < count; i++)
     {
-        // Split the entry into two parts at the = character
+        // Split the entry into two parts at the = character.
         char *pszEntry = papszENVIMetadata[i];
-        char **papszTokens
-            = CSLTokenizeString2( pszEntry, "=",
-                                  CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
+        char **papszTokens = CSLTokenizeString2(
+            pszEntry, "=", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
 
         if (CSLCount(papszTokens) != 2)
         {
-            CPLDebug( "ENVI",
-                      "Line of header file could not be split at = into "
-                      "two elements: %s", papszENVIMetadata[i] );
-            CSLDestroy( papszTokens );
+            CPLDebug("ENVI",
+                     "Line of header file could not be split at = into "
+                     "two elements: %s", papszENVIMetadata[i]);
+            CSLDestroy(papszTokens);
             continue;
         }
         // Replace _'s in the string with spaces
@@ -580,18 +497,16 @@ void ENVIDataset::FlushCache()
              poKey == "map info" ||
              poKey == "projection info" )
         {
-            CSLDestroy( papszTokens );
+            CSLDestroy(papszTokens);
             continue;
         }
-        bOK &= VSIFPrintfL( fp, "%s = %s\n",
-                            poKey.c_str(), papszTokens[1]) >= 0;
-        CSLDestroy( papszTokens );
+        bOK &= VSIFPrintfL(fp, "%s = %s\n", poKey.c_str(), papszTokens[1]) >= 0;
+        CSLDestroy(papszTokens);
     }
 
     if( !bOK )
         return;
 
-    /* Clean dirty flag */
     bHeaderDirty = false;
 }
 
@@ -606,11 +521,11 @@ char **ENVIDataset::GetFileList()
     char **papszFileList = RawDataset::GetFileList();
 
     // Header file.
-    papszFileList = CSLAddString( papszFileList, pszHDRFilename );
+    papszFileList = CSLAddString(papszFileList, pszHDRFilename);
 
     // Statistics file
-    if (osStaFilename.size() != 0)
-        papszFileList = CSLAddString( papszFileList, osStaFilename );
+    if (!osStaFilename.empty())
+        papszFileList = CSLAddString(papszFileList, osStaFilename);
 
     return papszFileList;
 }
@@ -628,62 +543,52 @@ char **ENVIDataset::GetFileList()
 static int ENVIGetEPSGGeogCS( OGRSpatialReference *poThis )
 
 {
-    const char *pszAuthName = poThis->GetAuthorityName( "GEOGCS" );
+    const char *pszAuthName = poThis->GetAuthorityName("GEOGCS");
 
-/* -------------------------------------------------------------------- */
-/*      Do we already have it?                                          */
-/* -------------------------------------------------------------------- */
+    // Do we already have it?
     if( pszAuthName != NULL && EQUAL(pszAuthName, "epsg") )
-        return atoi(poThis->GetAuthorityCode( "GEOGCS" ));
+        return atoi(poThis->GetAuthorityCode("GEOGCS"));
 
-/* -------------------------------------------------------------------- */
-/*      Get the datum and geogcs names.                                 */
-/* -------------------------------------------------------------------- */
-    const char *pszGEOGCS = poThis->GetAttrValue( "GEOGCS" );
-    const char *pszDatum = poThis->GetAttrValue( "DATUM" );
+    // Get the datum and geogcs names.
+    const char *pszGEOGCS = poThis->GetAttrValue("GEOGCS");
+    const char *pszDatum = poThis->GetAttrValue("DATUM");
 
     // We can only operate on coordinate systems with a geogcs.
     if( pszGEOGCS == NULL || pszDatum == NULL )
         return -1;
 
-/* -------------------------------------------------------------------- */
-/*      Is this a "well known" geographic coordinate system?            */
-/* -------------------------------------------------------------------- */
-    const bool bWGS = strstr(pszGEOGCS,"WGS") != NULL
-        || strstr(pszDatum, "WGS")
-        || strstr(pszGEOGCS, "World Geodetic System")
-        || strstr(pszGEOGCS, "World_Geodetic_System")
-        || strstr(pszDatum, "World Geodetic System")
-        || strstr(pszDatum, "World_Geodetic_System");
-
-    const bool bNAD = strstr(pszGEOGCS,"NAD") != NULL
-        || strstr(pszDatum, "NAD")
-        || strstr(pszGEOGCS, "North American")
-        || strstr(pszGEOGCS, "North_American")
-        || strstr(pszDatum, "North American")
-        || strstr(pszDatum, "North_American");
-
-    if( bWGS && (strstr(pszGEOGCS,"84") || strstr(pszDatum,"84")) )
+    // Is this a "well known" geographic coordinate system?
+    const bool bWGS = strstr(pszGEOGCS, "WGS") ||
+                      strstr(pszDatum, "WGS") ||
+                      strstr(pszGEOGCS, "World Geodetic System") ||
+                      strstr(pszGEOGCS, "World_Geodetic_System") ||
+                      strstr(pszDatum, "World Geodetic System") ||
+                      strstr(pszDatum, "World_Geodetic_System");
+
+    const bool bNAD = strstr(pszGEOGCS, "NAD") ||
+                      strstr(pszDatum, "NAD") ||
+                      strstr(pszGEOGCS, "North American") ||
+                      strstr(pszGEOGCS, "North_American") ||
+                      strstr(pszDatum, "North American") ||
+                      strstr(pszDatum, "North_American");
+
+    if( bWGS && (strstr(pszGEOGCS, "84") || strstr(pszDatum, "84")) )
         return 4326;
 
-    if( bWGS && (strstr(pszGEOGCS,"72") || strstr(pszDatum,"72")) )
+    if( bWGS && (strstr(pszGEOGCS, "72") || strstr(pszDatum, "72")) )
         return 4322;
 
-    if( bNAD && (strstr(pszGEOGCS,"83") || strstr(pszDatum,"83")) )
+    if( bNAD && (strstr(pszGEOGCS, "83") || strstr(pszDatum, "83")) )
         return 4269;
 
-    if( bNAD && (strstr(pszGEOGCS,"27") || strstr(pszDatum,"27")) )
+    if( bNAD && (strstr(pszGEOGCS, "27") || strstr(pszDatum, "27")) )
         return 4267;
 
-/* -------------------------------------------------------------------- */
-/*      If we know the datum, associate the most likely GCS with        */
-/*      it.                                                             */
-/* -------------------------------------------------------------------- */
-    pszAuthName = poThis->GetAuthorityName( "GEOGCS|DATUM" );
+    // If we know the datum, associate the most likely GCS with it.
+    pszAuthName = poThis->GetAuthorityName("GEOGCS|DATUM");
 
-    if( pszAuthName != NULL
-        && EQUAL(pszAuthName,"epsg")
-        && poThis->GetPrimeMeridian() == 0.0 )
+    if( pszAuthName != NULL && EQUAL(pszAuthName, "epsg") &&
+        poThis->GetPrimeMeridian() == 0.0 )
     {
         const int nDatum = atoi(poThis->GetAuthorityCode("GEOGCS|DATUM"));
 
@@ -701,50 +606,71 @@ static int ENVIGetEPSGGeogCS( OGRSpatialReference *poThis )
 void ENVIDataset::WriteProjectionInfo()
 
 {
-/* -------------------------------------------------------------------- */
-/*      Format the location (geotransform) portion of the map info      */
-/*      line.                                                           */
-/* -------------------------------------------------------------------- */
-    CPLString   osLocation;
-    osLocation.Printf( "1, 1, %.15g, %.15g, %.15g, %.15g",
-                       adfGeoTransform[0], adfGeoTransform[3],
-                       adfGeoTransform[1], fabs(adfGeoTransform[5]) );
-
-/* -------------------------------------------------------------------- */
-/*      Minimal case - write out simple geotransform if we have a       */
-/*      non-default geotransform.                                       */
-/* -------------------------------------------------------------------- */
+    // Format the location (geotransform) portion of the map info line.
+    CPLString osLocation;
+    CPLString osRotation;
+
+    const double dfPixelXSize = sqrt(adfGeoTransform[1] * adfGeoTransform[1] +
+                                     adfGeoTransform[2] * adfGeoTransform[2]);
+    const double dfPixelYSize = sqrt(adfGeoTransform[4] * adfGeoTransform[4] +
+                                     adfGeoTransform[5] * adfGeoTransform[5]);
+    const bool bHasNonDefaultGT =
+        adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0 ||
+        adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0 ||
+        adfGeoTransform[4] != 0.0 || adfGeoTransform[5] != 1.0;
+    if( bHasNonDefaultGT )
+    {
+        const double dfRotation1 =
+            -atan2(-adfGeoTransform[2], adfGeoTransform[1]) * kdfRadToDeg;
+        const double dfRotation2 =
+            -atan2(-adfGeoTransform[4], -adfGeoTransform[5]) * kdfRadToDeg;
+        const double dfRotation = (dfRotation1 + dfRotation2) / 2.0;
+
+        if( fabs(dfRotation1 - dfRotation2) > 1e-5 )
+        {
+            CPLDebug("ENVI", "rot1 = %.15g, rot2 = %.15g",
+                     dfRotation1, dfRotation2);
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Geotransform matrix has non rotational terms");
+        }
+        if( fabs(dfRotation) > 1e-5 )
+        {
+            osRotation.Printf(", rotation=%.15g", dfRotation);
+        }
+    }
+
+    osLocation.Printf("1, 1, %.15g, %.15g, %.15g, %.15g",
+                      adfGeoTransform[0], adfGeoTransform[3],
+                      dfPixelXSize, dfPixelYSize);
+
+    // Minimal case - write out simple geotransform if we have a
+    // non-default geotransform.
+    const std::string osLocalCs = "LOCAL_CS";
     if( pszProjection == NULL || strlen(pszProjection) == 0  ||
-        ( strlen(pszProjection) >= 8 &&
-          STARTS_WITH(pszProjection, "LOCAL_CS") ) )
+        (strlen(pszProjection) >= osLocalCs.size() &&
+         STARTS_WITH(pszProjection, osLocalCs.c_str())) )
     {
-        if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
-            || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
-            || adfGeoTransform[4] != 0.0 || adfGeoTransform[5] != 1.0 )
+        if( bHasNonDefaultGT )
         {
-            const char* pszHemisphere = "North";
-            if( VSIFPrintfL( fp, "map info = {Arbitrary, %s, %d, %s}\n",
-                             osLocation.c_str(), 0, pszHemisphere) < 0 )
+            const char *pszHemisphere = "North";
+            if( VSIFPrintfL(fp, "map info = {Arbitrary, %s, %d, %s%s}\n",
+                            osLocation.c_str(), 0, pszHemisphere,
+                            osRotation.c_str()) < 0)
                 return;
         }
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Ingest WKT.                                                     */
-/* -------------------------------------------------------------------- */
+    // Ingest WKT.
     OGRSpatialReference oSRS;
 
     char *pszProj = pszProjection;
 
-    if( oSRS.importFromWkt( &pszProj ) != OGRERR_NONE )
+    if( oSRS.importFromWkt(&pszProj) != OGRERR_NONE )
         return;
 
-/* -------------------------------------------------------------------- */
-/*      Try to translate the datum and get major/minor ellipsoid        */
-/*      values.                                                         */
-/* -------------------------------------------------------------------- */
-    const int nEPSG_GCS = ENVIGetEPSGGeogCS( &oSRS );
+    // Try to translate the datum and get major/minor ellipsoid values.
+    const int nEPSG_GCS = ENVIGetEPSGGeogCS(&oSRS);
     CPLString osDatum;
 
     if( nEPSG_GCS == 4326 )
@@ -766,73 +692,65 @@ void ENVIDataset::WriteProjectionInfo()
     else if( nEPSG_GCS == 4275 )
         osDatum = "Nouvelle Triangulation Francaise IGN";
 
-    CPLString osCommaDatum;
-    if( osDatum != "" )
-        osCommaDatum.Printf( ",%s", osDatum.c_str() );
+    const CPLString osCommaDatum =
+        osDatum.empty() ? "" : ("," + osDatum);
 
     const double dfA = oSRS.GetSemiMajor();
     const double dfB = oSRS.GetSemiMinor();
 
-/* -------------------------------------------------------------------- */
-/*      Do we have unusual linear units?                                */
-/* -------------------------------------------------------------------- */
-    CPLString osOptionalUnits;
-    if( fabs(oSRS.GetLinearUnits() - 0.3048) < 0.0001 )
-        osOptionalUnits = ", units=Feet";
-
-/* -------------------------------------------------------------------- */
-/*      Handle UTM case.                                                */
-/* -------------------------------------------------------------------- */
-    const char *pszHemisphere = NULL;
-    const char  *pszProjName = oSRS.GetAttrValue("PROJECTION");
+    // Do we have unusual linear units?
+    const double dfFeetPerMeter = 0.3048;
+    const CPLString osOptionalUnits =
+        fabs(oSRS.GetLinearUnits() - dfFeetPerMeter) < 0.0001
+        ? ", units=Feet" : "";
+
+    // Handle UTM case.
+    const char *pszProjName = oSRS.GetAttrValue("PROJECTION");
     int bNorth = FALSE;
-    const int iUTMZone = oSRS.GetUTMZone( &bNorth );
+    const int iUTMZone = oSRS.GetUTMZone(&bNorth);
     bool bOK = true;
     if ( iUTMZone )
     {
-        if ( bNorth )
-            pszHemisphere = "North";
-        else
-            pszHemisphere = "South";
+        const char *pszHemisphere = bNorth ? "North" : "South";
 
-        bOK &=
-            VSIFPrintfL( fp, "map info = {UTM, %s, %d, %s%s%s}\n",
-                         osLocation.c_str(), iUTMZone, pszHemisphere,
-                         osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+        bOK &= VSIFPrintfL(fp, "map info = {UTM, %s, %d, %s%s%s%s}\n",
+                           osLocation.c_str(), iUTMZone, pszHemisphere,
+                           osCommaDatum.c_str(), osOptionalUnits.c_str(),
+                           osRotation.c_str()) >= 0;
     }
     else if( oSRS.IsGeographic() )
     {
-        bOK &=
-            VSIFPrintfL( fp, "map info = {Geographic Lat/Lon, %s%s}\n",
-                         osLocation.c_str(), osCommaDatum.c_str()) >= 0;
+        bOK &= VSIFPrintfL(fp, "map info = {Geographic Lat/Lon, %s%s%s}\n",
+                           osLocation.c_str(), osCommaDatum.c_str(),
+                           osRotation.c_str()) >= 0;
     }
     else if( pszProjName == NULL )
     {
-        // what to do?
+        // What to do?
     }
-    else if( EQUAL(pszProjName,SRS_PT_NEW_ZEALAND_MAP_GRID) )
+    else if( EQUAL(pszProjName, SRS_PT_NEW_ZEALAND_MAP_GRID) )
     {
-        bOK &= VSIFPrintfL( fp, "map info = {New Zealand Map Grid, %s%s%s}\n",
-                     osLocation.c_str(),
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+        bOK &= VSIFPrintfL(fp, "map info = {New Zealand Map Grid, %s%s%s%s}\n",
+                           osLocation.c_str(),
+                           osCommaDatum.c_str(), osOptionalUnits.c_str(),
+                           osRotation.c_str()) >= 0;
 
-        bOK &=
-            VSIFPrintfL(
-                fp,
-                "projection info = {39, %.16g, %.16g, %.16g, %.16g, "
-                "%.16g, %.16g%s, New Zealand Map Grid}\n",
-                dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                osCommaDatum.c_str() ) >= 0;
+        bOK &= VSIFPrintfL(fp,
+                           "projection info = {39, %.16g, %.16g, %.16g, %.16g, "
+                           "%.16g, %.16g%s, New Zealand Map Grid}\n",
+                           dfA, dfB,
+                           oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                           oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                           oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                           oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
+                           osCommaDatum.c_str()) >= 0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_TRANSVERSE_MERCATOR) )
+    else if( EQUAL(pszProjName, SRS_PT_TRANSVERSE_MERCATOR) )
     {
-        bOK &= VSIFPrintfL( fp, "map info = {Transverse Mercator, %s%s%s}\n",
-                     osLocation.c_str(),
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+        bOK &= VSIFPrintfL(fp, "map info = {Transverse Mercator, %s%s%s%s}\n",
+                           osLocation.c_str(),
+                           osCommaDatum.c_str(), osOptionalUnits.c_str(),
+                           osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -840,21 +758,19 @@ void ENVIDataset::WriteProjectionInfo()
                 "projection info = {3, %.16g, %.16g, %.16g, ""%.16g, %.16g, "
                 "%.16g, %.16g%s, Transverse Mercator}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                osCommaDatum.c_str() ) >= 0;
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                osCommaDatum.c_str()) >= 0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP)
-             || EQUAL(pszProjName,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
+    else if( EQUAL(pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) ||
+             EQUAL(pszProjName, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
     {
-        bOK &=
-            VSIFPrintfL(
-                fp, "map info = {Lambert Conformal Conic, %s%s%s}\n",
-                osLocation.c_str(),
-                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+        bOK &= VSIFPrintfL(fp, "map info = {Lambert Conformal Conic, %s%s%s%s}\n",
+                           osLocation.c_str(), osCommaDatum.c_str(),
+                           osOptionalUnits.c_str(), osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -862,23 +778,21 @@ void ENVIDataset::WriteProjectionInfo()
                 "projection info = {4, %.16g, %.16g, %.16g, %.16g, %.16g, "
                 "%.16g, %.16g, %.16g%s, Lambert Conformal Conic}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
-                osCommaDatum.c_str() ) >= 0;
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0),
+                osCommaDatum.c_str()) >= 0;
     }
     else if( EQUAL(pszProjName,
                    SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
     {
         bOK &=
-            VSIFPrintfL(
-                fp,
-                "map info = {Hotine Oblique Mercator A, %s%s%s}\n",
-                osLocation.c_str(),
-                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+            VSIFPrintfL(fp, "map info = {Hotine Oblique Mercator A, %s%s%s%s}\n",
+                        osLocation.c_str(), osCommaDatum.c_str(),
+                        osOptionalUnits.c_str(), osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -887,24 +801,22 @@ void ENVIDataset::WriteProjectionInfo()
                 "%.16g, %.16g, %.16g, %.16g, %.16g%s, "
                 "Hotine Oblique Mercator A}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1,0.0),
-                oSRS.GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1,0.0),
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2,0.0),
-                oSRS.GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                osCommaDatum.c_str() ) >= 0;
-    }
-    else if( EQUAL(pszProjName,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                osCommaDatum.c_str()) >= 0;
+    }
+    else if( EQUAL(pszProjName, SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     {
         bOK &=
-            VSIFPrintfL(
-                fp,
-                "map info = {Hotine Oblique Mercator B, %s%s%s}\n",
-                osLocation.c_str(),
-                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+            VSIFPrintfL(fp, "map info = {Hotine Oblique Mercator B, %s%s%s%s}\n",
+                        osLocation.c_str(), osCommaDatum.c_str(),
+                        osOptionalUnits.c_str(), osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -912,23 +824,21 @@ void ENVIDataset::WriteProjectionInfo()
                 "projection info = {6, %.16g, %.16g, %.16g, %.16g, %.16g, "
                 "%.16g, %.16g, %.16g%s, Hotine Oblique Mercator B}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_AZIMUTH,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_AZIMUTH, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
                 osCommaDatum.c_str() ) >= 0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_STEREOGRAPHIC)
-             || EQUAL(pszProjName,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
+    else if( EQUAL(pszProjName, SRS_PT_STEREOGRAPHIC) ||
+             EQUAL(pszProjName, SRS_PT_OBLIQUE_STEREOGRAPHIC) )
     {
         bOK &=
-            VSIFPrintfL(
-                fp,
-                "map info = {Stereographic (ellipsoid), %s%s%s}\n",
-                osLocation.c_str(),
-                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+            VSIFPrintfL(fp, "map info = {Stereographic (ellipsoid), %s%s%s%s}\n",
+                        osLocation.c_str(), osCommaDatum.c_str(),
+                        osOptionalUnits.c_str(), osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -936,21 +846,19 @@ void ENVIDataset::WriteProjectionInfo()
                 "projection info = {7, %.16g, %.16g, %.16g, %.16g, %.16g, "
                 "%.16g, %.16g, %s, Stereographic (ellipsoid)}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                osCommaDatum.c_str() ) >= 0;
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                osCommaDatum.c_str()) >= 0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
+    else if( EQUAL(pszProjName, SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
         bOK &=
-            VSIFPrintfL(
-                fp,
-                "map info = {Albers Conical Equal Area, %s%s%s}\n",
-                osLocation.c_str(),
-                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+            VSIFPrintfL(fp, "map info = {Albers Conical Equal Area, %s%s%s%s}\n",
+                        osLocation.c_str(), osCommaDatum.c_str(),
+                        osOptionalUnits.c_str(), osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -958,19 +866,20 @@ void ENVIDataset::WriteProjectionInfo()
                 "projection info = {9, %.16g, %.16g, %.16g, %.16g, %.16g, "
                 "%.16g, %.16g, %.16g%s, Albers Conical Equal Area}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
-                osCommaDatum.c_str() ) >= 0;
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0),
+                osCommaDatum.c_str()) >= 0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_POLYCONIC) )
+    else if( EQUAL(pszProjName, SRS_PT_POLYCONIC) )
     {
-        bOK &= VSIFPrintfL( fp, "map info = {Polyconic, %s%s%s}\n",
-                     osLocation.c_str(),
-                     osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+        bOK &= VSIFPrintfL(fp, "map info = {Polyconic, %s%s%s%s}\n",
+                           osLocation.c_str(),
+                           osCommaDatum.c_str(), osOptionalUnits.c_str(),
+                           osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -978,20 +887,18 @@ void ENVIDataset::WriteProjectionInfo()
                 "projection info = {10, %.16g, %.16g, %.16g, %.16g, %.16g, "
                 "%.16g%s, Polyconic}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
                 osCommaDatum.c_str() ) >= 0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
+    else if( EQUAL(pszProjName, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
-        bOK &=
-            VSIFPrintfL(
-                fp,
-                "map info = {Lambert Azimuthal Equal Area, %s%s%s}\n",
-                osLocation.c_str(),
-                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+        bOK &= VSIFPrintfL(
+                   fp, "map info = {Lambert Azimuthal Equal Area, %s%s%s%s}\n",
+                   osLocation.c_str(), osCommaDatum.c_str(),
+                   osOptionalUnits.c_str(), osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -999,20 +906,17 @@ void ENVIDataset::WriteProjectionInfo()
                 "projection info = {11, %.16g, %.16g, %.16g, %.16g, %.16g, "
                 "%.16g%s, Lambert Azimuthal Equal Area}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
                 osCommaDatum.c_str() ) >= 0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
+    else if( EQUAL(pszProjName, SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     {
-        bOK &=
-            VSIFPrintfL(
-                fp,
-                "map info = {Azimuthal Equadistant, %s%s%s}\n",
-                osLocation.c_str(),
-                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+        bOK &= VSIFPrintfL(fp, "map info = {Azimuthal Equadistant, %s%s%s%s}\n",
+                           osLocation.c_str(), osCommaDatum.c_str(),
+                           osOptionalUnits.c_str(), osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -1020,20 +924,17 @@ void ENVIDataset::WriteProjectionInfo()
                 "projection info = {12, %.16g, %.16g, %.16g, %.16g, %.16g, "
                 "%.16g%s, Azimuthal Equadistant}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
                 osCommaDatum.c_str() ) >= 0;
     }
-    else if( EQUAL(pszProjName,SRS_PT_POLAR_STEREOGRAPHIC) )
+    else if( EQUAL(pszProjName, SRS_PT_POLAR_STEREOGRAPHIC) )
     {
-        bOK &=
-            VSIFPrintfL(
-                fp,
-                "map info = {Polar Stereographic, %s%s%s}\n",
-                osLocation.c_str(),
-                osCommaDatum.c_str(), osOptionalUnits.c_str() ) >= 0;
+        bOK &= VSIFPrintfL(fp, "map info = {Polar Stereographic, %s%s%s%s}\n",
+                           osLocation.c_str(), osCommaDatum.c_str(),
+                           osOptionalUnits.c_str(), osRotation.c_str()) >= 0;
 
         bOK &=
             VSIFPrintfL(
@@ -1041,16 +942,16 @@ void ENVIDataset::WriteProjectionInfo()
                 "projection info = {31, %.16g, %.16g, %.16g, %.16g, %.16g, "
                 "%.16g%s, Polar Stereographic}\n",
                 dfA, dfB,
-                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,90.0),
-                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-                osCommaDatum.c_str() ) >= 0;
+                oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 90.0),
+                oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                oSRS.GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
+                osCommaDatum.c_str()) >= 0;
     }
     else
     {
-        bOK &= VSIFPrintfL( fp, "map info = {%s, %s}\n",
-                            pszProjName, osLocation.c_str()) >= 0;
+        bOK &= VSIFPrintfL(fp, "map info = {%s, %s}\n",
+                           pszProjName, osLocation.c_str()) >= 0;
     }
 
     // write out coordinate system string
@@ -1060,10 +961,8 @@ void ENVIDataset::WriteProjectionInfo()
         if ( oSRS.exportToWkt(&pszProjESRI) == OGRERR_NONE )
         {
             if ( strlen(pszProjESRI) )
-                bOK &=
-                    VSIFPrintfL(
-                        fp,
-                        "coordinate system string = {%s}\n", pszProjESRI) >= 0;
+                bOK &= VSIFPrintfL(fp, "coordinate system string = {%s}\n",
+                                   pszProjESRI) >= 0;
         }
         CPLFree(pszProjESRI);
         pszProjESRI = NULL;
@@ -1071,7 +970,7 @@ void ENVIDataset::WriteProjectionInfo()
 
     if( !bOK )
     {
-        CPLError( CE_Failure, CPLE_FileIO, "Write error" );
+        CPLError(CE_Failure, CPLE_FileIO, "Write error");
     }
 }
 
@@ -1079,20 +978,20 @@ void ENVIDataset::WriteProjectionInfo()
 /*                ParseRpcCoeffsMetaDataString()                        */
 /************************************************************************/
 
-int ENVIDataset::ParseRpcCoeffsMetaDataString(
-    const char *psName, char **papszVal, int& idx)
+bool ENVIDataset::ParseRpcCoeffsMetaDataString(
+    const char *psName, char **papszVal, int &idx)
 {
-    // separate one string with 20 coefficients into an array of 20 strings.
+    // Separate one string with 20 coefficients into an array of 20 strings.
     const char *psz20Vals = GetMetadataItem(psName, "RPC");
     if (!psz20Vals)
-        return FALSE;
+        return false;
 
-    char** papszArr = CSLTokenizeString2(psz20Vals, " ", 0);
+    char **papszArr = CSLTokenizeString2(psz20Vals, " ", 0);
     if (!papszArr)
-        return FALSE;
+        return false;
 
     int x = 0;
-    while ((papszArr[x] != NULL) && (x < 20))
+    while ( (x < 20) && (papszArr[x] != NULL) )
     {
         papszVal[idx++] = CPLStrdup(papszArr[x]);
         x++;
@@ -1105,24 +1004,24 @@ int ENVIDataset::ParseRpcCoeffsMetaDataString(
 
 static char *CPLStrdupIfNotNull( const char *pszString )
 {
-  if (! pszString )
+  if (!pszString )
       return NULL;
 
-  return CPLStrdup( pszString );
+  return CPLStrdup(pszString);
 }
 
-
 /************************************************************************/
 /*                          WriteRpcInfo()                              */
 /************************************************************************/
 
 // TODO: This whole function needs to be cleaned up.
-int ENVIDataset::WriteRpcInfo()
+bool ENVIDataset::WriteRpcInfo()
 {
     // Write out 90 rpc coeffs into the envi header plus 3 envi specific rpc
     // values returns 0 if the coeffs are not present or not valid.
     int idx = 0;
-    char* papszVal[93] = { NULL };
+    // TODO(schwehr): Make 93 a constant.
+    char *papszVal[93] = { NULL };
 
     papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("LINE_OFF", "RPC"));
     papszVal[idx++] = CPLStrdupIfNotNull(GetMetadataItem("SAMP_OFF", "RPC"));
@@ -1138,7 +1037,7 @@ int ENVIDataset::WriteRpcInfo()
 
     bool bRet = false;
 
-    for ( int x = 0; x < 10; x++ ) // If we do not have 10 values we return 0.
+    for ( int x = 0; x < 10; x++ )  // If we do not have 10 values we return 0.
     {
         if (!papszVal[x])
             goto end;
@@ -1175,25 +1074,25 @@ int ENVIDataset::WriteRpcInfo()
     {
         int x = 1;
         bRet &= VSIFPrintfL(fp, "rpc info = {\n") >= 0;
-        for( int iR=0; iR < 93; iR++ )
+        for( int iR = 0; iR < 93; iR++ )
         {
-          if( papszVal[iR][0] == '-' )
-              bRet &= VSIFPrintfL(fp, " %s", papszVal[iR]) >= 0;
-          else
-              bRet &= VSIFPrintfL(fp, "  %s", papszVal[iR]) >= 0;
+            if( papszVal[iR][0] == '-' )
+                bRet &= VSIFPrintfL(fp, " %s", papszVal[iR]) >= 0;
+            else
+                bRet &= VSIFPrintfL(fp, "  %s", papszVal[iR]) >= 0;
 
-          if( iR < 92 )
-              bRet &= VSIFPrintfL(fp, ",") >= 0;
+            if( iR < 92 )
+                bRet &= VSIFPrintfL(fp, ",") >= 0;
 
-          if( (x % 4) == 0 )
-              bRet &= VSIFPrintfL(fp, "\n") >= 0;
+            if( (x % 4) == 0 )
+                bRet &= VSIFPrintfL(fp, "\n") >= 0;
 
-          x++;
-          if( x > 4 )
-              x = 1;
+            x++;
+            if( x > 4 )
+                x = 1;
         }
     }
-    bRet &= VSIFPrintfL(fp, "}\n" ) >= 0;
+    bRet &= VSIFPrintfL(fp, "}\n") >= 0;
 
     // TODO(schwehr): Rewrite without goto.
 end:
@@ -1207,14 +1106,14 @@ end:
 /*                        WritePseudoGcpInfo()                          */
 /************************************************************************/
 
-int ENVIDataset::WritePseudoGcpInfo()
+bool ENVIDataset::WritePseudoGcpInfo()
 {
     // Write out gcps into the envi header
     // returns 0 if the gcps are not present.
 
     const int iNum = GetGCPCount();
     if (iNum == 0)
-      return FALSE;
+        return false;
 
     const GDAL_GCP *pGcpStructs = GetGCPs();
 
@@ -1226,15 +1125,15 @@ int ENVIDataset::WritePseudoGcpInfo()
     bool bRet = VSIFPrintfL(fp, "geo points = {\n") >= 0;
     for( int iR = 0; iR < iNum; iR++ )
     {
-      bRet &= VSIFPrintfL(
-          fp, " %#0.4f, %#0.4f, %#0.8f, %#0.8f",
-          pGcpStructs[iR].dfGCPPixel, pGcpStructs[iR].dfGCPLine,
-          pGcpStructs[iR].dfGCPY, pGcpStructs[iR].dfGCPX) >= 0;
-      if( iR < iNum - 1 )
-        bRet &= VSIFPrintfL(fp, ",\n") >= 0;
+        bRet &= VSIFPrintfL(
+            fp, " %#0.4f, %#0.4f, %#0.8f, %#0.8f",
+            pGcpStructs[iR].dfGCPPixel, pGcpStructs[iR].dfGCPLine,
+            pGcpStructs[iR].dfGCPY, pGcpStructs[iR].dfGCPX) >= 0;
+        if( iR < iNum - 1 )
+            bRet &= VSIFPrintfL(fp, ",\n") >= 0;
     }
 
-    bRet &= VSIFPrintfL(fp, "}\n" ) >= 0;
+    bRet &= VSIFPrintfL(fp, "}\n") >= 0;
 
     return bRet;
 }
@@ -1243,11 +1142,7 @@ int ENVIDataset::WritePseudoGcpInfo()
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char *ENVIDataset::GetProjectionRef()
-
-{
-    return pszProjection;
-}
+const char *ENVIDataset::GetProjectionRef() { return pszProjection; }
 
 /************************************************************************/
 /*                          SetProjection()                             */
@@ -1256,8 +1151,8 @@ const char *ENVIDataset::GetProjectionRef()
 CPLErr ENVIDataset::SetProjection( const char *pszNewProjection )
 
 {
-    CPLFree( pszProjection );
-    pszProjection = CPLStrdup( pszNewProjection );
+    CPLFree(pszProjection);
+    pszProjection = CPLStrdup(pszNewProjection);
 
     bHeaderDirty = true;
 
@@ -1268,10 +1163,10 @@ CPLErr ENVIDataset::SetProjection( const char *pszNewProjection )
 /*                          GetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr ENVIDataset::GetGeoTransform( double * padfTransform )
+CPLErr ENVIDataset::GetGeoTransform( double *padfTransform )
 
 {
-    memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
+    memcpy(padfTransform, adfGeoTransform, sizeof(double) * 6);
 
     if( bFoundMapinfo )
         return CE_None;
@@ -1283,9 +1178,9 @@ CPLErr ENVIDataset::GetGeoTransform( double * padfTransform )
 /*                          SetGeoTransform()                           */
 /************************************************************************/
 
-CPLErr ENVIDataset::SetGeoTransform( double * padfTransform )
+CPLErr ENVIDataset::SetGeoTransform( double *padfTransform )
 {
-    memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
+    memcpy(adfGeoTransform, padfTransform, sizeof(double) * 6);
 
     bHeaderDirty = true;
     bFoundMapinfo = true;
@@ -1297,7 +1192,7 @@ CPLErr ENVIDataset::SetGeoTransform( double * padfTransform )
 /*                           SetDescription()                           */
 /************************************************************************/
 
-void ENVIDataset::SetDescription( const char * pszDescription )
+void ENVIDataset::SetDescription( const char *pszDescription )
 {
     bHeaderDirty = true;
     RawDataset::SetDescription(pszDescription);
@@ -1307,8 +1202,8 @@ void ENVIDataset::SetDescription( const char * pszDescription )
 /*                             SetMetadata()                            */
 /************************************************************************/
 
-CPLErr ENVIDataset::SetMetadata( char ** papszMetadata,
-                                 const char * pszDomain )
+CPLErr ENVIDataset::SetMetadata( char **papszMetadata,
+                                 const char *pszDomain )
 {
     if( pszDomain && (EQUAL(pszDomain, "RPC") || EQUAL(pszDomain, "ENVI")) )
     {
@@ -1321,9 +1216,9 @@ CPLErr ENVIDataset::SetMetadata( char ** papszMetadata,
 /*                             SetMetadataItem()                        */
 /************************************************************************/
 
-CPLErr ENVIDataset::SetMetadataItem( const char * pszName,
-                                     const char * pszValue,
-                                     const char * pszDomain )
+CPLErr ENVIDataset::SetMetadataItem( const char *pszName,
+                                     const char *pszValue,
+                                     const char *pszDomain )
 {
     if( pszDomain && (EQUAL(pszDomain, "RPC") || EQUAL(pszDomain, "ENVI")) )
     {
@@ -1374,9 +1269,9 @@ char **ENVIDataset::SplitList( const char *pszCleanInput )
             iFStart++;
 
         int iFEnd = iFStart;
-        while( pszInput[iFEnd] != ','
-               && pszInput[iFEnd] != '}'
-               && pszInput[iFEnd] != '\0' )
+        while( pszInput[iFEnd] != ',' &&
+               pszInput[iFEnd] != '}' &&
+               pszInput[iFEnd] != '\0' )
             iFEnd++;
 
         if( pszInput[iFEnd] == '\0' )
@@ -1389,10 +1284,10 @@ char **ENVIDataset::SplitList( const char *pszCleanInput )
             iFEnd--;
 
         pszInput[iFEnd + 1] = '\0';
-        papszReturn = CSLAddString( papszReturn, pszInput + iFStart );
+        papszReturn = CSLAddString(papszReturn, pszInput + iFStart);
     }
 
-    CPLFree( pszInput );
+    CPLFree(pszInput);
 
     return papszReturn;
 }
@@ -1407,45 +1302,45 @@ void ENVIDataset::SetENVIDatum( OGRSpatialReference *poSRS,
 {
     // Datums.
     if( EQUAL(pszENVIDatumName, "WGS-84") )
-        poSRS->SetWellKnownGeogCS( "WGS84" );
+        poSRS->SetWellKnownGeogCS("WGS84");
     else if( EQUAL(pszENVIDatumName, "WGS-72") )
-        poSRS->SetWellKnownGeogCS( "WGS72" );
+        poSRS->SetWellKnownGeogCS("WGS72");
     else if( EQUAL(pszENVIDatumName, "North America 1983") )
-        poSRS->SetWellKnownGeogCS( "NAD83" );
-    else if( EQUAL(pszENVIDatumName, "North America 1927")
-             || strstr(pszENVIDatumName,"NAD27")
-             || strstr(pszENVIDatumName,"NAD-27") )
-        poSRS->SetWellKnownGeogCS( "NAD27" );
+        poSRS->SetWellKnownGeogCS("NAD83");
+    else if( EQUAL(pszENVIDatumName, "North America 1927") ||
+             strstr(pszENVIDatumName, "NAD27") ||
+             strstr(pszENVIDatumName, "NAD-27") )
+        poSRS->SetWellKnownGeogCS("NAD27");
     else if( STARTS_WITH_CI(pszENVIDatumName, "European 1950") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4230" );
+        poSRS->SetWellKnownGeogCS("EPSG:4230");
     else if( EQUAL(pszENVIDatumName, "Ordnance Survey of Great Britain '36") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4277" );
+        poSRS->SetWellKnownGeogCS("EPSG:4277");
     else if( EQUAL(pszENVIDatumName, "SAD-69/Brazil") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4291" );
+        poSRS->SetWellKnownGeogCS("EPSG:4291");
     else if( EQUAL(pszENVIDatumName, "Geocentric Datum of Australia 1994") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4283" );
+        poSRS->SetWellKnownGeogCS("EPSG:4283");
     else if( EQUAL(pszENVIDatumName, "Australian Geodetic 1984") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4203" );
+        poSRS->SetWellKnownGeogCS("EPSG:4203");
     else if( EQUAL(pszENVIDatumName, "Nouvelle Triangulation Francaise IGN") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4275" );
+        poSRS->SetWellKnownGeogCS("EPSG:4275");
 
     // Ellipsoids
     else if( EQUAL(pszENVIDatumName, "GRS 80") )
-        poSRS->SetWellKnownGeogCS( "NAD83" );
+        poSRS->SetWellKnownGeogCS("NAD83");
     else if( EQUAL(pszENVIDatumName, "Airy") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4001" );
+        poSRS->SetWellKnownGeogCS("EPSG:4001");
     else if( EQUAL(pszENVIDatumName, "Australian National") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4003" );
+        poSRS->SetWellKnownGeogCS("EPSG:4003");
     else if( EQUAL(pszENVIDatumName, "Bessel 1841") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4004" );
+        poSRS->SetWellKnownGeogCS("EPSG:4004");
     else if( EQUAL(pszENVIDatumName, "Clark 1866") )
-        poSRS->SetWellKnownGeogCS( "EPSG:4008" );
+        poSRS->SetWellKnownGeogCS("EPSG:4008");
     else
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Unrecognized datum '%s', defaulting to WGS84.",
-                  pszENVIDatumName);
-        poSRS->SetWellKnownGeogCS( "WGS84" );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Unrecognized datum '%s', defaulting to WGS84.",
+                 pszENVIDatumName);
+        poSRS->SetWellKnownGeogCS("WGS84");
     }
 }
 
@@ -1461,11 +1356,10 @@ void ENVIDataset::SetENVIEllipse( OGRSpatialReference *poSRS,
     const double dfB = CPLAtofM(papszPI_EI[1]);
 
     double dfInvF = 0.0;
-    if( fabs(dfA-dfB) >= 0.1 )
+    if( fabs(dfA - dfB) >= 0.1 )
         dfInvF = dfA / (dfA - dfB);
 
-    poSRS->SetGeogCS( "Ellipse Based", "Ellipse Based", "Unnamed",
-                      dfA, dfInvF );
+    poSRS->SetGeogCS("Ellipse Based", "Ellipse Based", "Unnamed", dfA, dfInvF);
 }
 
 /************************************************************************/
@@ -1475,115 +1369,124 @@ void ENVIDataset::SetENVIEllipse( OGRSpatialReference *poSRS,
 /*      the header.                                                     */
 /************************************************************************/
 
-int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
+bool ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
 
 {
-    char **papszFields = SplitList( pszMapinfo );
+    char **papszFields = SplitList(pszMapinfo);
+    const char *pszUnits = NULL;
+    double dfRotation = 0.0;
     const int nCount = CSLCount(papszFields);
 
     if( nCount < 7 )
     {
-        CSLDestroy( papszFields );
-        return FALSE;
+        CSLDestroy(papszFields);
+        return false;
+    }
+
+    // Retrieve named values
+    for (int i = 0; i < nCount; ++i)
+    {
+        if ( STARTS_WITH(papszFields[i], "units=") )
+        {
+            pszUnits = papszFields[i] + strlen("units=");
+        }
+        else if ( STARTS_WITH(papszFields[i], "rotation=") )
+        {
+            dfRotation =
+                CPLAtof(papszFields[i] + strlen("rotation=")) *
+                kdfDegToRad * -1.0;
+        }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check if we have coordinate system string, and if so parse it.  */
-/* -------------------------------------------------------------------- */
+    // Check if we have coordinate system string, and if so parse it.
     char **papszCSS = NULL;
-    if( CSLFetchNameValue( papszHeader, "coordinate_system_string" ) != NULL )
+    if( CSLFetchNameValue(papszHeader, "coordinate_system_string") != NULL )
     {
         papszCSS = CSLTokenizeString2(
-            CSLFetchNameValue( papszHeader, "coordinate_system_string" ),
-            "{}", CSLT_PRESERVEQUOTES );
+            CSLFetchNameValue(papszHeader, "coordinate_system_string"),
+            "{}", CSLT_PRESERVEQUOTES);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check if we have projection info, and if so parse it.           */
-/* -------------------------------------------------------------------- */
+    // Check if we have projection info, and if so parse it.
     char **papszPI = NULL;
     int nPICount = 0;
-    if( CSLFetchNameValue( papszHeader, "projection_info" ) != NULL )
+    if( CSLFetchNameValue(papszHeader, "projection_info") != NULL )
     {
-        papszPI = SplitList(
-            CSLFetchNameValue( papszHeader, "projection_info" ) );
+        papszPI = SplitList(CSLFetchNameValue(papszHeader, "projection_info"));
         nPICount = CSLCount(papszPI);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Capture geotransform.                                           */
-/* -------------------------------------------------------------------- */
-    adfGeoTransform[1] = CPLAtof(papszFields[5]);  // Pixel width
-    adfGeoTransform[5] = -CPLAtof(papszFields[6]);  // Pixel height
-    // Upper left X coordinate.
-    adfGeoTransform[0] =
-        CPLAtof(papszFields[3]) -
-        (CPLAtof(papszFields[1]) - 1) * adfGeoTransform[1];
-    // Upper left Y coordinate.
-    adfGeoTransform[3] =
-        CPLAtof(papszFields[4]) -
-        (CPLAtof(papszFields[2]) - 1) * adfGeoTransform[5];
-    adfGeoTransform[2] = 0.0;
-    adfGeoTransform[4] = 0.0;
+    // Capture geotransform.
+    const double xReference = CPLAtof(papszFields[1]);
+    const double yReference = CPLAtof(papszFields[2]);
+    const double pixelEasting = CPLAtof(papszFields[3]);
+    const double pixelNorthing = CPLAtof(papszFields[4]);
+    const double xPixelSize = CPLAtof(papszFields[5]);
+    const double yPixelSize = CPLAtof(papszFields[6]);
+
+    adfGeoTransform[0] = pixelEasting - (xReference - 1) * xPixelSize;
+    adfGeoTransform[1] = cos(dfRotation) * xPixelSize;
+    adfGeoTransform[2] = -sin(dfRotation) * xPixelSize;
+    adfGeoTransform[3] = pixelNorthing + (yReference - 1) * yPixelSize;
+    adfGeoTransform[4] = -sin(dfRotation) * yPixelSize;
+    adfGeoTransform[5] = -cos(dfRotation) * yPixelSize;
 
-/* -------------------------------------------------------------------- */
-/*      Capture projection.                                             */
-/* -------------------------------------------------------------------- */
+    // TODO(schwehr): Symbolic constants for the fields.
+    // Capture projection.
     OGRSpatialReference oSRS;
-    if ( oSRS.importFromESRI( papszCSS ) != OGRERR_NONE )
+    if ( oSRS.importFromESRI(papszCSS) != OGRERR_NONE )
     {
         oSRS.Clear();
 
         if( STARTS_WITH_CI(papszFields[0], "UTM") && nCount >= 9 )
         {
-            oSRS.SetUTM( atoi(papszFields[7]),
-                         !EQUAL(papszFields[8],"South") );
-            if( nCount >= 10 && strstr(papszFields[9],"=") == NULL )
-                SetENVIDatum( &oSRS, papszFields[9] );
+            oSRS.SetUTM(atoi(papszFields[7]), !EQUAL(papszFields[8], "South"));
+            if( nCount >= 10 && strstr(papszFields[9], "=") == NULL )
+                SetENVIDatum(&oSRS, papszFields[9]);
             else
-                oSRS.SetWellKnownGeogCS( "NAD27" );
+                oSRS.SetWellKnownGeogCS("NAD27");
         }
-        else if( STARTS_WITH_CI(papszFields[0],"State Plane (NAD 27)")
-                 && nCount >= 7 )
+        else if( STARTS_WITH_CI(papszFields[0], "State Plane (NAD 27)") &&
+                 nCount >= 7 )
         {
-            oSRS.SetStatePlane( ITTVISToUSGSZone(atoi(papszFields[7])), FALSE );
+            oSRS.SetStatePlane(ITTVISToUSGSZone(atoi(papszFields[7])), FALSE);
         }
-        else if( STARTS_WITH_CI(papszFields[0],"State Plane (NAD 83)")
-                 && nCount >= 7 )
+        else if( STARTS_WITH_CI(papszFields[0], "State Plane (NAD 83)") &&
+                 nCount >= 7 )
         {
-            oSRS.SetStatePlane( ITTVISToUSGSZone(atoi(papszFields[7])), TRUE );
+            oSRS.SetStatePlane(ITTVISToUSGSZone(atoi(papszFields[7])), TRUE);
         }
-        else if( STARTS_WITH_CI(papszFields[0], "Geographic Lat")
-                 && nCount >= 8 )
+        else if( STARTS_WITH_CI(papszFields[0], "Geographic Lat") &&
+                 nCount >= 8 )
         {
-            if( nCount >= 8 && strstr(papszFields[7],"=") == NULL )
-                SetENVIDatum( &oSRS, papszFields[7] );
+            if( nCount >= 8 && strstr(papszFields[7], "=") == NULL )
+                SetENVIDatum(&oSRS, papszFields[7]);
             else
-                oSRS.SetWellKnownGeogCS( "WGS84" );
+                oSRS.SetWellKnownGeogCS("WGS84");
         }
-        else if( nPICount > 8 && atoi(papszPI[0]) == 3 ) // TM
+        else if( nPICount > 8 && atoi(papszPI[0]) == 3 )  // TM
         {
-            oSRS.SetTM( CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
-                        CPLAtofM(papszPI[7]),
-                        CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
+            oSRS.SetTM(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
+                       CPLAtofM(papszPI[7]),
+                       CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]));
         }
         else if( nPICount > 8 && atoi(papszPI[0]) == 4 )
         {
             // Lambert Conformal Conic
-            oSRS.SetLCC( CPLAtofM(papszPI[7]), CPLAtofM(papszPI[8]),
-                         CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
-                         CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
+            oSRS.SetLCC(CPLAtofM(papszPI[7]), CPLAtofM(papszPI[8]),
+                        CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
+                        CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]));
         }
         else if( nPICount > 10 && atoi(papszPI[0]) == 5 )
         {
             // Oblique Merc (2 point).
-            oSRS.SetHOM2PNO( CPLAtofM(papszPI[3]),
-                             CPLAtofM(papszPI[4]), CPLAtofM(papszPI[5]),
-                             CPLAtofM(papszPI[6]), CPLAtofM(papszPI[7]),
-                             CPLAtofM(papszPI[10]),
-                             CPLAtofM(papszPI[8]), CPLAtofM(papszPI[9]) );
+            oSRS.SetHOM2PNO(CPLAtofM(papszPI[3]),
+                            CPLAtofM(papszPI[4]), CPLAtofM(papszPI[5]),
+                            CPLAtofM(papszPI[6]), CPLAtofM(papszPI[7]),
+                            CPLAtofM(papszPI[10]),
+                            CPLAtofM(papszPI[8]), CPLAtofM(papszPI[9]));
         }
-        else if( nPICount > 8 && atoi(papszPI[0]) == 6 ) // Oblique Merc
+        else if( nPICount > 8 && atoi(papszPI[0]) == 6 )  // Oblique Merc
         {
             oSRS.SetHOM(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                         CPLAtofM(papszPI[5]), 0.0,
@@ -1592,32 +1495,32 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
         }
         else if( nPICount > 8 && atoi(papszPI[0]) == 7 ) // Stereographic
         {
-            oSRS.SetStereographic( CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
-                                   CPLAtofM(papszPI[7]),
-                                   CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
+            oSRS.SetStereographic(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
+                                  CPLAtofM(papszPI[7]),
+                                  CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]));
         }
-        else if( nPICount > 8 && atoi(papszPI[0]) == 9 ) // Albers Equal Area
+        else if( nPICount > 8 && atoi(papszPI[0]) == 9 )  // Albers Equal Area
         {
-            oSRS.SetACEA( CPLAtofM(papszPI[7]), CPLAtofM(papszPI[8]),
-                          CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
-                          CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
+            oSRS.SetACEA(CPLAtofM(papszPI[7]), CPLAtofM(papszPI[8]),
+                         CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
+                         CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]));
         }
-        else if( nPICount > 6 && atoi(papszPI[0]) == 10 ) // Polyconic
+        else if( nPICount > 6 && atoi(papszPI[0]) == 10 )  // Polyconic
         {
             oSRS.SetPolyconic(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                               CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
         }
-        else if( nPICount > 6 && atoi(papszPI[0]) == 11 ) // LAEA
+        else if( nPICount > 6 && atoi(papszPI[0]) == 11 )  // LAEA
         {
             oSRS.SetLAEA(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                          CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
         }
-        else if( nPICount > 6 && atoi(papszPI[0]) == 12 ) // Azimuthal Equid.
+        else if( nPICount > 6 && atoi(papszPI[0]) == 12 )  // Azimuthal Equid.
         {
             oSRS.SetAE(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                        CPLAtofM(papszPI[5]), CPLAtofM(papszPI[6]) );
         }
-        else if( nPICount > 6 && atoi(papszPI[0]) == 31 ) // Polar Stereographic
+        else if( nPICount > 6 && atoi(papszPI[0]) == 31 )  // Polar Stereographic
         {
             oSRS.SetPS(CPLAtofM(papszPI[3]), CPLAtofM(papszPI[4]),
                        1.0,
@@ -1625,28 +1528,24 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
         }
     }
 
-    CSLDestroy( papszCSS );
+    CSLDestroy(papszCSS);
 
     // Still lots more that could be added for someone with the patience.
 
-/* -------------------------------------------------------------------- */
-/*      Fallback to localcs if we don't recognise things.               */
-/* -------------------------------------------------------------------- */
+    // Fallback to localcs if we don't recognise things.
     if( oSRS.GetRoot() == NULL )
-        oSRS.SetLocalCS( papszFields[0] );
+        oSRS.SetLocalCS(papszFields[0]);
 
-/* -------------------------------------------------------------------- */
-/*      Try to set datum from projection info line if we have a         */
-/*      projected coordinate system without a GEOGCS.                   */
-/* -------------------------------------------------------------------- */
+    // Try to set datum from projection info line if we have a
+    // projected coordinate system without a GEOGCS.
     if( oSRS.IsProjected() && oSRS.GetAttrNode("GEOGCS") == NULL
         && nPICount > 3 )
     {
         // Do we have a datum on the projection info line?
-        int iDatum = nPICount-1;
+        int iDatum = nPICount - 1;
 
         // Ignore units= items.
-        if( strstr(papszPI[iDatum],"=") != NULL )
+        if( strstr(papszPI[iDatum], "=") != NULL )
             iDatum--;
 
         // Skip past the name.
@@ -1657,41 +1556,39 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
                                       "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
             != CPLString::npos )
         {
-            SetENVIDatum( &oSRS, osDatumName );
+            SetENVIDatum(&oSRS, osDatumName);
         }
         else
         {
-            SetENVIEllipse( &oSRS, papszPI + 1 );
+            SetENVIEllipse(&oSRS, papszPI + 1);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try to process specialized units.                               */
-/* -------------------------------------------------------------------- */
-    if( STARTS_WITH_CI(papszFields[nCount-1], "units"))
+    // Try to process specialized units.
+    if( pszUnits != NULL )
     {
-        /* Handle linear units first. */
-        if( EQUAL(papszFields[nCount-1], "units=Feet") )
+        // Handle linear units first.
+        if( EQUAL(pszUnits, "Feet") )
             oSRS.SetLinearUnitsAndUpdateParameters(
-                SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) );
-        else if( EQUAL(papszFields[nCount-1], "units=Meters") )
-            oSRS.SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1. );
-        else if( EQUAL(papszFields[nCount-1], "units=Km") )
-            oSRS.SetLinearUnitsAndUpdateParameters( "Kilometer", 1000.  );
-        else if( EQUAL(papszFields[nCount-1], "units=Yards") )
-            oSRS.SetLinearUnitsAndUpdateParameters( "Yard", .9144 );
-        else if( EQUAL(papszFields[nCount-1], "units=Miles") )
-            oSRS.SetLinearUnitsAndUpdateParameters( "Mile", 1609.344 );
-        else if( EQUAL(papszFields[nCount-1], "units=Nautical Miles") )
+                SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV));
+        else if( EQUAL(pszUnits, "Meters") )
+            oSRS.SetLinearUnitsAndUpdateParameters(SRS_UL_METER, 1.0);
+        else if( EQUAL(pszUnits, "Km") )
+            oSRS.SetLinearUnitsAndUpdateParameters("Kilometer", 1000.0);
+        else if( EQUAL(pszUnits, "Yards") )
+            oSRS.SetLinearUnitsAndUpdateParameters("Yard", 0.9144);
+        else if( EQUAL(pszUnits, "Miles") )
+            oSRS.SetLinearUnitsAndUpdateParameters("Mile", 1609.344);
+        else if( EQUAL(pszUnits, "Nautical Miles") )
             oSRS.SetLinearUnitsAndUpdateParameters(
-                SRS_UL_NAUTICAL_MILE, CPLAtof(SRS_UL_NAUTICAL_MILE_CONV) );
+                SRS_UL_NAUTICAL_MILE, CPLAtof(SRS_UL_NAUTICAL_MILE_CONV));
 
-        /* Only handle angular units if we know the projection is geographic. */
+        // Only handle angular units if we know the projection is geographic.
         if (oSRS.IsGeographic())
         {
-            if (EQUAL(papszFields[nCount-1], "units=Radians") )
+            if (EQUAL(pszUnits, "Radians") )
             {
-                oSRS.SetAngularUnits( SRS_UA_RADIAN, 1. );
+                oSRS.SetAngularUnits(SRS_UA_RADIAN, 1.0);
             }
             else
             {
@@ -1701,9 +1598,9 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
                     SRS_UA_DEGREE, CPLAtof(SRS_UA_DEGREE_CONV));
 
                 double conversionFactor = 1.0;
-                if( EQUAL(papszFields[nCount-1], "units=Minutes") )
+                if( EQUAL(pszUnits, "Minutes") )
                     conversionFactor = 60.0;
-                else if( EQUAL(papszFields[nCount-1], "units=Seconds") )
+                else if( EQUAL(pszUnits, "Seconds") )
                     conversionFactor = 3600.0;
                 adfGeoTransform[0] /= conversionFactor;
                 adfGeoTransform[1] /= conversionFactor;
@@ -1714,23 +1611,22 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
             }
         }
     }
-/* -------------------------------------------------------------------- */
-/*      Turn back into WKT.                                             */
-/* -------------------------------------------------------------------- */
+
+    // Turn back into WKT.
     if( oSRS.GetRoot() != NULL )
     {
         oSRS.Fixup();
         if ( pszProjection )
         {
-            CPLFree( pszProjection );
+            CPLFree(pszProjection);
             pszProjection = NULL;
         }
-        oSRS.exportToWkt( &pszProjection );
+        oSRS.exportToWkt(&pszProjection);
     }
 
-    CSLDestroy( papszFields );
-    CSLDestroy( papszPI );
-    return TRUE;
+    CSLDestroy(papszFields);
+    CSLDestroy(papszPI);
+    return true;
 }
 
 /************************************************************************/
@@ -1743,32 +1639,32 @@ int ENVIDataset::ProcessMapinfo( const char *pszMapinfo )
 void ENVIDataset::ProcessRPCinfo( const char *pszRPCinfo,
                                   int numCols, int numRows)
 {
-    char **papszFields = SplitList( pszRPCinfo );
+    char **papszFields = SplitList(pszRPCinfo);
     const int nCount = CSLCount(papszFields);
 
     if( nCount < 90 )
     {
-        CSLDestroy( papszFields );
+        CSLDestroy(papszFields);
         return;
     }
 
     char sVal[1280] = { '\0' };
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[0]));
-    SetMetadataItem("LINE_OFF",sVal,"RPC");
+    SetMetadataItem("LINE_OFF", sVal, "RPC");
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[5]));
-    SetMetadataItem("LINE_SCALE",sVal,"RPC");
+    SetMetadataItem("LINE_SCALE", sVal, "RPC");
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[1]));
-    SetMetadataItem("SAMP_OFF",sVal,"RPC");
+    SetMetadataItem("SAMP_OFF", sVal, "RPC");
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[6]));
-    SetMetadataItem("SAMP_SCALE",sVal,"RPC");
+    SetMetadataItem("SAMP_SCALE", sVal, "RPC");
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[2]));
-    SetMetadataItem("LAT_OFF",sVal,"RPC");
+    SetMetadataItem("LAT_OFF", sVal, "RPC");
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[7]));
-    SetMetadataItem("LAT_SCALE",sVal,"RPC");
+    SetMetadataItem("LAT_SCALE", sVal, "RPC");
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[3]));
-    SetMetadataItem("LONG_OFF",sVal,"RPC");
+    SetMetadataItem("LONG_OFF", sVal, "RPC");
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[8]));
-    SetMetadataItem("LONG_SCALE",sVal,"RPC");
+    SetMetadataItem("LONG_SCALE", sVal, "RPC");
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[4]));
     SetMetadataItem("HEIGHT_OFF", sVal, "RPC");
     CPLsnprintf(sVal, sizeof(sVal), "%.16g", CPLAtof(papszFields[9]));
@@ -1776,43 +1672,43 @@ void ENVIDataset::ProcessRPCinfo( const char *pszRPCinfo,
 
     sVal[0] = '\0';
     for( int i = 0; i < 20; i++ )
-        CPLsnprintf(sVal+strlen(sVal), sizeof(sVal)-strlen(sVal),  "%.16g ",
-           CPLAtof(papszFields[10+i]));
-    SetMetadataItem("LINE_NUM_COEFF",sVal,"RPC");
+        CPLsnprintf(sVal + strlen(sVal), sizeof(sVal) - strlen(sVal), "%.16g ",
+                    CPLAtof(papszFields[10 + i]));
+    SetMetadataItem("LINE_NUM_COEFF", sVal, "RPC");
 
     sVal[0] = '\0';
     for( int i = 0; i < 20; i++ )
-       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal)-strlen(sVal),  "%.16g ",
-           CPLAtof(papszFields[30+i]));
-    SetMetadataItem("LINE_DEN_COEFF",sVal,"RPC");
+        CPLsnprintf(sVal + strlen(sVal), sizeof(sVal) - strlen(sVal), "%.16g ",
+                    CPLAtof(papszFields[30 + i]));
+    SetMetadataItem("LINE_DEN_COEFF", sVal, "RPC");
 
     sVal[0] = '\0';
     for( int i = 0; i < 20; i++ )
-       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal)-strlen(sVal),  "%.16g ",
-           CPLAtof(papszFields[50+i]));
-    SetMetadataItem("SAMP_NUM_COEFF",sVal,"RPC");
+        CPLsnprintf(sVal + strlen(sVal), sizeof(sVal) - strlen(sVal), "%.16g ",
+                    CPLAtof(papszFields[50 + i]));
+    SetMetadataItem("SAMP_NUM_COEFF", sVal, "RPC");
 
     sVal[0] = '\0';
     for( int i = 0; i < 20; i++ )
-       CPLsnprintf(sVal+strlen(sVal), sizeof(sVal)-strlen(sVal),  "%.16g ",
-           CPLAtof(papszFields[70+i]));
+        CPLsnprintf(sVal + strlen(sVal), sizeof(sVal) - strlen(sVal), "%.16g ",
+                    CPLAtof(papszFields[70 + i]));
     SetMetadataItem("SAMP_DEN_COEFF", sVal, "RPC");
 
     CPLsnprintf(sVal, sizeof(sVal), "%.16g",
-        CPLAtof(papszFields[3]) - CPLAtof(papszFields[8]));
-    SetMetadataItem("MIN_LONG",sVal,"RPC");
+                CPLAtof(papszFields[3]) - CPLAtof(papszFields[8]));
+    SetMetadataItem("MIN_LONG", sVal, "RPC");
 
     CPLsnprintf(sVal, sizeof(sVal), "%.16g",
-        CPLAtof(papszFields[3]) + CPLAtof(papszFields[8]) );
-    SetMetadataItem("MAX_LONG",sVal,"RPC");
+                CPLAtof(papszFields[3]) + CPLAtof(papszFields[8]));
+    SetMetadataItem("MAX_LONG", sVal, "RPC");
 
     CPLsnprintf(sVal, sizeof(sVal), "%.16g",
-        CPLAtof(papszFields[2]) - CPLAtof(papszFields[7]));
-    SetMetadataItem("MIN_LAT",sVal,"RPC");
+                CPLAtof(papszFields[2]) - CPLAtof(papszFields[7]));
+    SetMetadataItem("MIN_LAT", sVal, "RPC");
 
     CPLsnprintf(sVal, sizeof(sVal), "%.16g",
-        CPLAtof(papszFields[2]) + CPLAtof(papszFields[7]));
-    SetMetadataItem("MAX_LAT",sVal,"RPC");
+                CPLAtof(papszFields[2]) + CPLAtof(papszFields[7]));
+    SetMetadataItem("MAX_LAT", sVal, "RPC");
 
     if (nCount == 93)
     {
@@ -1824,7 +1720,7 @@ void ENVIDataset::ProcessRPCinfo( const char *pszRPCinfo,
     // Handle the chipping case where the image is a subset.
     const double rowOffset = (nCount == 93) ? CPLAtof(papszFields[90]) : 0;
     const double colOffset = (nCount == 93) ? CPLAtof(papszFields[91]) : 0;
-    if (rowOffset || colOffset)
+    if (rowOffset != 0.0 || colOffset != 0.0)
     {
         SetMetadataItem("ICHIP_SCALE_FACTOR", "1");
         SetMetadataItem("ICHIP_ANAMORPH_CORR", "0");
@@ -1859,8 +1755,8 @@ void ENVIDataset::ProcessRPCinfo( const char *pszRPCinfo,
 
 void ENVIDataset::ProcessStatsFile()
 {
-    osStaFilename = CPLResetExtension( pszHDRFilename, "sta" );
-    VSILFILE *fpStaFile = VSIFOpenL( osStaFilename, "rb" );
+    osStaFilename = CPLResetExtension(pszHDRFilename, "sta");
+    VSILFILE *fpStaFile = VSIFOpenL(osStaFilename, "rb");
 
     if (!fpStaFile)
     {
@@ -1869,9 +1765,9 @@ void ENVIDataset::ProcessStatsFile()
     }
 
     int lTestHeader[10] = { 0 };
-    if( VSIFReadL( lTestHeader, sizeof(int), 10, fpStaFile ) != 10 )
+    if( VSIFReadL(lTestHeader, sizeof(int), 10, fpStaFile) != 10 )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fpStaFile ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpStaFile));
         osStaFilename = "";
         return;
     }
@@ -1883,56 +1779,57 @@ void ENVIDataset::ProcessStatsFile()
     if (nb < 0 || nb > nBands)
     {
         CPLDebug("ENVI", ".sta file has statistics for %d bands, "
-                         "whereas the dataset has only %d bands", nb, nBands);
+                         "whereas the dataset has only %d bands",
+                 nb, nBands);
         nb = nBands;
     }
 
+    // TODO(schwehr): What are 1, 4, 8, and 40?
     int lOffset = 0;
-    if( VSIFSeekL(fpStaFile, 40+(nb+1)*4, SEEK_SET) == 0 &&
+    if( VSIFSeekL(fpStaFile, 40 + (nb + 1) * 4, SEEK_SET) == 0 &&
         VSIFReadL(&lOffset, sizeof(int), 1, fpStaFile) == 1 &&
-        VSIFSeekL(fpStaFile, 40+(nb+1)*8+byteSwapInt(lOffset)+nb, SEEK_SET)
-            == 0)
+        VSIFSeekL(fpStaFile, 40 + (nb + 1) * 8 + byteSwapInt(lOffset) + nb,
+                  SEEK_SET) == 0)
     {
         // This should be the beginning of the statistics.
         if (isFloat)
         {
-            float *fStats = reinterpret_cast<float *>( CPLCalloc( nb * 4, 4 ) );
-            if ( static_cast<int>( VSIFReadL( fStats,4,nb*4,fpStaFile ) )
-                == nb*4)
+            float *fStats = static_cast<float *>(CPLCalloc( nb * 4, 4 ));
+            if ( static_cast<int>(VSIFReadL(fStats, 4, nb * 4, fpStaFile)) ==
+                 nb * 4)
             {
-                for( int i=0; i < nb; i++ )
+                for( int i = 0; i < nb; i++ )
                 {
-                    GetRasterBand(i+1)->SetStatistics(
+                    GetRasterBand(i + 1)->SetStatistics(
                         byteSwapFloat(fStats[i]),
-                        byteSwapFloat(fStats[nb+i]),
-                        byteSwapFloat(fStats[2*nb+i]),
-                        byteSwapFloat(fStats[3*nb+i]));
+                        byteSwapFloat(fStats[nb + i]),
+                        byteSwapFloat(fStats[2 * nb + i]),
+                        byteSwapFloat(fStats[3 * nb + i]));
                 }
             }
             CPLFree(fStats);
         }
         else
         {
-            double *dStats
-                = reinterpret_cast<double *>( CPLCalloc( nb * 4, 8 ) );
-            if ( static_cast<int>( VSIFReadL(dStats,8,nb*4,fpStaFile ) )
-                     == nb*4)
+            double *dStats = static_cast<double *>(CPLCalloc(nb * 4, 8));
+            if ( static_cast<int>(VSIFReadL(dStats, 8, nb * 4, fpStaFile)) ==
+                 nb * 4)
             {
-                for( int i=0; i < nb; i++ )
+                for( int i = 0; i < nb; i++ )
                 {
                     const double dMin = byteSwapDouble(dStats[i]);
-                    const double dMax = byteSwapDouble(dStats[nb+i]);
-                    const double dMean = byteSwapDouble(dStats[2*nb+i]);
-                    const double dStd = byteSwapDouble(dStats[3*nb+i]);
+                    const double dMax = byteSwapDouble(dStats[nb + i]);
+                    const double dMean = byteSwapDouble(dStats[2 * nb + i]);
+                    const double dStd = byteSwapDouble(dStats[3 * nb + i]);
                     if (dMin != dMax && dStd != 0)
-                        GetRasterBand(i+1)->
-                            SetStatistics( dMin, dMax, dMean, dStd );
+                        GetRasterBand(i + 1)->
+                            SetStatistics(dMin, dMax, dMean, dStd);
                 }
             }
             CPLFree(dStats);
         }
     }
-    CPL_IGNORE_RET_VAL(VSIFCloseL( fpStaFile ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fpStaFile));
 }
 
 int ENVIDataset::byteSwapInt(int swapMe)
@@ -1953,45 +1850,42 @@ double ENVIDataset::byteSwapDouble(double swapMe)
     return swapMe;
 }
 
-
 /************************************************************************/
 /*                             ReadHeader()                             */
 /************************************************************************/
 
-int ENVIDataset::ReadHeader( VSILFILE * fpHdr )
+// Always returns true.
+bool ENVIDataset::ReadHeader( VSILFILE *fpHdr )
 
 {
-    CPLReadLineL( fpHdr );
+    CPLReadLineL(fpHdr);
 
-/* -------------------------------------------------------------------- */
-/*      Now start forming sets of name/value pairs.                     */
-/* -------------------------------------------------------------------- */
+    // Start forming sets of name/value pairs.
     while( true )
     {
-        const char *pszNewLine = CPLReadLineL( fpHdr );
+        const char *pszNewLine = CPLReadLineL(fpHdr);
         if( pszNewLine == NULL )
             break;
 
-        if( strstr(pszNewLine,"=") == NULL )
+        if( strstr(pszNewLine, "=") == NULL )
             continue;
 
         char *pszWorkingLine = CPLStrdup(pszNewLine);
 
         // Collect additional lines if we have open sqiggly bracket.
-        if( strstr(pszWorkingLine,"{") != NULL
-            && strstr(pszWorkingLine,"}") == NULL )
+        if( strstr(pszWorkingLine, "{") != NULL &&
+            strstr(pszWorkingLine, "}") == NULL )
         {
             do {
-                pszNewLine = CPLReadLineL( fpHdr );
+                pszNewLine = CPLReadLineL(fpHdr);
                 if( pszNewLine )
                 {
-                    pszWorkingLine = reinterpret_cast<char *>(
-                        CPLRealloc( pszWorkingLine,
-                                    strlen(pszWorkingLine)
-                                    + strlen(pszNewLine) + 1) );
-                    strcat( pszWorkingLine, pszNewLine );
+                    pszWorkingLine = static_cast<char *>(
+                        CPLRealloc(pszWorkingLine, strlen(pszWorkingLine) +
+                                                       strlen(pszNewLine) + 1));
+                    strcat(pszWorkingLine, pszNewLine);
                 }
-            } while( pszNewLine != NULL && strstr(pszNewLine,"}") == NULL );
+            } while( pszNewLine != NULL && strstr(pszNewLine, "}") == NULL );
         }
 
         // Try to break input into name and value portions.  Trim whitespace.
@@ -2009,8 +1903,8 @@ int ENVIDataset::ReadHeader( VSILFILE * fpHdr )
 
             pszWorkingLine[iEqual--] = '\0';
             while( iEqual > 0
-                   && (pszWorkingLine[iEqual] == ' '
-                       || pszWorkingLine[iEqual] == '\t') )
+                   && (pszWorkingLine[iEqual] == ' ' ||
+                       pszWorkingLine[iEqual] == '\t') )
                 pszWorkingLine[iEqual--] = '\0';
 
             // Convert spaces in the name to underscores.
@@ -2020,34 +1914,30 @@ int ENVIDataset::ReadHeader( VSILFILE * fpHdr )
                     pszWorkingLine[i] = '_';
             }
 
-            papszHeader = CSLSetNameValue( papszHeader,
-                                           pszWorkingLine, pszValue );
+            papszHeader =
+                CSLSetNameValue(papszHeader, pszWorkingLine, pszValue);
         }
 
-        CPLFree( pszWorkingLine );
+        CPLFree(pszWorkingLine);
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
+GDALDataset *ENVIDataset::Open( GDALOpenInfo *poOpenInfo )
 
 {
-/* -------------------------------------------------------------------- */
-/*      We assume the user is pointing to the binary (i.e. .bil) file.  */
-/* -------------------------------------------------------------------- */
+    // Assume the caller is pointing to the binary (i.e. .bil) file.
     if( poOpenInfo->nHeaderBytes < 2 )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Do we have a .hdr file?  Try upper and lower case, and          */
-/*      replacing the extension as well as appending the extension      */
-/*      to whatever we currently have.                                  */
-/* -------------------------------------------------------------------- */
+    // Do we have a .hdr file?  Try upper and lower case, and
+    // replacing the extension as well as appending the extension
+    // to whatever we currently have.
 
     const char *pszMode = NULL;
     if( poOpenInfo->eAccess == GA_Update )
@@ -2057,59 +1947,55 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 
     CPLString osHdrFilename;
     VSILFILE *fpHeader = NULL;
-    char** papszSiblingFiles = poOpenInfo->GetSiblingFiles();
+    char **papszSiblingFiles = poOpenInfo->GetSiblingFiles();
     if (papszSiblingFiles == NULL)
     {
-        osHdrFilename = CPLResetExtension( poOpenInfo->pszFilename, "hdr" );
-        fpHeader = VSIFOpenL( osHdrFilename, pszMode );
+        osHdrFilename = CPLResetExtension(poOpenInfo->pszFilename, "hdr");
+        fpHeader = VSIFOpenL(osHdrFilename, pszMode);
 
         if( fpHeader == NULL && VSIIsCaseSensitiveFS(osHdrFilename) )
         {
-            osHdrFilename = CPLResetExtension( poOpenInfo->pszFilename, "HDR" );
-            fpHeader = VSIFOpenL( osHdrFilename, pszMode );
+            osHdrFilename = CPLResetExtension(poOpenInfo->pszFilename, "HDR");
+            fpHeader = VSIFOpenL(osHdrFilename, pszMode);
         }
 
         if( fpHeader == NULL )
         {
-            osHdrFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename,
-                                            "hdr" );
-            fpHeader = VSIFOpenL( osHdrFilename, pszMode );
+            osHdrFilename =
+                CPLFormFilename(NULL, poOpenInfo->pszFilename, "hdr");
+            fpHeader = VSIFOpenL(osHdrFilename, pszMode);
         }
 
         if( fpHeader == NULL && VSIIsCaseSensitiveFS(osHdrFilename) )
         {
-            osHdrFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename,
-                                            "HDR" );
-            fpHeader = VSIFOpenL( osHdrFilename, pszMode );
+            osHdrFilename =
+                CPLFormFilename(NULL, poOpenInfo->pszFilename, "HDR");
+            fpHeader = VSIFOpenL(osHdrFilename, pszMode);
         }
-
     }
     else
     {
-        /* -------------------------------------------------------------------- */
-        /*      Now we need to tear apart the filename to form a .HDR           */
-        /*      filename.                                                       */
-        /* -------------------------------------------------------------------- */
-        CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
-        CPLString osName = CPLGetFilename( poOpenInfo->pszFilename );
+        // Now we need to tear apart the filename to form a .HDR filename.
+        CPLString osPath = CPLGetPath(poOpenInfo->pszFilename);
+        CPLString osName = CPLGetFilename(poOpenInfo->pszFilename);
 
-        int iFile = CSLFindString( papszSiblingFiles,
-                                   CPLResetExtension( osName, "hdr" ) );
+        int iFile =
+            CSLFindString(papszSiblingFiles, CPLResetExtension(osName, "hdr"));
         if( iFile >= 0 )
         {
-            osHdrFilename = CPLFormFilename( osPath, papszSiblingFiles[iFile],
-                                             NULL );
-            fpHeader = VSIFOpenL( osHdrFilename, pszMode );
+            osHdrFilename =
+                CPLFormFilename(osPath, papszSiblingFiles[iFile], NULL);
+            fpHeader = VSIFOpenL(osHdrFilename, pszMode);
         }
         else
         {
             iFile = CSLFindString(papszSiblingFiles,
-                                  CPLFormFilename( NULL, osName, "hdr" ));
+                                  CPLFormFilename(NULL, osName, "hdr"));
             if( iFile >= 0 )
             {
                 osHdrFilename =
-                    CPLFormFilename( osPath, papszSiblingFiles[iFile], NULL );
-                fpHeader = VSIFOpenL( osHdrFilename, pszMode );
+                    CPLFormFilename(osPath, papszSiblingFiles[iFile], NULL);
+                fpHeader = VSIFOpenL(osHdrFilename, pszMode);
             }
         }
     }
@@ -2117,93 +2003,81 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
     if( fpHeader == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Check that the first line says "ENVI".                          */
-/* -------------------------------------------------------------------- */
+    // Check that the first line says "ENVI".
     char szTestHdr[4] = { '\0' };
 
-    if( VSIFReadL( szTestHdr, 4, 1, fpHeader ) != 1 )
+    if( VSIFReadL(szTestHdr, 4, 1, fpHeader) != 1 )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fpHeader ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpHeader));
         return NULL;
     }
     if( !STARTS_WITH(szTestHdr, "ENVI") )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fpHeader ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpHeader));
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create a corresponding GDALDataset.                             */
-/* -------------------------------------------------------------------- */
+    // Create a corresponding GDALDataset.
     ENVIDataset *poDS = new ENVIDataset();
     poDS->pszHDRFilename = CPLStrdup(osHdrFilename);
     poDS->fp = fpHeader;
 
-/* -------------------------------------------------------------------- */
-/*      Read the header.                                                */
-/* -------------------------------------------------------------------- */
-    if( !poDS->ReadHeader( fpHeader ) )
+    // Read the header.
+    if( !poDS->ReadHeader(fpHeader) )
     {
         delete poDS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Has the user selected the .hdr file to open?                    */
-/* -------------------------------------------------------------------- */
+    // Has the user selected the .hdr file to open?
     if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "hdr") )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "The selected file is an ENVI header file, but to "
-                  "open ENVI datasets, the data file should be selected "
-                  "instead of the .hdr file.  Please try again selecting "
-                  "the data file corresponding to the header file:  "
-                  "%s",
-                  poOpenInfo->pszFilename );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The selected file is an ENVI header file, but to "
+                 "open ENVI datasets, the data file should be selected "
+                 "instead of the .hdr file.  Please try again selecting "
+                 "the data file corresponding to the header file:  "
+                 "%s",
+                 poOpenInfo->pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Has the user selected the .sta (stats) file to open?            */
-/* -------------------------------------------------------------------- */
+    // Has the user selected the .sta (stats) file to open?
     if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "sta") )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "The selected file is an ENVI statistics file. "
-                  "To open ENVI datasets, the data file should be selected "
-                  "instead of the .sta file.  Please try again selecting "
-                  "the data file corresponding to the statistics file:  "
-                  "%s",
-                  poOpenInfo->pszFilename );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The selected file is an ENVI statistics file. "
+                 "To open ENVI datasets, the data file should be selected "
+                 "instead of the .sta file.  Please try again selecting "
+                 "the data file corresponding to the statistics file:  "
+                 "%s",
+                 poOpenInfo->pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Extract required values from the .hdr.                          */
-/* -------------------------------------------------------------------- */
+    // Extract required values from the .hdr.
     int nLines = 0;
-    if( CSLFetchNameValue(poDS->papszHeader,"lines") )
-        nLines = atoi(CSLFetchNameValue(poDS->papszHeader,"lines"));
+    if( CSLFetchNameValue(poDS->papszHeader, "lines") )
+        nLines = atoi(CSLFetchNameValue(poDS->papszHeader, "lines"));
 
     int nSamples = 0;
-    if( CSLFetchNameValue(poDS->papszHeader,"samples") )
-        nSamples = atoi(CSLFetchNameValue(poDS->papszHeader,"samples"));
+    if( CSLFetchNameValue(poDS->papszHeader, "samples") )
+        nSamples = atoi(CSLFetchNameValue(poDS->papszHeader, "samples"));
 
     int nBands = 0;
-    if( CSLFetchNameValue(poDS->papszHeader,"bands") )
-        nBands = atoi(CSLFetchNameValue(poDS->papszHeader,"bands"));
+    if( CSLFetchNameValue(poDS->papszHeader, "bands") )
+        nBands = atoi(CSLFetchNameValue(poDS->papszHeader, "bands"));
 
     const char *pszInterleave =
-        CSLFetchNameValue(poDS->papszHeader,"interleave");
+        CSLFetchNameValue(poDS->papszHeader, "interleave");
 
     // In case, there is no interleave keyword, we try to derive it from the
     // file extension.
     if( pszInterleave == NULL )
     {
-        const char* pszExtension = CPLGetExtension(poOpenInfo->pszFilename);
+        const char *pszExtension = CPLGetExtension(poOpenInfo->pszFilename);
         pszInterleave = pszExtension;
     }
 
@@ -2211,9 +2085,9 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
          !STARTS_WITH_CI(pszInterleave, "BIP") &&
          !STARTS_WITH_CI(pszInterleave, "BIL") )
     {
-        CPLDebug( "ENVI",
-                  "Unset or unknown value for 'interleave' keyword --> "
-                  "assuming BSQ interleaving" );
+        CPLDebug("ENVI",
+                 "Unset or unknown value for 'interleave' keyword --> "
+                 "assuming BSQ interleaving");
         pszInterleave = "bsq";
     }
 
@@ -2221,10 +2095,10 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
         !GDALCheckBandCount(nBands, FALSE) )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "The file appears to have an associated ENVI header, but "
-                  "one or more of the samples, lines and bands "
-                  "keywords appears to be missing or invalid." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The file appears to have an associated ENVI header, but "
+                 "one or more of the samples, lines and bands "
+                 "keywords appears to be missing or invalid.");
         return NULL;
     }
 
@@ -2233,14 +2107,12 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
         nHeaderSize =
             atoi(CSLFetchNameValue(poDS->papszHeader, "header_offset"));
 
-/* -------------------------------------------------------------------- */
-/*      Translate the datatype.                                         */
-/* -------------------------------------------------------------------- */
+    // Translate the datatype.
     GDALDataType eType = GDT_Byte;
 
-    if( CSLFetchNameValue(poDS->papszHeader, "data_type" ) != NULL )
+    if( CSLFetchNameValue(poDS->papszHeader, "data_type") != NULL )
     {
-        switch( atoi(CSLFetchNameValue(poDS->papszHeader, "data_type" )) )
+        switch( atoi(CSLFetchNameValue(poDS->papszHeader, "data_type")) )
         {
           case 1:
             eType = GDT_Byte;
@@ -2278,47 +2150,43 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
             eType = GDT_UInt32;
             break;
 
-            /* 14=Int64, 15=UInt64 */
+            // 14=Int64, 15=UInt64
 
           default:
             delete poDS;
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "The file does not have a value for the data_type "
-                      "that is recognised by the GDAL ENVI driver.");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "The file does not have a value for the data_type "
+                     "that is recognised by the GDAL ENVI driver.");
             return NULL;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Translate the byte order.                                       */
-/* -------------------------------------------------------------------- */
+    // Translate the byte order.
     bool bNativeOrder = true;
 
-    if( CSLFetchNameValue(poDS->papszHeader,"byte_order" ) != NULL )
+    if( CSLFetchNameValue(poDS->papszHeader, "byte_order") != NULL )
     {
 #ifdef CPL_LSB
-        bNativeOrder = atoi(CSLFetchNameValue(poDS->papszHeader,
-                                              "byte_order" )) == 0;
+        bNativeOrder =
+            atoi(CSLFetchNameValue(poDS->papszHeader, "byte_order")) == 0;
 #else
-        bNativeOrder = atoi(CSLFetchNameValue(poDS->papszHeader,
-                                              "byte_order" )) != 0;
+        bNativeOrder =
+            atoi(CSLFetchNameValue(poDS->papszHeader, "byte_order")) != 0;
 #endif
     }
 
-/* -------------------------------------------------------------------- */
-/*      Warn about unsupported file types virtual mosaic and meta file.*/
-/* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue(poDS->papszHeader,"file_type" ) != NULL )
+    // Warn about unsupported file types virtual mosaic and meta file.
+    if( CSLFetchNameValue(poDS->papszHeader, "file_type" ) != NULL )
     {
         // When the file type is one of these we return an invalid file type err
-            // 'envi meta file'
-            // 'envi virtual mosaic'
-            // 'envi spectral library'
-            // 'envi fft result'
+        // 'envi meta file'
+        // 'envi virtual mosaic'
+        // 'envi spectral library'
+        // 'envi fft result'
 
         // When the file type is one of these we open it
-            // 'envi standard'
-            // 'envi classification'
+        // 'envi standard'
+        // 'envi classification'
 
         // When the file type is anything else we attempt to open it as a
         // raster.
@@ -2332,38 +2200,32 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
             EQUAL(pszEnviFileType, "envi virtual mosaic") ||
             EQUAL(pszEnviFileType, "envi spectral library") )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "File %s contains an invalid file type in the ENVI .hdr "
-                      "GDAL does not support '%s' type files.",
-                      poOpenInfo->pszFilename, pszEnviFileType );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "File %s contains an invalid file type in the ENVI .hdr "
+                     "GDAL does not support '%s' type files.",
+                     poOpenInfo->pszFilename, pszEnviFileType);
             delete poDS;
             return NULL;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Detect (gzipped) compressed datasets.                           */
-/* -------------------------------------------------------------------- */
+    // Detect (gzipped) compressed datasets.
     bool bIsCompressed = false;
-    if( CSLFetchNameValue(poDS->papszHeader,"file_compression" ) != NULL )
+    if( CSLFetchNameValue(poDS->papszHeader, "file_compression") != NULL )
     {
-        if( atoi(CSLFetchNameValue(poDS->papszHeader,"file_compression" ))
+        if( atoi(CSLFetchNameValue(poDS->papszHeader, "file_compression"))
             != 0 )
         {
             bIsCompressed = true;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Capture some information from the file that is of interest.     */
-/* -------------------------------------------------------------------- */
+    // Capture some information from the file that is of interest.
     poDS->nRasterXSize = nSamples;
     poDS->nRasterYSize = nLines;
     poDS->eAccess = poOpenInfo->eAccess;
 
-/* -------------------------------------------------------------------- */
-/*      Reopen file in update mode if necessary.                        */
-/* -------------------------------------------------------------------- */
+    // Reopen file in update mode if necessary.
     CPLString osImageFilename(poOpenInfo->pszFilename);
     if ( bIsCompressed )
         osImageFilename = "/vsigzip/" + osImageFilename;
@@ -2372,29 +2234,27 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
         if( bIsCompressed )
         {
             delete poDS;
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Cannot open compressed file in update mode.\n" );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Cannot open compressed file in update mode.");
             return NULL;
         }
-        poDS->fpImage = VSIFOpenL( osImageFilename, "rb+" );
+        poDS->fpImage = VSIFOpenL(osImageFilename, "rb+");
     }
     else
     {
-        poDS->fpImage = VSIFOpenL( osImageFilename, "rb" );
+        poDS->fpImage = VSIFOpenL(osImageFilename, "rb");
     }
 
     if( poDS->fpImage == NULL )
     {
         delete poDS;
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to re-open %s within ENVI driver.",
-                  poOpenInfo->pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Failed to re-open %s within ENVI driver.",
+                 poOpenInfo->pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Compute the line offset.                                        */
-/* -------------------------------------------------------------------- */
+    // Compute the line offset.
     const int nDataSize = GDALGetDataTypeSizeBytes(eType);
     int nPixelOffset = 0;
     int nLineOffset = 0;
@@ -2405,12 +2265,11 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
     if( STARTS_WITH_CI(pszInterleave, "bil") )
     {
         poDS->interleave = BIL;
-        poDS->SetMetadataItem( "INTERLEAVE", "LINE", "IMAGE_STRUCTURE" );
-        if (nSamples > INT_MAX / (nDataSize * nBands))
+        poDS->SetMetadataItem("INTERLEAVE", "LINE", "IMAGE_STRUCTURE");
+        if (nSamples > std::numeric_limits<int>::max() / (nDataSize * nBands))
         {
             delete poDS;
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Int overflow occurred.");
+            CPLError(CE_Failure, CPLE_AppDefined, "Int overflow occurred.");
             return NULL;
         }
         nLineOffset = nDataSize * nSamples * nBands;
@@ -2420,27 +2279,25 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
     else if( STARTS_WITH_CI(pszInterleave, "bip") )
     {
         poDS->interleave = BIP;
-        poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
-        if (nSamples > INT_MAX / (nDataSize * nBands))
+        poDS->SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+        if (nSamples > std::numeric_limits<int>::max() / (nDataSize * nBands))
         {
             delete poDS;
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Int overflow occurred.");
+            CPLError(CE_Failure, CPLE_AppDefined, "Int overflow occurred.");
             return NULL;
         }
         nLineOffset = nDataSize * nSamples * nBands;
         nPixelOffset = nDataSize * nBands;
         nBandOffset = nDataSize;
     }
-    else /* bsq */
+    else
     {
         poDS->interleave = BSQ;
-        poDS->SetMetadataItem( "INTERLEAVE", "BAND", "IMAGE_STRUCTURE" );
-        if (nSamples > INT_MAX / nDataSize)
+        poDS->SetMetadataItem("INTERLEAVE", "BAND", "IMAGE_STRUCTURE");
+        if (nSamples > std::numeric_limits<int>::max() / nDataSize)
         {
             delete poDS;
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Int overflow occurred.");
+            CPLError(CE_Failure, CPLE_AppDefined, "Int overflow occurred.");
             return NULL;
         }
         nLineOffset = nDataSize * nSamples;
@@ -2448,18 +2305,16 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
         nBandOffset = (vsi_l_offset)nLineOffset * nLines;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create band information objects.                                */
-/* -------------------------------------------------------------------- */
+    // Create band information objects.
     poDS->nBands = nBands;
     CPLErrorReset();
     for( int i = 0; i < poDS->nBands; i++ )
     {
-        poDS->SetBand( i + 1,
-                       new ENVIRasterBand( poDS, i + 1, poDS->fpImage,
-                                           nHeaderSize + nBandOffset * i,
-                                           nPixelOffset, nLineOffset, eType,
-                                           bNativeOrder, TRUE) );
+        poDS->SetBand(i + 1,
+                      new ENVIRasterBand(poDS, i + 1, poDS->fpImage,
+                                         nHeaderSize + nBandOffset * i,
+                                         nPixelOffset, nLineOffset, eType,
+                                         bNativeOrder, TRUE));
         if( CPLGetLastErrorType() != CE_None )
         {
             poDS->nBands = i + 1;
@@ -2468,44 +2323,39 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Apply band names if we have them.                               */
-/*      Use wavelength for more descriptive information if possible     */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue( poDS->papszHeader, "band_names" ) != NULL ||
-        CSLFetchNameValue( poDS->papszHeader, "wavelength" ) != NULL)
+    // Apply band names if we have them.
+    // Use wavelength for more descriptive information if possible.
+    if( CSLFetchNameValue(poDS->papszHeader, "band_names") != NULL ||
+        CSLFetchNameValue(poDS->papszHeader, "wavelength") != NULL)
     {
         char **papszBandNames =
-            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader,
-                                                "band_names" ) );
+            poDS->SplitList(CSLFetchNameValue(poDS->papszHeader, "band_names"));
         char **papszWL =
-            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader,
-                                                "wavelength" ) );
+            poDS->SplitList(CSLFetchNameValue(poDS->papszHeader, "wavelength"));
 
         const char *pszWLUnits = NULL;
         const int nWLCount = CSLCount(papszWL);
         if (papszWL)
         {
-            /* If WL information is present, process wavelength units. */
-            pszWLUnits = CSLFetchNameValue( poDS->papszHeader,
-                                            "wavelength_units" );
+            // If WL information is present, process wavelength units.
+            pszWLUnits =
+                CSLFetchNameValue(poDS->papszHeader, "wavelength_units");
             if (pszWLUnits)
             {
-                /* Don't show unknown or index units */
-                if( EQUAL(pszWLUnits,"Unknown") ||
-                    EQUAL(pszWLUnits,"Index") )
-                    pszWLUnits=NULL;
+                // Don't show unknown or index units.
+                if( EQUAL(pszWLUnits, "Unknown") || EQUAL(pszWLUnits, "Index") )
+                    pszWLUnits = NULL;
             }
             if( pszWLUnits )
             {
-                /* Set wavelength units to dataset metadata. */
+                // Set wavelength units to dataset metadata.
                 poDS->SetMetadataItem("wavelength_units", pszWLUnits);
             }
         }
 
         for( int i = 0; i < nBands; i++ )
         {
-            /* First set up the wavelength names and units if available. */
+            // First set up the wavelength names and units if available.
             CPLString osWavelength;
             if (papszWL && nWLCount > i)
             {
@@ -2517,109 +2367,99 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
             }
 
-            /* Build the final name for this band. */
+            // Build the final name for this band.
             CPLString osBandName;
             if (papszBandNames && CSLCount(papszBandNames) > i)
             {
                 osBandName = papszBandNames[i];
-                if (strlen(osWavelength) > 0)
+                if( !osWavelength.empty() )
                 {
                     osBandName += " (";
                     osBandName += osWavelength;
                     osBandName += ")";
                 }
             }
-            else   /* WL but no band names */
+            else
             {
+                // WL but no band names.
                 osBandName = osWavelength;
             }
 
-            /* Description is for internal GDAL usage */
-            poDS->GetRasterBand(i + 1)->SetDescription( osBandName );
+            // Description is for internal GDAL usage.
+            poDS->GetRasterBand(i + 1)->SetDescription(osBandName);
 
-            /* Metadata field named Band_1, etc. needed for ArcGIS integration */
-            CPLString osBandId = CPLSPrintf("Band_%i", i+1);
+            // Metadata field named Band_1, etc. Needed for ArcGIS integration.
+            CPLString osBandId = CPLSPrintf("Band_%i", i + 1);
             poDS->SetMetadataItem(osBandId, osBandName);
 
-            /* Set wavelength metadata to band */
+            // Set wavelength metadata to band.
             if (papszWL && nWLCount > i)
             {
-                poDS->GetRasterBand(i+1)->SetMetadataItem(
-                    "wavelength", papszWL[i]);
+                poDS->GetRasterBand(i + 1)->SetMetadataItem("wavelength",
+                                                            papszWL[i]);
 
                 if (pszWLUnits)
                 {
-                    poDS->GetRasterBand(i+1)->SetMetadataItem(
+                    poDS->GetRasterBand(i + 1)->SetMetadataItem(
                         "wavelength_units", pszWLUnits);
                 }
             }
-
         }
-        CSLDestroy( papszWL );
-        CSLDestroy( papszBandNames );
+        CSLDestroy(papszWL);
+        CSLDestroy(papszBandNames);
     }
-/* -------------------------------------------------------------------- */
-/*      Apply class names if we have them.                              */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue( poDS->papszHeader, "class_names" ) != NULL )
+
+    // Apply class names if we have them.
+    if( CSLFetchNameValue(poDS->papszHeader, "class_names") != NULL )
     {
-        char **papszClassNames =
-            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader,
-                                                "class_names" ) );
+        char **papszClassNames = poDS->SplitList(
+            CSLFetchNameValue(poDS->papszHeader, "class_names"));
 
-        poDS->GetRasterBand(1)->SetCategoryNames( papszClassNames );
-        CSLDestroy( papszClassNames );
+        poDS->GetRasterBand(1)->SetCategoryNames(papszClassNames);
+        CSLDestroy(papszClassNames);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Apply colormap if we have one.                                  */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue( poDS->papszHeader, "class_lookup" ) != NULL )
+    // Apply colormap if we have one.
+    if( CSLFetchNameValue(poDS->papszHeader, "class_lookup") != NULL )
     {
-        char **papszClassColors =
-            poDS->SplitList( CSLFetchNameValue( poDS->papszHeader,
-                                                "class_lookup" ) );
+        char **papszClassColors = poDS->SplitList(
+            CSLFetchNameValue(poDS->papszHeader, "class_lookup"));
         const int nColorValueCount = CSLCount(papszClassColors);
         GDALColorTable oCT;
 
-        for( int i = 0; i*3+2 < nColorValueCount; i++ )
+        for( int i = 0; i * 3 + 2 < nColorValueCount; i++ )
         {
             GDALColorEntry sEntry;
 
-            sEntry.c1 = static_cast<short>( atoi(papszClassColors[i*3+0]) );
-            sEntry.c2 = static_cast<short>( atoi(papszClassColors[i*3+1]) );
-            sEntry.c3 = static_cast<short>( atoi(papszClassColors[i*3+2]) );
+            sEntry.c1 = static_cast<short>(atoi(papszClassColors[i * 3 + 0]));
+            sEntry.c2 = static_cast<short>(atoi(papszClassColors[i * 3 + 1]));
+            sEntry.c3 = static_cast<short>(atoi(papszClassColors[i * 3 + 2]));
             sEntry.c4 = 255;
-            oCT.SetColorEntry( i, &sEntry );
+            oCT.SetColorEntry(i, &sEntry);
         }
 
-        CSLDestroy( papszClassColors );
+        CSLDestroy(papszClassColors);
 
-        poDS->GetRasterBand(1)->SetColorTable( &oCT );
-        poDS->GetRasterBand(1)->SetColorInterpretation( GCI_PaletteIndex );
+        poDS->GetRasterBand(1)->SetColorTable(&oCT);
+        poDS->GetRasterBand(1)->SetColorInterpretation(GCI_PaletteIndex);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set the nodata value if it is present                           */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue(poDS->papszHeader,"data_ignore_value" ) != NULL )
+    // Set the nodata value if it is present.
+    if( CSLFetchNameValue(poDS->papszHeader, "data_ignore_value" ) != NULL )
     {
         for( int i = 0; i < poDS->nBands; i++ )
-            reinterpret_cast<RawRasterBand*>(
-                poDS->GetRasterBand(i+1) )->SetNoDataValue(CPLAtof(
-                    CSLFetchNameValue(poDS->papszHeader,"data_ignore_value")));
+            reinterpret_cast<RawRasterBand *>(poDS->GetRasterBand(i + 1))
+                ->SetNoDataValue(CPLAtof(
+                    CSLFetchNameValue(poDS->papszHeader, "data_ignore_value")));
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set all the header metadata into the ENVI domain                */
-/* -------------------------------------------------------------------- */
+    // Set all the header metadata into the ENVI domain.
     {
-        char** pTmp = poDS->papszHeader;
+        char **pTmp = poDS->papszHeader;
         while( *pTmp != NULL )
         {
-            char** pTokens =
-                CSLTokenizeString2(
-                    *pTmp, "=", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES );
+            char **pTokens = CSLTokenizeString2(
+                *pTmp, "=", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
             if (pTokens[0] != NULL && pTokens[1] != NULL && pTokens[2] == NULL)
             {
                 poDS->SetMetadataItem(pTokens[0], pTokens[1], "ENVI");
@@ -2629,42 +2469,30 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the stats file if it is present                            */
-/* -------------------------------------------------------------------- */
+    // Read the stats file if it is present.
     poDS->ProcessStatsFile();
 
-/* -------------------------------------------------------------------- */
-/*      Look for mapinfo                                                */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue( poDS->papszHeader, "map_info" ) != NULL )
+    // Look for mapinfo.
+    if( CSLFetchNameValue(poDS->papszHeader, "map_info") != NULL )
     {
-        poDS->bFoundMapinfo = CPL_TO_BOOL(
-            poDS->ProcessMapinfo(
-                CSLFetchNameValue(poDS->papszHeader, "map_info") ) );
+        poDS->bFoundMapinfo = CPL_TO_BOOL(poDS->ProcessMapinfo(
+            CSLFetchNameValue(poDS->papszHeader, "map_info")));
     }
 
-/* -------------------------------------------------------------------- */
-/*      Look for RPC mapinfo                                            */
-/* -------------------------------------------------------------------- */
+    // Look for RPC mapinfo.
     if( !poDS->bFoundMapinfo &&
-        CSLFetchNameValue( poDS->papszHeader, "rpc_info" ) != NULL )
+        CSLFetchNameValue(poDS->papszHeader, "rpc_info") != NULL )
     {
-        poDS->ProcessRPCinfo(
-            CSLFetchNameValue(poDS->papszHeader,"rpc_info"),
-            poDS->nRasterXSize, poDS->nRasterYSize);
+        poDS->ProcessRPCinfo(CSLFetchNameValue(poDS->papszHeader, "rpc_info"),
+                             poDS->nRasterXSize, poDS->nRasterYSize);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize any PAM information.                                 */
-/* -------------------------------------------------------------------- */
-    poDS->SetDescription( poOpenInfo->pszFilename );
+    // Initialize any PAM information.
+    poDS->SetDescription(poOpenInfo->pszFilename);
     poDS->TryLoadXML();
 
-/* -------------------------------------------------------------------- */
-/*      Check for overviews.                                            */
-/* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
+    // Check for overviews.
+    poDS->oOvManager.Initialize(poDS, poOpenInfo->pszFilename);
 
     // SetMetadata() calls in Open() makes the header dirty.
     // Don't re-write the header if nothing external has changed the metadata.
@@ -2675,132 +2503,115 @@ GDALDataset *ENVIDataset::Open( GDALOpenInfo * poOpenInfo )
 
 int ENVIDataset::GetEnviType(GDALDataType eType)
 {
-  int iENVIType = 1;
-  switch( eType )
-  {
-      case GDT_Byte:
-          iENVIType = 1;
-          break;
-      case GDT_Int16:
-          iENVIType = 2;
-          break;
-      case GDT_Int32:
-          iENVIType = 3;
-          break;
-      case GDT_Float32:
-          iENVIType = 4;
-          break;
-      case GDT_Float64:
-          iENVIType = 5;
-          break;
-      case GDT_CFloat32:
-          iENVIType = 6;
-          break;
-      case GDT_CFloat64:
-          iENVIType = 9;
-          break;
-      case GDT_UInt16:
-          iENVIType = 12;
-          break;
-      case GDT_UInt32:
-          iENVIType = 13;
-          break;
-
-      // 14=Int64, 15=UInt64
-
-      default:
-          CPLError( CE_Failure, CPLE_AppDefined,
-                    "Attempt to create ENVI .hdr labelled dataset with an "
-                    "illegal data type (%s).",
-                    GDALGetDataTypeName(eType) );
-          return 1;
-  }
-  return iENVIType;
+    int iENVIType = 1;
+    switch(eType)
+    {
+    case GDT_Byte:
+        iENVIType = 1;
+        break;
+    case GDT_Int16:
+        iENVIType = 2;
+        break;
+    case GDT_Int32:
+        iENVIType = 3;
+        break;
+    case GDT_Float32:
+        iENVIType = 4;
+        break;
+    case GDT_Float64:
+        iENVIType = 5;
+        break;
+    case GDT_CFloat32:
+        iENVIType = 6;
+        break;
+    case GDT_CFloat64:
+        iENVIType = 9;
+        break;
+    case GDT_UInt16:
+        iENVIType = 12;
+        break;
+    case GDT_UInt32:
+        iENVIType = 13;
+        break;
+
+    // 14=Int64, 15=UInt64
+
+    default:
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Attempt to create ENVI .hdr labelled dataset with an "
+                 "illegal data type (%s).",
+                 GDALGetDataTypeName(eType));
+        return 1;
+    }
+    return iENVIType;
 }
 
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
 
-GDALDataset *ENVIDataset::Create( const char * pszFilename,
+GDALDataset *ENVIDataset::Create( const char *pszFilename,
                                   int nXSize, int nYSize, int nBands,
                                   GDALDataType eType,
-                                  char ** papszOptions )
+                                  char **papszOptions )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Verify input options.                                           */
-/* -------------------------------------------------------------------- */
+    // Verify input options.
     int iENVIType = GetEnviType(eType);
     if( 0 == iENVIType )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Try to create the file.                                         */
-/* -------------------------------------------------------------------- */
-    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
+    // Try to create the file.
+    VSILFILE *fp = VSIFOpenL(pszFilename, "wb");
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Attempt to create file `%s' failed.", pszFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Just write out a couple of bytes to establish the binary        */
-/*      file, and then close it.                                        */
-/* -------------------------------------------------------------------- */
-    bool bRet =
-        VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "\0\0" ) ),
-                    2, 1, fp ) == 1;
-    if( VSIFCloseL( fp ) != 0 )
-        bRet = false;
-    if( !bRet )
-        return NULL;
+    // Just write out a couple of bytes to establish the binary
+    // file, and then close it.
+    {
+        const bool bRet = VSIFWriteL(
+            static_cast<void *>(const_cast<char *>("\0\0")), 2, 1, fp) == 1;
+        if( VSIFCloseL(fp) != 0 || !bRet )
+            return NULL;
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Create the .hdr filename.                                       */
-/* -------------------------------------------------------------------- */
+    // Create the .hdr filename.
     const char *pszHDRFilename = NULL;
-    const char *pszSuffix = CSLFetchNameValue( papszOptions, "SUFFIX" );
+    const char *pszSuffix = CSLFetchNameValue(papszOptions, "SUFFIX");
     if ( pszSuffix && STARTS_WITH_CI(pszSuffix, "ADD"))
-        pszHDRFilename = CPLFormFilename( NULL, pszFilename, "hdr" );
+        pszHDRFilename = CPLFormFilename(NULL, pszFilename, "hdr");
     else
-        pszHDRFilename = CPLResetExtension(pszFilename, "hdr" );
+        pszHDRFilename = CPLResetExtension(pszFilename, "hdr");
 
-/* -------------------------------------------------------------------- */
-/*      Open the file.                                                  */
-/* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszHDRFilename, "wt" );
+    // Open the file.
+    fp = VSIFOpenL(pszHDRFilename, "wt");
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.",
-                  pszHDRFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Attempt to create file `%s' failed.",
+                 pszHDRFilename);
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write out the header.                                           */
-/* -------------------------------------------------------------------- */
-    const int iBigEndian =
+    // Write out the header.
 #ifdef CPL_LSB
-    0
+    const int iBigEndian = 0;
 #else
-    1
+    const int iBigEndian = 1;
 #endif
-        ;
 
-    bRet = VSIFPrintfL( fp, "ENVI\n" ) > 0;
-    bRet &= VSIFPrintfL( fp, "samples = %d\nlines   = %d\nbands   = %d\n",
-                         nXSize, nYSize, nBands ) > 0;
+    bool bRet = VSIFPrintfL(fp, "ENVI\n") > 0;
+    bRet &= VSIFPrintfL(fp, "samples = %d\nlines   = %d\nbands   = %d\n",
+                        nXSize, nYSize, nBands) > 0;
     bRet &=
-        VSIFPrintfL( fp, "header offset = 0\nfile type = ENVI Standard\n" ) > 0;
-    bRet &= VSIFPrintfL( fp, "data type = %d\n", iENVIType ) > 0;
-    const char *pszInterleaving =
-        CSLFetchNameValue( papszOptions, "INTERLEAVE" );
+        VSIFPrintfL(fp, "header offset = 0\nfile type = ENVI Standard\n") > 0;
+    bRet &= VSIFPrintfL(fp, "data type = %d\n", iENVIType) > 0;
+    const char *pszInterleaving = CSLFetchNameValue(papszOptions, "INTERLEAVE");
     if ( pszInterleaving )
     {
         if( STARTS_WITH_CI(pszInterleaving, "bip") )
@@ -2811,18 +2622,17 @@ GDALDataset *ENVIDataset::Create( const char * pszFilename,
             pszInterleaving = "bsq";  // band sequential by default
     }
     else
+    {
         pszInterleaving = "bsq";
-    bRet &= VSIFPrintfL( fp, "interleave = %s\n", pszInterleaving) > 0;
-    bRet &= VSIFPrintfL( fp, "byte order = %d\n", iBigEndian ) > 0;
-
-    if( VSIFCloseL( fp ) != 0 )
-        bRet = false;
+    }
+    bRet &= VSIFPrintfL(fp, "interleave = %s\n", pszInterleaving) > 0;
+    bRet &= VSIFPrintfL(fp, "byte order = %d\n", iBigEndian) > 0;
 
-    if( !bRet )
+    if( VSIFCloseL(fp) != 0 || !bRet )
         return NULL;
 
-    GDALOpenInfo oOpenInfo( pszFilename, GA_Update );
-    ENVIDataset* poDS = reinterpret_cast<ENVIDataset*>(Open( &oOpenInfo ));
+    GDALOpenInfo oOpenInfo(pszFilename, GA_Update);
+    ENVIDataset *poDS = reinterpret_cast<ENVIDataset *>(Open(&oOpenInfo));
     if( poDS )
     {
         poDS->SetFillFile();
@@ -2840,18 +2650,18 @@ ENVIRasterBand::ENVIRasterBand( GDALDataset *poDSIn, int nBandIn,
                                 int nLineOffsetIn,
                                 GDALDataType eDataTypeIn, int bNativeOrderIn,
                                 int bIsVSILIn, int bOwnsFPIn ) :
-    RawRasterBand( poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
-                   nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn,
-                   bOwnsFPIn )
+    RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                  nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn,
+                  bOwnsFPIn)
 {}
 
 /************************************************************************/
 /*                           SetDescription()                           */
 /************************************************************************/
 
-void ENVIRasterBand::SetDescription( const char * pszDescription )
+void ENVIRasterBand::SetDescription( const char *pszDescription )
 {
-    reinterpret_cast<ENVIDataset *>( poDS )->bHeaderDirty = true;
+    reinterpret_cast<ENVIDataset *>(poDS)->bHeaderDirty = true;
     RawRasterBand::SetDescription(pszDescription);
 }
 
@@ -2859,9 +2669,9 @@ void ENVIRasterBand::SetDescription( const char * pszDescription )
 /*                           SetCategoryNames()                         */
 /************************************************************************/
 
-CPLErr ENVIRasterBand::SetCategoryNames( char ** papszCategoryNamesIn )
+CPLErr ENVIRasterBand::SetCategoryNames( char **papszCategoryNamesIn )
 {
-    reinterpret_cast<ENVIDataset *>( poDS )->bHeaderDirty = true;
+    reinterpret_cast<ENVIDataset *>(poDS)->bHeaderDirty = true;
     return RawRasterBand::SetCategoryNames(papszCategoryNamesIn);
 }
 
@@ -2871,34 +2681,35 @@ CPLErr ENVIRasterBand::SetCategoryNames( char ** papszCategoryNamesIn )
 
 void GDALRegister_ENVI()
 {
-    if( GDALGetDriverByName( "ENVI" ) != NULL )
+    if( GDALGetDriverByName("ENVI") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "ENVI" );
-    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "ENVI .hdr Labelled" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#ENVI" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
-                               "Byte Int16 UInt16 Int32 UInt32 "
-                               "Float32 Float64 CFloat32 CFloat64" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-"<CreationOptionList>"
-"   <Option name='SUFFIX' type='string-select'>"
-"       <Value>ADD</Value>"
-"   </Option>"
-"   <Option name='INTERLEAVE' type='string-select'>"
-"       <Value>BIP</Value>"
-"       <Value>BIL</Value>"
-"       <Value>BSQ</Value>"
-"   </Option>"
-"</CreationOptionList>" );
-
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetDescription("ENVI");
+    poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "ENVI .hdr Labelled");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "frmt_various.html#ENVI");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "");
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
+                              "Byte Int16 UInt16 Int32 UInt32 "
+                              "Float32 Float64 CFloat32 CFloat64");
+    poDriver->SetMetadataItem(
+        GDAL_DMD_CREATIONOPTIONLIST,
+        "<CreationOptionList>"
+        "   <Option name='SUFFIX' type='string-select'>"
+        "       <Value>ADD</Value>"
+        "   </Option>"
+        "   <Option name='INTERLEAVE' type='string-select'>"
+        "       <Value>BIP</Value>"
+        "       <Value>BIL</Value>"
+        "       <Value>BSQ</Value>"
+        "   </Option>"
+        "</CreationOptionList>");
+
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
     poDriver->pfnOpen = ENVIDataset::Open;
     poDriver->pfnCreate = ENVIDataset::Create;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/frmts/raw/envidataset.h b/frmts/raw/envidataset.h
new file mode 100644
index 0000000..758b127
--- /dev/null
+++ b/frmts/raw/envidataset.h
@@ -0,0 +1,153 @@
+/******************************************************************************
+ * $Id: envidataset.h 37514 2017-02-28 16:55:45Z goatbar $
+ *
+ * Project:  ENVI .hdr Driver
+ * Purpose:  Implementation of ENVI .hdr labelled raw raster support.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ * Maintainer: Chris Padwick (cpadwick at ittvis.com)
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDAL_FRMTS_RAW_ENVIDATASET_H_INCLUDED
+#define GDAL_FRMTS_RAW_ENVIDATASET_H_INCLUDED
+
+#include "cpl_port.h"
+#include "rawdataset.h"
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
+#include <limits>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_frmts.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
+
+class ENVIRasterBand;
+
+class ENVIDataset : public RawDataset
+{
+    friend class ENVIRasterBand;
+
+    VSILFILE   *fpImage;  // Image data file.
+    VSILFILE   *fp;  // Header file
+    char       *pszHDRFilename;
+
+    bool        bFoundMapinfo;
+    bool        bHeaderDirty;
+    bool        bFillFile;
+
+    double      adfGeoTransform[6];
+
+    char       *pszProjection;
+
+    char        **papszHeader;
+
+    CPLString   osStaFilename;
+
+    bool        ReadHeader( VSILFILE * );
+    bool        ProcessMapinfo( const char * );
+    void        ProcessRPCinfo( const char *, int, int);
+    void        ProcessStatsFile();
+    static int         byteSwapInt(int);
+    static float       byteSwapFloat(float);
+    static double      byteSwapDouble(double);
+    static void        SetENVIDatum( OGRSpatialReference *, const char * );
+    static void        SetENVIEllipse( OGRSpatialReference *, char ** );
+    void        WriteProjectionInfo();
+    bool        ParseRpcCoeffsMetaDataString( const char *psName,
+                                              char *papszVal[], int& idx );
+    bool        WriteRpcInfo();
+    bool        WritePseudoGcpInfo();
+
+    void        SetFillFile() { bFillFile = true; }
+
+    char        **SplitList( const char * );
+
+    enum Interleave { BSQ, BIL, BIP } interleave;
+    static int GetEnviType(GDALDataType eType);
+
+  public:
+            ENVIDataset();
+    virtual ~ENVIDataset();
+
+    virtual void    FlushCache() override;
+    virtual CPLErr  GetGeoTransform( double *padfTransform ) override;
+    virtual CPLErr  SetGeoTransform( double * ) override;
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr  SetProjection( const char * ) override;
+    virtual char  **GetFileList(void) override;
+
+    virtual void        SetDescription( const char * ) override;
+
+    virtual CPLErr      SetMetadata( char **papszMetadata,
+                                     const char *pszDomain = "" ) override;
+    virtual CPLErr      SetMetadataItem( const char *pszName,
+                                         const char *pszValue,
+                                         const char *pszDomain = "" ) override;
+    virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
+                            const char *pszGCPProjection ) override;
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static GDALDataset *Create( const char *pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType, char ** papszOptions );
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            ENVIRasterBand                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class ENVIRasterBand : public RawRasterBand
+{
+    public:
+                ENVIRasterBand( GDALDataset *poDS, int nBand, void *fpRaw,
+                                vsi_l_offset nImgOffset, int nPixelOffset,
+                                int nLineOffset,
+                                GDALDataType eDataType, int bNativeOrder,
+                                int bIsVSIL = FALSE, int bOwnsFP = FALSE );
+    virtual ~ENVIRasterBand() {}
+
+    virtual void        SetDescription( const char * ) override;
+
+    virtual CPLErr SetCategoryNames( char ** ) override;
+};
+
+#endif  // GDAL_FRMTS_RAW_ENVIDATASET_H_INCLUDED
diff --git a/frmts/raw/fastdataset.cpp b/frmts/raw/fastdataset.cpp
index 807ebe7..32ae6b4 100644
--- a/frmts/raw/fastdataset.cpp
+++ b/frmts/raw/fastdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: fastdataset.cpp 33935 2016-04-10 06:47:56Z goatbar $
  *
  * Project:  EOSAT FAST Format reader
  * Purpose:  Reads Landsat FAST-L7A, IRS 1C/1D
@@ -33,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: fastdataset.cpp 33935 2016-04-10 06:47:56Z goatbar $");
+CPL_CVSID("$Id: fastdataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 // static const int ADM_STD_HEADER_SIZE = 4608;  // Format specification says it
 static const int ADM_HEADER_SIZE = 5000;  // Should be 4608, but some vendors
@@ -124,12 +123,12 @@ class FASTDataset : public GDALPamDataset
 
     static GDALDataset *Open( GDALOpenInfo * );
 
-    CPLErr      GetGeoTransform( double * );
-    const char  *GetProjectionRef();
+    CPLErr      GetGeoTransform( double * ) override;
+    const char  *GetProjectionRef() override;
     VSILFILE    *FOpenChannel( const char *, int iBand, int iFASTBand );
     void        TryEuromap_IRS_1C_1D_ChannelNameConvention();
 
-    virtual  char** GetFileList();
+    virtual  char** GetFileList() override;
 };
 
 /************************************************************************/
@@ -147,7 +146,6 @@ class FASTRasterBand : public RawRasterBand
                                 int, int, GDALDataType, int );
 };
 
-
 /************************************************************************/
 /*                           FASTRasterBand()                           */
 /************************************************************************/
@@ -243,7 +241,7 @@ char** FASTDataset::GetFileList()
 
     for( int i = 0; i < 6; i++ )
     {
-        if (apoChannelFilenames[i].size() > 0)
+        if (!apoChannelFilenames[i].empty())
             papszFileList =
                 CSLAddString(papszFileList, apoChannelFilenames[i].c_str());
     }
@@ -267,7 +265,6 @@ int FASTDataset::OpenChannel( const char *pszFilenameIn, int iBand )
 /*                             FOpenChannel()                           */
 /************************************************************************/
 
-
 VSILFILE *FASTDataset::FOpenChannel( const char *pszBandname,
                                      int iBand, int iFASTBand )
 {
@@ -904,6 +901,12 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->SetMetadataItem( CPLSPrintf(pszFirst, i ), pszValue );
             CPLFree( pszValue );
         }
+        else
+        {
+            CPLFree(pszHeader);
+            delete poDS;
+            return NULL;
+        }
         pszTemp += nValueLen;
         pszTemp = strpbrk( pszTemp, "-.0123456789" );
         if ( pszTemp )
@@ -915,6 +918,12 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->SetMetadataItem( CPLSPrintf(pszSecond, i ), pszValue );
             CPLFree( pszValue );
         }
+        else
+        {
+            CPLFree(pszHeader);
+            delete poDS;
+            return NULL;
+        }
         pszTemp += nValueLen;
     }
 
@@ -965,8 +974,16 @@ GDALDataset *FASTDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             pszTemp = strpbrk( pszTemp, "-.0123456789" );
             if ( pszTemp )
+            {
                 adfProjParms[i] = CPLScanDouble( pszTemp, VALUE_SIZE );
-            pszTemp = strpbrk( pszTemp, " \t" );
+                pszTemp = strpbrk( pszTemp, " \t" );
+            }
+            if (pszTemp == NULL )
+            {
+                CPLFree(pszHeader);
+                delete poDS;
+                return NULL;
+            }
         }
     }
 
diff --git a/frmts/raw/fujibasdataset.cpp b/frmts/raw/fujibasdataset.cpp
index 3b1e763..fe9f45a 100644
--- a/frmts/raw/fujibasdataset.cpp
+++ b/frmts/raw/fujibasdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: fujibasdataset.cpp 33937 2016-04-10 15:40:56Z goatbar $
  *
  * Project:  eCognition
  * Purpose:  Implementation of FUJI BAS Format
@@ -32,11 +31,7 @@
 #include "gdal_frmts.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: fujibasdataset.cpp 33937 2016-04-10 15:40:56Z goatbar $");
-
-CPL_C_START
-void GDALRegister_FujiBAS();
-CPL_C_END
+CPL_CVSID("$Id: fujibasdataset.cpp 34643 2016-07-12 13:09:59Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -193,11 +188,11 @@ GDALDataset *FujiBASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information object.                                 */
 /* -------------------------------------------------------------------- */
-    const int bNativeOrder =
+    const bool bNativeOrder =
 #ifdef CPL_MSB
-    TRUE
+    true
 #else
-    FALSE
+    false
 #endif
         ;
     poDS->SetBand(
diff --git a/frmts/raw/genbindataset.cpp b/frmts/raw/genbindataset.cpp
index 48d3bde..d374081 100644
--- a/frmts/raw/genbindataset.cpp
+++ b/frmts/raw/genbindataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ehdrdataset.cpp 12350 2007-10-08 17:41:32Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Generic Binary format driver (.hdr but not ESRI .hdr!)
@@ -33,7 +32,9 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: ehdrdataset.cpp 12350 2007-10-08 17:41:32Z rouault $");
+#include <cstdlib>
+
+CPL_CVSID("$Id: genbindataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /* ==================================================================== */
 /*      Table relating USGS and ESRI state plane zones.                 */
@@ -206,10 +207,10 @@ class GenBinDataset : public RawDataset
     GenBinDataset();
     virtual ~GenBinDataset();
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef(void);
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef(void) override;
 
-    virtual char **GetFileList();
+    virtual char **GetFileList() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -228,7 +229,7 @@ class GenBinBitRasterBand : public GDALPamRasterBand
     GenBinBitRasterBand( GenBinDataset *poDS, int nBits );
     virtual ~GenBinBitRasterBand() {}
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -461,7 +462,7 @@ void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
     if( EQUAL(pszProjName,"UTM") && nZone != 0 )
     {
         // Just getting that the negative zone for southern hemisphere is used.
-        oSRS.SetUTM( ABS(nZone), nZone > 0 );
+        oSRS.SetUTM( std::abs(nZone), nZone > 0 );
     }
 
     else if( EQUAL(pszProjName,"State Plane") && nZone != 0 )
@@ -486,7 +487,7 @@ void GenBinDataset::ParseCoordinateSystem( char **papszHdr )
         else
             pszUnits = NULL;
 
-        oSRS.SetStatePlane( ABS(nZone),
+        oSRS.SetStatePlane( std::abs(nZone),
                             pszDatumName==NULL || !EQUAL(pszDatumName,"NAD27"),
                             pszUnits, dfUnits );
     }
diff --git a/frmts/raw/gscdataset.cpp b/frmts/raw/gscdataset.cpp
index c580875..c7ff57a 100644
--- a/frmts/raw/gscdataset.cpp
+++ b/frmts/raw/gscdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gscdataset.cpp 33939 2016-04-11 03:33:00Z goatbar $
  *
  * Project:  GSC Geogrid format driver.
  * Purpose:  Implements support for reading and writing GSC Geogrid format.
@@ -32,7 +31,7 @@
 #include "gdal_frmts.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: gscdataset.cpp 33939 2016-04-11 03:33:00Z goatbar $");
+CPL_CVSID("$Id: gscdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -50,7 +49,7 @@ class GSCDataset : public RawDataset
                 GSCDataset();
                 ~GSCDataset();
 
-    CPLErr      GetGeoTransform( double * padfTransform );
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
diff --git a/frmts/raw/gtxdataset.cpp b/frmts/raw/gtxdataset.cpp
index ab48cca..2c14fe1 100644
--- a/frmts/raw/gtxdataset.cpp
+++ b/frmts/raw/gtxdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gtxdataset.cpp 33940 2016-04-11 05:13:28Z goatbar $
  *
  * Project:  Vertical Datum Transformation
  * Purpose:  Implementation of NOAA .gtx vertical datum shift file format.
@@ -33,7 +32,7 @@
 #include "ogr_srs_api.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: gtxdataset.cpp 33940 2016-04-11 05:13:28Z goatbar $");
+CPL_CVSID("$Id: gtxdataset.cpp 37977 2017-04-13 15:25:27Z rouault $");
 
 /**
 
@@ -84,9 +83,9 @@ class GTXDataset : public RawDataset
                 }
     virtual ~GTXDataset();
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual CPLErr SetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef();
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr SetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -200,6 +199,15 @@ GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo )
 
     poDS->adfGeoTransform[5] *= -1;
 
+    if( CPLFetchBool(poOpenInfo->papszOpenOptions,
+                                "SHIFT_ORIGIN_IN_MINUS_180_PLUS_180", false) )
+    {
+        if( poDS->adfGeoTransform[0] < -180.0 )
+            poDS->adfGeoTransform[0] += 360.0;
+        else if( poDS->adfGeoTransform[0] > 180.0 )
+            poDS->adfGeoTransform[0] -= 360.0;
+    }
+
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
     {
         delete poDS;
@@ -386,7 +394,6 @@ GDALDataset *GTXDataset::Create( const char * pszFilename,
         GDALOpen( pszFilename, GA_Update ) );
 }
 
-
 /************************************************************************/
 /*                          GDALRegister_GTX()                          */
 /************************************************************************/
@@ -406,6 +413,12 @@ void GDALRegister_GTX()
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     // poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
     //                            "frmt_various.html#GTX" );
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"   <Option name='SHIFT_ORIGIN_IN_MINUS_180_PLUS_180' type='boolean' "
+    "description='Whether to apply a +/-360 deg shift to the longitude of "
+    "the top left corner so that it is in the [-180,180] range' default='NO'/>"
+"</OpenOptionList>" );
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
                                "Float32" );
diff --git a/frmts/raw/hkvdataset.cpp b/frmts/raw/hkvdataset.cpp
index a90a77d..0c57bc3 100644
--- a/frmts/raw/hkvdataset.cpp
+++ b/frmts/raw/hkvdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hkvdataset.cpp 33943 2016-04-11 17:41:09Z goatbar $
  *
  * Project:  GView
  * Purpose:  Implementation of Atlantis HKV labelled blob support
@@ -36,7 +35,11 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: hkvdataset.cpp 33943 2016-04-11 17:41:09Z goatbar $");
+#include <cmath>
+
+#include <algorithm>
+
+CPL_CVSID("$Id: hkvdataset.cpp 36763 2016-12-09 22:10:55Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -57,7 +60,7 @@ class HKVRasterBand : public RawRasterBand
                                GDALDataType eDataType, int bNativeOrder );
     virtual     ~HKVRasterBand() {};
 
-    virtual CPLErr SetNoDataValue( double );
+    virtual CPLErr SetNoDataValue( double ) override;
 };
 
 /************************************************************************/
@@ -165,7 +168,7 @@ class HKVDataset : public RawDataset
         // Update stored info.
         MFF2version = version_number;
     }
-    float       GetVersion() const { return MFF2version; }
+
     float       MFF2version;
 
     CPLErr      SetGCPProjection(const char *); // For use in CreateCopy.
@@ -196,15 +199,15 @@ class HKVDataset : public RawDataset
                 HKVDataset();
     virtual     ~HKVDataset();
 
-    virtual int GetGCPCount() /* const */ { return nGCPCount; };
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int GetGCPCount() override /* const */ { return nGCPCount; };
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
-    virtual CPLErr SetGeoTransform( double * );
-    virtual CPLErr SetProjection( const char * );
+    virtual CPLErr SetGeoTransform( double * ) override;
+    virtual CPLErr SetProjection( const char * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
@@ -428,7 +431,6 @@ CPLErr SaveHKVAttribFile( const char *pszFilenameIn,
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
@@ -784,7 +786,7 @@ CPLErr HKVDataset::SetProjection( const char * pszNewProjection )
     // Update a georef file.
 
 #ifdef DEBUG_VERBOSE
-    printf( "HKVDataset::SetProjection(%s)\n", pszNewProjection );
+    printf( "HKVDataset::SetProjection(%s)\n", pszNewProjection );/*ok*/
 #endif
 
     if( !STARTS_WITH_CI(pszNewProjection, "GEOGCS")
@@ -1756,8 +1758,8 @@ HKVDataset::CreateCopy( const char * pszFilename,
                     return NULL;
                 }
 
-                const int nTBXSize = MIN(nBlockXSize,nXSize-iXOffset);
-                const int nTBYSize = MIN(nBlockYSize,nYSize-iYOffset);
+                const int nTBXSize = std::min(nBlockXSize, nXSize - iXOffset);
+                const int nTBYSize = std::min(nBlockYSize, nYSize - iYOffset);
 
                 eErr = poSrcBand->RasterIO( GF_Read,
                                             iXOffset, iYOffset,
@@ -1799,8 +1801,9 @@ HKVDataset::CreateCopy( const char * pszFilename,
 
     if (( poSrcDS->GetGeoTransform( tempGeoTransform ) == CE_None)
         && (tempGeoTransform[0] != 0.0 || tempGeoTransform[1] != 1.0
-        || tempGeoTransform[2] != 0.0 || tempGeoTransform[3] != 0.0
-        || tempGeoTransform[4] != 0.0 || ABS(tempGeoTransform[5]) != 1.0 ))
+            || tempGeoTransform[2] != 0.0 || tempGeoTransform[3] != 0.0
+            || tempGeoTransform[4] != 0.0
+            || std::abs(tempGeoTransform[5]) != 1.0 ))
     {
 
           poDS->SetGCPProjection(poSrcDS->GetProjectionRef());
@@ -1825,7 +1828,6 @@ HKVDataset::CreateCopy( const char * pszFilename,
         poDstBand->FlushCache();
     }
 
-
     if( !pfnProgress( 1.0, NULL, pProgressData ) )
     {
         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -1842,7 +1844,6 @@ HKVDataset::CreateCopy( const char * pszFilename,
     return poDS;
 }
 
-
 /************************************************************************/
 /*                         GDALRegister_HKV()                           */
 /************************************************************************/
diff --git a/frmts/raw/idadataset.cpp b/frmts/raw/idadataset.cpp
index 322ce7f..20bce90 100644
--- a/frmts/raw/idadataset.cpp
+++ b/frmts/raw/idadataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: idadataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  IDA Raster Driver
  * Purpose:  Implemenents IDA driver/dataset/rasterband.
@@ -27,18 +26,87 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
-#include "ogr_spatialref.h"
+#include "gdal_priv.h"  // Must be first.
+
 #include "gdal_frmts.h"
 #include "gdal_rat.h"
+#include "ogr_spatialref.h"
+#include "rawdataset.h"
+
+CPL_CVSID("$Id: idadataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
+
+/************************************************************************/
+/*                                tp2c()                                */
+/*                                                                      */
+/*      convert a Turbo Pascal real into a double                       */
+/************************************************************************/
+
+static double tp2c( GByte *r )
+{
+    // Handle 0 case.
+    if( r[0] == 0 )
+        return 0.0;
+
+    // Extract sign: bit 7 of byte 5.
+    const int sign = (r[5] & 0x80) ? -1 : 1;
+
+    // Extract mantissa from first bit of byte 1 to bit 7 of byte 5.
+    double mant = 0.0;
+    for ( int i = 1; i < 5; i++ )
+      mant = (r[i] + mant) / 256;
+    mant = (mant + (r[5] & 0x7F)) / 128 + 1;
+
+    // Extract exponent.
+    const int exp = r[0] - 129;
 
-CPL_CVSID("$Id: idadataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
+    // Compute the damned number.
+    return sign * ldexp(mant, exp);
+}
+
+/************************************************************************/
+/*                                c2tp()                                */
+/*                                                                      */
+/*      convert a double into a Turbo Pascal real                       */
+/************************************************************************/
+
+static void c2tp( double x, GByte *r )
+{
+    // Handle 0 case.
+    if (x == 0.0)
+    {
+      // TODO(schwehr): memset.
+      for (int i = 0; i < 6; r[i++] = 0);
+      return;
+    }
+
+    // Compute mantissa, sign and exponent.
+    int exp = 0;
+    double mant = frexp(x, &exp) * 2 - 1;
+    exp--;
+    int negative = 0;
+    if( mant < 0 )
+    {
+      mant = -mant;
+      negative = 1;
+    }
+
+    // Stuff mantissa into Turbo Pascal real.
+    double temp = 0.0;
+    mant = modf(mant * 128, &temp);
+    r[5] = static_cast<unsigned char>( static_cast<int>(temp) & 0xff);
+    for( int i = 4; i >= 1; i-- )
+    {
+      mant = modf(mant * 256, &temp);
+      r[i] = static_cast<unsigned char>( temp );
+    }
 
-// convert a Turbo Pascal real into a double
-static double tp2c(GByte *r);
+    // Add sign.
+    if( negative )
+    r[5] |= 0x80;
 
-// convert a double into a Turbo Pascal real
-static void c2tp(double n, GByte *r);
+    // Put exponent.
+    r[0] = static_cast<GByte>( exp + 129 );
+}
 
 /************************************************************************/
 /* ==================================================================== */
@@ -73,7 +141,7 @@ class IDADataset : public RawDataset
     void        ProcessGeoref();
 
     GByte       abyHeader[512];
-    int         bHeaderDirty;
+    bool        bHeaderDirty;
 
     void        ReadColorTable();
 
@@ -81,19 +149,18 @@ class IDADataset : public RawDataset
                 IDADataset();
     virtual ~IDADataset();
 
-    virtual void FlushCache();
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
+    virtual void FlushCache() override;
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr SetProjection( const char * ) override;
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType,
                                 char ** /* papszParmList */ );
-
 };
 
 /************************************************************************/
@@ -113,14 +180,14 @@ class IDARasterBand : public RawRasterBand
                  IDARasterBand( IDADataset *poDSIn, VSILFILE *fpRaw, int nXSize );
     virtual     ~IDARasterBand();
 
-    virtual GDALRasterAttributeTable *GetDefaultRAT();
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
-    virtual double GetOffset( int *pbSuccess = NULL );
-    virtual CPLErr SetOffset( double dfNewValue );
-    virtual double GetScale( int *pbSuccess = NULL );
-    virtual CPLErr SetScale( double dfNewValue );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual GDALRasterAttributeTable *GetDefaultRAT() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual double GetOffset( int *pbSuccess = NULL ) override;
+    virtual CPLErr SetOffset( double dfNewValue ) override;
+    virtual double GetScale( int *pbSuccess = NULL ) override;
+    virtual CPLErr SetScale( double dfNewValue ) override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 };
 
 /************************************************************************/
@@ -142,8 +209,10 @@ IDARasterBand::IDARasterBand( IDADataset *poDSIn,
 IDARasterBand::~IDARasterBand()
 
 {
-    delete poColorTable;
-    delete poRAT;
+    if( poColorTable )
+        delete poColorTable;
+    if( poRAT )
+        delete poRAT;
 }
 
 /************************************************************************/
@@ -191,7 +260,7 @@ CPLErr IDARasterBand::SetOffset( double dfNewValue )
 
     poIDS->dfB = dfNewValue;
     c2tp( dfNewValue, poIDS->abyHeader + 177 );
-    poIDS->bHeaderDirty = TRUE;
+    poIDS->bHeaderDirty = true;
 
     return CE_None;
 }
@@ -223,13 +292,13 @@ CPLErr IDARasterBand::SetScale( double dfNewValue )
     if( poIDS->nImageType != 200 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Setting explicit scale only support for image type 200.");
+                  "Setting explicit scale only support for image type 200." );
         return CE_Failure;
     }
 
     poIDS->dfM = dfNewValue;
     c2tp( dfNewValue, poIDS->abyHeader + 171 );
-    poIDS->bHeaderDirty = TRUE;
+    poIDS->bHeaderDirty = true;
 
     return CE_None;
 }
@@ -284,17 +353,31 @@ GDALRasterAttributeTable *IDARasterBand::GetDefaultRAT()
 /************************************************************************/
 
 IDADataset::IDADataset() :
-    nImageType(0), nProjection(0), dfLatCenter(0.0), dfLongCenter(0.0),
-    dfXCenter(0.0), dfYCenter(0.0), dfDX(0.0), dfDY(0.0), dfParallel1(0.0),
-    dfParallel2(0.0), nMissing(0), dfM(0.0), dfB(0.0), fpRaw(NULL),
-    pszProjection(NULL), bHeaderDirty(FALSE)
+    nImageType(0),
+    nProjection(0),
+    dfLatCenter(0.0),
+    dfLongCenter(0.0),
+    dfXCenter(0.0),
+    dfYCenter(0.0),
+    dfDX(0.0),
+    dfDY(0.0),
+    dfParallel1(0.0),
+    dfParallel2(0.0),
+    nMissing(0),
+    dfM(0.0),
+    dfB(0.0),
+    fpRaw(NULL),
+    pszProjection(NULL),
+    bHeaderDirty(false)
 {
+    memset( szTitle, 0, sizeof(szTitle) );
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+    memset( abyHeader, 0, sizeof(abyHeader) );
 }
 
 /************************************************************************/
@@ -310,7 +393,7 @@ IDADataset::~IDADataset()
     {
         if( VSIFCloseL( fpRaw ) != 0 )
         {
-            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
         }
     }
     CPLFree( pszProjection );
@@ -393,7 +476,7 @@ void IDADataset::FlushCache()
     {
         CPL_IGNORE_RET_VAL(VSIFSeekL( fpRaw, 0, SEEK_SET ));
         CPL_IGNORE_RET_VAL(VSIFWriteL( abyHeader, 512, 1, fpRaw ));
-        bHeaderDirty = FALSE;
+        bHeaderDirty = false;
     }
 }
 
@@ -419,7 +502,7 @@ CPLErr IDADataset::SetGeoTransform( double *padfGeoTransform )
         return GDALPamDataset::SetGeoTransform( padfGeoTransform );
 
     memcpy( adfGeoTransform, padfGeoTransform, sizeof(double) * 6 );
-    bHeaderDirty = TRUE;
+    bHeaderDirty = true;
 
     dfDX = adfGeoTransform[1];
     dfDY = -adfGeoTransform[5];
@@ -456,7 +539,7 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
 {
     OGRSpatialReference oSRS;
 
-    oSRS.importFromWkt( (char **) &pszWKTIn );
+    oSRS.importFromWkt( const_cast<char **>( &pszWKTIn ) );
 
     if( !oSRS.IsGeographic() && !oSRS.IsProjected() )
         GDALPamDataset::SetProjection( pszWKTIn );
@@ -489,7 +572,7 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
         || oSRS.GetProjParm( SRS_PP_FALSE_NORTHING ) != 0.0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to set a projection on an IDA file with a non-zero\n"
+                  "Attempt to set a projection on an IDA file with a non-zero "
                   "false easting and/or northing.  This is not supported." );
         return CE_Failure;
     }
@@ -504,7 +587,7 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
     {
         /* do nothing - presumably geographic  */;
     }
-    else if( EQUAL(l_pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
+    else if( EQUAL(l_pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
     {
         nProjection = 4;
         dfParallel1 = oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
@@ -512,13 +595,13 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
         dfLatCenter = oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
         dfLongCenter = oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     }
-    else if( EQUAL(l_pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
+    else if( EQUAL(l_pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
         nProjection = 6;
         dfLatCenter = oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
         dfLongCenter = oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     }
-    else if( EQUAL(l_pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
+    else if( EQUAL(l_pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
         nProjection = 8;
         dfParallel1 = oSRS.GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0);
@@ -526,10 +609,10 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
         dfLatCenter = oSRS.GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0);
         dfLongCenter = oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
     }
-    else if( EQUAL(l_pszProjection,SRS_PT_GOODE_HOMOLOSINE) )
+    else if( EQUAL(l_pszProjection, SRS_PT_GOODE_HOMOLOSINE) )
     {
         nProjection = 9;
-        dfLongCenter = oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0);
+        dfLongCenter = oSRS.GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
     }
     else
     {
@@ -539,7 +622,7 @@ CPLErr IDADataset::SetProjection( const char *pszWKTIn )
 /* -------------------------------------------------------------------- */
 /*      Update header and mark it as dirty.                             */
 /* -------------------------------------------------------------------- */
-    bHeaderDirty = TRUE;
+    bHeaderDirty = true;
 
     abyHeader[23] = static_cast<GByte>( nProjection );
     c2tp( dfLatCenter, abyHeader + 120 );
@@ -561,7 +644,7 @@ void IDADataset::ReadColorTable()
 /*      Decide what .clr file to look for and try to open.              */
 /* -------------------------------------------------------------------- */
     CPLString osCLRFilename = CPLGetConfigOption( "IDA_COLOR_FILE", "" );
-    if( strlen(osCLRFilename) == 0 )
+    if( osCLRFilename.empty() )
         osCLRFilename = CPLResetExtension(GetDescription(), "clr" );
 
     VSILFILE *fp = VSIFOpenL( osCLRFilename, "r" );
@@ -610,40 +693,40 @@ void IDADataset::ReadColorTable()
             poRAT->SetValue( iRow, 3, atoi(papszTokens[3]) );
             poRAT->SetValue( iRow, 4, atoi(papszTokens[4]) );
 
-            // find name, first nonspace after 5th token.
+            // Find name, first nonspace after 5th token.
             const char *pszName = pszLine;
 
-            // skip from
+            // Skip from.
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
             while( *pszName != ' ' && *pszName != '\t' && *pszName != '\0' )
                 pszName++;
 
-            // skip to
+            // Skip to.
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
             while( *pszName != ' ' && *pszName != '\t' && *pszName != '\0' )
                 pszName++;
 
-            // skip red
+            // Skip red.
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
             while( *pszName != ' ' && *pszName != '\t' && *pszName != '\0' )
                 pszName++;
 
-            // skip green
+            // Skip green.
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
             while( *pszName != ' ' && *pszName != '\t' && *pszName != '\0' )
                 pszName++;
 
-            // skip blue
+            // Skip blue.
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
             while( *pszName != ' ' && *pszName != '\t' && *pszName != '\0' )
                 pszName++;
 
-            // skip pre-name white space
+            // Skip pre-name white space.
             while( *pszName == ' ' || *pszName == '\t' )
                 pszName++;
 
@@ -686,11 +769,11 @@ GDALDataset *IDADataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 512 )
         return NULL;
 
-    // projection legal?
+    // Projection legal?
     if( poOpenInfo->pabyHeader[23] > 10 )
         return NULL;
 
-    // imagetype legal?
+    // Image type legal?
     if( (poOpenInfo->pabyHeader[22] > 14
          && poOpenInfo->pabyHeader[22] < 100)
         || (poOpenInfo->pabyHeader[22] > 114
@@ -706,7 +789,8 @@ GDALDataset *IDADataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
 
     // The file just be exactly the image size + header size in length.
-    vsi_l_offset nExpectedFileSize = static_cast<vsi_l_offset>(nXSize) * nYSize + 512;
+    const vsi_l_offset nExpectedFileSize =
+        static_cast<vsi_l_offset>(nXSize) * nYSize + 512;
 
     CPL_IGNORE_RET_VAL(VSIFSeekL( poOpenInfo->fpL, 0, SEEK_END ));
     const vsi_l_offset nActualFileSize = VSIFTellL( poOpenInfo->fpL );
@@ -733,7 +817,9 @@ GDALDataset *IDADataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterXSize = poOpenInfo->pabyHeader[32]
         + poOpenInfo->pabyHeader[33] * 256;
 
-    strncpy( poDS->szTitle, (const char *) poOpenInfo->pabyHeader+38, 80 );
+    strncpy( poDS->szTitle,
+             reinterpret_cast<char *>( poOpenInfo->pabyHeader+38 ),
+             80 );
     poDS->szTitle[80] = '\0';
 
     int nLastTitleChar = static_cast<int>(strlen(poDS->szTitle))-1;
@@ -760,25 +846,8 @@ GDALDataset *IDADataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Handle various image types.                                     */
 /* -------------------------------------------------------------------- */
 
-/*
-GENERIC = 0
-FEW S NDVI = 1
-EROS NDVI = 6
-ARTEMIS CUTOFF = 10
-ARTEMIS RECODE = 11
-ARTEMIS NDVI = 12
-ARTEMIS FEWS = 13
-ARTEMIS NEWNASA = 14
-GENERIC DIFF = 100
-FEW S NDVI DIFF = 101
-EROS NDVI DIFF = 106
-ARTEMIS CUTOFF DIFF = 110
-ARTEMIS RECODE DIFF = 111
-ARTEMIS NDVI DIFF = 112
-ARTEMIS FEWS DIFF = 113
-ARTEMIS NEWNASA DIFF = 114
-CALCULATED =200
-*/
+// GENERIC = 0
+// GENERIC DIFF = 100
 
     poDS->nMissing = 0;
 
@@ -837,7 +906,7 @@ CALCULATED =200
         poDS->nMissing = 0;
         break;
 
-      case 106: /* EROS_DIFF */
+      case 106: /* EROS_DIFF NDVI? */
         poDS->dfM = 1/50.0;
         poDS->dfB = -128/50.0;
         poDS->nMissing = 0;
@@ -874,7 +943,8 @@ CALCULATED =200
         break;
 
       case 200:
-        /* we use the values from the header */
+        // Calculated.
+        // We use the values from the header.
         poDS->dfM = tp2c( poOpenInfo->pabyHeader + 171 );
         poDS->dfB = tp2c( poOpenInfo->pabyHeader + 177 );
         poDS->nMissing = poOpenInfo->pabyHeader[170];
@@ -926,77 +996,7 @@ CALCULATED =200
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
-}
-
-/************************************************************************/
-/*                                tp2c()                                */
-/*                                                                      */
-/*      convert a Turbo Pascal real into a double                       */
-/************************************************************************/
-
-static double tp2c(GByte *r)
-{
-  // handle 0 case
-  if (r[0] == 0)
-    return 0.0;
-
-  // extract sign: bit 7 of byte 5
-  const int sign = r[5] & 0x80 ? -1 : 1;
-
-  // extract mantissa from first bit of byte 1 to bit 7 of byte 5
-  double mant = 0.0;
-  for ( int i = 1; i < 5; i++ )
-    mant = (r[i] + mant) / 256;
-  mant = (mant + (r[5] & 0x7F)) / 128 + 1;
-
-   // extract exponent
-  const int exp = r[0] - 129;
-
-  // compute the damned number
-  return sign * ldexp(mant, exp);
-}
-
-/************************************************************************/
-/*                                c2tp()                                */
-/*                                                                      */
-/*      convert a double into a Turbo Pascal real                       */
-/************************************************************************/
-
-static void c2tp(double x, GByte *r)
-{
-  // handle 0 case
-  if (x == 0.0)
-  {
-    for (int i = 0; i < 6; r[i++] = 0);
-    return;
-  }
-
-  // compute mantissa, sign and exponent
-  int exp;
-  double mant = frexp(x, &exp) * 2 - 1;
-  exp--;
-  int negative = 0;
-  if (mant < 0)
-  {
-    mant = -mant;
-    negative = 1;
-  }
-  // stuff mantissa into Turbo Pascal real
-  double temp;
-  mant = modf(mant * 128, &temp);
-  r[5] = static_cast<unsigned char>( static_cast<int>(temp) & 0xff);
-  for ( int i = 4; i >= 1; i-- )
-  {
-    mant = modf(mant * 256, &temp);
-    r[i] = static_cast<unsigned char>( temp );
-  }
-  // add sign
-  if (negative)
-    r[5] |= 0x80;
-
-  // put exponent
-  r[0] = static_cast<GByte>( exp + 129 );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1035,22 +1035,21 @@ GDALDataset *IDADataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Prepare formatted header.                                       */
 /* -------------------------------------------------------------------- */
-    GByte abyHeader[512];
-    memset( abyHeader, 0, sizeof(abyHeader) );
-    abyHeader[22] = 200; /* image type - CALCULATED */
-    abyHeader[23] = 0; /* projection - NONE */
+    GByte abyHeader[512] = { 0 } ;
+    abyHeader[22] = 200;  // Image type - CALCULATED.
+    abyHeader[23] = 0;  // Projection - NONE.
     abyHeader[30] = nYSize % 256;
     abyHeader[31] = static_cast<GByte>( nYSize / 256 );
     abyHeader[32] = nXSize % 256;
     abyHeader[33] = static_cast<GByte>( nXSize / 256 );
 
-    abyHeader[170] = 255; /* missing = 255 */
-    c2tp( 1.0, abyHeader + 171 ); /* slope = 1.0 */
-    c2tp( 0.0, abyHeader + 177 ); /* offset = 0 */
-    abyHeader[168] = 0; // lower limit
-    abyHeader[169] = 254; // upper limit
+    abyHeader[170] = 255;  // Missing = 255
+    c2tp( 1.0, abyHeader + 171 );  // Slope = 1.0
+    c2tp( 0.0, abyHeader + 177 );  // Offset = 0
+    abyHeader[168] = 0;  // Lower limit.
+    abyHeader[169] = 254;  // Upper limit.
 
-    // pixel size = 1.0
+    // Pixel size = 1.0
     c2tp( 1.0, abyHeader + 144 );
     c2tp( 1.0, abyHeader + 150 );
 
@@ -1086,7 +1085,7 @@ GDALDataset *IDADataset::Create( const char * pszFilename,
         return NULL;
     }
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    return static_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
diff --git a/frmts/raw/iscedataset.cpp b/frmts/raw/iscedataset.cpp
index 5732fa1..74df692 100644
--- a/frmts/raw/iscedataset.cpp
+++ b/frmts/raw/iscedataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: iscedataset.cpp 35256 2016-08-30 13:48:26Z rouault $
  *
  * Project:  ISCE Raster Reader
  * Purpose:  Implementation of the ISCE raster reader
@@ -28,9 +27,10 @@
  ****************************************************************************/
 
 #include "gdal_frmts.h"
+#include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: iscedataset.cpp 35256 2016-08-30 13:48:26Z rouault $");
+CPL_CVSID("$Id: iscedataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 static const char * const apszISCE2GDALDatatypes[] = {
     "BYTE:Byte",
@@ -88,8 +88,8 @@ class ISCEDataset : public RawDataset
                 ISCEDataset();
     virtual ~ISCEDataset();
 
-    virtual void        FlushCache();
-    virtual char      **GetFileList();
+    virtual void        FlushCache() override;
+    virtual char      **GetFileList() override;
 
     static int          Identify( GDALOpenInfo *poOpenInfo );
     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
@@ -142,8 +142,9 @@ static CPLString getXMLFilename( GDALOpenInfo *poOpenInfo )
         const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
         const CPLString osName = CPLGetFilename( poOpenInfo->pszFilename );
 
-        int iFile = CSLFindString( papszSiblingFiles,
-                                   CPLFormFilename( NULL, osName, "xml" ) );
+        const int iFile =
+            CSLFindString( papszSiblingFiles,
+                           CPLFormFilename( NULL, osName, "xml" ) );
         if( iFile >= 0 )
         {
             osXMLFilename = CPLFormFilename( osPath,
@@ -163,7 +164,7 @@ ISCEDataset::ISCEDataset() :
     fpImage(NULL),
     pszXMLFilename(NULL),
     eScheme(BIL)
-{ }
+{}
 
 /************************************************************************/
 /*                            ~ISCEDataset()                          */
@@ -198,32 +199,33 @@ void ISCEDataset::FlushCache( void )
 /* -------------------------------------------------------------------- */
 /*      Recreate a XML doc with the dataset information.                */
 /* -------------------------------------------------------------------- */
-    char sBuf[64];
+    char sBuf[64] = { '\0' };
     CPLXMLNode *psDocNode = CPLCreateXMLNode( NULL, CXT_Element, "imageFile" );
 
     CPLXMLNode *psTmpNode
         = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
     CPLAddXMLAttributeAndValue( psTmpNode, "name", "WIDTH" );
-    snprintf(sBuf, sizeof(sBuf), "%d", nRasterXSize);
+    CPLsnprintf(sBuf, sizeof(sBuf), "%d", nRasterXSize);
     CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
 
     psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
     CPLAddXMLAttributeAndValue( psTmpNode, "name", "LENGTH" );
-    snprintf(sBuf, sizeof(sBuf), "%d", nRasterYSize);
+    CPLsnprintf(sBuf, sizeof(sBuf), "%d", nRasterYSize);
     CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
 
     psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
     CPLAddXMLAttributeAndValue( psTmpNode, "name", "NUMBER_BANDS" );
-    snprintf(sBuf, sizeof(sBuf), "%d", nBands);
+    CPLsnprintf(sBuf, sizeof(sBuf), "%d", nBands);
     CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
 
     const char *sType = GDALGetDataTypeName( band->GetRasterDataType() );
     psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
     CPLAddXMLAttributeAndValue( psTmpNode, "name", "DATA_TYPE" );
-    CPLCreateXMLElementAndValue( psTmpNode, "value",
-                                 CSLFetchNameValue(
-                                         (char **)apszGDAL2ISCEDatatypes,
-                                         sType ) );
+    CPLCreateXMLElementAndValue(
+        psTmpNode, "value",
+        CSLFetchNameValue(
+            const_cast<char **>(apszGDAL2ISCEDatatypes),
+            sType ) );
 
     const char *sScheme = apszSchemeNames[eScheme];
     psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
@@ -238,6 +240,15 @@ void ISCEDataset::FlushCache( void )
     CPLCreateXMLElementAndValue( psTmpNode, "value", "b" );
 #endif
 
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "ACCESS_MODE" );
+    CPLCreateXMLElementAndValue( psTmpNode, "value", "read" );
+
+    const char *pszFilename = CPLGetBasename( pszXMLFilename );
+    psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "FILE_NAME" );
+    CPLCreateXMLElementAndValue( psTmpNode, "value", pszFilename );
+
 /* -------------------------------------------------------------------- */
 /*      Then, add the ISCE domain metadata.                             */
 /* -------------------------------------------------------------------- */
@@ -253,7 +264,7 @@ void ISCEDataset::FlushCache( void )
         {
             CPLDebug( "ISCE",
                       "Line of header file could not be split at = into two"
-                          " elements: %s",
+                      " elements: %s",
                       papszISCEMetadata[i] );
             CSLDestroy( papszTokens );
             continue;
@@ -280,6 +291,137 @@ void ISCEDataset::FlushCache( void )
     }
 
 /* -------------------------------------------------------------------- */
+/*      Create the "Coordinate" component elements, possibly with       */
+/*      georeferencing.                                                 */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psCoordinate1Node, *psCoordinate2Node;
+    double adfGeoTransform[6];
+
+    /* Coordinate 1 */
+    psCoordinate1Node = CPLCreateXMLNode( psDocNode,
+                                          CXT_Element,
+                                          "component" );
+    CPLAddXMLAttributeAndValue( psCoordinate1Node, "name", "Coordinate1" );
+    CPLCreateXMLElementAndValue( psCoordinate1Node,
+                                 "factorymodule",
+                                 "isceobj.Image" );
+    CPLCreateXMLElementAndValue( psCoordinate1Node,
+                                 "factoryname",
+                                 "createCoordinate" );
+    CPLCreateXMLElementAndValue( psCoordinate1Node,
+                                 "doc",
+                                 "First coordinate of a 2D image (witdh)." );
+    /* Property name */
+    psTmpNode = CPLCreateXMLNode( psCoordinate1Node,
+                                  CXT_Element,
+                                  "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "name" );
+    CPLCreateXMLElementAndValue( psTmpNode,
+                                 "value",
+                                 "ImageCoordinate_name" );
+    /* Property family */
+    psTmpNode = CPLCreateXMLNode( psCoordinate1Node,
+                                  CXT_Element,
+                                  "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "family" );
+    CPLCreateXMLElementAndValue( psTmpNode,
+                                 "value",
+                                 "ImageCoordinate" );
+    /* Property size */
+    CPLsnprintf(sBuf, sizeof(sBuf), "%d", nRasterXSize);
+    psTmpNode = CPLCreateXMLNode( psCoordinate1Node,
+                                  CXT_Element,
+                                  "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "size" );
+    CPLCreateXMLElementAndValue( psTmpNode,
+                                 "value",
+                                 sBuf );
+
+    /* Coordinate 2 */
+    psCoordinate2Node = CPLCreateXMLNode( psDocNode,
+                                          CXT_Element,
+                                          "component" );
+    CPLAddXMLAttributeAndValue( psCoordinate2Node, "name", "Coordinate2" );
+    CPLCreateXMLElementAndValue( psCoordinate2Node,
+                                 "factorymodule",
+                                 "isceobj.Image" );
+    CPLCreateXMLElementAndValue( psCoordinate2Node,
+                                 "factoryname",
+                                 "createCoordinate" );
+    /* Property name */
+    psTmpNode = CPLCreateXMLNode( psCoordinate2Node,
+                                  CXT_Element,
+                                  "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "name" );
+    CPLCreateXMLElementAndValue( psTmpNode,
+                                 "value",
+                                 "ImageCoordinate_name" );
+    /* Property family */
+    psTmpNode = CPLCreateXMLNode( psCoordinate2Node,
+                                  CXT_Element,
+                                  "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "family" );
+    CPLCreateXMLElementAndValue( psTmpNode,
+                                 "value",
+                                 "ImageCoordinate" );
+    /* Property size */
+    CPLsnprintf(sBuf, sizeof(sBuf), "%d", nRasterYSize);
+    psTmpNode = CPLCreateXMLNode( psCoordinate2Node,
+                                  CXT_Element,
+                                  "property" );
+    CPLAddXMLAttributeAndValue( psTmpNode, "name", "size" );
+    CPLCreateXMLElementAndValue( psTmpNode,
+                                 "value",
+                                 sBuf );
+
+    if ( GetGeoTransform( adfGeoTransform ) == CE_None )
+    {
+        if ( adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0 )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "ISCE format do not support geotransform with "
+                          "rotation, discarding info.");
+        }
+        else {
+            CPLsnprintf( sBuf, sizeof(sBuf), "%g", adfGeoTransform[0] );
+            psTmpNode = CPLCreateXMLNode( psCoordinate1Node,
+                                          CXT_Element,
+                                          "property" );
+            CPLAddXMLAttributeAndValue( psTmpNode, "name", "startingValue" );
+            CPLCreateXMLElementAndValue( psTmpNode,
+                                         "value",
+                                         sBuf );
+
+            CPLsnprintf( sBuf, sizeof(sBuf), "%g", adfGeoTransform[1] );
+            psTmpNode = CPLCreateXMLNode( psCoordinate1Node,
+                                          CXT_Element,
+                                          "property" );
+            CPLAddXMLAttributeAndValue( psTmpNode, "name", "delta" );
+            CPLCreateXMLElementAndValue( psTmpNode,
+                                         "value",
+                                         sBuf );
+
+            CPLsnprintf( sBuf, sizeof(sBuf), "%g", adfGeoTransform[3] );
+            psTmpNode = CPLCreateXMLNode( psCoordinate2Node,
+                                          CXT_Element,
+                                          "property" );
+            CPLAddXMLAttributeAndValue( psTmpNode, "name", "startingValue" );
+            CPLCreateXMLElementAndValue( psTmpNode,
+                                         "value",
+                                         sBuf );
+
+            CPLsnprintf( sBuf, sizeof(sBuf), "%g", adfGeoTransform[5] );
+            psTmpNode = CPLCreateXMLNode( psCoordinate2Node,
+                                          CXT_Element,
+                                          "property" );
+            CPLAddXMLAttributeAndValue( psTmpNode, "name", "delta" );
+            CPLCreateXMLElementAndValue( psTmpNode,
+                                         "value",
+                                         sBuf );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Write the XML file.                                             */
 /* -------------------------------------------------------------------- */
     CPLSerializeXMLTreeToFile( psDocNode, pszXMLFilename );
@@ -314,7 +456,6 @@ int ISCEDataset::Identify( GDALOpenInfo *poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      TODO: This function is unusable now:                            */
 /*          * we can't just check for the presence of a XML file        */
-/*            the presence of a XML file                                */
 /*          * we cannot parse it to check basic tree (Identify() is     */
 /*            supposed to be faster than this                           */
 /*          * we could read only a few bytes and strstr() for           */
@@ -360,19 +501,73 @@ GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
     }
     CPLXMLNode *psCur  = CPLGetXMLNode( psNode, "=imageFile" )->psChild;
     char **papszXmlProps = NULL;
-    while ( psCur != NULL ) {
-        const char *name, *value;
-        if ( ! EQUAL(psCur->pszValue, "property") ) {
-            psCur = psCur->psNext;
-            continue;
+    while ( psCur != NULL )
+    {
+        if ( EQUAL( psCur->pszValue, "property" ) )
+        {
+            /* Top-level property */
+            const char *pszName = CPLGetXMLValue( psCur, "name", NULL );
+            const char *pszValue = CPLGetXMLValue( psCur, "value", NULL );
+            if ( pszName != NULL && pszValue != NULL)
+            {
+                papszXmlProps = CSLSetNameValue( papszXmlProps,
+                                                 pszName, pszValue );
+            }
+        }
+        else if ( EQUAL( psCur->pszValue, "component" ) )
+        {
+            /* "components" elements in ISCE store set of properties.   */
+            /* For now, they are avoided as I am not sure the full      */
+            /* scope of these. An exception is made for the ones named  */
+            /* Coordinate1 and Coordinate2, because they may have the   */
+            /* georeferencing information.                              */
+            const char *pszCurName = CPLGetXMLValue( psCur, "name", NULL );
+            if ( pszCurName != NULL
+                && ( EQUAL( pszCurName, "Coordinate1" )
+                    || EQUAL( pszCurName, "Coordinate2" ) ) )
+            {
+                /* We need two subproperties: startingValue and delta.  */
+                /* To simplify parsing code, we will store them in      */
+                /* papszXmlProps with the coordinate name prefixed to   */
+                /* the property name.                                   */
+                CPLXMLNode *psCur2 = psCur->psChild;
+                while ( psCur2 != NULL )
+                {
+                    if ( ! EQUAL( psCur2->pszValue, "property" ) )
+                    {
+                        psCur2 = psCur2->psNext;
+                        continue; /* Skip non property elements */
+                    }
+
+                    const char
+                       *pszCur2Name = CPLGetXMLValue( psCur2, "name", NULL ),
+                       *pszCur2Value = CPLGetXMLValue( psCur2, "value", NULL );
+
+                    if ( pszCur2Name == NULL || pszCur2Value == NULL )
+                    {
+                        psCur2 = psCur2->psNext;
+                        continue; /* Skip malformatted elements */
+                    }
+
+                    if ( EQUAL( pszCur2Name, "startingValue" )
+                        || EQUAL( pszCur2Name, "delta" ) )
+                    {
+                        char szPropName[32];
+                        snprintf(szPropName, sizeof(szPropName), "%s%s",
+                                 pszCurName, pszCur2Name);
+
+                        papszXmlProps =
+                            CSLSetNameValue( papszXmlProps,
+                                             szPropName,
+                                             pszCur2Value );
+                    }
+                    psCur2 = psCur2->psNext;
+                }
+            }
         }
-        name = CPLGetXMLValue( psCur, "name", NULL );
-        value = CPLGetXMLValue( psCur, "value.", NULL );
-        papszXmlProps = CSLSetNameValue( papszXmlProps,
-                                         name, value );
         psCur = psCur->psNext;
     }
-    /* TODO: extract <component name=Coordinate[12]> for georeferencing */
+
     CPLDestroyXMLNode( psNode );
 
 /* -------------------------------------------------------------------- */
@@ -441,23 +636,25 @@ GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
     const char *sDataType =
-        CSLFetchNameValue( (char **)apszISCE2GDALDatatypes,
+        CSLFetchNameValue( const_cast<char **>(apszISCE2GDALDatatypes),
                            CSLFetchNameValue( papszXmlProps, "DATA_TYPE" ) );
     const GDALDataType eDataType = GDALGetDataTypeByName( sDataType );
     const int nBands = atoi( CSLFetchNameValue( papszXmlProps, "NUMBER_BANDS" ) );
     const char *sScheme = CSLFetchNameValue( papszXmlProps, "SCHEME" );
-    int nPixelOffset, nLineOffset, nBandOffset;
-    if ( EQUAL( sScheme, "BIL" ) )
+    int nPixelOffset = 0;
+    int nLineOffset = 0;
+    int nBandOffset = 0;
+    if( EQUAL( sScheme, "BIL" ) )
     {
-                poDS->eScheme = BIL;
-        nPixelOffset = GDALGetDataTypeSize(eDataType)/8;
+        poDS->eScheme = BIL;
+        nPixelOffset = GDALGetDataTypeSizeBytes(eDataType);
         nLineOffset = nPixelOffset * nWidth * nBands;
-        nBandOffset = GDALGetDataTypeSize(eDataType)/8 * nWidth;
+        nBandOffset = GDALGetDataTypeSizeBytes(eDataType) * nWidth;
     }
-    else if ( EQUAL( sScheme, "BIP" ) )
+    else if( EQUAL( sScheme, "BIP" ) )
     {
         poDS->eScheme = BIP;
-        nPixelOffset = GDALGetDataTypeSize(eDataType)/8 * nBands;
+        nPixelOffset = GDALGetDataTypeSizeBytes(eDataType) * nBands;
         nLineOffset = nPixelOffset * nWidth;
         if( nBands > 1 )
         {
@@ -475,12 +672,12 @@ GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
                 nLineOffset = nLineOffset * nBands;
             }
         }
-        nBandOffset = GDALGetDataTypeSize(eDataType)/8;
+        nBandOffset = GDALGetDataTypeSizeBytes(eDataType);
     }
     else if ( EQUAL( sScheme, "BSQ" ) )
     {
         poDS->eScheme = BSQ;
-        nPixelOffset = GDALGetDataTypeSize(eDataType)/8;
+        nPixelOffset = GDALGetDataTypeSizeBytes(eDataType);
         nLineOffset = nPixelOffset * nWidth;
         nBandOffset = nLineOffset * nFileLength;
     }
@@ -489,7 +686,7 @@ GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
         CSLDestroy( papszXmlProps );
         delete poDS;
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unknown scheme \"%s\" within ISCE raster.\n",
+                  "Unknown scheme \"%s\" within ISCE raster.",
                   CSLFetchNameValue( papszXmlProps, "SCHEME" ) );
         return NULL;
     }
@@ -498,33 +695,58 @@ GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
     {
         poDS->SetBand( b + 1,
                        new ISCERasterBand( poDS, b + 1, poDS->fpImage,
-                                             nBandOffset * b,
-                                             nPixelOffset, nLineOffset,
-                                             eDataType, TRUE,
-                                             bNativeOrder, FALSE ) );
+                                           nBandOffset * b,
+                                           nPixelOffset, nLineOffset,
+                                           eDataType, bNativeOrder,
+                                           TRUE, FALSE ) );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Interpret georeferencing, if present.                           */
 /* -------------------------------------------------------------------- */
-   /* TODO */
+    if ( CSLFetchNameValue( papszXmlProps, "Coordinate1startingValue" ) != NULL
+         && CSLFetchNameValue( papszXmlProps, "Coordinate1delta" ) != NULL
+         && CSLFetchNameValue( papszXmlProps, "Coordinate2startingValue" ) != NULL
+         && CSLFetchNameValue( papszXmlProps, "Coordinate2delta" ) != NULL )
+    {
+        double adfGeoTransform[6];
+        adfGeoTransform[0] = CPLAtof( CSLFetchNameValue( papszXmlProps,
+                                                         "Coordinate1startingValue" ) );
+        adfGeoTransform[1] = CPLAtof( CSLFetchNameValue( papszXmlProps,
+                                                         "Coordinate1delta" ) );
+        adfGeoTransform[2] = 0.0;
+        adfGeoTransform[3] = CPLAtof( CSLFetchNameValue( papszXmlProps,
+                                                         "Coordinate2startingValue" ) );
+        adfGeoTransform[4] = 0.0;
+        adfGeoTransform[5] = CPLAtof( CSLFetchNameValue( papszXmlProps,
+                                                               "Coordinate2delta" ) );
+        poDS->SetGeoTransform( adfGeoTransform );
+
+        /* ISCE format seems not to have a projection field, but uses   */
+        /* WGS84.                                                       */
+        poDS->SetProjection( SRS_WKT_WGS84 );
+    }
 
 /* -------------------------------------------------------------------- */
-/*      Set all the other header metadata into the ISCE domain       */
+/*      Set all the other header metadata into the ISCE domain          */
 /* -------------------------------------------------------------------- */
-    for (int i = 0; papszXmlProps != NULL && papszXmlProps[i] != NULL; i++)
+    for( int i = 0; papszXmlProps != NULL && papszXmlProps[i] != NULL; i++ )
     {
-        char **papszTokens;
-        papszTokens = CSLTokenizeString2( papszXmlProps[i],
-                                          "=",
-                                          CSLT_STRIPLEADSPACES
-                                            | CSLT_STRIPENDSPACES);
+        char **papszTokens =
+            CSLTokenizeString2( papszXmlProps[i],
+                                "=",
+                                CSLT_STRIPLEADSPACES
+                                | CSLT_STRIPENDSPACES);
         if ( EQUAL( papszTokens[0], "WIDTH" )
               || EQUAL( papszTokens[0], "LENGTH" )
               || EQUAL( papszTokens[0], "NUMBER_BANDS" )
               || EQUAL( papszTokens[0], "DATA_TYPE" )
               || EQUAL( papszTokens[0], "SCHEME" )
-              || EQUAL( papszTokens[0], "BYTE_ORDER" ) )
+              || EQUAL( papszTokens[0], "BYTE_ORDER" )
+              || EQUAL( papszTokens[0], "Coordinate1startingValue" )
+              || EQUAL( papszTokens[0], "Coordinate1delta" )
+              || EQUAL( papszTokens[0], "Coordinate2startingValue" )
+              || EQUAL( papszTokens[0], "Coordinate2delta" ) )
         {
             CSLDestroy( papszTokens );
             continue;
@@ -549,7 +771,7 @@ GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -557,9 +779,9 @@ GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
 /************************************************************************/
 
 GDALDataset *ISCEDataset::Create( const char *pszFilename,
-                                    int nXSize, int nYSize, int nBands,
-                                    GDALDataType eType,
-                                    char **papszOptions )
+                                  int nXSize, int nYSize, int nBands,
+                                  GDALDataType eType,
+                                  char **papszOptions )
 {
     const char *sType = GDALGetDataTypeName( eType );
     const char *sScheme = CSLFetchNameValueDef( papszOptions,
@@ -573,7 +795,7 @@ GDALDataset *ISCEDataset::Create( const char *pszFilename,
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
+                  "Attempt to create file `%s' failed.",
                   pszFilename );
         return NULL;
     }
@@ -582,7 +804,7 @@ GDALDataset *ISCEDataset::Create( const char *pszFilename,
 /*      Just write out a couple of bytes to establish the binary        */
 /*      file, and then close it.                                        */
 /* -------------------------------------------------------------------- */
-    CPL_IGNORE_RET_VAL(VSIFWriteL( (void *) "\0\0", 2, 1, fp ));
+    CPL_IGNORE_RET_VAL(VSIFWriteL( "\0\0", 2, 1, fp ));
     CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
@@ -593,26 +815,27 @@ GDALDataset *ISCEDataset::Create( const char *pszFilename,
     CPLXMLNode *psTmpNode
         = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
     CPLAddXMLAttributeAndValue( psTmpNode, "name", "WIDTH" );
-    char sBuf[64];
-    snprintf(sBuf, sizeof(sBuf), "%d", nXSize);
+    char sBuf[64] = { '\0' };
+    CPLsnprintf(sBuf, sizeof(sBuf), "%d", nXSize);
     CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
 
     psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
     CPLAddXMLAttributeAndValue( psTmpNode, "name", "LENGTH" );
-    snprintf(sBuf, sizeof(sBuf), "%d", nYSize);
+    CPLsnprintf(sBuf, sizeof(sBuf), "%d", nYSize);
     CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
 
     psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
     CPLAddXMLAttributeAndValue( psTmpNode, "name", "NUMBER_BANDS" );
-    snprintf(sBuf, sizeof(sBuf), "%d", nBands);
+    CPLsnprintf(sBuf, sizeof(sBuf), "%d", nBands);
     CPLCreateXMLElementAndValue( psTmpNode, "value", sBuf );
 
     psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
     CPLAddXMLAttributeAndValue( psTmpNode, "name", "DATA_TYPE" );
-    CPLCreateXMLElementAndValue( psTmpNode, "value",
-                                 CSLFetchNameValue(
-                                         (char **)apszGDAL2ISCEDatatypes,
-                                         sType ));
+    CPLCreateXMLElementAndValue(
+        psTmpNode, "value",
+        CSLFetchNameValue(
+            const_cast<char **>(apszGDAL2ISCEDatatypes),
+            sType ));
 
     psTmpNode = CPLCreateXMLNode( psDocNode, CXT_Element, "property" );
     CPLAddXMLAttributeAndValue( psTmpNode, "name", "SCHEME" );
@@ -637,7 +860,7 @@ GDALDataset *ISCEDataset::Create( const char *pszFilename,
 /* -------------------------------------------------------------------- */
     CPLDestroyXMLNode( psDocNode );
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    return static_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
@@ -645,14 +868,14 @@ GDALDataset *ISCEDataset::Create( const char *pszFilename,
 /************************************************************************/
 
 ISCERasterBand::ISCERasterBand( GDALDataset *poDSIn, int nBandIn, void *fpRawIn,
-                                    vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
-                                    int nLineOffsetIn,
-                                    GDALDataType eDataTypeIn, int bNativeOrderIn,
-                                    int bIsVSILIn, int bOwnsFPIn ) :
-        RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
-                      nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn, bOwnsFPIn)
-{
-}
+                                vsi_l_offset nImgOffsetIn, int nPixelOffsetIn,
+                                int nLineOffsetIn,
+                                GDALDataType eDataTypeIn, int bNativeOrderIn,
+                                int bIsVSILIn, int bOwnsFPIn ) :
+    RawRasterBand( poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                   nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn,
+                   bOwnsFPIn )
+{}
 
 /************************************************************************/
 /*                         GDALRegister_ISCE()                          */
@@ -676,13 +899,13 @@ void GDALRegister_ISCE()
                                " Float64 CInt16 CInt64 CFloat32 "
                                " CFloat64" );
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-"<CreationOptionList>"
-"   <Option name='SCHEME' type='string-select'>"
-"       <Value>BIP</Value>"
-"       <Value>BIL</Value>"
-"       <Value>BSQ</Value>"
-"   </Option>"
-"</CreationOptionList>" );
+                               "<CreationOptionList>"
+                               "   <Option name='SCHEME' type='string-select'>"
+                               "       <Value>BIP</Value>"
+                               "       <Value>BIL</Value>"
+                               "       <Value>BSQ</Value>"
+                               "   </Option>"
+                               "</CreationOptionList>" );
     poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
diff --git a/frmts/raw/krodataset.cpp b/frmts/raw/krodataset.cpp
index 933795e..6911509 100644
--- a/frmts/raw/krodataset.cpp
+++ b/frmts/raw/krodataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: krodataset.cpp 33862 2016-04-02 11:17:23Z goatbar $
  *
  * Project:  KRO format reader/writer
  * Purpose:  Implementation of KOLOR Raw Format
@@ -32,9 +31,9 @@
 #include "gdal_frmts.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: krodataset.cpp 33862 2016-04-02 11:17:23Z goatbar $");
+CPL_CVSID("$Id: krodataset.cpp 34642 2016-07-12 13:05:02Z goatbar $");
 
-/* http://www.autopano.net/wiki-en/Format_KRO */
+// http://www.autopano.net/wiki-en/Format_KRO
 
 /************************************************************************/
 /* ==================================================================== */
@@ -77,7 +76,7 @@ KRODataset::~KRODataset()
     {
         if( VSIFCloseL( fpImage ) != 0 )
         {
-            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+          CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
         }
     }
 }
@@ -92,7 +91,8 @@ int KRODataset::Identify( GDALOpenInfo *poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 20 )
         return FALSE;
 
-    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "KRO\x01") )
+    if( !STARTS_WITH_CI( reinterpret_cast<char *>(poOpenInfo->pabyHeader),
+                         "KRO\x01") )
         return FALSE;
 
     return TRUE;
@@ -131,27 +131,27 @@ GDALDataset *KRODataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Read the file header.                                           */
 /* -------------------------------------------------------------------- */
-    char  achHeader[20];
+    char achHeader[20] = { '\0' };
     CPL_IGNORE_RET_VAL(VSIFReadL( achHeader, 1, 20, poDS->fpImage ));
 
     int nXSize;
     memcpy(&nXSize, achHeader + 4, 4);
     CPL_MSBPTR32( &nXSize );
 
-    int nYSize;
+    int nYSize = 0;
     memcpy(&nYSize, achHeader + 8, 4);
     CPL_MSBPTR32( &nYSize );
 
-    int nDepth;
+    int nDepth = 0;
     memcpy(&nDepth, achHeader + 12, 4);
     CPL_MSBPTR32( &nDepth );
 
-    int nComp;
+    int nComp = 0;
     memcpy(&nComp, achHeader + 16, 4);
     CPL_MSBPTR32( &nComp );
 
-    if (!GDALCheckDatasetDimensions(nXSize, nYSize) ||
-        !GDALCheckBandCount(nComp, FALSE))
+    if( !GDALCheckDatasetDimensions(nXSize, nYSize) ||
+        !GDALCheckBandCount(nComp, FALSE) )
     {
         delete poDS;
         return NULL;
@@ -160,17 +160,23 @@ GDALDataset *KRODataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->nRasterXSize = nXSize;
     poDS->nRasterYSize = nYSize;
 
-    GDALDataType eDT;
+    GDALDataType eDT = GDT_Unknown;
     if( nDepth == 8 )
+    {
         eDT = GDT_Byte;
+    }
     else if( nDepth == 16 )
+    {
         eDT = GDT_UInt16;
+    }
     else if( nDepth == 32 )
+    {
         eDT = GDT_Float32;
+    }
     else
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Unhandled depth : %d", nDepth);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unhandled depth : %d", nDepth );
         delete poDS;
         return NULL;
     }
@@ -180,8 +186,8 @@ GDALDataset *KRODataset::Open( GDALOpenInfo * poOpenInfo )
     if( nComp == 0 || nDataTypeSize == 0 ||
         poDS->nRasterXSize > INT_MAX / (nComp * nDataTypeSize) )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Too large width / number of bands");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Too large width / number of bands" );
         delete poDS;
         return NULL;
     }
@@ -224,7 +230,7 @@ GDALDataset *KRODataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -236,13 +242,13 @@ GDALDataset *KRODataset::Create( const char * pszFilename,
                                  int nYSize,
                                  int nBands,
                                  GDALDataType eType,
-                                 CPL_UNUSED char ** papszOptions )
+                                 char ** /* papszOptions */ )
 {
     if( eType != GDT_Byte && eType != GDT_UInt16 && eType != GDT_Float32 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Attempt to create KRO file with unsupported data type '%s'.",
-                 GDALGetDataTypeName( eType ) );
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to create KRO file with unsupported data type '%s'.",
+                  GDALGetDataTypeName( eType ) );
         return NULL;
     }
 
@@ -253,7 +259,7 @@ GDALDataset *KRODataset::Create( const char * pszFilename,
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
+                  "Attempt to create file `%s' failed.",
                   pszFilename );
         return NULL;
     }
@@ -271,7 +277,7 @@ GDALDataset *KRODataset::Create( const char * pszFilename,
     CPL_MSBPTR32(&nTmp);
     nRet += VSIFWriteL(&nTmp, 4, 1, fp);
 
-    nTmp = GDALGetDataTypeSize(eType);
+    nTmp = GDALGetDataTypeSizeBits(eType);
     CPL_MSBPTR32(&nTmp);
     nRet += VSIFWriteL(&nTmp, 4, 1, fp);
 
@@ -283,20 +289,24 @@ GDALDataset *KRODataset::Create( const char * pszFilename,
 /*      Zero out image data                                             */
 /* -------------------------------------------------------------------- */
 
-    CPL_IGNORE_RET_VAL(VSIFSeekL(fp, (vsi_l_offset)nXSize * nYSize * (GDALGetDataTypeSize(eType) / 8) * nBands - 1,
+    CPL_IGNORE_RET_VAL(
+        VSIFSeekL( fp,
+                   static_cast<vsi_l_offset>(nXSize) * nYSize *
+                   GDALGetDataTypeSizeBytes(eType) * nBands - 1,
               SEEK_CUR));
     GByte byNul = 0;
     nRet += VSIFWriteL(&byNul, 1, 1, fp);
     if( VSIFCloseL(fp) != 0 )
     {
-        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
         return NULL;
     }
 
     if( nRet != 6 )
         return NULL;
 
-    return reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
+    return
+        reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
diff --git a/frmts/raw/landataset.cpp b/frmts/raw/landataset.cpp
index bbc87ba..b63a12f 100644
--- a/frmts/raw/landataset.cpp
+++ b/frmts/raw/landataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: landataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  eCognition
  * Purpose:  Implementation of Erdas .LAN / .GIS format.
@@ -37,8 +36,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: landataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
-
+CPL_CVSID("$Id: landataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 /**
 
@@ -118,12 +116,12 @@ class LAN4BitRasterBand : public GDALPamRasterBand
                    LAN4BitRasterBand( LANDataset *, int );
     virtual ~LAN4BitRasterBand();
 
-    virtual GDALColorTable *GetColorTable();
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr SetColorTable( GDALColorTable * );
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
+    virtual GDALColorTable *GetColorTable() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual CPLErr SetColorTable( GDALColorTable * ) override;
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) override;
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
@@ -135,7 +133,7 @@ class LAN4BitRasterBand : public GDALPamRasterBand
 class LANDataset : public RawDataset
 {
   public:
-    VSILFILE    *fpImage;  // image data file.
+    VSILFILE    *fpImage;  // Image data file.
 
     char        pachHeader[ERD_HEADER_SIZE];
 
@@ -146,16 +144,16 @@ class LANDataset : public RawDataset
     CPLString   osSTAFilename;
     void        CheckForStatistics(void);
 
-    virtual char **GetFileList();
+    virtual char **GetFileList() override;
 
   public:
                 LANDataset();
     virtual ~LANDataset();
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual CPLErr SetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef();
-    virtual CPLErr SetProjection( const char * );
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr SetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr SetProjection( const char * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
@@ -181,7 +179,7 @@ LAN4BitRasterBand::LAN4BitRasterBand( LANDataset *poDSIn, int nBandIn ) :
     nBand = nBandIn;
     eDataType = GDT_Byte;
 
-    nBlockXSize = poDSIn->GetRasterXSize();;
+    nBlockXSize = poDSIn->GetRasterXSize();
     nBlockYSize = 1;
 }
 
@@ -213,8 +211,9 @@ CPLErr LAN4BitRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
     const vsi_l_offset nOffset =
         ERD_HEADER_SIZE
-        + (static_cast<vsi_l_offset>(nBlockYOff) * nRasterXSize * poLAN_DS->GetRasterCount()) / 2
-        + (static_cast<vsi_l_offset>(nBand - 1) * nRasterXSize) / 2;
+        + ( static_cast<vsi_l_offset>(nBlockYOff) * nRasterXSize *
+           poLAN_DS->GetRasterCount() ) / 2
+        + ( static_cast<vsi_l_offset>(nBand - 1) * nRasterXSize ) / 2;
 
     if( VSIFSeekL( poLAN_DS->fpImage, nOffset, SEEK_SET ) != 0 )
     {
@@ -226,8 +225,8 @@ CPLErr LAN4BitRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 /* -------------------------------------------------------------------- */
 /*      Read the profile.                                               */
 /* -------------------------------------------------------------------- */
-    if( VSIFReadL( pImage, 1, nRasterXSize/2, poLAN_DS->fpImage ) !=
-        (size_t) nRasterXSize / 2 )
+    if( VSIFReadL( pImage, 1, nRasterXSize / 2, poLAN_DS->fpImage ) !=
+        static_cast<size_t>( nRasterXSize ) / 2 )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "LAN Read failed:%s", VSIStrerror( errno ) );
@@ -240,9 +239,11 @@ CPLErr LAN4BitRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     for( int i = nRasterXSize-1; i >= 0; i-- )
     {
         if( (i & 0x01) != 0 )
-            reinterpret_cast<GByte *>( pImage )[i] = ((GByte *) pImage)[i/2] & 0x0f;
+            reinterpret_cast<GByte *>( pImage )[i] =
+                reinterpret_cast<GByte *>(pImage)[i/2] & 0x0f;
         else
-            reinterpret_cast<GByte *>( pImage )[i] = (((GByte *) pImage)[i/2] & 0xf0)/16;
+            reinterpret_cast<GByte *>( pImage )[i] =
+                (reinterpret_cast<GByte *>(pImage)[i/2] & 0xf0) / 16;
     }
 
     return CE_None;
@@ -314,6 +315,13 @@ LANDataset::LANDataset() :
     fpImage(NULL),
     pszProjection(NULL)
 {
+    memset( pachHeader, 0, sizeof(pachHeader) );
+    adfGeoTransform[0] =  0.0;
+    adfGeoTransform[1] =  0.0;  // TODO(schwehr): Should this be 1.0?
+    adfGeoTransform[2] =  0.0;
+    adfGeoTransform[3] =  0.0;
+    adfGeoTransform[4] =  0.0;
+    adfGeoTransform[5] =  0.0;  // TODO(schwehr): Should this be 1.0?
 }
 
 /************************************************************************/
@@ -329,7 +337,7 @@ LANDataset::~LANDataset()
     {
         if( VSIFCloseL( fpImage ) != 0 )
         {
-            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
         }
     }
 
@@ -350,8 +358,10 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < ERD_HEADER_SIZE )
         return NULL;
 
-    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "HEADER")
-        && !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader, "HEAD74") )
+    if( !STARTS_WITH_CI( reinterpret_cast<char *>(poOpenInfo->pabyHeader),
+                         "HEADER" )
+        && !STARTS_WITH_CI( reinterpret_cast<char *>(poOpenInfo->pabyHeader),
+                            "HEAD74" ) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -414,37 +424,32 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( STARTS_WITH_CI(poDS->pachHeader,"HEADER") )
     {
-        float fTmp;
+        float fTmp = 0.0;
         memcpy(&fTmp, poDS->pachHeader + 16, 4);
-        CPL_LSBPTR32(&fTmp);
         poDS->nRasterXSize = (int) fTmp;
         memcpy(&fTmp, poDS->pachHeader + 20, 4);
-        CPL_LSBPTR32(&fTmp);
         poDS->nRasterYSize = (int) fTmp;
     }
     else
     {
-        GInt32 nTmp;
+        GInt32 nTmp = 0;
         memcpy(&nTmp, poDS->pachHeader + 16, 4);
-        CPL_LSBPTR32(&nTmp);
         poDS->nRasterXSize = nTmp;
         memcpy(&nTmp, poDS->pachHeader + 20, 4);
-        CPL_LSBPTR32(&nTmp);
         poDS->nRasterYSize = nTmp;
     }
 
-    GInt16 nTmp16;
+    GInt16 nTmp16 = 0;
     memcpy(&nTmp16, poDS->pachHeader + 6, 2);
-    CPL_LSBPTR16(&nTmp16);
 
-    int nPixelOffset;
-    GDALDataType eDataType;
+    int nPixelOffset = 0;
+    GDALDataType eDataType = GDT_Unknown;
     if( nTmp16 == 0 )
     {
         eDataType = GDT_Byte;
         nPixelOffset = 1;
     }
-    else if( nTmp16 == 1 ) /* 4bit! */
+    else if( nTmp16 == 1 )  // 4 bit
     {
         eDataType = GDT_Byte;
         nPixelOffset = -1;
@@ -465,20 +470,20 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     }
 
     memcpy(&nTmp16, poDS->pachHeader + 8, 2);
-    CPL_LSBPTR16(&nTmp16);
     const int nBandCount = nTmp16;
 
-    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
-        !GDALCheckBandCount(nBandCount, FALSE))
+    if( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
+        !GDALCheckBandCount(nBandCount, FALSE) )
     {
         delete poDS;
         return NULL;
     }
 
-    if( nPixelOffset != -1 && poDS->nRasterXSize > INT_MAX / (nPixelOffset*nBandCount) )
+    if( nPixelOffset != -1 &&
+        poDS->nRasterXSize > INT_MAX / (nPixelOffset * nBandCount) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Int overflow occurred.");
+                  "Int overflow occurred." );
         delete poDS;
         return NULL;
     }
@@ -523,21 +528,17 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try to interpret georeferencing.                                */
 /* -------------------------------------------------------------------- */
-    float fTmp;
+    float fTmp = 0.0;
 
     memcpy(&fTmp, poDS->pachHeader + 112, 4);
-    CPL_LSBPTR32(&fTmp);
     poDS->adfGeoTransform[0] = fTmp;
     memcpy(&fTmp, poDS->pachHeader + 120, 4);
-    CPL_LSBPTR32(&fTmp);
     poDS->adfGeoTransform[1] = fTmp;
     poDS->adfGeoTransform[2] = 0.0;
     memcpy(&fTmp, poDS->pachHeader + 116, 4);
-    CPL_LSBPTR32(&fTmp);
     poDS->adfGeoTransform[3] = fTmp;
     poDS->adfGeoTransform[4] = 0.0;
     memcpy(&fTmp, poDS->pachHeader + 124, 4);
-    CPL_LSBPTR32(&fTmp);
     poDS->adfGeoTransform[5] = - fTmp;
 
     // adjust for center of pixel vs. top left corner of pixel.
@@ -560,7 +561,6 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Try to come up with something for the coordinate system.        */
 /* -------------------------------------------------------------------- */
     memcpy(&nTmp16, poDS->pachHeader + 88, 2);
-    CPL_LSBPTR16(&nTmp16);
     int nCoordSys = nTmp16;
 
     if( nCoordSys == 0 )
@@ -570,29 +570,32 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     else if( nCoordSys == 1 )
     {
         poDS->pszProjection =
-            CPLStrdup("LOCAL_CS[\"UTM - Zone Unknown\",UNIT[\"Meter\",1]]");
+            CPLStrdup( "LOCAL_CS[\"UTM - Zone Unknown\",UNIT[\"Meter\",1]]" );
     }
     else if( nCoordSys == 2 )
     {
-        poDS->pszProjection = CPLStrdup("LOCAL_CS[\"State Plane - Zone Unknown\",UNIT[\"US survey foot\",0.3048006096012192]]");
+        poDS->pszProjection =
+            CPLStrdup(
+                "LOCAL_CS[\"State Plane - Zone Unknown\","
+                "UNIT[\"US survey foot\",0.3048006096012192]]" );
     }
     else
     {
         poDS->pszProjection =
-            CPLStrdup("LOCAL_CS[\"Unknown\",UNIT[\"Meter\",1]]");
+            CPLStrdup( "LOCAL_CS[\"Unknown\",UNIT[\"Meter\",1]]" );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Check for a trailer file with a colormap in it.                 */
 /* -------------------------------------------------------------------- */
-    char *pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-    char *pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
+    char *pszPath = CPLStrdup( CPLGetPath(poOpenInfo->pszFilename) );
+    char *pszBasename = CPLStrdup( CPLGetBasename(poOpenInfo->pszFilename) );
     const char *pszTRLFilename =
         CPLFormCIFilename( pszPath, pszBasename, "trl" );
     VSILFILE *fpTRL = VSIFOpenL( pszTRLFilename, "rb" );
     if( fpTRL != NULL )
     {
-        char szTRLData[896];
+        char szTRLData[896] = { '\0' };
 
         CPL_IGNORE_RET_VAL(VSIFReadL( szTRLData, 1, 896, fpTRL ));
         CPL_IGNORE_RET_VAL(VSIFCloseL( fpTRL ));
@@ -600,15 +603,15 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
         GDALColorTable *poCT = new GDALColorTable();
         for( int iColor = 0; iColor < 256; iColor++ )
         {
-            GDALColorEntry sEntry;
+            GDALColorEntry sEntry = { 0, 0, 0, 0};
 
-            sEntry.c2 = ((GByte *) szTRLData)[iColor+128];
-            sEntry.c1 = ((GByte *) szTRLData)[iColor+128+256];
-            sEntry.c3 = ((GByte *) szTRLData)[iColor+128+512];
+            sEntry.c2 = reinterpret_cast<GByte *>(szTRLData)[iColor+128];
+            sEntry.c1 = reinterpret_cast<GByte *>(szTRLData)[iColor+128+256];
+            sEntry.c3 = reinterpret_cast<GByte *>(szTRLData)[iColor+128+512];
             sEntry.c4 = 255;
             poCT->SetColorEntry( iColor, &sEntry );
 
-            // only 16 colors in 4bit files.
+            // Only 16 colors in 4bit files.
             if( nPixelOffset == -1 && iColor == 15 )
                 break;
         }
@@ -622,7 +625,7 @@ GDALDataset *LANDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLFree( pszPath );
     CPLFree( pszBasename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -637,8 +640,8 @@ CPLErr LANDataset::GetGeoTransform( double * padfTransform )
         memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
         return CE_None;
     }
-    else
-        return GDALPamDataset::GetGeoTransform( padfTransform );
+
+    return GDALPamDataset::GetGeoTransform( padfTransform );
 }
 
 /************************************************************************/
@@ -648,28 +651,28 @@ CPLErr LANDataset::GetGeoTransform( double * padfTransform )
 CPLErr LANDataset::SetGeoTransform( double * padfTransform )
 
 {
-    unsigned char abyHeader[128];
+    unsigned char abyHeader[128] = { '\0' };
 
     memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
 
     CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
     CPL_IGNORE_RET_VAL(VSIFReadL( abyHeader, 128, 1, fpImage ));
 
-    // Upper Left X
+    // Upper Left X.
     float f32Val = static_cast<float>(
         adfGeoTransform[0] + 0.5 * adfGeoTransform[1] );
     memcpy( abyHeader + 112, &f32Val, 4 );
 
-    // Upper Left Y
+    // Upper Left Y.
     f32Val = static_cast<float>(
         adfGeoTransform[3] + 0.5 * adfGeoTransform[5] );
     memcpy( abyHeader + 116, &f32Val, 4 );
 
-    // width of pixel
+    // Width of pixel.
     f32Val = static_cast<float>( adfGeoTransform[1] );
     memcpy( abyHeader + 120, &f32Val, 4 );
 
-    // height of pixel
+    // Height of pixel.
     f32Val = static_cast<float>( std::abs( adfGeoTransform[5] ) );
     memcpy( abyHeader + 124, &f32Val, 4 );
 
@@ -709,7 +712,7 @@ const char *LANDataset::GetProjectionRef()
 CPLErr LANDataset::SetProjection( const char * pszWKT )
 
 {
-    unsigned char abyHeader[128];
+    unsigned char abyHeader[128] = { '\0' };
 
     CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
     CPL_IGNORE_RET_VAL(VSIFReadL( abyHeader, 128, 1, fpImage ));
@@ -719,13 +722,14 @@ CPLErr LANDataset::SetProjection( const char * pszWKT )
     GUInt16 nProjCode = 0;
 
     if( oSRS.IsGeographic() )
+    {
         nProjCode = 0;
-
+    }
     else if( oSRS.GetUTMZone() != 0 )
+    {
         nProjCode = 1;
-
+    }
     // Too bad we have no way of recognising state plane projections.
-
     else
     {
         const char *l_pszProjection = oSRS.GetAttrValue("PROJECTION");
@@ -768,7 +772,7 @@ CPLErr LANDataset::SetProjection( const char * pszWKT )
         else if( EQUAL(l_pszProjection,
                        SRS_PT_ORTHOGRAPHIC) )
             nProjCode = 14;
-        // we don't have GVNP.
+        // We do not have GVNP.
         else if( EQUAL(l_pszProjection,
                        SRS_PT_SINUSOIDAL) )
             nProjCode = 16;
@@ -804,7 +808,7 @@ char **LANDataset::GetFileList()
     // Main data file, etc.
     char **papszFileList = GDALPamDataset::GetFileList();
 
-    if( strlen(osSTAFilename) > 0 )
+    if( !osSTAFilename.empty() )
         papszFileList = CSLAddString( papszFileList, osSTAFilename );
 
     return papszFileList;
@@ -839,7 +843,7 @@ void LANDataset::CheckForStatistics()
 /* -------------------------------------------------------------------- */
 /*      Read it one band at a time.                                     */
 /* -------------------------------------------------------------------- */
-    GByte abyBandInfo[1152];
+    GByte abyBandInfo[1152] = { '\0' };
 
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
@@ -851,7 +855,8 @@ void LANDataset::CheckForStatistics()
         if( poBand == NULL )
             break;
 
-        GInt16 nMin, nMax;
+        GInt16 nMin = 0;
+        GInt16 nMax = 0;
 
         if( poBand->GetRasterDataType() != GDT_Byte )
         {
@@ -866,7 +871,8 @@ void LANDataset::CheckForStatistics()
             nMax = abyBandInfo[8];
         }
 
-        float fMean, fStdDev;
+        float fMean = 0.0;
+        float fStdDev = 0.0;
         memcpy( &fMean, abyBandInfo + 12, 4 );
         memcpy( &fStdDev, abyBandInfo + 24, 4 );
         CPL_LSBPTR32( &fMean );
@@ -887,7 +893,7 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
                                  int nYSize,
                                  int nBands,
                                  GDALDataType eType,
-                                 CPL_UNUSED char ** papszOptions )
+                                 char ** /* papszOptions */ )
 {
     if( eType != GDT_Byte && eType != GDT_Int16 )
     {
@@ -912,70 +918,70 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write out the header.                                           */
 /* -------------------------------------------------------------------- */
-    unsigned char abyHeader[128];
+    unsigned char abyHeader[128] = { '\0' };
 
     memset( abyHeader, 0, sizeof(abyHeader) );
 
     memcpy( abyHeader + 0, "HEAD74", 6 );
 
-    // Pixel type
-    GInt16  n16Val;
-    if( eType == GDT_Byte ) // do we want 4bit?
+    // Pixel type.
+    GInt16  n16Val = 0;
+    if( eType == GDT_Byte ) // Do we want 4bit?
         n16Val = 0;
     else
         n16Val = 2;
     memcpy( abyHeader + 6, &n16Val, 2 );
 
     // Number of Bands.
-    n16Val = (GInt16) nBands;
+    n16Val = static_cast<GInt16>( nBands );
     memcpy( abyHeader + 8, &n16Val, 2 );
 
-    // Unknown (6)
+    // Unknown (6).
 
-    // Width
+    // Width.
     GInt32  n32Val = nXSize;
     memcpy( abyHeader + 16, &n32Val, 4 );
 
-    // Height
+    // Height.
     n32Val = nYSize;
     memcpy( abyHeader + 20, &n32Val, 4 );
 
-    // X Start (4)
-    // Y Start (4)
+    // X Start (4).
+    // Y Start (4).
 
-    // Unknown (56)
+    // Unknown (56).
 
-    // Coordinate System
+    // Coordinate System.
     n16Val = 0;
     memcpy( abyHeader + 88, &n16Val, 2 );
 
-    // Classes in coverage
+    // Classes in coverage.
     n16Val = 0;
     memcpy( abyHeader + 90, &n16Val, 2 );
 
-    // Unknown (14)
+    // Unknown (14).
 
-    // Area Unit
+    // Area Unit.
     n16Val = 0;
     memcpy( abyHeader + 106, &n16Val, 2 );
 
-    // Pixel Area
+    // Pixel Area.
     float f32Val = 0.0f;
     memcpy( abyHeader + 108, &f32Val, 4 );
 
-    // Upper Left X
+    // Upper Left X.
     f32Val = 0.5f;
     memcpy( abyHeader + 112, &f32Val, 4 );
 
     // Upper Left Y
-    f32Val = (float) (nYSize - 0.5);
+    f32Val = static_cast<float>(nYSize - 0.5);
     memcpy( abyHeader + 116, &f32Val, 4 );
 
-    // width of pixel
+    // Width of pixel.
     f32Val = 1.0f;
     memcpy( abyHeader + 120, &f32Val, 4 );
 
-    // height of pixel
+    // Height of pixel.
     f32Val = 1.0f;
     memcpy( abyHeader + 124, &f32Val, 4 );
 
@@ -984,7 +990,7 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Extend the file to the target size.                             */
 /* -------------------------------------------------------------------- */
-    vsi_l_offset nImageBytes;
+    vsi_l_offset nImageBytes = 0;
 
     if( eType != GDT_Byte )
         nImageBytes = nXSize * static_cast<vsi_l_offset>( nYSize ) * 2;
@@ -1016,7 +1022,7 @@ GDALDataset *LANDataset::Create( const char * pszFilename,
         return NULL;
     }
 
-    return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    return static_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
diff --git a/frmts/raw/lcpdataset.cpp b/frmts/raw/lcpdataset.cpp
index e29f092..8bb62b7 100644
--- a/frmts/raw/lcpdataset.cpp
+++ b/frmts/raw/lcpdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: lcpdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  LCP Driver
  * Purpose:  FARSITE v.4 Landscape file (.lcp) reader for GDAL
@@ -35,7 +34,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: lcpdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
+CPL_CVSID("$Id: lcpdataset.cpp 36948 2016-12-18 13:32:14Z rouault $");
 
 static const size_t LCP_HEADER_SIZE = 7316;
 static const int LCP_MAX_BANDS = 10;
@@ -65,9 +64,9 @@ class LCPDataset : public RawDataset
                 LCPDataset();
     virtual ~LCPDataset();
 
-    virtual char **GetFileList(void);
+    virtual char **GetFileList(void) override;
 
-    virtual CPLErr GetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
@@ -76,24 +75,25 @@ class LCPDataset : public RawDataset
                                     int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress,
                                     void * pProgressData );
-    virtual const char *GetProjectionRef(void);
+    virtual const char *GetProjectionRef(void) override;
 
     int bHaveProjection;
 };
 
 /************************************************************************/
-/*                            LCPDataset()                             */
+/*                            LCPDataset()                              */
 /************************************************************************/
 
 LCPDataset::LCPDataset() :
     fpImage(NULL),
     pszProjection(CPLStrdup( "" ))
 {
+    memset( pachHeader, 0, sizeof(pachHeader) );
     bHaveProjection = FALSE;
 }
 
 /************************************************************************/
-/*                            ~LCPDataset()                            */
+/*                            ~LCPDataset()                             */
 /************************************************************************/
 
 LCPDataset::~LCPDataset()
@@ -104,7 +104,7 @@ LCPDataset::~LCPDataset()
     {
         if( VSIFCloseL( fpImage ) != 0 )
         {
-            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+            CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
         }
     }
     CPLFree(pszProjection);
@@ -116,14 +116,19 @@ LCPDataset::~LCPDataset()
 
 CPLErr LCPDataset::GetGeoTransform( double * padfTransform )
 {
-    double      dfEast, dfWest, dfNorth, dfSouth, dfCellX, dfCellY;
-
-    memcpy(&dfEast, pachHeader + 4172, sizeof(double));
-    memcpy(&dfWest, pachHeader + 4180, sizeof(double));
-    memcpy(&dfNorth, pachHeader + 4188, sizeof(double));
-    memcpy(&dfSouth, pachHeader + 4196, sizeof(double));
-    memcpy(&dfCellX, pachHeader + 4208, sizeof(double));
-    memcpy(&dfCellY, pachHeader + 4216, sizeof(double));
+    double dfEast = 0.0;
+    double dfWest = 0.0;
+    double dfNorth = 0.0;
+    double dfSouth = 0.0;
+    double dfCellX = 0.0;
+    double dfCellY = 0.0;
+
+    memcpy( &dfEast, pachHeader + 4172, sizeof(double) );
+    memcpy( &dfWest, pachHeader + 4180, sizeof(double) );
+    memcpy( &dfNorth, pachHeader + 4188, sizeof(double) );
+    memcpy( &dfSouth, pachHeader + 4196, sizeof(double) );
+    memcpy( &dfCellX, pachHeader + 4208, sizeof(double) );
+    memcpy( &dfCellY, pachHeader + 4216, sizeof(double) );
     CPL_LSBPTR64(&dfEast);
     CPL_LSBPTR64(&dfWest);
     CPL_LSBPTR64(&dfNorth);
@@ -156,12 +161,12 @@ int LCPDataset::Identify( GDALOpenInfo * poOpenInfo )
         return FALSE;
 
     /* check if first three fields have valid data */
-    if( (CPL_LSBINT32PTR(poOpenInfo->pabyHeader) != 20
-          && CPL_LSBINT32PTR(poOpenInfo->pabyHeader) != 21)
-        || (CPL_LSBINT32PTR(poOpenInfo->pabyHeader+4) != 20
-          && CPL_LSBINT32PTR(poOpenInfo->pabyHeader+4) != 21)
-        || (CPL_LSBINT32PTR(poOpenInfo->pabyHeader+8) < -90
-             || CPL_LSBINT32PTR(poOpenInfo->pabyHeader+8) > 90) )
+    if( (CPL_LSBSINT32PTR(poOpenInfo->pabyHeader) != 20
+          && CPL_LSBSINT32PTR(poOpenInfo->pabyHeader) != 21)
+        || (CPL_LSBSINT32PTR(poOpenInfo->pabyHeader+4) != 20
+          && CPL_LSBSINT32PTR(poOpenInfo->pabyHeader+4) != 21)
+        || (CPL_LSBSINT32PTR(poOpenInfo->pabyHeader+8) < -90
+             || CPL_LSBSINT32PTR(poOpenInfo->pabyHeader+8) > 90) )
     {
         return FALSE;
     }
@@ -194,7 +199,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 
 {
 /* -------------------------------------------------------------------- */
-/*      Verify that this is a FARSITE LCP file    */
+/*      Verify that this is a FARSITE LCP file                          */
 /* -------------------------------------------------------------------- */
     if( !Identify( poOpenInfo ) )
         return NULL;
@@ -204,7 +209,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( poOpenInfo->eAccess == GA_Update )
     {
-        CPLError( CE_Failure, CPLE_NotSupported, 
+        CPLError( CE_Failure, CPLE_NotSupported,
                   "The LCP driver does not support update access to existing"
                   " datasets." );
         return NULL;
@@ -223,15 +228,16 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Read the header and extract some information.                   */
 /* -------------------------------------------------------------------- */
    if (VSIFSeekL( poDS->fpImage, 0, SEEK_SET ) < 0 ||
-       VSIFReadL( poDS->pachHeader, 1, LCP_HEADER_SIZE, poDS->fpImage ) != LCP_HEADER_SIZE)
+       VSIFReadL( poDS->pachHeader, 1, LCP_HEADER_SIZE, poDS->fpImage )
+       != LCP_HEADER_SIZE)
    {
-       CPLError(CE_Failure, CPLE_FileIO, "File too short");
+       CPLError( CE_Failure, CPLE_FileIO, "File too short" );
        delete poDS;
        return NULL;
    }
 
-   int nWidth = CPL_LSBINT32PTR (poDS->pachHeader + 4164);
-   int nHeight = CPL_LSBINT32PTR (poDS->pachHeader + 4168);
+   const int nWidth = CPL_LSBSINT32PTR( poDS->pachHeader + 4164);
+   const int nHeight = CPL_LSBSINT32PTR( poDS->pachHeader + 4168);
 
    poDS->nRasterXSize = nWidth;
    poDS->nRasterYSize = nHeight;
@@ -242,13 +248,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
        return NULL;
    }
 
-   // crown fuels = canopy height, canopy base height, canopy bulk density
-   // 21 = have them, 20 = don't have them
-   const bool bHaveCrownFuels = CPL_TO_BOOL( CPL_LSBINT32PTR (poDS->pachHeader + 0) - 20 );
-   // ground fuels = duff loading, coarse woody
-   const bool bHaveGroundFuels = CPL_TO_BOOL( CPL_LSBINT32PTR (poDS->pachHeader + 4) - 20 );
+   // Crown fuels = canopy height, canopy base height, canopy bulk density.
+   // 21 = have them, 20 = do not have them
+   const bool bHaveCrownFuels =
+       CPL_TO_BOOL( CPL_LSBSINT32PTR (poDS->pachHeader + 0) - 20 );
+   // Ground fuels = duff loading, coarse woody.
+   const bool bHaveGroundFuels =
+       CPL_TO_BOOL( CPL_LSBSINT32PTR (poDS->pachHeader + 4) - 20 );
 
-   int nBands;
+   int nBands = 0;
    if( bHaveCrownFuels )
    {
        if( bHaveGroundFuels )
@@ -264,14 +272,14 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            nBands = 5;
    }
 
-   // add dataset-level metadata
+   // Add dataset-level metadata.
 
-   int nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 8);
-   char szTemp[32];
+   int nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 8);
+   char szTemp[32] = { '\0' };
    snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
    poDS->SetMetadataItem( "LATITUDE", szTemp );
 
-   nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 4204);
+   nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 4204);
    if ( nTemp == 0 )
       poDS->SetMetadataItem( "LINEAR_UNIT", "Meters" );
    if ( nTemp == 1 )
@@ -280,14 +288,11 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
    poDS->pachHeader[LCP_HEADER_SIZE-1] = '\0';
    poDS->SetMetadataItem( "DESCRIPTION", poDS->pachHeader + 6804 );
 
-
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
 
-   int          iPixelSize;
-   iPixelSize = nBands * 2;
-   int          bNativeOrder;
+   const int iPixelSize = nBands * 2;
 
    if (nWidth > INT_MAX / iPixelSize)
    {
@@ -297,12 +302,13 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
    }
 
 #ifdef CPL_LSB
-   bNativeOrder = TRUE;
+   const bool bNativeOrder = true;
 #else
-   bNativeOrder = FALSE;
+   const bool bNativeOrder = false;
 #endif
 
-   char* pszList = reinterpret_cast<char *>( CPLMalloc(2048) );
+   // TODO(schwehr): Explain the 2048.
+   char* pszList = static_cast<char *>( CPLMalloc(2048) );
    pszList[0] = '\0';
 
    for( int iBand = 1; iBand <= nBands; iBand++ )
@@ -317,7 +323,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
         case 1:
            poBand->SetDescription("Elevation");
 
-           nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4224);
+           nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4224);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_UNIT", szTemp );
 
@@ -326,15 +332,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            if ( nTemp == 1 )
               poBand->SetMetadataItem( "ELEVATION_UNIT_NAME", "Feet" );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 44);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 44);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_MIN", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 48);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 48);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_MAX", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 52);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 52);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ELEVATION_NUM_CLASSES", szTemp );
 
@@ -346,7 +352,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
         case 2:
            poBand->SetDescription("Slope");
 
-           nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4226);
+           nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4226);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_UNIT", szTemp );
 
@@ -355,15 +361,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            if ( nTemp == 1 )
               poBand->SetMetadataItem( "SLOPE_UNIT_NAME", "Percent" );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 456);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 456);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_MIN", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 460);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 460);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_MAX", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 464);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 464);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "SLOPE_NUM_CLASSES", szTemp );
 
@@ -375,7 +381,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
         case 3:
            poBand->SetDescription("Aspect");
 
-           nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4228);
+           nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4228);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_UNIT", szTemp );
 
@@ -386,15 +392,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            if ( nTemp == 2 )
               poBand->SetMetadataItem( "ASPECT_UNIT_NAME", "Azimuth degrees" );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 868);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 868);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_MIN", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 872);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 872);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_MAX", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 876);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 876);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "ASPECT_NUM_CLASSES", szTemp );
 
@@ -407,39 +413,48 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
         {
            poBand->SetDescription("Fuel models");
 
-           nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4230);
+           nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4230);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "FUEL_MODEL_OPTION", szTemp );
 
            if ( nTemp == 0 )
-              poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "no custom models AND no conversion file needed" );
+              poBand->SetMetadataItem(
+                  "FUEL_MODEL_OPTION_DESC",
+                  "no custom models AND no conversion file needed" );
            if ( nTemp == 1 )
-              poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "custom models BUT no conversion file needed" );
+              poBand->SetMetadataItem(
+                  "FUEL_MODEL_OPTION_DESC",
+                  "custom models BUT no conversion file needed" );
            if ( nTemp == 2 )
-              poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "no custom models BUT conversion file needed" );
+              poBand->SetMetadataItem(
+                  "FUEL_MODEL_OPTION_DESC",
+                  "no custom models BUT conversion file needed" );
            if ( nTemp == 3 )
-              poBand->SetMetadataItem( "FUEL_MODEL_OPTION_DESC", "custom models AND conversion file needed" );
+              poBand->SetMetadataItem(
+                  "FUEL_MODEL_OPTION_DESC",
+                  "custom models AND conversion file needed" );
 
-           const int nMinFM = CPL_LSBINT32PTR (poDS->pachHeader + 1280);
+           const int nMinFM = CPL_LSBSINT32PTR (poDS->pachHeader + 1280);
            snprintf( szTemp, sizeof(szTemp), "%d", nMinFM);
            poBand->SetMetadataItem( "FUEL_MODEL_MIN", szTemp );
 
-           const int nMaxFM = CPL_LSBINT32PTR (poDS->pachHeader + 1284);
+           const int nMaxFM = CPL_LSBSINT32PTR (poDS->pachHeader + 1284);
            snprintf( szTemp, sizeof(szTemp), "%d", nMaxFM);
            poBand->SetMetadataItem( "FUEL_MODEL_MAX", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1288);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 1288);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "FUEL_MODEL_NUM_CLASSES", szTemp );
 
            if (nTemp > 0 && nTemp <= 100) {
               strcpy(pszList, "");
               for ( int i = 0; i <= nTemp; i++ ) {
-                  const int nTemp2 = CPL_LSBINT32PTR (poDS->pachHeader + (1292+(i*4))) ;
+                  const int nTemp2 =
+                      CPL_LSBSINT32PTR( poDS->pachHeader + (1292+(i*4)) );
                   if ( nTemp2 >= nMinFM && nTemp2 <= nMaxFM ) {
                      snprintf( szTemp, sizeof(szTemp), "%d", nTemp2);
                      strcat(pszList, szTemp);
-                     if (i < (nTemp) )
+                     if (i < nTemp )
                         strcat(pszList, ",");
                   }
               }
@@ -447,31 +462,33 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            poBand->SetMetadataItem( "FUEL_MODEL_VALUES", pszList );
 
            *(poDS->pachHeader + 5012 + 255) = '\0';
-           poBand->SetMetadataItem( "FUEL_MODEL_FILE", poDS->pachHeader + 5012 );
+           poBand->SetMetadataItem( "FUEL_MODEL_FILE",
+                                    poDS->pachHeader + 5012 );
 
            break;
         }
         case 5:
            poBand->SetDescription("Canopy cover");
 
-           nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4232);
+           nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4232);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_UNIT", szTemp );
 
            if ( nTemp == 0 )
-              poBand->SetMetadataItem( "CANOPY_COV_UNIT_NAME", "Categories (0-4)" );
+              poBand->SetMetadataItem( "CANOPY_COV_UNIT_NAME",
+                                       "Categories (0-4)" );
            if ( nTemp == 1 )
               poBand->SetMetadataItem( "CANOPY_COV_UNIT_NAME", "Percent" );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1692);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 1692);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_MIN", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1696);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 1696);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_MAX", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 1700);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 1700);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CANOPY_COV_NUM_CLASSES", szTemp );
 
@@ -484,7 +501,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            if(bHaveCrownFuels) {
               poBand->SetDescription("Canopy height");
 
-              nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4234);
+              nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4234);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CANOPY_HT_UNIT", szTemp );
 
@@ -497,25 +514,27 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               if ( nTemp == 4 )
                  poBand->SetMetadataItem( "CANOPY_HT_UNIT_NAME", "Feet x 10" );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2104);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 2104);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CANOPY_HT_MIN", szTemp );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2108);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 2108);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CANOPY_HT_MAX", szTemp );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2112);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 2112);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CANOPY_HT_NUM_CLASSES", szTemp );
 
               *(poDS->pachHeader + 5524 + 255) = '\0';
-              poBand->SetMetadataItem( "CANOPY_HT_FILE", poDS->pachHeader + 5524 );
+              poBand->SetMetadataItem( "CANOPY_HT_FILE",
+                                       poDS->pachHeader + 5524 );
            }
-           else {
+           else
+           {
               poBand->SetDescription("Duff");
 
-              nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4240);
+              nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4240);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "DUFF_UNIT", szTemp );
 
@@ -524,15 +543,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               if ( nTemp == 2 )
                  poBand->SetMetadataItem( "DUFF_UNIT_NAME", "t/ac" );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3340);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3340);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "DUFF_MIN", szTemp );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3344);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3344);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "DUFF_MAX", szTemp );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3348);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3348);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "DUFF_NUM_CLASSES", szTemp );
 
@@ -545,7 +564,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            if(bHaveCrownFuels) {
               poBand->SetDescription("Canopy base height");
 
-              nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4236);
+              nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4236);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CBH_UNIT", szTemp );
 
@@ -558,25 +577,26 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               if ( nTemp == 4 )
                  poBand->SetMetadataItem( "CBH_UNIT_NAME", "Feet x 10" );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2516);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 2516);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CBH_MIN", szTemp );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2520);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 2520);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CBH_MAX", szTemp );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2524);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 2524);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CBH_NUM_CLASSES", szTemp );
 
               *(poDS->pachHeader + 5780 + 255) = '\0';
               poBand->SetMetadataItem( "CBH_FILE", poDS->pachHeader + 5780 );
            }
-           else {
-              poBand->SetDescription("Coarse woody debris");
+           else
+           {
+              poBand->SetDescription( "Coarse woody debris" );
 
-              nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4242);
+              nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4242);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CWD_OPTION", szTemp );
 
@@ -585,15 +605,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
               //if ( nTemp == 2 )
               //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3752);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3752);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CWD_MIN", szTemp );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3756);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3756);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CWD_MAX", szTemp );
 
-              nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3760);
+              nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3760);
               snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
               poBand->SetMetadataItem( "CWD_NUM_CLASSES", szTemp );
 
@@ -605,7 +625,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
         case 8:
            poBand->SetDescription("Canopy bulk density");
 
-           nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4238);
+           nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4238);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CBD_UNIT", szTemp );
 
@@ -618,15 +638,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            if ( nTemp == 4 )
               poBand->SetMetadataItem( "CBD_UNIT_NAME", "lb/ft^3 x 1000" );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2928);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 2928);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CBD_MIN", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2932);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 2932);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CBD_MAX", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 2936);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 2936);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CBD_NUM_CLASSES", szTemp );
 
@@ -638,7 +658,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
         case 9:
            poBand->SetDescription("Duff");
 
-           nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4240);
+           nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4240);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_UNIT", szTemp );
 
@@ -647,15 +667,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            if ( nTemp == 2 )
               poBand->SetMetadataItem( "DUFF_UNIT_NAME", "t/ac" );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3340);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3340);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_MIN", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3344);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3344);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_MAX", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3348);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3348);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "DUFF_NUM_CLASSES", szTemp );
 
@@ -667,7 +687,7 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
         case 10:
            poBand->SetDescription("Coarse woody debris");
 
-           nTemp = CPL_LSBINT16PTR (poDS->pachHeader + 4242);
+           nTemp = CPL_LSBUINT16PTR (poDS->pachHeader + 4242);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CWD_OPTION", szTemp );
 
@@ -676,15 +696,15 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
            //if ( nTemp == 2 )
            //   poBand->SetMetadataItem( "CWD_UNIT_DESC", "?" );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3752);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3752);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CWD_MIN", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3756);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3756);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CWD_MAX", szTemp );
 
-           nTemp = CPL_LSBINT32PTR (poDS->pachHeader + 3760);
+           nTemp = CPL_LSBSINT32PTR (poDS->pachHeader + 3760);
            snprintf( szTemp, sizeof(szTemp), "%d", nTemp);
            poBand->SetMetadataItem( "CWD_NUM_CLASSES", szTemp );
 
@@ -698,11 +718,11 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Try to read projection file.                                    */
 /* -------------------------------------------------------------------- */
-    char *pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-    char *pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
+    char * const pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
+    char * const pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));
 
     poDS->osPrjFilename = CPLFormFilename( pszDirname, pszBasename, "prj" );
-    VSIStatBufL   sStatBuf;
+    VSIStatBufL sStatBuf;
     int nRet = VSIStatL( poDS->osPrjFilename, &sStatBuf );
 
     if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename))
@@ -740,11 +760,12 @@ GDALDataset *LCPDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Check for external overviews.                                   */
 /* -------------------------------------------------------------------- */
-    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
+    poDS->oOvManager.Initialize(
+        poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );
 
     CPLFree(pszList);
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -786,12 +807,15 @@ CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
 
     const int nXSize = poBand->GetXSize();
     const int nYSize = poBand->GetYSize();
-    double dfMax, dfDummy;
+    double dfMax = 0.0;
+    double dfDummy = 0.0;
     poBand->GetStatistics( FALSE, TRUE, &dfDummy, &dfMax, &dfDummy, &dfDummy );
 
     const int nSpan = static_cast<int>( dfMax );
-    GInt16 *panValues = (GInt16*)CPLMalloc( sizeof( GInt16 ) * nXSize );
-    GByte *pabyFlags = (GByte*)CPLMalloc( sizeof( GByte ) * nSpan + 1 );
+    GInt16 *panValues =
+        static_cast<GInt16 *>( CPLMalloc( sizeof( GInt16 ) * nXSize ) );
+    GByte *pabyFlags =
+        static_cast<GByte *>( CPLMalloc( sizeof( GByte ) * nSpan + 1 ) );
     memset( pabyFlags, 0, nSpan + 1 );
 
     int nFound = 0;
@@ -800,7 +824,7 @@ CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
     for( int iLine = 0; iLine < nYSize; iLine++ )
     {
         eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
-                                 panValues, nXSize, 1, 
+                                 panValues, nXSize, 1,
                                  GDT_Int16, 0, 0, NULL );
         for( int iPixel = 0; iPixel < nXSize; iPixel++ )
         {
@@ -810,9 +834,10 @@ CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
             }
             if( nFound > 99 )
             {
-                CPLDebug( "LCP", "Found more that 100 unique values in " \
-                                 "band %d.  Not 'classifying' the data.",
-                                 poBand->GetBand() );
+                CPLDebug( "LCP",
+                          "Found more that 100 unique values in "
+                          "band %d.  Not 'classifying' the data.",
+                          poBand->GetBand() );
                 nFound = -1;
                 bTooMany = true;
                 break;
@@ -829,10 +854,9 @@ CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
         }
     }
     CPLAssert( nFound <= 100 );
-    /*
-    ** The classes are always padded with a leading 0.  This was for aligning
-    ** offsets, or making it a 1-based array instead of 0-based.
-    */
+
+    // The classes are always padded with a leading 0.  This was for aligning
+    // offsets, or making it a 1-based array instead of 0-based.
     panClasses[0] = 0;
     for( int j = 0, nIndex = 1; j < nSpan + 1; j++ )
     {
@@ -852,8 +876,8 @@ CPLErr LCPDataset::ClassifyBandData( GDALRasterBand *poBand,
 /*                          CreateCopy()                                */
 /************************************************************************/
 
-GDALDataset *LCPDataset::CreateCopy( const char * pszFilename, 
-                                     GDALDataset * poSrcDS, 
+GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
+                                     GDALDataset * poSrcDS,
                                      int bStrict, char ** papszOptions,
                                      GDALProgressFunc pfnProgress,
                                      void * pProgressData )
@@ -887,38 +911,28 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      What schema do we have (ground/crown fuels)                     */
 /* -------------------------------------------------------------------- */
-    int bHaveCrownFuels = FALSE;
-    int bHaveGroundFuels = FALSE;
 
-    if( nBands == 8 || nBands == 10 )
-    {
-        bHaveCrownFuels = TRUE;
-    }
-    if( nBands == 7 || nBands == 10 )
-    {
-        bHaveGroundFuels = TRUE;
-    }
-
-    /*
-    ** Since units are 'configurable', we should check for user
-    ** defined units.  This is a bit cumbersome, but the user should
-    ** be allowed to specify none to get default units/options.  Use 
-    ** default units every chance we get.
-    */
-    GInt16 panMetadata[LCP_MAX_BANDS];
-
-    panMetadata[0] = 0; /* ELEVATION_UNIT */
-    panMetadata[1] = 0; /* SLOPE_UNIT */
-    panMetadata[2] = 2; /* ASPECT_UNIT */
-    panMetadata[3] = 0; /* FUEL_MODEL_OPTION */
-    panMetadata[4] = 1; /* CANOPY_COV_UNIT */
-    panMetadata[5] = 3; /* CANOPY_HT_UNIT */
-    panMetadata[6] = 3; /* CBH_UNIT */
-    panMetadata[7] = 3; /* CBD_UNIT */
-    panMetadata[8] = 1; /* DUFF_UNIT */
-    panMetadata[9] = 0; /* CWD_OPTION */
-
-    /* Check the units/options for user overrides */
+    const bool bHaveCrownFuels = nBands == 8 || nBands == 10;
+    const bool bHaveGroundFuels = nBands == 7 || nBands == 10;
+
+    // Since units are 'configurable', we should check for user
+    // defined units.  This is a bit cumbersome, but the user should
+    // be allowed to specify none to get default units/options.  Use
+    // default units every chance we get.
+    GInt16 panMetadata[LCP_MAX_BANDS] = {
+        0, // 0 ELEVATION_UNIT
+        0, // 1 SLOPE_UNIT
+        2, // 2 ASPECT_UNIT
+        0, // 3 FUEL_MODEL_OPTION
+        1, // 4 CANOPY_COV_UNIT
+        3, // 5 CANOPY_HT_UNIT
+        3, // 6 CBH_UNIT
+        3, // 7 CBD_UNIT
+        1, // 8 DUFF_UNIT
+        0, // 9 CWD_OPTION
+    };
+
+    // Check the units/options for user overrides.
     const char *pszTemp
         = CSLFetchNameValueDef( papszOptions, "ELEVATION_UNIT", "METERS" );
     if( STARTS_WITH_CI(pszTemp, "METER") )
@@ -1037,7 +1051,8 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
         {
             panMetadata[5] = 3;
         }
-        else if( EQUAL( pszTemp, "FEET_X_10" ) || EQUAL( pszTemp, "FOOT_X_10" ) )
+        else if( EQUAL( pszTemp, "FEET_X_10" ) ||
+                 EQUAL( pszTemp, "FOOT_X_10" ) )
         {
             panMetadata[5] = 4;
         }
@@ -1064,7 +1079,8 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
         {
             panMetadata[6] = 3;
         }
-        else if( EQUAL( pszTemp, "FEET_X_10" ) || EQUAL( pszTemp, "FOOT_X_10" ) )
+        else if( EQUAL( pszTemp, "FEET_X_10" ) ||
+                 EQUAL( pszTemp, "FOOT_X_10" ) )
         {
             panMetadata[6] = 4;
         }
@@ -1126,21 +1142,17 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
         panMetadata[9] = 1;
     }
 
-    /*
-    ** Calculate the stats for each band.  The binary file carries along
-    ** these metadata for display purposes(?).
-    */
-    bool bCalculateStats = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "CALCULATE_STATS",
-                                            TRUE ));
-    const bool bClassifyData = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "CLASSIFY_DATA",
-                                                TRUE ));
-    /*
-    ** We should have stats if we classify, we'll get them anyway.
-    */
+    // Calculate the stats for each band.  The binary file carries along
+    // these metadata for display purposes(?).
+    bool bCalculateStats = CPLFetchBool(papszOptions, "CALCULATE_STATS", true);
+
+    const bool bClassifyData = CPLFetchBool(papszOptions, "CLASSIFY_DATA", true);
+
+    // We should have stats if we classify, we'll get them anyway.
     if( bClassifyData && !bCalculateStats )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "Ignoring request to not calculate statistics, " \
+                  "Ignoring request to not calculate statistics, "
                   "because CLASSIFY_DATA was set to ON" );
         bCalculateStats = true;
     }
@@ -1173,17 +1185,16 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
         nLatitude = atoi( CSLFetchNameValue( papszOptions, "LATITUDE" ) );
         if( nLatitude > 90 || nLatitude < -90 )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, 
+            CPLError( CE_Failure, CPLE_OpenFailed,
                       "Invalid value (%d) for LATITUDE.", nLatitude );
             return NULL;
         }
     }
-    /*
-    ** If no latitude is supplied, attempt to extract the central latitude
-    ** from the image.  It must be set either manually or here, otherwise
-    ** we fail.
-    */
-    double adfSrcGeoTransform[6];
+
+    // If no latitude is supplied, attempt to extract the central latitude
+    // from the image.  It must be set either manually or here, otherwise
+    // we fail.
+    double adfSrcGeoTransform[6] = { 0.0 };
     poSrcDS->GetGeoTransform( adfSrcGeoTransform );
     OGRSpatialReference oSrcSRS;
     const char *pszWkt = poSrcDS->GetProjectionRef();
@@ -1206,19 +1217,18 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
                 OGRCreateCoordinateTransformation( &oSrcSRS, &oDstSRS ) );
         if( poCT != NULL )
         {
-            dfLatitude = adfSrcGeoTransform[3] + adfSrcGeoTransform[5] * nYSize / 2;
+            dfLatitude =
+                adfSrcGeoTransform[3] + adfSrcGeoTransform[5] * nYSize / 2;
             const int nErr = static_cast<int>(
                 poCT->Transform( 1, &dfLongitude, &dfLatitude ) );
             if( !nErr )
             {
                 dfLatitude = 0.0;
-                /*
-                ** For the most part, this is an invalid LCP, but it is a
-                ** changeable value in Flammap/Farsite, etc.  We should
-                ** probably be strict here all the time.
-                */
+                // For the most part, this is an invalid LCP, but it is a
+                // changeable value in Flammap/Farsite, etc.  We should
+                // probably be strict here all the time.
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "Could not calculate latitude from spatial " \
+                          "Could not calculate latitude from spatial "
                           "reference and LATITUDE was not set." );
                 return NULL;
             }
@@ -1227,18 +1237,14 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     }
     else
     {
-        /*
-        ** See comment above on failure to transform.
-        */
-        CPLError( CE_Failure, CPLE_AppDefined, 
-                  "Could not calculate latitude from spatial reference " \
+        // See comment above on failure to transform.
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Could not calculate latitude from spatial reference "
                   "and LATITUDE was not set." );
         return NULL;
     }
-    /*
-    ** Set the linear units if the metadata item was not already set, and we
-    ** have an SRS.
-    */
+    // Set the linear units if the metadata item was not already set, and we
+    // have an SRS.
     if( bSetLinearUnits && !EQUAL( pszWkt, "" ) )
     {
         const char *pszUnit = oSrcSRS.GetAttrValue( "UNIT", 0 );
@@ -1280,20 +1286,20 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
             pszUnit = oSrcSRS.GetAttrValue( "UNIT", 1 );
             if( pszUnit != NULL )
             {
-                double dfScale = CPLAtof( pszUnit );
+                const double dfScale = CPLAtof( pszUnit );
                 if( dfScale != 1.0 )
                 {
                     if( bStrict )
                     {
                         CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Unit scale is %lf (!=1.0). It is not " \
+                                  "Unit scale is %lf (!=1.0). It is not "
                                   "supported.", dfScale );
                         return NULL;
                     }
                     else
                     {
                         CPLError( CE_Warning, CPLE_AppDefined,
-                                  "Unit scale is %lf (!=1.0). It is not " \
+                                  "Unit scale is %lf (!=1.0). It is not "
                                   "supported, ignoring.", dfScale );
                     }
                 }
@@ -1302,9 +1308,7 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     }
     else if( bSetLinearUnits )
     {
-        /*
-        ** This can be defaulted if it isn't a strict creation.
-        */
+        // This can be defaulted if it is not a strict creation.
         if( bStrict )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -1325,34 +1329,36 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
         CSLFetchNameValueDef( papszOptions, "DESCRIPTION",
                               "LCP file created by GDAL." );
 
-    /*
-    ** Loop through and get the stats for the bands if we need to calculate
-    ** them.  This probably should be done when we copy the data over to the
-    ** destination dataset, since we load the values into memory, but this is
-    ** much simpler code using GDALRasterBand->GetStatistics().  We also may
-    ** need to classify the data (number of unique values and a list of those
-    ** values if the number of unique values is > 100.  It is currently unclear
-    ** how these data are used though, so we will implement that at some point
-    ** if need be.
-    */
-    double *padfMin = reinterpret_cast<double *>( CPLMalloc( sizeof( double ) * nBands ) );
-    double *padfMax = reinterpret_cast<double *>( CPLMalloc( sizeof( double ) * nBands ) );
-    /*
-    ** Initialize these arrays to zeros
-    */
-    GInt32 *panFound = reinterpret_cast<GInt32 *>( VSIMalloc2( sizeof( GInt32 ), nBands ) );
+    // Loop through and get the stats for the bands if we need to calculate
+    // them.  This probably should be done when we copy the data over to the
+    // destination dataset, since we load the values into memory, but this is
+    // much simpler code using GDALRasterBand->GetStatistics().  We also may
+    // need to classify the data (number of unique values and a list of those
+    // values if the number of unique values is > 100.  It is currently unclear
+    // how these data are used though, so we will implement that at some point
+    // if need be.
+    double *padfMin =
+        static_cast<double *>( CPLMalloc( sizeof( double ) * nBands ) );
+    double *padfMax =
+        static_cast<double *>( CPLMalloc( sizeof( double ) * nBands ) );
+
+    // Initialize these arrays to zeros
+    GInt32 *panFound =
+        static_cast<GInt32 *>( VSIMalloc2( sizeof( GInt32 ), nBands ) );
     memset( panFound, 0, sizeof( GInt32 ) * nBands );
-    GInt32 *panClasses = reinterpret_cast<GInt32 *>( VSIMalloc3( sizeof( GInt32 ), nBands, LCP_MAX_CLASSES ) );
+    GInt32 *panClasses =
+        static_cast<GInt32 *>(
+            VSIMalloc3( sizeof( GInt32 ), nBands, LCP_MAX_CLASSES ) );
     memset( panClasses, 0, sizeof( GInt32 ) * nBands * LCP_MAX_CLASSES );
 
-    CPLErr eErr;
+    CPLErr eErr = CE_None;
     if( bCalculateStats )
     {
 
         for( int i = 0; i < nBands; i++ )
         {
             GDALRasterBand *poBand = poSrcDS->GetRasterBand( i + 1 );
-            double dfDummy;
+            double dfDummy = 0.0;
             eErr = poBand->GetStatistics( FALSE, TRUE, &padfMin[i],
                                           &padfMax[i], &dfDummy, &dfDummy );
             if( eErr != CE_None )
@@ -1363,9 +1369,8 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
                 padfMin[i] = 0.0;
                 padfMax[i] = 0.0;
             }
-            /*
-            ** See comment above.
-            */
+
+            // See comment above.
             if( bClassifyData )
             {
                 eErr = ClassifyBandData( poBand, panFound+ i,
@@ -1382,7 +1387,7 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
+        CPLError( CE_Failure, CPLE_OpenFailed,
                   "Unable to create lcp file %s.", pszFilename );
         CPLFree( padfMin );
         CPLFree( padfMax );
@@ -1419,10 +1424,8 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     CPL_LSBPTR64( &dfLatitude );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &dfLatitude, 8, 1, fp ));
 
-    /*
-    ** Swap the two classification arrays if we are writing them, and they need
-    ** to be swapped.
-    */
+    // Swap the two classification arrays if we are writing them, and they need
+    // to be swapped.
 #ifdef CPL_MSB
     if( bClassifyData )
     {
@@ -1435,27 +1438,25 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     {
         for( int i = 0; i < nBands; i++ )
         {
-            /*
-            ** If we don't have Crown fuels, but do have Ground fuels, we
-            ** have to 'fast forward'.
-            */
+            // If we don't have Crown fuels, but do have Ground fuels, we
+            // have to 'fast forward'.
             if( i == 5 && !bHaveCrownFuels && bHaveGroundFuels )
             {
                 CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 3340, SEEK_SET ));
             }
-            nTemp = (GInt32)padfMin[i];
+            nTemp = static_cast<GInt32>(padfMin[i]);
             CPL_LSBPTR32( &nTemp );
             CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
-            nTemp = (GInt32)padfMax[i];
+            nTemp = static_cast<GInt32>(padfMax[i]);
             CPL_LSBPTR32( &nTemp );
             CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
             if( bClassifyData )
             {
-                /*
-                ** These two arrays were swapped in their entirety above.
-                */
+                // These two arrays were swapped in their entirety above.
                 CPL_IGNORE_RET_VAL(VSIFWriteL( panFound + i, 4, 1, fp ));
-                CPL_IGNORE_RET_VAL(VSIFWriteL( panClasses + ( i * LCP_MAX_CLASSES ), 4, 100, fp ));
+                CPL_IGNORE_RET_VAL(
+                    VSIFWriteL(
+                        panClasses + ( i * LCP_MAX_CLASSES ), 4, 100, fp ));
             }
             else
             {
@@ -1470,41 +1471,39 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     {
         CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 4164, SEEK_SET ));
     }
-    CPLFree( reinterpret_cast<void *>( padfMin ) );
-    CPLFree( reinterpret_cast<void *>( padfMax ) );
-    CPLFree( reinterpret_cast<void *>( panFound ) );
-    CPLFree( reinterpret_cast<void *>( panClasses ) );
-
-    /*
-    ** Should be at one of 3 locations, 2104, 3340, or 4164.
-    */
+    CPLFree( padfMin );
+    CPLFree( padfMax );
+    CPLFree( panFound );
+    CPLFree( panClasses );
+
+    // Should be at one of 3 locations, 2104, 3340, or 4164.
     CPLAssert( VSIFTellL( fp ) == 2104  ||
                VSIFTellL( fp ) == 3340  ||
                VSIFTellL( fp ) == 4164 );
     CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 4164, SEEK_SET ));
 
     /* Image size */
-    nTemp = (GInt32)nXSize;
+    nTemp = static_cast<GInt32>(nXSize);
     CPL_LSBPTR32( &nTemp );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
-    nTemp = (GInt32)nYSize;
+    nTemp = static_cast<GInt32>(nYSize);
     CPL_LSBPTR32( &nTemp );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
 
-    /* X and Y boundaries */
-    /* max x */
+    // X and Y boundaries.
+    // Max x.
     double dfTemp = adfSrcGeoTransform[0] + adfSrcGeoTransform[1] * nXSize;
     CPL_LSBPTR64( &dfTemp );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
-    /* min x */
+    // Min x.
     dfTemp = adfSrcGeoTransform[0];
     CPL_LSBPTR64( &dfTemp );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
-    /* max y */
+    // Max y.
     dfTemp = adfSrcGeoTransform[3];
     CPL_LSBPTR64( &dfTemp );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
-    /* min y */
+    // Min y.
     dfTemp = adfSrcGeoTransform[3] + adfSrcGeoTransform[5] * nYSize;
     CPL_LSBPTR64( &dfTemp );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
@@ -1513,12 +1512,12 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
     CPL_LSBPTR32( &nTemp );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &nTemp, 4, 1, fp ));
 
-    /* Resolution */
-    /* x resolution */
+    // Resolution.
+    // X resolution.
     dfTemp = adfSrcGeoTransform[1];
     CPL_LSBPTR64( &dfTemp );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
-    /* y resolution */
+    // Y resolution.
     dfTemp = fabs( adfSrcGeoTransform[5] );
     CPL_LSBPTR64( &dfTemp );
     CPL_IGNORE_RET_VAL(VSIFWriteL( &dfTemp, 8, 1, fp ));
@@ -1528,7 +1527,7 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
 #endif
     CPL_IGNORE_RET_VAL(VSIFWriteL( panMetadata, 2, LCP_MAX_BANDS, fp ));
 
-    /* Write the source filenames */
+    // Write the source filenames.
     char **papszFileList = poSrcDS->GetFileList();
     if( papszFileList != NULL )
     {
@@ -1540,31 +1539,29 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
             }
             CPL_IGNORE_RET_VAL(VSIFWriteL( papszFileList[0], 1,
                         CPLStrnlen( papszFileList[0], LCP_MAX_PATH ), fp ));
-            CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 4244 + ( 256 * ( i+1 ) ), SEEK_SET ));
+            CPL_IGNORE_RET_VAL(
+                VSIFSeekL( fp, 4244 + ( 256 * ( i+1 ) ), SEEK_SET ));
         }
     }
-    /*
-    ** No file list, mem driver, etc.
-    */
+    // No file list, mem driver, etc.
     else
     {
         CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 6804, SEEK_SET ));
     }
     CSLDestroy( papszFileList );
-    /*
-    ** Should be at location 5524, 6292 or 6804.
-    */
+    // Should be at location 5524, 6292 or 6804.
     CPLAssert( VSIFTellL( fp ) == 5524 ||
                VSIFTellL( fp ) == 6292 ||
                VSIFTellL( fp ) == 6804 );
     CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 6804, SEEK_SET ));
 
-    /* Description */
-    CPL_IGNORE_RET_VAL(VSIFWriteL( pszDescription, 1, CPLStrnlen( pszDescription, LCP_MAX_DESC ),
-                fp ));
-    /*
-    ** Should be at or below location 7316, all done with the header.
-    */
+    // Description .
+    CPL_IGNORE_RET_VAL(
+        VSIFWriteL(
+            pszDescription, 1, CPLStrnlen( pszDescription, LCP_MAX_DESC ),
+            fp ));
+
+    // Should be at or below location 7316, all done with the header.
     CPLAssert( VSIFTellL( fp ) <= 7316 );
     CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 7316, SEEK_SET ));
 
@@ -1572,12 +1569,13 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
 /*      Loop over image, copying image data.                            */
 /* -------------------------------------------------------------------- */
 
-    GInt16 *panScanline = (GInt16 *)VSIMalloc3( 2, nBands, nXSize );
+    GInt16 *panScanline =
+        static_cast<GInt16 *>( VSIMalloc3( 2, nBands, nXSize ) );
 
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
-        VSIFree( reinterpret_cast<void *>( panScanline ) );
+        VSIFree( panScanline );
         return NULL;
     }
     for( int iLine = 0; iLine < nYSize; iLine++ )
@@ -1588,15 +1586,11 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
             eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
                                      panScanline + iBand, nXSize, 1, GDT_Int16,
                                      nBands * 2, nBands * nXSize * 2, NULL );
-            /* Not sure what to do here */
+            // Not sure what to do here.
             if( eErr != CE_None )
             {
-                CPLError( CE_Warning, CPLE_AppDefined, "Error reported in " \
+                CPLError( CE_Warning, CPLE_AppDefined, "Error reported in "
                                                        "RasterIO" );
-                /*
-                ** CPLError( eErr, CPLE_AppDefined, 
-                **           "Error reported in RasterIO" );
-                */
             }
         }
 #ifdef CPL_MSB
@@ -1604,7 +1598,8 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
 #endif
         CPL_IGNORE_RET_VAL(VSIFWriteL( panScanline, 2, nBands * nXSize, fp ));
 
-        if( !pfnProgress( iLine / (double)nYSize, NULL, pProgressData ) )
+        if( !pfnProgress( iLine / static_cast<double>(nYSize),
+                          NULL, pProgressData ) )
         {
             VSIFree( reinterpret_cast<void *>( panScanline ) );
             CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
@@ -1618,21 +1613,18 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
         return NULL;
     }
 
-    /*
-    ** Try to write projection file.  *Most* landfire data follows ESRI
-    **style projection files, so we use the same code as the AAIGrid driver.
-    */
-    const char  *pszOriginalProjection;
-
-    pszOriginalProjection = (char *)poSrcDS->GetProjectionRef();
+    // Try to write projection file.  *Most* landfire data follows ESRI
+    // style projection files, so we use the same code as the AAIGrid driver.
+    const char *pszOriginalProjection = poSrcDS->GetProjectionRef();
     if( !EQUAL( pszOriginalProjection, "" ) )
     {
-        OGRSpatialReference     oSRS;
+        OGRSpatialReference oSRS;
 
-        char *pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
-        char *pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
+        char * const pszDirname = CPLStrdup( CPLGetPath(pszFilename) );
+        char * const pszBasename = CPLStrdup( CPLGetBasename(pszFilename) );
 
-        char *pszPrjFilename = CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
+        char *pszPrjFilename =
+            CPLStrdup( CPLFormFilename( pszDirname, pszBasename, "prj" ) );
         fp = VSIFOpenL( pszPrjFilename, "wt" );
         if (fp != NULL)
         {
@@ -1640,7 +1632,9 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
             oSRS.morphToESRI();
             char *pszESRIProjection = NULL;
             oSRS.exportToWkt( &pszESRIProjection );
-            CPL_IGNORE_RET_VAL(VSIFWriteL( pszESRIProjection, 1, strlen(pszESRIProjection), fp ));
+            CPL_IGNORE_RET_VAL(
+                VSIFWriteL( pszESRIProjection, 1,
+                            strlen(pszESRIProjection), fp ) );
 
             CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             CPLFree( pszESRIProjection );
@@ -1654,7 +1648,7 @@ GDALDataset *LCPDataset::CreateCopy( const char * pszFilename,
         CPLFree( pszBasename );
         CPLFree( pszPrjFilename );
     }
-    return (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
+    return static_cast<GDALDataset *>( GDALOpen( pszFilename, GA_ReadOnly ) );
 }
 
 /************************************************************************/
@@ -1736,8 +1730,8 @@ void GDALRegister_LCP()
 "       <Value>MG_PER_HECTARE_X_10</Value>"
 "       <Value>TONS_PER_ACRE_X_10</Value>"
 "   </Option>"
-/* I don't think we need to override this, but maybe? */
-/*"   <Option name='CWD_OPTION' type='boolean' default='FALSE' description='Override logic for setting the coarse woody presence'/>" */
+// Kyle does not think we need to override this, but maybe?
+// "   <Option name='CWD_OPTION' type='boolean' default='FALSE' description='Override logic for setting the coarse woody presence'/>" */
 "   <Option name='CALCULATE_STATS' type='boolean' default='YES' description='Write the stats to the lcp'/>"
 "   <Option name='CLASSIFY_DATA' type='boolean' default='YES' description='Write the stats to the lcp'/>"
 "   <Option name='LINEAR_UNIT' type='string-select' default='SET_FROM_SRS' description='Set the linear units in the lcp'>"
diff --git a/frmts/raw/loslasdataset.cpp b/frmts/raw/loslasdataset.cpp
index 632feae..9698c85 100644
--- a/frmts/raw/loslasdataset.cpp
+++ b/frmts/raw/loslasdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: loslasdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  Horizontal Datum Formats
  * Purpose:  Implementation of NOAA/NADCON los/las datum shift format.
@@ -33,7 +32,7 @@
 #include "ogr_srs_api.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: loslasdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
+CPL_CVSID("$Id: loslasdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /**
 
@@ -85,8 +84,8 @@ class LOSLASDataset : public RawDataset
                 LOSLASDataset();
     virtual ~LOSLASDataset();
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef();
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -102,7 +101,10 @@ class LOSLASDataset : public RawDataset
 /*                             LOSLASDataset()                          */
 /************************************************************************/
 
-LOSLASDataset::LOSLASDataset() : fpImage(NULL), nRecordLength(0) { }
+LOSLASDataset::LOSLASDataset() : fpImage(NULL), nRecordLength(0)
+{
+    memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
+}
 
 /************************************************************************/
 /*                            ~LOSLASDataset()                          */
@@ -231,7 +233,7 @@ GDALDataset *LOSLASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/raw/makefile.vc b/frmts/raw/makefile.vc
index 189209f..6dd4cfb 100644
--- a/frmts/raw/makefile.vc
+++ b/frmts/raw/makefile.vc
@@ -7,7 +7,8 @@ OBJ	=	rawdataset.obj ehdrdataset.obj pauxdataset.obj doq1dataset.obj\
 		ndfdataset.obj dipxdataset.obj genbindataset.obj \
 		lcpdataset.obj eirdataset.obj gtxdataset.obj loslasdataset.obj \
 		ntv2dataset.obj ace2dataset.obj snodasdataset.obj \
-		ctable2dataset.obj krodataset.obj roipacdataset.obj iscedataset.obj
+		ctable2dataset.obj krodataset.obj roipacdataset.obj iscedataset.obj \
+		rrasterdataset.obj
 
 GDAL_ROOT	=	..\..
 
diff --git a/frmts/raw/mffdataset.cpp b/frmts/raw/mffdataset.cpp
index db31950..0ec982b 100644
--- a/frmts/raw/mffdataset.cpp
+++ b/frmts/raw/mffdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: mffdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  GView
  * Purpose:  Implementation of Atlantis MFF Support
@@ -28,25 +27,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "rawdataset.h"
+#include "atlsci_spheroid.h"
 #include "cpl_string.h"
 #include "gdal_frmts.h"
 #include "ogr_spatialref.h"
-#include "atlsci_spheroid.h"
+#include "rawdataset.h"
 
 #include <cctype>
+#include <cmath>
 #include <algorithm>
 
-CPL_CVSID("$Id: mffdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
+CPL_CVSID("$Id: mffdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 enum {
   MFFPRJ_NONE,
   MFFPRJ_LL,
   MFFPRJ_UTM,
   MFFPRJ_UNRECOGNIZED
-} ;
+};
 
-static int         GetMFFProjectionType(const char * pszNewProjection);
+static int GetMFFProjectionType(const char * pszNewProjection);
 
 /************************************************************************/
 /* ==================================================================== */
@@ -62,6 +62,7 @@ class MFFDataset : public RawDataset
     char *pszProjection;
     char *pszGCPProjection;
     double adfGeoTransform[6];
+    char**      m_papszFileList;
 
     void        ScanForGCPs();
     void        ScanForProjectionInfo();
@@ -74,12 +75,14 @@ class MFFDataset : public RawDataset
 
     VSILFILE        **pafpBandFiles;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual char** GetFileList() override;
+
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
-    virtual const char *GetProjectionRef();
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
@@ -90,7 +93,6 @@ class MFFDataset : public RawDataset
                                     int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress,
                                     void * pProgressData );
-
 };
 
 /************************************************************************/
@@ -103,8 +105,8 @@ class MFFTiledBand : public GDALRasterBand
 {
     friend class MFFDataset;
 
-    VSILFILE        *fpRaw;
-    int         bNative;
+    VSILFILE      *fpRaw;
+    bool           bNative;
 
   public:
 
@@ -112,10 +114,9 @@ class MFFTiledBand : public GDALRasterBand
                                  GDALDataType, int );
     virtual ~MFFTiledBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                            MFFTiledBand()                            */
 /************************************************************************/
@@ -124,7 +125,7 @@ MFFTiledBand::MFFTiledBand( MFFDataset *poDSIn, int nBandIn, VSILFILE *fp,
                             int nTileXSize, int nTileYSize,
                             GDALDataType eDataTypeIn, int bNativeIn ) :
     fpRaw(fp),
-    bNative(bNativeIn)
+    bNative(CPL_TO_BOOL(bNativeIn))
 {
     poDS = poDSIn;
     nBand = nBandIn;
@@ -144,11 +145,10 @@ MFFTiledBand::~MFFTiledBand()
 {
     if( VSIFCloseL( fpRaw ) != 0 )
     {
-        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+        CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
     }
 }
 
-
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
@@ -161,7 +161,8 @@ CPLErr MFFTiledBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     const int nWordSize = GDALGetDataTypeSize( eDataType ) / 8;
     const int nBlockSize = nWordSize * nBlockXSize * nBlockYSize;
 
-    const long nOffset = nBlockSize * (nBlockXOff + nBlockYOff*nTilesPerRow);
+    const vsi_l_offset nOffset = nBlockSize * (nBlockXOff +
+                        static_cast<vsi_l_offset>(nBlockYOff)*nTilesPerRow);
 
     if( VSIFSeekL( fpRaw, nOffset, SEEK_SET ) == -1
         || VSIFReadL( pImage, 1, nBlockSize, fpRaw ) < 1 )
@@ -242,6 +243,7 @@ MFFDataset::MFFDataset() :
     pasGCPList(NULL),
     pszProjection(CPLStrdup("")),
     pszGCPProjection(CPLStrdup("")),
+    m_papszFileList(NULL),
     papszHdrLines(NULL),
     pafpBandFiles(NULL)
 {
@@ -270,7 +272,7 @@ MFFDataset::~MFFDataset()
             {
                 if( VSIFCloseL( pafpBandFiles[i] ) != 0 )
                 {
-                    CPLError(CE_Failure, CPLE_FileIO, "I/O error");
+                    CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
                 }
             }
         }
@@ -284,7 +286,18 @@ MFFDataset::~MFFDataset()
     CPLFree( pasGCPList );
     CPLFree( pszProjection );
     CPLFree( pszGCPProjection );
+    CSLDestroy( m_papszFileList );
+}
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
 
+char** MFFDataset::GetFileList()
+{
+    char** papszFileList = RawDataset::GetFileList();
+    papszFileList = CSLInsertStrings(papszFileList, -1, m_papszFileList);
+    return papszFileList;
 }
 
 /************************************************************************/
@@ -356,7 +369,7 @@ void MFFDataset::ScanForGCPs()
         return;
 
     nGCPCount = 0;
-    pasGCPList = reinterpret_cast<GDAL_GCP *>(
+    pasGCPList = static_cast<GDAL_GCP *>(
         VSICalloc( sizeof(GDAL_GCP) , 5 + NUM_GCPS ) );
     if (pasGCPList == NULL)
         return;
@@ -364,7 +377,8 @@ void MFFDataset::ScanForGCPs()
     for( int nCorner = 0; nCorner < 5; nCorner++ )
     {
         const char * pszBase=NULL;
-        double       dfRasterX=0.0, dfRasterY=0.0;
+        double dfRasterX = 0.0;
+        double dfRasterY = 0.0;
 
         if( nCorner == 0 )
         {
@@ -397,7 +411,8 @@ void MFFDataset::ScanForGCPs()
             pszBase = "CENTRE";
         }
 
-        char szLatName[40], szLongName[40];
+        char szLatName[40] = { '\0' };
+        char szLongName[40] = { '\0' };
         snprintf( szLatName, sizeof(szLatName), "%s_LATITUDE", pszBase );
         snprintf( szLongName, sizeof(szLongName), "%s_LONGITUDE", pszBase );
 
@@ -431,7 +446,7 @@ void MFFDataset::ScanForGCPs()
 /* -------------------------------------------------------------------- */
     for( int i = 0; i < NUM_GCPS; i++ )
     {
-        char szName[25];
+        char szName[25] = { '\0' };
         snprintf( szName, sizeof(szName), "GCP%d", i+1 );
         if( CSLFetchNameValue( papszHdrLines, szName ) == NULL )
             continue;
@@ -482,8 +497,9 @@ void MFFDataset::ScanForProjectionInfo()
     }
     else if ((!EQUAL(pszProjName,"utm")) && (!EQUAL(pszProjName,"ll")))
     {
-        CPLError(CE_Warning,CPLE_AppDefined,
-                 "Warning- only utm and lat/long projections are currently supported.");
+        CPLError(
+            CE_Warning,CPLE_AppDefined,
+            "Only utm and lat/long projections are currently supported." );
         CPLFree( pszProjection );
         CPLFree( pszGCPProjection );
         pszProjection=CPLStrdup("");
@@ -499,9 +515,10 @@ void MFFDataset::ScanForProjectionInfo()
 
         if (pszOriginLong == NULL)
         {
-            /* If origin not specified, assume 0.0 */
-            CPLError(CE_Warning,CPLE_AppDefined,
-                   "Warning- no projection origin longitude specified.  Assuming 0.0.");
+          // If origin not specified, assume 0.0.
+            CPLError(
+                CE_Warning,CPLE_AppDefined,
+                "No projection origin longitude specified.  Assuming 0.0." );
             nZone = 31;
         }
         else
@@ -523,8 +540,9 @@ void MFFDataset::ScanForProjectionInfo()
 
     if (pszSpheroidName == NULL)
     {
-        CPLError(CE_Warning,CPLE_AppDefined,
-            "Warning- unspecified ellipsoid.  Using wgs-84 parameters.\n");
+        CPLError(
+            CE_Warning, CPLE_AppDefined,
+            "Unspecified ellipsoid.  Using wgs-84 parameters.\n" );
 
         oProj.SetWellKnownGeogCS( "WGS84" );
         oLL.SetWellKnownGeogCS( "WGS84" );
@@ -533,14 +551,14 @@ void MFFDataset::ScanForProjectionInfo()
     {
       if (mffEllipsoids->SpheroidInList(pszSpheroidName))
       {
-         oProj.SetGeogCS( "unknown","unknown",pszSpheroidName,
-                         mffEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
-                         mffEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
-                       );
-         oLL.SetGeogCS( "unknown","unknown",pszSpheroidName,
-                         mffEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
-                         mffEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName)
-                      );
+         oProj.SetGeogCS(
+             "unknown","unknown",pszSpheroidName,
+             mffEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
+             mffEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName) );
+         oLL.SetGeogCS(
+             "unknown","unknown",pszSpheroidName,
+             mffEllipsoids->GetSpheroidEqRadius(pszSpheroidName),
+             mffEllipsoids->GetSpheroidInverseFlattening(pszSpheroidName) );
       }
       else if (EQUAL(pszSpheroidName,"USER_DEFINED"))
       {
@@ -559,18 +577,21 @@ void MFFDataset::ScanForProjectionInfo()
           }
           else
           {
-              CPLError(CE_Warning,CPLE_AppDefined,
-                "Warning- radii not specified for user-defined ellipsoid. Using wgs-84 parameters. \n");
+              CPLError(
+                  CE_Warning, CPLE_AppDefined,
+                  "Radii not specified for user-defined ellipsoid. "
+                  "Using wgs-84 parameters.");
               oProj.SetWellKnownGeogCS( "WGS84" );
               oLL.SetWellKnownGeogCS( "WGS84" );
           }
       }
       else
       {
-         CPLError(CE_Warning,CPLE_AppDefined,
-            "Warning- unrecognized ellipsoid.  Using wgs-84 parameters.\n");
-         oProj.SetWellKnownGeogCS( "WGS84" );
-         oLL.SetWellKnownGeogCS( "WGS84" );
+          CPLError(
+              CE_Warning, CPLE_AppDefined,
+              "Unrecognized ellipsoid.  Using wgs-84 parameters.");
+          oProj.SetWellKnownGeogCS( "WGS84" );
+          oLL.SetWellKnownGeogCS( "WGS84" );
       }
     }
 
@@ -582,7 +603,10 @@ void MFFDataset::ScanForProjectionInfo()
 
     if (EQUAL(pszProjName,"LL"))
     {
-        transform_ok = CPL_TO_BOOL(GDALGCPsToGeoTransform(nGCPCount,pasGCPList,adfGeoTransform,0));
+        transform_ok =
+            CPL_TO_BOOL(
+                GDALGCPsToGeoTransform(
+                    nGCPCount, pasGCPList, adfGeoTransform, 0 ) );
     }
     else
     {
@@ -595,15 +619,20 @@ void MFFDataset::ScanForProjectionInfo()
             bSuccess = FALSE;
         }
 
-        double *dfPrjX = reinterpret_cast<double *>( CPLMalloc(nGCPCount*sizeof(double)) );
-        double *dfPrjY = reinterpret_cast<double *>( CPLMalloc(nGCPCount*sizeof(double)) );
+        double *dfPrjX =
+            static_cast<double *>( CPLMalloc(nGCPCount*sizeof(double)) );
+        double *dfPrjY =
+            static_cast<double *>( CPLMalloc(nGCPCount*sizeof(double)) );
 
         for( int gcp_index = 0; gcp_index < nGCPCount; gcp_index++ )
         {
             dfPrjX[gcp_index] = pasGCPList[gcp_index].dfGCPX;
             dfPrjY[gcp_index] = pasGCPList[gcp_index].dfGCPY;
 
-            if( bSuccess && !poTransform->Transform( 1, &(dfPrjX[gcp_index]), &(dfPrjY[gcp_index]) ) )
+            if( bSuccess &&
+                !poTransform->Transform( 1,
+                                         &(dfPrjX[gcp_index]),
+                                         &(dfPrjY[gcp_index]) ) )
                 bSuccess = FALSE;
         }
 
@@ -613,10 +642,11 @@ void MFFDataset::ScanForProjectionInfo()
             {
                 pasGCPList[gcp_index].dfGCPX = dfPrjX[gcp_index];
                 pasGCPList[gcp_index].dfGCPY = dfPrjY[gcp_index];
-
             }
-            transform_ok = CPL_TO_BOOL(GDALGCPsToGeoTransform(nGCPCount,pasGCPList,adfGeoTransform,0));
-
+            transform_ok =
+                CPL_TO_BOOL(
+                    GDALGCPsToGeoTransform(
+                        nGCPCount, pasGCPList, adfGeoTransform, 0 ) );
         }
 
         if (poTransform)
@@ -624,7 +654,6 @@ void MFFDataset::ScanForProjectionInfo()
 
         CPLFree(dfPrjX);
         CPLFree(dfPrjY);
-
     }
 
     CPLFree( pszProjection );
@@ -648,10 +677,8 @@ void MFFDataset::ScanForProjectionInfo()
     }
 
     delete mffEllipsoids;
-
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -665,7 +692,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 17 || poOpenInfo->fpL == NULL )
         return NULL;
 
-    if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"hdr") )
+    if( !EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "hdr") )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -681,7 +708,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
     for( int i = 0; papszHdrLines[i] != NULL; i++ )
     {
         int iDst = 0;
-        char     *pszLine = papszHdrLines[i];
+        char *pszLine = papszHdrLines[i];
 
         for( int iSrc=0; pszLine[iSrc] != '\0'; iSrc++ )
         {
@@ -697,7 +724,8 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Verify it is an MFF file.                                       */
 /* -------------------------------------------------------------------- */
     if( CSLFetchNameValue( papszHdrLines, "IMAGE_FILE_FORMAT" ) != NULL
-        && !EQUAL(CSLFetchNameValue(papszHdrLines,"IMAGE_FILE_FORMAT"),"MFF") )
+        && !EQUAL(CSLFetchNameValue(papszHdrLines, "IMAGE_FILE_FORMAT"),
+                  "MFF") )
     {
         CSLDestroy( papszHdrLines );
         return NULL;
@@ -732,8 +760,10 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
     }
     else
     {
-        poDS->nRasterXSize = atoi(CSLFetchNameValue(papszHdrLines,"LINE_SAMPLES"));
-        poDS->nRasterYSize = atoi(CSLFetchNameValue(papszHdrLines,"IMAGE_LINES"));
+        poDS->nRasterXSize =
+            atoi(CSLFetchNameValue(papszHdrLines, "LINE_SAMPLES"));
+        poDS->nRasterYSize =
+            atoi(CSLFetchNameValue(papszHdrLines, "IMAGE_LINES"));
     }
 
     if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
@@ -742,13 +772,13 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    int bNative = TRUE;
+    bool bNative = true;
     if( CSLFetchNameValue( papszHdrLines, "BYTE_ORDER" ) != NULL )
     {
 #ifdef CPL_MSB
-        bNative = EQUAL(CSLFetchNameValue(papszHdrLines,"BYTE_ORDER"),"MSB");
+        bNative = EQUAL(CSLFetchNameValue(papszHdrLines, "BYTE_ORDER"), "MSB");
 #else
-        bNative = EQUAL(CSLFetchNameValue(papszHdrLines,"BYTE_ORDER"),"LSB");
+        bNative = EQUAL(CSLFetchNameValue(papszHdrLines, "BYTE_ORDER"), "LSB");
 #endif
     }
 
@@ -758,7 +788,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
     int nTileXSize = 0;
     int nTileYSize = 0;
     const char *pszRefinedType = CSLFetchNameValue(papszHdrLines, "type" );
-    const bool bTiled = CSLFetchNameValue(papszHdrLines,"no_rows") != NULL;
+    const bool bTiled = CSLFetchNameValue(papszHdrLines, "no_rows") != NULL;
 
     if( bTiled )
     {
@@ -767,7 +797,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
                 atoi(CSLFetchNameValue(papszHdrLines,"tile_size_rows"));
         if( CSLFetchNameValue(papszHdrLines,"tile_size_columns") )
             nTileXSize =
-                atoi(CSLFetchNameValue(papszHdrLines,"tile_size_columns"));
+                atoi(CSLFetchNameValue(papszHdrLines,"tile_size_columns") );
 
         if (nTileXSize <= 0 || nTileYSize <= 0 ||
             poDS->nRasterXSize-1 > INT_MAX - nTileXSize ||
@@ -781,8 +811,9 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Read the directory to find matching band files.                 */
 /* -------------------------------------------------------------------- */
-    char *pszTargetPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-    char *pszTargetBase = CPLStrdup(CPLGetBasename( poOpenInfo->pszFilename ));
+    char * const pszTargetPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
+    char * const pszTargetBase =
+        CPLStrdup(CPLGetBasename( poOpenInfo->pszFilename ));
     char **papszDirFiles = VSIReadDir( CPLGetPath( poOpenInfo->pszFilename ) );
     if( papszDirFiles == NULL )
     {
@@ -799,7 +830,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 
         /* Find the next raw band file. */
 
-        int i = 0;
+        int i = 0;  // Used after for.
         for( ; papszDirFiles[i] != NULL; i++ )
         {
             if( !EQUAL(CPLGetBasename(papszDirFiles[i]),pszTargetBase) )
@@ -820,7 +851,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         const char *pszRawFilename = CPLFormFilename(pszTargetPath,
                                                      papszDirFiles[i], NULL );
 
-        VSILFILE *fpRaw;
+        VSILFILE *fpRaw = NULL;
         if( poOpenInfo->eAccess == GA_Update )
             fpRaw = VSIFOpenL( pszRawFilename, "rb+" );
         else
@@ -829,52 +860,57 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         if( fpRaw == NULL )
         {
             CPLError( CE_Warning, CPLE_OpenFailed,
-                      "Unable to open %s ... skipping.\n",
+                      "Unable to open %s ... skipping.",
                       pszRawFilename );
             nSkipped++;
             continue;
         }
+        poDS->m_papszFileList = CSLAddString(poDS->m_papszFileList, pszRawFilename);
 
-        GDALDataType eDataType;
+        GDALDataType eDataType = GDT_Unknown;
         pszExtension = CPLGetExtension(papszDirFiles[i]);
         if( pszRefinedType != NULL )
         {
-            if( EQUAL(pszRefinedType,"C*4") )
+            if( EQUAL(pszRefinedType, "C*4") )
                 eDataType = GDT_CFloat32;
-            else if( EQUAL(pszRefinedType,"C*8") )
+            else if( EQUAL(pszRefinedType, "C*8") )
                 eDataType = GDT_CFloat64;
-            else if( EQUAL(pszRefinedType,"R*4") )
+            else if( EQUAL(pszRefinedType, "R*4") )
                 eDataType = GDT_Float32;
-            else if( EQUAL(pszRefinedType,"R*8") )
+            else if( EQUAL(pszRefinedType, "R*8") )
                 eDataType = GDT_Float64;
-            else if( EQUAL(pszRefinedType,"I*1") )
+            else if( EQUAL(pszRefinedType, "I*1") )
                 eDataType = GDT_Byte;
-            else if( EQUAL(pszRefinedType,"I*2") )
+            else if( EQUAL(pszRefinedType, "I*2") )
                 eDataType = GDT_Int16;
-            else if( EQUAL(pszRefinedType,"I*4") )
+            else if( EQUAL(pszRefinedType, "I*4") )
                 eDataType = GDT_Int32;
-            else if( EQUAL(pszRefinedType,"U*2") )
+            else if( EQUAL(pszRefinedType, "U*2") )
                 eDataType = GDT_UInt16;
-            else if( EQUAL(pszRefinedType,"U*4") )
+            else if( EQUAL(pszRefinedType, "U*4") )
                 eDataType = GDT_UInt32;
-            else if( EQUAL(pszRefinedType,"J*1") )
+            else if( EQUAL(pszRefinedType, "J*1") )
             {
-                CPLError( CE_Warning, CPLE_OpenFailed,
-                        "Unable to open band %d because type J*1 is not handled ... skipping.\n",
-                         nRawBand + 1 );
+                CPLError(
+                    CE_Warning, CPLE_OpenFailed,
+                    "Unable to open band %d because type J*1 is not handled. "
+                    "Skipping.",
+                    nRawBand + 1 );
                 nSkipped++;
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fpRaw));
-                continue; /* we don't support 1 byte complex */
+                continue;  // Does not support 1 byte complex.
             }
-            else if( EQUAL(pszRefinedType,"J*2") )
+            else if( EQUAL(pszRefinedType, "J*2") )
                 eDataType = GDT_CInt16;
-            else if( EQUAL(pszRefinedType,"K*4") )
+            else if( EQUAL(pszRefinedType, "K*4") )
                 eDataType = GDT_CInt32;
             else
             {
-                CPLError( CE_Warning, CPLE_OpenFailed,
-                        "Unable to open band %d because type %s is not handled ... skipping.\n",
-                         nRawBand + 1, pszRefinedType );
+                CPLError(
+                    CE_Warning, CPLE_OpenFailed,
+                    "Unable to open band %d because type %s is not handled. "
+                    "Skipping.\n",
+                    nRawBand + 1, pszRefinedType );
                 nSkipped++;
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fpRaw));
                 continue;
@@ -904,7 +940,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         {
             CPLError( CE_Warning, CPLE_OpenFailed,
                       "Unable to open band %d because extension %s is not "
-                      "handled ... skipping.\n",
+                      "handled.  Skipping.",
                       nRawBand + 1, pszExtension );
             nSkipped++;
             CPL_IGNORE_RET_VAL(VSIFCloseL(fpRaw));
@@ -927,7 +963,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
             if (poDS->GetRasterXSize() > INT_MAX / nPixelOffset)
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                          "Int overflow occurred... skipping");
+                          "Int overflow occurred... skipping" );
                 nSkipped++;
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fpRaw));
                 continue;
@@ -954,8 +990,8 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         if( nSkipped > 0 && poOpenInfo->eAccess )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Failed to open %d files that were apparently bands.\n"
-                      "Perhaps this dataset is readonly?\n",
+                      "Failed to open %d files that were apparently bands.  "
+                      "Perhaps this dataset is readonly?",
                       nSkipped );
             delete poDS;
             return NULL;
@@ -963,7 +999,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
         else
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                      "MFF header file read successfully, but no bands\n"
+                      "MFF header file read successfully, but no bands "
                       "were successfully found and opened." );
             delete poDS;
             return NULL;
@@ -976,7 +1012,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     for( int i = 0; papszHdrLines[i] != NULL; i++ )
     {
-        char       *pszName;
+        char *pszName = NULL;
 
         const char *pszValue = CPLParseNameValue(papszHdrLines[i], &pszName);
         if( pszName == NULL || pszValue == NULL )
@@ -1017,7 +1053,7 @@ GDALDataset *MFFDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 int GetMFFProjectionType(const char *pszNewProjection)
@@ -1030,25 +1066,27 @@ int GetMFFProjectionType(const char *pszNewProjection)
       {
           return MFFPRJ_UNRECOGNIZED;
       }
-      else if (EQUAL(pszNewProjection,""))
+      else if( EQUAL(pszNewProjection,"") )
       {
           return MFFPRJ_NONE;
       }
       else
       {
-             if ((oSRS.GetAttrValue("PROJECTION") != NULL) &&
-                 (EQUAL(oSRS.GetAttrValue("PROJECTION"),SRS_PT_TRANSVERSE_MERCATOR)))
-             {
-               return MFFPRJ_UTM;
-             }
-             else if ((oSRS.GetAttrValue("PROJECTION") == NULL) && (oSRS.IsGeographic()))
-             {
-                  return MFFPRJ_LL;
-             }
-             else
-             {
-                  return MFFPRJ_UNRECOGNIZED;
-             }
+          if( oSRS.GetAttrValue("PROJECTION") != NULL &&
+              EQUAL(oSRS.GetAttrValue("PROJECTION"),
+                    SRS_PT_TRANSVERSE_MERCATOR) )
+          {
+              return MFFPRJ_UTM;
+          }
+          else if( oSRS.GetAttrValue("PROJECTION") == NULL &&
+                   oSRS.IsGeographic() )
+          {
+              return MFFPRJ_LL;
+          }
+          else
+          {
+              return MFFPRJ_UNRECOGNIZED;
+          }
       }
 }
 
@@ -1065,10 +1103,10 @@ GDALDataset *MFFDataset::Create( const char * pszFilenameIn,
 /* -------------------------------------------------------------------- */
 /*      Verify input options.                                           */
 /* -------------------------------------------------------------------- */
-    if (nBands <= 0)
+    if( nBands <= 0 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "MFF driver does not support %d bands.\n", nBands);
+                  "MFF driver does not support %d bands.", nBands );
         return NULL;
     }
 
@@ -1087,7 +1125,7 @@ GDALDataset *MFFDataset::Create( const char * pszFilenameIn,
 /*      Establish the base filename (path+filename, less extension).    */
 /* -------------------------------------------------------------------- */
     char *pszBaseFilename
-        = reinterpret_cast<char *>( CPLMalloc( strlen( pszFilenameIn ) + 5 ) );
+        = static_cast<char *>( CPLMalloc( strlen( pszFilenameIn ) + 5 ) );
     strcpy( pszBaseFilename, pszFilenameIn );
 
     for( int i = static_cast<int>(strlen(pszBaseFilename))-1; i > 0; i-- )
@@ -1137,18 +1175,18 @@ GDALDataset *MFFDataset::Create( const char * pszFilenameIn,
 /* -------------------------------------------------------------------- */
     for( int iBand = 0; bOK && iBand < nBands; iBand++ )
     {
-        char       szExtension[4];
+        char szExtension[4] = { '\0' };
 
         if( eType == GDT_Byte )
-            snprintf( szExtension, sizeof(szExtension), "b%02d", iBand );
+            CPLsnprintf( szExtension, sizeof(szExtension), "b%02d", iBand );
         else if( eType == GDT_UInt16 )
-            snprintf( szExtension, sizeof(szExtension), "i%02d", iBand );
+            CPLsnprintf( szExtension, sizeof(szExtension), "i%02d", iBand );
         else if( eType == GDT_Float32 )
-            snprintf( szExtension, sizeof(szExtension),  "r%02d", iBand );
+            CPLsnprintf( szExtension, sizeof(szExtension),  "r%02d", iBand );
         else if( eType == GDT_CInt16 )
-            snprintf( szExtension, sizeof(szExtension), "j%02d", iBand );
+            CPLsnprintf( szExtension, sizeof(szExtension), "j%02d", iBand );
         else if( eType == GDT_CFloat32 )
-            snprintf( szExtension, sizeof(szExtension), "x%02d", iBand );
+            CPLsnprintf( szExtension, sizeof(szExtension), "x%02d", iBand );
 
         pszFilename = CPLFormFilename( NULL, pszBaseFilename, szExtension );
         fp = VSIFOpenL( pszFilename, "wb" );
@@ -1160,8 +1198,7 @@ GDALDataset *MFFDataset::Create( const char * pszFilenameIn,
             return NULL;
         }
 
-        bOK &= VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "" ) ),
-                    1, 1, fp ) == 1;
+        bOK &= VSIFWriteL( "", 1, 1, fp ) == 1;
         if( VSIFCloseL( fp ) != 0 )
             bOK = false;
     }
@@ -1176,7 +1213,7 @@ GDALDataset *MFFDataset::Create( const char * pszFilenameIn,
 /*      Open the dataset normally.                                      */
 /* -------------------------------------------------------------------- */
     strcat( pszBaseFilename, ".hdr" );
-    GDALDataset *poDS = reinterpret_cast<GDALDataset *>(
+    GDALDataset *poDS = static_cast<GDALDataset *>(
         GDALOpen( pszBaseFilename, GA_Update ) );
     CPLFree( pszBaseFilename );
 
@@ -1190,7 +1227,7 @@ GDALDataset *MFFDataset::Create( const char * pszFilenameIn,
 GDALDataset *
 MFFDataset::CreateCopy( const char * pszFilename,
                         GDALDataset *poSrcDS,
-                        CPL_UNUSED int bStrict,
+                        int /* bStrict */,
                         char ** papszOptions,
                         GDALProgressFunc pfnProgress,
                         void * pProgressData )
@@ -1199,7 +1236,7 @@ MFFDataset::CreateCopy( const char * pszFilename,
     if (nBands == 0)
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "MFF driver does not support source dataset with zero band.\n");
+                  "MFF driver does not support source dataset with zero band.");
         return NULL;
     }
 
@@ -1207,8 +1244,8 @@ MFFDataset::CreateCopy( const char * pszFilename,
     if( !pfnProgress( 0.0, NULL, pProgressData ) )
         return NULL;
 
-    /* check that other bands match type- sets type */
-    /* to unknown if they differ.                  */
+    // Check that other bands match type- sets type
+    // to unknown if they differ.
     for( int iBand = 1; iBand < poSrcDS->GetRasterCount(); iBand++ )
      {
          GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
@@ -1227,7 +1264,6 @@ MFFDataset::CreateCopy( const char * pszFilename,
 
     CSLDestroy(newpapszOptions);
 
-    /* Check that Create worked- return Null if it didn't */
     if (poDS == NULL)
         return NULL;
 
@@ -1237,7 +1273,8 @@ MFFDataset::CreateCopy( const char * pszFilename,
     const int nXSize = poDS->GetRasterXSize();
     const int nYSize = poDS->GetRasterYSize();
 
-    int nBlockXSize, nBlockYSize;
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
     poDS->GetRasterBand(1)->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
     const int nBlockTotal = ((nXSize + nBlockXSize - 1) / nBlockXSize)
@@ -1250,8 +1287,8 @@ MFFDataset::CreateCopy( const char * pszFilename,
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
         GDALRasterBand *poDstBand = poDS->GetRasterBand( iBand+1 );
 
-        void *pData = CPLMalloc(nBlockXSize * nBlockYSize
-                                * GDALGetDataTypeSize(eType) / 8);
+        void *pData = CPLMalloc(
+            nBlockXSize * nBlockYSize * GDALGetDataTypeSizeBytes(eType) );
 
         for( int iYOffset = 0; iYOffset < nYSize; iYOffset += nBlockYSize )
         {
@@ -1266,7 +1303,7 @@ MFFDataset::CreateCopy( const char * pszFilename,
                     delete poDS;
                     CPLFree( pData );
 
-                    GDALDriver *poMFFDriver = reinterpret_cast<GDALDriver *>(
+                    GDALDriver *poMFFDriver = static_cast<GDALDriver *>(
                         GDALGetDriverByName( "MFF" ) );
                     poMFFDriver->Delete( pszFilename );
                     return NULL;
@@ -1311,8 +1348,8 @@ MFFDataset::CreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Establish the base filename (path+filename, less extension).    */
 /* -------------------------------------------------------------------- */
-    char *pszBaseFilename = reinterpret_cast<char *>(
-        CPLMalloc(strlen(pszFilename)+5) );
+    char *pszBaseFilename = static_cast<char *>(
+        CPLMalloc( strlen(pszFilename)+5) );
     strcpy( pszBaseFilename, pszFilename );
 
     for( int i = static_cast<int>(strlen(pszBaseFilename))-1; i > 0; i-- )
@@ -1342,54 +1379,65 @@ MFFDataset::CreateCopy( const char * pszFilename,
     /* MFF requires corner and center gcps */
     bool georef_created = false;
 
-    double *padfTiepoints = reinterpret_cast<double *>(
+    double *padfTiepoints = static_cast<double *>(
         CPLMalloc( 2 * sizeof(double) * 5 ) );
 
     const int src_prj = GetMFFProjectionType(poSrcDS->GetProjectionRef());
 
     if ((src_prj != MFFPRJ_NONE) && (src_prj != MFFPRJ_UNRECOGNIZED))
     {
-      double *tempGeoTransform = reinterpret_cast<double *>(
+      double *tempGeoTransform = static_cast<double *>(
           CPLMalloc( 6 * sizeof(double) ) );
 
-      if (( poSrcDS->GetGeoTransform( tempGeoTransform ) == CE_None)
+      if( ( poSrcDS->GetGeoTransform( tempGeoTransform ) == CE_None)
           && (tempGeoTransform[0] != 0.0 || tempGeoTransform[1] != 1.0
           || tempGeoTransform[2] != 0.0 || tempGeoTransform[3] != 0.0
-              || tempGeoTransform[4] != 0.0 || ABS(tempGeoTransform[5]) != 1.0 ))
+              || tempGeoTransform[4] != 0.0
+              || std::abs(tempGeoTransform[5]) != 1.0 ) )
       {
-          padfTiepoints[0]=tempGeoTransform[0] + tempGeoTransform[1]*0.5 +\
-                           tempGeoTransform[2]*0.5;
-
-          padfTiepoints[1]=tempGeoTransform[3] + tempGeoTransform[4]*0.5 +\
-                           tempGeoTransform[5]*0.5;
-
-          padfTiepoints[2]=tempGeoTransform[0] + tempGeoTransform[2]*0.5 +\
-                           tempGeoTransform[1]*(poSrcDS->GetRasterXSize()-0.5);
-
-          padfTiepoints[3]=tempGeoTransform[3] + tempGeoTransform[5]*0.5 +\
-                           tempGeoTransform[4]*(poSrcDS->GetRasterXSize()-0.5);
-
-          padfTiepoints[4]=tempGeoTransform[0] + tempGeoTransform[1]*0.5 +\
-                           tempGeoTransform[2]*(poSrcDS->GetRasterYSize()-0.5);
-
-          padfTiepoints[5]=tempGeoTransform[3] + tempGeoTransform[4]*0.5 +\
-                           tempGeoTransform[5]*(poSrcDS->GetRasterYSize()-0.5);
-
-          padfTiepoints[6]=tempGeoTransform[0] +\
-                           tempGeoTransform[1]*(poSrcDS->GetRasterXSize()-0.5) +\
-                           tempGeoTransform[2]*(poSrcDS->GetRasterYSize()-0.5);
-
-          padfTiepoints[7]=tempGeoTransform[3]+\
-                           tempGeoTransform[4]*(poSrcDS->GetRasterXSize()-0.5)+\
-                           tempGeoTransform[5]*(poSrcDS->GetRasterYSize()-0.5);
-
-          padfTiepoints[8]=tempGeoTransform[0]+\
-                           tempGeoTransform[1]*(poSrcDS->GetRasterXSize())/2.0+\
-                           tempGeoTransform[2]*(poSrcDS->GetRasterYSize())/2.0;
-
-          padfTiepoints[9]=tempGeoTransform[3]+\
-                           tempGeoTransform[4]*(poSrcDS->GetRasterXSize())/2.0+\
-                           tempGeoTransform[5]*(poSrcDS->GetRasterYSize())/2.0;
+          padfTiepoints[0] =
+              tempGeoTransform[0] + tempGeoTransform[1]*0.5 +
+              tempGeoTransform[2]*0.5;
+
+          padfTiepoints[1] =
+              tempGeoTransform[3] + tempGeoTransform[4]*0.5 +
+              tempGeoTransform[5]*0.5;
+
+          padfTiepoints[2] =
+              tempGeoTransform[0] + tempGeoTransform[2]*0.5 +
+              tempGeoTransform[1]*(poSrcDS->GetRasterXSize()-0.5);
+
+          padfTiepoints[3] =
+              tempGeoTransform[3] + tempGeoTransform[5]*0.5 +
+              tempGeoTransform[4]*(poSrcDS->GetRasterXSize()-0.5);
+
+          padfTiepoints[4] =
+              tempGeoTransform[0] + tempGeoTransform[1]*0.5 +
+              tempGeoTransform[2]*(poSrcDS->GetRasterYSize()-0.5);
+
+          padfTiepoints[5] =
+              tempGeoTransform[3] + tempGeoTransform[4]*0.5 +
+              tempGeoTransform[5]*(poSrcDS->GetRasterYSize()-0.5);
+
+          padfTiepoints[6] =
+              tempGeoTransform[0] +
+              tempGeoTransform[1]*(poSrcDS->GetRasterXSize()-0.5) +
+              tempGeoTransform[2]*(poSrcDS->GetRasterYSize()-0.5);
+
+          padfTiepoints[7] =
+              tempGeoTransform[3]+
+              tempGeoTransform[4]*(poSrcDS->GetRasterXSize()-0.5)+
+              tempGeoTransform[5]*(poSrcDS->GetRasterYSize()-0.5);
+
+          padfTiepoints[8] =
+              tempGeoTransform[0]+
+              tempGeoTransform[1]*(poSrcDS->GetRasterXSize())/2.0+
+              tempGeoTransform[2]*(poSrcDS->GetRasterYSize())/2.0;
+
+          padfTiepoints[9] =
+              tempGeoTransform[3]+
+              tempGeoTransform[4]*(poSrcDS->GetRasterXSize())/2.0+
+              tempGeoTransform[5]*(poSrcDS->GetRasterYSize())/2.0;
 
           OGRSpatialReference oUTMorLL(poSrcDS->GetProjectionRef());
           char *newGCPProjection = NULL;
@@ -1398,23 +1446,25 @@ MFFDataset::CreateCopy( const char * pszFilename,
           CPLFree(newGCPProjection);
           newGCPProjection = NULL;
 
-          if STARTS_WITH_CI(poSrcDS->GetProjectionRef(), "PROJCS")
+          if( STARTS_WITH_CI(poSrcDS->GetProjectionRef(), "PROJCS") )
           {
-            // projected coordinate system- need to translate gcps */
-            bool bSuccess = true;
-
             OGRCoordinateTransformation *poTransform
                 = OGRCreateCoordinateTransformation( &oUTMorLL, &oLL );
-            if( poTransform == NULL )
-                bSuccess = false;
+
+            // projected coordinate system- need to translate gcps */
+            bool bSuccess = poTransform != NULL;
 
             for ( int index = 0; index < 5; index++ )
             {
                 // TODO: If bSuccess is false, set it to false?
-                if( !bSuccess || !poTransform->Transform( 1, &(padfTiepoints[index*2]), &(padfTiepoints[index*2+1]) ) )
+                if( !bSuccess ||
+                    !poTransform->Transform(
+                        1,
+                        &(padfTiepoints[index*2]),
+                        &(padfTiepoints[index*2+1]) ) )
                   bSuccess = false;
             }
-            if (bSuccess == TRUE)
+            if( bSuccess )
                georef_created = true;
           }
           else
@@ -1426,33 +1476,43 @@ MFFDataset::CreateCopy( const char * pszFilename,
     }
 
     bool bOK = true;
-    if (georef_created == true)
+    if( georef_created )
     {
     /* -------------------------------------------------------------------- */
     /*      top left                                                        */
     /* -------------------------------------------------------------------- */
-          bOK &= VSIFPrintfL( fp, "TOP_LEFT_CORNER_LATITUDE = %.10f\n", padfTiepoints[1] ) >= 0;
-          bOK &= VSIFPrintfL( fp, "TOP_LEFT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[0] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "TOP_LEFT_CORNER_LATITUDE = %.10f\n",
+                              padfTiepoints[1] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "TOP_LEFT_CORNER_LONGITUDE = %.10f\n",
+                              padfTiepoints[0] ) >= 0;
     /* -------------------------------------------------------------------- */
     /*      top_right                                                       */
     /* -------------------------------------------------------------------- */
-          bOK &= VSIFPrintfL( fp, "TOP_RIGHT_CORNER_LATITUDE = %.10f\n", padfTiepoints[3] ) >= 0;
-          bOK &= VSIFPrintfL( fp, "TOP_RIGHT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[2] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "TOP_RIGHT_CORNER_LATITUDE = %.10f\n",
+                              padfTiepoints[3] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "TOP_RIGHT_CORNER_LONGITUDE = %.10f\n",
+                              padfTiepoints[2] ) >= 0;
     /* -------------------------------------------------------------------- */
     /*      bottom_left                                                     */
     /* -------------------------------------------------------------------- */
-          bOK &= VSIFPrintfL( fp, "BOTTOM_LEFT_CORNER_LATITUDE = %.10f\n", padfTiepoints[5] ) >= 0;
-          bOK &= VSIFPrintfL( fp, "BOTTOM_LEFT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[4] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "BOTTOM_LEFT_CORNER_LATITUDE = %.10f\n",
+                              padfTiepoints[5] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "BOTTOM_LEFT_CORNER_LONGITUDE = %.10f\n",
+                              padfTiepoints[4] ) >= 0;
     /* -------------------------------------------------------------------- */
     /*      bottom_right                                                    */
     /* -------------------------------------------------------------------- */
-          bOK &= VSIFPrintfL( fp, "BOTTOM_RIGHT_CORNER_LATITUDE = %.10f\n", padfTiepoints[7] ) >= 0;
-          bOK &= VSIFPrintfL( fp, "BOTTOM_RIGHT_CORNER_LONGITUDE = %.10f\n", padfTiepoints[6] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "BOTTOM_RIGHT_CORNER_LATITUDE = %.10f\n",
+                              padfTiepoints[7] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "BOTTOM_RIGHT_CORNER_LONGITUDE = %.10f\n",
+                              padfTiepoints[6] ) >= 0;
     /* -------------------------------------------------------------------- */
     /*      Center                                                          */
     /* -------------------------------------------------------------------- */
-          bOK &= VSIFPrintfL( fp, "CENTRE_LATITUDE = %.10f\n", padfTiepoints[9] ) >= 0;
-          bOK &= VSIFPrintfL( fp, "CENTRE_LONGITUDE = %.10f\n", padfTiepoints[8] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "CENTRE_LATITUDE = %.10f\n",
+                              padfTiepoints[9] ) >= 0;
+          bOK &= VSIFPrintfL( fp, "CENTRE_LONGITUDE = %.10f\n",
+                              padfTiepoints[8] ) >= 0;
     /* ------------------------------------------------------------------- */
     /*     Ellipsoid/projection                                            */
     /* --------------------------------------------------------------------*/
@@ -1464,24 +1524,28 @@ MFFDataset::CreateCopy( const char * pszFilename,
            && !STARTS_WITH_CI(pszSrcProjection, "PROJCS")
            && !EQUAL(pszSrcProjection,"") )
           {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                    "Only OGC WKT Projections supported for writing to MFF.\n"
-                    "%s not supported.",
-                      pszSrcProjection );
+            CPLError(
+                CE_Warning, CPLE_AppDefined,
+                "Only OGC WKT Projections supported for writing to MFF. "
+                "%s not supported.",
+                pszSrcProjection );
           }
           else if (!EQUAL(pszSrcProjection,""))
           {
              OGRSpatialReference oSRS(pszSrcProjection);
 
-             if ((oSRS.GetAttrValue("PROJECTION") != NULL) &&
-                 (EQUAL(oSRS.GetAttrValue("PROJECTION"),SRS_PT_TRANSVERSE_MERCATOR)))
+             if( oSRS.GetAttrValue("PROJECTION") != NULL &&
+                 EQUAL(oSRS.GetAttrValue("PROJECTION"),
+                       SRS_PT_TRANSVERSE_MERCATOR) )
              {
-                 bOK &= VSIFPrintfL(fp,"PROJECTION_NAME = UTM\n") >= 0;
+                 bOK &= VSIFPrintfL(fp, "PROJECTION_NAME = UTM\n") >= 0;
                  OGRErr ogrerrorOl = OGRERR_NONE;
-                 bOK &= VSIFPrintfL(fp,"PROJECTION_ORIGIN_LONGITUDE = %f\n",
-                         oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0,&ogrerrorOl)) >= 0;
+                 bOK &= VSIFPrintfL(fp, "PROJECTION_ORIGIN_LONGITUDE = %f\n",
+                         oSRS.GetProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0,
+                                          &ogrerrorOl)) >= 0;
              }
-             else if ((oSRS.GetAttrValue("PROJECTION") == NULL) && (oSRS.IsGeographic()))
+             else if (oSRS.GetAttrValue("PROJECTION") == NULL &&
+                      oSRS.IsGeographic())
              {
                   bOK &= VSIFPrintfL(fp,"PROJECTION_NAME = LL\n") >= 0;
              }
@@ -1490,19 +1554,22 @@ MFFDataset::CreateCopy( const char * pszFilename,
                   CPLError( CE_Warning, CPLE_AppDefined,
                             "Unrecognized projection- no georeferencing "
                             "information transferred." );
-                  bOK &= VSIFPrintfL(fp,"PROJECTION_NAME = LL\n") >= 0;
+                  bOK &= VSIFPrintfL(fp, "PROJECTION_NAME = LL\n") >= 0;
              }
              OGRErr ogrerrorEq = OGRERR_NONE;
              const double eq_radius = oSRS.GetSemiMajor(&ogrerrorEq);
              OGRErr ogrerrorInvf = OGRERR_NONE;
              const double inv_flattening = oSRS.GetInvFlattening(&ogrerrorInvf);
-             if ((ogrerrorEq == OGRERR_NONE) && (ogrerrorInvf == OGRERR_NONE))
+             if( ogrerrorEq == OGRERR_NONE && ogrerrorInvf == OGRERR_NONE )
              {
                  MFFSpheroidList *mffEllipsoids = new MFFSpheroidList;
-                 spheroid_name = mffEllipsoids->GetSpheroidNameByEqRadiusAndInvFlattening(eq_radius,inv_flattening);
+                 spheroid_name =
+                     mffEllipsoids->GetSpheroidNameByEqRadiusAndInvFlattening(
+                         eq_radius, inv_flattening);
                  if (spheroid_name != NULL)
                  {
-                     bOK &= VSIFPrintfL(fp,"SPHEROID_NAME = %s\n",spheroid_name ) >= 0;
+                     bOK &= VSIFPrintfL(fp, "SPHEROID_NAME = %s\n",
+                                        spheroid_name ) >= 0;
                  }
                  else
                  {
@@ -1510,7 +1577,7 @@ MFFDataset::CreateCopy( const char * pszFilename,
                          fp, "SPHEROID_NAME = USER_DEFINED\n"
                          "SPHEROID_EQUATORIAL_RADIUS = %.10f\n"
                          "SPHEROID_POLAR_RADIUS = %.10f\n",
-                     eq_radius,eq_radius*(1-1.0/inv_flattening) ) >= 0;
+                         eq_radius,eq_radius*(1-1.0/inv_flattening) ) >= 0;
                  }
                  delete mffEllipsoids;
                  CPLFree(spheroid_name);
@@ -1540,14 +1607,13 @@ MFFDataset::CreateCopy( const char * pszFilename,
         poDstBand->FlushCache();
     }
 
-
     if( !pfnProgress( 1.0, NULL, pProgressData ) )
     {
         CPLError( CE_Failure, CPLE_UserInterrupt,
                   "User terminated" );
         delete poDS;
 
-        GDALDriver *poMFFDriver = reinterpret_cast<GDALDriver *>(
+        GDALDriver *poMFFDriver = static_cast<GDALDriver *>(
             GDALGetDriverByName( "MFF" ) );
         poMFFDriver->Delete( pszFilename );
         CPLFree(pszBaseFilename);
@@ -1560,7 +1626,6 @@ MFFDataset::CreateCopy( const char * pszFilename,
     return poDS;
 }
 
-
 /************************************************************************/
 /*                         GDALRegister_MFF()                           */
 /************************************************************************/
diff --git a/frmts/raw/ndfdataset.cpp b/frmts/raw/ndfdataset.cpp
index 02a76b8..f0254ef 100644
--- a/frmts/raw/ndfdataset.cpp
+++ b/frmts/raw/ndfdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ndfdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  NDF Driver
  * Purpose:  Implementation of NLAPS Data Format read support.
@@ -33,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: ndfdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
+CPL_CVSID("$Id: ndfdataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -55,9 +54,9 @@ class NDFDataset : public RawDataset
                 NDFDataset();
     virtual ~NDFDataset();
 
-    virtual CPLErr  GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef(void);
-    virtual char **GetFileList(void);
+    virtual CPLErr  GetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef(void) override;
+    virtual char **GetFileList(void) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -181,10 +180,10 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
     if (fp == NULL)
         return NULL;
 
-    const char *pszLine;
+    const char *pszLine = NULL;
     const int nHeaderMax = 1000;
     int nHeaderLines = 0;
-    char **papszHeader = reinterpret_cast<char **>(
+    char **papszHeader = static_cast<char **>(
         CPLMalloc( sizeof(char *) * (nHeaderMax+1) ) );
 
     while( nHeaderLines < nHeaderMax
@@ -272,7 +271,7 @@ GDALDataset *NDFDataset::Open( GDALOpenInfo * poOpenInfo )
         CPLString osFilename = poDS->Get(szKey,"");
 
         // NDF1 file do not include the band filenames.
-        if( osFilename.size() == 0 )
+        if( osFilename.empty() )
         {
             char szBandExtension[15];
             snprintf( szBandExtension, sizeof(szBandExtension), "I%d", iBand+1 );
diff --git a/frmts/raw/ntv2dataset.cpp b/frmts/raw/ntv2dataset.cpp
index e0dab3d..ee87cfb 100644
--- a/frmts/raw/ntv2dataset.cpp
+++ b/frmts/raw/ntv2dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ntv2dataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  Horizontal Datum Formats
  * Purpose:  Implementation of NTv2 datum shift format used in Canada, France,
@@ -30,12 +29,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+// TODO(schwehr): There are a lot of magic numbers in this driver that should
+// be changed to constants and documented.
+
 #include "cpl_string.h"
 #include "gdal_frmts.h"
 #include "ogr_srs_api.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: ntv2dataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ntv2dataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /**
  * The header for the file, and each grid consists of 11 16byte records.
@@ -101,10 +105,10 @@ class NTv2Dataset : public RawDataset
                 NTv2Dataset();
     virtual ~NTv2Dataset();
 
-    virtual CPLErr SetGeoTransform( double * padfTransform );
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef();
-    virtual void   FlushCache(void);
+    virtual CPLErr SetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef() override;
+    virtual void   FlushCache(void) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -123,7 +127,19 @@ class NTv2Dataset : public RawDataset
 /*                             NTv2Dataset()                          */
 /************************************************************************/
 
-NTv2Dataset::NTv2Dataset() : m_bMustSwap(false), fpImage(NULL), nRecordLength(0), nGridOffset(0) { }
+NTv2Dataset::NTv2Dataset() :
+    m_bMustSwap(false),
+    fpImage(NULL),
+    nRecordLength(0),
+    nGridOffset(0)
+{
+    adfGeoTransform[0] =  0.0;
+    adfGeoTransform[1] =  0.0;  // TODO(schwehr): Should this be 1.0?
+    adfGeoTransform[2] =  0.0;
+    adfGeoTransform[3] =  0.0;
+    adfGeoTransform[4] =  0.0;
+    adfGeoTransform[5] =  0.0;  // TODO(schwehr): Should this be 1.0?
+}
 
 /************************************************************************/
 /*                            ~NTv2Dataset()                          */
@@ -151,7 +167,7 @@ static void SwapPtr32IfNecessary( bool bMustSwap, void* ptr )
 {
     if( bMustSwap )
     {
-        CPL_SWAP32PTR( (GByte*)ptr );
+        CPL_SWAP32PTR( static_cast<GByte *>(ptr) );
     }
 }
 
@@ -163,7 +179,7 @@ static void SwapPtr64IfNecessary( bool bMustSwap, void* ptr )
 {
     if( bMustSwap )
     {
-        CPL_SWAP64PTR( (GByte*)ptr );
+        CPL_SWAP64PTR( static_cast<GByte *>(ptr) );
     }
 }
 
@@ -187,14 +203,18 @@ void NTv2Dataset::FlushCache()
 /* -------------------------------------------------------------------- */
 /*      Load grid and file headers.                                     */
 /* -------------------------------------------------------------------- */
-    char achFileHeader[11*16];
-    char achGridHeader[11*16];
+    const int nRecords = 11;
+    const int nRecordSize = 16;
+    char achFileHeader[nRecords*nRecordSize] = { '\0' };
+    char achGridHeader[nRecords*nRecordSize] = { '\0' };
 
     CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
-    CPL_IGNORE_RET_VAL(VSIFReadL( achFileHeader, 11, 16, fpImage ));
+    CPL_IGNORE_RET_VAL(
+        VSIFReadL( achFileHeader, nRecords, nRecordSize, fpImage ));
 
     CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, nGridOffset, SEEK_SET ));
-    CPL_IGNORE_RET_VAL(VSIFReadL( achGridHeader, 11, 16, fpImage ));
+    CPL_IGNORE_RET_VAL(
+        VSIFReadL( achGridHeader, nRecords, nRecordSize, fpImage ));
 
 /* -------------------------------------------------------------------- */
 /*      Update the grid, and file headers with any available            */
@@ -206,6 +226,7 @@ void NTv2Dataset::FlushCache()
 
     for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
     {
+        const size_t nMinLen = 8;
         char *pszKey = NULL;
         const char *pszValue = CPLParseNameValue( papszMD[i], &pszKey );
         if( pszKey == NULL )
@@ -214,22 +235,30 @@ void NTv2Dataset::FlushCache()
         if( EQUAL(pszKey,"GS_TYPE") )
         {
             memcpy( achFileHeader + 3*16+8, "        ", 8 );
-            memcpy( achFileHeader + 3*16+8, pszValue, MIN(8,strlen(pszValue)) );
+            memcpy( achFileHeader + 3*16+8,
+                    pszValue,
+                    std::min(nMinLen, strlen(pszValue)) );
         }
         else if( EQUAL(pszKey,"VERSION") )
         {
             memcpy( achFileHeader + 4*16+8, "        ", 8 );
-            memcpy( achFileHeader + 4*16+8, pszValue, MIN(8,strlen(pszValue)) );
+            memcpy( achFileHeader + 4*16+8,
+                    pszValue,
+                    std::min(nMinLen, strlen(pszValue)) );
         }
         else if( EQUAL(pszKey,"SYSTEM_F") )
         {
             memcpy( achFileHeader + 5*16+8, "        ", 8 );
-            memcpy( achFileHeader + 5*16+8, pszValue, MIN(8,strlen(pszValue)) );
+            memcpy( achFileHeader + 5*16+8,
+                    pszValue,
+                    std::min(nMinLen, strlen(pszValue)) );
         }
         else if( EQUAL(pszKey,"SYSTEM_T") )
         {
             memcpy( achFileHeader + 6*16+8, "        ", 8 );
-            memcpy( achFileHeader + 6*16+8, pszValue, MIN(8,strlen(pszValue)) );
+            memcpy( achFileHeader + 6*16+8,
+                    pszValue,
+                    std::min(nMinLen, strlen(pszValue)) );
         }
         else if( EQUAL(pszKey,"MAJOR_F") )
         {
@@ -258,22 +287,30 @@ void NTv2Dataset::FlushCache()
         else if( EQUAL(pszKey,"SUB_NAME") )
         {
             memcpy( achGridHeader + 0*16+8, "        ", 8 );
-            memcpy( achGridHeader + 0*16+8, pszValue, MIN(8,strlen(pszValue)) );
+            memcpy( achGridHeader + 0*16+8,
+                    pszValue,
+                    std::min(nMinLen, strlen(pszValue)) );
         }
         else if( EQUAL(pszKey,"PARENT") )
         {
             memcpy( achGridHeader + 1*16+8, "        ", 8 );
-            memcpy( achGridHeader + 1*16+8, pszValue, MIN(8,strlen(pszValue)) );
+            memcpy( achGridHeader + 1*16+8,
+                    pszValue,
+                    std::min(nMinLen, strlen(pszValue)) );
         }
         else if( EQUAL(pszKey,"CREATED") )
         {
             memcpy( achGridHeader + 2*16+8, "        ", 8 );
-            memcpy( achGridHeader + 2*16+8, pszValue, MIN(8,strlen(pszValue)) );
+            memcpy( achGridHeader + 2*16+8,
+                    pszValue,
+                    std::min(nMinLen, strlen(pszValue)) );
         }
         else if( EQUAL(pszKey,"UPDATED") )
         {
             memcpy( achGridHeader + 3*16+8, "        ", 8 );
-            memcpy( achGridHeader + 3*16+8, pszValue, MIN(8,strlen(pszValue)) );
+            memcpy( achGridHeader + 3*16+8,
+                    pszValue,
+                    std::min(nMinLen, strlen(pszValue)) );
         }
         else
         {
@@ -287,10 +324,12 @@ void NTv2Dataset::FlushCache()
 /*      Load grid and file headers.                                     */
 /* -------------------------------------------------------------------- */
     CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, 0, SEEK_SET ));
-    CPL_IGNORE_RET_VAL(VSIFWriteL( achFileHeader, 11, 16, fpImage ));
+    CPL_IGNORE_RET_VAL(
+        VSIFWriteL( achFileHeader, nRecords, nRecordSize, fpImage ));
 
     CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, nGridOffset, SEEK_SET ));
-    CPL_IGNORE_RET_VAL(VSIFWriteL( achGridHeader, 11, 16, fpImage ));
+    CPL_IGNORE_RET_VAL(
+        VSIFWriteL( achGridHeader, nRecords, nRecordSize, fpImage ));
 
 /* -------------------------------------------------------------------- */
 /*      Clear flags if we got everything, then let pam and below do     */
@@ -315,10 +354,12 @@ int NTv2Dataset::Identify( GDALOpenInfo *poOpenInfo )
     if( poOpenInfo->nHeaderBytes < 64 )
         return FALSE;
 
-    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader + 0, "NUM_OREC") )
+    if( !STARTS_WITH_CI(reinterpret_cast<char *>(poOpenInfo->pabyHeader) + 0,
+                        "NUM_OREC") )
         return FALSE;
 
-    if( !STARTS_WITH_CI((const char *)poOpenInfo->pabyHeader +16, "NUM_SREC") )
+    if( !STARTS_WITH_CI(reinterpret_cast<char *>(poOpenInfo->pabyHeader) + 16,
+                        "NUM_SREC") )
         return FALSE;
 
     return TRUE;
@@ -342,7 +383,7 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
     if( STARTS_WITH_CI(poOpenInfo->pszFilename, "NTv2:") )
     {
-        const char *pszRest = poOpenInfo->pszFilename+5;
+        const char *pszRest = poOpenInfo->pszFilename + 5;
 
         iTargetGrid = atoi(pszRest);
         while( *pszRest != '\0' && *pszRest != ':' )
@@ -354,7 +395,9 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
         osFilename = pszRest;
     }
     else
+    {
         osFilename = poOpenInfo->pszFilename;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
@@ -379,7 +422,7 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Read the file header.                                           */
 /* -------------------------------------------------------------------- */
-    char achHeader[11*16];
+    char achHeader[11*16] = { 0 };
     if (VSIFSeekL( poDS->fpImage, 0, SEEK_SET ) != 0 ||
         VSIFReadL( achHeader, 11, 16, poDS->fpImage ) != 16 )
     {
@@ -387,8 +430,12 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    const bool bIsLE = (achHeader[8] == 11 && achHeader[9] == 0 && achHeader[10] == 0 && achHeader[11] == 0);
-    const bool bIsBE = (achHeader[8] == 0 && achHeader[9] == 0 && achHeader[10] == 0 && achHeader[11] == 11);
+    const bool bIsLE =
+        achHeader[8] == 11 && achHeader[9] == 0 && achHeader[10] == 0 &&
+        achHeader[11] == 0;
+    const bool bIsBE =
+        achHeader[8] == 0 && achHeader[9] == 0 && achHeader[10] == 0 &&
+        achHeader[11] == 11;
     if( !bIsLE && !bIsBE )
     {
         delete poDS;
@@ -402,12 +449,12 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->m_bMustSwap = bMustSwap;
 
     SwapPtr32IfNecessary( bMustSwap, achHeader + 2*16 + 8 );
-    GInt32 nSubFileCount;
+    GInt32 nSubFileCount = 0;
     memcpy( &nSubFileCount, achHeader + 2*16 + 8, 4 );
     if (nSubFileCount <= 0 || nSubFileCount >= 1024)
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                  "Invalid value for NUM_FILE : %d", nSubFileCount);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid value for NUM_FILE : %d", nSubFileCount );
         delete poDS;
         return NULL;
     }
@@ -417,7 +464,7 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->CaptureMetadataItem( achHeader + 5*16 );
     poDS->CaptureMetadataItem( achHeader + 6*16 );
 
-    double dfValue;
+    double dfValue = 0.0;
     memcpy( &dfValue, achHeader + 7*16 + 8, 8 );
     SwapPtr64IfNecessary( bMustSwap, &dfValue );
     CPLString osFValue;
@@ -449,8 +496,8 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
         if (VSIFSeekL( poDS->fpImage, nGridOffset, SEEK_SET ) < 0 ||
             VSIFReadL( achHeader, 11, 16, poDS->fpImage ) != 16)
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Cannot read header for subfile %d", iGrid);
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Cannot read header for subfile %d", iGrid );
             delete poDS;
             return NULL;
         }
@@ -460,7 +507,7 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
 
         SwapPtr32IfNecessary( bMustSwap, achHeader + 10*16 + 8 );
 
-        GUInt32 nGSCount;
+        GUInt32 nGSCount = 0;
         memcpy( &nGSCount, achHeader + 10*16 + 8, 4 );
 
         CPLString osSubName;
@@ -480,8 +527,8 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
         // If we are opening the file as a whole, list subdatasets.
         if( iTargetGrid == -1 )
         {
-            CPLString osKey, osValue;
-
+            CPLString osKey;
+            CPLString osValue;
             osKey.Printf( "SUBDATASET_%d_NAME", iGrid );
             osValue.Printf( "NTv2:%d:%s", iGrid, osFilename.c_str() );
             poDS->SetMetadataItem( osKey, osValue, "SUBDATASETS" );
@@ -505,7 +552,7 @@ GDALDataset *NTv2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -539,8 +586,10 @@ int NTv2Dataset::OpenGrid( char *pachHeader, vsi_l_offset nGridOffsetIn )
     e_long *= -1;
     w_long *= -1;
 
-    nRasterXSize = static_cast<int>( floor((e_long - w_long) / long_inc + 1.5) );
-    nRasterYSize = static_cast<int>( floor((n_lat - s_lat) / lat_inc + 1.5) );
+    nRasterXSize =
+        static_cast<int>( floor((e_long - w_long) / long_inc + 1.5) );
+    nRasterYSize =
+        static_cast<int>( floor((n_lat - s_lat) / lat_inc + 1.5) );
 
     if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize))
         return FALSE;
@@ -589,7 +638,8 @@ int NTv2Dataset::OpenGrid( char *pachHeader, vsi_l_offset nGridOffsetIn )
 void NTv2Dataset::CaptureMetadataItem( char *pszItem )
 
 {
-    CPLString osKey, osValue;
+    CPLString osKey;
+    CPLString osValue;
 
     osKey.assign( pszItem, 8 );
     osValue.assign( pszItem+8, 8 );
@@ -634,15 +684,15 @@ CPLErr NTv2Dataset::SetGeoTransform( double * padfTransform )
 /* -------------------------------------------------------------------- */
 /*      Update grid header.                                             */
 /* -------------------------------------------------------------------- */
-    double dfValue;
-    char   achHeader[11*16];
+    char achHeader[11*16] = { '\0' };
 
     // read grid header
     CPL_IGNORE_RET_VAL(VSIFSeekL( fpImage, nGridOffset, SEEK_SET ));
     CPL_IGNORE_RET_VAL(VSIFReadL( achHeader, 11, 16, fpImage ));
 
     // S_LAT
-    dfValue = 3600 * (adfGeoTransform[3] + (nRasterYSize-0.5) * adfGeoTransform[5]);
+    double dfValue =
+        3600 * (adfGeoTransform[3] + (nRasterYSize-0.5) * adfGeoTransform[5]);
     SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
     memcpy( achHeader +  4*16 + 8, &dfValue, 8 );
 
@@ -652,7 +702,8 @@ CPLErr NTv2Dataset::SetGeoTransform( double * padfTransform )
     memcpy( achHeader +  5*16 + 8, &dfValue, 8 );
 
     // E_LONG
-    dfValue = -3600 * (adfGeoTransform[0] + (nRasterXSize-0.5)*adfGeoTransform[1]);
+    dfValue =
+        -3600 * (adfGeoTransform[0] + (nRasterXSize-0.5)*adfGeoTransform[1]);
     SwapPtr64IfNecessary( m_bMustSwap, &dfValue );
     memcpy( achHeader +  6*16 + 8, &dfValue, 8 );
 
@@ -678,7 +729,6 @@ CPLErr NTv2Dataset::SetGeoTransform( double * padfTransform )
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
@@ -701,28 +751,29 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
 {
     if( eType != GDT_Float32 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
+        CPLError( CE_Failure, CPLE_AppDefined,
                  "Attempt to create NTv2 file with unsupported data type '%s'.",
-                 GDALGetDataTypeName( eType ) );
+                  GDALGetDataTypeName( eType ) );
         return NULL;
     }
     if( nBands != 4 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Attempt to create NTv2 file with unsupported band number '%d'.",
-                 nBands);
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to create NTv2 file with unsupported "
+                  "band number '%d'.",
+                  nBands);
         return NULL;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Are we extending an existing file?                              */
 /* -------------------------------------------------------------------- */
-    int bAppend = CSLFetchBoolean(papszOptions,"APPEND_SUBDATASET",FALSE);
+    const bool bAppend = CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false);
 
 /* -------------------------------------------------------------------- */
 /*      Try to open or create file.                                     */
 /* -------------------------------------------------------------------- */
-    VSILFILE *fp;
+    VSILFILE *fp = NULL;
     if( bAppend )
         fp = VSIFOpenL( pszFilename, "rb+" );
     else
@@ -739,8 +790,8 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create a file level header if we are creating new.              */
 /* -------------------------------------------------------------------- */
-    char achHeader[11*16];
-    const char *pszValue;
+    char achHeader[11*16] = { '\0' };
+    const char *pszValue = NULL;
     GUInt32 nNumFile = 1;
     bool bMustSwap = false;
     bool bIsLE = false;
@@ -771,21 +822,24 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
         memcpy( achHeader + 2*16 + 8, &nNumFile, 4 );
         SwapPtr32IfNecessary( bMustSwap, &nNumFile );
 
+        const size_t nMinLen = 16;
         memcpy( achHeader +  3*16, "GS_TYPE         ", 16 );
         pszValue = CSLFetchNameValueDef( papszOptions, "GS_TYPE", "SECONDS");
-        memcpy( achHeader +  3*16+8, pszValue, MIN(16,strlen(pszValue)) );
+        memcpy( achHeader +  3*16+8,
+                pszValue,
+                std::min(nMinLen, strlen(pszValue)) );
 
         memcpy( achHeader +  4*16, "VERSION         ", 16 );
         pszValue = CSLFetchNameValueDef( papszOptions, "VERSION", "" );
-        memcpy( achHeader +  4*16+8, pszValue, MIN(16,strlen(pszValue)) );
+        memcpy( achHeader +  4*16+8, pszValue, std::min(nMinLen, strlen(pszValue)) );
 
         memcpy( achHeader +  5*16, "SYSTEM_F        ", 16 );
         pszValue = CSLFetchNameValueDef( papszOptions, "SYSTEM_F", "" );
-        memcpy( achHeader +  5*16+8, pszValue, MIN(16,strlen(pszValue)) );
+        memcpy( achHeader +  5*16+8, pszValue, std::min(nMinLen, strlen(pszValue)) );
 
         memcpy( achHeader +  6*16, "SYSTEM_T        ", 16 );
         pszValue = CSLFetchNameValueDef( papszOptions, "SYSTEM_T", "" );
-        memcpy( achHeader +  6*16+8, pszValue, MIN(16,strlen(pszValue)) );
+        memcpy( achHeader +  6*16+8, pszValue, std::min(nMinLen, strlen(pszValue)) );
 
         memcpy( achHeader +  7*16, "MAJOR_F ", 8);
         memcpy( achHeader +  8*16, "MINOR_F ", 8 );
@@ -804,8 +858,16 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
         CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_SET ));
         CPL_IGNORE_RET_VAL(VSIFReadL( achHeader, 1, 16, fp ));
 
-        bIsLE = (achHeader[8] == 11 && achHeader[9] == 0 && achHeader[10] == 0 && achHeader[11] == 0);
-        const bool bIsBE = (achHeader[8] == 0 && achHeader[9] == 0 && achHeader[10] == 0 && achHeader[11] == 11);
+        bIsLE =
+            achHeader[8] == 11 &&
+            achHeader[9] == 0 &&
+            achHeader[10] == 0 &&
+            achHeader[11] == 0;
+        const bool bIsBE =
+            achHeader[8] == 0 &&
+            achHeader[9] == 0 &&
+            achHeader[10] == 0 &&
+            achHeader[11] == 11;
         if( !bIsLE && !bIsBE )
         {
             VSIFCloseL(fp);
@@ -829,7 +891,7 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
         SwapPtr32IfNecessary( bMustSwap, &nNumFile );
 
         CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_END ));
-        vsi_l_offset nEnd = VSIFTellL( fp );
+        const vsi_l_offset nEnd = VSIFTellL( fp );
         CPL_IGNORE_RET_VAL(VSIFSeekL( fp, nEnd-16, SEEK_SET ));
     }
 
@@ -838,21 +900,31 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     memset( achHeader, 0, sizeof(achHeader) );
 
+    const size_t nMinLen = 16;
+
     memcpy( achHeader +  0*16, "SUB_NAME        ", 16 );
     pszValue = CSLFetchNameValueDef( papszOptions, "SUB_NAME", "" );
-    memcpy( achHeader +  0*16+8, pszValue, MIN(16,strlen(pszValue)) );
+    memcpy( achHeader +  0*16+8,
+            pszValue,
+            std::min(nMinLen, strlen(pszValue)) );
 
     memcpy( achHeader +  1*16, "PARENT          ", 16 );
     pszValue = CSLFetchNameValueDef( papszOptions, "PARENT", "NONE" );
-    memcpy( achHeader +  1*16+8, pszValue, MIN(16,strlen(pszValue)) );
+    memcpy( achHeader +  1*16+8,
+            pszValue,
+            std::min(nMinLen, strlen(pszValue)) );
 
     memcpy( achHeader +  2*16, "CREATED         ", 16 );
     pszValue = CSLFetchNameValueDef( papszOptions, "CREATED", "" );
-    memcpy( achHeader +  2*16+8, pszValue, MIN(16,strlen(pszValue)) );
+    memcpy( achHeader +  2*16+8,
+            pszValue,
+            std::min(nMinLen, strlen(pszValue)) );
 
     memcpy( achHeader +  3*16, "UPDATED         ", 16 );
     pszValue = CSLFetchNameValueDef( papszOptions, "UPDATED", "" );
-    memcpy( achHeader +  3*16+8, pszValue, MIN(16,strlen(pszValue)) );
+    memcpy( achHeader + 3*16+8,
+            pszValue,
+            std::min(nMinLen, strlen(pszValue)) );
 
     double dfValue;
 
@@ -908,8 +980,8 @@ GDALDataset *NTv2Dataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write the end record.                                           */
 /* -------------------------------------------------------------------- */
-    memset( achHeader, 0, 16 );
     memcpy( achHeader, "END     ", 8 );
+    memset( achHeader + 8, 0, 8 );
     CPL_IGNORE_RET_VAL(VSIFWriteL( achHeader, 1, 16, fp ));
     CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
diff --git a/frmts/raw/pauxdataset.cpp b/frmts/raw/pauxdataset.cpp
index 9e8599d..f851520 100644
--- a/frmts/raw/pauxdataset.cpp
+++ b/frmts/raw/pauxdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pauxdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  PCI .aux Driver
  * Purpose:  Implementation of PAuxDataset
@@ -33,7 +32,9 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: pauxdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
+#include <cmath>
+
+CPL_CVSID("$Id: pauxdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -47,7 +48,7 @@ class PAuxDataset : public RawDataset
 {
     friend class PAuxRasterBand;
 
-    VSILFILE    *fpImage;  // image data file.
+    VSILFILE    *fpImage;  // Image data file.
 
     int         nGCPCount;
     GDAL_GCP    *pasGCPList;
@@ -62,17 +63,18 @@ class PAuxDataset : public RawDataset
                 PAuxDataset();
     virtual ~PAuxDataset();
 
+    // TODO(schwehr): Why are these public?
     char        *pszAuxFilename;
     char        **papszAuxLines;
     int         bAuxUpdated;
 
-    virtual const char *GetProjectionRef();
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
@@ -88,8 +90,6 @@ class PAuxDataset : public RawDataset
 
 class PAuxRasterBand : public RawRasterBand
 {
-    GDALColorTable *poCT;
-
   public:
 
                  PAuxRasterBand( GDALDataset *poDS, int nBand, VSILFILE * fpRaw,
@@ -99,13 +99,13 @@ class PAuxRasterBand : public RawRasterBand
 
     virtual ~PAuxRasterBand();
 
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr SetNoDataValue( double );
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual CPLErr SetNoDataValue( double ) override;
 
-    virtual GDALColorTable *GetColorTable();
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual GDALColorTable *GetColorTable() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 
-    virtual void SetDescription( const char *pszNewDescription );
+    virtual void SetDescription( const char *pszNewDescription ) override;
 };
 
 /************************************************************************/
@@ -118,15 +118,14 @@ PAuxRasterBand::PAuxRasterBand( GDALDataset *poDSIn, int nBandIn,
                                 GDALDataType eDataTypeIn, int bNativeOrderIn ) :
     RawRasterBand( poDSIn, nBandIn, fpRawIn,
                    nImgOffsetIn, nPixelOffsetIn, nLineOffsetIn,
-                   eDataTypeIn, bNativeOrderIn, TRUE ),
-    poCT(NULL)
+                   eDataTypeIn, bNativeOrderIn, TRUE )
 {
     PAuxDataset *poPDS = reinterpret_cast<PAuxDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
 /*      Does this channel have a description?                           */
 /* -------------------------------------------------------------------- */
-    char szTarget[128];
+    char szTarget[128] = { '\0' };
 
     snprintf( szTarget, sizeof(szTarget), "ChanDesc-%d", nBand );
     if( CSLFetchNameValue( poPDS->papszAuxLines, szTarget ) != NULL )
@@ -137,31 +136,36 @@ PAuxRasterBand::PAuxRasterBand( GDALDataset *poDSIn, int nBandIn,
 /*      See if we have colors.  Currently we must have color zero,      */
 /*      but this should not really be a limitation.                     */
 /* -------------------------------------------------------------------- */
-    snprintf( szTarget, sizeof(szTarget), "METADATA_IMG_%d_Class_%d_Color", nBand, 0 );
+    snprintf( szTarget, sizeof(szTarget),
+              "METADATA_IMG_%d_Class_%d_Color", nBand, 0 );
     if( CSLFetchNameValue( poPDS->papszAuxLines, szTarget ) != NULL )
     {
         poCT = new GDALColorTable();
 
         for( int i = 0; i < 256; i++ )
         {
-            snprintf( szTarget, sizeof(szTarget), "METADATA_IMG_%d_Class_%d_Color", nBand, i );
+            snprintf( szTarget, sizeof(szTarget),
+                      "METADATA_IMG_%d_Class_%d_Color", nBand, i );
             const char *pszLine
                 = CSLFetchNameValue( poPDS->papszAuxLines, szTarget );
             while( pszLine && *pszLine == ' ' )
                 pszLine++;
 
-            int nRed, nGreen, nBlue;
+            int nRed = 0;
+            int nGreen = 0;
+            int nBlue = 0;
+            // TODO(schwehr): Replace sscanf with something safe.
             if( pszLine != NULL
                 && STARTS_WITH_CI(pszLine, "(RGB:")
                 && sscanf( pszLine+5, "%d %d %d",
                            &nRed, &nGreen, &nBlue ) == 3 )
             {
-                GDALColorEntry    oColor;
-
-                oColor.c1 = (short) nRed;
-                oColor.c2 = (short) nGreen;
-                oColor.c3 = (short) nBlue;
-                oColor.c4 = 255;
+                GDALColorEntry oColor = {
+                    static_cast<short>(nRed),
+                    static_cast<short>(nGreen),
+                    static_cast<short>(nBlue),
+                    255
+                };
 
                 poCT->SetColorEntry( i, &oColor );
             }
@@ -176,8 +180,6 @@ PAuxRasterBand::PAuxRasterBand( GDALDataset *poDSIn, int nBandIn,
 PAuxRasterBand::~PAuxRasterBand()
 
 {
-    if( poCT != NULL )
-        delete poCT;
 }
 
 /************************************************************************/
@@ -187,8 +189,9 @@ PAuxRasterBand::~PAuxRasterBand()
 double PAuxRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
-    char szTarget[128];
-    snprintf( szTarget, sizeof(szTarget), "METADATA_IMG_%d_NO_DATA_VALUE", nBand );
+    char szTarget[128] = { '\0' };
+    snprintf( szTarget, sizeof(szTarget),
+              "METADATA_IMG_%d_NO_DATA_VALUE", nBand );
 
     PAuxDataset *poPDS = reinterpret_cast<PAuxDataset *>( poDS );
     const char  *pszLine = CSLFetchNameValue( poPDS->papszAuxLines, szTarget );
@@ -197,7 +200,7 @@ double PAuxRasterBand::GetNoDataValue( int *pbSuccess )
         *pbSuccess = (pszLine != NULL);
 
     if( pszLine == NULL )
-        return -1e8;
+        return -1.0e8;
 
     return CPLAtof(pszLine);
 }
@@ -216,10 +219,12 @@ CPLErr PAuxRasterBand::SetNoDataValue( double dfNewValue )
         return CE_Failure;
     }
 
-    char szTarget[128];
-    char szValue[128];
-    snprintf( szTarget, sizeof(szTarget), "METADATA_IMG_%d_NO_DATA_VALUE", nBand );
-    CPLsnprintf( szValue, sizeof(szValue), "%24.12f", dfNewValue );
+    char szTarget[128] = { '\0' };
+    char szValue[128] = { '\0' };
+    snprintf( szTarget, sizeof(szTarget),
+              "METADATA_IMG_%d_NO_DATA_VALUE", nBand );
+    CPLsnprintf( szValue, sizeof(szValue),
+                 "%24.12f", dfNewValue );
 
     PAuxDataset *poPDS = reinterpret_cast<PAuxDataset *>( poDS );
     poPDS->papszAuxLines =
@@ -242,7 +247,7 @@ void PAuxRasterBand::SetDescription( const char *pszNewDescription )
 {
     if( GetAccess() == GA_Update )
     {
-        char szTarget[128];
+        char szTarget[128] = { '\0' };
         snprintf( szTarget, sizeof(szTarget), "ChanDesc-%d", nBand );
 
         PAuxDataset *poPDS = reinterpret_cast<PAuxDataset *>( poDS );
@@ -256,7 +261,6 @@ void PAuxRasterBand::SetDescription( const char *pszNewDescription )
     GDALRasterBand::SetDescription( pszNewDescription );
 }
 
-
 /************************************************************************/
 /*                           GetColorTable()                            */
 /************************************************************************/
@@ -309,12 +313,9 @@ PAuxDataset::~PAuxDataset()
 
 {
     FlushCache();
-    if( fpImage != NULL )
+    if( fpImage != NULL && VSIFCloseL( fpImage ) != 0 )
     {
-        if( VSIFCloseL( fpImage ) != 0 )
-        {
-            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
-        }
+        CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
     }
 
     if( bAuxUpdated )
@@ -350,15 +351,15 @@ char *PAuxDataset::PCI2WKT( const char *pszGeosys,
 /* -------------------------------------------------------------------- */
 /*      Parse projection parameters array.                              */
 /* -------------------------------------------------------------------- */
-    double adfProjParms[16];
-
-    memset( adfProjParms, 0, sizeof(adfProjParms) );
+    double adfProjParms[16] = { 0.0 };
 
     if( pszProjParms != NULL )
     {
         char **papszTokens = CSLTokenizeString( pszProjParms );
 
-        for( int i=0; papszTokens != NULL && papszTokens[i] != NULL && i < 16; i++)
+        for( int i = 0;
+             i < 16 && papszTokens != NULL && papszTokens[i] != NULL;
+             i++ )
             adfProjParms[i] = CPLAtof(papszTokens[i]);
 
         CSLDestroy( papszTokens );
@@ -387,17 +388,20 @@ char *PAuxDataset::PCI2WKT( const char *pszGeosys,
 void PAuxDataset::ScanForGCPs()
 
 {
-    static const int MAX_GCP = 256;
+    const int MAX_GCP = 256;
 
     nGCPCount = 0;
+    CPLAssert( pasGCPList == NULL );
     pasGCPList = reinterpret_cast<GDAL_GCP *>(
         CPLCalloc( sizeof(GDAL_GCP), MAX_GCP ) );
 
 /* -------------------------------------------------------------------- */
 /*      Get the GCP coordinate system.                                  */
 /* -------------------------------------------------------------------- */
-    const char *pszMapUnits = CSLFetchNameValue( papszAuxLines, "GCP_1_MapUnits" );
-    const char *pszProjParms = CSLFetchNameValue( papszAuxLines, "GCP_1_ProjParms" );
+    const char *pszMapUnits =
+        CSLFetchNameValue( papszAuxLines, "GCP_1_MapUnits" );
+    const char *pszProjParms =
+        CSLFetchNameValue( papszAuxLines, "GCP_1_ProjParms" );
 
     if( pszMapUnits != NULL )
         pszGCPProjection = PCI2WKT( pszMapUnits, pszProjParms );
@@ -409,7 +413,7 @@ void PAuxDataset::ScanForGCPs()
 /* -------------------------------------------------------------------- */
     for( int i = 0; nGCPCount < MAX_GCP; i++ )
     {
-        char szName[50];
+        char szName[50] = { '\0' };
         snprintf( szName, sizeof(szName), "GCP_1_%d", i+1 );
         if( CSLFetchNameValue( papszAuxLines, szName ) == NULL )
             break;
@@ -507,26 +511,10 @@ const char *PAuxDataset::GetProjectionRef()
 CPLErr PAuxDataset::GetGeoTransform( double * padfGeoTransform )
 
 {
-    if( CSLFetchNameValue(papszAuxLines, "UpLeftX") != NULL
-        && CSLFetchNameValue(papszAuxLines, "UpLeftY") != NULL
-        && CSLFetchNameValue(papszAuxLines, "LoRightX") != NULL
-        && CSLFetchNameValue(papszAuxLines, "LoRightY") != NULL )
-    {
-        const double dfUpLeftX = CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftX" ));
-        const double dfUpLeftY = CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftY" ));
-        const double dfLoRightX = CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightX" ));
-        const double dfLoRightY = CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightY" ));
-
-        padfGeoTransform[0] = dfUpLeftX;
-        padfGeoTransform[1] = (dfLoRightX - dfUpLeftX) / GetRasterXSize();
-        padfGeoTransform[2] = 0.0;
-        padfGeoTransform[3] = dfUpLeftY;
-        padfGeoTransform[4] = 0.0;
-        padfGeoTransform[5] = (dfLoRightY - dfUpLeftY) / GetRasterYSize();
-
-        return CE_None;
-    }
-    else
+    if( CSLFetchNameValue(papszAuxLines, "UpLeftX") == NULL
+        || CSLFetchNameValue(papszAuxLines, "UpLeftY") == NULL
+        || CSLFetchNameValue(papszAuxLines, "LoRightX") == NULL
+        || CSLFetchNameValue(papszAuxLines, "LoRightY") == NULL )
     {
         padfGeoTransform[0] = 0.0;
         padfGeoTransform[1] = 1.0;
@@ -537,6 +525,24 @@ CPLErr PAuxDataset::GetGeoTransform( double * padfGeoTransform )
 
         return CE_Failure;
     }
+
+    const double dfUpLeftX =
+        CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftX" ));
+    const double dfUpLeftY =
+        CPLAtof(CSLFetchNameValue(papszAuxLines, "UpLeftY" ));
+    const double dfLoRightX =
+        CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightX" ));
+    const double dfLoRightY =
+        CPLAtof(CSLFetchNameValue(papszAuxLines, "LoRightY" ));
+
+    padfGeoTransform[0] = dfUpLeftX;
+    padfGeoTransform[1] = (dfLoRightX - dfUpLeftX) / GetRasterXSize();
+    padfGeoTransform[2] = 0.0;
+    padfGeoTransform[3] = dfUpLeftY;
+    padfGeoTransform[4] = 0.0;
+    padfGeoTransform[5] = (dfLoRightY - dfUpLeftY) / GetRasterYSize();
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -546,29 +552,37 @@ CPLErr PAuxDataset::GetGeoTransform( double * padfGeoTransform )
 CPLErr PAuxDataset::SetGeoTransform( double * padfGeoTransform )
 
 {
-    char szUpLeftX[128];
-    char szUpLeftY[128];
-    char szLoRightX[128];
-    char szLoRightY[128];
+    char szUpLeftX[128] = { '\0' };
+    char szUpLeftY[128] = { '\0' };
+    char szLoRightX[128] = { '\0' };
+    char szLoRightY[128] = { '\0' };
 
-    if( ABS(padfGeoTransform[0]) < 181
-        && ABS(padfGeoTransform[1]) < 1 )
+    if( std::abs(padfGeoTransform[0]) < 181
+        && std::abs(padfGeoTransform[1]) < 1 )
     {
-        CPLsnprintf( szUpLeftX, sizeof(szUpLeftX), "%.12f", padfGeoTransform[0] );
-        CPLsnprintf( szUpLeftY, sizeof(szUpLeftY), "%.12f", padfGeoTransform[3] );
+        CPLsnprintf( szUpLeftX, sizeof(szUpLeftX), "%.12f",
+                     padfGeoTransform[0] );
+        CPLsnprintf( szUpLeftY, sizeof(szUpLeftY), "%.12f",
+                     padfGeoTransform[3] );
         CPLsnprintf( szLoRightX, sizeof(szLoRightX), "%.12f",
-               padfGeoTransform[0] + padfGeoTransform[1] * GetRasterXSize() );
+                     padfGeoTransform[0] +
+                     padfGeoTransform[1] * GetRasterXSize() );
         CPLsnprintf( szLoRightY, sizeof(szLoRightY), "%.12f",
-               padfGeoTransform[3] + padfGeoTransform[5] * GetRasterYSize() );
+                     padfGeoTransform[3] +
+                     padfGeoTransform[5] * GetRasterYSize() );
     }
     else
     {
-        CPLsnprintf( szUpLeftX, sizeof(szUpLeftX), "%.3f", padfGeoTransform[0] );
-        CPLsnprintf( szUpLeftY, sizeof(szUpLeftY), "%.3f", padfGeoTransform[3] );
+        CPLsnprintf( szUpLeftX, sizeof(szUpLeftX), "%.3f",
+                     padfGeoTransform[0] );
+        CPLsnprintf( szUpLeftY, sizeof(szUpLeftY), "%.3f",
+                     padfGeoTransform[3] );
         CPLsnprintf( szLoRightX, sizeof(szLoRightX), "%.3f",
-               padfGeoTransform[0] + padfGeoTransform[1] * GetRasterXSize() );
+                     padfGeoTransform[0] +
+                     padfGeoTransform[1] * GetRasterXSize() );
         CPLsnprintf( szLoRightY, sizeof(szLoRightY), "%.3f",
-               padfGeoTransform[3] + padfGeoTransform[5] * GetRasterYSize() );
+                     padfGeoTransform[3] +
+                     padfGeoTransform[5] * GetRasterYSize() );
     }
 
     papszAuxLines = CSLSetNameValue( papszAuxLines, "UpLeftX", szUpLeftX );
@@ -599,25 +613,24 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
     CPLString osTarget = poOpenInfo->pszFilename;
 
     if( EQUAL(CPLGetExtension( poOpenInfo->pszFilename ),"aux")
-        && STARTS_WITH_CI((const char *) poOpenInfo->pabyHeader, "AuxilaryTarget: "))
+        && STARTS_WITH_CI(reinterpret_cast<char *>( poOpenInfo->pabyHeader ),
+                          "AuxilaryTarget: ") )
     {
-        char szAuxTarget[1024];
         const char *pszSrc = reinterpret_cast<const char *>(
             poOpenInfo->pabyHeader+16 );
 
-        int i = 0;
-        for( ;
-             pszSrc[i] != 10 && pszSrc[i] != 13 && pszSrc[i] != '\0'
-                 && i < static_cast<int>( sizeof(szAuxTarget) ) - 1;
+        char szAuxTarget[1024] = { '\0' };
+        for( int i = 0;
+             i < static_cast<int>( sizeof(szAuxTarget) ) - 1 &&
+             pszSrc[i] != 10 && pszSrc[i] != 13 && pszSrc[i] != '\0';
              i++ )
         {
             szAuxTarget[i] = pszSrc[i];
         }
-        szAuxTarget[i] = '\0';
+        szAuxTarget[sizeof(szAuxTarget) - 1] = '\0';
 
-        char *pszPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
-        osTarget = CPLFormFilename(pszPath, szAuxTarget, NULL);
-        CPLFree(pszPath);
+        const std::string osPath(CPLGetPath(poOpenInfo->pszFilename));
+        osTarget = CPLFormFilename(osPath.c_str(), szAuxTarget, NULL);
     }
 
 /* -------------------------------------------------------------------- */
@@ -753,7 +766,7 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
     int iBand = 0;
     for( int i = 0; i < poDS->nBands; i++ )
     {
-        char szDefnName[32];
+        char szDefnName[32] = { '\0' };
         snprintf( szDefnName, sizeof(szDefnName), "ChanDefinition-%d", i+1 );
 
         pszLine = CSLFetchNameValue(poDS->papszAuxLines, szDefnName);
@@ -770,7 +783,7 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
             continue;
         }
 
-        GDALDataType eType;
+        GDALDataType eType = GDT_Unknown;
         if( EQUAL(papszTokens[0],"16U") )
             eType = GDT_UInt16;
         else if( EQUAL(papszTokens[0],"16S") )
@@ -780,24 +793,25 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
         else
             eType = GDT_Byte;
 
-        int bNative = TRUE;
+        bool bNative = true;
         if( CSLCount(papszTokens) > 4 )
         {
 #ifdef CPL_LSB
-            bNative = EQUAL(papszTokens[4],"Swapped");
+            bNative = EQUAL(papszTokens[4], "Swapped");
 #else
-            bNative = EQUAL(papszTokens[4],"Unswapped");
+            bNative = EQUAL(papszTokens[4], "Unswapped");
 #endif
         }
 
-        const vsi_l_offset nBandOffset = CPLScanUIntBig(papszTokens[1],
-                                               static_cast<int>(strlen(papszTokens[1])));
+        const vsi_l_offset nBandOffset =
+            CPLScanUIntBig( papszTokens[1],
+                            static_cast<int>(strlen(papszTokens[1])) );
         const int nPixelOffset = atoi(papszTokens[2]);
         const int nLineOffset = atoi(papszTokens[3]);
 
         if (nPixelOffset <= 0 || nLineOffset <= 0)
         {
-            // Skip the band with broken offsets
+            // Skip the band with broken offsets.
             CSLDestroy( papszTokens );
             continue;
         }
@@ -817,8 +831,10 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Get the projection.                                             */
 /* -------------------------------------------------------------------- */
-    const char *pszMapUnits = CSLFetchNameValue( poDS->papszAuxLines, "MapUnits" );
-    const char *pszProjParms = CSLFetchNameValue( poDS->papszAuxLines, "ProjParms" );
+    const char *pszMapUnits =
+        CSLFetchNameValue( poDS->papszAuxLines, "MapUnits" );
+    const char *pszProjParms =
+        CSLFetchNameValue( poDS->papszAuxLines, "ProjParms" );
 
     if( pszMapUnits != NULL )
         poDS->pszProjection = poDS->PCI2WKT( pszMapUnits, pszProjParms );
@@ -837,7 +853,7 @@ GDALDataset *PAuxDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->ScanForGCPs();
     poDS->bAuxUpdated = FALSE;
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -874,7 +890,7 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
     int nPixelSizeSum = 0;
 
     for( int iBand = 0; iBand < nBands; iBand++ )
-        nPixelSizeSum += (GDALGetDataTypeSize(eType)/8);
+        nPixelSizeSum += GDALGetDataTypeSizeBytes(eType);
 
 /* -------------------------------------------------------------------- */
 /*      Try to create the file.                                         */
@@ -892,16 +908,15 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
 /*      Just write out a couple of bytes to establish the binary        */
 /*      file, and then close it.                                        */
 /* -------------------------------------------------------------------- */
-    CPL_IGNORE_RET_VAL(VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "\0\0" ) ),
-                2, 1, fp ));
+    CPL_IGNORE_RET_VAL(VSIFWriteL( "\0\0", 2, 1, fp ));
     CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
 /*      Create the aux filename.                                        */
 /* -------------------------------------------------------------------- */
-    char *pszAuxFilename = reinterpret_cast<char *>(
+    char *pszAuxFilename = static_cast<char *>(
         CPLMalloc( strlen( pszFilename ) + 5 ) );
-    strcpy( pszAuxFilename, pszFilename );;
+    strcpy( pszAuxFilename, pszFilename );
 
     for( int i = static_cast<int>(strlen(pszAuxFilename))-1; i > 0; i-- )
     {
@@ -949,21 +964,20 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
 /*      sequential files for now as these are pretty efficiently        */
 /*      handled by GDAL.                                                */
 /* -------------------------------------------------------------------- */
-    vsi_l_offset    nImgOffset = 0;
+    vsi_l_offset nImgOffset = 0;
 
     for( int iBand = 0; iBand < nBands; iBand++ )
     {
-        const char  *pszTypeName;
-        int nPixelOffset;
-        int nLineOffset;
-        vsi_l_offset nNextImgOffset;
+        int nPixelOffset = 0;
+        int nLineOffset = 0;
+        vsi_l_offset nNextImgOffset = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Establish our file layout based on supplied interleaving.       */
 /* -------------------------------------------------------------------- */
         if( EQUAL(pszInterleave,"LINE") )
         {
-            nPixelOffset = GDALGetDataTypeSize(eType)/8;
+            nPixelOffset = GDALGetDataTypeSizeBytes(eType);
             nLineOffset = nXSize * nPixelSizeSum;
             nNextImgOffset = nImgOffset + nPixelOffset * nXSize;
         }
@@ -971,18 +985,20 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
         {
             nPixelOffset = nPixelSizeSum;
             nLineOffset = nXSize * nPixelOffset;
-            nNextImgOffset = nImgOffset + (GDALGetDataTypeSize(eType)/8);
+            nNextImgOffset = nImgOffset + GDALGetDataTypeSizeBytes(eType);
         }
         else /* default to band */
         {
             nPixelOffset = GDALGetDataTypeSize(eType)/8;
             nLineOffset = nXSize * nPixelOffset;
-            nNextImgOffset = nImgOffset + nYSize * (vsi_l_offset) nLineOffset;
+            nNextImgOffset =
+                nImgOffset + nYSize * static_cast<vsi_l_offset>( nLineOffset );
         }
 
 /* -------------------------------------------------------------------- */
 /*      Write out line indicating layout.                               */
 /* -------------------------------------------------------------------- */
+        const char *pszTypeName = NULL;
         if( eType == GDT_Float32 )
             pszTypeName = "32R";
         else if( eType == GDT_Int16 )
@@ -992,16 +1008,17 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
         else
             pszTypeName = "8U";
 
-        CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "ChanDefinition-%d: %s " CPL_FRMT_GIB " %d %d %s\n",
-                                        iBand+1,
-                                        pszTypeName, (GIntBig) nImgOffset,
-                                        nPixelOffset, nLineOffset,
+        CPL_IGNORE_RET_VAL(
+            VSIFPrintfL( fp, "ChanDefinition-%d: %s " CPL_FRMT_GIB " %d %d %s\n",
+                         iBand+1,
+                         pszTypeName, static_cast<GIntBig>( nImgOffset ),
+                         nPixelOffset, nLineOffset,
 #ifdef CPL_LSB
-                    "Swapped"
+                         "Swapped"
 #else
-                    "Unswapped"
+                         "Unswapped"
 #endif
-                    ));
+                         ) );
 
         nImgOffset = nNextImgOffset;
     }
@@ -1011,7 +1028,7 @@ GDALDataset *PAuxDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
-    return reinterpret_cast<GDALDataset *>(
+    return static_cast<GDALDataset *>(
         GDALOpen( pszFilename, GA_Update ) );
 }
 
@@ -1026,7 +1043,8 @@ static CPLErr PAuxDelete( const char * pszBasename )
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s does not appear to be a PAux dataset, there is no .aux file.",
+                  "%s does not appear to be a PAux dataset: "
+                  "there is no .aux file.",
                   pszBasename );
         return CE_Failure;
     }
@@ -1037,7 +1055,7 @@ static CPLErr PAuxDelete( const char * pszBasename )
     if( pszLine == NULL || !STARTS_WITH_CI(pszLine, "AuxilaryTarget") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s does not appear to be a PAux dataset,\n"
+                  "%s does not appear to be a PAux dataset:"
                   "the .aux file does not start with AuxilaryTarget",
                   pszBasename );
         return CE_Failure;
@@ -1073,14 +1091,15 @@ void GDALRegister_PAux()
     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "frmt_various.html#PAux" );
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
                                "Byte Int16 UInt16 Float32" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-"<CreationOptionList>"
-"   <Option name='INTERLEAVE' type='string-select' default='BAND'>"
-"       <Value>BAND</Value>"
-"       <Value>LINE</Value>"
-"       <Value>PIXEL</Value>"
-"   </Option>"
-"</CreationOptionList>" );
+    poDriver->SetMetadataItem(
+        GDAL_DMD_CREATIONOPTIONLIST,
+        "<CreationOptionList>"
+        "   <Option name='INTERLEAVE' type='string-select' default='BAND'>"
+        "       <Value>BAND</Value>"
+        "       <Value>LINE</Value>"
+        "       <Value>PIXEL</Value>"
+        "   </Option>"
+        "</CreationOptionList>" );
 
     poDriver->pfnOpen = PAuxDataset::Open;
     poDriver->pfnCreate = PAuxDataset::Create;
diff --git a/frmts/raw/pnmdataset.cpp b/frmts/raw/pnmdataset.cpp
index b13c0dd..4adccda 100644
--- a/frmts/raw/pnmdataset.cpp
+++ b/frmts/raw/pnmdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: pnmdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  PNM Driver
  * Purpose:  Portable anymap file format imlementation
@@ -31,13 +30,9 @@
 #include "cpl_string.h"
 #include "gdal_frmts.h"
 #include "rawdataset.h"
-#include <ctype.h>
+#include <cctype>
 
-CPL_CVSID("$Id: pnmdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
-
-CPL_C_START
-void GDALRegister_PNM();
-CPL_C_END
+CPL_CVSID("$Id: pnmdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -47,16 +42,16 @@ CPL_C_END
 
 class PNMDataset : public RawDataset
 {
-    VSILFILE        *fpImage;       // image data file.
+    VSILFILE   *fpImage;  // Image data file.
 
-    int         bGeoTransformValid;
+    bool        bGeoTransformValid;
     double      adfGeoTransform[6];
 
   public:
                 PNMDataset();
     virtual ~PNMDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
@@ -71,7 +66,7 @@ class PNMDataset : public RawDataset
 
 PNMDataset::PNMDataset() :
     fpImage(NULL),
-    bGeoTransformValid(FALSE)
+    bGeoTransformValid(false)
 {
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -89,12 +84,9 @@ PNMDataset::~PNMDataset()
 
 {
     FlushCache();
-    if( fpImage != NULL )
+    if( fpImage != NULL && VSIFCloseL( fpImage ) != 0 )
     {
-        if( VSIFCloseL( fpImage ) != 0 )
-        {
-            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
-        }
+        CPLError(CE_Failure, CPLE_FileIO, "I/O error" );
     }
 }
 
@@ -129,10 +121,10 @@ int PNMDataset::Identify( GDALOpenInfo * poOpenInfo )
         return FALSE;
 
     if( poOpenInfo->pabyHeader[0] != 'P'  ||
-        (poOpenInfo->pabyHeader[2] != ' '  &&    // XXX: Magick number
-         poOpenInfo->pabyHeader[2] != '\t' &&    // may be followed
-         poOpenInfo->pabyHeader[2] != '\n' &&    // any of the blank
-         poOpenInfo->pabyHeader[2] != '\r') )    // characters
+        (poOpenInfo->pabyHeader[2] != ' '  &&  // XXX: Magick number
+         poOpenInfo->pabyHeader[2] != '\t' &&  // may be followed
+         poOpenInfo->pabyHeader[2] != '\n' &&  // any of the blank
+         poOpenInfo->pabyHeader[2] != '\r') )  // characters
         return FALSE;
 
     if( poOpenInfo->pabyHeader[1] != '5'
@@ -159,29 +151,28 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Parse out the tokens from the header.                           */
 /* -------------------------------------------------------------------- */
-    const char  *pszSrc = (const char *) poOpenInfo->pabyHeader;
-    char szToken[512];
+    const char *pszSrc = reinterpret_cast<char *>( poOpenInfo->pabyHeader );
+    char szToken[512] = { '\0' };
     int iToken = 0;
     int nWidth = -1;
     int nHeight = -1;
     int nMaxValue = -1;
-    unsigned int iOut;
 
     int iIn = 2;
     while( iIn < poOpenInfo->nHeaderBytes && iToken < 3 )
     {
-        iOut = 0;
+        unsigned int iOut = 0;
         szToken[0] = '\0';
         while( iOut < sizeof(szToken) && iIn < poOpenInfo->nHeaderBytes )
         {
             if( pszSrc[iIn] == '#' )
             {
-                while( pszSrc[iIn] != 10 && pszSrc[iIn] != 13
-                       && iIn < poOpenInfo->nHeaderBytes - 1 )
+                while( iIn < poOpenInfo->nHeaderBytes - 1 &&
+                       pszSrc[iIn] != 10 && pszSrc[iIn] != 13 )
                     iIn++;
             }
 
-            if( iOut != 0 && isspace((unsigned char)pszSrc[iIn]) )
+            if( iOut != 0 && isspace(static_cast<unsigned char>(pszSrc[iIn])) )
             {
                 szToken[iOut] = '\0';
 
@@ -197,7 +188,7 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
                 break;
             }
 
-            else if( !isspace((unsigned char)pszSrc[iIn]) )
+            else if( !isspace(static_cast<unsigned char>(pszSrc[iIn])) )
             {
                 szToken[iOut++] = pszSrc[iIn];
             }
@@ -235,7 +226,7 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
     if( poDS->fpImage == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to re-open %s within PNM driver.\n",
+                  "Failed to re-open %s within PNM driver.",
                   poOpenInfo->pszFilename );
         return NULL;
     }
@@ -246,18 +237,18 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
 #ifdef CPL_LSB
-    const int bMSBFirst = FALSE;
+    const bool bMSBFirst = false;
 #else
-    const int bMSBFirst = TRUE;
+    const bool bMSBFirst = true;
 #endif
 
-    GDALDataType eDataType;
+    GDALDataType eDataType = GDT_Unknown;
     if ( nMaxValue < 256 )
         eDataType = GDT_Byte;
     else
         eDataType = GDT_UInt16;
 
-    const int iPixelSize = GDALGetDataTypeSize( eDataType ) / 8;
+    const int iPixelSize = GDALGetDataTypeSizeBytes( eDataType );
 
     if( poOpenInfo->pabyHeader[1] == '5' )
     {
@@ -270,7 +261,8 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         poDS->SetBand(
             1, new RawRasterBand( poDS, 1, poDS->fpImage, iIn, iPixelSize,
-                                  nWidth*iPixelSize, eDataType, bMSBFirst, TRUE ));
+                                  nWidth*iPixelSize, eDataType, bMSBFirst,
+                                  TRUE ) );
         poDS->GetRasterBand(1)->SetColorInterpretation( GCI_GrayIndex );
     }
     else
@@ -284,7 +276,8 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
         }
         poDS->SetBand(
             1, new RawRasterBand( poDS, 1, poDS->fpImage, iIn, 3*iPixelSize,
-                                  nWidth*3*iPixelSize, eDataType, bMSBFirst, TRUE ));
+                                  nWidth*3*iPixelSize, eDataType, bMSBFirst,
+                                  TRUE ));
         poDS->SetBand(
             2, new RawRasterBand( poDS, 2, poDS->fpImage, iIn+iPixelSize,
                                   3*iPixelSize, nWidth*3*iPixelSize,
@@ -303,8 +296,9 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Check for world file.                                           */
 /* -------------------------------------------------------------------- */
     poDS->bGeoTransformValid =
-        GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
-                           poDS->adfGeoTransform );
+        CPL_TO_BOOL(
+            GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
+                               poDS->adfGeoTransform ) );
 
 /* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
@@ -317,7 +311,7 @@ GDALDataset *PNMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -336,8 +330,8 @@ GDALDataset *PNMDataset::Create( const char * pszFilename,
     if( eType != GDT_Byte && eType != GDT_UInt16 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create PNM dataset with an illegal\n"
-              "data type (%s), only Byte and UInt16 supported.\n",
+              "Attempt to create PNM dataset with an illegal "
+              "data type (%s), only Byte and UInt16 supported.",
               GDALGetDataTypeName(eType) );
 
         return NULL;
@@ -346,8 +340,8 @@ GDALDataset *PNMDataset::Create( const char * pszFilename,
     if( nBands != 1 && nBands != 3 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to create PNM dataset with an illegal number\n"
-                  "of bands (%d).  Must be 1 (greyscale) or 3 (RGB).\n",
+                  "Attempt to create PNM dataset with an illegal number"
+                  "of bands (%d).  Must be 1 (greyscale) or 3 (RGB).",
                   nBands );
 
         return NULL;
@@ -360,7 +354,7 @@ GDALDataset *PNMDataset::Create( const char * pszFilename,
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
+                  "Attempt to create file `%s' failed.",
                   pszFilename );
         return NULL;
     }
@@ -368,7 +362,7 @@ GDALDataset *PNMDataset::Create( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Write out the header.                                           */
 /* -------------------------------------------------------------------- */
-    int         nMaxValue = 0;
+    int nMaxValue = 0;
 
     const char *pszMaxValue = CSLFetchNameValue( papszOptions, "MAXVAL" );
     if ( pszMaxValue )
@@ -387,22 +381,23 @@ GDALDataset *PNMDataset::Create( const char * pszFilename,
             nMaxValue = 65535;
     }
 
-    char szHeader[500];
-    memset( szHeader, 0, sizeof(szHeader) );
+    char szHeader[500] = { '\0' };
 
     if( nBands == 3 )
-        snprintf( szHeader, sizeof(szHeader), "P6\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
+        snprintf( szHeader, sizeof(szHeader),
+                  "P6\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
     else
-        snprintf( szHeader, sizeof(szHeader), "P5\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
+        snprintf( szHeader, sizeof(szHeader),
+                  "P5\n%d %d\n%d\n", nXSize, nYSize, nMaxValue );
 
-    bool bOK = VSIFWriteL( reinterpret_cast<void *>( szHeader ),
-                strlen(szHeader) + 2, 1, fp ) == 1;
+    bool bOK = VSIFWriteL( szHeader, strlen(szHeader) + 2, 1, fp ) == 1;
     if( VSIFCloseL( fp ) != 0 )
         bOK = false;
 
     if( !bOK )
         return NULL;
-    return reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
+    return
+        reinterpret_cast<GDALDataset *>( GDALOpen( pszFilename, GA_Update ) );
 }
 
 /************************************************************************/
diff --git a/frmts/raw/rawdataset.cpp b/frmts/raw/rawdataset.cpp
index e8bedf9..007f138 100644
--- a/frmts/raw/rawdataset.cpp
+++ b/frmts/raw/rawdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rawdataset.cpp 33840 2016-04-01 00:47:00Z goatbar $
  *
  * Project:  Generic Raw Binary Driver
  * Purpose:  Implementation of RawDataset and RawRasterBand classes.
@@ -28,17 +27,30 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "rawdataset.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
 
+#include <climits>
 #include <cmath>
 #include <cstddef>
 #include <cstdlib>
-
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
 #include <algorithm>
+#include <limits>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_virtualmem.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: rawdataset.cpp 33840 2016-04-01 00:47:00Z goatbar $");
+CPL_CVSID("$Id: rawdataset.cpp 37414 2017-02-18 12:13:26Z goatbar $");
 
 /************************************************************************/
 /*                           RawRasterBand()                            */
@@ -64,29 +76,25 @@ RawRasterBand::RawRasterBand( GDALDataset *poDSIn, int nBandIn,
 
     if (bIsVSIL)
     {
-        fpRawL = reinterpret_cast<VSILFILE *>( fpRawIn );
+        fpRawL = reinterpret_cast<VSILFILE *>(fpRawIn);
     }
     else
     {
-        fpRaw = reinterpret_cast<FILE *>( fpRawIn );
+        fpRaw = reinterpret_cast<FILE *>(fpRawIn);
     }
 
-    CPLDebug( "GDALRaw",
-              "RawRasterBand(%p,%d,%p,\n"
-              "              Off=%d,PixOff=%d,LineOff=%d,%s,%d)",
-              poDS, nBand, fpRaw,
-              static_cast<unsigned int>(nImgOffset), nPixelOffset, nLineOffset,
-              GDALGetDataTypeName(eDataType), bNativeOrder );
+    CPLDebug("GDALRaw",
+             "RawRasterBand(%p,%d,%p,\n"
+             "              Off=%d,PixOff=%d,LineOff=%d,%s,%d)",
+             poDS, nBand, fpRaw,
+             static_cast<unsigned int>(nImgOffset), nPixelOffset, nLineOffset,
+             GDALGetDataTypeName(eDataType), bNativeOrder);
 
-/* -------------------------------------------------------------------- */
-/*      Treat one scanline as the block size.                           */
-/* -------------------------------------------------------------------- */
+    // Treat one scanline as the block size.
     nBlockXSize = poDS->GetRasterXSize();
     nBlockYSize = 1;
 
-/* -------------------------------------------------------------------- */
-/*      Initialize other fields, and setup the line buffer.             */
-/* -------------------------------------------------------------------- */
+    // Initialize other fields, and setup the line buffer.
     Initialize();
 }
 
@@ -121,22 +129,20 @@ RawRasterBand::RawRasterBand( void *fpRawIn, vsi_l_offset nImgOffsetIn,
 
     if (bIsVSIL)
     {
-        fpRawL = reinterpret_cast<VSILFILE *>( fpRawIn );
+        fpRawL = reinterpret_cast<VSILFILE *>(fpRawIn);
     }
     else
     {
-        fpRaw = reinterpret_cast<FILE *>( fpRawIn );
+        fpRaw = reinterpret_cast<FILE *>(fpRawIn);
     }
 
-    CPLDebug( "GDALRaw",
-              "RawRasterBand(floating,Off=%d,PixOff=%d,LineOff=%d,%s,%d)",
-              static_cast<unsigned int>( nImgOffset ),
-              nPixelOffset, nLineOffset,
-              GDALGetDataTypeName(eDataType), bNativeOrder );
+    CPLDebug("GDALRaw",
+             "RawRasterBand(floating,Off=%d,PixOff=%d,LineOff=%d,%s,%d)",
+             static_cast<unsigned int>(nImgOffset),
+             nPixelOffset, nLineOffset,
+             GDALGetDataTypeName(eDataType), bNativeOrder);
 
-/* -------------------------------------------------------------------- */
-/*      Treat one scanline as the block size.                           */
-/* -------------------------------------------------------------------- */
+    // Treat one scanline as the block size.
     nBlockXSize = nXSize;
     nBlockYSize = 1;
     nRasterXSize = nXSize;
@@ -147,9 +153,7 @@ RawRasterBand::RawRasterBand( void *fpRawIn, vsi_l_offset nImgOffsetIn,
         return;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Initialize other fields, and setup the line buffer.             */
-/* -------------------------------------------------------------------- */
+    // Initialize other fields, and setup the line buffer.
     Initialize();
 }
 
@@ -167,11 +171,10 @@ void RawRasterBand::Initialize()
 
     bDirty = FALSE;
 
-/* -------------------------------------------------------------------- */
-/*      Allocate working scanline.                                      */
-/* -------------------------------------------------------------------- */
+    // Allocate working scanline.
     nLoadedScanline = -1;
-    if (nBlockXSize <= 0 || std::abs(nPixelOffset) > INT_MAX / nBlockXSize)
+    if (nBlockXSize <= 0 ||
+        std::abs(nPixelOffset) > std::numeric_limits<int>::max() / nBlockXSize)
     {
         nLineSize = 0;
         pLineBuffer = NULL;
@@ -179,22 +182,22 @@ void RawRasterBand::Initialize()
     else
     {
         nLineSize = std::abs(nPixelOffset) * nBlockXSize;
-        pLineBuffer = VSIMalloc2( std::abs(nPixelOffset), nBlockXSize );
+        pLineBuffer = VSIMalloc2(std::abs(nPixelOffset), nBlockXSize);
     }
     if (pLineBuffer == NULL)
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Could not allocate line buffer: "
-                  "nPixelOffset=%d, nBlockXSize=%d",
-                  nPixelOffset, nBlockXSize);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Could not allocate line buffer: "
+                 "nPixelOffset=%d, nBlockXSize=%d",
+                 nPixelOffset, nBlockXSize);
     }
 
     if( nPixelOffset >= 0 )
         pLineStart = pLineBuffer;
     else
-        pLineStart = reinterpret_cast<char *> (pLineBuffer )
-            + static_cast<std::ptrdiff_t>( std::abs( nPixelOffset ) )
-            * ( nBlockXSize - 1 );
+        pLineStart = static_cast<char *>(pLineBuffer) +
+                     static_cast<std::ptrdiff_t>(std::abs(nPixelOffset)) *
+                         (nBlockXSize - 1);
 }
 
 /************************************************************************/
@@ -207,7 +210,7 @@ RawRasterBand::~RawRasterBand()
     if( poCT )
         delete poCT;
 
-    CSLDestroy( papszCategoryNames );
+    CSLDestroy(papszCategoryNames);
 
     FlushCache();
 
@@ -215,29 +218,25 @@ RawRasterBand::~RawRasterBand()
     {
         if ( bIsVSIL )
         {
-            if( VSIFCloseL( fpRawL ) != 0 )
+            if( VSIFCloseL(fpRawL) != 0 )
             {
                 CPLError(CE_Failure, CPLE_FileIO, "I/O error");
             }
         }
         else
         {
-            VSIFClose( fpRaw );
+            VSIFClose(fpRaw);
         }
     }
 
-    CPLFree( pLineBuffer );
+    CPLFree(pLineBuffer);
 }
 
-
 /************************************************************************/
 /*                             SetAccess()                              */
 /************************************************************************/
 
-void  RawRasterBand::SetAccess( GDALAccess eAccessIn )
-{
-    eAccess = eAccessIn;
-}
+void RawRasterBand::SetAccess(GDALAccess eAccessIn) { eAccess = eAccessIn; }
 
 /************************************************************************/
 /*                             FlushCache()                             */
@@ -252,16 +251,19 @@ CPLErr RawRasterBand::FlushCache()
 {
     CPLErr eErr = GDALRasterBand::FlushCache();
     if( eErr != CE_None )
+    {
+        bDirty = FALSE;
         return eErr;
+    }
 
     // If we have unflushed raw, flush it to disk now.
     if ( bDirty )
     {
         int nRet = 0;
         if( bIsVSIL )
-            nRet = VSIFFlushL( fpRawL );
+            nRet = VSIFFlushL(fpRawL);
         else
-            /*nRet = */VSIFFlush( fpRaw );
+            /* nRet = */ VSIFFlush(fpRaw);
 
         bDirty = FALSE;
         if( nRet < 0 )
@@ -284,84 +286,72 @@ CPLErr RawRasterBand::AccessLine( int iLine )
     if( nLoadedScanline == iLine )
         return CE_None;
 
-/* -------------------------------------------------------------------- */
-/*      Figure out where to start reading.                              */
-/* -------------------------------------------------------------------- */
-    vsi_l_offset nReadStart;
-    if( nPixelOffset >= 0 )
-    {
-        nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset;
-    }
-    else
-    {
-        nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset
-            - std::abs(nPixelOffset) * (nBlockXSize-1);
-    }
+    // Figure out where to start reading.
+    // Negative nPixelOffset is used to specify the offset.
+    const GIntBig nPixelOffsetActual =
+        nPixelOffset >= 0
+        ? 0 : nPixelOffset * static_cast<GIntBig>(nBlockXSize - 1);
+    const vsi_l_offset nReadStart = static_cast<vsi_l_offset>(
+        nImgOffset + static_cast<GIntBig>(iLine) * nLineOffset +
+        nPixelOffsetActual);
 
-/* -------------------------------------------------------------------- */
-/*      Seek to the right line.                                         */
-/* -------------------------------------------------------------------- */
+    // Seek to the correct line.
     if( Seek(nReadStart, SEEK_SET) == -1 )
     {
         if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
         {
-            CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to scanline %d @ " CPL_FRMT_GUIB ".",
-                  iLine, nImgOffset + (vsi_l_offset)iLine * nLineOffset );
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Failed to seek to scanline %d @ " CPL_FRMT_GUIB ".",
+                     iLine, nReadStart);
             return CE_Failure;
         }
         else
         {
-            memset( pLineBuffer, 0, nLineSize );
+            memset(pLineBuffer, 0, nLineSize);
             nLoadedScanline = iLine;
             return CE_None;
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the line.  Take care not to request any more bytes than    */
-/*      are needed, and not to lose a partially successful scanline     */
-/*      read.                                                           */
-/* -------------------------------------------------------------------- */
+    // Read the line.  Take care not to request any more bytes than
+    // are needed, and not to lose a partially successful scanline read.
     const size_t nBytesToRead = std::abs(nPixelOffset) * (nBlockXSize - 1)
         + GDALGetDataTypeSizeBytes(GetRasterDataType());
 
-    const size_t nBytesActuallyRead = Read( pLineBuffer, 1, nBytesToRead );
+    const size_t nBytesActuallyRead = Read(pLineBuffer, 1, nBytesToRead);
     if( nBytesActuallyRead < nBytesToRead )
     {
         if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
         {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Failed to read scanline %d.",
-                      iLine);
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Failed to read scanline %d.",
+                     iLine);
             return CE_Failure;
         }
         else
         {
             memset(
-                reinterpret_cast<GByte *>( pLineBuffer ) + nBytesActuallyRead,
-                0, nBytesToRead - nBytesActuallyRead );
+                static_cast<GByte *>(pLineBuffer) + nBytesActuallyRead,
+                0, nBytesToRead - nBytesActuallyRead);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Byte swap the interesting data, if required.                    */
-/* -------------------------------------------------------------------- */
+    // Byte swap the interesting data, if required.
     if( !bNativeOrder && eDataType != GDT_Byte )
     {
-        if( GDALDataTypeIsComplex( eDataType ) )
+        if( GDALDataTypeIsComplex(eDataType) )
         {
-            const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
-            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
-                           std::abs(nPixelOffset) );
+            const int nWordSize = GDALGetDataTypeSize(eDataType) / 16;
+            GDALSwapWords(pLineBuffer, nWordSize, nBlockXSize,
+                          std::abs(nPixelOffset));
             GDALSwapWords(
-                reinterpret_cast<GByte *>( pLineBuffer ) + nWordSize,
-                nWordSize, nBlockXSize, std::abs(nPixelOffset) );
+                static_cast<GByte *>(pLineBuffer) + nWordSize,
+                nWordSize, nBlockXSize, std::abs(nPixelOffset));
         }
         else
         {
-            GDALSwapWords( pLineBuffer, GDALGetDataTypeSizeBytes(eDataType),
-                           nBlockXSize, std::abs(nPixelOffset) );
+            GDALSwapWords(pLineBuffer, GDALGetDataTypeSizeBytes(eDataType),
+                          nBlockXSize, std::abs(nPixelOffset));
         }
     }
 
@@ -374,25 +364,23 @@ CPLErr RawRasterBand::AccessLine( int iLine )
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr RawRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
-                                  int nBlockYOff,
-                                  void * pImage )
+CPLErr RawRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
+                                 int nBlockYOff,
+                                 void *pImage)
 {
-    CPLAssert( nBlockXOff == 0 );
+    CPLAssert(nBlockXOff == 0);
 
     if (pLineBuffer == NULL)
         return CE_Failure;
 
-    const CPLErr eErr = AccessLine( nBlockYOff );
+    const CPLErr eErr = AccessLine(nBlockYOff);
     if( eErr == CE_Failure )
         return eErr;
 
-/* -------------------------------------------------------------------- */
-/*      Copy data from disk buffer to user block buffer.                */
-/* -------------------------------------------------------------------- */
-    GDALCopyWords( pLineStart, eDataType, nPixelOffset,
-                   pImage, eDataType, GDALGetDataTypeSizeBytes(eDataType),
-                   nBlockXSize );
+    // Copy data from disk buffer to user block buffer.
+    GDALCopyWords(pLineStart, eDataType, nPixelOffset,
+                  pImage, eDataType, GDALGetDataTypeSizeBytes(eDataType),
+                  nBlockXSize);
 
     return eErr;
 }
@@ -403,110 +391,94 @@ CPLErr RawRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
 CPLErr RawRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
                                    int nBlockYOff,
-                                   void * pImage )
+                                   void *pImage )
 {
-    CPLAssert( nBlockXOff == 0 );
+    CPLAssert(nBlockXOff == 0);
 
     if (pLineBuffer == NULL)
         return CE_Failure;
 
-/* -------------------------------------------------------------------- */
-/*      If the data for this band is completely contiguous we don't     */
-/*      have to worry about pre-reading from disk.                      */
-/* -------------------------------------------------------------------- */
+    // If the data for this band is completely contiguous, we don't
+    // have to worry about pre-reading from disk.
     CPLErr eErr = CE_None;
     if( std::abs(nPixelOffset) > GDALGetDataTypeSizeBytes(eDataType) )
-        eErr = AccessLine( nBlockYOff );
-
-/* -------------------------------------------------------------------- */
-/*      Copy data from user buffer into disk buffer.                    */
-/* -------------------------------------------------------------------- */
-    GDALCopyWords( pImage, eDataType, GDALGetDataTypeSizeBytes(eDataType),
-                   pLineStart, eDataType, nPixelOffset,
-                   nBlockXSize );
-
-/* -------------------------------------------------------------------- */
-/*      Byte swap (if necessary) back into disk order before writing.   */
-/* -------------------------------------------------------------------- */
+        eErr = AccessLine(nBlockYOff);
+
+    // Copy data from user buffer into disk buffer.
+    GDALCopyWords(pImage, eDataType, GDALGetDataTypeSizeBytes(eDataType),
+                  pLineStart, eDataType, nPixelOffset, nBlockXSize);
+
+
+    // Byte swap (if necessary) back into disk order before writing.
     if( !bNativeOrder && eDataType != GDT_Byte )
     {
-        if( GDALDataTypeIsComplex( eDataType ) )
+        if( GDALDataTypeIsComplex(eDataType) )
         {
-            const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
-            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
-                           std::abs(nPixelOffset) );
-            GDALSwapWords(
-                reinterpret_cast<GByte *>( pLineBuffer ) + nWordSize,
-                nWordSize, nBlockXSize, std::abs(nPixelOffset) );
+            const int nWordSize = GDALGetDataTypeSize(eDataType) / 16;
+            GDALSwapWords(pLineBuffer, nWordSize, nBlockXSize,
+                          std::abs(nPixelOffset));
+            GDALSwapWords(static_cast<GByte *>(pLineBuffer) + nWordSize,
+                          nWordSize, nBlockXSize, std::abs(nPixelOffset));
         }
         else
-            GDALSwapWords( pLineBuffer, GDALGetDataTypeSizeBytes(eDataType),
-                           nBlockXSize, std::abs(nPixelOffset) );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Figure out where to start reading.                              */
-/* -------------------------------------------------------------------- */
-    vsi_l_offset nWriteStart = 0;
-    if( nPixelOffset >= 0 )
-        nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset;
-    else
-    {
-        nWriteStart =
-            nImgOffset
-            + static_cast<vsi_l_offset>(nBlockYOff) * nLineOffset
-            - std::abs(nPixelOffset) * (nBlockXSize-1);
+        {
+            GDALSwapWords(pLineBuffer, GDALGetDataTypeSizeBytes(eDataType),
+                          nBlockXSize, std::abs(nPixelOffset));
+        }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Seek to correct location.                                       */
-/* -------------------------------------------------------------------- */
-    if( Seek( nWriteStart, SEEK_SET ) == -1 )
+    // Figure out where to start writing.
+    // Negative nPixelOffset is used to specify the offset.
+    const GIntBig nPixelOffsetActual =
+        nPixelOffset >= 0
+        ? 0 : nPixelOffset * static_cast<GIntBig>(nBlockXSize - 1);
+    const vsi_l_offset nWriteStart = static_cast<vsi_l_offset>(
+        nImgOffset + static_cast<GIntBig>(nBlockYOff) * nLineOffset +
+        nPixelOffsetActual);
+
+    // Seek to correct location.
+    if( Seek(nWriteStart, SEEK_SET) == -1 )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to seek to scanline %d @ " CPL_FRMT_GUIB
-                  " to write to file.",
-                  nBlockYOff, nImgOffset + nBlockYOff * nLineOffset );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Failed to seek to scanline %d @ " CPL_FRMT_GUIB
+                 " to write to file.",
+                 nBlockYOff, nImgOffset + nBlockYOff * nLineOffset);
 
         eErr = CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write data buffer.                                              */
-/* -------------------------------------------------------------------- */
-    const int nBytesToWrite = std::abs(nPixelOffset) * (nBlockXSize - 1)
-        + GDALGetDataTypeSizeBytes(GetRasterDataType());
+    // Write data buffer.
+    const int nBytesToWrite = std::abs(nPixelOffset) * (nBlockXSize - 1) +
+                              GDALGetDataTypeSizeBytes(GetRasterDataType());
 
     if( eErr == CE_None
-        && Write( pLineBuffer, 1, nBytesToWrite )
-        < static_cast<size_t>( nBytesToWrite ) )
+        && Write(pLineBuffer, 1, nBytesToWrite)
+        < static_cast<size_t>(nBytesToWrite) )
     {
-        CPLError( CE_Failure, CPLE_FileIO,
-                  "Failed to write scanline %d to file.",
-                  nBlockYOff );
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Failed to write scanline %d to file.",
+                 nBlockYOff);
 
         eErr = CE_Failure;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Byte swap (if necessary) back into machine order so the         */
-/*      buffer is still usable for reading purposes.                    */
-/* -------------------------------------------------------------------- */
+    // Byte swap (if necessary) back into machine order so the
+    // buffer is still usable for reading purposes.
     if( !bNativeOrder && eDataType != GDT_Byte )
     {
-        if( GDALDataTypeIsComplex( eDataType ) )
+        if( GDALDataTypeIsComplex(eDataType) )
         {
-            const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
-            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize,
-                           std::abs(nPixelOffset) );
-            GDALSwapWords( reinterpret_cast<GByte *>( pLineBuffer ) +
-                           nWordSize, nWordSize, nBlockXSize,
-                           std::abs(nPixelOffset) );
+            const int nWordSize = GDALGetDataTypeSize(eDataType) / 16;
+            GDALSwapWords(pLineBuffer, nWordSize, nBlockXSize,
+                          std::abs(nPixelOffset));
+            GDALSwapWords(static_cast<GByte *>(pLineBuffer) +
+                          nWordSize, nWordSize, nBlockXSize,
+                          std::abs(nPixelOffset));
         }
         else
         {
-            GDALSwapWords( pLineBuffer, GDALGetDataTypeSizeBytes(eDataType),
-                           nBlockXSize, std::abs(nPixelOffset) );
+            GDALSwapWords(pLineBuffer, GDALGetDataTypeSizeBytes(eDataType),
+                          nBlockXSize, std::abs(nPixelOffset));
         }
     }
 
@@ -518,47 +490,41 @@ CPLErr RawRasterBand::IWriteBlock( CPL_UNUSED int nBlockXOff,
 /*                             AccessBlock()                            */
 /************************************************************************/
 
-CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, size_t nBlockSize,
-                                   void * pData )
+CPLErr RawRasterBand::AccessBlock(vsi_l_offset nBlockOff, size_t nBlockSize,
+                                  void *pData)
 {
-/* -------------------------------------------------------------------- */
-/*      Seek to the right block.                                        */
-/* -------------------------------------------------------------------- */
-    if( Seek( nBlockOff, SEEK_SET ) == -1 )
+    // Seek to the correct block.
+    if( Seek(nBlockOff, SEEK_SET) == -1 )
     {
-        memset( pData, 0, nBlockSize );
+        memset(pData, 0, nBlockSize);
         return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Read the block.                                                 */
-/* -------------------------------------------------------------------- */
-    const size_t nBytesActuallyRead = Read( pData, 1, nBlockSize );
+    // Read the block.
+    const size_t nBytesActuallyRead = Read(pData, 1, nBlockSize);
     if( nBytesActuallyRead < nBlockSize )
     {
 
-        memset( reinterpret_cast<GByte *>( pData ) + nBytesActuallyRead,
-                0, nBlockSize - nBytesActuallyRead );
+        memset(static_cast<GByte *>(pData) + nBytesActuallyRead,
+               0, nBlockSize - nBytesActuallyRead);
         return CE_None;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Byte swap the interesting data, if required.                    */
-/* -------------------------------------------------------------------- */
+    // Byte swap the interesting data, if required.
     if( !bNativeOrder && eDataType != GDT_Byte )
     {
-        if( GDALDataTypeIsComplex( eDataType ) )
+        if( GDALDataTypeIsComplex(eDataType) )
         {
-            const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
-            GDALSwapWordsEx( pData, nWordSize, nBlockSize / nPixelOffset,
-                             nPixelOffset );
-            GDALSwapWordsEx( reinterpret_cast<GByte *>( pData ) + nWordSize,
-                           nWordSize, nBlockSize / nPixelOffset, nPixelOffset );
+            const int nWordSize = GDALGetDataTypeSize(eDataType) / 16;
+            GDALSwapWordsEx(pData, nWordSize, nBlockSize / nPixelOffset,
+                            nPixelOffset);
+            GDALSwapWordsEx(static_cast<GByte *>(pData) + nWordSize,
+                            nWordSize, nBlockSize / nPixelOffset, nPixelOffset);
         }
         else
         {
-            GDALSwapWordsEx( pData, GDALGetDataTypeSizeBytes(eDataType),
-                             nBlockSize / nPixelOffset, nPixelOffset );
+            GDALSwapWordsEx(pData, GDALGetDataTypeSizeBytes(eDataType),
+                            nBlockSize / nPixelOffset, nPixelOffset);
         }
     }
 
@@ -578,7 +544,7 @@ int RawRasterBand::IsSignificantNumberOfLinesLoaded( int nLineOff, int nLines )
 
     for ( int iLine = nLineOff; iLine < nLineOff + nLines; iLine++ )
     {
-        GDALRasterBlock *poBlock = TryGetLockedBlockRef( 0, iLine );
+        GDALRasterBlock *poBlock = TryGetLockedBlockRef(0, iLine);
         if( poBlock != NULL )
         {
             poBlock->DropLock();
@@ -604,31 +570,29 @@ int RawRasterBand::CanUseDirectIO(int /* nXOff */,
                                   GDALDataType /* eBufType*/)
 {
 
-/* -------------------------------------------------------------------- */
-/* Use direct IO without caching if:                                    */
-/*                                                                      */
-/* GDAL_ONE_BIG_READ is enabled                                         */
-/*                                                                      */
-/* or                                                                   */
-/*                                                                      */
-/* the length of a scanline on disk is more than 50000 bytes, and the   */
-/* width of the requested chunk is less than 40% of the whole scanline  */
-/* and no significant number of requested scanlines are already in the  */
-/* cache.                                                               */
-/* -------------------------------------------------------------------- */
+    // Use direct IO without caching if:
+    //
+    // GDAL_ONE_BIG_READ is enabled
+    //
+    // or
+    //
+    // the length of a scanline on disk is more than 50000 bytes, and the
+    // width of the requested chunk is less than 40% of the whole scanline and
+    // no significant number of requested scanlines are already in the cache.
+
     if( nPixelOffset < 0 )
     {
         return FALSE;
     }
 
-    const char* pszGDAL_ONE_BIG_READ =
-        CPLGetConfigOption( "GDAL_ONE_BIG_READ", NULL);
+    const char *pszGDAL_ONE_BIG_READ =
+        CPLGetConfigOption("GDAL_ONE_BIG_READ", NULL);
     if ( pszGDAL_ONE_BIG_READ == NULL )
     {
         const int nBytesToRW = nPixelOffset * nXSize;
         if ( nLineSize < 50000
              || nBytesToRW > nLineSize / 5 * 2
-             || IsSignificantNumberOfLinesLoaded( nYOff, nYSize ) )
+             || IsSignificantNumberOfLinesLoaded(nYOff, nYSize) )
         {
             return FALSE;
         }
@@ -657,42 +621,35 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if( nBandDataSize == 0 )
         return CE_Failure;
 #endif
-    const int nBufDataSize = GDALGetDataTypeSizeBytes( eBufType );
+    const int nBufDataSize = GDALGetDataTypeSizeBytes(eBufType);
 
-    if( !CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) )
+    if( !CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType) )
     {
-        return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
-                                          nXSize, nYSize,
-                                          pData, nBufXSize, nBufYSize,
-                                          eBufType,
-                                          nPixelSpace, nLineSpace, psExtraArg );
+        return GDALRasterBand::IRasterIO(eRWFlag, nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         pData, nBufXSize, nBufYSize,
+                                         eBufType,
+                                         nPixelSpace, nLineSpace, psExtraArg);
     }
 
     CPLDebug("RAW", "Using direct IO implementation");
 
-/* ==================================================================== */
-/*   Read data.                                                         */
-/* ==================================================================== */
+    // Read data.
     if ( eRWFlag == GF_Read )
     {
-/* -------------------------------------------------------------------- */
-/*      Do we have overviews that would be appropriate to satisfy       */
-/*      this request?                                                   */
-/* -------------------------------------------------------------------- */
+        // Do we have overviews that are appropriate to satisfy this request?
         if( (nBufXSize < nXSize || nBufYSize < nYSize)
             && GetOverviewCount() > 0 )
         {
-            if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                  pData, nBufXSize, nBufYSize,
-                                  eBufType, nPixelSpace, nLineSpace,
-                                  psExtraArg ) == CE_None )
+            if( OverviewRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                 pData, nBufXSize, nBufYSize,
+                                 eBufType, nPixelSpace, nLineSpace,
+                                 psExtraArg) == CE_None)
                 return CE_None;
         }
 
-/* ==================================================================== */
-/*   1. Simplest case when we should get contiguous block               */
-/*   of uninterleaved pixels.                                           */
-/* ==================================================================== */
+        // 1. Simplest case when we should get contiguous block
+        //    of uninterleaved pixels.
         if ( nXSize == GetXSize()
              && nXSize == nBufXSize
              && nYSize == nBufYSize
@@ -702,67 +659,59 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
              && nLineSpace == nPixelSpace * nXSize )
         {
             const vsi_l_offset nOffset =
-                nImgOffset
-                + static_cast<vsi_l_offset>(nYOff) * nLineOffset + nXOff;
+                nImgOffset + static_cast<vsi_l_offset>(nYOff) * nLineOffset +
+                nXOff;
             const size_t nBytesToRead =
                 static_cast<size_t>(nXSize) * nYSize * nBandDataSize;
-            if ( AccessBlock( nOffset, nBytesToRead, pData ) != CE_None )
+            if ( AccessBlock(nOffset, nBytesToRead, pData) != CE_None )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Failed to read " CPL_FRMT_GUIB
-                          " bytes at " CPL_FRMT_GUIB ".",
-                          static_cast<GUIntBig>(nBytesToRead), nOffset );
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Failed to read " CPL_FRMT_GUIB
+                         " bytes at " CPL_FRMT_GUIB ".",
+                         static_cast<GUIntBig>(nBytesToRead), nOffset);
                 return CE_Failure;
             }
         }
-
-/* ==================================================================== */
-/*   2. Case when we need deinterleave and/or subsample data.           */
-/* ==================================================================== */
+        // 2. Case when we need deinterleave and/or subsample data.
         else
         {
-            const double dfSrcXInc =
-                static_cast<double>( nXSize ) / nBufXSize;
-            const double dfSrcYInc =
-                static_cast<double>( nYSize ) / nBufYSize;
+            const double dfSrcXInc = static_cast<double>(nXSize) / nBufXSize;
+            const double dfSrcYInc = static_cast<double>(nYSize) / nBufYSize;
 
             const size_t nBytesToRW =
                 static_cast<size_t>(nPixelOffset) * nXSize;
-            GByte *pabyData = reinterpret_cast<GByte *>(
-                VSI_MALLOC_VERBOSE( nBytesToRW ) );
+            GByte *pabyData =
+                static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBytesToRW));
             if( pabyData == NULL )
                 return CE_Failure;
 
             for ( int iLine = 0; iLine < nBufYSize; iLine++ )
             {
-                const vsi_l_offset nOffset = nImgOffset
-                    +  ( (static_cast<vsi_l_offset>( nYOff )
-                          + static_cast<vsi_l_offset>( iLine * dfSrcYInc ) )
-                         * nLineOffset )
-                    + nXOff * nPixelOffset;
-                if ( AccessBlock( nOffset,
-                                  nBytesToRW, pabyData ) != CE_None )
+                const vsi_l_offset nOffset =
+                    nImgOffset +
+                    ((static_cast<vsi_l_offset>(nYOff) +
+                      static_cast<vsi_l_offset>(iLine * dfSrcYInc)) *
+                     nLineOffset) +
+                    nXOff * nPixelOffset;
+                if ( AccessBlock(nOffset,
+                                 nBytesToRW, pabyData) != CE_None )
                 {
-                    CPLError( CE_Failure, CPLE_FileIO,
-                              "Failed to read " CPL_FRMT_GUIB
-                              " bytes at " CPL_FRMT_GUIB ".",
-                              static_cast<GUIntBig>(nBytesToRW), nOffset );
-                    CPLFree( pabyData );
+                    CPLError(CE_Failure, CPLE_FileIO,
+                             "Failed to read " CPL_FRMT_GUIB
+                             " bytes at " CPL_FRMT_GUIB ".",
+                             static_cast<GUIntBig>(nBytesToRW), nOffset);
+                    CPLFree(pabyData);
                     return CE_Failure;
                 }
-
-/* -------------------------------------------------------------------- */
-/*      Copy data from disk buffer to user block buffer and subsample,  */
-/*      if needed.                                                      */
-/* -------------------------------------------------------------------- */
+                // Copy data from disk buffer to user block buffer and
+                // subsample, if needed.
                 if ( nXSize == nBufXSize && nYSize == nBufYSize )
                 {
-                    GDALCopyWords( pabyData, eDataType, nPixelOffset,
-                                   reinterpret_cast<GByte *>( pData ) +
-                                   static_cast<vsi_l_offset>( iLine ) *
-                                   nLineSpace,
-                                   eBufType, static_cast<int>(nPixelSpace),
-                                   nXSize );
+                    GDALCopyWords(
+                        pabyData, eDataType, nPixelOffset,
+                        static_cast<GByte *>(pData) +
+                            static_cast<vsi_l_offset>(iLine) * nLineSpace,
+                        eBufType, static_cast<int>(nPixelSpace), nXSize);
                 }
                 else
                 {
@@ -770,14 +719,13 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     {
                         GDALCopyWords(
                             pabyData +
-                            static_cast<vsi_l_offset>( iPixel * dfSrcXInc ) *
-                            nPixelOffset,
+                                static_cast<vsi_l_offset>(iPixel * dfSrcXInc) *
+                                    nPixelOffset,
                             eDataType, nPixelOffset,
-                            reinterpret_cast<GByte *>( pData ) +
-                            static_cast<vsi_l_offset>( iLine ) *
-                            nLineSpace +
-                            static_cast<vsi_l_offset>( iPixel) * nPixelSpace,
-                            eBufType, static_cast<int>(nPixelSpace), 1 );
+                            static_cast<GByte *>(pData) +
+                                static_cast<vsi_l_offset>(iLine) * nLineSpace +
+                                static_cast<vsi_l_offset>(iPixel) * nPixelSpace,
+                            eBufType, static_cast<int>(nPixelSpace), 1);
                     }
                 }
 
@@ -785,24 +733,19 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     !psExtraArg->pfnProgress(1.0 * (iLine + 1) / nBufYSize, "",
                                             psExtraArg->pProgressData) )
                 {
-                    CPLFree( pabyData );
+                    CPLFree(pabyData);
                     return CE_Failure;
                 }
             }
 
-            CPLFree( pabyData );
+            CPLFree(pabyData);
         }
     }
-
-/* ==================================================================== */
-/*   Write data.                                                        */
-/* ==================================================================== */
+    // Write data.
     else
     {
-/* ==================================================================== */
-/*   1. Simplest case when we should write contiguous block             */
-/*   of uninterleaved pixels.                                           */
-/* ==================================================================== */
+        // 1. Simplest case when we should write contiguous block of
+        //    uninterleaved pixels.
         if ( nXSize == GetXSize()
              && nXSize == nBufXSize
              && nYSize == nBufYSize
@@ -811,210 +754,190 @@ CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
              && nPixelSpace == nBufDataSize
              && nLineSpace == nPixelSpace * nXSize )
         {
-/* -------------------------------------------------------------------- */
-/*      Byte swap the data buffer, if required.                         */
-/* -------------------------------------------------------------------- */
+            // Byte swap the data buffer, if required.
             if( !bNativeOrder && eDataType != GDT_Byte )
             {
-                if( GDALDataTypeIsComplex( eDataType ) )
+                if( GDALDataTypeIsComplex(eDataType) )
                 {
-                    const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
-                    GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
-                    GDALSwapWords(
-                        reinterpret_cast<GByte *>( pData ) + nWordSize,
-                        nWordSize, nXSize, nPixelOffset );
+                    const int nWordSize = GDALGetDataTypeSize(eDataType) / 16;
+                    GDALSwapWords(pData, nWordSize, nXSize, nPixelOffset);
+                    GDALSwapWords(static_cast<GByte *>(pData) + nWordSize,
+                                  nWordSize, nXSize, nPixelOffset);
                 }
                 else
                 {
-                    GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
+                    GDALSwapWords(pData, nBandDataSize, nXSize, nPixelOffset);
                 }
             }
 
-/* -------------------------------------------------------------------- */
-/*      Seek to the right block.                                        */
-/* -------------------------------------------------------------------- */
-            vsi_l_offset nOffset =
-                nImgOffset +
-                static_cast<vsi_l_offset>(nYOff) * nLineOffset + nXOff;
-            if( Seek( nOffset, SEEK_SET) == -1 )
+            // Seek to the correct block.
+            const vsi_l_offset nOffset =
+                nImgOffset + static_cast<vsi_l_offset>(nYOff) * nLineOffset +
+                nXOff;
+            if( Seek(nOffset, SEEK_SET) == -1 )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Failed to seek to " CPL_FRMT_GUIB " to write data.",
-                          nOffset);
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Failed to seek to " CPL_FRMT_GUIB " to write data.",
+                         nOffset);
 
                 return CE_Failure;
             }
 
-/* -------------------------------------------------------------------- */
-/*      Write the block.                                                */
-/* -------------------------------------------------------------------- */
+            // Write the block.
             const size_t nBytesToRW =
                 static_cast<size_t>(nXSize) * nYSize * nBandDataSize;
 
-            const size_t nBytesActuallyWritten = Write( pData, 1, nBytesToRW );
+            const size_t nBytesActuallyWritten = Write(pData, 1, nBytesToRW);
             if( nBytesActuallyWritten < nBytesToRW )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Failed to write " CPL_FRMT_GUIB
-                          " bytes to file. " CPL_FRMT_GUIB " bytes written",
-                          static_cast<GUIntBig>(nBytesToRW),
-                          static_cast<GUIntBig>(nBytesActuallyWritten) );
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Failed to write " CPL_FRMT_GUIB
+                         " bytes to file. " CPL_FRMT_GUIB " bytes written",
+                         static_cast<GUIntBig>(nBytesToRW),
+                         static_cast<GUIntBig>(nBytesActuallyWritten));
 
                 return CE_Failure;
             }
 
-/* -------------------------------------------------------------------- */
-/*      Byte swap (if necessary) back into machine order so the         */
-/*      buffer is still usable for reading purposes.                    */
-/* -------------------------------------------------------------------- */
+            // Byte swap (if necessary) back into machine order so the
+            // buffer is still usable for reading purposes.
             if( !bNativeOrder  && eDataType != GDT_Byte )
             {
-                if( GDALDataTypeIsComplex( eDataType ) )
+                if( GDALDataTypeIsComplex(eDataType) )
                 {
                     const int nWordSize = GDALGetDataTypeSize(eDataType) / 16;
-                    GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
-                    GDALSwapWords(
-                        reinterpret_cast<GByte *>( pData ) + nWordSize,
-                        nWordSize, nXSize, nPixelOffset );
+                    GDALSwapWords(pData, nWordSize, nXSize, nPixelOffset);
+                    GDALSwapWords(static_cast<GByte *>(pData) + nWordSize,
+                                  nWordSize, nXSize, nPixelOffset);
                 }
                 else
                 {
-                    GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
+                    GDALSwapWords(pData, nBandDataSize, nXSize, nPixelOffset);
                 }
             }
         }
-
-/* ==================================================================== */
-/*   2. Case when we need deinterleave and/or subsample data.           */
-/* ==================================================================== */
+        // 2. Case when we need deinterleave and/or subsample data.
         else
         {
-            const double dfSrcXInc = static_cast<double>( nXSize ) / nBufXSize;
-            const double dfSrcYInc = static_cast<double>( nYSize ) / nBufYSize;
+            const double dfSrcXInc = static_cast<double>(nXSize) / nBufXSize;
+            const double dfSrcYInc = static_cast<double>(nYSize) / nBufYSize;
 
-            const size_t nBytesToRW = static_cast<size_t>(nPixelOffset) * nXSize;
-            GByte *pabyData = reinterpret_cast<GByte *>(
-                VSI_MALLOC_VERBOSE( nBytesToRW ) );
+            const size_t nBytesToRW =
+                static_cast<size_t>(nPixelOffset) * nXSize;
+            GByte *pabyData =
+                static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBytesToRW));
             if( pabyData == NULL )
                 return CE_Failure;
 
             for ( int iLine = 0; iLine < nBufYSize; iLine++ )
             {
                 const vsi_l_offset nBlockOff =
-                    nImgOffset
-                    + ( static_cast<vsi_l_offset>(nYOff) +
-                        static_cast<vsi_l_offset>(iLine*dfSrcYInc) )
-                    * nLineOffset
-                    + static_cast<vsi_l_offset>(nXOff) * nPixelOffset;
-
-/* -------------------------------------------------------------------- */
-/*      If the data for this band is completely contiguous we don't     */
-/*      have to worry about pre-reading from disk.                      */
-/* -------------------------------------------------------------------- */
+                    nImgOffset +
+                    (static_cast<vsi_l_offset>(nYOff) +
+                     static_cast<vsi_l_offset>(iLine * dfSrcYInc)) *
+                        nLineOffset +
+                    static_cast<vsi_l_offset>(nXOff) * nPixelOffset;
+
+                // If the data for this band is completely contiguous we don't
+                // have to worry about pre-reading from disk.
                 if( nPixelOffset > nBandDataSize )
-                    AccessBlock( nBlockOff, nBytesToRW, pabyData );
+                    AccessBlock(nBlockOff, nBytesToRW, pabyData);
 
-/* -------------------------------------------------------------------- */
-/*      Copy data from user block buffer to disk buffer and subsample,  */
-/*      if needed.                                                      */
-/* -------------------------------------------------------------------- */
+                // Copy data from user block buffer to disk buffer and
+                // subsample, if needed.
                 if ( nXSize == nBufXSize && nYSize == nBufYSize )
                 {
-                    GDALCopyWords(
-                        reinterpret_cast<GByte *>( pData ) +
-                        static_cast<vsi_l_offset>( iLine ) * nLineSpace,
-                        eBufType, static_cast<int>(nPixelSpace),
-                        pabyData, eDataType, nPixelOffset, nXSize );
+                    GDALCopyWords(static_cast<GByte *>(pData) +
+                                      static_cast<vsi_l_offset>(iLine) *
+                                          nLineSpace,
+                                  eBufType, static_cast<int>(nPixelSpace),
+                                  pabyData, eDataType, nPixelOffset, nXSize);
                 }
                 else
                 {
                     for ( int iPixel = 0; iPixel < nBufXSize; iPixel++ )
                     {
                         GDALCopyWords(
-                            reinterpret_cast<GByte *>(pData) +
-                            static_cast<vsi_l_offset>( iLine ) * nLineSpace +
-                            static_cast<vsi_l_offset>( iPixel ) * nPixelSpace,
+                            static_cast<GByte *>(pData) +
+                                static_cast<vsi_l_offset>(iLine) * nLineSpace +
+                                static_cast<vsi_l_offset>(iPixel) * nPixelSpace,
                             eBufType, static_cast<int>(nPixelSpace),
                             pabyData +
-                            static_cast<vsi_l_offset>( iPixel * dfSrcXInc ) *
-                            nPixelOffset,
-                            eDataType, nPixelOffset, 1 );
+                                static_cast<vsi_l_offset>(iPixel * dfSrcXInc) *
+                                    nPixelOffset,
+                            eDataType, nPixelOffset, 1);
                     }
                 }
 
-/* -------------------------------------------------------------------- */
-/*      Byte swap the data buffer, if required.                         */
-/* -------------------------------------------------------------------- */
+                // Byte swap the data buffer, if required.
                 if( !bNativeOrder && eDataType != GDT_Byte )
                 {
-                    if( GDALDataTypeIsComplex( eDataType ) )
+                    if( GDALDataTypeIsComplex(eDataType) )
                     {
-                        const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
-                        GDALSwapWords(
-                            pabyData, nWordSize, nXSize, nPixelOffset );
-                        GDALSwapWords(
-                            reinterpret_cast<GByte *>( pabyData ) + nWordSize,
-                            nWordSize, nXSize, nPixelOffset );
+                        const int nWordSize =
+                            GDALGetDataTypeSize(eDataType) / 16;
+                        GDALSwapWords(pabyData, nWordSize, nXSize,
+                                      nPixelOffset);
+                        GDALSwapWords(static_cast<GByte *>(pabyData) +
+                                          nWordSize,
+                                      nWordSize, nXSize, nPixelOffset);
                     }
                     else
-                        GDALSwapWords( pabyData, nBandDataSize, nXSize,
-                                       nPixelOffset );
+                    {
+                        GDALSwapWords(pabyData, nBandDataSize, nXSize,
+                                      nPixelOffset);
+                    }
                 }
 
-/* -------------------------------------------------------------------- */
-/*      Seek to the right line in block.                                */
-/* -------------------------------------------------------------------- */
-                if( Seek( nBlockOff, SEEK_SET) == -1 )
+                // Seek to the right line in block.
+                if( Seek(nBlockOff, SEEK_SET) == -1 )
                 {
-                    CPLError( CE_Failure, CPLE_FileIO,
-                              "Failed to seek to " CPL_FRMT_GUIB " to read.",
-                              nBlockOff );
-                    CPLFree( pabyData );
+                    CPLError(CE_Failure, CPLE_FileIO,
+                             "Failed to seek to " CPL_FRMT_GUIB " to read.",
+                             nBlockOff);
+                    CPLFree(pabyData);
                     return CE_Failure;
                 }
 
-/* -------------------------------------------------------------------- */
-/*      Write the line of block.                                        */
-/* -------------------------------------------------------------------- */
+                // Write the line of block.
                 const size_t nBytesActuallyWritten =
-                    Write( pabyData, 1, nBytesToRW );
+                    Write(pabyData, 1, nBytesToRW);
                 if( nBytesActuallyWritten < nBytesToRW )
                 {
-                    CPLError( CE_Failure, CPLE_FileIO,
-                              "Failed to write " CPL_FRMT_GUIB
-                              " bytes to file. " CPL_FRMT_GUIB " bytes written",
-                              static_cast<GUIntBig>(nBytesToRW),
-                              static_cast<GUIntBig>(nBytesActuallyWritten) );
-                    CPLFree( pabyData );
+                    CPLError(CE_Failure, CPLE_FileIO,
+                             "Failed to write " CPL_FRMT_GUIB
+                             " bytes to file. " CPL_FRMT_GUIB " bytes written",
+                             static_cast<GUIntBig>(nBytesToRW),
+                             static_cast<GUIntBig>(nBytesActuallyWritten));
+                    CPLFree(pabyData);
                     return CE_Failure;
                 }
 
-/* -------------------------------------------------------------------- */
-/*      Byte swap (if necessary) back into machine order so the         */
-/*      buffer is still usable for reading purposes.                    */
-/* -------------------------------------------------------------------- */
+
+                // Byte swap (if necessary) back into machine order so the
+                // buffer is still usable for reading purposes.
                 if( !bNativeOrder && eDataType != GDT_Byte )
                 {
-                    if( GDALDataTypeIsComplex( eDataType ) )
+                    if( GDALDataTypeIsComplex(eDataType) )
                     {
-                        const int nWordSize = GDALGetDataTypeSize(eDataType)/16;
-                        GDALSwapWords(
-                            pabyData, nWordSize, nXSize, nPixelOffset );
-                        GDALSwapWords(
-                            reinterpret_cast<GByte *>( pabyData ) + nWordSize,
-                            nWordSize, nXSize, nPixelOffset );
+                        const int nWordSize =
+                            GDALGetDataTypeSize(eDataType) / 16;
+                        GDALSwapWords(pabyData, nWordSize, nXSize,
+                                      nPixelOffset);
+                        GDALSwapWords(static_cast<GByte *>(pabyData) +
+                                          nWordSize,
+                                      nWordSize, nXSize, nPixelOffset);
                     }
                     else
                     {
-                        GDALSwapWords( pabyData, nBandDataSize, nXSize,
-                                       nPixelOffset );
+                        GDALSwapWords(pabyData, nBandDataSize, nXSize,
+                                      nPixelOffset);
                     }
                 }
-
             }
 
             bDirty = TRUE;
-            CPLFree( pabyData );
+            CPLFree(pabyData);
         }
     }
 
@@ -1029,9 +952,9 @@ int RawRasterBand::Seek( vsi_l_offset nOffset, int nSeekMode )
 
 {
     if( bIsVSIL )
-        return VSIFSeekL( fpRawL, nOffset, nSeekMode );
+        return VSIFSeekL(fpRawL, nOffset, nSeekMode);
 
-    return VSIFSeek( fpRaw, static_cast<long>( nOffset ), nSeekMode );
+    return VSIFSeek(fpRaw, static_cast<long>(nOffset), nSeekMode);
 }
 
 /************************************************************************/
@@ -1042,9 +965,9 @@ size_t RawRasterBand::Read( void *pBuffer, size_t nSize, size_t nCount )
 
 {
     if( bIsVSIL )
-        return VSIFReadL( pBuffer, nSize, nCount, fpRawL );
+        return VSIFReadL(pBuffer, nSize, nCount, fpRawL);
 
-    return VSIFRead( pBuffer, nSize, nCount, fpRaw );
+    return VSIFRead(pBuffer, nSize, nCount, fpRaw);
 }
 
 /************************************************************************/
@@ -1055,9 +978,9 @@ size_t RawRasterBand::Write( void *pBuffer, size_t nSize, size_t nCount )
 
 {
     if( bIsVSIL )
-        return VSIFWriteL( pBuffer, nSize, nCount, fpRawL );
+        return VSIFWriteL(pBuffer, nSize, nCount, fpRawL);
 
-    return VSIFWrite( pBuffer, nSize, nCount, fpRaw );
+    return VSIFWrite(pBuffer, nSize, nCount, fpRaw);
 }
 
 /************************************************************************/
@@ -1071,28 +994,24 @@ size_t RawRasterBand::Write( void *pBuffer, size_t nSize, size_t nCount )
 void RawRasterBand::StoreNoDataValue( double dfValue )
 
 {
-    SetNoDataValue( dfValue );
+    SetNoDataValue(dfValue);
 }
 
 /************************************************************************/
 /*                          GetCategoryNames()                          */
 /************************************************************************/
 
-char **RawRasterBand::GetCategoryNames()
-
-{
-    return papszCategoryNames;
-}
+char **RawRasterBand::GetCategoryNames() { return papszCategoryNames; }
 
 /************************************************************************/
 /*                          SetCategoryNames()                          */
 /************************************************************************/
 
-CPLErr RawRasterBand::SetCategoryNames( char ** papszNewNames )
+CPLErr RawRasterBand::SetCategoryNames( char **papszNewNames )
 
 {
-    CSLDestroy( papszCategoryNames );
-    papszCategoryNames = CSLDuplicate( papszNewNames );
+    CSLDestroy(papszCategoryNames);
+    papszCategoryNames = CSLDuplicate(papszNewNames);
 
     return CE_None;
 }
@@ -1118,11 +1037,7 @@ CPLErr RawRasterBand::SetColorTable( GDALColorTable *poNewCT )
 /*                           GetColorTable()                            */
 /************************************************************************/
 
-GDALColorTable *RawRasterBand::GetColorTable()
-
-{
-    return poCT;
-}
+GDALColorTable *RawRasterBand::GetColorTable() { return poCT; }
 
 /************************************************************************/
 /*                       SetColorInterpretation()                       */
@@ -1140,11 +1055,7 @@ CPLErr RawRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
 /*                       GetColorInterpretation()                       */
 /************************************************************************/
 
-GDALColorInterp RawRasterBand::GetColorInterpretation()
-
-{
-    return eInterp;
-}
+GDALColorInterp RawRasterBand::GetColorInterpretation() { return eInterp; }
 
 /************************************************************************/
 /*                           GetVirtualMemAuto()                        */
@@ -1162,36 +1073,41 @@ CPLVirtualMem  *RawRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
         static_cast<vsi_l_offset>(nRasterYSize - 1) * nLineOffset +
         (nRasterXSize - 1) * nPixelOffset + GDALGetDataTypeSizeBytes(eDataType);
 
+    const char *pszImpl = CSLFetchNameValueDef(
+            papszOptions, "USE_DEFAULT_IMPLEMENTATION", "AUTO");
     if( !bIsVSIL || VSIFGetNativeFileDescriptorL(fpRawL) == NULL ||
         !CPLIsVirtualMemFileMapAvailable() ||
         (eDataType != GDT_Byte && !bNativeOrder) ||
         static_cast<size_t>(nSize) != nSize ||
         nPixelOffset < 0 ||
         nLineOffset < 0 ||
-        CPLTestBool( CSLFetchNameValueDef(
-            papszOptions, "USE_DEFAULT_IMPLEMENTATION", "NO") ) )
+        EQUAL(pszImpl, "YES") || EQUAL(pszImpl, "ON") ||
+        EQUAL(pszImpl, "1") || EQUAL(pszImpl, "TRUE") )
     {
-        return GDALRasterBand::GetVirtualMemAuto( eRWFlag, pnPixelSpace,
-                                                  pnLineSpace, papszOptions);
+        return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
+                                                 pnLineSpace, papszOptions);
     }
 
     FlushCache();
 
-    CPLVirtualMem* pVMem = CPLVirtualMemFileMapNew(
+    CPLVirtualMem *pVMem = CPLVirtualMemFileMapNew(
         fpRawL, nImgOffset, nSize,
         (eRWFlag == GF_Write) ? VIRTUALMEM_READWRITE : VIRTUALMEM_READONLY,
         NULL, NULL);
     if( pVMem == NULL )
     {
-        return GDALRasterBand::GetVirtualMemAuto( eRWFlag, pnPixelSpace,
-                                                  pnLineSpace, papszOptions);
-    }
-    else
-    {
-        *pnPixelSpace = nPixelOffset;
-        *pnLineSpace = nLineOffset;
-        return pVMem;
+        if( EQUAL(pszImpl, "NO") || EQUAL(pszImpl, "OFF") ||
+            EQUAL(pszImpl, "0") || EQUAL(pszImpl, "FALSE") )
+        {
+            return NULL;
+        }
+        return GDALRasterBand::GetVirtualMemAuto(eRWFlag, pnPixelSpace,
+                                                 pnLineSpace, papszOptions);
     }
+
+    *pnPixelSpace = nPixelOffset;
+    *pnLineSpace = nLineOffset;
+    return pVMem;
 }
 
 /************************************************************************/
@@ -1200,7 +1116,6 @@ CPLVirtualMem  *RawRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            RawDataset()                              */
 /************************************************************************/
@@ -1211,7 +1126,7 @@ RawDataset::RawDataset() {}
 /*                           ~RawDataset()                              */
 /************************************************************************/
 
-    /* It's pure virtual function but must be defined, even if empty. */
+// It's pure virtual function but must be defined, even if empty.
 RawDataset::~RawDataset() {}
 
 /************************************************************************/
@@ -1236,25 +1151,26 @@ CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
     // BlockBasedRasterIO if the dataset is interleaved. However if the
     // access pattern is compatible with DirectIO() we don't want to go
     // BlockBasedRasterIO, but rather used our optimized path in
-    // RawRasterBand::IRasterIO()
+    // RawRasterBand::IRasterIO().
     if (nXSize == nBufXSize && nYSize == nBufYSize && nBandCount > 1 &&
-        (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL &&
+        (pszInterleave = GetMetadataItem("INTERLEAVE",
+                                         "IMAGE_STRUCTURE")) != NULL &&
         EQUAL(pszInterleave, "PIXEL"))
     {
         int iBandIndex = 0;
         for( ; iBandIndex < nBandCount; iBandIndex++ )
         {
-            RawRasterBand* poBand = reinterpret_cast<RawRasterBand *>(
-                GetRasterBand(panBandMap[iBandIndex]) );
-            if( !poBand->CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) )
+            RawRasterBand *poBand = static_cast<RawRasterBand *>(
+                GetRasterBand(panBandMap[iBandIndex]));
+            if( !poBand->CanUseDirectIO(nXOff, nYOff,
+                                        nXSize, nYSize, eBufType) )
             {
                 break;
             }
         }
         if( iBandIndex == nBandCount )
         {
-
-            GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
+            GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
             void *pProgressDataGlobal = psExtraArg->pProgressData;
 
             CPLErr eErr = CE_None;
@@ -1270,25 +1186,21 @@ CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
                     break;
                 }
 
-                GByte *pabyBandData = reinterpret_cast<GByte *>( pData )
-                    + iBandIndex * nBandSpace;
+                GByte *pabyBandData =
+                    static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
 
                 psExtraArg->pfnProgress = GDALScaledProgress;
-                psExtraArg->pProgressData =
-                    GDALCreateScaledProgress(
-                        1.0 * iBandIndex / nBandCount,
-                        1.0 * (iBandIndex + 1) / nBandCount,
-                        pfnProgressGlobal,
-                        pProgressDataGlobal );
-
-                eErr = poBand->RasterIO(
-                    eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                    reinterpret_cast<void *>( pabyBandData ),
-                    nBufXSize, nBufYSize,
-                    eBufType, nPixelSpace, nLineSpace,
-                    psExtraArg );
-
-                GDALDestroyScaledProgress( psExtraArg->pProgressData );
+                psExtraArg->pProgressData = GDALCreateScaledProgress(
+                    1.0 * iBandIndex / nBandCount,
+                    1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
+                    pProgressDataGlobal);
+
+                eErr = poBand->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                        static_cast<void *>(pabyBandData),
+                                        nBufXSize, nBufYSize, eBufType,
+                                        nPixelSpace, nLineSpace, psExtraArg);
+
+                GDALDestroyScaledProgress(psExtraArg->pProgressData);
             }
 
             psExtraArg->pfnProgress = pfnProgressGlobal;
@@ -1298,9 +1210,8 @@ CPLErr RawDataset::IRasterIO( GDALRWFlag eRWFlag,
         }
     }
 
-    return  GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                    pData, nBufXSize, nBufYSize, eBufType,
-                                    nBandCount, panBandMap,
-                                    nPixelSpace, nLineSpace, nBandSpace,
-                                    psExtraArg);
+    return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+                                  nBufXSize, nBufYSize, eBufType, nBandCount,
+                                  panBandMap, nPixelSpace, nLineSpace,
+                                  nBandSpace, psExtraArg);
 }
diff --git a/frmts/raw/rawdataset.h b/frmts/raw/rawdataset.h
index 9a52b73..aae457c 100644
--- a/frmts/raw/rawdataset.h
+++ b/frmts/raw/rawdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rawdataset.h 33673 2016-03-07 20:40:54Z goatbar $
+ * $Id: rawdataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Raw Translator
  * Purpose:  Implementation of RawDataset class.  Intended to be subclassed
@@ -36,7 +36,7 @@
 
 /************************************************************************/
 /* ==================================================================== */
-/*				RawDataset				*/
+/*                              RawDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -55,13 +55,13 @@ class CPL_DLL RawDataset : public GDALPamDataset
                                    int, int *,
                                    GSpacing nPixelSpace, GSpacing nLineSpace,
                                    GSpacing nBandSpace,
-                                   GDALRasterIOExtraArg* psExtraArg );
+                                   GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
   public:
                  RawDataset();
-                 ~RawDataset() = 0;
+         virtual ~RawDataset() = 0;
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(RawDataset);
+    CPL_DISALLOW_COPY_ASSIGN(RawDataset)
 };
 
 /************************************************************************/
@@ -85,13 +85,13 @@ protected:
     int         bIsVSIL;
 
     vsi_l_offset nImgOffset;
-    int		nPixelOffset;
-    int		nLineOffset;
+    int         nPixelOffset;
+    int         nLineOffset;
     int         nLineSize;
-    int		bNativeOrder;
+    int         bNativeOrder;
 
-    int		nLoadedScanline;
-    void	*pLineBuffer;
+    int         nLoadedScanline;
+    void        *pLineBuffer;
     void        *pLineStart;
     int         bDirty;
 
@@ -114,7 +114,7 @@ protected:
     virtual CPLErr  IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
     int         CanUseDirectIO(int nXOff, int nYOff, int nXSize, int nYSize,
                                GDALDataType eBufType);
@@ -133,34 +133,34 @@ public:
                                 GDALDataType eDataType, int bNativeOrder,
                                 int nXSize, int nYSize, int bIsVSIL = FALSE, int bOwnsFP = FALSE );
 
-                 ~RawRasterBand() /* = 0 */ ;
+    virtual ~RawRasterBand() /* = 0 */ ;
 
-    // should override RasterIO eventually.
+    // should CPL_OVERRIDE RasterIO eventually.
 
-    virtual CPLErr  IReadBlock( int, int, void * );
-    virtual CPLErr  IWriteBlock( int, int, void * );
+    virtual CPLErr  IReadBlock( int, int, void * ) CPL_OVERRIDE;
+    virtual CPLErr  IWriteBlock( int, int, void * ) CPL_OVERRIDE;
 
-    virtual GDALColorTable *GetColorTable();
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr SetColorTable( GDALColorTable * );
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
+    virtual GDALColorTable *GetColorTable() CPL_OVERRIDE;
+    virtual GDALColorInterp GetColorInterpretation() CPL_OVERRIDE;
+    virtual CPLErr SetColorTable( GDALColorTable * ) CPL_OVERRIDE;
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) CPL_OVERRIDE;
 
-    virtual char **GetCategoryNames();
-    virtual CPLErr SetCategoryNames( char ** );
+    virtual char **GetCategoryNames() CPL_OVERRIDE;
+    virtual CPLErr SetCategoryNames( char ** ) CPL_OVERRIDE;
 
-    virtual CPLErr  FlushCache();
+    virtual CPLErr  FlushCache() CPL_OVERRIDE;
 
     virtual CPLVirtualMem  *GetVirtualMemAuto( GDALRWFlag eRWFlag,
                                                int *pnPixelSpace,
                                                GIntBig *pnLineSpace,
-                                               char **papszOptions );
+                                               char **papszOptions ) CPL_OVERRIDE;
 
     CPLErr          AccessLine( int iLine );
 
     void            SetAccess( GDALAccess eAccess );
 
     // this is deprecated.
-    void	 StoreNoDataValue( double );
+    void         StoreNoDataValue( double );
 
     // Query methods for internal data.
     vsi_l_offset GetImgOffset() { return nImgOffset; }
@@ -173,7 +173,7 @@ public:
     int          GetOwnsFP() { return bOwnsFP; }
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(RawRasterBand);
+    CPL_DISALLOW_COPY_ASSIGN(RawRasterBand)
 };
 
 #endif // GDAL_FRMTS_RAW_RAWDATASET_H_INCLUDED
diff --git a/frmts/raw/roipacdataset.cpp b/frmts/raw/roipacdataset.cpp
index b1d718f..c8df00f 100644
--- a/frmts/raw/roipacdataset.cpp
+++ b/frmts/raw/roipacdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: roipacdataset.cpp 34639 2016-07-12 08:44:29Z rouault $
  *
  * Project:  ROI_PAC Raster Reader
  * Purpose:  Implementation of the ROI_PAC raster reader
@@ -31,7 +30,7 @@
 #include "ogr_spatialref.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: roipacdataset.cpp 34639 2016-07-12 08:44:29Z rouault $");
+CPL_CVSID("$Id: roipacdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -64,12 +63,12 @@ class ROIPACDataset : public RawDataset
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char **papszOptions );
 
-    virtual void        FlushCache( void );
-    CPLErr              GetGeoTransform( double *padfTransform );
-    virtual CPLErr      SetGeoTransform( double *padfTransform );
-    const char         *GetProjectionRef( void );
-    virtual CPLErr      SetProjection( const char *pszNewProjection );
-    virtual char      **GetFileList( void );
+    virtual void        FlushCache( void ) override;
+    CPLErr              GetGeoTransform( double *padfTransform ) override;
+    virtual CPLErr      SetGeoTransform( double *padfTransform ) override;
+    const char         *GetProjectionRef( void ) override;
+    virtual CPLErr      SetProjection( const char *pszNewProjection ) override;
+    virtual char      **GetFileList( void ) override;
 };
 
 /************************************************************************/
@@ -94,39 +93,37 @@ class ROIPACRasterBand : public RawRasterBand
 
 static CPLString getRscFilename( GDALOpenInfo *poOpenInfo )
 {
-    CPLString osRscFilename;
-
     char **papszSiblingFiles = poOpenInfo->GetSiblingFiles();
     if ( papszSiblingFiles == NULL )
     {
-        osRscFilename = CPLFormFilename( NULL, poOpenInfo->pszFilename,
-                                        "rsc" );
+        const CPLString osRscFilename =
+            CPLFormFilename( NULL, poOpenInfo->pszFilename,
+                             "rsc" );
         VSIStatBufL psRscStatBuf;
         if ( VSIStatL( osRscFilename, &psRscStatBuf ) != 0 )
         {
-            osRscFilename = "";
+            return "";
         }
+        return osRscFilename;
     }
-    else
-    {
-        /* ------------------------------------------------------------ */
-        /*      We need to tear apart the filename to form a .rsc       */
-        /*      filename.                                               */
-        /* ------------------------------------------------------------ */
-        CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
-        CPLString osName = CPLGetFilename( poOpenInfo->pszFilename );
 
-        int iFile = CSLFindString( papszSiblingFiles,
-                                   CPLFormFilename( NULL, osName, "rsc" ) );
-        if( iFile >= 0 )
-        {
-            osRscFilename = CPLFormFilename( osPath,
-                                             papszSiblingFiles[iFile],
-                                             NULL );
-        }
+    /* ------------------------------------------------------------ */
+    /*      We need to tear apart the filename to form a .rsc       */
+    /*      filename.                                               */
+    /* ------------------------------------------------------------ */
+    const CPLString osPath = CPLGetPath( poOpenInfo->pszFilename );
+    const CPLString osName = CPLGetFilename( poOpenInfo->pszFilename );
+
+    int iFile = CSLFindString( papszSiblingFiles,
+                               CPLFormFilename( NULL, osName, "rsc" ) );
+    if( iFile >= 0 )
+    {
+        return CPLFormFilename( osPath,
+                                papszSiblingFiles[iFile],
+                                NULL );
     }
 
-    return osRscFilename;
+    return "";
 }
 
 /************************************************************************/
@@ -155,19 +152,13 @@ ROIPACDataset::ROIPACDataset() :
 ROIPACDataset::~ROIPACDataset()
 {
     FlushCache();
-    if ( fpRsc != NULL )
+    if ( fpRsc != NULL && VSIFCloseL( fpRsc ) != 0 )
     {
-        if( VSIFCloseL( fpRsc ) != 0 )
-        {
-            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
-        }
+        CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
     }
-    if ( fpImage != NULL )
+    if ( fpImage != NULL && VSIFCloseL( fpImage ) != 0 )
     {
-        if( VSIFCloseL( fpImage ) != 0 )
-        {
-            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
-        }
+        CPLError( CE_Failure, CPLE_FileIO, "I/O error" );
     }
     CPLFree( pszRscFilename );
     CPLFree( pszProjection );
@@ -195,7 +186,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
     {
         return NULL;
     }
-    VSILFILE *fpRsc;
+    VSILFILE *fpRsc = NULL;
     if ( poOpenInfo->eAccess == GA_Update )
     {
         fpRsc = VSIFOpenL( osRscFilename, "r+" );
@@ -233,7 +224,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
             break;
         }
         papszRsc = CSLSetNameValue( papszRsc,
-                                       papszTokens[0], papszTokens[1] );
+                                    papszTokens[0], papszTokens[1] );
 
         CSLDestroy ( papszTokens );
     }
@@ -241,7 +232,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Fetch required fields.                                          */
 /* -------------------------------------------------------------------- */
-    if ( CSLFetchNameValue( papszRsc, "WIDTH" ) == NULL
+    if( CSLFetchNameValue( papszRsc, "WIDTH" ) == NULL
         || CSLFetchNameValue( papszRsc, "FILE_LENGTH" ) == NULL )
     {
         CSLDestroy( papszRsc );
@@ -249,7 +240,8 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
     const int nWidth = atoi( CSLFetchNameValue( papszRsc, "WIDTH" ) );
-    const int nFileLength = atoi( CSLFetchNameValue( papszRsc, "FILE_LENGTH" ) );
+    const int nFileLength =
+        atoi( CSLFetchNameValue( papszRsc, "FILE_LENGTH" ) );
 
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
@@ -276,7 +268,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
     {
         delete poDS;
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to re-open %s within ROI_PAC driver.\n",
+                  "Failed to re-open %s within ROI_PAC driver.",
                   poOpenInfo->pszFilename );
         CSLDestroy( papszRsc );
         return NULL;
@@ -285,9 +277,9 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    GDALDataType eDataType;
-    int nBands;
-    enum Interleave { LINE, PIXEL } eInterleave;
+    GDALDataType eDataType = GDT_Unknown;
+    int nBands = 0;
+    enum Interleave { UNKNOWN, LINE, PIXEL } eInterleave = UNKNOWN;
     const char *pszExtension = CPLGetExtension(poOpenInfo->pszFilename);
     if ( strcmp( pszExtension, "raw" ) == 0 )
     {
@@ -310,7 +302,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
 #endif
     }
     else if ( strcmp( pszExtension, "int" ) == 0
-                || strcmp( pszExtension, "slc" ) == 0 )
+              || strcmp( pszExtension, "slc" ) == 0 )
     {
         eDataType = GDT_CFloat32;
         nBands = 1;
@@ -323,10 +315,10 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
         eInterleave = PIXEL;
     }
     else if ( strcmp( pszExtension, "cor" ) == 0
-                || strcmp( pszExtension, "hgt" ) == 0
-                || strcmp( pszExtension, "unw" ) == 0
-                || strcmp( pszExtension, "msk" ) == 0
-                || strcmp( pszExtension, "trans" ) == 0 )
+              || strcmp( pszExtension, "hgt" ) == 0
+              || strcmp( pszExtension, "unw" ) == 0
+              || strcmp( pszExtension, "msk" ) == 0
+              || strcmp( pszExtension, "trans" ) == 0 )
     {
         eDataType = GDT_Float32;
         nBands = 2;
@@ -350,45 +342,53 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
         return NULL;
     }
 
-    int nPixelOffset;
-    int nLineOffset;
-    int nBandOffset;
+    int nPixelOffset = 0;
+    int nLineOffset = 0;
+    int nBandOffset = 0;
     if (eInterleave == LINE)
     {
-        nPixelOffset = GDALGetDataTypeSize(eDataType)/8;
+        nPixelOffset = GDALGetDataTypeSizeBytes(eDataType);
         nLineOffset = nPixelOffset * nWidth * nBands;
-        nBandOffset = GDALGetDataTypeSize(eDataType)/8 * nWidth;
+        nBandOffset = GDALGetDataTypeSizeBytes(eDataType) * nWidth;
     }
     else { /* PIXEL */
-        nPixelOffset = GDALGetDataTypeSize(eDataType)/8 * nBands;
+        nPixelOffset = GDALGetDataTypeSizeBytes(eDataType) * nBands;
         nLineOffset = nPixelOffset * nWidth;
-        nBandOffset = GDALGetDataTypeSize(eDataType)/8;
+        nBandOffset = GDALGetDataTypeSizeBytes(eDataType);
 
         if( nBands > 1 )
         {
-            // GDAL 2.0.[0-3] and 2.1.0  had a value of nLineOffset that was 
-            // equal to the theoretical nLineOffset multiplied by nBands...
+            // GDAL 2.0.[0-3] and 2.1.0  had a value of nLineOffset that was
+            // equal to the theoretical nLineOffset multiplied by nBands.
             VSIFSeekL( poDS->fpImage, 0, SEEK_END );
-            const GUIntBig nWrongFileSize = GDALGetDataTypeSizeBytes(eDataType) *
-                                            nWidth * (static_cast<GUIntBig>(nFileLength - 1) * nBands * nBands + nBands);
+            const GUIntBig nWrongFileSize =
+                GDALGetDataTypeSizeBytes(eDataType) *
+                nWidth * (static_cast<GUIntBig>(nFileLength - 1) *
+                          nBands * nBands + nBands);
             if( VSIFTellL( poDS->fpImage ) == nWrongFileSize )
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
                          "This file has been incorrectly generated by an older "
-                         "GDAL version whose line offset computation was erroneous. "
-                         "Taking that into account, but the file should be re-encoded ideally");
+                         "GDAL version whose line offset computation was "
+                         "erroneous.  Taking that into account, "
+                         "but the file should be re-encoded ideally.");
                 nLineOffset = nLineOffset * nBands;
             }
         }
     }
+#ifdef CPL_LSB
+    const bool bNativeOrder = true;
+#else
+    const bool bNativeOrder = false;
+#endif
     poDS->nBands = nBands;
-    for (int b = 0; b < nBands; b++)
+    for( int b = 0; b < nBands; b++ )
     {
         poDS->SetBand( b + 1,
                        new ROIPACRasterBand( poDS, b + 1, poDS->fpImage,
                                              nBandOffset * b,
                                              nPixelOffset, nLineOffset,
-                                             eDataType, TRUE,
+                                             eDataType, bNativeOrder,
                                              TRUE, FALSE ) );
     }
 
@@ -396,9 +396,9 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
 /*      Interpret georeferencing, if present.                           */
 /* -------------------------------------------------------------------- */
     if ( CSLFetchNameValue( papszRsc, "X_FIRST" ) != NULL
-          && CSLFetchNameValue( papszRsc, "X_STEP" ) != NULL
-          && CSLFetchNameValue( papszRsc, "Y_FIRST" ) != NULL
-          && CSLFetchNameValue( papszRsc, "Y_STEP" ) != NULL )
+         && CSLFetchNameValue( papszRsc, "X_STEP" ) != NULL
+         && CSLFetchNameValue( papszRsc, "Y_FIRST" ) != NULL
+         && CSLFetchNameValue( papszRsc, "Y_STEP" ) != NULL )
     {
         poDS->adfGeoTransform[0] = CPLAtof( CSLFetchNameValue( papszRsc,
                                                                "X_FIRST" ) );
@@ -421,8 +421,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
         /* bands!                                                       */
         /* ------------------------------------------------------------ */
         OGRSpatialReference oSRS;
-        if ( strcmp( CSLFetchNameValue( papszRsc, "PROJECTION" ),
-                     "LL" ) == 0 )
+        if ( strcmp( CSLFetchNameValue( papszRsc, "PROJECTION" ), "LL" ) == 0 )
         {
             if ( CSLFetchNameValue( papszRsc, "DATUM" ) != NULL )
             {
@@ -433,7 +432,8 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
                 oSRS.SetWellKnownGeogCS( "WGS84" );
             }
         }
-        else if( STARTS_WITH(CSLFetchNameValue( papszRsc, "PROJECTION" ), "UTM") )
+        else if( STARTS_WITH(CSLFetchNameValue( papszRsc, "PROJECTION" ),
+                             "UTM") )
         {
             const char *pszZone = CSLFetchNameValue( papszRsc,
                                                      "PROJECTION" ) + 3;
@@ -451,9 +451,9 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
     }
     if ( CSLFetchNameValue( papszRsc, "Z_OFFSET" ) != NULL )
     {
-        const double dfOffset
-            = strtod( CSLFetchNameValue( papszRsc, "Z_OFFSET" ), NULL);
-        for (int b = 1; b <= nBands; b++)
+        const double dfOffset =
+            strtod( CSLFetchNameValue( papszRsc, "Z_OFFSET" ), NULL);
+        for( int b = 1; b <= nBands; b++ )
         {
             GDALRasterBand *poBand = poDS->GetRasterBand(b);
             poBand->SetOffset( dfOffset );
@@ -461,20 +461,19 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
     }
     if ( CSLFetchNameValue( papszRsc, "Z_SCALE" ) != NULL )
     {
-        const double dfScale
-            = strtod( CSLFetchNameValue( papszRsc, "Z_SCALE" ), NULL);
-        for (int b = 1; b <= nBands; b++)
+        const double dfScale =
+            strtod( CSLFetchNameValue( papszRsc, "Z_SCALE" ), NULL);
+        for( int b = 1; b <= nBands; b++ )
         {
             GDALRasterBand *poBand = poDS->GetRasterBand(b);
             poBand->SetScale( dfScale );
         }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Set all the other header metadata into the ROI_PAC domain       */
 /* -------------------------------------------------------------------- */
-    for (int i = 0; i < CSLCount( papszRsc ); i++)
+    for( int i = 0; i < CSLCount( papszRsc ); i++ )
     {
         char **papszTokens = CSLTokenizeString2( papszRsc[i],
                                                  "=",
@@ -494,7 +493,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
             CSLDestroy( papszTokens );
             continue;
         }
-        poDS->SetMetadataItem(papszTokens[0], papszTokens[1], "ROI_PAC");
+        poDS->SetMetadataItem( papszTokens[0], papszTokens[1], "ROI_PAC" );
         CSLDestroy( papszTokens );
     }
 
@@ -514,7 +513,7 @@ GDALDataset *ROIPACDataset::Open( GDALOpenInfo *poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -527,23 +526,24 @@ int ROIPACDataset::Identify( GDALOpenInfo *poOpenInfo )
 /*      Check if:                                                       */
 /*      * 1. The data file extension is known                           */
 /* -------------------------------------------------------------------- */
-    const char *pszExtension = CPLGetExtension(poOpenInfo->pszFilename);
+    const char *pszExtension = CPLGetExtension( poOpenInfo->pszFilename );
     if ( strcmp( pszExtension, "raw" ) == 0 )
     {
         /* Since gdal do not read natively CInt8, more work is needed
          * to read raw files */
         return false;
     }
-    bool bExtensionIsValid = strcmp( pszExtension, "int" ) == 0
-                               || strcmp( pszExtension, "slc" ) == 0
-                               || strcmp( pszExtension, "amp" ) == 0
-                               || strcmp( pszExtension, "cor" ) == 0
-                               || strcmp( pszExtension, "hgt" ) == 0
-                               || strcmp( pszExtension, "unw" ) == 0
-                               || strcmp( pszExtension, "msk" ) == 0
-                               || strcmp( pszExtension, "trans" ) == 0
-                               || strcmp( pszExtension, "dem" ) == 0
-                               || strcmp( pszExtension, "flg" ) == 0;
+    const bool bExtensionIsValid =
+        strcmp( pszExtension, "int" ) == 0
+        || strcmp( pszExtension, "slc" ) == 0
+        || strcmp( pszExtension, "amp" ) == 0
+        || strcmp( pszExtension, "cor" ) == 0
+        || strcmp( pszExtension, "hgt" ) == 0
+        || strcmp( pszExtension, "unw" ) == 0
+        || strcmp( pszExtension, "msk" ) == 0
+        || strcmp( pszExtension, "trans" ) == 0
+        || strcmp( pszExtension, "dem" ) == 0
+        || strcmp( pszExtension, "flg" ) == 0;
     if ( !bExtensionIsValid )
     {
         return false;
@@ -568,7 +568,7 @@ int ROIPACDataset::Identify( GDALOpenInfo *poOpenInfo )
 GDALDataset *ROIPACDataset::Create( const char *pszFilename,
                                     int nXSize, int nYSize, int nBands,
                                     GDALDataType eType,
-                                    CPL_UNUSED char **papszOptions )
+                                    char ** /* papszOptions */ )
 {
 /* -------------------------------------------------------------------- */
 /*      Verify input options.                                           */
@@ -580,8 +580,8 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
         if ( nBands != 1 || eType != GDT_CFloat32 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to create ROI_PAC %s dataset with an illegal\n"
-                          "number of bands (%d) and/or data type (%s).\n",
+                      "Attempt to create ROI_PAC %s dataset with an illegal "
+                      "number of bands (%d) and/or data type (%s).",
                       pszExtension, nBands, GDALGetDataTypeName(eType) );
             return NULL;
         }
@@ -591,8 +591,8 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
         if ( nBands != 2 || eType != GDT_Float32 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to create ROI_PAC %s dataset with an illegal\n"
-                          "number of bands (%d) and/or data type (%s).\n",
+                      "Attempt to create ROI_PAC %s dataset with an illegal "
+                      "number of bands (%d) and/or data type (%s).",
                       pszExtension, nBands, GDALGetDataTypeName(eType) );
             return NULL;
         }
@@ -606,8 +606,8 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
         if ( nBands != 2 || eType != GDT_Float32 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to create ROI_PAC %s dataset with an illegal\n"
-                          "number of bands (%d) and/or data type (%s).\n",
+                      "Attempt to create ROI_PAC %s dataset with an illegal "
+                          "number of bands (%d) and/or data type (%s).",
                       pszExtension, nBands, GDALGetDataTypeName(eType) );
             return NULL;
         }
@@ -617,8 +617,8 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
         if ( nBands != 1 || eType != GDT_Int16 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Attempt to create ROI_PAC %s dataset with an illegal\n"
-                          "number of bands (%d) and/or data type (%s).\n",
+                      "Attempt to create ROI_PAC %s dataset with an illegal "
+                      "number of bands (%d) and/or data type (%s).",
                       pszExtension, nBands, GDALGetDataTypeName(eType) );
             return NULL;
         }
@@ -636,7 +636,7 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
     }
     else { /* Eeek */
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to create ROI_PAC dataset with an unknown type (%s)\n",
+                  "Attempt to create ROI_PAC dataset with an unknown type (%s)",
                   pszExtension );
         return NULL;
     }
@@ -648,7 +648,7 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
+                  "Attempt to create file `%s' failed.",
                   pszFilename );
         return NULL;
     }
@@ -657,8 +657,7 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
 /*      Just write out a couple of bytes to establish the binary        */
 /*      file, and then close it.                                        */
 /* -------------------------------------------------------------------- */
-    CPL_IGNORE_RET_VAL(VSIFWriteL( reinterpret_cast<void *>( const_cast<char *>( "\0\0" ) ),
-                2, 1, fp ));
+    CPL_IGNORE_RET_VAL(VSIFWriteL( "\0\0", 2, 1, fp ));
     CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
 
 /* -------------------------------------------------------------------- */
@@ -669,7 +668,7 @@ GDALDataset *ROIPACDataset::Create( const char *pszFilename,
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Attempt to create file `%s' failed.\n",
+                  "Attempt to create file `%s' failed.",
                   pszRSCFilename );
         return NULL;
     }
@@ -710,8 +709,10 @@ void ROIPACDataset::FlushCache( void )
 /* -------------------------------------------------------------------- */
 /*      Raster dimensions.                                              */
 /* -------------------------------------------------------------------- */
-    CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %d\n", "WIDTH", nRasterXSize ));
-    CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %d\n", "FILE_LENGTH", nRasterYSize ));
+    CPL_IGNORE_RET_VAL(
+        VSIFPrintfL( fpRsc, "%-40s %d\n", "WIDTH", nRasterXSize ));
+    CPL_IGNORE_RET_VAL(
+        VSIFPrintfL( fpRsc, "%-40s %d\n", "FILE_LENGTH", nRasterYSize ));
 
 /* -------------------------------------------------------------------- */
 /*      Georeferencing.                                                 */
@@ -722,42 +723,52 @@ void ROIPACDataset::FlushCache( void )
         OGRSpatialReference oSRS;
         if( oSRS.importFromWkt( &pszProjectionTmp ) == OGRERR_NONE )
         {
-            int bNorth;
+            int bNorth = FALSE;
             int iUTMZone = oSRS.GetUTMZone( &bNorth );
             if ( iUTMZone != 0 )
             {
-                CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s%d\n", "PROJECTION", "UTM", iUTMZone ));
+                CPL_IGNORE_RET_VAL(
+                    VSIFPrintfL( fpRsc, "%-40s %s%d\n", "PROJECTION", "UTM",
+                                 iUTMZone ) );
             }
             else if ( oSRS.IsGeographic() )
             {
-                CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "PROJECTION", "LL" ));
+                CPL_IGNORE_RET_VAL(
+                    VSIFPrintfL( fpRsc, "%-40s %s\n", "PROJECTION", "LL" ) );
             }
             else
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "ROI_PAC format only support Latitude/Longitude and "
-                              "UTM projections, discarding projection.");
+                          "UTM projections, discarding projection.");
             }
 
             if ( oSRS.GetAttrValue( "DATUM" ) != NULL )
             {
                 if ( strcmp( oSRS.GetAttrValue( "DATUM" ), "WGS_1984" ) == 0 )
                 {
-                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "DATUM", "WGS84" ));
+                    CPL_IGNORE_RET_VAL(
+                        VSIFPrintfL( fpRsc, "%-40s %s\n", "DATUM", "WGS84" ) );
                 }
                 else
                 {
                     CPLError( CE_Warning, CPLE_AppDefined,
                               "Datum \"%s\" probably not supported in the "
-                                  "ROI_PAC format, saving it anyway",
+                              "ROI_PAC format, saving it anyway",
                                   oSRS.GetAttrValue( "DATUM" ) );
-                    CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "DATUM", oSRS.GetAttrValue( "DATUM" ) ));
+                    CPL_IGNORE_RET_VAL(
+                        VSIFPrintfL( fpRsc, "%-40s %s\n", "DATUM",
+                                     oSRS.GetAttrValue( "DATUM" ) ) );
                 }
             }
             if ( oSRS.GetAttrValue( "UNIT" ) != NULL )
             {
-                CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "X_UNIT", oSRS.GetAttrValue( "UNIT" ) ));
-                CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", "Y_UNIT", oSRS.GetAttrValue( "UNIT" ) ));
+                CPL_IGNORE_RET_VAL(
+                    VSIFPrintfL( fpRsc, "%-40s %s\n", "X_UNIT",
+                                 oSRS.GetAttrValue( "UNIT" ) ));
+                CPL_IGNORE_RET_VAL(
+                    VSIFPrintfL( fpRsc, "%-40s %s\n", "Y_UNIT",
+                                 oSRS.GetAttrValue( "UNIT" ) ));
             }
         }
     }
@@ -771,12 +782,23 @@ void ROIPACDataset::FlushCache( void )
         }
         else
         {
-            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "X_FIRST", adfGeoTransform[0] ));
-            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "X_STEP", adfGeoTransform[1] ));
-            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Y_FIRST", adfGeoTransform[3] ));
-            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Y_STEP", adfGeoTransform[5] ));
-            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Z_OFFSET", band->GetOffset(NULL) ));
-            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n", "Z_SCALE", band->GetScale(NULL) ));
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintfL( fpRsc, "%-40s %.16g\n",
+                             "X_FIRST", adfGeoTransform[0] ));
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintfL( fpRsc, "%-40s %.16g\n",
+                             "X_STEP", adfGeoTransform[1] ));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %.16g\n",
+                                            "Y_FIRST", adfGeoTransform[3] ));
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintfL( fpRsc, "%-40s %.16g\n",
+                             "Y_STEP", adfGeoTransform[5] ));
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintfL( fpRsc, "%-40s %.16g\n",
+                             "Z_OFFSET", band->GetOffset(NULL) ));
+            CPL_IGNORE_RET_VAL(
+                VSIFPrintfL( fpRsc, "%-40s %.16g\n",
+                             "Z_SCALE", band->GetScale(NULL) ));
         }
     }
 
@@ -784,7 +806,7 @@ void ROIPACDataset::FlushCache( void )
 /*      Metadata stored in the ROI_PAC domain.                          */
 /* -------------------------------------------------------------------- */
     char** papszROIPACMetadata = GetMetadata( "ROI_PAC" );
-    for (int i = 0; i < CSLCount( papszROIPACMetadata ); i++)
+    for( int i = 0; i < CSLCount( papszROIPACMetadata ); i++ )
     {
         /* Get the tokens from the metadata item */
         char **papszTokens = CSLTokenizeString2( papszROIPACMetadata[i],
@@ -793,9 +815,10 @@ void ROIPACDataset::FlushCache( void )
                                                  | CSLT_STRIPENDSPACES);
         if ( CSLCount( papszTokens ) != 2 )
         {
-            CPLDebug("ROI_PAC",
-                     "Line of header file could not be split at = into two elements: %s",
-                     papszROIPACMetadata[i]);
+            CPLDebug( "ROI_PAC",
+                      "Line of header file could not be split at = "
+                      "into two elements: %s",
+                      papszROIPACMetadata[i] );
             CSLDestroy( papszTokens );
             continue;
         }
@@ -808,7 +831,9 @@ void ROIPACDataset::FlushCache( void )
             CSLDestroy( papszTokens );
             continue;
         }
-        CPL_IGNORE_RET_VAL(VSIFPrintfL( fpRsc, "%-40s %s\n", papszTokens[0], papszTokens[1] ));
+        CPL_IGNORE_RET_VAL(
+            VSIFPrintfL( fpRsc, "%-40s %s\n",
+                         papszTokens[0], papszTokens[1] ));
         CSLDestroy( papszTokens );
     }
 }
@@ -820,7 +845,7 @@ void ROIPACDataset::FlushCache( void )
 CPLErr ROIPACDataset::GetGeoTransform( double *padfTransform )
 {
     memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform) );
-    return (bValidGeoTransform) ? CE_None : CE_Failure;
+    return bValidGeoTransform ? CE_None : CE_Failure;
 }
 
 /************************************************************************/
@@ -840,7 +865,7 @@ CPLErr ROIPACDataset::SetGeoTransform( double *padfTransform )
 
 const char *ROIPACDataset::GetProjectionRef( void )
 {
-    return (pszProjection != NULL) ? pszProjection : "";
+    return pszProjection != NULL ? pszProjection : "";
 }
 
 /************************************************************************/
@@ -879,10 +904,10 @@ ROIPACRasterBand::ROIPACRasterBand( GDALDataset *poDSIn, int nBandIn, void *fpRa
                                     int nLineOffsetIn,
                                     GDALDataType eDataTypeIn, int bNativeOrderIn,
                                     int bIsVSILIn, int bOwnsFPIn ) :
-        RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
-                      nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn, bOwnsFPIn)
-{
-}
+    RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                  nLineOffsetIn, eDataTypeIn, bNativeOrderIn, bIsVSILIn,
+                  bOwnsFPIn)
+{}
 
 /************************************************************************/
 /*                        GDALRegister_ROIPAC()                         */
diff --git a/frmts/raw/rrasterdataset.cpp b/frmts/raw/rrasterdataset.cpp
new file mode 100644
index 0000000..c512a6a
--- /dev/null
+++ b/frmts/raw/rrasterdataset.cpp
@@ -0,0 +1,557 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Implements R Raster Format.
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_port.h"
+
+#include "gdal_frmts.h"
+
+#include "rawdataset.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: rrasterdataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+/************************************************************************/
+/* ==================================================================== */
+/*                           RRASTERDataset                             */
+/* ==================================================================== */
+/************************************************************************/
+
+class RRASTERDataset : public RawDataset
+{
+    CPLString   m_osGriFilename;
+    double      m_adfGeoTransform[6];
+    VSILFILE   *m_fpImage;
+    CPLString   m_osProjection;
+
+  public:
+                RRASTERDataset();
+       virtual ~RRASTERDataset();
+
+    virtual char **GetFileList(void) override;
+
+    static GDALDataset *Open( GDALOpenInfo * );
+    static int          Identify( GDALOpenInfo * );
+
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char *GetProjectionRef(void) override;
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                         RRASTERRasterBand                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class RRASTERRasterBand: public RawRasterBand
+{
+      bool      m_bMinMaxValid;
+      double    m_dfMin;
+      double    m_dfMax;
+
+  public:
+      RRASTERRasterBand( GDALDataset *poDS, int nBand, void * fpRaw,
+                    vsi_l_offset nImgOffset, int nPixelOffset,
+                    int nLineOffset,
+                    GDALDataType eDataType, int bNativeOrder );
+
+      void SetMinMax( double dfMin, double dfMax );
+      virtual double GetMinimum( int *pbSuccess = NULL ) override;
+      virtual double GetMaximum(int *pbSuccess = NULL ) override;
+
+#ifdef UPDATE_SUPPORTED
+  protected:
+      virtual CPLErr  IWriteBlock( int, int, void * );
+      virtual CPLErr  IRasterIO( GDALRWFlag, int, int, int, int,
+                                void *, int, int, GDALDataType,
+                                GSpacing nPixelSpace, GSpacing nLineSpace,
+                                GDALRasterIOExtraArg* psExtraArg );
+#endif
+};
+
+/************************************************************************/
+/*                           RRASTERDataset()                           */
+/************************************************************************/
+
+RRASTERRasterBand::RRASTERRasterBand( GDALDataset *poDSIn, int nBandIn,
+                                      void * fpRawIn,
+                                      vsi_l_offset nImgOffsetIn,
+                                      int nPixelOffsetIn,
+                                      int nLineOffsetIn,
+                                      GDALDataType eDataTypeIn,
+                                      int bNativeOrderIn ) :
+    RawRasterBand(poDSIn, nBandIn, fpRawIn, nImgOffsetIn, nPixelOffsetIn,
+                  nLineOffsetIn, eDataTypeIn, bNativeOrderIn, TRUE),
+    m_bMinMaxValid( false ),
+    m_dfMin( 0.0 ),
+    m_dfMax( 0.0 )
+{
+}
+
+/************************************************************************/
+/*                             SetMinMax()                              */
+/************************************************************************/
+
+void RRASTERRasterBand::SetMinMax( double dfMin, double dfMax )
+{
+    m_bMinMaxValid = true;
+    m_dfMin = dfMin;
+    m_dfMax = dfMax;
+}
+
+/************************************************************************/
+/*                            GetMinimum()                              */
+/************************************************************************/
+
+double RRASTERRasterBand::GetMinimum( int *pbSuccess )
+{
+    if( m_bMinMaxValid )
+    {
+        if( pbSuccess )
+            *pbSuccess = TRUE;
+        return m_dfMin;
+    }
+    return RawRasterBand::GetMinimum(pbSuccess);
+}
+
+/************************************************************************/
+/*                            GetMaximum()                              */
+/************************************************************************/
+
+double RRASTERRasterBand::GetMaximum(int *pbSuccess )
+{
+    if( m_bMinMaxValid )
+    {
+        if( pbSuccess )
+            *pbSuccess = TRUE;
+        return m_dfMax;
+    }
+    return RawRasterBand::GetMaximum(pbSuccess);
+}
+
+#ifdef UPDATE_SUPPORTED
+/************************************************************************/
+/*                            IWriteBlock()                             */
+/************************************************************************/
+
+CPLErr RRASTERRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
+                                       void * pImage )
+{
+    m_bMinMaxValid = false;
+    return RawRasterBand::IWriteBlock(nBlockXOff, nBlockYOff, pImage);
+}
+
+/************************************************************************/
+/*                             IRasterIO()                              */
+/************************************************************************/
+
+CPLErr RRASTERRasterBand::IRasterIO( GDALRWFlag eRWFlag,
+                                     int nXOff, int nYOff,
+                                     int nXSize, int nYSize,
+                                     void * pData, int nBufXSize, int nBufYSize,
+                                     GDALDataType eBufType,
+                                     GSpacing nPixelSpace, GSpacing nLineSpace,
+                                     GDALRasterIOExtraArg* psExtraArg )
+
+{
+    if( eRWFlag == GF_Write )
+        m_bMinMaxValid = false;
+    return RawRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
+                                     nXSize, nYSize,
+                                     pData, nBufXSize, nBufYSize,
+                                     eBufType,
+                                     nPixelSpace, nLineSpace, psExtraArg );
+}
+#endif
+
+/************************************************************************/
+/*                           RRASTERDataset()                           */
+/************************************************************************/
+
+RRASTERDataset::RRASTERDataset() :
+    m_fpImage(NULL)
+{
+    m_adfGeoTransform[0] = 0.0;
+    m_adfGeoTransform[1] = 1.0;
+    m_adfGeoTransform[2] = 0.0;
+    m_adfGeoTransform[3] = 0.0;
+    m_adfGeoTransform[4] = 0.0;
+    m_adfGeoTransform[5] = 1.0;
+}
+
+/************************************************************************/
+/*                          ~RRASTERDataset()                           */
+/************************************************************************/
+
+RRASTERDataset::~RRASTERDataset()
+
+{
+    FlushCache();
+    if( m_fpImage != NULL )
+        VSIFCloseL(m_fpImage);
+}
+
+/************************************************************************/
+/*                            GetFileList()                             */
+/************************************************************************/
+
+char **RRASTERDataset::GetFileList()
+
+{
+    char **papszFileList = RawDataset::GetFileList();
+
+    papszFileList = CSLAddString(papszFileList, m_osGriFilename);
+
+    return papszFileList;
+}
+
+/************************************************************************/
+/*                          GetGeoTransform()                           */
+/************************************************************************/
+
+CPLErr RRASTERDataset::GetGeoTransform( double * padfGeoTransform )
+{
+    memcpy( padfGeoTransform, m_adfGeoTransform, 6 * sizeof(double) );
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           GetProjectionRef()                         */
+/************************************************************************/
+
+const char * RRASTERDataset::GetProjectionRef()
+{
+    return m_osProjection.c_str();
+}
+
+/************************************************************************/
+/*                            Identify()                                */
+/************************************************************************/
+
+int RRASTERDataset::Identify( GDALOpenInfo * poOpenInfo )
+
+{
+    if( poOpenInfo->nHeaderBytes < 40
+        || poOpenInfo->fpL == NULL
+        || !EQUAL( CPLGetExtension(poOpenInfo->pszFilename), "grd" )
+        || strstr((const char *) poOpenInfo->pabyHeader, "ncols") == NULL
+        || strstr((const char *) poOpenInfo->pabyHeader, "nrows") == NULL
+        || strstr((const char *) poOpenInfo->pabyHeader, "xmin") == NULL
+        || strstr((const char *) poOpenInfo->pabyHeader, "ymin") == NULL
+        || strstr((const char *) poOpenInfo->pabyHeader, "xmax") == NULL
+        || strstr((const char *) poOpenInfo->pabyHeader, "ymax") == NULL
+        || strstr((const char *) poOpenInfo->pabyHeader, "datatype") == NULL )
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset *RRASTERDataset::Open( GDALOpenInfo * poOpenInfo )
+{
+    if( !Identify(poOpenInfo) )
+        return NULL;
+
+    if( poOpenInfo->eAccess == GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Update not supported");
+        return NULL;
+    }
+
+    const char* pszLine = NULL;
+    int nRows = 0;
+    int nCols = 0;
+    double dfXMin = 0.0;
+    double dfYMin = 0.0;
+    double dfXMax = 0.0;
+    double dfYMax = 0.0;
+    int l_nBands = 1;
+    CPLString osDataType;
+    CPLString osBandOrder;
+    CPLString osProjection;
+    CPLString osByteOrder;
+    CPLString osNoDataValue("NA");
+    CPLString osMinValue;
+    CPLString osMaxValue;
+    VSIRewindL(poOpenInfo->fpL);
+    while( (pszLine = CPLReadLine2L(poOpenInfo->fpL, 1024, NULL)) != NULL )
+    {
+        char* pszKey = NULL;
+        const char* pszValue = CPLParseNameValue(pszLine, &pszKey);
+        if( pszKey && pszValue )
+        {
+            if( EQUAL(pszKey, "ncols") )
+                nCols = atoi(pszValue);
+            else if( EQUAL(pszKey, "nrows") )
+                nRows = atoi(pszValue);
+            else if( EQUAL(pszKey, "xmin") )
+                dfXMin = CPLAtof(pszValue);
+            else if( EQUAL(pszKey, "ymin") )
+                dfYMin = CPLAtof(pszValue);
+            else if( EQUAL(pszKey, "xmax") )
+                dfXMax = CPLAtof(pszValue);
+            else if( EQUAL(pszKey, "ymax") )
+                dfYMax = CPLAtof(pszValue);
+            else if( EQUAL(pszKey, "projection") )
+                osProjection = pszValue;
+            else if( EQUAL(pszKey, "nbands") )
+                l_nBands = atoi(pszValue);
+            else if( EQUAL(pszKey, "bandorder") )
+                osBandOrder = pszValue;
+            else if( EQUAL(pszKey, "datatype") )
+                osDataType = pszValue;
+            else if( EQUAL(pszKey, "byteorder") )
+                osByteOrder = pszValue;
+            else if( EQUAL(pszKey, "nodatavalue") )
+                osNoDataValue = pszValue;
+            else if( EQUAL(pszKey, "minvalue") )
+                osMinValue = pszValue;
+            else if( EQUAL(pszKey, "maxvalue") )
+                osMaxValue = pszValue;
+        }
+        CPLFree(pszKey);
+    }
+    if( !GDALCheckDatasetDimensions(nCols, nRows) )
+        return NULL;
+    if( !GDALCheckBandCount(l_nBands, FALSE) )
+        return NULL;
+
+    GDALDataType eDT = GDT_Unknown;
+    if( EQUAL(osDataType, "LOG1S") )
+        eDT = GDT_Byte; // mapping TBC
+    else if( EQUAL(osDataType, "INT1S") )
+        eDT = GDT_Byte;
+    else if( EQUAL(osDataType, "INT2S") )
+        eDT = GDT_Int16;
+    else if( EQUAL(osDataType, "INT4S") )
+        eDT = GDT_Int32;
+    else if( EQUAL(osDataType, "INT8S") )
+        eDT = GDT_Float64; // Approximate matching
+    else if( EQUAL(osDataType, "INT1U") )
+        eDT = GDT_Byte;
+    else if( EQUAL(osDataType, "INT2U") )
+        eDT = GDT_UInt16;
+    else if( EQUAL(osDataType, "INT4U") ) // Not documented
+        eDT = GDT_UInt32;
+    else if( EQUAL(osDataType, "FLT4S") )
+        eDT = GDT_Float32;
+    else if( EQUAL(osDataType, "FLT8S") )
+        eDT = GDT_Float64;
+    else
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unhandled datatype=%s", osDataType.c_str() );
+        return NULL;
+    }
+    if( l_nBands > 1 && osBandOrder.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Missing 'bandorder'" );
+        return NULL;
+    }
+
+    int bNativeOrder = TRUE;
+    if( EQUAL(osByteOrder, "little") )
+    {
+        bNativeOrder = CPL_IS_LSB;
+    }
+    else if( EQUAL(osByteOrder, "big") )
+    {
+        bNativeOrder = !CPL_IS_LSB;
+    }
+    else if( !EQUAL(osByteOrder, "") )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Unhandled byteorder=%s. Assuming native order",
+                 osByteOrder.c_str() );
+    }
+
+    int nPixelOffset = 0;
+    int nLineOffset = 0;
+    vsi_l_offset nBandOffset = 0;
+    const int nPixelSize = GDALGetDataTypeSizeBytes( eDT );
+    if( l_nBands == 1 || EQUAL( osBandOrder, "BIL" ) )
+    {
+        nPixelOffset = nPixelSize;
+        if( l_nBands != 0 && nPixelSize != 0 &&
+            nCols > INT_MAX / ( l_nBands * nPixelSize ) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Too many columns" );
+            return NULL;
+        }
+        nLineOffset = nPixelSize * nCols * l_nBands;
+        nBandOffset = nPixelSize * nCols;
+    }
+    else if( EQUAL( osBandOrder, "BIP" ) )
+    {
+        if( l_nBands != 0 && nPixelSize != 0 &&
+            nCols > INT_MAX / ( l_nBands * nPixelSize ) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Too many columns" );
+            return NULL;
+        }
+        nPixelOffset = nPixelSize * l_nBands;
+        nLineOffset = nPixelSize * nCols * l_nBands;
+        nBandOffset = nPixelSize;
+    }
+    else if( EQUAL( osBandOrder, "BSQ" ) )
+    {
+        if( nPixelSize != 0 && nCols > INT_MAX / nPixelSize )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Too many columns" );
+            return NULL;
+        }
+        nPixelOffset = nPixelSize;
+        nLineOffset = nPixelSize * nCols;
+        nBandOffset = static_cast<vsi_l_offset>(nLineOffset) * nRows;
+    }
+    else if( l_nBands > 1 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Unknown bandorder" );
+        return NULL;
+    }
+
+    CPLString osGriFilename;
+    CPLString osDirname( CPLGetDirname(poOpenInfo->pszFilename) );
+    CPLString osBasename( CPLGetBasename(poOpenInfo->pszFilename) );
+    CPLString osGRDExtension( CPLGetExtension(poOpenInfo->pszFilename) );
+    CPLString osGRIExtension( (osGRDExtension[0] == 'g') ? "gri" : "GRI" );
+    char** papszSiblings = poOpenInfo->GetSiblingFiles();
+    if( papszSiblings )
+    {
+        int iFile = CSLFindString(papszSiblings,
+                            CPLFormFilename(NULL, osBasename, osGRIExtension) );
+        if( iFile < 0 )
+            return NULL;
+        osGriFilename = CPLFormFilename( osDirname,
+                                         papszSiblings[iFile], NULL );
+    }
+    else
+    {
+        osGriFilename = CPLFormFilename( osDirname, osBasename, osGRIExtension );
+    }
+
+    VSILFILE* fpImage = VSIFOpenL( osGriFilename, "rb" );
+    if( fpImage == NULL )
+        return NULL;
+
+    RRASTERDataset* poDS = new RRASTERDataset;
+    poDS->nRasterXSize = nCols;
+    poDS->nRasterYSize = nRows;
+    poDS->m_adfGeoTransform[0] = dfXMin;
+    poDS->m_adfGeoTransform[1] = (dfXMax - dfXMin) / nCols;
+    poDS->m_adfGeoTransform[2] = 0.0;
+    poDS->m_adfGeoTransform[3] = dfYMax;
+    poDS->m_adfGeoTransform[4] = 0.0;
+    poDS->m_adfGeoTransform[5] = -(dfYMax - dfYMin) / nRows;
+    poDS->m_osGriFilename = osGriFilename;
+    poDS->m_fpImage = fpImage;
+
+    if( !osProjection.empty() )
+    {
+        OGRSpatialReference oSRS;
+        if( oSRS.importFromProj4( osProjection.c_str() ) == OGRERR_NONE )
+        {
+            char* pszWKT = NULL;
+            oSRS.exportToWkt( &pszWKT );
+            if( pszWKT )
+                poDS->m_osProjection = pszWKT;
+            CPLFree( pszWKT );
+        }
+    }
+
+    char** papszMinValues = CSLTokenizeString2(osMinValue, ":", 0);
+    char** papszMaxValues = CSLTokenizeString2(osMaxValue, ":", 0);
+    if( CSLCount(papszMinValues) != l_nBands ||
+        CSLCount(papszMaxValues) != l_nBands )
+    {
+        CSLDestroy(papszMinValues);
+        CSLDestroy(papszMaxValues);
+        papszMinValues = NULL;
+        papszMaxValues = NULL;
+    }
+
+    for( int i=1; i<=l_nBands; i++ )
+    {
+        RRASTERRasterBand* poBand = new RRASTERRasterBand(
+                                  poDS, i, fpImage, nBandOffset * (i-1),
+                                  nPixelOffset,
+                                  nLineOffset, eDT, bNativeOrder );
+        poDS->SetBand( i, poBand );
+        if( EQUAL(osDataType, "INT1S") )
+        {
+            poDS->GetRasterBand(i)->SetMetadataItem(
+                    "SIGNEDBYTE", "PIXELTYPE", "IMAGE_STRUCTURE" );
+        }
+        if( !EQUAL(osNoDataValue, "NA") )
+        {
+            double dfNoDataValue = CPLAtof(osNoDataValue);
+            poBand->SetNoDataValue(dfNoDataValue);
+        }
+        if( papszMinValues && papszMaxValues )
+        {
+            poBand->SetMinMax( CPLAtof(papszMinValues[i-1]),
+                               CPLAtof(papszMaxValues[i-1]) );
+        }
+    }
+    CSLDestroy(papszMinValues);
+    CSLDestroy(papszMaxValues);
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                   GDALRegister_RRASTER()                             */
+/************************************************************************/
+
+void GDALRegister_RRASTER()
+
+{
+    if( GDALGetDriverByName( "RRASTER" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "RRASTER" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "grd" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "R Raster" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
+                               "frmt_various.html#RRASTER" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = RRASTERDataset::Open;
+    poDriver->pfnIdentify = RRASTERDataset::Identify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/frmts/raw/snodasdataset.cpp b/frmts/raw/snodasdataset.cpp
index f3b26bb..7952dca 100644
--- a/frmts/raw/snodasdataset.cpp
+++ b/frmts/raw/snodasdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: snodasdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $
  *
  * Project:  SNODAS driver
  * Purpose:  Implementation of SNODASDataset
@@ -32,9 +31,7 @@
 #include "ogr_srs_api.h"
 #include "rawdataset.h"
 
-CPL_CVSID("$Id: snodasdataset.cpp 33864 2016-04-02 11:50:14Z goatbar $");
-
-// g++ -g -Wall -fPIC frmts/raw/snodasdataset.cpp -shared -o gdal_SNODAS.so -Iport -Igcore -Ifrmts/raw -Iogr -L. -lgdal
+CPL_CVSID("$Id: snodasdataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -47,11 +44,11 @@ class SNODASRasterBand;
 class SNODASDataset : public RawDataset
 {
     CPLString   osDataFilename;
-    int         bGotTransform;
+    bool        bGotTransform;
     double      adfGeoTransform[6];
-    int         bHasNoData;
+    bool        bHasNoData;
     double      dfNoData;
-    int         bHasMin;
+    bool        bHasMin;
     double      dfMin;
     int         bHasMax;
     double      dfMax;
@@ -62,16 +59,15 @@ class SNODASDataset : public RawDataset
                     SNODASDataset();
     virtual ~SNODASDataset();
 
-    virtual CPLErr GetGeoTransform( double * padfTransform );
-    virtual const char *GetProjectionRef(void);
+    virtual CPLErr GetGeoTransform( double * padfTransform ) override;
+    virtual const char *GetProjectionRef(void) override;
 
-    virtual char **GetFileList();
+    virtual char **GetFileList() override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
 };
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                            SNODASRasterBand                          */
@@ -81,26 +77,24 @@ class SNODASDataset : public RawDataset
 class SNODASRasterBand : public RawRasterBand
 {
   public:
-            SNODASRasterBand(VSILFILE* fpRaw, int nXSize, int nYSize);
+            SNODASRasterBand( VSILFILE* fpRaw, int nXSize, int nYSize );
     virtual ~SNODASRasterBand() {}
 
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum(int *pbSuccess = NULL );
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum(int *pbSuccess = NULL ) override;
 };
 
-
 /************************************************************************/
 /*                         SNODASRasterBand()                           */
 /************************************************************************/
 
-SNODASRasterBand::SNODASRasterBand(VSILFILE* fpRawIn,
-                                   int nXSize, int nYSize) :
+SNODASRasterBand::SNODASRasterBand( VSILFILE* fpRawIn,
+                                    int nXSize, int nYSize ) :
     RawRasterBand( fpRawIn, 0, 2,
                    nXSize * 2, GDT_Int16,
                    !CPL_IS_LSB, nXSize, nYSize, TRUE, TRUE)
-{
-}
+{}
 
 /************************************************************************/
 /*                          GetNoDataValue()                            */
@@ -109,10 +103,10 @@ SNODASRasterBand::SNODASRasterBand(VSILFILE* fpRawIn,
 double SNODASRasterBand::GetNoDataValue( int *pbSuccess )
 {
     SNODASDataset* poGDS = reinterpret_cast<SNODASDataset *>( poDS );
-    if (pbSuccess)
+    if( pbSuccess )
         *pbSuccess = poGDS->bHasNoData;
 
-    if (poGDS->bHasNoData)
+    if( poGDS->bHasNoData )
         return poGDS->dfNoData;
 
     return RawRasterBand::GetNoDataValue(pbSuccess);
@@ -125,10 +119,10 @@ double SNODASRasterBand::GetNoDataValue( int *pbSuccess )
 double SNODASRasterBand::GetMinimum( int *pbSuccess )
 {
     SNODASDataset* poGDS = reinterpret_cast<SNODASDataset *>( poDS );
-    if (pbSuccess)
+    if( pbSuccess )
         *pbSuccess = poGDS->bHasMin;
 
-    if (poGDS->bHasMin)
+    if( poGDS->bHasMin )
         return poGDS->dfMin;
 
     return RawRasterBand::GetMinimum(pbSuccess);
@@ -141,10 +135,10 @@ double SNODASRasterBand::GetMinimum( int *pbSuccess )
 double SNODASRasterBand::GetMaximum( int *pbSuccess )
 {
     SNODASDataset* poGDS = reinterpret_cast<SNODASDataset *>( poDS );
-    if (pbSuccess)
+    if( pbSuccess )
         *pbSuccess = poGDS->bHasMax;
 
-    if (poGDS->bHasMax)
+    if( poGDS->bHasMax )
         return poGDS->dfMax;
 
     return RawRasterBand::GetMaximum(pbSuccess);
@@ -161,12 +155,12 @@ double SNODASRasterBand::GetMaximum( int *pbSuccess )
 /************************************************************************/
 
 SNODASDataset::SNODASDataset() :
-    bGotTransform(FALSE),
-    bHasNoData(FALSE),
+    bGotTransform(false),
+    bHasNoData(false),
     dfNoData(0.0),
-    bHasMin(FALSE),
+    bHasMin(false),
     dfMin(0.0),
-    bHasMax(FALSE),
+    bHasMax(false),
     dfMax(0.0)
 {
     adfGeoTransform[0] = 0.0;
@@ -211,10 +205,8 @@ CPLErr SNODASDataset::GetGeoTransform( double * padfTransform )
     }
 
     return GDALPamDataset::GetGeoTransform( padfTransform );
-
 }
 
-
 /************************************************************************/
 /*                            GetFileList()                             */
 /************************************************************************/
@@ -238,7 +230,9 @@ int SNODASDataset::Identify( GDALOpenInfo * poOpenInfo )
     if (poOpenInfo->nHeaderBytes == 0)
         return FALSE;
 
-    return STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "Format version: NOHRSC GIS/RS raster file v1.1");}
+    return STARTS_WITH_CI(
+        reinterpret_cast<char *>(poOpenInfo->pabyHeader),
+        "Format version: NOHRSC GIS/RS raster file v1.1" );}
 
 /************************************************************************/
 /*                                Open()                                */
@@ -256,7 +250,8 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    int             nRows = -1, nCols = -1;
+    int nRows = -1;
+    int nCols = -1;
     CPLString       osDataFilename;
     bool bIsInteger = false;
     bool bIs2Bytes = false;
@@ -266,40 +261,54 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
     bool bHasMin = false;
     double          dfMax = 0;
     bool bHasMax = false;
-    double          dfMinX = 0.0, dfMinY = 0.0, dfMaxX = 0.0, dfMaxY = 0.0;
+    double dfMinX = 0.0;
+    double dfMinY = 0.0;
+    double dfMaxX = 0.0;
+    double dfMaxY = 0.0;
     bool bHasMinX = false;
     bool bHasMinY = false;
     bool bHasMaxX = false;
     bool bHasMaxY = false;
     bool bNotProjected = false;
     bool bIsWGS84 = false;
-    CPLString       osDescription, osDataUnits;
-    int             nStartYear = -1, nStartMonth = -1, nStartDay = -1,
-                    nStartHour = -1, nStartMinute = -1, nStartSecond = -1;
-    int             nStopYear = -1, nStopMonth = -1, nStopDay = -1,
-                    nStopHour = -1, nStopMinute = -1, nStopSecond = -1;
-
-    const char *pszLine;
+    CPLString       osDataUnits;
+    CPLString       osDescription;
+    int nStartYear = -1;
+    int nStartMonth = -1;
+    int nStartDay = -1;
+    int nStartHour = -1;
+    int nStartMinute = -1;
+    int nStartSecond = -1;
+    int nStopYear = -1;
+    int nStopMonth = -1;
+    int nStopDay = -1;
+    int nStopHour = -1;
+    int nStopMinute = -1;
+    int nStopSecond = -1;
+
+    const char *pszLine = NULL;
     while( (pszLine = CPLReadLine2L( fp, 256, NULL )) != NULL )
     {
-        char** papszTokens = CSLTokenizeStringComplex( pszLine, ":", TRUE, FALSE );
+        char** papszTokens =
+            CSLTokenizeStringComplex( pszLine, ":", TRUE, FALSE );
         if( CSLCount( papszTokens ) != 2 )
         {
             CSLDestroy( papszTokens );
             continue;
         }
         if( papszTokens[1][0] == ' ' )
-            memmove(papszTokens[1], papszTokens[1] + 1, strlen(papszTokens[1] + 1) + 1);
+            memmove( papszTokens[1], papszTokens[1] + 1,
+                     strlen(papszTokens[1] + 1) + 1);
 
-        if( EQUAL(papszTokens[0],"Data file pathname") )
+        if( EQUAL(papszTokens[0], "Data file pathname") )
         {
             osDataFilename = papszTokens[1];
         }
-        else if( EQUAL(papszTokens[0],"Description") )
+        else if( EQUAL(papszTokens[0], "Description") )
         {
             osDescription = papszTokens[1];
         }
-        else if( EQUAL(papszTokens[0],"Data units") )
+        else if( EQUAL(papszTokens[0], "Data units") )
         {
             osDataUnits= papszTokens[1];
         }
@@ -310,81 +319,81 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
             nStartMonth = atoi(papszTokens[1]);
         else if( EQUAL(papszTokens[0],"Start day") )
             nStartDay = atoi(papszTokens[1]);
-        else if( EQUAL(papszTokens[0],"Start hour") )
+        else if( EQUAL(papszTokens[0], "Start hour") )
             nStartHour = atoi(papszTokens[1]);
-        else if( EQUAL(papszTokens[0],"Start minute") )
+        else if( EQUAL(papszTokens[0]," Start minute") )
             nStartMinute = atoi(papszTokens[1]);
-        else if( EQUAL(papszTokens[0],"Start second") )
+        else if( EQUAL(papszTokens[0], "Start second") )
             nStartSecond = atoi(papszTokens[1]);
 
-        else if( EQUAL(papszTokens[0],"Stop year") )
+        else if( EQUAL(papszTokens[0], "Stop year") )
             nStopYear = atoi(papszTokens[1]);
-        else if( EQUAL(papszTokens[0],"Stop month") )
+        else if( EQUAL(papszTokens[0], "Stop month") )
             nStopMonth = atoi(papszTokens[1]);
-        else if( EQUAL(papszTokens[0],"Stop day") )
+        else if( EQUAL(papszTokens[0], "Stop day") )
             nStopDay = atoi(papszTokens[1]);
-        else if( EQUAL(papszTokens[0],"Stop hour") )
+        else if( EQUAL(papszTokens[0], "Stop hour") )
             nStopHour = atoi(papszTokens[1]);
-        else if( EQUAL(papszTokens[0],"Stop minute") )
+        else if( EQUAL(papszTokens[0], "Stop minute") )
             nStopMinute = atoi(papszTokens[1]);
-        else if( EQUAL(papszTokens[0],"Stop second") )
+        else if( EQUAL(papszTokens[0], "Stop second") )
             nStopSecond = atoi(papszTokens[1]);
 
-        else if( EQUAL(papszTokens[0],"Number of columns") )
+        else if( EQUAL(papszTokens[0], "Number of columns") )
         {
             nCols = atoi(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"Number of rows") )
+        else if( EQUAL(papszTokens[0], "Number of rows") )
         {
             nRows = atoi(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"Data type"))
+        else if( EQUAL(papszTokens[0], "Data type") )
         {
             bIsInteger = EQUAL(papszTokens[1],"integer");
         }
-        else if( EQUAL(papszTokens[0],"Data bytes per pixel"))
+        else if( EQUAL(papszTokens[0], "Data bytes per pixel") )
         {
             bIs2Bytes = EQUAL(papszTokens[1],"2");
         }
-        else if( EQUAL(papszTokens[0],"Projected"))
+        else if( EQUAL(papszTokens[0], "Projected") )
         {
             bNotProjected = EQUAL(papszTokens[1],"no");
         }
-        else if( EQUAL(papszTokens[0],"Horizontal datum"))
+        else if( EQUAL(papszTokens[0], "Horizontal datum") )
         {
             bIsWGS84 = EQUAL(papszTokens[1],"WGS84");
         }
-        else if( EQUAL(papszTokens[0],"No data value"))
+        else if( EQUAL(papszTokens[0], "No data value") )
         {
             bHasNoData = true;
             dfNoData = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"Minimum data value"))
+        else if( EQUAL(papszTokens[0],"Minimum data value") )
         {
             bHasMin = true;
             dfMin = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"Maximum data value"))
+        else if( EQUAL(papszTokens[0], "Maximum data value") )
         {
             bHasMax = true;
             dfMax = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"Minimum x-axis coordinate") )
+        else if( EQUAL(papszTokens[0], "Minimum x-axis coordinate") )
         {
             bHasMinX = true;
             dfMinX = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"Minimum y-axis coordinate") )
+        else if( EQUAL(papszTokens[0], "Minimum y-axis coordinate") )
         {
             bHasMinY = true;
             dfMinY = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"Maximum x-axis coordinate") )
+        else if( EQUAL(papszTokens[0], "Maximum x-axis coordinate") )
         {
             bHasMaxX = true;
             dfMaxX = CPLAtofM(papszTokens[1]);
         }
-        else if( EQUAL(papszTokens[0],"Maximum y-axis coordinate") )
+        else if( EQUAL(papszTokens[0], "Maximum y-axis coordinate") )
         {
             bHasMaxY = true;
             dfMaxY = CPLAtofM(papszTokens[1]);
@@ -406,10 +415,10 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
     if( !bNotProjected || !bIsWGS84 )
         return NULL;
 
-    if( osDataFilename.size() == 0 )
+    if( osDataFilename.empty() )
         return NULL;
 
-    if (!GDALCheckDatasetDimensions(nCols, nRows))
+    if( !GDALCheckDatasetDimensions(nCols, nRows) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -437,9 +446,9 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->dfMin = dfMin;
     poDS->bHasMax = bHasMax;
     poDS->dfMax = dfMax;
-    if (bHasMinX && bHasMinY && bHasMaxX && bHasMaxY)
+    if( bHasMinX && bHasMinY && bHasMaxX && bHasMaxY )
     {
-        poDS->bGotTransform = TRUE;
+        poDS->bGotTransform = true;
         poDS->adfGeoTransform[0] = dfMinX;
         poDS->adfGeoTransform[1] = (dfMaxX - dfMinX) / nCols;
         poDS->adfGeoTransform[2] = 0.0;
@@ -448,18 +457,18 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->adfGeoTransform[5] = - (dfMaxY - dfMinY) / nRows;
     }
 
-    if (osDescription.size())
+    if( !osDescription.empty() )
         poDS->SetMetadataItem("Description", osDescription);
-    if (osDataUnits.size())
+    if( !osDataUnits.empty() )
         poDS->SetMetadataItem("Data_Units", osDataUnits);
-    if (nStartYear != -1 && nStartMonth != -1 && nStartDay != -1 &&
-        nStartHour != -1 && nStartMinute != -1 && nStartSecond != -1)
+    if( nStartYear != -1 && nStartMonth != -1 && nStartDay != -1 &&
+        nStartHour != -1 && nStartMinute != -1 && nStartSecond != -1 )
         poDS->SetMetadataItem("Start_Date",
                               CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d",
                                         nStartYear, nStartMonth, nStartDay,
                                         nStartHour, nStartMinute, nStartSecond));
-    if (nStopYear != -1 && nStopMonth != -1 && nStopDay != -1 &&
-        nStopHour != -1 && nStopMinute != -1 && nStopSecond != -1)
+    if( nStopYear != -1 && nStopMonth != -1 && nStopDay != -1 &&
+        nStopHour != -1 && nStopMinute != -1 && nStopSecond != -1 )
         poDS->SetMetadataItem("Stop_Date",
                               CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02d",
                                         nStopYear, nStopMonth, nStopDay,
@@ -481,7 +490,7 @@ GDALDataset *SNODASDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/rik/makefile.vc b/frmts/rik/makefile.vc
index 88669a0..f290707 100644
--- a/frmts/rik/makefile.vc
+++ b/frmts/rik/makefile.vc
@@ -5,7 +5,11 @@ GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS = 	-I..\zlib
+!IFDEF ZLIB_EXTERNAL_LIB
+EXTRAFLAGS = $(ZLIB_INC)
+!ELSE
+EXTRAFLAGS = -I..\zlib
+!ENDIF
 
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\o
diff --git a/frmts/rik/rikdataset.cpp b/frmts/rik/rikdataset.cpp
index 177674f..b65d29a 100644
--- a/frmts/rik/rikdataset.cpp
+++ b/frmts/rik/rikdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rikdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  RIK Reader
  * Purpose:  All code for RIK Reader
@@ -33,7 +32,7 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: rikdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: rikdataset.cpp 36763 2016-12-09 22:10:55Z rouault $");
 
 #define RIK_HEADER_DEBUG 0
 #define RIK_CLEAR_DEBUG 0
@@ -109,7 +108,7 @@ typedef struct
 
 /************************************************************************/
 /* ==================================================================== */
-/*				RIKDataset				*/
+/*                              RIKDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -121,7 +120,7 @@ class RIKDataset : public GDALPamDataset
 
     VSILFILE        *fp;
 
-    double      fTransform[6];
+    double      adfTransform[6];
 
     GUInt32     nBlockXSize;
     GUInt32     nBlockYSize;
@@ -134,13 +133,14 @@ class RIKDataset : public GDALPamDataset
     GDALColorTable *poColorTable;
 
   public:
+     RIKDataset();
     ~RIKDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
 
-    CPLErr 	GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
+    CPLErr      GetGeoTransform( double * padfTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
 /************************************************************************/
@@ -157,9 +157,9 @@ class RIKRasterBand : public GDALPamRasterBand
 
     RIKRasterBand( RIKDataset *, int );
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable *GetColorTable();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable *GetColorTable() override;
 };
 
 /************************************************************************/
@@ -224,7 +224,7 @@ static int GetNextLZWCode( int codeBits,
     }
 
 #if RIK_PIXEL_DEBUG
-    printf( "c%03X\n", ret );
+    printf( "c%03X\n", ret );/*ok*/
 #endif
 
     return ret;
@@ -249,7 +249,7 @@ static void OutputPixel( GByte pixel,
     imagePos++;
 
 #if RIK_PIXEL_DEBUG
-    printf( "_%02X %d\n", pixel, imagePos );
+    printf( "_%02X %d\n", pixel, imagePos );/*ok*/
 #endif
 
     // Check if we need to change line
@@ -257,7 +257,7 @@ static void OutputPixel( GByte pixel,
     if( imagePos == lineBreak )
     {
 #if RIK_PIXEL_DEBUG
-        printf( "\n%d\n", imageLine );
+        printf( "\n%d\n", imageLine );/*ok*/
 #endif
 
         imagePos = 0;
@@ -469,7 +469,7 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                     *stack = lastOutput;
                     stackPtr = 1;
                     decodeCode = lastCode;
-       	        }
+                }
                 else if( code > lastAdded + 1 )
                 {
                     throw "Too high code";
@@ -479,8 +479,8 @@ CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
                 int i = 0;
                 while( ++i < LZW_CODES &&
-       	               decodeCode >= LZW_CLEAR &&
-       	               decodeCode < LZW_NO_SUCH_CODE )
+                       decodeCode >= LZW_CLEAR &&
+                       decodeCode < LZW_NO_SUCH_CODE )
                 {
                     stack[stackPtr++] = character[decodeCode];
                     decodeCode = prefix[decodeCode];
@@ -596,11 +596,30 @@ GDALColorTable *RIKRasterBand::GetColorTable()
 
 /************************************************************************/
 /* ==================================================================== */
-/*				RIKDataset				*/
+/*                              RIKDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
 /************************************************************************/
+/*                             RIKDataset()                             */
+/************************************************************************/
+
+RIKDataset::RIKDataset() :
+    fp( NULL ),
+    nBlockXSize( 0 ),
+    nBlockYSize( 0 ),
+    nHorBlocks( 0 ),
+    nVertBlocks( 0 ),
+    nFileSize( 0 ),
+    pOffsets( NULL ),
+    options( 0 ),
+    poColorTable( NULL )
+
+{
+    memset( adfTransform, 0, sizeof(adfTransform) );
+}
+
+/************************************************************************/
 /*                            ~RIKDataset()                             */
 /************************************************************************/
 
@@ -621,7 +640,7 @@ RIKDataset::~RIKDataset()
 CPLErr RIKDataset::GetGeoTransform( double * padfTransform )
 
 {
-    memcpy( padfTransform, &fTransform, sizeof(double) * 6 );
+    memcpy( padfTransform, &adfTransform, sizeof(double) * 6 );
 
     return CE_None;
 }
@@ -1169,17 +1188,17 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
 
-    RIKDataset 	*poDS = new RIKDataset();
+    RIKDataset *poDS = new RIKDataset();
 
     poDS->fp = poOpenInfo->fpL;
     poOpenInfo->fpL = NULL;
 
-    poDS->fTransform[0] = header.fWest - metersPerPixel / 2.0;
-    poDS->fTransform[1] = metersPerPixel;
-    poDS->fTransform[2] = 0.0;
-    poDS->fTransform[3] = header.fNorth + metersPerPixel / 2.0;
-    poDS->fTransform[4] = 0.0;
-    poDS->fTransform[5] = -metersPerPixel;
+    poDS->adfTransform[0] = header.fWest - metersPerPixel / 2.0;
+    poDS->adfTransform[1] = metersPerPixel;
+    poDS->adfTransform[2] = 0.0;
+    poDS->adfTransform[3] = header.fNorth + metersPerPixel / 2.0;
+    poDS->adfTransform[4] = 0.0;
+    poDS->adfTransform[5] = -metersPerPixel;
 
     poDS->nBlockXSize = header.iBlockWidth;
     poDS->nBlockYSize = header.iBlockHeight;
@@ -1236,7 +1255,7 @@ GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/rmf/frmt_rmf.html b/frmts/rmf/frmt_rmf.html
index 5fe681e..d1e8298 100644
--- a/frmts/rmf/frmt_rmf.html
+++ b/frmts/rmf/frmt_rmf.html
@@ -10,7 +10,7 @@
 RMF is a simple tiled raster format used in the GIS "Integration" and
 "Panorama" GIS. The format itself has very poor capabilities.<p>
 
-There are two flavours of RMF called MTW and RSW. MTW supports 16-bit integer
+There are two flavors of RMF called MTW and RSW. MTW supports 16-bit integer
 and 32/64-bit floating point data in a single channel and aimed to store DEM
 data. RSW is a general purpose raster. It supports single channel colormapped
 or three channel RGB images. Only 8-bit data can be stored in RSW. Simple
diff --git a/frmts/rmf/rmfdataset.cpp b/frmts/rmf/rmfdataset.cpp
index c86706e..522f0b1 100644
--- a/frmts/rmf/rmfdataset.cpp
+++ b/frmts/rmf/rmfdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rmfdataset.cpp 36638 2016-12-02 19:08:00Z rouault $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Read/write raster files used in GIS "Integratsia"
@@ -34,7 +33,7 @@
 
 #include "rmfdataset.h"
 
-CPL_CVSID("$Id: rmfdataset.cpp 36638 2016-12-02 19:08:00Z rouault $");
+CPL_CVSID("$Id: rmfdataset.cpp 37464 2017-02-26 02:18:24Z goatbar $");
 
 static const int RMF_DEFAULT_BLOCKXSIZE = 256;
 static const int RMF_DEFAULT_BLOCKYSIZE = 256;
@@ -64,7 +63,7 @@ RMFRasterBand::RMFRasterBand( RMFDataset *poDSIn, int nBandIn,
     nBytesPerPixel(poDSIn->sHeader.nBitDepth / 8),
     nLastTileWidth(poDSIn->GetRasterXSize() % poDSIn->sHeader.nTileWidth),
     nLastTileHeight(poDSIn->GetRasterYSize() % poDSIn->sHeader.nTileHeight),
-    nDataSize(GDALGetDataTypeSize( eType ) / 8)
+    nDataSize(GDALGetDataTypeSizeBytes( eType ))
 {
     poDS = poDSIn;
     nBand = nBandIn;
@@ -107,7 +106,7 @@ CPLErr RMFRasterBand::ReadBuffer( GByte *pabyBuf, GUInt32 nBytes ) const
 
     const vsi_l_offset nOffset = VSIFTellL( poGDS->fp );
 
-    if ( VSIFReadL( pabyBuf, 1, nBytes, poGDS->fp ) < nBytes )
+    if( VSIFReadL( pabyBuf, 1, nBytes, poGDS->fp ) < nBytes )
     {
         // XXX
         if( poGDS->eAccess == GA_Update )
@@ -117,30 +116,30 @@ CPLErr RMFRasterBand::ReadBuffer( GByte *pabyBuf, GUInt32 nBytes ) const
         else
         {
             CPLError( CE_Failure, CPLE_FileIO,
-                      "Can't read at offset %ld from input file.\n%s\n",
+                      "Can't read at offset %ld from input file.\n%s",
                       static_cast<long>( nOffset ), VSIStrerror( errno ) );
             return CE_Failure;
         }
     }
 
 #ifdef CPL_MSB
-    if ( poGDS->eRMFType == RMFT_MTW )
+    if( poGDS->eRMFType == RMFT_MTW )
     {
-        if ( poGDS->sHeader.nBitDepth == 16 )
+        if( poGDS->sHeader.nBitDepth == 16 )
         {
-            for ( GUInt32 i = 0; i < nBytes; i += 2 )
+            for( GUInt32 i = 0; i < nBytes; i += 2 )
                 CPL_SWAP16PTR( pabyBuf + i );
         }
 
-        else if ( poGDS->sHeader.nBitDepth == 32 )
+        else if( poGDS->sHeader.nBitDepth == 32 )
         {
-            for ( GUInt32 i = 0; i < nBytes; i += 4 )
+            for( GUInt32 i = 0; i < nBytes; i += 4 )
                 CPL_SWAP32PTR( pabyBuf + i );
         }
 
-        else if ( poGDS->sHeader.nBitDepth == 64 )
+        else if( poGDS->sHeader.nBitDepth == 64 )
         {
-            for ( GUInt32 i = 0; i < nBytes; i += 8 )
+            for( GUInt32 i = 0; i < nBytes; i += 8 )
                 CPL_SWAPDOUBLE( pabyBuf + i );
         }
     }
@@ -165,77 +164,76 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
     memset( pImage, 0, nBlockBytes );
 
-    GUInt32 nTile = nBlockYOff * poGDS->nXTiles + nBlockXOff;
-    if (2 * nTile + 1 >= poGDS->sHeader.nTileTblSize / sizeof(GUInt32))
+    const GUInt32 nTile = nBlockYOff * poGDS->nXTiles + nBlockXOff;
+    if( 2 * nTile + 1 >= poGDS->sHeader.nTileTblSize / sizeof(GUInt32) )
     {
         return CE_Failure;
     }
 
     GUInt32 nTileBytes = poGDS->paiTiles[2 * nTile + 1];
-    GUInt32 nCurBlockYSize;
-
-    if ( nLastTileHeight
+    const GUInt32 nCurBlockYSize =
+        (nLastTileHeight
          && static_cast<GUInt32>( nBlockYOff ) == poGDS->nYTiles - 1 )
-        nCurBlockYSize = nLastTileHeight;
-    else
-        nCurBlockYSize = nBlockYSize;
-        
-    vsi_l_offset nTileOffset = poGDS->GetFileOffset( poGDS->paiTiles[2 * nTile] );
-    
-    if ( VSIFSeekL( poGDS->fp, nTileOffset, SEEK_SET ) < 0 )
+        ? nLastTileHeight
+        : nBlockYSize;
+
+    vsi_l_offset nTileOffset =
+        poGDS->GetFileOffset( poGDS->paiTiles[2 * nTile] );
+
+    if( VSIFSeekL( poGDS->fp, nTileOffset, SEEK_SET ) < 0 )
     {
         // XXX: We will not report error here, because file just may be
-	// in update state and data for this block will be available later
+        // in update state and data for this block will be available later
         if( poGDS->eAccess == GA_Update )
             return CE_None;
 
         CPLError( CE_Failure, CPLE_FileIO,
-                  "Can't seek to offset %ld in input file to read data.\n%s\n",
+                  "Can't seek to offset %ld in input file to read data.\n%s",
                   static_cast<long>( nTileOffset ),
                   VSIStrerror( errno ) );
         return CE_Failure;
     }
 
-    if ( poGDS->nBands == 1 &&
-         ( poGDS->sHeader.nBitDepth == 8
-           || poGDS->sHeader.nBitDepth == 16
-           || poGDS->sHeader.nBitDepth == 32
-           || poGDS->sHeader.nBitDepth == 64 ) )
+    if( poGDS->nBands == 1 &&
+        ( poGDS->sHeader.nBitDepth == 8
+          || poGDS->sHeader.nBitDepth == 16
+          || poGDS->sHeader.nBitDepth == 32
+          || poGDS->sHeader.nBitDepth == 64 ) )
     {
-        if ( nTileBytes > nBlockBytes )
+        if( nTileBytes > nBlockBytes )
             nTileBytes = nBlockBytes;
 
 /* -------------------------------------------------------------------- */
 /*  Decompress buffer, if needed.                                       */
 /* -------------------------------------------------------------------- */
-        if ( poGDS->Decompress )
+        if( poGDS->Decompress )
         {
-            GUInt32 nRawBytes;
+            GUInt32 nRawBytes = 0;
 
-            if ( nLastTileWidth && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
+            if( nLastTileWidth && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
                 nRawBytes = poGDS->nBands * nLastTileWidth * nDataSize;
             else
                 nRawBytes = poGDS->nBands * nBlockXSize * nDataSize;
 
-            if ( nLastTileHeight && (GUInt32)nBlockYOff == poGDS->nYTiles - 1 )
+            if( nLastTileHeight && (GUInt32)nBlockYOff == poGDS->nYTiles - 1 )
                 nRawBytes *= nLastTileHeight;
             else
                 nRawBytes *= nBlockYSize;
 
-            if ( nRawBytes > nTileBytes )
+            if( nRawBytes > nTileBytes )
             {
                 GByte *pabyTile = reinterpret_cast<GByte *>(
                     VSIMalloc( nTileBytes ) );
 
-                if ( !pabyTile )
+                if( !pabyTile )
                 {
                     CPLError( CE_Failure, CPLE_FileIO,
-                            "Can't allocate tile block of size %lu.\n%s\n",
+                            "Can't allocate tile block of size %lu.\n%s",
                             (unsigned long) nTileBytes, VSIStrerror( errno ) );
                     return CE_Failure;
                 }
 
-                if ( ReadBuffer( pabyTile, nTileBytes ) == CE_Failure )
+                if( ReadBuffer( pabyTile, nTileBytes ) == CE_Failure )
                 {
                     // XXX: Do not fail here, just return empty block
                     // and continue reading.
@@ -247,12 +245,12 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                       reinterpret_cast<GByte*>( pImage ),
                                       nRawBytes );
                 CPLFree( pabyTile );
-                /*nTileBytes = nRawBytes;*/
+                // nTileBytes = nRawBytes;
             }
             else
             {
-              if ( ReadBuffer( reinterpret_cast<GByte *>( pImage ),
-                               nTileBytes ) == CE_Failure )
+                if( ReadBuffer( reinterpret_cast<GByte *>( pImage ),
+                                nTileBytes ) == CE_Failure )
                 {
                     // XXX: Do not fail here, just return empty block
                     // and continue reading.
@@ -260,36 +258,30 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 }
             }
         }
-
         else
         {
-
-          if ( ReadBuffer( reinterpret_cast<GByte *>( pImage ),
-                           nTileBytes ) == CE_Failure )
+            if( ReadBuffer( reinterpret_cast<GByte *>( pImage ),
+                            nTileBytes ) == CE_Failure )
             {
                 // XXX: Do not fail here, just return empty block
                 // and continue reading.
                 return CE_None;
             }
-
         }
-
     }
-
-    else if ( poGDS->eRMFType == RMFT_RSW )
+    else if( poGDS->eRMFType == RMFT_RSW )
     {
         GByte *pabyTile = reinterpret_cast<GByte *>( VSIMalloc( nTileBytes ) );
 
-        if ( !pabyTile )
+        if( !pabyTile )
         {
             CPLError( CE_Failure, CPLE_FileIO,
-                      "Can't allocate tile block of size %lu.\n%s\n",
+                      "Can't allocate tile block of size %lu.\n%s",
                       (unsigned long) nTileBytes, VSIStrerror( errno ) );
             return CE_Failure;
         }
 
-
-        if ( ReadBuffer( pabyTile, nTileBytes ) == CE_Failure )
+        if( ReadBuffer( pabyTile, nTileBytes ) == CE_Failure )
         {
             // XXX: Do not fail here, just return empty block
             // and continue reading.
@@ -300,29 +292,29 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*  If buffer was compressed, decompress it first.                      */
 /* -------------------------------------------------------------------- */
-        if ( poGDS->Decompress )
+        if( poGDS->Decompress )
         {
-            GUInt32 nRawBytes;
+            GUInt32 nRawBytes = 0;
 
-            if ( nLastTileWidth && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
+            if( nLastTileWidth && (GUInt32)nBlockXOff == poGDS->nXTiles - 1 )
                 nRawBytes = poGDS->nBands * nLastTileWidth * nDataSize;
             else
                 nRawBytes = poGDS->nBands * nBlockXSize * nDataSize;
 
-            if ( nLastTileHeight && (GUInt32)nBlockYOff == poGDS->nYTiles - 1 )
+            if( nLastTileHeight && (GUInt32)nBlockYOff == poGDS->nYTiles - 1 )
                 nRawBytes *= nLastTileHeight;
             else
                 nRawBytes *= nBlockYSize;
 
-            if ( nRawBytes > nTileBytes )
+            if( nRawBytes > nTileBytes )
             {
                 GByte *pszRawBuf = reinterpret_cast<GByte *>(
                     VSIMalloc( nRawBytes ) );
-                if (pszRawBuf == NULL)
+                if( pszRawBuf == NULL )
                 {
                     CPLError( CE_Failure, CPLE_FileIO,
                               "Can't allocate a buffer for raw data of "
-                              "size %lu.\n%s\n",
+                              "size %lu.\n%s",
                               static_cast<unsigned long>( nRawBytes ),
                               VSIStrerror( errno ) );
 
@@ -341,11 +333,11 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /* -------------------------------------------------------------------- */
 /*  Deinterleave pixels from input buffer.                              */
 /* -------------------------------------------------------------------- */
-        if ( poGDS->sHeader.nBitDepth == 24 || poGDS->sHeader.nBitDepth == 32 )
+        if( poGDS->sHeader.nBitDepth == 24 || poGDS->sHeader.nBitDepth == 32 )
         {
             GUInt32 nTileSize = nTileBytes / nBytesPerPixel;
 
-            if ( nTileSize > nBlockSize )
+            if( nTileSize > nBlockSize )
                 nTileSize = nBlockSize;
 
             for( GUInt32 i = 0; i < nTileSize; i++ )
@@ -360,16 +352,16 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             }
         }
 
-        else if ( poGDS->sHeader.nBitDepth == 16 )
+        else if( poGDS->sHeader.nBitDepth == 16 )
         {
             GUInt32 nTileSize = nTileBytes / nBytesPerPixel;
 
-            if ( nTileSize > nBlockSize )
+            if( nTileSize > nBlockSize )
                 nTileSize = nBlockSize;
 
             for( GUInt32 i = 0; i < nTileSize; i++ )
             {
-                switch ( nBand )
+                switch( nBand )
                 {
                     case 1:
                         reinterpret_cast<GByte *>( pImage )[i] =
@@ -391,8 +383,7 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                 }
             }
         }
-
-        else if ( poGDS->sHeader.nBitDepth == 4 )
+        else if( poGDS->sHeader.nBitDepth == 4 )
         {
             GByte *pabyTemp = pabyTile;
 
@@ -408,15 +399,14 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             for( GUInt32 i = 0; i < nBlockSize; i++ )
             {
                 // Most significant part of the byte represents leftmost pixel
-                if ( i & 0x01 )
+                if( i & 0x01 )
                     reinterpret_cast<GByte *>( pImage )[i] = *pabyTemp++ & 0x0F;
                 else
                     reinterpret_cast<GByte *>( pImage )[i]
                         = (*pabyTemp & 0xF0) >> 4;
             }
         }
-
-        else if ( poGDS->sHeader.nBitDepth == 1 )
+        else if( poGDS->sHeader.nBitDepth == 1 )
         {
             GByte *pabyTemp = pabyTile;
 
@@ -431,31 +421,39 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 
             for( GUInt32 i = 0; i < nBlockSize; i++ )
             {
-                switch ( i & 0x7 )
+                switch( i & 0x7 )
                 {
                     case 0:
-                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x80) >> 7;
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            (*pabyTemp & 0x80) >> 7;
                         break;
                     case 1:
-                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x40) >> 6;
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            (*pabyTemp & 0x40) >> 6;
                         break;
                     case 2:
-                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x20) >> 5;
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            (*pabyTemp & 0x20) >> 5;
                         break;
                     case 3:
-                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x10) >> 4;
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            (*pabyTemp & 0x10) >> 4;
                         break;
                     case 4:
-                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x08) >> 3;
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            (*pabyTemp & 0x08) >> 3;
                         break;
                     case 5:
-                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x04) >> 2;
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            (*pabyTemp & 0x04) >> 2;
                         break;
                     case 6:
-                        reinterpret_cast<GByte *>( pImage )[i] = (*pabyTemp & 0x02) >> 1;
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            (*pabyTemp & 0x02) >> 1;
                         break;
                     case 7:
-                        reinterpret_cast<GByte *>( pImage )[i] = *pabyTemp++ & 0x01;
+                        reinterpret_cast<GByte *>( pImage )[i] =
+                            *pabyTemp++ & 0x01;
                         break;
                     default:
                         break;
@@ -466,10 +464,10 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         CPLFree( pabyTile );
     }
 
-    if ( nLastTileWidth
-         && static_cast<GUInt32>( nBlockXOff ) == poGDS->nXTiles - 1 )
+    if( nLastTileWidth
+        && static_cast<GUInt32>( nBlockXOff ) == poGDS->nXTiles - 1 )
     {
-        for ( GUInt32 iRow = nCurBlockYSize - 1; iRow > 0; iRow-- )
+        for( GUInt32 iRow = nCurBlockYSize - 1; iRow > 0; iRow-- )
         {
             memmove( reinterpret_cast<GByte *>( pImage )
                      + nBlockXSize * iRow * nDataSize,
@@ -477,7 +475,6 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                      iRow * nLastTileWidth * nDataSize,
                      nLastTileWidth * nDataSize );
         }
-
     }
 
     return CE_None;
@@ -490,22 +487,21 @@ CPLErr RMFRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                    void * pImage )
 {
-    RMFDataset  *poGDS = reinterpret_cast<RMFDataset *>( poDS );
-    GUInt32     nTile = nBlockYOff * poGDS->nXTiles + nBlockXOff;
-    GUInt32     nTileBytes = nDataSize * poGDS->nBands;
-    GUInt32     iInPixel, iOutPixel, nCurBlockYSize;
-    GByte       *pabyTile;
-
-    CPLAssert( poGDS != NULL
+    CPLAssert( poDS != NULL
                && nBlockXOff >= 0
                && nBlockYOff >= 0
                && pImage != NULL );
 
-    vsi_l_offset nTileOffset = poGDS->GetFileOffset( poGDS->paiTiles[2 * nTile] );
+    RMFDataset *poGDS = reinterpret_cast<RMFDataset *>( poDS );
+    const GUInt32 nTile = nBlockYOff * poGDS->nXTiles + nBlockXOff;
+    GUInt32 nTileBytes = nDataSize * poGDS->nBands;
+
+    vsi_l_offset nTileOffset =
+        poGDS->GetFileOffset( poGDS->paiTiles[2 * nTile] );
 
-    if ( nTileOffset )
+    if( nTileOffset )
     {
-        if ( VSIFSeekL( poGDS->fp, nTileOffset, SEEK_SET ) < 0 )
+        if( VSIFSeekL( poGDS->fp, nTileOffset, SEEK_SET ) < 0 )
         {
             CPLError( CE_Failure, CPLE_FileIO,
                 "Can't seek to offset %ld in output file to write data.\n%s",
@@ -516,7 +512,7 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     }
     else
     {
-        if ( VSIFSeekL( poGDS->fp, 0, SEEK_END ) < 0 )
+        if( VSIFSeekL( poGDS->fp, 0, SEEK_END ) < 0 )
         {
             CPLError( CE_Failure, CPLE_FileIO,
                 "Can't seek to offset %ld in output file to write data.\n%s",
@@ -524,32 +520,35 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                       VSIStrerror( errno ) );
             return CE_Failure;
         }
-        vsi_l_offset    nNewTileOffset;
         nTileOffset = VSIFTellL( poGDS->fp );
-        poGDS->paiTiles[2 * nTile] = poGDS->GetRMFOffset( nTileOffset, &nNewTileOffset );
-        
+        vsi_l_offset nNewTileOffset = 0;
+        poGDS->paiTiles[2 * nTile] =
+            poGDS->GetRMFOffset( nTileOffset, &nNewTileOffset );
+
         if( nTileOffset != nNewTileOffset )
         {   //May be it is better to write some zeros here?
-            if ( VSIFSeekL( poGDS->fp, nNewTileOffset, SEEK_SET ) < 0 )
+            if( VSIFSeekL( poGDS->fp, nNewTileOffset, SEEK_SET ) < 0 )
             {
                 CPLError( CE_Failure, CPLE_FileIO,
-                    "Can't seek to offset %ld in output file to write data.\n%s",
+                          "Can't seek to offset %ld in output file to "
+                          "write data.\n%s",
                           static_cast<long>( nNewTileOffset ),
                           VSIStrerror( errno ) );
                 return CE_Failure;
             }
         }
         nTileOffset = nNewTileOffset;
-        poGDS->bHeaderDirty = TRUE;
+        poGDS->bHeaderDirty = true;
     }
 
-    if ( nLastTileWidth
+    if( nLastTileWidth
          && static_cast<GUInt32>( nBlockXOff ) == poGDS->nXTiles - 1 )
         nTileBytes *= nLastTileWidth;
     else
         nTileBytes *= nBlockXSize;
 
-    if ( nLastTileHeight
+    GUInt32 nCurBlockYSize = 0;
+    if( nLastTileHeight
          && static_cast<GUInt32>( nBlockYOff ) == poGDS->nYTiles - 1 )
         nCurBlockYSize = nLastTileHeight;
     else
@@ -557,8 +556,8 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 
     nTileBytes *= nCurBlockYSize;
 
-    pabyTile = reinterpret_cast<GByte *>( VSICalloc( nTileBytes, 1 ) );
-    if ( !pabyTile )
+    GByte *pabyTile = static_cast<GByte *>( VSICalloc( nTileBytes, 1 ) );
+    if( !pabyTile )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Can't allocate space for the tile block of size %lu.\n%s",
@@ -567,14 +566,12 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         return CE_Failure;
     }
 
-    if ( nLastTileWidth
-         && static_cast<GUInt32>( nBlockXOff ) == poGDS->nXTiles - 1 )
+    if( nLastTileWidth
+        && static_cast<GUInt32>( nBlockXOff ) == poGDS->nXTiles - 1 )
     {
-        GUInt32 iRow;
-
-        if ( poGDS->nBands == 1 )
+        if( poGDS->nBands == 1 )
         {
-            for ( iRow = 0; iRow < nCurBlockYSize; iRow++ )
+            for( GUInt32 iRow = 0; iRow < nCurBlockYSize; iRow++ )
             {
                 memcpy( pabyTile + iRow * nLastTileWidth * nDataSize,
                         reinterpret_cast<GByte *>( pImage )
@@ -583,15 +580,15 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
         }
         else
         {
-            if ( poGDS->paiTiles[2 * nTile + 1] )
+            if( poGDS->paiTiles[2 * nTile + 1] )
             {
                 VSIFReadL( pabyTile, 1, nTileBytes, poGDS->fp );
                 VSIFSeekL( poGDS->fp, nTileOffset, SEEK_SET );
             }
 
-            for ( iRow = 0; iRow < nCurBlockYSize; iRow++ )
+            for( GUInt32 iRow = 0; iRow < nCurBlockYSize; iRow++ )
             {
-                for ( iInPixel = 0, iOutPixel = nBytesPerPixel - nBand;
+                for( GUInt32 iInPixel = 0, iOutPixel = nBytesPerPixel - nBand;
                       iOutPixel < nLastTileWidth * nDataSize * poGDS->nBands;
                       iInPixel++, iOutPixel += poGDS->nBands )
                     (pabyTile + iRow * nLastTileWidth * nDataSize * poGDS->nBands)[iOutPixel] =
@@ -602,40 +599,40 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     }
     else
     {
-        if ( poGDS->nBands == 1 )
+        if( poGDS->nBands == 1 )
+        {
             memcpy( pabyTile, pImage, nTileBytes );
+        }
         else
         {
-            if ( poGDS->paiTiles[2 * nTile + 1] )
+            if( poGDS->paiTiles[2 * nTile + 1] )
             {
                 VSIFReadL( pabyTile, 1, nTileBytes, poGDS->fp );
                 VSIFSeekL( poGDS->fp, nTileOffset, SEEK_SET );
             }
 
-            for ( iInPixel = 0, iOutPixel = nBytesPerPixel - nBand;
+            for( GUInt32 iInPixel = 0, iOutPixel = nBytesPerPixel - nBand;
                   iOutPixel < nTileBytes;
                   iInPixel++, iOutPixel += poGDS->nBands )
-                pabyTile[iOutPixel] = reinterpret_cast<GByte *>( pImage )[iInPixel];
-
+                pabyTile[iOutPixel] =
+                    reinterpret_cast<GByte *>( pImage )[iInPixel];
         }
     }
 
 #ifdef CPL_MSB
     if ( poGDS->eRMFType == RMFT_MTW )
-    {;
-        if ( poGDS->sHeader.nBitDepth == 16 )
+    {
+        if( poGDS->sHeader.nBitDepth == 16 )
         {
             for( GUInt32 i = 0; i < nTileBytes; i += 2 )
                 CPL_SWAP16PTR( pabyTile + i );
         }
-
-        else if ( poGDS->sHeader.nBitDepth == 32 )
+        else if( poGDS->sHeader.nBitDepth == 32 )
         {
             for( GUInt32 i = 0; i < nTileBytes; i += 4 )
                 CPL_SWAP32PTR( pabyTile + i );
         }
-
-        else if ( poGDS->sHeader.nBitDepth == 64 )
+        else if( poGDS->sHeader.nBitDepth == 64 )
         {
             for( GUInt32 i = 0; i < nTileBytes; i += 8 )
                 CPL_SWAPDOUBLE( pabyTile + i );
@@ -643,7 +640,7 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     }
 #endif
 
-    if ( VSIFWriteL( pabyTile, 1, nTileBytes, poGDS->fp ) < nTileBytes )
+    if( VSIFWriteL( pabyTile, 1, nTileBytes, poGDS->fp ) < nTileBytes )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Can't write block with X offset %d and Y offset %d.\n%s",
@@ -655,7 +652,7 @@ CPLErr RMFRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
     poGDS->paiTiles[2 * nTile + 1] = nTileBytes;
     VSIFree( pabyTile );
 
-    poGDS->bHeaderDirty = TRUE;
+    poGDS->bHeaderDirty = true;
 
     return CE_None;
 }
@@ -669,7 +666,7 @@ double RMFRasterBand::GetNoDataValue( int *pbSuccess )
 {
     RMFDataset *poGDS = reinterpret_cast<RMFDataset *>( poDS );
 
-    if ( pbSuccess )
+    if( pbSuccess )
         *pbSuccess = TRUE;
 
     return poGDS->sHeader.dfNoData;
@@ -721,11 +718,11 @@ CPLErr RMFRasterBand::SetColorTable( GDALColorTable *poColorTable )
 {
     RMFDataset *poGDS = reinterpret_cast<RMFDataset *>( poDS );
 
-    if ( poColorTable )
+    if( poColorTable )
     {
-        if ( poGDS->eRMFType == RMFT_RSW && poGDS->nBands == 1 )
+        if( poGDS->eRMFType == RMFT_RSW && poGDS->nBands == 1 )
         {
-            if ( !poGDS->pabyColorTable )
+            if( !poGDS->pabyColorTable )
                 return CE_Failure;
 
             GDALColorEntry  oEntry;
@@ -738,7 +735,7 @@ CPLErr RMFRasterBand::SetColorTable( GDALColorTable *poColorTable )
                 poGDS->pabyColorTable[i * 4 + 3] = 0;
             }
 
-            poGDS->bHeaderDirty = TRUE;
+            poGDS->bHeaderDirty = true;
         }
         return CE_None;
     }
@@ -766,7 +763,7 @@ GDALColorInterp RMFRasterBand::GetColorInterpretation()
         return GCI_Undefined;
     }
 
-    if ( poGDS->eRMFType == RMFT_RSW )
+    if( poGDS->eRMFType == RMFT_RSW )
         return GCI_PaletteIndex;
 
     return GCI_Undefined;
@@ -792,8 +789,8 @@ RMFDataset::RMFDataset() :
     poColorTable(NULL),
     pszProjection(CPLStrdup( "" )),
     pszUnitType(CPLStrdup( RMF_UnitsEmpty )),
-    bBigEndian(FALSE),
-    bHeaderDirty(FALSE),
+    bBigEndian(false),
+    bHeaderDirty(false),
     pszFilename(NULL),
     fp(NULL),
     Decompress(NULL)
@@ -821,9 +818,9 @@ RMFDataset::~RMFDataset()
     CPLFree( pszProjection );
     CPLFree( pszUnitType );
     CPLFree( pabyColorTable );
-    if ( poColorTable != NULL )
+    if( poColorTable != NULL )
         delete poColorTable;
-    if ( fp )
+    if( fp )
         VSIFCloseL( fp );
 }
 
@@ -849,13 +846,13 @@ CPLErr RMFDataset::SetGeoTransform( double * padfTransform )
 {
     memcpy( adfGeoTransform, padfTransform, sizeof(double) * 6 );
     sHeader.dfPixelSize = adfGeoTransform[1];
-    if ( sHeader.dfPixelSize != 0.0 )
+    if( sHeader.dfPixelSize != 0.0 )
         sHeader.dfResolution = sHeader.dfScale / sHeader.dfPixelSize;
     sHeader.dfLLX = adfGeoTransform[0];
     sHeader.dfLLY = adfGeoTransform[3] - nRasterYSize * sHeader.dfPixelSize;
     sHeader.iGeorefFlag = 1;
 
-    bHeaderDirty = TRUE;
+    bHeaderDirty = true;
 
     return CE_None;
 }
@@ -879,11 +876,10 @@ const char *RMFDataset::GetProjectionRef()
 CPLErr RMFDataset::SetProjection( const char * pszNewProjection )
 
 {
-    if ( pszProjection )
-        CPLFree( pszProjection );
+    CPLFree( pszProjection );
     pszProjection = CPLStrdup( (pszNewProjection) ? pszNewProjection : "" );
 
-    bHeaderDirty = TRUE;
+    bHeaderDirty = true;
 
     return CE_None;
 }
@@ -902,10 +898,13 @@ CPLErr RMFDataset::WriteHeader()
         OGRSpatialReference oSRS;
         char *pszProj = pszProjection;
 
-        if ( oSRS.importFromWkt( &pszProj ) == OGRERR_NONE )
+        if( oSRS.importFromWkt( &pszProj ) == OGRERR_NONE )
         {
-            long iProjection, iDatum, iEllips, iZone;
-            double  adfPrjParams[7];
+            long iProjection = 0;
+            long iDatum = 0;
+            long iEllips = 0;
+            long iZone = 0;
+            double adfPrjParams[7] = {};
 
             oSRS.exportToPanorama( &iProjection, &iDatum, &iEllips, &iZone,
                                    adfPrjParams );
@@ -925,28 +924,26 @@ CPLErr RMFDataset::WriteHeader()
 do {                                                    \
     GInt32  iLong = CPL_LSBWORD32( value );             \
     memcpy( (ptr) + (offset), &iLong, 4 );              \
-} while(0);
+} while( false );
 
 #define RMF_WRITE_ULONG( ptr,value, offset )            \
 do {                                                    \
     GUInt32 iULong = CPL_LSBWORD32( value );            \
     memcpy( (ptr) + (offset), &iULong, 4 );             \
-} while(0);
+} while( false );
 
 #define RMF_WRITE_DOUBLE( ptr,value, offset )           \
 do {                                                    \
     double  dfDouble = (value);                         \
     CPL_LSBPTR64( &dfDouble );                          \
     memcpy( (ptr) + (offset), &dfDouble, 8 );           \
-} while(0);
+} while( false );
 
 /* -------------------------------------------------------------------- */
 /*  Write out the main header.                                          */
 /* -------------------------------------------------------------------- */
     {
-        GByte   abyHeader[RMF_HEADER_SIZE];
-
-        memset( abyHeader, 0, sizeof(abyHeader) );
+        GByte abyHeader[RMF_HEADER_SIZE] = {};
 
         memcpy( abyHeader, sHeader.bySignature, RMF_SIGNATURE_SIZE );
         RMF_WRITE_ULONG( abyHeader, sHeader.iVersion, 4 );
@@ -1009,7 +1006,7 @@ do {                                                    \
 /*  Write out the extended header.                                      */
 /* -------------------------------------------------------------------- */
 
-    if ( sHeader.nExtHdrOffset && sHeader.nExtHdrSize )
+    if( sHeader.nExtHdrOffset && sHeader.nExtHdrSize )
     {
         GByte *pabyExtHeader = reinterpret_cast<GByte *>(
             CPLCalloc( sHeader.nExtHdrSize, 1 ) );
@@ -1032,7 +1029,7 @@ do {                                                    \
 /*  Write out the color table.                                          */
 /* -------------------------------------------------------------------- */
 
-    if ( sHeader.nClrTblOffset && sHeader.nClrTblSize )
+    if( sHeader.nClrTblOffset && sHeader.nClrTblSize )
     {
         VSIFSeekL( fp, GetFileOffset( sHeader.nClrTblOffset ), SEEK_SET );
         VSIFWriteL( pabyColorTable, 1, sHeader.nClrTblSize, fp );
@@ -1047,11 +1044,11 @@ do {                                                    \
 #ifdef CPL_MSB
     GUInt32 *paiTilesSwapped = reinterpret_cast<GUInt32 *>(
         CPLMalloc( sHeader.nTileTblSize ) );
-    if ( !paiTilesSwapped )
+    if( !paiTilesSwapped )
         return CE_Failure;
 
     memcpy( paiTilesSwapped, paiTiles, sHeader.nTileTblSize );
-    for ( GUInt32 i = 0; i < sHeader.nTileTblSize / sizeof(GUInt32); i++ )
+    for( GUInt32 i = 0; i < sHeader.nTileTblSize / sizeof(GUInt32); i++ )
         CPL_SWAP32PTR( paiTilesSwapped + i );
     VSIFWriteL( paiTilesSwapped, 1, sHeader.nTileTblSize, fp );
 
@@ -1060,7 +1057,7 @@ do {                                                    \
     VSIFWriteL( paiTiles, 1, sHeader.nTileTblSize, fp );
 #endif
 
-    bHeaderDirty = FALSE;
+    bHeaderDirty = false;
 
     return CE_None;
 }
@@ -1074,17 +1071,17 @@ void RMFDataset::FlushCache()
 {
     GDALDataset::FlushCache();
 
-    if ( !bHeaderDirty )
+    if( !bHeaderDirty )
         return;
 
-    if ( eRMFType == RMFT_MTW )
+    if( eRMFType == RMFT_MTW )
     {
         GDALRasterBand *poBand = GetRasterBand(1);
 
-        if ( poBand )
+        if( poBand )
         {
             poBand->ComputeRasterMinMax( FALSE, sHeader.adfElevMinMax );
-            bHeaderDirty = TRUE;
+            bHeaderDirty = true;
         }
     }
     WriteHeader();
@@ -1101,7 +1098,8 @@ int RMFDataset::Identify( GDALOpenInfo *poOpenInfo )
         return FALSE;
 
     if( memcmp(poOpenInfo->pabyHeader, RMF_SigRSW, sizeof(RMF_SigRSW)) != 0
-        && memcmp(poOpenInfo->pabyHeader, RMF_SigRSW_BE, sizeof(RMF_SigRSW_BE)) != 0
+        && memcmp(poOpenInfo->pabyHeader, RMF_SigRSW_BE,
+                  sizeof(RMF_SigRSW_BE)) != 0
         && memcmp(poOpenInfo->pabyHeader, RMF_SigMTW, sizeof(RMF_SigMTW)) != 0 )
         return FALSE;
 
@@ -1114,7 +1112,7 @@ int RMFDataset::Identify( GDALOpenInfo *poOpenInfo )
 
 GDALDataset *RMFDataset::Open( GDALOpenInfo * poOpenInfo )
 {
-    if ( !Identify(poOpenInfo) )
+    if( !Identify(poOpenInfo) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -1126,7 +1124,8 @@ GDALDataset *RMFDataset::Open( GDALOpenInfo * poOpenInfo )
         poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     else
         poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
-    if ( !poDS->fp )
+
+    if( !poDS->fp )
     {
         delete poDS;
         return NULL;
@@ -1134,7 +1133,7 @@ GDALDataset *RMFDataset::Open( GDALOpenInfo * poOpenInfo )
 
 #define RMF_READ_SHORT(ptr, value, offset)                              \
 do {                                                                    \
-    if ( poDS->bBigEndian )                                             \
+    if( poDS->bBigEndian )                                              \
     {                                                                   \
         (value) = CPL_MSBWORD16(*(GInt16*)((ptr) + (offset)));          \
     }                                                                   \
@@ -1142,11 +1141,11 @@ do {                                                                    \
     {                                                                   \
         (value) = CPL_LSBWORD16(*(GInt16*)((ptr) + (offset)));          \
     }                                                                   \
-} while(0);
+} while( false );
 
 #define RMF_READ_ULONG(ptr, value, offset)                              \
 do {                                                                    \
-    if ( poDS->bBigEndian )                                             \
+    if( poDS->bBigEndian )                                              \
     {                                                                   \
         (value) = CPL_MSBWORD32(*(GUInt32*)((ptr) + (offset)));         \
     }                                                                   \
@@ -1154,11 +1153,11 @@ do {                                                                    \
     {                                                                   \
         (value) = CPL_LSBWORD32(*(GUInt32*)((ptr) + (offset)));         \
     }                                                                   \
-} while(0);
+} while( false );
 
 #define RMF_READ_LONG(ptr, value, offset)                               \
 do {                                                                    \
-    if ( poDS->bBigEndian )                                             \
+    if( poDS->bBigEndian )                                              \
     {                                                                   \
         (value) = CPL_MSBWORD32(*(GInt32*)((ptr) + (offset)));          \
     }                                                                   \
@@ -1166,12 +1165,12 @@ do {                                                                    \
     {                                                                   \
         (value) = CPL_LSBWORD32(*(GInt32*)((ptr) + (offset)));          \
     }                                                                   \
-} while(0);
+} while( false );
 
 #define RMF_READ_DOUBLE(ptr, value, offset)                             \
 do {                                                                    \
     (value) = *reinterpret_cast<double*>((ptr) + (offset));             \
-    if ( poDS->bBigEndian )                                             \
+    if( poDS->bBigEndian )                                              \
     {                                                                   \
         CPL_MSBPTR64(&(value));                                         \
     }                                                                   \
@@ -1179,31 +1178,36 @@ do {                                                                    \
     {                                                                   \
         CPL_LSBPTR64(&(value));                                         \
     }                                                                   \
-} while(0);
+} while( false );
 
 /* -------------------------------------------------------------------- */
 /*  Read the main header.                                               */
 /* -------------------------------------------------------------------- */
 
     {
-        GByte   abyHeader[RMF_HEADER_SIZE];
+        GByte abyHeader[RMF_HEADER_SIZE] = {};
 
         VSIFSeekL( poDS->fp, 0, SEEK_SET );
-        if( VSIFReadL( abyHeader, 1, sizeof(abyHeader), poDS->fp ) != sizeof(abyHeader) )
+        if( VSIFReadL( abyHeader, 1, sizeof(abyHeader),
+                       poDS->fp ) != sizeof(abyHeader) )
         {
             delete poDS;
             return NULL;
         }
 
-        if ( memcmp(abyHeader, RMF_SigMTW, sizeof(RMF_SigMTW)) == 0 )
+        if( memcmp(abyHeader, RMF_SigMTW, sizeof(RMF_SigMTW)) == 0 )
+        {
             poDS->eRMFType = RMFT_MTW;
-        else if ( memcmp(abyHeader, RMF_SigRSW_BE, sizeof(RMF_SigRSW_BE)) == 0 )
+        }
+        else if( memcmp(abyHeader, RMF_SigRSW_BE, sizeof(RMF_SigRSW_BE)) == 0 )
         {
             poDS->eRMFType = RMFT_RSW;
-            poDS->bBigEndian = TRUE;
+            poDS->bBigEndian = true;
         }
         else
+        {
             poDS->eRMFType = RMFT_RSW;
+        }
 
         memcpy( poDS->sHeader.bySignature, abyHeader, RMF_SIGNATURE_SIZE );
         RMF_READ_ULONG( abyHeader, poDS->sHeader.iVersion, 4 );
@@ -1266,18 +1270,19 @@ do {                                                                    \
 /*  Read the extended header.                                           */
 /* -------------------------------------------------------------------- */
 
-    if ( poDS->sHeader.nExtHdrOffset && poDS->sHeader.nExtHdrSize )
+    if( poDS->sHeader.nExtHdrOffset && poDS->sHeader.nExtHdrSize )
     {
         /* coverity[tainted_data] */
         GByte *pabyExtHeader = reinterpret_cast<GByte *>(
             VSICalloc( poDS->sHeader.nExtHdrSize, 1 ) );
-        if (pabyExtHeader == NULL)
+        if( pabyExtHeader == NULL )
         {
             delete poDS;
             return NULL;
         }
 
-        VSIFSeekL( poDS->fp, poDS->GetFileOffset( poDS->sHeader.nExtHdrOffset ), SEEK_SET );
+        VSIFSeekL( poDS->fp, poDS->GetFileOffset( poDS->sHeader.nExtHdrOffset ),
+                   SEEK_SET );
         VSIFReadL( pabyExtHeader, 1, poDS->sHeader.nExtHdrSize, poDS->fp );
 
         RMF_READ_LONG( pabyExtHeader, poDS->sExtHeader.nEllipsoid, 24 );
@@ -1315,18 +1320,19 @@ do {                                                                    \
     CPLDebug( "RMF", "Georeferencing: pixel size %f, LLX %f, LLY %f",
               poDS->sHeader.dfPixelSize,
               poDS->sHeader.dfLLX, poDS->sHeader.dfLLY );
-    if ( poDS->sHeader.nROIOffset && poDS->sHeader.nROISize )
+    if( poDS->sHeader.nROIOffset && poDS->sHeader.nROISize )
     {
-        GInt32 nValue;
+        GInt32 nValue = 0;
 
         CPLDebug( "RMF", "ROI coordinates:" );
         /* coverity[tainted_data] */
-        for ( GUInt32 i = 0; i < poDS->sHeader.nROISize; i += sizeof(nValue) )
+        for( GUInt32 i = 0; i < poDS->sHeader.nROISize; i += sizeof(nValue) )
         {
-            if( VSIFSeekL( poDS->fp, 
-                           poDS->GetFileOffset( poDS->sHeader.nROIOffset + i ), 
+            if( VSIFSeekL( poDS->fp,
+                           poDS->GetFileOffset( poDS->sHeader.nROIOffset + i ),
                            SEEK_SET ) != 0 ||
-                VSIFReadL( &nValue, 1, sizeof(nValue), poDS->fp ) != sizeof(nValue) )
+                VSIFReadL( &nValue, 1, sizeof(nValue),
+                           poDS->fp ) != sizeof(nValue) )
             {
                 delete poDS;
                 return NULL;
@@ -1340,9 +1346,9 @@ do {                                                                    \
 /* -------------------------------------------------------------------- */
 /*  Read array of blocks offsets/sizes.                                 */
 /* -------------------------------------------------------------------- */
-    if ( VSIFSeekL( poDS->fp, 
-                    poDS->GetFileOffset( poDS->sHeader.nTileTblOffset ), 
-                    SEEK_SET ) < 0)
+    if( VSIFSeekL( poDS->fp,
+                   poDS->GetFileOffset( poDS->sHeader.nTileTblOffset ),
+                   SEEK_SET ) < 0 )
     {
         delete poDS;
         return NULL;
@@ -1351,14 +1357,14 @@ do {                                                                    \
     /* coverity[tainted_data] */
     poDS->paiTiles = reinterpret_cast<GUInt32 *>(
         VSIMalloc( poDS->sHeader.nTileTblSize ) );
-    if ( !poDS->paiTiles )
+    if( !poDS->paiTiles )
     {
         delete poDS;
         return NULL;
     }
 
-    if ( VSIFReadL( poDS->paiTiles, 1, poDS->sHeader.nTileTblSize,
-                    poDS->fp ) < poDS->sHeader.nTileTblSize )
+    if( VSIFReadL( poDS->paiTiles, 1, poDS->sHeader.nTileTblSize,
+                   poDS->fp ) < poDS->sHeader.nTileTblSize )
     {
         CPLDebug( "RMF", "Can't read tiles offsets/sizes table." );
         delete poDS;
@@ -1366,15 +1372,19 @@ do {                                                                    \
     }
 
 #ifdef CPL_MSB
-    if ( !poDS->bBigEndian )
+    if( !poDS->bBigEndian )
     {
-        for ( GUInt32 i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i++ )
+        for( GUInt32 i = 0;
+             i < poDS->sHeader.nTileTblSize / sizeof(GUInt32);
+             i++ )
             CPL_SWAP32PTR( poDS->paiTiles + i );
     }
 #else
-    if ( poDS->bBigEndian )
+    if( poDS->bBigEndian )
     {
-        for ( GUInt32 i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i++ )
+        for( GUInt32 i = 0;
+             i < poDS->sHeader.nTileTblSize / sizeof(GUInt32);
+             i++ )
             CPL_SWAP32PTR( poDS->paiTiles + i );
     }
 #endif
@@ -1382,7 +1392,9 @@ do {                                                                    \
 #ifdef DEBUG
     CPLDebug( "RMF", "List of block offsets/sizes:" );
 
-    for ( GUInt32 i = 0; i < poDS->sHeader.nTileTblSize / sizeof(GUInt32); i += 2 )
+    for( GUInt32 i = 0;
+         i < poDS->sHeader.nTileTblSize / sizeof(GUInt32);
+         i += 2 )
     {
         CPLDebug( "RMF", "    %d / %d",
                   poDS->paiTiles[i], poDS->paiTiles[i + 1] );
@@ -1397,15 +1409,15 @@ do {                                                                    \
     poDS->nRasterXSize = poDS->sHeader.nWidth;
     poDS->nRasterYSize = poDS->sHeader.nHeight;
 
-    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
+    if( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) )
     {
         delete poDS;
         return NULL;
     }
 
-    if ( poDS->eRMFType == RMFT_RSW )
+    if( poDS->eRMFType == RMFT_RSW )
     {
-        switch ( poDS->sHeader.nBitDepth )
+        switch( poDS->sHeader.nBitDepth )
         {
             case 32:
             case 24:
@@ -1418,10 +1430,11 @@ do {                                                                    \
                 {
                     // Allocate memory for colour table and read it
                     poDS->nColorTableSize = 1 << poDS->sHeader.nBitDepth;
-                    if ( poDS->nColorTableSize * 4 > poDS->sHeader.nClrTblSize )
+                    if( poDS->nColorTableSize * 4 > poDS->sHeader.nClrTblSize )
                     {
                         CPLDebug( "RMF",
-                                  "Wrong color table size. Expected %d, got %d.",
+                                  "Wrong color table size. "
+                                  "Expected %d, got %d.",
                                   poDS->nColorTableSize * 4,
                                   poDS->sHeader.nClrTblSize );
                         delete poDS;
@@ -1430,37 +1443,39 @@ do {                                                                    \
                     /* coverity[tainted_data] */
                     poDS->pabyColorTable = reinterpret_cast<GByte *>(
                         VSIMalloc( poDS->sHeader.nClrTblSize ) );
-                    if (poDS->pabyColorTable == NULL)
+                    if( poDS->pabyColorTable == NULL )
                     {
                         CPLDebug( "RMF", "Can't allocate color table." );
                         delete poDS;
                         return NULL;
                     }
-                    if ( VSIFSeekL( poDS->fp, 
-                                    poDS->GetFileOffset( poDS->sHeader.nClrTblOffset ),
-                                    SEEK_SET ) < 0 )
+                    if( VSIFSeekL( poDS->fp,
+                                   poDS->GetFileOffset( poDS->sHeader.nClrTblOffset ),
+                                   SEEK_SET ) < 0 )
                     {
-                        CPLDebug( "RMF", "Can't seek to color table location." );
+                        CPLDebug( "RMF",
+                                  "Can't seek to color table location." );
                         delete poDS;
                         return NULL;
                     }
-                    if ( VSIFReadL( poDS->pabyColorTable, 1,
-                                    poDS->sHeader.nClrTblSize, poDS->fp )
-                         < poDS->sHeader.nClrTblSize )
+                    if( VSIFReadL( poDS->pabyColorTable, 1,
+                                   poDS->sHeader.nClrTblSize, poDS->fp )
+                        < poDS->sHeader.nClrTblSize )
                     {
                         CPLDebug( "RMF", "Can't read color table." );
                         delete poDS;
                         return NULL;
                     }
 
-                    GDALColorEntry oEntry;
                     poDS->poColorTable = new GDALColorTable();
                     for( GUInt32 i = 0; i < poDS->nColorTableSize; i++ )
                     {
-                        oEntry.c1 = poDS->pabyColorTable[i * 4];     // Red
-                        oEntry.c2 = poDS->pabyColorTable[i * 4 + 1]; // Green
-                        oEntry.c3 = poDS->pabyColorTable[i * 4 + 2]; // Blue
-                        oEntry.c4 = 255;                             // Alpha
+                        const GDALColorEntry oEntry = {
+                            poDS->pabyColorTable[i * 4],     // Red
+                            poDS->pabyColorTable[i * 4 + 1], // Green
+                            poDS->pabyColorTable[i * 4 + 2], // Blue
+                            255                              // Alpha
+                        };
 
                         poDS->poColorTable->SetColorEntry( i, &oEntry );
                     }
@@ -1475,26 +1490,26 @@ do {                                                                    \
     else
     {
         poDS->nBands = 1;
-        if ( poDS->sHeader.nBitDepth == 8 )
+        if( poDS->sHeader.nBitDepth == 8 )
             eType = GDT_Byte;
-        else if ( poDS->sHeader.nBitDepth == 16 )
+        else if( poDS->sHeader.nBitDepth == 16 )
             eType = GDT_Int16;
-        else if ( poDS->sHeader.nBitDepth == 32 )
+        else if( poDS->sHeader.nBitDepth == 32 )
             eType = GDT_Int32;
-        else if ( poDS->sHeader.nBitDepth == 64 )
+        else if( poDS->sHeader.nBitDepth == 64 )
             eType = GDT_Float64;
     }
 
-    if (poDS->sHeader.nTileWidth == 0 || poDS->sHeader.nTileWidth > INT_MAX ||
-        poDS->sHeader.nTileHeight == 0 || poDS->sHeader.nTileHeight > INT_MAX)
+    if( poDS->sHeader.nTileWidth == 0 || poDS->sHeader.nTileWidth > INT_MAX ||
+        poDS->sHeader.nTileHeight == 0 || poDS->sHeader.nTileHeight > INT_MAX )
     {
-        CPLDebug ("RMF", "Invalid tile dimension : %u x %u",
-                  poDS->sHeader.nTileWidth, poDS->sHeader.nTileHeight);
+        CPLDebug("RMF", "Invalid tile dimension : %u x %u",
+                 poDS->sHeader.nTileWidth, poDS->sHeader.nTileHeight);
         delete poDS;
         return NULL;
     }
 
-    const int nDataSize = GDALGetDataTypeSize( eType ) / 8;
+    const int nDataSize = GDALGetDataTypeSizeBytes( eType );
     const int nBlockXSize = static_cast<int>(poDS->sHeader.nTileWidth);
     const int nBlockYSize = static_cast<int>(poDS->sHeader.nTileHeight);
     if( nDataSize == 0 ||
@@ -1520,10 +1535,10 @@ do {                                                                    \
 /*  XXX: The DEM compression method seems to be only applicable         */
 /*  to Int32 data.                                                      */
 /* -------------------------------------------------------------------- */
-    if ( poDS->sHeader.iCompression == RMF_COMPRESSION_LZW )
+    if( poDS->sHeader.iCompression == RMF_COMPRESSION_LZW )
         poDS->Decompress = &LZWDecompress;
-    else if ( poDS->sHeader.iCompression == RMF_COMPRESSION_DEM
-              && eType == GDT_Int32 )
+    else if( poDS->sHeader.iCompression == RMF_COMPRESSION_DEM
+             && eType == GDT_Int32 )
         poDS->Decompress = &DEMDecompress;
     else    // No compression
         poDS->Decompress = NULL;
@@ -1546,23 +1561,24 @@ do {                                                                    \
          poDS->sHeader.dfLLY != 0.0) )
     {
         OGRSpatialReference oSRS;
-        GInt32  nProj =
+        GInt32 nProj =
             (poDS->sHeader.iProjection) ? poDS->sHeader.iProjection : 1;
-        double  padfPrjParams[8];
-
-        padfPrjParams[0] = poDS->sHeader.dfStdP1;
-        padfPrjParams[1] = poDS->sHeader.dfStdP2;
-        padfPrjParams[2] = poDS->sHeader.dfCenterLat;
-        padfPrjParams[3] = poDS->sHeader.dfCenterLong;
-        padfPrjParams[4] = 1.0;
-        padfPrjParams[5] = 0.0;
-        padfPrjParams[6] = 0.0;
+        double padfPrjParams[8] = {
+            poDS->sHeader.dfStdP1,
+            poDS->sHeader.dfStdP2,
+            poDS->sHeader.dfCenterLat,
+            poDS->sHeader.dfCenterLong,
+            1.0,
+            0.0,
+            0.0,
+            0.0
+          };
 
         // XXX: Compute zone number for Gauss-Kruger (Transverse Mercator)
         // projection if it is not specified.
-        if ( nProj == 1L && poDS->sHeader.dfCenterLong == 0.0 )
+        if( nProj == 1L && poDS->sHeader.dfCenterLong == 0.0 )
         {
-            if ( poDS->sExtHeader.nZone == 0 )
+            if( poDS->sExtHeader.nZone == 0 )
             {
                 double centerXCoord = poDS->sHeader.dfLLX +
                     (poDS->nRasterXSize * poDS->sHeader.dfPixelSize / 2.0);
@@ -1570,14 +1586,14 @@ do {                                                                    \
                     floor((centerXCoord - 500000.0 ) / 1000000.0);
             }
             else
+            {
                 padfPrjParams[7] = poDS->sExtHeader.nZone;
+            }
         }
-        else
-            padfPrjParams[7] = 0.0;
 
         oSRS.importFromPanorama( nProj, poDS->sExtHeader.nDatum,
                                  poDS->sExtHeader.nEllipsoid, padfPrjParams );
-        if ( poDS->pszProjection )
+        if( poDS->pszProjection )
             CPLFree( poDS->pszProjection );
         oSRS.exportToWkt( &poDS->pszProjection );
     }
@@ -1585,8 +1601,8 @@ do {                                                                    \
 /* -------------------------------------------------------------------- */
 /*  Set up georeferencing.                                              */
 /* -------------------------------------------------------------------- */
-    if ( (poDS->eRMFType == RMFT_RSW && poDS->sHeader.iGeorefFlag) ||
-         (poDS->eRMFType == RMFT_MTW && poDS->sHeader.dfPixelSize != 0.0) )
+    if( (poDS->eRMFType == RMFT_RSW && poDS->sHeader.iGeorefFlag) ||
+        (poDS->eRMFType == RMFT_MTW && poDS->sHeader.dfPixelSize != 0.0) )
     {
         poDS->adfGeoTransform[0] = poDS->sHeader.dfLLX;
         poDS->adfGeoTransform[3] = poDS->sHeader.dfLLY
@@ -1601,7 +1617,7 @@ do {                                                                    \
 /*  Set units.                                                          */
 /* -------------------------------------------------------------------- */
 
-    if ( poDS->eRMFType == RMFT_MTW )
+    if( poDS->eRMFType == RMFT_MTW )
     {
         CPLFree(poDS->pszUnitType);
         switch ( poDS->sHeader.iElevationUnit )
@@ -1628,19 +1644,19 @@ do {                                                                    \
 /*  Report some other dataset related information.                      */
 /* -------------------------------------------------------------------- */
 
-    if ( poDS->eRMFType == RMFT_MTW )
+    if( poDS->eRMFType == RMFT_MTW )
     {
-        char        szTemp[256];
+        char szTemp[256] = {};
 
-        snprintf( szTemp, sizeof(szTemp), "%g", poDS->sHeader.adfElevMinMax[0] );
+        snprintf(szTemp, sizeof(szTemp), "%g", poDS->sHeader.adfElevMinMax[0]);
         poDS->SetMetadataItem( "ELEVATION_MINIMUM", szTemp );
 
-        snprintf( szTemp, sizeof(szTemp), "%g", poDS->sHeader.adfElevMinMax[1] );
+        snprintf(szTemp, sizeof(szTemp), "%g", poDS->sHeader.adfElevMinMax[1]);
         poDS->SetMetadataItem( "ELEVATION_MAXIMUM", szTemp );
 
         poDS->SetMetadataItem( "ELEVATION_UNITS", poDS->pszUnitType );
 
-        snprintf( szTemp, sizeof(szTemp), "%d", poDS->sHeader.iElevationType );
+        snprintf(szTemp, sizeof(szTemp), "%d", poDS->sHeader.iElevationType);
         poDS->SetMetadataItem( "ELEVATION_TYPE", szTemp );
     }
 
@@ -1649,7 +1665,7 @@ do {                                                                    \
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1661,36 +1677,38 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
                                  GDALDataType eType, char **papszParmList )
 
 {
-    if ( nBands != 1 && nBands != 3 )
+    if( nBands != 1 && nBands != 3 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "RMF driver doesn't support %d bands. Must be 1 or 3.\n",
+                  "RMF driver doesn't support %d bands. Must be 1 or 3.",
                   nBands );
 
         return NULL;
     }
 
-    if ( nBands == 1
-         && eType != GDT_Byte
-         && eType != GDT_Int16
-         && eType != GDT_Int32
-         && eType != GDT_Float64 )
+    if( nBands == 1
+        && eType != GDT_Byte
+        && eType != GDT_Int16
+        && eType != GDT_Int32
+        && eType != GDT_Float64 )
     {
-         CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create RMF dataset with an illegal data type (%s),\n"
-              "only Byte, Int16, Int32 and Float64 types supported "
-              "by the format for single-band images.\n",
-              GDALGetDataTypeName(eType) );
+         CPLError(
+             CE_Failure, CPLE_AppDefined,
+             "Attempt to create RMF dataset with an illegal data type (%s), "
+             "only Byte, Int16, Int32 and Float64 types supported "
+             "by the format for single-band images.",
+             GDALGetDataTypeName(eType) );
 
         return NULL;
     }
 
-    if ( nBands == 3 && eType != GDT_Byte )
+    if( nBands == 3 && eType != GDT_Byte )
     {
-         CPLError( CE_Failure, CPLE_AppDefined,
-              "Attempt to create RMF dataset with an illegal data type (%s),\n"
-              "only Byte type supported by the format for three-band images.\n",
-              GDALGetDataTypeName(eType) );
+         CPLError(
+             CE_Failure, CPLE_AppDefined,
+             "Attempt to create RMF dataset with an illegal data type (%s), "
+             "only Byte type supported by the format for three-band images.",
+             GDALGetDataTypeName(eType) );
 
         return NULL;
     }
@@ -1703,7 +1721,7 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     poDS->fp = VSIFOpenL( pszFilename, "w+b" );
     if( poDS->fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, "Unable to create file %s.\n",
+        CPLError( CE_Failure, CPLE_OpenFailed, "Unable to create file %s.",
                   pszFilename );
         delete poDS;
         return NULL;
@@ -1719,18 +1737,18 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     GUInt32 nBlockYSize =
         ( nYSize < RMF_DEFAULT_BLOCKYSIZE ) ? nYSize : RMF_DEFAULT_BLOCKYSIZE;
 
-    if ( CSLFetchBoolean( papszParmList, "MTW", FALSE) )
+    if( CPLFetchBool( papszParmList, "MTW", false) )
         poDS->eRMFType = RMFT_MTW;
     else
         poDS->eRMFType = RMFT_RSW;
-    if ( poDS->eRMFType == RMFT_MTW )
+    if( poDS->eRMFType == RMFT_MTW )
         memcpy( poDS->sHeader.bySignature, RMF_SigMTW, RMF_SIGNATURE_SIZE );
     else
         memcpy( poDS->sHeader.bySignature, RMF_SigRSW, RMF_SIGNATURE_SIZE );
-        
+
     const char *pszRMFHUGE = CSLFetchNameValue(papszParmList, "RMFHUGE");
-    GUInt32     iVersion = RMF_VERSION;
-    
+    GUInt32 iVersion = RMF_VERSION;
+
     if( pszRMFHUGE == NULL )
         pszRMFHUGE = "NO";// Keep old behavior by default
 
@@ -1744,10 +1762,11 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     }
     else if( EQUAL(pszRMFHUGE,"IF_SAFER") )
     {
-        double  dfImageSize = ((double)nXSize) *
-                              ((double)nYSize) *
-                              ((double)nBands) *
-                              ((double)(GDALGetDataTypeSize(eType)/8));
+        const double dfImageSize =
+            static_cast<double>(nXSize) *
+            static_cast<double>(nYSize) *
+            static_cast<double>(nBands) *
+            static_cast<double>(GDALGetDataTypeSizeBytes(eType));
         if( dfImageSize > 3.0*1024.0*1024.0*1024.0 )
         {
             iVersion = RMF_VERSION_HUGE;
@@ -1757,27 +1776,27 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
             iVersion = RMF_VERSION;
         }
     }
-    
+
     CPLDebug( "RMF", "Version %d", iVersion );
 
     poDS->sHeader.iVersion = iVersion;
     poDS->sHeader.nOvrOffset = 0x00;
     poDS->sHeader.iUserID = 0x00;
     memset( poDS->sHeader.byName, 0, sizeof(poDS->sHeader.byName) );
-    poDS->sHeader.nBitDepth = GDALGetDataTypeSize( eType ) * nBands;
+    poDS->sHeader.nBitDepth = GDALGetDataTypeSizeBits( eType ) * nBands;
     poDS->sHeader.nHeight = nYSize;
     poDS->sHeader.nWidth = nXSize;
 
     const char *pszValue = CSLFetchNameValue(papszParmList,"BLOCKXSIZE");
     if( pszValue != NULL )
         nBlockXSize = atoi( pszValue );
-    if( nBlockXSize <= 0 )
+    if( static_cast<int>(nBlockXSize) <= 0 )
         nBlockXSize = RMF_DEFAULT_BLOCKXSIZE;
 
     pszValue = CSLFetchNameValue(papszParmList,"BLOCKYSIZE");
     if( pszValue != NULL )
         nBlockYSize = atoi( pszValue );
-    if( nBlockYSize <= 0 )
+    if( static_cast<int>(nBlockYSize) <= 0 )
         nBlockYSize = RMF_DEFAULT_BLOCKXSIZE;
 
     poDS->sHeader.nTileWidth = nBlockXSize;
@@ -1788,10 +1807,10 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     poDS->nYTiles = poDS->sHeader.nYTiles =
         ( nYSize + poDS->sHeader.nTileHeight - 1 ) / poDS->sHeader.nTileHeight;
     poDS->sHeader.nLastTileHeight = nYSize % poDS->sHeader.nTileHeight;
-    if ( !poDS->sHeader.nLastTileHeight )
+    if( !poDS->sHeader.nLastTileHeight )
         poDS->sHeader.nLastTileHeight = poDS->sHeader.nTileHeight;
     poDS->sHeader.nLastTileWidth = nXSize % poDS->sHeader.nTileWidth;
-    if ( !poDS->sHeader.nLastTileWidth )
+    if( !poDS->sHeader.nLastTileWidth )
         poDS->sHeader.nLastTileWidth = poDS->sHeader.nTileWidth;
 
     poDS->sHeader.nROIOffset = 0x00;
@@ -1805,12 +1824,13 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
     nCurPtr += poDS->sHeader.nExtHdrSize;
 
     // Color table
-    if ( poDS->eRMFType == RMFT_RSW && nBands == 1 )
+    if( poDS->eRMFType == RMFT_RSW && nBands == 1 )
     {
-        if ( poDS->sHeader.nBitDepth > 8 )
+        if( poDS->sHeader.nBitDepth > 8 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Cannot create color table of RSW with nBitDepth = %d. Retry with MTW ?",
+                      "Cannot create color table of RSW with nBitDepth = %d. "
+                      "Retry with MTW ?",
                       poDS->sHeader.nBitDepth );
             delete poDS;
             return NULL;
@@ -1821,7 +1841,7 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
         poDS->sHeader.nClrTblSize = poDS->nColorTableSize * 4;
         poDS->pabyColorTable = reinterpret_cast<GByte *>(
             VSI_MALLOC_VERBOSE( poDS->sHeader.nClrTblSize ) );
-        if (poDS->pabyColorTable == NULL)
+        if( poDS->pabyColorTable == NULL )
         {
             delete poDS;
             return NULL;
@@ -1847,20 +1867,21 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
         poDS->sHeader.nXTiles * poDS->sHeader.nYTiles * 4 * 2;
     poDS->paiTiles = reinterpret_cast<GUInt32 *>(
         CPLCalloc( poDS->sHeader.nTileTblSize, 1 ) );
-    /*nCurPtr += poDS->sHeader.nTileTblSize;*/
-    const GUInt32 nTileSize = poDS->sHeader.nTileWidth * poDS->sHeader.nTileHeight
-        * GDALGetDataTypeSize( eType ) / 8;
+    // nCurPtr += poDS->sHeader.nTileTblSize;
+    const GUInt32 nTileSize =
+        poDS->sHeader.nTileWidth * poDS->sHeader.nTileHeight
+        * GDALGetDataTypeSizeBytes( eType );
     poDS->sHeader.nSize =
         poDS->paiTiles[poDS->sHeader.nTileTblSize / 4 - 2] + nTileSize;
 
     // Elevation units
-    if ( EQUAL(poDS->pszUnitType, RMF_UnitsM) )
+    if( EQUAL(poDS->pszUnitType, RMF_UnitsM) )
         poDS->sHeader.iElevationUnit = 0;
     else if ( EQUAL(poDS->pszUnitType, RMF_UnitsDM) )
         poDS->sHeader.iElevationUnit = 1;
     else if ( EQUAL(poDS->pszUnitType, RMF_UnitsCM) )
         poDS->sHeader.iElevationUnit = 2;
-    else if ( EQUAL(poDS->pszUnitType, RMF_UnitsMM) )
+    else if( EQUAL(poDS->pszUnitType, RMF_UnitsMM) )
         poDS->sHeader.iElevationUnit = 3;
     else
         poDS->sHeader.iElevationUnit = 0;
@@ -1906,37 +1927,36 @@ GDALDataset *RMFDataset::Create( const char * pszFilename,
 //GIS Panorama 11 was introduced new format for huge files (greater than 3 Gb)
 vsi_l_offset RMFDataset::GetFileOffset( GUInt32 iRMFOffset )
 {
-    if ( sHeader.iVersion >= RMF_VERSION_HUGE )
+    if( sHeader.iVersion >= RMF_VERSION_HUGE )
     {
         return ((vsi_l_offset)iRMFOffset) * RMF_HUGE_OFFSET_FACTOR;
     }
-    else
-    {
-        return (vsi_l_offset)iRMFOffset;
-    }
+
+    return (vsi_l_offset)iRMFOffset;
 }
 
-GUInt32 RMFDataset::GetRMFOffset( vsi_l_offset nFileOffset, vsi_l_offset* pnNewFileOffset )
+GUInt32 RMFDataset::GetRMFOffset( vsi_l_offset nFileOffset,
+                                  vsi_l_offset* pnNewFileOffset )
 {
-    if ( sHeader.iVersion >= RMF_VERSION_HUGE )
+    if( sHeader.iVersion >= RMF_VERSION_HUGE )
     {
         //Round offset to next RMF_HUGE_OFFSET_FACTOR
-        GUInt32 iRMFOffset = (GUInt32) ((nFileOffset + (RMF_HUGE_OFFSET_FACTOR-1) ) / RMF_HUGE_OFFSET_FACTOR );
-        if ( pnNewFileOffset != NULL )
+        const GUInt32 iRMFOffset = static_cast<GUInt32>(
+            (nFileOffset + (RMF_HUGE_OFFSET_FACTOR-1) ) /
+            RMF_HUGE_OFFSET_FACTOR );
+        if( pnNewFileOffset != NULL )
         {
             *pnNewFileOffset = GetFileOffset( iRMFOffset );
         }
         return iRMFOffset;
     }
-    else
+
+    if( pnNewFileOffset != NULL )
     {
-        if ( pnNewFileOffset != NULL )
-        {
-            *pnNewFileOffset = nFileOffset;
-        }
-        return (GUInt32)nFileOffset;
+        *pnNewFileOffset = nFileOffset;
     }
-} 
+    return static_cast<GUInt32>(nFileOffset);
+}
 
 /************************************************************************/
 /*                        GDALRegister_RMF()                            */
diff --git a/frmts/rmf/rmfdataset.h b/frmts/rmf/rmfdataset.h
index 3b4b4c5..7b58e28 100644
--- a/frmts/rmf/rmfdataset.h
+++ b/frmts/rmf/rmfdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: rmfdataset.h 33987 2016-04-17 14:56:07Z rouault $
+ * $Id: rmfdataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Private class declarations for the RMF classes used to read/write
@@ -147,8 +147,8 @@ class RMFDataset : public GDALDataset
 
     char            *pszUnitType;
 
-    int             bBigEndian;
-    int             bHeaderDirty;
+    bool            bBigEndian;
+    bool            bHeaderDirty;
 
     const char      *pszFilename;
     VSILFILE        *fp;
@@ -156,25 +156,25 @@ class RMFDataset : public GDALDataset
     CPLErr          WriteHeader();
     static int      LZWDecompress( const GByte*, GUInt32, GByte*, GUInt32 );
     static int      DEMDecompress( const GByte*, GUInt32, GByte*, GUInt32 );
-   int             (*Decompress)( const GByte*, GUInt32, GByte*, GUInt32 );
+    int             (*Decompress)( const GByte*, GUInt32, GByte*, GUInt32 );
 
   public:
                 RMFDataset();
-                ~RMFDataset();
+        virtual ~RMFDataset();
 
     static int          Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset  *Open( GDALOpenInfo * );
     static GDALDataset  *Create( const char *, int, int, int,
                                  GDALDataType, char ** );
-    virtual void        FlushCache( void );
+    virtual void        FlushCache() override;
+
+    virtual CPLErr      GetGeoTransform( double * padfTransform ) override;
+    virtual CPLErr      SetGeoTransform( double * ) override;
+    virtual const char  *GetProjectionRef() override;
+    virtual CPLErr      SetProjection( const char * ) override;
 
-    virtual CPLErr      GetGeoTransform( double * padfTransform );
-    virtual CPLErr      SetGeoTransform( double * );
-    virtual const char  *GetProjectionRef();
-    virtual CPLErr      SetProjection( const char * );
-    
     vsi_l_offset        GetFileOffset( GUInt32 iRMFOffset );
-    GUInt32             GetRMFOffset( vsi_l_offset iFileOffset, vsi_l_offset* piNewFileOffset );    
+    GUInt32             GetRMFOffset( vsi_l_offset iFileOffset, vsi_l_offset* piNewFileOffset );
 };
 
 /************************************************************************/
@@ -188,8 +188,10 @@ class RMFRasterBand : public GDALRasterBand
   private:
 
     GUInt32     nBytesPerPixel;
-    GUInt32     nBlockSize, nBlockBytes;
-    GUInt32     nLastTileWidth, nLastTileHeight;
+    GUInt32     nBlockSize;
+    GUInt32     nBlockBytes;
+    GUInt32     nLastTileWidth;
+    GUInt32     nLastTileHeight;
     GUInt32     nDataSize;
 
     CPLErr   ReadBuffer( GByte *, GUInt32 ) const;
@@ -197,14 +199,14 @@ class RMFRasterBand : public GDALRasterBand
   public:
 
                 RMFRasterBand( RMFDataset *, int, GDALDataType );
-                ~RMFRasterBand();
-
-    virtual CPLErr          IReadBlock( int, int, void * );
-    virtual CPLErr          IWriteBlock( int, int, void * );
-    virtual double          GetNoDataValue(int *pbSuccess = NULL);
-    virtual const char      *GetUnitType();
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual GDALColorTable  *GetColorTable();
-    virtual CPLErr          SetUnitType(const char *);
-    virtual CPLErr          SetColorTable( GDALColorTable * );
+        virtual ~RMFRasterBand();
+
+    virtual CPLErr          IReadBlock( int, int, void * ) override;
+    virtual CPLErr          IWriteBlock( int, int, void * ) override;
+    virtual double          GetNoDataValue(int *pbSuccess = NULL) override;
+    virtual const char      *GetUnitType() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual GDALColorTable  *GetColorTable() override;
+    virtual CPLErr          SetUnitType( const char * ) override;
+    virtual CPLErr          SetColorTable( GDALColorTable * ) override;
 };
diff --git a/frmts/rmf/rmfdem.cpp b/frmts/rmf/rmfdem.cpp
index 2515360..6e7efa1 100644
--- a/frmts/rmf/rmfdem.cpp
+++ b/frmts/rmf/rmfdem.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rmflzw.cpp 11865 2007-08-09 11:53:57Z warmerdam $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Implementation of the ad-hoc compression algorithm used in
@@ -32,6 +31,8 @@
 
 #include "rmfdataset.h"
 
+CPL_CVSID("$Id: rmfdem.cpp 35663 2016-10-09 16:35:15Z goatbar $");
+
 /*
  * The encoded data stream is a series of records.
  *
@@ -58,40 +59,42 @@
  */
 
 // Encoding types
-#define TYPE_OUT    0x00    // Value is out of range
-#define TYPE_ZERO   0x20    // Zero difference
-#define TYPE_INT4   0x40    // Difference is 4-bit wide
-#define TYPE_INT8   0x60    // Difference is 8-bit wide
-#define TYPE_INT12  0x80    // Difference is 12-bit wide
-#define TYPE_INT16  0xA0    // Difference is 16-bit wide
-#define TYPE_INT24  0xC0    // Difference is 24-bit wide
-#define TYPE_INT32  0xE0    // Difference is 32-bit wide
+enum  RmfTypes {
+    TYPE_OUT = 0x00,    // Value is out of range
+    TYPE_ZERO = 0x20,   // Zero difference
+    TYPE_INT4 = 0x40,   // Difference is 4-bit wide
+    TYPE_INT8 = 0x60,   // Difference is 8-bit wide
+    TYPE_INT12 = 0x80,  // Difference is 12-bit wide
+    TYPE_INT16 = 0xA0,  // Difference is 16-bit wide
+    TYPE_INT24 = 0xC0,  // Difference is 24-bit wide
+    TYPE_INT32 = 0xE0   // Difference is 32-bit wide
+};
 
 // Encoding ranges
-#define RANGE_INT4  0x00000007L    // 4-bit
-#define RANGE_INT12 0x000007FFL    // 12-bit
-#define RANGE_INT24 0x007FFFFFL    // 24-bit
+GInt32 RANGE_INT4 = 0x00000007L;    // 4-bit
+GInt32 RANGE_INT12 = 0x000007FFL;    // 12-bit
+GInt32 RANGE_INT24 = 0x007FFFFFL;    // 24-bit
 
 // Out of range codes
-#define OUT_INT4    ((GInt32)0xFFFFFFF8)
-#define OUT_INT8    ((GInt32)0xFFFFFF80)
-#define OUT_INT12   ((GInt32)0xFFFFF800)
-#define OUT_INT16   ((GInt32)0xFFFF8000)
-#define OUT_INT24   ((GInt32)0xFF800000)
-#define OUT_INT32   ((GInt32)0x80000000)
+GInt32 OUT_INT4 = 0xFFFFFFF8;
+GInt32 OUT_INT8 = 0xFFFFFF80;
+GInt32 OUT_INT12 = 0xFFFFF800;
+GInt32 OUT_INT16 = 0xFFFF8000;
+GInt32 OUT_INT24 = 0xFF800000;
+GInt32 OUT_INT32 = 0x80000000;
 
 // Inversion masks
-#define INV_INT4    0xFFFFFFF0L
-#define INV_INT12   0xFFFFF000L
-#define INV_INT24   0xFF000000L
-
+GInt32 INV_INT4 = 0xFFFFFFF0L;
+GInt32 INV_INT12 = 0xFFFFF000L;
+GInt32 INV_INT24 = 0xFF000000L;
 
 // Not sure which behaviour we wish for int32 overflow, so just do the
 // addition as uint32 to workaround -ftrapv
-static GInt32 AddInt32(GInt32& nTarget, GInt32 nVal)
+static GInt32 AddInt32( GInt32& nTarget, GInt32 nVal )
 {
-    GUInt32 nTargetU, nValU;
+    GUInt32 nTargetU = 0;
     memcpy(&nTargetU, &nTarget, 4);
+    GUInt32 nValU = 0;
     memcpy(&nValU, &nVal, 4);
     nTargetU += nValU;
     memcpy(&nTarget, &nTargetU, 4);
@@ -105,71 +108,67 @@ static GInt32 AddInt32(GInt32& nTarget, GInt32 nVal)
 int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                                GByte* pabyOut, GUInt32 nSizeOut )
 {
-    GUInt32 nCount;             // Number of encoded data elements to read
-    char* pabyTempIn;
-    GInt32* paiOut;
-    GInt32 nType;               // The encoding type
-    GInt32 iPrev = 0;           // The last data value decoded
-    GInt32 nCode;
-
-    if ( pabyIn == NULL ||
-         pabyOut == NULL ||
-         nSizeOut < nSizeIn ||
-         nSizeIn < 2 )
+    if( pabyIn == NULL ||
+        pabyOut == NULL ||
+        nSizeOut < nSizeIn ||
+        nSizeIn < 2 )
         return 0;
 
-    pabyTempIn  = (char*)pabyIn;
-    paiOut = (GInt32*)pabyOut;
+    GInt32 iPrev = 0;  // The last data value decoded.
+
+    const char* pabyTempIn  = reinterpret_cast<const char *>(pabyIn);
+    GInt32* paiOut = reinterpret_cast<GInt32 *>(pabyOut);
     nSizeOut /= sizeof(GInt32);
 
-    while ( nSizeIn > 0 )
+    while( nSizeIn > 0 )
     {
-        // Read number of codes in the record and encoding type
-        nCount = *pabyTempIn & 0x1F;
-        nType = *pabyTempIn++ & 0xE0;
+        // Read number of codes in the record and encoding type.
+        GUInt32 nCount = *pabyTempIn & 0x1F;
+        const GUInt32 nType = *pabyTempIn++ & 0xE0;  // The encoding type.
         nSizeIn--;
-        if ( nCount == 0 )
+        if( nCount == 0 )
         {
-            if ( nSizeIn == 0 )
+            if( nSizeIn == 0 )
                 break;
             nCount = 32 + *((unsigned char*)pabyTempIn++);
             nSizeIn--;
         }
 
-        switch (nType)
+        switch( nType )
         {
             case TYPE_ZERO:
-                if ( nSizeOut < nCount )
+                if( nSizeOut < nCount )
                     break;
                 nSizeOut -= nCount;
-                while ( nCount-- > 0 )
+                while( nCount-- > 0 )
                     *paiOut++ = iPrev;
                 break;
 
             case TYPE_OUT:
-                if ( nSizeOut < nCount )
+                if( nSizeOut < nCount )
                     break;
                 nSizeOut -= nCount;
-                while ( nCount-- > 0 )
+                while( nCount-- > 0 )
                     *paiOut++ = OUT_INT32;
                 break;
 
             case TYPE_INT4:
-                if ( nSizeIn < (nCount + 1) / 2 )
+                if( nSizeIn < (nCount + 1) / 2 )
                     break;
-                if ( nSizeOut < nCount )
+                if( nSizeOut < nCount )
                     break;
                 nSizeIn -= nCount / 2;
                 nSizeOut -= nCount;
-                while ( nCount-- > 0 )
+                while( nCount-- > 0 )
                 {
+    GInt32 nCode;
                     nCode = (*pabyTempIn) & 0x0F;
-                    if ( nCode > RANGE_INT4 )
+                    if( nCode > RANGE_INT4 )
                         nCode |= INV_INT4;
                     *paiOut++ = ( nCode == OUT_INT4 ) ?
                         OUT_INT32 : AddInt32(iPrev, nCode);
 
-                    if ( nCount-- == 0 )
+                    if( nCount-- == 0 )
                     {
                         if( nSizeIn )
                         {
@@ -180,7 +179,7 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                     }
 
                     nCode = ((*pabyTempIn++)>>4) & 0x0F;
-                    if ( nCode > RANGE_INT4 )
+                    if( nCode > RANGE_INT4 )
                         nCode |= INV_INT4;
                     *paiOut++ = ( nCode == OUT_INT4 ) ?
                         OUT_INT32 : AddInt32(iPrev, nCode);
@@ -188,36 +187,37 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                 break;
 
             case TYPE_INT8:
-                if ( nSizeIn < nCount )
+                if( nSizeIn < nCount )
                     break;
-                if ( nSizeOut < nCount )
+                if( nSizeOut < nCount )
                     break;
                 nSizeIn -= nCount;
                 nSizeOut -= nCount;
-                while ( nCount-- > 0 )
+                while( nCount-- > 0 )
                 {
+    GInt32 nCode;
                     *paiOut++ = ( (nCode = *pabyTempIn++) == OUT_INT8 ) ?
                         OUT_INT32 : AddInt32(iPrev, nCode);
                 }
                 break;
 
             case TYPE_INT12:
-                if ( nSizeIn < (3 * nCount + 1) / 2 )
+                if( nSizeIn < (3 * nCount + 1) / 2 )
                     break;
-                if ( nSizeOut < nCount )
+                if( nSizeOut < nCount )
                     break;
                 nSizeIn -= 3 * nCount / 2;
                 nSizeOut -= nCount;
 
-                while ( nCount-- > 0 )
+                while( nCount-- > 0 )
                 {
-                    nCode = *((GInt16*)pabyTempIn++) & 0x0FFF;
-                    if ( nCode > RANGE_INT12 )
+                    GInt32 nCode = *((GInt16*)pabyTempIn++) & 0x0FFF;
+                    if( nCode > RANGE_INT12 )
                         nCode |= INV_INT12;
                     *paiOut++ = ( nCode == OUT_INT12 ) ?
                         OUT_INT32 : AddInt32(iPrev, nCode);
 
-                    if ( nCount-- == 0 )
+                    if( nCount-- == 0 )
                     {
                         if( nSizeIn )
                         {
@@ -229,7 +229,7 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
 
                     nCode = ( (*(GInt16*)pabyTempIn) >> 4 ) & 0x0FFF;
                     pabyTempIn += 2;
-                    if ( nCode > RANGE_INT12 )
+                    if( nCode > RANGE_INT12 )
                         nCode |= INV_INT12;
                     *paiOut++ = ( nCode == OUT_INT12 ) ?
                         OUT_INT32 : AddInt32(iPrev, nCode);
@@ -237,16 +237,16 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                 break;
 
             case TYPE_INT16:
-                if ( nSizeIn < 2 * nCount )
+                if( nSizeIn < 2 * nCount )
                     break;
-                if ( nSizeOut < nCount )
+                if( nSizeOut < nCount )
                     break;
                 nSizeIn -= 2 * nCount;
                 nSizeOut -= nCount;
 
-                while ( nCount-- > 0 )
+                while( nCount-- > 0 )
                 {
-                    nCode = *((GInt16*)pabyTempIn);
+                    const GInt32 nCode = *((GInt16*)pabyTempIn);
                     pabyTempIn += 2;
                     *paiOut++ = ( nCode == OUT_INT16 ) ?
                         OUT_INT32 : AddInt32(iPrev, nCode);
@@ -254,18 +254,18 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                 break;
 
             case TYPE_INT24:
-                if ( nSizeIn < 3 * nCount )
+                if( nSizeIn < 3 * nCount )
                     break;
-                if ( nSizeOut < nCount )
+                if( nSizeOut < nCount )
                     break;
                 nSizeIn -= 3 * nCount;
                 nSizeOut -= nCount;
 
-                while ( nCount-- > 0 )
+                while( nCount-- > 0 )
                 {
-                    nCode =*((GInt32 *)pabyTempIn) & 0x00FFFFFF;
+                    GInt32 nCode = *((GInt32 *)pabyTempIn) & 0x00FFFFFF;
                     pabyTempIn += 3;
-                    if ( nCode > RANGE_INT24 )
+                    if( nCode > RANGE_INT24 )
                         nCode |= INV_INT24;
                     *paiOut++ = ( nCode == OUT_INT24 ) ?
                         OUT_INT32 : AddInt32(iPrev, nCode);
@@ -273,16 +273,16 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                 break;
 
             case TYPE_INT32:
-                if ( nSizeIn < 4 * nCount )
+                if( nSizeIn < 4 * nCount )
                     break;
-                if ( nSizeOut < nCount )
+                if( nSizeOut < nCount )
                     break;
                 nSizeIn -= 4 * nCount;
                 nSizeOut -= nCount;
 
-                while ( nCount-- > 0 )
+                while( nCount-- > 0 )
                 {
-                    nCode = *(GInt32 *)pabyTempIn;
+                    GInt32 nCode = *(GInt32 *)pabyTempIn;
                     pabyTempIn += 4;
                     *paiOut++ = ( nCode == OUT_INT32 ) ?
                         OUT_INT32 : AddInt32(iPrev, nCode);
@@ -293,4 +293,3 @@ int RMFDataset::DEMDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
 
   return static_cast<int>((GByte*)paiOut - pabyOut);
 }
-
diff --git a/frmts/rmf/rmflzw.cpp b/frmts/rmf/rmflzw.cpp
index 1721d36..2d33143 100644
--- a/frmts/rmf/rmflzw.cpp
+++ b/frmts/rmf/rmflzw.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rmflzw.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  Raster Matrix Format
  * Purpose:  Implementation of the LZW compression algorithm as used in
@@ -50,12 +49,14 @@
 
 #include "rmfdataset.h"
 
+CPL_CVSID("$Id: rmflzw.cpp 36404 2016-11-21 17:08:18Z rouault $");
+
 // Code marks that there is no predecessor in the string
-#define NO_PRED     0xFFFF
+static const GUInt32 NO_PRED = 0xFFFF;
 
 // We are using 12-bit codes in this particular implementation
-#define TABSIZE     4096U
-#define STACKSIZE   TABSIZE
+static const GUInt32 TABSIZE = 4096U;
+static const GUInt32 STACKSIZE = TABSIZE;
 
 /************************************************************************/
 /*                           LZWStringTab                               */
@@ -63,7 +64,7 @@
 
 typedef struct
 {
-    int     bUsed;
+    bool    bUsed;
     GUInt32 iNext;          // hi bit is 'used' flag
     GUInt32 iPredecessor;   // 12 bit code
     GByte   iFollower;
@@ -75,8 +76,6 @@ typedef struct
 
 static void LZWUpdateTab(LZWStringTab *poCodeTab, GUInt32 iPred, char bFoll)
 {
-    GUInt32 nNext;
-
 /* -------------------------------------------------------------------- */
 /* Hash uses the 'mid-square' algorithm. I.E. for a hash val of n bits  */
 /* hash = middle binary digits of (key * key).  Upon collision, hash    */
@@ -88,19 +87,18 @@ static void LZWUpdateTab(LZWStringTab *poCodeTab, GUInt32 iPred, char bFoll)
     nLocal = (nLocal*nLocal >> 6) & 0x0FFF;      // middle 12 bits of result
 
     // If string is not used
-    if (poCodeTab[nLocal].bUsed == FALSE)
-        nNext = nLocal;
-    else
+    GUInt32 nNext = nLocal;
+    if( poCodeTab[nLocal].bUsed )
     {
         // If collision has occurred
-        while ( (nNext = poCodeTab[nLocal].iNext) != 0 )
+        while( (nNext = poCodeTab[nLocal].iNext) != 0 )
             nLocal = nNext;
 
         // Search for free entry from nLocal + 101
         nNext = (nLocal + 101) & 0x0FFF;
-        while ( poCodeTab[nNext].bUsed )
+        while( poCodeTab[nNext].bUsed )
         {
-            if ( ++nNext >= TABSIZE )
+            if( ++nNext >= TABSIZE )
                 nNext = 0;
         }
 
@@ -108,7 +106,7 @@ static void LZWUpdateTab(LZWStringTab *poCodeTab, GUInt32 iPred, char bFoll)
         poCodeTab[nLocal].iNext = nNext;
     }
 
-    poCodeTab[nNext].bUsed = TRUE;
+    poCodeTab[nNext].bUsed = true;
     poCodeTab[nNext].iNext = 0;
     poCodeTab[nNext].iPredecessor = iPred;
     poCodeTab[nNext].iFollower = bFoll;
@@ -121,47 +119,41 @@ static void LZWUpdateTab(LZWStringTab *poCodeTab, GUInt32 iPred, char bFoll)
 int RMFDataset::LZWDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
                                GByte* pabyOut, GUInt32 nSizeOut )
 {
-    GUInt32         nCount = TABSIZE - 256;
-    GUInt32         iCode, iOldCode, iInCode;
-    GByte           iFinChar, bLastChar=FALSE;
-    LZWStringTab    *poCodeTab;
-    int             bBitsleft;
-
-    if ( pabyIn == NULL ||
-         pabyOut == NULL ||
-         nSizeOut < nSizeIn ||
-         nSizeIn < 2 )
+    if( pabyIn == NULL ||
+        pabyOut == NULL ||
+        nSizeOut < nSizeIn ||
+        nSizeIn < 2 )
         return 0;
 
     // Allocate space for the new table and pre-fill it
-    poCodeTab = (LZWStringTab *)CPLMalloc( TABSIZE * sizeof(LZWStringTab) );
-    if ( !poCodeTab )
+    LZWStringTab *poCodeTab =
+        (LZWStringTab *)CPLMalloc( TABSIZE * sizeof(LZWStringTab) );
+    if( !poCodeTab )
         return 0;
     memset( poCodeTab, 0, TABSIZE * sizeof(LZWStringTab) );
-    for ( iCode = 0; iCode < 256; iCode++ )
+    GUInt32 iCode = 0;
+    for( ; iCode < 256; iCode++ )
         LZWUpdateTab( poCodeTab, NO_PRED, (char)iCode );
 
     // The first code is always known
     iCode = (*pabyIn++ << 4) & 0xFF0; nSizeIn--;
     iCode += (*pabyIn >> 4) & 0x00F;
-    iOldCode = iCode;
-    bBitsleft = TRUE;
+    GUInt32 iOldCode = iCode;
+    bool bBitsleft = true;
+
+    GByte iFinChar = poCodeTab[iCode].iFollower; nSizeOut--;
+    *pabyOut++ = iFinChar;
 
-    *pabyOut++ = iFinChar = poCodeTab[iCode].iFollower; nSizeOut--;
+    GUInt32 nCount = TABSIZE - 256;
 
     // Decompress the input buffer
-    while ( nSizeIn > 0 )
+    while( nSizeIn > 0 )
     {
-        int     bNewCode;
-        GUInt32 nStackCount = 0;
-        GByte   abyStack[STACKSIZE];
-        GByte   *pabyTail = abyStack + STACKSIZE;
-
         // Fetch 12-bit code from input stream
-        if ( bBitsleft )
+        if( bBitsleft )
         {
             iCode = ((*pabyIn++ & 0x0F) << 8) & 0xF00; nSizeIn--;
-            if ( nSizeIn <= 0 )
+            if( nSizeIn == 0 )
                 break;
             iCode += *pabyIn++; nSizeIn--;
             bBitsleft = FALSE;
@@ -169,40 +161,46 @@ int RMFDataset::LZWDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
         else
         {
             iCode = (*pabyIn++ << 4) & 0xFF0; nSizeIn--;
-            if ( nSizeIn <= 0 )
+            if( nSizeIn == 0 )
                 break;
             iCode += (*pabyIn >> 4) & 0x00F;
             bBitsleft = TRUE;
         }
-        iInCode = iCode;
+
+        const GUInt32 iInCode = iCode;
+        GByte bLastChar = 0;  // TODO(schwehr): Why not nLastChar?
 
         // Do we have unknown code?
-        if ( poCodeTab[iCode].bUsed )
-            bNewCode = FALSE;
-        else
+        bool bNewCode = false;
+        if( !poCodeTab[iCode].bUsed )
         {
             iCode = iOldCode;
             bLastChar = iFinChar;
-            bNewCode = TRUE;
+            bNewCode = true;
         }
 
-        while ( poCodeTab[iCode].iPredecessor != NO_PRED )
+        GByte abyStack[STACKSIZE] = {};
+        GByte *pabyTail = abyStack + STACKSIZE;
+        GUInt32 nStackCount = 0;
+
+        while( poCodeTab[iCode].iPredecessor != NO_PRED )
         {
             // Stack overrun
-            if ( nStackCount >= STACKSIZE )
+            if( nStackCount >= STACKSIZE )
                 goto bad;
             // Put the decoded character into stack
             *(--pabyTail) = poCodeTab[iCode].iFollower; nStackCount++;
             iCode = poCodeTab[iCode].iPredecessor;
         }
 
-        if ( !nSizeOut )
+        if( !nSizeOut )
             goto bad;
         // The first character
-        *pabyOut++ = iFinChar = poCodeTab[iCode].iFollower; nSizeOut--;
+        iFinChar = poCodeTab[iCode].iFollower; nSizeOut--;
+        *pabyOut++ = iFinChar;
 
         // Output buffer overrun
-        if ( nStackCount > nSizeOut )
+        if( nStackCount > nSizeOut )
             goto bad;
 
         // Now copy the stack contents into output buffer. Our stack was
@@ -212,16 +210,17 @@ int RMFDataset::LZWDecompress( const GByte* pabyIn, GUInt32 nSizeIn,
         pabyOut += nStackCount;
 
         // If code isn't known
-        if ( bNewCode )
+        if( bNewCode )
         {
             // Output buffer overrun
-            if ( !nSizeOut )
+            if( !nSizeOut )
                 goto bad;
-            *pabyOut++ = iFinChar = bLastChar;  // the follower char of last
+            iFinChar = bLastChar;  // the follower char of last
+            *pabyOut++ = iFinChar;
             nSizeOut--;
         }
 
-        if ( nCount > 0 )
+        if( nCount > 0 )
         {
             nCount--;
             // Add code to the table
@@ -238,4 +237,3 @@ bad:
     CPLFree( poCodeTab );
     return 0;
 }
-
diff --git a/frmts/rs2/rs2dataset.cpp b/frmts/rs2/rs2dataset.cpp
index 0c418a3..647b553 100644
--- a/frmts/rs2/rs2dataset.cpp
+++ b/frmts/rs2/rs2dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rs2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Polarimetric Workstation
  * Purpose:  Radarsat 2 - XML Products (product.xml) driver
@@ -33,7 +32,7 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: rs2dataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: rs2dataset.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 typedef enum eCalibration_t {
     Sigma0 = 0,
@@ -54,7 +53,7 @@ static bool IsValidXMLFile( const char *pszPath, const char *pszLut)
 
     CPLFree(pszLutFile);
 
-    return psLut.get() != NULL;;
+    return psLut.get() != NULL;
 }
 
 /************************************************************************/
@@ -70,7 +69,7 @@ class RS2Dataset : public GDALPamDataset
     int           nGCPCount;
     GDAL_GCP      *pasGCPList;
     char          *pszGCPProjection;
-    char	**papszSubDatasets;
+    char        **papszSubDatasets;
     char          *pszProjection;
     double      adfGeoTransform[6];
     bool        bHaveGeoTransform;
@@ -78,22 +77,22 @@ class RS2Dataset : public GDALPamDataset
     char        **papszExtraFiles;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
   public:
             RS2Dataset();
-           ~RS2Dataset();
+    virtual ~RS2Dataset();
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char **GetMetadata( const char * pszDomain = "" );
-    virtual char **GetFileList(void);
+    virtual char      **GetMetadataDomainList() override;
+    virtual char **GetMetadata( const char * pszDomain = "" ) override;
+    virtual char **GetFileList(void) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
@@ -118,12 +117,11 @@ class RS2RasterBand : public GDALPamRasterBand
                                GDALDataset *poBandFile );
     virtual     ~RS2RasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
 
-
 /************************************************************************/
 /*                            RS2RasterBand                             */
 /************************************************************************/
@@ -256,7 +254,7 @@ CPLErr RS2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   GDT_Byte,
                                   1, NULL, 1, nBlockXSize, 0, NULL );
 
-    CPLAssert( FALSE );
+    CPLAssert( false );
     return CE_Failure;
 }
 
@@ -281,12 +279,13 @@ private:
 
     void ReadLUT();
 public:
-    RS2CalibRasterBand( RS2Dataset *poDataset, const char *pszPolarization,
+    RS2CalibRasterBand(
+        RS2Dataset *poDataset, const char *pszPolarization,
         GDALDataType eType, GDALDataset *poBandDataset, eCalibration eCalib,
-        const char *pszLUT);
+        const char *pszLUT );
     ~RS2CalibRasterBand();
 
-    CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage);
+    CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
 };
 
 /************************************************************************/
@@ -329,7 +328,9 @@ RS2CalibRasterBand::RS2CalibRasterBand(
     m_poBandDataset(poBandDataset),
     m_eType(eType),
     m_nfTable(NULL),
-    m_nTableSize(0)
+    m_nTableSize(0),
+    m_nfOffset(0),
+    m_pszLUTFile(VSIStrdup(pszLUT))
 {
     poDS = poDataset;
 
@@ -337,8 +338,6 @@ RS2CalibRasterBand::RS2CalibRasterBand(
         SetMetadataItem( "POLARIMETRIC_INTERP", pszPolarization );
     }
 
-    m_pszLUTFile = VSIStrdup(pszLUT);
-
     if (eType == GDT_CInt16)
         eDataType = GDT_CFloat32;
     else
@@ -399,9 +398,9 @@ CPLErr RS2CalibRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   pnImageTmp, nBlockXSize, nRequestYSize,
                                   GDT_Int16,
                                   2, NULL, 4, nBlockXSize * 4, 2, NULL );
-
         }
-        else {
+        else
+        {
             eErr =
                 m_poBandDataset->RasterIO( GF_Read,
                                       nBlockXOff * nBlockXSize,
@@ -489,13 +488,12 @@ CPLErr RS2CalibRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
         CPLFree(pnImageTmp);
     }
     else {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return CE_Failure;
     }
     return eErr;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                              RS2Dataset                              */
@@ -624,7 +622,6 @@ int RS2Dataset::Identify( GDALOpenInfo *poOpenInfo )
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -670,7 +667,7 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         //the GDALOpenInfo check would have failed because of the calibration string on the filename
         VSIStatBufL  sStat;
         if( VSIStatL( pszFilename, &sStat ) == 0 )
-        	poOpenInfo->bIsDirectory = VSI_ISDIR( sStat.st_mode );
+            poOpenInfo->bIsDirectory = VSI_ISDIR( sStat.st_mode );
     }
 
     CPLString osMDFilename;
@@ -812,14 +809,13 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     char *pszSigma0LUT = NULL;
 
     char *pszPath = CPLStrdup(CPLGetPath( osMDFilename ));
-    const int nFLen = static_cast<int>(strlen(osMDFilename));
+    const int nFLen = static_cast<int>(osMDFilename.size());
 
     CPLXMLNode *psNode = psImageAttributes->psChild;
     for( ;
          psNode != NULL;
          psNode = psNode->psNext )
     {
-        const char *pszBasename;
         if( psNode->eType != CXT_Element
             || !(EQUAL(psNode->pszValue,"fullResolutionImageData")
                  || EQUAL(psNode->pszValue,"lookupTable")) )
@@ -900,7 +896,7 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Fetch filename.                                                 */
 /* -------------------------------------------------------------------- */
-        pszBasename = CPLGetXMLValue( psNode, "", "" );
+        const char *pszBasename = CPLGetXMLValue( psNode, "", "" );
         if( *pszBasename == '\0' )
             continue;
 
@@ -942,7 +938,7 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
             poDS->SetBand( poDS->GetRasterCount() + 1, poBand );
         }
         else {
-            const char *pszLUT;
+            const char *pszLUT = NULL;
             switch (eCalib) {
               case Sigma0:
                 pszLUT = pszSigma0LUT;
@@ -1026,7 +1022,6 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         pszItem = CPLGetXMLValue( psSourceAttrs,
             "orbitAndAttitude.orbitInformation.orbitDataFile", "UNK" );
         poDS->SetMetadataItem( "ORBIT_DATA_FILE", pszItem );
-
     }
 
     CPLXMLNode *psSarProcessingInformation =
@@ -1065,11 +1060,8 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
         pszItem = CPLGetXMLValue( psSarProcessingInformation,
                                   "generalProcessingInformation.processingTime", "UNK" );
         poDS->SetMetadataItem( "PROCESSING_TIME", pszItem );
-
     }
 
-
-
 /*--------------------------------------------------------------------- */
 /*      Collect Map projection/Geotransform information, if present     */
 /* -------------------------------------------------------------------- */
@@ -1143,8 +1135,9 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
                           "corner coordinates inconsistent.");
             }
             else
+            {
                 poDS->bHaveGeoTransform = TRUE;
-
+            }
         }
     }
 
@@ -1332,6 +1325,45 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
     if (pszGammaLUT) CPLFree(pszGammaLUT);
 
 /* -------------------------------------------------------------------- */
+/*      Collect RPC.                                                   */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode *psRationalFunctions =
+        CPLGetXMLNode( psImageAttributes,
+                       "geographicInformation.rationalFunctions" );
+    if( psRationalFunctions != NULL ) {
+        char** papszRPC = NULL;
+        static const char* const apszXMLToGDALMapping[] =
+        {
+            "biasError", "ERR_BIAS",
+            "randomError", "ERR_RAND",
+            //"lineFitQuality", "????",
+            //"pixelFitQuality", "????",
+            "lineOffset", "LINE_OFF",
+            "pixelOffset", "SAMP_OFF",
+            "latitudeOffset", "LAT_OFF",
+            "longitudeOffset", "LONG_OFF",
+            "heightOffset", "HEIGHT_OFF",
+            "lineScale", "LINE_SCALE",
+            "pixelScale", "SAMP_SCALE",
+            "latitudeScale", "LAT_SCALE",
+            "longitudeScale", "LONG_SCALE",
+            "heightScale", "HEIGHT_SCALE",
+            "lineNumeratorCoefficients", "LINE_NUM_COEFF",
+            "lineDenominatorCoefficients", "LINE_DEN_COEFF",
+            "pixelNumeratorCoefficients", "SAMP_NUM_COEFF",
+            "pixelDenominatorCoefficients", "SAMP_DEN_COEFF",
+        };
+        for( size_t i = 0; i < CPL_ARRAYSIZE(apszXMLToGDALMapping); i+=2 )
+        {
+            const char* pszValue = CPLGetXMLValue(psRationalFunctions, apszXMLToGDALMapping[i], NULL);
+            if( pszValue )
+                papszRPC = CSLSetNameValue(papszRPC, apszXMLToGDALMapping[i+1], pszValue);
+        }
+        poDS->GDALDataset::SetMetadata(papszRPC, "RPC");
+        CSLDestroy(papszRPC);
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     CPLString osDescription;
@@ -1376,7 +1408,7 @@ GDALDataset *RS2Dataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1409,7 +1441,6 @@ const GDAL_GCP *RS2Dataset::GetGCPs()
     return pasGCPList;
 }
 
-
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
@@ -1417,7 +1448,7 @@ const GDAL_GCP *RS2Dataset::GetGCPs()
 const char *RS2Dataset::GetProjectionRef()
 
 {
-    return( pszProjection );
+    return pszProjection;
 }
 
 /************************************************************************/
@@ -1430,12 +1461,11 @@ CPLErr RS2Dataset::GetGeoTransform( double * padfTransform )
     memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 );
 
     if (bHaveGeoTransform)
-        return( CE_None );
+        return CE_None;
 
-    return( CE_Failure );
+    return CE_Failure;
 }
 
-
 /************************************************************************/
 /*                      GetMetadataDomainList()                         */
 /************************************************************************/
diff --git a/frmts/safe/frmt_safe.html b/frmts/safe/frmt_safe.html
index 8527408..ff9563a 100644
--- a/frmts/safe/frmt_safe.html
+++ b/frmts/safe/frmt_safe.html
@@ -38,7 +38,7 @@ polarizations), each one is available as a raster band - if the swath is the sam
 <li>Opening the Sentinel-1 product:
 
 <pre>
-$ gdalinfo S1A_IW_GRDH_1SDV_20150705T064241_20150705T064306_006672_008EA0_24EE.SAFE/manifest.safe 
+$ gdalinfo S1A_IW_GRDH_1SDV_20150705T064241_20150705T064306_006672_008EA0_24EE.SAFE/manifest.safe
 </pre>
 
 <pre>
@@ -48,7 +48,7 @@ Files: S1A_IW_GRDH_1SDV_20150705T064241_20150705T064306_006672_008EA0_24EE.SAFE/
        S1A_IW_GRDH_1SDV_20150705T064241_20150705T064306_006672_008EA0_24EE.SAFE/measurement/s1a-iw-grd-vv-20150705t064241-20150705t064306-006672-008ea0-001.tiff
 Size is 256, 167
 Coordinate System is `'
-GCP Projection = 
+GCP Projection =
 GEOGCS["WGS 84",
     DATUM["WGS_1984",
         SPHEROID["WGS 84",6378137,298.257223563,
@@ -121,7 +121,7 @@ Files: S1A_IW_GRDH_1SDV_20150705T064241_20150705T064306_006672_008EA0_24EE.SAFE/
        S1A_IW_GRDH_1SDV_20150705T064241_20150705T064306_006672_008EA0_24EE.SAFE/measurement/s1a-iw-grd-vh-20150705t064241-20150705t064306-006672-008ea0-002.tiff
 Size is 256, 167
 Coordinate System is `'
-GCP Projection = 
+GCP Projection =
 GEOGCS["WGS 84",
     DATUM["WGS_1984",
         SPHEROID["WGS 84",6378137,298.257223563,
@@ -174,7 +174,7 @@ Band 1 Block=256x16 Type=UInt16, ColorInterp=Undefined
 <li>A SLC product with 5 swaths in single pol (the first EW1/HH is selected by default):
 
 <pre>
-$ gdalinfo S1A_EW_SLC__1SSH_20150226T010823_20150226T010902_004787_005F2B_E43E.SAFE 
+$ gdalinfo S1A_EW_SLC__1SSH_20150226T010823_20150226T010902_004787_005F2B_E43E.SAFE
 </pre>
 
 <pre>
@@ -184,7 +184,7 @@ Files: S1A_EW_SLC__1SSH_20150226T010823_20150226T010902_004787_005F2B_E43E.SAFE/
        S1A_EW_SLC__1SSH_20150226T010823_20150226T010902_004787_005F2B_E43E.SAFE/measurement/s1a-ew1-slc-hh-20150226t010823-20150226t010859-004787-005f2b-001.tiff
 Size is 6871, 14016
 Coordinate System is `'
-GCP Projection = 
+GCP Projection =
 GEOGCS["WGS 84",
     DATUM["WGS_1984",
         SPHEROID["WGS 84",6378137,298.257223563,
@@ -199,7 +199,7 @@ GCP[  0]: Id=1, Info=
           (0,0) -> (-26.9158879633399,-76.5938687850829,250.211451298701)
 GCP[  1]: Id=2, Info=
 
-...supressed output...
+...suppressed output...
 
 GCP[272]: Id=273, Info=
           (6870,14015) -> (-35.4972634588715,-75.5331533717809,0)
diff --git a/frmts/safe/safedataset.cpp b/frmts/safe/safedataset.cpp
index 6b2f906..eea4a9f 100644
--- a/frmts/safe/safedataset.cpp
+++ b/frmts/safe/safedataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: safedataset.cpp 34273 2016-05-23 20:00:39Z rouault $
  *
  * Project:  Sentinel SAFE products
  * Purpose:  Sentinel Products (manifest.safe) driver
@@ -35,7 +34,7 @@
 #include <set>
 #include <map>
 
-CPL_CVSID("$Id: safedataset.cpp 34273 2016-05-23 20:00:39Z rouault $");
+CPL_CVSID("$Id: safedataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -58,31 +57,31 @@ class SAFEDataset : public GDALPamDataset
     char        **papszExtraFiles;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
     static CPLXMLNode * GetMetaDataObject(CPLXMLNode *, const char *);
 
     static CPLXMLNode * GetDataObject(CPLXMLNode *, const char *);
     static CPLXMLNode * GetDataObject(CPLXMLNode *, CPLXMLNode *, const char *);
-    
+
     static void AddSubDataset(SAFEDataset *poDS, int iDSNum, CPLString osName, CPLString osDesc);
 
   public:
             SAFEDataset();
-           ~SAFEDataset();
+    virtual ~SAFEDataset();
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 
 #ifdef notdef
     virtual char      **GetMetadataDomainList();
     virtual char **GetMetadata( const char * pszDomain = "" );
 #endif
-    virtual char **GetFileList(void);
+    virtual char **GetFileList(void) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
@@ -108,7 +107,7 @@ class SAFERasterBand : public GDALPamRasterBand
                                GDALDataset *poBandFile );
     virtual     ~SAFERasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
 };
@@ -118,14 +117,13 @@ class SAFERasterBand : public GDALPamRasterBand
 /************************************************************************/
 
 SAFERasterBand::SAFERasterBand( SAFEDataset *poDSIn,
-                              GDALDataType eDataTypeIn,
-                              const char *pszSwath,
-                              const char *pszPolarisation,
-                              GDALDataset *poBandFileIn )
-
+                                GDALDataType eDataTypeIn,
+                                const char *pszSwath,
+                                const char *pszPolarisation,
+                                GDALDataset *poBandFileIn ) :
+    poBandFile(poBandFileIn)
 {
     poDS = poDSIn;
-    poBandFile = poBandFileIn;
 
     GDALRasterBand *poSrcBand = poBandFile->GetRasterBand( 1 );
 
@@ -250,7 +248,7 @@ CPLErr SAFERasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                   GDT_Byte,
                                   1, NULL, 1, nBlockXSize, 0, NULL );
 
-    CPLAssert( FALSE );
+    CPLAssert( false );
     return CE_Failure;
 }
 
@@ -483,7 +481,6 @@ int SAFEDataset::Identify( GDALOpenInfo *poOpenInfo )
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -502,15 +499,14 @@ GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
 /*        Get subdataset information, if relevant                       */
 /* -------------------------------------------------------------------- */
     CPLString osMDFilename;
-    
+
     //Subdataset 1st level selection (ex: for swath selection)
     CPLString osSelectedSubDS1;
     //Subdataset 2nd level selection (ex: for polarisation selection)
     CPLString osSelectedSubDS2;
 
-    if (STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL1_DS:")) 
+    if (STARTS_WITH_CI(poOpenInfo->pszFilename, "SENTINEL1_DS:"))
     {
-      
       osMDFilename = poOpenInfo->pszFilename + strlen("SENTINEL1_DS:");
       const char* pszSelection1 = strrchr(osMDFilename.c_str(), ':');
       if (pszSelection1 == NULL || pszSelection1 == osMDFilename.c_str() )
@@ -520,7 +516,7 @@ GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
       }
       osMDFilename.resize( pszSelection1 - osMDFilename.c_str() );
       osSelectedSubDS1 = pszSelection1 + strlen(":");
-      
+
       const char* pszSelection2 = strchr(osSelectedSubDS1.c_str(), '_');
       if (pszSelection2 != NULL && pszSelection2 != pszSelection1 )
       {
@@ -532,12 +528,12 @@ GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
       VSIStatBufL  sStat;
       if( VSIStatL( osMDFilename.c_str(), &sStat ) == 0 )
           poOpenInfo->bIsDirectory = VSI_ISDIR( sStat.st_mode );
-      
-    } 
-    else {
+    }
+    else
+    {
       osMDFilename = poOpenInfo->pszFilename;
     }
-    
+
     if( poOpenInfo->bIsDirectory )
     {
         osMDFilename =
@@ -683,22 +679,26 @@ GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
                 //check object type
                 pszRepId = CPLGetXMLValue( psDO, "repID", "" );
 
-                if ( EQUAL(pszRepId, "s1Level1ProductSchema") ) {
+                if( EQUAL(pszRepId, "s1Level1ProductSchema") )
+                {
                     /* Get annotation filename */
                     pszAnnotation = CPLGetXMLValue(
                             psDO, "byteStream.fileLocation.href", "");
-                    if( *pszAnnotation == '\0' ) {
+                    if( *pszAnnotation == '\0' )
+                    {
                         continue;
                     }
-
-                } else if ( EQUAL(pszRepId, "s1Level1CalibrationSchema") ) {
+                }
+                else if( EQUAL(pszRepId, "s1Level1CalibrationSchema") )
+                {
                     pszCalibration = CPLGetXMLValue(
                             psDO, "byteStream.fileLocation.href", "");
                     if( *pszCalibration == '\0' ) {
                         continue;
                     }
-
-                } else {
+                }
+                else
+                {
                     continue;
                 }
             }
@@ -749,26 +749,26 @@ GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
                 psAnnotation, "=product.adsHeader.mode", "UNK" );
             CPLString osSwath = CPLGetXMLValue(
                 psAnnotation, "=product.adsHeader.swath", "UNK" );
-            
+
             oMapSwaths2Pols[osSwath].insert(osPolarisation);
-            
+
             if (osSelectedSubDS1.empty()) {
-              //if not subdataset was selected, 
-              //we open the first one we can find
+              // If not subdataset was selected,
+              // open the first one we can find.
               osSelectedSubDS1 = osSwath;
             }
-            
+
             if (!EQUAL(osSelectedSubDS1.c_str(), osSwath.c_str())) {
               //do not mix swath, otherwise it does not work for SLC products
               continue;
             }
-            
-            if (!osSelectedSubDS2.empty() 
+
+            if (!osSelectedSubDS2.empty()
               && (osSelectedSubDS2.find(osPolarisation)== std::string::npos)) {
-              //add only selected polarisations
+              // Add only selected polarisations.
               continue;
             }
-            
+
             poDS->SetMetadataItem("PRODUCT_TYPE", osProductType.c_str());
             poDS->SetMetadataItem("MISSION_ID", osMissionId.c_str());
             poDS->SetMetadataItem("MODE", osMode.c_str());
@@ -811,7 +811,7 @@ GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
                 "=product.imageAnnotation.imageInformation.azimuthPixelSpacing",
                 "UNK" );
             poDS->SetMetadataItem( "LINE_SPACING", pszLineSpacing );
-            
+
 /* -------------------------------------------------------------------- */
 /*      Form full filename (path of manifest.safe + measurement file).  */
 /* -------------------------------------------------------------------- */
@@ -833,7 +833,8 @@ GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
                 GDALClose( (GDALRasterBandH) poBandFile );
              }
             else {
-
+                poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles,
+                                                  osAnnotationFilePath );
                 poDS->papszExtraFiles = CSLAddString( poDS->papszExtraFiles,
                                                   pszFullname );
 
@@ -852,53 +853,49 @@ GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
             CPLFree( pszFullname );
         }
     }
-    
+
     //loop through all Swath/pols to add subdatasets
     int iSubDS = 1;
-    for (std::map<CPLString, std::set<CPLString> >::iterator iterSwath=oMapSwaths2Pols.begin(); 
-         iterSwath!=oMapSwaths2Pols.end(); ++iterSwath) 
+    for (std::map<CPLString, std::set<CPLString> >::iterator iterSwath=oMapSwaths2Pols.begin();
+         iterSwath!=oMapSwaths2Pols.end(); ++iterSwath)
     {
         CPLString osSubDS1 = iterSwath->first;
         CPLString osSubDS2;
-        
-        for (std::set<CPLString>::iterator iterPol=iterSwath->second.begin(); 
+
+        for (std::set<CPLString>::iterator iterPol=iterSwath->second.begin();
             iterPol!=iterSwath->second.end(); ++iterPol)
         {
             if (!osSubDS2.empty()) {
                 osSubDS2 += "+";
             }
             osSubDS2 += *iterPol;
-            
+
             //Create single band SubDataset
             SAFEDataset::AddSubDataset(poDS, iSubDS,
-                CPLSPrintf("SENTINEL1_DS:%s:%s_%s", 
-                    osPath.c_str(), 
-                    osSubDS1.c_str(), 
+                CPLSPrintf("SENTINEL1_DS:%s:%s_%s",
+                    osPath.c_str(),
+                    osSubDS1.c_str(),
                     (*iterPol).c_str()),
                 CPLSPrintf("Single band with %s swath and %s polarisation",
                     osSubDS1.c_str(),
                     (*iterPol).c_str())
             );
             iSubDS++;
-            
         }
-        
+
         if (iterSwath->second.size()>1) {
             //Create single band SubDataset with all polarisations
             SAFEDataset::AddSubDataset(poDS, iSubDS,
-                CPLSPrintf("SENTINEL1_DS:%s:%s", 
-                    osPath.c_str(), 
+                CPLSPrintf("SENTINEL1_DS:%s:%s",
+                    osPath.c_str(),
                     osSubDS1.c_str()),
                 CPLSPrintf("%s swath with all polarisations as bands",
                     osSubDS1.c_str())
             );
             iSubDS++;
         }
-        
     }
 
-
-    
     if (poDS->GetRasterCount() == 0) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Measurement bands not found." );
         delete poDS;
@@ -1103,10 +1100,9 @@ GDALDataset *SAFEDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
 
-    return( poDS );
+    return poDS;
 }
 
-
 /************************************************************************/
 /*                            AddSubDataset()                           */
 /************************************************************************/
@@ -1117,7 +1113,7 @@ void SAFEDataset::AddSubDataset(SAFEDataset *poDS, int iDSNum, CPLString osName,
         CPLSPrintf("SUBDATASET_%d_NAME", iDSNum),
         osName.c_str(),
         "SUBDATASETS");
-    
+
     poDS->GDALDataset::SetMetadataItem(
         CPLSPrintf("SUBDATASET_%d_DESC", iDSNum),
         osDesc.c_str(),
@@ -1152,14 +1148,13 @@ const GDAL_GCP *SAFEDataset::GetGCPs()
     return pasGCPList;
 }
 
-
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
 const char *SAFEDataset::GetProjectionRef()
 {
-    return( pszProjection );
+    return pszProjection;
 }
 
 /************************************************************************/
diff --git a/frmts/saga/sagadataset.cpp b/frmts/saga/sagadataset.cpp
index 0566ba8..97f6d88 100644
--- a/frmts/saga/sagadataset.cpp
+++ b/frmts/saga/sagadataset.cpp
@@ -1,9 +1,8 @@
 /******************************************************************************
- * $Id: sagadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  * Project:  SAGA GIS Binary Driver
  * Purpose:  Implements the SAGA GIS Binary Grid Format.
  * Author:   Volker Wichmann, wichmann at laserdata.at
- *	         (Based on gsbgdataset.cpp by Kevin Locke and Frank Warmerdam)
+ *   (Based on gsbgdataset.cpp by Kevin Locke and Frank Warmerdam)
  *
  ******************************************************************************
  * Copyright (c) 2009, Volker Wichmann <wichmann at laserdata.at>
@@ -38,21 +37,21 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: sagadataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: sagadataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 #ifndef INT_MAX
 # define INT_MAX 2147483647
 #endif /* INT_MAX */
 
 /* NODATA Values */
-//#define	SG_NODATA_GDT_Bit	0.0
+//#define SG_NODATA_GDT_Bit 0.0
 static const GByte SG_NODATA_GDT_Byte = 255;
-#define	SG_NODATA_GDT_UInt16	65535
-#define	SG_NODATA_GDT_Int16		-32767
-#define	SG_NODATA_GDT_UInt32	4294967295U
-#define	SG_NODATA_GDT_Int32		-2147483647
-#define	SG_NODATA_GDT_Float32	-99999.0
-#define	SG_NODATA_GDT_Float64	-99999.0
+#define SG_NODATA_GDT_UInt16    65535
+#define SG_NODATA_GDT_Int16     -32767
+#define SG_NODATA_GDT_UInt32    4294967295U
+#define SG_NODATA_GDT_Int32     -2147483647
+#define SG_NODATA_GDT_Float32   -99999.0
+#define SG_NODATA_GDT_Float64   -99999.0
 
 /************************************************************************/
 /* ==================================================================== */
@@ -76,7 +75,7 @@ class SAGADataset : public GDALPamDataset
 
   public:
         SAGADataset();
-        ~SAGADataset();
+    virtual ~SAGADataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
     static GDALDataset *Create( const char * pszFilename,
@@ -89,15 +88,14 @@ class SAGADataset : public GDALPamDataset
                                     GDALProgressFunc pfnProgress,
                                     void *pProgressData );
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual char **GetFileList();
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual char **GetFileList() override;
 
-    CPLErr GetGeoTransform( double *padfGeoTransform );
-    CPLErr SetGeoTransform( double *padfGeoTransform );
+    CPLErr GetGeoTransform( double *padfGeoTransform ) override;
+    CPLErr SetGeoTransform( double *padfGeoTransform ) override;
 };
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                            SAGARasterBand                            */
@@ -106,27 +104,27 @@ class SAGADataset : public GDALPamDataset
 
 class SAGARasterBand : public GDALPamRasterBand
 {
-    friend class	SAGADataset;
-
-    int				m_Cols;
-    int				m_Rows;
-    double			m_Xmin;
-    double			m_Ymin;
-    double			m_Cellsize;
-    double			m_NoData;
-    int				m_ByteOrder;
-    int				m_nBits;
-
-    void			SetDataType( GDALDataType eType );
+    friend class SAGADataset;
+
+    int             m_Cols;
+    int             m_Rows;
+    double          m_Xmin;
+    double          m_Ymin;
+    double          m_Cellsize;
+    double          m_NoData;
+    int             m_ByteOrder;
+    int             m_nBits;
+
+    void            SetDataType( GDALDataType eType );
     void            SwapBuffer(void* pImage);
 
 public:
     SAGARasterBand( SAGADataset *, int );
 
-    CPLErr		IReadBlock( int, int, void * );
-    CPLErr		IWriteBlock( int, int, void * );
+    CPLErr          IReadBlock( int, int, void * ) override;
+    CPLErr          IWriteBlock( int, int, void * ) override;
 
-    double		GetNoDataValue( int *pbSuccess = NULL );
+    double          GetNoDataValue( int *pbSuccess = NULL ) override;
 };
 
 /************************************************************************/
@@ -203,7 +201,6 @@ void SAGARasterBand::SwapBuffer(void* pImage)
             }
         }
     }
-
 }
 
 /************************************************************************/
@@ -211,11 +208,11 @@ void SAGARasterBand::SwapBuffer(void* pImage)
 /************************************************************************/
 
 CPLErr SAGARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-				   void * pImage )
+                                   void * pImage )
 
 {
     if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
-		return CE_Failure;
+        return CE_Failure;
 
     SAGADataset *poGDS = static_cast<SAGADataset *>( poDS );
     vsi_l_offset offset = static_cast<vsi_l_offset>( m_nBits / 8 )
@@ -245,18 +242,18 @@ CPLErr SAGARasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr SAGARasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-				    void *pImage )
+                                    void *pImage )
 
 {
     if( eAccess == GA_ReadOnly )
     {
-		CPLError( CE_Failure, CPLE_NoWriteAccess,
-			  "Unable to write block, dataset opened read only.\n" );
-		return CE_Failure;
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Unable to write block, dataset opened read only.\n" );
+        return CE_Failure;
     }
 
     if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 )
-		return CE_Failure;
+        return CE_Failure;
 
     const vsi_l_offset offset = static_cast<vsi_l_offset> (m_nBits / 8)
         * nRasterXSize * (nRasterYSize - nBlockYOff - 1);
@@ -302,11 +299,10 @@ double SAGARasterBand::GetNoDataValue( int * pbSuccess )
 
 /************************************************************************/
 /* ==================================================================== */
-/*                              SAGADataset	                            */
+/*                              SAGADataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
-
 SAGADataset::SAGADataset() :
     fp(NULL),
     pszProjection(CPLStrdup(""))
@@ -321,7 +317,6 @@ SAGADataset::~SAGADataset()
         VSIFCloseL( fp );
 }
 
-
 /************************************************************************/
 /*                            GetFileList()                             */
 /************************************************************************/
@@ -331,7 +326,6 @@ char** SAGADataset::GetFileList()
     const CPLString osPath = CPLGetPath( GetDescription() );
     const CPLString osName = CPLGetBasename( GetDescription() );
 
-
     // Main data file, etc.
     char **papszFileList = GDALPamDataset::GetFileList();
 
@@ -433,14 +427,19 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     /*      Is this file a SAGA header file?  Read a few lines of text      */
     /*      searching for something starting with nrows or ncols.           */
     /* -------------------------------------------------------------------- */
-    int				nRows = -1, nCols = -1;
-    double			dXmin = 0.0, dYmin = 0.0, dCellsize = 0.0, dNoData = 0.0, dZFactor = 0.0;
-    int				nLineCount			= 0;
-    char			szDataFormat[20]	= "DOUBLE";
-    char            szByteOrderBig[10]	= "FALSE";
-    char			szTopToBottom[10]	= "FALSE";
-
-    const char		*pszLine;
+    int nRows = -1;
+    int nCols = -1;
+    double dXmin = 0.0;
+    double dYmin = 0.0;
+    double dCellsize = 0.0;
+    double dNoData = 0.0;
+    double dZFactor = 0.0;
+    int nLineCount = 0;
+    char szDataFormat[20] = "DOUBLE";
+    char szByteOrderBig[10] = "FALSE";
+    char szTopToBottom[10] = "FALSE";
+
+    const char *pszLine = NULL;
     while( (pszLine = CPLReadLineL( fp )) != NULL )
     {
         nLineCount++;
@@ -485,7 +484,6 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
 
     VSIFCloseL( fp );
 
-
     /* -------------------------------------------------------------------- */
     /*      Did we get the required keywords?  If not we return with        */
     /*      this never having been considered to be a match. This isn't     */
@@ -518,13 +516,13 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     /* -------------------------------------------------------------------- */
     /*      Create a corresponding GDALDataset.                             */
     /* -------------------------------------------------------------------- */
-    SAGADataset	*poDS = new SAGADataset();
+    SAGADataset *poDS = new SAGADataset();
 
     poDS->eAccess = poOpenInfo->eAccess;
     if( poOpenInfo->eAccess == GA_ReadOnly )
-    	poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
+        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     else
-    	poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
+        poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" );
 
     if( poDS->fp == NULL )
     {
@@ -548,7 +546,6 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     else if( STARTS_WITH_CI(szByteOrderBig, "FALSE") )
         poBand->m_ByteOrder = 0;
 
-
     /* -------------------------------------------------------------------- */
     /*      Figure out the data type.                                       */
     /* -------------------------------------------------------------------- */
@@ -610,12 +607,12 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
     /* -------------------------------------------------------------------- */
     /*      Save band information                                           */
     /* -------------------------------------------------------------------- */
-    poBand->m_Xmin		= dXmin;
-    poBand->m_Ymin		= dYmin;
-    poBand->m_NoData	= dNoData;
-    poBand->m_Cellsize	= dCellsize;
-    poBand->m_Rows		= nRows;
-    poBand->m_Cols		= nCols;
+    poBand->m_Xmin = dXmin;
+    poBand->m_Ymin = dYmin;
+    poBand->m_NoData = dNoData;
+    poBand->m_Cellsize = dCellsize;
+    poBand->m_Rows = nRows;
+    poBand->m_Cols = nCols;
 
     poDS->SetBand( 1, poBand );
 
@@ -663,19 +660,19 @@ GDALDataset *SAGADataset::Open( GDALOpenInfo * poOpenInfo )
 CPLErr SAGADataset::GetGeoTransform( double *padfGeoTransform )
 {
     if( padfGeoTransform == NULL )
-		return CE_Failure;
+        return CE_Failure;
 
     SAGARasterBand *poGRB = static_cast<SAGARasterBand *>(GetRasterBand( 1 ));
 
     if( poGRB == NULL )
     {
-		padfGeoTransform[0] = 0;
-		padfGeoTransform[1] = 1;
-		padfGeoTransform[2] = 0;
-		padfGeoTransform[3] = 0;
-		padfGeoTransform[4] = 0;
-		padfGeoTransform[5] = 1;
-		return CE_Failure;
+        padfGeoTransform[0] = 0;
+        padfGeoTransform[1] = 1;
+        padfGeoTransform[2] = 0;
+        padfGeoTransform[3] = 0;
+        padfGeoTransform[4] = 0;
+        padfGeoTransform[5] = 1;
+        return CE_Failure;
     }
 
     /* check if we have a PAM GeoTransform stored */
@@ -684,14 +681,14 @@ CPLErr SAGADataset::GetGeoTransform( double *padfGeoTransform )
     CPLPopErrorHandler();
 
     if( eErr == CE_None )
-		return CE_None;
+        return CE_None;
 
-	padfGeoTransform[1] = poGRB->m_Cellsize;
-	padfGeoTransform[5] = poGRB->m_Cellsize * -1.0;
-	padfGeoTransform[0] = poGRB->m_Xmin - poGRB->m_Cellsize / 2;
-	padfGeoTransform[3] = poGRB->m_Ymin + (nRasterYSize - 1) * poGRB->m_Cellsize + poGRB->m_Cellsize / 2;
+    padfGeoTransform[1] = poGRB->m_Cellsize;
+    padfGeoTransform[5] = poGRB->m_Cellsize * -1.0;
+    padfGeoTransform[0] = poGRB->m_Xmin - poGRB->m_Cellsize / 2;
+    padfGeoTransform[3] = poGRB->m_Ymin + (nRasterYSize - 1) * poGRB->m_Cellsize + poGRB->m_Cellsize / 2;
 
-	/* tilt/rotation is not supported by SAGA grids */
+    /* tilt/rotation is not supported by SAGA grids */
     padfGeoTransform[4] = 0.0;
     padfGeoTransform[2] = 0.0;
 
@@ -761,7 +758,7 @@ CPLErr SAGADataset::WriteHeader( CPLString osHDRFilename, GDALDataType eType,
                                  double dfZFactor, bool bTopToBottom )
 
 {
-    VSILFILE	*fp = VSIFOpenL( osHDRFilename, "wt" );
+    VSILFILE *fp = VSIFOpenL( osHDRFilename, "wt" );
 
     if( fp == NULL )
     {
@@ -808,21 +805,19 @@ CPLErr SAGADataset::WriteHeader( CPLString osHDRFilename, GDALDataType eType,
     else
         VSIFPrintfL( fp, "TOPTOBOTTOM\t= FALSE\n" );
 
-
     VSIFCloseL( fp );
 
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
 
 GDALDataset *SAGADataset::Create( const char * pszFilename,
-				  int nXSize, int nYSize, int nBands,
-				  GDALDataType eType,
-				  char **papszParmList )
+                                  int nXSize, int nYSize, int nBands,
+                                  GDALDataType eType,
+                                  char **papszParmList )
 
 {
     if( nXSize <= 0 || nYSize <= 0 )
@@ -846,9 +841,9 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
         && eType != GDT_Float64 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-		  "SAGA Binary Grid only supports Byte, UInt16, Int16, "
-		  "UInt32, Int32, Float32 and Float64 datatypes.  Unable to "
-		  "create with type %s.\n", GDALGetDataTypeName( eType ) );
+                  "SAGA Binary Grid only supports Byte, UInt16, Int16, "
+                  "UInt32, Int32, Float32 and Float64 datatypes.  Unable to "
+                  "create with type %s.\n", GDALGetDataTypeName( eType ) );
 
         return NULL;
     }
@@ -872,8 +867,8 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
     }
     else
     {
-      switch (eType)	/* GDT_Byte, GDT_UInt16, GDT_Int16, GDT_UInt32  */
-      {				/* GDT_Int32, GDT_Float32, GDT_Float64 */
+      switch (eType)  /* GDT_Byte, GDT_UInt16, GDT_Int16, GDT_UInt32  */
+      {  /* GDT_Int32, GDT_Float32, GDT_Float64 */
         case (GDT_Byte):
         {
             dfNoDataVal = SG_NODATA_GDT_Byte;
@@ -929,7 +924,7 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
         return NULL;
     }
 
-    if (CSLFetchBoolean( papszParmList , "FILL_NODATA", TRUE ))
+    if( CPLFetchBool( papszParmList , "FILL_NODATA", true ) )
     {
         const int nDataTypeSize = GDALGetDataTypeSize(eType) / 8;
         GByte* pabyNoDataBuf = reinterpret_cast<GByte *>(
@@ -972,10 +967,10 @@ GDALDataset *SAGADataset::Create( const char * pszFilename,
 /************************************************************************/
 
 GDALDataset *SAGADataset::CreateCopy( const char *pszFilename,
-				      GDALDataset *poSrcDS,
-				      int bStrict, CPL_UNUSED char **papszOptions,
-				      GDALProgressFunc pfnProgress,
-				      void *pProgressData )
+                                      GDALDataset *poSrcDS,
+                                      int bStrict, CPL_UNUSED char **papszOptions,
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData )
 {
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
@@ -1021,7 +1016,7 @@ GDALDataset *SAGADataset::CreateCopy( const char *pszFilename,
         return NULL;
 
     /* -------------------------------------------------------------------- */
-    /*      Copy band data.	                                                */
+    /*      Copy band data.                                                 */
     /* -------------------------------------------------------------------- */
 
     CPLErr eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
diff --git a/frmts/sde/GNUmakefile b/frmts/sde/GNUmakefile
index 452569a..2840b91 100644
--- a/frmts/sde/GNUmakefile
+++ b/frmts/sde/GNUmakefile
@@ -1,13 +1,13 @@
-
-include ../../GDALmake.opt
-
-OBJ	=	sdedataset.o sdeerror.o sderasterband.o
-
-CPPFLAGS	:=	 $(SDE_INC) -DFRMT_sde $(CPPFLAGS)
-
-default:	$(OBJ:.o=.$(OBJ_EXT))
-
-clean:
-	rm -f *.o $(O_OBJ)
-
-install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+include ../../GDALmake.opt
+
+OBJ	=	sdedataset.o sdeerror.o sderasterband.o
+
+CPPFLAGS	:=	 $(SDE_INC) -DFRMT_sde $(CPPFLAGS)
+
+default:	$(OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/frmts/sde/gdal_sde.h b/frmts/sde/gdal_sde.h
index 20a8698..e5f9b0a 100644
--- a/frmts/sde/gdal_sde.h
+++ b/frmts/sde/gdal_sde.h
@@ -3,13 +3,6 @@
 
 #include "gdal_pam.h"
 
-
-CPL_CVSID("$Id: gdal_sde.h 32190 2015-12-16 13:50:27Z goatbar $");
-
-CPL_C_START
-void GDALRegister_SDE();
-CPL_C_END
-
 #include <sdetype.h>
 #include <sdeerno.h>
 #include <sderaster.h>
diff --git a/frmts/sde/sdedataset.cpp b/frmts/sde/sdedataset.cpp
index 255e80f..72390ec 100644
--- a/frmts/sde/sdedataset.cpp
+++ b/frmts/sde/sdedataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdedataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  ESRI ArcSDE Raster reader
  * Purpose:  Dataset implementation for ESRI ArcSDE Rasters
@@ -33,6 +32,8 @@
 #include "gdal_frmts.h"
 #include "sdedataset.h"
 
+CPL_CVSID("$Id: sdedataset.cpp 36455 2016-11-22 23:11:35Z rouault $");
+
 /************************************************************************/
 /*                          GetRastercount()                            */
 /************************************************************************/
@@ -63,7 +64,6 @@ int SDEDataset::GetRasterYSize( void )
     return nRasterYSize;
 }
 
-
 /************************************************************************/
 /*                          ComputeRasterInfo()                         */
 /************************************************************************/
@@ -191,7 +191,6 @@ CPLErr SDEDataset::ComputeRasterInfo() {
         return CE_Fatal;
     }
 
-
     for (int i=0; i < nBands; i++) {
         SetBand( i+1, new SDERasterBand( this, i+1, -1, &(paohSDERasterBands[i]) ));
     }
@@ -205,7 +204,6 @@ CPLErr SDEDataset::ComputeRasterInfo() {
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
@@ -249,13 +247,13 @@ const char *SDEDataset::GetProjectionRef()
     if (!hRasterColumn){
         CPLError ( CE_Failure, CPLE_AppDefined,
                    "Raster Column not defined");
-        return ("");
+        return "";
     }
 
     nSDEErr = SE_rascolinfo_get_coordref(hRasterColumn, coordref);
 
     if (nSDEErr == SE_NO_COORDREF) {
-        return ("");
+        return "";
     }
 
     if( nSDEErr != SE_SUCCESS )
@@ -271,9 +269,8 @@ const char *SDEDataset::GetProjectionRef()
     }
     SE_coordref_free(coordref);
 
-    OGRSpatialReference *poSRS;
     CPLDebug ("SDERASTER", "SDE says the coordinate system is: %s'", szWKT);
-    poSRS = new OGRSpatialReference(szWKT);
+    OGRSpatialReference *poSRS = new OGRSpatialReference(szWKT);
     poSRS->morphFromESRI();
 
     poSRS->exportToWkt(&pszWKT);
@@ -298,9 +295,7 @@ SDEDataset::SDEDataset(  )
     paohSDERasterBands  = NULL;
     hStream             = NULL;
     hRasterColumn       = NULL;
-    pszWKT		= NULL;
-    pszLayerName 	= NULL;
-    pszColumnName 	= NULL;
+    pszWKT              = NULL;
     nBands              = 0;
     nRasterXSize        = 0;
     nRasterYSize        = 0;
@@ -310,11 +305,8 @@ SDEDataset::SDEDataset(  )
     dfMaxX              = 0.0;
     dfMaxY              = 0.0;
     SE_rascolinfo_create(&hRasterColumn);
-
 }
 
-
-
 /************************************************************************/
 /*                            ~SDEDataset()                             */
 /************************************************************************/
@@ -348,7 +340,6 @@ SDEDataset::~SDEDataset()
         CPLFree(pszColumnName);
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -375,7 +366,6 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
                 poOpenInfo->pszFilename,
                 CSLCount( papszTokens ) );
 
-
     if( CSLCount( papszTokens ) < 5 || CSLCount( papszTokens ) > 7 )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -391,9 +381,7 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
 
-    SDEDataset *poDS;
-
-    poDS = new SDEDataset();
+    SDEDataset *poDS = new SDEDataset();
 /* -------------------------------------------------------------------- */
 /*      Try to establish connection.                                    */
 /* -------------------------------------------------------------------- */
@@ -413,7 +401,6 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Set unprotected concurrency policy, suitable for single         */
 /*      threaded access.                                                */
@@ -465,9 +452,6 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
             return NULL;
         }
         poDS->ComputeRasterInfo();
-
-
-
     } else {
 
         nSDEErr = SE_rastercolumn_get_info_list(poDS->hConnection,
@@ -504,7 +488,7 @@ GDALDataset *SDEDataset::Open( GDALOpenInfo * poOpenInfo )
     return NULL;
     }
     CSLDestroy( papszTokens);
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/sde/sdedataset.h b/frmts/sde/sdedataset.h
index 39de68b..603b015 100644
--- a/frmts/sde/sdedataset.h
+++ b/frmts/sde/sdedataset.h
@@ -3,7 +3,6 @@
 
 #include "gdal_sde.h"
 
-
 class SDEDataset : public GDALDataset
 {
     friend class SDERasterBand;
@@ -18,8 +17,7 @@ class SDEDataset : public GDALDataset
         SE_RASCOLINFO*      paohSDERasterColumns;
         SE_RASCOLINFO       hRasterColumn;
 
-
-        CPLErr              ComputeRasterInfo(void);
+        CPLErr              ComputeRasterInfo();
         SE_RASBANDINFO*     paohSDERasterBands;
 
     public:
@@ -37,12 +35,12 @@ class SDEDataset : public GDALDataset
         char                *pszLayerName;
         char                *pszColumnName;
 
-        virtual CPLErr  GetGeoTransform( double * padfTransform );
-        virtual int     GetRasterCount(void);
-        virtual int     GetRasterXSize(void);
-        virtual int     GetRasterYSize(void);
+        virtual CPLErr  GetGeoTransform( double * padfTransform ) override;
+        virtual int     GetRasterCount();
+        virtual int     GetRasterXSize();
+        virtual int     GetRasterYSize();
 
-        const char *GetProjectionRef();
+        const char *GetProjectionRef() override;
 };
 
 #endif
diff --git a/frmts/sde/sdeerror.cpp b/frmts/sde/sdeerror.cpp
index d55b898..17573c8 100644
--- a/frmts/sde/sdeerror.cpp
+++ b/frmts/sde/sdeerror.cpp
@@ -1,5 +1,8 @@
 
 #include "sdeerror.h"
+#include "cpl_port.h"
+
+CPL_CVSID("$Id: sdeerror.cpp 35929 2016-10-25 16:09:00Z goatbar $");
 
 /************************************************************************/
 /*                           IssueSDEError()                            */
@@ -49,8 +52,9 @@ void IssueSDEExtendedError ( int nErrorCode,
                    pszFunction, nErrorCode, szErrorMsg,
                    err.sde_error, err.ext_error,
                    err.err_msg1, err.err_msg2 );
-
-    } else {
+    }
+    else
+    {
         CPLError ( CE_Failure, CPLE_AppDefined,
            "%s: %d/%s",
            pszFunction, nErrorCode, szErrorMsg );
diff --git a/frmts/sde/sdeerror.h b/frmts/sde/sdeerror.h
index 900320d..64a3c00 100644
--- a/frmts/sde/sdeerror.h
+++ b/frmts/sde/sdeerror.h
@@ -1,7 +1,6 @@
 #ifndef SDEERROR_INCLUDED
 #define SDEERROR_INCLUDED
 
-
 #include "gdal_sde.h"
 
 void IssueSDEError( int nErrorCode,
diff --git a/frmts/sde/sderasterband.cpp b/frmts/sde/sderasterband.cpp
index 6ab6fb4..d7e57e3 100644
--- a/frmts/sde/sderasterband.cpp
+++ b/frmts/sde/sderasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdedataset.cpp 10804 2007-02-08 23:24:59Z hobu $
  *
  * Project:  ESRI ArcSDE Raster reader
  * Purpose:  Rasterband implementation for ESRI ArcSDE Rasters
@@ -32,6 +31,7 @@
 
 #include "sderasterband.h"
 
+CPL_CVSID("$Id: sderasterband.cpp 36337 2016-11-20 16:17:32Z rouault $");
 
 /************************************************************************/
 /*  SDERasterBand implements a GDAL RasterBand for ArcSDE.  This class  */
@@ -83,7 +83,6 @@
 /*                                                                      */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                           SDERasterBand()                            */
 /************************************************************************/
@@ -128,8 +127,6 @@ SDERasterBand::SDERasterBand(   SDEDataset *poDS,
     // nSDERasterType is set by GetRasterDataType
     this->dfDepth = MorphESRIRasterDepth(nSDERasterType);
     InitializeBand(this->nOverview);
-
-
 }
 
 /************************************************************************/
@@ -154,7 +151,6 @@ SDERasterBand::~SDERasterBand( void )
         delete poColorTable;
 }
 
-
 /************************************************************************/
 /*                             GetColorTable()                          */
 /************************************************************************/
@@ -169,7 +165,6 @@ GDALColorTable* SDERasterBand::GetColorTable(void)
     }
 }
 
-
 /************************************************************************/
 /*                             GetColorInterpretation()                 */
 /************************************************************************/
@@ -349,7 +344,6 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     // grab our Dataset to limit the casting we have to do.
     SDEDataset *poGDS = (SDEDataset *) poDS;
 
-
     // SDE manages the acquisition of raster data in "TileInfo" objects.
     // The hTile is the only heap-allocated object in this method, and
     // we should make sure to delete it at the end.  Once we get the
@@ -409,7 +403,6 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     int block_size = (nBlockXSize * bits_per_pixel + 7) / 8 * nBlockYSize;
     int bitmap_size = (nBlockXSize * nBlockYSize + 7) / 8;
 
-
     if (length == 0) {
         // ArcSDE says the block has no data in it.
         // Write 0's and be done with it
@@ -446,7 +439,6 @@ CPLErr SDERasterBand::IReadBlock( int nBlockXOff,
     return CE_None ;
 }
 
-
 /* ---------------------------------------------------------------------*/
 /* Private Methods                                                      */
 
@@ -460,18 +452,13 @@ void SDERasterBand::ComputeColorTable(void)
     SE_COLORMAP_DATA_TYPE eCMap_DataType;
 
     LONG nCMapEntries;
-    void * phSDEColormapData;
-
-    unsigned char* puszSDECMapData;
-    unsigned short* pushSDECMapData;
-
-    long nSDEErr;
-
-    nSDEErr = SE_rasbandinfo_get_colormap(  *poBand,
-                                            &eCMap_Type,
-                                            &eCMap_DataType,
-                                            &nCMapEntries,
-                                            &phSDEColormapData);
+    void *phSDEColormapData = NULL;
+    long nSDEErr =
+        SE_rasbandinfo_get_colormap( *poBand,
+                                     &eCMap_Type,
+                                     &eCMap_DataType,
+                                     &nCMapEntries,
+                                     &phSDEColormapData );
     if( nSDEErr != SE_SUCCESS )
     {
         IssueSDEError( nSDEErr, "SE_rasbandinfo_get_colormap" );
@@ -480,8 +467,8 @@ void SDERasterBand::ComputeColorTable(void)
     // Assign both the short and char pointers
     // to the void*, and we'll switch and read based
     // on the eCMap_DataType
-    puszSDECMapData = (unsigned char*) phSDEColormapData;
-    pushSDECMapData = (unsigned short*) phSDEColormapData;
+    unsigned char* puszSDECMapData = (unsigned char*) phSDEColormapData;
+    unsigned short* pushSDECMapData = (unsigned short*) phSDEColormapData;
 
     poColorTable = new GDALColorTable(GPI_RGB);
 
@@ -583,7 +570,6 @@ void SDERasterBand::ComputeColorTable(void)
     SE_rasbandinfo_free_colormap(phSDEColormapData);
 }
 
-
 /************************************************************************/
 /*                           InitializeBand()                           */
 /************************************************************************/
@@ -595,7 +581,6 @@ CPLErr SDERasterBand::InitializeBand( int nOverview )
 
     long nSDEErr;
 
-
     hConstraint = InitializeConstraint( NULL, NULL );
     if (!hConstraint)
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -635,7 +620,6 @@ CPLErr SDERasterBand::InitializeBand( int nOverview )
         return CE_Fatal;
     }
 
-
     CPLErr error = QueryRaster(hConstraint);
     if (error != CE_None)
         return error;
@@ -673,10 +657,11 @@ CPLErr SDERasterBand::InitializeBand( int nOverview )
     nBlockSize = nBlockXSize * nBlockYSize;
 
     // We're the base level
-    if (nOverview == -1) {
-        for (int i = 0; i<this->nOverviews; i++) {
+    if( nOverview == -1 )
+    {
+        for( int i = 0; i<this->nOverviews; i++ )
+        {
             papoOverviews[i]= new SDERasterBand(poGDS, nBand, i, poBand);
-
         }
     }
     return CE_None;
@@ -715,12 +700,12 @@ SE_RASCONSTRAINT& SDERasterBand::InitializeConstraint( long* nBlockXOff,
         {
             IssueSDEError( nSDEErr, "SE_rasconstraint_set_interleave" );
         }
-
     }
 
     if (nBlockXSize != -1 && nBlockYSize != -1) { // we aren't initialized yet
         if (nBlockXSize >= 0 && nBlockYSize >= 0) {
-            if (*nBlockXOff >= 0 &&  *nBlockYOff >= 0) {
+            if (nBlockXOff != NULL && nBlockYOff != NULL &&
+                *nBlockXOff >= 0 &&  *nBlockYOff >= 0) {
                 long nMinX, nMinY, nMaxX, nMaxY;
 
                 nMinX = *nBlockXOff;
@@ -782,7 +767,6 @@ SE_QUERYINFO& SDERasterBand::InitializeQuery( void )
     return hQuery;
 }
 
-
 /************************************************************************/
 /*                             MorphESRIRasterDepth()                   */
 /************************************************************************/
diff --git a/frmts/sde/sderasterband.h b/frmts/sde/sderasterband.h
index 21bc73e..6ee9a5e 100644
--- a/frmts/sde/sderasterband.h
+++ b/frmts/sde/sderasterband.h
@@ -17,11 +17,11 @@ class SDERasterBand : public GDALRasterBand
     private:
         const SE_RASBANDINFO* poBand;
 
-        double                  MorphESRIRasterDepth( int gtype );
-        GDALDataType            MorphESRIRasterType( int gtype );
-        void                    ComputeColorTable( void );
+        static double                  MorphESRIRasterDepth( int gtype );
+        static GDALDataType            MorphESRIRasterType( int gtype );
+        void                    ComputeColorTable();
         CPLErr                  InitializeBand( int nOverview );
-        SE_QUERYINFO&           InitializeQuery( void );
+        SE_QUERYINFO&           InitializeQuery();
         SE_RASCONSTRAINT&       InitializeConstraint (  long* nBlockXOff,
                                                         long* nBlockYOff);
         CPLErr                  QueryRaster( SE_RASCONSTRAINT& constraint );
@@ -42,22 +42,20 @@ class SDERasterBand : public GDALRasterBand
                        int nOverview,
                        const SE_RASBANDINFO* band);
 
-        ~SDERasterBand( void );
+        ~SDERasterBand();
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
                                   double *pdfMin, double *pdfMax,
-                                  double *pdfMean, double *pdfStdDev );
-    virtual GDALDataType GetRasterDataType(void);
-    virtual GDALColorTable *GetColorTable();
-    virtual GDALColorInterp GetColorInterpretation();
-
-
-    virtual double GetMinimum( int *pbSuccess );
-    virtual double GetMaximum( int *pbSuccess );
-    virtual int GetOverviewCount(void);
-    virtual GDALRasterBand* GetOverview(int nOverview);
-
+                                  double *pdfMean, double *pdfStdDev ) override;
+    virtual GDALDataType GetRasterDataType();
+    virtual GDALColorTable *GetColorTable() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
+
+    virtual double GetMinimum( int *pbSuccess ) override;
+    virtual double GetMaximum( int *pbSuccess ) override;
+    virtual int GetOverviewCount() override;
+    virtual GDALRasterBand* GetOverview(int nOverview) override;
 };
 
 #endif
diff --git a/frmts/sdts/Doxyfile b/frmts/sdts/Doxyfile
index d483160..58242a9 100644
--- a/frmts/sdts/Doxyfile
+++ b/frmts/sdts/Doxyfile
@@ -10,19 +10,19 @@
 #---------------------------------------------------------------------------
 
 # The PROJECT_NAME tag is a single word (or a sequence of word surrounded
-# by quotes) that should identify the project. 
+# by quotes) that should identify the project.
 
 PROJECT_NAME         =	SDTS_AL
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or 
+# This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER       =	
+PROJECT_NUMBER       =
 
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
 # where doxygen was started. If left blank the current directory will be used.
 
 OUTPUT_DIRECTORY     =
@@ -39,14 +39,14 @@ HTML_OUTPUT          =
 
 LATEX_OUTPUT          =
 
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard header.
 
 HTML_HEADER          =
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard footer.
 
 HTML_FOOTER          =
@@ -94,7 +94,7 @@ GENERATE_LATEX       = NO
 GENERATE_HTML        = YES
 
 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in 
+# include brief member descriptions after the members that are listed in
 # the file and class documentation (similar to JavaDoc).
 # Set to NO to disable this.
 
@@ -110,22 +110,22 @@ FULL_PATH_NAMES = NO
 # configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag is used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
 INPUT            =	. ../iso8211 ../../port
 
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
 # blank all files are included.
 
 FILE_PATTERNS    =	*.h *.cpp *.dox
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
 # the \include command).
 
 EXAMPLE_PATH     = . ../iso8211
@@ -137,16 +137,16 @@ EXAMPLE_PATH     = . ../iso8211
 RECURSIVE        = NO
 
 # The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program 
+# invoke to filter for each input file. Doxygen will invoke the filter program
 # by executing (via popen()) the command <filter> <input-file>, where <filter>
 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an
 # input file. Doxygen will then use the output that the filter program writes
 # to standard output.
 
-INPUT_FILTER     = 
+INPUT_FILTER     =
 
 #---------------------------------------------------------------------------
-# Configuration options related to the preprocessor 
+# Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
 # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
@@ -156,7 +156,7 @@ INPUT_FILTER     =
 ENABLE_PREPROCESSING = YES
 
 # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional 
+# names in the source code. If set to NO (the default) only conditional
 # compilation will be performed.
 
 MACRO_EXPANSION = NO
@@ -187,10 +187,10 @@ PREDEFINED =
 EXPAND_ONLY_PREDEF = NO
 
 #---------------------------------------------------------------------------
-# Configuration options related to external references 
+# Configuration options related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES tag can be used to specify one or more tagfiles. 
+# The TAGFILES tag can be used to specify one or more tagfiles.
 
 TAGFILES         =
 
@@ -211,10 +211,10 @@ ALLEXTERNALS     = NO
 PERL_PATH        = /usr/local/bin/perl
 
 #---------------------------------------------------------------------------
-# Configuration options related to the search engine 
+# Configuration options related to the search engine
 #---------------------------------------------------------------------------
 
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# The SEARCHENGINE tag specifies whether or not a search engine should be
 # used. If set to NO the values of all tags below this one will be ignored.
 
 SEARCHENGINE     = NO
@@ -226,13 +226,13 @@ SEARCHENGINE     = NO
 CGI_NAME         = search.cgi
 
 # The CGI_URL tag should be the absolute URL to the directory where the
-# cgi binaries are located. See the documentation of your http daemon for 
+# cgi binaries are located. See the documentation of your http daemon for
 # details.
 
 CGI_URL          =
 
 # The DOC_URL tag should be the absolute URL to the directory where the
-# documentation is located. If left blank the absolute path to the 
+# documentation is located. If left blank the absolute path to the
 # documentation, with file:// prepended to it, will be used.
 
 DOC_URL          =
@@ -248,7 +248,7 @@ DOC_ABSPATH      =
 
 BIN_ABSPATH      = /usr/local/bin/
 
-# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
 # documentation generated for other projects. This allows doxysearch to search
 # the documentation for these projects as well.
 
diff --git a/frmts/sdts/sdts2shp.cpp b/frmts/sdts/sdts2shp.cpp
index 955b4a8..8e88d9f 100644
--- a/frmts/sdts/sdts2shp.cpp
+++ b/frmts/sdts/sdts2shp.cpp
@@ -1,5 +1,4 @@
 /* ****************************************************************************
- * $Id: sdts2shp.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Mainline for converting to ArcView Shapefiles.
@@ -31,7 +30,7 @@
 #include "shapefil.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: sdts2shp.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: sdts2shp.cpp 36770 2016-12-10 01:47:26Z goatbar $");
 
 static int  bVerbose = FALSE;
 
@@ -61,7 +60,7 @@ WriteAttrRecordToDBF( DBFHandle hDBF, int nRecord,
 static void Usage()
 
 {
-    printf( "Usage: sdts2shp CATD_filename [-o shapefile_name]\n"
+    printf( "Usage: sdts2shp CATD_filename [-o shapefile_name]\n" /*ok*/
             "                [-m module_name] [-v]\n"
             "\n"
             "Modules include `LE01', `PC01', `NP01' and `ARDF'\n" );
@@ -101,7 +100,7 @@ int main( int nArgc, char ** papszArgv )
             bVerbose = TRUE;
         else
         {
-            printf( "Incomplete, or unsupported option `%s'\n\n",
+            printf( "Incomplete, or unsupported option `%s'\n\n",/*ok*/
                     papszArgv[i] );
             Usage();
         }
@@ -138,16 +137,16 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
     if( bVerbose )
     {
-        printf( "Layers:\n" );
+        printf( "Layers:\n" );/*ok*/
         for( i = 0; i < oTransfer.GetLayerCount(); i++ )
         {
             int         iCATDEntry = oTransfer.GetLayerCATDEntry(i);
 
-            printf( "  %s: `%s'\n",
+            printf( "  %s: `%s'\n",/*ok*/
                     oTransfer.GetCATD()->GetEntryModule(iCATDEntry),
                     oTransfer.GetCATD()->GetEntryTypeDesc(iCATDEntry) );
         }
-        printf( "\n" );
+        printf( "\n" );/*ok*/
     }
 
 /* -------------------------------------------------------------------- */
@@ -179,7 +178,7 @@ int main( int nArgc, char ** papszArgv )
 /* -------------------------------------------------------------------- */
 /*      If the module is a point one, dump to Shapefile.                */
 /* -------------------------------------------------------------------- */
-    else if( pszMODN[0] == 'N' || pszMODN[0] == 'N' )
+    else if( pszMODN[0] == 'N' || pszMODN[0] == 'n' )
     {
         WritePointShapefile( pszShapefile, &oTransfer, pszMODN );
     }
@@ -213,12 +212,10 @@ static void WriteLineShapefile( const char * pszShapefile,
                                 const char * pszMODN )
 
 {
-    SDTSLineReader      *poLineReader;
-
 /* -------------------------------------------------------------------- */
 /*      Fetch a reference to the indexed Pointgon reader.                */
 /* -------------------------------------------------------------------- */
-    poLineReader = (SDTSLineReader *)
+    SDTSLineReader *poLineReader = (SDTSLineReader *)
         poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
 
     if( poLineReader == NULL )
@@ -274,22 +271,19 @@ static void WriteLineShapefile( const char * pszShapefile,
 /* ==================================================================== */
 /*      Process all the line features in the module.                    */
 /* ==================================================================== */
-    SDTSRawLine *poRawLine;
+    SDTSRawLine *poRawLine = NULL;
 
     while( (poRawLine = poLineReader->GetNextLine()) != NULL )
     {
-        int             iShape;
-
 /* -------------------------------------------------------------------- */
 /*      Write out a shape with the vertices.                            */
 /* -------------------------------------------------------------------- */
-        SHPObject       *psShape;
-
-        psShape = SHPCreateSimpleObject( SHPT_ARC, poRawLine->nVertices,
-                                         poRawLine->padfX, poRawLine->padfY,
-                                         poRawLine->padfZ );
+        SHPObject *psShape =
+            SHPCreateSimpleObject( SHPT_ARC, poRawLine->nVertices,
+                                   poRawLine->padfX, poRawLine->padfY,
+                                   poRawLine->padfZ );
 
-        iShape = SHPWriteObject( hSHP, -1, psShape );
+        int iShape = SHPWriteObject( hSHP, -1, psShape );
 
         SHPDestroyObject( psShape );
 
@@ -301,22 +295,22 @@ static void WriteLineShapefile( const char * pszShapefile,
         DBFWriteIntegerAttribute( hDBF, iShape, nSDTSRecordField,
                                   poRawLine->oModId.nRecord );
 
-        sprintf( szID, "%s:%ld",
+        sprintf( szID, "%s:%d",
                  poRawLine->oLeftPoly.szModule,
                  poRawLine->oLeftPoly.nRecord );
         DBFWriteStringAttribute( hDBF, iShape, nLeftPolyField, szID );
 
-        sprintf( szID, "%s:%ld",
+        sprintf( szID, "%s:%d",
                  poRawLine->oRightPoly.szModule,
                  poRawLine->oRightPoly.nRecord );
         DBFWriteStringAttribute( hDBF, iShape, nRightPolyField, szID );
 
-        sprintf( szID, "%s:%ld",
+        sprintf( szID, "%s:%d",
                  poRawLine->oStartNode.szModule,
                  poRawLine->oStartNode.nRecord );
         DBFWriteStringAttribute( hDBF, iShape, nStartNodeField, szID );
 
-        sprintf( szID, "%s:%ld",
+        sprintf( szID, "%s:%d",
                  poRawLine->oEndNode.szModule,
                  poRawLine->oEndNode.nRecord );
         DBFWriteStringAttribute( hDBF, iShape, nEndNodeField, szID );
@@ -343,12 +337,10 @@ static void WritePointShapefile( const char * pszShapefile,
                                  const char * pszMODN )
 
 {
-    SDTSPointReader     *poPointReader;
-
 /* -------------------------------------------------------------------- */
 /*      Fetch a reference to the indexed Pointgon reader.                */
 /* -------------------------------------------------------------------- */
-    poPointReader = (SDTSPointReader *)
+    SDTSPointReader *poPointReader = (SDTSPointReader *)
         poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
 
     if( poPointReader == NULL )
@@ -400,23 +392,20 @@ static void WritePointShapefile( const char * pszShapefile,
 /* ==================================================================== */
 /*      Process all the line features in the module.                    */
 /* ==================================================================== */
-    SDTSRawPoint        *poRawPoint;
+    SDTSRawPoint *poRawPoint = NULL;
 
     while( (poRawPoint = poPointReader->GetNextPoint()) != NULL )
     {
-        int             iShape;
-
 /* -------------------------------------------------------------------- */
 /*      Write out a shape with the vertices.                            */
 /* -------------------------------------------------------------------- */
-        SHPObject       *psShape;
+        SHPObject *psShape =
+            SHPCreateSimpleObject( SHPT_POINT, 1,
+                                   &(poRawPoint->dfX),
+                                   &(poRawPoint->dfY),
+                                   &(poRawPoint->dfZ) );
 
-        psShape = SHPCreateSimpleObject( SHPT_POINT, 1,
-                                         &(poRawPoint->dfX),
-                                         &(poRawPoint->dfY),
-                                         &(poRawPoint->dfZ) );
-
-        iShape = SHPWriteObject( hSHP, -1, psShape );
+        int iShape = SHPWriteObject( hSHP, -1, psShape );
 
         SHPDestroyObject( psShape );
 
@@ -428,7 +417,7 @@ static void WritePointShapefile( const char * pszShapefile,
         DBFWriteIntegerAttribute( hDBF, iShape, nSDTSRecordField,
                                   poRawPoint->oModId.nRecord );
 
-        sprintf( szID, "%s:%ld",
+        sprintf( szID, "%s:%d",
                  poRawPoint->oAreaId.szModule,
                  poRawPoint->oAreaId.nRecord );
         DBFWriteStringAttribute( hDBF, iShape, nAreaField, szID );
@@ -455,12 +444,10 @@ static void WriteAttributeDBF( const char * pszShapefile,
                                const char * pszMODN )
 
 {
-    SDTSAttrReader      *poAttrReader;
-
 /* -------------------------------------------------------------------- */
-/*      Fetch a reference to the indexed Pointgon reader.                */
+/*      Fetch a reference to the indexed Pointgon reader.               */
 /* -------------------------------------------------------------------- */
-    poAttrReader = (SDTSAttrReader *)
+    SDTSAttrReader *poAttrReader = (SDTSAttrReader *)
         poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
 
     if( poAttrReader == NULL )
@@ -502,10 +489,11 @@ static void WriteAttributeDBF( const char * pszShapefile,
 /* ==================================================================== */
 /*      Process all the records in the module.                          */
 /* ==================================================================== */
-    SDTSAttrRecord *poRecord;
-    int         iRecord = 0;
+    SDTSAttrRecord *poRecord = NULL;
+    int iRecord = 0;
 
-    while((poRecord = (SDTSAttrRecord*)poAttrReader->GetNextFeature()) != NULL)
+    while( (poRecord = (SDTSAttrRecord*)poAttrReader->GetNextFeature())
+           != NULL )
     {
         DBFWriteIntegerAttribute( hDBF, iRecord, 0,
                                   poRecord->oModId.nRecord );
@@ -533,12 +521,10 @@ static void WritePolygonShapefile( const char * pszShapefile,
                                    const char * pszMODN )
 
 {
-    SDTSPolygonReader *poPolyReader;
-
 /* -------------------------------------------------------------------- */
 /*      Fetch a reference to the indexed polygon reader.                */
 /* -------------------------------------------------------------------- */
-    poPolyReader = (SDTSPolygonReader *)
+    SDTSPolygonReader *poPolyReader = (SDTSPolygonReader *)
         poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
 
     if( poPolyReader == NULL )
@@ -592,28 +578,25 @@ static void WritePolygonShapefile( const char * pszShapefile,
 /* ==================================================================== */
 /*      Process all the polygon features in the module.                 */
 /* ==================================================================== */
-    SDTSRawPolygon      *poRawPoly;
-
     poPolyReader->Rewind();
+
+    SDTSRawPolygon *poRawPoly = NULL;
     while( (poRawPoly = (SDTSRawPolygon *) poPolyReader->GetNextFeature())
            != NULL )
     {
-        int             iShape;
-
 /* -------------------------------------------------------------------- */
 /*      Write out a shape with the vertices.                            */
 /* -------------------------------------------------------------------- */
-        SHPObject       *psShape;
+        SHPObject *psShape =
+            SHPCreateObject( SHPT_POLYGON, -1, poRawPoly->nRings,
+                             poRawPoly->panRingStart, NULL,
+                             poRawPoly->nVertices,
+                             poRawPoly->padfX,
+                             poRawPoly->padfY,
+                             poRawPoly->padfZ,
+                             NULL );
 
-        psShape = SHPCreateObject( SHPT_POLYGON, -1, poRawPoly->nRings,
-                                   poRawPoly->panRingStart, NULL,
-                                   poRawPoly->nVertices,
-                                   poRawPoly->padfX,
-                                   poRawPoly->padfY,
-                                   poRawPoly->padfZ,
-                                   NULL );
-
-        iShape = SHPWriteObject( hSHP, -1, psShape );
+        int iShape = SHPWriteObject( hSHP, -1, psShape );
 
         SHPDestroyObject( psShape );
 
@@ -651,18 +634,16 @@ AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer *poTransfer,
          papszModuleList != NULL && papszModuleList[iModule] != NULL;
          iModule++ )
     {
-        SDTSAttrReader  *poAttrReader;
-
 /* -------------------------------------------------------------------- */
 /*      Get a reader on the desired module.                             */
 /* -------------------------------------------------------------------- */
-        poAttrReader = (SDTSAttrReader *)
+        SDTSAttrReader *poAttrReader = (SDTSAttrReader *)
             poTransfer->GetLayerIndexedReader(
                 poTransfer->FindLayer( papszModuleList[iModule] ) );
 
         if( poAttrReader == NULL )
         {
-            printf( "Unable to open attribute module %s, skipping.\n" ,
+            printf( "Unable to open attribute module %s, skipping.\n" ,/*ok*/
                     papszModuleList[iModule] );
             continue;
         }
@@ -673,9 +654,8 @@ AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer *poTransfer,
 /*      Read the first record so we can clone schema information off    */
 /*      of it.                                                          */
 /* -------------------------------------------------------------------- */
-        SDTSAttrRecord  *poAttrFeature;
-
-        poAttrFeature = (SDTSAttrRecord *) poAttrReader->GetNextFeature();
+        SDTSAttrRecord *poAttrFeature =
+            (SDTSAttrRecord *) poAttrReader->GetNextFeature();
         if( poAttrFeature == NULL )
         {
             fprintf( stderr,
@@ -745,7 +725,6 @@ AddPrimaryAttrToDBFSchema( DBFHandle hDBF, SDTSTransfer *poTransfer,
 
         if( !poAttrReader->IsIndexed() )
             delete poAttrFeature;
-
     } /* next module */
 }
 
@@ -761,13 +740,11 @@ WritePrimaryAttrToDBF( DBFHandle hDBF, int iRecord,
 /* ==================================================================== */
 /*      Loop over all the attribute records linked to this feature.     */
 /* ==================================================================== */
-    int         iAttrRecord;
-
-    for( iAttrRecord = 0; iAttrRecord < poFeature->nAttributes; iAttrRecord++)
+    for( int iAttrRecord = 0;
+         iAttrRecord < poFeature->nAttributes;
+         iAttrRecord++ )
     {
-        DDFField        *poSR;
-
-        poSR = poTransfer->GetAttr( poFeature->paoATID+iAttrRecord );
+        DDFField *poSR = poTransfer->GetAttr( poFeature->paoATID+iAttrRecord );
 
         WriteAttrRecordToDBF( hDBF, iRecord, poTransfer, poSR );
     }
@@ -814,10 +791,8 @@ WriteAttrRecordToDBF( DBFHandle hDBF, int iRecord,
         switch( poSFDefn->GetType() )
         {
           case DDFString:
-            const char  *pszValue;
-
-            pszValue = poSFDefn->ExtractStringData(pachData, nMaxBytes,
-                                                   NULL);
+            const char *pszValue
+                = poSFDefn->ExtractStringData(pachData, nMaxBytes, NULL);
 
             if( iField != -1 )
                 DBFWriteStringAttribute(hDBF, iRecord, iField, pszValue );
diff --git a/frmts/sdts/sdts_al.h b/frmts/sdts/sdts_al.h
index 59a7ba4..80500bd 100644
--- a/frmts/sdts/sdts_al.h
+++ b/frmts/sdts/sdts_al.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sdts_al.h 32067 2015-12-07 15:34:53Z goatbar $
+ * $Id: sdts_al.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  SDTS Translator
  * Purpose:  Include file for entire SDTS Abstraction Layer functions.
@@ -296,7 +296,7 @@ class SDTSRawLine : public SDTSFeature
         subfield. */
     SDTSModId   oEndNode;               /* ENID */
 
-    void        Dump( FILE * );
+    void        Dump( FILE * ) override;
 };
 
 /************************************************************************/
@@ -322,10 +322,10 @@ class SDTSLineReader : public SDTSIndexedReader
                 ~SDTSLineReader();
 
     int         Open( const char * );
-    SDTSRawLine *GetNextLine( void );
+    SDTSRawLine *GetNextLine();
     void        Close();
 
-    SDTSFeature *GetNextRawFeature( void ) { return GetNextLine(); }
+    SDTSFeature *GetNextRawFeature() override { return GetNextLine(); }
 
     void        AttachToPolygons( SDTSTransfer *, int iPolyLayer  );
 };
@@ -357,7 +357,7 @@ class SDTSAttrRecord : public SDTSFeature
 
     DDFField    *poATTR;
 
-    virtual void Dump( FILE * );
+    virtual void Dump( FILE * ) override;
 };
 
 /************************************************************************/
@@ -390,7 +390,7 @@ class SDTSAttrReader : public SDTSIndexedReader
       */
     int         IsSecondary() { return bIsSecondary; }
 
-    SDTSFeature *GetNextRawFeature( void ) { return GetNextAttrRecord(); }
+    SDTSFeature *GetNextRawFeature() override { return GetNextAttrRecord(); }
 };
 
 /************************************************************************/
@@ -418,7 +418,7 @@ class SDTSRawPoint : public SDTSFeature
     /** Optional identifier of area marked by this point (i.e. PC01:27). */
     SDTSModId   oAreaId;                /* ARID */
 
-    virtual void Dump( FILE * );
+    virtual void Dump( FILE * ) override;
 };
 
 /************************************************************************/
@@ -439,10 +439,10 @@ class SDTSPointReader : public SDTSIndexedReader
     virtual    ~SDTSPointReader();
 
     int         Open( const char * );
-    SDTSRawPoint *GetNextPoint( void );
+    SDTSRawPoint *GetNextPoint();
     void        Close();
 
-    SDTSFeature *GetNextRawFeature( void ) { return GetNextPoint(); }
+    SDTSFeature *GetNextRawFeature() override { return GetNextPoint(); }
 };
 
 /************************************************************************/
@@ -453,7 +453,7 @@ class SDTSPointReader : public SDTSIndexedReader
   Class for holding information about a polygon feature.
 
   When directly read from a polygon module, the polygon has no concept
-  of it's geometry.  Just it's ID, and references to attribute records.
+  of its geometry.  Just it's ID, and references to attribute records.
   However, if the SDTSLineReader::AttachToPolygons() method is called on
   the module containing the lines forming the polygon boundaries, then the
   nEdges/papoEdges information on the SDTSRawPolygon will be filled in.
@@ -503,7 +503,7 @@ class SDTSRawPolygon : public SDTSFeature
       rings via panRingStart.  The values are almost always zero. */
     double      *padfZ;
 
-    virtual void Dump( FILE * );
+    virtual void Dump( FILE * ) override;
 };
 
 /************************************************************************/
@@ -521,10 +521,10 @@ class SDTSPolygonReader : public SDTSIndexedReader
     virtual    ~SDTSPolygonReader();
 
     int         Open( const char * );
-    SDTSRawPolygon *GetNextPolygon( void );
+    SDTSRawPolygon *GetNextPolygon();
     void        Close();
 
-    SDTSFeature *GetNextRawFeature( void ) { return GetNextPolygon(); }
+    SDTSFeature *GetNextRawFeature() override { return GetNextPolygon(); }
 
     void        AssembleRings( SDTSTransfer *, int iPolyLayer );
 };
diff --git a/frmts/sdts/sdts_main.dox b/frmts/sdts/sdts_main.dox
index e68a3b3..608d1ef 100644
--- a/frmts/sdts/sdts_main.dox
+++ b/frmts/sdts/sdts_main.dox
@@ -16,19 +16,19 @@ of open source, easy to compile and integrate C++ code.<p>
 
 <h2>SDTS Background</h2>
 
-The USGS SDTS Page at 
+The USGS SDTS Page at
 <a href="http://mcmcweb.er.usgs.gov/sdts/">http://mcmcweb.er.usgs.gov/sdts</a>
 is the definitive source of information on the SDTS format.  The SDTS
-format is based on the 
+format is based on the
 <a href="http://starship.skyport.net/crew/tibs/iso8211/faq.html">ISO 8211</a>
 encoding scheme for the underlying files, and the SDTS Abstraction Library
-uses 
+uses
 <a href="http://gdal.velocet.ca/projects/iso8211/index.html">ISO8211Lib</a>
 library to decode them.  All references to DDF* classes are from ISO8211Lib.<p>
 
 An SDTS Transfer is a grouping of ISO8211 encoded files (ending in the
 .DDF extension), normally with part of the basename in common.  For instance
-a USGS DLG SDTS transfer might consists of many files matching the 
+a USGS DLG SDTS transfer might consists of many files matching the
 SC01????.DDF pattern.  The key file in an SDTS transfer is the catalog
 file, such as SC01CATD.DDF.<p>
 
@@ -36,11 +36,11 @@ file, such as SC01CATD.DDF.<p>
 
 <h2>Development Information</h2>
 
-The <a href="class_sdtstransfer-include.html">sdts_al.h</a> 
-include file contains the definitions for all public 
+The <a href="class_sdtstransfer-include.html">sdts_al.h</a>
+include file contains the definitions for all public
 SDTS classes, enumerations and other services.<p>
 
-The SDTSTransfer class is used to access a transfer as a whole.  The 
+The SDTSTransfer class is used to access a transfer as a whole.  The
 SDTSTransfer::Open() method is passed the name of the catalog file,
 such as SC01CATD.DDF, to open.<p>
 
@@ -48,17 +48,17 @@ The SDTSTransfer analyses the catalog, and some other aspects of the
 transfer, and builds a list of feature layers.  This list can be
 accessed using the SDTSTransfer::GetLayerCount(), SDTSTransfer::GetLayerType(),
 and SDTSTransfer::GetLayerIndexedReader() methods.  A typical TVP (Topological
-Vector Profile) transfer might include three point layers (of type 
+Vector Profile) transfer might include three point layers (of type
 SLTPoint), a line layer (of type SLTLine), a polygon layer (of type SLTPoly)
 as well as some additional attribute layers (of type SLTAttr).  the
-SDTSTransfer::GetLayerIndexedReader() method can be used to instantiate a 
+SDTSTransfer::GetLayerIndexedReader() method can be used to instantiate a
 reader object for reading a particular layer. (NOTE: raster layers are
 handled differently).<p>
 
-Each type of SDTSIndexedReader (SDTSPointReader, SDTSLineReader, 
+Each type of SDTSIndexedReader (SDTSPointReader, SDTSLineReader,
 SDTSPolygonReader, and SDTSAttrReader) returns specific subclasses of
 SDTSIndexedFeature from the SDTSIndexedReader::GetNextFeature() method.
-These classes are SDTSRawPoint, SDTSRawLine, SDTSRawPolygon and 
+These classes are SDTSRawPoint, SDTSRawLine, SDTSRawPolygon and
 SDTSAttrRecord.  These classes can be investigated for details on the
 data available for each.<p>
 
@@ -72,7 +72,7 @@ on how to use this library.<p>
 <ol>
 
 <li> First, fetch the source.  The most recent source should be accessible
-at an url such as 
+at an url such as
 <a href="ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.tar.gz">
 ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.tar.gz</a>.<p>
 
@@ -83,7 +83,7 @@ ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.tar.gz</a>.<p>
 % tar xzvf sdts_1_3.tar.gz
 </pre>
 
-<li> Type ``configure'' to establish configuration 
+<li> Type ``configure'' to establish configuration
 options. <p>
 
 <li> Type make to build sdts_al.a, and the sample
@@ -101,7 +101,7 @@ on how to use this library.<p>
 <ol>
 
 <li> First, fetch the source.  The most recent source should be accessible
-at an url such as 
+at an url such as
 <a href="ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.zip">
 ftp://gdal.velocet.ca/pub/outgoing/sdts_1_3.zip</a>.<p>
 
@@ -132,7 +132,7 @@ on how to use this library.<p>
 
 The sdts2shp program distributed with this toolkit is primary intended to
 serve as an example of how to use the SDTS access library.  However, it can
-be useful to translate SDTS datasets into ESRI Shapefile format.  
+be useful to translate SDTS datasets into ESRI Shapefile format.
 
 <pre>
 Usage: sdts2shp CATD_filename [-o shapefile_name]
@@ -200,8 +200,8 @@ The precise license text is:<p>
 <h2>Author and Acknowledgements</h2>
 
 The primary author of SDTS_AL is <a href="http://pobox.com/~warmerdam">
-Frank Warmerdam</a>, and I can be reached at 
-<a href="mailto:warmerdam at pobox.com">warmerdam at pobox.com</a>.  I am eager to 
+Frank Warmerdam</a>, and I can be reached at
+<a href="mailto:warmerdam at pobox.com">warmerdam at pobox.com</a>.  I am eager to
 receive bug reports, and also open to praise or suggestions.<p>
 
 I would like to thank:<p>
@@ -210,16 +210,16 @@ I would like to thank:<p>
 <li> <a href="http://www.safe.com/">Safe Software</a>
 who funded development of this library, and agreed for it to be Open Source.<p>
 
-<li> Mark Colletti, a primary author of 
+<li> Mark Colletti, a primary author of
 <a href="http://mcmcweb.er.usgs.gov/sdts/sdtsxx/index.html">SDTS++</a> from
-which I derived most of what I know about SDTS and ISO8211 and who was very 
+which I derived most of what I know about SDTS and ISO8211 and who was very
 supportive, answering a variety of questions.<p>
 
 </ul>
 
-I would also like to dedicate this library to the memory of Sol Katz.  
+I would also like to dedicate this library to the memory of Sol Katz.
 Sol released a variety of SDTS translators, at substantial
-personal effort, to the GIS community along with the many other generous 
+personal effort, to the GIS community along with the many other generous
 contributions he made to the community.  His example has been an inspiration
 to me, and I hope similar efforts on my part will contribute to his memory.<p>
 
diff --git a/frmts/sdts/sdts_tut.dox b/frmts/sdts/sdts_tut.dox
index 6f260a0..52b3b98 100644
--- a/frmts/sdts/sdts_tut.dox
+++ b/frmts/sdts/sdts_tut.dox
@@ -4,7 +4,7 @@
 <title>SDTS Abstraction Library Tutorial</title>
 </center>
 
-This page is a walk through of the polygon layer portion of the 
+This page is a walk through of the polygon layer portion of the
 <a href="sdts2shp.cpp.html">sdts2shp.cpp</a> example application.  It is should
 give sufficient information to utilize the SDTS_AL library to read SDTS
 files.<p>
@@ -16,7 +16,7 @@ passed to SDTSTransfer::Open() should be the name of the catalog file,
 such as <tt>palo_alto/SC01CATD.DDF</tt>.  The Open() method returns FALSE
 if it fails for any reason.  In addition to the message we print out ourselves,
 the SDTSTransfer::Open() method will also emit it's own error message using
-CPLError().  See the cpl_error.h page for more information on how to 
+CPLError().  See the cpl_error.h page for more information on how to
 capture and control CPLError() style error reporting.<p>
 
 <pre>
@@ -40,12 +40,12 @@ capture and control CPLError() style error reporting.<p>
 Once an SDTSTransfer has been opened, it is possible to establish what
 layers are available.  The sdts2shp example problem includes a -v argument
 to dump a list of available layers.  It isn't normally necessary to use the
-SDTS_CATD (catalog) from an application to access SDTS files; however, in 
+SDTS_CATD (catalog) from an application to access SDTS files; however, in
 this example we use it to fetch a module name, and description for each
 of the available layers.<p>
 
 In particular, the SDTSTransfer::GetLayerCount() method returns the
-number of feature layers in the transfer and the 
+number of feature layers in the transfer and the
 SDTSTransfer::GetLayerCATDEntry() is used to translate layer indexes into
 SDTS_CATD compatible CATD indexes.<p>
 
@@ -54,7 +54,7 @@ SDTS_CATD compatible CATD indexes.<p>
         for( i = 0; i < oTransfer.GetLayerCount(); i++ )
         {
             int		iCATDEntry = oTransfer.GetLayerCATDEntry(i);
-            
+
             printf( "  %s: `%s'\n",
                     oTransfer.GetCATD()->GetEntryModule(iCATDEntry),
                     oTransfer.GetCATD()->GetEntryTypeDesc(iCATDEntry) );
@@ -84,21 +84,21 @@ Layers:
 
 In order to read polygon features, it is necessary to instantiate a polygon
 reader on the desired layer.  The sdts2shp.cpp program allow the user to
-select a module name (such as PC01, stored in pszMODN) to write to shape 
+select a module name (such as PC01, stored in pszMODN) to write to shape
 format.  Other application might just search for, and operate on all known
 layers of a desired type.<p>
 
 The SDTSTransfer::GetLayerIndexedReader() method instantiates a reader of
-the desired type.  In this case we know we are instantiating a 
-SDTSPolygonReader so we can safely cast the returned SDTSIndexedReader 
+the desired type.  In this case we know we are instantiating a
+SDTSPolygonReader so we can safely cast the returned SDTSIndexedReader
 pointer to the more specific type SDTSPolygonReader.<p>
 
 <pre>
     SDTSPolygonReader *poPolyReader;
 
-    poPolyReader = (SDTSPolygonReader *) 
+    poPolyReader = (SDTSPolygonReader *)
         poTransfer->GetLayerIndexedReader( poTransfer->FindLayer( pszMODN ) );
-    
+
     if( poPolyReader == NULL )
     {
         fprintf( stderr, "Failed to open %s.\n",
@@ -123,7 +123,7 @@ method.  This method will scan all SLTLine layers in the transfer, indexing
 them and attaching their line work to the polygons.  Then it assembles the
 line work into rings.  It also ensures that the outer ring comes first, that
 the outer ring is counter-clockwise and that the inner ring(s) are
-clockwise. 
+clockwise.
 
 <pre>
     poPolyReader->AssembleRings( poTransfer );
@@ -138,8 +138,8 @@ list of edges that form their border.<p>
 
 In order to create the schema for the output shapefile dataset, it is
 necessary to identify the attributes associated with the polygons.  There
-are two types of attributes which can occur.  The first are hardcoded 
-attributes specific to the feature type, and the second are generic 
+are two types of attributes which can occur.  The first are hardcoded
+attributes specific to the feature type, and the second are generic
 user attributes stored in a separate primary attribute layer.<p>
 
 In the case of SDTSRawPolygon, there is only one attribute of interest,
@@ -156,19 +156,19 @@ the polygon within this module/layer.<p>
 Identification of user attributes is more complicated.  Any feature in a
 layer can have associates with 0, 1, 2 or potentially more attribute records
 in other primary attribute layers.  In order to establish a schema for the
-layer it is necessary to build up a list of all attribute layers (tables) 
+layer it is necessary to build up a list of all attribute layers (tables)
 to which references appear.  The SDTSIndexedReader::ScanModuleReferences()
 method can be used to scan a whole module for references to attribute modules
 via the ATID field.  The return result is a list of referenced modules in the
 form of a string list.  In a typical case this is one or two modules, such
-as "ASCF".<p>  
+as "ASCF".<p>
 
 <pre>
     char  **papszModRefs = poPolyReader->ScanModuleReferences();
 </pre>
 
 In sdts2shp.cpp, a subroutine (AddPrimaryAttrToDBFSchema()) is defined
-to add all the fields of all references attribute layers to the DBF file. 
+to add all the fields of all references attribute layers to the DBF file.
 For each module in the list the following steps are executed.<p>
 
 <h3>Fetch an Attribute Module Reader</h3>
@@ -210,12 +210,12 @@ the sdts2shp program fetches a prototype record from the attribute module.
             fprintf( stderr,
                      "Didn't find any meaningful attribute records in %s.\n",
                      papszModuleList[iModule] );
-        
+
             continue;
         }
 </pre>
 
-When no longer needed, the attribute record may need to be explicitly 
+When no longer needed, the attribute record may need to be explicitly
 deleted if it is not part of an indexed cached.<p>
 
 <pre>
@@ -228,7 +228,7 @@ deleted if it is not part of an indexed cached.<p>
 
 The Shapefile DBF fields are defined based on the information available for
 each of the subfields of the attribute records ATTR DDFField (the poATTR
-data member).  The following code loops over each of the subfields, 
+data member).  The following code loops over each of the subfields,
 getting a pointer to the DDBSubfieldDefn containing information about that
 subfield.<p>
 
@@ -236,14 +236,14 @@ subfield.<p>
         DDFFieldDefn 	*poFDefn = poAttrFeature->poATTR->GetFieldDefn();
         int		iSF;
         DDFField	*poSR = poAttrFeature->poATTR;
-    
+
         for( iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
         {
             DDFSubfieldDefn	*poSFDefn = poFDefn->GetSubfield( iSF );
 </pre>
 
 Then each of the significant ISO8211 field types is translated to an
-appropriate DBF field type.  In cases where the nWidth field is zero, 
+appropriate DBF field type.  In cases where the nWidth field is zero,
 indicating that the field is variable width, we use the length of the
 field in the prototype record.  Ideally we would scan the whole file to find
 the longest value for each field, but that would be a significant amount of
@@ -258,14 +258,14 @@ work. <p>
                 if( nWidth == 0 )
                 {
                     int		nMaxBytes;
-                
+
                     const char * pachData = poSR->GetSubfieldData(poSFDefn,
                                                                   &nMaxBytes);
 
                     nWidth = strlen(poSFDefn->ExtractStringData(pachData,
                                                                 nMaxBytes, NULL ));
                 }
-            
+
                 DBFAddField( hDBF, poSFDefn->GetName(), FTString, nWidth, 0 );
                 break;
 
@@ -302,7 +302,7 @@ delete it, if and only if the layer does not have an index cache.<p>
 
 <pre>
     SDTSRawPolygon	*poRawPoly;
-        
+
     poPolyReader->Rewind();
     while( (poRawPoly = (SDTSRawPolygon *) poPolyReader->GetNextFeature())
            != NULL )
@@ -319,18 +319,18 @@ delete it, if and only if the layer does not have an index cache.<p>
 In an earlier step we used the SDTSPolygonReader::AssembleRings() method to
 build ring geometry on the polygons from the linework in the line layers.<p>
 
-Coincidently (well, ok, maybe it isn't a coincidence) it so happens that the 
-ring organization exactly matches what is needed for the shapefile api.  
+Coincidently (well, ok, maybe it isn't a coincidence) it so happens that the
+ring organization exactly matches what is needed for the shapefile api.
 The following call creates a polygon from the ring information in the
-SDTSRawPolygon.  See the SDTSRawPolygon reference help for a fuller 
+SDTSRawPolygon.  See the SDTSRawPolygon reference help for a fuller
 definition of the nRings, panRingStart, nVertices, and vertex fields.<p>
 
 <pre>
         psShape = SHPCreateObject( SHPT_POLYGON, -1, poRawPoly->nRings,
                                    poRawPoly->panRingStart, NULL,
                                    poRawPoly->nVertices,
-                                   poRawPoly->padfX, 
-                                   poRawPoly->padfY, 
+                                   poRawPoly->padfX,
+                                   poRawPoly->padfY,
                                    poRawPoly->padfZ,
                                    NULL );
 </pre>
@@ -339,7 +339,7 @@ definition of the nRings, panRingStart, nVertices, and vertex fields.<p>
 
 The following call is used to write out the record number of the polygon,
 fetched from the SDTSIndexedFeature::oModId data member.  The szModule value
-in this data field will always match the module name for the whole layer. 
+in this data field will always match the module name for the whole layer.
 While not shown here, there is also an szOBRP field on oModId which have
 different values depending on whether the polygon is a universe or regular
 polygon.<p>
@@ -353,10 +353,10 @@ polygon.<p>
 
 In keeping with the setting up of the schema, accessing the user records
 is somewhat complicated.  In sdts2shp, the primary attribute records associated
-with any feature (including SDTSRawPolygons) can be fetched with the 
+with any feature (including SDTSRawPolygons) can be fetched with the
 WriteAttrRecordToDBF() function defined as follows.<p>
 
-In particular, the poFeature->nAttributes member indicates how many 
+In particular, the poFeature->nAttributes member indicates how many
 associated attribute records there are.  The poFeature->aoATID[] array
 contains the SDTSModId's for each record.  This SDTSModId can be passed
 to SDTSTransfer::GetAttr() to fetch the DDFField pointer for the user
@@ -365,13 +365,13 @@ and will be define later.<p>
 
 <pre>
     int		iAttrRecord;
-    
+
     for( iAttrRecord = 0; iAttrRecord < poFeature->nAttributes; iAttrRecord++)
     {
         DDFField	*poSR;
 
         poSR = poTransfer->GetAttr( poFeature->aoATID+iAttrRecord );
-          
+
         WriteAttrRecordToDBF( hDBF, iRecord, poTransfer, poSR );
     }
 </pre>
@@ -389,7 +389,7 @@ page.<p>
 /*      Process each subfield in the record.                            */
 /* -------------------------------------------------------------------- */
     DDFFieldDefn 	*poFDefn = poSR->GetFieldDefn();
-        
+
     for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
     {
         DDFSubfieldDefn	*poSFDefn = poFDefn->GetSubfield( iSF );
@@ -410,7 +410,7 @@ page.<p>
 
         if( iField == hDBF->nFields )
             iField = -1;
-            
+
 /* -------------------------------------------------------------------- */
 /*      Handle each of the types.                                       */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/sdts/sdtsattrreader.cpp b/frmts/sdts/sdtsattrreader.cpp
index 90745bd..dc1ce45 100644
--- a/frmts/sdts/sdtsattrreader.cpp
+++ b/frmts/sdts/sdtsattrreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtsattrreader.cpp 31596 2015-11-18 11:40:37Z rouault $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSAttrReader class.
@@ -29,8 +28,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsattrreader.cpp 31596 2015-11-18 11:40:37Z rouault $");
-
+CPL_CVSID("$Id: sdtsattrreader.cpp 35897 2016-10-24 11:54:24Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -69,7 +67,6 @@ void SDTSAttrRecord::Dump( FILE * fp )
         poATTR->Dump( fp );
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                             SDTSAttrReader                           */
@@ -84,7 +81,7 @@ void SDTSAttrRecord::Dump( FILE * fp )
 
 SDTSAttrReader::SDTSAttrReader() :
     bIsSecondary(FALSE)
-{ }
+{}
 
 /************************************************************************/
 /*                          ~SDTSAttrReader()                           */
@@ -197,7 +194,7 @@ SDTSAttrRecord *SDTSAttrReader::GetNextAttrRecord()
 
 {
     SDTSModId   oModId;
-    DDFRecord   *poRawRecord;
+    DDFRecord   *poRawRecord = NULL;
 
     DDFField *poATTRField = GetNextRecord( &oModId, &poRawRecord, TRUE );
 
diff --git a/frmts/sdts/sdtscatd.cpp b/frmts/sdts/sdtscatd.cpp
index 91db36a..cd3fd95 100644
--- a/frmts/sdts/sdtscatd.cpp
+++ b/frmts/sdts/sdtscatd.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtscatd.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTS_CATD and SDTS_CATDEntry classes for
@@ -30,8 +29,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtscatd.cpp 33717 2016-03-14 06:29:14Z goatbar $");
-
+CPL_CVSID("$Id: sdtscatd.cpp 35897 2016-10-24 11:54:24Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -140,7 +138,7 @@ int SDTS_CATD::Read( const char * pszFilename )
 /*      Loop reading CATD records, and adding to our list of entries    */
 /*      for each.                                                       */
 /* ==================================================================== */
-    DDFRecord *poRecord;
+    DDFRecord *poRecord = NULL;
     while( (poRecord = oCATDFile.ReadRecord()) != NULL )
     {
 /* -------------------------------------------------------------------- */
@@ -181,7 +179,6 @@ int SDTS_CATD::Read( const char * pszFilename )
     return nEntries > 0;
 }
 
-
 /************************************************************************/
 /*                         GetModuleFilePath()                          */
 /************************************************************************/
diff --git a/frmts/sdts/sdtsdataset.cpp b/frmts/sdts/sdtsdataset.cpp
index d2a9e55..9aaf6c3 100644
--- a/frmts/sdts/sdtsdataset.cpp
+++ b/frmts/sdts/sdtsdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  GDALDataset driver for SDTS Raster translator.
@@ -33,7 +32,7 @@
 #include "ogr_spatialref.h"
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: sdtsdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /**
  \file sdtsdataset.cpp
@@ -59,12 +58,13 @@ class SDTSDataset : public GDALPamDataset
     char        *pszProjection;
 
   public:
+                 SDTSDataset();
     virtual     ~SDTSDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
 };
 
 class SDTSRasterBand : public GDALPamRasterBand
@@ -77,14 +77,26 @@ class SDTSRasterBand : public GDALPamRasterBand
 
                 SDTSRasterBand( SDTSDataset *, int, SDTSRasterReader * );
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 
-    virtual double GetNoDataValue( int *pbSuccess );
-    virtual const char *GetUnitType();
+    virtual double GetNoDataValue( int *pbSuccess ) override;
+    virtual const char *GetUnitType() override;
 };
 
 
 /************************************************************************/
+/*                             SDTSDataset()                            */
+/************************************************************************/
+
+SDTSDataset::SDTSDataset() :
+    poTransfer( NULL ),
+    poRL( NULL ),
+    pszProjection( NULL )
+
+{
+}
+
+/************************************************************************/
 /*                            ~SDTSDataset()                            */
 /************************************************************************/
 
@@ -225,9 +237,7 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
         oSRS.SetWellKnownGeogCS( "NAD83" );
     else if( EQUAL(poXREF->pszDatum, "WGC") )
         oSRS.SetWellKnownGeogCS( "WGS72" );
-    else if( EQUAL(poXREF->pszDatum, "WGE") )
-        oSRS.SetWellKnownGeogCS( "WGS84" );
-    else
+    else /* if( EQUAL(poXREF->pszDatum, "WGE") ) or default */
         oSRS.SetWellKnownGeogCS( "WGS84" );
 
     oSRS.Fixup();
@@ -236,7 +246,6 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
     if( oSRS.exportToWkt( &poDS->pszProjection ) != OGRERR_NONE )
         poDS->pszProjection = CPLStrdup("");
 
-
 /* -------------------------------------------------------------------- */
 /*      Get metadata from the IDEN file.                                */
 /* -------------------------------------------------------------------- */
@@ -246,7 +255,7 @@ GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )
         DDFModule   oIDENFile;
         if( oIDENFile.Open( pszIDENFilePath ) )
         {
-            DDFRecord* poRecord;
+            DDFRecord* poRecord = NULL;
 
             while( (poRecord = oIDENFile.ReadRecord()) != NULL )
             {
diff --git a/frmts/sdts/sdtsindexedreader.cpp b/frmts/sdts/sdtsindexedreader.cpp
index db177cd..1e8a431 100644
--- a/frmts/sdts/sdtsindexedreader.cpp
+++ b/frmts/sdts/sdtsindexedreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtsindexedreader.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implmementation of SDTSIndexedReader class.  This base class for
@@ -32,7 +31,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsindexedreader.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: sdtsindexedreader.cpp 34968 2016-08-07 21:35:08Z goatbar $");
 
 /************************************************************************/
 /*                         SDTSIndexedReader()                          */
@@ -139,7 +138,7 @@ SDTSFeature *SDTSIndexedReader::GetNextFeature()
 /************************************************************************/
 
 /**
- Fetch a feature based on it's record number.
+ Fetch a feature based on its record number.
 
  This method will forcibly fill the feature cache, reading all the
  features in the file into memory, if they haven't already been loaded.
@@ -179,13 +178,12 @@ SDTSFeature *SDTSIndexedReader::GetIndexedFeatureRef( int iRecordId )
 void SDTSIndexedReader::FillIndex()
 
 {
-
     if( nIndexSize != 0 )
         return;
 
     Rewind();
 
-    SDTSFeature *poFeature;
+    SDTSFeature *poFeature = NULL;
     while( (poFeature = GetNextRawFeature()) != NULL )
     {
         const int iRecordId = poFeature->oModId.nRecord;
diff --git a/frmts/sdts/sdtsiref.cpp b/frmts/sdts/sdtsiref.cpp
index 2194f4a..4057a1b 100644
--- a/frmts/sdts/sdtsiref.cpp
+++ b/frmts/sdts/sdtsiref.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtsiref.cpp 31332 2015-11-03 17:34:39Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTS_IREF class for reading IREF module.
@@ -29,7 +28,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsiref.cpp 31332 2015-11-03 17:34:39Z goatbar $");
+CPL_CVSID("$Id: sdtsiref.cpp 35897 2016-10-24 11:54:24Z goatbar $");
 
 /************************************************************************/
 /*                             SDTS_IREF()                              */
@@ -187,14 +186,13 @@ int SDTS_IREF::GetSADR( DDFField * poField, int nVertices,
 
         for( int iVertex = 0; iVertex < nVertices; iVertex++ )
         {
-            double adfXYZ[3] = {0.0, 0.0, 0.0};
-
+            double adfXYZ[3] = { 0.0, 0.0, 0.0 };
 
             for( int iEntry = 0;
                  iEntry < poFieldDefn->GetSubfieldCount();
                  iEntry++ )
             {
-                int     nBytesConsumed = 0;
+                int nBytesConsumed = 0;
                 DDFSubfieldDefn *poSF = poFieldDefn->GetSubfield(iEntry);
 
                 switch( poSF->GetType() )
diff --git a/frmts/sdts/sdtslib.cpp b/frmts/sdts/sdtslib.cpp
index 80d147a..995fd45 100644
--- a/frmts/sdts/sdtslib.cpp
+++ b/frmts/sdts/sdtslib.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtslib.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Various utility functions that apply to all SDTS profiles.
@@ -32,7 +31,7 @@
 #include "sdts_al.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: sdtslib.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: sdtslib.cpp 36461 2016-11-23 12:05:14Z rouault $");
 
 /************************************************************************/
 /*                            SDTSFeature()                             */
@@ -54,7 +53,7 @@ void SDTSFeature::ApplyATID( DDFField * poField )
         = poField->GetFieldDefn()->FindSubfieldDefn( "MODN" );
     if( poMODN == NULL )
     {
-        //CPLAssert( FALSE );
+        // CPLAssert( false );
         return;
     }
 
@@ -124,10 +123,8 @@ int SDTSModId::Set( DDFField *poField )
             = poField->GetFieldDefn()->FindSubfieldDefn( "MODN" );
         int nBytesRemaining;
         pachData = poField->GetSubfieldData(poSF, &nBytesRemaining);
-        strncpy( szModule,
-                 poSF->ExtractStringData( pachData, nBytesRemaining, NULL),
-                 sizeof(szModule) );
-        szModule[sizeof(szModule)-1] = '\0';
+        snprintf( szModule, sizeof(szModule), "%s",
+                 poSF->ExtractStringData( pachData, nBytesRemaining, NULL) );
 
         poSF = poField->GetFieldDefn()->FindSubfieldDefn( "RCID" );
         if( poSF != NULL )
@@ -148,11 +145,8 @@ int SDTSModId::Set( DDFField *poField )
                 = poField->GetSubfieldData(poSF, &nBytesRemaining);
             if( pachData != NULL )
             {
-                strncpy( szOBRP,
-                        poSF->ExtractStringData( pachData, nBytesRemaining, NULL),
-                        sizeof(szOBRP) );
-
-                szOBRP[sizeof(szOBRP)-1] = '\0';
+                snprintf( szOBRP, sizeof(szOBRP), "%s",
+                        poSF->ExtractStringData( pachData, nBytesRemaining, NULL) );
             }
         }
     }
@@ -198,10 +192,9 @@ char **SDTSScanModuleReferences( DDFModule * poModule, const char * pszFName )
 /* -------------------------------------------------------------------- */
 /*      Scan the file.                                                  */
 /* -------------------------------------------------------------------- */
-
     poModule->Rewind();
 
-    DDFRecord *poRecord;
+    DDFRecord *poRecord = NULL;
     char **papszModnList = NULL;
     while( (poRecord = poModule->ReadRecord()) != NULL )
     {
diff --git a/frmts/sdts/sdtslinereader.cpp b/frmts/sdts/sdtslinereader.cpp
index 78f672e..9f51ed5 100644
--- a/frmts/sdts/sdtslinereader.cpp
+++ b/frmts/sdts/sdtslinereader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtslinereader.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSLineReader and SDTSRawLine classes.
@@ -29,7 +28,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtslinereader.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: sdtslinereader.cpp 35671 2016-10-09 23:46:52Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -87,10 +86,8 @@ int SDTSRawLine::Read( SDTS_IREF * poIREF, DDFRecord * poRecord )
     for( int iField = 0; iField < poRecord->GetFieldCount(); iField++ )
     {
         DDFField        *poField = poRecord->GetField( iField );
-        const char      *pszFieldName;
-
         CPLAssert( poField != NULL );
-        pszFieldName = poField->GetFieldDefn()->GetName();
+        const char *pszFieldName = poField->GetFieldDefn()->GetName();
 
         if( EQUAL(pszFieldName,"LINE") )
             oModId.Set( poField );
@@ -173,11 +170,9 @@ void SDTSRawLine::Dump( FILE * fp )
 /*                           SDTSLineReader()                           */
 /************************************************************************/
 
-SDTSLineReader::SDTSLineReader( SDTS_IREF * poIREFIn )
-
-{
-    poIREF = poIREFIn;
-}
+SDTSLineReader::SDTSLineReader( SDTS_IREF * poIREFIn ) :
+    poIREF(poIREFIn)
+{}
 
 /************************************************************************/
 /*                             ~SDTSLineReader()                        */
@@ -208,7 +203,7 @@ void SDTSLineReader::Close()
 int SDTSLineReader::Open( const char * pszFilename )
 
 {
-    return( oDDFModule.Open( pszFilename ) );
+    return oDDFModule.Open( pszFilename );
 }
 
 /************************************************************************/
@@ -241,7 +236,7 @@ SDTSRawLine *SDTSLineReader::GetNextLine()
 
     if( poRawLine->Read( poIREF, poRecord ) )
     {
-        return( poRawLine );
+        return poRawLine;
     }
 
     delete poRawLine;
@@ -285,7 +280,7 @@ void SDTSLineReader::AttachToPolygons( SDTSTransfer * poTransfer,
 /*      have as right and left faces.                                   */
 /* ==================================================================== */
     Rewind();
-    SDTSRawLine *poLine;
+    SDTSRawLine *poLine = NULL;
     SDTSPolygonReader *poPolyReader = NULL;
     while( (poLine = reinterpret_cast<SDTSRawLine *>( GetNextFeature()) )
            != NULL )
diff --git a/frmts/sdts/sdtspointreader.cpp b/frmts/sdts/sdtspointreader.cpp
index 3385cf9..d5db018 100644
--- a/frmts/sdts/sdtspointreader.cpp
+++ b/frmts/sdts/sdtspointreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtspointreader.cpp 31332 2015-11-03 17:34:39Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSPointReader and SDTSRawPoint classes.
@@ -29,7 +28,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtspointreader.cpp 31332 2015-11-03 17:34:39Z goatbar $");
+CPL_CVSID("$Id: sdtspointreader.cpp 35897 2016-10-24 11:54:24Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -118,7 +117,6 @@ void SDTSRawPoint::Dump( FILE * fp )
     fprintf( fp, "  Vertex = (%.2f,%.2f,%.2f)\n", dfX, dfY, dfZ );
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                             SDTSPointReader                          */
@@ -161,7 +159,7 @@ void SDTSPointReader::Close()
 int SDTSPointReader::Open( const char * pszFilename )
 
 {
-    return( oDDFModule.Open( pszFilename ) );
+    return oDDFModule.Open( pszFilename );
 }
 
 /************************************************************************/
@@ -191,7 +189,7 @@ SDTSRawPoint * SDTSPointReader::GetNextPoint()
 
     if( poRawPoint->Read( poIREF, poRecord ) )
     {
-        return( poRawPoint );
+        return poRawPoint;
     }
 
     delete poRawPoint;
diff --git a/frmts/sdts/sdtspolygonreader.cpp b/frmts/sdts/sdtspolygonreader.cpp
index ae3a853..f558b04 100644
--- a/frmts/sdts/sdtspolygonreader.cpp
+++ b/frmts/sdts/sdtspolygonreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtspolygonreader.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSPolygonReader and SDTSRawPolygon classes.
@@ -31,7 +30,7 @@
 
 #include <cmath>
 
-CPL_CVSID("$Id: sdtspolygonreader.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: sdtspolygonreader.cpp 35671 2016-10-09 23:46:52Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -193,7 +192,7 @@ void SDTSRawPolygon::AddEdgeToRing( int nVertToAdd,
  * This method then forms the lines into rings.  Rings are formed by:
  * <ol>
  * <li> Take a previously unconsumed line, and start a ring with it.  Mark
- *      it as consumed, and keep track of it's start and end node ids as
+ *      it as consumed, and keep track of its start and end node ids as
  *      being the start and end node ids of the ring.
  * <li> If the rings start id is the same as the end node id then this ring
  *      is completely formed, return to step 1.
@@ -515,7 +514,7 @@ void SDTSPolygonReader::Close()
 int SDTSPolygonReader::Open( const char * pszFilename )
 
 {
-    return( oDDFModule.Open( pszFilename ) );
+    return oDDFModule.Open( pszFilename );
 }
 
 /************************************************************************/
@@ -545,7 +544,7 @@ SDTSRawPolygon * SDTSPolygonReader::GetNextPolygon()
 
     if( poRawPolygon->Read( poRecord ) )
     {
-        return( poRawPolygon );
+        return poRawPolygon;
     }
 
     delete poRawPolygon;
@@ -617,7 +616,7 @@ void SDTSPolygonReader::AssembleRings( SDTSTransfer * poTransfer,
 /* -------------------------------------------------------------------- */
     Rewind();
 
-    SDTSFeature *poFeature;
+    SDTSFeature *poFeature = NULL;
     while( (poFeature = GetNextFeature()) != NULL )
     {
         SDTSRawPolygon  *poPoly
diff --git a/frmts/sdts/sdtsrasterreader.cpp b/frmts/sdts/sdtsrasterreader.cpp
index cbbebd3..763a4c5 100644
--- a/frmts/sdts/sdtsrasterreader.cpp
+++ b/frmts/sdts/sdtsrasterreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtsrasterreader.cpp 31332 2015-11-03 17:34:39Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSRasterReader class.
@@ -32,7 +31,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: sdtsrasterreader.cpp 31332 2015-11-03 17:34:39Z goatbar $");
+CPL_CVSID("$Id: sdtsrasterreader.cpp 36461 2016-11-23 12:05:14Z rouault $");
 
 /************************************************************************/
 /*                          SDTSRasterReader()                          */
@@ -47,6 +46,11 @@ SDTSRasterReader::SDTSRasterReader() :
     nYStart(0)
 {
     strcpy( szINTR, "CE" );
+    memset( szModule, 0, sizeof(szModule) );
+    memset( adfTransform, 0, sizeof(adfTransform) );
+    memset( szFMT, 0, sizeof(szFMT) );
+    memset( szUNITS, 0, sizeof(szUNITS) );
+    memset( szLabel, 0, sizeof(szLabel) );
 }
 
 /************************************************************************/
@@ -76,8 +80,7 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
                             const char * pszModule )
 
 {
-    strncpy( szModule, pszModule, sizeof(szModule) );
-    szModule[sizeof(szModule) - 1] = '\0';
+    snprintf( szModule, sizeof(szModule), "%s", pszModule );
 
 /* ==================================================================== */
 /*      Search the LDEF module for the requested cell module.           */
@@ -101,7 +104,7 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
 /* -------------------------------------------------------------------- */
 /*      Read each record, till we find what we want.                    */
 /* -------------------------------------------------------------------- */
-    DDFRecord *poRecord;
+    DDFRecord *poRecord = NULL;
     while( (poRecord = oLDEF.ReadRecord() ) != NULL )
     {
         const char* pszCandidateModule = poRecord->GetStringSubfield("LDEF",0,"CMNM",0);
@@ -329,7 +332,7 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
 /* -------------------------------------------------------------------- */
 /*      Open the cell file.                                             */
 /* -------------------------------------------------------------------- */
-    return( oDDFModule.Open( poCATD->GetModuleFilePath(pszModule) ) );
+    return oDDFModule.Open( poCATD->GetModuleFilePath(pszModule) );
 }
 
 /************************************************************************/
@@ -340,7 +343,7 @@ int SDTSRasterReader::Open( SDTS_CATD * poCATD, SDTS_IREF * poIREF,
 /*      Currently we will always use sequential access.  In the         */
 /*      future we should modify the iso8211 library to support          */
 /*      seeking, and modify this to seek directly to the right          */
-/*      record once it's location is known.                             */
+/*      record once its location is known.                              */
 /************************************************************************/
 
 /**
diff --git a/frmts/sdts/sdtstransfer.cpp b/frmts/sdts/sdtstransfer.cpp
index da66468..34ac2b8 100644
--- a/frmts/sdts/sdtstransfer.cpp
+++ b/frmts/sdts/sdtstransfer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtstransfer.cpp 31955 2015-12-02 06:07:22Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTSTransfer class.
@@ -31,7 +30,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: sdtstransfer.cpp 31955 2015-12-02 06:07:22Z goatbar $");
+CPL_CVSID("$Id: sdtstransfer.cpp 35897 2016-10-24 11:54:24Z goatbar $");
 
 /************************************************************************/
 /*                            SDTSTransfer()                            */
@@ -53,7 +52,6 @@ SDTSTransfer::~SDTSTransfer()
     Close();
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -203,7 +201,7 @@ SDTSLayerType SDTSTransfer::GetLayerType( int iEntry )
 
 /**
   Fetch the CATD module index for a layer.   This can be used to fetch
-  details about the layer/module from the SDTS_CATD object, such as it's
+  details about the layer/module from the SDTS_CATD object, such as its
   filename, and description.
 
   @param iEntry the layer index from 0 to GetLayerCount()-1.
@@ -408,7 +406,7 @@ DDFModule *SDTSTransfer::GetLayerModuleReader( int iEntry )
   GetLayerIndexedReader(), it will be returned instead of creating a new
   reader.  Among other things this means that the returned reader may not
   be positioned to read from the beginning of the module, and may already
-  have it's index filled.
+  have its index filled.
 
   <li> The returned reader will be of a type appropriate to the layer.
   See SDTSTransfer::GetLayerType() to see what reader classes correspond
@@ -581,7 +579,7 @@ int SDTSTransfer::GetBounds( double *pdfMinX, double *pdfMinY,
 
             poLayer->Rewind();
 
-            SDTSRawPoint *poPoint;
+            SDTSRawPoint *poPoint = NULL;
             while( (poPoint = reinterpret_cast<SDTSRawPoint *>(
                       poLayer->GetNextFeature() ) ) != NULL )
             {
diff --git a/frmts/sdts/sdtsxref.cpp b/frmts/sdts/sdtsxref.cpp
index 68a14d4..95e2038 100644
--- a/frmts/sdts/sdtsxref.cpp
+++ b/frmts/sdts/sdtsxref.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sdtsxref.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implementation of SDTS_XREF class for reading XREF module.
@@ -29,7 +28,7 @@
 
 #include "sdts_al.h"
 
-CPL_CVSID("$Id: sdtsxref.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+CPL_CVSID("$Id: sdtsxref.cpp 34810 2016-07-28 13:47:32Z goatbar $");
 
 /************************************************************************/
 /*                             SDTS_XREF()                              */
diff --git a/frmts/sentinel2/frmt_sentinel2.html b/frmts/sentinel2/frmt_sentinel2.html
index d2b6b4c..940b43b 100644
--- a/frmts/sentinel2/frmt_sentinel2.html
+++ b/frmts/sentinel2/frmt_sentinel2.html
@@ -13,7 +13,7 @@ Starting with GDAL 2.1.3, Level-1C with "Safe Compact" encoding are also support
 <p>The SENTINEL2 driver will be used if the main metadata .xml file at the
 root of a SENTINEL2 data product is opened (whose name is typically
 S2A_OPER_MTD_SAFL1C_....xml). It can also accept directly .zip files downloaded
-from the <a href="https://scihub.esa.int/">Sentinels Scientific Data Hub</a></p>
+from the <a href="https://scihub.copernicus.eu/">Sentinels Scientific Data Hub</a></p>
 
 <p>To be able to read the imagery, GDAL must be configured with at least one of
 the JPEG2000 capable drivers.</p>
diff --git a/frmts/sentinel2/sentinel2dataset.cpp b/frmts/sentinel2/sentinel2dataset.cpp
index fe3c8e4..be303d9 100644
--- a/frmts/sentinel2/sentinel2dataset.cpp
+++ b/frmts/sentinel2/sentinel2dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sentinel2dataset.cpp 37146 2017-01-14 20:29:26Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Sentinel2 products
@@ -36,8 +35,10 @@
 #include "ogr_geometry.h"
 #include "gdaljp2metadata.h"
 #include "../vrt/vrtdataset.h"
-#include <set>
+
+#include <algorithm>
 #include <map>
+#include <set>
 #include <vector>
 
 #ifdef HAVE_UNISTD_H
@@ -48,7 +49,7 @@
 #define STARTS_WITH_CI(a,b) EQUALN(a,b,strlen(b))
 #endif
 
-CPL_CVSID("$Id: sentinel2dataset.cpp 37146 2017-01-14 20:29:26Z rouault $");
+CPL_CVSID("$Id: sentinel2dataset.cpp 37145 2017-01-14 20:02:35Z rouault $");
 
 CPL_C_START
 // TODO: Leave this declaration while Sentinel2 folks use this as a
@@ -180,9 +181,9 @@ class SENTINEL2Dataset : public VRTDataset
 
     public:
                     SENTINEL2Dataset(int nXSize, int nYSize);
-                    ~SENTINEL2Dataset();
+        virtual ~SENTINEL2Dataset();
 
-        virtual char** GetFileList();
+        virtual char** GetFileList() override;
 
         static GDALDataset *Open( GDALOpenInfo * );
         static GDALDataset *OpenL1BUserProduct( GDALOpenInfo * );
@@ -229,8 +230,7 @@ class SENTINEL2AlphaBand: public VRTSourcedRasterBand
 #else
                               int nPixelSpace, int nLineSpace
 #endif
-                              );
-
+                              ) override;
 };
 
 /************************************************************************/
@@ -241,12 +241,11 @@ SENTINEL2AlphaBand::SENTINEL2AlphaBand( GDALDataset *poDSIn, int nBandIn,
                                         GDALDataType eType,
                                         int nXSize, int nYSize,
                                         int nSaturatedVal, int nNodataVal ) :
-                            VRTSourcedRasterBand(poDSIn, nBandIn, eType,
-                                                 nXSize, nYSize),
-                            m_nSaturatedVal(nSaturatedVal),
-                            m_nNodataVal(nNodataVal)
-{
-}
+    VRTSourcedRasterBand(poDSIn, nBandIn, eType,
+                         nXSize, nYSize),
+    m_nSaturatedVal(nSaturatedVal),
+    m_nNodataVal(nNodataVal)
+{}
 
 /************************************************************************/
 /*                             IRasterIO()                              */
@@ -329,7 +328,8 @@ CPLErr SENTINEL2AlphaBand::IRasterIO( GDALRWFlag eRWFlag,
 /*                          SENTINEL2Dataset()                          */
 /************************************************************************/
 
-SENTINEL2Dataset::SENTINEL2Dataset(int nXSize, int nYSize) : VRTDataset(nXSize,nYSize)
+SENTINEL2Dataset::SENTINEL2Dataset( int nXSize, int nYSize ) :
+    VRTDataset(nXSize, nYSize)
 {
     poDriver = NULL;
     SetWritable(FALSE);
@@ -339,9 +339,7 @@ SENTINEL2Dataset::SENTINEL2Dataset(int nXSize, int nYSize) : VRTDataset(nXSize,n
 /*                         ~SENTINEL2Dataset()                          */
 /************************************************************************/
 
-SENTINEL2Dataset::~SENTINEL2Dataset()
-{
-}
+SENTINEL2Dataset::~SENTINEL2Dataset() {}
 
 /************************************************************************/
 /*                            GetFileList()                             */
@@ -427,10 +425,14 @@ class SENTINEL2_CPLXMLNodeHolder
 {
     CPLXMLNode* m_psNode;
     public:
-        SENTINEL2_CPLXMLNodeHolder(CPLXMLNode* psNode) : m_psNode(psNode) {}
+        explicit SENTINEL2_CPLXMLNodeHolder(CPLXMLNode* psNode) : m_psNode(psNode) {}
        ~SENTINEL2_CPLXMLNodeHolder() { if(m_psNode) CPLDestroyXMLNode(m_psNode); }
 
-       CPLXMLNode* Release() { CPLXMLNode* psRet = m_psNode; m_psNode = NULL; return psRet; }
+       CPLXMLNode* Release() {
+           CPLXMLNode* psRet = m_psNode;
+           m_psNode = NULL;
+           return psRet;
+       }
 };
 
 /************************************************************************/
@@ -777,8 +779,9 @@ static bool SENTINEL2GetGranuleList(CPLXMLNode* psMainMTD,
                                            sizeof(szPointerFilename)));
     if (nBytes != -1)
     {
-        szPointerFilename[MIN(nBytes,
-                            static_cast<int>(sizeof(szPointerFilename)-1))] = 0;
+        const int nOffset =
+            std::min(nBytes, static_cast<int>(sizeof(szPointerFilename)-1));
+        szPointerFilename[nOffset] = '\0';
         osDirname = CPLGetDirname(szPointerFilename);
     }
 #endif
@@ -1097,7 +1100,7 @@ static bool SENTINEL2GetResolutionSet(CPLXMLNode* psProductInfo,
             osName = "0" + osName;
         oMapResolutionsToBands[psBandDesc->nResolution].insert(osName);
     }
-    if( oSetResolutions.size() == 0 )
+    if( oSetResolutions.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find any band");
         return false;
@@ -1156,7 +1159,7 @@ static CPLString SENTINEL2GetBandListForResolution(
                                             oIterBandnames != oBandnames.end();
                                         ++oIterBandnames)
     {
-        if( osBandNames.size() )
+        if( !osBandNames.empty() )
             osBandNames += ", ";
         const char* pszName = *oIterBandnames;
         if( *pszName == '0' )
@@ -1221,9 +1224,9 @@ GDALDataset *SENTINEL2Dataset::OpenL1BUserProduct( GDALOpenInfo * poOpenInfo )
     poDS->GDALDataset::SetMetadata(papszMD);
     CSLDestroy(papszMD);
 
-    if( osOriginalXML.size() )
+    if( !osOriginalXML.empty() )
     {
-        char* apszXMLMD[2];
+        char* apszXMLMD[2] = { NULL };
         apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
         apszXMLMD[1] = NULL;
         poDS->GDALDataset::SetMetadata(apszXMLMD, "xml:SENTINEL2");
@@ -1268,7 +1271,7 @@ GDALDataset *SENTINEL2Dataset::OpenL1BUserProduct( GDALOpenInfo * poOpenInfo )
     if( pszPosList != NULL )
     {
         CPLString osPolygon = SENTINEL2GetPolygonWKTFromPosList(pszPosList);
-        if( osPolygon.size() )
+        if( !osPolygon.empty() )
             poDS->GDALDataset::SetMetadataItem("FOOTPRINT", osPolygon.c_str());
     }
 
@@ -1376,7 +1379,7 @@ static CPLString SENTINEL2GetTilename(const CPLString& osGranulePath,
 
     CPLString osTile(osGranulePath);
     const char chSeparator = SENTINEL2GetPathSeparator(osTile);
-    if( osTile.size() )
+    if( !osTile.empty() )
         osTile += chSeparator;
     if( bIsPreview ||
         (psL2ABandDesc != NULL && psL2ABandDesc->eLocation == TL_QI_DATA ) )
@@ -1513,7 +1516,7 @@ static void SENTINEL2GetResolutionSetAndMainMDFromGranule(
 
     // Parse product MTD if available
     papszMD = NULL;
-    if( osMainMTD.size() != 0 &&
+    if( !osMainMTD.empty() &&
         /* env var for debug only */
         CPLTestBool(CPLGetConfigOption("SENTINEL2_USE_MAIN_MTD", "YES")) )
     {
@@ -1593,7 +1596,7 @@ GDALDataset *SENTINEL2Dataset::OpenL1BGranule( const char* pszFilename,
 
     SENTINEL2DatasetContainer* poDS = new SENTINEL2DatasetContainer();
 
-    if( osOriginalXML.size() )
+    if( !osOriginalXML.empty() )
     {
         char* apszXMLMD[2];
         apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
@@ -1636,7 +1639,7 @@ GDALDataset *SENTINEL2Dataset::OpenL1BGranule( const char* pszFilename,
     if( pszPosList != NULL )
     {
         CPLString osPolygon = SENTINEL2GetPolygonWKTFromPosList(pszPosList);
-        if( osPolygon.size() )
+        if( !osPolygon.empty() )
             poDS->GDALDataset::SetMetadataItem("FOOTPRINT", osPolygon.c_str());
     }
 
@@ -1773,7 +1776,8 @@ GDALDataset *SENTINEL2Dataset::OpenL1BSubdataset( GDALOpenInfo * poOpenInfo )
 
     int nBits = 0; /* 0 = unknown yet*/
     int nValMax = 0; /* 0 = unknown yet*/
-    int nRows = 0, nCols = 0;
+    int nRows = 0;
+    int nCols = 0;
     CPLXMLNode* psGranuleDimensions =
         CPLGetXMLNode(psRoot, "=Level-1B_Granule_ID.Geometric_Info.Granule_Dimensions");
     if( psGranuleDimensions == NULL )
@@ -1859,7 +1863,7 @@ GDALDataset *SENTINEL2Dataset::OpenL1BSubdataset( GDALOpenInfo * poOpenInfo )
 
     for(int nBand=1;nBand<=nBands;nBand++)
     {
-        VRTSourcedRasterBand* poBand;
+        VRTSourcedRasterBand* poBand = NULL;
 
         if( nBand != nAlphaBand )
         {
@@ -1923,12 +1927,12 @@ GDALDataset *SENTINEL2Dataset::OpenL1BSubdataset( GDALOpenInfo * poOpenInfo )
             continue;
         }
 
-        GDALProxyPoolDataset* proxyDS;
-        proxyDS = new GDALProxyPoolDataset(         osTile,
-                                                    poDS->nRasterXSize,
-                                                    poDS->nRasterYSize,
-                                                    GA_ReadOnly,
-                                                    TRUE);
+        GDALProxyPoolDataset* proxyDS =
+            new GDALProxyPoolDataset( osTile,
+                                      poDS->nRasterXSize,
+                                      poDS->nRasterYSize,
+                                      GA_ReadOnly,
+                                      TRUE );
         proxyDS->AddSrcBandDescription(eDT, 128, 128);
 
         if( nBand != nAlphaBand )
@@ -2231,7 +2235,7 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2A( const char* pszFilename,
     poDS->GDALDataset::SetMetadata(papszMD);
     CSLDestroy(papszMD);
 
-    if( osOriginalXML.size() )
+    if( !osOriginalXML.empty() )
     {
         char* apszXMLMD[2];
         apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
@@ -2348,7 +2352,7 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2A( const char* pszFilename,
     if( pszPosList != NULL )
     {
         CPLString osPolygon = SENTINEL2GetPolygonWKTFromPosList(pszPosList);
-        if( osPolygon.size() )
+        if( !osPolygon.empty() )
             poDS->GDALDataset::SetMetadataItem("FOOTPRINT", osPolygon.c_str());
     }
 
@@ -2460,7 +2464,7 @@ GDALDataset *SENTINEL2Dataset::OpenL1CTile( const char* pszFilename,
     poDS->GDALDataset::SetMetadata(papszMD);
     CSLDestroy(papszMD);
 
-    if( osOriginalXML.size() )
+    if( !osOriginalXML.empty() )
     {
         char* apszXMLMD[2];
         apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
@@ -2604,8 +2608,9 @@ static bool SENTINEL2GetTileInfo(const char* pszFilename,
                                     memcpy(pnHeight, pabyData, 4);
                                     CPL_MSBPTR32(pnHeight);
                                 }
-                                if( pnWidth )
+                                if( pnWidth != NULL )
                                 {
+                                    //cppcheck-suppress nullPointer
                                     memcpy(pnWidth, pabyData+4, 4);
                                     CPL_MSBPTR32(pnWidth);
                                 }
@@ -2812,7 +2817,7 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2ASubdataset( GDALOpenInfo * poOpenInfo,
                 osName = "0" + osName;
             oSetBands.insert(osName);
         }
-        if( oSetBands.size() == 0 )
+        if( oSetBands.empty() )
             return NULL;
     }
     else
@@ -2820,7 +2825,7 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2ASubdataset( GDALOpenInfo * poOpenInfo,
         oSetBands = oMapResolutionsToBands[nSubDSPrecision];
     }
 
-    if( aosBands.size() == 0 )
+    if( aosBands.empty() )
     {
         for(std::set<CPLString>::const_iterator oIterBandnames = oSetBands.begin();
                                                 oIterBandnames != oSetBands.end();
@@ -2873,9 +2878,9 @@ GDALDataset *SENTINEL2Dataset::OpenL1C_L2ASubdataset( GDALOpenInfo * poOpenInfo,
         return NULL;
     }
 
-    if( osOriginalXML.size() )
+    if( !osOriginalXML.empty() )
     {
-        char* apszXMLMD[2];
+        char* apszXMLMD[2] = { NULL };
         apszXMLMD[0] = const_cast<char*>(osOriginalXML.c_str());
         apszXMLMD[1] = NULL;
         poDS->GDALDataset::SetMetadata(apszXMLMD, "xml:SENTINEL2");
@@ -3038,7 +3043,10 @@ SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
 
     /* Iterate over granule metadata to know the layer extent */
     /* and the location of each granule */
-    double dfMinX = 1e20, dfMinY = 1e20, dfMaxX = -1e20, dfMaxY = -1e20;
+    double dfMinX = 1.0e20;
+    double dfMinY = 1.0e20;
+    double dfMaxX = -1.0e20;
+    double dfMaxY = -1.0e20;
     std::vector<SENTINEL2GranuleInfo> aosGranuleInfoList;
     const int nDesiredResolution = (bIsPreview || bIsTCI) ? 0 : nSubDSPrecision;
 
@@ -3051,9 +3059,11 @@ SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
     for(size_t i=0;i<aosGranuleList.size();i++)
     {
         int nEPSGCode = 0;
-        double dfULX = 0.0, dfULY = 0.0;
+        double dfULX = 0.0;
+        double dfULY = 0.0;
         int nResolution = 0;
-        int nWidth = 0, nHeight = 0;
+        int nWidth = 0;
+        int nHeight = 0;
         if( SENTINEL2GetGranuleInfo(eLevel,
                                     aosGranuleList[i],
                                     nDesiredResolution,
@@ -3119,7 +3129,7 @@ SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
         CPLDebug("SENTINEL2", "Invalid EPSG code %d", nSubDSEPSGCode);
     }
 
-    double adfGeoTransform[6];
+    double adfGeoTransform[6] = { 0 };
     adfGeoTransform[0] = dfMinX;
     adfGeoTransform[1] = nSubDSPrecision;
     adfGeoTransform[2] = 0;
@@ -3139,9 +3149,9 @@ SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
 
     std::map<CPLString, GDALProxyPoolDataset*> oMapPVITile;
 
-    for(int nBand=1;nBand<=nBands;nBand++)
+    for( int nBand = 1; nBand <= nBands; nBand++ )
     {
-        VRTSourcedRasterBand* poBand;
+        VRTSourcedRasterBand* poBand = NULL;
 
         if( nBand != nAlphaBand )
         {
@@ -3234,7 +3244,7 @@ SENTINEL2Dataset* SENTINEL2Dataset::CreateL1CL2ADataset(
                 continue;
             }
 
-            GDALProxyPoolDataset* proxyDS;
+            GDALProxyPoolDataset* proxyDS = NULL;
             if( bIsPreview )
             {
                 proxyDS = oMapPVITile[osTile];
diff --git a/frmts/sgi/sgidataset.cpp b/frmts/sgi/sgidataset.cpp
index d116a19..2961794 100644
--- a/frmts/sgi/sgidataset.cpp
+++ b/frmts/sgi/sgidataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: sgidataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  SGI Image Driver
  * Purpose:  Implement SGI Image Support based on Paul Bourke's SGI Image code.
@@ -39,7 +38,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: sgidataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: sgidataset.cpp 37456 2017-02-25 18:35:03Z rouault $");
 
 struct ImageRec
 {
@@ -111,7 +110,10 @@ static void ConvertLong(GUInt32* array, GInt32 length)
 {
    GUInt32* ptr = reinterpret_cast<GUInt32*>( array );
    while(length--)
-     CPL_SWAP32PTR(ptr++);
+   {
+     CPL_SWAP32PTR(ptr);
+     ptr ++;
+   }
 }
 #else
 static void ConvertLong(GUInt32* /*array*/, GInt32 /*length */)
@@ -199,7 +201,7 @@ static CPLErr ImageGetRow(ImageRec* image, unsigned char* buf, int y, int z)
         else
         {
             pixel = *iPtr++;
-    	memset(oPtr, pixel, count);
+            memset(oPtr, pixel, count);
         }
         oPtr += count;
         xsizeCount += count;
@@ -210,7 +212,7 @@ static CPLErr ImageGetRow(ImageRec* image, unsigned char* buf, int y, int z)
 
 /************************************************************************/
 /* ==================================================================== */
-/*				SGIDataset				*/
+/*                              SGIDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -222,16 +224,16 @@ class SGIDataset : public GDALPamDataset
 
     VSILFILE*  fpImage;
 
-    int	   bGeoTransformValid;
+    int    bGeoTransformValid;
     double adfGeoTransform[6];
 
     ImageRec image;
 
 public:
     SGIDataset();
-    ~SGIDataset();
+    virtual ~SGIDataset();
 
-    virtual CPLErr GetGeoTransform(double*);
+    virtual CPLErr GetGeoTransform(double*) override;
     static GDALDataset* Open(GDALOpenInfo*);
     static GDALDataset *Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
@@ -251,17 +253,16 @@ class SGIRasterBand : public GDALPamRasterBand
 public:
     SGIRasterBand(SGIDataset*, int);
 
-    virtual CPLErr IReadBlock(int, int, void*);
-    virtual CPLErr IWriteBlock(int, int, void*);
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr IReadBlock(int, int, void*) override;
+    virtual CPLErr IWriteBlock(int, int, void*) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
-
 /************************************************************************/
 /*                           SGIRasterBand()                            */
 /************************************************************************/
 
-SGIRasterBand::SGIRasterBand(SGIDataset* poDSIn, int nBandIn)
+SGIRasterBand::SGIRasterBand( SGIDataset* poDSIn, int nBandIn )
 
 {
   poDS = poDSIn;
@@ -280,9 +281,9 @@ SGIRasterBand::SGIRasterBand(SGIDataset* poDSIn, int nBandIn)
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr SGIRasterBand::IReadBlock(CPL_UNUSED int nBlockXOff,
-                                 int nBlockYOff,
-				 void*  pImage)
+CPLErr SGIRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
+                                  int nBlockYOff,
+                                  void* pImage )
 {
     SGIDataset* poGDS = reinterpret_cast<SGIDataset *>( poDS );
 
@@ -460,13 +461,12 @@ GDALColorInterp SGIRasterBand::GetColorInterpretation()
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            SGIDataset()                              */
 /************************************************************************/
 
-SGIDataset::SGIDataset()
-  : fpImage(NULL),
+SGIDataset::SGIDataset() :
+    fpImage(NULL),
     bGeoTransformValid(FALSE)
 {
     adfGeoTransform[0] = 0.0;
@@ -533,14 +533,20 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
 
 {
 /* -------------------------------------------------------------------- */
-/*	First we check to see if the file has the expected header	*/
-/*	bytes.								*/
+/*      First we check to see if the file has the expected header       */
+/*      bytes.                                                          */
 /* -------------------------------------------------------------------- */
     if(poOpenInfo->nHeaderBytes < 12)
         return NULL;
 
     ImageRec tmpImage;
-    memcpy(&tmpImage, poOpenInfo->pabyHeader, 12);
+    memcpy(&tmpImage.imagic, poOpenInfo->pabyHeader + 0, 2);
+    memcpy(&tmpImage.type,   poOpenInfo->pabyHeader + 2, 1);
+    memcpy(&tmpImage.bpc,    poOpenInfo->pabyHeader + 3, 1);
+    memcpy(&tmpImage.dim,    poOpenInfo->pabyHeader + 4, 2);
+    memcpy(&tmpImage.xsize,  poOpenInfo->pabyHeader + 6, 2);
+    memcpy(&tmpImage.ysize,  poOpenInfo->pabyHeader + 8, 2);
+    memcpy(&tmpImage.zsize,  poOpenInfo->pabyHeader + 10, 2);
     tmpImage.Swap();
 
     if(tmpImage.imagic != 474)
@@ -586,7 +592,7 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
     }
 
 /* -------------------------------------------------------------------- */
-/*	Read pre-image data after ensuring the file is rewound.         */
+/*      Read pre-image data after ensuring the file is rewound.         */
 /* -------------------------------------------------------------------- */
     VSIFSeekL(poDS->fpImage, 0, SEEK_SET);
     if(VSIFReadL(reinterpret_cast<void*>( &(poDS->image) ),
@@ -613,7 +619,7 @@ GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)
         delete poDS;
         return NULL;
     }
-    poDS->nBands = MAX(1,poDS->image.zsize);
+    poDS->nBands = std::max(static_cast<GUInt16>(1), poDS->image.zsize);
     if (poDS->nBands > 256)
     {
         CPLError(CE_Failure, CPLE_OpenFailed,
@@ -772,8 +778,8 @@ GDALDataset *SGIDataset::Create( const char * pszFilename,
     GInt32 nIntValue = CPL_MSBWORD32(0);
     memcpy( abyHeader + 12, &nIntValue, 4 );
 
-    nIntValue = CPL_MSBWORD32(255);
-    memcpy( abyHeader + 16, &nIntValue, 4 );
+    GUInt32 nUIntValue = CPL_MSBWORD32(255);
+    memcpy( abyHeader + 16, &nUIntValue, 4 );
 
     VSIFWriteL( abyHeader, 1, 512, fp );
 
diff --git a/frmts/srtmhgt/srtmhgtdataset.cpp b/frmts/srtmhgt/srtmhgtdataset.cpp
index 48f573d..97f63a1 100644
--- a/frmts/srtmhgt/srtmhgtdataset.cpp
+++ b/frmts/srtmhgt/srtmhgtdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: srtmhgtdataset.cpp 34884 2016-08-03 16:05:33Z rouault $
  *
  * Project:  SRTM HGT Driver
  * Purpose:  SRTM HGT File Read Support.
@@ -41,11 +40,11 @@
 
 static const GInt16 SRTMHG_NODATA_VALUE = -32768;
 
-CPL_CVSID("$Id: srtmhgtdataset.cpp 34884 2016-08-03 16:05:33Z rouault $");
+CPL_CVSID("$Id: srtmhgtdataset.cpp 37802 2017-03-19 22:34:53Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*				SRTMHGTDataset				*/
+/*                              SRTMHGTDataset                          */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -61,17 +60,16 @@ class SRTMHGTDataset : public GDALPamDataset
 
   public:
     SRTMHGTDataset();
-    ~SRTMHGTDataset();
+    virtual ~SRTMHGTDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr GetGeoTransform(double*);
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform(double*) override;
 
     static int Identify( GDALOpenInfo * poOpenInfo );
     static GDALDataset* Open(GDALOpenInfo*);
     static GDALDataset* CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                                     int bStrict, char ** papszOptions,
                                     GDALProgressFunc pfnProgress, void * pProgressData );
-
 };
 
 /************************************************************************/
@@ -84,27 +82,27 @@ class SRTMHGTRasterBand : public GDALPamRasterBand
 {
     friend class SRTMHGTDataset;
 
-    int	        bNoDataSet;
-    double	dfNoDataValue;
+    int         bNoDataSet;
+    double      dfNoDataValue;
 
   public:
     SRTMHGTRasterBand(SRTMHGTDataset*, int);
 
-    virtual CPLErr IReadBlock(int, int, void*);
-    virtual CPLErr IWriteBlock(int nBlockXOff, int nBlockYOff, void* pImage);
+    virtual CPLErr IReadBlock(int, int, void*) override;
+    virtual CPLErr IWriteBlock(int nBlockXOff, int nBlockYOff, void* pImage) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual GDALColorInterp GetColorInterpretation() override;
 
-    virtual double  GetNoDataValue( int *pbSuccess = NULL );
+    virtual double  GetNoDataValue( int *pbSuccess = NULL ) override;
 
-    virtual const char* GetUnitType() { return "m"; }
+    virtual const char* GetUnitType() override { return "m"; }
 };
 
 /************************************************************************/
 /*                           SRTMHGTRasterBand()                            */
 /************************************************************************/
 
-SRTMHGTRasterBand::SRTMHGTRasterBand(SRTMHGTDataset* poDSIn, int nBandIn) :
+SRTMHGTRasterBand::SRTMHGTRasterBand( SRTMHGTDataset* poDSIn, int nBandIn ) :
     bNoDataSet(TRUE),
     dfNoDataValue(SRTMHG_NODATA_VALUE)
 {
@@ -119,22 +117,11 @@ SRTMHGTRasterBand::SRTMHGTRasterBand(SRTMHGTDataset* poDSIn, int nBandIn) :
 /*                             IReadBlock()                             */
 /************************************************************************/
 
-CPLErr SRTMHGTRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
+CPLErr SRTMHGTRasterBand::IReadBlock(int /*nBlockXOff*/, int nBlockYOff,
                                      void* pImage)
 {
   SRTMHGTDataset* poGDS = reinterpret_cast<SRTMHGTDataset *>( poDS );
 
-  CPLAssert(nBlockXOff == 0);
-  if(nBlockXOff != 0)
-  {
-      CPLError(CE_Failure, CPLE_NotSupported,
-               "unhandled nBlockXOff value : %d", nBlockXOff);
-      return CE_Failure;
-  }
-
-  if((poGDS == NULL) || (poGDS->fpImage == NULL))
-    return CE_Failure;
-
 /* -------------------------------------------------------------------- */
 /*      Load the desired data into the working buffer.                  */
 /* -------------------------------------------------------------------- */
@@ -151,18 +138,11 @@ CPLErr SRTMHGTRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
 /*                             IWriteBlock()                            */
 /************************************************************************/
 
-CPLErr SRTMHGTRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff, void* pImage)
+CPLErr SRTMHGTRasterBand::IWriteBlock(int /*nBlockXOff*/, int nBlockYOff, void* pImage)
 {
     SRTMHGTDataset* poGDS = reinterpret_cast<SRTMHGTDataset *>( poDS );
 
-    CPLAssert(nBlockXOff == 0);
-    if(nBlockXOff != 0)
-    {
-        CPLError(CE_Failure, CPLE_NotSupported, "unhandled nBlockXOff value : %d", nBlockXOff);
-        return CE_Failure;
-    }
-
-    if((poGDS == NULL) || (poGDS->fpImage == NULL) || (poGDS->eAccess != GA_Update))
+    if( poGDS->eAccess != GA_Update )
         return CE_Failure;
 
     VSIFSeekL(poGDS->fpImage, nBlockYOff*nBlockXSize*2, SEEK_SET);
@@ -207,7 +187,6 @@ GDALColorInterp SRTMHGTRasterBand::GetColorInterpretation()
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            SRTMHGTDataset()                              */
 /************************************************************************/
@@ -253,7 +232,7 @@ CPLErr SRTMHGTDataset::GetGeoTransform(double * padfTransform)
 const char *SRTMHGTDataset::GetProjectionRef()
 
 {
-    return( SRS_WKT_WGS84 );
+    return SRS_WKT_WGS84;
 }
 
 /************************************************************************/
@@ -266,18 +245,32 @@ int SRTMHGTDataset::Identify( GDALOpenInfo * poOpenInfo )
   const char* fileName = CPLGetFilename(poOpenInfo->pszFilename);
   if( strlen(fileName) < 11 || fileName[7] != '.' )
     return FALSE;
-  
+  if( !STARTS_WITH(fileName, "/vsizip/") &&
+      EQUAL(fileName + strlen(fileName) - strlen(".hgt.zip"), ".hgt.zip") )
+  {
+    CPLString osNewName("/vsizip/");
+    osNewName += poOpenInfo->pszFilename;
+    osNewName += "/";
+    osNewName += CPLString(fileName).substr(0, 7);
+    osNewName += ".hgt";
+    GDALOpenInfo oOpenInfo(osNewName, GA_ReadOnly);
+    return Identify(&oOpenInfo);
+  }
+
   if( !EQUAL(fileName + strlen(fileName) - strlen(".hgt"), ".hgt") )
     return FALSE;
+
 /* -------------------------------------------------------------------- */
-/*	We check the file size to see if it is 25,934,402 bytes	        */
-/*	(SRTM 1) or 2,884,802 bytes (SRTM 3)				*/
+/*      We check the file size to see if it is                          */
+/*      SRTM1 (below or above lat 50) or SRTM 3                         */
 /* -------------------------------------------------------------------- */
   VSIStatBufL fileStat;
 
   if(VSIStatL(poOpenInfo->pszFilename, &fileStat) != 0)
       return FALSE;
-  if(fileStat.st_size != 25934402 && fileStat.st_size != 2884802)
+  if(fileStat.st_size != 3601 * 3601 * 2 &&
+     fileStat.st_size != 1801 * 3601 * 2 &&
+     fileStat.st_size != 1201 * 1201 * 2 )
       return FALSE;
 
   return TRUE;
@@ -293,12 +286,24 @@ GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo)
       return NULL;
 
   const char* fileName = CPLGetFilename(poOpenInfo->pszFilename);
+  if( !STARTS_WITH(fileName, "/vsizip/") &&
+      EQUAL(fileName + strlen(fileName) - strlen(".hgt.zip"), ".hgt.zip") )
+  {
+      CPLString osFilename ("/vsizip/");
+      osFilename += poOpenInfo->pszFilename;
+      osFilename += "/";
+      osFilename += CPLString(fileName).substr(0, 7);
+      osFilename += ".hgt";
+      GDALOpenInfo oOpenInfo(osFilename, poOpenInfo->eAccess);
+      return Open(&oOpenInfo);
+  }
 
   char latLonValueString[4];
   memset(latLonValueString, 0, 4);
   strncpy(latLonValueString, &fileName[1], 2);
   int southWestLat = atoi(latLonValueString);
   memset(latLonValueString, 0, 4);
+  // cppcheck-suppress redundantCopy
   strncpy(latLonValueString, &fileName[4], 3);
   int southWestLon = atoi(latLonValueString);
 
@@ -321,20 +326,8 @@ GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo)
 /* -------------------------------------------------------------------- */
   SRTMHGTDataset* poDS  = new SRTMHGTDataset();
 
-/* -------------------------------------------------------------------- */
-/*      Open the file using the large file api.                         */
-/* -------------------------------------------------------------------- */
-  poDS->fpImage = VSIFOpenL(
-      poOpenInfo->pszFilename,
-      (poOpenInfo->eAccess == GA_Update) ? "rb+" : "rb" );
-  if(poDS->fpImage == NULL)
-  {
-      CPLError( CE_Failure, CPLE_OpenFailed,
-                "VSIFOpenL(%s) failed unexpectedly in srtmhgtdataset.cpp",
-                poOpenInfo->pszFilename );
-      delete poDS;
-      return NULL;
-  }
+  poDS->fpImage = poOpenInfo->fpL;
+  poOpenInfo->fpL = NULL;
 
   VSIStatBufL fileStat;
   if(VSIStatL(poOpenInfo->pszFilename, &fileStat) != 0)
@@ -342,30 +335,47 @@ GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo)
       delete poDS;
       return NULL;
   }
-  const int numPixels = (fileStat.st_size == 25934402) ? 3601 : /* 2884802 */ 1201;
+
+  int numPixels_x, numPixels_y;
+
+  switch (fileStat.st_size) {
+  case 3601 * 3601 * 2:
+    numPixels_x = numPixels_y = 3601;
+    break;
+  case 1801 * 3601 * 2:
+    numPixels_x = 1801;
+    numPixels_y = 3601;
+    break;
+  case 1201 * 1201 * 2:
+    numPixels_x = numPixels_y = 1201;
+    break;
+  default:
+    numPixels_x = numPixels_y = 0;
+    break;
+  }    
 
   poDS->eAccess = poOpenInfo->eAccess;
 #ifdef CPL_LSB
   if(poDS->eAccess == GA_Update)
   {
       poDS->panBuffer
-          = reinterpret_cast<GInt16 *>( CPLMalloc(numPixels * sizeof(GInt16)) );
+          = reinterpret_cast<GInt16 *>( CPLMalloc(numPixels_x * sizeof(GInt16)) );
   }
 #endif
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
 /* -------------------------------------------------------------------- */
-  poDS->nRasterXSize = numPixels;
-  poDS->nRasterYSize = numPixels;
+  poDS->nRasterXSize = numPixels_x;
+  poDS->nRasterYSize = numPixels_y;
   poDS->nBands = 1;
 
-  poDS->adfGeoTransform[0] = southWestLon - 0.5 / (numPixels - 1);
-  poDS->adfGeoTransform[1] = 1.0 / (numPixels-1);
-  poDS->adfGeoTransform[2] = 0.0000000000;
-  poDS->adfGeoTransform[3] = southWestLat + 1 + 0.5 / (numPixels - 1);
-  poDS->adfGeoTransform[4] = 0.0000000000;
-  poDS->adfGeoTransform[5] = -1.0 / (numPixels-1);
+  poDS->adfGeoTransform[0] = southWestLon - 0.5 / (numPixels_x - 1);
+  poDS->adfGeoTransform[1] = 1.0 / (numPixels_x-1);
+  poDS->adfGeoTransform[2] = 0.0;
+  poDS->adfGeoTransform[3] = southWestLat + 1 + 0.5 / (numPixels_y - 1);
+  poDS->adfGeoTransform[4] = 0.0;
+  poDS->adfGeoTransform[5] = -1.0 / (numPixels_y-1);
 
   poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT );
 
@@ -396,13 +406,10 @@ GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo)
 GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
                                           GDALDataset *poSrcDS,
                                           int bStrict,
-                                          CPL_UNUSED char ** papszOptions,
+                                          char ** /* papszOptions*/,
                                           GDALProgressFunc pfnProgress,
                                           void * pProgressData )
 {
-    if( pfnProgress && !pfnProgress( 0.0, NULL, pProgressData ) )
-        return NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Some some rudimentary checks                                    */
 /* -------------------------------------------------------------------- */
@@ -475,10 +482,12 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
     const int nXSize = poSrcDS->GetRasterXSize();
     const int nYSize = poSrcDS->GetRasterYSize();
 
-    if (!((nXSize == 1201 && nYSize == 1201) || (nXSize == 3601 && nYSize == 3601)))
+    if (!((nXSize == 1201 && nYSize == 1201) ||
+          (nXSize == 3601 && nYSize == 3601) ||
+          (nXSize == 1801 && nYSize == 3601)))
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Image dimensions should be 1201x1201 or 3601x3601.");
+                  "Image dimensions should be 1201x1201, 3601x3601 or 1801x3601.");
         return NULL;
     }
 
@@ -486,11 +495,13 @@ GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
 /*      Check filename.                                                 */
 /* -------------------------------------------------------------------- */
     char expectedFileName[12];
-    snprintf(expectedFileName, sizeof(expectedFileName), "%c%02d%c%03d.HGT",
+
+    CPLsnprintf(expectedFileName, sizeof(expectedFileName), "%c%02d%c%03d.HGT",
              (nLLOriginLat >= 0) ? 'N' : 'S',
              (nLLOriginLat >= 0) ? nLLOriginLat : -nLLOriginLat,
              (nLLOriginLong >= 0) ? 'E' : 'W',
              (nLLOriginLong >= 0) ? nLLOriginLong : -nLLOriginLong);
+
     if (!EQUAL(expectedFileName, CPLGetFilename(pszFilename)))
     {
         CPLError( CE_Warning, CPLE_AppDefined,
diff --git a/frmts/terragen/terragendataset.cpp b/frmts/terragen/terragendataset.cpp
index 1750a62..8acfc9f 100644
--- a/frmts/terragen/terragendataset.cpp
+++ b/frmts/terragen/terragendataset.cpp
@@ -8,12 +8,12 @@
  * Portions of this module derived from GDAL drivers by
  * Frank Warmerdam, see http://www.gdal.org
 
- rcg	apr 19/06	Fixed bug with hf size being misread by one
-					if xpts/ypts tags not included in file.
-					Added Create() support.
-					Treat pixels as points.
+ rcg    apr 19/06       Fixed bug with hf size being misread by one
+                        if xpts/ypts tags not included in file.
+                        Added Create() support.
+                        Treat pixels as points.
 
- rcg	jun  6/07	Better heightscale/baseheight determination
+ rcg    jun  6/07       Better heightscale/baseheight determination
                     when writing.
 
  *
@@ -41,64 +41,64 @@
  */
 
 /*
-	Terragen format notes:
-
-	Based on official Planetside specs.
-
-	All distances along all three axes are in
-	terrain units, which are 30m by default.
-	If a SCAL chunk is present, however, it
-	can indicate something other than 30.
-	Note that uniform scaling should be used.
-
-	The offset (base height) in the ALTW chunk
-	is in terrain units, and the scale (height scale)
-	is a normalized value using unsigned 16-bit notation.
-	The physical terrain value for a read pixel is
-		hv' = hv * scale / 65536 + offset.
-		It still needs to be scaled by SCAL to
-		get to meters.
-
-	For writing:
-			SCAL = gridpost distance in meters
-			hv_px = hv_m / SCAL
-			span_px = span_m / SCAL
-			offset = see TerragenDataset::write_header()
-			scale = see TerragenDataset::write_header()
-			physical hv =
-				(hv_px - offset) * 65536.0/scale
-
-
-	We tell callers that:
-
-		Elevations are Int16 when reading,
-		and Float32 when writing. We need logical
-		elevations when writing so that we can
-		encode them with as much precision as possible
-		when going down to physical 16-bit ints.
-		Implementing band::SetScale/SetOffset won't work because
-		it requires callers to know format write details.
-		So we've added two Create() options that let the
-		caller tell us the span's logical extent, and with
-		those two values we can convert to physical pixels.
-
-		band::GetUnitType() returns meters.
-		band::GetScale() returns SCAL * (scale/65536)
-		band::GetOffset() returns SCAL * offset
-		ds::GetProjectionRef() returns a local CS
-			using meters.
-		ds::GetGeoTransform() returns a scale matrix
-			having SCAL sx,sy members.
-
-		ds::SetGeoTransform() lets us establish the
-			size of ground pixels.
-		ds::SetProjection() lets us establish what
-			units ground measures are in (also needed
-			to calc the size of ground pixels).
-		band::SetUnitType() tells us what units
-			the given Float32 elevations are in.
-		band::SetScale() is unused.
-		band::SetOffset() is unused.
+        Terragen format notes:
+
+        Based on official Planetside specs.
+
+        All distances along all three axes are in
+        terrain units, which are 30m by default.
+        If a SCAL chunk is present, however, it
+        can indicate something other than 30.
+        Note that uniform scaling should be used.
+
+        The offset (base height) in the ALTW chunk
+        is in terrain units, and the scale (height scale)
+        is a normalized value using unsigned 16-bit notation.
+        The physical terrain value for a read pixel is
+        hv' = hv * scale / 65536 + offset.
+        It still needs to be scaled by SCAL to
+        get to meters.
+
+        For writing:
+
+        SCAL = gridpost distance in meters
+        hv_px = hv_m / SCAL
+        span_px = span_m / SCAL
+        offset = see TerragenDataset::write_header()
+        scale = see TerragenDataset::write_header()
+        physical hv =
+          (hv_px - offset) * 65536.0/scale
+
+        We tell callers that:
+
+        Elevations are Int16 when reading,
+        and Float32 when writing. We need logical
+        elevations when writing so that we can
+        encode them with as much precision as possible
+        when going down to physical 16-bit ints.
+        Implementing band::SetScale/SetOffset won't work because
+        it requires callers to know format write details.
+        So we've added two Create() options that let the
+        caller tell us the span's logical extent, and with
+        those two values we can convert to physical pixels.
+
+        band::GetUnitType() returns meters.
+        band::GetScale() returns SCAL * (scale/65536)
+        band::GetOffset() returns SCAL * offset
+        ds::GetProjectionRef() returns a local CS
+                using meters.
+        ds::GetGeoTransform() returns a scale matrix
+                having SCAL sx,sy members.
+
+        ds::SetGeoTransform() lets us establish the
+                size of ground pixels.
+        ds::SetProjection() lets us establish what
+                units ground measures are in (also needed
+                to calc the size of ground pixels).
+        band::SetUnitType() tells us what units
+                the given Float32 elevations are in.
+        band::SetScale() is unused.
+        band::SetOffset() is unused.
 */
 
 #include "cpl_string.h"
@@ -110,14 +110,14 @@
 
 #include <algorithm>
 
-// CPL_CVSID("$Id: terragendataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+// CPL_CVSID("$Id: terragendataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 const double kdEarthCircumPolar = 40007849;
 const double kdEarthCircumEquat = 40075004;
 
 static double average(double a, double b)
 {
-	return 0.5 * (a + b);
+    return 0.5 * (a + b);
 }
 
 static double degrees_to_radians(double d)
@@ -131,10 +131,9 @@ static bool approx_equal(double a, double b)
     return std::abs(a-b) <= epsilon;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
-/*				TerragenDataset				*/
+/*                              TerragenDataset                         */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -144,7 +143,7 @@ class TerragenDataset : public GDALPamDataset
 {
     friend class TerragenRasterBand;
 
-    double		m_dScale,
+    double              m_dScale,
                         m_dOffset,
                         m_dSCAL, // 30.0 normally, from SCAL chunk
                         m_adfTransform[6],
@@ -156,47 +155,47 @@ class TerragenDataset : public GDALPamDataset
                         m_span_px[2];
 
     VSILFILE*           m_fp;
-    vsi_l_offset	m_nDataOffset;
+    vsi_l_offset        m_nDataOffset;
 
-    GInt16		m_nHeightScale;
-    GInt16		m_nBaseHeight;
+    GInt16              m_nHeightScale;
+    GInt16              m_nBaseHeight;
 
-    char*		m_pszFilename;
-    char*		m_pszProjection;
-    char		m_szUnits[32];
+    char*               m_pszFilename;
+    char*               m_pszProjection;
+    char                m_szUnits[32];
 
-    bool		m_bIsGeo;
+    bool                m_bIsGeo;
 
     int         LoadFromFile();
 
-	public:
-		TerragenDataset();
-		~TerragenDataset();
-
-		static GDALDataset* Open( GDALOpenInfo* );
-		static GDALDataset* Create( const char* pszFilename,
-                                            int nXSize, int nYSize, int nBands,
-                                            GDALDataType eType, char** papszOptions );
-
-		virtual CPLErr 	GetGeoTransform( double* );
-		virtual const char*	GetProjectionRef(void);
-		virtual CPLErr SetProjection( const char * );
-		virtual CPLErr SetGeoTransform( double * );
-
-	protected:
-		bool get(GInt16&);
-		bool get(GUInt16&);
-		bool get(float&);
-		bool put(GInt16);
-		bool put(float);
-		bool skip(size_t n) { return ( 0 == VSIFSeekL(m_fp, n, SEEK_CUR) ); }
-		bool pad(size_t n) { return skip( n ); }
-
-		bool read_next_tag(char*);
-		bool write_next_tag(const char*);
-		bool tag_is(const char* szTag, const char*);
-
-		bool write_header(void);
+  public:
+    TerragenDataset();
+    virtual ~TerragenDataset();
+
+    static GDALDataset* Open( GDALOpenInfo* );
+    static GDALDataset* Create( const char* pszFilename,
+                                int nXSize, int nYSize, int nBands,
+                                GDALDataType eType, char** papszOptions );
+
+    virtual CPLErr      GetGeoTransform( double* ) override;
+    virtual const char* GetProjectionRef(void) override;
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
+
+ protected:
+    bool get(GInt16&);
+    bool get(GUInt16&);
+    bool get(float&);
+    bool put(GInt16);
+    bool put(float);
+    bool skip(size_t n) { return 0 == VSIFSeekL(m_fp, n, SEEK_CUR); }
+    bool pad(size_t n) { return skip( n ); }
+
+    bool read_next_tag(char*);
+    bool write_next_tag(const char*);
+    static bool tag_is(const char* szTag, const char*);
+
+    bool write_header(void);
 };
 
 /************************************************************************/
@@ -209,50 +208,47 @@ class TerragenRasterBand : public GDALPamRasterBand
 {
     friend class TerragenDataset;
 
-	void*	        m_pvLine;
-	bool            m_bFirstTime;
+    void*               m_pvLine;
+    bool            m_bFirstTime;
 
 public:
 
     explicit TerragenRasterBand(TerragenDataset*);
-	virtual ~TerragenRasterBand()
-	{
-		if(m_pvLine != NULL)
-			CPLFree(m_pvLine);
-	}
+    virtual ~TerragenRasterBand()
+    {
+        if(m_pvLine != NULL)
+            CPLFree(m_pvLine);
+    }
 
     // Geomeasure support.
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual const char* GetUnitType();
-    virtual double GetOffset(int* pbSuccess = NULL);
-    virtual double GetScale(int* pbSuccess = NULL);
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual const char* GetUnitType() override;
+    virtual double GetOffset(int* pbSuccess = NULL) override;
+    virtual double GetScale(int* pbSuccess = NULL) override;
 
-    virtual CPLErr IWriteBlock( int, int, void * );
-    virtual CPLErr SetUnitType( const char* );
+    virtual CPLErr IWriteBlock( int, int, void * ) override;
+    virtual CPLErr SetUnitType( const char* ) override;
 };
 
-
 /************************************************************************/
 /*                         TerragenRasterBand()                         */
 /************************************************************************/
 
-TerragenRasterBand::TerragenRasterBand( TerragenDataset *poDSIn )
+TerragenRasterBand::TerragenRasterBand( TerragenDataset *poDSIn ) :
+    m_pvLine(CPLMalloc( sizeof(GInt16) * poDSIn->GetRasterXSize() )),
+    m_bFirstTime(true)
 {
-    m_bFirstTime = true;
     poDS = poDSIn;
     nBand = 1;
 
     eDataType = poDSIn->GetAccess() == GA_ReadOnly
-		? GDT_Int16
-		: GDT_Float32;
+        ? GDT_Int16
+        : GDT_Float32;
 
     nBlockXSize = poDSIn->GetRasterXSize();
     nBlockYSize = 1;
-
-    m_pvLine = CPLMalloc( sizeof(GInt16) * nBlockXSize );
 }
 
-
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
@@ -269,15 +265,15 @@ CPLErr TerragenRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
 
 /* -------------------------------------------------------------------- */
 /*      Seek to scanline.
-	Terragen is a bottom-top format, so we have to
-	invert the row location.
+        Terragen is a bottom-top format, so we have to
+        invert the row location.
  -------------------------------------------------------------------- */
     const size_t rowbytes = nBlockXSize * sizeof(GInt16);
 
     if(0 != VSIFSeekL(
            ds.m_fp,
            ds.m_nDataOffset +
-			  (ds.GetRasterYSize() -1 - nBlockYOff) * rowbytes,
+           (ds.GetRasterYSize() -1 - nBlockYOff) * rowbytes,
            SEEK_SET))
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -285,7 +281,6 @@ CPLErr TerragenRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
         return CE_Failure;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Read the scanline into the line buffer.                        */
 /* -------------------------------------------------------------------- */
@@ -307,21 +302,18 @@ CPLErr TerragenRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
     return CE_None;
 }
 
-
-
 /************************************************************************/
 /*                            GetUnitType()                             */
 /************************************************************************/
 const char *TerragenRasterBand::GetUnitType()
 {
-	// todo: Return elevation units.
-	// For Terragen documents, it's the same as the ground units.
+    // todo: Return elevation units.
+    // For Terragen documents, it's the same as the ground units.
     TerragenDataset *poGDS = reinterpret_cast<TerragenDataset *>( poDS );
 
     return poGDS->m_szUnits;
 }
 
-
 /************************************************************************/
 /*                              GetScale()                              */
 /************************************************************************/
@@ -348,8 +340,6 @@ double TerragenRasterBand::GetOffset(int* pbSuccess)
     return ds.m_dOffset;
 }
 
-
-
 /************************************************************************/
 /*                             IWriteBlock()                            */
 /************************************************************************/
@@ -370,20 +360,20 @@ CPLErr TerragenRasterBand::IWriteBlock
     TerragenDataset& ds = *reinterpret_cast<TerragenDataset *>(poDS );
     if( m_bFirstTime )
     {
-		m_bFirstTime = false;
-		ds.write_header();
-		ds.m_nDataOffset = VSIFTellL(ds.m_fp);
+        m_bFirstTime = false;
+        ds.write_header();
+        ds.m_nDataOffset = VSIFTellL(ds.m_fp);
     }
-	const size_t rowbytes = nBlockXSize * pixelsize;
+    const size_t rowbytes = nBlockXSize * pixelsize;
 
     GInt16* pLine = reinterpret_cast<GInt16 *>( m_pvLine );
 
-	if(0 == VSIFSeekL(
-       ds.m_fp,
-       ds.m_nDataOffset +
-		// Terragen is Y inverted.
-		(ds.GetRasterYSize()-1-nBlockYOff) * rowbytes,
-       SEEK_SET))
+    if(0 == VSIFSeekL(
+           ds.m_fp,
+           ds.m_nDataOffset +
+           // Terragen is Y inverted.
+           (ds.GetRasterYSize()-1-nBlockYOff) * rowbytes,
+           SEEK_SET))
     {
         // Convert each float32 to int16.
         float* pfImage = reinterpret_cast<float *>( pImage );
@@ -397,37 +387,34 @@ CPLErr TerragenRasterBand::IWriteBlock
         }
 
 #ifdef CPL_MSB
-		GDALSwapWords( m_pvLine, pixelsize, nBlockXSize, pixelsize );
+        GDALSwapWords( m_pvLine, pixelsize, nBlockXSize, pixelsize );
 #endif
-		if(1 == VSIFWriteL(m_pvLine, rowbytes, 1, ds.m_fp))
-			return CE_None;
+        if(1 == VSIFWriteL(m_pvLine, rowbytes, 1, ds.m_fp))
+            return CE_None;
     }
 
     return CE_Failure;
 }
 
-
 CPLErr TerragenRasterBand::SetUnitType( const char* psz )
 {
     TerragenDataset& ds = *reinterpret_cast<TerragenDataset *>( poDS );
 
-	if(EQUAL(psz, "m"))
-		ds.m_dMetersPerElevUnit = 1.0;
-	else if(EQUAL(psz, "ft"))
-		ds.m_dMetersPerElevUnit = 0.3048;
-	else if(EQUAL(psz, "sft"))
-		ds.m_dMetersPerElevUnit = 1200.0 / 3937.0;
-	else
-		return CE_Failure;
+    if(EQUAL(psz, "m"))
+        ds.m_dMetersPerElevUnit = 1.0;
+    else if(EQUAL(psz, "ft"))
+        ds.m_dMetersPerElevUnit = 0.3048;
+    else if(EQUAL(psz, "sft"))
+        ds.m_dMetersPerElevUnit = 1200.0 / 3937.0;
+    else
+        return CE_Failure;
 
-	return CE_None;
+    return CE_None;
 }
 
-
-
 /************************************************************************/
 /* ==================================================================== */
-/*				TerragenDataset		                                    */
+/*                          TerragenDataset                             */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -436,10 +423,19 @@ CPLErr TerragenRasterBand::SetUnitType( const char* psz )
 /************************************************************************/
 
 TerragenDataset::TerragenDataset() :
-    m_dScale(0.0), m_dOffset(0.0), m_dSCAL(30.0), m_dGroundScale(0.0),
-    m_dMetersPerGroundUnit(1.0), m_dMetersPerElevUnit(0.0), m_fp(NULL),
-    m_nDataOffset(0),  m_nHeightScale(0), m_nBaseHeight(0), m_pszFilename(NULL),
-    m_pszProjection(NULL), m_bIsGeo(false)
+    m_dScale(0.0),
+    m_dOffset(0.0),
+    m_dSCAL(30.0),
+    m_dGroundScale(0.0),
+    m_dMetersPerGroundUnit(1.0),
+    m_dMetersPerElevUnit(0.0),
+    m_fp(NULL),
+    m_nDataOffset(0),
+    m_nHeightScale(0),
+    m_nBaseHeight(0),
+    m_pszFilename(NULL),
+    m_pszProjection(NULL),
+    m_bIsGeo(false)
 {
     m_dLogSpan[0] = 0.0;
     m_dLogSpan[1] = 0.0;
@@ -450,6 +446,11 @@ TerragenDataset::TerragenDataset() :
     m_adfTransform[3] = 0.0;
     m_adfTransform[4] = 0.0;
     m_adfTransform[5] = m_dSCAL;
+    m_span_m[0] = 0.0;
+    m_span_m[1] = 0.0;
+    m_span_px[0] = 0.0;
+    m_span_px[1] = 0.0;
+    memset( m_szUnits, 0, sizeof(m_szUnits) );
 }
 
 /************************************************************************/
@@ -468,10 +469,10 @@ TerragenDataset::~TerragenDataset()
         VSIFCloseL( m_fp );
 }
 
-
 bool TerragenDataset::write_header()
 {
     char szHeader[16];
+    // cppcheck-suppress bufferNotZeroTerminated
     memcpy(szHeader, "TERRAGENTERRAIN ", sizeof(szHeader));
 
     if(1 != VSIFWriteL( reinterpret_cast<void *>( szHeader ), sizeof(szHeader), 1, m_fp ))
@@ -506,57 +507,56 @@ bool TerragenDataset::write_header()
         pad( sizeof(GInt16) );
     }
 
-	if(m_bIsGeo)
+    if(m_bIsGeo)
     {
-		/*
-			With a geographic projection (degrees),
-			m_dGroundScale will be in degrees and
-			m_dMetersPerGroundUnit is undefined.
-			So we're going to estimate a m_dMetersPerGroundUnit
-			value here (i.e., meters per degree).
-
-			We figure out the degree size of one
-			pixel, and then the latitude degrees
-			of the heightfield's center. The circumference of
-			the latitude's great circle lets us know how
-			wide the pixel is in meters, and we
-			average that with the pixel's meter breadth,
-			which is based on the polar circumference.
-		*/
-
-		/*const double m_dDegLongPerPixel =
-			fabs(m_adfTransform[1]);*/
+        /*
+          With a geographic projection (degrees),
+          m_dGroundScale will be in degrees and
+          m_dMetersPerGroundUnit is undefined.
+          So we're going to estimate a m_dMetersPerGroundUnit
+          value here (i.e., meters per degree).
+
+          We figure out the degree size of one
+          pixel, and then the latitude degrees
+          of the heightfield's center. The circumference of
+          the latitude's great circle lets us know how
+          wide the pixel is in meters, and we
+          average that with the pixel's meter breadth,
+          which is based on the polar circumference.
+        */
+
+        /* const double m_dDegLongPerPixel =
+              fabs(m_adfTransform[1]); */
 
         const double m_dDegLatPerPixel = std::abs(m_adfTransform[5]);
 
-		/*const double m_dCenterLongitude =
-			m_adfTransform[0] +
-			(0.5 * m_dDegLongPerPixel * (nXSize-1));*/
-
-		const double m_dCenterLatitude =
-			m_adfTransform[3] +
-			(0.5 * m_dDegLatPerPixel * (nYSize-1));
+        /* const double m_dCenterLongitude =
+              m_adfTransform[0] +
+              (0.5 * m_dDegLongPerPixel * (nXSize-1)); */
 
+        const double m_dCenterLatitude =
+            m_adfTransform[3] +
+            (0.5 * m_dDegLatPerPixel * (nYSize-1));
 
         const double dLatCircum = kdEarthCircumEquat
             * std::sin( degrees_to_radians( 90.0 - m_dCenterLatitude ) );
 
-		const double dMetersPerDegLongitude = dLatCircum / 360;
-		/*const double dMetersPerPixelX =
-			(m_dDegLongPerPixel / 360) * dLatCircum;*/
+        const double dMetersPerDegLongitude = dLatCircum / 360;
+        /* const double dMetersPerPixelX =
+              (m_dDegLongPerPixel / 360) * dLatCircum; */
 
-		const double dMetersPerDegLatitude =
-			kdEarthCircumPolar / 360;
-		/*const double dMetersPerPixelY =
-			(m_dDegLatPerPixel / 360) * kdEarthCircumPolar;*/
+        const double dMetersPerDegLatitude =
+            kdEarthCircumPolar / 360;
+        /* const double dMetersPerPixelY =
+              (m_dDegLatPerPixel / 360) * kdEarthCircumPolar; */
 
-		m_dMetersPerGroundUnit =
-			average(dMetersPerDegLongitude, dMetersPerDegLatitude);
+        m_dMetersPerGroundUnit =
+            average(dMetersPerDegLongitude, dMetersPerDegLatitude);
     }
 
-	m_dSCAL = m_dGroundScale * m_dMetersPerGroundUnit;
+    m_dSCAL = m_dGroundScale * m_dMetersPerGroundUnit;
 
-	if(m_dSCAL != 30.0)
+    if(m_dSCAL != 30.0)
     {
         const float sc = static_cast<float>( m_dSCAL );
         write_next_tag( "SCAL" );
@@ -576,26 +576,26 @@ bool TerragenDataset::write_header()
         return false;
     }
 
-	// Compute physical scales and offsets.
-	m_span_m[0] = m_dLogSpan[0] * m_dMetersPerElevUnit;
-	m_span_m[1] = m_dLogSpan[1] * m_dMetersPerElevUnit;
+    // Compute physical scales and offsets.
+    m_span_m[0] = m_dLogSpan[0] * m_dMetersPerElevUnit;
+    m_span_m[1] = m_dLogSpan[1] * m_dMetersPerElevUnit;
 
-	m_span_px[0] = m_span_m[0] / m_dSCAL;
-	m_span_px[1] = m_span_m[1] / m_dSCAL;
+    m_span_px[0] = m_span_m[0] / m_dSCAL;
+    m_span_px[1] = m_span_m[1] / m_dSCAL;
 
-	const double span_px = m_span_px[1] - m_span_px[0];
+    const double span_px = m_span_px[1] - m_span_px[0];
     m_nHeightScale = static_cast<GInt16>( span_px );
-	if(m_nHeightScale == 0)
-		m_nHeightScale++;
+    if(m_nHeightScale == 0)
+        m_nHeightScale++;
 
 // TODO(schwehr): Make static functions.
 #define P2L_PX(n, hs, bh) (static_cast<double>( n ) / 65536.0 * (hs) + (bh))
 
 #define L2P_PX(n, hs, bh) (static_cast<int>( ((n)-(bh)) * 65536.0 / (hs) ) )
 
-	// Increase the heightscale until the physical span
-	// fits within a 16-bit range. The smaller the logical span,
-	// the more necessary this becomes.
+    // Increase the heightscale until the physical span
+    // fits within a 16-bit range. The smaller the logical span,
+    // the more necessary this becomes.
     int hs = m_nHeightScale;
     int bh = 0;
     for( ; hs <= 32767; hs++)
@@ -608,19 +608,19 @@ bool TerragenDataset::write_header()
             const int nPeak = L2P_PX(m_span_px[1], hs, bh);
             if(nPeak > 32767) continue;
 
-			// now see how closely the baseheight gets
-			// to the pixel span.
+            // now see how closely the baseheight gets
+            // to the pixel span.
             const double d = P2L_PX(nValley, hs, bh);
             const double delta = std::abs(d - m_span_px[0]);
-			if(delta < prevdelta) // Converging?
-				prevdelta = delta;
-			else
-			{
-				// We're diverging, so use the previous bh
-				// and stop looking.
-				bh--;
-				break;
-			}
+            if(delta < prevdelta) // Converging?
+                prevdelta = delta;
+            else
+            {
+                // We're diverging, so use the previous bh
+                // and stop looking.
+                bh--;
+                break;
+            }
         }
         if(bh != 32768) break;
     }
@@ -638,19 +638,15 @@ bool TerragenDataset::write_header()
     m_nHeightScale = static_cast<GInt16>( hs );
     m_nBaseHeight = static_cast<GInt16>( bh );
 
-
-	// m_nHeightScale is the one that gives us the
-	// widest use of the 16-bit space. However, there
-	// might be larger heightscales that, even though
-	// the reduce the space usage, give us a better fit
-	// for preserving the span extents.
-
+    // m_nHeightScale is the one that gives us the
+    // widest use of the 16-bit space. However, there
+    // might be larger heightscales that, even though
+    // the reduce the space usage, give us a better fit
+    // for preserving the span extents.
 
     return put(m_nHeightScale) && put(m_nBaseHeight);
 }
 
-
-
 /************************************************************************/
 /*                                get()                                 */
 /************************************************************************/
@@ -665,7 +661,6 @@ bool TerragenDataset::get(GInt16& value)
     return false;
 }
 
-
 bool TerragenDataset::get(GUInt16& value)
 {
     if(1 == VSIFReadL(&value, sizeof(value), 1, m_fp))
@@ -676,7 +671,6 @@ bool TerragenDataset::get(GUInt16& value)
     return false;
 }
 
-
 bool TerragenDataset::get(float& value)
 {
     if(1 == VSIFReadL(&value, sizeof(value), 1, m_fp))
@@ -687,7 +681,6 @@ bool TerragenDataset::get(float& value)
     return false;
 }
 
-
 /************************************************************************/
 /*                                put()                                 */
 /************************************************************************/
@@ -698,7 +691,6 @@ bool TerragenDataset::put(GInt16 n)
     return 1 == VSIFWriteL(&n, sizeof(n), 1, m_fp);
 }
 
-
 bool TerragenDataset::put(float f)
 {
     CPL_LSBPTR32(&f);
@@ -709,27 +701,22 @@ bool TerragenDataset::put(float f)
 /*                              tag stuff                               */
 /************************************************************************/
 
-
 bool TerragenDataset::read_next_tag(char* szTag)
 {
     return 1 == VSIFReadL(szTag, 4, 1, m_fp);
 }
 
-
 bool TerragenDataset::write_next_tag(const char* szTag)
 {
   return 1 == VSIFWriteL(
       reinterpret_cast<void *>( const_cast<char *> ( szTag ) ), 4, 1, m_fp);
 }
 
-
 bool TerragenDataset::tag_is(const char* szTag, const char* sz)
 {
     return 0 == memcmp(szTag, sz, 4);
 }
 
-
-
 /************************************************************************/
 /*                            LoadFromFile()                            */
 /************************************************************************/
@@ -776,7 +763,7 @@ int TerragenDataset::LoadFromFile()
 
         if( tag_is(szTag, "SCAL") )
         {
-            float sc[3];
+            float sc[3] = { 0.0f };
             get(sc[0]);
             get(sc[1]);
             get(sc[2]);
@@ -811,7 +798,6 @@ int TerragenDataset::LoadFromFile()
         }
     }
 
-
     if(xpts == 0 || ypts == 0 || m_nDataOffset == 0)
         return FALSE;
 
@@ -836,7 +822,7 @@ int TerragenDataset::LoadFromFile()
     m_adfTransform[5] = m_dSCAL;
 
 /* -------------------------------------------------------------------- */
-/*      Set projection.							*/
+/*      Set projection.                                                 */
 /* -------------------------------------------------------------------- */
     // Terragen files as of Apr 2006 are partially georeferenced,
     // we can declare a local coordsys that uses meters.
@@ -896,7 +882,7 @@ CPLErr TerragenDataset::SetProjection( const char * pszNewProjection )
 /*                          GetProjectionRef()                          */
 /************************************************************************/
 
-const char*	TerragenDataset::GetProjectionRef(void)
+const char* TerragenDataset::GetProjectionRef(void)
 {
     if(m_pszProjection == NULL )
         return "";
@@ -910,17 +896,15 @@ const char*	TerragenDataset::GetProjectionRef(void)
 
 CPLErr TerragenDataset::SetGeoTransform( double *padfGeoTransform )
 {
-	memcpy(m_adfTransform, padfGeoTransform,
-		sizeof(m_adfTransform));
+    memcpy(m_adfTransform, padfGeoTransform,
+           sizeof(m_adfTransform));
 
-	// Average the projection scales.
-	m_dGroundScale =
-		average(fabs(m_adfTransform[1]), fabs(m_adfTransform[5]));
-	return CE_None;
+    // Average the projection scales.
+    m_dGroundScale =
+        average(fabs(m_adfTransform[1]), fabs(m_adfTransform[5]));
+    return CE_None;
 }
 
-
-
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /************************************************************************/
@@ -931,7 +915,6 @@ CPLErr TerragenDataset::GetGeoTransform(double* padfTransform)
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                                Create()                                */
 /************************************************************************/
@@ -946,11 +929,11 @@ GDALDataset* TerragenDataset::Create
 
     poDS->eAccess = GA_Update;
 
-	poDS->m_pszFilename = CPLStrdup(pszFilename);
+    poDS->m_pszFilename = CPLStrdup(pszFilename);
 
-	// --------------------------------------------------------------------
-	//      Verify input options.
-	// --------------------------------------------------------------------
+    // --------------------------------------------------------------------
+    //      Verify input options.
+    // --------------------------------------------------------------------
     const char* pszValue = CSLFetchNameValue( papszOptions,"MINUSERPIXELVALUE");
     if( pszValue != NULL )
         poDS->m_dLogSpan[0] = CPLAtof( pszValue );
@@ -979,14 +962,13 @@ GDALDataset* TerragenDataset::Create
         return NULL;
     }
 
-
     if( nBands != 1 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Terragen driver doesn't support %d bands. Must be 1.\n",
                   nBands );
 
-		delete poDS;
+        delete poDS;
         return NULL;
     }
 
@@ -1001,7 +983,7 @@ GDALDataset* TerragenDataset::Create
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "Attempt to create file `%s' failed.\n",
                   pszFilename );
-		delete poDS;
+        delete poDS;
         return NULL;
     }
 
@@ -1009,10 +991,9 @@ GDALDataset* TerragenDataset::Create
     poDS->nRasterYSize = nYSize;
 
     // Don't bother writing the header here; the first
-	// call to IWriteBlock will do that instead, since
-	// the elevation data's location depends on the
-	// header size.
-
+    // call to IWriteBlock will do that instead, since
+    // the elevation data's location depends on the
+    // header size.
 
 // --------------------------------------------------------------------
 //      Instance a band.
@@ -1021,7 +1002,7 @@ GDALDataset* TerragenDataset::Create
 
     //VSIFClose( poDS->m_fp );
 
-    //return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
+    // return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
     return reinterpret_cast<GDALDataset *>( poDS );
 }
 
@@ -1037,7 +1018,7 @@ GDALDataset *TerragenDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
 
     if( !EQUALN(reinterpret_cast<const char *>( poOpenInfo->pabyHeader ),
-		"TERRAGENTERRAIN ", 16) )
+                "TERRAGENTERRAIN ", 16) )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -1062,7 +1043,7 @@ GDALDataset *TerragenDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->eAccess = poOpenInfo->eAccess;
 
 /* -------------------------------------------------------------------- */
-/*	Read the file.							*/
+/*      Read the file.                                                  */
 /* -------------------------------------------------------------------- */
     if( !poDS->LoadFromFile() )
     {
@@ -1088,7 +1069,7 @@ GDALDataset *TerragenDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/til/tildataset.cpp b/frmts/til/tildataset.cpp
index 7be6cdd..fdc15b1 100644
--- a/frmts/til/tildataset.cpp
+++ b/frmts/til/tildataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tildataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  EarthWatch .TIL Driver
  * Purpose:  Implementation of the TILDataset class.
@@ -38,11 +37,11 @@
 #include "ogr_spatialref.h"
 #include "vrtdataset.h"
 
-CPL_CVSID("$Id: tildataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: tildataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*				TILDataset				*/
+/*                              TILDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -54,13 +53,13 @@ class CPL_DLL TILDataset : public GDALPamDataset
     char **papszMetadataFiles;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
   public:
     TILDataset();
-    ~TILDataset();
+    virtual ~TILDataset();
 
-    virtual char **GetFileList(void);
+    virtual char **GetFileList(void) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo *poOpenInfo );
@@ -82,11 +81,11 @@ class TILRasterBand : public GDALPamRasterBand
                    TILRasterBand( TILDataset *, int, VRTSourcedRasterBand * );
     virtual       ~TILRasterBand() {};
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) override;
 };
 
 /************************************************************************/
diff --git a/frmts/tsx/tsxdataset.cpp b/frmts/tsx/tsxdataset.cpp
index b878e28..e948629 100644
--- a/frmts/tsx/tsxdataset.cpp
+++ b/frmts/tsx/tsxdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tsxdataset.cpp 32237 2015-12-18 13:41:27Z goatbar $
  *
  * Project:     TerraSAR-X XML Product Support
  * Purpose:     Support for TerraSAR-X XML Metadata files
@@ -37,7 +36,7 @@
 
 #define MAX_GCPS 5000    //this should be more than enough ground control points
 
-CPL_CVSID("$Id: tsxdataset.cpp 32237 2015-12-18 13:41:27Z goatbar $");
+CPL_CVSID("$Id: tsxdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 enum ePolarization {
     HH=0,
@@ -92,14 +91,14 @@ class TSXDataset : public GDALPamDataset {
     eProductType nProduct;
 public:
     TSXDataset();
-    ~TSXDataset();
+    virtual ~TSXDataset();
 
-    virtual int GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
 
-    CPLErr GetGeoTransform( double* padfTransform);
-    const char* GetProjectionRef();
+    CPLErr GetGeoTransform( double* padfTransform) override;
+    const char* GetProjectionRef() override;
 
     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
     static int Identify( GDALOpenInfo *poOpenInfo );
@@ -121,7 +120,7 @@ public:
         ePolarization ePol, GDALDataset *poBand );
     virtual ~TSXRasterBand();
 
-    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage );
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void *pImage ) override;
 
     static GDALDataset *Open( GDALOpenInfo *poOpenInfo );
 };
@@ -333,12 +332,12 @@ bool TSXDataset::getGCPsFromGEOREF_XML(char *pszGeorefFilename)
     nGCPCount
         = atoi(CPLGetXMLValue( psGeolocationGrid, "numberOfGridPoints.total", "0" ));
     //count the gcps if the given count value is invalid
-    CPLXMLNode *psNode;
-    if (nGCPCount<=0)
+    CPLXMLNode *psNode = NULL;
+    if( nGCPCount<=0 )
     {
         for( psNode = psGeolocationGrid->psChild; psNode != NULL; psNode = psNode->psNext )
             if( EQUAL(psNode->pszValue,"gridPoint") )
-                nGCPCount++ ;
+                nGCPCount++;
     }
     //if there are no gcps, fail
     if(nGCPCount<=0)
@@ -710,9 +709,9 @@ GDALDataset *TSXDataset::Open( GDALOpenInfo *poOpenInfo ) {
             poDS->adfGeoTransform[4] = 0.0;
             poDS->adfGeoTransform[5] = 1.0;
         }
-
     }
-    else {
+    else
+    {
         CPLError(CE_Warning, CPLE_AppDefined,
             "Unable to find sceneInfo tag in XML document. "
             "Proceeding with caution.");
@@ -776,9 +775,9 @@ CPLErr TSXDataset::GetGeoTransform(double* padfTransform)
     memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
 
     if (bHaveGeoTransform)
-        return( CE_None );
+        return CE_None;
 
-    return( CE_Failure );
+    return CE_Failure;
 }
 
 /************************************************************************/
diff --git a/frmts/usgsdem/CDED.notes b/frmts/usgsdem/CDED.notes
index 68c108f..62f88bf 100644
--- a/frmts/usgsdem/CDED.notes
+++ b/frmts/usgsdem/CDED.notes
@@ -13,9 +13,9 @@ Offset Length Name                    Notes
 
   100     9   Filler                  Blank
 
-  109    26   SW Geographic Corner    Generated. 
+  109    26   SW Geographic Corner    Generated.
 
-  135     1   Process Code            Template or blank. 
+  135     1   Process Code            Template or blank.
 
   136     1   Filler                  Blank
 
@@ -23,7 +23,7 @@ Offset Length Name                    Notes
 
   140     4   Origin Code             Template or blank.
 
-  144     6   DEM Level Code          Template or blank. 
+  144     6   DEM Level Code          Template or blank.
 	                              "1" for PRODUCT=CDED50K
 
   150     6   Elevation Pattern       Hardcoded to "1" (regular)
@@ -36,7 +36,7 @@ Offset Length Name                    Notes
   168   360   Projection Parameters   Each hardcoded to 0.0.
 
   528     6   Horz. Unit of Measure   Hardcoded to "3" (arc seconds)
- 
+
   534     6   Vert. Unit of Measure   Hardcoded to "2" (meters)
 
   540     6   Cov. Polygon Sides      Hardcoded to "4".
@@ -49,9 +49,9 @@ Offset Length Name                    Notes
 
   786    24   Rotation Angle          Hardcoded to "0".
 
-  810     6   Accurancy Code          Hardcoded to "0" 
+  810     6   Accurancy Code          Hardcoded to "0"
 
-  816    36   Spatial Resolution      X/Y generated, Z hardcoded to 1.0. 
+  816    36   Spatial Resolution      X/Y generated, Z hardcoded to 1.0.
 
   852    6    Rows of Profiles        Hardcoded to "1".
 
@@ -73,34 +73,34 @@ Offset Length Name                    Notes
 
   888    2    Vertical Datum          Template or "1" (MSL).
 
-  890    2    Horizontal Datum        Template or "4" (NAD83). 
+  890    2    Horizontal Datum        Template or "4" (NAD83).
 
-  892    4    Data edition/version    Template or blank. 
+  892    4    Data edition/version    Template or blank.
               Spec edition/version    "1020" for PRODUCT=CDED50K
 
   896    4    Percent Void            Generated.
 
   900    8    Edge Matching Flags     Template or blank.
 
-  908    7    Vertical Datum Shift    Hardcoded to "0.0". 
+  908    7    Vertical Datum Shift    Hardcoded to "0.0".
 
 
 
 CDED Production Issues
 ======================
 
-The following fields should be addressed in a template file. 
+The following fields should be addressed in a template file.
 
 Offset Length Name                    Notes
 ------ ------ ----                    -----
 
-   40    60   Producer of Data        
+   40    60   Producer of Data
 
-  135     1   Process Code            The CDED spec lists options as 
+  135     1   Process Code            The CDED spec lists options as
                                          "8" = ANUDEM
                                          "9" = FME for LINUX, Build 842
                                          "A" = TopoGrid
 
-  140     4   Origin Code             Should be "YT" in Yukon I believe. 
+  140     4   Origin Code             Should be "YT" in Yukon I believe.
 
 
diff --git a/frmts/usgsdem/usgsdem_create.cpp b/frmts/usgsdem/usgsdem_create.cpp
index e1a7c66..90569ba 100644
--- a/frmts/usgsdem/usgsdem_create.cpp
+++ b/frmts/usgsdem/usgsdem_create.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: usgsdem_create.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  USGS DEM Driver
  * Purpose:  CreateCopy() implementation.
@@ -41,8 +40,7 @@
 
 #include <algorithm>
 
-
-CPL_CVSID("$Id: usgsdem_create.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: usgsdem_create.cpp 36423 2016-11-22 00:58:41Z rouault $");
 
 /* used by usgsdemdataset.cpp */
 GDALDataset *USGSDEMCreateCopy( const char *, GDALDataset *, int, char **,
@@ -69,7 +67,7 @@ typedef struct
     double      dfVertStepSize;
     double      dfElevStepSize;
 
-    char 	**papszOptions;
+    char        **papszOptions;
     int         bStrict;
 
     VSILFILE  *fp;
@@ -295,9 +293,7 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
         CSLFetchNameValue( psWInfo->papszOptions, "TEMPLATE" );
     if( pszTemplate != NULL )
     {
-        VSILFILE *fpTemplate;
-
-        fpTemplate = VSIFOpenL( pszTemplate, "rb" );
+        VSILFILE *fpTemplate = VSIFOpenL( pszTemplate, "rb" );
         if( fpTemplate == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
@@ -530,7 +526,8 @@ static int USGSDEMWriteARecord( USGSDEMWriteInfo *psWInfo )
         {
             if( nMin == DEM_NODATA )
             {
-                nMin = nMax = psWInfo->panData[i];
+                nMin = psWInfo->panData[i];
+                nMax = nMin;
             }
             else
             {
@@ -769,7 +766,6 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
         USGSDEMPrintDouble( achBuffer +  48, psWInfo->dfLLY );
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Local vertical datum offset.                                    */
 /* -------------------------------------------------------------------- */
@@ -789,7 +785,8 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
         {
             if( nMin == DEM_NODATA )
             {
-                nMin = nMax = psWInfo->panData[iData];
+                nMin = psWInfo->panData[iData];
+                nMax = nMin;
             }
             else
             {
@@ -854,7 +851,7 @@ static int USGSDEMWriteProfile( USGSDEMWriteInfo *psWInfo, int iProfile )
 /*                      USGSDEM_LookupNTSByLoc()                        */
 /************************************************************************/
 
-static int
+static bool
 USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
                         char *pszTile, char *pszName )
 
@@ -869,7 +866,7 @@ USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
     {
         CPLError( CE_Failure, CPLE_FileIO, "Unable to find NTS mapsheet lookup file: %s",
                   pszNTSFilename );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -880,8 +877,8 @@ USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
 /* -------------------------------------------------------------------- */
 /*      Find desired sheet.                                             */
 /* -------------------------------------------------------------------- */
-    int  bGotHit = FALSE;
-    char **papszTokens;
+    bool bGotHit = false;
+    char **papszTokens = NULL;
 
     while( !bGotHit
            && (papszTokens = CSVReadParseLine( fpNTS )) != NULL )
@@ -892,10 +889,10 @@ USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
             continue;
         }
 
-        if( ABS(dfULLong - CPLAtof(papszTokens[2])) < 0.01
-            && ABS(dfULLat - CPLAtof(papszTokens[3])) < 0.01 )
+        if( std::abs(dfULLong - CPLAtof(papszTokens[2])) < 0.01
+            && std::abs(dfULLat - CPLAtof(papszTokens[3])) < 0.01 )
         {
-            bGotHit = TRUE;
+            bGotHit = true;
             strncpy( pszTile, papszTokens[0], 7 );
             if( pszName != NULL )
                 strncpy( pszName, papszTokens[1], 100 );
@@ -913,7 +910,7 @@ USGSDEM_LookupNTSByLoc( double dfULLong, double dfULLat,
 /*                      USGSDEM_LookupNTSByTile()                       */
 /************************************************************************/
 
-static int
+static bool
 USGSDEM_LookupNTSByTile( const char *pszTile, char *pszName,
                          double *pdfULLong, double *pdfULLat )
 
@@ -922,14 +919,12 @@ USGSDEM_LookupNTSByTile( const char *pszTile, char *pszName,
 /*      Access NTS 1:50k sheet CSV file.                                */
 /* -------------------------------------------------------------------- */
     const char *pszNTSFilename = CSVFilename( "NTS-50kindex.csv" );
-    FILE *fpNTS;
-
-    fpNTS = VSIFOpen( pszNTSFilename, "rb" );
+    FILE *fpNTS = VSIFOpen( pszNTSFilename, "rb" );
     if( fpNTS == NULL )
     {
         CPLError( CE_Failure, CPLE_FileIO, "Unable to find NTS mapsheet lookup file: %s",
                   pszNTSFilename );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -941,7 +936,7 @@ USGSDEM_LookupNTSByTile( const char *pszTile, char *pszName,
 /*      Find desired sheet.                                             */
 /* -------------------------------------------------------------------- */
     bool bGotHit = false;
-    char **papszTokens;
+    char **papszTokens = NULL;
 
     while( !bGotHit
            && (papszTokens = CSVReadParseLine( fpNTS )) != NULL )
@@ -1034,8 +1029,8 @@ static int USGSDEMProductSetup_CDED50K( USGSDEMWriteInfo *psWInfo )
         dfULY = CPLDMSToDec( papszTokens[1] );
         CSLDestroy( papszTokens );
 
-        if( ABS(dfULX*4-floor(dfULX*4+0.00005)) > 0.0001
-            || ABS(dfULY*4-floor(dfULY*4+0.00005)) > 0.0001 )
+        if( std::abs(dfULX*4-floor(dfULX*4+0.00005)) > 0.0001
+            || std::abs(dfULY*4-floor(dfULY*4+0.00005)) > 0.0001 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TOPLEFT must be on a 15\" boundary for CDED50K, but is not." );
@@ -1325,6 +1320,7 @@ static int USGSDEMLoadRaster( CPL_UNUSED USGSDEMWriteInfo *psWInfo,
     char *apszOptions[] = { szDataPointer, NULL };
 
     memset( szDataPointer, 0, sizeof(szDataPointer) );
+    // cppcheck-suppress redundantCopy
     snprintf( szDataPointer, sizeof(szDataPointer), "DATAPOINTER=" );
     CPLPrintPointer( szDataPointer+strlen(szDataPointer),
                      psWInfo->panData,
@@ -1397,7 +1393,6 @@ static int USGSDEMLoadRaster( CPL_UNUSED USGSDEMWriteInfo *psWInfo,
     return eErr == CE_None;
 }
 
-
 /************************************************************************/
 /*                             CreateCopy()                             */
 /************************************************************************/
@@ -1520,7 +1515,6 @@ USGSDEMCreateCopy( const char *pszFilename,
         return NULL;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Read the whole area of interest into memory.                    */
 /* -------------------------------------------------------------------- */
diff --git a/frmts/usgsdem/usgsdemdataset.cpp b/frmts/usgsdem/usgsdemdataset.cpp
index edc27ce..1617921 100644
--- a/frmts/usgsdem/usgsdemdataset.cpp
+++ b/frmts/usgsdem/usgsdemdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: usgsdemdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  USGS DEM Driver
  * Purpose:  All reader for USGS DEM Reader
@@ -37,11 +36,11 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: usgsdemdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: usgsdemdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 typedef struct {
-    double	x;
-    double	y;
+    double      x;
+    double      y;
 } DPoint2;
 
 static const int USGSDEM_NODATA = -32767;
@@ -85,9 +84,8 @@ static int ReadInt( VSILFILE *fp )
                 szBuffer[nRead] = c;
             nRead ++;
         }
-
     }
-    szBuffer[MIN(nRead, 11)] = 0;
+    szBuffer[std::min(nRead, 11)] = 0;
     return atoi(szBuffer);
 }
 
@@ -236,7 +234,7 @@ static double USGSDEMReadDoubleFromBuffer( Buffer* psBuffer, int nCharCount, int
 static double DConvert( VSILFILE *fp, int nCharCount )
 
 {
-    char	szBuffer[100];
+    char szBuffer[100];
 
     CPL_IGNORE_RET_VAL(VSIFReadL( szBuffer, nCharCount, 1, fp ));
     szBuffer[nCharCount] = '\0';
@@ -252,7 +250,7 @@ static double DConvert( VSILFILE *fp, int nCharCount )
 
 /************************************************************************/
 /* ==================================================================== */
-/*				USGSDEMDataset				*/
+/*                              USGSDEMDataset                          */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -274,16 +272,16 @@ class USGSDEMDataset : public GDALPamDataset
 
     int         LoadFromFile( VSILFILE * );
 
-    VSILFILE	*fp;
+    VSILFILE    *fp;
 
   public:
                 USGSDEMDataset();
-		~USGSDEMDataset();
+                ~USGSDEMDataset();
 
     static int  Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
-    CPLErr 	GetGeoTransform( double * padfTransform );
-    const char *GetProjectionRef();
+    CPLErr GetGeoTransform( double * padfTransform ) override;
+    const char *GetProjectionRef() override;
 };
 
 /************************************************************************/
@@ -299,12 +297,11 @@ class USGSDEMRasterBand : public GDALPamRasterBand
   public:
                 explicit USGSDEMRasterBand( USGSDEMDataset * );
 
-    virtual const char *GetUnitType();
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual const char *GetUnitType() override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
-
 /************************************************************************/
 /*                           USGSDEMRasterBand()                            */
 /************************************************************************/
@@ -319,7 +316,6 @@ USGSDEMRasterBand::USGSDEMRasterBand( USGSDEMDataset *poDSIn )
 
     nBlockXSize = poDSIn->GetRasterXSize();
     nBlockYSize = poDSIn->GetRasterYSize();
-
 }
 
 /************************************************************************/
@@ -331,7 +327,7 @@ CPLErr USGSDEMRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                       void * pImage )
 
 {
-    /* int		bad = FALSE; */
+    /* int bad = FALSE; */
     USGSDEMDataset *poGDS = reinterpret_cast<USGSDEMDataset *>( poDS );
 
 /* -------------------------------------------------------------------- */
@@ -469,7 +465,7 @@ const char *USGSDEMRasterBand::GetUnitType()
 
 /************************************************************************/
 /* ==================================================================== */
-/*				USGSDEMDataset				*/
+/*                              USGSDEMDataset                          */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -484,7 +480,9 @@ USGSDEMDataset::USGSDEMDataset() :
     fVRes(0.0),
     pszUnits(NULL),
     fp(NULL)
-{ }
+{
+    memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
+}
 
 /************************************************************************/
 /*                            ~USGSDEMDataset()                         */
@@ -521,12 +519,12 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
     const bool bNewFormat = nRow != 1 || nColumn != 1;
     if (bNewFormat)
     {
-        CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 1024, 0)); 	// New Format
+        CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 1024, 0));  // New Format
         int i = ReadInt(InDem);
         int j = ReadInt(InDem);
-        if ( i != 1 || ( j != 1 && j != 0 ) )	// File OK?
+        if ( i != 1 || ( j != 1 && j != 0 ) )  // File OK?
         {
-            CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 893, 0)); 	// Undocumented Format (39109h1.dem)
+            CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 893, 0));  // Undocumented Format (39109h1.dem)
             i = ReadInt(InDem);
             j = ReadInt(InDem);
             if ( i != 1 || j != 1 )  // File OK?
@@ -608,7 +606,7 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
         CPL_IGNORE_RET_VAL(VSIFSeekL(InDem, 876, 0));
         char szDateBuffer[5];
         CPL_IGNORE_RET_VAL(VSIFReadL(szDateBuffer, 4, 1, InDem));
-        szDateBuffer[4] = 0;
+        /* szDateBuffer[4] = 0; */
 
         // Horizontal datum
         // 1=North American Datum 1927 (NAD 27)
@@ -656,7 +654,7 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
         bNAD83 = false;
     }
 
-    if (nCoordSystem == 1)	// UTM
+    if (nCoordSystem == 1)  // UTM
     {
         sr.SetUTM( iUTMZone, TRUE );
         if( nGUnit == 1 )
@@ -668,7 +666,7 @@ int USGSDEMDataset::LoadFromFile(VSILFILE *InDem)
         }
     }
 
-    else if (nCoordSystem == 2)	// state plane
+    else if (nCoordSystem == 2)  // state plane
     {
         if( nGUnit == 1 )
             sr.SetStatePlane( iUTMZone, bNAD83,
@@ -759,7 +757,6 @@ const char *USGSDEMDataset::GetProjectionRef()
     return pszProjection;
 }
 
-
 /************************************************************************/
 /*                              Identify()                              */
 /************************************************************************/
@@ -806,7 +803,7 @@ GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
     poDS->fp = fp;
 
 /* -------------------------------------------------------------------- */
-/*	Read the file.							*/
+/*      Read the file.                                                  */
 /* -------------------------------------------------------------------- */
     if( !poDS->LoadFromFile( poDS->fp ) )
     {
@@ -844,7 +841,7 @@ GDALDataset *USGSDEMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
 
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
diff --git a/frmts/vrt/GNUmakefile b/frmts/vrt/GNUmakefile
index ff18e0d..17cc367 100644
--- a/frmts/vrt/GNUmakefile
+++ b/frmts/vrt/GNUmakefile
@@ -1,21 +1,26 @@
+include ../../GDALmake.opt
 
+OBJ := vrtdataset.o vrtrasterband.o vrtdriver.o vrtsources.o
+OBJ += vrtfilters.o vrtsourcedrasterband.o vrtrawrasterband.o
+OBJ += vrtwarped.o vrtderivedrasterband.o vrtpansharpened.o
+OBJ += pixelfunctions.o
 
-include ../../GDALmake.opt
+CPPFLAGS := -I../raw $(CPPFLAGS)
 
-OBJ	=	vrtdataset.o vrtrasterband.o vrtdriver.o vrtsources.o \
-		vrtfilters.o vrtsourcedrasterband.o vrtrawrasterband.o \
-		vrtwarped.o vrtderivedrasterband.o vrtpansharpened.o
+ifeq ($(HAVE_GEOS),yes)
+CPPFLAGS        :=      -DHAVE_GEOS=1 $(CPPFLAGS)
+endif
 
-CPPFLAGS	:=	-I../raw  $(CPPFLAGS)
 
-default:	$(OBJ:.o=.$(OBJ_EXT))
+default: $(OBJ:.o=.$(OBJ_EXT))
 
 clean:
 	rm -f *.o $(O_OBJ)
 
-install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
+install-obj: $(O_OBJ:.o=.$(OBJ_EXT))
 
-$(OBJ) $(O_OBJ):	vrtdataset.h ../../alg/gdalwarper.h ../raw/rawdataset.h ../../gcore/gdal_proxy.h
+$(OBJ) $(O_OBJ): vrtdataset.h ../../alg/gdalwarper.h ../raw/rawdataset.h
+$(OBJ) $(O_OBJ): ../../gcore/gdal_proxy.h
 
 install:
 	$(INSTALL_DATA) vrtdataset.h $(DESTDIR)$(INST_INCLUDE)
diff --git a/frmts/vrt/gdal_vrt.h b/frmts/vrt/gdal_vrt.h
index 63f76ff..4ac1dac 100644
--- a/frmts/vrt/gdal_vrt.h
+++ b/frmts/vrt/gdal_vrt.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_vrt.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: gdal_vrt.h 36558 2016-11-30 01:46:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  C/Public declarations of virtual GDAL dataset objects.
@@ -36,16 +36,17 @@
  * Public (C callable) entry points for virtual GDAL dataset objects.
  */
 
-#include "gdal.h"
-#include "cpl_port.h"
 #include "cpl_error.h"
 #include "cpl_minixml.h"
+#include "cpl_port.h"
+#include "gdal.h"
 
+/** Special value to indicate that nodata is not set */
 #define VRT_NODATA_UNSET -1234.56
 
 CPL_C_START
 
-void GDALRegister_VRT();
+/** Type for a function that returns the pixel data in a provided window */
 typedef CPLErr
 (*VRTImageReadFunc)( void *hCBData,
                      int nXOff, int nYOff, int nXSize, int nYSize,
@@ -54,22 +55,27 @@ typedef CPLErr
 /* -------------------------------------------------------------------- */
 /*      Define handle types related to various VRT dataset classes.     */
 /* -------------------------------------------------------------------- */
-typedef void *VRTDriverH;
-typedef void *VRTSourceH;
-typedef void *VRTSimpleSourceH;
+/*! @cond Doxygen_Suppress */
 typedef void *VRTAveragedSourceH;
+typedef void *VRTAverageFilteredSourceH;
 typedef void *VRTComplexSourceH;
+typedef void *VRTDerivedRasterBandH;
+typedef void *VRTDriverH;
 typedef void *VRTFilteredSourceH;
-typedef void *VRTKernelFilteredSourceH;
-typedef void *VRTAverageFilteredSourceH;
 typedef void *VRTFuncSourceH;
-typedef void *VRTDatasetH;
-typedef void *VRTWarpedDatasetH;
+typedef void *VRTKernelFilteredSourceH;
 typedef void *VRTRasterBandH;
-typedef void *VRTSourcedRasterBandH;
-typedef void *VRTWarpedRasterBandH;
-typedef void *VRTDerivedRasterBandH;
 typedef void *VRTRawRasterBandH;
+typedef void *VRTSimpleSourceH;
+typedef void *VRTSourceH;
+typedef void *VRTWarpedDatasetH;
+typedef void *VRTWarpedRasterBandH;
+/*! @endcond */
+
+/** Opaque type for a VRT dataset */
+typedef void *VRTDatasetH;
+/** Opaque type for a VRT sourced raster band */
+typedef void *VRTSourcedRasterBandH;
 
 /* ==================================================================== */
 /*      VRTDataset class.                                               */
diff --git a/frmts/vrt/makefile.vc b/frmts/vrt/makefile.vc
index 442da64..721f3f8 100644
--- a/frmts/vrt/makefile.vc
+++ b/frmts/vrt/makefile.vc
@@ -2,13 +2,13 @@
 OBJ	=	vrtdataset.obj vrtrasterband.obj vrtdriver.obj \
 		vrtsources.obj vrtfilters.obj vrtsourcedrasterband.obj \
 		vrtrawrasterband.obj vrtderivedrasterband.obj vrtwarped.obj \
-		vrtpansharpened.obj
+		vrtpansharpened.obj pixelfunctions.obj
 
 GDAL_ROOT	=	..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS = 	-I..\raw
+EXTRAFLAGS = 	-I..\raw  $(GEOS_CFLAGS)
 
 default:	$(OBJ)
 	xcopy /D  /Y *.obj ..\o
diff --git a/frmts/vrt/pixelfunctions.cpp b/frmts/vrt/pixelfunctions.cpp
new file mode 100644
index 0000000..e98a027
--- /dev/null
+++ b/frmts/vrt/pixelfunctions.cpp
@@ -0,0 +1,939 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Implementation of a set of GDALDerivedPixelFunc(s) to be used
+ *           with source raster band of virtual GDAL datasets.
+ * Author:   Antonio Valentino <antonio.valentino at tiscali.it>
+ *
+ ******************************************************************************
+ * Copyright (c) 2008-2014 Antonio Valentino <antonio.valentino at tiscali.it>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#include <cmath>
+#include "gdal.h"
+#include "vrtdataset.h"
+
+CPL_CVSID("$Id: pixelfunctions.cpp 35897 2016-10-24 11:54:24Z goatbar $");
+
+static CPLErr RealPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace );
+
+static CPLErr ImagPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace );
+
+static CPLErr ComplexPixelFunc( void **papoSources, int nSources, void *pData,
+                                int nXSize, int nYSize,
+                                GDALDataType eSrcType, GDALDataType eBufType,
+                                int nPixelSpace, int nLineSpace );
+
+static CPLErr ModulePixelFunc( void **papoSources, int nSources, void *pData,
+                               int nXSize, int nYSize,
+                               GDALDataType eSrcType, GDALDataType eBufType,
+                               int nPixelSpace, int nLineSpace );
+
+static CPLErr PhasePixelFunc( void **papoSources, int nSources, void *pData,
+                              int nXSize, int nYSize,
+                              GDALDataType eSrcType, GDALDataType eBufType,
+                              int nPixelSpace, int nLineSpace );
+
+static CPLErr ConjPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace );
+
+static CPLErr SumPixelFunc( void **papoSources, int nSources, void *pData,
+                            int nXSize, int nYSize,
+                            GDALDataType eSrcType, GDALDataType eBufType,
+                            int nPixelSpace, int nLineSpace );
+
+static CPLErr DiffPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace );
+
+static CPLErr MulPixelFunc( void **papoSources, int nSources, void *pData,
+                            int nXSize, int nYSize,
+                            GDALDataType eSrcType, GDALDataType eBufType,
+                            int nPixelSpace, int nLineSpace );
+
+static CPLErr CMulPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace );
+
+static CPLErr InvPixelFunc( void **papoSources, int nSources, void *pData,
+                            int nXSize, int nYSize,
+                            GDALDataType eSrcType, GDALDataType eBufType,
+                            int nPixelSpace, int nLineSpace );
+
+static CPLErr IntensityPixelFunc( void **papoSources, int nSources, void *pData,
+                                  int nXSize, int nYSize,
+                                  GDALDataType eSrcType, GDALDataType eBufType,
+                                  int nPixelSpace, int nLineSpace );
+
+static CPLErr SqrtPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace );
+
+static CPLErr Log10PixelFunc( void **papoSources, int nSources, void *pData,
+                              int nXSize, int nYSize,
+                              GDALDataType eSrcType, GDALDataType eBufType,
+                              int nPixelSpace, int nLineSpace );
+
+static CPLErr DBPixelFunc( void **papoSources, int nSources, void *pData,
+                           int nXSize, int nYSize,
+                           GDALDataType eSrcType, GDALDataType eBufType,
+                           int nPixelSpace, int nLineSpace );
+
+static CPLErr dB2AmpPixelFunc( void **papoSources, int nSources, void *pData,
+                               int nXSize, int nYSize,
+                               GDALDataType eSrcType, GDALDataType eBufType,
+                               int nPixelSpace, int nLineSpace );
+
+static CPLErr dB2PowPixelFunc( void **papoSources, int nSources, void *pData,
+                               int nXSize, int nYSize,
+                               GDALDataType eSrcType, GDALDataType eBufType,
+                               int nPixelSpace, int nLineSpace );
+
+static CPLErr PowPixelFuncHelper( void **papoSources, int nSources, void *pData,
+                                  int nXSize, int nYSize,
+                                  GDALDataType eSrcType, GDALDataType eBufType,
+                                  int nPixelSpace, int nLineSpace,
+                                  double base, double fact );
+
+static CPLErr RealPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+
+    const int nPixelSpaceSrc = GDALGetDataTypeSizeBytes( eSrcType );
+    const int nLineSpaceSrc = nPixelSpaceSrc * nXSize;
+
+    /* ---- Set pixels ---- */
+    for( int iLine = 0; iLine < nYSize; ++iLine ) {
+        GDALCopyWords(
+            static_cast<GByte *>(papoSources[0]) + nLineSpaceSrc * iLine,
+            eSrcType, nPixelSpaceSrc,
+            static_cast<GByte *>(pData) + nLineSpace * iLine,
+            eBufType, nPixelSpace, nXSize );
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // RealPixelFunc
+
+static CPLErr ImagPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        const GDALDataType eSrcBaseType = GDALGetNonComplexDataType( eSrcType );
+        const int nPixelSpaceSrc = GDALGetDataTypeSizeBytes( eSrcType );
+        const int nLineSpaceSrc = nPixelSpaceSrc * nXSize;
+
+        const void * const pImag = static_cast<GByte *>(papoSources[0])
+            + GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0; iLine < nYSize; ++iLine )
+        {
+            GDALCopyWords(
+                static_cast<const GByte *>(pImag) + nLineSpaceSrc * iLine,
+                eSrcBaseType, nPixelSpaceSrc,
+                static_cast<GByte *>(pData) + nLineSpace * iLine,
+                eBufType, nPixelSpace, nXSize );
+        }
+    }
+    else
+    {
+        const double dfImag = 0;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0; iLine < nYSize; ++iLine )
+        {
+            // Always copy from the same location.
+            GDALCopyWords(
+                &dfImag, eSrcType, 0,
+                static_cast<GByte *>(pData) + nLineSpace * iLine,
+                eBufType, nPixelSpace, nXSize);
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // ImagPixelFunc
+
+static CPLErr ComplexPixelFunc( void **papoSources, int nSources, void *pData,
+                                int nXSize, int nYSize,
+                                GDALDataType eSrcType, GDALDataType eBufType,
+                                int nPixelSpace, int nLineSpace )
+{
+    const void * const pReal = papoSources[0];
+    const void * const pImag = papoSources[1];
+
+    /* ---- Init ---- */
+    if( nSources != 2 ) return CE_Failure;
+
+    /* ---- Set pixels ---- */
+    for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+        for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+            // Source raster pixels may be obtained with SRCVAL macro.
+            const double adfPixVal[2] = {
+                SRCVAL(pReal, eSrcType, ii),  // re
+                SRCVAL(pImag, eSrcType, ii)  // im
+            };
+
+            GDALCopyWords(adfPixVal, GDT_CFloat64, 0,
+                          static_cast<GByte *>(pData) + nLineSpace * iLine +
+                          iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // MakeComplexPixelFunc
+
+static CPLErr ModulePixelFunc( void **papoSources, int nSources, void *pData,
+                               int nXSize, int nYSize,
+                               GDALDataType eSrcType, GDALDataType eBufType,
+                               int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        const void *pReal = papoSources[0];
+        const void *pImag = static_cast<GByte *>(papoSources[0])
+                    + GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double dfReal = SRCVAL(pReal, eSrcType, ii);
+                const double dfImag = SRCVAL(pImag, eSrcType, ii);
+
+                const double dfPixVal =
+                    sqrt( dfReal * dfReal + dfImag * dfImag );
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+    else
+    {
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double dfPixVal =
+                    fabs(SRCVAL(papoSources[0], eSrcType, ii));
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // ModulePixelFunc
+
+static CPLErr PhasePixelFunc( void **papoSources, int nSources, void *pData,
+                              int nXSize, int nYSize,
+                              GDALDataType eSrcType, GDALDataType eBufType,
+                              int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        const void * const pReal = papoSources[0];
+        const void * const pImag = static_cast<GByte *>(papoSources[0])
+            + GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double dfReal = SRCVAL(pReal, eSrcType, ii);
+                const double dfImag = SRCVAL(pImag, eSrcType, ii);
+
+                const double dfPixVal = atan2(dfImag, dfReal);
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+    else
+    {
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                const void * const pReal = papoSources[0];
+
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double dfReal = SRCVAL(pReal, eSrcType, ii);
+                const double dfPixVal = (dfReal < 0) ? M_PI : 0.0;
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // PhasePixelFunc
+
+static CPLErr ConjPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+
+    if( GDALDataTypeIsComplex( eSrcType ) && GDALDataTypeIsComplex( eBufType ) )
+    {
+        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+        const void * const pReal = papoSources[0];
+        const void * const pImag =
+            static_cast<GByte *>(papoSources[0]) + nOffset;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double adfPixVal[2] = {
+                    +SRCVAL(pReal, eSrcType, ii),  // re
+                    -SRCVAL(pImag, eSrcType, ii)  // im
+                };
+
+                GDALCopyWords(
+                    adfPixVal, GDT_CFloat64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+    else
+    {
+        // No complex data type.
+        return RealPixelFunc(papoSources, nSources, pData, nXSize, nYSize,
+                             eSrcType, eBufType, nPixelSpace, nLineSpace);
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // ConjPixelFunc
+
+static CPLErr SumPixelFunc(void **papoSources, int nSources, void *pData,
+                    int nXSize, int nYSize,
+                    GDALDataType eSrcType, GDALDataType eBufType,
+                    int nPixelSpace, int nLineSpace)
+{
+    /* ---- Init ---- */
+    if( nSources < 2 ) return CE_Failure;
+
+    /* ---- Set pixels ---- */
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                double adfSum[2] = { 0.0, 0.0 };
+
+                for( int iSrc = 0; iSrc < nSources; ++iSrc ) {
+                    const void * const pReal = papoSources[iSrc];
+                    const void * const pImag =
+                        static_cast<const GByte *>(pReal) + nOffset;
+
+                    // Source raster pixels may be obtained with SRCVAL macro.
+                    adfSum[0] += SRCVAL(pReal, eSrcType, ii);
+                    adfSum[1] += SRCVAL(pImag, eSrcType, ii);
+                }
+
+                GDALCopyWords(
+                    adfSum, GDT_CFloat64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+            }
+        }
+    }
+    else
+    {
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                double dfSum = 0;  // Not complex.
+
+                for( int iSrc = 0; iSrc < nSources; ++iSrc ) {
+                    // Source raster pixels may be obtained with SRCVAL macro.
+                    dfSum += SRCVAL(papoSources[iSrc], eSrcType, ii);
+                }
+
+                GDALCopyWords(
+                    &dfSum, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+            }
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+} /* SumPixelFunc */
+
+static CPLErr DiffPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace)
+{
+    /* ---- Init ---- */
+    if( nSources != 2 ) return CE_Failure;
+
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+        const void * const pReal0 = papoSources[0];
+        const void * const pImag0 =
+            static_cast<GByte *>(papoSources[0]) + nOffset;
+        const void * const pReal1 = papoSources[1];
+        const void * const pImag1 =
+            static_cast<GByte *>(papoSources[1]) + nOffset;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                double adfPixVal[2] = {
+                    SRCVAL(pReal0, eSrcType, ii)
+                    - SRCVAL(pReal1, eSrcType, ii),
+                    SRCVAL(pImag0, eSrcType, ii)
+                    - SRCVAL(pImag1, eSrcType, ii)
+                };
+
+                GDALCopyWords(
+                    adfPixVal, GDT_CFloat64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+    else
+    {
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                // Not complex.
+                const double dfPixVal = SRCVAL(papoSources[0], eSrcType, ii)
+                    - SRCVAL(papoSources[1], eSrcType, ii);
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+            }
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // DiffPixelFunc
+
+static CPLErr MulPixelFunc( void **papoSources, int nSources, void *pData,
+                            int nXSize, int nYSize,
+                            GDALDataType eSrcType, GDALDataType eBufType,
+                            int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources < 2 ) return CE_Failure;
+
+    /* ---- Set pixels ---- */
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                double adfPixVal[2] = { 1.0, 0.0 };
+
+                for( int iSrc = 0; iSrc < nSources; ++iSrc ) {
+                    const void * const pReal = papoSources[iSrc];
+                    const void * const pImag =
+                        static_cast<const GByte *>(pReal) + nOffset;
+
+                    const double dfOldR = adfPixVal[0];
+                    const double dfOldI = adfPixVal[1];
+
+                    // Source raster pixels may be obtained with SRCVAL macro.
+                    const double dfNewR = SRCVAL(pReal, eSrcType, ii);
+                    const double dfNewI = SRCVAL(pImag, eSrcType, ii);
+
+                    adfPixVal[0] = dfOldR * dfNewR - dfOldI * dfNewI;
+                    adfPixVal[1] = dfOldR * dfNewI + dfOldI * dfNewR;
+                }
+
+                GDALCopyWords(
+                    adfPixVal, GDT_CFloat64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+            }
+        }
+    }
+    else
+    {
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                double dfPixVal = 1.0;  // Not complex.
+
+                for( int iSrc = 0; iSrc < nSources; ++iSrc ) {
+                    // Source raster pixels may be obtained with SRCVAL macro.
+                    dfPixVal *= SRCVAL(papoSources[iSrc], eSrcType, ii);
+                }
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+            }
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // MulPixelFunc
+
+static CPLErr CMulPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources != 2 ) return CE_Failure;
+
+    /* ---- Set pixels ---- */
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+        const void * const pReal0 = papoSources[0];
+        const void * const pImag0 =
+            static_cast<GByte *>(papoSources[0]) + nOffset;
+        const void * const pReal1 = papoSources[1];
+        const void * const pImag1 =
+            static_cast<GByte *>(papoSources[1]) + nOffset;
+
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double dfReal0 = SRCVAL(pReal0, eSrcType, ii);
+                const double dfReal1 = SRCVAL(pReal1, eSrcType, ii);
+                const double dfImag0 = SRCVAL(pImag0, eSrcType, ii);
+                const double dfImag1 = SRCVAL(pImag1, eSrcType, ii);
+                const double adfPixVal[2] = {
+                    dfReal0 * dfReal1 + dfImag0 * dfImag1,
+                    dfReal1 * dfImag0 - dfReal0 * dfImag1
+                };
+
+                GDALCopyWords(
+                    adfPixVal, GDT_CFloat64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+    else
+    {
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                // Not complex.
+                const double adfPixVal[2] = {
+                    SRCVAL(papoSources[0], eSrcType, ii)
+                    * SRCVAL(papoSources[1], eSrcType, ii),
+                    0.0
+                };
+
+                GDALCopyWords(
+                    adfPixVal, GDT_CFloat64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // CMulPixelFunc
+
+static CPLErr InvPixelFunc( void **papoSources, int nSources, void *pData,
+                            int nXSize, int nYSize,
+                            GDALDataType eSrcType, GDALDataType eBufType,
+                            int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+
+    /* ---- Set pixels ---- */
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+        const void * const pReal = papoSources[0];
+        const void * const pImag =
+            static_cast<GByte *>(papoSources[0]) + nOffset;
+
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double dfReal = SRCVAL(pReal, eSrcType, ii);
+                const double dfImag = SRCVAL(pImag, eSrcType, ii);
+                const double dfAux = dfReal * dfReal + dfImag * dfImag;
+                const double adfPixVal[2] = { dfReal / dfAux, -dfImag / dfAux };
+
+                GDALCopyWords(
+                    adfPixVal, GDT_CFloat64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+            }
+        }
+    }
+    else
+    {
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                // Not complex.
+                const double dfPixVal =
+                    1.0 / SRCVAL(papoSources[0], eSrcType, ii);
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // InvPixelFunc
+
+static CPLErr IntensityPixelFunc( void **papoSources, int nSources, void *pData,
+                                  int nXSize, int nYSize,
+                                  GDALDataType eSrcType, GDALDataType eBufType,
+                                  int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+        const void * const pReal = papoSources[0];
+        const void * const pImag =
+            static_cast<GByte *>(papoSources[0]) + nOffset;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double dfReal = SRCVAL(pReal, eSrcType, ii);
+                const double dfImag = SRCVAL(pImag, eSrcType, ii);
+
+                const double dfPixVal = dfReal * dfReal + dfImag * dfImag;
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+            }
+        }
+    }
+    else
+    {
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                double dfPixVal = SRCVAL(papoSources[0], eSrcType, ii);
+                dfPixVal *= dfPixVal;
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+            }
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // IntensityPixelFunc
+
+static CPLErr SqrtPixelFunc( void **papoSources, int nSources, void *pData,
+                             int nXSize, int nYSize,
+                             GDALDataType eSrcType, GDALDataType eBufType,
+                             int nPixelSpace, int nLineSpace )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+    if( GDALDataTypeIsComplex( eSrcType ) ) return CE_Failure;
+
+    /* ---- Set pixels ---- */
+    for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+        for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+            // Source raster pixels may be obtained with SRCVAL macro.
+            const double dfPixVal =
+                sqrt( SRCVAL(papoSources[0], eSrcType, ii) );
+
+            GDALCopyWords(
+                &dfPixVal, GDT_Float64, 0,
+                static_cast<GByte *>(pData) + nLineSpace * iLine +
+                iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // SqrtPixelFunc
+
+static CPLErr Log10PixelFuncHelper( void **papoSources, int nSources,
+                                    void *pData,
+                                    int nXSize, int nYSize,
+                                    GDALDataType eSrcType,
+                                    GDALDataType eBufType,
+                                    int nPixelSpace, int nLineSpace,
+                                    double fact )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+
+    if( GDALDataTypeIsComplex( eSrcType ) )
+    {
+        // Complex input datatype.
+        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
+        const void * const pReal = papoSources[0];
+        const void * const pImag =
+            static_cast<GByte *>(papoSources[0]) + nOffset;
+
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double dfReal = SRCVAL(pReal, eSrcType, ii);
+                const double dfImag = SRCVAL(pImag, eSrcType, ii);
+
+                const double dfPixVal =
+                    fact * log10( sqrt( dfReal * dfReal + dfImag * dfImag ) );
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+    else
+    {
+        /* ---- Set pixels ---- */
+        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+                // Source raster pixels may be obtained with SRCVAL macro.
+                const double dfPixVal =
+                    fact * log10( fabs(
+                        SRCVAL(papoSources[0], eSrcType, ii) ) );
+
+                GDALCopyWords(
+                    &dfPixVal, GDT_Float64, 0,
+                    static_cast<GByte *>(pData) + nLineSpace * iLine +
+                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
+            }
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // Log10PixelFuncHelper
+
+static CPLErr Log10PixelFunc( void **papoSources, int nSources, void *pData,
+                              int nXSize, int nYSize,
+                              GDALDataType eSrcType, GDALDataType eBufType,
+                              int nPixelSpace, int nLineSpace )
+{
+    return Log10PixelFuncHelper(papoSources, nSources, pData,
+                                nXSize, nYSize, eSrcType, eBufType,
+                                nPixelSpace, nLineSpace, 1.0);
+} // Log10PixelFunc
+
+static CPLErr DBPixelFunc( void **papoSources, int nSources, void *pData,
+                           int nXSize, int nYSize,
+                           GDALDataType eSrcType, GDALDataType eBufType,
+                           int nPixelSpace, int nLineSpace )
+{
+    return Log10PixelFuncHelper(papoSources, nSources, pData,
+                                nXSize, nYSize, eSrcType, eBufType,
+                                nPixelSpace, nLineSpace, 20.0);
+} // DBPixelFunc
+
+static CPLErr PowPixelFuncHelper( void **papoSources, int nSources, void *pData,
+                                  int nXSize, int nYSize,
+                                  GDALDataType eSrcType, GDALDataType eBufType,
+                                  int nPixelSpace, int nLineSpace,
+                                  double base, double fact )
+{
+    /* ---- Init ---- */
+    if( nSources != 1 ) return CE_Failure;
+    if( GDALDataTypeIsComplex( eSrcType ) ) return CE_Failure;
+
+    /* ---- Set pixels ---- */
+    for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
+        for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
+            // Source raster pixels may be obtained with SRCVAL macro.
+            const double dfPixVal =
+                pow(base, SRCVAL(papoSources[0], eSrcType, ii) / fact);
+
+            GDALCopyWords(
+                &dfPixVal, GDT_Float64, 0,
+                static_cast<GByte *>(pData) + nLineSpace * iLine +
+                iCol * nPixelSpace, eBufType, nPixelSpace, 1);
+        }
+    }
+
+    /* ---- Return success ---- */
+    return CE_None;
+}  // PowPixelFuncHelper
+
+static CPLErr dB2AmpPixelFunc( void **papoSources, int nSources, void *pData,
+                               int nXSize, int nYSize,
+                               GDALDataType eSrcType, GDALDataType eBufType,
+                               int nPixelSpace, int nLineSpace )
+{
+    return PowPixelFuncHelper(papoSources, nSources, pData,
+                              nXSize, nYSize, eSrcType, eBufType,
+                              nPixelSpace, nLineSpace, 10.0, 20.0);
+}  // dB2AmpPixelFunc
+
+static CPLErr dB2PowPixelFunc( void **papoSources, int nSources, void *pData,
+                               int nXSize, int nYSize,
+                               GDALDataType eSrcType, GDALDataType eBufType,
+                               int nPixelSpace, int nLineSpace )
+{
+    return PowPixelFuncHelper(papoSources, nSources, pData,
+                              nXSize, nYSize, eSrcType, eBufType,
+                              nPixelSpace, nLineSpace, 10.0, 10.0);
+}  // dB2PowPixelFunc
+
+/************************************************************************/
+/*                     GDALRegisterDefaultPixelFunc()                   */
+/************************************************************************/
+
+/**
+ * This adds a default set of pixel functions to the global list of
+ * available pixel functions for derived bands:
+ *
+ * - "real": extract real part from a single raster band (just a copy if the
+ *           input is non-complex)
+ * - "imag": extract imaginary part from a single raster band (0 for
+ *           non-complex)
+ * - "complex": make a complex band merging two bands used as real and
+ *              imag values
+ * - "mod": extract module from a single raster band (real or complex)
+ * - "phase": extract phase from a single raster band [-PI,PI] (0 or PI for
+              non-complex)
+ * - "conj": computes the complex conjugate of a single raster band (just a
+ *           copy if the input is non-complex)
+ * - "sum": sum 2 or more raster bands
+ * - "diff": computes the difference between 2 raster bands (b1 - b2)
+ * - "mul": multiply 2 or more raster bands
+ * - "cmul": multiply the first band for the complex conjugate of the second
+ * - "inv": inverse (1./x). Note: no check is performed on zero division
+ * - "intensity": computes the intensity Re(x*conj(x)) of a single raster band
+ *                (real or complex)
+ * - "sqrt": perform the square root of a single raster band (real only)
+ * - "log10": compute the logarithm (base 10) of the abs of a single raster
+ *            band (real or complex): log10( abs( x ) )
+ * - "dB": perform conversion to dB of the abs of a single raster
+ *         band (real or complex): 20. * log10( abs( x ) )
+ * - "dB2amp": perform scale conversion from logarithmic to linear
+ *             (amplitude) (i.e. 10 ^ ( x / 20 ) ) of a single raster
+ *                 band (real only)
+ * - "dB2pow": perform scale conversion from logarithmic to linear
+ *             (power) (i.e. 10 ^ ( x / 10 ) ) of a single raster
+ *             band (real only)
+ *
+ * @see GDALAddDerivedBandPixelFunc
+ *
+ * @return CE_None
+ */
+CPLErr GDALRegisterDefaultPixelFunc()
+{
+    GDALAddDerivedBandPixelFunc("real", RealPixelFunc);
+    GDALAddDerivedBandPixelFunc("imag", ImagPixelFunc);
+    GDALAddDerivedBandPixelFunc("complex", ComplexPixelFunc);
+    GDALAddDerivedBandPixelFunc("mod", ModulePixelFunc);
+    GDALAddDerivedBandPixelFunc("phase", PhasePixelFunc);
+    GDALAddDerivedBandPixelFunc("conj", ConjPixelFunc);
+    GDALAddDerivedBandPixelFunc("sum", SumPixelFunc);
+    GDALAddDerivedBandPixelFunc("diff", DiffPixelFunc);
+    GDALAddDerivedBandPixelFunc("mul", MulPixelFunc);
+    GDALAddDerivedBandPixelFunc("cmul", CMulPixelFunc);
+    GDALAddDerivedBandPixelFunc("inv", InvPixelFunc);
+    GDALAddDerivedBandPixelFunc("intensity", IntensityPixelFunc);
+    GDALAddDerivedBandPixelFunc("sqrt", SqrtPixelFunc);
+    GDALAddDerivedBandPixelFunc("log10", Log10PixelFunc);
+    GDALAddDerivedBandPixelFunc("dB", DBPixelFunc);
+    GDALAddDerivedBandPixelFunc("dB2amp", dB2AmpPixelFunc);
+    GDALAddDerivedBandPixelFunc("dB2pow", dB2PowPixelFunc);
+
+    return CE_None;
+}
diff --git a/frmts/vrt/vrt_tutorial.dox b/frmts/vrt/vrt_tutorial.dox
index efb55c7..b0a1f1c 100644
--- a/frmts/vrt/vrt_tutorial.dox
+++ b/frmts/vrt/vrt_tutorial.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: vrt_tutorial.dox 33123 2016-01-23 18:59:28Z rouault $ */
+/* $Id: vrt_tutorial.dox 36334 2016-11-20 15:42:08Z rouault $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -14,6 +14,8 @@
 <li> \ref gdal_vrttut_overviews
 <li> \ref gdal_vrttut_raw
 <li> \ref gdal_vrttut_creation
+<li> \ref gdal_vrttut_derived_c
+<li> \ref gdal_vrttut_derived_python
 <li> \ref gdal_vrttut_warped
 <li> \ref gdal_vrttut_pansharpen
 <li> \ref gdal_vrttut_mt
@@ -49,7 +51,7 @@ loaded from utm.tif might look like this:
 </VRTDataset>
 \endcode
 
-Many aspects of the VRT file are a direct XML encoding of the 
+Many aspects of the VRT file are a direct XML encoding of the
 <a href="gdal_datamodel.html">GDAL Data Model</a> which should be reviewed
 for understanding of the semantics of various elements.<p>
 
@@ -57,7 +59,7 @@ VRT files can be produced by translating to VRT format.  The resulting file can
 then be edited to modify mappings, add metadata or other purposes.  VRT files
 can also be produced programmatically by various means.<p>
 
-This tutorial will cover the .vrt file format (suitable for users editing 
+This tutorial will cover the .vrt file format (suitable for users editing
 .vrt files), and how .vrt files may be created and manipulated programmatically
 for developers.<p>
 
@@ -69,13 +71,13 @@ is available.<p>
 Virtual files stored on disk are kept in an XML format with the following
 elements.<p>
 
-<b>VRTDataset</b>: This is the root element for the whole GDAL dataset. 
-It must have the attributes rasterXSize and rasterYSize describing the width 
+<b>VRTDataset</b>: This is the root element for the whole GDAL dataset.
+It must have the attributes rasterXSize and rasterYSize describing the width
 and height of the dataset in pixels.
-It may have a subClass attributes with values VRTWarpedDataset (\ref gdal_vrttut_warped) or 
+It may have a subClass attributes with values VRTWarpedDataset (\ref gdal_vrttut_warped) or
 VRTPansharpenedDataset (\ref gdal_vrttut_pansharpen).
-It may have SRS, GeoTransform, 
-GCPList, Metadata, MaskBand and VRTRasterBand subelements. 
+It may have SRS, GeoTransform,
+GCPList, Metadata, MaskBand and VRTRasterBand subelements.
 
 \code
 <VRTDataset rasterXSize="512" rasterYSize="512">
@@ -85,7 +87,7 @@ The allowed subelements for VRTDataset are :
 
 <ul>
 
-<li> <b>SRS</b>: This element contains the spatial reference system (coordinate 
+<li> <b>SRS</b>: This element contains the spatial reference system (coordinate
 system) in OGC WKT format.  Note that this must be appropriately escaped for
 XML, so items like quotes will have the ampersand escape sequences substituted.
 As as well WKT, and valid input to the SetFromUserInput() method (such as well
@@ -96,8 +98,8 @@ known GEOGCS names, and PROJ.4 format) is also allowed in the SRS element.
 \endcode
 </li>
 
-<li> <b>GeoTransform</b>: This element contains a six value affine 
-geotransformation for the dataset, mapping between pixel/line coordinates 
+<li> <b>GeoTransform</b>: This element contains a six value affine
+geotransformation for the dataset, mapping between pixel/line coordinates
 and georeferenced coordinates.<P>
 
 \code
@@ -118,7 +120,7 @@ georeferenced coordinates in the same format as the SRS element.<P>
 \endcode
 </li>
 
-<li> <b>Metadata</b>: This element contains a list of metadata name/value 
+<li> <b>Metadata</b>: This element contains a list of metadata name/value
 pairs associated with the VRTDataset as a whole, or a VRTRasterBand.   It has
 <MDI> (metadata item) subelements which have a "key" attribute and the value
 as the data of the element. The Metadata element can be repeated multiple times,
@@ -154,10 +156,10 @@ the mask band itself.
 
 <li> <b>VRTRasterBand</b>: This represents one band of a dataset.  It will
 have a dataType attribute with the type of the pixel data associated with
-this band (use names Byte, UInt16, Int16, UInt32, Int32, Float32, Float64, 
+this band (use names Byte, UInt16, Int16, UInt32, Int32, Float32, Float64,
 CInt16, CInt32, CFloat32 or CFloat64) and the band this element represents
 (1 based).  This element may have Metadata, ColorInterp, NoDataValue, HideNoDataValue,
-ColorTable, Description and MaskBand subelements as well as the various kinds of 
+ColorTable, Description and MaskBand subelements as well as the various kinds of
 source elements such as SimpleSource, ComplexSource, etc.  A raster band may have many "sources"
 indicating where the actual raster data should be fetched from, and how it
 should be mapped into the raster bands pixel space.<p>
@@ -171,11 +173,11 @@ a color interpretation type.  One of Gray, Palette, Red, Green, Blue, Alpha,
 Hue, Saturation, Lightness, Cyan, Magenta, Yellow, Black, or Unknown.<p>
 
 \code
-  <ColorInterp>Gray</ColorInterp>: 
+  <ColorInterp>Gray</ColorInterp>:
 \endcode
 </li>
 
-<li> <b>NoDataValue</b>: If this element exists a raster band has a 
+<li> <b>NoDataValue</b>: If this element exists a raster band has a
 nodata value associated with, of the value given as data in the element.
 
 \code
@@ -197,11 +199,11 @@ Default value is 0 when this element is absent.
 \endcode
 </li>
 
-<li> <b>ColorTable</b>: This element is parent to a set of Entry 
+<li> <b>ColorTable</b>: This element is parent to a set of Entry
 elements defining the entries in a color table.  Currently only RGBA
 color tables are supported with c1 being red, c2 being green, c3 being
 blue and c4 being alpha.  The entries are ordered and will be assumed
-to start from color table entry 0. 
+to start from color table entry 0.
 
 \code
     <ColorTable>
@@ -220,7 +222,7 @@ of a raster band as it's text value.
 </li>
 
 <li> <b>UnitType</b>: This optional element contains the vertical units for
-elevation band data.  One of "m" for meters or "ft" for feet. Default 
+elevation band data.  One of "m" for meters or "ft" for feet. Default
 assumption is meters.<p>
 
 \code
@@ -229,7 +231,7 @@ assumption is meters.<p>
 </li>
 
 <li> <b>Offset</b>: This optional element contains the offset that should be
-applied when computing "real" pixel values from scaled pixel values on 
+applied when computing "real" pixel values from scaled pixel values on
 a raster band.   The default is 0.0.<p>
 
 \code
@@ -275,11 +277,11 @@ subelements with the names of the categories for classified raster band. <p>
 
 <li> <b>SimpleSource</b>: The SimpleSource indicates that raster data
 should be read from a separate dataset, indicating the dataset, and band to be
-read from, and how the data should map into this bands raster space.  
+read from, and how the data should map into this bands raster space.
 The SimpleSource may have the SourceFilename, SourceBand, SrcRect, and DstRect
 subelements.  The SrcRect element will indicate what rectangle on the indicated
-source file should be read, and the DstRect element indicates how that 
-rectangle of source data should be mapped into the VRTRasterBands space.  
+source file should be read, and the DstRect element indicates how that
+rectangle of source data should be mapped into the VRTRasterBands space.
 
 The relativeToVRT attribute on the SourceFilename indicates whether the
 filename should be interpreted as relative to the .vrt file (value is 1)
@@ -354,7 +356,7 @@ rectangle. Note: starting with GDAL 2.0, a more general mechanism to specify
 resampling algorithms can be used. See above paragraph about the 'resampling' attribute.
 
 <li> <b>ComplexSource</b>: The ComplexSource is derived from the
-SimpleSource (so it shares the SourceFilename, SourceBand, SrcRect and 
+SimpleSource (so it shares the SourceFilename, SourceBand, SrcRect and
 DestRect elements), but it provides support to rescale and offset
 the range of the source values. Certain regions of the source
 can be masked by specifying the NODATA value.
@@ -367,7 +369,7 @@ value (which might require analyzing the whole source dataset). Exponent
 must be positive. (Those 5 values can be set with the -exponent and -scale
 options of gdal_translate.)
 
-The ComplexSource supports adding a custom lookup table to transform 
+The ComplexSource supports adding a custom lookup table to transform
 the source values to the destination. The LUT can be specified using
 the following form:
 
@@ -427,8 +429,8 @@ Non-linear scaling:
 </li>
 
 <li> <b>KernelFilteredSource</b>: This is a pixel source derived from the
-Simple Source (so it shares the SourceFilename, SourceBand, SrcRect and 
-DestRect elements, but it also passes the data through a simple filtering 
+Simple Source (so it shares the SourceFilename, SourceBand, SrcRect and
+DestRect elements, but it also passes the data through a simple filtering
 kernel specified with the Kernel element.  The Kernel element should have
 two child elements, Size and Coefs and optionally the boolean attribute
 normalized (defaults to false=0).  The size must always be an odd number,
@@ -474,17 +476,17 @@ by external .vrt.ovr overviews that might be built later.</li>
 \section gdal_vrttut_raw .vrt Descriptions for Raw Files
 
 So far we have described how to derive new virtual datasets from existing
-files supports by GDAL.  However, it is also common to need to utilize 
+files supports by GDAL.  However, it is also common to need to utilize
 raw binary raster files for which the regular layout of the data is known
 but for which no format specific driver exists.  This can be accomplished
-by writing a .vrt file describing the raw file.  
+by writing a .vrt file describing the raw file.
 
 For example, the following .vrt describes a raw raster file containing
 floating point complex pixels in a file called <i>l2p3hhsso.img</i>.  The
 image data starts from the first byte (ImageOffset=0).  The byte offset
 between pixels is 8 (PixelOffset=8), the size of a CFloat32.  The byte offset
 from the start of one line to the start of the next is 9376 bytes
-(LineOffset=9376) which is the width (1172) times the size of a pixel (8). 
+(LineOffset=9376) which is the width (1172) times the size of a pixel (8).
 
 \code
 <VRTDataset rasterXSize="1172" rasterYSize="1864">
@@ -499,11 +501,11 @@ from the start of one line to the start of the next is 9376 bytes
 \endcode
 
 Some things to note are that the VRTRasterBand has a subClass specifier
-of "VRTRawRasterBand".  Also, the VRTRawRasterBand contains a number of 
+of "VRTRawRasterBand".  Also, the VRTRawRasterBand contains a number of
 previously unseen elements but no "source" information.  VRTRawRasterBands
 may never have sources (i.e. SimpleSource), but should contain the following
-elements in addition to all the normal "metadata" elements previously 
-described which are still supported. 
+elements in addition to all the normal "metadata" elements previously
+described which are still supported.
 
 <ul>
 
@@ -512,7 +514,7 @@ data for this band.  The relativeToVRT attribute can be used to indicate
 if the SourceFilename is relative to the .vrt file (1) or not (0).
 
 <li> <b>ImageOffset</b>: The offset in bytes to the beginning of the first
-pixel of data of this image band.   Defaults to zero. 
+pixel of data of this image band.   Defaults to zero.
 
 <li> <b>PixelOffset</b>: The offset in bytes from the beginning of one
 pixel and the next on the same line.  In packed single band data this will
@@ -520,13 +522,13 @@ be the size of the <b>dataType</b> in bytes.
 
 <li> <b>LineOffset</b>: The offset in bytes from the beginning of one
 scanline of data and the next scanline of data.  In packed single band
-data this will be PixelOffset * rasterXSize. 
+data this will be PixelOffset * rasterXSize.
 
-<li> <b>ByteOrder</b>: Defines the byte order of the data on disk.  
+<li> <b>ByteOrder</b>: Defines the byte order of the data on disk.
 Either LSB (Least Significant Byte first) such as the natural byte order
 on Intel x86 systems or MSB (Most Significant Byte first) such as the natural
 byte order on Motorola or Sparc systems.  Defaults to being the local machine
-order. 
+order.
 
 </ul>
 
@@ -535,9 +537,9 @@ A few other notes:
 <ul>
 
 <li> The image data on disk is assumed to be of the same data type as
-the band <b>dataType</b> of the VRTRawRasterBand. 
+the band <b>dataType</b> of the VRTRawRasterBand.
 
-<li> All the non-source attributes of the VRTRasterBand are supported, 
+<li> All the non-source attributes of the VRTRasterBand are supported,
 including color tables, metadata, nodata values, and color interpretation.
 
 <li> The VRTRawRasterBand supports in place update of the raster, whereas
@@ -545,15 +547,15 @@ the source based VRTRasterBand is always read-only.
 
 <li> The OpenEV tool includes a File menu option to input parameters
 describing a raw raster file in a GUI and create the corresponding .vrt
-file. 
+file.
 
-<li> Multiple bands in the one .vrt file can come from the same raw file. 
+<li> Multiple bands in the one .vrt file can come from the same raw file.
 Just ensure that the ImageOffset, PixelOffset, and LineOffset definition
-for each band is appropriate for the pixels of that particular band.  
+for each band is appropriate for the pixels of that particular band.
 
 </ul>
 
-Another example, in this case a 400x300 RGB pixel interleaved image. 
+Another example, in this case a 400x300 RGB pixel interleaved image.
 
 \code
 <VRTDataset rasterXSize="400" rasterYSize="300">
@@ -581,11 +583,11 @@ Another example, in this case a 400x300 RGB pixel interleaved image.
 </VRTDataset>
 \endcode
 
-\section gdal_vrttut_creation Programatic Creation of VRT Datasets
+\section gdal_vrttut_creation Programmatic Creation of VRT Datasets
 
 The VRT driver supports several methods of creating VRT datasets.  As of
 GDAL 1.2.0 the vrtdataset.h include file should be installed with the core
-GDAL include files, allowing direct access to the VRT classes.  However, 
+GDAL include files, allowing direct access to the VRT classes.  However,
 even without that most capabilities remain available through standard GDAL
 interfaces.<p>
 
@@ -617,7 +619,7 @@ such as metadata or coordinate system that are often hard to change on other
 formats, you might do the following.  In this case, the virtual dataset is
 created "in memory" only by virtual of creating it with an empty filename, and
 then used as a modified source to pass to a CreateCopy() written out in TIFF
-format. 
+format.
 
 \code
   poVRTDS = poDriver->CreateCopy( "", poSrcDS, FALSE, NULL, NULL, NULL );
@@ -643,14 +645,14 @@ that band.
   poVRTDS->GetRasterBand( 1 )->SetMetadataItem( "HideNoDataValue" , "1" );
 \endcode
 
-In this example a virtual dataset is created with the Create() method, and 
-adding bands and sources programmatically, but still via the "generic" API. 
+In this example a virtual dataset is created with the Create() method, and
+adding bands and sources programmatically, but still via the "generic" API.
 A special attribute of VRT datasets is that sources can be added to the VRTRasterBand
 (but not to VRTRawRasterBand) by passing the XML describing the source into SetMetadata() on the special
 domain target "new_vrt_sources".  The domain target "vrt_sources" may also be
 used, in which case any existing sources will be discarded before adding the
 new ones.  In this example we construct a simple averaging filter source
-instead of using the simple source. 
+instead of using the simple source.
 
 \code
   // construct XML for simple 3x3 average filter kernel source.
@@ -663,7 +665,7 @@ instead of using the simple source.
 "  </Kernel>"
 "</KernelFilteredSource>";
 
-  // Create the virtual dataset. 
+  // Create the virtual dataset.
   poVRTDS = poDriver->Create( "", 512, 512, 1, GDT_Byte, NULL );
   poVRTDS->GetRasterBand(1)->SetMetadataItem("source_0",pszFilterSourceXML,
                                              "new_vrt_sources");
@@ -671,7 +673,7 @@ instead of using the simple source.
 
 A more general form of this that will produce a 3x3 average filtered clone
 of any input datasource might look like the following.  In this case we
-deliberately set the filtered datasource as in the "vrt_sources" domain 
+deliberately set the filtered datasource as in the "vrt_sources" domain
 to override the SimpleSource created by the CreateCopy() method.  The fact
 that we used CreateCopy() ensures that all the other metadata, georeferencing
 and so forth is preserved from the source dataset ... the only thing we are
@@ -692,16 +694,16 @@ changing is the data source for each band.
 
       GDALRasterBand *poBand = poVRTDS->GetRasterBand( nBand );
 
-      sprintf( szFilterSourceXML, 
+      sprintf( szFilterSourceXML,
 	"<KernelFilteredSource>"
 	"  <SourceFilename>%s</SourceFilename><SourceBand>%d</SourceBand>"
 	"  <Kernel>"
 	"    <Size>3</Size>"
 	"    <Coefs>0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111</Coefs>"
 	"  </Kernel>"
-	"</KernelFilteredSource>", 
+	"</KernelFilteredSource>",
 	pszSourceFilename, nBand );
-	
+
       poBand->SetMetadataItem( "source_0", szFilterSourceXML, "vrt_sources" );
   }
 \endcode
@@ -720,9 +722,9 @@ should be specified with the above SetMetadata() / SetMetadataItem() examples.
   char** papszOptions = NULL;
   papszOptions = CSLAddNameValue(papszOptions, "subclass", "VRTRawRasterBand"); // if not specified, default to VRTRasterBand
   papszOptions = CSLAddNameValue(papszOptions, "SourceFilename", "src.tif"); // mandatory
-  papszOptions = CSLAddNameValue(papszOptions, "ImageOffset", "156"); // optional. default = 0 
-  papszOptions = CSLAddNameValue(papszOptions, "PixelOffset", "2"); // optional. default = size of band type 
-  papszOptions = CSLAddNameValue(papszOptions, "LineOffset", "1024"); // optional. default = size of band type * width 
+  papszOptions = CSLAddNameValue(papszOptions, "ImageOffset", "156"); // optional. default = 0
+  papszOptions = CSLAddNameValue(papszOptions, "PixelOffset", "2"); // optional. default = size of band type
+  papszOptions = CSLAddNameValue(papszOptions, "LineOffset", "1024"); // optional. default = size of band type * width
   papszOptions = CSLAddNameValue(papszOptions, "ByteOrder", "LSB"); // optional. default = machine order
   papszOptions = CSLAddNameValue(papszOptions, "relativeToVRT", "true"); // optional. default = false
   poVRTDS->AddBand(GDT_Byte, papszOptions);
@@ -731,7 +733,7 @@ should be specified with the above SetMetadata() / SetMetadataItem() examples.
   delete poVRTDS;
 \endcode
 
-<h2>Using Derived Bands</h2>
+\section gdal_vrttut_derived_c Using Derived Bands (with pixel functions in C/C++)
 
 A specialized type of band is a 'derived' band which derives its pixel
 information from its source bands.  With this type of band you must also
@@ -806,12 +808,37 @@ calling the pixel function, and the imaginary portion would be lost.
     ...
 \endcode
 
-<h3>Writing Pixel Functions</h3>
+\subsection gdal_vrttut_derived_default_c_pixel_functions Default Pixel Functions
+
+Starting with GDAL 2.2, GDAL provides a set of default pixel functions that can be used without writing new code:
+
+<ul>
+<li><b>"real": </b> extract real part from a single raster band (just a copy if the input is non-complex)
+<li><b>"imag": </b>
+    extract imaginary part from a single raster band (0 for non-complex)
+<li><b> "complex":   </b> make a complex band merging two bands used as real and imag values
+<li><b> "mod":       </b> extract module from a single raster band (real or complex)
+<li><b> "phase":     </b> extract phase from a single raster band [-PI,PI] (0 or PI for non-complex)
+<li><b> "conj":      </b> computes the complex conjugate of a single raster band (just a copy if the input is non-complex)
+<li><b> "sum":       </b> sum 2 or more raster bands
+<li><b> "diff":      </b> computes the difference between 2 raster bands (b1 - b2)
+<li><b> "mul":       </b> multiply 2 or more raster bands
+<li><b> "cmul":      </b> multiply the first band for the complex conjugate of the second
+<li><b> "inv":       </b>  inverse (1./x). Note: no check is performed on zero division
+<li><b> "intensity": </b> computes the intensity Re(x*conj(x)) of a single raster band (real or complex)
+<li><b> "sqrt":      </b> perform the square root of a single raster band (real only)
+<li><b> "log10":     </b> compute the logarithm (base 10) of the abs of a single raster band (real or complex): log10( abs( x ) )
+<li><b> "dB":        </b> perform conversion to dB of the abs of a single raster band (real or complex): 20. * log10( abs( x ) )
+<li><b> "dB2amp":    </b> perform scale conversion from logarithmic to linear (amplitude) (i.e. 10 ^ ( x / 20 ) ) of a single raster band (real only)
+<li><b> "dB2pow":    </b> perform scale conversion from logarithmic to linear (power) (i.e. 10 ^ ( x / 10 ) ) of a single raster band (real only)
+</ul>
+
+\subsection gdal_vrttut_derived_c_pixel_functions Writing Pixel Functions
 
 To register this function with GDAL (prior to accessing any VRT datasets
 with derived bands that use this function), an application calls
 GDALAddDerivedBandPixelFunc with a key and a GDALDerivedPixelFunc:
- 
+
 \code
     GDALAddDerivedBandPixelFunc("MyFirstFunction", TestFunction);
 \endcode
@@ -891,7 +918,7 @@ CPLErr TestFunction(void **papoSources, int nSources, void *pData,
             x8 = SRCVAL(papoSources[3], eSrcType, ii);
 
             pix_val = sqrt((x3*x3+x4*x4)/(x0*x8));
-            
+
             GDALCopyWords(&pix_val, GDT_Float64, 0,
                           ((GByte *)pData) + nLineSpace * iLine + iCol * nPixelSpace,
                           eBufType, nPixelSpace, 1);
@@ -903,6 +930,356 @@ CPLErr TestFunction(void **papoSources, int nSources, void *pData,
 }
 \endcode
 
+\section gdal_vrttut_derived_python Using Derived Bands (with pixel functions in Python)
+
+Starting with GDAL 2.2, in addition to pixel functions written in C/C++ as
+documented in the \ref gdal_vrttut_derived_c section, it is possible to use
+pixel functions written in Python. Both
+<a href="https://www.python.org/">CPython</a>
+and <a href="http://www.numpy.org/">NumPy</a> are requirements at run-time.
+
+The subelements for VRTRasterBand (whose subclass specification must be
+set to VRTDerivedRasterBand) are :
+<ul>
+
+<li> <i>PixelFunctionType</i> (required): Must be set to a function
+name that will be defined as a inline Python module in PixelFunctionCode
+element or as the form "module_name.function_name" to refer to a function in an
+external Python module</li>
+
+<li> <i>PixelFunctionLanguage</i> (required): Must be set to Python.</li>
+
+<li> <i>PixelFunctionArguments</i> (optional): It is possible to pass
+arguments to the Python pixel function by defining attributes in the
+PixelFunctionArguments element.</li>
+
+<li> <i>PixelFunctionCode</i> (required if PixelFunctionType is of the form
+"function_name", ignored otherwise). The in-lined code of a Python module, that
+must be at least have a function whose name is given by PixelFunctionType.</li>
+
+<li> <i>BufferRadius</i> (optional, defaults to 0): Amount of extra pixels, with
+respect to the original RasterIO() request to satisfy, that are fetched at the
+left, right, bottom and top of the input and output buffers passed to the pixel
+function. Note that the values of the output buffer in this buffer zone will
+be ignored.</li>
+
+</ul>
+
+The signature of the Python pixel function must have the following arguments:
+<ol>
+<li> <i>in_ar</i>: list of input NumPy arrays (one NumPy array for each
+source)</li>
+<li> <i>out_ar</i>: output NumPy array to fill. The array is initialized at the
+right dimensions and with the VRTRasterBand.dataType.</li>
+<li> <i>xoff</i>: pixel offset to the top left corner of the accessed region
+of the band. Generally not needed except if the processing depends on the
+pixel position in the raster.</li>
+<li> <i>yoff</i> line offset to the top left corner of the accessed region of
+the band. Generally not needed.</li>
+<li> <i>xsize</i>: width of the region of the accessed region of the band.
+Can be used together with out_ar.shape[1] to determine the horizontal
+resampling ratio of the request.</li>
+<li> <i>ysize</i>: height of the region of the accessed region of the band.
+Can be used together with out_ar.shape[0] to determine the vertical
+resampling ratio of the request.</li>
+<li> <i>raster_xsize</i>: total with of the raster band. Generally not
+needed.</li>
+<li> <i>raster_ysize</i>: total with of the raster band. Generally not
+needed.</li>
+<li> <i>buf_radius</i>: radius of the buffer (in pixels) added to the left,
+right, top and bottom of in_ar / out_ar. This is the value of the optional
+BufferRadius element that can be set so that the original pixel request is
+extended by a given amount of pixels.</li>
+<li> <i>gt</i>: geotransform. Array of 6 double values.</li>
+<li> <i>kwargs</i>: dictionary with user arguments defined in
+PixelFunctionArguments</li>
+</ol>
+
+\subsection gdal_vrttut_derived_python_examples Examples
+
+<ul>
+
+<li>VRT that multiplies the values of the source file by a factor of 1.5
+
+\code
+<VRTDataset rasterXSize="20" rasterYSize="20">
+  <SRS>EPSG:26711</SRS>
+  <GeoTransform>440720,60,0,3751320,0,-60</GeoTransform>
+  <VRTRasterBand dataType="Byte" band="1" subClass="VRTDerivedRasterBand">
+    <PixelFunctionType>multiply</PixelFunctionType>
+    <PixelFunctionLanguage>Python</PixelFunctionLanguage>
+    <PixelFunctionArguments factor="1.5"/>
+    <PixelFunctionCode><![CDATA[
+import numpy as np
+def multiply(in_ar, out_ar, xoff, yoff, xsize, ysize, raster_xsize,
+                   raster_ysize, buf_radius, gt, **kwargs):
+    factor = float(kwargs['factor'])
+    out_ar[:] = np.round_(np.clip(in_ar[0] * factor,0,255))
+]]>
+    </PixelFunctionCode>
+    <SimpleSource>
+      <SourceFilename relativeToVRT="1">byte.tif</SourceFilename>
+    </SimpleSource>
+  </VRTRasterBand>
+</VRTDataset>
+\endcode
+
+</li>
+
+<li>VRT that adds 2 (or more) rasters
+
+\code
+<VRTDataset rasterXSize="20" rasterYSize="20">
+  <SRS>EPSG:26711</SRS>
+  <GeoTransform>440720,60,0,3751320,0,-60</GeoTransform>
+  <VRTRasterBand dataType="Byte" band="1" subClass="VRTDerivedRasterBand">
+    <PixelFunctionType>add</PixelFunctionType>
+    <PixelFunctionLanguage>Python</PixelFunctionLanguage>
+    <PixelFunctionCode><![CDATA[
+import numpy as np
+def add(in_ar, out_ar, xoff, yoff, xsize, ysize, raster_xsize,
+                   raster_ysize, buf_radius, gt, **kwargs):
+    np.round_(np.clip(np.sum(in_ar, axis = 0, dtype = 'uint16'),0,255),
+              out = out_ar)
+]]>
+    </PixelFunctionCode>
+    <SimpleSource>
+      <SourceFilename relativeToVRT="1">byte.tif</SourceFilename>
+    </SimpleSource>
+    <SimpleSource>
+      <SourceFilename relativeToVRT="1">byte2.tif</SourceFilename>
+    </SimpleSource>
+  </VRTRasterBand>
+</VRTDataset>
+\endcode
+
+</li>
+
+<li>VRT that computes hillshading using an external library
+
+\code
+<VRTDataset rasterXSize="121" rasterYSize="121">
+  <SRS>EPSG:4326</SRS>
+  <GeoTransform>-80.004166666666663,0.008333333333333,0,
+44.004166666666663,0,-0.008333333333333</GeoTransform>
+  <VRTRasterBand dataType="Byte" band="1" subClass="VRTDerivedRasterBand">
+    <ColorInterp>Gray</ColorInterp>
+    <SimpleSource>
+      <SourceFilename relativeToVRT="1">n43.dt0</SourceFilename>
+    </SimpleSource>
+    <PixelFunctionLanguage>Python</PixelFunctionLanguage>
+    <PixelFunctionType>hillshading.hillshade</PixelFunctionType>
+    <PixelFunctionArguments scale="111120" z_factor="30" />
+    <BufferRadius>1</BufferRadius>
+    <SourceTransferType>Int16</SourceTransferType>
+  </VRTRasterBand>
+</VRTDataset>
+\endcode
+
+with hillshading.py:
+
+\code
+# Licence: X/MIT
+# Copyright 2016, Even Rouault
+import math
+
+def hillshade_int(in_ar, out_ar, xoff, yoff, xsize, ysize, raster_xsize,
+                         raster_ysize, radius, gt, z, scale):
+    ovr_scale_x = float(out_ar.shape[1] - 2 * radius) / xsize
+    ovr_scale_y = float(out_ar.shape[0] - 2 * radius) / ysize
+    ewres = gt[1] / ovr_scale_x
+    nsres = gt[5] / ovr_scale_y
+    inv_nsres = 1.0 / nsres
+    inv_ewres = 1.0 / ewres
+
+    az = 315
+    alt = 45
+    degreesToRadians = math.pi / 180
+
+    sin_alt = math.sin(alt * degreesToRadians)
+    azRadians = az * degreesToRadians
+    z_scale_factor = z / (8 * scale)
+    cos_alt_mul_z_scale_factor = \
+              math.cos(alt * degreesToRadians) * z_scale_factor
+    cos_az_mul_cos_alt_mul_z_scale_factor_mul_254 = \
+                254 * math.cos(azRadians) * cos_alt_mul_z_scale_factor
+    sin_az_mul_cos_alt_mul_z_scale_factor_mul_254 = \
+                254 * math.sin(azRadians) * cos_alt_mul_z_scale_factor
+    square_z_scale_factor = z_scale_factor * z_scale_factor
+    sin_alt_mul_254 = 254.0 * sin_alt
+
+    for j in range(radius, out_ar.shape[0]-radius):
+        win_line = in_ar[0][j-radius:j+radius+1,:]
+        for i in range(radius, out_ar.shape[1]-radius):
+            win = win_line[:,i-radius:i+radius+1].tolist()
+            x = inv_ewres * ((win[0][0] + win[1][0] + win[1][0] + win[2][0])-\
+                             (win[0][2] + win[1][2] + win[1][2] + win[2][2])) 
+            y = inv_nsres * ((win[2][0] + win[2][1] + win[2][1] + win[2][2])-\
+                             (win[0][0] + win[0][1] + win[0][1] + win[0][2]))
+            xx_plus_yy = x * x + y * y
+            cang_mul_254 = (sin_alt_mul_254 - \
+                (y * cos_az_mul_cos_alt_mul_z_scale_factor_mul_254 - \
+                    x * sin_az_mul_cos_alt_mul_z_scale_factor_mul_254)) / \
+                math.sqrt(1 + square_z_scale_factor * xx_plus_yy)
+            if cang_mul_254 < 0:
+                out_ar[j,i] = 1
+            else:
+                out_ar[j,i] = 1 + round(cang_mul_254)
+
+def hillshade(in_ar, out_ar, xoff, yoff, xsize, ysize, raster_xsize, 
+              raster_ysize, radius, gt, **kwargs):
+    z = float(kwargs['z_factor'])
+    scale= float(kwargs['scale'])
+    hillshade_int(in_ar, out_ar, xoff, yoff, xsize, ysize, raster_xsize,
+                  raster_ysize, radius, gt, z, scale)
+\endcode
+
+</li>
+
+
+\subsection gdal_vrttut_derived_python_security Security implications
+
+The ability to run Python code potentially opens the door to many potential
+vulnerabilities if the user of GDAL may process untrusted datasets. To avoid
+such issues, by default, execution of Python pixel function will be disabled.
+The execution policy can be controlled with the GDAL_VRT_ENABLE_PYTHON
+configuration option, which can accept 3 values:
+<ul>
+<li>YES: all VRT scripts are considered as trusted and their Python pixel
+functions will be run when pixel operations are involved.</li>
+<li>NO: all VRT scripts are considered untrusted, and none Python pixel
+function will be run.</li>
+<li>TRUSTED_MODULES (default setting): all VRT scripts with inline Python
+code in their PixelFunctionCode elements will be considered untrusted and will
+not be run. VRT scripts that use a PixelFunctionType of the form
+"module_name.function_name" will be considered as trusted, only if "module_name"
+is allowed in the GDAL_VRT_TRUSTED_MODULES configuration option. The value of
+this configuration option is a comma separated listed of trusted module names.
+The '*' wildcard can be used at the name of a string to match all strings beginning
+with the substring before the '*' character. For example 'every*' will make
+'every.thing' or 'everything' module trusted. '*' can also be used to make all
+modules to be trusted.
+The ".*" wildcard can also be used to match exact modules or submodules names.
+For example 'every.*' will make 'every' and 'every.thing' modules trusted, but
+not 'everything'.</li>
+</ul>
+
+\subsection gdal_vrttut_derived_python_interpreter Linking mechanism to a Python interpreter.
+
+Currently only CPython - 2.6, 2.7 and 3.x - is supported. The GDAL shared object
+is not explicitly linked at build time to any of the CPython library. When GDAL
+will need to run Python code, it will first determine if the Python interpreter
+is loaded in the current process (which is the case if the program is a Python
+interpreter itself, or if another program, e.g. QGIS, has already loaded the
+CPython library). Otherwise it will look if the PYTHONSO configuration option is
+defined. This option can be set to point to the name of the Python library to
+use, either as a shortname like "libpython2.7.so" if it is accessible through
+the Linux dynamic loader (so typically in one of the paths in /etc/ld.so.conf or
+LD_LIBRARY_PATH) or as a full path name like "/usr/lib/x86_64-linux-gnu/libpython2.7.so".
+The same holds on Windows will shortnames like "python27.dll" if accessible through
+the PATH or full path names like "c:\python27\python27.dll". If the PYTHONSO
+configuration option is not defined, it will look for a "python" binary in the
+directories of the PATH and will try to determine the related shared object
+(it will retry with "python3" if no "python" has been found). If the above
+was not successful, then a predefined list of shared objects names
+will be tried. At the time of writing, the order of versions searched is 2.7,
+2.6, 3.4, 3.5, 3.6, 3.3, 3.2. Enabling debug information (CPL_DEBUG=VRT) will
+show which Python version is used.
+
+\subsection gdal_vrttut_derived_python_jit Just-in-time compilation
+
+The use of a just-in-time compiler may significantly speed up execution times.
+<a href="http://numba.pydata.org/">Numba</a> has been successfully tested. For
+better performance, it is recommended to use a offline pixel function so that
+the just-in-time compiler may cache its compilation.
+
+Given the following mandelbrot.py file :
+
+\code
+# Trick for compatibility with and without numba
+try:
+    from numba import jit
+    #print('Using numba')
+    g_max_iterations = 100
+except:
+    class jit(object):
+        def __init__(self, nopython = True, nogil = True):
+            pass
+
+        def __call__(self, f):
+            return f
+
+    #print('Using non-JIT version')
+    g_max_iterations = 25
+
+# Use a wrapper for the entry point regarding GDAL, since GDAL cannot access
+# the jit decorated function with the expected signature.
+def mandelbrot(in_ar, out_ar, xoff, yoff, xsize, ysize, raster_xsize,
+                        raster_ysize, r, gt, **kwargs):
+    mandelbrot_jit(out_ar, xoff, yoff, xsize, ysize, raster_xsize, raster_ysize, 
+g_max_iterations)
+
+# Will make sure that the code is compiled to pure native code without Python
+# fallback.
+ at jit(nopython=True, nogil=True, cache=True)
+def mandelbrot_jit(out_ar, xoff, yoff, xsize, ysize, raster_xsize,
+                        raster_ysize, max_iterations):
+    ovr_factor_y = float(out_ar.shape[0]) / ysize
+    ovr_factor_x = float(out_ar.shape[1]) / xsize
+    for j in range( out_ar.shape[0]):
+        y0 = 2.0 * (yoff + j / ovr_factor_y) / raster_ysize - 1
+        for i in range(out_ar.shape[1]):
+            x0 = 3.5 * (xoff + i / ovr_factor_x) / raster_xsize - 2.5
+            x = 0.0
+            y = 0.0
+            x2 = 0.0
+            y2 = 0.0
+            iteration = 0
+            while x2 + y2 < 4 and iteration < max_iterations:
+                y = 2*x*y + y0
+                x = x2 - y2 + x0
+                x2 = x * x
+                y2 = y * y
+                iteration += 1
+
+            out_ar[j][i] = iteration * 255 / max_iterations
+\endcode
+
+the following VRT file can be used (to be opened with QGIS for example)
+
+\code
+
+<VRTDataset rasterXSize="100000000" rasterYSize="100000000">
+  <VRTRasterBand dataType="Byte" band="1" subClass="VRTDerivedRasterBand">
+    <PixelFunctionLanguage>Python</PixelFunctionLanguage>
+    <PixelFunctionType>mandelbrot.mandelbrot</PixelFunctionType>
+    <Metadata>
+      <MDI key="STATISTICS_MAXIMUM">255</MDI>
+      <MDI key="STATISTICS_MEAN">127</MDI>
+      <MDI key="STATISTICS_MINIMUM">0</MDI>
+      <MDI key="STATISTICS_STDDEV">127</MDI>
+    </Metadata>
+    <ColorInterp>Gray</ColorInterp>
+    <Histograms>
+      <HistItem>
+        <HistMin>-0.5</HistMin>
+        <HistMax>255.5</HistMax>
+        <BucketCount>256</BucketCount>
+        <IncludeOutOfRange>0</IncludeOutOfRange>
+        <Approximate>1</Approximate>
+        <HistCounts>0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
+0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0</HistCounts>
+      </HistItem>
+    </Histograms>
+  </VRTRasterBand>
+</VRTDataset>
+\endcode
+
 \section gdal_vrttut_warped Warped VRT
 
 A warped VRT is a VRTDataset with subClass="VRTWarpedDataset". It has a
@@ -970,7 +1347,7 @@ over the pseudo panchromatic intensity.
 
 Corresponding pseudo code:
 \code
-pseudo_panchro[pixel] = sum(weight[i] * spectral[pixel][i] for i=0 to nb_spectral_bands-1) 
+pseudo_panchro[pixel] = sum(weight[i] * spectral[pixel][i] for i=0 to nb_spectral_bands-1)
 ratio = panchro[pixel] / pseudo_panchro[pixel]
 for i=0 to nb_spectral_bands-1:
     output_value[pixel][i] = input_value[pixel][i] * ratio
@@ -983,7 +1360,7 @@ a <b>PanchroBand</b> child element and one of several <b>SpectralBand</b> elemen
 PanchroBand and SpectralBand elements must have at least a <b>SourceFilename</b> child
 element to specify the name of the dataset. They may also have a <b>SourceBand</b> child
 element to specify the number of the band in the dataset (starting with 1). If not
-specify, the first band will be assumed. 
+specify, the first band will be assumed.
 
 The SpectralBand element must generally have a <b>dstBand</b> attribute to specify the
 number of the output band (starting with 1) to which the input spectral band must be mapped.
@@ -1061,7 +1438,7 @@ and spectral bands have not the same geospatial extent. By default, Union will t
 the union of all spatial extents. Intersection the intersection of all spatial extents.
 None will not proceed to any adjustment at all (might be useful if the geotransform are
 somehow dummy, and the top-left and bottom-right corners of all bands match), but will
-emmit a warning. NoneWithoutWarning is the same as None, but in a silent way.</li>
+emit a warning. NoneWithoutWarning is the same as None, but in a silent way.</li>
 </li>
 </ul>
 
diff --git a/frmts/vrt/vrtdataset.cpp b/frmts/vrt/vrtdataset.cpp
index 2b2df06..15ac23c 100644
--- a/frmts/vrt/vrtdataset.cpp
+++ b/frmts/vrt/vrtdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vrtdataset.cpp 34730 2016-07-20 09:12:13Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDataset
@@ -32,12 +31,15 @@
 
 #include "cpl_minixml.h"
 #include "cpl_string.h"
+#include "gdal_frmts.h"
 #include "ogr_spatialref.h"
 
 #include <algorithm>
 #include <typeinfo>
 
-CPL_CVSID("$Id: vrtdataset.cpp 34730 2016-07-20 09:12:13Z rouault $");
+/*! @cond Doxygen_Suppress */
+
+CPL_CVSID("$Id: vrtdataset.cpp 37212 2017-01-26 10:01:56Z rouault $");
 
 /************************************************************************/
 /*                            VRTDataset()                             */
@@ -53,7 +55,8 @@ VRTDataset::VRTDataset( int nXSize, int nYSize ) :
     m_bWritable(TRUE),
     m_pszVRTPath(NULL),
     m_poMaskBand(NULL),
-    m_bCompatibleForDatasetIO(-1)
+    m_bCompatibleForDatasetIO(-1),
+    m_papszXMLVRTMetadata(NULL)
 {
     nRasterXSize = nXSize;
     nRasterYSize = nYSize;
@@ -70,6 +73,8 @@ VRTDataset::VRTDataset( int nXSize, int nYSize ) :
     poDriver = reinterpret_cast<GDALDriver *>( GDALGetDriverByName( "VRT" ) );
 }
 
+/*! @endcond */
+
 /************************************************************************/
 /*                              VRTCreate()                             */
 /************************************************************************/
@@ -81,9 +86,11 @@ VRTDataset::VRTDataset( int nXSize, int nYSize ) :
 VRTDatasetH CPL_STDCALL VRTCreate(int nXSize, int nYSize)
 
 {
-    return ( new VRTDataset(nXSize, nYSize) );
+    return new VRTDataset(nXSize, nYSize);
 }
 
+/*! @cond Doxygen_Suppress */
+
 /************************************************************************/
 /*                            ~VRTDataset()                            */
 /************************************************************************/
@@ -108,6 +115,7 @@ VRTDataset::~VRTDataset()
         delete m_apoOverviews[i];
     for(size_t i=0;i<m_apoOverviewsBak.size();i++)
         delete m_apoOverviewsBak[i];
+    CSLDestroy( m_papszXMLVRTMetadata );
 }
 
 /************************************************************************/
@@ -151,7 +159,9 @@ void VRTDataset::FlushCache()
         /* ------------------------------------------------------------------ */
         /*      Write to disk.                                                */
         /* ------------------------------------------------------------------ */
-        bOK &= VSIFWriteL( papszContent[0], 1, strlen(papszContent[0]), fpVRT ) == strlen(papszContent[0]);
+        bOK &=
+            VSIFWriteL( papszContent[0], 1, strlen(papszContent[0]), fpVRT )
+            == strlen(papszContent[0]);
     }
     if( VSIFCloseL( fpVRT ) != 0 )
         bOK = false;
@@ -174,7 +184,10 @@ char** VRTDataset::GetMetadata( const char *pszDomain )
         /* ------------------------------------------------------------------ */
         /*      Convert tree to a single block of XML text.                   */
         /* ------------------------------------------------------------------ */
-        char *l_pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
+        const char* pszDescription = GetDescription();
+        char *l_pszVRTPath = CPLStrdup(
+            pszDescription[0] && !STARTS_WITH(pszDescription, "<VRTDataset") ?
+                CPLGetPath(pszDescription): "" );
         CPLXMLNode *psDSTree = SerializeToXML( l_pszVRTPath );
         char *pszXML = CPLSerializeXMLTree( psDSTree );
 
@@ -182,14 +195,18 @@ char** VRTDataset::GetMetadata( const char *pszDomain )
 
         CPLFree( l_pszVRTPath );
 
-        char* apszContent[2] = { pszXML, NULL };
-        GDALDataset::SetMetadata(apszContent, "xml:VRT");
-        CPLFree(pszXML);
+        CSLDestroy(m_papszXMLVRTMetadata);
+        m_papszXMLVRTMetadata = static_cast<char**>(CPLMalloc(2 * sizeof(char*)));
+        m_papszXMLVRTMetadata[0] = pszXML;
+        m_papszXMLVRTMetadata[1] = NULL;
+        return m_papszXMLVRTMetadata;
     }
 
     return GDALDataset::GetMetadata(pszDomain);
 }
 
+/*! @endcond */
+
 /************************************************************************/
 /*                            VRTFlushCache()                           */
 /************************************************************************/
@@ -205,6 +222,8 @@ void CPL_STDCALL VRTFlushCache( VRTDatasetH hDataset )
     reinterpret_cast<VRTDataset *>( hDataset )->FlushCache();
 }
 
+/*! @cond Doxygen_Suppress */
+
 /************************************************************************/
 /*                           SerializeToXML()                           */
 /************************************************************************/
@@ -217,7 +236,7 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPathIn )
     /* -------------------------------------------------------------------- */
     CPLXMLNode *psDSTree = CPLCreateXMLNode( NULL, CXT_Element, "VRTDataset" );
 
-    char szNumber[128];
+    char szNumber[128] = { '\0' };
     snprintf( szNumber, sizeof(szNumber), "%d", GetRasterXSize() );
     CPLSetXMLValue( psDSTree, "#rasterXSize", szNumber );
 
@@ -282,7 +301,7 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPathIn )
     /* -------------------------------------------------------------------- */
     /*      Serialize dataset mask band.                                    */
     /* -------------------------------------------------------------------- */
-    if (m_poMaskBand)
+    if( m_poMaskBand )
     {
         CPLXMLNode *psBandTree =
             m_poMaskBand->SerializeToXML(pszVRTPathIn);
@@ -298,6 +317,7 @@ CPLXMLNode *VRTDataset::SerializeToXML( const char *pszVRTPathIn )
     return psDSTree;
 }
 
+/*! @endcond */
 /************************************************************************/
 /*                          VRTSerializeToXML()                         */
 /************************************************************************/
@@ -314,7 +334,7 @@ CPLXMLNode * CPL_STDCALL VRTSerializeToXML( VRTDatasetH hDataset,
     return reinterpret_cast<VRTDataset *>(
         hDataset )->SerializeToXML(pszVRTPath);
 }
-
+/*! @cond Doxygen_Suppress */
 /************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
@@ -387,8 +407,8 @@ CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
     /* Parse dataset mask band first */
     CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
 
-    CPLXMLNode *psChild;
-    if (psMaskBandNode)
+    CPLXMLNode *psChild = NULL;
+    if( psMaskBandNode )
         psChild = psMaskBandNode->psChild;
     else
         psChild = NULL;
@@ -436,7 +456,7 @@ CPLErr VRTDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
 /* -------------------------------------------------------------------- */
 /*      Create band information objects.                                */
 /* -------------------------------------------------------------------- */
-    int		l_nBands = 0;
+    int l_nBands = 0;
     for( psChild=psTree->psChild; psChild != NULL; psChild=psChild->psNext )
     {
         if( psChild->eType == CXT_Element
@@ -656,7 +676,7 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
 
 /* -------------------------------------------------------------------- */
-/*	Try to read the whole file into memory.				*/
+/*      Try to read the whole file into memory.                         */
 /* -------------------------------------------------------------------- */
     char *pszXML = NULL;
     VSILFILE *fp = poOpenInfo->fpL;
@@ -719,6 +739,7 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
         char* pszCurDir = CPLGetCurrentDir();
         const char *currentVrtFilename
             = CPLProjectRelativeFilename(pszCurDir, poOpenInfo->pszFilename);
+        CPLString osInitialCurrentVrtFilename(currentVrtFilename);
         CPLFree(pszCurDir);
 
 #if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
@@ -727,11 +748,14 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
         while( true ) {
             VSIStatBuf statBuffer;
             int lstatCode = lstat( currentVrtFilename, &statBuffer );
-            if ( lstatCode == -1 ) {
-                if (errno == ENOENT) {
-                    // The file could be a virtual file, let later checks handle it.
+            if( lstatCode == -1 ) {
+                if( errno == ENOENT )
+                {
+                    // File could be a virtual file, let later checks handle it.
                     break;
-                } else {
+                }
+                else
+                {
                     CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                     CPLFree( pszXML );
                     CPLError( CE_Failure, CPLE_FileIO,
@@ -742,21 +766,25 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
             }
 
-            if ( !VSI_ISLNK(statBuffer.st_mode) ) {
+            if( !VSI_ISLNK(statBuffer.st_mode) ) {
                 break;
             }
 
-            const int bufferSize = static_cast<int>(readlink( currentVrtFilename,
-                                             filenameBuffer,
-                                             sizeof(filenameBuffer) ));
-            if (bufferSize != -1) {
+            const int bufferSize = static_cast<int>(
+                readlink( currentVrtFilename,
+                          filenameBuffer,
+                          sizeof(filenameBuffer) ) );
+            if( bufferSize != -1 )
+            {
                 filenameBuffer[std::min(bufferSize, static_cast<int>(
                     sizeof(filenameBuffer) ) - 1)] = 0;
                 // The filename in filenameBuffer might be a relative path
                 // from the linkfile resolve it before looping
                 currentVrtFilename = CPLProjectRelativeFilename(
                     CPLGetDirname( currentVrtFilename ), filenameBuffer);
-            } else {
+            }
+            else
+            {
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
                 CPLFree( pszXML );
                 CPLError( CE_Failure, CPLE_FileIO,
@@ -768,7 +796,10 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
         }
 #endif  // HAVE_READLINK && HAVE_LSTAT
 
-        pszVRTPath = CPLStrdup(CPLGetPath(currentVrtFilename));
+        if( osInitialCurrentVrtFilename == currentVrtFilename )
+            pszVRTPath = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
+        else
+            pszVRTPath = CPLStrdup(CPLGetPath(currentVrtFilename));
 
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     }
@@ -806,7 +837,8 @@ GDALDataset *VRTDataset::Open( GDALOpenInfo * poOpenInfo )
     {
         poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
         if( poOpenInfo->AreSiblingFilesLoaded() )
-            poDS->oOvManager.TransferSiblingFiles( poOpenInfo->StealSiblingFiles() );
+            poDS->oOvManager.TransferSiblingFiles(
+                poOpenInfo->StealSiblingFiles() );
     }
 
     return poDS;
@@ -826,12 +858,12 @@ GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
  /* -------------------------------------------------------------------- */
  /*      Parse the XML.                                                  */
  /* -------------------------------------------------------------------- */
-    CPLXMLNode	*psTree = CPLParseXMLString( pszXML );
+    CPLXMLNode *psTree = CPLParseXMLString( pszXML );
     if( psTree == NULL )
         return NULL;
 
     CPLXMLNode *psRoot = CPLGetXMLNode( psTree, "=VRTDataset" );
-    if (psRoot == NULL)
+    if( psRoot == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Missing VRTDataset element." );
@@ -857,17 +889,17 @@ GDALDataset *VRTDataset::OpenXML( const char *pszXML, const char *pszVRTPath,
 /* -------------------------------------------------------------------- */
 /*      Create the new virtual dataset object.                          */
 /* -------------------------------------------------------------------- */
-    const int nXSize = atoi(CPLGetXMLValue(psRoot,"rasterXSize","0"));
-    const int nYSize = atoi(CPLGetXMLValue(psRoot,"rasterYSize","0"));
+    const int nXSize = atoi(CPLGetXMLValue(psRoot, "rasterXSize","0"));
+    const int nYSize = atoi(CPLGetXMLValue(psRoot, "rasterYSize","0"));
 
-    if ( !bIsPansharpened &&
-         !GDALCheckDatasetDimensions( nXSize, nYSize ) )
+    if( !bIsPansharpened &&
+        !GDALCheckDatasetDimensions( nXSize, nYSize ) )
     {
         CPLDestroyXMLNode( psTree );
         return NULL;
     }
 
-    VRTDataset *poDS;
+    VRTDataset *poDS = NULL;
     if( strstr(pszXML,"VRTWarpedDataset") != NULL )
         poDS = new VRTWarpedDataset( nXSize, nYSize );
     else if( bIsPansharpened )
@@ -913,9 +945,10 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Collect required information.                                   */
 /* -------------------------------------------------------------------- */
-        const char* pszImageOffset = CSLFetchNameValueDef(papszOptions, "ImageOffset", "0");
+        const char* pszImageOffset =
+            CSLFetchNameValueDef(papszOptions, "ImageOffset", "0");
         vsi_l_offset nImageOffset = CPLScanUIntBig(
-                        pszImageOffset, static_cast<int>(strlen(pszImageOffset)));
+            pszImageOffset, static_cast<int>(strlen(pszImageOffset)) );
 
         int nPixelOffset = nWordDataSize;
         if( CSLFetchNameValue(papszOptions, "PixelOffset") != NULL )
@@ -929,7 +962,7 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
         if( CSLFetchNameValue(papszOptions, "ByteOrder") != NULL )
             pszByteOrder = CSLFetchNameValue(papszOptions, "ByteOrder");
 
-        const char *pszFilename;
+        const char *pszFilename = NULL;
         if( CSLFetchNameValue(papszOptions, "SourceFilename") != NULL )
             pszFilename = CSLFetchNameValue(papszOptions, "SourceFilename");
         else
@@ -941,7 +974,7 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
         }
 
         const bool bRelativeToVRT =
-            CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "relativeToVRT", FALSE ));
+            CPLFetchBool( papszOptions, "relativeToVRT", false );
 
 /* -------------------------------------------------------------------- */
 /*      Create and initialize the band.                                 */
@@ -951,13 +984,13 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
             new VRTRawRasterBand( this, GetRasterCount() + 1, eType );
 
         char* l_pszVRTPath = CPLStrdup(CPLGetPath(GetDescription()));
-        if EQUAL(l_pszVRTPath, "")
+        if( EQUAL(l_pszVRTPath, "") )
         {
             CPLFree(l_pszVRTPath);
             l_pszVRTPath = NULL;
         }
 
-        CPLErr eErr =
+        const CPLErr eErr =
             poBand->SetRawLink( pszFilename, l_pszVRTPath, bRelativeToVRT,
                                 nImageOffset, nPixelOffset, nLineOffset,
                                 pszByteOrder );
@@ -978,9 +1011,9 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
 /* ==================================================================== */
     else
     {
-        VRTSourcedRasterBand *poBand;
+        VRTSourcedRasterBand *poBand = NULL;
 
-	/* ---- Check for our sourced band 'derived' subclass ---- */
+        /* ---- Check for our sourced band 'derived' subclass ---- */
         if(pszSubClass != NULL && EQUAL(pszSubClass,"VRTDerivedRasterBand")) {
 
             /* We'll need a pointer to the subclass in case we need */
@@ -992,15 +1025,17 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
             /* Set the pixel function options it provided. */
             const char* pszFuncName =
                 CSLFetchNameValue(papszOptions, "PixelFunctionType");
-            if (pszFuncName != NULL)
+            if( pszFuncName != NULL )
                 poDerivedBand->SetPixelFunctionName(pszFuncName);
 
             const char* pszTransferTypeName =
                 CSLFetchNameValue(papszOptions, "SourceTransferType");
-            if (pszTransferTypeName != NULL) {
+            if( pszTransferTypeName != NULL )
+            {
                 const GDALDataType eTransferType =
                     GDALGetDataTypeByName(pszTransferTypeName);
-                if (eTransferType == GDT_Unknown) {
+                if( eTransferType == GDT_Unknown )
+                {
                     CPLError( CE_Failure, CPLE_AppDefined,
                               "invalid SourceTransferType: \"%s\".",
                               pszTransferTypeName);
@@ -1015,7 +1050,6 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
             poBand = poDerivedBand;
         }
         else {
-
             /* ---- Standard sourced band ---- */
             poBand = new VRTSourcedRasterBand(
                 this, GetRasterCount() + 1, eType,
@@ -1059,7 +1093,7 @@ CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )
         return CE_None;
     }
 }
-
+/*! @endcond */
 /************************************************************************/
 /*                              VRTAddBand()                            */
 /************************************************************************/
@@ -1077,7 +1111,7 @@ int CPL_STDCALL VRTAddBand( VRTDatasetH hDataset, GDALDataType eType,
     return reinterpret_cast<VRTDataset *>(
         hDataset )->AddBand( eType, papszOptions );
 }
-
+/*! @cond Doxygen_Suppress */
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
@@ -1088,11 +1122,10 @@ VRTDataset::Create( const char * pszName,
                     GDALDataType eType, char ** papszOptions )
 
 {
-
     if( STARTS_WITH_CI(pszName, "<VRTDataset") )
     {
         GDALDataset *poDS = OpenXML( pszName, NULL, GA_Update );
-        if ( poDS != NULL )
+        if(  poDS != NULL )
             poDS->SetDescription( "<FromXML>" );
         return poDS;
     }
@@ -1169,7 +1202,7 @@ CPLErr VRTDataset::Delete( const char * pszFilename )
 {
     GDALDriverH hDriver = GDALIdentifyDriver(pszFilename, NULL);
 
-    if (!hDriver || !EQUAL( GDALGetDriverShortName(hDriver), "VRT" ) )
+    if( !hDriver || !EQUAL( GDALGetDriverShortName(hDriver), "VRT" ) )
         return CE_Failure;
 
     if( strstr(pszFilename, "<VRTDataset") == NULL &&
@@ -1191,7 +1224,7 @@ CPLErr VRTDataset::Delete( const char * pszFilename )
 
 CPLErr VRTDataset::CreateMaskBand( int )
 {
-    if (m_poMaskBand != NULL)
+    if( m_poMaskBand != NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "This VRT dataset has already a mask band");
@@ -1241,17 +1274,18 @@ int VRTDataset::CloseDependentDatasets()
 
 /* We will return TRUE only if all the bands are VRTSourcedRasterBands */
 /* made of identical sources, that are strictly VRTSimpleSource, and that */
-/* the band number of each source is the band number of the VRTSouredRasterBand */
+/* the band number of each source is the band number of the */
+/* VRTSouredRasterBand. */
 
 int VRTDataset::CheckCompatibleForDatasetIO()
 {
     int nSources = 0;
-    VRTSource    **papoSources = NULL;
+    VRTSource **papoSources = NULL;
     CPLString osResampling;
 
     for(int iBand = 0; iBand < nBands; iBand++)
     {
-        if (!reinterpret_cast<VRTRasterBand *>(
+        if( !reinterpret_cast<VRTRasterBand *>(
                 papoBands[iBand] )->IsSourcedRasterBand() )
             return FALSE;
 
@@ -1262,33 +1296,33 @@ int VRTDataset::CheckCompatibleForDatasetIO()
         if( typeid(*poBand) != typeid(VRTSourcedRasterBand) )
             return FALSE;
 
-        if (iBand == 0)
+        if( iBand == 0 )
         {
             nSources = poBand->nSources;
             papoSources = poBand->papoSources;
             for(int iSource = 0; iSource < nSources; iSource++)
             {
-                if (!papoSources[iSource]->IsSimpleSource())
+                if( !papoSources[iSource]->IsSimpleSource() )
                     return FALSE;
 
                 VRTSimpleSource* poSource = reinterpret_cast<VRTSimpleSource *>(
                     papoSources[iSource] );
-                if (!EQUAL(poSource->GetType(), "SimpleSource"))
+                if( !EQUAL(poSource->GetType(), "SimpleSource") )
                     return FALSE;
 
                 GDALRasterBand *srcband = poSource->GetBand();
-                if (srcband == NULL)
+                if( srcband == NULL )
                     return FALSE;
-                if (srcband->GetDataset() == NULL)
+                if( srcband->GetDataset() == NULL )
                     return FALSE;
-                if (srcband->GetDataset()->GetRasterCount() <= iBand)
+                if( srcband->GetDataset()->GetRasterCount() <= iBand )
                     return FALSE;
-                if (srcband->GetDataset()->GetRasterBand(iBand + 1) != srcband)
+                if( srcband->GetDataset()->GetRasterBand(iBand + 1) != srcband )
                     return FALSE;
                 osResampling = poSource->GetResampling();
             }
         }
-        else if (nSources != poBand->nSources)
+        else if( nSources != poBand->nSources )
         {
             return FALSE;
         }
@@ -1296,7 +1330,7 @@ int VRTDataset::CheckCompatibleForDatasetIO()
         {
             for(int iSource = 0; iSource < nSources; iSource++)
             {
-                if (!poBand->papoSources[iSource]->IsSimpleSource())
+                if( !poBand->papoSources[iSource]->IsSimpleSource() )
                     return FALSE;
                 VRTSimpleSource* poRefSource
                     = reinterpret_cast<VRTSimpleSource *>(
@@ -1304,21 +1338,21 @@ int VRTDataset::CheckCompatibleForDatasetIO()
 
                 VRTSimpleSource* poSource = reinterpret_cast<VRTSimpleSource *>(
                     poBand->papoSources[iSource] );
-                if (!EQUAL(poSource->GetType(), "SimpleSource"))
+                if( !EQUAL(poSource->GetType(), "SimpleSource") )
                     return FALSE;
-                if (!poSource->IsSameExceptBandNumber(poRefSource))
+                if( !poSource->IsSameExceptBandNumber(poRefSource) )
                     return FALSE;
 
                 GDALRasterBand *srcband = poSource->GetBand();
-                if (srcband == NULL)
+                if( srcband == NULL )
                     return FALSE;
-                if (srcband->GetDataset() == NULL)
+                if( srcband->GetDataset() == NULL )
                     return FALSE;
-                if (srcband->GetDataset()->GetRasterCount() <= iBand)
+                if( srcband->GetDataset()->GetRasterCount() <= iBand )
                     return FALSE;
-                if (srcband->GetDataset()->GetRasterBand(iBand + 1) != srcband)
+                if( srcband->GetDataset()->GetRasterBand(iBand + 1) != srcband )
                     return FALSE;
-                if (osResampling.compare(poSource->GetResampling()) != 0)
+                if( osResampling.compare(poSource->GetResampling()) != 0 )
                     return FALSE;
             }
         }
@@ -1338,7 +1372,7 @@ int VRTDataset::CheckCompatibleForDatasetIO()
 
 GDALDataset* VRTDataset::GetSingleSimpleSource()
 {
-    if (!CheckCompatibleForDatasetIO())
+    if( !CheckCompatibleForDatasetIO() )
         return NULL;
 
     VRTSourcedRasterBand* poVRTBand
@@ -1350,38 +1384,48 @@ GDALDataset* VRTDataset::GetSingleSimpleSource()
         poVRTBand->papoSources[0] );
 
     GDALRasterBand* poBand = poSource->GetBand();
-    if (poBand == NULL)
+    if( poBand == NULL )
         return NULL;
 
     GDALDataset* poSrcDS = poBand->GetDataset();
-    if (poSrcDS == NULL)
+    if( poSrcDS == NULL )
         return NULL;
 
     /* Check that it uses the full source dataset */
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
-    if (! poSource->GetSrcDstWindow( 0, 0,
-                                     poSrcDS->GetRasterXSize(),
-                                     poSrcDS->GetRasterYSize(),
-                                     poSrcDS->GetRasterXSize(),
-                                     poSrcDS->GetRasterYSize(),
-                                     &dfReqXOff, &dfReqYOff,
-                                     &dfReqXSize, &dfReqYSize,
-                                     &nReqXOff, &nReqYOff,
-                                     &nReqXSize, &nReqYSize,
-                                     &nOutXOff, &nOutYOff,
-                                     &nOutXSize, &nOutYSize ) )
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
+    if( !poSource->GetSrcDstWindow(
+           0, 0,
+           poSrcDS->GetRasterXSize(),
+           poSrcDS->GetRasterYSize(),
+           poSrcDS->GetRasterXSize(),
+           poSrcDS->GetRasterYSize(),
+           &dfReqXOff, &dfReqYOff,
+           &dfReqXSize, &dfReqYSize,
+           &nReqXOff, &nReqYOff,
+           &nReqXSize, &nReqYSize,
+           &nOutXOff, &nOutYOff,
+           &nOutXSize, &nOutYSize ) )
         return NULL;
 
-    if (nReqXOff != 0 || nReqYOff != 0 ||
+    if( nReqXOff != 0 || nReqYOff != 0 ||
         nReqXSize != poSrcDS->GetRasterXSize() ||
-        nReqYSize != poSrcDS->GetRasterYSize())
+        nReqYSize != poSrcDS->GetRasterYSize() )
         return NULL;
 
-    if (nOutXOff != 0 || nOutYOff != 0 ||
+    if( nOutXOff != 0 || nOutYOff != 0 ||
         nOutXSize != poSrcDS->GetRasterXSize() ||
-        nOutYSize != poSrcDS->GetRasterYSize())
+        nOutYSize != poSrcDS->GetRasterYSize() )
         return NULL;
 
     return poSrcDS;
@@ -1392,33 +1436,33 @@ GDALDataset* VRTDataset::GetSingleSimpleSource()
 /************************************************************************/
 
 CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg)
+                              int nXOff, int nYOff, int nXSize, int nYSize,
+                              void * pData, int nBufXSize, int nBufYSize,
+                              GDALDataType eBufType,
+                              int nBandCount, int *panBandMap,
+                              GSpacing nPixelSpace, GSpacing nLineSpace,
+                              GSpacing nBandSpace,
+                              GDALRasterIOExtraArg* psExtraArg )
 {
-    if (m_bCompatibleForDatasetIO < 0)
+    if( m_bCompatibleForDatasetIO < 0 )
     {
         m_bCompatibleForDatasetIO = CheckCompatibleForDatasetIO();
     }
 
     bool bLocalCompatibleForDatasetIO = CPL_TO_BOOL(m_bCompatibleForDatasetIO);
-    if (bLocalCompatibleForDatasetIO && eRWFlag == GF_Read &&
-        (nBufXSize < nXSize || nBufYSize < nYSize))
+    if( bLocalCompatibleForDatasetIO && eRWFlag == GF_Read &&
+        (nBufXSize < nXSize || nBufYSize < nYSize) )
     {
-        int bTried;
-        CPLErr eErr = TryOverviewRasterIO( eRWFlag,
-                                    nXOff, nYOff, nXSize, nYSize,
-                                    pData, nBufXSize, nBufYSize,
-                                    eBufType,
-                                    nBandCount, panBandMap,
-                                    nPixelSpace, nLineSpace,
-                                    nBandSpace,
-                                    psExtraArg,
-                                    &bTried );
+        int bTried = FALSE;
+        const CPLErr eErr = TryOverviewRasterIO( eRWFlag,
+                                                 nXOff, nYOff, nXSize, nYSize,
+                                                 pData, nBufXSize, nBufYSize,
+                                                 eBufType,
+                                                 nBandCount, panBandMap,
+                                                 nPixelSpace, nLineSpace,
+                                                 nBandSpace,
+                                                 psExtraArg,
+                                                 &bTried );
         if( bTried )
             return eErr;
 
@@ -1439,11 +1483,11 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
 
     // If resampling with non-nearest neighbour, we need to be careful
     // if the VRT band exposes a nodata value, but the sources do not have it
-    if (bLocalCompatibleForDatasetIO && eRWFlag == GF_Read &&
+    if( bLocalCompatibleForDatasetIO && eRWFlag == GF_Read &&
         (nXSize != nBufXSize || nYSize != nBufYSize) &&
         psExtraArg->eResampleAlg != GRIORA_NearestNeighbour )
     {
-        for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
+        for( int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++ )
         {
             VRTSourcedRasterBand* poBand =
                 reinterpret_cast<VRTSourcedRasterBand*>(
@@ -1472,7 +1516,7 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
         }
     }
 
-    if (bLocalCompatibleForDatasetIO && eRWFlag == GF_Read)
+    if( bLocalCompatibleForDatasetIO && eRWFlag == GF_Read )
     {
         for(int iBandIndex=0; iBandIndex<nBandCount; iBandIndex++)
         {
@@ -1497,9 +1541,8 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
         }
 
         CPLErr eErr = CE_None;
-
         GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
-        void             *pProgressDataGlobal = psExtraArg->pProgressData;
+        void *pProgressDataGlobal = psExtraArg->pProgressData;
 
         // Use the last band, because when sources reference a GDALProxyDataset,
         // they don't necessary instantiate all underlying rasterbands.
@@ -1511,10 +1554,11 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
         {
             psExtraArg->pfnProgress = GDALScaledProgress;
             psExtraArg->pProgressData =
-                GDALCreateScaledProgress( 1.0 * iSource / poBand->nSources,
-                                        1.0 * (iSource + 1) / poBand->nSources,
-                                        pfnProgressGlobal,
-                                        pProgressDataGlobal );
+                GDALCreateScaledProgress(
+                    1.0 * iSource / poBand->nSources,
+                    1.0 * (iSource + 1) / poBand->nSources,
+                    pfnProgressGlobal,
+                    pProgressDataGlobal );
 
             VRTSimpleSource* poSource = reinterpret_cast<VRTSimpleSource *>(
                 poBand->papoSources[iSource] );
@@ -1523,8 +1567,9 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
                                               pData, nBufXSize, nBufYSize,
                                               eBufType,
                                               nBandCount, panBandMap,
-                                              nPixelSpace, nLineSpace, nBandSpace,
-                                              psExtraArg);
+                                              nPixelSpace, nLineSpace,
+                                              nBandSpace,
+                                              psExtraArg );
 
             GDALDestroyScaledProgress( psExtraArg->pProgressData );
         }
@@ -1535,12 +1580,12 @@ CPLErr VRTDataset::IRasterIO( GDALRWFlag eRWFlag,
         return eErr;
     }
 
-    return GDALDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                  pData, nBufXSize, nBufYSize,
-                                  eBufType,
-                                  nBandCount, panBandMap,
-                                  nPixelSpace, nLineSpace, nBandSpace,
-                                  psExtraArg);
+    return GDALDataset::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                   pData, nBufXSize, nBufYSize,
+                                   eBufType,
+                                   nBandCount, panBandMap,
+                                   nPixelSpace, nLineSpace, nBandSpace,
+                                   psExtraArg );
 }
 
 /************************************************************************/
@@ -1561,7 +1606,7 @@ void VRTDataset::UnsetPreservedRelativeFilenames()
         VRTSource** papoSources = poBand->papoSources;
         for(int iSource = 0; iSource < nSources; iSource++)
         {
-            if (!papoSources[iSource]->IsSimpleSource())
+            if( !papoSources[iSource]->IsSimpleSource() )
                 continue;
 
             VRTSimpleSource* poSource = reinterpret_cast<VRTSimpleSource *>(
@@ -1580,12 +1625,12 @@ void VRTDataset::BuildVirtualOverviews()
     // Currently we expose virtual overviews only if the dataset is made of
     // a single SimpleSource/ComplexSource, in each band.
     // And if the underlying sources have overviews of course
-    if( m_apoOverviews.size() || m_apoOverviewsBak.size() )
+    if( !m_apoOverviews.empty() || !m_apoOverviewsBak.empty() )
         return;
 
     int nOverviews = 0;
     GDALRasterBand* poFirstBand = NULL;
-    for(int iBand = 0; iBand < nBands; iBand++)
+    for( int iBand = 0; iBand < nBands; iBand++ )
     {
         if( !reinterpret_cast<VRTRasterBand *>(
                papoBands[iBand] )->IsSourcedRasterBand())
@@ -1595,16 +1640,16 @@ void VRTDataset::BuildVirtualOverviews()
             = reinterpret_cast<VRTSourcedRasterBand *>( papoBands[iBand] );
         if( poVRTBand->nSources != 1 )
             return;
-        if (!poVRTBand->papoSources[0]->IsSimpleSource())
+        if( !poVRTBand->papoSources[0]->IsSimpleSource() )
             return;
 
         VRTSimpleSource* poSource
             = reinterpret_cast<VRTSimpleSource *>( poVRTBand->papoSources[0] );
-        if (!EQUAL(poSource->GetType(), "SimpleSource") &&
-            !EQUAL(poSource->GetType(), "ComplexSource"))
+        if( !EQUAL(poSource->GetType(), "SimpleSource") &&
+            !EQUAL(poSource->GetType(), "ComplexSource") )
             return;
         GDALRasterBand* poSrcBand = poSource->GetBand();
-        if (poSrcBand == NULL)
+        if( poSrcBand == NULL )
             return;
 
         // To prevent recursion
@@ -1623,7 +1668,7 @@ void VRTDataset::BuildVirtualOverviews()
             nOverviews = nOvrCount;
     }
 
-    for(int j=0;j<nOverviews;j++)
+    for( int j = 0; j < nOverviews; j++)
     {
         const double dfXRatio = static_cast<double>(
             poFirstBand->GetOverview(j)->GetXSize() ) / poFirstBand->GetXSize();
@@ -1636,7 +1681,7 @@ void VRTDataset::BuildVirtualOverviews()
         VRTDataset* poOvrVDS = new VRTDataset(nOvrXSize, nOvrYSize);
         m_apoOverviews.push_back(poOvrVDS);
 
-        for(int i=0;i<nBands;i++)
+        for( int i = 0; i < nBands; i++ )
         {
             VRTSourcedRasterBand* poVRTBand
                 = reinterpret_cast<VRTSourcedRasterBand *>(
@@ -1652,14 +1697,19 @@ void VRTDataset::BuildVirtualOverviews()
                 poVRTBand->papoSources[0] );
             VRTSimpleSource* poNewSource = NULL;
             if( EQUAL(poSrcSource->GetType(), "SimpleSource") )
-                poNewSource = new VRTSimpleSource(poSrcSource, dfXRatio, dfYRatio);
+            {
+                poNewSource =
+                    new VRTSimpleSource(poSrcSource, dfXRatio, dfYRatio);
+            }
             else if( EQUAL(poSrcSource->GetType(), "ComplexSource") )
+            {
               poNewSource = new VRTComplexSource(
                   reinterpret_cast<VRTComplexSource *>( poSrcSource ),
                   dfXRatio, dfYRatio );
+            }
             else
             {
-                CPLAssert(FALSE);
+                CPLAssert(false);
             }
             if( poNewSource->GetBand()->GetDataset() )
                 poNewSource->GetBand()->GetDataset()->Reference();
@@ -1681,10 +1731,10 @@ VRTDataset::IBuildOverviews( const char *pszResampling,
                              GDALProgressFunc pfnProgress,
                              void * pProgressData )
 {
-    /* Make implicit overviews invisible, but do not destroy */
-    /* them in case they are already used (not sure that the client */
-    /* has the right to do that. behaviour undefined in GDAL API I think) */
-    if( m_apoOverviews.size() )
+    // Make implicit overviews invisible, but do not destroy them in case they
+    // are already used.  Should the client do that?  Behaviour might undefined
+    // in GDAL API?
+    if( !m_apoOverviews.empty() )
     {
         m_apoOverviewsBak = m_apoOverviews;
         m_apoOverviews.resize(0);
@@ -1692,15 +1742,17 @@ VRTDataset::IBuildOverviews( const char *pszResampling,
     else
     {
         // Add a dummy overview so that GDALDataset::IBuildOverviews()
-        // doesn't manage to get a virtual implicit overview
+        // doesn't manage to get a virtual implicit overview.
         m_apoOverviews.push_back(NULL);
     }
 
-    return GDALDataset::IBuildOverviews(pszResampling,
-                                               nOverviews,
-                                               panOverviewList,
-                                               nListBands,
-                                               panBandList,
-                                               pfnProgress,
-                                               pProgressData);
+    return GDALDataset::IBuildOverviews( pszResampling,
+                                         nOverviews,
+                                         panOverviewList,
+                                         nListBands,
+                                         panBandList,
+                                         pfnProgress,
+                                         pProgressData );
 }
+
+/*! @endcond */
diff --git a/frmts/vrt/vrtdataset.h b/frmts/vrt/vrtdataset.h
index 7bf25a7..4ebb341 100644
--- a/frmts/vrt/vrtdataset.h
+++ b/frmts/vrt/vrtdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vrtdataset.h 35350 2016-09-07 07:21:52Z rouault $
+ * $Id: vrtdataset.h 37723 2017-03-16 17:07:53Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Declaration of virtual gdal dataset classes.
@@ -31,6 +31,8 @@
 #ifndef VIRTUALDATASET_H_INCLUDED
 #define VIRTUALDATASET_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "cpl_hash_set.h"
 #include "gdal_pam.h"
 #include "gdal_priv.h"
@@ -41,6 +43,7 @@
 
 int VRTApplyMetadata( CPLXMLNode *, GDALMajorObject * );
 CPLXMLNode *VRTSerializeMetadata( GDALMajorObject * );
+CPLErr GDALRegisterDefaultPixelFunc();
 
 #if 0
 int VRTWarpedOverviewTransform( void *pTransformArg, int bDstToSrc,
@@ -66,13 +69,12 @@ public:
         if( poBand == NULL )
             /* do nothing */;
         else if( poBand->GetDataset()->GetShared() )
-            GDALClose( (GDALDatasetH) poBand->GetDataset() );
+            GDALClose( /* (GDALDatasetH) */ poBand->GetDataset() );
         else
             poBand->GetDataset()->Dereference();
     }
 };
 
-
 /************************************************************************/
 /*                              VRTSource                               */
 /************************************************************************/
@@ -90,17 +92,20 @@ public:
 
     virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess ) = 0;
     virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess ) = 0;
-    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax ) = 0;
+    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK,
+                                        double* adfMinMax ) = 0;
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
                                       int bApproxOK,
                                       double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
-                                      GDALProgressFunc pfnProgress, void *pProgressData ) = 0;
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData ) = 0;
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
                                   double dfMin, double dfMax,
                                   int nBuckets, GUIntBig * panHistogram,
                                   int bIncludeOutOfRange, int bApproxOK,
-                                  GDALProgressFunc pfnProgress, void *pProgressData ) = 0;
+                                  GDALProgressFunc pfnProgress,
+                                  void *pProgressData ) = 0;
 
     virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * ) = 0;
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) = 0;
@@ -131,7 +136,7 @@ class CPL_DLL VRTDataset : public GDALDataset
     int            m_bGeoTransformSet;
     double         m_adfGeoTransform[6];
 
-    int           m_nGCPCount;
+    int            m_nGCPCount;
     GDAL_GCP      *m_pasGCPList;
     char          *m_pszGCPProjection;
 
@@ -146,43 +151,44 @@ class CPL_DLL VRTDataset : public GDALDataset
     int            CheckCompatibleForDatasetIO();
     std::vector<GDALDataset*> m_apoOverviews;
     std::vector<GDALDataset*> m_apoOverviewsBak;
+    char         **m_papszXMLVRTMetadata;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() CPL_OVERRIDE;
 
   public:
                  VRTDataset(int nXSize, int nYSize);
     virtual ~VRTDataset();
 
     void          SetNeedsFlush() { m_bNeedsFlush = TRUE; }
-    virtual void  FlushCache();
+    virtual void  FlushCache() CPL_OVERRIDE;
 
     void SetWritable(int bWritableIn) { m_bWritable = bWritableIn; }
 
-    virtual CPLErr          CreateMaskBand( int nFlags );
+    virtual CPLErr          CreateMaskBand( int nFlags ) CPL_OVERRIDE;
     void SetMaskBand(VRTRasterBand* poMaskBand);
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual const char *GetProjectionRef() CPL_OVERRIDE;
+    virtual CPLErr SetProjection( const char * ) CPL_OVERRIDE;
+    virtual CPLErr GetGeoTransform( double * ) CPL_OVERRIDE;
+    virtual CPLErr SetGeoTransform( double * ) CPL_OVERRIDE;
 
-    virtual CPLErr SetMetadata( char **papszMD, const char *pszDomain = "" );
+    virtual CPLErr SetMetadata( char **papszMD, const char *pszDomain = "" ) CPL_OVERRIDE;
     virtual CPLErr SetMetadataItem( const char *pszName, const char *pszValue,
-                                    const char *pszDomain = "" );
+                                    const char *pszDomain = "" ) CPL_OVERRIDE;
 
-    virtual char** GetMetadata( const char *pszDomain = "" );
+    virtual char** GetMetadata( const char *pszDomain = "" ) CPL_OVERRIDE;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() CPL_OVERRIDE;
+    virtual const char *GetGCPProjection() CPL_OVERRIDE;
+    virtual const GDAL_GCP *GetGCPs() CPL_OVERRIDE;
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) CPL_OVERRIDE;
 
     virtual CPLErr AddBand( GDALDataType eType,
-                            char **papszOptions=NULL );
+                            char **papszOptions=NULL ) CPL_OVERRIDE;
 
-    virtual char      **GetFileList();
+    virtual char      **GetFileList() CPL_OVERRIDE;
 
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
@@ -191,13 +197,13 @@ class CPL_DLL VRTDataset : public GDALDataset
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg) CPL_OVERRIDE;
 
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath);
     virtual CPLErr      XMLInit( CPLXMLNode *, const char * );
 
     virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
+                                    int, int *, GDALProgressFunc, void * ) CPL_OVERRIDE;
 
     /* Used by PDF driver for example */
     GDALDataset*        GetSingleSimpleSource();
@@ -207,7 +213,8 @@ class CPL_DLL VRTDataset : public GDALDataset
 
     static int          Identify( GDALOpenInfo * );
     static GDALDataset *Open( GDALOpenInfo * );
-    static GDALDataset *OpenXML( const char *, const char * = NULL, GDALAccess eAccess = GA_ReadOnly );
+    static GDALDataset *OpenXML( const char *, const char * = NULL,
+                                 GDALAccess eAccess = GA_ReadOnly );
     static GDALDataset *Create( const char * pszName,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType, char ** papszOptions );
@@ -233,10 +240,20 @@ class CPL_DLL VRTWarpedDataset : public VRTDataset
 
     void              CreateImplicitOverviews();
 
+    struct VerticalShiftGrid
+    {
+        CPLString osVGrids;
+        int       bInverse;
+        double    dfToMeterSrc;
+        double    dfToMeterDest;
+        CPLStringList aosOptions;
+    };
+    std::vector<VerticalShiftGrid> m_aoVerticalShiftGrids;
+
     friend class VRTWarpedRasterBand;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() CPL_OVERRIDE;
 
 public:
                       VRTWarpedDataset( int nXSize, int nYSize );
@@ -245,22 +262,28 @@ public:
     CPLErr            Initialize( /* GDALWarpOptions */ void * );
 
     virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
+                                    int, int *, GDALProgressFunc, void * ) CPL_OVERRIDE;
 
     virtual CPLErr SetMetadataItem( const char *pszName, const char *pszValue,
-                                    const char *pszDomain = "" );
+                                    const char *pszDomain = "" ) CPL_OVERRIDE;
 
-    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
-    virtual CPLErr    XMLInit( CPLXMLNode *, const char * );
+    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
+    virtual CPLErr    XMLInit( CPLXMLNode *, const char * ) CPL_OVERRIDE;
 
     virtual CPLErr AddBand( GDALDataType eType,
-                            char **papszOptions=NULL );
+                            char **papszOptions=NULL ) CPL_OVERRIDE;
 
-    virtual char      **GetFileList();
+    virtual char      **GetFileList() CPL_OVERRIDE;
 
     CPLErr            ProcessBlock( int iBlockX, int iBlockY );
 
     void              GetBlockSize( int *, int * );
+
+    void              SetApplyVerticalShiftGrid(const char* pszVGrids,
+                                             int bInverse,
+                                             double dfToMeterSrc,
+                                             double dfToMeterDest,
+                                             char** papszOptions );
 };
 
 /************************************************************************/
@@ -286,7 +309,8 @@ class VRTPansharpenedDataset : public VRTDataset
     GDALPansharpenOperation* m_poPansharpener;
     VRTPansharpenedDataset* m_poMainDataset;
     std::vector<VRTPansharpenedDataset*> m_apoOverviewDatasets;
-    std::map<CPLString,CPLString> m_oMapToRelativeFilenames; // map from absolute to relative
+    // Map from absolute to relative.
+    std::map<CPLString,CPLString> m_oMapToRelativeFilenames;
 
     int               m_bLoadingOtherBands;
 
@@ -303,24 +327,24 @@ class VRTPansharpenedDataset : public VRTDataset
     std::vector<GDALDataset*> m_apoDatasetsToClose;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() CPL_OVERRIDE;
 
 public:
                       VRTPansharpenedDataset( int nXSize, int nYSize );
-                     ~VRTPansharpenedDataset();
+    virtual ~VRTPansharpenedDataset();
 
-    virtual CPLErr    XMLInit( CPLXMLNode *, const char * );
-    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
+    virtual CPLErr    XMLInit( CPLXMLNode *, const char * ) CPL_OVERRIDE;
+    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
 
     CPLErr            XMLInit( CPLXMLNode *psTree, const char *pszVRTPath,
-                                        GDALRasterBandH hPanchroBandIn,
-                                        int nInputSpectralBandsIn,
-                                        GDALRasterBandH* pahInputSpectralBandsIn );
+                               GDALRasterBandH hPanchroBandIn,
+                               int nInputSpectralBandsIn,
+                               GDALRasterBandH* pahInputSpectralBandsIn );
 
     virtual CPLErr AddBand( GDALDataType eType,
-                            char **papszOptions=NULL );
+                            char **papszOptions=NULL ) CPL_OVERRIDE;
 
-    virtual char      **GetFileList();
+    virtual char      **GetFileList() CPL_OVERRIDE;
 
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
@@ -329,7 +353,7 @@ public:
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg) CPL_OVERRIDE;
 
     void              GetBlockSize( int *, int * );
 
@@ -349,7 +373,8 @@ class CPL_DLL VRTRasterBand : public GDALRasterBand
     int            m_bIsMaskBand;
 
     int            m_bNoDataValueSet;
-    int            m_bHideNoDataValue; // If set to true, will not report the existence of nodata
+    // If set to true, will not report the existence of nodata.
+    int            m_bHideNoDataValue;
     double         m_dfNoDataValue;
 
     GDALColorTable *m_poColorTable;
@@ -378,58 +403,58 @@ class CPL_DLL VRTRasterBand : public GDALRasterBand
     virtual CPLErr         XMLInit( CPLXMLNode *, const char * );
     virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
 
-    virtual CPLErr SetNoDataValue( double );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr DeleteNoDataValue();
+    virtual CPLErr SetNoDataValue( double ) CPL_OVERRIDE;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    virtual CPLErr DeleteNoDataValue() CPL_OVERRIDE;
 
-    virtual CPLErr SetColorTable( GDALColorTable * );
-    virtual GDALColorTable *GetColorTable();
+    virtual CPLErr SetColorTable( GDALColorTable * ) CPL_OVERRIDE;
+    virtual GDALColorTable *GetColorTable() CPL_OVERRIDE;
 
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) CPL_OVERRIDE;
+    virtual GDALColorInterp GetColorInterpretation() CPL_OVERRIDE;
 
-    virtual const char *GetUnitType();
-    CPLErr SetUnitType( const char * );
+    virtual const char *GetUnitType() CPL_OVERRIDE;
+    CPLErr SetUnitType( const char * ) CPL_OVERRIDE;
 
-    virtual char **GetCategoryNames();
-    virtual CPLErr SetCategoryNames( char ** );
+    virtual char **GetCategoryNames() CPL_OVERRIDE;
+    virtual CPLErr SetCategoryNames( char ** ) CPL_OVERRIDE;
 
-    virtual CPLErr SetMetadata( char **papszMD, const char *pszDomain = "" );
+    virtual CPLErr SetMetadata( char **papszMD, const char *pszDomain = "" ) CPL_OVERRIDE;
     virtual CPLErr SetMetadataItem( const char *pszName, const char *pszValue,
-                                    const char *pszDomain = "" );
+                                    const char *pszDomain = "" ) CPL_OVERRIDE;
 
-    virtual double GetOffset( int *pbSuccess = NULL );
-    CPLErr SetOffset( double );
-    virtual double GetScale( int *pbSuccess = NULL );
-    CPLErr SetScale( double );
+    virtual double GetOffset( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    CPLErr SetOffset( double ) CPL_OVERRIDE;
+    virtual double GetScale( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    CPLErr SetScale( double ) CPL_OVERRIDE;
 
-    virtual int GetOverviewCount();
-    virtual GDALRasterBand *GetOverview(int);
+    virtual int GetOverviewCount() CPL_OVERRIDE;
+    virtual GDALRasterBand *GetOverview(int) CPL_OVERRIDE;
 
     virtual CPLErr  GetHistogram( double dfMin, double dfMax,
-                          int nBuckets, GUIntBig * panHistogram,
-                          int bIncludeOutOfRange, int bApproxOK,
-                          GDALProgressFunc, void *pProgressData );
+                                  int nBuckets, GUIntBig * panHistogram,
+                                  int bIncludeOutOfRange, int bApproxOK,
+                                  GDALProgressFunc, void *pProgressData ) CPL_OVERRIDE;
 
     virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                         int *pnBuckets, GUIntBig ** ppanHistogram,
                                         int bForce,
-                                        GDALProgressFunc, void *pProgressData);
+                                        GDALProgressFunc, void *pProgressData) CPL_OVERRIDE;
 
     virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
-                                        int nBuckets, GUIntBig *panHistogram );
+                                        int nBuckets, GUIntBig *panHistogram ) CPL_OVERRIDE;
 
     CPLErr         CopyCommonInfoFrom( GDALRasterBand * );
 
     virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
                                int *pnMaxSize, CPLHashSet* hSetFiles);
 
-    virtual void   SetDescription( const char * );
+    virtual void   SetDescription( const char * ) CPL_OVERRIDE;
 
-    virtual GDALRasterBand *GetMaskBand();
-    virtual int             GetMaskFlags();
+    virtual GDALRasterBand *GetMaskBand() CPL_OVERRIDE;
+    virtual int             GetMaskFlags() CPL_OVERRIDE;
 
-    virtual CPLErr          CreateMaskBand( int nFlags );
+    virtual CPLErr          CreateMaskBand( int nFlags ) CPL_OVERRIDE;
 
     void SetMaskBand(VRTRasterBand* poMaskBand);
 
@@ -456,14 +481,13 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
     CPLString      m_osLastLocationInfo;
     char         **m_papszSourceList;
 
-    void           Initialize( int nXSize, int nYSize );
-
-    int            CanUseSourcesMinMaxImplementations();
+    bool           CanUseSourcesMinMaxImplementations();
+    void           CheckSource( VRTSimpleSource *poSS );
 
   public:
     int            nSources;
     VRTSource    **papoSources;
-    int            bEqualAreas;
+    int            bSkipBufferInitialization;
 
                    VRTSourcedRasterBand( GDALDataset *poDS, int nBand );
                    VRTSourcedRasterBand( GDALDataType eType,
@@ -476,32 +500,39 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) CPL_OVERRIDE;
+
+    virtual int IGetDataCoverageStatus( int nXOff, int nYOff,
+                                        int nXSize, int nYSize,
+                                        int nMaskFlagStop,
+                                        double* pdfDataPct) CPL_OVERRIDE;
 
-    virtual char      **GetMetadataDomainList();
+    virtual char      **GetMetadataDomainList() CPL_OVERRIDE;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) CPL_OVERRIDE;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) CPL_OVERRIDE;
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) CPL_OVERRIDE;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                          const char * pszValue,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) CPL_OVERRIDE;
 
-    virtual CPLErr         XMLInit( CPLXMLNode *, const char * );
-    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
+    virtual CPLErr         XMLInit( CPLXMLNode *, const char * ) CPL_OVERRIDE;
+    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
 
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum(int *pbSuccess = NULL );
-    virtual CPLErr ComputeRasterMinMax( int bApproxOK, double* adfMinMax );
+    virtual double GetMinimum( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    virtual double GetMaximum(int *pbSuccess = NULL ) CPL_OVERRIDE;
+    virtual CPLErr ComputeRasterMinMax( int bApproxOK, double* adfMinMax ) CPL_OVERRIDE;
     virtual CPLErr ComputeStatistics( int bApproxOK,
                                       double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
-                                      GDALProgressFunc pfnProgress, void *pProgressData );
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData ) CPL_OVERRIDE;
     virtual CPLErr  GetHistogram( double dfMin, double dfMax,
                                   int nBuckets, GUIntBig * panHistogram,
                                   int bIncludeOutOfRange, int bApproxOK,
-                                  GDALProgressFunc pfnProgress, void *pProgressData );
+                                  GDALProgressFunc pfnProgress,
+                                  void *pProgressData ) CPL_OVERRIDE;
 
     CPLErr         AddSource( VRTSource * );
     CPLErr         AddSimpleSource( GDALRasterBand *poSrcBand,
@@ -523,29 +554,31 @@ class CPL_DLL VRTSourcedRasterBand : public VRTRasterBand
 
     CPLErr         AddMaskBandSource( GDALRasterBand *poSrcBand,
                                       double dfSrcXOff=-1, double dfSrcYOff=-1,
-                                      double dfSrcXSize=-1, double dfSrcYSize=-1,
+                                      double dfSrcXSize=-1,
+                                      double dfSrcYSize=-1,
                                       double dfDstXOff=-1, double dfDstYOff=-1,
-                                      double dfDstXSize=-1, double dfDstYSize=-1 );
+                                      double dfDstXSize=-1,
+                                      double dfDstYSize=-1 );
 
     CPLErr         AddFuncSource( VRTImageReadFunc pfnReadFunc, void *hCBData,
                                   double dfNoDataValue = VRT_NODATA_UNSET );
 
     void           ConfigureSource(VRTSimpleSource *poSimpleSource,
-                                           GDALRasterBand *poSrcBand,
-                                           int bAddAsMaskBand,
-                                           double dfSrcXOff, double dfSrcYOff,
-                                           double dfSrcXSize, double dfSrcYSize,
-                                           double dfDstXOff, double dfDstYOff,
-                                           double dfDstXSize, double dfDstYSize);
+                                   GDALRasterBand *poSrcBand,
+                                   int bAddAsMaskBand,
+                                   double dfSrcXOff, double dfSrcYOff,
+                                   double dfSrcXSize, double dfSrcYSize,
+                                   double dfDstXOff, double dfDstYOff,
+                                   double dfDstXSize, double dfDstYSize );
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
 
     virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
-                               int *pnMaxSize, CPLHashSet* hSetFiles);
+                               int *pnMaxSize, CPLHashSet* hSetFiles) CPL_OVERRIDE;
 
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() CPL_OVERRIDE;
 
-    virtual int         IsSourcedRasterBand() { return TRUE; }
+    virtual int         IsSourcedRasterBand() CPL_OVERRIDE { return TRUE; }
 };
 
 /************************************************************************/
@@ -556,17 +589,17 @@ class CPL_DLL VRTWarpedRasterBand : public VRTRasterBand
 {
   public:
                    VRTWarpedRasterBand( GDALDataset *poDS, int nBand,
-                                     GDALDataType eType = GDT_Unknown );
+                                        GDALDataType eType = GDT_Unknown );
     virtual        ~VRTWarpedRasterBand();
 
-    virtual CPLErr         XMLInit( CPLXMLNode *, const char * );
-    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
+    virtual CPLErr         XMLInit( CPLXMLNode *, const char * ) CPL_OVERRIDE;
+    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
+    virtual CPLErr IWriteBlock( int, int, void * ) CPL_OVERRIDE;
 
-    virtual int GetOverviewCount();
-    virtual GDALRasterBand *GetOverview(int);
+    virtual int GetOverviewCount() CPL_OVERRIDE;
+    virtual GDALRasterBand *GetOverview(int) CPL_OVERRIDE;
 };
 /************************************************************************/
 /*                        VRTPansharpenedRasterBand                     */
@@ -577,62 +610,89 @@ class VRTPansharpenedRasterBand : public VRTRasterBand
     int               m_nIndexAsPansharpenedBand;
 
   public:
-                   VRTPansharpenedRasterBand( GDALDataset *poDS, int nBand,
-                                              GDALDataType eDataType = GDT_Unknown );
+                   VRTPansharpenedRasterBand(
+                       GDALDataset *poDS, int nBand,
+                       GDALDataType eDataType = GDT_Unknown );
     virtual        ~VRTPansharpenedRasterBand();
 
-    virtual CPLErr         XMLInit( CPLXMLNode *, const char * );
-    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
+    virtual CPLErr         XMLInit( CPLXMLNode *, const char * ) CPL_OVERRIDE;
+    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
 
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
                                GDALDataType eBufType,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg) CPL_OVERRIDE;
 
-    virtual int GetOverviewCount();
-    virtual GDALRasterBand *GetOverview(int);
+    virtual int GetOverviewCount() CPL_OVERRIDE;
+    virtual GDALRasterBand *GetOverview(int) CPL_OVERRIDE;
 
-    virtual int         IsPansharpenRasterBand() { return TRUE; }
+    virtual int         IsPansharpenRasterBand() CPL_OVERRIDE { return TRUE; }
 
-    void                SetIndexAsPansharpenedBand(int nIdx) { m_nIndexAsPansharpenedBand = nIdx; }
-    int                 GetIndexAsPansharpenedBand() const { return m_nIndexAsPansharpenedBand; }
+    void                SetIndexAsPansharpenedBand( int nIdx )
+        { m_nIndexAsPansharpenedBand = nIdx; }
+    int                 GetIndexAsPansharpenedBand() const
+        { return m_nIndexAsPansharpenedBand; }
 };
 
 /************************************************************************/
 /*                         VRTDerivedRasterBand                         */
 /************************************************************************/
 
+class VRTDerivedRasterBandPrivateData;
+
 class CPL_DLL VRTDerivedRasterBand : public VRTSourcedRasterBand
 {
+    VRTDerivedRasterBandPrivateData* m_poPrivate;
+    bool InitializePython();
 
  public:
     char *pszFuncName;
     GDALDataType eSourceTransferType;
 
-    VRTDerivedRasterBand(GDALDataset *poDS, int nBand);
-    VRTDerivedRasterBand(GDALDataset *poDS, int nBand,
-                         GDALDataType eType, int nXSize, int nYSize);
+    VRTDerivedRasterBand( GDALDataset *poDS, int nBand );
+    VRTDerivedRasterBand( GDALDataset *poDS, int nBand,
+                          GDALDataType eType, int nXSize, int nYSize );
     virtual        ~VRTDerivedRasterBand();
 
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
-    static CPLErr AddPixelFunction
-        (const char *pszFuncName, GDALDerivedPixelFunc pfnPixelFunc);
-    static GDALDerivedPixelFunc GetPixelFunction(const char *pszFuncName);
+    virtual int IGetDataCoverageStatus( int nXOff, int nYOff,
+                                        int nXSize, int nYSize,
+                                        int nMaskFlagStop,
+                                        double* pdfDataPct) CPL_OVERRIDE;
 
-    void SetPixelFunctionName(const char *pszFuncName);
-    void SetSourceTransferType(GDALDataType eDataType);
+    static CPLErr AddPixelFunction( const char *pszFuncName,
+                                    GDALDerivedPixelFunc pfnPixelFunc );
+    static GDALDerivedPixelFunc GetPixelFunction( const char *pszFuncName );
 
-    virtual CPLErr         XMLInit( CPLXMLNode *, const char * );
-    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
+    void SetPixelFunctionName( const char *pszFuncName );
+    void SetSourceTransferType( GDALDataType eDataType );
+
+    virtual CPLErr         XMLInit( CPLXMLNode *, const char * ) CPL_OVERRIDE;
+    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
+
+    virtual double GetMinimum( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    virtual double GetMaximum(int *pbSuccess = NULL ) CPL_OVERRIDE;
+    virtual CPLErr ComputeRasterMinMax( int bApproxOK, double* adfMinMax ) CPL_OVERRIDE;
+    virtual CPLErr ComputeStatistics( int bApproxOK,
+                                      double *pdfMin, double *pdfMax,
+                                      double *pdfMean, double *pdfStdDev,
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData ) CPL_OVERRIDE;
+    virtual CPLErr  GetHistogram( double dfMin, double dfMax,
+                                  int nBuckets, GUIntBig * panHistogram,
+                                  int bIncludeOutOfRange, int bApproxOK,
+                                  GDALProgressFunc pfnProgress,
+                                  void *pProgressData ) CPL_OVERRIDE;
 
+    static void Cleanup();
 };
 
 /************************************************************************/
@@ -653,16 +713,16 @@ class CPL_DLL VRTRawRasterBand : public VRTRasterBand
                                      GDALDataType eType = GDT_Unknown );
     virtual        ~VRTRawRasterBand();
 
-    virtual CPLErr         XMLInit( CPLXMLNode *, const char * );
-    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath );
+    virtual CPLErr         XMLInit( CPLXMLNode *, const char * ) CPL_OVERRIDE;
+    virtual CPLXMLNode *   SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
 
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
+    virtual CPLErr IWriteBlock( int, int, void * ) CPL_OVERRIDE;
 
     CPLErr         SetRawLink( const char *pszFilename,
                                const char *pszVRTPath,
@@ -673,8 +733,8 @@ class CPL_DLL VRTRawRasterBand : public VRTRasterBand
 
     void           ClearRawLink();
 
-    virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
-                               int *pnMaxSize, CPLHashSet* hSetFiles);
+    virtual void   GetFileList( char*** ppapszFileList, int *pnSize,
+                                int *pnMaxSize, CPLHashSet* hSetFiles ) CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -683,18 +743,16 @@ class CPL_DLL VRTRawRasterBand : public VRTRasterBand
 
 class VRTDriver : public GDALDriver
 {
-    void        *m_pDeserializerData;
-
   public:
                  VRTDriver();
-                 ~VRTDriver();
+    virtual ~VRTDriver();
 
     char         **papszSourceParsers;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadataDomainList() CPL_OVERRIDE;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) CPL_OVERRIDE;
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) CPL_OVERRIDE;
 
     VRTSource   *ParseSource( CPLXMLNode *psSrc, const char *pszVRTPath );
     void         AddSourceParser( const char *pszElementName,
@@ -708,10 +766,12 @@ class VRTDriver : public GDALDriver
 class CPL_DLL VRTSimpleSource : public VRTSource
 {
 protected:
+    friend class VRTSourcedRasterBand;
+
     GDALRasterBand      *m_poRasterBand;
 
-    /* when poRasterBand is a mask band, poMaskBandMainBand is the band */
-    /* from which the mask band is taken */
+    // When poRasterBand is a mask band, poMaskBandMainBand is the band
+    // from which the mask band is taken.
     GDALRasterBand      *m_poMaskBandMainBand;
 
     double              m_dfSrcXOff;
@@ -737,12 +797,12 @@ protected:
 
 public:
             VRTSimpleSource();
-            VRTSimpleSource(const VRTSimpleSource* poSrcSource,
-                                 double dfXDstRatio, double dfYDstRatio);
+            VRTSimpleSource( const VRTSimpleSource* poSrcSource,
+                             double dfXDstRatio, double dfYDstRatio );
     virtual ~VRTSimpleSource();
 
-    virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * );
-    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
+    virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * ) CPL_OVERRIDE;
+    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
 
     void           SetSrcBand( GDALRasterBand * );
     void           SetSrcMaskBand( GDALRasterBand * );
@@ -762,35 +822,38 @@ public:
                               void *pData, int nBufXSize, int nBufYSize,
                               GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
-    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess );
-    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
-    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax );
+    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess ) CPL_OVERRIDE;
+    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess ) CPL_OVERRIDE;
+    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK,
+                                        double* adfMinMax ) CPL_OVERRIDE;
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
                                       int bApproxOK,
                                       double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
-                                      GDALProgressFunc pfnProgress, void *pProgressData );
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData ) CPL_OVERRIDE;
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
                                   double dfMin, double dfMax,
                                   int nBuckets, GUIntBig * panHistogram,
                                   int bIncludeOutOfRange, int bApproxOK,
-                                  GDALProgressFunc pfnProgress, void *pProgressData );
+                                  GDALProgressFunc pfnProgress,
+                                  void *pProgressData ) CPL_OVERRIDE;
 
     void            DstToSrc( double dfX, double dfY,
                               double &dfXOut, double &dfYOut );
     void            SrcToDst( double dfX, double dfY,
                               double &dfXOut, double &dfYOut );
 
-    virtual void   GetFileList(char*** ppapszFileList, int *pnSize,
-                               int *pnMaxSize, CPLHashSet* hSetFiles);
+    virtual void   GetFileList( char*** ppapszFileList, int *pnSize,
+                                int *pnMaxSize, CPLHashSet* hSetFiles ) CPL_OVERRIDE;
 
-    virtual int    IsSimpleSource() { return TRUE; }
+    virtual int    IsSimpleSource() CPL_OVERRIDE { return TRUE; }
     virtual const char* GetType() { return "SimpleSource"; }
 
     GDALRasterBand* GetBand();
-    int             IsSameExceptBandNumber(VRTSimpleSource* poOtherSource);
+    int             IsSameExceptBandNumber( VRTSimpleSource* poOtherSource );
     CPLErr          DatasetRasterIO(
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
@@ -798,11 +861,11 @@ public:
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg );
 
     void             UnsetPreservedRelativeFilenames();
 
-    void                SetMaxValue(int nVal) { m_nMaxValue = nVal; }
+    void             SetMaxValue( int nVal ) { m_nMaxValue = nVal; }
 };
 
 /************************************************************************/
@@ -817,24 +880,27 @@ public:
                               void *pData, int nBufXSize, int nBufYSize,
                               GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
-    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess );
-    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
-    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax );
+    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess ) CPL_OVERRIDE;
+    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess ) CPL_OVERRIDE;
+    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK,
+                                        double* adfMinMax ) CPL_OVERRIDE;
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
                                       int bApproxOK,
                                       double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
-                                      GDALProgressFunc pfnProgress, void *pProgressData );
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData ) CPL_OVERRIDE;
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
                                   double dfMin, double dfMax,
                                   int nBuckets, GUIntBig * panHistogram,
                                   int bIncludeOutOfRange, int bApproxOK,
-                                  GDALProgressFunc pfnProgress, void *pProgressData );
+                                  GDALProgressFunc pfnProgress,
+                                  void *pProgressData ) CPL_OVERRIDE;
 
-    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
-    virtual const char* GetType() { return "AveragedSource"; }
+    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
+    virtual const char* GetType() CPL_OVERRIDE { return "AveragedSource"; }
 };
 
 /************************************************************************/
@@ -852,10 +918,10 @@ class CPL_DLL VRTComplexSource : public VRTSimpleSource
 {
 protected:
     VRTComplexSourceScaling m_eScalingType;
-    double         m_dfScaleOff; /* for linear scaling */
-    double         m_dfScaleRatio; /* for linear scaling */
+    double         m_dfScaleOff;  // For linear scaling.
+    double         m_dfScaleRatio;  // For linear scaling.
 
-    /* For non-linear scaling with a power function. */
+    // For non-linear scaling with a power function.
     int            m_bSrcMinMaxDefined;
     double         m_dfSrcMin;
     double         m_dfSrcMax;
@@ -884,40 +950,42 @@ public:
                              void *pData, int nBufXSize, int nBufYSize,
                              GDALDataType eBufType,
                              GSpacing nPixelSpace, GSpacing nLineSpace,
-                             GDALRasterIOExtraArg* psExtraArg );
+                             GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
-    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess );
-    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
-    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax );
+    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess ) CPL_OVERRIDE;
+    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess ) CPL_OVERRIDE;
+    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK,
+                                        double* adfMinMax ) CPL_OVERRIDE;
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
                                       int bApproxOK,
                                       double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
-                                      GDALProgressFunc pfnProgress, void *pProgressData );
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData ) CPL_OVERRIDE;
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
                                   double dfMin, double dfMax,
                                   int nBuckets, GUIntBig * panHistogram,
                                   int bIncludeOutOfRange, int bApproxOK,
-                                  GDALProgressFunc pfnProgress, void *pProgressData );
+                                  GDALProgressFunc pfnProgress,
+                                  void *pProgressData ) CPL_OVERRIDE;
 
-    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
-    virtual CPLErr XMLInit( CPLXMLNode *, const char * );
-    virtual const char* GetType() { return "ComplexSource"; }
+    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
+    virtual CPLErr XMLInit( CPLXMLNode *, const char * ) CPL_OVERRIDE;
+    virtual const char* GetType() CPL_OVERRIDE { return "ComplexSource"; }
 
     double  LookupValue( double dfInput );
 
-    void    SetLinearScaling(double dfOffset, double dfScale);
-    void    SetPowerScaling(double dfExponent,
-                            double dfSrcMin,
-                            double dfSrcMax,
-                            double dfDstMin,
-                            double dfDstMax);
-    void    SetColorTableComponent(int nComponent);
+    void    SetLinearScaling( double dfOffset, double dfScale );
+    void    SetPowerScaling( double dfExponent,
+                             double dfSrcMin,
+                             double dfSrcMax,
+                             double dfDstMin,
+                             double dfDstMax );
+    void    SetColorTableComponent( int nComponent );
 
     double         *m_padfLUTInputs;
     double         *m_padfLUTOutputs;
     int            m_nLUTItemCount;
-
 };
 
 /************************************************************************/
@@ -949,7 +1017,7 @@ public:
                               void *pData, int nBufXSize, int nBufYSize,
                               GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -969,11 +1037,11 @@ public:
             VRTKernelFilteredSource();
     virtual ~VRTKernelFilteredSource();
 
-    virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * );
-    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
+    virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * ) CPL_OVERRIDE;
+    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
 
     virtual CPLErr  FilterData( int nXSize, int nYSize, GDALDataType eType,
-                                GByte *pabySrcData, GByte *pabyDstData );
+                                GByte *pabySrcData, GByte *pabyDstData ) CPL_OVERRIDE;
 
     CPLErr          SetKernel( int nKernelSize, double *padfCoefs );
     void            SetNormalized( int );
@@ -989,8 +1057,8 @@ public:
             explicit VRTAverageFilteredSource( int nKernelSize );
     virtual ~VRTAverageFilteredSource();
 
-    virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * );
-    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
+    virtual CPLErr  XMLInit( CPLXMLNode *psTree, const char * ) CPL_OVERRIDE;
+    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -1002,28 +1070,31 @@ public:
             VRTFuncSource();
     virtual ~VRTFuncSource();
 
-    virtual CPLErr  XMLInit( CPLXMLNode *, const char *) { return CE_Failure; }
-    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
+    virtual CPLErr  XMLInit( CPLXMLNode *, const char *) CPL_OVERRIDE { return CE_Failure; }
+    virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath ) CPL_OVERRIDE;
 
     virtual CPLErr  RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                               void *pData, int nBufXSize, int nBufYSize,
                               GDALDataType eBufType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
-    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess );
-    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess );
-    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax );
+    virtual double GetMinimum( int nXSize, int nYSize, int *pbSuccess ) CPL_OVERRIDE;
+    virtual double GetMaximum( int nXSize, int nYSize, int *pbSuccess ) CPL_OVERRIDE;
+    virtual CPLErr ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK,
+                                        double* adfMinMax ) CPL_OVERRIDE;
     virtual CPLErr ComputeStatistics( int nXSize, int nYSize,
                                       int bApproxOK,
                                       double *pdfMin, double *pdfMax,
                                       double *pdfMean, double *pdfStdDev,
-                                      GDALProgressFunc pfnProgress, void *pProgressData );
+                                      GDALProgressFunc pfnProgress,
+                                      void *pProgressData ) CPL_OVERRIDE;
     virtual CPLErr  GetHistogram( int nXSize, int nYSize,
                                   double dfMin, double dfMax,
                                   int nBuckets, GUIntBig * panHistogram,
                                   int bIncludeOutOfRange, int bApproxOK,
-                                  GDALProgressFunc pfnProgress, void *pProgressData );
+                                  GDALProgressFunc pfnProgress,
+                                  void *pProgressData ) CPL_OVERRIDE;
 
     VRTImageReadFunc    pfnReadFunc;
     void               *pCBData;
@@ -1032,4 +1103,6 @@ public:
     float               fNoDataValue;
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* ndef VIRTUALDATASET_H_INCLUDED */
diff --git a/frmts/vrt/vrtderivedrasterband.cpp b/frmts/vrt/vrtderivedrasterband.cpp
index d42f2eb..76b9f89 100644
--- a/frmts/vrt/vrtderivedrasterband.cpp
+++ b/frmts/vrt/vrtderivedrasterband.cpp
@@ -28,12 +28,897 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-#include "vrtdataset.h"
 #include "cpl_minixml.h"
 #include "cpl_string.h"
+#include "vrtdataset.h"
+#include "cpl_multiproc.h"
+#include "cpl_spawn.h"
+
+#if !defined(WIN32)
+  #include <sys/stat.h>
+  #include <sys/types.h>
+  #ifdef HAVE_UNISTD_H
+    #include <unistd.h>
+  #endif
+#endif
+
+#include <algorithm>
 #include <map>
+#include <vector>
+#include <utility>
+
+/*! @cond Doxygen_Suppress */
+
+CPL_CVSID("$Id: vrtderivedrasterband.cpp 36981 2016-12-20 19:46:41Z rouault $");
+
+// #define GDAL_VRT_DISABLE_PYTHON
+// #define PYTHONSO_DEFAULT "libpython2.7.so"
+
+#ifndef GDAL_VRT_ENABLE_PYTHON_DEFAULT
+// Can be YES, NO or TRUSTED_MODULES
+#define GDAL_VRT_ENABLE_PYTHON_DEFAULT "TRUSTED_MODULES"
+#endif
 
 static std::map<CPLString, GDALDerivedPixelFunc> osMapPixelFunction;
+static bool gbHasInitializedPython = false;
+static int gnPythonInstanceCounter = 0;
+static CPLMutex* ghMutex = NULL;
+
+// Subset of Python API defined as function of pointers
+typedef struct PyObject_t PyObject;
+#define Py_file_input 257
+static void (*Py_SetProgramName)(const char*) = NULL;
+static PyObject* (*PyBuffer_FromReadWriteMemory)(void*, size_t) = NULL;
+static PyObject* (*PyTuple_New)(size_t) = NULL;
+static PyObject* (*PyInt_FromLong)(long) = NULL;
+static PyObject* (*PyFloat_FromDouble)(double) = NULL;
+static PyObject* (*PyObject_Call)(PyObject*, PyObject*, PyObject*) = NULL;
+static void (*Py_IncRef)(PyObject*) = NULL;
+static void (*Py_DecRef)(PyObject*) = NULL;
+static PyObject* (*PyErr_Occurred)(void) = NULL;
+static void (*PyErr_Print)(void) = NULL;
+static int (*Py_IsInitialized)(void) = NULL;
+static void (*Py_InitializeEx)(int) = NULL;
+static void (*PyEval_InitThreads)(void) = NULL;
+typedef struct PyThreadState_t PyThreadState;
+static PyThreadState* (*PyEval_SaveThread)(void) = NULL;
+static void (*PyEval_RestoreThread)(PyThreadState*) = NULL;
+static void (*Py_Finalize)(void) = NULL;
+static PyObject* (*Py_CompileString)(const char*, const char*, int) = NULL;
+static PyObject* (*PyImport_ExecCodeModule)(const char*, PyObject*) = NULL;
+static PyObject* (*PyObject_GetAttrString)(PyObject*, const char*) = NULL;
+static int (*PyTuple_SetItem)(PyObject *, size_t, PyObject *) = NULL;
+static void (*PyObject_Print)(PyObject*,FILE*,int) = NULL;
+static PyObject* (*PyString_FromStringAndSize)(const void*, size_t) = NULL;
+static PyObject* (*PyImport_ImportModule)(const char*) = NULL;
+static int (*PyCallable_Check)(PyObject*) = NULL;
+static PyObject* (*PyDict_New)(void) = NULL;
+static int (*PyDict_SetItemString)(PyObject *p, const char *key,
+                                   PyObject *val) = NULL;
+static void (*PyErr_Fetch)(PyObject **poPyType, PyObject **poPyValue,
+                           PyObject **poPyTraceback) = NULL;
+static void (*PyErr_Clear)(void) = NULL;
+static const char* (*PyString_AsString)(PyObject*) = NULL;
+static const char* (*Py_GetVersion)(void) = NULL;
+
+typedef int PyGILState_STATE;
+static PyGILState_STATE (*PyGILState_Ensure)(void) = NULL;
+static void (*PyGILState_Release)(PyGILState_STATE) = NULL;
+
+/* Flags for getting buffers */
+#define PyBUF_WRITABLE 0x0001
+#define PyBUF_FORMAT 0x0004
+#define PyBUF_ND 0x0008
+#define PyBUF_STRIDES (0x0010 | PyBUF_ND)
+#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
+#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT)
+
+typedef struct
+{
+    //cppcheck-suppress unusedStructMember
+    char big_enough[256];
+} Py_buffer;
+static int (*PyBuffer_FillInfo)(Py_buffer *view, PyObject *obj, void *buf,
+                                size_t len, int readonly, int infoflags) = NULL;
+static PyObject* (*PyMemoryView_FromBuffer)(Py_buffer *view) = NULL;
+
+static PyThreadState* gphThreadState = NULL;
+
+/************************************************************************/
+/*                        GDALCreateNumpyArray()                        */
+/************************************************************************/
+
+static PyObject* GDALCreateNumpyArray(PyObject* pCreateArray,
+                                      void* pBuffer,
+                                      GDALDataType eType,
+                                      int nHeight,
+                                      int nWidth )
+{
+    PyObject* poPyBuffer;
+    const size_t nSize = static_cast<size_t>(nHeight) * nWidth *
+                                    GDALGetDataTypeSizeBytes(eType);
+    if( PyBuffer_FromReadWriteMemory )
+    {
+        // Python 2
+        poPyBuffer = PyBuffer_FromReadWriteMemory(pBuffer, nSize);
+    }
+    else
+    {
+        // Python 3
+        Py_buffer pybuffer;
+        if( PyBuffer_FillInfo(&pybuffer, NULL, (char*)pBuffer,
+                              nSize,
+                              0, PyBUF_FULL) != 0)
+        {
+            return NULL;
+        }
+        poPyBuffer = PyMemoryView_FromBuffer(&pybuffer);
+    }
+    PyObject* pArgsCreateArray = PyTuple_New(4);
+    PyTuple_SetItem(pArgsCreateArray, 0, poPyBuffer);
+    const char* pszDataType = NULL;
+    switch( eType )
+    {
+        case GDT_Byte: pszDataType = "uint8"; break;
+        case GDT_UInt16: pszDataType = "uint16"; break;
+        case GDT_Int16: pszDataType = "int16"; break;
+        case GDT_UInt32: pszDataType = "uint32"; break;
+        case GDT_Int32: pszDataType = "int32"; break;
+        case GDT_Float32: pszDataType = "float32"; break;
+        case GDT_Float64: pszDataType = "float64"; break;
+        case GDT_CInt16:
+        case GDT_CInt32:
+            CPLAssert(FALSE);
+            break;
+        case GDT_CFloat32: pszDataType = "complex64"; break;
+        case GDT_CFloat64: pszDataType = "complex128"; break;
+        default:
+            CPLAssert(FALSE);
+            break;
+    }
+    PyTuple_SetItem(pArgsCreateArray, 1,
+                PyString_FromStringAndSize(pszDataType, strlen(pszDataType)));
+    PyTuple_SetItem(pArgsCreateArray, 2, PyInt_FromLong(nHeight));
+    PyTuple_SetItem(pArgsCreateArray, 3, PyInt_FromLong(nWidth));
+    PyObject* poNumpyArray = PyObject_Call(pCreateArray, pArgsCreateArray, NULL);
+    Py_DecRef(pArgsCreateArray);
+    if (PyErr_Occurred())
+        PyErr_Print();
+    return poNumpyArray;
+}
+
+/* MinGW32 might define HAVE_DLFCN_H, so skip the unix implementation */
+#if defined(HAVE_DLFCN_H) && !defined(WIN32)
+
+#include <dlfcn.h>
+
+typedef void* LibraryHandle;
+
+#define LOAD_NOCHECK_WITH_NAME(libHandle, x, name) \
+    do { \
+            void* ptr = dlsym(libHandle, name); \
+            memcpy(&x, &ptr, sizeof(void*)); \
+    } while(0)
+
+#elif defined(WIN32)
+
+#include <windows.h>
+#include <psapi.h>
+
+typedef HMODULE LibraryHandle;
+
+#define LOAD_NOCHECK_WITH_NAME(libHandle, x, name) \
+    do { \
+            FARPROC ptr = GetProcAddress(libHandle, name); \
+            memcpy(&x, &ptr, sizeof(void*)); \
+    } while(0)
+
+#endif
+
+#define STRINGIFY(x) #x
+
+#define LOAD_NOCHECK(libHandle, x) LOAD_NOCHECK_WITH_NAME(libHandle, x, STRINGIFY(x))
+#define LOAD_WITH_NAME(libHandle, x, name) \
+    do { \
+            LOAD_NOCHECK_WITH_NAME(libHandle, x, name); \
+            if (!x) \
+            { \
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", name); \
+                return false; \
+            } \
+    } while(0)
+#define LOAD(libHandle, x) LOAD_WITH_NAME(libHandle, x, STRINGIFY(x))
+
+/************************************************************************/
+/*                          LoadPythonAPI()                             */
+/************************************************************************/
+
+#if defined(LOAD_NOCHECK_WITH_NAME) && defined(HAVE_DLFCN_H) && !defined(WIN32)
+static LibraryHandle libHandleStatic = NULL;
+#endif
+
+/** Load the subset of the Python C API that we need */
+static bool LoadPythonAPI()
+{
+    CPLMutexHolder oHolder(&ghMutex);
+
+    static bool bInit = false;
+    if( bInit )
+        return true;
+
+#ifdef LOAD_NOCHECK_WITH_NAME
+    // The static here is just to avoid Coverity warning about resource leak.
+    LibraryHandle libHandle = NULL;
+
+    const char* pszPythonSO = CPLGetConfigOption("PYTHONSO", NULL);
+#if defined(HAVE_DLFCN_H) && !defined(WIN32)
+
+    // First try in the current process in case the python symbols would
+    // be already loaded
+    libHandle = dlopen(NULL, RTLD_LAZY);
+    libHandleStatic = libHandle;
+    if( libHandle != NULL &&
+        dlsym(libHandle, "Py_SetProgramName") != NULL )
+    {
+        CPLDebug("VRT", "Current process has python symbols loaded");
+    }
+    else
+    {
+        libHandle = NULL;
+    }
+
+    // Then try the user provided shared object name
+    if( libHandle == NULL && pszPythonSO != NULL )
+    {
+        // coverity[tainted_string]
+        libHandle = dlopen(pszPythonSO, RTLD_NOW | RTLD_GLOBAL);
+        if( libHandle == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot load %s",
+                     pszPythonSO);
+            return false;
+        }
+        if( dlsym(libHandle, "Py_SetProgramName") == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot find Py_SetProgramName symbol in %s",
+                     pszPythonSO);
+            return false;
+        }
+    }
+
+    // Then try the PYTHONSO_DEFAULT if defined at compile time
+#ifdef PYTHONSO_DEFAULT
+    if( libHandle == NULL )
+    {
+        libHandle = dlopen(PYTHONSO_DEFAULT, RTLD_NOW | RTLD_GLOBAL);
+        if( !libHandle )
+        {
+            CPLDebug("VRT", "%s found", PYTHONSO_DEFAULT);
+        }
+    }
+#endif
+
+    // Then try to find the libpython that corresponds to the python binary
+    // in the PATH
+    if( libHandle == NULL )
+    {
+#if defined(__MACH__) && defined(__APPLE__)
+#define SO_EXT "dylib"
+#else
+#define SO_EXT "so"
+#endif
+        CPLString osVersion;
+        char* pszPath = getenv("PATH");
+        if( pszPath != NULL
+#ifdef DEBUG
+           // For testing purposes
+           && CPLTestBool( CPLGetConfigOption(
+                                    "VRT_ENABLE_PYTHON_PATH", "YES") )
+#endif
+          )
+        {
+            char** papszTokens = CSLTokenizeString2(pszPath, ":", 0);
+            for( int iTry = 0; iTry < 2; ++iTry )
+            {
+                for( char** papszIter = papszTokens;
+                        papszIter != NULL && *papszIter != NULL;
+                        ++papszIter )
+                {
+                    struct stat sStat;
+                    CPLString osPythonBinary(
+                        CPLFormFilename(*papszIter, "python", NULL));
+                    if( iTry == 1 )
+                        osPythonBinary += "3";
+                    if( lstat(osPythonBinary, &sStat) != 0 )
+                        continue;
+
+                    CPLDebug("VRT", "Found %s", osPythonBinary.c_str());
+
+                    if( S_ISLNK(sStat.st_mode)
+#ifdef DEBUG
+                        // For testing purposes
+                        && CPLTestBool( CPLGetConfigOption(
+                                    "VRT_ENABLE_PYTHON_SYMLINK", "YES") )
+#endif
+                        )
+                    {
+                        // If this is a symlink, hopefully the resolved
+                        // name will be like "python2.7"
+                        const int nBufSize = 2048;
+                        std::vector<char> oFilename(nBufSize);
+                        char *szPointerFilename = &oFilename[0];
+                        int nBytes = static_cast<int>(
+                            readlink( osPythonBinary, szPointerFilename,
+                                      nBufSize ) );
+                        if (nBytes != -1)
+                        {
+                            szPointerFilename[std::min(nBytes,
+                                                       nBufSize - 1)] = 0;
+                            CPLString osFilename(
+                                            CPLGetFilename(szPointerFilename));
+                            CPLDebug("VRT", "Which is an alias to: %s",
+                                     szPointerFilename);
+                            if( STARTS_WITH(osFilename, "python") )
+                            {
+                                osVersion = osFilename.substr(strlen("python"));
+                                CPLDebug("VRT",
+                                         "Python version from binary name: %s",
+                                         osVersion.c_str());
+                            }
+                        }
+                        else
+                        {
+                            CPLDebug("VRT", "realink(%s) failed",
+                                        osPythonBinary.c_str());
+                        }
+                    }
+
+                    // Otherwise, expensive way: start the binary and ask
+                    // it for its version...
+                    if( osVersion.empty() )
+                    {
+                        const char* pszPrintVersion =
+                            "import sys; print(str(sys.version_info[0]) +"
+                            "'.' + str(sys.version_info[1]))";
+                        const char* const apszArgv[] = {
+                                osPythonBinary.c_str(), "-c",
+                                pszPrintVersion,
+                                NULL };
+                        const CPLString osTmpFilename(
+                                        "/vsimem/LoadPythonAPI/out.txt");
+                        VSILFILE* fout = VSIFOpenL( osTmpFilename, "wb+");
+                        if( CPLSpawn( apszArgv, NULL, fout, FALSE ) == 0 )
+                        {
+                            char* pszStr = reinterpret_cast<char*>(
+                                VSIGetMemFileBuffer( osTmpFilename,
+                                                        NULL, FALSE ));
+                            osVersion = pszStr;
+                            if( !osVersion.empty() &&
+                                osVersion.back() == '\n' )
+                            {
+                                osVersion.resize(osVersion.size() - 1);
+                            }
+                            CPLDebug("VRT", "Python version from binary: %s",
+                                        osVersion.c_str());
+                        }
+                        VSIFCloseL(fout);
+                        VSIUnlink(osTmpFilename);
+                    }
+                    break;
+                }
+                if( !osVersion.empty() )
+                    break;
+            }
+            CSLDestroy(papszTokens);
+        }
+
+        if( !osVersion.empty() )
+        {
+            CPLString osPythonSO("libpython");
+            osPythonSO += osVersion + "." SO_EXT;
+            CPLDebug("VRT", "Trying %s", osPythonSO.c_str());
+            libHandle = dlopen(osPythonSO, RTLD_NOW | RTLD_GLOBAL);
+            if( libHandle != NULL )
+            {
+                CPLDebug("VRT", "... success");
+            }
+            else if( osVersion[0] == '3' )
+            {
+                osPythonSO = "libpython" + osVersion + "m." SO_EXT;
+                CPLDebug("VRT", "Trying %s", osPythonSO.c_str());
+                libHandle = dlopen(osPythonSO, RTLD_NOW | RTLD_GLOBAL);
+                if( libHandle != NULL )
+                {
+                    CPLDebug("VRT", "... success");
+                }
+            }
+        }
+    }
+
+    // Otherwise probe a few known objects.
+    // Note: update vrt_tutorial.dox if change
+    if( libHandle == NULL )
+    {
+        const char* const apszPythonSO[] = { "libpython2.7." SO_EXT,
+                                                "libpython2.6." SO_EXT,
+                                                "libpython3.4m." SO_EXT,
+                                                "libpython3.5m." SO_EXT,
+                                                "libpython3.6m." SO_EXT,
+                                                "libpython3.3." SO_EXT,
+                                                "libpython3.2." SO_EXT };
+        for( size_t i = 0; libHandle == NULL &&
+                            i < CPL_ARRAYSIZE(apszPythonSO); ++i )
+        {
+            CPLDebug("VRT", "Trying %s", apszPythonSO[i]);
+            libHandle = dlopen(apszPythonSO[i], RTLD_NOW | RTLD_GLOBAL);
+            if( libHandle != NULL )
+                CPLDebug("VRT", "... success");
+        }
+    }
+
+#elif defined(WIN32)
+
+    // First try in the current process in case the python symbols would
+    // be already loaded
+    HANDLE hProcess = GetCurrentProcess();
+    HMODULE ahModules[100];
+    DWORD nSizeNeeded = 0;
+
+    EnumProcessModules(hProcess, ahModules, sizeof(ahModules),
+                        &nSizeNeeded);
+
+    const size_t nModules =
+        std::min(size_t(100),
+                 static_cast<size_t>(nSizeNeeded) / sizeof(HMODULE));
+    for( size_t i = 0; i < nModules; i++ )
+    {
+        if( GetProcAddress(ahModules[i], "Py_SetProgramName") )
+        {
+            libHandle = ahModules[i];
+            CPLDebug("VRT", "Current process has python symbols loaded");
+            break;
+        }
+    }
+
+    // Then try the user provided shared object name
+    if( libHandle == NULL && pszPythonSO != NULL )
+    {
+        UINT        uOldErrorMode;
+        /* Avoid error boxes to pop up (#5211, #5525) */
+        uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX |
+                                     SEM_FAILCRITICALERRORS);
+
+#if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
+        if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+        {
+            wchar_t *pwszFilename =
+                CPLRecodeToWChar( pszPythonSO, CPL_ENC_UTF8, CPL_ENC_UCS2 );
+            libHandle = LoadLibraryW(pwszFilename);
+            CPLFree( pwszFilename );
+        }
+        else
+#endif
+        {
+            libHandle = LoadLibrary(pszPythonSO);
+        }
+
+        SetErrorMode(uOldErrorMode);
+
+        if( libHandle == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot load %s",
+                     pszPythonSO);
+            return false;
+        }
+        if( GetProcAddress(libHandle, "Py_SetProgramName") == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot find Py_SetProgramName symbol in %s",
+                     pszPythonSO);
+            return false;
+        }
+    }
+
+    // Then try the PYTHONSO_DEFAULT if defined at compile time
+#ifdef PYTHONSO_DEFAULT
+    if( libHandle == NULL )
+    {
+        UINT        uOldErrorMode;
+        uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX |
+                                        SEM_FAILCRITICALERRORS);
+
+        libHandle = LoadLibrary(PYTHONSO_DEFAULT);
+        SetErrorMode(uOldErrorMode);
+        if( !libHandle )
+        {
+            CPLDebug("VRT", "%s found", PYTHONSO_DEFAULT);
+        }
+    }
+#endif
+
+    // Then try to find the pythonXY.dll that corresponds to the python binary
+    // in the PATH
+    if( libHandle == NULL )
+    {
+        CPLString osDLLName;
+        char* pszPath = getenv("PATH");
+        if( pszPath != NULL
+#ifdef DEBUG
+           // For testing purposes
+           && CPLTestBool( CPLGetConfigOption(
+                                    "VRT_ENABLE_PYTHON_PATH", "YES") )
+#endif
+          )
+        {
+            char** papszTokens = CSLTokenizeString2(pszPath, ";", 0);
+            for( int iTry = 0; iTry < 2; ++iTry )
+            {
+                for( char** papszIter = papszTokens;
+                        papszIter != NULL && *papszIter != NULL;
+                        ++papszIter )
+                {
+                    VSIStatBufL sStat;
+                    CPLString osPythonBinary(
+                            CPLFormFilename(*papszIter, "python.exe", NULL));
+                    if( iTry == 1 )
+                        osPythonBinary += "3";
+                    if( VSIStatL(osPythonBinary, &sStat) != 0 )
+                        continue;
+
+                    CPLDebug("VRT", "Found %s", osPythonBinary.c_str());
+
+                    // In python2.7, the dll is in the same directory as the exe
+                    char** papszFiles = VSIReadDir(*papszIter);
+                    for( char** papszFileIter = papszFiles;
+                                papszFileIter != NULL && *papszFileIter != NULL;
+                                ++papszFileIter )
+                    {
+                        if( STARTS_WITH_CI(*papszFileIter, "python") &&
+                            EQUAL(CPLGetExtension(*papszFileIter), "dll") )
+                        {
+                            osDLLName = CPLFormFilename(*papszIter,
+                                                        *papszFileIter,
+                                                        NULL);
+                            break;
+                        }
+                    }
+                    CSLDestroy(papszFiles);
+
+                    // In python3.2, the dll is in the DLLs subdirectory
+                    if( osDLLName.empty() )
+                    {
+                        CPLString osDLLsDir(
+                                CPLFormFilename(*papszIter, "DLLs", NULL));
+                        papszFiles = VSIReadDir( osDLLsDir );
+                        for( char** papszFileIter = papszFiles;
+                                    papszFileIter != NULL && *papszFileIter != NULL;
+                                    ++papszFileIter )
+                        {
+                            if( STARTS_WITH_CI(*papszFileIter, "python") &&
+                                EQUAL(CPLGetExtension(*papszFileIter), "dll") )
+                            {
+                                osDLLName = CPLFormFilename(osDLLsDir,
+                                                            *papszFileIter,
+                                                            NULL);
+                                break;
+                            }
+                        }
+                        CSLDestroy(papszFiles);
+                    }
+
+                    break;
+                }
+                if( !osDLLName.empty() )
+                    break;
+            }
+            CSLDestroy(papszTokens);
+        }
+
+        if( !osDLLName.empty() )
+        {
+            //CPLDebug("VRT", "Trying %s", osDLLName.c_str());
+            UINT        uOldErrorMode;
+            uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX |
+                                            SEM_FAILCRITICALERRORS);
+            libHandle = LoadLibrary(osDLLName);
+            SetErrorMode(uOldErrorMode);
+            if( libHandle != NULL )
+            {
+                CPLDebug("VRT", "%s loaded", osDLLName.c_str());
+            }
+        }
+    }
+
+    // Otherwise probe a few known objects
+    // Note: update vrt_tutorial.dox if change
+    if( libHandle == NULL )
+    {
+        const char* const apszPythonSO[] = { "python27.dll",
+                                            "python26.dll",
+                                            "python34.dll",
+                                            "python35.dll",
+                                            "python36.dll",
+                                            "python33.dll",
+                                            "python32.dll" };
+        UINT        uOldErrorMode;
+        uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX |
+                                        SEM_FAILCRITICALERRORS);
+
+        for( size_t i = 0; libHandle == NULL &&
+                            i < CPL_ARRAYSIZE(apszPythonSO); ++i )
+        {
+            CPLDebug("VRT", "Trying %s", apszPythonSO[i]);
+            libHandle = LoadLibrary(apszPythonSO[i]);
+            if( libHandle != NULL )
+                CPLDebug("VRT", "... success");
+        }
+        SetErrorMode(uOldErrorMode);
+    }
+#endif
+    if( !libHandle )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find python/libpython. You can set the PYTHONSO "
+                 "configuration option to point to the a python .so/.dll/.dylib");
+        return false;
+    }
+
+    LOAD(libHandle, Py_SetProgramName);
+    LOAD_NOCHECK(libHandle, PyBuffer_FromReadWriteMemory);
+    LOAD_NOCHECK(libHandle, PyBuffer_FillInfo);
+    LOAD_NOCHECK(libHandle, PyMemoryView_FromBuffer);
+    if( PyBuffer_FromReadWriteMemory == NULL &&
+        (PyBuffer_FillInfo == NULL || PyMemoryView_FromBuffer == NULL) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find PyBuffer_FillInfo or "
+                 "PyBuffer_FillInfo+PyMemoryView_FromBuffer\n");
+        return false;
+    }
+    LOAD(libHandle, PyTuple_New);
+    if( PyBuffer_FromReadWriteMemory )
+    {
+        // Python 2
+        LOAD(libHandle, PyInt_FromLong);
+        LOAD(libHandle, PyString_FromStringAndSize);
+        LOAD(libHandle, PyString_AsString);
+    }
+    else
+    {
+        // Python 3
+        LOAD_WITH_NAME(libHandle, PyInt_FromLong, "PyLong_FromLong");
+        LOAD_WITH_NAME(libHandle, PyString_FromStringAndSize,
+                                        "PyBytes_FromStringAndSize");
+        LOAD_WITH_NAME(libHandle, PyString_AsString, "PyBytes_AsString");
+    }
+    LOAD(libHandle, PyFloat_FromDouble);
+    LOAD(libHandle, PyObject_Call);
+    LOAD(libHandle, Py_IncRef);
+    LOAD(libHandle, Py_DecRef);
+    LOAD(libHandle, PyErr_Occurred);
+    LOAD(libHandle, PyErr_Print);
+    LOAD(libHandle, Py_IsInitialized);
+    LOAD(libHandle, Py_InitializeEx);
+    LOAD(libHandle, PyEval_InitThreads);
+    LOAD(libHandle, PyEval_SaveThread);
+    LOAD(libHandle, PyEval_RestoreThread);
+    LOAD(libHandle, Py_Finalize);
+    LOAD(libHandle, Py_CompileString);
+    LOAD(libHandle, PyImport_ExecCodeModule);
+    LOAD(libHandle, PyObject_GetAttrString);
+    LOAD(libHandle, PyTuple_SetItem);
+    LOAD(libHandle, PyObject_Print);
+    LOAD(libHandle, PyImport_ImportModule);
+    LOAD(libHandle, PyCallable_Check);
+    LOAD(libHandle, PyDict_New);
+    LOAD(libHandle, PyDict_SetItemString);
+    LOAD(libHandle, PyGILState_Ensure);
+    LOAD(libHandle, PyGILState_Release);
+    LOAD(libHandle, PyErr_Fetch);
+    LOAD(libHandle, PyErr_Clear);
+    LOAD(libHandle, Py_GetVersion);
+
+    CPLString osPythonVersion(Py_GetVersion());
+    osPythonVersion.replaceAll("\r\n", ' ');
+    osPythonVersion.replaceAll('\n', ' ');
+    CPLDebug("VRT", "Python version used: %s", osPythonVersion.c_str());
+
+#else // LOAD_NOCHECK_WITH_NAME
+    CPLError(CE_Failure, CPLE_AppDefined,
+             "This platform doesn't support dynamic loading of libraries")
+    return false;
+#endif // LOAD_NOCHECK_WITH_NAME
+
+    bInit = true;
+    return bInit;
+}
+
+/************************************************************************/
+/*                      GetPyExceptionString()                          */
+/************************************************************************/
+
+static CPLString GetPyExceptionString()
+{
+    PyObject *poPyType = NULL;
+    PyObject *poPyValue = NULL;
+    PyObject *poPyTraceback = NULL;
+
+    PyErr_Fetch(&poPyType, &poPyValue, &poPyTraceback);
+    if( poPyType )
+        Py_IncRef(poPyType);
+    if( poPyValue )
+        Py_IncRef(poPyValue);
+    if( poPyTraceback )
+        Py_IncRef(poPyTraceback);
+
+    // This is a mess. traceback.format_exception/format_exception_only
+    // sometimes throw exceptions themselves !
+    CPLString osPythonCode(
+        "import traceback\n"
+        "\n"
+        "def GDALFormatException2(etype, value):\n"
+        "    try:\n"
+        "       return ''.join(traceback.format_exception_only(etype, value)).encode('UTF-8')\n"
+        "    except:\n"
+        "       return (str(etype) + ', ' + str(value)).encode('UTF-8')\n"
+        "\n"
+        "def GDALFormatException3(etype, value, tb):\n"
+        //"    print(etype, value, tb)\n"
+        "    try:\n"
+        "       return ''.join(traceback.format_exception(etype, value, tb)).encode('UTF-8')\n"
+        "    except:\n"
+        "       return (str(etype) + ', ' + str(value)).encode('UTF-8')\n");
+
+    CPLString osRet("An exception occurred in exception formatting code...");
+
+    static int nCounter = 0;
+    CPLString osModuleName( CPLSPrintf("gdal_exception_%d", nCounter));
+    PyObject* poCompiledString = Py_CompileString(osPythonCode,
+                                                  osModuleName, Py_file_input);
+    if( poCompiledString == NULL || PyErr_Occurred() )
+    {
+        PyErr_Print();
+    }
+    else
+    {
+        PyObject* poModule =
+            PyImport_ExecCodeModule(osModuleName, poCompiledString);
+        CPLAssert(poModule);
+
+        Py_DecRef(poCompiledString);
+
+        PyObject* poPyGDALFormatException2 = PyObject_GetAttrString(poModule,
+                                                "GDALFormatException2" );
+        CPLAssert(poPyGDALFormatException2);
+
+        PyObject* poPyGDALFormatException3 = PyObject_GetAttrString(poModule,
+                                                "GDALFormatException3" );
+        CPLAssert(poPyGDALFormatException3);
+
+        Py_DecRef(poModule);
+
+        PyObject* pyArgs = PyTuple_New( poPyTraceback ? 3 : 2);
+        PyTuple_SetItem(pyArgs, 0, poPyType);
+        PyTuple_SetItem(pyArgs, 1, poPyValue);
+        if( poPyTraceback )
+            PyTuple_SetItem(pyArgs, 2, poPyTraceback );
+        PyObject* poPyRet = PyObject_Call(
+            poPyTraceback ? poPyGDALFormatException3 : poPyGDALFormatException2,
+            pyArgs, NULL );
+        Py_DecRef(pyArgs);
+
+        if( PyErr_Occurred() )
+        {
+            osRet = "An exception occurred in exception formatting code...";
+            PyErr_Print();
+        }
+        else
+        {
+            osRet = PyString_AsString(poPyRet);
+            Py_DecRef(poPyRet);
+        }
+
+        Py_DecRef(poPyGDALFormatException2);
+        Py_DecRef(poPyGDALFormatException3);
+    }
+
+    if( poPyType )
+        Py_DecRef(poPyType);
+    if( poPyValue )
+        Py_DecRef(poPyValue);
+    if( poPyTraceback )
+        Py_DecRef(poPyTraceback);
+
+    return osRet;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                     VRTDerivedRasterBandPrivateData                  */
+/* ==================================================================== */
+/************************************************************************/
+
+class VRTDerivedRasterBandPrivateData
+{
+    public:
+        CPLString m_osCode;
+        CPLString m_osLanguage;
+        int       m_nBufferRadius;
+        PyObject* m_poGDALCreateNumpyArray;
+        PyObject* m_poUserFunction;
+        bool      m_bPythonInitializationDone;
+        bool      m_bPythonInitializationSuccess;
+        bool      m_bExclusiveLock;
+        bool      m_bFirstTime;
+        std::vector< std::pair<CPLString,CPLString> > m_oFunctionArgs;
+
+        VRTDerivedRasterBandPrivateData():
+            m_osLanguage("C"),
+            m_nBufferRadius(0),
+            m_poGDALCreateNumpyArray(NULL),
+            m_poUserFunction(NULL),
+            m_bPythonInitializationDone(false),
+            m_bPythonInitializationSuccess(false),
+            m_bExclusiveLock(false),
+            m_bFirstTime(true)
+        {
+        }
+
+        virtual ~VRTDerivedRasterBandPrivateData()
+        {
+            if( m_poGDALCreateNumpyArray )
+                Py_DecRef(m_poGDALCreateNumpyArray);
+            if( m_poUserFunction )
+                Py_DecRef(m_poUserFunction);
+
+            CPLMutexHolder oHolder(&ghMutex);
+            gnPythonInstanceCounter --;
+        }
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                            VRT_GIL_Holder                            */
+/* ==================================================================== */
+/************************************************************************/
+
+class VRT_GIL_Holder
+{
+        bool             m_bExclusiveLock;
+        PyGILState_STATE m_eState;
+
+    public:
+
+        explicit VRT_GIL_Holder(bool bExclusiveLock);
+        virtual ~VRT_GIL_Holder();
+};
+
+VRT_GIL_Holder::VRT_GIL_Holder(bool bExclusiveLock):
+    m_bExclusiveLock(bExclusiveLock)
+{
+    if( bExclusiveLock )
+    {
+        if( ghMutex )
+            CPLAcquireMutex( ghMutex, 1000.0 );
+    }
+    m_eState = PyGILState_Ensure();
+}
+
+VRT_GIL_Holder::~VRT_GIL_Holder()
+{
+    PyGILState_Release(m_eState);
+    if( m_bExclusiveLock )
+    {
+        if( ghMutex )
+            CPLReleaseMutex( ghMutex );
+    }
+    else
+    {
+    }
+}
 
 /************************************************************************/
 /* ==================================================================== */
@@ -45,23 +930,29 @@ static std::map<CPLString, GDALDerivedPixelFunc> osMapPixelFunction;
 /*                        VRTDerivedRasterBand()                        */
 /************************************************************************/
 
-VRTDerivedRasterBand::VRTDerivedRasterBand(GDALDataset *poDSIn, int nBandIn) :
+VRTDerivedRasterBand::VRTDerivedRasterBand( GDALDataset *poDSIn, int nBandIn ) :
     VRTSourcedRasterBand( poDSIn, nBandIn ),
+    m_poPrivate(NULL),
     pszFuncName(NULL),
     eSourceTransferType(GDT_Unknown)
-{}
+{
+    m_poPrivate = new VRTDerivedRasterBandPrivateData;
+}
 
 /************************************************************************/
 /*                        VRTDerivedRasterBand()                        */
 /************************************************************************/
 
-VRTDerivedRasterBand::VRTDerivedRasterBand(GDALDataset *poDSIn, int nBandIn,
-					   GDALDataType eType,
-					   int nXSize, int nYSize) :
+VRTDerivedRasterBand::VRTDerivedRasterBand( GDALDataset *poDSIn, int nBandIn,
+                                            GDALDataType eType,
+                                            int nXSize, int nYSize ) :
     VRTSourcedRasterBand(poDSIn, nBandIn, eType, nXSize, nYSize),
+    m_poPrivate(NULL),
     pszFuncName(NULL),
     eSourceTransferType(GDT_Unknown)
-{}
+{
+    m_poPrivate = new VRTDerivedRasterBandPrivateData;
+}
 
 /************************************************************************/
 /*                       ~VRTDerivedRasterBand()                        */
@@ -71,12 +962,40 @@ VRTDerivedRasterBand::~VRTDerivedRasterBand()
 
 {
     CPLFree( pszFuncName );
+    delete m_poPrivate;
+}
+
+/************************************************************************/
+/*                               Cleanup()                              */
+/************************************************************************/
+
+void VRTDerivedRasterBand::Cleanup()
+{
+    if( ghMutex )
+        CPLDestroyMutex(ghMutex);
+    ghMutex = NULL;
+
+    if( gnPythonInstanceCounter == 0 && gbHasInitializedPython &&
+        CPLTestBool(CPLGetConfigOption("GDAL_VRT_ENABLE_PYTHON_FINALIZE",
+                                       "YES")) )
+    {
+        // We call Py_Finalize at driver destruction, rather at dataset
+        // destruction, since numpy crashes when it is reloaded after the next
+        // Py_Initialize
+        CPLDebug("VRT", "Py_Finalize() = %p", Py_Finalize);
+        PyEval_RestoreThread(gphThreadState);
+        Py_Finalize();
+        gbHasInitializedPython = false;
+        gphThreadState = NULL;
+    }
 }
 
 /************************************************************************/
 /*                           AddPixelFunction()                         */
 /************************************************************************/
 
+/*! @endcond */
+
 /**
  * This adds a pixel function to the global list of available pixel
  * functions for derived bands.  Pixel functions must be registered
@@ -93,12 +1012,12 @@ VRTDerivedRasterBand::~VRTDerivedRasterBand()
  *
  * @return CE_None, invalid (NULL) parameters are currently ignored.
  */
-CPLErr CPL_STDCALL GDALAddDerivedBandPixelFunc
-(const char *pszFuncName, GDALDerivedPixelFunc pfnNewFunction)
+CPLErr CPL_STDCALL
+GDALAddDerivedBandPixelFunc( const char *pszFuncName,
+                             GDALDerivedPixelFunc pfnNewFunction )
 {
-    /* ---- Init ---- */
-    if ((pszFuncName == NULL) || (pszFuncName[0] == '\0') ||
-        (pfnNewFunction == NULL))
+    if( pszFuncName == NULL || pszFuncName[0] == '\0' ||
+        pfnNewFunction == NULL )
     {
       return CE_None;
     }
@@ -108,6 +1027,8 @@ CPLErr CPL_STDCALL GDALAddDerivedBandPixelFunc
     return CE_None;
 }
 
+/*! @cond Doxygen_Suppress */
+
 /**
  * This adds a pixel function to the global list of available pixel
  * functions for derived bands.
@@ -121,8 +1042,9 @@ CPLErr CPL_STDCALL GDALAddDerivedBandPixelFunc
  *
  * @return CE_None, invalid (NULL) parameters are currently ignored.
  */
-CPLErr VRTDerivedRasterBand::AddPixelFunction
-(const char *pszFuncName, GDALDerivedPixelFunc pfnNewFunction)
+CPLErr
+VRTDerivedRasterBand::AddPixelFunction(
+    const char *pszFuncName, GDALDerivedPixelFunc pfnNewFunction )
 {
     return GDALAddDerivedBandPixelFunc(pszFuncName, pfnNewFunction);
 }
@@ -140,11 +1062,10 @@ CPLErr VRTDerivedRasterBand::AddPixelFunction
  * @return A derived band pixel function, or NULL if none have been
  * registered for pszFuncName.
  */
-GDALDerivedPixelFunc VRTDerivedRasterBand::GetPixelFunction
-(const char *pszFuncName)
+GDALDerivedPixelFunc
+VRTDerivedRasterBand::GetPixelFunction( const char *pszFuncName )
 {
-    /* ---- Init ---- */
-    if ((pszFuncName == NULL) || (pszFuncName[0] == '\0'))
+    if( pszFuncName == NULL || pszFuncName[0] == '\0' )
     {
         return NULL;
     }
@@ -166,10 +1087,10 @@ GDALDerivedPixelFunc VRTDerivedRasterBand::GetPixelFunction
  * Set the pixel function name to be applied to this derived band.  The
  * name should match a pixel function registered using AddPixelFunction.
  *
- * @param pszFuncName Name of pixel function to be applied to this derived
+ * @param pszFuncNameIn Name of pixel function to be applied to this derived
  * band.
  */
-void VRTDerivedRasterBand::SetPixelFunctionName(const char *pszFuncNameIn)
+void VRTDerivedRasterBand::SetPixelFunctionName( const char *pszFuncNameIn )
 {
     pszFuncName = CPLStrdup( pszFuncNameIn );
 }
@@ -186,12 +1107,356 @@ void VRTDerivedRasterBand::SetPixelFunctionName(const char *pszFuncNameIn)
  * if the pixel function generates a raster for a derived band that
  * is of type Byte.
  *
- * @param eDataType Data type to use to obtain pixel information from
+ * @param eDataTypeIn Data type to use to obtain pixel information from
  * the sources to be passed to the derived band pixel function.
  */
-void VRTDerivedRasterBand::SetSourceTransferType(GDALDataType eDataTypeIn)
+void VRTDerivedRasterBand::SetSourceTransferType( GDALDataType eDataTypeIn )
 {
-    this->eSourceTransferType = eDataTypeIn;
+    eSourceTransferType = eDataTypeIn;
+}
+
+/************************************************************************/
+/*                           InitializePython()                         */
+/************************************************************************/
+
+bool VRTDerivedRasterBand::InitializePython()
+{
+    if( m_poPrivate->m_bPythonInitializationDone )
+        return m_poPrivate->m_bPythonInitializationSuccess;
+
+    m_poPrivate->m_bPythonInitializationDone = true;
+    m_poPrivate->m_bPythonInitializationSuccess = false;
+
+    const CPLString osPythonFullname( pszFuncName ? pszFuncName : "" );
+    const size_t nIdxDot = osPythonFullname.rfind(".");
+    CPLString osPythonModule;
+    CPLString osPythonFunction;
+    if( nIdxDot != std::string::npos )
+    {
+        osPythonModule = osPythonFullname.substr(0, nIdxDot);
+        osPythonFunction = osPythonFullname.substr(nIdxDot+1);
+    }
+    else
+    {
+        osPythonFunction = osPythonFullname;
+    }
+
+#ifndef GDAL_VRT_DISABLE_PYTHON
+    const char* pszPythonEnabled =
+                            CPLGetConfigOption("GDAL_VRT_ENABLE_PYTHON", NULL);
+#else
+    const char* pszPythonEnabled = "NO";
+#endif
+    const CPLString osPythonEnabled(pszPythonEnabled ? pszPythonEnabled :
+                                            GDAL_VRT_ENABLE_PYTHON_DEFAULT);
+
+    if( EQUAL(osPythonEnabled, "TRUSTED_MODULES") )
+    {
+        bool bIsTrustedModule = false;
+        const CPLString osVRTTrustedModules(
+                    CPLGetConfigOption( "GDAL_VRT_PYTHON_TRUSTED_MODULES", "") );
+        if( !osPythonModule.empty() )
+        {
+            char** papszTrustedModules = CSLTokenizeString2(
+                                                osVRTTrustedModules, ",", 0 );
+            for( char** papszIter = papszTrustedModules;
+                !bIsTrustedModule && papszIter && *papszIter;
+                ++papszIter )
+            {
+                const char* pszIterModule = *papszIter;
+                size_t nIterModuleLen = strlen(pszIterModule);
+                if( nIterModuleLen > 2 &&
+                    strncmp(pszIterModule + nIterModuleLen - 2, ".*", 2) == 0 )
+                {
+                    bIsTrustedModule =
+                        (strncmp( osPythonModule, pszIterModule,
+                                                  nIterModuleLen - 2 ) == 0) &&
+                        (osPythonModule.size() == nIterModuleLen - 2 ||
+                         (osPythonModule.size() >= nIterModuleLen &&
+                          osPythonModule[nIterModuleLen-1] == '.') );
+                }
+                else if( nIterModuleLen >= 1 &&
+                        pszIterModule[nIterModuleLen-1] == '*' )
+                {
+                    bIsTrustedModule = (strncmp( osPythonModule, pszIterModule,
+                                                nIterModuleLen - 1 ) == 0);
+                }
+                else
+                {
+                    bIsTrustedModule =
+                                (strcmp(osPythonModule, pszIterModule) == 0);
+                }
+            }
+            CSLDestroy(papszTrustedModules);
+        }
+
+        if( !bIsTrustedModule )
+        {
+            if( osPythonModule.empty() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Python code needs to be executed, but it uses online code "
+                         "in the VRT whereas the current policy is to trust only "
+                         "code from external trusted modules (defined in the "
+                         "GDAL_VRT_PYTHON_TRUSTED_MODULES configuration option). "
+                         "If you trust the code in %s, you can set the "
+                         "GDAL_VRT_ENABLE_PYTHON configuration option to YES.",
+                         GetDataset() ? GetDataset()->GetDescription() :
+                                    "(unknown VRT)");
+            }
+            else if( osVRTTrustedModules.empty() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Python code needs to be executed, but it uses code "
+                         "from module '%s', whereas the current policy is to "
+                         "trust only code from modules defined in the "
+                         "GDAL_VRT_PYTHON_TRUSTED_MODULES configuration option, "
+                         "which is currently unset. "
+                         "If you trust the code in '%s', you can add module '%s' "
+                         "to GDAL_VRT_PYTHON_TRUSTED_MODULES (or set the "
+                         "GDAL_VRT_ENABLE_PYTHON configuration option to YES).",
+                         osPythonModule.c_str(),
+                         GetDataset() ? GetDataset()->GetDescription() :
+                                    "(unknown VRT)",
+                         osPythonModule.c_str());
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Python code needs to be executed, but it uses code "
+                         "from module '%s', whereas the current policy is to "
+                         "trust only code from modules '%s' (defined in the "
+                         "GDAL_VRT_PYTHON_TRUSTED_MODULES configuration option). "
+                         "If you trust the code in '%s', you can add module '%s' "
+                         "to GDAL_VRT_PYTHON_TRUSTED_MODULES (or set the "
+                         "GDAL_VRT_ENABLE_PYTHON configuration option to YES).",
+                         osPythonModule.c_str(),
+                         osVRTTrustedModules.c_str(),
+                         GetDataset() ? GetDataset()->GetDescription() :
+                                    "(unknown VRT)",
+                         osPythonModule.c_str());
+            }
+            return false;
+        }
+    }
+
+#ifdef disabled_because_this_is_probably_broken_by_design
+    // See https://lwn.net/Articles/574215/
+    // and http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html
+    else if( EQUAL(osPythonEnabled, "IF_SAFE") )
+    {
+        bool bSafe = true;
+        // If the function comes from another module, then we don't know
+        if( !osPythonModule.empty() )
+        {
+            CPLDebug("VRT", "Python function is from another module");
+            bSafe = false;
+        }
+
+        CPLString osCode(m_poPrivate->m_osCode);
+
+        // Reject all imports except a few trusted modules
+        const char* const apszTrustedImports[] = {
+                "import math",
+                "from math import",
+                "import numpy", // caution: numpy has lots of I/O functions !
+                "from numpy import",
+                // TODO: not sure if importing arbitrary stuff from numba is OK
+                // so let's just restrict to jit.
+                "from numba import jit",
+
+                // Not imports but still whitelisted, whereas other __ is banned
+                "__init__",
+                "__call__",
+        };
+        for( size_t i = 0; i < CPL_ARRAYSIZE(apszTrustedImports); ++i )
+        {
+            osCode.replaceAll(CPLString(apszTrustedImports[i]), "");
+        }
+
+        // Some dangerous built-in functions or numpy functions
+        const char* const apszUntrusted[] = { "import", // and __import__
+                                              "eval",
+                                              "compile",
+                                              "open",
+                                              "load", // reload, numpy.load
+                                              "file", // and exec_file, numpy.fromfile, numpy.tofile
+                                              "input", // and raw_input
+                                              "save", // numpy.save
+                                              "memmap", // numpy.memmap
+                                              "DataSource", // numpy.DataSource
+                                              "genfromtxt", // numpy.genfromtxt
+                                              "getattr",
+                                              "ctypeslib", // numpy.ctypeslib
+                                              "testing", // numpy.testing
+                                              "dump", // numpy.ndarray.dump
+                                              "fromregex", // numpy.fromregex
+                                              "__"
+                                             };
+        for( size_t i = 0; i < CPL_ARRAYSIZE(apszUntrusted); ++i )
+        {
+            if( osCode.find(apszUntrusted[i]) != std::string::npos )
+            {
+                CPLDebug("VRT", "Found '%s' word in Python code",
+                         apszUntrusted[i]);
+                bSafe = false;
+            }
+        }
+
+        if( !bSafe )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Python code needs to be executed, but we cannot verify "
+                     "if it is safe, so this is disabled by default. "
+                     "If you trust the code in %s, you can set the "
+                     "GDAL_VRT_ENABLE_PYTHON configuration option to YES.",
+                     GetDataset() ? GetDataset()->GetDescription() :
+                                    "(unknown VRT)");
+            return false;
+        }
+    }
+#endif //disabled_because_this_is_probably_broken_by_design
+
+    else if( !EQUAL(osPythonEnabled, "YES") &&
+             !EQUAL(osPythonEnabled, "ON") &&
+             !EQUAL(osPythonEnabled, "TRUE") )
+    {
+        if( pszPythonEnabled == NULL )
+        {
+            // Note: this is dead code with our current default policy
+            // GDAL_VRT_ENABLE_PYTHON == "TRUSTED_MODULES"
+            CPLError(CE_Failure, CPLE_AppDefined,
+                 "Python code needs to be executed, but this is "
+                 "disabled by default. If you trust the code in %s, "
+                 "you can set the GDAL_VRT_ENABLE_PYTHON configuration "
+                 "option to YES.",
+                GetDataset() ? GetDataset()->GetDescription() :
+                                                    "(unknown VRT)");
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Python code in %s needs to be executed, but this has been "
+                    "explicitly disabled.",
+                     GetDataset() ? GetDataset()->GetDescription() :
+                                                            "(unknown VRT)");
+        }
+        return false;
+    }
+
+    if( !LoadPythonAPI() )
+        return false;
+
+    // Make sure the python interpreter is initialized
+    {
+        CPLMutexHolder oHolder(&ghMutex);
+        int bIsInitialized = Py_IsInitialized();
+        if( !bIsInitialized)
+        {
+            gbHasInitializedPython = true;
+            Py_InitializeEx(0);
+            CPLDebug("VRT", "Py_Initialize()");
+            PyEval_InitThreads();
+            gphThreadState = PyEval_SaveThread();
+        }
+        gnPythonInstanceCounter ++;
+    }
+
+    // Whether we should just use our own global mutex, in addition to Python
+    // GIL locking.
+    m_poPrivate->m_bExclusiveLock =
+        CPLTestBool(CPLGetConfigOption("GDAL_VRT_PYTHON_EXCLUSIVE_LOCK", "NO"));
+
+    // numba jit'ification doesn't seem to be thread-safe, so force use of
+    // lock now and at first execution of function. Later executions seem to
+    // be thread-safe. This problem doesn't seem to appear for code in
+    // regular files
+    const bool bUseExclusiveLock = m_poPrivate->m_bExclusiveLock ||
+                    m_poPrivate->m_osCode.find("@jit") != std::string::npos;
+    VRT_GIL_Holder oHolder(bUseExclusiveLock);
+
+    // As we don't want to depend on numpy C API/ABI, we use a trick to build
+    // a numpy array object. We define a Python function to which we pass a
+    // Python buffer oject.
+
+    // We need to build a unique module name, otherwise this will crash in
+    // multithreaded use cases.
+    CPLString osModuleName( CPLSPrintf("gdal_vrt_module_%p", this) );
+    PyObject* poCompiledString = Py_CompileString(
+        ("import numpy\n"
+        "def GDALCreateNumpyArray(buffer, dtype, height, width):\n"
+        "    return numpy.frombuffer(buffer, dtype.decode('ascii'))."
+                                                "reshape([height, width])\n"
+        "\n" + m_poPrivate->m_osCode).c_str(),
+        osModuleName, Py_file_input);
+    if( poCompiledString == NULL || PyErr_Occurred() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Couldn't compile code:\n%s",
+                 GetPyExceptionString().c_str());
+        return false;
+    }
+    PyObject* poModule =
+        PyImport_ExecCodeModule(osModuleName, poCompiledString);
+    Py_DecRef(poCompiledString);
+
+    if( poModule == NULL || PyErr_Occurred() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s", GetPyExceptionString().c_str());
+        return false;
+    }
+
+    // Fetch user computation function
+    if( !osPythonModule.empty() )
+    {
+        PyObject* poUserModule = PyImport_ImportModule(osPythonModule);
+        if (poUserModule == NULL || PyErr_Occurred())
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s", GetPyExceptionString().c_str());
+            Py_DecRef(poModule);
+            return false;
+        }
+        m_poPrivate->m_poUserFunction = PyObject_GetAttrString(poUserModule,
+                                                            osPythonFunction );
+        Py_DecRef(poUserModule);
+    }
+    else
+    {
+        m_poPrivate->m_poUserFunction = PyObject_GetAttrString(poModule,
+                                            osPythonFunction );
+    }
+    if (m_poPrivate->m_poUserFunction == NULL || PyErr_Occurred())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s", GetPyExceptionString().c_str());
+        Py_DecRef(poModule);
+        return false;
+    }
+    if( !PyCallable_Check(m_poPrivate->m_poUserFunction) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Object '%s' is not callable",
+                 osPythonFunction.c_str());
+        Py_DecRef(poModule);
+        return false;
+    }
+
+    // Fetch our GDALCreateNumpyArray python function
+    m_poPrivate->m_poGDALCreateNumpyArray =
+        PyObject_GetAttrString(poModule, "GDALCreateNumpyArray" );
+    if (m_poPrivate->m_poGDALCreateNumpyArray == NULL || PyErr_Occurred())
+    {
+        // Shouldn't happen normally...
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s", GetPyExceptionString().c_str());
+        Py_DecRef(poModule);
+        return false;
+    }
+    Py_DecRef(poModule);
+
+    m_poPrivate->m_bPythonInitializationSuccess = true;
+    return true;
 }
 
 /************************************************************************/
@@ -251,13 +1516,13 @@ void VRTDerivedRasterBand::SetSourceTransferType(GDALDataType eDataTypeIn)
  *
  * @return CE_Failure if the access fails, otherwise CE_None.
  */
-CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
-				       int nXOff, int nYOff, int nXSize,
-				       int nYSize, void * pData, int nBufXSize,
-				       int nBufYSize, GDALDataType eBufType,
-				       GSpacing nPixelSpace,
-                                       GSpacing nLineSpace,
-                                       GDALRasterIOExtraArg* psExtraArg )
+CPLErr VRTDerivedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
+                                        int nXOff, int nYOff, int nXSize,
+                                        int nYSize, void * pData, int nBufXSize,
+                                        int nBufYSize, GDALDataType eBufType,
+                                        GSpacing nPixelSpace,
+                                        GSpacing nLineSpace,
+                                        GDALRasterIOExtraArg* psExtraArg )
 {
     if( eRWFlag == GF_Write )
     {
@@ -266,23 +1531,27 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
         return CE_Failure;
     }
 
-    int typesize = GDALGetDataTypeSizeBytes(eBufType);
-    if (GDALGetDataTypeSize(eBufType) % 8 > 0) typesize++;
+    const int nBufTypeSize = GDALGetDataTypeSizeBytes(eBufType);
     GDALDataType eSrcType = eSourceTransferType;
-    if ((eSrcType == GDT_Unknown) || (eSrcType >= GDT_TypeCount)) {
-	eSrcType = eBufType;
+    if( eSrcType == GDT_Unknown || eSrcType >= GDT_TypeCount ) {
+        eSrcType = eBufType;
     }
-    const int sourcesize = GDALGetDataTypeSizeBytes(eSrcType);
+    const int nSrcTypeSize = GDALGetDataTypeSizeBytes(eSrcType);
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the buffer to some background value. Use the         */
 /*      nodata value if available.                                      */
 /* -------------------------------------------------------------------- */
-    if ( nPixelSpace == typesize &&
-         (!m_bNoDataValueSet || m_dfNoDataValue == 0) ) {
-        memset( pData, 0, static_cast<size_t>(nBufXSize * nBufYSize * nPixelSpace) );
+    if( bSkipBufferInitialization )
+    {
+        // Do nothing
+    }
+    else if( nPixelSpace == nBufTypeSize &&
+        (!m_bNoDataValueSet || m_dfNoDataValue == 0) ) {
+        memset( pData, 0,
+                static_cast<size_t>(nBufXSize * nBufYSize * nPixelSpace) );
     }
-    else if ( !bEqualAreas || m_bNoDataValueSet )
+    else if( m_bNoDataValueSet )
     {
         double dfWriteValue = 0.0;
         if( m_bNoDataValueSet )
@@ -304,21 +1573,27 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
     if( (nBufXSize < nXSize || nBufYSize < nYSize)
         && GetOverviewCount() > 0 )
     {
-        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                              pData, nBufXSize, nBufYSize,
-                              eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
+        if( OverviewRasterIO(
+               eRWFlag, nXOff, nYOff, nXSize, nYSize,
+               pData, nBufXSize, nBufYSize,
+               eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
             return CE_None;
     }
 
     /* ---- Get pixel function for band ---- */
-    GDALDerivedPixelFunc pfnPixelFunc
-        = VRTDerivedRasterBand::GetPixelFunction(this->pszFuncName);
-    if (pfnPixelFunc == NULL) {
-	CPLError( CE_Failure, CPLE_IllegalArg,
-		  "VRTDerivedRasterBand::IRasterIO:"
-		  "Derived band pixel function '%s' not registered.\n",
-		  this->pszFuncName);
-	return CE_Failure;
+    GDALDerivedPixelFunc pfnPixelFunc = NULL;
+
+    if( EQUAL(m_poPrivate->m_osLanguage, "C") )
+    {
+        pfnPixelFunc = VRTDerivedRasterBand::GetPixelFunction(pszFuncName);
+        if( pfnPixelFunc == NULL )
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                    "VRTDerivedRasterBand::IRasterIO:"
+                    "Derived band pixel function '%s' not registered.",
+                    this->pszFuncName) ;
+            return CE_Failure;
+        }
     }
 
     /* TODO: It would be nice to use a MallocBlock function for each
@@ -328,13 +1603,21 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
        of freed blocks gets to be too great of a percentage of the size
        of the allocated blocks. */
 
-    /* ---- Get buffers for each source ---- */
+    // Get buffers for each source.
+    const int nBufferRadius = m_poPrivate->m_nBufferRadius;
+    if( nBufferRadius > (INT_MAX - nBufXSize) / 2 ||
+        nBufferRadius > (INT_MAX - nBufYSize) / 2 )
+    {
+        return CE_Failure;
+    }
+    const int nExtBufXSize = nBufXSize + 2 * nBufferRadius;
+    const int nExtBufYSize = nBufYSize + 2 * nBufferRadius;
     void **pBuffers
         = reinterpret_cast<void **>( CPLMalloc(sizeof(void *) * nSources) );
     for( int iSource = 0; iSource < nSources; iSource++ ) {
         pBuffers[iSource] =
-            VSI_MALLOC_VERBOSE(sourcesize * nBufXSize * nBufYSize);
-        if (pBuffers[iSource] == NULL)
+            VSI_MALLOC3_VERBOSE(nSrcTypeSize, nExtBufXSize, nExtBufYSize);
+        if( pBuffers[iSource] == NULL )
         {
             for (int i = 0; i < iSource; i++) {
                 VSIFree(pBuffers[i]);
@@ -349,39 +1632,304 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
         /* don't need any special line-by-line handling when a nonzero  */
         /* nodata value is set.                                         */
         /* ------------------------------------------------------------ */
-        if ( !m_bNoDataValueSet || m_dfNoDataValue == 0 )
+        if( !m_bNoDataValueSet || m_dfNoDataValue == 0 )
         {
-            memset( pBuffers[iSource], 0, sourcesize * nBufXSize * nBufYSize );
+            memset( pBuffers[iSource], 0, static_cast<size_t>(nSrcTypeSize) *
+                    nExtBufXSize * nExtBufYSize );
         }
         else
         {
             GDALCopyWords( &m_dfNoDataValue, GDT_Float64, 0,
-                           reinterpret_cast<GByte *>( pBuffers[iSource] ), eSrcType, sourcesize,
-                           nBufXSize * nBufYSize);
+                           reinterpret_cast<GByte *>( pBuffers[iSource] ),
+                           eSrcType, nSrcTypeSize,
+                           nExtBufXSize * nExtBufYSize );
         }
     }
 
     GDALRasterIOExtraArg sExtraArg;
-    INIT_RASTERIO_EXTRA_ARG(sExtraArg);
+    GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
+
+    int nXShiftInBuffer = 0;
+    int nYShiftInBuffer = 0;
+    int nExtBufXSizeReq = nExtBufXSize;
+    int nExtBufYSizeReq = nExtBufYSize;
+
+    int nXOffExt = nXOff;
+    int nYOffExt = nYOff;
+    int nXSizeExt = nXSize;
+    int nYSizeExt = nYSize;
+
+    if( nBufferRadius )
+    {
+        double dfXRatio = static_cast<double>(nXSize) / nBufXSize;
+        double dfYRatio = static_cast<double>(nYSize) / nBufYSize;
 
-    /* ---- Load values for sources into packed buffers ---- */
+        if( !sExtraArg.bFloatingPointWindowValidity )
+        {
+            sExtraArg.dfXOff = nXOff;
+            sExtraArg.dfYOff = nYOff;
+            sExtraArg.dfXSize = nXSize;
+            sExtraArg.dfYSize = nYSize;
+        }
+
+        sExtraArg.dfXOff -= dfXRatio * nBufferRadius;
+        sExtraArg.dfYOff -= dfYRatio * nBufferRadius;
+        sExtraArg.dfXSize += 2 * dfXRatio * nBufferRadius;
+        sExtraArg.dfYSize += 2 * dfYRatio * nBufferRadius;
+        if( sExtraArg.dfXOff < 0 )
+        {
+            nXShiftInBuffer = -static_cast<int>(sExtraArg.dfXOff / dfXRatio);
+            nExtBufXSizeReq -= nXShiftInBuffer;
+            sExtraArg.dfXSize += sExtraArg.dfXOff;
+            sExtraArg.dfXOff = 0;
+        }
+        if( sExtraArg.dfYOff < 0 )
+        {
+            nYShiftInBuffer = -static_cast<int>(sExtraArg.dfYOff / dfYRatio);
+            nExtBufYSizeReq -= nYShiftInBuffer;
+            sExtraArg.dfYSize += sExtraArg.dfYOff;
+            sExtraArg.dfYOff = 0;
+        }
+        if( sExtraArg.dfXOff + sExtraArg.dfXSize > nRasterXSize )
+        {
+            nExtBufXSizeReq -= static_cast<int>((sExtraArg.dfXOff +
+                        sExtraArg.dfXSize - nRasterXSize) / dfXRatio);
+            sExtraArg.dfXSize = nRasterXSize - sExtraArg.dfXOff;
+        }
+        if( sExtraArg.dfYOff + sExtraArg.dfYSize > nRasterYSize )
+        {
+            nExtBufYSizeReq -= static_cast<int>((sExtraArg.dfYOff +
+                        sExtraArg.dfYSize - nRasterYSize) / dfYRatio);
+            sExtraArg.dfYSize = nRasterYSize - sExtraArg.dfYOff;
+        }
+
+        nXOffExt = static_cast<int>(sExtraArg.dfXOff);
+        nYOffExt = static_cast<int>(sExtraArg.dfYOff);
+        nXSizeExt = std::min(static_cast<int>(sExtraArg.dfXSize + 0.5),
+                             nRasterXSize - nXOffExt);
+        nYSizeExt = std::min(static_cast<int>(sExtraArg.dfYSize + 0.5),
+                             nRasterYSize - nYOffExt);
+    }
+
+    // Load values for sources into packed buffers.
     CPLErr eErr = CE_None;
     for( int iSource = 0; iSource < nSources && eErr == CE_None; iSource++ ) {
+        GByte* pabyBuffer = reinterpret_cast<GByte*>(pBuffers[iSource]);
         eErr = reinterpret_cast<VRTSource *>( papoSources[iSource] )->RasterIO(
-	    nXOff, nYOff, nXSize, nYSize,
-            pBuffers[iSource], nBufXSize, nBufYSize,
-            eSrcType, GDALGetDataTypeSizeBytes( eSrcType ),
-            GDALGetDataTypeSizeBytes( eSrcType ) * nBufXSize, &sExtraArg);
+            nXOffExt, nYOffExt, nXSizeExt, nYSizeExt,
+            pabyBuffer + (nYShiftInBuffer * nExtBufXSize +
+                                            nXShiftInBuffer) * nSrcTypeSize,
+            nExtBufXSizeReq, nExtBufYSizeReq,
+            eSrcType,
+            nSrcTypeSize,
+            nSrcTypeSize * nExtBufXSize,
+            &sExtraArg );
+
+        // Extend first lines
+        for( int iY = 0; iY < nYShiftInBuffer; iY++ )
+        {
+            memcpy( pabyBuffer + iY * nExtBufXSize * nSrcTypeSize,
+                    pabyBuffer + nYShiftInBuffer * nExtBufXSize * nSrcTypeSize,
+                    nExtBufXSize * nSrcTypeSize );
+        }
+        // Extend last lines
+        for( int iY = nYShiftInBuffer + nExtBufYSizeReq; iY < nExtBufYSize; iY++ )
+        {
+            memcpy( pabyBuffer + iY * nExtBufXSize * nSrcTypeSize,
+                    pabyBuffer + (nYShiftInBuffer + nExtBufYSizeReq - 1) *
+                                                    nExtBufXSize * nSrcTypeSize,
+                    nExtBufXSize * nSrcTypeSize );
+        }
+        // Extend first cols
+        if( nXShiftInBuffer )
+        {
+            for( int iY = 0; iY < nExtBufYSize; iY ++ )
+            {
+                for( int iX = 0; iX < nXShiftInBuffer; iX++ )
+                {
+                    memcpy( pabyBuffer + (iY * nExtBufXSize + iX) * nSrcTypeSize,
+                            pabyBuffer + (iY * nExtBufXSize +
+                                                nXShiftInBuffer) * nSrcTypeSize,
+                            nSrcTypeSize );
+                }
+            }
+        }
+        // Extent last cols
+        if( nXShiftInBuffer + nExtBufXSizeReq < nExtBufXSize )
+        {
+            for( int iY = 0; iY < nExtBufYSize; iY ++ )
+            {
+                for( int iX = nXShiftInBuffer + nExtBufXSizeReq;
+                         iX < nExtBufXSize; iX++ )
+                {
+                    memcpy( pabyBuffer + (iY * nExtBufXSize + iX) * nSrcTypeSize,
+                            pabyBuffer + (iY * nExtBufXSize + nXShiftInBuffer +
+                                            nExtBufXSizeReq - 1) * nSrcTypeSize,
+                            nSrcTypeSize );
+                }
+            }
+        }
     }
 
-    /* ---- Apply pixel function ---- */
-    if (eErr == CE_None) {
+    // Apply pixel function.
+    if( eErr == CE_None && EQUAL(m_poPrivate->m_osLanguage, "Python") )
+    {
+        eErr = CE_Failure;
+
+        // numpy doesn't have native cint16/cint32
+        if( eSrcType == GDT_CInt16 || eSrcType == GDT_CInt32 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "CInt16/CInt32 data type not supported for SourceTransferType");
+            goto end;
+        }
+        if( eDataType == GDT_CInt16 || eDataType == GDT_CInt32 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "CInt16/CInt32 data type not supported for data type");
+            goto end;
+        }
+
+        if( !InitializePython() )
+            goto end;
+
+        GByte* pabyTmpBuffer = NULL;
+        // Do we need a temporary buffer or can we use directly the output
+        // buffer ?
+        if( nBufferRadius != 0 ||
+            eDataType != eBufType ||
+            nPixelSpace != nBufTypeSize ||
+            nLineSpace != static_cast<GSpacing>(nBufTypeSize) * nBufXSize )
+        {
+            pabyTmpBuffer = reinterpret_cast<GByte*>(VSI_CALLOC_VERBOSE(
+                            static_cast<size_t>(nExtBufXSize) * nExtBufYSize,
+                            GDALGetDataTypeSizeBytes(eDataType)));
+            if( !pabyTmpBuffer )
+                goto end;
+        }
+
+        {
+        const bool bUseExclusiveLock = m_poPrivate->m_bExclusiveLock ||
+                    ( m_poPrivate->m_bFirstTime &&
+                    m_poPrivate->m_osCode.find("@jit") != std::string::npos);
+        m_poPrivate->m_bFirstTime = false;
+        VRT_GIL_Holder oHolder(bUseExclusiveLock);
+
+        // Prepare target numpy array
+        PyObject* poPyDstArray = GDALCreateNumpyArray(
+                                    m_poPrivate->m_poGDALCreateNumpyArray,
+                                    pabyTmpBuffer ? pabyTmpBuffer : pData,
+                                    eDataType,
+                                    nExtBufYSize,
+                                    nExtBufXSize);
+        if( !poPyDstArray )
+        {
+            VSIFree(pabyTmpBuffer);
+            goto end;
+        }
+
+        // Wrap source buffers as input numpy arrays
+        PyObject* pyArgInputArray = PyTuple_New(nSources);
+        for( int i = 0; i < nSources; i++ )
+        {
+            GByte* pabyBuffer = reinterpret_cast<GByte*>(pBuffers[i]);
+            PyObject* poPySrcArray = GDALCreateNumpyArray(
+                        m_poPrivate->m_poGDALCreateNumpyArray,
+                        pabyBuffer,
+                        eSrcType,
+                        nExtBufYSize,
+                        nExtBufXSize);
+            CPLAssert(poPySrcArray);
+            PyTuple_SetItem(pyArgInputArray, i, poPySrcArray);
+        }
+
+        // Create arguments
+        PyObject* pyArgs = PyTuple_New(10);
+        PyTuple_SetItem(pyArgs, 0, pyArgInputArray);
+        PyTuple_SetItem(pyArgs, 1, poPyDstArray);
+        PyTuple_SetItem(pyArgs, 2, PyInt_FromLong(nXOff));
+        PyTuple_SetItem(pyArgs, 3, PyInt_FromLong(nYOff));
+        PyTuple_SetItem(pyArgs, 4, PyInt_FromLong(nXSize));
+        PyTuple_SetItem(pyArgs, 5, PyInt_FromLong(nYSize));
+        PyTuple_SetItem(pyArgs, 6, PyInt_FromLong(nRasterXSize));
+        PyTuple_SetItem(pyArgs, 7, PyInt_FromLong(nRasterYSize));
+        PyTuple_SetItem(pyArgs, 8, PyInt_FromLong(nBufferRadius));
+
+        double adfGeoTransform[6];
+        adfGeoTransform[0] = 0;
+        adfGeoTransform[1] = 1;
+        adfGeoTransform[2] = 0;
+        adfGeoTransform[3] = 0;
+        adfGeoTransform[4] = 0;
+        adfGeoTransform[5] = 1;
+        if( GetDataset() )
+            GetDataset()->GetGeoTransform(adfGeoTransform);
+        PyObject* pyGT = PyTuple_New(6);
+        for(int i = 0; i < 6; i++ )
+            PyTuple_SetItem(pyGT, i, PyFloat_FromDouble(adfGeoTransform[i]));
+        PyTuple_SetItem(pyArgs, 9, pyGT);
+
+        // Prepare kwargs
+        PyObject* pyKwargs = PyDict_New();
+        for( size_t i = 0; i < m_poPrivate->m_oFunctionArgs.size(); ++i )
+        {
+            const char* pszKey =
+                m_poPrivate->m_oFunctionArgs[i].first.c_str();
+            const char* pszValue =
+                m_poPrivate->m_oFunctionArgs[i].second.c_str();
+            PyDict_SetItemString(pyKwargs, pszKey,
+                PyString_FromStringAndSize(pszValue, strlen(pszValue)));
+        }
+
+        // Call user function
+        PyObject* pRetValue = PyObject_Call(
+                                        m_poPrivate->m_poUserFunction,
+                                        pyArgs, pyKwargs);
+
+        Py_DecRef(pyArgs);
+        Py_DecRef(pyKwargs);
+
+        if (PyErr_Occurred())
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "%s", GetPyExceptionString().c_str());
+        }
+        else
+        {
+            eErr = CE_None;
+        }
+        if( pRetValue )
+            Py_DecRef(pRetValue);
+        } // End of GIL section
+
+        if( pabyTmpBuffer )
+        {
+            // Copy numpy destination array to user buffer
+            for( int iY = 0; iY < nBufYSize; iY++ )
+            {
+                size_t nSrcOffset = (static_cast<size_t>(iY + nBufferRadius) *
+                    nExtBufXSize + nBufferRadius) *
+                    GDALGetDataTypeSizeBytes(eDataType);
+                GDALCopyWords(pabyTmpBuffer + nSrcOffset,
+                              eDataType,
+                              GDALGetDataTypeSizeBytes(eDataType),
+                              reinterpret_cast<GByte*>(pData) + iY * nLineSpace,
+                              eBufType,
+                              static_cast<int>(nPixelSpace),
+                              nBufXSize);
+            }
+
+            VSIFree(pabyTmpBuffer);
+        }
+    }
+    else if( eErr == CE_None && pfnPixelFunc != NULL ) {
         eErr = pfnPixelFunc( reinterpret_cast<void **>( pBuffers ), nSources,
-			     pData, nBufXSize, nBufYSize,
-			     eSrcType, eBufType, static_cast<int>(nPixelSpace), static_cast<int>(nLineSpace) );
+                             pData, nBufXSize, nBufYSize,
+                             eSrcType, eBufType, static_cast<int>(nPixelSpace),
+                             static_cast<int>(nLineSpace) );
     }
-
-    /* ---- Release buffers ---- */
+end:
+    // Release buffers.
     for ( int iSource = 0; iSource < nSources; iSource++ ) {
         VSIFree(pBuffers[iSource]);
     }
@@ -391,24 +1939,104 @@ CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
 }
 
 /************************************************************************/
+/*                         IGetDataCoverageStatus()                     */
+/************************************************************************/
+
+int  VRTDerivedRasterBand::IGetDataCoverageStatus( int /* nXOff */,
+                                                   int /* nYOff */,
+                                                   int /* nXSize */,
+                                                   int /* nYSize */,
+                                                   int /* nMaskFlagStop */,
+                                                   double* pdfDataPct)
+{
+    if( pdfDataPct != NULL )
+        *pdfDataPct = -1.0;
+    return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | GDAL_DATA_COVERAGE_STATUS_DATA;
+}
+
+/************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
 
 CPLErr VRTDerivedRasterBand::XMLInit( CPLXMLNode *psTree,
-				      const char *pszVRTPath )
+                                      const char *pszVRTPath )
 
 {
-    CPLErr eErr = VRTSourcedRasterBand::XMLInit( psTree, pszVRTPath );
+    const CPLErr eErr = VRTSourcedRasterBand::XMLInit( psTree, pszVRTPath );
     if( eErr != CE_None )
         return eErr;
 
-    /* ---- Read derived pixel function type ---- */
+    // Read derived pixel function type.
     SetPixelFunctionName( CPLGetXMLValue( psTree, "PixelFunctionType", NULL ) );
+    if( pszFuncName == NULL || EQUAL(pszFuncName, "") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "PixelFunctionType missing");
+        return CE_Failure;
+    }
 
-    /* ---- Read optional source transfer data type ---- */
+    m_poPrivate->m_osLanguage = CPLGetXMLValue( psTree,
+                                                "PixelFunctionLanguage", "C" );
+    if( !EQUAL(m_poPrivate->m_osLanguage, "C") &&
+        !EQUAL(m_poPrivate->m_osLanguage, "Python") )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Unsupported PixelFunctionLanguage");
+        return CE_Failure;
+    }
+
+    m_poPrivate->m_osCode =
+                        CPLGetXMLValue( psTree, "PixelFunctionCode", "" );
+    if( !m_poPrivate->m_osCode.empty() &&
+        !EQUAL(m_poPrivate->m_osLanguage, "Python") )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "PixelFunctionCode can only be used with Python");
+        return CE_Failure;
+    }
+
+    m_poPrivate->m_nBufferRadius =
+                        atoi(CPLGetXMLValue( psTree, "BufferRadius", "0" ));
+    if( m_poPrivate->m_nBufferRadius < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for BufferRadius");
+        return CE_Failure;
+    }
+    if( m_poPrivate->m_nBufferRadius != 0 &&
+        !EQUAL(m_poPrivate->m_osLanguage, "Python") )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "BufferRadius can only be used with Python");
+        return CE_Failure;
+    }
+
+    CPLXMLNode* psArgs = CPLGetXMLNode( psTree, "PixelFunctionArguments" );
+    if( psArgs != NULL )
+    {
+        if( !EQUAL(m_poPrivate->m_osLanguage, "Python") )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "PixelFunctionArguments can only be used with Python");
+            return CE_Failure;
+        }
+        for( CPLXMLNode* psIter = psArgs->psChild;
+                         psIter != NULL;
+                         psIter = psIter->psNext )
+        {
+            if( psIter->eType == CXT_Attribute )
+            {
+                m_poPrivate->m_oFunctionArgs.push_back(
+                    std::pair<CPLString,CPLString>(psIter->pszValue,
+                                                   psIter->psChild->pszValue));
+            }
+        }
+    }
+
+    // Read optional source transfer data type.
     const char *pszTypeName = CPLGetXMLValue(psTree, "SourceTransferType", NULL);
-    if (pszTypeName != NULL) {
-	eSourceTransferType = GDALGetDataTypeByName( pszTypeName );
+    if( pszTypeName != NULL )
+    {
+        eSourceTransferType = GDALGetDataTypeByName( pszTypeName );
     }
 
     return CE_None;
@@ -418,7 +2046,7 @@ CPLErr VRTDerivedRasterBand::XMLInit( CPLXMLNode *psTree,
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
-CPLXMLNode *VRTDerivedRasterBand::SerializeToXML(const char *pszVRTPath)
+CPLXMLNode *VRTDerivedRasterBand::SerializeToXML( const char *pszVRTPath )
 {
     CPLXMLNode *psTree = VRTSourcedRasterBand::SerializeToXML( pszVRTPath );
 
@@ -430,11 +2058,114 @@ CPLXMLNode *VRTDerivedRasterBand::SerializeToXML(const char *pszVRTPath)
         CXT_Text, "VRTDerivedRasterBand" );
 
     /* ---- Encode DerivedBand-specific fields ---- */
+    if( !EQUAL( m_poPrivate->m_osLanguage, "C" ) )
+    {
+        CPLSetXMLValue( psTree, "PixelFunctionLanguage",
+                        m_poPrivate->m_osLanguage );
+    }
     if( pszFuncName != NULL && strlen(pszFuncName) > 0 )
         CPLSetXMLValue( psTree, "PixelFunctionType", pszFuncName );
+    if( !m_poPrivate->m_oFunctionArgs.empty() )
+    {
+        CPLXMLNode* psArgs = CPLCreateXMLNode( psTree, CXT_Element,
+                                               "PixelFunctionArguments" );
+        for( size_t i = 0; i < m_poPrivate->m_oFunctionArgs.size(); ++i )
+        {
+            const char* pszKey =
+                m_poPrivate->m_oFunctionArgs[i].first.c_str();
+            const char* pszValue =
+                m_poPrivate->m_oFunctionArgs[i].second.c_str();
+            CPLCreateXMLNode(
+                CPLCreateXMLNode( psArgs, CXT_Attribute, pszKey ),
+                                  CXT_Text, pszValue );
+        }
+    }
+    if( !m_poPrivate->m_osCode.empty() )
+    {
+        if( m_poPrivate->m_osCode.find("<![CDATA[") == std::string::npos )
+        {
+            CPLCreateXMLNode(
+                CPLCreateXMLNode( psTree,
+                                  CXT_Element, "PixelFunctionCode" ),
+                 CXT_Literal,
+                 ("<![CDATA[" + m_poPrivate->m_osCode + "]]>").c_str() );
+        }
+        else
+        {
+            CPLSetXMLValue( psTree, "PixelFunctionCode",
+                            m_poPrivate->m_osCode );
+        }
+    }
+    if( m_poPrivate->m_nBufferRadius != 0 )
+        CPLSetXMLValue( psTree, "BufferRadius",
+                        CPLSPrintf("%d",m_poPrivate->m_nBufferRadius) );
     if( this->eSourceTransferType != GDT_Unknown)
         CPLSetXMLValue( psTree, "SourceTransferType",
-		        GDALGetDataTypeName( eSourceTransferType ) );
+                        GDALGetDataTypeName( eSourceTransferType ) );
 
     return psTree;
 }
+
+/************************************************************************/
+/*                             GetMinimum()                             */
+/************************************************************************/
+
+double VRTDerivedRasterBand::GetMinimum( int *pbSuccess )
+{
+    return GDALRasterBand::GetMinimum(pbSuccess);
+}
+
+/************************************************************************/
+/*                             GetMaximum()                             */
+/************************************************************************/
+
+double VRTDerivedRasterBand::GetMaximum( int *pbSuccess )
+{
+    return GDALRasterBand::GetMaximum(pbSuccess);
+}
+
+/************************************************************************/
+/*                       ComputeRasterMinMax()                          */
+/************************************************************************/
+
+CPLErr VRTDerivedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinMax )
+{
+    return GDALRasterBand::ComputeRasterMinMax( bApproxOK, adfMinMax );
+}
+
+/************************************************************************/
+/*                         ComputeStatistics()                          */
+/************************************************************************/
+
+CPLErr
+VRTDerivedRasterBand::ComputeStatistics( int bApproxOK,
+                                         double *pdfMin, double *pdfMax,
+                                         double *pdfMean, double *pdfStdDev,
+                                         GDALProgressFunc pfnProgress,
+                                         void *pProgressData )
+
+{
+    return GDALRasterBand::ComputeStatistics(  bApproxOK,
+                                            pdfMin, pdfMax,
+                                            pdfMean, pdfStdDev,
+                                            pfnProgress, pProgressData );
+}
+
+/************************************************************************/
+/*                            GetHistogram()                            */
+/************************************************************************/
+
+CPLErr VRTDerivedRasterBand::GetHistogram( double dfMin, double dfMax,
+                                           int nBuckets, GUIntBig *panHistogram,
+                                           int bIncludeOutOfRange, int bApproxOK,
+                                           GDALProgressFunc pfnProgress,
+                                           void *pProgressData )
+
+{
+    return VRTRasterBand::GetHistogram( dfMin, dfMax,
+                                            nBuckets, panHistogram,
+                                            bIncludeOutOfRange, bApproxOK,
+                                            pfnProgress, pProgressData );
+}
+
+/*! @endcond */
diff --git a/frmts/vrt/vrtdriver.cpp b/frmts/vrt/vrtdriver.cpp
index 35cd485..d705e59 100644
--- a/frmts/vrt/vrtdriver.cpp
+++ b/frmts/vrt/vrtdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vrtdriver.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTDriver
@@ -29,28 +28,28 @@
  ****************************************************************************/
 
 #include "vrtdataset.h"
+
 #include "cpl_minixml.h"
 #include "cpl_string.h"
-#include "gdal_frmts.h"
 #include "gdal_alg_priv.h"
+#include "gdal_frmts.h"
 
-CPL_CVSID("$Id: vrtdriver.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: vrtdriver.cpp 35585 2016-10-02 08:52:40Z rouault $");
+
+/*! @cond Doxygen_Suppress */
 
 /************************************************************************/
 /*                             VRTDriver()                              */
 /************************************************************************/
 
-VRTDriver::VRTDriver()
-
+VRTDriver::VRTDriver() :
+    papszSourceParsers(NULL)
 {
-    papszSourceParsers = NULL;
 #if 0
     pDeserializerData = GDALRegisterTransformDeserializer(
         "WarpedOverviewTransformer",
         VRTWarpedOverviewTransform,
         VRTDeserializeWarpedOverviewTransformer );
-#else
-    m_pDeserializerData = NULL;
 #endif
 }
 
@@ -62,8 +61,9 @@ VRTDriver::~VRTDriver()
 
 {
     CSLDestroy( papszSourceParsers );
+    VRTDerivedRasterBand::Cleanup();
 #if 0
-    if ( pDeserializerData )
+    if(  pDeserializerData )
     {
         GDALUnregisterTransformDeserializer( pDeserializerData );
     }
@@ -78,7 +78,7 @@ char **VRTDriver::GetMetadataDomainList()
 {
     return BuildMetadataDomainList( GDALDriver::GetMetadataDomainList(),
                                     TRUE,
-                                    "SourceParsers", NULL);
+                                    "SourceParsers", NULL );
 }
 
 /************************************************************************/
@@ -119,9 +119,12 @@ void VRTDriver::AddSourceParser( const char *pszElementName,
                                  VRTSourceParser pfnParser )
 
 {
-    char szPtrValue[128];
+    char szPtrValue[128] = { '\0' };
+    void* ptr;
+    CPL_STATIC_ASSERT(sizeof(pfnParser) == sizeof(void*));
+    memcpy(&ptr, &pfnParser, sizeof(void*));
     int nRet = CPLPrintPointer( szPtrValue,
-                                reinterpret_cast<void*>(pfnParser),
+                                ptr,
                                 sizeof(szPtrValue) );
     szPtrValue[nRet] = 0;
 
@@ -149,9 +152,11 @@ VRTSource *VRTDriver::ParseSource( CPLXMLNode *psSrc, const char *pszVRTPath )
     if( pszParserFunc == NULL )
         return NULL;
 
-    VRTSourceParser pfnParser = reinterpret_cast<VRTSourceParser>
-                        (CPLScanPointer(pszParserFunc,
-                                        static_cast<int>(strlen(pszParserFunc))));
+    VRTSourceParser pfnParser;
+    CPL_STATIC_ASSERT(sizeof(pfnParser) == sizeof(void*));
+    void* ptr = CPLScanPointer( pszParserFunc,
+                        static_cast<int>(strlen(pszParserFunc)) );
+    memcpy(&pfnParser, &ptr, sizeof(void*));
 
     if( pfnParser == NULL )
         return NULL;
@@ -205,7 +210,7 @@ VRTCreateCopy( const char * pszFilename,
         if( 0 != strlen( pszFilename ) )
         {
             VSILFILE *fpVRT = VSIFOpenL( pszFilename, "wb" );
-            if (fpVRT == NULL)
+            if( fpVRT == NULL )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Cannot create %s", pszFilename);
@@ -224,7 +229,6 @@ VRTCreateCopy( const char * pszFilename,
         else
         {
             /* No destination file is given, so pass serialized XML directly. */
-
             pCopyDS = reinterpret_cast<GDALDataset *>(
                 GDALOpen( pszXML, GA_Update ) );
         }
@@ -242,13 +246,13 @@ VRTCreateCopy( const char * pszFilename,
                             poSrcDS->GetRasterXSize(),
                             poSrcDS->GetRasterYSize(),
                             0, GDT_Byte, NULL ) );
-    if (poVRTDS == NULL)
+    if( poVRTDS == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a geotransform?                                      */
 /* -------------------------------------------------------------------- */
-    double adfGeoTransform[6];
+    double adfGeoTransform[6] = { 0.0 };
 
     if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
     {
@@ -291,7 +295,7 @@ VRTCreateCopy( const char * pszFilename,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Loop over all the bands.					*/
+/*      Loop over all the bands.                                        */
 /* -------------------------------------------------------------------- */
     for( int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
     {
@@ -319,7 +323,8 @@ VRTCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Add specific mask band.                                         */
 /* -------------------------------------------------------------------- */
-        if ( (poSrcBand->GetMaskFlags() & (GMF_PER_DATASET | GMF_ALL_VALID | GMF_NODATA)) == 0)
+        if( (poSrcBand->GetMaskFlags()
+              & (GMF_PER_DATASET | GMF_ALL_VALID | GMF_NODATA)) == 0)
         {
             VRTSourcedRasterBand* poVRTMaskBand = new VRTSourcedRasterBand(
                 poVRTDS, 0,
@@ -333,9 +338,9 @@ VRTCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Add dataset mask band                                           */
 /* -------------------------------------------------------------------- */
-    if (poSrcDS->GetRasterCount() != 0 &&
+    if( poSrcDS->GetRasterCount() != 0 &&
         poSrcDS->GetRasterBand(1) != NULL &&
-        poSrcDS->GetRasterBand(1)->GetMaskFlags() == GMF_PER_DATASET)
+        poSrcDS->GetRasterBand(1)->GetMaskFlags() == GMF_PER_DATASET )
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand(1);
         VRTSourcedRasterBand* poVRTMaskBand = new VRTSourcedRasterBand(
@@ -346,7 +351,13 @@ VRTCreateCopy( const char * pszFilename,
         poVRTDS->SetMaskBand( poVRTMaskBand );
     }
 
+    CPLErrorReset();
     poVRTDS->FlushCache();
+    if( CPLGetLastErrorType() != CE_None )
+    {
+        delete poVRTDS;
+        poVRTDS = NULL;
+    }
 
     return poVRTDS;
 }
@@ -358,6 +369,9 @@ VRTCreateCopy( const char * pszFilename,
 void GDALRegister_VRT()
 
 {
+    // First register the pixel functions
+    GDALRegisterDefaultPixelFunc();
+
     if( GDALGetDriverByName( "VRT" ) != NULL )
         return;
 
@@ -394,3 +408,5 @@ void GDALRegister_VRT()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
+
+/*! @endcond */
diff --git a/frmts/vrt/vrtfilters.cpp b/frmts/vrt/vrtfilters.cpp
index e53bf3d..44d7da8 100644
--- a/frmts/vrt/vrtfilters.cpp
+++ b/frmts/vrt/vrtfilters.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vrtfilters.cpp 35350 2016-09-07 07:21:52Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of some filter types.
@@ -28,11 +27,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "vrtdataset.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: vrtfilters.cpp 35350 2016-09-07 07:21:52Z rouault $");
+CPL_CVSID("$Id: vrtfilters.cpp 37310 2017-02-06 11:42:54Z goatbar $");
+
+/*! @cond Doxygen_Suppress */
 
 /************************************************************************/
 /* ==================================================================== */
@@ -48,6 +60,9 @@ VRTFilteredSource::VRTFilteredSource() :
     m_nSupportedTypesCount(1),
     m_nExtraEdgePixels(0)
 {
+    for( size_t i = 0; i < CPL_ARRAYSIZE(m_aeSupportedTypes); ++i )
+        m_aeSupportedTypes[i] = GDT_Unknown;
+
     m_aeSupportedTypes[0] = GDT_Float32;
 }
 
@@ -78,7 +93,7 @@ void VRTFilteredSource::SetFilteringDataTypesSupported( int nTypeCount,
     if( nTypeCount >
         static_cast<int>( sizeof(m_aeSupportedTypes) / sizeof(GDALDataType) ) )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         nTypeCount = static_cast<int>(
             sizeof(m_aeSupportedTypes) / sizeof(GDALDataType) );
     }
@@ -125,15 +140,25 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     {
         return VRTComplexSource::RasterIO( nXOff, nYOff, nXSize, nYSize,
                                            pData, nBufXSize, nBufYSize,
-                                           eBufType, nPixelSpace, nLineSpace, psExtraArg );
+                                           eBufType, nPixelSpace, nLineSpace,
+                                           psExtraArg );
     }
 
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                         &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
@@ -195,7 +220,7 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     const int nExtraYSize = nOutYSize + 2 * m_nExtraEdgePixels;
 
     // FIXME? : risk of multiplication overflow
-    GByte *pabyWorkData = reinterpret_cast<GByte *>(
+    GByte *pabyWorkData = static_cast<GByte *>(
         VSI_CALLOC_VERBOSE( nExtraXSize * nExtraYSize,
                    GDALGetDataTypeSize(eOperDataType) / 8 ) );
 
@@ -204,7 +229,7 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
         return CE_Failure;
     }
 
-    const int nPixelOffset = GDALGetDataTypeSize( eOperDataType ) / 8;
+    const int nPixelOffset = GDALGetDataTypeSizeBytes( eOperDataType );
     const int nLineOffset = nPixelOffset * nExtraXSize;
 
 /* -------------------------------------------------------------------- */
@@ -217,7 +242,7 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     if( nPixelSpace != nPixelOffset || nLineSpace != nLineOffset
         || eOperDataType != eBufType )
     {
-        pabyOutData = reinterpret_cast<GByte *>(
+        pabyOutData = static_cast<GByte *>(
             VSI_MALLOC3_VERBOSE( nOutXSize, nOutYSize, nPixelOffset ) );
 
         if( pabyOutData == NULL )
@@ -227,7 +252,9 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
         }
     }
     else
+    {
         pabyOutData = reinterpret_cast<GByte *>( pData );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Figure out the extended window that we want to load.  Note      */
@@ -239,10 +266,10 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     int nFileXSize = nExtraXSize;
     int nFileYSize = nExtraYSize;
 
-    int nTopFill=0;
-    int nLeftFill=0;
-    int nRightFill=0;
-    int nBottomFill=0;
+    int nTopFill = 0;
+    int nLeftFill = 0;
+    int nRightFill = 0;
+    int nBottomFill = 0;
 
     if( nFileXOff < 0 )
     {
@@ -273,24 +300,26 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Load the data.                                                  */
 /* -------------------------------------------------------------------- */
-    const bool bIsComplex = CPL_TO_BOOL( GDALDataTypeIsComplex(eOperDataType) );
-    CPLErr eErr
-        = VRTComplexSource::RasterIOInternal<float>(
-            nFileXOff, nFileYOff, nFileXSize, nFileYSize,
-            pabyWorkData + nLineOffset * nTopFill + nPixelOffset * nLeftFill,
-            nFileXSize, nFileYSize, eOperDataType,
-            nPixelOffset, nLineOffset, psExtraArg,
-            bIsComplex ? GDT_CFloat32 : GDT_Float32 );
-
-    if( eErr != CE_None )
     {
-        if( pabyWorkData != pData )
-            VSIFree( pabyWorkData );
+        const bool bIsComplex = CPL_TO_BOOL( GDALDataTypeIsComplex(eOperDataType) );
+        const CPLErr eErr
+            = VRTComplexSource::RasterIOInternal<float>(
+                nFileXOff, nFileYOff, nFileXSize, nFileYSize,
+                pabyWorkData + nLineOffset * nTopFill + nPixelOffset * nLeftFill,
+                nFileXSize, nFileYSize, eOperDataType,
+                nPixelOffset, nLineOffset, psExtraArg,
+                bIsComplex ? GDT_CFloat32 : GDT_Float32 );
+
+        if( eErr != CE_None )
+        {
+            if( pabyWorkData != pData )
+                VSIFree( pabyWorkData );
 
-        if( pabyOutData != pData )
-            VSIFree( pabyOutData );
+            if( pabyOutData != pData )
+                VSIFree( pabyOutData );
 
-        return eErr;
+            return eErr;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -336,8 +365,8 @@ VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Filter the data.                                                */
 /* -------------------------------------------------------------------- */
-    eErr = FilterData( nOutXSize, nOutYSize, eOperDataType,
-                       pabyWorkData, pabyOutData );
+    const CPLErr eErr = FilterData( nOutXSize, nOutYSize, eOperDataType,
+                                    pabyWorkData, pabyOutData );
 
     VSIFree( pabyWorkData );
     if( eErr != CE_None )
@@ -417,7 +446,8 @@ CPLErr VRTKernelFilteredSource::SetKernel( int nNewKernelSize,
     if( nNewKernelSize < 1 || (nNewKernelSize % 2) != 1 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Illegal filtering kernel size %d, must be odd positive number.",
+                  "Illegal filtering kernel size %d, "
+                  "must be odd positive number.",
                   nNewKernelSize );
         return CE_Failure;
     }
@@ -425,7 +455,7 @@ CPLErr VRTKernelFilteredSource::SetKernel( int nNewKernelSize,
     CPLFree( m_padfKernelCoefs );
     m_nKernelSize = nNewKernelSize;
 
-    m_padfKernelCoefs = reinterpret_cast<double *>(
+    m_padfKernelCoefs = static_cast<double *>(
         CPLMalloc(sizeof(double) * m_nKernelSize * m_nKernelSize ) );
     memcpy( m_padfKernelCoefs, padfNewCoefs,
             sizeof(double) * m_nKernelSize * m_nKernelSize );
@@ -439,9 +469,10 @@ CPLErr VRTKernelFilteredSource::SetKernel( int nNewKernelSize,
 /*                             FilterData()                             */
 /************************************************************************/
 
-CPLErr VRTKernelFilteredSource::
-FilterData( int nXSize, int nYSize, GDALDataType eType,
-            GByte *pabySrcData, GByte *pabyDstData )
+CPLErr VRTKernelFilteredSource::FilterData( int nXSize, int nYSize,
+                                            GDALDataType eType,
+                                            GByte *pabySrcData,
+                                            GByte *pabyDstData )
 
 {
 /* -------------------------------------------------------------------- */
@@ -464,37 +495,40 @@ FilterData( int nXSize, int nYSize, GDALDataType eType,
 /* -------------------------------------------------------------------- */
     if( eType == GDT_Float32 )
     {
-        int bHasNoData;
-        float fNoData
-            = static_cast<float>( m_poRasterBand->GetNoDataValue(&bHasNoData) );
+        int bHasNoData = FALSE;
+        const float fNoData =
+            static_cast<float>( m_poRasterBand->GetNoDataValue(&bHasNoData) );
 
         for( int iY = 0; iY < nYSize; iY++ )
         {
             for( int iX = 0; iX < nXSize; iX++ )
             {
-                const int iIndex
-                    = (iY+m_nKernelSize/2 ) * (nXSize+2*m_nExtraEdgePixels)
-                    + iX + m_nKernelSize/2;
-                const float  fCenter
-                    = reinterpret_cast<float *>( pabySrcData )[iIndex];
-
-                int iKern = 0;
-                double dfSum = 0.0;
-                double dfKernSum = 0.0;
+                const int iIndex =
+                    ( iY + m_nKernelSize / 2 ) *
+                    ( nXSize + 2 * m_nExtraEdgePixels )
+                    + iX + m_nKernelSize / 2;
+                const float fCenter =
+                    reinterpret_cast<float *>( pabySrcData )[iIndex];
+
                 float fResult = 0.0;
 
                 // Check if center srcpixel is NoData
-                if(!bHasNoData || fCenter != fNoData)
+                if( !bHasNoData || fCenter != fNoData )
                 {
+                    int iKern = 0;
+                    double dfSum = 0.0;
+                    double dfKernSum = 0.0;
+
                     for( int iYY = 0; iYY < m_nKernelSize; iYY++ )
                     {
-                        float *pafData
-                            = reinterpret_cast<float *>( pabySrcData )
+                        float *pafData =
+                            reinterpret_cast<float *>( pabySrcData )
                             + (iY+iYY) * (nXSize+2*m_nExtraEdgePixels) + iX;
 
-                        for( int i = 0; i < m_nKernelSize; i++, pafData++, iKern++ )
+                        for( int i = 0; i < m_nKernelSize; i++, pafData++,
+                             iKern++ )
                         {
-                            if(!bHasNoData || *pafData != fNoData)
+                            if( !bHasNoData || *pafData != fNoData )
                             {
                                 dfSum += *pafData * m_padfKernelCoefs[iKern];
                                 dfKernSum += m_padfKernelCoefs[iKern];
@@ -509,14 +543,18 @@ FilterData( int nXSize, int nYSize, GDALDataType eType,
                             fResult = 0.0;
                     }
                     else
+                    {
                         fResult = static_cast<float>( dfSum );
+                    }
 
-                    reinterpret_cast<float *>( pabyDstData )[iX + iY * nXSize]
-                        = fResult;
+                    reinterpret_cast<float *>( pabyDstData )[iX + iY * nXSize] =
+                        fResult;
                 }
                 else
-                    reinterpret_cast<float *>( pabyDstData )[iX + iY * nXSize]
-                        = fNoData;
+                {
+                    reinterpret_cast<float *>( pabyDstData )[iX + iY * nXSize] =
+                        fNoData;
+                }
             }
         }
     }
@@ -532,9 +570,11 @@ CPLErr VRTKernelFilteredSource::XMLInit( CPLXMLNode *psTree,
                                          const char *pszVRTPath )
 
 {
-    CPLErr eErr = VRTFilteredSource::XMLInit( psTree, pszVRTPath );
-    if( eErr != CE_None )
-        return eErr;
+    {
+        const CPLErr eErr = VRTFilteredSource::XMLInit( psTree, pszVRTPath );
+        if( eErr != CE_None )
+            return eErr;
+    }
 
     const int nNewKernelSize = atoi(CPLGetXMLValue(psTree,"Kernel.Size","0"));
 
@@ -550,20 +590,20 @@ CPLErr VRTKernelFilteredSource::XMLInit( CPLXMLNode *psTree,
     {
         CSLDestroy( papszCoefItems );
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Got wrong number of filter kernel coefficients (%s).\n"
+                  "Got wrong number of filter kernel coefficients (%s).  "
                   "Expected %d, got %d.",
                   CPLGetXMLValue(psTree,"Kernel.Coefs",""),
                   nNewKernelSize * nNewKernelSize, nCoefs );
         return CE_Failure;
     }
 
-    double *padfNewCoefs = reinterpret_cast<double *>(
+    double *padfNewCoefs = static_cast<double *>(
         CPLMalloc( sizeof(double) * nCoefs ) );
 
     for( int i = 0; i < nCoefs; i++ )
         padfNewCoefs[i] = CPLAtof(papszCoefItems[i]);
 
-    eErr = SetKernel( nNewKernelSize, padfNewCoefs );
+    const CPLErr eErr = SetKernel( nNewKernelSize, padfNewCoefs );
 
     CPLFree( padfNewCoefs );
     CSLDestroy( papszCoefItems );
@@ -604,14 +644,13 @@ CPLXMLNode *VRTKernelFilteredSource::SerializeToXML( const char *pszVRTPath )
 
     const int nCoefCount = m_nKernelSize * m_nKernelSize;
     const size_t nBufLen = nCoefCount * 32;
-    char *pszKernelCoefs = reinterpret_cast<char *>(
-        CPLMalloc(nBufLen) );
+    char *pszKernelCoefs = static_cast<char *>( CPLMalloc(nBufLen) );
 
     strcpy( pszKernelCoefs, "" );
     for( int iCoef = 0; iCoef < nCoefCount; iCoef++ )
         CPLsnprintf( pszKernelCoefs + strlen(pszKernelCoefs),
                      nBufLen - strlen(pszKernelCoefs),
-                 "%.8g ", m_padfKernelCoefs[iCoef] );
+                     "%.8g ", m_padfKernelCoefs[iCoef] );
 
     CPLSetXMLValue( psKernel, "Size", CPLSPrintf( "%d", m_nKernelSize ) );
     CPLSetXMLValue( psKernel, "Coefs", pszKernelCoefs );
@@ -628,14 +667,16 @@ CPLXMLNode *VRTKernelFilteredSource::SerializeToXML( const char *pszVRTPath )
 VRTSource *VRTParseFilterSources( CPLXMLNode *psChild, const char *pszVRTPath )
 
 {
-    if( EQUAL(psChild->pszValue,"KernelFilteredSource") )
+    if( EQUAL(psChild->pszValue, "KernelFilteredSource") )
     {
         VRTSource *poSrc = new VRTKernelFilteredSource();
         if( poSrc->XMLInit( psChild, pszVRTPath ) == CE_None )
             return poSrc;
-        else
-            delete poSrc;
+
+        delete poSrc;
     }
 
     return NULL;
 }
+
+/*! @endcond */
diff --git a/frmts/vrt/vrtpansharpened.cpp b/frmts/vrt/vrtpansharpened.cpp
index a0c2419..ddcc1de 100644
--- a/frmts/vrt/vrtpansharpened.cpp
+++ b/frmts/vrt/vrtpansharpened.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vrtpansharpened.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTPansharpenedRasterBand and VRTPansharpenedDataset.
@@ -27,20 +26,35 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "vrtdataset.h"
-
+#include "cpl_port.h"
 #include "gdal_vrt.h"
-#include "gdalpansharpen.h"
-#include "ogr_spatialref.h"
+#include "vrtdataset.h"
 
 #include <cassert>
 #include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
 
 #include <algorithm>
 #include <map>
 #include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "gdalpansharpen.h"
+#include "ogr_core.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: vrtpansharpened.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+CPL_CVSID("$Id: vrtpansharpened.cpp 37310 2017-02-06 11:42:54Z goatbar $");
 
 /************************************************************************/
 /*                    GDALCreatePansharpenedVRT()                       */
@@ -100,6 +114,8 @@ GDALDatasetH GDALCreatePansharpenedVRT( const char* pszXML,
     return reinterpret_cast<GDALDatasetH>( poDS );
 }
 
+/*! @cond Doxygen_Suppress */
+
 /************************************************************************/
 /* ==================================================================== */
 /*                        VRTPansharpenedDataset                        */
@@ -206,7 +222,6 @@ int VRTPansharpenedDataset::CloseDependentDatasets()
     return bHasDroppedRef;
 }
 
-
 /************************************************************************/
 /*                            GetFileList()                             */
 /************************************************************************/
@@ -416,7 +431,10 @@ CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPa
         bPanGeoTransformValid = ( poPanDataset->GetGeoTransform(adfPanGT) == CE_None );
     int nPanXSize = poPanBand->GetXSize();
     int nPanYSize = poPanBand->GetYSize();
-    double dfMinX = 0.0, dfMinY = 0.0, dfMaxX = 0.0, dfMaxY = 0.0;
+    double dfMinX = 0.0;
+    double dfMinY = 0.0;
+    double dfMaxX = 0.0;
+    double dfMaxY = 0.0;
     int bFoundRotatingTerms = FALSE;
     int bHasNoData = FALSE;
     double dfNoData = poPanBand->GetNoDataValue(&bHasNoData);
@@ -456,7 +474,7 @@ CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPa
         if( psIter->eType != CXT_Element || !EQUAL(psIter->pszValue, "SpectralBand") )
             continue;
 
-        if( nInputSpectralBandsIn  )
+        if( nInputSpectralBandsIn && pahInputSpectralBandsIn != NULL )
         {
             if( iSpectralBand == nInputSpectralBandsIn )
             {
@@ -513,9 +531,9 @@ CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPa
                 if( poDataset->GetProjectionRef() )
                     osProjection = poDataset->GetProjectionRef();
 
-                if( osPanProjection.size() )
+                if( !osPanProjection.empty() )
                 {
-                    if( osProjection.size() )
+                    if( !osProjection.empty() )
                     {
                         if( osPanProjection != osProjection )
                         {
@@ -541,7 +559,7 @@ CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPa
                                  osSourceFilename.c_str());
                     }
                 }
-                else if( osProjection.size() )
+                else if( !osProjection.empty() )
                 {
                     CPLError(CE_Warning, CPLE_AppDefined,
                              "Pan dataset has no projection, whereas %s has one. Results might be incorrect",
@@ -805,7 +823,7 @@ CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPa
             }
         }
 
-        if( nInputSpectralBandsIn  )
+        if( nInputSpectralBandsIn && pahInputSpectralBandsIn != NULL )
         {
             poBand = reinterpret_cast<GDALRasterBand *>(
                 pahInputSpectralBandsIn[iSpectralBand] );
@@ -864,7 +882,7 @@ CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPa
         iSpectralBand ++;
     }
 
-    if( ahSpectralBands.size() == 0 )
+    if( ahSpectralBands.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "No spectral band defined");
         goto error;
@@ -984,7 +1002,7 @@ CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPa
         }
     }
 
-    if( adfWeights.size() == 0 )
+    if( adfWeights.empty() )
     {
         for( int i = 0; i < static_cast<int>( ahSpectralBands.size() ); i++ )
         {
@@ -1000,7 +1018,7 @@ CPLErr VRTPansharpenedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPa
         goto error;
     }
 
-    if( aMapDstBandToSpectralBand.size() == 0 )
+    if( aMapDstBandToSpectralBand.empty() )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "No spectral band is mapped to an output band");
@@ -1120,7 +1138,7 @@ CPLXMLNode *VRTPansharpenedDataset::SerializeToXML( const char *pszVRTPathIn )
     }
     else
     {
-        CPLAssert(FALSE);
+        CPLAssert(false);
     }
     if( psOptions->nWeightCount )
     {
@@ -1180,12 +1198,12 @@ CPLXMLNode *VRTPansharpenedDataset::SerializeToXML( const char *pszVRTPathIn )
         CPLCreateXMLElementAndValue( psOptionsNode, "NoData", "None" );
     }
 
-    if( psOptions->dfMSShiftX )
+    if( psOptions->dfMSShiftX != 0.0 )
     {
         CPLCreateXMLElementAndValue( psOptionsNode, "MSShiftX",
                                      CPLSPrintf("%.16g", psOptions->dfMSShiftX) );
     }
-    if( psOptions->dfMSShiftY )
+    if( psOptions->dfMSShiftY != 0.0 )
     {
         CPLCreateXMLElementAndValue( psOptionsNode, "MSShiftY",
                                      CPLSPrintf("%.16g", psOptions->dfMSShiftY) );
@@ -1300,7 +1318,6 @@ CPLErr VRTPansharpenedDataset::AddBand( CPL_UNUSED GDALDataType eType,
     return CE_Failure;
 }
 
-
 /************************************************************************/
 /*                              IRasterIO()                             */
 /************************************************************************/
@@ -1355,7 +1372,6 @@ CPLErr VRTPansharpenedDataset::IRasterIO( GDALRWFlag eRWFlag,
         //{static int bDone = 0; if (!bDone) printf("(2)\n"); bDone = 1; }
         return m_poPansharpener->ProcessRegion(
                     nXOff, nYOff, nXSize, nYSize, pData, eBufType);
-
     }
 
 default_path:
@@ -1382,10 +1398,10 @@ VRTPansharpenedRasterBand::VRTPansharpenedRasterBand( GDALDataset *poDSIn, int n
 {
     Initialize( poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize() );
 
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->eAccess = GA_Update;
-    this->eDataType = eDataTypeIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eAccess = GA_Update;
+    eDataType = eDataTypeIn;
 
     reinterpret_cast<VRTPansharpenedDataset *>(
         poDS )->GetBlockSize( &nBlockXSize, &nBlockYSize );
@@ -1462,9 +1478,7 @@ CPLErr VRTPansharpenedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
             if( iOtherBand == nBand )
                 continue;
 
-            GDALRasterBlock *poBlock;
-
-            poBlock = poGDS->GetRasterBand(iOtherBand)->
+            GDALRasterBlock *poBlock = poGDS->GetRasterBand(iOtherBand)->
                 GetLockedBlockRef(nBlockXOff,nBlockYOff);
             if (poBlock == NULL)
             {
@@ -1652,7 +1666,7 @@ int VRTPansharpenedRasterBand::GetOverviewCount()
 
     // Build on-the-fly overviews from overviews of pan and spectral bands
     if( poGDS->m_poPansharpener != NULL &&
-        poGDS->m_apoOverviewDatasets.size() == 0 &&
+        poGDS->m_apoOverviewDatasets.empty() &&
         poGDS->m_poMainDataset == poGDS )
     {
         GDALPansharpenOptions* psOptions = poGDS->m_poPansharpener->GetOptions();
@@ -1753,3 +1767,5 @@ GDALRasterBand* VRTPansharpenedRasterBand::GetOverview(int iOvr)
 
     return poGDS->m_apoOverviewDatasets[iOvr]->GetRasterBand(nBand);
 }
+
+/*! @endcond */
diff --git a/frmts/vrt/vrtrasterband.cpp b/frmts/vrt/vrtrasterband.cpp
index 314775f..983b26d 100644
--- a/frmts/vrt/vrtrasterband.cpp
+++ b/frmts/vrt/vrtrasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vrtrasterband.cpp 33902 2016-04-06 19:07:34Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTRasterBand
@@ -28,13 +27,29 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "vrtdataset.h"
+
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <memory>
+#include <vector>
+
+#include "gdal.h"
+#include "gdal_pam.h"
+#include "gdal_priv.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_hash_set.h"
 #include "cpl_minixml.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
 
-#include <algorithm>
+/*! @cond Doxygen_Suppress */
 
-CPL_CVSID("$Id: vrtrasterband.cpp 33902 2016-04-06 19:07:34Z rouault $");
+CPL_CVSID("$Id: vrtrasterband.cpp 37310 2017-02-06 11:42:54Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -46,10 +61,29 @@ CPL_CVSID("$Id: vrtrasterband.cpp 33902 2016-04-06 19:07:34Z rouault $");
 /*                           VRTRasterBand()                            */
 /************************************************************************/
 
-VRTRasterBand::VRTRasterBand()
-
+VRTRasterBand::VRTRasterBand() :
+    m_bIsMaskBand(FALSE),
+    m_bNoDataValueSet(FALSE),
+    m_bHideNoDataValue(FALSE),
+    m_dfNoDataValue(-10000.0),
+    m_poColorTable(NULL),
+    m_eColorInterp(GCI_Undefined),
+    m_pszUnitType(NULL),
+    m_papszCategoryNames(NULL),
+    m_dfOffset(0.0),
+    m_dfScale(1.0),
+    m_psSavedHistograms(NULL),
+    m_poMaskBand(NULL)
 {
-    Initialize( 0, 0 );
+    // Initialize( 0, 0 );
+    poDS = NULL;
+    nBand = 0;
+    eAccess = GA_ReadOnly;
+    eDataType = GDT_Byte;
+    nRasterXSize = 0;
+    nRasterYSize = 0;
+    nBlockXSize = 0;
+    nBlockYSize = 0;
 }
 
 /************************************************************************/
@@ -383,6 +417,11 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
         for( CPLXMLNode *psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild;
              psEntry != NULL; psEntry = psEntry->psNext )
         {
+            if( !(psEntry->eType == CXT_Element &&
+                  EQUAL(psEntry->pszValue, "Entry")) )
+            {
+                continue;
+            }
             GDALColorEntry sCEntry;
 
             sCEntry.c1 = (short) atoi(CPLGetXMLValue( psEntry, "c1", "0" ));
@@ -459,8 +498,8 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
         const int nSrcBand = atoi(CPLGetXMLValue( psNode, "SourceBand", "1" ) );
 
         m_apoOverviews.resize( m_apoOverviews.size() + 1 );
-        m_apoOverviews[m_apoOverviews.size()-1].osFilename = pszSrcDSName;
-        m_apoOverviews[m_apoOverviews.size()-1].nBand = nSrcBand;
+        m_apoOverviews.back().osFilename = pszSrcDSName;
+        m_apoOverviews.back().nBand = nSrcBand;
 
         CPLFree( pszSrcDSName );
     }
@@ -506,7 +545,6 @@ CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree,
             break;
         }
 
-
         if( poBand->XMLInit( psNode, pszVRTPath ) == CE_None )
         {
             SetMaskBand(poBand);
@@ -639,8 +677,8 @@ CPLXMLNode *VRTRasterBand::SerializeToXML( const char *pszVRTPath )
         CPLXMLNode *psOVR_XML = CPLCreateXMLNode( psTree, CXT_Element,
                                                  "Overview" );
 
-        int              bRelativeToVRT;
-        const char      *pszRelativePath;
+        int bRelativeToVRT = FALSE;
+        const char *pszRelativePath = NULL;
         VSIStatBufL sStat;
 
         if( VSIStatExL( m_apoOverviews[iOvr].osFilename, &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
@@ -992,7 +1030,7 @@ int VRTRasterBand::GetOverviewCount()
 
 {
     // First: overviews declared in <Overview> element
-    if( m_apoOverviews.size() > 0 )
+    if( !m_apoOverviews.empty() )
         return static_cast<int>(m_apoOverviews.size());
 
     // If not found, external .ovr overviews
@@ -1003,7 +1041,7 @@ int VRTRasterBand::GetOverviewCount()
     // If not found, implicit virtual overviews
     VRTDataset* poVRTDS = reinterpret_cast<VRTDataset *>( poDS );
     poVRTDS->BuildVirtualOverviews();
-    if( poVRTDS->m_apoOverviews.size() && poVRTDS->m_apoOverviews[0] )
+    if( !poVRTDS->m_apoOverviews.empty() && poVRTDS->m_apoOverviews[0] )
         return static_cast<int>( poVRTDS->m_apoOverviews.size() );
 
     return 0;
@@ -1017,7 +1055,7 @@ GDALRasterBand *VRTRasterBand::GetOverview( int iOverview )
 
 {
     // First: overviews declared in <Overview> element
-    if( m_apoOverviews.size() > 0 )
+    if( !m_apoOverviews.empty() )
     {
         if( iOverview < 0
             || iOverview >= static_cast<int>( m_apoOverviews.size() ) )
@@ -1055,7 +1093,7 @@ GDALRasterBand *VRTRasterBand::GetOverview( int iOverview )
     // If not found, implicit virtual overviews
     VRTDataset* poVRTDS = reinterpret_cast<VRTDataset *>( poDS );
     poVRTDS->BuildVirtualOverviews();
-    if( poVRTDS->m_apoOverviews.size() && poVRTDS->m_apoOverviews[0] )
+    if( !poVRTDS->m_apoOverviews.empty() && poVRTDS->m_apoOverviews[0] )
     {
         if( iOverview < 0
             || iOverview >= static_cast<int>( poVRTDS->m_apoOverviews.size() ) )
@@ -1170,3 +1208,5 @@ int VRTRasterBand::CloseDependentDatasets()
 {
     return FALSE;
 }
+
+/*! @endcond */
diff --git a/frmts/vrt/vrtrawrasterband.cpp b/frmts/vrt/vrtrawrasterband.cpp
index 6cd8f4b..24e07a5 100644
--- a/frmts/vrt/vrtrawrasterband.cpp
+++ b/frmts/vrt/vrtrawrasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vrtrawrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTRawRasterBand
@@ -28,12 +27,27 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "rawdataset.h"
 #include "vrtdataset.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_hash_set.h"
 #include "cpl_minixml.h"
 #include "cpl_string.h"
-#include "rawdataset.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+
+CPL_CVSID("$Id: vrtrawrasterband.cpp 37310 2017-02-06 11:42:54Z goatbar $");
 
-CPL_CVSID("$Id: vrtrawrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+/*! @cond Doxygen_Suppress */
 
 /************************************************************************/
 /* ==================================================================== */
@@ -47,12 +61,15 @@ CPL_CVSID("$Id: vrtrawrasterband.cpp 33720 2016-03-15 00:39:53Z goatbar $");
 
 VRTRawRasterBand::VRTRawRasterBand( GDALDataset *poDSIn, int nBandIn,
                                     GDALDataType eType ) :
-    m_poRawRaster(NULL), m_pszSourceFilename(NULL), m_bRelativeToVRT(FALSE)
+    m_poRawRaster(NULL),
+    m_pszSourceFilename(NULL),
+    m_bRelativeToVRT(FALSE)
 {
     Initialize( poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize() );
 
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    // Declared in GDALRasterBand.
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     if( eType != GDT_Unknown )
         eDataType = eType;
@@ -74,12 +91,13 @@ VRTRawRasterBand::~VRTRawRasterBand()
 /************************************************************************/
 
 CPLErr VRTRawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
-                                 int nXOff, int nYOff, int nXSize, int nYSize,
-                                 void * pData, int nBufXSize, int nBufYSize,
-                                 GDALDataType eBufType,
-                                 GSpacing nPixelSpace,
-                                 GSpacing nLineSpace,
-                                 GDALRasterIOExtraArg* psExtraArg)
+                                    int nXOff, int nYOff,
+                                    int nXSize, int nYSize,
+                                    void * pData, int nBufXSize, int nBufYSize,
+                                    GDALDataType eBufType,
+                                    GSpacing nPixelSpace,
+                                    GSpacing nLineSpace,
+                                    GDALRasterIOExtraArg* psExtraArg )
 {
     if( m_poRawRaster == NULL )
     {
@@ -92,9 +110,9 @@ CPLErr VRTRawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
                   "Attempt to write to read only dataset in"
-                  "VRTRawRasterBand::IRasterIO().\n" );
+                  "VRTRawRasterBand::IRasterIO()." );
 
-        return( CE_Failure );
+        return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
@@ -106,15 +124,17 @@ CPLErr VRTRawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     {
         if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
                               pData, nBufXSize, nBufYSize,
-                              eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
+                              eBufType, nPixelSpace,
+                              nLineSpace, psExtraArg ) == CE_None )
             return CE_None;
     }
 
     m_poRawRaster->SetAccess(eAccess);
 
     return m_poRawRaster->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                  pData, nBufXSize, nBufYSize,
-                                  eBufType, nPixelSpace, nLineSpace, psExtraArg );
+                                    pData, nBufXSize, nBufYSize,
+                                    eBufType, nPixelSpace,
+                                    nLineSpace, psExtraArg );
 }
 
 /************************************************************************/
@@ -122,7 +142,7 @@ CPLErr VRTRawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /************************************************************************/
 
 CPLErr VRTRawRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                   void * pImage )
+                                     void * pImage )
 
 {
     if( m_poRawRaster == NULL )
@@ -188,7 +208,9 @@ CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
             CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
     }
     else
+    {
         pszExpandedFilename = CPLStrdup( pszFilename );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Try and open the file.  We always use the large file API.       */
@@ -207,9 +229,8 @@ CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unable to open %s.\n%s",
-                  pszExpandedFilename,
-                  VSIStrerror( errno ) );
+                  "Unable to open %s.%s",
+                  pszExpandedFilename, VSIStrerror( errno ) );
 
         CPLFree( pszExpandedFilename );
         return CE_Failure;
@@ -223,12 +244,12 @@ CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Work out if we are in native mode or not.                       */
 /* -------------------------------------------------------------------- */
-    int bNative = TRUE;
+    bool bNative = true;
 
     if( pszByteOrder != NULL )
     {
         if( EQUAL(pszByteOrder,"LSB") )
-            bNative = CPL_IS_LSB;
+            bNative = CPL_TO_BOOL(CPL_IS_LSB);
         else if( EQUAL(pszByteOrder,"MSB") )
             bNative = !CPL_IS_LSB;
         else
@@ -244,8 +265,8 @@ CPLErr VRTRawRasterBand::SetRawLink( const char *pszFilename,
 /*      Create a corresponding RawRasterBand.                           */
 /* -------------------------------------------------------------------- */
     m_poRawRaster = new RawRasterBand( fp, nImageOffset, nPixelOffset,
-                                     nLineOffset, GetRasterDataType(),
-                                     bNative, GetXSize(), GetYSize(), TRUE );
+                                       nLineOffset, GetRasterDataType(),
+                                       bNative, GetXSize(), GetYSize(), TRUE );
 
 /* -------------------------------------------------------------------- */
 /*      Reset block size to match the raw raster.                       */
@@ -267,8 +288,8 @@ void VRTRawRasterBand::ClearRawLink()
         VSILFILE* fp = m_poRawRaster->GetFPL();
         delete m_poRawRaster;
         m_poRawRaster = NULL;
-        /* We close the file after deleting the raster band */
-        /* since data can be flushed in the destructor */
+        // We close the file after deleting the raster band
+        // since data can be flushed in the destructor.
         if( fp != NULL )
         {
             CPLCloseShared( reinterpret_cast<FILE*>( fp ) );
@@ -283,10 +304,10 @@ void VRTRawRasterBand::ClearRawLink()
 /************************************************************************/
 
 CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
-                                      const char *pszVRTPath )
+                                  const char *pszVRTPath )
 
 {
-    CPLErr eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
+    const CPLErr eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
     if( eErr != CE_None )
         return eErr;
 
@@ -294,8 +315,8 @@ CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
 /*      Validate a bit.                                                 */
 /* -------------------------------------------------------------------- */
     if( psTree == NULL || psTree->eType != CXT_Element
-        || !EQUAL(psTree->pszValue,"VRTRasterBand")
-        || !EQUAL(CPLGetXMLValue(psTree,"subClass",""),"VRTRawRasterBand") )
+        || !EQUAL(psTree->pszValue, "VRTRasterBand")
+        || !EQUAL(CPLGetXMLValue(psTree,"subClass",""), "VRTRawRasterBand") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid node passed to VRTRawRasterBand::XMLInit()." );
@@ -315,31 +336,33 @@ CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
         return CE_Failure;
     }
 
-    const int l_bRelativeToVRT
-        = atoi(CPLGetXMLValue( psTree, "SourceFilename.relativeToVRT", "1" ) );
+    // TODO(schwehr): Should this be a bool?
+    const int l_bRelativeToVRT =
+        atoi(CPLGetXMLValue( psTree, "SourceFilename.relativeToVRT", "1" ) );
 
 /* -------------------------------------------------------------------- */
 /*      Collect layout information.                                     */
 /* -------------------------------------------------------------------- */
-    int nPixelOffset;
-    int nWordDataSize = GDALGetDataTypeSize( GetRasterDataType() ) / 8;
+    int nWordDataSize = GDALGetDataTypeSizeBytes( GetRasterDataType() );
 
     const char* pszImageOffset = CPLGetXMLValue( psTree, "ImageOffset", "0");
     const vsi_l_offset nImageOffset = CPLScanUIntBig(
-                        pszImageOffset, static_cast<int>(strlen(pszImageOffset)));
+        pszImageOffset, static_cast<int>(strlen(pszImageOffset)) );
 
-    if( CPLGetXMLValue( psTree, "PixelOffset", NULL ) == NULL )
-        nPixelOffset = nWordDataSize;
-    else
+    int nPixelOffset = nWordDataSize;
+    if( CPLGetXMLValue( psTree, "PixelOffset", NULL ) != NULL )
+    {
         nPixelOffset = atoi(CPLGetXMLValue( psTree, "PixelOffset", "0") );
+    }
     if (nPixelOffset <= 0)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Invalid value for <PixelOffset> element : %d", nPixelOffset );
+                  "Invalid value for <PixelOffset> element : %d",
+                  nPixelOffset );
         return CE_Failure;
     }
 
-    int nLineOffset;
+    int nLineOffset = 0;
     if( CPLGetXMLValue( psTree, "LineOffset", NULL ) == NULL )
         nLineOffset = nWordDataSize * GetXSize();
     else
@@ -356,17 +379,6 @@ CPLErr VRTRawRasterBand::XMLInit( CPLXMLNode * psTree,
 }
 
 /************************************************************************/
-/*                           VRTRawStripSpace()                         */
-/************************************************************************/
-
-static const char* VRTRawStripSpace(const char* pszStr)
-{
-    while( *pszStr == ' ' )
-        pszStr ++;
-    return pszStr;
-}
-
-/************************************************************************/
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
@@ -380,7 +392,8 @@ CPLXMLNode *VRTRawRasterBand::SerializeToXML( const char *pszVRTPath )
     if( m_poRawRaster == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "VRTRawRasterBand::SerializeToXML() fails because m_poRawRaster is NULL." );
+                  "VRTRawRasterBand::SerializeToXML() fails because "
+                  "m_poRawRaster is NULL." );
         return NULL;
     }
 
@@ -407,19 +420,18 @@ CPLXMLNode *VRTRawRasterBand::SerializeToXML( const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Set other layout information.                                   */
 /* -------------------------------------------------------------------- */
-    char szOffset[22];
 
-    CPLPrintUIntBig(szOffset, m_poRawRaster->GetImgOffset(), sizeof(szOffset)-1);
-    szOffset[sizeof(szOffset)-1] = '\0';
-    CPLCreateXMLElementAndValue(psTree, "ImageOffset", VRTRawStripSpace(szOffset));
+    CPLCreateXMLElementAndValue( psTree, "ImageOffset",
+                                 CPLSPrintf( CPL_FRMT_GUIB,
+                                             m_poRawRaster->GetImgOffset()) );
 
-    CPLPrintUIntBig(szOffset, m_poRawRaster->GetPixelOffset(),sizeof(szOffset)-1);
-    szOffset[sizeof(szOffset)-1] = '\0';
-    CPLCreateXMLElementAndValue(psTree, "PixelOffset", VRTRawStripSpace(szOffset));
+    CPLCreateXMLElementAndValue( psTree, "PixelOffset",
+                                 CPLSPrintf( "%d",
+                                             m_poRawRaster->GetPixelOffset()) );
 
-    CPLPrintUIntBig(szOffset, m_poRawRaster->GetLineOffset(), sizeof(szOffset)-1);
-    szOffset[sizeof(szOffset)-1] = '\0';
-    CPLCreateXMLElementAndValue(psTree, "LineOffset", VRTRawStripSpace(szOffset));
+    CPLCreateXMLElementAndValue( psTree, "LineOffset",
+                                 CPLSPrintf( "%d",
+                                             m_poRawRaster->GetLineOffset()) );
 
 #if CPL_IS_LSB == 1
     if( m_poRawRaster->GetNativeOrder() )
@@ -437,8 +449,8 @@ CPLXMLNode *VRTRawRasterBand::SerializeToXML( const char *pszVRTPath )
 /*                             GetFileList()                            */
 /************************************************************************/
 
-void VRTRawRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
-                                int *pnMaxSize, CPLHashSet* hSetFiles)
+void VRTRawRasterBand::GetFileList( char*** ppapszFileList, int *pnSize,
+                                    int *pnMaxSize, CPLHashSet* hSetFiles )
 {
     if (m_pszSourceFilename == NULL)
         return;
@@ -446,7 +458,14 @@ void VRTRawRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
 /* -------------------------------------------------------------------- */
 /*      Is it already in the list ?                                     */
 /* -------------------------------------------------------------------- */
-    if( CPLHashSetLookup(hSetFiles, m_pszSourceFilename) != NULL )
+    CPLString osSourceFilename;
+    if( m_bRelativeToVRT && strlen(poDS->GetDescription()) > 0 )
+        osSourceFilename = CPLFormFilename(
+              CPLGetDirname(poDS->GetDescription()), m_pszSourceFilename, NULL );
+    else
+        osSourceFilename = m_pszSourceFilename;
+
+    if( CPLHashSetLookup(hSetFiles, osSourceFilename) != NULL )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -462,12 +481,14 @@ void VRTRawRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
 /* -------------------------------------------------------------------- */
 /*      Add the string to the list                                      */
 /* -------------------------------------------------------------------- */
-    (*ppapszFileList)[*pnSize] = CPLStrdup(m_pszSourceFilename);
+    (*ppapszFileList)[*pnSize] = CPLStrdup(osSourceFilename);
     (*ppapszFileList)[(*pnSize + 1)] = NULL;
     CPLHashSetInsert(hSetFiles, (*ppapszFileList)[*pnSize]);
 
-    (*pnSize) ++;
+    (*pnSize)++;
 
     VRTRasterBand::GetFileList( ppapszFileList, pnSize,
                                 pnMaxSize, hSetFiles);
 }
+
+/*! @endcond */
diff --git a/frmts/vrt/vrtsourcedrasterband.cpp b/frmts/vrt/vrtsourcedrasterband.cpp
index 00c9ec2..566e420 100644
--- a/frmts/vrt/vrtsourcedrasterband.cpp
+++ b/frmts/vrt/vrtsourcedrasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vrtsourcedrasterband.cpp 35188 2016-08-23 15:02:58Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSourcedRasterBand
@@ -28,11 +27,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_vrt.h"
 #include "vrtdataset.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_hash_set.h"
 #include "cpl_minixml.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "ogr_geometry.h"
 
-CPL_CVSID("$Id: vrtsourcedrasterband.cpp 35188 2016-08-23 15:02:58Z rouault $");
+CPL_CVSID("$Id: vrtsourcedrasterband.cpp 37310 2017-02-06 11:42:54Z goatbar $");
+
+/*! @cond Doxygen_Suppress */
 
 /************************************************************************/
 /* ==================================================================== */
@@ -44,13 +63,18 @@ CPL_CVSID("$Id: vrtsourcedrasterband.cpp 35188 2016-08-23 15:02:58Z rouault $");
 /*                        VRTSourcedRasterBand()                        */
 /************************************************************************/
 
-VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDSIn, int nBandIn )
-
+VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDSIn, int nBandIn ) :
+    m_nRecursionCounter(0),
+    m_papszSourceList(NULL),
+    nSources(0),
+    papoSources(NULL),
+    bSkipBufferInitialization(FALSE)
 {
-    Initialize( poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize() );
+    VRTRasterBand::Initialize( poDSIn->GetRasterXSize(),
+                               poDSIn->GetRasterYSize() );
 
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 }
 
 /************************************************************************/
@@ -58,10 +82,14 @@ VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDSIn, int nBandIn )
 /************************************************************************/
 
 VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataType eType,
-                                            int nXSize, int nYSize )
-
+                                            int nXSize, int nYSize ) :
+    m_nRecursionCounter(0),
+    m_papszSourceList(NULL),
+    nSources(0),
+    papoSources(NULL),
+    bSkipBufferInitialization(FALSE)
 {
-    Initialize( nXSize, nYSize );
+    VRTRasterBand::Initialize( nXSize, nYSize );
 
     eDataType = eType;
 }
@@ -72,34 +100,22 @@ VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataType eType,
 
 VRTSourcedRasterBand::VRTSourcedRasterBand( GDALDataset *poDSIn, int nBandIn,
                                             GDALDataType eType,
-                                            int nXSize, int nYSize )
-
+                                            int nXSize, int nYSize ) :
+    m_nRecursionCounter(0),
+    m_papszSourceList(NULL),
+    nSources(0),
+    papoSources(NULL),
+    bSkipBufferInitialization(FALSE)
 {
-    Initialize( nXSize, nYSize );
+    VRTRasterBand::Initialize( nXSize, nYSize );
 
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
 
     eDataType = eType;
 }
 
 /************************************************************************/
-/*                             Initialize()                             */
-/************************************************************************/
-
-void VRTSourcedRasterBand::Initialize( int nXSize, int nYSize )
-
-{
-    VRTRasterBand::Initialize( nXSize, nYSize );
-
-    nSources = 0;
-    papoSources = NULL;
-    bEqualAreas = FALSE;
-    m_nRecursionCounter = 0;
-    m_papszSourceList = NULL;
-}
-
-/************************************************************************/
 /*                       ~VRTSourcedRasterBand()                        */
 /************************************************************************/
 
@@ -115,12 +131,14 @@ VRTSourcedRasterBand::~VRTSourcedRasterBand()
 /************************************************************************/
 
 CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
-                                 int nXOff, int nYOff, int nXSize, int nYSize,
-                                 void * pData, int nBufXSize, int nBufYSize,
-                                 GDALDataType eBufType,
-                                 GSpacing nPixelSpace,
-                                 GSpacing nLineSpace,
-                                 GDALRasterIOExtraArg* psExtraArg )
+                                        int nXOff, int nYOff,
+                                        int nXSize, int nYSize,
+                                        void *pData,
+                                        int nBufXSize, int nBufYSize,
+                                        GDALDataType eBufType,
+                                        GSpacing nPixelSpace,
+                                        GSpacing nLineSpace,
+                                        GDALRasterIOExtraArg *psExtraArg )
 
 {
     if( eRWFlag == GF_Write )
@@ -135,10 +153,11 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     // return the already opened dataset, we can just test a member variable.
     // We allow 1, since IRasterIO() can be called from ComputeStatistics(),
     // which itself increments the recursion counter.
-    if ( m_nRecursionCounter > 1 )
+    if( m_nRecursionCounter > 1 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "VRTSourcedRasterBand::IRasterIO() called recursively on the same band. "
+                  "VRTSourcedRasterBand::IRasterIO() called "
+                  "recursively on the same band. "
                   "It looks like the VRT is referencing itself." );
         return CE_Failure;
     }
@@ -150,9 +169,10 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if( (nBufXSize < nXSize || nBufYSize < nYSize)
         && GetOverviewCount() > 0 )
     {
-        if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                              pData, nBufXSize, nBufYSize,
-                              eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
+        if( OverviewRasterIO(
+               eRWFlag, nXOff, nYOff, nXSize, nYSize,
+               pData, nBufXSize, nBufYSize,
+               eBufType, nPixelSpace, nLineSpace, psExtraArg ) == CE_None )
             return CE_None;
     }
 
@@ -221,10 +241,15 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /*      Initialize the buffer to some background value. Use the         */
 /*      nodata value if available.                                      */
 /* -------------------------------------------------------------------- */
-    if ( nPixelSpace == GDALGetDataTypeSize(eBufType)/8 &&
-         (!m_bNoDataValueSet || (!CPLIsNan(m_dfNoDataValue) && m_dfNoDataValue == 0)) )
+    if( bSkipBufferInitialization )
+    {
+        // Do nothing
+    }
+    else if( nPixelSpace == GDALGetDataTypeSizeBytes(eBufType) &&
+         (!m_bNoDataValueSet || (!CPLIsNan(m_dfNoDataValue) &&
+                                 m_dfNoDataValue == 0)) )
     {
-        if (nLineSpace == nBufXSize * nPixelSpace)
+        if( nLineSpace == nBufXSize * nPixelSpace )
         {
              memset( pData, 0, static_cast<size_t>(nBufYSize * nLineSpace) );
         }
@@ -239,7 +264,7 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             }
         }
     }
-    else if ( !bEqualAreas || m_bNoDataValueSet )
+    else if( m_bNoDataValueSet )
     {
         double dfWriteValue = 0.0;
         if( m_bNoDataValueSet )
@@ -254,10 +279,10 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         }
     }
 
-    m_nRecursionCounter ++;
+    m_nRecursionCounter++;
 
-    GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
-    void             *pProgressDataGlobal = psExtraArg->pProgressData;
+    GDALProgressFunc const pfnProgressGlobal = psExtraArg->pfnProgress;
+    void * const pProgressDataGlobal = psExtraArg->pProgressData;
 
 /* -------------------------------------------------------------------- */
 /*      Overlay each source in turn over top this.                      */
@@ -267,10 +292,10 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     {
         psExtraArg->pfnProgress = GDALScaledProgress;
         psExtraArg->pProgressData =
-                GDALCreateScaledProgress( 1.0 * iSource / nSources,
-                                        1.0 * (iSource + 1) / nSources,
-                                        pfnProgressGlobal,
-                                        pProgressDataGlobal );
+            GDALCreateScaledProgress( 1.0 * iSource / nSources,
+                                      1.0 * (iSource + 1) / nSources,
+                                      pfnProgressGlobal,
+                                      pProgressDataGlobal );
         if( psExtraArg->pProgressData == NULL )
             psExtraArg->pfnProgress = NULL;
 
@@ -286,28 +311,147 @@ CPLErr VRTSourcedRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     psExtraArg->pfnProgress = pfnProgressGlobal;
     psExtraArg->pProgressData = pProgressDataGlobal;
 
-    m_nRecursionCounter --;
+    m_nRecursionCounter--;
 
     return eErr;
 }
 
 /************************************************************************/
+/*                         IGetDataCoverageStatus()                     */
+/************************************************************************/
+
+#ifndef HAVE_GEOS
+int  VRTSourcedRasterBand::IGetDataCoverageStatus( int /* nXOff */,
+                                                   int /* nYOff */,
+                                                   int /* nXSize */,
+                                                   int /* nYSize */,
+                                                   int /* nMaskFlagStop */,
+                                                   double* pdfDataPct)
+{
+    // TODO(rouault): Should this set pdfDataPct?
+    if( pdfDataPct != NULL )
+        *pdfDataPct = -1.0;
+    return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | GDAL_DATA_COVERAGE_STATUS_DATA;
+}
+#else
+int  VRTSourcedRasterBand::IGetDataCoverageStatus( int nXOff,
+                                                   int nYOff,
+                                                   int nXSize,
+                                                   int nYSize,
+                                                   int nMaskFlagStop,
+                                                   double* pdfDataPct)
+{
+    if( pdfDataPct != NULL )
+        *pdfDataPct = -1.0;
+    int nStatus = 0;
+
+    OGRPolygon* poPolyNonCoveredBySources = new OGRPolygon();
+    OGRLinearRing* poLR = new OGRLinearRing();
+    poLR->addPoint( nXOff, nYOff );
+    poLR->addPoint( nXOff, nYOff + nYSize );
+    poLR->addPoint( nXOff + nXSize, nYOff + nYSize );
+    poLR->addPoint( nXOff + nXSize, nYOff );
+    poLR->addPoint( nXOff, nYOff );
+    poPolyNonCoveredBySources->addRingDirectly(poLR);
+
+    for( int iSource = 0; iSource < nSources; iSource++ )
+    {
+        if( !papoSources[iSource]->IsSimpleSource() )
+        {
+            delete poPolyNonCoveredBySources;
+            return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED;
+        }
+        VRTSimpleSource* poSS = reinterpret_cast<VRTSimpleSource*>(papoSources[iSource]);
+        // Check if the AOI is fully inside the source
+        if( nXOff >= poSS->m_dfDstXOff &&
+            nYOff >= poSS->m_dfDstYOff &&
+            nXOff + nXSize <= poSS->m_dfDstXOff + poSS->m_dfDstXSize &&
+            nYOff + nYSize <= poSS->m_dfDstYOff + poSS->m_dfDstYSize )
+        {
+            if( pdfDataPct )
+                *pdfDataPct = 100.0;
+            delete poPolyNonCoveredBySources;
+            return GDAL_DATA_COVERAGE_STATUS_DATA;
+        }
+        // Check intersection of bounding boxes.
+        if( poSS->m_dfDstXOff + poSS->m_dfDstXSize > nXOff &&
+            poSS->m_dfDstYOff + poSS->m_dfDstYSize > nYOff &&
+            poSS->m_dfDstXOff < nXOff + nXSize &&
+            poSS->m_dfDstYOff < nYOff + nYSize )
+        {
+            nStatus |= GDAL_DATA_COVERAGE_STATUS_DATA;
+            if( poPolyNonCoveredBySources != NULL )
+            {
+                OGRPolygon oPolySource;
+                poLR = new OGRLinearRing();
+                poLR->addPoint( poSS->m_dfDstXOff,
+                                poSS->m_dfDstYOff );
+                poLR->addPoint( poSS->m_dfDstXOff,
+                                poSS->m_dfDstYOff + poSS->m_dfDstYSize );
+                poLR->addPoint( poSS->m_dfDstXOff + poSS->m_dfDstXSize,
+                                poSS->m_dfDstYOff + poSS->m_dfDstYSize );
+                poLR->addPoint( poSS->m_dfDstXOff + poSS->m_dfDstXSize,
+                                poSS->m_dfDstYOff );
+                poLR->addPoint( poSS->m_dfDstXOff,
+                                poSS->m_dfDstYOff );
+                oPolySource.addRingDirectly(poLR);
+                OGRGeometry* poRes = poPolyNonCoveredBySources->Difference(&oPolySource);
+                if( poRes != NULL && poRes->IsEmpty() )
+                {
+                    delete poRes;
+                    if( pdfDataPct )
+                        *pdfDataPct = 100.0;
+                    delete poPolyNonCoveredBySources;
+                    return GDAL_DATA_COVERAGE_STATUS_DATA;
+                }
+                else if( poRes != NULL && poRes->getGeometryType() == wkbPolygon )
+                {
+                    delete poPolyNonCoveredBySources;
+                    poPolyNonCoveredBySources = reinterpret_cast<OGRPolygon*>(poRes);
+                }
+                else
+                {
+                    delete poRes;
+                    delete poPolyNonCoveredBySources;
+                    poPolyNonCoveredBySources = NULL;
+                }
+            }
+        }
+        if( nMaskFlagStop != 0 && (nStatus & nMaskFlagStop) != 0 )
+        {
+            delete poPolyNonCoveredBySources;
+            return nStatus;
+        }
+    }
+    if( poPolyNonCoveredBySources != NULL )
+    {
+        if( !poPolyNonCoveredBySources->IsEmpty() )
+            nStatus |= GDAL_DATA_COVERAGE_STATUS_EMPTY;
+        if( pdfDataPct != NULL )
+            *pdfDataPct = 100.0 * (1.0 - poPolyNonCoveredBySources->get_Area() / nXSize / nYSize);
+    }
+    delete poPolyNonCoveredBySources;
+    return nStatus;
+}
+#endif  // HAVE_GEOS
+
+/************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
 CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                   void * pImage )
+                                         void * pImage )
 
 {
-    const int nPixelSize = GDALGetDataTypeSize(eDataType)/8;
+    const int nPixelSize = GDALGetDataTypeSizeBytes(eDataType);
 
-    int nReadXSize;
+    int nReadXSize = 0;
     if( (nBlockXOff+1) * nBlockXSize > GetXSize() )
         nReadXSize = GetXSize() - nBlockXOff * nBlockXSize;
     else
         nReadXSize = nBlockXSize;
 
-    int nReadYSize;
+    int nReadYSize = 0;
     if( (nBlockYOff+1) * nBlockYSize > GetYSize() )
         nReadYSize = GetYSize() - nBlockYOff * nBlockYSize;
     else
@@ -323,62 +467,63 @@ CPLErr VRTSourcedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                       nPixelSize, nPixelSize * nBlockXSize, &sExtraArg );
 }
 
-
 /************************************************************************/
 /*                    CanUseSourcesMinMaxImplementations()              */
 /************************************************************************/
 
-int VRTSourcedRasterBand::CanUseSourcesMinMaxImplementations()
+bool VRTSourcedRasterBand::CanUseSourcesMinMaxImplementations()
 {
-    const char* pszUseSources = CPLGetConfigOption("VRT_MIN_MAX_FROM_SOURCES", NULL);
+    const char* pszUseSources =
+        CPLGetConfigOption("VRT_MIN_MAX_FROM_SOURCES", NULL);
     if( pszUseSources )
         return CPLTestBool(pszUseSources);
 
-    // Use heuristics to determine if we are going to use the source GetMinimum()
-    // or GetMaximum() implementation: all the sources must be "simple" sources
-    // with a dataset description that match a "regular" file on the filesystem,
-    // whose open time and GetMinimum()/GetMaximum() implementations we hope to
-    // be fast enough.
-    // In case of doubt return FALSE
+    // Use heuristics to determine if we are going to use the source
+    // GetMinimum() or GetMaximum() implementation: all the sources must be
+    // "simple" sources with a dataset description that match a "regular" file
+    // on the filesystem, whose open time and GetMinimum()/GetMaximum()
+    // implementations we hope to be fast enough.
+    // In case of doubt return FALSE.
     for( int iSource = 0; iSource < nSources; iSource++ )
     {
         if( !(papoSources[iSource]->IsSimpleSource()) )
-            return FALSE;
-        VRTSimpleSource* poSimpleSource
+            return false;
+        VRTSimpleSource * const poSimpleSource
             = reinterpret_cast<VRTSimpleSource *>( papoSources[iSource] );
         GDALRasterBand* poBand = poSimpleSource->GetBand();
         if( poBand == NULL )
-            return FALSE;
+            return false;
         if( poBand->GetDataset() == NULL )
-            return FALSE;
+            return false;
         const char* pszFilename = poBand->GetDataset()->GetDescription();
         if( pszFilename == NULL )
-            return FALSE;
-        /* /vsimem/ should be fast */
+            return false;
+        // /vsimem/ should be fast.
         if( STARTS_WITH(pszFilename, "/vsimem/") )
             continue;
-        /* but not other /vsi filesystems */
+        // but not other /vsi filesystems
         if( STARTS_WITH(pszFilename, "/vsi") )
-            return FALSE;
-        char ch;
-        /* We will assume that filenames that are only with ascii characters */
-        /* are real filenames and so we will not try to 'stat' them */
+            return false;
+        char ch = '\0';
+        // We will assume that filenames that are only with ascii characters
+        // are real filenames and so we will not try to 'stat' them.
         for( int i = 0; (ch = pszFilename[i]) != '\0'; i++ )
         {
             if( !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
-                  (ch >= '0' && ch <= '9') || ch == ':' || ch == '/' || ch == '\\' ||
+                  (ch >= '0' && ch <= '9') || ch == ':' ||
+                  ch == '/' || ch == '\\' ||
                   ch == ' ' || ch == '.') )
                 break;
         }
         if( ch != '\0' )
         {
-            /* Otherwise do a real filesystem check */
+            // Otherwise do a real filesystem check.
             VSIStatBuf sStat;
             if( VSIStat(pszFilename, &sStat) != 0 )
-                return FALSE;
+                return false;
         }
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -390,7 +535,7 @@ double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
     if( !CanUseSourcesMinMaxImplementations() )
         return GDALRasterBand::GetMinimum(pbSuccess);
 
-    const char *pszValue = GetMetadataItem("STATISTICS_MINIMUM");
+    const char * const pszValue = GetMetadataItem("STATISTICS_MINIMUM");
     if( pszValue != NULL )
     {
         if( pbSuccess != NULL )
@@ -399,11 +544,13 @@ double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
         return CPLAtofM(pszValue);
     }
 
-    if ( m_nRecursionCounter > 0 )
+    if( m_nRecursionCounter > 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "VRTSourcedRasterBand::GetMinimum() called recursively on the same band. "
-                  "It looks like the VRT is referencing itself." );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "VRTSourcedRasterBand::GetMinimum() called "
+            "recursively on the same band. "
+            "It looks like the VRT is referencing itself." );
         if( pbSuccess != NULL )
             *pbSuccess = FALSE;
         return 0.0;
@@ -417,14 +564,14 @@ double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
         double dfSourceMin
             = papoSources[iSource]->GetMinimum(GetXSize(), GetYSize(),
                                                &bSuccess);
-        if (!bSuccess)
+        if( !bSuccess )
         {
             dfMin = GDALRasterBand::GetMinimum(pbSuccess);
             m_nRecursionCounter --;
             return dfMin;
         }
 
-        if (iSource == 0 || dfSourceMin < dfMin)
+        if( iSource == 0 || dfSourceMin < dfMin )
             dfMin = dfSourceMin;
     }
 
@@ -440,12 +587,12 @@ double VRTSourcedRasterBand::GetMinimum( int *pbSuccess )
 /*                             GetMaximum()                             */
 /************************************************************************/
 
-double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
+double VRTSourcedRasterBand::GetMaximum( int *pbSuccess )
 {
     if( !CanUseSourcesMinMaxImplementations() )
         return GDALRasterBand::GetMaximum(pbSuccess);
 
-    const char *pszValue = GetMetadataItem("STATISTICS_MAXIMUM");
+    const char * const pszValue = GetMetadataItem("STATISTICS_MAXIMUM");
     if( pszValue != NULL )
     {
         if( pbSuccess != NULL )
@@ -454,10 +601,11 @@ double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
         return CPLAtofM(pszValue);
     }
 
-    if ( m_nRecursionCounter > 0 )
+    if( m_nRecursionCounter > 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "VRTSourcedRasterBand::GetMaximum() called recursively on the same band. "
+                  "VRTSourcedRasterBand::GetMaximum() called "
+                  "recursively on the same band. "
                   "It looks like the VRT is referencing itself." );
         if( pbSuccess != NULL )
             *pbSuccess = FALSE;
@@ -469,19 +617,21 @@ double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
     for( int iSource = 0; iSource < nSources; iSource++ )
     {
         int bSuccess = FALSE;
-        double dfSourceMax = papoSources[iSource]->GetMaximum(GetXSize(), GetYSize(), &bSuccess);
-        if (!bSuccess)
+        const double dfSourceMax =
+            papoSources[iSource]->GetMaximum( GetXSize(), GetYSize(),
+                                              &bSuccess );
+        if( !bSuccess )
         {
             dfMax = GDALRasterBand::GetMaximum(pbSuccess);
-            m_nRecursionCounter --;
+            m_nRecursionCounter--;
             return dfMax;
         }
 
-        if (iSource == 0 || dfSourceMax > dfMax)
+        if( iSource == 0 || dfSourceMax > dfMax )
             dfMax = dfSourceMax;
     }
 
-    m_nRecursionCounter --;
+    m_nRecursionCounter--;
 
     if( pbSuccess != NULL )
         *pbSuccess = TRUE;
@@ -495,18 +645,16 @@ double VRTSourcedRasterBand::GetMaximum(int *pbSuccess )
 
 CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinMax )
 {
-    double  dfMin = 0.0;
-    double  dfMax = 0.0;
-
 /* -------------------------------------------------------------------- */
 /*      Does the driver already know the min/max?                       */
 /* -------------------------------------------------------------------- */
     if( bApproxOK )
     {
-        int          bSuccessMin, bSuccessMax;
+        int bSuccessMin = FALSE;
+        int bSuccessMax = FALSE;
 
-        dfMin = GetMinimum( &bSuccessMin );
-        dfMax = GetMaximum( &bSuccessMax );
+        const double dfMin = GetMinimum( &bSuccessMin );
+        const double dfMax = GetMaximum( &bSuccessMax );
 
         if( bSuccessMin && bSuccessMax )
         {
@@ -519,23 +667,25 @@ CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinM
 /* -------------------------------------------------------------------- */
 /*      If we have overview bands, use them for min/max.                */
 /* -------------------------------------------------------------------- */
-    if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
+    if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     {
-        GDALRasterBand *poBand
+        GDALRasterBand * const poBand
             = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
 
-        if ( poBand != this )
+        if( poBand != this )
             return poBand->ComputeRasterMinMax( TRUE, adfMinMax );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Try with source bands.                                          */
 /* -------------------------------------------------------------------- */
-    if ( m_nRecursionCounter > 0 )
+    if( m_nRecursionCounter > 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "VRTSourcedRasterBand::ComputeRasterMinMax() called recursively on the same band. "
-                  "It looks like the VRT is referencing itself." );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "VRTSourcedRasterBand::ComputeRasterMinMax() called "
+            "recursively on the same band. "
+            "It looks like the VRT is referencing itself." );
         return CE_Failure;
     }
     m_nRecursionCounter ++;
@@ -544,22 +694,25 @@ CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinM
     adfMinMax[1] = 0.0;
     for( int iSource = 0; iSource < nSources; iSource++ )
     {
-        double adfSourceMinMax[2];
-        CPLErr eErr = papoSources[iSource]->ComputeRasterMinMax(GetXSize(), GetYSize(), bApproxOK, adfSourceMinMax);
-        if (eErr != CE_None)
+        double adfSourceMinMax[2] = { 0.0, 0.0 };
+        const CPLErr eErr =
+            papoSources[iSource]->ComputeRasterMinMax(
+                GetXSize(), GetYSize(), bApproxOK, adfSourceMinMax );
+        if( eErr != CE_None )
         {
-            eErr = GDALRasterBand::ComputeRasterMinMax(bApproxOK, adfMinMax);
+            const CPLErr eErr2 =
+                GDALRasterBand::ComputeRasterMinMax( bApproxOK, adfMinMax );
             m_nRecursionCounter --;
-            return eErr;
+            return eErr2;
         }
 
-        if (iSource == 0 || adfSourceMinMax[0] < adfMinMax[0])
+        if( iSource == 0 || adfSourceMinMax[0] < adfMinMax[0] )
             adfMinMax[0] = adfSourceMinMax[0];
-        if (iSource == 0 || adfSourceMinMax[1] > adfMinMax[1])
+        if( iSource == 0 || adfSourceMinMax[1] > adfMinMax[1] )
             adfMinMax[1] = adfSourceMinMax[1];
     }
 
-    m_nRecursionCounter --;
+    m_nRecursionCounter--;
 
     return CE_None;
 }
@@ -570,10 +723,10 @@ CPLErr VRTSourcedRasterBand::ComputeRasterMinMax( int bApproxOK, double* adfMinM
 
 CPLErr
 VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
-                                   double *pdfMin, double *pdfMax,
-                                   double *pdfMean, double *pdfStdDev,
-                                   GDALProgressFunc pfnProgress,
-                                   void *pProgressData )
+                                         double *pdfMin, double *pdfMax,
+                                         double *pdfMean, double *pdfStdDev,
+                                         GDALProgressFunc pfnProgress,
+                                         void *pProgressData )
 
 {
     if( nSources != 1 || m_bNoDataValueSet )
@@ -590,7 +743,7 @@ VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
 /* -------------------------------------------------------------------- */
     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     {
-        GDALRasterBand *poBand
+        GDALRasterBand * const poBand
             = GetRasterSampleOverview( GDALSTAT_APPROX_NUMSAMPLES );
 
         if( poBand != this )
@@ -603,29 +756,36 @@ VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
 /* -------------------------------------------------------------------- */
 /*      Try with source bands.                                          */
 /* -------------------------------------------------------------------- */
-    if ( m_nRecursionCounter > 0 )
+    if( m_nRecursionCounter > 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "VRTSourcedRasterBand::ComputeStatistics() called recursively on the same band. "
-                  "It looks like the VRT is referencing itself." );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "VRTSourcedRasterBand::ComputeStatistics() called "
+            "recursively on the same band. "
+            "It looks like the VRT is referencing itself." );
         return CE_Failure;
     }
     m_nRecursionCounter ++;
 
-    double dfMin = 0.0, dfMax = 0.0, dfMean = 0.0, dfStdDev = 0.0;
+    double dfMin = 0.0;
+    double dfMax = 0.0;
+    double dfMean = 0.0;
+    double dfStdDev = 0.0;
 
-    CPLErr eErr = papoSources[0]->ComputeStatistics(GetXSize(), GetYSize(), bApproxOK,
-                                                    &dfMin, &dfMax,
-                                                    &dfMean, &dfStdDev,
-                                                    pfnProgress, pProgressData);
-    if (eErr != CE_None)
+    const CPLErr eErr =
+        papoSources[0]->ComputeStatistics( GetXSize(), GetYSize(), bApproxOK,
+                                           &dfMin, &dfMax,
+                                           &dfMean, &dfStdDev,
+                                           pfnProgress, pProgressData );
+    if( eErr != CE_None )
     {
-        eErr = GDALRasterBand::ComputeStatistics(bApproxOK,
-                                                 pdfMin, pdfMax,
-                                                 pdfMean, pdfStdDev,
-                                                 pfnProgress, pProgressData);
+        const CPLErr eErr2 =
+            GDALRasterBand::ComputeStatistics( bApproxOK,
+                                               pdfMin, pdfMax,
+                                               pdfMean, pdfStdDev,
+                                               pfnProgress, pProgressData );
         m_nRecursionCounter --;
-        return eErr;
+        return eErr2;
     }
 
     m_nRecursionCounter --;
@@ -654,10 +814,10 @@ VRTSourcedRasterBand::ComputeStatistics( int bApproxOK,
 /************************************************************************/
 
 CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax,
-                                     int nBuckets, GUIntBig *panHistogram,
-                                     int bIncludeOutOfRange, int bApproxOK,
-                                     GDALProgressFunc pfnProgress,
-                                     void *pProgressData )
+                                           int nBuckets, GUIntBig *panHistogram,
+                                           int bIncludeOutOfRange, int bApproxOK,
+                                           GDALProgressFunc pfnProgress,
+                                           void *pProgressData )
 
 {
     if( nSources != 1 )
@@ -674,7 +834,7 @@ CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
     if( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     {
-        // FIXME: should we use the most reduced overview here or use some
+        // FIXME: Should we use the most reduced overview here or use some
         // minimum number of samples like GDALRasterBand::ComputeStatistics()
         // does?
         GDALRasterBand *poBestOverview = GetRasterSampleOverview( 0 );
@@ -691,30 +851,34 @@ CPLErr VRTSourcedRasterBand::GetHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
 /*      Try with source bands.                                          */
 /* -------------------------------------------------------------------- */
-    if ( m_nRecursionCounter > 0 )
+    if( m_nRecursionCounter > 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "VRTSourcedRasterBand::GetHistogram() called recursively on the same band. "
-                  "It looks like the VRT is referencing itself." );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "VRTSourcedRasterBand::GetHistogram() called recursively on the "
+            "same band. It looks like the VRT is referencing itself." );
         return CE_Failure;
     }
     m_nRecursionCounter ++;
 
-    CPLErr eErr = papoSources[0]->GetHistogram(GetXSize(), GetYSize(), dfMin, dfMax, nBuckets,
-                                               panHistogram,
-                                               bIncludeOutOfRange, bApproxOK,
-                                               pfnProgress, pProgressData);
-    if (eErr != CE_None)
+    const CPLErr eErr =
+        papoSources[0]->GetHistogram( GetXSize(), GetYSize(), dfMin, dfMax,
+                                      nBuckets,
+                                      panHistogram,
+                                      bIncludeOutOfRange, bApproxOK,
+                                      pfnProgress, pProgressData );
+    if( eErr != CE_None )
     {
-        eErr = GDALRasterBand::GetHistogram( dfMin, dfMax,
-                                                  nBuckets, panHistogram,
-                                                  bIncludeOutOfRange, bApproxOK,
-                                                  pfnProgress, pProgressData );
+        const CPLErr eErr2 =
+            GDALRasterBand::GetHistogram( dfMin, dfMax,
+                                          nBuckets, panHistogram,
+                                          bIncludeOutOfRange, bApproxOK,
+                                          pfnProgress, pProgressData );
         m_nRecursionCounter --;
-        return eErr;
+        return eErr2;
     }
 
-    m_nRecursionCounter --;
+    m_nRecursionCounter--;
 
     SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogram );
 
@@ -730,22 +894,29 @@ CPLErr VRTSourcedRasterBand::AddSource( VRTSource *poNewSource )
 {
     nSources++;
 
-    papoSources = reinterpret_cast<VRTSource **>(
-        CPLRealloc(papoSources, sizeof(void*) * nSources) );
+    papoSources = static_cast<VRTSource **>(
+        CPLRealloc( papoSources, sizeof(void*) * nSources ) );
     papoSources[nSources-1] = poNewSource;
 
     reinterpret_cast<VRTDataset *>( poDS )->SetNeedsFlush();
 
-    if( poNewSource->IsSimpleSource() &&
-        GetMetadataItem("NBITS", "IMAGE_STRUCTURE") != NULL)
+    if( poNewSource->IsSimpleSource() )
     {
-        reinterpret_cast<VRTSimpleSource*>( poNewSource )->SetMaxValue(
-                (1 << atoi(GetMetadataItem("NBITS", "IMAGE_STRUCTURE")))-1);
+        VRTSimpleSource* poSS = reinterpret_cast<VRTSimpleSource*>( poNewSource );
+        if( GetMetadataItem("NBITS", "IMAGE_STRUCTURE") != NULL)
+        {
+            poSS->SetMaxValue(
+                    (1 << atoi(GetMetadataItem("NBITS", "IMAGE_STRUCTURE")))-1);
+        }
+
+        CheckSource( poSS );
     }
 
     return CE_None;
 }
 
+/*! @endcond */
+
 /************************************************************************/
 /*                              VRTAddSource()                          */
 /************************************************************************/
@@ -763,6 +934,8 @@ CPLErr CPL_STDCALL VRTAddSource( VRTSourcedRasterBandH hVRTBand,
         AddSource( reinterpret_cast<VRTSource *>( hNewSource ) );
 }
 
+/*! @cond Doxygen_Suppress */
+
 /************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
@@ -771,27 +944,16 @@ CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
                                       const char *pszVRTPath )
 
 {
-    CPLErr eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
-    if( eErr != CE_None )
-        return eErr;
-
-/* -------------------------------------------------------------------- */
-/*      Validate a bit.                                                 */
-/* -------------------------------------------------------------------- */
-    if( psTree == NULL || psTree->eType != CXT_Element
-        || (!EQUAL(psTree->pszValue,"VRTSourcedRasterBand")
-            && !EQUAL(psTree->pszValue,"VRTRasterBand")
-	    && !EQUAL(psTree->pszValue,"VRTDerivedRasterBand")) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Invalid node passed to VRTSourcedRasterBand::XMLInit()." );
-        return CE_Failure;
+        const CPLErr eErr = VRTRasterBand::XMLInit( psTree, pszVRTPath );
+        if( eErr != CE_None )
+            return eErr;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Process sources.                                                */
 /* -------------------------------------------------------------------- */
-    VRTDriver *poDriver = reinterpret_cast<VRTDriver *>(
+    VRTDriver * const poDriver = reinterpret_cast<VRTDriver *>(
         GDALGetDriverByName( "VRT" ) );
 
     for( CPLXMLNode *psChild = psTree->psChild;
@@ -802,7 +964,8 @@ CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
             continue;
 
         CPLErrorReset();
-        VRTSource *poSource = poDriver->ParseSource( psChild, pszVRTPath );
+        VRTSource * const poSource =
+            poDriver->ParseSource( psChild, pszVRTPath );
         if( poSource != NULL )
             AddSource( poSource );
         else if( CPLGetLastErrorType() != CE_None )
@@ -812,9 +975,11 @@ CPLErr VRTSourcedRasterBand::XMLInit( CPLXMLNode * psTree,
 /* -------------------------------------------------------------------- */
 /*      Done.                                                           */
 /* -------------------------------------------------------------------- */
-    if( nSources == 0 )
-        CPLDebug( "VRT", "No valid sources found for band in VRT file:\n%s",
-                  pszVRTPath ? pszVRTPath : "(null)" );
+    const char* pszSubclass = CPLGetXMLValue( psTree, "subclass",
+                                              "VRTSourcedRasterBand" );
+    if( nSources == 0 && !EQUAL(pszSubclass,"VRTDerivedRasterBand") )
+        CPLDebug( "VRT", "No valid sources found for band in VRT file %s",
+                  GetDataset() ? GetDataset()->GetDescription() : "" );
 
     return CE_None;
 }
@@ -836,7 +1001,7 @@ CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
     for( int iSource = 0; iSource < nSources; iSource++ )
     {
-        CPLXMLNode *psXMLSrc
+        CPLXMLNode * const psXMLSrc
             = papoSources[iSource]->SerializeToXML( pszVRTPath );
 
         if( psXMLSrc != NULL )
@@ -853,16 +1018,42 @@ CPLXMLNode *VRTSourcedRasterBand::SerializeToXML( const char *pszVRTPath )
 }
 
 /************************************************************************/
+/*                            CheckSource()                             */
+/************************************************************************/
+
+void VRTSourcedRasterBand::CheckSource( VRTSimpleSource *poSS )
+{
+/* -------------------------------------------------------------------- */
+/*      Check if we can avoid buffer initialization.                    */
+/* -------------------------------------------------------------------- */
+
+    // Note: if one day we do alpha compositing, we will need to check that.
+    if( strcmp(poSS->GetType(), "SimpleSource") == 0 &&
+        poSS->m_dfSrcXOff >= 0.0 &&
+        poSS->m_dfSrcYOff >= 0.0 &&
+        poSS->m_dfSrcXOff + poSS->m_dfSrcXSize <= poSS->m_poRasterBand->GetXSize() &&
+        poSS->m_dfSrcYOff + poSS->m_dfSrcYSize <= poSS->m_poRasterBand->GetYSize() &&
+        poSS->m_dfDstXOff <= 0.0 &&
+        poSS->m_dfDstYOff <= 0.0 &&
+        poSS->m_dfDstXOff + poSS->m_dfDstXSize >= nRasterXSize &&
+        poSS->m_dfDstYOff + poSS->m_dfDstYSize >= nRasterYSize )
+    {
+        bSkipBufferInitialization = TRUE;
+    }
+}
+
+/************************************************************************/
 /*                          ConfigureSource()                           */
 /************************************************************************/
 
-void VRTSourcedRasterBand::ConfigureSource(VRTSimpleSource *poSimpleSource,
-                                           GDALRasterBand *poSrcBand,
-                                           int bAddAsMaskBand,
-                                           double dfSrcXOff, double dfSrcYOff,
-                                           double dfSrcXSize, double dfSrcYSize,
-                                           double dfDstXOff, double dfDstYOff,
-                                           double dfDstXSize, double dfDstYSize)
+void VRTSourcedRasterBand::ConfigureSource( VRTSimpleSource *poSimpleSource,
+                                            GDALRasterBand *poSrcBand,
+                                            int bAddAsMaskBand,
+                                            double dfSrcXOff, double dfSrcYOff,
+                                            double dfSrcXSize, double dfSrcYSize,
+                                            double dfDstXOff, double dfDstYOff,
+                                            double dfDstXSize,
+                                            double dfDstYSize )
 {
 /* -------------------------------------------------------------------- */
 /*      Default source and dest rectangles.                             */
@@ -887,41 +1078,39 @@ void VRTSourcedRasterBand::ConfigureSource(VRTSimpleSource *poSimpleSource,
         poSimpleSource->SetSrcMaskBand( poSrcBand );
     else
         poSimpleSource->SetSrcBand( poSrcBand );
-    poSimpleSource->SetSrcWindow( dfSrcXOff, dfSrcYOff, dfSrcXSize, dfSrcYSize );
-    poSimpleSource->SetDstWindow( dfDstXOff, dfDstYOff, dfDstXSize, dfDstYSize );
 
-/* -------------------------------------------------------------------- */
-/*      Default source and dest rectangles.                             */
-/* -------------------------------------------------------------------- */
-    if ( dfSrcXOff == dfDstXOff && dfSrcYOff == dfDstYOff &&
-         dfSrcXSize == dfDstXSize && dfSrcYSize == nRasterYSize )
-        bEqualAreas = TRUE;
+    poSimpleSource->SetSrcWindow( dfSrcXOff, dfSrcYOff,
+                                  dfSrcXSize, dfSrcYSize );
+    poSimpleSource->SetDstWindow( dfDstXOff, dfDstYOff,
+                                  dfDstXSize, dfDstYSize );
+
+    CheckSource( poSimpleSource );
 
 /* -------------------------------------------------------------------- */
 /*      If we can get the associated GDALDataset, add a reference to it.*/
 /* -------------------------------------------------------------------- */
     if( poSrcBand->GetDataset() != NULL )
         poSrcBand->GetDataset()->Reference();
-
 }
 
 /************************************************************************/
 /*                          AddSimpleSource()                           */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
-                                       double dfSrcXOff, double dfSrcYOff,
-                                       double dfSrcXSize, double dfSrcYSize,
-                                       double dfDstXOff, double dfDstYOff,
-                                       double dfDstXSize, double dfDstYSize,
-                                       const char *pszResampling,
-                                       double dfNoDataValueIn )
+CPLErr VRTSourcedRasterBand::AddSimpleSource(
+    GDALRasterBand *poSrcBand,
+    double dfSrcXOff, double dfSrcYOff,
+    double dfSrcXSize, double dfSrcYSize,
+    double dfDstXOff, double dfDstYOff,
+    double dfDstXSize, double dfDstYSize,
+    const char *pszResampling,
+    double dfNoDataValueIn )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Create source.                                                  */
 /* -------------------------------------------------------------------- */
-    VRTSimpleSource *poSimpleSource;
+    VRTSimpleSource *poSimpleSource = NULL;
 
     if( pszResampling != NULL && STARTS_WITH_CI(pszResampling, "aver") )
         poSimpleSource = new VRTAveragedSource();
@@ -931,17 +1120,17 @@ CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
         if( dfNoDataValueIn != VRT_NODATA_UNSET )
             CPLError(
                 CE_Warning, CPLE_AppDefined,
-                "NODATA setting not currently supported for nearest\n"
+                "NODATA setting not currently supported for nearest  "
                 "neighbour sampled simple sources on Virtual Datasources." );
     }
 
-    ConfigureSource(poSimpleSource,
-                    poSrcBand,
-                    FALSE,
-                    dfSrcXOff, dfSrcYOff,
-                    dfSrcXSize, dfSrcYSize,
-                    dfDstXOff, dfDstYOff,
-                    dfDstXSize, dfDstYSize);
+    ConfigureSource( poSimpleSource,
+                     poSrcBand,
+                     FALSE,
+                     dfSrcXOff, dfSrcYOff,
+                     dfSrcXSize, dfSrcYSize,
+                     dfDstXOff, dfDstYOff,
+                     dfDstXSize, dfDstYSize );
 
     if( dfNoDataValueIn != VRT_NODATA_UNSET )
         poSimpleSource->SetNoDataValue( dfNoDataValueIn );
@@ -956,12 +1145,14 @@ CPLErr VRTSourcedRasterBand::AddSimpleSource( GDALRasterBand *poSrcBand,
 /*                         AddMaskBandSource()                          */
 /************************************************************************/
 
-/* poSrcBand is not the mask band, but the band from which the mask band is taken */
-CPLErr VRTSourcedRasterBand::AddMaskBandSource( GDALRasterBand *poSrcBand,
-                                                double dfSrcXOff, double dfSrcYOff,
-                                                double dfSrcXSize, double dfSrcYSize,
-                                                double dfDstXOff, double dfDstYOff,
-                                                double dfDstXSize, double dfDstYSize )
+// poSrcBand is not the mask band, but the band from which the mask band is
+// taken.
+CPLErr VRTSourcedRasterBand::AddMaskBandSource(
+    GDALRasterBand *poSrcBand,
+    double dfSrcXOff, double dfSrcYOff,
+    double dfSrcXSize, double dfSrcYSize,
+    double dfDstXOff, double dfDstYOff,
+    double dfDstXSize, double dfDstYSize )
 {
 /* -------------------------------------------------------------------- */
 /*      Create source.                                                  */
@@ -982,6 +1173,8 @@ CPLErr VRTSourcedRasterBand::AddMaskBandSource( GDALRasterBand *poSrcBand,
     return AddSource( poSimpleSource );
 }
 
+/*! @endcond */
+
 /************************************************************************/
 /*                         VRTAddSimpleSource()                         */
 /************************************************************************/
@@ -1011,33 +1204,36 @@ CPLErr CPL_STDCALL VRTAddSimpleSource( VRTSourcedRasterBandH hVRTBand,
             pszResampling, dfNoDataValue );
 }
 
+/*! @cond Doxygen_Suppress */
+
 /************************************************************************/
 /*                          AddComplexSource()                          */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand,
-                                               double dfSrcXOff, double dfSrcYOff,
-                                               double dfSrcXSize, double dfSrcYSize,
-                                               double dfDstXOff, double dfDstYOff,
-                                               double dfDstXSize, double dfDstYSize,
-                                               double dfScaleOff,
-                                               double dfScaleRatio,
-                                               double dfNoDataValueIn,
-                                               int nColorTableComponent)
+CPLErr VRTSourcedRasterBand::AddComplexSource(
+    GDALRasterBand *poSrcBand,
+    double dfSrcXOff, double dfSrcYOff,
+    double dfSrcXSize, double dfSrcYSize,
+    double dfDstXOff, double dfDstYOff,
+    double dfDstXSize, double dfDstYSize,
+    double dfScaleOff,
+    double dfScaleRatio,
+    double dfNoDataValueIn,
+    int nColorTableComponent )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Create source.                                                  */
 /* -------------------------------------------------------------------- */
-    VRTComplexSource *poSource = new VRTComplexSource();
+    VRTComplexSource * const poSource = new VRTComplexSource();
 
-    ConfigureSource(poSource,
-                    poSrcBand,
-                    FALSE,
-                    dfSrcXOff, dfSrcYOff,
-                    dfSrcXSize, dfSrcYSize,
-                    dfDstXOff, dfDstYOff,
-                    dfDstXSize, dfDstYSize);
+    ConfigureSource( poSource,
+                     poSrcBand,
+                     FALSE,
+                     dfSrcXOff, dfSrcYOff,
+                     dfSrcXSize, dfSrcYSize,
+                     dfDstXOff, dfDstYOff,
+                     dfDstXSize, dfDstYSize );
 
 /* -------------------------------------------------------------------- */
 /*      Set complex parameters.                                         */
@@ -1056,6 +1252,8 @@ CPLErr VRTSourcedRasterBand::AddComplexSource( GDALRasterBand *poSrcBand,
     return AddSource( poSource );
 }
 
+/*! @endcond */
+
 /************************************************************************/
 /*                         VRTAddComplexSource()                        */
 /************************************************************************/
@@ -1087,18 +1285,20 @@ CPLErr CPL_STDCALL VRTAddComplexSource( VRTSourcedRasterBandH hVRTBand,
             dfNoDataValue );
 }
 
+/*! @cond Doxygen_Suppress */
+
 /************************************************************************/
 /*                           AddFuncSource()                            */
 /************************************************************************/
 
-CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc,
-                                     void *pCBData, double dfNoDataValueIn )
+CPLErr VRTSourcedRasterBand::AddFuncSource(
+    VRTImageReadFunc pfnReadFunc, void *pCBData, double dfNoDataValueIn )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Create source.                                                  */
 /* -------------------------------------------------------------------- */
-    VRTFuncSource *poFuncSource = new VRTFuncSource;
+    VRTFuncSource * const poFuncSource = new VRTFuncSource;
 
     poFuncSource->fNoDataValue = static_cast<float>( dfNoDataValueIn );
     poFuncSource->pfnReadFunc = pfnReadFunc;
@@ -1111,6 +1311,8 @@ CPLErr VRTSourcedRasterBand::AddFuncSource( VRTImageReadFunc pfnReadFunc,
     return AddSource( poFuncSource );
 }
 
+/*! @endcond */
+
 /************************************************************************/
 /*                          VRTAddFuncSource()                          */
 /************************************************************************/
@@ -1129,6 +1331,7 @@ CPLErr CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH hVRTBand,
         AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
 }
 
+/*! @cond Doxygen_Suppress */
 
 /************************************************************************/
 /*                      GetMetadataDomainList()                         */
@@ -1136,10 +1339,11 @@ CPLErr CPL_STDCALL VRTAddFuncSource( VRTSourcedRasterBandH hVRTBand,
 
 char **VRTSourcedRasterBand::GetMetadataDomainList()
 {
-    return CSLAddString(GDALRasterBand::GetMetadataDomainList(), "LocationInfo");
+    return
+        CSLAddString( GDALRasterBand::GetMetadataDomainList(),
+                      "LocationInfo" );
 }
 
-
 /************************************************************************/
 /*                          GetMetadataItem()                           */
 /************************************************************************/
@@ -1153,22 +1357,25 @@ const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
 /* ==================================================================== */
     if( pszDomain != NULL
         && EQUAL(pszDomain,"LocationInfo")
-        && (STARTS_WITH_CI(pszName, "Pixel_") || STARTS_WITH_CI(pszName, "GeoPixel_")) )
+        && (STARTS_WITH_CI(pszName, "Pixel_") ||
+            STARTS_WITH_CI(pszName, "GeoPixel_")) )
     {
 /* -------------------------------------------------------------------- */
 /*      What pixel are we aiming at?                                    */
 /* -------------------------------------------------------------------- */
-        int iPixel, iLine;
+        int iPixel = 0;
+        int iLine = 0;
 
         if( STARTS_WITH_CI(pszName, "Pixel_") )
         {
+            // TODO(schwehr): Replace sscanf.
             if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
                 return NULL;
         }
         else if( STARTS_WITH_CI(pszName, "GeoPixel_") )
         {
             const double dfGeoX = CPLAtof(pszName + 9);
-            const char* pszUnderscore = strchr(pszName + 9, '_');
+            const char * const pszUnderscore = strchr(pszName + 9, '_');
             if( !pszUnderscore )
                 return NULL;
             const double dfGeoY = CPLAtof(pszUnderscore + 1);
@@ -1176,11 +1383,11 @@ const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
             if( GetDataset() == NULL )
                 return NULL;
 
-            double adfGeoTransform[6];
+            double adfGeoTransform[6] = { 0.0 };
             if( GetDataset()->GetGeoTransform( adfGeoTransform ) != CE_None )
                 return NULL;
 
-            double adfInvGeoTransform[6];
+            double adfInvGeoTransform[6] = { 0.0 };
             if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
                 return NULL;
 
@@ -1194,7 +1401,9 @@ const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
                 + adfInvGeoTransform[5] * dfGeoY ) );
         }
         else
+        {
             return NULL;
+        }
 
         if( iPixel < 0 || iLine < 0
             || iPixel >= GetXSize()
@@ -1205,32 +1414,42 @@ const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
 /*      Find the file(s) at this location.                              */
 /* -------------------------------------------------------------------- */
         char **papszFileList = NULL;
-        int nListSize = 0;
-        CPLHashSet* hSetFiles = CPLHashSetNew(CPLHashSetHashStr,
-                                              CPLHashSetEqualStr,
-                                              NULL);
+        int nListSize = 0; // keep it in this scope
+        int nListMaxSize = 0; // keep it in this scope
+        CPLHashSet * const hSetFiles = CPLHashSetNew( CPLHashSetHashStr,
+                                                      CPLHashSetEqualStr,
+                                                      NULL );
 
         for( int iSource = 0; iSource < nSources; iSource++ )
         {
-            if (!papoSources[iSource]->IsSimpleSource())
+            if( !papoSources[iSource]->IsSimpleSource() )
                 continue;
 
-            VRTSimpleSource *poSrc
+            VRTSimpleSource * const poSrc
                 = reinterpret_cast<VRTSimpleSource *>( papoSources[iSource] );
 
-            double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-            int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
-            int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+            double dfReqXOff = 0.0;
+            double dfReqYOff = 0.0;
+            double dfReqXSize = 0.0;
+            double dfReqYSize = 0.0;
+            int nReqXOff = 0;
+            int nReqYOff = 0;
+            int nReqXSize = 0;
+            int nReqYSize = 0;
+            int nOutXOff = 0;
+            int nOutYOff = 0;
+            int nOutXSize = 0;
+            int nOutYSize = 0;
 
             if( !poSrc->GetSrcDstWindow( iPixel, iLine, 1, 1, 1, 1,
-                                         &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
+                                         &dfReqXOff, &dfReqYOff,
+                                         &dfReqXSize, &dfReqYSize,
                                          &nReqXOff, &nReqYOff,
                                          &nReqXSize, &nReqYSize,
                                          &nOutXOff, &nOutYOff,
                                          &nOutXSize, &nOutYSize ) )
                 continue;
 
-            int nListMaxSize = 0;
             poSrc->GetFileList( &papszFileList, &nListSize, &nListMaxSize,
                                 hSetFiles );
         }
@@ -1242,7 +1461,8 @@ const char *VRTSourcedRasterBand::GetMetadataItem( const char * pszName,
         for( int i = 0; i < nListSize; i++ )
         {
             m_osLastLocationInfo += "<File>";
-            char* pszXMLEscaped = CPLEscapeString(papszFileList[i], -1, CPLES_XML);
+            char * const pszXMLEscaped = CPLEscapeString( papszFileList[i], -1,
+                                                          CPLES_XML );
             m_osLastLocationInfo += pszXMLEscaped;
             CPLFree(pszXMLEscaped);
             m_osLastLocationInfo += "</File>";
@@ -1282,11 +1502,12 @@ char **VRTSourcedRasterBand::GetMetadata( const char *pszDomain )
 /* -------------------------------------------------------------------- */
         for( int iSource = 0; iSource < nSources; iSource++ )
         {
-            CPLXMLNode *psXMLSrc = papoSources[iSource]->SerializeToXML( NULL );
+            CPLXMLNode * const psXMLSrc =
+                papoSources[iSource]->SerializeToXML( NULL );
             if( psXMLSrc == NULL )
                 continue;
 
-            char *pszXML = CPLSerializeXMLTree( psXMLSrc );
+            char * const pszXML = CPLSerializeXMLTree( psXMLSrc );
 
             m_papszSourceList =
                 CSLSetNameValue( m_papszSourceList,
@@ -1314,20 +1535,22 @@ CPLErr VRTSourcedRasterBand::SetMetadataItem( const char *pszName,
                                               const char *pszDomain )
 
 {
-    //CPLDebug( "VRT", "VRTSourcedRasterBand::SetMetadataItem(%s,%s,%s)\n",
-    //          pszName, pszValue, pszDomain );
+#if DEBUG_VERBOSE
+    CPLDebug( "VRT", "VRTSourcedRasterBand::SetMetadataItem(%s,%s,%s)\n",
+              pszName, pszValue, pszDomain );
+#endif
 
     if( pszDomain != NULL
         && EQUAL(pszDomain,"new_vrt_sources") )
     {
-        VRTDriver *poDriver = reinterpret_cast<VRTDriver *>(
+        VRTDriver * const poDriver = reinterpret_cast<VRTDriver *>(
             GDALGetDriverByName( "VRT" ) );
 
-        CPLXMLNode *psTree = CPLParseXMLString( pszValue );
+        CPLXMLNode * const psTree = CPLParseXMLString( pszValue );
         if( psTree == NULL )
             return CE_Failure;
 
-        VRTSource *poSource = poDriver->ParseSource( psTree, NULL );
+        VRTSource * const poSource = poDriver->ParseSource( psTree, NULL );
         CPLDestroyXMLNode( psTree );
 
         if( poSource != NULL )
@@ -1338,25 +1561,26 @@ CPLErr VRTSourcedRasterBand::SetMetadataItem( const char *pszName,
     else if( pszDomain != NULL
         && EQUAL(pszDomain,"vrt_sources") )
     {
-        int iSource;
-        if (sscanf(pszName, "source_%d", &iSource) != 1 || iSource < 0 ||
-            iSource >= nSources)
+        int iSource = 0;
+        // TODO(schwehr): Replace sscanf.
+        if( sscanf(pszName, "source_%d", &iSource) != 1 || iSource < 0 ||
+            iSource >= nSources )
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "%s metadata item name is not recognized. "
-                     "Should be between source_0 and source_%d",
-                     pszName, nSources - 1);
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "%s metadata item name is not recognized. "
+                      "Should be between source_0 and source_%d",
+                      pszName, nSources - 1 );
             return CE_Failure;
         }
 
-        VRTDriver *poDriver = reinterpret_cast<VRTDriver *>(
+        VRTDriver * const poDriver = reinterpret_cast<VRTDriver *>(
             GDALGetDriverByName( "VRT" ) );
 
-        CPLXMLNode *psTree = CPLParseXMLString( pszValue );
+        CPLXMLNode * const psTree = CPLParseXMLString( pszValue );
         if( psTree == NULL )
             return CE_Failure;
 
-        VRTSource *poSource = poDriver->ParseSource( psTree, NULL );
+        VRTSource * const poSource = poDriver->ParseSource( psTree, NULL );
         CPLDestroyXMLNode( psTree );
 
         if( poSource != NULL )
@@ -1384,7 +1608,7 @@ CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDoma
         && (EQUAL(pszDomain,"new_vrt_sources")
             || EQUAL(pszDomain,"vrt_sources")) )
     {
-        VRTDriver *poDriver
+        VRTDriver * const poDriver
             = reinterpret_cast<VRTDriver *>( GDALGetDriverByName( "VRT" ) );
 
         if( EQUAL(pszDomain,"vrt_sources") )
@@ -1398,19 +1622,20 @@ CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDoma
 
         for( int i = 0; i < CSLCount(papszNewMD); i++ )
         {
-            const char *pszXML = CPLParseNameValue( papszNewMD[i], NULL );
+            const char * const pszXML =
+                CPLParseNameValue( papszNewMD[i], NULL );
 
-            CPLXMLNode *psTree = CPLParseXMLString( pszXML );
+            CPLXMLNode * const psTree = CPLParseXMLString( pszXML );
             if( psTree == NULL )
                 return CE_Failure;
 
-            VRTSource *poSource = poDriver->ParseSource( psTree, NULL );
+            VRTSource * const poSource = poDriver->ParseSource( psTree, NULL );
             CPLDestroyXMLNode( psTree );
 
             if( poSource == NULL )
                 return CE_Failure;
 
-            CPLErr eErr = AddSource( poSource );
+            const CPLErr eErr = AddSource( poSource );
             if( eErr != CE_None )
                 return eErr;
         }
@@ -1425,17 +1650,17 @@ CPLErr VRTSourcedRasterBand::SetMetadata( char **papszNewMD, const char *pszDoma
 /*                             GetFileList()                            */
 /************************************************************************/
 
-void VRTSourcedRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
-                                       int *pnMaxSize, CPLHashSet* hSetFiles)
+void VRTSourcedRasterBand::GetFileList( char*** ppapszFileList, int *pnSize,
+                                        int *pnMaxSize, CPLHashSet* hSetFiles )
 {
     for( int i = 0; i < nSources; i++ )
     {
-        papoSources[i]->GetFileList(ppapszFileList, pnSize,
-                                    pnMaxSize, hSetFiles);
+        papoSources[i]->GetFileList( ppapszFileList, pnSize,
+                                     pnMaxSize, hSetFiles );
     }
 
     VRTRasterBand::GetFileList( ppapszFileList, pnSize,
-                                pnMaxSize, hSetFiles);
+                                pnMaxSize, hSetFiles );
 }
 
 /************************************************************************/
@@ -1444,7 +1669,7 @@ void VRTSourcedRasterBand::GetFileList(char*** ppapszFileList, int *pnSize,
 
 int VRTSourcedRasterBand::CloseDependentDatasets()
 {
-    if (nSources == 0)
+    if( nSources == 0 )
         return FALSE;
 
     for( int i = 0; i < nSources; i++ )
@@ -1456,3 +1681,5 @@ int VRTSourcedRasterBand::CloseDependentDatasets()
 
     return TRUE;
 }
+
+/*! @endcond */
diff --git a/frmts/vrt/vrtsources.cpp b/frmts/vrt/vrtsources.cpp
index cac84ce..672e313 100644
--- a/frmts/vrt/vrtsources.cpp
+++ b/frmts/vrt/vrtsources.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vrtsources.cpp 36800 2016-12-11 22:24:27Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTSimpleSource, VRTFuncSource and
@@ -29,12 +28,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "gdal_vrt.h"
 #include "vrtdataset.h"
-#include "gdal_proxy.h"
+
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_hash_set.h"
 #include "cpl_minixml.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "gdal_proxy.h"
 
-/* See #5459 */
+/*! @cond Doxygen_Suppress */
+
+// #define DEBUG_VERBOSE 1
+
+// See #5459
 #ifdef isnan
 #define HAS_ISNAN_MACRO
 #endif
@@ -43,7 +64,7 @@
 #define isnan std::isnan
 #endif
 
-CPL_CVSID("$Id: vrtsources.cpp 36800 2016-12-11 22:24:27Z rouault $");
+CPL_CVSID("$Id: vrtsources.cpp 37723 2017-03-16 17:07:53Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -51,20 +72,17 @@ CPL_CVSID("$Id: vrtsources.cpp 36800 2016-12-11 22:24:27Z rouault $");
 /* ==================================================================== */
 /************************************************************************/
 
-VRTSource::~VRTSource()
-{
-}
+VRTSource::~VRTSource() {}
 
 /************************************************************************/
 /*                             GetFileList()                            */
 /************************************************************************/
 
-void VRTSource::GetFileList(CPL_UNUSED char*** ppapszFileList,
-                            CPL_UNUSED int *pnSize,
-                            CPL_UNUSED int *pnMaxSize,
-                            CPL_UNUSED CPLHashSet* hSetFiles)
-{
-}
+void VRTSource::GetFileList(char*** /* ppapszFileList */,
+                            int * /* pnSize */,
+                            int * /* pnMaxSize */,
+                            CPLHashSet * /* hSetFiles */)
+{}
 
 /************************************************************************/
 /* ==================================================================== */
@@ -77,6 +95,8 @@ void VRTSource::GetFileList(CPL_UNUSED char*** ppapszFileList,
 /************************************************************************/
 
 VRTSimpleSource::VRTSimpleSource() :
+    m_poRasterBand(NULL),
+    m_poMaskBandMainBand(NULL),
     m_dfSrcXOff(0.0),
     m_dfSrcYOff(0.0),
     m_dfSrcXSize(0.0),
@@ -84,38 +104,34 @@ VRTSimpleSource::VRTSimpleSource() :
     m_dfDstXOff(0.0),
     m_dfDstYOff(0.0),
     m_dfDstXSize(0.0),
-    m_dfDstYSize(0.0)
-{
-    m_poRasterBand = NULL;
-    m_poMaskBandMainBand = NULL;
-    m_bNoDataSet = FALSE;
-    m_dfNoDataValue = VRT_NODATA_UNSET;
-    m_bRelativeToVRTOri = -1;
-    m_nMaxValue = 0;
-}
+    m_dfDstYSize(0.0),
+    m_bNoDataSet(FALSE),
+    m_dfNoDataValue(VRT_NODATA_UNSET),
+    m_nMaxValue(0),
+    m_bRelativeToVRTOri(-1)
+{}
 
 /************************************************************************/
 /*                          VRTSimpleSource()                           */
 /************************************************************************/
 
-VRTSimpleSource::VRTSimpleSource(const VRTSimpleSource* poSrcSource,
-                                 double dfXDstRatio, double dfYDstRatio)
-{
-    m_poRasterBand = poSrcSource->m_poRasterBand;
-    m_poMaskBandMainBand = poSrcSource->m_poMaskBandMainBand;
-    m_bNoDataSet = poSrcSource->m_bNoDataSet;
-    m_dfNoDataValue = poSrcSource->m_dfNoDataValue;
-    m_dfSrcXOff = poSrcSource->m_dfSrcXOff;
-    m_dfSrcYOff = poSrcSource->m_dfSrcYOff;
-    m_dfSrcXSize = poSrcSource->m_dfSrcXSize;
-    m_dfSrcYSize = poSrcSource->m_dfSrcYSize;
-    m_dfDstXOff = poSrcSource->m_dfDstXOff * dfXDstRatio;
-    m_dfDstYOff = poSrcSource->m_dfDstYOff * dfYDstRatio;
-    m_dfDstXSize = poSrcSource->m_dfDstXSize * dfXDstRatio;
-    m_dfDstYSize = poSrcSource->m_dfDstYSize * dfYDstRatio;
-    m_bRelativeToVRTOri = -1;
-    m_nMaxValue = poSrcSource->m_nMaxValue;
-}
+VRTSimpleSource::VRTSimpleSource( const VRTSimpleSource* poSrcSource,
+                                  double dfXDstRatio, double dfYDstRatio ) :
+    m_poRasterBand(poSrcSource->m_poRasterBand),
+    m_poMaskBandMainBand(poSrcSource->m_poMaskBandMainBand),
+    m_dfSrcXOff(poSrcSource->m_dfSrcXOff),
+    m_dfSrcYOff(poSrcSource->m_dfSrcYOff),
+    m_dfSrcXSize(poSrcSource->m_dfSrcXSize),
+    m_dfSrcYSize(poSrcSource->m_dfSrcYSize),
+    m_dfDstXOff(poSrcSource->m_dfDstXOff * dfXDstRatio),
+    m_dfDstYOff(poSrcSource->m_dfDstYOff * dfYDstRatio),
+    m_dfDstXSize(poSrcSource->m_dfDstXSize * dfXDstRatio),
+    m_dfDstYSize(poSrcSource->m_dfDstYSize * dfYDstRatio),
+    m_bNoDataSet(poSrcSource->m_bNoDataSet),
+    m_dfNoDataValue(poSrcSource->m_dfNoDataValue),
+    m_nMaxValue(poSrcSource->m_nMaxValue),
+    m_bRelativeToVRTOri(-1)
+{}
 
 /************************************************************************/
 /*                          ~VRTSimpleSource()                          */
@@ -124,25 +140,16 @@ VRTSimpleSource::VRTSimpleSource(const VRTSimpleSource* poSrcSource,
 VRTSimpleSource::~VRTSimpleSource()
 
 {
-    // We use bRelativeToVRTOri to know if the file has been opened from
-    // XMLInit(), and thus we are sure that no other code has a direct reference
-    // to the dataset
     if( m_poMaskBandMainBand != NULL )
     {
-        if (m_poMaskBandMainBand->GetDataset() != NULL )
+        if( m_poMaskBandMainBand->GetDataset() != NULL )
         {
-            if( m_poMaskBandMainBand->GetDataset()->GetShared() || m_bRelativeToVRTOri >= 0 )
-                GDALClose( (GDALDatasetH) m_poMaskBandMainBand->GetDataset() );
-            else
-                m_poMaskBandMainBand->GetDataset()->Dereference();
+            m_poMaskBandMainBand->GetDataset()->ReleaseRef();
         }
     }
     else if( m_poRasterBand != NULL && m_poRasterBand->GetDataset() != NULL )
     {
-        if( m_poRasterBand->GetDataset()->GetShared() || m_bRelativeToVRTOri >= 0 )
-            GDALClose( (GDALDatasetH) m_poRasterBand->GetDataset() );
-        else
-            m_poRasterBand->GetDataset()->Dereference();
+        m_poRasterBand->GetDataset()->ReleaseRef();
     }
 }
 
@@ -166,12 +173,12 @@ void VRTSimpleSource::SetSrcBand( GDALRasterBand *poNewSrcBand )
     m_poRasterBand = poNewSrcBand;
 }
 
-
 /************************************************************************/
 /*                          SetSrcMaskBand()                            */
 /************************************************************************/
 
-/* poSrcBand is not the mask band, but the band from which the mask band is taken */
+// poSrcBand is not the mask band, but the band from which the mask band is
+// taken.
 void VRTSimpleSource::SetSrcMaskBand( GDALRasterBand *poNewSrcBand )
 
 {
@@ -228,40 +235,35 @@ void VRTSimpleSource::SetNoDataValue( double dfNewNoDataValue )
     {
         m_bNoDataSet = FALSE;
         m_dfNoDataValue = VRT_NODATA_UNSET;
+        return;
     }
-    else
-    {
-        m_bNoDataSet = TRUE;
-        m_dfNoDataValue = dfNewNoDataValue;
-    }
+
+    m_bNoDataSet = TRUE;
+    m_dfNoDataValue = dfNewNoDataValue;
 }
 
 /************************************************************************/
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
-static const char* const apszSpecialSyntax[] = { "HDF5:\"{FILENAME}\":{ANY}",
-                                            "HDF5:{FILENAME}:{ANY}",
-                                            "NETCDF:\"{FILENAME}\":{ANY}",
-                                            "NETCDF:{FILENAME}:{ANY}",
-                                            "NITF_IM:{ANY}:{FILENAME}",
-                                            "PDF:{ANY}:{FILENAME}",
-                                            "RASTERLITE:{FILENAME},{ANY}" };
+static const char* const apszSpecialSyntax[] = {
+    "HDF5:\"{FILENAME}\":{ANY}",
+    "HDF5:{FILENAME}:{ANY}",
+    "NETCDF:\"{FILENAME}\":{ANY}",
+    "NETCDF:{FILENAME}:{ANY}",
+    "NITF_IM:{ANY}:{FILENAME}",
+    "PDF:{ANY}:{FILENAME}",
+    "RASTERLITE:{FILENAME},{ANY}" };
 
 CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
 
 {
-    CPLXMLNode      *psSrc;
-    int              bRelativeToVRT;
-    const char      *pszRelativePath;
-    int              nBlockXSize, nBlockYSize;
-
     if( m_poRasterBand == NULL )
         return NULL;
 
-    GDALDataset     *poDS;
+    GDALDataset *poDS = NULL;
 
-    if (m_poMaskBandMainBand)
+    if( m_poMaskBandMainBand )
     {
         poDS = m_poMaskBandMainBand->GetDataset();
         if( poDS == NULL || m_poMaskBandMainBand->GetBand() < 1 )
@@ -274,9 +276,10 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
             return NULL;
     }
 
-    psSrc = CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
+    CPLXMLNode * const psSrc =
+        CPLCreateXMLNode( NULL, CXT_Element, "SimpleSource" );
 
-    if( m_osResampling.size() )
+    if( !m_osResampling.empty() )
     {
         CPLCreateXMLNode(
             CPLCreateXMLNode( psSrc, CXT_Attribute, "resampling" ),
@@ -285,31 +288,37 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
 
     VSIStatBufL sStat;
     CPLString osTmp;
+    int bRelativeToVRT = FALSE;  // TODO(schwehr): Make this a bool?
+    const char *pszRelativePath = NULL;
+
     if( m_bRelativeToVRTOri >= 0 )
     {
         pszRelativePath = m_osSourceFileNameOri;
         bRelativeToVRT = m_bRelativeToVRTOri;
     }
-    else if ( strstr(poDS->GetDescription(), "/vsicurl/http") != NULL ||
-         strstr(poDS->GetDescription(), "/vsicurl/ftp") != NULL )
+    else if( strstr(poDS->GetDescription(), "/vsicurl/http") != NULL ||
+             strstr(poDS->GetDescription(), "/vsicurl/ftp") != NULL )
     {
-        /* Testing the existence of remote resources can be excruciating */
-        /* slow, so let's just suppose they exist */
+        // Testing the existence of remote resources can be excruciating
+        // slow, so let's just suppose they exist.
         pszRelativePath = poDS->GetDescription();
         bRelativeToVRT = FALSE;
     }
-    /* If this isn't actually a file, don't even try to know if it is */
-    /* a relative path. It can't be !, and unfortunately */
-    /* CPLIsFilenameRelative() can only work with strings that are filenames */
-    /* To be clear NITF_TOC_ENTRY:CADRG_JOG-A_250K_1_0:some_path isn't a relative */
-    /* file path */
-    else if( VSIStatExL( poDS->GetDescription(), &sStat, VSI_STAT_EXISTS_FLAG ) != 0 )
+    // If this isn't actually a file, don't even try to know if it is a
+    // relative path. It can't be !, and unfortunately CPLIsFilenameRelative()
+    // can only work with strings that are filenames To be clear
+    // NITF_TOC_ENTRY:CADRG_JOG-A_250K_1_0:some_path isn't a relative file
+    // path.
+    else if( VSIStatExL( poDS->GetDescription(), &sStat,
+                         VSI_STAT_EXISTS_FLAG ) != 0 )
     {
         pszRelativePath = poDS->GetDescription();
         bRelativeToVRT = FALSE;
-        for( size_t i = 0; i < sizeof(apszSpecialSyntax) / sizeof(apszSpecialSyntax[0]); i ++)
+        for( size_t i = 0;
+             i < sizeof(apszSpecialSyntax) / sizeof(apszSpecialSyntax[0]);
+             ++i )
         {
-            const char* pszSyntax = apszSpecialSyntax[i];
+            const char* const pszSyntax = apszSpecialSyntax[i];
             CPLString osPrefix(pszSyntax);
             osPrefix.resize(strchr(pszSyntax, ':') - pszSyntax + 1);
             if( pszSyntax[osPrefix.size()] == '"' )
@@ -319,29 +328,34 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
                 if( STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}") )
                 {
                     const char* pszLastPart = strrchr(pszRelativePath, ':') + 1;
-                    /* CSV:z:/foo.xyz */
+                    // CSV:z:/foo.xyz
                     if( (pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
-                        pszLastPart - pszRelativePath >= 3 && pszLastPart[-3] == ':' )
+                        pszLastPart - pszRelativePath >= 3 &&
+                        pszLastPart[-3] == ':' )
                         pszLastPart -= 2;
-                    CPLString osPrefixFilename = pszRelativePath;
+                    CPLString osPrefixFilename(pszRelativePath);
                     osPrefixFilename.resize(pszLastPart - pszRelativePath);
                     pszRelativePath =
                         CPLExtractRelativePath( pszVRTPath, pszLastPart,
-                                    &bRelativeToVRT );
+                                                &bRelativeToVRT );
                     osTmp = osPrefixFilename + pszRelativePath;
                     pszRelativePath = osTmp.c_str();
                 }
-                else if( STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{FILENAME}") )
+                else if( STARTS_WITH_CI(pszSyntax + osPrefix.size(),
+                                        "{FILENAME}") )
                 {
                     CPLString osFilename(pszRelativePath + osPrefix.size());
                     size_t nPos = 0;
                     if( osFilename.size() >= 3 && osFilename[1] == ':' &&
                         (osFilename[2] == '\\' || osFilename[2] == '/') )
                         nPos = 2;
-                    nPos = osFilename.find(pszSyntax[osPrefix.size() + strlen("{FILENAME}")], nPos);
+                    nPos =
+                        osFilename.find(
+                            pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
+                            nPos );
                     if( nPos != std::string::npos )
                     {
-                        CPLString osSuffix = osFilename.substr(nPos);
+                        const CPLString osSuffix = osFilename.substr(nPos);
                         osFilename.resize(nPos);
                         pszRelativePath =
                             CPLExtractRelativePath( pszVRTPath, osFilename,
@@ -379,7 +393,7 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
     char** papszOpenOptions = poDS->GetOpenOptions();
     GDALSerializeOpenOptionsToXML(psSrc, papszOpenOptions);
 
-    if (m_poMaskBandMainBand)
+    if( m_poMaskBandMainBand )
         CPLSetXMLValue( psSrc, "SourceBand",
                         CPLSPrintf("mask,%d",m_poMaskBandMainBand->GetBand()) );
     else
@@ -395,7 +409,11 @@ CPLXMLNode *VRTSimpleSource::SerializeToXML( const char *pszVRTPath )
                     CPLSPrintf("%d",m_poRasterBand->GetYSize()) );
     CPLSetXMLValue( psSrc, "SourceProperties.#DataType",
                 GDALGetDataTypeName( m_poRasterBand->GetRasterDataType() ) );
+
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
     m_poRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+
     CPLSetXMLValue( psSrc, "SourceProperties.#BlockXSize",
                     CPLSPrintf("%d",nBlockXSize) );
     CPLSetXMLValue( psSrc, "SourceProperties.#BlockYSize",
@@ -442,10 +460,10 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Prepare filename.                                               */
 /* -------------------------------------------------------------------- */
-    char *pszSrcDSName = NULL;
     CPLXMLNode* psSourceFileNameNode = CPLGetXMLNode(psSrc,"SourceFilename");
     const char *pszFilename =
-        psSourceFileNameNode ? CPLGetXMLValue(psSourceFileNameNode,NULL, NULL) : NULL;
+        psSourceFileNameNode ?
+        CPLGetXMLValue(psSourceFileNameNode, NULL, NULL) : NULL;
 
     if( pszFilename == NULL )
     {
@@ -457,19 +475,23 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     // Backup original filename and relativeToVRT so as to be able to
     // serialize them identically again (#5985)
     m_osSourceFileNameOri = pszFilename;
-    m_bRelativeToVRTOri = atoi(CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0"));
-    const char* pszShared = CPLGetXMLValue( psSourceFileNameNode, "shared", NULL);
-    int bShared = FALSE;
+    m_bRelativeToVRTOri =
+        atoi( CPLGetXMLValue( psSourceFileNameNode, "relativetoVRT", "0") );
+    const char* pszShared = CPLGetXMLValue( psSourceFileNameNode,
+                                            "shared", NULL );
+    bool bShared = false;
     if( pszShared != NULL )
         bShared = CPLTestBool(pszShared);
     else
         bShared = CPLTestBool(CPLGetConfigOption("VRT_SHARED_SOURCE", "TRUE"));
 
-    if( pszVRTPath != NULL
-        && m_bRelativeToVRTOri )
+    char *pszSrcDSName = NULL;
+    if( pszVRTPath != NULL && m_bRelativeToVRTOri )
     {
-        int bDone = FALSE;
-        for( size_t i = 0; i < sizeof(apszSpecialSyntax) / sizeof(apszSpecialSyntax[0]); i ++)
+        bool bDone = false;
+        for( size_t i = 0;
+             i < sizeof(apszSpecialSyntax) / sizeof(apszSpecialSyntax[0]);
+             ++i )
         {
             const char* pszSyntax = apszSpecialSyntax[i];
             CPLString osPrefix(pszSyntax);
@@ -480,16 +502,20 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
             {
                 if( STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{ANY}") )
                 {
-                    const char* pszLastPart = strrchr(pszFilename, ':') + 1;
-                    /* CSV:z:/foo.xyz */
-                    if( (pszLastPart[0] == '/' || pszLastPart[0] == '\\') &&
-                        pszLastPart - pszFilename >= 3 && pszLastPart[-3] == ':' )
+                    const char * pszLastPart = strrchr(pszFilename, ':') + 1;
+                    // CSV:z:/foo.xyz
+                    if( ( pszLastPart[0] == '/' ||
+                          pszLastPart[0] == '\\') &&
+                        pszLastPart - pszFilename >= 3 &&
+                        pszLastPart[-3] == ':' )
+                    {
                         pszLastPart -= 2;
+                    }
                     CPLString osPrefixFilename = pszFilename;
                     osPrefixFilename.resize(pszLastPart - pszFilename);
                     pszSrcDSName = CPLStrdup( (osPrefixFilename +
                         CPLProjectRelativeFilename( pszVRTPath, pszLastPart )).c_str() );
-                    bDone = TRUE;
+                    bDone = true;
                 }
                 else if( STARTS_WITH_CI(pszSyntax + osPrefix.size(), "{FILENAME}") )
                 {
@@ -498,14 +524,17 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
                     if( osFilename.size() >= 3 && osFilename[1] == ':' &&
                         (osFilename[2] == '\\' || osFilename[2] == '/') )
                         nPos = 2;
-                    nPos = osFilename.find(pszSyntax[osPrefix.size() + strlen("{FILENAME}")], nPos);
+                    nPos = osFilename.find(
+                        pszSyntax[osPrefix.size() + strlen("{FILENAME}")],
+                        nPos);
                     if( nPos != std::string::npos )
                     {
-                        CPLString osSuffix = osFilename.substr(nPos);
+                        const CPLString osSuffix = osFilename.substr(nPos);
                         osFilename.resize(nPos);
-                        pszSrcDSName = CPLStrdup( (osPrefix +
-                            CPLProjectRelativeFilename( pszVRTPath, osFilename ) + osSuffix).c_str() );
-                        bDone = TRUE;
+                        pszSrcDSName = CPLStrdup(
+                            (osPrefix + CPLProjectRelativeFilename(
+                                pszVRTPath, osFilename ) + osSuffix).c_str() );
+                        bDone = true;
                     }
                 }
                 break;
@@ -518,22 +547,26 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
         }
     }
     else
+    {
         pszSrcDSName = CPLStrdup( pszFilename );
+    }
 
     const char* pszSourceBand = CPLGetXMLValue(psSrc,"SourceBand","1");
     int nSrcBand = 0;
-    int bGetMaskBand = FALSE;
-    if (STARTS_WITH_CI(pszSourceBand, "mask"))
+    bool bGetMaskBand = false;
+    if( STARTS_WITH_CI(pszSourceBand, "mask") )
     {
-        bGetMaskBand = TRUE;
-        if (pszSourceBand[4] == ',')
+        bGetMaskBand = true;
+        if( pszSourceBand[4] == ',' )
             nSrcBand = atoi(pszSourceBand + 5);
         else
             nSrcBand = 1;
     }
     else
+    {
         nSrcBand = atoi(pszSourceBand);
-    if (!GDALCheckBandCount(nSrcBand, 0))
+    }
+    if( !GDALCheckBandCount(nSrcBand, 0) )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Invalid <SourceBand> element in VRTRasterBand." );
@@ -541,36 +574,45 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
         return CE_Failure;
     }
 
-    /* Newly generated VRT will have RasterXSize, RasterYSize, DataType, */
-    /* BlockXSize, BlockYSize tags, so that we don't have actually to */
-    /* open the real dataset immediately, but we can use a proxy dataset */
-    /* instead. This is particularly useful when dealing with huge VRT */
-    /* For example, a VRT with the world coverage of DTED0 (25594 files) */
+    // Newly generated VRT will have RasterXSize, RasterYSize, DataType,
+    // BlockXSize, BlockYSize tags, so that we don't have actually to
+    // open the real dataset immediately, but we can use a proxy dataset
+    // instead. This is particularly useful when dealing with huge VRT
+    // For example, a VRT with the world coverage of DTED0 (25594 files).
     CPLXMLNode* psSrcProperties = CPLGetXMLNode(psSrc,"SourceProperties");
-    int nRasterXSize = 0, nRasterYSize =0;
-    GDALDataType eDataType = (GDALDataType)-1;
-    int nBlockXSize = 0, nBlockYSize = 0;
-    if (psSrcProperties)
-    {
-        nRasterXSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterXSize","0"));
-        nRasterYSize = atoi(CPLGetXMLValue(psSrcProperties,"RasterYSize","0"));
-        const char *pszDataType = CPLGetXMLValue(psSrcProperties, "DataType", NULL);
+    int nRasterXSize = 0;
+    int nRasterYSize = 0;
+    // TODO(schwehr): What is the difference between 0 (GDT_Unknown) and -1?
+    // Does there need to be a GDT_Uninitialized?
+    GDALDataType eDataType = static_cast<GDALDataType>(-1);
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
+    if( psSrcProperties )
+    {
+        nRasterXSize =
+            atoi(CPLGetXMLValue(psSrcProperties, "RasterXSize", "0"));
+        nRasterYSize =
+            atoi(CPLGetXMLValue(psSrcProperties, "RasterYSize", "0"));
+        const char *pszDataType =
+            CPLGetXMLValue(psSrcProperties, "DataType", NULL);
         if( pszDataType != NULL )
         {
             for( int iType = 0; iType < GDT_TypeCount; iType++ )
             {
-                const char *pszThisName = GDALGetDataTypeName((GDALDataType)iType);
+                const char *pszThisName =
+                    GDALGetDataTypeName(static_cast<GDALDataType>(iType));
 
-                if( pszThisName != NULL && EQUAL(pszDataType,pszThisName) )
+                if( pszThisName != NULL && EQUAL(pszDataType, pszThisName) )
                 {
-                    eDataType = (GDALDataType) iType;
+                    eDataType = static_cast<GDALDataType>(iType);
                     break;
                 }
             }
         }
-        nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockXSize","0"));
-        nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties,"BlockYSize","0"));
-        if( nRasterXSize < 0 || nRasterYSize < 0 || nBlockXSize < 0 || nBlockYSize < 0 )
+        nBlockXSize = atoi(CPLGetXMLValue(psSrcProperties, "BlockXSize", "0"));
+        nBlockYSize = atoi(CPLGetXMLValue(psSrcProperties, "BlockYSize", "0"));
+        if( nRasterXSize < 0 || nRasterYSize < 0 ||
+            nBlockXSize < 0 || nBlockYSize < 0 )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Invalid <SourceProperties> element in VRTRasterBand." );
@@ -581,38 +623,56 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
 
     char** papszOpenOptions = GDALDeserializeOpenOptionsFromXML(psSrc);
     if( strstr(pszSrcDSName,"<VRTDataset") != NULL )
-        papszOpenOptions = CSLSetNameValue(papszOpenOptions, "ROOT_PATH", pszVRTPath);
+        papszOpenOptions =
+            CSLSetNameValue(papszOpenOptions, "ROOT_PATH", pszVRTPath);
 
-    GDALDataset *poSrcDS;
-    if (nRasterXSize == 0 || nRasterYSize == 0 || eDataType == (GDALDataType)-1 ||
-        nBlockXSize == 0 || nBlockYSize == 0)
+    GDALDataset *poSrcDS = NULL;
+    if( nRasterXSize == 0 || nRasterYSize == 0 ||
+        eDataType == static_cast<GDALDataType>(-1) ||
+        nBlockXSize == 0 || nBlockYSize == 0 )
     {
-        /* -------------------------------------------------------------------- */
-        /*      Open the file (shared).                                         */
-        /* -------------------------------------------------------------------- */
+        /* ----------------------------------------------------------------- */
+        /*      Open the file (shared).                                      */
+        /* ----------------------------------------------------------------- */
         int nOpenFlags = GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR;
         if( bShared )
             nOpenFlags |= GDAL_OF_SHARED;
-        poSrcDS = (GDALDataset *) GDALOpenEx(
+        poSrcDS = static_cast<GDALDataset *>( GDALOpenEx(
                     pszSrcDSName, nOpenFlags, NULL,
-                    (const char* const* )papszOpenOptions, NULL );
+                    (const char* const* )papszOpenOptions, NULL ) );
     }
     else
     {
-        /* -------------------------------------------------------------------- */
-        /*      Create a proxy dataset                                          */
-        /* -------------------------------------------------------------------- */
-        int i;
-        GDALProxyPoolDataset* proxyDS = new GDALProxyPoolDataset(pszSrcDSName, nRasterXSize, nRasterYSize, GA_ReadOnly, bShared);
+        /* ----------------------------------------------------------------- */
+        /*      Create a proxy dataset                                       */
+        /* ----------------------------------------------------------------- */
+        GDALProxyPoolDataset * const proxyDS =
+            new GDALProxyPoolDataset( pszSrcDSName, nRasterXSize, nRasterYSize,
+                                      GA_ReadOnly, bShared );
         proxyDS->SetOpenOptions(papszOpenOptions);
         poSrcDS = proxyDS;
 
-        /* Only the information of rasterBand nSrcBand will be accurate */
-        /* but that's OK since we only use that band afterwards */
-        for(i=1;i<=nSrcBand;i++)
+        // Only the information of rasterBand nSrcBand will be accurate
+        // but that's OK since we only use that band afterwards.
+        for( int i = 1; i <= nSrcBand; i++ )
             proxyDS->AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
-        if (bGetMaskBand)
-            ((GDALProxyPoolRasterBand*)proxyDS->GetRasterBand(nSrcBand))->AddSrcMaskBandDescription(eDataType, nBlockXSize, nBlockYSize);
+
+        if( bGetMaskBand )
+        {
+          GDALProxyPoolRasterBand *poMaskBand =
+              dynamic_cast<GDALProxyPoolRasterBand *>(
+              proxyDS->GetRasterBand(nSrcBand) );
+          if( poMaskBand == NULL )
+          {
+              CPLError(
+                  CE_Fatal, CPLE_AssertionFailed, "dynamic_cast failed." );
+          }
+          else
+          {
+              poMaskBand->AddSrcMaskBandDescription(
+                  eDataType, nBlockXSize, nBlockYSize );
+          }
+        }
     }
 
     CSLDestroy(papszOpenOptions);
@@ -630,10 +690,10 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     if( m_poRasterBand == NULL )
     {
         if( poSrcDS->GetShared() )
-            GDALClose( (GDALDatasetH) poSrcDS );
+            GDALClose( poSrcDS );
         return CE_Failure;
     }
-    if (bGetMaskBand)
+    if( bGetMaskBand )
     {
         m_poMaskBandMainBand = m_poRasterBand;
         m_poRasterBand = m_poRasterBand->GetMaskBand();
@@ -644,8 +704,8 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
 /* -------------------------------------------------------------------- */
 /*      Set characteristics.                                            */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode* psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
-    if (psSrcRect)
+    CPLXMLNode * const psSrcRect = CPLGetXMLNode(psSrc,"SrcRect");
+    if( psSrcRect )
     {
         SetSrcWindow( CPLAtof(CPLGetXMLValue(psSrcRect,"xOff","-1")),
                       CPLAtof(CPLGetXMLValue(psSrcRect,"yOff","-1")),
@@ -654,11 +714,14 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     }
     else
     {
-        m_dfSrcXOff = m_dfSrcYOff = m_dfSrcXSize = m_dfSrcYSize = -1;
+        m_dfSrcXOff = -1;
+        m_dfSrcYOff = -1;
+        m_dfSrcXSize = -1;
+        m_dfSrcYSize = -1;
     }
 
-    CPLXMLNode* psDstRect = CPLGetXMLNode(psSrc,"DstRect");
-    if (psDstRect)
+    CPLXMLNode * const psDstRect = CPLGetXMLNode(psSrc,"DstRect");
+    if( psDstRect )
     {
         SetDstWindow( CPLAtof(CPLGetXMLValue(psDstRect,"xOff","-1")),
                       CPLAtof(CPLGetXMLValue(psDstRect,"yOff","-1")),
@@ -667,7 +730,10 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
     }
     else
     {
-        m_dfDstXOff = m_dfDstYOff = m_dfDstXSize = m_dfDstYSize = -1;
+      m_dfDstXOff = -1;
+      m_dfDstYOff = -1;
+      m_dfDstXSize = -1;
+      m_dfDstYSize = -1;
     }
 
     return CE_None;
@@ -677,21 +743,21 @@ CPLErr VRTSimpleSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
 /*                             GetFileList()                            */
 /************************************************************************/
 
-void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
-                                  int *pnMaxSize, CPLHashSet* hSetFiles)
+void VRTSimpleSource::GetFileList( char*** ppapszFileList, int *pnSize,
+                                   int *pnMaxSize, CPLHashSet* hSetFiles )
 {
-    const char* pszFilename;
-    if (m_poRasterBand != NULL && m_poRasterBand->GetDataset() != NULL &&
-        (pszFilename = m_poRasterBand->GetDataset()->GetDescription()) != NULL)
+    const char* pszFilename = NULL;
+    if( m_poRasterBand != NULL && m_poRasterBand->GetDataset() != NULL &&
+        (pszFilename = m_poRasterBand->GetDataset()->GetDescription()) != NULL )
     {
 /* -------------------------------------------------------------------- */
 /*      Is the filename even a real filesystem object?                  */
 /* -------------------------------------------------------------------- */
-        if ( strstr(pszFilename, "/vsicurl/http") != NULL ||
-             strstr(pszFilename, "/vsicurl/ftp") != NULL )
+        if( strstr(pszFilename, "/vsicurl/http") != NULL ||
+            strstr(pszFilename, "/vsicurl/ftp") != NULL )
         {
-            /* Testing the existence of remote resources can be excruciating */
-            /* slow, so let's just suppose they exist */
+            // Testing the existence of remote resources can be excruciating
+            // slow, so just suppose they exist.
         }
         else
         {
@@ -709,11 +775,11 @@ void VRTSimpleSource::GetFileList(char*** ppapszFileList, int *pnSize,
 /* -------------------------------------------------------------------- */
 /*      Grow array if necessary                                         */
 /* -------------------------------------------------------------------- */
-        if (*pnSize + 1 >= *pnMaxSize)
+        if( *pnSize + 1 >= *pnMaxSize )
         {
-            *pnMaxSize = 2 + 2 * (*pnMaxSize);
-            *ppapszFileList = (char **) CPLRealloc(
-                        *ppapszFileList, sizeof(char*)  * (*pnMaxSize) );
+            *pnMaxSize = std::max(*pnSize + 2, 2 + 2 * (*pnMaxSize));
+            *ppapszFileList = static_cast<char **>( CPLRealloc(
+                *ppapszFileList, sizeof(char*) * (*pnMaxSize) ) );
         }
 
 /* -------------------------------------------------------------------- */
@@ -740,7 +806,7 @@ GDALRasterBand* VRTSimpleSource::GetBand()
 /*                       IsSameExceptBandNumber()                       */
 /************************************************************************/
 
-int VRTSimpleSource::IsSameExceptBandNumber(VRTSimpleSource* poOtherSource)
+int VRTSimpleSource::IsSameExceptBandNumber( VRTSimpleSource* poOtherSource )
 {
     return m_dfSrcXOff == poOtherSource->m_dfSrcXOff &&
            m_dfSrcYOff == poOtherSource->m_dfSrcYOff &&
@@ -847,39 +913,39 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      the virtual file that this source can set, then clip down       */
 /*      the requested window.                                           */
 /* -------------------------------------------------------------------- */
-    int bModifiedX = FALSE, bModifiedY = FALSE;
+    bool bModifiedX = false;
+    bool bModifiedY = false;
     double dfRXOff = nXOff;
     double dfRYOff = nYOff;
     double dfRXSize = nXSize;
     double dfRYSize = nYSize;
 
-
     if( bDstWinSet )
     {
         if( dfRXOff < m_dfDstXOff )
         {
             dfRXSize = dfRXSize + dfRXOff - m_dfDstXOff;
             dfRXOff = m_dfDstXOff;
-            bModifiedX = TRUE;
+            bModifiedX = true;
         }
 
         if( dfRYOff < m_dfDstYOff )
         {
             dfRYSize = dfRYSize + dfRYOff - m_dfDstYOff;
             dfRYOff = m_dfDstYOff;
-            bModifiedY = TRUE;
+            bModifiedY = true;
         }
 
         if( dfRXOff + dfRXSize > m_dfDstXOff + m_dfDstXSize )
         {
             dfRXSize = m_dfDstXOff + m_dfDstXSize - dfRXOff;
-            bModifiedX = TRUE;
+            bModifiedX = true;
         }
 
         if( dfRYOff + dfRYSize > m_dfDstYOff + m_dfDstYSize )
         {
             dfRYSize = m_dfDstYOff + m_dfDstYSize - dfRYOff;
-            bModifiedY = TRUE;
+            bModifiedY = true;
         }
     }
 
@@ -887,8 +953,8 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      Translate requested region in virtual file into the source      */
 /*      band coordinates.                                               */
 /* -------------------------------------------------------------------- */
-    const double      dfScaleX = m_dfSrcXSize / m_dfDstXSize;
-    const double      dfScaleY = m_dfSrcYSize / m_dfDstYSize;
+    const double dfScaleX = m_dfSrcXSize / m_dfDstXSize;
+    const double dfScaleY = m_dfSrcYSize / m_dfDstYSize;
 
     *pdfReqXOff = (dfRXOff - m_dfDstXOff) * dfScaleX + m_dfSrcXOff;
     *pdfReqYOff = (dfRYOff - m_dfDstYOff) * dfScaleY + m_dfSrcYOff;
@@ -914,27 +980,27 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
     {
         *pdfReqXSize += *pdfReqXOff;
         *pdfReqXOff = 0;
-        bModifiedX = TRUE;
+        bModifiedX = true;
     }
     if( *pdfReqYOff < 0 )
     {
         *pdfReqYSize += *pdfReqYOff;
         *pdfReqYOff = 0;
-        bModifiedY = TRUE;
+        bModifiedY = true;
     }
 
-    *pnReqXOff = (int) floor(*pdfReqXOff);
-    *pnReqYOff = (int) floor(*pdfReqYOff);
+    *pnReqXOff = static_cast<int>( floor(*pdfReqXOff) );
+    *pnReqYOff = static_cast<int>( floor(*pdfReqYOff) );
 
     if( *pdfReqXSize > INT_MAX )
         *pnReqXSize = INT_MAX;
     else
-        *pnReqXSize = (int) floor(*pdfReqXSize + 0.5);
+        *pnReqXSize = static_cast<int>( floor(*pdfReqXSize + 0.5) );
 
     if( *pdfReqYSize > INT_MAX )
         *pnReqYSize = INT_MAX;
     else
-        *pnReqYSize = (int) floor(*pdfReqYSize + 0.5);
+        *pnReqYSize = static_cast<int>( floor(*pdfReqYSize + 0.5) );
 
 /* -------------------------------------------------------------------- */
 /*      Clamp within the bounds of the available source data.           */
@@ -949,24 +1015,24 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
         *pnReqXOff + *pnReqXSize > m_poRasterBand->GetXSize() )
     {
         *pnReqXSize = m_poRasterBand->GetXSize() - *pnReqXOff;
-        bModifiedX = TRUE;
+        bModifiedX = true;
     }
     if( *pdfReqXOff + *pdfReqXSize > m_poRasterBand->GetXSize() )
     {
         *pdfReqXSize = m_poRasterBand->GetXSize() - *pdfReqXOff;
-        bModifiedX = TRUE;
+        bModifiedX = true;
     }
 
     if( *pnReqYSize > INT_MAX - *pnReqYOff ||
         *pnReqYOff + *pnReqYSize > m_poRasterBand->GetYSize() )
     {
         *pnReqYSize = m_poRasterBand->GetYSize() - *pnReqYOff;
-        bModifiedY = TRUE;
+        bModifiedY = true;
     }
     if( *pdfReqYOff + *pdfReqYSize > m_poRasterBand->GetYSize() )
     {
         *pdfReqYSize = m_poRasterBand->GetYSize() - *pdfReqYOff;
-        bModifiedY = TRUE;
+        bModifiedY = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -992,18 +1058,23 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      destination buffer coordinates in case the output region is     */
 /*      less than the whole buffer.                                     */
 /* -------------------------------------------------------------------- */
-    double dfDstULX, dfDstULY, dfDstLRX, dfDstLRY;
-    double dfScaleWinToBufX, dfScaleWinToBufY;
+    double dfDstULX = 0.0;
+    double dfDstULY = 0.0;
+    double dfDstLRX = 0.0;
+    double dfDstLRY = 0.0;
 
     SrcToDst( *pdfReqXOff, *pdfReqYOff, dfDstULX, dfDstULY );
     SrcToDst( *pdfReqXOff + *pdfReqXSize, *pdfReqYOff + *pdfReqYSize,
               dfDstLRX, dfDstLRY );
-    //CPLDebug("VRT", "dfDstULX=%g dfDstULY=%g dfDstLRX=%g dfDstLRY=%g",
-    //         dfDstULX, dfDstULY, dfDstLRX, dfDstLRY);
+#if DEBUG_VERBOSE
+    CPLDebug( "VRT", "dfDstULX=%g dfDstULY=%g dfDstLRX=%g dfDstLRY=%g",
+              dfDstULX, dfDstULY, dfDstLRX, dfDstLRY );
+#endif
 
     if( bModifiedX )
     {
-        dfScaleWinToBufX = nBufXSize / (double) nXSize;
+        const double dfScaleWinToBufX =
+            nBufXSize / static_cast<double>( nXSize );
 
         const double dfOutXOff = (dfDstULX - nXOff) * dfScaleWinToBufX+0.001;
         if( dfOutXOff <= 0 )
@@ -1019,7 +1090,7 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
             dfOutRightXOff = INT_MAX;
         *pnOutXSize = (int) ceil(dfOutRightXOff) - *pnOutXOff;
 
-        *pnOutXOff = MAX(0,*pnOutXOff);
+        *pnOutXOff = std::max(0, *pnOutXOff);
         if( *pnOutXSize > INT_MAX - *pnOutXOff ||
             *pnOutXOff + *pnOutXSize > nBufXSize )
             *pnOutXSize = nBufXSize - *pnOutXOff;
@@ -1027,7 +1098,8 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 
     if( bModifiedY )
     {
-        dfScaleWinToBufY = nBufYSize / (double) nYSize;
+        const double dfScaleWinToBufY =
+            nBufYSize / static_cast<double>( nYSize );
 
         const double dfOutYOff = (dfDstULY - nYOff) * dfScaleWinToBufY+0.001;
         if( dfOutYOff <= 0 )
@@ -1035,16 +1107,16 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
         else if( dfOutYOff > INT_MAX )
             *pnOutYOff = INT_MAX;
         else
-            *pnOutYOff = (int) (dfOutYOff);
+            *pnOutYOff = static_cast<int>(dfOutYOff);
         *pnOutYOff = (int) (dfOutYOff);
         double dfOutTopYOff = (dfDstLRY - nYOff) * dfScaleWinToBufY-0.001;
         if( dfOutTopYOff < dfOutYOff )
             return FALSE;
         if( dfOutTopYOff > INT_MAX )
             dfOutTopYOff = INT_MAX;
-        *pnOutYSize = (int) ceil(dfOutTopYOff) - *pnOutYOff;
+        *pnOutYSize = static_cast<int>( ceil(dfOutTopYOff) ) - *pnOutYOff;
 
-        *pnOutYOff = MAX(0,*pnOutYOff);
+        *pnOutYOff = std::max(0, *pnOutYOff);
         if( *pnOutYSize > INT_MAX - *pnOutYOff ||
             *pnOutYOff + *pnOutYSize > nBufYSize )
             *pnOutYSize = nBufYSize - *pnOutYOff;
@@ -1052,8 +1124,8 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 
     if( *pnOutXSize < 1 || *pnOutYSize < 1 )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -1062,15 +1134,16 @@ VRTSimpleSource::GetSrcDstWindow( int nXOff, int nYOff, int nXSize, int nYSize,
 
 int VRTSimpleSource::NeedMaxValAdjustment() const
 {
-    if( m_nMaxValue )
+    if( !m_nMaxValue )
+        return FALSE;
+
+    const char* pszNBITS =
+        m_poRasterBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+    const int nBits = (pszNBITS) ? atoi(pszNBITS) : 0;
+    const int nBandMaxValue = (1 << nBits) - 1;
+    if( nBandMaxValue == 0 || nBandMaxValue > m_nMaxValue )
     {
-        const char* pszNBITS = m_poRasterBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
-        int nBits = (pszNBITS) ? atoi(pszNBITS) : 0;
-        int nBandMaxValue = (1 << nBits) - 1;
-        if( nBandMaxValue == 0 || nBandMaxValue > m_nMaxValue )
-        {
-            return TRUE;
-        }
+        return TRUE;
     }
     return FALSE;
 }
@@ -1089,16 +1162,24 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 
 {
     GDALRasterIOExtraArg sExtraArg;
-
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
     GDALRasterIOExtraArg* psExtraArg = &sExtraArg;
 
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
                           nBufXSize, nBufYSize,
@@ -1125,9 +1206,7 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Actually perform the IO request.                                */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
-
-    if( m_osResampling.size() )
+    if( !m_osResampling.empty() )
     {
         psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
     }
@@ -1141,33 +1220,36 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     psExtraArg->dfXSize = dfReqXSize;
     psExtraArg->dfYSize = dfReqYSize;
 
-    GByte* pabyOut = ((unsigned char *) pData)
-                                + nOutXOff * nPixelSpace
-                                + (GPtrDiff_t)nOutYOff * nLineSpace;
-    eErr =
-        m_poRasterBand->RasterIO( GF_Read,
-                                nReqXOff, nReqYOff, nReqXSize, nReqYSize,
-                                pabyOut,
-                                nOutXSize, nOutYSize,
-                                eBufType, nPixelSpace, nLineSpace, psExtraArg );
+    GByte* pabyOut =
+        static_cast<unsigned char *>(pData)
+        + nOutXOff * nPixelSpace
+        + static_cast<GPtrDiff_t>(nOutYOff) * nLineSpace;
+
+    const CPLErr eErr =
+        m_poRasterBand->RasterIO(
+            GF_Read,
+            nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+            pabyOut,
+            nOutXSize, nOutYSize,
+            eBufType, nPixelSpace, nLineSpace, psExtraArg );
 
     if( NeedMaxValAdjustment() )
     {
-        for(int j=0;j<nOutYSize;j++)
+        for( int j = 0; j < nOutYSize; j++ )
         {
-            for(int i=0;i<nOutXSize;i++)
+            for( int i = 0; i < nOutXSize; i++ )
             {
-                int nVal;
-                GDALCopyWords(pabyOut + j * nLineSpace + i * nPixelSpace,
-                                eBufType, 0,
-                                &nVal, GDT_Int32, 0,
-                                1);
+                int nVal = 0;
+                GDALCopyWords( pabyOut + j * nLineSpace + i * nPixelSpace,
+                               eBufType, 0,
+                               &nVal, GDT_Int32, 0,
+                               1 );
                 if( nVal > m_nMaxValue )
                     nVal = m_nMaxValue;
-                GDALCopyWords(&nVal, GDT_Int32, 0,
-                                pabyOut + j * nLineSpace + i * nPixelSpace,
-                                eBufType, 0,
-                                1);
+                GDALCopyWords( &nVal, GDT_Int32, 0,
+                               pabyOut + j * nLineSpace + i * nPixelSpace,
+                               eBufType, 0,
+                               1);
             }
         }
     }
@@ -1182,11 +1264,20 @@ VRTSimpleSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 double VRTSimpleSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
 {
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
                           nXSize, nYSize,
@@ -1201,9 +1292,9 @@ double VRTSimpleSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
         return 0;
     }
 
-    double dfVal = m_poRasterBand->GetMinimum(pbSuccess);
+    const double dfVal = m_poRasterBand->GetMinimum(pbSuccess);
     if( NeedMaxValAdjustment() && dfVal > m_nMaxValue )
-        dfVal = m_nMaxValue;
+        return m_nMaxValue;
     return dfVal;
 }
 
@@ -1214,11 +1305,20 @@ double VRTSimpleSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
 double VRTSimpleSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
 {
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
                           nXSize, nYSize,
@@ -1233,9 +1333,9 @@ double VRTSimpleSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
         return 0;
     }
 
-    double dfVal = m_poRasterBand->GetMaximum(pbSuccess);
+    const double dfVal = m_poRasterBand->GetMaximum(pbSuccess);
     if( NeedMaxValAdjustment() && dfVal > m_nMaxValue )
-        dfVal = m_nMaxValue;
+        return m_nMaxValue;
     return dfVal;
 }
 
@@ -1243,14 +1343,24 @@ double VRTSimpleSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
 /*                       ComputeRasterMinMax()                          */
 /************************************************************************/
 
-CPLErr VRTSimpleSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
+CPLErr VRTSimpleSource::ComputeRasterMinMax( int nXSize, int nYSize,
+                                             int bApproxOK, double* adfMinMax )
 {
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( !GetSrcDstWindow( 0, 0, nXSize, nYSize,
                           nXSize, nYSize,
@@ -1264,7 +1374,8 @@ CPLErr VRTSimpleSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApprox
         return CE_Failure;
     }
 
-    CPLErr eErr = m_poRasterBand->ComputeRasterMinMax(bApproxOK, adfMinMax);
+    const CPLErr eErr =
+        m_poRasterBand->ComputeRasterMinMax( bApproxOK, adfMinMax );
     if( NeedMaxValAdjustment() )
     {
         if( adfMinMax[0] > m_nMaxValue )
@@ -1279,18 +1390,28 @@ CPLErr VRTSimpleSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApprox
 /*                         ComputeStatistics()                          */
 /************************************************************************/
 
-CPLErr VRTSimpleSource::ComputeStatistics( int nXSize, int nYSize,
-                                      int bApproxOK,
-                                      double *pdfMin, double *pdfMax,
-                                      double *pdfMean, double *pdfStdDev,
-                                      GDALProgressFunc pfnProgress, void *pProgressData )
+CPLErr VRTSimpleSource::ComputeStatistics(
+    int nXSize, int nYSize,
+    int bApproxOK,
+    double *pdfMin, double *pdfMax,
+    double *pdfMean, double *pdfStdDev,
+    GDALProgressFunc pfnProgress, void *pProgressData )
 {
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( NeedMaxValAdjustment() ||
         !GetSrcDstWindow( 0, 0, nXSize, nYSize,
@@ -1305,27 +1426,37 @@ CPLErr VRTSimpleSource::ComputeStatistics( int nXSize, int nYSize,
         return CE_Failure;
     }
 
-    return m_poRasterBand->ComputeStatistics(bApproxOK, pdfMin, pdfMax,
-                                           pdfMean, pdfStdDev,
-                                           pfnProgress, pProgressData);
+    return m_poRasterBand->ComputeStatistics( bApproxOK, pdfMin, pdfMax,
+                                              pdfMean, pdfStdDev,
+                                              pfnProgress, pProgressData );
 }
 
 /************************************************************************/
 /*                            GetHistogram()                            */
 /************************************************************************/
 
-CPLErr VRTSimpleSource::GetHistogram( int nXSize, int nYSize,
-                                  double dfMin, double dfMax,
-                                  int nBuckets, GUIntBig * panHistogram,
-                                  int bIncludeOutOfRange, int bApproxOK,
-                                  GDALProgressFunc pfnProgress, void *pProgressData )
+CPLErr VRTSimpleSource::GetHistogram(
+    int nXSize, int nYSize,
+    double dfMin, double dfMax,
+    int nBuckets, GUIntBig * panHistogram,
+    int bIncludeOutOfRange, int bApproxOK,
+    GDALProgressFunc pfnProgress, void *pProgressData )
 {
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( NeedMaxValAdjustment() ||
         !GetSrcDstWindow( 0, 0, nXSize, nYSize,
@@ -1341,9 +1472,9 @@ CPLErr VRTSimpleSource::GetHistogram( int nXSize, int nYSize,
     }
 
     return m_poRasterBand->GetHistogram( dfMin, dfMax, nBuckets,
-                                       panHistogram,
-                                       bIncludeOutOfRange, bApproxOK,
-                                       pfnProgress, pProgressData );
+                                         panHistogram,
+                                         bIncludeOutOfRange, bApproxOK,
+                                         pfnProgress, pProgressData );
 }
 
 /************************************************************************/
@@ -1351,15 +1482,15 @@ CPLErr VRTSimpleSource::GetHistogram( int nXSize, int nYSize,
 /************************************************************************/
 
 CPLErr VRTSimpleSource::DatasetRasterIO(
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArgIn)
+    int nXOff, int nYOff, int nXSize, int nYSize,
+    void * pData, int nBufXSize, int nBufYSize,
+    GDALDataType eBufType,
+    int nBandCount, int *panBandMap,
+    GSpacing nPixelSpace, GSpacing nLineSpace,
+    GSpacing nBandSpace,
+    GDALRasterIOExtraArg* psExtraArgIn )
 {
-    if (!EQUAL(GetType(), "SimpleSource"))
+    if( !EQUAL(GetType(), "SimpleSource") )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "DatasetRasterIO() not implemented for %s", GetType());
@@ -1367,16 +1498,24 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
     }
 
     GDALRasterIOExtraArg sExtraArg;
-
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
     GDALRasterIOExtraArg* psExtraArg = &sExtraArg;
 
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize,
                           nBufXSize, nBufYSize,
@@ -1388,10 +1527,10 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
     }
 
     GDALDataset* poDS = m_poRasterBand->GetDataset();
-    if (poDS == NULL)
+    if( poDS == NULL )
         return CE_Failure;
 
-    if( m_osResampling.size() )
+    if( !m_osResampling.empty() )
     {
         psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
     }
@@ -1405,35 +1544,43 @@ CPLErr VRTSimpleSource::DatasetRasterIO(
     psExtraArg->dfXSize = dfReqXSize;
     psExtraArg->dfYSize = dfReqYSize;
 
-    GByte* pabyOut = ((unsigned char *) pData)
-                           + nOutXOff * nPixelSpace
-                           + (GPtrDiff_t)nOutYOff * nLineSpace;
-    CPLErr eErr = poDS->RasterIO( GF_Read,
-                           nReqXOff, nReqYOff, nReqXSize, nReqYSize,
-                           pabyOut,
-                           nOutXSize, nOutYSize,
-                           eBufType, nBandCount, panBandMap,
-                           nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
+    GByte* pabyOut =
+        static_cast<unsigned char *>(pData)
+        + nOutXOff * nPixelSpace
+        + (GPtrDiff_t)nOutYOff * nLineSpace;
+    const CPLErr eErr = poDS->RasterIO(
+        GF_Read,
+        nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+        pabyOut,
+        nOutXSize, nOutYSize,
+        eBufType, nBandCount, panBandMap,
+        nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
 
     if( NeedMaxValAdjustment() )
     {
-        for(int k=0;k<nBandCount;k++)
+        for( int k = 0; k < nBandCount; k++ )
         {
-            for(int j=0;j<nOutYSize;j++)
+            for( int j = 0; j < nOutYSize; j++ )
             {
-                for(int i=0;i<nOutXSize;i++)
+                for( int i = 0; i < nOutXSize; i++ )
                 {
-                    int nVal;
-                    GDALCopyWords(pabyOut + k * nBandSpace + j * nLineSpace + i * nPixelSpace,
-                                eBufType, 0,
-                                &nVal, GDT_Int32, 0,
-                                1);
+                    int nVal = 0;
+                    GDALCopyWords(
+                        pabyOut + k * nBandSpace + j * nLineSpace +
+                            i * nPixelSpace,
+                        eBufType, 0,
+                        &nVal, GDT_Int32, 0,
+                        1 );
+
                     if( nVal > m_nMaxValue )
                         nVal = m_nMaxValue;
-                    GDALCopyWords(&nVal, GDT_Int32, 0,
-                                pabyOut + k * nBandSpace + j * nLineSpace + i * nPixelSpace,
-                                eBufType, 0,
-                                1);
+
+                    GDALCopyWords(
+                        &nVal, GDT_Int32, 0,
+                        pabyOut + k * nBandSpace + j * nLineSpace +
+                            i * nPixelSpace,
+                        eBufType, 0,
+                        1 );
                 }
             }
         }
@@ -1461,9 +1608,7 @@ void VRTSimpleSource::SetResampling( const char* pszResampling )
 /*                         VRTAveragedSource()                          */
 /************************************************************************/
 
-VRTAveragedSource::VRTAveragedSource()
-{
-}
+VRTAveragedSource::VRTAveragedSource() {}
 
 /************************************************************************/
 /*                           SerializeToXML()                           */
@@ -1472,7 +1617,7 @@ VRTAveragedSource::VRTAveragedSource()
 CPLXMLNode *VRTAveragedSource::SerializeToXML( const char *pszVRTPath )
 
 {
-    CPLXMLNode *psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
+    CPLXMLNode * const psSrc = VRTSimpleSource::SerializeToXML( pszVRTPath );
 
     if( psSrc == NULL )
         return NULL;
@@ -1489,24 +1634,32 @@ CPLXMLNode *VRTAveragedSource::SerializeToXML( const char *pszVRTPath )
 
 CPLErr
 VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
-                           void *pData, int nBufXSize, int nBufYSize,
-                           GDALDataType eBufType,
-                           GSpacing nPixelSpace,
-                           GSpacing nLineSpace,
-                           GDALRasterIOExtraArg* psExtraArgIn )
+                             void *pData, int nBufXSize, int nBufYSize,
+                             GDALDataType eBufType,
+                             GSpacing nPixelSpace,
+                             GSpacing nLineSpace,
+                             GDALRasterIOExtraArg* psExtraArgIn )
 
 {
     GDALRasterIOExtraArg sExtraArg;
-
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
     GDALRasterIOExtraArg* psExtraArg = &sExtraArg;
 
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                           &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
@@ -1518,9 +1671,8 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /*      Allocate a temporary buffer to whole the full resolution        */
 /*      data from the area of interest.                                 */
 /* -------------------------------------------------------------------- */
-    float *pafSrc;
-
-    pafSrc = (float *) VSI_MALLOC3_VERBOSE(sizeof(float), nReqXSize, nReqYSize);
+    float * const pafSrc = static_cast<float *>(
+        VSI_MALLOC3_VERBOSE(sizeof(float), nReqXSize, nReqYSize) );
     if( pafSrc == NULL )
     {
         return CE_Failure;
@@ -1529,9 +1681,7 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Load it.                                                        */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
-
-    if( m_osResampling.size() )
+    if( !m_osResampling.empty() )
     {
         psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
     }
@@ -1546,10 +1696,11 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     psExtraArg->dfXSize = dfReqXSize;
     psExtraArg->dfYSize = dfReqYSize;
 
-    eErr = m_poRasterBand->RasterIO( GF_Read,
-                                   nReqXOff, nReqYOff, nReqXSize, nReqYSize,
-                                   pafSrc, nReqXSize, nReqYSize, GDT_Float32,
-                                   0, 0, psExtraArg );
+    const CPLErr eErr =
+        m_poRasterBand->RasterIO( GF_Read,
+                                  nReqXOff, nReqYOff, nReqXSize, nReqYSize,
+                                  pafSrc, nReqXSize, nReqYSize, GDT_Float32,
+                                  0, 0, psExtraArg );
 
     if( eErr != CE_None )
     {
@@ -1562,19 +1713,18 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
     for( int iBufLine = nOutYOff; iBufLine < nOutYOff + nOutYSize; iBufLine++ )
     {
-        double  dfYDst;
-
-        dfYDst = (iBufLine / (double) nBufYSize) * nYSize + nYOff;
+        const double dfYDst =
+            (iBufLine / static_cast<double>(nBufYSize) ) * nYSize + nYOff;
 
         for( int iBufPixel = nOutXOff;
              iBufPixel < nOutXOff + nOutXSize;
              iBufPixel++ )
         {
-            double dfXDst;
             double dfXSrcStart, dfXSrcEnd, dfYSrcStart, dfYSrcEnd;
             int    iXSrcStart, iYSrcStart, iXSrcEnd, iYSrcEnd;
 
-            dfXDst = (iBufPixel / (double) nBufXSize) * nXSize + nXOff;
+            const double dfXDst =
+                (iBufPixel / static_cast<double>(nBufXSize)) * nXSize + nXOff;
 
             // Compute the source image rectangle needed for this pixel.
             DstToSrc( dfXDst, dfYDst, dfXSrcStart, dfYSrcStart );
@@ -1582,27 +1732,27 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 
             // Convert to integers, assuming that the center of the source
             // pixel must be in our rect to get included.
-            if (dfXSrcEnd >= dfXSrcStart + 1)
+            if( dfXSrcEnd >= dfXSrcStart + 1 )
             {
-                iXSrcStart = (int) floor(dfXSrcStart+0.5);
-                iXSrcEnd = (int) floor(dfXSrcEnd+0.5);
+                iXSrcStart = static_cast<int>(floor(dfXSrcStart+0.5));
+                iXSrcEnd = static_cast<int>(floor(dfXSrcEnd+0.5));
             }
             else
             {
                 /* If the resampling factor is less than 100%, the distance */
                 /* between the source pixel is < 1, so we stick to nearest */
                 /* neighbour */
-                iXSrcStart = (int) floor(dfXSrcStart);
+                iXSrcStart = static_cast<int>(floor(dfXSrcStart));
                 iXSrcEnd = iXSrcStart + 1;
             }
-            if (dfYSrcEnd >= dfYSrcStart + 1)
+            if( dfYSrcEnd >= dfYSrcStart + 1 )
             {
-                iYSrcStart = (int) floor(dfYSrcStart+0.5);
-                iYSrcEnd = (int) floor(dfYSrcEnd+0.5);
+                iYSrcStart = static_cast<int>(floor(dfYSrcStart+0.5));
+                iYSrcEnd = static_cast<int>(floor(dfYSrcEnd+0.5));
             }
             else
             {
-                iYSrcStart = (int) floor(dfYSrcStart);
+                iYSrcStart = static_cast<int>(floor(dfYSrcStart));
                 iYSrcEnd = iYSrcStart + 1;
             }
 
@@ -1613,7 +1763,7 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
             iYSrcEnd -= nReqYOff;
 
             double dfSum = 0.0;
-            int    nPixelCount = 0;
+            int nPixelCount = 0;
 
             for( int iY = iYSrcStart; iY < iYSrcEnd; iY++ )
             {
@@ -1625,11 +1775,12 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                     if( iX < 0 || iX >= nReqXSize )
                         continue;
 
-                    float fSampledValue = pafSrc[iX + iY * nReqXSize];
-                    if (CPLIsNan(fSampledValue))
+                    const float fSampledValue = pafSrc[iX + iY * nReqXSize];
+                    if( CPLIsNan(fSampledValue) )
                         continue;
 
-                    if( m_bNoDataSet && ARE_REAL_EQUAL(fSampledValue, m_dfNoDataValue))
+                    if( m_bNoDataSet &&
+                        ARE_REAL_EQUAL(fSampledValue, m_dfNoDataValue))
                         continue;
 
                     nPixelCount++;
@@ -1641,17 +1792,18 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                 continue;
 
             // Compute output value.
-            float dfOutputValue = (float) (dfSum / nPixelCount);
+            const float dfOutputValue = static_cast<float>(dfSum / nPixelCount);
 
             // Put it in the output buffer.
-            GByte *pDstLocation;
-
-            pDstLocation = ((GByte *)pData)
+            GByte *pDstLocation =
+                static_cast<GByte *>(pData)
                 + nPixelSpace * iBufPixel
-                + (GPtrDiff_t)nLineSpace * iBufLine;
+                + static_cast<GPtrDiff_t>(nLineSpace) * iBufLine;
 
             if( eBufType == GDT_Byte )
-                *pDstLocation = (GByte) MIN(255,MAX(0,dfOutputValue + 0.5));
+                *pDstLocation =
+                    static_cast<GByte>(
+                        std::min(255.0, std::max(0.0, dfOutputValue + 0.5)) );
             else
                 GDALCopyWords( &dfOutputValue, GDT_Float32, 4,
                                pDstLocation, eBufType, 8, 1 );
@@ -1667,34 +1819,34 @@ VRTAveragedSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /*                             GetMinimum()                             */
 /************************************************************************/
 
-double VRTAveragedSource::GetMinimum( CPL_UNUSED int nXSize,
-                                      CPL_UNUSED int nYSize,
-                                      CPL_UNUSED int *pbSuccess )
+double VRTAveragedSource::GetMinimum( int /* nXSize */,
+                                      int /* nYSize */,
+                                      int *pbSuccess )
 {
     *pbSuccess = FALSE;
-    return 0;
+    return 0.0;
 }
 
 /************************************************************************/
 /*                             GetMaximum()                             */
 /************************************************************************/
 
-double VRTAveragedSource::GetMaximum( CPL_UNUSED int nXSize,
-                                      CPL_UNUSED int nYSize,
-                                      CPL_UNUSED int *pbSuccess )
+double VRTAveragedSource::GetMaximum( int /* nXSize */,
+                                      int /* nYSize */,
+                                      int *pbSuccess )
 {
     *pbSuccess = FALSE;
-    return 0;
+    return 0.0;
 }
 
 /************************************************************************/
 /*                       ComputeRasterMinMax()                          */
 /************************************************************************/
 
-CPLErr VRTAveragedSource::ComputeRasterMinMax( CPL_UNUSED int nXSize,
-                                               CPL_UNUSED int nYSize,
-                                               CPL_UNUSED int bApproxOK,
-                                               CPL_UNUSED double* adfMinMax )
+CPLErr VRTAveragedSource::ComputeRasterMinMax( int /* nXSize */,
+                                               int /* nYSize */,
+                                               int /* bApproxOK */,
+                                               double* /* adfMinMax */)
 {
     return CE_Failure;
 }
@@ -1703,15 +1855,15 @@ CPLErr VRTAveragedSource::ComputeRasterMinMax( CPL_UNUSED int nXSize,
 /*                         ComputeStatistics()                          */
 /************************************************************************/
 
-CPLErr VRTAveragedSource::ComputeStatistics( CPL_UNUSED int nXSize,
-                                             CPL_UNUSED int nYSize,
-                                             CPL_UNUSED int bApproxOK,
-                                             CPL_UNUSED double *pdfMin,
-                                             CPL_UNUSED double *pdfMax,
-                                             CPL_UNUSED double *pdfMean,
-                                             CPL_UNUSED double *pdfStdDev,
-                                             CPL_UNUSED GDALProgressFunc pfnProgress,
-                                             CPL_UNUSED void *pProgressData )
+CPLErr VRTAveragedSource::ComputeStatistics( int /* nXSize */,
+                                             int /* nYSize */,
+                                             int /* bApproxOK */,
+                                             double * /* pdfMin */,
+                                             double * /* pdfMax */,
+                                             double * /* pdfMean */,
+                                             double * /* pdfStdDev */,
+                                             GDALProgressFunc /* pfnProgress */,
+                                             void * /* pProgressData */ )
 {
     return CE_Failure;
 }
@@ -1720,16 +1872,16 @@ CPLErr VRTAveragedSource::ComputeStatistics( CPL_UNUSED int nXSize,
 /*                            GetHistogram()                            */
 /************************************************************************/
 
-CPLErr VRTAveragedSource::GetHistogram( CPL_UNUSED int nXSize,
-                                        CPL_UNUSED int nYSize,
-                                        CPL_UNUSED double dfMin,
-                                        CPL_UNUSED double dfMax,
-                                        CPL_UNUSED int nBuckets,
-                                        CPL_UNUSED GUIntBig * panHistogram,
-                                        CPL_UNUSED int bIncludeOutOfRange,
-                                        CPL_UNUSED int bApproxOK,
-                                        CPL_UNUSED GDALProgressFunc pfnProgress,
-                                        CPL_UNUSED void *pProgressData )
+CPLErr VRTAveragedSource::GetHistogram( int /* nXSize */,
+                                        int /* nYSize */,
+                                        double /* dfMin */,
+                                        double /* dfMax */,
+                                        int /* nBuckets */,
+                                        GUIntBig * /* panHistogram */,
+                                        int /* bIncludeOutOfRange */,
+                                        int /* bApproxOK */,
+                                        GDALProgressFunc /* pfnProgress */,
+                                        void * /* pProgressData */)
 {
     return CE_Failure;
 }
@@ -1744,63 +1896,57 @@ CPLErr VRTAveragedSource::GetHistogram( CPL_UNUSED int nXSize,
 /*                          VRTComplexSource()                          */
 /************************************************************************/
 
-VRTComplexSource::VRTComplexSource()
-
-{
-    m_eScalingType = VRT_SCALING_NONE;
-    m_dfScaleOff = 0.0;
-    m_dfScaleRatio = 1.0;
-
-    m_padfLUTInputs = NULL;
-    m_padfLUTOutputs = NULL;
-    m_nLUTItemCount = 0;
-    m_nColorTableComponent = 0;
-
-    m_bSrcMinMaxDefined = FALSE;
-    m_dfSrcMin = 0.0;
-    m_dfSrcMax = 0.0;
-    m_dfDstMin = 0.0;
-    m_dfDstMax = 0.0;
-    m_dfExponent = 1.0;
-}
-
-VRTComplexSource::VRTComplexSource(const VRTComplexSource* poSrcSource,
-                                   double dfXDstRatio, double dfYDstRatio) :
-                        VRTSimpleSource(poSrcSource, dfXDstRatio, dfYDstRatio)
+VRTComplexSource::VRTComplexSource() :
+    m_eScalingType(VRT_SCALING_NONE),
+    m_dfScaleOff(0.0),
+    m_dfScaleRatio(1.0),
+    m_bSrcMinMaxDefined(FALSE),
+    m_dfSrcMin(0.0),
+    m_dfSrcMax(0.0),
+    m_dfDstMin(0.0),
+    m_dfDstMax(0.0),
+    m_dfExponent(1.0),
+    m_nColorTableComponent(0),
+    m_padfLUTInputs(NULL),
+    m_padfLUTOutputs(NULL),
+    m_nLUTItemCount(0)
+{}
+
+VRTComplexSource::VRTComplexSource( const VRTComplexSource* poSrcSource,
+                                    double dfXDstRatio, double dfYDstRatio ) :
+    VRTSimpleSource(poSrcSource, dfXDstRatio, dfYDstRatio),
+    m_eScalingType(poSrcSource->m_eScalingType),
+    m_dfScaleOff(poSrcSource->m_dfScaleOff),
+    m_dfScaleRatio(poSrcSource->m_dfScaleRatio),
+    m_bSrcMinMaxDefined(poSrcSource->m_bSrcMinMaxDefined),
+    m_dfSrcMin(poSrcSource->m_dfSrcMin),
+    m_dfSrcMax(poSrcSource->m_dfSrcMax),
+    m_dfDstMin(poSrcSource->m_dfDstMin),
+    m_dfDstMax(poSrcSource->m_dfDstMax),
+    m_dfExponent(poSrcSource->m_dfExponent),
+    m_nColorTableComponent(poSrcSource->m_nColorTableComponent),
+    m_padfLUTInputs(NULL),
+    m_padfLUTOutputs(NULL),
+    m_nLUTItemCount(poSrcSource->m_nLUTItemCount)
 {
-    m_eScalingType = poSrcSource->m_eScalingType;
-    m_dfScaleOff = poSrcSource->m_dfScaleOff;
-    m_dfScaleRatio = poSrcSource->m_dfScaleRatio;
-
-    m_nLUTItemCount = poSrcSource->m_nLUTItemCount;
     if( m_nLUTItemCount )
     {
-        m_padfLUTInputs = (double*)CPLMalloc(sizeof(double) * m_nLUTItemCount);
-        memcpy(m_padfLUTInputs, poSrcSource->m_padfLUTInputs, sizeof(double) * m_nLUTItemCount);
-        m_padfLUTOutputs = (double*)CPLMalloc(sizeof(double) * m_nLUTItemCount);
-        memcpy(m_padfLUTOutputs, poSrcSource->m_padfLUTOutputs, sizeof(double) * m_nLUTItemCount);
-    }
-    else
-    {
-        m_padfLUTInputs = NULL;
-        m_padfLUTOutputs = NULL;
-    }
-    m_nColorTableComponent = poSrcSource->m_nColorTableComponent;
+        m_padfLUTInputs = static_cast<double *>(
+            CPLMalloc(sizeof(double) * m_nLUTItemCount) );
+        memcpy( m_padfLUTInputs, poSrcSource->m_padfLUTInputs,
+                sizeof(double) * m_nLUTItemCount );
 
-    m_bSrcMinMaxDefined = poSrcSource->m_bSrcMinMaxDefined;
-    m_dfSrcMin = poSrcSource->m_dfSrcMin;
-    m_dfSrcMax = poSrcSource->m_dfSrcMax;
-    m_dfDstMin = poSrcSource->m_dfDstMin;
-    m_dfDstMax = poSrcSource->m_dfDstMax;
-    m_dfExponent = poSrcSource->m_dfExponent;
+        m_padfLUTOutputs = static_cast<double *>(
+            CPLMalloc(sizeof(double) * m_nLUTItemCount) );
+        memcpy( m_padfLUTOutputs, poSrcSource->m_padfLUTOutputs,
+                sizeof(double) * m_nLUTItemCount);
+    }
 }
 
 VRTComplexSource::~VRTComplexSource()
 {
-    if (m_padfLUTInputs)
-        VSIFree( m_padfLUTInputs );
-    if (m_padfLUTOutputs)
-        VSIFree( m_padfLUTOutputs );
+    VSIFree( m_padfLUTInputs );
+    VSIFree( m_padfLUTOutputs );
 }
 
 /************************************************************************/
@@ -1820,7 +1966,7 @@ CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
 
     if( m_bNoDataSet )
     {
-        if (CPLIsNan(m_dfNoDataValue))
+        if( CPLIsNan(m_dfNoDataValue) )
             CPLSetXMLValue( psSrc, "NODATA", "nan");
         else
             CPLSetXMLValue( psSrc, "NODATA",
@@ -1857,29 +2003,50 @@ CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
         }
     }
 
-    if ( m_nLUTItemCount )
+    if( m_nLUTItemCount )
     {
         // Make sure we print with sufficient precision to address really close
-        // entries (#6422)
+        // entries (#6422).
         CPLString osLUT;
+        // TODO(schwehr): How is this not a read past the end of the array if
+        // m_nLUTItemCount is 0 or 1?  Added in
+        // https://trac.osgeo.org/gdal/changeset/33779
         if( m_nLUTItemCount > 0 &&
-            CPLString().Printf("%g", m_padfLUTInputs[0]) == CPLString().Printf("%g", m_padfLUTInputs[1]) )
-            osLUT = CPLString().Printf("%.18g:%g", m_padfLUTInputs[0], m_padfLUTOutputs[0]);
+            CPLString().Printf("%g", m_padfLUTInputs[0]) ==
+            CPLString().Printf("%g", m_padfLUTInputs[1]) )
+        {
+            osLUT = CPLString().Printf(
+                "%.18g:%g", m_padfLUTInputs[0], m_padfLUTOutputs[0]);
+        }
         else
-            osLUT = CPLString().Printf("%g:%g", m_padfLUTInputs[0], m_padfLUTOutputs[0]);
-        int i;
-        for ( i = 1; i < m_nLUTItemCount; i++ )
         {
-            if( CPLString().Printf("%g", m_padfLUTInputs[i]) == CPLString().Printf("%g", m_padfLUTInputs[i-1]) ||
-                (i + 1 < m_nLUTItemCount && CPLString().Printf("%g", m_padfLUTInputs[i]) == CPLString().Printf("%g", m_padfLUTInputs[i+1])) )
-                osLUT += CPLString().Printf(",%.18g:%g", m_padfLUTInputs[i], m_padfLUTOutputs[i]);
+            osLUT = CPLString().Printf(
+                "%g:%g", m_padfLUTInputs[0], m_padfLUTOutputs[0]);
+        }
+        for ( int i = 1; i < m_nLUTItemCount; i++ )
+        {
+            if( CPLString().Printf("%g", m_padfLUTInputs[i]) ==
+                CPLString().Printf("%g", m_padfLUTInputs[i-1]) ||
+                (i + 1 < m_nLUTItemCount &&
+                 CPLString().Printf("%g", m_padfLUTInputs[i]) ==
+                 CPLString().Printf("%g", m_padfLUTInputs[i+1])) )
+            {
+                // TODO(schwehr): An explanation of the 18 would be helpful.
+                // Can someone distill the issue down to a quick comment?
+                // https://trac.osgeo.org/gdal/ticket/6422
+                osLUT += CPLString().Printf(
+                    ",%.18g:%g", m_padfLUTInputs[i], m_padfLUTOutputs[i]);
+            }
             else
-                osLUT += CPLString().Printf(",%g:%g", m_padfLUTInputs[i], m_padfLUTOutputs[i]);
+            {
+                osLUT += CPLString().Printf(
+                    ",%g:%g", m_padfLUTInputs[i], m_padfLUTOutputs[i]);
+            }
         }
         CPLSetXMLValue( psSrc, "LUT", osLUT );
     }
 
-    if ( m_nColorTableComponent )
+    if( m_nColorTableComponent )
     {
         CPLSetXMLValue( psSrc, "ColorTableComponent",
                         CPLSPrintf("%d", m_nColorTableComponent) );
@@ -1895,14 +2062,14 @@ CPLXMLNode *VRTComplexSource::SerializeToXML( const char *pszVRTPath )
 CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
 
 {
-    CPLErr eErr;
-
 /* -------------------------------------------------------------------- */
 /*      Do base initialization.                                         */
 /* -------------------------------------------------------------------- */
-    eErr = VRTSimpleSource::XMLInit( psSrc, pszVRTPath );
-    if( eErr != CE_None )
-        return eErr;
+    {
+        const CPLErr eErr = VRTSimpleSource::XMLInit( psSrc, pszVRTPath );
+        if( eErr != CE_None )
+            return eErr;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Complex parameters.                                             */
@@ -1911,47 +2078,48 @@ CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
         || CPLGetXMLValue(psSrc, "ScaleRatio", NULL) != NULL )
     {
         m_eScalingType = VRT_SCALING_LINEAR;
-        m_dfScaleOff = CPLAtof(CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
-        m_dfScaleRatio = CPLAtof(CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
+        m_dfScaleOff = CPLAtof( CPLGetXMLValue(psSrc, "ScaleOffset", "0") );
+        m_dfScaleRatio = CPLAtof( CPLGetXMLValue(psSrc, "ScaleRatio", "1") );
     }
     else if( CPLGetXMLValue(psSrc, "Exponent", NULL) != NULL &&
              CPLGetXMLValue(psSrc, "DstMin", NULL) != NULL &&
              CPLGetXMLValue(psSrc, "DstMax", NULL) != NULL )
     {
         m_eScalingType = VRT_SCALING_EXPONENTIAL;
-        m_dfExponent = CPLAtof(CPLGetXMLValue(psSrc, "Exponent", "1.0") );
+        m_dfExponent = CPLAtof( CPLGetXMLValue(psSrc, "Exponent", "1.0") );
 
         if( CPLGetXMLValue(psSrc, "SrcMin", NULL) != NULL
          && CPLGetXMLValue(psSrc, "SrcMax", NULL) != NULL )
         {
-            m_dfSrcMin = CPLAtof(CPLGetXMLValue(psSrc, "SrcMin", "0.0") );
-            m_dfSrcMax = CPLAtof(CPLGetXMLValue(psSrc, "SrcMax", "0.0") );
+            m_dfSrcMin = CPLAtof( CPLGetXMLValue(psSrc, "SrcMin", "0.0") );
+            m_dfSrcMax = CPLAtof( CPLGetXMLValue(psSrc, "SrcMax", "0.0") );
             m_bSrcMinMaxDefined = TRUE;
         }
 
-        m_dfDstMin = CPLAtof(CPLGetXMLValue(psSrc, "DstMin", "0.0") );
-        m_dfDstMax = CPLAtof(CPLGetXMLValue(psSrc, "DstMax", "0.0") );
+        m_dfDstMin = CPLAtof( CPLGetXMLValue(psSrc, "DstMin", "0.0") );
+        m_dfDstMax = CPLAtof( CPLGetXMLValue(psSrc, "DstMax", "0.0") );
     }
 
     if( CPLGetXMLValue(psSrc, "NODATA", NULL) != NULL )
     {
         m_bNoDataSet = TRUE;
-        m_dfNoDataValue = CPLAtofM(CPLGetXMLValue(psSrc, "NODATA", "0"));
+        m_dfNoDataValue = CPLAtofM( CPLGetXMLValue(psSrc, "NODATA", "0") );
     }
 
     if( CPLGetXMLValue(psSrc, "LUT", NULL) != NULL )
     {
-        int nIndex;
-        char **papszValues = CSLTokenizeString2(CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
+        char **papszValues =
+            CSLTokenizeString2(
+                CPLGetXMLValue(psSrc, "LUT", ""), ",:", CSLT_ALLOWEMPTYTOKENS);
 
-        if (m_nLUTItemCount)
+        if( m_nLUTItemCount )
         {
-            if (m_padfLUTInputs)
+            if( m_padfLUTInputs )
             {
                 VSIFree( m_padfLUTInputs );
                 m_padfLUTInputs = NULL;
             }
-            if (m_padfLUTOutputs)
+            if( m_padfLUTOutputs )
             {
                 VSIFree( m_padfLUTOutputs );
                 m_padfLUTOutputs = NULL;
@@ -1961,16 +2129,18 @@ CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
 
         m_nLUTItemCount = CSLCount(papszValues) / 2;
 
-        m_padfLUTInputs = (double *) VSIMalloc2(m_nLUTItemCount, sizeof(double));
-        if ( !m_padfLUTInputs )
+        m_padfLUTInputs = static_cast<double *>(
+            VSIMalloc2(m_nLUTItemCount, sizeof(double)) );
+        if( !m_padfLUTInputs )
         {
             CSLDestroy(papszValues);
             m_nLUTItemCount = 0;
             return CE_Failure;
         }
 
-        m_padfLUTOutputs = (double *) VSIMalloc2(m_nLUTItemCount, sizeof(double));
-        if ( !m_padfLUTOutputs )
+        m_padfLUTOutputs = static_cast<double *>(
+            VSIMalloc2(m_nLUTItemCount, sizeof(double)) );
+        if( !m_padfLUTOutputs )
         {
             CSLDestroy(papszValues);
             VSIFree( m_padfLUTInputs );
@@ -1979,22 +2149,24 @@ CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
             return CE_Failure;
         }
 
-        for ( nIndex = 0; nIndex < m_nLUTItemCount; nIndex++ )
+        for ( int nIndex = 0; nIndex < m_nLUTItemCount; nIndex++ )
         {
             m_padfLUTInputs[nIndex] = CPLAtof( papszValues[nIndex * 2] );
             m_padfLUTOutputs[nIndex] = CPLAtof( papszValues[nIndex * 2 + 1] );
 
-	    // Enforce the requirement that the LUT input array is monotonically non-decreasing.
-	    if ( nIndex > 0 && m_padfLUTInputs[nIndex] < m_padfLUTInputs[nIndex - 1] )
-	    {
-		CSLDestroy(papszValues);
-		VSIFree( m_padfLUTInputs );
-		VSIFree( m_padfLUTOutputs );
-		m_padfLUTInputs = NULL;
-		m_padfLUTOutputs = NULL;
-		m_nLUTItemCount = 0;
-		return CE_Failure;
-	    }
+            // Enforce the requirement that the LUT input array is
+            // monotonically non-decreasing.
+            if( nIndex > 0 &&
+                m_padfLUTInputs[nIndex] < m_padfLUTInputs[nIndex - 1] )
+            {
+                CSLDestroy(papszValues);
+                VSIFree( m_padfLUTInputs );
+                VSIFree( m_padfLUTOutputs );
+                m_padfLUTInputs = NULL;
+                m_padfLUTOutputs = NULL;
+                m_nLUTItemCount = 0;
+                return CE_Failure;
+            }
         }
 
         CSLDestroy(papszValues);
@@ -2002,7 +2174,8 @@ CPLErr VRTComplexSource::XMLInit( CPLXMLNode *psSrc, const char *pszVRTPath )
 
     if( CPLGetXMLValue(psSrc, "ColorTableComponent", NULL) != NULL )
     {
-        m_nColorTableComponent = atoi(CPLGetXMLValue(psSrc, "ColorTableComponent", "0"));
+        m_nColorTableComponent =
+            atoi( CPLGetXMLValue(psSrc, "ColorTableComponent", "0") );
     }
 
     return CE_None;
@@ -2017,29 +2190,35 @@ VRTComplexSource::LookupValue( double dfInput )
 {
     // Find the index of the first element in the LUT input array that
     // is not smaller than the input value.
-    int i = static_cast<int>(std::lower_bound(m_padfLUTInputs, m_padfLUTInputs + m_nLUTItemCount, dfInput) - m_padfLUTInputs);
+    int i = static_cast<int>(
+        std::lower_bound( m_padfLUTInputs,
+                          m_padfLUTInputs + m_nLUTItemCount,
+                          dfInput)
+        - m_padfLUTInputs );
 
-    if (i == 0)
-	return m_padfLUTOutputs[0];
+    if( i == 0 )
+        return m_padfLUTOutputs[0];
 
     // If the index is beyond the end of the LUT input array, the input
     // value is larger than all the values in the array.
-    if (i == m_nLUTItemCount)
-	return m_padfLUTOutputs[m_nLUTItemCount - 1];
+    if( i == m_nLUTItemCount )
+        return m_padfLUTOutputs[m_nLUTItemCount - 1];
 
-    if (m_padfLUTInputs[i] == dfInput)
-	return m_padfLUTOutputs[i];
+    if( m_padfLUTInputs[i] == dfInput )
+        return m_padfLUTOutputs[i];
 
     // Otherwise, interpolate.
-    return m_padfLUTOutputs[i - 1] + (dfInput - m_padfLUTInputs[i - 1]) *
-	((m_padfLUTOutputs[i] - m_padfLUTOutputs[i - 1]) / (m_padfLUTInputs[i] - m_padfLUTInputs[i - 1]));
+    return
+        m_padfLUTOutputs[i - 1] + (dfInput - m_padfLUTInputs[i - 1]) *
+        ( (m_padfLUTOutputs[i] - m_padfLUTOutputs[i - 1]) /
+          (m_padfLUTInputs[i] - m_padfLUTInputs[i - 1]) );
 }
 
 /************************************************************************/
 /*                         SetLinearScaling()                           */
 /************************************************************************/
 
-void VRTComplexSource::SetLinearScaling(double dfOffset, double dfScale)
+void VRTComplexSource::SetLinearScaling( double dfOffset, double dfScale )
 {
     m_eScalingType = VRT_SCALING_LINEAR;
     m_dfScaleOff = dfOffset;
@@ -2050,11 +2229,11 @@ void VRTComplexSource::SetLinearScaling(double dfOffset, double dfScale)
 /*                         SetPowerScaling()                           */
 /************************************************************************/
 
-void VRTComplexSource::SetPowerScaling(double dfExponentIn,
-                                       double dfSrcMinIn,
-                                       double dfSrcMaxIn,
-                                       double dfDstMinIn,
-                                       double dfDstMaxIn)
+void VRTComplexSource::SetPowerScaling( double dfExponentIn,
+                                        double dfSrcMinIn,
+                                        double dfSrcMaxIn,
+                                        double dfDstMinIn,
+                                        double dfDstMaxIn)
 {
     m_eScalingType = VRT_SCALING_EXPONENTIAL;
     m_dfExponent = dfExponentIn;
@@ -2069,7 +2248,7 @@ void VRTComplexSource::SetPowerScaling(double dfExponentIn,
 /*                    SetColorTableComponent()                          */
 /************************************************************************/
 
-void VRTComplexSource::SetColorTableComponent(int nComponent)
+void VRTComplexSource::SetColorTableComponent( int nComponent )
 {
     m_nColorTableComponent = nComponent;
 }
@@ -2084,20 +2263,28 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                             GDALDataType eBufType,
                             GSpacing nPixelSpace,
                             GSpacing nLineSpace,
-                            GDALRasterIOExtraArg* psExtraArgIn)
+                            GDALRasterIOExtraArg* psExtraArgIn )
 
 {
     GDALRasterIOExtraArg sExtraArg;
-
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
     GDALRasterIOExtraArg* psExtraArg = &sExtraArg;
 
     // The window we will actually request from the source raster band.
-    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
-    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
+    double dfReqXOff = 0.0;
+    double dfReqYOff = 0.0;
+    double dfReqXSize = 0.0;
+    double dfReqYSize = 0.0;
+    int nReqXOff = 0;
+    int nReqYOff = 0;
+    int nReqXSize = 0;
+    int nReqYSize = 0;
 
     // The window we will actual set _within_ the pData buffer.
-    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
+    int nOutXOff = 0;
+    int nOutYOff = 0;
+    int nOutXSize = 0;
+    int nOutYSize = 0;
 
     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                           &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
@@ -2118,7 +2305,7 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
         nOutXOff, nOutYOff, nOutXSize, nOutYSize );
 #endif
 
-    if( m_osResampling.size() )
+    if( !m_osResampling.empty() )
     {
         psExtraArg->eResampleAlg = GDALRasterIOGetResampleAlg(m_osResampling);
     }
@@ -2160,7 +2347,6 @@ VRTComplexSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                 bIsComplex ? GDT_CFloat32 : GDT_Float32);
     }
 
-
     return eErr;
 }
 
@@ -2212,7 +2398,7 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
         }
 
         const GDALRIOResampleAlg eResampleAlgBack = psExtraArg->eResampleAlg;
-        if( m_osResampling.size() )
+        if( !m_osResampling.empty() )
         {
             psExtraArg->eResampleAlg =
                 GDALRasterIOGetResampleAlg(m_osResampling);
@@ -2229,7 +2415,7 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
                                       nWordSize *
                                       static_cast<GSpacing>(nOutXSize),
                                       psExtraArg );
-        if( m_osResampling.size() )
+        if( !m_osResampling.empty() )
             psExtraArg->eResampleAlg = eResampleAlgBack;
 
         if( eErr != CE_None )
@@ -2353,7 +2539,10 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
                     fResult = static_cast<WorkingDT>(m_nMaxValue);
 
                 if( eBufType == GDT_Byte )
-                    *pDstLocation = (GByte) MIN(255,MAX(0,fResult + 0.5));
+                    *pDstLocation = static_cast<GByte>(
+                        std::min(255.0f,
+                                 std::max(0.0f,
+                                          static_cast<float>(fResult) + 0.5f)));
                 else
                     GDALCopyWords( &fResult, eWrkDataType, 0,
                                 pDstLocation, eBufType, 0, 1 );
@@ -2377,7 +2566,7 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
 
                 if( eBufType == GDT_Byte )
                     *pDstLocation = static_cast<GByte>(
-                        MIN(255,MAX(0,afResult[0] + 0.5) ) );
+                        std::min(255.0, std::max(0.0, afResult[0] + 0.5) ) );
                 else
                     GDALCopyWords( afResult, eWrkDataType, 0,
                                    pDstLocation, eBufType, 0, 1 );
@@ -2394,12 +2583,11 @@ CPLErr VRTComplexSource::RasterIOInternal( int nReqXOff, int nReqYOff,
 
                 if( eBufType == GDT_Byte )
                     *pDstLocation = static_cast<GByte>(
-                        MIN(255,MAX(0,fResult + 0.5)) );
+                        std::min(255.0, std::max(0.0, fResult + 0.5)) );
                 else
                     GDALCopyWords( &fResult, eWrkDataType, 0,
                                    pDstLocation, eBufType, 0, 1 );
             }
-
         }
     }
 
@@ -2424,8 +2612,8 @@ CPLErr VRTComplexSource::RasterIOInternal<float>( int nReqXOff, int nReqYOff,
 
 double VRTComplexSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
 {
-    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
-        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
+    if( m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0 )
     {
         return VRTSimpleSource::GetMinimum(nXSize, nYSize, pbSuccess);
     }
@@ -2440,8 +2628,8 @@ double VRTComplexSource::GetMinimum( int nXSize, int nYSize, int *pbSuccess )
 
 double VRTComplexSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
 {
-    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
-        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
+    if( m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0 )
     {
         return VRTSimpleSource::GetMaximum(nXSize, nYSize, pbSuccess);
     }
@@ -2456,10 +2644,11 @@ double VRTComplexSource::GetMaximum( int nXSize, int nYSize, int *pbSuccess )
 
 CPLErr VRTComplexSource::ComputeRasterMinMax( int nXSize, int nYSize, int bApproxOK, double* adfMinMax )
 {
-    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
-        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
+    if( m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0 )
     {
-        return VRTSimpleSource::ComputeRasterMinMax(nXSize, nYSize, bApproxOK, adfMinMax);
+        return VRTSimpleSource::ComputeRasterMinMax( nXSize, nYSize, bApproxOK,
+                                                     adfMinMax);
     }
 
     return CE_Failure;
@@ -2470,19 +2659,20 @@ CPLErr VRTComplexSource::ComputeRasterMinMax( int nXSize, int nYSize, int bAppro
 /************************************************************************/
 
 CPLErr VRTComplexSource::GetHistogram( int nXSize, int nYSize,
-                                  double dfMin, double dfMax,
-                                  int nBuckets, GUIntBig * panHistogram,
-                                  int bIncludeOutOfRange, int bApproxOK,
-                                  GDALProgressFunc pfnProgress, void *pProgressData )
+                                       double dfMin, double dfMax,
+                                       int nBuckets, GUIntBig * panHistogram,
+                                       int bIncludeOutOfRange, int bApproxOK,
+                                       GDALProgressFunc pfnProgress,
+                                       void *pProgressData )
 {
-    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
-        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
+    if( m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0 )
     {
-        return VRTSimpleSource::GetHistogram(nXSize, nYSize,
-                                             dfMin, dfMax, nBuckets,
-                                             panHistogram,
-                                             bIncludeOutOfRange, bApproxOK,
-                                             pfnProgress, pProgressData);
+        return VRTSimpleSource::GetHistogram( nXSize, nYSize,
+                                              dfMin, dfMax, nBuckets,
+                                              panHistogram,
+                                              bIncludeOutOfRange, bApproxOK,
+                                              pfnProgress, pProgressData );
     }
 
     return CE_Failure;
@@ -2493,17 +2683,19 @@ CPLErr VRTComplexSource::GetHistogram( int nXSize, int nYSize,
 /************************************************************************/
 
 CPLErr VRTComplexSource::ComputeStatistics( int nXSize, int nYSize,
-                                      int bApproxOK,
-                                      double *pdfMin, double *pdfMax,
-                                      double *pdfMean, double *pdfStdDev,
-                                      GDALProgressFunc pfnProgress, void *pProgressData )
+                                            int bApproxOK,
+                                            double *pdfMin, double *pdfMax,
+                                            double *pdfMean, double *pdfStdDev,
+                                            GDALProgressFunc pfnProgress,
+                                            void *pProgressData )
 {
-    if (m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
-        m_nLUTItemCount == 0 && m_nColorTableComponent == 0)
+    if( m_dfScaleOff == 0.0 && m_dfScaleRatio == 1.0 &&
+        m_nLUTItemCount == 0 && m_nColorTableComponent == 0 )
     {
-        return VRTSimpleSource::ComputeStatistics(nXSize, nYSize, bApproxOK, pdfMin, pdfMax,
-                                           pdfMean, pdfStdDev,
-                                           pfnProgress, pProgressData);
+        return VRTSimpleSource::ComputeStatistics( nXSize, nYSize, bApproxOK,
+                                                   pdfMin, pdfMax,
+                                                   pdfMean, pdfStdDev,
+                                                   pfnProgress, pProgressData );
     }
 
     return CE_Failure;
@@ -2519,23 +2711,18 @@ CPLErr VRTComplexSource::ComputeStatistics( int nXSize, int nYSize,
 /*                           VRTFuncSource()                            */
 /************************************************************************/
 
-VRTFuncSource::VRTFuncSource()
-
-{
-    pfnReadFunc = NULL;
-    pCBData = NULL;
-    fNoDataValue = (float) VRT_NODATA_UNSET;
-    eType = GDT_Byte;
-}
+VRTFuncSource::VRTFuncSource() :
+    pfnReadFunc(NULL),
+    pCBData(NULL),
+    eType(GDT_Byte),
+    fNoDataValue(static_cast<float>(VRT_NODATA_UNSET))
+{}
 
 /************************************************************************/
 /*                           ~VRTFuncSource()                           */
 /************************************************************************/
 
-VRTFuncSource::~VRTFuncSource()
-
-{
-}
+VRTFuncSource::~VRTFuncSource() {}
 
 /************************************************************************/
 /*                           SerializeToXML()                           */
@@ -2556,7 +2743,7 @@ VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
                          GDALDataType eBufType,
                          GSpacing nPixelSpace,
                          GSpacing nLineSpace,
-                         CPL_UNUSED GDALRasterIOExtraArg* psExtraArg )
+                         GDALRasterIOExtraArg* /* psExtraArg */ )
 {
     if( nPixelSpace*8 == GDALGetDataTypeSize( eBufType )
         && nLineSpace == nPixelSpace * nXSize
@@ -2569,14 +2756,18 @@ VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
     }
     else
     {
-        printf( "%d,%d  %d,%d, %d,%d %d,%d %d,%d\n",
-                (int)nPixelSpace*8, GDALGetDataTypeSize(eBufType),
-                (int)nLineSpace, (int)nPixelSpace * nXSize,
-                nBufXSize, nXSize,
-                nBufYSize, nYSize,
-                (int) eBufType, (int) eType );
         CPLError( CE_Failure, CPLE_AppDefined,
                   "VRTFuncSource::RasterIO() - Irregular request." );
+        CPLDebug("VRT", "Irregular request: %d,%d  %d,%d, %d,%d %d,%d %d,%d",
+                static_cast<int>(nPixelSpace)*8,
+                GDALGetDataTypeSize(eBufType),
+                static_cast<int>(nLineSpace),
+                static_cast<int>(nPixelSpace) * nXSize,
+                nBufXSize, nXSize,
+                nBufYSize, nYSize,
+                static_cast<int>(eBufType),
+                static_cast<int>(eType) );
+
         return CE_Failure;
     }
 }
@@ -2585,9 +2776,9 @@ VRTFuncSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize,
 /*                             GetMinimum()                             */
 /************************************************************************/
 
-double VRTFuncSource::GetMinimum( CPL_UNUSED int nXSize,
-                                  CPL_UNUSED int nYSize,
-                                  CPL_UNUSED CPL_UNUSED int *pbSuccess )
+double VRTFuncSource::GetMinimum( int /* nXSize */,
+                                  int /* nYSize */,
+                                  int *pbSuccess )
 {
     *pbSuccess = FALSE;
     return 0;
@@ -2597,9 +2788,9 @@ double VRTFuncSource::GetMinimum( CPL_UNUSED int nXSize,
 /*                             GetMaximum()                             */
 /************************************************************************/
 
-double VRTFuncSource::GetMaximum( CPL_UNUSED int nXSize,
-                                  CPL_UNUSED int nYSize,
-                                  CPL_UNUSED int *pbSuccess )
+double VRTFuncSource::GetMaximum( int /* nXSize */,
+                                  int /* nYSize */,
+                                  int *pbSuccess )
 {
     *pbSuccess = FALSE;
     return 0;
@@ -2609,10 +2800,10 @@ double VRTFuncSource::GetMaximum( CPL_UNUSED int nXSize,
 /*                       ComputeRasterMinMax()                          */
 /************************************************************************/
 
-CPLErr VRTFuncSource::ComputeRasterMinMax( CPL_UNUSED int nXSize,
-                                           CPL_UNUSED int nYSize,
-                                           CPL_UNUSED int bApproxOK,
-                                           CPL_UNUSED double* adfMinMax )
+CPLErr VRTFuncSource::ComputeRasterMinMax( int /* nXSize */,
+                                           int /* nYSize */,
+                                           int /* bApproxOK */,
+                                           double* /* adfMinMax */ )
 {
     return CE_Failure;
 }
@@ -2621,15 +2812,15 @@ CPLErr VRTFuncSource::ComputeRasterMinMax( CPL_UNUSED int nXSize,
 /*                         ComputeStatistics()                          */
 /************************************************************************/
 
-CPLErr VRTFuncSource::ComputeStatistics( CPL_UNUSED int nXSize,
-                                         CPL_UNUSED int nYSize,
-                                         CPL_UNUSED int bApproxOK,
-                                         CPL_UNUSED double *pdfMin,
-                                         CPL_UNUSED double *pdfMax,
-                                         CPL_UNUSED double *pdfMean,
-                                         CPL_UNUSED double *pdfStdDev,
-                                         CPL_UNUSED GDALProgressFunc pfnProgress,
-                                         CPL_UNUSED void *pProgressData )
+CPLErr VRTFuncSource::ComputeStatistics( int /* nXSize */,
+                                         int /* nYSize */,
+                                         int /* bApproxOK */,
+                                         double * /* pdfMin */,
+                                         double * /* pdfMax */,
+                                         double * /* pdfMean */,
+                                         double * /* pdfStdDev */,
+                                         GDALProgressFunc /* pfnProgress */,
+                                         void * /* pProgressData */ )
 {
     return CE_Failure;
 }
@@ -2638,16 +2829,16 @@ CPLErr VRTFuncSource::ComputeStatistics( CPL_UNUSED int nXSize,
 /*                            GetHistogram()                            */
 /************************************************************************/
 
-CPLErr VRTFuncSource::GetHistogram( CPL_UNUSED int nXSize,
-                                    CPL_UNUSED int nYSize,
-                                    CPL_UNUSED double dfMin,
-                                    CPL_UNUSED double dfMax,
-                                    CPL_UNUSED int nBuckets,
-                                    CPL_UNUSED GUIntBig * panHistogram,
-                                    CPL_UNUSED int bIncludeOutOfRange,
-                                    CPL_UNUSED int bApproxOK,
-                                    CPL_UNUSED GDALProgressFunc pfnProgress,
-                                    CPL_UNUSED void *pProgressData )
+CPLErr VRTFuncSource::GetHistogram( int /* nXSize */,
+                                    int /* nYSize */,
+                                    double /* dfMin */,
+                                    double /* dfMax */,
+                                    int /* nBuckets */,
+                                    GUIntBig * /* panHistogram */,
+                                    int /* bIncludeOutOfRange */,
+                                    int /* bApproxOK */,
+                                    GDALProgressFunc /* pfnProgress */,
+                                    void * /* pProgressData */)
 {
     return CE_Failure;
 }
@@ -2659,11 +2850,12 @@ CPLErr VRTFuncSource::GetHistogram( CPL_UNUSED int nXSize,
 VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
 
 {
-    VRTSource * poSource;
+    VRTSource * poSource = NULL;
 
     if( EQUAL(psChild->pszValue,"AveragedSource")
         || (EQUAL(psChild->pszValue,"SimpleSource")
-            && STARTS_WITH_CI(CPLGetXMLValue(psChild, "Resampling", "Nearest"), "Aver")) )
+            && STARTS_WITH_CI(CPLGetXMLValue(psChild, "Resampling", "Nearest"),
+                              "Aver")) )
     {
         poSource = new VRTAveragedSource();
     }
@@ -2682,9 +2874,10 @@ VRTSource *VRTParseCoreSources( CPLXMLNode *psChild, const char *pszVRTPath )
         return NULL;
     }
 
-    if ( poSource->XMLInit( psChild, pszVRTPath ) == CE_None )
+    if( poSource->XMLInit( psChild, pszVRTPath ) == CE_None )
         return poSource;
 
     delete poSource;
     return NULL;
 }
+/*! @endcond */
diff --git a/frmts/vrt/vrtwarped.cpp b/frmts/vrt/vrtwarped.cpp
index 134e3b1..902d0f8 100644
--- a/frmts/vrt/vrtwarped.cpp
+++ b/frmts/vrt/vrtwarped.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vrtwarped.cpp 34552 2016-07-05 17:47:34Z rouault $
  *
  * Project:  Virtual GDAL Datasets
  * Purpose:  Implementation of VRTWarpedRasterBand *and VRTWarpedDataset.
@@ -28,17 +27,28 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "vrtdataset.h"
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_alg.h"
 #include "gdal_alg_priv.h"
+#include "gdal_priv.h"
 #include "gdalwarper.h"
 
-#include <cassert>
-
-#include <algorithm>
-
-CPL_CVSID("$Id: vrtwarped.cpp 34552 2016-07-05 17:47:34Z rouault $");
+CPL_CVSID("$Id: vrtwarped.cpp 37723 2017-03-16 17:07:53Z rouault $");
 
 /************************************************************************/
 /*                      GDALAutoCreateWarpedVRT()                       */
@@ -100,7 +110,7 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Populate the warp options.                                      */
 /* -------------------------------------------------------------------- */
-    GDALWarpOptions *psWO;
+    GDALWarpOptions *psWO = NULL;
     if( psOptionsIn != NULL )
         psWO = GDALCloneWarpOptions( psOptionsIn );
     else
@@ -111,9 +121,9 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
     psWO->hSrcDS = hSrcDS;
 
     psWO->nBandCount = GDALGetRasterCount( hSrcDS );
-    psWO->panSrcBands = reinterpret_cast<int *>(
+    psWO->panSrcBands = static_cast<int *>(
         CPLMalloc( sizeof(int) * psWO->nBandCount ) );
-    psWO->panDstBands = reinterpret_cast<int *>(
+    psWO->panDstBands = static_cast<int *>(
         CPLMalloc( sizeof(int) * psWO->nBandCount ) );
 
     for( int i = 0; i < psWO->nBandCount; i++ )
@@ -142,8 +152,9 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Figure out the desired output bounds and resolution.            */
 /* -------------------------------------------------------------------- */
-    double adfDstGeoTransform[6];
-    int    nDstPixels, nDstLines;
+    double adfDstGeoTransform[6] = { 0.0 };
+    int nDstPixels = 0;
+    int nDstLines = 0;
     CPLErr eErr =
         GDALSuggestedWarpOutput( hSrcDS, psWO->pfnTransformer,
                                  psWO->pTransformerArg,
@@ -219,7 +230,8 @@ GDALAutoCreateWarpedVRT( GDALDatasetH hSrcDS,
  *
  * @param nLines Height of the virtual warped dataset to create
  *
- * @param padfGeoTransform Geotransform matrix of the virtual warped dataset to create
+ * @param padfGeoTransform Geotransform matrix of the virtual warped dataset
+ * to create
  *
  * @param psOptions Warp options. Must be different from NULL.
  *
@@ -239,18 +251,18 @@ GDALCreateWarpedVRT( GDALDatasetH hSrcDS,
 /* -------------------------------------------------------------------- */
     VRTWarpedDataset *poDS = new VRTWarpedDataset( nPixels, nLines );
 
-    psOptions->hDstDS = (GDALDatasetH) poDS;
+    psOptions->hDstDS = poDS;
 
     poDS->SetGeoTransform( padfGeoTransform );
 
     for( int i = 0; i < psOptions->nBandCount; i++ )
     {
-        GDALRasterBand *poSrcBand = reinterpret_cast<GDALRasterBand *>(
+        GDALRasterBand *poSrcBand = static_cast<GDALRasterBand *>(
             GDALGetRasterBand( hSrcDS, i+1 ) );
 
         poDS->AddBand( poSrcBand->GetRasterDataType(), NULL );
 
-        VRTWarpedRasterBand *poBand = reinterpret_cast<VRTWarpedRasterBand *>(
+        VRTWarpedRasterBand *poBand = static_cast<VRTWarpedRasterBand *>(
             poDS->GetRasterBand( i+1 ) );
         poBand->CopyCommonInfoFrom( poSrcBand );
     }
@@ -265,7 +277,7 @@ GDALCreateWarpedVRT( GDALDatasetH hSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Initialize the warp on the VRTWarpedDataset.                    */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr = poDS->Initialize( psOptions );
+    const CPLErr eErr = poDS->Initialize( psOptions );
     if( eErr == CE_Failure )
     {
          psOptions->hDstDS = NULL;
@@ -273,9 +285,11 @@ GDALCreateWarpedVRT( GDALDatasetH hSrcDS,
          return NULL;
     }
 
-    return reinterpret_cast<GDALDatasetH>( poDS );
+    return poDS;
 }
 
+/*! @cond Doxygen_Suppress */
+
 /************************************************************************/
 /* ==================================================================== */
 /*                          VRTWarpedDataset                            */
@@ -317,21 +331,18 @@ int VRTWarpedDataset::CloseDependentDatasets()
 {
     FlushCache();
 
-    int bHasDroppedRef = VRTDataset::CloseDependentDatasets();
+    bool bHasDroppedRef = CPL_TO_BOOL( VRTDataset::CloseDependentDatasets() );
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup overviews.                                              */
 /* -------------------------------------------------------------------- */
     for( int iOverview = 0; iOverview < m_nOverviewCount; iOverview++ )
     {
-        GDALDatasetH hDS
-            = reinterpret_cast<GDALDatasetH>( m_papoOverviews[iOverview] );
+        GDALDatasetH hDS = m_papoOverviews[iOverview];
 
-        if( GDALDereferenceDataset( hDS ) < 1 )
+        if( GDALReleaseDataset( hDS ) )
         {
-            GDALReferenceDataset( hDS );
-            GDALClose( hDS );
-            bHasDroppedRef = TRUE;
+            bHasDroppedRef = true;
         }
     }
 
@@ -356,10 +367,8 @@ int VRTWarpedDataset::CloseDependentDatasets()
 /* -------------------------------------------------------------------- */
         if( psWO != NULL && psWO->hSrcDS != NULL )
         {
-            if( GDALDereferenceDataset( psWO->hSrcDS ) < 1 )
+            if( GDALReleaseDataset( psWO->hSrcDS ) )
             {
-                GDALReferenceDataset( psWO->hSrcDS );
-                GDALClose( psWO->hSrcDS );
                 bHasDroppedRef = true;
             }
         }
@@ -394,8 +403,8 @@ CPLErr VRTWarpedDataset::SetMetadataItem( const char *pszName, const char *pszVa
                                           const char *pszDomain )
 
 {
-
-    if( (pszDomain == NULL || EQUAL(pszDomain, "")) && EQUAL(pszName, "SrcOvrLevel") )
+    if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
+        EQUAL(pszName, "SrcOvrLevel") )
     {
         const int nOldValue = m_nSrcOvrLevel;
         if( pszValue == NULL || EQUAL(pszValue, "AUTO") )
@@ -428,21 +437,25 @@ CPLErr VRTWarpedDataset::Initialize( void *psWO )
     m_poWarper = new GDALWarpOperation();
 
     GDALWarpOptions* psWO_Dup
-        = GDALCloneWarpOptions(reinterpret_cast<GDALWarpOptions *>( psWO ) );
+        = GDALCloneWarpOptions(static_cast<GDALWarpOptions *>( psWO ) );
 
     /* Avoid errors when adding an alpha band, but source dataset has */
     /* no alpha band (#4571) */
     if (CSLFetchNameValue( psWO_Dup->papszWarpOptions, "INIT_DEST" ) == NULL)
-        psWO_Dup->papszWarpOptions = CSLSetNameValue(psWO_Dup->papszWarpOptions, "INIT_DEST", "0");
+        psWO_Dup->papszWarpOptions =
+            CSLSetNameValue(psWO_Dup->papszWarpOptions, "INIT_DEST", "0");
+
+    CPLErr eErr = m_poWarper->Initialize( psWO_Dup );
 
     // The act of initializing this warped dataset with this warp options
     // will result in our assuming ownership of a reference to the
     // hSrcDS.
 
-    if( reinterpret_cast<GDALWarpOptions *>( psWO )->hSrcDS != NULL )
+    if( eErr == CE_None &&
+        static_cast<GDALWarpOptions *>( psWO )->hSrcDS != NULL )
+    {
         GDALReferenceDataset( psWO_Dup->hSrcDS );
-
-    CPLErr eErr = m_poWarper->Initialize( psWO_Dup );
+    }
 
     GDALDestroyWarpOptions(psWO_Dup);
 
@@ -466,33 +479,34 @@ void VRTWarpedDataset::CreateImplicitOverviews()
     if( psWO->hSrcDS == NULL || GDALGetRasterCount(psWO->hSrcDS) == 0 )
         return;
 
-    GDALDataset* poSrcDS = reinterpret_cast<GDALDataset *>( psWO->hSrcDS );
+    GDALDataset* poSrcDS = static_cast<GDALDataset *>( psWO->hSrcDS );
     const int nOvrCount = poSrcDS->GetRasterBand(1)->GetOverviewCount();
-    for(int iOvr = 0; iOvr < nOvrCount; iOvr++)
+    for( int iOvr = 0; iOvr < nOvrCount; iOvr++ )
     {
-        bool bDeleteSrcOvrDataset = false;
         GDALDataset* poSrcOvrDS = poSrcDS;
         if( m_nSrcOvrLevel < -2 )
         {
             if( iOvr + m_nSrcOvrLevel + 2 >= 0 )
             {
-                bDeleteSrcOvrDataset = true;
-                poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS,
-                                               iOvr + m_nSrcOvrLevel + 2, FALSE, FALSE);
+                poSrcOvrDS =
+                    GDALCreateOverviewDataset( poSrcDS,
+                                               iOvr + m_nSrcOvrLevel + 2,
+                                               FALSE );
             }
         }
         else if( m_nSrcOvrLevel == -2 )
         {
-            bDeleteSrcOvrDataset = true;
-            poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS, iOvr, FALSE, FALSE);
+            poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS, iOvr, FALSE);
         }
         else if( m_nSrcOvrLevel >= 0 )
         {
-            bDeleteSrcOvrDataset = true;
-            poSrcOvrDS = GDALCreateOverviewDataset(poSrcDS, m_nSrcOvrLevel, TRUE, FALSE);
+            poSrcOvrDS = GDALCreateOverviewDataset( poSrcDS, m_nSrcOvrLevel,
+                                                    TRUE );
         }
         if( poSrcOvrDS == NULL )
             break;
+        if( poSrcOvrDS == poSrcDS )
+            poSrcOvrDS->Reference();
 
         const double dfSrcRatioX = static_cast<double>(
             poSrcDS->GetRasterXSize() ) / poSrcOvrDS->GetRasterXSize();
@@ -510,7 +524,7 @@ void VRTWarpedDataset::CreateImplicitOverviews()
         const int nDstLines
             = static_cast<int>(nRasterYSize / dfTargetRatio + 0.5);
 
-        double adfDstGeoTransform[6];
+        double adfDstGeoTransform[6] = { 0.0 };
         GetGeoTransform(adfDstGeoTransform);
         if( adfDstGeoTransform[2] == 0.0 && adfDstGeoTransform[4] == 0.0 )
         {
@@ -529,26 +543,25 @@ void VRTWarpedDataset::CreateImplicitOverviews()
 
         if( nDstPixels < 1 || nDstLines < 1 )
         {
-            if( bDeleteSrcOvrDataset )
-                delete poSrcOvrDS;
+            poSrcOvrDS->ReleaseRef();
             break;
         }
 
 /* -------------------------------------------------------------------- */
 /*      Create transformer and warping options.                         */
 /* -------------------------------------------------------------------- */
-        void *pTransformerArg = GDALCreateSimilarTransformer(psWO->pTransformerArg,
-                                                             dfSrcRatioX,
-                                                             dfSrcRatioY);
+        void *pTransformerArg =
+                         GDALCreateSimilarTransformer( psWO->pTransformerArg,
+                                                       dfSrcRatioX,
+                                                       dfSrcRatioY );
         if( pTransformerArg == NULL )
         {
-            if( bDeleteSrcOvrDataset )
-                delete poSrcOvrDS;
+            poSrcOvrDS->ReleaseRef();
             break;
         }
 
         GDALWarpOptions* psWOOvr = GDALCloneWarpOptions( psWO );
-        psWOOvr->hSrcDS = (GDALDatasetH)poSrcOvrDS;
+        psWOOvr->hSrcDS = poSrcOvrDS;
         psWOOvr->pfnTransformer = psWO->pfnTransformer;
         psWOOvr->pTransformerArg = pTransformerArg;
 
@@ -564,18 +577,11 @@ void VRTWarpedDataset::CreateImplicitOverviews()
 /*      Create the VRT file.                                            */
 /* -------------------------------------------------------------------- */
         GDALDatasetH hDstDS = GDALCreateWarpedVRT(
-            reinterpret_cast<GDALDatasetH>( poSrcOvrDS ),
+            poSrcOvrDS,
             nDstPixels, nDstLines,
             adfDstGeoTransform, psWOOvr );
 
-        if( bDeleteSrcOvrDataset )
-        {
-            if( hDstDS == NULL )
-                delete poSrcOvrDS;
-            else
-                GDALDereferenceDataset(
-                    reinterpret_cast<GDALDatasetH>( poSrcOvrDS ) );
-        }
+        poSrcOvrDS->ReleaseRef();
 
         GDALDestroyWarpOptions(psWOOvr);
 
@@ -586,11 +592,11 @@ void VRTWarpedDataset::CreateImplicitOverviews()
         }
 
         m_nOverviewCount++;
-        m_papoOverviews = reinterpret_cast<VRTWarpedDataset **>(
+        m_papoOverviews = static_cast<VRTWarpedDataset **>(
             CPLRealloc( m_papoOverviews, sizeof(void*) * m_nOverviewCount ) );
 
         m_papoOverviews[m_nOverviewCount-1]
-            = reinterpret_cast<VRTWarpedDataset *>( hDstDS );
+            = static_cast<VRTWarpedDataset *>( hDstDS );
     }
 }
 
@@ -605,7 +611,7 @@ char** VRTWarpedDataset::GetFileList()
     if( m_poWarper != NULL )
     {
         const GDALWarpOptions *psWO = m_poWarper->GetOptions();
-        const char* pszFilename;
+        const char* pszFilename = NULL;
 
         if( psWO->hSrcDS != NULL &&
             (pszFilename =
@@ -622,6 +628,24 @@ char** VRTWarpedDataset::GetFileList()
     return papszFileList;
 }
 
+/************************************************************************/
+/*                      SetApplyVerticalShiftGrid()                     */
+/************************************************************************/
+
+void  VRTWarpedDataset::SetApplyVerticalShiftGrid(const char* pszVGrids,
+                                               int bInverse,
+                                               double dfToMeterSrc,
+                                               double dfToMeterDest,
+                                               char** papszOptions )
+{
+    VerticalShiftGrid oVertShiftGrid;
+    oVertShiftGrid.osVGrids = pszVGrids;
+    oVertShiftGrid.bInverse = bInverse;
+    oVertShiftGrid.dfToMeterSrc = dfToMeterSrc;
+    oVertShiftGrid.dfToMeterDest = dfToMeterDest;
+    oVertShiftGrid.aosOptions.Assign(papszOptions,FALSE);
+    m_aoVerticalShiftGrids.push_back(oVertShiftGrid);
+}
 
 
 /************************************************************************/
@@ -635,13 +659,12 @@ typedef struct {
 
     GDALTransformerFunc pfnBaseTransformer;
     void              *pBaseTransformerArg;
-    int                bOwnSubtransformer;
+    bool               bOwnSubtransformer;
 
     double            dfXOverviewFactor;
     double            dfYOverviewFactor;
 } VWOTInfo;
 
-
 static
 void* VRTCreateWarpedOverviewTransformer( GDALTransformerFunc pfnBaseTransformer,
                                           void *pBaseTransformArg,
@@ -665,15 +688,17 @@ static CPLXMLNode *
 VRTSerializeWarpedOverviewTransformer( void *pTransformArg )
 
 {
-    VWOTInfo *psInfo = reinterpret_cast<VWOTInfo *>( pTransformArg );
+    VWOTInfo *psInfo = static_cast<VWOTInfo *>( pTransformArg );
 
     CPLXMLNode *psTree
         = CPLCreateXMLNode( NULL, CXT_Element, "WarpedOverviewTransformer" );
 
-    CPLCreateXMLElementAndValue( psTree, "XFactor",
-                                 CPLString().Printf("%g",psInfo->dfXOverviewFactor) );
-    CPLCreateXMLElementAndValue( psTree, "YFactor",
-                                 CPLString().Printf("%g",psInfo->dfYOverviewFactor) );
+    CPLCreateXMLElementAndValue(
+        psTree, "XFactor",
+        CPLString().Printf("%g",psInfo->dfXOverviewFactor) );
+    CPLCreateXMLElementAndValue(
+        psTree, "YFactor",
+        CPLString().Printf("%g",psInfo->dfYOverviewFactor) );
 
 /* -------------------------------------------------------------------- */
 /*      Capture underlying transformer.                                 */
@@ -683,7 +708,7 @@ VRTSerializeWarpedOverviewTransformer( void *pTransformArg )
 
     CPLXMLNode *psTransformer
         = GDALSerializeTransformer( psInfo->pfnBaseTransformer,
-                                              psInfo->pBaseTransformerArg );
+                                    psInfo->pBaseTransformerArg );
     if( psTransformer != NULL )
         CPLAddXMLChild( psTransformerContainer, psTransformer );
 
@@ -695,9 +720,9 @@ VRTSerializeWarpedOverviewTransformer( void *pTransformArg )
 /************************************************************************/
 
 static void VRTWarpedOverviewTransformerOwnsSubtransformer( void *pTransformArg,
-                                                          int bOwnFlag )
+                                                            bool bOwnFlag )
 {
-    VWOTInfo *psInfo = reinterpret_cast<VWOTInfo *>( pTransformArg );
+    VWOTInfo *psInfo = static_cast<VWOTInfo *>( pTransformArg );
 
     psInfo->bOwnSubtransformer = bOwnFlag;
 }
@@ -709,20 +734,20 @@ static void VRTWarpedOverviewTransformerOwnsSubtransformer( void *pTransformArg,
 void* VRTDeserializeWarpedOverviewTransformer( CPLXMLNode *psTree )
 
 {
-    double dfXOverviewFactor = CPLAtof(CPLGetXMLValue( psTree, "XFactor",  "1" ));
-    double dfYOverviewFactor = CPLAtof(CPLGetXMLValue( psTree, "YFactor",  "1" ));
-    CPLXMLNode *psContainer;
+    const double dfXOverviewFactor =
+        CPLAtof(CPLGetXMLValue( psTree, "XFactor",  "1" ));
+    const double dfYOverviewFactor =
+        CPLAtof(CPLGetXMLValue( psTree, "YFactor",  "1" ));
     GDALTransformerFunc pfnBaseTransform = NULL;
     void *pBaseTransformerArg = NULL;
 
-    psContainer = CPLGetXMLNode( psTree, "BaseTransformer" );
+    CPLXMLNode *psContainer = CPLGetXMLNode( psTree, "BaseTransformer" );
 
     if( psContainer != NULL && psContainer->psChild != NULL )
     {
         GDALDeserializeTransformer( psContainer->psChild,
                                     &pfnBaseTransform,
                                     &pBaseTransformerArg );
-
     }
 
     if( pfnBaseTransform == NULL )
@@ -738,7 +763,7 @@ void* VRTDeserializeWarpedOverviewTransformer( CPLXMLNode *psTree )
                                                            pBaseTransformerArg,
                                                            dfXOverviewFactor,
                                                            dfYOverviewFactor );
-        VRTWarpedOverviewTransformerOwnsSubtransformer( pApproxCBData, TRUE );
+        VRTWarpedOverviewTransformerOwnsSubtransformer( pApproxCBData, true );
 
         return pApproxCBData;
     }
@@ -759,15 +784,17 @@ void* VRTCreateWarpedOverviewTransformer( GDALTransformerFunc pfnBaseTransformer
     if (pfnBaseTransformer == NULL)
         return NULL;
 
-    VWOTInfo *psSCTInfo = reinterpret_cast<VWOTInfo*>(
+    VWOTInfo *psSCTInfo = static_cast<VWOTInfo*>(
         CPLMalloc( sizeof(VWOTInfo) ) );
     psSCTInfo->pfnBaseTransformer = pfnBaseTransformer;
     psSCTInfo->pBaseTransformerArg = pBaseTransformerArg;
     psSCTInfo->dfXOverviewFactor = dfXOverviewFactor;
     psSCTInfo->dfYOverviewFactor = dfYOverviewFactor;
-    psSCTInfo->bOwnSubtransformer = FALSE;
+    psSCTInfo->bOwnSubtransformer = false;
 
-    memcpy( psSCTInfo->sTI.abySignature, GDAL_GTI2_SIGNATURE, strlen(GDAL_GTI2_SIGNATURE) );
+    memcpy( psSCTInfo->sTI.abySignature,
+            GDAL_GTI2_SIGNATURE,
+            strlen(GDAL_GTI2_SIGNATURE) );
     psSCTInfo->sTI.pszClassName = "VRTWarpedOverviewTransformer";
     psSCTInfo->sTI.pfnTransform = VRTWarpedOverviewTransform;
     psSCTInfo->sTI.pfnCleanup = VRTDestroyWarpedOverviewTransformer;
@@ -784,7 +811,7 @@ void* VRTCreateWarpedOverviewTransformer( GDALTransformerFunc pfnBaseTransformer
 static
 void VRTDestroyWarpedOverviewTransformer(void* pTransformArg)
 {
-    VWOTInfo *psInfo = reinterpret_cast<VWOTInfo *>( pTransformArg );
+    VWOTInfo *psInfo = static_cast<VWOTInfo *>( pTransformArg );
 
     if( psInfo->bOwnSubtransformer )
         GDALDestroyTransformer( psInfo->pBaseTransformerArg );
@@ -803,7 +830,7 @@ int VRTWarpedOverviewTransform( void *pTransformArg, int bDstToSrc,
                                 int *panSuccess )
 
 {
-    VWOTInfo *psInfo = reinterpret_cast<VWOTInfo *>( pTransformArg );
+    VWOTInfo *psInfo = static_cast<VWOTInfo *>( pTransformArg );
 
     if( bDstToSrc )
     {
@@ -814,10 +841,11 @@ int VRTWarpedOverviewTransform( void *pTransformArg, int bDstToSrc,
         }
     }
 
-    int bSuccess = psInfo->pfnBaseTransformer( psInfo->pBaseTransformerArg,
-                                           bDstToSrc,
-                                           nPointCount, padfX, padfY, padfZ,
-                                           panSuccess );
+    const int bSuccess =
+        psInfo->pfnBaseTransformer( psInfo->pBaseTransformerArg,
+                                    bDstToSrc,
+                                    nPointCount, padfX, padfY, padfZ,
+                                    panSuccess );
 
     if( !bDstToSrc )
     {
@@ -840,11 +868,11 @@ int VRTWarpedOverviewTransform( void *pTransformArg, int bDstToSrc,
 /************************************************************************/
 
 CPLErr
-VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
+VRTWarpedDataset::IBuildOverviews( const char * /* pszResampling */,
                                    int nOverviews,
                                    int *panOverviewList,
-                                   CPL_UNUSED int nListBands,
-                                   CPL_UNUSED int *panBandList,
+                                   int /* nListBands */,
+                                   int * /* panBandList */,
                                    GDALProgressFunc pfnProgress,
                                    void * pProgressData )
 {
@@ -865,18 +893,19 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
 /*      which are new.                                                  */
 /* -------------------------------------------------------------------- */
     int nNewOverviews = 0;
-    int *panNewOverviewList = reinterpret_cast<int *>(
+    int *panNewOverviewList = static_cast<int *>(
         CPLCalloc( sizeof(int), nOverviews ) );
     for( int i = 0; i < nOverviews; i++ )
     {
         for( int j = 0; j < m_nOverviewCount; j++ )
         {
-            GDALDataset *poOverview = m_papoOverviews[j];
+            GDALDataset * const poOverview = m_papoOverviews[j];
 
-            int nOvFactor = GDALComputeOvFactor(poOverview->GetRasterXSize(),
-                                            GetRasterXSize(),
-                                            poOverview->GetRasterYSize(),
-                                            GetRasterYSize());
+            const int nOvFactor =
+                GDALComputeOvFactor( poOverview->GetRasterXSize(),
+                                     GetRasterXSize(),
+                                     poOverview->GetRasterYSize(),
+                                     GetRasterYSize() );
 
             if( nOvFactor == panOverviewList[i]
                 || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
@@ -918,7 +947,8 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
             if( m_papoOverviews[j]->GetRasterXSize() > nOXSize &&
                 m_papoOverviews[j]->m_poWarper->GetOptions()->pfnTransformer !=
                                                 VRTWarpedOverviewTransform &&
-                m_papoOverviews[j]->GetRasterXSize() < poBaseDataset->GetRasterXSize() )
+                m_papoOverviews[j]->GetRasterXSize() <
+                poBaseDataset->GetRasterXSize() )
             {
                 poBaseDataset = m_papoOverviews[j];
             }
@@ -932,8 +962,8 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
 
         for( int iBand = 0; iBand < GetRasterCount(); iBand++ )
         {
-            GDALRasterBand *poOldBand = GetRasterBand(iBand+1);
-            VRTWarpedRasterBand *poNewBand =
+            GDALRasterBand * const poOldBand = GetRasterBand(iBand+1);
+            VRTWarpedRasterBand * const poNewBand =
                 new VRTWarpedRasterBand( poOverviewDS, iBand+1,
                                          poOldBand->GetRasterDataType() );
 
@@ -974,11 +1004,10 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
         }
 
         m_nOverviewCount++;
-        m_papoOverviews = reinterpret_cast<VRTWarpedDataset **>(
+        m_papoOverviews = static_cast<VRTWarpedDataset **>(
             CPLRealloc( m_papoOverviews, sizeof(void*) * m_nOverviewCount ) );
 
         m_papoOverviews[m_nOverviewCount-1] = poOverviewDS;
-
     }
 
     CPLFree( panNewOverviewList );
@@ -993,6 +1022,8 @@ VRTWarpedDataset::IBuildOverviews( CPL_UNUSED const char *pszResampling,
     return eErr;
 }
 
+/*! @endcond */
+
 /************************************************************************/
 /*                      GDALInitializeWarpedVRT()                       */
 /************************************************************************/
@@ -1023,6 +1054,8 @@ GDALInitializeWarpedVRT( GDALDatasetH hDS, GDALWarpOptions *psWO )
     return reinterpret_cast<VRTWarpedDataset *>( hDS )->Initialize( psWO );
 }
 
+/*! @cond Doxygen_Suppress */
+
 /************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
@@ -1036,22 +1069,25 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
 /*      band initializers can get it from the dataset object when       */
 /*      they are created.                                               */
 /* -------------------------------------------------------------------- */
-    m_nBlockXSize = atoi(CPLGetXMLValue(psTree,"BlockXSize","512"));
-    m_nBlockYSize = atoi(CPLGetXMLValue(psTree,"BlockYSize","128"));
+    m_nBlockXSize = atoi(CPLGetXMLValue(psTree, "BlockXSize", "512"));
+    m_nBlockYSize = atoi(CPLGetXMLValue(psTree, "BlockYSize", "128"));
 
 /* -------------------------------------------------------------------- */
 /*      Initialize all the general VRT stuff.  This will even           */
 /*      create the VRTWarpedRasterBands and initialize them.            */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr = VRTDataset::XMLInit( psTree, pszVRTPathIn );
+    {
+        const CPLErr eErr = VRTDataset::XMLInit( psTree, pszVRTPathIn );
 
-    if( eErr != CE_None )
-        return eErr;
+        if( eErr != CE_None )
+            return eErr;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Find the GDALWarpOptions XML tree.                              */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psOptionsTree = CPLGetXMLNode( psTree, "GDALWarpOptions" );
+    CPLXMLNode * const psOptionsTree =
+        CPLGetXMLNode( psTree, "GDALWarpOptions" );
     if( psOptionsTree == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1069,7 +1105,7 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
 
     const char *pszRelativePath = CPLGetXMLValue(psOptionsTree,
                                                  "SourceDataset", "" );
-    char *pszAbsolutePath;
+    char *pszAbsolutePath = NULL;
 
     if( bRelativeToVRT )
         pszAbsolutePath =
@@ -1091,10 +1127,11 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
 
     /* Avoid errors when adding an alpha band, but source dataset has */
     /* no alpha band (#4571) */
-    if (CSLFetchNameValue( psWO->papszWarpOptions, "INIT_DEST" ) == NULL)
-        psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions, "INIT_DEST", "0");
+    if( CSLFetchNameValue( psWO->papszWarpOptions, "INIT_DEST" ) == NULL )
+        psWO->papszWarpOptions =
+            CSLSetNameValue(psWO->papszWarpOptions, "INIT_DEST", "0");
 
-    this->eAccess = GA_Update;
+    eAccess = GA_Update;
 
     if( psWO->hDstDS != NULL )
     {
@@ -1105,11 +1142,88 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
     psWO->hDstDS = this;
 
 /* -------------------------------------------------------------------- */
+/*      Deserialize vertical shift grids.                               */
+/* -------------------------------------------------------------------- */
+    CPLXMLNode* psIter = psTree->psChild;
+    for( ; psWO->hSrcDS != NULL && psIter != NULL; psIter = psIter->psNext )
+    {
+        if( psIter->eType != CXT_Element ||
+            !EQUAL(psIter->pszValue, "VerticalShiftGrids") )
+        {
+            continue;
+        }
+        const char* pszVGrids = CPLGetXMLValue(psIter, "Grids", NULL);
+        if( pszVGrids )
+        {
+            int bInverse = CSLTestBoolean(
+                CPLGetXMLValue(psIter, "Inverse", "FALSE") );
+            double dfToMeterSrc = CPLAtof(
+                CPLGetXMLValue( psIter, "ToMeterSrc", "1.0") );
+            double dfToMeterDest = CPLAtof(
+                CPLGetXMLValue( psIter, "ToMeterDest", "1.0") );
+            char** papszOptions = NULL;
+            CPLXMLNode* psIter2 = psIter->psChild;
+            for( ; psIter2 != NULL; psIter2 = psIter2->psNext )
+            {
+                if( psIter2->eType != CXT_Element ||
+                    !EQUAL(psIter2->pszValue, "Option") )
+                {
+                    continue;
+                }
+                const char* pszName = CPLGetXMLValue(psIter2, "name", NULL);
+                const char* pszValue = CPLGetXMLValue(psIter2, NULL, NULL);
+                if( pszName && pszValue )
+                {
+                    papszOptions = CSLSetNameValue(papszOptions, pszName,
+                                                   pszValue);
+                }
+            }
+            SetApplyVerticalShiftGrid(pszVGrids, bInverse,
+                                      dfToMeterSrc, dfToMeterDest,
+                                      papszOptions );
+            int bError = FALSE;
+            GDALDatasetH hGridDataset =
+                GDALOpenVerticalShiftGrid(pszVGrids, &bError);
+            if( bError && hGridDataset == NULL )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                            "Cannot open %s. Source dataset will no "
+                            "be vertically adjusted regarding "
+                            "vertical datum", pszVGrids);
+            }
+            else if( hGridDataset != NULL )
+            {
+                // Transform from source vertical datum to WGS84
+                GDALDatasetH hTmpDS = GDALApplyVerticalShiftGrid(
+                    psWO->hSrcDS, hGridDataset, bInverse,
+                    dfToMeterSrc, dfToMeterDest, papszOptions );
+                GDALReleaseDataset(hGridDataset);
+                if( hTmpDS == NULL )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "Source dataset will no "
+                            "be vertically adjusted regarding "
+                            "vertical datum %s", pszVGrids);
+                }
+                else
+                {
+                    CPLDebug("GDALWARP", "Adjusting source dataset "
+                            "with vertical datum using %s", pszVGrids);
+                    GDALReleaseDataset(psWO->hSrcDS);
+                    psWO->hSrcDS = hTmpDS;
+                }
+            }
+
+            CSLDestroy(papszOptions);
+        }
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Instantiate the warp operation.                                 */
 /* -------------------------------------------------------------------- */
     m_poWarper = new GDALWarpOperation();
 
-    eErr = m_poWarper->Initialize( psWO );
+    const CPLErr eErr = m_poWarper->Initialize( psWO );
     if( eErr != CE_None)
     {
 /* -------------------------------------------------------------------- */
@@ -1150,10 +1264,10 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
 
     CreateImplicitOverviews();
 
-    /* OverviewList is historical, and quite inefficient, since it uses */
-    /* the full resolution source dataset, so only build it afterwards */
+    // OverviewList is historical, and quite inefficient, since it uses
+    // the full resolution source dataset, so only build it afterwards.
     char **papszTokens = CSLTokenizeString(
-        CPLGetXMLValue( psTree, "OverviewList", "" ));
+        CPLGetXMLValue( psTree, "OverviewList", "" ) );
 
     for( int iOverview = 0;
          papszTokens != NULL && papszTokens[iOverview] != NULL;
@@ -1164,8 +1278,9 @@ CPLErr VRTWarpedDataset::XMLInit( CPLXMLNode *psTree, const char *pszVRTPathIn )
         if (nOvFactor > 0)
             BuildOverviews( "NEAREST", 1, &nOvFactor, 0, NULL, NULL, NULL );
         else
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Bad value for overview factor : %s", papszTokens[iOverview]);
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Bad value for overview factor : %s", papszTokens[iOverview] );
     }
 
     CSLDestroy( papszTokens );
@@ -1211,21 +1326,19 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPathIn )
             GDALGetRasterCount(m_poWarper->GetOptions()->hSrcDS) > 0 )
         {
             nSrcDSOvrCount
-                = reinterpret_cast<GDALDataset*>(
+                = static_cast<GDALDataset*>(
                     m_poWarper->GetOptions()->hSrcDS)->
                 GetRasterBand(1)->GetOverviewCount();
         }
 
-        char *pszOverviewList;
         if( m_nOverviewCount != nSrcDSOvrCount )
         {
-            const size_t nLen = m_nOverviewCount*8 + 10;
-            pszOverviewList = reinterpret_cast<char *>(
-                CPLMalloc( nLen ) );
+            const size_t nLen = m_nOverviewCount * 8 + 10;
+            char *pszOverviewList = static_cast<char *>( CPLMalloc( nLen ) );
             pszOverviewList[0] = '\0';
             for( int iOverview = 0; iOverview < m_nOverviewCount; iOverview++ )
             {
-                int nOvFactor = static_cast<int>(
+                const int nOvFactor = static_cast<int>(
                     0.5 + GetRasterXSize()
                     / static_cast<double>(
                         m_papoOverviews[iOverview]->GetRasterXSize() ) );
@@ -1235,7 +1348,8 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPathIn )
                          "%d ", nOvFactor );
             }
 
-            CPLCreateXMLElementAndValue( psTree, "OverviewList", pszOverviewList );
+            CPLCreateXMLElementAndValue( psTree, "OverviewList",
+                                         pszOverviewList );
 
             CPLFree( pszOverviewList );
         }
@@ -1247,28 +1361,67 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPathIn )
     if( m_nSrcOvrLevel != -2 )
     {
         if( m_nSrcOvrLevel < -2 )
-            CPLCreateXMLElementAndValue( psTree, "SrcOvrLevel", CPLSPrintf("AUTO%d", m_nSrcOvrLevel+2) );
+            CPLCreateXMLElementAndValue(
+                psTree, "SrcOvrLevel", CPLSPrintf("AUTO%d", m_nSrcOvrLevel+2) );
         else if( m_nSrcOvrLevel == -1 )
             CPLCreateXMLElementAndValue( psTree, "SrcOvrLevel", "NONE" );
         else
-            CPLCreateXMLElementAndValue( psTree, "SrcOvrLevel", CPLSPrintf("%d", m_nSrcOvrLevel) );
+            CPLCreateXMLElementAndValue(
+                psTree, "SrcOvrLevel", CPLSPrintf("%d", m_nSrcOvrLevel) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Serialize vertical shift grids.                                 */
+/* -------------------------------------------------------------------- */
+    for(size_t i = 0; i < m_aoVerticalShiftGrids.size(); ++i )
+    {
+        CPLXMLNode* psVertShiftGridNode = 
+            CPLCreateXMLNode( psTree, CXT_Element, "VerticalShiftGrids" );
+        CPLCreateXMLElementAndValue(psVertShiftGridNode,
+                                    "Grids",
+                                    m_aoVerticalShiftGrids[i].osVGrids);
+        CPLCreateXMLElementAndValue(psVertShiftGridNode,
+                "Inverse",
+                m_aoVerticalShiftGrids[i].bInverse ? "TRUE" : "FALSE");
+        CPLCreateXMLElementAndValue(psVertShiftGridNode,
+                "ToMeterSrc",
+                CPLSPrintf("%.18g", m_aoVerticalShiftGrids[i].dfToMeterSrc));
+        CPLCreateXMLElementAndValue(psVertShiftGridNode,
+                "ToMeterDest",
+                CPLSPrintf("%.18g", m_aoVerticalShiftGrids[i].dfToMeterDest));
+        for( int j=0; j < m_aoVerticalShiftGrids[i].aosOptions.size(); ++j )
+        {
+            char* pszKey = NULL;
+            const char* pszValue = CPLParseNameValue(
+                m_aoVerticalShiftGrids[i].aosOptions[j], &pszKey);
+            if( pszKey && pszValue )
+            {
+                CPLXMLNode* psOption = CPLCreateXMLElementAndValue(
+                    psVertShiftGridNode,
+                    "Option",
+                    pszValue);
+                CPLCreateXMLNode(
+                    CPLCreateXMLNode( psOption, CXT_Attribute, "name" ),
+                    CXT_Text, pszKey );
+            }
+            CPLFree(pszKey);
+        }
     }
 
 /* ==================================================================== */
 /*      Serialize the warp options.                                     */
 /* ==================================================================== */
-    CPLXMLNode *psWOTree;
-
     if( m_poWarper != NULL )
     {
 /* -------------------------------------------------------------------- */
 /*      We reset the destination dataset name so it doesn't get         */
 /*      written out in the serialize warp options.                      */
 /* -------------------------------------------------------------------- */
-        char *pszSavedName = CPLStrdup(GetDescription());
+        char * const pszSavedName = CPLStrdup(GetDescription());
         SetDescription("");
 
-        psWOTree = GDALSerializeWarpOptions( m_poWarper->GetOptions() );
+        CPLXMLNode * const psWOTree =
+            GDALSerializeWarpOptions( m_poWarper->GetOptions() );
         CPLAddXMLChild( psTree, psWOTree );
 
         SetDescription( pszSavedName );
@@ -1280,7 +1433,7 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPathIn )
 /* -------------------------------------------------------------------- */
         CPLXMLNode *psSDS = CPLGetXMLNode( psWOTree, "SourceDataset" );
         int bRelativeToVRT = FALSE;
-        VSIStatBufL  sStat;
+        VSIStatBufL sStat;
 
         if( VSIStatExL( psSDS->psChild->pszValue, &sStat,
                         VSI_STAT_EXISTS_FLAG) == 0 )
@@ -1308,8 +1461,8 @@ CPLXMLNode *VRTWarpedDataset::SerializeToXML( const char *pszVRTPathIn )
 void VRTWarpedDataset::GetBlockSize( int *pnBlockXSize, int *pnBlockYSize )
 
 {
-    assert( NULL != pnBlockXSize );
-    assert( NULL != pnBlockYSize );
+    CPLAssert( NULL != pnBlockXSize );
+    CPLAssert( NULL != pnBlockYSize );
 
     *pnBlockXSize = m_nBlockXSize;
     *pnBlockYSize = m_nBlockYSize;
@@ -1334,7 +1487,7 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
 /*      Allocate block of memory large enough to hold all the bands     */
 /*      for this block.                                                 */
 /* -------------------------------------------------------------------- */
-    const int nWordSize = (GDALGetDataTypeSize(psWO->eWorkingDataType) / 8);
+    const int nWordSize = GDALGetDataTypeSizeBytes(psWO->eWorkingDataType);
 
     int nReqXSize = m_nBlockXSize;
     if( iBlockX * m_nBlockXSize + nReqXSize > nRasterXSize )
@@ -1348,7 +1501,7 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
     const int nDstBufferSize
         = nReqXSize * nReqYSize * psWO->nBandCount * nWordSize;
 
-    GByte *pabyDstBuffer = reinterpret_cast<GByte *>(
+    GByte *pabyDstBuffer = static_cast<GByte *>(
         VSI_MALLOC_VERBOSE(nDstBufferSize) );
 
     if( pabyDstBuffer == NULL )
@@ -1379,7 +1532,7 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
             const char *pszBandInit
                 = papszInitValues[std::min( iBand, nInitCount - 1 )];
 
-            double adfInitRealImag[2];
+            double adfInitRealImag[2] = { 0.0, 0.0 };
             if( EQUAL(pszBandInit,"NO_DATA")
                 && psWO->padfDstNoDataReal != NULL )
             {
@@ -1397,14 +1550,20 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
 
             if( psWO->eWorkingDataType == GDT_Byte )
                 memset( pBandData,
-                        std::max(0,std::min(255,static_cast<int>( adfInitRealImag[0] ))),
+                        std::max( 0,
+                                  std::min( 255,
+                                            static_cast<int>(
+                                                adfInitRealImag[0] ) ) ),
                         nBandSize);
-            else if( !CPLIsNan(adfInitRealImag[0]) && adfInitRealImag[0] == 0.0 &&
-                     !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
+            else if( !CPLIsNan(adfInitRealImag[0]) &&
+                     adfInitRealImag[0] == 0.0 &&
+                     !CPLIsNan(adfInitRealImag[1]) &&
+                     adfInitRealImag[1] == 0.0 )
             {
                 memset( pBandData, 0, nBandSize );
             }
-            else if( !CPLIsNan(adfInitRealImag[1]) && adfInitRealImag[1] == 0.0 )
+            else if( !CPLIsNan(adfInitRealImag[1]) &&
+                     adfInitRealImag[1] == 0.0 )
             {
                 GDALCopyWords( &adfInitRealImag, GDT_Float64, 0,
                                pBandData,psWO->eWorkingDataType,nWordSize,
@@ -1425,8 +1584,8 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
 /*      Warp into this buffer.                                          */
 /* -------------------------------------------------------------------- */
 
-    CPLErr eErr
-        = m_poWarper->WarpRegionToBuffer(
+    const CPLErr eErr =
+        m_poWarper->WarpRegionToBuffer(
             iBlockX * m_nBlockXSize, iBlockY * m_nBlockYSize,
             nReqXSize, nReqYSize,
             pabyDstBuffer, psWO->eWorkingDataType );
@@ -1452,26 +1611,32 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
             {
                 if( nReqXSize == m_nBlockXSize && nReqYSize == m_nBlockYSize )
                 {
-                    GDALCopyWords( pabyDstBuffer + iBand*m_nBlockXSize*m_nBlockYSize*nWordSize,
-                                psWO->eWorkingDataType, nWordSize,
-                                poBlock->GetDataRef(),
-                                poBlock->GetDataType(),
-                                GDALGetDataTypeSize(poBlock->GetDataType())/8,
-                                m_nBlockXSize * m_nBlockYSize );
+                    GDALCopyWords(
+                        pabyDstBuffer +
+                        iBand*m_nBlockXSize*m_nBlockYSize*nWordSize,
+                        psWO->eWorkingDataType, nWordSize,
+                        poBlock->GetDataRef(),
+                        poBlock->GetDataType(),
+                        GDALGetDataTypeSizeBytes(poBlock->GetDataType()),
+                        m_nBlockXSize * m_nBlockYSize );
                 }
                 else
                 {
                     GByte* pabyBlock = reinterpret_cast<GByte *>(
                         poBlock->GetDataRef() );
-                    const int nDTSize = GDALGetDataTypeSize(poBlock->GetDataType())/8;
+                    const int nDTSize =
+                        GDALGetDataTypeSizeBytes(poBlock->GetDataType());
                     for(int iY=0;iY<nReqYSize;iY++)
                     {
-                        GDALCopyWords( pabyDstBuffer + iBand*nReqXSize*nReqYSize*nWordSize + iY * nReqXSize*nWordSize,
-                                       psWO->eWorkingDataType, nWordSize,
-                                       pabyBlock + iY * m_nBlockXSize * nDTSize,
-                                       poBlock->GetDataType(),
-                                       nDTSize,
-                                       nReqXSize );
+                        GDALCopyWords(
+                            pabyDstBuffer +
+                            iBand*nReqXSize*nReqYSize*nWordSize +
+                            iY * nReqXSize*nWordSize,
+                            psWO->eWorkingDataType, nWordSize,
+                            pabyBlock + iY * m_nBlockXSize * nDTSize,
+                            poBlock->GetDataType(),
+                            nDTSize,
+                            nReqXSize );
                     }
                 }
             }
@@ -1489,11 +1654,9 @@ CPLErr VRTWarpedDataset::ProcessBlock( int iBlockX, int iBlockY )
 /*                              AddBand()                               */
 /************************************************************************/
 
-CPLErr VRTWarpedDataset::AddBand( GDALDataType eType, char **papszOptions )
+CPLErr VRTWarpedDataset::AddBand( GDALDataType eType, char ** /* papszOptions */ )
 
 {
-    UNREFERENCED_PARAM( papszOptions );
-
     SetBand( GetRasterCount() + 1,
              new VRTWarpedRasterBand( this, GetRasterCount() + 1, eType ) );
 
@@ -1516,9 +1679,9 @@ VRTWarpedRasterBand::VRTWarpedRasterBand( GDALDataset *poDSIn, int nBandIn,
 {
     Initialize( poDSIn->GetRasterXSize(), poDSIn->GetRasterYSize() );
 
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
-    this->eAccess = GA_Update;
+    poDS = poDSIn;
+    nBand = nBandIn;
+    eAccess = GA_Update;
 
     reinterpret_cast<VRTWarpedDataset *>( poDS )->GetBlockSize( &nBlockXSize,
                                                                 &nBlockYSize );
@@ -1542,7 +1705,7 @@ VRTWarpedRasterBand::~VRTWarpedRasterBand()
 /************************************************************************/
 
 CPLErr VRTWarpedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
-                                     void * pImage )
+                                        void * pImage )
 
 {
     VRTWarpedDataset *poWDS = reinterpret_cast<VRTWarpedDataset *>( poDS );
@@ -1550,7 +1713,7 @@ CPLErr VRTWarpedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     if( poBlock == NULL )
         return CE_Failure;
 
-    CPLErr eErr = poWDS->ProcessBlock( nBlockXOff, nBlockYOff );
+    const CPLErr eErr = poWDS->ProcessBlock( nBlockXOff, nBlockYOff );
 
     if( eErr == CE_None && pImage != poBlock->GetDataRef() )
     {
@@ -1570,28 +1733,23 @@ CPLErr VRTWarpedRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr VRTWarpedRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
-                                     void * pImage )
+                                         void * pImage )
 
 {
     VRTWarpedDataset *poWDS = reinterpret_cast<VRTWarpedDataset *>( poDS );
 
-    /* This is a bit tricky. In the case we are warping a VRTWarpedDataset */
-    /* with a destination alpha band, IWriteBlock can be called on that alpha */
-    /* band by GDALWarpDstAlphaMasker */
-    /* We don't need to do anything since the data will be kept in the block */
-    /* cache by VRTWarpedRasterBand::IReadBlock */
-    CPLErr eErr;
-    if (poWDS->m_poWarper->GetOptions()->nDstAlphaBand == nBand)
-    {
-        eErr = CE_None;
-    }
-    else
+    // This is a bit tricky. In the case we are warping a VRTWarpedDataset
+    // with a destination alpha band, IWriteBlock can be called on that alpha
+    // band by GDALWarpDstAlphaMasker
+    // We don't need to do anything since the data will be kept in the block
+    // cache by VRTWarpedRasterBand::IReadBlock.
+    if (poWDS->m_poWarper->GetOptions()->nDstAlphaBand != nBand)
     {
         /* Otherwise, call the superclass method, that will fail of course */
-        eErr = VRTRasterBand::IWriteBlock(nBlockXOff, nBlockYOff, pImage);
+        return VRTRasterBand::IWriteBlock(nBlockXOff, nBlockYOff, pImage);
     }
 
-    return eErr;
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1599,7 +1757,7 @@ CPLErr VRTWarpedRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
 /************************************************************************/
 
 CPLErr VRTWarpedRasterBand::XMLInit( CPLXMLNode * psTree,
-                                  const char *pszVRTPathIn )
+                                     const char *pszVRTPathIn )
 
 {
     return VRTRasterBand::XMLInit( psTree, pszVRTPathIn );
@@ -1612,7 +1770,7 @@ CPLErr VRTWarpedRasterBand::XMLInit( CPLXMLNode * psTree,
 CPLXMLNode *VRTWarpedRasterBand::SerializeToXML( const char *pszVRTPathIn )
 
 {
-    CPLXMLNode *psTree = VRTRasterBand::SerializeToXML( pszVRTPathIn );
+    CPLXMLNode * const psTree = VRTRasterBand::SerializeToXML( pszVRTPathIn );
 
 /* -------------------------------------------------------------------- */
 /*      Set subclass.                                                   */
@@ -1631,7 +1789,8 @@ CPLXMLNode *VRTWarpedRasterBand::SerializeToXML( const char *pszVRTPathIn )
 int VRTWarpedRasterBand::GetOverviewCount()
 
 {
-    VRTWarpedDataset *poWDS = reinterpret_cast<VRTWarpedDataset *>( poDS );
+    VRTWarpedDataset * const poWDS =
+        reinterpret_cast<VRTWarpedDataset *>( poDS );
 
     poWDS->CreateImplicitOverviews();
 
@@ -1645,10 +1804,13 @@ int VRTWarpedRasterBand::GetOverviewCount()
 GDALRasterBand *VRTWarpedRasterBand::GetOverview( int iOverview )
 
 {
-    VRTWarpedDataset *poWDS = reinterpret_cast<VRTWarpedDataset *>( poDS );
+    VRTWarpedDataset * const poWDS =
+        reinterpret_cast<VRTWarpedDataset *>( poDS );
 
     if( iOverview < 0 || iOverview >= GetOverviewCount() )
         return NULL;
 
     return poWDS->m_papoOverviews[iOverview]->GetRasterBand( nBand );
 }
+
+/*! @endcond */
diff --git a/frmts/wcs/GNUmakefile b/frmts/wcs/GNUmakefile
index 421e75e..d13e853 100644
--- a/frmts/wcs/GNUmakefile
+++ b/frmts/wcs/GNUmakefile
@@ -3,7 +3,7 @@ include ../../GDALmake.opt
 
 OBJ	=	wcsdataset.o httpdriver.o
 
-CPPFLAGS	:=	 $(CPPFLAGS) 
+CPPFLAGS	:=	 $(CPPFLAGS)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
diff --git a/frmts/wcs/httpdriver.cpp b/frmts/wcs/httpdriver.cpp
index 3500a0e..679a69d 100644
--- a/frmts/wcs/httpdriver.cpp
+++ b/frmts/wcs/httpdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: httpdriver.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  WCS Client Driver
  * Purpose:  Implementation of an HTTP fetching driver.
@@ -34,8 +33,7 @@
 #include "gdal_frmts.h"
 #include "gdal_pam.h"
 
-CPL_CVSID("$Id: httpdriver.cpp 33720 2016-03-15 00:39:53Z goatbar $");
-
+CPL_CVSID("$Id: httpdriver.cpp 35929 2016-10-25 16:09:00Z goatbar $");
 
 /************************************************************************/
 /*               HTTPFetchContentDispositionFilename()                 */
@@ -134,7 +132,8 @@ static GDALDataset *HTTPOpen( GDALOpenInfo * poOpenInfo )
 /*      it.                                                             */
 /* -------------------------------------------------------------------- */
     psResult->pabyData = NULL;
-    psResult->nDataLen = psResult->nDataAlloc = 0;
+    psResult->nDataLen = 0;
+    psResult->nDataAlloc = 0;
 
     CPLHTTPDestroyResult( psResult );
 
@@ -144,7 +143,8 @@ static GDALDataset *HTTPOpen( GDALOpenInfo * poOpenInfo )
     /* suppress errors as not all drivers support /vsimem */
     CPLPushErrorHandler( CPLQuietErrorHandler );
     GDALDataset *poDS = (GDALDataset *)
-        GDALOpenEx( osResultFilename, poOpenInfo->nOpenFlags, NULL,
+        GDALOpenEx( osResultFilename, poOpenInfo->nOpenFlags,
+                    poOpenInfo->papszAllowedDrivers,
                     poOpenInfo->papszOpenOptions, NULL);
     CPLPopErrorHandler();
 
@@ -171,13 +171,13 @@ static GDALDataset *HTTPOpen( GDALOpenInfo * poOpenInfo )
         else
         {
             poDS =  (GDALDataset *)
-                GDALOpenEx( osTempFilename, poOpenInfo->nOpenFlags, NULL,
+                GDALOpenEx( osTempFilename, poOpenInfo->nOpenFlags,
+                            poOpenInfo->papszAllowedDrivers,
                             poOpenInfo->papszOpenOptions, NULL );
             if( VSIUnlink( osTempFilename ) != 0 && poDS != NULL )
                 poDS->MarkSuppressOnClose(); /* VSIUnlink() may not work on windows */
             if( poDS && strcmp(poDS->GetDescription(), osTempFilename) == 0 )
                 poDS->SetDescription(poOpenInfo->pszFilename);
-
         }
     }
     else if( strcmp(poDS->GetDescription(), osResultFilename) == 0 )
diff --git a/frmts/wcs/wcsdataset.cpp b/frmts/wcs/wcsdataset.cpp
index 1d6ecb8..f79436a 100644
--- a/frmts/wcs/wcsdataset.cpp
+++ b/frmts/wcs/wcsdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: wcsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  WCS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WCS.
@@ -35,11 +34,13 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: wcsdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: wcsdataset.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
-/*				WCSDataset				*/
+/*                              WCSDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -85,14 +86,14 @@ class CPL_DLL WCSDataset : public GDALPamDataset
                               int, int *,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
                               GSpacing nBandSpace,
-                              GDALRasterIOExtraArg* psExtraArg);
+                              GDALRasterIOExtraArg* psExtraArg) override;
 
-    int		DescribeCoverage();
+    int         DescribeCoverage();
     int         ExtractGridInfo100();
     int         ExtractGridInfo();
     int         EstablishRasterDetails();
 
-    int         ProcessError( CPLHTTPResult *psResult );
+    static int         ProcessError( CPLHTTPResult *psResult );
     GDALDataset *GDALOpenResult( CPLHTTPResult *psResult );
     void        FlushMemoryResult();
     CPLString   osResultFilename;
@@ -105,17 +106,17 @@ class CPL_DLL WCSDataset : public GDALPamDataset
 
   public:
                 WCSDataset();
-                ~WCSDataset();
+    virtual ~WCSDataset();
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int Identify( GDALOpenInfo * );
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual const char *GetProjectionRef(void);
-    virtual char **GetFileList(void);
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual const char *GetProjectionRef(void) override;
+    virtual char **GetFileList(void) override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char **GetMetadata( const char *pszDomain );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char **GetMetadata( const char *pszDomain ) override;
 };
 
 /************************************************************************/
@@ -139,31 +140,35 @@ class WCSRasterBand : public GDALPamRasterBand
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                              GDALRasterIOExtraArg* psExtraArg );
+                              GDALRasterIOExtraArg* psExtraArg ) override;
 
   public:
 
                    WCSRasterBand( WCSDataset *, int nBand, int iOverview );
-                  ~WCSRasterBand();
+    virtual ~WCSRasterBand();
 
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 
-    virtual int GetOverviewCount();
-    virtual GDALRasterBand *GetOverview(int);
+    virtual int GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview(int) override;
 
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
 };
 
 /************************************************************************/
 /*                           WCSRasterBand()                            */
 /************************************************************************/
 
-WCSRasterBand::WCSRasterBand( WCSDataset *poDSIn, int nBandIn, int iOverviewIn )
-
+WCSRasterBand::WCSRasterBand( WCSDataset *poDSIn, int nBandIn,
+                              int iOverviewIn ) :
+    iOverview(iOverviewIn),
+    nResFactor(1 << (iOverviewIn+1)), // iOverview == -1 is base layer
+    poODS(poDSIn),
+    nOverviewCount(0),
+    papoOverviews(NULL)
 {
     poDS = poDSIn;
-    poODS = poDSIn;
-    this->nBand = nBandIn;
+    nBand = nBandIn;
 
     eDataType = GDALGetDataTypeByName(
         CPLGetXMLValue( poDSIn->psService, "BandType", "Byte" ) );
@@ -171,8 +176,6 @@ WCSRasterBand::WCSRasterBand( WCSDataset *poDSIn, int nBandIn, int iOverviewIn )
 /* -------------------------------------------------------------------- */
 /*      Establish resolution reduction for this overview level.         */
 /* -------------------------------------------------------------------- */
-    this->iOverview = iOverviewIn;
-    nResFactor = 1 << (iOverview+1); // iOverview == -1 is base layer
 
 /* -------------------------------------------------------------------- */
 /*      Establish block size.                                           */
@@ -204,14 +207,13 @@ WCSRasterBand::WCSRasterBand( WCSDataset *poDSIn, int nBandIn, int iOverviewIn )
 /* -------------------------------------------------------------------- */
     if( iOverview == -1 )
     {
-        int i;
-
         nOverviewCount = atoi(CPLGetXMLValue(poODS->psService,"OverviewCount",
                                              "-1"));
         if( nOverviewCount < 0 )
         {
             for( nOverviewCount = 0;
-                 (MAX(nRasterXSize,nRasterYSize) / (1 << nOverviewCount)) > 900;
+                 (std::max(nRasterXSize, nRasterYSize) /
+                  (1 << nOverviewCount)) > 900;
                  nOverviewCount++ ) {}
         }
         else if( nOverviewCount > 30 )
@@ -224,14 +226,9 @@ WCSRasterBand::WCSRasterBand( WCSDataset *poDSIn, int nBandIn, int iOverviewIn )
         papoOverviews = (WCSRasterBand **)
             CPLCalloc( nOverviewCount, sizeof(void*) );
 
-        for( i = 0; i < nOverviewCount; i++ )
+        for( int i = 0; i < nOverviewCount; i++ )
             papoOverviews[i] = new WCSRasterBand( poODS, nBand, i );
     }
-    else
-    {
-        nOverviewCount = 0;
-        papoOverviews = NULL;
-    }
 }
 
 /************************************************************************/
@@ -245,9 +242,7 @@ WCSRasterBand::~WCSRasterBand()
 
     if( nOverviewCount > 0 )
     {
-        int i;
-
-        for( i = 0; i < nOverviewCount; i++ )
+        for( int i = 0; i < nOverviewCount; i++ )
             delete papoOverviews[i];
 
         CPLFree( papoOverviews );
@@ -444,15 +439,20 @@ GDALRasterBand *WCSRasterBand::GetOverview( int iOverviewIn )
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                             WCSDataset()                             */
 /************************************************************************/
 
 WCSDataset::WCSDataset() :
-    bServiceDirty(FALSE), psService(NULL), papszSDSModifiers(NULL),
-    nVersion(0), pszProjection(NULL), pabySavedDataBuffer(NULL),
-    papszHttpOptions(NULL), nMaxCols(-1), nMaxRows(-1)
+    bServiceDirty(FALSE),
+    psService(NULL),
+    papszSDSModifiers(NULL),
+    nVersion(0),
+    pszProjection(NULL),
+    pabySavedDataBuffer(NULL),
+    papszHttpOptions(NULL),
+    nMaxCols(-1),
+    nMaxRows(-1)
 {
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -618,8 +618,8 @@ WCSDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
         return CE_Failure;
     }
 
-    if( (strlen(osBandIdentifier) && poTileDS->GetRasterCount() != nBandCount)
-        || (!strlen(osBandIdentifier) && poTileDS->GetRasterCount() !=
+    if( (!osBandIdentifier.empty() && poTileDS->GetRasterCount() != nBandCount)
+        || (osBandIdentifier.empty() && poTileDS->GetRasterCount() !=
             GetRasterCount() ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -631,17 +631,15 @@ WCSDataset::DirectRasterIO( CPL_UNUSED GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Pull requested bands from the downloaded dataset.               */
 /* -------------------------------------------------------------------- */
-    int iBand;
-
     eErr = CE_None;
 
-    for( iBand = 0;
+    for( int iBand = 0;
          iBand < nBandCount && eErr == CE_None;
          iBand++ )
     {
-        GDALRasterBand *poTileBand;
+        GDALRasterBand *poTileBand = NULL;
 
-        if( strlen(osBandIdentifier) )
+        if( !osBandIdentifier.empty() )
             poTileBand = poTileDS->GetRasterBand( iBand + 1 );
         else
             poTileBand = poTileDS->GetRasterBand( panBandMap[iBand] );
@@ -697,7 +695,7 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
     CPLString osBandList;
     int       bSelectingBands = FALSE;
 
-    if( strlen(osBandIdentifier) && nBandCount > 0 )
+    if( !osBandIdentifier.empty() && nBandCount > 0 && panBandList != NULL )
     {
         int iBand;
 
@@ -714,16 +712,13 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      URL encode strings that could have questionable characters.     */
 /* -------------------------------------------------------------------- */
-    CPLString osCoverage, osFormat;
-    char *pszEncoded;
+    CPLString osCoverage = CPLGetXMLValue( psService, "CoverageName", "" );
 
-    osCoverage = CPLGetXMLValue( psService, "CoverageName", "" );
-
-    pszEncoded = CPLEscapeString( osCoverage, -1, CPLES_URL );
+    char *pszEncoded = CPLEscapeString( osCoverage, -1, CPLES_URL );
     osCoverage = pszEncoded;
     CPLFree( pszEncoded );
 
-    osFormat = CPLGetXMLValue( psService, "PreferredFormat", "" );
+    CPLString osFormat = CPLGetXMLValue( psService, "PreferredFormat", "" );
 
     pszEncoded = CPLEscapeString( osFormat, -1, CPLES_URL );
     osFormat = pszEncoded;
@@ -737,7 +732,7 @@ CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize,
     osTime = CSLFetchNameValueDef( papszSDSModifiers, "time", osDefaultTime );
 
 /* -------------------------------------------------------------------- */
-/*      Construct a "simple" GetCoverage request (WCS 1.0).		*/
+/*      Construct a "simple" GetCoverage request (WCS 1.0).             */
 /* -------------------------------------------------------------------- */
     CPLString osRequest;
 
@@ -1152,7 +1147,7 @@ int WCSDataset::ExtractGridInfo100()
              papszFormatList != NULL && papszFormatList[iFormat] != NULL;
              iFormat++ )
         {
-            if( strlen(osPreferredFormat) == 0 )
+            if( osPreferredFormat.empty() )
                 osPreferredFormat = papszFormatList[iFormat];
 
             if( strstr(papszFormatList[iFormat],"tiff") != NULL
@@ -1166,7 +1161,7 @@ int WCSDataset::ExtractGridInfo100()
 
         CSLDestroy( papszFormatList );
 
-        if( strlen(osPreferredFormat) > 0 )
+        if( !osPreferredFormat.empty() )
         {
             bServiceDirty = TRUE;
             CPLCreateXMLElementAndValue( psService, "PreferredFormat",
@@ -1200,7 +1195,7 @@ int WCSDataset::ExtractGridInfo100()
       "CoverageOffering.rangeSet.RangeSet.axisDescription.AxisDescription" );
     CPLXMLNode *psValues;
 
-    if( strlen(osBandIdentifier) == 0
+    if( osBandIdentifier.empty()
         && psAD != NULL
         && (EQUAL(CPLGetXMLValue(psAD,"name",""),"Band")
             || EQUAL(CPLGetXMLValue(psAD,"name",""),"Bands"))
@@ -1226,7 +1221,7 @@ int WCSDataset::ExtractGridInfo100()
             }
         }
 
-        if( strlen(osBandIdentifier) )
+        if( !osBandIdentifier.empty() )
         {
             bServiceDirty = TRUE;
             CPLCreateXMLElementAndValue( psService, "BandIdentifier",
@@ -1261,13 +1256,12 @@ int WCSDataset::ExtractGridInfo100()
 
         // we will default to the last - likely the most recent - entry.
 
-        if( aosTimePositions.size() > 0
-            && osDefaultTime == ""
+        if( !aosTimePositions.empty()
+            && osDefaultTime.empty()
             && osServiceURL.ifind("time=") == std::string::npos
             && osCoverageExtra.ifind("time=") == std::string::npos )
         {
-            osDefaultTime = aosTimePositions[aosTimePositions.size()-1];
-
+            osDefaultTime = aosTimePositions.back();
             bServiceDirty = TRUE;
             CPLCreateXMLElementAndValue( psService, "DefaultTime",
                                          osDefaultTime );
@@ -1460,7 +1454,7 @@ int WCSDataset::ExtractGridInfo()
 /* -------------------------------------------------------------------- */
     osCRS = CPLGetXMLValue( psGCRS, "GridBaseCRS", "" );
 
-    if( strlen(osCRS) == 0 )
+    if( osCRS.empty() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Unable to find GridCRS.GridBaseCRS" );
@@ -1580,7 +1574,7 @@ int WCSDataset::ExtractGridInfo()
                 && psNode->psChild
                 && psNode->psChild->eType == CXT_Text )
             {
-                if( strlen(osPreferredFormat) == 0 )
+                if( osPreferredFormat.empty() )
                     osPreferredFormat = psNode->psChild->pszValue;
 
                 if( strstr(psNode->psChild->pszValue,"tiff") != NULL
@@ -1593,7 +1587,7 @@ int WCSDataset::ExtractGridInfo()
             }
         }
 
-        if( strlen(osPreferredFormat) > 0 )
+        if( !osPreferredFormat.empty() )
         {
             bServiceDirty = TRUE;
             CPLCreateXMLElementAndValue( psService, "PreferredFormat",
@@ -1626,7 +1620,7 @@ int WCSDataset::ExtractGridInfo()
         CPLString osFieldName =
             CPLGetXMLValue( psCO, "Range.Field.Identifier", "" );
 
-        if( strlen(osFieldName) > 0 )
+        if( !osFieldName.empty() )
         {
             bServiceDirty = TRUE;
             CPLCreateXMLElementAndValue( psService, "FieldName",
@@ -1674,7 +1668,7 @@ int WCSDataset::ExtractGridInfo()
             }
         }
 
-        if( strlen(osBandIdentifier) )
+        if( !osBandIdentifier.empty() )
         {
             bServiceDirty = TRUE;
             if( CPLGetXMLValue(psService,"BandIdentifier",NULL) == NULL )
@@ -1778,7 +1772,6 @@ int WCSDataset::ProcessError( CPLHTTPResult *psResult )
         return TRUE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Hopefully the error already issued by CPLHTTPFetch() is         */
 /*      sufficient.                                                     */
@@ -1884,7 +1877,7 @@ int WCSDataset::EstablishRasterDetails()
 void WCSDataset::FlushMemoryResult()
 
 {
-    if( strlen(osResultFilename) > 0 )
+    if( !osResultFilename.empty() )
     {
         VSIUnlink( osResultFilename );
         osResultFilename = "";
@@ -2012,7 +2005,6 @@ GDALDataset *WCSDataset::GDALOpenResult( CPLHTTPResult *psResult )
     pabySavedDataBuffer = psResult->pabyData;
 
     psResult->pabyData = NULL;
-    psResult->nDataLen = psResult->nDataAlloc = 0;
 
     if( poDS == NULL )
         FlushMemoryResult();
@@ -2095,7 +2087,6 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
             CPLFree( papszModifiers[iLast] );
             papszModifiers[iLast] = NULL;
         }
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -2161,7 +2152,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    WCSDataset 	*poDS;
+    WCSDataset *poDS;
 
     poDS = new WCSDataset();
 
@@ -2261,7 +2252,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
     if( !STARTS_WITH_CI(poOpenInfo->pszFilename, "WCS_SDS:")
         && !STARTS_WITH_CI(poOpenInfo->pszFilename, "<WCS_GDAL>")
-        && poDS->aosTimePositions.size() > 0 )
+        && !poDS->aosTimePositions.empty() )
     {
         char **papszSubdatasets = NULL;
         int iTime;
@@ -2299,7 +2290,7 @@ GDALDataset *WCSDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Initialize any PAM information.                                 */
 /* -------------------------------------------------------------------- */
     poDS->TryLoadXML();
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -2310,7 +2301,7 @@ CPLErr WCSDataset::GetGeoTransform( double * padfTransform )
 
 {
     memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -2327,7 +2318,7 @@ const char *WCSDataset::GetProjectionRef()
     if ( pszProjection && strlen(pszProjection) > 0 )
         return pszProjection;
 
-    return( "" );
+    return "";
 }
 
 /************************************************************************/
@@ -2398,7 +2389,6 @@ char **WCSDataset::GetMetadata( const char *pszDomain )
     return apszCoverageOfferingMD;
 }
 
-
 /************************************************************************/
 /*                          GDALRegister_WCS()                          */
 /************************************************************************/
diff --git a/frmts/webp/webpdataset.cpp b/frmts/webp/webpdataset.cpp
index 7560963..0281a9c 100644
--- a/frmts/webp/webpdataset.cpp
+++ b/frmts/webp/webpdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: webpdataset.cpp 32827 2016-01-08 11:22:33Z rouault $
  *
  * Project:  GDAL WEBP Driver
  * Purpose:  Implement GDAL WEBP Support based on libwebp
@@ -33,7 +32,7 @@
 
 #include "webp_headers.h"
 
-CPL_CVSID("$Id: webpdataset.cpp 32827 2016-01-08 11:22:33Z rouault $");
+CPL_CVSID("$Id: webpdataset.cpp 37788 2017-03-19 11:52:40Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -57,17 +56,17 @@ class WEBPDataset : public GDALPamDataset
 
   public:
                  WEBPDataset();
-                 ~WEBPDataset();
+    virtual ~WEBPDataset();
 
     virtual CPLErr      IRasterIO( GDALRWFlag, int, int, int, int,
                                    void *, int, int, GDALDataType,
                                    int, int *,
                                    GSpacing nPixelSpace, GSpacing nLineSpace,
                                    GSpacing nBandSpace,
-                                   GDALRasterIOExtraArg* psExtraArg);
+                                   GDALRasterIOExtraArg* psExtraArg) override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char  **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char  **GetMetadata( const char * pszDomain = "" ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -91,8 +90,8 @@ class WEBPRasterBand : public GDALPamRasterBand
   public:
                    WEBPRasterBand( WEBPDataset *, int );
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual GDALColorInterp GetColorInterpretation() override;
 };
 
 /************************************************************************/
@@ -156,7 +155,6 @@ GDALColorInterp WEBPRasterBand::GetColorInterpretation()
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                            WEBPDataset()                              */
 /************************************************************************/
@@ -346,7 +344,7 @@ CPLErr WEBPDataset::IRasterIO( GDALRWFlag eRWFlag,
     if((eRWFlag == GF_Read) &&
        (nBandCount == nBands) &&
        (nXOff == 0) &&
-       (nYOff == 0) && // TODO: X -> Y on this was correct?
+       (nYOff == 0) &&
        (nXSize == nBufXSize) && (nXSize == nRasterXSize) &&
        (nYSize == nBufYSize) && (nYSize == nRasterYSize) &&
        (eBufType == GDT_Byte) &&
@@ -684,7 +682,7 @@ WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     FETCH_AND_SET_OPTION_INT("PARTITION_LIMIT", partition_limit, 0, 100);
 #endif
 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
-    sConfig.lossless = CSLFetchBoolean(papszOptions, "LOSSLESS", FALSE);
+    sConfig.lossless = CPLFetchBool(papszOptions, "LOSSLESS", false);
     if (sConfig.lossless)
         sPicture.use_argb = 1;
 #endif
diff --git a/frmts/wms/GNUmakefile b/frmts/wms/GNUmakefile
index 6821d15..2fc4941 100644
--- a/frmts/wms/GNUmakefile
+++ b/frmts/wms/GNUmakefile
@@ -7,9 +7,9 @@ OBJ =	gdalwmscache.o gdalwmsdataset.o gdalwmsrasterband.o \
 	minidriver_tileservice.o minidriver_worldwind.o \
 	minidriver_tms.o minidriver_tiled_wms.o wmsmetadataset.o \
 	minidriver_virtualearth.o minidriver_arcgis_server.o \
-	minidriver_iip.o
+	minidriver_iip.o minidriver_mrf.o
 
-CPPFLAGS	:=	 $(CPPFLAGS) $(CURL_INC)
+CPPFLAGS	:=	 $(CPPFLAGS) -DHAVE_CURL $(CURL_INC)
 
 default:	$(OBJ:.o=.$(OBJ_EXT))
 
@@ -21,4 +21,5 @@ install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
 $(OBJ) $(O_OBJ):	gdalhttp.h md5.h minidriver_tileservice.h \
 	minidriver_wms.h minidriver_worldwind.h minidriver_tms.h \
 	minidriver_tiled_wms.h wmsdriver.h wmsmetadataset.h \
-	minidriver_virtualearth.h minidriver_arcgis_server.h
+	minidriver_virtualearth.h minidriver_arcgis_server.h \
+        minidriver_mrf.h
diff --git a/frmts/wms/frmt_wms_arcgis_mapserver_tms.xml b/frmts/wms/frmt_wms_arcgis_mapserver_tms.xml
index dd4d9d3..e22cd76 100644
--- a/frmts/wms/frmt_wms_arcgis_mapserver_tms.xml
+++ b/frmts/wms/frmt_wms_arcgis_mapserver_tms.xml
@@ -1,6 +1,6 @@
 <GDAL_WMS>
     <Service name="TMS">
-        <ServerUrl>http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/${z}/${y}/${x}</ServerUrl>>
+        <ServerUrl>http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/${z}/${y}/${x}</ServerUrl>
     </Service>
     <DataWindow>
         <UpperLeftX>-20037508.34</UpperLeftX>
diff --git a/frmts/wms/frmt_wms_arcgis_terrain_tms_lerc.xml b/frmts/wms/frmt_wms_arcgis_terrain_tms_lerc.xml
new file mode 100644
index 0000000..7d13ad3
--- /dev/null
+++ b/frmts/wms/frmt_wms_arcgis_terrain_tms_lerc.xml
@@ -0,0 +1,21 @@
+<GDAL_WMS>
+  <Service name="TMS">
+    <ServerUrl>http://elevation3d.arcgis.com/ArcGIS/rest/services/WorldElevation3D/Terrain3D/ImageServer/tile/${z}/${y}/${x}</ServerUrl>
+  </Service>
+  <DataWindow>
+    <UpperLeftX>-20037508.34</UpperLeftX>
+    <UpperLeftY>20037508.34</UpperLeftY>
+    <LowerRightX>20037508.34</LowerRightX>
+    <LowerRightY>-20037508.34</LowerRightY>
+    <TileLevel>15</TileLevel>
+    <TileCountX>1</TileCountX>
+    <TileCountY>1</TileCountY>
+    <YOrigin>top</YOrigin>
+  </DataWindow>
+  <Projection>EPSG:900913</Projection>
+  <BlockSizeX>257</BlockSizeX>
+  <BlockSizeY>257</BlockSizeY>
+  <BandsCount>1</BandsCount>
+  <DataType>Float32</DataType>
+  <MaxConnections>10</MaxConnections>
+</GDAL_WMS>
diff --git a/frmts/wms/gdalhttp.cpp b/frmts/wms/gdalhttp.cpp
index 8024e2c..0312050 100644
--- a/frmts/wms/gdalhttp.cpp
+++ b/frmts/wms/gdalhttp.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalhttp.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -9,6 +8,7 @@
  ******************************************************************************
  * Copyright (c) 2007, Adam Nowacki
  * Copyright (c) 2007-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2016, Lucian Plesea
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -30,8 +30,9 @@
  ****************************************************************************/
 
 #include "wmsdriver.h"
+#include <algorithm>
 
-void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions);
+CPL_CVSID("$Id: gdalhttp.cpp 37949 2017-04-10 20:53:07Z lplesea $");
 
 /* CURLINFO_RESPONSE_CODE was known as CURLINFO_HTTP_CODE in libcurl 7.10.7 and earlier */
 #if LIBCURL_VERSION_NUM < 0x070a07
@@ -39,7 +40,7 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions);
 #endif
 
 static size_t CPLHTTPWriteFunc(void *buffer, size_t count, size_t nmemb, void *req) {
-    CPLHTTPRequest *psRequest = reinterpret_cast<CPLHTTPRequest *>(req);
+    WMSHTTPRequest *psRequest = reinterpret_cast<WMSHTTPRequest *>(req);
     size_t size = count * nmemb;
 
     if (size == 0) return 0;
@@ -53,7 +54,8 @@ static size_t CPLHTTPWriteFunc(void *buffer, size_t count, size_t nmemb, void *r
         if (pabyNewData == NULL) {
             VSIFree(psRequest->pabyData);
             psRequest->pabyData = NULL;
-            psRequest->pszError = CPLStrdup(CPLString().Printf("Out of memory allocating %u bytes for HTTP data buffer.", static_cast<int>(new_size)));
+            psRequest->Error.Printf("Out of memory allocating %u bytes for HTTP data buffer.",
+                static_cast<unsigned int>(new_size));
             psRequest->nDataAlloc = 0;
             psRequest->nDataLen = 0;
             return 0;
@@ -66,146 +68,106 @@ static size_t CPLHTTPWriteFunc(void *buffer, size_t count, size_t nmemb, void *r
     return nmemb;
 }
 
-void CPLHTTPInitializeRequest(CPLHTTPRequest *psRequest, const char *pszURL, const char *const *papszOptions) {
-    psRequest->pszURL = CPLStrdup(pszURL);
-    psRequest->papszOptions = CSLDuplicate(const_cast<char **>(papszOptions));
+// Builds a curl request
+void WMSHTTPInitializeRequest(WMSHTTPRequest *psRequest) {
     psRequest->nStatus = 0;
-    psRequest->pszContentType = NULL;
-    psRequest->pszError = NULL;
     psRequest->pabyData = NULL;
     psRequest->nDataLen = 0;
     psRequest->nDataAlloc = 0;
-    psRequest->m_curl_handle = NULL;
-    psRequest->m_headers = NULL;
-    psRequest->m_curl_error = NULL;
 
     psRequest->m_curl_handle = curl_easy_init();
     if (psRequest->m_curl_handle == NULL) {
         CPLError(CE_Fatal, CPLE_AppDefined, "CPLHTTPInitializeRequest(): Unable to create CURL handle.");
+        // This should return somehow?
     }
 
-    char** papszOptionsDup = CSLDuplicate(const_cast<char **>(psRequest->papszOptions));
-
-    /* Set User-Agent */
-    const char *pszUserAgent = CSLFetchNameValue(papszOptionsDup, "USERAGENT");
-    if (pszUserAgent == NULL)
-        papszOptionsDup = CSLAddNameValue(papszOptionsDup, "USERAGENT",
-                                          "GDAL WMS driver (http://www.gdal.org/frmt_wms.html)");
-
-    /* Set URL */
-    curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_URL, psRequest->pszURL);
-
-    /* Set Headers (copied&pasted from cpl_http.cpp, but unused by callers of CPLHTTPInitializeRequest) .*/
-    const char *headers = CSLFetchNameValue(const_cast<char **>(psRequest->papszOptions), "HEADERS");
-    if (headers != NULL) {
-        psRequest->m_headers = curl_slist_append(psRequest->m_headers, headers);
-        curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_HTTPHEADER, psRequest->m_headers);
-    }
+    if (!psRequest->Range.empty())
+        curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_RANGE, psRequest->Range.c_str());
 
+    curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_URL, psRequest->URL.c_str());
     curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_WRITEDATA, psRequest);
     curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_WRITEFUNCTION, CPLHTTPWriteFunc);
 
-    psRequest->m_curl_error = reinterpret_cast<char *>(CPLMalloc(CURL_ERROR_SIZE + 1));
-    psRequest->m_curl_error[0] = '\0';
-    curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_ERRORBUFFER, psRequest->m_curl_error);
+    psRequest->m_curl_error.resize(CURL_ERROR_SIZE + 1);
+    curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_ERRORBUFFER, &psRequest->m_curl_error[0]);
 
-    CPLHTTPSetOptions(psRequest->m_curl_handle, papszOptionsDup);
+    psRequest->m_headers = static_cast<struct curl_slist*>(
+            CPLHTTPSetOptions(psRequest->m_curl_handle, psRequest->options));
+    if( psRequest->m_headers != NULL )
+        curl_easy_setopt(psRequest->m_curl_handle, CURLOPT_HTTPHEADER,
+                         psRequest->m_headers);
 
-    CSLDestroy(papszOptionsDup);
 }
 
-void CPLHTTPCleanupRequest(CPLHTTPRequest *psRequest) {
-    if (psRequest->m_curl_handle) {
-        curl_easy_cleanup(psRequest->m_curl_handle);
-        psRequest->m_curl_handle = NULL;
-    }
-    if (psRequest->m_headers) {
-        curl_slist_free_all(psRequest->m_headers);
-        psRequest->m_headers = NULL;
-    }
-    if (psRequest->m_curl_error) {
-        CPLFree(psRequest->m_curl_error);
-        psRequest->m_curl_error = NULL;
-    }
-
-    if (psRequest->pszContentType) {
-        CPLFree(psRequest->pszContentType);
-        psRequest->pszContentType = NULL;
-    }
-    if (psRequest->pszError) {
-        CPLFree(psRequest->pszError);
-        psRequest->pszError = NULL;
-    }
-    if (psRequest->pabyData) {
-        CPLFree(psRequest->pabyData);
-        psRequest->pabyData = NULL;
-        psRequest->nDataLen = 0;
-        psRequest->nDataAlloc = 0;
-    }
-    if (psRequest->papszOptions) {
-        CSLDestroy(psRequest->papszOptions);
-        psRequest->papszOptions = NULL;
-    }
-    if (psRequest->pszURL) {
-        CPLFree(psRequest->pszURL);
-        psRequest->pszURL = NULL;
-    }
+WMSHTTPRequest::~WMSHTTPRequest() {
+    if (m_curl_handle != NULL)
+        curl_easy_cleanup(m_curl_handle);
+    if( m_headers != NULL )
+        curl_slist_free_all(m_headers);
+    if (pabyData != NULL)
+        CPLFree(pabyData);
 }
 
-CPLErr CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount, const char *const *papszOptions) {
+//
+// Like CPLHTTPFetch, but multiple requests in parallel
+// By default it uses 5 connections
+//
+CPLErr WMSHTTPFetchMulti(WMSHTTPRequest *pasRequest, int nRequestCount) {
     CPLErr ret = CE_None;
     CURLM *curl_multi = NULL;
     int still_running;
     int max_conn;
     int i, conn_i;
 
-    if( nRequestCount > 0 &&
-        STARTS_WITH(pasRequest[0].pszURL, "/vsimem/") &&
+    CPLAssert(nRequestCount >= 0);
+    if (nRequestCount == 0)
+        return CE_None;
+
+    const char *max_conn_opt = CSLFetchNameValue(const_cast<char **>(pasRequest->options), "MAXCONN");
+    max_conn = (max_conn_opt == NULL) ? 5 : MAX(1, MIN(atoi(max_conn_opt), 1000));
+
+    // If the first url starts with vsimem, assume all do and defer to CPLHTTPFetch
+    if( STARTS_WITH(pasRequest[0].URL.c_str(), "/vsimem/") &&
         /* Disabled by default for potential security issues */
         CPLTestBool(CPLGetConfigOption("CPL_CURL_ENABLE_VSIMEM", "FALSE")) )
     {
         for(i = 0; i< nRequestCount;i++)
         {
-            CPLHTTPResult* psResult = CPLHTTPFetch(pasRequest[i].pszURL, (char**)papszOptions);
+            CPLHTTPResult* psResult = CPLHTTPFetch(pasRequest[i].URL.c_str(),
+                                                    const_cast<char**>(pasRequest[i].options));
             pasRequest[i].pabyData = psResult->pabyData;
             pasRequest[i].nDataLen = psResult->nDataLen;
-            pasRequest[i].pszError = psResult->pszErrBuf;
-            // Conventions a bit different between this module and cpl_http...
+            pasRequest[i].Error = psResult->pszErrBuf ? psResult->pszErrBuf : "";
+            // Conventions are different between this module and cpl_http...
             if( psResult->pszErrBuf != NULL &&
                 strcmp(psResult->pszErrBuf, "HTTP error code : 404") == 0 )
                 pasRequest[i].nStatus = 404;
             else
                 pasRequest[i].nStatus = 200;
-            pasRequest[i].pszContentType = psResult->pszContentType;
+            pasRequest[i].ContentType = psResult->pszContentType ? psResult->pszContentType : "";
+            // took ownership of content, we're done with the rest
             psResult->pabyData = NULL;
             psResult->nDataLen = 0;
-            psResult->pszErrBuf = NULL;
-            psResult->pszContentType = NULL;
             CPLHTTPDestroyResult(psResult);
         }
         return CE_None;
     }
 
-    const char *max_conn_opt = CSLFetchNameValue(const_cast<char **>(papszOptions), "MAXCONN");
-    if (max_conn_opt && (max_conn_opt[0] != '\0')) {
-        max_conn = MAX(1, MIN(atoi(max_conn_opt), 1000));
-    } else {
-        max_conn = 5;
-    }
-
     curl_multi = curl_multi_init();
     if (curl_multi == NULL) {
         CPLError(CE_Fatal, CPLE_AppDefined, "CPLHTTPFetchMulti(): Unable to create CURL multi-handle.");
     }
 
     // add at most max_conn requests
-    for (conn_i = 0; conn_i < MIN(nRequestCount, max_conn); ++conn_i) {
-        CPLHTTPRequest *const psRequest = &pasRequest[conn_i];
-        CPLDebug("HTTP", "Requesting [%d/%d] %s", conn_i + 1, nRequestCount, pasRequest[conn_i].pszURL);
+    for (conn_i = 0; conn_i < std::min(nRequestCount, max_conn); ++conn_i) {
+        WMSHTTPRequest *const psRequest = &pasRequest[conn_i];
+        CPLDebug("HTTP", "Requesting [%d/%d] %s", conn_i + 1, nRequestCount,
+            pasRequest[conn_i].URL.c_str());
         curl_multi_add_handle(curl_multi, psRequest->m_curl_handle);
     }
 
     while (curl_multi_perform(curl_multi, &still_running) == CURLM_CALL_MULTI_PERFORM);
+
     while (still_running || (conn_i != nRequestCount)) {
         struct timeval timeout;
         fd_set fdread, fdwrite, fdexcep;
@@ -216,16 +178,19 @@ CPLErr CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount, const ch
         do {
             msg = curl_multi_info_read(curl_multi, &msgs_in_queue);
             if (msg != NULL) {
-                if (msg->msg == CURLMSG_DONE) { // transfer completed, check if we have more waiting and add them
+                if (msg->msg == CURLMSG_DONE) {
+                    // transfer completed, add more handles if available
                     if (conn_i < nRequestCount) {
-                        CPLHTTPRequest *const psRequest = &pasRequest[conn_i];
-                        CPLDebug("HTTP", "Requesting [%d/%d] %s", conn_i + 1, nRequestCount, pasRequest[conn_i].pszURL);
+                        WMSHTTPRequest *const psRequest = &pasRequest[conn_i];
+                        CPLDebug("HTTP", "Requesting [%d/%d] %s", conn_i + 1,
+                                    nRequestCount, pasRequest[conn_i].URL.c_str());
                         curl_multi_add_handle(curl_multi, psRequest->m_curl_handle);
                         ++conn_i;
                     }
                 }
             }
         } while (msg != NULL);
+
         FD_ZERO(&fdread);
         FD_ZERO(&fdwrite);
         FD_ZERO(&fdexcep);
@@ -240,42 +205,48 @@ CPLErr CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount, const ch
                 break;
             }
         }
+
         while (curl_multi_perform(curl_multi, &still_running) == CURLM_CALL_MULTI_PERFORM);
     }
 
     if (conn_i != nRequestCount) { // something gone really really wrong
         CPLError(CE_Fatal, CPLE_AppDefined, "CPLHTTPFetchMulti(): conn_i != nRequestCount, this should never happen ...");
     }
+
     for (i = 0; i < nRequestCount; ++i) {
-        CPLHTTPRequest *const psRequest = &pasRequest[i];
+        WMSHTTPRequest *const psRequest = &pasRequest[i];
 
-        long response_code = 0;
+        long response_code;
         curl_easy_getinfo(psRequest->m_curl_handle, CURLINFO_RESPONSE_CODE, &response_code);
         psRequest->nStatus = static_cast<int>(response_code);
 
         char *content_type = NULL;
         curl_easy_getinfo(psRequest->m_curl_handle, CURLINFO_CONTENT_TYPE, &content_type);
-        if (content_type) psRequest->pszContentType = CPLStrdup(content_type);
+        psRequest->ContentType = content_type ? content_type : "";
 
-        if ((psRequest->pszError == NULL) && (psRequest->m_curl_error != NULL) && (psRequest->m_curl_error[0] != '\0')) {
-            psRequest->pszError = CPLStrdup(psRequest->m_curl_error);
-        }
+        if (psRequest->Error.empty())
+            psRequest->Error = &psRequest->m_curl_error[0];
 
         /* In the case of a file:// URL, curl will return a status == 0, so if there's no */
         /* error returned, patch the status code to be 200, as it would be for http:// */
-        if (STARTS_WITH(psRequest->pszURL, "file://") && psRequest->nStatus == 0 &&
-            psRequest->pszError == NULL)
-        {
+        if (psRequest->nStatus == 0 && psRequest->Error.empty() && STARTS_WITH(psRequest->URL.c_str(), "file://"))
             psRequest->nStatus = 200;
-        }
+
+        // If there is an error with no error message, use the content if it is text
+        if (psRequest->Error.empty()
+            && psRequest->nStatus != 0
+            && psRequest->nStatus != 200
+            && strstr(psRequest->ContentType, "text"))
+            psRequest->Error = reinterpret_cast<const char *>(psRequest->pabyData);
 
         CPLDebug("HTTP", "Request [%d] %s : status = %d, content type = %s, error = %s",
-                 i, psRequest->pszURL, psRequest->nStatus,
-                 (psRequest->pszContentType) ? psRequest->pszContentType : "(null)",
-                 (psRequest->pszError) ? psRequest->pszError : "(null)");
+                 i, psRequest->URL.c_str(), psRequest->nStatus,
+                 !psRequest->ContentType.empty() ? psRequest->ContentType.c_str() : "(null)",
+                 !psRequest->Error.empty() ? psRequest->Error.c_str() : "(null)");
 
-        curl_multi_remove_handle(curl_multi, pasRequest[i].m_curl_handle);
+        curl_multi_remove_handle(curl_multi, pasRequest->m_curl_handle);
     }
+
     curl_multi_cleanup(curl_multi);
 
     return ret;
diff --git a/frmts/wms/gdalhttp.h b/frmts/wms/gdalhttp.h
index 811ba8e..ca353c5 100644
--- a/frmts/wms/gdalhttp.h
+++ b/frmts/wms/gdalhttp.h
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * $Id: gdalhttp.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: gdalhttp.h 37646 2017-03-08 00:24:45Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,29 +28,44 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-typedef struct {
+#ifndef GDALHTTP_H
+#define GDALHTTP_H
+
+#include "cpl_port.h"
+#include "cpl_http.h"
+
+struct WMSHTTPRequest {
+    WMSHTTPRequest()
+        :options(NULL), nStatus(0), pabyData(NULL), nDataLen(0), nDataAlloc(0), m_curl_handle(NULL), m_headers(NULL), x(0), y(0) {};
+    ~WMSHTTPRequest();
+
     /* Input */
-    char *pszURL;
-    char **papszOptions;
+    CPLString URL;
+    // Not owned, do not release
+    const char *const *options;
+    CPLString Range;
 
     /* Output */
-    int nStatus;		/* 200 = success, 404 = not found, 0 = no response / error */
-    char *pszContentType;
-    char *pszError;
+    CPLString ContentType;
+    CPLString Error;
 
+    int nStatus;  /* 200 = success, 404 = not found, 0 = no response / error */
     GByte *pabyData;
     size_t nDataLen;
     size_t nDataAlloc;
 
-    //    int nMimePartCount;
-    //    CPLMimePart *pasMimePart;
-
-    /* Internal stuff */
+    /* curl internal stuff */
     CURL *m_curl_handle;
-    struct curl_slist *m_headers;
-    char *m_curl_error;
-} CPLHTTPRequest;
+    struct curl_slist* m_headers;
+    // Which tile is being requested
+    int x, y;
+
+    // Space for error message, doesn't seem to be used by the multi-request interface
+    std::vector<char> m_curl_error;
+};
+
+// Not public, only for use within WMS
+void WMSHTTPInitializeRequest(WMSHTTPRequest *psRequest);
+CPLErr WMSHTTPFetchMulti(WMSHTTPRequest *psRequest, int nRequestCount = 1);
 
-void CPL_DLL CPLHTTPInitializeRequest(CPLHTTPRequest *psRequest, const char *pszURL = NULL, const char *const *papszOptions = NULL);
-void CPL_DLL CPLHTTPCleanupRequest(CPLHTTPRequest *psRequest);
-CPLErr CPL_DLL CPLHTTPFetchMulti(CPLHTTPRequest *pasRequest, int nRequestCount = 1, const char *const *papszOptions = NULL);
+#endif /*  GDALHTTP_H */
diff --git a/frmts/wms/gdalwmscache.cpp b/frmts/wms/gdalwmscache.cpp
index 78a05a6..ceac4c9 100644
--- a/frmts/wms/gdalwmscache.cpp
+++ b/frmts/wms/gdalwmscache.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalwmscache.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -30,14 +29,15 @@
 
 #include "wmsdriver.h"
 
-GDALWMSCache::GDALWMSCache() {
-    m_cache_path = "./gdalwmscache";
-    m_postfix = "";
-    m_cache_depth = 2;
-}
+CPL_CVSID("$Id: gdalwmscache.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
-GDALWMSCache::~GDALWMSCache() {
-}
+GDALWMSCache::GDALWMSCache() :
+    m_cache_path("./gdalwmscache"),
+    // No need to do the default: m_postfix("");
+    m_cache_depth(2)
+{}
+
+GDALWMSCache::~GDALWMSCache() {}
 
 CPLErr GDALWMSCache::Initialize(CPLXMLNode *config) {
     const char *xmlcache_path = CPLGetXMLValue(config, "Path", NULL);
@@ -67,14 +67,25 @@ CPLErr GDALWMSCache::Initialize(CPLXMLNode *config) {
     return CE_None;
 }
 
+// Recursive makedirs, ignoring errors
+static void MakeDirs(const CPLString & path) {
+    CPLString p(CPLGetDirname(path));
+    if (p.size() >= 2)
+        MakeDirs(p);
+    VSIMkdir(p, 0744);
+}
+
+// Warns if it fails to write, but returns success
 CPLErr GDALWMSCache::Write(const char *key, const CPLString &file_name) {
     CPLString cache_file(KeyToCacheFile(key));
-    //	printf("GDALWMSCache::Write(%s, %s) -> %s\n", key, file_name.c_str());
-    if (CPLCopyFile(cache_file.c_str(), file_name.c_str()) != CE_None) {
-        MakeDirs(cache_file.c_str());
-        CPLCopyFile(cache_file.c_str(), file_name.c_str());
-    }
-
+    // printf("GDALWMSCache::Write(%s, %s) -> %s\n", key, file_name.c_str());
+    if (CPLCopyFile(cache_file, file_name) == CE_None)
+        return CE_None;
+    MakeDirs(cache_file.c_str());
+    if (CPLCopyFile(cache_file, file_name) == CE_None)
+        return CE_None;
+    // Warn if it fails after folder creation
+    CPLError(CE_Warning, CPLE_FileIO, "Error writing to WMS cache %s", m_cache_path.c_str());
     return CE_None;
 }
 
@@ -88,7 +99,6 @@ CPLErr GDALWMSCache::Read(const char *key, CPLString *file_name) {
         *file_name = cache_file;
         ret = CE_None;
     }
-    //    printf("GDALWMSCache::Read(...) -> %s\n", cache_file.c_str());
 
     return ret;
 }
@@ -97,7 +107,8 @@ CPLString GDALWMSCache::KeyToCacheFile(const char *key) {
     CPLString hash(MD5String(key));
     CPLString cache_file(m_cache_path);
 
-    if (cache_file.size() && (cache_file[cache_file.size() - 1] != '/')) cache_file.append(1, '/');
+    if (!cache_file.empty() && cache_file.back() != '/')
+        cache_file.append(1, '/');
     for (int i = 0; i < m_cache_depth; ++i) {
         cache_file.append(1, hash[i]);
         cache_file.append(1, '/');
diff --git a/frmts/wms/gdalwmsdataset.cpp b/frmts/wms/gdalwmsdataset.cpp
index acf46a9..0c4d4f0 100644
--- a/frmts/wms/gdalwmsdataset.cpp
+++ b/frmts/wms/gdalwmsdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalwmsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -35,9 +34,7 @@
  *
  ***************************************************************************/
 
-
 #include "wmsdriver.h"
-
 #include "minidriver_wms.h"
 #include "minidriver_tileservice.h"
 #include "minidriver_worldwind.h"
@@ -45,34 +42,40 @@
 #include "minidriver_tiled_wms.h"
 #include "minidriver_virtualearth.h"
 
+#include <algorithm>
+
+CPL_CVSID("$Id: gdalwmsdataset.cpp 37949 2017-04-10 20:53:07Z lplesea $");
+
 /************************************************************************/
 /*                           GDALWMSDataset()                           */
 /************************************************************************/
 GDALWMSDataset::GDALWMSDataset() :
+    m_mini_driver(NULL),
+    m_cache(NULL),
+    m_poColorTable(NULL),
+    m_data_type(GDT_Byte),
     m_block_size_x(0),
     m_block_size_y(0),
     m_use_advise_read(0),
     m_verify_advise_read(0),
     m_offline_mode(0),
     m_http_max_conn(0),
-    m_http_timeout(0)
+    m_http_timeout(0),
+    m_http_options(NULL),
+    m_tileOO(NULL),
+    m_clamp_requests(true),
+    m_unsafeSsl(false),
+    m_zeroblock_on_serverexceptions(0),
+    m_default_block_size_x(1024),
+    m_default_block_size_y(1024),
+    m_default_tile_count_x(1),
+    m_default_tile_count_y(1),
+    m_default_overview_count(-1),
+    m_bNeedsDataWindow(true)
 {
-    m_mini_driver = NULL;
-    m_cache = NULL;
     m_hint.m_valid = false;
-    m_data_type = GDT_Byte;
-    m_clamp_requests = true;
-    m_unsafeSsl = false;
     m_data_window.m_sx = -1;
     nBands = 0;
-    m_default_block_size_x = 1024;
-    m_default_block_size_y = 1024;
-    m_bNeedsDataWindow = TRUE;
-    m_default_tile_count_x = 1;
-    m_default_tile_count_y = 1;
-    m_default_overview_count = -1;
-    m_zeroblock_on_serverexceptions = 0;
-    m_poColorTable = NULL;
 }
 
 /************************************************************************/
@@ -82,12 +85,14 @@ GDALWMSDataset::~GDALWMSDataset() {
     if (m_mini_driver) delete m_mini_driver;
     if (m_cache) delete m_cache;
     if (m_poColorTable) delete m_poColorTable;
+    CSLDestroy(m_http_options);
+    CSLDestroy(m_tileOO);
 }
 
 /************************************************************************/
 /*                             Initialize()                             */
 /************************************************************************/
-CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
+CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config, char **l_papszOpenOptions) {
     CPLErr ret = CE_None;
 
     char* pszXML = CPLSerializeXMLTree( config );
@@ -97,60 +102,196 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
         CPLFree(pszXML);
     }
 
-    // Initialize the minidriver, which can set parameters for the dataset using member functions
-    CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
-    if (service_node != NULL)
-    {
-        const CPLString service_name = CPLGetXMLValue(service_node, "name", "");
-        if (!service_name.empty())
-        {
-            GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
-            GDALWMSMiniDriverFactory *const mdf = mdm->Find(service_name);
-            if (mdf != NULL)
-            {
-                m_mini_driver = mdf->New();
-                m_mini_driver->m_parent_dataset = this;
-                if (m_mini_driver->Initialize(service_node) == CE_None)
-                {
-                    m_mini_driver_caps.m_capabilities_version = -1;
-                    m_mini_driver->GetCapabilities(&m_mini_driver_caps);
-                    if (m_mini_driver_caps.m_capabilities_version == -1)
-                    {
-                        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Internal error, mini-driver capabilities version not set.");
-                        ret = CE_Failure;
-                    }
+    // Generic options that apply to all minidrivers
+
+    // UserPwd
+    const char *pszUserPwd = CPLGetXMLValue(config, "UserPwd", "");
+    if (pszUserPwd[0] != '\0')
+        m_osUserPwd = pszUserPwd;
+
+    const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
+    if (pszUserAgent[0] != '\0')
+        m_osUserAgent = pszUserAgent;
+    else
+        m_osUserAgent = CPLGetConfigOption("GDAL_HTTP_USERAGENT", "");
+
+    const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
+    if (pszReferer[0] != '\0')
+        m_osReferer = pszReferer;
+
+    if (ret == CE_None) {
+        const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
+        if (pszHttpZeroBlockCodes[0] == '\0') {
+            m_http_zeroblock_codes.insert(204);
+        }
+        else {
+            char **kv = CSLTokenizeString2(pszHttpZeroBlockCodes, ",", CSLT_HONOURSTRINGS);
+            for (int i = 0; i < CSLCount(kv); i++) {
+                int code = atoi(kv[i]);
+                if (code <= 0) {
+                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockHttpCodes "
+                        "\"%s\", comma separated HTTP response codes expected.", kv[i]);
+                    ret = CE_Failure;
+                    break;
                 }
-                else
-                {
-                    delete m_mini_driver;
-                    m_mini_driver = NULL;
+                m_http_zeroblock_codes.insert(code);
+            }
+            CSLDestroy(kv);
+        }
+    }
+
+    if (ret == CE_None) {
+        const char *pszZeroExceptions = CPLGetXMLValue(config, "ZeroBlockOnServerException", "");
+        if (pszZeroExceptions[0] != '\0') {
+            m_zeroblock_on_serverexceptions = StrToBool(pszZeroExceptions);
+            if (m_zeroblock_on_serverexceptions == -1) {
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockOnServerException "
+                    "\"%s\", true/false expected.", pszZeroExceptions);
+                ret = CE_Failure;
+            }
+        }
+    }
+
+    if (ret == CE_None) {
+        const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
+        if (max_conn[0] != '\0') {
+            m_http_max_conn = atoi(max_conn);
+        }
+        else {
+            m_http_max_conn = 2;
+        }
+    }
+
+    if (ret == CE_None) {
+        const char *timeout = CPLGetXMLValue(config, "Timeout", "");
+        if (timeout[0] != '\0') {
+            m_http_timeout = atoi(timeout);
+        }
+        else {
+            m_http_timeout = 300;
+        }
+    }
 
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
+    if (ret == CE_None) {
+        const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
+        if (offline_mode[0] != '\0') {
+            const int offline_mode_bool = StrToBool(offline_mode);
+            if (offline_mode_bool == -1) {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                    "GDALWMS: Invalid value of OfflineMode, true / false expected.");
+                ret = CE_Failure;
+            }
+            else {
+                m_offline_mode = offline_mode_bool;
+            }
+        }
+        else {
+            m_offline_mode = 0;
+        }
+    }
+
+    if (ret == CE_None) {
+        const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
+        if (advise_read[0] != '\0') {
+            const int advise_read_bool = StrToBool(advise_read);
+            if (advise_read_bool == -1) {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                    "GDALWMS: Invalid value of AdviseRead, true / false expected.");
+                ret = CE_Failure;
+            }
+            else {
+                m_use_advise_read = advise_read_bool;
+            }
+        }
+        else {
+            m_use_advise_read = 0;
+        }
+    }
+
+    if (ret == CE_None) {
+        const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
+        if (m_use_advise_read) {
+            if (verify_advise_read[0] != '\0') {
+                const int verify_advise_read_bool = StrToBool(verify_advise_read);
+                if (verify_advise_read_bool == -1) {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                        "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
                     ret = CE_Failure;
                 }
+                else {
+                    m_verify_advise_read = verify_advise_read_bool;
+                }
             }
-            else
-            {
+            else {
+                m_verify_advise_read = 1;
+            }
+        }
+    }
+
+    if (ret == CE_None) {
+        CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
+        if (cache_node != NULL) {
+            m_cache = new GDALWMSCache();
+            if (m_cache->Initialize(cache_node) != CE_None) {
+                delete m_cache;
+                m_cache = NULL;
                 CPLError(CE_Failure, CPLE_AppDefined,
-                         "GDALWMS: No mini-driver registered for '%s'.", service_name.c_str());
+                    "GDALWMS: Failed to initialize cache.");
                 ret = CE_Failure;
             }
         }
-        else
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
+    }
+
+    if (ret == CE_None) {
+        const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
+        if (v == -1) {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
             ret = CE_Failure;
         }
+        else {
+            m_unsafeSsl = v;
+        }
     }
-    else
+
+    // Initialize the minidriver, which can set parameters for the dataset using member functions
+    CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
+    if (service_node == NULL) {
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "GDALWMS: No Service specified.");
+        return CE_Failure;
+    }
+
+    const CPLString service_name = CPLGetXMLValue(service_node, "name", "");
+    if (service_name.empty()) {
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "GDALWMS: No Service name specified.");
+        return CE_Failure;
+    }
+
+    m_mini_driver = NewWMSMiniDriver(service_name);
+    if (m_mini_driver == NULL) {
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "GDALWMS: No mini-driver registered for '%s'.", service_name.c_str());
+        return CE_Failure;
+    }
+
+    // Set up minidriver
+    m_mini_driver->m_parent_dataset = this;
+    if (m_mini_driver->Initialize(service_node, l_papszOpenOptions) != CE_None)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
+        delete m_mini_driver;
+        m_mini_driver = NULL;
         ret = CE_Failure;
     }
-
+    else
+    {
+        m_mini_driver->GetCapabilities(&m_mini_driver_caps);
+    }
 
     /*
-      Parameters that could be set by minidriver already, based on server side information.
+      Parameters that could be set by minidriver already
       If the size is set, minidriver has done this already
       A "server" side minidriver needs to set at least:
       - Blocksize (x and y)
@@ -167,11 +308,14 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
 
         if (ret == CE_None)
         {
-            m_block_size_x = atoi(CPLGetXMLValue(config, "BlockSizeX", CPLString().Printf("%d", m_default_block_size_x)));
-            m_block_size_y = atoi(CPLGetXMLValue(config, "BlockSizeY", CPLString().Printf("%d", m_default_block_size_y)));
+            m_block_size_x = atoi(CPLGetXMLValue(config, "BlockSizeX",
+                CPLString().Printf("%d", m_default_block_size_x)));
+            m_block_size_y = atoi(CPLGetXMLValue(config, "BlockSizeY",
+                CPLString().Printf("%d", m_default_block_size_y)));
             if (m_block_size_x <= 0 || m_block_size_y <= 0)
             {
-                CPLError( CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
+                CPLError( CE_Failure, CPLE_AppDefined,
+                    "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
                 ret = CE_Failure;
             }
         }
@@ -181,7 +325,8 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
             m_clamp_requests = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
             if (m_clamp_requests<0)
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true/false expected.");
+                CPLError(CE_Failure, CPLE_AppDefined,
+                    "GDALWMS: Invalid value of ClampRequests, true/false expected.");
                 ret = CE_Failure;
             }
         }
@@ -218,9 +363,12 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
                 const char *sy = CPLGetXMLValue(data_window_node, "SizeY", "");
                 const char *tx = CPLGetXMLValue(data_window_node, "TileX", "0");
                 const char *ty = CPLGetXMLValue(data_window_node, "TileY", "0");
-                const char *tlevel = CPLGetXMLValue(data_window_node, "TileLevel", osDefaultTileLevel);
-                const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", osDefaultTileCountX);
-                const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", osDefaultTileCountY);
+                const char *tlevel =
+                    CPLGetXMLValue(data_window_node, "TileLevel", osDefaultTileLevel);
+                const char *str_tile_count_x =
+                    CPLGetXMLValue(data_window_node, "TileCountX", osDefaultTileCountX);
+                const char *str_tile_count_y =
+                    CPLGetXMLValue(data_window_node, "TileCountY", osDefaultTileCountY);
                 const char *y_origin = CPLGetXMLValue(data_window_node, "YOrigin", "default");
 
                 if (ret == CE_None)
@@ -235,7 +383,8 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
                     else
                     {
                         CPLError(CE_Failure, CPLE_AppDefined,
-                                 "GDALWMS: Mandatory elements of DataWindow missing: UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
+                                 "GDALWMS: Mandatory elements of DataWindow missing: "
+                                 "UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
                         ret = CE_Failure;
                     }
                 }
@@ -290,10 +439,18 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
                     }
                     else
                     {
-                        const int min_overview_size = MAX(32, MIN(m_block_size_x, m_block_size_y));
-                        double a = log(static_cast<double>(MIN(m_data_window.m_sx, m_data_window.m_sy))) / log(2.0)
-                            - log(static_cast<double>(min_overview_size)) / log(2.0);
-                        nOverviews = MAX(0, MIN(static_cast<int>(ceil(a)), 32));
+                        const int min_overview_size =
+                            std::max(32, std::min(m_block_size_x,
+                                                  m_block_size_y));
+                        double a =
+                            log(static_cast<double>(
+                                std::min(m_data_window.m_sx,
+                                         m_data_window.m_sy))) / log(2.0)
+                            - log(static_cast<double>(min_overview_size)) /
+                            log(2.0);
+                        nOverviews =
+                            std::max(0,
+                                     std::min(static_cast<int>(ceil(a)), 32));
                     }
                 }
                 if (ret == CE_None)
@@ -329,13 +486,16 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
         if (ret == CE_None)
         {
             const char *data_type = CPLGetXMLValue(config, "DataType", "Byte");
-            m_data_type = GDALGetDataTypeByName( data_type );
-            if ( m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount )
+            m_data_type = GDALGetDataTypeByName(data_type);
+            if (m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount)
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                    "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type);
                 ret = CE_Failure;
             }
+            else if (!STARTS_WITH(data_type, "Byte")) { // Valid, non-byte
+                m_tileOO = CSLSetNameValue(m_tileOO, "@DATATYPE", data_type);
+            }
         }
 
         // Initialize the bands and the overviews.  Assumes overviews are powers of two
@@ -373,122 +533,12 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
         }
     }
 
-    // UserPwd
-    const char *pszUserPwd = CPLGetXMLValue(config, "UserPwd", "");
-    if (pszUserPwd[0] != '\0')
-        m_osUserPwd = pszUserPwd;
-
-    const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
-    if (pszUserAgent[0] != '\0')
-        m_osUserAgent = pszUserAgent;
-
-    const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
-    if (pszReferer[0] != '\0')
-        m_osReferer = pszReferer;
-
-    if (ret == CE_None) {
-        const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
-        if(pszHttpZeroBlockCodes[0] == '\0') {
-            m_http_zeroblock_codes.push_back(204);
-        } else {
-            char **kv = CSLTokenizeString2(pszHttpZeroBlockCodes,",",CSLT_HONOURSTRINGS);
-            int nCount = CSLCount(kv);
-            for(int i=0; i<nCount; i++) {
-                int code = atoi(kv[i]);
-                if(code <= 0) {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockHttpCodes \"%s\", comma separated HTTP response codes expected.",
-                             kv[i]);
-                    ret = CE_Failure;
-                    break;
-                }
-                m_http_zeroblock_codes.push_back(code);
-            }
-            CSLDestroy(kv);
-        }
-    }
-
-    if (ret == CE_None) {
-        const char *pszZeroExceptions = CPLGetXMLValue(config, "ZeroBlockOnServerException", "");
-        if(pszZeroExceptions[0] != '\0') {
-            m_zeroblock_on_serverexceptions = StrToBool(pszZeroExceptions);
-            if (m_zeroblock_on_serverexceptions == -1) {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockOnServerException \"%s\", true/false expected.",
-                         pszZeroExceptions);
-                ret = CE_Failure;
-            }
-        }
-    }
-
-    if (ret == CE_None) {
-        const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
-        if (max_conn[0] != '\0') {
-            m_http_max_conn = atoi(max_conn);
-        } else {
-            m_http_max_conn = 2;
-        }
-    }
-    if (ret == CE_None) {
-        const char *timeout = CPLGetXMLValue(config, "Timeout", "");
-        if (timeout[0] != '\0') {
-            m_http_timeout = atoi(timeout);
-        } else {
-            m_http_timeout = 300;
-        }
-    }
-    if (ret == CE_None) {
-        const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
-        if (offline_mode[0] != '\0') {
-            const int offline_mode_bool = StrToBool(offline_mode);
-            if (offline_mode_bool == -1) {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
-                ret = CE_Failure;
-            } else {
-                m_offline_mode = offline_mode_bool;
-            }
-        } else {
-            m_offline_mode = 0;
-        }
-    }
-
-    if (ret == CE_None) {
-        const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
-        if (advise_read[0] != '\0') {
-            const int advise_read_bool = StrToBool(advise_read);
-            if (advise_read_bool == -1) {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
-                ret = CE_Failure;
-            } else {
-                m_use_advise_read = advise_read_bool;
-            }
-        } else {
-            m_use_advise_read = 0;
-        }
-    }
-
-    if (ret == CE_None) {
-        const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
-        if (m_use_advise_read) {
-            if (verify_advise_read[0] != '\0') {
-                const int verify_advise_read_bool = StrToBool(verify_advise_read);
-                if (verify_advise_read_bool == -1) {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
-                    ret = CE_Failure;
-                } else {
-                    m_verify_advise_read = verify_advise_read_bool;
-                }
-            } else {
-                m_verify_advise_read = 1;
-            }
-        }
-    }
-
     // Let the local configuration override the minidriver supplied projection
-
     if (ret == CE_None) {
         const char *proj = CPLGetXMLValue(config, "Projection", "");
         if (proj[0] != '\0') {
             m_projection = ProjToWKT(proj);
-            if (m_projection.size() == 0) {
+            if (m_projection.empty()) {
                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
                 ret = CE_Failure;
             }
@@ -511,30 +561,6 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
     }
 
     if (ret == CE_None) {
-        CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
-        if (cache_node != NULL) {
-            m_cache = new GDALWMSCache();
-            if (m_cache->Initialize(cache_node) != CE_None) {
-                delete m_cache;
-                m_cache = NULL;
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
-                ret = CE_Failure;
-            }
-        }
-    }
-
-    if (ret == CE_None) {
-    	const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
-    	if (v == -1) {
-	    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
-	    ret = CE_Failure;
-        } else {
-	    m_unsafeSsl = v;
-        }
-    }
-
-    if (ret == CE_None) {
-        /* If we do not have projection already set ask mini-driver. */
         if (!m_projection.size()) {
             const char *proj = m_mini_driver->GetProjectionInWKT();
             if (proj != NULL) {
@@ -543,6 +569,10 @@ CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
         }
     }
 
+    // Finish the minidriver initialization
+    if (ret == CE_None)
+        m_mini_driver->EndInit();
+
     return ret;
 }
 
@@ -567,7 +597,7 @@ CPLErr GDALWMSDataset::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy,
     m_hint.m_sy = sy;
     m_hint.m_overview = -1;
     m_hint.m_valid = true;
-    //	printf("[%p] GDALWMSDataset::IRasterIO(x0: %d, y0: %d, sx: %d, sy: %d, bsx: %d, bsy: %d, band_count: %d, band_map: %p)\n", this, x0, y0, sx, sy, bsx, bsy, band_count, band_map);
+    // printf("[%p] GDALWMSDataset::IRasterIO(x0: %d, y0: %d, sx: %d, sy: %d, bsx: %d, bsy: %d, band_count: %d, band_map: %p)\n", this, x0, y0, sx, sy, bsx, bsy, band_count, band_map);
     ret = GDALDataset::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, band_count, band_map,
                                  nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
     m_hint.m_valid = false;
@@ -663,3 +693,35 @@ const char *GDALWMSDataset::GetMetadataItem( const char * pszName,
 
     return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
 }
+
+// Builds a CSL of options or returns the previous one
+const char * const * GDALWMSDataset::GetHTTPRequestOpts()
+{
+    if (m_http_options != NULL)
+        return m_http_options;
+
+    char **opts = NULL;
+    if (m_http_timeout != -1)
+        opts = CSLAddString(opts, CPLOPrintf("TIMEOUT=%d", m_http_timeout));
+
+    if (!m_osUserAgent.empty())
+        opts = CSLAddNameValue(opts, "USERAGENT", m_osUserAgent);
+    else
+        opts = CSLAddString(opts, "USERAGENT=GDAL WMS driver (http://www.gdal.org/frmt_wms.html)");
+
+    if (!m_osReferer.empty())
+        opts = CSLAddNameValue(opts, "REFERER", m_osReferer);
+
+    if (m_unsafeSsl >= 1)
+        opts = CSLAddString(opts, "UNSAFESSL=1");
+
+    if (!m_osUserPwd.empty())
+        opts = CSLAddNameValue(opts, "USERPWD", m_osUserPwd);
+
+    if (m_http_max_conn > 0)
+        opts = CSLAddString(opts, CPLOPrintf("MAXCONN=%d", m_http_max_conn));
+
+    m_http_options = opts;
+    return m_http_options;
+}
+
diff --git a/frmts/wms/gdalwmsrasterband.cpp b/frmts/wms/gdalwmsrasterband.cpp
index 8a53692..eb818bd 100644
--- a/frmts/wms/gdalwmsrasterband.cpp
+++ b/frmts/wms/gdalwmsrasterband.cpp
@@ -1,886 +1,912 @@
-/******************************************************************************
- * $Id: gdalwmsrasterband.cpp 33717 2016-03-14 06:29:14Z goatbar $
- *
- * Project:  WMS Client Driver
- * Purpose:  GDALWMSRasterBand implementation.
- * Author:   Adam Nowacki, nowak at xpam.de
- *
- ******************************************************************************
- * Copyright (c) 2007, Adam Nowacki
- * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "wmsdriver.h"
-
-GDALWMSRasterBand::GDALWMSRasterBand(GDALWMSDataset *parent_dataset, int band, double scale) {
-    //	printf("[%p] GDALWMSRasterBand::GDALWMSRasterBand(%p, %d, %f)\n", this, parent_dataset, band, scale);
-    m_parent_dataset = parent_dataset;
-    m_scale = scale;
-    m_overview = -1;
-    m_color_interp = GCI_Undefined;
-
-    if( scale == 1.0 )
-        poDS = parent_dataset;
-    else
-        poDS = NULL;
-    if( parent_dataset->m_mini_driver_caps.m_overview_dim_computation_method == OVERVIEW_ROUNDED )
-    {
-        nRasterXSize = static_cast<int>(m_parent_dataset->m_data_window.m_sx * scale + 0.5);
-        nRasterYSize = static_cast<int>(m_parent_dataset->m_data_window.m_sy * scale + 0.5);
-    }
-    else
-    {
-        nRasterXSize = static_cast<int>(m_parent_dataset->m_data_window.m_sx * scale);
-        nRasterYSize = static_cast<int>(m_parent_dataset->m_data_window.m_sy * scale);
-    }
-    nBand = band;
-    eDataType = m_parent_dataset->m_data_type;
-    nBlockXSize = m_parent_dataset->m_block_size_x;
-    nBlockYSize = m_parent_dataset->m_block_size_y;
-}
-
-GDALWMSRasterBand::~GDALWMSRasterBand() {
-    for (std::vector<GDALWMSRasterBand *>::iterator it = m_overviews.begin(); it != m_overviews.end(); ++it) {
-        GDALWMSRasterBand *p = *it;
-        delete p;
-    }
-}
-
-char** GDALWMSRasterBand::BuildHTTPRequestOpts()
-{
-    char **http_request_opts = NULL;
-    if (m_parent_dataset->m_http_timeout != -1) {
-        CPLString http_request_optstr;
-        http_request_optstr.Printf("TIMEOUT=%d", m_parent_dataset->m_http_timeout);
-        http_request_opts = CSLAddString(http_request_opts, http_request_optstr.c_str());
-    }
-
-    if (m_parent_dataset->m_osUserAgent.size() != 0)
-    {
-        CPLString osUserAgentOptStr("USERAGENT=");
-        osUserAgentOptStr += m_parent_dataset->m_osUserAgent;
-        http_request_opts = CSLAddString(http_request_opts, osUserAgentOptStr.c_str());
-    }
-    if (m_parent_dataset->m_osReferer.size() != 0)
-    {
-        CPLString osRefererOptStr("REFERER=");
-        osRefererOptStr += m_parent_dataset->m_osReferer;
-        http_request_opts = CSLAddString(http_request_opts, osRefererOptStr.c_str());
-    }
-    if (m_parent_dataset->m_unsafeSsl >= 1) {
-        http_request_opts = CSLAddString(http_request_opts, "UNSAFESSL=1");
-    }
-    if (m_parent_dataset->m_osUserPwd.size() != 0)
-    {
-        CPLString osUserPwdOptStr("USERPWD=");
-        osUserPwdOptStr += m_parent_dataset->m_osUserPwd;
-        http_request_opts = CSLAddString(http_request_opts, osUserPwdOptStr.c_str());
-    }
-
-   return http_request_opts;
-}
-
-CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by0, int bx1, int by1, int advise_read) {
-    CPLErr ret = CE_None;
-    int i;
-
-    int max_request_count = (bx1 - bx0 + 1) * (by1 - by0 + 1);
-    int request_count = 0;
-    CPLHTTPRequest *download_requests = NULL;
-    GDALWMSCache *cache = m_parent_dataset->m_cache;
-    struct BlockXY {
-        int x, y;
-    } *download_blocks = NULL;
-    if (!m_parent_dataset->m_offline_mode) {
-        download_requests = new CPLHTTPRequest[max_request_count];
-        download_blocks = new BlockXY[max_request_count];
-    }
-
-    char **http_request_opts = BuildHTTPRequestOpts();
-
-    for (int iy = by0; iy <= by1; ++iy) {
-        for (int ix = bx0; ix <= bx1; ++ix) {
-            bool need_this_block = false;
-            if (!advise_read) {
-                for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
-                    if ((ix == x) && (iy == y) && (ib == nBand)) {
-                        need_this_block = true;
-                    } else {
-                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
-                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
-                        if (!band->IsBlockInCache(ix, iy)) need_this_block = true;
-                    }
-                }
-            } else {
-                need_this_block = true;
-            }
-            CPLString url;
-            if (need_this_block) {
-                CPLString file_name;
-                AskMiniDriverForBlock(&url, ix, iy);
-                if ((cache != NULL) && (cache->Read(url.c_str(), &file_name) == CE_None)) {
-                    if (advise_read) {
-                        need_this_block = false;
-                    } else {
-                        void *p = NULL;
-                        if ((ix == x) && (iy == y)) p = buffer;
-                        if (ReadBlockFromFile(ix, iy, file_name.c_str(), nBand, p, 0) == CE_None) need_this_block = false;
-                    }
-                }
-            }
-            if (need_this_block) {
-                if (/*m_parent_dataset->m_offline_mode */ download_blocks == NULL) {
-                    if (!advise_read) {
-                        void *p = NULL;
-                        if ((ix == x) && (iy == y)) p = buffer;
-                        if (ZeroBlock(ix, iy, nBand, p) != CE_None) {
-                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
-                            ret = CE_Failure;
-                        }
-                    }
-                } else {
-                    CPLHTTPInitializeRequest(&download_requests[request_count], url.c_str(), http_request_opts);
-                    download_blocks[request_count].x = ix;
-                    download_blocks[request_count].y = iy;
-                    ++request_count;
-                }
-            }
-        }
-    }
-    if (http_request_opts != NULL) {
-        CSLDestroy(http_request_opts);
-    }
-
-    if (request_count > 0) {
-        char **opts = NULL;
-        CPLString optstr;
-        if (m_parent_dataset->m_http_max_conn != -1) {
-            optstr.Printf("MAXCONN=%d", m_parent_dataset->m_http_max_conn);
-            opts = CSLAddString(opts, optstr.c_str());
-        }
-        if (CPLHTTPFetchMulti(download_requests, request_count, opts) != CE_None) {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: CPLHTTPFetchMulti failed.");
-            ret = CE_Failure;
-        }
-        if (opts != NULL) {
-            CSLDestroy(opts);
-        }
-    }
-
-    for (i = 0; i < request_count; ++i) {
-        if (ret == CE_None) {
-            if ((download_requests[i].nStatus == 200) && (download_requests[i].pabyData != NULL) && (download_requests[i].nDataLen > 0)) {
-                CPLString file_name(BufferToVSIFile(download_requests[i].pabyData, download_requests[i].nDataLen));
-                if (file_name.size() > 0) {
-                    bool wms_exception = false;
-                    /* check for error xml */
-                    if (download_requests[i].nDataLen >= 20) {
-                        const char *download_data = reinterpret_cast<char *>(download_requests[i].pabyData);
-                        if (STARTS_WITH_CI(download_data, "<?xml ")
-                        || STARTS_WITH_CI(download_data, "<!DOCTYPE ")
-                        || STARTS_WITH_CI(download_data, "<ServiceException")) {
-                            if (ReportWMSException(file_name.c_str()) != CE_None) {
-                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned unknown exception.");
-                            }
-                            wms_exception = true;
-                            ret = CE_Failure;
-                        }
-                    }
-                    if (ret == CE_None) {
-                        if (advise_read && !m_parent_dataset->m_verify_advise_read) {
-                            if (cache != NULL) {
-                                cache->Write(download_requests[i].pszURL, file_name);
-                            }
-                        } else {
-                            void *p = NULL;
-                            if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
-                            if (ReadBlockFromFile(download_blocks[i].x, download_blocks[i].y, file_name.c_str(), nBand, p, advise_read) == CE_None) {
-                                if (cache != NULL) {
-                                    cache->Write(download_requests[i].pszURL, file_name);
-                                }
-                            } else {
-                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ReadBlockFromFile (%s) failed.",
-                                         download_requests[i].pszURL);
-                                ret = CE_Failure;
-                            }
-                        }
-                    } else if( wms_exception && m_parent_dataset->m_zeroblock_on_serverexceptions ) {
-                         void *p = NULL;
-                         if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
-                         if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
-                             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
-                         } else {
-                             ret = CE_None;
-                         }
-
-                    }
-                    VSIUnlink(file_name.c_str());
-                }
-            } else {
-               std::vector<int>::iterator zero_it = std::find(
-                     m_parent_dataset->m_http_zeroblock_codes.begin(),
-                     m_parent_dataset->m_http_zeroblock_codes.end(),
-                     download_requests[i].nStatus);
-               if ( zero_it != m_parent_dataset->m_http_zeroblock_codes.end() ) {
-                    if (!advise_read) {
-                        void *p = NULL;
-                        if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
-                        if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
-                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
-                            ret = CE_Failure;
-                        }
-                    }
-                } else {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to download block %d, %d.\n  URL: %s\n  HTTP status code: %d, error: %s.\n"
-                        "Add the HTTP status code to <ZeroBlockHttpCodes> to ignore that error (see http://www.gdal.org/frmt_wms.html).",
-                        download_blocks[i].x, download_blocks[i].y, download_requests[i].pszURL, download_requests[i].nStatus,
-		    download_requests[i].pszError ? download_requests[i].pszError : "(null)");
-                    ret = CE_Failure;
-                }
-            }
-        }
-        CPLHTTPCleanupRequest(&download_requests[i]);
-    }
-    if (!m_parent_dataset->m_offline_mode) {
-        delete[] download_blocks;
-        delete[] download_requests;
-    }
-
-    return ret;
-}
-
-CPLErr GDALWMSRasterBand::IReadBlock(int x, int y, void *buffer) {
-    int bx0 = x;
-    int by0 = y;
-    int bx1 = x;
-    int by1 = y;
-
-    if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview)) {
-        int tbx0 = m_parent_dataset->m_hint.m_x0 / nBlockXSize;
-        int tby0 = m_parent_dataset->m_hint.m_y0 / nBlockYSize;
-        int tbx1 = (m_parent_dataset->m_hint.m_x0 + m_parent_dataset->m_hint.m_sx - 1) / nBlockXSize;
-        int tby1 = (m_parent_dataset->m_hint.m_y0 + m_parent_dataset->m_hint.m_sy - 1) / nBlockYSize;
-        if ((tbx0 <= bx0) && (tby0 <= by0) && (tbx1 >= bx1) && (tby1 >= by1)) {
-            bx0 = tbx0;
-            by0 = tby0;
-            bx1 = tbx1;
-            by1 = tby1;
-        }
-    }
-
-    CPLErr eErr = ReadBlocks(x, y, buffer, bx0, by0, bx1, by1, 0);
-
-    if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview))
-    {
-        m_parent_dataset->m_hint.m_valid = false;
-    }
-
-    return eErr;
-}
-
-CPLErr GDALWMSRasterBand::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy,
-                                    void *buffer, int bsx, int bsy, GDALDataType bdt,
-                                    GSpacing nPixelSpace, GSpacing nLineSpace,
-                                    GDALRasterIOExtraArg* psExtraArg) {
-    CPLErr ret;
-
-    if (rw != GF_Read) return CE_Failure;
-    if (buffer == NULL) return CE_Failure;
-    if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0)) return CE_None;
-
-    m_parent_dataset->m_hint.m_x0 = x0;
-    m_parent_dataset->m_hint.m_y0 = y0;
-    m_parent_dataset->m_hint.m_sx = sx;
-    m_parent_dataset->m_hint.m_sy = sy;
-    m_parent_dataset->m_hint.m_overview = m_overview;
-    m_parent_dataset->m_hint.m_valid = true;
-    ret = GDALRasterBand::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, nPixelSpace, nLineSpace, psExtraArg);
-    m_parent_dataset->m_hint.m_valid = false;
-
-    return ret;
-}
-
-int GDALWMSRasterBand::HasArbitraryOverviews() {
-//    return m_parent_dataset->m_mini_driver_caps.m_has_arb_overviews;
-    return 0; // not implemented yet
-}
-
-int GDALWMSRasterBand::GetOverviewCount() {
-    return static_cast<int>(m_overviews.size());
-}
-
-GDALRasterBand *GDALWMSRasterBand::GetOverview(int n) {
-    if ((m_overviews.size() > 0) && (static_cast<size_t>(n) < m_overviews.size())) return m_overviews[n];
-    else return NULL;
-}
-
-void GDALWMSRasterBand::AddOverview(double scale) {
-    GDALWMSRasterBand *overview = new GDALWMSRasterBand(m_parent_dataset, nBand, scale);
-    std::vector<GDALWMSRasterBand *>::iterator it = m_overviews.begin();
-    for (; it != m_overviews.end(); ++it) {
-        GDALWMSRasterBand *p = *it;
-        if (p->m_scale < scale) break;
-    }
-    m_overviews.insert(it, overview);
-    it = m_overviews.begin();
-    for (int i = 0; it != m_overviews.end(); ++it, ++i) {
-        GDALWMSRasterBand *p = *it;
-        p->m_overview = i;
-    }
-}
-
-bool GDALWMSRasterBand::IsBlockInCache(int x, int y) {
-    bool ret = false;
-    GDALRasterBlock *b = TryGetLockedBlockRef(x, y);
-    if (b != NULL) {
-        ret = true;
-        b->DropLock();
-    }
-    return ret;
-}
-
-// This is the function that calculates the block coordinates for the fetch
-void GDALWMSRasterBand::AskMiniDriverForBlock(CPLString *url, int x, int y)
-{
-    GDALWMSImageRequestInfo iri;
-    GDALWMSTiledImageRequestInfo tiri;
-
-    ComputeRequestInfo(iri, tiri, x, y);
-
-    m_parent_dataset->m_mini_driver->TiledImageRequest(url, iri, tiri);
-}
-
-void GDALWMSRasterBand::ComputeRequestInfo(GDALWMSImageRequestInfo &iri,
-                                           GDALWMSTiledImageRequestInfo &tiri,
-                                           int x, int y)
-{
-    int x0 = MAX(0, x * nBlockXSize);
-    int y0 = MAX(0, y * nBlockYSize);
-    int x1 = MAX(0, (x + 1) * nBlockXSize);
-    int y1 = MAX(0, (y + 1) * nBlockYSize);
-    if (m_parent_dataset->m_clamp_requests) {
-	x0 = MIN(x0, nRasterXSize);
-	y0 = MIN(y0, nRasterYSize);
-	x1 = MIN(x1, nRasterXSize);
-	y1 = MIN(y1, nRasterYSize);
-    }
-
-    const double rx = (m_parent_dataset->m_data_window.m_x1 - m_parent_dataset->m_data_window.m_x0) / static_cast<double>(nRasterXSize);
-    const double ry = (m_parent_dataset->m_data_window.m_y1 - m_parent_dataset->m_data_window.m_y0) / static_cast<double>(nRasterYSize);
-    /* Use different method for x0,y0 and x1,y1 to make sure calculated values are exact for corner requests */
-    iri.m_x0 = x0 * rx + m_parent_dataset->m_data_window.m_x0;
-    iri.m_y0 = y0 * ry + m_parent_dataset->m_data_window.m_y0;
-    iri.m_x1 = m_parent_dataset->m_data_window.m_x1 - (nRasterXSize - x1) * rx;
-    iri.m_y1 = m_parent_dataset->m_data_window.m_y1 - (nRasterYSize - y1) * ry;
-    iri.m_sx = x1 - x0;
-    iri.m_sy = y1 - y0;
-
-    int level = m_overview + 1;
-    tiri.m_x = (m_parent_dataset->m_data_window.m_tx >> level) + x;
-    tiri.m_y = (m_parent_dataset->m_data_window.m_ty >> level) + y;
-    tiri.m_level = m_parent_dataset->m_data_window.m_tlevel - level;
-}
-
-
-/************************************************************************/
-/*                      GetMetadataDomainList()                         */
-/************************************************************************/
-
-char **GDALWMSRasterBand::GetMetadataDomainList()
-{
-    return CSLAddString(GDALPamRasterBand::GetMetadataDomainList(), "LocationInfo");
-}
-
-const char *GDALWMSRasterBand::GetMetadataItem( const char * pszName,
-                                                const char * pszDomain )
-{
-/* ==================================================================== */
-/*      LocationInfo handling.                                          */
-/* ==================================================================== */
-    if( pszDomain != NULL
-        && EQUAL(pszDomain,"LocationInfo")
-        && (STARTS_WITH_CI(pszName, "Pixel_") || STARTS_WITH_CI(pszName, "GeoPixel_")) )
-    {
-        int iPixel, iLine;
-
-/* -------------------------------------------------------------------- */
-/*      What pixel are we aiming at?                                    */
-/* -------------------------------------------------------------------- */
-        if( STARTS_WITH_CI(pszName, "Pixel_") )
-        {
-            if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
-                return NULL;
-        }
-        else if( STARTS_WITH_CI(pszName, "GeoPixel_") )
-        {
-            double adfGeoTransform[6];
-            double adfInvGeoTransform[6];
-            double dfGeoX, dfGeoY;
-
-            {
-                dfGeoX = CPLAtof(pszName + 9);
-                const char* pszUnderscore = strchr(pszName + 9, '_');
-                if( !pszUnderscore )
-                    return NULL;
-                dfGeoY = CPLAtof(pszUnderscore+1);
-            }
-
-            if( m_parent_dataset->GetGeoTransform( adfGeoTransform ) != CE_None )
-                return NULL;
-
-            if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
-                return NULL;
-
-            iPixel = (int) floor(
-                adfInvGeoTransform[0]
-                + adfInvGeoTransform[1] * dfGeoX
-                + adfInvGeoTransform[2] * dfGeoY );
-            iLine = (int) floor(
-                adfInvGeoTransform[3]
-                + adfInvGeoTransform[4] * dfGeoX
-                + adfInvGeoTransform[5] * dfGeoY );
-
-            /* The GetDataset() for the WMS driver is always the main overview level, so rescale */
-            /* the values if we are an overview */
-            if (m_overview >= 0)
-            {
-                iPixel = (int) (1.0 * iPixel * GetXSize() / m_parent_dataset->GetRasterBand(1)->GetXSize());
-                iLine = (int) (1.0 * iLine * GetYSize() / m_parent_dataset->GetRasterBand(1)->GetYSize());
-            }
-        }
-        else
-            return NULL;
-
-        if( iPixel < 0 || iLine < 0
-            || iPixel >= GetXSize()
-            || iLine >= GetYSize() )
-            return NULL;
-
-        if (nBand != 1)
-        {
-            GDALRasterBand* poFirstBand = m_parent_dataset->GetRasterBand(1);
-            if (m_overview >= 0)
-                poFirstBand = poFirstBand->GetOverview(m_overview);
-            if (poFirstBand)
-                return poFirstBand->GetMetadataItem(pszName, pszDomain);
-        }
-
-        GDALWMSImageRequestInfo iri;
-        GDALWMSTiledImageRequestInfo tiri;
-        int nBlockXOff = iPixel / nBlockXSize;
-        int nBlockYOff = iLine / nBlockYSize;
-
-        ComputeRequestInfo(iri, tiri, nBlockXOff, nBlockYOff);
-
-        CPLString url;
-        m_parent_dataset->m_mini_driver->GetTiledImageInfo(&url,
-                                                           iri, tiri,
-                                                           iPixel % nBlockXSize,
-                                                           iLine % nBlockXSize);
-
-
-        char* pszRes = NULL;
-
-        if (url.size() != 0)
-        {
-            if (url == osMetadataItemURL)
-            {
-                return osMetadataItem.size() != 0 ? osMetadataItem.c_str() : NULL;
-            }
-            osMetadataItemURL = url;
-
-            char **http_request_opts = BuildHTTPRequestOpts();
-            CPLHTTPResult* psResult = CPLHTTPFetch( url.c_str(), http_request_opts);
-            if( psResult && psResult->pabyData )
-                pszRes = CPLStrdup((const char*) psResult->pabyData);
-            CPLHTTPDestroyResult(psResult);
-            CSLDestroy(http_request_opts);
-        }
-
-        if (pszRes)
-        {
-            osMetadataItem = "<LocationInfo>";
-            CPLPushErrorHandler(CPLQuietErrorHandler);
-            CPLXMLNode* psXML = CPLParseXMLString(pszRes);
-            CPLPopErrorHandler();
-            if (psXML != NULL && psXML->eType == CXT_Element)
-            {
-                if (strcmp(psXML->pszValue, "?xml") == 0)
-                {
-                    if (psXML->psNext)
-                    {
-                        char* pszXML = CPLSerializeXMLTree(psXML->psNext);
-                        osMetadataItem += pszXML;
-                        CPLFree(pszXML);
-                    }
-                }
-                else
-                {
-                    osMetadataItem += pszRes;
-                }
-            }
-            else
-            {
-                char* pszEscapedXML = CPLEscapeString(pszRes, -1, CPLES_XML_BUT_QUOTES);
-                osMetadataItem += pszEscapedXML;
-                CPLFree(pszEscapedXML);
-            }
-            if (psXML != NULL)
-                CPLDestroyXMLNode(psXML);
-
-            osMetadataItem += "</LocationInfo>";
-            CPLFree(pszRes);
-            return osMetadataItem.c_str();
-        }
-        else
-        {
-            osMetadataItem = "";
-            return NULL;
-        }
-    }
-
-    return GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
-}
-
-CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name, int to_buffer_band, void *buffer, int advise_read) {
-    CPLErr ret = CE_None;
-    GDALDataset *ds = NULL;
-    GByte *color_table = NULL;
-    int i;
-
-    //CPLDebug("WMS", "ReadBlockFromFile: to_buffer_band=%d, (x,y)=(%d, %d)", to_buffer_band, x, y);
-
-    /* expected size */
-    const int esx = MIN(MAX(0, (x + 1) * nBlockXSize), nRasterXSize) - MIN(MAX(0, x * nBlockXSize), nRasterXSize);
-    const int esy = MIN(MAX(0, (y + 1) * nBlockYSize), nRasterYSize) - MIN(MAX(0, y * nBlockYSize), nRasterYSize);
-    ds = reinterpret_cast<GDALDataset*>(GDALOpen(file_name, GA_ReadOnly));
-    if (ds != NULL) {
-        int sx = ds->GetRasterXSize();
-        int sy = ds->GetRasterYSize();
-        bool accepted_as_no_alpha = false;  // if the request is for 4 bands but the wms returns 3
-        /* Allow bigger than expected so pre-tiled constant size images work on corners */
-        if ((sx > nBlockXSize) || (sy > nBlockYSize) || (sx < esx) || (sy < esy)) {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect size %d x %d of downloaded block, expected %d x %d, max %d x %d.",
-                sx, sy, esx, esy, nBlockXSize, nBlockYSize);
-            ret = CE_Failure;
-        }
-        if (ret == CE_None) {
-            int nDSRasterCount = ds->GetRasterCount();
-            if (nDSRasterCount != m_parent_dataset->nBands) {
-                /* Maybe its an image with color table */
-                bool accepted_as_ct = false;
-                if ((eDataType == GDT_Byte) && (ds->GetRasterCount() == 1)) {
-                    GDALRasterBand *rb = ds->GetRasterBand(1);
-                    if (rb->GetRasterDataType() == GDT_Byte) {
-                        GDALColorTable *ct = rb->GetColorTable();
-                        if (ct != NULL) {
-                            accepted_as_ct = true;
-                            if (!advise_read) {
-                                color_table = new GByte[256 * 4];
-                                const int count = MIN(256, ct->GetColorEntryCount());
-                                for (i = 0; i < count; ++i) {
-                                    GDALColorEntry ce;
-                                    ct->GetColorEntryAsRGB(i, &ce);
-                                    color_table[i] = static_cast<GByte>(ce.c1);
-                                    color_table[i + 256] = static_cast<GByte>(ce.c2);
-                                    color_table[i + 512] = static_cast<GByte>(ce.c3);
-                                    color_table[i + 768] = static_cast<GByte>(ce.c4);
-                                }
-                                for (i = count; i < 256; ++i) {
-                                    color_table[i] = 0;
-                                    color_table[i + 256] = 0;
-                                    color_table[i + 512] = 0;
-                                    color_table[i + 768] = 0;
-                                }
-                            }
-                        }
-                    }
-                }
-
-                if (nDSRasterCount == 4 && m_parent_dataset->nBands == 3)
-                {
-                    /* metacarta TMS service sometimes return a 4 band PNG instead of the expected 3 band... */
-                }
-                else if (!accepted_as_ct) {
-                   if (ds->GetRasterCount()==3 && m_parent_dataset->nBands == 4 && (eDataType == GDT_Byte))
-                   { // WMS returned a file with no alpha so we will fill the alpha band with "opaque"
-                      accepted_as_no_alpha = true;
-                   }
-                   else
-                   {
-                      CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
-                         nDSRasterCount, m_parent_dataset->nBands);
-                      ret = CE_Failure;
-                   }
-                }
-            }
-        }
-        if (!advise_read) {
-            for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
-                if (ret == CE_None) {
-                    void *p = NULL;
-                    GDALRasterBlock *b = NULL;
-                    if ((buffer != NULL) && (ib == to_buffer_band)) {
-                        p = buffer;
-                    } else {
-                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
-                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
-                        if (!band->IsBlockInCache(x, y)) {
-                            b = band->GetLockedBlockRef(x, y, true);
-                            if (b != NULL) {
-                                p = b->GetDataRef();
-                                if (p == NULL) {
-                                  CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
-                                  ret = CE_Failure;
-                                }
-                            }
-                        }
-                        else
-                        {
-                            //CPLDebug("WMS", "Band %d, block (x,y)=(%d, %d) already in cache", band->GetBand(), x, y);
-                        }
-                    }
-                    if (p != NULL) {
-                        int pixel_space = GDALGetDataTypeSize(eDataType) / 8;
-                        int line_space = pixel_space * nBlockXSize;
-                        if (color_table == NULL) {
-                            if( ib <= ds->GetRasterCount()) {
-				GDALDataType dt=eDataType;
-				// Get the data from the PNG as stored instead of converting, if the server asks for that
-                                // TODO: This hack is from #3493 - not sure it really belongs here.
-				if ((GDT_Int16==dt)&&(GDT_UInt16==ds->GetRasterBand(ib)->GetRasterDataType()))
-				    dt=GDT_UInt16;
-				if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, dt, 1, &ib, pixel_space, line_space, 0, NULL) != CE_None) {
-				    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
-				    ret = CE_Failure;
-				}
-                            }
-                            else
-                            {  // parent expects 4 bands but file only has 3 so generate a all "opaque" 4th band
-                               if (accepted_as_no_alpha)
-                               {
-                                  // the file had 3 bands and we are reading band 4 (Alpha) so fill with 255 (no alpha)
-                                  GByte *byte_buffer = reinterpret_cast<GByte *>(p);
-                                  for (int l_y = 0; l_y < sy; ++l_y) {
-                                     for (int l_x = 0; l_x < sx; ++l_x) {
-                                        const int offset = l_x + l_y * line_space;
-                                        byte_buffer[offset] = 255;  // fill with opaque
-                                     }
-                                  }
-                               }
-                               else
-                               {  // we should never get here because this case was caught above
-                                  CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
-                                     ds->GetRasterCount(), m_parent_dataset->nBands);
-                                  ret = CE_Failure;
-                               }
-                            }
-                        } else if (ib <= 4) {
-                            if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, eDataType, 1, NULL, pixel_space, line_space, 0, NULL) != CE_None) {
-                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
-                                ret = CE_Failure;
-                            }
-                            if (ret == CE_None) {
-                                GByte *band_color_table = color_table + 256 * (ib - 1);
-                                GByte *byte_buffer = reinterpret_cast<GByte *>(p);
-                                for (int l_y = 0; l_y < sy; ++l_y) {
-                                    for (int l_x = 0; l_x < sx; ++l_x) {
-                                        const int offset = l_x + l_y * line_space;
-                                        byte_buffer[offset] = band_color_table[byte_buffer[offset]];
-                                    }
-                                }
-                            }
-                        } else {
-                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Color table supports at most 4 components.");
-                            ret = CE_Failure;
-                        }
-                    }
-                    if (b != NULL) {
-                        b->DropLock();
-                    }
-                }
-            }
-        }
-        GDALClose(ds);
-    } else {
-        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to open downloaded block.");
-        ret = CE_Failure;
-    }
-
-    if (color_table != NULL) {
-        delete[] color_table;
-    }
-
-    return ret;
-}
-
-CPLErr GDALWMSRasterBand::ZeroBlock(int x, int y, int to_buffer_band, void *buffer) {
-    CPLErr ret = CE_None;
-
-    for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
-        if (ret == CE_None) {
-            void *p = NULL;
-            GDALRasterBlock *b = NULL;
-            if ((buffer != NULL) && (ib == to_buffer_band)) {
-                p = buffer;
-            } else {
-                GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
-                if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
-                if (!band->IsBlockInCache(x, y)) {
-                    b = band->GetLockedBlockRef(x, y, true);
-                    if (b != NULL) {
-                        p = b->GetDataRef();
-                        if (p == NULL) {
-                          CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
-                          ret = CE_Failure;
-                        }
-                    }
-                }
-            }
-            if (p != NULL) {
-                unsigned char *paby = reinterpret_cast<unsigned char *>(p);
-                int block_size = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
-                for (int i = 0; i < block_size; ++i) paby[i] = 0;
-            }
-            if (b != NULL) {
-                b->DropLock();
-            }
-        }
-    }
-
-    return ret;
-}
-
-CPLErr GDALWMSRasterBand::ReportWMSException(const char *file_name) {
-    CPLErr ret = CE_None;
-    int reported_errors_count = 0;
-
-    CPLXMLNode *orig_root = CPLParseXMLFile(file_name);
-    CPLXMLNode *root = orig_root;
-    if (root != NULL) {
-        root = CPLGetXMLNode(root, "=ServiceExceptionReport");
-    }
-    if (root != NULL) {
-        CPLXMLNode *n = CPLGetXMLNode(root, "ServiceException");
-        while (n != NULL) {
-            const char *exception = CPLGetXMLValue(n, "=ServiceException", "");
-            const char *exception_code = CPLGetXMLValue(n, "=ServiceException.code", "");
-            if (exception[0] != '\0') {
-                if (exception_code[0] != '\0') {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s': %s", exception_code, exception);
-                    ++reported_errors_count;
-                } else {
-                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception: %s", exception);
-                    ++reported_errors_count;
-                }
-            } else if (exception_code[0] != '\0') {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s'.", exception_code);
-                ++reported_errors_count;
-            }
-
-            n = n->psNext;
-            if (n != NULL) {
-                n = CPLGetXMLNode(n, "=ServiceException");
-            }
-        }
-    } else {
-        ret = CE_Failure;
-    }
-    if (orig_root != NULL) {
-        CPLDestroyXMLNode(orig_root);
-    }
-
-    if (reported_errors_count == 0) {
-        ret = CE_Failure;
-    }
-
-    return ret;
-}
-
-
-CPLErr GDALWMSRasterBand::AdviseRead(int x0, int y0,
-                                     int sx, int sy,
-                                     CPL_UNUSED int bsx,
-                                     CPL_UNUSED int bsy,
-                                     CPL_UNUSED GDALDataType bdt,
-                                     CPL_UNUSED char **options) {
-//    printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
-    if (m_parent_dataset->m_offline_mode || !m_parent_dataset->m_use_advise_read) return CE_None;
-    if (m_parent_dataset->m_cache == NULL) return CE_Failure;
-
-    int bx0 = x0 / nBlockXSize;
-    int by0 = y0 / nBlockYSize;
-    int bx1 = (x0 + sx - 1) / nBlockXSize;
-    int by1 = (y0 + sy - 1) / nBlockYSize;
-
-    return ReadBlocks(0, 0, NULL, bx0, by0, bx1, by1, 1);
-}
-
-GDALColorInterp GDALWMSRasterBand::GetColorInterpretation() {
-    return m_color_interp;
-}
-
-CPLErr GDALWMSRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
-{
-    m_color_interp = eNewInterp;
-    return CE_None;
-}
-
-// Utility function, returns a value from a vector corresponding to the band index
-// or the first entry
-static double getBandValue(std::vector<double> &v,size_t idx)
-{
-    idx--;
-    if (v.size()>idx) return v[idx];
-    return v[0];
-}
-
-double GDALWMSRasterBand::GetNoDataValue( int *pbSuccess)
-{
-    std::vector<double> &v=m_parent_dataset->vNoData;
-    if (v.size()==0)
-        return GDALPamRasterBand::GetNoDataValue(pbSuccess);
-    if (pbSuccess) *pbSuccess=TRUE;
-    return getBandValue(v,nBand);
-}
-
-double GDALWMSRasterBand::GetMinimum( int *pbSuccess)
-{
-    std::vector<double> &v=m_parent_dataset->vMin;
-    if (v.size()==0)
-        return GDALPamRasterBand::GetMinimum(pbSuccess);
-    if (pbSuccess) *pbSuccess=TRUE;
-    return getBandValue(v,nBand);
-}
-
-double GDALWMSRasterBand::GetMaximum( int *pbSuccess)
-{
-    std::vector<double> &v=m_parent_dataset->vMax;
-    if (v.size()==0)
-        return GDALPamRasterBand::GetMaximum(pbSuccess);
-    if (pbSuccess) *pbSuccess=TRUE;
-    return getBandValue(v,nBand);
-}
-
-GDALColorTable *GDALWMSRasterBand::GetColorTable()
-{
-    return m_parent_dataset->m_poColorTable;
-}
+/******************************************************************************
+ *
+ * Project:  WMS Client Driver
+ * Purpose:  GDALWMSRasterBand implementation.
+ * Author:   Adam Nowacki, nowak at xpam.de
+ *
+ ******************************************************************************
+ * Copyright (c) 2007, Adam Nowacki
+ * Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "wmsdriver.h"
+
+CPL_CVSID("$Id: gdalwmsrasterband.cpp 37917 2017-04-07 16:45:48Z rouault $");
+
+GDALWMSRasterBand::GDALWMSRasterBand(GDALWMSDataset *parent_dataset, int band,
+                                        double scale):
+    m_parent_dataset(parent_dataset),
+    m_scale(scale),
+    m_overview(-1),
+    m_color_interp(GCI_Undefined)
+{
+#ifdef DEBUG_VERBOSE
+    printf("[%p] GDALWMSRasterBand::GDALWMSRasterBand(%p, %d, %f)\n",/*ok*/
+           this, parent_dataset, band, scale);
+#endif
+
+    if( scale == 1.0 )
+        poDS = parent_dataset;
+    else
+        poDS = NULL;
+    if( parent_dataset->m_mini_driver_caps.m_overview_dim_computation_method ==
+        OVERVIEW_ROUNDED )
+    {
+        nRasterXSize = static_cast<int>(
+            m_parent_dataset->m_data_window.m_sx * scale + 0.5);
+        nRasterYSize = static_cast<int>(
+            m_parent_dataset->m_data_window.m_sy * scale + 0.5);
+    }
+    else
+    {
+        nRasterXSize = static_cast<int>(
+            m_parent_dataset->m_data_window.m_sx * scale);
+        nRasterYSize = static_cast<int>(
+            m_parent_dataset->m_data_window.m_sy * scale);
+    }
+    nBand = band;
+    eDataType = m_parent_dataset->m_data_type;
+    nBlockXSize = m_parent_dataset->m_block_size_x;
+    nBlockYSize = m_parent_dataset->m_block_size_y;
+}
+
+GDALWMSRasterBand::~GDALWMSRasterBand() {
+    while (!m_overviews.empty()) {
+        delete m_overviews.back();
+        m_overviews.pop_back();
+    }
+ }
+
+// Request for x, y but all blocks between bx0-bx1 and by0-by1 should be read
+CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by0, int bx1, int by1, int advise_read) {
+    CPLErr ret = CE_None;
+
+    // Get a vector of requests large enough for this call
+    std::vector<WMSHTTPRequest> requests((bx1 - bx0 + 1)*(by1 - by0 + 1));
+
+    size_t count = 0; // How many requests are valid
+    GDALWMSCache *cache = m_parent_dataset->m_cache;
+    int offline = m_parent_dataset->m_offline_mode;
+    const char *const *options = m_parent_dataset->GetHTTPRequestOpts();
+
+    for (int iy = by0; iy <= by1; ++iy) {
+        for (int ix = bx0; ix <= bx1; ++ix) {
+            WMSHTTPRequest &request = requests[count];
+            request.x = ix;
+            request.y = iy;
+            bool need_this_block = false;
+            if (!advise_read) {
+                for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
+                    if ((ix == x) && (iy == y) && (ib == nBand)) {
+                        need_this_block = true;
+                    } else {
+                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
+                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
+                        if (!band->IsBlockInCache(ix, iy)) need_this_block = true;
+                    }
+                }
+            } else {
+                need_this_block = true;
+            }
+
+            void *p = ((ix == x) && (iy == y)) ? buffer : NULL;
+            if (need_this_block) {
+                ret = AskMiniDriverForBlock(request, ix, iy);
+                if (ret != CE_None) {
+                    CPLError(CE_Failure, CPLE_AppDefined, "%s", request.Error.c_str());
+                    ret = CE_Failure;
+                }
+                // A missing tile is signaled by setting a range of "none"
+                if (EQUAL(request.Range, "none")) {
+                    if (!advise_read) {
+                        if (ZeroBlock(ix, iy, nBand, p) != CE_None) {
+                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
+                            ret = CE_Failure;
+                        }
+                    }
+                    need_this_block = false;
+                }
+                if (ret == CE_None && cache != NULL) {
+                    CPLString file_name;
+                    if (cache->Read(request.URL, &file_name) == CE_None) {
+                        if (advise_read) {
+                            need_this_block = false;
+                        }
+                        else {
+                            if (ReadBlockFromFile(ix, iy, file_name, nBand, p, 0) == CE_None)
+                                need_this_block = false;
+                        }
+                    }
+                }
+            }
+
+            if (need_this_block) {
+                if (offline) {
+                    if (!advise_read) {
+                        if (ZeroBlock(ix, iy, nBand, p) != CE_None) {
+                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
+                            ret = CE_Failure;
+                        }
+                    }
+                } else {
+                    request.options = options;
+                    WMSHTTPInitializeRequest(&request);
+                    count++;
+                }
+            }
+        }
+    }
+
+    // Fetch all the requests, OK to call with count of 0
+    if (WMSHTTPFetchMulti(count ? &requests[0] : NULL, static_cast<int>(count)) != CE_None) {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: CPLHTTPFetchMulti failed.");
+        ret = CE_Failure;
+    }
+
+    for (size_t i = 0; i < count; ++i) {
+        WMSHTTPRequest &request = requests[i];
+        void *p = ((request.x == x) && (request.y == y)) ? buffer : NULL;
+        if (ret == CE_None) {
+            int success = (request.nStatus == 200) || 
+                          (!request.Range.empty() && request.nStatus == 206);
+            if (success && (request.pabyData != NULL) && (request.nDataLen > 0)) {
+                CPLString file_name(BufferToVSIFile(request.pabyData, request.nDataLen));
+                if (!file_name.empty()) {
+                    bool wms_exception = false;
+                    /* check for error xml */
+                    if (request.nDataLen >= 20) {
+                        const char *download_data = reinterpret_cast<char *>(request.pabyData);
+                        if (STARTS_WITH_CI(download_data, "<?xml ")
+                        || STARTS_WITH_CI(download_data, "<!DOCTYPE ")
+                        || STARTS_WITH_CI(download_data, "<ServiceException")) {
+                            if (ReportWMSException(file_name) != CE_None) {
+                                CPLError(CE_Failure, CPLE_AppDefined, 
+                                        "GDALWMS: The server returned unknown exception.");
+                            }
+                            wms_exception = true;
+                            ret = CE_Failure;
+                        }
+                    }
+                    if (ret == CE_None) {
+                        if (advise_read && !m_parent_dataset->m_verify_advise_read) {
+                            if (cache != NULL)
+                                cache->Write(request.URL, file_name);
+                        } else {
+                            ret = ReadBlockFromFile(request.x, request.y, file_name, nBand, p, advise_read);
+                            if (ret == CE_None) {
+                                if (cache != NULL)
+                                    cache->Write(request.URL, file_name);
+                            } else {
+                                CPLError(ret, CPLE_AppDefined, 
+                                        "GDALWMS: ReadBlockFromFile (%s) failed.", request.URL.c_str());
+                            }
+                        }
+                    }
+                    else if (wms_exception && m_parent_dataset->m_zeroblock_on_serverexceptions) {
+                        ret = ZeroBlock(request.x, request.y, nBand, p);
+                        if (ret != CE_None)
+                            CPLError(ret, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
+                    }
+                    VSIUnlink(file_name);
+                }
+            } else { // HTTP error
+                if (m_parent_dataset->m_http_zeroblock_codes.find(request.nStatus)
+                    != m_parent_dataset->m_http_zeroblock_codes.end())
+                {
+                    if (!advise_read) {
+                        ret = ZeroBlock(request.x, request.y, nBand, p);
+                        if (ret != CE_None) 
+                            CPLError(ret, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
+                    }
+                } else {
+                    ret = CE_Failure;
+                    CPLError(ret, CPLE_AppDefined,
+                                "GDALWMS: Unable to download block %d, %d.\n"
+                                "URL: %s\n  HTTP status code: %d, error: %s.\n"
+                                "Add the HTTP status code to <ZeroBlockHttpCodes> to ignore this error (see http://www.gdal.org/frmt_wms.html).",
+                                request.x,
+                                request.y,
+                                !request.URL.empty() ? request.Error.c_str(): "(null)",
+                                request.nStatus,
+                                !request.Error.empty() ? request.Error.c_str() : "(null)");
+                }
+            }
+        }
+    }
+
+    return ret;
+}
+
+CPLErr GDALWMSRasterBand::IReadBlock(int x, int y, void *buffer) {
+    int bx0 = x;
+    int by0 = y;
+    int bx1 = x;
+    int by1 = y;
+
+    if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview)) {
+        int tbx0 = m_parent_dataset->m_hint.m_x0 / nBlockXSize;
+        int tby0 = m_parent_dataset->m_hint.m_y0 / nBlockYSize;
+        int tbx1 = (m_parent_dataset->m_hint.m_x0 + m_parent_dataset->m_hint.m_sx - 1) / nBlockXSize;
+        int tby1 = (m_parent_dataset->m_hint.m_y0 + m_parent_dataset->m_hint.m_sy - 1) / nBlockYSize;
+        if ((tbx0 <= bx0) && (tby0 <= by0) && (tbx1 >= bx1) && (tby1 >= by1)) {
+            bx0 = tbx0;
+            by0 = tby0;
+            bx1 = tbx1;
+            by1 = tby1;
+        }
+    }
+
+    CPLErr eErr = ReadBlocks(x, y, buffer, bx0, by0, bx1, by1, 0);
+
+    if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview))
+    {
+        m_parent_dataset->m_hint.m_valid = false;
+    }
+
+    return eErr;
+}
+
+CPLErr GDALWMSRasterBand::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy,
+                                    void *buffer, int bsx, int bsy, GDALDataType bdt,
+                                    GSpacing nPixelSpace, GSpacing nLineSpace,
+                                    GDALRasterIOExtraArg* psExtraArg) {
+    CPLErr ret;
+
+    if (rw != GF_Read) return CE_Failure;
+    if (buffer == NULL) return CE_Failure;
+    if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0)) return CE_None;
+
+    m_parent_dataset->m_hint.m_x0 = x0;
+    m_parent_dataset->m_hint.m_y0 = y0;
+    m_parent_dataset->m_hint.m_sx = sx;
+    m_parent_dataset->m_hint.m_sy = sy;
+    m_parent_dataset->m_hint.m_overview = m_overview;
+    m_parent_dataset->m_hint.m_valid = true;
+    ret = GDALRasterBand::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, nPixelSpace, nLineSpace, psExtraArg);
+    m_parent_dataset->m_hint.m_valid = false;
+
+    return ret;
+}
+
+int GDALWMSRasterBand::HasArbitraryOverviews() {
+//    return m_parent_dataset->m_mini_driver_caps.m_has_arb_overviews;
+    return 0; // not implemented yet
+}
+
+int GDALWMSRasterBand::GetOverviewCount() {
+    return static_cast<int>(m_overviews.size());
+}
+
+GDALRasterBand *GDALWMSRasterBand::GetOverview(int n) {
+    if ((!m_overviews.empty()) && (static_cast<size_t>(n) < m_overviews.size())) return m_overviews[n];
+    else return NULL;
+}
+
+void GDALWMSRasterBand::AddOverview(double scale) {
+    GDALWMSRasterBand *overview = new GDALWMSRasterBand(m_parent_dataset, nBand, scale);
+    std::vector<GDALWMSRasterBand *>::iterator it = m_overviews.begin();
+    for (; it != m_overviews.end(); ++it) {
+        GDALWMSRasterBand *p = *it;
+        if (p->m_scale < scale) break;
+    }
+    m_overviews.insert(it, overview);
+    it = m_overviews.begin();
+    for (int i = 0; it != m_overviews.end(); ++it, ++i) {
+        GDALWMSRasterBand *p = *it;
+        p->m_overview = i;
+    }
+}
+
+bool GDALWMSRasterBand::IsBlockInCache(int x, int y) {
+    bool ret = false;
+    GDALRasterBlock *b = TryGetLockedBlockRef(x, y);
+    if (b != NULL) {
+        ret = true;
+        b->DropLock();
+    }
+    return ret;
+}
+
+// This is the function that calculates the block coordinates for the fetch
+CPLErr GDALWMSRasterBand::AskMiniDriverForBlock(WMSHTTPRequest &r, int x, int y)
+{
+    GDALWMSImageRequestInfo iri;
+    GDALWMSTiledImageRequestInfo tiri;
+
+    ComputeRequestInfo(iri, tiri, x, y);
+    return m_parent_dataset->m_mini_driver->TiledImageRequest(r, iri, tiri);
+}
+
+void GDALWMSRasterBand::ComputeRequestInfo(GDALWMSImageRequestInfo &iri,
+                                           GDALWMSTiledImageRequestInfo &tiri,
+                                           int x, int y)
+{
+    int x0 = std::max(0, x * nBlockXSize);
+    int y0 = std::max(0, y * nBlockYSize);
+    int x1 = std::max(0, (x + 1) * nBlockXSize);
+    int y1 = std::max(0, (y + 1) * nBlockYSize);
+    if (m_parent_dataset->m_clamp_requests) {
+        x0 = std::min(x0, nRasterXSize);
+        y0 = std::min(y0, nRasterYSize);
+        x1 = std::min(x1, nRasterXSize);
+        y1 = std::min(y1, nRasterYSize);
+    }
+
+    const double rx = (m_parent_dataset->m_data_window.m_x1 - m_parent_dataset->m_data_window.m_x0) / static_cast<double>(nRasterXSize);
+    const double ry = (m_parent_dataset->m_data_window.m_y1 - m_parent_dataset->m_data_window.m_y0) / static_cast<double>(nRasterYSize);
+    /* Use different method for x0,y0 and x1,y1 to make sure calculated values are exact for corner requests */
+    iri.m_x0 = x0 * rx + m_parent_dataset->m_data_window.m_x0;
+    iri.m_y0 = y0 * ry + m_parent_dataset->m_data_window.m_y0;
+    iri.m_x1 = m_parent_dataset->m_data_window.m_x1 - (nRasterXSize - x1) * rx;
+    iri.m_y1 = m_parent_dataset->m_data_window.m_y1 - (nRasterYSize - y1) * ry;
+    iri.m_sx = x1 - x0;
+    iri.m_sy = y1 - y0;
+
+    int level = m_overview + 1;
+    tiri.m_x = (m_parent_dataset->m_data_window.m_tx >> level) + x;
+    tiri.m_y = (m_parent_dataset->m_data_window.m_ty >> level) + y;
+    tiri.m_level = m_parent_dataset->m_data_window.m_tlevel - level;
+}
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **GDALWMSRasterBand::GetMetadataDomainList()
+{
+    char **m_list = GDALPamRasterBand::GetMetadataDomainList();
+    char **mini_list = m_parent_dataset->m_mini_driver->GetMetadataDomainList();
+    if (mini_list != NULL) {
+        m_list = CSLMerge(m_list, mini_list);
+        CSLDestroy(mini_list);
+    }
+    return m_list;
+}
+
+const char *GDALWMSRasterBand::GetMetadataItem(const char * pszName,
+                                                const char * pszDomain)
+{
+    if (!m_parent_dataset->m_mini_driver_caps.m_has_getinfo
+        || !(pszDomain != NULL
+             && EQUAL(pszDomain, "LocationInfo")
+             && (STARTS_WITH_CI(pszName, "Pixel_") || STARTS_WITH_CI(pszName, "GeoPixel_"))))
+        return GDALPamRasterBand::GetMetadataItem(pszName, pszDomain);
+
+    /* ==================================================================== */
+    /*      LocationInfo handling.                                          */
+    /* ==================================================================== */
+
+    /* -------------------------------------------------------------------- */
+    /*      What pixel are we aiming at?                                    */
+    /* -------------------------------------------------------------------- */
+    int iPixel, iLine;
+    if (STARTS_WITH_CI(pszName, "Pixel_"))
+    {
+        if (sscanf(pszName + 6, "%d_%d", &iPixel, &iLine) != 2)
+            return NULL;
+    }
+    else if (STARTS_WITH_CI(pszName, "GeoPixel_"))
+    {
+        double adfGeoTransform[6];
+        double adfInvGeoTransform[6];
+        double dfGeoX, dfGeoY;
+
+        {
+            dfGeoX = CPLAtof(pszName + 9);
+            const char* pszUnderscore = strchr(pszName + 9, '_');
+            if (!pszUnderscore)
+                return NULL;
+            dfGeoY = CPLAtof(pszUnderscore + 1);
+        }
+
+        if (m_parent_dataset->GetGeoTransform(adfGeoTransform) != CE_None)
+            return NULL;
+
+        if (!GDALInvGeoTransform(adfGeoTransform, adfInvGeoTransform))
+            return NULL;
+
+        iPixel = (int)floor(
+            adfInvGeoTransform[0]
+            + adfInvGeoTransform[1] * dfGeoX
+            + adfInvGeoTransform[2] * dfGeoY);
+        iLine = (int)floor(
+            adfInvGeoTransform[3]
+            + adfInvGeoTransform[4] * dfGeoX
+            + adfInvGeoTransform[5] * dfGeoY);
+
+        /* The GetDataset() for the WMS driver is always the main overview level, so rescale */
+        /* the values if we are an overview */
+        if (m_overview >= 0)
+        {
+            iPixel = (int)(1.0 * iPixel * GetXSize() / m_parent_dataset->GetRasterBand(1)->GetXSize());
+            iLine = (int)(1.0 * iLine * GetYSize() / m_parent_dataset->GetRasterBand(1)->GetYSize());
+        }
+    }
+    else
+        return NULL;
+
+    if (iPixel < 0 || iLine < 0
+        || iPixel >= GetXSize()
+        || iLine >= GetYSize())
+        return NULL;
+
+    if (nBand != 1)
+    {
+        GDALRasterBand* poFirstBand = m_parent_dataset->GetRasterBand(1);
+        if (m_overview >= 0)
+            poFirstBand = poFirstBand->GetOverview(m_overview);
+        if (poFirstBand)
+            return poFirstBand->GetMetadataItem(pszName, pszDomain);
+    }
+
+    GDALWMSImageRequestInfo iri;
+    GDALWMSTiledImageRequestInfo tiri;
+    int nBlockXOff = iPixel / nBlockXSize;
+    int nBlockYOff = iLine / nBlockYSize;
+
+    ComputeRequestInfo(iri, tiri, nBlockXOff, nBlockYOff);
+
+    CPLString url;
+    m_parent_dataset->m_mini_driver->GetTiledImageInfo(url,
+        iri, tiri,
+        iPixel % nBlockXSize,
+        iLine % nBlockXSize);
+
+    if (url.empty())
+        return NULL;
+
+    CPLDebug("WMS", "URL = %s", url.c_str());
+
+    if (url == osMetadataItemURL)
+    {
+        // osMetadataItem.c_str() MUST be used, and not osMetadataItem,
+        // otherwise a temporary copy is returned
+        return !osMetadataItem.empty() ? osMetadataItem.c_str() : NULL;
+    }
+
+    osMetadataItemURL = url;
+
+    // This is OK, CPLHTTPFetch does not touch the options
+    char **papszOptions = const_cast<char **>(m_parent_dataset->GetHTTPRequestOpts());
+    CPLHTTPResult* psResult = CPLHTTPFetch(url, papszOptions);
+
+    CPLString pszRes;
+
+    if (psResult && psResult->pabyData)
+        pszRes = reinterpret_cast<const char *>(psResult->pabyData);
+    CPLHTTPDestroyResult(psResult);
+
+    if (pszRes.empty()) {
+        osMetadataItem = "";
+        return NULL;
+    }
+
+    osMetadataItem = "<LocationInfo>";
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    CPLXMLNode* psXML = CPLParseXMLString(pszRes);
+    CPLPopErrorHandler();
+    if (psXML != NULL && psXML->eType == CXT_Element)
+    {
+        if (strcmp(psXML->pszValue, "?xml") == 0)
+        {
+            if (psXML->psNext)
+            {
+                char* pszXML = CPLSerializeXMLTree(psXML->psNext);
+                osMetadataItem += pszXML;
+                CPLFree(pszXML);
+            }
+        }
+        else
+        {
+            osMetadataItem += pszRes;
+        }
+    }
+    else
+    {
+        char* pszEscapedXML = CPLEscapeString(pszRes, -1, CPLES_XML_BUT_QUOTES);
+        osMetadataItem += pszEscapedXML;
+        CPLFree(pszEscapedXML);
+    }
+    if (psXML != NULL)
+        CPLDestroyXMLNode(psXML);
+
+    osMetadataItem += "</LocationInfo>";
+
+    // osMetadataItem.c_str() MUST be used, and not osMetadataItem,
+    // otherwise a temporary copy is returned
+    return osMetadataItem.c_str();
+}
+
+static const int * GetBandMapForExpand( int nSourceBands, int nWmsBands )
+{
+    static const int  bandmap1to1[] = { 1 };
+    static const int  bandmap2to1[] = { 1 };
+    static const int  bandmap3to1[] = { 1 };
+    static const int  bandmap4to1[] = { 1 };
+
+    static const int  bandmap1to2[] = { 1, 0 }; // 0 == full opaque alpha band
+    static const int  bandmap2to2[] = { 1, 2 };
+    static const int  bandmap3to2[] = { 1, 0 };
+    static const int  bandmap4to2[] = { 1, 4 };
+
+    static const int  bandmap1to3[] = { 1, 1, 1 };
+    static const int  bandmap2to3[] = { 1, 1, 1 };
+    static const int  bandmap3to3[] = { 1, 2, 3 };
+    static const int  bandmap4to3[] = { 1, 2, 3 };
+
+    static const int  bandmap1to4[] = { 1, 1, 1, 0 };
+    static const int  bandmap2to4[] = { 1, 1, 1, 2 };
+    static const int  bandmap3to4[] = { 1, 2, 3, 0 };
+    static const int  bandmap4to4[] = { 1, 2, 3, 4 };
+
+    static const int* const bandmap_selector[4][4] = {
+        { bandmap1to1, bandmap2to1, bandmap3to1, bandmap4to1 },
+        { bandmap1to2, bandmap2to2, bandmap3to2, bandmap4to2 },
+        { bandmap1to3, bandmap2to3, bandmap3to3, bandmap4to3 },
+        { bandmap1to4, bandmap2to4, bandmap3to4, bandmap4to4 },
+    };
+
+    if( nSourceBands > 4 || nSourceBands < 1 )
+    {
+        return NULL;
+    }
+    if( nWmsBands > 4 || nWmsBands < 1 )
+    {
+        return NULL;
+    }
+    return bandmap_selector[nWmsBands - 1][nSourceBands - 1];
+}
+
+CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name,
+                                            int to_buffer_band, void *buffer, int advise_read)
+{
+    CPLErr ret = CE_None;
+    GDALDataset *ds = NULL;
+    GByte *color_table = NULL;
+    int i;
+
+    //CPLDebug("WMS", "ReadBlockFromFile: to_buffer_band=%d, (x,y)=(%d, %d)", to_buffer_band, x, y);
+
+    /* expected size */
+    const int esx =
+        std::min(std::max(0, (x + 1) * nBlockXSize),
+                 nRasterXSize) - std::min(std::max(0, x * nBlockXSize),
+                                          nRasterXSize);
+    const int esy =
+        std::min(std::max(0, (y + 1) * nBlockYSize),
+                 nRasterYSize) - std::min(std::max(0, y * nBlockYSize),
+                                          nRasterYSize);
+
+    ds = reinterpret_cast<GDALDataset*>(GDALOpenEx(file_name,
+                                                    GDAL_OF_RASTER 
+                                                    | GDAL_OF_READONLY 
+                                                    | GDAL_OF_VERBOSE_ERROR,
+                                                    NULL, 
+                                                    m_parent_dataset->m_tileOO, 
+                                                    NULL));
+
+    if (ds != NULL) {
+        int sx = ds->GetRasterXSize();
+        int sy = ds->GetRasterYSize();
+        /* Allow bigger than expected so pre-tiled constant size images work on corners */
+        if ((sx > nBlockXSize) || (sy > nBlockYSize) || (sx < esx) || (sy < esy)) {
+            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect size %d x %d of downloaded block, expected %d x %d, max %d x %d.",
+                sx, sy, esx, esy, nBlockXSize, nBlockYSize);
+            ret = CE_Failure;
+        }
+        int nDSRasterCount = ds->GetRasterCount();
+        if (ret == CE_None) {
+            if (nDSRasterCount != m_parent_dataset->nBands) {
+                /* Maybe its an image with color table */
+                if ((eDataType == GDT_Byte) && (ds->GetRasterCount() == 1)) {
+                    GDALRasterBand *rb = ds->GetRasterBand(1);
+                    if (rb->GetRasterDataType() == GDT_Byte) {
+                        GDALColorTable *ct = rb->GetColorTable();
+                        if (ct != NULL) {
+                            if (!advise_read) {
+                                color_table = new GByte[256 * 4];
+                                const int count =
+                                    std::min(256, ct->GetColorEntryCount());
+                                for (i = 0; i < count; ++i) {
+                                    GDALColorEntry ce;
+                                    ct->GetColorEntryAsRGB(i, &ce);
+                                    color_table[i] = static_cast<GByte>(ce.c1);
+                                    color_table[i + 256] = static_cast<GByte>(ce.c2);
+                                    color_table[i + 512] = static_cast<GByte>(ce.c3);
+                                    color_table[i + 768] = static_cast<GByte>(ce.c4);
+                                }
+                                for (i = count; i < 256; ++i) {
+                                    color_table[i] = 0;
+                                    color_table[i + 256] = 0;
+                                    color_table[i + 512] = 0;
+                                    color_table[i + 768] = 0;
+                                }
+                            }
+                        }
+                        else if (m_parent_dataset->nBands <= 4) { // Promote single band to fake color table
+                            color_table = new GByte[256 * 4];
+                            for (i = 0; i < 256; i++) {
+                                color_table[i] = static_cast<GByte>(i);
+                                color_table[i + 256] = static_cast<GByte>(i);
+                                color_table[i + 256*2] = static_cast<GByte>(i);
+                                color_table[i + 256*3] = 255; // Transparency
+                            }
+                            if (m_parent_dataset->nBands == 2) { // Luma-Alpha fixup
+                                for (i = 0; i < 256; i++)
+                                    color_table[i + 256] = 255;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (!advise_read) {
+            const int * const bandmap = GetBandMapForExpand( nDSRasterCount, m_parent_dataset->nBands );
+            for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
+                if (ret == CE_None) {
+                    void *p = NULL;
+                    GDALRasterBlock *b = NULL;
+                    if ((buffer != NULL) && (ib == to_buffer_band)) {
+                        p = buffer;
+                    } else {
+                        GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
+                        if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
+                        if (!band->IsBlockInCache(x, y)) {
+                            b = band->GetLockedBlockRef(x, y, true);
+                            if (b != NULL) {
+                                p = b->GetDataRef();
+                                if (p == NULL) {
+                                  CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
+                                  ret = CE_Failure;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            //CPLDebug("WMS", "Band %d, block (x,y)=(%d, %d) already in cache", band->GetBand(), x, y);
+                        }
+                    }
+                    if (p != NULL) {
+                        int pixel_space = GDALGetDataTypeSize(eDataType) / 8;
+                        int line_space = pixel_space * nBlockXSize;
+                        if (color_table == NULL) {
+                            if( bandmap == NULL || bandmap[ib - 1] != 0 ) {
+                                GDALDataType dt=eDataType;
+                                int     nSourceBand = ib;
+                                if( bandmap != NULL )
+                                {
+                                    nSourceBand = bandmap[ib - 1];
+                                }
+                                // Get the data from the PNG as stored instead of converting, if the server asks for that
+                                // TODO: This hack is from #3493 - not sure it really belongs here.
+                                if ((GDT_Int16 == dt) && (GDT_UInt16 == ds->GetRasterBand(ib)->GetRasterDataType()))
+                                    dt = GDT_UInt16;
+                                if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, dt, 1, &nSourceBand, pixel_space, line_space, 0, NULL) != CE_None) {
+                                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
+                                    ret = CE_Failure;
+                                }
+                            }
+                            else if( bandmap != NULL && bandmap[ib - 1] == 0 )
+                            {  // parent expects 4 bands but file has fewer count so generate a all "opaque" 4th band
+                                GByte *byte_buffer = reinterpret_cast<GByte *>(p);
+                                for (int l_y = 0; l_y < sy; ++l_y) {
+                                    for (int l_x = 0; l_x < sx; ++l_x) {
+                                        const int offset = l_x + l_y * line_space;
+                                        byte_buffer[offset] = 255;  // fill with opaque
+                                    }
+                                }
+                            }
+                            else
+                            {  // we should never get here because this case was caught above
+                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
+                                         ds->GetRasterCount(), m_parent_dataset->nBands);
+                                ret = CE_Failure;
+                            }
+                        } else if (ib <= 4) {
+                            if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, eDataType, 1, NULL, pixel_space, line_space, 0, NULL) != CE_None) {
+                                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
+                                ret = CE_Failure;
+                            }
+                            if (ret == CE_None) {
+                                GByte *band_color_table = color_table + 256 * (ib - 1);
+                                GByte *byte_buffer = reinterpret_cast<GByte *>(p);
+                                for (int l_y = 0; l_y < sy; ++l_y) {
+                                    for (int l_x = 0; l_x < sx; ++l_x) {
+                                        const int offset = l_x + l_y * line_space;
+                                        byte_buffer[offset] = band_color_table[byte_buffer[offset]];
+                                    }
+                                }
+                            }
+                        } else {
+                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Color table supports at most 4 components.");
+                            ret = CE_Failure;
+                        }
+                    }
+                    if (b != NULL) {
+                        b->DropLock();
+                    }
+                }
+            }
+        }
+        GDALClose(ds);
+    } else {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to open downloaded block.");
+        ret = CE_Failure;
+    }
+
+    if (color_table != NULL) {
+        delete[] color_table;
+    }
+
+    return ret;
+}
+
+CPLErr GDALWMSRasterBand::ZeroBlock(int x, int y, int to_buffer_band, void *buffer) {
+    CPLErr ret = CE_None;
+
+    for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
+        if (ret == CE_None) {
+            void *p = NULL;
+            GDALRasterBlock *b = NULL;
+            if ((buffer != NULL) && (ib == to_buffer_band)) {
+                p = buffer;
+            } else {
+                GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
+                if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
+                if (!band->IsBlockInCache(x, y)) {
+                    b = band->GetLockedBlockRef(x, y, true);
+                    if (b != NULL) {
+                        p = b->GetDataRef();
+                        if (p == NULL) {
+                          CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
+                          ret = CE_Failure;
+                        }
+                    }
+                }
+            }
+            if (p != NULL) {
+                unsigned char *paby = reinterpret_cast<unsigned char *>(p);
+                int block_size = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
+                for (int i = 0; i < block_size; ++i) paby[i] = 0;
+            }
+            if (b != NULL) {
+                b->DropLock();
+            }
+        }
+    }
+
+    return ret;
+}
+
+CPLErr GDALWMSRasterBand::ReportWMSException(const char *file_name) {
+    CPLErr ret = CE_None;
+    int reported_errors_count = 0;
+
+    CPLXMLNode *orig_root = CPLParseXMLFile(file_name);
+    CPLXMLNode *root = orig_root;
+    if (root != NULL) {
+        root = CPLGetXMLNode(root, "=ServiceExceptionReport");
+    }
+    if (root != NULL) {
+        CPLXMLNode *n = CPLGetXMLNode(root, "ServiceException");
+        while (n != NULL) {
+            const char *exception = CPLGetXMLValue(n, "=ServiceException", "");
+            const char *exception_code = CPLGetXMLValue(n, "=ServiceException.code", "");
+            if (exception[0] != '\0') {
+                if (exception_code[0] != '\0') {
+                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s': %s", exception_code, exception);
+                    ++reported_errors_count;
+                } else {
+                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception: %s", exception);
+                    ++reported_errors_count;
+                }
+            } else if (exception_code[0] != '\0') {
+                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s'.", exception_code);
+                ++reported_errors_count;
+            }
+
+            n = n->psNext;
+            if (n != NULL) {
+                n = CPLGetXMLNode(n, "=ServiceException");
+            }
+        }
+    } else {
+        ret = CE_Failure;
+    }
+    if (orig_root != NULL) {
+        CPLDestroyXMLNode(orig_root);
+    }
+
+    if (reported_errors_count == 0) {
+        ret = CE_Failure;
+    }
+
+    return ret;
+}
+
+CPLErr GDALWMSRasterBand::AdviseRead(int x0, int y0,
+                                     int sx, int sy,
+                                     CPL_UNUSED int bsx,
+                                     CPL_UNUSED int bsy,
+                                     CPL_UNUSED GDALDataType bdt,
+                                     CPL_UNUSED char **options) {
+//    printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
+    if (m_parent_dataset->m_offline_mode || !m_parent_dataset->m_use_advise_read) return CE_None;
+    if (m_parent_dataset->m_cache == NULL) return CE_Failure;
+
+    int bx0 = x0 / nBlockXSize;
+    int by0 = y0 / nBlockYSize;
+    int bx1 = (x0 + sx - 1) / nBlockXSize;
+    int by1 = (y0 + sy - 1) / nBlockYSize;
+
+    return ReadBlocks(0, 0, NULL, bx0, by0, bx1, by1, 1);
+}
+
+GDALColorInterp GDALWMSRasterBand::GetColorInterpretation() {
+    return m_color_interp;
+}
+
+CPLErr GDALWMSRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
+{
+    m_color_interp = eNewInterp;
+    return CE_None;
+}
+
+// Utility function, returns a value from a vector corresponding to the band index
+// or the first entry
+static double getBandValue(std::vector<double> &v,size_t idx)
+{
+    idx--;
+    if (v.size()>idx) return v[idx];
+    return v[0];
+}
+
+double GDALWMSRasterBand::GetNoDataValue( int *pbSuccess)
+{
+    std::vector<double> &v=m_parent_dataset->vNoData;
+    if (v.empty())
+        return GDALPamRasterBand::GetNoDataValue(pbSuccess);
+    if (pbSuccess) *pbSuccess=TRUE;
+    return getBandValue(v,nBand);
+}
+
+double GDALWMSRasterBand::GetMinimum( int *pbSuccess)
+{
+    std::vector<double> &v=m_parent_dataset->vMin;
+    if (v.empty())
+        return GDALPamRasterBand::GetMinimum(pbSuccess);
+    if (pbSuccess) *pbSuccess=TRUE;
+    return getBandValue(v,nBand);
+}
+
+double GDALWMSRasterBand::GetMaximum( int *pbSuccess)
+{
+    std::vector<double> &v=m_parent_dataset->vMax;
+    if (v.empty())
+        return GDALPamRasterBand::GetMaximum(pbSuccess);
+    if (pbSuccess) *pbSuccess=TRUE;
+    return getBandValue(v,nBand);
+}
+
+GDALColorTable *GDALWMSRasterBand::GetColorTable()
+{
+    return m_parent_dataset->m_poColorTable;
+}
diff --git a/frmts/wms/makefile.vc b/frmts/wms/makefile.vc
index 722eba6..f459816 100644
--- a/frmts/wms/makefile.vc
+++ b/frmts/wms/makefile.vc
@@ -5,7 +5,7 @@ OBJ	= \
 	minidriver_wms.obj minidriver_tileservice.obj \
 	minidriver_worldwind.obj minidriver_tms.obj minidriver_tiled_wms.obj \
 	wmsmetadataset.obj minidriver_virtualearth.obj minidriver_arcgis_server.obj \
-	minidriver_iip.obj
+	minidriver_iip.obj minidriver_mrf.obj
 
 EXTRAFLAGS = -DHAVE_CURL $(CURL_CFLAGS) $(CURL_INC)
 
diff --git a/frmts/wms/md5.cpp b/frmts/wms/md5.cpp
index dc2c2c2..2707138 100644
--- a/frmts/wms/md5.cpp
+++ b/frmts/wms/md5.cpp
@@ -37,10 +37,13 @@ this file is only about 3k of object code.  */
 #include "config.h"
 #endif
 
-#include <string.h>	/* for memcpy() and memset() */
+#include <string.h>  /* for memcpy() and memset() */
 
+#include "cpl_port.h"
 #include "md5.h"
 
+CPL_CVSID("$Id: md5.cpp 36237 2016-11-14 20:06:34Z lplesea $");
+
 /* Little-endian byte-swapping routines.  Note that these do not
 depend on the size of datatypes such as cvs_uint32, nor do they require
 us to detect the endianness of the machine we are running on.  It
@@ -49,7 +52,7 @@ surprised if they were a performance bottleneck for MD5.  */
 
 static cvs_uint32 getu32(const unsigned char *addr)
 {
-    return (((((unsigned long)addr[3] << 8) | addr[2]) << 8)
+    return (((((cvs_uint32)addr[3] << 8) | addr[2]) << 8)
         | addr[1]) << 8 | addr[0];
 }
 
@@ -97,10 +100,10 @@ struct cvs_MD5Context *ctx,
 
     t = ctx->bits[0];
     if ((ctx->bits[0] = (t + ((cvs_uint32)len << 3)) & 0xffffffff) < t)
-        ctx->bits[1]++;	/* Carry from low to high */
+        ctx->bits[1]++;  /* Carry from low to high */
     ctx->bits[1] += len >> 29;
 
-    t = (t >> 3) & 0x3f;	/* Bytes already in shsInfo->data */
+    t = (t >> 3) & 0x3f;  /* Bytes already in shsInfo->data */
 
     /* Handle any leading odd-sized chunks */
 
@@ -177,7 +180,7 @@ struct cvs_MD5Context *ctx)
     putu32(ctx->buf[1], digest + 4);
     putu32(ctx->buf[2], digest + 8);
     putu32(ctx->buf[3], digest + 12);
-    memset(ctx, 0, sizeof(*ctx));	/* In case it's sensitive */
+    memset(ctx, 0, sizeof(*ctx));  /* In case it's sensitive */
 }
 
 #ifndef ASM_MD5
diff --git a/frmts/wms/md5.h b/frmts/wms/md5.h
index 7b85ca1..17e1f72 100644
--- a/frmts/wms/md5.h
+++ b/frmts/wms/md5.h
@@ -8,7 +8,12 @@
 bits instead of 64 is not important; speed is considerably more
 important.  ANSI guarantees that "unsigned long" will be big enough,
 and always using it seems to have few disadvantages.  */
+#if defined(CPL_BASE_H_INCLUDED)
+// Alias cvs_uint32 to GUInt32
+#define cvs_uint32 GUInt32
+#else
 typedef unsigned long cvs_uint32;
+#endif
 
 struct cvs_MD5Context {
     cvs_uint32 buf[4];
diff --git a/frmts/wms/minidriver.cpp b/frmts/wms/minidriver.cpp
index 6dbb7d0..afc13da 100644
--- a/frmts/wms/minidriver.cpp
+++ b/frmts/wms/minidriver.cpp
@@ -1,12 +1,17 @@
 /******************************************************************************
- * $Id: minidriver.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
- * Purpose:  GDALWMSMiniDriver base class implementation.
+ * Purpose:  WMSMiniDriverManager implementation.
  * Author:   Adam Nowacki, nowak at xpam.de
  *
  ******************************************************************************
+ *
  * Copyright (c) 2007, Adam Nowacki
+ *               2016, Lucian Plesea
+ *
+ * A single global MiniDriverManager exists, containing factories for all possible
+ * types of WMS minidrivers.  Minidriver object factories get registered in wmsdriver.cpp,
+ * during the WMS driver registration with GDAL
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,103 +34,60 @@
 
 #include "wmsdriver.h"
 
-static volatile GDALWMSMiniDriverManager *g_mini_driver_manager = NULL;
-static CPLMutex *g_mini_driver_manager_mutex = NULL;
+CPL_CVSID("$Id: minidriver.cpp 36611 2016-12-01 23:13:38Z lplesea $");
 
-GDALWMSMiniDriver::GDALWMSMiniDriver() {
-    m_parent_dataset = NULL;
-}
+class WMSMiniDriverManager {
+public:
+    WMSMiniDriverManager() {};
+    ~WMSMiniDriverManager() { erase(); };
 
-GDALWMSMiniDriver::~GDALWMSMiniDriver() {
-}
+public:
+    void Register(WMSMiniDriverFactory *mdf);
+    // Clean up the minidriver factories
+    void erase();
+    WMSMiniDriverFactory *Find(const CPLString &name);
 
-CPLErr GDALWMSMiniDriver::Initialize(CPL_UNUSED CPLXMLNode *config) {
-    return CE_None;
-}
-
-void GDALWMSMiniDriver::GetCapabilities(CPL_UNUSED GDALWMSMiniDriverCapabilities *caps) {
-}
+protected:
+    std::vector<WMSMiniDriverFactory *> m_mdfs;
+};
 
-void GDALWMSMiniDriver::ImageRequest(CPL_UNUSED CPLString *url, CPL_UNUSED const GDALWMSImageRequestInfo &iri) {
+// Called by WMS driver deregister, also by destructor
+void WMSMiniDriverManager::erase() {
+    for (size_t i = 0; i < m_mdfs.size(); i++)
+        delete m_mdfs[i];
+    m_mdfs.clear();
 }
 
-void GDALWMSMiniDriver::TiledImageRequest(CPL_UNUSED CPLString *url,
-                                          CPL_UNUSED const GDALWMSImageRequestInfo &iri,
-                                          CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri) {
-}
-
-void GDALWMSMiniDriver::GetTiledImageInfo(CPL_UNUSED CPLString *url,
-                                          CPL_UNUSED const GDALWMSImageRequestInfo &iri,
-                                          CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri,
-                                          CPL_UNUSED int nXInBlock,
-                                          CPL_UNUSED int nYInBlock)
-{
-}
-
-const char *GDALWMSMiniDriver::GetProjectionInWKT() {
+WMSMiniDriverFactory *WMSMiniDriverManager::Find(const CPLString &name) {
+    for (size_t i = 0; i < m_mdfs.size(); i++)
+        if (EQUAL(name.c_str(), m_mdfs[i]->m_name))
+            return m_mdfs[i];
     return NULL;
 }
 
-GDALWMSMiniDriverFactory::GDALWMSMiniDriverFactory() {
-}
-
-GDALWMSMiniDriverFactory::~GDALWMSMiniDriverFactory() {
-}
-
-GDALWMSMiniDriverManager *GetGDALWMSMiniDriverManager() {
-    if (g_mini_driver_manager == NULL) {
-        CPLMutexHolderD(&g_mini_driver_manager_mutex);
-        if (g_mini_driver_manager == NULL) {
-            g_mini_driver_manager = new GDALWMSMiniDriverManager();
-        }
-        CPLAssert(g_mini_driver_manager != NULL);
-    }
-    return const_cast<GDALWMSMiniDriverManager *>(g_mini_driver_manager);
-}
-
-void DestroyWMSMiniDriverManager()
-
-{
-    {
-        CPLMutexHolderD(&g_mini_driver_manager_mutex);
-
-        if( g_mini_driver_manager != NULL )
-        {
-            delete g_mini_driver_manager;
-            g_mini_driver_manager = NULL;
-        }
-    }
-
-    if( g_mini_driver_manager_mutex != NULL )
-    {
-        CPLDestroyMutex(g_mini_driver_manager_mutex);
-        g_mini_driver_manager_mutex = NULL;
-    }
-}
-
-GDALWMSMiniDriverManager::GDALWMSMiniDriverManager() {
-}
-
-GDALWMSMiniDriverManager::~GDALWMSMiniDriverManager() {
-    for (std::list<GDALWMSMiniDriverFactory *>::iterator it = m_mdfs.begin();
-         it != m_mdfs.end(); ++it) {
-        GDALWMSMiniDriverFactory *mdf = *it;
+void WMSMiniDriverManager::Register(WMSMiniDriverFactory *mdf) {
+    // Prevent duplicates
+    if (!Find(mdf->m_name))
+        m_mdfs.push_back(mdf);
+    else // Register takes ownership of factories, so it removes the duplicate
         delete mdf;
-    }
 }
 
-void GDALWMSMiniDriverManager::Register(GDALWMSMiniDriverFactory *mdf) {
-    CPLMutexHolderD(&g_mini_driver_manager_mutex);
+// global object containing minidriver factories
+static WMSMiniDriverManager g_mini_driver_manager;
 
-    m_mdfs.push_back(mdf);
+// If a matching factory is found in the global minidriver manager, it returns a new minidriver object
+WMSMiniDriver *NewWMSMiniDriver(const CPLString &name) {
+    const WMSMiniDriverFactory *factory = g_mini_driver_manager.Find(name);
+    if (factory == NULL) return NULL;
+    return factory->New();
 }
 
-GDALWMSMiniDriverFactory *GDALWMSMiniDriverManager::Find(const CPLString &name) {
-    CPLMutexHolderD(&g_mini_driver_manager_mutex);
+// Registers a minidriver factory with the global minidriver manager
+void WMSRegisterMiniDriverFactory(WMSMiniDriverFactory *mdf) {
+    g_mini_driver_manager.Register(mdf);
+}
 
-    for (std::list<GDALWMSMiniDriverFactory *>::iterator it = m_mdfs.begin(); it != m_mdfs.end(); ++it) {
-        GDALWMSMiniDriverFactory *const mdf = *it;
-        if (EQUAL(mdf->GetName().c_str(), name.c_str())) return mdf;
-    }
-    return NULL;
+void WMSDeregisterMiniDrivers(CPL_UNUSED GDALDriver *) {
+    g_mini_driver_manager.erase();
 }
diff --git a/frmts/wms/minidriver_arcgis_server.cpp b/frmts/wms/minidriver_arcgis_server.cpp
index 2c358e2..535ca92 100644
--- a/frmts/wms/minidriver_arcgis_server.cpp
+++ b/frmts/wms/minidriver_arcgis_server.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  Arc GIS Server Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -31,232 +30,155 @@
 #include "wmsdriver.h"
 #include "minidriver_arcgis_server.h"
 
-CPP_GDALWMSMiniDriverFactory(AGS)
+#include <algorithm>
 
-GDALWMSMiniDriver_AGS::GDALWMSMiniDriver_AGS()
+CPL_CVSID("$Id: minidriver_arcgis_server.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+WMSMiniDriver_AGS::WMSMiniDriver_AGS() {}
+
+WMSMiniDriver_AGS::~WMSMiniDriver_AGS() {}
+
+static double GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what)
 {
+    switch (what)
+    {
+    case 'x': return std::min(iri.m_x0, iri.m_x1);
+    case 'y': return std::min(iri.m_y0, iri.m_y1);
+    case 'X': return std::max(iri.m_x0, iri.m_x1);
+    case 'Y': return std::max(iri.m_y0, iri.m_y1);
+    }
+    return 0.0;
 }
 
-GDALWMSMiniDriver_AGS::~GDALWMSMiniDriver_AGS()
-{
+char **WMSMiniDriver_AGS::GetMetadataDomainList(void) {
+    return CSLAddString(NULL, "LocationInfo");
 }
 
-CPLErr GDALWMSMiniDriver_AGS::Initialize(CPLXMLNode *config)
+CPLErr WMSMiniDriver_AGS::Initialize(CPLXMLNode *config, CPL_UNUSED char **papszOpenOptions)
 {
-    CPLErr ret = CE_None;
-    int i;
-
-    if (ret == CE_None)
-    {
-        const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
-        if (base_url[0] != '\0')
-        {
-            /* Try the old name */
-            base_url = CPLGetXMLValue(config, "ServerUrl", "");
-        }
-
-        if (base_url[0] != '\0')
-        {
-            m_base_url = base_url;
-        }
-        else
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, ArcGIS Server mini-driver: ServerURL missing.");
-            ret = CE_Failure;
-        }
+    // Bounding box, if specified, has to be xyXY
+    m_bbox_order = CPLGetXMLValue(config, "BBoxOrder", "xyXY");
+    if (m_bbox_order.size() < 4 || m_bbox_order.find("xyXY") != 0) {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ArcGIS BBoxOrder value has to be xyXY");
+        return CE_Failure;
     }
 
-	if (ret == CE_None)
-	{
-        m_image_format = CPLGetXMLValue(config, "ImageFormat", "png");
-        m_transparent = CPLGetXMLValue(config, "Transparent","");
-		// the transparent flag needs to be "true" or "false"
-		// in lower case according to the ArcGIS Server REST API
-        for(i = 0; i < (int)m_transparent.size(); i++)
-        {
-			m_transparent[i] = (char) tolower(m_transparent[i]);
-        }
-
-		m_layers = CPLGetXMLValue(config, "Layers", "");
+    m_base_url = CPLGetXMLValue(config, "ServerURL", CPLGetXMLValue(config, "ServerUrl", ""));
+    if (m_base_url.empty()) {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ArcGIS Server mini-driver: ServerURL missing.");
+        return CE_Failure;
     }
 
-	if (ret == CE_None)
-	{
-		const char* irs = CPLGetXMLValue(config, "SRS", "102100");
+    m_image_format = CPLGetXMLValue(config, "ImageFormat", "png");
+    m_time_range = CPLGetXMLValue(config, "TimeRange", "");
+    m_transparent = CPLGetXMLValue(config, "Transparent", "");
+    m_transparent.tolower();
+    m_layers = CPLGetXMLValue(config, "Layers", "");
 
-		if (irs != NULL)
-		{
-	        if(STARTS_WITH_CI(irs, "EPSG:")) //if we have EPSG code just convert it to WKT
-	        {
-	            m_projection_wkt = ProjToWKT(irs);
-	            m_irs = irs + 5;
-	        }
-	        else //if we have AGS code - try if it's EPSG
-		    {
-		        m_irs = irs;
-		        m_projection_wkt = ProjToWKT("EPSG:" + m_irs);
-		    }
-		    // TODO: if we have AGS JSON
-		}
-		m_identification_tolerance = CPLGetXMLValue(config, "IdentificationTolerance", "2");
-	}
+    const char* irs = CPLGetXMLValue(config, "SRS", "102100");
 
-	if (ret == CE_None)
-	{
-        const char *bbox_order = CPLGetXMLValue(config, "BBoxOrder", "xyXY");
-        if (bbox_order[0] != '\0')
+    if (irs != NULL)
+    {
+        if (STARTS_WITH_CI(irs, "EPSG:")) //if we have EPSG code just convert it to WKT
         {
-            for (i = 0; i < 4; ++i)
-            {
-                if ((bbox_order[i] != 'x') && (bbox_order[i] != 'y') &&
-                    (bbox_order[i] != 'X') && (bbox_order[i] != 'Y'))
-                    break;
-            }
-
-            if (i == 4)
-            {
-                m_bbox_order = bbox_order;
-            }
-            else
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, ArcGIS Server mini-driver: Incorrect BBoxOrder.");
-                ret = CE_Failure;
-            }
+            m_projection_wkt = ProjToWKT(irs);
+            m_irs = irs + 5;
         }
-        else
+        else //if we have AGS code - try if it's EPSG
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, ArcGIS Server mini-driver: BBoxOrder missing.");
-            ret = CE_Failure;
+            m_irs = irs;
+            m_projection_wkt = ProjToWKT("EPSG:" + m_irs);
         }
+        // TODO: if we have AGS JSON
     }
+    m_identification_tolerance = CPLGetXMLValue(config, "IdentificationTolerance", "2");
 
-    return ret;
+    return CE_None;
 }
 
-void GDALWMSMiniDriver_AGS::GetCapabilities(GDALWMSMiniDriverCapabilities *caps)
+void WMSMiniDriver_AGS::GetCapabilities(WMSMiniDriverCapabilities *caps)
 {
-    caps->m_capabilities_version = 1;
-    caps->m_has_arb_overviews = 1;
-    caps->m_has_image_request = 1;
-    caps->m_has_tiled_image_requeset = 1;
-    caps->m_max_overview_count = 32;
+    caps->m_has_getinfo = 1;
 }
 
-void GDALWMSMiniDriver_AGS::ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri)
+CPLErr WMSMiniDriver_AGS::TiledImageRequest(WMSHTTPRequest &request,
+                                                const GDALWMSImageRequestInfo &iri,
+                                                CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri)
 {
-    *url = m_base_url;
-
-    if (m_base_url.ifind( "/export?") == std::string::npos)
-        URLAppend(url, "/export?");
-
-    URLAppendF(url, "&f=image");
-    URLAppendF(url, "&bbox=%.8f,%.8f,%.8f,%.8f",
-            GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
-    GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
-    URLAppendF(url, "&size=%d,%d", iri.m_sx,iri.m_sy);
-    URLAppendF(url, "&dpi=");
-    URLAppendF(url, "&imageSR=%s", m_irs.c_str());
-    URLAppendF(url, "&bboxSR=%s", m_irs.c_str());
-    URLAppendF(url, "&format=%s", m_image_format.c_str());
-
-    URLAppendF(url, "&layerdefs=");
-    URLAppendF(url, "&layers=%s", m_layers.c_str());
-
-    if(m_transparent.size())
-        URLAppendF(url, "&transparent=%s", m_transparent.c_str());
+    CPLString &url = request.URL;
+    url = m_base_url;
+
+    // Assume map service if exportImage is not explicitly requested
+    if ((url.ifind("/export?") == std::string::npos) && (url.ifind("/exportImage?") == std::string::npos))
+        url += "/export?";
+
+    URLPrepare(url);
+    url += "f=image&dpi=&layerdefs=&layerTimeOptions=&dynamicLayers=";
+    url += CPLOPrintf("&bbox=%.8f,%.8f,%.8f,%.8f",
+                GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
+                GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]))
+        + CPLOPrintf("&size=%d,%d", iri.m_sx, iri.m_sy)
+        + CPLOPrintf("&imageSR=%s", m_irs.c_str())
+        + CPLOPrintf("&bboxSR=%s", m_irs.c_str())
+        + CPLOPrintf("&format=%s", m_image_format.c_str())
+        + CPLOPrintf("&layers=%s", m_layers.c_str());
+
+    if (!m_transparent.empty() )
+        url +=  CPLOPrintf("&transparent=%s", m_transparent.c_str());
     else
-        URLAppendF(url, "&transparent=%s", "false");
-
-    URLAppendF(url, "&time=");
-    URLAppendF(url, "&layerTimeOptions=");
-    URLAppendF(url, "&dynamicLayers=");
+        url += "&transparent=false";
 
-    CPLDebug("AGS", "URL = %s\n", url->c_str());
-}
+    if (!m_time_range.empty() )
+        url += CPLOPrintf("&time=%s", m_time_range.c_str());
+    else
+        url += "&time=";
 
-void GDALWMSMiniDriver_AGS::TiledImageRequest(CPLString *url,
-                                      const GDALWMSImageRequestInfo &iri,
-                                      CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri)
-{
-	ImageRequest(url, iri);
+    return CE_None;
 }
 
-
-void GDALWMSMiniDriver_AGS::GetTiledImageInfo(CPLString *url,
+void WMSMiniDriver_AGS::GetTiledImageInfo(CPLString &url,
                                               const GDALWMSImageRequestInfo &iri,
                                               CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri,
                                               int nXInBlock,
                                               int nYInBlock)
 {
-    *url = m_base_url;
+    url = m_base_url;
 
-    if (m_base_url.ifind( "/identify?") == std::string::npos)
-        URLAppend(url, "/identify?");
+    if (m_base_url.ifind("/identify?") == std::string::npos)
+        url += "/identify?";
 
-    URLAppendF(url, "&f=json");
+    URLPrepare(url);
+    // Constant part
+    url += "f=json&geometryType=esriGeometryPoint&returnGeometry=false"
+           "&layerdefs=&time=&layerTimeOptions=&maxAllowableOffset=";
 
     double fX = GetBBoxCoord(iri, 'x') + nXInBlock * (GetBBoxCoord(iri, 'X') -
                 GetBBoxCoord(iri, 'x')) / iri.m_sx;
     double fY = GetBBoxCoord(iri, 'y') + (iri.m_sy - nYInBlock) * (GetBBoxCoord(iri, 'Y') -
                 GetBBoxCoord(iri, 'y')) / iri.m_sy;
 
-    URLAppendF(url, "&geometry=%8f,%8f", fX, fY);
-    URLAppendF(url, "&geometryType=esriGeometryPoint");
-
-    URLAppendF(url, "&sr=%s", m_irs.c_str());
-    URLAppendF(url, "&layerdefs=");
-    URLAppendF(url, "&time=");
-    URLAppendF(url, "&layerTimeOptions=");
+    url += CPLOPrintf("&geometry=%8f,%8f", fX, fY)
+        +  CPLOPrintf("&sr=%s", m_irs.c_str());
 
     CPLString layers("visible");
-    if ( m_layers.find("show") != std::string::npos )
-    {
-            layers = m_layers;
-            layers.replace( layers.find("show"), 4, "all" );
-    }
-
-    if ( m_layers.find("hide") != std::string::npos )
-    {
-            layers = "top";
-    }
-
-    if ( m_layers.find("include") != std::string::npos )
-    {
-            layers = "top";
-    }
 
-    if ( m_layers.find("exclude") != std::string::npos )
+    if (m_layers.find("show") != std::string::npos)
     {
-            layers = "top";
+        layers = m_layers;
+        layers.replace(layers.find("show"), 4, "all");
     }
 
-    URLAppendF(url, "&layers=%s", layers.c_str());
-
-    URLAppendF(url, "&tolerance=%s", m_identification_tolerance.c_str());
-    URLAppendF(url, "&mapExtent=%.8f,%.8f,%.8f,%.8f",
-            GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
-    GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
-    URLAppendF(url, "&imageDisplay=%d,%d,96", iri.m_sx,iri.m_sy);
-    URLAppendF(url, "&returnGeometry=false");
-
-    URLAppendF(url, "&maxAllowableOffset=");
-    CPLDebug("AGS", "URL = %s", url->c_str());
-}
-
-
-const char *GDALWMSMiniDriver_AGS::GetProjectionInWKT()
-{
-    return m_projection_wkt.c_str();
-}
-
-double GDALWMSMiniDriver_AGS::GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what)
-{
-    switch (what)
-    {
-        case 'x': return MIN(iri.m_x0, iri.m_x1);
-        case 'y': return MIN(iri.m_y0, iri.m_y1);
-        case 'X': return MAX(iri.m_x0, iri.m_x1);
-        case 'Y': return MAX(iri.m_y0, iri.m_y1);
-    }
-    return 0.0;
+    if (m_layers.find("hide") != std::string::npos
+            || m_layers.find("include") != std::string::npos
+            || m_layers.find("exclude") != std::string::npos)
+        layers = "top";
+
+    url += "&layers=";
+    url += layers;
+    url += "&tolerance=";
+    url += m_identification_tolerance;
+    url += CPLOPrintf("&mapExtent=%.8f,%.8f,%.8f,%.8f",
+        GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
+        GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]))
+        + CPLOPrintf("&imageDisplay=%d,%d,96", iri.m_sx, iri.m_sy);
 }
diff --git a/frmts/wms/minidriver_arcgis_server.h b/frmts/wms/minidriver_arcgis_server.h
index 9806b56..14b903d 100644
--- a/frmts/wms/minidriver_arcgis_server.h
+++ b/frmts/wms/minidriver_arcgis_server.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: minidriver_arcgis_server.h 36611 2016-12-01 23:13:38Z lplesea $
  *
  * Project:  Arc GIS Server Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,46 +28,42 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-H_GDALWMSMiniDriverFactory(AGS)
-
-class GDALWMSMiniDriver_AGS : public GDALWMSMiniDriver
+class WMSMiniDriver_AGS : public WMSMiniDriver
 {
 public:
-    GDALWMSMiniDriver_AGS();
-    virtual ~GDALWMSMiniDriver_AGS();
+    WMSMiniDriver_AGS();
+    virtual ~WMSMiniDriver_AGS();
 
 public:
-    virtual CPLErr Initialize(CPLXMLNode *config);
-    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
-    virtual void ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri,
-                                   const GDALWMSTiledImageRequestInfo &tiri);
-    virtual void GetTiledImageInfo(CPLString *url,
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) override;
+    virtual void GetCapabilities(WMSMiniDriverCapabilities *caps) override;
+    virtual CPLErr TiledImageRequest(WMSHTTPRequest &request,
+                                   const GDALWMSImageRequestInfo &iri,
+                                   const GDALWMSTiledImageRequestInfo &tiri) override;
+    virtual void GetTiledImageInfo(CPLString &url,
                                    const GDALWMSImageRequestInfo &iri,
                                    const GDALWMSTiledImageRequestInfo &tiri,
                                    int nXInBlock,
-                                   int nYInBlock);
-    virtual const char *GetProjectionInWKT();
+                                   int nYInBlock) override;
 
-protected:
-    double GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what);
+    virtual char **GetMetadataDomainList() override;
 
 protected:
-    CPLString m_base_url;
-	/*
-	 * png | png8 | png24 | jpg | pdf | bmp | gif | svg | png32
-	 * http://resources.arcgis.com/en/help/rest/apiref/
-	 * Parameter - format
-	 */
-	CPLString m_image_format;
-	CPLString m_transparent;
-	CPLString m_bbox_order;
-	CPLString m_irs;
+
+    /*
+     * png | png8 | png24 | jpg | pdf | bmp | gif | svg | png32
+     * http://resources.arcgis.com/en/help/rest/apiref/
+     * Parameter - format
+     */
+    CPLString m_image_format;
+    CPLString m_transparent;
+    CPLString m_bbox_order;
+    CPLString m_irs;
 
     CPLString m_layers;
     CPLString m_srs;
     CPLString m_crs;
-    CPLString m_projection_wkt;
+    CPLString m_time_range;
 
-	CPLString m_identification_tolerance;
+    CPLString m_identification_tolerance;
 };
diff --git a/frmts/wms/minidriver_iip.cpp b/frmts/wms/minidriver_iip.cpp
index 9598564..3498df7 100644
--- a/frmts/wms/minidriver_iip.cpp
+++ b/frmts/wms/minidriver_iip.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: minidriver_iip.cpp 33844 2016-04-01 08:42:13Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Mini driver for Internet Imaging Protocol (IIP)
@@ -30,52 +29,43 @@
 #include "wmsdriver.h"
 #include "minidriver_iip.h"
 
+CPL_CVSID("$Id: minidriver_iip.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
-CPP_GDALWMSMiniDriverFactory(IIP)
+WMSMiniDriver_IIP::WMSMiniDriver_IIP() {}
 
-GDALWMSMiniDriver_IIP::GDALWMSMiniDriver_IIP() {
-}
-
-GDALWMSMiniDriver_IIP::~GDALWMSMiniDriver_IIP() {
-}
+WMSMiniDriver_IIP::~WMSMiniDriver_IIP() {}
 
-CPLErr GDALWMSMiniDriver_IIP::Initialize(CPLXMLNode *config) {
+CPLErr WMSMiniDriver_IIP::Initialize(CPLXMLNode *config, CPL_UNUSED char **papszOpenOptions) {
     CPLErr ret = CE_None;
 
-    if (ret == CE_None) {
-        const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
-        if (base_url[0] != '\0') {
-            m_base_url = base_url;
-        } else {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, IIP mini-driver: ServerURL missing.");
-            ret = CE_Failure;
-        }
+    m_base_url = CPLGetXMLValue(config, "ServerURL", "");
+    if (m_base_url.empty()) {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, IIP mini-driver: ServerURL missing.");
+        return CE_Failure;
     }
 
     return ret;
 }
 
-void GDALWMSMiniDriver_IIP::GetCapabilities(GDALWMSMiniDriverCapabilities *caps) {
-    caps->m_capabilities_version = 1;
-    caps->m_has_arb_overviews = 0;
-    caps->m_has_image_request = 0;
-    caps->m_has_tiled_image_requeset = 1;
-    caps->m_max_overview_count = 32;
+void WMSMiniDriver_IIP::GetCapabilities(WMSMiniDriverCapabilities *caps) {
     caps->m_overview_dim_computation_method = OVERVIEW_FLOOR;
     caps->m_has_geotransform = false;
 }
 
-void GDALWMSMiniDriver_IIP::TiledImageRequest(
-    CPLString *url,
+CPLErr WMSMiniDriver_IIP::TiledImageRequest(
+    WMSHTTPRequest &request,
     const GDALWMSImageRequestInfo & /* iri */,
     const GDALWMSTiledImageRequestInfo &tiri)
 {
+    CPLString &url = request.URL;
+    url = m_base_url;
+    URLPrepare(url);
+
     int nTileXCount = (
         (m_parent_dataset->GetRasterXSize()
-         >> (m_parent_dataset->GetRasterBand(1)->GetOverviewCount()
-          - tiri.m_level)) + 255) / 256;
+        >> (m_parent_dataset->GetRasterBand(1)->GetOverviewCount()
+        - tiri.m_level)) + 255) / 256;
     int numTile = tiri.m_x + tiri.m_y * nTileXCount;
-
-    *url = m_base_url;
-    *url += CPLSPrintf("&jtl=%d,%d", tiri.m_level, numTile);
+    url += CPLOPrintf("jtl=%d,%d", tiri.m_level, numTile);
+    return CE_None;
 }
diff --git a/frmts/wms/minidriver_iip.h b/frmts/wms/minidriver_iip.h
index 99552f9..86d14e5 100644
--- a/frmts/wms/minidriver_iip.h
+++ b/frmts/wms/minidriver_iip.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_iip.h 33844 2016-04-01 08:42:13Z rouault $
+ * $Id: minidriver_iip.h 37463 2017-02-26 02:16:35Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Mini driver for Internet Imaging Protocol (IIP)
@@ -27,18 +27,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-H_GDALWMSMiniDriverFactory(IIP)
-
-class GDALWMSMiniDriver_IIP : public GDALWMSMiniDriver {
+class WMSMiniDriver_IIP : public WMSMiniDriver {
 public:
-    GDALWMSMiniDriver_IIP();
-    virtual ~GDALWMSMiniDriver_IIP();
+    WMSMiniDriver_IIP();
+    virtual ~WMSMiniDriver_IIP();
 
 public:
-    virtual CPLErr Initialize(CPLXMLNode *config);
-    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
-
-protected:
-    CPLString m_base_url;
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) override;
+    virtual void GetCapabilities(WMSMiniDriverCapabilities *caps) override;
+    virtual CPLErr TiledImageRequest(WMSHTTPRequest &request,
+                                     const GDALWMSImageRequestInfo &iri,
+                                     const GDALWMSTiledImageRequestInfo &tiri) override;
 };
diff --git a/frmts/wms/minidriver_mrf.cpp b/frmts/wms/minidriver_mrf.cpp
new file mode 100644
index 0000000..cace792
--- /dev/null
+++ b/frmts/wms/minidriver_mrf.cpp
@@ -0,0 +1,323 @@
+/******************************************************************************
+* $Id$
+*
+* Project:  WMS Client Mini Driver
+* Purpose:  Implementation of Dataset and RasterBand classes for WMS
+*           and other similar services.
+* Author:   Lucian Plesea
+*
+******************************************************************************
+* Copyright (c) 2016, Lucian Plesea
+*
+* Copyright 2016 Esri
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+****************************************************************************/
+
+/*
+ A WMS style minidriver that allows an MRF or an Esri bundle to be read from a URL, using one range request per tile
+ All parameters have to be defined in the WMS file, especially for the MRF, so only simple MRF files work.
+ For a bundle, the size is assumed to be 128 tiles of 256 pixels each, which is the standard size.
+ */
+
+#include "wmsdriver.h"
+#include "minidriver_mrf.h"
+
+CPL_CVSID("$Id$");
+
+using namespace WMSMiniDriver_MRF_ns;
+
+// Copied from frmts/mrf
+
+// A tile index record, 16 bytes, big endian
+typedef struct {
+    GIntBig offset;
+    GIntBig size;
+} MRFIdx;
+
+// Number of pages of size psz needed to hold n elements
+static inline int pcount(const int n, const int sz) {
+    return 1 + (n - 1) / sz;
+}
+
+// Returns a pagecount per dimension, .l will have the total number
+static inline const ILSize pcount(const ILSize &size, const ILSize &psz) {
+    ILSize count;
+    count.x = pcount(size.x, psz.x);
+    count.y = pcount(size.y, psz.y);
+    count.z = pcount(size.z, psz.z);
+    count.c = pcount(size.c, psz.c);
+    count.l = static_cast<GIntBig>(count.x) * count.y * count.z * count.c;
+    return count;
+}
+
+// End copied from frmts/mrf
+
+
+// pread_t adapter for VSIL
+static size_t pread_VSIL(void *user_data, void *buff, size_t count, off_t offset) {
+    VSILFILE *fp = reinterpret_cast<VSILFILE *>(user_data);
+    VSIFSeekL(fp, offset, SEEK_SET);
+    return VSIFReadL(buff, 1, count, fp);
+}
+
+// pread_t adapter for curl.  We use the multi interface to get the same options
+static size_t pread_curl(void *user_data, void *buff, size_t count, off_t offset) {
+    // Use a copy of the provided request, which has the options and the URL preset
+    WMSHTTPRequest request(*(reinterpret_cast<WMSHTTPRequest *>(user_data)));
+    request.Range.Printf(CPL_FRMT_GUIB "-" CPL_FRMT_GUIB,
+                            static_cast<GUIntBig>(offset),
+                            static_cast<GUIntBig>(offset + count - 1));
+    WMSHTTPInitializeRequest(&request);
+    if (WMSHTTPFetchMulti(&request) != CE_None) {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS_MRF: failed to retrieve index data");
+        return 0;
+    }
+
+    int success = (request.nStatus == 200) ||
+        (!request.Range.empty() && request.nStatus == 206);
+    if (!success || request.pabyData == NULL || request.nDataLen == 0) {
+        CPLError(CE_Failure, CPLE_HttpResponse,
+            "GDALWMS: Unable to download data from %s",
+            request.URL.c_str());
+        return 0; // Error flag
+    }
+
+    // Might get less data than requested
+    if (request.nDataLen < count)
+        memset(buff, 0, count);
+    memcpy(buff, request.pabyData, request.nDataLen);
+    return request.nDataLen;
+}
+
+SectorCache::SectorCache(void *user_data,
+                         pread_t fn,
+                         unsigned int size,
+                         unsigned int count ) :
+    n(count + 2), m(size), reader(fn ? fn : pread_VSIL),
+    reader_data(user_data), last_used(NULL)
+{
+}
+
+
+// Returns an in-memory offset to the byte at the given address, within a sector
+// Returns NULL if the sector can't be read
+void *SectorCache::data(size_t address) {
+    for (size_t i = 0; i < store.size(); i++) {
+        if (store[i].uid == address / m) {
+            last_used = &store[i];
+            return &(last_used->range[address % m]);
+        }
+    }
+
+    // Not found, need a target sector to replace
+    Sector *target;
+    if (store.size() < m) { // Create a new sector if there are slots available
+        store.resize(store.size() + 1);
+        target = &store.back();
+    }
+    else { // Choose a random one to replace, but not the last used, to avoid thrashing
+        do {
+            // coverity[dont_call]
+            target = &(store[rand() % n]);
+        } while (target == last_used);
+    }
+
+    target->range.resize(m);
+    if (reader(reader_data, &target->range[0], m, static_cast<off_t>((address / m ) * m))) { // Success
+        target->uid = address / m;
+        last_used = target;
+        return &(last_used->range[address %m]);
+    }
+
+    // Failure
+    // If this is the last sector, it could be a new sector with invalid data, so we remove it
+    // Otherwise, the previous content is still good
+    if (target == &store.back())
+        store.resize(store.size() - 1);
+    // Signal invalid request
+    return NULL;
+}
+
+// Keep in sync with the type enum
+static const int ir_size[WMSMiniDriver_MRF::tEND] = { 16, 8 };
+
+WMSMiniDriver_MRF::WMSMiniDriver_MRF(): m_type(tMRF), fp(NULL), m_request(NULL),index_cache(NULL) {};
+
+WMSMiniDriver_MRF::~WMSMiniDriver_MRF() {
+    if (index_cache)
+        delete index_cache;
+    if (fp)
+        VSIFCloseL(fp);
+}
+
+CPLErr WMSMiniDriver_MRF::Initialize(CPLXMLNode *config, CPL_UNUSED char **papszOpenOptions) {
+    // This gets called before the rest of the WMS driver gets initialized
+    // The MRF reader only works if all datawindow is defined within the WMS file
+
+    m_base_url = CPLGetXMLValue(config, "ServerURL", "");
+    if (m_base_url.empty()) {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, MRF: ServerURL missing.");
+        return CE_Failure;
+    }
+
+    // Index file location, in case it is different from the normal file name
+    m_idxname = CPLGetXMLValue(config, "index", "");
+
+    CPLString osType(CPLGetXMLValue(config, "type", ""));
+
+    if (EQUAL(osType, "bundle"))
+        m_type = tBundle;
+
+    if (m_type == tBundle) {
+        m_parent_dataset->WMSSetDefaultOverviewCount(0);
+        m_parent_dataset->WMSSetDefaultTileCount(128, 128);
+        m_parent_dataset->WMSSetDefaultBlockSize(256, 256);
+        m_parent_dataset->WMSSetDefaultTileLevel(0);
+        m_parent_dataset->WMSSetNeedsDataWindow(FALSE);
+        offsets.push_back(64);
+    }
+    else { // MRF
+        offsets.push_back(0);
+    }
+
+    return CE_None;
+}
+
+// Test for URL, things that curl can deal with while doing a range request
+// http and https should work, not sure about ftp or file
+int inline static is_url(const CPLString &value) {
+    return (value.ifind("http://") == 0
+        || value.ifind("https://") == 0
+        || value.ifind("ftp://") == 0
+        || value.ifind("file://") == 0
+        );
+}
+
+// Called after the dataset is initialized by the main WMS driver
+CPLErr WMSMiniDriver_MRF::EndInit() {
+    int index_is_url = 1;
+    if (!m_idxname.empty() ) { // Provided, could be path or URL
+        if (!is_url(m_idxname)) {
+            index_is_url = 0;
+            fp = VSIFOpenL(m_idxname, "rb");
+            if (fp == NULL) {
+                CPLError(CE_Failure, CPLE_FileIO, "Can't open index file %s", m_idxname.c_str());
+                return CE_Failure;
+            }
+            index_cache = new SectorCache(fp);
+        }
+    }
+    else { // Not provided, change extension to .idx if we can, otherwise use the same file
+        m_idxname = m_base_url;
+    }
+
+    if (index_is_url) { // prepare a WMS request, the pread_curl will execute it repeatedly
+        m_request = new WMSHTTPRequest();
+        m_request->URL = m_idxname;
+        m_request->options = m_parent_dataset->GetHTTPRequestOpts();
+        index_cache = new SectorCache(m_request, pread_curl);
+    }
+
+    // Set the level index offsets, assume MRF order since esri bundles don't have overviews
+    ILSize size(m_parent_dataset->GetRasterXSize(),
+                m_parent_dataset->GetRasterYSize(),
+                1, // Single slice for now
+                1, // Ignore the c, only single or interleved data supported by WMS
+                m_parent_dataset->GetRasterBand(1)->GetOverviewCount());
+
+    int psx, psy;
+    m_parent_dataset->GetRasterBand(1)->GetBlockSize(&psx, &psy);
+    ILSize pagesize(psx, psy, 1, 1, 1);
+
+    if (m_type == tBundle) { // A bundle contains 128x128 pages, regadless of the raster size
+        size.x = psx * 128;
+        size.y = psy * 128;
+    }
+
+    for (GIntBig l = size.l; l >= 0; l--) {
+        ILSize pagecount = pcount(size, pagesize);
+        pages.push_back(pagecount);
+        if (l > 0) // Only for existing levels
+            offsets.push_back(offsets.back() + ir_size[m_type] * pagecount.l);
+
+        // Sometimes this may be a 3
+        size.x = pcount(size.x, 2);
+        size.y = pcount(size.y, 2);
+    }
+
+    return CE_None;
+}
+
+// Return -1 if error occurs
+size_t WMSMiniDriver_MRF::GetIndexAddress(const GDALWMSTiledImageRequestInfo &tiri) {
+    // Bottom level is 0
+    int l = - tiri.m_level;
+    if (l < 0 || l >= static_cast<int>(offsets.size()))
+        return ~static_cast<size_t>(0); // Indexing error
+    if (tiri.m_x >= pages[l].x || tiri.m_y >= pages[l].y)
+        return ~static_cast<size_t>(0);
+    return static_cast<size_t>(offsets[l] + (pages[l].x * tiri.m_y + tiri.m_x) * ir_size[m_type]);
+}
+
+// Signal errors and return error message
+CPLErr WMSMiniDriver_MRF::TiledImageRequest(WMSHTTPRequest &request,
+    CPL_UNUSED const GDALWMSImageRequestInfo &iri,
+    const GDALWMSTiledImageRequestInfo &tiri)
+{
+    CPLString &url = request.URL;
+    url = m_base_url;
+
+    size_t offset = GetIndexAddress(tiri);
+    if (offset == static_cast<size_t>(-1)) {
+        request.Error = "Invalid level requested";
+        return CE_Failure;
+    }
+
+    void *raw_index = index_cache->data(offset);
+    if (raw_index == NULL) {
+        request.Error = "Invalid indexing";
+        return CE_Failure;
+    };
+
+    // Store the tile size and offset in this structure
+    MRFIdx idx;
+
+    if (m_type == tMRF) {
+        memcpy(&idx, raw_index, sizeof(idx));
+
+#if defined(CPL_LSB) // raw index is MSB
+        idx.offset = CPL_SWAP64(idx.offset);
+        idx.size = CPL_SWAP64(idx.size);
+#endif
+
+    } else { // Bundle
+        GIntBig bidx;
+        memcpy(&bidx, raw_index, sizeof(bidx));
+
+#if defined(CPL_MSB) // bundle index is LSB
+        bidx = CPL_SWAP64(bidx);
+#endif
+
+        idx.offset = bidx & ((1ULL << 40) -1);
+        idx.size = bidx >> 40;
+    }
+
+    // Set the range or flag it as missing
+    if (idx.size == 0)
+        request.Range = "none"; // Signal that this block doesn't exist server-side
+    else
+        request.Range.Printf(CPL_FRMT_GUIB "-" CPL_FRMT_GUIB, idx.offset, idx.offset + idx.size - 1);
+
+    return CE_None;
+}
diff --git a/frmts/wms/minidriver_mrf.h b/frmts/wms/minidriver_mrf.h
new file mode 100644
index 0000000..5567319
--- /dev/null
+++ b/frmts/wms/minidriver_mrf.h
@@ -0,0 +1,117 @@
+/******************************************************************************
+* $Id: minidriver_mrf.h 35774 2016-10-17 00:35:33Z lplesea $
+*
+* Project:  WMS driver
+* Purpose:  Access a remote MRF tile by tile, using range requests
+* Author:   Lucian Plesea
+*
+******************************************************************************
+* Copyright (c) 2016, Lucian Plesea
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+****************************************************************************/
+
+#include <vector>
+
+namespace WMSMiniDriver_MRF_ns {
+
+    //
+// Almost like pread, but no thread safety
+// Unlike pread, the first argument is a pointer to an opaque structure
+// Return of zero means an error occurred (could be end of file)
+//
+typedef size_t(*pread_t)(void *user_data, void *buff, size_t count, off_t offset);
+
+//
+// A sector cache, for up to N sectors of a fixed size M
+// N has to be at least two, the user specifies extras
+// Used for session caching the remote index
+//
+class SectorCache {
+public:
+    SectorCache(void *user_data,
+                pread_t fn = NULL,
+                unsigned int size = 1024,
+                unsigned int count = 2);
+
+    // Fetches a pointer within the sector to the byte at the given address
+    // No alignment is guaranteed, and only enough bytes to reach the end of the sector are available
+    void *data(size_t address);
+
+private:
+    SectorCache();
+    struct Sector {
+        std::vector<char> range;
+        size_t uid;
+    };
+
+    // N sectors of M bytes each
+    unsigned int n, m;
+
+    // Pointer to an pread like function
+    pread_t reader;
+    void *reader_data;
+    // To avoid thrashing
+    Sector *last_used;
+    std::vector<Sector> store;
+};
+
+// Size of an image, also used as a tile or pixel location
+struct ILSize {
+    ILSize():  x(0), y(0), z(0), c(0), l(0) {};
+    ILSize(GInt32 _x, GInt32 _y, GInt32 _z = 1, GInt32 _c = 1, GInt32 _l = -1) :
+        x(_x), y(_y), z(_z), c(_c), l(_l) {};
+    GInt32 x, y, z, c;
+    GIntBig l; // Dual use, sometimes it holds the number of pages
+};
+
+}; // namespace WMSMiniDriver_MRF
+
+class WMSMiniDriver_MRF : public WMSMiniDriver {
+public:
+    WMSMiniDriver_MRF();
+    virtual ~WMSMiniDriver_MRF();
+
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) override;
+    virtual CPLErr EndInit() override;
+
+    virtual CPLErr TiledImageRequest(WMSHTTPRequest &url,
+                                    const GDALWMSImageRequestInfo &iri,
+                                    const GDALWMSTiledImageRequestInfo &tiri) override;
+
+    enum { tMRF, tBundle, tEND };
+
+private:
+    size_t GetIndexAddress(const GDALWMSTiledImageRequestInfo &tiri);
+
+    // The path or URL for index
+    CPLString m_idxname;
+
+    // Which type of remote file this is, one of the types above
+    int m_type;
+
+    VSILFILE *fp; // If index is a file
+    WMSHTTPRequest *m_request; // If index is an URL
+    WMSMiniDriver_MRF_ns::SectorCache *index_cache;
+
+    // Per level index offsets, level 0 being the full resolution
+    std::vector<GUIntBig> offsets;
+    // Matching pagecounts
+    std::vector<WMSMiniDriver_MRF_ns::ILSize> pages;
+};
diff --git a/frmts/wms/minidriver_tiled_wms.cpp b/frmts/wms/minidriver_tiled_wms.cpp
index 373f764..0690710 100644
--- a/frmts/wms/minidriver_tiled_wms.cpp
+++ b/frmts/wms/minidriver_tiled_wms.cpp
@@ -32,9 +32,9 @@
 #include "wmsdriver.h"
 #include "minidriver_tiled_wms.h"
 
-CPP_GDALWMSMiniDriverFactory(TiledWMS)
+CPL_CVSID("$Id: minidriver_tiled_wms.cpp 37949 2017-04-10 20:53:07Z lplesea $");
 
-static const char SIG[]="GDAL_WMS TiledWMS: ";
+static const char SIG[] = "GDAL_WMS TiledWMS: ";
 
 /*
  *\brief Read a number from an xml element
@@ -42,7 +42,7 @@ static const char SIG[]="GDAL_WMS TiledWMS: ";
 
 static double getXMLNum(CPLXMLNode *poRoot, const char *pszPath, const char *pszDefault)
 {
-    return CPLAtof(CPLGetXMLValue(poRoot,pszPath,pszDefault));
+    return CPLAtof(CPLGetXMLValue(poRoot, pszPath, pszDefault));
 }
 
 /*
@@ -53,14 +53,13 @@ static double getXMLNum(CPLXMLNode *poRoot, const char *pszPath, const char *psz
 static GDALColorEntry GetXMLColorEntry(CPLXMLNode *p)
 {
     GDALColorEntry ce;
-    ce.c1= static_cast<short>(getXMLNum(p,"c1","0"));
-    ce.c2= static_cast<short>(getXMLNum(p,"c2","0"));
-    ce.c3= static_cast<short>(getXMLNum(p,"c3","0"));
-    ce.c4= static_cast<short>(getXMLNum(p,"c4","255"));
+    ce.c1 = static_cast<short>(getXMLNum(p, "c1", "0"));
+    ce.c2 = static_cast<short>(getXMLNum(p, "c2", "0"));
+    ce.c3 = static_cast<short>(getXMLNum(p, "c3", "0"));
+    ce.c4 = static_cast<short>(getXMLNum(p, "c4", "255"));
     return ce;
 }
 
-
 /************************************************************************/
 /*                           SearchXMLSiblings()                        */
 /************************************************************************/
@@ -80,24 +79,24 @@ static GDALColorEntry GetXMLColorEntry(CPLXMLNode *p)
  * @return The first matching node or NULL on failure.
  */
 
-static CPLXMLNode *SearchXMLSiblings( CPLXMLNode *psRoot, const char *pszElement )
+static CPLXMLNode *SearchXMLSiblings(CPLXMLNode *psRoot, const char *pszElement)
 
 {
-    if( psRoot == NULL || pszElement == NULL )
+    if (psRoot == NULL || pszElement == NULL)
         return NULL;
 
     // If the strings starts with '=', skip it and test the root
     // If not, start testing with the next sibling
-    if (pszElement[0]=='=')
+    if (pszElement[0] == '=')
         pszElement++;
     else
-        psRoot=psRoot->psNext;
+        psRoot = psRoot->psNext;
 
-    for (;psRoot!=NULL;psRoot=psRoot->psNext)
+    for (; psRoot != NULL; psRoot = psRoot->psNext)
     {
         if ((psRoot->eType == CXT_Element ||
-             psRoot->eType == CXT_Attribute)
-             && EQUAL(pszElement,psRoot->pszValue))
+            psRoot->eType == CXT_Attribute)
+            && EQUAL(pszElement, psRoot->pszValue))
             return psRoot;
     }
     return NULL;
@@ -118,30 +117,30 @@ static CPLXMLNode *SearchXMLSiblings( CPLXMLNode *psRoot, const char *pszElement
  * @return The XML node of the matching TileGroup or NULL on failure.
  */
 
-static CPLXMLNode *SearchLeafGroupName( CPLXMLNode *psRoot, const char *name )
+static CPLXMLNode *SearchLeafGroupName(CPLXMLNode *psRoot, const char *name)
 
 {
-    CPLXMLNode *ret=NULL;
+    CPLXMLNode *ret = NULL;
 
-    if( psRoot == NULL || name == NULL ) return NULL;
+    if (psRoot == NULL || name == NULL) return NULL;
 
     // Has to be a leaf TileGroup with the right name
-    if (NULL==SearchXMLSiblings(psRoot->psChild,"TiledGroup"))
+    if (NULL == SearchXMLSiblings(psRoot->psChild, "TiledGroup"))
     {
-        if (EQUAL(name,CPLGetXMLValue(psRoot,"Name","")))
+        if (EQUAL(name, CPLGetXMLValue(psRoot, "Name", "")))
         {
             return psRoot;
         }
         else
         { // Try a sibling
-            return SearchLeafGroupName(psRoot->psNext,name);
+            return SearchLeafGroupName(psRoot->psNext, name);
         }
     }
     else
     { // Is metagroup, try children then siblings
-        ret=SearchLeafGroupName(psRoot->psChild,name);
-        if (NULL!=ret) return ret;
-        return SearchLeafGroupName(psRoot->psNext,name);
+        ret = SearchLeafGroupName(psRoot->psChild, name);
+        if (NULL != ret) return ret;
+        return SearchLeafGroupName(psRoot->psNext, name);
     }
 }
 
@@ -162,14 +161,14 @@ static CPLXMLNode *SearchLeafGroupName( CPLXMLNode *psRoot, const char *name )
 
 static GDALColorInterp BandInterp(int nbands, int band) {
     switch (nbands) {
-      case 1: return GCI_GrayIndex;
-      case 2: return ((band==1)?GCI_GrayIndex:GCI_AlphaBand);
-      case 3: // RGB
-      case 4: // RBGA
-        if (band<3)
-            return ((band==1)?GCI_RedBand:GCI_GreenBand);
-        return ((band==3)?GCI_BlueBand:GCI_AlphaBand);
-      default:
+    case 1: return GCI_GrayIndex;
+    case 2: return band == 1 ? GCI_GrayIndex : GCI_AlphaBand;
+    case 3: // RGB
+    case 4: // RBGA
+        if (band < 3)
+            return band == 1 ? GCI_RedBand : GCI_GreenBand;
+        return band == 3 ? GCI_BlueBand : GCI_AlphaBand;
+    default:
         return GCI_Undefined;
     }
 }
@@ -209,53 +208,53 @@ static int FindBbox(CPLString in) {
  * @param ret The return value, a matching request or an empty string
  */
 
-static void FindChangePattern( char *cdata,char **substs, char **keys, CPLString &ret)
+static void FindChangePattern(char *cdata, char **substs, char **keys, CPLString &ret)
 {
-    char **papszTokens=CSLTokenizeString2(cdata," \t\n\r",
-                                           CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
+    char **papszTokens = CSLTokenizeString2(cdata, " \t\n\r",
+        CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
     ret.clear();
 
-    int matchcount=CSLCount(substs);
-    int keycount=CSLCount(keys);
-    if (keycount<matchcount)
+    int matchcount = CSLCount(substs);
+    int keycount = CSLCount(keys);
+    if (keycount < matchcount)
     {
         CSLDestroy(papszTokens);
         return;
     }
 
     // A valid string has only the keys in the substs list and none other
-    for (int j=0;j<CSLCount(papszTokens);j++)
+    for (int j = 0; j < CSLCount(papszTokens); j++)
     {
-        ret=papszTokens[j];  // The target string
-        bool matches=true;
+        ret = papszTokens[j];  // The target string
+        bool matches = true;
 
-        for (int k=0;k<keycount && keys != NULL;k++)
+        for (int k = 0; k < keycount && keys != NULL; k++)
         {
-            const char *key=keys[k];
-            int sub_number=CSLPartialFindString(substs,key);
-            if (sub_number!=-1)
+            const char *key = keys[k];
+            int sub_number = CSLPartialFindString(substs, key);
+            if (sub_number != -1)
             { // It is a listed match
                 // But is the match for the key position?
-                char *found_key=NULL;
-                const char *found_value=CPLParseNameValue(substs[sub_number],&found_key);
-                if (found_key!=NULL && EQUAL(found_key,key))
+                char *found_key = NULL;
+                const char *found_value = CPLParseNameValue(substs[sub_number], &found_key);
+                if (found_key != NULL && EQUAL(found_key, key))
                 {  // Should exits in the request
-                    if (std::string::npos==ret.find(key))
+                    if (std::string::npos == ret.find(key))
                     {
-                        matches=false;
+                        matches = false;
                         CPLFree(found_key);
                         break;
                     }
                     // Execute the substitution on the "ret" string
-                    URLSearchAndReplace(&ret,key,"%s",found_value);
+                    URLSearchAndReplace(&ret, key, "%s", found_value);
                 }
-                if (found_key!=NULL) CPLFree(found_key);
+                if (found_key != NULL) CPLFree(found_key);
             }
             else
             {  // Key not in the subst list, should not match
-                if (std::string::npos!=ret.find(key))
+                if (std::string::npos != ret.find(key))
                 {
-                    matches=false;
+                    matches = false;
                     break;
                 }
             }
@@ -270,47 +269,45 @@ static void FindChangePattern( char *cdata,char **substs, char **keys, CPLString
     CSLDestroy(papszTokens);
 }
 
-GDALWMSMiniDriver_TiledWMS::GDALWMSMiniDriver_TiledWMS() :
-    m_requests(NULL),
-    m_bsx(0),
-    m_bsy(0)
-{ }
+WMSMiniDriver_TiledWMS::WMSMiniDriver_TiledWMS() :
+m_requests(NULL),
+m_bsx(0),
+m_bsy(0)
+{}
 
-GDALWMSMiniDriver_TiledWMS::~GDALWMSMiniDriver_TiledWMS() {
+WMSMiniDriver_TiledWMS::~WMSMiniDriver_TiledWMS() {
     CSLDestroy(m_requests);
 }
 
-
 // Returns the scale of a WMS request as compared to the base resolution
-double GDALWMSMiniDriver_TiledWMS::Scale(const char *request) {
-    int bbox=FindBbox(request);
-    if (bbox<0) return 0;
-    double x,y,X,Y;
-    CPLsscanf(request+bbox,"%lf,%lf,%lf,%lf",&x,&y,&X,&Y);
-    return (m_data_window.m_x1-m_data_window.m_x0)/(X-x)*m_bsx/m_data_window.m_sx;
+double WMSMiniDriver_TiledWMS::Scale(const char *request) {
+    int bbox = FindBbox(request);
+    if (bbox < 0) return 0;
+    double x, y, X, Y;
+    CPLsscanf(request + bbox, "%lf,%lf,%lf,%lf", &x, &y, &X, &Y);
+    return (m_data_window.m_x1 - m_data_window.m_x0) / (X - x)*m_bsx / m_data_window.m_sx;
 }
 
-
 // Finds, extracts, and returns the highest resolution request string from a list, starting at item i
-CPLString GDALWMSMiniDriver_TiledWMS::GetLowestScale(char **& list,int i)
+CPLString WMSMiniDriver_TiledWMS::GetLowestScale(char **& list, int i)
 {
     CPLString req;
-    double scale=-1;
-    int position=-1;
-    while (NULL!=list[i])
+    double scale = -1;
+    int position = -1;
+    while (NULL != list[i])
     {
-        double tscale=Scale(list[i]);
-        if (tscale>=scale)
+        double tscale = Scale(list[i]);
+        if (tscale >= scale)
         {
-            scale=tscale;
-            position=i;
+            scale = tscale;
+            position = i;
         }
         i++;
     }
-    if (position>-1)
+    if (position > -1)
     {
-        req=list[position];
-        list = CSLRemoveStrings(list,position,1,NULL);
+        req = list[position];
+        list = CSLRemoveStrings(list, position, 1, NULL);
     }
     return req;
 }
@@ -319,146 +316,123 @@ CPLString GDALWMSMiniDriver_TiledWMS::GetLowestScale(char **& list,int i)
  *\Brief Initialize minidriver with info from the server
  */
 
-CPLErr GDALWMSMiniDriver_TiledWMS::Initialize(CPLXMLNode *config)
+CPLErr WMSMiniDriver_TiledWMS::Initialize(CPLXMLNode *config, CPL_UNUSED char **OpenOptions)
 {
     CPLErr ret = CE_None;
-    CPLXMLNode *tileServiceConfig=NULL;
-    CPLHTTPResult *psResult=NULL;
-    CPLXMLNode *TG=NULL;
-
-    char **requests=NULL;
-    char **substs=NULL;
-    char **keys=NULL;
+    CPLXMLNode *tileServiceConfig = NULL;
+    CPLXMLNode *TG = NULL;
 
-    for (int once=1;once;once--) { // Something to break out of
-        // Parse info from the service
+    char **requests = NULL;
+    char **substs = NULL;
+    char **keys = NULL;
 
-        m_end_url = CPLGetXMLValue(config,"AdditionalArgs","");
+    try { // Parse info from the WMS Service node
+//        m_end_url = CPLGetXMLValue(config, "AdditionalArgs", "");
         m_base_url = CPLGetXMLValue(config, "ServerURL", "");
-        if (m_base_url.empty()) {
-            CPLError(ret=CE_Failure, CPLE_AppDefined, "%s ServerURL missing.",SIG);
-            break;
-        }
 
-        CPLString tiledGroupName (CPLGetXMLValue(config, "TiledGroupName", ""));
-        if (tiledGroupName.empty()) {
-            CPLError(ret=CE_Failure, CPLE_AppDefined, "%s TiledGroupName missing.",SIG);
-            break;
-        }
+        if (m_base_url.empty())
+            throw CPLOPrintf("%s ServerURL missing.", SIG);
+
+        CPLString tiledGroupName(CPLGetXMLValue(config, "TiledGroupName", ""));
+        if (tiledGroupName.empty())
+            throw CPLOPrintf("%s TiledGroupName missing.", SIG);
 
         // Change strings, key is an attribute, value is the value of the Change node
         // Multiple substitutions are possible
-        TG=CPLSearchXMLNode(config, "Change");
-        while(TG!=NULL) {
-            CPLString name=CPLGetXMLValue(TG,"key","");
-            if (name.empty()) {
-                CPLError(ret=CE_Failure, CPLE_AppDefined,
-                    "%s Change element needs a non-empty \"key\" attribute",SIG);
-                break;
-            }
-            substs=CSLSetNameValue(substs,name,CPLGetXMLValue(TG,"",""));
-            TG=SearchXMLSiblings(TG,"Change");
+        TG = CPLSearchXMLNode(config, "Change");
+        while (TG != NULL) {
+            CPLString name = CPLGetXMLValue(TG, "key", "");
+            if (name.empty())
+                throw CPLOPrintf("%s Change element needs a non-empty \"key\" attribute", SIG);
+            substs = CSLSetNameValue(substs, name, CPLGetXMLValue(TG, "", ""));
+            TG = SearchXMLSiblings(TG, "Change");
         }
-        if (ret!=CE_None) break;
 
-        CPLString getTileServiceUrl = m_base_url + "request=GetTileService";
-        psResult = CPLHTTPFetch(getTileServiceUrl, NULL);
+        // Part of WMS config
+        const char *psconfig = CPLGetXMLValue(config, "Configuration", "");
 
-        if (NULL==psResult) {
-            CPLError(ret=CE_Failure, CPLE_AppDefined, "%s Can't use HTTP", SIG);
-            break;
-        }
+        CPLString buffer;
 
-        if ((psResult->nStatus!=0)||(NULL==psResult->pabyData)||('\0'==psResult->pabyData[0])) {
-            CPLError(ret=CE_Failure, CPLE_AppDefined, "%s Server response error on GetTileService.",SIG);
-            break;
+        if (strlen(psconfig) != 0) { // Probably XML encoded because it is XML itself
+            buffer = psconfig; // The copy will be replaced by the decoded result
+            psconfig = WMSUtilDecode(buffer, CPLGetXMLValue(config, "Configuration.encoding", ""));
         }
+        else { // Not inline, use the WMSdriver to fetch the server config
+            CPLString getTileServiceUrl = m_base_url + "request=GetTileService";
 
-        if (NULL==(tileServiceConfig=CPLParseXMLString((const char*)psResult->pabyData))) {
-            CPLError(ret=CE_Failure,CPLE_AppDefined, "%s Error parsing the GetTileService response.",SIG);
-            break;
-        }
+            // This returns a string managed by the cfg cache
+            psconfig = GDALWMSDataset::GetServerConfig(getTileServiceUrl,
+                const_cast<char **>(m_parent_dataset->GetHTTPRequestOpts()));
 
-        if (NULL==(TG=CPLSearchXMLNode(tileServiceConfig, "TiledPatterns"))) {
-            CPLError(ret=CE_Failure,CPLE_AppDefined,
-                "%s Can't locate TiledPatterns in server response.",SIG);
-            break;
+            if (psconfig == NULL)
+                throw CPLOPrintf("%s HTTP failure", SIG);
         }
 
+        // psconfig contains the GetTileService return now
+        if (NULL == (tileServiceConfig = CPLParseXMLString(psconfig)))
+            throw CPLOPrintf("%s Error parsing the GetTileService response", SIG);
+
+        if (NULL == (TG = CPLSearchXMLNode(tileServiceConfig, "TiledPatterns")))
+            throw CPLOPrintf("%s Can't locate TiledPatterns in server response.", SIG);
+
         // Get the global base_url and bounding box, these can be overwritten at the tileGroup level
         // They are just pointers into existing structures, cleanup is not required
-        const char *global_base_url=CPLGetXMLValue(tileServiceConfig,"TiledPatterns.OnlineResource.xlink:href","");
-        CPLXMLNode *global_latlonbbox=CPLGetXMLNode(tileServiceConfig, "TiledPatterns.LatLonBoundingBox");
-        CPLXMLNode *global_bbox=CPLGetXMLNode(tileServiceConfig, "TiledPatterns.BoundingBox");
-
-        if (NULL==(TG=SearchLeafGroupName(TG->psChild,tiledGroupName))) {
-            CPLError(ret=CE_Failure,CPLE_AppDefined,
-                "%s Can't locate TiledGroup ""%s"" in server response.",SIG,
-                tiledGroupName.c_str());
-            break;
-        }
+        const char *global_base_url = CPLGetXMLValue(tileServiceConfig, "TiledPatterns.OnlineResource.xlink:href", "");
+        CPLXMLNode *global_latlonbbox = CPLGetXMLNode(tileServiceConfig, "TiledPatterns.LatLonBoundingBox");
+        CPLXMLNode *global_bbox = CPLGetXMLNode(tileServiceConfig, "TiledPatterns.BoundingBox");
 
-        int band_count=atoi(CPLGetXMLValue(TG, "Bands", "3"));
+        if (NULL == (TG = SearchLeafGroupName(TG->psChild, tiledGroupName)))
+            throw CPLOPrintf("%s No TiledGroup ""%s"" in server response.", SIG, tiledGroupName.c_str());
 
-        if (!GDALCheckBandCount(band_count, FALSE)) {
-            CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
-                "Invalid number of bands in server response");
-            break;
-        }
+        int band_count = atoi(CPLGetXMLValue(TG, "Bands", "3"));
+
+        if (!GDALCheckBandCount(band_count, FALSE))
+            throw CPLOPrintf("%s Invalid number of bands in server response", SIG);
 
         // Collect all keys defined by this tileset
-        if (NULL!=CPLGetXMLNode(TG,"Key")) {
-            CPLXMLNode *node=CPLGetXMLNode(TG,"Key");
-                while (NULL!=node) {
-                    const char *val=CPLGetXMLValue(node,NULL,NULL);
-                    if (val) keys=CSLAddString(keys,val);
-                    node=SearchXMLSiblings(node,"Key");
-                }
+        if (NULL != CPLGetXMLNode(TG, "Key")) {
+            CPLXMLNode *node = CPLGetXMLNode(TG, "Key");
+            while (NULL != node) {
+                const char *val = CPLGetXMLValue(node, NULL, NULL);
+                if (val) keys = CSLAddString(keys, val);
+                node = SearchXMLSiblings(node, "Key");
+            }
         }
 
-       // Data values are attributes, they include NoData Min and Max
-       if (NULL!=CPLGetXMLNode(TG,"DataValues")) {
-           const char *nodata=CPLGetXMLValue(TG,"DataValues.NoData",NULL);
-           if (nodata!=NULL) m_parent_dataset->WMSSetNoDataValue(nodata);
-           const char *min=CPLGetXMLValue(TG,"DataValues.min",NULL);
-           if (min!=NULL) m_parent_dataset->WMSSetMinValue(min);
-           const char *max=CPLGetXMLValue(TG,"DataValues.max",NULL);
-           if (max!=NULL) m_parent_dataset->WMSSetMaxValue(max);
-       }
+        // Data values are attributes, they include NoData Min and Max
+        if (NULL != CPLGetXMLNode(TG, "DataValues")) {
+            const char *nodata = CPLGetXMLValue(TG, "DataValues.NoData", NULL);
+            if (nodata != NULL) m_parent_dataset->WMSSetNoDataValue(nodata);
+            const char *min = CPLGetXMLValue(TG, "DataValues.min", NULL);
+            if (min != NULL) m_parent_dataset->WMSSetMinValue(min);
+            const char *max = CPLGetXMLValue(TG, "DataValues.max", NULL);
+            if (max != NULL) m_parent_dataset->WMSSetMaxValue(max);
+        }
 
         m_parent_dataset->WMSSetBandsCount(band_count);
         m_parent_dataset->WMSSetDataType(GDALGetDataTypeByName(CPLGetXMLValue(TG, "DataType", "Byte")));
-        m_projection_wkt=CPLGetXMLValue(TG, "Projection","");
+        m_projection_wkt = CPLGetXMLValue(TG, "Projection", "");
 
-        m_base_url=CPLGetXMLValue(TG,"OnlineResource.xlink:href",global_base_url);
-        if (m_base_url[0]=='\0') {
-            CPLError(ret=CE_Failure,CPLE_AppDefined, "%s%s",SIG,
-                "Can't locate OnlineResource in the server response.");
-            break;
-        }
+        m_base_url = CPLGetXMLValue(TG, "OnlineResource.xlink:href", global_base_url);
+        if (m_base_url[0] == '\0')
+            throw CPLOPrintf("%s Can't locate OnlineResource in the server response", SIG);
 
         // Bounding box, local, global, local lat-lon, global lat-lon, in this order
         CPLXMLNode *bbox = CPLGetXMLNode(TG, "BoundingBox");
-        if (NULL==bbox) bbox=global_bbox;
-        if (NULL==bbox) bbox=CPLGetXMLNode(TG, "LatLonBoundingBox");
-        if (NULL==bbox) bbox=global_latlonbbox;
-
-        if (NULL==bbox) {
-            CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
-                "Can't locate the LatLonBoundingBox in server response.");
-            break;
-        }
+        if (NULL == bbox) bbox = global_bbox;
+        if (NULL == bbox) bbox = CPLGetXMLNode(TG, "LatLonBoundingBox");
+        if (NULL == bbox) bbox = global_latlonbbox;
 
-        m_data_window.m_x0=CPLAtof(CPLGetXMLValue(bbox,"minx","0"));
-        m_data_window.m_x1=CPLAtof(CPLGetXMLValue(bbox,"maxx","-1"));
-        m_data_window.m_y0=CPLAtof(CPLGetXMLValue(bbox,"maxy","0"));
-        m_data_window.m_y1=CPLAtof(CPLGetXMLValue(bbox,"miny","-1"));
+        if (NULL == bbox)
+            throw CPLOPrintf("%s Can't locate the LatLonBoundingBox in server response", SIG);
 
-        if ((m_data_window.m_x1-m_data_window.m_x0)<0) {
-            CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s", SIG,
-                "Coordinate order in BBox, problem in server response");
-            break;
-        }
+        m_data_window.m_x0 = CPLAtof(CPLGetXMLValue(bbox, "minx", "0"));
+        m_data_window.m_x1 = CPLAtof(CPLGetXMLValue(bbox, "maxx", "-1"));
+        m_data_window.m_y0 = CPLAtof(CPLGetXMLValue(bbox, "maxy", "0"));
+        m_data_window.m_y1 = CPLAtof(CPLGetXMLValue(bbox, "miny", "-1"));
+
+        if ((m_data_window.m_x1 - m_data_window.m_x0) < 0)
+            throw CPLOPrintf("%s Coordinate order in BBox problem in server response", SIG);
 
         // Is there a palette?
         //
@@ -476,226 +450,229 @@ CPLErr GDALWMSMiniDriver_TiledWMS::Initialize(CPLXMLNode *config)
         // RGB or RGBA are same
         //
 
-        GDALColorTable *poColorTable=NULL;
+        GDALColorTable *poColorTable = NULL;
 
-        if ((band_count==1) && CPLGetXMLNode(TG,"Palette")) {
+        if ((band_count == 1) && CPLGetXMLNode(TG, "Palette")) {
+            CPLXMLNode *node = CPLGetXMLNode(TG, "Palette");
 
-            CPLXMLNode *node=CPLGetXMLNode(TG,"Palette");
+            int entries = static_cast<int>(getXMLNum(node, "Size", "255"));
+            GDALPaletteInterp eInterp = GPI_RGB;
 
-            int entries=static_cast<int>(getXMLNum(node,"Size","255"));
-            GDALPaletteInterp eInterp=GPI_RGB;
+            CPLString pModel = CPLGetXMLValue(node, "Model", "RGB");
+            if (!pModel.empty() && pModel.find("RGB") != std::string::npos)
+                eInterp = GPI_RGB;
+            else
+                throw CPLOPrintf("%s Palette Model %s is unknown, use RGB or RGBA", SIG, pModel.c_str());
 
-            CPLString pModel=CPLGetXMLValue(node,"Model","RGB");
-            if (!pModel.empty() && pModel.find("RGB")!=std::string::npos)
-                eInterp=GPI_RGB;
-            else {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                    "%s Palette Model %s is unknown, use RGB or RGBA",
-                    SIG, pModel.c_str());
-                return CE_Failure;
-            }
+            if ((entries < 1) || (entries > 256))
+                throw CPLOPrintf("%s Palette definition error", SIG);
 
-            if ((entries>0)&&(entries<257)) {
-                int start_idx, end_idx;
-                GDALColorEntry ce_start={0,0,0,255},ce_end={0,0,0,255};
+            // Create it and initialize it to nothing
+            try {
+                int start_idx;
+                int end_idx;
+                GDALColorEntry ce_start = { 0, 0, 0, 255 };
+                GDALColorEntry ce_end = { 0, 0, 0, 255 };
 
-                // Create it and initialize it to nothing
                 poColorTable = new GDALColorTable(eInterp);
-                poColorTable->CreateColorRamp(0,&ce_start,entries-1,&ce_end);
+                poColorTable->CreateColorRamp(0, &ce_start, entries - 1, &ce_end);
                 // Read the values
-                CPLXMLNode *p=CPLGetXMLNode(node,"Entry");
+                CPLXMLNode *p = CPLGetXMLNode(node, "Entry");
                 if (p) {
                     // Initialize the first entry
-                    start_idx=static_cast<int>(getXMLNum(p,"idx","0"));
-                    ce_start=GetXMLColorEntry(p);
-                    if (start_idx<0) {
-                        CPLError(CE_Failure, CPLE_AppDefined,
-                            "%s Palette index %d not allowed",SIG,start_idx);
-                        delete poColorTable;
-                        return CE_Failure;
-                    }
-                    poColorTable->SetColorEntry(start_idx,&ce_start);
-                    while (NULL!=(p=SearchXMLSiblings(p,"Entry"))) {
+                    start_idx = static_cast<int>(getXMLNum(p, "idx", "0"));
+                    ce_start = GetXMLColorEntry(p);
+
+                    if (start_idx < 0)
+                        throw CPLOPrintf("%s Palette index %d not allowed", SIG, start_idx);
+
+                    poColorTable->SetColorEntry(start_idx, &ce_start);
+                    while (NULL != (p = SearchXMLSiblings(p, "Entry"))) {
                         // For every entry, create a ramp
-                        ce_end=GetXMLColorEntry(p);
-                        end_idx=static_cast<int>(getXMLNum(p,"idx",CPLString().FormatC(start_idx+1).c_str()));
-                        if ((end_idx<=start_idx)||(start_idx>=entries)) {
-                            CPLError(CE_Failure, CPLE_AppDefined,
-                                "%s Index Error at index %d",SIG,end_idx);
-                            delete poColorTable;
-                            return CE_Failure;
-                        }
-                        poColorTable->CreateColorRamp(start_idx,&ce_start,
-                            end_idx,&ce_end);
-                        ce_start=ce_end;
-                        start_idx=end_idx;
+                        ce_end = GetXMLColorEntry(p);
+                        end_idx = static_cast<int>(getXMLNum(p, "idx", CPLOPrintf("%d", start_idx + 1)));
+                        if ((end_idx <= start_idx) || (start_idx >= entries))
+                            throw CPLOPrintf("%s Index Error at index %d", SIG, end_idx);
+
+                        poColorTable->CreateColorRamp(start_idx, &ce_start, end_idx, &ce_end);
+                        ce_start = ce_end;
+                        start_idx = end_idx;
                     }
                 }
+
+                // Dataset has ownership
                 m_parent_dataset->SetColorTable(poColorTable);
-            } else {
-                CPLError(CE_Failure, CPLE_AppDefined,"%s Palette definition error",SIG);
-                return CE_Failure;
             }
-        }
+            catch (const CPLString &) {
+                delete poColorTable;
+                throw;
+            }
+        } // If palette
 
-        int overview_count=0;
-        CPLXMLNode *Pattern=TG->psChild;
+        int overview_count = 0;
+        CPLXMLNode *Pattern = TG->psChild;
 
-        m_bsx=m_bsy=-1;
-        m_data_window.m_sx=m_data_window.m_sy=0;
+        m_bsx = -1;
+        m_bsy = -1;
+        m_data_window.m_sx = 0;
+        m_data_window.m_sy = 0;
 
-        for (int once2=1;once2;once2--) { // Something to break out of
-            while ((NULL!=Pattern)&&(NULL!=(Pattern=SearchXMLSiblings(Pattern,"=TilePattern")))) {
-                int mbsx,mbsy;
+        while ((NULL != Pattern) && (NULL != (Pattern = SearchXMLSiblings(Pattern, "=TilePattern")))) {
+            int mbsx, mbsy, sx, sy;
+            double x, y, X, Y;
 
-                CPLString request;
-                FindChangePattern(Pattern->psChild->pszValue,substs,keys,request);
+            CPLString request;
+            FindChangePattern(Pattern->psChild->pszValue, substs, keys, request);
 
-                char **papszTokens=CSLTokenizeString2(request,"&",0);
+            char **papszTokens = CSLTokenizeString2(request, "&", 0);
 
-                const char* pszWIDTH = CSLFetchNameValue(papszTokens,"WIDTH");
-                const char* pszHEIGHT = CSLFetchNameValue(papszTokens,"HEIGHT");
+            try {
+                const char* pszWIDTH = CSLFetchNameValue(papszTokens, "WIDTH");
+                const char* pszHEIGHT = CSLFetchNameValue(papszTokens, "HEIGHT");
                 if (pszWIDTH == NULL || pszHEIGHT == NULL)
-                {
-                    CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
-                        "Cannot find width and/or height parameters.");
-                    overview_count=0;
-                    CSLDestroy(papszTokens);
-                    break;
-                }
+                    throw CPLOPrintf("%s Cannot find width or height parameters in %s", SIG, request.c_str());
 
-                mbsx=atoi(pszWIDTH);
-                mbsy=atoi(pszHEIGHT);
+                mbsx = atoi(pszWIDTH);
+                mbsy = atoi(pszHEIGHT);
                 if (m_projection_wkt.empty()) {
-                    m_projection_wkt = CSLFetchNameValueDef(papszTokens,"SRS", "");
+                    m_projection_wkt = CSLFetchNameValueDef(papszTokens, "SRS", "");
                     if (!m_projection_wkt.empty())
-                        m_projection_wkt=ProjToWKT(m_projection_wkt);
+                        m_projection_wkt = ProjToWKT(m_projection_wkt);
                 }
 
-                if (-1==m_bsx) m_bsx=mbsx;
-                if (-1==m_bsy) m_bsy=mbsy;
-                if ((m_bsx!=mbsx)||(m_bsy!=mbsy)) {
-                    CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
-                        "Tileset uses different block sizes.");
-                    overview_count=0;
-                    CSLDestroy(papszTokens);
-                    break;
-                }
+                if (-1 == m_bsx) m_bsx = mbsx;
+                if (-1 == m_bsy) m_bsy = mbsy;
+                if ((m_bsx != mbsx) || (m_bsy != mbsy))
+                    throw CPLOPrintf("%s Tileset uses different block sizes", SIG);
+
+                if (CPLsscanf(CSLFetchNameValueDef(papszTokens, "BBOX", ""), "%lf,%lf,%lf,%lf", &x, &y, &X, &Y) != 4)
+                    throw CPLOPrintf("%s Error parsing BBOX, pattern %d\n", SIG, overview_count + 1);
 
-                double x,y,X,Y;
-                if (CPLsscanf(CSLFetchNameValueDef(papszTokens,"BBOX", ""),"%lf,%lf,%lf,%lf",&x,&y,&X,&Y)!=4)
-                {
-                    CPLError(ret=CE_Failure,CPLE_AppDefined,
-                        "%s Error parsing BBOX, pattern %d\n",SIG,overview_count+1);
-                    CSLDestroy(papszTokens);
-                    break;
-                }
                 // Pick the largest size
-                int sx=static_cast<int>((m_data_window.m_x1-m_data_window.m_x0)/(X-x)*m_bsx);
-                int sy=static_cast<int>(fabs((m_data_window.m_y1-m_data_window.m_y0)/(Y-y)*m_bsy));
-                if (sx>m_data_window.m_sx) m_data_window.m_sx=sx;
-                if (sy>m_data_window.m_sy) m_data_window.m_sy=sy;
+                sx = static_cast<int>((m_data_window.m_x1 - m_data_window.m_x0) / (X - x)*m_bsx);
+                sy = static_cast<int>(fabs((m_data_window.m_y1 - m_data_window.m_y0) / (Y - y)*m_bsy));
+                if (sx > m_data_window.m_sx) m_data_window.m_sx = sx;
+                if (sy > m_data_window.m_sy) m_data_window.m_sy = sy;
+            }
+            catch (const CPLString &) {
                 CSLDestroy(papszTokens);
+                throw;
+            }
 
-                // Only use overlays where the top coordinate is within a pixel from the top of coverage
-                double pix_off,temp;
-                pix_off=m_bsy*modf(fabs((Y-m_data_window.m_y0)/(Y-y)),&temp);
-                if ((pix_off<1)||((m_bsy-pix_off)<1)) {
-                    requests=CSLAddString(requests,request);
-                    overview_count++;
-                } else
-                    CPLError(CE_Warning,CPLE_AppDefined,
-                    "%s Overlay size %dX%d can't be used due to alignment",SIG,sx,sy);
-
-                Pattern=Pattern->psNext;
+            CSLDestroy(papszTokens);
 
+            // Only use overlays where the top coordinate is within a pixel from the top of coverage
+            double pix_off, temp;
+            pix_off = m_bsy * modf(fabs((Y - m_data_window.m_y0) / (Y - y)), &temp);
+            if ((pix_off < 1) || ((m_bsy - pix_off) < 1)) {
+                requests = CSLAddString(requests, request);
+                overview_count++;
+            }
+            else
+                CPLError(CE_Warning, CPLE_AppDefined, "%s Overlay size %dX%d can't be used due to alignment", SIG, sx, sy);
+
+            Pattern = Pattern->psNext;
+        } // Search for matching TilePattern
+
+        // The tlevel is needed, the tx and ty are not used by this minidriver
+        m_data_window.m_tlevel = 0;
+        m_data_window.m_tx = 0;
+        m_data_window.m_ty = 0;
+
+        // Make sure the parent_dataset values are set before creating the bands
+        m_parent_dataset->WMSSetBlockSize(m_bsx, m_bsy);
+        m_parent_dataset->WMSSetRasterSize(m_data_window.m_sx, m_data_window.m_sy);
+
+        m_parent_dataset->WMSSetDataWindow(m_data_window);
+        //m_parent_dataset->WMSSetOverviewCount(overview_count);
+        m_parent_dataset->WMSSetClamp(false);
+
+        // Ready for the Rasterband creation
+        for (int i = 0; i < overview_count; i++) {
+            CPLString request = GetLowestScale(requests, i);
+            double scale = Scale(request);
+
+            // Base scale should be very close to 1
+            if ((0 == i) && (fabs(scale - 1) > 1e-6))
+                throw CPLOPrintf("%s Base resolution pattern missing", SIG);
+
+            // Prepare the request and insert it back into the list
+            // Find returns an answer relative to the original string start!
+            size_t startBbox = FindBbox(request);
+            size_t endBbox = request.find('&', startBbox);
+            if (endBbox == std::string::npos)
+                endBbox = request.size();
+            request.replace(startBbox, endBbox - startBbox, "${GDAL_BBOX}");
+            requests = CSLInsertString(requests, i, request);
+
+            // Create the Rasterband or overview
+            for (int j = 1; j <= band_count; j++) {
+                if (i != 0)
+                    m_parent_dataset->mGetBand(j)->AddOverview(scale);
+                else { // Base resolution
+                    GDALWMSRasterBand *band = new
+                        GDALWMSRasterBand(m_parent_dataset, j, 1);
+                    if (poColorTable != NULL) band->SetColorInterpretation(GCI_PaletteIndex);
+                    else band->SetColorInterpretation(BandInterp(band_count, j));
+                    m_parent_dataset->mSetBand(j, band);
+                }
             }
+        }
 
-            // The tlevel is needed, the tx and ty are not used by this minidriver
-            m_data_window.m_tlevel = 0;
-            m_data_window.m_tx = 0;
-            m_data_window.m_ty = 0;
+        if ((overview_count == 0) || (m_bsx < 1) || (m_bsy < 1))
+            throw CPLOPrintf("%s No usable TilePattern elements found", SIG);
 
-            // Make sure the parent_dataset values are set before creating the bands
-            m_parent_dataset->WMSSetBlockSize(m_bsx,m_bsy);
-            m_parent_dataset->WMSSetRasterSize(m_data_window.m_sx,m_data_window.m_sy);
+        // Do we need to embed the server configuration in the prototype XML
+        if (CPLGetXMLValue(config, "Configuration", NULL) == NULL) {
+            // Get the proposed XML, it will exist at this point
+            CPLXMLNode *cfg_root = CPLParseXMLString(m_parent_dataset->GetMetadataItem("XML", "WMS"));
 
-            m_parent_dataset->WMSSetDataWindow(m_data_window);
-            //m_parent_dataset->WMSSetOverviewCount(overview_count);
-            m_parent_dataset->WMSSetClamp(false);
+            if (cfg_root && CPLGetXMLNode(cfg_root, "Cache")) { // Only if there is a cache node
 
-            // Ready for the Rasterband creation
-            for (int i=0;i<overview_count;i++) {
-                CPLString request=GetLowestScale(requests,i);
-                double scale=Scale(request);
+                char *server_xml = CPLSerializeXMLTree(tileServiceConfig);
 
-                // Base scale should be very close to 1
-                if ((0==i)&&(fabs(scale-1) > 1e-6)) {
-                    CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
-                        "Base resolution pattern missing.");
-                    break;
-                }
+                int len = static_cast<int>(strlen(server_xml));
+                char *encoded_server_xml = CPLEscapeString(server_xml, len, CPLES_XML);
+                CPLFree(server_xml);
 
-                // Prepare the request and insert it back into the list
-                // Find returns an answer relative to the original string start!
-                size_t startBbox=FindBbox(request);
-                size_t endBbox=request.find('&',startBbox);
-                if (endBbox==std::string::npos) endBbox=request.size();
-                request.replace(startBbox,endBbox-startBbox,"${GDAL_BBOX}");
-                requests = CSLInsertString(requests,i,request);
-
-                // Create the Rasterband or overview
-                for (int j = 1; j <= band_count; j++) {
-                    if (i!=0)
-                        m_parent_dataset->mGetBand(j)->AddOverview(scale);
-                    else { // Base resolution
-                        GDALWMSRasterBand *band=new
-                            GDALWMSRasterBand(m_parent_dataset,j,1);
-                        if (poColorTable!=NULL) band->SetColorInterpretation(GCI_PaletteIndex);
-                        else band->SetColorInterpretation(BandInterp(band_count,j));
-                        m_parent_dataset->mSetBand(j, band);
-                    };
-                }
-            }
-            if ((overview_count==0)||(m_bsx<1)||(m_bsy<1)) {
-                CPLError(ret=CE_Failure,CPLE_AppDefined,
-                    "%s No usable TilePattern elements found",SIG);
-                break;
+                // It doesn't have a Service.Configuration element, safe to add one
+                CPLXMLNode *service_node = CPLGetXMLNode(cfg_root, "Service");
+                CPLXMLNode *scfg = CPLCreateXMLElementAndValue(service_node, "Configuration", encoded_server_xml);
+                CPLAddXMLAttributeAndValue(scfg, "encoding", "XMLencoded");
+                CPLFree(encoded_server_xml);
+
+                char * osXML = CPLSerializeXMLTree(cfg_root);
+
+                m_parent_dataset->SetXML(osXML);
+                CPLFree(osXML);
             }
+
+            CPLDestroyXMLNode(cfg_root);
         }
     }
+    catch (const CPLString &msg) {
+        ret = CE_Failure;
+        CPLError(ret, CPLE_AppDefined, "%s", msg.c_str());
+    }
 
     CSLDestroy(keys);
     CSLDestroy(substs);
     if (tileServiceConfig) CPLDestroyXMLNode(tileServiceConfig);
-    if (psResult) CPLHTTPDestroyResult(psResult);
 
-    m_requests=requests;
+    m_requests = requests;
     return ret;
 }
 
-void GDALWMSMiniDriver_TiledWMS::GetCapabilities(GDALWMSMiniDriverCapabilities *caps) {
-    caps->m_capabilities_version = 1;
-    caps->m_has_arb_overviews = 0;
-    caps->m_has_image_request = 1;
-    caps->m_has_tiled_image_requeset = 1;
-    caps->m_max_overview_count = 32;
-}
-
-
-// not called
-void GDALWMSMiniDriver_TiledWMS::ImageRequest(CPL_UNUSED CPLString *url,
-                                              CPL_UNUSED const GDALWMSImageRequestInfo &iri) {
-}
-
-void GDALWMSMiniDriver_TiledWMS::TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri) {
-    *url = m_base_url;
-    URLAppend(url,CSLGetField(m_requests,-tiri.m_level));
-    URLSearchAndReplace(url,"${GDAL_BBOX}","%013.8f,%013.8f,%013.8f,%013.8f",
-                        iri.m_x0,iri.m_y1,iri.m_x1,iri.m_y0);
-    URLAppend(url,m_end_url);
-}
-
-const char *GDALWMSMiniDriver_TiledWMS::GetProjectionInWKT() {
-    return m_projection_wkt.c_str();
+CPLErr WMSMiniDriver_TiledWMS::TiledImageRequest(
+    WMSHTTPRequest &request,
+    const GDALWMSImageRequestInfo &iri,
+    const GDALWMSTiledImageRequestInfo &tiri)
+{
+    CPLString &url = request.URL;
+    url = m_base_url;
+    URLPrepare(url);
+    url += CSLGetField(m_requests, -tiri.m_level);
+    URLSearchAndReplace(&url, "${GDAL_BBOX}", "%013.8f,%013.8f,%013.8f,%013.8f",
+        iri.m_x0, iri.m_y1, iri.m_x1, iri.m_y0);
+    return CE_None;
 }
diff --git a/frmts/wms/minidriver_tiled_wms.h b/frmts/wms/minidriver_tiled_wms.h
index 78a5c90..1c07601 100644
--- a/frmts/wms/minidriver_tiled_wms.h
+++ b/frmts/wms/minidriver_tiled_wms.h
@@ -28,28 +28,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-H_GDALWMSMiniDriverFactory(TiledWMS)
+class WMSMiniDriver_TiledWMS : public WMSMiniDriver {
 
-class GDALWMSMiniDriver_TiledWMS : public GDALWMSMiniDriver {
 public:
-    GDALWMSMiniDriver_TiledWMS();
-    virtual ~GDALWMSMiniDriver_TiledWMS();
+    WMSMiniDriver_TiledWMS();
+    virtual ~WMSMiniDriver_TiledWMS();
 
-public:
-    virtual CPLErr Initialize(CPLXMLNode *config);
-    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
-    virtual void ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
-    virtual const char *GetProjectionInWKT();
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) override;
+    virtual CPLErr TiledImageRequest(WMSHTTPRequest &request,
+                                const GDALWMSImageRequestInfo &iri,
+                                const GDALWMSTiledImageRequestInfo &tiri) override;
 
 protected:
     double Scale(const char *request);
     CPLString GetLowestScale(char **&list,int i);
     GDALWMSDataWindow m_data_window;
     char **m_requests;
-    CPLString m_base_url;
-    CPLString m_end_url;
     int m_bsx;
     int m_bsy;
-    CPLString m_projection_wkt;
 };
diff --git a/frmts/wms/minidriver_tileservice.cpp b/frmts/wms/minidriver_tileservice.cpp
index 364fcf0..903f08b 100644
--- a/frmts/wms/minidriver_tileservice.cpp
+++ b/frmts/wms/minidriver_tileservice.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: minidriver_tileservice.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -31,64 +30,39 @@
 #include "wmsdriver.h"
 #include "minidriver_tileservice.h"
 
-CPP_GDALWMSMiniDriverFactory(TileService)
+CPL_CVSID("$Id: minidriver_tileservice.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
-GDALWMSMiniDriver_TileService::GDALWMSMiniDriver_TileService() {
-}
+WMSMiniDriver_TileService::WMSMiniDriver_TileService() {}
 
-GDALWMSMiniDriver_TileService::~GDALWMSMiniDriver_TileService() {
-}
+WMSMiniDriver_TileService::~WMSMiniDriver_TileService() {}
 
-CPLErr GDALWMSMiniDriver_TileService::Initialize(CPLXMLNode *config) {
+CPLErr WMSMiniDriver_TileService::Initialize(CPLXMLNode *config, CPL_UNUSED char **papszOpenOptions) {
     CPLErr ret = CE_None;
 
-    if (ret == CE_None) {
-        const char *version = CPLGetXMLValue(config, "Version", "1");
-        if (version[0] != '\0') {
-            m_version = version;
-        }
-    }
+    // Try both spellings
+    m_base_url = CPLGetXMLValue(config, "ServerURL",
+                                CPLGetXMLValue(config, "ServerUrl", ""));
 
-    if (ret == CE_None) {
-        const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
-        if (base_url[0] != '\0') {
-            /* Try the old name */
-            base_url = CPLGetXMLValue(config, "ServerUrl", "");
-        }
-        if (base_url[0] != '\0') {
-            m_base_url = base_url;
-        } else {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, TileService mini-driver: ServerURL missing.");
-            ret = CE_Failure;
-        }
+    if (m_base_url.empty()) {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, TileService mini-driver: ServerURL missing.");
+        ret = CE_Failure;
+    }
+    else { // Prepare the url, leave it ready for extra arguments
+        URLPrepare(m_base_url);
+        const char *dataset = CPLGetXMLValue(config, "Dataset", "");
+        const char *version = CPLGetXMLValue(config, "Version", "1");
+        m_base_url += CPLOPrintf("interface=map&version=%s&dataset=%s&", version, dataset);
     }
-
-    m_dataset = CPLGetXMLValue(config, "Dataset", "");
 
     return ret;
 }
 
-void GDALWMSMiniDriver_TileService::GetCapabilities(GDALWMSMiniDriverCapabilities *caps) {
-    caps->m_capabilities_version = 1;
-    caps->m_has_arb_overviews = 0;
-    caps->m_has_image_request = 0;
-    caps->m_has_tiled_image_requeset = 1;
-    caps->m_max_overview_count = 32;
-}
-
-void GDALWMSMiniDriver_TileService::ImageRequest(CPL_UNUSED CPLString *url,
-                                                 CPL_UNUSED const GDALWMSImageRequestInfo &iri) {
-}
-
-void GDALWMSMiniDriver_TileService::TiledImageRequest(CPLString *url,
+CPLErr WMSMiniDriver_TileService::TiledImageRequest(WMSHTTPRequest &request,
                                                       CPL_UNUSED const GDALWMSImageRequestInfo &iri,
                                                       const GDALWMSTiledImageRequestInfo &tiri) {
     // http://s0.tileservice.worldwindcentral.com/getTile?interface=map&version=1&dataset=bmng.topo.bathy.200401&level=5&x=18&y=6
-    *url = m_base_url;
-    URLAppend(url, "&interface=map");
-    URLAppendF(url, "&version=%s", m_version.c_str());
-    URLAppendF(url, "&dataset=%s", m_dataset.c_str());
-    URLAppendF(url, "&level=%d", tiri.m_level);
-    URLAppendF(url, "&x=%d", tiri.m_x);
-    URLAppendF(url, "&y=%d", tiri.m_y);
+    CPLString &url = request.URL;
+    url = m_base_url;
+    url += CPLOPrintf("level=%d&x=%d&y=%d", tiri.m_level, tiri.m_x, tiri.m_y);
+    return CE_None;
 }
diff --git a/frmts/wms/minidriver_tileservice.h b/frmts/wms/minidriver_tileservice.h
index ab1744d..603b8ad 100644
--- a/frmts/wms/minidriver_tileservice.h
+++ b/frmts/wms/minidriver_tileservice.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_tileservice.h 18020 2009-11-14 14:33:20Z rouault $
+ * $Id: minidriver_tileservice.h 37463 2017-02-26 02:16:35Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,21 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-H_GDALWMSMiniDriverFactory(TileService)
-
-class GDALWMSMiniDriver_TileService : public GDALWMSMiniDriver {
+class WMSMiniDriver_TileService : public WMSMiniDriver {
 public:
-    GDALWMSMiniDriver_TileService();
-    virtual ~GDALWMSMiniDriver_TileService();
+    WMSMiniDriver_TileService();
+    virtual ~WMSMiniDriver_TileService();
 
 public:
-    virtual CPLErr Initialize(CPLXMLNode *config);
-    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
-    virtual void ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
-
-protected:
-    CPLString m_base_url;
-    CPLString m_version;
-    CPLString m_dataset;
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) override;
+    virtual CPLErr TiledImageRequest(WMSHTTPRequest &request,
+                                const GDALWMSImageRequestInfo &iri,
+                                const GDALWMSTiledImageRequestInfo &tiri) override;
 };
diff --git a/frmts/wms/minidriver_tms.cpp b/frmts/wms/minidriver_tms.cpp
index f4d7bcb..0d05a92 100644
--- a/frmts/wms/minidriver_tms.cpp
+++ b/frmts/wms/minidriver_tms.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: minidriver_tms.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -31,24 +30,21 @@
 #include "wmsdriver.h"
 #include "minidriver_tms.h"
 
+CPL_CVSID("$Id: minidriver_tms.cpp 37463 2017-02-26 02:16:35Z goatbar $");
 
-CPP_GDALWMSMiniDriverFactory(TMS)
+WMSMiniDriver_TMS::WMSMiniDriver_TMS() {}
 
-GDALWMSMiniDriver_TMS::GDALWMSMiniDriver_TMS() {
-}
-
-GDALWMSMiniDriver_TMS::~GDALWMSMiniDriver_TMS() {
-}
+WMSMiniDriver_TMS::~WMSMiniDriver_TMS() {}
 
-CPLErr GDALWMSMiniDriver_TMS::Initialize(CPLXMLNode *config) {
+CPLErr WMSMiniDriver_TMS::Initialize(CPLXMLNode *config, CPL_UNUSED char **papszOpenOptions) {
     CPLErr ret = CE_None;
 
-    if (ret == CE_None) {
+    {
         const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
         if (base_url[0] != '\0') {
             m_base_url = base_url;
             if (m_base_url.find("${") == std::string::npos) {
-                if (m_base_url[m_base_url.size()-1] != '/') {
+                if (m_base_url.back() != '/') {
                     m_base_url += "/";
                 }
                 m_base_url += "${version}/${layer}/${z}/${x}/${y}.${format}";
@@ -59,26 +55,22 @@ CPLErr GDALWMSMiniDriver_TMS::Initialize(CPLXMLNode *config) {
         }
     }
 
-    m_dataset  = CPLGetXMLValue(config, "Layer", "");
-    m_version  = CPLGetXMLValue(config, "Version", "1.0.0");
-    m_format   = CPLGetXMLValue(config, "Format", "jpg");
+    // These never change
+    const char *dataset = CPLGetXMLValue(config, "Layer", "");
+    URLSearchAndReplace(&m_base_url, "${layer}", "%s", dataset);
+    const char *version = CPLGetXMLValue(config, "Version", "1.0.0");
+    URLSearchAndReplace(&m_base_url, "${version}", "%s", version);
+    const char *format = CPLGetXMLValue(config, "Format", "jpg");
+    URLSearchAndReplace(&m_base_url, "${format}", "%s", format);
 
     return ret;
 }
 
-void GDALWMSMiniDriver_TMS::GetCapabilities(GDALWMSMiniDriverCapabilities *caps) {
-    caps->m_capabilities_version = 1;
-    caps->m_has_arb_overviews = 0;
-    caps->m_has_image_request = 0;
-    caps->m_has_tiled_image_requeset = 1;
-    caps->m_max_overview_count = 32;
-}
-
-void GDALWMSMiniDriver_TMS::ImageRequest(CPL_UNUSED CPLString *url,
-                                         CPL_UNUSED const GDALWMSImageRequestInfo &iri) {
-}
-
-void GDALWMSMiniDriver_TMS::TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri) {
+CPLErr WMSMiniDriver_TMS::TiledImageRequest(WMSHTTPRequest &request,
+                                            const GDALWMSImageRequestInfo &iri,
+                                            const GDALWMSTiledImageRequestInfo &tiri)
+{
+    CPLString &url = request.URL;
     const GDALWMSDataWindow *data_window = m_parent_dataset->WMSGetDataWindow();
     int tms_y;
 
@@ -89,18 +81,16 @@ void GDALWMSMiniDriver_TMS::TiledImageRequest(CPLString *url, const GDALWMSImage
         tms_y = tiri.m_y;
     }
     // http://tms25.arc.nasa.gov/tile/tile.aspx?T=geocover2000&L=0&X=86&Y=39
-    *url = m_base_url;
+    url = m_base_url;
 
-    URLSearchAndReplace(url, "${version}", "%s", m_version.c_str());
-    URLSearchAndReplace(url, "${layer}", "%s", m_dataset.c_str());
-    URLSearchAndReplace(url, "${format}", "%s", m_format.c_str());
-    URLSearchAndReplace(url, "${x}", "%d", tiri.m_x);
-    URLSearchAndReplace(url, "${y}", "%d", tms_y);
-    URLSearchAndReplace(url, "${z}", "%d", tiri.m_level);
+    URLSearchAndReplace(&url, "${x}", "%d", tiri.m_x);
+    URLSearchAndReplace(&url, "${y}", "%d", tms_y);
+    URLSearchAndReplace(&url, "${z}", "%d", tiri.m_level);
 
     /* Hack for some TMS like servers that require tile numbers split into 3 groups of */
     /* 3 digits, like http://tile8.geo.admin.ch/geoadmin/ch.swisstopo.pixelkarte-farbe */
-    URLSearchAndReplace(url, "${xxx}", "%03d/%03d/%03d", tiri.m_x / 1000000, (tiri.m_x / 1000) % 1000, tiri.m_x % 1000);
-    URLSearchAndReplace(url, "${yyy}", "%03d/%03d/%03d", tms_y / 1000000, (tms_y / 1000) % 1000, tms_y % 1000);
+    URLSearchAndReplace(&url, "${xxx}", "%03d/%03d/%03d", tiri.m_x / 1000000, (tiri.m_x / 1000) % 1000, tiri.m_x % 1000);
+    URLSearchAndReplace(&url, "${yyy}", "%03d/%03d/%03d", tms_y / 1000000, (tms_y / 1000) % 1000, tms_y % 1000);
 
+    return CE_None;
 }
diff --git a/frmts/wms/minidriver_tms.h b/frmts/wms/minidriver_tms.h
index fd20b2e..cf20135 100644
--- a/frmts/wms/minidriver_tms.h
+++ b/frmts/wms/minidriver_tms.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_tms.h 18589 2010-01-19 18:54:53Z warmerdam $
+ * $Id: minidriver_tms.h 37463 2017-02-26 02:16:35Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,22 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-H_GDALWMSMiniDriverFactory(TMS)
-
-class GDALWMSMiniDriver_TMS : public GDALWMSMiniDriver {
+class WMSMiniDriver_TMS : public WMSMiniDriver {
 public:
-    GDALWMSMiniDriver_TMS();
-    virtual ~GDALWMSMiniDriver_TMS();
+    WMSMiniDriver_TMS();
+    virtual ~WMSMiniDriver_TMS();
 
 public:
-    virtual CPLErr Initialize(CPLXMLNode *config);
-    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
-    virtual void ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
-
-protected:
-    CPLString m_base_url;
-    CPLString m_dataset;
-    CPLString m_version;
-    CPLString m_format;
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) override;
+    virtual CPLErr TiledImageRequest(WMSHTTPRequest &request,
+                                     const GDALWMSImageRequestInfo &iri,
+                                     const GDALWMSTiledImageRequestInfo &tiri) override;
 };
diff --git a/frmts/wms/minidriver_virtualearth.cpp b/frmts/wms/minidriver_virtualearth.cpp
index e5e4724..85851c7 100644
--- a/frmts/wms/minidriver_virtualearth.cpp
+++ b/frmts/wms/minidriver_virtualearth.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: minidriver_virtualearth.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -31,68 +30,53 @@
 #include "wmsdriver.h"
 #include "minidriver_virtualearth.h"
 
+#include <algorithm>
 
-CPP_GDALWMSMiniDriverFactory(VirtualEarth)
+CPL_CVSID("$Id: minidriver_virtualearth.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
-GDALWMSMiniDriver_VirtualEarth::GDALWMSMiniDriver_VirtualEarth()
-{
-}
+// These should be global, they are used all over the place
+const double SPHERICAL_RADIUS = 6378137.0;
+const double MAX_GM = SPHERICAL_RADIUS * M_PI;  // 20037508.342789244
 
-GDALWMSMiniDriver_VirtualEarth::~GDALWMSMiniDriver_VirtualEarth()
-{
-}
+WMSMiniDriver_VirtualEarth::WMSMiniDriver_VirtualEarth() {}
 
-CPLErr GDALWMSMiniDriver_VirtualEarth::Initialize(CPLXMLNode *config)
+WMSMiniDriver_VirtualEarth::~WMSMiniDriver_VirtualEarth() {}
+
+CPLErr WMSMiniDriver_VirtualEarth::Initialize(CPLXMLNode *config, CPL_UNUSED char **papszOpenOptions)
 {
-    CPLErr ret = CE_None;
+    m_base_url = CPLGetXMLValue(config, "ServerURL", "");
+    if (m_base_url.empty()) {
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "GDALWMS, VirtualEarth mini-driver: ServerURL missing.");
+        return CE_Failure;
+    }
 
-    if (ret == CE_None) {
-        const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
-        if (base_url[0] != '\0') {
-            m_base_url = base_url;
-            if (m_base_url.find("${quadkey}") == std::string::npos) {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "GDALWMS, VirtualEarth mini-driver: ${quadkey} missing in ServerURL.");
-                ret = CE_Failure;
-            }
-        } else {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "GDALWMS, VirtualEarth mini-driver: ServerURL missing.");
-            ret = CE_Failure;
-        }
+    if (m_base_url.find("${quadkey}") == std::string::npos) {
+        CPLError(CE_Failure, CPLE_AppDefined,
+            "GDALWMS, VirtualEarth mini-driver: ${quadkey} missing in ServerURL.");
+        return CE_Failure;
     }
 
     m_parent_dataset->WMSSetDefaultBlockSize(256, 256);
-    m_parent_dataset->WMSSetDefaultDataWindowCoordinates(-20037508.34,20037508.34,20037508.34,-20037508.34);
+    m_parent_dataset->WMSSetDefaultDataWindowCoordinates(-MAX_GM, MAX_GM, MAX_GM, -MAX_GM);
     m_parent_dataset->WMSSetDefaultTileLevel(19);
     m_parent_dataset->WMSSetDefaultOverviewCount(18);
     m_parent_dataset->WMSSetNeedsDataWindow(FALSE);
-
-    m_projection_wkt=ProjToWKT("EPSG:900913");
-
-    return ret;
-}
-
-void GDALWMSMiniDriver_VirtualEarth::GetCapabilities(GDALWMSMiniDriverCapabilities *caps)
-{
-    caps->m_capabilities_version = 1;
-    caps->m_has_arb_overviews = 0;
-    caps->m_has_image_request = 0;
-    caps->m_has_tiled_image_requeset = 1;
-    caps->m_max_overview_count = 32;
+    m_projection_wkt = ProjToWKT("EPSG:900913");
+    return CE_None;
 }
 
-void GDALWMSMiniDriver_VirtualEarth::TiledImageRequest(CPLString *url,
-                                                       CPL_UNUSED const GDALWMSImageRequestInfo &iri,
-                                                       const GDALWMSTiledImageRequestInfo &tiri)
+CPLErr WMSMiniDriver_VirtualEarth::TiledImageRequest(WMSHTTPRequest &request,
+                                                CPL_UNUSED const GDALWMSImageRequestInfo &iri,
+                                                const GDALWMSTiledImageRequestInfo &tiri)
 {
-
-    *url = m_base_url;
+    CPLString &url = request.URL;
+    url = m_base_url;
 
     char szTileNumber[64];
     int x = tiri.m_x;
     int y = tiri.m_y;
-    int z = MIN(32,tiri.m_level);
+    int z = std::min(32, tiri.m_level);
 
     for(int i = 0; i < z; i ++)
     {
@@ -106,11 +90,8 @@ void GDALWMSMiniDriver_VirtualEarth::TiledImageRequest(CPLString *url,
     }
     szTileNumber[z] = 0;
 
-    URLSearchAndReplace(url, "${quadkey}", "%s", szTileNumber);
-    URLSearchAndReplace(url, "${server_num}", "%d",
-                        (tiri.m_x + tiri.m_y + z) % 4);
-}
-
-const char *GDALWMSMiniDriver_VirtualEarth::GetProjectionInWKT() {
-    return m_projection_wkt.c_str();
+    URLSearchAndReplace(&url, "${quadkey}", "%s", szTileNumber);
+    // Sounds like this should be random
+    URLSearchAndReplace(&url, "${server_num}", "%d", (tiri.m_x + tiri.m_y + z) % 4);
+    return CE_None;
 }
diff --git a/frmts/wms/minidriver_virtualearth.h b/frmts/wms/minidriver_virtualearth.h
index 208ded1..5aab965 100644
--- a/frmts/wms/minidriver_virtualearth.h
+++ b/frmts/wms/minidriver_virtualearth.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_virtualearth.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: minidriver_virtualearth.h 36611 2016-12-01 23:13:38Z lplesea $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,20 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-H_GDALWMSMiniDriverFactory(VirtualEarth)
-
-class GDALWMSMiniDriver_VirtualEarth : public GDALWMSMiniDriver {
+class WMSMiniDriver_VirtualEarth : public WMSMiniDriver {
 public:
-    GDALWMSMiniDriver_VirtualEarth();
-    virtual ~GDALWMSMiniDriver_VirtualEarth();
+    WMSMiniDriver_VirtualEarth();
+    virtual ~WMSMiniDriver_VirtualEarth();
 
 public:
-    virtual CPLErr Initialize(CPLXMLNode *config);
-    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
-    virtual const char* GetProjectionInWKT();
-
-protected:
-    CPLString m_base_url;
-    CPLString m_projection_wkt;
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) override;
+    virtual CPLErr TiledImageRequest(WMSHTTPRequest &request,
+                                        const GDALWMSImageRequestInfo &iri,
+                                        const GDALWMSTiledImageRequestInfo &tiri) override;
 };
diff --git a/frmts/wms/minidriver_wms.cpp b/frmts/wms/minidriver_wms.cpp
index 656a21f..cf43950 100644
--- a/frmts/wms/minidriver_wms.cpp
+++ b/frmts/wms/minidriver_wms.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: minidriver_wms.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -32,18 +31,28 @@
 #include "wmsdriver.h"
 #include "minidriver_wms.h"
 
-CPP_GDALWMSMiniDriverFactory(WMS)
+#include <algorithm>
 
-GDALWMSMiniDriver_WMS::GDALWMSMiniDriver_WMS() : m_iversion(0) {
-}
+CPL_CVSID("$Id: minidriver_wms.cpp 37463 2017-02-26 02:16:35Z goatbar $");
+
+WMSMiniDriver_WMS::WMSMiniDriver_WMS() : m_iversion(0) {}
+
+WMSMiniDriver_WMS::~WMSMiniDriver_WMS() {}
 
-GDALWMSMiniDriver_WMS::~GDALWMSMiniDriver_WMS() {
+static double GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what) {
+    switch (what) {
+    case 'x': return std::min(iri.m_x0, iri.m_x1);
+    case 'y': return std::min(iri.m_y0, iri.m_y1);
+    case 'X': return std::max(iri.m_x0, iri.m_x1);
+    case 'Y': return std::max(iri.m_y0, iri.m_y1);
+    }
+    return 0.0;
 }
 
-CPLErr GDALWMSMiniDriver_WMS::Initialize(CPLXMLNode *config) {
+CPLErr WMSMiniDriver_WMS::Initialize(CPLXMLNode *config, CPL_UNUSED char **papszOpenOptions) {
     CPLErr ret = CE_None;
 
-    if (ret == CE_None) {
+    {
         const char *version = CPLGetXMLValue(config, "Version", "1.1.0");
         if (version[0] != '\0') {
             m_version = version;
@@ -101,15 +110,16 @@ CPLErr GDALWMSMiniDriver_WMS::Initialize(CPLXMLNode *config) {
     }
 
     if (ret == CE_None) {
-        if (m_srs.size()) {
+        if (!m_srs.empty() ) {
             m_projection_wkt = ProjToWKT(m_srs);
-        } else if (m_crs.size()) {
+        } else if (!m_crs.empty() ) {
             m_projection_wkt = ProjToWKT(m_crs);
         }
     }
 
     if (ret == CE_None) {
         m_image_format = CPLGetXMLValue(config, "ImageFormat", "image/jpeg");
+        m_info_format = CPLGetConfigOption("WMS_INFO_FORMAT", "application/vnd.ogc.gml");
         m_layers = CPLGetXMLValue(config, "Layers", "");
         m_styles = CPLGetXMLValue(config, "Styles", "");
         m_transparent = CPLGetXMLValue(config, "Transparent","");
@@ -142,73 +152,64 @@ CPLErr GDALWMSMiniDriver_WMS::Initialize(CPLXMLNode *config) {
     return ret;
 }
 
-void GDALWMSMiniDriver_WMS::GetCapabilities(GDALWMSMiniDriverCapabilities *caps) {
-    caps->m_capabilities_version = 1;
-    caps->m_has_arb_overviews = 1;
-    caps->m_has_image_request = 1;
-    caps->m_has_tiled_image_requeset = 1;
-    caps->m_max_overview_count = 32;
+void WMSMiniDriver_WMS::GetCapabilities(WMSMiniDriverCapabilities *caps) {
+    caps->m_has_getinfo = 1;
 }
 
-void GDALWMSMiniDriver_WMS::BuildURL(CPLString *url, const GDALWMSImageRequestInfo &iri, const char* pszRequest) {
+void WMSMiniDriver_WMS::BuildURL(CPLString &url,
+                                    const GDALWMSImageRequestInfo &iri,
+                                    const char* pszRequest)
+{
     // http://onearth.jpl.nasa.gov/wms.cgi?request=GetMap&width=1000&height=500&layers=modis,global_mosaic&styles=&srs=EPSG:4326&format=image/jpeg&bbox=-180.000000,-90.000000,180.000000,090.000000
-    *url = m_base_url;
-    if (m_base_url.ifind( "service=") == std::string::npos)
-        URLAppend(url, "&service=WMS");
-    URLAppendF(url, "&request=%s", pszRequest);
-    URLAppendF(url, "&version=%s", m_version.c_str());
-    URLAppendF(url, "&layers=%s", m_layers.c_str());
-    URLAppendF(url, "&styles=%s", m_styles.c_str());
-    if (m_srs.size()) URLAppendF(url, "&srs=%s", m_srs.c_str());
-    if (m_crs.size()) URLAppendF(url, "&crs=%s", m_crs.c_str());
-    if (m_transparent.size()) URLAppendF(url, "&transparent=%s", m_transparent.c_str());
-    URLAppendF(url, "&format=%s", m_image_format.c_str());
-    URLAppendF(url, "&width=%d", iri.m_sx);
-    URLAppendF(url, "&height=%d", iri.m_sy);
-    URLAppendF(url, "&bbox=%.8f,%.8f,%.8f,%.8f",
-        GetBBoxCoord(iri, m_bbox_order[0]), GetBBoxCoord(iri, m_bbox_order[1]),
-        GetBBoxCoord(iri, m_bbox_order[2]), GetBBoxCoord(iri, m_bbox_order[3]));
-}
+    url = m_base_url;
+
+    URLPrepare(url);
+    url += "request=";
+    url += pszRequest;
+
+    if (url.ifind( "service=") == std::string::npos)
+        url += "&service=WMS";
+
+    url += CPLOPrintf("&version=%s&layers=%s&styles=%s&format=%s&width=%d&height=%d&bbox=%.8f,%.8f,%.8f,%.8f",
+                        m_version.c_str(),
+                        m_layers.c_str(),
+                        m_styles.c_str(),
+                        m_image_format.c_str(),
+                        iri.m_sx,
+                        iri.m_sy,
+                        GetBBoxCoord(iri, m_bbox_order[0]),
+                        GetBBoxCoord(iri, m_bbox_order[1]),
+                        GetBBoxCoord(iri, m_bbox_order[2]),
+                        GetBBoxCoord(iri, m_bbox_order[3]));
+
+    if (!m_srs.empty())
+        url += CPLOPrintf("&srs=%s", m_srs.c_str());
+    if (!m_crs.empty())
+        url += CPLOPrintf("&crs=%s", m_crs.c_str());
+    if (!m_transparent.empty())
+        url += CPLOPrintf("&transparent=%s", m_transparent.c_str());
 
-void GDALWMSMiniDriver_WMS::ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri) {
-    BuildURL(url, iri, "GetMap");
-    CPLDebug("WMS", "URL = %s", url->c_str());
 }
 
-void GDALWMSMiniDriver_WMS::TiledImageRequest(CPLString *url,
+CPLErr WMSMiniDriver_WMS::TiledImageRequest(WMSHTTPRequest &request,
                                               const GDALWMSImageRequestInfo &iri,
-                                              CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri) {
-    ImageRequest(url, iri);
+                                              CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri)
+{
+    CPLString &url = request.URL;
+    BuildURL(url, iri, "GetMap");
+    return CE_None;
 }
 
-
-void GDALWMSMiniDriver_WMS::GetTiledImageInfo(CPLString *url,
+void WMSMiniDriver_WMS::GetTiledImageInfo(CPLString &url,
                                               const GDALWMSImageRequestInfo &iri,
                                               CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri,
                                               int nXInBlock,
                                               int nYInBlock)
 {
     BuildURL(url, iri, "GetFeatureInfo");
-    URLAppendF(url, "&query_layers=%s", m_layers.c_str());
-    URLAppendF(url, "&x=%d", nXInBlock);
-    URLAppendF(url, "&y=%d", nYInBlock);
-    const char* pszInfoFormat = CPLGetConfigOption("WMS_INFO_FORMAT", "application/vnd.ogc.gml");
-    URLAppendF(url, "&info_format=%s", pszInfoFormat);
-
-    CPLDebug("WMS", "URL = %s", url->c_str());
-}
-
-
-const char *GDALWMSMiniDriver_WMS::GetProjectionInWKT() {
-    return m_projection_wkt.c_str();
-}
-
-double GDALWMSMiniDriver_WMS::GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what) {
-    switch (what) {
-        case 'x': return MIN(iri.m_x0, iri.m_x1);
-        case 'y': return MIN(iri.m_y0, iri.m_y1);
-        case 'X': return MAX(iri.m_x0, iri.m_x1);
-        case 'Y': return MAX(iri.m_y0, iri.m_y1);
-    }
-    return 0.0;
+    url += CPLOPrintf("&query_layers=%s&x=%d&y=%d&info_format=%s",
+                        m_layers.c_str(),
+                        nXInBlock,
+                        nYInBlock,
+                        m_info_format.c_str());
 }
diff --git a/frmts/wms/minidriver_wms.h b/frmts/wms/minidriver_wms.h
index 90dc92b..9dff478 100644
--- a/frmts/wms/minidriver_wms.h
+++ b/frmts/wms/minidriver_wms.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_wms.h 23722 2012-01-07 22:15:29Z rouault $
+ * $Id: minidriver_wms.h 37463 2017-02-26 02:16:35Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,33 +28,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-H_GDALWMSMiniDriverFactory(WMS)
-
-class GDALWMSMiniDriver_WMS : public GDALWMSMiniDriver {
-
-    void    BuildURL(CPLString *url, const GDALWMSImageRequestInfo &iri, const char* pszRequest);
+/*
+ * Base class for a WMS minidriver.
+ * At least Initialize() and one of the ImageRequest() or TiledImageRequest() has to be provided
+ * All minidrivers are instantiated in wmsdriver.cpp, in GDALRegister_WMS()
+ */
 
+class WMSMiniDriver_WMS : public WMSMiniDriver {
 public:
-    GDALWMSMiniDriver_WMS();
-    virtual ~GDALWMSMiniDriver_WMS();
+    WMSMiniDriver_WMS();
+    virtual ~WMSMiniDriver_WMS();
 
 public:
-    virtual CPLErr Initialize(CPLXMLNode *config);
-    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
-    virtual void ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
-    virtual void GetTiledImageInfo(CPLString *url,
-                                              const GDALWMSImageRequestInfo &iri,
-                                              const GDALWMSTiledImageRequestInfo &tiri,
-                                              int nXInBlock,
-                                              int nYInBlock);
-    virtual const char *GetProjectionInWKT();
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) override;
+    virtual void GetCapabilities(WMSMiniDriverCapabilities *caps) override;
+
+    // Return error message in request.Error
+    virtual CPLErr TiledImageRequest(WMSHTTPRequest &request,
+                                        const GDALWMSImageRequestInfo &iri,
+                                        const GDALWMSTiledImageRequestInfo &tiri) override;
+
+    virtual void GetTiledImageInfo(CPLString &url,
+                                        const GDALWMSImageRequestInfo &iri,
+                                        const GDALWMSTiledImageRequestInfo &tiri,
+                                        int nXInBlock,
+                                        int nYInBlock) override;
 
 protected:
-    double GetBBoxCoord(const GDALWMSImageRequestInfo &iri, char what);
+    void   BuildURL(CPLString &url, const GDALWMSImageRequestInfo &iri, const char* pszRequest);
 
 protected:
-    CPLString m_base_url;
     CPLString m_version;
     int m_iversion;
     CPLString m_layers;
@@ -62,7 +65,7 @@ protected:
     CPLString m_srs;
     CPLString m_crs;
     CPLString m_image_format;
-    CPLString m_projection_wkt;
+    CPLString m_info_format;
     CPLString m_bbox_order;
     CPLString m_transparent;
 };
diff --git a/frmts/wms/minidriver_worldwind.cpp b/frmts/wms/minidriver_worldwind.cpp
index ead4822..eaadd7f 100644
--- a/frmts/wms/minidriver_worldwind.cpp
+++ b/frmts/wms/minidriver_worldwind.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: minidriver_worldwind.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -31,60 +30,41 @@
 #include "wmsdriver.h"
 #include "minidriver_worldwind.h"
 
-CPP_GDALWMSMiniDriverFactory(WorldWind)
+CPL_CVSID("$Id: minidriver_worldwind.cpp 37463 2017-02-26 02:16:35Z goatbar $");
 
-GDALWMSMiniDriver_WorldWind::GDALWMSMiniDriver_WorldWind() {
-}
+WMSMiniDriver_WorldWind::WMSMiniDriver_WorldWind() {}
 
-GDALWMSMiniDriver_WorldWind::~GDALWMSMiniDriver_WorldWind() {
-}
+WMSMiniDriver_WorldWind::~WMSMiniDriver_WorldWind() {}
 
-CPLErr GDALWMSMiniDriver_WorldWind::Initialize(CPLXMLNode *config) {
+CPLErr WMSMiniDriver_WorldWind::Initialize(CPLXMLNode *config, CPL_UNUSED char **papszOpenOptions) {
     CPLErr ret = CE_None;
 
-    if (ret == CE_None) {
-        const char *base_url = CPLGetXMLValue(config, "ServerURL", "");
-        if (base_url[0] != '\0') {
-            /* Try the old name */
-            base_url = CPLGetXMLValue(config, "ServerUrl", "");
-        }
-        if (base_url[0] != '\0') {
-            m_base_url = base_url;
-        } else {
-            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, WorldWind mini-driver: ServerURL missing.");
-            ret = CE_Failure;
-        }
+    // Try both spellings
+    m_base_url = CPLGetXMLValue(config, "ServerURL",
+        CPLGetXMLValue(config, "ServerUrl", ""));
+
+    if (m_base_url.empty()) {
+        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS, TileService mini-driver: ServerURL missing.");
+        ret = CE_Failure;
+    }
+    else { // Prepare the url, leave it ready for extra arguments
+        const char *dataset = CPLGetXMLValue(config, "Layer", "");
+        URLPrepare(m_base_url);
+        m_base_url += CPLOPrintf("T=%s", dataset);
     }
 
-    m_dataset = CPLGetXMLValue(config, "Layer", "");
     m_projection_wkt = ProjToWKT("EPSG:4326");
-
     return ret;
 }
 
-void GDALWMSMiniDriver_WorldWind::GetCapabilities(GDALWMSMiniDriverCapabilities *caps) {
-    caps->m_capabilities_version = 1;
-    caps->m_has_arb_overviews = 0;
-    caps->m_has_image_request = 0;
-    caps->m_has_tiled_image_requeset = 1;
-    caps->m_max_overview_count = 32;
-}
-
-void GDALWMSMiniDriver_WorldWind::ImageRequest(CPL_UNUSED CPLString *url,
-                                               CPL_UNUSED const GDALWMSImageRequestInfo &iri) {
-}
-
-void GDALWMSMiniDriver_WorldWind::TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri) {
+CPLErr WMSMiniDriver_WorldWind::TiledImageRequest(WMSHTTPRequest &request,
+                                                    const GDALWMSImageRequestInfo &iri,
+                                                    const GDALWMSTiledImageRequestInfo &tiri)
+{
+    CPLString &url = request.URL;
     const GDALWMSDataWindow *data_window = m_parent_dataset->WMSGetDataWindow();
     int worldwind_y = static_cast<int>(floor(((data_window->m_y1 - data_window->m_y0) / (iri.m_y1 - iri.m_y0)) + 0.5)) - tiri.m_y - 1;
     // http://worldwind25.arc.nasa.gov/tile/tile.aspx?T=geocover2000&L=0&X=86&Y=39
-    *url = m_base_url;
-    URLAppendF(url, "&T=%s", m_dataset.c_str());
-    URLAppendF(url, "&L=%d", tiri.m_level);
-    URLAppendF(url, "&X=%d", tiri.m_x);
-    URLAppendF(url, "&Y=%d", worldwind_y);
-}
-
-const char *GDALWMSMiniDriver_WorldWind::GetProjectionInWKT() {
-    return m_projection_wkt.c_str();
+    url = m_base_url + CPLOPrintf("L=%d&X=%d&Y=%d", tiri.m_level, tiri.m_x, worldwind_y);
+    return CE_None;
 }
diff --git a/frmts/wms/minidriver_worldwind.h b/frmts/wms/minidriver_worldwind.h
index 812f547..4ffc681 100644
--- a/frmts/wms/minidriver_worldwind.h
+++ b/frmts/wms/minidriver_worldwind.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: minidriver_worldwind.h 18020 2009-11-14 14:33:20Z rouault $
+ * $Id: minidriver_worldwind.h 37463 2017-02-26 02:16:35Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -28,22 +28,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-H_GDALWMSMiniDriverFactory(WorldWind)
-
-class GDALWMSMiniDriver_WorldWind : public GDALWMSMiniDriver {
+class WMSMiniDriver_WorldWind : public WMSMiniDriver {
 public:
-    GDALWMSMiniDriver_WorldWind();
-    virtual ~GDALWMSMiniDriver_WorldWind();
+    WMSMiniDriver_WorldWind();
+    virtual ~WMSMiniDriver_WorldWind();
 
 public:
-    virtual CPLErr Initialize(CPLXMLNode *config);
-    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
-    virtual void ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
-    virtual const char *GetProjectionInWKT();
-
-protected:
-    CPLString m_base_url;
-    CPLString m_dataset;
-    CPLString m_projection_wkt;
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) override;
+    virtual CPLErr TiledImageRequest(WMSHTTPRequest &request,
+                                     const GDALWMSImageRequestInfo &iri,
+                                     const GDALWMSTiledImageRequestInfo &tiri) override;
 };
diff --git a/frmts/wms/wmsdriver.cpp b/frmts/wms/wmsdriver.cpp
index e5a67a9..1ac97c9 100644
--- a/frmts/wms/wmsdriver.cpp
+++ b/frmts/wms/wmsdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: wmsdriver.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -41,8 +40,20 @@
 #include "minidriver_virtualearth.h"
 #include "minidriver_arcgis_server.h"
 #include "minidriver_iip.h"
+#include "minidriver_mrf.h"
 
 #include <limits>
+#include <utility>
+
+CPL_CVSID("$Id: wmsdriver.cpp 37949 2017-04-10 20:53:07Z lplesea $");
+
+//
+// A static map holding seen server GetTileService responses, per process
+// It makes opening and reopening rasters from the same server faster
+//
+GDALWMSDataset::StringMap_t GDALWMSDataset::cfg;
+CPLMutex *GDALWMSDataset::cfgmtx = NULL;
+
 
 /************************************************************************/
 /*              GDALWMSDatasetGetConfigFromURL()                        */
@@ -89,17 +100,17 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
     osBaseURL = CPLURLAddKVP(osBaseURL, "MINRESOLUTION", NULL);
     osBaseURL = CPLURLAddKVP(osBaseURL, "BBOXORDER", NULL);
 
-    if (osBaseURL.size() > 0 && osBaseURL[osBaseURL.size() - 1] == '&')
+    if (!osBaseURL.empty() && osBaseURL.back() == '&')
         osBaseURL.resize(osBaseURL.size() - 1);
 
-    if (osVersion.size() == 0)
+    if (osVersion.empty())
         osVersion = "1.1.1";
 
     CPLString osSRSTag;
     CPLString osSRSValue;
     if(VersionStringToInt(osVersion.c_str())>= VersionStringToInt("1.3.0"))
     {
-        if (osSRS.size())
+        if (!osSRS.empty() )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
                      "WMS version 1.3 and above expects CRS however SRS was set instead.");
@@ -109,7 +120,7 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
     }
     else
     {
-        if (osCRS.size())
+        if (!osCRS.empty() )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
                      "WMS version 1.1.1 and below expects SRS however CRS was set instead.");
@@ -118,10 +129,10 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
         osSRSTag = "SRS";
     }
 
-    if (osSRSValue.size() == 0)
+    if (osSRSValue.empty())
         osSRSValue = "EPSG:4326";
 
-    if (osBBOX.size() == 0)
+    if (osBBOX.empty())
     {
         if (osBBOXOrder.compare("yxYX") == 0)
             osBBOX = "-90,-180,90,180";
@@ -166,7 +177,7 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
 
     int nOverviewCount = (osOverviewCount.size()) ? atoi(osOverviewCount) : 20;
 
-    if (osMinResolution.size() != 0)
+    if (!osMinResolution.empty())
     {
         double dfMinResolution = CPLAtofM(osMinResolution);
 
@@ -221,9 +232,9 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromURL(GDALOpenInfo *poOpenInfo)
     nXSize = (int) dXSize;
     nYSize = (int) dYSize;
 
-    bool bTransparent = osTransparent.size() != 0 && CPLTestBool(osTransparent);
+    bool bTransparent = !osTransparent.empty() && CPLTestBool(osTransparent);
 
-    if (osFormat.size() == 0)
+    if (osFormat.empty())
     {
         if (!bTransparent)
         {
@@ -401,7 +412,7 @@ CPLXMLNode * GDALWMSDatasetGetConfigFromTileMap(CPLXMLNode* psXML)
         }
     }
 
-    if (nLevelCount == 0 || osURL.size() == 0)
+    if (nLevelCount == 0 || osURL.empty())
         return NULL;
 
     int nXSize = 0;
@@ -488,12 +499,15 @@ static CPLXMLNode* GDALWMSDatasetGetConfigFromArcGISJSON(const char* pszURL,
                                          strlen(pszContent),
                                          FALSE);
     const char* pszLine;
-    int nTileWidth = -1, nTileHeight = -1;
+    int nTileWidth = -1;
+    int nTileHeight = -1;
     int nWKID = -1;
-    double dfMinX = 0, dfMaxY = 0;
-    int bHasMinX = FALSE, bHasMaxY = FALSE;
+    double dfMinX = 0.0;
+    double dfMaxY = 0.0;
+    int bHasMinX = FALSE;
+    int bHasMaxY = FALSE;
     int nExpectedLevel = 0;
-    double dfBaseResolution = 0;
+    double dfBaseResolution = 0.0;
     while((pszLine = CPLReadLine2L(fp, 4096, NULL)) != NULL)
     {
         const char* pszVal;
@@ -772,7 +786,7 @@ GDALDataset *GDALWMSDataset::Open(GDALOpenInfo *poOpenInfo)
     {
         CPLString osLayers = CPLURLGetValue(pszFilename, "LAYERS");
         CPLString osRequest = CPLURLGetValue(pszFilename, "REQUEST");
-        if (osLayers.size() != 0)
+        if (!osLayers.empty())
             config = GDALWMSDatasetGetConfigFromURL(poOpenInfo);
         else if (EQUAL(osRequest, "GetTileService"))
             return GDALWMSMetaDataset::DownloadGetTileService(poOpenInfo);
@@ -847,7 +861,7 @@ GDALDataset *GDALWMSDataset::Open(GDALOpenInfo *poOpenInfo)
     else if (poOpenInfo->nHeaderBytes == 0 &&
               STARTS_WITH_CI(pszFilename, "AGS:"))
     {
-		return NULL;
+        return NULL;
     }
     else if (poOpenInfo->nHeaderBytes == 0 &&
               STARTS_WITH_CI(pszFilename, "IIP:"))
@@ -910,7 +924,7 @@ GDALDataset *GDALWMSDataset::Open(GDALOpenInfo *poOpenInfo)
     }
 
     GDALWMSDataset *ds = new GDALWMSDataset();
-    ret = ds->Initialize(config);
+    ret = ds->Initialize(config, poOpenInfo->papszOpenOptions);
     if (ret != CE_None) {
         delete ds;
         ds = NULL;
@@ -929,6 +943,49 @@ GDALDataset *GDALWMSDataset::Open(GDALOpenInfo *poOpenInfo)
 
     return ds;
 }
+
+/************************************************************************/
+/*                             GetServerConfig()                        */
+/************************************************************************/
+
+const char *GDALWMSDataset::GetServerConfig(const char *URI, char **papszHTTPOptions)
+{
+    CPLMutexHolder oHolder(&cfgmtx);
+
+    // Might have it cached already
+    if (cfg.end() != cfg.find(URI))
+        return cfg.find(URI)->second;
+
+    CPLHTTPResult *psResult = CPLHTTPFetch(URI, papszHTTPOptions);
+
+    if (NULL == psResult)
+        return NULL;
+
+    // Capture the result in buffer, get rid of http result
+    if ((psResult->nStatus == 0) && (NULL != psResult->pabyData) && ('\0' != psResult->pabyData[0]))
+        cfg.insert(make_pair(URI, static_cast<CPLString>(reinterpret_cast<const char *>(psResult->pabyData))));
+
+    CPLHTTPDestroyResult(psResult);
+
+    if (cfg.end() != cfg.find(URI))
+        return cfg.find(URI)->second;
+    else
+        return NULL;
+}
+
+// Empties the server configuration cache and removes the mutex
+void GDALWMSDataset::ClearConfigCache() {
+    // Obviously not thread safe, should only be called when no WMS files are being opened
+    cfg.clear();
+    DestroyCfgMutex();
+}
+
+void GDALWMSDataset::DestroyCfgMutex() {
+    if (cfgmtx)
+        CPLDestroyMutex(cfgmtx);
+    cfgmtx = NULL;
+}
+
 /************************************************************************/
 /*                             CreateCopy()                             */
 /************************************************************************/
@@ -967,16 +1024,20 @@ GDALDataset *GDALWMSDataset::CreateCopy( const char * pszFilename,
     return Open(&oOpenInfo);
 }
 
-/************************************************************************/
-/*                         GDALDeregister_WMS()                         */
-/************************************************************************/
-
-static void GDALDeregister_WMS( GDALDriver * )
-
-{
-    DestroyWMSMiniDriverManager();
+void WMSDeregister(CPL_UNUSED GDALDriver *d) {
+    GDALWMSDataset::DestroyCfgMutex();
 }
 
+// Define a minidriver factory type, create one and register it
+#define RegisterMinidriver(name) \
+    class WMSMiniDriverFactory_##name : public WMSMiniDriverFactory { \
+    public: \
+        WMSMiniDriverFactory_##name() { m_name = CPLString(#name); };\
+        virtual ~WMSMiniDriverFactory_##name() {};\
+        virtual WMSMiniDriver* New() const override { return new WMSMiniDriver_##name;}; \
+    }; \
+    WMSRegisterMiniDriverFactory(new WMSMiniDriverFactory_##name());
+
 /************************************************************************/
 /*                          GDALRegister_WMS()                          */
 /************************************************************************/
@@ -987,6 +1048,17 @@ void GDALRegister_WMS()
     if( GDALGetDriverByName( "WMS" ) != NULL )
         return;
 
+    // Register all minidrivers here
+    RegisterMinidriver(WMS);
+    RegisterMinidriver(TileService);
+    RegisterMinidriver(WorldWind);
+    RegisterMinidriver(TMS);
+    RegisterMinidriver(TiledWMS);
+    RegisterMinidriver(VirtualEarth);
+    RegisterMinidriver(AGS);
+    RegisterMinidriver(IIP);
+    RegisterMinidriver(MRF);
+
     GDALDriver *poDriver = new GDALDriver();
 
     poDriver->SetDescription("WMS");
@@ -998,18 +1070,8 @@ void GDALRegister_WMS()
 
     poDriver->pfnOpen = GDALWMSDataset::Open;
     poDriver->pfnIdentify = GDALWMSDataset::Identify;
-    poDriver->pfnUnloadDriver = GDALDeregister_WMS;
+    poDriver->pfnUnloadDriver = WMSDeregister;
     poDriver->pfnCreateCopy = GDALWMSDataset::CreateCopy;
 
     GetGDALDriverManager()->RegisterDriver(poDriver);
-
-    GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
-    mdm->Register(new GDALWMSMiniDriverFactory_WMS());
-    mdm->Register(new GDALWMSMiniDriverFactory_TileService());
-    mdm->Register(new GDALWMSMiniDriverFactory_WorldWind());
-    mdm->Register(new GDALWMSMiniDriverFactory_TMS());
-    mdm->Register(new GDALWMSMiniDriverFactory_TiledWMS());
-    mdm->Register(new GDALWMSMiniDriverFactory_VirtualEarth());
-    mdm->Register(new GDALWMSMiniDriverFactory_AGS());
-    mdm->Register(new GDALWMSMiniDriverFactory_IIP());
 }
diff --git a/frmts/wms/wmsdriver.h b/frmts/wms/wmsdriver.h
index e4e2cdc..3cffd6e 100644
--- a/frmts/wms/wmsdriver.h
+++ b/frmts/wms/wmsdriver.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsdriver.h 33717 2016-03-14 06:29:14Z goatbar $
+ * $Id: wmsdriver.h 37949 2017-04-10 20:53:07Z lplesea $
  *
  * Project:  WMS Client Driver
  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
@@ -32,15 +32,16 @@
 #ifndef WMSDRIVER_H_INCLUDED
 #define WMSDRIVER_H_INCLUDED
 
-#include <math.h>
+#include <cmath>
 #include <vector>
-#include <list>
+#include <set>
 #include <algorithm>
+#include <map>
+#include <utility>
 #include <curl/curl.h>
 
 #include "cpl_conv.h"
 #include "cpl_http.h"
-#include "cpl_multiproc.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 #include "gdalwarper.h"
@@ -57,19 +58,24 @@ class GDALWMSRasterBand;
 /* -------------------------------------------------------------------- */
 CPLString MD5String(const char *s);
 CPLString ProjToWKT(const CPLString &proj);
-void URLAppend(CPLString *url, const char *s);
-void URLAppendF(CPLString *url, const char *s, ...) CPL_PRINT_FUNC_FORMAT (2, 3);
-void URLAppend(CPLString *url, const CPLString &s);
-CPLString BufferToVSIFile(GByte *buffer, size_t size);
-CPLErr MakeDirs(const char *path);
 
+// Decode s from encoding "base64" or "XMLencoded".
+// If encoding is "file", s is the file name on input and file content on output
+// If encoding is not recognized, does nothing
+const char *WMSUtilDecode(CPLString &s, const char *encoding);
+
+// Ensure that the url ends in ? or &
+void URLPrepare(CPLString &url);
+// void URLAppend(CPLString *url, const char *s);
+// void URLAppendF(CPLString *url, const char *s, ...) CPL_PRINT_FUNC_FORMAT (2, 3);
+// void URLAppend(CPLString *url, const CPLString &s);
+CPLString BufferToVSIFile(GByte *buffer, size_t size);
 
 int StrToBool(const char *p);
 int URLSearchAndReplace (CPLString *base, const char *search, const char *fmt, ...) CPL_PRINT_FUNC_FORMAT (3, 4);
 /* Convert a.b.c.d to a * 0x1000000 + b * 0x10000 + c * 0x100 + d */
 int VersionStringToInt(const char *version);
 
-
 class GDALWMSImageRequestInfo {
 public:
     double m_x0, m_y0;
@@ -124,116 +130,91 @@ typedef enum
     OVERVIEW_FLOOR
 } GDALWMSOverviewDimComputationMethod;
 
-class GDALWMSMiniDriverCapabilities {
+class WMSMiniDriverCapabilities {
 public:
-  GDALWMSMiniDriverCapabilities() :
-      m_capabilities_version(0),
-      m_has_image_request(0),
-      m_has_tiled_image_requeset(0),
-      m_has_arb_overviews(0),
-      m_max_overview_count(-1),
-      m_overview_dim_computation_method(OVERVIEW_ROUNDED),
-      m_has_geotransform(true)
-  {}
-
-/* Version N capabilities require all version N and earlier variables to be set to correct values */
-    int m_capabilities_version;
-
-/* Version 1 capabilities */
-    int m_has_image_request;            // 1 if ImageRequest method is implemented
-    int m_has_tiled_image_requeset;     // 1 if TiledImageRequest method is implemented
-    int m_has_arb_overviews;            // 1 if ImageRequest method supports arbitrary overviews / resolutions
-    int m_max_overview_count;               // Maximum number of overviews supported if known, -1 otherwise
+    // Default capabilities, suitable in most cases
+    WMSMiniDriverCapabilities() :
+        m_has_getinfo(0),
+        m_has_geotransform(1),
+        m_overview_dim_computation_method(OVERVIEW_ROUNDED)
+    {}
+
+    int m_has_getinfo; // Does it have meaningful implementation
+    int m_has_geotransform;
     GDALWMSOverviewDimComputationMethod m_overview_dim_computation_method;
-    bool m_has_geotransform;
 };
 
 /* All data returned by mini-driver as pointer should remain valid for mini-driver lifetime
-   and should be freed by mini-driver destructor unless otherwise specified. */
-class GDALWMSMiniDriver {
-friend class GDALWMSDataset;
-public:
-    GDALWMSMiniDriver();
-    virtual ~GDALWMSMiniDriver();
+   and should be freed by mini-driver destructor unless otherwise specified.
+ */
 
+// Base class for minidrivers
+// A minidriver has to implement at least the Initialize and the TiledImageRequest
+//
+class WMSMiniDriver {
+friend class GDALWMSDataset;
 public:
-/* Read mini-driver specific configuration. */
-    virtual CPLErr Initialize(CPLXMLNode *config);
+    WMSMiniDriver() : m_parent_dataset(NULL) {};
+    virtual ~WMSMiniDriver() {};
 
 public:
-    virtual void GetCapabilities(GDALWMSMiniDriverCapabilities *caps);
-    virtual void ImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri);
-    virtual void TiledImageRequest(CPLString *url, const GDALWMSImageRequestInfo &iri, const GDALWMSTiledImageRequestInfo &tiri);
-    virtual void GetTiledImageInfo(CPLString *url,
-                                              const GDALWMSImageRequestInfo &iri,
-                                              const GDALWMSTiledImageRequestInfo &tiri,
-                                              int nXInBlock,
-                                              int nYInBlock);
-
-/* Return data projection in WKT format, NULL or empty string if unknown */
-    virtual const char *GetProjectionInWKT();
+    // MiniDriver specific initialization from XML, required
+    // Called once at the beginning of the dataset initialization
+    virtual CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions) = 0;
+
+    // Called once at the end of the dataset initialization
+    virtual CPLErr EndInit() { return CE_None; };
+
+    // Error message returned in url, required
+    // Set error message in request.Error
+    // If tile doesn't exist serverside, set request.range to "none"
+    virtual CPLErr TiledImageRequest(CPL_UNUSED WMSHTTPRequest &,
+        CPL_UNUSED const GDALWMSImageRequestInfo &iri,
+        CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri) = 0;
+
+    // change capabilities to be used by the parent
+    virtual void GetCapabilities(CPL_UNUSED WMSMiniDriverCapabilities *caps) {};
+
+    // signal by setting the m_has_getinfo in the GetCapabilities call
+    virtual void GetTiledImageInfo(CPL_UNUSED CPLString &url,
+        CPL_UNUSED const GDALWMSImageRequestInfo &iri,
+        CPL_UNUSED const GDALWMSTiledImageRequestInfo &tiri,
+        CPL_UNUSED int nXInBlock,
+        CPL_UNUSED int nYInBlock) {};
+
+    virtual const char *GetProjectionInWKT() {
+        if (!m_projection_wkt.empty())
+            return m_projection_wkt.c_str();
+        return NULL;
+    };
+
+    virtual char **GetMetadataDomainList() {
+        return NULL;
+    };
 
 protected:
+    CPLString m_base_url;
+    CPLString m_projection_wkt;
     GDALWMSDataset *m_parent_dataset;
 };
 
-class GDALWMSMiniDriverFactory {
-public:
-    GDALWMSMiniDriverFactory();
-    virtual ~GDALWMSMiniDriverFactory();
-
+class WMSMiniDriverFactory {
 public:
-    virtual GDALWMSMiniDriver* New() = 0;
-    virtual void Delete(GDALWMSMiniDriver *instance) = 0;
+    WMSMiniDriverFactory() {};
+    virtual ~WMSMiniDriverFactory() {};
 
 public:
-    const CPLString &GetName() {
-        return m_name;
-    }
-
-protected:
+    virtual WMSMiniDriver* New() const = 0;
     CPLString m_name;
 };
 
-class GDALWMSMiniDriverManager {
-public:
-    GDALWMSMiniDriverManager();
-    ~GDALWMSMiniDriverManager();
+// Interface with the global mini driver manager
+WMSMiniDriver *NewWMSMiniDriver(const CPLString &name);
+void WMSRegisterMiniDriverFactory(WMSMiniDriverFactory *mdf);
+void WMSDeregisterMiniDrivers(GDALDriver *);
 
-public:
-    void Register(GDALWMSMiniDriverFactory *mdf);
-    GDALWMSMiniDriverFactory *Find(const CPLString &name);
-
-protected:
-    std::list<GDALWMSMiniDriverFactory *> m_mdfs;
-};
-
-#define H_GDALWMSMiniDriverFactory(name) \
-class GDALWMSMiniDriverFactory_##name : public GDALWMSMiniDriverFactory { \
-public: \
-    GDALWMSMiniDriverFactory_##name(); \
-    virtual ~GDALWMSMiniDriverFactory_##name(); \
-    \
-public: \
-    virtual GDALWMSMiniDriver* New(); \
-    virtual void Delete(GDALWMSMiniDriver *instance); \
-};
-
-#define CPP_GDALWMSMiniDriverFactory(name) \
-    GDALWMSMiniDriverFactory_##name::GDALWMSMiniDriverFactory_##name() { \
-    m_name = #name;\
-} \
-    \
-    GDALWMSMiniDriverFactory_##name::~GDALWMSMiniDriverFactory_##name() { \
-} \
-    \
-    GDALWMSMiniDriver* GDALWMSMiniDriverFactory_##name::New() { \
-    return new GDALWMSMiniDriver_##name(); \
-} \
-    \
-    void GDALWMSMiniDriverFactory_##name::Delete(GDALWMSMiniDriver *instance) { \
-    delete instance; \
-}
+// WARNING: Called by GDALDestructor, unsafe to use any static objects
+void WMSDeregister(GDALDriver *);
 
 /************************************************************************/
 /*                            GDALWMSCache                              */
@@ -247,6 +228,7 @@ public:
 public:
     CPLErr Initialize(CPLXMLNode *config);
     CPLErr Write(const char *key, const CPLString &file_name);
+    // Bad name for this function, it only tests that the file is in cache and returns the real name
     CPLErr Read(const char *key, CPLString *file_name);
 
 protected:
@@ -269,15 +251,15 @@ public:
     GDALWMSDataset();
     virtual ~GDALWMSDataset();
 
-    virtual const char *GetProjectionRef();
-    virtual CPLErr SetProjection(const char *proj);
-    virtual CPLErr GetGeoTransform(double *gt);
-    virtual CPLErr SetGeoTransform(double *gt);
-    virtual CPLErr AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, char **options);
+    virtual const char *GetProjectionRef() override;
+    virtual CPLErr SetProjection(const char *proj) override;
+    virtual CPLErr GetGeoTransform(double *gt) override;
+    virtual CPLErr SetGeoTransform(double *gt) override;
+    virtual CPLErr AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, char **options) override;
 
-    virtual char      **GetMetadataDomainList();
+    virtual char      **GetMetadataDomainList() override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
 
     void SetColorTable(GDALColorTable *pct) { m_poColorTable=pct; }
 
@@ -289,34 +271,34 @@ public:
     }
 
     void WMSSetBlockSize(int x, int y) {
-        m_block_size_x=x;
-        m_block_size_y=y;
+        m_block_size_x = x;
+        m_block_size_y = y;
     }
 
     void WMSSetRasterSize(int x, int y) {
-        nRasterXSize=x;
-        nRasterYSize=y;
+        nRasterXSize = x;
+        nRasterYSize = y;
     }
 
     void WMSSetBandsCount(int count) {
-        nBands=count;
+        nBands = count;
     }
 
-    void WMSSetClamp(bool flag=true) {
-        m_clamp_requests=flag;
+    void WMSSetClamp(bool flag = true) {
+        m_clamp_requests = flag;
     }
 
     void WMSSetDataType(GDALDataType type) {
-        m_data_type=type;
+        m_data_type = type;
     }
 
     void WMSSetDataWindow(GDALWMSDataWindow &window) {
-        m_data_window=window;
+        m_data_window = window;
     }
 
     void WMSSetDefaultBlockSize(int x, int y) {
-        m_default_block_size_x=x;
-        m_default_block_size_y=y;
+        m_default_block_size_x = x;
+        m_default_block_size_y = y;
     }
 
     void WMSSetDefaultDataWindowCoordinates(double x0, double y0, double x1, double y1) {
@@ -339,7 +321,7 @@ public:
         m_default_overview_count = overview_count;
     }
 
-    void WMSSetNeedsDataWindow(int flag) {
+    void WMSSetNeedsDataWindow(bool flag) {
         m_bNeedsDataWindow = flag;
     }
 
@@ -365,6 +347,12 @@ public:
         list2vec(vMax,pszMax);
     }
 
+    void SetXML(const char *psz) {
+        m_osXML.clear();
+        if (psz)
+            m_osXML = psz;
+    }
+
     static GDALDataset* Open(GDALOpenInfo *poOpenInfo);
     static int Identify(GDALOpenInfo *poOpenInfo);
     static GDALDataset *CreateCopy( const char * pszFilename,
@@ -373,22 +361,30 @@ public:
                                     GDALProgressFunc pfnProgress,
                                     void * pProgressData );
 
+    const char * const * GetHTTPRequestOpts();
+
+    static const char *GetServerConfig(const char *URI, char **papszHTTPOptions);
+    static void DestroyCfgMutex();
+    static void ClearConfigCache();
+
 protected:
     virtual CPLErr IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer,
                              int bsx, int bsy, GDALDataType bdt,
                              int band_count, int *band_map,
                              GSpacing nPixelSpace, GSpacing nLineSpace,
                              GSpacing nBandSpace,
-                             GDALRasterIOExtraArg* psExtraArg);
-    CPLErr Initialize(CPLXMLNode *config);
+                             GDALRasterIOExtraArg* psExtraArg) override;
+    CPLErr Initialize(CPLXMLNode *config, char **papszOpenOptions);
 
     GDALWMSDataWindow m_data_window;
-    GDALWMSMiniDriver *m_mini_driver;
-    GDALWMSMiniDriverCapabilities m_mini_driver_caps;
+    WMSMiniDriver *m_mini_driver;
+    WMSMiniDriverCapabilities m_mini_driver_caps;
     GDALWMSCache *m_cache;
     CPLString m_projection;
     GDALColorTable *m_poColorTable;
-    std::vector<double> vNoData, vMin, vMax;
+    std::vector<double> vNoData;
+    std::vector<double> vMin;
+    std::vector<double> vMax;
     GDALDataType m_data_type;
     int m_block_size_x;
     int m_block_size_y;
@@ -398,22 +394,32 @@ protected:
     int m_offline_mode;
     int m_http_max_conn;
     int m_http_timeout;
+    char **m_http_options;
+    // Open Option list for tiles
+    char **m_tileOO;
     int m_clamp_requests;
     int m_unsafeSsl;
-    std::vector<int> m_http_zeroblock_codes;
+    std::set<int> m_http_zeroblock_codes;
     int m_zeroblock_on_serverexceptions;
     CPLString m_osUserAgent;
     CPLString m_osReferer;
     CPLString m_osUserPwd;
 
     GDALWMSDataWindow m_default_data_window;
-    int m_default_block_size_x, m_default_block_size_y;
-    int m_default_tile_count_x, m_default_tile_count_y;
+    int m_default_block_size_x;
+    int m_default_block_size_y;
+    int m_default_tile_count_x;
+    int m_default_tile_count_y;
     int m_default_overview_count;
 
-    int m_bNeedsDataWindow;
+    bool m_bNeedsDataWindow;
 
     CPLString m_osXML;
+
+    // Per session cache of server configurations
+    typedef std::map<CPLString, CPLString> StringMap_t;
+    static CPLMutex *cfgmtx;
+    static StringMap_t cfg;
 };
 
 /************************************************************************/
@@ -422,8 +428,6 @@ protected:
 
 class GDALWMSRasterBand : public GDALPamRasterBand {
     friend class GDALWMSDataset;
-
-    char**  BuildHTTPRequestOpts();
     void    ComputeRequestInfo( GDALWMSImageRequestInfo &iri,
                                 GDALWMSTiledImageRequestInfo &tiri,
                                 int x, int y);
@@ -432,36 +436,36 @@ class GDALWMSRasterBand : public GDALPamRasterBand {
     CPLString osMetadataItemURL;
 
 public:
-    GDALWMSRasterBand(GDALWMSDataset *parent_dataset, int band, double scale);
+    GDALWMSRasterBand( GDALWMSDataset *parent_dataset, int band, double scale );
     virtual ~GDALWMSRasterBand();
     void AddOverview(double scale);
-    virtual double GetNoDataValue( int * );
-    virtual double GetMinimum( int * );
-    virtual double GetMaximum( int * );
-    virtual GDALColorTable *GetColorTable();
-    virtual CPLErr AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, char **options);
-
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
-    virtual CPLErr IReadBlock(int x, int y, void *buffer);
+    virtual double GetNoDataValue( int * ) override;
+    virtual double GetMinimum( int * ) override;
+    virtual double GetMaximum( int * ) override;
+    virtual GDALColorTable *GetColorTable() override;
+    virtual CPLErr AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, char **options) override;
+
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) override;
+    virtual CPLErr IReadBlock(int x, int y, void *buffer) override;
     virtual CPLErr IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer, int bsx, int bsy, GDALDataType bdt,
                              GSpacing nPixelSpace, GSpacing nLineSpace,
-                             GDALRasterIOExtraArg* psExtraArg);
-    virtual int HasArbitraryOverviews();
-    virtual int GetOverviewCount();
-    virtual GDALRasterBand *GetOverview(int n);
+                             GDALRasterIOExtraArg* psExtraArg) override;
+    virtual int HasArbitraryOverviews() override;
+    virtual int GetOverviewCount() override;
+    virtual GDALRasterBand *GetOverview(int n) override;
 
-    virtual char      **GetMetadataDomainList();
+    virtual char      **GetMetadataDomainList() override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
 
 protected:
     CPLErr ReadBlocks(int x, int y, void *buffer, int bx0, int by0, int bx1, int by1, int advise_read);
     bool IsBlockInCache(int x, int y);
-    void AskMiniDriverForBlock(CPLString *url, int x, int y);
+    CPLErr AskMiniDriverForBlock(WMSHTTPRequest &request, int x, int y);
     CPLErr ReadBlockFromFile(int x, int y, const char *file_name, int to_buffer_band, void *buffer, int advise_read);
     CPLErr ZeroBlock(int x, int y, int to_buffer_band, void *buffer);
-    CPLErr ReportWMSException(const char *file_name);
+    static CPLErr ReportWMSException(const char *file_name);
 
 protected:
     GDALWMSDataset *m_parent_dataset;
@@ -471,7 +475,4 @@ protected:
     GDALColorInterp m_color_interp;
 };
 
-GDALWMSMiniDriverManager *GetGDALWMSMiniDriverManager();
-void DestroyWMSMiniDriverManager(void);
-
 #endif /* notdef WMSDRIVER_H_INCLUDED */
diff --git a/frmts/wms/wmsmetadataset.cpp b/frmts/wms/wmsmetadataset.cpp
index 1ed7879..5b2be30 100644
--- a/frmts/wms/wmsmetadataset.cpp
+++ b/frmts/wms/wmsmetadataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: wmsmetadataset.cpp 32078 2015-12-08 09:09:45Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Definition of GDALWMSMetaDataset class
@@ -29,15 +28,15 @@
 
 #include "wmsmetadataset.h"
 
+CPL_CVSID("$Id: wmsmetadataset.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 int VersionStringToInt(const char *version);
 
 /************************************************************************/
 /*                          GDALWMSMetaDataset()                        */
 /************************************************************************/
 
-GDALWMSMetaDataset::GDALWMSMetaDataset() : papszSubDatasets(NULL)
-{
-}
+GDALWMSMetaDataset::GDALWMSMetaDataset() : papszSubDatasets(NULL) {}
 
 /************************************************************************/
 /*                         ~GDALWMSMetaDataset()                        */
@@ -81,10 +80,10 @@ GDALDataset *GDALWMSMetaDataset::DownloadGetCapabilities(GDALOpenInfo *poOpenInf
     CPLString osTransparent = CPLURLGetValue(pszURL, "TRANSPARENT");
     CPLString osVersion = CPLURLGetValue(pszURL, "VERSION");
     CPLString osPreferredSRS = CPLURLGetValue(pszURL, "SRS");
-    if( osPreferredSRS.size() == 0 )
+    if( osPreferredSRS.empty() )
         osPreferredSRS = CPLURLGetValue(pszURL, "CRS");
 
-    if (osVersion.size() == 0)
+    if (osVersion.empty())
         osVersion = "1.1.1";
 
     CPLString osURL(pszURL);
@@ -141,7 +140,6 @@ GDALDataset *GDALWMSMetaDataset::DownloadGetCapabilities(GDALOpenInfo *poOpenInf
     return poRet;
 }
 
-
 /************************************************************************/
 /*                         DownloadGetTileService()                     */
 /************************************************************************/
@@ -264,16 +262,16 @@ void GDALWMSMetaDataset::AddSubDataset( const char* pszLayerName,
         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "SRS", pszSRS);
     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "BBOX",
              CPLSPrintf("%s,%s,%s,%s", pszMinX, pszMinY, pszMaxX, pszMaxY));
-    if (osFormat.size() != 0)
+    if (!osFormat.empty())
         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "FORMAT",
                                         osFormat);
-    if (osTransparent.size() != 0)
+    if (!osTransparent.empty())
         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TRANSPARENT",
                                         osTransparent);
 
     if (pszTitle)
     {
-        if (osXMLEncoding.size() != 0 &&
+        if (!osXMLEncoding.empty() &&
             osXMLEncoding != "utf-8" &&
             osXMLEncoding != "UTF-8")
         {
@@ -296,7 +294,6 @@ void GDALWMSMetaDataset::AddSubDataset( const char* pszLayerName,
     }
 }
 
-
 /************************************************************************/
 /*                         AddWMSCSubDataset()                          */
 /************************************************************************/
@@ -322,7 +319,7 @@ void GDALWMSMetaDataset::AddWMSCSubDataset(WMSCTileSetDesc& oWMSCTileSetDesc,
                                        oWMSCTileSetDesc.osMaxY.c_str()));
 
     osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "FORMAT", oWMSCTileSetDesc.osFormat);
-    if (osTransparent.size() != 0)
+    if (!osTransparent.empty())
         osSubdatasetName = CPLURLAddKVP(osSubdatasetName, "TRANSPARENT",
                                         osTransparent);
     if (oWMSCTileSetDesc.nTileWidth != oWMSCTileSetDesc.nTileHeight)
@@ -338,7 +335,7 @@ void GDALWMSMetaDataset::AddWMSCSubDataset(WMSCTileSetDesc& oWMSCTileSetDesc,
 
     if (pszTitle)
     {
-        if (osXMLEncoding.size() != 0 &&
+        if (!osXMLEncoding.empty() &&
             osXMLEncoding != "utf-8" &&
             osXMLEncoding != "UTF-8")
         {
@@ -400,7 +397,7 @@ void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
         {
             psSRS = psIter;
             pszSRSLocal = CPLGetXMLValue(psSRS, pszSRSTagName, NULL);
-            if( osPreferredSRS.size() == 0 || pszSRSLocal == NULL )
+            if( osPreferredSRS.empty() || pszSRSLocal == NULL )
                 break;
             if( EQUAL(osPreferredSRS, pszSRSLocal) )
                 break;
@@ -418,7 +415,6 @@ void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
             pszSRSLocal = "EPSG:4326";
     }
 
-
     if (pszSRSLocal != NULL && psSRS != NULL)
     {
         pszMinXLocal = CPLGetXMLValue(psSRS, "minx", NULL);
@@ -439,7 +435,7 @@ void GDALWMSMetaDataset::ExploreLayer(CPLXMLNode* psXML,
     if (pszName != NULL && pszSRS && pszMinX && pszMinY && pszMaxX && pszMaxY)
     {
         CPLString osLocalTransparent(osTransparent);
-        if (osLocalTransparent.size() == 0)
+        if (osLocalTransparent.empty())
         {
             const char* pszOpaque = CPLGetXMLValue(psXML, "opaque", "0");
             if (EQUAL(pszOpaque, "1"))
@@ -643,7 +639,7 @@ void GDALWMSMetaDataset::AddTiledSubDataset(const char* pszTiledGroupName,
 
     if (pszTitle)
     {
-        if (osXMLEncoding.size() != 0 &&
+        if (!osXMLEncoding.empty() &&
             osXMLEncoding != "utf-8" &&
             osXMLEncoding != "UTF-8")
         {
diff --git a/frmts/wms/wmsmetadataset.h b/frmts/wms/wmsmetadataset.h
index 9d06775..5866eaa 100644
--- a/frmts/wms/wmsmetadataset.h
+++ b/frmts/wms/wmsmetadataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: wmsmetadataset.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: wmsmetadataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Declaration of GDALWMSMetaDataset class
@@ -103,10 +103,10 @@ class GDALWMSMetaDataset : public GDALPamDataset
 
   public:
         GDALWMSMetaDataset();
-       ~GDALWMSMetaDataset();
+    virtual ~GDALWMSMetaDataset();
 
-    virtual char      **GetMetadataDomainList();
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadataDomainList() override;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
 
     static GDALDataset* AnalyzeGetCapabilities(CPLXMLNode* psXML,
                                                CPLString osFormat = "",
diff --git a/frmts/wms/wmsutils.cpp b/frmts/wms/wmsutils.cpp
index 4ac9fcd..60e751e 100644
--- a/frmts/wms/wmsutils.cpp
+++ b/frmts/wms/wmsutils.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: wmsutils.cpp 31640 2015-11-18 23:17:59Z rouault $
  *
  * Project:  WMS Client Driver
  * Purpose:  Supporting utility functions for GDAL WMS driver.
@@ -29,6 +28,8 @@
 
 #include "wmsdriver.h"
 
+CPL_CVSID("$Id: wmsutils.cpp 37290 2017-02-03 19:57:05Z lplesea $");
+
 CPLString MD5String(const char *s) {
     unsigned char hash[16];
     char hhash[33];
@@ -66,32 +67,18 @@ CPLString ProjToWKT(const CPLString &proj) {
     }
     sr.exportToWkt(&wkt);
     srs = wkt;
-    OGRFree(wkt);
+    CPLFree(wkt);
     return srs;
 }
 
-void URLAppend(CPLString *url, const char *s) {
-    if ((s == NULL) || (s[0] == '\0')) return;
-    if (s[0] == '&') {
-        if (url->find('?') == std::string::npos) url->append(1, '?');
-        if (((*url)[url->size() - 1] == '?') || ((*url)[url->size() - 1] == '&')) url->append(s + 1);
-        else url->append(s);
-    } else url->append(s);
-}
-
-void URLAppendF(CPLString *url, const char *s, ...) {
-    CPLString tmp;
-    va_list args;
-
-    va_start(args, s);
-    tmp.vPrintf(s, args);
-    va_end(args);
-
-    URLAppend(url, tmp.c_str());
-}
-
-void URLAppend(CPLString *url, const CPLString &s) {
-    URLAppend(url, s.c_str());
+// Terminates an URL base with either ? or &, so extra args can be appended
+void URLPrepare(CPLString &url) {
+    if (url.find("?") == std::string::npos) {
+        url.append("?");
+    } else {
+        if (*url.rbegin() != '?' && *url.rbegin() != '&')
+            url.append("&");
+    }
 }
 
 CPLString BufferToVSIFile(GByte *buffer, size_t size) {
@@ -104,16 +91,6 @@ CPLString BufferToVSIFile(GByte *buffer, size_t size) {
     return file_name;
 }
 
-CPLErr MakeDirs(const char *path) {
-    char *p = CPLStrdup(CPLGetDirname(path));
-    if (strlen(p) >= 2) {
-        MakeDirs(p);
-    }
-    VSIMkdir(p, 0744);
-    CPLFree(p);
-    return CE_None;
-}
-
 int VersionStringToInt(const char *version) {
     if (version == NULL) return -1;
     const char *p = version;
@@ -149,3 +126,33 @@ int URLSearchAndReplace (CPLString *base, const char *search, const char *fmt, .
     base->replace(start, strlen(search), tmp);
     return static_cast<int>(start);
 }
+
+// decode s from base64, XMLencoded or read from the file name s
+const char *WMSUtilDecode(CPLString &s, const char *encoding) {
+    if (EQUAL(encoding, "base64")) {
+        std::vector<char> buffer(s.begin(), s.end());
+        buffer.push_back('\0');
+        CPLBase64DecodeInPlace(reinterpret_cast<GByte *>(&buffer[0]));
+        s.assign(&buffer[0], strlen(&buffer[0]));
+    }
+    else if (EQUAL(encoding, "XMLencoded")) {
+        int len = static_cast<int>(s.size());
+        char *result = CPLUnescapeString(s.c_str(), &len, CPLES_XML);
+        s.assign(result, static_cast<size_t>(len));
+        CPLFree(result);
+    }
+    else if (EQUAL(encoding, "file")) { // Not an encoding but an external file
+        VSILFILE *f = VSIFOpenL(s.c_str(), "rb");
+        s.clear(); // Return an empty string if file can't be opened or read
+        if (f) {
+            VSIFSeekL(f, 0, SEEK_END);
+            size_t size = static_cast<size_t>(VSIFTellL(f));
+            VSIFSeekL(f, 0, SEEK_SET);
+            std::vector<char> buffer(size);
+            if (VSIFReadL(reinterpret_cast<void *>(&buffer[0]), size, 1, f))
+                s.assign(&buffer[0], buffer.size());
+            VSIFCloseL(f);
+        }
+    }
+    return s.c_str();
+}
diff --git a/frmts/wmts/frmt_wmts.html b/frmts/wmts/frmt_wmts.html
index fc70c3a..05806a2 100644
--- a/frmts/wmts/frmt_wmts.html
+++ b/frmts/wmts/frmt_wmts.html
@@ -44,9 +44,9 @@ the URL to the GetCapabilities response of a WTMS service:
 
 <li><p>
 the URL to the GetCapabilities response of a WTMS service, prefixed with <i>WMTS:</i>,
-and possibly with optional layer, tilematrixset, style and extendbeyonddateline parameters,
+and possibly with optional layer, tilematrixset, tilematrix/zoom_level, style and extendbeyonddateline parameters,
 with the following syntax
-<i>WMTS:url[,layer=layer_id][,tilematrixset=tms_id][,style=style_id][,extendbeyonddateline=yes/no]</i>.
+<i>WMTS:url[,layer=layer_id][,tilematrixset=tms_id][,tilematrix=tm_id|,zoom_level=level][,style=style_id][,extendbeyonddateline=yes/no]</i>.
 
 <pre>gdalinfo "WMTS:http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml"</pre>
 <pre>gdalinfo "WMTS:http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml,layer=lb"</pre>
@@ -55,7 +55,7 @@ with the following syntax
 
 <li><p>
 the <i>WMTS:</i> prefix with open options URL (required), LAYER, TILEMATRIXSET,
-STYLE, EXTENDBEYONDDATELINE.
+TILEMATRIX, ZOOM_LEVEL, STYLE, EXTENDBEYONDDATELINE.
 <pre>gdalinfo WMTS: -oo URL=http://maps.wien.gv.at/wmts/1.0.0/WMTSCapabilities.xml -oo LAYER=lb</pre>
 </p></li>
 
@@ -97,6 +97,14 @@ It is important that there be no spaces or other content before the <tt><GDAL
                         <td class="desc">Tile Matrix Set identifier. Must be one of the listed tile matrix set for the layer. (optional, but may be needed to disambiguate between several tile matrix sets)</td>
                 </tr>
                 <tr>
+                        <td class="xml">  <TileMatrix><span class="value">tile_matrix_id</span></TileMatrix></td>
+                        <td class="desc">Tile Matrix identifier. Must be one of the listed tile matrix of the select tile matrix set for the layer. (optional, GDAL >= 2.2. Exclusive with ZoomLevel. If not specified the last tile matrix, ie the one with the best resolution, is selected)</td>
+                </tr>
+                <tr>
+                        <td class="xml">  <ZoomLevel><span class="value">int_value</span></ZoomLevel></td>
+                        <td class="desc">Index of the maximum zoom level / tile matrix to use. The first one (ie the one of lower resolution) is indexed 0. (optional, GDAL >= 2.2. Exclusive with TileMatrix. If not specified the last tile matrix, ie the one with the best resolution, is selected)</td>
+                </tr>
+                <tr>
                         <td class="xml">  <Format><span class="value">image/png</span></Format></td>
                         <td class="desc">Tile format, used by GetTile requests. Must be one of the listed Format for the layer. (optional, but may be needed to disambiguate between several Format)</td>
                 </tr>
diff --git a/frmts/wmts/wmtsdataset.cpp b/frmts/wmts/wmtsdataset.cpp
index c6dfbbf..bc04bbb 100644
--- a/frmts/wmts/wmtsdataset.cpp
+++ b/frmts/wmts/wmtsdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: wmtsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $
  *
  * Project:  GDAL WMTS driver
  * Purpose:  Implement GDAL WMTS support
@@ -34,9 +33,12 @@
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 #include "../vrt/gdal_vrt.h"
-#include <vector>
-#include <set>
+
+#include <algorithm>
 #include <map>
+#include <set>
+#include <vector>
+#include <limits>
 
 extern "C" void GDALRegister_WMTS();
 
@@ -45,9 +47,17 @@ extern "C" void GDALRegister_WMTS();
 /* Set in stone by WMTS spec. In pixel/meter */
 #define WMTS_PITCH                      0.00028
 
-#define WMTS_METERS_FOR_ONE_DEG         (6378137 * 2 * M_PI / 360)
+#define WMTS_WGS84_DEG_PER_METER    (180 / M_PI / SRS_WGS84_SEMIMAJOR)
+
+CPL_CVSID("$Id: wmtsdataset.cpp 37921 2017-04-08 16:10:05Z rouault $");
 
-CPL_CVSID("$Id: wmtsdataset.cpp 33717 2016-03-14 06:29:14Z goatbar $");
+typedef enum
+{
+    AUTO,
+    LAYER_BBOX,
+    TILE_MATRIX_SET,
+    MOST_PRECISE_TILE_MATRIX
+} ExtentMethod;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -96,9 +106,15 @@ class WMTSTileMatrixSet
     public:
         OGRSpatialReference         oSRS;
         CPLString                   osSRS;
-        int                         bBoundingBoxValid;
+        bool                        bBoundingBoxValid;
         OGREnvelope                 sBoundingBox; /* expressed in TMS SRS */
         std::vector<WMTSTileMatrix> aoTM;
+
+        WMTSTileMatrixSet() :
+            oSRS( OGRSpatialReference() ),
+            bBoundingBoxValid(false)
+        {
+        }
 };
 
 /************************************************************************/
@@ -135,6 +151,8 @@ class WMTSDataset : public GDALPamDataset
                                            const char* pszOperation);
     static int          ReadTMS(CPLXMLNode* psContents,
                                 const CPLString& osIdentifier,
+                                const CPLString& osMaxTileMatrixIdentifier,
+                                int nMaxZoomLevel,
                                 WMTSTileMatrixSet& oTMS);
     static int          ReadTMLimits(CPLXMLNode* psTMSLimits,
                                      std::map<CPLString, WMTSTileMatrixLimits>& aoMapTileMatrixLimits);
@@ -143,10 +161,10 @@ class WMTSDataset : public GDALPamDataset
                  WMTSDataset();
     virtual     ~WMTSDataset();
 
-    virtual CPLErr GetGeoTransform(double* padfGT);
-    virtual const char* GetProjectionRef();
+    virtual CPLErr GetGeoTransform(double* padfGT) override;
+    virtual const char* GetProjectionRef() override;
     virtual const char* GetMetadataItem(const char* pszName,
-                                        const char* pszDomain);
+                                        const char* pszDomain) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -158,7 +176,7 @@ class WMTSDataset : public GDALPamDataset
                                          CPL_UNUSED void * pProgressData );
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
     virtual CPLErr  IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
@@ -167,7 +185,7 @@ class WMTSDataset : public GDALPamDataset
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace,
                                GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg) override;
 };
 
 /************************************************************************/
@@ -181,31 +199,31 @@ class WMTSBand : public GDALPamRasterBand
   public:
                   WMTSBand(WMTSDataset* poDS, int nBand);
 
-    virtual GDALRasterBand* GetOverview(int nLevel);
-    virtual int GetOverviewCount();
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual GDALRasterBand* GetOverview(int nLevel) override;
+    virtual int GetOverviewCount() override;
+    virtual GDALColorInterp GetColorInterpretation() override;
     virtual const char* GetMetadataItem(const char* pszName,
-                                        const char* pszDomain);
+                                        const char* pszDomain) override;
 
   protected:
-    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage);
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage) override;
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing, GSpacing,
-                              GDALRasterIOExtraArg* psExtraArg );
-
+                              GDALRasterIOExtraArg* psExtraArg ) override;
 };
 
 /************************************************************************/
 /*                            WMTSBand()                                */
 /************************************************************************/
 
-WMTSBand::WMTSBand(WMTSDataset* poDSIn, int nBandIn)
+WMTSBand::WMTSBand( WMTSDataset* poDSIn, int nBandIn )
 {
-    this->poDS = poDSIn;
-    this->nBand = nBandIn;
+    poDS = poDSIn;
+    nBand = nBandIn;
     eDataType = GDT_Byte;
-    poDSIn->apoDatasets[0]->GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    poDSIn->apoDatasets[0]->GetRasterBand(1)->
+        GetBlockSize(&nBlockXSize, &nBlockYSize);
 }
 
 /************************************************************************/
@@ -218,7 +236,6 @@ CPLErr WMTSBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage)
     return poGDS->apoDatasets[0]->GetRasterBand(nBand)->ReadBlock(nBlockXOff, nBlockYOff, pImage);
 }
 
-
 /************************************************************************/
 /*                             IRasterIO()                              */
 /************************************************************************/
@@ -325,8 +342,8 @@ const char *WMTSBand::GetMetadataItem( const char * pszName,
 /* ==================================================================== */
     if( pszDomain != NULL && EQUAL(pszDomain,"LocationInfo") &&
         pszName != NULL && STARTS_WITH_CI(pszName, "Pixel_") &&
-        poGDS->oTMS.aoTM.size() &&
-        poGDS->osURLFeatureInfoTemplate.size() )
+        !poGDS->oTMS.aoTM.empty() &&
+        !poGDS->osURLFeatureInfoTemplate.empty() )
     {
         int iPixel, iLine;
 
@@ -336,7 +353,7 @@ const char *WMTSBand::GetMetadataItem( const char * pszName,
         if( sscanf( pszName+6, "%d_%d", &iPixel, &iLine ) != 2 )
             return NULL;
 
-        const WMTSTileMatrix& oTM = poGDS->oTMS.aoTM[poGDS->oTMS.aoTM.size()-1];
+        const WMTSTileMatrix& oTM = poGDS->oTMS.aoTM.back();
 
         iPixel += (int)floor(0.5 + (poGDS->adfGT[0] - oTM.dfTLX) / oTM.dfPixelSize);
         iLine += (int)floor(0.5 + (oTM.dfTLY - poGDS->adfGT[3]) / oTM.dfPixelSize);
@@ -408,7 +425,8 @@ const char *WMTSBand::GetMetadataItem( const char * pszName,
 /*                          WMTSDataset()                               */
 /************************************************************************/
 
-WMTSDataset::WMTSDataset()
+WMTSDataset::WMTSDataset() :
+    papszHTTPOptions(NULL)
 {
     adfGT[0] = 0;
     adfGT[1] = 1;
@@ -416,7 +434,6 @@ WMTSDataset::WMTSDataset()
     adfGT[3] = 0;
     adfGT[4] = 0;
     adfGT[5] = 1;
-    papszHTTPOptions = NULL;
 }
 
 /************************************************************************/
@@ -436,7 +453,7 @@ WMTSDataset::~WMTSDataset()
 int WMTSDataset::CloseDependentDatasets()
 {
     int bRet = GDALPamDataset::CloseDependentDatasets();
-    if( apoDatasets.size() )
+    if( !apoDatasets.empty() )
     {
         for(size_t i=0;i<apoDatasets.size();i++)
             delete apoDatasets[i];
@@ -597,7 +614,7 @@ CPLString WMTSDataset::FixCRSName(const char* pszCRS)
 
     CPLString osRet(pszCRS);
     while( osRet.size() &&
-           (osRet[osRet.size()-1] == ' ' || osRet[osRet.size()-1] == '\r' || osRet[osRet.size()-1] == '\n') )
+           (osRet.back() == ' ' || osRet.back() == '\r' || osRet.back() == '\n') )
     {
         osRet.resize(osRet.size() - 1);
     }
@@ -610,6 +627,8 @@ CPLString WMTSDataset::FixCRSName(const char* pszCRS)
 
 int WMTSDataset::ReadTMS(CPLXMLNode* psContents,
                          const CPLString& osIdentifier,
+                         const CPLString& osMaxTileMatrixIdentifier,
+                         int nMaxZoomLevel,
                          WMTSTileMatrixSet& oTMS)
 {
     for(CPLXMLNode* psIter = psContents->psChild; psIter != NULL; psIter = psIter->psNext )
@@ -634,7 +653,7 @@ int WMTSDataset::ReadTMS(CPLXMLNode* psContents,
         }
         int bSwap = oTMS.oSRS.EPSGTreatsAsLatLong() || oTMS.oSRS.EPSGTreatsAsNorthingEasting();
         CPLXMLNode* psBB = CPLGetXMLNode(psIter, "BoundingBox");
-        oTMS.bBoundingBoxValid = FALSE;
+        oTMS.bBoundingBoxValid = false;
         if( psBB != NULL )
         {
             CPLString osCRS = CPLGetXMLValue(psBB, "crs", "");
@@ -642,7 +661,7 @@ int WMTSDataset::ReadTMS(CPLXMLNode* psContents,
             {
                 CPLString osLowerCorner = CPLGetXMLValue(psBB, "LowerCorner", "");
                 CPLString osUpperCorner = CPLGetXMLValue(psBB, "UpperCorner", "");
-                if( osLowerCorner.size() && osUpperCorner.size() )
+                if( !osLowerCorner.empty() && !osUpperCorner.empty() )
                 {
                     char** papszLC = CSLTokenizeString(osLowerCorner);
                     char** papszUC = CSLTokenizeString(osUpperCorner);
@@ -652,7 +671,7 @@ int WMTSDataset::ReadTMS(CPLXMLNode* psContents,
                         oTMS.sBoundingBox.MinY = CPLAtof(papszLC[(bSwap)? 0 : 1]);
                         oTMS.sBoundingBox.MaxX = CPLAtof(papszUC[(bSwap)? 1 : 0]);
                         oTMS.sBoundingBox.MaxY = CPLAtof(papszUC[(bSwap)? 0 : 1]);
-                        oTMS.bBoundingBoxValid = TRUE;
+                        oTMS.bBoundingBoxValid = true;
                     }
                     CSLDestroy(papszLC);
                     CSLDestroy(papszUC);
@@ -671,10 +690,11 @@ int WMTSDataset::ReadTMS(CPLXMLNode* psContents,
                 oTMS.sBoundingBox.MinY = -90;
                 oTMS.sBoundingBox.MaxX = 180;
                 oTMS.sBoundingBox.MaxY = 90;
-                oTMS.bBoundingBoxValid = TRUE;
+                oTMS.bBoundingBoxValid = true;
             }
         }
 
+        bool bFoundTileMatrix = false;
         for(CPLXMLNode* psSubIter = psIter->psChild; psSubIter != NULL; psSubIter = psSubIter->psNext )
         {
             if( psSubIter->eType != CXT_Element || strcmp(psSubIter->pszValue, "TileMatrix") != 0 )
@@ -700,7 +720,7 @@ int WMTSDataset::ReadTMS(CPLXMLNode* psContents,
             oTM.dfScaleDenominator = CPLAtof(pszScaleDenominator);
             oTM.dfPixelSize = oTM.dfScaleDenominator * WMTS_PITCH;
             if( oTMS.oSRS.IsGeographic() )
-                oTM.dfPixelSize /= WMTS_METERS_FOR_ONE_DEG;
+                oTM.dfPixelSize *= WMTS_WGS84_DEG_PER_METER;
             double dfVal1 = CPLAtof(pszTopLeftCorner);
             double dfVal2 = CPLAtof(strchr(pszTopLeftCorner, ' ')+1);
             if( !bSwap ||
@@ -718,8 +738,8 @@ int WMTSDataset::ReadTMS(CPLXMLNode* psContents,
             }
             oTM.nTileWidth = atoi(pszTileWidth);
             oTM.nTileHeight = atoi(pszTileHeight);
-            if( oTM.nTileWidth < 128 || oTM.nTileWidth > 4096 ||
-                oTM.nTileHeight < 128 || oTM.nTileHeight > 4096 )
+            if( oTM.nTileWidth <= 0 || oTM.nTileWidth > 4096 ||
+                oTM.nTileHeight <= 0 || oTM.nTileHeight > 4096 )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Invalid TileWidth/TileHeight element");
@@ -732,8 +752,32 @@ int WMTSDataset::ReadTMS(CPLXMLNode* psContents,
             if( oTM.nMatrixWidth < 1 || oTM.nMatrixHeight < 1 )
                 continue;
             oTMS.aoTM.push_back(oTM);
+            if( (nMaxZoomLevel >= 0 && static_cast<int>(oTMS.aoTM.size())-1
+                                                        == nMaxZoomLevel) ||
+                (!osMaxTileMatrixIdentifier.empty() &&
+                 EQUAL(osMaxTileMatrixIdentifier, l_pszIdentifier)) )
+            {
+                bFoundTileMatrix = true;
+                break;
+            }
         }
-        if( oTMS.aoTM.size() == 0 )
+        if( nMaxZoomLevel >= 0 && !bFoundTileMatrix )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot find TileMatrix of zoom level %d in TileMatrixSet '%s'",
+                     nMaxZoomLevel,
+                     osIdentifier.c_str());
+            return FALSE;
+        }
+        if( !osMaxTileMatrixIdentifier.empty() && !bFoundTileMatrix )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot find TileMatrix '%s' in TileMatrixSet '%s'",
+                     osMaxTileMatrixIdentifier.c_str(),
+                     osIdentifier.c_str());
+            return FALSE;
+        }
+        if( oTMS.aoTM.empty() )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot find TileMatrix in TileMatrixSet '%s'",
                      osIdentifier.c_str());
@@ -933,10 +977,19 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                                     "LAYER", "");
     CPLString osTMS = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
                                     "TILEMATRIXSET", "");
+    CPLString osMaxTileMatrixIdentifier = CSLFetchNameValueDef(
+                                    poOpenInfo->papszOpenOptions,
+                                    "TILEMATRIX", "");
+    int nUserMaxZoomLevel = atoi(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                                    "ZOOM_LEVEL",
+                                    CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                                    "ZOOMLEVEL", "-1")));
     CPLString osStyle = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
                                     "STYLE", "");
-    int bExtendBeyondDateLine = CSLFetchBoolean(poOpenInfo->papszOpenOptions,
-                                    "EXTENDBEYONDDATELINE", FALSE);
+
+    int bExtendBeyondDateLine =
+        CPLFetchBool(poOpenInfo->papszOpenOptions,
+                     "EXTENDBEYONDDATELINE", false);
 
     CPLString osOtherXML = "<Cache />"
                      "<UnsafeSSL>true</UnsafeSSL>"
@@ -960,6 +1013,11 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                         osLayer = pszValue;
                     else if( EQUAL(pszKey, "tilematrixset") )
                         osTMS = pszValue;
+                    else if( EQUAL(pszKey, "tilematrix") )
+                        osMaxTileMatrixIdentifier = pszValue;
+                    else if( EQUAL(pszKey, "zoom_level") ||
+                             EQUAL(pszKey, "zoomlevel") )
+                        nUserMaxZoomLevel = atoi(pszValue);
                     else if( EQUAL(pszKey, "style") )
                         osStyle = pszValue;
                     else if( EQUAL(pszKey, "extendbeyonddateline") )
@@ -1005,7 +1063,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
             return NULL;
         }
         osGetCapabilitiesURL = CPLGetXMLValue(psRoot, "GetCapabilitiesUrl", "");
-        if( osGetCapabilitiesURL.size() == 0 )
+        if( osGetCapabilitiesURL.empty() )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Missing <GetCapabilitiesUrl>");
             CPLDestroyXMLNode(psGDALWMTS);
@@ -1014,6 +1072,10 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
 
         osLayer = CPLGetXMLValue(psRoot, "Layer", osLayer);
         osTMS = CPLGetXMLValue(psRoot, "TileMatrixSet", osTMS);
+        osMaxTileMatrixIdentifier = CPLGetXMLValue(psRoot, "TileMatrix",
+                                                   osMaxTileMatrixIdentifier);
+        nUserMaxZoomLevel = atoi(CPLGetXMLValue(psRoot, "ZoomLevel",
+                                       CPLSPrintf("%d", nUserMaxZoomLevel)));
         osStyle = CPLGetXMLValue(psRoot, "Style", osStyle);
         osTileFormat = CPLGetXMLValue(psRoot, "Format", osTileFormat);
         osInfoFormat = CPLGetXMLValue(psRoot, "InfoFormat", osInfoFormat);
@@ -1080,7 +1142,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
         else
         {
             osGetCapabilitiesURL = GetOperationKVPURL(psXML, "GetCapabilities");
-            if( osGetCapabilitiesURL.size() )
+            if( !osGetCapabilitiesURL.empty() )
             {
                 osGetCapabilitiesURL = CPLURLAddKVP(osGetCapabilitiesURL, "service", "WMTS");
                 osGetCapabilitiesURL = CPLURLAddKVP(osGetCapabilitiesURL, "request", "GetCapabilities");
@@ -1096,7 +1158,8 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
     CPLString osSelectLayer(osLayer), osSelectTMS(osTMS), osSelectStyle(osStyle);
     CPLString osSelectLayerTitle, osSelectLayerAbstract;
     CPLString osSelectTileFormat(osTileFormat), osSelectInfoFormat(osInfoFormat);
-    int nCountTileFormat = 0, nCountInfoFormat = 0;
+    int nCountTileFormat = 0;
+    int nCountInfoFormat = 0;
     CPLString osURLTileTemplate;
     CPLString osURLFeatureInfoTemplate;
     std::set<CPLString> aoSetLayers;
@@ -1116,10 +1179,10 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                      pszIdentifier);
         }
         aoSetLayers.insert(pszIdentifier);
-        if( osLayer.size() && strcmp(osLayer, pszIdentifier) != 0 )
+        if( !osLayer.empty() && strcmp(osLayer, pszIdentifier) != 0 )
             continue;
         const char* pszTitle = CPLGetXMLValue(psIter, "Title", NULL);
-        if( osSelectLayer.size() == 0 )
+        if( osSelectLayer.empty() )
         {
             osSelectLayer = pszIdentifier;
         }
@@ -1145,10 +1208,10 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                 strcmp(psSubIter->pszValue, "Format") == 0 )
             {
                 const char* pszValue = CPLGetXMLValue(psSubIter, "", "");
-                if( osTileFormat.size() && strcmp(osTileFormat, pszValue) != 0 )
+                if( !osTileFormat.empty() && strcmp(osTileFormat, pszValue) != 0 )
                     continue;
                 nCountTileFormat ++;
-                if( osSelectTileFormat.size() == 0 ||
+                if( osSelectTileFormat.empty() ||
                     EQUAL(pszValue, "image/png") )
                 {
                     osSelectTileFormat = pszValue;
@@ -1158,10 +1221,10 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                      strcmp(psSubIter->pszValue, "InfoFormat") == 0 )
             {
                 const char* pszValue = CPLGetXMLValue(psSubIter, "", "");
-                if( osInfoFormat.size() && strcmp(osInfoFormat, pszValue) != 0 )
+                if( !osInfoFormat.empty() && strcmp(osInfoFormat, pszValue) != 0 )
                     continue;
                 nCountInfoFormat ++;
-                if( osSelectInfoFormat.size() == 0 ||
+                if( osSelectInfoFormat.empty() ||
                     (EQUAL(pszValue, "application/vnd.ogc.gml") &&
                      !EQUAL(osSelectInfoFormat, "application/vnd.ogc.gml/3.1.1")) ||
                     EQUAL(pszValue, "application/vnd.ogc.gml/3.1.1") )
@@ -1182,10 +1245,10 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
             {
                 const char* pszTMS = CPLGetXMLValue(
                                             psSubIter, "TileMatrixSet", "");
-                if( osTMS.size() && strcmp(osTMS, pszTMS) != 0 )
+                if( !osTMS.empty() && strcmp(osTMS, pszTMS) != 0 )
                     continue;
                 if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
-                    osSelectTMS.size() == 0 )
+                    osSelectTMS.empty() )
                 {
                     osSelectTMS = pszTMS;
                 }
@@ -1205,7 +1268,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                                             psSubIter, "isDefault", "false"));
                 const char* l_pszIdentifier = CPLGetXMLValue(
                                             psSubIter, "Identifier", "");
-                if( osStyle.size() && strcmp(osStyle, l_pszIdentifier) != 0 )
+                if( !osStyle.empty() && strcmp(osStyle, l_pszIdentifier) != 0 )
                     continue;
                 const char* pszStyleTitle = CPLGetXMLValue(
                                         psSubIter, "Title", l_pszIdentifier);
@@ -1216,7 +1279,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                     aosStylesTitle.insert(aosStylesTitle.begin(),
                                             CPLString(pszStyleTitle));
                     if( strcmp(osSelectLayer, l_pszIdentifier) == 0 &&
-                        osSelectStyle.size() == 0 )
+                        osSelectStyle.empty() )
                     {
                         osSelectStyle = l_pszIdentifier;
                     }
@@ -1232,7 +1295,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                       strcmp(psSubIter->pszValue, "WGS84BoundingBox") == 0) )
             {
                 CPLString osCRS = CPLGetXMLValue(psSubIter, "crs", "");
-                if( osCRS.size() == 0 )
+                if( osCRS.empty() )
                 {
                     if( strcmp(psSubIter->pszValue, "WGS84BoundingBox") == 0 )
                     {
@@ -1254,7 +1317,8 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                         {
                             // For 13-082_WMTS_Simple_Profile/schemas/wmts/1.0/profiles/WMTSSimple/examples/wmtsGetCapabilities_response_OSM.xml
                             WMTSTileMatrixSet oTMS;
-                            if( ReadTMS(psContents, osSingleTileMatrixSet, oTMS) )
+                            if( ReadTMS(psContents, osSingleTileMatrixSet,
+                                        CPLString(), -1, oTMS) )
                             {
                                 osCRS = oTMS.osSRS;
                             }
@@ -1264,7 +1328,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                 CPLString osLowerCorner = CPLGetXMLValue(psSubIter, "LowerCorner", "");
                 CPLString osUpperCorner = CPLGetXMLValue(psSubIter, "UpperCorner", "");
                 OGRSpatialReference oSRS;
-                if( osCRS.size() && osLowerCorner.size() && osUpperCorner.size() &&
+                if( !osCRS.empty() && !osLowerCorner.empty() && !osUpperCorner.empty() &&
                     oSRS.SetFromUserInput(FixCRSName(osCRS)) == OGRERR_NONE )
                 {
                     int bSwap = oSRS.EPSGTreatsAsLatLong() ||
@@ -1290,23 +1354,23 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                 if( EQUAL(CPLGetXMLValue(psSubIter, "resourceType", ""), "tile") )
                 {
                     const char* pszFormat = CPLGetXMLValue(psSubIter, "format", "");
-                    if( osTileFormat.size() && strcmp(osTileFormat, pszFormat) != 0 )
+                    if( !osTileFormat.empty() && strcmp(osTileFormat, pszFormat) != 0 )
                         continue;
-                    if( osURLTileTemplate.size() == 0 )
+                    if( osURLTileTemplate.empty() )
                         osURLTileTemplate = CPLGetXMLValue(psSubIter, "template", "");
                 }
                 else if( EQUAL(CPLGetXMLValue(psSubIter, "resourceType", ""), "FeatureInfo") )
                 {
                     const char* pszFormat = CPLGetXMLValue(psSubIter, "format", "");
-                    if( osInfoFormat.size() && strcmp(osInfoFormat, pszFormat) != 0 )
+                    if( !osInfoFormat.empty() && strcmp(osInfoFormat, pszFormat) != 0 )
                         continue;
-                    if( osURLFeatureInfoTemplate.size() == 0 )
+                    if( osURLFeatureInfoTemplate.empty() )
                         osURLFeatureInfoTemplate = CPLGetXMLValue(psSubIter, "template", "");
                 }
             }
         }
         if( strcmp(osSelectLayer, pszIdentifier) == 0 &&
-            osSelectStyle.size() == 0 && aosStylesIdentifier.size() > 0 )
+            osSelectStyle.empty() && !aosStylesIdentifier.empty() )
         {
             osSelectStyle = aosStylesIdentifier[0];
         }
@@ -1347,7 +1411,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                     CPLSPrintf("SUBDATASET_%d_DESC", nIdx), osDesc);
             }
         }
-        if( aosTMS.size() && aosStylesIdentifier.size() )
+        if( !aosTMS.empty() && !aosStylesIdentifier.empty() )
             nLayerCount ++;
         else
             CPLError(CE_Failure, CPLE_AppDefined, "Missing TileMatrixSetLink and/or Style");
@@ -1366,9 +1430,9 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
 
     if( nLayerCount == 1 )
     {
-        if( osSelectLayerTitle.size() )
+        if( !osSelectLayerTitle.empty() )
             poDS->SetMetadataItem("TITLE", osSelectLayerTitle);
-        if( osSelectLayerAbstract.size() )
+        if( !osSelectLayerAbstract.empty() )
             poDS->SetMetadataItem("ABSTRACT", osSelectLayerAbstract);
 
         poDS->papszHTTPOptions = BuildHTTPRequestOpts(osOtherXML);
@@ -1376,15 +1440,27 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
         poDS->osTMS = osSelectTMS;
 
         WMTSTileMatrixSet oTMS;
-        if( !ReadTMS(psContents, osSelectTMS, oTMS) )
+        if( !ReadTMS(psContents, osSelectTMS, osMaxTileMatrixIdentifier,
+                     nUserMaxZoomLevel, oTMS) )
         {
             CPLDestroyXMLNode(psXML);
             delete poDS;
             return NULL;
         }
 
+        const char* pszExtentMethod = CSLFetchNameValueDef(
+            poOpenInfo->papszOpenOptions, "EXTENT_METHOD", "AUTO");
+        ExtentMethod eExtentMethod = AUTO;
+        if( EQUAL(pszExtentMethod, "LAYER_BBOX") )
+            eExtentMethod = LAYER_BBOX;
+        else if( EQUAL(pszExtentMethod, "TILE_MATRIX_SET") )
+            eExtentMethod = TILE_MATRIX_SET;
+        else if( EQUAL(pszExtentMethod, "MOST_PRECISE_TILE_MATRIX") )
+            eExtentMethod = MOST_PRECISE_TILE_MATRIX;
+
         // Use in priority layer bounding box expressed in the SRS of the TMS
         if( (!bHasAOI || bExtendBeyondDateLine) &&
+            (eExtentMethod == AUTO || eExtentMethod == LAYER_BBOX) &&
             aoMapBoundingBox.find(oTMS.osSRS) != aoMapBoundingBox.end() )
         {
             if( !bHasAOI )
@@ -1468,10 +1544,10 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                                 poCT->Transform(1, &dfX2, &dfY2) )
                             {
                                 bExtendBeyondDateLine = TRUE;
-                                sAOI.MinX = MIN(dfX1, dfX2);
-                                sAOI.MinY = MIN(dfY1, dfY2);
-                                sAOI.MaxX = MAX(dfX1, dfX2);
-                                sAOI.MaxY = MAX(dfY1, dfY2);
+                                sAOI.MinX = std::min(dfX1, dfX2);
+                                sAOI.MinY = std::min(dfY1, dfY2);
+                                sAOI.MaxX = std::max(dfX1, dfX2);
+                                sAOI.MaxY = std::max(dfY1, dfY2);
                                 CPLDebug("WMTS",
                                          "ExtendBeyondDateLine using %s bounding box",
                                          oIter->first.c_str());
@@ -1495,9 +1571,10 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
             }
         }
 
-        // Otherwise default to reprojection a layer bounding box expressed in
+        // Otherwise default to reproject a layer bounding box expressed in
         // another SRS
-        if( !bHasAOI && aoMapBoundingBox.size() )
+        if( !bHasAOI && !aoMapBoundingBox.empty() &&
+            (eExtentMethod == AUTO || eExtentMethod == LAYER_BBOX) )
         {
             std::map<CPLString, OGREnvelope>::iterator oIter = aoMapBoundingBox.begin();
             for(; oIter != aoMapBoundingBox.end(); ++oIter )
@@ -1505,6 +1582,125 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                 OGRSpatialReference oSRS;
                 if( oSRS.SetFromUserInput(FixCRSName(oIter->first)) == OGRERR_NONE )
                 {
+                    // Check if this doesn't match the most precise tile matrix
+                    // by densifying its contour
+                    const WMTSTileMatrix& oTM = oTMS.aoTM.back();
+
+                    bool bMatchFound = false;
+                    const char *pszProjectionTMS = oTMS.oSRS.GetAttrValue("PROJECTION");
+                    const char *pszProjectionBBOX = oSRS.GetAttrValue("PROJECTION");
+                    const bool bIsTMerc = (pszProjectionTMS != NULL &&
+                        EQUAL(pszProjectionTMS, SRS_PT_TRANSVERSE_MERCATOR)) ||
+                        (pszProjectionBBOX != NULL &&
+                        EQUAL(pszProjectionBBOX, SRS_PT_TRANSVERSE_MERCATOR));
+                    // If one of the 2 SRS is a TMerc, try with classical tmerc
+                    // or etmerc.
+                    for( int j = 0; j < (bIsTMerc ? 2 : 1); j++ )
+                    {
+                        CPLString osOldVal =
+                            CPLGetThreadLocalConfigOption("OSR_USE_ETMERC", "");
+                        if( bIsTMerc )
+                        {
+                            CPLSetThreadLocalConfigOption("OSR_USE_ETMERC",
+                                                      (j==0) ? "NO" : "YES");
+                        }
+                        OGRCoordinateTransformation* poRevCT =
+                            OGRCreateCoordinateTransformation(&oTMS.oSRS, &oSRS);
+                        if( bIsTMerc )
+                        {
+                            CPLSetThreadLocalConfigOption("OSR_USE_ETMERC",
+                                osOldVal.empty() ? NULL : osOldVal.c_str());
+                        }
+                        if( poRevCT != NULL )
+                        {
+                            const double dfX0 = oTM.dfTLX;
+                            const double dfY1 = oTM.dfTLY;
+                            const double dfX1 = oTM.dfTLX +
+                            oTM.nMatrixWidth  * oTM.dfPixelSize * oTM.nTileWidth;
+                            const double dfY0 = oTM.dfTLY -
+                            oTM.nMatrixHeight * oTM.dfPixelSize * oTM.nTileHeight;
+                            double dfXMin = std::numeric_limits<double>::infinity();
+                            double dfYMin = std::numeric_limits<double>::infinity();
+                            double dfXMax = -std::numeric_limits<double>::infinity();
+                            double dfYMax = -std::numeric_limits<double>::infinity();
+
+                            const int NSTEPS = 20;
+                            for(int i=0;i<=NSTEPS;i++)
+                            {
+                                double dfX = dfX0 + (dfX1 - dfX0) * i / NSTEPS;
+                                double dfY = dfY0;
+                                if( poRevCT->Transform(1, &dfX, &dfY) )
+                                {
+                                    dfXMin = std::min(dfXMin, dfX);
+                                    dfYMin = std::min(dfYMin, dfY);
+                                    dfXMax = std::max(dfXMax, dfX);
+                                    dfYMax = std::max(dfYMax, dfY);
+                                }
+
+                                dfX = dfX0 + (dfX1 - dfX0) * i / NSTEPS;
+                                dfY = dfY1;
+                                if( poRevCT->Transform(1, &dfX, &dfY) )
+                                {
+                                    dfXMin = std::min(dfXMin, dfX);
+                                    dfYMin = std::min(dfYMin, dfY);
+                                    dfXMax = std::max(dfXMax, dfX);
+                                    dfYMax = std::max(dfYMax, dfY);
+                                }
+
+                                dfX = dfX0;
+                                dfY = dfY0 + (dfY1 - dfY0) * i / NSTEPS;
+                                if( poRevCT->Transform(1, &dfX, &dfY) )
+                                {
+                                    dfXMin = std::min(dfXMin, dfX);
+                                    dfYMin = std::min(dfYMin, dfY);
+                                    dfXMax = std::max(dfXMax, dfX);
+                                    dfYMax = std::max(dfYMax, dfY);
+                                }
+
+                                dfX = dfX1;
+                                dfY = dfY0 + (dfY1 - dfY0) * i / NSTEPS;
+                                if( poRevCT->Transform(1, &dfX, &dfY) )
+                                {
+                                    dfXMin = std::min(dfXMin, dfX);
+                                    dfYMin = std::min(dfYMin, dfY);
+                                    dfXMax = std::max(dfXMax, dfX);
+                                    dfYMax = std::max(dfYMax, dfY);
+                                }
+                            }
+
+                            delete poRevCT;
+#ifdef DEBUG_VERBOSE
+                            CPLDebug("WMTS", "Reprojected densified bbox of most "
+                                    "precise tile matrix in %s: %.8g %8g %8g %8g",
+                                    oIter->first.c_str(),
+                                    dfXMin, dfYMin, dfXMax, dfYMax);
+#endif
+                            if( fabs(oIter->second.MinX - dfXMin) < 1e-5 *
+                                std::max(fabs(oIter->second.MinX),fabs(dfXMin)) &&
+                                fabs(oIter->second.MinY - dfYMin) < 1e-5 *
+                                std::max(fabs(oIter->second.MinY),fabs(dfYMin)) &&
+                                fabs(oIter->second.MaxX - dfXMax) < 1e-5 *
+                                std::max(fabs(oIter->second.MaxX),fabs(dfXMax)) &&
+                                fabs(oIter->second.MaxY - dfYMax) < 1e-5 *
+                                std::max(fabs(oIter->second.MaxY),fabs(dfYMax)) )
+                            {
+                                bMatchFound = true;
+#ifdef DEBUG_VERBOSE
+                                CPLDebug("WMTS", "Matches layer bounding box, so "
+                                        "that one is not significant");
+#endif
+                                break;
+                            }
+                        }
+                    }
+
+                    if( bMatchFound )
+                    {
+                        if( eExtentMethod == LAYER_BBOX )
+                            eExtentMethod = MOST_PRECISE_TILE_MATRIX;
+                        break;
+                    }
+
                     OGRCoordinateTransformation* poCT =
                         OGRCreateCoordinateTransformation(&oSRS, &oTMS.oSRS);
                     if( poCT != NULL )
@@ -1522,10 +1718,14 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                             poCT->Transform(1, &dfX3, &dfY3) &&
                             poCT->Transform(1, &dfX4, &dfY4) )
                         {
-                            sAOI.MinX = MIN(MIN(dfX1, dfX2),MIN(dfX3,dfX4));
-                            sAOI.MinY = MIN(MIN(dfY1, dfY2),MIN(dfY3,dfY4));
-                            sAOI.MaxX = MAX(MAX(dfX1, dfX2),MAX(dfX3,dfX4));
-                            sAOI.MaxY = MAX(MAX(dfY1, dfY2),MAX(dfY3,dfY4));
+                            sAOI.MinX = std::min(std::min(dfX1, dfX2),
+                                                 std::min(dfX3, dfX4));
+                            sAOI.MinY = std::min(std::min(dfY1, dfY2),
+                                                 std::min(dfY3, dfY4));
+                            sAOI.MaxX = std::max(std::max(dfX1, dfX2),
+                                                 std::max(dfX3, dfX4));
+                            sAOI.MaxY = std::max(std::max(dfY1, dfY2),
+                                                 std::max(dfY3, dfY4));
                             bHasAOI = TRUE;
                         }
                         delete poCT;
@@ -1536,7 +1736,8 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
         }
 
         // Otherwise default to BoundingBox of the TMS
-        if( !bHasAOI && oTMS.bBoundingBoxValid )
+        if( !bHasAOI && oTMS.bBoundingBoxValid &&
+            (eExtentMethod == AUTO || eExtentMethod == TILE_MATRIX_SET) )
         {
             CPLDebug("WMTS", "Using TMS bounding box");
             sAOI = oTMS.sBoundingBox;
@@ -1544,43 +1745,63 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
         }
 
         // Otherwise default to implied BoundingBox of the most precise TM
-        if( !bHasAOI )
+        if( !bHasAOI &&
+            (eExtentMethod == AUTO || eExtentMethod == MOST_PRECISE_TILE_MATRIX) )
         {
-            const WMTSTileMatrix& oTM = oTMS.aoTM[oTMS.aoTM.size()-1];
+            const WMTSTileMatrix& oTM = oTMS.aoTM.back();
             CPLDebug("WMTS", "Using TM level %s bounding box", oTM.osIdentifier.c_str() );
 
             sAOI.MinX = oTM.dfTLX;
             sAOI.MaxY = oTM.dfTLY;
             sAOI.MaxX = oTM.dfTLX + oTM.nMatrixWidth  * oTM.dfPixelSize * oTM.nTileWidth;
             sAOI.MinY = oTM.dfTLY - oTM.nMatrixHeight * oTM.dfPixelSize * oTM.nTileHeight;
-            /*bHasAOI = TRUE;*/
+            bHasAOI = TRUE;
         }
-        else
+
+        if( !bHasAOI )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Could not determine raster extent");
+            CPLDestroyXMLNode(psXML);
+            delete poDS;
+            return NULL;
+        }
+
         {
             // Clip with implied BoundingBox of the most precise TM
             // Useful for http://tileserver.maptiler.com/wmts
-            const WMTSTileMatrix& oTM = oTMS.aoTM[oTMS.aoTM.size()-1];
+            const WMTSTileMatrix& oTM = oTMS.aoTM.back();
 
             // For https://data.linz.govt.nz/services;key=XXXXXXXX/wmts/1.0.0/set/69/WMTSCapabilities.xml
-            // only clip in Y since there's a warp over dateline
-            //sAOI.MinX = MAX(sAOI.MinX, oTM.dfTLX);
-            sAOI.MaxY = MIN(sAOI.MaxY, oTM.dfTLY);
-            //sAOI.MaxX = MIN(sAOI.MaxX, oTM.dfTLX + oTM.nMatrixWidth  * oTM.dfPixelSize * oTM.nTileWidth);
-            sAOI.MinY = MAX(sAOI.MinY, oTM.dfTLY - oTM.nMatrixHeight * oTM.dfPixelSize * oTM.nTileHeight);
+            // only clip in Y since there's a warp over dateline.
+            // Update: it sems that the content of the server has changed since
+            // initial coding. So do X clipping in default mode.
+            if( !bExtendBeyondDateLine )
+            {
+                sAOI.MinX = std::max(sAOI.MinX, oTM.dfTLX);
+                sAOI.MaxX = std::min(sAOI.MaxX,
+                    oTM.dfTLX +
+                    oTM.nMatrixWidth  * oTM.dfPixelSize * oTM.nTileWidth);
+            }
+            sAOI.MaxY = std::min(sAOI.MaxY, oTM.dfTLY);
+            sAOI.MinY =
+                std::max(sAOI.MinY,
+                         oTM.dfTLY -
+                         oTM.nMatrixHeight * oTM.dfPixelSize * oTM.nTileHeight);
         }
 
         // Clip with limits of most precise TM when available
         {
-            const WMTSTileMatrix& oTM = oTMS.aoTM[oTMS.aoTM.size()-1];
+            const WMTSTileMatrix& oTM = oTMS.aoTM.back();
             if( aoMapTileMatrixLimits.find(oTM.osIdentifier) != aoMapTileMatrixLimits.end() )
             {
                 const WMTSTileMatrixLimits& oTMLimits = aoMapTileMatrixLimits[oTM.osIdentifier];
                 double dfTileWidthUnits = oTM.dfPixelSize * oTM.nTileWidth;
                 double dfTileHeightUnits = oTM.dfPixelSize * oTM.nTileHeight;
-                sAOI.MinX = MAX(sAOI.MinX, oTM.dfTLX + oTMLimits.nMinTileCol * dfTileWidthUnits);
-                sAOI.MaxY = MIN(sAOI.MaxY, oTM.dfTLY - oTMLimits.nMinTileRow * dfTileHeightUnits);
-                sAOI.MaxX = MIN(sAOI.MaxX, oTM.dfTLX + (oTMLimits.nMaxTileCol + 1) * dfTileWidthUnits);
-                sAOI.MinY = MAX(sAOI.MinY, oTM.dfTLY - (oTMLimits.nMaxTileRow + 1) * dfTileHeightUnits);
+                sAOI.MinX = std::max(sAOI.MinX, oTM.dfTLX + oTMLimits.nMinTileCol * dfTileWidthUnits);
+                sAOI.MaxY = std::min(sAOI.MaxY, oTM.dfTLY - oTMLimits.nMinTileRow * dfTileHeightUnits);
+                sAOI.MaxX = std::min(sAOI.MaxX, oTM.dfTLX + (oTMLimits.nMaxTileCol + 1) * dfTileWidthUnits);
+                sAOI.MinY = std::max(sAOI.MinY, oTM.dfTLY - (oTMLimits.nMaxTileRow + 1) * dfTileHeightUnits);
             }
         }
 
@@ -1597,7 +1818,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                 {
                     CPLDebug("WMTS", "Using zoom level %s instead of %s to avoid int overflow",
                              oTMS.aoTM[nMaxZoomLevel].osIdentifier.c_str(),
-                             oTMS.aoTM[(int)oTMS.aoTM.size()-1].osIdentifier.c_str());
+                             oTMS.aoTM.back().osIdentifier.c_str());
                 }
 
                 // Align AOI on pixel boundaries with respect to TopLeftCorner of
@@ -1622,10 +1843,12 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
             delete poDS;
             return NULL;
         }
+        CPLDebug("WMTS", "Using tilematrix=%s (zoom level %d)",
+                 oTMS.aoTM[nMaxZoomLevel].osIdentifier.c_str(), nMaxZoomLevel);
         oTMS.aoTM.resize(1 + nMaxZoomLevel);
         poDS->oTMS = oTMS;
 
-        if( osProjection.size() )
+        if( !osProjection.empty() )
         {
             OGRSpatialReference oSRS;
             if( oSRS.SetFromUserInput(osProjection) == OGRERR_NONE )
@@ -1636,7 +1859,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
                 CPLFree(pszWKT);
             }
         }
-        if( poDS->osProjection.size() == 0 )
+        if( poDS->osProjection.empty() )
         {
             // Strip AXIS
             OGR_SRSNode *poGEOGCS = oTMS.oSRS.GetAttrNode( "GEOGCS" );
@@ -1653,10 +1876,10 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
             CPLFree(pszWKT);
         }
 
-        if( osURLTileTemplate.size() == 0 )
+        if( osURLTileTemplate.empty() )
         {
             osURLTileTemplate = GetOperationKVPURL(psXML, "GetTile");
-            if( osURLTileTemplate.size() == 0 )
+            if( osURLTileTemplate.empty() )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "No RESTful nor KVP GetTile operation found");
@@ -1700,10 +1923,10 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
             }
         }
 
-        if( osURLFeatureInfoTemplate.size() == 0 && osSelectInfoFormat.size() != 0 )
+        if( osURLFeatureInfoTemplate.empty() && !osSelectInfoFormat.empty() )
         {
             osURLFeatureInfoTemplate = GetOperationKVPURL(psXML, "GetFeatureInfo");
-            if( osURLFeatureInfoTemplate.size() != 0 )
+            if( !osURLFeatureInfoTemplate.empty() )
             {
                 osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate, "service", "WMTS");
                 osURLFeatureInfoTemplate = CPLURLAddKVP(osURLFeatureInfoTemplate, "request", "GetFeatureInfo");
@@ -1749,7 +1972,8 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
             const WMTSTileMatrix& oTM = oTMS.aoTM[i];
             int nRasterXSize = int(0.5 + poDS->nRasterXSize / oTM.dfPixelSize * poDS->adfGT[1]);
             int nRasterYSize = int(0.5 + poDS->nRasterYSize / oTM.dfPixelSize * poDS->adfGT[1]);
-            if( nRasterXSize < 128 || nRasterYSize < 128 )
+            if( !poDS->apoDatasets.empty() &&
+                (nRasterXSize < 128 || nRasterYSize < 128) )
             {
                 break;
             }
@@ -1777,7 +2001,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
             double dfDateLineX = oTM.dfTLX + oTM.nMatrixWidth * dfTileWidthUnits;
             int nSizeX1 = int(0.5+(dfDateLineX - dfULX) / oTM.dfPixelSize);
             int nSizeX2 = int(0.5+(dfLRX - dfDateLineX) / oTM.dfPixelSize);
-            if( dfDateLineX > dfLRX )
+            if( bExtendBeyondDateLine && dfDateLineX > dfLRX )
             {
                 CPLDebug("WMTS", "ExtendBeyondDateLine ignored in that case");
                 bExtendBeyondDateLine = FALSE;
@@ -1887,7 +2111,7 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
             poDS->apoDatasets.push_back((GDALDataset*)hVRTDS);
         }
 
-        if( poDS->apoDatasets.size() == 0 )
+        if( poDS->apoDatasets.empty() )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "No zoom level found");
             CPLDestroyXMLNode(psXML);
@@ -1903,15 +2127,19 @@ GDALDataset* WMTSDataset::Open(GDALOpenInfo* poOpenInfo)
         poDS->osXML += "  <GetCapabilitiesUrl>" +
                      WMTSEscapeXML(osGetCapabilitiesURL) +
                      "</GetCapabilitiesUrl>\n";
-        if( osSelectLayer.size() )
+        if( !osSelectLayer.empty() )
             poDS->osXML += "  <Layer>" + WMTSEscapeXML(osSelectLayer) + "</Layer>\n";
-        if( osSelectStyle.size() )
+        if( !osSelectStyle.empty() )
             poDS->osXML += "  <Style>" + WMTSEscapeXML(osSelectStyle) + "</Style>\n";
-        if( osSelectTMS.size() )
+        if( !osSelectTMS.empty() )
             poDS->osXML += "  <TileMatrixSet>" + WMTSEscapeXML(osSelectTMS) + "</TileMatrixSet>\n";
-        if( nCountTileFormat > 1 && osSelectTileFormat.size() )
+        if( !osMaxTileMatrixIdentifier.empty() )
+            poDS->osXML += "  <TileMatrix>" + WMTSEscapeXML(osMaxTileMatrixIdentifier) + "</TileMatrix>\n";
+        if( nUserMaxZoomLevel >= 0 )
+            poDS->osXML += "  <ZoomLevel>" + CPLString().Printf("%d", nUserMaxZoomLevel) + "</ZoomLevel>\n";
+        if( nCountTileFormat > 1 && !osSelectTileFormat.empty() )
             poDS->osXML += "  <Format>" + WMTSEscapeXML(osSelectTileFormat) + "</Format>\n";
-        if( nCountInfoFormat > 1 && osSelectInfoFormat.size() )
+        if( nCountInfoFormat > 1 && !osSelectInfoFormat.empty() )
             poDS->osXML += "  <InfoFormat>" + WMTSEscapeXML(osSelectInfoFormat) + "</InfoFormat>\n";
         poDS->osXML += "  <DataWindow>\n";
         poDS->osXML += CPLSPrintf("    <UpperLeftX>%.16g</UpperLeftX>\n",
@@ -2005,8 +2233,16 @@ void GDALRegister_WMTS()
 "  <Option name='URL' type='string' description='URL that points to GetCapabilities response' required='YES'/>"
 "  <Option name='LAYER' type='string' description='Layer identifier'/>"
 "  <Option name='TILEMATRIXSET' alias='TMS' type='string' description='Tile matrix set identifier'/>"
+"  <Option name='TILEMATRIX' type='string' description='Tile matrix identifier of maximum zoom level. Exclusive with ZOOM_LEVEL.'/>"
+"  <Option name='ZOOM_LEVEL' alias='ZOOMLEVEL' type='int' description='Maximum zoom level. Exclusive with TILEMATRIX.'/>"
 "  <Option name='STYLE' type='string' description='Style identifier'/>"
 "  <Option name='EXTENDBEYONDDATELINE' type='boolean' description='Whether to enable extend-beyond-dateline behaviour' default='NO'/>"
+"  <Option name='EXTENT_METHOD' type='string-select' description='How the raster extent is computed' default='AUTO'>"
+"       <Value>AUTO</Value>"
+"       <Value>LAYER_BBOX</Value>"
+"       <Value>TILE_MATRIX_SET</Value>"
+"       <Value>MOST_PRECISE_TILE_MATRIX</Value>"
+"  </Option>"
 "</OpenOptionList>");
 
     poDriver->pfnOpen = WMTSDataset::Open;
diff --git a/frmts/xpm/xpmdataset.cpp b/frmts/xpm/xpmdataset.cpp
index 62f5416..65d43f7 100644
--- a/frmts/xpm/xpmdataset.cpp
+++ b/frmts/xpm/xpmdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: xpmdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  XPM Driver
  * Purpose:  Implement GDAL XPM Support
@@ -33,7 +32,10 @@
 #include "memdataset.h"
 #include "gdal_frmts.h"
 
-CPL_CVSID("$Id: xpmdataset.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <cstdlib>
+#include <algorithm>
+
+CPL_CVSID("$Id: xpmdataset.cpp 36436 2016-11-22 21:41:51Z rouault $");
 
 static unsigned char *ParseXPM( const char *pszInput,
                                 unsigned int nFileSize,
@@ -42,7 +44,7 @@ static unsigned char *ParseXPM( const char *pszInput,
 
 /************************************************************************/
 /* ==================================================================== */
-/*				XPMDataset				*/
+/*                              XPMDataset                              */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -161,7 +163,7 @@ GDALDataset *XPMDataset::Open( GDALOpenInfo * poOpenInfo )
 /* -------------------------------------------------------------------- */
 /*      Create a corresponding GDALDataset.                             */
 /* -------------------------------------------------------------------- */
-    XPMDataset 	*poDS = new XPMDataset();
+    XPMDataset *poDS = new XPMDataset();
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file that is of interest.     */
@@ -265,7 +267,7 @@ XPMCreateCopy( const char * pszFilename,
 
     int  anPixelMapping[256];
     GDALColorEntry asPixelColor[256];
-    int nActiveColors = MIN(poCT->GetColorEntryCount(),256);
+    int nActiveColors = std::min(poCT->GetColorEntryCount(),256);
 
     // Setup initial colortable and pixel value mapping.
     memset( anPixelMapping+0, 0, sizeof(int) * 256 );
@@ -296,9 +298,12 @@ XPMCreateCopy( const char * pszFilename,
                     nDistance = 0;
                 else
                     nDistance =
-                        ABS(asPixelColor[iColor1].c1-asPixelColor[iColor2].c1)
-                      + ABS(asPixelColor[iColor1].c2-asPixelColor[iColor2].c2)
-                      + ABS(asPixelColor[iColor1].c3-asPixelColor[iColor2].c3);
+                        std::abs(asPixelColor[iColor1].c1 -
+                                 asPixelColor[iColor2].c1)
+                        + std::abs(asPixelColor[iColor1].c2 -
+                                   asPixelColor[iColor2].c2)
+                        + std::abs(asPixelColor[iColor1].c3 -
+                                   asPixelColor[iColor2].c3);
 
                 if( nDistance < nClosestDistance )
                 {
@@ -376,7 +381,7 @@ XPMCreateCopy( const char * pszFilename,
     }
 
 /* -------------------------------------------------------------------- */
-/*	Dump image.							*/
+/*      Dump image.                                                     */
 /* -------------------------------------------------------------------- */
     GByte *pabyScanline = reinterpret_cast<GByte *>( CPLMalloc( nXSize ) );
 
@@ -587,7 +592,7 @@ ParseXPM( const char *pszInput,
         anCharLookup[*(reinterpret_cast<GByte*>(papszXPMList[iColor+1]))] = iColor;
 
         GDALColorEntry sColor;
-        int nRed, nGreen, nBlue;
+        unsigned int nRed, nGreen, nBlue;
 
         if( EQUAL(papszTokens[1],"None") )
         {
@@ -647,10 +652,10 @@ ParseXPM( const char *pszInput,
             return NULL;
         }
 
-        for( int iPixel = 0;
-             pabyInLine[iPixel] != '\0' && iPixel < *pnXSize;
-             iPixel++ )
+        for( int iPixel = 0; iPixel < *pnXSize; iPixel++ )
         {
+            if( pabyInLine[iPixel] == '\0' )
+                break;
             const int nPixelValue
                 = anCharLookup[pabyInLine[iPixel]];
             if( nPixelValue != -1 )
diff --git a/frmts/xyz/xyzdataset.cpp b/frmts/xyz/xyzdataset.cpp
index 64aec58..fa7b53f 100644
--- a/frmts/xyz/xyzdataset.cpp
+++ b/frmts/xyz/xyzdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: xyzdataset.cpp 34022 2016-04-18 19:53:58Z rouault $
  *
  * Project:  XYZ driver
  * Purpose:  GDALDataset driver for XYZ dataset.
@@ -35,7 +34,7 @@
 #include <algorithm>
 #include <vector>
 
-CPL_CVSID("$Id: xyzdataset.cpp 34022 2016-04-18 19:53:58Z rouault $");
+CPL_CVSID("$Id: xyzdataset.cpp 36822 2016-12-12 11:18:45Z rouault $");
 
 static const double RELATIVE_ERROR = 1e-3;
 
@@ -72,7 +71,7 @@ class XYZDataset : public GDALPamDataset
                  XYZDataset();
     virtual     ~XYZDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -97,13 +96,12 @@ class XYZRasterBand : public GDALPamRasterBand
 
                 XYZRasterBand( XYZDataset *, int, GDALDataType );
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual double GetMinimum( int *pbSuccess = NULL );
-    virtual double GetMaximum( int *pbSuccess = NULL );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual double GetMinimum( int *pbSuccess = NULL ) override;
+    virtual double GetMaximum( int *pbSuccess = NULL ) override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 };
 
-
 /************************************************************************/
 /*                           XYZRasterBand()                            */
 /************************************************************************/
@@ -262,7 +260,9 @@ CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
             char ch;
             nCol = 0;
             bLastWasSep = true;
-            double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
+            double dfX = 0.0;
+            double dfY = 0.0;
+            double dfZ = 0.0;
             int nUsefulColsFound = 0;
             while((ch = *pszPtr) != '\0')
             {
@@ -450,7 +450,7 @@ XYZDataset::XYZDataset() :
     nZIndex(-1),
     nMinTokens(0),
     nLineNum(0),
-    nDataLineNum(((GIntBig)0x7FFFFFFF) << 32 | 0xFFFFFFFF),
+    nDataLineNum(GINTBIG_MAX),
     bSameNumberOfValuesPerLine(TRUE),
     dfMinZ(0),
     dfMaxZ(0)
@@ -489,7 +489,6 @@ int XYZDataset::Identify( GDALOpenInfo * poOpenInfo )
 /*                            IdentifyEx()                              */
 /************************************************************************/
 
-
 int XYZDataset::IdentifyEx( GDALOpenInfo * poOpenInfo,
                             int& bHasHeaderLine,
                             int& nCommentLineCount)
@@ -657,7 +656,9 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
             VSICreateBufferedReaderHandle(
                 reinterpret_cast<VSIVirtualHandle *>( fp ) ) );
 
-    int nXIndex = -1, nYIndex = -1, nZIndex = -1;
+    int nXIndex = -1;
+    int nYIndex = -1;
+    int nZIndex = -1;
     int nMinTokens = 0;
 
     for( int i = 0; i < nCommentLineCount; i++ )
@@ -711,7 +712,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
             nYIndex = 1;
             nZIndex = 2;
         }
-        nMinTokens = 1 + MAX(MAX(nXIndex, nYIndex), nZIndex);
+        nMinTokens = 1 + std::max(std::max(nXIndex, nYIndex), nZIndex);
     }
     else
     {
@@ -727,11 +728,19 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 
     GIntBig nLineNum = 0;
     GIntBig nDataLineNum = 0;
-    double dfX = 0, dfY = 0, dfZ = 0;
-    double dfMinX = 0, dfMinY = 0, dfMaxX = 0, dfMaxY = 0;
-    double dfMinZ = 0, dfMaxZ = 0;
-    double dfLastX = 0, dfLastY = 0;
-    std::vector<double> adfStepX, adfStepY;
+    double dfX = 0.0;
+    double dfY = 0.0;
+    double dfZ = 0.0;
+    double dfMinX = 0.0;
+    double dfMinY = 0.0;
+    double dfMaxX = 0.0;
+    double dfMaxY = 0.0;
+    double dfMinZ = 0.0;
+    double dfMaxZ = 0.0;
+    double dfLastX = 0.0;
+    double dfLastY = 0.0;
+    std::vector<double> adfStepX;
+    std::vector<double> adfStepY;
     GDALDataType eDT = GDT_Byte;
     bool bSameNumberOfValuesPerLine = true;
     char chDecimalSep = '\0';
@@ -818,11 +827,19 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                     {
                         dfZ = CPLAtofDelim(pszPtr, chLocalDecimalSep);
                         if( nDataLineNum == 0 )
-                            dfMinZ = dfMaxZ = dfZ;
+                        {
+                            dfMinZ = dfZ;
+                            dfMaxZ = dfZ;
+                        }
                         else if( dfZ < dfMinZ )
+                        {
                             dfMinZ = dfZ;
+                        }
                         else if( dfZ > dfMaxZ )
+                        {
                             dfMaxZ = dfZ;
+                        }
+
                         if( dfZ < INT_MIN || dfZ > INT_MAX )
                         {
                             eDT = GDT_Float32;
@@ -867,15 +884,17 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 
         if (nDataLineNum == 1)
         {
-            dfMinX = dfMaxX = dfX;
-            dfMinY = dfMaxY = dfY;
+            dfMinX = dfX;
+            dfMaxX = dfX;
+            dfMinY = dfY;
+            dfMaxY = dfY;
         }
         else
         {
             double dfStepY = dfY - dfLastY;
             if( dfStepY == 0.0 )
             {
-                double dfStepX = dfX - dfLastX;
+                const double dfStepX = dfX - dfLastX;
                 if( dfStepX <= 0 )
                 {
                     CPLError(CE_Failure, CPLE_AppDefined,
@@ -887,21 +906,23 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                 if( std::find(adfStepX.begin(), adfStepX.end(), dfStepX) == adfStepX.end() )
                 {
                     bool bAddNewValue = true;
-                    // TODO: Danger!  Erase called on the iterator.
                     std::vector<double>::iterator oIter = adfStepX.begin();
+                    std::vector<double> adfStepXNew;
                     while( oIter != adfStepX.end() )
                     {
                         if( fabs(( dfStepX - *oIter ) / dfStepX ) < RELATIVE_ERROR )
                         {
+                            double dfNewVal = *oIter;
                             if( nCountStepX > 0 )
                             {
                                 // Update mean step
                                 /* n * mean(n) = (n-1) * mean(n-1) + val(n)
                                 mean(n) = mean(n-1) + (val(n) - mean(n-1)) / n */
                                 nCountStepX ++;
-                                *oIter += ( dfStepX - *oIter ) / nCountStepX;
+                                dfNewVal += ( dfStepX - *oIter ) / nCountStepX;
                             }
 
+                            adfStepXNew.push_back( dfNewVal );
                             bAddNewValue = false;
                             break;
                         }
@@ -909,20 +930,22 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                                  fabs(*oIter - static_cast<int>(*oIter / dfStepX + 0.5) * dfStepX) / dfStepX < RELATIVE_ERROR )
                         {
                             nCountStepX = -1; // disable update of mean
-                            adfStepX.erase(oIter);
                         }
                         else if( dfStepX > *oIter &&
                                  fabs(dfStepX - static_cast<int>(dfStepX / *oIter + 0.5) * (*oIter)) / dfStepX < RELATIVE_ERROR )
                         {
                             nCountStepX = -1; // disable update of mean
                             bAddNewValue = false;
+                            adfStepXNew.push_back( *oIter );
                             break;
                         }
                         else
                         {
+                            adfStepXNew.push_back( *oIter );
                             ++ oIter;
                         }
                     }
+                    adfStepX = adfStepXNew;
                     if( bAddNewValue )
                     {
                         CPLDebug("XYZ", "New stepX=%.15f", dfStepX);
@@ -960,7 +983,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
                 }
                 if( bNewStepYSign < 0 ) dfStepY = -dfStepY;
                 nCountStepY ++;
-                if( adfStepY.size() == 0 )
+                if( adfStepY.empty() )
                 {
                     adfStepY.push_back(dfStepY);
                 }
@@ -1085,7 +1108,7 @@ GDALDataset *XYZDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Support overviews.                                              */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
-    return( poDS );
+    return poDS;
 }
 
 /************************************************************************/
@@ -1275,7 +1298,7 @@ CPLErr XYZDataset::GetGeoTransform( double * padfTransform )
 {
     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
diff --git a/frmts/zlib/README b/frmts/zlib/README
index 1ae6df7..f187b5d 100644
--- a/frmts/zlib/README
+++ b/frmts/zlib/README
@@ -1,8 +1,8 @@
-$Id: README 31826 2015-11-29 15:39:57Z goatbar $
+$Id: README 35222 2016-08-28 06:06:11Z goatbar $
 
 zlib 1.2.3 is a general purpose data compression library.
 All the code is thread safe. The data format used by the zlib library
-is described by RFCs (Request for Comments) 1950 to 1952 in the files 
+is described by RFCs (Request for Comments) 1950 to 1952 in the files
 ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
 format) and rfc1952.txt (gzip format). These documents are also available in
 other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
@@ -92,7 +92,7 @@ Notes for some targets:
   With -O, one libpng test fails. The test works in 32 bit mode (with
   the -n32 compiler flag). The compiler bug has been reported to SGI.
 
-- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1   
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1
   it works when compiled with cc.
 
 - on Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1
diff --git a/frmts/zlib/deflate.c b/frmts/zlib/deflate.c
index 6560287..be3595e 100644
--- a/frmts/zlib/deflate.c
+++ b/frmts/zlib/deflate.c
@@ -47,7 +47,7 @@
  *
  */
 
-/* @(#) $Id: deflate.c 10656 2007-01-19 01:31:01Z mloskot $ */
+/* @(#) $Id: deflate.c 36393 2016-11-21 14:25:42Z rouault $ */
 
 #include "deflate.h"
 
@@ -1245,7 +1245,7 @@ local void check_match(s, start, match, length)
         z_error("invalid match");
     }
     if (z_verbose > 1) {
-        fprintf(stderr,"\\[%d,%d]", start-match, length);
+        fprintf(stderr,"\\[%u,%d]", start-match, length);
         do { putc(s->window[start++], stderr); } while (--length != 0);
     }
 }
diff --git a/frmts/zlib/inflate.c b/frmts/zlib/inflate.c
index a6c40dd..25ef2bd 100644
--- a/frmts/zlib/inflate.c
+++ b/frmts/zlib/inflate.c
@@ -629,7 +629,7 @@ int flush;
             state->dmax = 1U << len;
             Tracev((stderr, "inflate:   zlib header ok\n"));
             strm->adler = state->check = adler32(0L, Z_NULL, 0);
-            state->mode = hold & 0x200 ? DICTID : TYPE;
+            state->mode = (hold & 0x200) ? DICTID : TYPE;
             INITBITS();
             break;
 #ifdef GUNZIP
diff --git a/frmts/zlib/trees.c b/frmts/zlib/trees.c
index 8faf40e..2011f28 100644
--- a/frmts/zlib/trees.c
+++ b/frmts/zlib/trees.c
@@ -29,7 +29,7 @@
  *          Addison-Wesley, 1983. ISBN 0-201-06672-6.
  */
 
-/* @(#) $Id: trees.c 10656 2007-01-19 01:31:01Z mloskot $ */
+/* @(#) $Id: trees.c 36402 2016-11-21 16:04:04Z rouault $ */
 
 /* #define GEN_TREES_H */
 
@@ -169,7 +169,7 @@ local void gen_trees_header OF((void));
 
 #else /* DEBUG */
 #  define send_code(s, c, tree) \
-     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+     { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(int)(c)); \
        send_bits(s, tree[c].Code, tree[c].Len); }
 #endif
 
@@ -824,7 +824,7 @@ local int build_bl_tree(s)
     }
     /* Update opt_len to include the bit length tree and counts */
     s->opt_len += 3*(max_blindex+1) + 5+5+4;
-    Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+    Tracev((stderr, "\ndyn trees: dyn %lu, stat %lu",
             s->opt_len, s->static_len));
 
     return max_blindex;
@@ -849,16 +849,16 @@ local void send_all_trees(s, lcodes, dcodes, blcodes)
     send_bits(s, dcodes-1,   5);
     send_bits(s, blcodes-4,  4); /* not -3 as stated in appnote.txt */
     for (rank = 0; rank < blcodes; rank++) {
-        Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+        Tracev((stderr, "\nbl code %2u ", bl_order[rank]));
         send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
     }
-    Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+    Tracev((stderr, "\nbl tree: sent %lu", s->bits_sent));
 
     send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
-    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+    Tracev((stderr, "\nlit tree: sent %lu", s->bits_sent));
 
     send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
-    Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+    Tracev((stderr, "\ndist tree: sent %lu", s->bits_sent));
 }
 
 /* ===========================================================================
@@ -936,11 +936,11 @@ void _tr_flush_block(s, buf, stored_len, eof)
 
         /* Construct the literal and distance trees */
         build_tree(s, (tree_desc *)(&(s->l_desc)));
-        Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+        Tracev((stderr, "\nlit data: dyn %lu, stat %lu", s->opt_len,
                 s->static_len));
 
         build_tree(s, (tree_desc *)(&(s->d_desc)));
-        Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+        Tracev((stderr, "\ndist data: dyn %lu, stat %lu", s->opt_len,
                 s->static_len));
         /* At this point, opt_len and static_len are the total bit lengths of
          * the compressed block data, excluding the tree representations.
diff --git a/frmts/zlib/zlib.h b/frmts/zlib/zlib.h
index 93c8579..43dafbf 100644
--- a/frmts/zlib/zlib.h
+++ b/frmts/zlib/zlib.h
@@ -1,4 +1,4 @@
-	/* zlib.h -- interface of the 'zlib' general purpose compression library
+/* zlib.h -- interface of the 'zlib' general purpose compression library
   version 1.2.3, July 18th, 2005
 
   Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
diff --git a/frmts/zlib/zutil.c b/frmts/zlib/zutil.c
index b611f1a..5cd45a9 100644
--- a/frmts/zlib/zutil.c
+++ b/frmts/zlib/zutil.c
@@ -3,7 +3,7 @@
  * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
-/* @(#) $Id: zutil.c 30901 2015-10-08 04:18:30Z goatbar $ */
+/* @(#) $Id: zutil.c 36387 2016-11-21 12:56:56Z rouault $ */
 
 #include "zutil.h"
 
@@ -294,7 +294,8 @@ voidpf zcalloc (opaque, items, size)
     unsigned items;
     unsigned size;
 {
-    if (opaque) items += size - size; /* make compiler happy */
+    /* cppcheck-suppress uselessAssignmentPtrArg */
+    if (opaque) opaque = 0; /* to make compiler happy */
     return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
                               (voidpf)calloc(items, size);
 }
diff --git a/frmts/zmap/zmapdataset.cpp b/frmts/zmap/zmapdataset.cpp
index c6d3a3a..ce7d719 100644
--- a/frmts/zmap/zmapdataset.cpp
+++ b/frmts/zmap/zmapdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: zmapdataset.cpp 32984 2016-01-14 19:08:12Z goatbar $
  *
  * Project:  ZMap driver
  * Purpose:  GDALDataset driver for ZMap dataset.
@@ -34,7 +33,7 @@
 
 #include <cmath>
 
-CPL_CVSID("$Id: zmapdataset.cpp 32984 2016-01-14 19:08:12Z goatbar $");
+CPL_CVSID("$Id: zmapdataset.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -61,7 +60,7 @@ class ZMapDataset : public GDALPamDataset
                  ZMapDataset();
     virtual     ~ZMapDataset();
 
-    virtual CPLErr GetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * ) override;
 
     static GDALDataset *Open( GDALOpenInfo * );
     static int          Identify( GDALOpenInfo * );
@@ -83,11 +82,10 @@ class ZMapRasterBand : public GDALPamRasterBand
   public:
     explicit ZMapRasterBand( ZMapDataset * );
 
-    virtual CPLErr IReadBlock( int, int, void * );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
+    virtual CPLErr IReadBlock( int, int, void * ) override;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
 };
 
-
 /************************************************************************/
 /*                           ZMapRasterBand()                           */
 /************************************************************************/
@@ -458,10 +456,9 @@ GDALDataset *ZMapDataset::Open( GDALOpenInfo * poOpenInfo )
 /*      Support overviews.                                              */
 /* -------------------------------------------------------------------- */
     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
-    return( poDS );
+    return poDS;
 }
 
-
 /************************************************************************/
 /*                       WriteRightJustified()                          */
 /************************************************************************/
@@ -689,7 +686,7 @@ CPLErr ZMapDataset::GetGeoTransform( double * padfTransform )
 {
     memcpy(padfTransform, adfGeoTransform, 6 * sizeof(double));
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
diff --git a/gcore/GNUmakefile b/gcore/GNUmakefile
index 75647cc..58439cf 100644
--- a/gcore/GNUmakefile
+++ b/gcore/GNUmakefile
@@ -36,14 +36,17 @@ ifeq ($(HAVE_LIBXML2),yes)
 CXXFLAGS	:=	$(CXXFLAGS) $(LIBXML2_INC) -DHAVE_LIBXML2
 endif
 
-default: mdreader-target $(OBJ:.o=.$(OBJ_EXT))
+default: mdreader-target $(OBJ:.o=.$(OBJ_EXT)) rasterio_ssse3.$(OBJ_EXT)
+
+rasterio_ssse3.$(OBJ_EXT):   rasterio_ssse3.cpp
+	$(CXX) $(GDAL_INCLUDE) $(CXXFLAGS_NO_LTO_IF_SSSE3_NONDEFAULT) $(SSSE3FLAGS) $(CPPFLAGS) -c -o $@ $<
 
 $(OBJ):	gdal_priv.h gdal_proxy.h
 
 clean: mdreader-clean
 	$(RM) *.o $(O_OBJ)
 
-docs:	
+docs:
 	(cd ..; $(MAKE) docs)
 
 gdal_misc.$(OBJ_EXT):	gdal_misc.cpp gdal_version.h
diff --git a/gcore/Version.rc b/gcore/Version.rc
index a1eecaf..8854a30 100644
--- a/gcore/Version.rc
+++ b/gcore/Version.rc
@@ -1,11 +1,11 @@
 /******************************************************************************
- * $Id: Version.rc 13360 2007-12-18 03:47:06Z mloskot $
+ * $Id: Version.rc 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Project:  GDAL Core
- * Purpose:  GDAL DLL registration information. 
+ * Purpose:  GDAL DLL registration information.
  * Author:   Martin Daly (Cadcorp)
  *
- * Copyright assignment provided by Martin Daly by email, "Be my guest.  Fame!  
+ * Copyright assignment provided by Martin Daly by email, "Be my guest.  Fame!
  * At last!  Best not let it go to my head, eh?"
  *
  ******************************************************************************
diff --git a/gcore/gdal.h b/gcore/gdal.h
index 65395f6..eed5437 100644
--- a/gcore/gdal.h
+++ b/gcore/gdal.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal.h 33852 2016-04-01 23:27:53Z goatbar $
+ * $Id: gdal.h 37723 2017-03-16 17:07:53Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Core C/Public declarations.
@@ -78,17 +78,18 @@ const char CPL_DLL * CPL_STDCALL GDALGetDataTypeName( GDALDataType );
 GDALDataType CPL_DLL CPL_STDCALL GDALGetDataTypeByName( const char * );
 GDALDataType CPL_DLL CPL_STDCALL GDALDataTypeUnion( GDALDataType, GDALDataType );
 double CPL_DLL GDALAdjustValueToDataType( GDALDataType eDT, double dfValue, int* pbClamped, int* pbRounded );
+GDALDataType CPL_STDCALL GDALGetNonComplexDataType( GDALDataType );
 
 /**
 * status of the asynchronous stream
 */
 typedef enum
 {
-	GARIO_PENDING = 0,
-	GARIO_UPDATE = 1,
-	GARIO_ERROR = 2,
-	GARIO_COMPLETE = 3,
-	GARIO_TypeCount = 4
+    GARIO_PENDING = 0,
+    GARIO_UPDATE = 1,
+    GARIO_ERROR = 2,
+    GARIO_COMPLETE = 3,
+    GARIO_TypeCount = 4
 } GDALAsyncStatusType;
 
 const char CPL_DLL * CPL_STDCALL GDALGetAsyncStatusTypeName( GDALAsyncStatusType );
@@ -157,7 +158,9 @@ typedef struct
     double                 dfYSize;
 } GDALRasterIOExtraArg;
 
+#ifndef DOXYGEN_SKIP
 #define RASTERIO_EXTRA_ARG_CURRENT_VERSION  1
+#endif
 
 /** Macro to initialize an instance of GDALRasterIOExtraArg structure.
   * @since GDAL 2.0
@@ -208,8 +211,14 @@ const char CPL_DLL *GDALGetPaletteInterpretationName( GDALPaletteInterp );
 
 /* "well known" metadata items. */
 
+/** Metadata item for dataset that indicates the spatial interpreation of a
+ *  pixel */
 #define GDALMD_AREA_OR_POINT   "AREA_OR_POINT"
+/** Value for GDALMD_AREA_OR_POINT that indicates that a pixel represents an
+ * area */
 #  define GDALMD_AOP_AREA      "Area"
+/** Value for GDALMD_AREA_OR_POINT that indicates that a pixel represents a
+ * point */
 #  define GDALMD_AOP_POINT     "Point"
 
 /* -------------------------------------------------------------------- */
@@ -217,7 +226,9 @@ const char CPL_DLL *GDALGetPaletteInterpretationName( GDALPaletteInterp );
 /*                                                                      */
 /*      error codes 100 to 299 reserved for GDAL.                       */
 /* -------------------------------------------------------------------- */
+#ifndef DOXYGEN_SKIP
 #define CPLE_WrongFormat        (CPLErrorNum)200
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Define handle types related to various internal classes.        */
@@ -346,11 +357,15 @@ GDALCreateCopy( GDALDriverH, const char *, GDALDatasetH,
 
 GDALDriverH CPL_DLL CPL_STDCALL GDALIdentifyDriver( const char * pszFilename,
                                             char ** papszFileList );
+
+GDALDriverH CPL_DLL CPL_STDCALL GDALIdentifyDriverEx(
+    const char *pszFilename, unsigned int nIdentifyFlags,
+    const char *const *papszAllowedDrivers, const char *const *papszFileList);
+
 GDALDatasetH CPL_DLL CPL_STDCALL
 GDALOpen( const char *pszFilename, GDALAccess eAccess ) CPL_WARN_UNUSED_RESULT;
 GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenShared( const char *, GDALAccess ) CPL_WARN_UNUSED_RESULT;
 
-
 /* Note: we define GDAL_OF_READONLY and GDAL_OF_UPDATE to be on purpose */
 /* equals to GA_ReadOnly and GA_Update */
 
@@ -384,7 +399,6 @@ GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenShared( const char *, GDALAccess ) CPL_
  */
 #define     GDAL_OF_VECTOR          0x04
 
-
 /** Allow gnm drivers to be used.
  * Used by GDALOpenEx().
  * @since GDAL 2.1
@@ -449,8 +463,14 @@ GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenShared( const char *, GDALAccess ) CPL_
  */
 #define     GDAL_OF_HASHSET_BLOCK_ACCESS  0x200
 
+#ifndef DOXYGEN_SKIP
+/* Reserved for a potential future alternative to GDAL_OF_ARRAY_BLOCK_ACCESS
+ * and GDAL_OF_HASHSET_BLOCK_ACCESS */
 #define     GDAL_OF_RESERVED_1            0x300
+
+/** Mask to detect the block access method */
 #define     GDAL_OF_BLOCK_ACCESS_MASK     0x300
+#endif
 
 GDALDatasetH CPL_DLL CPL_STDCALL GDALOpenEx( const char* pszFilename,
                                              unsigned int nOpenFlags,
@@ -467,7 +487,9 @@ void        CPL_DLL CPL_STDCALL GDALDestroyDriver( GDALDriverH );
 int         CPL_DLL CPL_STDCALL GDALRegisterDriver( GDALDriverH );
 void        CPL_DLL CPL_STDCALL GDALDeregisterDriver( GDALDriverH );
 void        CPL_DLL CPL_STDCALL GDALDestroyDriverManager( void );
+#ifndef DOXYGEN_SKIP
 void        CPL_DLL             GDALDestroy( void );
+#endif
 CPLErr      CPL_DLL CPL_STDCALL GDALDeleteDataset( GDALDriverH, const char * );
 CPLErr      CPL_DLL CPL_STDCALL GDALRenameDataset( GDALDriverH,
                                                    const char * pszNewName,
@@ -548,6 +570,7 @@ void CPL_DLL CPL_STDCALL GDALSetDescription( GDALMajorObjectH, const char * );
 /*      GDALDataset class ... normally this represents one file.        */
 /* ==================================================================== */
 
+/** Name of driver metadata item for layer creation option list */
 #define GDAL_DS_LAYER_CREATIONOPTIONLIST "DS_LAYER_CREATIONOPTIONLIST"
 
 GDALDriverH CPL_DLL CPL_STDCALL GDALGetDatasetDriver( GDALDatasetH );
@@ -606,6 +629,7 @@ CPLErr CPL_DLL CPL_STDCALL GDALSetGCPs( GDALDatasetH, int, const GDAL_GCP *,
 void CPL_DLL * CPL_STDCALL GDALGetInternalHandle( GDALDatasetH, const char * );
 int CPL_DLL CPL_STDCALL GDALReferenceDataset( GDALDatasetH );
 int CPL_DLL CPL_STDCALL GDALDereferenceDataset( GDALDatasetH );
+int CPL_DLL CPL_STDCALL GDALReleaseDataset( GDALDatasetH );
 
 CPLErr CPL_DLL CPL_STDCALL
 GDALBuildOverviews( GDALDatasetH, const char *, int, int *,
@@ -622,7 +646,8 @@ CPLErr CPL_DLL CPL_STDCALL GDALDatasetCopyWholeRaster(
     GDALProgressFunc pfnProgress, void *pProgressData ) CPL_WARN_UNUSED_RESULT;
 
 CPLErr CPL_DLL CPL_STDCALL GDALRasterBandCopyWholeRaster(
-    GDALRasterBandH hSrcBand, GDALRasterBandH hDstBand, char **papszOptions,
+    GDALRasterBandH hSrcBand, GDALRasterBandH hDstBand,
+    const char * const * constpapszOptions,
     GDALProgressFunc pfnProgress, void *pProgressData ) CPL_WARN_UNUSED_RESULT;
 
 CPLErr CPL_DLL
@@ -640,6 +665,12 @@ OGRLayerH CPL_DLL GDALDatasetCreateLayer( GDALDatasetH, const char *,
                                       char ** );
 OGRLayerH CPL_DLL GDALDatasetCopyLayer( GDALDatasetH, OGRLayerH, const char *,
                                         char ** );
+void CPL_DLL GDALDatasetResetReading( GDALDatasetH );
+OGRFeatureH CPL_DLL GDALDatasetGetNextFeature( GDALDatasetH hDS,
+                                               OGRLayerH* phBelongingLayer,
+                                               double* pdfProgressPct,
+                                               GDALProgressFunc pfnProgress,
+                                               void* pProgressData );
 int    CPL_DLL GDALDatasetTestCapability( GDALDatasetH, const char * );
 OGRLayerH CPL_DLL GDALDatasetExecuteSQL( GDALDatasetH, const char *,
                                      OGRGeometryH, const char * );
@@ -651,7 +682,6 @@ OGRErr CPL_DLL GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce);
 OGRErr CPL_DLL GDALDatasetCommitTransaction(GDALDatasetH hDS);
 OGRErr CPL_DLL GDALDatasetRollbackTransaction(GDALDatasetH hDS);
 
-
 /* ==================================================================== */
 /*      GDALRasterBand ... one band/channel in a dataset.               */
 /* ==================================================================== */
@@ -684,16 +714,22 @@ OGRErr CPL_DLL GDALDatasetRollbackTransaction(GDALDatasetH hDS);
       (eSrcType == GDT_CFloat64 ? \
           ((double *)papoSource)[ii * 2] : 0)))))))))))
 
+/** Type of functions to pass to GDALAddDerivedBandPixelFunc.
+ * @since GDAL 2.2 */
 typedef CPLErr
 (*GDALDerivedPixelFunc)(void **papoSources, int nSources, void *pData,
-			int nBufXSize, int nBufYSize,
-			GDALDataType eSrcType, GDALDataType eBufType,
+                        int nBufXSize, int nBufYSize,
+                        GDALDataType eSrcType, GDALDataType eBufType,
                         int nPixelSpace, int nLineSpace);
 
 GDALDataType CPL_DLL CPL_STDCALL GDALGetRasterDataType( GDALRasterBandH );
 void CPL_DLL CPL_STDCALL
 GDALGetBlockSize( GDALRasterBandH, int * pnXSize, int * pnYSize );
 
+CPLErr CPL_DLL CPL_STDCALL
+GDALGetActualBlockSize( GDALRasterBandH, int nXBlockOff, int nYBlockOff,
+                        int *pnXValid, int *pnYValid );
+
 CPLErr CPL_DLL CPL_STDCALL GDALRasterAdviseRead( GDALRasterBandH hRB,
     int nDSXOff, int nDSYOff, int nDSXSize, int nDSYSize,
     int nBXSize, int nBYSize, GDALDataType eBDataType, char **papszOptions );
@@ -815,11 +851,42 @@ int CPL_DLL CPL_STDCALL GDALGetMaskFlags( GDALRasterBandH hBand );
 CPLErr CPL_DLL CPL_STDCALL
                        GDALCreateMaskBand( GDALRasterBandH hBand, int nFlags );
 
+/** Flag returned by GDALGetMaskFlags() to indicate that all pixels are valid */
 #define GMF_ALL_VALID     0x01
+/** Flag returned by GDALGetMaskFlags() to indicate that the mask band is
+ * valid for all bands */
 #define GMF_PER_DATASET   0x02
+/** Flag returned by GDALGetMaskFlags() to indicate that the mask band is
+ * an alpha band */
 #define GMF_ALPHA         0x04
+/** Flag returned by GDALGetMaskFlags() to indicate that the mask band is
+ * computed from nodata values */
 #define GMF_NODATA        0x08
 
+/** Flag returned by GDALGetDataCoverageStatus() when the driver does not
+ * implement GetDataCoverageStatus(). This flag should be returned together
+ * with GDAL_DATA_COVERAGE_STATUS_DATA */
+#define GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED 0x01
+
+/** Flag returned by GDALGetDataCoverageStatus() when there is (potentially)
+ * data in the queried window. Can be combined with the binary or operator
+ * with GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED or
+ * GDAL_DATA_COVERAGE_STATUS_EMPTY */
+#define GDAL_DATA_COVERAGE_STATUS_DATA          0x02
+
+/** Flag returned by GDALGetDataCoverageStatus() when there is nodata in the
+ * queried window. This is typically identified by the concept of missing block
+ * in formats that supports it.
+ * Can be combined with the binary or operator with
+ * GDAL_DATA_COVERAGE_STATUS_DATA */
+#define GDAL_DATA_COVERAGE_STATUS_EMPTY         0x04
+
+int CPL_DLL CPL_STDCALL GDALGetDataCoverageStatus( GDALRasterBandH hBand,
+                                                   int nXOff, int nYOff,
+                                                   int nXSize, int nYSize,
+                                                   int nMaskFlagStop,
+                                                   double* pdfDataPct );
+
 /* ==================================================================== */
 /*     GDALAsyncReader                                                  */
 /* ==================================================================== */
@@ -843,8 +910,10 @@ void CPL_DLL CPL_STDCALL GDALSwapWordsEx( void *pData, int nWordSize, size_t nWo
                                   int nWordSkip );
 
 void CPL_DLL CPL_STDCALL
-    GDALCopyWords( const void * pSrcData, GDALDataType eSrcType, int nSrcPixelOffset,
-                   void * pDstData, GDALDataType eDstType, int nDstPixelOffset,
+    GDALCopyWords( const void * CPL_RESTRICT pSrcData,
+                   GDALDataType eSrcType, int nSrcPixelOffset,
+                   void * CPL_RESTRICT pDstData,
+                   GDALDataType eDstType, int nDstPixelOffset,
                    int nWordCount );
 
 void CPL_DLL
@@ -873,7 +942,9 @@ double CPL_DLL CPL_STDCALL GDALDecToPackedDMS( double );
 /* Note to developers : please keep this section in sync with ogr_core.h */
 
 #ifndef GDAL_VERSION_INFO_DEFINED
+#ifndef DOXYGEN_SKIP
 #define GDAL_VERSION_INFO_DEFINED
+#endif
 const char CPL_DLL * CPL_STDCALL GDALVersionInfo( const char * );
 #endif
 
@@ -890,29 +961,31 @@ int CPL_DLL CPL_STDCALL GDALCheckVersion( int nVersionMajor, int nVersionMinor,
 
 #endif
 
-typedef struct {
-    double      dfLINE_OFF;
-    double      dfSAMP_OFF;
-    double      dfLAT_OFF;
-    double      dfLONG_OFF;
-    double      dfHEIGHT_OFF;
-
-    double      dfLINE_SCALE;
-    double      dfSAMP_SCALE;
-    double      dfLAT_SCALE;
-    double      dfLONG_SCALE;
-    double      dfHEIGHT_SCALE;
-
-    double      adfLINE_NUM_COEFF[20];
-    double      adfLINE_DEN_COEFF[20];
-    double      adfSAMP_NUM_COEFF[20];
-    double      adfSAMP_DEN_COEFF[20];
-
-    double	dfMIN_LONG;
-    double      dfMIN_LAT;
-    double      dfMAX_LONG;
-    double	dfMAX_LAT;
-
+/** Strucutre to store Rational Polynomial Coefficients / Rigorous Projection
+ * Model. See http://geotiff.maptools.org/rpc_prop.html */
+typedef struct
+{
+    double dfLINE_OFF;   /*!< Line offset */
+    double dfSAMP_OFF;   /*!< Sample/Pixel offset */
+    double dfLAT_OFF;    /*!< Latitude offset */
+    double dfLONG_OFF;   /*!< Longitude offset */
+    double dfHEIGHT_OFF; /*!< Height offset */
+
+    double dfLINE_SCALE;   /*!< Line scale */
+    double dfSAMP_SCALE;   /*!< Sample/Pixel scale */
+    double dfLAT_SCALE;    /*!< Latitude scale */
+    double dfLONG_SCALE;   /*!< Longitude scale */
+    double dfHEIGHT_SCALE; /*!< Height scale */
+
+    double adfLINE_NUM_COEFF[20]; /*!< Line Numerator Coefficients */
+    double adfLINE_DEN_COEFF[20]; /*!< Line Denominator Coefficients */
+    double adfSAMP_NUM_COEFF[20]; /*!< Sample/Pixel Numerator Coefficients */
+    double adfSAMP_DEN_COEFF[20]; /*!< Sample/Pixel Denominator Coefficients */
+
+    double dfMIN_LONG; /*!< Minimum longitude */
+    double dfMIN_LAT;  /*!< Minimum latitude */
+    double dfMAX_LONG; /*!< Maximum longitude */
+    double dfMAX_LAT;  /*!< Maximum latitude */
 } GDALRPCInfo;
 
 int CPL_DLL CPL_STDCALL GDALExtractRPCInfo( char **, GDALRPCInfo * );
@@ -950,12 +1023,12 @@ void CPL_DLL CPL_STDCALL GDALCreateColorRamp( GDALColorTableH hTable,
             int nEndIndex, const GDALColorEntry *psEndColor );
 
 /* ==================================================================== */
-/*      Raster Attribute Table						*/
+/*      Raster Attribute Table                                          */
 /* ==================================================================== */
 
 /** Field type of raster attribute table */
 typedef enum {
-    /*! Integer field */	   	   GFT_Integer,
+    /*! Integer field */                   GFT_Integer,
     /*! Floating point (double) field */   GFT_Real,
     /*! String field */                    GFT_String
 } GDALRATFieldType;
@@ -1048,7 +1121,6 @@ void CPL_DLL* CPL_STDCALL
 
 int CPL_DLL CPL_STDCALL GDALRATGetRowOfValue( GDALRasterAttributeTableH, double );
 
-
 /* ==================================================================== */
 /*      GDAL Cache Management                                           */
 /* ==================================================================== */
@@ -1100,6 +1172,7 @@ CPLVirtualMem CPL_DLL* GDALGetVirtualMemAuto( GDALRasterBandH hBand,
                                               GIntBig *pnLineSpace,
                                               char **papszOptions ) CPL_WARN_UNUSED_RESULT;
 
+/**! Enumeration to describe the tile organization */
 typedef enum
 {
     /*! Tile Interleaved by Pixel: tile (0,0) with internal band interleaved by pixel organization, tile (1, 0), ...  */
diff --git a/gcore/gdal_avx2_emulation.hpp b/gcore/gdal_avx2_emulation.hpp
new file mode 100644
index 0000000..d84da1b
--- /dev/null
+++ b/gcore/gdal_avx2_emulation.hpp
@@ -0,0 +1,240 @@
+/******************************************************************************
+ * Project:  GDAL
+ * Purpose:  AVX2 emulation with SSE2 + a few SSE4.1 emulation
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef GDAL_AVX2_EMULATION_H_INCLUDED
+#define GDAL_AVX2_EMULATION_H_INCLUDED
+
+#include <emmintrin.h>
+
+#ifdef __SSE4_1__
+#include <smmintrin.h>
+
+#define GDALmm_min_epu16   _mm_min_epu16
+#define GDALmm_max_epu16   _mm_max_epu16
+#define GDALmm_mullo_epi32 _mm_mullo_epi32
+
+#else
+// Emulation of SSE4.1 _mm_min_epu16 and _mm_max_epu16 with SSE2 only
+
+static inline __m128i GDALAVX2Emul_mm_cmple_epu16 (__m128i x, __m128i y)
+{
+    return _mm_cmpeq_epi16(_mm_subs_epu16(x, y), _mm_setzero_si128() );
+}
+
+static inline __m128i GDALAVX2Emul_mm_ternary(__m128i mask,
+                                      __m128i then_reg,
+                                      __m128i else_reg)
+{
+    return _mm_or_si128(_mm_and_si128(mask, then_reg),
+                        _mm_andnot_si128(mask, else_reg));
+}
+
+static inline __m128i GDALmm_min_epu16 (__m128i x, __m128i y)
+{
+    const __m128i mask = GDALAVX2Emul_mm_cmple_epu16(x, y);
+    return GDALAVX2Emul_mm_ternary(mask, x, y);
+}
+
+static inline __m128i GDALmm_max_epu16 (__m128i x, __m128i y)
+{
+    const __m128i mask = GDALAVX2Emul_mm_cmple_epu16(x, y);
+    return GDALAVX2Emul_mm_ternary(mask, y, x);
+}
+
+static inline __m128i GDALmm_mullo_epi32 (__m128i x, __m128i y)
+{
+    const __m128i mul02 = _mm_shuffle_epi32(_mm_mul_epu32(x, y), 2 << 2);
+    const __m128i mul13 = _mm_shuffle_epi32(_mm_mul_epu32(_mm_srli_si128(x, 4),
+                                                          _mm_srli_si128(y, 4)),
+                                            2 << 2);
+    return _mm_unpacklo_epi32(mul02, mul13);;
+}
+#endif // __SSE4_1__
+
+
+#ifdef __AVX2__
+
+#include <immintrin.h>
+
+typedef __m256i GDALm256i;
+
+#define GDALmm256_set1_epi8             _mm256_set1_epi8
+#define GDALmm256_set1_epi16            _mm256_set1_epi16
+#define GDALmm256_setzero_si256         _mm256_setzero_si256
+#define GDALmm256_load_si256            _mm256_load_si256
+#define GDALmm256_store_si256           _mm256_store_si256
+#define GDALmm256_storeu_si256          _mm256_storeu_si256
+#define GDALmm256_cmpeq_epi8            _mm256_cmpeq_epi8
+#define GDALmm256_sad_epu8              _mm256_sad_epu8
+#define GDALmm256_add_epi32             _mm256_add_epi32
+#define GDALmm256_andnot_si256          _mm256_andnot_si256
+#define GDALmm256_and_si256             _mm256_and_si256
+#define GDALmm256_or_si256              _mm256_or_si256
+#define GDALmm256_min_epu8              _mm256_min_epu8
+#define GDALmm256_max_epu8              _mm256_max_epu8
+#define GDALmm256_extracti128_si256     _mm256_extracti128_si256
+#define GDALmm256_cvtepu8_epi16         _mm256_cvtepu8_epi16
+#define GDALmm256_madd_epi16            _mm256_madd_epi16
+#define GDALmm256_min_epu16             _mm256_min_epu16
+#define GDALmm256_max_epu16             _mm256_max_epu16
+#define GDALmm256_cvtepu16_epi32        _mm256_cvtepu16_epi32
+#define GDALmm256_cvtepu16_epi64        _mm256_cvtepu16_epi64
+#define GDALmm256_cvtepu32_epi64        _mm256_cvtepu32_epi64
+#define GDALmm256_mullo_epi32           _mm256_mullo_epi32
+#define GDALmm256_add_epi64             _mm256_add_epi64
+#define GDALmm256_add_epi16             _mm256_add_epi16
+#define GDALmm256_sub_epi16             _mm256_sub_epi16
+#define GDALmm256_min_epi16             _mm256_min_epi16
+#define GDALmm256_max_epi16             _mm256_max_epi16
+
+#else
+
+typedef struct
+{
+    __m128i low;
+    __m128i high;
+} GDALm256i;
+
+static inline GDALm256i GDALmm256_set1_epi8(char c)
+{
+    GDALm256i reg;
+    reg.low = _mm_set1_epi8(c);
+    reg.high = _mm_set1_epi8(c);
+    return reg;
+}
+
+static inline GDALm256i GDALmm256_set1_epi16(short s)
+{
+    GDALm256i reg;
+    reg.low = _mm_set1_epi16(s);
+    reg.high = _mm_set1_epi16(s);
+    return reg;
+}
+
+static inline GDALm256i GDALmm256_setzero_si256()
+{
+    GDALm256i reg;
+    reg.low = _mm_setzero_si128();
+    reg.high = _mm_setzero_si128();
+    return reg;
+}
+
+static inline GDALm256i GDALmm256_load_si256(GDALm256i const * p)
+{
+    GDALm256i reg;
+    reg.low = _mm_load_si128((__m128i const*)p);
+    reg.high = _mm_load_si128((__m128i const*)((char*)p+16));
+    return reg;
+}
+
+static inline void GDALmm256_store_si256(GDALm256i * p, GDALm256i reg)
+{
+    _mm_store_si128((__m128i*)p, reg.low);
+    _mm_store_si128((__m128i*)((char*)p+16), reg.high);
+}
+
+static inline void GDALmm256_storeu_si256(GDALm256i * p, GDALm256i reg)
+{
+    _mm_storeu_si128((__m128i*)p, reg.low);
+    _mm_storeu_si128((__m128i*)((char*)p+16), reg.high);
+}
+
+#define DEFINE_BINARY_MM256(mm256name, mm128name) \
+static inline GDALm256i mm256name(GDALm256i r1, GDALm256i r2) \
+{ \
+    GDALm256i reg; \
+    reg.low = mm128name(r1.low, r2.low); \
+    reg.high = mm128name(r1.high, r2.high); \
+    return reg; \
+}
+
+DEFINE_BINARY_MM256(GDALmm256_cmpeq_epi8, _mm_cmpeq_epi8)
+DEFINE_BINARY_MM256(GDALmm256_sad_epu8, _mm_sad_epu8)
+DEFINE_BINARY_MM256(GDALmm256_add_epi32, _mm_add_epi32)
+DEFINE_BINARY_MM256(GDALmm256_andnot_si256, _mm_andnot_si128)
+DEFINE_BINARY_MM256(GDALmm256_and_si256, _mm_and_si128)
+DEFINE_BINARY_MM256(GDALmm256_or_si256, _mm_or_si128)
+DEFINE_BINARY_MM256(GDALmm256_min_epu8, _mm_min_epu8)
+DEFINE_BINARY_MM256(GDALmm256_max_epu8, _mm_max_epu8)
+DEFINE_BINARY_MM256(GDALmm256_madd_epi16, _mm_madd_epi16)
+DEFINE_BINARY_MM256(GDALmm256_min_epu16, GDALmm_min_epu16)
+DEFINE_BINARY_MM256(GDALmm256_max_epu16, GDALmm_max_epu16)
+DEFINE_BINARY_MM256(GDALmm256_mullo_epi32, GDALmm_mullo_epi32)
+DEFINE_BINARY_MM256(GDALmm256_add_epi64, _mm_add_epi64)
+DEFINE_BINARY_MM256(GDALmm256_add_epi16, _mm_add_epi16)
+DEFINE_BINARY_MM256(GDALmm256_sub_epi16, _mm_sub_epi16)
+DEFINE_BINARY_MM256(GDALmm256_min_epi16, _mm_min_epi16)
+DEFINE_BINARY_MM256(GDALmm256_max_epi16, _mm_max_epi16)
+
+static inline __m128i GDALmm256_extracti128_si256(GDALm256i reg, int index)
+{
+    return (index == 0) ? reg.low : reg.high;
+}
+
+static inline GDALm256i GDALmm256_cvtepu8_epi16(__m128i reg128)
+{
+    GDALm256i reg;
+    reg.low = _mm_unpacklo_epi8(reg128, _mm_setzero_si128());
+    reg.high = _mm_unpacklo_epi8(_mm_shuffle_epi32(reg128, 2 | (3 << 2)),
+                                 _mm_setzero_si128());
+    return reg;
+}
+
+static inline GDALm256i GDALmm256_cvtepu16_epi32(__m128i reg128)
+{
+    GDALm256i reg;
+    reg.low = _mm_unpacklo_epi16(reg128, _mm_setzero_si128());
+    reg.high = _mm_unpacklo_epi16(_mm_shuffle_epi32(reg128, 2 | (3 << 2)),
+                                  _mm_setzero_si128());
+    return reg;
+}
+
+static inline GDALm256i GDALmm256_cvtepu16_epi64(__m128i reg128)
+{
+    GDALm256i reg;
+    reg.low = _mm_unpacklo_epi32(_mm_unpacklo_epi16(reg128,
+                                                    _mm_setzero_si128()),
+                                 _mm_setzero_si128());
+    reg.high = _mm_unpacklo_epi32(_mm_unpacklo_epi16(
+                                     _mm_srli_si128(reg128, 4),
+                                                    _mm_setzero_si128()),
+                                     _mm_setzero_si128());
+    return reg;
+}
+
+static inline GDALm256i GDALmm256_cvtepu32_epi64(__m128i reg128)
+{
+    GDALm256i reg;
+    reg.low = _mm_unpacklo_epi32(reg128, _mm_setzero_si128());
+    reg.high = _mm_unpacklo_epi32(_mm_shuffle_epi32(reg128, 2 | (3 << 2)),
+                                  _mm_setzero_si128());
+    return reg;
+}
+
+#endif
+
+#endif /* GDAL_AVX2_EMULATION_H_INCLUDED */
diff --git a/gcore/gdal_frmts.h b/gcore/gdal_frmts.h
index 44d06f8..f7495af 100644
--- a/gcore/gdal_frmts.h
+++ b/gcore/gdal_frmts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_frmts.h 33351 2016-02-03 15:52:38Z goatbar $
+ * $Id: gdal_frmts.h 36731 2016-12-07 11:08:07Z rouault $
  *
  * Project:  GDAL
  * Purpose:  Prototypes for all format specific driver initialization.
@@ -186,6 +186,10 @@ void CPL_DLL GDALRegister_WMTS(void);
 void CPL_DLL GDALRegister_SAFE(void);
 void CPL_DLL GDALRegister_SENTINEL2(void);
 void CPL_DLL GDALRegister_mrf(void);
+void CPL_DLL GDALRegister_RRASTER(void);
+void CPL_DLL GDALRegister_Derived(void);
+void CPL_DLL GDALRegister_JP2Lura(void);
+void CPL_DLL GDALRegister_PRF(void);
 CPL_C_END
 
 #endif /* ndef GDAL_FRMTS_H_INCLUDED */
diff --git a/gcore/gdal_mdreader.cpp b/gcore/gdal_mdreader.cpp
index e954fb2..f8d856e 100644
--- a/gcore/gdal_mdreader.cpp
+++ b/gcore/gdal_mdreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_mdreader.cpp 33873 2016-04-03 14:13:37Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata (mainly the remote sensing imagery) from files of
@@ -31,9 +30,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_mdreader.h"
+
+#include <cctype>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#include <ctime>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "cplkeywordparser.h"
-#include "gdal_mdreader.h"
+#include "gdal_priv.h"
 
 //readers
 #include "mdreader/reader_alos.h"
@@ -48,7 +61,7 @@
 #include "mdreader/reader_rdk1.h"
 #include "mdreader/reader_spot.h"
 
-CPL_CVSID("$Id: gdal_mdreader.cpp 33873 2016-04-03 14:13:37Z rouault $");
+CPL_CVSID("$Id: gdal_mdreader.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /**
  * The RPC parameters names
@@ -90,7 +103,7 @@ GDALMDReaderManager::GDALMDReaderManager() :
  */
 GDALMDReaderManager::~GDALMDReaderManager()
 {
-   if(NULL != m_pReader)
+   if( NULL != m_pReader )
    {
        delete m_pReader;
    }
@@ -411,7 +424,6 @@ char** GDALMDReaderBase::ReadXMLToList(CPLXMLNode* psNode, char** papszList,
 // Miscellaneous functions
 //------------------------------------------------------------------------------
 
-
 /**
  * GDALCheckFileHeader()
  */
@@ -455,7 +467,7 @@ CPLString CPLStrip(const CPLString& sString, const char cChar)
         dCopyCount--;
     }
 
-    if (sString[sString.size() - 1] == cChar)
+    if (sString.back() == cChar)
         dCopyCount--;
 
     if(dCopyCount == 0)
@@ -472,9 +484,6 @@ CPLString CPLStripQuotes(const CPLString& sString)
     return CPLStrip( CPLStrip(sString, '"'), '\'');
 }
 
-
-
-
 /************************************************************************/
 /*                          GDALLoadRPBFile()                           */
 /************************************************************************/
@@ -691,7 +700,6 @@ CPLErr GDALWriteRPCTXTFile( const char *pszFilename, char **papszMD )
         bOK &= VSIFPrintfL( fp, "%s: %s\n", apszRPCTXTSingleValItems[i], pszRPCVal ) > 0;
     }
 
-
     for( int i = 0; apszRPCTXT20ValItems[i] != NULL; i ++ )
     {
         const char *pszRPCVal = CSLFetchNameValue( papszMD, apszRPCTXT20ValItems[i] );
@@ -728,7 +736,6 @@ CPLErr GDALWriteRPCTXTFile( const char *pszFilename, char **papszMD )
         CSLDestroy( papszItems );
     }
 
-
     if( VSIFCloseL( fp ) != 0 )
         bOK = false;
 
@@ -1068,10 +1075,10 @@ CPLErr GDALWriteIMDFile( const char *pszFilename, char **papszMD )
 /* -------------------------------------------------------------------- */
 /*      Close and/or start sections as needed.                          */
 /* -------------------------------------------------------------------- */
-        if( osCurSection.size() && !EQUAL(osCurSection,osKeySection) )
+        if( !osCurSection.empty() && !EQUAL(osCurSection,osKeySection) )
             bOK &= VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() ) > 0;
 
-        if( osKeySection.size() && !EQUAL(osCurSection,osKeySection) )
+        if( !osKeySection.empty() && !EQUAL(osCurSection,osKeySection) )
             bOK &= VSIFPrintfL( fp, "BEGIN_GROUP = %s\n", osKeySection.c_str() ) > 0;
 
         osCurSection = osKeySection;
@@ -1079,7 +1086,7 @@ CPLErr GDALWriteIMDFile( const char *pszFilename, char **papszMD )
 /* -------------------------------------------------------------------- */
 /*      Print out simple item.                                          */
 /* -------------------------------------------------------------------- */
-        if( osCurSection.size() )
+        if( !osCurSection.empty() )
             bOK &= VSIFPrintfL( fp, "\t%s = ", osKeyItem.c_str() ) > 0;
         else
             bOK &= VSIFPrintfL( fp, "%s = ", osKeyItem.c_str() ) > 0;
@@ -1093,7 +1100,7 @@ CPLErr GDALWriteIMDFile( const char *pszFilename, char **papszMD )
 /* -------------------------------------------------------------------- */
 /*      Close off.                                                      */
 /* -------------------------------------------------------------------- */
-    if( osCurSection.size() )
+    if( !osCurSection.empty() )
         bOK &= VSIFPrintfL( fp, "END_GROUP = %s\n", osCurSection.c_str() ) > 0;
 
     bOK &= VSIFPrintfL( fp, "END;\n" ) > 0;
diff --git a/gcore/gdal_mdreader.h b/gcore/gdal_mdreader.h
index 2c69a56..93e3c75 100644
--- a/gcore/gdal_mdreader.h
+++ b/gcore/gdal_mdreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_mdreader.h 33694 2016-03-10 17:54:30Z goatbar $
+ * $Id: gdal_mdreader.h 35883 2016-10-24 05:49:15Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata (mainly the remote sensing imagery) from files of
@@ -31,7 +31,6 @@
 #ifndef GDAL_MDREADER_H_INCLUDED
 #define GDAL_MDREADER_H_INCLUDED
 
-
 #include "cpl_port.h"
 #include "gdal_priv.h"
 
@@ -88,7 +87,6 @@ typedef enum {
                MDR_LS | MDR_RE | MDR_KOMPSAT | MDR_EROS | MDR_ALOS /**< any reader */
 } MDReaders;
 
-
 /**
  * The base class for all metadata readers
  */
@@ -156,11 +154,13 @@ protected:
     virtual char** AddXMLNameValueToList(char** papszList, const char *pszName,
                                          const char *pszValue);
 protected:
+//! @cond Doxygen_Suppress
     char **m_papszIMDMD;
     char **m_papszRPCMD;
     char **m_papszIMAGERYMD;
     char **m_papszDEFAULTMD;
     bool m_bIsMetadataLoad;
+//! @endcond
 };
 
 /**
@@ -187,7 +187,9 @@ public:
                                         char **papszSiblingFiles,
                                         GUInt32 nType = MDR_ANY);
 protected:
+//! @cond Doxygen_Suppress
     GDALMDReaderBase *m_pReader;
+//! @endcond
 };
 
 // misc
diff --git a/gcore/gdal_misc.cpp b/gcore/gdal_misc.cpp
index 4702cc5..5ccce78 100644
--- a/gcore/gdal_misc.cpp
+++ b/gcore/gdal_misc.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_misc.cpp 33873 2016-04-03 14:13:37Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Free standing functions for GDAL.
@@ -28,20 +27,37 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h"
-#include "cpl_minixml.h"
-#include "cpl_multiproc.h"
-#include "gdal_mdreader.h"
-#include "gdal_priv.h"
-#include "ogr_spatialref.h"
+#include "cpl_port.h"
+#include "gdal.h"
 
 #include <cctype>
-
+#include <cerrno>
+#include <clocale>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <fcntl.h>
+
+#include <algorithm>
 #include <iostream>
 #include <limits>
 #include <string>
 
-CPL_CVSID("$Id: gdal_misc.cpp 33873 2016-04-03 14:13:37Z rouault $");
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal_mdreader.h"
+#include "gdal_priv.h"
+#include "gdal_version.h"
+#include "ogr_core.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: gdal_misc.cpp 36763 2016-12-09 22:10:55Z rouault $");
 
 /************************************************************************/
 /*                         GDALDataTypeUnion()                          */
@@ -61,60 +77,63 @@ GDALDataType CPL_STDCALL
 GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
 
 {
-    int         bFloating, nBits, bSigned;
+    bool bSigned = false;
+    bool bFloating = false;
+    int nBits = 0;
 
-    int bComplex = GDALDataTypeIsComplex(eType1) | GDALDataTypeIsComplex(eType2);
+    const bool bComplex = CPL_TO_BOOL(
+        GDALDataTypeIsComplex(eType1) | GDALDataTypeIsComplex(eType2) );
 
     switch( eType1 )
     {
       case GDT_Byte:
         nBits = 8;
-        bSigned = FALSE;
-        bFloating = FALSE;
+        bSigned = false;
+        bFloating = false;
         break;
 
       case GDT_Int16:
       case GDT_CInt16:
         nBits = 16;
-        bSigned = TRUE;
-        bFloating = FALSE;
+        bSigned = true;
+        bFloating = false;
         break;
 
       case GDT_UInt16:
         nBits = 16;
-        bSigned = FALSE;
-        bFloating = FALSE;
+        bSigned = false;
+        bFloating = false;
         break;
 
       case GDT_Int32:
       case GDT_CInt32:
         nBits = 32;
-        bSigned = TRUE;
-        bFloating = FALSE;
+        bSigned = true;
+        bFloating = false;
         break;
 
       case GDT_UInt32:
         nBits = 32;
-        bSigned = FALSE;
-        bFloating = FALSE;
+        bSigned = false;
+        bFloating = false;
         break;
 
       case GDT_Float32:
       case GDT_CFloat32:
         nBits = 32;
-        bSigned = TRUE;
-        bFloating = TRUE;
+        bSigned = true;
+        bFloating = true;
         break;
 
       case GDT_Float64:
       case GDT_CFloat64:
         nBits = 64;
-        bSigned = TRUE;
-        bFloating = TRUE;
+        bSigned = true;
+        bFloating = true;
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return GDT_Unknown;
     }
 
@@ -125,40 +144,40 @@ GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
 
       case GDT_Int16:
       case GDT_CInt16:
-        nBits = MAX(nBits,16);
-        bSigned = TRUE;
+        nBits = std::max(nBits, 16);
+        bSigned = true;
         break;
 
       case GDT_UInt16:
-        nBits = MAX(nBits,16);
+        nBits = std::max(nBits, 16);
         break;
 
       case GDT_Int32:
       case GDT_CInt32:
-        nBits = MAX(nBits,32);
-        bSigned = TRUE;
+        nBits = std::max(nBits, 32);
+        bSigned = true;
         break;
 
       case GDT_UInt32:
-        nBits = MAX(nBits,32);
+        nBits = std::max(nBits, 32);
         break;
 
       case GDT_Float32:
       case GDT_CFloat32:
-        nBits = MAX(nBits,32);
-        bSigned = TRUE;
-        bFloating = TRUE;
+        nBits = std::max(nBits, 32);
+        bSigned = true;
+        bFloating = true;
         break;
 
       case GDT_Float64:
       case GDT_CFloat64:
-        nBits = MAX(nBits,64);
-        bSigned = TRUE;
-        bFloating = TRUE;
+        nBits = std::max(nBits, 64);
+        bSigned = true;
+        bFloating = true;
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return GDT_Unknown;
     }
 
@@ -186,7 +205,6 @@ GDALDataTypeUnion( GDALDataType eType1, GDALDataType eType2 )
         return GDT_Float64;
 }
 
-
 /************************************************************************/
 /*                        GDALGetDataTypeSizeBytes()                    */
 /************************************************************************/
@@ -402,21 +420,24 @@ GDALDataType CPL_STDCALL GDALGetDataTypeByName( const char *pszName )
 /*                      GDALAdjustValueToDataType()                     */
 /************************************************************************/
 
-template<class T> static inline void ClampAndRound(double& dfValue, int& bClamped, int &bRounded)
+template<class T> static inline void ClampAndRound(
+    double& dfValue, bool& bClamped, bool &bRounded )
 {
+    // TODO(schwehr): Rework this template.  ::min() versus ::lowest.
+
     if (dfValue < std::numeric_limits<T>::min())
     {
-        bClamped = TRUE;
+        bClamped = true;
         dfValue = static_cast<double>(std::numeric_limits<T>::min());
     }
     else if (dfValue > std::numeric_limits<T>::max())
     {
-        bClamped = TRUE;
+        bClamped = true;
         dfValue = static_cast<double>(std::numeric_limits<T>::max());
     }
     else if (dfValue != static_cast<double>(static_cast<T>(dfValue)))
     {
-        bRounded = TRUE;
+        bRounded = true;
         dfValue = static_cast<double>(static_cast<T>(floor(dfValue + 0.5)));
     }
 }
@@ -436,9 +457,11 @@ template<class T> static inline void ClampAndRound(double& dfValue, int& bClampe
  * @since GDAL 2.1
  */
 
-double GDALAdjustValueToDataType( GDALDataType eDT, double dfValue, int* pbClamped, int* pbRounded )
+double GDALAdjustValueToDataType(
+    GDALDataType eDT, double dfValue, int* pbClamped, int* pbRounded )
 {
-    int bClamped = FALSE, bRounded = FALSE;
+    bool bClamped = false;
+    bool bRounded = false;
     switch(eDT)
     {
         case GDT_Byte:
@@ -458,18 +481,25 @@ double GDALAdjustValueToDataType( GDALDataType eDT, double dfValue, int* pbClamp
             break;
         case GDT_Float32:
         {
+            // TODO(schwehr): ::min() versus ::lowest.
+            // Use ClampAndRound after it has been fixed.
             if ( dfValue < -std::numeric_limits<float>::max())
             {
                 bClamped = TRUE;
-                dfValue = static_cast<double>(-std::numeric_limits<float>::max());
+                dfValue = static_cast<double>(
+                    -std::numeric_limits<float>::max());
             }
             else if (dfValue > std::numeric_limits<float>::max())
             {
                 bClamped = TRUE;
-                dfValue = static_cast<double>(std::numeric_limits<float>::max());
+                dfValue = static_cast<double>(
+                    std::numeric_limits<float>::max());
             }
             else
             {
+                // Intentionaly loose precision.
+                // TODO(schwehr): Is the double cast really necessary?
+                // If so, why?  What will fail?
                 dfValue = static_cast<double>(static_cast<float>(dfValue));
             }
             break;
@@ -485,6 +515,38 @@ double GDALAdjustValueToDataType( GDALDataType eDT, double dfValue, int* pbClamp
 }
 
 /************************************************************************/
+/*                        GDALGetNonComplexDataType()                */
+/************************************************************************/
+/**
+ * \brief Return the base data type for the specified input.
+ *
+ * If the input data type is complex this function returns the base type
+ * i.e. the data type of the real and imaginary parts (non-complex).
+ * If the input data type is already non-complex, then it is returned
+ * unchanged.
+ *
+ * @param eDataType type, such as GDT_CFloat32.
+ *
+ * @return GDAL data type.
+ */
+GDALDataType CPL_STDCALL GDALGetNonComplexDataType( GDALDataType eDataType )
+{
+    switch( eDataType )
+    {
+      case GDT_CInt16:
+        return GDT_Int16;
+      case GDT_CInt32:
+        return GDT_Int32;
+      case GDT_CFloat32:
+        return GDT_Float32;
+      case GDT_CFloat64:
+        return GDT_Float64;
+      default:
+        return eDataType;
+    }
+}
+
+/************************************************************************/
 /*                        GDALGetAsyncStatusTypeByName()                */
 /************************************************************************/
 /**
@@ -497,16 +559,16 @@ double GDALAdjustValueToDataType( GDALDataType eDT, double dfValue, int* pbClamp
  *
  * @return GDAL AsyncStatus type.
  */
-GDALAsyncStatusType CPL_DLL CPL_STDCALL GDALGetAsyncStatusTypeByName( const char *pszName )
+GDALAsyncStatusType CPL_DLL CPL_STDCALL GDALGetAsyncStatusTypeByName(
+    const char *pszName )
 {
     VALIDATE_POINTER1( pszName, "GDALGetAsyncStatusTypeByName", GARIO_ERROR);
 
-    int	iType;
-
-    for( iType = 1; iType < GARIO_TypeCount; iType++ )
+    for( int iType = 1; iType < GARIO_TypeCount; iType++ )
     {
         if( GDALGetAsyncStatusTypeName((GDALAsyncStatusType)iType) != NULL
-            && EQUAL(GDALGetAsyncStatusTypeName((GDALAsyncStatusType)iType), pszName) )
+            && EQUAL(GDALGetAsyncStatusTypeName((GDALAsyncStatusType)iType),
+                     pszName) )
         {
             return (GDALAsyncStatusType)iType;
         }
@@ -515,7 +577,6 @@ GDALAsyncStatusType CPL_DLL CPL_STDCALL GDALGetAsyncStatusTypeByName( const char
     return GARIO_ERROR;
 }
 
-
 /************************************************************************/
 /*                        GDALGetAsyncStatusTypeName()                 */
 /************************************************************************/
@@ -533,7 +594,8 @@ GDALAsyncStatusType CPL_DLL CPL_STDCALL GDALGetAsyncStatusTypeByName( const char
  * @return string corresponding to type.
  */
 
- const char * CPL_STDCALL GDALGetAsyncStatusTypeName( GDALAsyncStatusType eAsyncStatusType )
+ const char * CPL_STDCALL GDALGetAsyncStatusTypeName(
+     GDALAsyncStatusType eAsyncStatusType )
 
 {
     switch( eAsyncStatusType )
@@ -549,6 +611,7 @@ GDALAsyncStatusType CPL_DLL CPL_STDCALL GDALGetAsyncStatusTypeByName( const char
 
       case GARIO_COMPLETE:
         return "COMPLETE";
+
       default:
         return NULL;
     }
@@ -692,11 +755,13 @@ const char *GDALGetColorInterpretationName( GDALColorInterp eInterp )
 GDALColorInterp GDALGetColorInterpretationByName( const char *pszName )
 
 {
-    VALIDATE_POINTER1( pszName, "GDALGetColorInterpretationByName", GCI_Undefined );
+    VALIDATE_POINTER1( pszName, "GDALGetColorInterpretationByName",
+                       GCI_Undefined );
 
     for( int iType = 0; iType <= GCI_Max; iType++ )
     {
-        if( EQUAL(GDALGetColorInterpretationName((GDALColorInterp)iType), pszName) )
+        if( EQUAL(GDALGetColorInterpretationName((GDALColorInterp)iType),
+                  pszName) )
         {
             return (GDALColorInterp)iType;
         }
@@ -709,6 +774,12 @@ GDALColorInterp GDALGetColorInterpretationByName( const char *pszName )
 /*                     GDALGetRandomRasterSample()                      */
 /************************************************************************/
 
+/** Undocumented
+ * @param hBand undocumented.
+ * @param nSamples undocumented.
+ * @param pafSampleBuf undocumented.
+ * @return undocumented
+ */
 int CPL_STDCALL
 GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
                            float *pafSampleBuf )
@@ -725,23 +796,21 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
 /*      Figure out the ratio of blocks we will read to get an           */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
-    int         nBlockXSize, nBlockYSize;
-    int         nBlocksPerRow, nBlocksPerColumn;
-    int         nSampleRate;
-    int         bGotNoDataValue;
-    int         nActualSamples = 0;
-    int         nBlockSampleRate;
-    int         nBlockPixels, nBlockCount;
+    int bGotNoDataValue = FALSE;
 
     double dfNoDataValue = poBand->GetNoDataValue( &bGotNoDataValue );
 
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
     poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    nBlocksPerRow = (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
-    nBlocksPerColumn = (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize;
+    const int nBlocksPerRow =
+        (poBand->GetXSize() + nBlockXSize - 1) / nBlockXSize;
+    const int nBlocksPerColumn =
+        (poBand->GetYSize() + nBlockYSize - 1) / nBlockYSize;
 
-    nBlockPixels = nBlockXSize * nBlockYSize;
-    nBlockCount = nBlocksPerRow * nBlocksPerColumn;
+    const int nBlockPixels = nBlockXSize * nBlockYSize;
+    const int nBlockCount = nBlocksPerRow * nBlocksPerColumn;
 
     if( nBlocksPerRow == 0 || nBlocksPerColumn == 0 || nBlockPixels == 0
         || nBlockCount == 0 )
@@ -753,7 +822,8 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
         return FALSE;
     }
 
-    nSampleRate = (int) MAX(1,sqrt((double) nBlockCount)-2.0);
+    int nSampleRate = static_cast<int>(
+        std::max(1.0, sqrt( static_cast<double>(nBlockCount) ) - 2.0));
 
     if( nSampleRate == nBlocksPerRow && nSampleRate > 1 )
         nSampleRate--;
@@ -762,45 +832,48 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
            && ((nBlockCount-1) / nSampleRate + 1) * nBlockPixels < nSamples )
         nSampleRate--;
 
-    if ((nSamples / ((nBlockCount-1) / nSampleRate + 1)) == 0)
-        nBlockSampleRate = 1;
-    else
+    int nBlockSampleRate = 1;
+
+    if ((nSamples / ((nBlockCount-1) / nSampleRate + 1)) != 0)
         nBlockSampleRate =
-            MAX(1,nBlockPixels / (nSamples / ((nBlockCount-1) / nSampleRate + 1)));
+            std::max( 1,
+                 nBlockPixels /
+                 (nSamples / ((nBlockCount-1) / nSampleRate + 1)));
+
+    int nActualSamples = 0;
 
     for( int iSampleBlock = 0;
          iSampleBlock < nBlockCount;
          iSampleBlock += nSampleRate )
     {
-        double dfValue = 0.0, dfReal, dfImag;
-        int  iXBlock, iYBlock, iX, iY, iXValid, iYValid, iRemainder = 0;
-        GDALRasterBlock *poBlock;
 
-        iYBlock = iSampleBlock / nBlocksPerRow;
-        iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
+        const int iYBlock = iSampleBlock / nBlocksPerRow;
+        const int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
 
-        poBlock = poBand->GetLockedBlockRef( iXBlock, iYBlock );
+        GDALRasterBlock * const poBlock =
+            poBand->GetLockedBlockRef( iXBlock, iYBlock );
         if( poBlock == NULL )
             continue;
         void* pDataRef = poBlock->GetDataRef();
 
+        int iXValid = nBlockXSize;
         if( (iXBlock + 1) * nBlockXSize > poBand->GetXSize() )
             iXValid = poBand->GetXSize() - iXBlock * nBlockXSize;
-        else
-            iXValid = nBlockXSize;
 
+        int iYValid = nBlockYSize;
         if( (iYBlock + 1) * nBlockYSize > poBand->GetYSize() )
             iYValid = poBand->GetYSize() - iYBlock * nBlockYSize;
-        else
-            iYValid = nBlockYSize;
 
-        for( iY = 0; iY < iYValid; iY++ )
+        int iRemainder = 0;
+
+        for( int iY = 0; iY < iYValid; iY++ )
         {
-            for( iX = iRemainder; iX < iXValid; iX += nBlockSampleRate )
+            int iX = iRemainder;  // Used after for.
+            for( ; iX < iXValid; iX += nBlockSampleRate )
             {
-                int     iOffset;
+                double dfValue = 0.0;
+                const int iOffset = iX + iY * nBlockXSize;
 
-                iOffset = iX + iY * nBlockXSize;
                 switch( poBlock->GetDataType() )
                 {
                   case GDT_Byte:
@@ -825,27 +898,36 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
                     dfValue = ((double *) pDataRef)[iOffset];
                     break;
                   case GDT_CInt16:
-                    dfReal = ((GInt16 *) pDataRef)[iOffset*2];
-                    dfImag = ((GInt16 *) pDataRef)[iOffset*2+1];
+                  {
+                    // TODO(schwehr): Clean up casts.
+                    const double dfReal = ((GInt16 *) pDataRef)[iOffset*2];
+                    const double dfImag = ((GInt16 *) pDataRef)[iOffset*2+1];
                     dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
                     break;
+                  }
                   case GDT_CInt32:
-                    dfReal = ((GInt32 *) pDataRef)[iOffset*2];
-                    dfImag = ((GInt32 *) pDataRef)[iOffset*2+1];
+                  {
+                    const double dfReal = ((GInt32 *) pDataRef)[iOffset*2];
+                    const double dfImag = ((GInt32 *) pDataRef)[iOffset*2+1];
                     dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
                     break;
+                  }
                   case GDT_CFloat32:
-                    dfReal = ((float *) pDataRef)[iOffset*2];
-                    dfImag = ((float *) pDataRef)[iOffset*2+1];
+                  {
+                    const double dfReal = ((float *) pDataRef)[iOffset*2];
+                    const double dfImag = ((float *) pDataRef)[iOffset*2+1];
                     dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
                     break;
+                  }
                   case GDT_CFloat64:
-                    dfReal = ((double *) pDataRef)[iOffset*2];
-                    dfImag = ((double *) pDataRef)[iOffset*2+1];
+                  {
+                    const double dfReal = ((double *) pDataRef)[iOffset*2];
+                    const double dfImag = ((double *) pDataRef)[iOffset*2+1];
                     dfValue = sqrt(dfReal*dfReal + dfImag*dfImag);
                     break;
+                  }
                   default:
-                    CPLAssert( FALSE );
+                    CPLAssert( false );
                 }
 
                 if( bGotNoDataValue && dfValue == dfNoDataValue )
@@ -868,7 +950,17 @@ GDALGetRandomRasterSample( GDALRasterBandH hBand, int nSamples,
 /*                            GDALInitGCPs()                            */
 /************************************************************************/
 
-void CPL_STDCALL GDALInitGCPs( int nCount, GDAL_GCP * psGCP )
+/** Initialize an array of GCPs.
+ *
+ * Numeric values are initialized to 0 and strings to the empty string ""
+ * allocated with CPLStrdup()
+ * An array initialized with GDALInitGCPs() must be de-initialized with
+ * GDALDeinitGCPs().
+ *
+ * @param nCount number of GCPs in psGCP
+ * @param psGCP array of GCPs of size nCount.
+ */
+void CPL_STDCALL GDALInitGCPs( int nCount, GDAL_GCP *psGCP )
 
 {
     if( nCount > 0 )
@@ -889,7 +981,12 @@ void CPL_STDCALL GDALInitGCPs( int nCount, GDAL_GCP * psGCP )
 /*                           GDALDeinitGCPs()                           */
 /************************************************************************/
 
-void CPL_STDCALL GDALDeinitGCPs( int nCount, GDAL_GCP * psGCP )
+/** De-initialize an array of GCPs (initialized with GDALInitGCPs())
+ *
+ * @param nCount number of GCPs in psGCP
+ * @param psGCP array of GCPs of size nCount.
+ */
+void CPL_STDCALL GDALDeinitGCPs( int nCount, GDAL_GCP *psGCP )
 
 {
     if ( nCount > 0 )
@@ -909,11 +1006,18 @@ void CPL_STDCALL GDALDeinitGCPs( int nCount, GDAL_GCP * psGCP )
 /*                         GDALDuplicateGCPs()                          */
 /************************************************************************/
 
-GDAL_GCP * CPL_STDCALL
-GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
+/** Duplicate an array of GCPs
+ *
+ * The return must be freed with GDALDeinitGCPs() followed by CPLFree()
+ *
+ * @param nCount number of GCPs in psGCP
+ * @param pasGCPList array of GCPs of size nCount.
+ */
+GDAL_GCP * CPL_STDCALL GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
 
 {
-    GDAL_GCP *pasReturn = (GDAL_GCP *) CPLMalloc(sizeof(GDAL_GCP) * nCount);
+    GDAL_GCP *pasReturn = static_cast<GDAL_GCP *>(
+        CPLMalloc(sizeof(GDAL_GCP) * nCount) );
     GDALInitGCPs( nCount, pasReturn );
 
     for( int iGCP = 0; iGCP < nCount; iGCP++ )
@@ -939,6 +1043,7 @@ GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
 /************************************************************************/
 
 /**
+ * \fn GDALFindAssociatedFile(const char*, const char*, char**, int)
  * Find file with alternate extension.
  *
  * Finds the file with the indicated extension, substituting it in place
@@ -964,6 +1069,9 @@ GDALDuplicateGCPs( int nCount, const GDAL_GCP *pasGCPList )
  * file with similar path style as the pszBaseFilename.
  */
 
+/**/
+/**/
+
 CPLString GDALFindAssociatedFile( const char *pszBaseFilename,
                                   const char *pszExt,
                                   char **papszSiblingFiles,
@@ -993,8 +1101,8 @@ CPLString GDALFindAssociatedFile( const char *pszBaseFilename,
     }
     else
     {
-        int iSibling = CSLFindString( papszSiblingFiles,
-                                      CPLGetFilename(osTarget) );
+        const int iSibling = CSLFindString( papszSiblingFiles,
+                                            CPLGetFilename(osTarget) );
         if( iSibling < 0 )
             return "";
 
@@ -1009,17 +1117,20 @@ CPLString GDALFindAssociatedFile( const char *pszBaseFilename,
 /*                         GDALLoadOziMapFile()                         */
 /************************************************************************/
 
-
+/** Helper function for translator implementer wanting support for OZI .map
+ *
+ * @param pszFilename filename of .tab file
+ * @param padfGeoTransform output geotransform. Must hold 6 doubles.
+ * @param ppszWKT output pointer to a string that will be allocated with CPLMalloc().
+ * @param pnGCPCount output pointer to GCP count.
+ * @param ppasGCPs outputer pointer to an array of GCPs.
+ * @return TRUE in case of success, FALSE otherwise.
+ */
 int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
                                     double *padfGeoTransform, char **ppszWKT,
                                     int *pnGCPCount, GDAL_GCP **ppasGCPs )
 
-
 {
-    int	        nCoordinateCount = 0;
-    static const int MAX_GCP = 30;
-    GDAL_GCP    asGCPs[MAX_GCP];
-
     VALIDATE_POINTER1( pszFilename, "GDALLoadOziMapFile", FALSE );
     VALIDATE_POINTER1( padfGeoTransform, "GDALLoadOziMapFile", FALSE );
     VALIDATE_POINTER1( pnGCPCount, "GDALLoadOziMapFile", FALSE );
@@ -1054,8 +1165,7 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
     /* is explained at http://tech.groups.yahoo.com/group/OziUsers-L/message/12484 */
     double dfMSF = 1;
 
-    int	iLine;
-    for ( iLine = 5; iLine < nLines; iLine++ )
+    for ( int iLine = 5; iLine < nLines; iLine++ )
     {
         if ( STARTS_WITH_CI(papszLines[iLine], "MSF,") )
         {
@@ -1075,15 +1185,17 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
             oSRS.exportToWkt( ppszWKT );
     }
 
+    int nCoordinateCount = 0;
+    // TODO(schwehr): Initialize asGCPs.
+    GDAL_GCP asGCPs[30];
+
     // Iterate all lines in the MAP-file
-    for ( iLine = 5; iLine < nLines; iLine++ )
+    for ( int iLine = 5; iLine < nLines; iLine++ )
     {
-        char    **papszTok = NULL;
-
-        papszTok = CSLTokenizeString2( papszLines[iLine], ",",
-                                       CSLT_ALLOWEMPTYTOKENS
-                                       | CSLT_STRIPLEADSPACES
-                                       | CSLT_STRIPENDSPACES );
+        char **papszTok = CSLTokenizeString2( papszLines[iLine], ",",
+                                              CSLT_ALLOWEMPTYTOKENS
+                                              | CSLT_STRIPLEADSPACES
+                                              | CSLT_STRIPENDSPACES );
 
         if ( CSLCount(papszTok) < 12 )
         {
@@ -1095,10 +1207,12 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
              && STARTS_WITH_CI(papszTok[0], "Point")
              && !EQUAL(papszTok[2], "")
              && !EQUAL(papszTok[3], "")
-             && nCoordinateCount < MAX_GCP )
+             && nCoordinateCount <
+             static_cast<int>(CPL_ARRAYSIZE(asGCPs)) )
         {
             bool bReadOk = false;
-            double  dfLon = 0., dfLat = 0.;
+            double dfLon = 0.0;
+            double dfLat = 0.0;
 
             if ( !EQUAL(papszTok[6], "")
                  && !EQUAL(papszTok[7], "")
@@ -1117,16 +1231,17 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
                 // coordinates.
                 if ( eErr == OGRERR_NONE )
                 {
-                    OGRSpatialReference *poLatLong = NULL;
-                    OGRCoordinateTransformation *poTransform = NULL;
+                    OGRSpatialReference *poLatLong = oSRS.CloneGeogCS();
 
-                    poLatLong = oSRS.CloneGeogCS();
                     if ( poLatLong )
                     {
-                        poTransform = OGRCreateCoordinateTransformation( poLatLong, &oSRS );
+                        OGRCoordinateTransformation *poTransform =
+                            OGRCreateCoordinateTransformation( poLatLong,
+                                                               &oSRS );
                         if ( poTransform )
                         {
-                            bReadOk = CPL_TO_BOOL(poTransform->Transform( 1, &dfLon, &dfLat ));
+                            bReadOk = CPL_TO_BOOL(
+                                poTransform->Transform( 1, &dfLon, &dfLat ));
                             delete poTransform;
                         }
                         delete poLatLong;
@@ -1150,8 +1265,10 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
                 GDALInitGCPs( 1, asGCPs + nCoordinateCount );
 
                 // Set pixel/line part
-                asGCPs[nCoordinateCount].dfGCPPixel = CPLAtofM(papszTok[2]) / dfMSF;
-                asGCPs[nCoordinateCount].dfGCPLine = CPLAtofM(papszTok[3]) / dfMSF;
+                asGCPs[nCoordinateCount].dfGCPPixel =
+                    CPLAtofM(papszTok[2]) / dfMSF;
+                asGCPs[nCoordinateCount].dfGCPLine =
+                    CPLAtofM(papszTok[3]) / dfMSF;
 
                 asGCPs[nCoordinateCount].dfGCPX = dfLon;
                 asGCPs[nCoordinateCount].dfGCPY = dfLat;
@@ -1176,8 +1293,9 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
 /*      Try to convert the GCPs into a geotransform definition, if      */
 /*      possible.  Otherwise we will need to use them as GCPs.          */
 /* -------------------------------------------------------------------- */
-    if( !GDALGCPsToGeoTransform( nCoordinateCount, asGCPs, padfGeoTransform,
-                                 CPLTestBool(CPLGetConfigOption("OZI_APPROX_GEOTRANSFORM", "NO")) ) )
+    if( !GDALGCPsToGeoTransform(
+            nCoordinateCount, asGCPs, padfGeoTransform,
+            CPLTestBool(CPLGetConfigOption("OZI_APPROX_GEOTRANSFORM", "NO")) ) )
     {
         if ( pnGCPCount && ppasGCPs )
         {
@@ -1186,8 +1304,8 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
                 "first order geotransform.  Using points as GCPs.",
                 pszFilename );
 
-            *ppasGCPs = (GDAL_GCP *)
-                CPLCalloc( sizeof(GDAL_GCP),nCoordinateCount );
+            *ppasGCPs = static_cast<GDAL_GCP *>(
+                CPLCalloc( sizeof(GDAL_GCP), nCoordinateCount ) );
             memcpy( *ppasGCPs, asGCPs, sizeof(GDAL_GCP) * nCoordinateCount );
             *pnGCPCount = nCoordinateCount;
         }
@@ -1204,11 +1322,19 @@ int CPL_STDCALL GDALLoadOziMapFile( const char *pszFilename,
 /*                       GDALReadOziMapFile()                           */
 /************************************************************************/
 
+/** Helper function for translator implementer wanting support for OZI .map
+ *
+ * @param pszBaseFilename filename whose basename will help building the .map filename.
+ * @param padfGeoTransform output geotransform. Must hold 6 doubles.
+ * @param ppszWKT output pointer to a string that will be allocated with CPLMalloc().
+ * @param pnGCPCount output pointer to GCP count.
+ * @param ppasGCPs outputer pointer to an array of GCPs.
+ * @return TRUE in case of success, FALSE otherwise.
+ */
 int CPL_STDCALL GDALReadOziMapFile( const char * pszBaseFilename,
                                     double *padfGeoTransform, char **ppszWKT,
                                     int *pnGCPCount, GDAL_GCP **ppasGCPs )
 
-
 {
 /* -------------------------------------------------------------------- */
 /*      Try lower case, then upper case.                                */
@@ -1238,34 +1364,37 @@ int CPL_STDCALL GDALReadOziMapFile( const char * pszBaseFilename,
 /************************************************************************/
 /*                         GDALLoadTabFile()                            */
 /*                                                                      */
-/*      Helper function for translator implementer wanting              */
-/*      support for MapInfo .tab-files.                                 */
 /************************************************************************/
 
-#define MAX_GCP 256
-
+/** Helper function for translator implementer wanting support for MapInfo
+ * .tab files.
+ *
+ * @param pszFilename filename of .tab
+ * @param padfGeoTransform output geotransform. Must hold 6 doubles.
+ * @param ppszWKT output pointer to a string that will be allocated with CPLMalloc().
+ * @param pnGCPCount output pointer to GCP count.
+ * @param ppasGCPs outputer pointer to an array of GCPs.
+ * @return TRUE in case of success, FALSE otherwise.
+ */
 int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
                                  double *padfGeoTransform, char **ppszWKT,
                                  int *pnGCPCount, GDAL_GCP **ppasGCPs )
 
-
 {
-    char        **papszTok=NULL;
-    bool        bTypeRasterFound = false;
-    bool        bInsideTableDef = false;
-    int	        nCoordinateCount = 0;
-    GDAL_GCP    asGCPs[MAX_GCP];
-
     char **papszLines = CSLLoad2( pszFilename, 1000, 200, NULL );
 
     if ( !papszLines )
         return FALSE;
 
-    int numLines = CSLCount(papszLines);
+    char **papszTok = NULL;
+    bool bTypeRasterFound = false;
+    bool bInsideTableDef = false;
+    int nCoordinateCount = 0;
+    GDAL_GCP asGCPs[256];  // TODO(schwehr): Initialize.
+    const int numLines = CSLCount(papszLines);
 
     // Iterate all lines in the TAB-file
-    int iLine;
-    for(iLine=0; iLine<numLines; iLine++)
+    for( int iLine=0; iLine<numLines; iLine++ )
     {
         CSLDestroy(papszTok);
         papszTok = CSLTokenizeStringComplex(papszLines[iLine], " \t(),;",
@@ -1296,7 +1425,8 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
         else if (bTypeRasterFound && bInsideTableDef
                  && CSLCount(papszTok) > 4
                  && EQUAL(papszTok[4], "Label")
-                 && nCoordinateCount < MAX_GCP )
+                 && nCoordinateCount <
+                 static_cast<int>(CPL_ARRAYSIZE(asGCPs)) )
         {
             GDALInitGCPs( 1, asGCPs + nCoordinateCount );
 
@@ -1332,16 +1462,18 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
             if( ppszWKT != NULL && *ppszWKT != NULL
                 && STARTS_WITH_CI(*ppszWKT, "PROJCS") )
             {
-                OGRSpatialReference oSRS, oSRSGeogCS;
                 char *pszSrcWKT = *ppszWKT;
 
+                OGRSpatialReference oSRS;
                 oSRS.importFromWkt( &pszSrcWKT );
+
+                OGRSpatialReference oSRSGeogCS;
                 oSRSGeogCS.CopyGeogCSFrom( &oSRS );
                 CPLFree( *ppszWKT );
+
                 oSRSGeogCS.exportToWkt( ppszWKT );
             }
         }
-
     }
 
     CSLDestroy(papszTok);
@@ -1358,18 +1490,19 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
 /*      Try to convert the GCPs into a geotransform definition, if      */
 /*      possible.  Otherwise we will need to use them as GCPs.          */
 /* -------------------------------------------------------------------- */
-    if( !GDALGCPsToGeoTransform( nCoordinateCount, asGCPs, padfGeoTransform,
-                                 CPLTestBool(CPLGetConfigOption("TAB_APPROX_GEOTRANSFORM", "NO")) ) )
+    if( !GDALGCPsToGeoTransform(
+            nCoordinateCount, asGCPs, padfGeoTransform,
+            CPLTestBool(CPLGetConfigOption("TAB_APPROX_GEOTRANSFORM", "NO")) ) )
     {
         if (pnGCPCount && ppasGCPs)
         {
             CPLDebug( "GDAL",
-                "GDALLoadTabFile(%s) found file, was not able to derive a\n"
+                "GDALLoadTabFile(%s) found file, was not able to derive a "
                 "first order geotransform.  Using points as GCPs.",
                 pszFilename );
 
-            *ppasGCPs = (GDAL_GCP *)
-                CPLCalloc( sizeof(GDAL_GCP),nCoordinateCount );
+            *ppasGCPs = static_cast<GDAL_GCP *>(
+                CPLCalloc( sizeof(GDAL_GCP), nCoordinateCount ) );
             memcpy( *ppasGCPs, asGCPs, sizeof(GDAL_GCP) * nCoordinateCount );
             *pnGCPCount = nCoordinateCount;
         }
@@ -1382,42 +1515,42 @@ int CPL_STDCALL GDALLoadTabFile( const char *pszFilename,
     return TRUE;
 }
 
-#undef MAX_GCP
-
 /************************************************************************/
 /*                         GDALReadTabFile()                            */
-/*                                                                      */
-/*      Helper function for translator implementer wanting              */
-/*      support for MapInfo .tab-files.                                 */
 /************************************************************************/
 
+/** Helper function for translator implementer wanting support for MapInfo
+ * .tab files.
+ *
+ * @param pszBaseFilename filename whose basename will help building the .tab filename.
+ * @param padfGeoTransform output geotransform. Must hold 6 doubles.
+ * @param ppszWKT output pointer to a string that will be allocated with CPLMalloc().
+ * @param pnGCPCount output pointer to GCP count.
+ * @param ppasGCPs outputer pointer to an array of GCPs.
+ * @return TRUE in case of success, FALSE otherwise.
+ */
 int CPL_STDCALL GDALReadTabFile( const char * pszBaseFilename,
                                  double *padfGeoTransform, char **ppszWKT,
                                  int *pnGCPCount, GDAL_GCP **ppasGCPs )
 
-
 {
-    return GDALReadTabFile2(pszBaseFilename, padfGeoTransform,
-                            ppszWKT, pnGCPCount, ppasGCPs,
-                            NULL, NULL);
+    return GDALReadTabFile2( pszBaseFilename, padfGeoTransform,
+                             ppszWKT, pnGCPCount, ppasGCPs,
+                             NULL, NULL );
 }
 
-
 int GDALReadTabFile2( const char * pszBaseFilename,
                       double *padfGeoTransform, char **ppszWKT,
                       int *pnGCPCount, GDAL_GCP **ppasGCPs,
                       char** papszSiblingFiles, char** ppszTabFileNameOut )
 {
-    const char	*pszTAB;
-    VSILFILE	*fpTAB;
-
     if (ppszTabFileNameOut)
         *ppszTabFileNameOut = NULL;
 
     if( !GDALCanFileAcceptSidecarFile(pszBaseFilename) )
         return FALSE;
 
-    pszTAB = CPLResetExtension( pszBaseFilename, "tab" );
+    const char *pszTAB = CPLResetExtension( pszBaseFilename, "tab" );
 
     if (papszSiblingFiles)
     {
@@ -1443,7 +1576,7 @@ int GDALReadTabFile2( const char * pszBaseFilename,
 /*      Try lower case, then upper case.                                */
 /* -------------------------------------------------------------------- */
 
-    fpTAB = VSIFOpenL( pszTAB, "rt" );
+    VSILFILE *fpTAB = VSIFOpenL( pszTAB, "rt" );
 
     if( fpTAB == NULL && VSIIsCaseSensitiveFS(pszTAB) )
     {
@@ -1502,21 +1635,21 @@ int CPL_STDCALL
 GDALLoadWorldFile( const char *pszFilename, double *padfGeoTransform )
 
 {
-    char        **papszLines;
-
     VALIDATE_POINTER1( pszFilename, "GDALLoadWorldFile", FALSE );
     VALIDATE_POINTER1( padfGeoTransform, "GDALLoadWorldFile", FALSE );
 
-    papszLines = CSLLoad2( pszFilename, 100, 100, NULL );
+    char **papszLines = CSLLoad2( pszFilename, 100, 100, NULL );
 
     if ( !papszLines )
         return FALSE;
 
-   double world[6];
+    double world[6] = { 0.0 };
     // reads the first 6 non-empty lines
     int nLines = 0;
-    int nLinesCount = CSLCount(papszLines);
-    for( int i = 0; i < nLinesCount && nLines < 6; ++i )
+    const int nLinesCount = CSLCount(papszLines);
+    for( int i = 0;
+         i < nLinesCount && nLines < static_cast<int>(CPL_ARRAYSIZE(world));
+         ++i )
     {
         CPLString line(papszLines[i]);
         if( line.Trim().empty() )
@@ -1597,18 +1730,14 @@ GDALReadWorldFile( const char *pszBaseFilename, const char *pszExtension,
                    double *padfGeoTransform )
 
 {
-    return GDALReadWorldFile2(pszBaseFilename, pszExtension,
-                              padfGeoTransform, NULL, NULL);
+    return GDALReadWorldFile2( pszBaseFilename, pszExtension,
+                               padfGeoTransform, NULL, NULL );
 }
 
 int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
                         double *padfGeoTransform, char** papszSiblingFiles,
                         char** ppszWorldFileNameOut )
 {
-    const char  *pszTFW;
-    char        szExtUpper[32], szExtLower[32];
-    int         i;
-
     VALIDATE_POINTER1( pszBaseFilename, "GDALReadWorldFile", FALSE );
     VALIDATE_POINTER1( padfGeoTransform, "GDALReadWorldFile", FALSE );
 
@@ -1624,13 +1753,13 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
 /* -------------------------------------------------------------------- */
     if( pszExtension == NULL )
     {
-        char szDerivedExtension[100];
-        std::string  oBaseExt = CPLGetExtension( pszBaseFilename );
+        const std::string oBaseExt = CPLGetExtension( pszBaseFilename );
 
         if( oBaseExt.length() < 2 )
             return FALSE;
 
         // windows version - first + last + 'w'
+        char szDerivedExtension[100] = { '\0' };
         szDerivedExtension[0] = oBaseExt[0];
         szDerivedExtension[1] = oBaseExt[oBaseExt.length()-1];
         szDerivedExtension[2] = 'w';
@@ -1645,10 +1774,11 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
         if( oBaseExt.length() > sizeof(szDerivedExtension)-2 )
             return FALSE;
 
-        snprintf( szDerivedExtension, sizeof(szDerivedExtension), "%sw", oBaseExt.c_str() );
+        snprintf( szDerivedExtension, sizeof(szDerivedExtension),
+                  "%sw", oBaseExt.c_str() );
         return GDALReadWorldFile2( pszBaseFilename, szDerivedExtension,
-                                  padfGeoTransform, papszSiblingFiles,
-                                  ppszWorldFileNameOut );
+                                   padfGeoTransform, papszSiblingFiles,
+                                   ppszWorldFileNameOut );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1660,22 +1790,23 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
 /* -------------------------------------------------------------------- */
 /*      Generate upper and lower case versions of the extension.        */
 /* -------------------------------------------------------------------- */
+    char szExtUpper[32] = { '\0' };
+    char szExtLower[32] = { '\0' };
     CPLStrlcpy( szExtUpper, pszExtension, sizeof(szExtUpper) );
     CPLStrlcpy( szExtLower, pszExtension, sizeof(szExtLower) );
 
-    for( i = 0; szExtUpper[i] != '\0'; i++ )
+    for( int i = 0; szExtUpper[i] != '\0'; i++ )
     {
-        szExtUpper[i] = (char) toupper(szExtUpper[i]);
-        szExtLower[i] = (char) tolower(szExtLower[i]);
+        szExtUpper[i] = static_cast<char>( toupper(szExtUpper[i]) );
+        szExtLower[i] = static_cast<char>( tolower(szExtLower[i]) );
     }
 
-    VSIStatBufL sStatBuf;
-
-    pszTFW = CPLResetExtension( pszBaseFilename, szExtLower );
+    const char *pszTFW = CPLResetExtension( pszBaseFilename, szExtLower );
 
     if (papszSiblingFiles)
     {
-        int iSibling = CSLFindString(papszSiblingFiles, CPLGetFilename(pszTFW));
+        const int iSibling =
+            CSLFindString(papszSiblingFiles, CPLGetFilename(pszTFW));
         if (iSibling >= 0)
         {
             CPLString osTFWFilename = pszBaseFilename;
@@ -1696,6 +1827,7 @@ int GDALReadWorldFile2( const char *pszBaseFilename, const char *pszExtension,
 /*      Try lower case, then upper case.                                */
 /* -------------------------------------------------------------------- */
 
+    VSIStatBufL sStatBuf;
     bool bGotTFW = VSIStatExL( pszTFW, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0;
 
     if( !bGotTFW  && VSIIsCaseSensitiveFS(pszTFW) )
@@ -1780,17 +1912,16 @@ GDALWriteWorldFile( const char * pszBaseFilename, const char *pszExtension,
 /* -------------------------------------------------------------------- */
 /*      Update extension, and write to disk.                            */
 /* -------------------------------------------------------------------- */
-    const char  *pszTFW;
-    VSILFILE    *fpTFW;
-
-    pszTFW = CPLResetExtension( pszBaseFilename, pszExtension );
-    fpTFW = VSIFOpenL( pszTFW, "wt" );
+    const char *pszTFW = CPLResetExtension( pszBaseFilename, pszExtension );
+    VSILFILE * const fpTFW = VSIFOpenL( pszTFW, "wt" );
     if( fpTFW == NULL )
         return FALSE;
 
-    int bRet = ( VSIFWriteL( (void *) osTFWText.c_str(), osTFWText.size(), 1, fpTFW ) == 1 );
+    const int bRet =
+        VSIFWriteL( (void *) osTFWText.c_str(), osTFWText.size(), 1, fpTFW )
+        == 1;
     if( VSIFCloseL( fpTFW ) != 0 )
-        bRet = FALSE;
+        return FALSE;
 
     return bRet;
 }
@@ -1839,11 +1970,11 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
 #ifdef PAM_ENABLED
         osBuildInfo += "PAM_ENABLED=YES\n";
 #endif
-        osBuildInfo += "OGR_ENABLED=YES\n";
+        osBuildInfo += "OGR_ENABLED=YES\n";  // Deprecated.  Always yes.
 
         CPLFree(CPLGetTLS(CTLS_VERSIONINFO));
         CPLSetTLS(CTLS_VERSIONINFO, CPLStrdup(osBuildInfo), TRUE );
-        return (char *) CPLGetTLS(CTLS_VERSIONINFO);
+        return static_cast<char *>( CPLGetTLS(CTLS_VERSIONINFO) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1852,7 +1983,8 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
 /* -------------------------------------------------------------------- */
     if( pszRequest != NULL && EQUAL(pszRequest,"LICENSE") )
     {
-        char* pszResultLicence = (char*) CPLGetTLS( CTLS_VERSIONINFO_LICENCE );
+        char* pszResultLicence = reinterpret_cast<char *>(
+            CPLGetTLS( CTLS_VERSIONINFO_LICENCE ) );
         if( pszResultLicence != NULL )
         {
             return pszResultLicence;
@@ -1860,7 +1992,6 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
 
         const char *pszFilename = CPLFindFile( "etc", "LICENSE.TXT" );
         VSILFILE *fp = NULL;
-        int  nLength;
 
         if( pszFilename != NULL )
             fp = VSIFOpenL( pszFilename, "r" );
@@ -1869,12 +2000,17 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
         {
             if( VSIFSeekL( fp, 0, SEEK_END ) == 0 )
             {
-                nLength = (int) VSIFTellL( fp ) + 1;
+                // TODO(schwehr): Handle if VSITellL returns a value too large
+                // for size_t.
+                const size_t nLength =
+                    static_cast<size_t>( VSIFTellL( fp ) + 1 );
                 if( VSIFSeekL( fp, SEEK_SET, 0 ) == 0 )
                 {
-                    pszResultLicence = (char *) VSICalloc(1,nLength);
+                    pszResultLicence = static_cast<char *>(
+                        VSICalloc(1, nLength) );
                     if (pszResultLicence)
-                        CPL_IGNORE_RET_VAL(VSIFReadL( pszResultLicence, 1, nLength-1, fp ));
+                        CPL_IGNORE_RET_VAL(
+                            VSIFReadL( pszResultLicence, 1, nLength - 1, fp ) );
                 }
             }
 
@@ -1913,7 +2049,7 @@ const char * CPL_STDCALL GDALVersionInfo( const char *pszRequest )
 
     CPLFree(CPLGetTLS(CTLS_VERSIONINFO)); // clear old value.
     CPLSetTLS(CTLS_VERSIONINFO, CPLStrdup(osVersionInfo), TRUE );
-    return (char *) CPLGetTLS(CTLS_VERSIONINFO);
+    return static_cast<char *>( CPLGetTLS(CTLS_VERSIONINFO) );
 }
 
 /************************************************************************/
@@ -1945,7 +2081,8 @@ int CPL_STDCALL GDALCheckVersion( int nVersionMajor, int nVersionMinor,
     if (pszCallingComponentName)
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s was compiled against GDAL %d.%d but current library version is %d.%d\n",
+                  "%s was compiled against GDAL %d.%d, but "
+                  "the current library version is %d.%d",
                   pszCallingComponentName, nVersionMajor, nVersionMinor,
                   GDAL_VERSION_MAJOR, GDAL_VERSION_MINOR);
     }
@@ -1954,11 +2091,10 @@ int CPL_STDCALL GDALCheckVersion( int nVersionMajor, int nVersionMinor,
 
 /************************************************************************/
 /*                            GDALDecToDMS()                            */
-/*                                                                      */
-/*      Translate a decimal degrees value to a DMS string with          */
-/*      hemisphere.                                                     */
 /************************************************************************/
 
+/** Translate a decimal degrees value to a DMS string with hemisphere.
+ */
 const char * CPL_STDCALL GDALDecToDMS( double dfAngle, const char * pszAxis,
                           int nPrecision )
 
@@ -2025,13 +2161,12 @@ double CPL_STDCALL GDALDecToPackedDMS( double dfDec )
  * and the fit is poor.
  */
 
+// TODO(schwehr): Add consts to args.
 int CPL_STDCALL
 GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
                         double *padfGeoTransform, int bApproxOK )
 
 {
-    int    i;
-
 /* -------------------------------------------------------------------- */
 /*      Recognise a few special cases.                                  */
 /* -------------------------------------------------------------------- */
@@ -2110,23 +2245,23 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
     double min_geoy = pasGCPs[0].dfGCPY;
     double max_geoy = pasGCPs[0].dfGCPY;
 
-    for (i = 1; i < nGCPCount; ++i) {
-        min_pixel = MIN(min_pixel, pasGCPs[i].dfGCPPixel);
-        max_pixel = MAX(max_pixel, pasGCPs[i].dfGCPPixel);
-        min_line = MIN(min_line, pasGCPs[i].dfGCPLine);
-        max_line = MAX(max_line, pasGCPs[i].dfGCPLine);
-        min_geox = MIN(min_geox, pasGCPs[i].dfGCPX);
-        max_geox = MAX(max_geox, pasGCPs[i].dfGCPX);
-        min_geoy = MIN(min_geoy, pasGCPs[i].dfGCPY);
-        max_geoy = MAX(max_geoy, pasGCPs[i].dfGCPY);
+    for( int i = 1; i < nGCPCount; ++i ) {
+        min_pixel = std::min(min_pixel, pasGCPs[i].dfGCPPixel);
+        max_pixel = std::max(max_pixel, pasGCPs[i].dfGCPPixel);
+        min_line = std::min(min_line, pasGCPs[i].dfGCPLine);
+        max_line = std::max(max_line, pasGCPs[i].dfGCPLine);
+        min_geox = std::min(min_geox, pasGCPs[i].dfGCPX);
+        max_geox = std::max(max_geox, pasGCPs[i].dfGCPX);
+        min_geoy = std::min(min_geoy, pasGCPs[i].dfGCPY);
+        max_geoy = std::max(max_geoy, pasGCPs[i].dfGCPY);
     }
 
     double EPS = 1.0e-12;
 
-    if( ABS(max_pixel - min_pixel) < EPS
-        || ABS(max_line - min_line) < EPS
-        || ABS(max_geox - min_geox) < EPS
-        || ABS(max_geoy - min_geoy) < EPS)
+    if( std::abs(max_pixel - min_pixel) < EPS
+        || std::abs(max_line - min_line) < EPS
+        || std::abs(max_geox - min_geox) < EPS
+        || std::abs(max_geoy - min_geoy) < EPS)
     {
         return FALSE;  // degenerate in at least one dimension.
     }
@@ -2149,15 +2284,22 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 
 /* -------------------------------------------------------------------- */
 /* In the general case, do a least squares error approximation by       */
-/* solving the equation Sum[(A - B*x + C*y - Lon)^2] = minimum		*/
-/* -------------------------------------------------------------------- */
-
-    double sum_x = 0.0, sum_y = 0.0, sum_xy = 0.0, sum_xx = 0.0, sum_yy = 0.0;
-    double sum_Lon = 0.0, sum_Lonx = 0.0, sum_Lony = 0.0;
-    double sum_Lat = 0.0, sum_Latx = 0.0, sum_Laty = 0.0;
-    double divisor;
-
-    for (i = 0; i < nGCPCount; ++i) {
+/* solving the equation Sum[(A - B*x + C*y - Lon)^2] = minimum          */
+/* -------------------------------------------------------------------- */
+
+    double sum_x = 0.0;
+    double sum_y = 0.0;
+    double sum_xy = 0.0;
+    double sum_xx = 0.0;
+    double sum_yy = 0.0;
+    double sum_Lon = 0.0;
+    double sum_Lonx = 0.0;
+    double sum_Lony = 0.0;
+    double sum_Lat = 0.0;
+    double sum_Latx = 0.0;
+    double sum_Laty = 0.0;
+
+    for ( int i = 0; i < nGCPCount; ++i ) {
         double pixel, line, geox, geoy;
 
         GDALApplyGeoTransform(pl_normalize,
@@ -2182,7 +2324,8 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
         sum_Laty += geoy * line;
     }
 
-    divisor = nGCPCount * (sum_xx * sum_yy - sum_xy * sum_xy)
+    const double divisor =
+        nGCPCount * (sum_xx * sum_yy - sum_xy * sum_xy)
         + 2 * sum_x * sum_y * sum_xy - sum_y * sum_y * sum_xx
         - sum_x * sum_x * sum_yy;
 
@@ -2195,7 +2338,7 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 /* -------------------------------------------------------------------- */
 /*      Compute top/left origin.                                        */
 /* -------------------------------------------------------------------- */
-    double gt_normalized[6];
+  double gt_normalized[6] = { 0.0 };
     gt_normalized[0] = (sum_Lon * (sum_xx * sum_yy - sum_xy * sum_xy)
                   + sum_Lonx * (sum_y * sum_xy - sum_x *  sum_yy)
                   + sum_Lony * (sum_x * sum_xy - sum_y * sum_xx))
@@ -2236,7 +2379,8 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
 /*      Compose the resulting transformation with the normalization     */
 /*      geotransformations.                                             */
 /* -------------------------------------------------------------------- */
-    double gt1p2[6], inv_geo_normalize[6];
+    double gt1p2[6] = { 0.0 };
+    double inv_geo_normalize[6] = { 0.0 };
     if( !GDALInvGeoTransform(geo_normalize, inv_geo_normalize))
         return FALSE;
 
@@ -2250,31 +2394,32 @@ GDALGCPsToGeoTransform( int nGCPCount, const GDAL_GCP *pasGCPs,
     {
         // FIXME? Not sure if it is the more accurate way of computing
         // pixel size
-        double dfPixelSize = 0.5 * (ABS(padfGeoTransform[1])
-            + ABS(padfGeoTransform[2])
-            + ABS(padfGeoTransform[4])
-            + ABS(padfGeoTransform[5]));
+        double dfPixelSize =
+            0.5 * (std::abs(padfGeoTransform[1])
+            + std::abs(padfGeoTransform[2])
+            + std::abs(padfGeoTransform[4])
+            + std::abs(padfGeoTransform[5]));
 
-        for( i = 0; i < nGCPCount; i++ )
+        for( int i = 0; i < nGCPCount; i++ )
         {
-            double      dfErrorX, dfErrorY;
-
-            dfErrorX =
+            const double dfErrorX =
                 (pasGCPs[i].dfGCPPixel * padfGeoTransform[1]
                  + pasGCPs[i].dfGCPLine * padfGeoTransform[2]
                  + padfGeoTransform[0])
                 - pasGCPs[i].dfGCPX;
-            dfErrorY =
+            const double dfErrorY =
                 (pasGCPs[i].dfGCPPixel * padfGeoTransform[4]
                  + pasGCPs[i].dfGCPLine * padfGeoTransform[5]
                  + padfGeoTransform[3])
                 - pasGCPs[i].dfGCPY;
 
-            if( ABS(dfErrorX) > 0.25 * dfPixelSize
-                || ABS(dfErrorY) > 0.25 * dfPixelSize )
+            if( std::abs(dfErrorX) > 0.25 * dfPixelSize
+                || std::abs(dfErrorY) > 0.25 * dfPixelSize )
             {
-                CPLDebug("GDAL", "dfErrorX/dfPixelSize = %.2f, dfErrorY/dfPixelSize = %.2f",
-                         ABS(dfErrorX)/dfPixelSize, ABS(dfErrorY)/dfPixelSize);
+                CPLDebug("GDAL", "dfErrorX/dfPixelSize = %.2f, "
+                         "dfErrorY/dfPixelSize = %.2f",
+                         std::abs(dfErrorX)/dfPixelSize,
+                         std::abs(dfErrorY)/dfPixelSize);
                 return FALSE;
             }
         }
@@ -2303,7 +2448,7 @@ void GDALComposeGeoTransforms(const double *padfGT1, const double *padfGT2,
                               double *padfGTOut)
 
 {
-    double gtwrk[6];
+    double gtwrk[6] = { 0.0 };
     // We need to think of the geotransform in a more normal form to do
     // the matrix multiple:
     //
@@ -2338,7 +2483,7 @@ void GDALComposeGeoTransforms(const double *padfGT1, const double *padfGT2,
         padfGT2[4] * padfGT1[0]
         + padfGT2[5] * padfGT1[3]
         + padfGT2[3] * 1.0;
-    memcpy(padfGTOut, gtwrk, sizeof(double) * 6);
+    memcpy(padfGTOut, gtwrk, sizeof(gtwrk));
 }
 
 /************************************************************************/
@@ -2411,7 +2556,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         if( EQUAL(papszArgv[iArg],"--version") )
         {
-            printf( "%s\n", GDALVersionInfo( "--version" ) );
+            printf( "%s\n", GDALVersionInfo( "--version" ) );/*ok*/
             CSLDestroy( papszReturn );
             return 0;
         }
@@ -2421,7 +2566,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg],"--build") )
         {
-            printf( "%s", GDALVersionInfo( "BUILD_INFO" ) );
+            printf( "%s", GDALVersionInfo( "BUILD_INFO" ) );/*ok*/
             CSLDestroy( papszReturn );
             return 0;
         }
@@ -2431,7 +2576,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg],"--license") )
         {
-            printf( "%s\n", GDALVersionInfo( "LICENSE" ) );
+            printf( "%s\n", GDALVersionInfo( "LICENSE" ) );/*ok*/
             CSLDestroy( papszReturn );
             return 0;
         }
@@ -2581,7 +2726,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
             if( nOptions == 0 )
                 nOptions = GDAL_OF_RASTER;
 
-            printf( "Supported Formats:\n" );
+            printf( "Supported Formats:\n" );/*ok*/
             for( int iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
             {
                 GDALDriverH hDriver = GDALGetDriver(iDr);
@@ -2590,48 +2735,48 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
                 char** papszMD = GDALGetMetadata( hDriver, NULL );
 
                 if( nOptions == GDAL_OF_RASTER &&
-                    !CSLFetchBoolean( papszMD, GDAL_DCAP_RASTER, FALSE ) )
+                    !CPLFetchBool( papszMD, GDAL_DCAP_RASTER, false ) )
                     continue;
                 if( nOptions == GDAL_OF_VECTOR &&
-                    !CSLFetchBoolean( papszMD, GDAL_DCAP_VECTOR, FALSE ) )
+                    !CPLFetchBool( papszMD, GDAL_DCAP_VECTOR, false ) )
                     continue;
                 if( nOptions == GDAL_OF_GNM &&
-                    !CSLFetchBoolean( papszMD, GDAL_DCAP_GNM, FALSE ) )
+                    !CPLFetchBool( papszMD, GDAL_DCAP_GNM, false ) )
                     continue;
 
-                if( CSLFetchBoolean( papszMD, GDAL_DCAP_OPEN, FALSE ) )
+                if( CPLFetchBool( papszMD, GDAL_DCAP_OPEN, false ) )
                     pszRFlag = "r";
 
-                if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATE, FALSE ) )
+                if( CPLFetchBool( papszMD, GDAL_DCAP_CREATE, false ) )
                     pszWFlag = "w+";
-                else if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATECOPY, FALSE ) )
+                else if( CPLFetchBool( papszMD, GDAL_DCAP_CREATECOPY, false ) )
                     pszWFlag = "w";
                 else
                     pszWFlag = "o";
 
-                if( CSLFetchBoolean( papszMD, GDAL_DCAP_VIRTUALIO, FALSE ) )
+                if( CPLFetchBool( papszMD, GDAL_DCAP_VIRTUALIO, false ) )
                     pszVirtualIO = "v";
                 else
                     pszVirtualIO = "";
 
-                if( CSLFetchBoolean( papszMD, GDAL_DMD_SUBDATASETS, FALSE ) )
+                if( CPLFetchBool( papszMD, GDAL_DMD_SUBDATASETS, false ) )
                     pszSubdatasets = "s";
                 else
                     pszSubdatasets = "";
 
-                if( CSLFetchBoolean( papszMD, GDAL_DCAP_RASTER, FALSE ) &&
-                    CSLFetchBoolean( papszMD, GDAL_DCAP_VECTOR, FALSE ))
+                if( CPLFetchBool( papszMD, GDAL_DCAP_RASTER, false ) &&
+                    CPLFetchBool( papszMD, GDAL_DCAP_VECTOR, false ))
                     pszKind = "raster,vector";
-                else if( CSLFetchBoolean( papszMD, GDAL_DCAP_RASTER, FALSE ) )
+                else if( CPLFetchBool( papszMD, GDAL_DCAP_RASTER, false ) )
                     pszKind = "raster";
-                else if( CSLFetchBoolean( papszMD, GDAL_DCAP_VECTOR, FALSE ) )
+                else if( CPLFetchBool( papszMD, GDAL_DCAP_VECTOR, false ) )
                     pszKind = "vector";
-                else if( CSLFetchBoolean( papszMD, GDAL_DCAP_GNM, FALSE ) )
+                else if( CPLFetchBool( papszMD, GDAL_DCAP_GNM, false ) )
                     pszKind = "geography network";
                 else
                     pszKind = "unknown kind";
 
-                printf( "  %s -%s- (%s%s%s%s): %s\n",
+                printf( "  %s -%s- (%s%s%s%s): %s\n",/*ok*/
                         GDALGetDriverShortName( hDriver ),
                         pszKind,
                         pszRFlag, pszWFlag, pszVirtualIO, pszSubdatasets,
@@ -2672,52 +2817,52 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
                 return -1;
             }
 
-            printf( "Format Details:\n" );
-            printf( "  Short Name: %s\n", GDALGetDriverShortName( hDriver ) );
-            printf( "  Long Name: %s\n", GDALGetDriverLongName( hDriver ) );
+            printf( "Format Details:\n" );/*ok*/
+            printf( "  Short Name: %s\n", GDALGetDriverShortName( hDriver ) );/*ok*/
+            printf( "  Long Name: %s\n", GDALGetDriverLongName( hDriver ) );/*ok*/
 
             papszMD = GDALGetMetadata( hDriver, NULL );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_RASTER, FALSE ) )
-                printf( "  Supports: Raster\n" );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_VECTOR, FALSE ) )
-                printf( "  Supports: Vector\n" );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_GNM, FALSE ) )
-                printf( "  Supports: Geography Network\n" );
+            if( CPLFetchBool( papszMD, GDAL_DCAP_RASTER, false ) )
+                printf( "  Supports: Raster\n" );/*ok*/
+            if( CPLFetchBool( papszMD, GDAL_DCAP_VECTOR, false ) )
+                printf( "  Supports: Vector\n" );/*ok*/
+            if( CPLFetchBool( papszMD, GDAL_DCAP_GNM, false ) )
+                printf( "  Supports: Geography Network\n" );/*ok*/
 
             const char* pszExt = CSLFetchNameValue( papszMD, GDAL_DMD_EXTENSIONS );
             if( pszExt != NULL )
-                printf( "  Extension%s: %s\n", (strchr(pszExt, ' ') ? "s" : ""),
+                printf( "  Extension%s: %s\n", (strchr(pszExt, ' ') ? "s" : ""),/*ok*/
                         pszExt );
 
             if( CSLFetchNameValue( papszMD, GDAL_DMD_MIMETYPE ) )
-                printf( "  Mime Type: %s\n",
+                printf( "  Mime Type: %s\n",/*ok*/
                         CSLFetchNameValue( papszMD, GDAL_DMD_MIMETYPE ) );
             if( CSLFetchNameValue( papszMD, GDAL_DMD_HELPTOPIC ) )
-                printf( "  Help Topic: %s\n",
+                printf( "  Help Topic: %s\n",/*ok*/
                         CSLFetchNameValue( papszMD, GDAL_DMD_HELPTOPIC ) );
 
-            if( CSLFetchBoolean( papszMD, GDAL_DMD_SUBDATASETS, FALSE ) )
-                printf( "  Supports: Subdatasets\n" );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_OPEN, FALSE ) )
-                printf( "  Supports: Open() - Open existing dataset.\n" );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATE, FALSE ) )
-                printf( "  Supports: Create() - Create writable dataset.\n" );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_CREATECOPY, FALSE ) )
-                printf( "  Supports: CreateCopy() - Create dataset by copying another.\n" );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_VIRTUALIO, FALSE ) )
-                printf( "  Supports: Virtual IO - eg. /vsimem/\n" );
+            if( CPLFetchBool( papszMD, GDAL_DMD_SUBDATASETS, false ) )
+                printf( "  Supports: Subdatasets\n" );/*ok*/
+            if( CPLFetchBool( papszMD, GDAL_DCAP_OPEN, false ) )
+                printf( "  Supports: Open() - Open existing dataset.\n" );/*ok*/
+            if( CPLFetchBool( papszMD, GDAL_DCAP_CREATE, false ) )
+                printf( "  Supports: Create() - Create writable dataset.\n" );/*ok*/
+            if( CPLFetchBool( papszMD, GDAL_DCAP_CREATECOPY, false ) )
+                printf( "  Supports: CreateCopy() - Create dataset by copying another.\n" );/*ok*/
+            if( CPLFetchBool( papszMD, GDAL_DCAP_VIRTUALIO, false ) )
+                printf( "  Supports: Virtual IO - eg. /vsimem/\n" );/*ok*/
             if( CSLFetchNameValue( papszMD, GDAL_DMD_CREATIONDATATYPES ) )
-                printf( "  Creation Datatypes: %s\n",
+                printf( "  Creation Datatypes: %s\n",/*ok*/
                         CSLFetchNameValue( papszMD, GDAL_DMD_CREATIONDATATYPES ) );
             if( CSLFetchNameValue( papszMD, GDAL_DMD_CREATIONFIELDDATATYPES ) )
-                printf( "  Creation Field Datatypes: %s\n",
+                printf( "  Creation Field Datatypes: %s\n",/*ok*/
                         CSLFetchNameValue( papszMD, GDAL_DMD_CREATIONFIELDDATATYPES ) );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_NOTNULL_FIELDS, FALSE ) )
-                printf( "  Supports: Creating fields with NOT NULL constraint.\n" );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_DEFAULT_FIELDS, FALSE ) )
-                printf( "  Supports: Creating fields with DEFAULT values.\n" );
-            if( CSLFetchBoolean( papszMD, GDAL_DCAP_NOTNULL_GEOMFIELDS, FALSE ) )
-                printf( "  Supports: Creating geometry fields with NOT NULL constraint.\n" );
+            if( CPLFetchBool( papszMD, GDAL_DCAP_NOTNULL_FIELDS, false ) )
+                printf( "  Supports: Creating fields with NOT NULL constraint.\n" );/*ok*/
+            if( CPLFetchBool( papszMD, GDAL_DCAP_DEFAULT_FIELDS, false ) )
+                printf( "  Supports: Creating fields with DEFAULT values.\n" );/*ok*/
+            if( CPLFetchBool( papszMD, GDAL_DCAP_NOTNULL_GEOMFIELDS, false ) )
+                printf( "  Supports: Creating geometry fields with NOT NULL constraint.\n" );/*ok*/
             if( CSLFetchNameValue( papszMD, GDAL_DMD_CREATIONOPTIONLIST ) )
             {
                 CPLXMLNode *psCOL =
@@ -2729,7 +2874,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 
                 CPLDestroyXMLNode( psCOL );
 
-                printf( "\n%s\n", pszFormattedXML );
+                printf( "\n%s\n", pszFormattedXML );/*ok*/
                 CPLFree( pszFormattedXML );
             }
             if( CSLFetchNameValue( papszMD, GDAL_DS_LAYER_CREATIONOPTIONLIST ) )
@@ -2743,12 +2888,12 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 
                 CPLDestroyXMLNode( psCOL );
 
-                printf( "\n%s\n", pszFormattedXML );
+                printf( "\n%s\n", pszFormattedXML );/*ok*/
                 CPLFree( pszFormattedXML );
             }
 
             if( CSLFetchNameValue( papszMD, GDAL_DMD_CONNECTION_PREFIX ) )
-                printf( "  Connection prefix: %s\n",
+                printf( "  Connection prefix: %s\n",/*ok*/
                         CSLFetchNameValue( papszMD, GDAL_DMD_CONNECTION_PREFIX ) );
 
             if( CSLFetchNameValue( papszMD, GDAL_DMD_OPENOPTIONLIST ) )
@@ -2762,7 +2907,7 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 
                 CPLDestroyXMLNode( psCOL );
 
-                printf( "%s\n", pszFormattedXML );
+                printf( "%s\n", pszFormattedXML );/*ok*/
                 CPLFree( pszFormattedXML );
             }
             return 0;
@@ -2773,18 +2918,18 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
 /* -------------------------------------------------------------------- */
         else if( EQUAL(papszArgv[iArg],"--help-general") )
         {
-            printf( "Generic GDAL utility command options:\n" );
-            printf( "  --version: report version of GDAL in use.\n" );
-            printf( "  --license: report GDAL license info.\n" );
-            printf( "  --formats: report all configured format drivers.\n" );
-            printf( "  --format [format]: details of one format.\n" );
-            printf( "  --optfile filename: expand an option file into the argument list.\n" );
-            printf( "  --config key value: set system configuration option.\n" );
-            printf( "  --debug [on/off/value]: set debug level.\n" );
-            printf( "  --pause: wait for user input, time to attach debugger\n" );
-            printf( "  --locale [locale]: install locale for debugging "
+            printf( "Generic GDAL utility command options:\n" );/*ok*/
+            printf( "  --version: report version of GDAL in use.\n" );/*ok*/
+            printf( "  --license: report GDAL license info.\n" );/*ok*/
+            printf( "  --formats: report all configured format drivers.\n" );/*ok*/
+            printf( "  --format [format]: details of one format.\n" );/*ok*/
+            printf( "  --optfile filename: expand an option file into the argument list.\n" );/*ok*/
+            printf( "  --config key value: set system configuration option.\n" );/*ok*/
+            printf( "  --debug [on/off/value]: set debug level.\n" );/*ok*/
+            printf( "  --pause: wait for user input, time to attach debugger\n" );/*ok*/
+            printf( "  --locale [locale]: install locale for debugging "/*ok*/
                     "(i.e. en_US.UTF-8)\n" );
-            printf( "  --help-general: report detailed help on general options.\n" );
+            printf( "  --help-general: report detailed help on general options.\n" );/*ok*/
             CSLDestroy( papszReturn );
             return 0;
         }
@@ -2821,7 +2966,6 @@ GDALGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
     return CSLCount( *ppapszArgv );
 }
 
-
 /************************************************************************/
 /*                          _FetchDblFromMD()                           */
 /************************************************************************/
@@ -2867,12 +3011,16 @@ static bool _FetchDblFromMD( char **papszMD, const char *pszKey,
 
 /************************************************************************/
 /*                         GDALExtractRPCInfo()                         */
-/*                                                                      */
-/*      Extract RPC info from metadata, and apply to an RPCInfo         */
-/*      structure.  The inverse of this function is RPCInfoToMD() in    */
-/*      alg/gdal_rpc.cpp (should it be needed).                         */
 /************************************************************************/
 
+/** Extract RPC info from metadata, and apply to an RPCInfo structure.
+ *
+ * The inverse of this function is RPCInfoToMD() in alg/gdal_rpc.cpp
+ *
+ * @param papszMD Dictionary of metadata representing RPC
+ * @param psRPC (output) Pointer to structure to hold the RPC values.
+ * @return TRUE in case of success. FALSE in case of failure.
+ */
 int CPL_STDCALL GDALExtractRPCInfo( char **papszMD, GDALRPCInfo *psRPC )
 
 {
@@ -3199,7 +3347,6 @@ int GDALCheckBandCount( int nBands, int bIsZeroAllowed )
 
 CPL_C_END
 
-
 /************************************************************************/
 /*                     GDALSerializeGCPListToXML()                      */
 /************************************************************************/
@@ -3226,10 +3373,9 @@ void GDALSerializeGCPListToXML( CPLXMLNode* psParentNode,
 
     for( int iGCP = 0; iGCP < nGCPCount; iGCP++ )
     {
-        CPLXMLNode *psXMLGCP;
         GDAL_GCP *psGCP = pasGCPList + iGCP;
 
-        psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
+        CPLXMLNode *psXMLGCP = CPLCreateXMLNode( NULL, CXT_Element, "GCP" );
 
         if( psLastChild == NULL )
             psPamGCPList->psChild = psXMLGCP;
@@ -3270,13 +3416,11 @@ void GDALDeserializeGCPListFromXML( CPLXMLNode* psGCPList,
                                     int* pnGCPCount,
                                     char** ppszGCPProjection )
 {
-    CPLXMLNode *psXMLGCP;
-    OGRSpatialReference oSRS;
-
     if( ppszGCPProjection )
     {
         const char *pszRawProj = CPLGetXMLValue(psGCPList, "Projection", "");
 
+        OGRSpatialReference oSRS;
         if( strlen(pszRawProj) > 0
             && oSRS.SetFromUserInput( pszRawProj ) == OGRERR_NONE )
             oSRS.exportToWkt( ppszGCPProjection );
@@ -3285,16 +3429,21 @@ void GDALDeserializeGCPListFromXML( CPLXMLNode* psGCPList,
     }
 
     // Count GCPs.
-    int  nGCPMax = 0;
+    int nGCPMax = 0;
 
-    for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL;
+    for( CPLXMLNode *psXMLGCP = psGCPList->psChild;
+         psXMLGCP != NULL;
          psXMLGCP = psXMLGCP->psNext )
+    {
         nGCPMax++;
+    }
 
-    *ppasGCPList = (GDAL_GCP *) CPLCalloc(sizeof(GDAL_GCP),nGCPMax);
+    *ppasGCPList = static_cast<GDAL_GCP *>(
+        CPLCalloc(sizeof(GDAL_GCP), nGCPMax) );
     *pnGCPCount = 0;
 
-    for( psXMLGCP = psGCPList->psChild; psXMLGCP != NULL;
+    for( CPLXMLNode *psXMLGCP = psGCPList->psChild;
+         psXMLGCP != NULL;
          psXMLGCP = psXMLGCP->psNext )
     {
         GDAL_GCP *psGCP = *ppasGCPList + *pnGCPCount;
@@ -3319,12 +3468,13 @@ void GDALDeserializeGCPListFromXML( CPLXMLNode* psGCPList,
         const char* pszZ = CPLGetXMLValue(psXMLGCP,"Z",NULL);
         if( pszZ == NULL )
         {
-            /* Note: GDAL 1.10.1 and older generated #GCPZ, but could not read it back */
+            // Note: GDAL 1.10.1 and older generated #GCPZ,
+            // but could not read it back.
             pszZ = CPLGetXMLValue(psXMLGCP,"GCPZ","0.0");
         }
         psGCP->dfGCPZ = CPLAtof(pszZ);
 
-        (*pnGCPCount) ++;
+        (*pnGCPCount)++;
     }
 }
 
@@ -3447,7 +3597,7 @@ const char* GDALRasterIOGetResampleAlg(GDALRIOResampleAlg eResampleAlg)
         case GRIORA_Gauss:
             return "Gauss";
         default:
-            CPLAssert(FALSE);
+            CPLAssert(false);
             return "Unknown";
     }
 }
@@ -3479,7 +3629,7 @@ int GDALCanFileAcceptSidecarFile(const char* pszFilename)
 {
     if( strstr(pszFilename, "/vsicurl/") && strchr(pszFilename, '?') )
         return FALSE;
-    /* Do no attempt reading side-car files on /vsisubfile/ (#6241) */
+    // Do no attempt reading side-car files on /vsisubfile/ (#6241)
     if( strncmp(pszFilename, "/vsisubfile/", strlen("/vsisubfile/")) == 0 )
         return FALSE;
     return TRUE;
diff --git a/gcore/gdal_pam.h b/gcore/gdal_pam.h
index 83a14a0..cdfa9e9 100644
--- a/gcore/gdal_pam.h
+++ b/gcore/gdal_pam.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_pam.h 33694 2016-03-10 17:54:30Z goatbar $
+ * $Id: gdal_pam.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Declaration for Peristable Auxiliary Metadata classes.
@@ -30,6 +30,8 @@
 #ifndef GDAL_PAM_H_INCLUDED
 #define GDAL_PAM_H_INCLUDED
 
+//! @cond Doxygen_Suppress
+
 #include "gdal_priv.h"
 
 class GDALPamRasterBand;
@@ -68,7 +70,7 @@ class GDALPamRasterBand;
 
 /* GDAL PAM Flags */
 /* ERO 2011/04/13 : GPF_AUXMODE seems to be unimplemented */
-#define GPF_DIRTY		0x01  // .pam file needs to be written on close
+#define GPF_DIRTY               0x01  // .pam file needs to be written on close
 #define GPF_TRIED_READ_FAILED   0x02  // no need to keep trying to read .pam.
 #define GPF_DISABLED            0x04  // do not try any PAM stuff.
 #define GPF_AUXMODE             0x08  // store info in .aux (HFA) file.
@@ -87,7 +89,7 @@ class GDALDatasetPamInfo
 public:
     char        *pszPamFilename;
 
-    char	*pszProjection;
+    char        *pszProjection;
 
     int         bHaveGeoTransform;
     double      adfGeoTransform[6];
@@ -102,11 +104,13 @@ public:
 
     int         bHasMetadata;
 };
+//! @endcond
 
 /* ******************************************************************** */
 /*                           GDALPamDataset                             */
 /* ******************************************************************** */
 
+/** PAM dataset */
 class CPL_DLL GDALPamDataset : public GDALDataset
 {
     friend class GDALPamRasterBand;
@@ -115,8 +119,9 @@ class CPL_DLL GDALPamDataset : public GDALDataset
     int IsPamFilenameAPotentialSiblingFile();
 
   protected:
-                GDALPamDataset(void);
 
+                GDALPamDataset(void);
+//! @cond Doxygen_Suppress
     int         nPamFlags;
     GDALDatasetPamInfo *psPam;
 
@@ -138,54 +143,57 @@ class CPL_DLL GDALPamDataset : public GDALDataset
     const char *GetPhysicalFilename();
     void   SetSubdatasetName( const char *);
     const char *GetSubdatasetName();
+//! @endcond
 
   public:
     virtual     ~GDALPamDataset();
 
-    virtual void FlushCache(void);
+    virtual void FlushCache(void) CPL_OVERRIDE;
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
+    virtual const char *GetProjectionRef(void) CPL_OVERRIDE;
+    virtual CPLErr SetProjection( const char * ) CPL_OVERRIDE;
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * ) CPL_OVERRIDE;
+    virtual CPLErr SetGeoTransform( double * ) CPL_OVERRIDE;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() CPL_OVERRIDE;
+    virtual const char *GetGCPProjection() CPL_OVERRIDE;
+    virtual const GDAL_GCP *GetGCPs() CPL_OVERRIDE;
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) CPL_OVERRIDE;
 
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) CPL_OVERRIDE;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                          const char * pszValue,
-                                         const char * pszDomain = "" );
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) CPL_OVERRIDE;
+    virtual char      **GetMetadata( const char * pszDomain = "" ) CPL_OVERRIDE;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) CPL_OVERRIDE;
 
-    virtual char      **GetFileList(void);
+    virtual char      **GetFileList(void) CPL_OVERRIDE;
 
+//! @cond Doxygen_Suppress
     virtual CPLErr CloneInfo( GDALDataset *poSrcDS, int nCloneInfoFlags );
 
     virtual CPLErr IBuildOverviews( const char *pszResampling,
                                     int nOverviews, int *panOverviewList,
                                     int nListBands, int *panBandList,
                                     GDALProgressFunc pfnProgress,
-                                    void * pProgressData );
-
+                                    void * pProgressData ) CPL_OVERRIDE;
 
     // "semi private" methods.
     void   MarkPamDirty() { nPamFlags |= GPF_DIRTY; }
     GDALDatasetPamInfo *GetPamInfo() { return psPam; }
     int    GetPamFlags() { return nPamFlags; }
     void   SetPamFlags(int nValue ) { nPamFlags = nValue; }
+//! @endcond
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALPamDataset);
+    CPL_DISALLOW_COPY_ASSIGN(GDALPamDataset)
 };
 
+//! @cond Doxygen_Suppress
 /* ==================================================================== */
 /*      GDALRasterBandPamInfo                                           */
 /*                                                                      */
@@ -223,16 +231,18 @@ typedef struct {
     GDALRasterAttributeTable *poDefaultRAT;
 
 } GDALRasterBandPamInfo;
-
+//! @endcond
 /* ******************************************************************** */
 /*                          GDALPamRasterBand                           */
 /* ******************************************************************** */
+
+/** PAM raster band */
 class CPL_DLL GDALPamRasterBand : public GDALRasterBand
 {
     friend class GDALPamDataset;
 
   protected:
-
+//! @cond Doxygen_Suppress
     virtual CPLXMLNode *SerializeToXML( const char *pszVRTPath );
     virtual CPLErr      XMLInit( CPLXMLNode *, const char * );
 
@@ -240,67 +250,72 @@ class CPL_DLL GDALPamRasterBand : public GDALRasterBand
     void   PamClear();
 
     GDALRasterBandPamInfo *psPam;
+//! @endcond
 
   public:
                 GDALPamRasterBand();
-                GDALPamRasterBand(int bForceCachedIO);
+//! @cond Doxygen_Suppress
+    explicit    GDALPamRasterBand(int bForceCachedIO);
+//! @endcond
     virtual     ~GDALPamRasterBand();
 
-    virtual void        SetDescription( const char * );
+    virtual void        SetDescription( const char * ) CPL_OVERRIDE;
 
-    virtual CPLErr SetNoDataValue( double );
-    virtual double GetNoDataValue( int *pbSuccess = NULL );
-    virtual CPLErr DeleteNoDataValue();
+    virtual CPLErr SetNoDataValue( double ) CPL_OVERRIDE;
+    virtual double GetNoDataValue( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    virtual CPLErr DeleteNoDataValue() CPL_OVERRIDE;
 
-    virtual CPLErr SetColorTable( GDALColorTable * );
-    virtual GDALColorTable *GetColorTable();
+    virtual CPLErr SetColorTable( GDALColorTable * ) CPL_OVERRIDE;
+    virtual GDALColorTable *GetColorTable() CPL_OVERRIDE;
 
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
-    virtual GDALColorInterp GetColorInterpretation();
+    virtual CPLErr SetColorInterpretation( GDALColorInterp ) CPL_OVERRIDE;
+    virtual GDALColorInterp GetColorInterpretation() CPL_OVERRIDE;
 
-    virtual const char *GetUnitType();
-    CPLErr SetUnitType( const char * );
+    virtual const char *GetUnitType() CPL_OVERRIDE;
+    CPLErr SetUnitType( const char * ) CPL_OVERRIDE;
 
-    virtual char **GetCategoryNames();
-    virtual CPLErr SetCategoryNames( char ** );
+    virtual char **GetCategoryNames() CPL_OVERRIDE;
+    virtual CPLErr SetCategoryNames( char ** ) CPL_OVERRIDE;
 
-    virtual double GetOffset( int *pbSuccess = NULL );
-    CPLErr SetOffset( double );
-    virtual double GetScale( int *pbSuccess = NULL );
-    CPLErr SetScale( double );
+    virtual double GetOffset( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    CPLErr SetOffset( double ) CPL_OVERRIDE;
+    virtual double GetScale( int *pbSuccess = NULL ) CPL_OVERRIDE;
+    CPLErr SetScale( double ) CPL_OVERRIDE;
 
     virtual CPLErr  GetHistogram( double dfMin, double dfMax,
                           int nBuckets, GUIntBig * panHistogram,
                           int bIncludeOutOfRange, int bApproxOK,
-                          GDALProgressFunc, void *pProgressData );
+                          GDALProgressFunc, void *pProgressData ) CPL_OVERRIDE;
 
     virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                         int *pnBuckets, GUIntBig ** ppanHistogram,
                                         int bForce,
-                                        GDALProgressFunc, void *pProgressData);
+                                        GDALProgressFunc, void *pProgressData) CPL_OVERRIDE;
 
     virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
-                                        int nBuckets, GUIntBig *panHistogram );
+                                        int nBuckets, GUIntBig *panHistogram ) CPL_OVERRIDE;
 
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) CPL_OVERRIDE;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                          const char * pszValue,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) CPL_OVERRIDE;
 
-    virtual GDALRasterAttributeTable *GetDefaultRAT();
-    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
+    virtual GDALRasterAttributeTable *GetDefaultRAT() CPL_OVERRIDE;
+    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * ) CPL_OVERRIDE;
 
+//! @cond Doxygen_Suppress
     // new in GDALPamRasterBand.
     virtual CPLErr CloneInfo( GDALRasterBand *poSrcBand, int nCloneInfoFlags );
 
     // "semi private" methods.
     GDALRasterBandPamInfo *GetPamInfo() { return psPam; }
-
+//! @endcond
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALPamRasterBand);
+    CPL_DISALLOW_COPY_ASSIGN(GDALPamRasterBand)
 };
 
+//! @cond Doxygen_Suppress
 // These are mainly helper functions for internal use.
 int CPL_DLL PamParseHistogram( CPLXMLNode *psHistItem,
                                double *pdfMin, double *pdfMax,
@@ -321,4 +336,6 @@ const char CPL_DLL * PamAllocateProxy( const char * );
 const char CPL_DLL * PamDeallocateProxy( const char * );
 void CPL_DLL PamCleanProxyDB( void );
 
+//! @endcond
+
 #endif /* ndef GDAL_PAM_H_INCLUDED */
diff --git a/gcore/gdal_priv.h b/gcore/gdal_priv.h
index ecf6be4..c34d2f9 100644
--- a/gcore/gdal_priv.h
+++ b/gcore/gdal_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_priv.h 35549 2016-09-29 22:56:53Z rouault $
+ * $Id: gdal_priv.h 37723 2017-03-16 17:07:53Z rouault $
  *
  * Name:     gdal_priv.h
  * Project:  GDAL Core
@@ -69,17 +69,20 @@ class GDALAsyncReader;
 #include <map>
 #include "ogr_core.h"
 
+//! @cond Doxygen_Suppress
 #define GMO_VALID                0x0001
 #define GMO_IGNORE_UNIMPLEMENTED 0x0002
 #define GMO_SUPPORT_MD           0x0004
 #define GMO_SUPPORT_MDMD         0x0008
 #define GMO_MD_DIRTY             0x0010
 #define GMO_PAM_CLASS            0x0020
+//! @endcond
 
 /************************************************************************/
 /*                       GDALMultiDomainMetadata                        */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 class CPL_DLL GDALMultiDomainMetadata
 {
 private:
@@ -107,8 +110,9 @@ public:
     void        Clear();
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALMultiDomainMetadata);
+    CPL_DISALLOW_COPY_ASSIGN(GDALMultiDomainMetadata)
 };
+//! @endcond
 
 /* ******************************************************************** */
 /*                           GDALMajorObject                            */
@@ -117,23 +121,25 @@ public:
 /*      services shared by major objects.                               */
 /* ******************************************************************** */
 
-//! Object with metadata.
-
+/** Object with metadata. */
 class CPL_DLL GDALMajorObject
 {
   protected:
+//! @cond Doxygen_Suppress
     int                 nFlags; // GMO_* flags.
     CPLString           sDescription;
     GDALMultiDomainMetadata oMDMD;
 
-    char               **BuildMetadataDomainList(char** papszList, int bCheckNonEmpty, ...) CPL_NULL_TERMINATED;
+//! @endcond
 
+    char               **BuildMetadataDomainList( char** papszList,
+                                                  int bCheckNonEmpty, ... ) CPL_NULL_TERMINATED;
   public:
                         GDALMajorObject();
     virtual            ~GDALMajorObject();
 
-    int                 GetMOFlags();
-    void                SetMOFlags(int nFlagsIn);
+    int                 GetMOFlags() const;
+    void                SetMOFlags( int nFlagsIn );
 
     virtual const char *GetDescription() const;
     virtual void        SetDescription( const char * );
@@ -153,6 +159,8 @@ class CPL_DLL GDALMajorObject
 /* ******************************************************************** */
 /*                         GDALDefaultOverviews                         */
 /* ******************************************************************** */
+
+//! @cond Doxygen_Suppress
 class CPL_DLL GDALDefaultOverviews
 {
     friend class GDALDataset;
@@ -162,21 +170,21 @@ class CPL_DLL GDALDefaultOverviews
 
     CPLString   osOvrFilename;
 
-    int         bOvrIsAux;
+    bool        bOvrIsAux;
 
-    int         bCheckedForMask;
-    int         bOwnMaskDS;
+    bool        bCheckedForMask;
+    bool        bOwnMaskDS;
     GDALDataset *poMaskDS;
 
-    // for "overview datasets" we record base level info so we can
+    // For "overview datasets" we record base level info so we can
     // find our way back to get overview masks.
     GDALDataset *poBaseDS;
 
-    // Stuff for deferred initialize/overviewscans...
+    // Stuff for deferred initialize/overviewscans.
     bool        bCheckedForOverviews;
     void        OverviewScan();
     char       *pszInitName;
-    int         bInitNameIsOVR;
+    bool        bInitNameIsOVR;
     char      **papszInitSiblingFiles;
 
   public:
@@ -187,7 +195,7 @@ class CPL_DLL GDALDefaultOverviews
                            char **papszSiblingFiles = NULL,
                            int bNameIsOVR = FALSE );
 
-    void       TransferSiblingFiles(char** papszSiblingFiles);
+    void       TransferSiblingFiles( char** papszSiblingFiles );
 
     int        IsInitialized();
 
@@ -195,8 +203,8 @@ class CPL_DLL GDALDefaultOverviews
 
     // Overview Related
 
-    int        GetOverviewCount(int);
-    GDALRasterBand *GetOverview(int,int);
+    int        GetOverviewCount( int nBand );
+    GDALRasterBand *GetOverview( int nBand, int iOverview );
 
     CPLErr     BuildOverviews( const char * pszBasename,
                                const char * pszResampling,
@@ -226,15 +234,15 @@ class CPL_DLL GDALDefaultOverviews
     char**     GetSiblingFiles() { return papszInitSiblingFiles; }
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALDefaultOverviews);
+    CPL_DISALLOW_COPY_ASSIGN(GDALDefaultOverviews)
 };
+//! @endcond
 
 /* ******************************************************************** */
 /*                             GDALOpenInfo                             */
-/*                                                                      */
-/*      Structure of data about dataset for open functions.             */
 /* ******************************************************************** */
 
+/** Class for dataset open functions. */
 class CPL_DLL GDALOpenInfo
 {
     bool        bHasGotSiblingFiles;
@@ -246,27 +254,39 @@ class CPL_DLL GDALOpenInfo
                               char **papszSiblingFiles = NULL );
                 ~GDALOpenInfo( void );
 
+    /** Filename */
     char        *pszFilename;
+    /** Open options */
     char**      papszOpenOptions;
 
+    /** Access flag */
     GDALAccess  eAccess;
+    /** Open flags */
     int         nOpenFlags;
 
+    /** Whether stat()'ing the file was successful */
     int         bStatOK;
+    /** Whether the file is a directory */
     int         bIsDirectory;
 
+    /** Pointer to the file */
     VSILFILE   *fpL;
 
+    /** Number of bytes in pabyHeader */
     int         nHeaderBytes;
+    /** Buffer with first bytes of the file */
     GByte       *pabyHeader;
 
+    /** Allowed drivers (NULL for all) */
+    const char* const* papszAllowedDrivers;
+
     int         TryToIngest(int nBytes);
     char      **GetSiblingFiles();
     char      **StealSiblingFiles();
     bool        AreSiblingFilesLoaded() const;
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALOpenInfo);
+    CPL_DISALLOW_COPY_ASSIGN(GDALOpenInfo)
 };
 
 /* ******************************************************************** */
@@ -279,20 +299,26 @@ class OGRSpatialReference;
 class OGRStyleTable;
 class swq_select;
 class swq_select_parse_options;
+
+//! @cond Doxygen_Suppress
 typedef struct GDALSQLParseInfo GDALSQLParseInfo;
+//! @endcond
 
 #ifdef DETECT_OLD_IRASTERIO
 typedef void signature_changed;
 #endif
 
+//! @cond Doxygen_Suppress
 #ifdef GDAL_COMPILATION
 #define OPTIONAL_OUTSIDE_GDAL(val)
 #else
 #define OPTIONAL_OUTSIDE_GDAL(val) = val
 #endif
+//! @endcond
 
-//! A set of associated raster bands, usually from one file.
+class OGRFeature;
 
+/** A set of associated raster bands, usually from one file. */
 class CPL_DLL GDALDataset : public GDALMajorObject
 {
     friend GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
@@ -309,9 +335,10 @@ class CPL_DLL GDALDataset : public GDALMajorObject
 
     void AddToDatasetOpenList();
 
-    void           Init(int bForceCachedIO);
+    void           Init( bool bForceCachedIO );
 
   protected:
+//! @cond Doxygen_Suppress
     GDALDriver  *poDriver;
     GDALAccess  eAccess;
 
@@ -324,13 +351,13 @@ class CPL_DLL GDALDataset : public GDALMajorObject
     int         nOpenFlags;
 
     int         nRefCount;
-    GByte       bForceCachedIO;
-    GByte       bShared;
-    GByte       bIsInternal;
-    GByte       bSuppressOnClose;
+    bool        bForceCachedIO;
+    bool        bShared;
+    bool        bIsInternal;
+    bool        bSuppressOnClose;
 
                 GDALDataset(void);
-                GDALDataset(int bForceCachedIO);
+    explicit    GDALDataset(int bForceCachedIO);
 
     void        RasterInitialize( int, int );
     void        SetBand( int, GDALRasterBand * );
@@ -392,8 +419,9 @@ class CPL_DLL GDALDataset : public GDALMajorObject
                                 GDALRasterIOExtraArg* psExtraArg,
                                 int* pbTried);
 
+//! @endcond
     virtual int         CloseDependentDatasets();
-
+//! @cond Doxygen_Suppress
     int                 ValidateLayerCreationOptions( const char* const* papszLCO );
 
     char            **papszOpenOptions;
@@ -413,6 +441,7 @@ class CPL_DLL GDALDataset : public GDALMajorObject
 
     int          AcquireMutex();
     void         ReleaseMutex();
+//! @endcond
 
   public:
     virtual     ~GDALDataset();
@@ -425,15 +454,15 @@ class CPL_DLL GDALDataset : public GDALMajorObject
     virtual void FlushCache(void);
 
     virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
+    virtual CPLErr SetProjection( const char * pszProjection );
 
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual CPLErr GetGeoTransform( double * padfTransform );
+    virtual CPLErr SetGeoTransform( double * padfTransform );
 
     virtual CPLErr        AddBand( GDALDataType eType,
                                    char **papszOptions=NULL );
 
-    virtual void *GetInternalHandle( const char * );
+    virtual void *GetInternalHandle( const char * pszHandleName );
     virtual GDALDriver *GetDriver(void);
     virtual char      **GetFileList(void);
 
@@ -473,13 +502,22 @@ class CPL_DLL GDALDataset : public GDALMajorObject
 
     int           Reference();
     int           Dereference();
+    int           ReleaseRef();
+
+    /** Return access mode.
+     * @return access mode.
+     */
     GDALAccess    GetAccess() const { return eAccess; }
 
-    int           GetShared();
+    int           GetShared() const;
     void          MarkAsShared();
 
-    void          MarkSuppressOnClose() { bSuppressOnClose = TRUE; }
+    /** Set that the dataset must be deleted on close. */
+    void          MarkSuppressOnClose() { bSuppressOnClose = true; }
 
+    /** Return open options.
+     * @return open options.
+     */
     char        **GetOpenOptions() { return papszOpenOptions; }
 
     static GDALDataset **GetOpenDatasets( int *pnDatasetCount );
@@ -489,6 +527,21 @@ class CPL_DLL GDALDataset : public GDALMajorObject
 
     void ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (4, 5);
 
+    virtual char ** GetMetadata(const char * pszDomain = "") CPL_OVERRIDE;
+
+// Only defined when Doxygen enabled
+#ifdef DOXYGEN_SKIP
+    virtual CPLErr      SetMetadata( char ** papszMetadata,
+                                     const char * pszDomain ) CPL_OVERRIDE;
+    virtual const char *GetMetadataItem( const char * pszName,
+                                         const char * pszDomain ) CPL_OVERRIDE;
+    virtual CPLErr      SetMetadataItem( const char * pszName,
+                                         const char * pszValue,
+                                         const char * pszDomain ) CPL_OVERRIDE;
+#endif
+
+    virtual char ** GetMetadataDomainList() CPL_OVERRIDE;
+
 private:
     void           *m_hPrivateData;
 
@@ -496,13 +549,19 @@ private:
                                              OGRGeometry *poSpatialFilter,
                                              const char *pszDialect,
                                              swq_select_parse_options* poSelectParseOptions);
-
+    CPLStringList oDerivedMetadataList;
   public:
 
     virtual int         GetLayerCount();
-    virtual OGRLayer    *GetLayer(int);
+    virtual OGRLayer    *GetLayer(int iLayer);
     virtual OGRLayer    *GetLayerByName(const char *);
-    virtual OGRErr      DeleteLayer(int);
+    virtual OGRErr      DeleteLayer(int iLayer);
+
+    virtual void        ResetReading();
+    virtual OGRFeature* GetNextFeature( OGRLayer** ppoBelongingLayer,
+                                        double* pdfProgressPct,
+                                        GDALProgressFunc pfnProgress,
+                                        void* pProgressData );
 
     virtual int         TestCapability( const char * );
 
@@ -532,24 +591,26 @@ private:
     virtual OGRErr      CommitTransaction();
     virtual OGRErr      RollbackTransaction();
 
+//! @cond Doxygen_Suppress
     static int          IsGenericSQLDialect(const char* pszDialect);
 
     // Semi-public methods. Only to be used by in-tree drivers.
     GDALSQLParseInfo*   BuildParseInfo(swq_select* psSelectInfo,
                                        swq_select_parse_options* poSelectParseOptions);
-    void                DestroyParseInfo(GDALSQLParseInfo* psParseInfo );
+    static void         DestroyParseInfo(GDALSQLParseInfo* psParseInfo );
     OGRLayer *          ExecuteSQL( const char *pszStatement,
                                     OGRGeometry *poSpatialFilter,
                                     const char *pszDialect,
                                     swq_select_parse_options* poSelectParseOptions);
+//! @endcond
 
   protected:
-
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
                                      char ** papszOptions = NULL );
 
+//! @cond Doxygen_Suppress
     OGRErr              ProcessSQLCreateIndex( const char * );
     OGRErr              ProcessSQLDropIndex( const char * );
     OGRErr              ProcessSQLDropTable( const char * );
@@ -559,26 +620,27 @@ private:
     OGRErr              ProcessSQLAlterTableRenameColumn( const char * );
 
     OGRStyleTable      *m_poStyleTable;
+//! @endcond
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALDataset);
+    CPL_DISALLOW_COPY_ASSIGN(GDALDataset)
 };
 
 /* ******************************************************************** */
 /*                           GDALRasterBlock                            */
 /* ******************************************************************** */
 
-//! A single raster block in the block cache.
-// And the global block manager that manages a least-recently-used list of
-// blocks from various datasets/bands
-
+/** A single raster block in the block cache.
+ *
+ * And the global block manager that manages a least-recently-used list of
+ * blocks from various datasets/bands */
 class CPL_DLL GDALRasterBlock
 {
     friend class GDALAbstractBandBlockCache;
 
     GDALDataType        eType;
 
-    int                 bDirty;
+    bool                bDirty;
     volatile int        nLockCount;
 
     int                 nXOff;
@@ -594,7 +656,7 @@ class CPL_DLL GDALRasterBlock
     GDALRasterBlock     *poNext;
     GDALRasterBlock     *poPrevious;
 
-    int                  bMustDetach;
+    bool                 bMustDetach;
 
     void        Detach_unlocked( void );
     void        Touch_unlocked( void );
@@ -610,20 +672,45 @@ class CPL_DLL GDALRasterBlock
     void        Touch( void );
     void        MarkDirty( void );
     void        MarkClean( void );
+    /** Increment the lock count */
     int         AddLock( void ) { return CPLAtomicInc(&nLockCount); }
+    /** Decrement the lock count */
     int         DropLock( void ) { return CPLAtomicDec(&nLockCount); }
     void        Detach();
 
     CPLErr      Write();
 
+    /** Return the data type
+     * @return data type
+     */
     GDALDataType GetDataType() const { return eType; }
+    /** Return the x offset of the top-left corner of the block
+     * @return x offset
+     */
     int         GetXOff() const { return nXOff; }
+    /** Return the y offset of the top-left corner of the block
+     * @return y offset
+     */
     int         GetYOff() const { return nYOff; }
+    /** Return the width of the block
+     * @return width
+     */
     int         GetXSize() const { return nXSize; }
+    /** Return the height of the block
+     * @return height
+     */
     int         GetYSize() const { return nYSize; }
+    /** Return the dirty flag
+     * @return dirty flag
+     */
     int         GetDirty() const { return bDirty; }
-
+    /** Return the data buffer
+     * @return data buffer
+     */
     void        *GetDataRef( void ) { return pData; }
+    /** Return the block size in bytes
+     * @return block size.
+     */
     int          GetBlockSize() const {
         return nXSize * nYSize * GDALGetDataTypeSizeBytes(eType); }
 
@@ -645,17 +732,19 @@ class CPL_DLL GDALRasterBlock
 #endif
 
     /* Should only be called by GDALDestroyDriverManager() */
+//! @cond Doxygen_Suppress
     static void DestroyRBMutex();
+//! @endcond
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALRasterBlock);
+    CPL_DISALLOW_COPY_ASSIGN(GDALRasterBlock)
 };
 
 /* ******************************************************************** */
 /*                             GDALColorTable                           */
 /* ******************************************************************** */
 
-/*! A color table / palette. */
+/** A color table / palette. */
 
 class CPL_DLL GDALColorTable
 {
@@ -664,7 +753,7 @@ class CPL_DLL GDALColorTable
     std::vector<GDALColorEntry> aoEntries;
 
 public:
-                GDALColorTable( GDALPaletteInterp = GPI_RGB );
+    explicit     GDALColorTable( GDALPaletteInterp = GPI_RGB );
                 ~GDALColorTable();
 
     GDALColorTable *Clone() const;
@@ -684,6 +773,8 @@ public:
 /*                       GDALAbstractBandBlockCache                     */
 /* ******************************************************************** */
 
+ //! @cond Doxygen_Suppress
+
 //! This manages how a raster band store its cached block.
 // CPL_DLL is just technical here. This is really a private concept
 // only used by GDALRasterBand implementation.
@@ -707,7 +798,7 @@ class CPL_DLL GDALAbstractBandBlockCache
         void              WaitKeepAliveCounter();
 
     public:
-                     GDALAbstractBandBlockCache(GDALRasterBand* poBand);
+            explicit GDALAbstractBandBlockCache(GDALRasterBand* poBand);
             virtual ~GDALAbstractBandBlockCache();
 
             GDALRasterBlock* CreateBlock(int nXBlockOff, int nYBlockOff);
@@ -727,11 +818,13 @@ class CPL_DLL GDALAbstractBandBlockCache
 GDALAbstractBandBlockCache* GDALArrayBandBlockCacheCreate(GDALRasterBand* poBand);
 GDALAbstractBandBlockCache* GDALHashSetBandBlockCacheCreate(GDALRasterBand* poBand);
 
+//! @endcond
+
 /* ******************************************************************** */
 /*                            GDALRasterBand                            */
 /* ******************************************************************** */
 
-//! A single raster band (or channel).
+/** A single raster band (or channel). */
 
 class CPL_DLL GDALRasterBand : public GDALMajorObject
 {
@@ -749,6 +842,7 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
     void           Init(int bForceCachedIO);
 
   protected:
+//! @cond Doxygen_Suppress
     GDALDataset *poDS;
     int         nBand; /* 1 based */
 
@@ -784,10 +878,11 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
     int          EnterReadWrite(GDALRWFlag eRWFlag);
     void         LeaveReadWrite();
     void         InitRWLock();
+//! @endcond
 
   protected:
-    virtual CPLErr IReadBlock( int, int, void * ) = 0;
-    virtual CPLErr IWriteBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int nBlockXOff, int nBlockYOff, void * pData ) = 0;
+    virtual CPLErr IWriteBlock( int nBlockXOff, int nBlockYOff, void * pData );
 
 #ifdef DETECT_OLD_IRASTERIO
     virtual signature_changed IRasterIO( GDALRWFlag, int, int, int, int,
@@ -798,6 +893,12 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
                               GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
+
+    virtual int IGetDataCoverageStatus( int nXOff, int nYOff,
+                                        int nXSize, int nYSize,
+                                        int nMaskFlagStop,
+                                        double* pdfDataPct);
+//! @cond Doxygen_Suppress
     CPLErr         OverviewRasterIO( GDALRWFlag, int, int, int, int,
                                      void *, int, int, GDALDataType,
                                      GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg ) CPL_WARN_UNUSED_RESULT;
@@ -812,13 +913,14 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
 
     int            InitBlockInfo();
 
-    CPLErr         AdoptBlock( GDALRasterBlock * );
-    GDALRasterBlock *TryGetLockedBlockRef( int nXBlockOff, int nYBlockYOff );
     void           AddBlockToFreeList( GDALRasterBlock * );
+//! @endcond
+
+    GDALRasterBlock *TryGetLockedBlockRef( int nXBlockOff, int nYBlockYOff );
 
   public:
                 GDALRasterBand();
-                GDALRasterBand(int bForceCachedIO);
+    explicit    GDALRasterBand(int bForceCachedIO);
 
     virtual     ~GDALRasterBand();
 
@@ -829,6 +931,7 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
 
     GDALDataType GetRasterDataType( void );
     void        GetBlockSize( int *, int * );
+    CPLErr      GetActualBlockSize ( int, int, int *, int * );
     GDALAccess  GetAccess();
 
     CPLErr      RasterIO( GDALRWFlag, int, int, int, int,
@@ -864,14 +967,14 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
     virtual GDALColorTable *GetColorTable();
     virtual CPLErr Fill(double dfRealValue, double dfImaginaryValue = 0);
 
-    virtual CPLErr SetCategoryNames( char ** );
-    virtual CPLErr SetNoDataValue( double );
+    virtual CPLErr SetCategoryNames( char ** papszNames );
+    virtual CPLErr SetNoDataValue( double dfNoData );
     virtual CPLErr DeleteNoDataValue();
-    virtual CPLErr SetColorTable( GDALColorTable * );
-    virtual CPLErr SetColorInterpretation( GDALColorInterp );
-    virtual CPLErr SetOffset( double );
-    virtual CPLErr SetScale( double );
-    virtual CPLErr SetUnitType( const char * );
+    virtual CPLErr SetColorTable( GDALColorTable * poCT );
+    virtual CPLErr SetColorInterpretation( GDALColorInterp eColorInterp );
+    virtual CPLErr SetOffset( double dfNewOffset );
+    virtual CPLErr SetScale( double dfNewScale );
+    virtual CPLErr SetUnitType( const char * pszNewValue );
 
     virtual CPLErr GetStatistics( int bApproxOK, int bForce,
                                   double *pdfMin, double *pdfMax,
@@ -884,16 +987,31 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
                                   double dfMean, double dfStdDev );
     virtual CPLErr ComputeRasterMinMax( int, double* );
 
+// Only defined when Doxygen enabled
+#ifdef DOXYGEN_SKIP
+    virtual char      **GetMetadata( const char * pszDomain = "" ) CPL_OVERRIDE;
+    virtual CPLErr      SetMetadata( char ** papszMetadata,
+                                     const char * pszDomain ) CPL_OVERRIDE;
+    virtual const char *GetMetadataItem( const char * pszName,
+                                         const char * pszDomain ) CPL_OVERRIDE;
+    virtual CPLErr      SetMetadataItem( const char * pszName,
+                                         const char * pszValue,
+                                         const char * pszDomain ) CPL_OVERRIDE;
+#endif
+
     virtual int HasArbitraryOverviews();
     virtual int GetOverviewCount();
     virtual GDALRasterBand *GetOverview(int);
     virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig );
-    virtual CPLErr BuildOverviews( const char *, int, int *,
-                                   GDALProgressFunc, void * );
+    virtual CPLErr BuildOverviews( const char * pszResampling,
+                                   int nOverviews,
+                                   int * panOverviewList,
+                                   GDALProgressFunc pfnProgress,
+                                   void * pProgressData );
 
     virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                int nBufXSize, int nBufYSize,
-                               GDALDataType eDT, char **papszOptions );
+                               GDALDataType eBufType, char **papszOptions );
 
     virtual CPLErr  GetHistogram( double dfMin, double dfMax,
                           int nBuckets, GUIntBig * panHistogram,
@@ -908,7 +1026,7 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
                                         int nBuckets, GUIntBig *panHistogram );
 
     virtual GDALRasterAttributeTable *GetDefaultRAT();
-    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
+    virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * poRAT );
 
     virtual GDALRasterBand *GetMaskBand();
     virtual int             GetMaskFlags();
@@ -919,12 +1037,18 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject
                                                GIntBig *pnLineSpace,
                                                char **papszOptions ) CPL_WARN_UNUSED_RESULT;
 
+    int GetDataCoverageStatus( int nXOff, int nYOff,
+                               int nXSize, int nYSize,
+                               int nMaskFlagStop = 0,
+                               double* pdfDataPct = NULL );
+
     void ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (4, 5);
 
 private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALRasterBand);
+    CPL_DISALLOW_COPY_ASSIGN(GDALRasterBand)
 };
 
+//! @cond Doxygen_Suppress
 /* ******************************************************************** */
 /*                         GDALAllValidMaskBand                         */
 /* ******************************************************************** */
@@ -932,14 +1056,14 @@ private:
 class CPL_DLL GDALAllValidMaskBand : public GDALRasterBand
 {
   protected:
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
 
   public:
-                GDALAllValidMaskBand( GDALRasterBand * );
+    explicit     GDALAllValidMaskBand( GDALRasterBand * );
     virtual     ~GDALAllValidMaskBand();
 
-    virtual GDALRasterBand *GetMaskBand();
-    virtual int             GetMaskFlags();
+    virtual GDALRasterBand *GetMaskBand() CPL_OVERRIDE;
+    virtual int             GetMaskFlags() CPL_OVERRIDE;
 };
 
 /* ******************************************************************** */
@@ -952,13 +1076,13 @@ class CPL_DLL GDALNoDataMaskBand : public GDALRasterBand
     GDALRasterBand *poParent;
 
   protected:
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
-                              GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg );
+                              GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
   public:
-                GDALNoDataMaskBand( GDALRasterBand * );
+    explicit     GDALNoDataMaskBand( GDALRasterBand * );
     virtual     ~GDALNoDataMaskBand();
 };
 
@@ -971,10 +1095,10 @@ class CPL_DLL GDALNoDataValuesMaskBand : public GDALRasterBand
     double      *padfNodataValues;
 
   protected:
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
 
   public:
-                GDALNoDataValuesMaskBand( GDALDataset * );
+    explicit     GDALNoDataValuesMaskBand( GDALDataset * );
     virtual     ~GDALNoDataValuesMaskBand();
 };
 
@@ -988,15 +1112,16 @@ class GDALRescaledAlphaBand : public GDALRasterBand
     void           *pTemp;
 
   protected:
-    virtual CPLErr IReadBlock( int, int, void * );
+    virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
     virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                               void *, int, int, GDALDataType,
-                              GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg );
+                              GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
   public:
-                GDALRescaledAlphaBand( GDALRasterBand * );
+    explicit     GDALRescaledAlphaBand( GDALRasterBand * );
     virtual     ~GDALRescaledAlphaBand();
 };
+//! @endcond
 
 /* ******************************************************************** */
 /*                          GDALIdentifyEnum                            */
@@ -1021,7 +1146,6 @@ typedef enum
 /*                              GDALDriver                              */
 /* ******************************************************************** */
 
-
 /**
  * \brief Format specific driver.
  *
@@ -1037,11 +1161,11 @@ class CPL_DLL GDALDriver : public GDALMajorObject
 {
   public:
                         GDALDriver();
-                        ~GDALDriver();
+               virtual ~GDALDriver();
 
     virtual CPLErr      SetMetadataItem( const char * pszName,
-                                 const char * pszValue,
-                                 const char * pszDomain = "" );
+                                         const char * pszValue,
+                                         const char * pszDomain = "" ) CPL_OVERRIDE;
 
 /* -------------------------------------------------------------------- */
 /*      Public C++ methods.                                             */
@@ -1066,6 +1190,7 @@ class CPL_DLL GDALDriver : public GDALMajorObject
 /*      by anyone but the formats instantiating and populating the      */
 /*      drivers.                                                        */
 /* -------------------------------------------------------------------- */
+//! @cond Doxygen_Suppress
     GDALDataset         *(*pfnOpen)( GDALOpenInfo * );
 
     GDALDataset         *(*pfnCreate)( const char * pszName,
@@ -1105,10 +1230,12 @@ class CPL_DLL GDALDriver : public GDALMajorObject
                                                  char ** papszOptions );
     CPLErr              (*pfnDeleteDataSource)( GDALDriver*,
                                                  const char * pszName );
+//! @endcond
 
 /* -------------------------------------------------------------------- */
 /*      Helper methods.                                                 */
 /* -------------------------------------------------------------------- */
+//! @cond Doxygen_Suppress
     GDALDataset         *DefaultCreateCopy( const char *, GDALDataset *,
                                             int, char **,
                                             GDALProgressFunc pfnProgress,
@@ -1116,14 +1243,17 @@ class CPL_DLL GDALDriver : public GDALMajorObject
     static CPLErr        DefaultCopyMasks( GDALDataset *poSrcDS,
                                            GDALDataset *poDstDS,
                                            int bStrict );
+//! @endcond
     static CPLErr       QuietDelete( const char * pszName );
 
-    CPLErr              DefaultRename( const char * pszNewName,
+//! @cond Doxygen_Suppress
+    static CPLErr       DefaultRename( const char * pszNewName,
                                        const char * pszOldName );
-    CPLErr              DefaultCopyFiles( const char * pszNewName,
+    static CPLErr       DefaultCopyFiles( const char * pszNewName,
                                           const char * pszOldName );
+//! @endcond
 private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALDriver);
+    CPL_DISALLOW_COPY_ASSIGN(GDALDriver)
 };
 
 /* ******************************************************************** */
@@ -1144,7 +1274,8 @@ class CPL_DLL GDALDriverManager : public GDALMajorObject
     std::map<CPLString, GDALDriver*> oMapNameToDrivers;
 
     GDALDriver  *GetDriver_unlocked( int iDriver )
-            { return (iDriver >= 0 && iDriver < nDrivers) ? papoDrivers[iDriver] : NULL; }
+            { return (iDriver >= 0 && iDriver < nDrivers) ?
+                  papoDrivers[iDriver] : NULL; }
 
     GDALDriver  *GetDriverByName_unlocked( const char * pszName )
             { return oMapNameToDrivers[CPLString(pszName).toupper()]; }
@@ -1153,7 +1284,7 @@ class CPL_DLL GDALDriverManager : public GDALMajorObject
                 GDALDriverManager();
                 ~GDALDriverManager();
 
-    int         GetDriverCount( void );
+    int         GetDriverCount( void ) const;
     GDALDriver  *GetDriver( int );
     GDALDriver  *GetDriverByName( const char * );
 
@@ -1161,7 +1292,7 @@ class CPL_DLL GDALDriverManager : public GDALMajorObject
     void        DeregisterDriver( GDALDriver * );
 
     // AutoLoadDrivers is a no-op if compiled with GDAL_NO_AUTOLOAD defined.
-    void        AutoLoadDrivers();
+    static void        AutoLoadDrivers();
     void        AutoSkipDrivers();
 };
 
@@ -1181,6 +1312,7 @@ CPL_C_END
 class CPL_DLL GDALAsyncReader
 {
   protected:
+//! @cond Doxygen_Suppress
     GDALDataset* poDS;
     int          nXOff;
     int          nYOff;
@@ -1195,24 +1327,67 @@ class CPL_DLL GDALAsyncReader
     int          nPixelSpace;
     int          nLineSpace;
     int          nBandSpace;
+//! @endcond
 
   public:
     GDALAsyncReader();
     virtual ~GDALAsyncReader();
 
+    /** Return dataset.
+     * @return dataset
+     */
     GDALDataset* GetGDALDataset() {return poDS;}
+    /** Return x offset.
+     * @return x offset.
+     */
     int GetXOffset() const { return nXOff; }
+    /** Return y offset.
+     * @return y offset.
+     */
     int GetYOffset() const { return nYOff; }
+    /** Return width.
+     * @return width
+     */
     int GetXSize() const { return nXSize; }
+    /** Return height.
+     * @return height
+     */
     int GetYSize() const { return nYSize; }
+    /** Return buffer.
+     * @return buffer
+     */
     void * GetBuffer() {return pBuf;}
+    /** Return buffer width.
+     * @return buffer width.
+     */
     int GetBufferXSize() const { return nBufXSize; }
+    /** Return buffer height.
+     * @return buffer height.
+     */
     int GetBufferYSize() const { return nBufYSize; }
+    /** Return buffer data type.
+     * @return buffer data type.
+     */
     GDALDataType GetBufferType() const { return eBufType; }
+    /** Return band count.
+     * @return band count
+     */
     int GetBandCount() const { return nBandCount; }
+    /** Return band map.
+     * @return band map.
+     */
     int* GetBandMap() { return panBandMap; }
+    /** Return pixel spacing.
+     * @return pixel spacing.
+     */
     int GetPixelSpace() const { return nPixelSpace; }
+    /** Return line spacing.
+     * @return line spacing.
+     */
     int GetLineSpace() const { return nLineSpace; }
+    /** Return band spacing.
+     * @return band spacing.
+     */
     int GetBandSpace() const { return nBandSpace; }
 
     virtual GDALAsyncStatusType
@@ -1227,6 +1402,7 @@ class CPL_DLL GDALAsyncReader
 /*      An assortment of overview related stuff.                        */
 /* ==================================================================== */
 
+//! @cond Doxygen_Suppress
 /* Only exported for drivers as plugin. Signature may change */
 CPLErr CPL_DLL
 GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
@@ -1251,7 +1427,8 @@ typedef CPLErr (*GDALResampleFunction)
                         const char * pszResampling,
                         int bHasNoData, float fNoDataValue,
                         GDALColorTable* poColorTable,
-                        GDALDataType eSrcDataType);
+                        GDALDataType eSrcDataType,
+                        bool bPropagateNoData );
 
 GDALResampleFunction GDALGetResampleFunction(const char* pszResampling,
                                                  int* pnRadius);
@@ -1342,7 +1519,6 @@ CPLErr CPL_DLL GDALParseGMLCoverage( CPLXMLNode *psTree,
 int CPL_DLL GDALCheckDatasetDimensions( int nXSize, int nYSize );
 int CPL_DLL GDALCheckBandCount( int nBands, int bIsZeroAllowed );
 
-
 // Test if 2 floating point values match. Useful when comparing values
 // stored as a string at some point. See #3573, #4183, #4506
 #define ARE_REAL_EQUAL(dfVal1, dfVal2) \
@@ -1399,9 +1575,9 @@ void GDALRasterIOExtraArgSetResampleAlg(GDALRasterIOExtraArg* psExtraArg,
                                         int nXSize, int nYSize,
                                         int nBufXSize, int nBufYSize);
 
-/* CPL_DLL exported, but only for gdalwarp */
-GDALDataset CPL_DLL* GDALCreateOverviewDataset(GDALDataset* poDS, int nOvrLevel,
-                                               int bThisLevelOnly, int bOwnDS);
+
+GDALDataset* GDALCreateOverviewDataset(GDALDataset* poDS, int nOvrLevel,
+                                       int bThisLevelOnly);
 
 #define DIV_ROUND_UP(a, b) ( ((a) % (b)) == 0 ? ((a) / (b)) : (((a) / (b)) + 1) )
 
@@ -1426,5 +1602,6 @@ void GDALSerializeOpenOptionsToXML( CPLXMLNode* psParentNode, char** papszOpenOp
 char** GDALDeserializeOpenOptionsFromXML( CPLXMLNode* psParentNode );
 
 int GDALCanFileAcceptSidecarFile(const char* pszFilename);
+//! @endcond
 
 #endif /* ndef GDAL_PRIV_H_INCLUDED */
diff --git a/gcore/gdal_priv_templates.hpp b/gcore/gdal_priv_templates.hpp
index cf4e1a0..1740c7d 100644
--- a/gcore/gdal_priv_templates.hpp
+++ b/gcore/gdal_priv_templates.hpp
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_priv_templates.hpp 31950 2015-12-01 20:01:42Z rouault $
+ * $Id: gdal_priv_templates.hpp 36822 2016-12-12 11:18:45Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Inline C++ templates
@@ -30,8 +30,6 @@
 #ifndef GDAL_PRIV_TEMPLATES_HPP_INCLUDED
 #define GDAL_PRIV_TEMPLATES_HPP_INCLUDED
 
-#define SSE_USE_SAME_ROUNDING_AS_NON_SSE
-
 #include <limits>
 
 /************************************************************************/
@@ -161,58 +159,6 @@ inline void GDALCopyWord(const float fValueIn, Tout &tValueOut)
         GDALClampValue(fValueIn + 0.5f, fMaxVal, fMinVal));
 }
 
-// Just need SSE, but don't bother being too specific
-#if (defined(__x86_64) || defined(_M_X64)) && defined(this_is_disabled)
-
-#include <xmmintrin.h>
-
-template <class Tout>
-inline void GDALCopyWordSSE(const float fValueIn, Tout &tValueOut)
-{
-    float fMaxVal, fMinVal;
-    GDALGetDataLimits<float, Tout>(fMaxVal, fMinVal);
-    __m128 xmm = _mm_set_ss(fValueIn);
-    __m128 xmm_min = _mm_set_ss(fMinVal);
-    __m128 xmm_max = _mm_set_ss(fMaxVal);
-    xmm = _mm_min_ss(_mm_max_ss(xmm, xmm_min), xmm_max);
-#ifdef SSE_USE_SAME_ROUNDING_AS_NON_SSE
-    __m128 p0d5 = _mm_set_ss(0.5f);
-    if (std::numeric_limits<Tout>::is_signed)
-    {
-        __m128 mask = _mm_cmpge_ss(xmm, _mm_set_ss(0.f));
-        __m128 m0d5 = _mm_set_ss(-0.5f);
-        xmm = _mm_add_ss(xmm, _mm_or_ps(_mm_and_ps(mask, p0d5), _mm_andnot_ps(mask, m0d5)));
-    }
-    else
-    {
-        xmm = _mm_add_ss(xmm, p0d5);
-    }
-#endif
-
-#ifdef SSE_USE_SAME_ROUNDING_AS_NON_SSE
-    tValueOut = (Tout)_mm_cvttss_si32(xmm);
-#else
-    tValueOut = (Tout)_mm_cvtss_si32(xmm);
-#endif
-}
-
-inline void GDALCopyWord(const float fValueIn, GByte &tValueOut)
-{
-    GDALCopyWordSSE(fValueIn, tValueOut);
-}
-
-inline void GDALCopyWord(const float fValueIn, GInt16 &tValueOut)
-{
-    GDALCopyWordSSE(fValueIn, tValueOut);
-}
-
-inline void GDALCopyWord(const float fValueIn, GUInt16 &tValueOut)
-{
-    GDALCopyWordSSE(fValueIn, tValueOut);
-}
-
-#else
-
 inline void GDALCopyWord(const float fValueIn, short &nValueOut)
 {
     float fMaxVal, fMinVal;
@@ -223,8 +169,6 @@ inline void GDALCopyWord(const float fValueIn, short &nValueOut)
         GDALClampValue(fValue, fMaxVal, fMinVal));
 }
 
-#endif //  defined(__x86_64) || defined(_M_X64)
-
 template <class Tout>
 inline void GDALCopyWord(const double dfValueIn, Tout &tValueOut)
 {
@@ -268,7 +212,7 @@ inline void GDALCopyWord(const float fValueIn, int &nValueOut)
     }
     else
     {
-        nValueOut = static_cast<int>(fValueIn > 0.0f ? 
+        nValueOut = static_cast<int>(fValueIn > 0.0f ?
             fValueIn + 0.5f : fValueIn - 0.5f);
     }
 }
@@ -291,145 +235,119 @@ inline void GDALCopyWord(const float fValueIn, unsigned int &nValueOut)
     }
 }
 
-#ifdef notdef
 /************************************************************************/
-/*                         GDALCopy2Words()                             */
+/*                         GDALCopy4Words()                             */
 /************************************************************************/
 /**
- * Copy 2 words, optionally rounding if appropriate (i.e. going
- * from the float to the integer case).
+ * Copy 4 packed words to 4 packed words, optionally rounding if appropriate
+ * (i.e. going from the float to the integer case).
  *
- * @param pValueIn pointer to 2 input values of type Tin.
- * @param pValueOut pointer to 2 output values of type Tout.
+ * @param pValueIn pointer to 4 input values of type Tin.
+ * @param pValueOut pointer to 4 output values of type Tout.
  */
 
 template <class Tin, class Tout>
-inline void GDALCopy2Words(const Tin* pValueIn, Tout* const &pValueOut)
+inline void GDALCopy4Words(const Tin* pValueIn, Tout* const &pValueOut)
 {
     GDALCopyWord(pValueIn[0], pValueOut[0]);
     GDALCopyWord(pValueIn[1], pValueOut[1]);
+    GDALCopyWord(pValueIn[2], pValueOut[2]);
+    GDALCopyWord(pValueIn[3], pValueOut[3]);
 }
 
-// Just need SSE, but don't bother being too specific
-#if defined(__x86_64) || defined(_M_X64)
+// Needs SSE2
+// _mm_cvtsi128_si64 doesn't work gcc 3.4
+#if (defined(__x86_64) || defined(_M_X64)) && !(defined(__GNUC__) && __GNUC__ < 4)
 
-#include <xmmintrin.h>
+#include <emmintrin.h>
 
-template <class Tout>
-inline void GDALCopy2WordsSSE(const float* pValueIn, Tout* const &pValueOut)
+static inline void GDALCopyXMMToInt32(const __m128i xmm, void* pDest)
 {
-    float fMaxVal, fMinVal;
-    GDALGetDataLimits<float, Tout>(fMaxVal, fMinVal);
-    __m128 xmm = _mm_set_ps(0, 0, pValueIn[1], pValueIn[0]);
-    __m128 xmm_min = _mm_set_ps(0, 0, fMinVal, fMinVal);
-    __m128 xmm_max = _mm_set_ps(0, 0, fMaxVal, fMaxVal);
-    xmm = _mm_min_ps(_mm_max_ps(xmm, xmm_min), xmm_max);
-    pValueOut[0] = _mm_cvtss_si32(xmm);
-    pValueOut[1] = _mm_cvtss_si32(_mm_shuffle_ps(xmm, xmm, _MM_SHUFFLE(0, 0, 0, 1)));
+#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
+    int n32 = _mm_cvtsi128_si32 (xmm);     // Extract lower 32 bit word
+    memcpy(pDest, &n32, sizeof(n32));
+#else
+    *(int*)pDest = _mm_cvtsi128_si32 (xmm);
+#endif
 }
 
-inline void GDALCopy2Words(const float* pValueIn, GByte* const &pValueOut)
+static inline void GDALCopyXMMToInt64(const __m128i xmm, void* pDest)
 {
-    GDALCopy2WordsSSE(pValueIn, pValueOut);
+#ifdef CPL_CPU_REQUIRES_ALIGNED_ACCESS
+    GInt64 n64 = _mm_cvtsi128_si64 (xmm);   // Extract lower 64 bit word
+    memcpy(pDest, &n64, sizeof(n64));
+#else
+    *(GInt64*)pDest = _mm_cvtsi128_si64 (xmm);
+#endif
 }
 
-inline void GDALCopy2Words(const float* pValueIn, GInt16* const &pValueOut)
-{
-    GDALCopy2WordsSSE(pValueIn, pValueOut);
-}
+#if __SSE4_1__
+#include <smmintrin.h>
+#endif
 
-inline void GDALCopy2Words(const float* pValueIn, GUInt16* const &pValueOut)
+inline void GDALCopy4Words(const float* pValueIn, GByte* const &pValueOut)
 {
-    GDALCopy2WordsSSE(pValueIn, pValueOut);
-}
-#endif //  defined(__x86_64) || defined(_M_X64)
-
-#endif
+    __m128 xmm = _mm_loadu_ps(pValueIn);
 
-/************************************************************************/
-/*                         GDALCopy4Words()                             */
-/************************************************************************/
-/**
- * Copy 4 words, optionally rounding if appropriate (i.e. going
- * from the float to the integer case).
- *
- * @param pValueIn pointer to 4 input values of type Tin.
- * @param pValueOut pointer to 4 output values of type Tout.
- */
+    // The following clamping would be useless due to the final saturating
+    // packing if we could guarantee the input range in [INT_MIN,INT_MAX]
+    const __m128 xmm_min = _mm_set1_ps(0);
+    const __m128 xmm_max = _mm_set1_ps(255);
+    xmm = _mm_min_ps(_mm_max_ps(xmm, xmm_min), xmm_max);
 
-template <class Tin, class Tout>
-inline void GDALCopy4Words(const Tin* pValueIn, Tout* const &pValueOut)
-{
-    GDALCopyWord(pValueIn[0], pValueOut[0]);
-    GDALCopyWord(pValueIn[1], pValueOut[1]);
-    GDALCopyWord(pValueIn[2], pValueOut[2]);
-    GDALCopyWord(pValueIn[3], pValueOut[3]);
-}
+    const __m128 p0d5 = _mm_set1_ps(0.5f);
+    xmm = _mm_add_ps(xmm, p0d5);
 
-// Needs SSE2 for _mm_cvtps_epi32 and store operations
-#if defined(__x86_64) || defined(_M_X64)
+    __m128i xmm_i = _mm_cvttps_epi32 (xmm);
 
-#include <emmintrin.h>
+    xmm_i = _mm_packs_epi32(xmm_i, xmm_i);   // Pack int32 to int16
+    xmm_i = _mm_packus_epi16(xmm_i, xmm_i);  // Pack int16 to uint8
+    GDALCopyXMMToInt32(xmm_i, pValueOut);
+}
 
-template <class Tout>
-inline void GDALCopy4WordsSSE(const float* pValueIn, Tout* const &pValueOut)
+inline void GDALCopy4Words(const float* pValueIn, GInt16* const &pValueOut)
 {
-    float fMaxVal, fMinVal;
-    GDALGetDataLimits<float, Tout>(fMaxVal, fMinVal);
     __m128 xmm = _mm_loadu_ps(pValueIn);
 
-    __m128 xmm_min = _mm_set1_ps(fMinVal);
-    __m128 xmm_max = _mm_set1_ps(fMaxVal);
+    const __m128 xmm_min = _mm_set1_ps(-32768);
+    const __m128 xmm_max = _mm_set1_ps(32767);
     xmm = _mm_min_ps(_mm_max_ps(xmm, xmm_min), xmm_max);
 
-#ifdef SSE_USE_SAME_ROUNDING_AS_NON_SSE
-    __m128 p0d5 = _mm_set1_ps(0.5f);
-     if (std::numeric_limits<Tout>::is_signed)
-     {
-        __m128 m0d5 = _mm_set1_ps(-0.5f);
-        //__m128 mask = _mm_cmpge_ps(xmm, _mm_set1_ps(0.f));
-        __m128 mask = _mm_cmpge_ps(xmm, p0d5);
-        xmm = _mm_add_ps(xmm, _mm_or_ps(_mm_and_ps(mask, p0d5), _mm_andnot_ps(mask, m0d5))); /* f >= 0.5f ? f + 0.5f : f - 0.5f */
-     }
-     else
-     {
-         xmm = _mm_add_ps(xmm, p0d5);
-     }
-#endif
+    const __m128 p0d5 = _mm_set1_ps(0.5f);
+    const __m128 m0d5 = _mm_set1_ps(-0.5f);
+    const __m128 mask = _mm_cmpge_ps(xmm, p0d5);
+    // f >= 0.5f ? f + 0.5f : f - 0.5f
+    xmm = _mm_add_ps(xmm, _mm_or_ps(_mm_and_ps(mask, p0d5),
+                                    _mm_andnot_ps(mask, m0d5)));
 
-#ifdef SSE_USE_SAME_ROUNDING_AS_NON_SSE
     __m128i xmm_i = _mm_cvttps_epi32 (xmm);
-#else
-    __m128i xmm_i = _mm_cvtps_epi32(xmm);
-#endif
-#if 0
-    int aTemp[4];
-    _mm_storeu_si128 ( (__m128i *)aTemp, xmm_i);
-    pValueOut[0] = (Tout)aTemp[0];
-    pValueOut[1] = (Tout)aTemp[1];
-    pValueOut[2] = (Tout)aTemp[2];
-    pValueOut[3] = (Tout)aTemp[3];
-#else
-    pValueOut[0] = (Tout)_mm_extract_epi16(xmm_i, 0);
-    pValueOut[1] = (Tout)_mm_extract_epi16(xmm_i, 2);
-    pValueOut[2] = (Tout)_mm_extract_epi16(xmm_i, 4);
-    pValueOut[3] = (Tout)_mm_extract_epi16(xmm_i, 6);
-#endif
-}
 
-inline void GDALCopy4Words(const float* pValueIn, GByte* const &pValueOut)
-{
-    GDALCopy4WordsSSE(pValueIn, pValueOut);
-}
-
-inline void GDALCopy4Words(const float* pValueIn, GInt16* const &pValueOut)
-{
-    GDALCopy4WordsSSE(pValueIn, pValueOut);
+    xmm_i = _mm_packs_epi32(xmm_i, xmm_i);   // Pack int32 to int16
+    GDALCopyXMMToInt64(xmm_i, pValueOut);
 }
 
 inline void GDALCopy4Words(const float* pValueIn, GUInt16* const &pValueOut)
 {
-    GDALCopy4WordsSSE(pValueIn, pValueOut);
+    __m128 xmm = _mm_loadu_ps(pValueIn);
+
+    const __m128 xmm_min = _mm_set1_ps(0);
+    const __m128 xmm_max = _mm_set1_ps(65535);
+    xmm = _mm_min_ps(_mm_max_ps(xmm, xmm_min), xmm_max);
+
+    xmm = _mm_add_ps(xmm, _mm_set1_ps(0.5f));
+
+    __m128i xmm_i = _mm_cvttps_epi32 (xmm);
+
+#if __SSE4_1__
+     xmm_i = _mm_packus_epi32(xmm_i, xmm_i);   // Pack int32 to uint16
+#else
+    // Translate to int16 range because _mm_packus_epi32 is SSE4.1 only
+    xmm_i = _mm_add_epi32(xmm_i, _mm_set1_epi32(-32768));
+    xmm_i = _mm_packs_epi32(xmm_i, xmm_i);   // Pack int32 to int16
+    // Translate back to uint16 range (actually -32768==32768 in int16)
+    xmm_i = _mm_add_epi16(xmm_i, _mm_set1_epi16(-32768));
+#endif
+    GDALCopyXMMToInt64(xmm_i, pValueOut);
 }
 #endif //  defined(__x86_64) || defined(_M_X64)
 
diff --git a/gcore/gdal_proxy.h b/gcore/gdal_proxy.h
index 8a17c35..1a6ed84 100644
--- a/gcore/gdal_proxy.h
+++ b/gcore/gdal_proxy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_proxy.h 33694 2016-03-10 17:54:30Z goatbar $
+ * $Id: gdal_proxy.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Core C++/Private declarations
@@ -30,6 +30,8 @@
 #ifndef GDAL_PROXY_H_INCLUDED
 #define GDAL_PROXY_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "gdal.h"
 
 #ifdef __cplusplus
@@ -50,51 +52,51 @@ class CPL_DLL GDALProxyDataset : public GDALDataset
         virtual void UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset);
 
         virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
+                                    int, int *, GDALProgressFunc, void * ) CPL_OVERRIDE;
         virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                                 void *, int, int, GDALDataType,
                                 int, int *, GSpacing, GSpacing, GSpacing,
-                                GDALRasterIOExtraArg* psExtraArg );
+                                GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
     public:
 
-        virtual char      **GetMetadataDomainList();
-        virtual char      **GetMetadata( const char * pszDomain  );
+        virtual char      **GetMetadataDomainList() CPL_OVERRIDE;
+        virtual char      **GetMetadata( const char * pszDomain  ) CPL_OVERRIDE;
         virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                        const char * pszDomain  );
+                                        const char * pszDomain  ) CPL_OVERRIDE;
         virtual const char *GetMetadataItem( const char * pszName,
-                                            const char * pszDomain  );
+                                            const char * pszDomain  ) CPL_OVERRIDE;
         virtual CPLErr      SetMetadataItem( const char * pszName,
                                             const char * pszValue,
-                                            const char * pszDomain );
+                                            const char * pszDomain ) CPL_OVERRIDE;
 
-        virtual void FlushCache(void);
+        virtual void FlushCache(void) CPL_OVERRIDE;
 
-        virtual const char *GetProjectionRef(void);
-        virtual CPLErr SetProjection( const char * );
+        virtual const char *GetProjectionRef(void) CPL_OVERRIDE;
+        virtual CPLErr SetProjection( const char * ) CPL_OVERRIDE;
 
-        virtual CPLErr GetGeoTransform( double * );
-        virtual CPLErr SetGeoTransform( double * );
+        virtual CPLErr GetGeoTransform( double * ) CPL_OVERRIDE;
+        virtual CPLErr SetGeoTransform( double * ) CPL_OVERRIDE;
 
-        virtual void *GetInternalHandle( const char * );
-        virtual GDALDriver *GetDriver(void);
-        virtual char      **GetFileList(void);
+        virtual void *GetInternalHandle( const char * ) CPL_OVERRIDE;
+        virtual GDALDriver *GetDriver(void) CPL_OVERRIDE;
+        virtual char      **GetFileList(void) CPL_OVERRIDE;
 
-        virtual int    GetGCPCount();
-        virtual const char *GetGCPProjection();
-        virtual const GDAL_GCP *GetGCPs();
+        virtual int    GetGCPCount() CPL_OVERRIDE;
+        virtual const char *GetGCPProjection() CPL_OVERRIDE;
+        virtual const GDAL_GCP *GetGCPs() CPL_OVERRIDE;
         virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                                const char *pszGCPProjection );
+                                const char *pszGCPProjection ) CPL_OVERRIDE;
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                 int nBufXSize, int nBufYSize,
                                 GDALDataType eDT,
                                 int nBandCount, int *panBandList,
-                                char **papszOptions );
+                                char **papszOptions ) CPL_OVERRIDE;
 
-        virtual CPLErr          CreateMaskBand( int nFlags );
+        virtual CPLErr          CreateMaskBand( int nFlags ) CPL_OVERRIDE;
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALProxyDataset);
+    CPL_DISALLOW_COPY_ASSIGN(GDALProxyDataset)
 };
 
 /* ******************************************************************** */
@@ -109,94 +111,93 @@ class CPL_DLL GDALProxyRasterBand : public GDALRasterBand
         virtual GDALRasterBand* RefUnderlyingRasterBand() = 0;
         virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand);
 
-        virtual CPLErr IReadBlock( int, int, void * );
-        virtual CPLErr IWriteBlock( int, int, void * );
+        virtual CPLErr IReadBlock( int, int, void * ) CPL_OVERRIDE;
+        virtual CPLErr IWriteBlock( int, int, void * ) CPL_OVERRIDE;
         virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
                                 void *, int, int, GDALDataType,
-                                GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg );
+                                GSpacing, GSpacing, GDALRasterIOExtraArg* psExtraArg ) CPL_OVERRIDE;
 
     public:
 
-        virtual char      **GetMetadataDomainList();
-        virtual char      **GetMetadata( const char * pszDomain  );
+        virtual char      **GetMetadataDomainList() CPL_OVERRIDE;
+        virtual char      **GetMetadata( const char * pszDomain  ) CPL_OVERRIDE;
         virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                        const char * pszDomain  );
+                                        const char * pszDomain  ) CPL_OVERRIDE;
         virtual const char *GetMetadataItem( const char * pszName,
-                                            const char * pszDomain  );
+                                            const char * pszDomain  ) CPL_OVERRIDE;
         virtual CPLErr      SetMetadataItem( const char * pszName,
                                             const char * pszValue,
-                                            const char * pszDomain );
-        virtual CPLErr FlushCache();
-        virtual char **GetCategoryNames();
-        virtual double GetNoDataValue( int *pbSuccess = NULL );
-        virtual double GetMinimum( int *pbSuccess = NULL );
-        virtual double GetMaximum(int *pbSuccess = NULL );
-        virtual double GetOffset( int *pbSuccess = NULL );
-        virtual double GetScale( int *pbSuccess = NULL );
-        virtual const char *GetUnitType();
-        virtual GDALColorInterp GetColorInterpretation();
-        virtual GDALColorTable *GetColorTable();
-        virtual CPLErr Fill(double dfRealValue, double dfImaginaryValue = 0);
-
-        virtual CPLErr SetCategoryNames( char ** );
-        virtual CPLErr SetNoDataValue( double );
-        virtual CPLErr DeleteNoDataValue();
-        virtual CPLErr SetColorTable( GDALColorTable * );
-        virtual CPLErr SetColorInterpretation( GDALColorInterp );
-        virtual CPLErr SetOffset( double );
-        virtual CPLErr SetScale( double );
-        virtual CPLErr SetUnitType( const char * );
+                                            const char * pszDomain ) CPL_OVERRIDE;
+        virtual CPLErr FlushCache() CPL_OVERRIDE;
+        virtual char **GetCategoryNames() CPL_OVERRIDE;
+        virtual double GetNoDataValue( int *pbSuccess = NULL ) CPL_OVERRIDE;
+        virtual double GetMinimum( int *pbSuccess = NULL ) CPL_OVERRIDE;
+        virtual double GetMaximum(int *pbSuccess = NULL ) CPL_OVERRIDE;
+        virtual double GetOffset( int *pbSuccess = NULL ) CPL_OVERRIDE;
+        virtual double GetScale( int *pbSuccess = NULL ) CPL_OVERRIDE;
+        virtual const char *GetUnitType() CPL_OVERRIDE;
+        virtual GDALColorInterp GetColorInterpretation() CPL_OVERRIDE;
+        virtual GDALColorTable *GetColorTable() CPL_OVERRIDE;
+        virtual CPLErr Fill(double dfRealValue, double dfImaginaryValue = 0) CPL_OVERRIDE;
+
+        virtual CPLErr SetCategoryNames( char ** ) CPL_OVERRIDE;
+        virtual CPLErr SetNoDataValue( double ) CPL_OVERRIDE;
+        virtual CPLErr DeleteNoDataValue() CPL_OVERRIDE;
+        virtual CPLErr SetColorTable( GDALColorTable * ) CPL_OVERRIDE;
+        virtual CPLErr SetColorInterpretation( GDALColorInterp ) CPL_OVERRIDE;
+        virtual CPLErr SetOffset( double ) CPL_OVERRIDE;
+        virtual CPLErr SetScale( double ) CPL_OVERRIDE;
+        virtual CPLErr SetUnitType( const char * ) CPL_OVERRIDE;
 
         virtual CPLErr GetStatistics( int bApproxOK, int bForce,
                                     double *pdfMin, double *pdfMax,
-                                    double *pdfMean, double *padfStdDev );
+                                    double *pdfMean, double *padfStdDev ) CPL_OVERRIDE;
         virtual CPLErr ComputeStatistics( int bApproxOK,
                                         double *pdfMin, double *pdfMax,
                                         double *pdfMean, double *pdfStdDev,
-                                        GDALProgressFunc, void *pProgressData );
+                                        GDALProgressFunc, void *pProgressData ) CPL_OVERRIDE;
         virtual CPLErr SetStatistics( double dfMin, double dfMax,
-                                    double dfMean, double dfStdDev );
-        virtual CPLErr ComputeRasterMinMax( int, double* );
+                                    double dfMean, double dfStdDev ) CPL_OVERRIDE;
+        virtual CPLErr ComputeRasterMinMax( int, double* ) CPL_OVERRIDE;
 
-        virtual int HasArbitraryOverviews();
-        virtual int GetOverviewCount();
-        virtual GDALRasterBand *GetOverview(int);
-        virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig );
+        virtual int HasArbitraryOverviews() CPL_OVERRIDE;
+        virtual int GetOverviewCount() CPL_OVERRIDE;
+        virtual GDALRasterBand *GetOverview(int) CPL_OVERRIDE;
+        virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig ) CPL_OVERRIDE;
         virtual CPLErr BuildOverviews( const char *, int, int *,
-                                    GDALProgressFunc, void * );
+                                    GDALProgressFunc, void * ) CPL_OVERRIDE;
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                 int nBufXSize, int nBufYSize,
-                                GDALDataType eDT, char **papszOptions );
+                                GDALDataType eDT, char **papszOptions ) CPL_OVERRIDE;
 
         virtual CPLErr  GetHistogram( double dfMin, double dfMax,
                             int nBuckets, GUIntBig * panHistogram,
                             int bIncludeOutOfRange, int bApproxOK,
-                            GDALProgressFunc, void *pProgressData );
+                            GDALProgressFunc, void *pProgressData ) CPL_OVERRIDE;
 
         virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                             int *pnBuckets, GUIntBig ** ppanHistogram,
                                             int bForce,
-                                            GDALProgressFunc, void *pProgressData);
+                                            GDALProgressFunc, void *pProgressData) CPL_OVERRIDE;
         virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
-                                            int nBuckets, GUIntBig *panHistogram );
+                                            int nBuckets, GUIntBig *panHistogram ) CPL_OVERRIDE;
 
-        virtual GDALRasterAttributeTable *GetDefaultRAT();
-        virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
+        virtual GDALRasterAttributeTable *GetDefaultRAT() CPL_OVERRIDE;
+        virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * ) CPL_OVERRIDE;
 
-        virtual GDALRasterBand *GetMaskBand();
-        virtual int             GetMaskFlags();
-        virtual CPLErr          CreateMaskBand( int nFlags );
+        virtual GDALRasterBand *GetMaskBand() CPL_OVERRIDE;
+        virtual int             GetMaskFlags() CPL_OVERRIDE;
+        virtual CPLErr          CreateMaskBand( int nFlags ) CPL_OVERRIDE;
 
         virtual CPLVirtualMem  *GetVirtualMemAuto( GDALRWFlag eRWFlag,
                                                 int *pnPixelSpace,
                                                 GIntBig *pnLineSpace,
-                                                char **papszOptions );
+                                                char **papszOptions ) CPL_OVERRIDE;
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALProxyRasterBand);
+    CPL_DISALLOW_COPY_ASSIGN(GDALProxyRasterBand)
 };
 
-
 /* ******************************************************************** */
 /*                     GDALProxyPoolDataset                             */
 /* ******************************************************************** */
@@ -222,8 +223,8 @@ class CPL_DLL GDALProxyPoolDataset : public GDALProxyDataset
         GDALProxyPoolCacheEntry* cacheEntry;
 
     protected:
-        virtual GDALDataset *RefUnderlyingDataset();
-        virtual void UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset);
+        virtual GDALDataset *RefUnderlyingDataset() CPL_OVERRIDE;
+        virtual void UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset) CPL_OVERRIDE;
 
         friend class     GDALProxyPoolRasterBand;
 
@@ -234,30 +235,30 @@ class CPL_DLL GDALProxyPoolDataset : public GDALProxyDataset
                             int bShared = FALSE,
                             const char * pszProjectionRef = NULL,
                             double * padfGeoTransform = NULL);
-        ~GDALProxyPoolDataset();
+        virtual ~GDALProxyPoolDataset();
 
         void         SetOpenOptions(char** papszOpenOptions);
         void         AddSrcBandDescription( GDALDataType eDataType, int nBlockXSize, int nBlockYSize);
 
-        virtual const char *GetProjectionRef(void);
-        virtual CPLErr SetProjection( const char * );
+        virtual const char *GetProjectionRef(void) CPL_OVERRIDE;
+        virtual CPLErr SetProjection( const char * ) CPL_OVERRIDE;
 
-        virtual CPLErr GetGeoTransform( double * );
-        virtual CPLErr SetGeoTransform( double * );
+        virtual CPLErr GetGeoTransform( double * ) CPL_OVERRIDE;
+        virtual CPLErr SetGeoTransform( double * ) CPL_OVERRIDE;
 
         /* Special behaviour for the following methods : they return a pointer */
         /* data type, that must be cached by the proxy, so it doesn't become invalid */
         /* when the underlying object get closed */
-        virtual char      **GetMetadata( const char * pszDomain  );
+        virtual char      **GetMetadata( const char * pszDomain  ) CPL_OVERRIDE;
         virtual const char *GetMetadataItem( const char * pszName,
-                                            const char * pszDomain  );
+                                            const char * pszDomain  ) CPL_OVERRIDE;
 
-        virtual void *GetInternalHandle( const char * pszRequest );
+        virtual void *GetInternalHandle( const char * pszRequest ) CPL_OVERRIDE;
 
-        virtual const char *GetGCPProjection();
-        virtual const GDAL_GCP *GetGCPs();
+        virtual const char *GetGCPProjection() CPL_OVERRIDE;
+        virtual const GDAL_GCP *GetGCPs() CPL_OVERRIDE;
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALProxyPoolDataset);
+    CPL_DISALLOW_COPY_ASSIGN(GDALProxyPoolDataset)
 };
 
 /* ******************************************************************** */
@@ -283,8 +284,8 @@ class CPL_DLL GDALProxyPoolRasterBand : public GDALProxyRasterBand
         void Init();
 
     protected:
-        virtual GDALRasterBand* RefUnderlyingRasterBand();
-        virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand);
+        virtual GDALRasterBand* RefUnderlyingRasterBand() CPL_OVERRIDE;
+        virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand) CPL_OVERRIDE;
 
         friend class GDALProxyPoolOverviewRasterBand;
         friend class GDALProxyPoolMaskBand;
@@ -295,24 +296,24 @@ class CPL_DLL GDALProxyPoolRasterBand : public GDALProxyRasterBand
                                 int nBlockXSize, int nBlockYSize);
         GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDS,
                                 GDALRasterBand* poUnderlyingRasterBand);
-        ~GDALProxyPoolRasterBand();
+        virtual ~GDALProxyPoolRasterBand();
 
         void AddSrcMaskBandDescription( GDALDataType eDataType, int nBlockXSize, int nBlockYSize);
 
         /* Special behaviour for the following methods : they return a pointer */
         /* data type, that must be cached by the proxy, so it doesn't become invalid */
         /* when the underlying object get closed */
-        virtual char      **GetMetadata( const char * pszDomain  );
+        virtual char      **GetMetadata( const char * pszDomain  ) CPL_OVERRIDE;
         virtual const char *GetMetadataItem( const char * pszName,
-                                            const char * pszDomain  );
-        virtual char **GetCategoryNames();
-        virtual const char *GetUnitType();
-        virtual GDALColorTable *GetColorTable();
-        virtual GDALRasterBand *GetOverview(int);
-        virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig nDesiredSamples); // TODO
-        virtual GDALRasterBand *GetMaskBand();
+                                            const char * pszDomain  ) CPL_OVERRIDE;
+        virtual char **GetCategoryNames() CPL_OVERRIDE;
+        virtual const char *GetUnitType() CPL_OVERRIDE;
+        virtual GDALColorTable *GetColorTable() CPL_OVERRIDE;
+        virtual GDALRasterBand *GetOverview(int) CPL_OVERRIDE;
+        virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig nDesiredSamples) CPL_OVERRIDE; // TODO
+        virtual GDALRasterBand *GetMaskBand() CPL_OVERRIDE;
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALProxyPoolRasterBand);
+    CPL_DISALLOW_COPY_ASSIGN(GDALProxyPoolRasterBand)
 };
 
 /* ******************************************************************** */
@@ -329,15 +330,15 @@ class GDALProxyPoolOverviewRasterBand : public GDALProxyPoolRasterBand
         int                      nRefCountUnderlyingMainRasterBand;
 
     protected:
-        virtual GDALRasterBand* RefUnderlyingRasterBand();
-        virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand);
+        virtual GDALRasterBand* RefUnderlyingRasterBand() CPL_OVERRIDE;
+        virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand) CPL_OVERRIDE;
 
     public:
         GDALProxyPoolOverviewRasterBand(GDALProxyPoolDataset* poDS,
                                         GDALRasterBand* poUnderlyingOverviewBand,
                                         GDALProxyPoolRasterBand* poMainBand,
                                         int nOverviewBand);
-        ~GDALProxyPoolOverviewRasterBand();
+        virtual ~GDALProxyPoolOverviewRasterBand();
 };
 
 /* ******************************************************************** */
@@ -353,8 +354,8 @@ class GDALProxyPoolMaskBand : public GDALProxyPoolRasterBand
         int                      nRefCountUnderlyingMainRasterBand;
 
     protected:
-        virtual GDALRasterBand* RefUnderlyingRasterBand();
-        virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand);
+        virtual GDALRasterBand* RefUnderlyingRasterBand() CPL_OVERRIDE;
+        virtual void UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand) CPL_OVERRIDE;
 
     public:
         GDALProxyPoolMaskBand(GDALProxyPoolDataset* poDS,
@@ -364,17 +365,15 @@ class GDALProxyPoolMaskBand : public GDALProxyPoolRasterBand
                               GDALProxyPoolRasterBand* poMainBand,
                               GDALDataType eDataType,
                               int nBlockXSize, int nBlockYSize);
-        ~GDALProxyPoolMaskBand();
+        virtual ~GDALProxyPoolMaskBand();
 };
 
 #endif
 
-
 /* ******************************************************************** */
 /*            C types and methods declarations                          */
 /* ******************************************************************** */
 
-
 CPL_C_START
 
 typedef struct GDALProxyPoolDatasetHS *GDALProxyPoolDatasetH;
@@ -393,4 +392,6 @@ void CPL_DLL GDALProxyPoolDatasetAddSrcBandDescription( GDALProxyPoolDatasetH hP
 
 CPL_C_END
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* GDAL_PROXY_H_INCLUDED */
diff --git a/gcore/gdal_rat.cpp b/gcore/gdal_rat.cpp
index bfab72c..d7260b8 100644
--- a/gcore/gdal_rat.cpp
+++ b/gcore/gdal_rat.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdal_rat.cpp 33785 2016-03-25 16:34:55Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRasterAttributeTable and related classes.
@@ -28,12 +27,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal.h"
 #include "gdal_priv.h"
 #include "gdal_rat.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+
+#include <algorithm>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
 #include "json.h"
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
 #include "ogrgeojsonwriter.h"
 
-CPL_CVSID("$Id: gdal_rat.cpp 33785 2016-03-25 16:34:55Z goatbar $");
+CPL_CVSID("$Id: gdal_rat.cpp 36759 2016-12-09 16:15:51Z goatbar $");
 
 /**
  * \class GDALRasterAttributeTable
@@ -289,7 +312,7 @@ CPLErr CPL_STDCALL GDALRATValuesIOAsString(
  * @param nNewCount the new number of rows.
  */
 
-void GDALRasterAttributeTable::SetRowCount( int /* nNewCount */ ) {}
+void GDALRasterAttributeTable::SetRowCount( CPL_UNUSED int nNewCount ) {}
 
 /************************************************************************/
 /*                         GDALRATSetRowCount()                         */
@@ -300,6 +323,9 @@ void GDALRasterAttributeTable::SetRowCount( int /* nNewCount */ ) {}
  *
  * This function is the same as the C++ method
  * GDALRasterAttributeTable::SetRowCount()
+ *
+ * @param hRAT RAT handle.
+ * @param nNewCount the new number of rows.
  */
 void CPL_STDCALL
 GDALRATSetRowCount( GDALRasterAttributeTableH hRAT, int nNewCount )
@@ -315,6 +341,7 @@ GDALRATSetRowCount( GDALRasterAttributeTableH hRAT, int nNewCount )
 /************************************************************************/
 
 /**
+ * \fn GDALRasterAttributeTable::GetRowOfValue(double) const
  * \brief Get row for pixel value.
  *
  * Given a raw pixel value, the raster attribute table is scanned to
@@ -328,6 +355,9 @@ GDALRATSetRowCount( GDALRasterAttributeTableH hRAT, int nNewCount )
  * @return the row index or -1 if no row is appropriate.
  */
 
+/**/
+/**/
+
 int GDALRasterAttributeTable::GetRowOfValue( double /* dfValue */ ) const
 {
     return -1;
@@ -355,11 +385,25 @@ GDALRATGetRowOfValue( GDALRasterAttributeTableH hRAT, double dfValue )
 
 /************************************************************************/
 /*                           GetRowOfValue()                            */
-/*                                                                      */
-/*      Int arg for now just converted to double.  Perhaps we will      */
-/*      handle this in a special way some day?                          */
 /************************************************************************/
 
+/**
+ * \brief Get row for pixel value.
+ *
+ * Given a raw pixel value, the raster attribute table is scanned to
+ * determine which row in the table applies to the pixel value.  The
+ * row index is returned.
+ *
+ * Int arg for now just converted to double.  Perhaps we will
+ * handle this in a special way some day?
+ *
+ * This method is the same as the C function GDALRATGetRowOfValue().
+ *
+ * @param nValue the pixel value.
+ *
+ * @return the row index or -1 if no row is appropriate.
+ */
+
 int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
 
 {
@@ -371,6 +415,7 @@ int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
 /************************************************************************/
 
 /**
+ * \fn GDALRasterAttributeTable::CreateColumn(const char*, GDALRATFieldType, GDALRATFieldUsage)
  * \brief Create new column.
  *
  * If the table already has rows, all row values for the new column will
@@ -387,6 +432,9 @@ int GDALRasterAttributeTable::GetRowOfValue( int nValue ) const
  * @return CE_None on success or CE_Failure if something goes wrong.
  */
 
+/**/
+/**/
+
 CPLErr GDALRasterAttributeTable::CreateColumn(
     const char * /* pszFieldName */, GDALRATFieldType /* eFieldType */,
     GDALRATFieldUsage /* eFieldUsage */ )
@@ -435,8 +483,8 @@ CPLErr CPL_STDCALL GDALRATCreateColumn( GDALRasterAttributeTableH hRAT,
  * @return CE_None on success or CE_Failure on failure.
  */
 
-CPLErr GDALRasterAttributeTable::SetLinearBinning( double /* dfRow0MinIn */,
-                                                   double /* dfBinSizeIn */ )
+CPLErr GDALRasterAttributeTable::SetLinearBinning( CPL_UNUSED double dfRow0MinIn,
+                                                   CPL_UNUSED double dfBinSizeIn )
 {
     return CE_Failure;
 }
@@ -480,7 +528,8 @@ GDALRATSetLinearBinning( GDALRasterAttributeTableH hRAT,
  */
 
 int GDALRasterAttributeTable::GetLinearBinning(
-    double * /* pdfRow0Min */ , double * /* pdfBinSize */ ) const
+    CPL_UNUSED double * pdfRow0Min ,
+    CPL_UNUSED double * pdfBinSize ) const
 {
     return FALSE;
 }
@@ -510,6 +559,9 @@ GDALRATGetLinearBinning( GDALRasterAttributeTableH hRAT,
 /*                             Serialize()                              */
 /************************************************************************/
 
+/** Serialize as a XML tree.
+ * @return XML tree.
+ */
 CPLXMLNode *GDALRasterAttributeTable::Serialize() const
 
 {
@@ -608,9 +660,12 @@ CPLXMLNode *GDALRasterAttributeTable::Serialize() const
 }
 
 /************************************************************************/
-/*                             SerializeJSON()                              */
+/*                             SerializeJSON()                           */
 /************************************************************************/
 
+/** Serialize as a JSON object.
+ * @return JSON object (of type json_object*)
+ */
 void *GDALRasterAttributeTable::SerializeJSON() const
 
 {
@@ -619,12 +674,13 @@ void *GDALRasterAttributeTable::SerializeJSON() const
     if( ( GetColumnCount() == 0 ) && ( GetRowCount() == 0 ) )
         return poRAT;
 
-
 /* -------------------------------------------------------------------- */
 /*      Add attributes with regular binning info if appropriate.        */
 /* -------------------------------------------------------------------- */
-    double dfRow0Min, dfBinSize;
-    json_object *poRow0Min, *poBinSize;
+    double dfRow0Min = 0.0;
+    double dfBinSize = 0.0;
+    json_object *poRow0Min = NULL;
+    json_object *poBinSize = NULL;
 
     if( GetLinearBinning(&dfRow0Min, &dfBinSize) )
     {
@@ -705,6 +761,10 @@ void *GDALRasterAttributeTable::SerializeJSON() const
 /*                              XMLInit()                               */
 /************************************************************************/
 
+/** Deserialize from XML.
+ * @param psTree XML tree
+ * @return error code.
+ */
 CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree,
                                           const char * /*pszVRTPath*/ )
 
@@ -772,7 +832,6 @@ CPLErr GDALRasterAttributeTable::XMLInit( CPLXMLNode *psTree,
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                      InitializeFromColorTable()                      */
 /************************************************************************/
@@ -904,13 +963,14 @@ GDALColorTable *GDALRasterAttributeTable::TranslateToColorTable(
             return NULL;
 
         for( int iRow = 0; iRow < GetRowCount(); iRow++ )
-            nEntryCount = MAX(nEntryCount, GetValueAsInt(iRow, iMaxCol) + 1);
+            nEntryCount =
+                std::max(nEntryCount, GetValueAsInt(iRow, iMaxCol) + 1);
 
         if( nEntryCount < 0 )
             return NULL;
 
-        // restrict our number of entries to something vaguely sensible
-        nEntryCount = MIN(65535, nEntryCount);
+        // Restrict our number of entries to something vaguely sensible.
+        nEntryCount = std::min(65535, nEntryCount);
     }
 
 /* -------------------------------------------------------------------- */
@@ -961,7 +1021,6 @@ GDALRATTranslateToColorTable( GDALRasterAttributeTableH hRAT,
         TranslateToColorTable( nEntryCount );
 }
 
-
 /************************************************************************/
 /*                            DumpReadable()                            */
 /************************************************************************/
@@ -981,7 +1040,7 @@ void GDALRasterAttributeTable::DumpReadable( FILE * fp )
 
 {
     CPLXMLNode *psTree = Serialize();
-    char *pszXMLText = CPLSerializeXMLTree( psTree );
+    char * const pszXMLText = CPLSerializeXMLTree( psTree );
 
     CPLDestroyXMLNode( psTree );
 
@@ -1012,7 +1071,6 @@ GDALRATDumpReadable( GDALRasterAttributeTableH hRAT, FILE *fp )
     static_cast<GDALRasterAttributeTable *>(hRAT)->DumpReadable( fp );
 }
 
-
 /* \class GDALDefaultRasterAttributeTable
  *
  * An implementation of GDALRasterAttributeTable that keeps
@@ -1147,6 +1205,10 @@ int CPL_STDCALL GDALRATGetColumnCount( GDALRasterAttributeTableH hRAT )
 /*                            GetNameOfCol()                            */
 /************************************************************************/
 
+/** \brief Fetch name of indicated column.
+ * @param iCol column index.
+ * @return name.
+ */
 const char *GDALDefaultRasterAttributeTable::GetNameOfCol( int iCol ) const
 
 {
@@ -1165,6 +1227,9 @@ const char *GDALDefaultRasterAttributeTable::GetNameOfCol( int iCol ) const
  *
  * This function is the same as the C++ method
  * GDALRasterAttributeTable::GetNameOfCol()
+ * @param hRAT RAT handle.
+ * @param iCol column index.
+ * @return name.
  */
 const char *CPL_STDCALL GDALRATGetNameOfCol( GDALRasterAttributeTableH hRAT,
                                              int iCol )
@@ -1179,6 +1244,12 @@ const char *CPL_STDCALL GDALRATGetNameOfCol( GDALRasterAttributeTableH hRAT,
 /*                           GetUsageOfCol()                            */
 /************************************************************************/
 
+/**
+ * \brief Fetch column usage value.
+ *
+ * @param iCol column index.
+ * @return usage.
+ */
 GDALRATFieldUsage GDALDefaultRasterAttributeTable::GetUsageOfCol(
     int iCol ) const
 
@@ -1197,7 +1268,10 @@ GDALRATFieldUsage GDALDefaultRasterAttributeTable::GetUsageOfCol(
  * \brief Fetch column usage value.
  *
  * This function is the same as the C++ method
- * GDALRasterAttributeTable::GetUsageOfColetNameOfCol()
+ * GDALRasterAttributeTable::GetUsageOfCol()
+ * @param hRAT RAT handle.
+ * @param iCol column index.
+ * @return usage.
  */
 GDALRATFieldUsage CPL_STDCALL
 GDALRATGetUsageOfCol( GDALRasterAttributeTableH hRAT, int iCol )
@@ -1212,6 +1286,12 @@ GDALRATGetUsageOfCol( GDALRasterAttributeTableH hRAT, int iCol )
 /*                            GetTypeOfCol()                            */
 /************************************************************************/
 
+/**
+ * \brief Fetch column type.
+ *
+ * @param iCol column index.
+ * @return type.
+ */
 GDALRATFieldType GDALDefaultRasterAttributeTable::GetTypeOfCol( int iCol ) const
 
 {
@@ -1230,6 +1310,9 @@ GDALRATFieldType GDALDefaultRasterAttributeTable::GetTypeOfCol( int iCol ) const
  *
  * This function is the same as the C++ method
  * GDALRasterAttributeTable::GetTypeOfCol()
+ * @param hRAT RAT handle.
+ * @param iCol column index.
+ * @return type.
  */
 GDALRATFieldType CPL_STDCALL
 GDALRATGetTypeOfCol( GDALRasterAttributeTableH hRAT, int iCol )
@@ -1244,6 +1327,10 @@ GDALRATGetTypeOfCol( GDALRasterAttributeTableH hRAT, int iCol )
 /*                           GetColOfUsage()                            */
 /************************************************************************/
 
+/** Return the index of the column that corresponds to the passed usage.
+ * @param eUsage usage.
+ * @return column index, or -1 in case of error.
+ */
 int GDALDefaultRasterAttributeTable::GetColOfUsage(
     GDALRATFieldUsage eUsage ) const
 
@@ -1495,6 +1582,9 @@ GDALRATGetValueAsDouble( GDALRasterAttributeTableH hRAT, int iRow, int iField )
 /*                            SetRowCount()                             */
 /************************************************************************/
 
+/** Set row count.
+ * @param nNewCount new count.
+ */
 void GDALDefaultRasterAttributeTable::SetRowCount( int nNewCount )
 
 {
@@ -1526,6 +1616,11 @@ void GDALDefaultRasterAttributeTable::SetRowCount( int nNewCount )
 /*                              SetValue()                              */
 /************************************************************************/
 
+/** Set value
+ * @param iRow row index.
+ * @param iField field index.
+ * @param pszValue value.
+ */
 void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
                                                 const char *pszValue )
 
@@ -1574,6 +1669,10 @@ void GDALDefaultRasterAttributeTable::SetValue( int iRow, int iField,
  *
  * This function is the same as the C++ method
  * GDALRasterAttributeTable::SetValue()
+ * @param hRAT RAT handle.
+ * @param iRow row index.
+ * @param iField field index.
+ * @param pszValue value.
  */
 void CPL_STDCALL
 GDALRATSetValueAsString( GDALRasterAttributeTableH hRAT, int iRow, int iField,
@@ -1882,9 +1981,10 @@ int GDALDefaultRasterAttributeTable::GetLinearBinning(
 /*                            CreateColumn()                            */
 /************************************************************************/
 
-CPLErr GDALDefaultRasterAttributeTable::CreateColumn( const char *pszFieldName,
-                                               GDALRATFieldType eFieldType,
-                                               GDALRATFieldUsage eFieldUsage )
+CPLErr GDALDefaultRasterAttributeTable::CreateColumn(
+    const char *pszFieldName,
+    GDALRATFieldType eFieldType,
+    GDALRATFieldUsage eFieldUsage )
 
 {
     const size_t iNewField = aoFields.size();
diff --git a/gcore/gdal_rat.h b/gcore/gdal_rat.h
index 4a7a4f3..e06e395 100644
--- a/gcore/gdal_rat.h
+++ b/gcore/gdal_rat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_rat.h 33773 2016-03-23 18:39:47Z goatbar $
+ * $Id: gdal_rat.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  GDALRasterAttributeTable class declarations.
@@ -79,7 +79,7 @@ public:
      *
      * @return the column name or an empty string for invalid column numbers.
      */
-    virtual const char   *GetNameOfCol( int ) const = 0;
+    virtual const char   *GetNameOfCol( int iCol ) const = 0;
 
     /**
      * \brief Fetch column usage value.
@@ -90,7 +90,7 @@ public:
      *
      * @return the column usage, or GFU_Generic for improper column numbers.
      */
-    virtual GDALRATFieldUsage GetUsageOfCol( int ) const = 0;
+    virtual GDALRATFieldUsage GetUsageOfCol( int iCol ) const = 0;
 
     /**
      * \brief Fetch column type.
@@ -101,7 +101,7 @@ public:
      *
      * @return column type or GFT_Integer if the column index is illegal.
      */
-    virtual GDALRATFieldType GetTypeOfCol( int ) const = 0;
+    virtual GDALRATFieldType GetTypeOfCol( int iCol ) const = 0;
 
     /**
      * \brief Fetch column index for given usage.
@@ -115,7 +115,7 @@ public:
      *
      * @return column index, or -1 on failure.
      */
-    virtual int           GetColOfUsage( GDALRATFieldUsage ) const = 0;
+    virtual int           GetColOfUsage( GDALRATFieldUsage eUsage ) const = 0;
 
     /**
      * \brief Fetch row count.
@@ -279,7 +279,7 @@ public:
 /*                                                                      */
 /*      (private)                                                       */
 /************************************************************************/
-
+//! @cond Doxygen_Suppress
 class GDALRasterAttributeField
 {
  public:
@@ -293,6 +293,7 @@ class GDALRasterAttributeField
     std::vector<double> adfValues;
     std::vector<CPLString> aosValues;
 };
+//! @endcond
 
 /************************************************************************/
 /*                    GDALDefaultRasterAttributeTable                   */
@@ -321,42 +322,42 @@ class CPL_DLL GDALDefaultRasterAttributeTable : public GDALRasterAttributeTable
  public:
     GDALDefaultRasterAttributeTable();
     GDALDefaultRasterAttributeTable( const GDALDefaultRasterAttributeTable& );
-    ~GDALDefaultRasterAttributeTable();
+    virtual ~GDALDefaultRasterAttributeTable();
 
-    GDALDefaultRasterAttributeTable *Clone() const;
+    GDALDefaultRasterAttributeTable *Clone() const CPL_OVERRIDE;
 
-    virtual int           GetColumnCount() const;
+    virtual int           GetColumnCount() const CPL_OVERRIDE;
 
-    virtual const char   *GetNameOfCol( int ) const;
-    virtual GDALRATFieldUsage GetUsageOfCol( int ) const;
-    virtual GDALRATFieldType GetTypeOfCol( int ) const;
+    virtual const char   *GetNameOfCol( int ) const CPL_OVERRIDE;
+    virtual GDALRATFieldUsage GetUsageOfCol( int ) const CPL_OVERRIDE;
+    virtual GDALRATFieldType GetTypeOfCol( int ) const CPL_OVERRIDE;
 
-    virtual int           GetColOfUsage( GDALRATFieldUsage ) const;
+    virtual int           GetColOfUsage( GDALRATFieldUsage ) const CPL_OVERRIDE;
 
-    virtual int           GetRowCount() const;
+    virtual int           GetRowCount() const CPL_OVERRIDE;
 
-    virtual const char   *GetValueAsString( int iRow, int iField ) const;
-    virtual int           GetValueAsInt( int iRow, int iField ) const;
-    virtual double        GetValueAsDouble( int iRow, int iField ) const;
+    virtual const char   *GetValueAsString( int iRow, int iField ) const CPL_OVERRIDE;
+    virtual int           GetValueAsInt( int iRow, int iField ) const CPL_OVERRIDE;
+    virtual double        GetValueAsDouble( int iRow, int iField ) const CPL_OVERRIDE;
 
     virtual void          SetValue( int iRow, int iField,
-                                    const char *pszValue );
-    virtual void          SetValue( int iRow, int iField, double dfValue);
-    virtual void          SetValue( int iRow, int iField, int nValue );
+                                    const char *pszValue ) CPL_OVERRIDE;
+    virtual void          SetValue( int iRow, int iField, double dfValue) CPL_OVERRIDE;
+    virtual void          SetValue( int iRow, int iField, int nValue ) CPL_OVERRIDE;
 
-    virtual int           ChangesAreWrittenToFile();
-    virtual void          SetRowCount( int iCount );
+    virtual int           ChangesAreWrittenToFile() CPL_OVERRIDE;
+    virtual void          SetRowCount( int iCount ) CPL_OVERRIDE;
 
-    virtual int           GetRowOfValue( double dfValue ) const;
-    virtual int           GetRowOfValue( int nValue ) const;
+    virtual int           GetRowOfValue( double dfValue ) const CPL_OVERRIDE;
+    virtual int           GetRowOfValue( int nValue ) const CPL_OVERRIDE;
 
     virtual CPLErr        CreateColumn( const char *pszFieldName,
                                         GDALRATFieldType eFieldType,
-                                        GDALRATFieldUsage eFieldUsage );
+                                        GDALRATFieldUsage eFieldUsage ) CPL_OVERRIDE;
     virtual CPLErr        SetLinearBinning( double dfRow0Min,
-                                            double dfBinSize );
+                                            double dfBinSize ) CPL_OVERRIDE;
     virtual int           GetLinearBinning( double *pdfRow0Min,
-                                            double *pdfBinSize ) const;
+                                            double *pdfBinSize ) const CPL_OVERRIDE;
 };
 
 #endif /* ndef GDAL_RAT_H_INCLUDED */
diff --git a/gcore/gdal_version.h b/gcore/gdal_version.h
index a486be4..f273397 100644
--- a/gcore/gdal_version.h
+++ b/gcore/gdal_version.h
@@ -1,3 +1,4 @@
+/* $Id: gdal_version.h 37989 2017-04-14 07:47:45Z rouault $ */
 
 /* -------------------------------------------------------------------- */
 /*      GDAL Version Information.                                       */
@@ -5,12 +6,12 @@
 
 #ifndef GDAL_VERSION_MAJOR
 #  define GDAL_VERSION_MAJOR    2
-#  define GDAL_VERSION_MINOR    1
-#  define GDAL_VERSION_REV      3
+#  define GDAL_VERSION_MINOR    2
+#  define GDAL_VERSION_REV      0
 #  define GDAL_VERSION_BUILD    0
 #endif
 
-    /* GDAL_COMPUTE_VERSION macro introduced in GDAL 1.10 */
+/* GDAL_COMPUTE_VERSION macro introduced in GDAL 1.10 */
 /* Must be used ONLY to compare with version numbers for GDAL >= 1.10 */
 #ifndef GDAL_COMPUTE_VERSION
 #define GDAL_COMPUTE_VERSION(maj,min,rev) ((maj)*1000000+(min)*10000+(rev)*100)
@@ -22,8 +23,8 @@
 #endif
 
 #ifndef GDAL_RELEASE_DATE
-#  define GDAL_RELEASE_DATE     20172001
+#  define GDAL_RELEASE_DATE     20170414
 #endif
 #ifndef GDAL_RELEASE_NAME
-#  define GDAL_RELEASE_NAME     "2.1.3"
+#  define GDAL_RELEASE_NAME     "2.2.0beta1"
 #endif
diff --git a/gcore/gdalabstractbandblockcache.cpp b/gcore/gdalabstractbandblockcache.cpp
index b633203..d81a030 100644
--- a/gcore/gdalabstractbandblockcache.cpp
+++ b/gcore/gdalabstractbandblockcache.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalabstractbandblockcache.cpp 35731 2016-10-14 17:07:59Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Store cached blocks
@@ -27,11 +26,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
-#include "cpl_multiproc.h"
+
+#include <cstddef>
 #include <new>
 
-CPL_CVSID("$Id: gdalabstractbandblockcache.cpp 35731 2016-10-14 17:07:59Z rouault $");
+#include "cpl_atomic_ops.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+
+//! @cond Doxygen_Suppress
+
+CPL_CVSID("$Id: gdalabstractbandblockcache.cpp 36776 2016-12-10 11:17:47Z rouault $");
 
 #ifdef DEBUG_VERBOSE_ABBC
 static int nAllBandsKeptAlivedBlocks = 0;
@@ -41,7 +48,8 @@ static int nAllBandsKeptAlivedBlocks = 0;
 /*                       GDALArrayBandBlockCache()                      */
 /************************************************************************/
 
-GDALAbstractBandBlockCache::GDALAbstractBandBlockCache(GDALRasterBand* poBandIn) :
+GDALAbstractBandBlockCache::GDALAbstractBandBlockCache(
+    GDALRasterBand* poBandIn ) :
     hSpinLock(CPLCreateLock(LOCK_SPIN)),
     psListBlocksToFree(NULL),
     hCond(CPLCreateCond()),
@@ -100,7 +108,7 @@ void GDALAbstractBandBlockCache::AddBlockToFreeList( GDALRasterBlock *poBlock )
     {
 #ifdef DEBUG_VERBOSE_ABBC
         CPLAtomicInc(&nAllBandsKeptAlivedBlocks);
-        fprintf(stderr, "AddBlockToFreeList(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks);
+        fprintf(stderr, "AddBlockToFreeList(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks);/*ok*/
 #endif
         CPLLockHolderOptionalLockD(hSpinLock);
         poBlock->poNext = psListBlocksToFree;
@@ -152,7 +160,7 @@ void GDALAbstractBandBlockCache::FreeDanglingBlocks()
     {
 #ifdef DEBUG_VERBOSE_ABBC
         CPLAtomicDec(&nAllBandsKeptAlivedBlocks);
-        fprintf(stderr, "FreeDanglingBlocks(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks);
+        fprintf(stderr, "FreeDanglingBlocks(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks);/*ok*/
 #endif
         GDALRasterBlock* poNext = poList->poNext;
         poList->poNext = NULL;
@@ -176,7 +184,7 @@ GDALRasterBlock* GDALAbstractBandBlockCache::CreateBlock(int nXBlockOff,
         {
 #ifdef DEBUG_VERBOSE_ABBC
             CPLAtomicDec(&nAllBandsKeptAlivedBlocks);
-            fprintf(stderr, "CreateBlock(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks);
+            fprintf(stderr, "CreateBlock(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks);/*ok*/
 #endif
             psListBlocksToFree = poBlock->poNext;
         }
@@ -188,3 +196,4 @@ GDALRasterBlock* GDALAbstractBandBlockCache::CreateBlock(int nXBlockOff,
             poBand, nXBlockOff, nYBlockOff );
     return poBlock;
 }
+//! @endcond
diff --git a/gcore/gdalallvalidmaskband.cpp b/gcore/gdalallvalidmaskband.cpp
index b4f7f75..7d770ca 100644
--- a/gcore/gdalallvalidmaskband.cpp
+++ b/gcore/gdalallvalidmaskband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalallvalidmaskband.cpp 31440 2015-11-12 01:38:25Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALAllValidMaskBand, a class implementing all
@@ -28,10 +27,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalallvalidmaskband.cpp 31440 2015-11-12 01:38:25Z goatbar $");
+#include <cstring>
 
+#include "gdal.h"
+#include "cpl_error.h"
+
+CPL_CVSID("$Id: gdalallvalidmaskband.cpp 36522 2016-11-26 16:04:27Z goatbar $");
+
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                        GDALAllValidMaskBand()                        */
 /************************************************************************/
@@ -87,3 +93,4 @@ int GDALAllValidMaskBand::GetMaskFlags()
 {
     return GMF_ALL_VALID;
 }
+//! @endcond
diff --git a/gcore/gdalarraybandblockcache.cpp b/gcore/gdalarraybandblockcache.cpp
index fc83611..1234dbe 100644
--- a/gcore/gdalarraybandblockcache.cpp
+++ b/gcore/gdalarraybandblockcache.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalarraybandblockcache.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Store cached blocks in a array or a two-level array
@@ -28,15 +27,25 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
-#include "cpl_multiproc.h"
+
+#include <climits>
+#include <cstddef>
 #include <new>
 
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_vsi.h"
+
+//! @cond Doxygen_Suppress
+
 static const int SUBBLOCK_SIZE = 64;
 #define TO_SUBBLOCK(x) ((x) >> 6)
 #define WITHIN_SUBBLOCK(x) ((x) & 0x3f)
 
-CPL_CVSID("$Id: gdalarraybandblockcache.cpp 33694 2016-03-10 17:54:30Z goatbar $");
+CPL_CVSID("$Id: gdalarraybandblockcache.cpp 36522 2016-11-26 16:04:27Z goatbar $");
 
 /* ******************************************************************** */
 /*                        GDALArrayBandBlockCache                       */
@@ -54,16 +63,16 @@ class GDALArrayBandBlockCache CPL_FINAL : public GDALAbstractBandBlockCache
     } u;
 
     public:
-            explicit GDALArrayBandBlockCache(GDALRasterBand* poBand);
-           ~GDALArrayBandBlockCache();
-
-           virtual bool             Init();
-           virtual bool             IsInitOK();
-           virtual CPLErr           FlushCache();
-           virtual CPLErr           AdoptBlock( GDALRasterBlock * );
-           virtual GDALRasterBlock *TryGetLockedBlockRef( int nXBlockOff, int nYBlockYOff );
-           virtual CPLErr           UnreferenceBlock( GDALRasterBlock* poBlock );
-           virtual CPLErr           FlushBlock( int nXBlockOff, int nYBlockOff, int bWriteDirtyBlock );
+           explicit GDALArrayBandBlockCache( GDALRasterBand* poBand );
+           virtual ~GDALArrayBandBlockCache();
+
+           virtual bool             Init() override;
+           virtual bool             IsInitOK() override;
+           virtual CPLErr           FlushCache() override;
+           virtual CPLErr           AdoptBlock( GDALRasterBlock * )  override;
+           virtual GDALRasterBlock *TryGetLockedBlockRef( int nXBlockOff, int nYBlockYOff ) override;
+           virtual CPLErr           UnreferenceBlock( GDALRasterBlock* poBlock ) override;
+           virtual CPLErr           FlushBlock( int nXBlockOff, int nYBlockOff, int bWriteDirtyBlock ) override;
 };
 
 /************************************************************************/
@@ -150,7 +159,6 @@ bool GDALArrayBandBlockCache::Init()
                                     "Out of memory in InitBlockInfo()." );
                 return false;
             }
-
         }
         else
         {
@@ -479,3 +487,5 @@ GDALRasterBlock *GDALArrayBandBlockCache::TryGetLockedBlockRef( int nXBlockOff,
 
     return poBlock;
 }
+
+//! @endcond
diff --git a/gcore/gdalclientserver.cpp b/gcore/gdalclientserver.cpp
index f46b1a5..e4e4e95 100644
--- a/gcore/gdalclientserver.cpp
+++ b/gcore/gdalclientserver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalclientserver.cpp 33810 2016-03-29 22:18:45Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  GDAL Client/server dataset mechanism.
@@ -62,10 +61,36 @@
 #include <sys/ioctl.h>
 #endif
 
+#include <cerrno>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cpl_config.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_multiproc.h"
+#include "cpl_progress.h"
+#include "cpl_spawn.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 #include "gdal_pam.h"
+#include "gdal_priv.h"
 #include "gdal_rat.h"
-#include "cpl_spawn.h"
-#include "cpl_multiproc.h"
+#include "gdal_version.h"
 
 /*!
 \page gdal_api_proxy GDAL API Proxy
@@ -74,57 +99,67 @@
 
 (GDAL >= 1.10.0)
 
-When dealing with some file formats, particularly the drivers relying on third-party
-(potentially closed-source) libraries, it is difficult to ensure that those third-party
-libraries will be robust to hostile/corrupted datasource.
+When dealing with some file formats, particularly the drivers relying on
+third-party (potentially closed-source) libraries, it is difficult to ensure
+that those third-party libraries will be robust to hostile/corrupted datasource.
 
-The implemented solution is to have a (private) API_PROXY driver that will expose a GDALClientDataset
-object, which will forward all the GDAL API calls to another process ("server"), where the real driver
-will be effectively run. This way, if the server aborts due to a fatal error, the calling process will
-be unaffected and will report a clean error instead of aborting itself.
+The implemented solution is to have a (private) API_PROXY driver that will
+expose a GDALClientDataset object, which will forward all the GDAL API calls to
+another process ("server"), where the real driver will be effectively run. This
+way, if the server aborts due to a fatal error, the calling process will be
+unaffected and will report a clean error instead of aborting itself.
 
 \section gdal_api_proxy_enabling How to enable ?
 
-The API_PROXY mechanism can be enabled by setting the GDAL_API_PROXY config option to YES.
-The option can also be set to a list of file extensions that must be the only ones to trigger
-this mechanism (e.g. GDAL_API_PROXY=ecw,sid).
+The API_PROXY mechanism can be enabled by setting the GDAL_API_PROXY config
+option to YES.  The option can also be set to a list of file extensions that
+must be the only ones to trigger this mechanism (e.g. GDAL_API_PROXY=ecw,sid).
 
-When enabled, datasets can be handled with GDALOpen(), GDALCreate() or GDALCreateCopy() with
-their nominal filename (or connection string).
+When enabled, datasets can be handled with GDALOpen(), GDALCreate() or
+GDALCreateCopy() with their nominal filename (or connection string).
 
-Alternatively, the API_PROXY mechanism can be used selectively on a datasource by prefixing its
-name with API_PROXY:, for example GDALOpen("API_PROXY:foo.tif", GA_ReadOnly).
+Alternatively, the API_PROXY mechanism can be used selectively on a datasource
+by prefixing its name with API_PROXY:, for example GDALOpen("API_PROXY:foo.tif",
+GA_ReadOnly).
 
 \section gdal_api_proxy_options Advanced options
 
-For now, the server launched is the gdalserver executable on Windows. On Unix, the default behaviour is
-to just fork() the current process. It is also possible to launch the gdalserver executable
-by forcing GDAL_API_PROXY_SERVER=YES.
-The full filename of the gdalserver executable can also be specified in the GDAL_API_PROXY_SERVER.
-
-It is also possible to connect to a gdalserver in TCP, possibly on a remote host. In that case,
-gdalserver must be launched on a host with "gdalserver -tcpserver the_tcp_port". And the client
-must set GDAL_API_PROXY_SERVER="hostname:the_tcp_port", where hostname is a string or a IP address.
-
-On Unix, gdalserver can also be launched on a Unix socket, which "gdalserver -unixserver /a/filename".
-Clients should then set GDAL_API_PROXY_SERVER to "/a/filename".
-
-In case of many dataset opening or creation, to avoid the cost of repeated process forking,
-a pool of unused connections is established. Each time a dataset is closed, the associated connection
-is pushed in the pool (if there's an empty bucket). When a following dataset is to be opened, one of those
-connections will be reused. This behaviour is controlled with the GDAL_API_PROXY_CONN_POOL config option
-that is set to YES by default, and will keep a maximum of 4 unused connections.
-GDAL_API_PROXY_CONN_POOL can be set to a integer value to specify the maximum number of unused connections.
+For now, the server launched is the gdalserver executable on Windows. On Unix,
+the default behaviour is to just fork() the current process. It is also possible
+to launch the gdalserver executable by forcing GDAL_API_PROXY_SERVER=YES.  The
+full filename of the gdalserver executable can also be specified in the
+GDAL_API_PROXY_SERVER.
+
+It is also possible to connect to a gdalserver in TCP, possibly on a remote
+host. In that case, gdalserver must be launched on a host with "gdalserver
+-tcpserver the_tcp_port". And the client must set
+GDAL_API_PROXY_SERVER="hostname:the_tcp_port", where hostname is a string or a
+IP address.
+
+On Unix, gdalserver can also be launched on a Unix socket, which "gdalserver
+-unixserver /a/filename".  Clients should then set GDAL_API_PROXY_SERVER to
+"/a/filename".
+
+In case of many dataset opening or creation, to avoid the cost of repeated
+process forking, a pool of unused connections is established. Each time a
+dataset is closed, the associated connection is pushed in the pool (if there's
+an empty bucket). When a following dataset is to be opened, one of those
+connections will be reused. This behaviour is controlled with the
+GDAL_API_PROXY_CONN_POOL config option that is set to YES by default, and will
+keep a maximum of 4 unused connections.  GDAL_API_PROXY_CONN_POOL can be set to
+a integer value to specify the maximum number of unused connections.
 
 \section gdal_api_proxy_limitations Limitations
 
-Datasets stored in the memory virtual file system (/vsimem) or handled by the MEM driver are excluded from
-the API Proxy mechanism.
+Datasets stored in the memory virtual file system (/vsimem) or handled by the
+MEM driver are excluded from the API Proxy mechanism.
 
-Additionnaly, for GDALCreate() or GDALCreateCopy(), the VRT driver is also excluded from that mechanism.
+Additionnaly, for GDALCreate() or GDALCreateCopy(), the VRT driver is also
+excluded from that mechanism.
 
-Currently, the client dataset returned is not protected by a mutex, so it is unsafe to use it concurrently
-from multiple threads. However, it is safe to use several client datasets from multiple threads.
+Currently, the client dataset returned is not protected by a mutex, so it is
+unsafe to use it concurrently from multiple threads. However, it is safe to use
+several client datasets from multiple threads.
 
 \section gdal_api_proxy_concurrent Concurrent use of a dataset
 
@@ -146,9 +181,6 @@ would deadlock the server.
 #define GDAL_CLIENT_SERVER_PROTOCOL_MAJOR 3
 #define GDAL_CLIENT_SERVER_PROTOCOL_MINOR 0
 
-#include <map>
-#include <vector>
-
 CPL_C_START
 int CPL_DLL GDALServerLoop(CPL_FILE_HANDLE fin, CPL_FILE_HANDLE fout);
 const char* GDALClientDatasetGetFilename(const char* pszFilename);
@@ -392,7 +424,7 @@ class EnterObject
 
 #define CLIENT_ENTER() EnterObject o(__FUNCTION__)
 #else
-#define CLIENT_ENTER() while(0)
+#define CLIENT_ENTER() while( false )
 #endif
 
 /************************************************************************/
@@ -409,7 +441,7 @@ CPL_UNUSED
     SetCurrentDirectory(pszCWD);
 #else
     if(chdir(pszCWD) != 0)
-        fprintf(stderr, "chdir(%s) failed\n", pszCWD);
+        fprintf(stderr, "chdir(%s) failed\n", pszCWD);/*ok*/
 #endif
 }
 
@@ -454,23 +486,23 @@ class GDALClientDataset: public GDALPamDataset
                                           GDALDataType eType,
                                           char ** papszOptions );
 
-                                  GDALClientDataset(GDALServerSpawnedProcess* ssp);
+                         explicit GDALClientDataset(GDALServerSpawnedProcess* ssp);
 
         static GDALClientDataset* CreateAndConnect();
 
     protected:
        virtual CPLErr IBuildOverviews( const char *, int, int *,
-                                    int, int *, GDALProgressFunc, void * );
+                                    int, int *, GDALProgressFunc, void * ) override;
        virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
                                GDALDataType eBufType,
                                int nBandCount, int *panBandMap,
                                GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg);
+                               GDALRasterIOExtraArg* psExtraArg) override;
     public:
-                            GDALClientDataset(GDALPipe* p);
-                            ~GDALClientDataset();
+                   explicit GDALClientDataset(GDALPipe* p);
+                   virtual ~GDALClientDataset();
 
         int                 Init(const char* pszFilename, GDALAccess eAccess,
                                  char** papszOpenOptions);
@@ -479,43 +511,43 @@ class GDALClientDataset: public GDALPamDataset
         int                 ProcessAsyncProgress();
         int                 SupportsInstr(InstrEnum instr) const { return abyCaps[instr / 8] & (1 << (instr % 8)); }
 
-        virtual void        FlushCache();
+        virtual void        FlushCache() override;
 
         virtual CPLErr        AddBand( GDALDataType eType,
-                                   char **papszOptions=NULL );
+                                   char **papszOptions=NULL ) override;
 
         //virtual void        SetDescription( const char * );
 
         virtual const char* GetMetadataItem( const char * pszName,
-                                             const char * pszDomain = ""  );
-        virtual char      **GetMetadata( const char * pszDomain = "" );
+                                             const char * pszDomain = ""  ) override;
+        virtual char      **GetMetadata( const char * pszDomain = "" ) override;
         virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
         virtual CPLErr      SetMetadataItem( const char * pszName,
                                              const char * pszValue,
-                                             const char * pszDomain = "" );
+                                             const char * pszDomain = "" ) override;
 
-        virtual const char* GetProjectionRef();
-        virtual CPLErr SetProjection( const char * );
+        virtual const char* GetProjectionRef() override;
+        virtual CPLErr SetProjection( const char * ) override;
 
-        virtual CPLErr GetGeoTransform( double * );
-        virtual CPLErr SetGeoTransform( double * );
+        virtual CPLErr GetGeoTransform( double * ) override;
+        virtual CPLErr SetGeoTransform( double * ) override;
 
-        virtual int    GetGCPCount();
-        virtual const char *GetGCPProjection();
-        virtual const GDAL_GCP *GetGCPs();
+        virtual int    GetGCPCount() override;
+        virtual const char *GetGCPProjection() override;
+        virtual const GDAL_GCP *GetGCPs() override;
         virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                                const char *pszGCPProjection );
+                                const char *pszGCPProjection ) override;
 
-        virtual char      **GetFileList(void);
+        virtual char      **GetFileList(void) override;
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                 int nBufXSize, int nBufYSize,
                                 GDALDataType eDT,
                                 int nBandCount, int *panBandList,
-                                char **papszOptions );
+                                char **papszOptions ) override;
 
-        virtual CPLErr          CreateMaskBand( int nFlags );
+        virtual CPLErr          CreateMaskBand( int nFlags ) override;
 
         static GDALDataset *Open( GDALOpenInfo * );
         static int          Identify( GDALOpenInfo * );
@@ -575,14 +607,14 @@ class GDALClientRasterBand : public GDALPamRasterBand
                                 GSpacing nPixelSpace, GSpacing nLineSpace );
     protected:
 
-        virtual CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, void* pImage);
-        virtual CPLErr IWriteBlock(int nBlockXOff, int nBlockYOff, void* pImage);
+        virtual CPLErr IReadBlock(int nBlockXOff, int nBlockYOff, void* pImage) override;
+        virtual CPLErr IWriteBlock(int nBlockXOff, int nBlockYOff, void* pImage) override;
         virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
                                   int nXOff, int nYOff, int nXSize, int nYSize,
                                   void * pData, int nBufXSize, int nBufYSize,
                                   GDALDataType eBufType,
                                   GSpacing nPixelSpace, GSpacing nLineSpace,
-                                  GDALRasterIOExtraArg* psExtraArg);
+                                  GDALRasterIOExtraArg* psExtraArg) override;
 
     public:
         GDALClientRasterBand(GDALPipe* p, int iSrvBand,
@@ -590,95 +622,94 @@ class GDALClientRasterBand : public GDALPamRasterBand
                              int nRasterXSize, int nRasterYSize,
                              GDALDataType eDataType, int nBlockXSize, int nBlockYSize,
                              GByte abyCaps[16]);
-        ~GDALClientRasterBand();
+        virtual ~GDALClientRasterBand();
 
         int GetSrvBand() const { return iSrvBand; }
         int SupportsInstr(InstrEnum instr) const { return abyCaps[instr / 8] & (1 << (instr % 8)); }
 
         void ClearOverviewCache() { aMapOvrBandsCurrent.clear(); }
 
-        virtual CPLErr FlushCache();
+        virtual CPLErr FlushCache() override;
 
-        virtual void        SetDescription( const char * );
+        virtual void        SetDescription( const char * ) override;
 
         virtual const char* GetMetadataItem( const char * pszName,
-                                             const char * pszDomain = ""  );
-        virtual char      **GetMetadata( const char * pszDomain = "" );
+                                             const char * pszDomain = ""  ) override;
+        virtual char      **GetMetadata( const char * pszDomain = "" ) override;
         virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
         virtual CPLErr      SetMetadataItem( const char * pszName,
                                              const char * pszValue,
-                                             const char * pszDomain = "" );
+                                             const char * pszDomain = "" ) override;
 
-        virtual GDALColorInterp GetColorInterpretation();
-        virtual CPLErr SetColorInterpretation( GDALColorInterp );
+        virtual GDALColorInterp GetColorInterpretation() override;
+        virtual CPLErr SetColorInterpretation( GDALColorInterp ) override;
 
-        virtual char **GetCategoryNames();
-        virtual double GetNoDataValue( int *pbSuccess = NULL );
-        virtual double GetMinimum( int *pbSuccess = NULL );
-        virtual double GetMaximum(int *pbSuccess = NULL );
-        virtual double GetOffset( int *pbSuccess = NULL );
-        virtual double GetScale( int *pbSuccess = NULL );
+        virtual char **GetCategoryNames() override;
+        virtual double GetNoDataValue( int *pbSuccess = NULL ) override;
+        virtual double GetMinimum( int *pbSuccess = NULL ) override;
+        virtual double GetMaximum(int *pbSuccess = NULL ) override;
+        virtual double GetOffset( int *pbSuccess = NULL ) override;
+        virtual double GetScale( int *pbSuccess = NULL ) override;
 
-        virtual GDALColorTable *GetColorTable();
-        virtual CPLErr SetColorTable( GDALColorTable * );
+        virtual GDALColorTable *GetColorTable() override;
+        virtual CPLErr SetColorTable( GDALColorTable * ) override;
 
-        virtual const char *GetUnitType();
-        virtual CPLErr SetUnitType( const char * );
+        virtual const char *GetUnitType() override;
+        virtual CPLErr SetUnitType( const char * ) override;
 
-        virtual CPLErr Fill(double dfRealValue, double dfImaginaryValue = 0);
+        virtual CPLErr Fill(double dfRealValue, double dfImaginaryValue = 0) override;
 
-        virtual CPLErr SetCategoryNames( char ** );
-        virtual CPLErr SetNoDataValue( double );
-        virtual CPLErr DeleteNoDataValue();
-        virtual CPLErr SetOffset( double );
-        virtual CPLErr SetScale( double );
+        virtual CPLErr SetCategoryNames( char ** ) override;
+        virtual CPLErr SetNoDataValue( double ) override;
+        virtual CPLErr DeleteNoDataValue() override;
+        virtual CPLErr SetOffset( double ) override;
+        virtual CPLErr SetScale( double ) override;
 
         virtual CPLErr GetStatistics( int bApproxOK, int bForce,
                                     double *pdfMin, double *pdfMax,
-                                    double *pdfMean, double *padfStdDev );
+                                    double *pdfMean, double *padfStdDev ) override;
         virtual CPLErr ComputeStatistics( int bApproxOK,
                                         double *pdfMin, double *pdfMax,
                                         double *pdfMean, double *pdfStdDev,
-                                        GDALProgressFunc, void *pProgressData );
+                                        GDALProgressFunc, void *pProgressData ) override;
         virtual CPLErr SetStatistics( double dfMin, double dfMax,
-                                      double dfMean, double dfStdDev );
-        virtual CPLErr ComputeRasterMinMax( int, double* );
+                                      double dfMean, double dfStdDev ) override;
+        virtual CPLErr ComputeRasterMinMax( int, double* ) override;
 
         virtual CPLErr GetHistogram( double dfMin, double dfMax,
                                      int nBuckets, GUIntBig *panHistogram,
                                      int bIncludeOutOfRange, int bApproxOK,
                                      GDALProgressFunc pfnProgress,
-                                     void *pProgressData );
+                                     void *pProgressData ) override;
 
         virtual CPLErr GetDefaultHistogram( double *pdfMin, double *pdfMax,
                                             int *pnBuckets, GUIntBig ** ppanHistogram,
                                             int bForce,
-                                            GDALProgressFunc, void *pProgressData);
+                                            GDALProgressFunc, void *pProgressData) override;
         virtual CPLErr SetDefaultHistogram( double dfMin, double dfMax,
-                                            int nBuckets, GUIntBig *panHistogram );
+                                            int nBuckets, GUIntBig *panHistogram ) override;
 
-        virtual int HasArbitraryOverviews();
-        virtual int GetOverviewCount();
-        virtual GDALRasterBand *GetOverview(int);
+        virtual int HasArbitraryOverviews() override;
+        virtual int GetOverviewCount() override;
+        virtual GDALRasterBand *GetOverview(int) override;
 
-        virtual GDALRasterBand *GetMaskBand();
-        virtual int             GetMaskFlags();
-        virtual CPLErr          CreateMaskBand( int nFlags );
+        virtual GDALRasterBand *GetMaskBand() override;
+        virtual int             GetMaskFlags() override;
+        virtual CPLErr          CreateMaskBand( int nFlags ) override;
 
         virtual CPLErr BuildOverviews( const char *, int, int *,
-                                       GDALProgressFunc, void * );
+                                       GDALProgressFunc, void * ) override;
 
-        virtual GDALRasterAttributeTable *GetDefaultRAT();
-        virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * );
+        virtual GDALRasterAttributeTable *GetDefaultRAT() override;
+        virtual CPLErr SetDefaultRAT( const GDALRasterAttributeTable * ) override;
 
         virtual CPLErr AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                 int nBufXSize, int nBufYSize,
-                                GDALDataType eDT, char **papszOptions );
+                                GDALDataType eDT, char **papszOptions ) override;
         /*
-        virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig );
+        virtual GDALRasterBand *GetRasterSampleOverview( GUIntBig ) override;
         */
-
 };
 
 /************************************************************************/
@@ -875,7 +906,6 @@ begin:
 #endif
         return GDALPipeReadSocketInternal(p, data, length);
     }
-
 }
 
 /************************************************************************/
@@ -983,7 +1013,6 @@ static int GDALPipeRead(GDALPipe* p, char** ppszStr)
     return TRUE;
 }
 
-
 static int GDALPipeRead(GDALPipe* p, char*** ppapszStr)
 {
     int nStrCount = 0;
@@ -1210,7 +1239,7 @@ static int GDALSkipUntilEndOfJunkMarker(GDALPipe* p)
             if( nStep == nMarkerSize )
             {
                 osJunk.resize(osJunk.size() - nMarkerSize);
-                if( osJunk.size() )
+                if( !osJunk.empty() )
                     CPLDebug("GDAL", "Got junk : %s", osJunk.c_str());
                 return TRUE;
             }
@@ -1912,7 +1941,7 @@ public:
     void* pBuffer;
     int nBufferSize;
 
-        GDALServerInstance(GDALPipe* p);
+        explicit GDALServerInstance(GDALPipe* p);
        ~GDALServerInstance();
 };
 
@@ -1930,7 +1959,6 @@ GDALServerInstance::~GDALServerInstance()
         GDALClose((GDALDatasetH)poDS);
         poDS = NULL;
     }
-
 }
 
 /************************************************************************/
@@ -2039,7 +2067,7 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
         }
 
 #ifdef DEBUG_VERBOSE
-        fprintf(stderr, "[%d] %s\n", (int)getpid(), (instr >= 0 && instr < INSTR_END) ? apszInstr[instr] : "unknown");
+        fprintf(stderr, "[%d] %s\n", (int)getpid(), (instr >= 0 && instr < INSTR_END) ? apszInstr[instr] : "unknown");/*ok*/
 #endif
 
         GDALRasterBand* poBand = NULL;
@@ -2077,7 +2105,7 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
                 break;
             if( bClientIsLSB != CPL_IS_LSB )
             {
-                fprintf(stderr, "Server does not understand client endianness.\n");
+                fprintf(stderr, "Server does not understand client endianness.\n");/*ok*/
                 break;
             }
 
@@ -2121,7 +2149,8 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
         }
         else if( instr == INSTR_SetConfigOption )
         {
-            char *pszKey = NULL, *pszValue = NULL;
+            char *pszKey = NULL;
+            char *pszValue = NULL;
             if( !GDALPipeRead(p, &pszKey) ||
                 !GDALPipeRead(p, &pszValue) )
             {
@@ -2135,11 +2164,13 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
         }
         else if( instr == INSTR_Progress )
         {
-            double dfProgress;
+            double dfProgress = 0.0;
             char* pszProgressMsg = NULL;
             if( !GDALPipeRead(p, &dfProgress) ||
                 !GDALPipeRead(p, &pszProgressMsg) )
                 break;
+            CPLAssert( pfnProgress );
+            // cppcheck-suppress nullPointer
             nRet = pfnProgress(dfProgress, pszProgressMsg, pProgressData);
             GDALEmitEndOfJunkMarker(p);
             GDALPipeWrite(p, nRet);
@@ -2216,6 +2247,7 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
             GDALPipeWrite(p, poDS != NULL);
             if( poDS != NULL )
             {
+                // cppcheck-suppress knownConditionTrueFalse
                 CPLAssert(INSTR_END < 128);
                 GByte abyCaps[16]; /* 16 * 8 = 128 */
                 memset(abyCaps, 0, sizeof(abyCaps));
@@ -2252,13 +2284,13 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
                 GDALPipeWrite(p, poDS->GetRasterYSize());
                 int nBands = poDS->GetRasterCount();
                 GDALPipeWrite(p, nBands);
-                int i;
                 int bAllSame = TRUE;
                 GDALRasterBand* poFirstBand = NULL;
-                int nFBBlockXSize = 0, nFBBlockYSize = 0;
+                int nFBBlockXSize = 0;
+                int nFBBlockYSize = 0;
 
                 /* Check if all bands are identical */
-                for(i=0;i<nBands;i++)
+                for( int i = 0; i < nBands; i++ )
                 {
                     GDALRasterBand* poOtherBand = poDS->GetRasterBand(i+1);
                     if( strlen(poOtherBand->GetDescription()) > 0 )
@@ -2289,7 +2321,7 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
 
                 /* Transmit bands */
                 GDALPipeWrite(p, bAllSame);
-                for(i=0;i<nBands;i++)
+                for( int i = 0; i < nBands; i++ )
                 {
                     GDALRasterBand* poOtherBand = poDS->GetRasterBand(i+1);
                     if( i > 0 && bAllSame )
@@ -2620,7 +2652,6 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
 
             GDALEmitEndOfJunkMarker(p);
             GDALPipeWrite(p, eErr );
-
         }
         else if( instr == INSTR_GetFileList )
         {
@@ -3254,7 +3285,10 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
             if( !GDALPipeRead(p, &bApproxOK) ||
                 !GDALPipeRead(p, &bForce) )
                 break;
-            double dfMin = 0.0, dfMax = 0.0, dfMean = 0.0, dfStdDev = 0.0;
+            double dfMin = 0.0;
+            double dfMax = 0.0;
+            double dfMean = 0.0;
+            double dfStdDev = 0.0;
             CPLErr eErr = poBand->GetStatistics(bApproxOK, bForce,
                                                 &dfMin, &dfMax, &dfMean, &dfStdDev);
             GDALEmitEndOfJunkMarker(p);
@@ -3272,7 +3306,10 @@ static int GDALServerLoopInternal(GDALServerInstance* poSrvInstance,
             int bApproxOK;
             if( !GDALPipeRead(p, &bApproxOK) )
                 break;
-            double dfMin = 0.0, dfMax = 0.0, dfMean = 0.0, dfStdDev = 0.0;
+            double dfMin = 0.0;
+            double dfMax = 0.0;
+            double dfMean = 0.0;
+            double dfStdDev = 0.0;
             CPLErr eErr = poBand->ComputeStatistics(bApproxOK,
                                                     &dfMin, &dfMax, &dfMean, &dfStdDev,
                                                     NULL, NULL);
@@ -4303,7 +4340,6 @@ CPLErr GDALClientDataset::AddBand( GDALDataType eType,
     return eRet;
 }
 
-
 /************************************************************************/
 /*                             AdviseRead()                             */
 /************************************************************************/
@@ -4390,7 +4426,6 @@ GDALClientRasterBand::GDALClientRasterBand(GDALPipe* pIn, int iSrvBandIn,
     eCachedBufType = GDT_Unknown;
     nCachedYStart = -1;
     nCachedLines = 0;
-
 }
 
 /************************************************************************/
@@ -5513,7 +5548,6 @@ CPLErr GDALClientRasterBand::DeleteNoDataValue()
     if( !SupportsInstr(INSTR_Band_DeleteNoDataValue) )
         return GDALPamRasterBand::DeleteNoDataValue();
 
-
     CLIENT_ENTER();
     if( !WriteInstr(INSTR_Band_DeleteNoDataValue) )
         return CE_Failure;
@@ -5863,7 +5897,8 @@ int GDALClientDataset::Init(const char* pszFilename, GDALAccess eAccessIn,
 
         while(true)
         {
-            char* pszKey = NULL, *pszVal = NULL;
+            char *pszKey = NULL;
+            char *pszVal = NULL;
             if( !GDALPipeRead(p, &pszKey) )
                 return FALSE;
             if( pszKey == NULL )
@@ -6132,7 +6167,7 @@ int GDALClientDataset::mCreateCopy( const char* pszFilename,
         return FALSE;
     }
 
-    if( !CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE) )
+    if( !CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false) )
     {
         if( !GDALClientDatasetQuietDelete(p, pszFilename) )
             return FALSE;
@@ -6231,7 +6266,7 @@ int GDALClientDataset::mCreate( const char * pszFilename,
         return FALSE;
     }
 
-    if( !CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE) )
+    if( !CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false) )
     {
         if( !GDALClientDatasetQuietDelete(p, pszFilename) )
             return FALSE;
@@ -6329,7 +6364,7 @@ CPLErr GDALClientDataset::Delete( const char * pszFilename )
 /************************************************************************/
 static GDALDriver* poAPIPROXYDriver = NULL;
 
-static void GDALUnloadAPIPROXYDriver(CPL_UNUSED GDALDriver* poDriver)
+static void GDALUnloadAPIPROXYDriver( GDALDriver* /* poDriver */ )
 {
     if( bRecycleChild )
     {
@@ -6360,13 +6395,14 @@ GDALDriver* GDALGetAPIPROXYDriver()
         CPL_STATIC_ASSERT(INSTR_END + 1 == sizeof(apszInstr) / sizeof(apszInstr[0]));
 #endif
         /* If asserted, change GDAL_CLIENT_SERVER_PROTOCOL_MAJOR / GDAL_CLIENT_SERVER_PROTOCOL_MINOR */
+        // cppcheck-suppress duplicateExpression
         CPL_STATIC_ASSERT(INSTR_END + 1 == 81);
 
         const char* pszConnPool = CPLGetConfigOption("GDAL_API_PROXY_CONN_POOL", "YES");
         if( atoi(pszConnPool) > 0 )
         {
             bRecycleChild = TRUE;
-            nMaxRecycled = MIN(atoi(pszConnPool), MAX_RECYCLED);
+            nMaxRecycled = std::min(atoi(pszConnPool), MAX_RECYCLED);
         }
         else if( CPLTestBool(pszConnPool) )
         {
diff --git a/gcore/gdalcolortable.cpp b/gcore/gdalcolortable.cpp
index a597edf..32e9bb1 100644
--- a/gcore/gdalcolortable.cpp
+++ b/gcore/gdalcolortable.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalcolortable.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Color table implementation.
@@ -28,9 +27,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalcolortable.cpp 33694 2016-03-10 17:54:30Z goatbar $");
+#include <cstring>
+#include <exception>
+#include <memory>
+#include <vector>
+
+#include "cpl_error.h"
+#include "gdal.h"
+
+CPL_CVSID("$Id: gdalcolortable.cpp 37103 2017-01-11 18:53:09Z goatbar $");
 
 /************************************************************************/
 /*                           GDALColorTable()                           */
@@ -64,7 +72,6 @@ GDALColorTableH CPL_STDCALL GDALCreateColorTable( GDALPaletteInterp eInterp )
     return reinterpret_cast<GDALColorTableH>( new GDALColorTable( eInterp ) );
 }
 
-
 /************************************************************************/
 /*                          ~GDALColorTable()                           */
 /************************************************************************/
@@ -119,7 +126,6 @@ const GDALColorEntry *GDALColorTable::GetColorEntry( int i ) const
 /*                         GDALGetColorEntry()                          */
 /************************************************************************/
 
-
 /**
  * \brief Fetch a color entry from table.
  *
@@ -134,7 +140,6 @@ GDALGetColorEntry( GDALColorTableH hTable, int i )
     return reinterpret_cast<GDALColorTable *>( hTable )->GetColorEntry( i );
 }
 
-
 /************************************************************************/
 /*                         GetColorEntryAsRGB()                         */
 /************************************************************************/
@@ -173,7 +178,8 @@ int GDALColorTable::GetColorEntryAsRGB( int i, GDALColorEntry *poEntry ) const
 /**
  * \brief Fetch a table entry in RGB format.
  *
- * This function is the same as the C++ method GDALColorTable::GetColorEntryAsRGB()
+ * This function is the same as the C++ method
+ * GDALColorTable::GetColorEntryAsRGB().
  */
 int CPL_STDCALL GDALGetColorEntryAsRGB( GDALColorTableH hTable, int i,
                             GDALColorEntry *poEntry )
@@ -215,8 +221,7 @@ void GDALColorTable::SetColorEntry( int i, const GDALColorEntry * poEntry )
     {
         if( i >= static_cast<int>(aoEntries.size()) )
         {
-            GDALColorEntry oBlack;
-            oBlack.c1 = oBlack.c2 = oBlack.c3 = oBlack.c4 = 0;
+            GDALColorEntry oBlack = { 0, 0, 0, 0 };
             aoEntries.resize(i+1, oBlack);
         }
 
@@ -238,7 +243,7 @@ void GDALColorTable::SetColorEntry( int i, const GDALColorEntry * poEntry )
  * This function is the same as the C++ method GDALColorTable::SetColorEntry()
  */
 void CPL_STDCALL GDALSetColorEntry( GDALColorTableH hTable, int i,
-                        const GDALColorEntry * poEntry )
+                                    const GDALColorEntry * poEntry )
 
 {
     VALIDATE_POINTER0( hTable, "GDALSetColorEntry" );
@@ -247,7 +252,6 @@ void CPL_STDCALL GDALSetColorEntry( GDALColorTableH hTable, int i,
     reinterpret_cast<GDALColorTable *>( hTable )->SetColorEntry( i, poEntry );
 }
 
-
 /************************************************************************/
 /*                               Clone()                                */
 /************************************************************************/
@@ -261,7 +265,7 @@ void CPL_STDCALL GDALSetColorEntry( GDALColorTableH hTable, int i,
 GDALColorTable *GDALColorTable::Clone() const
 
 {
-	return new GDALColorTable(*this);
+    return new GDALColorTable(*this);
 }
 
 /************************************************************************/
@@ -375,11 +379,10 @@ GDALGetPaletteInterpretation( GDALColorTableH hTable )
  */
 
 int GDALColorTable::CreateColorRamp(
-            int nStartIndex, const GDALColorEntry *psStartColor,
-            int nEndIndex, const GDALColorEntry *psEndColor )
+    int nStartIndex, const GDALColorEntry *psStartColor,
+    int nEndIndex, const GDALColorEntry *psEndColor )
 {
-    /* validate indexes */
-
+    // Validate indexes.
     if( nStartIndex < 0 || nStartIndex > 255 ||
         nEndIndex < 0 || nEndIndex > 255 ||
         nStartIndex > nEndIndex )
@@ -387,61 +390,47 @@ int GDALColorTable::CreateColorRamp(
         return -1;
     }
 
-    /* validate color entries */
-
+    // Validate color entries.
     if( psStartColor == NULL || psEndColor == NULL )
     {
         return -1;
     }
 
-    /* calculate number of colors in-between */
-
+    // Calculate number of colors in-between + 1.
     const int nColors = nEndIndex - nStartIndex;
 
-    /* set starting color */
-
+    // Set starting color.
     SetColorEntry( nStartIndex, psStartColor );
 
     if( nColors == 0 )
     {
-        return GetColorEntryCount(); /* it should not proceed */
+        return GetColorEntryCount();  // Only one color.  No ramp to create.
     }
 
-    /* set ending color */
-
+    // Set ending color.
     SetColorEntry( nEndIndex, psEndColor );
 
-    /* calculate the slope of the linear transformation */
-
-    const double dfSlope1 = ( psEndColor->c1 - psStartColor->c1 )
-        / static_cast<double>( nColors );
-    const double dfSlope2 = ( psEndColor->c2 - psStartColor->c2 )
-        / static_cast<double>( nColors );
-    const double dfSlope3 = ( psEndColor->c3 - psStartColor->c3 )
-        / static_cast<double>( nColors );
-    const double dfSlope4 = ( psEndColor->c4 - psStartColor->c4 )
-        / static_cast<double>( nColors );
-
-    /* loop through the new colors */
+    // Calculate the slope of the linear transformation.
+    const double dfColors = static_cast<double>(nColors);
+    const double dfSlope1 = (psEndColor->c1 - psStartColor->c1) / dfColors;
+    const double dfSlope2 = (psEndColor->c2 - psStartColor->c2) / dfColors;
+    const double dfSlope3 = (psEndColor->c3 - psStartColor->c3) / dfColors;
+    const double dfSlope4 = (psEndColor->c4 - psStartColor->c4) / dfColors;
 
+    // Loop through the new colors.
     GDALColorEntry sColor = *psStartColor;
 
     for( int i = 1; i < nColors; i++ )
     {
-        sColor.c1 = static_cast<short>(
-            i * dfSlope1 + static_cast<double>( psStartColor->c1 ) );
-        sColor.c2 = static_cast<short>(
-            i * dfSlope2 + static_cast<double>( psStartColor->c2 ) );
-        sColor.c3 = static_cast<short>(
-            i * dfSlope3 + static_cast<double>( psStartColor->c3 ) );
-        sColor.c4 = static_cast<short>(
-            i * dfSlope4 + static_cast<double>( psStartColor->c4 ) );
+        sColor.c1 = static_cast<short>(i * dfSlope1 + psStartColor->c1);
+        sColor.c2 = static_cast<short>(i * dfSlope2 + psStartColor->c2);
+        sColor.c3 = static_cast<short>(i * dfSlope3 + psStartColor->c3);
+        sColor.c4 = static_cast<short>(i * dfSlope4 + psStartColor->c4);
 
         SetColorEntry( nStartIndex + i, &sColor );
     }
 
-    /* return the total number of colors */
-
+    // Return the total number of colors.
     return GetColorEntryCount();
 }
 
@@ -456,10 +445,10 @@ int GDALColorTable::CreateColorRamp(
  */
 void CPL_STDCALL
 GDALCreateColorRamp( GDALColorTableH hTable,
-            int nStartIndex, const GDALColorEntry *psStartColor,
-            int nEndIndex, const GDALColorEntry *psEndColor )
+                     int nStartIndex, const GDALColorEntry *psStartColor,
+                     int nEndIndex, const GDALColorEntry *psEndColor )
 {
-    VALIDATE_POINTER0( hTable, "GDALCreateColorRamp" );
+    VALIDATE_POINTER0(hTable, "GDALCreateColorRamp");
 
     reinterpret_cast<GDALColorTable *>( hTable )->
         CreateColorRamp( nStartIndex, psStartColor,
@@ -481,7 +470,7 @@ GDALCreateColorRamp( GDALColorTableH hTable,
 int GDALColorTable::IsSame(const GDALColorTable* poOtherCT) const
 {
     return aoEntries.size() == poOtherCT->aoEntries.size() &&
-           (aoEntries.size() == 0 ||
+           (aoEntries.empty() ||
             memcmp(&aoEntries[0], &poOtherCT->aoEntries[0], aoEntries.size()
                    * sizeof(GDALColorEntry)) == 0);
 }
diff --git a/gcore/gdaldataset.cpp b/gcore/gdaldataset.cpp
index 91b04dd..7e513b5 100644
--- a/gcore/gdaldataset.cpp
+++ b/gcore/gdaldataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaldataset.cpp 35731 2016-10-14 17:07:59Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for raster file formats.
@@ -28,39 +27,63 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h"
+#include "cpl_port.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+
+#include <climits>
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <map>
+#include <new>
+#include <string>
+#include <utility>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_hash_set.h"
 #include "cpl_multiproc.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "cpl_vsi_error.h"
-#include "gdal_priv.h"
+#include "ogr_api.h"
 #include "ogr_attrind.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
 #include "ogr_featurestyle.h"
 #include "ogr_gensql.h"
+#include "ogr_geometry.h"
 #include "ogr_p.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
 #include "ograpispy.h"
+#include "ogrsf_frmts.h"
 #include "ogrunionlayer.h"
 #include "swq.h"
 
+#include "../frmts/derived/derivedlist.h"
+
 #ifdef SQLITE_ENABLED
 #include "../sqlite/ogrsqliteexecutesql.h"
 #endif
 
-#include <map>
-#include <new>
-
-CPL_CVSID("$Id: gdaldataset.cpp 35731 2016-10-14 17:07:59Z rouault $");
+CPL_CVSID("$Id: gdaldataset.cpp 37723 2017-03-16 17:07:53Z rouault $");
 
 CPL_C_START
 GDALAsyncReader *
 GDALGetDefaultAsyncReader( GDALDataset *poDS,
-                             int nXOff, int nYOff,
-                             int nXSize, int nYSize,
-                             void *pBuf,
-                             int nBufXSize, int nBufYSize,
-                             GDALDataType eBufType,
-                             int nBandCount, int* panBandMap,
-                             int nPixelSpace, int nLineSpace,
-                             int nBandSpace, char **papszOptions);
+                           int nXOff, int nYOff,
+                           int nXSize, int nYSize,
+                           void *pBuf,
+                           int nBufXSize, int nBufYSize,
+                           GDALDataType eBufType,
+                           int nBandCount, int* panBandMap,
+                           int nPixelSpace, int nLineSpace,
+                           int nBandSpace, char **papszOptions );
 CPL_C_END
 
 typedef enum
@@ -70,68 +93,90 @@ typedef enum
     RW_MUTEX_STATE_DISABLED
 } GDALAllowReadWriteMutexState;
 
+const GIntBig TOTAL_FEATURES_NOT_INIT = -2;
+const GIntBig TOTAL_FEATURES_UNKNOWN = -1;
+
 class GDALDatasetPrivate
 {
-    public:
-        CPLMutex* hMutex;
-        std::map<GIntBig, int> oMapThreadToMutexTakenCount;
+  public:
+    CPLMutex *hMutex;
+    std::map<GIntBig, int> oMapThreadToMutexTakenCount;
 #ifdef DEBUG_EXTRA
-        std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved;
+    std::map<GIntBig, int> oMapThreadToMutexTakenCountSaved;
 #endif
-        GDALAllowReadWriteMutexState eStateReadWriteMutex;
-
-        GDALDatasetPrivate() :
-            hMutex(NULL),
-            eStateReadWriteMutex(RW_MUTEX_STATE_UNKNOWN) {}
-
+    GDALAllowReadWriteMutexState eStateReadWriteMutex;
+    int nCurrentLayerIdx;
+    int nLayerCount;
+    GIntBig nFeatureReadInLayer;
+    GIntBig nFeatureReadInDataset;
+    GIntBig nTotalFeaturesInLayer;
+    GIntBig nTotalFeatures;
+    OGRLayer *poCurrentLayer;
+
+    GDALDatasetPrivate() :
+        hMutex(NULL),
+        eStateReadWriteMutex(RW_MUTEX_STATE_UNKNOWN),
+        nCurrentLayerIdx(0),
+        nLayerCount(-1),
+        nFeatureReadInLayer(0),
+        nFeatureReadInDataset(0),
+        nTotalFeaturesInLayer(TOTAL_FEATURES_NOT_INIT),
+        nTotalFeatures(TOTAL_FEATURES_NOT_INIT),
+        poCurrentLayer(NULL)
+        {}
 };
 
 typedef struct
 {
-    /* PID of the thread that mark the dataset as shared */
-    /* This may not be the actual PID, but the responsiblePID */
-    GIntBig      nPID;
-    char        *pszDescription;
-    GDALAccess   eAccess;
+    // PID of the thread that mark the dataset as shared
+    // This may not be the actual PID, but the responsiblePID.
+    GIntBig nPID;
+    char *pszDescription;
+    GDALAccess eAccess;
 
     GDALDataset *poDS;
 } SharedDatasetCtxt;
 
-/* Set of datasets opened as shared datasets (with GDALOpenShared) */
-/* The values in the set are of type SharedDatasetCtxt */
-static CPLHashSet* phSharedDatasetSet = NULL;
+// Set of datasets opened as shared datasets (with GDALOpenShared)
+// The values in the set are of type SharedDatasetCtxt.
+static CPLHashSet *phSharedDatasetSet = NULL;
 
-/* Set of all datasets created in the constructor of GDALDataset */
-/* In the case of a shared dataset, memorize the PID of the thread */
-/* that marked the dataset as shared, so that we can remove it from */
-/* the phSharedDatasetSet in the destructor of the dataset, even */
-/* if GDALClose is called from a different thread */
-static std::map<GDALDataset*, GIntBig>* poAllDatasetMap = NULL;
+// Set of all datasets created in the constructor of GDALDataset.
+// In the case of a shared dataset, memorize the PID of the thread
+// that marked the dataset as shared, so that we can remove it from
+// the phSharedDatasetSet in the destructor of the dataset, even
+// if GDALClose is called from a different thread.
+static std::map<GDALDataset *, GIntBig> *poAllDatasetMap = NULL;
 
 static CPLMutex *hDLMutex = NULL;
 
-/* Static array of all datasets. Used by GDALGetOpenDatasets */
-/* Not thread-safe. See GDALGetOpenDatasets */
-static GDALDataset** ppDatasets = NULL;
+// Static array of all datasets. Used by GDALGetOpenDatasets.
+// Not thread-safe. See GDALGetOpenDatasets.
+static GDALDataset **ppDatasets = NULL;
 
-static unsigned long GDALSharedDatasetHashFunc(const void* elt)
+static unsigned long GDALSharedDatasetHashFunc( const void *elt )
 {
-    SharedDatasetCtxt* psStruct = (SharedDatasetCtxt*) elt;
-    return (unsigned long) (CPLHashSetHashStr(psStruct->pszDescription) ^ psStruct->eAccess ^ psStruct->nPID);
+    const SharedDatasetCtxt *psStruct =
+        static_cast<const SharedDatasetCtxt *>(elt);
+    return static_cast<unsigned long>(
+        CPLHashSetHashStr(psStruct->pszDescription) ^ psStruct->eAccess ^
+        psStruct->nPID);
 }
 
-static int GDALSharedDatasetEqualFunc(const void* elt1, const void* elt2)
+static int GDALSharedDatasetEqualFunc( const void* elt1, const void* elt2 )
 {
-    SharedDatasetCtxt* psStruct1 = (SharedDatasetCtxt*) elt1;
-    SharedDatasetCtxt* psStruct2 = (SharedDatasetCtxt*) elt2;
+    const SharedDatasetCtxt *psStruct1 =
+        static_cast<const SharedDatasetCtxt *>(elt1);
+    const SharedDatasetCtxt *psStruct2 =
+        static_cast<const SharedDatasetCtxt *>(elt2);
     return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
            psStruct1->nPID == psStruct2->nPID &&
            psStruct1->eAccess == psStruct2->eAccess;
 }
 
-static void GDALSharedDatasetFreeFunc(void* elt)
+static void GDALSharedDatasetFreeFunc( void* elt )
 {
-    SharedDatasetCtxt* psStruct = (SharedDatasetCtxt*) elt;
+    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
     CPLFree(psStruct->pszDescription);
     CPLFree(psStruct);
 }
@@ -140,35 +185,34 @@ static void GDALSharedDatasetFreeFunc(void* elt)
 /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
 /************************************************************************/
 
-/* The open-shared mutex must be used by the ProxyPool too */
-CPLMutex** GDALGetphDLMutex()
-{
-    return &hDLMutex;
-}
+// The open-shared mutex must be used by the ProxyPool too.
+CPLMutex **GDALGetphDLMutex() { return &hDLMutex; }
 
-/* The current thread will act in the behalf of the thread of PID responsiblePID */
+// The current thread will act in the behalf of the thread of PID
+// responsiblePID.
 void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
 {
-    GIntBig* pResponsiblePID = (GIntBig*) CPLGetTLS(CTLS_RESPONSIBLEPID);
-    if (pResponsiblePID == NULL)
+    GIntBig *pResponsiblePID =
+        static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
+    if(pResponsiblePID == NULL)
     {
-        pResponsiblePID = (GIntBig*) CPLMalloc(sizeof(GIntBig));
+        pResponsiblePID = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
         CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
     }
     *pResponsiblePID = responsiblePID;
 }
 
-/* Get the PID of the thread that the current thread will act in the behalf of */
-/* By default : the current thread acts in the behalf of itself */
+// Get the PID of the thread that the current thread will act in the behalf of
+// By default : the current thread acts in the behalf of itself.
 GIntBig GDALGetResponsiblePIDForCurrentThread()
 {
-    GIntBig* pResponsiblePID = (GIntBig*) CPLGetTLS(CTLS_RESPONSIBLEPID);
-    if (pResponsiblePID == NULL)
+    GIntBig *pResponsiblePID =
+        static_cast<GIntBig *>(CPLGetTLS(CTLS_RESPONSIBLEPID));
+    if( pResponsiblePID == NULL )
         return CPLGetPID();
     return *pResponsiblePID;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                             GDALDataset                              */
@@ -191,20 +235,20 @@ GIntBig GDALGetResponsiblePIDForCurrentThread()
 /*                            GDALDataset()                             */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 GDALDataset::GDALDataset()
 
 {
-    Init( CPLTestBool(
-        CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") ) );
+    Init(CPLTestBool(CPLGetConfigOption("GDAL_FORCE_CACHING", "NO")));
 }
 
 GDALDataset::GDALDataset(int bForceCachedIOIn)
 
 {
-    Init(bForceCachedIOIn);
+    Init(CPL_TO_BOOL(bForceCachedIOIn));
 }
 
-void GDALDataset::Init(int bForceCachedIOIn)
+void GDALDataset::Init(bool bForceCachedIOIn)
 {
     poDriver = NULL;
     eAccess = GA_ReadOnly;
@@ -214,19 +258,20 @@ void GDALDataset::Init(int bForceCachedIOIn)
     papoBands = NULL;
     nRefCount = 1;
     nOpenFlags = 0;
-    bShared = FALSE;
-    bIsInternal = TRUE;
-    bSuppressOnClose = FALSE;
+    bShared = false;
+    bIsInternal = true;
+    bSuppressOnClose = false;
     papszOpenOptions = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Set forced caching flag.                                        */
 /* -------------------------------------------------------------------- */
-    bForceCachedIO = (GByte)bForceCachedIOIn;
+    bForceCachedIO = bForceCachedIOIn;
 
     m_poStyleTable = NULL;
-    m_hPrivateData = new (std::nothrow) GDALDatasetPrivate;
+    m_hPrivateData = new(std::nothrow) GDALDatasetPrivate;
 }
+//! @endcond
 
 /************************************************************************/
 /*                            ~GDALDataset()                            */
@@ -243,8 +288,8 @@ void GDALDataset::Init(int bForceCachedIOIn)
  * zero.
  *
  * For Windows users, it is not recommended to use the delete operator on the
- * dataset object because of known issues when allocating and freeing memory across
- * module boundaries. Calling GDALClose() is then a better option.
+ * dataset object because of known issues when allocating and freeing memory
+ * across module boundaries. Calling GDALClose() is then a better option.
  */
 
 GDALDataset::~GDALDataset()
@@ -252,16 +297,15 @@ GDALDataset::~GDALDataset()
 {
     // we don't want to report destruction of datasets that
     // were never really open or meant as internal
-    if( !bIsInternal && ( nBands != 0 || !EQUAL(GetDescription(),"") ) )
+    if( !bIsInternal && (nBands != 0 || !EQUAL(GetDescription(), "")) )
     {
         if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
-            CPLDebug( "GDAL",
-                      "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)", GetDescription(), this,
-                      (int)CPLGetPID(),
-                      (int)GDALGetResponsiblePIDForCurrentThread() );
+            CPLDebug("GDAL",
+                     "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)",
+                     GetDescription(), this, static_cast<int>(CPLGetPID()),
+                     static_cast<int>(GDALGetResponsiblePIDForCurrentThread()));
         else
-            CPLDebug( "GDAL",
-                      "GDALClose(%s, this=%p)", GetDescription(), this );
+            CPLDebug("GDAL", "GDALClose(%s, this=%p)", GetDescription(), this);
     }
 
     if( bSuppressOnClose )
@@ -272,33 +316,36 @@ GDALDataset::~GDALDataset()
 /* -------------------------------------------------------------------- */
     if( !bIsInternal )
     {
-        CPLMutexHolderD( &hDLMutex );
+        CPLMutexHolderD(&hDLMutex);
         if( poAllDatasetMap )
         {
-            std::map<GDALDataset*, GIntBig>::iterator oIter = poAllDatasetMap->find(this);
+            std::map<GDALDataset *, GIntBig>::iterator oIter =
+                poAllDatasetMap->find(this);
             CPLAssert(oIter != poAllDatasetMap->end());
             GIntBig nPIDCreatorForShared = oIter->second;
             poAllDatasetMap->erase(oIter);
 
-            if (bShared && phSharedDatasetSet != NULL)
+            if( bShared && phSharedDatasetSet != NULL )
             {
-                SharedDatasetCtxt* psStruct;
                 SharedDatasetCtxt sStruct;
                 sStruct.nPID = nPIDCreatorForShared;
                 sStruct.eAccess = eAccess;
-                sStruct.pszDescription = (char*) GetDescription();
-                psStruct = (SharedDatasetCtxt*) CPLHashSetLookup(phSharedDatasetSet, &sStruct);
-                if (psStruct && psStruct->poDS == this)
+                sStruct.pszDescription = const_cast<char *>(GetDescription());
+                SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
+                    CPLHashSetLookup(phSharedDatasetSet, &sStruct));
+                if( psStruct && psStruct->poDS == this )
                 {
                     CPLHashSetRemove(phSharedDatasetSet, psStruct);
                 }
                 else
                 {
-                    CPLDebug("GDAL", "Should not happen. Cannot find %s, this=%p in phSharedDatasetSet", GetDescription(), this);
+                    CPLDebug("GDAL", "Should not happen. Cannot find %s, "
+                                     "this=%p in phSharedDatasetSet",
+                             GetDescription(), this);
                 }
             }
 
-            if (poAllDatasetMap->size() == 0)
+            if (poAllDatasetMap->empty())
             {
                 delete poAllDatasetMap;
                 poAllDatasetMap = NULL;
@@ -316,13 +363,13 @@ GDALDataset::~GDALDataset()
 /* -------------------------------------------------------------------- */
 /*      Destroy the raster bands if they exist.                         */
 /* -------------------------------------------------------------------- */
-    for( int i = 0; i < nBands && papoBands != NULL; i++ )
+    for( int i = 0; i < nBands && papoBands != NULL; ++i )
     {
         if( papoBands[i] != NULL )
             delete papoBands[i];
     }
 
-    CPLFree( papoBands );
+    CPLFree(papoBands);
 
     if ( m_poStyleTable )
     {
@@ -330,12 +377,13 @@ GDALDataset::~GDALDataset()
         m_poStyleTable = NULL;
     }
 
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
     if( psPrivate != NULL && psPrivate->hMutex != NULL )
-        CPLDestroyMutex( psPrivate->hMutex );
+        CPLDestroyMutex(psPrivate->hMutex);
     delete psPrivate;
 
-    CSLDestroy( papszOpenOptions );
+    CSLDestroy(papszOpenOptions);
 }
 
 /************************************************************************/
@@ -347,12 +395,12 @@ void GDALDataset::AddToDatasetOpenList()
 /* -------------------------------------------------------------------- */
 /*      Add this dataset to the open dataset list.                      */
 /* -------------------------------------------------------------------- */
-    bIsInternal = FALSE;
+    bIsInternal = false;
 
-    CPLMutexHolderD( &hDLMutex );
+    CPLMutexHolderD(&hDLMutex);
 
     if (poAllDatasetMap == NULL)
-        poAllDatasetMap = new std::map<GDALDataset*, GIntBig>;
+        poAllDatasetMap = new std::map<GDALDataset *, GIntBig>;
     (*poAllDatasetMap)[this] = -1;
 }
 
@@ -387,7 +435,7 @@ void GDALDataset::FlushCache()
 
     if( papoBands != NULL )
     {
-        for( int i = 0; i < nBands; i++ )
+        for( int i = 0; i < nBands; ++i )
         {
             if( papoBands[i] != NULL )
                 papoBands[i]->FlushCache();
@@ -395,11 +443,13 @@ void GDALDataset::FlushCache()
     }
 
     const int nLayers = GetLayerCount();
+    // cppcheck-suppress knownConditionTrueFalse
     if( nLayers > 0 )
     {
-        GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-        CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
-        for( int i = 0; i < nLayers ; i++ )
+        GDALDatasetPrivate *psPrivate =
+            static_cast<GDALDatasetPrivate *>(m_hPrivateData);
+        CPLMutexHolderD(psPrivate ? &(psPrivate->hMutex) : NULL);
+        for( int i = 0; i < nLayers; ++i )
         {
             OGRLayer *poLayer = GetLayer(i);
 
@@ -424,9 +474,9 @@ void GDALDataset::FlushCache()
 void CPL_STDCALL GDALFlushCache( GDALDatasetH hDS )
 
 {
-    VALIDATE_POINTER0( hDS, "GDALFlushCache" );
+    VALIDATE_POINTER0(hDS, "GDALFlushCache");
 
-    ((GDALDataset *) hDS)->FlushCache();
+    static_cast<GDALDataset *>(hDS)->FlushCache();
 }
 
 /************************************************************************/
@@ -440,28 +490,30 @@ void CPL_STDCALL GDALFlushCache( GDALDatasetH hDS )
 /*      all bands before proceeding to the next block.                  */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 void GDALDataset::BlockBasedFlushCache()
 
 {
-    GDALRasterBand *poBand1 = GetRasterBand( 1 );
+    GDALRasterBand *poBand1 = GetRasterBand(1);
     if( poBand1 == NULL )
     {
         GDALDataset::FlushCache();
         return;
     }
 
-    int  nBlockXSize, nBlockYSize;
-    poBand1->GetBlockSize( &nBlockXSize, &nBlockYSize );
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
+    poBand1->GetBlockSize(&nBlockXSize, &nBlockYSize);
 
 /* -------------------------------------------------------------------- */
 /*      Verify that all bands match.                                    */
 /* -------------------------------------------------------------------- */
-    for( int iBand = 1; iBand < nBands; iBand++ )
+    for( int iBand = 1; iBand < nBands; ++iBand )
     {
-        GDALRasterBand *poBand = GetRasterBand( iBand+1 );
+        GDALRasterBand *poBand = GetRasterBand(iBand + 1);
 
         int nThisBlockXSize, nThisBlockYSize;
-        poBand->GetBlockSize( &nThisBlockXSize, &nThisBlockYSize );
+        poBand->GetBlockSize(&nThisBlockXSize, &nThisBlockYSize);
         if( nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize )
         {
             GDALDataset::FlushCache();
@@ -472,17 +524,15 @@ void GDALDataset::BlockBasedFlushCache()
 /* -------------------------------------------------------------------- */
 /*      Now flush writable data.                                        */
 /* -------------------------------------------------------------------- */
-    for( int iY = 0; iY < poBand1->nBlocksPerColumn; iY++ )
+    for( int iY = 0; iY < poBand1->nBlocksPerColumn; ++iY )
     {
-        for( int iX = 0; iX < poBand1->nBlocksPerRow; iX++ )
+        for( int iX = 0; iX < poBand1->nBlocksPerRow; ++iX )
         {
-            for( int iBand = 0; iBand < nBands; iBand++ )
+            for( int iBand = 0; iBand < nBands; ++iBand )
             {
-                GDALRasterBand *poBand = GetRasterBand( iBand+1 );
-
-                CPLErr    eErr;
+                GDALRasterBand *poBand = GetRasterBand(iBand + 1);
 
-                eErr = poBand->FlushBlock( iX, iY );
+                const CPLErr eErr = poBand->FlushBlock(iX, iY);
 
                 if( eErr != CE_None )
                     return;
@@ -500,17 +550,19 @@ void GDALDataset::BlockBasedFlushCache()
 void GDALDataset::RasterInitialize( int nXSize, int nYSize )
 
 {
-    CPLAssert( nXSize > 0 && nYSize > 0 );
+    CPLAssert(nXSize > 0 && nYSize > 0);
 
     nRasterXSize = nXSize;
     nRasterYSize = nYSize;
 }
+//! @endcond
 
 /************************************************************************/
 /*                              AddBand()                               */
 /************************************************************************/
 
 /**
+ * \fn GDALDataset::AddBand(GDALDataType, char**)
  * \brief Add a band to a dataset.
  *
  * This method will add a new band to the dataset if the underlying format
@@ -529,14 +581,12 @@ void GDALDataset::RasterInitialize( int nXSize, int nYSize )
  * @return CE_None on success or CE_Failure on failure.
  */
 
-CPLErr GDALDataset::AddBand( GDALDataType eType, char ** papszOptions )
+CPLErr GDALDataset::AddBand( CPL_UNUSED GDALDataType eType,
+                             CPL_UNUSED char **papszOptions )
 
 {
-    (void) eType;
-    (void) papszOptions;
-
-    ReportError( CE_Failure, CPLE_NotSupported,
-              "Dataset does not support the AddBand() method." );
+    ReportError(CE_Failure, CPLE_NotSupported,
+                "Dataset does not support the AddBand() method.");
 
     return CE_Failure;
 }
@@ -552,62 +602,69 @@ CPLErr GDALDataset::AddBand( GDALDataType eType, char ** papszOptions )
  */
 
 CPLErr CPL_STDCALL GDALAddBand( GDALDatasetH hDataset,
-                    GDALDataType eType, char **papszOptions )
+                                GDALDataType eType, char **papszOptions )
 
 {
-    VALIDATE_POINTER1( hDataset, "GDALAddBand", CE_Failure );
+    VALIDATE_POINTER1(hDataset, "GDALAddBand", CE_Failure);
 
-    return ((GDALDataset *) hDataset)->AddBand( eType, papszOptions );
+    return static_cast<GDALDataset *>(hDataset)->AddBand(eType, papszOptions);
 }
 
 /************************************************************************/
 /*                              SetBand()                               */
-/*                                                                      */
-/*      Set a band in the band array, updating the band count, and      */
-/*      array size appropriately.                                       */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
+/**  Set a band in the band array, updating the band count, and array size
+ * appropriately.
+ *
+ * @param nNewBand new band number (indexing starts at 1)
+ * @param poBand band object.
+ */
+
 void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Do we need to grow the bands list?                              */
 /* -------------------------------------------------------------------- */
-    if( nBands < nNewBand || papoBands == NULL ) {
-        GDALRasterBand** papoNewBands;
+    if( nBands < nNewBand || papoBands == NULL )
+    {
+        GDALRasterBand **papoNewBands = NULL;
 
         if( papoBands == NULL )
-            papoNewBands = (GDALRasterBand **)
-                VSICalloc(sizeof(GDALRasterBand*), MAX(nNewBand,nBands));
+            papoNewBands = static_cast<GDALRasterBand **>(VSICalloc(
+                sizeof(GDALRasterBand *), std::max(nNewBand, nBands)));
         else
-            papoNewBands = (GDALRasterBand **)
-                VSIRealloc(papoBands, sizeof(GDALRasterBand*) *
-                           MAX(nNewBand,nBands));
+            papoNewBands = static_cast<GDALRasterBand **>(
+                VSIRealloc(papoBands, sizeof(GDALRasterBand *) *
+                                          std::max(nNewBand, nBands)));
         if (papoNewBands == NULL)
         {
             ReportError(CE_Failure, CPLE_OutOfMemory,
-                     "Cannot allocate band array");
+                        "Cannot allocate band array");
             return;
         }
+
         papoBands = papoNewBands;
 
-        for( int i = nBands; i < nNewBand; i++ )
+        for( int i = nBands; i < nNewBand; ++i )
             papoBands[i] = NULL;
 
-        nBands = MAX(nBands,nNewBand);
+        nBands = std::max(nBands, nNewBand);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set the band.  Resetting the band is currently not permitted.   */
 /* -------------------------------------------------------------------- */
-    if( papoBands[nNewBand-1] != NULL )
+    if( papoBands[nNewBand - 1] != NULL )
     {
         ReportError(CE_Failure, CPLE_NotSupported,
-                 "Cannot set band %d as it is already set", nNewBand);
+                    "Cannot set band %d as it is already set", nNewBand);
         return;
     }
 
-    papoBands[nNewBand-1] = poBand;
+    papoBands[nNewBand - 1] = poBand;
 
 /* -------------------------------------------------------------------- */
 /*      Set back reference information on the raster band.  Note        */
@@ -618,8 +675,9 @@ void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
     poBand->poDS = this;
     poBand->nRasterXSize = nRasterXSize;
     poBand->nRasterYSize = nRasterYSize;
-    poBand->eAccess = eAccess; /* default access to be same as dataset */
+    poBand->eAccess = eAccess;  // Default access to be same as dataset.
 }
+//! @endcond
 
 /************************************************************************/
 /*                           GetRasterXSize()                           */
@@ -635,11 +693,7 @@ void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
 
 */
 
-int GDALDataset::GetRasterXSize()
-
-{
-    return nRasterXSize;
-}
+int GDALDataset::GetRasterXSize() { return nRasterXSize; }
 
 /************************************************************************/
 /*                         GDALGetRasterXSize()                         */
@@ -654,12 +708,11 @@ int GDALDataset::GetRasterXSize()
 int CPL_STDCALL GDALGetRasterXSize( GDALDatasetH hDataset )
 
 {
-    VALIDATE_POINTER1( hDataset, "GDALGetRasterXSize", 0 );
+    VALIDATE_POINTER1(hDataset, "GDALGetRasterXSize", 0);
 
-    return ((GDALDataset *) hDataset)->GetRasterXSize();
+    return static_cast<GDALDataset *>(hDataset)->GetRasterXSize();
 }
 
-
 /************************************************************************/
 /*                           GetRasterYSize()                           */
 /************************************************************************/
@@ -674,11 +727,7 @@ int CPL_STDCALL GDALGetRasterXSize( GDALDatasetH hDataset )
 
 */
 
-int GDALDataset::GetRasterYSize()
-
-{
-    return nRasterYSize;
-}
+int GDALDataset::GetRasterYSize() { return nRasterYSize; }
 
 /************************************************************************/
 /*                         GDALGetRasterYSize()                         */
@@ -693,9 +742,9 @@ int GDALDataset::GetRasterYSize()
 int CPL_STDCALL GDALGetRasterYSize( GDALDatasetH hDataset )
 
 {
-    VALIDATE_POINTER1( hDataset, "GDALGetRasterYSize", 0 );
+    VALIDATE_POINTER1(hDataset, "GDALGetRasterYSize", 0);
 
-    return ((GDALDataset *) hDataset)->GetRasterYSize();
+    return static_cast<GDALDataset *>(hDataset)->GetRasterYSize();
 }
 
 /************************************************************************/
@@ -722,13 +771,13 @@ GDALRasterBand * GDALDataset::GetRasterBand( int nBandId )
     {
         if( nBandId < 1 || nBandId > nBands )
         {
-            ReportError( CE_Failure, CPLE_IllegalArg,
-                      "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
-                      nBandId );
+            ReportError(CE_Failure, CPLE_IllegalArg,
+                        "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
+                        nBandId);
             return NULL;
         }
-        else
-            return( papoBands[nBandId-1] );
+
+        return papoBands[nBandId - 1];
     }
     return NULL;
 }
@@ -745,9 +794,10 @@ GDALRasterBand * GDALDataset::GetRasterBand( int nBandId )
 GDALRasterBandH CPL_STDCALL GDALGetRasterBand( GDALDatasetH hDS, int nBandId )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALGetRasterBand", NULL );
+    VALIDATE_POINTER1(hDS, "GDALGetRasterBand", NULL);
 
-    return( (GDALRasterBandH) ((GDALDataset *) hDS)->GetRasterBand(nBandId) );
+    return static_cast<GDALRasterBandH>(
+        static_cast<GDALDataset *>(hDS)->GetRasterBand(nBandId));
 }
 
 /************************************************************************/
@@ -762,11 +812,7 @@ GDALRasterBandH CPL_STDCALL GDALGetRasterBand( GDALDatasetH hDS, int nBandId )
  * @return the number of raster bands.
  */
 
-int GDALDataset::GetRasterCount()
-
-{
-    return papoBands ? nBands : 0;
-}
+int GDALDataset::GetRasterCount() { return papoBands ? nBands : 0; }
 
 /************************************************************************/
 /*                         GDALGetRasterCount()                         */
@@ -781,9 +827,9 @@ int GDALDataset::GetRasterCount()
 int CPL_STDCALL GDALGetRasterCount( GDALDatasetH hDS )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALGetRasterCount", 0 );
+    VALIDATE_POINTER1(hDS, "GDALGetRasterCount", 0);
 
-    return( ((GDALDataset *) hDS)->GetRasterCount() );
+    return static_cast<GDALDataset *>(hDS)->GetRasterCount();
 }
 
 /************************************************************************/
@@ -808,11 +854,7 @@ int CPL_STDCALL GDALGetRasterCount( GDALDatasetH hDS )
  * @see http://www.gdal.org/osr_tutorial.html
  */
 
-const char *GDALDataset::GetProjectionRef()
-
-{
-    return( "" );
-}
+const char *GDALDataset::GetProjectionRef() { return (""); }
 
 /************************************************************************/
 /*                        GDALGetProjectionRef()                        */
@@ -827,9 +869,9 @@ const char *GDALDataset::GetProjectionRef()
 const char * CPL_STDCALL GDALGetProjectionRef( GDALDatasetH hDS )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALGetProjectionRef", NULL );
+    VALIDATE_POINTER1(hDS, "GDALGetProjectionRef", NULL);
 
-    return( ((GDALDataset *) hDS)->GetProjectionRef() );
+    return static_cast<GDALDataset *>(hDS)->GetProjectionRef();
 }
 
 /************************************************************************/
@@ -837,6 +879,7 @@ const char * CPL_STDCALL GDALGetProjectionRef( GDALDatasetH hDS )
 /************************************************************************/
 
 /**
+ * \fn GDALDataset::SetProjection(const char*)
  * \brief Set the projection reference string for this dataset.
  *
  * The string should be in OGC WKT or PROJ.4 format.  An error may occur
@@ -851,11 +894,11 @@ const char * CPL_STDCALL GDALGetProjectionRef( GDALDatasetH hDS )
  * @return CE_Failure if an error occurs, otherwise CE_None.
  */
 
-CPLErr GDALDataset::SetProjection( CPL_UNUSED const char * pszProjection )
+CPLErr GDALDataset::SetProjection( CPL_UNUSED const char *pszProjection )
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        ReportError( CE_Failure, CPLE_NotSupported,
-                  "Dataset does not support the SetProjection() method." );
+        ReportError(CE_Failure, CPLE_NotSupported,
+                    "Dataset does not support the SetProjection() method.");
     return CE_Failure;
 }
 
@@ -869,12 +912,13 @@ CPLErr GDALDataset::SetProjection( CPL_UNUSED const char * pszProjection )
  * @see GDALDataset::SetProjection()
  */
 
-CPLErr CPL_STDCALL GDALSetProjection( GDALDatasetH hDS, const char * pszProjection )
+CPLErr CPL_STDCALL GDALSetProjection( GDALDatasetH hDS,
+                                      const char * pszProjection )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALSetProjection", CE_Failure );
+    VALIDATE_POINTER1(hDS, "GDALSetProjection", CE_Failure);
 
-    return( ((GDALDataset *) hDS)->SetProjection(pszProjection) );
+    return static_cast<GDALDataset *>(hDS)->SetProjection(pszProjection);
 }
 
 /************************************************************************/
@@ -911,17 +955,17 @@ CPLErr CPL_STDCALL GDALSetProjection( GDALDatasetH hDS, const char * pszProjecti
 CPLErr GDALDataset::GetGeoTransform( double * padfTransform )
 
 {
-    CPLAssert( padfTransform != NULL );
+    CPLAssert(padfTransform != NULL);
 
-    padfTransform[0] = 0.0;     /* X Origin (top left corner) */
-    padfTransform[1] = 1.0;     /* X Pixel size */
+    padfTransform[0] = 0.0;  // X Origin (top left corner)
+    padfTransform[1] = 1.0;  // X Pixel size */
     padfTransform[2] = 0.0;
 
-    padfTransform[3] = 0.0;     /* Y Origin (top left corner) */
+    padfTransform[3] = 0.0;  // Y Origin (top left corner)
     padfTransform[4] = 0.0;
-    padfTransform[5] = 1.0;     /* Y Pixel Size */
+    padfTransform[5] = 1.0;  // Y Pixel Size
 
-    return( CE_Failure );
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -934,12 +978,13 @@ CPLErr GDALDataset::GetGeoTransform( double * padfTransform )
  * @see GDALDataset::GetGeoTransform()
  */
 
-CPLErr CPL_STDCALL GDALGetGeoTransform( GDALDatasetH hDS, double * padfTransform )
+CPLErr CPL_STDCALL GDALGetGeoTransform( GDALDatasetH hDS,
+                                        double * padfTransform )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALGetGeoTransform", CE_Failure );
+    VALIDATE_POINTER1(hDS, "GDALGetGeoTransform", CE_Failure);
 
-    return( ((GDALDataset *) hDS)->GetGeoTransform(padfTransform) );
+    return static_cast<GDALDataset *>(hDS)->GetGeoTransform(padfTransform);
 }
 
 /************************************************************************/
@@ -947,6 +992,7 @@ CPLErr CPL_STDCALL GDALGetGeoTransform( GDALDatasetH hDS, double * padfTransform
 /************************************************************************/
 
 /**
+ * \fn GDALDataset::SetGeoTransform(double*)
  * \brief Set the affine transformation coefficients.
  *
  * See GetGeoTransform() for details on the meaning of the padfTransform
@@ -961,14 +1007,14 @@ CPLErr CPL_STDCALL GDALGetGeoTransform( GDALDatasetH hDS, double * padfTransform
  * written.
  */
 
-CPLErr GDALDataset::SetGeoTransform( CPL_UNUSED double * padfTransform )
+CPLErr GDALDataset::SetGeoTransform( CPL_UNUSED double *padfTransform )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        ReportError( CE_Failure, CPLE_NotSupported,
-                  "SetGeoTransform() not supported for this dataset." );
+        ReportError(CE_Failure, CPLE_NotSupported,
+                    "SetGeoTransform() not supported for this dataset.");
 
-    return( CE_Failure );
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -982,12 +1028,12 @@ CPLErr GDALDataset::SetGeoTransform( CPL_UNUSED double * padfTransform )
  */
 
 CPLErr CPL_STDCALL
-GDALSetGeoTransform( GDALDatasetH hDS, double * padfTransform )
+GDALSetGeoTransform( GDALDatasetH hDS, double *padfTransform )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALSetGeoTransform", CE_Failure );
+    VALIDATE_POINTER1(hDS, "GDALSetGeoTransform", CE_Failure);
 
-    return( ((GDALDataset *) hDS)->SetGeoTransform(padfTransform) );
+    return static_cast<GDALDataset *>(hDS)->SetGeoTransform(padfTransform);
 }
 
 /************************************************************************/
@@ -995,6 +1041,7 @@ GDALSetGeoTransform( GDALDatasetH hDS, double * padfTransform )
 /************************************************************************/
 
 /**
+ * \fn GDALDataset::GetInternalHandle(const char*)
  * \brief Fetch a format specific internally meaningful handle.
  *
  * This method is the same as the C GDALGetInternalHandle() method.
@@ -1005,10 +1052,10 @@ GDALSetGeoTransform( GDALDatasetH hDS, double * padfTransform )
  * @return the desired handle value, or NULL if not recognized/supported.
  */
 
-void *GDALDataset::GetInternalHandle( CPL_UNUSED const char * pszHandleName )
+void *GDALDataset::GetInternalHandle( CPL_UNUSED const char *pszHandleName )
 
 {
-    return( NULL );
+    return NULL;
 }
 
 /************************************************************************/
@@ -1025,9 +1072,9 @@ void * CPL_STDCALL
 GDALGetInternalHandle( GDALDatasetH hDS, const char * pszRequest )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALGetInternalHandle", NULL );
+    VALIDATE_POINTER1(hDS, "GDALGetInternalHandle", NULL);
 
-    return( ((GDALDataset *) hDS)->GetInternalHandle(pszRequest) );
+    return static_cast<GDALDataset *>(hDS)->GetInternalHandle(pszRequest);
 }
 
 /************************************************************************/
@@ -1043,11 +1090,7 @@ GDALGetInternalHandle( GDALDatasetH hDS, const char * pszRequest )
  * GDALCreate().
  */
 
-GDALDriver * GDALDataset::GetDriver()
-
-{
-    return poDriver;
-}
+GDALDriver *GDALDataset::GetDriver() { return poDriver; }
 
 /************************************************************************/
 /*                        GDALGetDatasetDriver()                        */
@@ -1062,9 +1105,10 @@ GDALDriver * GDALDataset::GetDriver()
 GDALDriverH CPL_STDCALL GDALGetDatasetDriver( GDALDatasetH hDataset )
 
 {
-    VALIDATE_POINTER1( hDataset, "GDALGetDatasetDriver", NULL );
+    VALIDATE_POINTER1(hDataset, "GDALGetDatasetDriver", NULL);
 
-    return (GDALDriverH) ((GDALDataset *) hDataset)->GetDriver();
+    return static_cast<GDALDriverH>(
+        static_cast<GDALDataset *>(hDataset)->GetDriver());
 }
 
 /************************************************************************/
@@ -1081,11 +1125,7 @@ GDALDriverH CPL_STDCALL GDALGetDatasetDriver( GDALDatasetH hDataset )
  * @return the post-increment reference count.
  */
 
-int GDALDataset::Reference()
-
-{
-    return ++nRefCount;
-}
+int GDALDataset::Reference() { return ++nRefCount; }
 
 /************************************************************************/
 /*                        GDALReferenceDataset()                        */
@@ -1100,9 +1140,9 @@ int GDALDataset::Reference()
 int CPL_STDCALL GDALReferenceDataset( GDALDatasetH hDataset )
 
 {
-    VALIDATE_POINTER1( hDataset, "GDALReferenceDataset", 0 );
+    VALIDATE_POINTER1(hDataset, "GDALReferenceDataset", 0);
 
-    return ((GDALDataset *) hDataset)->Reference();
+    return static_cast<GDALDataset *>(hDataset)->Reference();
 }
 
 /************************************************************************/
@@ -1120,11 +1160,7 @@ int CPL_STDCALL GDALReferenceDataset( GDALDatasetH hDataset )
  * @return the post-decrement reference count.
  */
 
-int GDALDataset::Dereference()
-
-{
-    return --nRefCount;
-}
+int GDALDataset::Dereference() { return --nRefCount; }
 
 /************************************************************************/
 /*                       GDALDereferenceDataset()                       */
@@ -1139,28 +1175,68 @@ int GDALDataset::Dereference()
 int CPL_STDCALL GDALDereferenceDataset( GDALDatasetH hDataset )
 
 {
-    VALIDATE_POINTER1( hDataset, "GDALDereferenceDataset", 0 );
+    VALIDATE_POINTER1(hDataset, "GDALDereferenceDataset", 0);
 
-    return ((GDALDataset *) hDataset)->Dereference();
+    return static_cast<GDALDataset *>(hDataset)->Dereference();
 }
 
+
 /************************************************************************/
-/*                             GetShared()                              */
+/*                            ReleaseRef()                              */
 /************************************************************************/
 
 /**
- * \brief Returns shared flag.
+ * \brief Drop a reference to this object, and destroy if no longer referenced.
+ * @return TRUE if the object has been destroyed.
+ * @since GDAL 2.2
+ */
+
+int GDALDataset::ReleaseRef()
+
+{
+    CPLAssert( NULL != this );
+
+    if( Dereference() <= 0 )
+    {
+        nRefCount = 1;
+        delete this;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/************************************************************************/
+/*                        GDALReleaseDataset()                          */
+/************************************************************************/
+
+/**
+ * \brief Drop a reference to this object, and destroy if no longer referenced.
  *
- * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
+ * @see GDALDataset::ReleaseRef()
+ * @since GDAL 2.2
  */
 
-int GDALDataset::GetShared()
+int CPL_STDCALL GDALReleaseDataset( GDALDatasetH hDataset )
 
 {
-    return bShared;
+    VALIDATE_POINTER1(hDataset, "GDALReleaseDataset", 0);
+
+    return static_cast<GDALDataset *>(hDataset)->ReleaseRef();
 }
 
 /************************************************************************/
+/*                             GetShared()                              */
+/************************************************************************/
+
+/**
+ * \brief Returns shared flag.
+ *
+ * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
+ */
+
+int GDALDataset::GetShared() const { return bShared; }
+
+/************************************************************************/
 /*                            MarkAsShared()                            */
 /************************************************************************/
 
@@ -1171,21 +1247,23 @@ int GDALDataset::GetShared()
 void GDALDataset::MarkAsShared()
 
 {
-    CPLAssert( !bShared );
+    CPLAssert(!bShared);
 
-    bShared = TRUE;
+    bShared = true;
     if( bIsInternal )
         return;
 
     GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
-    SharedDatasetCtxt* psStruct;
 
-    /* Insert the dataset in the set of shared opened datasets */
-    CPLMutexHolderD( &hDLMutex );
+    // Insert the dataset in the set of shared opened datasets.
+    CPLMutexHolderD(&hDLMutex);
     if (phSharedDatasetSet == NULL)
-        phSharedDatasetSet = CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc, GDALSharedDatasetFreeFunc);
+        phSharedDatasetSet =
+            CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc,
+                          GDALSharedDatasetFreeFunc);
 
-    psStruct = (SharedDatasetCtxt*)CPLMalloc(sizeof(SharedDatasetCtxt));
+    SharedDatasetCtxt *psStruct =
+        static_cast<SharedDatasetCtxt *>(CPLMalloc(sizeof(SharedDatasetCtxt)));
     psStruct->poDS = this;
     psStruct->nPID = nPID;
     psStruct->eAccess = eAccess;
@@ -1194,7 +1272,8 @@ void GDALDataset::MarkAsShared()
     {
         CPLFree(psStruct);
         ReportError(CE_Failure, CPLE_AppDefined,
-                 "An existing shared dataset already has this description. This should not happen.");
+                    "An existing shared dataset already has this description. "
+                    "This should not happen.");
     }
     else
     {
@@ -1216,11 +1295,7 @@ void GDALDataset::MarkAsShared()
  * @return number of GCPs for this dataset.  Zero if there are none.
  */
 
-int GDALDataset::GetGCPCount()
-
-{
-    return 0;
-}
+int GDALDataset::GetGCPCount() { return 0; }
 
 /************************************************************************/
 /*                          GDALGetGCPCount()                           */
@@ -1235,9 +1310,9 @@ int GDALDataset::GetGCPCount()
 int CPL_STDCALL GDALGetGCPCount( GDALDatasetH hDS )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALGetGCPCount", 0 );
+    VALIDATE_POINTER1(hDS, "GDALGetGCPCount", 0);
 
-    return ((GDALDataset *) hDS)->GetGCPCount();
+    return static_cast<GDALDataset *>(hDS)->GetGCPCount();
 }
 
 /************************************************************************/
@@ -1255,11 +1330,7 @@ int CPL_STDCALL GDALGetGCPCount( GDALDatasetH hDS )
  *  It should not be altered, freed or expected to last for long.
  */
 
-const char *GDALDataset::GetGCPProjection()
-
-{
-    return "";
-}
+const char *GDALDataset::GetGCPProjection() { return ""; }
 
 /************************************************************************/
 /*                        GDALGetGCPProjection()                        */
@@ -1274,9 +1345,9 @@ const char *GDALDataset::GetGCPProjection()
 const char * CPL_STDCALL GDALGetGCPProjection( GDALDatasetH hDS )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALGetGCPProjection", NULL );
+    VALIDATE_POINTER1(hDS, "GDALGetGCPProjection", NULL);
 
-    return ((GDALDataset *) hDS)->GetGCPProjection();
+    return static_cast<GDALDataset *>(hDS)->GetGCPProjection();
 }
 
 /************************************************************************/
@@ -1292,11 +1363,7 @@ const char * CPL_STDCALL GDALGetGCPProjection( GDALDatasetH hDS )
  * and may change on the next GDAL call.
  */
 
-const GDAL_GCP *GDALDataset::GetGCPs()
-
-{
-    return NULL;
-}
+const GDAL_GCP *GDALDataset::GetGCPs() { return NULL; }
 
 /************************************************************************/
 /*                            GDALGetGCPs()                             */
@@ -1311,17 +1378,17 @@ const GDAL_GCP *GDALDataset::GetGCPs()
 const GDAL_GCP * CPL_STDCALL GDALGetGCPs( GDALDatasetH hDS )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALGetGCPs", NULL );
+    VALIDATE_POINTER1(hDS, "GDALGetGCPs", NULL);
 
-    return ((GDALDataset *) hDS)->GetGCPs();
+    return static_cast<GDALDataset *>(hDS)->GetGCPs();
 }
 
-
 /************************************************************************/
 /*                              SetGCPs()                               */
 /************************************************************************/
 
 /**
+ * \fn GDALDataset::SetGCPs(int, const GDAL_GCP*, const char*)
  * \brief Assign GCPs.
  *
  * This method is the same as the C function GDALSetGCPs().
@@ -1346,18 +1413,14 @@ const GDAL_GCP * CPL_STDCALL GDALGetGCPs( GDALDatasetH hDS )
  * not supported for this format).
  */
 
-CPLErr GDALDataset::SetGCPs( int nGCPCount,
-                             const GDAL_GCP *pasGCPList,
-                             const char * pszGCPProjection )
+CPLErr GDALDataset::SetGCPs( CPL_UNUSED int nGCPCount,
+                             CPL_UNUSED const GDAL_GCP *pasGCPList,
+                             CPL_UNUSED const char *pszGCPProjection )
 
 {
-    (void) nGCPCount;
-    (void) pasGCPList;
-    (void) pszGCPProjection;
-
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
-        ReportError( CE_Failure, CPLE_NotSupported,
-                  "Dataset does not support the SetGCPs() method." );
+        ReportError(CE_Failure, CPLE_NotSupported,
+                    "Dataset does not support the SetGCPs() method.");
 
     return CE_Failure;
 }
@@ -1373,14 +1436,14 @@ CPLErr GDALDataset::SetGCPs( int nGCPCount,
  */
 
 CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
-                    const GDAL_GCP *pasGCPList,
-                    const char *pszGCPProjection )
+                                const GDAL_GCP *pasGCPList,
+                                const char *pszGCPProjection )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALSetGCPs", CE_Failure );
+    VALIDATE_POINTER1(hDS, "GDALSetGCPs", CE_Failure);
 
-    return ((GDALDataset *) hDS)->SetGCPs( nGCPCount, pasGCPList,
-                                           pszGCPProjection );
+    return static_cast<GDALDataset *>(hDS)
+        ->SetGCPs(nGCPCount, pasGCPList, pszGCPProjection);
 }
 
 /************************************************************************/
@@ -1394,14 +1457,19 @@ CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
  * CE_Failure is returned, and CPLGetLastErrorNo() will return
  * CPLE_NotSupported.
  *
+ * Depending on the actual file format, all overviews level can be also
+ * deleted by specifying nOverviews == 0. This works at least for external
+ * overviews (.ovr), TIFF internal overviews, etc.
+ *
  * This method is the same as the C function GDALBuildOverviews().
  *
  * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE",
  * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
- * @param nOverviews number of overviews to build.
- * @param panOverviewList the list of overview decimation factors to build.
- * @param nListBands number of bands to build overviews for in panBandList.  Build
- * for all bands if this is 0.
+ * @param nOverviews number of overviews to build, or 0 to clean overviews.
+ * @param panOverviewList the list of overview decimation factors to build, or
+ *                        NULL if nOverviews == 0.
+ * @param nListBands number of bands to build overviews for in panBandList.
+ * Build for all bands if this is 0.
  * @param panBandList list of band numbers.
  * @param pfnProgress a function to call to report progress, or NULL.
  * @param pProgressData application data to pass to the progress function.
@@ -1427,15 +1495,15 @@ CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
                                     void * pProgressData )
 
 {
-    CPLErr   eErr;
-    int      *panAllBandList = NULL;
+    int *panAllBandList = NULL;
 
     if( nListBands == 0 )
     {
         nListBands = GetRasterCount();
-        panAllBandList = (int *) CPLMalloc(sizeof(int) * nListBands);
-        for( int i = 0; i < nListBands; i++ )
-            panAllBandList[i] = i+1;
+        panAllBandList =
+            static_cast<int *>(CPLMalloc(sizeof(int) * nListBands));
+        for( int i = 0; i < nListBands; ++i )
+            panAllBandList[i] = i + 1;
 
         panBandList = panAllBandList;
     }
@@ -1443,11 +1511,12 @@ CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
-    eErr = IBuildOverviews( pszResampling, nOverviews, panOverviewList,
-                            nListBands, panBandList, pfnProgress, pProgressData );
+    const CPLErr eErr =
+        IBuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
+                        panBandList, pfnProgress, pProgressData);
 
     if( panAllBandList != NULL )
-        CPLFree( panAllBandList );
+        CPLFree(panAllBandList);
 
     return eErr;
 }
@@ -1463,18 +1532,18 @@ CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
  */
 
 CPLErr CPL_STDCALL GDALBuildOverviews( GDALDatasetH hDataset,
-                           const char *pszResampling,
-                           int nOverviews, int *panOverviewList,
-                           int nListBands, int *panBandList,
-                           GDALProgressFunc pfnProgress,
-                           void * pProgressData )
+                                       const char *pszResampling,
+                                       int nOverviews, int *panOverviewList,
+                                       int nListBands, int *panBandList,
+                                       GDALProgressFunc pfnProgress,
+                                       void * pProgressData )
 
 {
-    VALIDATE_POINTER1( hDataset, "GDALBuildOverviews", CE_Failure );
+    VALIDATE_POINTER1(hDataset, "GDALBuildOverviews", CE_Failure);
 
-    return ((GDALDataset *) hDataset)->BuildOverviews(
-        pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
-        pfnProgress, pProgressData );
+    return static_cast<GDALDataset *>(hDataset)
+        ->BuildOverviews(pszResampling, nOverviews, panOverviewList, nListBands,
+                         panBandList, pfnProgress, pProgressData);
 }
 
 /************************************************************************/
@@ -1483,6 +1552,7 @@ CPLErr CPL_STDCALL GDALBuildOverviews( GDALDatasetH hDataset,
 /*      Default implementation.                                         */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
                                      int nOverviews, int *panOverviewList,
                                      int nListBands, int *panBandList,
@@ -1491,18 +1561,18 @@ CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
 
 {
     if( oOvManager.IsInitialized() )
-        return oOvManager.BuildOverviews( NULL, pszResampling,
-                                          nOverviews, panOverviewList,
-                                          nListBands, panBandList,
-                                          pfnProgress, pProgressData );
+        return oOvManager.BuildOverviews(
+            NULL, pszResampling, nOverviews, panOverviewList, nListBands,
+            panBandList, pfnProgress, pProgressData);
     else
     {
-        ReportError( CE_Failure, CPLE_NotSupported,
-                  "BuildOverviews() not supported for this dataset." );
+        ReportError(CE_Failure, CPLE_NotSupported,
+                    "BuildOverviews() not supported for this dataset.");
 
-        return( CE_Failure );
+        return CE_Failure;
     }
 }
+//! @endcond
 
 /************************************************************************/
 /*                             IRasterIO()                              */
@@ -1513,6 +1583,7 @@ CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
 /*      choose instead the BlockBasedRasterIO() implementation.         */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
@@ -1524,19 +1595,19 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
 
 {
 
-    const char* pszInterleave = NULL;
+    const char *pszInterleave = NULL;
 
-    CPLAssert( NULL != pData );
+    CPLAssert(NULL != pData);
 
     if (nXSize == nBufXSize && nYSize == nBufYSize && nBandCount > 1 &&
-        (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL &&
+        (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) !=
+            NULL &&
         EQUAL(pszInterleave, "PIXEL"))
     {
-        return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                   pData, nBufXSize, nBufYSize,
-                                   eBufType, nBandCount, panBandMap,
-                                   nPixelSpace, nLineSpace, nBandSpace,
-                                   psExtraArg );
+        return BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+                                  nBufXSize, nBufYSize, eBufType, nBandCount,
+                                  panBandMap, nPixelSpace, nLineSpace,
+                                  nBandSpace, psExtraArg);
     }
 
     if( eRWFlag == GF_Read &&
@@ -1548,23 +1619,23 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
     {
         GDALDataType eFirstBandDT = GDT_Unknown;
         int nFirstMaskFlags = 0;
-        GDALRasterBand* poFirstMaskBand = NULL;
+        GDALRasterBand *poFirstMaskBand = NULL;
         int nOKBands = 0;
-        for(int i=0;i<nBandCount;i++)
+        for( int i = 0; i < nBandCount; ++i )
         {
-            GDALRasterBand* poBand = GetRasterBand(panBandMap[i]);
+            GDALRasterBand *poBand = GetRasterBand(panBandMap[i]);
             if( (nBufXSize < nXSize || nBufYSize < nYSize) &&
                 poBand->GetOverviewCount() )
             {
-                // Could be improved to select the appropriate overview
+                // Could be improved to select the appropriate overview.
                 break;
             }
             if( poBand->GetColorTable() != NULL )
             {
                 break;
             }
-            GDALDataType eDT = poBand->GetRasterDataType();
-            if( GDALDataTypeIsComplex( eDT ) )
+            const GDALDataType eDT = poBand->GetRasterDataType();
+            if( GDALDataTypeIsComplex(eDT) )
             {
                 break;
             }
@@ -1581,14 +1652,15 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
                     break;
                 }
                 int nMaskFlags = poBand->GetMaskFlags();
-                GDALRasterBand* poMaskBand = poBand->GetMaskBand();
-                if( nFirstMaskFlags == GMF_ALL_VALID && nMaskFlags == GMF_ALL_VALID )
+                GDALRasterBand *poMaskBand = poBand->GetMaskBand();
+                if( nFirstMaskFlags == GMF_ALL_VALID &&
+                    nMaskFlags == GMF_ALL_VALID )
                 {
-                    /* ok */
+                    // Ok.
                 }
                 else if( poFirstMaskBand == poMaskBand )
                 {
-                    /* ok */
+                    // Ok.
                 }
                 else
                 {
@@ -1596,11 +1668,11 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
                 }
             }
 
-            nOKBands ++;
+            ++nOKBands;
         }
 
-        GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
-        void             *pProgressDataGlobal = psExtraArg->pProgressData;
+        GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
+        void *pProgressDataGlobal = psExtraArg->pProgressData;
 
         CPLErr eErr = CE_None;
         if( nOKBands > 0 )
@@ -1608,23 +1680,22 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
             if( nOKBands < nBandCount )
             {
                 psExtraArg->pfnProgress = GDALScaledProgress;
-                psExtraArg->pProgressData =
-                    GDALCreateScaledProgress( 0.0, (double)nOKBands / nBandCount,
-                                            pfnProgressGlobal,
-                                            pProgressDataGlobal );
+                psExtraArg->pProgressData = GDALCreateScaledProgress(
+                    0.0, static_cast<double>(nOKBands) / nBandCount,
+                    pfnProgressGlobal,
+                    pProgressDataGlobal);
                 if( psExtraArg->pProgressData == NULL )
                     psExtraArg->pfnProgress = NULL;
             }
 
-            eErr = RasterIOResampled( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                   pData, nBufXSize, nBufYSize,
-                                   eBufType, nOKBands, panBandMap,
-                                   nPixelSpace, nLineSpace, nBandSpace,
-                                   psExtraArg );
+            eErr = RasterIOResampled(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                     pData, nBufXSize, nBufYSize, eBufType,
+                                     nOKBands, panBandMap, nPixelSpace,
+                                     nLineSpace, nBandSpace, psExtraArg);
 
             if( nOKBands < nBandCount )
             {
-                GDALDestroyScaledProgress( psExtraArg->pProgressData );
+                GDALDestroyScaledProgress(psExtraArg->pProgressData);
             }
         }
         if( eErr == CE_None && nOKBands < nBandCount )
@@ -1632,21 +1703,22 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
             if( nOKBands > 0 )
             {
                 psExtraArg->pfnProgress = GDALScaledProgress;
-                psExtraArg->pProgressData =
-                    GDALCreateScaledProgress( (double)nOKBands / nBandCount, 1.0,
-                                            pfnProgressGlobal,
-                                            pProgressDataGlobal );
+                psExtraArg->pProgressData = GDALCreateScaledProgress(
+                    static_cast<double>(nOKBands) / nBandCount,
+                    1.0, pfnProgressGlobal,
+                    pProgressDataGlobal);
                 if( psExtraArg->pProgressData == NULL )
                     psExtraArg->pfnProgress = NULL;
             }
-            eErr = BandBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                   (GByte*)pData + nBandSpace * nOKBands, nBufXSize, nBufYSize,
-                                   eBufType, nBandCount - nOKBands, panBandMap + nOKBands,
-                                   nPixelSpace, nLineSpace, nBandSpace,
-                                   psExtraArg );
+            eErr = BandBasedRasterIO(
+                eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                static_cast<GByte *>(pData) + nBandSpace * nOKBands,
+                nBufXSize, nBufYSize,
+                eBufType, nBandCount - nOKBands, panBandMap + nOKBands,
+                nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
             if( nOKBands > 0 )
             {
-                GDALDestroyScaledProgress( psExtraArg->pProgressData );
+                GDALDestroyScaledProgress(psExtraArg->pProgressData);
             }
         }
 
@@ -1656,12 +1728,12 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
         return eErr;
     }
 
-    return BandBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                   pData, nBufXSize, nBufYSize,
-                                   eBufType, nBandCount, panBandMap,
-                                   nPixelSpace, nLineSpace, nBandSpace,
-                                   psExtraArg );
+    return BandBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+                             nBufXSize, nBufYSize, eBufType, nBandCount,
+                             panBandMap, nPixelSpace, nLineSpace, nBandSpace,
+                             psExtraArg);
 }
+//! @endcond
 
 /************************************************************************/
 /*                         BandBasedRasterIO()                          */
@@ -1670,6 +1742,7 @@ CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
 /*      appropriate arguments.                                          */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag,
                                int nXOff, int nYOff, int nXSize, int nYSize,
                                void * pData, int nBufXSize, int nBufYSize,
@@ -1683,15 +1756,14 @@ CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag,
     int iBandIndex;
     CPLErr eErr = CE_None;
 
-    GDALProgressFunc  pfnProgressGlobal = psExtraArg->pfnProgress;
-    void             *pProgressDataGlobal = psExtraArg->pProgressData;
+    GDALProgressFunc pfnProgressGlobal = psExtraArg->pfnProgress;
+    void *pProgressDataGlobal = psExtraArg->pProgressData;
 
     for( iBandIndex = 0;
          iBandIndex < nBandCount && eErr == CE_None;
-         iBandIndex++ )
+         ++iBandIndex )
     {
         GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
-        GByte *pabyBandData;
 
         if (poBand == NULL)
         {
@@ -1699,27 +1771,26 @@ CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag,
             break;
         }
 
-        pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
+        GByte *pabyBandData =
+            static_cast<GByte *>(pData) + iBandIndex * nBandSpace;
 
         if( nBandCount > 1 )
         {
             psExtraArg->pfnProgress = GDALScaledProgress;
-            psExtraArg->pProgressData =
-                GDALCreateScaledProgress( 1.0 * iBandIndex / nBandCount,
-                                        1.0 * (iBandIndex + 1) / nBandCount,
-                                        pfnProgressGlobal,
-                                        pProgressDataGlobal );
+            psExtraArg->pProgressData = GDALCreateScaledProgress(
+                1.0 * iBandIndex / nBandCount,
+                1.0 * (iBandIndex + 1) / nBandCount, pfnProgressGlobal,
+                pProgressDataGlobal);
             if( psExtraArg->pProgressData == NULL )
                 psExtraArg->pfnProgress = NULL;
         }
 
-        eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                  (void *) pabyBandData, nBufXSize, nBufYSize,
-                                  eBufType, nPixelSpace, nLineSpace,
-                                  psExtraArg );
+        eErr = poBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                 pabyBandData, nBufXSize, nBufYSize,
+                                 eBufType, nPixelSpace, nLineSpace, psExtraArg);
 
         if( nBandCount > 1 )
-            GDALDestroyScaledProgress( psExtraArg->pProgressData );
+            GDALDestroyScaledProgress(psExtraArg->pProgressData);
     }
 
     psExtraArg->pfnProgress = pfnProgressGlobal;
@@ -1727,11 +1798,13 @@ CPLErr GDALDataset::BandBasedRasterIO( GDALRWFlag eRWFlag,
 
     return eErr;
 }
+//! @endcond
 
 /************************************************************************/
 /*               ValidateRasterIOOrAdviseReadParameters()               */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
                                const char* pszCallingFunc,
                                int* pbStopProcessingOnCENone,
@@ -1746,13 +1819,13 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
 /* -------------------------------------------------------------------- */
     if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
     {
-        CPLDebug( "GDAL",
-                  "%s skipped for odd window or buffer size.\n"
-                  "  Window = (%d,%d)x%dx%d\n"
-                  "  Buffer = %dx%d\n",
-                  pszCallingFunc,
-                  nXOff, nYOff, nXSize, nYSize,
-                  nBufXSize, nBufYSize );
+        CPLDebug("GDAL",
+                 "%s skipped for odd window or buffer size.\n"
+                 "  Window = (%d,%d)x%dx%d\n"
+                 "  Buffer = %dx%d",
+                 pszCallingFunc,
+                 nXOff, nYOff, nXSize, nYSize,
+                 nBufXSize, nBufYSize);
 
         *pbStopProcessingOnCENone = TRUE;
         return CE_None;
@@ -1764,10 +1837,11 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
     if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
         || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
     {
-        ReportError( CE_Failure, CPLE_IllegalArg,
-                  "Access window out of range in %s.  Requested\n"
-                  "(%d,%d) of size %dx%d on raster of %dx%d.",
-                  pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
+        ReportError(CE_Failure, CPLE_IllegalArg,
+                    "Access window out of range in %s.  Requested "
+                    "(%d,%d) of size %dx%d on raster of %dx%d.",
+                    pszCallingFunc, nXOff, nYOff, nXSize, nYSize, nRasterXSize,
+                    nRasterYSize);
         eErr = CE_Failure;
     }
 
@@ -1779,28 +1853,31 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
         eErr = CE_Failure;
     }
 
-    for( int i = 0; i < nBandCount && eErr == CE_None; i++ )
+    for( int i = 0; i < nBandCount && eErr == CE_None; ++i )
     {
         int iBand = (panBandMap != NULL) ? panBandMap[i] : i + 1;
         if( iBand < 1 || iBand > GetRasterCount() )
         {
-            ReportError( CE_Failure, CPLE_IllegalArg,
-                      "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
-                      pszCallingFunc, i, iBand );
+            ReportError(
+                CE_Failure, CPLE_IllegalArg,
+                "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
+                pszCallingFunc, i, iBand);
             eErr = CE_Failure;
         }
 
         if( eErr == CE_None && GetRasterBand( iBand ) == NULL )
         {
-            ReportError( CE_Failure, CPLE_IllegalArg,
-                      "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
-                      pszCallingFunc, i, iBand );
+            ReportError(
+                CE_Failure, CPLE_IllegalArg,
+                "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
+                pszCallingFunc, i, iBand);
             eErr = CE_Failure;
         }
     }
 
     return eErr;
 }
+//! @endcond
 
 /************************************************************************/
 /*                              RasterIO()                              */
@@ -1876,11 +1953,11 @@ CPLErr GDALDataset::ValidateRasterIOOrAdviseReadParameters(
  * nLineSpace * nBufYSize implying band sequential organization
  * of the data buffer.
  *
- * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg structure with additional
- * arguments to specify resampling and progress callback, or NULL for default
- * behaviour. The GDAL_RASTERIO_RESAMPLING configuration option can also be defined
- * to override the default resampling to one of BILINEAR, CUBIC, CUBICSPLINE,
- * LANCZOS, AVERAGE or MODE.
+ * @param psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg
+ * structure with additional arguments to specify resampling and progress
+ * callback, or NULL for default behaviour. The GDAL_RASTERIO_RESAMPLING
+ * configuration option can also be defined to override the default resampling
+ * to one of BILINEAR, CUBIC, CUBICSPLINE, LANCZOS, AVERAGE or MODE.
  *
  * @return CE_Failure if the access fails, otherwise CE_None.
  */
@@ -1895,10 +1972,6 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
                               GDALRasterIOExtraArg* psExtraArg )
 
 {
-    int i = 0;
-    bool bNeedToFreeBandMap = false;
-    CPLErr eErr = CE_None;
-
     GDALRasterIOExtraArg sExtraArg;
     if( psExtraArg == NULL )
     {
@@ -1907,18 +1980,18 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
     }
     else if( psExtraArg->nVersion != RASTERIO_EXTRA_ARG_CURRENT_VERSION )
     {
-        ReportError( CE_Failure, CPLE_AppDefined,
-                     "Unhandled version of GDALRasterIOExtraArg" );
+        ReportError(CE_Failure, CPLE_AppDefined,
+                    "Unhandled version of GDALRasterIOExtraArg");
         return CE_Failure;
     }
 
-    GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize,
-                                       nBufXSize, nBufYSize);
+    GDALRasterIOExtraArgSetResampleAlg(psExtraArg, nXSize, nYSize, nBufXSize,
+                                       nBufYSize);
 
     if( NULL == pData )
     {
-        ReportError( CE_Failure, CPLE_AppDefined,
-                  "The buffer into which the data should be read is null" );
+        ReportError(CE_Failure, CPLE_AppDefined,
+                    "The buffer into which the data should be read is null");
         return CE_Failure;
     }
 
@@ -1928,17 +2001,17 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 
     if( eRWFlag != GF_Read && eRWFlag != GF_Write )
     {
-        ReportError( CE_Failure, CPLE_IllegalArg,
-                  "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
-                  eRWFlag );
+        ReportError(
+            CE_Failure, CPLE_IllegalArg,
+            "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
+            eRWFlag);
         return CE_Failure;
     }
 
     int bStopProcessing = FALSE;
-    eErr = ValidateRasterIOOrAdviseReadParameters( "RasterIO()", &bStopProcessing,
-                                                    nXOff, nYOff, nXSize, nYSize,
-                                                    nBufXSize, nBufYSize,
-                                                    nBandCount, panBandMap);
+    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
+        "RasterIO()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize, nBufXSize,
+        nBufYSize, nBandCount, panBandMap);
     if( eErr != CE_None || bStopProcessing )
         return eErr;
 
@@ -1947,7 +2020,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 /*      value assuming a packed buffer.                                 */
 /* -------------------------------------------------------------------- */
     if( nPixelSpace == 0 )
-        nPixelSpace = GDALGetDataTypeSizeBytes( eBufType );
+        nPixelSpace = GDALGetDataTypeSizeBytes(eBufType);
 
     if( nLineSpace == 0 )
     {
@@ -1959,26 +2032,30 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
         nBandSpace = nLineSpace * nBufYSize;
     }
 
+    bool bNeedToFreeBandMap = false;
     int anBandMap[] = { 1, 2, 3, 4 };
     if( panBandMap == NULL )
     {
         if( nBandCount > 4 )
         {
-            panBandMap = (int *) VSIMalloc2(sizeof(int), nBandCount);
+            panBandMap =
+                static_cast<int *>(VSIMalloc2(sizeof(int), nBandCount));
             if (panBandMap == NULL)
             {
-                ReportError( CE_Failure, CPLE_OutOfMemory,
-                          "Out of memory while allocating band map array" );
+                ReportError(CE_Failure, CPLE_OutOfMemory,
+                            "Out of memory while allocating band map array");
                 return CE_Failure;
             }
 
-            for( i = 0; i < nBandCount; i++ )
-                panBandMap[i] = i+1;
+            for( int i = 0; i < nBandCount; ++i )
+                panBandMap[i] = i + 1;
 
             bNeedToFreeBandMap = true;
         }
         else
+        {
             panBandMap = anBandMap;
+        }
     }
 
     int bCallLeaveReadWrite = EnterReadWrite(eRWFlag);
@@ -1989,12 +2066,10 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
     if( bForceCachedIO )
     {
-        eErr =
-            BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                pData, nBufXSize, nBufYSize, eBufType,
-                                nBandCount, panBandMap,
-                                nPixelSpace, nLineSpace, nBandSpace,
-                                psExtraArg );
+        eErr = BlockBasedRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+                                  nBufXSize, nBufYSize, eBufType, nBandCount,
+                                  panBandMap, nPixelSpace, nLineSpace,
+                                  nBandSpace, psExtraArg);
     }
 
 /* -------------------------------------------------------------------- */
@@ -2002,12 +2077,9 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
     else if( eErr == CE_None )
     {
-        eErr =
-            IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                       pData, nBufXSize, nBufYSize, eBufType,
-                       nBandCount, panBandMap,
-                       nPixelSpace, nLineSpace, nBandSpace,
-                       psExtraArg );
+        eErr = IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+                         nBufXSize, nBufYSize, eBufType, nBandCount, panBandMap,
+                         nPixelSpace, nLineSpace, nBandSpace, psExtraArg);
     }
 
     if( bCallLeaveReadWrite ) LeaveReadWrite();
@@ -2016,7 +2088,7 @@ CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
     if( bNeedToFreeBandMap )
-        CPLFree( panBandMap );
+        CPLFree(panBandMap);
 
     return eErr;
 }
@@ -2043,14 +2115,14 @@ GDALDatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
                      int nPixelSpace, int nLineSpace, int nBandSpace )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetRasterIO", CE_Failure );
+    VALIDATE_POINTER1(hDS, "GDALDatasetRasterIO", CE_Failure);
 
-    GDALDataset    *poDS = (GDALDataset *) hDS;
+    GDALDataset *poDS = static_cast<GDALDataset *>(hDS);
 
-    return( poDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                            pData, nBufXSize, nBufYSize, eBufType,
-                            nBandCount, panBandMap,
-                            nPixelSpace, nLineSpace, nBandSpace, NULL ) );
+    return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+                          nBufXSize, nBufYSize, eBufType, nBandCount,
+                          panBandMap, nPixelSpace, nLineSpace, nBandSpace,
+                          NULL);
 }
 
 /************************************************************************/
@@ -2064,25 +2136,22 @@ GDALDatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
  * @since GDAL 2.0
  */
 
-CPLErr CPL_STDCALL
-GDALDatasetRasterIOEx( GDALDatasetH hDS, GDALRWFlag eRWFlag,
-                       int nXOff, int nYOff, int nXSize, int nYSize,
-                       void * pData, int nBufXSize, int nBufYSize,
-                       GDALDataType eBufType,
-                       int nBandCount, int *panBandMap,
-                       GSpacing nPixelSpace, GSpacing nLineSpace,
-                       GSpacing nBandSpace,
-                       GDALRasterIOExtraArg* psExtraArg )
+CPLErr CPL_STDCALL GDALDatasetRasterIOEx(
+    GDALDatasetH hDS, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize,
+    int nYSize, void *pData, int nBufXSize, int nBufYSize,
+    GDALDataType eBufType, int nBandCount, int *panBandMap,
+    GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
+    GDALRasterIOExtraArg *psExtraArg )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetRasterIOEx", CE_Failure );
+    VALIDATE_POINTER1(hDS, "GDALDatasetRasterIOEx", CE_Failure);
 
-    GDALDataset    *poDS = (GDALDataset *) hDS;
+    GDALDataset *poDS = static_cast<GDALDataset *>(hDS);
 
-    return( poDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                            pData, nBufXSize, nBufYSize, eBufType,
-                            nBandCount, panBandMap,
-                            nPixelSpace, nLineSpace, nBandSpace, psExtraArg ) );
+    return poDS->RasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize, pData,
+                          nBufXSize, nBufYSize, eBufType, nBandCount,
+                          panBandMap, nPixelSpace, nLineSpace, nBandSpace,
+                          psExtraArg);
 }
 /************************************************************************/
 /*                          GetOpenDatasets()                           */
@@ -2105,23 +2174,22 @@ GDALDatasetRasterIOEx( GDALDatasetH hDS, GDALRWFlag eRWFlag,
 GDALDataset **GDALDataset::GetOpenDatasets( int *pnCount )
 
 {
-    CPLMutexHolderD( &hDLMutex );
+    CPLMutexHolderD(&hDLMutex);
 
-    if (poAllDatasetMap != NULL)
-    {
-        int i = 0;
-        *pnCount = static_cast<int>(poAllDatasetMap->size());
-        ppDatasets = (GDALDataset**) CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset*));
-        std::map<GDALDataset*, GIntBig>::iterator oIter = poAllDatasetMap->begin();
-        for(; oIter != poAllDatasetMap->end(); ++oIter, i++ )
-            ppDatasets[i] = oIter->first;
-        return ppDatasets;
-    }
-    else
+    if (poAllDatasetMap == NULL)
     {
         *pnCount = 0;
         return NULL;
     }
+
+    *pnCount = static_cast<int>(poAllDatasetMap->size());
+    ppDatasets = static_cast<GDALDataset **>(
+        CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset *)));
+    std::map<GDALDataset *, GIntBig>::iterator oIter =
+        poAllDatasetMap->begin();
+    for( int i = 0; oIter != poAllDatasetMap->end(); ++oIter, ++i )
+        ppDatasets[i] = oIter->first;
+    return ppDatasets;
 }
 
 /************************************************************************/
@@ -2137,19 +2205,18 @@ GDALDataset **GDALDataset::GetOpenDatasets( int *pnCount )
 void CPL_STDCALL GDALGetOpenDatasets( GDALDatasetH **ppahDSList, int *pnCount )
 
 {
-    VALIDATE_POINTER0( ppahDSList, "GDALGetOpenDatasets" );
-    VALIDATE_POINTER0( pnCount, "GDALGetOpenDatasets" );
+    VALIDATE_POINTER0(ppahDSList, "GDALGetOpenDatasets");
+    VALIDATE_POINTER0(pnCount, "GDALGetOpenDatasets");
 
-    *ppahDSList = (GDALDatasetH *) GDALDataset::GetOpenDatasets( pnCount);
+    *ppahDSList = (GDALDatasetH *)GDALDataset::GetOpenDatasets(pnCount);
 }
 
-
 /************************************************************************/
 /*                        GDALCleanOpenDatasetsList()                   */
 /************************************************************************/
 
-/* Useful when called from the child of a fork(), to avoid closing */
-/* the datasets of the parent at the child termination */
+// Useful when called from the child of a fork(), to avoid closing
+// the datasets of the parent at the child termination.
 void GDALNullifyOpenDatasetsList()
 {
     poAllDatasetMap = NULL;
@@ -2170,9 +2237,9 @@ void GDALNullifyOpenDatasetsList()
 
 int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS )
 {
-    VALIDATE_POINTER1( hDS, "GDALGetAccess", 0 );
+    VALIDATE_POINTER1(hDS, "GDALGetAccess", 0);
 
-    return ((GDALDataset *) hDS)->GetAccess();
+    return static_cast<GDALDataset *>(hDS)->GetAccess();
 }
 
 /************************************************************************/
@@ -2230,30 +2297,27 @@ CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
                                 char **papszOptions )
 
 {
-    int iBand;
-
 /* -------------------------------------------------------------------- */
 /*      Do some validation of parameters.                               */
 /* -------------------------------------------------------------------- */
     int bStopProcessing = FALSE;
-    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters( "AdviseRead()", &bStopProcessing,
-                                                    nXOff, nYOff, nXSize, nYSize,
-                                                    nBufXSize, nBufYSize,
-                                                    nBandCount, panBandMap);
+    CPLErr eErr = ValidateRasterIOOrAdviseReadParameters(
+        "AdviseRead()", &bStopProcessing, nXOff, nYOff, nXSize, nYSize,
+        nBufXSize, nBufYSize, nBandCount, panBandMap);
     if( eErr != CE_None || bStopProcessing )
         return eErr;
 
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    for( int iBand = 0; iBand < nBandCount; ++iBand )
     {
-        GDALRasterBand *poBand;
+        GDALRasterBand *poBand = NULL;
 
         if( panBandMap == NULL )
-            poBand = GetRasterBand(iBand+1);
+            poBand = GetRasterBand(iBand + 1);
         else
             poBand = GetRasterBand(panBandMap[iBand]);
 
-        eErr = poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize,
-                                   nBufXSize, nBufYSize, eBufType, papszOptions );
+        eErr = poBand->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize,
+                                  nBufYSize, eBufType, papszOptions);
 
         if( eErr != CE_None )
             return eErr;
@@ -2278,12 +2342,11 @@ GDALDatasetAdviseRead( GDALDatasetH hDS,
                        int nBandCount, int *panBandMap,char **papszOptions )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetAdviseRead", CE_Failure );
+    VALIDATE_POINTER1(hDS, "GDALDatasetAdviseRead", CE_Failure);
 
-    return ((GDALDataset *) hDS)->AdviseRead( nXOff, nYOff, nXSize, nYSize,
-                                              nBufXSize, nBufYSize, eDT,
-                                              nBandCount, panBandMap,
-                                              papszOptions );
+    return static_cast<GDALDataset *>(hDS)
+        ->AdviseRead(nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize, eDT,
+                     nBandCount, panBandMap, papszOptions);
 }
 
 /************************************************************************/
@@ -2312,13 +2375,13 @@ char **GDALDataset::GetFileList()
 
 {
     CPLString osMainFilename = GetDescription();
-    int bMainFileReal;
-    VSIStatBufL  sStat;
+    VSIStatBufL sStat;
 
 /* -------------------------------------------------------------------- */
 /*      Is the main filename even a real filesystem object?             */
 /* -------------------------------------------------------------------- */
-    bMainFileReal = VSIStatExL( osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG ) == 0;
+    int bMainFileReal =
+        VSIStatExL(osMainFilename, &sStat, VSI_STAT_EXISTS_FLAG) == 0;
 
 /* -------------------------------------------------------------------- */
 /*      Form new list.                                                  */
@@ -2326,20 +2389,20 @@ char **GDALDataset::GetFileList()
     char **papszList = NULL;
 
     if( bMainFileReal )
-        papszList = CSLAddString( papszList, osMainFilename );
+        papszList = CSLAddString(papszList, osMainFilename);
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a known overview file?                               */
 /* -------------------------------------------------------------------- */
-    if( oOvManager.IsInitialized() && oOvManager.poODS != NULL )
+    if(oOvManager.IsInitialized() && oOvManager.poODS != NULL)
     {
         char **papszOvrList = oOvManager.poODS->GetFileList();
-        papszList = CSLInsertStrings( papszList, -1, papszOvrList );
-        CSLDestroy( papszOvrList );
+        papszList = CSLInsertStrings(papszList, -1, papszOvrList);
+        CSLDestroy(papszOvrList);
     }
 
 /* -------------------------------------------------------------------- */
-/*      Do we have a known overview file?                               */
+/*      Do we have a known mask file?                                   */
 /* -------------------------------------------------------------------- */
     if( oOvManager.HaveMaskFile() )
     {
@@ -2349,43 +2412,9 @@ char **GDALDataset::GetFileList()
         {
             if( CSLFindString( papszList, *papszIter ) < 0 )
                 papszList = CSLAddString( papszList, *papszIter );
-            papszIter ++;
-        }
-        CSLDestroy( papszMskList );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Do we have a world file?                                        */
-/* -------------------------------------------------------------------- */
-    if( bMainFileReal &&
-        !GDALCanFileAcceptSidecarFile(osMainFilename) )
-    {
-        const char* pszExtension = CPLGetExtension( osMainFilename );
-        if( strlen(pszExtension) > 2 )
-        {
-            // first + last + 'w'
-            char szDerivedExtension[4];
-            szDerivedExtension[0] = pszExtension[0];
-            szDerivedExtension[1] = pszExtension[strlen(pszExtension)-1];
-            szDerivedExtension[2] = 'w';
-            szDerivedExtension[3] = '\0';
-            CPLString osWorldFilename = CPLResetExtension( osMainFilename, szDerivedExtension );
-
-            if (oOvManager.papszInitSiblingFiles)
-            {
-                int iSibling = CSLFindString(oOvManager.papszInitSiblingFiles,
-                                             CPLGetFilename(osWorldFilename));
-                if (iSibling >= 0)
-                {
-                    osWorldFilename.resize(strlen(osWorldFilename) -
-                                           strlen(oOvManager.papszInitSiblingFiles[iSibling]));
-                    osWorldFilename += oOvManager.papszInitSiblingFiles[iSibling];
-                    papszList = CSLAddString( papszList, osWorldFilename );
-                }
-            }
-            else if( VSIStatExL( osWorldFilename, &sStat, VSI_STAT_EXISTS_FLAG ) == 0 )
-                papszList = CSLAddString( papszList, osWorldFilename );
+            ++papszIter;
         }
+        CSLDestroy(papszMskList);
     }
 
     return papszList;
@@ -2404,9 +2433,9 @@ char **GDALDataset::GetFileList()
 char ** CPL_STDCALL GDALGetFileList( GDALDatasetH hDS )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALGetFileList", NULL );
+    VALIDATE_POINTER1(hDS, "GDALGetFileList", NULL);
 
-    return ((GDALDataset *) hDS)->GetFileList();
+    return static_cast<GDALDataset *>(hDS)->GetFileList();
 }
 
 /************************************************************************/
@@ -2423,17 +2452,23 @@ char ** CPL_STDCALL GDALGetFileList( GDALDatasetH hDS )
  * one band.
  * The mask images will be deflate compressed tiled images with the same
  * block size as the original image if possible.
+ * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
+ * level, where xx matches the band number of a band of the main dataset. The
+ * value of those items will be the one of the nFlagsIn parameter.
  *
- * Note that if you got a mask band with a previous call to GetMaskBand(),
- * it might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
+ * Note that if you got a mask band with a previous call to GetMaskBand(), it
+ * might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
  * again.
  *
  * @since GDAL 1.5.0
  *
- * @param nFlags ignored. GMF_PER_DATASET will be assumed.
+ * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
+ *                 GMF_PER_DATASET will be always set, even if not explicitly
+ *                 specified.
  * @return CE_None on success or CE_Failure on an error.
  *
  * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
+ * @see GDALRasterBand::CreateMaskBand()
  *
  */
 CPLErr GDALDataset::CreateMaskBand( int nFlagsIn )
@@ -2441,15 +2476,14 @@ CPLErr GDALDataset::CreateMaskBand( int nFlagsIn )
 {
     if( oOvManager.IsInitialized() )
     {
-        CPLErr eErr = oOvManager.CreateMaskBand( nFlagsIn, -1 );
+        CPLErr eErr = oOvManager.CreateMaskBand(nFlagsIn, -1);
         if (eErr != CE_None)
             return eErr;
 
-        /* Invalidate existing raster band masks */
-        int i;
-        for(i=0;i<nBands;i++)
+        // Invalidate existing raster band masks.
+        for( int i = 0; i < nBands; ++i )
         {
-            GDALRasterBand* poBand = papoBands[i];
+            GDALRasterBand *poBand = papoBands[i];
             if (poBand->bOwnMask)
                 delete poBand->poMask;
             poBand->bOwnMask = false;
@@ -2459,10 +2493,10 @@ CPLErr GDALDataset::CreateMaskBand( int nFlagsIn )
         return CE_None;
     }
 
-    ReportError( CE_Failure, CPLE_NotSupported,
-              "CreateMaskBand() not supported for this dataset." );
+    ReportError(CE_Failure, CPLE_NotSupported,
+                "CreateMaskBand() not supported for this dataset.");
 
-    return( CE_Failure );
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -2476,9 +2510,9 @@ CPLErr GDALDataset::CreateMaskBand( int nFlagsIn )
 CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALCreateDatasetMaskBand", CE_Failure );
+    VALIDATE_POINTER1(hDS, "GDALCreateDatasetMaskBand", CE_Failure);
 
-    return ((GDALDataset *) hDS)->CreateMaskBand( nFlags );
+    return static_cast<GDALDataset *>(hDS)->CreateMaskBand(nFlags);
 }
 
 /************************************************************************/
@@ -2497,19 +2531,20 @@ CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags )
  * <ul>
  * <li>If you open a dataset object with GA_Update access, it is not recommended
  * to open a new dataset on the same underlying file.</li>
- * <li>The returned dataset should only be accessed by one thread at a time. If you
- * want to use it from different threads, you must add all necessary code (mutexes, etc.)
- * to avoid concurrent use of the object. (Some drivers, such as GeoTIFF, maintain internal
- * state variables that are updated each time a new block is read, thus preventing concurrent
- * use.) </li>
+ * <li>The returned dataset should only be accessed by one thread at a time. If
+ * you want to use it from different threads, you must add all necessary code
+ * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
+ * as GeoTIFF, maintain internal state variables that are updated each time a
+ * new block is read, thus preventing concurrent use.) </li>
  * </ul>
  *
- * For drivers supporting the VSI virtual file API, it is possible to open
- * a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
- * (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
+ * For drivers supporting the VSI virtual file API, it is possible to open a
+ * file in a .zip archive (see VSIInstallZipFileHandler()), in a
+ * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
+ * server (see VSIInstallCurlFileHandler())
  *
- * In some situations (dealing with unverified data), the datasets can be opened in another
- * process through the \ref gdal_api_proxy mechanism.
+ * In some situations (dealing with unverified data), the datasets can be opened
+ * in another process through the \ref gdal_api_proxy mechanism.
  *
  * \sa GDALOpenShared()
  * \sa GDALOpenEx()
@@ -2530,14 +2565,13 @@ GDALDatasetH CPL_STDCALL
 GDALOpen( const char * pszFilename, GDALAccess eAccess )
 
 {
-    return GDALOpenEx( pszFilename,
-                       GDAL_OF_RASTER |
-                       (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
-                       GDAL_OF_VERBOSE_ERROR,
-                       NULL, NULL, NULL );
+    const int nUpdateFlag = eAccess == GA_Update ? GDAL_OF_UPDATE : 0;
+    const int nOpenFlags = GDAL_OF_RASTER | nUpdateFlag | GDAL_OF_VERBOSE_ERROR;
+    GDALDatasetH hDataset =
+        GDALOpenEx(pszFilename, nOpenFlags, NULL, NULL, NULL);
+    return hDataset;
 }
 
-
 /************************************************************************/
 /*                             GDALOpenEx()                             */
 /************************************************************************/
@@ -2552,28 +2586,29 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess )
  *
  * Several recommendations :
  * <ul>
- * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not recommended
- * to open a new dataset on the same underlying file.</li>
- * <li>The returned dataset should only be accessed by one thread at a time. If you
- * want to use it from different threads, you must add all necessary code (mutexes, etc.)
- * to avoid concurrent use of the object. (Some drivers, such as GeoTIFF, maintain internal
- * state variables that are updated each time a new block is read, thus preventing concurrent
- * use.) </li>
+ * <li>If you open a dataset object with GDAL_OF_UPDATE access, it is not
+ * recommended to open a new dataset on the same underlying file.</li>
+ * <li>The returned dataset should only be accessed by one thread at a time. If
+ * you want to use it from different threads, you must add all necessary code
+ * (mutexes, etc.)  to avoid concurrent use of the object. (Some drivers, such
+ * as GeoTIFF, maintain internal state variables that are updated each time a
+ * new block is read, thus preventing concurrent use.) </li>
  * </ul>
  *
- * For drivers supporting the VSI virtual file API, it is possible to open
- * a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
- * (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
+ * For drivers supporting the VSI virtual file API, it is possible to open a
+ * file in a .zip archive (see VSIInstallZipFileHandler()), in a
+ * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
+ * server (see VSIInstallCurlFileHandler())
  *
- * In some situations (dealing with unverified data), the datasets can be opened in another
- * process through the \ref gdal_api_proxy mechanism.
+ * In some situations (dealing with unverified data), the datasets can be opened
+ * in another process through the \ref gdal_api_proxy mechanism.
  *
  * In order to reduce the need for searches through the operating system
  * file system machinery, it is possible to give an optional list of files with
  * the papszSiblingFiles parameter.
  * This is the list of all files at the same level in the file system as the
  * target file, including the target file. The filenames must not include any
- * path components, are an essentially just the output of VSIReadDir() on the
+ * path components, are essentially just the output of VSIReadDir() on the
  * parent directory. If the target object does not have filesystem semantics
  * then the file list should be NULL.
  *
@@ -2582,30 +2617,31 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess )
  * information for the driver on how to access a dataset.  It should be in UTF-8
  * encoding.
  *
- * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined through
- * logical or operator.
+ * @param nOpenFlags a combination of GDAL_OF_ flags that may be combined
+ * through logical or operator.
  * <ul>
- * <li>Driver kind: GDAL_OF_RASTER for raster drivers, GDAL_OF_VECTOR for vector drivers.
- *     If none of the value is specified, both kinds are implied.</li>
+ * <li>Driver kind: GDAL_OF_RASTER for raster drivers, GDAL_OF_VECTOR for vector
+ *     drivers.  If none of the value is specified, both kinds are implied.</li>
  * <li>Access mode: GDAL_OF_READONLY (exclusive)or GDAL_OF_UPDATE.</li>
- * <li>Shared mode: GDAL_OF_SHARED. If set, it allows the sharing of
- *  GDALDataset handles for a dataset with other callers that have set GDAL_OF_SHARED.
+ * <li>Shared mode: GDAL_OF_SHARED. If set, it allows the sharing of GDALDataset
+ * handles for a dataset with other callers that have set GDAL_OF_SHARED.
  * In particular, GDALOpenEx() will first consult its list of currently
  * open and shared GDALDataset's, and if the GetDescription() name for one
  * exactly matches the pszFilename passed to GDALOpenEx() it will be
  * referenced and returned, if GDALOpenEx() is called from the same thread.</li>
- * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set, a failed attempt to open the
- * file will lead to an error message to be reported.</li>
+ * <li>Verbose error: GDAL_OF_VERBOSE_ERROR. If set, a failed attempt to open
+ * the file will lead to an error message to be reported.</li>
  * </ul>
  *
  * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
- * terminated list of strings with the driver short names that must be considered.
+ * terminated list of strings with the driver short names that must be
+ * considered.
  *
  * @param papszOpenOptions NULL, or a NULL terminated list of strings with open
  * options passed to candidate drivers. An option exists for all drivers,
  * OVERVIEW_LEVEL=level, to select a particular overview level of a dataset.
- * The level index starts at 0. The level number can be suffixed by "only" to specify that
- * only this overview level must be visible, and not sub-levels.
+ * The level index starts at 0. The level number can be suffixed by "only" to
+ * specify that only this overview level must be visible, and not sub-levels.
  * Open options are validated by default, and a warning is emitted in case the
  * option is not recognized. In some scenarios, it might be not desirable (e.g.
  * when not knowing which driver will open the file), so the special open option
@@ -2613,9 +2649,9 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess )
  * since GDAL 2.1, an option name can be preceded by the @ character to indicate
  * that it may not cause a warning if the driver doesn't declare this option.
  *
- * @param papszSiblingFiles  NULL, or a NULL terminated list of strings that are
- * filenames that are auxiliary to the main filename. If NULL is passed, a probing
- * of the file system will be done.
+ * @param papszSiblingFiles NULL, or a NULL terminated list of strings that are
+ * filenames that are auxiliary to the main filename. If NULL is passed, a
+ * probing of the file system will be done.
  *
  * @return A GDALDatasetH handle or NULL on failure.  For C++ applications
  * this handle can be cast to a GDALDataset *.
@@ -2623,13 +2659,13 @@ GDALOpen( const char * pszFilename, GDALAccess eAccess )
  * @since GDAL 2.0
  */
 
-GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
-                                 unsigned int nOpenFlags,
-                                 const char* const* papszAllowedDrivers,
-                                 const char* const* papszOpenOptions,
-                                 const char* const* papszSiblingFiles )
+GDALDatasetH CPL_STDCALL GDALOpenEx( const char *pszFilename,
+                                     unsigned int nOpenFlags,
+                                     const char *const *papszAllowedDrivers,
+                                     const char *const *papszOpenOptions,
+                                     const char *const *papszSiblingFiles )
 {
-    VALIDATE_POINTER1( pszFilename, "GDALOpen", NULL );
+    VALIDATE_POINTER1(pszFilename, "GDALOpen", NULL);
 
 /* -------------------------------------------------------------------- */
 /*      In case of shared dataset, first scan the existing list to see  */
@@ -2639,26 +2675,29 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
     {
         if( nOpenFlags & GDAL_OF_INTERNAL )
         {
-            CPLError(CE_Failure, CPLE_IllegalArg, "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
+            CPLError(CE_Failure, CPLE_IllegalArg,
+                     "GDAL_OF_SHARED and GDAL_OF_INTERNAL are exclusive");
             return NULL;
         }
 
-        CPLMutexHolderD( &hDLMutex );
+        CPLMutexHolderD(&hDLMutex);
 
         if (phSharedDatasetSet != NULL)
         {
-            GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
-            SharedDatasetCtxt* psStruct;
+            const GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
             SharedDatasetCtxt sStruct;
 
             sStruct.nPID = nThisPID;
-            sStruct.pszDescription = (char*) pszFilename;
-            sStruct.eAccess = (nOpenFlags & GDAL_OF_UPDATE) ? GA_Update : GA_ReadOnly;
-            psStruct = (SharedDatasetCtxt*) CPLHashSetLookup(phSharedDatasetSet, &sStruct);
+            sStruct.pszDescription = const_cast<char *>(pszFilename);
+            sStruct.eAccess =
+                (nOpenFlags & GDAL_OF_UPDATE) ? GA_Update : GA_ReadOnly;
+            SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(
+                CPLHashSetLookup(phSharedDatasetSet, &sStruct));
             if (psStruct == NULL && (nOpenFlags & GDAL_OF_UPDATE) == 0)
             {
                 sStruct.eAccess = GA_Update;
-                psStruct = (SharedDatasetCtxt*) CPLHashSetLookup(phSharedDatasetSet, &sStruct);
+                psStruct = static_cast<SharedDatasetCtxt *>(
+                    CPLHashSetLookup(phSharedDatasetSet, &sStruct));
             }
             if (psStruct)
             {
@@ -2668,32 +2707,32 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
         }
     }
 
-    /* If no driver kind is specified, assume all are to be probed */
+    // If no driver kind is specified, assume all are to be probed.
     if( (nOpenFlags & GDAL_OF_KIND_MASK) == 0 )
         nOpenFlags |= GDAL_OF_KIND_MASK;
 
-    int         iDriver;
     GDALDriverManager *poDM = GetGDALDriverManager();
-    //CPLLocaleC  oLocaleForcer;
+    // CPLLocaleC  oLocaleForcer;
 
     CPLErrorReset();
     VSIErrorReset();
-    CPLAssert( NULL != poDM );
+    CPLAssert(NULL != poDM);
 
-    /* Build GDALOpenInfo just now to avoid useless file stat'ing if a */
-    /* shared dataset was asked before */
-    GDALOpenInfo oOpenInfo(pszFilename,
-                           nOpenFlags,
-                           (char**) papszSiblingFiles);
+    // Build GDALOpenInfo just now to avoid useless file stat'ing if a
+    // shared dataset was asked before.
+    GDALOpenInfo oOpenInfo(pszFilename, nOpenFlags,
+                           const_cast<char **>(papszSiblingFiles));
+    oOpenInfo.papszAllowedDrivers = papszAllowedDrivers;
 
-    // Prevent infinite recursion
+    // Prevent infinite recursion.
     {
-        int* pnRecCount = (int*)CPLGetTLS( CTLS_GDALDATASET_REC_PROTECT_MAP );
+        int *pnRecCount =
+            static_cast<int *>(CPLGetTLS(CTLS_GDALDATASET_REC_PROTECT_MAP));
         if( pnRecCount == NULL )
         {
-            pnRecCount = (int*) CPLMalloc(sizeof(int));
+            pnRecCount = static_cast<int *>(CPLMalloc(sizeof(int)));
             *pnRecCount = 0;
-            CPLSetTLS( CTLS_GDALDATASET_REC_PROTECT_MAP, pnRecCount, TRUE );
+            CPLSetTLS(CTLS_GDALDATASET_REC_PROTECT_MAP, pnRecCount, TRUE);
         }
         if( *pnRecCount == 100 )
         {
@@ -2701,33 +2740,36 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
                      "GDALOpen() called with too many recursion levels");
             return NULL;
         }
-        (*pnRecCount) ++;
+        (*pnRecCount)++;
     }
 
-    // Remove leading @ if present
-    char** papszOpenOptionsCleaned = CSLDuplicate((char**)papszOpenOptions);
-    for(char** papszIter = papszOpenOptionsCleaned;
-                                        papszIter && *papszIter; ++papszIter)
+    // Remove leading @ if present.
+    char **papszOpenOptionsCleaned =
+        CSLDuplicate(const_cast<char **>(papszOpenOptions));
+    for(char **papszIter = papszOpenOptionsCleaned; papszIter && *papszIter;
+        ++papszIter)
     {
-        char* pszOption = *papszIter;
+        char *pszOption = *papszIter;
         if( pszOption[0] == '@' )
-            memmove( pszOption, pszOption+1, strlen(pszOption+1)+1 );
+            memmove(pszOption, pszOption + 1, strlen(pszOption + 1) + 1);
     }
 
     oOpenInfo.papszOpenOptions = papszOpenOptionsCleaned;
 
-    for( iDriver = -1; iDriver < poDM->GetDriverCount(); iDriver++ )
+    for( int iDriver = -1; iDriver < poDM->GetDriverCount(); ++iDriver )
     {
-        GDALDriver      *poDriver;
-        GDALDataset     *poDS;
+        GDALDriver *poDriver = NULL;
 
         if( iDriver < 0 )
+        {
             poDriver = GDALGetAPIPROXYDriver();
+        }
         else
         {
-            poDriver = poDM->GetDriver( iDriver );
+            poDriver = poDM->GetDriver(iDriver);
             if (papszAllowedDrivers != NULL &&
-                CSLFindString((char**)papszAllowedDrivers, GDALGetDriverShortName(poDriver)) == -1)
+                CSLFindString(papszAllowedDrivers,
+                              GDALGetDriverShortName(poDriver)) == -1)
                 continue;
         }
 
@@ -2740,42 +2782,47 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
             poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == NULL )
             continue;
 
-        /* Remove general OVERVIEW_LEVEL open options from list before */
-        /* passing it to the driver, if it isn't a driver specific option already */
-        char** papszTmpOpenOptions = NULL;
-        char** papszTmpOpenOptionsToValidate = NULL;
-        char** papszOptionsToValidate = (char**) papszOpenOptions;
-        if( CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") != NULL &&
+        // Remove general OVERVIEW_LEVEL open options from list before passing
+        // it to the driver, if it isn't a driver specific option already.
+        char **papszTmpOpenOptions = NULL;
+        char **papszTmpOpenOptionsToValidate = NULL;
+        char **papszOptionsToValidate = const_cast<char **>(papszOpenOptions);
+        if( CSLFetchNameValue(papszOpenOptionsCleaned, "OVERVIEW_LEVEL") !=
+               NULL &&
             (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == NULL ||
-             CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST)).ifind("OVERVIEW_LEVEL") == std::string::npos) )
+             CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
+                    .ifind("OVERVIEW_LEVEL") == std::string::npos) )
         {
             papszTmpOpenOptions = CSLDuplicate(papszOpenOptionsCleaned);
-            papszTmpOpenOptions = CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", NULL);
+            papszTmpOpenOptions =
+                CSLSetNameValue(papszTmpOpenOptions, "OVERVIEW_LEVEL", NULL);
             oOpenInfo.papszOpenOptions = papszTmpOpenOptions;
 
             papszOptionsToValidate = CSLDuplicate(papszOptionsToValidate);
-            papszOptionsToValidate = CSLSetNameValue(papszOptionsToValidate, "OVERVIEW_LEVEL", NULL);
+            papszOptionsToValidate =
+                CSLSetNameValue(papszOptionsToValidate, "OVERVIEW_LEVEL", NULL);
             papszTmpOpenOptionsToValidate = papszOptionsToValidate;
         }
 
-        int bIdentifyRes =
-            ( poDriver->pfnIdentify && poDriver->pfnIdentify(&oOpenInfo) > 0 );
+        const bool bIdentifyRes =
+            poDriver->pfnIdentify && poDriver->pfnIdentify(&oOpenInfo) > 0;
         if( bIdentifyRes )
         {
-            GDALValidateOpenOptions( poDriver, papszOptionsToValidate );
+            GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
         }
 
+        GDALDataset *poDS = NULL;
         if ( poDriver->pfnOpen != NULL )
         {
-            poDS = poDriver->pfnOpen( &oOpenInfo );
-            // If we couldn't determine for sure with Identify() (it returned -1)
-            // but that Open() managed to open the file, post validate options.
+            poDS = poDriver->pfnOpen(&oOpenInfo);
+            // If we couldn't determine for sure with Identify() (it returned
+            // -1), but Open() managed to open the file, post validate options.
             if( poDS != NULL && poDriver->pfnIdentify && !bIdentifyRes )
-                GDALValidateOpenOptions( poDriver, papszOptionsToValidate );
+                GDALValidateOpenOptions(poDriver, papszOptionsToValidate);
         }
         else if( poDriver->pfnOpenWithDriverArg != NULL )
         {
-            poDS = poDriver->pfnOpenWithDriverArg( poDriver, &oOpenInfo );
+            poDS = poDriver->pfnOpenWithDriverArg(poDriver, &oOpenInfo);
         }
         else
         {
@@ -2794,7 +2841,7 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
             poDS->nOpenFlags = nOpenFlags;
 
             if( strlen(poDS->GetDescription()) == 0 )
-                poDS->SetDescription( pszFilename );
+                poDS->SetDescription(pszFilename);
 
             if( poDS->poDriver == NULL )
                 poDS->poDriver = poDriver;
@@ -2808,28 +2855,34 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
             if( !(nOpenFlags & GDAL_OF_INTERNAL) )
             {
                 if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
-                    CPLDebug( "GDAL", "GDALOpen(%s, this=%p) succeeds as %s (pid=%d, responsiblePID=%d).",
-                              pszFilename, poDS, poDriver->GetDescription(),
-                              (int)CPLGetPID(), (int)GDALGetResponsiblePIDForCurrentThread() );
+                    CPLDebug("GDAL",
+                             "GDALOpen(%s, this=%p) succeeds as "
+                             "%s (pid=%d, responsiblePID=%d).",
+                             pszFilename, poDS, poDriver->GetDescription(),
+                             static_cast<int>(CPLGetPID()),
+                             static_cast<int>(
+                                 GDALGetResponsiblePIDForCurrentThread()));
                 else
-                    CPLDebug( "GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
-                              pszFilename, poDS, poDriver->GetDescription() );
+                    CPLDebug("GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
+                             pszFilename, poDS, poDriver->GetDescription());
 
                 poDS->AddToDatasetOpenList();
             }
 
-            int* pnRecCount = (int*)CPLGetTLS( CTLS_GDALDATASET_REC_PROTECT_MAP );
+            int *pnRecCount =
+                static_cast<int *>(CPLGetTLS(CTLS_GDALDATASET_REC_PROTECT_MAP));
             if( pnRecCount )
-                (*pnRecCount) --;
+                (*pnRecCount)--;
 
             if( nOpenFlags & GDAL_OF_SHARED )
             {
                 if (strcmp(pszFilename, poDS->GetDescription()) != 0)
                 {
                     CPLError(CE_Warning, CPLE_NotSupported,
-                            "A dataset opened by GDALOpenShared should have the same filename (%s) "
-                            "and description (%s)",
-                            pszFilename, poDS->GetDescription());
+                             "A dataset opened by GDALOpenShared should have "
+                             "the same filename (%s) "
+                             "and description (%s)",
+                             pszFilename, poDS->GetDescription());
                 }
                 else
                 {
@@ -2837,43 +2890,44 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
                 }
             }
 
-            /* Deal with generic OVERVIEW_LEVEL open option, unless it is */
-            /* driver specific */
-            if( CSLFetchNameValue((char**) papszOpenOptions, "OVERVIEW_LEVEL") != NULL &&
+            // Deal with generic OVERVIEW_LEVEL open option, unless it is
+            // driver specific.
+            if( CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL") != NULL &&
                 (poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST) == NULL ||
-                CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST)).ifind("OVERVIEW_LEVEL") == std::string::npos) )
+                CPLString(poDriver->GetMetadataItem(GDAL_DMD_OPENOPTIONLIST))
+                        .ifind("OVERVIEW_LEVEL") == std::string::npos) )
             {
-                CPLString osVal(CSLFetchNameValue((char**) papszOpenOptions, "OVERVIEW_LEVEL"));
-                int nOvrLevel = atoi(osVal);
-                int bThisLevelOnly = osVal.ifind("only") != std::string::npos;
-                GDALDataset* poOvrDS = GDALCreateOverviewDataset(poDS, nOvrLevel, bThisLevelOnly, TRUE);
-                if( poOvrDS == NULL )
+                CPLString osVal(
+                    CSLFetchNameValue(papszOpenOptions, "OVERVIEW_LEVEL"));
+                const int nOvrLevel = atoi(osVal);
+                const bool bThisLevelOnly =
+                    osVal.ifind("only") != std::string::npos;
+                GDALDataset *poOvrDS = GDALCreateOverviewDataset(
+                    poDS, nOvrLevel, bThisLevelOnly);
+                poDS->ReleaseRef();
+                poDS = poOvrDS;
+                if( poDS == NULL )
                 {
                     if( nOpenFlags & GDAL_OF_VERBOSE_ERROR )
                     {
-                        CPLError( CE_Failure, CPLE_OpenFailed,
-                                  "Cannot open overview level %d of %s",
-                                  nOvrLevel, pszFilename );
+                        CPLError(CE_Failure, CPLE_OpenFailed,
+                                 "Cannot open overview level %d of %s",
+                                 nOvrLevel, pszFilename);
                     }
-                    GDALClose( poDS );
-                    poDS = NULL;
-                }
-                else
-                {
-                    poDS = poOvrDS;
                 }
             }
             VSIErrorReset();
 
             CSLDestroy(papszOpenOptionsCleaned);
-            return (GDALDatasetH) poDS;
+            return poDS;
         }
 
-        if( CPLGetLastErrorNo() != 0 )
+        if( CPLGetLastErrorNo() != 0 && CPLGetLastErrorType() > CE_Warning)
         {
-            int* pnRecCount = (int*)CPLGetTLS( CTLS_GDALDATASET_REC_PROTECT_MAP );
+            int *pnRecCount =
+                static_cast<int *>(CPLGetTLS(CTLS_GDALDATASET_REC_PROTECT_MAP));
             if( pnRecCount )
-                (*pnRecCount) --;
+                (*pnRecCount)--;
 
             CSLDestroy(papszOpenOptionsCleaned);
             return NULL;
@@ -2886,25 +2940,30 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
     {
         // Check to see if there was a filesystem error, and report it if so.
         // If not, return a more generic error.
-        if(!VSIToCPLError(CE_Failure, CPLE_OpenFailed)) {
+        if(!VSIToCPLError(CE_Failure, CPLE_OpenFailed))
+        {
             if( oOpenInfo.bStatOK )
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                          "`%s' not recognized as a supported file format.\n",
-                          pszFilename );
-            else {
-                // If Stat failed and no VSI error was set,
-                // assume it is because the file did not exist on the filesystem.
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                          "`%s' does not exist in the file system,\n"
-                          "and is not recognized as a supported dataset name.\n",
-                          pszFilename );
+            {
+                CPLError(CE_Failure, CPLE_OpenFailed,
+                         "`%s' not recognized as a supported file format.",
+                         pszFilename);
+            }
+            else
+            {
+                // If Stat failed and no VSI error was set, assume it is because
+                // the file did not exist on the filesystem.
+                CPLError(CE_Failure, CPLE_OpenFailed,
+                         "`%s' does not exist in the file system, "
+                         "and is not recognized as a supported dataset name.",
+                         pszFilename);
             }
         }
     }
 
-    int* pnRecCount = (int*)CPLGetTLS( CTLS_GDALDATASET_REC_PROTECT_MAP );
+    int *pnRecCount =
+        static_cast<int *>(CPLGetTLS(CTLS_GDALDATASET_REC_PROTECT_MAP));
     if( pnRecCount )
-        (*pnRecCount) --;
+        (*pnRecCount)--;
 
     return NULL;
 }
@@ -2919,22 +2978,23 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
  * This function works the same as GDALOpen(), but allows the sharing of
  * GDALDataset handles for a dataset with other callers to GDALOpenShared().
  *
- * In particular, GDALOpenShared() will first consult it's list of currently
+ * In particular, GDALOpenShared() will first consult its list of currently
  * open and shared GDALDataset's, and if the GetDescription() name for one
  * exactly matches the pszFilename passed to GDALOpenShared() it will be
  * referenced and returned.
  *
- * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same pszFilename
- * from two different threads, a different GDALDataset object will be returned as
- * it is not safe to use the same dataset from different threads, unless the user
- * does explicitly use mutexes in its code.
+ * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same
+ * pszFilename from two different threads, a different GDALDataset object will
+ * be returned as it is not safe to use the same dataset from different threads,
+ * unless the user does explicitly use mutexes in its code.
  *
- * For drivers supporting the VSI virtual file API, it is possible to open
- * a file in a .zip archive (see VSIInstallZipFileHandler()), in a .tar/.tar.gz/.tgz archive
- * (see VSIInstallTarFileHandler()) or on a HTTP / FTP server (see VSIInstallCurlFileHandler())
+ * For drivers supporting the VSI virtual file API, it is possible to open a
+ * file in a .zip archive (see VSIInstallZipFileHandler()), in a
+ * .tar/.tar.gz/.tgz archive (see VSIInstallTarFileHandler()) or on a HTTP / FTP
+ * server (see VSIInstallCurlFileHandler())
  *
- * In some situations (dealing with unverified data), the datasets can be opened in another
- * process through the \ref gdal_api_proxy mechanism.
+ * In some situations (dealing with unverified data), the datasets can be opened
+ * in another process through the \ref gdal_api_proxy mechanism.
  *
  * \sa GDALOpen()
  * \sa GDALOpenEx()
@@ -2954,13 +3014,12 @@ GDALDatasetH CPL_STDCALL GDALOpenEx( const char* pszFilename,
 GDALDatasetH CPL_STDCALL
 GDALOpenShared( const char *pszFilename, GDALAccess eAccess )
 {
-    VALIDATE_POINTER1( pszFilename, "GDALOpenShared", NULL );
-    return GDALOpenEx( pszFilename,
-                       GDAL_OF_RASTER |
-                       (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
-                       GDAL_OF_SHARED |
-                       GDAL_OF_VERBOSE_ERROR,
-                       NULL, NULL, NULL );
+    VALIDATE_POINTER1(pszFilename, "GDALOpenShared", NULL);
+    return GDALOpenEx(pszFilename,
+                      GDAL_OF_RASTER |
+                          (eAccess == GA_Update ? GDAL_OF_UPDATE : 0) |
+                          GDAL_OF_SHARED | GDAL_OF_VERBOSE_ERROR,
+                      NULL, NULL, NULL);
 }
 
 /************************************************************************/
@@ -2984,7 +3043,7 @@ void CPL_STDCALL GDALClose( GDALDatasetH hDS )
     if( hDS == NULL )
         return;
 
-    GDALDataset *poDS = (GDALDataset *) hDS;
+    GDALDataset *poDS = static_cast<GDALDataset *>(hDS);
 
     if (poDS->GetShared())
     {
@@ -3010,57 +3069,45 @@ void CPL_STDCALL GDALClose( GDALDatasetH hDS )
 /*                        GDALDumpOpenDataset()                         */
 /************************************************************************/
 
-static int GDALDumpOpenSharedDatasetsForeach(void* elt, void* user_data)
+static int GDALDumpOpenSharedDatasetsForeach(void *elt, void *user_data)
 {
-    SharedDatasetCtxt* psStruct = (SharedDatasetCtxt*) elt;
-    FILE *fp = (FILE*) user_data;
-    const char *pszDriverName;
+    SharedDatasetCtxt *psStruct = static_cast<SharedDatasetCtxt *>(elt);
+    FILE *fp = static_cast<FILE *>(user_data);
     GDALDataset *poDS = psStruct->poDS;
 
-    if( poDS->GetDriver() == NULL )
-        pszDriverName = "DriverIsNULL";
-    else
-        pszDriverName = poDS->GetDriver()->GetDescription();
+    const char *pszDriverName = poDS->GetDriver() == NULL
+                                    ? "DriverIsNULL"
+                                    : poDS->GetDriver()->GetDescription();
 
     poDS->Reference();
-    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "  %d %c %-6s %7d %dx%dx%d %s\n",
-                poDS->Dereference(),
-                poDS->GetShared() ? 'S' : 'N',
-                pszDriverName,
-                (int)psStruct->nPID,
-                poDS->GetRasterXSize(),
-                poDS->GetRasterYSize(),
-                poDS->GetRasterCount(),
-                poDS->GetDescription() ));
+    CPL_IGNORE_RET_VAL(
+        VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
+                   poDS->GetShared() ? 'S' : 'N', pszDriverName,
+                   static_cast<int>(psStruct->nPID), poDS->GetRasterXSize(),
+                   poDS->GetRasterYSize(), poDS->GetRasterCount(),
+                   poDS->GetDescription()));
 
     return TRUE;
 }
 
-
-static int GDALDumpOpenDatasetsForeach(GDALDataset* poDS, FILE *fp)
+static int GDALDumpOpenDatasetsForeach(GDALDataset *poDS, FILE *fp)
 {
-    const char *pszDriverName;
 
-    /* Don't list shared datasets. They have already been listed by */
-    /* GDALDumpOpenSharedDatasetsForeach */
+    // Don't list shared datasets. They have already been listed by
+    // GDALDumpOpenSharedDatasetsForeach.
     if (poDS->GetShared())
         return TRUE;
 
-    if( poDS->GetDriver() == NULL )
-        pszDriverName = "DriverIsNULL";
-    else
-        pszDriverName = poDS->GetDriver()->GetDescription();
+    const char *pszDriverName = poDS->GetDriver() == NULL
+                                    ? "DriverIsNULL"
+                                    : poDS->GetDriver()->GetDescription();
 
     poDS->Reference();
-    CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "  %d %c %-6s %7d %dx%dx%d %s\n",
-                poDS->Dereference(),
-                poDS->GetShared() ? 'S' : 'N',
-                pszDriverName,
-                -1,
-                poDS->GetRasterXSize(),
-                poDS->GetRasterYSize(),
-                poDS->GetRasterCount(),
-                poDS->GetDescription() ));
+    CPL_IGNORE_RET_VAL(
+        VSIFPrintf(fp, "  %d %c %-6s %7d %dx%dx%d %s\n", poDS->Dereference(),
+                   poDS->GetShared() ? 'S' : 'N', pszDriverName, -1,
+                   poDS->GetRasterXSize(), poDS->GetRasterYSize(),
+                   poDS->GetRasterCount(), poDS->GetDescription()));
 
     return TRUE;
 }
@@ -3078,32 +3125,32 @@ static int GDALDumpOpenDatasetsForeach(GDALDataset* poDS, FILE *fp)
 int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
 
 {
-    VALIDATE_POINTER1( fp, "GDALDumpOpenDatasets", 0 );
+    VALIDATE_POINTER1(fp, "GDALDumpOpenDatasets", 0);
+
+    CPLMutexHolderD(&hDLMutex);
 
-    CPLMutexHolderD( &hDLMutex );
+    if (poAllDatasetMap == NULL)
+        return 0;
 
-    if (poAllDatasetMap != NULL)
+    CPL_IGNORE_RET_VAL(VSIFPrintf(fp, "Open GDAL Datasets:\n"));
+
+    for( std::map<GDALDataset *, GIntBig>::iterator oIter =
+             poAllDatasetMap->begin();
+         oIter != poAllDatasetMap->end(); ++oIter )
     {
-        CPL_IGNORE_RET_VAL(VSIFPrintf( fp, "Open GDAL Datasets:\n" ));
-        std::map<GDALDataset*, GIntBig>::iterator oIter = poAllDatasetMap->begin();
-        for(; oIter != poAllDatasetMap->end(); ++oIter )
-        {
-            GDALDumpOpenDatasetsForeach(oIter->first, fp);
-        }
-        if (phSharedDatasetSet != NULL)
-        {
-            CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach, fp);
-        }
-        return (int)poAllDatasetMap->size();
+        GDALDumpOpenDatasetsForeach(oIter->first, fp);
     }
-    else
+
+    if (phSharedDatasetSet != NULL)
     {
-        return 0;
+        CPLHashSetForeach(phSharedDatasetSet,
+                          GDALDumpOpenSharedDatasetsForeach, fp);
     }
+    return static_cast<int>(poAllDatasetMap->size());
 }
 
 /************************************************************************/
-/*                        BeginAsyncReader()                          */
+/*                        BeginAsyncReader()                            */
 /************************************************************************/
 
 /**
@@ -3180,51 +3227,117 @@ int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
  * @return The GDALAsyncReader object representing the request.
  */
 
-GDALAsyncReader*
-GDALDataset::BeginAsyncReader(int nXOff, int nYOff,
-                              int nXSize, int nYSize,
-                              void *pBuf,
-                              int nBufXSize, int nBufYSize,
-                              GDALDataType eBufType,
-                              int nBandCount, int* panBandMap,
-                              int nPixelSpace, int nLineSpace,
-                              int nBandSpace, char **papszOptions)
+GDALAsyncReader *GDALDataset::BeginAsyncReader(
+    int nXOff, int nYOff, int nXSize, int nYSize, void *pBuf, int nBufXSize,
+    int nBufYSize, GDALDataType eBufType, int nBandCount, int *panBandMap,
+    int nPixelSpace, int nLineSpace, int nBandSpace, char **papszOptions )
 {
     // See gdaldefaultasync.cpp
 
-    return
-        GDALGetDefaultAsyncReader( this,
-                                     nXOff, nYOff, nXSize, nYSize,
-                                     pBuf, nBufXSize, nBufYSize, eBufType,
-                                     nBandCount, panBandMap,
-                                     nPixelSpace, nLineSpace, nBandSpace,
-                                     papszOptions );
+    return GDALGetDefaultAsyncReader(this, nXOff, nYOff, nXSize, nYSize, pBuf,
+                                     nBufXSize, nBufYSize, eBufType, nBandCount,
+                                     panBandMap, nPixelSpace, nLineSpace,
+                                     nBandSpace, papszOptions);
 }
 
 /************************************************************************/
 /*                        GDALBeginAsyncReader()                      */
 /************************************************************************/
 
+/**
+ * \brief Sets up an asynchronous data request
+ *
+ * This method establish an asynchronous raster read request for the
+ * indicated window on the dataset into the indicated buffer.  The parameters
+ * for windowing, buffer size, buffer type and buffer organization are similar
+ * to those for GDALDataset::RasterIO(); however, this call only launches
+ * the request and filling the buffer is accomplished via calls to
+ * GetNextUpdatedRegion() on the return GDALAsyncReader session object.
+ *
+ * Once all processing for the created session is complete, or if no further
+ * refinement of the request is required, the GDALAsyncReader object should
+ * be destroyed with the GDALDataset::EndAsyncReader() method.
+ *
+ * Note that the data buffer (pData) will potentially continue to be
+ * updated as long as the session lives, but it is not deallocated when
+ * the session (GDALAsyncReader) is destroyed with EndAsyncReader().  It
+ * should be deallocated by the application at that point.
+ *
+ * Additional information on asynchronous IO in GDAL may be found at:
+ *   http://trac.osgeo.org/gdal/wiki/rfc24_progressive_data_support
+ *
+ * This method is the same as the C++ GDALDataset::BeginAsyncReader() method.
+ *
+ * @param hDS handle to the dataset object.
+ *
+ * @param nXOff The pixel offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the left side.
+ *
+ * @param nYOff The line offset to the top left corner of the region
+ * of the band to be accessed.  This would be zero to start from the top.
+ *
+ * @param nXSize The width of the region of the band to be accessed in pixels.
+ *
+ * @param nYSize The height of the region of the band to be accessed in lines.
+ *
+ * @param pBuf The buffer into which the data should be read. This buffer must
+ * contain at least nBufXSize * nBufYSize * nBandCount words of type eBufType.
+ * It is organized in left to right,top to bottom pixel order.  Spacing is
+ * controlled by the nPixelSpace, and nLineSpace parameters.
+ *
+ * @param nBufXSize the width of the buffer image into which the desired region
+ * is to be read, or from which it is to be written.
+ *
+ * @param nBufYSize the height of the buffer image into which the desired
+ * region is to be read, or from which it is to be written.
+ *
+ * @param eBufType the type of the pixel values in the pData data buffer.  The
+ * pixel values will automatically be translated to/from the GDALRasterBand
+ * data type as needed.
+ *
+ * @param nBandCount the number of bands being read or written.
+ *
+ * @param panBandMap the list of nBandCount band numbers being read/written.
+ * Note band numbers are 1 based.   This may be NULL to select the first
+ * nBandCount bands.
+ *
+ * @param nPixelSpace The byte offset from the start of one pixel value in
+ * pData to the start of the next pixel value within a scanline.  If defaulted
+ * (0) the size of the datatype eBufType is used.
+ *
+ * @param nLineSpace The byte offset from the start of one scanline in
+ * pData to the start of the next.  If defaulted the size of the datatype
+ * eBufType * nBufXSize is used.
+ *
+ * @param nBandSpace the byte offset from the start of one bands data to the
+ * start of the next.  If defaulted (zero) the value will be
+ * nLineSpace * nBufYSize implying band sequential organization
+ * of the data buffer.
+ *
+ * @param papszOptions Driver specific control options in a string list or NULL.
+ * Consult driver documentation for options supported.
+ *
+ * @return handle representing the request.
+ */
+
 GDALAsyncReaderH CPL_STDCALL
-GDALBeginAsyncReader(GDALDatasetH hDS, int xOff, int yOff,
-                       int xSize, int ySize,
-                       void *pBuf,
-                       int bufXSize, int bufYSize,
-                       GDALDataType bufType,
-                       int nBandCount, int* bandMap,
-                       int nPixelSpace, int nLineSpace,
-                       int nBandSpace,
-                       char **papszOptions)
+GDALBeginAsyncReader( GDALDatasetH hDS, int nXOff, int nYOff,
+                      int nXSize, int nYSize,
+                      void *pBuf,
+                      int nBufXSize, int nBufYSize,
+                      GDALDataType eBufType,
+                      int nBandCount, int* panBandMap,
+                      int nPixelSpace, int nLineSpace,
+                      int nBandSpace,
+                      char **papszOptions )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDataset", NULL );
-    return (GDALAsyncReaderH)((GDALDataset *) hDS)->
-        BeginAsyncReader(xOff, yOff,
-                           xSize, ySize,
-                           pBuf, bufXSize, bufYSize,
-                           bufType, nBandCount, bandMap,
-                           nPixelSpace, nLineSpace,
-                           nBandSpace, papszOptions);
+    VALIDATE_POINTER1(hDS, "GDALDataset", NULL);
+    return static_cast<GDALAsyncReaderH>(
+        static_cast<GDALDataset *>(hDS)->BeginAsyncReader(
+            nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize, nBufYSize, eBufType,
+            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
+            papszOptions));
 }
 
 /************************************************************************/
@@ -3242,19 +3355,31 @@ GDALBeginAsyncReader(GDALDatasetH hDS, int xOff, int yOff,
  * @param poARIO pointer to a GDALAsyncReader
  */
 
-void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO )
-{
-    delete poARIO;
-}
+void GDALDataset::EndAsyncReader(GDALAsyncReader *poARIO) { delete poARIO; }
 
 /************************************************************************/
 /*                        GDALEndAsyncReader()                        */
 /************************************************************************/
-void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS, GDALAsyncReaderH hAsyncReaderH)
+
+/**
+ * End asynchronous request.
+ *
+ * This method destroys an asynchronous io request and recovers all
+ * resources associated with it.
+ *
+ * This method is the same as the C++ method GDALDataset::EndAsyncReader().
+ *
+ * @param hDS handle to the dataset object.
+ * @param hAsyncReaderH handle returned by GDALBeginAsyncReader()
+ */
+
+void CPL_STDCALL GDALEndAsyncReader( GDALDatasetH hDS,
+                                     GDALAsyncReaderH hAsyncReaderH )
 {
-    VALIDATE_POINTER0( hDS, "GDALDataset" );
-    VALIDATE_POINTER0( hAsyncReaderH, "GDALAsyncReader" );
-    ((GDALDataset *) hDS) -> EndAsyncReader((GDALAsyncReader *)hAsyncReaderH);
+    VALIDATE_POINTER0(hDS, "GDALDataset");
+    VALIDATE_POINTER0(hAsyncReaderH, "GDALAsyncReader");
+    static_cast<GDALDataset *>(hDS)
+        ->EndAsyncReader(static_cast<GDALAsyncReader *>(hAsyncReaderH));
 }
 
 /************************************************************************/
@@ -3277,8 +3402,8 @@ void CPL_STDCALL GDALEndAsyncReader(GDALDatasetH hDS, GDALAsyncReaderH hAsyncRea
  * The driver implementation may choose to destroy its raster bands,
  * so be careful not to call any method on the raster bands afterwards.
  *
- * Basically the only safe action you can do after calling CloseDependentDatasets()
- * is to call the destructor.
+ * Basically the only safe action you can do after calling
+ * CloseDependentDatasets() is to call the destructor.
  *
  * Note: the only legitimate caller of CloseDependentDatasets() is
  * GDALDriverManager::~GDALDriverManager()
@@ -3310,108 +3435,188 @@ int GDALDataset::CloseDependentDatasets()
  * @since GDAL 1.9.0
  */
 
-void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)
+void GDALDataset::ReportError(CPLErr eErrClass, CPLErrorNum err_no,
+                              const char *fmt, ...)
 {
     va_list args;
 
     va_start(args, fmt);
 
-    char szNewFmt[256];
-    const char* pszDSName = GetDescription();
+    char szNewFmt[256] = {};
+    const char *pszDSName = GetDescription();
     if (strlen(fmt) + strlen(pszDSName) + 3 >= sizeof(szNewFmt) - 1)
         pszDSName = CPLGetFilename(pszDSName);
     if (pszDSName[0] != '\0' &&
         strlen(fmt) + strlen(pszDSName) + 3 < sizeof(szNewFmt) - 1)
     {
-        snprintf(szNewFmt, sizeof(szNewFmt), "%s: %s",
-                 pszDSName, fmt);
-        CPLErrorV( eErrClass, err_no, szNewFmt, args );
+        snprintf(szNewFmt, sizeof(szNewFmt), "%s: %s", pszDSName, fmt);
+        CPLErrorV(eErrClass, err_no, szNewFmt, args);
     }
     else
     {
-        CPLErrorV( eErrClass, err_no, fmt, args );
+        CPLErrorV(eErrClass, err_no, fmt, args);
     }
     va_end(args);
 }
 
 /************************************************************************/
-/*                            GetDriverName()                           */
+/*                            GetMetadata()                             */
 /************************************************************************/
-
-const char* GDALDataset::GetDriverName()
+char **GDALDataset::GetMetadata(const char *pszDomain)
 {
-    if( poDriver )
-        return poDriver->GetDescription();
-    return "";
-}
+    if( pszDomain != NULL && EQUAL(pszDomain, "DERIVED_SUBDATASETS") )
+    {
+        oDerivedMetadataList.Clear();
 
-/************************************************************************/
-/*                     GDALDatasetReleaseResultSet()                    */
-/************************************************************************/
+        // First condition: at least one raster band.
+        if(GetRasterCount() > 0)
+        {
+            // Check if there is at least one complex band.
+            bool hasAComplexBand = false;
 
-/**
- \brief Release results of ExecuteSQL().
+            for(int rasterId = 1; rasterId <= GetRasterCount(); ++rasterId)
+            {
+                if(GDALDataTypeIsComplex(
+                       GetRasterBand(rasterId)->GetRasterDataType()))
+                {
+                    hasAComplexBand = true;
+                    break;
+                }
+            }
 
- This function should only be used to deallocate OGRLayers resulting from
- an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
- results set before destroying the GDALDataset may cause errors.
+            unsigned int nbSupportedDerivedDS = 0;
+            const DerivedDatasetDescription *poDDSDesc =
+                GDALGetDerivedDatasetDescriptions(&nbSupportedDerivedDS);
 
- This function is the same as the C++ method GDALDataset::ReleaseResultSet()
+            int nNumDataset = 1;
+            for(unsigned int derivedId = 0; derivedId < nbSupportedDerivedDS;
+                ++derivedId)
+            {
+                if(hasAComplexBand ||
+                   CPLString(poDDSDesc[derivedId].pszInputPixelType) !=
+                       "complex")
+                {
+                    oDerivedMetadataList.SetNameValue(
+                        CPLSPrintf("DERIVED_SUBDATASET_%d_NAME", nNumDataset),
+                        CPLSPrintf("DERIVED_SUBDATASET:%s:%s",
+                                   poDDSDesc[derivedId].pszDatasetName,
+                                   GetDescription()));
+
+                    CPLString osDesc(
+                        CPLSPrintf("%s from %s",
+                                   poDDSDesc[derivedId].pszDatasetDescription,
+                                   GetDescription()));
+                    oDerivedMetadataList.SetNameValue(
+                        CPLSPrintf("DERIVED_SUBDATASET_%d_DESC", nNumDataset),
+                        osDesc.c_str());
+
+                    nNumDataset++;
+                }
+            }
+        }
+        return oDerivedMetadataList.List();
+    }
 
- @since GDAL 2.0
+    return GDALMajorObject::GetMetadata(pszDomain);
+}
 
- @param hDS the dataset handle.
- @param hLayer the result of a previous ExecuteSQL() call.
+/**
+ * \fn GDALDataset::SetMetadata( char ** papszMetadata, const char * pszDomain)
+ * \brief Set metadata.
+ *
+ * CAUTION: depending on the format, older values of the updated information
+ * might still be found in the file in a "ghost" state, even if no longer
+ * accessible through the GDAL API. This is for example the case of the GTiff
+ * format (this is not a exhaustive list)
+ *
+ * The C function GDALSetMetadata() does the same thing as this method.
+ *
+ * @param papszMetadata the metadata in name=value string list format to
+ * apply.
+ * @param pszDomain the domain of interest.  Use "" or NULL for the default
+ * domain.
+ * @return CE_None on success, CE_Failure on failure and CE_Warning if the
+ * metadata has been accepted, but is likely not maintained persistently
+ * by the underlying object between sessions.
+ */
 
-*/
-void GDALDatasetReleaseResultSet( GDALDatasetH hDS, OGRLayerH hLayer )
+/**
+ * \fn GDALDataset::SetMetadataItem( const char * pszName, const char *
+ * pszValue, const char * pszDomain)
+ * \brief Set single metadata item.
+ *
+ * CAUTION: depending on the format, older values of the updated information
+ * might still be found in the file in a "ghost" state, even if no longer
+ * accessible through the GDAL API. This is for example the case of the GTiff
+ * format (this is not a exhaustive list)
+ *
+ * The C function GDALSetMetadataItem() does the same thing as this method.
+ *
+ * @param pszName the key for the metadata item to fetch.
+ * @param pszValue the value to assign to the key.
+ * @param pszDomain the domain to set within, use NULL for the default domain.
+ *
+ * @return CE_None on success, or an error code on failure.
+ */
 
+/************************************************************************/
+/*                            GetMetadataDomainList()                   */
+/************************************************************************/
+
+char **GDALDataset::GetMetadataDomainList()
 {
-    VALIDATE_POINTER0( hDS, "GDALDatasetReleaseResultSet" );
+    char **currentDomainList = CSLDuplicate(oMDMD.GetDomainList());
 
-    ((GDALDataset *) hDS)->ReleaseResultSet( (OGRLayer *) hLayer );
+    // Ensure that we do not duplicate DERIVED domain.
+    if(GetRasterCount() > 0 &&
+       CSLFindString(currentDomainList, "DERIVED_SUBDATASETS") == -1)
+    {
+        currentDomainList =
+            CSLAddString(currentDomainList, "DERIVED_SUBDATASETS");
+    }
+    return currentDomainList;
 }
 
 /************************************************************************/
-/*                     GDALDatasetTestCapability()                      */
+/*                            GetDriverName()                           */
 /************************************************************************/
 
-/**
- \brief Test if capability is available.
+/** Return driver name.
+ * @return driver name.
+ */
+const char *GDALDataset::GetDriverName()
+{
+    if( poDriver )
+        return poDriver->GetDescription();
+    return "";
+}
 
- One of the following dataset capability names can be passed into this
- function, and a TRUE or FALSE value will be returned indicating whether or not
- the capability is available for this object.
+/************************************************************************/
+/*                     GDALDatasetReleaseResultSet()                    */
+/************************************************************************/
 
- <ul>
-  <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
-  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing layers.<p>
-  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
-        datasource support CreateGeomField() just after layer creation.<p>
-  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve geometries.<p>
-  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient) transactions.<p>
-  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports transactions through emulation.<p>
- </ul>
+/**
+ \brief Release results of ExecuteSQL().
 
- The \#define macro forms of the capability names should be used in preference
- to the strings themselves to avoid misspelling.
+ This function should only be used to deallocate OGRLayers resulting from
+ an ExecuteSQL() call on the same GDALDataset.  Failure to deallocate a
+ results set before destroying the GDALDataset may cause errors.
 
- This function is the same as the C++ method GDALDataset::TestCapability()
+ This function is the same as the C++ method GDALDataset::ReleaseResultSet()
 
  @since GDAL 2.0
 
  @param hDS the dataset handle.
- @param pszCap the capability to test.
+ @param hLayer the result of a previous ExecuteSQL() call.
 
- @return TRUE if capability available otherwise FALSE.
 */
-int GDALDatasetTestCapability( GDALDatasetH hDS, const char *pszCap )
+void GDALDatasetReleaseResultSet( GDALDatasetH hDS, OGRLayerH hLayer )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetTestCapability", 0 );
-    VALIDATE_POINTER1( pszCap, "GDALDatasetTestCapability", 0 );
+    VALIDATE_POINTER0(hDS, "GDALDatasetReleaseResultSet");
 
-    return ((GDALDataset *) hDS)->TestCapability( pszCap );
+    static_cast<GDALDataset *>(hDS)
+        ->ReleaseResultSet(reinterpret_cast<OGRLayer *>(hLayer));
 }
 
 /************************************************************************/
@@ -3432,9 +3637,9 @@ int GDALDatasetTestCapability( GDALDatasetH hDS, const char *pszCap )
 int GDALDatasetGetLayerCount( GDALDatasetH hDS )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetH", 0 );
+    VALIDATE_POINTER1(hDS, "GDALDatasetH", 0);
 
-    return ((GDALDataset *)hDS)->GetLayerCount();
+    return static_cast<GDALDataset *>(hDS)->GetLayerCount();
 }
 
 /************************************************************************/
@@ -3460,9 +3665,10 @@ int GDALDatasetGetLayerCount( GDALDatasetH hDS )
 OGRLayerH GDALDatasetGetLayer( GDALDatasetH hDS, int iLayer )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetGetLayer", NULL );
+    VALIDATE_POINTER1(hDS, "GDALDatasetGetLayer", NULL);
 
-    return (OGRLayerH) ((GDALDataset*)hDS)->GetLayer( iLayer );
+    return reinterpret_cast<OGRLayerH>(
+        static_cast<GDALDataset *>(hDS)->GetLayer(iLayer));
 }
 
 /************************************************************************/
@@ -3488,9 +3694,10 @@ OGRLayerH GDALDatasetGetLayer( GDALDatasetH hDS, int iLayer )
 OGRLayerH GDALDatasetGetLayerByName( GDALDatasetH hDS, const char *pszName )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetGetLayerByName", NULL );
+    VALIDATE_POINTER1(hDS, "GDALDatasetGetLayerByName", NULL);
 
-    return (OGRLayerH) ((GDALDataset *) hDS)->GetLayerByName( pszName );
+    return reinterpret_cast<OGRLayerH>(
+        static_cast<GDALDataset *>(hDS)->GetLayerByName(pszName));
 }
 
 /************************************************************************/
@@ -3517,9 +3724,9 @@ OGRLayerH GDALDatasetGetLayerByName( GDALDatasetH hDS, const char *pszName )
 OGRErr GDALDatasetDeleteLayer( GDALDatasetH hDS, int iLayer )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE );
+    VALIDATE_POINTER1(hDS, "GDALDatasetH", OGRERR_INVALID_HANDLE);
 
-    return ((GDALDataset *) hDS)->DeleteLayer( iLayer );
+    return static_cast<GDALDataset *>(hDS)->DeleteLayer(iLayer);
 }
 
 /************************************************************************/
@@ -3527,31 +3734,32 @@ OGRErr GDALDatasetDeleteLayer( GDALDatasetH hDS, int iLayer )
 /************************************************************************/
 
 /**
-\brief This method attempts to create a new layer on the dataset with the indicated name, coordinate system, geometry type.
+\brief This method attempts to create a new layer on the dataset with the
+indicated name, coordinate system, geometry type.
 
 The papszOptions argument
 can be used to control driver specific creation options.  These options are
 normally documented in the format specific documentation.
 
- In GDAL 2.0, drivers should extend the ICreateLayer() method and not CreateLayer().
- CreateLayer() adds validation of layer creation options, before delegating the
- actual work to ICreateLayer().
+In GDAL 2.0, drivers should extend the ICreateLayer() method and not
+CreateLayer().  CreateLayer() adds validation of layer creation options, before
+delegating the actual work to ICreateLayer().
 
- This method is the same as the C function GDALDatasetCreateLayer() and the
- deprecated OGR_DS_CreateLayer().
+This method is the same as the C function GDALDatasetCreateLayer() and the
+deprecated OGR_DS_CreateLayer().
 
- In GDAL 1.X, this method used to be in the OGRDataSource class.
+In GDAL 1.X, this method used to be in the OGRDataSource class.
 
- @param pszName the name for the new layer.  This should ideally not
+ at param pszName the name for the new layer.  This should ideally not
 match any existing layer on the datasource.
- @param poSpatialRef the coordinate system to use for the new layer, or NULL if
+ at param poSpatialRef the coordinate system to use for the new layer, or NULL if
 no coordinate system is available.
- @param eGType the geometry type for the layer.  Use wkbUnknown if there
+ at param eGType the geometry type for the layer.  Use wkbUnknown if there
 are no constraints on the types geometry to be written.
- @param papszOptions a StringList of name=value options.  Options are driver
+ at param papszOptions a StringList of name=value options.  Options are driver
 specific.
 
- @return NULL is returned on failure, or a new OGRLayer handle on success.
+ at return NULL is returned on failure, or a new OGRLayer handle on success.
 
 <b>Example:</b>
 
@@ -3587,21 +3795,22 @@ OGRLayer *GDALDataset::CreateLayer( const char * pszName,
                                       char **papszOptions )
 
 {
-    ValidateLayerCreationOptions( papszOptions );
+    ValidateLayerCreationOptions(papszOptions);
 
     if( OGR_GT_IsNonLinear(eGType) && !TestCapability(ODsCCurveGeometries) )
     {
         eGType = OGR_GT_GetLinear(eGType);
     }
 
-    OGRLayer* poLayer = ICreateLayer(pszName, poSpatialRef, eGType, papszOptions);
+    OGRLayer *poLayer =
+        ICreateLayer(pszName, poSpatialRef, eGType, papszOptions);
 #ifdef DEBUG
     if( poLayer != NULL && OGR_GT_IsNonLinear(poLayer->GetGeomType()) &&
         !poLayer->TestCapability(OLCCurveGeometries) )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Inconsistent driver: Layer geometry type is non-linear, but "
-                  "TestCapability(OLCCurveGeometries) returns FALSE." );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Inconsistent driver: Layer geometry type is non-linear, but "
+                 "TestCapability(OLCCurveGeometries) returns FALSE.");
     }
 #endif
 
@@ -3613,27 +3822,28 @@ OGRLayer *GDALDataset::CreateLayer( const char * pszName,
 /************************************************************************/
 
 /**
-\brief This function attempts to create a new layer on the dataset with the indicated name, coordinate system, geometry type.
+\brief This function attempts to create a new layer on the dataset with the
+indicated name, coordinate system, geometry type.
 
-The papszOptions argument
-can be used to control driver specific creation options.  These options are
-normally documented in the format specific documentation.
+The papszOptions argument can be used to control driver specific creation
+options.  These options are normally documented in the format specific
+documentation.
 
- This method is the same as the C++ method GDALDataset::CreateLayer().
+This method is the same as the C++ method GDALDataset::CreateLayer().
 
- @since GDAL 2.0
+ at since GDAL 2.0
 
- @param hDS the dataset handle
- @param pszName the name for the new layer.  This should ideally not
+ at param hDS the dataset handle
+ at param pszName the name for the new layer.  This should ideally not
 match any existing layer on the datasource.
- @param hSpatialRef the coordinate system to use for the new layer, or NULL if
+ at param hSpatialRef the coordinate system to use for the new layer, or NULL if
 no coordinate system is available.
- @param eGType the geometry type for the layer.  Use wkbUnknown if there
+ at param eGType the geometry type for the layer.  Use wkbUnknown if there
 are no constraints on the types geometry to be written.
- @param papszOptions a StringList of name=value options.  Options are driver
+ at param papszOptions a StringList of name=value options.  Options are driver
 specific.
 
- @return NULL is returned on failure, or a new OGRLayer handle on success.
+ at return NULL is returned on failure, or a new OGRLayer handle on success.
 
 <b>Example:</b>
 
@@ -3670,18 +3880,20 @@ OGRLayerH GDALDatasetCreateLayer( GDALDatasetH hDS,
                               char ** papszOptions )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetCreateLayer", NULL );
+    VALIDATE_POINTER1(hDS, "GDALDatasetCreateLayer", NULL);
 
     if (pszName == NULL)
     {
-        CPLError ( CE_Failure, CPLE_ObjectNull, "Name was NULL in GDALDatasetCreateLayer");
+        CPLError(CE_Failure, CPLE_ObjectNull,
+                 "Name was NULL in GDALDatasetCreateLayer");
         return NULL;
     }
-    return (OGRLayerH) ((GDALDataset *)hDS)->CreateLayer(
-        pszName, (OGRSpatialReference *) hSpatialRef, eGType, papszOptions );
+    return reinterpret_cast<OGRLayerH>(
+        static_cast<GDALDataset *>(hDS)->CreateLayer(
+            pszName, reinterpret_cast<OGRSpatialReference *>(hSpatialRef),
+            eGType, papszOptions));
 }
 
-
 /************************************************************************/
 /*                         GDALDatasetCopyLayer()                       */
 /************************************************************************/
@@ -3713,13 +3925,13 @@ OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS,
                                 char **papszOptions )
 
 {
-    VALIDATE_POINTER1( hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", NULL );
-    VALIDATE_POINTER1( hSrcLayer, "GDALDatasetCopyLayer", NULL );
-    VALIDATE_POINTER1( pszNewName, "GDALDatasetCopyLayer", NULL );
+    VALIDATE_POINTER1(hDS, "OGR_DS_CopyGDALDatasetCopyLayerLayer", NULL);
+    VALIDATE_POINTER1(hSrcLayer, "GDALDatasetCopyLayer", NULL);
+    VALIDATE_POINTER1(pszNewName, "GDALDatasetCopyLayer", NULL);
 
-    return (OGRLayerH)
-        ((GDALDataset *) hDS)->CopyLayer( (OGRLayer *) hSrcLayer,
-                                            pszNewName, papszOptions );
+    return reinterpret_cast<OGRLayerH>(
+        static_cast<GDALDataset *>(hDS)->CopyLayer(
+            reinterpret_cast<OGRLayer *>(hSrcLayer), pszNewName, papszOptions));
 }
 
 /************************************************************************/
@@ -3750,10 +3962,11 @@ OGRLayerH GDALDatasetCopyLayer( GDALDatasetH hDS,
  @param hDS the dataset handle.
  @param pszStatement the SQL statement to execute.
  @param hSpatialFilter geometry which represents a spatial filter. Can be NULL.
+
  @param pszDialect allows control of the statement dialect. If set to NULL, the
-OGR SQL engine will be used, except for RDBMS drivers that will use their dedicated SQL engine,
-unless OGRSQL is explicitly passed as the dialect. Starting with OGR 1.10, the SQLITE dialect
-can also be used.
+ OGR SQL engine will be used, except for RDBMS drivers that will use their
+ dedicated SQL engine, unless OGRSQL is explicitly passed as the
+ dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
 
  @return an OGRLayer containing the results of the query.  Deallocate with
  ReleaseResultSet().
@@ -3766,12 +3979,12 @@ OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS,
                              const char *pszDialect )
 
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetExecuteSQL", NULL );
+    VALIDATE_POINTER1(hDS, "GDALDatasetExecuteSQL", NULL);
 
-    return (OGRLayerH)
-        ((GDALDataset *)hDS)->ExecuteSQL( pszStatement,
-                                            (OGRGeometry *) hSpatialFilter,
-                                            pszDialect );
+    return reinterpret_cast<OGRLayerH>(
+        static_cast<GDALDataset *>(hDS)->ExecuteSQL(
+            pszStatement, reinterpret_cast<OGRGeometry *>(hSpatialFilter),
+            pszDialect));
 }
 
 /************************************************************************/
@@ -3793,9 +4006,10 @@ OGRLayerH GDALDatasetExecuteSQL( GDALDatasetH hDS,
 OGRStyleTableH GDALDatasetGetStyleTable( GDALDatasetH hDS )
 
 {
-    VALIDATE_POINTER1( hDS, "OGR_DS_GetStyleTable", NULL );
+    VALIDATE_POINTER1(hDS, "OGR_DS_GetStyleTable", NULL);
 
-    return (OGRStyleTableH) ((GDALDataset *) hDS)->GetStyleTable( );
+    return reinterpret_cast<OGRStyleTableH>(
+        static_cast<GDALDataset *>(hDS)->GetStyleTable());
 }
 
 /************************************************************************/
@@ -3808,7 +4022,8 @@ OGRStyleTableH GDALDatasetGetStyleTable( GDALDatasetH hDS )
  This function operate exactly as GDALDatasetSetStyleTable() except that it
  assumes ownership of the passed table.
 
- This function is the same as the C++ method GDALDataset::SetStyleTableDirectly()
+ This function is the same as the C++ method
+ GDALDataset::SetStyleTableDirectly()
 
  @since GDAL 2.0
 
@@ -3818,12 +4033,13 @@ OGRStyleTableH GDALDatasetGetStyleTable( GDALDatasetH hDS )
 */
 
 void GDALDatasetSetStyleTableDirectly( GDALDatasetH hDS,
-                                   OGRStyleTableH hStyleTable )
+                                       OGRStyleTableH hStyleTable )
 
 {
-    VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTableDirectly" );
+    VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTableDirectly");
 
-    ((GDALDataset *) hDS)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
+    static_cast<GDALDataset *>(hDS)
+        ->SetStyleTableDirectly(reinterpret_cast<OGRStyleTable *>(hStyleTable));
 }
 
 /************************************************************************/
@@ -3833,8 +4049,8 @@ void GDALDatasetSetStyleTableDirectly( GDALDatasetH hDS,
 /**
  \brief Set dataset style table.
 
- This function operate exactly as GDALDatasetSetStyleTableDirectly() except that it
- assumes ownership of the passed table.
+ This function operate exactly as GDALDatasetSetStyleTableDirectly() except that
+ it assumes ownership of the passed table.
 
  This function is the same as the C++ method GDALDataset::SetStyleTable()
 
@@ -3848,37 +4064,42 @@ void GDALDatasetSetStyleTableDirectly( GDALDatasetH hDS,
 void GDALDatasetSetStyleTable( GDALDatasetH hDS, OGRStyleTableH hStyleTable )
 
 {
-    VALIDATE_POINTER0( hDS, "OGR_DS_SetStyleTable" );
-    VALIDATE_POINTER0( hStyleTable, "OGR_DS_SetStyleTable" );
+    VALIDATE_POINTER0(hDS, "OGR_DS_SetStyleTable");
+    VALIDATE_POINTER0(hStyleTable, "OGR_DS_SetStyleTable");
 
-    ((GDALDataset *) hDS)->SetStyleTable( (OGRStyleTable *) hStyleTable);
+    static_cast<GDALDataset *>(hDS)
+        ->SetStyleTable(reinterpret_cast<OGRStyleTable *>(hStyleTable));
 }
 
 /************************************************************************/
 /*                    ValidateLayerCreationOptions()                    */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 int GDALDataset::ValidateLayerCreationOptions( const char* const* papszLCO )
 {
-    const char *pszOptionList = GetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST );
+    const char *pszOptionList =
+        GetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST);
     if( pszOptionList == NULL && poDriver != NULL )
     {
         pszOptionList =
-             poDriver->GetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST );
+            poDriver->GetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST );
     }
     CPLString osDataset;
     osDataset.Printf("dataset %s", GetDescription());
-    return GDALValidateOptions( pszOptionList, papszLCO,
-                                "layer creation option",
-                                osDataset );
+    return GDALValidateOptions(pszOptionList, papszLCO,
+                               "layer creation option",
+                               osDataset);
 }
+//! @endcond
 
 /************************************************************************/
 /*                              Release()                               */
 /************************************************************************/
 
 /**
-\brief Drop a reference to this dataset, and if the reference count drops to one close (destroy) the dataset.
+\brief Drop a reference to this dataset, and if the reference count drops to one
+close (destroy) the dataset.
 
 This method is the same as the C function OGRReleaseDataSource().
 
@@ -3890,7 +4111,7 @@ This method is the same as the C function OGRReleaseDataSource().
 OGRErr GDALDataset::Release()
 
 {
-    GDALClose( (GDALDatasetH) this );
+    ReleaseRef();
     return OGRERR_NONE;
 }
 
@@ -3908,12 +4129,7 @@ In GDAL 1.X, this method used to be in the OGRDataSource class.
 @return the current reference count for the datasource object itself.
 */
 
-
-int GDALDataset::GetRefCount() const
-
-{
-    return nRefCount;
-}
+int GDALDataset::GetRefCount() const { return nRefCount; }
 
 /************************************************************************/
 /*                         GetSummaryRefCount()                         */
@@ -3934,14 +4150,14 @@ In GDAL 1.X, this method used to be in the OGRDataSource class.
 int GDALDataset::GetSummaryRefCount() const
 
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
+    CPLMutexHolderD(psPrivate ? &(psPrivate->hMutex) : NULL);
     int nSummaryCount = nRefCount;
-    int iLayer;
-    GDALDataset *poUseThis = (GDALDataset *) this;
+    GDALDataset *poUseThis = const_cast<GDALDataset *>(this);
 
-    for( iLayer=0; iLayer < poUseThis->GetLayerCount(); iLayer++ )
-        nSummaryCount += poUseThis->GetLayer( iLayer )->GetRefCount();
+    for( int iLayer = 0; iLayer < poUseThis->GetLayerCount(); ++iLayer )
+        nSummaryCount += poUseThis->GetLayer(iLayer)->GetRefCount();
 
     return nSummaryCount;
 }
@@ -3951,41 +4167,37 @@ int GDALDataset::GetSummaryRefCount() const
 /************************************************************************/
 
 /**
-\brief This method attempts to create a new layer on the dataset with the indicated name, coordinate system, geometry type.
+ \brief This method attempts to create a new layer on the dataset with the
+ indicated name, coordinate system, geometry type.
 
-This method is reserved to implementation by drivers.
+ This method is reserved to implementation by drivers.
 
-The papszOptions argument
-can be used to control driver specific creation options.  These options are
-normally documented in the format specific documentation.
+ The papszOptions argument can be used to control driver specific creation
+ options.  These options are normally documented in the format specific
+ documentation.
 
  @param pszName the name for the new layer.  This should ideally not
-match any existing layer on the datasource.
+ match any existing layer on the datasource.
  @param poSpatialRef the coordinate system to use for the new layer, or NULL if
-no coordinate system is available.
+ no coordinate system is available.
  @param eGType the geometry type for the layer.  Use wkbUnknown if there
-are no constraints on the types geometry to be written.
+ are no constraints on the types geometry to be written.
  @param papszOptions a StringList of name=value options.  Options are driver
-specific.
+ specific.
 
  @return NULL is returned on failure, or a new OGRLayer handle on success.
 
  @since GDAL 2.0
 */
 
-OGRLayer *GDALDataset::ICreateLayer( const char * pszName,
-                                      OGRSpatialReference * poSpatialRef,
-                                      OGRwkbGeometryType eGType,
-                                      char **papszOptions )
+OGRLayer *GDALDataset::ICreateLayer( const char * /* pszName */,
+                                     OGRSpatialReference * /* poSpatialRef */,
+                                     OGRwkbGeometryType /* eGType */,
+                                     char ** /* papszOptions */ )
 
 {
-    (void) eGType;
-    (void) poSpatialRef;
-    (void) pszName;
-    (void) papszOptions;
-
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "CreateLayer() not supported by this dataset." );
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "CreateLayer() not supported by this dataset.");
 
     return NULL;
 }
@@ -4020,46 +4232,45 @@ OGRLayer *GDALDataset::ICreateLayer( const char * pszName,
 */
 
 OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
-                                    const char *pszNewName,
-                                    char **papszOptions )
+                                  const char *pszNewName,
+                                  char **papszOptions )
 
 {
-    OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
-    OGRLayer *poDstLayer = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Create the layer.                                               */
 /* -------------------------------------------------------------------- */
     if( !TestCapability( ODsCCreateLayer ) )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "This datasource does not support creation of layers." );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "This datasource does not support creation of layers.");
         return NULL;
     }
 
-    const char* pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
+    const char *pszSRSWKT = CSLFetchNameValue(papszOptions, "DST_SRSWKT");
     OGRSpatialReference oDstSpaRef(pszSRSWKT);
+    OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
+    OGRLayer *poDstLayer = NULL;
 
     CPLErrorReset();
     if( poSrcDefn->GetGeomFieldCount() > 1 &&
         TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
     {
-        poDstLayer =ICreateLayer( pszNewName, NULL, wkbNone, papszOptions );
+        poDstLayer = ICreateLayer(pszNewName, NULL, wkbNone, papszOptions);
     }
     else
     {
         if(NULL == pszSRSWKT)
         {
-        poDstLayer =ICreateLayer( pszNewName, poSrcLayer->GetSpatialRef(),
-                                  poSrcDefn->GetGeomType(), papszOptions );
-    }
+            poDstLayer = ICreateLayer(pszNewName, poSrcLayer->GetSpatialRef(),
+                                      poSrcDefn->GetGeomType(), papszOptions);
+        }
         else
         {
-            // remove DST_WKT from option list to prevent WARNINfrom driver
-            int nSRSPos = CSLFindName(papszOptions, "DST_SRSWKT");
+            // Remove DST_WKT from option list to prevent warning from driver.
+            const int nSRSPos = CSLFindName(papszOptions, "DST_SRSWKT");
             papszOptions = CSLRemoveStrings(papszOptions, nSRSPos, 1, NULL);
-            poDstLayer = ICreateLayer( pszNewName, &oDstSpaRef,
-                                  poSrcDefn->GetGeomType(), papszOptions );
+            poDstLayer = ICreateLayer(pszNewName, &oDstSpaRef,
+                                      poSrcDefn->GetGeomType(), papszOptions);
         }
     }
 
@@ -4072,26 +4283,23 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
 /*      case the target datasource has altered it (e.g. Shapefile       */
 /*      limited to 10 char field names).                                */
 /* -------------------------------------------------------------------- */
-    int         nSrcFieldCount = poSrcDefn->GetFieldCount();
-    int         nDstFieldCount = 0;
-    int         iField, *panMap;
+    const int nSrcFieldCount = poSrcDefn->GetFieldCount();
 
-    // Initialize the index-to-index map to -1's
-    panMap = (int *) CPLMalloc( sizeof(int) * nSrcFieldCount );
-    for( iField=0; iField < nSrcFieldCount; iField++)
+    // Initialize the index-to-index map to -1's.
+    int *panMap = static_cast<int *>(CPLMalloc(sizeof(int) * nSrcFieldCount));
+    for( int iField = 0; iField < nSrcFieldCount; ++iField )
         panMap[iField] = -1;
 
-    /* Caution : at the time of writing, the MapInfo driver */
-    /* returns NULL until a field has been added */
-    OGRFeatureDefn* poDstFDefn = poDstLayer->GetLayerDefn();
-    if (poDstFDefn)
-        nDstFieldCount = poDstFDefn->GetFieldCount();
-    for( iField = 0; iField < nSrcFieldCount; iField++ )
+    // Caution: At the time of writing, the MapInfo driver
+    // returns NULL until a field has been added.
+    OGRFeatureDefn *poDstFDefn = poDstLayer->GetLayerDefn();
+    int nDstFieldCount = poDstFDefn ? poDstFDefn->GetFieldCount() : 0;
+    for( int iField = 0; iField < nSrcFieldCount; ++iField )
     {
-        OGRFieldDefn* poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
-        OGRFieldDefn oFieldDefn( poSrcFieldDefn );
+        OGRFieldDefn *poSrcFieldDefn = poSrcDefn->GetFieldDefn(iField);
+        OGRFieldDefn oFieldDefn(poSrcFieldDefn);
 
-        /* The field may have been already created at layer creation */
+        // The field may have been already created at layer creation.
         int iDstField = -1;
         if (poDstFDefn)
             iDstField = poDstFDefn->GetFieldIndex(oFieldDefn.GetNameRef());
@@ -4101,22 +4309,23 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
         }
         else if (poDstLayer->CreateField( &oFieldDefn ) == OGRERR_NONE)
         {
-            /* now that we've created a field, GetLayerDefn() won't return NULL */
+            // Now that we've created a field, GetLayerDefn() won't return NULL.
             if (poDstFDefn == NULL)
                 poDstFDefn = poDstLayer->GetLayerDefn();
 
-            /* Sanity check : if it fails, the driver is buggy */
+            // Sanity check: if it fails, the driver is buggy.
             if (poDstFDefn != NULL &&
                 poDstFDefn->GetFieldCount() != nDstFieldCount + 1)
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
-                         "The output driver has claimed to have added the %s field, but it did not!",
-                         oFieldDefn.GetNameRef() );
+                         "The output driver has claimed to have added the %s "
+                         "field, but it did not!",
+                         oFieldDefn.GetNameRef());
             }
             else
             {
                 panMap[iField] = nDstFieldCount;
-                nDstFieldCount ++;
+                ++nDstFieldCount;
             }
         }
     }
@@ -4127,34 +4336,34 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
     if (sourceSRS != NULL && pszSRSWKT != NULL &&
             sourceSRS->IsSame(&oDstSpaRef) == FALSE)
     {
-        poCT = (OGRCoordinateTransformation*)OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef);
+        poCT = OGRCreateCoordinateTransformation(sourceSRS, &oDstSpaRef);
         if(NULL == poCT)
         {
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "This input/output spatial reference is not supported." );
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "This input/output spatial reference is not supported.");
             CPLFree(panMap);
             return NULL;
         }
     }
-/*      Create geometry fields.                                         */
 /* -------------------------------------------------------------------- */
 /*      Create geometry fields.                                         */
 /* -------------------------------------------------------------------- */
-    int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
+    const int nSrcGeomFieldCount = poSrcDefn->GetGeomFieldCount();
     if( nSrcGeomFieldCount > 1 &&
         TestCapability(ODsCCreateGeomFieldAfterCreateLayer) )
     {
 
-        for( iField = 0; iField < nSrcGeomFieldCount; iField++ )
+        for( int iField = 0; iField < nSrcGeomFieldCount; ++iField )
         {
             if(NULL == pszSRSWKT)
-        {
-            poDstLayer->CreateGeomField( poSrcDefn->GetGeomFieldDefn(iField) );
-        }
+            {
+                poDstLayer->CreateGeomField(
+                    poSrcDefn->GetGeomFieldDefn(iField));
+            }
             else
             {
-                OGRGeomFieldDefn* pDstGeomFieldDefn =
-                        poSrcDefn->GetGeomFieldDefn(iField);
+                OGRGeomFieldDefn *pDstGeomFieldDefn =
+                    poSrcDefn->GetGeomFieldDefn(iField);
                 pDstGeomFieldDefn->SetSpatialRef(&oDstSpaRef);
                 poDstLayer->CreateGeomField(pDstGeomFieldDefn);
             }
@@ -4165,188 +4374,198 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
 /*      Check if the destination layer supports transactions and set a  */
 /*      default number of features in a single transaction.             */
 /* -------------------------------------------------------------------- */
-    int nGroupTransactions = 0;
-    if( poDstLayer->TestCapability( OLCTransactions ) )
-        nGroupTransactions = 128;
+    const int nGroupTransactions =
+        poDstLayer->TestCapability(OLCTransactions) ? 128 : 0;
 
 /* -------------------------------------------------------------------- */
 /*      Transfer features.                                              */
 /* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature;
+    OGRFeature *poFeature = NULL;
 
     poSrcLayer->ResetReading();
 
     if( nGroupTransactions <= 0 )
     {
-      while( true )
-      {
-        OGRFeature      *poDstFeature = NULL;
+        while( true )
+        {
+            poFeature = poSrcLayer->GetNextFeature();
 
-        poFeature = poSrcLayer->GetNextFeature();
+            if( poFeature == NULL )
+                break;
 
-        if( poFeature == NULL )
-            break;
+            CPLErrorReset();
+            OGRFeature *poDstFeature =
+                OGRFeature::CreateFeature(poDstLayer->GetLayerDefn());
 
-        CPLErrorReset();
-        poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
+            if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) !=
+                    OGRERR_NONE )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Unable to translate feature " CPL_FRMT_GIB
+                         " from layer %s.",
+                         poFeature->GetFID(), poSrcDefn->GetName());
+                OGRFeature::DestroyFeature(poFeature);
+                CPLFree(panMap);
+                if(NULL != poCT)
+                    OCTDestroyCoordinateTransformation(
+                        reinterpret_cast<OGRCoordinateTransformationH>(poCT));
+                return poDstLayer;
+            }
 
-        if( poDstFeature->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to translate feature " CPL_FRMT_GIB " from layer %s.\n",
-                      poFeature->GetFID(), poSrcDefn->GetName() );
-            OGRFeature::DestroyFeature( poFeature );
-            CPLFree(panMap);
             if(NULL != poCT)
-                OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)poCT);
-            return poDstLayer;
-        }
-
-        if(NULL != poCT)
-        {
-            for( iField = 0; iField < nSrcGeomFieldCount; iField++ )
             {
-                OGRGeometry* pGeom = poDstFeature->GetGeomFieldRef(iField);
-                if(NULL != pGeom)
+                for( int iField = 0; iField < nSrcGeomFieldCount; ++iField )
                 {
-                    OGRErr eErr = pGeom->transform(poCT);
-                    if(eErr != OGRERR_NONE)
-                    {
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Unable to transform geometry " CPL_FRMT_GIB
-                                  " from layer %s.\n",
-                                  poFeature->GetFID(), poSrcDefn->GetName() );
-                        OGRFeature::DestroyFeature( poFeature );
-                        CPLFree(panMap);
-                        OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)poCT);
-                        return poDstLayer;
-                    }
+                    OGRGeometry *pGeom = poDstFeature->GetGeomFieldRef(iField);
+                    if(NULL == pGeom)
+                        continue;
+
+                    const OGRErr eErr = pGeom->transform(poCT);
+                    if(eErr == OGRERR_NONE)
+                        continue;
+
+                    CPLError(
+                        CE_Failure, CPLE_AppDefined,
+                        "Unable to transform geometry " CPL_FRMT_GIB
+                        " from layer %s.",
+                        poFeature->GetFID(), poSrcDefn->GetName());
+                    OGRFeature::DestroyFeature(poFeature);
+                    CPLFree(panMap);
+                    OCTDestroyCoordinateTransformation(
+                        reinterpret_cast<OGRCoordinateTransformationH>(poCT));
+                    return poDstLayer;
                 }
             }
-        }
 
-        poDstFeature->SetFID( poFeature->GetFID() );
+            poDstFeature->SetFID(poFeature->GetFID());
 
-        OGRFeature::DestroyFeature( poFeature );
+            OGRFeature::DestroyFeature(poFeature);
 
-        CPLErrorReset();
-        if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
-        {
-            OGRFeature::DestroyFeature( poDstFeature );
-            CPLFree(panMap);
-            if(NULL != poCT)
-                OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)poCT);
-            return poDstLayer;
-        }
+            CPLErrorReset();
+            if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
+            {
+                OGRFeature::DestroyFeature(poDstFeature);
+                CPLFree(panMap);
+                if(NULL != poCT)
+                    OCTDestroyCoordinateTransformation(
+                        reinterpret_cast<OGRCoordinateTransformationH>(poCT));
+                return poDstLayer;
+            }
 
-        OGRFeature::DestroyFeature( poDstFeature );
-      }
+            OGRFeature::DestroyFeature(poDstFeature);
+        }
     }
     else
     {
-      bool bStopTransfer = false;
-      bool bStopTransaction = false;
-      int nFeatCount = 0; // Number of features in the temporary array
-      int nFeaturesToAdd = 0;
-      OGRFeature **papoDstFeature =
-          (OGRFeature **)VSI_CALLOC_VERBOSE(sizeof(OGRFeature *), nGroupTransactions);
-      if( papoDstFeature == NULL )
-          bStopTransfer = true;
-      while( !bStopTransfer )
-      {
+        OGRFeature **papoDstFeature = static_cast<OGRFeature **>(
+            VSI_CALLOC_VERBOSE(sizeof(OGRFeature *), nGroupTransactions));
+
+        bool bStopTransfer = papoDstFeature == NULL;
+        while( !bStopTransfer )
+        {
 /* -------------------------------------------------------------------- */
-/*      Fill the array with features                                    */
+/*      Fill the array with features.                                   */
 /* -------------------------------------------------------------------- */
-        for( nFeatCount = 0; nFeatCount < nGroupTransactions; nFeatCount++ )
-        {
-            poFeature = poSrcLayer->GetNextFeature();
-
-            if( poFeature == NULL )
+            // Number of features in the temporary array.
+            int nFeatCount = 0;  // Used after for.
+            for( nFeatCount = 0; nFeatCount < nGroupTransactions; ++nFeatCount )
             {
-                bStopTransfer = true;
-                break;
-            }
+                poFeature = poSrcLayer->GetNextFeature();
 
-            CPLErrorReset();
-            papoDstFeature[nFeatCount] =
-                        OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
+                if( poFeature == NULL )
+                {
+                    bStopTransfer = true;
+                    break;
+                }
 
-            if( papoDstFeature[nFeatCount]->SetFrom( poFeature, panMap, TRUE ) != OGRERR_NONE )
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Unable to translate feature " CPL_FRMT_GIB " from layer %s.\n",
-                          poFeature->GetFID(), poSrcDefn->GetName() );
-                OGRFeature::DestroyFeature( poFeature );
-                poFeature = NULL;
-                bStopTransfer = true;
-                break;
-            }
+                CPLErrorReset();
+                papoDstFeature[nFeatCount] =
+                    OGRFeature::CreateFeature(poDstLayer->GetLayerDefn());
 
-            if(NULL != poCT)
-            {
-                for( iField = 0; iField < nSrcGeomFieldCount; iField++ )
+                if( papoDstFeature[nFeatCount]->SetFrom(poFeature, panMap,
+                                                       TRUE) != OGRERR_NONE )
                 {
-                    OGRGeometry* pGeom = papoDstFeature[nFeatCount]->GetGeomFieldRef(iField);
-                    if(NULL != pGeom)
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Unable to translate feature " CPL_FRMT_GIB
+                             " from layer %s.",
+                             poFeature->GetFID(), poSrcDefn->GetName());
+                    OGRFeature::DestroyFeature( poFeature );
+                    poFeature = NULL;
+                    bStopTransfer = true;
+                    break;
+                }
+
+                if(NULL != poCT)
+                {
+                    for( int iField = 0; iField < nSrcGeomFieldCount; ++iField )
                     {
-                        OGRErr eErr = pGeom->transform(poCT);
-                        if(eErr != OGRERR_NONE)
-                        {
-                            CPLError( CE_Failure, CPLE_AppDefined,
-                                      "Unable to transform geometry " CPL_FRMT_GIB
-                                      " from layer %s.\n",
-                                      poFeature->GetFID(), poSrcDefn->GetName() );
-                            OGRFeature::DestroyFeature( poFeature );
-                            bStopTransfer = true;
-                            poFeature = NULL;
-                            break;
-                        }
+                        OGRGeometry *pGeom =
+                            papoDstFeature[nFeatCount]->GetGeomFieldRef(iField);
+                        if(NULL == pGeom)
+                            continue;
+
+                        const OGRErr eErr = pGeom->transform(poCT);
+                        if(eErr == OGRERR_NONE)
+                            continue;
+
+                        CPLError(
+                            CE_Failure, CPLE_AppDefined,
+                            "Unable to transform geometry " CPL_FRMT_GIB
+                            " from layer %s.",
+                            poFeature->GetFID(), poSrcDefn->GetName());
+                        OGRFeature::DestroyFeature(poFeature);
+                        bStopTransfer = true;
+                        poFeature = NULL;
+                        break;
                     }
                 }
-            }
-
-            if (poFeature)
-            {
-                papoDstFeature[nFeatCount]->SetFID( poFeature->GetFID() );
-                OGRFeature::DestroyFeature( poFeature );
-                poFeature = NULL;
-            }
-        }
-        nFeaturesToAdd = nFeatCount;
 
-        CPLErrorReset();
-        bStopTransaction = false;
-        while( !bStopTransaction )
-        {
-            bStopTransaction = true;
-            if( poDstLayer->StartTransaction() != OGRERR_NONE )
-                break;
-            for( int i = 0; i < nFeaturesToAdd; i++ )
-            {
-                if( poDstLayer->CreateFeature( papoDstFeature[i] ) != OGRERR_NONE )
+                if (poFeature)
                 {
-                    nFeaturesToAdd = i;
-                    bStopTransfer = true;
-                    bStopTransaction = false;
+                    papoDstFeature[nFeatCount]->SetFID(poFeature->GetFID());
+                    OGRFeature::DestroyFeature(poFeature);
+                    poFeature = NULL;
                 }
             }
-            if( bStopTransaction )
+            int nFeaturesToAdd = nFeatCount;
+
+            CPLErrorReset();
+            bool bStopTransaction = false;
+            while( !bStopTransaction )
             {
-                if( poDstLayer->CommitTransaction() != OGRERR_NONE )
+                bStopTransaction = true;
+                if( poDstLayer->StartTransaction() != OGRERR_NONE )
                     break;
+                for( int i = 0; i < nFeaturesToAdd; ++i )
+                {
+                    if( poDstLayer->CreateFeature( papoDstFeature[i] ) !=
+                       OGRERR_NONE )
+                    {
+                        nFeaturesToAdd = i;
+                        bStopTransfer = true;
+                        bStopTransaction = false;
+                    }
+                }
+                if( bStopTransaction )
+                {
+                    if( poDstLayer->CommitTransaction() != OGRERR_NONE )
+                        break;
+                }
+                else
+                {
+                    poDstLayer->RollbackTransaction();
+                }
             }
-            else
-                poDstLayer->RollbackTransaction();
-        }
 
-        for( int i = 0; i < nFeatCount; i++ )
-            OGRFeature::DestroyFeature( papoDstFeature[i] );
-      }
-      CPLFree(papoDstFeature);
+            for( int i = 0; i < nFeatCount; ++i )
+                OGRFeature::DestroyFeature(papoDstFeature[i]);
+        }
+        CPLFree(papoDstFeature);
     }
 
     if(NULL != poCT)
-        OCTDestroyCoordinateTransformation((OGRCoordinateTransformationH)poCT);
+        OCTDestroyCoordinateTransformation(
+            reinterpret_cast<OGRCoordinateTransformationH>(poCT));
 
     CPLFree(panMap);
 
@@ -4358,6 +4577,7 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
 /************************************************************************/
 
 /**
+ \fn GDALDataset::DeleteLayer(int)
  \brief Delete the indicated layer from the datasource.
 
  If this method is supported
@@ -4374,12 +4594,12 @@ OGRLayer *GDALDataset::CopyLayer( OGRLayer *poSrcLayer,
  layers is not supported for this datasource.
 
 */
-OGRErr GDALDataset::DeleteLayer( int iLayer )
+
+OGRErr GDALDataset::DeleteLayer( CPL_UNUSED int iLayer )
 
 {
-    (void) iLayer;
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "DeleteLayer() not supported by this dataset." );
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "DeleteLayer() not supported by this dataset.");
 
     return OGRERR_UNSUPPORTED_OPERATION;
 }
@@ -4407,16 +4627,15 @@ OGRErr GDALDataset::DeleteLayer( int iLayer )
 OGRLayer *GDALDataset::GetLayerByName( const char *pszName )
 
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-    CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
+    CPLMutexHolderD(psPrivate ? &(psPrivate->hMutex) : NULL);
 
     if ( ! pszName )
         return NULL;
 
-    int  i;
-
-    /* first a case sensitive check */
-    for( i = 0; i < GetLayerCount(); i++ )
+    // First a case sensitive check.
+    for( int i = 0; i < GetLayerCount(); ++i )
     {
         OGRLayer *poLayer = GetLayer(i);
 
@@ -4424,8 +4643,8 @@ OGRLayer *GDALDataset::GetLayerByName( const char *pszName )
             return poLayer;
     }
 
-    /* then case insensitive */
-    for( i = 0; i < GetLayerCount(); i++ )
+    // Then case insensitive.
+    for( int i = 0; i < GetLayerCount(); ++i )
     {
         OGRLayer *poLayer = GetLayer(i);
 
@@ -4436,6 +4655,7 @@ OGRLayer *GDALDataset::GetLayerByName( const char *pszName )
     return NULL;
 }
 
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                       ProcessSQLCreateIndex()                        */
 /*                                                                      */
@@ -4448,37 +4668,37 @@ OGRLayer *GDALDataset::GetLayerByName( const char *pszName )
 OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
 
 {
-    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+    char **papszTokens = CSLTokenizeString(pszSQLCommand);
 
 /* -------------------------------------------------------------------- */
 /*      Do some general syntax checking.                                */
 /* -------------------------------------------------------------------- */
     if( CSLCount(papszTokens) != 6
-        || !EQUAL(papszTokens[0],"CREATE")
-        || !EQUAL(papszTokens[1],"INDEX")
-        || !EQUAL(papszTokens[2],"ON")
-        || !EQUAL(papszTokens[4],"USING") )
-    {
-        CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Syntax error in CREATE INDEX command.\n"
-                  "Was '%s'\n"
-                  "Should be of form 'CREATE INDEX ON <table> USING <field>'",
-                  pszSQLCommand );
+        || !EQUAL(papszTokens[0], "CREATE")
+        || !EQUAL(papszTokens[1], "INDEX")
+        || !EQUAL(papszTokens[2], "ON")
+        || !EQUAL(papszTokens[4], "USING") )
+    {
+        CSLDestroy(papszTokens);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Syntax error in CREATE INDEX command.\n"
+                 "Was '%s'\n"
+                 "Should be of form 'CREATE INDEX ON <table> USING <field>'",
+                 pszSQLCommand);
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Find the named layer.                                           */
 /* -------------------------------------------------------------------- */
-    int  i;
     OGRLayer *poLayer = NULL;
 
     {
-        GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-        CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
+        GDALDatasetPrivate *psPrivate =
+            static_cast<GDALDatasetPrivate *>(m_hPrivateData);
+        CPLMutexHolderD(psPrivate ? &(psPrivate->hMutex) : NULL);
 
-        for( i = 0; i < GetLayerCount(); i++ )
+        for( int i = 0; i < GetLayerCount(); ++i )
         {
             poLayer = GetLayer(i);
 
@@ -4489,10 +4709,10 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
 
         if( poLayer == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "CREATE INDEX ON failed, no such layer as `%s'.",
-                      papszTokens[3] );
-            CSLDestroy( papszTokens );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "CREATE INDEX ON failed, no such layer as `%s'.",
+                     papszTokens[3]);
+            CSLDestroy(papszTokens);
             return OGRERR_FAILURE;
         }
     }
@@ -4502,45 +4722,45 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
 /* -------------------------------------------------------------------- */
     if( poLayer->GetIndex() == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "CREATE INDEX ON not supported by this driver." );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "CREATE INDEX ON not supported by this driver.");
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Find the named field.                                           */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
+    int i = 0;  // Used after for.
+    for( ; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i )
     {
         if( EQUAL(papszTokens[5],
                   poLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef()) )
             break;
     }
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
 
     if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "`%s' failed, field not found.",
-                  pszSQLCommand );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "`%s' failed, field not found.",
+                 pszSQLCommand);
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Attempt to create the index.                                    */
 /* -------------------------------------------------------------------- */
-    OGRErr eErr;
-
-    eErr = poLayer->GetIndex()->CreateIndex( i );
+    OGRErr eErr = poLayer->GetIndex()->CreateIndex(i);
     if( eErr == OGRERR_NONE )
-        eErr = poLayer->GetIndex()->IndexAllFeatures( i );
+    {
+        eErr = poLayer->GetIndex()->IndexAllFeatures(i);
+    }
     else
     {
         if( strlen(CPLGetLastErrorMsg()) == 0 )
-            CPLError( CE_Failure, CPLE_AppDefined,
-                    "Cannot '%s'", pszSQLCommand);
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot '%s'", pszSQLCommand);
     }
 
     return eErr;
@@ -4558,37 +4778,37 @@ OGRErr GDALDataset::ProcessSQLCreateIndex( const char *pszSQLCommand )
 OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
 
 {
-    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+    char **papszTokens = CSLTokenizeString(pszSQLCommand);
 
 /* -------------------------------------------------------------------- */
 /*      Do some general syntax checking.                                */
 /* -------------------------------------------------------------------- */
     if( (CSLCount(papszTokens) != 4 && CSLCount(papszTokens) != 6)
-        || !EQUAL(papszTokens[0],"DROP")
-        || !EQUAL(papszTokens[1],"INDEX")
-        || !EQUAL(papszTokens[2],"ON")
-        || (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4],"USING")) )
-    {
-        CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Syntax error in DROP INDEX command.\n"
-                  "Was '%s'\n"
-                  "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
-                  pszSQLCommand );
+        || !EQUAL(papszTokens[0], "DROP")
+        || !EQUAL(papszTokens[1], "INDEX")
+        || !EQUAL(papszTokens[2], "ON")
+        || (CSLCount(papszTokens) == 6 && !EQUAL(papszTokens[4], "USING")) )
+    {
+        CSLDestroy(papszTokens);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Syntax error in DROP INDEX command.\n"
+                 "Was '%s'\n"
+                 "Should be of form 'DROP INDEX ON <table> [USING <field>]'",
+                 pszSQLCommand);
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Find the named layer.                                           */
 /* -------------------------------------------------------------------- */
-    int  i;
-    OGRLayer *poLayer=NULL;
+    OGRLayer *poLayer = NULL;
 
     {
-        GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
-        CPLMutexHolderD( psPrivate ? &(psPrivate->hMutex) : NULL );
+        GDALDatasetPrivate *psPrivate =
+            static_cast<GDALDatasetPrivate *>(m_hPrivateData);
+        CPLMutexHolderD(psPrivate ? &(psPrivate->hMutex) : NULL);
 
-        for( i = 0; i < GetLayerCount(); i++ )
+        for( int i = 0; i < GetLayerCount(); ++i )
         {
             poLayer = GetLayer(i);
 
@@ -4599,10 +4819,10 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
 
         if( poLayer == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "CREATE INDEX ON failed, no such layer as `%s'.",
-                      papszTokens[3] );
-            CSLDestroy( papszTokens );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "CREATE INDEX ON failed, no such layer as `%s'.",
+                     papszTokens[3]);
+            CSLDestroy(papszTokens);
             return OGRERR_FAILURE;
         }
     }
@@ -4612,28 +4832,26 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
 /* -------------------------------------------------------------------- */
     if( poLayer->GetIndex() == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Indexes not supported by this driver." );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Indexes not supported by this driver.");
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      If we were not given a field name, drop all indexes.            */
 /* -------------------------------------------------------------------- */
-    OGRErr eErr;
-
     if( CSLCount(papszTokens) == 4 )
     {
-        for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
+        for( int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i )
         {
             OGRAttrIndex *poAttrIndex;
 
             poAttrIndex = poLayer->GetIndex()->GetFieldIndex(i);
             if( poAttrIndex != NULL )
             {
-                eErr = poLayer->GetIndex()->DropIndex( i );
-                if( eErr != OGRERR_NONE )
+                const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
+                if(eErr != OGRERR_NONE)
                 {
                     CSLDestroy(papszTokens);
                     return eErr;
@@ -4648,27 +4866,27 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
 /* -------------------------------------------------------------------- */
 /*      Find the named field.                                           */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
+    int i = 0;  // Used after for.
+    for( ; i < poLayer->GetLayerDefn()->GetFieldCount(); ++i )
     {
         if( EQUAL(papszTokens[5],
                   poLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef()) )
             break;
     }
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
 
     if( i >= poLayer->GetLayerDefn()->GetFieldCount() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "`%s' failed, field not found.",
-                  pszSQLCommand );
+        CPLError(CE_Failure, CPLE_AppDefined, "`%s' failed, field not found.",
+                 pszSQLCommand);
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Attempt to drop the index.                                      */
 /* -------------------------------------------------------------------- */
-    eErr = poLayer->GetIndex()->DropIndex( i );
+    const OGRErr eErr = poLayer->GetIndex()->DropIndex(i);
 
     return eErr;
 }
@@ -4685,31 +4903,31 @@ OGRErr GDALDataset::ProcessSQLDropIndex( const char *pszSQLCommand )
 OGRErr GDALDataset::ProcessSQLDropTable( const char *pszSQLCommand )
 
 {
-    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+    char **papszTokens = CSLTokenizeString(pszSQLCommand);
 
 /* -------------------------------------------------------------------- */
 /*      Do some general syntax checking.                                */
 /* -------------------------------------------------------------------- */
     if( CSLCount(papszTokens) != 3
-        || !EQUAL(papszTokens[0],"DROP")
-        || !EQUAL(papszTokens[1],"TABLE") )
-    {
-        CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Syntax error in DROP TABLE command.\n"
-                  "Was '%s'\n"
-                  "Should be of form 'DROP TABLE <table>'",
-                  pszSQLCommand );
+        || !EQUAL(papszTokens[0], "DROP")
+        || !EQUAL(papszTokens[1], "TABLE") )
+    {
+        CSLDestroy(papszTokens);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Syntax error in DROP TABLE command.\n"
+                 "Was '%s'\n"
+                 "Should be of form 'DROP TABLE <table>'",
+                 pszSQLCommand);
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Find the named layer.                                           */
 /* -------------------------------------------------------------------- */
-    int  i;
-    OGRLayer *poLayer=NULL;
+    OGRLayer *poLayer = NULL;
 
-    for( i = 0; i < GetLayerCount(); i++ )
+    int i = 0;  // Used after for.
+    for( ; i < GetLayerCount(); ++i )
     {
         poLayer = GetLayer(i);
 
@@ -4720,35 +4938,36 @@ OGRErr GDALDataset::ProcessSQLDropTable( const char *pszSQLCommand )
 
     if( poLayer == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "DROP TABLE failed, no such layer as `%s'.",
-                  papszTokens[2] );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "DROP TABLE failed, no such layer as `%s'.", papszTokens[2]);
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
 
 /* -------------------------------------------------------------------- */
 /*      Delete it.                                                      */
 /* -------------------------------------------------------------------- */
 
-    return DeleteLayer( i );
+    return DeleteLayer(i);
 }
+//! @endcond
 
 /************************************************************************/
 /*                    GDALDatasetParseSQLType()                       */
 /************************************************************************/
 
 /* All arguments will be altered */
-static OGRFieldType GDALDatasetParseSQLType(char* pszType, int& nWidth, int &nPrecision)
+static OGRFieldType GDALDatasetParseSQLType(char *pszType, int &nWidth,
+                                            int &nPrecision)
 {
-    char* pszParenthesis = strchr(pszType, '(');
+    char *pszParenthesis = strchr(pszType, '(');
     if (pszParenthesis)
     {
         nWidth = atoi(pszParenthesis + 1);
         *pszParenthesis = '\0';
-        char* pszComma = strchr(pszParenthesis + 1, ',');
+        char *pszComma = strchr(pszParenthesis + 1, ',');
         if (pszComma)
             nPrecision = atoi(pszComma + 1);
     }
@@ -4785,11 +5004,10 @@ static OGRFieldType GDALDatasetParseSQLType(char* pszType, int& nWidth, int &nPr
              EQUAL(pszType, "DATETIME") /* unofficial alias */ )
         eType = OFTDateTime;
     else
-    {
         CPLError(CE_Warning, CPLE_NotSupported,
                  "Unsupported column type '%s'. Defaulting to VARCHAR",
                  pszType);
-    }
+
     return eType;
 }
 
@@ -4799,37 +5017,37 @@ static OGRFieldType GDALDatasetParseSQLType(char* pszType, int& nWidth, int &nPr
 /*      The correct syntax for adding a column in the OGR SQL           */
 /*      dialect is:                                                     */
 /*                                                                      */
-/*          ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype>*/
+/*       ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype> */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 OGRErr GDALDataset::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
 
 {
-    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+    char **papszTokens = CSLTokenizeString(pszSQLCommand);
 
 /* -------------------------------------------------------------------- */
 /*      Do some general syntax checking.                                */
 /* -------------------------------------------------------------------- */
-    const char* pszLayerName = NULL;
-    const char* pszColumnName = NULL;
-    char* pszType = NULL;
+    const char *pszLayerName = NULL;
+    const char *pszColumnName = NULL;
     int iTypeIndex = 0;
-    int nTokens = CSLCount(papszTokens);
+    const int nTokens = CSLCount(papszTokens);
 
     if( nTokens >= 7
-        && EQUAL(papszTokens[0],"ALTER")
-        && EQUAL(papszTokens[1],"TABLE")
-        && EQUAL(papszTokens[3],"ADD")
-        && EQUAL(papszTokens[4],"COLUMN"))
+        && EQUAL(papszTokens[0], "ALTER")
+        && EQUAL(papszTokens[1], "TABLE")
+        && EQUAL(papszTokens[3], "ADD")
+        && EQUAL(papszTokens[4], "COLUMN"))
     {
         pszLayerName = papszTokens[2];
         pszColumnName = papszTokens[5];
         iTypeIndex = 6;
     }
     else if( nTokens >= 6
-             && EQUAL(papszTokens[0],"ALTER")
-             && EQUAL(papszTokens[1],"TABLE")
-             && EQUAL(papszTokens[3],"ADD"))
+             && EQUAL(papszTokens[0], "ALTER")
+             && EQUAL(papszTokens[1], "TABLE")
+             && EQUAL(papszTokens[3], "ADD"))
     {
         pszLayerName = papszTokens[2];
         pszColumnName = papszTokens[4];
@@ -4837,12 +5055,13 @@ OGRErr GDALDataset::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
     }
     else
     {
-        CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Syntax error in ALTER TABLE ADD COLUMN command.\n"
-                  "Was '%s'\n"
-                  "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] <columnname> <columntype>'",
-                  pszSQLCommand );
+        CSLDestroy(papszTokens);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Syntax error in ALTER TABLE ADD COLUMN command.\n"
+                 "Was '%s'\n"
+                 "Should be of form 'ALTER TABLE <layername> ADD [COLUMN] "
+                 "<columnname> <columntype>'",
+                 pszSQLCommand);
         return OGRERR_FAILURE;
     }
 
@@ -4851,12 +5070,12 @@ OGRErr GDALDataset::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
 /*      with spaces                                                     */
 /* -------------------------------------------------------------------- */
     CPLString osType;
-    for(int i=iTypeIndex;i<nTokens;i++)
+    for( int i = iTypeIndex; i < nTokens; ++i )
     {
         osType += papszTokens[i];
         CPLFree(papszTokens[i]);
     }
-    pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
+    char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
     papszTokens[iTypeIndex + 1] = NULL;
 
 /* -------------------------------------------------------------------- */
@@ -4865,11 +5084,10 @@ OGRErr GDALDataset::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
     OGRLayer *poLayer = GetLayerByName(pszLayerName);
     if( poLayer == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s failed, no such layer as `%s'.",
-                  pszSQLCommand,
-                  pszLayerName );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s failed, no such layer as `%s'.", pszSQLCommand,
+                 pszLayerName);
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
@@ -4877,15 +5095,16 @@ OGRErr GDALDataset::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
 /*      Add column.                                                     */
 /* -------------------------------------------------------------------- */
 
-    int nWidth = 0, nPrecision = 0;
+    int nWidth = 0;
+    int nPrecision = 0;
     OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
     OGRFieldDefn oFieldDefn(pszColumnName, eType);
     oFieldDefn.SetWidth(nWidth);
     oFieldDefn.SetPrecision(nPrecision);
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
 
-    return poLayer->CreateField( &oFieldDefn );
+    return poLayer->CreateField(&oFieldDefn);
 }
 
 /************************************************************************/
@@ -4900,38 +5119,39 @@ OGRErr GDALDataset::ProcessSQLAlterTableAddColumn( const char *pszSQLCommand )
 OGRErr GDALDataset::ProcessSQLAlterTableDropColumn( const char *pszSQLCommand )
 
 {
-    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+    char **papszTokens = CSLTokenizeString(pszSQLCommand);
 
 /* -------------------------------------------------------------------- */
 /*      Do some general syntax checking.                                */
 /* -------------------------------------------------------------------- */
-    const char* pszLayerName = NULL;
-    const char* pszColumnName = NULL;
+    const char *pszLayerName = NULL;
+    const char *pszColumnName = NULL;
     if( CSLCount(papszTokens) == 6
-        && EQUAL(papszTokens[0],"ALTER")
-        && EQUAL(papszTokens[1],"TABLE")
-        && EQUAL(papszTokens[3],"DROP")
-        && EQUAL(papszTokens[4],"COLUMN"))
+        && EQUAL(papszTokens[0], "ALTER")
+        && EQUAL(papszTokens[1], "TABLE")
+        && EQUAL(papszTokens[3], "DROP")
+        && EQUAL(papszTokens[4], "COLUMN"))
     {
         pszLayerName = papszTokens[2];
         pszColumnName = papszTokens[5];
     }
     else if( CSLCount(papszTokens) == 5
-             && EQUAL(papszTokens[0],"ALTER")
-             && EQUAL(papszTokens[1],"TABLE")
-             && EQUAL(papszTokens[3],"DROP"))
+             && EQUAL(papszTokens[0], "ALTER")
+             && EQUAL(papszTokens[1], "TABLE")
+             && EQUAL(papszTokens[3], "DROP"))
     {
         pszLayerName = papszTokens[2];
         pszColumnName = papszTokens[4];
     }
     else
     {
-        CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Syntax error in ALTER TABLE DROP COLUMN command.\n"
-                  "Was '%s'\n"
-                  "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] <columnname>'",
-                  pszSQLCommand );
+        CSLDestroy(papszTokens);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Syntax error in ALTER TABLE DROP COLUMN command.\n"
+                 "Was '%s'\n"
+                 "Should be of form 'ALTER TABLE <layername> DROP [COLUMN] "
+                 "<columnname>'",
+                 pszSQLCommand);
         return OGRERR_FAILURE;
     }
 
@@ -4941,11 +5161,10 @@ OGRErr GDALDataset::ProcessSQLAlterTableDropColumn( const char *pszSQLCommand )
     OGRLayer *poLayer = GetLayerByName(pszLayerName);
     if( poLayer == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s failed, no such layer as `%s'.",
-                  pszSQLCommand,
-                  pszLayerName );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s failed, no such layer as `%s'.", pszSQLCommand,
+                 pszLayerName);
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
@@ -4956,22 +5175,20 @@ OGRErr GDALDataset::ProcessSQLAlterTableDropColumn( const char *pszSQLCommand )
     int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
     if( nFieldIndex < 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s failed, no such field as `%s'.",
-                  pszSQLCommand,
-                  pszColumnName );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s failed, no such field as `%s'.", pszSQLCommand,
+                 pszColumnName);
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Remove it.                                                      */
 /* -------------------------------------------------------------------- */
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
 
-    return poLayer->DeleteField( nFieldIndex );
+    return poLayer->DeleteField(nFieldIndex);
 }
 
 /************************************************************************/
@@ -4983,33 +5200,34 @@ OGRErr GDALDataset::ProcessSQLAlterTableDropColumn( const char *pszSQLCommand )
 /*       ALTER TABLE <layername> RENAME [COLUMN] <oldname> TO <newname> */
 /************************************************************************/
 
-OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand )
+OGRErr
+GDALDataset::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand )
 
 {
-    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+    char **papszTokens = CSLTokenizeString(pszSQLCommand);
 
 /* -------------------------------------------------------------------- */
 /*      Do some general syntax checking.                                */
 /* -------------------------------------------------------------------- */
-    const char* pszLayerName = NULL;
-    const char* pszOldColName = NULL;
-    const char* pszNewColName = NULL;
+    const char *pszLayerName = NULL;
+    const char *pszOldColName = NULL;
+    const char *pszNewColName = NULL;
     if( CSLCount(papszTokens) == 8
-        && EQUAL(papszTokens[0],"ALTER")
-        && EQUAL(papszTokens[1],"TABLE")
-        && EQUAL(papszTokens[3],"RENAME")
-        && EQUAL(papszTokens[4],"COLUMN")
-        && EQUAL(papszTokens[6],"TO"))
+        && EQUAL(papszTokens[0], "ALTER")
+        && EQUAL(papszTokens[1], "TABLE")
+        && EQUAL(papszTokens[3], "RENAME")
+        && EQUAL(papszTokens[4], "COLUMN")
+        && EQUAL(papszTokens[6], "TO"))
     {
         pszLayerName = papszTokens[2];
         pszOldColName = papszTokens[5];
         pszNewColName = papszTokens[7];
     }
     else if( CSLCount(papszTokens) == 7
-             && EQUAL(papszTokens[0],"ALTER")
-             && EQUAL(papszTokens[1],"TABLE")
-             && EQUAL(papszTokens[3],"RENAME")
-             && EQUAL(papszTokens[5],"TO"))
+             && EQUAL(papszTokens[0], "ALTER")
+             && EQUAL(papszTokens[1], "TABLE")
+             && EQUAL(papszTokens[3], "RENAME")
+             && EQUAL(papszTokens[5], "TO"))
     {
         pszLayerName = papszTokens[2];
         pszOldColName = papszTokens[4];
@@ -5017,12 +5235,13 @@ OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand
     }
     else
     {
-        CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
-                  "Was '%s'\n"
-                  "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] <columnname> TO <newname>'",
-                  pszSQLCommand );
+        CSLDestroy(papszTokens);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Syntax error in ALTER TABLE RENAME COLUMN command.\n"
+                 "Was '%s'\n"
+                 "Should be of form 'ALTER TABLE <layername> RENAME [COLUMN] "
+                 "<columnname> TO <newname>'",
+                 pszSQLCommand);
         return OGRERR_FAILURE;
     }
 
@@ -5032,11 +5251,10 @@ OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand
     OGRLayer *poLayer = GetLayerByName(pszLayerName);
     if( poLayer == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s failed, no such layer as `%s'.",
-                  pszSQLCommand,
-                  pszLayerName );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s failed, no such layer as `%s'.", pszSQLCommand,
+                 pszLayerName);
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
@@ -5044,27 +5262,29 @@ OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand
 /*      Find the field.                                                 */
 /* -------------------------------------------------------------------- */
 
-    int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
+    const int nFieldIndex =
+        poLayer->GetLayerDefn()->GetFieldIndex(pszOldColName);
     if( nFieldIndex < 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s failed, no such field as `%s'.",
-                  pszSQLCommand,
-                  pszOldColName );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s failed, no such field as `%s'.", pszSQLCommand,
+                 pszOldColName);
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Rename column.                                                  */
 /* -------------------------------------------------------------------- */
-    OGRFieldDefn* poOldFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
+    OGRFieldDefn *poOldFieldDefn =
+        poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
     OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
     oNewFieldDefn.SetName(pszNewColName);
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
 
-    return poLayer->AlterFieldDefn( nFieldIndex, &oNewFieldDefn, ALTER_NAME_FLAG );
+    return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn,
+                                   ALTER_NAME_FLAG);
 }
 
 /************************************************************************/
@@ -5079,33 +5299,32 @@ OGRErr GDALDataset::ProcessSQLAlterTableRenameColumn( const char *pszSQLCommand
 OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
 
 {
-    char **papszTokens = CSLTokenizeString( pszSQLCommand );
+    char **papszTokens = CSLTokenizeString(pszSQLCommand);
 
 /* -------------------------------------------------------------------- */
 /*      Do some general syntax checking.                                */
 /* -------------------------------------------------------------------- */
-    const char* pszLayerName = NULL;
-    const char* pszColumnName = NULL;
-    char* pszType = NULL;
+    const char *pszLayerName = NULL;
+    const char *pszColumnName = NULL;
     int iTypeIndex = 0;
-    int nTokens = CSLCount(papszTokens);
+    const int nTokens = CSLCount(papszTokens);
 
     if( nTokens >= 8
-        && EQUAL(papszTokens[0],"ALTER")
-        && EQUAL(papszTokens[1],"TABLE")
-        && EQUAL(papszTokens[3],"ALTER")
-        && EQUAL(papszTokens[4],"COLUMN")
-        && EQUAL(papszTokens[6],"TYPE"))
+        && EQUAL(papszTokens[0], "ALTER")
+        && EQUAL(papszTokens[1], "TABLE")
+        && EQUAL(papszTokens[3], "ALTER")
+        && EQUAL(papszTokens[4], "COLUMN")
+        && EQUAL(papszTokens[6], "TYPE"))
     {
         pszLayerName = papszTokens[2];
         pszColumnName = papszTokens[5];
         iTypeIndex = 7;
     }
     else if( nTokens >= 7
-             && EQUAL(papszTokens[0],"ALTER")
-             && EQUAL(papszTokens[1],"TABLE")
-             && EQUAL(papszTokens[3],"ALTER")
-             && EQUAL(papszTokens[5],"TYPE"))
+             && EQUAL(papszTokens[0], "ALTER")
+             && EQUAL(papszTokens[1], "TABLE")
+             && EQUAL(papszTokens[3], "ALTER")
+             && EQUAL(papszTokens[5], "TYPE"))
     {
         pszLayerName = papszTokens[2];
         pszColumnName = papszTokens[4];
@@ -5113,12 +5332,13 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
     }
     else
     {
-        CSLDestroy( papszTokens );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
-                  "Was '%s'\n"
-                  "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] <columnname> TYPE <columntype>'",
-                  pszSQLCommand );
+        CSLDestroy(papszTokens);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Syntax error in ALTER TABLE ALTER COLUMN command.\n"
+                 "Was '%s'\n"
+                 "Should be of form 'ALTER TABLE <layername> ALTER [COLUMN] "
+                 "<columnname> TYPE <columntype>'",
+                 pszSQLCommand);
         return OGRERR_FAILURE;
     }
 
@@ -5127,12 +5347,12 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
 /*      with spaces                                                     */
 /* -------------------------------------------------------------------- */
     CPLString osType;
-    for(int i=iTypeIndex;i<nTokens;i++)
+    for( int i = iTypeIndex; i < nTokens; ++i )
     {
         osType += papszTokens[i];
         CPLFree(papszTokens[i]);
     }
-    pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
+    char *pszType = papszTokens[iTypeIndex] = CPLStrdup(osType);
     papszTokens[iTypeIndex + 1] = NULL;
 
 /* -------------------------------------------------------------------- */
@@ -5141,11 +5361,10 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
     OGRLayer *poLayer = GetLayerByName(pszLayerName);
     if( poLayer == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s failed, no such layer as `%s'.",
-                  pszSQLCommand,
-                  pszLayerName );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s failed, no such layer as `%s'.", pszSQLCommand,
+                 pszLayerName);
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
@@ -5153,14 +5372,14 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
 /*      Find the field.                                                 */
 /* -------------------------------------------------------------------- */
 
-    int nFieldIndex = poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
+    const int nFieldIndex =
+        poLayer->GetLayerDefn()->GetFieldIndex(pszColumnName);
     if( nFieldIndex < 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s failed, no such field as `%s'.",
-                  pszSQLCommand,
-                  pszColumnName );
-        CSLDestroy( papszTokens );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s failed, no such field as `%s'.", pszSQLCommand,
+                 pszColumnName);
+        CSLDestroy(papszTokens);
         return OGRERR_FAILURE;
     }
 
@@ -5168,10 +5387,12 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
 /*      Alter column.                                                   */
 /* -------------------------------------------------------------------- */
 
-    OGRFieldDefn* poOldFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
+    OGRFieldDefn *poOldFieldDefn =
+        poLayer->GetLayerDefn()->GetFieldDefn(nFieldIndex);
     OGRFieldDefn oNewFieldDefn(poOldFieldDefn);
 
-    int nWidth = 0, nPrecision = 0;
+    int nWidth = 0;
+    int nPrecision = 0;
     OGRFieldType eType = GDALDatasetParseSQLType(pszType, nWidth, nPrecision);
     oNewFieldDefn.SetType(eType);
     oNewFieldDefn.SetWidth(nWidth);
@@ -5184,13 +5405,14 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
         poOldFieldDefn->GetPrecision() != oNewFieldDefn.GetPrecision())
         l_nFlags |= ALTER_WIDTH_PRECISION_FLAG;
 
-    CSLDestroy( papszTokens );
+    CSLDestroy(papszTokens);
 
     if (l_nFlags == 0)
         return OGRERR_NONE;
-    else
-        return poLayer->AlterFieldDefn( nFieldIndex, &oNewFieldDefn, l_nFlags );
+
+    return poLayer->AlterFieldDefn(nFieldIndex, &oNewFieldDefn, l_nFlags);
 }
+//! @endcond
 
 /************************************************************************/
 /*                             ExecuteSQL()                             */
@@ -5221,38 +5443,40 @@ OGRErr GDALDataset::ProcessSQLAlterTableAlterColumn( const char *pszSQLCommand )
  @param pszStatement the SQL statement to execute.
  @param poSpatialFilter geometry which represents a spatial filter. Can be NULL.
  @param pszDialect allows control of the statement dialect. If set to NULL, the
-OGR SQL engine will be used, except for RDBMS drivers that will use their dedicated SQL engine,
-unless OGRSQL is explicitly passed as the dialect. Starting with OGR 1.10, the SQLITE dialect
-can also be used.
+ OGR SQL engine will be used, except for RDBMS drivers that will use their
+ dedicated SQL engine, unless OGRSQL is explicitly passed as the
+ dialect. Starting with OGR 1.10, the SQLITE dialect can also be used.
 
  @return an OGRLayer containing the results of the query.  Deallocate with
  ReleaseResultSet().
 
 */
 
-OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
-                                      OGRGeometry *poSpatialFilter,
-                                      const char *pszDialect )
+OGRLayer *GDALDataset::ExecuteSQL( const char *pszStatement,
+                                   OGRGeometry *poSpatialFilter,
+                                   const char *pszDialect )
 
 {
     return ExecuteSQL(pszStatement, poSpatialFilter, pszDialect, NULL);
 }
 
-OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
-                                    OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect,
-                                    swq_select_parse_options* poSelectParseOptions)
+//! @cond Doxygen_Suppress
+OGRLayer *
+GDALDataset::ExecuteSQL( const char *pszStatement,
+                         OGRGeometry *poSpatialFilter,
+                         const char *pszDialect,
+                         swq_select_parse_options *poSelectParseOptions )
 
 {
-    swq_select *psSelectInfo = NULL;
-
     if( pszDialect != NULL && EQUAL(pszDialect, "SQLite") )
     {
 #ifdef SQLITE_ENABLED
-        return OGRSQLiteExecuteSQL( this, pszStatement, poSpatialFilter, pszDialect );
+        return OGRSQLiteExecuteSQL(this, pszStatement, poSpatialFilter,
+                                   pszDialect);
 #else
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "The SQLite driver needs to be compiled to support the SQLite SQL dialect");
+                 "The SQLite driver needs to be compiled to support the "
+                 "SQLite SQL dialect");
         return NULL;
 #endif
     }
@@ -5262,7 +5486,7 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
     if( STARTS_WITH_CI(pszStatement, "CREATE INDEX") )
     {
-        ProcessSQLCreateIndex( pszStatement );
+        ProcessSQLCreateIndex(pszStatement);
         return NULL;
     }
 
@@ -5271,7 +5495,7 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
     if( STARTS_WITH_CI(pszStatement, "DROP INDEX") )
     {
-        ProcessSQLDropIndex( pszStatement );
+        ProcessSQLDropIndex(pszStatement);
         return NULL;
     }
 
@@ -5280,7 +5504,7 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
     if( STARTS_WITH_CI(pszStatement, "DROP TABLE") )
     {
-        ProcessSQLDropTable( pszStatement );
+        ProcessSQLDropTable(pszStatement);
         return NULL;
     }
 
@@ -5289,40 +5513,39 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
     if( STARTS_WITH_CI(pszStatement, "ALTER TABLE") )
     {
-        char **papszTokens = CSLTokenizeString( pszStatement );
+        char **papszTokens = CSLTokenizeString(pszStatement);
         if( CSLCount(papszTokens) >= 4 &&
-            EQUAL(papszTokens[3],"ADD") )
+            EQUAL(papszTokens[3], "ADD") )
         {
-            ProcessSQLAlterTableAddColumn( pszStatement );
+            ProcessSQLAlterTableAddColumn(pszStatement);
             CSLDestroy(papszTokens);
             return NULL;
         }
         else if( CSLCount(papszTokens) >= 4 &&
-                 EQUAL(papszTokens[3],"DROP") )
+                 EQUAL(papszTokens[3], "DROP") )
         {
             ProcessSQLAlterTableDropColumn( pszStatement );
             CSLDestroy(papszTokens);
             return NULL;
         }
         else if( CSLCount(papszTokens) >= 4 &&
-                 EQUAL(papszTokens[3],"RENAME") )
+                 EQUAL(papszTokens[3], "RENAME") )
         {
-            ProcessSQLAlterTableRenameColumn( pszStatement );
+            ProcessSQLAlterTableRenameColumn(pszStatement);
             CSLDestroy(papszTokens);
             return NULL;
         }
         else if( CSLCount(papszTokens) >= 4 &&
-                 EQUAL(papszTokens[3],"ALTER") )
+                 EQUAL(papszTokens[3], "ALTER") )
         {
-            ProcessSQLAlterTableAlterColumn( pszStatement );
+            ProcessSQLAlterTableAlterColumn(pszStatement);
             CSLDestroy(papszTokens);
             return NULL;
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unsupported ALTER TABLE command : %s",
-                      pszStatement );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unsupported ALTER TABLE command : %s", pszStatement);
             CSLDestroy(papszTokens);
             return NULL;
         }
@@ -5331,8 +5554,8 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
 /*      Preparse the SQL statement.                                     */
 /* -------------------------------------------------------------------- */
-    psSelectInfo = new swq_select();
-    swq_custom_func_registrar* poCustomFuncRegistrar = NULL;
+    swq_select *psSelectInfo = new swq_select();
+    swq_custom_func_registrar *poCustomFuncRegistrar = NULL;
     if( poSelectParseOptions != NULL )
         poCustomFuncRegistrar = poSelectParseOptions->poCustomFuncRegistrar;
     if( psSelectInfo->preparse( pszStatement,
@@ -5347,56 +5570,50 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
     if( psSelectInfo->poOtherSelect == NULL )
     {
-        return BuildLayerFromSelectInfo(psSelectInfo,
-                                        poSpatialFilter,
-                                        pszDialect,
-                                        poSelectParseOptions);
+        return BuildLayerFromSelectInfo(psSelectInfo, poSpatialFilter,
+                                        pszDialect, poSelectParseOptions);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Build result union layer.                                       */
 /* -------------------------------------------------------------------- */
     int nSrcLayers = 0;
-    OGRLayer** papoSrcLayers = NULL;
+    OGRLayer **papoSrcLayers = NULL;
 
     do
     {
-        swq_select* psNextSelectInfo = psSelectInfo->poOtherSelect;
+        swq_select *psNextSelectInfo = psSelectInfo->poOtherSelect;
         psSelectInfo->poOtherSelect = NULL;
 
-        OGRLayer* poLayer = BuildLayerFromSelectInfo(psSelectInfo,
-                                                     poSpatialFilter,
-                                                     pszDialect,
-                                                     poSelectParseOptions);
+        OGRLayer *poLayer = BuildLayerFromSelectInfo(
+            psSelectInfo, poSpatialFilter, pszDialect, poSelectParseOptions);
         if( poLayer == NULL )
         {
-            /* Each source layer owns an independent select info. */
-            for(int i=0;i<nSrcLayers;i++)
+            // Each source layer owns an independent select info.
+            for( int i = 0; i < nSrcLayers; ++i )
                 delete papoSrcLayers[i];
             CPLFree(papoSrcLayers);
 
-            /* So we just have to destroy the remaining select info */
+            // So we just have to destroy the remaining select info.
             delete psNextSelectInfo;
 
             return NULL;
         }
         else
         {
-            papoSrcLayers = (OGRLayer**) CPLRealloc(papoSrcLayers,
-                                sizeof(OGRLayer*) * (nSrcLayers + 1));
+            papoSrcLayers = static_cast<OGRLayer **>(CPLRealloc(
+                papoSrcLayers, sizeof(OGRLayer *) * (nSrcLayers + 1)));
             papoSrcLayers[nSrcLayers] = poLayer;
-            nSrcLayers ++;
+            ++nSrcLayers;
 
             psSelectInfo = psNextSelectInfo;
         }
     }
     while( psSelectInfo != NULL );
 
-    return new OGRUnionLayer("SELECT",
-                                nSrcLayers,
-                                papoSrcLayers,
-                                TRUE);
+    return new OGRUnionLayer("SELECT", nSrcLayers, papoSrcLayers, TRUE);
 }
+//! @endcond
 
 /************************************************************************/
 /*                        BuildLayerFromSelectInfo()                    */
@@ -5405,26 +5622,24 @@ OGRLayer * GDALDataset::ExecuteSQL( const char *pszStatement,
 struct GDALSQLParseInfo
 {
     swq_field_list sFieldList;
-    int            nExtraDSCount;
-    GDALDataset**  papoExtraDS;
-    char          *pszWHERE;
+    int nExtraDSCount;
+    GDALDataset **papoExtraDS;
+    char *pszWHERE;
 };
 
-OGRLayer* GDALDataset::BuildLayerFromSelectInfo(swq_select* psSelectInfo,
-                                                OGRGeometry *poSpatialFilter,
-                                                const char *pszDialect,
-                                                swq_select_parse_options* poSelectParseOptions)
+OGRLayer *GDALDataset::BuildLayerFromSelectInfo(
+    swq_select *psSelectInfo, OGRGeometry *poSpatialFilter,
+    const char *pszDialect, swq_select_parse_options *poSelectParseOptions)
 {
     OGRGenSQLResultsLayer *poResults = NULL;
-    GDALSQLParseInfo* psParseInfo = BuildParseInfo(psSelectInfo,
-                                                   poSelectParseOptions);
+    GDALSQLParseInfo *psParseInfo =
+        BuildParseInfo(psSelectInfo, poSelectParseOptions);
 
     if( psParseInfo )
     {
-        poResults = new OGRGenSQLResultsLayer( this, psSelectInfo,
-                                               poSpatialFilter,
-                                               psParseInfo->pszWHERE,
-                                               pszDialect );
+        poResults =
+            new OGRGenSQLResultsLayer(this, psSelectInfo, poSpatialFilter,
+                                      psParseInfo->pszWHERE, pszDialect);
     }
     else
     {
@@ -5439,90 +5654,93 @@ OGRLayer* GDALDataset::BuildLayerFromSelectInfo(swq_select* psSelectInfo,
 /*                             DestroyParseInfo()                       */
 /************************************************************************/
 
-void GDALDataset::DestroyParseInfo(GDALSQLParseInfo* psParseInfo )
+//! @cond Doxygen_Suppress
+void GDALDataset::DestroyParseInfo(GDALSQLParseInfo *psParseInfo)
 {
-    if( psParseInfo != NULL )
-    {
-        CPLFree( psParseInfo->sFieldList.names );
-        CPLFree( psParseInfo->sFieldList.types );
-        CPLFree( psParseInfo->sFieldList.table_ids );
-        CPLFree( psParseInfo->sFieldList.ids );
+    if( psParseInfo == NULL )
+        return;
 
-        /* Release the datasets we have opened with OGROpenShared() */
-        /* It is safe to do that as the 'new OGRGenSQLResultsLayer' itself */
-        /* has taken a reference on them, which it will release in its */
-        /* destructor */
-        for(int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; iEDS++)
-            GDALClose( (GDALDatasetH)psParseInfo->papoExtraDS[iEDS] );
-        CPLFree(psParseInfo->papoExtraDS);
+    CPLFree(psParseInfo->sFieldList.names);
+    CPLFree(psParseInfo->sFieldList.types);
+    CPLFree(psParseInfo->sFieldList.table_ids);
+    CPLFree(psParseInfo->sFieldList.ids);
 
-        CPLFree(psParseInfo->pszWHERE);
+    // Release the datasets we have opened with OGROpenShared()
+    // It is safe to do that as the 'new OGRGenSQLResultsLayer' itself
+    // has taken a reference on them, which it will release in its
+    // destructor.
+    for( int iEDS = 0; iEDS < psParseInfo->nExtraDSCount; ++iEDS )
+        GDALClose(psParseInfo->papoExtraDS[iEDS]);
 
-        CPLFree(psParseInfo);
-    }
+    CPLFree(psParseInfo->papoExtraDS);
+    CPLFree(psParseInfo->pszWHERE);
+    CPLFree(psParseInfo);
 }
 
 /************************************************************************/
 /*                            BuildParseInfo()                          */
 /************************************************************************/
 
-GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
-                                              swq_select_parse_options* poSelectParseOptions)
+GDALSQLParseInfo *
+GDALDataset::BuildParseInfo(swq_select *psSelectInfo,
+                            swq_select_parse_options *poSelectParseOptions)
 {
-    int            nFIDIndex = 0;
+    int nFIDIndex = 0;
 
-    GDALSQLParseInfo* psParseInfo = (GDALSQLParseInfo*)CPLCalloc(1, sizeof(GDALSQLParseInfo));
+    GDALSQLParseInfo *psParseInfo =
+        static_cast<GDALSQLParseInfo *>(CPLCalloc(1, sizeof(GDALSQLParseInfo)));
 
 /* -------------------------------------------------------------------- */
 /*      Validate that all the source tables are recognized, count       */
 /*      fields.                                                         */
 /* -------------------------------------------------------------------- */
-    int  nFieldCount = 0, iTable, iField;
+    int nFieldCount = 0;
 
-    for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
+    for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
     {
         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
-        OGRLayer *poSrcLayer;
         GDALDataset *poTableDS = this;
 
         if( psTableDef->data_source != NULL )
         {
-            poTableDS = (GDALDataset *)
-                OGROpenShared( psTableDef->data_source, FALSE, NULL );
+            poTableDS = reinterpret_cast<GDALDataset *>(
+                OGROpenShared(psTableDef->data_source, FALSE, NULL));
             if( poTableDS == NULL )
             {
                 if( strlen(CPLGetLastErrorMsg()) == 0 )
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Unable to open secondary datasource\n"
-                              "`%s' required by JOIN.",
-                              psTableDef->data_source );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Unable to open secondary datasource "
+                             "`%s' required by JOIN.",
+                             psTableDef->data_source);
 
                 DestroyParseInfo(psParseInfo);
                 return NULL;
             }
 
-            /* Keep in an array to release at the end of this function */
-            psParseInfo->papoExtraDS = (GDALDataset** )CPLRealloc(
-                               psParseInfo->papoExtraDS,
-                               sizeof(GDALDataset*) * (psParseInfo->nExtraDSCount + 1));
+            // Keep in an array to release at the end of this function.
+            psParseInfo->papoExtraDS = static_cast<GDALDataset **>(CPLRealloc(
+                psParseInfo->papoExtraDS,
+                sizeof(GDALDataset *) * (psParseInfo->nExtraDSCount + 1)));
             psParseInfo->papoExtraDS[psParseInfo->nExtraDSCount++] = poTableDS;
         }
 
-        poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name );
+        OGRLayer *poSrcLayer =
+            poTableDS->GetLayerByName(psTableDef->table_name);
 
         if( poSrcLayer == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "SELECT from table %s failed, no such table/featureclass.",
-                      psTableDef->table_name );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "SELECT from table %s failed, no such table/featureclass.",
+                     psTableDef->table_name);
 
             DestroyParseInfo(psParseInfo);
             return NULL;
         }
 
         nFieldCount += poSrcLayer->GetLayerDefn()->GetFieldCount();
-        if( iTable == 0 || (poSelectParseOptions &&
-                            poSelectParseOptions->bAddSecondaryTablesGeometryFields) )
+        if( iTable == 0 ||
+            (poSelectParseOptions &&
+            poSelectParseOptions->bAddSecondaryTablesGeometryFields) )
             nFieldCount += poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
     }
 
@@ -5534,38 +5752,41 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
     psParseInfo->sFieldList.table_defs = psSelectInfo->table_defs;
 
     psParseInfo->sFieldList.count = 0;
-    psParseInfo->sFieldList.names = (char **) CPLMalloc( sizeof(char *) * (nFieldCount+SPECIAL_FIELD_COUNT) );
-    psParseInfo->sFieldList.types = (swq_field_type *)
-        CPLMalloc( sizeof(swq_field_type) * (nFieldCount+SPECIAL_FIELD_COUNT) );
-    psParseInfo->sFieldList.table_ids = (int *)
-        CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
-    psParseInfo->sFieldList.ids = (int *)
-        CPLMalloc( sizeof(int) * (nFieldCount+SPECIAL_FIELD_COUNT) );
+    psParseInfo->sFieldList.names = static_cast<char **>(
+        CPLMalloc(sizeof(char *) * (nFieldCount + SPECIAL_FIELD_COUNT)));
+    psParseInfo->sFieldList.types = static_cast<swq_field_type *>(CPLMalloc(
+        sizeof(swq_field_type) * (nFieldCount + SPECIAL_FIELD_COUNT)));
+    psParseInfo->sFieldList.table_ids = static_cast<int *>(
+        CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
+    psParseInfo->sFieldList.ids = static_cast<int *>(
+        CPLMalloc(sizeof(int) * (nFieldCount + SPECIAL_FIELD_COUNT)));
 
     bool bIsFID64 = false;
-    for( iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
+    for( int iTable = 0; iTable < psSelectInfo->table_count; iTable++ )
     {
         swq_table_def *psTableDef = psSelectInfo->table_defs + iTable;
         GDALDataset *poTableDS = this;
-        OGRLayer *poSrcLayer;
 
         if( psTableDef->data_source != NULL )
         {
-            poTableDS = (GDALDataset *)
-                OGROpenShared( psTableDef->data_source, FALSE, NULL );
-            CPLAssert( poTableDS != NULL );
+            poTableDS = reinterpret_cast<GDALDataset *>(
+                OGROpenShared(psTableDef->data_source, FALSE, NULL));
+            CPLAssert(poTableDS != NULL);
             poTableDS->Dereference();
         }
 
-        poSrcLayer = poTableDS->GetLayerByName( psTableDef->table_name );
+        OGRLayer *poSrcLayer =
+            poTableDS->GetLayerByName(psTableDef->table_name);
 
-        for( iField = 0;
+        for( int iField = 0;
              iField < poSrcLayer->GetLayerDefn()->GetFieldCount();
              iField++ )
         {
-            OGRFieldDefn *poFDefn=poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
-            int iOutField = psParseInfo->sFieldList.count++;
-            psParseInfo->sFieldList.names[iOutField] = (char *) poFDefn->GetNameRef();
+            OGRFieldDefn *poFDefn =
+                poSrcLayer->GetLayerDefn()->GetFieldDefn(iField);
+            const int iOutField = psParseInfo->sFieldList.count++;
+            psParseInfo->sFieldList.names[iOutField] =
+                const_cast<char *>(poFDefn->GetNameRef());
             if( poFDefn->GetType() == OFTInteger )
             {
                 if( poFDefn->GetSubType() == OFSTBoolean )
@@ -5597,25 +5818,30 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
             psParseInfo->sFieldList.ids[iOutField] = iField;
         }
 
-        if( iTable == 0 || (poSelectParseOptions &&
-                            poSelectParseOptions->bAddSecondaryTablesGeometryFields) )
+        if( iTable == 0 ||
+            (poSelectParseOptions &&
+             poSelectParseOptions->bAddSecondaryTablesGeometryFields) )
         {
             nFIDIndex = psParseInfo->sFieldList.count;
 
-            for( iField = 0;
+            for( int iField = 0;
                  iField < poSrcLayer->GetLayerDefn()->GetGeomFieldCount();
                  iField++ )
             {
-                OGRGeomFieldDefn *poFDefn=poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
-                int iOutField = psParseInfo->sFieldList.count++;
-                psParseInfo->sFieldList.names[iOutField] = (char *) poFDefn->GetNameRef();
+                OGRGeomFieldDefn *poFDefn =
+                    poSrcLayer->GetLayerDefn()->GetGeomFieldDefn(iField);
+                const int iOutField = psParseInfo->sFieldList.count++;
+                psParseInfo->sFieldList.names[iOutField] =
+                    const_cast<char *>(poFDefn->GetNameRef());
                 if( *psParseInfo->sFieldList.names[iOutField] == '\0' )
-                    psParseInfo->sFieldList.names[iOutField] = (char*) OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME;
+                    psParseInfo->sFieldList.names[iOutField] =
+                        const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
                 psParseInfo->sFieldList.types[iOutField] = SWQ_GEOMETRY;
 
                 psParseInfo->sFieldList.table_ids[iOutField] = iTable;
                 psParseInfo->sFieldList.ids[iOutField] =
-                    GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poSrcLayer->GetLayerDefn(), iField);
+                    GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(
+                        poSrcLayer->GetLayerDefn(), iField);
             }
         }
 
@@ -5629,28 +5855,34 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
 /* -------------------------------------------------------------------- */
 /*      Expand '*' in 'SELECT *' now before we add the pseudo fields    */
 /* -------------------------------------------------------------------- */
-    int bAlwaysPrefixWithTableName = poSelectParseOptions &&
-                                     poSelectParseOptions->bAlwaysPrefixWithTableName;
-    if( psSelectInfo->expand_wildcard( &psParseInfo->sFieldList,
-                                       bAlwaysPrefixWithTableName)  != CE_None )
+    const bool bAlwaysPrefixWithTableName =
+        poSelectParseOptions &&
+        poSelectParseOptions->bAlwaysPrefixWithTableName;
+    if( psSelectInfo->expand_wildcard(&psParseInfo->sFieldList,
+                                      bAlwaysPrefixWithTableName) != CE_None )
     {
         DestroyParseInfo(psParseInfo);
         return NULL;
     }
 
-    for (iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
+    for (int iField = 0; iField < SPECIAL_FIELD_COUNT; iField++)
     {
-        psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] = (char*) SpecialFieldNames[iField];
-        psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] = (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64: SpecialFieldTypes[iField];
+        psParseInfo->sFieldList.names[psParseInfo->sFieldList.count] =
+            const_cast<char *>(SpecialFieldNames[iField]);
+        psParseInfo->sFieldList.types[psParseInfo->sFieldList.count] =
+            (iField == SPF_FID && bIsFID64) ? SWQ_INTEGER64
+                                            : SpecialFieldTypes[iField];
         psParseInfo->sFieldList.table_ids[psParseInfo->sFieldList.count] = 0;
-        psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] = nFIDIndex + iField;
+        psParseInfo->sFieldList.ids[psParseInfo->sFieldList.count] =
+            nFIDIndex + iField;
         psParseInfo->sFieldList.count++;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Finish the parse operation.                                     */
 /* -------------------------------------------------------------------- */
-    if( psSelectInfo->parse( &psParseInfo->sFieldList, poSelectParseOptions ) != CE_None )
+    if( psSelectInfo->parse(&psParseInfo->sFieldList, poSelectParseOptions) !=
+        CE_None )
     {
         DestroyParseInfo(psParseInfo);
         return NULL;
@@ -5661,12 +5893,14 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
 /* -------------------------------------------------------------------- */
     if( psSelectInfo->where_expr != NULL )
     {
-        psParseInfo->pszWHERE = psSelectInfo->where_expr->Unparse( &psParseInfo->sFieldList, '"' );
-        //CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
+        psParseInfo->pszWHERE =
+            psSelectInfo->where_expr->Unparse(&psParseInfo->sFieldList, '"');
+        // CPLDebug( "OGR", "Unparse() -> %s", pszWHERE );
     }
 
     return psParseInfo;
 }
+//! @endcond
 
 /************************************************************************/
 /*                          ReleaseResultSet()                          */
@@ -5687,7 +5921,7 @@ GDALSQLParseInfo* GDALDataset::BuildParseInfo(swq_select* psSelectInfo,
  @param poResultsSet the result of a previous ExecuteSQL() call.
 */
 
-void GDALDataset::ReleaseResultSet( OGRLayer * poResultsSet )
+void GDALDataset::ReleaseResultSet( OGRLayer *poResultsSet )
 
 {
     delete poResultsSet;
@@ -5709,10 +5943,7 @@ void GDALDataset::ReleaseResultSet( OGRLayer * poResultsSet )
  caller.
 */
 
-OGRStyleTable *GDALDataset::GetStyleTable()
-{
-    return m_poStyleTable;
-}
+OGRStyleTable *GDALDataset::GetStyleTable() { return m_poStyleTable; }
 
 /************************************************************************/
 /*                         SetStyleTableDirectly()                      */
@@ -5724,8 +5955,8 @@ OGRStyleTable *GDALDataset::GetStyleTable()
  This method operate exactly as SetStyleTable() except that it
  assumes ownership of the passed table.
 
- This method is the same as the C function GDALDatasetSetStyleTableDirectly() and
- the deprecated OGR_DS_SetStyleTableDirectly().
+ This method is the same as the C function GDALDatasetSetStyleTableDirectly()
+ and the deprecated OGR_DS_SetStyleTableDirectly().
 
  In GDAL 1.X, this method used to be in the OGRDataSource class.
 
@@ -5770,12 +6001,13 @@ void GDALDataset::SetStyleTable(OGRStyleTable *poStyleTable)
 /*                         IsGenericSQLDialect()                        */
 /************************************************************************/
 
-int GDALDataset::IsGenericSQLDialect(const char* pszDialect)
+//! @cond Doxygen_Suppress
+int GDALDataset::IsGenericSQLDialect(const char *pszDialect)
 {
-    return ( pszDialect != NULL && (EQUAL(pszDialect,"OGRSQL") ||
-                                    EQUAL(pszDialect,"SQLITE")) );
-
+    return pszDialect != NULL &&
+           (EQUAL(pszDialect, "OGRSQL") || EQUAL(pszDialect, "SQLITE"));
 }
+//! @endcond
 
 /************************************************************************/
 /*                            GetLayerCount()                           */
@@ -5792,16 +6024,14 @@ int GDALDataset::IsGenericSQLDialect(const char* pszDialect)
  @return layer count.
 */
 
-int GDALDataset::GetLayerCount()
-{
-    return 0;
-}
+int GDALDataset::GetLayerCount() { return 0; }
 
 /************************************************************************/
 /*                                GetLayer()                            */
 /************************************************************************/
 
 /**
+ \fn GDALDataset::GetLayer(int)
  \brief Fetch a layer by index.
 
  The returned layer remains owned by the
@@ -5817,9 +6047,294 @@ int GDALDataset::GetLayerCount()
  @return the layer, or NULL if iLayer is out of range or an error occurs.
 */
 
-OGRLayer* GDALDataset::GetLayer(CPL_UNUSED int iLayer)
+OGRLayer *GDALDataset::GetLayer(CPL_UNUSED int iLayer) { return NULL; }
+
+/************************************************************************/
+/*                           ResetReading()                             */
+/************************************************************************/
+
+/**
+ \brief Reset feature reading to start on the first feature.
+
+ This affects GetNextFeature().
+
+ Depending on drivers, this may also have the side effect of calling
+ OGRLayer::ResetReading() on the layers of this dataset.
+
+ This method is the same as the C function GDALDatasetResetReading().
+
+ @since GDAL 2.2
+*/
+void GDALDataset::ResetReading()
 {
-    return NULL;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
+    if( !psPrivate )
+        return;
+    psPrivate->nCurrentLayerIdx = 0;
+    psPrivate->nLayerCount = -1;
+    psPrivate->poCurrentLayer = NULL;
+    psPrivate->nFeatureReadInLayer = 0;
+    psPrivate->nFeatureReadInDataset = 0;
+    psPrivate->nTotalFeaturesInLayer = TOTAL_FEATURES_NOT_INIT;
+    psPrivate->nTotalFeatures = TOTAL_FEATURES_NOT_INIT;
+}
+
+/************************************************************************/
+/*                         GDALDatasetResetReading()                    */
+/************************************************************************/
+
+/**
+ \brief Reset feature reading to start on the first feature.
+
+ This affects GDALDatasetGetNextFeature().
+
+ Depending on drivers, this may also have the side effect of calling
+ OGR_L_ResetReading() on the layers of this dataset.
+
+ This method is the same as the C++ method GDALDataset::ResetReading()
+
+ @param hDS dataset handle
+ @since GDAL 2.2
+*/
+void CPL_DLL GDALDatasetResetReading( GDALDatasetH hDS )
+{
+    VALIDATE_POINTER0(hDS, "GDALDatasetResetReading");
+
+    return static_cast<GDALDataset *>(hDS)->ResetReading();
+}
+
+/************************************************************************/
+/*                          GetNextFeature()                            */
+/************************************************************************/
+
+/**
+ \brief Fetch the next available feature from this dataset.
+
+ This method is intended for the few drivers where OGRLayer::GetNextFeature()
+ is not efficient, but in general OGRLayer::GetNextFeature() is a more
+ natural API.
+
+ The returned feature becomes the responsibility of the caller to
+ delete with OGRFeature::DestroyFeature().
+
+ Depending on the driver, this method may return features from layers in a
+ non sequential way. This is what may happen when the
+ ODsCRandomLayerRead capability is declared (for example for the
+ OSM and GMLAS drivers). When datasets declare this capability, it is strongly
+ advised to use GDALDataset::GetNextFeature() instead of
+ OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
+ implementation.
+
+ The default implementation, used by most drivers, will
+ however iterate over each layer, and then over each feature within this
+ layer.
+
+ This method takes into account spatial and attribute filters set on layers that
+ will be iterated upon.
+
+ The ResetReading() method can be used to start at the beginning again.
+
+ Depending on drivers, this may also have the side effect of calling
+ OGRLayer::GetNextFeature() on the layers of this dataset.
+
+ This method is the same as the C function GDALDatasetGetNextFeature().
+
+ @param ppoBelongingLayer a pointer to a OGRLayer* variable to receive the
+                          layer to which the object belongs to, or NULL.
+                          It is possible that the output of *ppoBelongingLayer
+                          to be NULL despite the feature not being NULL.
+ @param pdfProgressPct    a pointer to a double variable to receive the
+                          percentage progress (in [0,1] range), or NULL.
+                          On return, the pointed value might be negative if
+                          determining the progress is not possible.
+ @param pfnProgress       a progress callback to report progress (for
+                          GetNextFeature() calls that might have a long
+                          duration) and offer cancellation possibility, or NULL.
+ @param pProgressData     user data provided to pfnProgress, or NULL
+ @return a feature, or NULL if no more features are available.
+ @since GDAL 2.2
+*/
+
+OGRFeature *GDALDataset::GetNextFeature( OGRLayer **ppoBelongingLayer,
+                                         double *pdfProgressPct,
+                                         GDALProgressFunc pfnProgress,
+                                         void *pProgressData )
+{
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
+    if( !psPrivate || psPrivate->nCurrentLayerIdx < 0 )
+    {
+        if( ppoBelongingLayer != NULL )
+            *ppoBelongingLayer = NULL;
+        if( pdfProgressPct != NULL )
+            *pdfProgressPct = 1.0;
+        if( pfnProgress != NULL )
+            pfnProgress(1.0, "", pProgressData);
+        return NULL;
+    }
+
+    if ( psPrivate->poCurrentLayer == NULL &&
+         (pdfProgressPct != NULL || pfnProgress != NULL) )
+    {
+        if( psPrivate->nLayerCount < 0 )
+        {
+            psPrivate->nLayerCount = GetLayerCount();
+        }
+
+        if( psPrivate->nTotalFeatures == TOTAL_FEATURES_NOT_INIT )
+        {
+            psPrivate->nTotalFeatures = 0;
+            for(int i = 0; i < psPrivate->nLayerCount; i++)
+            {
+                OGRLayer *poLayer = GetLayer(i);
+                if( poLayer == NULL ||
+                    !poLayer->TestCapability(OLCFastFeatureCount) )
+                {
+                    psPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
+                    break;
+                }
+                GIntBig nCount = poLayer->GetFeatureCount(FALSE);
+                if( nCount < 0 )
+                {
+                    psPrivate->nTotalFeatures = TOTAL_FEATURES_UNKNOWN;
+                    break;
+                }
+                psPrivate->nTotalFeatures += nCount;
+            }
+        }
+    }
+
+    while( true )
+    {
+        if( psPrivate->poCurrentLayer == NULL )
+        {
+            psPrivate->poCurrentLayer = GetLayer(psPrivate->nCurrentLayerIdx);
+            if( psPrivate->poCurrentLayer == NULL )
+            {
+                psPrivate->nCurrentLayerIdx = -1;
+                if( ppoBelongingLayer != NULL )
+                    *ppoBelongingLayer = NULL;
+                if( pdfProgressPct != NULL )
+                    *pdfProgressPct = 1.0;
+                return NULL;
+            }
+            psPrivate->poCurrentLayer->ResetReading();
+            psPrivate->nFeatureReadInLayer = 0;
+            if( psPrivate->nTotalFeatures < 0 && pdfProgressPct != NULL )
+            {
+                if( psPrivate->poCurrentLayer->TestCapability(
+                        OLCFastFeatureCount) )
+                    psPrivate->nTotalFeaturesInLayer =
+                        psPrivate->poCurrentLayer->GetFeatureCount(FALSE);
+                else
+                    psPrivate->nTotalFeaturesInLayer = 0;
+            }
+        }
+        OGRFeature *poFeature = psPrivate->poCurrentLayer->GetNextFeature();
+        if( poFeature == NULL )
+        {
+            psPrivate->nCurrentLayerIdx++;
+            psPrivate->poCurrentLayer = NULL;
+            continue;
+        }
+
+        psPrivate->nFeatureReadInLayer++;
+        psPrivate->nFeatureReadInDataset++;
+        if( pdfProgressPct != NULL || pfnProgress != NULL )
+        {
+            double dfPct = 0.0;
+            if( psPrivate->nTotalFeatures > 0 )
+            {
+                dfPct = 1.0 * psPrivate->nFeatureReadInDataset /
+                        psPrivate->nTotalFeatures;
+            }
+            else
+            {
+                dfPct =
+                    1.0 * psPrivate->nCurrentLayerIdx / psPrivate->nLayerCount;
+                if( psPrivate->nTotalFeaturesInLayer > 0 )
+                {
+                    dfPct += 1.0 * psPrivate->nFeatureReadInLayer /
+                             psPrivate->nTotalFeaturesInLayer /
+                             psPrivate->nLayerCount;
+                }
+            }
+            if( pdfProgressPct )
+                *pdfProgressPct = dfPct;
+            if( pfnProgress )
+                pfnProgress(dfPct, "", NULL);
+        }
+
+        if( ppoBelongingLayer != NULL )
+            *ppoBelongingLayer = psPrivate->poCurrentLayer;
+        return poFeature;
+    }
+}
+
+/************************************************************************/
+/*                     GDALDatasetGetNextFeature()                      */
+/************************************************************************/
+/**
+ \brief Fetch the next available feature from this dataset.
+
+ This method is intended for the few drivers where OGR_L_GetNextFeature()
+ is not efficient, but in general OGR_L_GetNextFeature() is a more
+ natural API.
+
+ The returned feature becomes the responsibility of the caller to
+ delete with OGRFeature::DestroyFeature().
+
+ Depending on the driver, this method may return features from layers in a
+ non sequential way. This is what may happen when the
+ ODsCRandomLayerRead capability is declared (for example for the
+ OSM and GMLAS drivers). When datasets declare this capability, it is strongly
+ advised to use GDALDataset::GetNextFeature() instead of
+ OGRLayer::GetNextFeature(), as the later might have a slow, incomplete or stub
+ implementation.
+
+ The default implementation, used by most drivers, will
+ however iterate over each layer, and then over each feature within this
+ layer.
+
+ This method takes into account spatial and attribute filters set on layers that
+ will be iterated upon.
+
+ The ResetReading() method can be used to start at the beginning again.
+
+ Depending on drivers, this may also have the side effect of calling
+ OGRLayer::GetNextFeature() on the layers of this dataset.
+
+ This method is the same as the C++ method GDALDataset::GetNextFeature()
+
+ @param hDS               dataset handle.
+ @param phBelongingLayer  a pointer to a OGRLayer* variable to receive the
+                          layer to which the object belongs to, or NULL.
+                          It is possible that the output of *ppoBelongingLayer
+                          to be NULL despite the feature not being NULL.
+ @param pdfProgressPct    a pointer to a double variable to receive the
+                          percentage progress (in [0,1] range), or NULL.
+                          On return, the pointed value might be negative if
+                          determining the progress is not possible.
+ @param pfnProgress       a progress callback to report progress (for
+                          GetNextFeature() calls that might have a long
+                          duration) and offer cancellation possibility, or NULL
+ @param pProgressData     user data provided to pfnProgress, or NULL
+ @return a feature, or NULL if no more features are available.
+ @since GDAL 2.2
+*/
+OGRFeatureH CPL_DLL GDALDatasetGetNextFeature( GDALDatasetH hDS,
+                                               OGRLayerH *phBelongingLayer,
+                                               double *pdfProgressPct,
+                                               GDALProgressFunc pfnProgress,
+                                               void *pProgressData )
+{
+    VALIDATE_POINTER1(hDS, "GDALDatasetGetNextFeature", NULL);
+
+    return reinterpret_cast<OGRFeatureH>(
+        reinterpret_cast<GDALDataset *>(hDS)
+            ->GetNextFeature((OGRLayer **)phBelongingLayer, pdfProgressPct,
+                             pfnProgress, pProgressData));
 }
 
 /************************************************************************/
@@ -5827,6 +6342,7 @@ OGRLayer* GDALDataset::GetLayer(CPL_UNUSED int iLayer)
 /************************************************************************/
 
 /**
+ \fn GDALDataset::TestCapability( const char * pszCap )
  \brief Test if capability is available.
 
  One of the following dataset capability names can be passed into this
@@ -5835,12 +6351,21 @@ OGRLayer* GDALDataset::GetLayer(CPL_UNUSED int iLayer)
 
  <ul>
   <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
-  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing layers.<p>
+  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
+          layers.<p>
   <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
-        datasource support CreateGeomField() just after layer creation.<p>
-  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve geometries.<p>
-  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient) transactions.<p>
-  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports transactions through emulation.<p>
+          datasource support CreateGeomField() just after layer creation.<p>
+  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
+          geometries.<p>
+  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
+          transactions.<p>
+  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
+          transactions through emulation.<p>
+  <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
+          GetNextFeature() implementation, potentially returning features from
+          layers in a non sequential way.<p>
+  <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
+         CreateFeature() on layers in a non sequential way.<p>
  </ul>
 
  The \#define macro forms of the capability names should be used in preference
@@ -5856,9 +6381,57 @@ OGRLayer* GDALDataset::GetLayer(CPL_UNUSED int iLayer)
  @return TRUE if capability available otherwise FALSE.
 */
 
-int GDALDataset::TestCapability( CPL_UNUSED const char * pszCap )
+int GDALDataset::TestCapability(CPL_UNUSED const char *pszCap) { return FALSE; }
+
+/************************************************************************/
+/*                     GDALDatasetTestCapability()                      */
+/************************************************************************/
+
+/**
+ \brief Test if capability is available.
+
+ One of the following dataset capability names can be passed into this
+ function, and a TRUE or FALSE value will be returned indicating whether or not
+ the capability is available for this object.
+
+ <ul>
+  <li> <b>ODsCCreateLayer</b>: True if this datasource can create new layers.<p>
+  <li> <b>ODsCDeleteLayer</b>: True if this datasource can delete existing
+          layers.<p>
+  <li> <b>ODsCCreateGeomFieldAfterCreateLayer</b>: True if the layers of this
+          datasource support CreateGeomField() just after layer creation.<p>
+  <li> <b>ODsCCurveGeometries</b>: True if this datasource supports curve
+          geometries.<p>
+  <li> <b>ODsCTransactions</b>: True if this datasource supports (efficient)
+          transactions.<p>
+  <li> <b>ODsCEmulatedTransactions</b>: True if this datasource supports
+          transactions through emulation.<p>
+  <li> <b>ODsCRandomLayerRead</b>: True if this datasource has a dedicated
+          GetNextFeature() implementation, potentially returning features from
+          layers in a non sequential way.<p>
+  <li> <b>ODsCRandomLayerWrite</b>: True if this datasource supports calling
+          CreateFeature() on layers in a non sequential way.<p>
+ </ul>
+
+ The \#define macro forms of the capability names should be used in preference
+ to the strings themselves to avoid misspelling.
+
+ This function is the same as the C++ method GDALDataset::TestCapability()
+
+ @since GDAL 2.0
+
+ @param hDS the dataset handle.
+ @param pszCap the capability to test.
+
+ @return TRUE if capability available otherwise FALSE.
+*/
+int GDALDatasetTestCapability( GDALDatasetH hDS, const char *pszCap )
+
 {
-    return FALSE;
+    VALIDATE_POINTER1(hDS, "GDALDatasetTestCapability", 0);
+    VALIDATE_POINTER1(pszCap, "GDALDatasetTestCapability", 0);
+
+    return static_cast<GDALDataset *>(hDS)->TestCapability(pszCap);
 }
 
 /************************************************************************/
@@ -5866,6 +6439,7 @@ int GDALDataset::TestCapability( CPL_UNUSED const char * pszCap )
 /************************************************************************/
 
 /**
+ \fn GDALDataset::StartTransaction(int)
  \brief For datasources which support transactions, StartTransaction creates a
 `transaction.
 
@@ -5875,39 +6449,44 @@ int GDALDataset::TestCapability( CPL_UNUSED const char * pszCap )
 
  Nested transactions are not supported.
 
- All changes done after the start of the transaction are definitely applied in the
- datasource if CommitTransaction() is called. They may be canceled by calling
- RollbackTransaction() instead.
+ All changes done after the start of the transaction are definitely applied in
+ the datasource if CommitTransaction() is called. They may be canceled by
+ calling RollbackTransaction() instead.
 
  At the time of writing, transactions only apply on vector layers.
 
- Datasets that support transactions will advertise the ODsCTransactions capability.
- Use of transactions at dataset level is generally preferred to transactions at
- layer level, whose scope is rarely limited to the layer from which it was started.
+ Datasets that support transactions will advertise the ODsCTransactions
+ capability.  Use of transactions at dataset level is generally preferred to
+ transactions at layer level, whose scope is rarely limited to the layer from
+ which it was started.
 
- In case StartTransaction() fails, neither CommitTransaction() or RollbackTransaction()
- should be called.
+ In case StartTransaction() fails, neither CommitTransaction() or
+ RollbackTransaction() should be called.
 
- If an error occurs after a successful StartTransaction(), the whole
- transaction may or may not be implicitly canceled, depending on drivers. (e.g.
- the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
- error, an explicit call to RollbackTransaction() should be done to keep things balanced.
+ If an error occurs after a successful StartTransaction(), the whole transaction
+ may or may not be implicitly canceled, depending on drivers. (e.g.  the PG
+ driver will cancel it, SQLite/GPKG not). In any case, in the event of an error,
+ an explicit call to RollbackTransaction() should be done to keep things
+ balanced.
 
  By default, when bForce is set to FALSE, only "efficient" transactions will be
  attempted. Some drivers may offer an emulation of transactions, but sometimes
- with significant overhead, in which case the user must explicitly allow for such
- an emulation by setting bForce to TRUE. Drivers that offer emulated transactions
- should advertise the ODsCEmulatedTransactions capability (and not ODsCTransactions).
+ with significant overhead, in which case the user must explicitly allow for
+ such an emulation by setting bForce to TRUE. Drivers that offer emulated
+ transactions should advertise the ODsCEmulatedTransactions capability (and not
+ ODsCTransactions).
 
  This function is the same as the C function GDALDatasetStartTransaction().
 
- @param bForce can be set to TRUE if an emulation, possibly slow, of a transaction
+ @param bForce can be set to TRUE if an emulation, possibly slow, of a
+ transaction
                mechanism is acceptable.
 
  @return OGRERR_NONE on success.
  @since GDAL 2.0
 */
-OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
+
+OGRErr GDALDataset::StartTransaction( CPL_UNUSED int bForce )
 {
     return OGRERR_UNSUPPORTED_OPERATION;
 }
@@ -5926,34 +6505,39 @@ OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
 
  Nested transactions are not supported.
 
- All changes done after the start of the transaction are definitely applied in the
- datasource if CommitTransaction() is called. They may be canceled by calling
- RollbackTransaction() instead.
+ All changes done after the start of the transaction are definitely applied in
+ the datasource if CommitTransaction() is called. They may be canceled by
+ calling RollbackTransaction() instead.
 
  At the time of writing, transactions only apply on vector layers.
 
- Datasets that support transactions will advertise the ODsCTransactions capability.
+ Datasets that support transactions will advertise the ODsCTransactions
+ capability.
  Use of transactions at dataset level is generally preferred to transactions at
- layer level, whose scope is rarely limited to the layer from which it was started.
+ layer level, whose scope is rarely limited to the layer from which it was
+ started.
 
- In case StartTransaction() fails, neither CommitTransaction() or RollbackTransaction()
- should be called.
+ In case StartTransaction() fails, neither CommitTransaction() or
+ RollbackTransaction() should be called.
 
  If an error occurs after a successful StartTransaction(), the whole
  transaction may or may not be implicitly canceled, depending on drivers. (e.g.
  the PG driver will cancel it, SQLite/GPKG not). In any case, in the event of an
- error, an explicit call to RollbackTransaction() should be done to keep things balanced.
+ error, an explicit call to RollbackTransaction() should be done to keep things
+ balanced.
 
  By default, when bForce is set to FALSE, only "efficient" transactions will be
  attempted. Some drivers may offer an emulation of transactions, but sometimes
- with significant overhead, in which case the user must explicitly allow for such
- an emulation by setting bForce to TRUE. Drivers that offer emulated transactions
- should advertise the ODsCEmulatedTransactions capability (and not ODsCTransactions).
+ with significant overhead, in which case the user must explicitly allow for
+ such an emulation by setting bForce to TRUE. Drivers that offer emulated
+ transactions should advertise the ODsCEmulatedTransactions capability (and not
+ ODsCTransactions).
 
  This function is the same as the C++ method GDALDataset::StartTransaction()
 
  @param hDS the dataset handle.
- @param bForce can be set to TRUE if an emulation, possibly slow, of a transaction
+ @param bForce can be set to TRUE if an emulation, possibly slow, of a
+ transaction
                mechanism is acceptable.
 
  @return OGRERR_NONE on success.
@@ -5961,14 +6545,15 @@ OGRErr GDALDataset::StartTransaction(CPL_UNUSED int bForce)
 */
 OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetStartTransaction", OGRERR_INVALID_HANDLE );
+    VALIDATE_POINTER1(hDS, "GDALDatasetStartTransaction",
+                      OGRERR_INVALID_HANDLE);
 
 #ifdef OGRAPISPY_ENABLED
     if( bOGRAPISpyEnabled )
         OGRAPISpy_Dataset_StartTransaction(hDS, bForce);
 #endif
 
-    return ((GDALDataset*) hDS)->StartTransaction(bForce);
+    return static_cast<GDALDataset *>(hDS)->StartTransaction(bForce);
 }
 
 /************************************************************************/
@@ -5976,7 +6561,8 @@ OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
 /************************************************************************/
 
 /**
- \brief For datasources which support transactions, CommitTransaction commits a transaction.
+ \brief For datasources which support transactions, CommitTransaction commits a
+ transaction.
 
  If no transaction is active, or the commit fails, will return
  OGRERR_FAILURE. Datasources which do not support transactions will
@@ -5990,17 +6576,15 @@ OGRErr GDALDatasetStartTransaction(GDALDatasetH hDS, int bForce)
  @return OGRERR_NONE on success.
  @since GDAL 2.0
 */
-OGRErr GDALDataset::CommitTransaction()
-{
-    return OGRERR_UNSUPPORTED_OPERATION;
-}
+OGRErr GDALDataset::CommitTransaction() { return OGRERR_UNSUPPORTED_OPERATION; }
 
 /************************************************************************/
 /*                        GDALDatasetCommitTransaction()                */
 /************************************************************************/
 
 /**
- \brief For datasources which support transactions, CommitTransaction commits a transaction.
+ \brief For datasources which support transactions, CommitTransaction commits a
+ transaction.
 
  If no transaction is active, or the commit fails, will return
  OGRERR_FAILURE. Datasources which do not support transactions will
@@ -6016,14 +6600,15 @@ OGRErr GDALDataset::CommitTransaction()
 */
 OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetCommitTransaction", OGRERR_INVALID_HANDLE );
+    VALIDATE_POINTER1(hDS, "GDALDatasetCommitTransaction",
+                      OGRERR_INVALID_HANDLE);
 
 #ifdef OGRAPISPY_ENABLED
     if( bOGRAPISpyEnabled )
         OGRAPISpy_Dataset_CommitTransaction(hDS);
 #endif
 
-    return ((GDALDataset*) hDS)->CommitTransaction();
+    return static_cast<GDALDataset *>(hDS)->CommitTransaction();
 }
 
 /************************************************************************/
@@ -6032,7 +6617,8 @@ OGRErr GDALDatasetCommitTransaction(GDALDatasetH hDS)
 
 /**
  \brief For datasources which support transactions, RollbackTransaction will
- roll back a datasource to its state before the start of the current transaction.
+ roll back a datasource to its state before the start of the current
+ transaction.
  If no transaction is active, or the rollback fails, will return
  OGRERR_FAILURE. Datasources which do not support transactions will
  always return OGRERR_UNSUPPORTED_OPERATION.
@@ -6053,7 +6639,8 @@ OGRErr GDALDataset::RollbackTransaction()
 
 /**
  \brief For datasources which support transactions, RollbackTransaction will
- roll back a datasource to its state before the start of the current transaction.
+ roll back a datasource to its state before the start of the current
+ transaction.
  If no transaction is active, or the rollback fails, will return
  OGRERR_FAILURE. Datasources which do not support transactions will
  always return OGRERR_UNSUPPORTED_OPERATION.
@@ -6063,33 +6650,37 @@ OGRErr GDALDataset::RollbackTransaction()
  @return OGRERR_NONE on success.
  @since GDAL 2.0
 */
-OGRErr GDALDatasetRollbackTransaction(GDALDatasetH hDS)
+OGRErr GDALDatasetRollbackTransaction( GDALDatasetH hDS )
 {
-    VALIDATE_POINTER1( hDS, "GDALDatasetRollbackTransaction", OGRERR_INVALID_HANDLE );
+    VALIDATE_POINTER1(hDS, "GDALDatasetRollbackTransaction",
+                      OGRERR_INVALID_HANDLE);
 
 #ifdef OGRAPISPY_ENABLED
     if( bOGRAPISpyEnabled )
         OGRAPISpy_Dataset_RollbackTransaction(hDS);
 #endif
 
-    return ((GDALDataset*) hDS)->RollbackTransaction();
+    return static_cast<GDALDataset *>(hDS)->RollbackTransaction();
 }
 
 /************************************************************************/
 /*                          EnterReadWrite()                            */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
     if( psPrivate != NULL && eAccess == GA_Update )
     {
         if( psPrivate->eStateReadWriteMutex == RW_MUTEX_STATE_UNKNOWN )
         {
             // In case dead-lock would occur, which is not impossible,
             // this can be used to prevent it, but at the risk of other
-            // issues
-            if( CSLTestBoolean(CPLGetConfigOption( "GDAL_ENABLE_READ_WRITE_MUTEX", "YES") ) )
+            // issues.
+            if(CPLTestBool(
+                   CPLGetConfigOption("GDAL_ENABLE_READ_WRITE_MUTEX", "YES")))
             {
                 psPrivate->eStateReadWriteMutex = RW_MUTEX_STATE_ALLOWED;
             }
@@ -6103,13 +6694,15 @@ int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
         {
             // There should be no race related to creating this mutex since
             // it should be first created through IWriteBlock() / IRasterIO()
-            // and then GDALRasterBlock might call it from another thread
+            // and then GDALRasterBlock might call it from another thread.
 #ifdef DEBUG_VERBOSE
-            CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
+            CPLDebug("GDAL",
+                     "[Thread " CPL_FRMT_GIB "] Acquiring RW mutex for %s",
                      CPLGetPID(), GetDescription());
 #endif
-            CPLCreateOrAcquireMutex( &(psPrivate->hMutex), 1000.0 );
-            psPrivate->oMapThreadToMutexTakenCount[ CPLGetPID() ] ++; /* not sure if we can have recursive calls, so ...*/
+            CPLCreateOrAcquireMutex(&(psPrivate->hMutex), 1000.0);
+            // Not sure if we can have recursive calls, so...
+            psPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]++;
             return TRUE;
         }
     }
@@ -6122,14 +6715,15 @@ int GDALDataset::EnterReadWrite(GDALRWFlag eRWFlag)
 
 void GDALDataset::LeaveReadWrite()
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
     if( psPrivate )
     {
-        psPrivate->oMapThreadToMutexTakenCount[ CPLGetPID() ] --;
+        psPrivate->oMapThreadToMutexTakenCount[CPLGetPID()]--;
         CPLReleaseMutex(psPrivate->hMutex);
 #ifdef DEBUG_VERBOSE
         CPLDebug("GDAL", "[Thread " CPL_FRMT_GIB "] Releasing RW mutex for %s",
-                     CPLGetPID(), GetDescription());
+                 CPLGetPID(), GetDescription());
 #endif
     }
 }
@@ -6140,7 +6734,8 @@ void GDALDataset::LeaveReadWrite()
 
 void GDALDataset::InitRWLock()
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
     if( psPrivate )
     {
         if( psPrivate->eStateReadWriteMutex == RW_MUTEX_STATE_UNKNOWN )
@@ -6155,13 +6750,14 @@ void GDALDataset::InitRWLock()
 /*                       DisableReadWriteMutex()                        */
 /************************************************************************/
 
-/* The mutex logic is broken in multi-threaded situations, for example */
-/* with 2 WarpedVRT datasets being read at the same time. In that */
-/* particular case, the mutex is not needed, so allow the VRTWarpedDataset code */
-/* to disable it. */
+// The mutex logic is broken in multi-threaded situations, for example
+// with 2 WarpedVRT datasets being read at the same time. In that
+// particular case, the mutex is not needed, so allow the VRTWarpedDataset code
+// to disable it.
 void GDALDataset::DisableReadWriteMutex()
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
     if( psPrivate )
     {
         psPrivate->eStateReadWriteMutex = RW_MUTEX_STATE_DISABLED;
@@ -6174,7 +6770,8 @@ void GDALDataset::DisableReadWriteMutex()
 
 void GDALDataset::TemporarilyDropReadWriteLock()
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
     if( psPrivate && psPrivate->hMutex )
     {
 #ifdef DEBUG_VERBOSE
@@ -6183,11 +6780,11 @@ void GDALDataset::TemporarilyDropReadWriteLock()
                  CPLGetPID(), GetDescription());
 #endif
         CPLAcquireMutex(psPrivate->hMutex, 1000.0);
-        const int nCount = psPrivate->oMapThreadToMutexTakenCount[ CPLGetPID() ];
+        const int nCount = psPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
 #ifdef DEBUG_EXTRA
-        psPrivate->oMapThreadToMutexTakenCountSaved[ CPLGetPID() ] = nCount;
+        psPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()] = nCount;
 #endif
-        for(int i=0;i<nCount + 1;i++)
+        for(int i = 0; i < nCount + 1; i++)
         {
             CPLReleaseMutex(psPrivate->hMutex);
         }
@@ -6200,7 +6797,8 @@ void GDALDataset::TemporarilyDropReadWriteLock()
 
 void GDALDataset::ReacquireReadWriteLock()
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
     if( psPrivate && psPrivate->hMutex )
     {
 #ifdef DEBUG_VERBOSE
@@ -6209,13 +6807,14 @@ void GDALDataset::ReacquireReadWriteLock()
                  CPLGetPID(), GetDescription());
 #endif
         CPLAcquireMutex(psPrivate->hMutex, 1000.0);
-        const int nCount = psPrivate->oMapThreadToMutexTakenCount[ CPLGetPID() ];
+        const int nCount = psPrivate->oMapThreadToMutexTakenCount[CPLGetPID()];
 #ifdef DEBUG_EXTRA
-        CPLAssert( nCount == psPrivate->oMapThreadToMutexTakenCountSaved[ CPLGetPID() ] );
+        CPLAssert(nCount ==
+                  psPrivate->oMapThreadToMutexTakenCountSaved[CPLGetPID()]);
 #endif
         if( nCount == 0 )
             CPLReleaseMutex(psPrivate->hMutex);
-        for(int i=0;i<nCount - 1;i++)
+        for(int i = 0; i < nCount - 1; i++)
         {
             CPLAcquireMutex(psPrivate->hMutex, 1000.0);
         }
@@ -6228,7 +6827,8 @@ void GDALDataset::ReacquireReadWriteLock()
 
 int GDALDataset::AcquireMutex()
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
     if( psPrivate == NULL )
         return 0;
     return CPLCreateOrAcquireMutex(&(psPrivate->hMutex), 1000.0);
@@ -6240,7 +6840,9 @@ int GDALDataset::AcquireMutex()
 
 void GDALDataset::ReleaseMutex()
 {
-    GDALDatasetPrivate* psPrivate = (GDALDatasetPrivate* )m_hPrivateData;
+    GDALDatasetPrivate *psPrivate =
+        static_cast<GDALDatasetPrivate *>(m_hPrivateData);
     if( psPrivate )
         CPLReleaseMutex(psPrivate->hMutex);
 }
+//! @endcond
diff --git a/gcore/gdaldefaultasync.cpp b/gcore/gdaldefaultasync.cpp
index ee34157..7f4f084 100644
--- a/gcore/gdaldefaultasync.cpp
+++ b/gcore/gdaldefaultasync.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaldataset.cpp 16796 2009-04-17 23:35:04Z normanb $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDefaultAsyncReader and the
@@ -28,9 +27,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdaldataset.cpp 16796 2009-04-17 23:35:04Z normanb $");
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "gdal.h"
+
+CPL_CVSID("$Id: gdaldefaultasync.cpp 36523 2016-11-27 04:13:26Z goatbar $");
 
 CPL_C_START
 GDALAsyncReader *
@@ -83,7 +90,7 @@ GDALAsyncReader::~GDALAsyncReader()
 /************************************************************************/
 
 /**
- * \fn GDALAsyncStatusType GDALAsyncReader::GetNextUpdatedRegion( double dfTimeout, int* pnBufXOff, int* pnBufYOff, int* pnBufXSize, int* pnBufXSize) = 0;
+ * \fn GDALAsyncStatusType GDALAsyncReader::GetNextUpdatedRegion( double dfTimeout, int* pnBufXOff, int* pnBufYOff, int* pnBufXSize, int* pnBufYSize) = 0;
  *
  * \brief Get async IO update
  *
@@ -125,14 +132,54 @@ GDALAsyncReader::~GDALAsyncReader()
 /*                     GDALARGetNextUpdatedRegion()                     */
 /************************************************************************/
 
+/**
+ * \brief Get async IO update
+ *
+ * Provide an opportunity for an asynchronous IO request to update the
+ * image buffer and return an indication of the area of the buffer that
+ * has been updated.
+ *
+ * The dfTimeout parameter can be used to wait for additional data to
+ * become available.  The timeout does not limit the amount
+ * of time this method may spend actually processing available data.
+ *
+ * The following return status are possible.
+ * - GARIO_PENDING: No imagery was altered in the buffer, but there is still
+ * activity pending, and the application should continue to call
+ * GetNextUpdatedRegion() as time permits.
+ * - GARIO_UPDATE: Some of the imagery has been updated, but there is still
+ * activity pending.
+ * - GARIO_ERROR: Something has gone wrong. The asynchronous request should
+ * be ended.
+ * - GARIO_COMPLETE: An update has occurred and there is no more pending work
+ * on this request. The request should be ended and the buffer used.
+ *
+ * This is the same as GDALAsyncReader::GetNextUpdatedRegion()
+ *
+ * @param hARIO handle to the async reader.
+ * @param dfTimeout the number of seconds to wait for additional updates.  Use
+ * -1 to wait indefinitely, or zero to not wait at all if there is no data
+ * available.
+ * @param pnBufXOff location to return the X offset of the area of the
+ * request buffer that has been updated.
+ * @param pnBufYOff location to return the Y offset of the area of the
+ * request buffer that has been updated.
+ * @param pnBufXSize location to return the X size of the area of the
+ * request buffer that has been updated.
+ * @param pnBufYSize location to return the Y size of the area of the
+ * request buffer that has been updated.
+ *
+ * @return GARIO_ status, details described above.
+ */
+
 GDALAsyncStatusType CPL_STDCALL
-GDALARGetNextUpdatedRegion(GDALAsyncReaderH hARIO, double timeout,
-                           int* pnxbufoff, int* pnybufoff,
-                           int* pnxbufsize, int* pnybufsize)
+GDALARGetNextUpdatedRegion(GDALAsyncReaderH hARIO, double dfTimeout,
+                           int* pnBufXOff, int* pnBufYOff,
+                           int* pnBufXSize, int* pnBufYSize)
 {
     VALIDATE_POINTER1(hARIO, "GDALARGetNextUpdatedRegion", GARIO_ERROR);
     return ((GDALAsyncReader *)hARIO)->GetNextUpdatedRegion(
-        timeout, pnxbufoff, pnybufoff, pnxbufsize, pnybufsize);
+        dfTimeout, pnBufXOff, pnBufYOff, pnBufXSize, pnBufYSize);
 }
 
 /************************************************************************/
@@ -140,6 +187,7 @@ GDALARGetNextUpdatedRegion(GDALAsyncReaderH hARIO, double timeout,
 /************************************************************************/
 
 /**
+ * \fn GDALAsyncReader::LockBuffer(double)
  * \brief Lock image buffer.
  *
  * Locks the image buffer passed into GDALDataset::BeginAsyncReader().
@@ -154,15 +202,36 @@ GDALARGetNextUpdatedRegion(GDALAsyncReaderH hARIO, double timeout,
  * @return TRUE if successful, or FALSE on an error.
  */
 
-int GDALAsyncReader::LockBuffer( CPL_UNUSED double dfTimeout )
+/**/
+/**/
+
+int GDALAsyncReader::LockBuffer( double /* dfTimeout */ )
 {
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                          GDALARLockBuffer()                          */
 /************************************************************************/
+
+/**
+ * \brief Lock image buffer.
+ *
+ * Locks the image buffer passed into GDALDataset::BeginAsyncReader().
+ * This is useful to ensure the image buffer is not being modified while
+ * it is being used by the application.  UnlockBuffer() should be used
+ * to release this lock when it is no longer needed.
+ *
+ * This is the same as GDALAsyncReader::LockBuffer()
+ *
+ * @param hARIO handle to async reader.
+ * @param dfTimeout the time in seconds to wait attempting to lock the buffer.
+ * -1.0 to wait indefinitely and 0 to not wait at all if it can't be
+ * acquired immediately.  Default is -1.0 (infinite wait).
+ *
+ * @return TRUE if successful, or FALSE on an error.
+ */
+
 int CPL_STDCALL GDALARLockBuffer(GDALAsyncReaderH hARIO, double dfTimeout )
 {
     VALIDATE_POINTER1(hARIO, "GDALARLockBuffer",FALSE);
@@ -185,8 +254,19 @@ void GDALAsyncReader::UnlockBuffer()
 }
 
 /************************************************************************/
-/*                          GDALARUnlockBuffer()                          */
+/*                          GDALARUnlockBuffer()                        */
 /************************************************************************/
+
+/**
+ * \brief Unlock image buffer.
+ *
+ * Releases a lock on the image buffer previously taken with LockBuffer().
+ *
+ * This is the same as GDALAsyncReader::UnlockBuffer()
+ *
+ * @param hARIO handle to async reader.
+ */
+
 void CPL_STDCALL GDALARUnlockBuffer(GDALAsyncReaderH hARIO)
 {
     VALIDATE_POINTER0(hARIO, "GDALARUnlockBuffer");
@@ -214,13 +294,13 @@ class GDALDefaultAsyncReader : public GDALAsyncReader
                              int nBandCount, int* panBandMap,
                              int nPixelSpace, int nLineSpace,
                              int nBandSpace, char **papszOptions);
-    ~GDALDefaultAsyncReader();
+    virtual ~GDALDefaultAsyncReader();
 
     virtual GDALAsyncStatusType GetNextUpdatedRegion(double dfTimeout,
                                                      int* pnBufXOff,
                                                      int* pnBufYOff,
                                                      int* pnBufXSize,
-                                                     int* pnBufYSize);
+                                                     int* pnBufYSize) override;
 };
 
 /************************************************************************/
@@ -306,11 +386,11 @@ GDALDefaultAsyncReader::~GDALDefaultAsyncReader()
 /************************************************************************/
 
 GDALAsyncStatusType
-GDALDefaultAsyncReader::GetNextUpdatedRegion(CPL_UNUSED double dfTimeout,
-                                             int* pnBufXOff,
-                                             int* pnBufYOff,
-                                             int* pnBufXSize,
-                                             int* pnBufYSize )
+GDALDefaultAsyncReader::GetNextUpdatedRegion( double /*dfTimeout*/,
+                                              int* pnBufXOff,
+                                              int* pnBufYOff,
+                                              int* pnBufXSize,
+                                              int* pnBufYSize )
 {
     CPLErr eErr;
 
diff --git a/gcore/gdaldefaultoverviews.cpp b/gcore/gdaldefaultoverviews.cpp
index ac7d833..96abbac 100644
--- a/gcore/gdaldefaultoverviews.cpp
+++ b/gcore/gdaldefaultoverviews.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaldefaultoverviews.cpp 33874 2016-04-03 14:55:22Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Helper code to implement overview and mask support for many
@@ -29,34 +28,43 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
+
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 
-CPL_CVSID("$Id: gdaldefaultoverviews.cpp 33874 2016-04-03 14:55:22Z rouault $");
+CPL_CVSID("$Id: gdaldefaultoverviews.cpp 36957 2016-12-19 13:31:09Z rouault $");
 
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                        GDALDefaultOverviews()                        */
 /************************************************************************/
 
-GDALDefaultOverviews::GDALDefaultOverviews()
-
-{
-    poDS = NULL;
-    poODS = NULL;
-    bOvrIsAux = FALSE;
-
-    bCheckedForMask = FALSE;
-    bCheckedForOverviews = FALSE;
-
-    poMaskDS = NULL;
-
-    bOwnMaskDS = FALSE;
-    poBaseDS = NULL;
-
-    papszInitSiblingFiles = NULL;
-    pszInitName = NULL;
-    bInitNameIsOVR = FALSE;
-}
+GDALDefaultOverviews::GDALDefaultOverviews() :
+    poDS(NULL),
+    poODS(NULL),
+    bOvrIsAux(false),
+    bCheckedForMask(false),
+    bOwnMaskDS(false),
+    poMaskDS(NULL),
+    poBaseDS(NULL),
+    bCheckedForOverviews(FALSE),
+    pszInitName(NULL),
+    bInitNameIsOVR(false),
+    papszInitSiblingFiles(NULL)
+{}
 
 /************************************************************************/
 /*                       ~GDALDefaultOverviews()                        */
@@ -134,7 +142,10 @@ void GDALDefaultOverviews::Initialize( GDALDataset *poDSIn,
         GDALClose( poODS );
         poODS = NULL;
 
-        CPLDebug( "GDAL", "GDALDefaultOverviews::Initialize() called twice - this is odd and perhaps dangerous!" );
+        CPLDebug(
+            "GDAL",
+            "GDALDefaultOverviews::Initialize() called twice - "
+            "this is odd and perhaps dangerous!" );
     }
 
 /* -------------------------------------------------------------------- */
@@ -147,7 +158,7 @@ void GDALDefaultOverviews::Initialize( GDALDataset *poDSIn,
     pszInitName = NULL;
     if( pszBasename != NULL )
         pszInitName = CPLStrdup(pszBasename);
-    bInitNameIsOVR = bNameIsOVR;
+    bInitNameIsOVR = CPL_TO_BOOL(bNameIsOVR);
 
     CSLDestroy( papszInitSiblingFiles );
     papszInitSiblingFiles = NULL;
@@ -163,7 +174,7 @@ void GDALDefaultOverviews::Initialize( GDALDataset *poDSIn,
 /*      "de-allocatable" with CSLDestroy()                              */
 /************************************************************************/
 
-void GDALDefaultOverviews::TransferSiblingFiles(char** papszSiblingFiles)
+void GDALDefaultOverviews::TransferSiblingFiles( char** papszSiblingFiles )
 {
     CSLDestroy( papszInitSiblingFiles );
     papszInitSiblingFiles = papszSiblingFiles;
@@ -191,8 +202,6 @@ void GDALDefaultOverviews::OverviewScan()
 /* -------------------------------------------------------------------- */
 /*      Open overview dataset if it exists.                             */
 /* -------------------------------------------------------------------- */
-    int bExists;
-
     if( pszInitName == NULL )
         pszInitName = CPLStrdup(poDS->GetDescription());
 
@@ -206,18 +215,22 @@ void GDALDefaultOverviews::OverviewScan()
 
         std::vector<char> achOvrFilename;
         achOvrFilename.resize(osOvrFilename.size() + 1);
-        memcpy(&(achOvrFilename[0]), osOvrFilename.c_str(), osOvrFilename.size() + 1);
-        bExists = CPLCheckForFile( &achOvrFilename[0],
-                                   papszInitSiblingFiles );
+        memcpy(&(achOvrFilename[0]),
+               osOvrFilename.c_str(),
+               osOvrFilename.size() + 1);
+        bool bExists = CPL_TO_BOOL(
+            CPLCheckForFile( &achOvrFilename[0], papszInitSiblingFiles ) );
         osOvrFilename = &achOvrFilename[0];
 
 #if !defined(WIN32)
         if( !bInitNameIsOVR && !bExists && !papszInitSiblingFiles )
         {
             osOvrFilename.Printf( "%s.OVR", pszInitName );
-            memcpy(&(achOvrFilename[0]), osOvrFilename.c_str(), osOvrFilename.size() + 1);
-            bExists = CPLCheckForFile( &achOvrFilename[0],
-                                       papszInitSiblingFiles );
+            memcpy(&(achOvrFilename[0]),
+                   osOvrFilename.c_str(),
+                   osOvrFilename.size() + 1);
+            bExists = CPL_TO_BOOL(
+                CPLCheckForFile( &achOvrFilename[0], papszInitSiblingFiles ) );
             osOvrFilename = &achOvrFilename[0];
             if( !bExists )
                 osOvrFilename.Printf( "%s.ovr", pszInitName );
@@ -226,10 +239,11 @@ void GDALDefaultOverviews::OverviewScan()
 
         if( bExists )
         {
-            poODS = (GDALDataset*) GDALOpenEx( osOvrFilename,
-                                               GDAL_OF_RASTER |
-                                               ((poDS->GetAccess() == GA_Update) ? GDAL_OF_UPDATE : 0),
-                                               NULL, NULL, papszInitSiblingFiles );
+           poODS = static_cast<GDALDataset *>( GDALOpenEx(
+                osOvrFilename,
+                GDAL_OF_RASTER |
+                (poDS->GetAccess() == GA_Update ? GDAL_OF_UPDATE : 0),
+                NULL, NULL, papszInitSiblingFiles ) );
         }
     }
 
@@ -249,7 +263,7 @@ void GDALDefaultOverviews::OverviewScan()
         {
             CPLString osAuxFilename = CPLResetExtension( pszInitName, "aux");
             int iSibling = CSLFindString( papszInitSiblingFiles,
-                                        CPLGetFilename(osAuxFilename) );
+                                          CPLGetFilename(osAuxFilename) );
             if( iSibling < 0 )
             {
                 osAuxFilename = pszInitName;
@@ -261,7 +275,7 @@ void GDALDefaultOverviews::OverviewScan()
             }
         }
 
-        if (bTryFindAssociatedAuxFile)
+        if( bTryFindAssociatedAuxFile )
         {
             poODS = GDALFindAssociatedAuxFile( pszInitName, poDS->GetAccess(),
                                             poDS );
@@ -269,12 +283,12 @@ void GDALDefaultOverviews::OverviewScan()
 
         if( poODS )
         {
-            int bUseRRD = CPLTestBool(CPLGetConfigOption("USE_RRD","NO"));
+            const bool bUseRRD = CPLTestBool(CPLGetConfigOption("USE_RRD","NO"));
 
-            bOvrIsAux = TRUE;
+            bOvrIsAux = true;
             if( GetOverviewCount(1) == 0 && !bUseRRD )
             {
-                bOvrIsAux = FALSE;
+                bOvrIsAux = false;
                 GDALClose( poODS );
                 poODS = NULL;
             }
@@ -299,16 +313,18 @@ void GDALDefaultOverviews::OverviewScan()
         {
             if( STARTS_WITH_CI(pszProxyOvrFilename, ":::BASE:::") )
             {
-                CPLString osPath = CPLGetPath(poDS->GetDescription());
+                const CPLString osPath = CPLGetPath(poDS->GetDescription());
 
                 osOvrFilename =
                     CPLFormFilename( osPath, pszProxyOvrFilename+10, NULL );
             }
             else
+            {
                 osOvrFilename = pszProxyOvrFilename;
+            }
 
             CPLPushErrorHandler(CPLQuietErrorHandler);
-            poODS = (GDALDataset *) GDALOpen(osOvrFilename,poDS->GetAccess());
+            poODS = static_cast<GDALDataset *>(GDALOpen(osOvrFilename, poDS->GetAccess()));
             CPLPopErrorHandler();
         }
     }
@@ -320,15 +336,13 @@ void GDALDefaultOverviews::OverviewScan()
 /* -------------------------------------------------------------------- */
     if( poODS )
     {
-        int nOverviewCount = GetOverviewCount(1);
+        const int nOverviewCount = GetOverviewCount(1);
 
         for( int iOver = 0; iOver < nOverviewCount; iOver++ )
         {
-            GDALRasterBand *poBand = GetOverview( 1, iOver );
-            GDALDataset    *poOverDS = NULL;
-
-            if( poBand != NULL )
-                poOverDS = poBand->GetDataset();
+            GDALRasterBand * const poBand = GetOverview( 1, iOver );
+            GDALDataset * const poOverDS = poBand != NULL ?
+                poBand->GetDataset() : NULL;
 
             if( poOverDS != NULL )
             {
@@ -346,20 +360,17 @@ void GDALDefaultOverviews::OverviewScan()
 int GDALDefaultOverviews::GetOverviewCount( int nBand )
 
 {
-
     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
         return 0;
 
     GDALRasterBand * poBand = poODS->GetRasterBand( nBand );
     if( poBand == NULL )
         return 0;
-    else
-    {
-        if( bOvrIsAux )
-            return poBand->GetOverviewCount();
-        else
-            return poBand->GetOverviewCount() + 1;
-    }
+
+    if( bOvrIsAux )
+        return poBand->GetOverviewCount();
+
+    return poBand->GetOverviewCount() + 1;
 }
 
 /************************************************************************/
@@ -373,22 +384,21 @@ GDALDefaultOverviews::GetOverview( int nBand, int iOverview )
     if( poODS == NULL || nBand < 1 || nBand > poODS->GetRasterCount() )
         return NULL;
 
-    GDALRasterBand * poBand = poODS->GetRasterBand( nBand );
+    GDALRasterBand * const poBand = poODS->GetRasterBand( nBand );
     if( poBand == NULL )
         return NULL;
 
     if( bOvrIsAux )
         return poBand->GetOverview( iOverview );
 
-    else // TIFF case, base is overview 0.
-    {
-        if( iOverview == 0 )
-            return poBand;
-        else if( iOverview-1 >= poBand->GetOverviewCount() )
-            return NULL;
-        else
-            return poBand->GetOverview( iOverview-1 );
-    }
+    // TIFF case, base is overview 0.
+    if( iOverview == 0 )
+        return poBand;
+
+    if( iOverview-1 >= poBand->GetOverviewCount() )
+        return NULL;
+
+    return poBand->GetOverview( iOverview-1 );
 }
 
 /************************************************************************/
@@ -414,25 +424,22 @@ int GDALOvLevelAdjust( int nOvLevel, int nXSize )
     return (int) (0.5 + nXSize / (double) nOXSize);
 }
 
-
 int GDALOvLevelAdjust2( int nOvLevel, int nXSize, int nYSize )
 
 {
-    /* Select the larger dimension to have increased accuracy, but */
-    /* with a slight preference to x even if (a bit) smaller than y */
-    /* in an attempt to behave closer as previous behaviour */
+    // Select the larger dimension to have increased accuracy, but
+    // with a slight preference to x even if (a bit) smaller than y
+    // in an attempt to behave closer as previous behaviour.
     if( nXSize >= nYSize / 2 && !(nXSize < nYSize && nXSize < nOvLevel) )
     {
-        int     nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
+        const int nOXSize = (nXSize + nOvLevel - 1) / nOvLevel;
 
-        return (int) (0.5 + nXSize / (double) nOXSize);
+        return static_cast<int>(0.5 + nXSize / static_cast<double>(nOXSize));
     }
-    else
-    {
-        int     nOYSize = (nYSize + nOvLevel - 1) / nOvLevel;
 
-        return (int) (0.5 + nYSize / (double) nOYSize);
-    }
+    const int nOYSize = (nYSize + nOvLevel - 1) / nOvLevel;
+
+    return static_cast<int>(0.5 + nYSize / static_cast<double>(nOYSize));
 }
 
 /************************************************************************/
@@ -442,19 +449,15 @@ int GDALOvLevelAdjust2( int nOvLevel, int nXSize, int nYSize )
 int GDALComputeOvFactor( int nOvrXSize, int nRasterXSize,
                          int nOvrYSize, int nRasterYSize )
 {
-    /* Select the larger dimension to have increased accuracy, but */
-    /* with a slight preference to x even if (a bit) smaller than y */
-    /* in an attempt to behave closer as previous behaviour */
+    // Select the larger dimension to have increased accuracy, but
+    // with a slight preference to x even if (a bit) smaller than y
+    // in an attempt to behave closer as previous behaviour.
     if( nRasterXSize >= nRasterYSize / 2 )
     {
-        return (int)
-                (0.5 + nRasterXSize / (double) nOvrXSize);
-    }
-    else
-    {
-        return (int)
-                (0.5 + nRasterYSize / (double) nOvrYSize);
+        return static_cast<int>(0.5 + nRasterXSize / static_cast<double>(nOvrXSize));
     }
+
+    return static_cast<int>(0.5 + nRasterYSize / static_cast<double>(nOvrYSize));
 }
 
 /************************************************************************/
@@ -475,11 +478,8 @@ CPLErr GDALDefaultOverviews::CleanOverviews()
     GDALClose( poODS );
     poODS = NULL;
 
-    CPLErr eErr;
-    if( poOvrDriver != NULL )
-        eErr = poOvrDriver->Delete( osOvrFilename );
-    else
-        eErr = CE_None;
+    const CPLErr eErr = poOvrDriver != NULL ?
+        poOvrDriver->Delete( osOvrFilename ) : CE_None;
 
     // Reset the saved overview filename.
     if( !EQUAL(poDS->GetDescription(),":::VIRTUAL:::") )
@@ -492,7 +492,9 @@ CPLErr GDALDefaultOverviews::CleanOverviews()
             osOvrFilename.Printf( "%s.ovr", poDS->GetDescription() );
     }
     else
+    {
         osOvrFilename = "";
+    }
 
     return eErr;
 }
@@ -512,24 +514,28 @@ GDALDefaultOverviews::BuildOverviewsSubDataset(
 {
     if( osOvrFilename.length() == 0 && nOverviews > 0 )
     {
-        int iSequence = 0;
         VSIStatBufL sStatBuf;
 
+        int iSequence = 0;  // Used after for.
         for( iSequence = 0; iSequence < 100; iSequence++ )
         {
             osOvrFilename.Printf( "%s_%d.ovr", pszPhysicalFile, iSequence );
-            if( VSIStatExL( osOvrFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
+            if( VSIStatExL( osOvrFilename, &sStatBuf,
+                            VSI_STAT_EXISTS_FLAG ) != 0 )
             {
                 CPLString osAdjustedOvrFilename;
 
                 if( poDS->GetMOFlags() & GMO_PAM_CLASS )
                 {
-                    osAdjustedOvrFilename.Printf( ":::BASE:::%s_%d.ovr",
-                                                  CPLGetFilename(pszPhysicalFile),
-                                                  iSequence );
+                    osAdjustedOvrFilename.Printf(
+                        ":::BASE:::%s_%d.ovr",
+                        CPLGetFilename(pszPhysicalFile),
+                        iSequence );
                 }
                 else
+                {
                     osAdjustedOvrFilename = osOvrFilename;
+                }
 
                 poDS->SetMetadataItem( "OVERVIEW_FILE",
                                        osAdjustedOvrFilename,
@@ -559,9 +565,6 @@ GDALDefaultOverviews::BuildOverviews(
     GDALProgressFunc pfnProgress, void * pProgressData)
 
 {
-    CPLErr       eErr;
-    int          i;
-
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
@@ -577,11 +580,11 @@ GDALDefaultOverviews::BuildOverviews(
         bOvrIsAux = CPLTestBool(CPLGetConfigOption( "USE_RRD", "NO" ));
         if( bOvrIsAux )
         {
-            VSIStatBufL sStatBuf;
-
             osOvrFilename = CPLResetExtension(poDS->GetDescription(),"aux");
 
-            if( VSIStatExL( osOvrFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+            VSIStatBufL sStatBuf;
+            if( VSIStatExL( osOvrFilename, &sStatBuf,
+                            VSI_STAT_EXISTS_FLAG ) == 0 )
                 osOvrFilename.Printf( "%s.aux", poDS->GetDescription() );
         }
     }
@@ -592,7 +595,8 @@ GDALDefaultOverviews::BuildOverviews(
     else if( poODS->GetAccess() == GA_ReadOnly )
     {
         GDALClose( poODS );
-        poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update );
+        poODS = static_cast<GDALDataset *>(
+            GDALOpen( osOvrFilename, GA_Update ));
         if( poODS == NULL )
             return CE_Failure;
     }
@@ -604,9 +608,9 @@ GDALDefaultOverviews::BuildOverviews(
     if( !bOvrIsAux && nBands != poDS->GetRasterCount() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Generation of overviews in external TIFF currently only"
-                  " supported when operating on all bands.\n"
-                  "Operation failed.\n" );
+                  "Generation of overviews in external TIFF currently only "
+                  "supported when operating on all bands.  "
+                  "Operation failed." );
         return CE_Failure;
     }
 
@@ -633,38 +637,48 @@ GDALDefaultOverviews::BuildOverviews(
     GDALRasterBand *poBand = poDS->GetRasterBand( 1 );
 
     int nNewOverviews = 0;
-    int *panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews);
-    for( i = 0; i < nOverviews && poBand != NULL; i++ )
+    int *panNewOverviewList = static_cast<int *>(
+        CPLCalloc(sizeof(int), nOverviews) );
+    double dfAreaNewOverviews = 0;
+    double dfAreaRefreshedOverviews = 0;
+    for( int i = 0; i < nOverviews && poBand != NULL; i++ )
     {
         for( int j = 0; j < poBand->GetOverviewCount(); j++ )
         {
-            int    nOvFactor;
             GDALRasterBand * poOverview = poBand->GetOverview( j );
-            if (poOverview == NULL)
+            if( poOverview == NULL )
                 continue;
 
-            nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
-                                             poBand->GetXSize(),
-                                             poOverview->GetYSize(),
-                                             poBand->GetYSize());
+            int nOvFactor =
+                GDALComputeOvFactor(poOverview->GetXSize(),
+                                    poBand->GetXSize(),
+                                    poOverview->GetYSize(),
+                                    poBand->GetYSize());
 
             if( nOvFactor == panOverviewList[i]
                 || nOvFactor == GDALOvLevelAdjust2( panOverviewList[i],
                                                    poBand->GetXSize(),
                                                    poBand->GetYSize() ) )
+            {
                 panOverviewList[i] *= -1;
+            }
         }
 
+        const double dfArea = 1.0 / (panOverviewList[i] * panOverviewList[i]);
+        dfAreaRefreshedOverviews += dfArea;
         if( panOverviewList[i] > 0 )
+        {
+            dfAreaNewOverviews += dfArea;
             panNewOverviewList[nNewOverviews++] = panOverviewList[i];
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Build band list.                                                */
 /* -------------------------------------------------------------------- */
-    GDALRasterBand **pahBands
-        = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands);
-    for( i = 0; i < nBands; i++ )
+    GDALRasterBand **pahBands = static_cast<GDALRasterBand **>(
+        CPLCalloc(sizeof(GDALRasterBand *), nBands) );
+    for( int i = 0; i < nBands; i++ )
         pahBands[i] = poDS->GetRasterBand( panBandList[i] );
 
 /* -------------------------------------------------------------------- */
@@ -674,6 +688,11 @@ GDALDefaultOverviews::BuildOverviews(
 /*      produce the imagery.                                            */
 /* -------------------------------------------------------------------- */
 
+    CPLErr eErr = CE_None;
+
+    void* pScaledProgress = GDALCreateScaledProgress(
+            0, dfAreaNewOverviews / dfAreaRefreshedOverviews,
+            pfnProgress, pProgressData );
     if( bOvrIsAux )
     {
         if( nNewOverviews == 0 )
@@ -681,15 +700,16 @@ GDALDefaultOverviews::BuildOverviews(
             /* if we call HFAAuxBuildOverviews() with nNewOverviews == 0 */
             /* because that there's no new, this will wipe existing */
             /* overviews (#4831) */
-            eErr = CE_None;
+            // eErr = CE_None;
         }
         else
+        {
             eErr = HFAAuxBuildOverviews( osOvrFilename, poDS, &poODS,
                                      nBands, panBandList,
                                      nNewOverviews, panNewOverviewList,
                                      pszResampling,
-                                     pfnProgress, pProgressData );
-
+                                     GDALScaledProgress, pScaledProgress );
+        }
         for( int j = 0; j < nOverviews; j++ )
         {
             if( panOverviewList[j] > 0 )
@@ -711,7 +731,8 @@ GDALDefaultOverviews::BuildOverviews(
 
         eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands,
                                     nNewOverviews, panNewOverviewList,
-                                    pszResampling, pfnProgress, pProgressData );
+                                    pszResampling,
+                                    GDALScaledProgress, pScaledProgress );
 
         // Probe for proxy overview filename.
         if( eErr == CE_Failure )
@@ -725,49 +746,51 @@ GDALDefaultOverviews::BuildOverviews(
                 eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands,
                                             nNewOverviews, panNewOverviewList,
                                             pszResampling,
-                                            pfnProgress, pProgressData );
+                                            GDALScaledProgress, pScaledProgress );
             }
         }
 
         if( eErr == CE_None )
         {
-            poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update );
+            poODS = static_cast<GDALDataset *>(
+                GDALOpen( osOvrFilename, GA_Update ) );
             if( poODS == NULL )
                 eErr = CE_Failure;
         }
     }
 
+    GDALDestroyScaledProgress( pScaledProgress );
+
 /* -------------------------------------------------------------------- */
 /*      Refresh old overviews that were listed.                         */
 /* -------------------------------------------------------------------- */
-    GDALRasterBand **papoOverviewBands;
-
-    papoOverviewBands = (GDALRasterBand **)
-        CPLCalloc(sizeof(void*),nOverviews);
+    GDALRasterBand **papoOverviewBands = static_cast<GDALRasterBand **>(
+        CPLCalloc(sizeof(void*), nOverviews) );
 
     for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
     {
         poBand = poDS->GetRasterBand( panBandList[iBand] );
 
         nNewOverviews = 0;
-        for( i = 0; i < nOverviews && poBand != NULL; i++ )
+        for( int i = 0; i < nOverviews && poBand != NULL; i++ )
         {
             for( int j = 0; j < poBand->GetOverviewCount(); j++ )
             {
                 GDALRasterBand * poOverview = poBand->GetOverview( j );
-                if (poOverview == NULL)
+                if( poOverview == NULL )
                     continue;
 
-                int bHasNoData;
+                int bHasNoData = FALSE;
                 double noDataValue = poBand->GetNoDataValue(&bHasNoData);
 
-                if (bHasNoData)
+                if( bHasNoData )
                   poOverview->SetNoDataValue(noDataValue);
 
-                int nOvFactor = GDALComputeOvFactor(poOverview->GetXSize(),
-                                                 poBand->GetXSize(),
-                                                 poOverview->GetYSize(),
-                                                 poBand->GetYSize());
+                const int nOvFactor =
+                    GDALComputeOvFactor(poOverview->GetXSize(),
+                                        poBand->GetXSize(),
+                                        poOverview->GetYSize(),
+                                        poBand->GetYSize());
 
                 if( nOvFactor == - panOverviewList[i]
                     || (panOverviewList[i] < 0 &&
@@ -783,11 +806,18 @@ GDALDefaultOverviews::BuildOverviews(
 
         if( nNewOverviews > 0 )
         {
+            const double dfOffset = dfAreaNewOverviews / dfAreaRefreshedOverviews;
+            const double dfScale = 1.0 - dfOffset;
+            pScaledProgress = GDALCreateScaledProgress(
+                    dfOffset + dfScale * iBand / nBands,
+                    dfOffset + dfScale * (iBand+1) / nBands,
+                    pfnProgress, pProgressData );
             eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand,
                                             nNewOverviews,
                                             (GDALRasterBandH*)papoOverviewBands,
                                             pszResampling,
-                                            pfnProgress, pProgressData );
+                                            GDALScaledProgress, pScaledProgress );
+            GDALDestroyScaledProgress( pScaledProgress );
         }
     }
 
@@ -799,15 +829,16 @@ GDALDefaultOverviews::BuildOverviews(
     CPLFree( pahBands );
 
 /* -------------------------------------------------------------------- */
-/*      If we have a mask file, we need to build it's overviews         */
-/*      too.                                                            */
+/*      If we have a mask file, we need to build its overviews too.     */
 /* -------------------------------------------------------------------- */
     if( HaveMaskFile() && poMaskDS )
     {
-        /* Some config option are not compatible with mask overviews */
-        /* so unset them, and define more sensible values */
-        int bJPEG = EQUAL(CPLGetConfigOption("COMPRESS_OVERVIEW", ""), "JPEG");
-        int bPHOTOMETRIC_YCBCR = EQUAL(CPLGetConfigOption("PHOTOMETRIC_OVERVIEW", ""), "YCBCR");
+        // Some config option are not compatible with mask overviews
+        // so unset them, and define more sensible values.
+        const bool bJPEG =
+            EQUAL(CPLGetConfigOption("COMPRESS_OVERVIEW", ""), "JPEG");
+        const bool bPHOTOMETRIC_YCBCR =
+            EQUAL(CPLGetConfigOption("PHOTOMETRIC_OVERVIEW", ""), "YCBCR");
         if( bJPEG )
             CPLSetThreadLocalConfigOption("COMPRESS_OVERVIEW", "DEFLATE");
         if( bPHOTOMETRIC_YCBCR )
@@ -816,7 +847,7 @@ GDALDefaultOverviews::BuildOverviews(
         poMaskDS->BuildOverviews( pszResampling, nOverviews, panOverviewList,
                                   0, NULL, pfnProgress, pProgressData );
 
-        /* Restore config option */
+        // Restore config option.
         if( bJPEG )
             CPLSetThreadLocalConfigOption("COMPRESS_OVERVIEW", "JPEG");
         if( bPHOTOMETRIC_YCBCR )
@@ -824,8 +855,8 @@ GDALDefaultOverviews::BuildOverviews(
 
         if( bOwnMaskDS )
         {
-            /* Reset the poMask member of main dataset bands, since it */
-            /* will become invalid after poMaskDS closing */
+            // Reset the poMask member of main dataset bands, since it
+            // will become invalid after poMaskDS closing.
             for( int iBand = 1; iBand <= poDS->GetRasterCount(); iBand ++ )
             {
                 GDALRasterBand *poOtherBand = poDS->GetRasterBand(iBand);
@@ -838,8 +869,8 @@ GDALDefaultOverviews::BuildOverviews(
 
         // force next request to reread mask file.
         poMaskDS = NULL;
-        bOwnMaskDS = FALSE;
-        bCheckedForMask = FALSE;
+        bOwnMaskDS = false;
+        bCheckedForMask = false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -849,18 +880,15 @@ GDALDefaultOverviews::BuildOverviews(
 /* -------------------------------------------------------------------- */
     if( poODS )
     {
-        int nOverviewCount = GetOverviewCount(1);
-        int iOver;
+        const int nOverviewCount = GetOverviewCount(1);
 
-        for( iOver = 0; iOver < nOverviewCount; iOver++ )
+        for( int iOver = 0; iOver < nOverviewCount; iOver++ )
         {
             GDALRasterBand *poOtherBand = GetOverview( 1, iOver );
-            GDALDataset    *poOverDS = NULL;
-
-            if( poOtherBand != NULL )
-                poOverDS = poOtherBand->GetDataset();
+            GDALDataset *poOverDS = poOtherBand != NULL ?
+                poOtherBand->GetDataset() : NULL;
 
-            if (poOverDS != NULL)
+            if( poOverDS != NULL )
             {
                 poOverDS->oOvManager.poBaseDS = poDS;
                 poOverDS->oOvManager.poDS = poOverDS;
@@ -891,29 +919,27 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
 /* -------------------------------------------------------------------- */
     if( poMaskDS == NULL )
     {
-        GDALDriver *poDr = (GDALDriver *) GDALGetDriverByName( "GTiff" );
+        GDALDriver * const poDr =
+            static_cast<GDALDriver *>( GDALGetDriverByName( "GTiff" ) );
 
         if( poDr == NULL )
             return CE_Failure;
 
-        GDALRasterBand *poTBand = poDS->GetRasterBand(1);
+        GDALRasterBand * const poTBand = poDS->GetRasterBand(1);
         if( poTBand == NULL )
             return CE_Failure;
 
-        int nBands;
-        if( nFlags & GMF_PER_DATASET )
-            nBands = 1;
-        else
-            nBands = poDS->GetRasterCount();
+        const int nBands = (nFlags & GMF_PER_DATASET) ?
+            1 : poDS->GetRasterCount();
 
-        char **papszOpt = NULL;
-        papszOpt = CSLSetNameValue( papszOpt, "COMPRESS", "DEFLATE" );
+        char **papszOpt = CSLSetNameValue( NULL, "COMPRESS", "DEFLATE" );
         papszOpt = CSLSetNameValue( papszOpt, "INTERLEAVE", "BAND" );
 
-        int  nBX, nBY;
+        int nBX = 0;
+        int nBY = 0;
         poTBand->GetBlockSize( &nBX, &nBY );
 
-        // try to create matching tile size if legal in TIFF.
+        // Try to create matching tile size if legal in TIFF.
         if( (nBX % 16) == 0 && (nBY % 16) == 0 )
         {
             papszOpt = CSLSetNameValue( papszOpt, "TILED", "YES" );
@@ -931,10 +957,10 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
                                  nBands, GDT_Byte, papszOpt );
         CSLDestroy( papszOpt );
 
-        if( poMaskDS == NULL ) // presumably error already issued.
+        if( poMaskDS == NULL )  // Presumably error already issued.
             return CE_Failure;
 
-        bOwnMaskDS = TRUE;
+        bOwnMaskDS = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -943,7 +969,7 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
     if( nBand > poMaskDS->GetRasterCount() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to create a mask band for band %d of %s,\n"
+                  "Attempt to create a mask band for band %d of %s, "
                   "but the .msk file has a PER_DATASET mask.",
                   nBand, poDS->GetDescription() );
         return CE_Failure;
@@ -968,12 +994,15 @@ CPLErr GDALDefaultOverviews::CreateMaskBand( int nFlags, int nBand )
 /*                            GetMaskBand()                             */
 /************************************************************************/
 
+// Secret code meaning we don't handle this band.
+static const int MISSING_FLAGS = 0x8000;
+
 GDALRasterBand *GDALDefaultOverviews::GetMaskBand( int nBand )
 
 {
     const int nFlags = GetMaskFlags( nBand );
 
-    if( nFlags == 0x8000 ) // secret code meaning we don't handle this band.
+    if( nFlags == MISSING_FLAGS )
         return NULL;
 
     if( nFlags & GMF_PER_DATASET )
@@ -1001,10 +1030,10 @@ int GDALDefaultOverviews::GetMaskFlags( int nBand )
 
     const char *pszValue =
         poMaskDS->GetMetadataItem(
-            CPLString().Printf( "INTERNAL_MASK_FLAGS_%d", MAX(nBand,1)) );
+            CPLString().Printf( "INTERNAL_MASK_FLAGS_%d", std::max(nBand, 1)) );
 
     if( pszValue == NULL )
-        return 0x8000;
+        return MISSING_FLAGS;
 
     return atoi(pszValue);
 }
@@ -1035,20 +1064,18 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
 /* -------------------------------------------------------------------- */
     if( poBaseDS != NULL && poBaseDS->oOvManager.HaveMaskFile() )
     {
-        GDALRasterBand *poBaseBand = poBaseDS->GetRasterBand(1);
-        GDALRasterBand *poBaseMask = NULL;
-
-        if( poBaseBand != NULL )
-            poBaseMask = poBaseBand->GetMaskBand();
+        GDALRasterBand * const poBaseBand = poBaseDS->GetRasterBand(1);
+        GDALRasterBand * poBaseMask = poBaseBand != NULL ?
+            poBaseBand->GetMaskBand() : NULL;
 
-        int nOverviewCount = 0;
-        if( poBaseMask )
-            nOverviewCount = poBaseMask->GetOverviewCount();
+        const int nOverviewCount = poBaseMask != NULL ?
+            poBaseMask->GetOverviewCount() : 0;
 
         for( int iOver = 0; iOver < nOverviewCount; iOver++ )
         {
-            GDALRasterBand *poOverBand = poBaseMask->GetOverview( iOver );
-            if (poOverBand == NULL)
+            GDALRasterBand * const poOverBand =
+                poBaseMask->GetOverview( iOver );
+            if( poOverBand == NULL )
                 continue;
 
             if( poOverBand->GetXSize() == poDS->GetRasterXSize()
@@ -1059,8 +1086,8 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
             }
         }
 
-        bCheckedForMask = TRUE;
-        bOwnMaskDS = FALSE;
+        bCheckedForMask = true;
+        bOwnMaskDS = false;
 
         CPLAssert( poMaskDS != poDS );
 
@@ -1077,8 +1104,7 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
 /* -------------------------------------------------------------------- */
 /*      Check for .msk file.                                            */
 /* -------------------------------------------------------------------- */
-    CPLString osMskFilename;
-    bCheckedForMask = TRUE;
+    bCheckedForMask = true;
 
     if( pszBasename == NULL )
         pszBasename = poDS->GetDescription();
@@ -1089,22 +1115,29 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
 
     if( !GDALCanFileAcceptSidecarFile(pszBasename) )
         return FALSE;
+    CPLString osMskFilename;
     osMskFilename.Printf( "%s.msk", pszBasename );
 
     std::vector<char> achMskFilename;
     achMskFilename.resize(osMskFilename.size() + 1);
-    memcpy(&(achMskFilename[0]), osMskFilename.c_str(), osMskFilename.size() + 1);
-    int bExists = CPLCheckForFile( &achMskFilename[0],
-                                   papszSiblingFiles );
+    memcpy(&(achMskFilename[0]),
+           osMskFilename.c_str(),
+           osMskFilename.size() + 1);
+    bool bExists = CPL_TO_BOOL(
+        CPLCheckForFile( &achMskFilename[0],
+                         papszSiblingFiles ) );
     osMskFilename = &achMskFilename[0];
 
 #if !defined(WIN32)
     if( !bExists && !papszSiblingFiles )
     {
         osMskFilename.Printf( "%s.MSK", pszBasename );
-        memcpy(&(achMskFilename[0]), osMskFilename.c_str(), osMskFilename.size() + 1);
-        bExists = CPLCheckForFile( &achMskFilename[0],
-                                   papszSiblingFiles );
+        memcpy(&(achMskFilename[0]),
+               osMskFilename.c_str(),
+               osMskFilename.size() + 1);
+        bExists = CPL_TO_BOOL(
+            CPLCheckForFile( &achMskFilename[0],
+                             papszSiblingFiles ) );
         osMskFilename = &achMskFilename[0];
     }
 #endif
@@ -1115,16 +1148,18 @@ int GDALDefaultOverviews::HaveMaskFile( char ** papszSiblingFiles,
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    poMaskDS = (GDALDataset *) GDALOpenEx( osMskFilename,
-                                           GDAL_OF_RASTER |
-                                           ((poDS->GetAccess() == GA_Update) ? GDAL_OF_UPDATE : 0),
-                                           NULL, NULL, papszInitSiblingFiles );
+    poMaskDS = static_cast<GDALDataset *>(
+        GDALOpenEx( osMskFilename,
+                    GDAL_OF_RASTER |
+                    (poDS->GetAccess() == GA_Update ? GDAL_OF_UPDATE : 0),
+                    NULL, NULL, papszInitSiblingFiles ));
     CPLAssert( poMaskDS != poDS );
 
     if( poMaskDS == NULL )
         return FALSE;
 
-    bOwnMaskDS = TRUE;
+    bOwnMaskDS = true;
 
     return TRUE;
 }
+//! @endcond
diff --git a/gcore/gdaldllmain.cpp b/gcore/gdaldllmain.cpp
index d3d3bf1..f987d8e 100644
--- a/gcore/gdaldllmain.cpp
+++ b/gcore/gdaldllmain.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL Core
  * Purpose:  The library set-up/clean-up routines.
@@ -28,16 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal.h"
-#include "ogr_api.h"
-#include "cpl_multiproc.h"
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
 #include "cpl_string.h"
+#include "ogr_api.h"
+
 
-static int bInGDALGlobalDestructor = FALSE;
-extern "C" int CPL_DLL GDALIsInGlobalDestructor(void);
+static bool bInGDALGlobalDestructor = false;
+extern "C" int CPL_DLL GDALIsInGlobalDestructor();
 
-int GDALIsInGlobalDestructor(void)
+int GDALIsInGlobalDestructor()
 {
     return bInGDALGlobalDestructor;
 }
@@ -70,11 +73,11 @@ void GDALDestroy(void)
     bGDALDestroyAlreadyCalled = true;
 
     CPLDebug("GDAL", "In GDALDestroy - unloading GDAL shared library.");
-    bInGDALGlobalDestructor = TRUE;
+    bInGDALGlobalDestructor = true;
     GDALDestroyDriverManager();
 
     OGRCleanupAll();
-    bInGDALGlobalDestructor = FALSE;
+    bInGDALGlobalDestructor = false;
 
     /* See https://trac.osgeo.org/gdal/ticket/6139 */
     /* Needed in case no driver manager has been instantiated. */
@@ -125,7 +128,6 @@ static void GDALDestructor(void)
 
 #endif // __GNUC__
 
-
 /************************************************************************/
 /*  The library set-up/clean-up routine implemented as DllMain entry    */
 /*  point specific for Windows.                                         */
@@ -134,11 +136,10 @@ static void GDALDestructor(void)
 
 #include <windows.h>
 
-extern "C" int WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
+extern "C" int WINAPI DllMain( HINSTANCE /* hInstance */,
+                               DWORD dwReason,
+                               LPVOID /* lpReserved */ )
 {
-    UNREFERENCED_PARAMETER(hInstance);
-    UNREFERENCED_PARAMETER(lpReserved);
-
     if (dwReason == DLL_PROCESS_ATTACH)
     {
         // nothing to do
diff --git a/gcore/gdaldriver.cpp b/gcore/gdaldriver.cpp
index eb8c654..e3f32c3 100644
--- a/gcore/gdaldriver.cpp
+++ b/gcore/gdaldriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaldriver.cpp 33711 2016-03-12 06:29:35Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriver class (and C wrappers)
@@ -28,35 +27,49 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal.h"
 #include "gdal_priv.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "ogr_core.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: gdaldriver.cpp 33711 2016-03-12 06:29:35Z goatbar $");
+CPL_CVSID("$Id: gdaldriver.cpp 37656 2017-03-09 13:19:58Z rouault $");
 
 CPL_C_START
-const char* GDALClientDatasetGetFilename(const char* pszFilename);
+// TODO(schwehr): Why is this not in a header?
+const char* GDALClientDatasetGetFilename( const char* pszFilename );
 CPL_C_END
 
 /************************************************************************/
 /*                             GDALDriver()                             */
 /************************************************************************/
 
-GDALDriver::GDALDriver()
-
-{
-    pfnOpen = NULL;
-    pfnCreate = NULL;
-    pfnDelete = NULL;
-    pfnCreateCopy = NULL;
-    pfnUnloadDriver = NULL;
-    pDriverData = NULL;
-    pfnIdentify = NULL;
-    pfnRename = NULL;
-    pfnCopyFiles = NULL;
-    pfnOpenWithDriverArg = NULL;
-    pfnCreateVectorOnly = NULL;
-    pfnDeleteDataSource = NULL;
-}
+GDALDriver::GDALDriver() :
+    pfnOpen(NULL),
+    pfnCreate(NULL),
+    pfnDelete(NULL),
+    pfnCreateCopy(NULL),
+    pDriverData(NULL),
+    pfnUnloadDriver(NULL),
+    pfnIdentify(NULL),
+    pfnRename(NULL),
+    pfnCopyFiles(NULL),
+    pfnOpenWithDriverArg(NULL),
+    pfnCreateVectorOnly(NULL),
+    pfnDeleteDataSource(NULL)
+{}
 
 /************************************************************************/
 /*                            ~GDALDriver()                             */
@@ -87,7 +100,7 @@ void CPL_STDCALL GDALDestroyDriver( GDALDriverH hDriver )
 
 {
     if( hDriver != NULL )
-        delete ((GDALDriver *) hDriver);
+        delete static_cast<GDALDriver *>(hDriver);
 }
 
 /************************************************************************/
@@ -100,17 +113,18 @@ void CPL_STDCALL GDALDestroyDriver( GDALDriverH hDriver )
  * What argument values are legal for particular drivers is driver specific,
  * and there is no way to query in advance to establish legal values.
  *
- * That function will try to validate the creation option list passed to the driver
- * with the GDALValidateCreationOptions() method. This check can be disabled
- * by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS=NO.
+ * That function will try to validate the creation option list passed to the
+ * driver with the GDALValidateCreationOptions() method. This check can be
+ * disabled by defining the configuration option
+ * GDAL_VALIDATE_CREATION_OPTIONS=NO.
  *
- * After you have finished working with the returned dataset, it is <b>required</b>
- * to close it with GDALClose(). This does not only close the file handle, but
- * also ensures that all the data and metadata has been written to the dataset
- * (GDALFlushCache() is not sufficient for that purpose).
+ * After you have finished working with the returned dataset, it is
+ * <b>required</b> to close it with GDALClose(). This does not only close the
+ * file handle, but also ensures that all the data and metadata has been written
+ * to the dataset (GDALFlushCache() is not sufficient for that purpose).
  *
- * In some situations, the new dataset can be created in another process through the
- * \ref gdal_api_proxy mechanism.
+ * In some situations, the new dataset can be created in another process through
+ * the \ref gdal_api_proxy mechanism.
  *
  * In GDAL 2, the arguments nXSize, nYSize and nBands can be passed to 0 when
  * creating a vector-only dataset for a compatible driver.
@@ -134,8 +148,6 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
                                   GDALDataType eType, char ** papszOptions )
 
 {
-    //CPLLocaleC  oLocaleForcer;
-
 /* -------------------------------------------------------------------- */
 /*      Does this format support creation.                              */
 /* -------------------------------------------------------------------- */
@@ -143,14 +155,14 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "GDALDriver::Create() ... no create method implemented"
-                  " for this format.\n" );
+                  " for this format." );
 
         return NULL;
     }
 /* -------------------------------------------------------------------- */
 /*      Do some rudimentary argument checking.                          */
 /* -------------------------------------------------------------------- */
-    if (nBands < 0)
+    if( nBands < 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Attempt to create dataset with %d bands is illegal,"
@@ -177,14 +189,15 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
         GDALDriver* poAPIPROXYDriver = GDALGetAPIPROXYDriver();
         if( poAPIPROXYDriver != this )
         {
-            if( poAPIPROXYDriver == NULL || poAPIPROXYDriver->pfnCreate == NULL )
+            if( poAPIPROXYDriver == NULL ||
+                poAPIPROXYDriver->pfnCreate == NULL )
                 return NULL;
             char** papszOptionsDup = CSLDuplicate(papszOptions);
             papszOptionsDup = CSLAddNameValue(papszOptionsDup, "SERVER_DRIVER",
-                                               GetDescription());
+                                              GetDescription());
             GDALDataset* poDstDS = poAPIPROXYDriver->pfnCreate(
                 pszClientFilename, nXSize, nYSize, nBands,
-                eType, papszOptionsDup);
+                eType, papszOptionsDup );
 
             CSLDestroy(papszOptionsDup);
 
@@ -208,36 +221,33 @@ GDALDataset * GDALDriver::Create( const char * pszFilename,
 /*      name.  But even if that seems to fail we will continue since    */
 /*      it might just be a corrupt file or something.                   */
 /* -------------------------------------------------------------------- */
-    if( !CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE) )
+    if( !CPLFetchBool(papszOptions, "APPEND_SUBDATASET", false) )
         QuietDelete( pszFilename );
 
 /* -------------------------------------------------------------------- */
 /*      Validate creation options.                                      */
 /* -------------------------------------------------------------------- */
-    if (CPLTestBool(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
+    if( CPLTestBool(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS",
+                                       "YES")) )
         GDALValidateCreationOptions( this, papszOptions );
 
 /* -------------------------------------------------------------------- */
 /*      Proceed with creation.                                          */
 /* -------------------------------------------------------------------- */
-    GDALDataset *poDS;
-
     CPLDebug( "GDAL", "GDALDriver::Create(%s,%s,%d,%d,%d,%s,%p)",
               GetDescription(), pszFilename, nXSize, nYSize, nBands,
               GDALGetDataTypeName( eType ),
               papszOptions );
 
+    GDALDataset *poDS = NULL;
     if( pfnCreate != NULL )
     {
         poDS = pfnCreate( pszFilename, nXSize, nYSize, nBands, eType,
                           papszOptions );
     }
-    else
+    else if( nBands < 1 )
     {
-        if( nBands > 0 )
-            poDS = NULL;
-        else
-            poDS = pfnCreateVectorOnly( this, pszFilename, papszOptions );
+        poDS = pfnCreateVectorOnly( this, pszFilename, papszOptions );
     }
 
     if( poDS != NULL )
@@ -273,40 +283,42 @@ GDALCreate( GDALDriverH hDriver, const char * pszFilename,
 {
     VALIDATE_POINTER1( hDriver, "GDALCreate", NULL );
 
-    return( ((GDALDriver *) hDriver)->Create( pszFilename,
-                                              nXSize, nYSize, nBands,
-                                              eBandType, papszOptions ) );
+    return
+        static_cast<GDALDriver *>(hDriver)->Create( pszFilename,
+                                                    nXSize, nYSize, nBands,
+                                                    eBandType, papszOptions );
 }
 
 /************************************************************************/
 /*                          DefaultCopyMasks()                          */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
                                      GDALDataset *poDstDS,
                                      int bStrict )
 
 {
-    CPLErr eErr = CE_None;
-
     int nBands = poSrcDS->GetRasterCount();
     if (nBands == 0)
         return CE_None;
 
-    const char* papszOptions[2] = { "COMPRESSED=YES", NULL };
-
 /* -------------------------------------------------------------------- */
 /*      Try to copy mask if it seems appropriate.                       */
 /* -------------------------------------------------------------------- */
+    const char* papszOptions[2] = { "COMPRESSED=YES", NULL };
+    CPLErr eErr = CE_None;
+
     for( int iBand = 0;
          eErr == CE_None && iBand < nBands;
-         iBand++ )
+         ++iBand )
     {
         GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
 
         int nMaskFlags = poSrcBand->GetMaskFlags();
         if( eErr == CE_None
-            && !(nMaskFlags & (GMF_ALL_VALID|GMF_PER_DATASET|GMF_ALPHA|GMF_NODATA) ) )
+            && !(nMaskFlags &
+                 (GMF_ALL_VALID|GMF_PER_DATASET|GMF_ALPHA|GMF_NODATA) ) )
         {
             GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand+1 );
             if (poDstBand != NULL)
@@ -317,11 +329,13 @@ CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
                     eErr = GDALRasterBandCopyWholeRaster(
                         poSrcBand->GetMaskBand(),
                         poDstBand->GetMaskBand(),
-                        (char**)papszOptions,
+                        papszOptions,
                         GDALDummyProgress, NULL);
                 }
                 else if( !bStrict )
+                {
                     eErr = CE_None;
+                }
             }
         }
     }
@@ -329,7 +343,7 @@ CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
 /* -------------------------------------------------------------------- */
 /*      Try to copy a per-dataset mask if we have one.                  */
 /* -------------------------------------------------------------------- */
-    int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
+    const int nMaskFlags = poSrcDS->GetRasterBand(1)->GetMaskFlags();
     if( eErr == CE_None
         && !(nMaskFlags & (GMF_ALL_VALID|GMF_ALPHA|GMF_NODATA) )
         && (nMaskFlags & GMF_PER_DATASET) )
@@ -340,11 +354,13 @@ CPLErr GDALDriver::DefaultCopyMasks( GDALDataset *poSrcDS,
             eErr = GDALRasterBandCopyWholeRaster(
                 poSrcDS->GetRasterBand(1)->GetMaskBand(),
                 poDstDS->GetRasterBand(1)->GetMaskBand(),
-                (char**)papszOptions,
+                papszOptions,
                 GDALDummyProgress, NULL);
         }
         else if( !bStrict )
+        {
             eErr = CE_None;
+        }
     }
 
     return eErr;
@@ -369,14 +385,15 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Validate that we can create the output as requested.            */
 /* -------------------------------------------------------------------- */
-    int          nXSize = poSrcDS->GetRasterXSize();
-    int          nYSize = poSrcDS->GetRasterYSize();
-    int          nBands = poSrcDS->GetRasterCount();
+    const int nXSize = poSrcDS->GetRasterXSize();
+    const int nYSize = poSrcDS->GetRasterYSize();
+    const int nBands = poSrcDS->GetRasterCount();
 
     CPLDebug( "GDAL", "Using default GDALDriver::CreateCopy implementation." );
 
-    int nLayerCount = poSrcDS->GetLayerCount();
-    if (nBands == 0 && nLayerCount == 0 && GetMetadataItem(GDAL_DCAP_VECTOR) == NULL )
+    const int nLayerCount = poSrcDS->GetLayerCount();
+    if( nBands == 0 && nLayerCount == 0 &&
+        GetMetadataItem(GDAL_DCAP_VECTOR) == NULL )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "GDALDriver::DefaultCreateCopy does not support zero band" );
@@ -389,7 +406,8 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
         GetMetadataItem(GDAL_DCAP_VECTOR) != NULL )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Source driver is raster-only whereas output driver is vector-only" );
+                  "Source driver is raster-only whereas output driver is "
+                  "vector-only" );
         return NULL;
     }
     else if( poSrcDS->GetDriver() != NULL &&
@@ -399,7 +417,8 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
         GetMetadataItem(GDAL_DCAP_VECTOR) == NULL )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Source driver is vector-only whereas output driver is raster-only" );
+                  "Source driver is vector-only whereas output driver is "
+                  "raster-only" );
         return NULL;
     }
 
@@ -415,13 +434,14 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 /*      didn't provide values.                                          */
 /* -------------------------------------------------------------------- */
     char **papszCreateOptions = CSLDuplicate( papszOptions );
-    int  iOptItem;
-    static const char * const apszOptItems[] = {
+    const char * const apszOptItems[] = {
         "NBITS", "IMAGE_STRUCTURE",
         "PIXELTYPE", "IMAGE_STRUCTURE",
         NULL };
 
-    for( iOptItem = 0; nBands > 0 && apszOptItems[iOptItem] != NULL; iOptItem += 2 )
+    for( int iOptItem = 0;
+         nBands > 0 && apszOptItems[iOptItem] != NULL;
+         iOptItem += 2 )
     {
         // does the source have this metadata item on the first band?
         const char *pszValue =
@@ -431,7 +451,7 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
         if( pszValue == NULL )
             continue;
 
-        // do not override provided value.
+        // Do not override provided value.
         if( CSLFetchNameValue( papszCreateOptions, pszValue ) != NULL )
             continue;
 
@@ -451,28 +471,29 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Create destination dataset.                                     */
 /* -------------------------------------------------------------------- */
-    GDALDataset  *poDstDS;
     GDALDataType eType = GDT_Unknown;
-    CPLErr       eErr = CE_None;
 
     if( nBands > 0 )
         eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
-    poDstDS = Create( pszFilename, nXSize, nYSize,
-                      nBands, eType, papszCreateOptions );
+    GDALDataset  *poDstDS = Create( pszFilename, nXSize, nYSize,
+                                    nBands, eType, papszCreateOptions );
 
     CSLDestroy(papszCreateOptions);
 
     if( poDstDS == NULL )
         return NULL;
+
     int nDstBands = poDstDS->GetRasterCount();
+    CPLErr eErr = CE_None;
     if( nDstBands != nBands )
     {
         if( GetMetadataItem(GDAL_DCAP_RASTER) != NULL )
         {
-            /* Should not happen for a well-behaved driver */
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Output driver created only %d bands whereas %d were expected",
-                     nDstBands, nBands);
+            // Should not happen for a well-behaved driver.
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Output driver created only %d bands whereas %d were expected",
+                nDstBands, nBands );
             eErr = CE_Failure;
         }
         nDstBands = 0;
@@ -482,13 +503,14 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 /*      Try setting the projection and geotransform if it seems         */
 /*      suitable.                                                       */
 /* -------------------------------------------------------------------- */
-    double      adfGeoTransform[6];
+    double adfGeoTransform[6] = {};
 
     if( nDstBands == 0 && !bStrict )
         CPLPushErrorHandler(CPLQuietErrorHandler);
 
     if( eErr == CE_None
         && poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
+        // TODO(schwehr): The default value check should be a function.
         && (adfGeoTransform[0] != 0.0
             || adfGeoTransform[1] != 1.0
             || adfGeoTransform[2] != 0.0
@@ -544,19 +566,15 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
     for( int iBand = 0;
          eErr == CE_None && iBand < nDstBands;
-         iBand++ )
+         ++iBand )
     {
-        GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
-        GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand+1 );
+        GDALRasterBand * const poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
+        GDALRasterBand * const poDstBand = poDstDS->GetRasterBand( iBand+1 );
 
 /* -------------------------------------------------------------------- */
 /*      Do we need to copy a colortable.                                */
 /* -------------------------------------------------------------------- */
-        GDALColorTable *poCT;
-        int bSuccess;
-        double dfValue;
-
-        poCT = poSrcBand->GetColorTable();
+        GDALColorTable * const poCT = poSrcBand->GetColorTable();
         if( poCT != NULL )
             poDstBand->SetColorTable( poCT );
 
@@ -574,7 +592,8 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
         if( CSLCount(poSrcBand->GetMetadata()) > 0 )
             poDstBand->SetMetadata( poSrcBand->GetMetadata() );
 
-        dfValue = poSrcBand->GetOffset( &bSuccess );
+        int bSuccess = FALSE;
+        double dfValue = poSrcBand->GetOffset( &bSuccess );
         if( bSuccess && dfValue != 0.0 )
             poDstBand->SetOffset( dfValue );
 
@@ -592,8 +611,7 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
             poDstBand->SetColorInterpretation(
                 poSrcBand->GetColorInterpretation() );
 
-        char** papszCatNames;
-        papszCatNames = poSrcBand->GetCategoryNames();
+        char** papszCatNames = poSrcBand->GetCategoryNames();
         if (NULL != papszCatNames)
             poDstBand->SetCategoryNames( papszCatNames );
 
@@ -603,15 +621,16 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
             CPLErrorReset();
         }
         else
+        {
             eErr = CPLGetLastErrorType();
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Copy image data.                                                */
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None && nDstBands > 0 )
-        eErr = GDALDatasetCopyWholeRaster( (GDALDatasetH) poSrcDS,
-                                           (GDALDatasetH) poDstDS,
+        eErr = GDALDatasetCopyWholeRaster( poSrcDS, poDstDS,
                                            NULL, pfnProgress, pProgressData );
 
 /* -------------------------------------------------------------------- */
@@ -623,14 +642,13 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Copy vector layers                                              */
 /* -------------------------------------------------------------------- */
-
     if( eErr == CE_None )
     {
         if( nLayerCount > 0 && poDstDS->TestCapability(ODsCCreateLayer) )
         {
-            for( int iLayer = 0; iLayer < nLayerCount; iLayer++ )
+            for( int iLayer = 0; iLayer < nLayerCount; ++iLayer )
             {
-                OGRLayer        *poLayer = poSrcDS->GetLayer(iLayer);
+                OGRLayer *poLayer = poSrcDS->GetLayer(iLayer);
 
                 if( poLayer == NULL )
                     continue;
@@ -650,10 +668,13 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
         return NULL;
     }
     else
+    {
         CPLErrorReset();
+    }
 
     return poDstDS;
 }
+//! @endcond
 
 /************************************************************************/
 /*                             CreateCopy()                             */
@@ -674,21 +695,22 @@ GDALDataset *GDALDriver::DefaultCreateCopy( const char * pszFilename,
  * be used.
  *
  * It is intended that CreateCopy() will often be used with a source dataset
- * which is a virtual dataset allowing configuration of band types, and
- * other information without actually duplicating raster data (see the VRT driver).
+ * which is a virtual dataset allowing configuration of band types, and other
+ * information without actually duplicating raster data (see the VRT driver).
  * This is what is done by the gdal_translate utility for example.
  *
- * That function will try to validate the creation option list passed to the driver
- * with the GDALValidateCreationOptions() method. This check can be disabled
- * by defining the configuration option GDAL_VALIDATE_CREATION_OPTIONS=NO.
+ * That function will try to validate the creation option list passed to the
+ * driver with the GDALValidateCreationOptions() method. This check can be
+ * disabled by defining the configuration option
+ * GDAL_VALIDATE_CREATION_OPTIONS=NO.
  *
- * After you have finished working with the returned dataset, it is <b>required</b>
- * to close it with GDALClose(). This does not only close the file handle, but
- * also ensures that all the data and metadata has been written to the dataset
- * (GDALFlushCache() is not sufficient for that purpose).
+ * After you have finished working with the returned dataset, it is
+ * <b>required</b> to close it with GDALClose(). This does not only close the
+ * file handle, but also ensures that all the data and metadata has been written
+ * to the dataset (GDALFlushCache() is not sufficient for that purpose).
  *
- * In some situations, the new dataset can be created in another process through the
- * \ref gdal_api_proxy mechanism.
+ * In some situations, the new dataset can be created in another process through
+ * the \ref gdal_api_proxy mechanism.
  *
  * @param pszFilename the name for the new dataset.  UTF-8 encoded.
  * @param poSrcDS the dataset being duplicated.
@@ -711,8 +733,6 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
                                      void * pProgressData )
 
 {
-    //CPLLocaleC  oLocaleForcer;
-
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
@@ -727,8 +747,8 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
                 return NULL;
             char** papszOptionsDup = CSLDuplicate(papszOptions);
             papszOptionsDup = CSLAddNameValue(papszOptionsDup, "SERVER_DRIVER",
-                                               GetDescription());
-            GDALDataset* poDstDS = poAPIPROXYDriver->pfnCreateCopy(
+                                              GetDescription());
+            GDALDataset* const poDstDS = poAPIPROXYDriver->pfnCreateCopy(
                 pszClientFilename, poSrcDS, bStrict, papszOptionsDup,
                 pfnProgress, pProgressData);
             if( poDstDS != NULL )
@@ -752,10 +772,12 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
 /*      name.  But even if that seems to fail we will continue since    */
 /*      it might just be a corrupt file or something.                   */
 /* -------------------------------------------------------------------- */
-    const bool bAppendSubdataset
-        = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "APPEND_SUBDATASET", FALSE));
+    const bool bAppendSubdataset =
+        CPLFetchBool(const_cast<const char **>(papszOptions),
+                     "APPEND_SUBDATASET", false);
     if( !bAppendSubdataset &&
-        CSLFetchBoolean(papszOptions, "QUIET_DELETE_ON_CREATE_COPY", TRUE) )
+        CPLFetchBool(const_cast<const char **>(papszOptions),
+                     "QUIET_DELETE_ON_CREATE_COPY", true) )
         QuietDelete( pszFilename );
 
     char** papszOptionsToDelete = NULL;
@@ -765,7 +787,9 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
     {
         if( papszOptionsToDelete == NULL )
             papszOptionsToDelete = CSLDuplicate(papszOptions);
-        papszOptions = CSLRemoveStrings(papszOptionsToDelete, iIdxQuietDeleteOnCreateCopy, 1, NULL);
+        papszOptions =
+            CSLRemoveStrings(papszOptionsToDelete, iIdxQuietDeleteOnCreateCopy,
+                             1, NULL);
         papszOptionsToDelete = papszOptions;
     }
 
@@ -773,31 +797,37 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
 /*      If _INTERNAL_DATASET=YES, the returned dataset will not be      */
 /*      registered in the global list of open datasets.                 */
 /* -------------------------------------------------------------------- */
-    int iIdxInternalDataset =
+    const int iIdxInternalDataset =
         CSLPartialFindString(papszOptions, "_INTERNAL_DATASET=");
     bool bInternalDataset = false;
     if( iIdxInternalDataset >= 0 )
     {
-        bInternalDataset = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "_INTERNAL_DATASET", FALSE));
+        bInternalDataset =
+            CPLFetchBool(const_cast<const char **>(papszOptions),
+                         "_INTERNAL_DATASET", false);
         if( papszOptionsToDelete == NULL )
             papszOptionsToDelete = CSLDuplicate(papszOptions);
-        papszOptions = CSLRemoveStrings(papszOptionsToDelete, iIdxInternalDataset, 1, NULL);
+        papszOptions =
+            CSLRemoveStrings(papszOptionsToDelete, iIdxInternalDataset,
+                             1, NULL);
         papszOptionsToDelete = papszOptions;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Validate creation options.                                      */
 /* -------------------------------------------------------------------- */
-    if (CPLTestBool(CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES")))
-        GDALValidateCreationOptions( this, papszOptions);
+    if( CPLTestBool(
+            CPLGetConfigOption("GDAL_VALIDATE_CREATION_OPTIONS", "YES") ) )
+        GDALValidateCreationOptions( this, papszOptions );
 
 /* -------------------------------------------------------------------- */
 /*      If the format provides a CreateCopy() method use that,          */
 /*      otherwise fallback to the internal implementation using the     */
 /*      Create() method.                                                */
 /* -------------------------------------------------------------------- */
-    GDALDataset *poDstDS;
-    if( pfnCreateCopy != NULL && !CPLTestBool(CPLGetConfigOption("GDAL_DEFAULT_CREATE_COPY", "NO")) )
+    GDALDataset *poDstDS = NULL;
+    if( pfnCreateCopy != NULL &&
+        !CPLTestBool(CPLGetConfigOption("GDAL_DEFAULT_CREATE_COPY", "NO")) )
     {
         poDstDS = pfnCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions,
                                  pfnProgress, pProgressData );
@@ -835,19 +865,19 @@ GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
  */
 
 GDALDatasetH CPL_STDCALL GDALCreateCopy( GDALDriverH hDriver,
-                             const char * pszFilename,
-                             GDALDatasetH hSrcDS,
-                             int bStrict, char ** papszOptions,
-                             GDALProgressFunc pfnProgress,
-                             void * pProgressData )
+                                         const char * pszFilename,
+                                         GDALDatasetH hSrcDS,
+                                         int bStrict, char ** papszOptions,
+                                         GDALProgressFunc pfnProgress,
+                                         void * pProgressData )
 
 {
     VALIDATE_POINTER1( hDriver, "GDALCreateCopy", NULL );
     VALIDATE_POINTER1( hSrcDS, "GDALCreateCopy", NULL );
 
-    return (GDALDatasetH) ((GDALDriver *) hDriver)->
-        CreateCopy( pszFilename, (GDALDataset *) hSrcDS, bStrict, papszOptions,
-                    pfnProgress, pProgressData );
+    return static_cast<GDALDriver *>(hDriver)->
+        CreateCopy( pszFilename, static_cast<GDALDataset *>(hSrcDS),
+                    bStrict, papszOptions, pfnProgress, pProgressData );
 }
 
 /************************************************************************/
@@ -875,7 +905,9 @@ CPLErr GDALDriver::QuietDelete( const char *pszName )
 
 {
     VSIStatBufL sStat;
-    int bExists = VSIStatExL(pszName, &sStat, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0;
+    const bool bExists =
+        VSIStatExL(pszName, &sStat,
+                   VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0;
 
 #ifdef S_ISFIFO
     if( bExists && S_ISFIFO(sStat.st_mode) )
@@ -885,13 +917,14 @@ CPLErr GDALDriver::QuietDelete( const char *pszName )
     if( bExists &&
         VSI_ISDIR(sStat.st_mode) )
     {
-        /* It is not desirable to remove directories quietly */
-        /* Necessary to avoid ogr_mitab_12 to destroy file created at ogr_mitab_7 */
+        // It is not desirable to remove directories quietly.  Necessary to
+        // avoid ogr_mitab_12 to destroy file created at ogr_mitab_7.
         return CE_None;
     }
 
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    GDALDriver *poDriver = (GDALDriver*) GDALIdentifyDriver( pszName, NULL );
+    GDALDriver * const poDriver =
+        static_cast<GDALDriver *>( GDALIdentifyDriver( pszName, NULL ) );
     CPLPopErrorHandler();
 
     if( poDriver == NULL )
@@ -899,11 +932,12 @@ CPLErr GDALDriver::QuietDelete( const char *pszName )
 
     CPLDebug( "GDAL", "QuietDelete(%s) invoking Delete()", pszName );
 
-    CPLErr eErr;
-    int bQuiet = ( !bExists && poDriver->pfnDelete == NULL && poDriver->pfnDeleteDataSource == NULL );
+    const bool bQuiet =
+        !bExists && poDriver->pfnDelete == NULL &&
+        poDriver->pfnDeleteDataSource == NULL;
     if( bQuiet )
         CPLPushErrorHandler(CPLQuietErrorHandler);
-    eErr  = poDriver->Delete( pszName );
+    CPLErr eErr = poDriver->Delete( pszName );
     if( bQuiet )
     {
         CPLPopErrorHandler();
@@ -947,7 +981,8 @@ CPLErr GDALDriver::Delete( const char * pszFilename )
 /* -------------------------------------------------------------------- */
 /*      Collect file list.                                              */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hDS = (GDALDataset *) GDALOpenEx(pszFilename,0,NULL,NULL,NULL);
+    GDALDatasetH hDS = static_cast<GDALDataset *>(
+        GDALOpenEx(pszFilename, 0, NULL, NULL, NULL) );
 
     if( hDS == NULL )
     {
@@ -961,22 +996,22 @@ CPLErr GDALDriver::Delete( const char * pszFilename )
     char **papszFileList = GDALGetFileList( hDS );
 
     GDALClose( hDS );
+    hDS = NULL;
 
     if( CSLCount( papszFileList ) == 0 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Unable to determine files associated with %s,\n"
+                  "Unable to determine files associated with %s, "
                   "delete fails.", pszFilename );
-
+        CSLDestroy( papszFileList );
         return CE_Failure;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Delete all files.                                               */
 /* -------------------------------------------------------------------- */
-    int i;
-
-    for( i = 0; papszFileList[i] != NULL; i++ )
+    CPLErr eErr = CE_None;
+    for( int i = 0; papszFileList[i] != NULL; ++i )
     {
         if( VSIUnlink( papszFileList[i] ) != 0 )
         {
@@ -984,14 +1019,13 @@ CPLErr GDALDriver::Delete( const char * pszFilename )
                       "Deleting %s failed:\n%s",
                       papszFileList[i],
                       VSIStrerror(errno) );
-            CSLDestroy( papszFileList );
-            return CE_Failure;
+            eErr = CE_Failure;
         }
     }
 
     CSLDestroy( papszFileList );
 
-    return CE_None;
+    return eErr;
 }
 
 /************************************************************************/
@@ -1004,7 +1038,8 @@ CPLErr GDALDriver::Delete( const char * pszFilename )
  * @see GDALDriver::Delete()
  */
 
-CPLErr CPL_STDCALL GDALDeleteDataset( GDALDriverH hDriver, const char * pszFilename )
+CPLErr CPL_STDCALL GDALDeleteDataset( GDALDriverH hDriver,
+                                      const char * pszFilename )
 
 {
     if( hDriver == NULL )
@@ -1018,7 +1053,7 @@ CPLErr CPL_STDCALL GDALDeleteDataset( GDALDriverH hDriver, const char * pszFilen
         return CE_Failure;
     }
 
-    return ((GDALDriver *) hDriver)->Delete( pszFilename );
+    return static_cast<GDALDriver *>(hDriver)->Delete( pszFilename );
 }
 
 /************************************************************************/
@@ -1028,6 +1063,7 @@ CPLErr CPL_STDCALL GDALDeleteDataset( GDALDriverH hDriver, const char * pszFilen
 /*      there is no format specific implementation.                     */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLErr GDALDriver::DefaultRename( const char * pszNewName,
                                   const char *pszOldName )
 
@@ -1035,7 +1071,8 @@ CPLErr GDALDriver::DefaultRename( const char * pszNewName,
 /* -------------------------------------------------------------------- */
 /*      Collect file list.                                              */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hDS = (GDALDataset *) GDALOpen(pszOldName,GA_ReadOnly);
+    GDALDatasetH hDS = static_cast<GDALDataset *>(
+        GDALOpen(pszOldName, GA_ReadOnly) );
 
     if( hDS == NULL )
     {
@@ -1064,14 +1101,13 @@ CPLErr GDALDriver::DefaultRename( const char * pszNewName,
 /*      names.                                                          */
 /* -------------------------------------------------------------------- */
     CPLErr eErr = CE_None;
-    int i;
     char **papszNewFileList =
         CPLCorrespondingPaths( pszOldName, pszNewName, papszFileList );
 
     if( papszNewFileList == NULL )
         return CE_Failure;
 
-    for( i = 0; papszFileList[i] != NULL; i++ )
+    for( int i = 0; papszFileList[i] != NULL; ++i )
     {
         if( CPLMoveFile( papszNewFileList[i], papszFileList[i] ) != 0 )
         {
@@ -1088,6 +1124,7 @@ CPLErr GDALDriver::DefaultRename( const char * pszNewName,
 
     return eErr;
 }
+//! @endcond
 
 /************************************************************************/
 /*                               Rename()                               */
@@ -1115,8 +1152,8 @@ CPLErr GDALDriver::Rename( const char * pszNewName, const char *pszOldName )
 {
     if( pfnRename != NULL )
         return pfnRename( pszNewName, pszOldName );
-    else
-        return DefaultRename( pszNewName, pszOldName );
+
+    return DefaultRename( pszNewName, pszOldName );
 }
 
 /************************************************************************/
@@ -1145,7 +1182,7 @@ CPLErr CPL_STDCALL GDALRenameDataset( GDALDriverH hDriver,
         return CE_Failure;
     }
 
-    return ((GDALDriver *) hDriver)->Rename( pszNewName, pszOldName );
+    return static_cast<GDALDriver *>(hDriver)->Rename( pszNewName, pszOldName );
 }
 
 /************************************************************************/
@@ -1155,14 +1192,16 @@ CPLErr CPL_STDCALL GDALRenameDataset( GDALDriverH hDriver,
 /*      there is no format specific implementation.                     */
 /************************************************************************/
 
-CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
+//! @cond Doxygen_Suppress
+CPLErr GDALDriver::DefaultCopyFiles( const char *pszNewName,
                                      const char *pszOldName )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Collect file list.                                              */
 /* -------------------------------------------------------------------- */
-    GDALDatasetH hDS = (GDALDataset *) GDALOpen(pszOldName,GA_ReadOnly);
+    GDALDatasetH hDS = static_cast<GDALDataset *>(
+        GDALOpen(pszOldName,GA_ReadOnly) );
 
     if( hDS == NULL )
     {
@@ -1176,6 +1215,7 @@ CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
     char **papszFileList = GDALGetFileList( hDS );
 
     GDALClose( hDS );
+    hDS = NULL;
 
     if( CSLCount( papszFileList ) == 0 )
     {
@@ -1191,20 +1231,19 @@ CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
 /*      names.                                                          */
 /* -------------------------------------------------------------------- */
     CPLErr eErr = CE_None;
-    int i;
     char **papszNewFileList =
         CPLCorrespondingPaths( pszOldName, pszNewName, papszFileList );
 
     if( papszNewFileList == NULL )
         return CE_Failure;
 
-    for( i = 0; papszFileList[i] != NULL; i++ )
+    for( int i = 0; papszFileList[i] != NULL; ++i )
     {
         if( CPLCopyFile( papszNewFileList[i], papszFileList[i] ) != 0 )
         {
             eErr = CE_Failure;
             // Try to put the ones we moved back.
-            for( --i; i >= 0; i-- )
+            for( --i; i >= 0; --i )
                 VSIUnlink( papszNewFileList[i] );
             break;
         }
@@ -1215,6 +1254,7 @@ CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
 
     return eErr;
 }
+//! @endcond
 
 /************************************************************************/
 /*                             CopyFiles()                              */
@@ -1233,13 +1273,13 @@ CPLErr GDALDriver::DefaultCopyFiles( const char * pszNewName,
  * @return CE_None on success, or CE_Failure if the operation fails.
  */
 
-CPLErr GDALDriver::CopyFiles( const char * pszNewName, const char *pszOldName )
+CPLErr GDALDriver::CopyFiles( const char *pszNewName, const char *pszOldName )
 
 {
     if( pfnCopyFiles != NULL )
         return pfnCopyFiles( pszNewName, pszOldName );
-    else
-        return DefaultCopyFiles( pszNewName, pszOldName );
+
+    return DefaultCopyFiles( pszNewName, pszOldName );
 }
 
 /************************************************************************/
@@ -1253,8 +1293,8 @@ CPLErr GDALDriver::CopyFiles( const char * pszNewName, const char *pszOldName )
  */
 
 CPLErr CPL_STDCALL GDALCopyDatasetFiles( GDALDriverH hDriver,
-                                         const char * pszNewName,
-                                         const char * pszOldName )
+                                         const char *pszNewName,
+                                         const char *pszOldName )
 
 {
     if( hDriver == NULL )
@@ -1268,7 +1308,8 @@ CPLErr CPL_STDCALL GDALCopyDatasetFiles( GDALDriverH hDriver,
         return CE_Failure;
     }
 
-    return ((GDALDriver *) hDriver)->CopyFiles( pszNewName, pszOldName );
+    return static_cast<GDALDriver *>(hDriver)->
+        CopyFiles( pszNewName, pszOldName );
 }
 
 /************************************************************************/
@@ -1293,7 +1334,7 @@ const char * CPL_STDCALL GDALGetDriverShortName( GDALDriverH hDriver )
 {
     VALIDATE_POINTER1( hDriver, "GDALGetDriverShortName", NULL );
 
-    return ((GDALDriver *) hDriver)->GetDescription();
+    return static_cast<GDALDriver *>(hDriver)->GetDescription();
 }
 
 /************************************************************************/
@@ -1316,12 +1357,13 @@ const char * CPL_STDCALL GDALGetDriverLongName( GDALDriverH hDriver )
     VALIDATE_POINTER1( hDriver, "GDALGetDriverLongName", NULL );
 
     const char *pszLongName =
-        ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_LONGNAME );
+        static_cast<GDALDriver *>(hDriver)->
+            GetMetadataItem( GDAL_DMD_LONGNAME );
 
     if( pszLongName == NULL )
         return "";
-    else
-        return pszLongName;
+
+    return pszLongName;
 }
 
 /************************************************************************/
@@ -1345,7 +1387,8 @@ const char * CPL_STDCALL GDALGetDriverHelpTopic( GDALDriverH hDriver )
 {
     VALIDATE_POINTER1( hDriver, "GDALGetDriverHelpTopic", NULL );
 
-    return ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_HELPTOPIC );
+    return static_cast<GDALDriver *>(hDriver)->
+        GetMetadataItem( GDAL_DMD_HELPTOPIC );
 }
 
 /************************************************************************/
@@ -1370,12 +1413,13 @@ const char * CPL_STDCALL GDALGetDriverCreationOptionList( GDALDriverH hDriver )
     VALIDATE_POINTER1( hDriver, "GDALGetDriverCreationOptionList", NULL );
 
     const char *pszOptionList =
-        ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
+        static_cast<GDALDriver *>(hDriver)->
+            GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
 
     if( pszOptionList == NULL )
         return "";
-    else
-        return pszOptionList;
+
+    return pszOptionList;
 }
 
 /************************************************************************/
@@ -1405,24 +1449,30 @@ const char * CPL_STDCALL GDALGetDriverCreationOptionList( GDALDriverH hDriver )
  */
 
 int CPL_STDCALL GDALValidateCreationOptions( GDALDriverH hDriver,
-                                             char** papszCreationOptions)
+                                             char** papszCreationOptions )
 {
     VALIDATE_POINTER1( hDriver, "GDALValidateCreationOptions", FALSE );
     const char *pszOptionList =
-        ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST );
+        static_cast<GDALDriver *>(hDriver)->GetMetadataItem(
+            GDAL_DMD_CREATIONOPTIONLIST );
     CPLString osDriver;
-    osDriver.Printf("driver %s", ((GDALDriver *) hDriver)->GetDescription());
+    osDriver.Printf("driver %s",
+                    static_cast<GDALDriver *>(hDriver)->GetDescription());
     char** papszOptionsToValidate = papszCreationOptions;
     char** papszOptionsToFree = NULL;
     if( CSLFetchNameValue( papszCreationOptions, "APPEND_SUBDATASET") )
     {
-        papszOptionsToValidate = papszOptionsToFree =
-            CSLSetNameValue(CSLDuplicate(papszCreationOptions), "APPEND_SUBDATASET", NULL);
+        papszOptionsToFree =
+            CSLSetNameValue(CSLDuplicate(papszCreationOptions),
+                            "APPEND_SUBDATASET", NULL);
+        papszOptionsToValidate = papszOptionsToFree;
     }
-    int bRet = GDALValidateOptions( pszOptionList,
-                                (const char* const* )papszOptionsToValidate,
-                                "creation option",
-                                osDriver);
+    const bool bRet = CPL_TO_BOOL(
+        GDALValidateOptions(
+            pszOptionList,
+            const_cast<const char* const*>(papszOptionsToValidate),
+            "creation option",
+            osDriver ) );
     CSLDestroy(papszOptionsToFree);
     return bRet;
 }
@@ -1435,13 +1485,14 @@ int GDALValidateOpenOptions( GDALDriverH hDriver,
                              const char* const* papszOpenOptions)
 {
     VALIDATE_POINTER1( hDriver, "GDALValidateOpenOptions", FALSE );
-    const char *pszOptionList =
-        ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_OPENOPTIONLIST );
+    const char *pszOptionList = static_cast<GDALDriver *>(hDriver)->
+        GetMetadataItem( GDAL_DMD_OPENOPTIONLIST );
     CPLString osDriver;
-    osDriver.Printf("driver %s", ((GDALDriver *) hDriver)->GetDescription());
+    osDriver.Printf("driver %s",
+                    static_cast<GDALDriver *>(hDriver)->GetDescription());
     return GDALValidateOptions( pszOptionList, papszOpenOptions,
                                 "open option",
-                                osDriver);
+                                osDriver );
 }
 
 /************************************************************************/
@@ -1453,8 +1504,6 @@ int GDALValidateOptions( const char* pszOptionList,
                          const char* pszErrorMessageOptionType,
                          const char* pszErrorMessageContainerName)
 {
-    int bRet = TRUE;
-
     if( papszOptionsToValidate == NULL || *papszOptionsToValidate == NULL)
         return TRUE;
     if( pszOptionList == NULL )
@@ -1469,6 +1518,7 @@ int GDALValidateOptions( const char* pszOptionList,
         return TRUE;
     }
 
+    bool bRet = true;
     while(*papszOptionsToValidate)
     {
         char* pszKey = NULL;
@@ -1479,15 +1529,15 @@ int GDALValidateOptions( const char* pszOptionList,
                      "%s '%s' is not formatted with the key=value format",
                      pszErrorMessageOptionType,
                      *papszOptionsToValidate);
-            bRet = FALSE;
+            bRet = false;
 
-            papszOptionsToValidate ++;
+            ++papszOptionsToValidate;
             continue;
         }
 
         if( EQUAL(pszKey, "VALIDATE_OPEN_OPTIONS") )
         {
-            papszOptionsToValidate ++;
+            ++papszOptionsToValidate;
             CPLFree(pszKey);
             continue;
         }
@@ -1541,18 +1591,19 @@ int GDALValidateOptions( const char* pszOptionList,
         {
             if( bWarnIfMissingKey &&
                 (!EQUAL(pszErrorMessageOptionType, "open option") ||
-                 CSLFetchBoolean((char**)papszOptionsToValidate, "VALIDATE_OPEN_OPTIONS", TRUE)) )
+                 CPLFetchBool((char**)papszOptionsToValidate,
+                              "VALIDATE_OPEN_OPTIONS", true)) )
             {
                 CPLError(CE_Warning, CPLE_NotSupported,
                         "%s does not support %s %s",
                         pszErrorMessageContainerName,
                         pszErrorMessageOptionType,
                         pszKey);
-                bRet = FALSE;
+                bRet = false;
             }
 
             CPLFree(pszKey);
-            papszOptionsToValidate ++;
+            ++papszOptionsToValidate;
             continue;
         }
 
@@ -1572,7 +1623,8 @@ int GDALValidateOptions( const char* pszOptionList,
                       EQUAL(psChildSubNode->pszValue, "max") ||
                       EQUAL(psChildSubNode->pszValue, "default") ||
                       EQUAL(psChildSubNode->pszValue, "maxsize") ||
-                      EQUAL(psChildSubNode->pszValue, "required")) )
+                      EQUAL(psChildSubNode->pszValue, "required") ||
+                      EQUAL(psChildSubNode->pszValue, "scope")) )
                 {
                     /* Driver error */
                     CPLError(CE_Warning, CPLE_NotSupported,
@@ -1603,26 +1655,26 @@ int GDALValidateOptions( const char* pszOptionList,
                         CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s of type int.",
                              pszValue, pszKey, pszErrorMessageOptionType);
-                        bRet = FALSE;
+                        bRet = false;
                         break;
                     }
-                    pszValueIter++;
+                    ++pszValueIter;
                 }
-                if( *pszValueIter == '0' )
+                if( *pszValueIter == '\0' )
                 {
                     if( pszMin && atoi(pszValue) < atoi(pszMin) )
                     {
                         CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s that should be >= %s.",
                              pszValue, pszKey, pszErrorMessageOptionType, pszMin);
-                        break;
+                        bRet = false;
                     }
                     if( pszMax && atoi(pszValue) > atoi(pszMax) )
                     {
                         CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s that should be <= %s.",
                              pszValue, pszKey, pszErrorMessageOptionType, pszMax);
-                        break;
+                        bRet = false;
                     }
                 }
             }
@@ -1637,26 +1689,26 @@ int GDALValidateOptions( const char* pszOptionList,
                         CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s of type unsigned int.",
                              pszValue, pszKey, pszErrorMessageOptionType);
-                        bRet = FALSE;
+                        bRet = false;
                         break;
                     }
-                    pszValueIter++;
-                    if( *pszValueIter == '0' )
+                    ++pszValueIter;
+                }
+                if( *pszValueIter == '\0' )
+                {
+                    if( pszMin && atoi(pszValue) < atoi(pszMin) )
                     {
-                        if( pszMin && atoi(pszValue) < atoi(pszMin) )
-                        {
-                            CPLError(CE_Warning, CPLE_NotSupported,
-                                "'%s' is an unexpected value for %s %s that should be >= %s.",
-                                pszValue, pszKey, pszErrorMessageOptionType, pszMin);
-                            break;
-                        }
-                        if( pszMax && atoi(pszValue) > atoi(pszMax) )
-                        {
-                            CPLError(CE_Warning, CPLE_NotSupported,
-                                "'%s' is an unexpected value for %s %s that should be <= %s.",
-                                pszValue, pszKey, pszErrorMessageOptionType, pszMax);
-                            break;
-                        }
+                        CPLError(CE_Warning, CPLE_NotSupported,
+                            "'%s' is an unexpected value for %s %s that should be >= %s.",
+                            pszValue, pszKey, pszErrorMessageOptionType, pszMin);
+                        bRet = false;
+                    }
+                    if( pszMax && atoi(pszValue) > atoi(pszMax) )
+                    {
+                        CPLError(CE_Warning, CPLE_NotSupported,
+                            "'%s' is an unexpected value for %s %s that should be <= %s.",
+                            pszValue, pszKey, pszErrorMessageOptionType, pszMax);
+                        bRet = false;
                     }
                 }
             }
@@ -1669,7 +1721,7 @@ int GDALValidateOptions( const char* pszOptionList,
                     CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s of type float.",
                              pszValue, pszKey, pszErrorMessageOptionType);
-                    bRet = FALSE;
+                    bRet = false;
                 }
                 else
                 {
@@ -1678,16 +1730,14 @@ int GDALValidateOptions( const char* pszOptionList,
                         CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s that should be >= %s.",
                              pszValue, pszKey, pszErrorMessageOptionType, pszMin);
-                        CPLFree(pszKey);
-                        break;
+                        bRet = false;
                     }
                     if( pszMax && dfVal > CPLAtof(pszMax) )
                     {
                         CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s that should be <= %s.",
                              pszValue, pszKey, pszErrorMessageOptionType, pszMax);
-                        CPLFree(pszKey);
-                        break;
+                        bRet = false;
                     }
                 }
             }
@@ -1699,7 +1749,7 @@ int GDALValidateOptions( const char* pszOptionList,
                     CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s of type boolean.",
                              pszValue, pszKey, pszErrorMessageOptionType);
-                    bRet = FALSE;
+                    bRet = false;
                 }
             }
             else if (EQUAL(pszType, "STRING-SELECT"))
@@ -1720,6 +1770,14 @@ int GDALValidateOptions( const char* pszOptionList,
                                 bMatchFound = true;
                                 break;
                             }
+                            if( psOptionNode->eType == CXT_Attribute &&
+                                (EQUAL(psOptionNode->pszValue, "alias") ||
+                                 EQUAL(psOptionNode->pszValue, "deprecated_alias") ) &&
+                                 EQUAL(psOptionNode->psChild->pszValue, pszValue) )
+                            {
+                                bMatchFound = true;
+                                break;
+                            }
                             psOptionNode = psOptionNode->psNext;
                         }
                         if (bMatchFound)
@@ -1732,7 +1790,7 @@ int GDALValidateOptions( const char* pszOptionList,
                     CPLError(CE_Warning, CPLE_NotSupported,
                              "'%s' is an unexpected value for %s %s of type string-select.",
                              pszValue, pszKey, pszErrorMessageOptionType);
-                    bRet = FALSE;
+                    bRet = false;
                 }
             }
             else if (EQUAL(pszType, "STRING"))
@@ -1746,7 +1804,7 @@ int GDALValidateOptions( const char* pszOptionList,
                              "'%s' is of size %d, whereas maximum size for %s %s is %d.",
                              pszValue, (int)strlen(pszValue), pszKey,
                                  pszErrorMessageOptionType, atoi(pszMaxSize));
-                        bRet = FALSE;
+                        bRet = false;
                     }
                 }
             }
@@ -1771,11 +1829,11 @@ int GDALValidateOptions( const char* pszOptionList,
                      pszErrorMessageOptionType);
         }
         CPLFree(pszKey);
-        papszOptionsToValidate++;
+        ++papszOptionsToValidate;
     }
 
     CPLDestroyXMLNode(psNode);
-    return bRet;
+    return bRet ? TRUE : FALSE;
 }
 
 /************************************************************************/
@@ -1794,7 +1852,7 @@ int GDALValidateOptions( const char* pszOptionList,
  * file system machinery, it is possible to give an optional list of files.
  * This is the list of all files at the same level in the file system as the
  * target file, including the target file. The filenames will not include any
- * path components, are an essentially just the output of VSIReadDir() on the
+ * path components, are essentially just the output of VSIReadDir() on the
  * parent directory. If the target object does not have filesystem semantics
  * then the file list should be NULL.
  *
@@ -1802,68 +1860,151 @@ int GDALValidateOptions( const char* pszOptionList,
  * exotic drivers this may not refer to a physical file, but instead contain
  * information for the driver on how to access a dataset.
  *
- * @param papszFileList an array of strings, whose last element is the NULL pointer.
- * These strings are filenames that are auxiliary to the main filename. The passed
- * value may be NULL.
+ * @param papszFileList an array of strings, whose last element is the NULL
+ * pointer.  These strings are filenames that are auxiliary to the main
+ * filename. The passed value may be NULL.
  *
  * @return A GDALDriverH handle or NULL on failure.  For C++ applications
  * this handle can be cast to a GDALDriver *.
  */
 
-
 GDALDriverH CPL_STDCALL
 GDALIdentifyDriver( const char * pszFilename,
                     char **papszFileList )
 
 {
-    int         	iDriver;
+    return GDALIdentifyDriverEx( pszFilename, 0, NULL, papszFileList );
+}
+
+/************************************************************************/
+/*                         GDALIdentifyDriverEx()                       */
+/************************************************************************/
+
+/**
+ * \brief Identify the driver that can open a raster file.
+ *
+ * This function will try to identify the driver that can open the passed file
+ * name by invoking the Identify method of each registered GDALDriver in turn.
+ * The first driver that successful identifies the file name will be returned.
+ * If all drivers fail then NULL is returned.
+ *
+ * In order to reduce the need for such searches touch the operating system
+ * file system machinery, it is possible to give an optional list of files.
+ * This is the list of all files at the same level in the file system as the
+ * target file, including the target file. The filenames will not include any
+ * path components, are essentially just the output of VSIReadDir() on the
+ * parent directory. If the target object does not have filesystem semantics
+ * then the file list should be NULL.
+ *
+ * @param pszFilename the name of the file to access.  In the case of
+ * exotic drivers this may not refer to a physical file, but instead contain
+ * information for the driver on how to access a dataset.
+ *
+ * @param nIdentifyFlags a combination of GDAL_OF_RASTER for raster drivers
+ * or GDAL_OF_VECTOR for vector drivers. If none of the value is specified,
+ * both kinds are implied.
+ *
+ * @param papszAllowedDrivers NULL to consider all candidate drivers, or a NULL
+ * terminated list of strings with the driver short names that must be considered.
+ *
+ * @param papszFileList an array of strings, whose last element is the NULL
+ * pointer.  These strings are filenames that are auxiliary to the main
+ * filename. The passed value may be NULL.
+ *
+ * @return A GDALDriverH handle or NULL on failure.  For C++ applications
+ * this handle can be cast to a GDALDriver *.
+ *
+ * @since GDAL 2.2
+ */
+
+GDALDriverH CPL_STDCALL
+GDALIdentifyDriverEx( const char* pszFilename,
+                      unsigned int nIdentifyFlags,
+                      const char* const* papszAllowedDrivers,
+                      const char* const* papszFileList )
+{
     GDALDriverManager  *poDM = GetGDALDriverManager();
-    GDALOpenInfo        oOpenInfo( pszFilename, GA_ReadOnly, papszFileList );
-    //CPLLocaleC          oLocaleForcer;
+    CPLAssert( NULL != poDM );
+    GDALOpenInfo oOpenInfo( pszFilename, GA_ReadOnly, (char**)papszFileList );
 
     CPLErrorReset();
-    CPLAssert( NULL != poDM );
 
-    int nDriverCount = poDM->GetDriverCount();
+    const int nDriverCount = poDM->GetDriverCount();
 
-    // First pass: only use drivers that have a pfnIdentify implementation
-    for( iDriver = -1; iDriver < nDriverCount; iDriver++ )
+    // First pass: only use drivers that have a pfnIdentify implementation.
+    for( int iDriver = -1; iDriver < nDriverCount; ++iDriver )
     {
-        GDALDriver      *poDriver;
+        GDALDriver* poDriver;
 
         if( iDriver < 0 )
             poDriver = GDALGetAPIPROXYDriver();
         else
+        {
             poDriver = poDM->GetDriver( iDriver );
+            if (papszAllowedDrivers != NULL &&
+                CSLFindString((char**)papszAllowedDrivers,
+                              GDALGetDriverShortName(poDriver)) == -1)
+                continue;
+        }
 
         VALIDATE_POINTER1( poDriver, "GDALIdentifyDriver", NULL );
 
-        if( poDriver->pfnIdentify != NULL )
+        if( poDriver->pfnIdentify == NULL )
         {
-            if( poDriver->pfnIdentify( &oOpenInfo ) > 0 )
-                return (GDALDriverH) poDriver;
+            continue;
         }
+
+        if (papszAllowedDrivers != NULL &&
+            CSLFindString((char**)papszAllowedDrivers,
+                          GDALGetDriverShortName(poDriver)) == -1)
+            continue;
+        if( (nIdentifyFlags & GDAL_OF_RASTER) != 0 &&
+            (nIdentifyFlags & GDAL_OF_VECTOR) == 0 &&
+            poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == NULL )
+            continue;
+        if( (nIdentifyFlags & GDAL_OF_VECTOR) != 0 &&
+            (nIdentifyFlags & GDAL_OF_RASTER) == 0 &&
+            poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == NULL )
+            continue;
+
+        if( poDriver->pfnIdentify( &oOpenInfo ) > 0 )
+            return poDriver;
     }
 
-    // Second pass: slow method
-    for( iDriver = -1; iDriver < nDriverCount; iDriver++ )
+    // Second pass: slow method.
+    for( int iDriver = -1; iDriver < nDriverCount; ++iDriver )
     {
-        GDALDriver      *poDriver;
-        GDALDataset     *poDS;
+        GDALDriver* poDriver;
 
         if( iDriver < 0 )
             poDriver = GDALGetAPIPROXYDriver();
         else
+        {
             poDriver = poDM->GetDriver( iDriver );
+            if (papszAllowedDrivers != NULL &&
+                CSLFindString((char**)papszAllowedDrivers,
+                              GDALGetDriverShortName(poDriver)) == -1)
+                continue;
+        }
 
         VALIDATE_POINTER1( poDriver, "GDALIdentifyDriver", NULL );
 
+        if( (nIdentifyFlags & GDAL_OF_RASTER) != 0 &&
+            (nIdentifyFlags & GDAL_OF_VECTOR) == 0 &&
+            poDriver->GetMetadataItem(GDAL_DCAP_RASTER) == NULL )
+            continue;
+        if( (nIdentifyFlags & GDAL_OF_VECTOR) != 0 &&
+            (nIdentifyFlags & GDAL_OF_RASTER) == 0 &&
+            poDriver->GetMetadataItem(GDAL_DCAP_VECTOR) == NULL )
+            continue;
+
         if( poDriver->pfnIdentify != NULL )
         {
             if( poDriver->pfnIdentify( &oOpenInfo ) == 0 )
                 continue;
         }
 
+        GDALDataset     *poDS;
         if( poDriver->pfnOpen != NULL )
         {
             poDS = poDriver->pfnOpen( &oOpenInfo );
@@ -1897,9 +2038,9 @@ GDALIdentifyDriver( const char * pszFilename,
 /*                          SetMetadataItem()                           */
 /************************************************************************/
 
-CPLErr GDALDriver::SetMetadataItem( const char * pszName,
-                                    const char * pszValue,
-                                    const char * pszDomain )
+CPLErr GDALDriver::SetMetadataItem( const char *pszName,
+                                    const char *pszValue,
+                                    const char *pszDomain )
 
 {
     if( pszDomain == NULL || pszDomain[0] == '\0' )
diff --git a/gcore/gdaldrivermanager.cpp b/gcore/gdaldrivermanager.cpp
index 66fd3e4..c4e4370 100644
--- a/gcore/gdaldrivermanager.cpp
+++ b/gcore/gdaldrivermanager.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaldrivermanager.cpp 34979 2016-08-08 09:30:34Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALDriverManager class.
@@ -28,12 +27,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_priv.h"
+
+#include <cstring>
+#include <map>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
+#include "cpl_port.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal_alg.h"
 #include "gdal_alg_priv.h"
+#include "gdal.h"
 #include "gdal_pam.h"
-#include "gdal_priv.h"
 #include "ogr_srs_api.h"
+#include "ogr_xerces.h"
 
 #ifdef _MSC_VER
 #  ifdef MSVC_USE_VLD
@@ -42,7 +53,12 @@
 #  endif
 #endif
 
-CPL_CVSID("$Id: gdaldrivermanager.cpp 34979 2016-08-08 09:30:34Z rouault $");
+// FIXME: Disabled following code as it crashed on OSX CI test.
+//#if HAVE_CXX11
+//#include <mutex>
+//#endif
+
+CPL_CVSID("$Id: gdaldrivermanager.cpp 36523 2016-11-27 04:13:26Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -50,9 +66,14 @@ CPL_CVSID("$Id: gdaldrivermanager.cpp 34979 2016-08-08 09:30:34Z rouault $");
 /* ==================================================================== */
 /************************************************************************/
 
-static volatile GDALDriverManager        *poDM = NULL;
+static volatile GDALDriverManager *poDM = NULL;
 static CPLMutex *hDMMutex = NULL;
 
+// FIXME: Disale following code as it crashed on OSX CI test.
+//#if HAVE_CXX11
+//static std::mutex oDeleteMutex;
+//#endif
+
 CPLMutex** GDALGetphDMMutex() { return &hDMMutex; }
 
 /************************************************************************/
@@ -106,11 +127,11 @@ GDALDriverManager::GDALDriverManager() :
 /*      and we hope other mechanisms such as environment variables will */
 /*      have been employed.                                             */
 /* -------------------------------------------------------------------- */
+#ifdef INST_DATA
     if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
     {
-        // this one is picked up automatically by finder initialization.
+        // This one is picked up automatically by finder initialization.
     }
-#ifdef INST_DATA
     else
     {
         CPLPushFinderLocation( INST_DATA );
@@ -122,8 +143,9 @@ GDALDriverManager::GDALDriverManager() :
 /*                         ~GDALDriverManager()                         */
 /************************************************************************/
 
-void GDALDatasetPoolPreventDestroy(); /* keep that in sync with gdalproxypool.cpp */
-void GDALDatasetPoolForceDestroy(); /* keep that in sync with gdalproxypool.cpp */
+// Keep these two in sync with gdalproxypool.cpp.
+void GDALDatasetPoolPreventDestroy();
+void GDALDatasetPoolForceDestroy();
 
 GDALDriverManager::~GDALDriverManager()
 
@@ -132,53 +154,59 @@ GDALDriverManager::~GDALDriverManager()
 /*      Cleanup any open datasets.                                      */
 /* -------------------------------------------------------------------- */
 
-    /* We have to prevent the destroying of the dataset pool during this first */
-    /* phase, otherwise it cause crashes with a VRT B referencing a VRT A, and if */
-    /* CloseDependentDatasets() is called first on VRT A. */
-    /* If we didn't do this nasty trick, due to the refCountOfDisableRefCount */
-    /* mechanism that cheats the real refcount of the dataset pool, we might */
-    /* destroy the dataset pool too early, leading the VRT A to */
-    /* destroy itself indirectly ... Ok, I am aware this explanation does */
-    /* not make any sense unless you try it under a debugger ... */
-    /* When people just manipulate "top-level" dataset handles, we luckily */
-    /* don't need this horrible hack, but GetOpenDatasets() expose "low-level" */
-    /* datasets, which defeat some "design" of the proxy pool */
+    // We have to prevent the destroying of the dataset pool during this first
+    // phase, otherwise it cause crashes with a VRT B referencing a VRT A, and
+    // if CloseDependentDatasets() is called first on VRT A.
+    // If we didn't do this nasty trick, due to the refCountOfDisableRefCount
+    // mechanism that cheats the real refcount of the dataset pool, we might
+    // destroy the dataset pool too early, leading the VRT A to
+    // destroy itself indirectly ... Ok, I am aware this explanation does
+    // not make any sense unless you try it under a debugger ...
+    // When people just manipulate "top-level" dataset handles, we luckily
+    // don't need this horrible hack, but GetOpenDatasets() expose "low-level"
+    // datasets, which defeat some "design" of the proxy pool.
     GDALDatasetPoolPreventDestroy();
 
-    /* First begin by requesting each remaining dataset to drop any reference */
-    /* to other datasets */
+    // First begin by requesting each remaining dataset to drop any reference
+    // to other datasets.
     bool bHasDroppedRef = false;
 
     do
     {
-        int nDSCount;
+        int nDSCount = 0;
         GDALDataset **papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
-        /* If a dataset has dropped a reference, the list might have become */
-        /* invalid, so go out of the loop and try again with the new valid */
-        /* list */
+
+        // If a dataset has dropped a reference, the list might have become
+        // invalid, so go out of the loop and try again with the new valid
+        // list.
         bHasDroppedRef = false;
-        for(int i=0;i<nDSCount && !bHasDroppedRef;i++)
+        for( int i = 0; i < nDSCount && !bHasDroppedRef; ++i )
         {
-            //CPLDebug("GDAL", "Call CloseDependentDatasets() on %s",
-            //      papoDSList[i]->GetDescription() );
-            bHasDroppedRef = CPL_TO_BOOL(papoDSList[i]->CloseDependentDatasets());
+#if DEBUG_VERBOSE
+            CPLDebug( "GDAL", "Call CloseDependentDatasets() on %s",
+                      papoDSList[i]->GetDescription() );
+#endif  // DEBUG_VERBOSE
+            bHasDroppedRef =
+                CPL_TO_BOOL(papoDSList[i]->CloseDependentDatasets());
         }
     } while(bHasDroppedRef);
 
-    /* Now let's destroy the dataset pool. Nobody should use it afterwards */
-    /* if people have well released their dependent datasets above */
+    // Now let's destroy the dataset pool. Nobody should use it afterwards
+    // if people have well released their dependent datasets above.
     GDALDatasetPoolForceDestroy();
 
-    /* Now close the stand-alone datasets */
-    int nDSCount;
+    // Now close the stand-alone datasets.
+    int nDSCount = 0;
     GDALDataset **papoDSList = GDALDataset::GetOpenDatasets(&nDSCount);
-    for(int i=0;i<nDSCount;i++)
+    for( int i = 0; i < nDSCount; ++i )
     {
-        CPLDebug( "GDAL", "force close of %s (%p) in GDALDriverManager cleanup.",
+        CPLDebug( "GDAL",
+                  "Force close of %s (%p) in GDALDriverManager cleanup.",
                   papoDSList[i]->GetDescription(), papoDSList[i] );
-        /* Destroy with delete operator rather than GDALClose() to force deletion of */
-        /* datasets with multiple reference count */
-        /* We could also iterate while GetOpenDatasets() returns a non NULL list */
+        // Destroy with delete operator rather than GDALClose() to force
+        // deletion of datasets with multiple reference count.
+        // We could also iterate while GetOpenDatasets() returns a non NULL
+        // list.
         delete papoDSList[i];
     }
 
@@ -220,6 +248,8 @@ GDALDriverManager::~GDALDriverManager()
 /* -------------------------------------------------------------------- */
     OSRCleanup();
 
+    OGRCleanupXercesMutex();
+
 /* -------------------------------------------------------------------- */
 /*      Cleanup VSIFileManager.                                         */
 /* -------------------------------------------------------------------- */
@@ -241,36 +271,36 @@ GDALDriverManager::~GDALDriverManager()
     }
 
 /* -------------------------------------------------------------------- */
-/*      Cleanup dataset list mutex                                      */
+/*      Cleanup dataset list mutex.                                     */
 /* -------------------------------------------------------------------- */
-    if ( *GDALGetphDLMutex() != NULL )
+    if( *GDALGetphDLMutex() != NULL )
     {
         CPLDestroyMutex( *GDALGetphDLMutex() );
         *GDALGetphDLMutex() = NULL;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Cleanup raster block mutex                                      */
+/*      Cleanup raster block mutex.                                     */
 /* -------------------------------------------------------------------- */
     GDALRasterBlock::DestroyRBMutex();
 
 /* -------------------------------------------------------------------- */
-/*      Cleanup gdaltransformer.cpp mutex                               */
+/*      Cleanup gdaltransformer.cpp mutex.                              */
 /* -------------------------------------------------------------------- */
     GDALCleanupTransformDeserializerMutex();
 
 /* -------------------------------------------------------------------- */
-/*      Cleanup cpl_error.cpp mutex                                     */
+/*      Cleanup cpl_error.cpp mutex.                                    */
 /* -------------------------------------------------------------------- */
     CPLCleanupErrorMutex();
 
 /* -------------------------------------------------------------------- */
-/*      Cleanup CPLsetlocale mutex                                      */
+/*      Cleanup CPLsetlocale mutex.                                     */
 /* -------------------------------------------------------------------- */
     CPLCleanupSetlocaleMutex();
 
 /* -------------------------------------------------------------------- */
-/*      Cleanup QHull mutex                                             */
+/*      Cleanup QHull mutex.                                            */
 /* -------------------------------------------------------------------- */
     GDALTriangulationTerminate();
 
@@ -299,10 +329,10 @@ GDALDriverManager::~GDALDriverManager()
  * @return the number of registered drivers.
  */
 
-int GDALDriverManager::GetDriverCount()
+int GDALDriverManager::GetDriverCount() const
 
 {
-    return( nDrivers );
+    return nDrivers;
 }
 
 /************************************************************************/
@@ -356,7 +386,7 @@ GDALDriver * GDALDriverManager::GetDriver( int iDriver )
 GDALDriverH CPL_STDCALL GDALGetDriver( int iDriver )
 
 {
-    return (GDALDriverH) GetGDALDriverManager()->GetDriver(iDriver);
+    return /* (GDALDriverH) */ GetGDALDriverManager()->GetDriver(iDriver);
 }
 
 /************************************************************************/
@@ -393,7 +423,7 @@ int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
 /* -------------------------------------------------------------------- */
     if( GetDriverByName_unlocked( poDriver->GetDescription() ) != NULL )
     {
-        for( int i = 0; i < nDrivers; i++ )
+        for( int i = 0; i < nDrivers; ++i )
         {
             if( papoDrivers[i] == poDriver )
             {
@@ -401,20 +431,20 @@ int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
             }
         }
 
-        CPLAssert( FALSE );
+        CPLAssert( false );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Otherwise grow the list to hold the new entry.                  */
 /* -------------------------------------------------------------------- */
-    GDALDriver** papoNewDrivers = (GDALDriver **)
-        VSI_REALLOC_VERBOSE(papoDrivers, sizeof(GDALDriver *) * (nDrivers+1));
+    GDALDriver** papoNewDrivers = static_cast<GDALDriver **>(
+        VSI_REALLOC_VERBOSE(papoDrivers, sizeof(GDALDriver *) * (nDrivers+1)) );
     if( papoNewDrivers == NULL )
         return -1;
     papoDrivers = papoNewDrivers;
 
     papoDrivers[nDrivers] = poDriver;
-    nDrivers++;
+    ++nDrivers;
 
     if( poDriver->pfnOpen != NULL ||
         poDriver->pfnOpenWithDriverArg != NULL )
@@ -426,16 +456,16 @@ int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
     if( poDriver->pfnCreateCopy != NULL )
         poDriver->SetMetadataItem( GDAL_DCAP_CREATECOPY, "YES" );
 
-    /* Backward compatibility for GDAL raster out-of-tree drivers: */
-    /* if a driver hasn't explicitly set a vector capability, assume it is */
-    /* a raster driver (legacy OGR drivers will have DCAP_VECTOR set before */
-    /* calling RegisterDriver() ) */
+    // Backward compatibility for GDAL raster out-of-tree drivers:
+    // If a driver hasn't explicitly set a vector capability, assume it is
+    // a raster-only driver (legacy OGR drivers will have DCAP_VECTOR set before
+    // calling RegisterDriver()).
     if( poDriver->GetMetadataItem( GDAL_DCAP_RASTER ) == NULL &&
         poDriver->GetMetadataItem( GDAL_DCAP_VECTOR ) == NULL &&
         poDriver->GetMetadataItem( GDAL_DCAP_GNM ) == NULL )
     {
-        CPLDebug("GDAL", "Assuming DCAP_RASTER for driver %s. Please fix it.",
-                 poDriver->GetDescription() );
+        CPLDebug( "GDAL", "Assuming DCAP_RASTER for driver %s. Please fix it.",
+                  poDriver->GetDescription() );
         poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
     }
 
@@ -443,12 +473,14 @@ int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
         poDriver->pfnIdentify == NULL &&
         !STARTS_WITH_CI(poDriver->GetDescription(), "Interlis") )
     {
-        CPLDebug("GDAL", "Driver %s that defines GDAL_DMD_OPENOPTIONLIST must also "
-                 "implement Identify(), so that it can be used",
-                 poDriver->GetDescription() );
+        CPLDebug( "GDAL",
+                  "Driver %s that defines GDAL_DMD_OPENOPTIONLIST must also "
+                  "implement Identify(), so that it can be used",
+                  poDriver->GetDescription() );
     }
 
-    oMapNameToDrivers[CPLString(poDriver->GetDescription()).toupper()] = poDriver;
+    oMapNameToDrivers[CPLString(poDriver->GetDescription()).toupper()] =
+        poDriver;
 
     int iResult = nDrivers - 1;
 
@@ -470,10 +502,10 @@ int CPL_STDCALL GDALRegisterDriver( GDALDriverH hDriver )
 {
     VALIDATE_POINTER1( hDriver, "GDALRegisterDriver", 0 );
 
-    return GetGDALDriverManager()->RegisterDriver( (GDALDriver *) hDriver );
+    return GetGDALDriverManager()->
+        RegisterDriver( static_cast<GDALDriver *>( hDriver ) );
 }
 
-
 /************************************************************************/
 /*                          DeregisterDriver()                          */
 /************************************************************************/
@@ -493,8 +525,8 @@ void GDALDriverManager::DeregisterDriver( GDALDriver * poDriver )
 {
     CPLMutexHolderD( &hDMMutex );
 
-    int i = 0;
-    for( ; i < nDrivers; i++ )
+    int i = 0;  // Used after for.
+    for( ; i < nDrivers; ++i )
     {
         if( papoDrivers[i] == poDriver )
             break;
@@ -504,12 +536,12 @@ void GDALDriverManager::DeregisterDriver( GDALDriver * poDriver )
         return;
 
     oMapNameToDrivers.erase(CPLString(poDriver->GetDescription()).toupper());
-    nDrivers--;
+    --nDrivers;
     // Move all following drivers down by one to pack the list.
     while( i < nDrivers )
     {
         papoDrivers[i] = papoDrivers[i+1];
-        i++;
+        ++i;
     }
 }
 
@@ -531,7 +563,6 @@ void CPL_STDCALL GDALDeregisterDriver( GDALDriverH hDriver )
     GetGDALDriverManager()->DeregisterDriver( (GDALDriver *) hDriver );
 }
 
-
 /************************************************************************/
 /*                          GetDriverByName()                           */
 /************************************************************************/
@@ -573,7 +604,7 @@ GDALDriverH CPL_STDCALL GDALGetDriverByName( const char * pszName )
 {
     VALIDATE_POINTER1( pszName, "GDALGetDriverByName", NULL );
 
-    return( GetGDALDriverManager()->GetDriverByName( pszName ) );
+    return GetGDALDriverManager()->GetDriverByName( pszName );
 }
 
 /************************************************************************/
@@ -603,27 +634,31 @@ void GDALDriverManager::AutoSkipDrivers()
     const char* pszGDAL_SKIP = CPLGetConfigOption( "GDAL_SKIP", NULL );
     if( pszGDAL_SKIP != NULL )
     {
-        /* Favour comma as a separator. If not found, then use space */
+        // Favor comma as a separator. If not found, then use space.
         const char* pszSep = (strchr(pszGDAL_SKIP, ',') != NULL) ? "," : " ";
-        apapszList[0] = CSLTokenizeStringComplex( pszGDAL_SKIP, pszSep, FALSE, FALSE);
+        apapszList[0] =
+            CSLTokenizeStringComplex( pszGDAL_SKIP, pszSep, FALSE, FALSE );
     }
     const char* pszOGR_SKIP = CPLGetConfigOption( "OGR_SKIP", NULL );
     if( pszOGR_SKIP != NULL )
     {
-        /* OGR has always used comma as a separator */
+        // OGR has always used comma as a separator.
         apapszList[1] = CSLTokenizeStringComplex(pszOGR_SKIP, ",", FALSE, FALSE);
     }
 
-    for( int j = 0; j < 2; j++ )
+    for( int j = 0; j < 2; ++j )
     {
-        for( int i = 0; apapszList[j] != NULL &&  apapszList[j][i] != NULL; i++ )
+        for( int i = 0; apapszList[j] != NULL && apapszList[j][i] != NULL; ++i )
         {
-            GDALDriver *poDriver = GetDriverByName( apapszList[j][i] );
+            GDALDriver * const poDriver = GetDriverByName( apapszList[j][i] );
 
             if( poDriver == NULL )
+            {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                        "Unable to find driver %s to unload from GDAL_SKIP environment variable.",
+                          "Unable to find driver %s to unload from GDAL_SKIP "
+                          "environment variable.",
                         apapszList[j][i] );
+            }
             else
             {
                 CPLDebug( "GDAL", "AutoSkipDriver(%s)", apapszList[j][i] );
@@ -656,7 +691,7 @@ void GDALDriverManager::AutoSkipDrivers()
  * search separated by colons on UNIX, or semi-colons on Windows.  Otherwise
  * the /usr/local/lib/gdalplugins directory, and (if known) the
  * lib/gdalplugins subdirectory of the gdal home directory are searched on
- * UNIX and $(BINDIR)\gdalplugins on Windows.
+ * UNIX and $(BINDIR)\\gdalplugins on Windows.
  *
  * Auto loading can be completely disabled by setting the GDAL_DRIVER_PATH
  * config option to "disable".
@@ -732,7 +767,6 @@ void GDALDriverManager::AutoLoadDrivers()
                                      num2str(GDAL_VERSION_MAJOR) "."
                                      num2str(GDAL_VERSION_MINOR) "/PlugIns" );
    #endif
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -745,7 +779,7 @@ void GDALDriverManager::AutoLoadDrivers()
 /* -------------------------------------------------------------------- */
 /*      Scan each directory looking for files starting with gdal_       */
 /* -------------------------------------------------------------------- */
-    for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
+    for( int iDir = 0; iDir < CSLCount(papszSearchPath); ++iDir )
     {
         CPLString osABISpecificDir =
             CPLFormFilename( papszSearchPath[iDir], osABIVersion, NULL );
@@ -757,7 +791,7 @@ void GDALDriverManager::AutoLoadDrivers()
         char **papszFiles = VSIReadDir( osABISpecificDir );
         const int nFileCount = CSLCount(papszFiles);
 
-        for( int iFile = 0; iFile < nFileCount; iFile++ )
+        for( int iFile = 0; iFile < nFileCount; ++iFile )
         {
             const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
 
@@ -775,7 +809,7 @@ void GDALDriverManager::AutoLoadDrivers()
                           "GDALRegister_%s",
                         CPLGetBasename(papszFiles[iFile]) + strlen("gdal_") );
             }
-            else if ( STARTS_WITH_CI(papszFiles[iFile], "ogr_") )
+            else if( STARTS_WITH_CI(papszFiles[iFile], "ogr_") )
             {
                 pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
                 snprintf( pszFuncName,
@@ -823,7 +857,6 @@ void GDALDriverManager::AutoLoadDrivers()
     CSLDestroy( papszSearchPath );
 
 #endif  // GDAL_NO_AUTOLOAD
-
 }
 
 /************************************************************************/
@@ -845,6 +878,15 @@ void CPL_STDCALL GDALDestroyDriverManager( void )
     // THREADSAFETY: We would like to lock the mutex here, but it
     // needs to be reacquired within the destructor during driver
     // deregistration.
+
+// FIXME: Disale following code as it crashed on OSX CI test.
+//#if HAVE_CXX11
+//    std::lock_guard<std::mutex> oLock(oDeleteMutex);
+//#endif
+
     if( poDM != NULL )
+    {
         delete poDM;
+        poDM = NULL;
+    }
 }
diff --git a/gcore/gdalexif.cpp b/gcore/gdalexif.cpp
index 5e053eb..f95a440 100644
--- a/gcore/gdalexif.cpp
+++ b/gcore/gdalexif.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalexif.cpp 33229 2016-01-29 19:45:40Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Implements a EXIF directory reader
@@ -31,20 +30,28 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_priv.h"
+#include "gdalexif.h"
+
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
 #include <vector>
 
 #include "cpl_conv.h"
-#include "cpl_port.h"
 #include "cpl_error.h"
 #include "cpl_string.h"
 #include "cpl_vsi.h"
 
-#include "gdal_priv.h"
-#include "gdalexif.h"
-
 using std::vector;
 
-CPL_CVSID("$Id: gdalexif.cpp 33229 2016-01-29 19:45:40Z goatbar $");
+CPL_CVSID("$Id: gdalexif.cpp 36523 2016-11-27 04:13:26Z goatbar $");
 
 static const int MAXSTRINGLENGTH = 65535;
 static const int EXIFOFFSETTAG = 0x8769;
@@ -68,7 +75,8 @@ static void EXIFPrintData(char* pszData, GUInt16 type,
   case TIFF_UNDEFINED:
   case TIFF_BYTE:
     for(;count>0;count--) {
-      snprintf(szTemp, sizeof(szTemp), "%s%#02x", sep, *data++), sep = " ";
+      snprintf(szTemp, sizeof(szTemp), "%s%#02x", sep, *data++);
+      sep = " ";
       if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
       strcat(pszDataEnd,szTemp);
@@ -78,7 +86,8 @@ static void EXIFPrintData(char* pszData, GUInt16 type,
 
   case TIFF_SBYTE:
     for(;count>0;count--) {
-      snprintf(szTemp, sizeof(szTemp), "%s%d", sep, *(const char *)data++), sep = " ";
+      snprintf(szTemp, sizeof(szTemp), "%s%d", sep, *(const char *)data++);
+      sep = " ";
       if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
       strcat(pszDataEnd,szTemp);
@@ -94,7 +103,8 @@ static void EXIFPrintData(char* pszData, GUInt16 type,
   case TIFF_SHORT: {
     const GUInt16 *wp = (const GUInt16*)data;
     for(;count>0;count--) {
-      snprintf(szTemp, sizeof(szTemp), "%s%u", sep, *wp++), sep = " ";
+      snprintf(szTemp, sizeof(szTemp), "%s%u", sep, *wp++);
+      sep = " ";
       if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
       strcat(pszDataEnd,szTemp);
@@ -129,7 +139,8 @@ static void EXIFPrintData(char* pszData, GUInt16 type,
   case TIFF_SLONG: {
     const GInt32 *lp = (const GInt32*)data;
     for(;count>0;count--) {
-      snprintf(szTemp, sizeof(szTemp), "%s%ld", sep, (long) *lp++), sep = " ";
+      snprintf(szTemp, sizeof(szTemp), "%s%ld", sep, (long) *lp++);
+      sep = " ";
       if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
       strcat(pszDataEnd,szTemp);
@@ -175,7 +186,8 @@ static void EXIFPrintData(char* pszData, GUInt16 type,
   case TIFF_FLOAT: {
     const float *fp = (const float *)data;
     for(;count>0;count--) {
-      CPLsnprintf(szTemp, sizeof(szTemp), "%s%g", sep, *fp++), sep = " ";
+      CPLsnprintf(szTemp, sizeof(szTemp), "%s%g", sep, *fp++);
+      sep = " ";
       if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
       strcat(pszDataEnd,szTemp);
@@ -186,7 +198,8 @@ static void EXIFPrintData(char* pszData, GUInt16 type,
   case TIFF_DOUBLE: {
     const double *dp = (const double *)data;
     for(;count>0;count--) {
-      CPLsnprintf(szTemp, sizeof(szTemp), "%s%g", sep, *dp++), sep = " ";
+      CPLsnprintf(szTemp, sizeof(szTemp), "%s%g", sep, *dp++);
+      sep = " ";
       if (strlen(szTemp) + pszDataEnd - pszData >= MAXSTRINGLENGTH)
           break;
       strcat(pszDataEnd,szTemp);
@@ -294,7 +307,7 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
               poExifTags++)
         {
             if(poExifTags->tag == poTIFFDirEntry->tdir_tag) {
-                CPLAssert( NULL != poExifTags && NULL != poExifTags->name );
+                CPLAssert( NULL != poExifTags->name );
 
                 CPLStrlcpy(szName, poExifTags->name, sizeof(szName));
                 break;
@@ -307,7 +320,7 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
                  poGPSTags++ )
             {
                 if( poGPSTags->tag == poTIFFDirEntry->tdir_tag ) {
-                    CPLAssert( NULL != poGPSTags && NULL != poGPSTags->name );
+                    CPLAssert( NULL != poGPSTags->name );
                     CPLStrlcpy(szName, poGPSTags->name, sizeof(szName));
                     break;
                 }
@@ -320,7 +333,7 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
             const struct intr_tag *poInterTags = intr_tags;
             for( ; poInterTags->tag; poInterTags++)
                 if(poInterTags->tag == poTIFFDirEntry->tdir_tag) {
-                    CPLAssert( NULL != poInterTags && NULL != poInterTags->name );
+                    CPLAssert( NULL != poInterTags->name );
                     CPLStrlcpy(szName, poInterTags->name, sizeof(szName));
                     break;
                 }
@@ -347,7 +360,7 @@ CPLErr EXIFExtractMetadata(char**& papszMetadata,
 /* -------------------------------------------------------------------- */
         if( szName[0] == '\0' )
         {
-            snprintf( szName, sizeof(szName), "EXIF_%d", poTIFFDirEntry->tdir_tag );
+            snprintf( szName, sizeof(szName), "EXIF_%u", poTIFFDirEntry->tdir_tag );
             continue;
         }
 
diff --git a/gcore/gdalexif.h b/gcore/gdalexif.h
index 6ab1560..92e5c8f 100644
--- a/gcore/gdalexif.h
+++ b/gcore/gdalexif.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalexif.h 33175 2016-01-27 00:37:49Z goatbar $
+ * $Id: gdalexif.h 35883 2016-10-24 05:49:15Z goatbar $
  *
  * Project:  JPEG JFIF Driver
  * Purpose:  Implement GDAL JPEG Support based on IJG libjpeg.
@@ -27,6 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+//! @cond Doxygen_Suppress
+
 #ifdef RENAME_INTERNAL_LIBTIFF_SYMBOLS
 #include "../frmts/gtiff/libtiff/gdal_libtiff_symbol_rename.h"
 #endif
@@ -73,119 +75,117 @@ static const struct tagname {
   GUInt16       tag;
   const char*   name;
 } tagnames [] = {
-
-//    { 0x100,	"EXIF_Image_Width"},
-//    { 0x101,	"EXIF_Image_Length"},
-    { 0x102,	"EXIF_BitsPerSample"},
-    { 0x103,	"EXIF_Compression"},
-    { 0x106,	"EXIF_PhotometricInterpretation"},
-    { 0x10A,	"EXIF_Fill_Order"},
-    { 0x10D,	"EXIF_Document_Name"},
-    { 0x10E,	"EXIF_ImageDescription"},
-    { 0x10F,	"EXIF_Make"},
-    { 0x110,	"EXIF_Model"},
-    { 0x111,	"EXIF_StripOffsets"},
-    { 0x112,	"EXIF_Orientation"},
-    { 0x115,	"EXIF_SamplesPerPixel"},
-    { 0x116,	"EXIF_RowsPerStrip"},
-    { 0x117,	"EXIF_StripByteCounts"},
-    { 0x11A,	"EXIF_XResolution"},
-    { 0x11B,	"EXIF_YResolution"},
-    { 0x11C,	"EXIF_PlanarConfiguration"},
-    { 0x128,	"EXIF_ResolutionUnit"},
-    { 0x12D,	"EXIF_TransferFunction"},
-    { 0x131,	"EXIF_Software"},
-    { 0x132,	"EXIF_DateTime"},
-    { 0x13B,	"EXIF_Artist"},
-    { 0x13E,	"EXIF_WhitePoint"},
-    { 0x13F,	"EXIF_PrimaryChromaticities"},
-    { 0x156,	"EXIF_Transfer_Range"},
-    { 0x200,	"EXIF_JPEG_Proc"},
-    { 0x201,	"EXIF_JPEGInterchangeFormat"},
-    { 0x202,	"EXIF_JPEGInterchangeFormatLength"},
-    { 0x211,	"EXIF_YCbCrCoefficients"},
-    { 0x212,	"EXIF_YCbCrSubSampling"},
-    { 0x213,	"EXIF_YCbCrPositioning"},
-    { 0x214,	"EXIF_ReferenceBlackWhite"},
-    { 0x828D,	"EXIF_CFA_Repeat_Pattern_Dim"},
-    { 0x828E,	"EXIF_CFA_Pattern"},
-    { 0x828F,	"EXIF_Battery_Level"},
-    { 0x8298,	"EXIF_Copyright"},
-    { 0x829A,	"EXIF_ExposureTime"},
-    { 0x829D,	"EXIF_FNumber"},
-    { 0x83BB,	"EXIF_IPTC/NAA"},
-//	{ 0x8769,	"EXIF_Offset"},
-    { 0x8773,	"EXIF_Inter_Color_Profile"},
-    { 0x8822,	"EXIF_ExposureProgram"},
-    { 0x8824,	"EXIF_SpectralSensitivity"},
-//	{ 0x8825,	"EXIF_GPSOffset"},
-    { 0x8827,	"EXIF_ISOSpeedRatings"},
-    { 0x8828,	"EXIF_OECF"},
-    { 0x9000,	"EXIF_ExifVersion"},
-    { 0x9003,	"EXIF_DateTimeOriginal"},
-    { 0x9004,	"EXIF_DateTimeDigitized"},
-    { 0x9101,	"EXIF_ComponentsConfiguration"},
-    { 0x9102,	"EXIF_CompressedBitsPerPixel"},
-    { 0x9201,	"EXIF_ShutterSpeedValue"},
-    { 0x9202,	"EXIF_ApertureValue"},
-    { 0x9203,	"EXIF_BrightnessValue"},
-    { 0x9204,	"EXIF_ExposureBiasValue"},
-    { 0x9205,	"EXIF_MaxApertureValue"},
-    { 0x9206,	"EXIF_SubjectDistance"},
-    { 0x9207,	"EXIF_MeteringMode"},
-    { 0x9208,	"EXIF_LightSource"},
-    { 0x9209,	"EXIF_Flash"},
-    { 0x920A,	"EXIF_FocalLength"},
-    { 0x9214,   "EXIF_SubjectArea"},
-    { 0x927C,	"EXIF_MakerNote"},
-    { 0x9286,	"EXIF_UserComment"},
-    { 0x9290,	"EXIF_SubSecTime"},
-    { 0x9291,	"EXIF_SubSecTime_Original"},
-    { 0x9292,	"EXIF_SubSecTime_Digitized"},
-    { 0xA000,	"EXIF_FlashpixVersion"},
-    { 0xA001,	"EXIF_ColorSpace"},
-    { 0xA002,	"EXIF_PixelXDimension"},
-    { 0xA003,	"EXIF_PixelYDimension"},
-    { 0xA004,       "EXIF_RelatedSoundFile"},
-//	{ 0xA005,	"EXIF_InteroperabilityOffset"},
-    { 0xA20B,	"EXIF_FlashEnergy"},	  // 0x920B in TIFF/EP
-    { 0xA20C,	"EXIF_SpatialFrequencyResponse"},   // 0x920C    -  -
-    { 0xA20E,	"EXIF_FocalPlaneXResolution"},     // 0x920E    -  -
-    { 0xA20F,	"EXIF_FocalPlaneYResolution"},     // 0x920F    -  -
-    { 0xA210,	"EXIF_FocalPlaneResolutionUnit"},  // 0x9210    -  -
-    { 0xA214,	"EXIF_SubjectLocation"},	// 0x9214    -  -
-    { 0xA215,	"EXIF_ExposureIndex"},		// 0x9215    -  -
-    { 0xA217,	"EXIF_SensingMethod"},		// 0x9217    -  -
-    { 0xA300,	"EXIF_FileSource"},
-    { 0xA301,	"EXIF_SceneType"},
-    { 0xA302,   "EXIF_CFAPattern"},
-    { 0xA401,   "EXIF_CustomRendered"},
-    { 0xA402,   "EXIF_ExposureMode"},
-    { 0XA403,   "EXIF_WhiteBalance"},
-    { 0xA404,   "EXIF_DigitalZoomRatio"},
-    { 0xA405,   "EXIF_FocalLengthIn35mmFilm"},
-    { 0xA406,   "EXIF_SceneCaptureType"},
-    { 0xA407,   "EXIF_GainControl"},
-    { 0xA408,   "EXIF_Contrast"},
-    { 0xA409,   "EXIF_Saturation"},
-    { 0xA40A,   "EXIF_Sharpness"},
-    { 0xA40B,   "EXIF_DeviceSettingDescription"},
-    { 0xA40C,   "EXIF_SubjectDistanceRange"},
-    { 0xA420,   "EXIF_ImageUniqueID"},
-    { 0x0000,       ""}
+    //{ 0x100, "EXIF_Image_Width"},
+    //  { 0x101, "EXIF_Image_Length"},
+    { 0x102, "EXIF_BitsPerSample"},
+    { 0x103, "EXIF_Compression"},
+    { 0x106, "EXIF_PhotometricInterpretation"},
+    { 0x10A, "EXIF_Fill_Order"},
+    { 0x10D, "EXIF_Document_Name"},
+    { 0x10E, "EXIF_ImageDescription"},
+    { 0x10F, "EXIF_Make"},
+    { 0x110, "EXIF_Model"},
+    { 0x111, "EXIF_StripOffsets"},
+    { 0x112, "EXIF_Orientation"},
+    { 0x115, "EXIF_SamplesPerPixel"},
+    { 0x116, "EXIF_RowsPerStrip"},
+    { 0x117, "EXIF_StripByteCounts"},
+    { 0x11A, "EXIF_XResolution"},
+    { 0x11B, "EXIF_YResolution"},
+    { 0x11C, "EXIF_PlanarConfiguration"},
+    { 0x128, "EXIF_ResolutionUnit"},
+    { 0x12D, "EXIF_TransferFunction"},
+    { 0x131, "EXIF_Software"},
+    { 0x132, "EXIF_DateTime"},
+    { 0x13B, "EXIF_Artist"},
+    { 0x13E, "EXIF_WhitePoint"},
+    { 0x13F, "EXIF_PrimaryChromaticities"},
+    { 0x156, "EXIF_Transfer_Range"},
+    { 0x200, "EXIF_JPEG_Proc"},
+    { 0x201, "EXIF_JPEGInterchangeFormat"},
+    { 0x202, "EXIF_JPEGInterchangeFormatLength"},
+    { 0x211, "EXIF_YCbCrCoefficients"},
+    { 0x212, "EXIF_YCbCrSubSampling"},
+    { 0x213, "EXIF_YCbCrPositioning"},
+    { 0x214, "EXIF_ReferenceBlackWhite"},
+    { 0x828D, "EXIF_CFA_Repeat_Pattern_Dim"},
+    { 0x828E, "EXIF_CFA_Pattern"},
+    { 0x828F, "EXIF_Battery_Level"},
+    { 0x8298, "EXIF_Copyright"},
+    { 0x829A, "EXIF_ExposureTime"},
+    { 0x829D, "EXIF_FNumber"},
+    { 0x83BB, "EXIF_IPTC/NAA"},
+    // { 0x8769, "EXIF_Offset"},
+    { 0x8773, "EXIF_Inter_Color_Profile"},
+    { 0x8822, "EXIF_ExposureProgram"},
+    { 0x8824, "EXIF_SpectralSensitivity"},
+    // { 0x8825, "EXIF_GPSOffset"},
+    { 0x8827, "EXIF_ISOSpeedRatings"},
+    { 0x8828, "EXIF_OECF"},
+    { 0x9000, "EXIF_ExifVersion"},
+    { 0x9003, "EXIF_DateTimeOriginal"},
+    { 0x9004, "EXIF_DateTimeDigitized"},
+    { 0x9101, "EXIF_ComponentsConfiguration"},
+    { 0x9102, "EXIF_CompressedBitsPerPixel"},
+    { 0x9201, "EXIF_ShutterSpeedValue"},
+    { 0x9202, "EXIF_ApertureValue"},
+    { 0x9203, "EXIF_BrightnessValue"},
+    { 0x9204, "EXIF_ExposureBiasValue"},
+    { 0x9205, "EXIF_MaxApertureValue"},
+    { 0x9206, "EXIF_SubjectDistance"},
+    { 0x9207, "EXIF_MeteringMode"},
+    { 0x9208, "EXIF_LightSource"},
+    { 0x9209, "EXIF_Flash"},
+    { 0x920A, "EXIF_FocalLength"},
+    { 0x9214, "EXIF_SubjectArea"},
+    { 0x927C, "EXIF_MakerNote"},
+    { 0x9286, "EXIF_UserComment"},
+    { 0x9290, "EXIF_SubSecTime"},
+    { 0x9291, "EXIF_SubSecTime_Original"},
+    { 0x9292, "EXIF_SubSecTime_Digitized"},
+    { 0xA000, "EXIF_FlashpixVersion"},
+    { 0xA001, "EXIF_ColorSpace"},
+    { 0xA002, "EXIF_PixelXDimension"},
+    { 0xA003, "EXIF_PixelYDimension"},
+    { 0xA004, "EXIF_RelatedSoundFile"},
+    // { 0xA005, "EXIF_InteroperabilityOffset"},
+    { 0xA20B, "EXIF_FlashEnergy"},   // 0x920B in TIFF/EP
+    { 0xA20C, "EXIF_SpatialFrequencyResponse"},   // 0x920C    -  -
+    { 0xA20E, "EXIF_FocalPlaneXResolution"},     // 0x920E    -  -
+    { 0xA20F, "EXIF_FocalPlaneYResolution"},     // 0x920F    -  -
+    { 0xA210, "EXIF_FocalPlaneResolutionUnit"},  // 0x9210    -  -
+    { 0xA214, "EXIF_SubjectLocation"}, // 0x9214    -  -
+    { 0xA215, "EXIF_ExposureIndex"},  // 0x9215    -  -
+    { 0xA217, "EXIF_SensingMethod"},  // 0x9217    -  -
+    { 0xA300, "EXIF_FileSource"},
+    { 0xA301, "EXIF_SceneType"},
+    { 0xA302, "EXIF_CFAPattern"},
+    { 0xA401, "EXIF_CustomRendered"},
+    { 0xA402, "EXIF_ExposureMode"},
+    { 0XA403, "EXIF_WhiteBalance"},
+    { 0xA404, "EXIF_DigitalZoomRatio"},
+    { 0xA405, "EXIF_FocalLengthIn35mmFilm"},
+    { 0xA406, "EXIF_SceneCaptureType"},
+    { 0xA407, "EXIF_GainControl"},
+    { 0xA408, "EXIF_Contrast"},
+    { 0xA409, "EXIF_Saturation"},
+    { 0xA40A, "EXIF_Sharpness"},
+    { 0xA40B, "EXIF_DeviceSettingDescription"},
+    { 0xA40C, "EXIF_SubjectDistanceRange"},
+    { 0xA420, "EXIF_ImageUniqueID"},
+    { 0x0000, ""}
 };
 
-
 static const struct intr_tag {
   GInt16        tag;
   const char*   name;
 } intr_tags [] = {
 
-    { 0x1,	"EXIF_Interoperability_Index"},
-    { 0x2,	"EXIF_Interoperability_Version"},
-    { 0x1000,	"EXIF_Related_Image_File_Format"},
-    { 0x1001,	"EXIF_Related_Image_Width"},
-    { 0x1002,	"EXIF_Related_Image_Length"},
+    { 0x1, "EXIF_Interoperability_Index"},
+    { 0x2, "EXIF_Interoperability_Version"},
+    { 0x1000, "EXIF_Related_Image_File_Format"},
+    { 0x1001, "EXIF_Related_Image_Width"},
+    { 0x1002, "EXIF_Related_Image_Length"},
     { 0x0000,       ""}
 };
 
@@ -225,11 +225,14 @@ typedef struct {
 } GDALEXIFTIFFDirEntry;
 
 CPL_C_START
-extern	int TIFFDataWidth(GDALEXIFTIFFDataType);    /* table of tag datatype widths */
-extern	void TIFFSwabShort(GUInt16*);
-extern	void TIFFSwabLong(GUInt32*);
-extern	void TIFFSwabDouble(double*);
-extern	void TIFFSwabArrayOfShort(GUInt16*, unsigned long);
-extern	void TIFFSwabArrayOfLong(GUInt32*, unsigned long);
-extern	void TIFFSwabArrayOfDouble(double*, unsigned long);
+/* Table of tag datatype widths. */
+extern int TIFFDataWidth(GDALEXIFTIFFDataType);
+extern void TIFFSwabShort(GUInt16*);
+extern void TIFFSwabLong(GUInt32*);
+extern void TIFFSwabDouble(double*);
+extern void TIFFSwabArrayOfShort(GUInt16*, unsigned long);
+extern void TIFFSwabArrayOfLong(GUInt32*, unsigned long);
+extern void TIFFSwabArrayOfDouble(double*, unsigned long);
 CPL_C_END
+
+//! @endcond
diff --git a/gcore/gdalgeorefpamdataset.cpp b/gcore/gdalgeorefpamdataset.cpp
index 6de69a7..9513318 100644
--- a/gcore/gdalgeorefpamdataset.cpp
+++ b/gcore/gdalgeorefpamdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalgeorefpamdataset.cpp 33535 2016-02-23 17:41:09Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  GDALPamDataset with internal storage for georeferencing, with
@@ -30,6 +29,13 @@
 
 #include "gdalgeorefpamdataset.h"
 
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "gdal.h"
+
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                       GDALGeorefPamDataset()                         */
 /************************************************************************/
@@ -38,7 +44,18 @@ GDALGeorefPamDataset::GDALGeorefPamDataset() :
     bGeoTransformValid(false),
     pszProjection(NULL),
     nGCPCount(0),
-    pasGCPList(NULL)
+    pasGCPList(NULL),
+    m_papszRPC(NULL),
+    m_bPixelIsPoint(false),
+    m_nGeoTransformGeorefSrcIndex(-1),
+    m_nGCPGeorefSrcIndex(-1),
+    m_nProjectionGeorefSrcIndex(-1),
+    m_nRPCGeorefSrcIndex(-1),
+    m_nPixelIsPointGeorefSrcIndex(-1),
+    m_bGotPAMGeorefSrcIndex(false),
+    m_nPAMGeorefSrcIndex(0),
+    m_bPAMLoaded(false),
+    m_papszMainMD(NULL)
 {
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
@@ -61,98 +78,266 @@ GDALGeorefPamDataset::~GDALGeorefPamDataset()
         GDALDeinitGCPs( nGCPCount, pasGCPList );
         CPLFree( pasGCPList );
     }
+    CSLDestroy(m_papszMainMD);
+    CSLDestroy(m_papszRPC);
+}
+
+/************************************************************************/
+/*                          GetMetadata()                               */
+/************************************************************************/
+
+char      **GDALGeorefPamDataset::GetMetadata( const char * pszDomain )
+{
+    if( pszDomain != NULL && EQUAL(pszDomain, "RPC") )
+    {
+        const int nPAMIndex = GetPAMGeorefSrcIndex();
+        if( nPAMIndex >= 0 &&
+            ((m_papszRPC != NULL && nPAMIndex < m_nRPCGeorefSrcIndex) ||
+            m_nRPCGeorefSrcIndex < 0 || m_papszRPC == NULL))
+        {
+            char** papszMD = GDALPamDataset::GetMetadata(pszDomain);
+            if( papszMD )
+                return papszMD;
+        }
+        return m_papszRPC;
+    }
+
+    if( pszDomain == NULL || EQUAL(pszDomain, "") )
+    {
+        if( m_papszMainMD )
+            return m_papszMainMD;
+        m_papszMainMD = CSLDuplicate(GDALPamDataset::GetMetadata(pszDomain));
+        const int nPAMIndex = GetPAMGeorefSrcIndex();
+        if( nPAMIndex >= 0 &&
+            ((m_bPixelIsPoint && nPAMIndex < m_nPixelIsPointGeorefSrcIndex) ||
+            m_nPixelIsPointGeorefSrcIndex < 0 || !m_bPixelIsPoint))
+        {
+            if( CSLFetchNameValue(m_papszMainMD, GDALMD_AREA_OR_POINT) != NULL )
+                return m_papszMainMD;
+        }
+        if( m_bPixelIsPoint )
+        {
+            m_papszMainMD = CSLSetNameValue(m_papszMainMD,
+                                            GDALMD_AREA_OR_POINT,
+                                            GDALMD_AOP_POINT);
+        }
+        else
+        {
+            m_papszMainMD = CSLSetNameValue(m_papszMainMD,
+                                            GDALMD_AREA_OR_POINT, NULL);
+        }
+        return m_papszMainMD;
+    }
+
+    return GDALPamDataset::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                         GetMetadataItem()                            */
+/************************************************************************/
+
+const char *GDALGeorefPamDataset::GetMetadataItem( const char * pszName,
+                                                   const char * pszDomain )
+{
+    if( pszDomain == NULL || EQUAL(pszDomain, "") || EQUAL(pszDomain, "RPC") )
+    {
+        return CSLFetchNameValue( GetMetadata(pszDomain), pszName );
+    }
+    return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                           TryLoadXML()                              */
+/************************************************************************/
+
+CPLErr GDALGeorefPamDataset::TryLoadXML(char **papszSiblingFiles)
+{
+    m_bPAMLoaded = true;
+    CPLErr eErr = GDALPamDataset::TryLoadXML(papszSiblingFiles);
+    CSLDestroy(m_papszMainMD);
+    m_papszMainMD = NULL;
+    return eErr;
+}
+
+/************************************************************************/
+/*                            SetMetadata()                             */
+/************************************************************************/
+
+CPLErr GDALGeorefPamDataset::SetMetadata( char ** papszMetadata,
+                                           const char * pszDomain )
+{
+    if( m_bPAMLoaded && (pszDomain == NULL || EQUAL(pszDomain, "")) )
+    {
+        CSLDestroy(m_papszMainMD);
+        m_papszMainMD = CSLDuplicate(papszMetadata);
+    }
+    return GDALPamDataset::SetMetadata(papszMetadata, pszDomain);
 }
 
+/************************************************************************/
+/*                            SetMetadata()                             */
+/************************************************************************/
+
+CPLErr GDALGeorefPamDataset::SetMetadataItem( const char * pszName,
+                                            const char * pszValue,
+                                            const char * pszDomain )
+{
+    if( m_bPAMLoaded && (pszDomain == NULL || EQUAL(pszDomain, "")) )
+    {
+        m_papszMainMD = CSLSetNameValue( GetMetadata(), pszName, pszValue );
+    }
+    return GDALPamDataset::SetMetadataItem(pszName, pszValue, pszDomain);
+}
 
 /************************************************************************/
 /*                            GetGCPCount()                             */
 /*                                                                      */
-/*      We let PAM coordinate system override the one stored inside     */
-/*      our file.                                                       */
+/*      By default, we let PAM override the value stored                */
+/*      inside our file, unless GDAL_GEOREF_SOURCES is defined.         */
 /************************************************************************/
 
 int GDALGeorefPamDataset::GetGCPCount()
 
 {
-    const int nPamGCPCount = GDALPamDataset::GetGCPCount();
-    if( nGCPCount > 0 && nPamGCPCount == 0)
-        return nGCPCount;
+    const int nPAMIndex = GetPAMGeorefSrcIndex();
+    if( nPAMIndex >= 0 &&
+        ((nGCPCount != 0 && nPAMIndex < m_nGCPGeorefSrcIndex) ||
+         m_nGCPGeorefSrcIndex < 0 || nGCPCount == 0))
+    {
+        const int nPAMGCPCount = GDALPamDataset::GetGCPCount();
+        if( nPAMGCPCount )
+            return nPAMGCPCount;
+    }
 
-    return nPamGCPCount;
+    return nGCPCount;
 }
 
 /************************************************************************/
 /*                          GetGCPProjection()                          */
 /*                                                                      */
-/*      We let PAM coordinate system override the one stored inside     */
-/*      our file.                                                       */
+/*      By default, we let PAM override the value stored                */
+/*      inside our file, unless GDAL_GEOREF_SOURCES is defined.         */
 /************************************************************************/
 
 const char *GDALGeorefPamDataset::GetGCPProjection()
 
 {
-    const char* pszPamPrj = GDALPamDataset::GetGCPProjection();
-    if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
+    const int nPAMIndex = GetPAMGeorefSrcIndex();
+    if( nPAMIndex >= 0 &&
+        ((pszProjection != NULL && nPAMIndex < m_nProjectionGeorefSrcIndex) ||
+         m_nProjectionGeorefSrcIndex < 0 || pszProjection == NULL) )
+    {
+        const char* pszPAMGCPProjection = GDALPamDataset::GetGCPProjection();
+        if( pszPAMGCPProjection != NULL && strlen(pszPAMGCPProjection) > 0 )
+            return pszPAMGCPProjection;
+    }
+
+    if( pszProjection != NULL )
         return pszProjection;
 
-    return pszPamPrj;
+    return "";
 }
 
 /************************************************************************/
 /*                               GetGCP()                               */
 /*                                                                      */
-/*      We let PAM coordinate system override the one stored inside     */
-/*      our file.                                                       */
+/*      By default, we let PAM override the value stored                */
+/*      inside our file, unless GDAL_GEOREF_SOURCES is defined.         */
 /************************************************************************/
 
 const GDAL_GCP *GDALGeorefPamDataset::GetGCPs()
 
 {
-    const int nPamGCPCount = GDALPamDataset::GetGCPCount();
-    if( nGCPCount > 0 && nPamGCPCount == 0)
-        return pasGCPList;
+    const int nPAMIndex = GetPAMGeorefSrcIndex();
+    if( nPAMIndex >= 0 &&
+        ((nGCPCount != 0 && nPAMIndex < m_nGCPGeorefSrcIndex) ||
+         m_nGCPGeorefSrcIndex < 0 || nGCPCount == 0))
+    {
+        const GDAL_GCP* pasPAMGCPList = GDALPamDataset::GetGCPs();
+        if( pasPAMGCPList )
+            return pasPAMGCPList;
+    }
 
-    return GDALPamDataset::GetGCPs();
+    return pasGCPList;
 }
 
 /************************************************************************/
 /*                          GetProjectionRef()                          */
 /*                                                                      */
-/*      We let PAM coordinate system override the one stored inside     */
-/*      our file.                                                       */
+/*      By default, we let PAM override the value stored                */
+/*      inside our file, unless GDAL_GEOREF_SOURCES is defined.         */
 /************************************************************************/
 
 const char *GDALGeorefPamDataset::GetProjectionRef()
 
 {
-    const char* pszPamPrj = GDALPamDataset::GetProjectionRef();
-
     if( GetGCPCount() > 0 )
         return "";
 
-    if( pszProjection != NULL && strlen(pszPamPrj) == 0 )
+    const int nPAMIndex = GetPAMGeorefSrcIndex();
+    if( nPAMIndex >= 0 &&
+        ((pszProjection != NULL && nPAMIndex < m_nProjectionGeorefSrcIndex) ||
+         m_nProjectionGeorefSrcIndex < 0 || pszProjection == NULL) )
+    {
+        const char* pszPAMProjection = GDALPamDataset::GetProjectionRef();
+        if( pszPAMProjection != NULL && strlen(pszPAMProjection) > 0 )
+            return pszPAMProjection;
+    }
+
+    if( pszProjection != NULL )
         return pszProjection;
 
-    return pszPamPrj;
+    return "";
 }
 
 /************************************************************************/
 /*                          GetGeoTransform()                           */
 /*                                                                      */
-/*      Let the PAM geotransform override the native one if it is       */
-/*      available.                                                      */
+/*      By default, we let PAM override the value stored                */
+/*      inside our file, unless GDAL_GEOREF_SOURCES is defined.         */
 /************************************************************************/
 
 CPLErr GDALGeorefPamDataset::GetGeoTransform( double * padfTransform )
 
 {
-    CPLErr eErr = GDALPamDataset::GetGeoTransform( padfTransform );
+    const int nPAMIndex = GetPAMGeorefSrcIndex();
+    if( nPAMIndex >= 0 &&
+        ((bGeoTransformValid && nPAMIndex <= m_nGeoTransformGeorefSrcIndex) ||
+          m_nGeoTransformGeorefSrcIndex < 0 || !bGeoTransformValid) )
+    {
+        if( GDALPamDataset::GetGeoTransform( padfTransform ) == CE_None )
+        {
+            m_nGeoTransformGeorefSrcIndex = nPAMIndex;
+            return CE_None;
+        }
+    }
 
-    if( eErr != CE_None && bGeoTransformValid )
+    if( bGeoTransformValid )
     {
         memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
         return( CE_None );
     }
 
-    return eErr;
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                     GetPAMGeorefSrcIndex()                           */
+/*                                                                      */
+/*      Get priority index of PAM (the lower, the more prioritary)      */
+/************************************************************************/
+int GDALGeorefPamDataset::GetPAMGeorefSrcIndex()
+{
+    if( !m_bGotPAMGeorefSrcIndex )
+    {
+        m_bGotPAMGeorefSrcIndex = true;
+        const char* pszGeorefSources = CSLFetchNameValueDef( papszOpenOptions,
+            "GEOREF_SOURCES",
+            CPLGetConfigOption("GDAL_GEOREF_SOURCES", "PAM,OTHER") );
+        char** papszTokens = CSLTokenizeString2(pszGeorefSources, ",", 0);
+        m_nPAMGeorefSrcIndex = CSLFindString(papszTokens, "PAM");
+        CSLDestroy(papszTokens);
+    }
+    return m_nPAMGeorefSrcIndex;
 }
+//! @endcond
diff --git a/gcore/gdalgeorefpamdataset.h b/gcore/gdalgeorefpamdataset.h
index 326b2b3..c91977e 100644
--- a/gcore/gdalgeorefpamdataset.h
+++ b/gcore/gdalgeorefpamdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalgeorefpamdataset.h 33794 2016-03-26 13:19:07Z goatbar $
+ * $Id: gdalgeorefpamdataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL
  * Purpose:  GDALPamDataset with internal storage for georeferencing, with
@@ -31,6 +31,8 @@
 #ifndef GDAL_GEOREF_PAM_DATASET_H_INCLUDED
 #define GDAL_GEOREF_PAM_DATASET_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "gdal_pam.h"
 
 class CPL_DLL GDALGeorefPamDataset : public GDALPamDataset
@@ -41,17 +43,45 @@ class CPL_DLL GDALGeorefPamDataset : public GDALPamDataset
     char        *pszProjection;
     int         nGCPCount;
     GDAL_GCP    *pasGCPList;
+    char**      m_papszRPC;
+    bool        m_bPixelIsPoint;
+
+    int         m_nGeoTransformGeorefSrcIndex;
+    int         m_nGCPGeorefSrcIndex;
+    int         m_nProjectionGeorefSrcIndex;
+    int         m_nRPCGeorefSrcIndex;
+    int         m_nPixelIsPointGeorefSrcIndex;
+
+    int         GetPAMGeorefSrcIndex();
+    bool        m_bGotPAMGeorefSrcIndex;
+    int         m_nPAMGeorefSrcIndex;
+
+    bool        m_bPAMLoaded;
+    char**      m_papszMainMD;
 
   public:
         GDALGeorefPamDataset();
         virtual ~GDALGeorefPamDataset();
 
-    virtual CPLErr          GetGeoTransform( double * );
-    virtual const char     *GetProjectionRef();
+    virtual CPLErr TryLoadXML(char **papszSiblingFiles = NULL) CPL_OVERRIDE;
 
-    virtual int             GetGCPCount();
-    virtual const char     *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual CPLErr          GetGeoTransform( double * ) CPL_OVERRIDE;
+    virtual const char     *GetProjectionRef() CPL_OVERRIDE;
+
+    virtual int             GetGCPCount() CPL_OVERRIDE;
+    virtual const char     *GetGCPProjection() CPL_OVERRIDE;
+    virtual const GDAL_GCP *GetGCPs() CPL_OVERRIDE;
+
+    virtual char      **GetMetadata( const char * pszDomain = "" ) CPL_OVERRIDE;
+    virtual const char *GetMetadataItem( const char * pszName,
+                                          const char * pszDomain = "" ) CPL_OVERRIDE;
+    virtual CPLErr      SetMetadata( char ** papszMetadata,
+                             const char * pszDomain = "" ) CPL_OVERRIDE;
+    virtual CPLErr      SetMetadataItem( const char * pszName,
+                                 const char * pszValue,
+                                 const char * pszDomain = "" ) CPL_OVERRIDE;
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* GDAL_GEOREF_PAM_DATASET_H_INCLUDED */
diff --git a/gcore/gdalgmlcoverage.cpp b/gcore/gdalgmlcoverage.cpp
index 89bac9c..1aac97b 100644
--- a/gcore/gdalgmlcoverage.cpp
+++ b/gcore/gdalgmlcoverage.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalgmlcoverage.cpp 33526 2016-02-22 20:54:09Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  Generic support for GML Coverage descriptions.
@@ -27,14 +26,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h"
-#include "cpl_minixml.h"
+#include "cpl_port.h"
 #include "gdal_priv.h"
+
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdalgmlcoverage.cpp 33526 2016-02-22 20:54:09Z goatbar $");
+CPL_CVSID("$Id: gdalgmlcoverage.cpp 36523 2016-11-27 04:13:26Z goatbar $");
 
 /************************************************************************/
 /*                        ParseGMLCoverageDesc()                        */
diff --git a/gcore/gdalhashsetbandblockcache.cpp b/gcore/gdalhashsetbandblockcache.cpp
index 4415719..5da51ea 100644
--- a/gcore/gdalhashsetbandblockcache.cpp
+++ b/gcore/gdalhashsetbandblockcache.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalhashsetbandblockcache.cpp 33536 2016-02-23 17:48:22Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Store cached blocks in a hash set
@@ -28,12 +27,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_hash_set.h"
-#include "cpl_multiproc.h"
+#include "cpl_port.h"
 #include "gdal_priv.h"
+
+#include <cstddef>
 #include <algorithm>
+#include <vector>
 
-CPL_CVSID("$Id: gdalhashsetbandblockcache.cpp 33536 2016-02-23 17:48:22Z goatbar $");
+#include "cpl_config.h"
+#include "cpl_error.h"
+#include "cpl_hash_set.h"
+#include "cpl_multiproc.h"
+
+CPL_CVSID("$Id: gdalhashsetbandblockcache.cpp 36523 2016-11-27 04:13:26Z goatbar $");
+
+//! @cond Doxygen_Suppress
 
 /* ******************************************************************** */
 /*                        GDALHashSetBandBlockCache                     */
@@ -45,25 +53,26 @@ class GDALHashSetBandBlockCache CPL_FINAL : public GDALAbstractBandBlockCache
     CPLLock        *hLock;
 
     public:
-            GDALHashSetBandBlockCache(GDALRasterBand* poBand);
-           ~GDALHashSetBandBlockCache();
+           explicit GDALHashSetBandBlockCache( GDALRasterBand* poBand );
+           virtual ~GDALHashSetBandBlockCache();
 
-           virtual bool             Init();
-           virtual bool             IsInitOK();
-           virtual CPLErr           FlushCache();
-           virtual CPLErr           AdoptBlock( GDALRasterBlock * );
+           virtual bool             Init() override;
+           virtual bool             IsInitOK() override;
+           virtual CPLErr           FlushCache() override;
+           virtual CPLErr           AdoptBlock( GDALRasterBlock * ) override;
            virtual GDALRasterBlock *TryGetLockedBlockRef( int nXBlockOff,
-                                                          int nYBlockYOff );
-           virtual CPLErr           UnreferenceBlock( GDALRasterBlock* poBlock );
+                                                          int nYBlockYOff ) override;
+           virtual CPLErr           UnreferenceBlock( GDALRasterBlock* poBlock ) override;
            virtual CPLErr           FlushBlock( int nXBlockOff, int nYBlockOff,
-                                                int bWriteDirtyBlock );
+                                                int bWriteDirtyBlock ) override;
 };
 
 /************************************************************************/
 /*                     GDALHashSetBandBlockCacheCreate()                */
 /************************************************************************/
 
-GDALAbstractBandBlockCache* GDALHashSetBandBlockCacheCreate(GDALRasterBand* poBand)
+GDALAbstractBandBlockCache* GDALHashSetBandBlockCacheCreate(
+    GDALRasterBand* poBand )
 {
     return new GDALHashSetBandBlockCache(poBand);
 }
@@ -72,14 +81,15 @@ GDALAbstractBandBlockCache* GDALHashSetBandBlockCacheCreate(GDALRasterBand* poBa
 /*                      GDALRasterBlockHashFunc()                       */
 /************************************************************************/
 
-/* calculate hash value */
+// Calculate hash value.
 static unsigned long GDALRasterBlockHashFunc( const void * const elt )
 {
     const GDALRasterBlock * const poBlock =
-        static_cast<const GDALRasterBlock * const>(elt);
+        static_cast<const GDALRasterBlock *>(elt);
 #if SIZEOF_UNSIGNED_LONG == 8
     return static_cast<unsigned long>(
-        poBlock->GetXOff() | (((unsigned long)poBlock->GetYOff()) << 32));
+        poBlock->GetXOff() |
+        (static_cast<unsigned long>(poBlock->GetYOff()) << 32) );
 #else
     return static_cast<unsigned long>(
         ((poBlock->GetXOff() & 0xFFFF) ^ (poBlock->GetYOff() >> 16)) |
@@ -91,14 +101,15 @@ static unsigned long GDALRasterBlockHashFunc( const void * const elt )
 /*                      GDALRasterBlockEqualFunc()                      */
 /************************************************************************/
 
-/* test equality */
+// Test equality.
+// Must return an int rather than a bool to work with CPLHashSetNew.
 static int GDALRasterBlockEqualFunc( const void * const elt1,
                                      const void * const elt2 )
 {
     const GDALRasterBlock * const poBlock1 =
-        static_cast<const GDALRasterBlock * const>(elt1);
+        static_cast<const GDALRasterBlock *>(elt1);
     const GDALRasterBlock * const poBlock2 =
-        static_cast<const GDALRasterBlock * const >(elt2);
+        static_cast<const GDALRasterBlock *>(elt2);
     return poBlock1->GetXOff() == poBlock2->GetXOff() &&
            poBlock1->GetYOff() == poBlock2->GetYOff();
 }
@@ -107,9 +118,11 @@ static int GDALRasterBlockEqualFunc( const void * const elt1,
 /*                       GDALHashSetBandBlockCache()                    */
 /************************************************************************/
 
-GDALHashSetBandBlockCache::GDALHashSetBandBlockCache(GDALRasterBand* poBandIn) :
+GDALHashSetBandBlockCache::GDALHashSetBandBlockCache(
+    GDALRasterBand* poBandIn ) :
     GDALAbstractBandBlockCache(poBandIn),
-    hSet(CPLHashSetNew(GDALRasterBlockHashFunc, GDALRasterBlockEqualFunc, NULL)),
+    hSet(CPLHashSetNew(GDALRasterBlockHashFunc,
+                       GDALRasterBlockEqualFunc, NULL)),
     hLock(CPLCreateLock(LOCK_ADAPTIVE_MUTEX))
 {}
 
@@ -161,12 +174,16 @@ CPLErr GDALHashSetBandBlockCache::AdoptBlock( GDALRasterBlock * poBlock )
 /*              GDALHashSetBandBlockCacheFlushCacheIterFunc()           */
 /************************************************************************/
 
-static int GDALHashSetBandBlockCacheFlushCacheIterFunc(void* elt, void* user_data)
+// Must return an int to work with CPLHashSetForeach.
+static int GDALHashSetBandBlockCacheFlushCacheIterFunc( void* elt,
+                                                        void* user_data )
 {
-    std::vector<GDALRasterBlock*>* papoBlocks = (std::vector<GDALRasterBlock*>*)user_data;
-    GDALRasterBlock* poBlock = (GDALRasterBlock*) elt;
+    // TODO(schwehr): Do all of the HashSet stuff be done in a type safe manner.
+    std::vector<GDALRasterBlock*>* papoBlocks =
+        static_cast<std::vector<GDALRasterBlock *> *>(user_data);
+    GDALRasterBlock* poBlock = static_cast<GDALRasterBlock *>(elt);
     papoBlocks->push_back(poBlock);
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -174,8 +191,8 @@ static int GDALHashSetBandBlockCacheFlushCacheIterFunc(void* elt, void* user_dat
 /************************************************************************/
 
 // TODO: Both args should be const.
-static bool GDALHashSetBandBlockCacheSortBlocks(GDALRasterBlock* poBlock1,
-                                                GDALRasterBlock* poBlock2)
+static bool GDALHashSetBandBlockCacheSortBlocks( GDALRasterBlock* poBlock1,
+                                                 GDALRasterBlock* poBlock2 )
 {
     return poBlock1->GetYOff() < poBlock2->GetYOff() ||
            ( poBlock1->GetYOff() == poBlock2->GetYOff() &&
@@ -204,15 +221,16 @@ CPLErr GDALHashSetBandBlockCache::FlushCache()
 
     // Sort blocks by increasing y and then x in order to please some tests
     // like tiff_write_133
-    std::sort(apoBlocks.begin(), apoBlocks.end(), GDALHashSetBandBlockCacheSortBlocks);
+    std::sort(apoBlocks.begin(), apoBlocks.end(),
+              GDALHashSetBandBlockCacheSortBlocks);
 
-    for(size_t i=0;i<apoBlocks.size();i++)
+    for( size_t i = 0; i < apoBlocks.size(); ++i )
     {
-        GDALRasterBlock* poBlock = apoBlocks[i];
+        GDALRasterBlock* const poBlock = apoBlocks[i];
 
         if( poBlock->DropLockForRemovalFromStorage() )
         {
-            CPLErr    eErr = CE_None;
+            CPLErr eErr = CE_None;
 
             if( eGlobalErr == CE_None && poBlock->GetDirty() )
                 eErr = poBlock->Write();
@@ -278,8 +296,8 @@ CPLErr GDALHashSetBandBlockCache::FlushBlock( int nXBlockOff, int nYBlockOff,
 /*                        TryGetLockedBlockRef()                        */
 /************************************************************************/
 
-GDALRasterBlock *GDALHashSetBandBlockCache::TryGetLockedBlockRef( int nXBlockOff,
-                                                                  int nYBlockOff )
+GDALRasterBlock *GDALHashSetBandBlockCache::TryGetLockedBlockRef(
+    int nXBlockOff, int nYBlockOff )
 
 {
     GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
@@ -300,3 +318,5 @@ GDALRasterBlock *GDALHashSetBandBlockCache::TryGetLockedBlockRef( int nXBlockOff
     poBlock->Touch();
     return poBlock;
 }
+
+//! @endcond
diff --git a/gcore/gdaljp2abstractdataset.cpp b/gcore/gdaljp2abstractdataset.cpp
index d50e6f4..09f4e03 100644
--- a/gcore/gdaljp2abstractdataset.cpp
+++ b/gcore/gdaljp2abstractdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaljp2abstractdataset.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  GDALGeorefPamDataset with helper to read georeferencing and other
@@ -29,21 +28,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdaljp2abstractdataset.h"
+
+#include <cstring>
+
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_mdreader.h"
+#include "gdal_priv.h"
 #include "gdaljp2metadata.h"
 #include "ogrsf_frmts.h"
-#include "gdal_mdreader.h"
+
+/*! @cond Doxygen_Suppress */
 
 /************************************************************************/
 /*                     GDALJP2AbstractDataset()                         */
 /************************************************************************/
 
-GDALJP2AbstractDataset::GDALJP2AbstractDataset()
-{
-    pszWldFilename = NULL;
-    poMemDS = NULL;
-    papszMetadataFiles = NULL;
-}
+GDALJP2AbstractDataset::GDALJP2AbstractDataset() :
+    pszWldFilename(NULL),
+    poMemDS(NULL),
+    papszMetadataFiles(NULL),
+    m_nWORLDFILEIndex(-1)
+{}
 
 /************************************************************************/
 /*                     ~GDALJP2AbstractDataset()                        */
@@ -62,60 +76,118 @@ GDALJP2AbstractDataset::~GDALJP2AbstractDataset()
 
 int GDALJP2AbstractDataset::CloseDependentDatasets()
 {
-    int bRet = GDALGeorefPamDataset::CloseDependentDatasets();
-    if( poMemDS )
-    {
-        GDALClose(poMemDS);
-        poMemDS = NULL;
-        bRet = TRUE;
-    }
-    return bRet;
+    const bool bRet =
+        CPL_TO_BOOL( GDALGeorefPamDataset::CloseDependentDatasets() );
+    if( poMemDS == NULL )
+      return bRet;
+
+    GDALClose(poMemDS);
+    poMemDS = NULL;
+    return true;
 }
 
 /************************************************************************/
 /*                          LoadJP2Metadata()                           */
 /************************************************************************/
 
-void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
-                                             const char* pszOverrideFilenameIn)
+void GDALJP2AbstractDataset::LoadJP2Metadata(
+    GDALOpenInfo* poOpenInfo, const char* pszOverrideFilenameIn )
 {
     const char* pszOverrideFilename = pszOverrideFilenameIn;
     if( pszOverrideFilename == NULL )
         pszOverrideFilename = poOpenInfo->pszFilename;
 
 /* -------------------------------------------------------------------- */
+/*      Identify authorized georeferencing sources                      */
+/* -------------------------------------------------------------------- */
+    const char* pszGeorefSourcesOption =
+        CSLFetchNameValue( poOpenInfo->papszOpenOptions, "GEOREF_SOURCES");
+    bool bGeorefSourcesConfigOption = pszGeorefSourcesOption != NULL;
+    CPLString osGeorefSources = (pszGeorefSourcesOption) ?
+        pszGeorefSourcesOption :
+        CPLGetConfigOption("GDAL_GEOREF_SOURCES", "PAM,INTERNAL,WORLDFILE");
+    size_t nInternalIdx = osGeorefSources.ifind("INTERNAL");
+    if( nInternalIdx != std::string::npos &&
+        (nInternalIdx == 0 || osGeorefSources[nInternalIdx-1] == ',') &&
+        (nInternalIdx + strlen("INTERNAL") == osGeorefSources.size() ||
+         osGeorefSources[nInternalIdx+strlen("INTERNAL")] == ',') )
+    {
+        osGeorefSources.replace( nInternalIdx, strlen("INTERNAL"),
+                                 "GEOJP2,GMLJP2,MSIG" );
+    }
+    char** papszTokens = CSLTokenizeString2(osGeorefSources, ",", 0);
+    m_bGotPAMGeorefSrcIndex = true;
+    m_nPAMGeorefSrcIndex = CSLFindString(papszTokens, "PAM");
+    const int nGEOJP2Index = CSLFindString(papszTokens, "GEOJP2");
+    const int nGMLJP2Index = CSLFindString(papszTokens, "GMLJP2");
+    const int nMSIGIndex = CSLFindString(papszTokens, "MSIG");
+    m_nWORLDFILEIndex = CSLFindString(papszTokens, "WORLDFILE");
+
+    if( bGeorefSourcesConfigOption )
+    {
+        for(char** papszIter = papszTokens; *papszIter; ++papszIter )
+        {
+            if( !EQUAL(*papszIter, "PAM") &&
+                !EQUAL(*papszIter, "GEOJP2") &&
+                !EQUAL(*papszIter, "GMLJP2") &&
+                !EQUAL(*papszIter, "MSIG") &&
+                !EQUAL(*papszIter, "WORLDFILE") &&
+                !EQUAL(*papszIter, "NONE") )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Unhandled value %s in GEOREF_SOURCES", *papszIter);
+            }
+        }
+    }
+    CSLDestroy(papszTokens);
+
+/* -------------------------------------------------------------------- */
 /*      Check for georeferencing information.                           */
 /* -------------------------------------------------------------------- */
     GDALJP2Metadata oJP2Geo;
-
-    if( (poOpenInfo->fpL != NULL && pszOverrideFilenameIn == NULL &&
-         oJP2Geo.ReadAndParse(poOpenInfo->fpL) ) ||
+    int nIndexUsed = -1;
+    if( ((poOpenInfo->fpL != NULL && pszOverrideFilenameIn == NULL &&
+         oJP2Geo.ReadAndParse(poOpenInfo->fpL, nGEOJP2Index, nGMLJP2Index,
+                              nMSIGIndex, &nIndexUsed) ) ||
         (!(poOpenInfo->fpL != NULL && pszOverrideFilenameIn == NULL) &&
-         oJP2Geo.ReadAndParse( pszOverrideFilename )) )
+         oJP2Geo.ReadAndParse( pszOverrideFilename, nGEOJP2Index, nGMLJP2Index,
+                               nMSIGIndex, m_nWORLDFILEIndex, &nIndexUsed ))) &&
+        (nGMLJP2Index >= 0 || nGEOJP2Index >= 0 || nMSIGIndex >= 0 ||
+         m_nWORLDFILEIndex >= 0) )
     {
         CPLFree(pszProjection);
         pszProjection = CPLStrdup(oJP2Geo.pszProjection);
+        if( strlen(pszProjection) > 0 )
+            m_nProjectionGeorefSrcIndex = nIndexUsed;
         bGeoTransformValid = CPL_TO_BOOL( oJP2Geo.bHaveGeoTransform );
+        if( bGeoTransformValid )
+            m_nGeoTransformGeorefSrcIndex = nIndexUsed;
         memcpy( adfGeoTransform, oJP2Geo.adfGeoTransform,
                 sizeof(double) * 6 );
         nGCPCount = oJP2Geo.nGCPCount;
+        if( nGCPCount )
+            m_nGCPGeorefSrcIndex = nIndexUsed;
         pasGCPList =
             GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
 
         if( oJP2Geo.bPixelIsPoint )
-            GDALDataset::SetMetadataItem(GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT);
+        {
+            m_bPixelIsPoint = true;
+            m_nPixelIsPointGeorefSrcIndex = nIndexUsed;
+        }
         if( oJP2Geo.papszRPCMD )
-            GDALDataset::SetMetadata( oJP2Geo.papszRPCMD, "RPC" );
+        {
+            m_papszRPC = CSLDuplicate( oJP2Geo.papszRPCMD );
+            m_nRPCGeorefSrcIndex = nIndexUsed;
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Report XML UUID box in a dedicated metadata domain              */
 /* -------------------------------------------------------------------- */
-    if (oJP2Geo.pszXMPMetadata)
+    if( oJP2Geo.pszXMPMetadata )
     {
-        char *apszMDList[2];
-        apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
-        apszMDList[1] = NULL;
+        char *apszMDList[2] = { oJP2Geo.pszXMPMetadata, NULL };
         GDALDataset::SetMetadata(apszMDList, "xml:XMP");
     }
 
@@ -124,23 +196,19 @@ void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
 /*      domain metadata? (Note: the GDAL multidomain metadata XML box   */
 /*      has been excluded and is dealt a few lines below.               */
 /* -------------------------------------------------------------------- */
-    int iBox;
 
-    for( iBox = 0;
-            oJP2Geo.papszGMLMetadata
-                && oJP2Geo.papszGMLMetadata[iBox] != NULL;
-            iBox++ )
+    for( int iBox = 0;
+         oJP2Geo.papszGMLMetadata
+             && oJP2Geo.papszGMLMetadata[iBox] != NULL;
+         ++iBox )
     {
         char *pszName = NULL;
         const char *pszXML =
             CPLParseNameValue( oJP2Geo.papszGMLMetadata[iBox],
                                 &pszName );
         CPLString osDomain;
-        char *apszMDList[2];
-
         osDomain.Printf( "xml:%s", pszName );
-        apszMDList[0] = (char *) pszXML;
-        apszMDList[1] = NULL;
+        char *apszMDList[2] = { const_cast<char *>(pszXML), NULL };
 
         GDALDataset::SetMetadata( apszMDList, osDomain );
 
@@ -152,7 +220,14 @@ void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
 /* -------------------------------------------------------------------- */
     if( oJP2Geo.pszGDALMultiDomainMetadata != NULL )
     {
-        CPLXMLNode* psXMLNode = CPLParseXMLString(oJP2Geo.pszGDALMultiDomainMetadata);
+        CPLErr eLastErr = CPLGetLastErrorType();
+        int nLastErrNo = CPLGetLastErrorNo();
+        CPLString osLastErrorMsg = CPLGetLastErrorMsg();
+        CPLXMLNode* psXMLNode =
+            CPLParseXMLString(oJP2Geo.pszGDALMultiDomainMetadata);
+        if( CPLGetLastErrorType() == CE_None && eLastErr != CE_None )
+            CPLErrorSetState( eLastErr, nLastErrNo, osLastErrorMsg.c_str() );
+
         if( psXMLNode )
         {
             GDALMultiDomainMetadata oLocalMDMD;
@@ -162,22 +237,28 @@ void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
             GDALDataset::SetMetadata(oLocalMDMD.GetMetadata());
             while( papszIter && *papszIter )
             {
-                if( !EQUAL(*papszIter, "") && !EQUAL(*papszIter, "IMAGE_STRUCTURE") )
+                if( !EQUAL(*papszIter, "") &&
+                    !EQUAL(*papszIter, "IMAGE_STRUCTURE") )
                 {
                     if( GDALDataset::GetMetadata(*papszIter) != NULL )
                     {
-                        CPLDebug("GDALJP2",
-                                 "GDAL metadata overrides metadata in %s domain over metadata read from other boxes",
-                                 *papszIter);
+                        CPLDebug(
+                            "GDALJP2",
+                            "GDAL metadata overrides metadata in %s domain "
+                            "over metadata read from other boxes",
+                            *papszIter );
                     }
-                    GDALDataset::SetMetadata(oLocalMDMD.GetMetadata(*papszIter), *papszIter);
+                    GDALDataset::SetMetadata(
+                        oLocalMDMD.GetMetadata(*papszIter), *papszIter );
                 }
-                papszIter ++;
+                ++papszIter;
             }
             CPLDestroyXMLNode(psXMLNode);
         }
         else
+        {
             CPLErrorReset();
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -198,15 +279,16 @@ void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
 /* -------------------------------------------------------------------- */
     if( oJP2Geo.pszXMLIPR != NULL )
     {
-        char* apszMD[2] = { NULL, NULL };
-        apszMD[0] = oJP2Geo.pszXMLIPR;
+        char* apszMD[2] = { oJP2Geo.pszXMLIPR, NULL };
         GDALDataset::SetMetadata( apszMD, "xml:IPR" );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Check for world file.                                           */
 /* -------------------------------------------------------------------- */
-    if( !bGeoTransformValid )
+    if( m_nWORLDFILEIndex >= 0 &&
+        ((bGeoTransformValid && m_nWORLDFILEIndex <
+                    m_nGeoTransformGeorefSrcIndex) || !bGeoTransformValid) )
     {
         bGeoTransformValid |=
             GDALReadWorldFile2( pszOverrideFilename, NULL,
@@ -214,12 +296,20 @@ void GDALJP2AbstractDataset::LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
                                 poOpenInfo->GetSiblingFiles(), &pszWldFilename )
             || GDALReadWorldFile2( pszOverrideFilename, ".wld",
                                    adfGeoTransform,
-                                   poOpenInfo->GetSiblingFiles(), &pszWldFilename );
+                                   poOpenInfo->GetSiblingFiles(),
+                                   &pszWldFilename );
+        if( bGeoTransformValid )
+        {
+            m_nGeoTransformGeorefSrcIndex = m_nWORLDFILEIndex;
+            m_bPixelIsPoint = false;
+            m_nPixelIsPointGeorefSrcIndex = -1;
+        }
     }
 
     GDALMDReaderManager mdreadermanager;
-    GDALMDReaderBase* mdreader = mdreadermanager.GetReader(poOpenInfo->pszFilename,
-                                poOpenInfo->GetSiblingFiles(), MDR_ANY);
+    GDALMDReaderBase* mdreader =
+        mdreadermanager.GetReader(poOpenInfo->pszFilename,
+                                  poOpenInfo->GetSiblingFiles(), MDR_ANY);
     if(NULL != mdreader)
     {
         mdreader->FillMetadata(&(oMDMD));
@@ -237,15 +327,22 @@ char **GDALJP2AbstractDataset::GetFileList()
     char **papszFileList = GDALGeorefPamDataset::GetFileList();
 
     if( pszWldFilename != NULL &&
+        m_nGeoTransformGeorefSrcIndex == m_nWORLDFILEIndex &&
         CSLFindString( papszFileList, pszWldFilename ) == -1 )
     {
-        papszFileList = CSLAddString( papszFileList, pszWldFilename );
+        double l_adfGeoTransform[6];
+        GetGeoTransform(l_adfGeoTransform);
+        if( m_nGeoTransformGeorefSrcIndex == m_nWORLDFILEIndex )
+        {
+            papszFileList = CSLAddString( papszFileList, pszWldFilename );
+        }
     }
-    if(NULL != papszMetadataFiles)
+    if( papszMetadataFiles != NULL )
     {
-        for( int i = 0; papszMetadataFiles[i] != NULL; i++ )
+        for( int i = 0; papszMetadataFiles[i] != NULL; ++i )
         {
-            papszFileList = CSLAddString( papszFileList, papszMetadataFiles[i] );
+            papszFileList =
+                CSLAddString( papszFileList, papszMetadataFiles[i] );
         }
     }
     return papszFileList;
@@ -255,29 +352,40 @@ char **GDALJP2AbstractDataset::GetFileList()
 /*                        LoadVectorLayers()                            */
 /************************************************************************/
 
-void GDALJP2AbstractDataset::LoadVectorLayers(int bOpenRemoteResources)
+void GDALJP2AbstractDataset::LoadVectorLayers( int bOpenRemoteResources )
 {
     char** papszGMLJP2 = GetMetadata("xml:gml.root-instance");
     if( papszGMLJP2 == NULL )
         return;
-    GDALDriver* poMemDriver = (GDALDriver*)GDALGetDriverByName("Memory");
+    GDALDriver * const poMemDriver =
+        static_cast<GDALDriver *>(GDALGetDriverByName("Memory"));
     if( poMemDriver == NULL )
         return;
-    CPLXMLNode* psRoot = CPLParseXMLString(papszGMLJP2[0]);
+
+    CPLErr eLastErr = CPLGetLastErrorType();
+    int nLastErrNo = CPLGetLastErrorNo();
+    CPLString osLastErrorMsg = CPLGetLastErrorMsg();
+    CPLXMLNode* const psRoot = CPLParseXMLString(papszGMLJP2[0]);
+    if( CPLGetLastErrorType() == CE_None && eLastErr != CE_None )
+        CPLErrorSetState( eLastErr, nLastErrNo, osLastErrorMsg.c_str() );
+
     if( psRoot == NULL )
         return;
-    CPLXMLNode* psCC = CPLGetXMLNode(psRoot, "=gmljp2:GMLJP2CoverageCollection");
+    CPLXMLNode* const psCC =
+        CPLGetXMLNode(psRoot, "=gmljp2:GMLJP2CoverageCollection");
     if( psCC == NULL )
     {
         CPLDestroyXMLNode(psRoot);
         return;
     }
 
-    // Find feature collections
-    CPLXMLNode* psCCChildIter = psCC->psChild;
+    // Find feature collections.
     int nLayersAtCC = 0;
     int nLayersAtGC = 0;
-    for( ; psCCChildIter != NULL; psCCChildIter = psCCChildIter->psNext )
+    // CPLXMLNode* psCCChildIter = psCC->psChild;
+    for( CPLXMLNode* psCCChildIter = psCC->psChild;
+         psCCChildIter != NULL;
+         psCCChildIter = psCCChildIter->psNext )
     {
         if( psCCChildIter->eType != CXT_Element ||
             strcmp(psCCChildIter->pszValue, "gmljp2:featureMember") != 0 ||
@@ -285,105 +393,132 @@ void GDALJP2AbstractDataset::LoadVectorLayers(int bOpenRemoteResources)
             psCCChildIter->psChild->eType != CXT_Element )
             continue;
 
-        CPLXMLNode* psGCorGMLJP2Features = psCCChildIter->psChild;
-        int bIsGC = ( strstr(psGCorGMLJP2Features->pszValue, "GridCoverage") != NULL );
+        CPLXMLNode * const psGCorGMLJP2Features = psCCChildIter->psChild;
+        bool bIsGC =
+            strstr(psGCorGMLJP2Features->pszValue, "GridCoverage") != NULL;
 
-        CPLXMLNode* psGCorGMLJP2FeaturesChildIter = psGCorGMLJP2Features->psChild;
-        for( ; psGCorGMLJP2FeaturesChildIter != NULL;
-               psGCorGMLJP2FeaturesChildIter = psGCorGMLJP2FeaturesChildIter->psNext )
+        for( CPLXMLNode *psGCorGMLJP2FeaturesChildIter =
+                 psGCorGMLJP2Features->psChild;
+             psGCorGMLJP2FeaturesChildIter != NULL;
+             psGCorGMLJP2FeaturesChildIter =
+                 psGCorGMLJP2FeaturesChildIter->psNext )
         {
             if( psGCorGMLJP2FeaturesChildIter->eType != CXT_Element ||
-                strcmp(psGCorGMLJP2FeaturesChildIter->pszValue, "gmljp2:feature") != 0 ||
+                strcmp(psGCorGMLJP2FeaturesChildIter->pszValue,
+                       "gmljp2:feature") != 0 ||
                 psGCorGMLJP2FeaturesChildIter->psChild == NULL )
                 continue;
 
             CPLXMLNode* psFC = NULL;
-            int bFreeFC = FALSE;
-            CPLString osGMLTmpFile;
+            bool bFreeFC = false;
 
-            CPLXMLNode* psChild = psGCorGMLJP2FeaturesChildIter->psChild;
+            CPLXMLNode * const psChild = psGCorGMLJP2FeaturesChildIter->psChild;
             if( psChild->eType == CXT_Attribute &&
                 strcmp(psChild->pszValue, "xlink:href") == 0 &&
                 STARTS_WITH(psChild->psChild->pszValue, "gmljp2://xml/") )
             {
-                const char* pszBoxName = psChild->psChild->pszValue + strlen("gmljp2://xml/");
-                char** papszBoxData = GetMetadata(CPLSPrintf("xml:%s", pszBoxName));
+                const char * const pszBoxName =
+                    psChild->psChild->pszValue + strlen("gmljp2://xml/");
+                char** papszBoxData =
+                    GetMetadata(CPLSPrintf("xml:%s", pszBoxName));
                 if( papszBoxData != NULL )
                 {
                     psFC = CPLParseXMLString(papszBoxData[0]);
-                    bFreeFC = TRUE;
+                    bFreeFC = true;
                 }
                 else
                 {
-                    CPLDebug("GMLJP2",
-                             "gmljp2:feature references %s, but no corresponding box found",
-                             psChild->psChild->pszValue);
+                    CPLDebug(
+                        "GMLJP2",
+                        "gmljp2:feature references %s, "
+                        "but no corresponding box found",
+                        psChild->psChild->pszValue);
                 }
             }
+
+            CPLString osGMLTmpFile;
             if( psChild->eType == CXT_Attribute &&
                 strcmp(psChild->pszValue, "xlink:href") == 0 &&
                 (STARTS_WITH(psChild->psChild->pszValue, "http://") ||
                  STARTS_WITH(psChild->psChild->pszValue, "https://")) )
             {
                 if( !bOpenRemoteResources )
-                    CPLDebug("GMLJP2",
-                             "Remote feature collection %s mentioned in "
-                             "GMLJP2 box",
-                             psChild->psChild->pszValue);
+                    CPLDebug(
+                        "GMLJP2",
+                        "Remote feature collection %s mentioned in GMLJP2 box",
+                        psChild->psChild->pszValue);
                 else
-                    osGMLTmpFile = "/vsicurl/" + CPLString(psChild->psChild->pszValue);
+                    osGMLTmpFile =
+                        "/vsicurl/" + CPLString(psChild->psChild->pszValue);
             }
             else if( psChild->eType == CXT_Element &&
                      strstr(psChild->pszValue, "FeatureCollection") != NULL )
             {
                 psFC = psChild;
             }
-            if( psFC == NULL && osGMLTmpFile.size() == 0 )
+
+            if( psFC == NULL && osGMLTmpFile.empty() )
+            {
                 continue;
+            }
 
             if( psFC != NULL )
             {
                 osGMLTmpFile = CPLSPrintf("/vsimem/gmljp2/%p/my.gml", this);
-                // Create temporary .gml file
+                // Create temporary .gml file.
                 CPLSerializeXMLTreeToFile(psFC, osGMLTmpFile);
             }
 
             CPLDebug("GMLJP2", "Found a FeatureCollection at %s level",
-                     (bIsGC) ? "GridCoverage" : "CoverageCollection");
+                     bIsGC ? "GridCoverage" : "CoverageCollection");
 
             CPLString osXSDTmpFile;
 
             if( psFC )
             {
                 // Try to localize its .xsd schema in a GMLJP2 auxiliary box
-                const char* pszSchemaLocation = CPLGetXMLValue(psFC, "xsi:schemaLocation", NULL);
+                const char * const pszSchemaLocation =
+                    CPLGetXMLValue(psFC, "xsi:schemaLocation", NULL);
                 if( pszSchemaLocation )
                 {
                     char **papszTokens = CSLTokenizeString2(
                             pszSchemaLocation, " \t\n",
-                            CSLT_HONOURSTRINGS | CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
+                            CSLT_HONOURSTRINGS | CSLT_STRIPLEADSPACES |
+                            CSLT_STRIPENDSPACES );
 
                     if( (CSLCount(papszTokens) % 2) == 0 )
                     {
-                        for(char** papszIter = papszTokens; *papszIter; papszIter += 2 )
+                        for( char** papszIter = papszTokens;
+                             *papszIter != NULL;
+                             papszIter += 2 )
                         {
                             if( STARTS_WITH(papszIter[1], "gmljp2://xml/") )
                             {
-                                const char* pszBoxName = papszIter[1] + strlen("gmljp2://xml/");
-                                char** papszBoxData = GetMetadata(CPLSPrintf("xml:%s", pszBoxName));
+                                const char* pszBoxName =
+                                    papszIter[1] + strlen("gmljp2://xml/");
+                                char** papszBoxData =
+                                    GetMetadata(CPLSPrintf("xml:%s",
+                                                           pszBoxName));
                                 if( papszBoxData != NULL )
                                 {
-                                    osXSDTmpFile = CPLSPrintf("/vsimem/gmljp2/%p/my.xsd", this);
-                                    CPL_IGNORE_RET_VAL(VSIFCloseL(VSIFileFromMemBuffer(osXSDTmpFile,
-                                                                    (GByte*)papszBoxData[0],
-                                                                    strlen(papszBoxData[0]),
-                                                                    FALSE)));
+                                    osXSDTmpFile =
+                                        CPLSPrintf("/vsimem/gmljp2/%p/my.xsd",
+                                                   this);
+                                    CPL_IGNORE_RET_VAL(VSIFCloseL(
+                                        VSIFileFromMemBuffer(
+                                            osXSDTmpFile,
+                                            reinterpret_cast<GByte *>(
+                                                papszBoxData[0]),
+                                            strlen(papszBoxData[0]),
+                                            FALSE)));
                                 }
                                 else
                                 {
-                                    CPLDebug("GMLJP2",
-                                            "Feature collection references %s, but no corresponding box found",
-                                            papszIter[1]);
+                                    CPLDebug(
+                                        "GMLJP2",
+                                        "Feature collection references %s, "
+                                        "but no corresponding box found",
+                                        papszIter[1] );
                                 }
                                 break;
                             }
@@ -402,97 +537,109 @@ void GDALJP2AbstractDataset::LoadVectorLayers(int bOpenRemoteResources)
             GDALDriverH hGMLDrv = GDALGetDriverByName("GML");
             if( hDrv != NULL && hDrv == hGMLDrv )
             {
-                char* apszOpenOptions[2];
-                apszOpenOptions[0] = (char*) "FORCE_SRS_DETECTION=YES";
-                apszOpenOptions[1] = NULL;
-                GDALDataset* poTmpDS = (GDALDataset*)GDALOpenEx( osGMLTmpFile,
-                                        GDAL_OF_VECTOR, NULL, apszOpenOptions, NULL );
+                char* apszOpenOptions[2] = {
+                    const_cast<char *>( "FORCE_SRS_DETECTION=YES" ), NULL };
+                GDALDataset* poTmpDS = static_cast<GDALDataset *>(
+                    GDALOpenEx( osGMLTmpFile, GDAL_OF_VECTOR, NULL,
+                                apszOpenOptions, NULL ) );
                 if( poTmpDS )
                 {
                     int nLayers = poTmpDS->GetLayerCount();
-                    for(int i=0;i<nLayers;i++)
+                    for( int i = 0; i < nLayers; ++i )
                     {
                         if( poMemDS == NULL )
-                            poMemDS = poMemDriver->Create("", 0, 0, 0, GDT_Unknown, NULL);
+                            poMemDS =
+                                poMemDriver->Create("", 0, 0, 0,
+                                                    GDT_Unknown, NULL);
                         OGRLayer* poSrcLyr = poTmpDS->GetLayer(i);
-                        const char* pszLayerName;
-                        if( bIsGC )
-                            pszLayerName = CPLSPrintf("FC_GridCoverage_%d_%s",
-                                                    ++nLayersAtGC, poSrcLyr->GetName());
-                        else
-                            pszLayerName = CPLSPrintf("FC_CoverageCollection_%d_%s",
-                                                    ++nLayersAtCC, poSrcLyr->GetName());
+                        const char* const pszLayerName = bIsGC ?
+                            CPLSPrintf("FC_GridCoverage_%d_%s",
+                                       ++nLayersAtGC, poSrcLyr->GetName()) :
+                            CPLSPrintf("FC_CoverageCollection_%d_%s",
+                                       ++nLayersAtCC, poSrcLyr->GetName());
                         poMemDS->CopyLayer(poSrcLyr, pszLayerName, NULL);
                     }
                     GDALClose(poTmpDS);
 
-                    // In case we don't have a schema, a .gfs might have been generated
+                    // If there was no schema, a .gfs might have been generated.
                     VSIUnlink(CPLSPrintf("/vsimem/gmljp2/%p/my.gfs", this));
                 }
             }
             else
             {
-                CPLDebug("GMLJP2", "No GML driver found to read feature collection");
+                CPLDebug(
+                    "GMLJP2",
+                    "No GML driver found to read feature collection" );
             }
 
             if( !STARTS_WITH(osGMLTmpFile, "/vsicurl/") )
                 VSIUnlink(osGMLTmpFile);
-            if( osXSDTmpFile.size() )
+            if( !osXSDTmpFile.empty() )
                 VSIUnlink(osXSDTmpFile);
         }
     }
 
     // Find annotations
-    psCCChildIter = psCC->psChild;
     int nAnnotations = 0;
-    for( ; psCCChildIter != NULL; psCCChildIter = psCCChildIter->psNext )
+    for( CPLXMLNode* psCCChildIter = psCC->psChild;
+         psCCChildIter != NULL;
+         psCCChildIter = psCCChildIter->psNext )
     {
         if( psCCChildIter->eType != CXT_Element ||
             strcmp(psCCChildIter->pszValue, "gmljp2:featureMember") != 0 ||
             psCCChildIter->psChild == NULL ||
             psCCChildIter->psChild->eType != CXT_Element )
             continue;
-        CPLXMLNode* psGCorGMLJP2Features = psCCChildIter->psChild;
-        int bIsGC = ( strstr(psGCorGMLJP2Features->pszValue, "GridCoverage") != NULL );
+        CPLXMLNode * const psGCorGMLJP2Features = psCCChildIter->psChild;
+        bool bIsGC =
+            strstr(psGCorGMLJP2Features->pszValue, "GridCoverage") != NULL;
         if( !bIsGC )
             continue;
-        CPLXMLNode* psGCorGMLJP2FeaturesChildIter = psGCorGMLJP2Features->psChild;
-        for( ; psGCorGMLJP2FeaturesChildIter != NULL;
-               psGCorGMLJP2FeaturesChildIter = psGCorGMLJP2FeaturesChildIter->psNext )
+        for( CPLXMLNode* psGCorGMLJP2FeaturesChildIter =
+                 psGCorGMLJP2Features->psChild;
+             psGCorGMLJP2FeaturesChildIter != NULL;
+             psGCorGMLJP2FeaturesChildIter =
+                 psGCorGMLJP2FeaturesChildIter->psNext )
         {
             if( psGCorGMLJP2FeaturesChildIter->eType != CXT_Element ||
-                strcmp(psGCorGMLJP2FeaturesChildIter->pszValue, "gmljp2:annotation") != 0 ||
+                strcmp(psGCorGMLJP2FeaturesChildIter->pszValue,
+                       "gmljp2:annotation") != 0 ||
                 psGCorGMLJP2FeaturesChildIter->psChild == NULL ||
                 psGCorGMLJP2FeaturesChildIter->psChild->eType != CXT_Element ||
-                strstr(psGCorGMLJP2FeaturesChildIter->psChild->pszValue, "kml") == NULL )
+                strstr(psGCorGMLJP2FeaturesChildIter->psChild->pszValue,
+                       "kml") == NULL )
                 continue;
+
             CPLDebug("GMLJP2", "Found a KML annotation");
 
-            // Create temporary .kml file
-            CPLXMLNode* psKML = psGCorGMLJP2FeaturesChildIter->psChild;
-            CPLString osKMLTmpFile(CPLSPrintf("/vsimem/gmljp2/%p/my.kml", this));
+            // Create temporary .kml file.
+            CPLXMLNode* const psKML = psGCorGMLJP2FeaturesChildIter->psChild;
+            CPLString osKMLTmpFile(
+                CPLSPrintf("/vsimem/gmljp2/%p/my.kml", this) );
             CPLSerializeXMLTreeToFile(psKML, osKMLTmpFile);
 
-            GDALDataset* poTmpDS = (GDALDataset*)GDALOpenEx( osKMLTmpFile,
-                                    GDAL_OF_VECTOR, NULL, NULL, NULL );
+            GDALDataset * const poTmpDS = static_cast<GDALDataset *>(
+                GDALOpenEx( osKMLTmpFile, GDAL_OF_VECTOR, NULL, NULL, NULL ) );
             if( poTmpDS )
             {
                 int nLayers = poTmpDS->GetLayerCount();
-                for(int i=0;i<nLayers;i++)
+                for( int i = 0; i < nLayers; ++i )
                 {
                     if( poMemDS == NULL )
-                        poMemDS = poMemDriver->Create("", 0, 0, 0, GDT_Unknown, NULL);
-                    OGRLayer* poSrcLyr = poTmpDS->GetLayer(i);
-                    const char* pszLayerName;
-                    pszLayerName = CPLSPrintf("Annotation_%d_%s",
-                                                ++nAnnotations, poSrcLyr->GetName());
+                        poMemDS =
+                            poMemDriver->Create("", 0, 0, 0, GDT_Unknown, NULL);
+                    OGRLayer* const poSrcLyr = poTmpDS->GetLayer(i);
+                    const char* pszLayerName =
+                        CPLSPrintf("Annotation_%d_%s",
+                                   ++nAnnotations, poSrcLyr->GetName());
                     poMemDS->CopyLayer(poSrcLyr, pszLayerName, NULL);
                 }
                 GDALClose(poTmpDS);
             }
             else
             {
-                CPLDebug("GMLJP2", "No KML/LIBKML driver found to read annotation");
+                CPLDebug(
+                    "GMLJP2", "No KML/LIBKML driver found to read annotation" );
             }
 
             VSIUnlink(osKMLTmpFile);
@@ -508,14 +655,16 @@ void GDALJP2AbstractDataset::LoadVectorLayers(int bOpenRemoteResources)
 
 int GDALJP2AbstractDataset::GetLayerCount()
 {
-    return (poMemDS != NULL) ? poMemDS->GetLayerCount() : 0;
+    return poMemDS != NULL ? poMemDS->GetLayerCount() : 0;
 }
 
 /************************************************************************/
 /*                             GetLayer()                               */
 /************************************************************************/
 
-OGRLayer* GDALJP2AbstractDataset::GetLayer(int i)
+OGRLayer* GDALJP2AbstractDataset::GetLayer( int i )
 {
-    return (poMemDS != NULL) ? poMemDS->GetLayer(i) : NULL;
+    return poMemDS != NULL ? poMemDS->GetLayer(i) : NULL;
 }
+
+/*! @endcond */
diff --git a/gcore/gdaljp2abstractdataset.h b/gcore/gdaljp2abstractdataset.h
index aea9600..224c62c 100644
--- a/gcore/gdaljp2abstractdataset.h
+++ b/gcore/gdaljp2abstractdataset.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2abstractdataset.h 33794 2016-03-26 13:19:07Z goatbar $
+ * $Id: gdaljp2abstractdataset.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL
  * Purpose:  GDALGeorefPamDataset with helper to read georeferencing and other
@@ -31,6 +31,7 @@
 #ifndef GDAL_JP2_ABSTRACT_DATASET_H_INCLUDED
 #define GDAL_JP2_ABSTRACT_DATASET_H_INCLUDED
 
+//! @cond Doxygen_Suppress
 #include "gdalgeorefpamdataset.h"
 
 class CPL_DLL GDALJP2AbstractDataset: public GDALGeorefPamDataset
@@ -39,22 +40,24 @@ class CPL_DLL GDALJP2AbstractDataset: public GDALGeorefPamDataset
 
     GDALDataset*        poMemDS;
     char**              papszMetadataFiles;
+    int                 m_nWORLDFILEIndex;
 
   protected:
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() CPL_OVERRIDE;
 
   public:
         GDALJP2AbstractDataset();
         virtual ~GDALJP2AbstractDataset();
 
-        void LoadJP2Metadata(GDALOpenInfo* poOpenInfo,
-                             const char* pszOverrideFilename = NULL);
-        void            LoadVectorLayers(int bOpenRemoteResources = FALSE);
+        void LoadJP2Metadata( GDALOpenInfo* poOpenInfo,
+                              const char* pszOverrideFilename = NULL );
+        void            LoadVectorLayers( int bOpenRemoteResources = FALSE );
 
-        virtual char      **GetFileList(void);
+        virtual char      **GetFileList( void ) CPL_OVERRIDE;
 
-        virtual int         GetLayerCount();
-        virtual OGRLayer   *GetLayer(int i);
+        virtual int         GetLayerCount() CPL_OVERRIDE;
+        virtual OGRLayer   *GetLayer( int i ) CPL_OVERRIDE;
 };
+//! @endcond
 
 #endif /* GDAL_JP2_ABSTRACT_DATASET_H_INCLUDED */
diff --git a/gcore/gdaljp2box.cpp b/gcore/gdaljp2box.cpp
index 3fb9d68..916567f 100644
--- a/gcore/gdaljp2box.cpp
+++ b/gcore/gdaljp2box.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaljp2box.cpp 33550 2016-02-25 12:47:15Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  GDALJP2Box Implementation - Low level JP2 box reader.
@@ -28,10 +27,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h"
+#include "cpl_port.h"
 #include "gdaljp2metadata.h"
 
-CPL_CVSID("$Id: gdaljp2box.cpp 33550 2016-02-25 12:47:15Z goatbar $");
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+
+CPL_CVSID("$Id: gdaljp2box.cpp 36822 2016-12-12 11:18:45Z rouault $");
+
+/*! @cond Doxygen_Suppress */
 
 /************************************************************************/
 /*                             GDALJP2Box()                             */
@@ -39,12 +54,17 @@ CPL_CVSID("$Id: gdaljp2box.cpp 33550 2016-02-25 12:47:15Z goatbar $");
 
 GDALJP2Box::GDALJP2Box( VSILFILE *fpIn ) :
     fpVSIL(fpIn),
+#if HAVE_CXX11
+    szBoxType{'\0', '\0', '\0', '\0', '\0'},
+#endif
     nBoxOffset(-1),
     nBoxLength(0),
     nDataOffset(-1),
     pabyData(NULL)
 {
-    szBoxType[0] = '\0';
+#if !HAVE_CXX11
+    std::fill_n(szBoxType, CPL_ARRAYSIZE(szBoxType), '\0');
+#endif
 }
 
 /************************************************************************/
@@ -162,16 +182,21 @@ int GDALJP2Box::ReadBox()
         if( VSIFReadL( abyXLBox, 8, 1, fpVSIL ) != 1 )
             return FALSE;
 
-        if( sizeof(nBoxLength) == 8 )
-        {
-            CPL_MSBPTR64( abyXLBox );
-            memcpy( &nBoxLength, abyXLBox, 8 );
-        }
-        else
+#ifdef CPL_HAS_GINT64
+        CPL_MSBPTR64( abyXLBox );
+        memcpy( &nBoxLength, abyXLBox, 8 );
+#else
+        // In case we lack a 64 bit integer type
+        if( abyXLBox[0] != 0 || abyXLBox[1] != 0 || abyXLBox[2] != 0 ||
+            abyXLBox[3] != 0 )
         {
-            CPL_MSBPTR32( abyXLBox+4 );
-            memcpy( &nBoxLength, abyXLBox+4, 4 );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                        "Box size requires a 64 bit integer type");
+            return FALSE;
         }
+        CPL_MSBPTR32( abyXLBox+4 );
+        memcpy( &nBoxLength, abyXLBox+4, 4 );
+#endif
         if( nBoxLength < 0 )
         {
             CPLDebug("GDALJP2", "Invalid length for box %s", szBoxType);
@@ -276,14 +301,16 @@ int GDALJP2Box::DumpReadable( FILE *fpOut, int nIndentLevel )
     if( fpOut == NULL )
         fpOut = stdout;
 
-    for( int i=0; i < nIndentLevel; i++)
+    for( int i=0; i < nIndentLevel; ++i)
         fprintf( fpOut, "  " );
 
-    fprintf( fpOut,
+    char szBuffer[128];
+    CPLsnprintf( szBuffer, sizeof(szBuffer),
              "  Type=%s, Offset=" CPL_FRMT_GIB "/" CPL_FRMT_GIB
              ", Data Size=" CPL_FRMT_GIB,
              szBoxType, nBoxOffset, nDataOffset,
              GetDataLength() );
+    fprintf( fpOut, "%s", szBuffer );
 
     if( IsSuperBox() )
     {
@@ -307,7 +334,7 @@ int GDALJP2Box::DumpReadable( FILE *fpOut, int nIndentLevel )
     if( EQUAL(GetType(),"uuid") )
     {
         char *pszHex = CPLBinaryToHex( 16, GetUUID() );
-        for( int i=0; i < nIndentLevel; i++ )
+        for( int i = 0; i < nIndentLevel; ++i )
             fprintf( fpOut, "  " );
 
         fprintf( fpOut, "    UUID=%s", pszHex );
@@ -348,10 +375,10 @@ void GDALJP2Box::SetWritableData( int nLength, const GByte *pabyDataIn )
 {
     CPLFree( pabyData );
 
-    pabyData = (GByte *) CPLMalloc(nLength);
+    pabyData = static_cast<GByte *>( CPLMalloc(nLength) );
     memcpy( pabyData, pabyDataIn, nLength );
 
-    nBoxOffset = -9; // virtual offsets for data length computation.
+    nBoxOffset = -9; // Virtual offsets for data length computation.
     nDataOffset = -1;
 
     nBoxLength = 8 + nLength;
@@ -366,7 +393,7 @@ void GDALJP2Box::AppendWritableData( int nLength, const void *pabyDataIn )
 {
     if( pabyData == NULL )
     {
-        nBoxOffset = -9; // virtual offsets for data length computation.
+        nBoxOffset = -9; // Virtual offsets for data length computation.
         nDataOffset = -1;
         nBoxLength = 8;
     }
@@ -414,7 +441,7 @@ GDALJP2Box *GDALJP2Box::CreateUUIDBox(
     const GByte *pabyUUID, int nDataSize, const GByte *pabyDataIn )
 
 {
-    GDALJP2Box *poBox = new GDALJP2Box();
+    GDALJP2Box * const poBox = new GDALJP2Box();
     poBox->SetType( "uuid" );
 
     poBox->AppendWritableData( 16, pabyUUID );
@@ -432,7 +459,6 @@ GDALJP2Box *GDALJP2Box::CreateAsocBox( int nCount, GDALJP2Box **papoBoxes )
     return CreateSuperBox("asoc", nCount, papoBoxes);
 }
 
-
 /************************************************************************/
 /*                           CreateAsocBox()                            */
 /************************************************************************/
@@ -440,12 +466,12 @@ GDALJP2Box *GDALJP2Box::CreateAsocBox( int nCount, GDALJP2Box **papoBoxes )
 GDALJP2Box *GDALJP2Box::CreateSuperBox( const char* pszType,
                                         int nCount, GDALJP2Box **papoBoxes )
 {
-    int nDataSize=0;
+    int nDataSize = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Compute size of data area of asoc box.                          */
 /* -------------------------------------------------------------------- */
-    for( int iBox = 0; iBox < nCount; iBox++ )
+    for( int iBox = 0; iBox < nCount; ++iBox )
         nDataSize += 8 + static_cast<int>( papoBoxes[iBox]->GetDataLength() );
 
     GByte *pabyNext = static_cast<GByte *>( CPLMalloc(nDataSize) );
@@ -454,9 +480,9 @@ GDALJP2Box *GDALJP2Box::CreateSuperBox( const char* pszType,
 /* -------------------------------------------------------------------- */
 /*      Copy subboxes headers and data into buffer.                     */
 /* -------------------------------------------------------------------- */
-    for( int iBox = 0; iBox < nCount; iBox++ )
+    for( int iBox = 0; iBox < nCount; ++iBox )
     {
-        GUInt32   nLBox = CPL_MSBWORD32(
+        GUInt32 nLBox = CPL_MSBWORD32(
             static_cast<GUInt32>(papoBoxes[iBox]->nBoxLength));
         memcpy( pabyNext, &nLBox, 4 );
         pabyNext += 4;
@@ -465,14 +491,14 @@ GDALJP2Box *GDALJP2Box::CreateSuperBox( const char* pszType,
         pabyNext += 4;
 
         memcpy( pabyNext, papoBoxes[iBox]->pabyData,
-                (int) papoBoxes[iBox]->GetDataLength() );
+                static_cast<int>(papoBoxes[iBox]->GetDataLength()) );
         pabyNext += papoBoxes[iBox]->GetDataLength();
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create asoc box.                                                */
 /* -------------------------------------------------------------------- */
-    GDALJP2Box *poAsoc = new GDALJP2Box();
+    GDALJP2Box * const poAsoc = new GDALJP2Box();
 
     poAsoc->SetType( pszType );
     poAsoc->SetWritableData( nDataSize, pabyCompositeData );
@@ -489,7 +515,7 @@ GDALJP2Box *GDALJP2Box::CreateSuperBox( const char* pszType,
 GDALJP2Box *GDALJP2Box::CreateLblBox( const char *pszLabel )
 
 {
-    GDALJP2Box *poBox = new GDALJP2Box();
+    GDALJP2Box * const poBox = new GDALJP2Box();
     poBox->SetType( "lbl " );
     poBox->SetWritableData( static_cast<int>(strlen(pszLabel)+1),
                             reinterpret_cast<const GByte *>( pszLabel ) );
@@ -519,3 +545,5 @@ GDALJP2Box *GDALJP2Box::CreateLabelledXMLAssoc( const char *pszLabel,
 
     return CreateAsocBox( 2, aoList );
 }
+
+/*! @endcond */
diff --git a/gcore/gdaljp2metadata.cpp b/gcore/gdaljp2metadata.cpp
index adcff7a..0616280 100644
--- a/gcore/gdaljp2metadata.cpp
+++ b/gcore/gdaljp2metadata.cpp
@@ -1,5 +1,5 @@
+
 /******************************************************************************
- * $Id: gdaljp2metadata.cpp 33579 2016-02-26 23:55:40Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  GDALJP2Metadata - Read GeoTIFF and/or GML georef info.
@@ -30,17 +30,38 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdaljp2metadata.h"
+#include "gdaljp2metadatagenerator.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "cpl_error.h"
 #include "cpl_string.h"
 #include "cpl_minixml.h"
-#include "gt_wkt_srs_for_gdal.h"
-#include "gdaljp2metadata.h"
 #include "gdaljp2metadatagenerator.h"
-#include "json.h"
+#include "gt_wkt_srs_for_gdal.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
 #include "ogr_spatialref.h"
+#include "ogrgeojsonreader.h"
+
+/*! @cond Doxygen_Suppress */
 
-CPL_CVSID("$Id: gdaljp2metadata.cpp 33579 2016-02-26 23:55:40Z goatbar $");
+CPL_CVSID("$Id: gdaljp2metadata.cpp 37110 2017-01-12 10:36:04Z rouault $");
 
 static const unsigned char msi_uuid2[16] = {
     0xb1,0x4b,0xf8,0xbd,0x08,0x3d,0x4b,0x43,
@@ -72,8 +93,11 @@ GDALJP2Metadata::GDALJP2Metadata() :
     nMSIGSize(0),
     pabyMSIGData(NULL),
     papszGMLMetadata(NULL),
-    bHaveGeoTransform (FALSE),
-    bPixelIsPoint(FALSE),
+    bHaveGeoTransform(false),
+#if HAVE_CXX11
+    adfGeoTransform{0.0, 1.0, 0.0, 0.0, 0.0, 1.0},
+#endif
+    bPixelIsPoint(false),
     pszProjection(NULL),
     nGCPCount(0),
     pasGCPList(NULL),
@@ -83,12 +107,14 @@ GDALJP2Metadata::GDALJP2Metadata() :
     pszGDALMultiDomainMetadata(NULL),
     pszXMLIPR(NULL)
 {
+#if !HAVE_CXX11
     adfGeoTransform[0] = 0.0;
     adfGeoTransform[1] = 1.0;
     adfGeoTransform[2] = 0.0;
     adfGeoTransform[3] = 0.0;
     adfGeoTransform[4] = 0.0;
     adfGeoTransform[5] = 1.0;
+#endif
 }
 
 /************************************************************************/
@@ -106,7 +132,7 @@ GDALJP2Metadata::~GDALJP2Metadata()
     }
     CSLDestroy(papszRPCMD);
 
-    for( int i=0; i < nGeoTIFFBoxesCount; i++ )
+    for( int i = 0; i < nGeoTIFFBoxesCount; ++i )
     {
         CPLFree( pasGeoTIFFBoxes[i].pabyGeoTIFFData );
     }
@@ -127,13 +153,12 @@ GDALJP2Metadata::~GDALJP2Metadata()
 /*      if anything useful is found.                                    */
 /************************************************************************/
 
-int GDALJP2Metadata::ReadAndParse( const char *pszFilename )
+int GDALJP2Metadata::ReadAndParse( const char *pszFilename, int nGEOJP2Index,
+                                   int nGMLJP2Index, int nMSIGIndex,
+                                   int nWorldFileIndex, int *pnIndexUsed  )
 
 {
-    VSILFILE *fpLL;
-
-    fpLL = VSIFOpenL( pszFilename, "rb" );
-
+    VSILFILE *fpLL = VSIFOpenL( pszFilename, "rb" );
     if( fpLL == NULL )
     {
         CPLDebug( "GDALJP2Metadata", "Could not even open %s.",
@@ -142,35 +167,58 @@ int GDALJP2Metadata::ReadAndParse( const char *pszFilename )
         return FALSE;
     }
 
-    int bRet = ReadAndParse( fpLL );
+    int nIndexUsed = -1;
+    bool bRet = CPL_TO_BOOL(ReadAndParse( fpLL, nGEOJP2Index, nGMLJP2Index,
+                                          nMSIGIndex, &nIndexUsed ));
     CPL_IGNORE_RET_VAL(VSIFCloseL( fpLL ));
 
 /* -------------------------------------------------------------------- */
 /*      If we still don't have a geotransform, look for a world         */
 /*      file.                                                           */
 /* -------------------------------------------------------------------- */
-    if( !bHaveGeoTransform )
+    if( nWorldFileIndex >= 0 &&
+        ((bHaveGeoTransform && nWorldFileIndex < nIndexUsed) ||
+         !bHaveGeoTransform) )
     {
-        bHaveGeoTransform =
+        bHaveGeoTransform = CPL_TO_BOOL(
             GDALReadWorldFile( pszFilename, NULL, adfGeoTransform )
-            || GDALReadWorldFile( pszFilename, ".wld", adfGeoTransform );
+            || GDALReadWorldFile( pszFilename, ".wld", adfGeoTransform ) );
         bRet |= bHaveGeoTransform;
     }
 
+    if( pnIndexUsed )
+        *pnIndexUsed = nIndexUsed;
+
     return bRet;
 }
 
-
-int GDALJP2Metadata::ReadAndParse( VSILFILE *fpLL )
+int GDALJP2Metadata::ReadAndParse( VSILFILE *fpLL, int nGEOJP2Index,
+                                   int nGMLJP2Index, int nMSIGIndex,
+                                   int *pnIndexUsed )
 
 {
     ReadBoxes( fpLL );
 
 /* -------------------------------------------------------------------- */
-/*      Try JP2GeoTIFF, GML and finally MSIG to get something.          */
+/*      Try JP2GeoTIFF, GML and finally MSIG in specified order.        */
 /* -------------------------------------------------------------------- */
-    if( !ParseJP2GeoTIFF() && !ParseGMLCoverageDesc() )
-        ParseMSIG();
+    std::set<int> aoSetPriorities;
+    if( nGEOJP2Index >= 0 ) aoSetPriorities.insert(nGEOJP2Index);
+    if( nGMLJP2Index >= 0 ) aoSetPriorities.insert(nGMLJP2Index);
+    if( nMSIGIndex >= 0 ) aoSetPriorities.insert(nMSIGIndex);
+    std::set<int>::iterator oIter = aoSetPriorities.begin();
+    for( ; oIter != aoSetPriorities.end(); ++oIter )
+    {
+        int nIndex = *oIter;
+        if( (nIndex == nGEOJP2Index && ParseJP2GeoTIFF()) ||
+            (nIndex == nGMLJP2Index && ParseGMLCoverageDesc()) ||
+            (nIndex == nMSIGIndex && ParseMSIG() ) )
+        {
+            if( pnIndexUsed )
+                *pnIndexUsed = nIndex;
+            break;
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Return success either either of projection or geotransform      */
@@ -203,36 +251,38 @@ void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
         {
             GDALJP2Box oSubChildBox( oChildBox.GetFILE() );
 
-            char *pszLabel = NULL;
-            char *pszXML = NULL;
-
             if( !oSubChildBox.ReadFirstChild( &oChildBox ) )
                 break;
 
+            char *pszLabel = NULL;
+            char *pszXML = NULL;
+
             while( strlen(oSubChildBox.GetType()) > 0 )
             {
                 if( EQUAL(oSubChildBox.GetType(),"lbl ") )
                     pszLabel = (char *)oSubChildBox.ReadBoxData();
                 else if( EQUAL(oSubChildBox.GetType(),"xml ") )
                 {
-                    pszXML = (char *) oSubChildBox.ReadBoxData();
+                    pszXML =
+                        reinterpret_cast<char *>( oSubChildBox.ReadBoxData() );
                     GIntBig nXMLLength = oSubChildBox.GetDataLength();
 
-                    // Some GML data contains \0 instead of \n !
+                    // Some GML data contains \0 instead of \n.
                     // See http://trac.osgeo.org/gdal/ticket/5760
+                    // TODO(schwehr): Explain the numbers in the next line.
                     if( pszXML != NULL && nXMLLength < 100 * 1024 * 1024 )
                     {
-                        GIntBig i;
-                        /* coverity[tainted_data] */
-                        for(i=nXMLLength-1; i >= 0; i--)
+                        // coverity[tainted_data].
+                        for( GIntBig i = nXMLLength - 1; i >= 0; --i )
                         {
                             if( pszXML[i] == '\0' )
-                                nXMLLength --;
+                                --nXMLLength;
                             else
                                 break;
                         }
-                        /* coverity[tainted_data] */
-                        for(i=0;i<nXMLLength;i++)
+                        // coverity[tainted_data]
+                        GIntBig i = 0;  // Used after for.
+                        for( ; i < nXMLLength; ++i )
                         {
                             if( pszXML[i] == '\0' )
                                 break;
@@ -244,16 +294,21 @@ void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
                             CPLPopErrorHandler();
                             if( psNode == NULL )
                             {
-                                CPLDebug("GMLJP2", "GMLJP2 data contains nul characters inside content. Replacing them by \\n");
-                                /* coverity[tainted_data] */
-                                for(i=0;i<nXMLLength;i++)
+                                CPLDebug(
+                                    "GMLJP2",
+                                    "GMLJP2 data contains nul characters "
+                                    "inside content. Replacing them by \\n");
+                                // coverity[tainted_data]
+                                for( GIntBig j = 0; j < nXMLLength; ++j )
                                 {
-                                    if( pszXML[i] == '\0' )
-                                        pszXML[i] = '\n';
+                                    if( pszXML[j] == '\0' )
+                                        pszXML[j] = '\n';
                                 }
                             }
                             else
+                            {
                                 CPLDestroyXMLNode(psNode);
+                            }
                         }
                     }
                 }
@@ -274,9 +329,11 @@ void GDALJP2Metadata::CollectGMLData( GDALJP2Box *poGMLData )
                     CPLXMLNode* psTree = CPLParseXMLString(pszXML);
                     if( psTree != NULL )
                     {
-                        CPLXMLNode* psGDALMDMD = CPLSearchXMLNode(psTree, "GDALMultiDomainMetadata");
+                        CPLXMLNode* psGDALMDMD =
+                            CPLSearchXMLNode(psTree, "GDALMultiDomainMetadata");
                         if( psGDALMDMD )
-                            pszGDALMultiDomainMetadata = CPLSerializeXMLTree(psGDALMDMD);
+                            pszGDALMultiDomainMetadata =
+                                CPLSerializeXMLTree(psGDALMDMD);
                     }
                     CPLDestroyXMLNode(psTree);
                 }
@@ -299,11 +356,11 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
 
 {
     GDALJP2Box oBox( fpVSIL );
-    int iBox = 0;
 
     if (!oBox.ReadFirst())
         return FALSE;
 
+    int iBox = 0;
     while( strlen(oBox.GetType()) > 0 )
     {
 #ifdef DEBUG
@@ -317,29 +374,36 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
         if( EQUAL(oBox.GetType(),"uuid")
             && memcmp( oBox.GetUUID(), msi_uuid2, 16 ) == 0 )
         {
-            /* Erdas JPEG2000 files can in some conditions contain 2 GeoTIFF */
-            /* UUID boxes. One that is correct, another one that does not contain */
-            /* correct georeferencing. So let's fetch at most 2 of them */
-            /* for later analysis. */
+            // Erdas JPEG2000 files sometimes contain 2 GeoTIFF UUID boxes. One
+            // that is correct, another one that does not contain correct
+            // georeferencing. Fetch at most 2 of them for later analysis.
             if( nGeoTIFFBoxesCount == MAX_JP2GEOTIFF_BOXES )
             {
-                CPLDebug("GDALJP2", "Too many UUID GeoTIFF boxes. Ignoring this one");
+                CPLDebug( "GDALJP2",
+                          "Too many UUID GeoTIFF boxes. Ignoring this one" );
             }
             else
             {
-                int nGeoTIFFSize = (int) oBox.GetDataLength();
+                const int nGeoTIFFSize =
+                    static_cast<int>( oBox.GetDataLength() );
                 GByte* pabyGeoTIFFData = oBox.ReadBoxData();
-                if (pabyGeoTIFFData == NULL)
+                if( pabyGeoTIFFData == NULL )
                 {
-                    CPLDebug("GDALJP2", "Cannot read data for UUID GeoTIFF box");
+                    CPLDebug( "GDALJP2",
+                              "Cannot read data for UUID GeoTIFF box" );
                 }
                 else
                 {
-                    pasGeoTIFFBoxes = (GDALJP2GeoTIFFBox*) CPLRealloc(
-                        pasGeoTIFFBoxes, sizeof(GDALJP2GeoTIFFBox) * (nGeoTIFFBoxesCount + 1) );
-                    pasGeoTIFFBoxes[nGeoTIFFBoxesCount].nGeoTIFFSize = nGeoTIFFSize;
-                    pasGeoTIFFBoxes[nGeoTIFFBoxesCount].pabyGeoTIFFData = pabyGeoTIFFData;
-                    nGeoTIFFBoxesCount ++;
+                    pasGeoTIFFBoxes = static_cast<GDALJP2GeoTIFFBox *>(
+                        CPLRealloc(
+                            pasGeoTIFFBoxes,
+                            sizeof(GDALJP2GeoTIFFBox) *
+                                (nGeoTIFFBoxesCount + 1) ) );
+                    pasGeoTIFFBoxes[nGeoTIFFBoxesCount].nGeoTIFFSize =
+                        nGeoTIFFSize;
+                    pasGeoTIFFBoxes[nGeoTIFFBoxesCount].pabyGeoTIFFData =
+                        pabyGeoTIFFData;
+                    ++nGeoTIFFBoxesCount;
                 }
             }
         }
@@ -352,7 +416,7 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
         {
             if( nMSIGSize == 0 )
             {
-                nMSIGSize = (int) oBox.GetDataLength();
+                nMSIGSize = static_cast<int>( oBox.GetDataLength() );
                 pabyMSIGData = oBox.ReadBoxData();
 
                 if( nMSIGSize < 70
@@ -413,7 +477,8 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
             CPLString osBoxName;
 
             char *pszXML = (char *) oBox.ReadBoxData();
-            if( pszXML != NULL && STARTS_WITH(pszXML, "<GDALMultiDomainMetadata>") )
+            if( pszXML != NULL &&
+                STARTS_WITH(pszXML, "<GDALMultiDomainMetadata>") )
             {
                 if( pszGDALMultiDomainMetadata == NULL )
                 {
@@ -422,7 +487,9 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
                 }
                 else
                 {
-                    CPLDebug("GDALJP2", "Too many GDAL metadata boxes. Ignoring this one");
+                    CPLDebug(
+                        "GDALJP2",
+                        "Too many GDAL metadata boxes. Ignoring this one");
                 }
             }
             else if( pszXML != NULL )
@@ -469,10 +536,12 @@ int GDALJP2Metadata::ReadBoxes( VSILFILE *fpVSIL )
                         nHorzExp = pabyResData[9];
 
                         // compute in pixels/cm
-                        double dfVertRes =
-                            (nVertNum/(double)nVertDen) * pow(10.0,nVertExp)/100;
-                        double dfHorzRes =
-                            (nHorzNum/(double)nHorzDen) * pow(10.0,nHorzExp)/100;
+                        const double dfVertRes =
+                            (nVertNum / static_cast<double>(nVertDen)) *
+                            pow(10.0, nVertExp) / 100;
+                        const double dfHorzRes =
+                            (nHorzNum / static_cast<double>(nHorzDen)) *
+                            pow(10.0,nHorzExp)/100;
                         CPLString osFormatter;
 
                         papszMetadata = CSLSetNameValue(
@@ -543,9 +612,8 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
     int abPixelIsPoint[MAX_JP2GEOTIFF_BOXES] = { 0 };
     char** apapszRPCMD[MAX_JP2GEOTIFF_BOXES] = { NULL };
 
-    int i;
-    int nMax = MIN(nGeoTIFFBoxesCount, MAX_JP2GEOTIFF_BOXES);
-    for(i=0; i < nMax; i++)
+    const int nMax = std::min(nGeoTIFFBoxesCount, MAX_JP2GEOTIFF_BOXES);
+    for( int i = 0; i < nMax; ++i )
     {
     /* -------------------------------------------------------------------- */
     /*      Convert raw data into projection and geotransform.              */
@@ -567,9 +635,9 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
         }
     }
 
-    /* Detect which box is the better one */
+    // Detect which box is the better one.
     int iBestIndex = -1;
-    for(i=0; i < nMax; i++)
+    for( int i = 0; i < nMax; ++i )
     {
         if( abValidProjInfo[i] && iBestIndex < 0 )
         {
@@ -577,7 +645,7 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
         }
         else if( abValidProjInfo[i] && apszProjection[i] != NULL )
         {
-            /* Anything else than a LOCAL_CS will probably be better */
+            // Anything else than a LOCAL_CS will probably be better.
             if( STARTS_WITH_CI(apszProjection[iBestIndex], "LOCAL_CS") )
                 iBestIndex = i;
         }
@@ -585,7 +653,7 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
 
     if( iBestIndex < 0 )
     {
-        for(i=0; i < nMax; i++)
+        for( int i = 0; i < nMax; ++i )
         {
             if( aadfGeoTransform[i][0] != 0
                 || aadfGeoTransform[i][1] != 1
@@ -607,7 +675,7 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
         memcpy(adfGeoTransform, aadfGeoTransform[iBestIndex], 6 * sizeof(double));
         nGCPCount = anGCPCount[iBestIndex];
         pasGCPList = apasGCPList[iBestIndex];
-        bPixelIsPoint = abPixelIsPoint[iBestIndex];
+        bPixelIsPoint = CPL_TO_BOOL(abPixelIsPoint[iBestIndex]);
         papszRPCMD = apapszRPCMD[iBestIndex];
 
         if( adfGeoTransform[0] != 0
@@ -616,7 +684,7 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
             || adfGeoTransform[3] != 0
             || adfGeoTransform[4] != 0
             || adfGeoTransform[5] != 1 )
-            bHaveGeoTransform = TRUE;
+            bHaveGeoTransform = true;
 
         if( pszProjection )
             CPLDebug( "GDALJP2Metadata",
@@ -624,8 +692,8 @@ int GDALJP2Metadata::ParseJP2GeoTIFF()
                 iBestIndex, pszProjection );
     }
 
-    /* Cleanup unused boxes */
-    for(i=0; i < nMax; i++)
+    // Cleanup unused boxes.
+    for( int i = 0; i < nMax; ++i )
     {
         if( i != iBestIndex )
         {
@@ -676,7 +744,7 @@ int GDALJP2Metadata::ParseMSIG()
     adfGeoTransform[3] -= 0.5 * adfGeoTransform[4];
     adfGeoTransform[3] -= 0.5 * adfGeoTransform[5];
 
-    bHaveGeoTransform = TRUE;
+    bHaveGeoTransform = true;
 
     return TRUE;
 }
@@ -689,10 +757,7 @@ static CPLXMLNode *
 GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
 
 {
-    char *pszLabel;
-    const char *pszFragmentId = NULL;
-    int i;
-
+    char *pszLabel = NULL;
 
     if( STARTS_WITH_CI(pszURN, "urn:jp2k:xml:") )
         pszLabel = CPLStrdup( pszURN + 13 );
@@ -706,17 +771,22 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
 /* -------------------------------------------------------------------- */
 /*      Split out label and fragment id.                                */
 /* -------------------------------------------------------------------- */
-    for( i = 0; pszLabel[i] != '#'; i++ )
+    const char *pszFragmentId = NULL;
+
     {
-        if( pszLabel[i] == '\0' )
+        int i = 0;  // Used after for.
+        for( ; pszLabel[i] != '#'; ++i )
         {
-            CPLFree(pszLabel);
-            return NULL;
+            if( pszLabel[i] == '\0' )
+            {
+                CPLFree(pszLabel);
+                return NULL;
+            }
         }
-    }
 
-    pszFragmentId = pszLabel + i + 1;
-    pszLabel[i] = '\0';
+        pszFragmentId = pszLabel + i + 1;
+        pszLabel[i] = '\0';
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Can we find an XML box with the desired label?                  */
@@ -786,7 +856,6 @@ GetDictionaryItem( char **papszGMLMetadata, const char *pszURN )
     return psHit;
 }
 
-
 /************************************************************************/
 /*                            GMLSRSLookup()                            */
 /*                                                                      */
@@ -817,7 +886,7 @@ int GDALJP2Metadata::GMLSRSLookup( const char *pszURN )
 /*      Try to convert into an OGRSpatialReference.                     */
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oSRS;
-    int bSuccess = FALSE;
+    bool bSuccess = false;
 
     if( oSRS.importFromXML( pszDictEntryXML ) == OGRERR_NONE )
     {
@@ -825,7 +894,7 @@ int GDALJP2Metadata::GMLSRSLookup( const char *pszURN )
         pszProjection = NULL;
 
         oSRS.exportToWkt( &pszProjection );
-        bSuccess = TRUE;
+        bSuccess = true;
     }
 
     CPLFree( pszDictEntryXML );
@@ -871,13 +940,13 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psRG = CPLSearchXMLNode( psXML, "=RectifiedGrid" );
     CPLXMLNode *psOriginPoint = NULL;
-    const char *pszOffset1=NULL, *pszOffset2=NULL;
+    const char *pszOffset1 = NULL;
+    const char *pszOffset2 = NULL;
 
     if( psRG != NULL )
     {
         psOriginPoint = CPLGetXMLNode( psRG, "origin.Point" );
 
-
         CPLXMLNode *psOffset1 = CPLGetXMLNode( psRG, "offsetVector" );
         if( psOffset1 != NULL )
         {
@@ -948,7 +1017,7 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
         adfGeoTransform[3] -= adfGeoTransform[5]*0.5;
 
         bSuccess = true;
-        bHaveGeoTransform = TRUE;
+        bHaveGeoTransform = true;
     }
 
     CSLDestroy( papszOffset1Tokens );
@@ -1049,7 +1118,6 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
 
         CPLFree(pszProjection);
         oSRS.exportToWkt( &pszProjection );
-
     }
 
     /* Some Pleiades files have explicit <gml:axisName>Easting</gml:axisName> */
@@ -1076,12 +1144,14 @@ int GDALJP2Metadata::ParseGMLCoverageDesc()
                 {
                     bSecondAxisIsNorthOrLat = true;
                 }
-                nAxisCount ++;
+                ++nAxisCount;
             }
         }
         if( bFirstAxisIsEastOrLong && bSecondAxisIsNorthOrLat )
         {
-            CPLDebug( "GMLJP2", "Disable axis flip because of explicit axisName disabling it" );
+            CPLDebug(
+                "GMLJP2",
+                "Disable axis flip because of explicit axisName disabling it" );
             bNeedAxisFlip = false;
         }
     }
@@ -1411,7 +1481,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
         }
 
         CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_END ));
-        int nLength = (int) VSIFTellL( fp );
+        const int nLength = static_cast<int>( VSIFTellL( fp ) );
         pszGML = (char *) CPLCalloc(1,nLength+1);
         CPL_IGNORE_RET_VAL(VSIFSeekL( fp, 0, SEEK_SET ));
         CPL_IGNORE_RET_VAL(VSIFReadL( pszGML, 1, nLength, fp ));
@@ -1464,10 +1534,10 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
     double dfY2 = adfGeoTransform[3] + nXSize * adfGeoTransform[4];
     double dfY3 = adfGeoTransform[3] +                               nYSize * adfGeoTransform[5];
     double dfY4 = adfGeoTransform[3] + nXSize * adfGeoTransform[4] + nYSize * adfGeoTransform[5];
-    double dfLCX = MIN(MIN(dfX1,dfX2),MIN(dfX3,dfX4));
-    double dfLCY = MIN(MIN(dfY1,dfY2),MIN(dfY3,dfY4));
-    double dfUCX = MAX(MAX(dfX1,dfX2),MAX(dfX3,dfX4));
-    double dfUCY = MAX(MAX(dfY1,dfY2),MAX(dfY3,dfY4));
+    double dfLCX = std::min(std::min(dfX1, dfX2), std::min(dfX3, dfX4));
+    double dfLCY = std::min(std::min(dfY1, dfY2), std::min(dfY3, dfY4));
+    double dfUCX = std::max(std::max(dfX1, dfX2), std::max(dfX3, dfX4));
+    double dfUCY = std::max(std::max(dfY1, dfY2), std::max(dfY3, dfY4));
     if( bNeedAxisFlip )
     {
         double dfTmp = dfLCX;
@@ -1554,7 +1624,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2( int nXSize, int nYSize )
 /* -------------------------------------------------------------------- */
 /*      Add optional dictionary.                                        */
 /* -------------------------------------------------------------------- */
-    if( osDictBox.size() > 0 )
+    if( !osDictBox.empty() )
         apoGMLBoxes[nGMLBoxes++] =
             GDALJP2Box::CreateLabelledXMLAssoc( "CRSDictionary.gml",
                                                 osDictBox );
@@ -1628,6 +1698,7 @@ class GMLJP2V2GMLFileDesc
         CPLString osFile;
         CPLString osRemoteResource;
         CPLString osNamespace;
+        CPLString osNamespacePrefix;
         CPLString osSchemaLocation;
         int       bInline;
         int       bParentCoverageCollection;
@@ -1686,6 +1757,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
     CPLString osRootGMLId = "ID_GMLJP2_0";
     CPLString osGridCoverage;
     CPLString osGridCoverageFile;
+    CPLString osCoverageRangeTypeXML;
     bool bCRSURL = true;
     std::vector<GMLJP2V2MetadataDesc> aoMetadata;
     std::vector<GMLJP2V2AnnotationDesc> aoAnnotations;
@@ -1721,6 +1793,19 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             "If not specified, GDAL will auto-generate a GMLJP2RectifiedGridCoverage" ],
         "grid_coverage_file": "gmljp2gridcoverage.xml",
 
+        "#grid_coverage_range_type_field_predefined_name_doc": [
+            "One of Color, Elevation_meter or Panchromatic ",
+            "to fill gmlcov:rangeType/swe:DataRecord/swe:field",
+            "Only used if grid_coverage_file is not defined.",
+            "Exclusive with grid_coverage_range_type_file" ],
+        "grid_coverage_range_type_field_predefined_name": "Color",
+
+        "#grid_coverage_range_type_file_doc": [
+            "File that is XML content to put under gml:RectifiedGrid/gmlcov:rangeType",
+            "Only used if grid_coverage_file is not defined.",
+            "Exclusive with grid_coverage_range_type_field_predefined_name" ],
+        "grid_coverage_range_type_file": "grid_coverage_range_type.xml",
+
         "#crs_url_doc": [
             "true for http://www.opengis.net/def/crs/EPSG/0/XXXX CRS URL.",
             "If false, use CRS URN. Default value is true" ],
@@ -1759,7 +1844,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 "#parent_node": ["Where to put the metadata.",
                                  "Under CoverageCollection (default) or GridCoverage" ],
                 "parent_node": "CoverageCollection"
-            },
+            }
         ],
 
         "#annotations_doc": [ "An array of filenames, either directly KML files",
@@ -1804,7 +1889,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             }
         ],
 
-        "#styles_doc: [ "An array of styles. For example SLD files" ],
+        "#styles_doc": [ "An array of styles. For example SLD files" ],
         "styles" : [
             {
                 "#file_doc": "Can use relative or absolute paths.",
@@ -1816,7 +1901,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             }
         ],
 
-        "#extensions_doc: [ "An array of extensions." ],
+        "#extensions_doc": [ "An array of extensions." ],
         "extensions" : [
             {
                 "#file_doc": "Can use relative or absolute paths.",
@@ -1859,29 +1944,99 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
         }
         json_tokener_free(jstok);
 
-        json_object* poRootInstance = json_object_object_get(poObj, "root_instance");
+        json_object* poRootInstance = CPL_json_object_object_get(poObj, "root_instance");
         if( poRootInstance && json_object_get_type(poRootInstance) == json_type_object )
         {
-            json_object* poGMLId = json_object_object_get(poRootInstance, "gml_id");
+            json_object* poGMLId = CPL_json_object_object_get(poRootInstance, "gml_id");
             if( poGMLId && json_object_get_type(poGMLId) == json_type_string )
                 osRootGMLId = json_object_get_string(poGMLId);
 
-            json_object* poGridCoverageFile = json_object_object_get(poRootInstance, "grid_coverage_file");
+            json_object* poGridCoverageFile = CPL_json_object_object_get(poRootInstance, "grid_coverage_file");
             if( poGridCoverageFile && json_object_get_type(poGridCoverageFile) == json_type_string )
                 osGridCoverageFile = json_object_get_string(poGridCoverageFile);
 
-            json_object* poCRSURL = json_object_object_get(poRootInstance, "crs_url");
+            json_object* poGCRTFPN =
+                CPL_json_object_object_get(poRootInstance, "grid_coverage_range_type_field_predefined_name");
+            if( poGCRTFPN && json_object_get_type(poGCRTFPN) == json_type_string )
+            {
+                CPLString osPredefinedName( json_object_get_string(poGCRTFPN) );
+                if( EQUAL(osPredefinedName, "Color") )
+                {
+                    osCoverageRangeTypeXML =
+    "<swe:DataRecord>"
+        "<swe:field name=\"Color\">"
+            "<swe:Quantity definition=\"http://www.opengis.net/def/ogc-eo/opt/SpectralMode/Color\">"
+                "<swe:description>Color image</swe:description>"
+                "<swe:uom code=\"unity\"/>"
+            "</swe:Quantity>"
+        "</swe:field>"
+    "</swe:DataRecord>";
+                }
+                else if( EQUAL(osPredefinedName, "Elevation_meter") )
+                {
+                    osCoverageRangeTypeXML =
+    "<swe:DataRecord>"
+        "<swe:field name=\"Elevation\">"
+            "<swe:Quantity definition=\"http://inspire.ec.europa.eu/enumeration/ElevationPropertyTypeValue/height\" "
+                          "referenceFrame=\"http://www.opengis.net/def/crs/EPSG/0/5714\">"
+                "<swe:description>Elevation above sea level</swe:description>"
+                "<swe:uom code=\"m\"/>"
+            "</swe:Quantity>"
+        "</swe:field>"
+    "</swe:DataRecord>";
+                }
+                else if( EQUAL(osPredefinedName, "Panchromatic") )
+                {
+                    osCoverageRangeTypeXML =
+    "<swe:DataRecord>"
+        "<swe:field name=\"Panchromatic\">"
+            "<swe:Quantity definition=\"http://www.opengis.net/def/ogc-eo/opt/SpectralMode/Panchromatic\">"
+                "<swe:description>Panchromatic Channel</swe:description>"
+                "<swe:uom code=\"unity\"/>"
+            "</swe:Quantity>"
+        "</swe:field>"
+    "</swe:DataRecord>";
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Unrecognized value for grid_coverage_range_type_field_predefined_name");
+                }
+            }
+            else
+            {
+                json_object* poGCRTFile =
+                    CPL_json_object_object_get(poRootInstance, "grid_coverage_range_type_file");
+                if( poGCRTFile && json_object_get_type(poGCRTFile) == json_type_string )
+                {
+                    CPLXMLNode* psTmp = CPLParseXMLFile(json_object_get_string(poGCRTFile));
+                    if( psTmp != NULL )
+                    {
+                        CPLXMLNode* psTmpRoot = GDALGMLJP2GetXMLRoot(psTmp);
+                        if( psTmpRoot )
+                        {
+                            char* pszTmp = CPLSerializeXMLTree(psTmpRoot);
+                            osCoverageRangeTypeXML = pszTmp;
+                            CPLFree(pszTmp);
+                        }
+                        CPLDestroyXMLNode(psTmp);
+                    }
+                }
+            }
+
+            json_object* poCRSURL = CPL_json_object_object_get(poRootInstance, "crs_url");
             if( poCRSURL && json_object_get_type(poCRSURL) == json_type_boolean )
                 bCRSURL = CPL_TO_BOOL(json_object_get_boolean(poCRSURL));
 
-
-            json_object* poMetadatas = json_object_object_get(poRootInstance, "metadata");
+            json_object* poMetadatas = CPL_json_object_object_get(poRootInstance, "metadata");
             if( poMetadatas && json_object_get_type(poMetadatas) == json_type_array )
             {
-                for(int i=0;i<json_object_array_length(poMetadatas);i++)
+                for( int i = 0; i < json_object_array_length(poMetadatas); ++i )
                 {
-                    json_object* poMetadata = json_object_array_get_idx(poMetadatas, i);
-                    if( poMetadata && json_object_get_type(poMetadata) == json_type_string )
+                    json_object* poMetadata =
+                        json_object_array_get_idx(poMetadatas, i);
+                    if( poMetadata &&
+                        json_object_get_type(poMetadata) == json_type_string )
                     {
                         GMLJP2V2MetadataDesc oDesc;
                         const char* pszStr = json_object_get_string(poMetadata);
@@ -1894,28 +2049,28 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                     else if ( poMetadata && json_object_get_type(poMetadata) == json_type_object )
                     {
                         const char* pszFile = NULL;
-                        json_object* poFile = json_object_object_get(poMetadata, "file");
+                        json_object* poFile = CPL_json_object_object_get(poMetadata, "file");
                         if( poFile && json_object_get_type(poFile) == json_type_string )
                             pszFile = json_object_get_string(poFile);
 
                         const char* pszContent = NULL;
-                        json_object* poContent = json_object_object_get(poMetadata, "content");
+                        json_object* poContent = CPL_json_object_object_get(poMetadata, "content");
                         if( poContent && json_object_get_type(poContent) == json_type_string )
                             pszContent = json_object_get_string(poContent);
 
                         const char* pszTemplate = NULL;
                         const char* pszSource = NULL;
-                        json_object* poDynamicMetadata = json_object_object_get(poMetadata, "dynamic_metadata");
+                        json_object* poDynamicMetadata = CPL_json_object_object_get(poMetadata, "dynamic_metadata");
                         if( poDynamicMetadata && json_object_get_type(poDynamicMetadata) == json_type_object )
                         {
 #ifdef HAVE_LIBXML2
                             if( CPLTestBool(CPLGetConfigOption("GDAL_DEBUG_PROCESS_DYNAMIC_METADATA", "YES")) )
                             {
-                                json_object* poTemplate = json_object_object_get(poDynamicMetadata, "template");
+                                json_object* poTemplate = CPL_json_object_object_get(poDynamicMetadata, "template");
                                 if( poTemplate && json_object_get_type(poTemplate) == json_type_string )
                                     pszTemplate = json_object_get_string(poTemplate);
 
-                                json_object* poSource = json_object_object_get(poDynamicMetadata, "source");
+                                json_object* poSource = CPL_json_object_object_get(poDynamicMetadata, "source");
                                 if( poSource && json_object_get_type(poSource) == json_type_string )
                                     pszSource = json_object_get_string(poSource);
                             }
@@ -1927,10 +2082,11 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                             }
                         }
 
-                        int bGDALMetadata = FALSE;
-                        json_object* poGDALMetadata = json_object_object_get(poMetadata, "gdal_metadata");
+                        bool bGDALMetadata = false;
+                        json_object* poGDALMetadata = CPL_json_object_object_get(poMetadata, "gdal_metadata");
                         if( poGDALMetadata && json_object_get_type(poGDALMetadata) == json_type_boolean )
-                            bGDALMetadata = json_object_get_boolean(poGDALMetadata);
+                            bGDALMetadata = CPL_TO_BOOL(
+                                json_object_get_boolean(poGDALMetadata));
 
                         if( pszFile != NULL || pszContent != NULL ||
                             (pszTemplate != NULL && pszSource != NULL) ||
@@ -1947,7 +2103,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                                 oDesc.osSourceFile = pszSource;
                             oDesc.bGDALMetadata = bGDALMetadata;
 
-                            json_object* poLocation = json_object_object_get(poMetadata, "parent_node");
+                            json_object* poLocation = CPL_json_object_object_get(poMetadata, "parent_node");
                             if( poLocation && json_object_get_type(poLocation) == json_type_string )
                             {
                                 const char* pszLocation = json_object_get_string(poLocation);
@@ -1966,10 +2122,12 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
             }
 
-            json_object* poAnnotations = json_object_object_get(poRootInstance, "annotations");
+            json_object* poAnnotations = CPL_json_object_object_get(poRootInstance, "annotations");
             if( poAnnotations && json_object_get_type(poAnnotations) == json_type_array )
             {
-                for(int i=0;i<json_object_array_length(poAnnotations);i++)
+                for( int i = 0;
+                     i < json_object_array_length(poAnnotations);
+                     ++i )
                 {
                     json_object* poAnnotation = json_object_array_get_idx(poAnnotations, i);
                     if( poAnnotation && json_object_get_type(poAnnotation) == json_type_string )
@@ -1981,21 +2139,27 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
             }
 
-            json_object* poGMLFileList = json_object_object_get(poRootInstance, "gml_filelist");
-            if( poGMLFileList && json_object_get_type(poGMLFileList) == json_type_array )
+            json_object* poGMLFileList =
+                CPL_json_object_object_get(poRootInstance, "gml_filelist");
+            if( poGMLFileList &&
+                json_object_get_type(poGMLFileList) == json_type_array )
             {
-                for(int i=0;i<json_object_array_length(poGMLFileList);i++)
+                for( int i = 0;
+                     i < json_object_array_length(poGMLFileList);
+                     ++i )
                 {
-                    json_object* poGMLFile = json_object_array_get_idx(poGMLFileList, i);
-                    if( poGMLFile && json_object_get_type(poGMLFile) == json_type_object )
+                    json_object* poGMLFile =
+                        json_object_array_get_idx(poGMLFileList, i);
+                    if( poGMLFile &&
+                        json_object_get_type(poGMLFile) == json_type_object )
                     {
                         const char* pszFile = NULL;
-                        json_object* poFile = json_object_object_get(poGMLFile, "file");
+                        json_object* poFile = CPL_json_object_object_get(poGMLFile, "file");
                         if( poFile && json_object_get_type(poFile) == json_type_string )
                             pszFile = json_object_get_string(poFile);
 
                         const char* pszRemoteResource = NULL;
-                        json_object* poRemoteResource = json_object_object_get(poGMLFile, "remote_resource");
+                        json_object* poRemoteResource = CPL_json_object_object_get(poGMLFile, "remote_resource");
                         if( poRemoteResource && json_object_get_type(poRemoteResource) == json_type_string )
                             pszRemoteResource = json_object_get_string(poRemoteResource);
 
@@ -2007,20 +2171,23 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                             else if( pszRemoteResource )
                                 oDesc.osRemoteResource = pszRemoteResource;
 
-                            json_object* poNamespace = json_object_object_get(poGMLFile, "namespace");
+                            json_object* poNamespacePrefix = CPL_json_object_object_get(poGMLFile, "namespace_prefix");
+                            if( poNamespacePrefix && json_object_get_type(poNamespacePrefix) == json_type_string )
+                                oDesc.osNamespacePrefix = json_object_get_string(poNamespacePrefix);
+
+                            json_object* poNamespace = CPL_json_object_object_get(poGMLFile, "namespace");
                             if( poNamespace && json_object_get_type(poNamespace) == json_type_string )
                                 oDesc.osNamespace = json_object_get_string(poNamespace);
 
-                            json_object* poSchemaLocation = json_object_object_get(poGMLFile, "schema_location");
+                            json_object* poSchemaLocation = CPL_json_object_object_get(poGMLFile, "schema_location");
                             if( poSchemaLocation && json_object_get_type(poSchemaLocation) == json_type_string )
                                 oDesc.osSchemaLocation = json_object_get_string(poSchemaLocation);
 
-                            json_object* poInline = json_object_object_get(poGMLFile, "inline");
+                            json_object* poInline = CPL_json_object_object_get(poGMLFile, "inline");
                             if( poInline && json_object_get_type(poInline) == json_type_boolean )
                                 oDesc.bInline = json_object_get_boolean(poInline);
 
-
-                            json_object* poLocation = json_object_object_get(poGMLFile, "parent_node");
+                            json_object* poLocation = CPL_json_object_object_get(poGMLFile, "parent_node");
                             if( poLocation && json_object_get_type(poLocation) == json_type_string )
                             {
                                 const char* pszLocation = json_object_get_string(poLocation);
@@ -2045,16 +2212,16 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
             }
 
-            json_object* poStyles = json_object_object_get(poRootInstance, "styles");
+            json_object* poStyles = CPL_json_object_object_get(poRootInstance, "styles");
             if( poStyles && json_object_get_type(poStyles) == json_type_array )
             {
-                for(int i=0;i<json_object_array_length(poStyles);i++)
+                for( int i = 0; i < json_object_array_length(poStyles); ++i )
                 {
                     json_object* poStyle = json_object_array_get_idx(poStyles, i);
                     if( poStyle && json_object_get_type(poStyle) == json_type_object )
                     {
                         const char* pszFile = NULL;
-                        json_object* poFile = json_object_object_get(poStyle, "file");
+                        json_object* poFile = CPL_json_object_object_get(poStyle, "file");
                         if( poFile && json_object_get_type(poFile) == json_type_string )
                             pszFile = json_object_get_string(poFile);
 
@@ -2063,7 +2230,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                             GMLJP2V2StyleDesc oDesc;
                             oDesc.osFile = pszFile;
 
-                            json_object* poLocation = json_object_object_get(poStyle, "parent_node");
+                            json_object* poLocation = CPL_json_object_object_get(poStyle, "parent_node");
                             if( poLocation && json_object_get_type(poLocation) == json_type_string )
                             {
                                 const char* pszLocation = json_object_get_string(poLocation);
@@ -2088,16 +2255,18 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
             }
 
-            json_object* poExtensions = json_object_object_get(poRootInstance, "extensions");
+            json_object* poExtensions = CPL_json_object_object_get(poRootInstance, "extensions");
             if( poExtensions && json_object_get_type(poExtensions) == json_type_array )
             {
-                for(int i=0;i<json_object_array_length(poExtensions);i++)
+                for( int i = 0;
+                     i < json_object_array_length(poExtensions);
+                     ++i )
                 {
                     json_object* poExtension = json_object_array_get_idx(poExtensions, i);
                     if( poExtension && json_object_get_type(poExtension) == json_type_object )
                     {
                         const char* pszFile = NULL;
-                        json_object* poFile = json_object_object_get(poExtension, "file");
+                        json_object* poFile = CPL_json_object_object_get(poExtension, "file");
                         if( poFile && json_object_get_type(poFile) == json_type_string )
                             pszFile = json_object_get_string(poFile);
 
@@ -2106,7 +2275,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                             GMLJP2V2ExtensionDesc oDesc;
                             oDesc.osFile = pszFile;
 
-                            json_object* poLocation = json_object_object_get(poExtension, "parent_node");
+                            json_object* poLocation = CPL_json_object_object_get(poExtension, "parent_node");
                             if( poLocation && json_object_get_type(poLocation) == json_type_string )
                             {
                                 const char* pszLocation = json_object_get_string(poLocation);
@@ -2132,22 +2301,25 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             }
         }
 
-        json_object* poBoxes = json_object_object_get(poObj, "boxes");
+        json_object* poBoxes = CPL_json_object_object_get(poObj, "boxes");
         if( poBoxes && json_object_get_type(poBoxes) == json_type_array )
         {
-            for(int i=0;i<json_object_array_length(poBoxes);i++)
+            for( int i = 0; i < json_object_array_length(poBoxes); ++i )
             {
                 json_object* poBox = json_object_array_get_idx(poBoxes, i);
                 if( poBox && json_object_get_type(poBox) == json_type_object )
                 {
-                    json_object* poFile = json_object_object_get(poBox, "file");
-                    if( poFile && json_object_get_type(poFile) == json_type_string )
+                    json_object* poFile = CPL_json_object_object_get(poBox, "file");
+                    if( poFile &&
+                        json_object_get_type(poFile) == json_type_string )
                     {
                         GMLJP2V2BoxDesc oDesc;
                         oDesc.osFile = json_object_get_string(poFile);
 
-                        json_object* poLabel = json_object_object_get(poBox, "label");
-                        if( poLabel && json_object_get_type(poLabel) == json_type_string )
+                        json_object* poLabel =
+                            CPL_json_object_object_get(poBox, "label");
+                        if( poLabel &&
+                            json_object_get_type(poLabel) == json_type_string )
                             oDesc.osLabel = json_object_get_string(poLabel);
                         else
                             oDesc.osLabel = CPLGetFilename(oDesc.osFile);
@@ -2155,7 +2327,8 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                         aoBoxes.push_back(oDesc);
                     }
                 }
-                else if( poBox && json_object_get_type(poBox) == json_type_string )
+                else if( poBox &&
+                         json_object_get_type(poBox) == json_type_string )
                 {
                     GMLJP2V2BoxDesc oDesc;
                     oDesc.osFile = json_object_get_string(poBox);
@@ -2169,28 +2342,34 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 
         // Check that if a GML file points to an internal schemaLocation,
         // the matching box really exists.
-        for(int i=0;i<(int)aoGMLFiles.size();i++)
+        for( int i = 0; i < static_cast<int>(aoGMLFiles.size()); ++i )
         {
-            if( aoGMLFiles[i].osSchemaLocation.size() &&
-                STARTS_WITH(aoGMLFiles[i].osSchemaLocation, "gmljp2://xml/") )            {
+            if( !aoGMLFiles[i].osSchemaLocation.empty() &&
+                STARTS_WITH(aoGMLFiles[i].osSchemaLocation, "gmljp2://xml/") )
+            {
                 const char* pszLookedLabel =
-                    aoGMLFiles[i].osSchemaLocation.c_str() + strlen("gmljp2://xml/");
+                    aoGMLFiles[i].osSchemaLocation.c_str() +
+                    strlen("gmljp2://xml/");
                 bool bFound = false;
-                for(int j=0; !bFound && j<(int)aoBoxes.size();j++)
+                for( int j = 0;
+                     !bFound && j < static_cast<int>(aoBoxes.size());
+                     ++j )
                     bFound = (strcmp(pszLookedLabel, aoBoxes[j].osLabel) == 0);
                 if( !bFound )
                 {
-                    CPLError(CE_Warning, CPLE_AppDefined,
-                             "GML file %s has a schema_location=%s, but no box with label %s is defined",
-                             aoGMLFiles[i].osFile.c_str(),
-                             aoGMLFiles[i].osSchemaLocation.c_str(),
-                             pszLookedLabel);
+                    CPLError(
+                        CE_Warning, CPLE_AppDefined,
+                        "GML file %s has a schema_location=%s, "
+                        "but no box with label %s is defined",
+                        aoGMLFiles[i].osFile.c_str(),
+                        aoGMLFiles[i].osSchemaLocation.c_str(),
+                        pszLookedLabel);
                 }
             }
         }
 
-        // Read custom grid coverage file
-        if( osGridCoverageFile.size() > 0 )
+        // Read custom grid coverage file.
+        if( !osGridCoverageFile.empty() )
         {
             CPLXMLNode* psTmp = CPLParseXMLFile(osGridCoverageFile);
             if( psTmp == NULL )
@@ -2209,7 +2388,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
     CPLString osDictBox;
     CPLString osDoc;
 
-    if( osGridCoverage.size() == 0 )
+    if( osGridCoverage.empty() )
     {
 /* -------------------------------------------------------------------- */
 /*      Prepare GMLJP2RectifiedGridCoverage                             */
@@ -2241,8 +2420,18 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             snprintf( szSRSName, sizeof(szSRSName), "%s",
                     "gmljp2://xml/CRSDictionary.gml#ogrcrs1" );
 
+        const double dfLLX = adfGeoTransform[0];
+        const double dfLLY = adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
+        const double dfURX = adfGeoTransform[0] + adfGeoTransform[1] * nXSize;
+        const double dfURY = adfGeoTransform[3];
         osGridCoverage.Printf(
 "   <gmljp2:GMLJP2RectifiedGridCoverage gml:id=\"RGC_1_%s\">\n"
+"     <gml:boundedBy>\n"
+"       <gml:Envelope srsDimension=\"2\" srsName=\"%s\">\n"
+"         <gml:lowerCorner>%.15g %.15g</gml:lowerCorner>\n"
+"         <gml:upperCorner>%.15g %.15g</gml:upperCorner>\n"
+"       </gml:Envelope>\n"
+"     </gml:boundedBy>\n"
 "     <gml:domainSet>\n"
 "      <gml:RectifiedGrid gml:id=\"RGC_1_GRID_%s\" dimension=\"2\" srsName=\"%s\">\n"
 "       <gml:limits>\n"
@@ -2270,20 +2459,26 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 "        <gml:fileStructure>inapplicable</gml:fileStructure>\n"
 "      </gml:File>\n"
 "     </gml:rangeSet>\n"
-"     <gmlcov:rangeType/>\n"
+"     <gmlcov:rangeType>%s</gmlcov:rangeType>\n"
 "   </gmljp2:GMLJP2RectifiedGridCoverage>\n",
             osRootGMLId.c_str(),
+            szSRSName,
+            dfLLX, dfLLY,
+            dfURX, dfURY,
             osRootGMLId.c_str(),
             szSRSName,
             nXSize-1, nYSize-1, szSRSName, adfOrigin[0], adfOrigin[1],
             pszComment,
             szSRSName, adfXVector[0], adfXVector[1],
-            szSRSName, adfYVector[0], adfYVector[1] );
+            szSRSName, adfYVector[0], adfYVector[1],
+            osCoverageRangeTypeXML.c_str() );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Main node.                                                      */
 /* -------------------------------------------------------------------- */
+
+    // Per http://docs.opengeospatial.org/is/08-085r5/08-085r5.html#requirement_11
     osDoc.Printf(
 //"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
 "<gmljp2:GMLJP2CoverageCollection gml:id=\"%s\"\n"
@@ -2293,15 +2488,18 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 "     xmlns:swe=\"http://www.opengis.net/swe/2.0\"\n"
 "     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
 "     xsi:schemaLocation=\"http://www.opengis.net/gmljp2/2.0 http://schemas.opengis.net/gmljp2/2.0/gmljp2.xsd\">\n"
-"  <gml:gridDomain/>\n"
+"  <gml:domainSet nilReason=\"inapplicable\"/>\n"
 "  <gml:rangeSet>\n"
-"   <gml:File>\n"
-"     <gml:rangeParameters/>\n"
-"     <gml:fileName>gmljp2://codestream</gml:fileName>\n"
-"     <gml:fileStructure>inapplicable</gml:fileStructure>\n"
-"   </gml:File>\n"
+"    <gml:DataBlock>\n"
+"       <gml:rangeParameters nilReason=\"inapplicable\"/>\n"
+"       <gml:doubleOrNilReasonTupleList>inapplicable</gml:doubleOrNilReasonTupleList>\n"
+"     </gml:DataBlock>\n"
 "  </gml:rangeSet>\n"
-"  <gmlcov:rangeType/>\n"
+"  <gmlcov:rangeType>\n"
+"    <swe:DataRecord>\n"
+"      <swe:field name=\"Collection\"> </swe:field>\n"
+"    </swe:DataRecord>\n"
+"  </gmlcov:rangeType>\n"
 "  <gmljp2:featureMember>\n"
 "%s"
 "  </gmljp2:featureMember>\n"
@@ -2313,21 +2511,20 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 /*      Process metadata, annotations and features collections.         */
 /* -------------------------------------------------------------------- */
     std::vector<CPLString> aosTmpFiles;
-    bool bRootHasXLink = false;
-    if( aoMetadata.size() || aoAnnotations.size() || aoGMLFiles.size() ||
-        aoStyles.size() || aoExtensions.size() )
+    if( !aoMetadata.empty() || !aoAnnotations.empty() || !aoGMLFiles.empty() ||
+        !aoStyles.empty() || !aoExtensions.empty() )
     {
         CPLXMLNode* psRoot = CPLParseXMLString(osDoc);
         CPLAssert(psRoot);
         CPLXMLNode* psGMLJP2CoverageCollection = GDALGMLJP2GetXMLRoot(psRoot);
         CPLAssert(psGMLJP2CoverageCollection);
 
-        for( int i=0; i < (int)aoMetadata.size(); i++ )
+        for( int i=0; i < static_cast<int>(aoMetadata.size()); ++i )
         {
-            CPLXMLNode* psMetadata;
-            if( aoMetadata[i].osFile.size() )
+            CPLXMLNode* psMetadata = NULL;
+            if( !aoMetadata[i].osFile.empty() )
                 psMetadata = CPLParseXMLFile(aoMetadata[i].osFile);
-            else if( aoMetadata[i].osContent.size() )
+            else if( !aoMetadata[i].osContent.empty() )
                 psMetadata = CPLParseXMLString(aoMetadata[i].osContent);
             else if( aoMetadata[i].bGDALMetadata )
             {
@@ -2335,20 +2532,23 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 if( psMetadata )
                 {
                     CPLSetXMLValue(psMetadata, "#xmlns", "http://gdal.org");
-                    CPLXMLNode* psNewMetadata = CPLCreateXMLNode(NULL, CXT_Element, "gmljp2:metadata");
+                    CPLXMLNode* psNewMetadata =
+                        CPLCreateXMLNode(NULL, CXT_Element, "gmljp2:metadata");
                     CPLAddXMLChild(psNewMetadata, psMetadata);
                     psMetadata = psNewMetadata;
                 }
             }
             else
-                psMetadata = GDALGMLJP2GenerateMetadata(aoMetadata[i].osTemplateFile,
-                                                        aoMetadata[i].osSourceFile);
+                psMetadata =
+                    GDALGMLJP2GenerateMetadata(aoMetadata[i].osTemplateFile,
+                                               aoMetadata[i].osSourceFile);
             if( psMetadata == NULL )
                 continue;
             CPLXMLNode* psMetadataRoot = GDALGMLJP2GetXMLRoot(psMetadata);
             if( psMetadataRoot )
             {
-                if( strcmp(psMetadataRoot->pszValue, "eop:EarthObservation") == 0 )
+                if( strcmp(psMetadataRoot->pszValue,
+                           "eop:EarthObservation") == 0 )
                 {
                     CPLXMLNode* psNewMetadata = CPLCreateXMLNode(NULL, CXT_Element, "gmljp2:eopMetadata");
                     CPLAddXMLChild(psNewMetadata, CPLCloneXMLTree(psMetadataRoot));
@@ -2406,14 +2606,15 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             CPLDestroyXMLNode(psMetadata);
         }
 
+        bool bRootHasXLink = false;
+
         // Examples of inline or reference feature collections can be found
         // in http://schemas.opengis.net/gmljp2/2.0/examples/gmljp2.xml
-
-        for( int i=0; i < (int)aoGMLFiles.size(); i++ )
+        for( int i = 0; i < static_cast<int>(aoGMLFiles.size()); ++i )
         {
-            // Is the file already a GML file ?
+            // Is the file already a GML file?
             CPLXMLNode* psGMLFile = NULL;
-            if( aoGMLFiles[i].osFile.size() )
+            if( !aoGMLFiles[i].osFile.empty() )
             {
                 if( EQUAL(CPLGetExtension(aoGMLFiles[i].osFile), "gml") ||
                     EQUAL(CPLGetExtension(aoGMLFiles[i].osFile), "xml") )
@@ -2427,8 +2628,8 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                     if( hDrv == NULL )
                     {
                         CPLError(CE_Failure, CPLE_AppDefined,
-                                "%s is no a GDAL recognized file",
-                                aoGMLFiles[i].osFile.c_str());
+                                 "%s is no a GDAL recognized file",
+                                 aoGMLFiles[i].osFile.c_str());
                         continue;
                     }
                 }
@@ -2456,11 +2657,32 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                                                         this,
                                                         i,
                                                         CPLGetBasename(aoGMLFiles[i].osFile));
-                        char* apszOptions[2];
-                        apszOptions[0] = (char*) "FORMAT=GML3.2";
-                        apszOptions[1] = NULL;
-                        GDALDatasetH hDS = GDALCreateCopy(hGMLDrv, osTmpFile, hSrcDS,
-                                                        FALSE, apszOptions, NULL, NULL);
+                        char ** papszOptions = NULL;
+                        papszOptions = CSLSetNameValue(papszOptions,
+                                                       "FORMAT", "GML3.2");
+                        papszOptions = CSLSetNameValue(papszOptions,
+                                "SRSNAME_FORMAT",
+                                (bCRSURL) ? "OGC_URL" : "OGC_URN");
+                        if( aoGMLFiles.size() > 1 ||
+                            !aoGMLFiles[i].osNamespace.empty() ||
+                            !aoGMLFiles[i].osNamespacePrefix.empty() )
+                        {
+                            papszOptions = CSLSetNameValue(papszOptions,
+                                "PREFIX",
+                                    aoGMLFiles[i].osNamespacePrefix.empty() ?
+                                        CPLSPrintf("ogr%d", i) :
+                                        aoGMLFiles[i].osNamespacePrefix.c_str());
+                            papszOptions = CSLSetNameValue(papszOptions,
+                                "TARGET_NAMESPACE",
+                                aoGMLFiles[i].osNamespace.empty() ?
+                                    CPLSPrintf("http://ogr.maptools.org/%d", i) :
+                                    aoGMLFiles[i].osNamespace.c_str());
+                        }
+                        GDALDatasetH hDS = GDALCreateCopy(
+                                    hGMLDrv, osTmpFile, hSrcDS,
+                                    FALSE,
+                                    papszOptions, NULL, NULL);
+                        CSLDestroy(papszOptions);
                         if( hDS )
                         {
                             GDALClose(hDS);
@@ -2483,7 +2705,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             }
 
             CPLXMLNode* psGMLFileRoot = psGMLFile ? GDALGMLJP2GetXMLRoot(psGMLFile) : NULL;
-            if( psGMLFileRoot || aoGMLFiles[i].osRemoteResource.size() )
+            if( psGMLFileRoot || !aoGMLFiles[i].osRemoteResource.empty() )
             {
                 CPLXMLNode *node_f;
                 if( aoGMLFiles[i].bParentCoverageCollection )
@@ -2495,7 +2717,6 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                     CPLXMLNode *node_gf = CPLCreateXMLNode(
                             node_fm, CXT_Element, "gmljp2:GMLJP2Features" );
 
-
                     CPLSetXMLValue(node_gf, "#gml:id", CPLSPrintf("%s_GMLJP2Features_%d",
                                                                     osRootGMLId.c_str(),
                                                                     i));
@@ -2512,7 +2733,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                     node_f = CPLCreateXMLNode( psGridCoverage, CXT_Element, "gmljp2:feature"  );
                 }
 
-                if( !aoGMLFiles[i].bInline || aoGMLFiles[i].osRemoteResource.size() )
+                if( !aoGMLFiles[i].bInline || !aoGMLFiles[i].osRemoteResource.empty() )
                 {
                     if( !bRootHasXLink )
                     {
@@ -2522,7 +2743,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                     }
                 }
 
-                if( aoGMLFiles[i].osRemoteResource.size() )
+                if( !aoGMLFiles[i].osRemoteResource.empty() )
                 {
                     CPLSetXMLValue(node_f, "#xlink:href",
                                    aoGMLFiles[i].osRemoteResource.c_str());
@@ -2530,7 +2751,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 }
 
                 CPLString osTmpFile;
-                if( !aoGMLFiles[i].bInline || aoGMLFiles[i].osRemoteResource.size() )
+                if( !aoGMLFiles[i].bInline || !aoGMLFiles[i].osRemoteResource.empty() )
                 {
                     osTmpFile = CPLSPrintf("/vsimem/gmljp2/%p/%d/%s.gml",
                                            this,
@@ -2576,8 +2797,8 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                     CPLString osSchemaLocation;
 
                     if( CSLCount(papszTokens) == 2 &&
-                        aoGMLFiles[i].osNamespace.size() == 0 &&
-                        aoGMLFiles[i].osSchemaLocation.size() )
+                        aoGMLFiles[i].osNamespace.empty() &&
+                        !aoGMLFiles[i].osSchemaLocation.empty() )
                     {
                         osSchemaLocation += papszTokens[0];
                         osSchemaLocation += " ";
@@ -2585,9 +2806,9 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                     }
 
                     else if( CSLCount(papszTokens) == 2 &&
-                                (aoGMLFiles[i].osNamespace.size() == 0 ||
+                                (aoGMLFiles[i].osNamespace.empty() ||
                                 strcmp(papszTokens[0], aoGMLFiles[i].osNamespace) == 0) &&
-                                aoGMLFiles[i].osSchemaLocation.size() == 0 )
+                                aoGMLFiles[i].osSchemaLocation.empty() )
                     {
                         VSIStatBufL sStat;
                         CPLString osXSD;
@@ -2606,7 +2827,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                             osXSD = CPLFormFilename(CPLGetDirname(aoGMLFiles[i].osFile),
                                                         papszTokens[1], NULL);
                         }
-                        if( osXSD.size() )
+                        if( !osXSD.empty() )
                         {
                             GMLJP2V2BoxDesc oDesc;
                             oDesc.osFile = osXSD;
@@ -2615,30 +2836,34 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                             osSchemaLocation += " ";
                             osSchemaLocation += "gmljp2://xml/";
                             osSchemaLocation += oDesc.osLabel;
-                            int j;
-                            for( j=0; j<(int)aoBoxes.size(); j++)
+                            int j = 0;  // Used after for.
+                            for( ; j < static_cast<int>(aoBoxes.size()); ++j )
                             {
                                 if( aoBoxes[j].osLabel == oDesc.osLabel )
                                     break;
                             }
-                            if( j == (int)aoBoxes.size() )
+                            if( j == static_cast<int>(aoBoxes.size()) )
                                 aoBoxes.push_back(oDesc);
                         }
                     }
 
                     else if( (CSLCount(papszTokens) % 2) == 0 )
                     {
-                        for(char** papszIter = papszTokens; *papszIter; papszIter += 2 )
+                        for( char** papszIter = papszTokens;
+                             *papszIter;
+                             papszIter += 2 )
                         {
-                            if( osSchemaLocation.size() )
+                            if( !osSchemaLocation.empty() )
                                 osSchemaLocation += " ";
-                            if( aoGMLFiles[i].osNamespace.size() &&
-                                aoGMLFiles[i].osSchemaLocation.size() &&
-                                strcmp(papszIter[0], aoGMLFiles[i].osNamespace) == 0 )
+                            if( !aoGMLFiles[i].osNamespace.empty() &&
+                                !aoGMLFiles[i].osSchemaLocation.empty() &&
+                                strcmp(papszIter[0],
+                                       aoGMLFiles[i].osNamespace) == 0 )
                             {
                                 osSchemaLocation += papszIter[0];
                                 osSchemaLocation += " ";
-                                osSchemaLocation += aoGMLFiles[i].osSchemaLocation;
+                                osSchemaLocation +=
+                                    aoGMLFiles[i].osSchemaLocation;
                             }
                             else
                             {
@@ -2660,10 +2885,11 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             CPLDestroyXMLNode(psGMLFile);
         }
 
-        // Cf http://schemas.opengis.net/gmljp2/2.0/examples/gmljp2_annotation.xml
-        for( int i=0; i < (int)aoAnnotations.size(); i++ )
+        // c.f.
+        // http://schemas.opengis.net/gmljp2/2.0/examples/gmljp2_annotation.xml
+        for( int i = 0; i < static_cast<int>(aoAnnotations.size()); ++i )
         {
-            // Is the file already a KML file ?
+            // Is the file already a KML file?
             CPLXMLNode* psKMLFile = NULL;
             if( EQUAL(CPLGetExtension(aoAnnotations[i].osFile), "kml") )
                  psKMLFile = CPLParseXMLFile(aoAnnotations[i].osFile);
@@ -2702,12 +2928,17 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                                                      this,
                                                      i,
                                                      CPLGetBasename(aoAnnotations[i].osFile));
-                    char* apszOptions[2];
-                    apszOptions[0] = NULL;
-                    apszOptions[1] = NULL;
+                    char** papszOptions = NULL;
+                    if( aoAnnotations.size() > 1 )
+                    {
+                        papszOptions = CSLSetNameValue(
+                            papszOptions, "DOCUMENT_ID",
+                            CPLSPrintf("root_doc_%d", i));
+                    }
                     GDALDatasetH hDS = GDALCreateCopy(hLIBKMLDrv ? hLIBKMLDrv : hKMLDrv,
                                                       osTmpFile, hSrcDS,
-                                                      FALSE, apszOptions, NULL, NULL);
+                                                      FALSE, papszOptions, NULL, NULL);
+                    CSLDestroy(papszOptions);
                     if( hDS )
                     {
                         GDALClose(hDS);
@@ -2753,8 +2984,8 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             CPLDestroyXMLNode(psKMLFile);
         }
 
-        // Add styles
-        for( int i=0; i < (int)aoStyles.size(); i++ )
+        // Add styles.
+        for( int i = 0; i < static_cast<int>(aoStyles.size()); ++i )
         {
             CPLXMLNode* psStyle = CPLParseXMLFile(aoStyles[i].osFile);
             if( psStyle == NULL )
@@ -2763,26 +2994,33 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             CPLXMLNode* psStyleRoot = GDALGMLJP2GetXMLRoot(psStyle);
             if( psStyleRoot )
             {
-                CPLXMLNode *psGMLJP2Style;
+                CPLXMLNode *psGMLJP2Style = NULL;
                 if( aoStyles[i].bParentCoverageCollection )
                 {
-                    psGMLJP2Style = CPLCreateXMLNode( psGMLJP2CoverageCollection, CXT_Element, "gmljp2:style"  );
+                    psGMLJP2Style =
+                        CPLCreateXMLNode( psGMLJP2CoverageCollection,
+                                          CXT_Element, "gmljp2:style" );
                 }
                 else
                 {
                     CPLXMLNode* psFeatureMemberOfGridCoverage =
-                        CPLGetXMLNode(psGMLJP2CoverageCollection, "gmljp2:featureMember");
+                        CPLGetXMLNode(psGMLJP2CoverageCollection,
+                                      "gmljp2:featureMember");
                     CPLAssert(psFeatureMemberOfGridCoverage);
-                    CPLXMLNode* psGridCoverage = psFeatureMemberOfGridCoverage->psChild;
+                    CPLXMLNode* psGridCoverage =
+                        psFeatureMemberOfGridCoverage->psChild;
                     CPLAssert(psGridCoverage);
-                    psGMLJP2Style = CPLCreateXMLNode( psGridCoverage, CXT_Element, "gmljp2:style"  );
+                    psGMLJP2Style =
+                        CPLCreateXMLNode( psGridCoverage,
+                                          CXT_Element, "gmljp2:style" );
                 }
 
                 // Add dummy namespace for validation purposes if needed
                 if( strchr(psStyleRoot->pszValue, ':') == NULL &&
                     CPLGetXMLValue(psStyleRoot, "xmlns", NULL) == NULL )
                 {
-                    CPLSetXMLValue(psStyleRoot, "#xmlns", "http://undefined_namespace");
+                    CPLSetXMLValue(psStyleRoot, "#xmlns",
+                                   "http://undefined_namespace");
                 }
 
                 CPLAddXMLChild( psGMLJP2Style, CPLCloneXMLTree(psStyleRoot) );
@@ -2790,8 +3028,8 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
             CPLDestroyXMLNode(psStyle);
         }
 
-        // Add extensions
-        for( int i=0; i < (int)aoExtensions.size(); i++ )
+        // Add extensions.
+        for( int i = 0; i < static_cast<int>(aoExtensions.size()); ++i )
         {
             CPLXMLNode* psExtension = CPLParseXMLFile(aoExtensions[i].osFile);
             if( psExtension == NULL )
@@ -2803,26 +3041,34 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
                 CPLXMLNode *psGMLJP2Extension;
                 if( aoExtensions[i].bParentCoverageCollection )
                 {
-                    psGMLJP2Extension = CPLCreateXMLNode( psGMLJP2CoverageCollection, CXT_Element, "gmljp2:extension"  );
+                    psGMLJP2Extension =
+                        CPLCreateXMLNode( psGMLJP2CoverageCollection,
+                                          CXT_Element, "gmljp2:extension" );
                 }
                 else
                 {
                     CPLXMLNode* psFeatureMemberOfGridCoverage =
-                        CPLGetXMLNode(psGMLJP2CoverageCollection, "gmljp2:featureMember");
+                        CPLGetXMLNode(psGMLJP2CoverageCollection,
+                                      "gmljp2:featureMember");
                     CPLAssert(psFeatureMemberOfGridCoverage);
-                    CPLXMLNode* psGridCoverage = psFeatureMemberOfGridCoverage->psChild;
+                    CPLXMLNode* psGridCoverage =
+                        psFeatureMemberOfGridCoverage->psChild;
                     CPLAssert(psGridCoverage);
-                    psGMLJP2Extension = CPLCreateXMLNode( psGridCoverage, CXT_Element, "gmljp2:extension"  );
+                    psGMLJP2Extension =
+                        CPLCreateXMLNode( psGridCoverage,
+                                          CXT_Element, "gmljp2:extension" );
                 }
 
                 // Add dummy namespace for validation purposes if needed
                 if( strchr(psExtensionRoot->pszValue, ':') == NULL &&
                     CPLGetXMLValue(psExtensionRoot, "xmlns", NULL) == NULL )
                 {
-                    CPLSetXMLValue(psExtensionRoot, "#xmlns", "http://undefined_namespace");
+                    CPLSetXMLValue(psExtensionRoot, "#xmlns",
+                                   "http://undefined_namespace");
                 }
 
-                CPLAddXMLChild( psGMLJP2Extension, CPLCloneXMLTree(psExtensionRoot) );
+                CPLAddXMLChild( psGMLJP2Extension,
+                                CPLCloneXMLTree(psExtensionRoot) );
             }
             CPLDestroyXMLNode(psExtension);
         }
@@ -2851,7 +3097,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Add optional dictionary.                                        */
 /* -------------------------------------------------------------------- */
-    if( osDictBox.size() > 0 )
+    if( !osDictBox.empty() )
         apoGMLBoxes.push_back(
             GDALJP2Box::CreateLabelledXMLAssoc( "CRSDictionary.gml",
                                                 osDictBox ) );
@@ -2859,7 +3105,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Additional user specified boxes.                                */
 /* -------------------------------------------------------------------- */
-    for( int i=0; i < (int)aoBoxes.size(); i++ )
+    for( int i = 0; i < static_cast<int>(aoBoxes.size()); ++i )
     {
         GByte* pabyContent = NULL;
         if( VSIIngestFile( NULL, aoBoxes[i].osFile, &pabyContent, NULL, -1 ) )
@@ -2887,16 +3133,17 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 /* -------------------------------------------------------------------- */
 /*      Bundle gml.data boxes into an association.                      */
 /* -------------------------------------------------------------------- */
-    GDALJP2Box *poGMLData = GDALJP2Box::CreateAsocBox( (int)apoGMLBoxes.size(),
-                                                       &apoGMLBoxes[0]);
+    GDALJP2Box *poGMLData =
+        GDALJP2Box::CreateAsocBox( static_cast<int>(apoGMLBoxes.size()),
+                                   &apoGMLBoxes[0] );
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup working boxes.                                          */
 /* -------------------------------------------------------------------- */
-    for( int i=0; i < (int)apoGMLBoxes.size(); i++ )
+    for( int i = 0; i < static_cast<int>(apoGMLBoxes.size()); ++i )
         delete apoGMLBoxes[i];
 
-    for( int i=0; i < (int)aosTmpFiles.size(); i++ )
+    for( int i = 0; i < static_cast<int>(aosTmpFiles.size()); ++i )
     {
         VSIUnlink(aosTmpFiles[i]);
     }
@@ -2909,8 +3156,7 @@ GDALJP2Box *GDALJP2Metadata::CreateGMLJP2V2( int nXSize, int nYSize,
 /************************************************************************/
 
 CPLXMLNode* GDALJP2Metadata::CreateGDALMultiDomainMetadataXML(
-                                       GDALDataset* poSrcDS,
-                                       int bMainMDDomainOnly )
+    GDALDataset* poSrcDS, int bMainMDDomainOnly )
 {
     GDALMultiDomainMetadata oLocalMDMD;
     char** papszSrcMD = CSLDuplicate(poSrcDS->GetMetadata());
@@ -2940,10 +3186,12 @@ CPLXMLNode* GDALJP2Metadata::CreateGDALMultiDomainMetadataXML(
     {
         char** papszMDList = poSrcDS->GetMetadataDomainList();
         for( char** papszMDListIter = papszMDList;
-            papszMDListIter && *papszMDListIter; ++papszMDListIter )
+             papszMDListIter && *papszMDListIter;
+             ++papszMDListIter )
         {
             if( !EQUAL(*papszMDListIter, "") &&
                 !EQUAL(*papszMDListIter, "IMAGE_STRUCTURE") &&
+                !EQUAL(*papszMDListIter, "DERIVED_SUBDATASETS") &&
                 !EQUAL(*papszMDListIter, "JPEG2000") &&
                 !STARTS_WITH_CI(*papszMDListIter, "xml:BOX_") &&
                 !EQUAL(*papszMDListIter, "xml:gml.root-instance") &&
@@ -3006,7 +3254,8 @@ GDALJP2Box** GDALJP2Metadata::CreateXMLBoxes( GDALDataset* poSrcDS,
     *pnBoxes = 0;
     char** papszMDList = poSrcDS->GetMetadataDomainList();
     for( char** papszMDListIter = papszMDList;
-        papszMDListIter && *papszMDListIter; ++papszMDListIter )
+         papszMDListIter && *papszMDListIter;
+         ++papszMDListIter )
     {
         /* Write metadata that look like originating from JP2 XML boxes */
         /* as a standalone JP2 XML box */
@@ -3021,7 +3270,7 @@ GDALJP2Box** GDALJP2Metadata::CreateXMLBoxes( GDALDataset* poSrcDS,
                                        (const GByte*)*papszSrcMD);
                 papoBoxes = (GDALJP2Box**)CPLRealloc(papoBoxes,
                                         sizeof(GDALJP2Box*) * (*pnBoxes + 1));
-                papoBoxes[(*pnBoxes) ++] = poBox;
+                papoBoxes[(*pnBoxes)++] = poBox;
             }
         }
     }
@@ -3081,3 +3330,5 @@ int GDALJP2Metadata::IsUUID_XMP(const GByte *abyUUID)
 {
     return memcmp(abyUUID, xmp_uuid, 16) == 0;
 }
+
+/*! @endcond */
diff --git a/gcore/gdaljp2metadata.h b/gcore/gdaljp2metadata.h
index 8e80d90..95e6008 100644
--- a/gcore/gdaljp2metadata.h
+++ b/gcore/gdaljp2metadata.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2metadata.h 33694 2016-03-10 17:54:30Z goatbar $
+ * $Id: gdaljp2metadata.h 36411 2016-11-21 22:03:48Z rouault $
  *
  * Project:  GDAL
  * Purpose:  JP2 Box Reader (and GMLJP2 Interpreter)
@@ -31,6 +31,8 @@
 #ifndef GDAL_JP2READER_H_INCLUDED
 #define GDAL_JP2READER_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "cpl_conv.h"
 #include "cpl_minixml.h"
 #include "cpl_vsi.h"
@@ -58,7 +60,7 @@ class CPL_DLL GDALJP2Box
     GByte      *pabyData;
 
 public:
-                GDALJP2Box( VSILFILE * = NULL );
+    explicit    GDALJP2Box( VSILFILE * = NULL );
                 ~GDALJP2Box();
 
     int         SetOffset( GIntBig nNewOffset );
@@ -141,9 +143,9 @@ private:
 public:
     char  **papszGMLMetadata;
 
-    int     bHaveGeoTransform;
+    bool    bHaveGeoTransform;
     double  adfGeoTransform[6];
-    int     bPixelIsPoint;
+    bool    bPixelIsPoint;
 
     char   *pszProjection;
 
@@ -167,8 +169,12 @@ public:
     int     ParseMSIG();
     int     ParseGMLCoverageDesc();
 
-    int     ReadAndParse( VSILFILE * fpVSIL );
-    int     ReadAndParse( const char *pszFilename );
+    int     ReadAndParse( VSILFILE * fpVSIL,
+                          int nGEOJP2Index = 0, int nGMLJP2Index = 1,
+                          int nMSIGIndex = 2, int *pnIndexUsed = NULL );
+    int     ReadAndParse( const char *pszFilename, int nGEOJP2Index = 0,
+                          int nGMLJP2Index = 1, int nMSIGIndex = 2,
+                          int nWorldFileIndex = 3, int *pnIndexUsed = NULL );
 
     // Write oriented.
     void    SetProjection( const char *pszWKT );
@@ -193,4 +199,6 @@ public:
     static int   IsUUID_XMP(const GByte *abyUUID);
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* ndef GDAL_JP2READER_H_INCLUDED */
diff --git a/gcore/gdaljp2metadatagenerator.cpp b/gcore/gdaljp2metadatagenerator.cpp
index 1f9f6f5..77c6914 100644
--- a/gcore/gdaljp2metadatagenerator.cpp
+++ b/gcore/gdaljp2metadatagenerator.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaljp2metadatagenerator.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  GDALJP2Metadata: metadata generator
@@ -27,20 +26,30 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <vector>
+#include "cpl_port.h"
 #include "gdaljp2metadatagenerator.h"
 
-CPL_CVSID("$Id: gdaljp2metadatagenerator.cpp 33694 2016-03-10 17:54:30Z goatbar $");
+#include <cstddef>
 
-//#define ENABLE_BRAIN_DAMAGE
+CPL_CVSID("$Id: gdaljp2metadatagenerator.cpp 36759 2016-12-09 16:15:51Z goatbar $");
 
 #ifdef HAVE_LIBXML2
 
-#include <libxml/tree.h>
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
+
 #include <libxml/parser.h>
+#include <libxml/tree.h>
 #include <libxml/xpath.h>
 #include <libxml/xpathInternals.h>
 
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
 /************************************************************************/
 /*                            GDALGMLJP2Expr                            */
 /************************************************************************/
@@ -50,100 +59,57 @@ typedef enum
     GDALGMLJP2Expr_Unknown,
     GDALGMLJP2Expr_XPATH,
     GDALGMLJP2Expr_STRING_LITERAL,
-#ifdef ENABLE_BRAIN_DAMAGE
-    GDALGMLJP2Expr_NUMERIC_LITERAL,
-    GDALGMLJP2Expr_ADD,
-    GDALGMLJP2Expr_SUB,
-    GDALGMLJP2Expr_NOT,
-    GDALGMLJP2Expr_AND,
-    GDALGMLJP2Expr_OR,
-    GDALGMLJP2Expr_EQ,
-    GDALGMLJP2Expr_NEQ,
-    GDALGMLJP2Expr_LT,
-    GDALGMLJP2Expr_LE,
-    GDALGMLJP2Expr_GT,
-    GDALGMLJP2Expr_GE,
-    GDALGMLJP2Expr_IF,
-    GDALGMLJP2Expr_CONCAT,
-    GDALGMLJP2Expr_EVAL,
-    GDALGMLJP2Expr_CAST_TO_STRING,
-    GDALGMLJP2Expr_CAST_TO_NUMERIC,
-    GDALGMLJP2Expr_SUBSTRING,
-    GDALGMLJP2Expr_SUBSTRING_BEFORE,
-    GDALGMLJP2Expr_SUBSTRING_AFTER,
-    GDALGMLJP2Expr_STRING_LENGTH,
-    GDALGMLJP2Expr_UUID
-#endif
 } GDALGMLJP2ExprType;
 
-// {{{IF(EQ(XPATH(), '5'), '', '')}}}
-
 class GDALGMLJP2Expr
 {
-        static void             SkipSpaces(const char*& pszStr);
-        static GDALGMLJP2Expr*  BuildNaryOp(const char* pszOriStr,
-                                            const char*& pszStr, int nary);
-
-    public:
-        GDALGMLJP2ExprType           eType;
-        CPLString                    osValue;
-#ifdef ENABLE_BRAIN_DAMAGE
-        std::vector<GDALGMLJP2Expr*> apoSubExpr;
-#endif
-
-                                GDALGMLJP2Expr(): eType(GDALGMLJP2Expr_Unknown) {}
-                                GDALGMLJP2Expr(const char* pszVal): eType(GDALGMLJP2Expr_STRING_LITERAL), osValue(pszVal) {}
-                                GDALGMLJP2Expr(CPLString osVal): eType(GDALGMLJP2Expr_STRING_LITERAL), osValue(osVal) {}
-#ifdef ENABLE_BRAIN_DAMAGE
-                                GDALGMLJP2Expr(bool b): eType(GDALGMLJP2Expr_STRING_LITERAL), osValue(b ? "true" : "false") {}
-#endif
-                               ~GDALGMLJP2Expr();
-
-        GDALGMLJP2Expr          Evaluate(xmlXPathContextPtr pXPathCtx,
-                                         xmlDocPtr pDoc);
-
-        static GDALGMLJP2Expr*  Build(const char* pszOriStr,
-                                      const char*& pszStr);
-        static void             ReportError(const char* pszOriStr,
-                                            const char* pszStr,
-                                            const char* pszIntroMessage = "Parsing error at:\n");
+    static void SkipSpaces( const char*& pszStr );
+
+  public:
+    GDALGMLJP2ExprType           eType;
+    CPLString                    osValue;
+
+    GDALGMLJP2Expr() : eType(GDALGMLJP2Expr_Unknown) {}
+    GDALGMLJP2Expr( const char* pszVal ) :
+        eType(GDALGMLJP2Expr_STRING_LITERAL), osValue(pszVal) {}
+    GDALGMLJP2Expr( CPLString osVal ) :
+        eType(GDALGMLJP2Expr_STRING_LITERAL), osValue(osVal) {}
+    ~GDALGMLJP2Expr() {};
+
+    GDALGMLJP2Expr          Evaluate( xmlXPathContextPtr pXPathCtx,
+                                      xmlDocPtr pDoc );
+
+    static GDALGMLJP2Expr* Build( const char* pszOriStr,
+                                  const char*& pszStr );
+    static void ReportError( const char* pszOriStr,
+                             const char* pszStr,
+                             const char* pszIntroMessage =
+                                 "Parsing error at:\n" );
 };
 
 /************************************************************************/
-/*                             Build()                                  */
-/************************************************************************/
-
-GDALGMLJP2Expr::~GDALGMLJP2Expr()
-{
-#ifdef ENABLE_BRAIN_DAMAGE
-    for(size_t i=0;i<apoSubExpr.size();i++)
-        delete apoSubExpr[i];
-#endif
-}
-
-/************************************************************************/
-/*                             Build()                                  */
+/*                         ReportError()                                */
 /************************************************************************/
 
-void GDALGMLJP2Expr::ReportError(const char* pszOriStr,
-                                 const char* pszStr,
-                                 const char* pszIntroMessage)
+void GDALGMLJP2Expr::ReportError( const char* pszOriStr,
+                                  const char* pszStr,
+                                  const char* pszIntroMessage )
 {
-    size_t nDist = (size_t)(pszStr - pszOriStr);
+    size_t nDist = static_cast<size_t>(pszStr - pszOriStr);
     if( nDist > 40 )
         nDist = 40;
     CPLString osErrMsg(pszIntroMessage);
     CPLString osInvalidExpr = CPLString(pszStr - nDist).substr(0, nDist + 20);
-    for(int i=(int)nDist-1;i>=0;i--)
+    for( int i = static_cast<int>(nDist) - 1; i >= 0; --i )
     {
         if( osInvalidExpr[i] == '\n' )
         {
             osInvalidExpr = osInvalidExpr.substr(i+1);
-            nDist -= i+1;
+            nDist -= i + 1;
             break;
         }
     }
-    for(size_t i=nDist;i<osInvalidExpr.size();i++)
+    for( size_t i = nDist; i < osInvalidExpr.size(); ++i )
     {
         if( osInvalidExpr[i] == '\n' )
         {
@@ -153,97 +119,29 @@ void GDALGMLJP2Expr::ReportError(const char* pszOriStr,
     }
     osErrMsg += osInvalidExpr;
     osErrMsg += "\n";
-    for(size_t i=0;i<nDist;i++)
+    for( size_t i = 0; i < nDist; ++i )
         osErrMsg += " ";
     osErrMsg += "^";
     CPLError(CE_Failure, CPLE_AppDefined, "%s", osErrMsg.c_str());
 }
 
 /************************************************************************/
-/*                             Build()                                  */
+/*                        SkipSpaces()                                  */
 /************************************************************************/
 
-void GDALGMLJP2Expr::SkipSpaces(const char*& pszStr)
+void GDALGMLJP2Expr::SkipSpaces( const char*& pszStr )
 {
-    while( *pszStr == ' ' || *pszStr == '\t' || *pszStr == '\r' || *pszStr ==  '\n' )
-        pszStr ++;
+    while( *pszStr == ' ' || *pszStr == '\t' ||
+           *pszStr == '\r' || *pszStr ==  '\n' )
+        ++pszStr;
 }
 
-#ifdef ENABLE_BRAIN_DAMAGE
-
 /************************************************************************/
 /*                             Build()                                  */
 /************************************************************************/
 
-GDALGMLJP2Expr* GDALGMLJP2Expr::BuildNaryOp(const char* pszOriStr,
-                                            const char*& pszStr, int nary)
-{
-    GDALGMLJP2Expr* poExpr = new GDALGMLJP2Expr();
-
-    SkipSpaces(pszStr);
-    if( *pszStr != '(' )
-    {
-        ReportError(pszOriStr, pszStr);
-        delete poExpr;
-        return NULL;
-    }
-    pszStr ++;
-    SkipSpaces(pszStr);
-    for( int i=0;nary < 0 || i<nary;i++)
-    {
-        GDALGMLJP2Expr* poSubExpr = Build(pszOriStr, pszStr);
-        if( poSubExpr == NULL )
-        {
-            delete poExpr;
-            return NULL;
-        }
-        SkipSpaces(pszStr);
-        poExpr->apoSubExpr.push_back(poSubExpr);
-        if( nary < 0 && *pszStr == ')' )
-        {
-            break;
-        }
-        else if( nary < 0 || i < nary - 1 )
-        {
-            if( *pszStr != ',' )
-            {
-                ReportError(pszOriStr, pszStr);
-                delete poExpr;
-                return NULL;
-            }
-            pszStr ++;
-            SkipSpaces(pszStr);
-        }
-    }
-    if( *pszStr != ')' )
-    {
-        ReportError(pszOriStr, pszStr);
-        delete poExpr;
-        return NULL;
-    }
-    pszStr ++;
-    return poExpr;
-}
-
-#endif // ENABLE_BRAIN_DAMAGE
-
-/************************************************************************/
-/*                             Build()                                  */
-/************************************************************************/
-
-#ifdef ENABLE_BRAIN_DAMAGE
-
-typedef struct
-{
-    const char*        pszOp;
-    GDALGMLJP2ExprType eType;
-    int                nary;
-} GDALGMLJP2Operators;
-
-#endif
-
-GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
-                                      const char*& pszStr)
+GDALGMLJP2Expr* GDALGMLJP2Expr::Build( const char* pszOriStr,
+                                       const char*& pszStr )
 {
     if( STARTS_WITH_CI(pszStr, "{{{") )
     {
@@ -271,7 +169,7 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
             ReportError(pszOriStr, pszStr);
             return NULL;
         }
-        pszStr ++;
+        ++pszStr;
         SkipSpaces(pszStr);
         CPLString l_osValue;
         int nParenthesisIndent = 0;
@@ -283,19 +181,19 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
                 if( *pszStr == chLiteralQuote )
                     chLiteralQuote = '\0';
                 l_osValue += *pszStr;
-                pszStr++;
+                ++pszStr;
             }
             else if( *pszStr == '\'' || *pszStr == '"' )
             {
                 chLiteralQuote = *pszStr;
                 l_osValue += *pszStr;
-                pszStr++;
+                ++pszStr;
             }
             else if( *pszStr == '(' )
             {
-                nParenthesisIndent ++;
+                ++nParenthesisIndent;
                 l_osValue += *pszStr;
-                pszStr++;
+                ++pszStr;
             }
             else if( *pszStr == ')' )
             {
@@ -306,11 +204,14 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
                     GDALGMLJP2Expr* poExpr = new GDALGMLJP2Expr();
                     poExpr->eType = GDALGMLJP2Expr_XPATH;
                     poExpr->osValue = l_osValue;
-                    //CPLDebug("GMLJP2", "XPath expression '%s'", l_osValue.c_str());
+#if DEBUG_VERBOSE
+                    CPLDebug("GMLJP2", "XPath expression '%s'",
+                             l_osValue.c_str());
+#endif
                     return poExpr;
                 }
                 l_osValue += *pszStr;
-                pszStr++;
+                ++pszStr;
             }
             else
             {
@@ -321,144 +222,18 @@ GDALGMLJP2Expr* GDALGMLJP2Expr::Build(const char* pszOriStr,
         ReportError(pszOriStr, pszStr);
         return NULL;
     }
-#ifdef ENABLE_BRAIN_DAMAGE
-    else if( pszStr[0] == '\'' )
-    {
-        pszStr ++;
-        CPLString l_osValue;
-        while( *pszStr )
-        {
-            if( *pszStr == '\\' )
-            {
-                if( pszStr[1] == '\\' )
-                    l_osValue += "\\";
-                else if( pszStr[1] == '\'' )
-                    l_osValue += "\'";
-                else
-                {
-                    ReportError(pszOriStr, pszStr);
-                    return NULL;
-                }
-                pszStr += 2;
-            }
-            else if( *pszStr == '\'' )
-            {
-                pszStr ++;
-                GDALGMLJP2Expr* poExpr = new GDALGMLJP2Expr();
-                poExpr->eType = GDALGMLJP2Expr_STRING_LITERAL;
-                poExpr->osValue = l_osValue;
-                return poExpr;
-            }
-            else
-            {
-                l_osValue += *pszStr;
-                pszStr ++;
-            }
-        }
-        ReportError(pszOriStr, pszStr);
-        return NULL;
-    }
-    else if( pszStr[0] == '-' || pszStr[0] == '.'||
-             (pszStr[0] >= '0' && pszStr[0] <= '9') )
-    {
-        CPLString osValue;
-        while( *pszStr )
-        {
-            if( *pszStr == ' ' || *pszStr == ')' || *pszStr == ',' || *pszStr == '}' )
-            {
-                GDALGMLJP2Expr* poExpr = new GDALGMLJP2Expr();
-                poExpr->eType = GDALGMLJP2Expr_NUMERIC_LITERAL;
-                poExpr->osValue = osValue;
-                return poExpr;
-            }
-            osValue += *pszStr;
-            pszStr ++;
-        }
-        ReportError(pszOriStr, pszStr);
-        return NULL;
-    }
-    else
-    {
-        static const GDALGMLJP2Operators asOperators[] =
-        {
-            { "IF", GDALGMLJP2Expr_IF, 3 },
-            { "ADD", GDALGMLJP2Expr_ADD, 2 },
-            { "AND", GDALGMLJP2Expr_AND, 2 },
-            { "OR", GDALGMLJP2Expr_OR, 2 },
-            { "NOT", GDALGMLJP2Expr_NOT, 1 },
-            { "EQ", GDALGMLJP2Expr_EQ, 2 },
-            { "NEQ", GDALGMLJP2Expr_NEQ, 2 },
-            { "LT", GDALGMLJP2Expr_LT, 2 },
-            { "LE", GDALGMLJP2Expr_LE, 2 },
-            { "GT", GDALGMLJP2Expr_GT, 2 },
-            { "GE", GDALGMLJP2Expr_GE, 2 },
-            { "CONCAT", GDALGMLJP2Expr_CONCAT, -1 },
-            { "NUMERIC", GDALGMLJP2Expr_CAST_TO_NUMERIC, 1 },
-            { "STRING_LENGTH", GDALGMLJP2Expr_STRING_LENGTH, 1 },
-            { "STRING", GDALGMLJP2Expr_CAST_TO_STRING, 1 }, /* must be after */
-            { "SUBSTRING_BEFORE", GDALGMLJP2Expr_SUBSTRING_BEFORE, 2 },
-            { "SUBSTRING_AFTER", GDALGMLJP2Expr_SUBSTRING_AFTER, 2 },
-            { "SUBSTRING", GDALGMLJP2Expr_SUBSTRING, 3 }, /* must be after */
-            { "SUB", GDALGMLJP2Expr_SUB, 2 }, /* must be after */
-            { "UUID", GDALGMLJP2Expr_UUID, 0},
-            { "EVAL", GDALGMLJP2Expr_EVAL, 1}
-        };
-        for(size_t i=0; i<sizeof(asOperators)/sizeof(asOperators[0]);i++)
-        {
-            const char* pszOp = asOperators[i].pszOp;
-            if( EQUALN(pszStr, pszOp, strlen(pszOp)) )
-            {
-                pszStr += strlen(pszOp);
-                GDALGMLJP2Expr* poExpr = BuildNaryOp(pszOriStr, pszStr, asOperators[i].nary);
-                if( poExpr )
-                {
-                    if( asOperators[i].eType == GDALGMLJP2Expr_NEQ )
-                    {
-                        poExpr->eType = GDALGMLJP2Expr_EQ;
-                        GDALGMLJP2Expr* poTopExpr = new GDALGMLJP2Expr();
-                        poTopExpr->eType = GDALGMLJP2Expr_NOT;
-                        poTopExpr->apoSubExpr.push_back(poExpr);
-                        poExpr = poTopExpr;
-                    }
-                    else if( asOperators[i].eType == GDALGMLJP2Expr_GT )
-                    {
-                        poExpr->eType = GDALGMLJP2Expr_LE;
-                        GDALGMLJP2Expr* poTopExpr = new GDALGMLJP2Expr();
-                        poTopExpr->eType = GDALGMLJP2Expr_NOT;
-                        poTopExpr->apoSubExpr.push_back(poExpr);
-                        poExpr = poTopExpr;
-                    }
-                    else if( asOperators[i].eType == GDALGMLJP2Expr_GE )
-                    {
-                        poExpr->eType = GDALGMLJP2Expr_LT;
-                        GDALGMLJP2Expr* poTopExpr = new GDALGMLJP2Expr();
-                        poTopExpr->eType = GDALGMLJP2Expr_NOT;
-                        poTopExpr->apoSubExpr.push_back(poExpr);
-                        poExpr = poTopExpr;
-                    }
-                    else
-                        poExpr->eType = asOperators[i].eType;
-                }
-                return poExpr;
-            }
-        }
-        ReportError(pszOriStr, pszStr);
-        return NULL;
-    }
-#else
     else
     {
         ReportError(pszOriStr, pszStr);
         return NULL;
     }
-#endif
 }
 
 /************************************************************************/
 /*                       GDALGMLJP2HexFormatter()                       */
 /************************************************************************/
 
-static const char* GDALGMLJP2HexFormatter(GByte nVal)
+static const char* GDALGMLJP2HexFormatter( GByte nVal )
 {
     return CPLSPrintf("%02X", nVal);
 }
@@ -467,21 +242,15 @@ static const char* GDALGMLJP2HexFormatter(GByte nVal)
 /*                            Evaluate()                                */
 /************************************************************************/
 
-static CPLString GDALGMLJP2EvalExpr(const CPLString& osTemplate,
-                                    xmlXPathContextPtr pXPathCtx,
-                                    xmlDocPtr pDoc);
+static CPLString GDALGMLJP2EvalExpr( const CPLString& osTemplate,
+                                     xmlXPathContextPtr pXPathCtx,
+                                     xmlDocPtr pDoc );
 
 GDALGMLJP2Expr GDALGMLJP2Expr::Evaluate(xmlXPathContextPtr pXPathCtx,
                                    xmlDocPtr pDoc)
 {
-    switch(eType)
+    switch( eType )
     {
-#ifdef ENABLE_BRAIN_DAMAGE
-        case GDALGMLJP2Expr_STRING_LITERAL:
-        case GDALGMLJP2Expr_NUMERIC_LITERAL:
-            return *this;
-#endif
-
         case GDALGMLJP2Expr_XPATH:
         {
             xmlXPathObjectPtr pXPathObj = xmlXPathEvalExpression(
@@ -489,7 +258,7 @@ GDALGMLJP2Expr GDALGMLJP2Expr::Evaluate(xmlXPathContextPtr pXPathCtx,
             if( pXPathObj == NULL )
                 return GDALGMLJP2Expr("");
 
-            // Add result of the evaluation
+            // Add result of the evaluation.
             CPLString osXMLRes;
             if( pXPathObj->type == XPATH_STRING )
                 osXMLRes = (const char*)pXPathObj->stringval;
@@ -515,207 +284,8 @@ GDALGMLJP2Expr GDALGMLJP2Expr::Evaluate(xmlXPathContextPtr pXPathCtx,
             xmlXPathFreeObject(pXPathObj);
             return GDALGMLJP2Expr(osXMLRes);
         }
-#ifdef ENABLE_BRAIN_DAMAGE
-        case GDALGMLJP2Expr_AND:
-        {
-            return GDALGMLJP2Expr(
-                apoSubExpr[0]->Evaluate(pXPathCtx,pDoc).osValue == "true" &&
-                apoSubExpr[1]->Evaluate(pXPathCtx,pDoc).osValue == "true" );
-        }
-
-        case GDALGMLJP2Expr_OR:
-        {
-            return GDALGMLJP2Expr(
-                apoSubExpr[0]->Evaluate(pXPathCtx,pDoc).osValue == "true" ||
-                apoSubExpr[1]->Evaluate(pXPathCtx,pDoc).osValue == "true" );
-        }
-
-        case GDALGMLJP2Expr_NOT:
-        {
-            return GDALGMLJP2Expr(
-                apoSubExpr[0]->Evaluate(pXPathCtx,pDoc).osValue != "true");
-        }
-
-        case GDALGMLJP2Expr_ADD:
-        {
-            const GDALGMLJP2Expr& oExpr1 = apoSubExpr[0]->Evaluate(pXPathCtx,pDoc);
-            const GDALGMLJP2Expr& oExpr2 = apoSubExpr[1]->Evaluate(pXPathCtx,pDoc);
-            GDALGMLJP2Expr oExpr(CPLSPrintf("%.16g", CPLAtof(oExpr1.osValue) + CPLAtof(oExpr2.osValue)));
-            oExpr.eType = GDALGMLJP2Expr_NUMERIC_LITERAL;
-            return oExpr;
-        }
-
-        case GDALGMLJP2Expr_SUB:
-        {
-            const GDALGMLJP2Expr& oExpr1 = apoSubExpr[0]->Evaluate(pXPathCtx,pDoc);
-            const GDALGMLJP2Expr& oExpr2 = apoSubExpr[1]->Evaluate(pXPathCtx,pDoc);
-            GDALGMLJP2Expr oExpr(CPLSPrintf("%.16g", CPLAtof(oExpr1.osValue) - CPLAtof(oExpr2.osValue)));
-            oExpr.eType = GDALGMLJP2Expr_NUMERIC_LITERAL;
-            return oExpr;
-        }
-
-        case GDALGMLJP2Expr_EQ:
-        {
-            const GDALGMLJP2Expr& oExpr1 = apoSubExpr[0]->Evaluate(pXPathCtx,pDoc);
-            const GDALGMLJP2Expr& oExpr2 = apoSubExpr[1]->Evaluate(pXPathCtx,pDoc);
-            bool bRes;
-            if( oExpr1.eType == GDALGMLJP2Expr_NUMERIC_LITERAL &&
-                oExpr2.eType == GDALGMLJP2Expr_NUMERIC_LITERAL )
-            {
-                bRes = ( CPLAtof(oExpr1.osValue) == CPLAtof(oExpr2.osValue) );
-            }
-            else
-            {
-                bRes = (oExpr1.osValue == oExpr2.osValue );
-            }
-            return GDALGMLJP2Expr(bRes);
-        }
-
-        case GDALGMLJP2Expr_LT:
-        {
-            const GDALGMLJP2Expr& oExpr1 = apoSubExpr[0]->Evaluate(pXPathCtx,pDoc);
-            const GDALGMLJP2Expr& oExpr2 = apoSubExpr[1]->Evaluate(pXPathCtx,pDoc);
-            bool bRes;
-            if( oExpr1.eType == GDALGMLJP2Expr_NUMERIC_LITERAL &&
-                oExpr2.eType == GDALGMLJP2Expr_NUMERIC_LITERAL )
-            {
-                bRes = ( CPLAtof(oExpr1.osValue) < CPLAtof(oExpr2.osValue) );
-            }
-            else
-            {
-                bRes = (oExpr1.osValue < oExpr2.osValue );
-            }
-            return GDALGMLJP2Expr(bRes);
-        }
-
-        case GDALGMLJP2Expr_LE:
-        {
-            const GDALGMLJP2Expr& oExpr1 = apoSubExpr[0]->Evaluate(pXPathCtx,pDoc);
-            const GDALGMLJP2Expr& oExpr2 = apoSubExpr[1]->Evaluate(pXPathCtx,pDoc);
-            bool bRes;
-            if( oExpr1.eType == GDALGMLJP2Expr_NUMERIC_LITERAL &&
-                oExpr2.eType == GDALGMLJP2Expr_NUMERIC_LITERAL )
-            {
-                bRes = ( CPLAtof(oExpr1.osValue) <= CPLAtof(oExpr2.osValue) );
-            }
-            else
-            {
-                bRes = (oExpr1.osValue <= oExpr2.osValue );
-            }
-            return GDALGMLJP2Expr(bRes);
-        }
-
-        case GDALGMLJP2Expr_IF:
-        {
-            if( apoSubExpr[0]->Evaluate(pXPathCtx,pDoc).osValue == "true" )
-                return apoSubExpr[1]->Evaluate(pXPathCtx,pDoc);
-            else
-                return apoSubExpr[2]->Evaluate(pXPathCtx,pDoc);
-        }
-
-        case GDALGMLJP2Expr_EVAL:
-        {
-            return GDALGMLJP2Expr(
-                GDALGMLJP2EvalExpr(apoSubExpr[0]->Evaluate(pXPathCtx,pDoc).osValue,pXPathCtx,pDoc));
-        }
-
-        case GDALGMLJP2Expr_CONCAT:
-        {
-            CPLString osRet;
-            for(size_t i=0;i<apoSubExpr.size();i++)
-                osRet += apoSubExpr[i]->Evaluate(pXPathCtx,pDoc).osValue;
-            return GDALGMLJP2Expr(osRet);
-        }
-
-        case GDALGMLJP2Expr_CAST_TO_NUMERIC:
-        {
-            GDALGMLJP2Expr oExpr = CPLSPrintf("%.16g", CPLAtof(apoSubExpr[0]->Evaluate(pXPathCtx,pDoc).osValue));
-            oExpr.eType = GDALGMLJP2Expr_NUMERIC_LITERAL;
-            return oExpr;
-        }
-
-        case GDALGMLJP2Expr_CAST_TO_STRING:
-        {
-            GDALGMLJP2Expr oExpr = apoSubExpr[0]->Evaluate(pXPathCtx,pDoc).osValue;
-            oExpr.eType = GDALGMLJP2Expr_STRING_LITERAL;
-            return oExpr;
-        }
-
-        case GDALGMLJP2Expr_UUID:
-        {
-            CPLString osRet;
-            static int nCounter = 0;
-            srand((unsigned int)time(NULL) + nCounter);
-            nCounter ++;
-            for( int i=0; i<4; i ++ )
-                osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
-            osRet += "-";
-            osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
-            osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
-            osRet += "-";
-            osRet += GDALGMLJP2HexFormatter((rand() & 0x0F) | 0x40); // set the version number bits (4 == random)
-            osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
-            osRet += "-";
-            osRet += GDALGMLJP2HexFormatter((rand() & 0x3F) | 0x80); // set the variant bits
-            osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
-            osRet += "-";
-            for( int i=0; i<6; i ++ )
-                osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
-            return GDALGMLJP2Expr(osRet);
-        }
-
-        case GDALGMLJP2Expr_STRING_LENGTH:
-        {
-            GDALGMLJP2Expr oExpr(CPLSPrintf("%d",
-                (int)strlen(apoSubExpr[0]->Evaluate(pXPathCtx,pDoc).osValue)));
-            oExpr.eType = GDALGMLJP2Expr_NUMERIC_LITERAL;
-            return oExpr;
-        }
-
-        case GDALGMLJP2Expr_SUBSTRING:
-        {
-            const GDALGMLJP2Expr& oExpr1 = apoSubExpr[0]->Evaluate(pXPathCtx,pDoc);
-            const GDALGMLJP2Expr& oExpr2 = apoSubExpr[1]->Evaluate(pXPathCtx,pDoc);
-            const GDALGMLJP2Expr& oExpr3 = apoSubExpr[2]->Evaluate(pXPathCtx,pDoc);
-            int nStart = atoi(oExpr2.osValue);
-            int nLen = atoi(oExpr3.osValue);
-            nStart --; /* from XPath/SQL convention to C convention */
-            if( nStart < 0 )
-            {
-                nLen += nStart;
-                nStart = 0;
-            }
-            if( nLen < 0 )
-                return GDALGMLJP2Expr("");
-            if( nStart >= (int)oExpr1.osValue.size() )
-                return GDALGMLJP2Expr("");
-            if( nStart + nLen > (int)oExpr1.osValue.size() )
-                nLen = (int)oExpr1.osValue.size() - nStart;
-            return GDALGMLJP2Expr(oExpr1.osValue.substr(nStart, nLen));
-        }
-
-        case GDALGMLJP2Expr_SUBSTRING_BEFORE:
-        {
-            const GDALGMLJP2Expr& oExpr1 = apoSubExpr[0]->Evaluate(pXPathCtx,pDoc);
-            const GDALGMLJP2Expr& oExpr2 = apoSubExpr[1]->Evaluate(pXPathCtx,pDoc);
-            size_t nPos = oExpr1.osValue.find(oExpr2.osValue);
-            if( nPos == std::string::npos )
-                return GDALGMLJP2Expr("");
-            return GDALGMLJP2Expr(oExpr1.osValue.substr(0, nPos));
-        }
-
-        case GDALGMLJP2Expr_SUBSTRING_AFTER:
-        {
-            const GDALGMLJP2Expr& oExpr1 = apoSubExpr[0]->Evaluate(pXPathCtx,pDoc);
-            const GDALGMLJP2Expr& oExpr2 = apoSubExpr[1]->Evaluate(pXPathCtx,pDoc);
-            size_t nPos = oExpr1.osValue.find(oExpr2.osValue);
-            if( nPos == std::string::npos )
-                return GDALGMLJP2Expr("");
-            return GDALGMLJP2Expr(oExpr1.osValue.substr(nPos + oExpr2.osValue.size()));
-        }
-#endif
         default:
-            CPLAssert(FALSE);
+            CPLAssert(false);
             return GDALGMLJP2Expr("");
     }
 }
@@ -732,16 +302,16 @@ static CPLString GDALGMLJP2EvalExpr(const CPLString& osTemplate,
     size_t nPos = 0;
     while( true )
     {
-        // Get next expression
+        // Get next expression.
         size_t nStartPos = osTemplate.find("{{{", nPos);
         if( nStartPos == std::string::npos)
         {
-            // Add terminating portion of the template
+            // Add terminating portion of the template.
             osXMLRes += osTemplate.substr(nPos);
             break;
         }
 
-        // Add portion of template before the expression
+        // Add portion of template before the expression.
         osXMLRes += osTemplate.substr(nPos, nStartPos - nPos);
 
         const char* pszExpr = osTemplate.c_str() + nStartPos;
@@ -759,8 +329,8 @@ static CPLString GDALGMLJP2EvalExpr(const CPLString& osTemplate,
 /*                      GDALGMLJP2XPathErrorHandler()                   */
 /************************************************************************/
 
-static void GDALGMLJP2XPathErrorHandler(CPL_UNUSED void * userData,
-                                        xmlErrorPtr error)
+static void GDALGMLJP2XPathErrorHandler( void * /* userData */,
+                                         xmlErrorPtr error)
 {
     if( error->domain == XML_FROM_XPATH &&
         error->str1 != NULL &&
@@ -840,60 +410,58 @@ static void GDALGMLJP2XPathUUID(xmlXPathParserContextPtr ctxt, int nargs)
 
     CPLString osRet;
     static int nCounter = 0;
-    srand((unsigned int)time(NULL) + nCounter);
-    nCounter ++;
+    srand(static_cast<unsigned int>(time(NULL)) + nCounter);
+    ++nCounter;
     for( int i=0; i<4; i ++ )
         osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
     osRet += "-";
     osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
     osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
     osRet += "-";
-    osRet += GDALGMLJP2HexFormatter((rand() & 0x0F) | 0x40); // set the version number bits (4 == random)
+    // Set the version number bits (4 == random).
+    osRet += GDALGMLJP2HexFormatter((rand() & 0x0F) | 0x40);
     osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
     osRet += "-";
-    osRet += GDALGMLJP2HexFormatter((rand() & 0x3F) | 0x80); // set the variant bits
+    // Set the variant bits.
+    osRet += GDALGMLJP2HexFormatter((rand() & 0x3F) | 0x80);
     osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
     osRet += "-";
-    for( int i=0; i<6; i ++ )
+    for( int i = 0; i < 6; ++i )
     {
-        /* coverity[dont_call] */
+        // coverity[dont_call]
         osRet += GDALGMLJP2HexFormatter(rand() & 0xFF);
     }
 
-    valuePush(ctxt, xmlXPathNewString((const xmlChar*)osRet.c_str()));
+    valuePush(ctxt,
+              xmlXPathNewString(
+                  reinterpret_cast<const xmlChar *>(osRet.c_str())));
 }
 
-#endif /* defined(LIBXML2) */
+#endif  // LIBXML2
 
 /************************************************************************/
 /*                      GDALGMLJP2GenerateMetadata()                    */
 /************************************************************************/
 
-CPLXMLNode* GDALGMLJP2GenerateMetadata(
 #ifdef HAVE_LIBXML2
+CPLXMLNode* GDALGMLJP2GenerateMetadata(
     const CPLString& osTemplateFile,
     const CPLString& osSourceFile
-#else
-    const CPLString& /* osTemplateFile */,
-    const CPLString& /* osSourceFile */
-#endif
 )
 {
-#ifndef HAVE_LIBXML2
-    return NULL;
-#else
     GByte* pabyStr = NULL;
     if( !VSIIngestFile( NULL, osTemplateFile, &pabyStr, NULL, -1 ) )
         return NULL;
-    CPLString osTemplate((const char*)pabyStr);
+    CPLString osTemplate(reinterpret_cast<char *>(pabyStr));
     CPLFree(pabyStr);
 
     if( !VSIIngestFile( NULL, osSourceFile, &pabyStr, NULL, -1 ) )
         return NULL;
-    CPLString osSource((const char*)pabyStr);
+    CPLString osSource(reinterpret_cast<char *>(pabyStr));
     CPLFree(pabyStr);
 
-    xmlDocPtr pDoc = xmlParseDoc((const xmlChar *)osSource.c_str());
+    xmlDocPtr pDoc = xmlParseDoc(
+        reinterpret_cast<const xmlChar *>(osSource.c_str()));
     if( pDoc == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot parse %s",
@@ -908,8 +476,10 @@ CPLXMLNode* GDALGMLJP2GenerateMetadata(
         return NULL;
     }
 
-    xmlXPathRegisterFunc(pXPathCtx, (const xmlChar *)"if", GDALGMLJP2XPathIf);
-    xmlXPathRegisterFunc(pXPathCtx, (const xmlChar *)"uuid", GDALGMLJP2XPathUUID);
+    xmlXPathRegisterFunc(pXPathCtx, reinterpret_cast<const xmlChar *>("if"),
+                         GDALGMLJP2XPathIf);
+    xmlXPathRegisterFunc(pXPathCtx, reinterpret_cast<const xmlChar *>("uuid"),
+                         GDALGMLJP2XPathUUID);
 
     pXPathCtx->error = GDALGMLJP2XPathErrorHandler;
 
@@ -921,5 +491,13 @@ CPLXMLNode* GDALGMLJP2GenerateMetadata(
     xmlFreeDoc(pDoc);
 
     return CPLParseXMLString(osXMLRes);
-#endif
 }
+#else  // !HAVE_LIBXML2
+CPLXMLNode* GDALGMLJP2GenerateMetadata(
+    const CPLString&  /* osTemplateFile */,
+    const CPLString&  /* osSourceFile */
+)
+{
+    return NULL;
+}
+#endif  // HAVE_LIBXML2
diff --git a/gcore/gdaljp2metadatagenerator.h b/gcore/gdaljp2metadatagenerator.h
index bf7faf0..474c0f8 100644
--- a/gcore/gdaljp2metadatagenerator.h
+++ b/gcore/gdaljp2metadatagenerator.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdaljp2metadatagenerator.h 33694 2016-03-10 17:54:30Z goatbar $
+ * $Id: gdaljp2metadatagenerator.h 35883 2016-10-24 05:49:15Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  GDALJP2Metadata: metadata generator
@@ -30,7 +30,6 @@
 #ifndef GDAL_JP2METADATA_GENERATOR_H_INCLUDED
 #define GDAL_JP2METADATA_GENERATOR_H_INCLUDED
 
-
 #include "cpl_string.h"
 #include "cpl_minixml.h"
 
diff --git a/gcore/gdaljp2structure.cpp b/gcore/gdaljp2structure.cpp
index dac6edb..94227ec 100644
--- a/gcore/gdaljp2structure.cpp
+++ b/gcore/gdaljp2structure.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaljp2structure.cpp 33581 2016-02-27 07:27:13Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  GDALJP2Stucture - Dump structure of a JP2/J2K file
@@ -27,8 +26,25 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdaljp2metadata.h"
 
+#include <cmath>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+
 static void AddField(CPLXMLNode* psParent, const char* pszFieldName,
                      int nFieldSize, const char* pszValue,
                      const char* pszDescription = NULL)
@@ -37,7 +53,7 @@ static void AddField(CPLXMLNode* psParent, const char* pszFieldName,
                                     psParent, "Field", pszValue );
     CPLAddXMLAttributeAndValue(psField, "name", pszFieldName );
     CPLAddXMLAttributeAndValue(psField, "type", "string" );
-    CPLAddXMLAttributeAndValue(psField, "size", CPLSPrintf("%d", nFieldSize )  );
+    CPLAddXMLAttributeAndValue(psField, "size", CPLSPrintf("%d", nFieldSize ) );
     if( pszDescription )
         CPLAddXMLAttributeAndValue(psField, "description", pszDescription );
 }
@@ -50,7 +66,7 @@ static void AddHexField(CPLXMLNode* psParent, const char* pszFieldName,
                                     psParent, "Field", pszValue );
     CPLAddXMLAttributeAndValue(psField, "name", pszFieldName );
     CPLAddXMLAttributeAndValue(psField, "type", "hexint" );
-    CPLAddXMLAttributeAndValue(psField, "size", CPLSPrintf("%d", nFieldSize )  );
+    CPLAddXMLAttributeAndValue(psField, "size", CPLSPrintf("%d", nFieldSize ) );
     if( pszDescription )
         CPLAddXMLAttributeAndValue(psField, "description", pszDescription );
 }
@@ -559,7 +575,12 @@ static void DumpRESxBox(CPLXMLNode* psBox, GDALJP2Box& oBox)
             CPLCreateXMLNode( psBox, CXT_Element, "DecodedContent" );
         GIntBig nRemainingLength = nBoxDataLength;
         GByte* pabyIter = pabyBoxData;
-        GUInt16 nNumV = 0, nNumH = 0, nDenomV = 1, nDenomH = 1, nExpV = 0, nExpH = 0;
+        GUInt16 nNumV = 0;
+        GUInt16 nNumH = 0;
+        GUInt16 nDenomV = 1;
+        GUInt16 nDenomH = 1;
+        GUInt16 nExpV = 0;
+        GUInt16 nExpH = 0;
         if( nRemainingLength >= 2 )
         {
             GUInt16 nVal;
@@ -917,7 +938,6 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
         GUInt16 nRemainingMarkerSize = nMarkerSize - 2;
         GUInt32 nLastVal = 0;
 
-
 #define READ_MARKER_FIELD_UINT8_COMMENT(name, comment) \
         do { if( nRemainingMarkerSize >= 1 ) { \
             nLastVal = *pabyMarkerDataIter; \
@@ -929,7 +949,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
                 AddError(psMarker, CPLSPrintf("Cannot read field %s", name)); \
                 nLastVal = 0; \
             } \
-        } while(0)
+        } while( false )
 
 #define READ_MARKER_FIELD_UINT8(name) \
         READ_MARKER_FIELD_UINT8_COMMENT(name, NULL)
@@ -948,7 +968,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
                 AddError(psMarker, CPLSPrintf("Cannot read field %s", name)); \
                 nLastVal = 0; \
             } \
-        } while(0)
+        } while( false )
 
 #define READ_MARKER_FIELD_UINT16(name) \
         READ_MARKER_FIELD_UINT16_COMMENT(name, NULL)
@@ -967,7 +987,7 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
                 AddError(psMarker, CPLSPrintf("Cannot read field %s", name)); \
                 nLastVal = 0; \
             } \
-        } while(0)
+        } while( false )
 
 #define READ_MARKER_FIELD_UINT32(name) \
         READ_MARKER_FIELD_UINT32_COMMENT(name, NULL)
@@ -1126,7 +1146,8 @@ static CPLXMLNode* DumpJPK2CodeStream(CPLXMLNode* psBox,
         else if( abyMarker[1] == 0x55 ) /* TLM */
         {
             READ_MARKER_FIELD_UINT8("Ztlm");
-            int ST = 0, SP = 0;
+            int ST = 0;
+            int SP = 0;
             READ_MARKER_FIELD_UINT8_COMMENT("Stlm",
                     CPLSPrintf("ST=%d SP=%d",
                                (ST = (nLastVal >> 4) & 3),
@@ -1255,8 +1276,8 @@ void GDALGetJPEG2000StructureInternal(CPLXMLNode* psParent,
                     VSIFree(pszBinaryContent);
                 }
 
-                if( (CSLFetchBoolean(papszOptions, "BINARY_CONTENT", FALSE) ||
-                     CSLFetchBoolean(papszOptions, "ALL", FALSE) ) &&
+                if( (CPLFetchBool(papszOptions, "BINARY_CONTENT", false) ||
+                     CPLFetchBool(papszOptions, "ALL", false) ) &&
                     strcmp(pszBoxType, "jp2c") != 0 &&
                     nBoxDataLength < 100 * 1024 )
                 {
@@ -1278,8 +1299,8 @@ void GDALGetJPEG2000StructureInternal(CPLXMLNode* psParent,
                     VSIFree(pszBinaryContent);
                 }
 
-                if( (CSLFetchBoolean(papszOptions, "TEXT_CONTENT", FALSE) ||
-                     CSLFetchBoolean(papszOptions, "ALL", FALSE) ) &&
+                if( (CPLFetchBool(papszOptions, "TEXT_CONTENT", false) ||
+                     CPLFetchBool(papszOptions, "ALL", false) ) &&
                     strcmp(pszBoxType, "jp2c") != 0 &&
                     nBoxDataLength < 100 * 1024 )
                 {
@@ -1315,8 +1336,8 @@ void GDALGetJPEG2000StructureInternal(CPLXMLNode* psParent,
 
                 if( strcmp(pszBoxType, "jp2c") == 0 )
                 {
-                    if( CSLFetchBoolean(papszOptions, "CODESTREAM", FALSE) ||
-                        CSLFetchBoolean(papszOptions, "ALL", FALSE) )
+                    if( CPLFetchBool(papszOptions, "CODESTREAM", false) ||
+                        CPLFetchBool(papszOptions, "ALL", false) )
                     {
                         DumpJPK2CodeStream(psBox, fp,
                                            oBox.GetDataOffset(), nBoxDataLength);
@@ -1412,8 +1433,8 @@ CPLXMLNode* GDALGetJPEG2000Structure(const char* pszFilename,
     CPLXMLNode* psParent = NULL;
     if( memcmp(abyHeader, jpc_header, sizeof(jpc_header)) == 0 )
     {
-        if( CSLFetchBoolean(papszOptions, "CODESTREAM", FALSE) ||
-            CSLFetchBoolean(papszOptions, "ALL", FALSE) )
+        if( CPLFetchBool(papszOptions, "CODESTREAM", false) ||
+            CPLFetchBool(papszOptions, "ALL", false) )
         {
             if( VSIFSeekL(fp, 0, SEEK_END) == 0 )
             {
diff --git a/gcore/gdalmajorobject.cpp b/gcore/gdalmajorobject.cpp
index 9ccba0c..40e93da 100644
--- a/gcore/gdalmajorobject.cpp
+++ b/gcore/gdalmajorobject.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalmajorobject.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for objects with metadata, etc.
@@ -28,20 +27,25 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
+
+#include <cstdarg>
+#include <cstddef>
+
+#include "cpl_error.h"
 #include "cpl_string.h"
+#include "gdal.h"
 
-CPL_CVSID("$Id: gdalmajorobject.cpp 33694 2016-03-10 17:54:30Z goatbar $");
+CPL_CVSID("$Id: gdalmajorobject.cpp 36525 2016-11-27 14:15:26Z goatbar $");
 
 /************************************************************************/
 /*                          GDALMajorObject()                           */
 /************************************************************************/
 
-GDALMajorObject::GDALMajorObject()
-
-{
-    nFlags = GMO_VALID;
-}
+GDALMajorObject::GDALMajorObject() :
+    nFlags(GMO_VALID)
+{}
 
 /************************************************************************/
 /*                          ~GDALMajorObject()                          */
@@ -93,7 +97,7 @@ const char * CPL_STDCALL GDALGetDescription( GDALMajorObjectH hObject )
 {
     VALIDATE_POINTER1( hObject, "GDALGetDescription", NULL );
 
-    return ((GDALMajorObject *) hObject)->GetDescription();
+    return static_cast<GDALMajorObject *>(hObject)->GetDescription();
 }
 
 /************************************************************************/
@@ -129,12 +133,13 @@ void GDALMajorObject::SetDescription( const char * pszNewDesc )
  * @see GDALMajorObject::SetDescription()
  */
 
-void CPL_STDCALL GDALSetDescription( GDALMajorObjectH hObject, const char *pszNewDesc )
+void CPL_STDCALL GDALSetDescription( GDALMajorObjectH hObject,
+                                     const char *pszNewDesc )
 
 {
     VALIDATE_POINTER0( hObject, "GDALSetDescription" );
 
-    ((GDALMajorObject *) hObject)->SetDescription( pszNewDesc );
+    static_cast<GDALMajorObject *>(hObject)->SetDescription( pszNewDesc );
 }
 
 /************************************************************************/
@@ -177,10 +182,11 @@ char **GDALMajorObject::GetMetadataDomainList()
  * @since GDAL 1.11
  */
 
-char **GDALMajorObject::BuildMetadataDomainList(char** papszList, int bCheckNonEmpty, ...)
+char **GDALMajorObject::BuildMetadataDomainList( char** papszList,
+                                                 int bCheckNonEmpty, ... )
 {
     va_list args;
-    const char* pszDomain;
+    const char* pszDomain = NULL;
     va_start(args, bCheckNonEmpty);
 
     while( (pszDomain = va_arg(args, const char*)) != NULL )
@@ -210,12 +216,12 @@ char **GDALMajorObject::BuildMetadataDomainList(char** papszList, int bCheckNonE
  */
 
 char ** CPL_STDCALL
-GDALGetMetadataDomainList( GDALMajorObjectH hObject)
+GDALGetMetadataDomainList( GDALMajorObjectH hObject )
 
 {
     VALIDATE_POINTER1( hObject, "GetMetadataDomainList", NULL );
 
-    return ((GDALMajorObject *) hObject)->GetMetadataDomainList();
+    return static_cast<GDALMajorObject *>(hObject)->GetMetadataDomainList();
 }
 
 /************************************************************************/
@@ -262,7 +268,7 @@ GDALGetMetadata( GDALMajorObjectH hObject, const char * pszDomain )
 {
     VALIDATE_POINTER1( hObject, "GDALGetMetadata", NULL );
 
-    return ((GDALMajorObject *) hObject)->GetMetadata(pszDomain);
+    return static_cast<GDALMajorObject *>(hObject)->GetMetadata(pszDomain);
 }
 
 /************************************************************************/
@@ -298,7 +304,14 @@ CPLErr GDALMajorObject::SetMetadata( char ** papszMetadataIn,
 /**
  * \brief Set metadata.
  *
- * @see GDALMajorObject::SetMetadata()
+ * CAUTION: when using this function on a GDALDatasetH or GDALRasterBandH,
+ * depending on the format, older values of the updated information might
+ * still be found in the file in a "ghost" state, even if no longer accessible
+ * through the GDAL API. This is for example the case of the GTiff format (this is
+ * not a exhaustive list)
+ *
+ * @see GDALMajorObject::SetMetadata(), GDALDataset::SetMetadata(),
+ *      GDALRasterBand::SetMetadata()
  */
 
 CPLErr CPL_STDCALL
@@ -308,10 +321,10 @@ GDALSetMetadata( GDALMajorObjectH hObject, char **papszMD,
 {
     VALIDATE_POINTER1( hObject, "GDALSetMetadata", CE_Failure );
 
-    return ((GDALMajorObject *) hObject)->SetMetadata( papszMD, pszDomain );
+    return static_cast<GDALMajorObject *>(hObject)->
+        SetMetadata( papszMD, pszDomain );
 }
 
-
 /************************************************************************/
 /*                          GetMetadataItem()                           */
 /************************************************************************/
@@ -346,13 +359,14 @@ const char *GDALMajorObject::GetMetadataItem( const char * pszName,
  */
 
 const char * CPL_STDCALL GDALGetMetadataItem( GDALMajorObjectH hObject,
-                                 const char *pszName,
-                                 const char *pszDomain )
+                                              const char *pszName,
+                                              const char *pszDomain )
 
 {
     VALIDATE_POINTER1( hObject, "GDALGetMetadataItem", NULL );
 
-    return ((GDALMajorObject *) hObject)->GetMetadataItem( pszName, pszDomain);
+    return static_cast<GDALMajorObject *>(hObject)->
+        GetMetadataItem( pszName, pszDomain);
 }
 
 /************************************************************************/
@@ -387,7 +401,14 @@ CPLErr GDALMajorObject::SetMetadataItem( const char * pszName,
 /**
  * \brief Set single metadata item.
  *
- * @see GDALMajorObject::SetMetadataItem()
+ * CAUTION: when using this function on a GDALDatasetH or GDALRasterBandH,
+ * depending on the format, older values of the updated information might
+ * still be found in the file in a "ghost" state, even if no longer accessible
+ * through the GDAL API. This is for example the case of the GTiff format (this is
+ * not a exhaustive list)
+ *
+ * @see GDALMajorObject::SetMetadataItem(), GDALDataset::SetMetadataItem(),
+ *      GDALRasterBand::SetMetadataItem()
  */
 
 CPLErr CPL_STDCALL
@@ -398,15 +419,18 @@ GDALSetMetadataItem( GDALMajorObjectH hObject,
 {
     VALIDATE_POINTER1( hObject, "GDALSetMetadataItem", CE_Failure );
 
-    return ((GDALMajorObject *) hObject)->SetMetadataItem( pszName, pszValue,
-                                                           pszDomain );
+    return static_cast<GDALMajorObject *>(hObject)->
+        SetMetadataItem( pszName, pszValue, pszDomain );
 }
 
 /************************************************************************/
 /*                             GetMOFlags()                             */
 /************************************************************************/
 
-int GDALMajorObject::GetMOFlags()
+/** Returns the GMO_ flags.
+ * @return flags
+ */
+int GDALMajorObject::GetMOFlags() const
 
 {
     return nFlags;
@@ -416,6 +440,9 @@ int GDALMajorObject::GetMOFlags()
 /*                             SetMOFlags()                             */
 /************************************************************************/
 
+/** Assign GMO_flags.
+ * @param nNewFlags new flags.
+ */
 void GDALMajorObject::SetMOFlags( int nNewFlags )
 
 {
diff --git a/gcore/gdalmultidomainmetadata.cpp b/gcore/gdalmultidomainmetadata.cpp
index 57f8aba..5ca8c8b 100644
--- a/gcore/gdalmultidomainmetadata.cpp
+++ b/gcore/gdalmultidomainmetadata.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalmultidomainmetadata.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALMultiDomainMetadata class.  This class
@@ -29,22 +28,28 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gdal_pam.h"
+#include "cpl_port.h"
+#include "gdal_priv.h"
+
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
 #include "cpl_string.h"
-#include <map>
+#include "gdal_pam.h"
 
-CPL_CVSID("$Id: gdalmultidomainmetadata.cpp 33694 2016-03-10 17:54:30Z goatbar $");
+CPL_CVSID("$Id: gdalmultidomainmetadata.cpp 36525 2016-11-27 14:15:26Z goatbar $");
 
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                      GDALMultiDomainMetadata()                       */
 /************************************************************************/
 
-GDALMultiDomainMetadata::GDALMultiDomainMetadata()
-
-{
-    papszDomainList = NULL;
-    papoMetadataLists = NULL;
-}
+GDALMultiDomainMetadata::GDALMultiDomainMetadata() :
+    papszDomainList(NULL),
+    papoMetadataLists(NULL)
+{}
 
 /************************************************************************/
 /*                      ~GDALMultiDomainMetadata()                      */
@@ -63,13 +68,11 @@ GDALMultiDomainMetadata::~GDALMultiDomainMetadata()
 void GDALMultiDomainMetadata::Clear()
 
 {
-    int i, nDomainCount;
-
-    nDomainCount = CSLCount( papszDomainList );
+    const int nDomainCount = CSLCount( papszDomainList );
     CSLDestroy( papszDomainList );
     papszDomainList = NULL;
 
-    for( i = 0; i < nDomainCount; i++ )
+    for( int i = 0; i < nDomainCount; i++ )
     {
         delete papoMetadataLists[i];
     }
@@ -77,7 +80,6 @@ void GDALMultiDomainMetadata::Clear()
     papoMetadataLists = NULL;
 }
 
-
 /************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
@@ -88,12 +90,12 @@ char **GDALMultiDomainMetadata::GetMetadata( const char *pszDomain )
     if( pszDomain == NULL )
         pszDomain = "";
 
-    int iDomain = CSLFindString( papszDomainList, pszDomain );
+    const int iDomain = CSLFindString( papszDomainList, pszDomain );
 
     if( iDomain == -1 )
         return NULL;
-    else
-        return papoMetadataLists[iDomain]->List();
+
+    return papoMetadataLists[iDomain]->List();
 }
 
 /************************************************************************/
@@ -111,10 +113,8 @@ CPLErr GDALMultiDomainMetadata::SetMetadata( char **papszMetadata,
 
     if( iDomain == -1 )
     {
-        int nDomainCount;
-
         papszDomainList = CSLAddString( papszDomainList, pszDomain );
-        nDomainCount = CSLCount( papszDomainList );
+        const int nDomainCount = CSLCount( papszDomainList );
 
         papoMetadataLists = (CPLStringList **)
             CPLRealloc( papoMetadataLists, sizeof(void*)*(nDomainCount+1) );
@@ -144,12 +144,12 @@ const char *GDALMultiDomainMetadata::GetMetadataItem( const char *pszName,
     if( pszDomain == NULL )
         pszDomain = "";
 
-    int iDomain = CSLFindString( papszDomainList, pszDomain );
+    const int iDomain = CSLFindString( papszDomainList, pszDomain );
 
     if( iDomain == -1 )
         return NULL;
-    else
-        return papoMetadataLists[iDomain]->FetchNameValue( pszName );
+
+    return papoMetadataLists[iDomain]->FetchNameValue( pszName );
 }
 
 /************************************************************************/
@@ -190,32 +190,30 @@ CPLErr GDALMultiDomainMetadata::SetMetadataItem( const char *pszName,
 /*      <Metadata> elements.                                            */
 /************************************************************************/
 
-int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, CPL_UNUSED int bMerge )
+int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, int /* bMerge */ )
 {
-    CPLXMLNode *psMetadata;
+    CPLXMLNode *psMetadata = NULL;
 
 /* ==================================================================== */
 /*      Process all <Metadata> elements, each for one domain.           */
 /* ==================================================================== */
     for( psMetadata = psTree->psChild;
-         psMetadata != NULL; psMetadata = psMetadata->psNext )
+         psMetadata != NULL;
+         psMetadata = psMetadata->psNext )
     {
-        CPLXMLNode *psMDI;
-        const char *pszDomain, *pszFormat;
-
         if( psMetadata->eType != CXT_Element
             || !EQUAL(psMetadata->pszValue,"Metadata") )
             continue;
 
-        pszDomain = CPLGetXMLValue( psMetadata, "domain", "" );
-        pszFormat = CPLGetXMLValue( psMetadata, "format", "" );
+        const char *pszDomain = CPLGetXMLValue( psMetadata, "domain", "" );
+        const char *pszFormat = CPLGetXMLValue( psMetadata, "format", "" );
 
         // Make sure we have a CPLStringList for this domain,
         // without wiping out an existing one.
         if( GetMetadata( pszDomain ) == NULL )
             SetMetadata( NULL, pszDomain );
 
-        int iDomain = CSLFindString( papszDomainList, pszDomain );
+        const int iDomain = CSLFindString( papszDomainList, pszDomain );
         CPLAssert( iDomain != -1 );
 
         CPLStringList *poMDList = papoMetadataLists[iDomain];
@@ -225,10 +223,8 @@ int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, CPL_UNUSED int bMerge
 /* -------------------------------------------------------------------- */
         if( EQUAL(pszFormat,"xml") )
         {
-            CPLXMLNode *psSubDoc;
-
-            /* find first non-attribute child of current element */
-            psSubDoc = psMetadata->psChild;
+            // Find first non-attribute child of current element.
+            CPLXMLNode *psSubDoc = psMetadata->psChild;
             while( psSubDoc != NULL && psSubDoc->eType == CXT_Attribute )
                 psSubDoc = psSubDoc->psNext;
 
@@ -244,7 +240,8 @@ int GDALMultiDomainMetadata::XMLInit( CPLXMLNode *psTree, CPL_UNUSED int bMerge
 /* -------------------------------------------------------------------- */
         else
         {
-            for( psMDI = psMetadata->psChild; psMDI != NULL;
+            for( CPLXMLNode *psMDI = psMetadata->psChild;
+                 psMDI != NULL;
                  psMDI = psMDI->psNext )
             {
                 if( !EQUAL(psMDI->pszValue,"MDI")
@@ -277,23 +274,22 @@ CPLXMLNode *GDALMultiDomainMetadata::Serialize()
 
     for( int iDomain = 0;
          papszDomainList != NULL && papszDomainList[iDomain] != NULL;
-         iDomain++)
+         iDomain++ )
     {
         char **papszMD = papoMetadataLists[iDomain]->List();
-        // Do not serialize empty domains
+        // Do not serialize empty domains.
         if( papszMD == NULL || papszMD[0] == NULL )
             continue;
 
-        CPLXMLNode *psMD;
-        bool bFormatXML = false;
-
-        psMD = CPLCreateXMLNode( NULL, CXT_Element, "Metadata" );
+        CPLXMLNode *psMD = CPLCreateXMLNode( NULL, CXT_Element, "Metadata" );
 
         if( strlen( papszDomainList[iDomain] ) > 0 )
             CPLCreateXMLNode(
                 CPLCreateXMLNode( psMD, CXT_Attribute, "domain" ),
                 CXT_Text, papszDomainList[iDomain] );
 
+        bool bFormatXML = false;
+
         if( STARTS_WITH_CI(papszDomainList[iDomain], "xml:")
             && CSLCount(papszMD) == 1 )
         {
@@ -313,7 +309,7 @@ CPLXMLNode *GDALMultiDomainMetadata::Serialize()
         if( !bFormatXML )
         {
             CPLXMLNode* psLastChild = NULL;
-            // To go after domain attribute
+            // To go after domain attribute.
             if( psMD->psChild != NULL )
             {
                 psLastChild = psMD->psChild;
@@ -322,13 +318,13 @@ CPLXMLNode *GDALMultiDomainMetadata::Serialize()
             }
             for( int i = 0; papszMD != NULL && papszMD[i] != NULL; i++ )
             {
-                const char *pszRawValue;
                 char *pszKey = NULL;
-                CPLXMLNode *psMDI;
 
-                pszRawValue = CPLParseNameValue( papszMD[i], &pszKey );
+                const char *pszRawValue =
+                    CPLParseNameValue( papszMD[i], &pszKey );
 
-                psMDI = CPLCreateXMLNode( NULL, CXT_Element, "MDI" );
+                CPLXMLNode *psMDI =
+                    CPLCreateXMLNode( NULL, CXT_Element, "MDI" );
                 if( psLastChild == NULL )
                     psMD->psChild = psMDI;
                 else
@@ -350,3 +346,4 @@ CPLXMLNode *GDALMultiDomainMetadata::Serialize()
 
     return psFirst;
 }
+//! @endcond
diff --git a/gcore/gdalnodatamaskband.cpp b/gcore/gdalnodatamaskband.cpp
index e268c5a..48ef49a 100644
--- a/gcore/gdalnodatamaskband.cpp
+++ b/gcore/gdalnodatamaskband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalnodatamaskband.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALNoDataMaskBand, a class implementing all
@@ -29,48 +28,52 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalnodatamaskband.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+#include <cstring>
 
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+
+CPL_CVSID("$Id: gdalnodatamaskband.cpp 36525 2016-11-27 14:15:26Z goatbar $");
+
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                        GDALNoDataMaskBand()                          */
 /************************************************************************/
 
-GDALNoDataMaskBand::GDALNoDataMaskBand( GDALRasterBand *poParentIn )
-
+GDALNoDataMaskBand::GDALNoDataMaskBand( GDALRasterBand *poParentIn ) :
+    dfNoDataValue(poParentIn->GetNoDataValue()),
+    poParent(poParentIn)
 {
     poDS = NULL;
     nBand = 0;
-    poParent = poParentIn;
 
     nRasterXSize = poParent->GetXSize();
     nRasterYSize = poParent->GetYSize();
 
     eDataType = GDT_Byte;
     poParent->GetBlockSize( &nBlockXSize, &nBlockYSize );
-
-    dfNoDataValue = poParent->GetNoDataValue();
 }
 
 /************************************************************************/
 /*                       ~GDALNoDataMaskBand()                          */
 /************************************************************************/
 
-GDALNoDataMaskBand::~GDALNoDataMaskBand()
-
-{
-}
+GDALNoDataMaskBand::~GDALNoDataMaskBand() {}
 
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
 CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
-                                         void * pImage )
+                                       void * pImage )
 
 {
-    GDALDataType eWrkDT;
+    GDALDataType eWrkDT = GDT_Unknown;
 
 /* -------------------------------------------------------------------- */
 /*      Decide on a working type.                                       */
@@ -104,7 +107,7 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         eWrkDT = GDT_Float64;
         break;
     }
@@ -112,8 +115,7 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 /* -------------------------------------------------------------------- */
 /*      Read the image data.                                            */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
-
+    // TODO(schwehr): pabySrc would probably be better as a void ptr.
     GByte *pabySrc = static_cast<GByte *>(
         VSI_MALLOC3_VERBOSE( GDALGetDataTypeSizeBytes(eWrkDT),
                              nBlockXSize, nBlockYSize ) );
@@ -122,7 +124,6 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
         return CE_Failure;
     }
 
-
     int nXSizeRequest = nBlockXSize;
     if (nXBlockOff * nBlockXSize + nBlockXSize > nRasterXSize)
         nXSizeRequest = nRasterXSize - nXBlockOff * nBlockXSize;
@@ -132,110 +133,103 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 
     if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize)
     {
-        /* memset the whole buffer to avoid Valgrind warnings in case we can't */
-        /* fetch a full block */
+        // memset the whole buffer to avoid Valgrind warnings in case RasterIO
+        // fetches a partial block.
         memset( pabySrc, 0,
                 GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize );
     }
 
-    eErr = poParent->RasterIO( GF_Read,
-                               nXBlockOff * nBlockXSize,
-                               nYBlockOff * nBlockYSize,
-                               nXSizeRequest, nYSizeRequest,
-                               pabySrc, nXSizeRequest, nYSizeRequest,
-                               eWrkDT, 0,
-                               nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT),
-                               NULL );
+    CPLErr eErr =
+        poParent->RasterIO( GF_Read,
+                            nXBlockOff * nBlockXSize,
+                            nYBlockOff * nBlockYSize,
+                            nXSizeRequest, nYSizeRequest,
+                            pabySrc, nXSizeRequest, nYSizeRequest,
+                            eWrkDT, 0,
+                            nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT),
+                            NULL );
     if( eErr != CE_None )
     {
         CPLFree(pabySrc);
         return eErr;
     }
 
-    int bIsNoDataNan = CPLIsNan(dfNoDataValue);
+    const bool bIsNoDataNan = CPLIsNan(dfNoDataValue) != 0;
 
 /* -------------------------------------------------------------------- */
 /*      Process different cases.                                        */
 /* -------------------------------------------------------------------- */
-    int i;
     switch( eWrkDT )
     {
       case GDT_Byte:
       {
-          GByte byNoData = (GByte) dfNoDataValue;
+          GByte byNoData = static_cast<GByte>( dfNoDataValue );
 
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; --i )
           {
-              if( pabySrc[i] == byNoData )
-                  ((GByte *) pImage)[i] = 0;
-              else
-                  ((GByte *) pImage)[i] = 255;
+              static_cast<GByte *>(pImage)[i] = pabySrc[i] == byNoData ? 0: 255;
           }
       }
       break;
 
       case GDT_UInt32:
       {
-          GUInt32 nNoData = (GUInt32) dfNoDataValue;
+          GUInt32 nNoData = static_cast<GUInt32>( dfNoDataValue );
 
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; --i )
           {
-              if( ((GUInt32 *)pabySrc)[i] == nNoData )
-                  ((GByte *) pImage)[i] = 0;
-              else
-                  ((GByte *) pImage)[i] = 255;
+              static_cast<GByte *>(pImage)[i] =
+                  reinterpret_cast<GUInt32 *>(pabySrc)[i] == nNoData ? 0 : 255;
           }
       }
       break;
 
       case GDT_Int32:
       {
-          GInt32 nNoData = (GInt32) dfNoDataValue;
+          GInt32 nNoData = static_cast<GInt32>( dfNoDataValue );
 
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; --i )
           {
-              if( ((GInt32 *)pabySrc)[i] == nNoData )
-                  ((GByte *) pImage)[i] = 0;
-              else
-                  ((GByte *) pImage)[i] = 255;
+              static_cast<GByte *>(pImage)[i] =
+                  reinterpret_cast<GInt32 *>(pabySrc)[i] == nNoData ? 0 : 255;
           }
       }
       break;
 
       case GDT_Float32:
       {
-          float fNoData = (float) dfNoDataValue;
+          float fNoData = static_cast<float>( dfNoDataValue );
 
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; --i )
           {
-              float fVal =((float *)pabySrc)[i];
+              const float fVal = reinterpret_cast<float *>(pabySrc)[i];
               if( bIsNoDataNan && CPLIsNan(fVal))
-                  ((GByte *) pImage)[i] = 0;
+                  static_cast<GByte *>(pImage)[i] = 0;
               else if( ARE_REAL_EQUAL(fVal, fNoData) )
-                  ((GByte *) pImage)[i] = 0;
+                  static_cast<GByte *>(pImage)[i] = 0;
               else
-                  ((GByte *) pImage)[i] = 255;
+                  static_cast<GByte *>(pImage)[i] = 255;
           }
       }
       break;
 
       case GDT_Float64:
       {
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
           {
-              double dfVal =((double *)pabySrc)[i];
+              const double dfVal = reinterpret_cast<double *>(pabySrc)[i];
               if( bIsNoDataNan && CPLIsNan(dfVal))
-                  ((GByte *) pImage)[i] = 0;
+                  static_cast<GByte *>(pImage)[i] = 0;
               else if( ARE_REAL_EQUAL(dfVal, dfNoDataValue) )
-                  ((GByte *) pImage)[i] = 0;
+                  static_cast<GByte *>(pImage)[i] = 0;
               else
-                  ((GByte *) pImage)[i] = 255;
+                  static_cast<GByte *>(pImage)[i] = 255;
           }
       }
       break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         break;
     }
 
@@ -249,36 +243,36 @@ CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 /************************************************************************/
 
 CPLErr GDALNoDataMaskBand::IRasterIO( GDALRWFlag eRWFlag,
-                                      int nXOff, int nYOff, int nXSize, int nYSize,
-                                      void * pData, int nBufXSize, int nBufYSize,
+                                      int nXOff, int nYOff,
+                                      int nXSize, int nYSize,
+                                      void * pData,
+                                      int nBufXSize, int nBufYSize,
                                       GDALDataType eBufType,
                                       GSpacing nPixelSpace, GSpacing nLineSpace,
                                       GDALRasterIOExtraArg* psExtraArg )
 {
-    /* Optimization in common use case (#4488) */
-    /* This avoids triggering the block cache on this band, which helps */
-    /* reducing the global block cache consumption */
+    // Optimization in common use case (#4488).
+    // This avoids triggering the block cache on this band, which helps
+    // reducing the global block cache consumption.
     if (eRWFlag == GF_Read && eBufType == GDT_Byte &&
         poParent->GetRasterDataType() == GDT_Byte &&
         nXSize == nBufXSize && nYSize == nBufYSize &&
         nPixelSpace == 1 && nLineSpace == nBufXSize)
     {
-        CPLErr eErr = poParent->RasterIO( GF_Read, nXOff, nYOff, nXSize, nYSize,
-                                          pData, nBufXSize, nBufYSize,
-                                          eBufType,
-                                          nPixelSpace, nLineSpace, psExtraArg );
+        const CPLErr eErr =
+            poParent->RasterIO( GF_Read, nXOff, nYOff, nXSize, nYSize,
+                                pData, nBufXSize, nBufYSize,
+                                eBufType,
+                                nPixelSpace, nLineSpace, psExtraArg );
         if (eErr != CE_None)
             return eErr;
 
-        GByte* pabyData = (GByte*) pData;
-        GByte byNoData = (GByte) dfNoDataValue;
+        GByte* pabyData = static_cast<GByte*>( pData );
+        GByte byNoData = static_cast<GByte>( dfNoDataValue );
 
-        for( int i = nBufXSize * nBufYSize - 1; i >= 0; i-- )
+        for( int i = nBufXSize * nBufYSize - 1; i >= 0; --i )
         {
-            if( pabyData[i] == byNoData )
-                pabyData[i] = 0;
-            else
-                pabyData[i] = 255;
+            pabyData[i] = pabyData[i] == byNoData ? 0 : 255;
         }
         return CE_None;
     }
@@ -288,3 +282,4 @@ CPLErr GDALNoDataMaskBand::IRasterIO( GDALRWFlag eRWFlag,
                                       eBufType,
                                       nPixelSpace, nLineSpace, psExtraArg );
 }
+//! @endcond
diff --git a/gcore/gdalnodatavaluesmaskband.cpp b/gcore/gdalnodatavaluesmaskband.cpp
index ef1f67b..4e03c33 100644
--- a/gcore/gdalnodatavaluesmaskband.cpp
+++ b/gcore/gdalnodatavaluesmaskband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalnodatavaluesmaskband.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALNoDataValuesMaskBand, a class implementing
@@ -30,23 +29,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalnodatavaluesmaskband.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+#include <cstring>
 
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+
+CPL_CVSID("$Id: gdalnodatavaluesmaskband.cpp 36525 2016-11-27 14:15:26Z goatbar $");
+
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                   GDALNoDataValuesMaskBand()                         */
 /************************************************************************/
 
-GDALNoDataValuesMaskBand::GDALNoDataValuesMaskBand( GDALDataset* poDSIn )
-
+GDALNoDataValuesMaskBand::GDALNoDataValuesMaskBand( GDALDataset* poDSIn ) :
+    padfNodataValues(NULL)
 {
     const char* pszNoDataValues = poDSIn->GetMetadataItem("NODATA_VALUES");
-    char** papszNoDataValues = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
+    char** papszNoDataValues =
+        CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
 
-    int i;
-    padfNodataValues = (double*)CPLMalloc(sizeof(double) * poDSIn->GetRasterCount());
-    for(i=0;i<poDSIn->GetRasterCount();i++)
+    padfNodataValues = static_cast<double*>(
+        CPLMalloc(sizeof(double) * poDSIn->GetRasterCount()) );
+    for( int i = 0; i < poDSIn->GetRasterCount(); ++i )
     {
         padfNodataValues[i] = CPLAtof(papszNoDataValues[i]);
     }
@@ -78,11 +88,10 @@ GDALNoDataValuesMaskBand::~GDALNoDataValuesMaskBand()
 /************************************************************************/
 
 CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
-                                         void * pImage )
+                                             void * pImage )
 
 {
-    int iBand;
-    GDALDataType eWrkDT;
+    GDALDataType eWrkDT = GDT_Unknown;
 
 /* -------------------------------------------------------------------- */
 /*      Decide on a working type.                                       */
@@ -116,7 +125,7 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         eWrkDT = GDT_Float64;
         break;
     }
@@ -124,9 +133,7 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 /* -------------------------------------------------------------------- */
 /*      Read the image data.                                            */
 /* -------------------------------------------------------------------- */
-    CPLErr eErr;
-
-    int nBands = poDS->GetRasterCount();
+    const int nBands = poDS->GetRasterCount();
     GByte *pabySrc = static_cast<GByte *>(
         VSI_MALLOC3_VERBOSE( nBands * GDALGetDataTypeSizeBytes(eWrkDT),
                              nBlockXSize, nBlockYSize ) );
@@ -144,8 +151,8 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 
     if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize)
     {
-        /* memset the whole buffer to avoid Valgrind warnings in case we can't */
-        /* fetch a full block */
+        // memset the whole buffer to avoid Valgrind warnings in case we can't
+        // fetch a full block.
         memset( pabySrc, 0,
                 nBands * GDALGetDataTypeSizeBytes(eWrkDT) *
                 nBlockXSize * nBlockYSize );
@@ -154,20 +161,21 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
     int nBlockOffsetPixels = nBlockXSize * nBlockYSize;
     const int nBandOffsetByte =
         GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize;
-    for(iBand=0;iBand<nBands;iBand++)
+    for( int iBand = 0; iBand < nBands; ++iBand )
     {
-        eErr = poDS->GetRasterBand(iBand + 1)->RasterIO(
-            GF_Read,
-            nXBlockOff * nBlockXSize,
-            nYBlockOff * nBlockYSize,
-            nXSizeRequest,
-            nYSizeRequest,
-            pabySrc + iBand * nBandOffsetByte,
-            nXSizeRequest,
-            nYSizeRequest,
-            eWrkDT, 0,
-            nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT),
-            NULL );
+        const CPLErr eErr =
+            poDS->GetRasterBand(iBand + 1)->RasterIO(
+                GF_Read,
+                nXBlockOff * nBlockXSize,
+                nYBlockOff * nBlockYSize,
+                nXSizeRequest,
+                nYSizeRequest,
+                pabySrc + iBand * nBandOffsetByte,
+                nXSizeRequest,
+                nYSizeRequest,
+                eWrkDT, 0,
+                nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT),
+                NULL );
         if( eErr != CE_None )
             return eErr;
     }
@@ -175,29 +183,29 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 /* -------------------------------------------------------------------- */
 /*      Process different cases.                                        */
 /* -------------------------------------------------------------------- */
-    int i;
+    // TODO(schwehr): Cleanup casting.
     switch( eWrkDT )
     {
       case GDT_Byte:
       {
-          GByte* pabyNoData = (GByte*) CPLMalloc(nBands * sizeof(GByte));
-          for(iBand=0;iBand<nBands;iBand++)
+          GByte* pabyNoData = static_cast<GByte*>(
+              CPLMalloc(nBands * sizeof(GByte)) );
+          for( int iBand = 0; iBand < nBands; ++iBand )
           {
-              pabyNoData[iBand] = (GByte)padfNodataValues[iBand];
+              pabyNoData[iBand] = static_cast<GByte>(padfNodataValues[iBand]);
           }
 
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; --i )
           {
               int nCountNoData = 0;
-              for(iBand=0;iBand<nBands;iBand++)
+              for( int iBand = 0; iBand < nBands; ++iBand )
               {
-                  if( pabySrc[i + iBand * nBlockOffsetPixels] == pabyNoData[iBand] )
-                      nCountNoData ++;
+                  if( pabySrc[i + iBand * nBlockOffsetPixels] ==
+                      pabyNoData[iBand] )
+                      ++nCountNoData;
               }
-              if (nCountNoData == nBands)
-                  ((GByte *) pImage)[i] = 0;
-              else
-                  ((GByte *) pImage)[i] = 255;
+              static_cast<GByte *>(pImage)[i] =
+                  nCountNoData == nBands ? 0 : 255;
           }
 
           CPLFree(pabyNoData);
@@ -206,24 +214,23 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 
       case GDT_UInt32:
       {
-          GUInt32* panNoData = (GUInt32*) CPLMalloc(nBands * sizeof(GUInt32));
-          for(iBand=0;iBand<nBands;iBand++)
+          GUInt32* panNoData = static_cast<GUInt32 *>(
+              CPLMalloc(nBands * sizeof(GUInt32)) );
+          for( int iBand = 0; iBand < nBands; ++iBand )
           {
               panNoData[iBand] = (GUInt32)padfNodataValues[iBand];
           }
 
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; --i )
           {
               int nCountNoData = 0;
-              for(iBand=0;iBand<nBands;iBand++)
+              for( int iBand = 0; iBand < nBands; ++iBand )
               {
-                  if( ((GUInt32 *)pabySrc)[i + iBand * nBlockOffsetPixels] == panNoData[iBand] )
-                      nCountNoData ++;
+                  if( reinterpret_cast<GUInt32 *>(pabySrc)[
+                          i + iBand * nBlockOffsetPixels] == panNoData[iBand] )
+                      ++nCountNoData;
               }
-              if (nCountNoData == nBands)
-                  ((GByte *) pImage)[i] = 0;
-              else
-                  ((GByte *) pImage)[i] = 255;
+              static_cast<GByte *>(pImage)[i] = nCountNoData == nBands ? 0 :255;
           }
 
           CPLFree(panNoData);
@@ -232,24 +239,25 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 
       case GDT_Int32:
       {
-          GInt32* panNoData = (GInt32*) CPLMalloc(nBands * sizeof(GInt32));
-          for(iBand=0;iBand<nBands;iBand++)
+          GInt32* panNoData = static_cast<GInt32 *>(
+              CPLMalloc(nBands * sizeof(GInt32)) );
+          for( int iBand = 0; iBand < nBands; ++iBand )
           {
-              panNoData[iBand] = (GInt32)padfNodataValues[iBand];
+              // Intentional rounding.
+              panNoData[iBand] = static_cast<GInt32>(padfNodataValues[iBand]);
           }
 
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; --i )
           {
               int nCountNoData = 0;
-              for(iBand=0;iBand<nBands;iBand++)
+              for( int iBand = 0; iBand < nBands; ++iBand )
               {
-                  if( ((GInt32 *)pabySrc)[i + iBand * nBlockOffsetPixels] == panNoData[iBand] )
-                      nCountNoData ++;
+                  if( reinterpret_cast<GInt32 *>(pabySrc)[
+                          i + iBand * nBlockOffsetPixels] == panNoData[iBand] )
+                      ++nCountNoData;
               }
-              if (nCountNoData == nBands)
-                  ((GByte *) pImage)[i] = 0;
-              else
-                  ((GByte *) pImage)[i] = 255;
+              static_cast<GByte *>(pImage)[i] =
+                  nCountNoData == nBands ? 0 : 255;
           }
 
           CPLFree(panNoData);
@@ -258,24 +266,27 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 
       case GDT_Float32:
       {
-          float* pafNoData = (float*) CPLMalloc(nBands * sizeof(float));
-          for(iBand=0;iBand<nBands;iBand++)
+          float* pafNoData = static_cast<float *>(
+              CPLMalloc(nBands * sizeof(float)) );
+          for( int iBand = 0; iBand < nBands; ++iBand )
           {
-              pafNoData[iBand] = (float)padfNodataValues[iBand];
+              // Loss of precision.
+              pafNoData[iBand] = static_cast<float>(padfNodataValues[iBand]);
           }
 
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; --i )
           {
               int nCountNoData = 0;
-              for(iBand=0;iBand<nBands;iBand++)
+              for( int iBand = 0; iBand < nBands; ++iBand )
               {
-                  if( ((float *)pabySrc)[i + iBand * nBlockOffsetPixels] == pafNoData[iBand] )
-                      nCountNoData ++;
+                  if( reinterpret_cast<float *>(pabySrc)[
+                          i + iBand * nBlockOffsetPixels] == pafNoData[iBand] )
+                      ++nCountNoData;
               }
               if (nCountNoData == nBands)
-                  ((GByte *) pImage)[i] = 0;
+                  static_cast<GByte *>(pImage)[i] = 0;
               else
-                  ((GByte *) pImage)[i] = 255;
+                  static_cast<GByte *>(pImage)[i] = 255;
           }
 
           CPLFree(pafNoData);
@@ -284,24 +295,24 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 
       case GDT_Float64:
       {
-          double* padfNoData = (double*) CPLMalloc(nBands * sizeof(double));
-          for(iBand=0;iBand<nBands;iBand++)
+          double* padfNoData = static_cast<double*>(
+              CPLMalloc(nBands * sizeof(double)) );
+          for( int iBand = 0; iBand < nBands; ++iBand )
           {
-              padfNoData[iBand] = (double)padfNodataValues[iBand];
+              padfNoData[iBand] = padfNodataValues[iBand];
           }
 
-          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+          for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; --i )
           {
               int nCountNoData = 0;
-              for(iBand=0;iBand<nBands;iBand++)
+              for( int iBand = 0; iBand < nBands; ++iBand )
               {
-                  if( ((double *)pabySrc)[i + iBand * nBlockOffsetPixels] == padfNoData[iBand] )
-                      nCountNoData ++;
+                  if( reinterpret_cast<double *>(pabySrc)[
+                          i + iBand * nBlockOffsetPixels] == padfNoData[iBand] )
+                      ++nCountNoData;
               }
-              if (nCountNoData == nBands)
-                  ((GByte *) pImage)[i] = 0;
-              else
-                  ((GByte *) pImage)[i] = 255;
+              static_cast<GByte *>(pImage)[i] =
+                  nCountNoData == nBands ? 0 : 255;
           }
 
           CPLFree(padfNoData);
@@ -309,7 +320,7 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
       break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         break;
     }
 
@@ -317,3 +328,4 @@ CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
 
     return CE_None;
 }
+//! @endcond
diff --git a/gcore/gdalopeninfo.cpp b/gcore/gdalopeninfo.cpp
index 9b50745..a193fe5 100644
--- a/gcore/gdalopeninfo.cpp
+++ b/gcore/gdalopeninfo.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalopeninfo.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALOpenInfo class.
@@ -29,18 +28,25 @@
  ****************************************************************************/
 
 #include "gdal_priv.h"  // Must be included first for mingw VSIStatBufL.
-#include "cpl_conv.h"
-#include "cpl_vsi.h"
+#include "cpl_port.h"
 
+#include <cstdlib>
+#include <cstring>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
+#include <algorithm>
 #include <vector>
 
-CPL_CVSID("$Id: gdalopeninfo.cpp 33758 2016-03-21 09:06:22Z rouault $");
+#include "cpl_config.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
 
-using std::vector;
+CPL_CVSID("$Id: gdalopeninfo.cpp 37005 2016-12-23 15:03:59Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -52,6 +58,11 @@ using std::vector;
 /*                            GDALOpenInfo()                            */
 /************************************************************************/
 
+/** Constructor/
+ * @param pszFilenameIn filename
+ * @param nOpenFlagsIn open flags
+ * @param papszSiblingsIn list of sibling files, or NULL.
+ */
 GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, int nOpenFlagsIn,
                             char **papszSiblingsIn ) :
     bHasGotSiblingFiles(false),
@@ -65,7 +76,8 @@ GDALOpenInfo::GDALOpenInfo( const char * pszFilenameIn, int nOpenFlagsIn,
     bIsDirectory(FALSE),
     fpL(NULL),
     nHeaderBytes(0),
-    pabyHeader(NULL)
+    pabyHeader(NULL),
+    papszAllowedDrivers(NULL)
 {
 
 /* -------------------------------------------------------------------- */
@@ -186,13 +198,13 @@ retry:  // TODO(schwehr): Stop using goto.
             // my_remote_utm.tif.  This helps a lot for GDAL based readers that
             // only provide file explorers to open datasets.
             const int nBufSize = 2048;
-            vector<char> oFilename(nBufSize);
+            std::vector<char> oFilename(nBufSize);
             char *szPointerFilename = &oFilename[0];
             int nBytes = static_cast<int>(
                 readlink( pszFilename, szPointerFilename, nBufSize ) );
             if (nBytes != -1)
             {
-                szPointerFilename[MIN(nBytes, nBufSize - 1)] = 0;
+                szPointerFilename[std::min(nBytes, nBufSize - 1)] = 0;
                 CPLFree(pszFilename);
                 pszFilename = CPLStrdup(szPointerFilename);
                 papszSiblingsIn = NULL;
@@ -261,6 +273,9 @@ GDALOpenInfo::~GDALOpenInfo()
 /*                         GetSiblingFiles()                            */
 /************************************************************************/
 
+/** Return sibling files.
+ * @return sibling files. Ownership below to the object.
+ */
 char** GDALOpenInfo::GetSiblingFiles()
 {
     if( bHasGotSiblingFiles )
@@ -299,6 +314,9 @@ char** GDALOpenInfo::GetSiblingFiles()
 /*      member variable is set to NULL.                                 */
 /************************************************************************/
 
+/** Return sibling files and steal reference
+ * @return sibling files. Ownership below to the caller (must be freed with CSLDestroy)
+ */
 char** GDALOpenInfo::StealSiblingFiles()
 {
     char** papszRet = GetSiblingFiles();
@@ -310,6 +328,9 @@ char** GDALOpenInfo::StealSiblingFiles()
 /*                        AreSiblingFilesLoaded()                       */
 /************************************************************************/
 
+/** Return whether sibling files have been loaded.
+ * @return true or false.
+ */
 bool GDALOpenInfo::AreSiblingFilesLoaded() const
 {
     return bHasGotSiblingFiles;
@@ -319,6 +340,10 @@ bool GDALOpenInfo::AreSiblingFilesLoaded() const
 /*                           TryToIngest()                              */
 /************************************************************************/
 
+/** Ingest bytes from the file.
+ * @param nBytes number of bytes to ingest.
+ * @return TRUE if successful
+ */
 int GDALOpenInfo::TryToIngest(int nBytes)
 {
     if( fpL == NULL )
diff --git a/gcore/gdaloverviewdataset.cpp b/gcore/gdaloverviewdataset.cpp
index e081bfb..4b97164 100644
--- a/gcore/gdaloverviewdataset.cpp
+++ b/gcore/gdaloverviewdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdaloverviewdataset.cpp 33816 2016-03-30 13:18:07Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of a dataset overview warping class
@@ -27,10 +26,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_priv.h"
+
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "gdal.h"
 #include "gdal_mdreader.h"
 #include "gdal_proxy.h"
 
-CPL_CVSID("$Id: gdaloverviewdataset.cpp 33816 2016-03-30 13:18:07Z goatbar $");
+CPL_CVSID("$Id: gdaloverviewdataset.cpp 37723 2017-03-16 17:07:53Z rouault $");
 
 /** In GDAL, GDALRasterBand::GetOverview() returns a stand-alone band, that may
     have no parent dataset. This can be inconvenient in certain contexts, where
@@ -53,9 +62,8 @@ class GDALOverviewDataset : public GDALDataset
         friend class GDALOverviewBand;
 
         GDALDataset* poMainDS;
-        int          bOwnDS;
 
-        GDALDataset* poOvrDS; /* will be often NULL */
+        GDALDataset* poOvrDS;  // Will be often NULL.
         int          nOvrLevel;
         int          bThisLevelOnly;
 
@@ -64,37 +72,37 @@ class GDALOverviewDataset : public GDALDataset
         char       **papszMD_RPC;
         char       **papszMD_GEOLOCATION;
 
-        static void  Rescale(char**& papszMD, const char* pszItem,
-                             double dfRatio, double dfDefaultVal);
+        static void  Rescale( char**& papszMD, const char* pszItem,
+                              double dfRatio, double dfDefaultVal );
 
     protected:
         virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int,
-                                void *, int, int, GDALDataType,
-                                int, int *,
-                                GSpacing, GSpacing, GSpacing,
-                                GDALRasterIOExtraArg* psExtraArg );
+                                  void *, int, int, GDALDataType,
+                                  int, int *,
+                                  GSpacing, GSpacing, GSpacing,
+                                  GDALRasterIOExtraArg* psExtraArg ) override;
 
     public:
-                        GDALOverviewDataset(GDALDataset* poMainDS, int nOvrLevel,
-                                            int bThisLevelOnly,
-                                            int bOwnDS);
+                        GDALOverviewDataset( GDALDataset* poMainDS,
+                                             int nOvrLevel,
+                                             int bThisLevelOnly );
         virtual        ~GDALOverviewDataset();
 
-        virtual const char *GetProjectionRef(void);
-        virtual CPLErr GetGeoTransform( double * );
+        virtual const char *GetProjectionRef( void ) override;
+        virtual CPLErr GetGeoTransform( double * ) override;
 
-        virtual int    GetGCPCount();
-        virtual const char *GetGCPProjection();
-        virtual const GDAL_GCP *GetGCPs();
+        virtual int    GetGCPCount() override;
+        virtual const char *GetGCPProjection() override;
+        virtual const GDAL_GCP *GetGCPs() override;
 
-        virtual char  **GetMetadata( const char * pszDomain = "" );
+        virtual char  **GetMetadata( const char * pszDomain = "" ) override;
         virtual const char *GetMetadataItem( const char * pszName,
-                                             const char * pszDomain = "" );
+                                             const char * pszDomain = "" ) override;
 
-        virtual int        CloseDependentDatasets();
+        virtual int        CloseDependentDatasets() override;
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALOverviewDataset);
+    CPL_DISALLOW_COPY_ASSIGN(GDALOverviewDataset)
 };
 
 /* ******************************************************************** */
@@ -107,34 +115,35 @@ class GDALOverviewBand : public GDALProxyRasterBand
         friend class GDALOverviewDataset;
 
         GDALRasterBand*         poUnderlyingBand;
-        virtual GDALRasterBand* RefUnderlyingRasterBand();
+        virtual GDALRasterBand* RefUnderlyingRasterBand() override;
 
     public:
-                    GDALOverviewBand(GDALOverviewDataset* poDS, int nBand);
+                    GDALOverviewBand( GDALOverviewDataset* poDS, int nBand );
         virtual    ~GDALOverviewBand();
 
-        virtual CPLErr FlushCache();
+        virtual CPLErr FlushCache() override;
 
-        virtual int GetOverviewCount();
-        virtual GDALRasterBand *GetOverview(int);
+        virtual int GetOverviewCount() override;
+        virtual GDALRasterBand *GetOverview( int ) override;
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(GDALOverviewBand);
+    CPL_DISALLOW_COPY_ASSIGN(GDALOverviewBand)
 };
 
 /************************************************************************/
 /*                       GDALCreateOverviewDataset()                    */
 /************************************************************************/
 
-GDALDataset* GDALCreateOverviewDataset(GDALDataset* poMainDS, int nOvrLevel,
-                                       int bThisLevelOnly, int bOwnDS)
+// Takes a reference on poMainDS in case of success.
+GDALDataset* GDALCreateOverviewDataset( GDALDataset* poMainDS, int nOvrLevel,
+                                        int bThisLevelOnly )
 {
-    /* Sanity checks */
+    // Sanity checks.
     const int nBands = poMainDS->GetRasterCount();
     if( nBands == 0 )
         return NULL;
 
-    for( int i = 1; i<= nBands; i++ )
+    for( int i = 1; i<= nBands; ++i )
     {
         if( poMainDS->GetRasterBand(i)->GetOverview(nOvrLevel) == NULL )
         {
@@ -149,19 +158,17 @@ GDALDataset* GDALCreateOverviewDataset(GDALDataset* poMainDS, int nOvrLevel,
         }
     }
 
-    return new GDALOverviewDataset(poMainDS, nOvrLevel, bThisLevelOnly, bOwnDS);
+    return new GDALOverviewDataset(poMainDS, nOvrLevel, bThisLevelOnly);
 }
 
 /************************************************************************/
 /*                        GDALOverviewDataset()                         */
 /************************************************************************/
 
-GDALOverviewDataset::GDALOverviewDataset(GDALDataset* poMainDSIn,
-                                         int nOvrLevelIn,
-                                         int bThisLevelOnlyIn,
-                                         int bOwnDSIn) :
+GDALOverviewDataset::GDALOverviewDataset( GDALDataset* poMainDSIn,
+                                          int nOvrLevelIn,
+                                          int bThisLevelOnlyIn ) :
     poMainDS(poMainDSIn),
-    bOwnDS(bOwnDSIn),
     nOvrLevel(nOvrLevelIn),
     bThisLevelOnly(bThisLevelOnlyIn),
     nGCPCount(0),
@@ -169,6 +176,7 @@ GDALOverviewDataset::GDALOverviewDataset(GDALDataset* poMainDSIn,
     papszMD_RPC(NULL),
     papszMD_GEOLOCATION(NULL)
 {
+    poMainDSIn->Reference();
     eAccess = poMainDS->GetAccess();
     nRasterXSize =
         poMainDS->GetRasterBand(1)->GetOverview(nOvrLevel)->GetXSize();
@@ -183,15 +191,15 @@ GDALOverviewDataset::GDALOverviewDataset(GDALDataset* poMainDSIn,
         poOvrDS = NULL;
     }
     nBands = poMainDS->GetRasterCount();
-    for(int i=0;i<nBands;i++)
+    for( int i = 0; i < nBands; ++i )
     {
         SetBand(i+1, new GDALOverviewBand(this, i+1));
     }
 
-    /* We create a fake driver that has the same name as the original */
-    /* one, but we cannot use the real driver object, so that code */
-    /* doesn't try to cast the GDALOverviewDataset* as a native dataset */
-    /* object */
+    // We create a fake driver that has the same name as the original
+    // one, but we cannot use the real driver object, so that code
+    // doesn't try to cast the GDALOverviewDataset* as a native dataset
+    // object.
     if( poMainDS->GetDriver() != NULL )
     {
         poDriver = new GDALDriver();
@@ -202,10 +210,10 @@ GDALOverviewDataset::GDALOverviewDataset(GDALDataset* poMainDSIn,
     SetDescription( poMainDS->GetDescription() );
 
     CPLDebug( "GDAL", "GDALOverviewDataset(%s, this=%p) creation.",
-                          poMainDS->GetDescription(), this );
+              poMainDS->GetDescription(), this );
 
     papszOpenOptions = CSLDuplicate(poMainDS->GetOpenOptions());
-    /* Add OVERVIEW_LEVEL if not called from GDALOpenEx() but directly */
+    // Add OVERVIEW_LEVEL if not called from GDALOpenEx(), but directly.
     papszOpenOptions = CSLSetNameValue(papszOpenOptions, "OVERVIEW_LEVEL",
                                        CPLSPrintf("%d", nOvrLevel));
 }
@@ -238,26 +246,25 @@ GDALOverviewDataset::~GDALOverviewDataset()
 
 int GDALOverviewDataset::CloseDependentDatasets()
 {
-    int bRet = FALSE;
+    bool bRet = false;
 
-    if( bOwnDS )
+    if( poMainDS )
     {
-        for(int i=0;i<nBands;i++)
+        for( int i = 0; i < nBands; ++i )
         {
             GDALOverviewBand* const band =
                 dynamic_cast<GDALOverviewBand*>(papoBands[i]);
             if( band == NULL )
             {
                 CPLError( CE_Fatal, CPLE_AppDefined,
-                          "OverviewBand cast fail." );
-                return FALSE;
+                            "OverviewBand cast fail." );
+                return false;
             }
             band->poUnderlyingBand = NULL;
         }
-        GDALClose( poMainDS );
+        if( poMainDS->ReleaseRef() )
+            bRet = true;
         poMainDS = NULL;
-        bOwnDS = FALSE;
-        bRet = TRUE;
     }
 
     return bRet;
@@ -272,22 +279,26 @@ int GDALOverviewDataset::CloseDependentDatasets()
 /************************************************************************/
 
 CPLErr GDALOverviewDataset::IRasterIO( GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg)
+                                       int nXOff, int nYOff,
+                                       int nXSize, int nYSize,
+                                       void * pData,
+                                       int nBufXSize, int nBufYSize,
+                                       GDALDataType eBufType,
+                                       int nBandCount, int *panBandMap,
+                                       GSpacing nPixelSpace,
+                                       GSpacing nLineSpace,
+                                       GSpacing nBandSpace,
+                                       GDALRasterIOExtraArg* psExtraArg )
 
 {
-    /* In case the overview bands are really linked to a dataset, then issue */
-    /* the request to that dataset */
+    // In case the overview bands are really linked to a dataset, then issue
+    // the request to that dataset.
     if( poOvrDS != NULL )
     {
         return poOvrDS->RasterIO(
             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
-            eBufType, nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
+            eBufType, nBandCount, panBandMap, nPixelSpace,
+            nLineSpace, nBandSpace,
             psExtraArg);
     }
 
@@ -297,12 +308,12 @@ CPLErr GDALOverviewDataset::IRasterIO( GDALRWFlag eRWFlag,
 
     for( int iBandIndex = 0;
          iBandIndex < nBandCount && eErr == CE_None;
-         iBandIndex++ )
+         ++iBandIndex )
     {
         GDALOverviewBand *poBand =
             dynamic_cast<GDALOverviewBand *>(
                 GetRasterBand(panBandMap[iBandIndex]) );
-        if (poBand == NULL)
+        if( poBand == NULL )
         {
             eErr = CE_Failure;
             break;
@@ -350,7 +361,7 @@ const char *GDALOverviewDataset::GetProjectionRef()
 CPLErr GDALOverviewDataset::GetGeoTransform( double * padfTransform )
 
 {
-    double adfGeoTransform[6] = { 0.0 };
+    double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
     if( poMainDS->GetGeoTransform(adfGeoTransform) != CE_None )
         return CE_Failure;
 
@@ -404,7 +415,7 @@ const GDAL_GCP *GDALOverviewDataset::GetGCPs()
     nGCPCount = poMainDS->GetGCPCount();
 
     pasGCPList = GDALDuplicateGCPs( nGCPCount, pasGCPsMain );
-    for(int i = 0; i < nGCPCount; i++)
+    for( int i = 0; i < nGCPCount; ++i )
     {
         pasGCPList[i].dfGCPPixel *= static_cast<double>(nRasterXSize) /
             poMainDS->GetRasterXSize();
@@ -418,8 +429,8 @@ const GDAL_GCP *GDALOverviewDataset::GetGCPs()
 /*                             Rescale()                                */
 /************************************************************************/
 
-void GDALOverviewDataset::Rescale(char**& papszMD, const char* pszItem,
-                                  double dfRatio, double dfDefaultVal)
+void GDALOverviewDataset::Rescale( char**& papszMD, const char* pszItem,
+                                   double dfRatio, double dfDefaultVal )
 {
     double dfVal =
         CPLAtofM( CSLFetchNameValueDef(papszMD, pszItem,
@@ -434,7 +445,7 @@ void GDALOverviewDataset::Rescale(char**& papszMD, const char* pszItem,
 
 char  **GDALOverviewDataset::GetMetadata( const char * pszDomain )
 {
-    if (poOvrDS != NULL)
+    if( poOvrDS != NULL )
     {
         char** papszMD = poOvrDS->GetMetadata(pszDomain);
         if( papszMD != NULL )
@@ -443,7 +454,7 @@ char  **GDALOverviewDataset::GetMetadata( const char * pszDomain )
 
     char** papszMD = poMainDS->GetMetadata(pszDomain);
 
-    /* We may need to rescale some values from the RPC metadata domain */
+    // We may need to rescale some values from the RPC metadata domain.
     if( pszDomain != NULL && EQUAL(pszDomain, MD_DOMAIN_RPC) &&
         papszMD != NULL )
     {
@@ -502,7 +513,7 @@ char  **GDALOverviewDataset::GetMetadata( const char * pszDomain )
 const char *GDALOverviewDataset::GetMetadataItem( const char * pszName,
                                                   const char * pszDomain )
 {
-    if (poOvrDS != NULL)
+    if( poOvrDS != NULL )
     {
         const char* pszValue = poOvrDS->GetMetadataItem(pszName, pszDomain);
         if( pszValue != NULL )
@@ -523,11 +534,12 @@ const char *GDALOverviewDataset::GetMetadataItem( const char * pszName,
 /*                          GDALOverviewBand()                          */
 /************************************************************************/
 
-GDALOverviewBand::GDALOverviewBand(GDALOverviewDataset* poDSIn, int nBandIn)
+GDALOverviewBand::GDALOverviewBand( GDALOverviewDataset* poDSIn, int nBandIn ) :
+    poUnderlyingBand(poDSIn->poMainDS->GetRasterBand(nBandIn)->
+                         GetOverview(poDSIn->nOvrLevel))
 {
     poDS = poDSIn;
     nBand = nBandIn;
-    poUnderlyingBand = poDSIn->poMainDS->GetRasterBand(nBand)->GetOverview(poDSIn->nOvrLevel);
     nRasterXSize = poDSIn->nRasterXSize;
     nRasterYSize = poDSIn->nRasterYSize;
     eDataType = poUnderlyingBand->GetRasterDataType();
@@ -590,7 +602,7 @@ int GDALOverviewBand::GetOverviewCount()
 /*                           GetOverview()                              */
 /************************************************************************/
 
-GDALRasterBand *GDALOverviewBand::GetOverview(int iOvr)
+GDALRasterBand *GDALOverviewBand::GetOverview( int iOvr )
 {
     if( iOvr < 0 || iOvr >= GetOverviewCount() )
         return NULL;
diff --git a/gcore/gdalpamdataset.cpp b/gcore/gdalpamdataset.cpp
index 46f05eb..6750517 100644
--- a/gcore/gdalpamdataset.cpp
+++ b/gcore/gdalpamdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalpamdataset.cpp 33760 2016-03-21 13:52:50Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALPamDataset, a dataset base class that
@@ -29,11 +28,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h"
+#include "cpl_port.h"
 #include "gdal_pam.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdalpamdataset.cpp 33760 2016-03-21 13:52:50Z goatbar $");
+CPL_CVSID("$Id: gdalpamdataset.cpp 37188 2017-01-19 15:53:01Z rouault $");
 
 /************************************************************************/
 /*                           GDALPamDataset()                           */
@@ -124,6 +138,7 @@ CPL_CVSID("$Id: gdalpamdataset.cpp 33760 2016-03-21 13:52:50Z goatbar $");
  *      poDS->TryLoadXML();
  * \endcode
  */
+class GDALPamDataset;
 
 GDALPamDataset::GDALPamDataset() :
     nPamFlags(0),
@@ -164,6 +179,7 @@ void GDALPamDataset::FlushCache()
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLXMLNode *GDALPamDataset::SerializeToXML( const char *pszUnused )
 
 {
@@ -398,44 +414,64 @@ CPLErr GDALPamDataset::XMLInit( CPLXMLNode *psTree, const char *pszUnused )
     oMDMD.XMLInit( psTree, TRUE );
 
 /* -------------------------------------------------------------------- */
-/*      Try loading ESRI xml encoded projection                         */
+/*      Try loading ESRI xml encoded GeodataXform.                      */
 /* -------------------------------------------------------------------- */
     if (psPam->pszProjection == NULL)
     {
-        char** papszXML = oMDMD.GetMetadata( "xml:ESRI" );
-        if (CSLCount(papszXML) == 1)
+        // ArcGIS 9.3: GeodataXform as a root element
+        CPLXMLNode* psGeodataXform = CPLGetXMLNode(psTree, "=GeodataXform");
+        CPLXMLNode *psValueAsXML = NULL;
+        if( psGeodataXform != NULL )
         {
-            CPLXMLNode *psValueAsXML = CPLParseXMLString( papszXML[0] );
-            if (psValueAsXML)
+            char* apszMD[2];
+            apszMD[0] = CPLSerializeXMLTree(psGeodataXform);
+            apszMD[1] = NULL;
+            oMDMD.SetMetadata( apszMD, "xml:ESRI");
+            CPLFree(apszMD[0]);
+        }
+        else
+        {
+            // ArcGIS 10: GeodataXform as content of xml:ESRI metadata domain.
+            char** papszXML = oMDMD.GetMetadata( "xml:ESRI" );
+            if (CSLCount(papszXML) == 1)
             {
-                const char* pszESRI_WKT = CPLGetXMLValue(psValueAsXML,
-                                  "=GeodataXform.SpatialReference.WKT", NULL);
-                if (pszESRI_WKT)
+                psValueAsXML = CPLParseXMLString( papszXML[0] );
+                if( psValueAsXML )
+                    psGeodataXform = CPLGetXMLNode(psValueAsXML, "=GeodataXform");
+            }
+        }
+
+        if (psGeodataXform)
+        {
+            const char* pszESRI_WKT = CPLGetXMLValue(psGeodataXform,
+                                "SpatialReference.WKT", NULL);
+            if (pszESRI_WKT)
+            {
+                OGRSpatialReference* poSRS = new OGRSpatialReference(NULL);
+                char* pszTmp = (char*)pszESRI_WKT;
+                if (poSRS->importFromWkt(&pszTmp) == OGRERR_NONE &&
+                    poSRS->morphFromESRI() == OGRERR_NONE)
                 {
-                    OGRSpatialReference* poSRS = new OGRSpatialReference(NULL);
-                    char* pszTmp = (char*)pszESRI_WKT;
-                    if (poSRS->importFromWkt(&pszTmp) == OGRERR_NONE &&
-                        poSRS->morphFromESRI() == OGRERR_NONE)
+                    char* pszWKT = NULL;
+                    if (poSRS->exportToWkt(&pszWKT) == OGRERR_NONE)
                     {
-                        char* pszWKT = NULL;
-                        if (poSRS->exportToWkt(&pszWKT) == OGRERR_NONE)
-                        {
-                            psPam->pszProjection = CPLStrdup(pszWKT);
-                        }
-                        CPLFree(pszWKT);
+                        psPam->pszProjection = CPLStrdup(pszWKT);
                     }
-                    delete poSRS;
+                    CPLFree(pszWKT);
                 }
-                CPLDestroyXMLNode(psValueAsXML);
+                delete poSRS;
             }
         }
+        if( psValueAsXML )
+            CPLDestroyXMLNode(psValueAsXML);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Process bands.                                                  */
 /* -------------------------------------------------------------------- */
     for( CPLXMLNode *psBandTree = psTree->psChild;
-         psBandTree != NULL; psBandTree = psBandTree->psNext )
+         psBandTree != NULL;
+         psBandTree = psBandTree->psNext )
     {
         if( psBandTree->eType != CXT_Element
             || !EQUAL(psBandTree->pszValue,"PAMRasterBand") )
@@ -622,6 +658,10 @@ CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
     VSIStatBufL sStatBuf;
     CPLXMLNode *psTree = NULL;
 
+    CPLErr eLastErr = CPLGetLastErrorType();
+    int nLastErrNo = CPLGetLastErrorNo();
+    CPLString osLastErrorMsg = CPLGetLastErrorMsg();
+
     if (papszSiblingFiles != NULL && IsPamFilenameAPotentialSiblingFile())
     {
         const int iSibling =
@@ -633,6 +673,7 @@ CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
             CPLPushErrorHandler( CPLQuietErrorHandler );
             psTree = CPLParseXMLFile( psPam->pszPamFilename );
             CPLPopErrorHandler();
+            CPLErrorReset();
         }
     }
     else
@@ -644,13 +685,16 @@ CPLErr GDALPamDataset::TryLoadXML(char **papszSiblingFiles)
         CPLPushErrorHandler( CPLQuietErrorHandler );
         psTree = CPLParseXMLFile( psPam->pszPamFilename );
         CPLPopErrorHandler();
+        CPLErrorReset();
     }
 
+    if( eLastErr != CE_None )
+        CPLErrorSetState( eLastErr, nLastErrNo, osLastErrorMsg.c_str() );
+
 /* -------------------------------------------------------------------- */
-/*      If we are looking for a subdataset, search for it's subtree     */
-/*      now.                                                            */
+/*      If we are looking for a subdataset, search for its subtree not. */
 /* -------------------------------------------------------------------- */
-    if( psTree && psPam->osSubdatasetName.size() )
+    if( psTree && !psPam->osSubdatasetName.empty() )
     {
         CPLXMLNode *psSubTree = psTree->psChild;
 
@@ -735,7 +779,7 @@ CPLErr GDALPamDataset::TrySaveXML()
 /*      the subdataset tree within the whole existing pam tree,         */
 /*      after removing any old version of the same subdataset.          */
 /* -------------------------------------------------------------------- */
-    if( psPam->osSubdatasetName.size() != 0 )
+    if( !psPam->osSubdatasetName.empty() )
     {
         CPLXMLNode *psOldTree, *psSubTree;
 
@@ -965,6 +1009,7 @@ CPLErr GDALPamDataset::CloneInfo( GDALDataset *poSrcDS, int nCloneFlags )
 
     return CE_None;
 }
+//! @endcond
 
 /************************************************************************/
 /*                            GetFileList()                             */
@@ -977,7 +1022,7 @@ char **GDALPamDataset::GetFileList()
 {
     char **papszFileList = GDALDataset::GetFileList();
 
-    if( psPam && psPam->osPhysicalFilename.size() > 0
+    if( psPam && !psPam->osPhysicalFilename.empty()
         && CSLFindString( papszFileList, psPam->osPhysicalFilename ) == -1 )
     {
         papszFileList = CSLInsertString( papszFileList, 0,
@@ -1007,7 +1052,7 @@ char **GDALPamDataset::GetFileList()
         }
     }
 
-    if( psPam && psPam->osAuxFilename.size() > 0 &&
+    if( psPam && !psPam->osAuxFilename.empty() &&
         CSLFindString( papszFileList, psPam->osAuxFilename ) == -1 )
     {
         papszFileList = CSLAddString( papszFileList, psPam->osAuxFilename );
@@ -1019,6 +1064,7 @@ char **GDALPamDataset::GetFileList()
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLErr GDALPamDataset::IBuildOverviews( const char *pszResampling,
                                         int nOverviews, int *panOverviewList,
                                         int nListBands, int *panBandList,
@@ -1055,7 +1101,7 @@ CPLErr GDALPamDataset::IBuildOverviews( const char *pszResampling,
                                          nListBands, panBandList,
                                          pfnProgress, pProgressData );
 }
-
+//! @endcond
 
 /************************************************************************/
 /*                          GetProjectionRef()                          */
@@ -1313,6 +1359,7 @@ char **GDALPamDataset::GetMetadata( const char *pszDomain )
 /*                             TryLoadAux()                             */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLErr GDALPamDataset::TryLoadAux(char **papszSiblingFiles)
 
 {
@@ -1471,3 +1518,4 @@ CPLErr GDALPamDataset::TryLoadAux(char **papszSiblingFiles)
 
     return CE_Failure;
 }
+//! @endcond
diff --git a/gcore/gdalpamproxydb.cpp b/gcore/gdalpamproxydb.cpp
index 5e274f9..4f29f54 100644
--- a/gcore/gdalpamproxydb.cpp
+++ b/gcore/gdalpamproxydb.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalpamproxydb.cpp 33766 2016-03-21 19:51:16Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of the GDAL PAM Proxy database interface.
@@ -30,12 +29,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal_pam.h"
+
+#include <cerrno>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "gdal_pam.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: gdalpamproxydb.cpp 33766 2016-03-21 19:51:16Z goatbar $");
+CPL_CVSID("$Id: gdalpamproxydb.cpp 36526 2016-11-27 15:46:54Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -269,7 +287,6 @@ void GDALPamProxyDB::SaveDB()
         CPLUnlockFile( hLock );
 }
 
-
 /************************************************************************/
 /*                            InitProxyDB()                             */
 /*                                                                      */
diff --git a/gcore/gdalpamrasterband.cpp b/gcore/gdalpamrasterband.cpp
index b93b721..84efc46 100644
--- a/gcore/gdalpamrasterband.cpp
+++ b/gcore/gdalpamrasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalpamrasterband.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALPamRasterBand, a raster band base class
@@ -30,11 +29,27 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_pam.h"
-#include "gdal_rat.h"
+
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "gdal_rat.h"
 
-CPL_CVSID("$Id: gdalpamrasterband.cpp 33694 2016-03-10 17:54:30Z goatbar $");
+CPL_CVSID("$Id: gdalpamrasterband.cpp 37690 2017-03-11 20:31:20Z rouault $");
 
 /************************************************************************/
 /*                         GDALPamRasterBand()                          */
@@ -51,12 +66,14 @@ GDALPamRasterBand::GDALPamRasterBand()
 /*                         GDALPamRasterBand()                          */
 /************************************************************************/
 
-GDALPamRasterBand::GDALPamRasterBand(int bForceCachedIOIn) : GDALRasterBand(bForceCachedIOIn)
-
+//! @cond Doxygen_Suppress
+GDALPamRasterBand::GDALPamRasterBand( int bForceCachedIOIn ) :
+    GDALRasterBand(bForceCachedIOIn)
 {
     psPam = NULL;
     SetMOFlags( GetMOFlags() | GMO_PAM_CLASS );
 }
+//! @endcond
 
 /************************************************************************/
 /*                         ~GDALPamRasterBand()                         */
@@ -72,7 +89,8 @@ GDALPamRasterBand::~GDALPamRasterBand()
 /*                           SerializeToXML()                           */
 /************************************************************************/
 
-CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused )
+//! @cond Doxygen_Suppress
+CPLXMLNode *GDALPamRasterBand::SerializeToXML( const char * /* pszUnused */ )
 {
     if( psPam == NULL )
         return NULL;
@@ -80,12 +98,9 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
 /* -------------------------------------------------------------------- */
 /*      Setup root node and attributes.                                 */
 /* -------------------------------------------------------------------- */
-    CPLString oFmt;
-
-    CPLXMLNode *psTree;
-
-    psTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMRasterBand" );
+    CPLXMLNode *psTree = CPLCreateXMLNode( NULL, CXT_Element, "PAMRasterBand" );
 
+    CPLString oFmt;
     if( GetBand() > 0 )
         CPLSetXMLValue( psTree, "#band", oFmt.Printf( "%d", GetBand() ) );
 
@@ -97,24 +112,24 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
 
     if( psPam->bNoDataValueSet )
     {
-        if (CPLIsNan(psPam->dfNoDataValue))
+        if( CPLIsNan(psPam->dfNoDataValue) )
             CPLSetXMLValue( psTree, "NoDataValue",  "nan" );
         else
             CPLSetXMLValue( psTree, "NoDataValue",
                             oFmt.Printf( "%.14E", psPam->dfNoDataValue ) );
 
-        /* hex encode real floating point values */
-        if( psPam->dfNoDataValue != floor(psPam->dfNoDataValue)
+        // Hex encode real floating point values.
+        if( psPam->dfNoDataValue != floor(psPam->dfNoDataValue )
             || psPam->dfNoDataValue != CPLAtof(oFmt) )
         {
-            double dfNoDataLittleEndian;
-
-            dfNoDataLittleEndian = psPam->dfNoDataValue;
+            double dfNoDataLittleEndian = psPam->dfNoDataValue;
             CPL_LSBPTR64( &dfNoDataLittleEndian );
 
             char *pszHexEncoding =
-                CPLBinaryToHex( 8, (GByte *) &dfNoDataLittleEndian );
-            CPLSetXMLValue( psTree, "NoDataValue.#le_hex_equiv",pszHexEncoding);
+                CPLBinaryToHex(
+                    8, reinterpret_cast<GByte *>( &dfNoDataLittleEndian ) );
+            CPLSetXMLValue( psTree, "NoDataValue.#le_hex_equiv",
+                            pszHexEncoding );
             CPLFree( pszHexEncoding );
         }
     }
@@ -145,8 +160,8 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
 
         for( int iEntry=0; psPam->papszCategoryNames[iEntry] != NULL; iEntry++)
         {
-            CPLXMLNode *psNode = CPLCreateXMLElementAndValue( NULL, "Category",
-                                         psPam->papszCategoryNames[iEntry] );
+            CPLXMLNode *psNode = CPLCreateXMLElementAndValue(
+                NULL, "Category", psPam->papszCategoryNames[iEntry] );
             if( psLastChild == NULL )
                 psCT_XML->psChild = psNode;
             else
@@ -164,10 +179,10 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
                                                  "ColorTable" );
         CPLXMLNode* psLastChild = NULL;
 
-        for( int iEntry=0; iEntry < psPam->poColorTable->GetColorEntryCount();
+        for( int iEntry = 0;
+             iEntry < psPam->poColorTable->GetColorEntryCount();
              iEntry++ )
         {
-            GDALColorEntry sEntry;
             CPLXMLNode *psEntry_XML = CPLCreateXMLNode( NULL, CXT_Element,
                                                         "Entry" );
             if( psLastChild == NULL )
@@ -176,6 +191,7 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
                 psLastChild->psNext = psEntry_XML;
             psLastChild = psEntry_XML;
 
+            GDALColorEntry sEntry;
             psPam->poColorTable->GetColorEntryAsRGB( iEntry, &sEntry );
 
             CPLSetXMLValue( psEntry_XML, "#c1", oFmt.Printf("%d",sEntry.c1) );
@@ -226,9 +242,7 @@ CPLXMLNode *GDALPamRasterBand::SerializeToXML( CPL_UNUSED const char *pszUnused
 /* -------------------------------------------------------------------- */
 /*      Metadata.                                                       */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psMD;
-
-    psMD = oMDMD.Serialize();
+    CPLXMLNode *psMD = oMDMD.Serialize();
     if( psMD != NULL )
     {
         CPLAddXMLChild( psTree, psMD );
@@ -258,10 +272,16 @@ void GDALPamRasterBand::PamInitialize()
         return;
 
     GDALDataset* poNonPamParentDS = GetDataset();
-    if( poNonPamParentDS == NULL || !(poNonPamParentDS->GetMOFlags() & GMO_PAM_CLASS) )
+    if( poNonPamParentDS == NULL ||
+        !(poNonPamParentDS->GetMOFlags() & GMO_PAM_CLASS) )
         return;
 
-    GDALPamDataset *poParentDS = (GDALPamDataset *) poNonPamParentDS;
+    GDALPamDataset *poParentDS =
+        dynamic_cast<GDALPamDataset *>( poNonPamParentDS );
+    if( poParentDS == NULL ) {
+        // Should never happen.
+        CPLAssert(false);
+    }
 
     poParentDS->PamInitialize();
     if( poParentDS->psPam == NULL )
@@ -271,8 +291,8 @@ void GDALPamRasterBand::PamInitialize()
     if( psPam != NULL )
         return;
 
-    psPam = (GDALRasterBandPamInfo *)
-        VSI_CALLOC_VERBOSE(sizeof(GDALRasterBandPamInfo),1);
+    psPam = static_cast<GDALRasterBandPamInfo *>(
+        VSI_CALLOC_VERBOSE(sizeof(GDALRasterBandPamInfo), 1) );
     if( psPam == NULL )
         return;
 
@@ -289,37 +309,38 @@ void GDALPamRasterBand::PamInitialize()
 void GDALPamRasterBand::PamClear()
 
 {
-    if( psPam )
-    {
-        if( psPam->poColorTable )
-            delete psPam->poColorTable;
-        psPam->poColorTable = NULL;
+    if( !psPam )
+        return;
 
-        CPLFree( psPam->pszUnitType );
-        CSLDestroy( psPam->papszCategoryNames );
+    if( psPam->poColorTable )
+        delete psPam->poColorTable;
+    psPam->poColorTable = NULL;
 
-        if( psPam->poDefaultRAT != NULL )
-        {
-            delete psPam->poDefaultRAT;
-            psPam->poDefaultRAT = NULL;
-        }
+    CPLFree( psPam->pszUnitType );
+    CSLDestroy( psPam->papszCategoryNames );
 
-        if (psPam->psSavedHistograms != NULL)
-        {
-            CPLDestroyXMLNode (psPam->psSavedHistograms );
-            psPam->psSavedHistograms = NULL;
-        }
+    if( psPam->poDefaultRAT != NULL )
+    {
+        delete psPam->poDefaultRAT;
+        psPam->poDefaultRAT = NULL;
+    }
 
-        CPLFree( psPam );
-        psPam = NULL;
+    if( psPam->psSavedHistograms != NULL )
+    {
+        CPLDestroyXMLNode (psPam->psSavedHistograms );
+        psPam->psSavedHistograms = NULL;
     }
+
+    CPLFree( psPam );
+    psPam = NULL;
 }
 
 /************************************************************************/
 /*                              XMLInit()                               */
 /************************************************************************/
 
-CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *pszUnused )
+CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree,
+                                   const char * /* pszUnused */ )
 {
     PamInitialize();
 
@@ -331,7 +352,8 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
 /* -------------------------------------------------------------------- */
 /*      Collect various other items of metadata.                        */
 /* -------------------------------------------------------------------- */
-    GDALMajorObject::SetDescription( CPLGetXMLValue( psTree, "Description", "" ) );
+    GDALMajorObject::SetDescription(
+        CPLGetXMLValue( psTree, "Description", "" ) );
 
     if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL )
     {
@@ -372,7 +394,7 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
     {
         const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL );
         GDALPamRasterBand::SetColorInterpretation(
-                                GDALGetColorInterpretationByName(pszInterp));
+            GDALGetColorInterpretationByName(pszInterp));
     }
 
 /* -------------------------------------------------------------------- */
@@ -380,20 +402,22 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL )
     {
-        CPLXMLNode *psEntry;
         CPLStringList oCategoryNames;
 
-        for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
-             psEntry != NULL; psEntry = psEntry->psNext )
+        for( CPLXMLNode *psEntry =
+                 CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
+             psEntry != NULL;
+             psEntry = psEntry->psNext )
         {
             /* Don't skeep <Category> tag with empty content */
             if( psEntry->eType != CXT_Element
                 || !EQUAL(psEntry->pszValue,"Category")
-                || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) )
+                || (psEntry->psChild != NULL &&
+                    psEntry->psChild->eType != CXT_Text) )
                 continue;
 
             oCategoryNames.AddString(
-                                 (psEntry->psChild) ? psEntry->psChild->pszValue : "" );
+                psEntry->psChild ? psEntry->psChild->pszValue : "" );
         }
 
         GDALPamRasterBand::SetCategoryNames( oCategoryNames.List() );
@@ -404,19 +428,26 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
 /* -------------------------------------------------------------------- */
     if( CPLGetXMLNode( psTree, "ColorTable" ) != NULL )
     {
-        CPLXMLNode *psEntry;
         GDALColorTable oTable;
-        int        iEntry = 0;
+        int iEntry = 0;
 
-        for( psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild;
-             psEntry != NULL; psEntry = psEntry->psNext )
+        for( CPLXMLNode *psEntry =
+                 CPLGetXMLNode( psTree, "ColorTable" )->psChild;
+             psEntry != NULL;
+             psEntry = psEntry->psNext )
         {
-            GDALColorEntry sCEntry;
+            if( !(psEntry->eType == CXT_Element &&
+                  EQUAL(psEntry->pszValue, "Entry")) )
+            {
+                continue;
+            }
 
-            sCEntry.c1 = (short) atoi(CPLGetXMLValue( psEntry, "c1", "0" ));
-            sCEntry.c2 = (short) atoi(CPLGetXMLValue( psEntry, "c2", "0" ));
-            sCEntry.c3 = (short) atoi(CPLGetXMLValue( psEntry, "c3", "0" ));
-            sCEntry.c4 = (short) atoi(CPLGetXMLValue( psEntry, "c4", "255" ));
+            GDALColorEntry sCEntry = {
+                static_cast<short>(atoi(CPLGetXMLValue( psEntry, "c1", "0" ))),
+                static_cast<short>(atoi(CPLGetXMLValue( psEntry, "c2", "0" ))),
+                static_cast<short>(atoi(CPLGetXMLValue( psEntry, "c3", "0" ))),
+                static_cast<short>(atoi(CPLGetXMLValue( psEntry, "c4", "255" )))
+            };
 
             oTable.SetColorEntry( iEntry++, &sCEntry );
         }
@@ -431,16 +462,17 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
         && CPLGetXMLNode( psTree, "Maximum" ) != NULL )
     {
         psPam->bHaveMinMax = TRUE;
-        psPam->dfMin = CPLAtof(CPLGetXMLValue(psTree, "Minimum","0"));
-        psPam->dfMax = CPLAtof(CPLGetXMLValue(psTree, "Maximum","0"));
+        psPam->dfMin = CPLAtofM(CPLGetXMLValue(psTree, "Minimum","0"));
+        psPam->dfMax = CPLAtofM(CPLGetXMLValue(psTree, "Maximum","0"));
     }
 
     if( CPLGetXMLNode( psTree, "Mean" ) != NULL
         && CPLGetXMLNode( psTree, "StandardDeviation" ) != NULL )
     {
         psPam->bHaveStats = TRUE;
-        psPam->dfMean = CPLAtof(CPLGetXMLValue(psTree, "Mean","0"));
-        psPam->dfStdDev = CPLAtof(CPLGetXMLValue(psTree,"StandardDeviation","0"));
+        psPam->dfMean = CPLAtofM(CPLGetXMLValue(psTree, "Mean","0"));
+        psPam->dfStdDev =
+            CPLAtofM(CPLGetXMLValue(psTree, "StandardDeviation", "0"));
     }
 
 /* -------------------------------------------------------------------- */
@@ -452,7 +484,7 @@ CPLErr GDALPamRasterBand::XMLInit( CPLXMLNode *psTree, CPL_UNUSED const char *ps
         CPLXMLNode *psNext = psHist->psNext;
         psHist->psNext = NULL;
 
-        if (psPam->psSavedHistograms != NULL)
+        if( psPam->psSavedHistograms != NULL )
         {
             CPLDestroyXMLNode (psPam->psSavedHistograms );
             psPam->psSavedHistograms = NULL;
@@ -487,9 +519,8 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
                                      int nCloneFlags )
 
 {
-    int bOnlyIfMissing = nCloneFlags & GCIF_ONLY_IF_MISSING;
-    int bSuccess;
-    int nSavedMOFlags = GetMOFlags();
+    const bool bOnlyIfMissing = (nCloneFlags & GCIF_ONLY_IF_MISSING) != 0;
+    const int nSavedMOFlags = GetMOFlags();
 
     PamInitialize();
 
@@ -507,7 +538,8 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
         if( poSrcBand->GetMetadata() != NULL )
         {
             if( !bOnlyIfMissing
-             || CSLCount(GetMetadata()) != CSLCount(poSrcBand->GetMetadata()) )
+                || CSLCount(GetMetadata()) !=
+                CSLCount(poSrcBand->GetMetadata()) )
             {
                 SetMetadata( poSrcBand->GetMetadata() );
             }
@@ -531,7 +563,8 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
 /* -------------------------------------------------------------------- */
     if( nCloneFlags & GCIF_NODATA )
     {
-        double dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
+        int bSuccess = FALSE;  // TODO(schwehr): int -> bool.
+        const double dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
 
         if( bSuccess )
         {
@@ -550,7 +583,8 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
         if( poSrcBand->GetCategoryNames() != NULL )
         {
             if( !bOnlyIfMissing || GetCategoryNames() == NULL )
-                GDALPamRasterBand::SetCategoryNames( poSrcBand->GetCategoryNames() );
+                GDALPamRasterBand::SetCategoryNames(
+                    poSrcBand->GetCategoryNames() );
         }
     }
 
@@ -559,7 +593,8 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
 /* -------------------------------------------------------------------- */
     if( nCloneFlags & GCIF_SCALEOFFSET )
     {
-        double dfOffset = poSrcBand->GetOffset( &bSuccess );
+        int bSuccess = FALSE;  // TODO(schwehr): int -> bool.
+        const double dfOffset = poSrcBand->GetOffset( &bSuccess );
 
         if( bSuccess )
         {
@@ -567,7 +602,7 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
                 GDALPamRasterBand::SetOffset( dfOffset );
         }
 
-        double dfScale = poSrcBand->GetScale( &bSuccess );
+        const double dfScale = poSrcBand->GetScale( &bSuccess );
 
         if( bSuccess )
         {
@@ -644,13 +679,14 @@ CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand,
 
     return CE_None;
 }
+//! @endcond
 
 /************************************************************************/
 /*                            SetMetadata()                             */
 /************************************************************************/
 
 CPLErr GDALPamRasterBand::SetMetadata( char **papszMetadata,
-                                    const char *pszDomain )
+                                       const char *pszDomain )
 
 {
     PamInitialize();
@@ -666,8 +702,8 @@ CPLErr GDALPamRasterBand::SetMetadata( char **papszMetadata,
 /************************************************************************/
 
 CPLErr GDALPamRasterBand::SetMetadataItem( const char *pszName,
-                                        const char *pszValue,
-                                        const char *pszDomain )
+                                           const char *pszValue,
+                                           const char *pszDomain )
 
 {
     PamInitialize();
@@ -687,15 +723,13 @@ CPLErr GDALPamRasterBand::SetNoDataValue( double dfNewValue )
 {
     PamInitialize();
 
-    if( psPam )
-    {
-        psPam->bNoDataValueSet = TRUE;
-        psPam->dfNoDataValue = dfNewValue;
-        psPam->poParentDS->MarkPamDirty();
-        return CE_None;
-    }
-    else
+    if( !psPam )
         return GDALRasterBand::SetNoDataValue( dfNewValue );
+
+    psPam->bNoDataValueSet = TRUE;
+    psPam->dfNoDataValue = dfNewValue;
+    psPam->poParentDS->MarkPamDirty();
+    return CE_None;
 }
 
 /************************************************************************/
@@ -707,15 +741,13 @@ CPLErr GDALPamRasterBand::DeleteNoDataValue()
 {
     PamInitialize();
 
-    if( psPam )
-    {
-        psPam->bNoDataValueSet = FALSE;
-        psPam->dfNoDataValue = 0.0;
-        psPam->poParentDS->MarkPamDirty();
-        return CE_None;
-    }
-    else
+    if( !psPam )
         return GDALRasterBand::DeleteNoDataValue();
+
+    psPam->bNoDataValueSet = FALSE;
+    psPam->dfNoDataValue = 0.0;
+    psPam->poParentDS->MarkPamDirty();
+    return CE_None;
 }
 
 /************************************************************************/
@@ -725,15 +757,13 @@ CPLErr GDALPamRasterBand::DeleteNoDataValue()
 double GDALPamRasterBand::GetNoDataValue( int *pbSuccess )
 
 {
-    if( psPam != NULL )
-    {
-        if( pbSuccess )
-            *pbSuccess = psPam->bNoDataValueSet;
-
-        return psPam->dfNoDataValue;
-    }
-    else
+    if( psPam == NULL )
         return GDALRasterBand::GetNoDataValue( pbSuccess );
+
+    if( pbSuccess )
+        *pbSuccess = psPam->bNoDataValueSet;
+
+    return psPam->dfNoDataValue;
 }
 
 /************************************************************************/
@@ -743,15 +773,13 @@ double GDALPamRasterBand::GetNoDataValue( int *pbSuccess )
 double GDALPamRasterBand::GetOffset( int *pbSuccess )
 
 {
-    if( psPam )
-    {
-        if( pbSuccess != NULL )
-            *pbSuccess = TRUE;
-
-        return psPam->dfOffset;
-    }
-    else
+    if( !psPam )
         return GDALRasterBand::GetOffset( pbSuccess );
+
+    if( pbSuccess != NULL )
+        *pbSuccess = TRUE;
+
+    return psPam->dfOffset;
 }
 
 /************************************************************************/
@@ -763,18 +791,16 @@ CPLErr GDALPamRasterBand::SetOffset( double dfNewOffset )
 {
     PamInitialize();
 
-    if( psPam != NULL )
-    {
-        if( psPam->dfOffset != dfNewOffset )
-        {
-            psPam->dfOffset = dfNewOffset;
-            psPam->poParentDS->MarkPamDirty();
-        }
+    if( psPam == NULL )
+        return GDALRasterBand::SetOffset( dfNewOffset );
 
-        return CE_None;
+    if( psPam->dfOffset != dfNewOffset )
+    {
+        psPam->dfOffset = dfNewOffset;
+        psPam->poParentDS->MarkPamDirty();
     }
-    else
-        return GDALRasterBand::SetOffset( dfNewOffset );
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -784,15 +810,13 @@ CPLErr GDALPamRasterBand::SetOffset( double dfNewOffset )
 double GDALPamRasterBand::GetScale( int *pbSuccess )
 
 {
-    if( psPam )
-    {
-        if( pbSuccess != NULL )
-            *pbSuccess = TRUE;
-
-        return psPam->dfScale;
-    }
-    else
+    if( !psPam )
         return GDALRasterBand::GetScale( pbSuccess );
+
+    if( pbSuccess != NULL )
+        *pbSuccess = TRUE;
+
+    return psPam->dfScale;
 }
 
 /************************************************************************/
@@ -804,17 +828,15 @@ CPLErr GDALPamRasterBand::SetScale( double dfNewScale )
 {
     PamInitialize();
 
-    if( psPam != NULL )
+    if( psPam == NULL )
+        return GDALRasterBand::SetScale( dfNewScale );
+
+    if( dfNewScale != psPam->dfScale )
     {
-        if( dfNewScale != psPam->dfScale )
-        {
-            psPam->dfScale = dfNewScale;
-            psPam->poParentDS->MarkPamDirty();
-        }
-        return CE_None;
+        psPam->dfScale = dfNewScale;
+        psPam->poParentDS->MarkPamDirty();
     }
-    else
-        return GDALRasterBand::SetScale( dfNewScale );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -824,15 +846,13 @@ CPLErr GDALPamRasterBand::SetScale( double dfNewScale )
 const char *GDALPamRasterBand::GetUnitType()
 
 {
-    if( psPam != NULL )
-    {
-        if( psPam->pszUnitType == NULL )
-            return "";
-        else
-            return psPam->pszUnitType;
-    }
-    else
+    if( psPam == NULL )
         return GDALRasterBand::GetUnitType();
+
+    if( psPam->pszUnitType == NULL )
+        return "";
+
+    return psPam->pszUnitType;
 }
 
 /************************************************************************/
@@ -844,28 +864,26 @@ CPLErr GDALPamRasterBand::SetUnitType( const char *pszNewValue )
 {
     PamInitialize();
 
-    if( psPam )
-    {
-        if( pszNewValue == NULL || pszNewValue[0] == '\0' )
-        {
-            if (psPam->pszUnitType != NULL)
-                psPam->poParentDS->MarkPamDirty();
-            CPLFree( psPam->pszUnitType );
-            psPam->pszUnitType = NULL;
-        }
-        else
-        {
-            if (psPam->pszUnitType == NULL ||
-                strcmp(psPam->pszUnitType, pszNewValue) != 0)
-                psPam->poParentDS->MarkPamDirty();
-            CPLFree( psPam->pszUnitType );
-            psPam->pszUnitType = CPLStrdup(pszNewValue);
-        }
+    if( !psPam )
+        return GDALRasterBand::SetUnitType( pszNewValue );
 
-        return CE_None;
+    if( pszNewValue == NULL || pszNewValue[0] == '\0' )
+    {
+        if( psPam->pszUnitType != NULL )
+            psPam->poParentDS->MarkPamDirty();
+        CPLFree( psPam->pszUnitType );
+        psPam->pszUnitType = NULL;
     }
     else
-        return GDALRasterBand::SetUnitType( pszNewValue );
+    {
+        if( psPam->pszUnitType == NULL ||
+            strcmp(psPam->pszUnitType, pszNewValue) != 0 )
+            psPam->poParentDS->MarkPamDirty();
+        CPLFree( psPam->pszUnitType );
+        psPam->pszUnitType = CPLStrdup(pszNewValue);
+    }
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -877,8 +895,8 @@ char **GDALPamRasterBand::GetCategoryNames()
 {
     if( psPam )
         return psPam->papszCategoryNames;
-    else
-        return GDALRasterBand::GetCategoryNames();
+
+    return GDALRasterBand::GetCategoryNames();
 }
 
 /************************************************************************/
@@ -890,19 +908,15 @@ CPLErr GDALPamRasterBand::SetCategoryNames( char ** papszNewNames )
 {
     PamInitialize();
 
-    if( psPam )
-    {
-        CSLDestroy( psPam->papszCategoryNames );
-        psPam->papszCategoryNames = CSLDuplicate( papszNewNames );
-        psPam->poParentDS->MarkPamDirty();
-        return CE_None;
-    }
-    else
+    if( !psPam )
         return GDALRasterBand::SetCategoryNames( papszNewNames );
 
+    CSLDestroy( psPam->papszCategoryNames );
+    psPam->papszCategoryNames = CSLDuplicate( papszNewNames );
+    psPam->poParentDS->MarkPamDirty();
+    return CE_None;
 }
 
-
 /************************************************************************/
 /*                           GetColorTable()                            */
 /************************************************************************/
@@ -912,8 +926,8 @@ GDALColorTable *GDALPamRasterBand::GetColorTable()
 {
     if( psPam )
         return psPam->poColorTable;
-    else
-        return GDALRasterBand::GetColorTable();
+
+    return GDALRasterBand::GetColorTable();
 }
 
 /************************************************************************/
@@ -925,27 +939,24 @@ CPLErr GDALPamRasterBand::SetColorTable( GDALColorTable *poTableIn )
 {
     PamInitialize();
 
-    if( psPam )
-    {
-        if( psPam->poColorTable != NULL )
-        {
-            delete psPam->poColorTable;
-            psPam->poColorTable = NULL;
-        }
-
-        if( poTableIn )
-        {
-            psPam->poColorTable = poTableIn->Clone();
-            psPam->eColorInterp = GCI_PaletteIndex;
-        }
+    if( !psPam )
+        return GDALRasterBand::SetColorTable( poTableIn );
 
-        psPam->poParentDS->MarkPamDirty();
+    if( psPam->poColorTable != NULL )
+    {
+        delete psPam->poColorTable;
+        psPam->poColorTable = NULL;
+    }
 
-        return CE_None;
+    if( poTableIn )
+    {
+        psPam->poColorTable = poTableIn->Clone();
+        psPam->eColorInterp = GCI_PaletteIndex;
     }
-    else
-        return GDALRasterBand::SetColorTable( poTableIn );
 
+    psPam->poParentDS->MarkPamDirty();
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -965,8 +976,8 @@ CPLErr GDALPamRasterBand::SetColorInterpretation( GDALColorInterp eInterpIn )
 
         return CE_None;
     }
-    else
-        return GDALRasterBand::SetColorInterpretation( eInterpIn );
+
+    return GDALRasterBand::SetColorInterpretation( eInterpIn );
 }
 
 /************************************************************************/
@@ -978,8 +989,8 @@ GDALColorInterp GDALPamRasterBand::GetColorInterpretation()
 {
     if( psPam )
         return psPam->eColorInterp;
-    else
-        return GDALRasterBand::GetColorInterpretation();
+
+    return GDALRasterBand::GetColorInterpretation();
 }
 
 /************************************************************************/
@@ -1004,52 +1015,54 @@ void GDALPamRasterBand::SetDescription( const char *pszDescription )
 /*                         PamParseHistogram()                          */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 int
 PamParseHistogram( CPLXMLNode *psHistItem,
                    double *pdfMin, double *pdfMax,
                    int *pnBuckets, GUIntBig **ppanHistogram,
-                   CPL_UNUSED int *pbIncludeOutOfRange,
-                   CPL_UNUSED int *pbApproxOK )
+                   int * /* pbIncludeOutOfRange */,
+                   int * /* pbApproxOK */ )
 {
     if( psHistItem == NULL )
         return FALSE;
 
-    *pdfMin = CPLAtof(CPLGetXMLValue( psHistItem, "HistMin", "0"));
-    *pdfMax = CPLAtof(CPLGetXMLValue( psHistItem, "HistMax", "1"));
+    *pdfMin = CPLAtofM(CPLGetXMLValue( psHistItem, "HistMin", "0"));
+    *pdfMax = CPLAtofM(CPLGetXMLValue( psHistItem, "HistMax", "1"));
     *pnBuckets = atoi(CPLGetXMLValue( psHistItem, "BucketCount","2"));
 
-    if (*pnBuckets <= 0 || *pnBuckets > INT_MAX / 2)
+    if( *pnBuckets <= 0 || *pnBuckets > INT_MAX / 2 )
         return FALSE;
 
     if( ppanHistogram == NULL )
         return TRUE;
 
     // Fetch the histogram and use it.
-    int iBucket;
     const char *pszHistCounts = CPLGetXMLValue( psHistItem,
                                                 "HistCounts", "" );
 
-    /* Sanity check to test consistency of BucketCount and HistCounts */
-    if( strlen(pszHistCounts) < 2 * (size_t)(*pnBuckets) -1 )
+    // Sanity check to test consistency of BucketCount and HistCounts.
+    if( strlen(pszHistCounts) < 2 * static_cast<size_t>(*pnBuckets) - 1 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "HistCounts content isn't consistent with BucketCount value");
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "HistCounts content isn't consistent with BucketCount value" );
         return FALSE;
     }
 
-    *ppanHistogram = (GUIntBig *) VSICalloc(sizeof(GUIntBig),*pnBuckets);
-    if (*ppanHistogram == NULL)
+    *ppanHistogram = static_cast<GUIntBig *>(
+        VSICalloc(sizeof(GUIntBig),*pnBuckets) );
+    if( *ppanHistogram == NULL )
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot allocate memory for %d buckets", *pnBuckets);
+        CPLError( CE_Failure, CPLE_OutOfMemory,
+                  "Cannot allocate memory for %d buckets", *pnBuckets );
         return FALSE;
     }
 
-    for( iBucket = 0; iBucket < *pnBuckets; iBucket++ )
+    for( int iBucket = 0; iBucket < *pnBuckets; iBucket++ )
     {
         (*ppanHistogram)[iBucket] = CPLAtoGIntBig(pszHistCounts);
 
-        // skip to next number.
+        // Skip to next number.
         while( *pszHistCounts != '\0' && *pszHistCounts != '|' )
             pszHistCounts++;
         if( *pszHistCounts == '|' )
@@ -1071,23 +1084,26 @@ PamFindMatchingHistogram( CPLXMLNode *psSavedHistograms,
     if( psSavedHistograms == NULL )
         return NULL;
 
-    CPLXMLNode *psXMLHist;
-    for( psXMLHist = psSavedHistograms->psChild;
-         psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
+    for( CPLXMLNode *psXMLHist = psSavedHistograms->psChild;
+         psXMLHist != NULL;
+         psXMLHist = psXMLHist->psNext )
     {
         if( psXMLHist->eType != CXT_Element
             || !EQUAL(psXMLHist->pszValue,"HistItem") )
             continue;
 
-        double dfHistMin = CPLAtof(CPLGetXMLValue( psXMLHist, "HistMin", "0"));
-        double dfHistMax = CPLAtof(CPLGetXMLValue( psXMLHist, "HistMax", "0"));
+        const double dfHistMin =
+            CPLAtofM(CPLGetXMLValue( psXMLHist, "HistMin", "0"));
+        const double dfHistMax =
+            CPLAtofM(CPLGetXMLValue( psXMLHist, "HistMax", "0"));
 
-        if( !(ARE_REAL_EQUAL(dfHistMin, dfMin))
-            || !(ARE_REAL_EQUAL(dfHistMax, dfMax))
+        if( !(ARE_REAL_EQUAL(dfHistMin, dfMin) )
+            || !(ARE_REAL_EQUAL(dfHistMax, dfMax) )
             || atoi(CPLGetXMLValue( psXMLHist,
                                     "BucketCount","0")) != nBuckets
             || !atoi(CPLGetXMLValue( psXMLHist,
-                                     "IncludeOutOfRange","0")) != !bIncludeOutOfRange
+                                     "IncludeOutOfRange","0")) !=
+                !bIncludeOutOfRange
             || (!bApproxOK && atoi(CPLGetXMLValue( psXMLHist,
                                                    "Approximate","0"))) )
 
@@ -1109,22 +1125,17 @@ PamHistogramToXMLTree( double dfMin, double dfMax,
                        int bIncludeOutOfRange, int bApprox )
 
 {
-    char *pszHistCounts;
-    int iBucket;
-    size_t iHistOffset;
-    CPLXMLNode *psXMLHist;
-    CPLString oFmt;
-
     if( nBuckets > (INT_MAX - 10) / 12 )
         return NULL;
 
     const size_t nLen = 22 * static_cast<size_t>(nBuckets) + 10;
-    pszHistCounts = (char *) VSIMalloc(nLen);
+    char *pszHistCounts = static_cast<char *>( VSIMalloc(nLen) );
     if( pszHistCounts == NULL )
         return NULL;
 
-    psXMLHist = CPLCreateXMLNode( NULL, CXT_Element, "HistItem" );
+    CPLXMLNode *psXMLHist = CPLCreateXMLNode( NULL, CXT_Element, "HistItem" );
 
+    CPLString oFmt;
     CPLSetXMLValue( psXMLHist, "HistMin",
                     oFmt.Printf( "%.16g", dfMin ));
     CPLSetXMLValue( psXMLHist, "HistMax",
@@ -1136,9 +1147,9 @@ PamHistogramToXMLTree( double dfMin, double dfMax,
     CPLSetXMLValue( psXMLHist, "Approximate",
                     oFmt.Printf( "%d", bApprox ));
 
-    iHistOffset = 0;
+    size_t iHistOffset = 0;
     pszHistCounts[0] = '\0';
-    for( iBucket = 0; iBucket < nBuckets; iBucket++ )
+    for( int iBucket = 0; iBucket < nBuckets; iBucket++ )
     {
         snprintf( pszHistCounts + iHistOffset,
                   nLen - iHistOffset,
@@ -1153,6 +1164,7 @@ PamHistogramToXMLTree( double dfMin, double dfMax,
 
     return psXMLHist;
 }
+//! @endcond
 
 /************************************************************************/
 /*                            GetHistogram()                            */
@@ -1176,11 +1188,10 @@ CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
 /*      Check if we have a matching histogram.                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psHistItem;
-
-    psHistItem = PamFindMatchingHistogram( psPam->psSavedHistograms,
-                                           dfMin, dfMax, nBuckets,
-                                           bIncludeOutOfRange, bApproxOK );
+    CPLXMLNode * const psHistItem =
+        PamFindMatchingHistogram( psPam->psSavedHistograms,
+                                  dfMin, dfMax, nBuckets,
+                                  bIncludeOutOfRange, bApproxOK );
     if( psHistItem != NULL )
     {
         GUIntBig *panTempHist = NULL;
@@ -1209,26 +1220,25 @@ CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
 /*      Save an XML description of this histogram.                      */
 /* -------------------------------------------------------------------- */
-    if( eErr == CE_None )
-    {
-        CPLXMLNode *psXMLHist;
+    if( eErr != CE_None )
+        return eErr;
 
-        psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
-                                           panHistogram,
-                                           bIncludeOutOfRange, bApproxOK );
-        if( psXMLHist != NULL )
-        {
-            psPam->poParentDS->MarkPamDirty();
+    CPLXMLNode *psXMLHist = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
+                                                   panHistogram,
+                                                   bIncludeOutOfRange,
+                                                   bApproxOK );
+    if( psXMLHist != NULL )
+    {
+        psPam->poParentDS->MarkPamDirty();
 
-            if( psPam->psSavedHistograms == NULL )
-                psPam->psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
-                                                             "Histograms" );
+        if( psPam->psSavedHistograms == NULL )
+            psPam->psSavedHistograms = CPLCreateXMLNode( NULL, CXT_Element,
+                                                         "Histograms" );
 
-            CPLAddXMLChild( psPam->psSavedHistograms, psXMLHist );
-        }
+        CPLAddXMLChild( psPam->psSavedHistograms, psXMLHist );
     }
 
-    return eErr;
+    return CE_None;
 }
 
 /************************************************************************/
@@ -1236,11 +1246,10 @@ CPLErr GDALPamRasterBand::GetHistogram( double dfMin, double dfMax,
 /************************************************************************/
 
 CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
-                                               int nBuckets, GUIntBig *panHistogram)
+                                               int nBuckets,
+                                               GUIntBig *panHistogram )
 
 {
-    CPLXMLNode *psNode;
-
     PamInitialize();
 
     if( psPam == NULL )
@@ -1250,9 +1259,9 @@ CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
 /*      Do we have a matching histogram we should replace?              */
 /* -------------------------------------------------------------------- */
-    psNode = PamFindMatchingHistogram( psPam->psSavedHistograms,
-                                       dfMin, dfMax, nBuckets,
-                                       TRUE, TRUE );
+    CPLXMLNode *psNode = PamFindMatchingHistogram( psPam->psSavedHistograms,
+                                                   dfMin, dfMax, nBuckets,
+                                                   TRUE, TRUE );
     if( psNode != NULL )
     {
         /* blow this one away */
@@ -1263,10 +1272,8 @@ CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 /* -------------------------------------------------------------------- */
 /*      Translate into a histogram XML tree.                            */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psHistItem;
-
-    psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
-                                        panHistogram, TRUE, FALSE );
+    CPLXMLNode *psHistItem = PamHistogramToXMLTree( dfMin, dfMax, nBuckets,
+                                                    panHistogram, TRUE, FALSE );
     if( psHistItem == NULL )
         return CE_Failure;
 
@@ -1292,7 +1299,8 @@ CPLErr GDALPamRasterBand::SetDefaultHistogram( double dfMin, double dfMax,
 
 CPLErr
 GDALPamRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
-                                        int *pnBuckets, GUIntBig **ppanHistogram,
+                                        int *pnBuckets,
+                                        GUIntBig **ppanHistogram,
                                         int bForce,
                                         GDALProgressFunc pfnProgress,
                                         void *pProgressData )
@@ -1300,23 +1308,23 @@ GDALPamRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
 {
     if( psPam && psPam->psSavedHistograms != NULL )
     {
-        CPLXMLNode *psXMLHist;
+        CPLXMLNode *psXMLHist = psPam->psSavedHistograms->psChild;
 
-        for( psXMLHist = psPam->psSavedHistograms->psChild;
-             psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
+        for( ; psXMLHist != NULL; psXMLHist = psXMLHist->psNext )
         {
-            int bApprox, bIncludeOutOfRange;
-
             if( psXMLHist->eType != CXT_Element
                 || !EQUAL(psXMLHist->pszValue,"HistItem") )
                 continue;
 
+            // TODO(schwehr): int -> bool.
+            int bApprox = FALSE;
+            int bIncludeOutOfRange = FALSE;
             if( PamParseHistogram( psXMLHist, pdfMin, pdfMax, pnBuckets,
                                    ppanHistogram, &bIncludeOutOfRange,
                                    &bApprox ) )
                 return CE_None;
-            else
-                return CE_Failure;
+
+            return CE_Failure;
         }
     }
 
@@ -1344,7 +1352,7 @@ GDALRasterAttributeTable *GDALPamRasterBand::GetDefaultRAT()
 /*                           SetDefaultRAT()                            */
 /************************************************************************/
 
-CPLErr GDALPamRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT)
+CPLErr GDALPamRasterBand::SetDefaultRAT( const GDALRasterAttributeTable *poRAT )
 
 {
     PamInitialize();
diff --git a/gcore/gdalproxydataset.cpp b/gcore/gdalproxydataset.cpp
index 628da37..f111336 100644
--- a/gcore/gdalproxydataset.cpp
+++ b/gcore/gdalproxydataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalproxydataset.cpp 33694 2016-03-10 17:54:30Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  A dataset and raster band classes that act as proxy for underlying
@@ -28,15 +27,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_proxy.h"
 
-CPL_CVSID("$Id: gdalproxydataset.cpp 33694 2016-03-10 17:54:30Z goatbar $");
+#include <cstddef>
 
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_virtualmem.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+
+CPL_CVSID("$Id: gdalproxydataset.cpp 36526 2016-11-27 15:46:54Z goatbar $");
+
+/*! @cond Doxygen_Suppress */
 /* ******************************************************************** */
 /*                        GDALProxyDataset                              */
 /* ******************************************************************** */
 
-#define D_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, argList, argParams) \
+#define D_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, \
+                                argList, argParams) \
 retType GDALProxyDataset::methodName argList \
 { \
     retType ret; \
@@ -53,20 +63,77 @@ retType GDALProxyDataset::methodName argList \
     return ret; \
 }
 
-
-D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, IRasterIO,
-                        ( GDALRWFlag eRWFlag,
+CPLErr GDALProxyDataset::IRasterIO( GDALRWFlag eRWFlag,
                         int nXOff, int nYOff, int nXSize, int nYSize,
                         void * pData, int nBufXSize, int nBufYSize,
                         GDALDataType eBufType,
                         int nBandCount, int *panBandMap,
                         GSpacing nPixelSpace, GSpacing nLineSpace, GSpacing nBandSpace,
-                        GDALRasterIOExtraArg* psExtraArg),
-                        ( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                        pData, nBufXSize, nBufYSize,
-                        eBufType, nBandCount, panBandMap,
-                        nPixelSpace, nLineSpace, nBandSpace, psExtraArg ))
-
+                        GDALRasterIOExtraArg* psExtraArg)
+{
+    CPLErr ret;
+    GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
+    if (poUnderlyingDataset)
+    {
+/* -------------------------------------------------------------------- */
+/*      Do some validation of parameters.                               */
+/* -------------------------------------------------------------------- */
+        if( nXOff + nXSize > poUnderlyingDataset->GetRasterXSize() ||
+            nYOff + nYSize > poUnderlyingDataset->GetRasterYSize() )
+        {
+            ReportError( CE_Failure, CPLE_IllegalArg,
+                         "Access window out of range in RasterIO().  Requested\n"
+                         "(%d,%d) of size %dx%d on raster of %dx%d.",
+                         nXOff, nYOff, nXSize, nYSize,
+                         poUnderlyingDataset->GetRasterXSize(),
+                         poUnderlyingDataset->GetRasterYSize() );
+            ret = CE_Failure;
+        }
+        else if( panBandMap == NULL && nBandCount > poUnderlyingDataset->GetRasterCount() )
+        {
+            ReportError( CE_Failure, CPLE_IllegalArg,
+                        "%s: nBandCount cannot be greater than %d",
+                        "IRasterIO", poUnderlyingDataset->GetRasterCount() );
+            ret = CE_Failure;
+        }
+        else
+        {
+            ret = CE_None;
+            for( int i = 0; i < nBandCount && ret == CE_None; ++i )
+            {
+                int iBand = (panBandMap != NULL) ? panBandMap[i] : i + 1;
+                if( iBand < 1 || iBand > poUnderlyingDataset->GetRasterCount() )
+                {
+                    ReportError( CE_Failure, CPLE_IllegalArg,
+                              "%s: panBandMap[%d] = %d, this band does not exist on dataset.",
+                              "IRasterIO", i, iBand );
+                    ret = CE_Failure;
+                }
+
+                if( ret == CE_None && poUnderlyingDataset->GetRasterBand( iBand ) == NULL )
+                {
+                    ReportError( CE_Failure, CPLE_IllegalArg,
+                              "%s: panBandMap[%d]=%d, this band should exist but is NULL!",
+                              "IRasterIO", i, iBand );
+                    ret = CE_Failure;
+                }
+            }
+            if( ret != CE_Failure )
+            {
+                ret = poUnderlyingDataset->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                pData, nBufXSize, nBufYSize,
+                                eBufType, nBandCount, panBandMap,
+                                nPixelSpace, nLineSpace, nBandSpace, psExtraArg );
+            }
+        }
+        UnrefUnderlyingDataset(poUnderlyingDataset);
+    }
+    else
+    {
+        ret = CE_Failure;
+    }
+    return ret;
+}
 
 D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, IBuildOverviews,
                         ( const char *pszResampling,
@@ -127,15 +194,14 @@ D_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, CreateMaskBand, ( int nFlagsIn ), (n
 /*                    UnrefUnderlyingDataset()                        */
 /************************************************************************/
 
-void GDALProxyDataset::UnrefUnderlyingDataset(CPL_UNUSED GDALDataset* poUnderlyingDataset)
-{
-}
+void GDALProxyDataset::UnrefUnderlyingDataset(
+    GDALDataset* /* poUnderlyingDataset */)
+{}
 
 /* ******************************************************************** */
 /*                        GDALProxyRasterBand                           */
 /* ******************************************************************** */
 
-
 #define RB_PROXY_METHOD_WITH_RET(retType, retErrValue, methodName, argList, argParams) \
 retType GDALProxyRasterBand::methodName argList \
 { \
@@ -153,7 +219,6 @@ retType GDALProxyRasterBand::methodName argList \
     return ret; \
 }
 
-
 #define RB_PROXY_METHOD_WITH_RET_WITH_INIT_BLOCK(retType, retErrValue, methodName, argList, argParams) \
 retType GDALProxyRasterBand::methodName argList \
 { \
@@ -164,7 +229,24 @@ retType GDALProxyRasterBand::methodName argList \
         if( !poSrcBand->InitBlockInfo() ) \
             ret = CE_Failure; \
         else \
-            ret = poSrcBand->methodName argParams; \
+        { \
+            int nSrcBlockXSize, nSrcBlockYSize; \
+            poSrcBand->GetBlockSize(&nSrcBlockXSize, &nSrcBlockYSize); \
+            if( poSrcBand->GetRasterDataType() != GetRasterDataType() ) \
+            { \
+                CPLError(CE_Failure, CPLE_AppDefined, "Inconsistent datatype between proxy and source"); \
+                ret = CE_Failure; \
+            } \
+            else if( nSrcBlockXSize != nBlockXSize || nSrcBlockYSize != nBlockYSize) \
+            { \
+                CPLError(CE_Failure, CPLE_AppDefined, "Inconsistent block dimensions between proxy and source"); \
+                ret = CE_Failure; \
+            } \
+            else \
+            { \
+                ret = poSrcBand->methodName argParams; \
+            } \
+        } \
         UnrefUnderlyingRasterBand(poSrcBand); \
     } \
     else \
@@ -180,17 +262,44 @@ RB_PROXY_METHOD_WITH_RET_WITH_INIT_BLOCK(CPLErr, CE_Failure, IReadBlock,
 RB_PROXY_METHOD_WITH_RET_WITH_INIT_BLOCK(CPLErr, CE_Failure, IWriteBlock,
                                 ( int nXBlockOff, int nYBlockOff, void* pImage),
                                 (nXBlockOff, nYBlockOff, pImage) )
-RB_PROXY_METHOD_WITH_RET(CPLErr, CE_Failure, IRasterIO,
-                        ( GDALRWFlag eRWFlag,
+
+CPLErr GDALProxyRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void * pData, int nBufXSize, int nBufYSize,
                                 GDALDataType eBufType,
                                 GSpacing nPixelSpace,
                                 GSpacing nLineSpace,
-                                GDALRasterIOExtraArg* psExtraArg ),
-                        (eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                                GDALRasterIOExtraArg* psExtraArg )
+{
+    CPLErr ret;
+    GDALRasterBand* poSrcBand = RefUnderlyingRasterBand();
+    if (poSrcBand)
+    {
+/* -------------------------------------------------------------------- */
+/*      Do some validation of parameters.                               */
+/* -------------------------------------------------------------------- */
+        if( nXOff + nXSize > poSrcBand->GetXSize() || nYOff + nYSize > poSrcBand->GetYSize() )
+        {
+            ReportError( CE_Failure, CPLE_IllegalArg,
+                      "Access window out of range in RasterIO().  Requested\n"
+                      "(%d,%d) of size %dx%d on raster of %dx%d.",
+                      nXOff, nYOff, nXSize, nYSize, poSrcBand->GetXSize(), poSrcBand->GetYSize() );
+            ret =  CE_Failure;
+        }
+        else
+        {
+            ret = poSrcBand->IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
                                 pData, nBufXSize, nBufYSize, eBufType,
-                                nPixelSpace, nLineSpace, psExtraArg ) )
+                                nPixelSpace, nLineSpace, psExtraArg );
+        }
+        UnrefUnderlyingRasterBand(poSrcBand);
+    }
+    else
+    {
+        ret = CE_Failure;
+    }
+    return ret;
+}
 
 RB_PROXY_METHOD_WITH_RET(char**, NULL, GetMetadataDomainList, (), ())
 RB_PROXY_METHOD_WITH_RET(char**, NULL, GetMetadata, (const char * pszDomain), (pszDomain))
@@ -301,6 +410,8 @@ RB_PROXY_METHOD_WITH_RET(CPLVirtualMem*, NULL, GetVirtualMemAuto,
 /*                 UnrefUnderlyingRasterBand()                        */
 /************************************************************************/
 
-void GDALProxyRasterBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALRasterBand* poUnderlyingRasterBand)
-{
-}
+void GDALProxyRasterBand::UnrefUnderlyingRasterBand(
+    GDALRasterBand* /* poUnderlyingRasterBand */ )
+{}
+
+/*! @endcond */
diff --git a/gcore/gdalproxypool.cpp b/gcore/gdalproxypool.cpp
index b4a9d73..205f33b 100644
--- a/gcore/gdalproxypool.cpp
+++ b/gcore/gdalproxypool.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalproxypool.cpp 32234 2015-12-18 12:40:59Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  A dataset and raster band classes that differ the opening of the
@@ -28,10 +27,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_proxy.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_hash_set.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "gdal.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalproxypool.cpp 32234 2015-12-18 12:40:59Z rouault $");
+//! @cond Doxygen_Suppress
+
+CPL_CVSID("$Id: gdalproxypool.cpp 36763 2016-12-09 22:10:55Z rouault $");
 
 /* We *must* share the same mutex as the gdaldataset.cpp file, as we are */
 /* doing GDALOpen() calls that can indirectly call GDALOpenShared() on */
@@ -87,7 +100,7 @@ class GDALDatasetPool
 
         /* Caution : to be sure that we don't run out of entries, size must be at */
         /* least greater or equal than the maximum number of threads */
-        GDALDatasetPool(int maxSize);
+        explicit GDALDatasetPool(int maxSize);
         ~GDALDatasetPool();
         GDALProxyPoolCacheEntry* _RefDataset(const char* pszFileName,
                                              GDALAccess eAccess,
@@ -95,8 +108,11 @@ class GDALDatasetPool
                                              int bShared);
         void _CloseDataset(const char* pszFileName, GDALAccess eAccess);
 
+#ifdef DEBUG_PROXY_POOL
+        // cppcheck-suppress unusedPrivateFunction
         void ShowContent();
         void CheckLinks();
+#endif
 
     public:
         static void Ref();
@@ -112,7 +128,6 @@ class GDALDatasetPool
         static void ForceDestroy();
 };
 
-
 /************************************************************************/
 /*                         GDALDatasetPool()                            */
 /************************************************************************/
@@ -151,6 +166,7 @@ GDALDatasetPool::~GDALDatasetPool()
     GDALSetResponsiblePIDForCurrentThread(responsiblePID);
 }
 
+#ifdef DEBUG_PROXY_POOL
 /************************************************************************/
 /*                            ShowContent()                             */
 /************************************************************************/
@@ -161,7 +177,7 @@ void GDALDatasetPool::ShowContent()
     int i = 0;
     while(cur)
     {
-        printf("[%d] pszFileName=%s, refCount=%d, responsiblePID=%d\n",
+        printf("[%d] pszFileName=%s, refCount=%d, responsiblePID=%d\n",/*ok*/
                i, cur->pszFileName, cur->refCount, (int)cur->responsiblePID);
         i++;
         cur = cur->next;
@@ -180,12 +196,13 @@ void GDALDatasetPool::CheckLinks()
     {
         CPLAssert(cur == firstEntry || cur->prev->next == cur);
         CPLAssert(cur == lastEntry || cur->next->prev == cur);
-        i++;
-	CPLAssert(cur->next != NULL || cur == lastEntry);
+        ++i;
+        CPLAssert(cur->next != NULL || cur == lastEntry);
         cur = cur->next;
     }
     CPLAssert(i == currentSize);
 }
+#endif
 
 /************************************************************************/
 /*                            _RefDataset()                             */
@@ -268,7 +285,7 @@ GDALProxyPoolCacheEntry* GDALDatasetPool::_RefDataset(const char* pszFileName,
         if (lastEntryWithZeroRefCount->prev)
             lastEntryWithZeroRefCount->prev->next = lastEntryWithZeroRefCount->next;
         else {
-            CPLAssert(0);
+            CPLAssert(false);
         }
         if (lastEntryWithZeroRefCount->next)
             lastEntryWithZeroRefCount->next->prev = lastEntryWithZeroRefCount->prev;
@@ -320,7 +337,8 @@ GDALProxyPoolCacheEntry* GDALDatasetPool::_RefDataset(const char* pszFileName,
 /*                       _CloseDataset()                                */
 /************************************************************************/
 
-void GDALDatasetPool::_CloseDataset(const char* pszFileName, CPL_UNUSED GDALAccess eAccess)
+void GDALDatasetPool::_CloseDataset( const char* pszFileName,
+                                     GDALAccess /* eAccess */ )
 {
     GDALProxyPoolCacheEntry* cur = firstEntry;
     GIntBig responsiblePID = GDALGetResponsiblePIDForCurrentThread();
@@ -387,7 +405,6 @@ void GDALDatasetPoolPreventDestroy()
     GDALDatasetPool::PreventDestroy();
 }
 
-
 /************************************************************************/
 /*                               Unref()                                */
 /************************************************************************/
@@ -397,7 +414,7 @@ void GDALDatasetPool::Unref()
     CPLMutexHolderD( GDALGetphDLMutex() );
     if (! singleton)
     {
-        CPLAssert(0);
+        CPLAssert(false);
         return;
     }
     if (singleton->refCountOfDisableRefCount == 0)
@@ -497,7 +514,6 @@ void free_func_get_metadata(void* _elt)
     CPLFree(elt);
 }
 
-
 typedef struct
 {
     char* pszName;
@@ -561,7 +577,7 @@ GDALProxyPoolDataset::GDALProxyPoolDataset(const char* pszSourceDatasetDescripti
     nRasterYSize = nRasterYSizeIn;
     eAccess = eAccessIn;
 
-    bShared = static_cast<GByte>(bSharedIn);
+    bShared = CPL_TO_BOOL(bSharedIn);
 
     responsiblePID = GDALGetResponsiblePIDForCurrentThread();
 
@@ -614,7 +630,7 @@ GDALProxyPoolDataset::~GDALProxyPoolDataset()
     /* want ~GDALDataset() to try to release it from its */
     /* shared dataset hashset. This will save a */
     /* "Should not happen. Cannot find %s, this=%p in phSharedDatasetSet" debug message */
-    bShared = FALSE;
+    bShared = false;
 
     CPLFree(pszProjectionRef);
     CPLFree(pszGCPProjection);
@@ -685,7 +701,8 @@ GDALDataset* GDALProxyPoolDataset::RefUnderlyingDataset()
 /*                    UnrefUnderlyingDataset()                        */
 /************************************************************************/
 
-void GDALProxyPoolDataset::UnrefUnderlyingDataset(CPL_UNUSED GDALDataset* poUnderlyingDataset)
+void GDALProxyPoolDataset::UnrefUnderlyingDataset(
+    CPL_UNUSED GDALDataset* poUnderlyingDataset )
 {
     if (cacheEntry != NULL)
     {
@@ -967,8 +984,7 @@ GDALProxyPoolRasterBand::~GDALProxyPoolRasterBand()
     if (poColorTable)
         delete poColorTable;
 
-    int i;
-    for(i=0;i<nSizeProxyOverviewRasterBand;i++)
+    for( int i=0; i < nSizeProxyOverviewRasterBand; i++ )
     {
         if (papoProxyOverviewRasterBand[i])
             delete papoProxyOverviewRasterBand[i];
@@ -978,7 +994,6 @@ GDALProxyPoolRasterBand::~GDALProxyPoolRasterBand()
         delete poProxyMaskBand;
 }
 
-
 /************************************************************************/
 /*                 AddSrcMaskBandDescription()                          */
 /************************************************************************/
@@ -1171,11 +1186,10 @@ GDALRasterBand *GDALProxyPoolRasterBand::GetOverview(int nOverviewBand)
 
     if (nOverviewBand >= nSizeProxyOverviewRasterBand)
     {
-        int i;
         papoProxyOverviewRasterBand = (GDALProxyPoolOverviewRasterBand**)
                 CPLRealloc(papoProxyOverviewRasterBand,
                         sizeof(GDALProxyPoolOverviewRasterBand*) * (nOverviewBand + 1));
-        for(i=nSizeProxyOverviewRasterBand; i<nOverviewBand + 1;i++)
+        for( int i=nSizeProxyOverviewRasterBand; i<nOverviewBand + 1; i++ )
             papoProxyOverviewRasterBand[i] = NULL;
         nSizeProxyOverviewRasterBand = nOverviewBand + 1;
     }
@@ -1194,7 +1208,8 @@ GDALRasterBand *GDALProxyPoolRasterBand::GetOverview(int nOverviewBand)
 /*                     GetRasterSampleOverview()                        */
 /* ******************************************************************** */
 
-GDALRasterBand *GDALProxyPoolRasterBand::GetRasterSampleOverview( CPL_UNUSED GUIntBig nDesiredSamples)
+GDALRasterBand *GDALProxyPoolRasterBand::GetRasterSampleOverview(
+    GUIntBig /* nDesiredSamples */ )
 {
     CPLError(CE_Failure, CPLE_AppDefined,
              "GDALProxyPoolRasterBand::GetRasterSampleOverview : not implemented yet");
@@ -1270,13 +1285,13 @@ GDALRasterBand* GDALProxyPoolOverviewRasterBand::RefUnderlyingRasterBand()
 /*                  UnrefUnderlyingRasterBand()                         */
 /* ******************************************************************** */
 
-void GDALProxyPoolOverviewRasterBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALRasterBand* poUnderlyingRasterBand)
+void GDALProxyPoolOverviewRasterBand::UnrefUnderlyingRasterBand(
+    GDALRasterBand* /* poUnderlyingRasterBand */ )
 {
     poMainBand->UnrefUnderlyingRasterBand(poUnderlyingMainRasterBand);
     nRefCountUnderlyingMainRasterBand --;
 }
 
-
 /* ******************************************************************** */
 /*                     GDALProxyPoolMaskBand()                          */
 /* ******************************************************************** */
@@ -1335,8 +1350,11 @@ GDALRasterBand* GDALProxyPoolMaskBand::RefUnderlyingRasterBand()
 /*                  UnrefUnderlyingRasterBand()                         */
 /* ******************************************************************** */
 
-void GDALProxyPoolMaskBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALRasterBand* poUnderlyingRasterBand)
+void GDALProxyPoolMaskBand::UnrefUnderlyingRasterBand(
+    GDALRasterBand* /* poUnderlyingRasterBand */ )
 {
     poMainBand->UnrefUnderlyingRasterBand(poUnderlyingMainRasterBand);
     nRefCountUnderlyingMainRasterBand --;
 }
+
+//! @endcond
diff --git a/gcore/gdalrasterband.cpp b/gcore/gdalrasterband.cpp
index b8f7c3f..e218c11 100644
--- a/gcore/gdalrasterband.cpp
+++ b/gcore/gdalrasterband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalrasterband.cpp 35549 2016-09-29 22:56:53Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Base class for format specific band class implementation.  This
@@ -8,7 +7,7 @@
  *
  ******************************************************************************
  * Copyright (c) 1998, Frank Warmerdam
- * Copyright (c) 2007-2014, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2007-2016, Even Rouault <even dot rouault at spatialys dot com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -29,11 +28,30 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
-#include "gdal_rat.h"
+
+#include <climits>
+#include <cmath>
+#include <cstdarg>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <limits>
+#include <new>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
 #include "cpl_string.h"
+#include "cpl_virtualmem.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_rat.h"
 
-CPL_CVSID("$Id: gdalrasterband.cpp 35549 2016-09-29 22:56:53Z rouault $");
+CPL_CVSID("$Id: gdalrasterband.cpp 37473 2017-02-26 02:48:38Z goatbar $");
 
 /************************************************************************/
 /*                           GDALRasterBand()                           */
@@ -47,6 +65,9 @@ GDALRasterBand::GDALRasterBand()
     Init(CPLTestBool( CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") ) );
 }
 
+/** Constructor. Applications should never create GDALRasterBands directly.
+ * @param bForceCachedIOIn Whether cached IO should be forced.
+ */
 GDALRasterBand::GDALRasterBand(int bForceCachedIOIn)
 
 {
@@ -57,10 +78,12 @@ void GDALRasterBand::Init(int bForceCachedIOIn)
 {
     poDS = NULL;
     nBand = 0;
-    nRasterXSize = nRasterYSize = 0;
+    nRasterXSize = 0;
+    nRasterYSize = 0;
 
     eAccess = GA_ReadOnly;
-    nBlockXSize = nBlockYSize = -1;
+    nBlockXSize = -1;
+    nBlockYSize = -1;
     eDataType = GDT_Byte;
 
     nBlocksPerRow = 0;
@@ -108,6 +131,13 @@ GDALRasterBand::~GDALRasterBand()
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
+ *                                int nXOff, int nYOff, int nXSize, int nYSize,
+ *                                void * pData, int nBufXSize, int nBufYSize,
+ *                                GDALDataType eBufType,
+ *                                GSpacing nPixelSpace,
+ *                                GSpacing nLineSpace,
+ *                                GDALRasterIOExtraArg* psExtraArg )
  * \brief Read/write a region of image data for this band.
  *
  * This method allows reading a region of a GDALRasterBand into a buffer,
@@ -178,6 +208,77 @@ GDALRasterBand::~GDALRasterBand()
  * @return CE_Failure if the access fails, otherwise CE_None.
  */
 
+/**
+ * \brief Read/write a region of image data for this band.
+ *
+ * This method allows reading a region of a GDALRasterBand into a buffer,
+ * or writing data from a buffer into a region of a GDALRasterBand. It
+ * automatically takes care of data type translation if the data type
+ * (eBufType) of the buffer is different than that of the GDALRasterBand.
+ * The method also takes care of image decimation / replication if the
+ * buffer size (nBufXSize x nBufYSize) is different than the size of the
+ * region being accessed (nXSize x nYSize).
+ *
+ * The nPixelSpace and nLineSpace parameters allow reading into or
+ * writing from unusually organized buffers. This is primarily used
+ * for buffers containing more than one bands raster data in interleaved
+ * format.
+ *
+ * Some formats may efficiently implement decimation into a buffer by
+ * reading from lower resolution overview images.
+ *
+ * For highest performance full resolution data access, read and write
+ * on "block boundaries" as returned by GetBlockSize(), or use the
+ * ReadBlock() and WriteBlock() methods.
+ *
+ * This method is the same as the C GDALRasterIO() or GDALRasterIOEx() functions.
+ *
+ * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
+ * write a region of data.
+ *
+ * @param nXOff The pixel offset to the top left corner of the region
+ * of the band to be accessed. This would be zero to start from the left side.
+ *
+ * @param nYOff The line offset to the top left corner of the region
+ * of the band to be accessed. This would be zero to start from the top.
+ *
+ * @param nXSize The width of the region of the band to be accessed in pixels.
+ *
+ * @param nYSize The height of the region of the band to be accessed in lines.
+ *
+ * @param[in,out] pData The buffer into which the data should be read, or from which
+ * it should be written. This buffer must contain at least nBufXSize *
+ * nBufYSize words of type eBufType. It is organized in left to right,
+ * top to bottom pixel order. Spacing is controlled by the nPixelSpace,
+ * and nLineSpace parameters.
+ *
+ * @param nBufXSize the width of the buffer image into which the desired region is
+ * to be read, or from which it is to be written.
+ *
+ * @param nBufYSize the height of the buffer image into which the desired region is
+ * to be read, or from which it is to be written.
+ *
+ * @param eBufType the type of the pixel values in the pData data buffer. The
+ * pixel values will automatically be translated to/from the GDALRasterBand
+ * data type as needed.
+ *
+ * @param nPixelSpace The byte offset from the start of one pixel value in
+ * pData to the start of the next pixel value within a scanline. If defaulted
+ * (0) the size of the datatype eBufType is used.
+ *
+ * @param nLineSpace The byte offset from the start of one scanline in
+ * pData to the start of the next. If defaulted (0) the size of the datatype
+ * eBufType * nBufXSize is used.
+ *
+ * @param[in] psExtraArg (new in GDAL 2.0) pointer to a GDALRasterIOExtraArg structure with additional
+ * arguments to specify resampling and progress callback, or NULL for default
+ * behaviour. The GDAL_RASTERIO_RESAMPLING configuration option can also be defined
+ * to override the default resampling to one of BILINEAR, CUBIC, CUBICSPLINE,
+ * LANCZOS, AVERAGE or MODE.
+ *
+ * @return CE_Failure if the access fails, otherwise CE_None.
+ */
+
 CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
                                  int nXOff, int nYOff, int nXSize, int nYSize,
                                  void * pData, int nBufXSize, int nBufYSize,
@@ -366,10 +467,10 @@ GDALRasterIOEx( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
  * block oriented data without an extra copy into an application buffer.
  *
  * @param nXBlockOff the horizontal block offset, with zero indicating
- * the leftmost block, 1 the next block and so forth.
+ * the left most block, 1 the next block and so forth.
  *
  * @param nYBlockOff the vertical block offset, with zero indicating
- * the topmost block, 1 the next block and so forth.
+ * the top most block, 1 the next block and so forth.
  *
  * @param pImage the buffer into which the data will be read.  The buffer
  * must be large enough to hold GetBlockXSize()*GetBlockYSize() words
@@ -408,15 +509,7 @@ GDALRasterIOEx( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
 
              // Compute the portion of the block that is valid
              // for partial edge blocks.
-             if( (iXBlock+1) * nXBlockSize > poBand->GetXSize() )
-                 nXValid = poBand->GetXSize() - iXBlock * nXBlockSize;
-             else
-                 nXValid = nXBlockSize;
-
-             if( (iYBlock+1) * nYBlockSize > poBand->GetYSize() )
-                 nYValid = poBand->GetYSize() - iYBlock * nYBlockSize;
-             else
-                 nYValid = nYBlockSize;
+             poBand->GetActualBlockSize(iXBlock, iYBlock, &nXValid, &nYValid)
 
              // Collect the histogram counts.
              for( int iY = 0; iY < nYValid; iY++ )
@@ -433,7 +526,6 @@ GDALRasterIOEx( GDALRasterBandH hBand, GDALRWFlag eRWFlag,
 </pre>
  */
 
-
 CPLErr GDALRasterBand::ReadBlock( int nXBlockOff, int nYBlockOff,
                                    void * pImage )
 
@@ -496,13 +588,42 @@ CPLErr CPL_STDCALL GDALReadBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
 }
 
 /************************************************************************/
+/*                            IReadBlock()                             */
+/************************************************************************/
+
+/** \fn GDALRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void *pData )
+ * \brief Read a block of data.
+ *
+ * Default internal implementation ... to be overridden by
+ * subclasses that support reading.
+ * @param nBlockXOff Block X Offset
+ * @param nBlockYOff Block Y Offset
+ * @param pData Pixel buffer into which to place read data.
+ * @return CE_None on success or CE_Failure on an error.
+ */
+
+/************************************************************************/
 /*                            IWriteBlock()                             */
-/*                                                                      */
-/*      Default internal implementation ... to be overridden by          */
-/*      subclasses that support writing.                                */
 /************************************************************************/
 
-CPLErr GDALRasterBand::IWriteBlock( int, int, void * )
+/**
+ * \fn GDALRasterBand::IWriteBlock(int, int, void*)
+ * Write a block of data.
+ *
+ * Default internal implementation ... to be overridden by
+ * subclasses that support writing.
+ * @param nBlockXOff Block X Offset
+ * @param nBlockYOff Block Y Offset
+ * @param pData Pixel buffer to write
+ * @return CE_None on success or CE_Failure on an error.
+ */
+
+/**/
+/**/
+
+CPLErr GDALRasterBand::IWriteBlock( int /*nBlockXOff*/,
+                                    int /*nBlockYOff*/,
+                                    void * /*pData*/ )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
@@ -621,6 +742,83 @@ CPLErr CPL_STDCALL GDALWriteBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
     return( poBand->WriteBlock( nXOff, nYOff, pData ) );
 }
 
+/************************************************************************/
+/*                         GetActualBlockSize()                         */
+/************************************************************************/
+/**
+* \brief Fetch the actual block size for a given block offset.
+*
+* Handles partial blocks at the edges of the raster and returns the true
+* number of pixels
+*
+* @param nXBlockOff the horizontal block offset for which to calculate the number of
+* valid pixels, with zero indicating the left most block, 1 the next block and so forth.
+*
+* @param nYBlockOff the vertical block offset, with zero indicating
+* the left most block, 1 the next block and so forth.
+*
+* @param pnXValid pointer to an integer in which the number of valid pixels in the x
+* direction will be stored
+*
+* @param pnYValid pointer to an integer in which the number of valid pixels in the y
+* direction will be stored
+*
+* @return CE_None if the input parameter are valid, CE_Failure otherwise
+*
+* @since GDAL 2.2
+*/
+CPLErr GDALRasterBand::GetActualBlockSize(int nXBlockOff, int nYBlockOff,
+                                          int *pnXValid, int *pnYValid)
+{
+    if( nXBlockOff < 0 || nBlockXSize == 0 ||
+        nXBlockOff >= nRasterXSize / nBlockXSize + ((nRasterXSize % nBlockXSize) ? 1 : 0) ||
+        nYBlockOff < 0 || nBlockYSize == 0 ||
+        nYBlockOff >= nRasterYSize / nBlockYSize + ((nRasterYSize % nBlockYSize) ? 1 : 0) )
+    {
+        return CE_Failure;
+    }
+
+    int nXPixelOff = nXBlockOff * nBlockXSize;
+    int nYPixelOff = nYBlockOff * nBlockYSize;
+
+    *pnXValid = nBlockXSize;
+    *pnYValid = nBlockYSize;
+
+    if( nXPixelOff + nBlockXSize >= nRasterXSize)
+    {
+        *pnXValid = nRasterXSize - nXPixelOff;
+    }
+
+    if( nYPixelOff + nBlockYSize >= nRasterYSize)
+    {
+        *pnYValid = nRasterYSize - nYPixelOff;
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                           GDALGetActualBlockSize()                   */
+/************************************************************************/
+
+/**
+ * \brief Retrieve the actual block size for a given block offset.
+ *
+ * @see GDALRasterBand::GetActualBlockSize()
+ */
+
+CPLErr CPL_STDCALL GDALGetActualBlockSize( GDALRasterBandH hBand,
+                                           int nXBlockOff,
+                                           int nYBlockOff,
+                                           int *pnXValid,
+                                           int *pnYValid )
+
+{
+    VALIDATE_POINTER1( hBand, "GDALGetActualBlockSize", CE_Failure );
+
+    GDALRasterBand *poBand = static_cast<GDALRasterBand *>( hBand );
+    return( poBand->GetActualBlockSize( nXBlockOff, nYBlockOff, pnXValid, pnYValid ) );
+}
 
 /************************************************************************/
 /*                         GetRasterDataType()                          */
@@ -634,7 +832,6 @@ CPLErr CPL_STDCALL GDALWriteBlock( GDALRasterBandH hBand, int nXOff, int nYOff,
  * @return the data type of pixels for this band.
  */
 
-
 GDALDataType GDALRasterBand::GetRasterDataType()
 
 {
@@ -731,6 +928,7 @@ GDALGetBlockSize( GDALRasterBandH hBand, int * pnXSize, int * pnYSize )
 /*                           InitBlockInfo()                            */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 int GDALRasterBand::InitBlockInfo()
 
 {
@@ -808,28 +1006,7 @@ int GDALRasterBand::InitBlockInfo()
         return FALSE;
     return poBandBlockCache->Init();
 }
-
-/************************************************************************/
-/*                             AdoptBlock()                             */
-/*                                                                      */
-/*      Add a block to the raster band's block matrix.  If this         */
-/*      exceeds our maximum blocks for this layer, flush the oldest     */
-/*      block out.                                                      */
-/*                                                                      */
-/*      This method is protected.                                       */
-/************************************************************************/
-
-CPLErr GDALRasterBand::AdoptBlock( GDALRasterBlock * poBlock )
-
-{
-    if( !InitBlockInfo() )
-        return CE_Failure;
-
-    CPLErr eErr = poBandBlockCache->AdoptBlock(poBlock);
-    if( eErr == CE_None )
-        poBlock->Touch();
-    return eErr;
-}
+//! @endcond
 
 /************************************************************************/
 /*                             FlushCache()                             */
@@ -882,7 +1059,6 @@ CPLErr CPL_STDCALL GDALFlushRasterCache( GDALRasterBandH hBand )
     return ((GDALRasterBand *) hBand)->FlushCache();
 }
 
-
 /************************************************************************/
 /*                        UnreferenceBlock()                            */
 /*                                                                      */
@@ -898,19 +1074,19 @@ CPLErr GDALRasterBand::UnreferenceBlock( GDALRasterBlock* poBlock )
     if( poBandBlockCache == NULL || !poBandBlockCache->IsInitOK() )
     {
         if( poBandBlockCache == NULL )
-            printf("poBandBlockCache == NULL\n");
+            printf("poBandBlockCache == NULL\n");/*ok*/
         else
-            printf("!poBandBlockCache->IsInitOK()\n");
-        printf("caller = %s\n", pszCaller);
-        printf("GDALRasterBand: %p\n", this);
-        printf("GDALRasterBand: nBand=%d\n", nBand);
-        printf("nRasterXSize = %d\n", nRasterXSize);
-        printf("nRasterYSize = %d\n", nRasterYSize);
-        printf("nBlockXSize = %d\n", nBlockXSize);
-        printf("nBlockYSize = %d\n", nBlockYSize);
+            printf("!poBandBlockCache->IsInitOK()\n");/*ok*/
+        printf("caller = %s\n", pszCaller);/*ok*/
+        printf("GDALRasterBand: %p\n", this);/*ok*/
+        printf("GDALRasterBand: nBand=%d\n", nBand);/*ok*/
+        printf("nRasterXSize = %d\n", nRasterXSize);/*ok*/
+        printf("nRasterYSize = %d\n", nRasterYSize);/*ok*/
+        printf("nBlockXSize = %d\n", nBlockXSize);/*ok*/
+        printf("nBlockYSize = %d\n", nBlockYSize);/*ok*/
         poBlock->DumpBlock();
         if( GetDataset() != NULL )
-            printf("Dataset: %s\n", GetDataset()->GetDescription());
+            printf("Dataset: %s\n", GetDataset()->GetDescription());/*ok*/
         GDALRasterBlock::Verify();
         abort();
     }
@@ -927,18 +1103,24 @@ CPLErr GDALRasterBand::UnreferenceBlock( GDALRasterBlock* poBlock )
 /*      method.                                                         */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 void GDALRasterBand::AddBlockToFreeList( GDALRasterBlock * poBlock )
 {
     CPLAssert(poBandBlockCache && poBandBlockCache->IsInitOK());
     return poBandBlockCache->AddBlockToFreeList( poBlock );
 }
+//! @endcond
 
 /************************************************************************/
 /*                             FlushBlock()                             */
-/*                                                                      */
-/*      Flush a block out of the block cache.                           */
 /************************************************************************/
 
+/** Flush a block out of the block cache.
+ * @param nXBlockOff block x offset
+ * @param nYBlockOff blocky offset
+ * @param bWriteDirtyBlock whether the block should be written to disk if dirty.
+ * @return CE_None in case of success, an error code otherwise.
+ */
 CPLErr GDALRasterBand::FlushBlock( int nXBlockOff, int nYBlockOff,
                                    int bWriteDirtyBlock )
 
@@ -1130,14 +1312,14 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
         {
             poBlock->DropLock();
             delete poBlock;
-            return( NULL );
+            return NULL;
         }
 
-        if ( AdoptBlock( poBlock ) != CE_None )
+        if ( poBandBlockCache->AdoptBlock(poBlock) != CE_None )
         {
             poBlock->DropLock();
             delete poBlock;
-            return( NULL );
+            return NULL;
         }
 
         if( !bJustInitialize )
@@ -1191,7 +1373,7 @@ GDALRasterBlock * GDALRasterBand::GetLockedBlockRef( int nXBlockOff,
  *
  * @return CE_Failure if the write fails, otherwise CE_None
  */
-CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
+CPLErr GDALRasterBand::Fill( double dfRealValue, double dfImaginaryValue ) {
 
     // General approach is to construct a source block of the file's
     // native type containing the appropriate value and then copy this
@@ -1202,31 +1384,32 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
     // underlying file, rather than simply directly to the underlying
     // file.)
 
-    // Check we can write to the file
+    // Check we can write to the file.
     if( eAccess == GA_ReadOnly ) {
-        ReportError(CE_Failure, CPLE_NoWriteAccess,
-                 "Attempt to write to read only dataset in"
-                 "GDALRasterBand::Fill().\n" );
+        ReportError( CE_Failure, CPLE_NoWriteAccess,
+                     "Attempt to write to read only dataset in "
+                     "GDALRasterBand::Fill()." );
         return CE_Failure;
     }
 
-    // Make sure block parameters are set
+    // Make sure block parameters are set.
     if( !InitBlockInfo() )
         return CE_Failure;
 
-    // Allocate the source block
+    // Allocate the source block.
     int blockSize = nBlockXSize * nBlockYSize;
     int elementSize = GDALGetDataTypeSizeBytes(eDataType);
     int blockByteSize = blockSize * elementSize;
-    unsigned char* srcBlock = (unsigned char*) VSIMalloc(blockByteSize);
+    unsigned char* srcBlock =
+        static_cast<unsigned char*>( VSIMalloc(blockByteSize) );
     if (srcBlock == NULL) {
-        ReportError(CE_Failure, CPLE_OutOfMemory,
-                 "GDALRasterBand::Fill(): Out of memory "
-		 "allocating %d bytes.\n", blockByteSize);
+        ReportError( CE_Failure, CPLE_OutOfMemory,
+                     "GDALRasterBand::Fill(): Out of memory "
+                     "allocating %d bytes.\n", blockByteSize );
         return CE_Failure;
     }
 
-    // Initialize the source block
+    // Initialize the source block.
     double complexSrc[2] = { dfRealValue, dfImaginaryValue };
     GDALCopyWords(complexSrc, GDT_CFloat64, 0,
                   srcBlock, eDataType, elementSize, blockSize);
@@ -1235,19 +1418,20 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
 
     // Write block to block cache
     for (int j = 0; j < nBlocksPerColumn; ++j) {
-	for (int i = 0; i < nBlocksPerRow; ++i) {
-	    GDALRasterBlock* destBlock = GetLockedBlockRef(i, j, TRUE);
-	    if (destBlock == NULL) {
-            ReportError(CE_Failure, CPLE_OutOfMemory,
-			 "GDALRasterBand::Fill(): Error "
-			 "while retrieving cache block.\n");
+        for (int i = 0; i < nBlocksPerRow; ++i) {
+            GDALRasterBlock* destBlock = GetLockedBlockRef(i, j, TRUE);
+            if (destBlock == NULL)
+            {
+                ReportError( CE_Failure, CPLE_OutOfMemory,
+                             "GDALRasterBand::Fill(): Error "
+                             "while retrieving cache block.");
                 VSIFree(srcBlock);
-		return CE_Failure;
-	    }
-	    memcpy(destBlock->GetDataRef(), srcBlock, blockByteSize);
-	    destBlock->MarkDirty();
+                return CE_Failure;
+            }
+            memcpy(destBlock->GetDataRef(), srcBlock, blockByteSize);
+            destBlock->MarkDirty();
             destBlock->DropLock();
-	}
+        }
     }
 
     if( bCallLeaveReadWrite ) LeaveReadWrite();
@@ -1258,7 +1442,6 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                         GDALFillRaster()                             */
 /************************************************************************/
@@ -1268,8 +1451,8 @@ CPLErr GDALRasterBand::Fill(double dfRealValue, double dfImaginaryValue) {
  *
  * @see GDALRasterBand::Fill()
  */
-CPLErr CPL_STDCALL GDALFillRaster(GDALRasterBandH hBand, double dfRealValue,
-		      double dfImaginaryValue)
+CPLErr CPL_STDCALL GDALFillRaster(
+    GDALRasterBandH hBand, double dfRealValue, double dfImaginaryValue )
 {
     VALIDATE_POINTER1( hBand, "GDALFillRaster", CE_Failure );
 
@@ -1365,6 +1548,7 @@ char ** CPL_STDCALL GDALGetRasterCategoryNames( GDALRasterBandH hBand )
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::SetCategoryNames(char**)
  * \brief Set the category names for this band.
  *
  * See the GetCategoryNames() method for more on the interpretation of
@@ -1379,11 +1563,14 @@ char ** CPL_STDCALL GDALGetRasterCategoryNames( GDALRasterBandH hBand )
  * by the driver CE_Failure is returned, but no error message is reported.
  */
 
-CPLErr GDALRasterBand::SetCategoryNames( CPL_UNUSED char ** papszNames )
+/**/
+/**/
+
+CPLErr GDALRasterBand::SetCategoryNames( char ** /*papszNames*/ )
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
-                  "SetCategoryNames() not supported for this dataset." );
+                     "SetCategoryNames() not supported for this dataset." );
 
     return CE_Failure;
 }
@@ -1462,6 +1649,7 @@ GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::SetNoDataValue(double)
  * \brief Set the no data value for this band.
  *
  * Depending on drivers, changing the no data value may or may not have an
@@ -1483,12 +1671,15 @@ GDALGetRasterNoDataValue( GDALRasterBandH hBand, int *pbSuccess )
  * been emitted.
  */
 
-CPLErr GDALRasterBand::SetNoDataValue( CPL_UNUSED double dfNoData )
+/**/
+/**/
+
+CPLErr GDALRasterBand::SetNoDataValue( double /*dfNoData*/ )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
-                  "SetNoDataValue() not supported for this dataset." );
+                     "SetNoDataValue() not supported for this dataset." );
 
     return CE_Failure;
 }
@@ -1530,8 +1721,6 @@ GDALSetRasterNoDataValue( GDALRasterBandH hBand, double dfValue )
  *
  * This method is the same as the C function GDALDeleteRasterNoDataValue().
  *
- * @param dfNoData the value to set.
- *
  * @return CE_None on success, or CE_Failure on failure.  If unsupported
  * by the driver, CE_Failure is returned by no error message will have
  * been emitted.
@@ -1544,7 +1733,7 @@ CPLErr GDALRasterBand::DeleteNoDataValue()
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
-                  "DeleteNoDataValue() not supported for this dataset." );
+                     "DeleteNoDataValue() not supported for this dataset." );
 
     return CE_Failure;
 }
@@ -1609,11 +1798,12 @@ double GDALRasterBand::GetMaximum( int *pbSuccess )
     {
       case GDT_Byte:
       {
-        const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
+        const char* pszPixelType =
+            GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
         if (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"))
             return 127;
-        else
-            return 255;
+
+        return 255;
       }
 
       case GDT_UInt16:
@@ -1632,14 +1822,14 @@ double GDALRasterBand::GetMaximum( int *pbSuccess )
 
       case GDT_Float32:
       case GDT_CFloat32:
-        return 4294967295.0; /* not actually accurate */
+        return 4294967295.0;  // Not actually accurate.
 
       case GDT_Float64:
       case GDT_CFloat64:
-        return 4294967295.0; /* not actually accurate */
+        return 4294967295.0;  // Not actually accurate.
 
       default:
-        return 4294967295.0; /* not actually accurate */
+        return 4294967295.0;  // Not actually accurate.
     }
 }
 
@@ -1701,11 +1891,12 @@ double GDALRasterBand::GetMinimum( int *pbSuccess )
     {
       case GDT_Byte:
       {
-        const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
+        const char* pszPixelType =
+            GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
         if (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"))
             return -128;
-        else
-            return 0;
+
+        return 0;
       }
 
       case GDT_UInt16:
@@ -1721,13 +1912,13 @@ double GDALRasterBand::GetMinimum( int *pbSuccess )
         return 0;
 
       case GDT_Float32:
-        return -4294967295.0; /* not actually accurate */
+        return -4294967295.0;  // Not actually accurate.
 
       case GDT_Float64:
-        return -4294967295.0; /* not actually accurate */
+        return -4294967295.0;  // Not actually accurate.
 
       default:
-        return -4294967295.0; /* not actually accurate */
+        return -4294967295.0;  // Not actually accurate.
     }
 }
 
@@ -1787,7 +1978,8 @@ GDALColorInterp CPL_STDCALL
 GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
 
 {
-    VALIDATE_POINTER1( hBand, "GDALGetRasterColorInterpretation", GCI_Undefined );
+    VALIDATE_POINTER1( hBand, "GDALGetRasterColorInterpretation",
+                       GCI_Undefined );
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
     return poBand->GetColorInterpretation();
@@ -1798,6 +1990,7 @@ GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::SetColorInterpretation(GDALColorInterp)
  * \brief Set color interpretation of a band.
  *
  * This method is the same as the C function GDALSetRasterColorInterpretation().
@@ -1807,10 +2000,13 @@ GDALGetRasterColorInterpretation( GDALRasterBandH hBand )
  * @return CE_None on success or CE_Failure if method is unsupported by format.
  */
 
-CPLErr GDALRasterBand::SetColorInterpretation( GDALColorInterp eColorInterp)
+/**/
+/**/
+
+CPLErr GDALRasterBand::SetColorInterpretation(
+    GDALColorInterp /*eColorInterp*/ )
 
 {
-    (void) eColorInterp;
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
                   "SetColorInterpretation() not supported for this dataset." );
@@ -1884,6 +2080,7 @@ GDALColorTableH CPL_STDCALL GDALGetRasterColorTable( GDALRasterBandH hBand )
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::SetColorTable(GDALColorTable*)
  * \brief Set the raster color table.
  *
  * The driver will make a copy of all desired data in the colortable.  It
@@ -1899,10 +2096,12 @@ GDALColorTableH CPL_STDCALL GDALGetRasterColorTable( GDALRasterBandH hBand )
  * error is issued.
  */
 
-CPLErr GDALRasterBand::SetColorTable( GDALColorTable * poCT )
+/**/
+/**/
+
+CPLErr GDALRasterBand::SetColorTable( GDALColorTable * /*poCT*/ )
 
 {
-    (void) poCT;
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
                   "SetColorTable() not supported for this dataset." );
@@ -1990,8 +2189,8 @@ int GDALRasterBand::GetOverviewCount()
 {
     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
         return poDS->oOvManager.GetOverviewCount( nBand );
-    else
-        return 0;
+
+    return 0;
 }
 
 /************************************************************************/
@@ -2013,7 +2212,6 @@ int CPL_STDCALL GDALGetOverviewCount( GDALRasterBandH hBand )
     return poBand->GetOverviewCount();
 }
 
-
 /************************************************************************/
 /*                            GetOverview()                             */
 /************************************************************************/
@@ -2033,8 +2231,8 @@ GDALRasterBand * GDALRasterBand::GetOverview( int i )
 {
     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
         return poDS->oOvManager.GetOverview( nBand, i );
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -2078,12 +2276,13 @@ GDALRasterBandH CPL_STDCALL GDALGetOverview( GDALRasterBandH hBand, int i )
  * @return optimal overview or the band itself.
  */
 
-GDALRasterBand *GDALRasterBand::GetRasterSampleOverview( GUIntBig nDesiredSamples )
+GDALRasterBand *GDALRasterBand::GetRasterSampleOverview(
+    GUIntBig nDesiredSamples )
 
 {
     GDALRasterBand *poBestBand = this;
 
-    double dfBestSamples = GetXSize() * (double)GetYSize();
+    double dfBestSamples = GetXSize() * static_cast<double>(GetYSize());
 
     for( int iOverview = 0; iOverview < GetOverviewCount(); iOverview++ )
     {
@@ -2092,8 +2291,8 @@ GDALRasterBand *GDALRasterBand::GetRasterSampleOverview( GUIntBig nDesiredSample
         if (poOBand == NULL)
             continue;
 
-        const double dfOSamples
-            = poOBand->GetXSize() * (double)poOBand->GetYSize();
+        const double dfOSamples =
+            poOBand->GetXSize() * static_cast<double>(poOBand->GetYSize());
 
         if( dfOSamples < dfBestSamples && dfOSamples > nDesiredSamples )
         {
@@ -2126,8 +2325,9 @@ GDALGetRasterSampleOverview( GDALRasterBandH hBand, int nDesiredSamples )
     VALIDATE_POINTER1( hBand, "GDALGetRasterSampleOverview", NULL );
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
-    return (GDALRasterBandH)
-        poBand->GetRasterSampleOverview( nDesiredSamples < 0 ? 0 : (GUIntBig)nDesiredSamples );
+    return /* (GDALRasterBandH) */
+        poBand->GetRasterSampleOverview(
+            nDesiredSamples < 0 ? 0 : static_cast<GUIntBig>(nDesiredSamples) );
 }
 
 /************************************************************************/
@@ -2157,6 +2357,7 @@ GDALGetRasterSampleOverviewEx( GDALRasterBandH hBand, GUIntBig nDesiredSamples )
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::BuildOverviews(const char*, int, int*, GDALProgressFunc, void*)
  * \brief Build raster overview(s)
  *
  * If the operation is unsupported for the indicated dataset, then
@@ -2180,15 +2381,18 @@ GDALGetRasterSampleOverviewEx( GDALRasterBandH hBand, GUIntBig nDesiredSamples )
  * @return CE_None on success or CE_Failure if the operation doesn't work.
  */
 
-CPLErr GDALRasterBand::BuildOverviews( const char * /* pszResampling */,
-                                       int /* nOverviews */,
-                                       int * /* panOverviewList */,
-                                       GDALProgressFunc /* pfnProgress */,
-                                       void * /* pProgressData */)
+/**/
+/**/
+
+CPLErr GDALRasterBand::BuildOverviews( const char* /*pszResampling*/,
+                                       int /*nOverviews*/,
+                                       int* /*panOverviewList*/,
+                                       GDALProgressFunc /*pfnProgress*/,
+                                       void * /*pProgressData*/ )
 
 {
     ReportError( CE_Failure, CPLE_NotSupported,
-              "BuildOverviews() not supported for this dataset." );
+                 "BuildOverviews() not supported for this dataset." );
 
     return( CE_Failure );
 }
@@ -2251,6 +2455,7 @@ double CPL_STDCALL GDALGetRasterOffset( GDALRasterBandH hBand, int *pbSuccess )
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::SetOffset(double)
  * \brief Set scaling offset.
  *
  * Very few formats implement this method.   When not implemented it will
@@ -2263,11 +2468,14 @@ double CPL_STDCALL GDALGetRasterOffset( GDALRasterBandH hBand, int *pbSuccess )
  * @return CE_None or success or CE_Failure on failure.
  */
 
-CPLErr GDALRasterBand::SetOffset( CPL_UNUSED double dfNewOffset )
+/**/
+/**/
+
+CPLErr GDALRasterBand::SetOffset( double /*dfNewOffset*/ )
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
-                  "SetOffset() not supported on this raster band." );
+                     "SetOffset() not supported on this raster band." );
 
     return CE_Failure;
 }
@@ -2350,6 +2558,7 @@ double CPL_STDCALL GDALGetRasterScale( GDALRasterBandH hBand, int *pbSuccess )
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::SetScale(double)
  * \brief Set scaling ratio.
  *
  * Very few formats implement this method.   When not implemented it will
@@ -2362,12 +2571,15 @@ double CPL_STDCALL GDALGetRasterScale( GDALRasterBandH hBand, int *pbSuccess )
  * @return CE_None or success or CE_Failure on failure.
  */
 
-CPLErr GDALRasterBand::SetScale( CPL_UNUSED double dfNewScale )
+/**/
+/**/
+
+CPLErr GDALRasterBand::SetScale( double /*dfNewScale*/ )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
-                  "SetScale() not supported on this raster band." );
+                     "SetScale() not supported on this raster band." );
 
     return CE_Failure;
 }
@@ -2439,6 +2651,7 @@ const char * CPL_STDCALL GDALGetRasterUnitType( GDALRasterBandH hBand )
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::SetUnitType(const char*)
  * \brief Set unit type.
  *
  * Set the unit type for a raster band.  Values should be one of
@@ -2453,12 +2666,15 @@ const char * CPL_STDCALL GDALGetRasterUnitType( GDALRasterBandH hBand )
  * unsupported.
  */
 
-CPLErr GDALRasterBand::SetUnitType( CPL_UNUSED const char *pszNewValue )
+/**/
+/**/
+
+CPLErr GDALRasterBand::SetUnitType( const char * /*pszNewValue*/ )
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
-                  "SetUnitType() not supported on this raster band." );
+                     "SetUnitType() not supported on this raster band." );
     return CE_Failure;
 }
 
@@ -2565,7 +2781,7 @@ int CPL_STDCALL GDALGetRasterBandYSize( GDALRasterBandH hBand )
  * \brief Fetch the band number.
  *
  * This method returns the band that this GDALRasterBand objects represents
- * within it's dataset.  This method may return a value of 0 to indicate
+ * within its dataset.  This method may return a value of 0 to indicate
  * GDALRasterBand objects without an apparently relationship to a dataset,
  * such as GDALRasterBands serving as overviews.
  *
@@ -2729,16 +2945,27 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
     const double dfScale = nBuckets / (dfMax - dfMin);
     memset( panHistogram, 0, sizeof(GUIntBig) * nBuckets );
 
-    int bGotNoDataValue;
+    int bGotNoDataValue = FALSE;
     const double dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
     bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
-    /* Not advertized. May be removed at any time. Just as a provision if the */
-    /* old behaviour made sense somethimes... */
+    // Not advertized. May be removed at any time. Just as a provision if the
+    // old behaviour made sense somethimes.
     bGotNoDataValue = bGotNoDataValue &&
         !CPLTestBool(CPLGetConfigOption("GDAL_NODATA_IN_HISTOGRAM", "NO"));
+    bool bGotFloatNoDataValue = false;
+    float fNoDataValue = 0.0f;
+    if( eDataType == GDT_Float32 && bGotNoDataValue &&
+        (fabs(dfNoDataValue) <= std::numeric_limits<float>::max() ||
+         CPLIsInf(dfNoDataValue)) )
+    {
+        fNoDataValue = static_cast<float>(dfNoDataValue);
+        bGotFloatNoDataValue = true;
+        bGotNoDataValue = false;
+    }
 
     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
-    const bool bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
+    const bool bSignedByte =
+        pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE");
 
     if ( bApproxOK && HasArbitraryOverviews() )
     {
@@ -2746,11 +2973,12 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
 /*      Figure out how much the image should be reduced to get an       */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
-        double  dfReduction = sqrt(
-            (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
-
-        int     nXReduced, nYReduced;
+        const double dfReduction = sqrt(
+            static_cast<double>(nRasterXSize) * nRasterYSize /
+            GDALSTAT_APPROX_NUMSAMPLES );
 
+        int nXReduced = nRasterXSize;
+        int nYReduced = nRasterYSize;
         if ( dfReduction > 1.0 )
         {
             nXReduced = (int)( nRasterXSize / dfReduction );
@@ -2762,68 +2990,71 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
             if ( nYReduced == 0 )
                 nYReduced = 1;
         }
-        else
-        {
-            nXReduced = nRasterXSize;
-            nYReduced = nRasterYSize;
-        }
 
         void *pData =
             CPLMalloc(
                 GDALGetDataTypeSizeBytes(eDataType) * nXReduced * nYReduced );
 
-        CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
-                   nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
+        const CPLErr eErr =
+            IRasterIO(
+                GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
+                nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
         if ( eErr != CE_None )
         {
             CPLFree(pData);
             return eErr;
         }
 
-        /* this isn't the fastest way to do this, but is easier for now */
+        // This isn't the fastest way to do this, but is easier for now.
         for( int iY = 0; iY < nYReduced; iY++ )
         {
             for( int iX = 0; iX < nXReduced; iX++ )
             {
-                int    iOffset = iX + iY * nXReduced;
+                const int iOffset = iX + iY * nXReduced;
                 double dfValue = 0.0;
 
                 switch( eDataType )
                 {
                   case GDT_Byte:
                   {
-                    if (bSignedByte)
-                        dfValue = ((signed char *)pData)[iOffset];
+                    if( bSignedByte )
+                        dfValue = static_cast<signed char *>(pData)[iOffset];
                     else
-                        dfValue = ((GByte *)pData)[iOffset];
+                        dfValue = static_cast<GByte *>(pData)[iOffset];
                     break;
                   }
                   case GDT_UInt16:
-                    dfValue = ((GUInt16 *)pData)[iOffset];
+                    dfValue = static_cast<GUInt16 *>(pData)[iOffset];
                     break;
                   case GDT_Int16:
-                    dfValue = ((GInt16 *)pData)[iOffset];
+                    dfValue = static_cast<GInt16 *>(pData)[iOffset];
                     break;
                   case GDT_UInt32:
-                    dfValue = ((GUInt32 *)pData)[iOffset];
+                    dfValue = static_cast<GUInt32 *>(pData)[iOffset];
                     break;
                   case GDT_Int32:
-                    dfValue = ((GInt32 *)pData)[iOffset];
+                    dfValue = static_cast<GInt32 *>(pData)[iOffset];
                     break;
                   case GDT_Float32:
-                    dfValue = ((float *)pData)[iOffset];
-                    if (CPLIsNan(dfValue))
+                  {
+                    const float fValue = static_cast<float *>(pData)[iOffset];
+                    if( CPLIsNan(fValue) ||
+                        (bGotFloatNoDataValue && fValue == fNoDataValue) )
                         continue;
+                    dfValue = fValue;
                     break;
+                  }
                   case GDT_Float64:
-                    dfValue = ((double *)pData)[iOffset];
-                    if (CPLIsNan(dfValue))
+                    dfValue = static_cast<double *>(pData)[iOffset];
+                    if( CPLIsNan(dfValue) )
                         continue;
                     break;
                   case GDT_CInt16:
                     {
-                        double dfReal = ((GInt16 *)pData)[iOffset*2];
-                        double dfImag = ((GInt16 *)pData)[iOffset*2+1];
+                        const double dfReal =
+                            static_cast<GInt16 *>(pData)[iOffset*2];
+                        const double dfImag =
+                            static_cast<GInt16 *>(pData)[iOffset*2+1];
                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
                             continue;
                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
@@ -2831,8 +3062,10 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                     break;
                   case GDT_CInt32:
                     {
-                        double dfReal = ((GInt32 *)pData)[iOffset*2];
-                        double dfImag = ((GInt32 *)pData)[iOffset*2+1];
+                        const double dfReal =
+                            static_cast<GInt32 *>(pData)[iOffset*2];
+                        const double dfImag =
+                            static_cast<GInt32 *>(pData)[iOffset*2+1];
                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
                             continue;
                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
@@ -2840,8 +3073,10 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                     break;
                   case GDT_CFloat32:
                     {
-                        double dfReal = ((float *)pData)[iOffset*2];
-                        double dfImag = ((float *)pData)[iOffset*2+1];
+                        const double dfReal =
+                            static_cast<float *>(pData)[iOffset*2];
+                        const double dfImag =
+                            static_cast<float *>(pData)[iOffset*2+1];
                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
                             continue;
                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
@@ -2849,21 +3084,24 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                     break;
                   case GDT_CFloat64:
                     {
-                        double dfReal = ((double *)pData)[iOffset*2];
-                        double dfImag = ((double *)pData)[iOffset*2+1];
+                        const double dfReal =
+                            static_cast<double *>(pData)[iOffset*2];
+                        const double dfImag =
+                            static_cast<double *>(pData)[iOffset*2+1];
                         if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
                             continue;
                         dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
                     }
                     break;
                   default:
-                    CPLAssert( FALSE );
+                    CPLAssert( false );
                 }
 
                 if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                     continue;
 
-                int nIndex = (int) floor((dfValue - dfMin) * dfScale);
+                const int nIndex =
+                    static_cast<int>(floor((dfValue - dfMin) * dfScale));
 
                 if( nIndex < 0 )
                 {
@@ -2873,21 +3111,19 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                 else if( nIndex >= nBuckets )
                 {
                     if( bIncludeOutOfRange )
-                        panHistogram[nBuckets-1]++;
+                        ++panHistogram[nBuckets-1];
                 }
                 else
                 {
-                    panHistogram[nIndex]++;
+                    ++panHistogram[nIndex];
                 }
             }
         }
 
         CPLFree( pData );
     }
-
-    else    // No arbitrary overviews
+    else  // No arbitrary overviews.
     {
-
         if( !InitBlockInfo() )
             return CE_Failure;
 
@@ -2896,19 +3132,19 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
 
-        int nSampleRate;
+        int nSampleRate = 1;
         if ( bApproxOK )
         {
-            nSampleRate =
-                (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
+            nSampleRate = static_cast<int>(
+                std::max(1.0,
+                         sqrt(static_cast<double>(nBlocksPerRow) *
+                              nBlocksPerColumn)));
             // We want to avoid probing only the first column of blocks for
             // a square shaped raster, because it is not unlikely that it may
-            // be padding only (#6378)
+            // be padding only (#6378).
             if( nSampleRate == nBlocksPerRow && nBlocksPerRow > 1 )
               nSampleRate += 1;
         }
-        else
-            nSampleRate = 1;
 
 /* -------------------------------------------------------------------- */
 /*      Read the blocks, and add to histogram.                          */
@@ -2917,15 +3153,14 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
              iSampleBlock += nSampleRate )
         {
-            int  nXCheck, nYCheck;
-
-            if( !pfnProgress( iSampleBlock
-                              / ((double)nBlocksPerRow * nBlocksPerColumn),
-                              "Compute Histogram", pProgressData ) )
+            if( !pfnProgress(
+                    iSampleBlock /
+                        (static_cast<double>(nBlocksPerRow) * nBlocksPerColumn),
+                    "Compute Histogram", pProgressData ) )
                 return CE_Failure;
 
-            int iYBlock = iSampleBlock / nBlocksPerRow;
-            int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
+            const int iYBlock = iSampleBlock / nBlocksPerRow;
+            const int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
 
             GDALRasterBlock *poBlock = GetLockedBlockRef( iXBlock, iYBlock );
             if( poBlock == NULL )
@@ -2933,100 +3168,103 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
 
             void *pData = poBlock->GetDataRef();
 
+            int nXCheck = nBlockXSize;
             if( (iXBlock+1) * nBlockXSize > GetXSize() )
                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
-            else
-                nXCheck = nBlockXSize;
 
+            int nYCheck = nBlockYSize;
             if( (iYBlock+1) * nBlockYSize > GetYSize() )
                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
-            else
-                nYCheck = nBlockYSize;
 
-            /* this is a special case for a common situation */
+            // this is a special case for a common situation.
             if( eDataType == GDT_Byte && !bSignedByte
                 && dfScale == 1.0 && (dfMin >= -0.5 && dfMin <= 0.5)
                 && nYCheck == nBlockYSize && nXCheck == nBlockXSize
                 && nBuckets == 256 )
             {
-                int    nPixels = nXCheck * nYCheck;
-                GByte  *pabyData = (GByte *) pData;
+                const int nPixels = nXCheck * nYCheck;
+                GByte *pabyData = static_cast<GByte *>(pData);
 
                 for( int i = 0; i < nPixels; i++ )
-                    if (! (bGotNoDataValue && (pabyData[i] == (GByte)dfNoDataValue)))
+                    if( ! (bGotNoDataValue &&
+                           (pabyData[i] == (GByte)dfNoDataValue)))
                     {
                         panHistogram[pabyData[i]]++;
                     }
 
                 poBlock->DropLock();
-                continue; /* to next sample block */
+                continue;  // To next sample block.
             }
 
-            /* this isn't the fastest way to do this, but is easier for now */
+            // This isn't the fastest way to do this, but is easier for now.
             for( int iY = 0; iY < nYCheck; iY++ )
             {
                 for( int iX = 0; iX < nXCheck; iX++ )
                 {
-                    int    iOffset = iX + iY * nBlockXSize;
-                    int    nIndex;
+                    const int iOffset = iX + iY * nBlockXSize;
                     double dfValue = 0.0;
 
                     switch( eDataType )
                     {
                       case GDT_Byte:
                       {
-                        if (bSignedByte)
-                            dfValue = ((signed char *) pData)[iOffset];
+                        if( bSignedByte )
+                            dfValue =
+                                static_cast<signed char *>(pData)[iOffset];
                         else
-                            dfValue = ((GByte *) pData)[iOffset];
+                            dfValue = static_cast<GByte *>(pData)[iOffset];
                         break;
                       }
                       case GDT_UInt16:
-                        dfValue = ((GUInt16 *) pData)[iOffset];
+                        dfValue = static_cast<GUInt16 *>(pData)[iOffset];
                         break;
                       case GDT_Int16:
-                        dfValue = ((GInt16 *) pData)[iOffset];
+                        dfValue = static_cast<GInt16 *>(pData)[iOffset];
                         break;
                       case GDT_UInt32:
-                        dfValue = ((GUInt32 *) pData)[iOffset];
+                        dfValue = static_cast<GUInt32 *>(pData)[iOffset];
                         break;
                       case GDT_Int32:
-                        dfValue = ((GInt32 *) pData)[iOffset];
+                        dfValue = static_cast<GInt32 *>(pData)[iOffset];
                         break;
                       case GDT_Float32:
-                        dfValue = ((float *) pData)[iOffset];
-                        if (CPLIsNan(dfValue))
+                      {
+                        const float fValue = static_cast<float *>(pData)[iOffset];
+                        if( CPLIsNan(fValue) ||
+                            (bGotFloatNoDataValue && fValue == fNoDataValue) )
                             continue;
+                        dfValue = fValue;
                         break;
+                      }
                       case GDT_Float64:
-                        dfValue = ((double *) pData)[iOffset];
-                        if (CPLIsNan(dfValue))
+                        dfValue = static_cast<double *>(pData)[iOffset];
+                        if( CPLIsNan(dfValue) )
                             continue;
                         break;
                       case GDT_CInt16:
                         {
                             double  dfReal =
-                                ((GInt16 *) pData)[iOffset*2];
+                                static_cast<GInt16 *>(pData)[iOffset*2];
                             double  dfImag =
-                                ((GInt16 *) pData)[iOffset*2+1];
+                                static_cast<GInt16 *>(pData)[iOffset*2+1];
                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
                         }
                         break;
                       case GDT_CInt32:
                         {
                             double  dfReal =
-                                ((GInt32 *) pData)[iOffset*2];
+                                static_cast<GInt32 *>(pData)[iOffset*2];
                             double  dfImag =
-                                ((GInt32 *) pData)[iOffset*2+1];
+                                static_cast<GInt32 *>(pData)[iOffset*2+1];
                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
                         }
                         break;
                       case GDT_CFloat32:
                         {
                             double  dfReal =
-                                ((float *) pData)[iOffset*2];
+                                static_cast<float *>(pData)[iOffset*2];
                             double  dfImag =
-                                ((float *) pData)[iOffset*2+1];
+                                static_cast<float *>(pData)[iOffset*2+1];
                             if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
                                 continue;
                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
@@ -3035,33 +3273,35 @@ CPLErr GDALRasterBand::GetHistogram( double dfMin, double dfMax,
                       case GDT_CFloat64:
                         {
                             double  dfReal =
-                                ((double *) pData)[iOffset*2];
+                                static_cast<double *>(pData)[iOffset*2];
                             double  dfImag =
-                                ((double *) pData)[iOffset*2+1];
+                                static_cast<double *>(pData)[iOffset*2+1];
                             if ( CPLIsNan(dfReal) || CPLIsNan(dfImag) )
                                 continue;
                             dfValue = sqrt( dfReal * dfReal + dfImag * dfImag );
                         }
                         break;
                       default:
-                        CPLAssert( FALSE );
+                        CPLAssert( false );
                         return CE_Failure;
                     }
 
-                    if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
+                    if( bGotNoDataValue &&
+                        ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                         continue;
 
-                    nIndex = (int) floor((dfValue - dfMin) * dfScale);
+                    const int nIndex =
+                        static_cast<int>(floor((dfValue - dfMin) * dfScale));
 
                     if( nIndex < 0 )
                     {
                         if( bIncludeOutOfRange )
-                            panHistogram[0]++;
+                            ++panHistogram[0];
                     }
                     else if( nIndex >= nBuckets )
                     {
                         if( bIncludeOutOfRange )
-                            panHistogram[nBuckets-1]++;
+                            ++panHistogram[nBuckets-1];
                     }
                     else
                     {
@@ -3107,17 +3347,20 @@ GDALGetRasterHistogram( GDALRasterBandH hBand,
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
 
-    GUIntBig* panHistogramTemp = (GUIntBig*)VSIMalloc2(sizeof(GUIntBig), nBuckets);
+    GUIntBig* panHistogramTemp = static_cast<GUIntBig *>(
+        VSIMalloc2(sizeof(GUIntBig), nBuckets) );
     if( panHistogramTemp == NULL )
     {
-        poBand->ReportError( CE_Failure, CPLE_OutOfMemory,
-                     "Out of memory in GDALGetRasterHistogram()." );
+        poBand->ReportError(
+            CE_Failure, CPLE_OutOfMemory,
+            "Out of memory in GDALGetRasterHistogram()." );
         return CE_Failure;
     }
 
-    CPLErr eErr = poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogramTemp,
-                      bIncludeOutOfRange, bApproxOK,
-                      pfnProgress, pProgressData );
+    CPLErr eErr = poBand->GetHistogram(
+        dfMin, dfMax, nBuckets, panHistogramTemp,
+        bIncludeOutOfRange, bApproxOK,
+        pfnProgress, pProgressData );
 
     if( eErr == CE_None )
     {
@@ -3125,13 +3368,17 @@ GDALGetRasterHistogram( GDALRasterBandH hBand,
         {
             if( panHistogramTemp[i] > INT_MAX )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "Count for bucket %d, which is " CPL_FRMT_GUIB " exceeds maximum 32 bit value",
-                         i, panHistogramTemp[i]);
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Count for bucket %d, which is " CPL_FRMT_GUIB
+                    " exceeds maximum 32 bit value",
+                    i, panHistogramTemp[i] );
                 panHistogram[i] = INT_MAX;
             }
             else
-                panHistogram[i] = (int)panHistogramTemp[i];
+            {
+                panHistogram[i] = static_cast<int>(panHistogramTemp[i]);
+            }
         }
     }
 
@@ -3154,11 +3401,11 @@ GDALGetRasterHistogram( GDALRasterBandH hBand,
 
 CPLErr CPL_STDCALL
 GDALGetRasterHistogramEx( GDALRasterBandH hBand,
-                        double dfMin, double dfMax,
-                        int nBuckets, GUIntBig *panHistogram,
-                        int bIncludeOutOfRange, int bApproxOK,
-                        GDALProgressFunc pfnProgress,
-                        void *pProgressData )
+                          double dfMin, double dfMax,
+                          int nBuckets, GUIntBig *panHistogram,
+                          int bIncludeOutOfRange, int bApproxOK,
+                          GDALProgressFunc pfnProgress,
+                          void *pProgressData )
 
 {
     VALIDATE_POINTER1( hBand, "GDALGetRasterHistogramEx", CE_Failure );
@@ -3167,8 +3414,8 @@ GDALGetRasterHistogramEx( GDALRasterBandH hBand,
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
 
     return poBand->GetHistogram( dfMin, dfMax, nBuckets, panHistogram,
-                      bIncludeOutOfRange, bApproxOK,
-                      pfnProgress, pProgressData );
+                                 bIncludeOutOfRange, bApproxOK,
+                                 pfnProgress, pProgressData );
 }
 
 /************************************************************************/
@@ -3179,17 +3426,23 @@ GDALGetRasterHistogramEx( GDALRasterBandH hBand,
  * \brief Fetch default raster histogram.
  *
  * The default method in GDALRasterBand will compute a default histogram. This
- * method is overridden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
- * that may be able to fetch efficiently an already stored histogram.
+ * method is overridden by derived classes (such as GDALPamRasterBand,
+ * VRTDataset, HFADataset...) that may be able to fetch efficiently an already
+ * stored histogram.
  *
  * This method is the same as the C functions GDALGetDefaultHistogram() and
  * GDALGetDefaultHistogramEx().
  *
- * @param pdfMin pointer to double value that will contain the lower bound of the histogram.
- * @param pdfMax pointer to double value that will contain the upper bound of the histogram.
- * @param pnBuckets pointer to int value that will contain the number of buckets in *ppanHistogram.
- * @param ppanHistogram pointer to array into which the histogram totals are placed. To be freed with VSIFree
- * @param bForce TRUE to force the computation. If FALSE and no default histogram is available, the method will return CE_Warning
+ * @param pdfMin pointer to double value that will contain the lower bound of
+ * the histogram.
+ * @param pdfMax pointer to double value that will contain the upper bound of
+ * the histogram.
+ * @param pnBuckets pointer to int value that will contain the number of buckets
+ * in *ppanHistogram.
+ * @param ppanHistogram pointer to array into which the histogram totals are
+ * placed. To be freed with VSIFree
+ * @param bForce TRUE to force the computation. If FALSE and no default
+ * histogram is available, the method will return CE_Warning
  * @param pfnProgress function to report progress to completion.
  * @param pProgressData application data to pass to pfnProgress.
  *
@@ -3199,7 +3452,8 @@ GDALGetRasterHistogramEx( GDALRasterBandH hBand,
 
 CPLErr
     GDALRasterBand::GetDefaultHistogram( double *pdfMin, double *pdfMax,
-                                         int *pnBuckets, GUIntBig **ppanHistogram,
+                                         int *pnBuckets,
+                                         GUIntBig **ppanHistogram,
                                          int bForce,
                                          GDALProgressFunc pfnProgress,
                                          void *pProgressData )
@@ -3216,10 +3470,11 @@ CPLErr
     if( !bForce )
         return CE_Warning;
 
-    int nBuckets = 256;
+    const int nBuckets = 256;
 
     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
-    int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
+    const int bSignedByte =
+        pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE");
 
     if( GetRasterDataType() == GDT_Byte && !bSignedByte)
     {
@@ -3228,11 +3483,10 @@ CPLErr
     }
     else
     {
-        CPLErr eErr = CE_Failure;
-        double dfHalfBucket = 0;
 
-        eErr = GetStatistics( TRUE, TRUE, pdfMin, pdfMax, NULL, NULL );
-        dfHalfBucket = (*pdfMax - *pdfMin) / (2 * (nBuckets - 1));
+        const CPLErr eErr =
+            GetStatistics( TRUE, TRUE, pdfMin, pdfMax, NULL, NULL );
+        const double dfHalfBucket = (*pdfMax - *pdfMin) / (2 * (nBuckets - 1));
         *pdfMin -= dfHalfBucket;
         *pdfMax += dfHalfBucket;
 
@@ -3240,7 +3494,8 @@ CPLErr
             return eErr;
     }
 
-    *ppanHistogram = (GUIntBig *) VSICalloc(sizeof(GUIntBig), nBuckets);
+    *ppanHistogram = static_cast<GUIntBig *>(
+        VSICalloc(sizeof(GUIntBig), nBuckets) );
     if( *ppanHistogram == NULL )
     {
         ReportError( CE_Failure, CPLE_OutOfMemory,
@@ -3249,8 +3504,13 @@ CPLErr
     }
 
     *pnBuckets = nBuckets;
-    return GetHistogram( *pdfMin, *pdfMax, *pnBuckets, *ppanHistogram,
+    CPLErr eErr = GetHistogram( *pdfMin, *pdfMax, *pnBuckets, *ppanHistogram,
                          TRUE, FALSE, pfnProgress, pProgressData );
+    if( eErr != CE_None )
+    {
+        *pnBuckets = 0;
+    }
+    return eErr;
 }
 
 /************************************************************************/
@@ -3267,12 +3527,13 @@ CPLErr
   * @see GDALGetRasterHistogramEx()
   */
 
-CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand,
-                                double *pdfMin, double *pdfMax,
-                                int *pnBuckets, int **ppanHistogram,
-                                int bForce,
-                                GDALProgressFunc pfnProgress,
-                                void *pProgressData )
+CPLErr CPL_STDCALL GDALGetDefaultHistogram(
+    GDALRasterBandH hBand,
+    double *pdfMin, double *pdfMax,
+    int *pnBuckets, int **ppanHistogram,
+    int bForce,
+    GDALProgressFunc pfnProgress,
+    void *pProgressData )
 
 {
     VALIDATE_POINTER1( hBand, "GDALGetDefaultHistogram", CE_Failure );
@@ -3281,39 +3542,46 @@ CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand,
     VALIDATE_POINTER1( pnBuckets, "GDALGetDefaultHistogram", CE_Failure );
     VALIDATE_POINTER1( ppanHistogram, "GDALGetDefaultHistogram", CE_Failure );
 
-    GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
+    GDALRasterBand * const poBand = static_cast<GDALRasterBand*>(hBand);
     GUIntBig* panHistogramTemp = NULL;
     CPLErr eErr = poBand->GetDefaultHistogram( pdfMin, pdfMax,
         pnBuckets, &panHistogramTemp, bForce, pfnProgress, pProgressData );
     if( eErr == CE_None )
     {
-        int nBuckets = *pnBuckets;
-        *ppanHistogram = (int*) VSIMalloc2(sizeof(int), nBuckets);
+        const int nBuckets = *pnBuckets;
+        *ppanHistogram = static_cast<int *>(VSIMalloc2(sizeof(int), nBuckets));
         if( *ppanHistogram == NULL )
         {
-            poBand->ReportError( CE_Failure, CPLE_OutOfMemory,
-                        "Out of memory in GDALGetDefaultHistogram()." );
+            poBand->ReportError(
+                CE_Failure, CPLE_OutOfMemory,
+                "Out of memory in GDALGetDefaultHistogram()." );
             VSIFree(panHistogramTemp);
             return CE_Failure;
         }
 
-        for(int i=0;i<nBuckets;i++)
+        for( int i = 0; i < nBuckets; ++i )
         {
             if( panHistogramTemp[i] > INT_MAX )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "Count for bucket %d, which is " CPL_FRMT_GUIB " exceeds maximum 32 bit value",
-                         i, panHistogramTemp[i]);
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Count for bucket %d, which is " CPL_FRMT_GUIB
+                    " exceeds maximum 32 bit value",
+                    i, panHistogramTemp[i] );
                 (*ppanHistogram)[i] = INT_MAX;
             }
             else
-                (*ppanHistogram)[i] = (int)panHistogramTemp[i];
+            {
+                (*ppanHistogram)[i] = static_cast<int>(panHistogramTemp[i]);
+            }
         }
 
         CPLFree(panHistogramTemp);
     }
     else
+    {
         *ppanHistogram = NULL;
+    }
 
     return eErr;
 }
@@ -3330,12 +3598,13 @@ CPLErr CPL_STDCALL GDALGetDefaultHistogram( GDALRasterBandH hBand,
   * @since GDAL 2.0
   */
 
-CPLErr CPL_STDCALL GDALGetDefaultHistogramEx( GDALRasterBandH hBand,
-                                double *pdfMin, double *pdfMax,
-                                int *pnBuckets, GUIntBig **ppanHistogram,
-                                int bForce,
-                                GDALProgressFunc pfnProgress,
-                                void *pProgressData )
+CPLErr CPL_STDCALL GDALGetDefaultHistogramEx(
+    GDALRasterBandH hBand,
+    double *pdfMin, double *pdfMax,
+    int *pnBuckets, GUIntBig **ppanHistogram,
+    int bForce,
+    GDALProgressFunc pfnProgress,
+    void *pProgressData )
 
 {
     VALIDATE_POINTER1( hBand, "GDALGetDefaultHistogram", CE_Failure );
@@ -3353,6 +3622,7 @@ CPLErr CPL_STDCALL GDALGetDefaultHistogramEx( GDALRasterBandH hBand,
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::AdviseRead(int,int,int,int,int,int,GDALDataType,char**)
  * \brief Advise driver of upcoming read requests.
  *
  * Some GDAL drivers operate more efficiently if they know in advance what
@@ -3390,11 +3660,18 @@ CPLErr CPL_STDCALL GDALGetDefaultHistogramEx( GDALRasterBandH hBand,
  * is ignored.
  */
 
+/**/
+/**/
+
 CPLErr GDALRasterBand::AdviseRead(
-    CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
-    CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
-    CPL_UNUSED int nBufXSize, CPL_UNUSED int nBufYSize,
-    CPL_UNUSED GDALDataType eBufType, CPL_UNUSED char **papszOptions )
+    int /*nXOff*/,
+    int /*nYOff*/,
+    int /*nXSize*/,
+    int /*nYSize*/,
+    int /*nBufXSize*/,
+    int /*nBufYSize*/,
+    GDALDataType /*eBufType*/,
+    char ** /*papszOptions*/ )
 {
     return CE_None;
 }
@@ -3403,7 +3680,6 @@ CPLErr GDALRasterBand::AdviseRead(
 /*                        GDALRasterAdviseRead()                        */
 /************************************************************************/
 
-
 /**
  * \brief Advise driver of upcoming read requests.
  *
@@ -3472,7 +3748,8 @@ CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
                                       double *pdfMean, double *pdfStdDev )
 
 {
-    double       dfMin=0.0, dfMax=0.0;
+    double dfMin = 0.0;
+    double dfMax = 0.0;
 
 /* -------------------------------------------------------------------- */
 /*      Do we already have metadata items for the requested values?     */
@@ -3499,7 +3776,8 @@ CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
 /* -------------------------------------------------------------------- */
     if( bApproxOK && pdfMean == NULL && pdfStdDev == NULL )
     {
-        int          bSuccessMin, bSuccessMax;
+        int bSuccessMin = FALSE;
+        int bSuccessMax = FALSE;
 
         dfMin = GetMinimum( &bSuccessMin );
         dfMax = GetMaximum( &bSuccessMax );
@@ -3536,8 +3814,8 @@ CPLErr GDALRasterBand::GetStatistics( int bApproxOK, int bForce,
  */
 
 CPLErr CPL_STDCALL GDALGetRasterStatistics(
-        GDALRasterBandH hBand, int bApproxOK, int bForce,
-        double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
+    GDALRasterBandH hBand, int bApproxOK, int bForce,
+    double *pdfMin, double *pdfMax, double *pdfMean, double *pdfStdDev )
 
 {
     VALIDATE_POINTER1( hBand, "GDALGetRasterStatistics", CE_Failure );
@@ -3547,51 +3825,892 @@ CPLErr CPL_STDCALL GDALGetRasterStatistics(
         bApproxOK, bForce, pdfMin, pdfMax, pdfMean, pdfStdDev );
 }
 
+#ifdef CPL_HAS_GINT64
+
 /************************************************************************/
-/*                         ComputeStatistics()                          */
+/*                         GDALUInt128                                  */
 /************************************************************************/
 
-/**
- * \brief Compute image statistics.
- *
- * Returns the minimum, maximum, mean and standard deviation of all
- * pixel values in this band.  If approximate statistics are sufficient,
- * the bApproxOK flag can be set to true in which case overviews, or a
- * subset of image tiles may be used in computing the statistics.
- *
- * Once computed, the statistics will generally be "set" back on the
- * raster band using SetStatistics().
- *
- * This method is the same as the C function GDALComputeRasterStatistics().
- *
- * @param bApproxOK If TRUE statistics may be computed based on overviews
- * or a subset of all tiles.
- *
- * @param pdfMin Location into which to load image minimum (may be NULL).
- *
- * @param pdfMax Location into which to load image maximum (may be NULL).-
- *
- * @param pdfMean Location into which to load image mean (may be NULL).
- *
- * @param pdfStdDev Location into which to load image standard deviation
- * (may be NULL).
- *
- * @param pfnProgress a function to call to report progress, or NULL.
- *
- * @param pProgressData application data to pass to the progress function.
- *
- * @return CE_None on success, or CE_Failure if an error occurs or processing
- * is terminated by the user.
- */
+#ifdef HAVE_UINT128_T
+class GDALUInt128
+{
+        __uint128_t val;
 
-CPLErr
-GDALRasterBand::ComputeStatistics( int bApproxOK,
-                                   double *pdfMin, double *pdfMax,
-                                   double *pdfMean, double *pdfStdDev,
-                                   GDALProgressFunc pfnProgress,
-                                   void *pProgressData )
+        explicit GDALUInt128(__uint128_t valIn) : val(valIn) {}
 
-{
+    public:
+        static GDALUInt128 Mul(GUIntBig first, GUIntBig second)
+        {
+            // Evaluates to just a single mul on x86_64
+            return GDALUInt128((__uint128_t)first * second);
+        }
+
+        GDALUInt128 operator- (const GDALUInt128& other) const
+        {
+            return GDALUInt128(val - other.val);
+        }
+
+        operator double() const
+        {
+            return static_cast<double>(val);
+        }
+};
+#else
+
+#if defined(_MSC_VER) && defined(_M_X64)
+#include <intrin.h>
+#endif
+
+class GDALUInt128
+{
+        GUIntBig low, high;
+
+        GDALUInt128(GUIntBig lowIn, GUIntBig highIn):
+                                        low(lowIn), high(highIn) {}
+
+    public:
+        static GDALUInt128 Mul(GUIntBig first, GUIntBig second)
+        {
+#if defined(_MSC_VER) && defined(_M_X64)
+            GUIntBig highRes;
+            GUIntBig lowRes = _umul128(first, second, &highRes);
+            return GDALUInt128(lowRes, highRes);
+#else
+            const GUInt32 firstLow = static_cast<GUInt32>(first);
+            const GUInt32 firstHigh = static_cast<GUInt32>(first >> 32);
+            const GUInt32 secondLow = static_cast<GUInt32>(second);
+            const GUInt32 secondHigh = static_cast<GUInt32>(second >> 32);
+            GUIntBig highRes = 0;
+            const GUIntBig firstLowSecondHigh =
+                    static_cast<GUIntBig>(firstLow) * secondHigh;
+            const GUIntBig firstHighSecondLow =
+                    static_cast<GUIntBig>(firstHigh) * secondLow;
+            const GUIntBig middleTerm = firstLowSecondHigh + firstHighSecondLow;
+            if( middleTerm < firstLowSecondHigh ) // check for overflow
+                highRes += ((GUIntBig)1) << 32;
+            const GUIntBig firstLowSecondLow =
+                    static_cast<GUIntBig>(firstLow) * secondLow;
+            GUIntBig lowRes = firstLowSecondLow + (middleTerm << 32);
+            if( lowRes < firstLowSecondLow ) // check for overflow
+                highRes ++;
+            highRes += (middleTerm >> 32) +
+                            static_cast<GUIntBig>(firstHigh) * secondHigh;
+            return GDALUInt128(lowRes, highRes);
+#endif
+        }
+
+        GDALUInt128 operator- (const GDALUInt128& other) const
+        {
+            GUIntBig highRes = high - other.high;
+            GUIntBig lowRes = low - other.low;
+            if (lowRes > low) // check for underflow
+                --highRes;
+            return GDALUInt128(lowRes, highRes);
+        }
+
+        operator double() const
+        {
+            const double twoPow64 = 18446744073709551616.0;
+            return high * twoPow64 + low;
+        }
+};
+#endif
+
+/************************************************************************/
+/*                    ComputeStatisticsInternal()                       */
+/************************************************************************/
+
+// The rationale for below optimizations is detailed in statistics.txt
+
+// Use with T = GDT_Byte or GDT_UInt16 only !
+template<class T>
+static void ComputeStatisticsInternalGeneric( int nXCheck,
+                                       int nBlockXSize,
+                                       int nYCheck,
+                                       const T* pData,
+                                       bool bHasNoData,
+                                       GUInt32 nNoDataValue,
+                                       GUInt32& nMin,
+                                       GUInt32& nMax,
+                                       GUIntBig& nSum,
+                                       GUIntBig& nSumSquare,
+                                       GUIntBig& nSampleCount )
+{
+    if( bHasNoData )
+    {
+        // General case
+        for( int iY = 0; iY < nYCheck; iY++ )
+        {
+            for( int iX = 0; iX < nXCheck; iX++ )
+            {
+                const int iOffset = iX + iY * nBlockXSize;
+                const GUInt32 nValue = pData[iOffset];
+                if( nValue == nNoDataValue )
+                    continue;
+                nSampleCount ++;
+                if( nValue < nMin )
+                    nMin = nValue;
+                if( nValue > nMax )
+                    nMax = nValue;
+                nSum += nValue;
+                nSumSquare += nValue * nValue;
+            }
+        }
+    }
+    else if( nMin == std::numeric_limits<T>::min() &&
+             nMax == std::numeric_limits<T>::max() )
+    {
+        // Optimization when there is no nodata and we know we have already
+        // reached the min and max
+        for( int iY = 0; iY < nYCheck; iY++ )
+        {
+            int iX;
+            for( iX = 0; iX + 3 < nXCheck; iX+=4 )
+            {
+                const int iOffset = iX + iY * nBlockXSize;
+                const GUInt32 nValue = pData[iOffset];
+                const GUInt32 nValue2 = pData[iOffset+1];
+                const GUInt32 nValue3 = pData[iOffset+2];
+                const GUInt32 nValue4 = pData[iOffset+3];
+                nSum += nValue;
+                nSumSquare += nValue * nValue;
+                nSum += nValue2;
+                nSumSquare += nValue2 * nValue2;
+                nSum += nValue3;
+                nSumSquare += nValue3 * nValue3;
+                nSum += nValue4;
+                nSumSquare += nValue4 * nValue4;
+            }
+            for( ; iX < nXCheck; ++iX )
+            {
+                const int iOffset = iX + iY * nBlockXSize;
+                const GUInt32 nValue = pData[iOffset];
+                nSum += nValue;
+                nSumSquare += nValue * nValue;
+            }
+        }
+        nSampleCount += nXCheck * nYCheck;
+    }
+    else
+    {
+        for( int iY = 0; iY < nYCheck; iY++ )
+        {
+            int iX;
+            for( iX = 0; iX + 1 < nXCheck; iX+=2 )
+            {
+                const int iOffset = iX + iY * nBlockXSize;
+                const GUInt32 nValue = pData[iOffset];
+                const GUInt32 nValue2 = pData[iOffset+1];
+                if( nValue < nValue2 )
+                {
+                    if( nValue < nMin )
+                        nMin = nValue;
+                    if( nValue2 > nMax )
+                        nMax = nValue2;
+                }
+                else
+                {
+                    if( nValue2 < nMin )
+                        nMin = nValue2;
+                    if( nValue > nMax )
+                        nMax = nValue;
+                }
+                nSum += nValue;
+                nSumSquare += nValue * nValue;
+                nSum += nValue2;
+                nSumSquare += nValue2 * nValue2;
+            }
+            if( iX < nXCheck )
+            {
+                const int iOffset = iX + iY * nBlockXSize;
+                const GUInt32 nValue = pData[iOffset];
+                if( nValue < nMin )
+                    nMin = nValue;
+                if( nValue > nMax )
+                    nMax = nValue;
+                nSum += nValue;
+                nSumSquare += nValue * nValue;
+            }
+        }
+        nSampleCount += nXCheck * nYCheck;
+    }
+}
+
+// Specialization for Byte that is mostly 32 bit friendly as it avoids
+// using 64bit accumulators in internal loops. This also slightly helps in
+// 64bit mode.
+template<>
+void ComputeStatisticsInternalGeneric<GByte>( int nXCheck,
+                                       int nBlockXSize,
+                                       int nYCheck,
+                                       const GByte* pData,
+                                       bool bHasNoData,
+                                       GUInt32 nNoDataValue,
+                                       GUInt32& nMin,
+                                       GUInt32& nMax,
+                                       GUIntBig& nSum,
+                                       GUIntBig& nSumSquare,
+                                       GUIntBig& nSampleCount )
+{
+    int nOuterLoops = nXCheck / 65536;
+    if( nXCheck % 65536 )
+        nOuterLoops ++;
+
+    if( bHasNoData )
+    {
+        // General case
+        for( int iY = 0; iY < nYCheck; iY++ )
+        {
+            int iX = 0;
+            for( int k=0; k< nOuterLoops; k++ )
+            {
+                int iMax = iX + 65536;
+                if (iMax > nXCheck )
+                    iMax = nXCheck;
+                GUInt32 nSum32bit = 0;
+                GUInt32 nSumSquare32bit = 0;
+                GUInt32 nSampleCount32bit = 0;
+                for( ; iX < iMax; iX++)
+                {
+                    const int iOffset = iX + iY * nBlockXSize;
+                    const GUInt32 nValue = pData[iOffset];
+                    if( nValue == nNoDataValue )
+                        continue;
+                    nSampleCount32bit ++;
+                    if( nValue < nMin )
+                        nMin = nValue;
+                    if( nValue > nMax )
+                        nMax = nValue;
+                    nSum32bit += nValue;
+                    nSumSquare32bit += nValue * nValue;
+                }
+                nSampleCount += nSampleCount32bit;
+                nSum += nSum32bit;
+                nSumSquare += nSumSquare32bit;
+            }
+        }
+    }
+    else if( nMin == 0 &&
+             nMax == 255 )
+    {
+        // Optimization when there is no nodata and we know we have already
+        // reached the min and max
+        for( int iY = 0; iY < nYCheck; iY++ )
+        {
+            int iX = 0;
+            for( int k=0; k< nOuterLoops; k++ )
+            {
+                int iMax = iX + 65536;
+                if (iMax > nXCheck )
+                    iMax = nXCheck;
+                GUInt32 nSum32bit = 0;
+                GUInt32 nSumSquare32bit = 0;
+                for( ; iX + 3 < iMax; iX+=4 )
+                {
+                    const int iOffset = iX + iY * nBlockXSize;
+                    const GUInt32 nValue = pData[iOffset];
+                    const GUInt32 nValue2 = pData[iOffset+1];
+                    const GUInt32 nValue3 = pData[iOffset+2];
+                    const GUInt32 nValue4 = pData[iOffset+3];
+                    nSum32bit += nValue;
+                    nSumSquare32bit += nValue * nValue;
+                    nSum32bit += nValue2;
+                    nSumSquare32bit += nValue2 * nValue2;
+                    nSum32bit += nValue3;
+                    nSumSquare32bit += nValue3 * nValue3;
+                    nSum32bit += nValue4;
+                    nSumSquare32bit += nValue4 * nValue4;
+                }
+                nSum += nSum32bit;
+                nSumSquare += nSumSquare32bit;
+            }
+            for( ; iX < nXCheck; ++iX )
+            {
+                const int iOffset = iX + iY * nBlockXSize;
+                const GUInt32 nValue = pData[iOffset];
+                nSum += nValue;
+                nSumSquare += nValue * nValue;
+            }
+        }
+        nSampleCount += nXCheck * nYCheck;
+    }
+    else
+    {
+        for( int iY = 0; iY < nYCheck; iY++ )
+        {
+            int iX = 0;
+            for( int k=0; k< nOuterLoops; k++ )
+            {
+                int iMax = iX + 65536;
+                if (iMax > nXCheck )
+                    iMax = nXCheck;
+                GUInt32 nSum32bit = 0;
+                GUInt32 nSumSquare32bit = 0;
+                for( ; iX + 1 < iMax; iX+=2 )
+                {
+                    const int iOffset = iX + iY * nBlockXSize;
+                    const GUInt32 nValue = pData[iOffset];
+                    const GUInt32 nValue2 = pData[iOffset+1];
+                    if( nValue < nValue2 )
+                    {
+                        if( nValue < nMin )
+                            nMin = nValue;
+                        if( nValue2 > nMax )
+                            nMax = nValue2;
+                    }
+                    else
+                    {
+                        if( nValue2 < nMin )
+                            nMin = nValue2;
+                        if( nValue > nMax )
+                            nMax = nValue;
+                    }
+                    nSum32bit += nValue;
+                    nSumSquare32bit += nValue * nValue;
+                    nSum32bit += nValue2;
+                    nSumSquare32bit += nValue2 * nValue2;
+                }
+                nSum += nSum32bit;
+                nSumSquare += nSumSquare32bit;
+            }
+            if( iX < nXCheck )
+            {
+                const int iOffset = iX + iY * nBlockXSize;
+                const GUInt32 nValue = pData[iOffset];
+                if( nValue < nMin )
+                    nMin = nValue;
+                if( nValue > nMax )
+                    nMax = nValue;
+                nSum += nValue;
+                nSumSquare += nValue * nValue;
+            }
+        }
+        nSampleCount += nXCheck * nYCheck;
+    }
+}
+
+template<class T>
+static void ComputeStatisticsInternal( int nXCheck,
+                                       int nBlockXSize,
+                                       int nYCheck,
+                                       const T* pData,
+                                       bool bHasNoData,
+                                       GUInt32 nNoDataValue,
+                                       GUInt32& nMin,
+                                       GUInt32& nMax,
+                                       GUIntBig& nSum,
+                                       GUIntBig& nSumSquare,
+                                       GUIntBig& nSampleCount )
+{
+    ComputeStatisticsInternalGeneric( nXCheck, nBlockXSize, nYCheck,
+                                      pData,
+                                      bHasNoData, nNoDataValue,
+                                      nMin, nMax, nSum, nSumSquare,
+                                      nSampleCount );
+}
+
+#if (defined(__x86_64__) || defined(_M_X64)) && (defined(__GNUC__) || defined(_MSC_VER))
+
+#include <emmintrin.h>
+
+#ifdef __SSE4_1__
+#include <smmintrin.h>
+#endif
+
+#if defined(__GNUC__)
+#define ALIGNED_16(x) x __attribute__ ((aligned (16)))
+#else
+#define ALIGNED_16(x) __declspec(align(16)) x
+#endif
+
+// Some convenience macros
+#define ZERO128                      _mm_setzero_si128()
+#ifdef __SSE4_1__
+#define EXTEND_UINT16_TO_UINT32(reg) _mm_cvtepu16_epi32(reg)
+#else
+#define EXTEND_UINT16_TO_UINT32(reg) _mm_unpacklo_epi16(reg, ZERO128)
+#endif
+#define GET_HIGH_64BIT(reg)          _mm_shuffle_epi32(reg, 2 | (3 << 2))
+
+#include "gdal_avx2_emulation.hpp"
+
+#define ZERO256                      GDALmm256_setzero_si256()
+
+// SSE2/AVX2 optimization for GByte case
+// In pure SSE2, this relies on gdal_avx2_emulation.hpp. There is no
+// penaly in using the emulation, because, given the mm256 intrinsics used here,
+// there are strictly equivalent to 2 parallel SSE2 streams.
+template<>
+void ComputeStatisticsInternal<GByte>( int nXCheck,
+                                       int nBlockXSize,
+                                       int nYCheck,
+                                       // assumed to be aligned on 256 bits
+                                       const GByte* pData,
+                                       bool bHasNoData,
+                                       GUInt32 nNoDataValue,
+                                       GUInt32& nMin,
+                                       GUInt32& nMax,
+                                       GUIntBig& nSum,
+                                       GUIntBig& nSumSquare,
+                                       GUIntBig& nSampleCount )
+{
+    if( bHasNoData && nXCheck == nBlockXSize && nXCheck * nYCheck >= 32 &&
+        nMin <= nMax )
+    {
+        // 32-byte alignment may not be enforced by linker, so do it at hand
+        GByte aby32ByteUnaligned[32+32+32+32+32];
+        GByte* paby32ByteAligned = aby32ByteUnaligned +
+                                    (32 - ((GUIntptr_t)aby32ByteUnaligned % 32));
+        GByte* pabyMin = paby32ByteAligned;
+        GByte* pabyMax = paby32ByteAligned + 32;
+        GUInt32* panSum = (GUInt32*)(paby32ByteAligned + 32*2);
+        GUInt32* panSumSquare = (GUInt32*)(paby32ByteAligned + 32*3);
+
+        int i = 0;
+        // Make sure that sumSquare can fit on uint32
+        // * 8 since we can hold 8 sums per vector register
+        const int nMaxIterationsPerInnerLoop = 8 *
+                ((std::numeric_limits<GUInt32>::max() / (255 * 255)) & ~31);
+        int nOuterLoops = (nXCheck * nYCheck) / nMaxIterationsPerInnerLoop;
+        if( ((nXCheck * nYCheck) % nMaxIterationsPerInnerLoop) != 0 )
+            nOuterLoops ++;
+
+        const GDALm256i ymm_nodata = GDALmm256_set1_epi8(
+                                        static_cast<GByte>(nNoDataValue) );
+        // any non noData value in [min,max] would do.
+        const GDALm256i ymm_neutral = GDALmm256_set1_epi8(
+                                        static_cast<GByte>(nMin) );
+        GDALm256i ymm_min = ymm_neutral;
+        GDALm256i ymm_max = ymm_neutral;
+
+        const bool bComputeMinMax = nMin > 0 || nMax < 255;
+
+        for( int k=0; k< nOuterLoops; k++ )
+        {
+            int iMax = i + nMaxIterationsPerInnerLoop;
+            if( iMax > nXCheck * nYCheck )
+                iMax = nXCheck * nYCheck;
+
+            // holds 4 uint32 sums in [0], [2], [4] and [6]
+            GDALm256i ymm_sum = ZERO256;
+            // holds 8 uint32 sums
+            GDALm256i ymm_sumsquare = ZERO256;
+            // holds 4 uint32 sums in [0], [2], [4] and [6]
+            GDALm256i ymm_count_nodata_mul_255 = ZERO256;
+            const int iInit = i;
+            for( ;i+31<iMax; i+=32 )
+            {
+                const GDALm256i ymm = GDALmm256_load_si256((GDALm256i*)(pData + i));
+
+                // Check which values are nodata
+                const GDALm256i ymm_eq_nodata =
+                                        GDALmm256_cmpeq_epi8( ymm, ymm_nodata );
+                // Count how many values are nodata (due to cmpeq putting 255
+                // when condition is met, this will actually be 255 times
+                // the number of nodata value, spread in 4 64 bits words).
+                // We can use add_epi32 as the counter will not overflow uint32
+                ymm_count_nodata_mul_255 = GDALmm256_add_epi32 (
+                                    ymm_count_nodata_mul_255,
+                                    GDALmm256_sad_epu8(ymm_eq_nodata, ZERO256) );
+                // Replace all nodata values by zero for the purpose of sum
+                // and sumquare.
+                const GDALm256i ymm_nodata_by_zero =
+                                GDALmm256_andnot_si256(ymm_eq_nodata, ymm);
+                if( bComputeMinMax )
+                {
+                    // Replace all nodata values by a neutral value for the
+                    // purpose of min and max.
+                    const GDALm256i ymm_nodata_by_neutral = GDALmm256_or_si256(
+                                GDALmm256_and_si256(ymm_eq_nodata, ymm_neutral),
+                                ymm_nodata_by_zero);
+
+                    ymm_min = GDALmm256_min_epu8 (ymm_min,
+                                                  ymm_nodata_by_neutral);
+                    ymm_max = GDALmm256_max_epu8 (ymm_max,
+                                                  ymm_nodata_by_neutral);
+                }
+
+                // Extend lower 128 bits of ymm from uint8 to uint16
+                const GDALm256i ymm_low = GDALmm256_cvtepu8_epi16(
+                            GDALmm256_extracti128_si256(ymm_nodata_by_zero, 0));
+                // Compute square of those 16 values as 32 bit result
+                // and add adjacent pairs
+                const GDALm256i ymm_low_square =
+                                            GDALmm256_madd_epi16(ymm_low, ymm_low);
+                // Add to the sumsquare accumulator
+                ymm_sumsquare = GDALmm256_add_epi32(ymm_sumsquare, ymm_low_square);
+
+                // Same as before with high 128bits of ymm
+                const GDALm256i ymm_high = GDALmm256_cvtepu8_epi16(
+                            GDALmm256_extracti128_si256(ymm_nodata_by_zero, 1));
+                const GDALm256i ymm_high_square =
+                                        GDALmm256_madd_epi16(ymm_high, ymm_high);
+                ymm_sumsquare = GDALmm256_add_epi32(ymm_sumsquare, ymm_high_square);
+
+                // Now compute the sums
+                ymm_sum = GDALmm256_add_epi32(ymm_sum,
+                                GDALmm256_sad_epu8(ymm_nodata_by_zero, ZERO256));
+            }
+
+            GUInt32* panCoutNoDataMul255 = panSum;
+            GDALmm256_store_si256((GDALm256i*)panCoutNoDataMul255,
+                               ymm_count_nodata_mul_255);
+            nSampleCount += (i - iInit) -
+                        (panCoutNoDataMul255[0] + panCoutNoDataMul255[2] +
+                         panCoutNoDataMul255[4] + panCoutNoDataMul255[6]) / 255;
+
+            GDALmm256_store_si256((GDALm256i*)panSum, ymm_sum);
+            GDALmm256_store_si256((GDALm256i*)panSumSquare, ymm_sumsquare);
+            nSum += panSum[0] + panSum[2] + panSum[4] + panSum[6];
+            nSumSquare += static_cast<GUIntBig>(panSumSquare[0]) +
+                          panSumSquare[1] + panSumSquare[2] + panSumSquare[3] +
+                          panSumSquare[4] + panSumSquare[5] + panSumSquare[6] +
+                          panSumSquare[7];
+        }
+
+        if( bComputeMinMax )
+        {
+            GDALmm256_store_si256((GDALm256i*)pabyMin, ymm_min);
+            GDALmm256_store_si256((GDALm256i*)pabyMax, ymm_max);
+            for(int j=0;j<32;j++)
+            {
+                if( pabyMin[j] < nMin ) nMin = pabyMin[j];
+                if( pabyMax[j] > nMax ) nMax = pabyMax[j];
+            }
+        }
+
+        for( ; i<nXCheck * nYCheck; i++)
+        {
+            const GUInt32 nValue = pData[i];
+            if( nValue == nNoDataValue )
+                continue;
+            nSampleCount ++;
+            if( nValue < nMin )
+                nMin = nValue;
+            if( nValue > nMax )
+                nMax = nValue;
+            nSum += nValue;
+            nSumSquare += nValue * nValue;
+        }
+    }
+    else if( !bHasNoData && nXCheck == nBlockXSize && nXCheck * nYCheck >= 32 )
+    {
+        // 32-byte alignment may not be enforced by linker, so do it at hand
+        GByte aby32ByteUnaligned[32+32+32+32+32];
+        GByte* paby32ByteAligned = aby32ByteUnaligned +
+                                    (32 - ((GUIntptr_t)aby32ByteUnaligned % 32));
+        GByte* pabyMin = paby32ByteAligned;
+        GByte* pabyMax = paby32ByteAligned + 32;
+        GUInt32* panSum = (GUInt32*)(paby32ByteAligned + 32*2);
+        GUInt32* panSumSquare = (GUInt32*)(paby32ByteAligned + 32*3);
+
+        int i = 0;
+        // Make sure that sumSquare can fit on uint32
+        // * 8 since we can hold 8 sums per vector register
+        const int nMaxIterationsPerInnerLoop = 8 *
+                ((std::numeric_limits<GUInt32>::max() / (255 * 255)) & ~31);
+        int nOuterLoops = (nXCheck * nYCheck) / nMaxIterationsPerInnerLoop;
+        if( ((nXCheck * nYCheck) % nMaxIterationsPerInnerLoop) != 0 )
+            nOuterLoops ++;
+
+        GDALm256i ymm_min = GDALmm256_load_si256((GDALm256i*)(pData + i));
+        GDALm256i ymm_max = ymm_min;
+
+        const bool bComputeMinMax = nMin > 0 || nMax < 255;
+
+        for( int k=0; k< nOuterLoops; k++ )
+        {
+            int iMax = i + nMaxIterationsPerInnerLoop;
+            if( iMax > nXCheck * nYCheck )
+                iMax = nXCheck * nYCheck;
+
+            // holds 4 uint32 sums in [0], [2], [4] and [6]
+            GDALm256i ymm_sum = ZERO256;
+            GDALm256i ymm_sumsquare = ZERO256; // holds 8 uint32 sums
+            for( ;i+31<iMax; i+=32 )
+            {
+                const GDALm256i ymm = GDALmm256_load_si256((GDALm256i*)(pData + i));
+                if( bComputeMinMax )
+                {
+                    ymm_min = GDALmm256_min_epu8 (ymm_min, ymm);
+                    ymm_max = GDALmm256_max_epu8 (ymm_max, ymm);
+                }
+
+                // Extend lower 128 bits of ymm from uint8 to uint16
+                const GDALm256i ymm_low = GDALmm256_cvtepu8_epi16(
+                                            GDALmm256_extracti128_si256(ymm, 0));
+                // Compute square of those 16 values as 32 bit result
+                // and add adjacent pairs
+                const GDALm256i ymm_low_square =
+                                            GDALmm256_madd_epi16(ymm_low, ymm_low);
+                // Add to the sumsquare accumulator
+                ymm_sumsquare = GDALmm256_add_epi32(ymm_sumsquare, ymm_low_square);
+
+                // Same as before with high 128bits of ymm
+                const GDALm256i ymm_high = GDALmm256_cvtepu8_epi16(
+                                            GDALmm256_extracti128_si256(ymm, 1));
+                const GDALm256i ymm_high_square =
+                                        GDALmm256_madd_epi16(ymm_high, ymm_high);
+                ymm_sumsquare = GDALmm256_add_epi32(ymm_sumsquare, ymm_high_square);
+
+                // Now compute the sums
+                ymm_sum = GDALmm256_add_epi32(ymm_sum,
+                                           GDALmm256_sad_epu8(ymm, ZERO256));
+            }
+
+            GDALmm256_store_si256((GDALm256i*)panSum, ymm_sum);
+            GDALmm256_store_si256((GDALm256i*)panSumSquare, ymm_sumsquare);
+
+            nSum += panSum[0] + panSum[2] + panSum[4] + panSum[6];
+            nSumSquare += static_cast<GUIntBig>(panSumSquare[0]) +
+                          panSumSquare[1] + panSumSquare[2] + panSumSquare[3] +
+                          panSumSquare[4] + panSumSquare[5] + panSumSquare[6] +
+                          panSumSquare[7];
+        }
+
+        if( bComputeMinMax )
+        {
+            GDALmm256_store_si256((GDALm256i*)pabyMin, ymm_min);
+            GDALmm256_store_si256((GDALm256i*)pabyMax, ymm_max);
+            for(int j=0;j<32;j++)
+            {
+                if( pabyMin[j] < nMin ) nMin = pabyMin[j];
+                if( pabyMax[j] > nMax ) nMax = pabyMax[j];
+            }
+        }
+
+        for( ; i<nXCheck * nYCheck; i++)
+        {
+            const GUInt32 nValue = pData[i];
+            if( nValue < nMin )
+                nMin = nValue;
+            if( nValue > nMax )
+                nMax = nValue;
+            nSum += nValue;
+            nSumSquare += nValue * nValue;
+        }
+
+        nSampleCount += nXCheck * nYCheck;
+    }
+    else
+    {
+        ComputeStatisticsInternalGeneric( nXCheck, nBlockXSize, nYCheck,
+                                          pData,
+                                          bHasNoData, nNoDataValue,
+                                          nMin, nMax, nSum, nSumSquare,
+                                          nSampleCount );
+    }
+}
+
+// AVX2/SSE2 optimization for GUInt16 case
+template<>
+void ComputeStatisticsInternal<GUInt16>( int nXCheck,
+                                       int nBlockXSize,
+                                       int nYCheck,
+                                       // assumed to be aligned on 128 bits
+                                       const GUInt16* pData,
+                                       bool bHasNoData,
+                                       GUInt32 nNoDataValue,
+                                       GUInt32& nMin,
+                                       GUInt32& nMax,
+                                       GUIntBig& nSum,
+                                       GUIntBig& nSumSquare,
+                                       GUIntBig& nSampleCount )
+{
+    if( !bHasNoData && nXCheck == nBlockXSize && nXCheck * nYCheck >= 16 )
+    {
+        int i = 0;
+        // In SSE2, min_epu16 and max_epu16 do not exist, so shift from
+        // UInt16 to SInt16 to be able to use min_epi16 and max_epi16.
+        // Furthermore the shift is also needed to use madd_epi16
+        const GDALm256i ymm_m32768 = GDALmm256_set1_epi16(-32768);
+        GDALm256i ymm_min = GDALmm256_load_si256((GDALm256i*)(pData + i));
+        ymm_min = GDALmm256_add_epi16(ymm_min, ymm_m32768);
+        GDALm256i ymm_max = ymm_min;
+        GDALm256i ymm_sumsquare = ZERO256; // holds 4 uint64 sums
+
+        // Make sure that sum can fit on uint32
+        // * 8 since we can hold 8 sums per vector register
+        const int nMaxIterationsPerInnerLoop = 8 *
+                ((std::numeric_limits<GUInt32>::max() / 65535) & ~15);
+        int nOuterLoops = (nXCheck * nYCheck) / nMaxIterationsPerInnerLoop;
+        if( ((nXCheck * nYCheck) % nMaxIterationsPerInnerLoop) != 0 )
+            nOuterLoops ++;
+
+        const bool bComputeMinMax = nMin > 0 || nMax < 65535;
+
+        GUIntBig nSumThis = 0;
+        for( int k=0; k< nOuterLoops; k++ )
+        {
+            int iMax = i + nMaxIterationsPerInnerLoop;
+            if( iMax > nXCheck * nYCheck )
+                iMax = nXCheck * nYCheck;
+
+            GDALm256i ymm_sum = ZERO256; // holds 8 uint32 sums
+            for( ;i+15<iMax ; i+=16 )
+            {
+                const GDALm256i ymm = GDALmm256_load_si256((GDALm256i*)(pData + i));
+                const GDALm256i ymm_shifted = GDALmm256_add_epi16(ymm, ymm_m32768);
+                if( bComputeMinMax )
+                {
+                    ymm_min = GDALmm256_min_epi16 (ymm_min, ymm_shifted);
+                    ymm_max = GDALmm256_max_epi16 (ymm_max, ymm_shifted);
+                }
+
+                // Extend the 8 lower uint16 to uint32
+                const GDALm256i ymm_low = GDALmm256_cvtepu16_epi32(
+                                            GDALmm256_extracti128_si256(ymm, 0));
+                const GDALm256i ymm_high = GDALmm256_cvtepu16_epi32(
+                                            GDALmm256_extracti128_si256(ymm, 1));
+
+#ifndef naive_version
+                // Note: the int32 range can overflow for (0-32768)^2 +
+                // (0-32768)^2 = 0x80000000, but as we know the result is
+                // positive, this is OK as we interpret is a uint32.
+                const GDALm256i ymm_square = GDALmm256_madd_epi16(ymm_shifted,
+                                                                  ymm_shifted);
+                const GDALm256i ymm_square_low = GDALmm256_cvtepu32_epi64(
+                                    GDALmm256_extracti128_si256(ymm_square, 0));
+                ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare,
+                                                    ymm_square_low);
+                const GDALm256i ymm_square_high = GDALmm256_cvtepu32_epi64(
+                                    GDALmm256_extracti128_si256(ymm_square, 1));
+                ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare,
+                                                    ymm_square_high);
+#else
+                // Compute square of those 8 values
+                const GDALm256i ymm_low2 = GDALmm256_mullo_epi32(ymm_low, ymm_low);
+                // Extract 4 low uint32 and extend them to uint64
+                const GDALm256i ymm_low2_low = GDALmm256_cvtepu32_epi64(
+                                            GDALmm256_extracti128_si256(ymm_low2, 0));
+                // Extract 4 high uint32 and extend them to uint64
+                const GDALm256i ymm_low2_high = GDALmm256_cvtepu32_epi64(
+                                            GDALmm256_extracti128_si256(ymm_low2, 1));
+                // Add to the sumsquare accumulator
+                ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare, ymm_low2_low);
+                ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare, ymm_low2_high);
+
+                // Same with the 8 upper uint16
+                const GDALm256i ymm_high2 = GDALmm256_mullo_epi32(ymm_high, ymm_high);
+                const GDALm256i ymm_high2_low = GDALmm256_cvtepu32_epi64(
+                                            GDALmm256_extracti128_si256(ymm_high2, 0));
+                const GDALm256i ymm_high2_high = GDALmm256_cvtepu32_epi64(
+                                            GDALmm256_extracti128_si256(ymm_high2, 1));
+                ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare, ymm_high2_low);
+                ymm_sumsquare = GDALmm256_add_epi64(ymm_sumsquare, ymm_high2_high);
+#endif
+
+                // Now compute the sums
+                ymm_sum = GDALmm256_add_epi32(ymm_sum, ymm_low);
+                ymm_sum = GDALmm256_add_epi32(ymm_sum, ymm_high);
+            }
+
+            GUInt32 anSum[8];
+            GDALmm256_storeu_si256((GDALm256i*)anSum, ymm_sum);
+            nSumThis += static_cast<GUIntBig>(anSum[0]) + anSum[1] +
+                    anSum[2] + anSum[3] + anSum[4] + anSum[5] +
+                    anSum[6] + anSum[7];
+        }
+
+        if( bComputeMinMax )
+        {
+            GUInt16 anMin[16];
+            GUInt16 anMax[16];
+
+            // Unshift the result
+            ymm_min = GDALmm256_sub_epi16(ymm_min, ymm_m32768);
+            ymm_max = GDALmm256_sub_epi16(ymm_max, ymm_m32768);
+            GDALmm256_storeu_si256((GDALm256i*)anMin, ymm_min);
+            GDALmm256_storeu_si256((GDALm256i*)anMax, ymm_max);
+            for(int j=0;j<16;j++)
+            {
+                if( anMin[j] < nMin ) nMin = anMin[j];
+                if( anMax[j] > nMax ) nMax = anMax[j];
+            }
+        }
+
+        GUIntBig anSumSquare[4];
+        GDALmm256_storeu_si256((GDALm256i*)anSumSquare, ymm_sumsquare);
+        nSumSquare += anSumSquare[0] +
+                        anSumSquare[1] + anSumSquare[2] + anSumSquare[3];
+#ifndef naive_version
+        // Unshift the sum of squares
+        nSumSquare += 32768 * (2 * nSumThis - static_cast<GUIntBig>(i) * 32768);
+#endif
+        nSum += nSumThis;
+
+        for( ; i<nXCheck * nYCheck; i++)
+        {
+            const GUInt32 nValue = pData[i];
+            if( nValue < nMin )
+                nMin = nValue;
+            if( nValue > nMax )
+                nMax = nValue;
+            nSum += nValue;
+            nSumSquare += nValue * nValue;
+        }
+
+        nSampleCount += nXCheck * nYCheck;
+    }
+    else
+    {
+        ComputeStatisticsInternalGeneric( nXCheck, nBlockXSize, nYCheck,
+                                          pData,
+                                          bHasNoData, nNoDataValue,
+                                          nMin, nMax, nSum, nSumSquare,
+                                          nSampleCount );
+    }
+}
+
+#endif // (defined(__x86_64__) || defined(_M_X64)) && (defined(__GNUC__) || defined(_MSC_VER))
+
+#endif // CPL_HAS_GINT64
+
+/************************************************************************/
+/*                         ComputeStatistics()                          */
+/************************************************************************/
+
+/**
+ * \brief Compute image statistics.
+ *
+ * Returns the minimum, maximum, mean and standard deviation of all
+ * pixel values in this band.  If approximate statistics are sufficient,
+ * the bApproxOK flag can be set to true in which case overviews, or a
+ * subset of image tiles may be used in computing the statistics.
+ *
+ * Once computed, the statistics will generally be "set" back on the
+ * raster band using SetStatistics().
+ *
+ * This method is the same as the C function GDALComputeRasterStatistics().
+ *
+ * @param bApproxOK If TRUE statistics may be computed based on overviews
+ * or a subset of all tiles.
+ *
+ * @param pdfMin Location into which to load image minimum (may be NULL).
+ *
+ * @param pdfMax Location into which to load image maximum (may be NULL).-
+ *
+ * @param pdfMean Location into which to load image mean (may be NULL).
+ *
+ * @param pdfStdDev Location into which to load image standard deviation
+ * (may be NULL).
+ *
+ * @param pfnProgress a function to call to report progress, or NULL.
+ *
+ * @param pProgressData application data to pass to the progress function.
+ *
+ * @return CE_None on success, or CE_Failure if an error occurs or processing
+ * is terminated by the user.
+ */
+
+CPLErr
+GDALRasterBand::ComputeStatistics( int bApproxOK,
+                                   double *pdfMin, double *pdfMax,
+                                   double *pdfMean, double *pdfStdDev,
+                                   GDALProgressFunc pfnProgress,
+                                   void *pProgressData )
+
+{
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
 
@@ -3610,50 +4729,67 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
                                               pfnProgress, pProgressData );
     }
 
+    if( !pfnProgress( 0.0, "Compute Statistics", pProgressData ) )
+    {
+        ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+        return CE_Failure;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Read actual data and compute statistics.                        */
 /* -------------------------------------------------------------------- */
-    double      dfMin = 0.0, dfMax = 0.0;
     bool bFirstValue = true;
-    /* Using Welford algorithm ( http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance ) */
-    /* to compute standard deviation in a more numerically robust way than */
-    /* the difference of the sum of square values with the square of the sum */
-    /* dfMean and dfM2 are updated at each sample */
-    /* dfM2 is the sum of square of differences to the current mean */
-    double      dfMean = 0.0, dfM2 = 0.0;
-    GIntBig     nSampleCount = 0;
+    // Using Welford algorithm:
+    // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
+    // to compute standard deviation in a more numerically robust way than
+    // the difference of the sum of square values with the square of the sum.
+    // dfMean and dfM2 are updated at each sample.
+    // dfM2 is the sum of square of differences to the current mean.
+    double dfMin = 0.0;
+    double dfMax = 0.0;
+    double dfMean = 0.0;
+    double dfM2 = 0.0;
 
     GDALRasterIOExtraArg sExtraArg;
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
-    if( !pfnProgress( 0.0, "Compute Statistics", pProgressData ) )
+    int bGotNoDataValue = FALSE;
+    const double dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
+    bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
+    bool bGotFloatNoDataValue = false;
+    float fNoDataValue = 0.0f;
+    if( eDataType == GDT_Float32 && bGotNoDataValue &&
+        (fabs(dfNoDataValue) <= std::numeric_limits<float>::max() ||
+         CPLIsInf(dfNoDataValue)) )
     {
-        ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
-        return CE_Failure;
+        fNoDataValue = static_cast<float>(dfNoDataValue);
+        bGotFloatNoDataValue = true;
+        bGotNoDataValue = false;
     }
 
-    int bGotNoDataValue;
-    const double dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
-    bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
+    const char* pszPixelType =
+        GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
+    const bool bSignedByte =
+        pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE");
 
-    const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
-    int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
+    GUIntBig nSampleCount = 0;
 
-    if ( bApproxOK && HasArbitraryOverviews() )
+  if ( bApproxOK && HasArbitraryOverviews() )
     {
 /* -------------------------------------------------------------------- */
 /*      Figure out how much the image should be reduced to get an       */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
-        void    *pData;
-        int     nXReduced, nYReduced;
         double  dfReduction = sqrt(
-            (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
+            static_cast<double>(nRasterXSize) * nRasterYSize /
+            GDALSTAT_APPROX_NUMSAMPLES );
 
+        int nXReduced = nRasterXSize;
+        int nYReduced = nRasterYSize;
         if ( dfReduction > 1.0 )
         {
-            nXReduced = (int)( nRasterXSize / dfReduction );
-            nYReduced = (int)( nRasterYSize / dfReduction );
+            nXReduced = static_cast<int>( nRasterXSize / dfReduction );
+            nYReduced = static_cast<int>( nRasterYSize / dfReduction );
 
             // Catch the case of huge resizing ratios here
             if ( nXReduced == 0 )
@@ -3661,18 +4797,14 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
             if ( nYReduced == 0 )
                 nYReduced = 1;
         }
-        else
-        {
-            nXReduced = nRasterXSize;
-            nYReduced = nRasterYSize;
-        }
 
-        pData =
+        void *pData =
             CPLMalloc(
                 GDALGetDataTypeSizeBytes(eDataType) * nXReduced * nYReduced );
 
-        CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
-                   nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
+        const CPLErr eErr = IRasterIO(
+            GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
+            nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
         if ( eErr != CE_None )
         {
             CPLFree(pData);
@@ -3684,59 +4816,65 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
         {
             for( int iX = 0; iX < nXReduced; iX++ )
             {
-                int    iOffset = iX + iY * nXReduced;
+                const int iOffset = iX + iY * nXReduced;
                 double dfValue = 0.0;
 
+                // TODO(schwehr): This switch is repeated multiple times.
+                // Factor out to an inline function.
                 switch( eDataType )
                 {
                   case GDT_Byte:
                   {
-                    if (bSignedByte)
-                        dfValue = ((signed char *)pData)[iOffset];
+                    if( bSignedByte )
+                        dfValue = static_cast<signed char *>(pData)[iOffset];
                     else
-                        dfValue = ((GByte *)pData)[iOffset];
+                        dfValue = static_cast<GByte *>(pData)[iOffset];
                     break;
                   }
                   case GDT_UInt16:
-                    dfValue = ((GUInt16 *)pData)[iOffset];
+                    dfValue = static_cast<GUInt16 *>(pData)[iOffset];
                     break;
                   case GDT_Int16:
-                    dfValue = ((GInt16 *)pData)[iOffset];
+                    dfValue = static_cast<GInt16 *>(pData)[iOffset];
                     break;
                   case GDT_UInt32:
-                    dfValue = ((GUInt32 *)pData)[iOffset];
+                    dfValue = static_cast<GUInt32 *>(pData)[iOffset];
                     break;
                   case GDT_Int32:
-                    dfValue = ((GInt32 *)pData)[iOffset];
+                    dfValue = static_cast<GInt32 *>(pData)[iOffset];
                     break;
                   case GDT_Float32:
-                    dfValue = ((float *)pData)[iOffset];
-                    if (CPLIsNan(dfValue))
+                  {
+                    const float fValue = static_cast<float *>(pData)[iOffset];
+                    if( CPLIsNan(fValue) ||
+                        (bGotFloatNoDataValue && fValue == fNoDataValue) )
                         continue;
+                    dfValue = fValue;
                     break;
+                  }
                   case GDT_Float64:
-                    dfValue = ((double *)pData)[iOffset];
-                    if (CPLIsNan(dfValue))
+                    dfValue = static_cast<double *>(pData)[iOffset];
+                    if( CPLIsNan(dfValue) )
                         continue;
                     break;
                   case GDT_CInt16:
-                    dfValue = ((GInt16 *)pData)[iOffset*2];
+                    dfValue = static_cast<GInt16 *>(pData)[iOffset*2];
                     break;
                   case GDT_CInt32:
-                    dfValue = ((GInt32 *)pData)[iOffset*2];
+                    dfValue = static_cast<GInt32 *>(pData)[iOffset*2];
                     break;
                   case GDT_CFloat32:
-                    dfValue = ((float *)pData)[iOffset*2];
+                    dfValue = static_cast<float *>(pData)[iOffset*2];
                     if( CPLIsNan(dfValue) )
                         continue;
                     break;
                   case GDT_CFloat64:
-                    dfValue = ((double *)pData)[iOffset*2];
+                    dfValue = static_cast<double *>(pData)[iOffset*2];
                     if( CPLIsNan(dfValue) )
                         continue;
                     break;
                   default:
-                    CPLAssert( FALSE );
+                    CPLAssert( false );
                 }
 
                 if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
@@ -3744,17 +4882,18 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 
                 if( bFirstValue )
                 {
-                    dfMin = dfMax = dfValue;
+                    dfMin = dfValue;
+                    dfMax = dfValue;
                     bFirstValue = false;
                 }
                 else
                 {
-                    dfMin = MIN(dfMin,dfValue);
-                    dfMax = MAX(dfMax,dfValue);
+                    dfMin = std::min(dfMin, dfValue);
+                    dfMax = std::max(dfMax, dfValue);
                 }
 
                 nSampleCount++;
-                double dfDelta = dfValue - dfMean;
+                const double dfDelta = dfValue - dfMean;
                 dfMean += dfDelta / nSampleCount;
                 dfM2 += dfDelta * (dfValue - dfMean);
             }
@@ -3763,7 +4902,7 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
         CPLFree( pData );
     }
 
-    else    // No arbitrary overviews
+    else  // No arbitrary overviews.
     {
         if( !InitBlockInfo() )
             return CE_Failure;
@@ -3772,123 +4911,263 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 /*      Figure out the ratio of blocks we will read to get an           */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
-        int nSampleRate;
+        int nSampleRate = 1;
         if ( bApproxOK )
         {
-            nSampleRate =
-                (int)MAX( 1, sqrt((double)nBlocksPerRow * nBlocksPerColumn) );
+            nSampleRate = static_cast<int>(
+                std::max(1.0,
+                         sqrt(static_cast<double>(nBlocksPerRow) *
+                              nBlocksPerColumn)));
             // We want to avoid probing only the first column of blocks for
             // a square shaped raster, because it is not unlikely that it may
             // be padding only (#6378)
             if( nSampleRate == nBlocksPerRow && nBlocksPerRow > 1 )
               nSampleRate += 1;
         }
-        else
-            nSampleRate = 1;
+
+#ifdef CPL_HAS_GINT64
+        // Particular case for GDT_Byte that only use integral types for all
+        // intermediate computations. Only possible if the number of pixels
+        // explored is lower than GUINTBIG_MAX / (255*255), so that nSumSquare
+        // can fit on a uint64. Should be 99.99999% of cases.
+        // For GUInt16, this limits to raster of 4 giga pixels
+        if( (eDataType == GDT_Byte && !bSignedByte &&
+             static_cast<GUIntBig>(nBlocksPerRow)*nBlocksPerColumn/nSampleRate <
+                GUINTBIG_MAX / (255U * 255U) /
+                        static_cast<GUInt32>(nBlockXSize * nBlockYSize)) ||
+            (eDataType == GDT_UInt16 &&
+             static_cast<GUIntBig>(nBlocksPerRow)*nBlocksPerColumn/nSampleRate <
+                GUINTBIG_MAX / (65535U * 65535U) /
+                        static_cast<GUInt32>(nBlockXSize * nBlockYSize)) )
+        {
+            const GUInt32 nMaxValueType = (eDataType == GDT_Byte) ? 255 : 65535;
+            GUInt32 nMin = nMaxValueType;
+            GUInt32 nMax = 0;
+            GUIntBig nSum = 0;
+            GUIntBig nSumSquare = 0;
+            // If no valid nodata, map to invalid value (256 for Byte)
+            const GUInt32 nNoDataValue =
+                (bGotNoDataValue && dfNoDataValue >= 0 &&
+                 dfNoDataValue <= nMaxValueType &&
+                 fabs(dfNoDataValue -
+                      static_cast<GUInt32>(dfNoDataValue + 1e-10)) < 1e-10 ) ?
+                            static_cast<GUInt32>(dfNoDataValue + 1e-10) :
+                            nMaxValueType+1;
+
+            for( int iSampleBlock = 0;
+                iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
+                iSampleBlock += nSampleRate )
+            {
+                const int iYBlock = iSampleBlock / nBlocksPerRow;
+                const int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
+
+                GDALRasterBlock * const poBlock =
+                    GetLockedBlockRef( iXBlock, iYBlock );
+                if( poBlock == NULL )
+                    continue;
+
+                void* const pData = poBlock->GetDataRef();
+
+                int nXCheck = nBlockXSize;
+                if( (iXBlock+1) * nBlockXSize > GetXSize() )
+                    nXCheck = GetXSize() - iXBlock * nBlockXSize;
+
+                int nYCheck = nBlockYSize;
+                if( (iYBlock+1) * nBlockYSize > GetYSize() )
+                    nYCheck = GetYSize() - iYBlock * nBlockYSize;
+
+                if( eDataType == GDT_Byte )
+                {
+                    ComputeStatisticsInternal( nXCheck,
+                                               nBlockXSize,
+                                               nYCheck,
+                                               static_cast<const GByte*>(pData),
+                                               nNoDataValue <= nMaxValueType,
+                                               nNoDataValue,
+                                               nMin, nMax, nSum,
+                                               nSumSquare,
+                                               nSampleCount );
+                }
+                else
+                {
+                    ComputeStatisticsInternal( nXCheck,
+                                               nBlockXSize,
+                                               nYCheck,
+                                               static_cast<const GUInt16*>(pData),
+                                               nNoDataValue <= nMaxValueType,
+                                               nNoDataValue,
+                                               nMin, nMax, nSum,
+                                               nSumSquare,
+                                               nSampleCount );
+                }
+
+                poBlock->DropLock();
+
+                if ( !pfnProgress( iSampleBlock
+                        / static_cast<double>(nBlocksPerRow*nBlocksPerColumn),
+                        "Compute Statistics", pProgressData) )
+                {
+                    ReportError( CE_Failure, CPLE_UserInterrupt,
+                                 "User terminated" );
+                    return CE_Failure;
+                }
+            }
+
+            if( !pfnProgress( 1.0, "Compute Statistics", pProgressData ) )
+            {
+                ReportError( CE_Failure, CPLE_UserInterrupt,
+                             "User terminated" );
+                return CE_Failure;
+            }
+
+/* -------------------------------------------------------------------- */
+/*      Save computed information.                                      */
+/* -------------------------------------------------------------------- */
+            if( nSampleCount )
+                dfMean = static_cast<double>(nSum) / nSampleCount;
+
+            // To avoid potential precision issues when doing the difference,
+            // we need to do that computation on 128 bit rather than casting
+            // to double
+            const GDALUInt128 nTmpForStdDev(
+                    GDALUInt128::Mul(nSumSquare,nSampleCount) -
+                    GDALUInt128::Mul(nSum,nSum));
+            const double dfStdDev =
+                nSampleCount > 0 ?
+                    sqrt(static_cast<double>(nTmpForStdDev)) / nSampleCount :
+                    0.0;
+
+            if( nSampleCount > 0 )
+                SetStatistics( nMin, nMax, dfMean, dfStdDev );
+
+/* -------------------------------------------------------------------- */
+/*      Record results.                                                 */
+/* -------------------------------------------------------------------- */
+            if( pdfMin != NULL )
+                *pdfMin = nSampleCount ? nMin : 0;
+            if( pdfMax != NULL )
+                *pdfMax = nSampleCount ? nMax : 0;
+
+            if( pdfMean != NULL )
+                *pdfMean = dfMean;
+
+            if( pdfStdDev != NULL )
+                *pdfStdDev = dfStdDev;
+
+            if( nSampleCount > 0 )
+                return CE_None;
+
+            ReportError(
+                CE_Failure, CPLE_AppDefined,
+                "Failed to compute statistics, no valid pixels found in sampling." );
+            return CE_Failure;
+        }
+#endif
 
         for( int iSampleBlock = 0;
              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
              iSampleBlock += nSampleRate )
         {
-            int  iXBlock, iYBlock, nXCheck, nYCheck;
-            GDALRasterBlock *poBlock;
-            void* pData;
+            const int iYBlock = iSampleBlock / nBlocksPerRow;
+            const int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
 
-            iYBlock = iSampleBlock / nBlocksPerRow;
-            iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
-
-            poBlock = GetLockedBlockRef( iXBlock, iYBlock );
+            GDALRasterBlock * const poBlock = GetLockedBlockRef( iXBlock, iYBlock );
             if( poBlock == NULL )
                 continue;
 
-            pData = poBlock->GetDataRef();
+            void* const pData = poBlock->GetDataRef();
 
+            int nXCheck = nBlockXSize;
             if( (iXBlock+1) * nBlockXSize > GetXSize() )
                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
-            else
-                nXCheck = nBlockXSize;
 
+            int nYCheck = nBlockYSize;
             if( (iYBlock+1) * nBlockYSize > GetYSize() )
                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
-            else
-                nYCheck = nBlockYSize;
 
-            /* this isn't the fastest way to do this, but is easier for now */
+            // This isn't the fastest way to do this, but is easier for now.
             for( int iY = 0; iY < nYCheck; iY++ )
             {
                 for( int iX = 0; iX < nXCheck; iX++ )
                 {
-                    int    iOffset = iX + iY * nBlockXSize;
+                    const int iOffset = iX + iY * nBlockXSize;
                     double dfValue = 0.0;
 
                     switch( eDataType )
                     {
                       case GDT_Byte:
                       {
-                        if (bSignedByte)
-                            dfValue = ((signed char *)pData)[iOffset];
+                        if( bSignedByte )
+                            dfValue =
+                                static_cast<signed char *>(pData)[iOffset];
                         else
-                            dfValue = ((GByte *)pData)[iOffset];
+                            dfValue = static_cast<GByte *>(pData)[iOffset];
                         break;
                       }
                       case GDT_UInt16:
-                        dfValue = ((GUInt16 *)pData)[iOffset];
+                        dfValue = static_cast<GUInt16 *>(pData)[iOffset];
                         break;
                       case GDT_Int16:
-                        dfValue = ((GInt16 *)pData)[iOffset];
+                        dfValue = static_cast<GInt16 *>(pData)[iOffset];
                         break;
                       case GDT_UInt32:
-                        dfValue = ((GUInt32 *)pData)[iOffset];
+                        dfValue = static_cast<GUInt32 *>(pData)[iOffset];
                         break;
                       case GDT_Int32:
-                        dfValue = ((GInt32 *)pData)[iOffset];
+                        dfValue = static_cast<GInt32 *>(pData)[iOffset];
                         break;
                       case GDT_Float32:
-                        dfValue = ((float *)pData)[iOffset];
-                        if (CPLIsNan(dfValue))
+                      {
+                        const float fValue = static_cast<float *>(pData)[iOffset];
+                        if( CPLIsNan(fValue) ||
+                            (bGotFloatNoDataValue && fValue == fNoDataValue) )
                             continue;
+                        dfValue = fValue;
                         break;
+                      }
                       case GDT_Float64:
                         dfValue = ((double *)pData)[iOffset];
-                        if (CPLIsNan(dfValue))
+                        if( CPLIsNan(dfValue) )
                             continue;
                         break;
                       case GDT_CInt16:
-                        dfValue = ((GInt16 *)pData)[iOffset*2];
+                        dfValue = static_cast<GInt16 *>(pData)[iOffset*2];
                         break;
                       case GDT_CInt32:
-                        dfValue = ((GInt32 *)pData)[iOffset*2];
+                        dfValue = static_cast<GInt32 *>(pData)[iOffset*2];
                         break;
                       case GDT_CFloat32:
-                        dfValue = ((float *)pData)[iOffset*2];
+                        dfValue = static_cast<float *>(pData)[iOffset*2];
                         if( CPLIsNan(dfValue) )
                             continue;
                         break;
                       case GDT_CFloat64:
-                        dfValue = ((double *)pData)[iOffset*2];
+                        dfValue = static_cast<double *>(pData)[iOffset*2];
                         if( CPLIsNan(dfValue) )
                             continue;
                         break;
                       default:
-                        CPLAssert( FALSE );
+                        CPLAssert( false );
                     }
 
-                    if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
+                    if( bGotNoDataValue &&
+                        ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                         continue;
 
                     if( bFirstValue )
                     {
-                        dfMin = dfMax = dfValue;
+                        dfMin = dfValue;
+                        dfMax = dfValue;
                         bFirstValue = false;
                     }
                     else
                     {
-                        dfMin = MIN(dfMin,dfValue);
-                        dfMax = MAX(dfMax,dfValue);
+                        dfMin = std::min(dfMin, dfValue);
+                        dfMax = std::max(dfMax, dfValue);
                     }
 
                     nSampleCount++;
-                    double dfDelta = dfValue - dfMean;
+                    const double dfDelta = dfValue - dfMean;
                     dfMean += dfDelta / nSampleCount;
                     dfM2 += dfDelta * (dfValue - dfMean);
                 }
@@ -3896,9 +5175,10 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 
             poBlock->DropLock();
 
-            if ( !pfnProgress(iSampleBlock
-                              / ((double)(nBlocksPerRow*nBlocksPerColumn)),
-                              "Compute Statistics", pProgressData) )
+            if ( !pfnProgress(
+                     iSampleBlock
+                         / static_cast<double>(nBlocksPerRow*nBlocksPerColumn),
+                     "Compute Statistics", pProgressData) )
             {
                 ReportError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
                 return CE_Failure;
@@ -3915,7 +5195,8 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 /* -------------------------------------------------------------------- */
 /*      Save computed information.                                      */
 /* -------------------------------------------------------------------- */
-    const double dfStdDev = (nSampleCount > 0) ? sqrt(dfM2 / nSampleCount) : 0.0;
+    const double dfStdDev =
+        nSampleCount > 0 ? sqrt(dfM2 / nSampleCount) : 0.0;
 
     if( nSampleCount > 0 )
         SetStatistics( dfMin, dfMax, dfMean, dfStdDev );
@@ -3936,12 +5217,11 @@ GDALRasterBand::ComputeStatistics( int bApproxOK,
 
     if( nSampleCount > 0 )
         return CE_None;
-    else
-    {
-        ReportError( CE_Failure, CPLE_AppDefined,
+
+    ReportError(
+        CE_Failure, CPLE_AppDefined,
         "Failed to compute statistics, no valid pixels found in sampling." );
-        return CE_Failure;
-    }
+    return CE_Failure;
 }
 
 /************************************************************************/
@@ -4064,19 +5344,19 @@ CPLErr CPL_STDCALL GDALSetRasterStatistics(
  * @return CE_None on success or CE_Failure on failure.
  */
 
-
 CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
-                                            double adfMinMax[2] )
+                                            double* adfMinMax )
 {
-    double  dfMin = 0.0;
-    double  dfMax = 0.0;
+    double dfMin = 0.0;
+    double dfMax = 0.0;
 
 /* -------------------------------------------------------------------- */
 /*      Does the driver already know the min/max?                       */
 /* -------------------------------------------------------------------- */
     if( bApproxOK )
     {
-        int          bSuccessMin, bSuccessMax;
+        int bSuccessMin = FALSE;
+        int bSuccessMax = FALSE;
 
         dfMin = GetMinimum( &bSuccessMin );
         dfMax = GetMaximum( &bSuccessMax );
@@ -4092,6 +5372,7 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 /* -------------------------------------------------------------------- */
 /*      If we have overview bands, use them for min/max.                */
 /* -------------------------------------------------------------------- */
+    // cppcheck-suppress knownConditionTrueFalse
     if ( bApproxOK && GetOverviewCount() > 0 && !HasArbitraryOverviews() )
     {
         GDALRasterBand *poBand =
@@ -4104,29 +5385,40 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 /* -------------------------------------------------------------------- */
 /*      Read actual data and compute minimum and maximum.               */
 /* -------------------------------------------------------------------- */
-    int bGotNoDataValue;
-    bool bFirstValue = true;
-
+    int bGotNoDataValue = FALSE;
     const double dfNoDataValue = GetNoDataValue( &bGotNoDataValue );
     bGotNoDataValue = bGotNoDataValue && !CPLIsNan(dfNoDataValue);
+    bool bGotFloatNoDataValue = false;
+    float fNoDataValue = 0.0f;
+    if( eDataType == GDT_Float32 && bGotNoDataValue &&
+        (fabs(dfNoDataValue) <= std::numeric_limits<float>::max() ||
+         CPLIsInf(dfNoDataValue)) )
+    {
+        fNoDataValue = static_cast<float>(dfNoDataValue);
+        bGotFloatNoDataValue = true;
+        bGotNoDataValue = false;
+    }
 
     const char* pszPixelType = GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
-    int bSignedByte = (pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE"));
+    const bool bSignedByte =
+        pszPixelType != NULL && EQUAL(pszPixelType, "SIGNEDBYTE");
 
     GDALRasterIOExtraArg sExtraArg;
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
+    bool bFirstValue = true;
     if ( bApproxOK && HasArbitraryOverviews() )
     {
 /* -------------------------------------------------------------------- */
 /*      Figure out how much the image should be reduced to get an       */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
-        void    *pData;
-        int     nXReduced, nYReduced;
         double  dfReduction = sqrt(
-            (double)nRasterXSize * nRasterYSize / GDALSTAT_APPROX_NUMSAMPLES );
+            static_cast<double>(nRasterXSize) * nRasterYSize /
+            GDALSTAT_APPROX_NUMSAMPLES );
 
+        int nXReduced = nRasterXSize;
+        int nYReduced = nRasterYSize;
         if ( dfReduction > 1.0 )
         {
             nXReduced = (int)( nRasterXSize / dfReduction );
@@ -4138,18 +5430,14 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
             if ( nYReduced == 0 )
                 nYReduced = 1;
         }
-        else
-        {
-            nXReduced = nRasterXSize;
-            nYReduced = nRasterYSize;
-        }
 
-        pData =
+        void * const pData =
             CPLMalloc(
                 GDALGetDataTypeSizeBytes(eDataType) * nXReduced * nYReduced );
 
-        CPLErr eErr = IRasterIO( GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
-                   nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
+        const CPLErr eErr = IRasterIO(
+            GF_Read, 0, 0, nRasterXSize, nRasterYSize, pData,
+            nXReduced, nYReduced, eDataType, 0, 0, &sExtraArg );
         if ( eErr != CE_None )
         {
             CPLFree(pData);
@@ -4161,59 +5449,63 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
         {
             for( int iX = 0; iX < nXReduced; iX++ )
             {
-                int    iOffset = iX + iY * nXReduced;
+                const int iOffset = iX + iY * nXReduced;
                 double dfValue = 0.0;
 
                 switch( eDataType )
                 {
                   case GDT_Byte:
                   {
-                    if (bSignedByte)
-                        dfValue = ((signed char *)pData)[iOffset];
+                    if( bSignedByte )
+                        dfValue = static_cast<signed char *>(pData)[iOffset];
                     else
-                        dfValue = ((GByte *)pData)[iOffset];
+                        dfValue = static_cast<GByte *>(pData)[iOffset];
                     break;
                   }
                   case GDT_UInt16:
-                    dfValue = ((GUInt16 *)pData)[iOffset];
+                    dfValue = static_cast<GUInt16 *>(pData)[iOffset];
                     break;
                   case GDT_Int16:
-                    dfValue = ((GInt16 *)pData)[iOffset];
+                    dfValue = static_cast<GInt16 *>(pData)[iOffset];
                     break;
                   case GDT_UInt32:
-                    dfValue = ((GUInt32 *)pData)[iOffset];
+                    dfValue = static_cast<GUInt32 *>(pData)[iOffset];
                     break;
                   case GDT_Int32:
-                    dfValue = ((GInt32 *)pData)[iOffset];
+                    dfValue = static_cast<GInt32 *>(pData)[iOffset];
                     break;
                   case GDT_Float32:
-                    dfValue = ((float *)pData)[iOffset];
-                    if (CPLIsNan(dfValue))
+                  {
+                    const float fValue = static_cast<float *>(pData)[iOffset];
+                    if( CPLIsNan(fValue) ||
+                        (bGotFloatNoDataValue && fValue == fNoDataValue) )
                         continue;
+                    dfValue = fValue;
                     break;
+                  }
                   case GDT_Float64:
-                    dfValue = ((double *)pData)[iOffset];
-                    if (CPLIsNan(dfValue))
+                    dfValue = static_cast<double *>(pData)[iOffset];
+                    if( CPLIsNan(dfValue) )
                         continue;
                     break;
                   case GDT_CInt16:
-                    dfValue = ((GInt16 *)pData)[iOffset*2];
+                    dfValue = static_cast<GInt16 *>(pData)[iOffset*2];
                     break;
                   case GDT_CInt32:
-                    dfValue = ((GInt32 *)pData)[iOffset*2];
+                    dfValue = static_cast<GInt32 *>(pData)[iOffset*2];
                     break;
                   case GDT_CFloat32:
-                    dfValue = ((float *)pData)[iOffset*2];
+                    dfValue = static_cast<float *>(pData)[iOffset*2];
                     if( CPLIsNan(dfValue) )
                         continue;
                     break;
                   case GDT_CFloat64:
-                    dfValue = ((double *)pData)[iOffset*2];
+                    dfValue = static_cast<double *>(pData)[iOffset*2];
                     if( CPLIsNan(dfValue) )
                         continue;
                     break;
                   default:
-                    CPLAssert( FALSE );
+                    CPLAssert( false );
                 }
 
                 if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
@@ -4221,13 +5513,14 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 
                 if( bFirstValue )
                 {
-                    dfMin = dfMax = dfValue;
+                    dfMin = dfValue;
+                    dfMax = dfValue;
                     bFirstValue = false;
                 }
                 else
                 {
-                    dfMin = MIN(dfMin,dfValue);
-                    dfMax = MAX(dfMax,dfValue);
+                    dfMin = std::min(dfMin, dfValue);
+                    dfMax = std::max(dfMax, dfValue);
                 }
             }
         }
@@ -4235,7 +5528,7 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
         CPLFree( pData );
     }
 
-    else    // No arbitrary overviews
+    else  // No arbitrary overviews
     {
         if( !InitBlockInfo() )
             return CE_Failure;
@@ -4244,51 +5537,48 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 /*      Figure out the ratio of blocks we will read to get an           */
 /*      approximate value.                                              */
 /* -------------------------------------------------------------------- */
-        int nSampleRate;
+        int nSampleRate = 1;
 
         if ( bApproxOK )
         {
-            nSampleRate =
-                (int) MAX(1,sqrt((double) nBlocksPerRow * nBlocksPerColumn));
+            nSampleRate = static_cast<int>(
+                std::max(1.0,
+                         sqrt(static_cast<double>(nBlocksPerRow) *
+                              nBlocksPerColumn)));
             // We want to avoid probing only the first column of blocks for
             // a square shaped raster, because it is not unlikely that it may
-            // be padding only (#6378)
+            // be padding only (#6378).
             if( nSampleRate == nBlocksPerRow && nBlocksPerRow > 1 )
               nSampleRate += 1;
         }
-        else
-            nSampleRate = 1;
 
         for( int iSampleBlock = 0;
              iSampleBlock < nBlocksPerRow * nBlocksPerColumn;
              iSampleBlock += nSampleRate )
         {
-            int iYBlock = iSampleBlock / nBlocksPerRow;
-            int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
+            const int iYBlock = iSampleBlock / nBlocksPerRow;
+            const int iXBlock = iSampleBlock - nBlocksPerRow * iYBlock;
 
             GDALRasterBlock *poBlock = GetLockedBlockRef( iXBlock, iYBlock );
             if( poBlock == NULL )
                 continue;
 
-            void *pData = poBlock->GetDataRef();
+            void * const pData = poBlock->GetDataRef();
 
-            int nXCheck, nYCheck;
+            int nXCheck = nBlockXSize;
             if( (iXBlock+1) * nBlockXSize > GetXSize() )
                 nXCheck = GetXSize() - iXBlock * nBlockXSize;
-            else
-                nXCheck = nBlockXSize;
 
+            int nYCheck = nBlockYSize;
             if( (iYBlock+1) * nBlockYSize > GetYSize() )
                 nYCheck = GetYSize() - iYBlock * nBlockYSize;
-            else
-                nYCheck = nBlockYSize;
 
-            /* this isn't the fastest way to do this, but is easier for now */
+            // This isn't the fastest way to do this, but is easier for now.
             for( int iY = 0; iY < nYCheck; iY++ )
             {
                 for( int iX = 0; iX < nXCheck; iX++ )
                 {
-                    int    iOffset = iX + iY * nBlockXSize;
+                    const int iOffset = iX + iY * nBlockXSize;
                     double dfValue = 0.0;
 
                     switch( eDataType )
@@ -4296,65 +5586,71 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
                       case GDT_Byte:
                       {
                         if (bSignedByte)
-                            dfValue = ((signed char *) pData)[iOffset];
+                            dfValue = static_cast<signed char *>(pData)[iOffset];
                         else
-                            dfValue = ((GByte *) pData)[iOffset];
+                            dfValue = static_cast<GByte *>(pData)[iOffset];
                         break;
                       }
                       case GDT_UInt16:
-                        dfValue = ((GUInt16 *) pData)[iOffset];
+                        dfValue = static_cast<GUInt16 *>(pData)[iOffset];
                         break;
                       case GDT_Int16:
-                        dfValue = ((GInt16 *) pData)[iOffset];
+                        dfValue = static_cast<GInt16 *>(pData)[iOffset];
                         break;
                       case GDT_UInt32:
-                        dfValue = ((GUInt32 *) pData)[iOffset];
+                        dfValue = static_cast<GUInt32 *>(pData)[iOffset];
                         break;
                       case GDT_Int32:
-                        dfValue = ((GInt32 *) pData)[iOffset];
+                        dfValue = static_cast<GInt32 *>(pData)[iOffset];
                         break;
                       case GDT_Float32:
-                        dfValue = ((float *) pData)[iOffset];
-                        if( CPLIsNan(dfValue) )
-                            continue;
-                        break;
+                      {
+                          const float fValue = static_cast<float *>(pData)[iOffset];
+                          if( CPLIsNan(fValue) ||
+                              (bGotFloatNoDataValue && fValue == fNoDataValue) )
+                              continue;
+                          dfValue = fValue;
+                          break;
+                      }
                       case GDT_Float64:
-                        dfValue = ((double *) pData)[iOffset];
+                        dfValue = static_cast<double *>(pData)[iOffset];
                         if( CPLIsNan(dfValue) )
                             continue;
                         break;
                       case GDT_CInt16:
-                        dfValue = ((GInt16 *) pData)[iOffset*2];
+                        dfValue = static_cast<GInt16 *>(pData)[iOffset*2];
                         break;
                       case GDT_CInt32:
-                        dfValue = ((GInt32 *) pData)[iOffset*2];
+                        dfValue = static_cast<GInt32 *>(pData)[iOffset*2];
                         break;
                       case GDT_CFloat32:
-                        dfValue = ((float *) pData)[iOffset*2];
+                        dfValue = static_cast<float *>(pData)[iOffset*2];
                         if( CPLIsNan(dfValue) )
                             continue;
                         break;
                       case GDT_CFloat64:
-                        dfValue = ((double *) pData)[iOffset*2];
+                        dfValue = static_cast<double *>(pData)[iOffset*2];
                         if( CPLIsNan(dfValue) )
                             continue;
                         break;
                       default:
-                        CPLAssert( FALSE );
+                        CPLAssert( false );
                     }
 
-                    if( bGotNoDataValue && ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
+                    if( bGotNoDataValue &&
+                        ARE_REAL_EQUAL(dfValue, dfNoDataValue) )
                         continue;
 
                     if( bFirstValue )
                     {
-                        dfMin = dfMax = dfValue;
+                        dfMin = dfValue;
+                        dfMax = dfValue;
                         bFirstValue = false;
                     }
                     else
                     {
-                        dfMin = MIN(dfMin,dfValue);
-                        dfMax = MAX(dfMax,dfValue);
+                        dfMin = std::min(dfMin, dfValue);
+                        dfMax = std::max(dfMax, dfValue);
                     }
                 }
             }
@@ -4368,14 +5664,13 @@ CPLErr GDALRasterBand::ComputeRasterMinMax( int bApproxOK,
 
     if (bFirstValue)
     {
-        ReportError( CE_Failure, CPLE_AppDefined,
+        ReportError(
+            CE_Failure, CPLE_AppDefined,
             "Failed to compute min/max, no valid pixels found in sampling." );
         return CE_Failure;
     }
-    else
-    {
-        return CE_None;
-    }
+
+    return CE_None;
 }
 
 /************************************************************************/
@@ -4410,15 +5705,15 @@ GDALComputeRasterMinMax( GDALRasterBandH hBand, int bApproxOK,
  * This method is the same as the C function GDALSetDefaultHistogram() and
  * GDALSetDefaultHistogramEx()
  */
-CPLErr GDALRasterBand::SetDefaultHistogram( CPL_UNUSED double dfMin,
-                                            CPL_UNUSED double dfMax,
-                                            CPL_UNUSED int nBuckets,
-                                            CPL_UNUSED GUIntBig *panHistogram )
+CPLErr GDALRasterBand::SetDefaultHistogram( double /* dfMin */,
+                                            double /* dfMax */,
+                                            int /* nBuckets */,
+                                            GUIntBig * /* panHistogram */)
 
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
-                  "SetDefaultHistogram() not implemented for this format." );
+                     "SetDefaultHistogram() not implemented for this format." );
 
     return CE_Failure;
 }
@@ -4446,20 +5741,23 @@ CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand,
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
 
-    GUIntBig* panHistogramTemp = (GUIntBig*) VSIMalloc2(sizeof(GUIntBig), nBuckets);
+    GUIntBig* panHistogramTemp = static_cast<GUIntBig *>(
+        VSIMalloc2(sizeof(GUIntBig), nBuckets) );
     if( panHistogramTemp == NULL )
     {
-        poBand->ReportError( CE_Failure, CPLE_OutOfMemory,
-                    "Out of memory in GDALSetDefaultHistogram()." );
+        poBand->ReportError(
+            CE_Failure, CPLE_OutOfMemory,
+            "Out of memory in GDALSetDefaultHistogram()." );
         return CE_Failure;
     }
 
-    for(int i=0;i<nBuckets;i++)
+    for( int i = 0; i < nBuckets; ++i )
     {
         panHistogramTemp[i] = (GUIntBig)panHistogram[i];
     }
 
-    CPLErr eErr = poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogramTemp );
+    const CPLErr eErr =
+        poBand->SetDefaultHistogram( dfMin, dfMax, nBuckets, panHistogramTemp );
 
     CPLFree(panHistogramTemp);
 
@@ -4479,8 +5777,9 @@ CPLErr CPL_STDCALL GDALSetDefaultHistogram( GDALRasterBandH hBand,
  */
 
 CPLErr CPL_STDCALL GDALSetDefaultHistogramEx( GDALRasterBandH hBand,
-                                            double dfMin, double dfMax,
-                                            int nBuckets, GUIntBig *panHistogram )
+                                              double dfMin, double dfMax,
+                                              int nBuckets,
+                                              GUIntBig *panHistogram )
 
 {
     VALIDATE_POINTER1( hBand, "GDALSetDefaultHistogramEx", CE_Failure );
@@ -4535,6 +5834,7 @@ GDALRasterAttributeTableH CPL_STDCALL GDALGetDefaultRAT( GDALRasterBandH hBand)
 /************************************************************************/
 
 /**
+ * \fn GDALRasterBand::SetDefaultRAT(const GDALRasterAttributeTable*)
  * \brief Set default Raster Attribute Table.
  *
  * Associates a default RAT with the band.  If not implemented for the
@@ -4549,11 +5849,15 @@ GDALRasterAttributeTableH CPL_STDCALL GDALGetDefaultRAT( GDALRasterBandH hBand)
  * failing.
  */
 
-CPLErr GDALRasterBand::SetDefaultRAT( CPL_UNUSED const GDALRasterAttributeTable *poRAT )
+/**/
+/**/
+
+CPLErr GDALRasterBand::SetDefaultRAT(
+    const GDALRasterAttributeTable * /* poRAT */ )
 {
     if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
         ReportError( CE_Failure, CPLE_NotSupported,
-                  "SetDefaultRAT() not implemented for this format." );
+                     "SetDefaultRAT() not implemented for this format." );
 
     return CE_Failure;
 }
@@ -4606,8 +5910,20 @@ CPLErr CPL_STDCALL GDALSetDefaultRAT( GDALRasterBandH hBand,
  *     The null flags will return GMF_ALL_VALID.</li>
  * </ul>
  *
- * Note that the GetMaskBand() should always return a GDALRasterBand mask, even if it is only
- * an all 255 mask with the flags indicating GMF_ALL_VALID.
+ * Note that the GetMaskBand() should always return a GDALRasterBand mask, even
+ * if it is only an all 255 mask with the flags indicating GMF_ALL_VALID.
+ *
+ * For an external .msk file to be recognized by GDAL, it must be a valid GDAL
+ * dataset, with the same name as the main dataset and suffixed with .msk,
+ * with either one band (in the GMF_PER_DATASET case), or as many bands as the
+ * main dataset.
+ * It must have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
+ * level, where xx matches the band number of a band of the main dataset. The
+ * value of those items is a combination of the flags GMF_ALL_VALID,
+ * GMF_PER_DATASET, GMF_ALPHA and GMF_NODATA. If a metadata item is missing for
+ * a band, then the other rules explained above will be used to generate a
+ * on-the-fly mask band.
+ * \see CreateMaskBand() for the characteristics of .msk files created by GDAL.
  *
  * This method is the same as the C function GDALGetMaskBand().
  *
@@ -4640,33 +5956,33 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
 /* -------------------------------------------------------------------- */
 /*      Check for NODATA_VALUES metadata.                               */
 /* -------------------------------------------------------------------- */
-    if (poDS != NULL)
+    if( poDS != NULL )
     {
         const char* pszNoDataValues = poDS->GetMetadataItem("NODATA_VALUES");
-        if (pszNoDataValues != NULL)
+        if( pszNoDataValues != NULL )
         {
             char** papszNoDataValues
                 = CSLTokenizeStringComplex(pszNoDataValues, " ", FALSE, FALSE);
 
-            /* Make sure we have as many values as bands */
+            // Make sure we have as many values as bands.
             if (CSLCount(papszNoDataValues) == poDS->GetRasterCount()
                 && poDS->GetRasterCount() != 0)
             {
                 // Make sure that all bands have the same data type
                 // This is clearly not a fundamental condition, just a
                 // condition to make implementation easier.
-                int i;
                 GDALDataType eDT = GDT_Unknown;
-                for(i=0;i<poDS->GetRasterCount();i++)
+                int i = 0;  // Used after for.
+                for( ; i < poDS->GetRasterCount(); ++i )
                 {
-                    if (i == 0)
+                    if( i == 0 )
                         eDT = poDS->GetRasterBand(1)->GetRasterDataType();
                     else if (eDT != poDS->GetRasterBand(i + 1)->GetRasterDataType())
                     {
                         break;
                     }
                 }
-                if (i == poDS->GetRasterCount())
+                if( i == poDS->GetRasterCount() )
                 {
                     nMaskFlags = GMF_NODATA | GMF_PER_DATASET;
                     try
@@ -4684,17 +6000,19 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
                 }
                 else
                 {
-                    ReportError(CE_Warning, CPLE_AppDefined,
-                                "All bands should have the same type in "
-                                "order the NODATA_VALUES metadata item "
-                                "to be used as a mask.");
+                    ReportError( CE_Warning, CPLE_AppDefined,
+                                 "All bands should have the same type in "
+                                 "order the NODATA_VALUES metadata item "
+                                 "to be used as a mask." );
                 }
             }
             else
             {
-                ReportError(CE_Warning, CPLE_AppDefined,
-                        "NODATA_VALUES metadata item doesn't have the same number of values as the number of bands.\n"
-                        "Ignoring it for mask.");
+                ReportError(
+                    CE_Warning, CPLE_AppDefined,
+                    "NODATA_VALUES metadata item doesn't have the same number "
+                    "of values as the number of bands.  "
+                    "Ignoring it for mask.");
             }
 
             CSLDestroy(papszNoDataValues);
@@ -4704,8 +6022,7 @@ GDALRasterBand *GDALRasterBand::GetMaskBand()
 /* -------------------------------------------------------------------- */
 /*      Check for nodata case.                                          */
 /* -------------------------------------------------------------------- */
-    int bHaveNoData;
-
+    int bHaveNoData = FALSE;
     GetNoDataValue( &bHaveNoData );
 
     if( bHaveNoData )
@@ -4843,6 +6160,18 @@ GDALRasterBandH CPL_STDCALL GDALGetMaskBand( GDALRasterBandH hBand )
  *     The null flags will return GMF_ALL_VALID.</li>
  * </ul>
  *
+ * For an external .msk file to be recognized by GDAL, it must be a valid GDAL
+ * dataset, with the same name as the main dataset and suffixed with .msk,
+ * with either one band (in the GMF_PER_DATASET case), or as many bands as the
+ * main dataset.
+ * It must have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
+ * level, where xx matches the band number of a band of the main dataset. The
+ * value of those items is a combination of the flags GMF_ALL_VALID,
+ * GMF_PER_DATASET, GMF_ALPHA and GMF_NODATA. If a metadata item is missing for
+ * a band, then the other rules explained above will be used to generate a
+ * on-the-fly mask band.
+ * \see CreateMaskBand() for the characteristics of .msk files created by GDAL.
+ *
  * This method is the same as the C function GDALGetMaskFlags().
  *
  * @since GDAL 1.5.0
@@ -4887,6 +6216,7 @@ int CPL_STDCALL GDALGetMaskFlags( GDALRasterBandH hBand )
 /*                         InvalidateMaskBand()                         */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 void GDALRasterBand::InvalidateMaskBand()
 {
     if (bOwnMask)
@@ -4895,6 +6225,7 @@ void GDALRasterBand::InvalidateMaskBand()
     nMaskFlags = 0;
     poMask = NULL;
 }
+//! @endcond
 
 /************************************************************************/
 /*                           CreateMaskBand()                           */
@@ -4910,6 +6241,9 @@ void GDALRasterBand::InvalidateMaskBand()
  * as many bands as the original image (or just one for GMF_PER_DATASET).
  * The mask images will be deflate compressed tiled images with the same
  * block size as the original image if possible.
+ * It will have INTERNAL_MASK_FLAGS_xx metadata items set at the dataset
+ * level, where xx matches the band number of a band of the main dataset. The
+ * value of those items will be the one of the nFlagsIn parameter.
  *
  * Note that if you got a mask band with a previous call to GetMaskBand(),
  * it might be invalidated by CreateMaskBand(). So you have to call GetMaskBand()
@@ -4919,9 +6253,12 @@ void GDALRasterBand::InvalidateMaskBand()
  *
  * @since GDAL 1.5.0
  *
+ * @param nFlagsIn 0 or combination of GMF_PER_DATASET / GMF_ALPHA.
+ *
  * @return CE_None on success or CE_Failure on an error.
  *
  * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
+ * @see GDALDataset::CreateMaskBand()
  *
  */
 
@@ -4930,7 +6267,7 @@ CPLErr GDALRasterBand::CreateMaskBand( int nFlagsIn )
 {
     if( poDS != NULL && poDS->oOvManager.IsInitialized() )
     {
-        CPLErr eErr = poDS->oOvManager.CreateMaskBand( nFlagsIn, nBand );
+        const CPLErr eErr = poDS->oOvManager.CreateMaskBand( nFlagsIn, nBand );
         if (eErr != CE_None)
             return eErr;
 
@@ -4940,7 +6277,7 @@ CPLErr GDALRasterBand::CreateMaskBand( int nFlagsIn )
     }
 
     ReportError( CE_Failure, CPLE_NotSupported,
-              "CreateMaskBand() not supported for this band." );
+                 "CreateMaskBand() not supported for this band." );
 
     return CE_Failure;
 }
@@ -4995,32 +6332,37 @@ CPLErr CPL_STDCALL GDALCreateMaskBand( GDALRasterBandH hBand, int nFlags )
  *         The table must be freed with CPLFree if NULL was passed for pTranslationTable.
  */
 
-unsigned char* GDALRasterBand::GetIndexColorTranslationTo(GDALRasterBand* poReferenceBand,
-                                                          unsigned char* pTranslationTable,
-                                                          int* pApproximateMatching )
+unsigned char* GDALRasterBand::GetIndexColorTranslationTo(
+    GDALRasterBand* poReferenceBand,
+    unsigned char* pTranslationTable,
+    int* pApproximateMatching )
 {
     if (poReferenceBand == NULL)
         return NULL;
 
+    // cppcheck-suppress knownConditionTrueFalse
     if (poReferenceBand->GetColorInterpretation() == GCI_PaletteIndex &&
+        // cppcheck-suppress knownConditionTrueFalse
         GetColorInterpretation() == GCI_PaletteIndex &&
         poReferenceBand->GetRasterDataType() == GDT_Byte &&
         GetRasterDataType() == GDT_Byte)
     {
-        GDALColorTable* srcColorTable = GetColorTable();
+        const GDALColorTable* srcColorTable = GetColorTable();
         GDALColorTable* destColorTable = poReferenceBand->GetColorTable();
         if (srcColorTable != NULL && destColorTable != NULL)
         {
-            int nEntries = srcColorTable->GetColorEntryCount();
-            int nRefEntries = destColorTable->GetColorEntryCount();
-            int bHasNoDataValueSrc;
+            const int nEntries = srcColorTable->GetColorEntryCount();
+            const int nRefEntries = destColorTable->GetColorEntryCount();
+            int bHasNoDataValueSrc = FALSE;
             double dfNoDataValueSrc = GetNoDataValue(&bHasNoDataValueSrc);
-            int noDataValueSrc = (bHasNoDataValueSrc) ? (int)dfNoDataValueSrc : 0;
-            int bHasNoDataValueRef;
-            double dfNoDataValueRef = poReferenceBand->GetNoDataValue(&bHasNoDataValueRef);
-            int noDataValueRef = (bHasNoDataValueRef) ? (int)dfNoDataValueRef : 0;
-            int samePalette;
-            int i, j;
+            const int noDataValueSrc =
+                bHasNoDataValueSrc ? static_cast<int>(dfNoDataValueSrc) : 0;
+            int bHasNoDataValueRef = FALSE;
+            const double dfNoDataValueRef =
+                poReferenceBand->GetNoDataValue(&bHasNoDataValueRef);
+            const int noDataValueRef =
+                bHasNoDataValueRef ? static_cast<int>(dfNoDataValueRef) : 0;
+            bool samePalette = false;
 
             if (pApproximateMatching)
                 *pApproximateMatching = FALSE;
@@ -5028,8 +6370,8 @@ unsigned char* GDALRasterBand::GetIndexColorTranslationTo(GDALRasterBand* poRefe
             if (nEntries == nRefEntries && bHasNoDataValueSrc == bHasNoDataValueRef &&
                 (bHasNoDataValueSrc == FALSE || noDataValueSrc == noDataValueRef))
             {
-                samePalette = TRUE;
-                for(i=0;i<nEntries;i++)
+                samePalette = true;
+                for( int i = 0; i < nEntries; ++i )
                 {
                     if (noDataValueSrc == i)
                         continue;
@@ -5039,62 +6381,74 @@ unsigned char* GDALRasterBand::GetIndexColorTranslationTo(GDALRasterBand* poRefe
                         entry->c2 != entryRef->c2 ||
                         entry->c3 != entryRef->c3)
                     {
-                        samePalette = FALSE;
+                        samePalette = false;
                     }
                 }
             }
-            else
-            {
-                samePalette = FALSE;
-            }
-            if (samePalette == FALSE)
+
+            if( !samePalette )
             {
+                // TODO(schwehr): Make 256 a constant and explain it.
                 if (pTranslationTable == NULL)
-                    pTranslationTable = (unsigned char*)CPLMalloc(256);
+                    pTranslationTable =
+                        static_cast<unsigned char *>( CPLMalloc(256) );
 
-                /* Trying to remap the product palette on the subdataset palette */
-                for(i=0;i<nEntries;i++)
+                // Trying to remap the product palette on the subdataset
+                // palette.
+                for( int i = 0; i < nEntries; ++i )
                 {
-                    if (bHasNoDataValueSrc && bHasNoDataValueRef && noDataValueSrc == i)
+                    if( bHasNoDataValueSrc && bHasNoDataValueRef &&
+                        noDataValueSrc == i )
                         continue;
-                    const GDALColorEntry* entry = srcColorTable->GetColorEntry(i);
-                    for(j=0;j<nRefEntries;j++)
+                    const GDALColorEntry* entry =
+                        srcColorTable->GetColorEntry(i);
+                    int j = 0;  // j used after for.
+                    for( j = 0; j < nRefEntries; ++j )
                     {
                         if (bHasNoDataValueRef && noDataValueRef == j)
                             continue;
-                        const GDALColorEntry* entryRef = destColorTable->GetColorEntry(j);
-                        if (entry->c1 == entryRef->c1 &&
+                        const GDALColorEntry* entryRef =
+                            destColorTable->GetColorEntry(j);
+                        if( entry->c1 == entryRef->c1 &&
                             entry->c2 == entryRef->c2 &&
-                            entry->c3 == entryRef->c3)
+                            entry->c3 == entryRef->c3 )
                         {
-                            pTranslationTable[i] = (unsigned char) j;
+                            pTranslationTable[i] =
+                                static_cast<unsigned char>(j);
                             break;
                         }
                     }
-                    if (j == nEntries)
+                    if( j == nEntries )
                     {
-                        /* No exact match. Looking for closest color now... */
+                        // No exact match. Looking for closest color now.
                         int best_j = 0;
                         int best_distance = 0;
-                        if (pApproximateMatching)
+                        if( pApproximateMatching )
                             *pApproximateMatching = TRUE;
-                        for(j=0;j<nRefEntries;j++)
+                        for( j = 0; j < nRefEntries; ++j )
                         {
-                            const GDALColorEntry* entryRef = destColorTable->GetColorEntry(j);
-                            int distance = (entry->c1 - entryRef->c1) * (entry->c1 - entryRef->c1) +
-                                           (entry->c2 - entryRef->c2) * (entry->c2 - entryRef->c2) +
-                                           (entry->c3 - entryRef->c3) * (entry->c3 - entryRef->c3);
-                            if (j == 0 || distance < best_distance)
+                            const GDALColorEntry* entryRef =
+                                destColorTable->GetColorEntry(j);
+                            int distance =
+                                (entry->c1 - entryRef->c1) *
+                                    (entry->c1 - entryRef->c1) +
+                                (entry->c2 - entryRef->c2) *
+                                    (entry->c2 - entryRef->c2) +
+                                (entry->c3 - entryRef->c3) *
+                                    (entry->c3 - entryRef->c3);
+                            if( j == 0 || distance < best_distance )
                             {
                                 best_j = j;
                                 best_distance = distance;
                             }
                         }
-                        pTranslationTable[i] = (unsigned char) best_j;
+                        pTranslationTable[i] =
+                            static_cast<unsigned char>(best_j);
                     }
                 }
-                if (bHasNoDataValueRef && bHasNoDataValueSrc)
-                    pTranslationTable[noDataValueSrc] = (unsigned char) noDataValueRef;
+                if( bHasNoDataValueRef && bHasNoDataValueSrc )
+                    pTranslationTable[noDataValueSrc] =
+                        static_cast<unsigned char>( noDataValueRef );
 
                 return pTranslationTable;
             }
@@ -5144,18 +6498,19 @@ void GDALRasterBand::SetFlushBlockErr( CPLErr eErr )
  * @since GDAL 1.9.0
  */
 
-void GDALRasterBand::ReportError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)
+void GDALRasterBand::ReportError( CPLErr eErrClass, CPLErrorNum err_no,
+                                  const char *fmt, ... )
 {
     va_list args;
 
     va_start(args, fmt);
 
-    char szNewFmt[256];
+    char szNewFmt[256] = { '\0' };
     const char* pszDSName = poDS ? poDS->GetDescription() : "";
-    if (strlen(fmt) + strlen(pszDSName) + 20 >= sizeof(szNewFmt) - 1)
+    if( strlen(fmt) + strlen(pszDSName) + 20 >= sizeof(szNewFmt) - 1 )
         pszDSName = CPLGetFilename(pszDSName);
-    if (pszDSName[0] != '\0' &&
-        strlen(fmt) + strlen(pszDSName) + 20 < sizeof(szNewFmt) - 1)
+    if( pszDSName[0] != '\0' &&
+        strlen(fmt) + strlen(pszDSName) + 20 < sizeof(szNewFmt) - 1 )
     {
         snprintf(szNewFmt, sizeof(szNewFmt), "%s, band %d: %s",
                  pszDSName, GetBand(), fmt);
@@ -5168,14 +6523,13 @@ void GDALRasterBand::ReportError(CPLErr eErrClass, CPLErrorNum err_no, const cha
     va_end(args);
 }
 
-
 /************************************************************************/
 /*                           GetVirtualMemAuto()                        */
 /************************************************************************/
 
 /** \brief Create a CPLVirtualMem object from a GDAL raster band object.
  *
- * Only supported on Linux for now.
+ * Only supported on Linux and Unix systems with mmap() for now.
  *
  * This method allows creating a virtual memory object for a GDALRasterBand,
  * that exposes the whole image data as a virtual array.
@@ -5218,6 +6572,9 @@ void GDALRasterBand::ReportError(CPLErr eErrClass, CPLErrorNum err_no, const cha
  * @param papszOptions NULL terminated list of options.
  *                     If a specialized implementation exists, defining USE_DEFAULT_IMPLEMENTATION=YES
  *                     will cause the default implementation to be used.
+ *                     On the contrary, starting with GDAL 2.2, defining USE_DEFAULT_IMPLEMENTATION=NO
+ *                     will prevent the default implementation from being used (thus only allowing
+ *                     efficient implementations to be used).
  *                     When requiring or falling back to the default implementation, the following
  *                     options are available : CACHE_SIZE (in bytes, defaults to 40 MB),
  *                     PAGE_SIZE_HINT (in bytes),
@@ -5234,19 +6591,28 @@ CPLVirtualMem  *GDALRasterBand::GetVirtualMemAuto( GDALRWFlag eRWFlag,
                                                    GIntBig *pnLineSpace,
                                                    char **papszOptions )
 {
+    const char* pszImpl = CSLFetchNameValueDef(
+            papszOptions, "USE_DEFAULT_IMPLEMENTATION", "AUTO");
+    if( EQUAL(pszImpl, "NO") || EQUAL(pszImpl, "OFF") ||
+        EQUAL(pszImpl, "0") || EQUAL(pszImpl, "FALSE") )
+    {
+        return NULL;
+    }
+
     const int nPixelSpace = GDALGetDataTypeSizeBytes(eDataType);
-    GIntBig nLineSpace = (GIntBig)nRasterXSize * nPixelSpace;
+    const GIntBig nLineSpace = static_cast<GIntBig>(nRasterXSize) * nPixelSpace;
     if( pnPixelSpace )
         *pnPixelSpace = nPixelSpace;
     if( pnLineSpace )
         *pnLineSpace = nLineSpace;
-    size_t nCacheSize = atoi(CSLFetchNameValueDef(papszOptions,
-                                            "CACHE_SIZE", "40000000"));
-    size_t nPageSizeHint = atoi(CSLFetchNameValueDef(papszOptions,
-                                            "PAGE_SIZE_HINT", "0"));
-    int bSingleThreadUsage = CPLTestBool(CSLFetchNameValueDef(papszOptions,
-                                            "SINGLE_THREAD", "FALSE"));
-    return GDALRasterBandGetVirtualMem( (GDALRasterBandH) this,
+    const size_t nCacheSize = atoi(
+        CSLFetchNameValueDef(papszOptions, "CACHE_SIZE", "40000000"));
+    const size_t nPageSizeHint = atoi(
+        CSLFetchNameValueDef(papszOptions, "PAGE_SIZE_HINT", "0") );
+    const bool bSingleThreadUsage =
+        CPLTestBool( CSLFetchNameValueDef( papszOptions,
+                                           "SINGLE_THREAD", "FALSE" ) );
+    return GDALRasterBandGetVirtualMem( /* (GDALRasterBandH) */ this,
                                         eRWFlag,
                                         0, 0, nRasterXSize, nRasterYSize,
                                         nRasterXSize, nRasterYSize,
@@ -5278,16 +6644,315 @@ CPLVirtualMem * GDALGetVirtualMemAuto( GDALRasterBandH hBand,
 
     GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
 
-    return poBand->GetVirtualMemAuto(eRWFlag, pnPixelSpace,
-                                     pnLineSpace, papszOptions);
+    return poBand->GetVirtualMemAuto( eRWFlag, pnPixelSpace,
+                                      pnLineSpace, papszOptions );
 }
 
+/************************************************************************/
+/*                        GDALGetDataCoverageStatus()                   */
+/************************************************************************/
 
+/**
+ * \brief Get the coverage status of a sub-window of the raster.
+ *
+ * Returns whether a sub-window of the raster contains only data, only empty
+ * blocks or a mix of both. This function can be used to determine quickly
+ * if it is worth issuing RasterIO / ReadBlock requests in datasets that may
+ * be sparse.
+ *
+ * Empty blocks are blocks that are generally not physically present in the
+ * file, and when read through GDAL, contain only pixels whose value is the
+ * nodata value when it is set, or whose value is 0 when the nodata value is
+ * not set.
+ *
+ * The query is done in an efficient way without reading the actual pixel
+ * values. If not possible, or not implemented at all by the driver,
+ * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | GDAL_DATA_COVERAGE_STATUS_DATA will
+ * be returned.
+ *
+ * The values that can be returned by the function are the following,
+ * potentially combined with the binary or operator :
+ * <ul>
+ * <li>GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED : the driver does not implement
+ * GetDataCoverageStatus(). This flag should be returned together with
+ * GDAL_DATA_COVERAGE_STATUS_DATA.</li>
+ * <li>GDAL_DATA_COVERAGE_STATUS_DATA: There is (potentially) data in the queried
+ * window.</li>
+ * <li>GDAL_DATA_COVERAGE_STATUS_EMPTY: There is nodata in the queried window.
+ * This is typically identified by the concept of missing block in formats that
+ * supports it.
+ * </li>
+ * </ul>
+ *
+ * Note that GDAL_DATA_COVERAGE_STATUS_DATA might have false positives and
+ * should be interpreted more as hint of potential presence of data. For example
+ * if a GeoTIFF file is created with blocks filled with zeroes (or set to the
+ * nodata value), instead of using the missing block mechanism,
+ * GDAL_DATA_COVERAGE_STATUS_DATA will be returned. On the contrary,
+ * GDAL_DATA_COVERAGE_STATUS_EMPTY should have no false positives.
+ *
+ * The nMaskFlagStop should be generally set to 0. It can be set to a
+ * binary-or'ed mask of the above mentioned values to enable a quick exiting of
+ * the function as soon as the computed mask matches the nMaskFlagStop. For
+ * example, you can issue a request on the whole raster with nMaskFlagStop =
+ * GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon as one missing block is encountered,
+ * the function will exit, so that you can potentially refine the requested area
+ * to find which particular region(s) have missing blocks.
+ *
+ * @see GDALRasterBand::GetDataCoverageStatus()
+ *
+ * @param hBand raster band
+ *
+ * @param nXOff The pixel offset to the top left corner of the region
+ * of the band to be queried. This would be zero to start from the left side.
+ *
+ * @param nYOff The line offset to the top left corner of the region
+ * of the band to be queried. This would be zero to start from the top.
+ *
+ * @param nXSize The width of the region of the band to be queried in pixels.
+ *
+ * @param nYSize The height of the region of the band to be queried in lines.
+ *
+ * @param nMaskFlagStop 0, or a binary-or'ed mask of possible values
+ * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
+ * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon
+ * as the computation of the coverage matches the mask, the computation will be
+ * stopped. *pdfDataPct will not be valid in that case.
+ *
+ * @param pdfDataPct Optional output parameter whose pointed value will be set
+ * to the (approximate) percentage in [0,100] of pixels in the queried
+ * sub-window that have valid values. The implementation might not always be
+ * able to compute it, in which case it will be set to a negative value.
+ *
+ * @return a binary-or'ed combination of possible values
+ * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
+ * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY
+ *
+ * @note Added in GDAL 2.2
+ */
+
+int CPL_STDCALL GDALGetDataCoverageStatus( GDALRasterBandH hBand,
+                               int nXOff, int nYOff,
+                               int nXSize,
+                               int nYSize,
+                               int nMaskFlagStop,
+                               double* pdfDataPct)
+{
+    VALIDATE_POINTER1( hBand, "GDALGetDataCoverageStatus",
+                       GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED );
+
+    GDALRasterBand *poBand = static_cast<GDALRasterBand*>(hBand);
+
+    return poBand->GetDataCoverageStatus( nXOff, nYOff, nXSize, nYSize,
+                                          nMaskFlagStop, pdfDataPct );
+}
+
+/************************************************************************/
+/*                          GetDataCoverageStatus()                     */
+/************************************************************************/
+
+/**
+ * \fn GDALRasterBand::IGetDataCoverageStatus( int nXOff,
+ *                                           int nYOff,
+ *                                           int nXSize,
+ *                                           int nYSize,
+ *                                           int nMaskFlagStop,
+ *                                           double* pdfDataPct)
+ * \brief Get the coverage status of a sub-window of the raster.
+ *
+ * Returns whether a sub-window of the raster contains only data, only empty
+ * blocks or a mix of both. This function can be used to determine quickly
+ * if it is worth issuing RasterIO / ReadBlock requests in datasets that may
+ * be sparse.
+ *
+ * Empty blocks are blocks that contain only pixels whose value is the nodata
+ * value when it is set, or whose value is 0 when the nodata value is not set.
+ *
+ * The query is done in an efficient way without reading the actual pixel
+ * values. If not possible, or not implemented at all by the driver,
+ * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | GDAL_DATA_COVERAGE_STATUS_DATA will
+ * be returned.
+ *
+ * The values that can be returned by the function are the following,
+ * potentially combined with the binary or operator :
+ * <ul>
+ * <li>GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED : the driver does not implement
+ * GetDataCoverageStatus(). This flag should be returned together with
+ * GDAL_DATA_COVERAGE_STATUS_DATA.</li>
+ * <li>GDAL_DATA_COVERAGE_STATUS_DATA: There is (potentially) data in the queried
+ * window.</li>
+ * <li>GDAL_DATA_COVERAGE_STATUS_EMPTY: There is nodata in the queried window.
+ * This is typically identified by the concept of missing block in formats that
+ * supports it.
+ * </li>
+ * </ul>
+ *
+ * Note that GDAL_DATA_COVERAGE_STATUS_DATA might have false positives and
+ * should be interpreted more as hint of potential presence of data. For example
+ * if a GeoTIFF file is created with blocks filled with zeroes (or set to the
+ * nodata value), instead of using the missing block mechanism,
+ * GDAL_DATA_COVERAGE_STATUS_DATA will be returned. On the contrary,
+ * GDAL_DATA_COVERAGE_STATUS_EMPTY should have no false positives.
+ *
+ * The nMaskFlagStop should be generally set to 0. It can be set to a
+ * binary-or'ed mask of the above mentioned values to enable a quick exiting of
+ * the function as soon as the computed mask matches the nMaskFlagStop. For
+ * example, you can issue a request on the whole raster with nMaskFlagStop =
+ * GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon as one missing block is encountered,
+ * the function will exit, so that you can potentially refine the requested area
+ * to find which particular region(s) have missing blocks.
+ *
+ * @see GDALGetDataCoverageStatus()
+ *
+ * @param nXOff The pixel offset to the top left corner of the region
+ * of the band to be queried. This would be zero to start from the left side.
+ *
+ * @param nYOff The line offset to the top left corner of the region
+ * of the band to be queried. This would be zero to start from the top.
+ *
+ * @param nXSize The width of the region of the band to be queried in pixels.
+ *
+ * @param nYSize The height of the region of the band to be queried in lines.
+ *
+ * @param nMaskFlagStop 0, or a binary-or'ed mask of possible values
+ * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
+ * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon
+ * as the computation of the coverage matches the mask, the computation will be
+ * stopped. *pdfDataPct will not be valid in that case.
+ *
+ * @param pdfDataPct Optional output parameter whose pointed value will be set
+ * to the (approximate) percentage in [0,100] of pixels in the queried
+ * sub-window that have valid values. The implementation might not always be
+ * able to compute it, in which case it will be set to a negative value.
+ *
+ * @return a binary-or'ed combination of possible values
+ * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
+ * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY
+ *
+ * @note Added in GDAL 2.2
+ */
+
+/**
+ * \brief Get the coverage status of a sub-window of the raster.
+ *
+ * Returns whether a sub-window of the raster contains only data, only empty
+ * blocks or a mix of both. This function can be used to determine quickly
+ * if it is worth issuing RasterIO / ReadBlock requests in datasets that may
+ * be sparse.
+ *
+ * Empty blocks are blocks that contain only pixels whose value is the nodata
+ * value when it is set, or whose value is 0 when the nodata value is not set.
+ *
+ * The query is done in an efficient way without reading the actual pixel
+ * values. If not possible, or not implemented at all by the driver,
+ * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED | GDAL_DATA_COVERAGE_STATUS_DATA will
+ * be returned.
+ *
+ * The values that can be returned by the function are the following,
+ * potentially combined with the binary or operator :
+ * <ul>
+ * <li>GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED : the driver does not implement
+ * GetDataCoverageStatus(). This flag should be returned together with
+ * GDAL_DATA_COVERAGE_STATUS_DATA.</li>
+ * <li>GDAL_DATA_COVERAGE_STATUS_DATA: There is (potentially) data in the queried
+ * window.</li>
+ * <li>GDAL_DATA_COVERAGE_STATUS_EMPTY: There is nodata in the queried window.
+ * This is typically identified by the concept of missing block in formats that
+ * supports it.
+ * </li>
+ * </ul>
+ *
+ * Note that GDAL_DATA_COVERAGE_STATUS_DATA might have false positives and
+ * should be interpreted more as hint of potential presence of data. For example
+ * if a GeoTIFF file is created with blocks filled with zeroes (or set to the
+ * nodata value), instead of using the missing block mechanism,
+ * GDAL_DATA_COVERAGE_STATUS_DATA will be returned. On the contrary,
+ * GDAL_DATA_COVERAGE_STATUS_EMPTY should have no false positives.
+ *
+ * The nMaskFlagStop should be generally set to 0. It can be set to a
+ * binary-or'ed mask of the above mentioned values to enable a quick exiting of
+ * the function as soon as the computed mask matches the nMaskFlagStop. For
+ * example, you can issue a request on the whole raster with nMaskFlagStop =
+ * GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon as one missing block is encountered,
+ * the function will exit, so that you can potentially refine the requested area
+ * to find which particular region(s) have missing blocks.
+ *
+ * @see GDALGetDataCoverageStatus()
+ *
+ * @param nXOff The pixel offset to the top left corner of the region
+ * of the band to be queried. This would be zero to start from the left side.
+ *
+ * @param nYOff The line offset to the top left corner of the region
+ * of the band to be queried. This would be zero to start from the top.
+ *
+ * @param nXSize The width of the region of the band to be queried in pixels.
+ *
+ * @param nYSize The height of the region of the band to be queried in lines.
+ *
+ * @param nMaskFlagStop 0, or a binary-or'ed mask of possible values
+ * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
+ * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY. As soon
+ * as the computation of the coverage matches the mask, the computation will be
+ * stopped. *pdfDataPct will not be valid in that case.
+ *
+ * @param pdfDataPct Optional output parameter whose pointed value will be set
+ * to the (approximate) percentage in [0,100] of pixels in the queried
+ * sub-window that have valid values. The implementation might not always be
+ * able to compute it, in which case it will be set to a negative value.
+ *
+ * @return a binary-or'ed combination of possible values
+ * GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED,
+ * GDAL_DATA_COVERAGE_STATUS_DATA and GDAL_DATA_COVERAGE_STATUS_EMPTY
+ *
+ * @note Added in GDAL 2.2
+ */
+
+int  GDALRasterBand::GetDataCoverageStatus( int nXOff,
+                                            int nYOff,
+                                            int nXSize,
+                                            int nYSize,
+                                            int nMaskFlagStop,
+                                            double* pdfDataPct)
+{
+    if( nXOff < 0 || nYOff < 0 ||
+        nXSize > INT_MAX - nXOff ||
+        nYSize > INT_MAX - nYOff ||
+        nXOff + nXSize > nRasterXSize ||
+        nYOff + nYSize > nRasterYSize )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Bad window");
+        if( pdfDataPct )
+            *pdfDataPct = 0.0;
+        return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED |
+               GDAL_DATA_COVERAGE_STATUS_EMPTY;
+    }
+    return IGetDataCoverageStatus(nXOff, nYOff, nXSize, nYSize,
+                                  nMaskFlagStop, pdfDataPct);
+}
+
+/************************************************************************/
+/*                         IGetDataCoverageStatus()                     */
+/************************************************************************/
+
+int  GDALRasterBand::IGetDataCoverageStatus( int /*nXOff*/,
+                                             int /*nYOff*/,
+                                             int /*nXSize*/,
+                                             int /*nYSize*/,
+                                             int /*nMaskFlagStop*/,
+                                             double* pdfDataPct)
+{
+    if( pdfDataPct != NULL )
+        *pdfDataPct = 100.0;
+    return GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED |
+           GDAL_DATA_COVERAGE_STATUS_DATA;
+}
+
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                          EnterReadWrite()                            */
 /************************************************************************/
 
-int GDALRasterBand::EnterReadWrite(GDALRWFlag eRWFlag)
+int GDALRasterBand::EnterReadWrite( GDALRWFlag eRWFlag )
 {
     if( poDS != NULL )
         return poDS->EnterReadWrite(eRWFlag);
@@ -5313,3 +6978,43 @@ void GDALRasterBand::InitRWLock()
     if( poDS != NULL )
         poDS->InitRWLock();
 }
+
+//! @endcond
+
+/**
+ * \fn GDALRasterBand::SetMetadata( char ** papszMetadata, const char * pszDomain)
+ * \brief Set metadata.
+ *
+ * CAUTION: depending on the format, older values of the updated information might
+ * still be found in the file in a "ghost" state, even if no longer accessible
+ * through the GDAL API. This is for example the case of the GTiff format (this is
+ * not a exhaustive list)
+ *
+ * The C function GDALSetMetadata() does the same thing as this method.
+ *
+ * @param papszMetadata the metadata in name=value string list format to
+ * apply.
+ * @param pszDomain the domain of interest.  Use "" or NULL for the default
+ * domain.
+ * @return CE_None on success, CE_Failure on failure and CE_Warning if the
+ * metadata has been accepted, but is likely not maintained persistently
+ * by the underlying object between sessions.
+ */
+
+/**
+ * \fn GDALRasterBand::SetMetadataItem( const char * pszName, const char * pszValue, const char * pszDomain)
+ * \brief Set single metadata item.
+ *
+ * CAUTION: depending on the format, older values of the updated information might
+ * still be found in the file in a "ghost" state, even if no longer accessible
+ * through the GDAL API. This is for example the case of the GTiff format (this is
+ * not a exhaustive list)
+ *
+ * The C function GDALSetMetadataItem() does the same thing as this method.
+ *
+ * @param pszName the key for the metadata item to fetch.
+ * @param pszValue the value to assign to the key.
+ * @param pszDomain the domain to set within, use NULL for the default domain.
+ *
+ * @return CE_None on success, or an error code on failure.
+ */
diff --git a/gcore/gdalrasterblock.cpp b/gcore/gdalrasterblock.cpp
index c3001e4..23c39a7 100644
--- a/gcore/gdalrasterblock.cpp
+++ b/gcore/gdalrasterblock.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalrasterblock.cpp 35549 2016-09-29 22:56:53Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRasterBlock class and related global
@@ -29,34 +28,47 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal.h"
 #include "gdal_priv.h"
+
+#include <climits>
+#include <cstring>
+
+#include "cpl_atomic_ops.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: gdalrasterblock.cpp 35549 2016-09-29 22:56:53Z rouault $");
+CPL_CVSID("$Id: gdalrasterblock.cpp 36763 2016-12-09 22:10:55Z rouault $");
 
 static bool bCacheMaxInitialized = false;
-static GIntBig nCacheMax = 40 * 1024*1024; /* Will later be overridden by the default 5% if GDAL_CACHEMAX not defined */
+// Will later be overridden by the default 5% if GDAL_CACHEMAX not defined.
+static GIntBig nCacheMax = 40 * 1024 * 1024;
 static volatile GIntBig nCacheUsed = 0;
 
-static GDALRasterBlock *poOldest = NULL;    /* tail */
-static GDALRasterBlock *poNewest = NULL;    /* head */
+static GDALRasterBlock *poOldest = NULL;  // Tail.
+static GDALRasterBlock *poNewest = NULL;  // Head.
 
 #if 0
 static CPLMutex *hRBLock = NULL;
-#define INITIALIZE_LOCK         CPLMutexHolderD( &hRBLock )
-#define TAKE_LOCK               CPLMutexHolderOptionalLockD( hRBLock )
-#define DESTROY_LOCK            CPLDestroyMutex( hRBLock )
+#define INITIALIZE_LOCK CPLMutexHolderD( &hRBLock )
+#define TAKE_LOCK       CPLMutexHolderOptionalLockD( hRBLock )
+#define DESTROY_LOCK    CPLDestroyMutex( hRBLock )
 #else
 
 static CPLLock* hRBLock = NULL;
-static int bDebugContention = FALSE;
+static bool bDebugContention = false;
 static bool bSleepsForBockCacheDebug = false;
 static CPLLockType GetLockType()
 {
     static int nLockType = -1;
     if( nLockType < 0 )
     {
-        const char* pszLockType = CPLGetConfigOption("GDAL_RB_LOCK_TYPE", "ADAPTIVE");
+        const char* pszLockType =
+            CPLGetConfigOption("GDAL_RB_LOCK_TYPE", "ADAPTIVE");
         if( EQUAL(pszLockType, "ADAPTIVE") )
             nLockType = LOCK_ADAPTIVE_MUTEX;
         else if( EQUAL(pszLockType, "RECURSIVE") )
@@ -65,12 +77,14 @@ static CPLLockType GetLockType()
             nLockType = LOCK_SPIN;
         else
         {
-            CPLError(CE_Warning, CPLE_NotSupported,
-                     "GDAL_RB_LOCK_TYPE=%s not supported. Falling back to ADAPTIVE",
-                     pszLockType);
+            CPLError(
+                CE_Warning, CPLE_NotSupported,
+                "GDAL_RB_LOCK_TYPE=%s not supported. Falling back to ADAPTIVE",
+                pszLockType);
             nLockType = LOCK_ADAPTIVE_MUTEX;
         }
-        bDebugContention = CPLTestBool(CPLGetConfigOption("GDAL_RB_LOCK_DEBUG_CONTENTION", "NO"));
+        bDebugContention = CPLTestBool(
+            CPLGetConfigOption("GDAL_RB_LOCK_DEBUG_CONTENTION", "NO"));
     }
     return (CPLLockType) nLockType;
 }
@@ -106,7 +120,6 @@ void CPL_STDCALL GDALSetCacheMax( int nNewSizeInBytes )
     GDALSetCacheMax64(nNewSizeInBytes);
 }
 
-
 /************************************************************************/
 /*                        GDALSetCacheMax64()                           */
 /************************************************************************/
@@ -140,7 +153,7 @@ void CPL_STDCALL GDALSetCacheMax64( GIntBig nNewSizeInBytes )
 
     {
         INITIALIZE_LOCK;
-    }   
+    }
     bCacheMaxInitialized = true;
     nCacheMax = nNewSizeInBytes;
 
@@ -150,7 +163,7 @@ void CPL_STDCALL GDALSetCacheMax64( GIntBig nNewSizeInBytes )
 /* -------------------------------------------------------------------- */
     while( nCacheUsed > nCacheMax )
     {
-        GIntBig nOldCacheUsed = nCacheUsed;
+        const GIntBig nOldCacheUsed = nCacheUsed;
 
         GDALFlushCacheBlock();
 
@@ -189,9 +202,9 @@ int CPL_STDCALL GDALGetCacheMax()
         static bool bHasWarned = false;
         if (!bHasWarned)
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Cache max value doesn't fit on a 32 bit integer. "
-                     "Call GDALGetCacheMax64() instead");
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Cache max value doesn't fit on a 32 bit integer. "
+                      "Call GDALGetCacheMax64() instead" );
             bHasWarned = true;
         }
         nRes = INT_MAX;
@@ -227,24 +240,37 @@ GIntBig CPL_STDCALL GDALGetCacheMax64()
         {
             INITIALIZE_LOCK;
         }
-        bSleepsForBockCacheDebug = CPLTestBool(CPLGetConfigOption("GDAL_DEBUG_BLOCK_CACHE", "NO"));
+        bSleepsForBockCacheDebug = CPLTestBool(
+            CPLGetConfigOption("GDAL_DEBUG_BLOCK_CACHE", "NO"));
 
         const char* pszCacheMax = CPLGetConfigOption("GDAL_CACHEMAX","5%");
 
         GIntBig nNewCacheMax;
         if( strchr(pszCacheMax, '%') != NULL )
         {
-            GIntBig nUsagePhysicalRAM = CPLGetUsablePhysicalRAM();
-            // For some reason, coverity pretends that this will overflow...
-            // "Multiply operation overflows on operands static_cast<double>(nUsagePhysicalRAM)
-            // and CPLAtof(pszCacheMax). Example values for operands: CPLAtof(pszCacheMax) = 2251799813685248,
-            // static_cast<double>(nUsagePhysicalRAM) = -9223372036854775808."
-            /* coverity[overflow] */
-            double dfCacheMax = static_cast<double>(nUsagePhysicalRAM) * CPLAtof(pszCacheMax) / 100.0;
-            if( dfCacheMax >= 0 && dfCacheMax < 1e15 )
-                nNewCacheMax = static_cast<GIntBig>(dfCacheMax);
+            GIntBig nUsablePhysicalRAM = CPLGetUsablePhysicalRAM();
+            if( nUsablePhysicalRAM > 0 )
+            {
+                // For some reason, coverity pretends that this will overflow.
+                // "Multiply operation overflows on operands static_cast<double>(
+                // nUsablePhysicalRAM ) and CPLAtof(pszCacheMax). Example values for
+                // operands: CPLAtof( pszCacheMax ) = 2251799813685248,
+                // static_cast<double>(nUsablePhysicalRAM) = -9223372036854775808."
+                // coverity[overflow]
+                double dfCacheMax =
+                    static_cast<double>(nUsablePhysicalRAM) *
+                    CPLAtof(pszCacheMax) / 100.0;
+                if( dfCacheMax >= 0 && dfCacheMax < 1e15 )
+                    nNewCacheMax = static_cast<GIntBig>(dfCacheMax);
+                else
+                    nNewCacheMax = nCacheMax;
+            }
             else
+            {
+                CPLDebug("GDAL",
+                         "Cannot determine usable physical RAM.");
                 nNewCacheMax = nCacheMax;
+            }
         }
         else
         {
@@ -253,13 +279,19 @@ GIntBig CPL_STDCALL GDALGetCacheMax64()
             {
                 if (nNewCacheMax < 0)
                 {
-                    CPLError(CE_Failure, CPLE_NotSupported,
-                                "Invalid value for GDAL_CACHEMAX. Using default value.");
-                    GIntBig nUsagePhysicalRAM = CPLGetUsablePhysicalRAM();
-                    if( nUsagePhysicalRAM )
-                        nNewCacheMax = nUsagePhysicalRAM / 20;
+                    CPLError(
+                        CE_Failure, CPLE_NotSupported,
+                        "Invalid value for GDAL_CACHEMAX. "
+                        "Using default value.");
+                    GIntBig nUsablePhysicalRAM = CPLGetUsablePhysicalRAM();
+                    if( nUsablePhysicalRAM )
+                        nNewCacheMax = nUsablePhysicalRAM / 20;
                     else
+                    {
+                        CPLDebug("GDAL",
+                                 "Cannot determine usable physical RAM.");
                         nNewCacheMax = nCacheMax;
+                    }
                 }
                 else
                 {
@@ -268,11 +300,11 @@ GIntBig CPL_STDCALL GDALGetCacheMax64()
             }
         }
         nCacheMax = nNewCacheMax;
-        CPLDebug("GDAL", "GDAL_CACHEMAX = " CPL_FRMT_GIB " MB",
-                 nCacheMax / (1024 * 1024));
+        CPLDebug( "GDAL", "GDAL_CACHEMAX = " CPL_FRMT_GIB " MB",
+                  nCacheMax / (1024 * 1024));
         bCacheMaxInitialized = true;
     }
-    /* coverity[overflow_sink] */
+    // coverity[overflow_sink]
     return nCacheMax;
 }
 
@@ -294,14 +326,14 @@ int CPL_STDCALL GDALGetCacheUsed()
         static bool bHasWarned = false;
         if (!bHasWarned)
         {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Cache used value doesn't fit on a 32 bit integer. "
-                     "Call GDALGetCacheUsed64() instead");
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Cache used value doesn't fit on a 32 bit integer. "
+                      "Call GDALGetCacheUsed64() instead" );
             bHasWarned = true;
         }
         return INT_MAX;
     }
-    return (int)nCacheUsed;
+    return static_cast<int>(nCacheUsed);
 }
 
 /************************************************************************/
@@ -317,10 +349,7 @@ int CPL_STDCALL GDALGetCacheUsed()
  * @since GDAL 1.8.0
  */
 
-GIntBig CPL_STDCALL GDALGetCacheUsed64()
-{
-    return nCacheUsed;
-}
+GIntBig CPL_STDCALL GDALGetCacheUsed64() { return nCacheUsed; }
 
 /************************************************************************/
 /*                        GDALFlushCacheBlock()                         */
@@ -396,7 +425,7 @@ int CPL_STDCALL GDALFlushCacheBlock()
  * @return TRUE if successful or FALSE if no flushable block is found.
  */
 
-int GDALRasterBlock::FlushCacheBlock(int bDirtyBlocksOnly)
+int GDALRasterBlock::FlushCacheBlock( int bDirtyBlocksOnly )
 
 {
     GDALRasterBlock *poTarget;
@@ -409,7 +438,8 @@ int GDALRasterBlock::FlushCacheBlock(int bDirtyBlocksOnly)
         {
             if( !bDirtyBlocksOnly || poTarget->GetDirty() )
             {
-                if( CPLAtomicCompareAndExchange(&(poTarget->nLockCount), 0, -1) )
+                if( CPLAtomicCompareAndExchange(
+                        &(poTarget->nLockCount), 0, -1) )
                     break;
             }
             poTarget = poTarget->poPrevious;
@@ -418,26 +448,29 @@ int GDALRasterBlock::FlushCacheBlock(int bDirtyBlocksOnly)
         if( poTarget == NULL )
             return FALSE;
         if( bSleepsForBockCacheDebug )
-            CPLSleep(CPLAtof(CPLGetConfigOption("GDAL_RB_FLUSHBLOCK_SLEEP_AFTER_DROP_LOCK", "0")));
+            CPLSleep(CPLAtof(
+                CPLGetConfigOption(
+                    "GDAL_RB_FLUSHBLOCK_SLEEP_AFTER_DROP_LOCK", "0")));
 
         poTarget->Detach_unlocked();
         poTarget->GetBand()->UnreferenceBlock(poTarget);
     }
 
     if( bSleepsForBockCacheDebug )
-        CPLSleep(CPLAtof(CPLGetConfigOption("GDAL_RB_FLUSHBLOCK_SLEEP_AFTER_RB_LOCK", "0")));
+        CPLSleep(CPLAtof(
+            CPLGetConfigOption("GDAL_RB_FLUSHBLOCK_SLEEP_AFTER_RB_LOCK", "0")));
 
     if( poTarget->GetDirty() )
     {
-        CPLErr eErr = poTarget->Write();
+        const CPLErr eErr = poTarget->Write();
         if( eErr != CE_None )
         {
-             /* Save the error for later reporting */
+            // Save the error for later reporting.
             poTarget->GetBand()->SetFlushBlockErr(eErr);
         }
     }
 
-    VSIFree(poTarget->pData);
+    VSIFreeAligned(poTarget->pData);
     poTarget->pData = NULL;
     poTarget->GetBand()->AddBlockToFreeList(poTarget);
 
@@ -454,9 +487,9 @@ int GDALRasterBlock::FlushCacheBlock(int bDirtyBlocksOnly)
  * This static method is normally used to recover memory and is especially
  * useful when doing multi-threaded code that can trigger the block cache.
  *
- * Due to the current design of the block cache, dirty blocks belonging to a same
- * dataset could be pushed simultaneously to the IWriteBlock() method of that
- * dataset from different threads, causing races.
+ * Due to the current design of the block cache, dirty blocks belonging to a
+ * same dataset could be pushed simultaneously to the IWriteBlock() method of
+ * that dataset from different threads, causing races.
  *
  * Calling this method before that code can help workarounding that issue,
  * in a multiple readers, one writer scenario.
@@ -493,22 +526,22 @@ void GDALRasterBlock::FlushDirtyBlocks()
  */
 
 GDALRasterBlock::GDALRasterBlock( GDALRasterBand *poBandIn,
-                                  int nXOffIn, int nYOffIn )
-
+                                  int nXOffIn, int nYOffIn ) :
+    eType(poBandIn->GetRasterDataType()),
+    bDirty(false),
+    nLockCount(0),
+    nXOff(nXOffIn),
+    nYOff(nYOffIn),
+    nXSize(0),
+    nYSize(0),
+    pData(NULL),
+    poBand(poBandIn),
+    poNext(NULL),
+    poPrevious(NULL),
+    bMustDetach(true)
 {
     CPLAssert( poBandIn != NULL );
-    poBand = poBandIn;
     poBand->GetBlockSize( &nXSize, &nYSize );
-    eType = poBand->GetRasterDataType();
-    pData = NULL;
-    bDirty = FALSE;
-    nLockCount = 0;
-
-    poNext = poPrevious = NULL;
-
-    nXOff = nXOffIn;
-    nYOff = nYOffIn;
-    bMustDetach = TRUE;
 }
 
 /************************************************************************/
@@ -529,22 +562,20 @@ GDALRasterBlock::GDALRasterBlock( GDALRasterBand *poBandIn,
  * the top most block, 1 the next block and so forth.
  */
 
-GDALRasterBlock::GDALRasterBlock( int nXOffIn, int nYOffIn )
-
-{
-    poBand = NULL;
-    nXSize = nYSize = 0;
-    eType = GDT_Unknown;
-    pData = NULL;
-    bDirty = FALSE;
-    nLockCount = 0;
-
-    poNext = poPrevious = NULL;
-
-    nXOff = nXOffIn;
-    nYOff = nYOffIn;
-    bMustDetach = FALSE;
-}
+GDALRasterBlock::GDALRasterBlock( int nXOffIn, int nYOffIn ) :
+    eType(GDT_Unknown),
+    bDirty(false),
+    nLockCount(0),
+    nXOff(nXOffIn),
+    nYOff(nYOffIn),
+    nXSize(0),
+    nYSize(0),
+    pData(NULL),
+    poBand(NULL),
+    poNext(NULL),
+    poPrevious(NULL),
+    bMustDetach(false)
+{}
 
 /************************************************************************/
 /*                                  RecycleFor()                        */
@@ -560,14 +591,15 @@ void GDALRasterBlock::RecycleFor( int nXOffIn, int nYOffIn )
 {
     CPLAssert(pData == NULL);
     pData = NULL;
-    bDirty = FALSE;
+    bDirty = false;
     nLockCount = 0;
 
-    poNext = poPrevious = NULL;
+    poNext = NULL;
+    poPrevious = NULL;
 
     nXOff = nXOffIn;
     nYOff = nYOffIn;
-    bMustDetach = TRUE;
+    bMustDetach = true;
 }
 
 /************************************************************************/
@@ -587,7 +619,7 @@ GDALRasterBlock::~GDALRasterBlock()
 
     if( pData != NULL )
     {
-        VSIFree( pData );
+        VSIFreeAligned( pData );
     }
 
     CPLAssert( nLockCount <= 0 );
@@ -638,7 +670,7 @@ void GDALRasterBlock::Detach_unlocked()
 
     poPrevious = NULL;
     poNext = NULL;
-    bMustDetach = FALSE;
+    bMustDetach = false;
 
     if( pData )
         nCacheUsed -= GetBlockSize();
@@ -689,8 +721,8 @@ void GDALRasterBlock::Verify()
 void GDALRasterBlock::Verify() {}
 #endif
 
-#if 0
-void GDALRasterBlock::CheckNonOrphanedBlocks(GDALRasterBand* poBand)
+#ifdef notdef
+void GDALRasterBlock::CheckNonOrphanedBlocks( GDALRasterBand* poBand )
 {
     TAKE_LOCK;
     for( GDALRasterBlock *poBlock = poNewest;
@@ -699,17 +731,18 @@ void GDALRasterBlock::CheckNonOrphanedBlocks(GDALRasterBand* poBand)
     {
         if ( poBlock->GetBand() == poBand )
         {
-            printf("Cache has still blocks of band %p\n", poBand);
-            printf("Band : %d\n", poBand->GetBand());
-            printf("nRasterXSize = %d\n", poBand->GetXSize());
-            printf("nRasterYSize = %d\n", poBand->GetYSize());
+            printf("Cache has still blocks of band %p\n", poBand);/*ok*/
+            printf("Band : %d\n", poBand->GetBand());/*ok*/
+            printf("nRasterXSize = %d\n", poBand->GetXSize());/*ok*/
+            printf("nRasterYSize = %d\n", poBand->GetYSize());/*ok*/
             int nBlockXSize, nBlockYSize;
             poBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
-            printf("nBlockXSize = %d\n", nBlockXSize);
-            printf("nBlockYSize = %d\n", nBlockYSize);
-            printf("Dataset : %p\n", poBand->GetDataset());
+            printf("nBlockXSize = %d\n", nBlockXSize);/*ok*/
+            printf("nBlockYSize = %d\n", nBlockYSize);/*ok*/
+            printf("Dataset : %p\n", poBand->GetDataset());/*ok*/
             if( poBand->GetDataset() )
-                printf("Dataset : %s\n", poBand->GetDataset()->GetDescription());
+                printf("Dataset : %s\n",/*ok*/
+                       poBand->GetDataset()->GetDescription());
         }
     }
 }
@@ -722,7 +755,7 @@ void GDALRasterBlock::CheckNonOrphanedBlocks(GDALRasterBand* poBand)
 /**
  * Force writing of the current block, if dirty.
  *
- * The block is written using GDALRasterBand::IWriteBlock() on it's
+ * The block is written using GDALRasterBand::IWriteBlock() on its
  * corresponding band object.  Even if the write fails the block will
  * be marked clean.
  *
@@ -765,25 +798,34 @@ CPLErr GDALRasterBlock::Write()
 void GDALRasterBlock::Touch()
 
 {
+    // Can be safely tested outside the lock
+    if( poNewest == this )
+        return;
+
     TAKE_LOCK;
     Touch_unlocked();
 }
 
-
 void GDALRasterBlock::Touch_unlocked()
 
 {
+    // Could happen even if tested in Touch() before taking the lock
+    // Scenario would be :
+    // 0. this is the second block (the one pointed by poNewest->poNext)
+    // 1. Thread 1 calls Touch() and poNewest != this at that point
+    // 2. Thread 2 detaches poNewest
+    // 3. Thread 1 arrives here
     if( poNewest == this )
         return;
 
-    // In theory, we should not try to touch a block that has been detached
+    // In theory, we should not try to touch a block that has been detached.
     CPLAssert(bMustDetach);
     if( !bMustDetach )
     {
         if( pData )
             nCacheUsed += GetBlockSize();
 
-        bMustDetach = TRUE;
+        bMustDetach = true;
     }
 
     if( poOldest == this )
@@ -833,17 +875,16 @@ void GDALRasterBlock::Touch_unlocked()
 CPLErr GDALRasterBlock::Internalize()
 
 {
-    void        *pNewData = NULL;
-    int         nSizeInBytes;
-
     CPLAssert( pData == NULL );
 
+    void        *pNewData = NULL;
+
     // This call will initialize the hRBLock mutex. Other call places can
     // only be called if we have go through there.
-    GIntBig     nCurCacheMax = GDALGetCacheMax64();
+    const GIntBig nCurCacheMax = GDALGetCacheMax64();
 
-    /* No risk of overflow as it is checked in GDALRasterBand::InitBlockInfo() */
-    nSizeInBytes = GetBlockSize();
+    // No risk of overflow as it is checked in GDALRasterBand::InitBlockInfo().
+    const int nSizeInBytes = GetBlockSize();
 
 /* -------------------------------------------------------------------- */
 /*      Flush old blocks if we are nearing our memory limit.            */
@@ -853,7 +894,7 @@ CPLErr GDALRasterBlock::Internalize()
     do
     {
         bLoopAgain = false;
-        GDALRasterBlock* apoBlocksToFree[64];
+        GDALRasterBlock* apoBlocksToFree[64] = { NULL };
         int nBlocksToFree = 0;
         {
             TAKE_LOCK;
@@ -865,7 +906,8 @@ CPLErr GDALRasterBlock::Internalize()
             {
                 while( poTarget != NULL )
                 {
-                    if( CPLAtomicCompareAndExchange(&(poTarget->nLockCount), 0, -1) )
+                    if( CPLAtomicCompareAndExchange(
+                            &(poTarget->nLockCount), 0, -1) )
                         break;
                     poTarget = poTarget->poPrevious;
                 }
@@ -873,7 +915,10 @@ CPLErr GDALRasterBlock::Internalize()
                 if( poTarget != NULL )
                 {
                     if( bSleepsForBockCacheDebug )
-                        CPLSleep(CPLAtof(CPLGetConfigOption("GDAL_RB_INTERNALIZE_SLEEP_AFTER_DROP_LOCK", "0")));
+                        CPLSleep(CPLAtof(
+                            CPLGetConfigOption(
+                                "GDAL_RB_INTERNALIZE_SLEEP_AFTER_DROP_LOCK",
+                                "0")));
 
                     GDALRasterBlock* _poPrevious = poTarget->poPrevious;
 
@@ -884,9 +929,9 @@ CPLErr GDALRasterBlock::Internalize()
                     if( poTarget->GetDirty() )
                     {
                         // Only free one dirty block at a time so that
-                        // other dirty blocks of other bands with the same coordinates
-                        // can be found with TryGetLockedBlock()
-                        bLoopAgain = ( nCacheUsed > nCurCacheMax );
+                        // other dirty blocks of other bands with the same
+                        // coordinates can be found with TryGetLockedBlock()
+                        bLoopAgain = nCacheUsed > nCurCacheMax;
                         break;
                     }
                     if( nBlocksToFree == 64 )
@@ -898,34 +943,36 @@ CPLErr GDALRasterBlock::Internalize()
                     poTarget = _poPrevious;
                 }
                 else
+                {
                     break;
+                }
             }
 
-        /* -------------------------------------------------------------------- */
-        /*      Add this block to the list.                                     */
-        /* -------------------------------------------------------------------- */
+        /* ------------------------------------------------------------------ */
+        /*      Add this block to the list.                                   */
+        /* ------------------------------------------------------------------ */
             if( !bLoopAgain )
                 Touch_unlocked();
         }
 
         bFirstIter = false;
 
-        /* Now free blocks we have detached and removed from their band */
-        for(int i=0;i<nBlocksToFree;i++)
+        // Now free blocks we have detached and removed from their band.
+        for( int i = 0; i < nBlocksToFree; ++i)
         {
-            GDALRasterBlock *poBlock = apoBlocksToFree[i];
+            GDALRasterBlock * const poBlock = apoBlocksToFree[i];
 
             if( poBlock->GetDirty() )
             {
                 CPLErr eErr = poBlock->Write();
                 if( eErr != CE_None )
                 {
-                    /* Save the error for later reporting */
+                    // Save the error for later reporting.
                     poBlock->GetBand()->SetFlushBlockErr(eErr);
                 }
             }
 
-            /* Try to recycle the data of an existing block */
+            // Try to recycle the data of an existing block.
             void* pDataBlock = poBlock->pData;
             if( pNewData == NULL && pDataBlock != NULL &&
                 poBlock->GetBlockSize() == nSizeInBytes )
@@ -934,7 +981,7 @@ CPLErr GDALRasterBlock::Internalize()
             }
             else
             {
-                VSIFree(poBlock->pData);
+                VSIFreeAligned(poBlock->pData);
             }
             poBlock->pData = NULL;
 
@@ -945,7 +992,7 @@ CPLErr GDALRasterBlock::Internalize()
 
     if( pNewData == NULL )
     {
-        pNewData = VSI_MALLOC_VERBOSE( nSizeInBytes );
+        pNewData = VSI_MALLOC_ALIGNED_AUTO_VERBOSE( nSizeInBytes );
         if( pNewData == NULL )
         {
             return( CE_Failure );
@@ -954,7 +1001,7 @@ CPLErr GDALRasterBlock::Internalize()
 
     pData = pNewData;
 
-    return( CE_None );
+    return CE_None;
 }
 
 /************************************************************************/
@@ -975,7 +1022,6 @@ void GDALRasterBlock::MarkDirty()
         poBand->InitRWLock();
 }
 
-
 /************************************************************************/
 /*                             MarkClean()                              */
 /************************************************************************/
@@ -987,22 +1033,20 @@ void GDALRasterBlock::MarkDirty()
  * to disk before it can be flushed.
  */
 
-void GDALRasterBlock::MarkClean()
-
-{
-    bDirty = FALSE;
-}
+void GDALRasterBlock::MarkClean() { bDirty = false; }
 
 /************************************************************************/
 /*                          DestroyRBMutex()                           */
 /************************************************************************/
 
+/*! @cond Doxygen_Suppress */
 void GDALRasterBlock::DestroyRBMutex()
 {
     if( hRBLock != NULL )
         DESTROY_LOCK;
     hRBLock = NULL;
 }
+/*! @endcond */
 
 /************************************************************************/
 /*                              TakeLock()                              */
@@ -1021,19 +1065,23 @@ void GDALRasterBlock::DestroyRBMutex()
 
 int GDALRasterBlock::TakeLock()
 {
-    int nLockVal = AddLock();
+    const int nLockVal = AddLock();
     CPLAssert(nLockVal >= 0);
     if( bSleepsForBockCacheDebug )
-        CPLSleep(CPLAtof(CPLGetConfigOption("GDAL_RB_TRYGET_SLEEP_AFTER_TAKE_LOCK", "0")));
+        CPLSleep(CPLAtof(
+            CPLGetConfigOption("GDAL_RB_TRYGET_SLEEP_AFTER_TAKE_LOCK", "0")));
     if( nLockVal == 0 )
     {
 #ifdef DEBUG
-        CPLDebug("GDAL", "TakeLock(%p): Block(%d,%d,%p) is being evicted while trying to reacquire it",
-                 (void*)CPLGetPID(), nXOff, nYOff, poBand);
+        CPLDebug(
+            "GDAL",
+            "TakeLock(%p): Block(%d,%d,%p) is being evicted while trying to "
+            "reacquire it.",
+            reinterpret_cast<void *>(CPLGetPID()), nXOff, nYOff, poBand );
 #endif
         // The block is being evicted by GDALRasterBlock::Internalize()
         // or FlushCacheBlock(), so wait for this to be done before trying
-        // again
+        // again.
         DropLock();
 
         // wait for the block having been unreferenced
@@ -1065,12 +1113,14 @@ int GDALRasterBlock::DropLockForRemovalFromStorage()
     if( CPLAtomicCompareAndExchange(&nLockCount, 0, -1) )
         return TRUE;
 #ifdef DEBUG
-    CPLDebug("GDAL", "DropLockForRemovalFromStorage(%p): Block(%d,%d,%p) was "
-                "attempted to be flushed from band but it is flushed by global cache",
-                (void*)CPLGetPID(), nXOff, nYOff, poBand);
+    CPLDebug(
+        "GDAL",
+        "DropLockForRemovalFromStorage(%p): Block(%d,%d,%p) was attempted "
+        "to be flushed from band but it is flushed by global cache.",
+        reinterpret_cast<void *>(CPLGetPID()), nXOff, nYOff, poBand );
 #endif
 
-    // Wait for the block for having been unreferenced
+    // Wait for the block for having been unreferenced.
     TAKE_LOCK;
 
     return FALSE;
@@ -1081,28 +1131,29 @@ void GDALRasterBlock::DumpAll()
 {
     int iBlock = 0;
     for( GDALRasterBlock *poBlock = poNewest;
-                            poBlock != NULL;
-                            poBlock = poBlock->poNext )
+         poBlock != NULL;
+         poBlock = poBlock->poNext )
     {
-        printf("Block %d\n", iBlock);
+        printf("Block %d\n", iBlock);/*ok*/
         poBlock->DumpBlock();
-        printf("\n");
-        iBlock ++;
+        printf("\n");/*ok*/
+        iBlock++;
     }
 }
 
 void GDALRasterBlock::DumpBlock()
 {
-        printf("  Lock count = %d\n", nLockCount);
-        printf("  bDirty = %d\n", bDirty);
-        printf("  nXOff = %d\n", nXOff);
-        printf("  nYOff = %d\n", nYOff);
-        printf("  nXSize = %d\n", nXSize);
-        printf("  nYSize = %d\n", nYSize);
-        printf("  eType = %d\n", eType);
-        printf("  Band %p\n", GetBand());
-        printf("  Band %d\n", GetBand()->GetBand());
-        if( GetBand()->GetDataset() )
-            printf("  Dataset = %s\n", GetBand()->GetDataset()->GetDescription());
+    printf("  Lock count = %d\n", nLockCount);/*ok*/
+    printf("  bDirty = %d\n", static_cast<int>(bDirty));/*ok*/
+    printf("  nXOff = %d\n", nXOff);/*ok*/
+    printf("  nYOff = %d\n", nYOff);/*ok*/
+    printf("  nXSize = %d\n", nXSize);/*ok*/
+    printf("  nYSize = %d\n", nYSize);/*ok*/
+    printf("  eType = %d\n", eType);/*ok*/
+    printf("  Band %p\n", GetBand());/*ok*/
+    printf("  Band %d\n", GetBand()->GetBand());/*ok*/
+    if( GetBand()->GetDataset() )
+        printf("  Dataset = %s\n",/*ok*/
+               GetBand()->GetDataset()->GetDescription());
 }
-#endif
+#endif  // if 0
diff --git a/gcore/gdalrescaledalphaband.cpp b/gcore/gdalrescaledalphaband.cpp
index 92ef8de..139ca50 100644
--- a/gcore/gdalrescaledalphaband.cpp
+++ b/gcore/gdalrescaledalphaband.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gdalrescaledalphaband.cpp 31703 2015-11-21 22:11:38Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Implementation of GDALRescaledAlphaBand, a class implementing
@@ -28,20 +27,29 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal_priv.h"
 
-CPL_CVSID("$Id: gdalrescaledalphaband.cpp 31703 2015-11-21 22:11:38Z rouault $");
+#include <cstddef>
 
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+
+CPL_CVSID("$Id: gdalrescaledalphaband.cpp 36526 2016-11-27 15:46:54Z goatbar $");
+
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                        GDALRescaledAlphaBand()                       */
 /************************************************************************/
 
-GDALRescaledAlphaBand::GDALRescaledAlphaBand( GDALRasterBand *poParentIn )
-
+GDALRescaledAlphaBand::GDALRescaledAlphaBand( GDALRasterBand *poParentIn ) :
+    poParent(poParentIn),
+    pTemp(NULL)
 {
-    poParent = poParentIn;
     CPLAssert(poParent->GetRasterDataType() == GDT_UInt16);
 
+    // Defined in GDALRasterBand.
     poDS = NULL;
     nBand = 0;
 
@@ -50,26 +58,20 @@ GDALRescaledAlphaBand::GDALRescaledAlphaBand( GDALRasterBand *poParentIn )
 
     eDataType = GDT_Byte;
     poParent->GetBlockSize( &nBlockXSize, &nBlockYSize );
-
-    pTemp = NULL;
 }
 
 /************************************************************************/
 /*                      ~GDALRescaledAlphaBand()                        */
 /************************************************************************/
 
-GDALRescaledAlphaBand::~GDALRescaledAlphaBand()
-
-{
-    VSIFree(pTemp);
-}
+GDALRescaledAlphaBand::~GDALRescaledAlphaBand() { VSIFree(pTemp); }
 
 /************************************************************************/
 /*                             IReadBlock()                             */
 /************************************************************************/
 
 CPLErr GDALRescaledAlphaBand::IReadBlock( int nXBlockOff, int nYBlockOff,
-                                         void * pImage )
+                                          void * pImage )
 {
     int nXSizeRequest = nBlockXSize;
     if (nXBlockOff * nBlockXSize + nBlockXSize > nRasterXSize)
@@ -81,55 +83,59 @@ CPLErr GDALRescaledAlphaBand::IReadBlock( int nXBlockOff, int nYBlockOff,
     GDALRasterIOExtraArg sExtraArg;
     INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
-    return IRasterIO(GF_Read, nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize,
-                     nXSizeRequest, nYSizeRequest, pImage,
-                     nXSizeRequest, nYSizeRequest, GDT_Byte,
-                     1, nBlockXSize, &sExtraArg);
+    return IRasterIO(
+        GF_Read, nXBlockOff * nBlockXSize, nYBlockOff * nBlockYSize,
+        nXSizeRequest, nYSizeRequest, pImage,
+        nXSizeRequest, nYSizeRequest, GDT_Byte,
+        1, nBlockXSize, &sExtraArg );
 }
 
 /************************************************************************/
 /*                             IRasterIO()                              */
 /************************************************************************/
 
-CPLErr GDALRescaledAlphaBand::IRasterIO( GDALRWFlag eRWFlag,
-                                      int nXOff, int nYOff, int nXSize, int nYSize,
-                                      void * pData, int nBufXSize, int nBufYSize,
-                                      GDALDataType eBufType,
-                                      GSpacing nPixelSpace,
-                                      GSpacing nLineSpace,
-                                      GDALRasterIOExtraArg* psExtraArg )
+CPLErr GDALRescaledAlphaBand::IRasterIO(
+    GDALRWFlag eRWFlag,
+    int nXOff, int nYOff, int nXSize, int nYSize,
+    void * pData, int nBufXSize, int nBufYSize,
+    GDALDataType eBufType,
+    GSpacing nPixelSpace,
+    GSpacing nLineSpace,
+    GDALRasterIOExtraArg* psExtraArg )
 {
-    /* Optimization in common use case */
-    /* This avoids triggering the block cache on this band, which helps */
-    /* reducing the global block cache consumption */
-    if (eRWFlag == GF_Read && eBufType == GDT_Byte &&
+    // Optimization in common use case.
+    // This avoids triggering the block cache on this band, which helps
+    // reducing the global block cache consumption.
+    if( eRWFlag == GF_Read && eBufType == GDT_Byte &&
         nXSize == nBufXSize && nYSize == nBufYSize &&
-        nPixelSpace == 1)
+        nPixelSpace == 1 )
     {
         if( pTemp == NULL )
         {
             pTemp = VSI_MALLOC2_VERBOSE( sizeof(GUInt16), nRasterXSize );
-            if (pTemp == NULL)
+            if( pTemp == NULL )
             {
                 return CE_Failure;
             }
         }
-        for(int j = 0; j < nBufYSize; j++ )
+        for( int j = 0; j < nBufYSize; j++ )
         {
-            CPLErr eErr = poParent->RasterIO( GF_Read, nXOff, nYOff + j, nXSize, 1,
-                                              pTemp, nBufXSize, 1,
-                                              GDT_UInt16,
-                                              0, 0, NULL );
-            if (eErr != CE_None)
+            const CPLErr eErr =
+                poParent->RasterIO( GF_Read, nXOff, nYOff + j, nXSize, 1,
+                                    pTemp, nBufXSize, 1,
+                                    GDT_UInt16,
+                                    0, 0, NULL );
+            if( eErr != CE_None )
                 return eErr;
 
-            GByte* pabyImage = ((GByte*) pData) + j * nLineSpace;
-            GUInt16* pSrc = (GUInt16 *)pTemp;
+            GByte* pabyImage = static_cast<GByte*>(pData) + j * nLineSpace;
+            GUInt16* pSrc = static_cast<GUInt16 *>(pTemp);
 
             for( int i = 0; i < nBufXSize; i++ )
             {
-                /* In case the dynamics was actually 0-255 and not 0-65535 as */
-                /* expected, we want to make sure non-zero alpha will still be non-zero */
+                // In case the dynamics was actually 0-255 and not 0-65535 as
+                // expected, we want to make sure non-zero alpha will still
+                // be non-zero.
                 if( pSrc[i] > 0 && pSrc[i] < 257 )
                     pabyImage[i] = 1;
                 else
@@ -144,3 +150,4 @@ CPLErr GDALRescaledAlphaBand::IRasterIO( GDALRWFlag eRWFlag,
                                       eBufType,
                                       nPixelSpace, nLineSpace, psExtraArg );
 }
+//! @endcond
diff --git a/gcore/gdalsse_priv.h b/gcore/gdalsse_priv.h
index ffc10ef..7db7ff8 100644
--- a/gcore/gdalsse_priv.h
+++ b/gcore/gdalsse_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalsse_priv.h 32173 2015-12-14 00:04:53Z goatbar $
+ * $Id: gdalsse_priv.h 34921 2016-08-04 22:26:31Z rouault $
  *
  * Project:  GDAL
  * Purpose:  SSE2 helper
@@ -30,6 +30,8 @@
 #ifndef GDALSSE_PRIV_H_INCLUDED
 #define GDALSSE_PRIV_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "cpl_port.h"
 
 /* We restrict to 64bit processors because they are guaranteed to have SSE2 */
@@ -40,6 +42,10 @@
 #include <emmintrin.h>
 #include <string.h>
 
+#ifdef __SSE4_1__
+#include <smmintrin.h>
+#endif
+
 class XMMReg2Double
 {
   public:
@@ -182,8 +188,12 @@ class XMMReg2Double
 #else
         __m128i xmm_i = _mm_cvtsi32_si128(*(unsigned short*)(ptr));
 #endif
+#ifdef __SSE4_1__
+        xmm_i = _mm_cvtepu8_epi32(xmm_i);
+#else
         xmm_i = _mm_unpacklo_epi8(xmm_i, _mm_setzero_si128());
         xmm_i = _mm_unpacklo_epi16(xmm_i, _mm_setzero_si128());
+#endif
         xmm = _mm_cvtepi32_pd(xmm_i);
     }
 
@@ -192,8 +202,12 @@ class XMMReg2Double
         int i;
         memcpy(&i, ptr, 4);
         __m128i xmm_i = _mm_cvtsi32_si128(i);
+#ifdef __SSE4_1__
+        xmm_i = _mm_cvtepi16_epi32(xmm_i);
+#else
         xmm_i = _mm_unpacklo_epi16(xmm_i,xmm_i); /* 0|0|0|0|0|0|b|a --> 0|0|0|0|b|b|a|a */
         xmm_i = _mm_srai_epi32(xmm_i, 16);       /* 0|0|0|0|b|b|a|a --> 0|0|0|0|sign(b)|b|sign(a)|a */
+#endif
         xmm = _mm_cvtepi32_pd(xmm_i);
     }
 
@@ -202,8 +216,11 @@ class XMMReg2Double
         int i;
         memcpy(&i, ptr, 4);
         __m128i xmm_i = _mm_cvtsi32_si128(i);
-        xmm_i = _mm_unpacklo_epi16(xmm_i,xmm_i); /* 0|0|0|0|0|0|b|a --> 0|0|0|0|b|b|a|a */
-        xmm_i = _mm_srli_epi32(xmm_i, 16);       /* 0|0|0|0|b|b|a|a --> 0|0|0|0|0|b|0|a */
+#ifdef __SSE4_1__
+        xmm_i = _mm_cvtepu16_epi32(xmm_i);
+#else
+        xmm_i = _mm_unpacklo_epi16(xmm_i,_mm_setzero_si128()); /* 0|0|0|0|0|0|b|a --> 0|0|0|0|0|b|0|a */
+#endif
         xmm = _mm_cvtepi32_pd(xmm_i);
     }
 
@@ -216,8 +233,12 @@ class XMMReg2Double
 #else
         __m128i xmm_i = _mm_cvtsi32_si128(*(int*)(ptr));
 #endif
+#ifdef __SSE4_1__
+        xmm_i = _mm_cvtepu8_epi32(xmm_i);
+#else
         xmm_i = _mm_unpacklo_epi8(xmm_i, _mm_setzero_si128());
         xmm_i = _mm_unpacklo_epi16(xmm_i, _mm_setzero_si128());
+#endif
         low.xmm = _mm_cvtepi32_pd(xmm_i);
         high.xmm =  _mm_cvtepi32_pd(_mm_shuffle_epi32(xmm_i,_MM_SHUFFLE(3,2,3,2)));
     }
@@ -852,4 +873,6 @@ class XMMReg4Double
     }
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* GDALSSE_PRIV_H_INCLUDED */
diff --git a/gcore/gdalvirtualmem.cpp b/gcore/gdalvirtualmem.cpp
index 0776d34..a0287b9 100644
--- a/gcore/gdalvirtualmem.cpp
+++ b/gcore/gdalvirtualmem.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: gdalvirtualmem.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Name:     gdalvirtualmem.cpp
  * Project:  GDAL
@@ -28,12 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gdal.h"
+#include "gdal_priv.h"
+
+#include <cstddef>
+#include <cstring>
+
+#include <algorithm>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_virtualmem.h"
-#include "gdal_priv.h"
 
-/* To be changed if we go to 64-bit RasterIO coordinates and spacing */
+// To be changed if we go to 64-bit RasterIO coordinates and spacing.
 typedef int coord_type;
 typedef int spacing_type;
 
@@ -47,8 +54,8 @@ class GDALVirtualMem
     GDALRasterBandH hBand;
     coord_type nXOff;
     coord_type nYOff;
-    /*int nXSize;
-    int nYSize;*/
+    // int nXSize;
+    // int nYSize;
     coord_type nBufXSize;
     coord_type nBufYSize;
     GDALDataType eBufType;
@@ -58,47 +65,52 @@ class GDALVirtualMem
     GIntBig nLineSpace;
     GIntBig nBandSpace;
 
-    int     bIsCompact;
-    int     bIsBandSequential;
+    bool bIsCompact;
+    bool bIsBandSequential;
 
-    int  IsCompact() const { return bIsCompact; }
-    int  IsBandSequential() const { return bIsBandSequential; }
+    bool IsCompact() const { return bIsCompact; }
+    bool IsBandSequential() const { return bIsBandSequential; }
 
-    void GetXYBand( size_t nOffset, coord_type& x, coord_type& y, int& band ) const;
-    size_t GetOffset(coord_type x, coord_type y, int band) const;
-    int  GotoNextPixel(coord_type& x, coord_type& y, int& band) const;
+    void GetXYBand( size_t nOffset, coord_type& x, coord_type& y,
+                    int& band ) const;
+    size_t GetOffset( coord_type x, coord_type y, int band ) const;
+    bool GotoNextPixel( coord_type& x, coord_type& y, int& band ) const;
 
     void DoIOBandSequential( GDALRWFlag eRWFlag, size_t nOffset,
-                              void* pPage, size_t nBytes ) const;
+                             void* pPage, size_t nBytes ) const;
     void DoIOPixelInterleaved( GDALRWFlag eRWFlag, size_t nOffset,
                                void* pPage, size_t nBytes ) const;
 
 public:
              GDALVirtualMem( GDALDatasetH hDS,
                              GDALRasterBandH hBand,
-                          coord_type nXOff, coord_type nYOff,
-                          coord_type nXSize, coord_type nYSize,
-                          coord_type nBufXSize, coord_type nBufYSize,
-                          GDALDataType eBufType,
-                          int nBandCount, const int* panBandMapIn,
-                          int nPixelSpace,
-                          GIntBig nLineSpace,
-                          GIntBig nBandSpace );
+                             coord_type nXOff, coord_type nYOff,
+                             coord_type nXSize, coord_type nYSize,
+                             coord_type nBufXSize, coord_type nBufYSize,
+                             GDALDataType eBufType,
+                             int nBandCount, const int* panBandMapIn,
+                             int nPixelSpace,
+                             GIntBig nLineSpace,
+                             GIntBig nBandSpace );
             ~GDALVirtualMem();
 
-    static void FillCacheBandSequential(CPLVirtualMem* ctxt,  size_t nOffset,
+    static void FillCacheBandSequential( CPLVirtualMem* ctxt,  size_t nOffset,
                                          void* pPageToFill,
-                                         size_t nToFill, void* pUserData);
-    static void SaveFromCacheBandSequential(CPLVirtualMem* ctxt,  size_t nOffset,
+                                         size_t nToFill, void* pUserData );
+    static void SaveFromCacheBandSequential( CPLVirtualMem* ctxt,
+                                             size_t nOffset,
                                              const void* pPageToBeEvicted,
-                                             size_t nToEvicted, void* pUserData);
-
-    static void FillCachePixelInterleaved(CPLVirtualMem* ctxt,  size_t nOffset,
-                                          void* pPageToFill,
-                                          size_t nToFill, void* pUserData);
-    static void SaveFromCachePixelInterleaved(CPLVirtualMem* ctxt,  size_t nOffset,
-                                              const void* pPageToBeEvicted,
-                                              size_t nToEvicted, void* pUserData);
+                                             size_t nToEvicted,
+                                             void* pUserData );
+
+    static void FillCachePixelInterleaved( CPLVirtualMem* ctxt, size_t nOffset,
+                                           void* pPageToFill,
+                                           size_t nToFill, void* pUserData );
+    static void SaveFromCachePixelInterleaved( CPLVirtualMem* ctxt,
+                                               size_t nOffset,
+                                               const void* pPageToBeEvicted,
+                                               size_t nToEvicted,
+                                               void* pUserData);
 
     static void Destroy(void* pUserData);
 };
@@ -110,30 +122,39 @@ public:
 GDALVirtualMem::GDALVirtualMem( GDALDatasetH hDSIn,
                                 GDALRasterBandH hBandIn,
                                 coord_type nXOffIn, coord_type nYOffIn,
-                                CPL_UNUSED coord_type nXSize,
-                                CPL_UNUSED coord_type nYSize,
+                                coord_type /* nXSize */,
+                                coord_type /* nYSize */,
                                 coord_type nBufXSizeIn, coord_type nBufYSizeIn,
                                 GDALDataType eBufTypeIn,
                                 int nBandCountIn, const int* panBandMapIn,
                                 int nPixelSpaceIn,
                                 GIntBig nLineSpaceIn,
                                 GIntBig nBandSpaceIn ) :
-    hDS(hDSIn), hBand(hBandIn), nXOff(nXOffIn), nYOff(nYOffIn), /*nXSize(nXSize), nYSize(nYSize),*/
-    nBufXSize(nBufXSizeIn), nBufYSize(nBufYSizeIn), eBufType(eBufTypeIn),
-    nBandCount(nBandCountIn), nPixelSpace(nPixelSpaceIn), nLineSpace(nLineSpaceIn),
+    hDS(hDSIn),
+    hBand(hBandIn),
+    nXOff(nXOffIn),
+    nYOff(nYOffIn),
+    // TODO(schwehr): Why not used or removed?
+    // nXSize(nXSize),
+    // nYSize(nYSize),
+    nBufXSize(nBufXSizeIn),
+    nBufYSize(nBufYSizeIn),
+    eBufType(eBufTypeIn),
+    nBandCount(nBandCountIn),
+    nPixelSpace(nPixelSpaceIn),
+    nLineSpace(nLineSpaceIn),
     nBandSpace(nBandSpaceIn)
 {
     if( hDS != NULL )
     {
+        panBandMap = static_cast<int *>( CPLMalloc(nBandCount * sizeof(int)) );
         if( panBandMapIn )
         {
-            panBandMap = (int*) CPLMalloc(nBandCount * sizeof(int));
             memcpy(panBandMap, panBandMapIn, nBandCount * sizeof(int));
         }
         else
         {
-            panBandMap = (int*) CPLMalloc(nBandCount * sizeof(int));
-            for(int i=0;i<nBandCount;i++)
+            for( int i = 0; i < nBandCount; i++ )
                 panBandMap[i] = i + 1;
         }
     }
@@ -145,17 +166,17 @@ GDALVirtualMem::GDALVirtualMem( GDALDatasetH hDSIn,
 
     const int nDataTypeSize = GDALGetDataTypeSizeBytes(eBufType);
     if( nPixelSpace == nDataTypeSize &&
-        nLineSpace == (GIntBig)nBufXSize * nPixelSpace &&
+        nLineSpace == static_cast<GIntBig>(nBufXSize) * nPixelSpace &&
         nBandSpace == nBufYSize * nLineSpace )
-        bIsCompact = TRUE;
+        bIsCompact = true;
     else if( nBandSpace == nDataTypeSize &&
-            nPixelSpace == nBandCount * nBandSpace &&
-            nLineSpace == (GIntBig)nBufXSize * nPixelSpace )
-        bIsCompact = TRUE;
+             nPixelSpace == nBandCount * nBandSpace &&
+             nLineSpace == static_cast<GIntBig>(nBufXSize) * nPixelSpace )
+        bIsCompact = true;
     else
-        bIsCompact = FALSE;
+        bIsCompact = false;
 
-    bIsBandSequential = ( nBandSpace >= nBufYSize * nLineSpace );
+    bIsBandSequential = nBandSpace >= nBufYSize * nLineSpace;
 }
 
 /************************************************************************/
@@ -171,25 +192,28 @@ GDALVirtualMem::~GDALVirtualMem()
 /*                              GetXYBand()                             */
 /************************************************************************/
 
-void GDALVirtualMem::GetXYBand( size_t nOffset, coord_type& x, coord_type& y, int& band ) const
+void GDALVirtualMem::GetXYBand( size_t nOffset, coord_type& x, coord_type& y,
+                                int& band ) const
 {
     if( IsBandSequential() )
     {
         if( nBandCount == 1 )
             band = 0;
         else
-            band = (int)(nOffset / nBandSpace);
-        y = (coord_type)((nOffset - band * nBandSpace) / nLineSpace);
-        x = (coord_type)((nOffset - band * nBandSpace - y * nLineSpace) / nPixelSpace);
+            band = static_cast<int>(nOffset / nBandSpace);
+        y = static_cast<coord_type>((nOffset - band * nBandSpace) / nLineSpace);
+        x = static_cast<coord_type>(
+            (nOffset - band * nBandSpace - y * nLineSpace) / nPixelSpace );
     }
     else
     {
-        y = (coord_type)(nOffset / nLineSpace);
-        x = (coord_type)((nOffset - y * nLineSpace) / nPixelSpace);
+        y = static_cast<coord_type>(nOffset / nLineSpace);
+        x = static_cast<coord_type>((nOffset - y * nLineSpace) / nPixelSpace);
         if( nBandCount == 1 )
             band = 0;
         else
-            band = (int)((nOffset - y * nLineSpace - x * nPixelSpace) / nBandSpace);
+            band = static_cast<int>(
+                (nOffset - y * nLineSpace - x * nPixelSpace) / nBandSpace);
     }
 }
 
@@ -197,7 +221,8 @@ void GDALVirtualMem::GetXYBand( size_t nOffset, coord_type& x, coord_type& y, in
 /*                            GotoNextPixel()                           */
 /************************************************************************/
 
-int GDALVirtualMem::GotoNextPixel(coord_type& x, coord_type& y, int& band) const
+bool GDALVirtualMem::GotoNextPixel( coord_type& x, coord_type& y,
+                                    int& band ) const
 {
     if( IsBandSequential() )
     {
@@ -211,8 +236,8 @@ int GDALVirtualMem::GotoNextPixel(coord_type& x, coord_type& y, int& band) const
         {
             y = 0;
             band ++;
-            if (band == nBandCount)
-                return FALSE;
+            if( band == nBandCount )
+                return false;
         }
     }
     else
@@ -227,11 +252,11 @@ int GDALVirtualMem::GotoNextPixel(coord_type& x, coord_type& y, int& band) const
         {
             x = 0;
             y ++;
-            if(y == nBufYSize)
-                return FALSE;
+            if( y == nBufYSize )
+                return false;
         }
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -240,22 +265,26 @@ int GDALVirtualMem::GotoNextPixel(coord_type& x, coord_type& y, int& band) const
 
 size_t GDALVirtualMem::GetOffset(coord_type x, coord_type y, int band) const
 {
-    return (size_t)(x * nPixelSpace + y * nLineSpace + band * nBandSpace);
+    return static_cast<size_t>(
+        x * nPixelSpace + y * nLineSpace + band * nBandSpace);
 }
 
 /************************************************************************/
 /*                          DoIOPixelInterleaved()                      */
 /************************************************************************/
 
-void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
-                        const size_t nOffset, void* pPage, size_t nBytes ) const
+void GDALVirtualMem::DoIOPixelInterleaved(
+    GDALRWFlag eRWFlag, const size_t nOffset, void* pPage, size_t nBytes ) const
 {
-    coord_type x, y;
-    int band;
+    coord_type x = 0;
+    coord_type y = 0;
+    int band = 0;
 
     GetXYBand(nOffset, x, y, band);
-    /*fprintf(stderr, "eRWFlag=%d, nOffset=%d, x=%d, y=%d, band=%d\n",
-            eRWFlag, (int)nOffset, x, y, band);*/
+#ifdef DEBUG_VERBOSE
+    fprintf(stderr, "eRWFlag=%d, nOffset=%d, x=%d, y=%d, band=%d\n",/*ok*/
+            eRWFlag, static_cast<int>(nOffset), x, y, band);
+#endif
 
     if( eRWFlag == GF_Read && !IsCompact() )
         memset(pPage, 0, nBytes);
@@ -285,7 +314,7 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
     if( band > 0 )
     {
         size_t nEndOffsetEndOfPixel = GetOffset(x, y, nBandCount);
-        int bandEnd;
+        int bandEnd = nBandCount;
         // Check that we have enough space to load/store until last band
         // Should be always OK unless the number of bands is really huge
         if( nEndOffsetEndOfPixel - nOffset > nBytes )
@@ -296,16 +325,17 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
             CPLAssert(x == xEnd);
             CPLAssert(y == yEnd);
         }
-        else
-            bandEnd = nBandCount;
 
         // Finish reading/writing the remaining bands for that pixel
-        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
-                            nXOff + x, nYOff + y, 1, 1,
-                            (char*)pPage + nOffsetShift,
-                            1, 1, eBufType,
-                            bandEnd - band, panBandMap + band,
-                            nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
+        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO(
+            hDS, eRWFlag,
+            nXOff + x, nYOff + y, 1, 1,
+            static_cast<char *>(pPage) + nOffsetShift,
+            1, 1, eBufType,
+            bandEnd - band, panBandMap + band,
+            nPixelSpace,
+            static_cast<spacing_type>(nLineSpace),
+            static_cast<spacing_type>(nBandSpace) ));
 
         if( bandEnd < nBandCount )
             return;
@@ -331,12 +361,15 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
 
         if( x < xEnd )
         {
-            CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
-                                nXOff + x, nYOff + y, xEnd - x, 1,
-                                (char*) pPage + nOffsetShift,
-                                xEnd - x, 1, eBufType,
-                                nBandCount, panBandMap,
-                                nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
+            CPL_IGNORE_RET_VAL(GDALDatasetRasterIO(
+                hDS, eRWFlag,
+                nXOff + x, nYOff + y, xEnd - x, 1,
+                static_cast<char *>(pPage) + nOffsetShift,
+                xEnd - x, 1, eBufType,
+                nBandCount, panBandMap,
+                nPixelSpace,
+                static_cast<spacing_type>(nLineSpace),
+                static_cast<spacing_type>(nBandSpace) ));
         }
 
         // Are there partial bands to read/write for the last pixel ?
@@ -351,26 +384,32 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
             if( bandEnd >= nBandCount )
                 bandEnd = nBandCount;
 
-            CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
-                                nXOff + x, nYOff + y, 1, 1,
-                                (char*) pPage + nOffsetShift,
-                                1, 1, eBufType,
-                                bandEnd, panBandMap,
-                                nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
+            CPL_IGNORE_RET_VAL(GDALDatasetRasterIO(
+                hDS, eRWFlag,
+                nXOff + x, nYOff + y, 1, 1,
+                static_cast<char *>(pPage) + nOffsetShift,
+                1, 1, eBufType,
+                bandEnd, panBandMap,
+                nPixelSpace,
+                static_cast<spacing_type>(nLineSpace),
+                static_cast<spacing_type>(nBandSpace) ));
         }
 
         return;
     }
 
     // Yes, enough place to read/write until end of line
-    if( x > 0 || nBytes - nOffsetShift < (size_t)nLineSpace )
+    if( x > 0 || nBytes - nOffsetShift < static_cast<size_t>(nLineSpace) )
     {
-        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
-                    nXOff + x, nYOff + y, nBufXSize - x, 1,
-                    (char*)pPage + nOffsetShift,
-                    nBufXSize - x, 1, eBufType,
-                    nBandCount, panBandMap,
-                    nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
+        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO(
+            hDS, eRWFlag,
+            nXOff + x, nYOff + y, nBufXSize - x, 1,
+            static_cast<char *>(pPage) + nOffsetShift,
+            nBufXSize - x, 1, eBufType,
+            nBandCount, panBandMap,
+            nPixelSpace,
+            static_cast<spacing_type>(nLineSpace),
+            static_cast<spacing_type>(nBandSpace) ) );
 
         // Go to beginning of next line
         x = nBufXSize - 1;
@@ -389,12 +428,15 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
         nLineCount = nBufYSize - y;
     if( nLineCount > 0 )
     {
-        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
-                             nXOff + 0, nYOff + y, nBufXSize, nLineCount,
-                             (GByte*) pPage + nOffsetShift,
-                             nBufXSize, nLineCount, eBufType,
-                             nBandCount, panBandMap,
-                             nPixelSpace, (spacing_type)nLineSpace, (spacing_type)nBandSpace ));
+        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO(
+            hDS, eRWFlag,
+            nXOff + 0, nYOff + y, nBufXSize, nLineCount,
+            static_cast<GByte *>(pPage) + nOffsetShift,
+            nBufXSize, nLineCount, eBufType,
+            nBandCount, panBandMap,
+            nPixelSpace,
+            static_cast<spacing_type>(nLineSpace),
+            static_cast<spacing_type>(nBandSpace) ) );
 
         y += nLineCount;
         if( y == nBufYSize )
@@ -405,8 +447,10 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
 
     if( nOffsetShift < nBytes )
     {
-        DoIOPixelInterleaved( eRWFlag, nOffsetRecompute,
-               (char*) pPage + nOffsetShift, nBytes - nOffsetShift );
+        DoIOPixelInterleaved(
+            eRWFlag, nOffsetRecompute,
+            static_cast<char*>(pPage) + nOffsetShift,
+            nBytes - nOffsetShift );
     }
 }
 
@@ -414,15 +458,18 @@ void GDALVirtualMem::DoIOPixelInterleaved( GDALRWFlag eRWFlag,
 /*                          DoIOPixelInterleaved()                      */
 /************************************************************************/
 
-void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
-                        const size_t nOffset, void* pPage, size_t nBytes ) const
+void GDALVirtualMem::DoIOBandSequential(
+    GDALRWFlag eRWFlag, const size_t nOffset, void* pPage, size_t nBytes ) const
 {
-    coord_type x, y;
-    int band;
+    coord_type x = 0;
+    coord_type y = 0;
 
+    int band = 0;
     GetXYBand(nOffset, x, y, band);
-    /*fprintf(stderr, "eRWFlag=%d, nOffset=%d, x=%d, y=%d, band=%d\n",
-            eRWFlag, (int)nOffset, x, y, band);*/
+#if DEBUG_VERBOSE
+    fprintf( stderr, "eRWFlag=%d, nOffset=%d, x=%d, y=%d, band=%d\n",/*ok*/
+             eRWFlag, static_cast<int>(nOffset), x, y, band );
+#endif
 
     if( eRWFlag == GF_Read && !IsCompact() )
         memset(pPage, 0, nBytes);
@@ -447,7 +494,7 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
     if( nOffsetShift >= nBytes )
         return;
 
-    // Is there enough place to store/load up to the end of current line ?
+    // Is there enough place to store/load up to the end of current line?
     size_t nEndOffsetEndOfLine = GetOffset(nBufXSize, y, band);
     if( nEndOffsetEndOfLine - nOffset > nBytes )
     {
@@ -457,11 +504,13 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
         GetXYBand(nOffset + nBytes, xEnd, yEnd, bandEnd);
         CPLAssert(y == yEnd);
         CPLAssert(band == bandEnd);
-        CPL_IGNORE_RET_VAL(GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
-                      nXOff + x, nYOff + y, xEnd - x, 1,
-                      (char*)pPage + nOffsetShift,
-                      xEnd - x, 1, eBufType,
-                      nPixelSpace, (spacing_type)nLineSpace ));
+        CPL_IGNORE_RET_VAL(GDALRasterIO(
+            hBand ? hBand : GDALGetRasterBand(hDS, panBandMap[band]),
+            eRWFlag,
+            nXOff + x, nYOff + y, xEnd - x, 1,
+            static_cast<char *>(pPage) + nOffsetShift,
+            xEnd - x, 1, eBufType,
+            nPixelSpace, static_cast<spacing_type>(nLineSpace) ));
 
         return;
     }
@@ -469,11 +518,13 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
     // Yes, enough place to read/write until end of line
     if( x > 0 || nBytes - nOffsetShift < (size_t)nLineSpace )
     {
-        CPL_IGNORE_RET_VAL(GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
+        CPL_IGNORE_RET_VAL(GDALRasterIO(
+            hBand ? hBand : GDALGetRasterBand(hDS, panBandMap[band]),
+            eRWFlag,
                     nXOff + x, nYOff + y, nBufXSize - x, 1,
-                    (char*)pPage + nOffsetShift,
+                    static_cast<char *>(pPage) + nOffsetShift,
                     nBufXSize - x, 1, eBufType,
-                    nPixelSpace, (spacing_type)nLineSpace ));
+                    nPixelSpace, static_cast<spacing_type>(nLineSpace) ));
 
         // Go to beginning of next line
         x = nBufXSize - 1;
@@ -491,11 +542,14 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
         nLineCount = nBufYSize - y;
     if( nLineCount > 0 )
     {
-        CPL_IGNORE_RET_VAL(GDALRasterIO( (hBand) ? hBand : GDALGetRasterBand(hDS, panBandMap[band]), eRWFlag,
-                    nXOff + 0, nYOff + y, nBufXSize, nLineCount,
-                    (GByte*) pPage + nOffsetShift,
-                    nBufXSize, nLineCount, eBufType,
-                    nPixelSpace, (spacing_type)nLineSpace ));
+        CPL_IGNORE_RET_VAL(GDALRasterIO(
+            hBand ? hBand : GDALGetRasterBand(hDS, panBandMap[band]),
+            eRWFlag,
+            nXOff + 0, nYOff + y, nBufXSize, nLineCount,
+            static_cast<GByte *>(pPage) + nOffsetShift,
+            nBufXSize, nLineCount, eBufType,
+            nPixelSpace,
+            static_cast<spacing_type>(nLineSpace) ) );
 
         y += nLineCount;
         if( y == nBufYSize )
@@ -520,13 +574,14 @@ void GDALVirtualMem::DoIOBandSequential( GDALRWFlag eRWFlag,
 /*                    FillCacheBandSequential()                        */
 /************************************************************************/
 
-void GDALVirtualMem::FillCacheBandSequential(CPLVirtualMem*,
-                  size_t nOffset,
-                  void* pPageToFill,
-                  size_t nToFill,
-                  void* pUserData)
+void GDALVirtualMem::FillCacheBandSequential(
+    CPLVirtualMem*,
+    size_t nOffset,
+    void* pPageToFill,
+    size_t nToFill,
+    void* pUserData )
 {
-    const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
+    const GDALVirtualMem* psParms = static_cast<GDALVirtualMem *>(pUserData);
     psParms->DoIOBandSequential(GF_Read, nOffset, pPageToFill, nToFill);
 }
 
@@ -534,27 +589,30 @@ void GDALVirtualMem::FillCacheBandSequential(CPLVirtualMem*,
 /*                    SaveFromCacheBandSequential()                    */
 /************************************************************************/
 
-void GDALVirtualMem::SaveFromCacheBandSequential(CPLVirtualMem*,
-                  size_t nOffset,
-                  const void* pPageToBeEvicted,
-                  size_t nToEvicted,
-                  void* pUserData)
+void GDALVirtualMem::SaveFromCacheBandSequential(
+    CPLVirtualMem*,
+    size_t nOffset,
+    const void* pPageToBeEvicted,
+    size_t nToEvicted,
+    void* pUserData )
 {
-    const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
-    psParms->DoIOBandSequential(GF_Write, nOffset, (void*)pPageToBeEvicted, nToEvicted);
+    const GDALVirtualMem* psParms = static_cast<GDALVirtualMem *>(pUserData);
+    psParms->DoIOBandSequential(
+        GF_Write, nOffset, const_cast<void *>(pPageToBeEvicted), nToEvicted);
 }
 
 /************************************************************************/
 /*                     FillCachePixelInterleaved()                      */
 /************************************************************************/
 
-void GDALVirtualMem::FillCachePixelInterleaved(CPLVirtualMem*,
-                  size_t nOffset,
-                  void* pPageToFill,
-                  size_t nToFill,
-                  void* pUserData)
+void GDALVirtualMem::FillCachePixelInterleaved(
+    CPLVirtualMem*,
+    size_t nOffset,
+    void* pPageToFill,
+    size_t nToFill,
+    void* pUserData )
 {
-    const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
+    const GDALVirtualMem* psParms = static_cast<GDALVirtualMem *>(pUserData);
     psParms->DoIOPixelInterleaved(GF_Read, nOffset, pPageToFill, nToFill);
 }
 
@@ -562,14 +620,16 @@ void GDALVirtualMem::FillCachePixelInterleaved(CPLVirtualMem*,
 /*                     SaveFromCachePixelInterleaved()                  */
 /************************************************************************/
 
-void GDALVirtualMem::SaveFromCachePixelInterleaved(CPLVirtualMem*,
-                  size_t nOffset,
-                  const void* pPageToBeEvicted,
-                  size_t nToEvicted,
-                  void* pUserData)
+void GDALVirtualMem::SaveFromCachePixelInterleaved(
+    CPLVirtualMem*,
+    size_t nOffset,
+    const void* pPageToBeEvicted,
+    size_t nToEvicted,
+    void* pUserData )
 {
-    const GDALVirtualMem* psParms = (const GDALVirtualMem* )pUserData;
-    psParms->DoIOPixelInterleaved(GF_Write, nOffset, (void*)pPageToBeEvicted, nToEvicted);
+    const GDALVirtualMem* psParms = static_cast<GDALVirtualMem *>(pUserData);
+    psParms->DoIOPixelInterleaved(
+        GF_Write, nOffset, const_cast<void *>(pPageToBeEvicted), nToEvicted);
 }
 
 /************************************************************************/
@@ -578,7 +638,7 @@ void GDALVirtualMem::SaveFromCachePixelInterleaved(CPLVirtualMem*,
 
 void GDALVirtualMem::Destroy(void* pUserData)
 {
-    GDALVirtualMem* psParams = (GDALVirtualMem*) pUserData;
+    GDALVirtualMem* psParams = static_cast<GDALVirtualMem *>( pUserData );
     delete psParams;
 }
 
@@ -591,26 +651,26 @@ static bool GDALCheckBandParameters( GDALDatasetH hDS,
 {
     if( nBandCount == 0 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "nBandCount == 0");
+        CPLError( CE_Failure, CPLE_AppDefined, "nBandCount == 0" );
         return false;
     }
 
     if( panBandMap != NULL )
     {
-        for(int i=0;i<nBandCount;i++)
+        for( int i = 0; i < nBandCount; i++ )
         {
             if( panBandMap[i] < 1 || panBandMap[i] > GDALGetRasterCount(hDS) )
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "panBandMap[%d]=%d",
-                        i, panBandMap[i]);
+                CPLError( CE_Failure, CPLE_AppDefined, "panBandMap[%d]=%d",
+                          i, panBandMap[i] );
                 return false;
             }
         }
     }
     else if( nBandCount > GDALGetRasterCount(hDS) )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                "nBandCount > GDALGetRasterCount(hDS)");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                 "nBandCount > GDALGetRasterCount(hDS)" );
         return false;
     }
     return true;
@@ -625,7 +685,8 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
                                          GDALRWFlag eRWFlag,
                                          coord_type nXOff, coord_type nYOff,
                                          coord_type nXSize, coord_type nYSize,
-                                         coord_type nBufXSize, coord_type nBufYSize,
+                                         coord_type nBufXSize,
+                                         coord_type nBufYSize,
                                          GDALDataType eBufType,
                                          int nBandCount, int* panBandMap,
                                          int nPixelSpace,
@@ -636,19 +697,21 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
                                          int bSingleThreadUsage,
                                          char ** /*papszOptions*/ )
 {
-    CPLVirtualMem* view;
-    GDALVirtualMem* psParams;
-    GUIntBig nReqMem;
+    CPLVirtualMem* view = NULL;
+    GDALVirtualMem* psParams = NULL;
+    GUIntBig nReqMem = 0;
 
     if( nXSize != nBufXSize || nYSize != nBufYSize )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "nXSize != nBufXSize || nYSize != nBufYSize");
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "nXSize != nBufXSize || nYSize != nBufYSize" );
         return NULL;
     }
 
-    int nRasterXSize = (hDS) ? GDALGetRasterXSize(hDS) : GDALGetRasterBandXSize(hBand);
-    int nRasterYSize = (hDS) ? GDALGetRasterYSize(hDS) : GDALGetRasterBandYSize(hBand);
+    int nRasterXSize =
+        hDS ? GDALGetRasterXSize(hDS) : GDALGetRasterBandXSize(hBand);
+    int nRasterYSize =
+        hDS ? GDALGetRasterYSize(hDS) : GDALGetRasterBandYSize(hBand);
 
     if( nXOff < 0 || nYOff < 0 ||
         nXSize == 0 || nYSize == 0 ||
@@ -656,14 +719,14 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
         nXOff + nXSize > nRasterXSize ||
         nYOff + nYSize > nRasterYSize )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Invalid window request");
+        CPLError( CE_Failure, CPLE_AppDefined, "Invalid window request" );
         return NULL;
     }
 
     if( nPixelSpace < 0 || nLineSpace < 0 || nBandSpace < 0)
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                "nPixelSpace < 0 || nLineSpace < 0 || nBandSpace < 0");
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "nPixelSpace < 0 || nLineSpace < 0 || nBandSpace < 0" );
         return NULL;
     }
 
@@ -674,35 +737,40 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
     if( nPixelSpace == 0 )
         nPixelSpace = nDataTypeSize;
     if( nLineSpace == 0 )
-        nLineSpace = (GIntBig)nBufXSize * nPixelSpace;
+        nLineSpace = static_cast<GIntBig>(nBufXSize) * nPixelSpace;
     if( nBandSpace == 0 )
-        nBandSpace = (GIntBig)nBufYSize * nLineSpace;
-
-    // OFFSET = offset(x,y,band) = x * nPixelSpace + y * nLineSpace + band * nBandSpace
-    // where 0 <= x < nBufXSize and 0 <= y < nBufYSize and 0 <= band < nBandCount
-    // if nPixelSpace, nLineSpace and nBandSpace can have arbitrary values, there's
-    // no way of finding a unique(x,y,band) solution. We need to restrict the
-    // space of possibilities strongly.
-    // if nBandSpace >= nBufYSize * nLineSpace and nLineSpace >= nBufXSize * nPixelSpace,           INTERLEAVE = BAND
+        nBandSpace = static_cast<GIntBig>(nBufYSize) * nLineSpace;
+
+    // OFFSET = offset(x,y,band) = x * nPixelSpace + y * nLineSpace + band *
+    // nBandSpace where 0 <= x < nBufXSize and 0 <= y < nBufYSize and 0 <= band
+    // < nBandCount if nPixelSpace, nLineSpace and nBandSpace can have arbitrary
+    // values, there is no way of finding a unique(x,y,band) solution. We need
+    // to restrict the space of possibilities strongly.
+    // if nBandSpace >= nBufYSize * nLineSpace and
+    //   nLineSpace >= nBufXSize * nPixelSpace,           INTERLEAVE = BAND
     //      band = OFFSET / nBandSpace
     //      y = (OFFSET - band * nBandSpace) / nLineSpace
     //      x = (OFFSET - band * nBandSpace - y * nLineSpace) / nPixelSpace
-    // else if nPixelSpace >= nBandCount * nBandSpace and nLineSpace >= nBufXSize * nPixelSpace,    INTERLEAVE = PIXEL
+    // else if nPixelSpace >= nBandCount * nBandSpace and
+    //   nLineSpace >= nBufXSize * nPixelSpace,    INTERLEAVE = PIXEL
     //      y = OFFSET / nLineSpace
     //      x = (OFFSET - y * nLineSpace) / nPixelSpace
     //      band = (OFFSET - y * nLineSpace - x * nPixelSpace) / nBandSpace
 
     if( nDataTypeSize == 0 || /* to please Coverity. not needed */
-        nLineSpace < (GIntBig)nBufXSize * nPixelSpace ||
+        nLineSpace < static_cast<GIntBig>(nBufXSize) * nPixelSpace ||
         (nBandCount > 1 &&
         (nBandSpace == nPixelSpace ||
         (nBandSpace < nPixelSpace &&
-         (nBandSpace < nDataTypeSize || nPixelSpace < nBandCount * nBandSpace)) ||
+         (nBandSpace < nDataTypeSize ||
+          nPixelSpace < nBandCount * nBandSpace)) ||
         (nBandSpace > nPixelSpace &&
-         (nPixelSpace < nDataTypeSize || nBandSpace < nBufYSize * nLineSpace)))) )
+         (nPixelSpace < nDataTypeSize ||
+          nBandSpace < nBufYSize * nLineSpace)))) )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Only pixel interleaving or band interleaving are supported");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Only pixel interleaving or band interleaving are supported" );
         return NULL;
     }
 
@@ -713,43 +781,45 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
         (nLineSpace % nDataTypeSize) != 0 ||
         (nBandSpace % nDataTypeSize) != 0 )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                    "Unsupported spacing");
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Unsupported spacing" );
         return NULL;
     }
 
-    int bIsBandSequential = ( nBandSpace >= nBufYSize * nLineSpace );
+    bool bIsBandSequential = nBandSpace >= nBufYSize * nLineSpace;
     if( bIsBandSequential )
         nReqMem = nBandCount * nBandSpace;
     else
         nReqMem = nBufYSize * nLineSpace;
     if( nReqMem != (GUIntBig)(size_t)nReqMem )
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot reserve " CPL_FRMT_GUIB " bytes", nReqMem);
+        CPLError( CE_Failure, CPLE_OutOfMemory,
+                  "Cannot reserve " CPL_FRMT_GUIB " bytes", nReqMem );
         return NULL;
     }
 
-    psParams = new GDALVirtualMem(hDS, hBand, nXOff, nYOff,
-                               nXSize, nYSize,
-                               nBufXSize, nBufYSize,
-                               eBufType,
-                               nBandCount, panBandMap,
-                               nPixelSpace,
-                               nLineSpace,
-                               nBandSpace);
-
-    view = CPLVirtualMemNew((size_t)nReqMem,
-                         nCacheSize,
-                         nPageSizeHint,
-                         bSingleThreadUsage,
-                         (eRWFlag == GF_Read) ? VIRTUALMEM_READONLY_ENFORCED : VIRTUALMEM_READWRITE,
-                         (bIsBandSequential) ? GDALVirtualMem::FillCacheBandSequential :
-                                                GDALVirtualMem::FillCachePixelInterleaved,
-                         (bIsBandSequential) ? GDALVirtualMem::SaveFromCacheBandSequential :
-                                                GDALVirtualMem::SaveFromCachePixelInterleaved,
-                         GDALVirtualMem::Destroy,
-                         psParams);
+    psParams = new GDALVirtualMem( hDS, hBand, nXOff, nYOff,
+                                   nXSize, nYSize,
+                                   nBufXSize, nBufYSize,
+                                   eBufType,
+                                   nBandCount, panBandMap,
+                                   nPixelSpace,
+                                   nLineSpace,
+                                   nBandSpace );
+
+    view = CPLVirtualMemNew(
+        static_cast<size_t>(nReqMem),
+        nCacheSize,
+        nPageSizeHint,
+        bSingleThreadUsage,
+        eRWFlag == GF_Read ?
+        VIRTUALMEM_READONLY_ENFORCED : VIRTUALMEM_READWRITE,
+        bIsBandSequential ? GDALVirtualMem::FillCacheBandSequential :
+                            GDALVirtualMem::FillCachePixelInterleaved,
+        bIsBandSequential ? GDALVirtualMem::SaveFromCacheBandSequential :
+                            GDALVirtualMem::SaveFromCachePixelInterleaved,
+        GDALVirtualMem::Destroy,
+        psParams );
 
     if( view == NULL )
     {
@@ -777,16 +847,17 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
  * CPLVirtualMemGetAddr(). It remains valid until CPLVirtualMemFree() is called.
  * CPLVirtualMemFree() must be called before the dataset object is destroyed.
  *
- * If p is such a pointer and base_type the C type matching eBufType, for default
- * values of spacing parameters, the element of image coordinates (x, y)
+ * If p is such a pointer and base_type the C type matching eBufType, for
+ * default values of spacing parameters, the element of image coordinates (x, y)
  * (relative to xOff, yOff) for band b can be accessed with
  * ((base_type*)p)[x + y * nBufXSize + (b-1)*nBufXSize*nBufYSize].
  *
  * Note that the mechanism used to transparently fill memory pages when they are
  * accessed is the same (but in a controlled way) than what occurs when a memory
- * error occurs in a program. Debugging software will generally interrupt program
- * execution when that happens. If needed, CPLVirtualMemPin() can be used to avoid
- * that by ensuring memory pages are allocated before being accessed.
+ * error occurs in a program. Debugging software will generally interrupt
+ * program execution when that happens. If needed, CPLVirtualMemPin() can be
+ * used to avoid that by ensuring memory pages are allocated before being
+ * accessed.
  *
  * The size of the region that can be mapped as a virtual memory object depends
  * on hardware and operating system limitations.
@@ -844,12 +915,12 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
  * nBandCount bands.
  *
  * @param nPixelSpace The byte offset from the start of one pixel value in
- * the buffer to the start of the next pixel value within a scanline. If defaulted
- * (0) the size of the datatype eBufType is used.
+ * the buffer to the start of the next pixel value within a scanline. If
+ * defaulted (0) the size of the datatype eBufType is used.
  *
  * @param nLineSpace The byte offset from the start of one scanline in
- * the buffer to the start of the next. If defaulted (0) the size of the datatype
- * eBufType * nBufXSize is used.
+ * the buffer to the start of the next. If defaulted (0) the size of the
+ * datatype eBufType * nBufXSize is used.
  *
  * @param nBandSpace the byte offset from the start of one bands data to the
  * start of the next. If defaulted (0) the value will be
@@ -865,8 +936,8 @@ static CPLVirtualMem* GDALGetVirtualMem( GDALDatasetH hDS,
  *                      let the function determine a default page size.
  *
  * @param bSingleThreadUsage set to TRUE if there will be no concurrent threads
- *                           that will access the virtual memory mapping. This can
- *                           optimize performance a bit. If set to FALSE,
+ *                           that will access the virtual memory mapping. This
+ *                           can optimize performance a bit. If set to FALSE,
  *                           CPLVirtualMemDeclareThread() must be called.
  *
  * @param papszOptions NULL terminated list of options. Unused for now.
@@ -916,18 +987,20 @@ CPLVirtualMem* GDALDatasetGetVirtualMem( GDALDatasetH hDS,
  *
  * The pointer to access the virtual memory object is obtained with
  * CPLVirtualMemGetAddr(). It remains valid until CPLVirtualMemFree() is called.
- * CPLVirtualMemFree() must be called before the raster band object is destroyed.
+ * CPLVirtualMemFree() must be called before the raster band object is
+ * destroyed.
  *
- * If p is such a pointer and base_type the C type matching eBufType, for default
+ * If p is such a pointer and base_type the C type matching eBufType, for
  * values of spacing parameters, the element of image coordinates (x, y)
- * (relative to xOff, yOff) can be accessed with
+ * default (relative to xOff, yOff) can be accessed with
  * ((base_type*)p)[x + y * nBufXSize].
  *
  * Note that the mechanism used to transparently fill memory pages when they are
  * accessed is the same (but in a controlled way) than what occurs when a memory
- * error occurs in a program. Debugging software will generally interrupt program
- * execution when that happens. If needed, CPLVirtualMemPin() can be used to avoid
- * that by ensuring memory pages are allocated before being accessed.
+ * error occurs in a program. Debugging software will generally interrupt
+ * program execution when that happens. If needed, CPLVirtualMemPin() can be
+ * used to avoid that by ensuring memory pages are allocated before being
+ * accessed.
  *
  * The size of the region that can be mapped as a virtual memory object depends
  * on hardware and operating system limitations.
@@ -943,9 +1016,10 @@ CPLVirtualMem* GDALDatasetGetVirtualMem( GDALDatasetH hDS,
  * buffer size (nBufXSize x nBufYSize).
  *
  * The nPixelSpace and nLineSpace parameters allow reading into or
- * writing from various organization of buffers. Arbitrary values for the spacing
- * parameters are not supported. Those values must be multiple of the size of the
- * buffer data type and must be such that nLineSpace >= nPixelSpace * nBufXSize.
+ * writing from various organization of buffers. Arbitrary values for the
+ * spacing parameters are not supported. Those values must be multiple of the
+ * size of the buffer data type and must be such that nLineSpace >=
+ * nPixelSpace * nBufXSize.
  *
  * @param hBand Rasterband object
  *
@@ -972,12 +1046,12 @@ CPLVirtualMem* GDALDatasetGetVirtualMem( GDALDatasetH hDS,
  * pixel values will automatically be translated to/from the GDALRasterBand
  * data type as needed.
  *
- * @param nPixelSpace The byte offset from the start of one pixel value in
- * the buffer to the start of the next pixel value within a scanline. If defaulted
+ * @param nPixelSpace The byte offset from the start of one pixel value in the
+ * buffer to the start of the next pixel value within a scanline. If defaulted
  * (0) the size of the datatype eBufType is used.
  *
- * @param nLineSpace The byte offset from the start of one scanline in
- * the buffer to the start of the next. If defaulted (0) the size of the datatype
+ * @param nLineSpace The byte offset from the start of one scanline in the
+ * buffer to the start of the next. If defaulted (0) the size of the datatype
  * eBufType * nBufXSize is used.
  *
  * @param nCacheSize   size in bytes of the maximum memory that will be really
@@ -989,8 +1063,8 @@ CPLVirtualMem* GDALDatasetGetVirtualMem( GDALDatasetH hDS,
  *                      let the function determine a default page size.
  *
  * @param bSingleThreadUsage set to TRUE if there will be no concurrent threads
- *                           that will access the virtual memory mapping. This can
- *                           optimize performance a bit. If set to FALSE,
+ *                           that will access the virtual memory mapping. This
+ *                           can optimize performance a bit. If set to FALSE,
  *                           CPLVirtualMemDeclareThread() must be called.
  *
  * @param papszOptions NULL terminated list of options. Unused for now.
@@ -1002,19 +1076,20 @@ CPLVirtualMem* GDALDatasetGetVirtualMem( GDALDatasetH hDS,
  */
 
 CPLVirtualMem* GDALRasterBandGetVirtualMem( GDALRasterBandH hBand,
-                                         GDALRWFlag eRWFlag,
-                                         int nXOff, int nYOff,
-                                         int nXSize, int nYSize,
-                                         int nBufXSize, int nBufYSize,
-                                         GDALDataType eBufType,
-                                         int nPixelSpace,
-                                         GIntBig nLineSpace,
-                                         size_t nCacheSize,
-                                         size_t nPageSizeHint,
-                                         int bSingleThreadUsage,
-                                         char **papszOptions )
+                                            GDALRWFlag eRWFlag,
+                                            int nXOff, int nYOff,
+                                            int nXSize, int nYSize,
+                                            int nBufXSize, int nBufYSize,
+                                            GDALDataType eBufType,
+                                            int nPixelSpace,
+                                            GIntBig nLineSpace,
+                                            size_t nCacheSize,
+                                            size_t nPageSizeHint,
+                                            int bSingleThreadUsage,
+                                            char **papszOptions )
 {
-    return GDALGetVirtualMem( NULL, hBand, eRWFlag, nXOff, nYOff, nXSize, nYSize,
+    return GDALGetVirtualMem( NULL, hBand, eRWFlag, nXOff, nYOff,
+                              nXSize, nYSize,
                               nBufXSize, nBufYSize, eBufType,
                               1, NULL,
                               nPixelSpace, nLineSpace, 0,
@@ -1055,43 +1130,51 @@ public:
                                   GDALTileOrganization eTileOrganization );
             ~GDALTiledVirtualMem();
 
-    static void FillCache(CPLVirtualMem* ctxt,  size_t nOffset,
-                                         void* pPageToFill,
-                                         size_t nPageSize, void* pUserData);
-    static void SaveFromCache(CPLVirtualMem* ctxt,  size_t nOffset,
-                                             const void* pPageToBeEvicted,
-                                             size_t nToEvicted, void* pUserData);
+    static void FillCache( CPLVirtualMem* ctxt,  size_t nOffset,
+                           void* pPageToFill,
+                           size_t nPageSize, void* pUserData );
+    static void SaveFromCache( CPLVirtualMem* ctxt,  size_t nOffset,
+                               const void* pPageToBeEvicted,
+                               size_t nToEvicted, void* pUserData );
 
-    static void Destroy(void* pUserData);
+    static void Destroy( void* pUserData );
 };
 
 /************************************************************************/
 /*                        GDALTiledVirtualMem()                         */
 /************************************************************************/
 
-GDALTiledVirtualMem::GDALTiledVirtualMem( GDALDatasetH hDSIn,
-                                          GDALRasterBandH hBandIn,
-                                  int nXOffIn, int nYOffIn,
-                                  int nXSizeIn, int nYSizeIn,
-                                  int nTileXSizeIn, int nTileYSizeIn,
-                                  GDALDataType eBufTypeIn,
-                                  int nBandCountIn, const int* panBandMapIn,
-                                  GDALTileOrganization eTileOrganizationIn ):
-    hDS(hDSIn), hBand(hBandIn), nXOff(nXOffIn), nYOff(nYOffIn), nXSize(nXSizeIn), nYSize(nYSizeIn),
-    nTileXSize(nTileXSizeIn), nTileYSize(nTileYSizeIn), eBufType(eBufTypeIn),
-    nBandCount(nBandCountIn), eTileOrganization(eTileOrganizationIn)
+GDALTiledVirtualMem::GDALTiledVirtualMem(
+    GDALDatasetH hDSIn,
+    GDALRasterBandH hBandIn,
+    int nXOffIn, int nYOffIn,
+    int nXSizeIn, int nYSizeIn,
+    int nTileXSizeIn, int nTileYSizeIn,
+    GDALDataType eBufTypeIn,
+    int nBandCountIn, const int* panBandMapIn,
+    GDALTileOrganization eTileOrganizationIn ) :
+    hDS(hDSIn),
+    hBand(hBandIn),
+    nXOff(nXOffIn),
+    nYOff(nYOffIn),
+    nXSize(nXSizeIn),
+    nYSize(nYSizeIn),
+    nTileXSize(nTileXSizeIn),
+    nTileYSize(nTileYSizeIn),
+    eBufType(eBufTypeIn),
+    nBandCount(nBandCountIn),
+    eTileOrganization(eTileOrganizationIn)
 {
     if( hDS != NULL )
     {
+        panBandMap = static_cast<int*>(CPLMalloc(nBandCount * sizeof(int)));
         if( panBandMapIn )
         {
-            panBandMap = (int*) CPLMalloc(nBandCount * sizeof(int));
             memcpy(panBandMap, panBandMapIn, nBandCount * sizeof(int));
         }
         else
         {
-            panBandMap = (int*) CPLMalloc(nBandCount * sizeof(int));
-            for(int i=0;i<nBandCount;i++)
+            for(int i = 0; i < nBandCount; i++ )
                 panBandMap[i] = i + 1;
         }
     }
@@ -1126,9 +1209,11 @@ void GDALTiledVirtualMem::DoIO( GDALRWFlag eRWFlag, size_t nOffset,
         nPageSize *= nBandCount;
     CPLAssert((nOffset % nPageSize) == 0);
     CPLAssert(nBytes == nPageSize);
-    size_t nTile;
-    int band;
-    int nPixelSpace, nLineSpace, nBandSpace;
+    size_t nTile = 0;
+    int band = 0;
+    int nPixelSpace = 0;
+    int nLineSpace = 0;
+    int nBandSpace = 0;
     if( eTileOrganization == GTO_TIP )
     {
         nTile = nOffset / nPageSize;
@@ -1147,8 +1232,9 @@ void GDALTiledVirtualMem::DoIO( GDALRWFlag eRWFlag, size_t nOffset,
     }
     else
     {
-        //offset = nPageSize * (band * nTilesPerRow * nTilesPerCol + nTile)
-        band = static_cast<int>(nOffset / (nPageSize * nTilesPerRow * nTilesPerCol));
+        // offset = nPageSize * (band * nTilesPerRow * nTilesPerCol + nTile)
+        band = static_cast<int>(
+            nOffset / (nPageSize * nTilesPerRow * nTilesPerCol));
         nTile = nOffset / nPageSize - band * nTilesPerRow * nTilesPerCol;
         nPixelSpace = nDataTypeSize;
         nLineSpace = nPixelSpace * nTileXSize;
@@ -1158,33 +1244,38 @@ void GDALTiledVirtualMem::DoIO( GDALRWFlag eRWFlag, size_t nOffset,
     size_t nYTile = nTile / nTilesPerRow;
     size_t nXTile = nTile - nYTile * nTilesPerRow;
 
-    int nReqXSize = MIN( nTileXSize, nXSize - (int)(nXTile * nTileXSize) );
-    int nReqYSize = MIN( nTileYSize, nYSize - (int)(nYTile * nTileYSize) );
-    if( eRWFlag == GF_Read && (nReqXSize < nTileXSize || nReqYSize < nTileYSize) )
+    int nReqXSize = std::min( nTileXSize,
+                              nXSize - static_cast<int>(nXTile * nTileXSize) );
+    int nReqYSize = std::min( nTileYSize,
+                              nYSize - static_cast<int>(nYTile * nTileYSize) );
+    if( eRWFlag == GF_Read && (nReqXSize < nTileXSize ||
+                               nReqYSize < nTileYSize) )
         memset(pPage, 0, nBytes);
     if( hDS != NULL )
     {
-        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO( hDS, eRWFlag,
-                            static_cast<int>(nXOff + nXTile * nTileXSize),
-                            static_cast<int>(nYOff + nYTile * nTileYSize),
-                            nReqXSize, nReqYSize,
-                            pPage,
-                            nReqXSize, nReqYSize,
-                            eBufType,
-                            ( eTileOrganization != GTO_BSQ ) ? nBandCount : 1,
-                            ( eTileOrganization != GTO_BSQ ) ? panBandMap : &band,
-                            nPixelSpace, nLineSpace, nBandSpace ));
+        CPL_IGNORE_RET_VAL(GDALDatasetRasterIO(
+            hDS, eRWFlag,
+            static_cast<int>(nXOff + nXTile * nTileXSize),
+            static_cast<int>(nYOff + nYTile * nTileYSize),
+            nReqXSize, nReqYSize,
+            pPage,
+            nReqXSize, nReqYSize,
+            eBufType,
+            eTileOrganization != GTO_BSQ ? nBandCount : 1,
+            eTileOrganization != GTO_BSQ ? panBandMap : &band,
+            nPixelSpace, nLineSpace, nBandSpace ));
     }
     else
     {
-        CPL_IGNORE_RET_VAL(GDALRasterIO(hBand, eRWFlag,
-                      static_cast<int>(nXOff + nXTile * nTileXSize),
-                      static_cast<int>(nYOff + nYTile * nTileYSize),
-                     nReqXSize, nReqYSize,
-                     pPage,
-                     nReqXSize, nReqYSize,
-                     eBufType,
-                     nPixelSpace, nLineSpace ));
+        CPL_IGNORE_RET_VAL( GDALRasterIO(
+            hBand, eRWFlag,
+            static_cast<int>(nXOff + nXTile * nTileXSize),
+            static_cast<int>(nYOff + nYTile * nTileYSize),
+            nReqXSize, nReqYSize,
+            pPage,
+            nReqXSize, nReqYSize,
+            eBufType,
+            nPixelSpace, nLineSpace ) );
     }
 }
 
@@ -1192,11 +1283,14 @@ void GDALTiledVirtualMem::DoIO( GDALRWFlag eRWFlag, size_t nOffset,
 /*                           FillCache()                                */
 /************************************************************************/
 
-void GDALTiledVirtualMem::FillCache(CPLVirtualMem*,  size_t nOffset,
-                                         void* pPageToFill,
-                                         size_t nToFill, void* pUserData)
+void GDALTiledVirtualMem::FillCache( CPLVirtualMem*,
+                                     size_t nOffset,
+                                     void* pPageToFill,
+                                     size_t nToFill,
+                                     void* pUserData)
 {
-    const GDALTiledVirtualMem* psParms = (const GDALTiledVirtualMem* )pUserData;
+    const GDALTiledVirtualMem* psParms =
+        static_cast<GDALTiledVirtualMem *>( pUserData );
     psParms->DoIO(GF_Read, nOffset, pPageToFill, nToFill);
 }
 
@@ -1204,21 +1298,26 @@ void GDALTiledVirtualMem::FillCache(CPLVirtualMem*,  size_t nOffset,
 /*                          SaveFromCache()                             */
 /************************************************************************/
 
-void GDALTiledVirtualMem::SaveFromCache(CPLVirtualMem*,  size_t nOffset,
-                                             const void* pPageToBeEvicted,
-                                             size_t nToEvicted, void* pUserData)
+void GDALTiledVirtualMem::SaveFromCache( CPLVirtualMem*,
+                                         size_t nOffset,
+                                         const void* pPageToBeEvicted,
+                                         size_t nToEvicted, void* pUserData)
 {
-    const GDALTiledVirtualMem* psParms = (const GDALTiledVirtualMem* )pUserData;
-    psParms->DoIO(GF_Write, nOffset, (void*)pPageToBeEvicted, nToEvicted);
+    const GDALTiledVirtualMem* psParms =
+        static_cast<GDALTiledVirtualMem *>( pUserData );
+    psParms->DoIO( GF_Write, nOffset,
+                   const_cast<void *>(pPageToBeEvicted),
+                   nToEvicted );
 }
 
 /************************************************************************/
 /*                                Destroy()                             */
 /************************************************************************/
 
-void GDALTiledVirtualMem::Destroy(void* pUserData)
+void GDALTiledVirtualMem::Destroy( void* pUserData )
 {
-    GDALTiledVirtualMem* psParams = (GDALTiledVirtualMem*) pUserData;
+    GDALTiledVirtualMem* psParams =
+        static_cast<GDALTiledVirtualMem*>( pUserData );
     delete psParams;
 }
 
@@ -1226,18 +1325,19 @@ void GDALTiledVirtualMem::Destroy(void* pUserData)
 /*                      GDALGetTiledVirtualMem()                        */
 /************************************************************************/
 
-static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
-                                              GDALRasterBandH hBand,
-                                              GDALRWFlag eRWFlag,
-                                              int nXOff, int nYOff,
-                                              int nXSize, int nYSize,
-                                              int nTileXSize, int nTileYSize,
-                                              GDALDataType eBufType,
-                                              int nBandCount, int* panBandMap,
-                                              GDALTileOrganization eTileOrganization,
-                                              size_t nCacheSize,
-                                              int bSingleThreadUsage,
-                                              char ** /* papszOptions */ )
+static CPLVirtualMem* GDALGetTiledVirtualMem(
+    GDALDatasetH hDS,
+    GDALRasterBandH hBand,
+    GDALRWFlag eRWFlag,
+    int nXOff, int nYOff,
+    int nXSize, int nYSize,
+    int nTileXSize, int nTileYSize,
+    GDALDataType eBufType,
+    int nBandCount, int* panBandMap,
+    GDALTileOrganization eTileOrganization,
+    size_t nCacheSize,
+    int bSingleThreadUsage,
+    char ** /* papszOptions */ )
 {
     CPLVirtualMem* view;
     GDALTiledVirtualMem* psParams;
@@ -1245,13 +1345,17 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
     size_t nPageSize = CPLGetPageSize();
     if( nPageSize == 0 )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-             "GDALGetTiledVirtualMem() unsupported on this operating system / configuration");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "GDALGetTiledVirtualMem() unsupported on this "
+            "operating system / configuration" );
         return NULL;
     }
 
-    int nRasterXSize = (hDS) ? GDALGetRasterXSize(hDS) : GDALGetRasterBandXSize(hBand);
-    int nRasterYSize = (hDS) ? GDALGetRasterYSize(hDS) : GDALGetRasterBandYSize(hBand);
+    int nRasterXSize =
+        hDS ? GDALGetRasterXSize(hDS) : GDALGetRasterBandXSize(hBand);
+    int nRasterYSize =
+        hDS ? GDALGetRasterYSize(hDS) : GDALGetRasterBandYSize(hBand);
 
     if( nXOff < 0 || nYOff < 0 ||
         nTileXSize <= 0 || nTileYSize <= 0 ||
@@ -1272,8 +1376,8 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
                         nTileXSize * nTileYSize * nBandCount * nDataTypeSize;
     if( nReqMem != (GUIntBig)(size_t)nReqMem )
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Cannot reserve " CPL_FRMT_GUIB " bytes", nReqMem);
+        CPLError( CE_Failure, CPLE_OutOfMemory,
+                  "Cannot reserve " CPL_FRMT_GUIB " bytes", nReqMem );
         return NULL;
     }
 
@@ -1282,27 +1386,29 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
         nPageSizeHint *= nBandCount;
     if( (nPageSizeHint % nPageSize) != 0 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Tile dimensions incompatible with page size");
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Tile dimensions incompatible with page size");
         return NULL;
     }
 
-    psParams = new GDALTiledVirtualMem(hDS, hBand, nXOff, nYOff,
-                                       nXSize, nYSize,
-                                       nTileXSize, nTileYSize,
-                                       eBufType,
-                                       nBandCount, panBandMap,
-                                       eTileOrganization);
-
-    view = CPLVirtualMemNew((size_t)nReqMem,
-                         nCacheSize,
-                         nPageSizeHint,
-                         bSingleThreadUsage,
-                         (eRWFlag == GF_Read) ? VIRTUALMEM_READONLY_ENFORCED : VIRTUALMEM_READWRITE,
-                         GDALTiledVirtualMem::FillCache,
-                         GDALTiledVirtualMem::SaveFromCache,
-                         GDALTiledVirtualMem::Destroy,
-                         psParams);
+    psParams = new GDALTiledVirtualMem( hDS, hBand, nXOff, nYOff,
+                                        nXSize, nYSize,
+                                        nTileXSize, nTileYSize,
+                                        eBufType,
+                                        nBandCount, panBandMap,
+                                        eTileOrganization );
+
+    view = CPLVirtualMemNew(
+        static_cast<size_t>(nReqMem),
+        nCacheSize,
+        nPageSizeHint,
+        bSingleThreadUsage,
+        eRWFlag == GF_Read ?
+        VIRTUALMEM_READONLY_ENFORCED : VIRTUALMEM_READWRITE,
+        GDALTiledVirtualMem::FillCache,
+        GDALTiledVirtualMem::SaveFromCache,
+        GDALTiledVirtualMem::Destroy,
+        psParams );
 
     if( view == NULL )
     {
@@ -1310,9 +1416,11 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
     }
     else if( CPLVirtualMemGetPageSize(view) != nPageSizeHint )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Did not get expected page size : %d vs %d",
-                 (int)CPLVirtualMemGetPageSize(view), (int)nPageSizeHint);
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Did not get expected page size : %d vs %d",
+            static_cast<int>(CPLVirtualMemGetPageSize(view)),
+            static_cast<int>(nPageSizeHint) );
         CPLVirtualMemFree(view);
         return NULL;
     }
@@ -1340,20 +1448,26 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
  * can be selected with the eTileOrganization parameter.
  *
  * If nXSize is not a multiple of nTileXSize or nYSize is not a multiple of
- * nTileYSize, partial tiles will exists at the right and/or bottom of the region
- * of interest. Those partial tiles will also have nTileXSize * nTileYSize dimension,
- * with padding pixels.
+ * nTileYSize, partial tiles will exists at the right and/or bottom of the
+ * region of interest. Those partial tiles will also have nTileXSize *
+ * nTileYSize dimension, with padding pixels.
  *
  * The pointer to access the virtual memory object is obtained with
  * CPLVirtualMemGetAddr(). It remains valid until CPLVirtualMemFree() is called.
  * CPLVirtualMemFree() must be called before the dataset object is destroyed.
  *
- * If p is such a pointer and base_type the C type matching eBufType, for default
- * values of spacing parameters, the element of image coordinates (x, y)
- * (relative to xOff, yOff) for band b can be accessed with :
- *  - for eTileOrganization = GTO_TIP, ((base_type*)p)[tile_number(x,y)*nBandCount*tile_size + offset_in_tile(x,y)*nBandCount + (b-1)].
- *  - for eTileOrganization = GTO_BIT, ((base_type*)p)[(tile_number(x,y)*nBandCount + (b-1)) * tile_size + offset_in_tile(x,y)].
- *  - for eTileOrganization = GTO_BSQ, ((base_type*)p)[(tile_number(x,y) + (b-1)*nTilesCount) * tile_size + offset_in_tile(x,y)].
+ * If p is such a pointer and base_type the C type matching eBufType, for
+ * default values of spacing parameters, the element of image coordinates (x, y)
+ * (relative to xOff, yOff) for band b can be accessed with:
+ *  - for eTileOrganization = GTO_TIP,
+ *        ((base_type*)p)[tile_number(x,y)*nBandCount*tile_size +
+ *                        offset_in_tile(x,y)*nBandCount + (b-1)].
+ *  - for eTileOrganization = GTO_BIT,
+ *        ((base_type*)p)[(tile_number(x,y)*nBandCount +
+ *                        (b-1)) * tile_size + offset_in_tile(x,y)].
+ *  - for eTileOrganization = GTO_BSQ,
+ *        ((base_type*)p)[(tile_number(x,y) +
+ *                        (b-1)*nTilesCount) * tile_size + offset_in_tile(x,y)].
  *
  * where nTilesPerRow = ceil(nXSize / nTileXSize)
  *       nTilesPerCol = ceil(nYSize / nTileYSize)
@@ -1366,9 +1480,10 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
  *
  * Note that the mechanism used to transparently fill memory pages when they are
  * accessed is the same (but in a controlled way) than what occurs when a memory
- * error occurs in a program. Debugging software will generally interrupt program
- * execution when that happens. If needed, CPLVirtualMemPin() can be used to avoid
- * that by ensuring memory pages are allocated before being accessed.
+ * error occurs in a program. Debugging software will generally interrupt
+ * program execution when that happens. If needed, CPLVirtualMemPin() can be
+ * used to avoid that by ensuring memory pages are allocated before being
+ * accessed.
  *
  * The size of the region that can be mapped as a virtual memory object depends
  * on hardware and operating system limitations.
@@ -1414,8 +1529,8 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
  *                     allocated (must ideally fit into RAM)
  *
  * @param bSingleThreadUsage set to TRUE if there will be no concurrent threads
- *                           that will access the virtual memory mapping. This can
- *                           optimize performance a bit. If set to FALSE,
+ *                           that will access the virtual memory mapping. This
+ *                           can optimize performance a bit. If set to FALSE,
  *                           CPLVirtualMemDeclareThread() must be called.
  *
  * @param papszOptions NULL terminated list of options. Unused for now.
@@ -1426,23 +1541,25 @@ static CPLVirtualMem* GDALGetTiledVirtualMem( GDALDatasetH hDS,
  * @since GDAL 1.11
  */
 
-CPLVirtualMem* GDALDatasetGetTiledVirtualMem( GDALDatasetH hDS,
-                                              GDALRWFlag eRWFlag,
-                                              int nXOff, int nYOff,
-                                              int nXSize, int nYSize,
-                                              int nTileXSize, int nTileYSize,
-                                              GDALDataType eBufType,
-                                              int nBandCount, int* panBandMap,
-                                              GDALTileOrganization eTileOrganization,
-                                              size_t nCacheSize,
-                                              int bSingleThreadUsage,
-                                              char **papszOptions )
+CPLVirtualMem* GDALDatasetGetTiledVirtualMem(
+    GDALDatasetH hDS,
+    GDALRWFlag eRWFlag,
+    int nXOff, int nYOff,
+    int nXSize, int nYSize,
+    int nTileXSize, int nTileYSize,
+    GDALDataType eBufType,
+    int nBandCount, int* panBandMap,
+    GDALTileOrganization eTileOrganization,
+    size_t nCacheSize,
+    int bSingleThreadUsage,
+    char **papszOptions )
 {
     return GDALGetTiledVirtualMem( hDS, NULL, eRWFlag, nXOff, nYOff,
                                    nXSize, nYSize, nTileXSize, nTileYSize,
                                    eBufType, nBandCount, panBandMap,
                                    eTileOrganization,
-                                   nCacheSize, bSingleThreadUsage, papszOptions );
+                                   nCacheSize, bSingleThreadUsage,
+                                   papszOptions );
 }
 
 /************************************************************************/
@@ -1464,17 +1581,18 @@ CPLVirtualMem* GDALDatasetGetTiledVirtualMem( GDALDatasetH hDS,
  * instead of scanlines.
  *
  * If nXSize is not a multiple of nTileXSize or nYSize is not a multiple of
- * nTileYSize, partial tiles will exists at the right and/or bottom of the region
- * of interest. Those partial tiles will also have nTileXSize * nTileYSize dimension,
- * with padding pixels.
+ * nTileYSize, partial tiles will exists at the right and/or bottom of the
+ * region of interest. Those partial tiles will also have nTileXSize *
+ * nTileYSize dimension, with padding pixels.
  *
  * The pointer to access the virtual memory object is obtained with
  * CPLVirtualMemGetAddr(). It remains valid until CPLVirtualMemFree() is called.
- * CPLVirtualMemFree() must be called before the raster band object is destroyed.
+ * CPLVirtualMemFree() must be called before the raster band object is
+ * destroyed.
  *
- * If p is such a pointer and base_type the C type matching eBufType, for default
- * values of spacing parameters, the element of image coordinates (x, y)
- * (relative to xOff, yOff) can be accessed with :
+ * If p is such a pointer and base_type the C type matching eBufType, for
+ * default values of spacing parameters, the element of image coordinates (x, y)
+ * (relative to xOff, yOff) can be accessed with:
  *  ((base_type*)p)[tile_number(x,y)*tile_size + offset_in_tile(x,y)].
  *
  * where nTilesPerRow = ceil(nXSize / nTileXSize)
@@ -1485,9 +1603,10 @@ CPLVirtualMem* GDALDatasetGetTiledVirtualMem( GDALDatasetH hDS,
  *
  * Note that the mechanism used to transparently fill memory pages when they are
  * accessed is the same (but in a controlled way) than what occurs when a memory
- * error occurs in a program. Debugging software will generally interrupt program
- * execution when that happens. If needed, CPLVirtualMemPin() can be used to avoid
- * that by ensuring memory pages are allocated before being accessed.
+ * error occurs in a program. Debugging software will generally interrupt
+ * program execution when that happens. If needed, CPLVirtualMemPin() can be
+ * used to avoid that by ensuring memory pages are allocated before being
+ * accessed.
  *
  * The size of the region that can be mapped as a virtual memory object depends
  * on hardware and operating system limitations.
@@ -1525,8 +1644,8 @@ CPLVirtualMem* GDALDatasetGetTiledVirtualMem( GDALDatasetH hDS,
  *                     allocated (must ideally fit into RAM)
  *
  * @param bSingleThreadUsage set to TRUE if there will be no concurrent threads
- *                           that will access the virtual memory mapping. This can
- *                           optimize performance a bit. If set to FALSE,
+ *                           that will access the virtual memory mapping. This
+ *                           can optimize performance a bit. If set to FALSE,
  *                           CPLVirtualMemDeclareThread() must be called.
  *
  * @param papszOptions NULL terminated list of options. Unused for now.
@@ -1538,18 +1657,19 @@ CPLVirtualMem* GDALDatasetGetTiledVirtualMem( GDALDatasetH hDS,
  */
 
 CPLVirtualMem* GDALRasterBandGetTiledVirtualMem( GDALRasterBandH hBand,
-                                              GDALRWFlag eRWFlag,
-                                              int nXOff, int nYOff,
-                                              int nXSize, int nYSize,
-                                              int nTileXSize, int nTileYSize,
-                                              GDALDataType eBufType,
-                                              size_t nCacheSize,
-                                              int bSingleThreadUsage,
-                                              char **papszOptions )
+                                                 GDALRWFlag eRWFlag,
+                                                 int nXOff, int nYOff,
+                                                 int nXSize, int nYSize,
+                                                 int nTileXSize, int nTileYSize,
+                                                 GDALDataType eBufType,
+                                                 size_t nCacheSize,
+                                                 int bSingleThreadUsage,
+                                                 char **papszOptions )
 {
     return GDALGetTiledVirtualMem( NULL, hBand, eRWFlag, nXOff, nYOff,
                                    nXSize, nYSize, nTileXSize, nTileYSize,
                                    eBufType, 1, NULL,
                                    GTO_BSQ,
-                                   nCacheSize, bSingleThreadUsage, papszOptions );
+                                   nCacheSize, bSingleThreadUsage,
+                                   papszOptions );
 }
diff --git a/gcore/makefile.vc b/gcore/makefile.vc
index 0a58e24..39d1d1a 100644
--- a/gcore/makefile.vc
+++ b/gcore/makefile.vc
@@ -22,6 +22,10 @@ GDAL_ROOT	=	..
 
 !INCLUDE ..\nmake.opt
 
+!IF "$(SSSE3FLAGS)" == "/DHAVE_SSSE3_AT_COMPILE_TIME"
+SSSE3_OBJ = rasterio_ssse3.obj
+!ENDIF
+
 EXTRAFLAGS =	$(PAM_SETTING) -I..\frmts\gtiff -I..\frmts\mem -I..\frmts\vrt -I..\ogr\ogrsf_frmts\generic -I../ogr/ogrsf_frmts/geojson -I..\ogr\ogrsf_frmts\geojson\libjson $(SQLITEDEF)
 
 !IFDEF SQLITE_LIB
@@ -32,7 +36,7 @@ SQLITEDEF	=	-DSQLITE_ENABLED
 EXTRAFLAGS =	$(EXTRAFLAGS) -DHAVE_LIBXML2 $(LIBXML2_INC)
 !ENDIF
 
-default:	$(OBJ) $(RES) mdreader_dir
+default:	$(OBJ) $(RES) mdreader_dir $(SSSE3_OBJ)
 
 clean:
 	-del *.obj *.res
diff --git a/gcore/mdreader/reader_alos.cpp b/gcore/mdreader/reader_alos.cpp
index 7e5bfb9..4fa8cd7 100644
--- a/gcore/mdreader/reader_alos.cpp
+++ b/gcore/mdreader/reader_alos.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Alos imagery.
@@ -30,6 +29,18 @@
 
 #include "reader_alos.h"
 
+#include <cstdio>
+#include <cstdlib>
+
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "gdal_mdreader.h"
+
+CPL_CVSID("$Id: reader_alos.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 /**
  * GDALMDReaderALOS()
  */
@@ -136,13 +147,13 @@ GDALMDReaderALOS::GDALMDReaderALOS(const char *pszPath,
         }
     }
 
-    if(m_osIMDSourceFilename.size())
+    if(!m_osIMDSourceFilename.empty() )
         CPLDebug( "MDReaderALOS", "IMD Filename: %s",
               m_osIMDSourceFilename.c_str() );
-    if(m_osHDRSourceFilename.size())
+    if(!m_osHDRSourceFilename.empty() )
         CPLDebug( "MDReaderALOS", "HDR Filename: %s",
               m_osHDRSourceFilename.c_str() );
-    if(m_osRPBSourceFilename.size())
+    if(!m_osRPBSourceFilename.empty() )
         CPLDebug( "MDReaderALOS", "RPB Filename: %s",
               m_osRPBSourceFilename.c_str() );
 }
@@ -237,7 +248,6 @@ void GDALMDReaderALOS::LoadMetadata()
                                 MD_NAME_SATELLITE, CPLStripQuotes(pszSatId2));
     }
 
-
     const char* pszCloudCover = CSLFetchNameValue(m_papszIMDMD,
                                                  "Img_CloudQuantityOfAllImage");
     if(NULL != pszCloudCover)
diff --git a/gcore/mdreader/reader_alos.h b/gcore/mdreader/reader_alos.h
index ab0e020..a3636eb 100644
--- a/gcore/mdreader/reader_alos.h
+++ b/gcore/mdreader/reader_alos.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: reader_alos.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Alos imagery.
@@ -53,12 +53,12 @@ class GDALMDReaderALOS: public GDALMDReaderBase
 public:
     GDALMDReaderALOS(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderALOS();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
 protected:
-    virtual void LoadMetadata();
+    virtual void LoadMetadata() override;
     char** LoadRPCTxtFile();
-    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime) override;
 protected:
     CPLString m_osIMDSourceFilename;
     CPLString m_osHDRSourceFilename;
diff --git a/gcore/mdreader/reader_digital_globe.cpp b/gcore/mdreader/reader_digital_globe.cpp
index 458882a..df9d661 100644
--- a/gcore/mdreader/reader_digital_globe.cpp
+++ b/gcore/mdreader/reader_digital_globe.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: reader_digital_globe.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from DigitalGlobe imagery.
@@ -28,30 +27,39 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "reader_digital_globe.h"
 
-CPL_CVSID("$Id: reader_digital_globe.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <ctime>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "gdal_priv.h"
+
+CPL_CVSID("$Id: reader_digital_globe.cpp 36528 2016-11-27 16:35:01Z goatbar $");
 
 /**
  * GDALMDReaderDigitalGlobe()
  */
 GDALMDReaderDigitalGlobe::GDALMDReaderDigitalGlobe(const char *pszPath,
-        char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
+                                                   char **papszSiblingFiles) :
+    GDALMDReaderBase(pszPath, papszSiblingFiles),
+    m_osXMLSourceFilename ( GDALFindAssociatedFile( pszPath, "XML",
+                                                         papszSiblingFiles, 0 ) ),
+    m_osIMDSourceFilename ( GDALFindAssociatedFile( pszPath, "IMD",
+                                                         papszSiblingFiles, 0 ) ),
+    m_osRPBSourceFilename ( GDALFindAssociatedFile( pszPath, "RPB",
+                                                         papszSiblingFiles, 0 ) )
 {
-    m_osIMDSourceFilename = GDALFindAssociatedFile( pszPath, "IMD",
-                                                         papszSiblingFiles, 0 );
-    m_osRPBSourceFilename = GDALFindAssociatedFile( pszPath, "RPB",
-                                                         papszSiblingFiles, 0 );
-    m_osXMLSourceFilename = GDALFindAssociatedFile( pszPath, "XML",
-                                                         papszSiblingFiles, 0 );
-
-    if( m_osIMDSourceFilename.size() )
+    if( !m_osIMDSourceFilename.empty() )
         CPLDebug( "MDReaderDigitalGlobe", "IMD Filename: %s",
                   m_osIMDSourceFilename.c_str() );
-    if( m_osRPBSourceFilename.size() )
+    if( !m_osRPBSourceFilename.empty() )
         CPLDebug( "MDReaderDigitalGlobe", "RPB Filename: %s",
                   m_osRPBSourceFilename.c_str() );
-    if( m_osXMLSourceFilename.size() )
+    if( !m_osXMLSourceFilename.empty() )
         CPLDebug( "MDReaderDigitalGlobe", "XML Filename: %s",
                   m_osXMLSourceFilename.c_str() );
 }
diff --git a/gcore/mdreader/reader_digital_globe.h b/gcore/mdreader/reader_digital_globe.h
index 555d21c..4c95035 100644
--- a/gcore/mdreader/reader_digital_globe.h
+++ b/gcore/mdreader/reader_digital_globe.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_digital_globe.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: reader_digital_globe.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from DigitalGlobe imagery.
@@ -59,10 +59,10 @@ class GDALMDReaderDigitalGlobe: public GDALMDReaderBase
 public:
     GDALMDReaderDigitalGlobe(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderDigitalGlobe();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
 protected:
-    virtual void LoadMetadata();
+    virtual void LoadMetadata() override;
     char** LoadRPBXmlNode(CPLXMLNode* psNode);
     char** LoadIMDXmlNode(CPLXMLNode* psNode);
 protected:
diff --git a/gcore/mdreader/reader_eros.cpp b/gcore/mdreader/reader_eros.cpp
index 2b22003..f051d01 100644
--- a/gcore/mdreader/reader_eros.cpp
+++ b/gcore/mdreader/reader_eros.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from EROS imagery.
@@ -28,8 +27,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "reader_eros.h"
 
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: reader_eros.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 /**
  * GDALMDReaderEROS()
  */
@@ -100,10 +110,10 @@ GDALMDReaderEROS::GDALMDReaderEROS(const char *pszPath,
         }
     }
 
-    if(m_osIMDSourceFilename.size())
+    if(!m_osIMDSourceFilename.empty() )
         CPLDebug( "MDReaderEROS", "IMD Filename: %s",
               m_osIMDSourceFilename.c_str() );
-    if(m_osRPBSourceFilename.size())
+    if(!m_osRPBSourceFilename.empty() )
         CPLDebug( "MDReaderEROS", "RPB Filename: %s",
               m_osRPBSourceFilename.c_str() );
 }
@@ -209,7 +219,6 @@ void GDALMDReaderEROS::LoadMetadata()
         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
                                            MD_NAME_ACQDATETIME, buffer);
     }
-
 }
 
 /**
diff --git a/gcore/mdreader/reader_eros.h b/gcore/mdreader/reader_eros.h
index 1d0be26..7507782 100644
--- a/gcore/mdreader/reader_eros.h
+++ b/gcore/mdreader/reader_eros.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: reader_eros.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from EROS imagery.
@@ -49,12 +49,12 @@ class GDALMDReaderEROS: public GDALMDReaderBase
 public:
     GDALMDReaderEROS(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderEROS();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
 protected:
-    virtual void LoadMetadata();
+    virtual void LoadMetadata() override;
     char** LoadImdTxtFile();
-    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime) override;
 protected:
     CPLString m_osIMDSourceFilename;
     CPLString m_osRPBSourceFilename;
diff --git a/gcore/mdreader/reader_geo_eye.cpp b/gcore/mdreader/reader_geo_eye.cpp
index 5fd3e9b..ad2634d 100644
--- a/gcore/mdreader/reader_geo_eye.cpp
+++ b/gcore/mdreader/reader_geo_eye.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: reader_geo_eye.cpp 33720 2016-03-15 00:39:53Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from GeoEye imagery.
@@ -28,9 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "reader_geo_eye.h"
 
-CPL_CVSID("$Id: reader_geo_eye.cpp 33720 2016-03-15 00:39:53Z goatbar $");
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: reader_geo_eye.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /**
  * GDALMDReaderGeoEye()
@@ -97,10 +107,10 @@ GDALMDReaderGeoEye::GDALMDReaderGeoEye(const char *pszPath,
         }
     }
 
-    if( m_osIMDSourceFilename.size() )
+    if( !m_osIMDSourceFilename.empty() )
         CPLDebug( "MDReaderGeoEye", "IMD Filename: %s",
                   m_osIMDSourceFilename.c_str() );
-    if( m_osRPBSourceFilename.size() )
+    if( !m_osRPBSourceFilename.empty() )
         CPLDebug( "MDReaderGeoEye", "RPB Filename: %s",
                   m_osRPBSourceFilename.c_str() );
 }
diff --git a/gcore/mdreader/reader_geo_eye.h b/gcore/mdreader/reader_geo_eye.h
index 7a0074f..44fd8c6 100644
--- a/gcore/mdreader/reader_geo_eye.h
+++ b/gcore/mdreader/reader_geo_eye.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_geo_eye.h 32174 2015-12-14 00:09:26Z goatbar $
+ * $Id: reader_geo_eye.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from GeoEye imagery.
@@ -52,11 +52,11 @@ class GDALMDReaderGeoEye: public GDALMDReaderBase
 public:
     GDALMDReaderGeoEye(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderGeoEye();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
 protected:
-    virtual void LoadMetadata();
-    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual void LoadMetadata() override;
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime) override;
     char **LoadRPCWktFile() const;
     char **LoadIMDWktFile() const;
 protected:
diff --git a/gcore/mdreader/reader_kompsat.cpp b/gcore/mdreader/reader_kompsat.cpp
index ab093c6..6028a8f 100644
--- a/gcore/mdreader/reader_kompsat.cpp
+++ b/gcore/mdreader/reader_kompsat.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Kompsat imagery.
@@ -28,23 +27,35 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "reader_kompsat.h"
 
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "gdal_mdreader.h"
+#include "gdal_priv.h"
+
+CPL_CVSID("$Id: reader_kompsat.cpp 36528 2016-11-27 16:35:01Z goatbar $");
+
 /**
  * GDALMDReaderKompsat()
  */
 GDALMDReaderKompsat::GDALMDReaderKompsat(const char *pszPath,
-        char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
+                                         char **papszSiblingFiles) :
+    GDALMDReaderBase(pszPath, papszSiblingFiles),
+    m_osIMDSourceFilename ( GDALFindAssociatedFile( pszPath, "TXT",
+                                                    papszSiblingFiles, 0 ) ),
+    m_osRPBSourceFilename ( GDALFindAssociatedFile( pszPath, "RPC",
+                                                    papszSiblingFiles, 0 ) )
 {
-    m_osIMDSourceFilename = GDALFindAssociatedFile( pszPath, "TXT",
-                                                         papszSiblingFiles, 0 );
-    m_osRPBSourceFilename = GDALFindAssociatedFile( pszPath, "RPC",
-                                                         papszSiblingFiles, 0 );
-
-    if(m_osIMDSourceFilename.size())
+    if( !m_osIMDSourceFilename.empty() )
         CPLDebug( "MDReaderDigitalGlobe", "IMD Filename: %s",
               m_osIMDSourceFilename.c_str() );
-    if(m_osRPBSourceFilename.size())
+    if( !m_osRPBSourceFilename.empty() )
         CPLDebug( "MDReaderDigitalGlobe", "RPB Filename: %s",
               m_osRPBSourceFilename.c_str() );
 }
@@ -223,7 +234,7 @@ char** GDALMDReaderKompsat::ReadTxtToList()
         }
 
         // trim
-        while( pszLine[j] == ' ' && pszLine[j] != 0) j++;
+        while( pszLine[j] == ' ' ) j++;
 
         if(soGroupName.empty())
         {
@@ -234,7 +245,6 @@ char** GDALMDReaderKompsat::ReadTxtToList()
             papszIMD = CSLAddNameValue(papszIMD, CPLSPrintf("%s.%s",
                                        soGroupName.c_str(), szName), pszLine + j);
         }
-
     }
 
     CSLDestroy(papszLines);
diff --git a/gcore/mdreader/reader_kompsat.h b/gcore/mdreader/reader_kompsat.h
index 52b35d1..d09aabf 100644
--- a/gcore/mdreader/reader_kompsat.h
+++ b/gcore/mdreader/reader_kompsat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: reader_kompsat.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Kompsat imagery.
@@ -50,12 +50,12 @@ class GDALMDReaderKompsat: public GDALMDReaderBase
 public:
     GDALMDReaderKompsat(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderKompsat();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
 protected:
-    virtual void LoadMetadata();
+    virtual void LoadMetadata() override;
     char** ReadTxtToList();
-    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime) override;
 protected:
     CPLString m_osIMDSourceFilename;
     CPLString m_osRPBSourceFilename;
diff --git a/gcore/mdreader/reader_landsat.cpp b/gcore/mdreader/reader_landsat.cpp
index de6ace0..d96b491 100644
--- a/gcore/mdreader/reader_landsat.cpp
+++ b/gcore/mdreader/reader_landsat.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: reader_landsat.cpp 31120 2015-10-24 19:55:09Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Landsat imagery.
@@ -28,9 +27,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "reader_landsat.h"
 
-CPL_CVSID("$Id: reader_landsat.cpp 31120 2015-10-24 19:55:09Z rouault $");
+#include <cstddef>
+#include <cstring>
+#include <ctime>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: reader_landsat.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /**
  * GDALMDReaderLandsat()
@@ -75,7 +83,7 @@ GDALMDReaderLandsat::GDALMDReaderLandsat(const char *pszPath,
         }
     }
 
-    if( m_osIMDSourceFilename.size() )
+    if( !m_osIMDSourceFilename.empty() )
         CPLDebug( "MDReaderLandsat", "IMD Filename: %s",
                   m_osIMDSourceFilename.c_str() );
 }
@@ -191,5 +199,4 @@ void GDALMDReaderLandsat::LoadMetadata()
         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
                                            MD_NAME_ACQDATETIME, buffer);
     }
-
 }
diff --git a/gcore/mdreader/reader_landsat.h b/gcore/mdreader/reader_landsat.h
index 340dda9..d2d6f06 100644
--- a/gcore/mdreader/reader_landsat.h
+++ b/gcore/mdreader/reader_landsat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_landsat.h 33720 2016-03-15 00:39:53Z goatbar $
+ * $Id: reader_landsat.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Landsat imagery.
@@ -54,10 +54,10 @@ class GDALMDReaderLandsat: public GDALMDReaderBase
 public:
     GDALMDReaderLandsat(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderLandsat();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
 protected:
-    virtual void LoadMetadata();
+    virtual void LoadMetadata() override;
 protected:
     CPLString m_osIMDSourceFilename;
 };
diff --git a/gcore/mdreader/reader_orb_view.cpp b/gcore/mdreader/reader_orb_view.cpp
index 2b18a40..6b66286 100644
--- a/gcore/mdreader/reader_orb_view.cpp
+++ b/gcore/mdreader/reader_orb_view.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: reader_orb_view.cpp 29915 2015-08-29 21:29:57Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from OrbView imagery.
@@ -28,19 +27,28 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "reader_orb_view.h"
 
-CPL_CVSID("$Id: reader_orb_view.cpp 29915 2015-08-29 21:29:57Z rouault $");
+#include <ctime>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "gdal_priv.h"
+
+CPL_CVSID("$Id: reader_orb_view.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /**
  * GDALMDReaderOrbView()
  */
 GDALMDReaderOrbView::GDALMDReaderOrbView(const char *pszPath,
-        char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
+                                         char **papszSiblingFiles) :
+    GDALMDReaderBase(pszPath, papszSiblingFiles),
+    m_osIMDSourceFilename( GDALFindAssociatedFile( pszPath, "PVL",
+                                                    papszSiblingFiles, 0 ) ),
+    m_osRPBSourceFilename( CPLString() )
 {
-    m_osIMDSourceFilename = GDALFindAssociatedFile( pszPath, "PVL",
-                                                    papszSiblingFiles, 0 );
-
     const char* pszBaseName = CPLGetBasename(pszPath);
     const char* pszDirName = CPLGetDirname(pszPath);
 
@@ -62,10 +70,10 @@ GDALMDReaderOrbView::GDALMDReaderOrbView(const char *pszPath,
         }
     }
 
-    if( m_osIMDSourceFilename.size() )
+    if( !m_osIMDSourceFilename.empty() )
         CPLDebug( "MDReaderOrbView", "IMD Filename: %s",
                   m_osIMDSourceFilename.c_str() );
-    if( m_osRPBSourceFilename.size() )
+    if( !m_osRPBSourceFilename.empty() )
         CPLDebug( "MDReaderOrbView", "RPB Filename: %s",
                   m_osRPBSourceFilename.c_str() );
 }
diff --git a/gcore/mdreader/reader_orb_view.h b/gcore/mdreader/reader_orb_view.h
index c5d9af4..a25894f 100644
--- a/gcore/mdreader/reader_orb_view.h
+++ b/gcore/mdreader/reader_orb_view.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_orb_view.h 29915 2015-08-29 21:29:57Z rouault $
+ * $Id: reader_orb_view.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from OrbView imagery.
@@ -50,10 +50,10 @@ class GDALMDReaderOrbView: public GDALMDReaderBase
 public:
     GDALMDReaderOrbView(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderOrbView();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
 protected:
-    virtual void LoadMetadata();
+    virtual void LoadMetadata() override;
 protected:
     CPLString m_osIMDSourceFilename;
     CPLString m_osRPBSourceFilename;
diff --git a/gcore/mdreader/reader_pleiades.cpp b/gcore/mdreader/reader_pleiades.cpp
index 4a9c48d..2752964 100644
--- a/gcore/mdreader/reader_pleiades.cpp
+++ b/gcore/mdreader/reader_pleiades.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: reader_pleiades.cpp 34367 2016-06-17 13:58:32Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Pleiades imagery.
@@ -28,17 +27,32 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "reader_pleiades.h"
 
-CPL_CVSID("$Id: reader_pleiades.cpp 34367 2016-06-17 13:58:32Z rouault $");
+#include <cstddef>
+#include <cstring>
+#include <ctime>
+
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: reader_pleiades.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /**
  * GDALMDReaderPleiades()
  */
 GDALMDReaderPleiades::GDALMDReaderPleiades(const char *pszPath,
-        char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
+                                        char **papszSiblingFiles) :
+    GDALMDReaderBase(pszPath, papszSiblingFiles),
+    m_osBaseFilename( pszPath ),
+    m_osIMDSourceFilename( CPLString() ),
+    m_osRPBSourceFilename( CPLString() )
 {
-    m_osBaseFilename = pszPath;
     const char* pszBaseName = CPLGetBasename(pszPath);
     size_t nBaseNameLen = strlen(pszBaseName);
     if( nBaseNameLen < 4 || nBaseNameLen > 511 )
@@ -91,14 +105,25 @@ GDALMDReaderPleiades::GDALMDReaderPleiades(const char *pszPath,
         }
     }
 
-    if( m_osIMDSourceFilename.size() )
+    if( !m_osIMDSourceFilename.empty() )
         CPLDebug( "MDReaderPleiades", "IMD Filename: %s",
                   m_osIMDSourceFilename.c_str() );
-    if( m_osRPBSourceFilename.size() )
+    if( !m_osRPBSourceFilename.empty() )
         CPLDebug( "MDReaderPleiades", "RPB Filename: %s",
                   m_osRPBSourceFilename.c_str() );
 }
 
+GDALMDReaderPleiades::GDALMDReaderPleiades() : GDALMDReaderBase(NULL, NULL)
+{
+}
+
+GDALMDReaderPleiades* GDALMDReaderPleiades::CreateReaderForRPC(const char* pszRPCSourceFilename)
+{
+    GDALMDReaderPleiades* poReader = new GDALMDReaderPleiades();
+    poReader->m_osRPBSourceFilename = pszRPCSourceFilename;
+    return poReader;
+}
+
 /**
  * ~GDALMDReaderPleiades()
  */
@@ -189,7 +214,6 @@ void GDALMDReaderPleiades::LoadMetadata()
         }
     }
 
-
     const char* pszSatId2;
     if(nCounter == -1)
         pszSatId2 = CSLFetchNameValue(m_papszIMDMD,
@@ -217,7 +241,6 @@ void GDALMDReaderPleiades::LoadMetadata()
                                 MD_NAME_SATELLITE, CPLStripQuotes(pszSatId2));
     }
 
-
     const char* pszDate;
     if(nCounter == -1)
         pszDate = CSLFetchNameValue(m_papszIMDMD,
diff --git a/gcore/mdreader/reader_pleiades.h b/gcore/mdreader/reader_pleiades.h
index 45b2735..aa85723 100644
--- a/gcore/mdreader/reader_pleiades.h
+++ b/gcore/mdreader/reader_pleiades.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_pleiades.h 34367 2016-06-17 13:58:32Z rouault $
+ * $Id: reader_pleiades.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Pleiades imagery.
@@ -51,15 +51,21 @@ class GDALMDReaderPleiades: public GDALMDReaderBase
 public:
     GDALMDReaderPleiades(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderPleiades();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
-protected:
-    virtual void LoadMetadata();
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
+
+    static GDALMDReaderPleiades* CreateReaderForRPC(const char* pszRPCSourceFilename);
+
     char** LoadRPCXmlFile();
+
+protected:
+    virtual void LoadMetadata() override;
 protected:
     CPLString m_osBaseFilename;
     CPLString m_osIMDSourceFilename;
     CPLString m_osRPBSourceFilename;
+private:
+    GDALMDReaderPleiades();
 };
 
 #endif // READER_PLEIADES_H_INCLUDED
diff --git a/gcore/mdreader/reader_rapid_eye.cpp b/gcore/mdreader/reader_rapid_eye.cpp
index 71c6862..f5224cc 100644
--- a/gcore/mdreader/reader_rapid_eye.cpp
+++ b/gcore/mdreader/reader_rapid_eye.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from RapidEye imagery.
@@ -30,6 +29,15 @@
 
 #include "reader_rapid_eye.h"
 
+#include <ctime>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: reader_rapid_eye.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 /**
  * GDALMDReaderRapidEye()
  */
@@ -57,7 +65,7 @@ GDALMDReaderRapidEye::GDALMDReaderRapidEye(const char *pszPath,
         }
     }
 
-    if(m_osXMLSourceFilename.size())
+    if(!m_osXMLSourceFilename.empty() )
         CPLDebug( "MDReaderRapidEye", "XML Filename: %s",
               m_osXMLSourceFilename.c_str() );
 }
@@ -151,5 +159,4 @@ void GDALMDReaderRapidEye::LoadMetadata()
         m_papszIMAGERYMD = CSLAddNameValue(m_papszIMAGERYMD,
                                 MD_NAME_CLOUDCOVER, pszCC);
     }
-
 }
diff --git a/gcore/mdreader/reader_rapid_eye.h b/gcore/mdreader/reader_rapid_eye.h
index 392b3d0..06252be 100644
--- a/gcore/mdreader/reader_rapid_eye.h
+++ b/gcore/mdreader/reader_rapid_eye.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: reader_rapid_eye.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from RapidEye imagery.
@@ -51,10 +51,10 @@ class GDALMDReaderRapidEye: public GDALMDReaderBase
 public:
     GDALMDReaderRapidEye(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderRapidEye();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
 protected:
-    virtual void LoadMetadata();
+    virtual void LoadMetadata() override;
 protected:
     CPLString m_osXMLSourceFilename;
 };
diff --git a/gcore/mdreader/reader_rdk1.cpp b/gcore/mdreader/reader_rdk1.cpp
index c9ac76e..50c370a 100644
--- a/gcore/mdreader/reader_rdk1.cpp
+++ b/gcore/mdreader/reader_rdk1.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: reader_rdk1.cpp 31812 2015-11-28 22:37:37Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Resurs-DK1 imagery.
@@ -28,19 +27,28 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "reader_rdk1.h"
 
-CPL_CVSID("$Id: reader_rdk1.cpp 31812 2015-11-28 22:37:37Z goatbar $");
+#include <cstdio>
+
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "gdal_priv.h"
+
+CPL_CVSID("$Id: reader_rdk1.cpp 36528 2016-11-27 16:35:01Z goatbar $");
 
 /**
  * GDALMDReaderResursDK1()
  */
 GDALMDReaderResursDK1::GDALMDReaderResursDK1(const char *pszPath,
-        char **papszSiblingFiles) : GDALMDReaderBase(pszPath, papszSiblingFiles)
+                                             char **papszSiblingFiles) :
+    GDALMDReaderBase(pszPath, papszSiblingFiles),
+    m_osXMLSourceFilename( GDALFindAssociatedFile( pszPath, "XML",
+                                                    papszSiblingFiles, 0 ) )
 {
-    m_osXMLSourceFilename = GDALFindAssociatedFile( pszPath, "XML",
-                                                         papszSiblingFiles, 0 );
-    if( m_osXMLSourceFilename.size() )
+    if( !m_osXMLSourceFilename.empty() )
         CPLDebug( "MDReaderResursDK1", "XML Filename: %s",
                   m_osXMLSourceFilename.c_str() );
 }
@@ -118,7 +126,6 @@ void GDALMDReaderResursDK1::LoadMetadata()
                                            CPLStripQuotes(pszSatId));
     }
 
-
     const char* pszDate = CSLFetchNameValue(m_papszIMDMD,
                                             "MSP_ROOT.Normal.dSceneDate");
 
diff --git a/gcore/mdreader/reader_rdk1.h b/gcore/mdreader/reader_rdk1.h
index f1889c8..6446713 100644
--- a/gcore/mdreader/reader_rdk1.h
+++ b/gcore/mdreader/reader_rdk1.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: reader_rdk1.h 29915 2015-08-29 21:29:57Z rouault $
+ * $Id: reader_rdk1.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Resurs-DK1 imagery.
@@ -50,13 +50,13 @@ class GDALMDReaderResursDK1: public GDALMDReaderBase
 public:
     GDALMDReaderResursDK1(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderResursDK1();
-    virtual bool HasRequiredFiles() const;
-    virtual char** GetMetadataFiles() const;
+    virtual bool HasRequiredFiles() const override;
+    virtual char** GetMetadataFiles() const override;
 protected:
-    virtual void LoadMetadata();
-    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime);
+    virtual void LoadMetadata() override;
+    virtual time_t GetAcquisitionTimeFromString(const char* pszDateTime) override;
     virtual char** AddXMLNameValueToList(char** papszList, const char *pszName,
-                                         const char *pszValue);
+                                         const char *pszValue) override;
 protected:
     CPLString m_osXMLSourceFilename;
 };
diff --git a/gcore/mdreader/reader_spot.cpp b/gcore/mdreader/reader_spot.cpp
index 493c35d..5bc8152 100644
--- a/gcore/mdreader/reader_spot.cpp
+++ b/gcore/mdreader/reader_spot.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Spot imagery.
@@ -28,8 +27,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "reader_spot.h"
 
+#include <ctime>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "gdal_mdreader.h"
+
+CPL_CVSID("$Id: reader_spot.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 /**
  * GDALMDReaderSpot()
  */
@@ -83,7 +93,7 @@ GDALMDReaderSpot::GDALMDReaderSpot(const char *pszPath,
         }
     }
 
-    if(m_osIMDSourceFilename.size())
+    if(!m_osIMDSourceFilename.empty() )
         CPLDebug( "MDReaderSpot", "IMD Filename: %s",
               m_osIMDSourceFilename.c_str() );
 }
@@ -146,7 +156,6 @@ void GDALMDReaderSpot::LoadMetadata()
         }
     }
 
-
     const char* pszSatId2;
     if(nCounter == -1)
         pszSatId2 = CSLFetchNameValue(m_papszIMDMD,
@@ -174,7 +183,6 @@ void GDALMDReaderSpot::LoadMetadata()
                                 MD_NAME_SATELLITE, CPLStripQuotes(pszSatId2));
     }
 
-
     const char* pszDate;
     if(nCounter == -1)
         pszDate = CSLFetchNameValue(m_papszIMDMD,
@@ -210,7 +218,6 @@ void GDALMDReaderSpot::LoadMetadata()
                                        MD_CLOUDCOVER_NA);
 }
 
-
 /**
  * ReadXMLToList()
  */
diff --git a/gcore/mdreader/reader_spot.h b/gcore/mdreader/reader_spot.h
index c8809c3..1ad51d1 100644
--- a/gcore/mdreader/reader_spot.h
+++ b/gcore/mdreader/reader_spot.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: reader_spot.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL Core
  * Purpose:  Read metadata from Spot imagery.
@@ -51,9 +51,9 @@ public:
     GDALMDReaderSpot(const char *pszPath, char **papszSiblingFiles);
     virtual ~GDALMDReaderSpot();
 protected:
-    virtual void LoadMetadata();
+    virtual void LoadMetadata() override;
     virtual char** ReadXMLToList(CPLXMLNode* psNode, char** papszList,
-                                 const char* pszName = "");
+                                 const char* pszName = "") override;
 };
 
 #endif // READER_SPOT_H_INCLUDED
diff --git a/gcore/overview.cpp b/gcore/overview.cpp
index bfdc8eb..c645048 100644
--- a/gcore/overview.cpp
+++ b/gcore/overview.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: overview.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Helper code to implement overview support in different drivers.
@@ -28,12 +27,27 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <limits>
-
+#include "cpl_port.h"
 #include "gdal_priv.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+
+#include <algorithm>
+#include <limits>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+// TODO(schwehr): Fix warning: Software emulation of SSE2.
+// #include "gdalsse_priv.h"
 #include "gdalwarper.h"
 
-CPL_CVSID("$Id: overview.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: overview.cpp 37377 2017-02-13 18:43:53Z rouault $");
 
 /************************************************************************/
 /*                     GDALResampleChunk32R_Near()                      */
@@ -42,19 +56,17 @@ CPL_CVSID("$Id: overview.cpp 33808 2016-03-29 21:15:28Z goatbar $");
 template <class T>
 static CPLErr
 GDALResampleChunk32R_NearT( double dfXRatioDstToSrc,
-                              double dfYRatioDstToSrc,
-                              GDALDataType eWrkDataType,
-                              T * pChunk,
-                              int nChunkXOff, int nChunkXSize,
-                              int nChunkYOff,
-                              int nDstXOff, int nDstXOff2,
-                              int nDstYOff, int nDstYOff2,
-                              GDALRasterBand * poOverview)
+                            double dfYRatioDstToSrc,
+                            GDALDataType eWrkDataType,
+                            T * pChunk,
+                            int nChunkXOff, int nChunkXSize,
+                            int nChunkYOff,
+                            int nDstXOff, int nDstXOff2,
+                            int nDstYOff, int nDstYOff2,
+                            GDALRasterBand * poOverview )
 
 {
-    CPLErr eErr = CE_None;
-
-    int nDstXWidth = nDstXOff2 - nDstXOff;
+    const int nDstXWidth = nDstXOff2 - nDstXOff;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate scanline buffer.                                       */
@@ -63,7 +75,8 @@ GDALResampleChunk32R_NearT( double dfXRatioDstToSrc,
     T* pDstScanline = static_cast<T *>(
         VSI_MALLOC_VERBOSE(
             nDstXWidth * GDALGetDataTypeSizeBytes(eWrkDataType) ) );
-    int* panSrcXOff = (int*)VSI_MALLOC_VERBOSE(nDstXWidth * sizeof(int));
+    int* panSrcXOff = static_cast<int *>(
+        VSI_MALLOC_VERBOSE(nDstXWidth * sizeof(int)) );
 
     if( pDstScanline == NULL || panSrcXOff == NULL )
     {
@@ -75,10 +88,10 @@ GDALResampleChunk32R_NearT( double dfXRatioDstToSrc,
 /* ==================================================================== */
 /*      Precompute inner loop constants.                                */
 /* ==================================================================== */
-    for( int iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
+    for( int iDstPixel = nDstXOff; iDstPixel < nDstXOff2; ++iDstPixel )
     {
-        int nSrcXOff = (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
-        if ( nSrcXOff < nChunkXOff )
+        int nSrcXOff = static_cast<int>(0.5 + iDstPixel * dfXRatioDstToSrc);
+        if( nSrcXOff < nChunkXOff )
             nSrcXOff = nChunkXOff;
 
         panSrcXOff[iDstPixel - nDstXOff] = nSrcXOff;
@@ -87,28 +100,30 @@ GDALResampleChunk32R_NearT( double dfXRatioDstToSrc,
 /* ==================================================================== */
 /*      Loop over destination scanlines.                                */
 /* ==================================================================== */
-    for( int iDstLine = nDstYOff; iDstLine < nDstYOff2 && eErr == CE_None; iDstLine++ )
+    CPLErr eErr = CE_None;
+    for( int iDstLine = nDstYOff;
+         iDstLine < nDstYOff2 && eErr == CE_None;
+         ++iDstLine )
     {
-        T *pSrcScanline;
-        int   nSrcYOff;
-
-        nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
-        if ( nSrcYOff < nChunkYOff )
+        int   nSrcYOff = static_cast<int>(0.5 + iDstLine * dfYRatioDstToSrc);
+        if( nSrcYOff < nChunkYOff )
             nSrcYOff = nChunkYOff;
 
-        pSrcScanline = pChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize) - nChunkXOff;
+        const T * const pSrcScanline =
+            pChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize) - nChunkXOff;
 
 /* -------------------------------------------------------------------- */
 /*      Loop over destination pixels                                    */
 /* -------------------------------------------------------------------- */
-        for( int iDstPixel = 0; iDstPixel < nDstXWidth; iDstPixel++ )
+        for( int iDstPixel = 0; iDstPixel < nDstXWidth; ++iDstPixel )
         {
             pDstScanline[iDstPixel] = pSrcScanline[panSrcXOff[iDstPixel]];
         }
 
-        eErr = poOverview->RasterIO( GF_Write, nDstXOff, iDstLine, nDstXWidth, 1,
-                                     pDstScanline, nDstXWidth, 1, eWrkDataType,
-                                     0, 0, NULL );
+        eErr = poOverview->RasterIO(
+            GF_Write, nDstXOff, iDstLine, nDstXWidth, 1,
+            pDstScanline, nDstXWidth, 1, eWrkDataType,
+            0, 0, NULL );
     }
 
     CPLFree( pDstScanline );
@@ -119,55 +134,59 @@ GDALResampleChunk32R_NearT( double dfXRatioDstToSrc,
 
 static CPLErr
 GDALResampleChunk32R_Near( double dfXRatioDstToSrc,
-                        double dfYRatioDstToSrc,
-                        CPL_UNUSED double dfSrcXDelta,
-                        CPL_UNUSED double dfSrcYDelta,
-                        GDALDataType eWrkDataType,
-                        void * pChunk,
-                        CPL_UNUSED GByte * pabyChunkNodataMask_unused,
-                        int nChunkXOff, int nChunkXSize,
-                        int nChunkYOff, CPL_UNUSED int nChunkYSize,
-                        int nDstXOff, int nDstXOff2,
-                        int nDstYOff, int nDstYOff2,
-                        GDALRasterBand * poOverview,
-                        CPL_UNUSED const char * pszResampling_unused,
-                        CPL_UNUSED int bHasNoData_unused,
-                        CPL_UNUSED float fNoDataValue_unused,
-                        CPL_UNUSED GDALColorTable* poColorTable_unused,
-                        CPL_UNUSED GDALDataType eSrcDataType)
+                           double dfYRatioDstToSrc,
+                           double /* dfSrcXDelta */,
+                           double /* dfSrcYDelta */,
+                           GDALDataType eWrkDataType,
+                           void * pChunk,
+                           GByte * /* pabyChunkNodataMask_unused */,
+                           int nChunkXOff, int nChunkXSize,
+                           int nChunkYOff, int /* nChunkYSize */,
+                           int nDstXOff, int nDstXOff2,
+                           int nDstYOff, int nDstYOff2,
+                           GDALRasterBand * poOverview,
+                           const char * /* pszResampling_unused */,
+                           int /* bHasNoData_unused */,
+                           float /* fNoDataValue_unused */,
+                           GDALColorTable* /* poColorTable_unused */,
+                           GDALDataType /* eSrcDataType */,
+                           bool /* bPropagateNoData */ )
 {
-    if (eWrkDataType == GDT_Byte)
-        return GDALResampleChunk32R_NearT(dfXRatioDstToSrc,
-                        dfYRatioDstToSrc,
-                        eWrkDataType,
-                        (GByte *) pChunk,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        poOverview);
-    else if (eWrkDataType == GDT_UInt16)
-        return GDALResampleChunk32R_NearT(dfXRatioDstToSrc,
-                        dfYRatioDstToSrc,
-                        eWrkDataType,
-                        (GInt16 *) pChunk,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        poOverview);
-    else if (eWrkDataType == GDT_Float32)
-        return GDALResampleChunk32R_NearT(dfXRatioDstToSrc,
-                        dfYRatioDstToSrc,
-                        eWrkDataType,
-                        (float *) pChunk,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        poOverview);
-
-    CPLAssert(0);
+    if( eWrkDataType == GDT_Byte )
+        return GDALResampleChunk32R_NearT(
+            dfXRatioDstToSrc,
+            dfYRatioDstToSrc,
+            eWrkDataType,
+            static_cast<GByte *>( pChunk ),
+            nChunkXOff, nChunkXSize,
+            nChunkYOff,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            poOverview );
+    else if( eWrkDataType == GDT_UInt16 )
+        return GDALResampleChunk32R_NearT(
+            dfXRatioDstToSrc,
+            dfYRatioDstToSrc,
+            eWrkDataType,
+            static_cast<GInt16 *>( pChunk ),
+            nChunkXOff, nChunkXSize,
+            nChunkYOff,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            poOverview );
+    else if( eWrkDataType == GDT_Float32 )
+        return GDALResampleChunk32R_NearT(
+            dfXRatioDstToSrc,
+            dfYRatioDstToSrc,
+            eWrkDataType,
+            static_cast<float *>( pChunk ),
+            nChunkXOff, nChunkXSize,
+            nChunkYOff,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            poOverview);
+
+    CPLAssert(false);
     return CE_Failure;
 }
 
@@ -175,19 +194,23 @@ GDALResampleChunk32R_Near( double dfXRatioDstToSrc,
 /*                          GDALFindBestEntry()                         */
 /************************************************************************/
 
-static int GDALFindBestEntry(int nEntryCount, const GDALColorEntry* aEntries,
-                             int nR, int nG, int nB, int nNoDataIndex)
+// Find in the color table the entry whose (c1,c2,c3) value is the closest
+// (using quadratic distance) to the passed (nR,nG,nB) triplet, ignoring
+// transparent entries.
+static int GDALFindBestEntry( int nEntryCount, const GDALColorEntry* aEntries,
+                              int nR, int nG, int nB )
 {
     int nMinDist = std::numeric_limits<int>::max();
-    int iBestEntry = (nNoDataIndex != 0 || nEntryCount == 1) ? 0 : 1;
-    for( int i=0; i < nEntryCount; i++ )
+    int iBestEntry = 0;
+    for( int i = 0; i < nEntryCount; ++i )
     {
-        if (i == nNoDataIndex || aEntries[i].c4 == 0)
+        // Ignore transparent entries
+        if( aEntries[i].c4 == 0 )
             continue;
         int nDist = (nR - aEntries[i].c1) *  (nR - aEntries[i].c1) +
             (nG - aEntries[i].c2) *  (nG - aEntries[i].c2) +
             (nB - aEntries[i].c3) *  (nB - aEntries[i].c3);
-        if (nDist < nMinDist)
+        if( nDist < nMinDist )
         {
             nMinDist = nDist;
             iBestEntry = i;
@@ -197,20 +220,25 @@ static int GDALFindBestEntry(int nEntryCount, const GDALColorEntry* aEntries,
 }
 
 /************************************************************************/
-/*                      ReadColorTableAsArray()                        */
+/*                      ReadColorTableAsArray()                         */
 /************************************************************************/
 
-static bool ReadColorTableAsArray(const GDALColorTable* poColorTable,
-                                  int& nEntryCount,
-                                  GDALColorEntry*& aEntries)
+static bool ReadColorTableAsArray( const GDALColorTable* poColorTable,
+                                   int& nEntryCount,
+                                   GDALColorEntry*& aEntries,
+                                   int& nTransparentIdx )
 {
     nEntryCount = poColorTable->GetColorEntryCount();
-    aEntries = (GDALColorEntry* )VSI_MALLOC2_VERBOSE(sizeof(GDALColorEntry), nEntryCount);
+    aEntries = static_cast<GDALColorEntry *>(
+        VSI_MALLOC2_VERBOSE(sizeof(GDALColorEntry), nEntryCount) );
+    nTransparentIdx = -1;
     if( aEntries == NULL )
         return false;
-    for(int i=0;i<nEntryCount;i++)
+    for( int i = 0; i < nEntryCount; ++i )
     {
         poColorTable->GetColorEntryAsRGB(i, &aEntries[i]);
+        if( nTransparentIdx < 0 && aEntries[i].c4 == 0 )
+            nTransparentIdx = i;
     }
     return true;
 }
@@ -222,33 +250,35 @@ static bool ReadColorTableAsArray(const GDALColorTable* poColorTable,
 template <class T, class Tsum>
 static CPLErr
 GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
-                                 double dfYRatioDstToSrc,
-                                 GDALDataType eWrkDataType,
-                                 T* pChunk,
-                                 GByte * pabyChunkNodataMask,
-                                 int nChunkXOff, int nChunkXSize,
-                                 int nChunkYOff, int nChunkYSize,
-                                 int nDstXOff, int nDstXOff2,
-                                 int nDstYOff, int nDstYOff2,
-                                 GDALRasterBand * poOverview,
-                                 const char * pszResampling,
-                                 int bHasNoData, float fNoDataValue,
-                                 GDALColorTable* poColorTable)
+                               double dfYRatioDstToSrc,
+                               double dfSrcXDelta,
+                               double dfSrcYDelta,
+                               GDALDataType eWrkDataType,
+                               T* pChunk,
+                               GByte * pabyChunkNodataMask,
+                               int nChunkXOff, int nChunkXSize,
+                               int nChunkYOff, int nChunkYSize,
+                               int nDstXOff, int nDstXOff2,
+                               int nDstYOff, int nDstYOff2,
+                               GDALRasterBand * poOverview,
+                               const char * pszResampling,
+                               int bHasNoData,  // TODO(schwehr): bool.
+                               float fNoDataValue,
+                               GDALColorTable* poColorTable,
+                               bool bPropagateNoData )
 {
-    int bBit2Grayscale = STARTS_WITH_CI(pszResampling,"AVERAGE_BIT2G" /* AVERAGE_BIT2GRAYSCALE */);
-    if (bBit2Grayscale)
+    // AVERAGE_BIT2GRAYSCALE
+    const bool bBit2Grayscale =
+        CPL_TO_BOOL( STARTS_WITH_CI( pszResampling, "AVERAGE_BIT2G" ) );
+    if( bBit2Grayscale )
         poColorTable = NULL;
 
-
     T tNoDataValue;
-    if (!bHasNoData)
+    if( !bHasNoData )
         tNoDataValue = 0;
     else
         tNoDataValue = (T)fNoDataValue;
 
-    int nOXSize = poOverview->GetXSize();
-    int nOYSize = poOverview->GetYSize();
-
     int nChunkRightXOff = nChunkXOff + nChunkXSize;
     int nChunkBottomYOff = nChunkYOff + nChunkYSize;
     int nDstXWidth = nDstXOff2 - nDstXOff;
@@ -260,7 +290,8 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
     T *pDstScanline = static_cast<T *>(
         VSI_MALLOC_VERBOSE(
             nDstXWidth * GDALGetDataTypeSizeBytes(eWrkDataType) ) );
-    int* panSrcXOffShifted = (int*)VSI_MALLOC_VERBOSE(2 * nDstXWidth * sizeof(int));
+    int* panSrcXOffShifted = static_cast<int *>(
+        VSI_MALLOC_VERBOSE(2 * nDstXWidth * sizeof(int) ) );
 
     if( pDstScanline == NULL || panSrcXOffShifted == NULL )
     {
@@ -271,41 +302,75 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
 
     int nEntryCount = 0;
     GDALColorEntry* aEntries = NULL;
-    if(poColorTable && !ReadColorTableAsArray(poColorTable,nEntryCount,aEntries))
+    int nTransparentIdx = -1;
+
+    if( poColorTable &&
+        !ReadColorTableAsArray(poColorTable, nEntryCount, aEntries,
+                               nTransparentIdx) )
     {
         VSIFree(pDstScanline);
         VSIFree(panSrcXOffShifted);
         return CE_Failure;
     }
 
+    // Force c4 of nodata entry to 0 so that GDALFindBestEntry() identifies
+    // it as nodata value
+    if( bHasNoData && fNoDataValue >= 0.0f && tNoDataValue < nEntryCount )
+    {
+        if( aEntries == NULL )
+        {
+            CPLError(CE_Failure, CPLE_ObjectNull, "No aEntries.");
+            VSIFree(pDstScanline);
+            VSIFree(panSrcXOffShifted);
+            return CE_Failure;
+        }
+        aEntries[static_cast<int>(tNoDataValue)].c4 = 0;
+    }
+    // Or if we have no explicit nodata, but a color table entry that is
+    // transparent, consider it as the nodata value
+    else if( !bHasNoData && nTransparentIdx >= 0 )
+    {
+        bHasNoData = TRUE;
+        tNoDataValue = static_cast<T>(nTransparentIdx);
+    }
+
 /* ==================================================================== */
 /*      Precompute inner loop constants.                                */
 /* ==================================================================== */
-    int iDstPixel;
     bool bSrcXSpacingIsTwo = true;
-    for( iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
-    {
-        int   nSrcXOff, nSrcXOff2;
-
-        nSrcXOff =
-            (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
-        if ( nSrcXOff < nChunkXOff )
+    for( int iDstPixel = nDstXOff; iDstPixel < nDstXOff2; ++iDstPixel )
+    {
+        double dfSrcXOff = dfSrcXDelta + iDstPixel * dfXRatioDstToSrc;
+        // Apply some epsilon to avoid numerical precision issues
+        int nSrcXOff = static_cast<int>(dfSrcXOff + 1e-8);
+#ifdef only_pixels_with_more_than_10_pct_participation
+        // When oversampling, don't take into account pixels that have a tiny
+        // participation in the resulting pixel
+        if( dfXRatioDstToSrc > 1 && dfSrcXOff - nSrcXOff > 0.9 &&
+            nSrcXOff < nChunkRightXOff)
+            nSrcXOff ++;
+#endif
+        if( nSrcXOff < nChunkXOff )
             nSrcXOff = nChunkXOff;
-        nSrcXOff2 = (int)
-            (0.5 + (iDstPixel+1)* dfXRatioDstToSrc);
+
+        double dfSrcXOff2 = dfSrcXDelta + (iDstPixel+1)* dfXRatioDstToSrc;
+        int nSrcXOff2 = static_cast<int>(ceil(dfSrcXOff2 - 1e-8));
+#ifdef only_pixels_with_more_than_10_pct_participation
+        // When oversampling, don't take into account pixels that have a tiny
+        // participation in the resulting pixel
+        if( dfXRatioDstToSrc > 1 && nSrcXOff2 - dfSrcXOff2 > 0.9 &&
+            nSrcXOff2 > nChunkXOff)
+            nSrcXOff2 --;
+#endif
         if( nSrcXOff2 == nSrcXOff )
             nSrcXOff2 ++;
-
-        if( nSrcXOff2 > nChunkRightXOff || (dfXRatioDstToSrc > 1 && iDstPixel == nOXSize-1) )
-        {
-            if( nSrcXOff == nChunkRightXOff && nChunkRightXOff - 1 >= nChunkXOff )
-                nSrcXOff = nChunkRightXOff - 1;
+        if( nSrcXOff2 > nChunkRightXOff )
             nSrcXOff2 = nChunkRightXOff;
-        }
 
         panSrcXOffShifted[2 * (iDstPixel - nDstXOff)] = nSrcXOff - nChunkXOff;
-        panSrcXOffShifted[2 * (iDstPixel - nDstXOff) + 1] = nSrcXOff2 - nChunkXOff;
-        if (nSrcXOff2 - nSrcXOff != 2)
+        panSrcXOffShifted[2 * (iDstPixel - nDstXOff) + 1] =
+            nSrcXOff2 - nChunkXOff;
+        if( nSrcXOff2 - nSrcXOff != 2 )
             bSrcXSpacingIsTwo = false;
     }
 
@@ -313,44 +378,57 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
 /*      Loop over destination scanlines.                                */
 /* ==================================================================== */
     CPLErr eErr = CE_None;
-    for( int iDstLine = nDstYOff; iDstLine < nDstYOff2 && eErr == CE_None; iDstLine++ )
-    {
-        int nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
-        if ( nSrcYOff < nChunkYOff )
+    for( int iDstLine = nDstYOff;
+         iDstLine < nDstYOff2 && eErr == CE_None;
+         ++iDstLine )
+    {
+        double dfSrcYOff = dfSrcYDelta + iDstLine * dfYRatioDstToSrc;
+        int nSrcYOff = static_cast<int>(dfSrcYOff + 1e-8);
+#ifdef only_pixels_with_more_than_10_pct_participation
+        // When oversampling, don't take into account pixels that have a tiny
+        // participation in the resulting pixel
+        if( dfYRatioDstToSrc > 1 && dfSrcYOff - nSrcYOff > 0.9 &&
+            nSrcYOff < nChunkBottomYOff)
+            nSrcYOff ++;
+#endif
+        if( nSrcYOff < nChunkYOff )
             nSrcYOff = nChunkYOff;
 
-        int nSrcYOff2 =
-            (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc);
+        double dfSrcYOff2 = dfSrcYDelta + (iDstLine+1) * dfYRatioDstToSrc;
+        int nSrcYOff2 = static_cast<int>(ceil(dfSrcYOff2 - 1e-8));
+#ifdef only_pixels_with_more_than_10_pct_participation
+        // When oversampling, don't take into account pixels that have a tiny
+        // participation in the resulting pixel
+        if( dfYRatioDstToSrc > 1 && nSrcYOff2 - dfSrcYOff2 > 0.9 &&
+            nSrcYOff2 > nChunkYOff)
+            nSrcYOff2 --;
+#endif
         if( nSrcYOff2 == nSrcYOff )
-            nSrcYOff2 ++;
-
-        if( nSrcYOff2 > nChunkBottomYOff || (dfYRatioDstToSrc > 1 && iDstLine == nOYSize-1) )
-        {
-            if( nSrcYOff == nChunkBottomYOff && nChunkBottomYOff - 1 >= nChunkYOff )
-                nSrcYOff = nChunkBottomYOff - 1;
+            ++nSrcYOff2;
+        if( nSrcYOff2 > nChunkBottomYOff )
             nSrcYOff2 = nChunkBottomYOff;
-        }
-        if( nSrcYOff2 <= nSrcYOff )
-            CPLDebug("GDAL", "nSrcYOff=%d nSrcYOff2=%d", nSrcYOff, nSrcYOff2);
 
 /* -------------------------------------------------------------------- */
 /*      Loop over destination pixels                                    */
 /* -------------------------------------------------------------------- */
-        if (poColorTable == NULL)
+        if( poColorTable == NULL )
         {
-            if (bSrcXSpacingIsTwo && nSrcYOff2 == nSrcYOff + 2 &&
-                pabyChunkNodataMask == NULL && (eWrkDataType == GDT_Byte || eWrkDataType == GDT_UInt16))
+            if( bSrcXSpacingIsTwo && nSrcYOff2 == nSrcYOff + 2 &&
+                pabyChunkNodataMask == NULL &&
+                (eWrkDataType == GDT_Byte || eWrkDataType == GDT_UInt16) )
             {
-                /* Optimized case : no nodata, overview by a factor of 2 and regular x and y src spacing */
-                T* pSrcScanlineShifted = pChunk + panSrcXOffShifted[0] + (nSrcYOff - nChunkYOff) * nChunkXSize;
-                for( iDstPixel = 0; iDstPixel < nDstXWidth; iDstPixel++ )
+                // Optimized case : no nodata, overview by a factor of 2 and
+                // regular x and y src spacing.
+                const T* pSrcScanlineShifted =
+                    pChunk + panSrcXOffShifted[0] +
+                    (nSrcYOff - nChunkYOff) * nChunkXSize;
+                for( int iDstPixel = 0; iDstPixel < nDstXWidth; ++iDstPixel )
                 {
-                    Tsum nTotal;
-
-                    nTotal = pSrcScanlineShifted[0];
-                    nTotal += pSrcScanlineShifted[1];
-                    nTotal += pSrcScanlineShifted[nChunkXSize];
-                    nTotal += pSrcScanlineShifted[1+nChunkXSize];
+                    const Tsum nTotal =
+                        pSrcScanlineShifted[0]
+                        + pSrcScanlineShifted[1]
+                        + pSrcScanlineShifted[nChunkXSize]
+                        + pSrcScanlineShifted[1+nChunkXSize];
 
                     pDstScanline[iDstPixel] = (T) ((nTotal + 2) / 4);
                     pSrcScanlineShifted += 2;
@@ -361,35 +439,41 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
                 nSrcYOff -= nChunkYOff;
                 nSrcYOff2 -= nChunkYOff;
 
-                for( iDstPixel = 0; iDstPixel < nDstXWidth; iDstPixel++ )
+                for( int iDstPixel = 0; iDstPixel < nDstXWidth; ++iDstPixel )
                 {
-                    int  nSrcXOff = panSrcXOffShifted[2 * iDstPixel],
-                         nSrcXOff2 = panSrcXOffShifted[2 * iDstPixel + 1];
+                    const int nSrcXOff = panSrcXOffShifted[2 * iDstPixel];
+                    const int nSrcXOff2 = panSrcXOffShifted[2 * iDstPixel + 1];
 
-                    T val;
                     Tsum dfTotal = 0;
-                    int    nCount = 0, iX, iY;
+                    int nCount = 0;
 
-                    for( iY = nSrcYOff; iY < nSrcYOff2; iY++ )
+                    for( int iY = nSrcYOff; iY < nSrcYOff2; ++iY )
                     {
-                        for( iX = nSrcXOff; iX < nSrcXOff2; iX++ )
+                        for( int iX = nSrcXOff; iX < nSrcXOff2; ++iX )
                         {
-                            val = pChunk[iX + iY *nChunkXSize];
-                            if (pabyChunkNodataMask == NULL ||
-                                pabyChunkNodataMask[iX + iY *nChunkXSize])
+                            const T val = pChunk[iX + iY *nChunkXSize];
+                            if( pabyChunkNodataMask == NULL ||
+                                pabyChunkNodataMask[iX + iY *nChunkXSize] )
                             {
                                 dfTotal += val;
-                                nCount++;
+                                ++nCount;
                             }
                         }
                     }
 
-                    if( nCount == 0 )
+                    if( nCount == 0 ||
+                        (bPropagateNoData && nCount <
+                            (nSrcYOff2 - nSrcYOff) * (nSrcXOff2 - nSrcXOff)))
+                    {
                         pDstScanline[iDstPixel] = tNoDataValue;
-                    else if (eWrkDataType == GDT_Byte || eWrkDataType == GDT_UInt16)
-                        pDstScanline[iDstPixel] = (T) ((dfTotal + nCount / 2) / nCount);
+                    }
+                    else if( eWrkDataType == GDT_Byte ||
+                             eWrkDataType == GDT_UInt16)
+                        pDstScanline[iDstPixel] =
+                            static_cast<T>((dfTotal + nCount / 2) / nCount);
                     else
-                        pDstScanline[iDstPixel] = (T) (dfTotal / nCount);
+                        pDstScanline[iDstPixel] =
+                            static_cast<T>(dfTotal / nCount);
                 }
             }
         }
@@ -398,51 +482,54 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
             nSrcYOff -= nChunkYOff;
             nSrcYOff2 -= nChunkYOff;
 
-            for( iDstPixel = 0; iDstPixel < nDstXWidth; iDstPixel++ )
+            for( int iDstPixel = 0; iDstPixel < nDstXWidth; ++iDstPixel )
             {
                 const int nSrcXOff = panSrcXOffShifted[2 * iDstPixel];
                 const int nSrcXOff2 = panSrcXOffShifted[2 * iDstPixel + 1];
 
-                T val;
-                int    nTotalR = 0, nTotalG = 0, nTotalB = 0;
-                int    nCount = 0;
+                int nTotalR = 0;
+                int nTotalG = 0;
+                int nTotalB = 0;
+                int nCount = 0;
 
-                for( int iY = nSrcYOff; iY < nSrcYOff2; iY++ )
+                for( int iY = nSrcYOff; iY < nSrcYOff2; ++iY )
                 {
-                    for( int iX = nSrcXOff; iX < nSrcXOff2; iX++ )
+                    for( int iX = nSrcXOff; iX < nSrcXOff2; ++iX )
                     {
-                        val = pChunk[iX + iY *nChunkXSize];
-                        if (bHasNoData == FALSE || val != tNoDataValue)
+                        const T val = pChunk[iX + iY *nChunkXSize];
+                        int nVal = static_cast<int>(val);
+                        if( nVal >= 0 && nVal < nEntryCount &&
+                            aEntries[nVal].c4 )
                         {
-                            int nVal = (int)val;
-                            if (nVal >= 0 && nVal < nEntryCount)
-                            {
-                                nTotalR += aEntries[nVal].c1;
-                                nTotalG += aEntries[nVal].c2;
-                                nTotalB += aEntries[nVal].c3;
-                                nCount++;
-                            }
+                            nTotalR += aEntries[nVal].c1;
+                            nTotalG += aEntries[nVal].c2;
+                            nTotalB += aEntries[nVal].c3;
+                            ++nCount;
                         }
                     }
                 }
 
-                if( nCount == 0 )
+                if( nCount == 0 ||
+                    (bPropagateNoData && nCount <
+                        (nSrcYOff2 - nSrcYOff) * (nSrcXOff2 - nSrcXOff)) )
+                {
                     pDstScanline[iDstPixel] = tNoDataValue;
+                }
                 else
                 {
                     int nR = (nTotalR + nCount / 2) / nCount,
                         nG = (nTotalG + nCount / 2) / nCount,
                         nB = (nTotalB + nCount / 2) / nCount;
                     pDstScanline[iDstPixel] = (T)GDALFindBestEntry(
-                        nEntryCount, aEntries, nR, nG, nB,
-                        bHasNoData ? static_cast<int>(tNoDataValue) : -1);
+                        nEntryCount, aEntries, nR, nG, nB);
                 }
             }
         }
 
-        eErr = poOverview->RasterIO( GF_Write, nDstXOff, iDstLine, nDstXWidth, 1,
-                                     pDstScanline, nDstXWidth, 1, eWrkDataType,
-                                     0, 0, NULL );
+        eErr = poOverview->RasterIO(
+            GF_Write, nDstXOff, iDstLine, nDstXWidth, 1,
+            pDstScanline, nDstXWidth, 1, eWrkDataType,
+            0, 0, NULL );
     }
 
     CPLFree( pDstScanline );
@@ -454,62 +541,73 @@ GDALResampleChunk32R_AverageT( double dfXRatioDstToSrc,
 
 static CPLErr
 GDALResampleChunk32R_Average( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
-                        CPL_UNUSED double dfSrcXDelta,
-                        CPL_UNUSED double dfSrcYDelta,
-                        GDALDataType eWrkDataType,
-                        void * pChunk,
-                        GByte * pabyChunkNodataMask,
-                        int nChunkXOff, int nChunkXSize,
-                        int nChunkYOff, int nChunkYSize,
-                        int nDstXOff, int nDstXOff2,
-                        int nDstYOff, int nDstYOff2,
-                        GDALRasterBand * poOverview,
-                        const char * pszResampling,
-                        int bHasNoData, float fNoDataValue,
-                        GDALColorTable* poColorTable,
-                        CPL_UNUSED GDALDataType eSrcDataType)
+                              double dfSrcXDelta,
+                              double dfSrcYDelta,
+                              GDALDataType eWrkDataType,
+                              void * pChunk,
+                              GByte * pabyChunkNodataMask,
+                              int nChunkXOff, int nChunkXSize,
+                              int nChunkYOff, int nChunkYSize,
+                              int nDstXOff, int nDstXOff2,
+                              int nDstYOff, int nDstYOff2,
+                              GDALRasterBand * poOverview,
+                              const char * pszResampling,
+                              int bHasNoData, float fNoDataValue,
+                              GDALColorTable* poColorTable,
+                              GDALDataType /* eSrcDataType */,
+                              bool bPropagateNoData )
 {
-    if (eWrkDataType == GDT_Byte)
-        return GDALResampleChunk32R_AverageT<GByte, int>(dfXRatioDstToSrc, dfYRatioDstToSrc,
-                        eWrkDataType,
-                        (GByte *) pChunk,
-                        pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff, nChunkYSize,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        poOverview,
-                        pszResampling,
-                        bHasNoData, fNoDataValue,
-                        poColorTable);
-    else if (eWrkDataType == GDT_UInt16 && dfXRatioDstToSrc * dfYRatioDstToSrc < 65536 )
-        return GDALResampleChunk32R_AverageT<GUInt16, GUInt32>(dfXRatioDstToSrc, dfYRatioDstToSrc,
-                        eWrkDataType,
-                        (GUInt16 *) pChunk,
-                        pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff, nChunkYSize,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        poOverview,
-                        pszResampling,
-                        bHasNoData, fNoDataValue,
-                        poColorTable);
-    else if (eWrkDataType == GDT_Float32)
-        return GDALResampleChunk32R_AverageT<float, double>(dfXRatioDstToSrc, dfYRatioDstToSrc,
-                        eWrkDataType,
-                        (float *) pChunk,
-                        pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff, nChunkYSize,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        poOverview,
-                        pszResampling,
-                        bHasNoData, fNoDataValue,
-                        poColorTable);
-
-    CPLAssert(0);
+    if( eWrkDataType == GDT_Byte )
+        return GDALResampleChunk32R_AverageT<GByte, int>(
+            dfXRatioDstToSrc, dfYRatioDstToSrc,
+            dfSrcXDelta, dfSrcYDelta,
+            eWrkDataType,
+            static_cast<GByte *>( pChunk ),
+            pabyChunkNodataMask,
+            nChunkXOff, nChunkXSize,
+            nChunkYOff, nChunkYSize,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            poOverview,
+            pszResampling,
+            bHasNoData, fNoDataValue,
+            poColorTable,
+            bPropagateNoData );
+    else if( eWrkDataType == GDT_UInt16 &&
+             dfXRatioDstToSrc * dfYRatioDstToSrc < 65536 )
+        return GDALResampleChunk32R_AverageT<GUInt16, GUInt32>(
+            dfXRatioDstToSrc, dfYRatioDstToSrc,
+            dfSrcXDelta, dfSrcYDelta,
+            eWrkDataType,
+            static_cast<GUInt16 *>( pChunk ),
+            pabyChunkNodataMask,
+            nChunkXOff, nChunkXSize,
+            nChunkYOff, nChunkYSize,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            poOverview,
+            pszResampling,
+            bHasNoData, fNoDataValue,
+            poColorTable,
+            bPropagateNoData );
+    else if( eWrkDataType == GDT_Float32 )
+        return GDALResampleChunk32R_AverageT<float, double>(
+            dfXRatioDstToSrc, dfYRatioDstToSrc,
+            dfSrcXDelta, dfSrcYDelta,
+            eWrkDataType,
+            static_cast<float *>( pChunk ),
+            pabyChunkNodataMask,
+            nChunkXOff, nChunkXSize,
+            nChunkYOff, nChunkYSize,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            poOverview,
+            pszResampling,
+            bHasNoData, fNoDataValue,
+            poColorTable,
+            bPropagateNoData );
+
+    CPLAssert(false);
     return CE_Failure;
 }
 
@@ -519,25 +617,24 @@ GDALResampleChunk32R_Average( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
 
 static CPLErr
 GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
-                              CPL_UNUSED double dfSrcXDelta,
-                              CPL_UNUSED double dfSrcYDelta,
-                              CPL_UNUSED GDALDataType eWrkDataType,
-                              void * pChunk,
-                              GByte * pabyChunkNodataMask,
-                              int nChunkXOff, int nChunkXSize,
-                              int nChunkYOff, int nChunkYSize,
-                              int nDstXOff, int nDstXOff2,
-                              int nDstYOff, int nDstYOff2,
-                              GDALRasterBand * poOverview,
-                              CPL_UNUSED const char * pszResampling,
-                              int bHasNoData, float fNoDataValue,
-                              GDALColorTable* poColorTable,
-                              CPL_UNUSED GDALDataType eSrcDataType)
+                            double /* dfSrcXDelta */,
+                            double /* dfSrcYDelta */,
+                            GDALDataType /* eWrkDataType */,
+                            void * pChunk,
+                            GByte * pabyChunkNodataMask,
+                            int nChunkXOff, int nChunkXSize,
+                            int nChunkYOff, int nChunkYSize,
+                            int nDstXOff, int nDstXOff2,
+                            int nDstYOff, int nDstYOff2,
+                            GDALRasterBand * poOverview,
+                            const char * /* pszResampling */,
+                            int bHasNoData, float fNoDataValue,
+                            GDALColorTable* poColorTable,
+                            GDALDataType /* eSrcDataType */,
+                            bool /* bPropagateNoData */ )
 
 {
-    CPLErr eErr = CE_None;
-
-    float * pafChunk = (float*) pChunk;
+    float * pafChunk = static_cast<float *>( pChunk );
 
 /* -------------------------------------------------------------------- */
 /*      Create the filter kernel and allocate scanline buffer.          */
@@ -545,28 +642,28 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
     int nGaussMatrixDim = 3;
     const int *panGaussMatrix;
     static const int anGaussMatrix3x3[] ={
-        1,2,1,
-        2,4,2,
-        1,2,1
+        1, 2, 1,
+        2, 4, 2,
+        1, 2, 1
     };
     static const int anGaussMatrix5x5[] = {
-        1,4,6,4,1,
-        4,16,24,16,4,
-        6,24,36,24,6,
-        4,16,24,16,4,
-        1,4,6,4,1};
+        1, 4, 6, 4, 1,
+        4, 16, 24, 16, 4,
+        6, 24, 36, 24, 6,
+        4, 16, 24, 16, 4,
+        1, 4, 6, 4, 1};
     static const int anGaussMatrix7x7[] = {
-        1,6,15,20,15,6,1,
-        6,36,90,120,90,36,6,
-        15,90,225,300,225,90,15,
-        20,120,300,400,300,120,20,
-        15,90,225,300,225,90,15,
-        6,36,90,120,90,36,6,
-        1,6,15,20,15,6,1};
-
-    int nOXSize = poOverview->GetXSize();
-    int nOYSize = poOverview->GetYSize();
-    int nResYFactor = (int) (0.5 + dfYRatioDstToSrc);
+        1, 6, 15, 20, 15, 6, 1,
+        6, 36, 90, 120, 90, 36, 6,
+        15, 90, 225, 300, 225, 90, 15,
+        20, 120, 300, 400, 300, 120, 20,
+        15, 90, 225, 300, 225, 90, 15,
+        6, 36, 90, 120, 90, 36, 6,
+        1, 6, 15, 20, 15, 6, 1};
+
+    const int nOXSize = poOverview->GetXSize();
+    const int nOYSize = poOverview->GetYSize();
+    const int nResYFactor = static_cast<int>(0.5 + dfYRatioDstToSrc);
 
     // matrix for gauss filter
     if(nResYFactor <= 2 )
@@ -574,7 +671,7 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
         panGaussMatrix = anGaussMatrix3x3;
         nGaussMatrixDim=3;
     }
-    else if (nResYFactor <= 4)
+    else if( nResYFactor <= 4 )
     {
         panGaussMatrix = anGaussMatrix5x5;
         nGaussMatrixDim=5;
@@ -585,31 +682,60 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
         nGaussMatrixDim=7;
     }
 
-    float *pafDstScanline
-        = (float *) VSI_MALLOC_VERBOSE((nDstXOff2 - nDstXOff) * sizeof(float));
+    float *pafDstScanline = static_cast<float *>(
+        VSI_MALLOC_VERBOSE((nDstXOff2 - nDstXOff) * sizeof(float)) );
     if( pafDstScanline == NULL )
     {
         return CE_Failure;
     }
 
+    if( !bHasNoData )
+        fNoDataValue = 0.0f;
+
     int nEntryCount = 0;
     GDALColorEntry* aEntries = NULL;
-    if(poColorTable && !ReadColorTableAsArray(poColorTable,nEntryCount,aEntries))
+    int nTransparentIdx = -1;
+    if( poColorTable &&
+        !ReadColorTableAsArray(poColorTable, nEntryCount, aEntries,
+                               nTransparentIdx) )
     {
         VSIFree(pafDstScanline);
         return CE_Failure;
     }
 
-    int nChunkRightXOff = nChunkXOff + nChunkXSize;
-    int nChunkBottomYOff = nChunkYOff + nChunkYSize;
+    // Force c4 of nodata entry to 0 so that GDALFindBestEntry() identifies
+    // it as nodata value.
+    if( bHasNoData && fNoDataValue >= 0.0f && fNoDataValue < nEntryCount )
+    {
+        if( aEntries == NULL )
+        {
+            CPLError(CE_Failure, CPLE_ObjectNull, "No aEntries");
+            VSIFree(pafDstScanline);
+            return CE_Failure;
+        }
+        aEntries[static_cast<int>(fNoDataValue)].c4 = 0;
+    }
+    // Or if we have no explicit nodata, but a color table entry that is
+    // transparent, consider it as the nodata value.
+    else if( !bHasNoData && nTransparentIdx >= 0 )
+    {
+        fNoDataValue = static_cast<float>(nTransparentIdx);
+    }
+
+    const int nChunkRightXOff = nChunkXOff + nChunkXSize;
+    const int nChunkBottomYOff = nChunkYOff + nChunkYSize;
 
 /* ==================================================================== */
 /*      Loop over destination scanlines.                                */
 /* ==================================================================== */
-    for( int iDstLine = nDstYOff; iDstLine < nDstYOff2 && eErr == CE_None; iDstLine++ )
+    CPLErr eErr = CE_None;
+    for( int iDstLine = nDstYOff;
+         iDstLine < nDstYOff2 && eErr == CE_None;
+         ++iDstLine )
     {
-        int nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
-        int nSrcYOff2 = (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc) + 1;
+        int nSrcYOff = static_cast<int>(0.5 + iDstLine * dfYRatioDstToSrc);
+        int nSrcYOff2 =
+            static_cast<int>(0.5 + (iDstLine+1) * dfYRatioDstToSrc) + 1;
 
         if( nSrcYOff < nChunkYOff )
         {
@@ -617,7 +743,7 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
             nSrcYOff2++;
         }
 
-        int iSizeY = nSrcYOff2 - nSrcYOff;
+        const int iSizeY = nSrcYOff2 - nSrcYOff;
         nSrcYOff = nSrcYOff + iSizeY/2 - nGaussMatrixDim/2;
         nSrcYOff2 = nSrcYOff + nGaussMatrixDim;
         int nYShiftGaussMatrix = 0;
@@ -627,26 +753,27 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
             nSrcYOff = 0;
         }
 
-        if( nSrcYOff2 > nChunkBottomYOff || (dfYRatioDstToSrc > 1 && iDstLine == nOYSize-1) )
+        if( nSrcYOff2 > nChunkBottomYOff ||
+            (dfYRatioDstToSrc > 1 && iDstLine == nOYSize-1) )
             nSrcYOff2 = nChunkBottomYOff;
 
-        float *pafSrcScanline = pafChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize);
-        GByte *pabySrcScanlineNodataMask;
-        if (pabyChunkNodataMask != NULL)
-            pabySrcScanlineNodataMask = pabyChunkNodataMask + ((nSrcYOff-nChunkYOff) * nChunkXSize);
-        else
-            pabySrcScanlineNodataMask = NULL;
+        const float * const pafSrcScanline =
+            pafChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize);
+        GByte *pabySrcScanlineNodataMask = NULL;
+        if( pabyChunkNodataMask != NULL )
+            pabySrcScanlineNodataMask =
+                pabyChunkNodataMask + ((nSrcYOff-nChunkYOff) * nChunkXSize);
 
 /* -------------------------------------------------------------------- */
 /*      Loop over destination pixels                                    */
 /* -------------------------------------------------------------------- */
-        int  iDstPixel;
-        for( iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
+        for( int iDstPixel = nDstXOff; iDstPixel < nDstXOff2; ++iDstPixel )
         {
-            int nSrcXOff = (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
-            int nSrcXOff2 = (int)(0.5 + (iDstPixel+1) * dfXRatioDstToSrc) + 1;
+            int nSrcXOff = static_cast<int>(0.5 + iDstPixel * dfXRatioDstToSrc);
+            int nSrcXOff2 =
+                static_cast<int>(0.5 + (iDstPixel+1) * dfXRatioDstToSrc) + 1;
 
-            int iSizeX = nSrcXOff2 - nSrcXOff;
+            const int iSizeX = nSrcXOff2 - nSrcXOff;
             nSrcXOff = nSrcXOff + iSizeX/2 - nGaussMatrixDim/2;
             nSrcXOff2 = nSrcXOff + nGaussMatrixDim;
             int nXShiftGaussMatrix = 0;
@@ -656,98 +783,102 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
                 nSrcXOff = 0;
             }
 
-            if( nSrcXOff2 > nChunkRightXOff || (dfXRatioDstToSrc > 1 && iDstPixel == nOXSize-1) )
+            if( nSrcXOff2 > nChunkRightXOff ||
+                (dfXRatioDstToSrc > 1 && iDstPixel == nOXSize-1) )
                 nSrcXOff2 = nChunkRightXOff;
 
-            if (poColorTable == NULL)
+            if( poColorTable == NULL )
             {
-                double dfTotal = 0.0, val;
+                double dfTotal = 0.0;
                 int nCount = 0;
                 const int *panLineWeight = panGaussMatrix +
                     nYShiftGaussMatrix * nGaussMatrixDim + nXShiftGaussMatrix;
 
-                for( int j=0, iY = nSrcYOff; iY < nSrcYOff2;
-                        iY++, j++, panLineWeight += nGaussMatrixDim )
+                for( int j=0, iY = nSrcYOff;
+                     iY < nSrcYOff2;
+                     ++iY, ++j, panLineWeight += nGaussMatrixDim )
                 {
-                    for( int i=0, iX = nSrcXOff; iX < nSrcXOff2; iX++,++i )
+                    for( int i=0, iX = nSrcXOff; iX < nSrcXOff2; ++iX, ++i )
                     {
-                        val = pafSrcScanline[iX-nChunkXOff+(iY-nSrcYOff)*nChunkXSize];
-                        if (pabySrcScanlineNodataMask == NULL ||
-                            pabySrcScanlineNodataMask[iX-nChunkXOff+(iY-nSrcYOff)*nChunkXSize])
+                        const double val =
+                            pafSrcScanline[iX-nChunkXOff+(iY-nSrcYOff)
+                                           * nChunkXSize];
+                        if( pabySrcScanlineNodataMask == NULL ||
+                            pabySrcScanlineNodataMask[iX - nChunkXOff
+                                                      +(iY - nSrcYOff)
+                                                      * nChunkXSize] )
                         {
-                            int nWeight = panLineWeight[i];
+                            const int nWeight = panLineWeight[i];
                             dfTotal += val * nWeight;
                             nCount += nWeight;
                         }
                     }
                 }
 
-                if (bHasNoData && nCount == 0)
+                if( nCount == 0 )
                 {
                     pafDstScanline[iDstPixel - nDstXOff] = fNoDataValue;
                 }
                 else
                 {
-                    if( nCount == 0 )
-                        pafDstScanline[iDstPixel - nDstXOff] = 0.0;
-                    else
-                        pafDstScanline[iDstPixel - nDstXOff] = (float) (dfTotal / nCount);
+                    pafDstScanline[iDstPixel - nDstXOff] =
+                        static_cast<float>(dfTotal / nCount);
                 }
             }
             else
             {
-                double val;
-                int  nTotalR = 0, nTotalG = 0, nTotalB = 0;
-                int  nTotalWeight = 0;
-                const int *panLineWeight = panGaussMatrix +
-                    nYShiftGaussMatrix * nGaussMatrixDim + nXShiftGaussMatrix;
+                int nTotalR = 0;
+                int nTotalG = 0;
+                int nTotalB = 0;
+                int nTotalWeight = 0;
+                const int *panLineWeight =
+                    panGaussMatrix + nYShiftGaussMatrix * nGaussMatrixDim +
+                    nXShiftGaussMatrix;
 
                 for( int j=0, iY = nSrcYOff; iY < nSrcYOff2;
-                        iY++, j++, panLineWeight += nGaussMatrixDim )
+                        ++iY, ++j, panLineWeight += nGaussMatrixDim )
                 {
-                    for( int i=0, iX = nSrcXOff; iX < nSrcXOff2; iX++,++i )
+                    for( int i=0, iX = nSrcXOff; iX < nSrcXOff2; ++iX, ++i )
                     {
-                        val = pafSrcScanline[iX-nChunkXOff+(iY-nSrcYOff)*nChunkXSize];
-                        if (bHasNoData == FALSE || val != fNoDataValue)
+                        const double val =
+                            pafSrcScanline[iX - nChunkXOff +
+                                           (iY-nSrcYOff) * nChunkXSize];
+                        int nVal = static_cast<int>(val);
+                        if( nVal >= 0 && nVal < nEntryCount &&
+                            aEntries[nVal].c4 )
                         {
-                            int nVal = (int)val;
-                            if (nVal >= 0 && nVal < nEntryCount)
-                            {
-                                int nWeight = panLineWeight[i];
-                                nTotalR += aEntries[nVal].c1 * nWeight;
-                                nTotalG += aEntries[nVal].c2 * nWeight;
-                                nTotalB += aEntries[nVal].c3 * nWeight;
-                                nTotalWeight += nWeight;
-                            }
+                            const int nWeight = panLineWeight[i];
+                            nTotalR += aEntries[nVal].c1 * nWeight;
+                            nTotalG += aEntries[nVal].c2 * nWeight;
+                            nTotalB += aEntries[nVal].c3 * nWeight;
+                            nTotalWeight += nWeight;
                         }
                     }
                 }
 
-                if (bHasNoData && nTotalWeight == 0)
+                if( nTotalWeight == 0 )
                 {
                     pafDstScanline[iDstPixel - nDstXOff] = fNoDataValue;
                 }
                 else
                 {
-                    if( nTotalWeight == 0 )
-                        pafDstScanline[iDstPixel - nDstXOff] = 0.0;
-                    else
-                    {
-                        int nR = (nTotalR + nTotalWeight / 2) / nTotalWeight,
-                            nG = (nTotalG + nTotalWeight / 2) / nTotalWeight,
-                            nB = (nTotalB + nTotalWeight / 2) / nTotalWeight;
-                        pafDstScanline[iDstPixel - nDstXOff] =
-                            (float) GDALFindBestEntry(
-                                    nEntryCount, aEntries, nR, nG, nB, bHasNoData ? (int)fNoDataValue : -1);
-                    }
+                    const int nR =
+                        (nTotalR + nTotalWeight / 2) / nTotalWeight;
+                    const int nG =
+                        (nTotalG + nTotalWeight / 2) / nTotalWeight;
+                    const int nB =
+                        (nTotalB + nTotalWeight / 2) / nTotalWeight;
+                    pafDstScanline[iDstPixel - nDstXOff] =
+                        static_cast<float>( GDALFindBestEntry(
+                            nEntryCount, aEntries, nR, nG, nB ) );
                 }
             }
-
         }
 
-        eErr = poOverview->RasterIO( GF_Write, nDstXOff, iDstLine, nDstXOff2 - nDstXOff, 1,
-                                     pafDstScanline, nDstXOff2 - nDstXOff, 1, GDT_Float32,
-                                     0, 0, NULL );
+        eErr = poOverview->RasterIO(
+            GF_Write, nDstXOff, iDstLine, nDstXOff2 - nDstXOff, 1,
+            pafDstScanline, nDstXOff2 - nDstXOff, 1, GDT_Float32,
+            0, 0, NULL );
     }
 
     CPLFree( pafDstScanline );
@@ -762,135 +893,160 @@ GDALResampleChunk32R_Gauss( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
 
 static CPLErr
 GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
-                             CPL_UNUSED double dfSrcXDelta,
-                             CPL_UNUSED double dfSrcYDelta,
-                             CPL_UNUSED GDALDataType eWrkDataType,
-                             void * pChunk,
-                             GByte * pabyChunkNodataMask,
-                             int nChunkXOff, int nChunkXSize,
-                             int nChunkYOff, int nChunkYSize,
-                             int nDstXOff, int nDstXOff2,
-                             int nDstYOff, int nDstYOff2,
-                             GDALRasterBand * poOverview,
-                             CPL_UNUSED const char * pszResampling,
-                             int bHasNoData, float fNoDataValue,
-                             GDALColorTable* poColorTable,
-                             GDALDataType eSrcDataType)
+                           double dfSrcXDelta,
+                           double dfSrcYDelta,
+                           GDALDataType /* eWrkDataType */,
+                           void * pChunk,
+                           GByte * pabyChunkNodataMask,
+                           int nChunkXOff, int nChunkXSize,
+                           int nChunkYOff, int nChunkYSize,
+                           int nDstXOff, int nDstXOff2,
+                           int nDstYOff, int nDstYOff2,
+                           GDALRasterBand * poOverview,
+                           const char * /* pszResampling */,
+                           int bHasNoData, float fNoDataValue,
+                           GDALColorTable* poColorTable,
+                           GDALDataType eSrcDataType,
+                           bool /* bPropagateNoData */ )
 
 {
-    float * pafChunk = (float*) pChunk;
+    float * pafChunk = static_cast<float*>( pChunk );
 
 /* -------------------------------------------------------------------- */
 /*      Create the filter kernel and allocate scanline buffer.          */
 /* -------------------------------------------------------------------- */
-    int nOXSize, nOYSize;
-    float    *pafDstScanline;
-
-    nOXSize = poOverview->GetXSize();
-    nOYSize = poOverview->GetYSize();
-
-    pafDstScanline = (float *) VSI_MALLOC_VERBOSE((nDstXOff2 - nDstXOff) * sizeof(float));
+    float *pafDstScanline = static_cast<float *>(
+        VSI_MALLOC_VERBOSE((nDstXOff2 - nDstXOff) * sizeof(float)) );
     if( pafDstScanline == NULL )
     {
         return CE_Failure;
     }
 
+    if( !bHasNoData )
+        fNoDataValue = 0.0f;
     int nEntryCount = 0;
     GDALColorEntry* aEntries = NULL;
-    if(poColorTable && !ReadColorTableAsArray(poColorTable,nEntryCount,aEntries))
+    int nTransparentIdx = -1;
+    if( poColorTable &&
+        !ReadColorTableAsArray(poColorTable, nEntryCount,
+                               aEntries, nTransparentIdx) )
     {
         VSIFree(pafDstScanline);
         return CE_Failure;
     }
 
-    int      nMaxNumPx = 0;
-    float*   pafVals = NULL;
-    int*     panSums = NULL;
+    int nMaxNumPx = 0;
+    float *pafVals = NULL;
+    int *panSums = NULL;
 
-    int nChunkRightXOff = nChunkXOff + nChunkXSize;
-    int nChunkBottomYOff = nChunkYOff + nChunkYSize;
+    const int nChunkRightXOff = nChunkXOff + nChunkXSize;
+    const int nChunkBottomYOff = nChunkYOff + nChunkYSize;
 
 /* ==================================================================== */
 /*      Loop over destination scanlines.                                */
 /* ==================================================================== */
     CPLErr eErr = CE_None;
-    for( int iDstLine = nDstYOff; iDstLine < nDstYOff2 && eErr == CE_None; iDstLine++ )
-    {
-        int iDstPixel;
-
-        int nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
-        if ( nSrcYOff < nChunkYOff )
+    for( int iDstLine = nDstYOff;
+         iDstLine < nDstYOff2 && eErr == CE_None;
+         ++iDstLine )
+    {
+        double dfSrcYOff = dfSrcYDelta + iDstLine * dfYRatioDstToSrc;
+        int nSrcYOff = static_cast<int>(dfSrcYOff + 1e-8);
+#ifdef only_pixels_with_more_than_10_pct_participation
+        // When oversampling, don't take into account pixels that have a tiny
+        // participation in the resulting pixel
+        if( dfYRatioDstToSrc > 1 && dfSrcYOff - nSrcYOff > 0.9 &&
+            nSrcYOff < nChunkBottomYOff)
+            nSrcYOff ++;
+#endif
+        if( nSrcYOff < nChunkYOff )
             nSrcYOff = nChunkYOff;
 
-        int nSrcYOff2 =
-            (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc);
+        double dfSrcYOff2 = dfSrcYDelta + (iDstLine+1) * dfYRatioDstToSrc;
+        int nSrcYOff2 = static_cast<int>(ceil(dfSrcYOff2 - 1e-8));
+#ifdef only_pixels_with_more_than_10_pct_participation
+        // When oversampling, don't take into account pixels that have a tiny
+        // participation in the resulting pixel
+        if( dfYRatioDstToSrc > 1 && nSrcYOff2 - dfSrcYOff2 > 0.9 &&
+            nSrcYOff2 > nChunkYOff)
+            nSrcYOff2 --;
+#endif
         if( nSrcYOff2 == nSrcYOff )
-            nSrcYOff2 ++;
-
-        if( nSrcYOff2 > nChunkBottomYOff || (dfYRatioDstToSrc > 1 && iDstLine == nOYSize-1) )
-        {
-            if( nSrcYOff == nChunkBottomYOff && nChunkBottomYOff - 1 >= nChunkYOff )
-                nSrcYOff = nChunkBottomYOff - 1;
+            ++nSrcYOff2;
+        if( nSrcYOff2 > nChunkBottomYOff )
             nSrcYOff2 = nChunkBottomYOff;
-        }
 
-        float *pafSrcScanline = pafChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize);
-        GByte *pabySrcScanlineNodataMask;
-        if (pabyChunkNodataMask != NULL)
-            pabySrcScanlineNodataMask = pabyChunkNodataMask + ((nSrcYOff-nChunkYOff) * nChunkXSize);
-        else
-            pabySrcScanlineNodataMask = NULL;
+        const float * const pafSrcScanline =
+            pafChunk + ((nSrcYOff-nChunkYOff) * nChunkXSize);
+        GByte *pabySrcScanlineNodataMask = NULL;
+        if( pabyChunkNodataMask != NULL )
+            pabySrcScanlineNodataMask =
+                pabyChunkNodataMask + (nSrcYOff-nChunkYOff) * nChunkXSize;
 
 /* -------------------------------------------------------------------- */
 /*      Loop over destination pixels                                    */
 /* -------------------------------------------------------------------- */
-        for( iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
+        for( int iDstPixel = nDstXOff; iDstPixel < nDstXOff2; ++iDstPixel )
         {
-            int nSrcXOff =
-                (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
-            if ( nSrcXOff < nChunkXOff )
+            double dfSrcXOff = dfSrcXDelta + iDstPixel * dfXRatioDstToSrc;
+            // Apply some epsilon to avoid numerical precision issues
+            int nSrcXOff = static_cast<int>(dfSrcXOff + 1e-8);
+#ifdef only_pixels_with_more_than_10_pct_participation
+            // When oversampling, don't take into account pixels that have a tiny
+            // participation in the resulting pixel
+            if( dfXRatioDstToSrc > 1 && dfSrcXOff - nSrcXOff > 0.9 &&
+                nSrcXOff < nChunkRightXOff)
+                nSrcXOff ++;
+#endif
+            if( nSrcXOff < nChunkXOff )
                 nSrcXOff = nChunkXOff;
-            int nSrcXOff2 = (int)
-                (0.5 + (iDstPixel+1) * dfXRatioDstToSrc);
+
+            double dfSrcXOff2 = dfSrcXDelta + (iDstPixel+1)* dfXRatioDstToSrc;
+            int nSrcXOff2 = static_cast<int>(ceil(dfSrcXOff2 - 1e-8));
+#ifdef only_pixels_with_more_than_10_pct_participation
+            // When oversampling, don't take into account pixels that have a tiny
+            // participation in the resulting pixel
+            if( dfXRatioDstToSrc > 1 && nSrcXOff2 - dfSrcXOff2 > 0.9 &&
+                nSrcXOff2 > nChunkXOff)
+                nSrcXOff2 --;
+#endif
             if( nSrcXOff2 == nSrcXOff )
                 nSrcXOff2 ++;
-
-            if( nSrcXOff2 > nChunkRightXOff || (dfXRatioDstToSrc > 1 && iDstPixel == nOXSize-1) )
-            {
-                if( nSrcXOff == nChunkRightXOff && nChunkRightXOff - 1 >= nChunkXOff )
-                    nSrcXOff = nChunkRightXOff - 1;
+            if( nSrcXOff2 > nChunkRightXOff )
                 nSrcXOff2 = nChunkRightXOff;
-            }
 
-            if (eSrcDataType != GDT_Byte || nEntryCount > 256)
+            if( eSrcDataType != GDT_Byte || nEntryCount > 256 )
             {
-                /* I'm not sure how much sense it makes to run a majority
-                    filter on floating point data, but here it is for the sake
-                    of compatibility. It won't look right on RGB images by the
-                    nature of the filter. */
-                int     nNumPx = (nSrcYOff2-nSrcYOff)*(nSrcXOff2-nSrcXOff);
-                int     iMaxInd = 0, iMaxVal = -1, iY, iX;
-
-                if (pafVals == NULL || nNumPx > nMaxNumPx)
+                // Not sure how much sense it makes to run a majority
+                // filter on floating point data, but here it is for the sake
+                // of compatibility. It won't look right on RGB images by the
+                // nature of the filter.
+                int nNumPx = (nSrcYOff2-nSrcYOff)*(nSrcXOff2-nSrcXOff);
+                int iMaxInd = 0;
+                int iMaxVal = -1;
+
+                if( pafVals == NULL || nNumPx > nMaxNumPx )
                 {
-                    pafVals = (float*) CPLRealloc(pafVals, nNumPx * sizeof(float));
-                    panSums = (int*) CPLRealloc(panSums, nNumPx * sizeof(int));
+                    pafVals = static_cast<float *>(
+                        CPLRealloc(pafVals, nNumPx * sizeof(float)) );
+                    panSums = static_cast<int *>(
+                        CPLRealloc(panSums, nNumPx * sizeof(int)) );
                     nMaxNumPx = nNumPx;
                 }
 
-                for( iY = nSrcYOff; iY < nSrcYOff2; ++iY )
+                for( int iY = nSrcYOff; iY < nSrcYOff2; ++iY )
                 {
-                    int     iTotYOff = (iY-nSrcYOff)*nChunkXSize-nChunkXOff;
-                    for( iX = nSrcXOff; iX < nSrcXOff2; ++iX )
+                    const int iTotYOff = (iY-nSrcYOff)*nChunkXSize-nChunkXOff;
+                    for( int iX = nSrcXOff; iX < nSrcXOff2; ++iX )
                     {
-                        if (pabySrcScanlineNodataMask == NULL ||
-                            pabySrcScanlineNodataMask[iX+iTotYOff])
+                        if( pabySrcScanlineNodataMask == NULL ||
+                            pabySrcScanlineNodataMask[iX+iTotYOff] )
                         {
-                            float fVal = pafSrcScanline[iX+iTotYOff];
-                            int i;
+                            const float fVal = pafSrcScanline[iX+iTotYOff];
+                            int i = 0;  // Used after for.
 
-                            //Check array for existing entry
-                            for( i = 0; i < iMaxInd; ++i )
+                            // Check array for existing entry.
+                            for( ; i < iMaxInd; ++i )
                                 if( pafVals[i] == fVal
                                     && ++panSums[i] > panSums[iMaxVal] )
                                 {
@@ -898,7 +1054,7 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
                                     break;
                                 }
 
-                            //Add to arr if entry not already there
+                            // Add to arr if entry not already there.
                             if( i == iMaxInd )
                             {
                                 pafVals[iMaxInd] = fVal;
@@ -918,27 +1074,28 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
                 else
                     pafDstScanline[iDstPixel - nDstXOff] = pafVals[iMaxVal];
             }
-            else /* if (eSrcDataType == GDT_Byte && nEntryCount < 256) */
+            else // if( eSrcDataType == GDT_Byte && nEntryCount < 256 )
             {
-                /* So we go here for a paletted or non-paletted byte band */
-                /* The input values are then between 0 and 255 */
-                int     anVals[256], nMaxVal = 0, iMaxInd = -1;
-
-                memset(anVals, 0, 256*sizeof(int));
+                // So we go here for a paletted or non-paletted byte band.
+                // The input values are then between 0 and 255.
+                std::vector<int> anVals(256, 0);
+                int nMaxVal = 0;
+                int iMaxInd = -1;
 
                 for( int iY = nSrcYOff; iY < nSrcYOff2; ++iY )
                 {
-                    int     iTotYOff = (iY-nSrcYOff)*nChunkXSize-nChunkXOff;
+                    const int iTotYOff =
+                        (iY - nSrcYOff) * nChunkXSize - nChunkXOff;
                     for( int iX = nSrcXOff; iX < nSrcXOff2; ++iX )
                     {
-                        float  val = pafSrcScanline[iX+iTotYOff];
-                        if (bHasNoData == FALSE || val != fNoDataValue)
+                        const float val = pafSrcScanline[iX+iTotYOff];
+                        if( bHasNoData == FALSE || val != fNoDataValue )
                         {
-                            int nVal = (int) val;
-                            if ( ++anVals[nVal] > nMaxVal)
+                            int nVal = static_cast<int>(val);
+                            if( ++anVals[nVal] > nMaxVal)
                             {
-                                //Sum the density
-                                //Is it the most common value so far?
+                                // Sum the density.
+                                // Is it the most common value so far?
                                 iMaxInd = nVal;
                                 nMaxVal = anVals[nVal];
                             }
@@ -949,13 +1106,15 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
                 if( iMaxInd == -1 )
                     pafDstScanline[iDstPixel - nDstXOff] = fNoDataValue;
                 else
-                    pafDstScanline[iDstPixel - nDstXOff] = (float)iMaxInd;
+                    pafDstScanline[iDstPixel - nDstXOff] =
+                        static_cast<float>(iMaxInd);
             }
         }
 
-        eErr = poOverview->RasterIO( GF_Write, nDstXOff, iDstLine, nDstXOff2 - nDstXOff, 1,
-                                     pafDstScanline, nDstXOff2 - nDstXOff, 1, GDT_Float32,
-                                     0, 0, NULL );
+        eErr = poOverview->RasterIO(
+            GF_Write, nDstXOff, iDstLine, nDstXOff2 - nDstXOff, 1,
+            pafDstScanline, nDstXOff2 - nDstXOff, 1, GDT_Float32,
+            0, 0, NULL );
     }
 
     CPLFree( pafDstScanline );
@@ -971,18 +1130,19 @@ GDALResampleChunk32R_Mode( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
 /************************************************************************/
 
 template<class T> static inline double GDALResampleConvolutionHorizontal(
-                            const T* pChunk, const double* padfWeights, int nSrcPixelCount)
+    const T* pChunk, const double* padfWeights, int nSrcPixelCount )
 {
-    double dfVal1 = 0.0, dfVal2 = 0.0;
-    int i = 0;
-    for(;i+3<nSrcPixelCount;i+=4)
+    double dfVal1 = 0.0;
+    double dfVal2 = 0.0;
+    int i = 0;  // Used after for.
+    for( ; i + 3 < nSrcPixelCount; i += 4 )
     {
         dfVal1 += pChunk[i] * padfWeights[i];
         dfVal1 += pChunk[i+1] * padfWeights[i+1];
         dfVal2 += pChunk[i+2] * padfWeights[i+2];
         dfVal2 += pChunk[i+3] * padfWeights[i+3];
     }
-    for(;i<nSrcPixelCount;i++)
+    for( ; i < nSrcPixelCount; ++i )
     {
         dfVal1 += pChunk[i] * padfWeights[i];
     }
@@ -990,43 +1150,46 @@ template<class T> static inline double GDALResampleConvolutionHorizontal(
 }
 
 template<class T> static inline void GDALResampleConvolutionHorizontalWithMask(
-                            const T* pChunk, const GByte* pabyMask,
-                            const double* padfWeights, int nSrcPixelCount,
-                            double& dfVal, double &dfWeightSum)
+    const T* pChunk, const GByte* pabyMask,
+    const double* padfWeights, int nSrcPixelCount,
+    double& dfVal, double &dfWeightSum)
 {
     dfVal = 0;
     dfWeightSum = 0;
     int i = 0;
-    for(;i+3<nSrcPixelCount;i+=4)
+    for( ; i + 3 < nSrcPixelCount; i += 4 )
     {
-        double dfWeight0 = padfWeights[i] * pabyMask[i];
-        double dfWeight1 = padfWeights[i+1] * pabyMask[i+1];
-        double dfWeight2 = padfWeights[i+2] * pabyMask[i+2];
-        double dfWeight3 = padfWeights[i+3] * pabyMask[i+3];
+        const double dfWeight0 = padfWeights[i] * pabyMask[i];
+        const double dfWeight1 = padfWeights[i+1] * pabyMask[i+1];
+        const double dfWeight2 = padfWeights[i+2] * pabyMask[i+2];
+        const double dfWeight3 = padfWeights[i+3] * pabyMask[i+3];
         dfVal += pChunk[i] * dfWeight0;
         dfVal += pChunk[i+1] * dfWeight1;
         dfVal += pChunk[i+2] * dfWeight2;
         dfVal += pChunk[i+3] * dfWeight3;
         dfWeightSum += dfWeight0 + dfWeight1 + dfWeight2 + dfWeight3;
     }
-    for(;i<nSrcPixelCount;i++)
+    for( ; i < nSrcPixelCount; ++i )
     {
-        double dfWeight = padfWeights[i] * pabyMask[i];
+        const double dfWeight = padfWeights[i] * pabyMask[i];
         dfVal += pChunk[i] * dfWeight;
         dfWeightSum += dfWeight;
     }
 }
 
 template<class T> static inline void GDALResampleConvolutionHorizontal_3rows(
-                            const T* pChunkRow1, const T* pChunkRow2, const T* pChunkRow3,
-                            const double* padfWeights, int nSrcPixelCount,
-                            double& dfRes1, double& dfRes2, double& dfRes3)
+    const T* pChunkRow1, const T* pChunkRow2, const T* pChunkRow3,
+    const double* padfWeights, int nSrcPixelCount,
+    double& dfRes1, double& dfRes2, double& dfRes3)
 {
-    double dfVal1 = 0.0, dfVal2 = 0.0,
-           dfVal3 = 0.0, dfVal4 = 0.0,
-           dfVal5 = 0.0, dfVal6 = 0.0;
-    int i = 0;
-    for(;i+3<nSrcPixelCount;i+=4)
+    double dfVal1 = 0.0;
+    double dfVal2 = 0.0;
+    double dfVal3 = 0.0;
+    double dfVal4 = 0.0;
+    double dfVal5 = 0.0;
+    double dfVal6 = 0.0;
+    int i = 0;  // Used after for.
+    for( ; i + 3 < nSrcPixelCount; i += 4 )
     {
         dfVal1 += pChunkRow1[i] * padfWeights[i];
         dfVal1 += pChunkRow1[i+1] * padfWeights[i+1];
@@ -1041,7 +1204,7 @@ template<class T> static inline void GDALResampleConvolutionHorizontal_3rows(
         dfVal6 += pChunkRow3[i+2] * padfWeights[i+2];
         dfVal6 += pChunkRow3[i+3] * padfWeights[i+3];
     }
-    for(;i<nSrcPixelCount;i++)
+    for( ; i < nSrcPixelCount; ++i )
     {
         dfVal1 += pChunkRow1[i] * padfWeights[i];
         dfVal3 += pChunkRow2[i] * padfWeights[i];
@@ -1052,15 +1215,16 @@ template<class T> static inline void GDALResampleConvolutionHorizontal_3rows(
     dfRes3 = dfVal5 + dfVal6;
 }
 
-template<class T> static inline void GDALResampleConvolutionHorizontalPixelCountLess8_3rows(
-                            const T* pChunkRow1, const T* pChunkRow2, const T* pChunkRow3,
-                            const double* padfWeights, int nSrcPixelCount,
-                            double& dfRes1, double& dfRes2, double& dfRes3)
+template<class T> static inline void
+GDALResampleConvolutionHorizontalPixelCountLess8_3rows(
+    const T* pChunkRow1, const T* pChunkRow2, const T* pChunkRow3,
+    const double* padfWeights, int nSrcPixelCount,
+    double& dfRes1, double& dfRes2, double& dfRes3 )
 {
     GDALResampleConvolutionHorizontal_3rows(
-                            pChunkRow1, pChunkRow2, pChunkRow3,
-                            padfWeights, nSrcPixelCount,
-                            dfRes1, dfRes2, dfRes3);
+        pChunkRow1, pChunkRow2, pChunkRow3,
+        padfWeights, nSrcPixelCount,
+        dfRes1, dfRes2, dfRes3 );
 }
 
 /************************************************************************/
@@ -1068,18 +1232,20 @@ template<class T> static inline void GDALResampleConvolutionHorizontalPixelCount
 /************************************************************************/
 
 template<class T> static inline double GDALResampleConvolutionVertical(
-                 const T* pChunk, int nStride, const double* padfWeights, int nSrcLineCount)
+    const T* pChunk, int nStride, const double* padfWeights, int nSrcLineCount )
 {
-    double dfVal1 = 0.0, dfVal2 = 0.0;
-    int i = 0, j = 0;
-    for(;i+3<nSrcLineCount;i+=4, j+=4*nStride)
+    double dfVal1 = 0.0;
+    double dfVal2 = 0.0;
+    int i = 0;
+    int j = 0;
+    for( ; i + 3 < nSrcLineCount; i+=4, j+=4*nStride)
     {
         dfVal1 += pChunk[j] * padfWeights[i];
         dfVal1 += pChunk[j + nStride] * padfWeights[i+1];
         dfVal2 += pChunk[j + 2 * nStride] * padfWeights[i+2];
         dfVal2 += pChunk[j + 3 * nStride] * padfWeights[i+3];
     }
-    for(;i<nSrcLineCount;i++,j+=nStride)
+    for( ; i < nSrcLineCount; ++i, j += nStride)
     {
         dfVal1 += pChunk[j] * padfWeights[i];
     }
@@ -1087,12 +1253,15 @@ template<class T> static inline double GDALResampleConvolutionVertical(
 }
 
 template<class T> static inline void GDALResampleConvolutionVertical_2cols(
-                 const T* pChunk, int nStride, const double* padfWeights, int nSrcLineCount,
-                 double& dfRes1, double& dfRes2)
+    const T* pChunk, int nStride, const double* padfWeights, int nSrcLineCount,
+    double& dfRes1, double& dfRes2 )
 {
-    double dfVal1 = 0.0, dfVal2 = 0.0,
-           dfVal3 = 0.0, dfVal4 = 0.0;
-    int i = 0, j = 0;
+    double dfVal1 = 0.0;
+    double dfVal2 = 0.0;
+    double dfVal3 = 0.0;
+    double dfVal4 = 0.0;
+    int i = 0;
+    int j = 0;
     for(;i+3<nSrcLineCount;i+=4, j+=4*nStride)
     {
         dfVal1 += pChunk[j] * padfWeights[i];
@@ -1104,7 +1273,7 @@ template<class T> static inline void GDALResampleConvolutionVertical_2cols(
         dfVal2 += pChunk[j + 3 * nStride] * padfWeights[i+3];
         dfVal4 += pChunk[j+1 + 3 * nStride] * padfWeights[i+3];
     }
-    for(;i<nSrcLineCount;i++,j+=nStride)
+    for( ; i < nSrcLineCount; ++i, j += nStride )
     {
         dfVal1 += pChunk[j] * padfWeights[i];
         dfVal3 += pChunk[j+1] * padfWeights[i];
@@ -1112,8 +1281,10 @@ template<class T> static inline void GDALResampleConvolutionVertical_2cols(
     dfRes1 = dfVal1 + dfVal2;
     dfRes2 = dfVal3 + dfVal4;
 }
-/* We restrict to 64bit processors because they are guaranteed to have SSE2 */
-/* Could possibly be used too on 32bit, but we would need to check at runtime */
+
+// TODO(schwehr): Move define of USE_SSE2 and include to the top of the file.
+// Restrict to 64bit processors because they are guaranteed to have SSE2.
+// Could possibly be used too on 32bit, but we would need to check at runtime.
 #if defined(__x86_64) || defined(_M_X64)
 #define USE_SSE2
 #endif
@@ -1126,18 +1297,20 @@ template<class T> static inline void GDALResampleConvolutionVertical_2cols(
 /************************************************************************/
 
 template<class T> static inline double GDALResampleConvolutionHorizontalSSE2(
-                         const T* pChunk, const double* padfWeightsAligned, int nSrcPixelCount)
+    const T* pChunk, const double* padfWeightsAligned, int nSrcPixelCount )
 {
     XMMReg4Double v_acc1 = XMMReg4Double::Zero();
     XMMReg4Double v_acc2 = XMMReg4Double::Zero();
-    int i = 0;
-    for(;i+7<nSrcPixelCount;i+=8)
+    int i = 0;  // Used after for.
+    for( ; i + 7 < nSrcPixelCount; i += 8 )
     {
         // Retrieve the pixel & accumulate
-        XMMReg4Double v_pixels1 = XMMReg4Double::Load4Val(pChunk+i);
-        XMMReg4Double v_pixels2 = XMMReg4Double::Load4Val(pChunk+i+4);
-        XMMReg4Double v_weight1 = XMMReg4Double::Load4ValAligned(padfWeightsAligned+i);
-        XMMReg4Double v_weight2 = XMMReg4Double::Load4ValAligned(padfWeightsAligned+i+4);
+        const XMMReg4Double v_pixels1 = XMMReg4Double::Load4Val(pChunk+i);
+        const XMMReg4Double v_pixels2 = XMMReg4Double::Load4Val(pChunk+i+4);
+        const XMMReg4Double v_weight1 =
+            XMMReg4Double::Load4ValAligned(padfWeightsAligned+i);
+        const XMMReg4Double v_weight2 =
+            XMMReg4Double::Load4ValAligned(padfWeightsAligned+i+4);
 
         v_acc1 += v_pixels1 * v_weight1;
         v_acc2 += v_pixels2 * v_weight2;
@@ -1146,8 +1319,8 @@ template<class T> static inline double GDALResampleConvolutionHorizontalSSE2(
     v_acc1 += v_acc2;
     v_acc1.AddLowAndHigh();
 
-    double dfVal = (double)v_acc1.GetLow();
-    for(;i<nSrcPixelCount;i++)
+    double dfVal = static_cast<double>(v_acc1.GetLow());
+    for( ; i < nSrcPixelCount; ++i )
     {
         dfVal += pChunk[i] * padfWeightsAligned[i];
     }
@@ -1159,45 +1332,50 @@ template<class T> static inline double GDALResampleConvolutionHorizontalSSE2(
 /************************************************************************/
 
 template<> inline double GDALResampleConvolutionHorizontal<GByte>(
-                         const GByte* pChunk, const double* padfWeightsAligned, int nSrcPixelCount)
+    const GByte* pChunk, const double* padfWeightsAligned, int nSrcPixelCount )
 {
-    return GDALResampleConvolutionHorizontalSSE2(pChunk, padfWeightsAligned, nSrcPixelCount);
+    return GDALResampleConvolutionHorizontalSSE2( pChunk, padfWeightsAligned,
+                                                  nSrcPixelCount );
 }
 
 template<> inline double GDALResampleConvolutionHorizontal<GUInt16>(
-                         const GUInt16* pChunk, const double* padfWeightsAligned, int nSrcPixelCount)
+    const GUInt16* pChunk, const double* padfWeightsAligned,
+    int nSrcPixelCount )
 {
-    return GDALResampleConvolutionHorizontalSSE2(pChunk, padfWeightsAligned, nSrcPixelCount);
+    return GDALResampleConvolutionHorizontalSSE2( pChunk, padfWeightsAligned,
+                                                  nSrcPixelCount) ;
 }
 
 /************************************************************************/
 /*              GDALResampleConvolutionHorizontalWithMaskSSE2<T>        */
 /************************************************************************/
 
-template<class T> static inline void GDALResampleConvolutionHorizontalWithMaskSSE2(
-                            const T* pChunk, const GByte* pabyMask,
-                            const double* padfWeightsAligned, int nSrcPixelCount,
-                            double& dfVal, double &dfWeightSum)
+template<class T> static inline void
+GDALResampleConvolutionHorizontalWithMaskSSE2(
+    const T* pChunk, const GByte* pabyMask,
+    const double* padfWeightsAligned, int nSrcPixelCount,
+    double& dfVal, double &dfWeightSum )
 {
-    int i = 0;
-    XMMReg4Double v_acc = XMMReg4Double::Zero(),
-                  v_acc_weight = XMMReg4Double::Zero();
-    for(;i+3<nSrcPixelCount;i+=4)
-    {
-        XMMReg4Double v_pixels = XMMReg4Double::Load4Val(pChunk+i);
-        XMMReg4Double v_mask = XMMReg4Double::Load4Val(pabyMask+i);
-        XMMReg4Double v_weight = XMMReg4Double::Load4ValAligned(padfWeightsAligned+i);
+    int i = 0;  // Used after for.
+    XMMReg4Double v_acc = XMMReg4Double::Zero();
+    XMMReg4Double v_acc_weight = XMMReg4Double::Zero();
+    for( ; i + 3 < nSrcPixelCount; i += 4 )
+    {
+        const XMMReg4Double v_pixels = XMMReg4Double::Load4Val(pChunk+i);
+        const XMMReg4Double v_mask = XMMReg4Double::Load4Val(pabyMask+i);
+        XMMReg4Double v_weight =
+            XMMReg4Double::Load4ValAligned(padfWeightsAligned+i);
         v_weight *= v_mask;
         v_acc += v_pixels * v_weight;
         v_acc_weight += v_weight;
     }
     v_acc.AddLowAndHigh();
     v_acc_weight.AddLowAndHigh();
-    dfVal = (double)v_acc.GetLow();
-    dfWeightSum = (double)v_acc_weight.GetLow();
-    for(;i<nSrcPixelCount;i++)
+    dfVal = static_cast<double>(v_acc.GetLow());
+    dfWeightSum = static_cast<double>(v_acc_weight.GetLow());
+    for( ; i < nSrcPixelCount; ++i )
     {
-        double dfWeight = padfWeightsAligned[i] * pabyMask[i];
+        const double dfWeight = padfWeightsAligned[i] * pabyMask[i];
         dfVal += pChunk[i] * dfWeight;
         dfWeightSum += dfWeight;
     }
@@ -1208,9 +1386,9 @@ template<class T> static inline void GDALResampleConvolutionHorizontalWithMaskSS
 /************************************************************************/
 
 template<> inline void GDALResampleConvolutionHorizontalWithMask<GByte>(
-                            const GByte* pChunk, const GByte* pabyMask,
-                            const double* padfWeightsAligned, int nSrcPixelCount,
-                            double& dfVal, double &dfWeightSum)
+    const GByte* pChunk, const GByte* pabyMask,
+    const double* padfWeightsAligned, int nSrcPixelCount,
+    double& dfVal, double &dfWeightSum)
 {
     GDALResampleConvolutionHorizontalWithMaskSSE2(pChunk, pabyMask,
                                                   padfWeightsAligned,
@@ -1219,36 +1397,39 @@ template<> inline void GDALResampleConvolutionHorizontalWithMask<GByte>(
 }
 
 template<> inline void GDALResampleConvolutionHorizontalWithMask<GUInt16>(
-                            const GUInt16* pChunk, const GByte* pabyMask,
-                            const double* padfWeightsAligned, int nSrcPixelCount,
-                            double& dfVal, double &dfWeightSum)
+    const GUInt16* pChunk, const GByte* pabyMask,
+    const double* padfWeightsAligned, int nSrcPixelCount,
+    double& dfVal, double &dfWeightSum )
 {
-    GDALResampleConvolutionHorizontalWithMaskSSE2(pChunk, pabyMask,
-                                                  padfWeightsAligned,
-                                                  nSrcPixelCount,
-                                                  dfVal, dfWeightSum);
+    GDALResampleConvolutionHorizontalWithMaskSSE2( pChunk, pabyMask,
+                                                   padfWeightsAligned,
+                                                   nSrcPixelCount,
+                                                   dfVal, dfWeightSum );
 }
 
 /************************************************************************/
 /*              GDALResampleConvolutionHorizontal_3rows_SSE2<T>         */
 /************************************************************************/
 
-template<class T> static inline void GDALResampleConvolutionHorizontal_3rows_SSE2(
-                            const T* pChunkRow1, const T* pChunkRow2, const T* pChunkRow3,
-                            const double* padfWeightsAligned, int nSrcPixelCount,
-                            double& dfRes1, double& dfRes2, double& dfRes3)
+template<class T> static inline void
+GDALResampleConvolutionHorizontal_3rows_SSE2(
+    const T* pChunkRow1, const T* pChunkRow2, const T* pChunkRow3,
+    const double* padfWeightsAligned, int nSrcPixelCount,
+    double& dfRes1, double& dfRes2, double& dfRes3 )
 {
     XMMReg4Double v_acc1 = XMMReg4Double::Zero(),
                   v_acc2 = XMMReg4Double::Zero(),
                   v_acc3 = XMMReg4Double::Zero();
     int i = 0;
-    for(;i+7<nSrcPixelCount;i+=8)
+    for( ; i + 7 < nSrcPixelCount; i += 8 )
     {
-        // Retrieve the pixel & accumulate
+        // Retrieve the pixel & accumulate.
         XMMReg4Double v_pixels1 = XMMReg4Double::Load4Val(pChunkRow1+i);
         XMMReg4Double v_pixels2 = XMMReg4Double::Load4Val(pChunkRow1+i+4);
-        XMMReg4Double v_weight1 = XMMReg4Double::Load4ValAligned(padfWeightsAligned+i);
-        XMMReg4Double v_weight2 = XMMReg4Double::Load4ValAligned(padfWeightsAligned+i+4);
+        const XMMReg4Double v_weight1 =
+            XMMReg4Double::Load4ValAligned(padfWeightsAligned+i);
+        const XMMReg4Double v_weight2 =
+            XMMReg4Double::Load4ValAligned(padfWeightsAligned+i+4);
 
         v_acc1 += v_pixels1 * v_weight1;
         v_acc1 += v_pixels2 * v_weight2;
@@ -1262,17 +1443,16 @@ template<class T> static inline void GDALResampleConvolutionHorizontal_3rows_SSE
         v_pixels2 = XMMReg4Double::Load4Val(pChunkRow3+i+4);
         v_acc3 += v_pixels1 * v_weight1;
         v_acc3 += v_pixels2 * v_weight2;
-
     }
 
     v_acc1.AddLowAndHigh();
     v_acc2.AddLowAndHigh();
     v_acc3.AddLowAndHigh();
 
-    dfRes1 = (double)v_acc1.GetLow();
-    dfRes2 = (double)v_acc2.GetLow();
-    dfRes3 = (double)v_acc3.GetLow();
-    for(;i<nSrcPixelCount;i++)
+    dfRes1 = static_cast<double>(v_acc1.GetLow());
+    dfRes2 = static_cast<double>(v_acc2.GetLow());
+    dfRes3 = static_cast<double>(v_acc3.GetLow());
+    for( ; i < nSrcPixelCount; ++i )
     {
         dfRes1 += pChunkRow1[i] * padfWeightsAligned[i];
         dfRes2 += pChunkRow2[i] * padfWeightsAligned[i];
@@ -1285,45 +1465,50 @@ template<class T> static inline void GDALResampleConvolutionHorizontal_3rows_SSE
 /************************************************************************/
 
 template<> inline void GDALResampleConvolutionHorizontal_3rows<GByte>(
-                            const GByte* pChunkRow1, const GByte* pChunkRow2, const GByte* pChunkRow3,
-                            const double* padfWeightsAligned, int nSrcPixelCount,
-                            double& dfRes1, double& dfRes2, double& dfRes3)
+    const GByte* pChunkRow1, const GByte* pChunkRow2, const GByte* pChunkRow3,
+    const double* padfWeightsAligned, int nSrcPixelCount,
+    double& dfRes1, double& dfRes2, double& dfRes3 )
 {
-    GDALResampleConvolutionHorizontal_3rows_SSE2(pChunkRow1, pChunkRow2, pChunkRow3,
-                                                 padfWeightsAligned, nSrcPixelCount,
-                                                 dfRes1, dfRes2, dfRes3);
+    GDALResampleConvolutionHorizontal_3rows_SSE2(
+        pChunkRow1, pChunkRow2, pChunkRow3,
+        padfWeightsAligned, nSrcPixelCount,
+        dfRes1, dfRes2, dfRes3 );
 }
 
 template<> inline void GDALResampleConvolutionHorizontal_3rows<GUInt16>(
-                            const GUInt16* pChunkRow1, const GUInt16* pChunkRow2, const GUInt16* pChunkRow3,
-                            const double* padfWeightsAligned, int nSrcPixelCount,
-                            double& dfRes1, double& dfRes2, double& dfRes3)
+    const GUInt16* pChunkRow1, const GUInt16* pChunkRow2,
+    const GUInt16* pChunkRow3,
+    const double* padfWeightsAligned, int nSrcPixelCount,
+    double& dfRes1, double& dfRes2, double& dfRes3 )
 {
-    GDALResampleConvolutionHorizontal_3rows_SSE2(pChunkRow1, pChunkRow2, pChunkRow3,
-                                                 padfWeightsAligned, nSrcPixelCount,
-                                                 dfRes1, dfRes2, dfRes3);
+    GDALResampleConvolutionHorizontal_3rows_SSE2(
+        pChunkRow1, pChunkRow2, pChunkRow3,
+        padfWeightsAligned, nSrcPixelCount,
+        dfRes1, dfRes2, dfRes3);
 }
 
 /************************************************************************/
 /*     GDALResampleConvolutionHorizontalPixelCountLess8_3rows_SSE2<T>   */
 /************************************************************************/
 
-template<class T> static inline void GDALResampleConvolutionHorizontalPixelCountLess8_3rows_SSE2(
-                            const T* pChunkRow1, const T* pChunkRow2, const T* pChunkRow3,
-                            const double* padfWeightsAligned, int nSrcPixelCount,
-                            double& dfRes1, double& dfRes2, double& dfRes3)
+template<class T> static inline void
+GDALResampleConvolutionHorizontalPixelCountLess8_3rows_SSE2(
+    const T* pChunkRow1, const T* pChunkRow2, const T* pChunkRow3,
+    const double* padfWeightsAligned, int nSrcPixelCount,
+    double& dfRes1, double& dfRes2, double& dfRes3)
 {
-    XMMReg4Double v_acc1 = XMMReg4Double::Zero(),
-                  v_acc2 = XMMReg4Double::Zero(),
-                  v_acc3 = XMMReg4Double::Zero();
-    int i = 0;
-    for(;i+3<nSrcPixelCount;i+=4)
+    XMMReg4Double v_acc1 = XMMReg4Double::Zero();
+    XMMReg4Double v_acc2 = XMMReg4Double::Zero();
+    XMMReg4Double v_acc3 = XMMReg4Double::Zero();
+    int i = 0;  // Use after for.
+    for( ; i + 3 < nSrcPixelCount; i += 4)
     {
-        // Retrieve the pixel & accumulate
-        XMMReg4Double v_pixels1 = XMMReg4Double::Load4Val(pChunkRow1+i);
-        XMMReg4Double v_pixels2 = XMMReg4Double::Load4Val(pChunkRow2+i);
-        XMMReg4Double v_pixels3 = XMMReg4Double::Load4Val(pChunkRow3+i);
-        XMMReg4Double v_weight = XMMReg4Double::Load4ValAligned(padfWeightsAligned+i);
+        // Retrieve the pixel & accumulate.
+        const XMMReg4Double v_pixels1 = XMMReg4Double::Load4Val(pChunkRow1+i);
+        const XMMReg4Double v_pixels2 = XMMReg4Double::Load4Val(pChunkRow2+i);
+        const XMMReg4Double v_pixels3 = XMMReg4Double::Load4Val(pChunkRow3+i);
+        const XMMReg4Double v_weight =
+            XMMReg4Double::Load4ValAligned(padfWeightsAligned + i);
 
         v_acc1 += v_pixels1 * v_weight;
         v_acc2 += v_pixels2 * v_weight;
@@ -1334,10 +1519,11 @@ template<class T> static inline void GDALResampleConvolutionHorizontalPixelCount
     v_acc2.AddLowAndHigh();
     v_acc3.AddLowAndHigh();
 
-    dfRes1 = (double)v_acc1.GetLow();
-    dfRes2 = (double)v_acc2.GetLow();
-    dfRes3 = (double)v_acc3.GetLow();
-    for(;i<nSrcPixelCount;i++)
+    dfRes1 = static_cast<double>(v_acc1.GetLow());
+    dfRes2 = static_cast<double>(v_acc2.GetLow());
+    dfRes3 = static_cast<double>(v_acc3.GetLow());
+
+    for( ; i < nSrcPixelCount; ++i )
     {
         dfRes1 += pChunkRow1[i] * padfWeightsAligned[i];
         dfRes2 += pChunkRow2[i] * padfWeightsAligned[i];
@@ -1349,123 +1535,139 @@ template<class T> static inline void GDALResampleConvolutionHorizontalPixelCount
 /*     GDALResampleConvolutionHorizontalPixelCountLess8_3rows<GByte>    */
 /************************************************************************/
 
-template<> inline void GDALResampleConvolutionHorizontalPixelCountLess8_3rows<GByte>(
-                            const GByte* pChunkRow1, const GByte* pChunkRow2, const GByte* pChunkRow3,
-                            const double* padfWeightsAligned, int nSrcPixelCount,
-                            double& dfRes1, double& dfRes2, double& dfRes3)
+template<> inline void
+GDALResampleConvolutionHorizontalPixelCountLess8_3rows<GByte>(
+    const GByte* pChunkRow1, const GByte* pChunkRow2, const GByte* pChunkRow3,
+    const double* padfWeightsAligned, int nSrcPixelCount,
+    double& dfRes1, double& dfRes2, double& dfRes3 )
 {
-    GDALResampleConvolutionHorizontalPixelCountLess8_3rows_SSE2(pChunkRow1, pChunkRow2, pChunkRow3,
-                                                                padfWeightsAligned, nSrcPixelCount,
-                                                                dfRes1, dfRes2, dfRes3);
+    GDALResampleConvolutionHorizontalPixelCountLess8_3rows_SSE2(
+        pChunkRow1, pChunkRow2, pChunkRow3,
+        padfWeightsAligned, nSrcPixelCount,
+        dfRes1, dfRes2, dfRes3 );
 }
 
-template<> inline void GDALResampleConvolutionHorizontalPixelCountLess8_3rows<GUInt16>(
-                            const GUInt16* pChunkRow1, const GUInt16* pChunkRow2, const GUInt16* pChunkRow3,
-                            const double* padfWeightsAligned, int nSrcPixelCount,
-                            double& dfRes1, double& dfRes2, double& dfRes3)
+template<> inline void
+GDALResampleConvolutionHorizontalPixelCountLess8_3rows<GUInt16>(
+    const GUInt16* pChunkRow1, const GUInt16* pChunkRow2,
+    const GUInt16* pChunkRow3,
+    const double* padfWeightsAligned, int nSrcPixelCount,
+    double& dfRes1, double& dfRes2, double& dfRes3 )
 {
-    GDALResampleConvolutionHorizontalPixelCountLess8_3rows_SSE2(pChunkRow1, pChunkRow2, pChunkRow3,
-                                                                padfWeightsAligned, nSrcPixelCount,
-                                                                dfRes1, dfRes2, dfRes3);
+    GDALResampleConvolutionHorizontalPixelCountLess8_3rows_SSE2(
+        pChunkRow1, pChunkRow2, pChunkRow3,
+        padfWeightsAligned, nSrcPixelCount,
+        dfRes1, dfRes2, dfRes3 );
 }
 
-#endif /*  USE_SSE2 */
+#endif  // USE_SSE2
 
 /************************************************************************/
 /*                   GDALResampleChunk32R_Convolution()                 */
 /************************************************************************/
 
-template<class T, int bMultipleBands> static CPLErr
-GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstToSrc,
-                                     double dfSrcXDelta,
-                                     double dfSrcYDelta,
-                                     const T * pChunk, int nBands,
-                                     GByte * pabyChunkNodataMask,
-                                     int nChunkXOff, int nChunkXSize,
-                                     int nChunkYOff, int nChunkYSize,
-                                     int nDstXOff, int nDstXOff2,
-                                     int nDstYOff, int nDstYOff2,
-                                     GDALRasterBand ** papoDstBands,
-                                     int bHasNoData,
-                                     float fNoDataValue,
-                                     FilterFuncType pfnFilterFunc,
-                                     FilterFunc4ValuesType pfnFilterFunc4Values,
-                                     int nKernelRadius,
-                                     float fMaxVal )
+// TODO(schwehr): Does bMultipleBands really have to be a part of the template?
+
+// class MSVCPedanticBool fails with bMultipleBands being a bool.
+template<class T, EMULATED_BOOL bMultipleBands> static CPLErr
+GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc,
+                                   double dfYRatioDstToSrc,
+                                   double dfSrcXDelta,
+                                   double dfSrcYDelta,
+                                   const T * pChunk, int nBands,
+                                   GByte * pabyChunkNodataMask,
+                                   int nChunkXOff, int nChunkXSize,
+                                   int nChunkYOff, int nChunkYSize,
+                                   int nDstXOff, int nDstXOff2,
+                                   int nDstYOff, int nDstYOff2,
+                                   GDALRasterBand ** papoDstBands,
+                                   int bHasNoData,
+                                   float fNoDataValue,
+                                   FilterFuncType pfnFilterFunc,
+                                   FilterFunc4ValuesType pfnFilterFunc4Values,
+                                   int nKernelRadius,
+                                   float fMaxVal )
 
 {
-    if (!bHasNoData)
+    if( !bHasNoData )
         fNoDataValue = 0.0f;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate work buffers.                                          */
 /* -------------------------------------------------------------------- */
-    int nDstXSize = nDstXOff2 - nDstXOff;
+    const int nDstXSize = nDstXOff2 - nDstXOff;
 
-    double dfXScale = 1.0 / dfXRatioDstToSrc;
-    double dfXScaleWeight = ( dfXScale >= 1.0 ) ? 1.0 : dfXScale;
-    double dfXScaledRadius = nKernelRadius / dfXScaleWeight;
-    double dfYScale = 1.0 / dfYRatioDstToSrc;
-    double dfYScaleWeight = ( dfYScale >= 1.0 ) ? 1.0 : dfYScale;
-    double dfYScaledRadius = nKernelRadius / dfYScaleWeight;
+    const double dfXScale = 1.0 / dfXRatioDstToSrc;
+    const double dfXScaleWeight = ( dfXScale >= 1.0 ) ? 1.0 : dfXScale;
+    const double dfXScaledRadius = nKernelRadius / dfXScaleWeight;
+    const double dfYScale = 1.0 / dfYRatioDstToSrc;
+    const double dfYScaleWeight = ( dfYScale >= 1.0 ) ? 1.0 : dfYScale;
+    const double dfYScaledRadius = nKernelRadius / dfYScaleWeight;
 
-    float* pafDstScanline = (float *) VSI_MALLOC_VERBOSE(nDstXSize * sizeof(float));
+    float* pafDstScanline = static_cast<float *>(
+        VSI_MALLOC_VERBOSE(nDstXSize * sizeof(float)) );
 
-    /* Temporary array to store result of horizontal filter */
-    double* padfHorizontalFiltered = (double*) VSI_MALLOC_VERBOSE(nChunkYSize * nDstXSize * sizeof(double) * nBands);
+    // Temporary array to store result of horizontal filter.
+    double* padfHorizontalFiltered = static_cast<double*>(
+        VSI_MALLOC_VERBOSE(nChunkYSize * nDstXSize * sizeof(double) * nBands) );
 
-    /* To store convolution coefficients */
-    double* padfWeightsAlloc = (double*) VSI_MALLOC_VERBOSE((int)(
-        2 + 2 * MAX(dfXScaledRadius, dfYScaledRadius) + 0.5 + 1 /* for alignment*/) * sizeof(double));
+    // To store convolution coefficients.
+    double* padfWeights = static_cast<double *>(
+        VSI_MALLOC_ALIGNED_AUTO_VERBOSE(
+            static_cast<int>(
+                2 + 2 * std::max(dfXScaledRadius, dfYScaledRadius) +
+                0.5) * sizeof(double) ) );
 
     GByte* pabyChunkNodataMaskHorizontalFiltered = NULL;
     if( pabyChunkNodataMask )
-        pabyChunkNodataMaskHorizontalFiltered = (GByte*) VSI_MALLOC_VERBOSE(nChunkYSize * nDstXSize);
-    if( pafDstScanline == NULL || padfHorizontalFiltered == NULL ||
-        padfWeightsAlloc == NULL || (pabyChunkNodataMask != NULL && pabyChunkNodataMaskHorizontalFiltered == NULL) )
+        pabyChunkNodataMaskHorizontalFiltered = static_cast<GByte*>(
+            VSI_MALLOC_VERBOSE(nChunkYSize * nDstXSize) );
+    if( pafDstScanline == NULL ||
+        padfHorizontalFiltered == NULL ||
+        padfWeights == NULL ||
+        (pabyChunkNodataMask != NULL &&
+         pabyChunkNodataMaskHorizontalFiltered == NULL) )
     {
         VSIFree(pafDstScanline);
         VSIFree(padfHorizontalFiltered);
-        VSIFree(padfWeightsAlloc);
+        VSIFreeAligned(padfWeights);
         VSIFree(pabyChunkNodataMaskHorizontalFiltered);
         return CE_Failure;
     }
 
-    /* Make sure we are aligned on 16 bits */
-    double* padfWeights = padfWeightsAlloc;
-    if( (((size_t)padfWeights) % 16) != 0 )
-        padfWeights ++;
-
 /* ==================================================================== */
-/*      Fist pass: horizontal filter                                    */
+/*      First pass: horizontal filter                                   */
 /* ==================================================================== */
-    int nChunkRightXOff = nChunkXOff + nChunkXSize;
+    const int nChunkRightXOff = nChunkXOff + nChunkXSize;
 #ifdef USE_SSE2
     bool bSrcPixelCountLess8 = dfXScaledRadius < 4;
 #endif
-    for( int iDstPixel = nDstXOff; iDstPixel < nDstXOff2; iDstPixel++ )
+    for( int iDstPixel = nDstXOff; iDstPixel < nDstXOff2; ++iDstPixel )
     {
-        double dfSrcPixel = (iDstPixel+0.5)*dfXRatioDstToSrc + dfSrcXDelta;
-        int nSrcPixelStart = (int)floor(dfSrcPixel - dfXScaledRadius + 0.5);
-        int nSrcPixelStop = (int)(dfSrcPixel + dfXScaledRadius + 0.5);
+        const double dfSrcPixel =
+            (iDstPixel + 0.5) * dfXRatioDstToSrc + dfSrcXDelta;
+        int nSrcPixelStart =
+            static_cast<int>(floor(dfSrcPixel - dfXScaledRadius + 0.5));
         if( nSrcPixelStart < nChunkXOff )
             nSrcPixelStart = nChunkXOff;
+        int nSrcPixelStop =
+            static_cast<int>(dfSrcPixel + dfXScaledRadius + 0.5);
         if( nSrcPixelStop > nChunkRightXOff )
             nSrcPixelStop = nChunkRightXOff;
 #if 0
         if( nSrcPixelStart < nChunkXOff && nChunkXOff > 0 )
         {
-            printf("truncated iDstPixel = %d\n", iDstPixel);
+            printf( "truncated iDstPixel = %d\n", iDstPixel );/*ok*/
         }
         if( nSrcPixelStop > nChunkRightXOff && nChunkRightXOff < nSrcWidth )
         {
-            printf("truncated iDstPixel = %d\n", iDstPixel);
+            printf( "truncated iDstPixel = %d\n", iDstPixel );/*ok*/
         }
 #endif
-        int nSrcPixelCount = nSrcPixelStop - nSrcPixelStart;
+        const int nSrcPixelCount = nSrcPixelStop - nSrcPixelStart;
         double dfWeightSum = 0.0;
 
-        /* Compute convolution coefficients */
+        // Compute convolution coefficients.
         int nSrcPixel = nSrcPixelStart;
         double dfX = dfXScaleWeight * (nSrcPixel - dfSrcPixel + 0.5);
         for( ; nSrcPixel + 3 < nSrcPixelStop; nSrcPixel+=4)
@@ -1478,22 +1680,23 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
             dfX += dfXScaleWeight;
             padfWeights[nSrcPixel+3 - nSrcPixelStart] = dfX;
             dfX += dfXScaleWeight;
-            dfWeightSum += pfnFilterFunc4Values(padfWeights + nSrcPixel - nSrcPixelStart);
+            dfWeightSum +=
+                pfnFilterFunc4Values(padfWeights + nSrcPixel - nSrcPixelStart);
         }
-        for( ; nSrcPixel < nSrcPixelStop; nSrcPixel++, dfX += dfXScaleWeight)
+        for( ; nSrcPixel < nSrcPixelStop; ++nSrcPixel, dfX += dfXScaleWeight)
         {
-            double dfWeight = pfnFilterFunc(dfX);
+            const double dfWeight = pfnFilterFunc(dfX);
             padfWeights[nSrcPixel - nSrcPixelStart] = dfWeight;
             dfWeightSum += dfWeight;
         }
 
-        int nHeight = nChunkYSize * nBands;
+        const int nHeight = nChunkYSize * nBands;
         if( pabyChunkNodataMask == NULL )
         {
             if( dfWeightSum != 0 )
             {
-                double dfInvWeightSum = 1.0 / dfWeightSum;
-                for(int i=0;i<nSrcPixelCount;i++)
+                const double dfInvWeightSum = 1.0 / dfWeightSum;
+                for( int i = 0; i < nSrcPixelCount; ++i )
                     padfWeights[i] *= dfInvWeightSum;
             }
             int iSrcLineOff = 0;
@@ -1502,14 +1705,22 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
             {
                 for( ; iSrcLineOff+2 < nHeight; iSrcLineOff +=3 )
                 {
-                    int j=iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
-                    double dfVal1, dfVal2, dfVal3;
+                    const int j =
+                        iSrcLineOff * nChunkXSize +
+                        (nSrcPixelStart - nChunkXOff);
+                    double dfVal1 = 0.0;
+                    double dfVal2 = 0.0;
+                    double dfVal3 = 0.0;
                     GDALResampleConvolutionHorizontalPixelCountLess8_3rows(
-                        pChunk + j, pChunk + j + nChunkXSize, pChunk + j + 2 * nChunkXSize,
+                        pChunk + j, pChunk + j + nChunkXSize,
+                        pChunk + j + 2 * nChunkXSize,
                         padfWeights, nSrcPixelCount, dfVal1, dfVal2, dfVal3);
-                    padfHorizontalFiltered[iSrcLineOff * nDstXSize + iDstPixel - nDstXOff] = dfVal1;
-                    padfHorizontalFiltered[(iSrcLineOff+1) * nDstXSize + iDstPixel - nDstXOff] = dfVal2;
-                    padfHorizontalFiltered[(iSrcLineOff+2) * nDstXSize + iDstPixel - nDstXOff] = dfVal3;
+                    padfHorizontalFiltered[iSrcLineOff * nDstXSize +
+                                           iDstPixel - nDstXOff] = dfVal1;
+                    padfHorizontalFiltered[(iSrcLineOff + 1) * nDstXSize +
+                                           iDstPixel - nDstXOff] = dfVal2;
+                    padfHorizontalFiltered[(iSrcLineOff + 2) * nDstXSize +
+                                           iDstPixel - nDstXOff] = dfVal3;
                 }
             }
             else
@@ -1517,35 +1728,49 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
             {
                 for( ; iSrcLineOff+2 < nHeight; iSrcLineOff +=3 )
                 {
-                    int j=iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
-                    double dfVal1, dfVal2, dfVal3;
+                    const int j =
+                        iSrcLineOff * nChunkXSize +
+                        (nSrcPixelStart - nChunkXOff);
+                    double dfVal1 = 0.0;
+                    double dfVal2 = 0.0;
+                    double dfVal3 = 0.0;
                     GDALResampleConvolutionHorizontal_3rows(
-                        pChunk + j, pChunk + j + nChunkXSize, pChunk + j + 2 * nChunkXSize,
+                        pChunk + j,
+                        pChunk + j + nChunkXSize,
+                        pChunk + j + 2 * nChunkXSize,
                         padfWeights, nSrcPixelCount, dfVal1, dfVal2, dfVal3);
-                    padfHorizontalFiltered[iSrcLineOff * nDstXSize + iDstPixel - nDstXOff] = dfVal1;
-                    padfHorizontalFiltered[(iSrcLineOff+1) * nDstXSize + iDstPixel - nDstXOff] = dfVal2;
-                    padfHorizontalFiltered[(iSrcLineOff+2) * nDstXSize + iDstPixel - nDstXOff] = dfVal3;
+                    padfHorizontalFiltered[iSrcLineOff * nDstXSize +
+                                           iDstPixel - nDstXOff] = dfVal1;
+                    padfHorizontalFiltered[(iSrcLineOff + 1) * nDstXSize +
+                                           iDstPixel - nDstXOff] = dfVal2;
+                    padfHorizontalFiltered[(iSrcLineOff + 2) * nDstXSize +
+                                           iDstPixel - nDstXOff] = dfVal3;
                 }
             }
-            for( ; iSrcLineOff < nHeight; iSrcLineOff ++ )
+            for( ; iSrcLineOff < nHeight; ++iSrcLineOff )
             {
-                int j=iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
-                double dfVal =
+                const int j =
+                    iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
+                const double dfVal =
                     GDALResampleConvolutionHorizontal(pChunk + j,
                                                 padfWeights, nSrcPixelCount);
-                padfHorizontalFiltered[iSrcLineOff * nDstXSize + iDstPixel - nDstXOff] = dfVal;
+                padfHorizontalFiltered[iSrcLineOff * nDstXSize +
+                                       iDstPixel - nDstXOff] = dfVal;
             }
         }
         else
         {
-            for( int iSrcLineOff = 0; iSrcLineOff < nHeight; iSrcLineOff ++ )
+            for( int iSrcLineOff = 0; iSrcLineOff < nHeight; ++iSrcLineOff )
             {
-                double dfVal;
-                int j=iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
-                GDALResampleConvolutionHorizontalWithMask(pChunk + j, pabyChunkNodataMask + j,
-                                                            padfWeights, nSrcPixelCount,
-                                                            dfVal, dfWeightSum);
-                int nTempOffset = iSrcLineOff * nDstXSize + iDstPixel - nDstXOff;
+                double dfVal = 0.0;
+                const int j =
+                    iSrcLineOff * nChunkXSize + (nSrcPixelStart - nChunkXOff);
+                GDALResampleConvolutionHorizontalWithMask(
+                    pChunk + j, pabyChunkNodataMask + j,
+                    padfWeights, nSrcPixelCount,
+                    dfVal, dfWeightSum );
+                const int nTempOffset =
+                    iSrcLineOff * nDstXSize + iDstPixel - nDstXOff;
                 if( dfWeightSum > 0.0 )
                 {
                     padfHorizontalFiltered[nTempOffset] = dfVal / dfWeightSum;
@@ -1563,18 +1788,21 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
 /* ==================================================================== */
 /*      Second pass: vertical filter                                    */
 /* ==================================================================== */
-    int nChunkBottomYOff = nChunkYOff + nChunkYSize;
+    const int nChunkBottomYOff = nChunkYOff + nChunkYSize;
 
     CPLErr eErr = CE_None;
 
-  for(int iBand=0;iBand< ((bMultipleBands)?nBands:1);iBand++)
+  for( int iBand = 0; iBand < (bMultipleBands ? nBands : 1); ++iBand )
   {
-    const double* padfHorizontalFilteredBand = padfHorizontalFiltered + iBand * nChunkYSize * nDstXSize;
-    for( int iDstLine = nDstYOff; iDstLine < nDstYOff2; iDstLine++ )
-    {
-        double dfSrcLine = (iDstLine+0.5)*dfYRatioDstToSrc + dfSrcYDelta;
-        int nSrcLineStart = (int)floor(dfSrcLine - dfYScaledRadius + 0.5);
-        int nSrcLineStop = (int)(dfSrcLine + dfYScaledRadius + 0.5);
+    const double* padfHorizontalFilteredBand =
+        padfHorizontalFiltered + iBand * nChunkYSize * nDstXSize;
+    for( int iDstLine = nDstYOff; iDstLine < nDstYOff2; ++iDstLine )
+    {
+        const double dfSrcLine =
+            (iDstLine + 0.5) * dfYRatioDstToSrc + dfSrcYDelta;
+        int nSrcLineStart =
+            static_cast<int>(floor(dfSrcLine - dfYScaledRadius + 0.5));
+        int nSrcLineStop = static_cast<int>(dfSrcLine + dfYScaledRadius + 0.5);
         if( nSrcLineStart < nChunkYOff )
             nSrcLineStart = nChunkYOff;
         if( nSrcLineStop > nChunkBottomYOff )
@@ -1583,30 +1811,33 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
         if( nSrcLineStart < nChunkYOff &&
             nChunkYOff > 0 )
         {
-            printf("truncated iDstLine = %d\n", iDstLine);
+            printf( "truncated iDstLine = %d\n", iDstLine );/*ok*/
         }
         if( nSrcLineStop > nChunkBottomYOff && nChunkBottomYOff < nSrcHeight )
         {
-            printf("truncated iDstLine = %d\n", iDstLine);
+            printf( "truncated iDstLine = %d\n", iDstLine );/*ok*/
         }
 #endif
-        int nSrcLineCount = nSrcLineStop - nSrcLineStart;
+        const int nSrcLineCount = nSrcLineStop - nSrcLineStart;
         double dfWeightSum = 0.0;
 
-        /* Compute convolution coefficients */
-        int nSrcLine = nSrcLineStart;
+        // Compute convolution coefficients.
+        int nSrcLine = nSrcLineStart;  // Used after for.
         double dfY = dfYScaleWeight * (nSrcLine - dfSrcLine + 0.5);
-        for( ; nSrcLine + 3 < nSrcLineStop; nSrcLine+=4, dfY += 4 * dfYScaleWeight)
+        for( ;
+             nSrcLine + 3 < nSrcLineStop;
+             nSrcLine += 4, dfY += 4 * dfYScaleWeight)
         {
             padfWeights[nSrcLine - nSrcLineStart] = dfY;
             padfWeights[nSrcLine+1 - nSrcLineStart] = dfY + dfYScaleWeight;
             padfWeights[nSrcLine+2 - nSrcLineStart] = dfY + 2 * dfYScaleWeight;
             padfWeights[nSrcLine+3 - nSrcLineStart] = dfY + 3 * dfYScaleWeight;
-            dfWeightSum += pfnFilterFunc4Values(padfWeights + nSrcLine - nSrcLineStart);
+            dfWeightSum +=
+                pfnFilterFunc4Values(padfWeights + nSrcLine - nSrcLineStart);
         }
-        for( ; nSrcLine < nSrcLineStop; nSrcLine++, dfY += dfYScaleWeight)
+        for( ; nSrcLine < nSrcLineStop; ++nSrcLine, dfY += dfYScaleWeight )
         {
-            double dfWeight = pfnFilterFunc(dfY);
+            const double dfWeight = pfnFilterFunc(dfY);
             padfWeights[nSrcLine - nSrcLineStart] = dfWeight;
             dfWeightSum += dfWeight;
         }
@@ -1615,47 +1846,63 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
         {
             if( dfWeightSum != 0 )
             {
-                double dfInvWeightSum = 1.0 / dfWeightSum;
-                for(int i=0;i<nSrcLineCount;i++)
+                const double dfInvWeightSum = 1.0 / dfWeightSum;
+                for( int i = 0; i < nSrcLineCount; ++i )
                     padfWeights[i] *= dfInvWeightSum;
             }
         }
 
         if( pabyChunkNodataMask == NULL )
         {
-            int iFilteredPixelOff = 0;
-            int j=(nSrcLineStart - nChunkYOff) * nDstXSize;
-            for( ; iFilteredPixelOff+1 < nDstXSize; iFilteredPixelOff += 2, j+=2 )
+            int iFilteredPixelOff = 0;  // Used after for.
+            // j used after for.
+            int j = (nSrcLineStart - nChunkYOff) * nDstXSize;
+            for( ;
+                 iFilteredPixelOff+1 < nDstXSize;
+                 iFilteredPixelOff += 2, j += 2 )
             {
-                double dfVal1, dfVal2;
+                double dfVal1 = 0.0;
+                double dfVal2 = 0.0;
                 GDALResampleConvolutionVertical_2cols(
-                    padfHorizontalFilteredBand + j, nDstXSize, padfWeights, nSrcLineCount, dfVal1, dfVal2);
-                pafDstScanline[iFilteredPixelOff] = (float)dfVal1;
-                pafDstScanline[iFilteredPixelOff+1] = (float)dfVal2;
+                    padfHorizontalFilteredBand + j, nDstXSize, padfWeights,
+                    nSrcLineCount, dfVal1, dfVal2 );
+                pafDstScanline[iFilteredPixelOff] = static_cast<float>(dfVal1);
+                pafDstScanline[iFilteredPixelOff+1] =
+                    static_cast<float>(dfVal2);
             }
             if( iFilteredPixelOff < nDstXSize )
             {
-                double dfVal = GDALResampleConvolutionVertical(
-                    padfHorizontalFilteredBand + j, nDstXSize, padfWeights, nSrcLineCount);
-                pafDstScanline[iFilteredPixelOff] = (float)dfVal;
+                const double dfVal =
+                    GDALResampleConvolutionVertical(
+                        padfHorizontalFilteredBand + j,
+                        nDstXSize, padfWeights, nSrcLineCount );
+                pafDstScanline[iFilteredPixelOff] = static_cast<float>(dfVal);
             }
         }
         else
         {
-            for( int iFilteredPixelOff = 0; iFilteredPixelOff < nDstXSize; iFilteredPixelOff ++ )
+            for( int iFilteredPixelOff = 0;
+                 iFilteredPixelOff < nDstXSize;
+                 ++iFilteredPixelOff )
             {
                 double dfVal = 0.0;
                 dfWeightSum = 0.0;
-                for(int i=0, j=(nSrcLineStart - nChunkYOff) * nDstXSize + iFilteredPixelOff;
-                    i<nSrcLineCount; i++, j+=nDstXSize)
+                for( int i = 0,
+                         j = (nSrcLineStart - nChunkYOff) * nDstXSize
+                             + iFilteredPixelOff;
+                    i < nSrcLineCount;
+                    ++i, j += nDstXSize)
                 {
-                    double dfWeight = padfWeights[i] * pabyChunkNodataMaskHorizontalFiltered[j];
+                    const double dfWeight =
+                        padfWeights[i]
+                        * pabyChunkNodataMaskHorizontalFiltered[j];
                     dfVal += padfHorizontalFilteredBand[j] * dfWeight;
                     dfWeightSum += dfWeight;
                 }
                 if( dfWeightSum > 0.0 )
                 {
-                    pafDstScanline[iFilteredPixelOff] = (float)(dfVal / dfWeightSum);
+                    pafDstScanline[iFilteredPixelOff] =
+                        static_cast<float>(dfVal / dfWeightSum);
                 }
                 else
                 {
@@ -1664,45 +1911,47 @@ GDALResampleChunk32R_ConvolutionT( double dfXRatioDstToSrc, double dfYRatioDstTo
             }
         }
 
-        if( fMaxVal )
+        if( fMaxVal != 0.0f )
         {
-            for(int i=0;i<nDstXSize;i++)
+            for( int i = 0; i < nDstXSize; ++i )
             {
                 if( pafDstScanline[i] > fMaxVal )
                     pafDstScanline[i] = fMaxVal;
             }
         }
 
-        eErr = papoDstBands[iBand]->RasterIO( GF_Write, nDstXOff, iDstLine, nDstXSize, 1,
-                                     pafDstScanline, nDstXSize, 1, GDT_Float32,
-                                     0, 0, NULL );
+        eErr = papoDstBands[iBand]->RasterIO(
+            GF_Write, nDstXOff, iDstLine, nDstXSize, 1,
+            pafDstScanline, nDstXSize, 1, GDT_Float32,
+            0, 0, NULL );
     }
   }
 
-    VSIFree( padfWeightsAlloc );
+    VSIFreeAligned( padfWeights );
     VSIFree( padfHorizontalFiltered );
     VSIFree( pafDstScanline );
-    VSIFree(pabyChunkNodataMaskHorizontalFiltered);
+    VSIFree( pabyChunkNodataMaskHorizontalFiltered );
 
     return eErr;
 }
 
 static CPLErr GDALResampleChunk32R_Convolution(
-                        double dfXRatioDstToSrc, double dfYRatioDstToSrc,
-                        double dfSrcXDelta,
-                        double dfSrcYDelta,
-                        GDALDataType eWrkDataType,
-                        void * pChunk,
-                        GByte * pabyChunkNodataMask,
-                        int nChunkXOff, int nChunkXSize,
-                        int nChunkYOff, int nChunkYSize,
-                        int nDstXOff, int nDstXOff2,
-                        int nDstYOff, int nDstYOff2,
-                        GDALRasterBand * poOverview,
-                        const char * pszResampling,
-                        int bHasNoData, float fNoDataValue,
-                        CPL_UNUSED GDALColorTable* poColorTable_unused,
-                        CPL_UNUSED GDALDataType eSrcDataType)
+    double dfXRatioDstToSrc, double dfYRatioDstToSrc,
+    double dfSrcXDelta,
+    double dfSrcYDelta,
+    GDALDataType eWrkDataType,
+    void * pChunk,
+    GByte * pabyChunkNodataMask,
+    int nChunkXOff, int nChunkXSize,
+    int nChunkYOff, int nChunkYSize,
+    int nDstXOff, int nDstXOff2,
+    int nDstYOff, int nDstYOff2,
+    GDALRasterBand * poOverview,
+    const char * pszResampling,
+    int bHasNoData, float fNoDataValue,
+    GDALColorTable* /* poColorTable_unused */,
+    GDALDataType /* eSrcDataType */,
+    bool /* bPropagateNoData */ )
 {
     GDALResampleAlg eResample;
     if( EQUAL(pszResampling, "BILINEAR") )
@@ -1715,78 +1964,84 @@ static CPLErr GDALResampleChunk32R_Convolution(
         eResample = GRA_Lanczos;
     else
     {
-        CPLAssert(0);
+        CPLAssert(false);
         return CE_Failure;
     }
-    int nKernelRadius = GWKGetFilterRadius(eResample);
+    const int nKernelRadius = GWKGetFilterRadius(eResample);
     FilterFuncType pfnFilterFunc = GWKGetFilterFunc(eResample);
-    FilterFunc4ValuesType pfnFilterFunc4Values = GWKGetFilterFunc4Values(eResample);
+    const FilterFunc4ValuesType pfnFilterFunc4Values =
+        GWKGetFilterFunc4Values(eResample);
 
     float fMaxVal = 0.f;
     // Cubic, etc... can have overshoots, so make sure we clamp values to the
-    // maximum value if NBITS is set
-    const char* pszNBITS = poOverview->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+    // maximum value if NBITS is set.
+    const char* pszNBITS =
+        poOverview->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
     GDALDataType eBandDT = poOverview->GetRasterDataType();
     if( eResample != GRA_Bilinear && pszNBITS != NULL &&
-        (eBandDT == GDT_Byte || eBandDT == GDT_UInt16 || eBandDT == GDT_UInt32) )
+        (eBandDT == GDT_Byte || eBandDT == GDT_UInt16 ||
+         eBandDT == GDT_UInt32) )
     {
         int nBits = atoi(pszNBITS);
         if( nBits == GDALGetDataTypeSize(eBandDT) )
             nBits = 0;
         if( nBits )
-            fMaxVal = (float)((1 << nBits) -1);
-    }
-
-    if (eWrkDataType == GDT_Byte)
-        return GDALResampleChunk32R_ConvolutionT<GByte, FALSE>
-                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
-                        dfSrcXDelta, dfSrcYDelta,
-                        (GByte *) pChunk, 1,
-                        pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff, nChunkYSize,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        &poOverview,
-                        bHasNoData, fNoDataValue,
-                        pfnFilterFunc,
-                        pfnFilterFunc4Values,
-                        nKernelRadius,
-                        fMaxVal);
-   else if (eWrkDataType == GDT_UInt16)
-        return GDALResampleChunk32R_ConvolutionT<GUInt16,FALSE>
-                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
-                        dfSrcXDelta, dfSrcYDelta,
-                        (GUInt16 *) pChunk, 1,
-                        pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff, nChunkYSize,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        &poOverview,
-                        bHasNoData, fNoDataValue,
-                        pfnFilterFunc,
-                        pfnFilterFunc4Values,
-                        nKernelRadius,
-                        fMaxVal);
-    else if (eWrkDataType == GDT_Float32)
-        return GDALResampleChunk32R_ConvolutionT<float,FALSE>
-                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
-                        dfSrcXDelta, dfSrcYDelta,
-                        (float *) pChunk, 1,
-                        pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff, nChunkYSize,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        &poOverview,
-                        bHasNoData, fNoDataValue,
-                        pfnFilterFunc,
-                        pfnFilterFunc4Values,
-                        nKernelRadius,
-                        fMaxVal);
-
-    CPLAssert(0);
+            fMaxVal = static_cast<float>((1 << nBits) -1);
+    }
+
+    if( eWrkDataType == GDT_Byte )
+        return GDALResampleChunk32R_ConvolutionT<GByte, false>(
+            dfXRatioDstToSrc, dfYRatioDstToSrc,
+            dfSrcXDelta, dfSrcYDelta,
+            static_cast<GByte *>( pChunk ),
+            1,
+            pabyChunkNodataMask,
+            nChunkXOff, nChunkXSize,
+            nChunkYOff, nChunkYSize,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            &poOverview,
+            bHasNoData, fNoDataValue,
+            pfnFilterFunc,
+            pfnFilterFunc4Values,
+            nKernelRadius,
+            fMaxVal );
+    else if( eWrkDataType == GDT_UInt16 )
+        return GDALResampleChunk32R_ConvolutionT<GUInt16, false>(
+            dfXRatioDstToSrc, dfYRatioDstToSrc,
+            dfSrcXDelta, dfSrcYDelta,
+            static_cast<GUInt16 *>( pChunk ),
+            1,
+            pabyChunkNodataMask,
+            nChunkXOff, nChunkXSize,
+            nChunkYOff, nChunkYSize,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            &poOverview,
+            bHasNoData, fNoDataValue,
+            pfnFilterFunc,
+            pfnFilterFunc4Values,
+            nKernelRadius,
+            fMaxVal );
+    else if( eWrkDataType == GDT_Float32 )
+        return GDALResampleChunk32R_ConvolutionT<float, false>(
+            dfXRatioDstToSrc, dfYRatioDstToSrc,
+            dfSrcXDelta, dfSrcYDelta,
+            static_cast<float *>( pChunk ),
+            1,
+            pabyChunkNodataMask,
+            nChunkXOff, nChunkXSize,
+            nChunkYOff, nChunkYSize,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            &poOverview,
+            bHasNoData, fNoDataValue,
+            pfnFilterFunc,
+            pfnFilterFunc4Values,
+            nKernelRadius,
+            fMaxVal );
+
+    CPLAssert(false);
     return CE_Failure;
 }
 
@@ -1796,36 +2051,38 @@ static CPLErr GDALResampleChunk32R_Convolution(
 
 static CPLErr
 GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
-                         float * pafChunk, int nChunkYOff, int nChunkYSize,
-                         int nDstYOff, int nDstYOff2,
-                         GDALRasterBand * poOverview,
-                         const char * pszResampling )
+                       float * pafChunk, int nChunkYOff, int nChunkYSize,
+                       int nDstYOff, int nDstYOff2,
+                       GDALRasterBand * poOverview,
+                       const char * pszResampling )
 
 {
-    CPLErr   eErr = CE_None;
-
-    int nOXSize = poOverview->GetXSize();
-    int nOYSize = poOverview->GetYSize();
-    double dfXRatioDstToSrc = (double)nSrcWidth / nOXSize;
-    double dfYRatioDstToSrc = (double)nSrcHeight / nOYSize;
+    const int nOXSize = poOverview->GetXSize();
 
-    float *pafDstScanline
-        = (float *) VSI_MALLOC_VERBOSE(nOXSize * sizeof(float) * 2);
+    float * const pafDstScanline
+        = static_cast<float *>(VSI_MALLOC_VERBOSE(nOXSize * sizeof(float) * 2));
     if( pafDstScanline == NULL )
     {
         return CE_Failure;
     }
 
+    const int nOYSize = poOverview->GetYSize();
+    const double dfXRatioDstToSrc = static_cast<double>(nSrcWidth) / nOXSize;
+    const double dfYRatioDstToSrc = static_cast<double>(nSrcHeight) / nOYSize;
+
 /* ==================================================================== */
 /*      Loop over destination scanlines.                                */
 /* ==================================================================== */
-    for( int iDstLine = nDstYOff; iDstLine < nDstYOff2 && eErr == CE_None; iDstLine++ )
+    CPLErr eErr = CE_None;
+    for( int iDstLine = nDstYOff;
+         iDstLine < nDstYOff2 && eErr == CE_None;
+         ++iDstLine )
     {
-        int nSrcYOff = (int) (0.5 + iDstLine * dfYRatioDstToSrc);
+        int nSrcYOff = static_cast<int>(0.5 + iDstLine * dfYRatioDstToSrc);
         if( nSrcYOff < nChunkYOff )
             nSrcYOff = nChunkYOff;
 
-        int nSrcYOff2 = (int) (0.5 + (iDstLine+1) * dfYRatioDstToSrc);
+        int nSrcYOff2 = static_cast<int>(0.5 + (iDstLine+1) * dfYRatioDstToSrc);
         if( nSrcYOff2 == nSrcYOff )
             nSrcYOff2 ++;
 
@@ -1838,18 +2095,17 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
         if( nSrcYOff2 > nChunkYOff + nChunkYSize )
             nSrcYOff2 = nChunkYOff + nChunkYSize;
 
-        float *pafSrcScanline
-            = pafChunk + ((nSrcYOff-nChunkYOff) * nSrcWidth) * 2;
+        float * const pafSrcScanline =
+            pafChunk + ((nSrcYOff - nChunkYOff) * nSrcWidth) * 2;
 
 /* -------------------------------------------------------------------- */
 /*      Loop over destination pixels                                    */
 /* -------------------------------------------------------------------- */
-        int iDstPixel;
-        for( iDstPixel = 0; iDstPixel < nOXSize; iDstPixel++ )
+        for( int iDstPixel = 0; iDstPixel < nOXSize; ++iDstPixel )
         {
-            int nSrcXOff = (int) (0.5 + iDstPixel * dfXRatioDstToSrc);
-            int nSrcXOff2 = (int)
-                (0.5 + (iDstPixel+1) * dfXRatioDstToSrc);
+            int nSrcXOff = static_cast<int>(0.5 + iDstPixel * dfXRatioDstToSrc);
+            int nSrcXOff2 = static_cast<int>(
+                0.5 + (iDstPixel+1) * dfXRatioDstToSrc);
             if( nSrcXOff2 == nSrcXOff )
                 nSrcXOff2 ++;
             if( nSrcXOff2 > nSrcWidth || iDstPixel == nOXSize-1 )
@@ -1864,21 +2120,25 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
                 pafDstScanline[iDstPixel*2] = pafSrcScanline[nSrcXOff*2];
                 pafDstScanline[iDstPixel*2+1] = pafSrcScanline[nSrcXOff*2+1];
             }
-            else if( EQUAL(pszResampling,"AVERAGE_MAGPHASE") )
+            else if( EQUAL(pszResampling, "AVERAGE_MAGPHASE") )
             {
-                double dfTotalR = 0.0, dfTotalI = 0.0, dfTotalM = 0.0;
-                int    nCount = 0;
+                double dfTotalR = 0.0;
+                double dfTotalI = 0.0;
+                double dfTotalM = 0.0;
+                int nCount = 0;
 
-                for( int iY = nSrcYOff; iY < nSrcYOff2; iY++ )
+                for( int iY = nSrcYOff; iY < nSrcYOff2; ++iY )
                 {
-                    for( int iX = nSrcXOff; iX < nSrcXOff2; iX++ )
+                    for( int iX = nSrcXOff; iX < nSrcXOff2; ++iX )
                     {
-                        double dfR = pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2];
-                        double dfI = pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2+1];
+                        const double dfR =
+                            pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2];
+                        const double dfI =
+                            pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2+1];
                         dfTotalR += dfR;
                         dfTotalI += dfI;
                         dfTotalM += sqrt( dfR*dfR + dfI*dfI );
-                        nCount++;
+                        ++nCount;
                     }
                 }
 
@@ -1890,32 +2150,43 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
                 }
                 else
                 {
-                    pafDstScanline[iDstPixel*2  ] = (float) (dfTotalR/nCount);
-                    pafDstScanline[iDstPixel*2+1] = (float) (dfTotalI/nCount);
-
-                    const double dfM = sqrt(pafDstScanline[iDstPixel*2  ]*pafDstScanline[iDstPixel*2  ]
-                             + pafDstScanline[iDstPixel*2+1]*pafDstScanline[iDstPixel*2+1]);
+                    pafDstScanline[iDstPixel*2  ] =
+                        static_cast<float>(dfTotalR/nCount);
+                    pafDstScanline[iDstPixel*2+1] =
+                        static_cast<float>(dfTotalI/nCount);
+
+                    const double dfM =
+                        sqrt( pafDstScanline[iDstPixel*2]
+                                  * pafDstScanline[iDstPixel*2]
+                              + pafDstScanline[iDstPixel*2+1]
+                                  * pafDstScanline[iDstPixel*2+1] );
                     const double dfDesiredM = dfTotalM / nCount;
-                    double dfRatio=1.0;
+                    double dfRatio = 1.0;
                     if( dfM != 0.0 )
                         dfRatio = dfDesiredM / dfM;
 
-                    pafDstScanline[iDstPixel*2  ] *= (float) dfRatio;
-                    pafDstScanline[iDstPixel*2+1] *= (float) dfRatio;
+                    pafDstScanline[iDstPixel*2] *=
+                        static_cast<float>(dfRatio);
+                    pafDstScanline[iDstPixel*2+1] *=
+                        static_cast<float>(dfRatio);
                 }
             }
             else if( STARTS_WITH_CI(pszResampling, "AVER") )
             {
-                double dfTotalR = 0.0, dfTotalI = 0.0;
+                double dfTotalR = 0.0;
+                double dfTotalI = 0.0;
                 int nCount = 0;
 
-                for( int iY = nSrcYOff; iY < nSrcYOff2; iY++ )
+                for( int iY = nSrcYOff; iY < nSrcYOff2; ++iY )
                 {
-                    for( int iX = nSrcXOff; iX < nSrcXOff2; iX++ )
+                    for( int iX = nSrcXOff; iX < nSrcXOff2; ++iX )
                     {
-                        dfTotalR += pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2];
-                        dfTotalI += pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2+1];
-                        nCount++;
+                        // TODO(schwehr): Maybe use std::complex?
+                        dfTotalR +=
+                            pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2];
+                        dfTotalI +=
+                            pafSrcScanline[iX*2+(iY-nSrcYOff)*nSrcWidth*2+1];
+                        ++nCount;
                     }
                 }
 
@@ -1927,8 +2198,10 @@ GDALResampleChunkC32R( int nSrcWidth, int nSrcHeight,
                 }
                 else
                 {
-                    pafDstScanline[iDstPixel*2  ] = (float) (dfTotalR/nCount);
-                    pafDstScanline[iDstPixel*2+1] = (float) (dfTotalI/nCount);
+                    pafDstScanline[iDstPixel*2  ] =
+                        static_cast<float>(dfTotalR/nCount);
+                    pafDstScanline[iDstPixel*2+1] =
+                        static_cast<float>(dfTotalI/nCount);
                 }
             }
         }
@@ -1961,14 +2234,14 @@ GDALRegenerateCascadingOverviews(
 /*      First, we must put the overviews in order from largest to       */
 /*      smallest.                                                       */
 /* -------------------------------------------------------------------- */
-    for( int i = 0; i < nOverviews-1; i++ )
+    for( int i = 0; i < nOverviews-1; ++i )
     {
-        for( int j = 0; j < nOverviews - i - 1; j++ )
+        for( int j = 0; j < nOverviews - i - 1; ++j )
         {
             if( papoOvrBands[j]->GetXSize()
-                * (float) papoOvrBands[j]->GetYSize() <
+                * static_cast<float>( papoOvrBands[j]->GetYSize() ) <
                 papoOvrBands[j+1]->GetXSize()
-                * (float) papoOvrBands[j+1]->GetYSize() )
+                * static_cast<float>( papoOvrBands[j+1]->GetYSize() ) )
             {
                 GDALRasterBand *poTempBand = papoOvrBands[j];
                 papoOvrBands[j] = papoOvrBands[j+1];
@@ -1981,44 +2254,43 @@ GDALRegenerateCascadingOverviews(
 /*      Count total pixels so we can prepare appropriate scaled         */
 /*      progress functions.                                             */
 /* -------------------------------------------------------------------- */
-    double       dfTotalPixels = 0.0;
+    double dfTotalPixels = 0.0;
 
-    for( int i = 0; i < nOverviews; i++ )
+    for( int i = 0; i < nOverviews; ++i )
     {
         dfTotalPixels += papoOvrBands[i]->GetXSize()
-            * (double) papoOvrBands[i]->GetYSize();
+            * static_cast<double>( papoOvrBands[i]->GetYSize() );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Generate all the bands.                                         */
 /* -------------------------------------------------------------------- */
-    double      dfPixelsProcessed = 0.0;
+    double dfPixelsProcessed = 0.0;
 
-    for( int i = 0; i < nOverviews; i++ )
+    for( int i = 0; i < nOverviews; ++i )
     {
-        GDALRasterBand *poBaseBand;
-
-        if( i == 0 )
-            poBaseBand = poSrcBand;
-        else
+        GDALRasterBand *poBaseBand = poSrcBand;
+        if( i != 0 )
             poBaseBand = papoOvrBands[i-1];
 
-        double  dfPixels
-            = papoOvrBands[i]->GetXSize()
-            * (double) papoOvrBands[i]->GetYSize();
+        double dfPixels =
+            papoOvrBands[i]->GetXSize()
+            * static_cast<double>( papoOvrBands[i]->GetYSize() );
 
-        void *pScaledProgressData
-            = GDALCreateScaledProgress(
+        void *pScaledProgressData =
+            GDALCreateScaledProgress(
             dfPixelsProcessed / dfTotalPixels,
             (dfPixelsProcessed + dfPixels) / dfTotalPixels,
             pfnProgress, pProgressData );
 
-        CPLErr eErr
-            = GDALRegenerateOverviews( (GDALRasterBandH) poBaseBand,
-                                        1, (GDALRasterBandH *) papoOvrBands+i,
-                                        pszResampling,
-                                        GDALScaledProgress,
-                                        pScaledProgressData );
+        const CPLErr eErr =
+            GDALRegenerateOverviews(
+                poBaseBand,
+                1,
+                reinterpret_cast<GDALRasterBandH *>( papoOvrBands ) + i,
+                pszResampling,
+                GDALScaledProgress,
+                pScaledProgressData );
         GDALDestroyScaledProgress( pScaledProgressData );
 
         if( eErr != CE_None )
@@ -2026,8 +2298,9 @@ GDALRegenerateCascadingOverviews(
 
         dfPixelsProcessed += dfPixels;
 
-        /* we only do the bit2grayscale promotion on the base band */
-        if( STARTS_WITH_CI(pszResampling,"AVERAGE_BIT2G" /* AVERAGE_BIT2GRAYSCALE */) )
+        // Only do the bit2grayscale promotion on the base band.
+        if( STARTS_WITH_CI( pszResampling,
+                            "AVERAGE_BIT2G" /* AVERAGE_BIT2GRAYSCALE */) )
             pszResampling = "AVERAGE";
     }
 
@@ -2038,8 +2311,8 @@ GDALRegenerateCascadingOverviews(
 /*                    GDALGetResampleFunction()                         */
 /************************************************************************/
 
-GDALResampleFunction GDALGetResampleFunction(const char* pszResampling,
-                                                 int* pnRadius)
+GDALResampleFunction GDALGetResampleFunction( const char* pszResampling,
+                                              int* pnRadius )
 {
     if( pnRadius ) *pnRadius = 0;
     if( STARTS_WITH_CI(pszResampling, "NEAR") )
@@ -2075,9 +2348,10 @@ GDALResampleFunction GDALGetResampleFunction(const char* pszResampling,
     }
     else
     {
-       CPLError( CE_Failure, CPLE_AppDefined,
-                  "GDALGetResampleFunction: Unsupported resampling method \"%s\".",
-                  pszResampling );
+       CPLError(
+           CE_Failure, CPLE_AppDefined,
+           "GDALGetResampleFunction: Unsupported resampling method \"%s\".",
+           pszResampling );
         return NULL;
     }
 }
@@ -2085,28 +2359,28 @@ GDALResampleFunction GDALGetResampleFunction(const char* pszResampling,
 #ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
 
 // For some reason, this does not perform better, and sometimes it performs
-// worse that when operating band after band. Probably due to cache misses
+// worse that when operating band after band. Probably due to cache misses.
 
 /************************************************************************/
 /*             GDALResampleChunk32RMultiBands_Convolution()             */
 /************************************************************************/
 
 static CPLErr GDALResampleChunk32RMultiBands_Convolution(
-                        double dfXRatioDstToSrc, double dfYRatioDstToSrc,
-                        double dfSrcXDelta,
-                        double dfSrcYDelta,
-                        GDALDataType eWrkDataType,
-                        void * pChunk, int nBands,
-                        GByte * pabyChunkNodataMask,
-                        int nChunkXOff, int nChunkXSize,
-                        int nChunkYOff, int nChunkYSize,
-                        int nDstXOff, int nDstXOff2,
-                        int nDstYOff, int nDstYOff2,
-                        GDALRasterBand **papoDstBands,
-                        const char * pszResampling,
-                        int bHasNoData, float fNoDataValue,
-                        CPL_UNUSED GDALColorTable* poColorTable_unused,
-                        CPL_UNUSED GDALDataType eSrcDataType)
+    double dfXRatioDstToSrc, double dfYRatioDstToSrc,
+    double dfSrcXDelta,
+    double dfSrcYDelta,
+    GDALDataType eWrkDataType,
+    void * pChunk, int nBands,
+    GByte * pabyChunkNodataMask,
+    int nChunkXOff, int nChunkXSize,
+    int nChunkYOff, int nChunkYSize,
+    int nDstXOff, int nDstXOff2,
+    int nDstYOff, int nDstYOff2,
+    GDALRasterBand **papoDstBands,
+    const char * pszResampling,
+    int bHasNoData, float fNoDataValue,
+    GDALColorTable* /* poColorTable_unused */,
+    GDALDataType /* eSrcDataType */ )
 {
     GDALResampleAlg eResample;
     if( EQUAL(pszResampling, "BILINEAR") )
@@ -2119,78 +2393,81 @@ static CPLErr GDALResampleChunk32RMultiBands_Convolution(
         eResample = GRA_Lanczos;
     else
     {
-        CPLAssert(0);
+        CPLAssert(false);
         return CE_Failure;
     }
     int nKernelRadius = GWKGetFilterRadius(eResample);
     FilterFuncType pfnFilterFunc = GWKGetFilterFunc(eResample);
-    FilterFunc4ValuesType pfnFilterFunc4Values = GWKGetFilterFunc4Values(eResample);
+    FilterFunc4ValuesType pfnFilterFunc4Values =
+        GWKGetFilterFunc4Values(eResample);
 
-    float fMaxVal = 0.f;
+    float fMaxVal = 0.0f;
     // Cubic, etc... can have overshoots, so make sure we clamp values to the
     // maximum value if NBITS is set
-    const char* pszNBITS = papoDstBands[0]->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+    const char* pszNBITS =
+        papoDstBands[0]->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
     GDALDataType eBandDT = papoDstBands[0]->GetRasterDataType();
     if( eResample != GRA_Bilinear && pszNBITS != NULL &&
-        (eBandDT == GDT_Byte || eBandDT == GDT_UInt16 || eBandDT == GDT_UInt32) )
+        (eBandDT == GDT_Byte || eBandDT == GDT_UInt16 ||
+         eBandDT == GDT_UInt32) )
     {
         int nBits = atoi(pszNBITS);
         if( nBits == GDALGetDataTypeSize(eBandDT) )
             nBits = 0;
         if( nBits )
-            fMaxVal = (float)((1 << nBits) -1);
-    }
-
-    if (eWrkDataType == GDT_Byte)
-        return GDALResampleChunk32R_ConvolutionT<GByte, TRUE>
-                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
-                        dfSrcXDelta, dfSrcYDelta,
-                        (GByte *) pChunk, nBands,
-                        pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff, nChunkYSize,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        papoDstBands,
-                        bHasNoData, fNoDataValue,
-                        pfnFilterFunc,
-                        pfnFilterFunc4Values,
-                        nKernelRadius,
-                        fMaxVal);
-   else if (eWrkDataType == GDT_UInt16)
-        return GDALResampleChunk32R_ConvolutionT<GUInt16,TRUE>
-                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
-                        dfSrcXDelta, dfSrcYDelta,
-                        (GUInt16 *) pChunk, nBands,
-                        pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff, nChunkYSize,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        papoDstBands,
-                        bHasNoData, fNoDataValue,
-                        pfnFilterFunc,
-                        pfnFilterFunc4Values,
-                        nKernelRadius,
-                        fMaxVal);
-    else if (eWrkDataType == GDT_Float32)
-        return GDALResampleChunk32R_ConvolutionT<float,TRUE>
-                       (dfXRatioDstToSrc, dfYRatioDstToSrc,
-                        dfSrcXDelta, dfSrcYDelta,
-                        (float *) pChunk, nBands,
-                        pabyChunkNodataMask,
-                        nChunkXOff, nChunkXSize,
-                        nChunkYOff, nChunkYSize,
-                        nDstXOff, nDstXOff2,
-                        nDstYOff, nDstYOff2,
-                        papoDstBands,
-                        bHasNoData, fNoDataValue,
-                        pfnFilterFunc,
-                        pfnFilterFunc4Values,
-                        nKernelRadius,
-                        fMaxVal);
-
-    CPLAssert(0);
+            fMaxVal = static_cast<float>((1 << nBits) -1);
+    }
+
+    if( eWrkDataType == GDT_Byte )
+        return GDALResampleChunk32R_ConvolutionT<GByte, true>(
+            dfXRatioDstToSrc, dfYRatioDstToSrc,
+            dfSrcXDelta, dfSrcYDelta,
+            static_cast<GByte *>( pChunk ), nBands,
+            pabyChunkNodataMask,
+            nChunkXOff, nChunkXSize,
+            nChunkYOff, nChunkYSize,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            papoDstBands,
+            bHasNoData, fNoDataValue,
+            pfnFilterFunc,
+            pfnFilterFunc4Values,
+            nKernelRadius,
+            fMaxVal );
+    else if( eWrkDataType == GDT_UInt16 )
+        return GDALResampleChunk32R_ConvolutionT<GUInt16, true>(
+            dfXRatioDstToSrc, dfYRatioDstToSrc,
+            dfSrcXDelta, dfSrcYDelta,
+            static_cast<GUInt16 *>( pChunk ), nBands,
+            pabyChunkNodataMask,
+            nChunkXOff, nChunkXSize,
+            nChunkYOff, nChunkYSize,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            papoDstBands,
+            bHasNoData, fNoDataValue,
+            pfnFilterFunc,
+            pfnFilterFunc4Values,
+            nKernelRadius,
+            fMaxVal );
+    else if( eWrkDataType == GDT_Float32 )
+        return GDALResampleChunk32R_ConvolutionT<float, true>(
+            dfXRatioDstToSrc, dfYRatioDstToSrc,
+            dfSrcXDelta, dfSrcYDelta,
+            static_cast<float *>( pChunk ), nBands,
+            pabyChunkNodataMask,
+            nChunkXOff, nChunkXSize,
+            nChunkYOff, nChunkYSize,
+            nDstXOff, nDstXOff2,
+            nDstYOff, nDstYOff2,
+            papoDstBands,
+            bHasNoData, fNoDataValue,
+            pfnFilterFunc,
+            pfnFilterFunc4Values,
+            nKernelRadius,
+            fMaxVal );
+
+    CPLAssert(false);
     return CE_Failure;
 }
 
@@ -2199,34 +2476,31 @@ static CPLErr GDALResampleChunk32RMultiBands_Convolution(
 /************************************************************************/
 
 GDALResampleFunctionMultiBands GDALGetResampleFunctionMultiBands(
-                                                 const char* pszResampling,
-                                                 int* pnRadius)
+    const char* pszResampling, int* pnRadius )
 {
     if( pnRadius ) *pnRadius = 0;
-    if( EQUAL(pszResampling,"CUBIC") )
+    if( EQUAL(pszResampling, "CUBIC") )
     {
         if( pnRadius ) *pnRadius = GWKGetFilterRadius(GRA_Cubic);
         return GDALResampleChunk32RMultiBands_Convolution;
     }
-    else if( EQUAL(pszResampling,"CUBICSPLINE") )
+    else if( EQUAL(pszResampling, "CUBICSPLINE") )
     {
         if( pnRadius ) *pnRadius = GWKGetFilterRadius(GRA_CubicSpline);
         return GDALResampleChunk32RMultiBands_Convolution;
     }
-    else if( EQUAL(pszResampling,"LANCZOS") )
+    else if( EQUAL(pszResampling, "LANCZOS") )
     {
         if( pnRadius ) *pnRadius = GWKGetFilterRadius(GRA_Lanczos);
         return GDALResampleChunk32RMultiBands_Convolution;
     }
-    else if( EQUAL(pszResampling,"BILINEAR") )
+    else if( EQUAL(pszResampling, "BILINEAR") )
     {
         if( pnRadius ) *pnRadius = GWKGetFilterRadius(GRA_Bilinear);
         return GDALResampleChunk32RMultiBands_Convolution;
     }
-    else
-    {
-        return NULL;
-    }
+
+    return NULL;
 }
 #endif
 
@@ -2234,27 +2508,31 @@ GDALResampleFunctionMultiBands GDALGetResampleFunctionMultiBands(
 /*                      GDALGetOvrWorkDataType()                        */
 /************************************************************************/
 
-GDALDataType GDALGetOvrWorkDataType(const char* pszResampling,
-                                        GDALDataType eSrcDataType)
+GDALDataType GDALGetOvrWorkDataType( const char* pszResampling,
+                                     GDALDataType eSrcDataType )
 {
     if( (STARTS_WITH_CI(pszResampling, "NEAR") ||
          STARTS_WITH_CI(pszResampling, "AVER") ||
-         EQUAL(pszResampling,"CUBIC") ||
-         EQUAL(pszResampling,"CUBICSPLINE") ||
-         EQUAL(pszResampling,"LANCZOS") ||
-         EQUAL(pszResampling,"BILINEAR")) &&
-        eSrcDataType == GDT_Byte)
+         EQUAL(pszResampling, "CUBIC") ||
+         EQUAL(pszResampling, "CUBICSPLINE") ||
+         EQUAL(pszResampling, "LANCZOS") ||
+         EQUAL(pszResampling, "BILINEAR")) &&
+        eSrcDataType == GDT_Byte )
+    {
         return GDT_Byte;
+    }
     else if( (STARTS_WITH_CI(pszResampling, "NEAR") ||
          STARTS_WITH_CI(pszResampling, "AVER") ||
-         EQUAL(pszResampling,"CUBIC") ||
-         EQUAL(pszResampling,"CUBICSPLINE") ||
-         EQUAL(pszResampling,"LANCZOS") ||
-         EQUAL(pszResampling,"BILINEAR")) &&
-        eSrcDataType == GDT_UInt16)
+         EQUAL(pszResampling, "CUBIC") ||
+         EQUAL(pszResampling, "CUBICSPLINE") ||
+         EQUAL(pszResampling, "LANCZOS") ||
+         EQUAL(pszResampling, "BILINEAR")) &&
+        eSrcDataType == GDT_UInt16 )
+    {
         return GDT_UInt16;
-    else
-        return GDT_Float32;
+    }
+
+    return GDT_Float32;
 }
 
 /************************************************************************/
@@ -2264,20 +2542,21 @@ GDALDataType GDALGetOvrWorkDataType(const char* pszResampling,
 /**
  * \brief Generate downsampled overviews.
  *
- * This function will generate one or more overview images from a base
- * image using the requested downsampling algorithm.  It's primary use
- * is for generating overviews via GDALDataset::BuildOverviews(), but it
- * can also be used to generate downsampled images in one file from another
- * outside the overview architecture.
+ * This function will generate one or more overview images from a base image
+ * using the requested downsampling algorithm.  Its primary use is for
+ * generating overviews via GDALDataset::BuildOverviews(), but it can also be
+ * used to generate downsampled images in one file from another outside the
+ * overview architecture.
  *
  * The output bands need to exist in advance.
  *
  * The full set of resampling algorithms is documented in
  * GDALDataset::BuildOverviews().
  *
- * This function will honour properly NODATA_VALUES tuples (special dataset metadata) so
- * that only a given RGB triplet (in case of a RGB image) will be considered as the
- * nodata value and not each value of the triplet independently per band.
+ * This function will honour properly NODATA_VALUES tuples (special dataset
+ * metadata) so that only a given RGB triplet (in case of a RGB image) will be
+ * considered as the nodata value and not each value of the triplet
+ * independently per band.
  *
  * @param hSrcBand the source (base level) band.
  * @param nOverviewCount the number of downsampled bands being generated.
@@ -2294,8 +2573,9 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
                          GDALProgressFunc pfnProgress, void * pProgressData )
 
 {
-    GDALRasterBand *poSrcBand = (GDALRasterBand *) hSrcBand;
-    GDALRasterBand **papoOvrBands = (GDALRasterBand **) pahOvrBands;
+    GDALRasterBand *poSrcBand = static_cast<GDALRasterBand *>( hSrcBand );
+    GDALRasterBand **papoOvrBands =
+        reinterpret_cast<GDALRasterBand **>( pahOvrBands );
 
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
@@ -2303,11 +2583,11 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
     if( EQUAL(pszResampling,"NONE") )
         return CE_None;
 
-    int nKernelRadius;
+    int nKernelRadius = 0;
     GDALResampleFunction pfnResampleFn
         = GDALGetResampleFunction(pszResampling, &nKernelRadius);
 
-    if (pfnResampleFn == NULL)
+    if( pfnResampleFn == NULL )
         return CE_Failure;
 
 /* -------------------------------------------------------------------- */
@@ -2315,20 +2595,21 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
     GDALColorTable* poColorTable = NULL;
 
-    if ((STARTS_WITH_CI(pszResampling, "AVER")
+    if( (STARTS_WITH_CI(pszResampling, "AVER")
          || STARTS_WITH_CI(pszResampling, "MODE")
          || STARTS_WITH_CI(pszResampling, "GAUSS")) &&
-        poSrcBand->GetColorInterpretation() == GCI_PaletteIndex)
+        poSrcBand->GetColorInterpretation() == GCI_PaletteIndex )
     {
         poColorTable = poSrcBand->GetColorTable();
-        if (poColorTable != NULL)
+        if( poColorTable != NULL )
         {
-            if (poColorTable->GetPaletteInterpretation() != GPI_RGB)
+            if( poColorTable->GetPaletteInterpretation() != GPI_RGB )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                        "Computing overviews on palette index raster bands "
-                        "with a palette whose color interpretation is not RGB "
-                        "will probably lead to unexpected results.");
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Computing overviews on palette index raster bands "
+                    "with a palette whose color interpretation is not RGB "
+                    "will probably lead to unexpected results." );
                 poColorTable = NULL;
             }
         }
@@ -2341,20 +2622,19 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
         }
     }
     // Not ready yet
-    else if( (EQUAL(pszResampling,"CUBIC") ||
-              EQUAL(pszResampling,"CUBICSPLINE") ||
-              EQUAL(pszResampling,"LANCZOS") ||
-              EQUAL(pszResampling,"BILINEAR") )
+    else if( (EQUAL(pszResampling, "CUBIC") ||
+              EQUAL(pszResampling, "CUBICSPLINE") ||
+              EQUAL(pszResampling, "LANCZOS") ||
+              EQUAL(pszResampling, "BILINEAR") )
         && poSrcBand->GetColorInterpretation() == GCI_PaletteIndex )
     {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                    "Computing %s overviews on palette index raster bands "
-                    "will probably lead to unexpected results.", pszResampling);
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Computing %s overviews on palette index raster bands "
+                  "will probably lead to unexpected results.", pszResampling );
     }
 
-
-    /* If we have a nodata mask and we are doing something more complicated */
-    /* than nearest neighbouring, we have to fetch to nodata mask */
+    // If we have a nodata mask and we are doing something more complicated
+    // than nearest neighbouring, we have to fetch to nodata mask.
 
     GDALRasterBand* poMaskBand = NULL;
     int nMaskFlags = 0;
@@ -2362,9 +2642,9 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 
     if( !STARTS_WITH_CI(pszResampling, "NEAR") )
     {
-        /* Special case if we are the alpha band. We want it to be considered */
-        /* as the mask band to avoid alpha=0 to be taken into account in average */
-        /* computation */
+        // Special case if we are the alpha band. We want it to be considered
+        // as the mask band to avoid alpha=0 to be taken into account in average
+        // computation.
         if( poSrcBand->GetColorInterpretation() == GCI_AlphaBand )
         {
             poMaskBand = poSrcBand;
@@ -2376,7 +2656,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
             nMaskFlags = poSrcBand->GetMaskFlags();
         }
 
-        bUseNoDataMask = ((nMaskFlags & GMF_ALL_VALID) == 0);
+        bUseNoDataMask = (nMaskFlags & GMF_ALL_VALID) == 0;
     }
 
 /* -------------------------------------------------------------------- */
@@ -2385,15 +2665,15 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 /*      amount of computation.                                          */
 /* -------------------------------------------------------------------- */
 
-    /* In case the mask made be computed from another band of the dataset, */
-    /* we can't use cascaded generation, as the computation of the overviews */
-    /* of the band used for the mask band may not have yet occurred (#3033) */
+    // In case the mask made be computed from another band of the dataset,
+    // we can't use cascaded generation, as the computation of the overviews
+    // of the band used for the mask band may not have yet occurred (#3033).
     if( (STARTS_WITH_CI(pszResampling, "AVER") |
          STARTS_WITH_CI(pszResampling, "GAUSS") ||
-         EQUAL(pszResampling,"CUBIC") ||
-         EQUAL(pszResampling,"CUBICSPLINE") ||
-         EQUAL(pszResampling,"LANCZOS") ||
-         EQUAL(pszResampling,"BILINEAR")) && nOverviewCount > 1
+         EQUAL(pszResampling, "CUBIC") ||
+         EQUAL(pszResampling, "CUBICSPLINE") ||
+         EQUAL(pszResampling, "LANCZOS") ||
+         EQUAL(pszResampling, "BILINEAR")) && nOverviewCount > 1
          && !(bUseNoDataMask && nMaskFlags != GMF_NODATA))
         return GDALRegenerateCascadingOverviews( poSrcBand,
                                                  nOverviewCount, papoOvrBands,
@@ -2404,39 +2684,46 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
 /*      Setup one horizontal swath to read from the raw buffer.         */
 /* -------------------------------------------------------------------- */
-    int nFRXBlockSize, nFRYBlockSize;
+    int nFRXBlockSize = 0;
+    int nFRYBlockSize = 0;
     poSrcBand->GetBlockSize( &nFRXBlockSize, &nFRYBlockSize );
 
-    int nFullResYChunk;
+    int nFullResYChunk = 0;
     if( nFRYBlockSize < 16 || nFRYBlockSize > 256 )
         nFullResYChunk = 64;
     else
         nFullResYChunk = nFRYBlockSize;
 
-    GDALDataType eType;
+    GDALDataType eType = GDT_Unknown;
     if( GDALDataTypeIsComplex( poSrcBand->GetRasterDataType() ) )
         eType = GDT_CFloat32;
     else
-        eType = GDALGetOvrWorkDataType(pszResampling, poSrcBand->GetRasterDataType());
+        eType = GDALGetOvrWorkDataType( pszResampling,
+                                        poSrcBand->GetRasterDataType() );
 
     const int nWidth = poSrcBand->GetXSize();
     const int nHeight = poSrcBand->GetYSize();
 
     int nMaxOvrFactor = 1;
-    for( int iOverview = 0; iOverview < nOverviewCount; iOverview ++ )
+    for( int iOverview = 0; iOverview < nOverviewCount; ++iOverview )
     {
         const int nDstWidth = papoOvrBands[iOverview]->GetXSize();
         const int nDstHeight = papoOvrBands[iOverview]->GetYSize();
-        nMaxOvrFactor = MAX( nMaxOvrFactor, (int)((double)nWidth / nDstWidth + 0.5) );
-        nMaxOvrFactor = MAX( nMaxOvrFactor, (int)((double)nHeight / nDstHeight + 0.5) );
+        nMaxOvrFactor = std::max(
+            nMaxOvrFactor,
+            static_cast<int>(static_cast<double>(nWidth) / nDstWidth + 0.5) );
+        nMaxOvrFactor = std::max(
+            nMaxOvrFactor,
+            static_cast<int>(static_cast<double>(nHeight) / nDstHeight + 0.5) );
     }
-    const int nMaxChunkYSizeQueried = nFullResYChunk + 2 * nKernelRadius * nMaxOvrFactor;
+    const int nMaxChunkYSizeQueried =
+        nFullResYChunk + 2 * nKernelRadius * nMaxOvrFactor;
 
     GByte *pabyChunkNodataMask = NULL;
     void *pChunk =
         VSI_MALLOC3_VERBOSE(
             GDALGetDataTypeSizeBytes(eType), nMaxChunkYSizeQueried, nWidth );
-    if (bUseNoDataMask)
+    if( bUseNoDataMask )
     {
         pabyChunkNodataMask =
             (GByte*) VSI_MALLOC2_VERBOSE( nMaxChunkYSizeQueried, nWidth );
@@ -2449,20 +2736,23 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
         return CE_Failure;
     }
 
-    int bHasNoData;
-    const float fNoDataValue = (float) poSrcBand->GetNoDataValue(&bHasNoData);
+    int bHasNoData = FALSE;
+    const float fNoDataValue =
+        static_cast<float>( poSrcBand->GetNoDataValue(&bHasNoData) );
+    const bool bPropagateNoData =
+        CPLTestBool( CPLGetConfigOption("GDAL_OVR_PROPAGATE_NODATA", "NO") );
 
 /* -------------------------------------------------------------------- */
 /*      Loop over image operating on chunks.                            */
 /* -------------------------------------------------------------------- */
-    int  nChunkYOff = 0;
+    int nChunkYOff = 0;
     CPLErr eErr = CE_None;
 
     for( nChunkYOff = 0;
          nChunkYOff < nHeight && eErr == CE_None;
          nChunkYOff += nFullResYChunk )
     {
-        if( !pfnProgress( nChunkYOff / (double) nHeight,
+        if( !pfnProgress( nChunkYOff / static_cast<double>( nHeight ),
                           NULL, pProgressData ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -2473,7 +2763,8 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
             nFullResYChunk = nHeight - nChunkYOff;
 
         int nChunkYOffQueried = nChunkYOff - nKernelRadius * nMaxOvrFactor;
-        int nChunkYSizeQueried = nFullResYChunk + 2 * nKernelRadius * nMaxOvrFactor;
+        int nChunkYSizeQueried =
+            nFullResYChunk + 2 * nKernelRadius * nMaxOvrFactor;
         if( nChunkYOffQueried < 0 )
         {
             nChunkYSizeQueried += nChunkYOffQueried;
@@ -2482,56 +2773,58 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
         if( nChunkYOffQueried + nChunkYSizeQueried > nHeight )
             nChunkYSizeQueried = nHeight - nChunkYOffQueried;
 
-        /* read chunk */
-        if (eErr == CE_None)
-            eErr = poSrcBand->RasterIO( GF_Read, 0, nChunkYOffQueried, nWidth, nChunkYSizeQueried,
-                                pChunk, nWidth, nChunkYSizeQueried, eType,
-                                0, 0, NULL );
-        if (eErr == CE_None && bUseNoDataMask)
-            eErr = poMaskBand->RasterIO( GF_Read, 0, nChunkYOffQueried, nWidth, nChunkYSizeQueried,
-                                pabyChunkNodataMask, nWidth, nChunkYSizeQueried, GDT_Byte,
-                                0, 0, NULL );
-
-        /* special case to promote 1bit data to 8bit 0/255 values */
-        if( EQUAL(pszResampling,"AVERAGE_BIT2GRAYSCALE") )
+        // Read chunk.
+        if( eErr == CE_None )
+            eErr = poSrcBand->RasterIO(
+                GF_Read, 0, nChunkYOffQueried, nWidth, nChunkYSizeQueried,
+                pChunk, nWidth, nChunkYSizeQueried, eType,
+                0, 0, NULL );
+        if( eErr == CE_None && bUseNoDataMask )
+            eErr = poMaskBand->RasterIO(
+                GF_Read, 0, nChunkYOffQueried, nWidth, nChunkYSizeQueried,
+                pabyChunkNodataMask, nWidth, nChunkYSizeQueried, GDT_Byte,
+                0, 0, NULL );
+
+        // Special case to promote 1bit data to 8bit 0/255 values.
+        if( EQUAL(pszResampling, "AVERAGE_BIT2GRAYSCALE") )
         {
-            if (eType == GDT_Float32)
+            if( eType == GDT_Float32 )
             {
-                float* pafChunk = (float*)pChunk;
-                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                float* pafChunk = static_cast<float*>(pChunk);
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; --i )
                 {
                     if( pafChunk[i] == 1.0 )
                         pafChunk[i] = 255.0;
                 }
             }
-            else if (eType == GDT_Byte)
+            else if( eType == GDT_Byte )
             {
-                GByte* pabyChunk = (GByte*)pChunk;
-                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+              GByte* pabyChunk = static_cast<GByte*>(pChunk);
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; --i )
                 {
                     if( pabyChunk[i] == 1 )
                         pabyChunk[i] = 255;
                 }
             }
-            else if (eType == GDT_UInt16)
+            else if( eType == GDT_UInt16 )
             {
-                GUInt16* pasChunk = (GUInt16*)pChunk;
-                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                GUInt16* pasChunk = static_cast<GUInt16*>(pChunk);
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; --i )
                 {
                     if( pasChunk[i] == 1 )
                         pasChunk[i] = 255;
                 }
             }
             else {
-                CPLAssert(0);
+                CPLAssert(false);
             }
         }
-        else if( EQUAL(pszResampling,"AVERAGE_BIT2GRAYSCALE_MINISWHITE") )
+        else if( EQUAL(pszResampling, "AVERAGE_BIT2GRAYSCALE_MINISWHITE") )
         {
-            if (eType == GDT_Float32)
+            if( eType == GDT_Float32 )
             {
-                float* pafChunk = (float*)pChunk;
-                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                float* pafChunk = static_cast<float*>(pChunk);
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; --i )
                 {
                     if( pafChunk[i] == 1.0 )
                         pafChunk[i] = 0.0;
@@ -2539,10 +2832,10 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
                         pafChunk[i] = 255.0;
                 }
             }
-            else if (eType == GDT_Byte)
+            else if( eType == GDT_Byte )
             {
-                GByte* pabyChunk = (GByte*)pChunk;
-                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                GByte* pabyChunk = static_cast<GByte*>(pChunk);
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; --i )
                 {
                     if( pabyChunk[i] == 1 )
                         pabyChunk[i] = 0;
@@ -2550,10 +2843,10 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
                         pabyChunk[i] = 255;
                 }
             }
-            else if (eType == GDT_UInt16)
+            else if( eType == GDT_UInt16 )
             {
-                GUInt16* pasChunk = (GUInt16*)pChunk;
-                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; i-- )
+                GUInt16* pasChunk = static_cast<GUInt16*>(pChunk);
+                for( int i = nChunkYSizeQueried*nWidth - 1; i >= 0; --i )
                 {
                     if( pasChunk[i] == 1 )
                         pasChunk[i] = 0;
@@ -2562,17 +2855,21 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
                 }
             }
             else {
-                CPLAssert(0);
+                CPLAssert(false);
             }
         }
 
-        for( int iOverview = 0; iOverview < nOverviewCount && eErr == CE_None; iOverview++ )
+        for( int iOverview = 0;
+             iOverview < nOverviewCount && eErr == CE_None;
+             ++iOverview )
         {
             const int nDstWidth = papoOvrBands[iOverview]->GetXSize();
             const int nDstHeight = papoOvrBands[iOverview]->GetYSize();
 
-            const double dfXRatioDstToSrc = (double)nWidth / nDstWidth;
-            const double dfYRatioDstToSrc = (double)nHeight / nDstHeight;
+            const double dfXRatioDstToSrc =
+                static_cast<double>(nWidth) / nDstWidth;
+            const double dfYRatioDstToSrc =
+                static_cast<double>(nHeight) / nDstHeight;
 
 /* -------------------------------------------------------------------- */
 /*      Figure out the line to start writing to, and the first line     */
@@ -2580,33 +2877,41 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 /*      every output line will be written if all input chunks are       */
 /*      processed.                                                      */
 /* -------------------------------------------------------------------- */
-            int nDstYOff = (int) (0.5 + nChunkYOff/dfYRatioDstToSrc);
-            int nDstYOff2 = (int)
-                (0.5 + (nChunkYOff+nFullResYChunk)/dfYRatioDstToSrc);
+            int nDstYOff = static_cast<int>(0.5 + nChunkYOff/dfYRatioDstToSrc);
+            int nDstYOff2 = static_cast<int>(
+                0.5 + (nChunkYOff+nFullResYChunk)/dfYRatioDstToSrc);
 
             if( nChunkYOff + nFullResYChunk == nHeight )
                 nDstYOff2 = nDstHeight;
-            //CPLDebug("GDAL", "nDstYOff=%d, nDstYOff2=%d", nDstYOff, nDstYOff2);
-
-            if( eType == GDT_Byte || eType == GDT_UInt16 || eType == GDT_Float32 )
-                eErr = pfnResampleFn(dfXRatioDstToSrc, dfYRatioDstToSrc,
-                                       0.0, 0.0,
-                                              eType,
-                                              pChunk,
-                                              pabyChunkNodataMask,
-                                              0, nWidth,
-                                              nChunkYOffQueried, nChunkYSizeQueried,
-                                              0, nDstWidth,
-                                              nDstYOff, nDstYOff2,
-                                              papoOvrBands[iOverview], pszResampling,
-                                              bHasNoData, fNoDataValue, poColorTable,
-                                              poSrcBand->GetRasterDataType());
+#if DEBUG_VERBOSE
+            CPLDebug( "GDAL",
+                      "nDstYOff=%d, nDstYOff2=%d", nDstYOff, nDstYOff2 );
+#endif
+
+            if( eType == GDT_Byte ||
+                eType == GDT_UInt16 ||
+                eType == GDT_Float32 )
+                eErr = pfnResampleFn(
+                    dfXRatioDstToSrc, dfYRatioDstToSrc,
+                    0.0, 0.0,
+                    eType,
+                    pChunk,
+                    pabyChunkNodataMask,
+                    0, nWidth,
+                    nChunkYOffQueried, nChunkYSizeQueried,
+                    0, nDstWidth,
+                    nDstYOff, nDstYOff2,
+                    papoOvrBands[iOverview], pszResampling,
+                    bHasNoData, fNoDataValue, poColorTable,
+                    poSrcBand->GetRasterDataType(),
+                    bPropagateNoData);
             else
-                eErr = GDALResampleChunkC32R(nWidth, nHeight,
-                                               (float*)pChunk,
-                                               nChunkYOffQueried, nChunkYSizeQueried,
-                                               nDstYOff, nDstYOff2,
-                                               papoOvrBands[iOverview], pszResampling);
+                eErr = GDALResampleChunkC32R(
+                    nWidth, nHeight,
+                    static_cast<float*>(pChunk),
+                    nChunkYOffQueried, nChunkYSizeQueried,
+                    nDstYOff, nDstYOff2,
+                    papoOvrBands[iOverview], pszResampling);
         }
     }
 
@@ -2618,10 +2923,11 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
     if( eErr == CE_None && EQUAL(pszResampling,"AVERAGE_MP") )
     {
-        GDALOverviewMagnitudeCorrection( (GDALRasterBandH) poSrcBand,
-                                         nOverviewCount,
-                                         (GDALRasterBandH *) papoOvrBands,
-                                         GDALDummyProgress, NULL );
+        GDALOverviewMagnitudeCorrection(
+            poSrcBand,
+            nOverviewCount,
+            reinterpret_cast<GDALRasterBandH *>( papoOvrBands ),
+            GDALDummyProgress, NULL );
     }
 
 /* -------------------------------------------------------------------- */
@@ -2629,19 +2935,17 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
     for( int iOverview = 0;
          eErr == CE_None && iOverview < nOverviewCount;
-         iOverview++ )
+         ++iOverview )
     {
         eErr = papoOvrBands[iOverview]->FlushCache();
     }
 
-    if (eErr == CE_None)
+    if( eErr == CE_None )
         pfnProgress( 1.0, NULL, pProgressData );
 
     return eErr;
 }
 
-
-
 /************************************************************************/
 /*            GDALRegenerateOverviewsMultiBand()                        */
 /************************************************************************/
@@ -2651,7 +2955,7 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
  * compressed pixel-interleaved overviews (JPEG-IN-TIFF for example)
  *
  * This function will generate one or more overview images from a base
- * image using the requested downsampling algorithm.  It's primary use
+ * image using the requested downsampling algorithm.  Its primary use
  * is for generating overviews via GDALDataset::BuildOverviews(), but it
  * can also be used to generate downsampled images in one file from another
  * outside the overview architecture.
@@ -2669,16 +2973,18 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
  *               read the source data of size deltax * deltay for all the bands
  *               generate the corresponding overview block for all the bands
  *
- * This function will honour properly NODATA_VALUES tuples (special dataset metadata) so
- * that only a given RGB triplet (in case of a RGB image) will be considered as the
- * nodata value and not each value of the triplet independently per band.
+ * This function will honour properly NODATA_VALUES tuples (special dataset
+ * metadata) so that only a given RGB triplet (in case of a RGB image) will be
+ * considered as the nodata value and not each value of the triplet
+ * independently per band.
  *
  * @param nBands the number of bands, size of papoSrcBands and size of
  *               first dimension of papapoOverviewBands
  * @param papoSrcBands the list of source bands to downsample
  * @param nOverviews the number of downsampled overview levels being generated.
- * @param papapoOverviewBands bidimension array of bands. First dimension is indexed
- *                            by nBands. Second dimension is indexed by nOverviews.
+ * @param papapoOverviewBands bidimension array of bands. First dimension is
+ *                            indexed by nBands. Second dimension is indexed by
+ *                            nOverviews.
  * @param pszResampling Resampling algorithm ("NEAREST", "AVERAGE" or "GAUSS").
  * @param pfnProgress progress report function.
  * @param pProgressData progress function callback data.
@@ -2686,11 +2992,12 @@ GDALRegenerateOverviews( GDALRasterBandH hSrcBand,
  */
 
 CPLErr
-GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
-                                 int nOverviews,
-                                 GDALRasterBand*** papapoOverviewBands,
-                                 const char * pszResampling,
-                                 GDALProgressFunc pfnProgress, void * pProgressData )
+GDALRegenerateOverviewsMultiBand( int nBands, GDALRasterBand** papoSrcBands,
+                                  int nOverviews,
+                                  GDALRasterBand*** papapoOverviewBands,
+                                  const char * pszResampling,
+                                  GDALProgressFunc pfnProgress,
+                                  void * pProgressData )
 {
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
@@ -2698,99 +3005,117 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
     if( EQUAL(pszResampling,"NONE") )
         return CE_None;
 
-    /* Sanity checks */
-    if (!STARTS_WITH_CI(pszResampling, "NEAR") &&
+    // Sanity checks.
+    if( !STARTS_WITH_CI(pszResampling, "NEAR") &&
         !EQUAL(pszResampling, "AVERAGE") &&
         !EQUAL(pszResampling, "GAUSS") &&
         !EQUAL(pszResampling, "CUBIC") &&
-        !EQUAL(pszResampling,"CUBICSPLINE") &&
-        !EQUAL(pszResampling,"LANCZOS") &&
-        !EQUAL(pszResampling,"BILINEAR"))
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "GDALRegenerateOverviewsMultiBand: pszResampling='%s' not supported", pszResampling);
+        !EQUAL(pszResampling, "CUBICSPLINE") &&
+        !EQUAL(pszResampling, "LANCZOS") &&
+        !EQUAL(pszResampling, "BILINEAR") )
+    {
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "GDALRegenerateOverviewsMultiBand: pszResampling='%s' "
+            "not supported", pszResampling );
         return CE_Failure;
     }
 
-    int nKernelRadius;
-    GDALResampleFunction pfnResampleFn = GDALGetResampleFunction(pszResampling,
-                                                                       &nKernelRadius);
-    if (pfnResampleFn == NULL)
+    int nKernelRadius = 0;
+    GDALResampleFunction pfnResampleFn =
+        GDALGetResampleFunction(pszResampling, &nKernelRadius);
+    if( pfnResampleFn == NULL )
         return CE_Failure;
 
     int nSrcWidth = papoSrcBands[0]->GetXSize();
     int nSrcHeight = papoSrcBands[0]->GetYSize();
     GDALDataType eDataType = papoSrcBands[0]->GetRasterDataType();
-    for(int iBand=1;iBand<nBands;iBand++)
+    for( int iBand = 1; iBand < nBands; ++iBand )
     {
-        if (papoSrcBands[iBand]->GetXSize() != nSrcWidth ||
-            papoSrcBands[iBand]->GetYSize() != nSrcHeight)
+        if( papoSrcBands[iBand]->GetXSize() != nSrcWidth ||
+            papoSrcBands[iBand]->GetYSize() != nSrcHeight )
         {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                    "GDALRegenerateOverviewsMultiBand: all the source bands must have the same dimensions");
+            CPLError(
+                CE_Failure, CPLE_NotSupported,
+                "GDALRegenerateOverviewsMultiBand: all the source bands must "
+                "have the same dimensions" );
             return CE_Failure;
         }
-        if (papoSrcBands[iBand]->GetRasterDataType() != eDataType)
+        if( papoSrcBands[iBand]->GetRasterDataType() != eDataType )
         {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                    "GDALRegenerateOverviewsMultiBand: all the source bands must have the same data type");
+            CPLError(
+                CE_Failure, CPLE_NotSupported,
+                "GDALRegenerateOverviewsMultiBand: all the source bands must "
+                "have the same data type" );
             return CE_Failure;
         }
     }
 
-    for(int iOverview=0;iOverview<nOverviews;iOverview++)
+    for( int iOverview = 0; iOverview < nOverviews; ++iOverview )
     {
-        int nDstWidth = papapoOverviewBands[0][iOverview]->GetXSize();
-        int nDstHeight = papapoOverviewBands[0][iOverview]->GetYSize();
-        for(int iBand=1;iBand<nBands;iBand++)
+        const int nDstWidth = papapoOverviewBands[0][iOverview]->GetXSize();
+        const int nDstHeight = papapoOverviewBands[0][iOverview]->GetYSize();
+        for( int iBand = 1; iBand < nBands; ++iBand )
         {
-            if (papapoOverviewBands[iBand][iOverview]->GetXSize() != nDstWidth ||
-                papapoOverviewBands[iBand][iOverview]->GetYSize() != nDstHeight)
+            if( papapoOverviewBands[iBand][iOverview]->GetXSize() !=
+                nDstWidth ||
+                papapoOverviewBands[iBand][iOverview]->GetYSize()
+                != nDstHeight )
             {
-                CPLError(CE_Failure, CPLE_NotSupported,
-                        "GDALRegenerateOverviewsMultiBand: all the overviews bands of the same level must have the same dimensions");
+                CPLError(
+                    CE_Failure, CPLE_NotSupported,
+                    "GDALRegenerateOverviewsMultiBand: all the overviews bands "
+                    "of the same level must have the same dimensions" );
                 return CE_Failure;
             }
-            if (papapoOverviewBands[iBand][iOverview]->GetRasterDataType() != eDataType)
+            if( papapoOverviewBands[iBand][iOverview]->GetRasterDataType() !=
+                eDataType )
             {
-                CPLError(CE_Failure, CPLE_NotSupported,
-                        "GDALRegenerateOverviewsMultiBand: all the overviews bands must have the same data type as the source bands");
+                CPLError(
+                    CE_Failure, CPLE_NotSupported,
+                    "GDALRegenerateOverviewsMultiBand: all the overviews bands "
+                    "must have the same data type as the source bands" );
                 return CE_Failure;
             }
         }
     }
 
-    /* First pass to compute the total number of pixels to read */
+    // First pass to compute the total number of pixels to read.
     double dfTotalPixelCount = 0;
-    for(int iOverview=0;iOverview<nOverviews;iOverview++)
+    for( int iOverview = 0; iOverview < nOverviews; ++iOverview )
     {
         nSrcWidth = papoSrcBands[0]->GetXSize();
         nSrcHeight = papoSrcBands[0]->GetYSize();
 
-        int nDstWidth = papapoOverviewBands[0][iOverview]->GetXSize();
-        /* Try to use previous level of overview as the source to compute */
-        /* the next level */
-        if (iOverview > 0 && papapoOverviewBands[0][iOverview - 1]->GetXSize() > nDstWidth)
+        const int nDstWidth = papapoOverviewBands[0][iOverview]->GetXSize();
+        // Try to use previous level of overview as the source to compute
+        // the next level.
+        if( iOverview > 0 &&
+            papapoOverviewBands[0][iOverview - 1]->GetXSize() > nDstWidth )
         {
             nSrcWidth = papapoOverviewBands[0][iOverview - 1]->GetXSize();
             nSrcHeight = papapoOverviewBands[0][iOverview - 1]->GetYSize();
         }
 
-        dfTotalPixelCount += (double)nSrcWidth * nSrcHeight;
+        dfTotalPixelCount += static_cast<double>(nSrcWidth) * nSrcHeight;
     }
 
     nSrcWidth = papoSrcBands[0]->GetXSize();
     nSrcHeight = papoSrcBands[0]->GetYSize();
 
-    GDALDataType eWrkDataType = GDALGetOvrWorkDataType(pszResampling, eDataType);
+    GDALDataType eWrkDataType =
+        GDALGetOvrWorkDataType(pszResampling, eDataType);
 
-    /* If we have a nodata mask and we are doing something more complicated */
-    /* than nearest neighbouring, we have to fetch to nodata mask */
-    bool bUseNoDataMask = (!STARTS_WITH_CI(pszResampling, "NEAR") &&
-                          (papoSrcBands[0]->GetMaskFlags() & GMF_ALL_VALID) == 0);
+    // If we have a nodata mask and we are doing something more complicated
+    // than nearest neighbouring, we have to fetch to nodata mask.
+    const bool bUseNoDataMask =
+        !STARTS_WITH_CI(pszResampling, "NEAR") &&
+        (papoSrcBands[0]->GetMaskFlags() & GMF_ALL_VALID) == 0;
 
-    int* pabHasNoData = (int*)VSI_MALLOC_VERBOSE(nBands * sizeof(int));
-    float* pafNoDataValue = (float*)VSI_MALLOC_VERBOSE(nBands * sizeof(float));
+    int* const pabHasNoData = static_cast<int *>(
+        VSI_MALLOC_VERBOSE(nBands * sizeof(int)) );
+    float* const pafNoDataValue = static_cast<float *>(
+        VSI_MALLOC_VERBOSE(nBands * sizeof(float)) );
     if( pabHasNoData == NULL || pafNoDataValue == NULL )
     {
         CPLFree(pabHasNoData);
@@ -2798,49 +3123,64 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
         return CE_Failure;
     }
 
-    for(int iBand=0;iBand<nBands;iBand++)
+    for( int iBand = 0; iBand < nBands; ++iBand )
     {
         pabHasNoData[iBand] = FALSE;
-        pafNoDataValue[iBand] = (float) papoSrcBands[iBand]->GetNoDataValue(&pabHasNoData[iBand]);
+        pafNoDataValue[iBand] = static_cast<float>(
+            papoSrcBands[iBand]->GetNoDataValue(&pabHasNoData[iBand]) );
     }
+    const bool bPropagateNoData =
+        CPLTestBool( CPLGetConfigOption("GDAL_OVR_PROPAGATE_NODATA", "NO") );
 
-    /* Second pass to do the real job ! */
+    // Second pass to do the real job.
     double dfCurPixelCount = 0;
     CPLErr eErr = CE_None;
-    for(int iOverview=0;iOverview<nOverviews && eErr == CE_None;iOverview++)
+    for( int iOverview = 0;
+         iOverview < nOverviews && eErr == CE_None;
+         ++iOverview )
     {
-        int iSrcOverview = -1; /* -1 means the source bands */
+        int iSrcOverview = -1;  // -1 means the source bands.
+
+        int nDstBlockXSize = 0;
+        int nDstBlockYSize = 0;
+        papapoOverviewBands[0][iOverview]->GetBlockSize( &nDstBlockXSize,
+                                                         &nDstBlockYSize );
 
-        int nDstBlockXSize, nDstBlockYSize;
-        int nDstWidth, nDstHeight;
-        papapoOverviewBands[0][iOverview]->GetBlockSize(&nDstBlockXSize, &nDstBlockYSize);
-        nDstWidth = papapoOverviewBands[0][iOverview]->GetXSize();
-        nDstHeight = papapoOverviewBands[0][iOverview]->GetYSize();
+        const int nDstWidth = papapoOverviewBands[0][iOverview]->GetXSize();
+        const int nDstHeight = papapoOverviewBands[0][iOverview]->GetYSize();
 
-        /* Try to use previous level of overview as the source to compute */
-        /* the next level */
-        if (iOverview > 0 && papapoOverviewBands[0][iOverview - 1]->GetXSize() > nDstWidth)
+        // Try to use previous level of overview as the source to compute
+        // the next level.
+        if( iOverview > 0 &&
+            papapoOverviewBands[0][iOverview - 1]->GetXSize() > nDstWidth )
         {
             nSrcWidth = papapoOverviewBands[0][iOverview - 1]->GetXSize();
             nSrcHeight = papapoOverviewBands[0][iOverview - 1]->GetYSize();
             iSrcOverview = iOverview - 1;
         }
 
-        double dfXRatioDstToSrc = (double)nSrcWidth / nDstWidth;
-        double dfYRatioDstToSrc = (double)nSrcHeight / nDstHeight;
+        const double dfXRatioDstToSrc =
+            static_cast<double>(nSrcWidth) / nDstWidth;
+        const double dfYRatioDstToSrc =
+            static_cast<double>(nSrcHeight) / nDstHeight;
 
         // Compute the maximum chunk size of the source such as it will match
         // the size of a block of the overview.
-        int nFullResXChunk = 1 + (int)(nDstBlockXSize * dfXRatioDstToSrc);
-        int nFullResYChunk = 1 + (int)(nDstBlockYSize * dfYRatioDstToSrc);
+        const int nFullResXChunk =
+            1 + static_cast<int>(nDstBlockXSize * dfXRatioDstToSrc);
+        const int nFullResYChunk =
+            1 + static_cast<int>(nDstBlockYSize * dfYRatioDstToSrc);
 
-        int nOvrFactor = MAX( (int)(0.5 + dfXRatioDstToSrc),
-                              (int)(0.5 + dfYRatioDstToSrc) );
+        int nOvrFactor = std::max( static_cast<int>(0.5 + dfXRatioDstToSrc),
+                                   static_cast<int>(0.5 + dfYRatioDstToSrc) );
         if( nOvrFactor == 0 ) nOvrFactor = 1;
-        int nFullResXChunkQueried = nFullResXChunk + 2 * nKernelRadius * nOvrFactor;
-        int nFullResYChunkQueried = nFullResYChunk + 2 * nKernelRadius * nOvrFactor;
+        const int nFullResXChunkQueried =
+            nFullResXChunk + 2 * nKernelRadius * nOvrFactor;
+        const int nFullResYChunkQueried =
+            nFullResYChunk + 2 * nKernelRadius * nOvrFactor;
 
-        void** papaChunk = (void**) VSI_MALLOC_VERBOSE(nBands * sizeof(void*));
+        void** papaChunk = static_cast<void **>(
+            VSI_MALLOC_VERBOSE(nBands * sizeof(void*)) );
         if( papaChunk == NULL )
         {
             CPLFree(pabHasNoData);
@@ -2848,7 +3188,7 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
             return CE_Failure;
         }
         GByte* pabyChunkNoDataMask = NULL;
-        for(int iBand=0;iBand<nBands;iBand++)
+        for( int iBand = 0; iBand < nBands; ++iBand )
         {
             papaChunk[iBand] = VSI_MALLOC3_VERBOSE(
                 nFullResXChunkQueried,
@@ -2864,12 +3204,14 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                 return CE_Failure;
             }
         }
-        if (bUseNoDataMask)
+        if( bUseNoDataMask )
         {
-            pabyChunkNoDataMask = (GByte*) VSI_MALLOC2_VERBOSE(nFullResXChunkQueried, nFullResYChunkQueried);
+            pabyChunkNoDataMask = static_cast<GByte *>(
+                VSI_MALLOC2_VERBOSE( nFullResXChunkQueried,
+                                     nFullResYChunkQueried ) );
             if( pabyChunkNoDataMask == NULL )
             {
-                for(int iBand=0;iBand<nBands;iBand++)
+                for( int iBand = 0; iBand < nBands; ++iBand )
                 {
                     CPLFree(papaChunk[iBand]);
                 }
@@ -2880,18 +3222,23 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
             }
         }
 
-        int nDstYOff;
-        /* Iterate on destination overview, block by block */
-        for( nDstYOff = 0; nDstYOff < nDstHeight && eErr == CE_None; nDstYOff += nDstBlockYSize )
+        int nDstYOff = 0;
+        // Iterate on destination overview, block by block.
+        for( nDstYOff = 0;
+             nDstYOff < nDstHeight && eErr == CE_None;
+             nDstYOff += nDstBlockYSize )
         {
             int nDstYCount;
-            if  (nDstYOff + nDstBlockYSize <= nDstHeight)
+            if( nDstYOff + nDstBlockYSize <= nDstHeight )
                 nDstYCount = nDstBlockYSize;
             else
                 nDstYCount = nDstHeight - nDstYOff;
 
-            int nChunkYOff = (int) (0.5 + nDstYOff * dfYRatioDstToSrc);
-            int nChunkYOff2 = (int) (0.5 + (nDstYOff + nDstYCount) * dfYRatioDstToSrc);
+            int nChunkYOff =
+                static_cast<int>(0.5 + nDstYOff * dfYRatioDstToSrc);
+            int nChunkYOff2 =
+                static_cast<int>(
+                    0.5 + (nDstYOff + nDstYCount) * dfYRatioDstToSrc );
             if( nChunkYOff2 > nSrcHeight || nDstYOff + nDstYCount == nDstHeight)
                 nChunkYOff2 = nSrcHeight;
             int nYCount = nChunkYOff2 - nChunkYOff;
@@ -2915,25 +3262,32 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                 eErr = CE_Failure;
             }
 
-            int nDstXOff;
-            /* Iterate on destination overview, block by block */
-            for( nDstXOff = 0; nDstXOff < nDstWidth && eErr == CE_None; nDstXOff += nDstBlockXSize )
+            int nDstXOff = 0;
+            // Iterate on destination overview, block by block.
+            for( nDstXOff = 0;
+                 nDstXOff < nDstWidth && eErr == CE_None;
+                 nDstXOff += nDstBlockXSize )
             {
-                int nDstXCount;
-                if  (nDstXOff + nDstBlockXSize <= nDstWidth)
+                int nDstXCount = 0;
+                if( nDstXOff + nDstBlockXSize <= nDstWidth )
                     nDstXCount = nDstBlockXSize;
                 else
                     nDstXCount = nDstWidth - nDstXOff;
 
-                int nChunkXOff = (int) (0.5 + nDstXOff * dfXRatioDstToSrc);
-                int nChunkXOff2 = (int) (0.5 + (nDstXOff + nDstXCount) * dfXRatioDstToSrc);
-                if( nChunkXOff2 > nSrcWidth || nDstXOff + nDstXCount == nDstWidth)
+                int nChunkXOff =
+                    static_cast<int>(0.5 + nDstXOff * dfXRatioDstToSrc);
+                int nChunkXOff2 =
+                    static_cast<int>(
+                        0.5 + (nDstXOff + nDstXCount) * dfXRatioDstToSrc );
+                if( nChunkXOff2 > nSrcWidth ||
+                    nDstXOff + nDstXCount == nDstWidth )
                     nChunkXOff2 = nSrcWidth;
-                int nXCount = nChunkXOff2 - nChunkXOff;
+                const int nXCount = nChunkXOff2 - nChunkXOff;
                 CPLAssert(nXCount <= nFullResXChunk);
 
                 int nChunkXOffQueried = nChunkXOff - nKernelRadius * nOvrFactor;
-                int nChunkXSizeQueried = nXCount + 2 * nKernelRadius * nOvrFactor;
+                int nChunkXSizeQueried =
+                    nXCount + 2 * nKernelRadius * nOvrFactor;
                 if( nChunkXOffQueried < 0 )
                 {
                     nChunkXSizeQueried += nChunkXOffQueried;
@@ -2942,90 +3296,105 @@ GDALRegenerateOverviewsMultiBand(int nBands, GDALRasterBand** papoSrcBands,
                 if( nChunkXSizeQueried + nChunkXOffQueried > nSrcWidth )
                     nChunkXSizeQueried = nSrcWidth - nChunkXOffQueried;
                 CPLAssert(nChunkXSizeQueried <= nFullResXChunkQueried);
-                /*CPLDebug("GDAL", "Reading (%dx%d -> %dx%d) for output (%dx%d -> %dx%d)",
-                         nChunkXOff, nChunkYOff, nXCount, nYCount,
-                         nDstXOff, nDstYOff, nDstXCount, nDstYCount);*/
+#if DEBUG_VERBOSE
+                CPLDebug(
+                    "GDAL",
+                    "Reading (%dx%d -> %dx%d) for output (%dx%d -> %dx%d)",
+                    nChunkXOff, nChunkYOff, nXCount, nYCount,
+                    nDstXOff, nDstYOff, nDstXCount, nDstYCount );
+#endif
 
-                /* Read the source buffers for all the bands */
-                for(int iBand=0;iBand<nBands && eErr == CE_None;iBand++)
+                // Read the source buffers for all the bands.
+                for( int iBand = 0; iBand < nBands && eErr == CE_None; ++iBand )
                 {
-                    GDALRasterBand* poSrcBand;
-                    if (iSrcOverview == -1)
+                    GDALRasterBand* poSrcBand = NULL;
+                    if( iSrcOverview == -1 )
                         poSrcBand = papoSrcBands[iBand];
                     else
                         poSrcBand = papapoOverviewBands[iBand][iSrcOverview];
-                    eErr = poSrcBand->RasterIO( GF_Read,
-                                                nChunkXOffQueried, nChunkYOffQueried,
-                                                nChunkXSizeQueried, nChunkYSizeQueried,
-                                                papaChunk[iBand],
-                                                nChunkXSizeQueried, nChunkYSizeQueried,
-                                                eWrkDataType, 0, 0, NULL );
+                    eErr = poSrcBand->RasterIO(
+                        GF_Read,
+                        nChunkXOffQueried, nChunkYOffQueried,
+                        nChunkXSizeQueried, nChunkYSizeQueried,
+                        papaChunk[iBand],
+                        nChunkXSizeQueried, nChunkYSizeQueried,
+                        eWrkDataType, 0, 0, NULL );
                 }
 
-                if (bUseNoDataMask && eErr == CE_None)
+                if( bUseNoDataMask && eErr == CE_None )
                 {
-                    GDALRasterBand* poSrcBand;
-                    if (iSrcOverview == -1)
+                    GDALRasterBand* poSrcBand = NULL;
+                    if( iSrcOverview == -1 )
                         poSrcBand = papoSrcBands[0];
                     else
                         poSrcBand = papapoOverviewBands[0][iSrcOverview];
-                    eErr = poSrcBand->GetMaskBand()->RasterIO( GF_Read,
-                                                               nChunkXOffQueried, nChunkYOffQueried,
-                                                               nChunkXSizeQueried, nChunkYSizeQueried,
-                                                               pabyChunkNoDataMask,
-                                                               nChunkXSizeQueried, nChunkYSizeQueried,
-                                                               GDT_Byte, 0, 0, NULL );
+                    eErr = poSrcBand->GetMaskBand()->RasterIO(
+                        GF_Read,
+                        nChunkXOffQueried, nChunkYOffQueried,
+                        nChunkXSizeQueried, nChunkYSizeQueried,
+                        pabyChunkNoDataMask,
+                        nChunkXSizeQueried, nChunkYSizeQueried,
+                        GDT_Byte, 0, 0, NULL );
                 }
 
-                /* Compute the resulting overview block */
-                for(int iBand=0;iBand<nBands && eErr == CE_None;iBand++)
+                // Compute the resulting overview block.
+                for( int iBand = 0; iBand < nBands && eErr == CE_None; ++iBand )
                 {
-                    eErr = pfnResampleFn(   dfXRatioDstToSrc, dfYRatioDstToSrc,
-                                            0.0, 0.0,
-                                            eWrkDataType,
-                                            papaChunk[iBand],
-                                            pabyChunkNoDataMask,
-                                            nChunkXOffQueried, nChunkXSizeQueried,
-                                            nChunkYOffQueried, nChunkYSizeQueried,
-                                            nDstXOff, nDstXOff + nDstXCount,
-                                            nDstYOff, nDstYOff + nDstYCount,
-                                            papapoOverviewBands[iBand][iOverview],
-                                            pszResampling,
-                                            pabHasNoData[iBand],
-                                            pafNoDataValue[iBand],
-                                            /*poColorTable*/ NULL,
-                                            eDataType);
+                    eErr = pfnResampleFn(
+                        dfXRatioDstToSrc, dfYRatioDstToSrc,
+                        0.0, 0.0,
+                        eWrkDataType,
+                        papaChunk[iBand],
+                        pabyChunkNoDataMask,
+                        nChunkXOffQueried, nChunkXSizeQueried,
+                        nChunkYOffQueried, nChunkYSizeQueried,
+                        nDstXOff, nDstXOff + nDstXCount,
+                        nDstYOff, nDstYOff + nDstYCount,
+                        papapoOverviewBands[iBand][iOverview],
+                        pszResampling,
+                        pabHasNoData[iBand],
+                        pafNoDataValue[iBand],
+                        /*poColorTable*/ NULL,
+                        eDataType,
+                        bPropagateNoData);
                 }
             }
 
-            dfCurPixelCount += (double)nYCount * nSrcWidth;
+            dfCurPixelCount += static_cast<double>(nYCount) * nSrcWidth;
         }
 
-        /* Flush the data to overviews */
-        for(int iBand=0;iBand<nBands;iBand++)
+        // Flush the data to overviews.
+        for( int iBand = 0; iBand < nBands; ++iBand )
         {
             CPLFree(papaChunk[iBand]);
             papapoOverviewBands[iBand][iOverview]->FlushCache();
         }
         CPLFree(papaChunk);
         CPLFree(pabyChunkNoDataMask);
-
     }
 
     CPLFree(pabHasNoData);
     CPLFree(pafNoDataValue);
 
-    if (eErr == CE_None)
+    if( eErr == CE_None )
         pfnProgress( 1.0, NULL, pProgressData );
 
     return eErr;
 }
 
-
 /************************************************************************/
 /*                        GDALComputeBandStats()                        */
 /************************************************************************/
 
+/** Undocumented
+ * @param hSrcBand undocumented.
+ * @param nSampleStep undocumented.
+ * @param pdfMean undocumented.
+ * @param pdfStdDev undocumented.
+ * @param pfnProgress undocumented.
+ * @param pProgressData undocumented.
+ * @return undocumented
+ */
 CPLErr CPL_STDCALL
 GDALComputeBandStats( GDALRasterBandH hSrcBand,
                       int nSampleStep,
@@ -3036,7 +3405,7 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
 {
     VALIDATE_POINTER1( hSrcBand, "GDALComputeBandStats", CE_Failure );
 
-    GDALRasterBand *poSrcBand = (GDALRasterBand *) hSrcBand;
+    GDALRasterBand *poSrcBand = static_cast<GDALRasterBand *>( hSrcBand );
 
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
@@ -3047,18 +3416,20 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
     if( nSampleStep >= nHeight || nSampleStep < 1 )
         nSampleStep = 1;
 
-    GDALDataType eWrkType;
-    float *pafData;
+    GDALDataType eWrkType = GDT_Unknown;
+    float *pafData = NULL;
     GDALDataType eType = poSrcBand->GetRasterDataType();
     const bool bComplex = CPL_TO_BOOL(GDALDataTypeIsComplex(eType));
     if( bComplex )
     {
-        pafData = (float *) VSI_MALLOC_VERBOSE(nWidth * 2 * sizeof(float));
+        pafData = static_cast<float *>(
+            VSI_MALLOC_VERBOSE(nWidth * 2 * sizeof(float)) );
         eWrkType = GDT_CFloat32;
     }
     else
     {
-        pafData = (float *) VSI_MALLOC_VERBOSE(nWidth * sizeof(float));
+        pafData = static_cast<float *>(
+            VSI_MALLOC_VERBOSE(nWidth * sizeof(float)) );
         eWrkType = GDT_Float32;
     }
 
@@ -3071,14 +3442,14 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
 /* -------------------------------------------------------------------- */
 /*      Loop over all sample lines.                                     */
 /* -------------------------------------------------------------------- */
-    double dfSum=0.0;
-    double dfSum2=0.0;
+    double dfSum = 0.0;
+    double dfSum2 = 0.0;
     int iLine = 0;
     int nSamples = 0;
 
     do
     {
-        if( !pfnProgress( iLine / (double) nHeight,
+        if( !pfnProgress( iLine / static_cast<double>( nHeight ),
                           NULL, pProgressData ) )
         {
             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -3086,25 +3457,26 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
             return CE_Failure;
         }
 
-        CPLErr eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nWidth, 1,
-                             pafData, nWidth, 1, eWrkType,
-                             0, 0, NULL );
-        if ( eErr != CE_None )
+        const CPLErr eErr =
+            poSrcBand->RasterIO( GF_Read, 0, iLine, nWidth, 1,
+                                 pafData, nWidth, 1, eWrkType,
+                                 0, 0, NULL );
+        if( eErr != CE_None )
         {
             CPLFree( pafData );
             return eErr;
         }
 
-        for( int iPixel = 0; iPixel < nWidth; iPixel++ )
+        for( int iPixel = 0; iPixel < nWidth; ++iPixel )
         {
-            float       fValue;
+            float fValue = 0.0f;
 
             if( bComplex )
             {
                 // Compute the magnitude of the complex value.
-                fValue = (float)
+                fValue = static_cast<float>(
                     sqrt(pafData[iPixel*2  ] * pafData[iPixel*2  ]
-                         + pafData[iPixel*2+1] * pafData[iPixel*2+1]);
+                         + pafData[iPixel*2+1] * pafData[iPixel*2+1]) );
             }
             else
             {
@@ -3117,7 +3489,6 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
 
         nSamples += nWidth;
         iLine += nSampleStep;
-
     } while( iLine < nHeight );
 
     if( !pfnProgress( 1.0, NULL, pProgressData ) )
@@ -3152,6 +3523,14 @@ GDALComputeBandStats( GDALRasterBandH hSrcBand,
 /*      the given band to match the base layer approximately.           */
 /************************************************************************/
 
+/** Undocumented
+ * @param hBaseBand undocumented.
+ * @param nOverviewCount undocumented.
+ * @param pahOverviews undocumented.
+ * @param pfnProgress undocumented.
+ * @param pProgressData undocumented.
+ * @return undocumented
+ */
 CPLErr
 GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
                                  int nOverviewCount,
@@ -3160,38 +3539,41 @@ GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
                                  void *pProgressData )
 
 {
-    VALIDATE_POINTER1( hBaseBand, "GDALOverviewMagnitudeCorrection", CE_Failure );
+    VALIDATE_POINTER1( hBaseBand, "GDALOverviewMagnitudeCorrection",
+                       CE_Failure );
 
 /* -------------------------------------------------------------------- */
 /*      Compute mean/stddev for source raster.                          */
 /* -------------------------------------------------------------------- */
-    double dfOrigMean, dfOrigStdDev;
-    CPLErr eErr
-        = GDALComputeBandStats( hBaseBand, 2, &dfOrigMean, &dfOrigStdDev,
-                                pfnProgress, pProgressData );
+    double dfOrigMean = 0.0;
+    double dfOrigStdDev = 0.0;
+    {
+        const CPLErr eErr
+            = GDALComputeBandStats( hBaseBand, 2, &dfOrigMean, &dfOrigStdDev,
+                                    pfnProgress, pProgressData );
 
-    if( eErr != CE_None )
-        return eErr;
+        if( eErr != CE_None )
+            return eErr;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Loop on overview bands.                                         */
 /* -------------------------------------------------------------------- */
-    for( int iOverview = 0; iOverview < nOverviewCount; iOverview++ )
+    for( int iOverview = 0; iOverview < nOverviewCount; ++iOverview )
     {
         GDALRasterBand *poOverview = (GDALRasterBand *)pahOverviews[iOverview];
         double  dfOverviewMean, dfOverviewStdDev;
 
-        eErr = GDALComputeBandStats( pahOverviews[iOverview], 1,
-                                     &dfOverviewMean, &dfOverviewStdDev,
-                                     pfnProgress, pProgressData );
+        const CPLErr eErr =
+            GDALComputeBandStats( pahOverviews[iOverview], 1,
+                                  &dfOverviewMean, &dfOverviewStdDev,
+                                  pfnProgress, pProgressData );
 
         if( eErr != CE_None )
             return eErr;
 
-        double dfGain;
-        if( dfOrigStdDev < 0.0001 )
-            dfGain = 1.0;
-        else
+        double dfGain = 1.0;
+        if( dfOrigStdDev >= 0.0001 )
             dfGain = dfOrigStdDev / dfOverviewStdDev;
 
 /* -------------------------------------------------------------------- */
@@ -3200,18 +3582,20 @@ GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
         const int nWidth = poOverview->GetXSize();
         const int nHeight = poOverview->GetYSize();
 
-        GDALDataType eWrkType;
-        float *pafData;
+        GDALDataType eWrkType = GDT_Unknown;
+        float *pafData = NULL;
         const GDALDataType eType = poOverview->GetRasterDataType();
         const bool bComplex = CPL_TO_BOOL(GDALDataTypeIsComplex(eType));
         if( bComplex )
         {
-            pafData = (float *) VSI_MALLOC2_VERBOSE(nWidth, 2 * sizeof(float));
+            pafData = static_cast<float *>(
+                VSI_MALLOC2_VERBOSE(nWidth, 2 * sizeof(float)) );
             eWrkType = GDT_CFloat32;
         }
         else
         {
-            pafData = (float *) VSI_MALLOC2_VERBOSE(nWidth, sizeof(float));
+            pafData = static_cast<float *>(
+                VSI_MALLOC2_VERBOSE(nWidth, sizeof(float)) );
             eWrkType = GDT_Float32;
         }
 
@@ -3220,9 +3604,9 @@ GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
             return CE_Failure;
         }
 
-        for( int iLine = 0; iLine < nHeight; iLine++ )
+        for( int iLine = 0; iLine < nHeight; ++iLine )
         {
-            if( !pfnProgress( iLine / (double) nHeight,
+            if( !pfnProgress( iLine / static_cast<double>( nHeight ),
                               NULL, pProgressData ) )
             {
                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
@@ -3231,31 +3615,31 @@ GDALOverviewMagnitudeCorrection( GDALRasterBandH hBaseBand,
             }
 
             if( poOverview->RasterIO( GF_Read, 0, iLine, nWidth, 1,
-                                  pafData, nWidth, 1, eWrkType,
-                                  0, 0, NULL ) != CE_None )
+                                      pafData, nWidth, 1, eWrkType,
+                                      0, 0, NULL ) != CE_None )
             {
                 CPLFree( pafData );
                 return CE_Failure;
             }
 
-            for( int iPixel = 0; iPixel < nWidth; iPixel++ )
+            for( int iPixel = 0; iPixel < nWidth; ++iPixel )
             {
                 if( bComplex )
                 {
-                    pafData[iPixel*2] *= (float) dfGain;
-                    pafData[iPixel*2+1] *= (float) dfGain;
+                    pafData[iPixel*2] *= static_cast<float>( dfGain );
+                    pafData[iPixel*2+1] *= static_cast<float>( dfGain );
                 }
                 else
                 {
-                    pafData[iPixel] = (float)
-                        ((pafData[iPixel]-dfOverviewMean)*dfGain + dfOrigMean);
-
+                    pafData[iPixel] = static_cast<float>(
+                        (pafData[iPixel] - dfOverviewMean)
+                        * dfGain + dfOrigMean );
                 }
             }
 
             if( poOverview->RasterIO( GF_Write, 0, iLine, nWidth, 1,
-                                  pafData, nWidth, 1, eWrkType,
-                                  0, 0, NULL ) != CE_None )
+                                      pafData, nWidth, 1, eWrkType,
+                                      0, 0, NULL ) != CE_None )
             {
                 CPLFree( pafData );
                 return CE_Failure;
diff --git a/gcore/rasterio.cpp b/gcore/rasterio.cpp
index 77e2ca5..b092b12 100644
--- a/gcore/rasterio.cpp
+++ b/gcore/rasterio.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: rasterio.cpp 33808 2016-03-29 21:15:28Z goatbar $
  *
  * Project:  GDAL Core
  * Purpose:  Contains default implementation of GDALRasterBand::IRasterIO()
@@ -29,17 +28,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "gdal.h"
 #include "gdal_priv.h"
-#include "gdal_vrt.h"
-#include "vrtdataset.h"
-#include "memdataset.h"
-#include "gdalwarper.h"
 
-#include <stdexcept>
+#include <climits>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
 #include <limits>
+#include <stdexcept>
+
+#include "cpl_conv.h"
+#include "cpl_cpu_features.h"
+#include "cpl_error.h"
+#include "cpl_progress.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "gdal_priv_templates.hpp"
+#include "gdal_vrt.h"
+#include "gdalwarper.h"
+#include "memdataset.h"
+#include "vrtdataset.h"
 
-CPL_CVSID("$Id: rasterio.cpp 33808 2016-03-29 21:15:28Z goatbar $");
+CPL_CVSID("$Id: rasterio.cpp 37528 2017-02-28 23:13:53Z rouault $");
 
 /************************************************************************/
 /*                             IRasterIO()                              */
@@ -57,12 +73,6 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                   GDALRasterIOExtraArg* psExtraArg )
 
 {
-    const int nBandDataSize = GDALGetDataTypeSizeBytes( eDataType );
-    const int nBufDataSize = GDALGetDataTypeSizeBytes( eBufType );
-    GByte       *pabySrcBlock = NULL;
-    GDALRasterBlock *poBlock = NULL;
-    int         nLBlockX=-1, nLBlockY=-1, iBufYOff, iBufXOff, iSrcY;
-
     if( eRWFlag == GF_Write && eFlushBlockErr != CE_None )
     {
         CPLError( eFlushBlockErr, CPLE_AppDefined,
@@ -77,6 +87,22 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         return CE_Failure;
     }
 
+    const int nBandDataSize = GDALGetDataTypeSizeBytes( eDataType );
+    const int nBufDataSize = GDALGetDataTypeSizeBytes( eBufType );
+    GByte *pabySrcBlock = NULL;
+    GDALRasterBlock *poBlock = NULL;
+    int nLBlockX = -1;
+    int nLBlockY = -1;
+    int iBufYOff = 0;
+    int iBufXOff = 0;
+    int iSrcY = 0;
+    const bool bUseIntegerRequestCoords =
+           (!psExtraArg->bFloatingPointWindowValidity ||
+            (nXOff == psExtraArg->dfXOff &&
+             nYOff == psExtraArg->dfYOff &&
+             nXSize == psExtraArg->dfXSize &&
+             nYSize == psExtraArg->dfYSize));
+
 /* ==================================================================== */
 /*      A common case is the data requested with the destination        */
 /*      is packed, and the block width is the raster width.             */
@@ -85,38 +111,37 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         && nLineSpace == nPixelSpace * nXSize
         && nBlockXSize == GetXSize()
         && nBufXSize == nXSize
-        && nBufYSize == nYSize )
+        && nBufYSize == nYSize
+        && bUseIntegerRequestCoords )
     {
         CPLErr eErr = CE_None;
 
         for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
         {
-            int         nSrcByteOffset;
-
             iSrcY = iBufYOff + nYOff;
 
             if( iSrcY < nLBlockY * nBlockYSize
-                || iSrcY >= (nLBlockY+1) * nBlockYSize )
+                || iSrcY - nBlockYSize >= nLBlockY * nBlockYSize )
             {
                 nLBlockY = iSrcY / nBlockYSize;
-                int bJustInitialize =
+                bool bJustInitialize =
                     eRWFlag == GF_Write
                     && nXOff == 0 && nXSize == nBlockXSize
                     && nYOff <= nLBlockY * nBlockYSize
-                    && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize;
+                    && nYOff + nYSize - nBlockYSize >= nLBlockY * nBlockYSize;
 
-                /* Is this a partial tile at right and/or bottom edges of */
-                /* the raster, and that is going to be completely written? */
-                /* If so, do not load it from storage, but zero it so that */
-                /* the content outsize of the validity area is initialized. */
+                // Is this a partial tile at right and/or bottom edges of
+                // the raster, and that is going to be completely written?
+                // If so, do not load it from storage, but zero it so that
+                // the content outsize of the validity area is initialized.
                 bool bMemZeroBuffer = false;
                 if( eRWFlag == GF_Write && !bJustInitialize &&
                     nXOff == 0 && nXSize == nBlockXSize &&
                     nYOff <= nLBlockY * nBlockYSize &&
                     nYOff + nYSize == GetYSize() &&
-                    (nLBlockY+1) * nBlockYSize > GetYSize() )
+                    nLBlockY * nBlockYSize > GetYSize() - nBlockYSize )
                 {
-                    bJustInitialize = TRUE;
+                    bJustInitialize = true;
                     bMemZeroBuffer = true;
                 }
 
@@ -125,8 +150,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
                 poBlock = GetLockedBlockRef( 0, nLBlockY, bJustInitialize );
                 if( poBlock == NULL )
-                {
-                    CPLError( CE_Failure, CPLE_AppDefined,
+                {CPLError( CE_Failure, CPLE_AppDefined,
                               "GetBlockRef failed at X block offset %d, "
                               "Y block offset %d", 0, nLBlockY );
                     eErr = CE_Failure;
@@ -147,39 +171,49 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             // To make Coverity happy. Should not happen by design.
             if( pabySrcBlock == NULL )
             {
-                CPLAssert(FALSE);
+                CPLAssert(false);
                 eErr = CE_Failure;
                 break;
             }
 
-            nSrcByteOffset = ((iSrcY-nLBlockY*nBlockYSize)*nBlockXSize + nXOff)
+            const int nSrcByteOffset =
+                ((iSrcY - nLBlockY * nBlockYSize) * nBlockXSize + nXOff)
                 * nBandDataSize;
 
             if( eDataType == eBufType )
             {
                 if( eRWFlag == GF_Read )
-                    memcpy( ((GByte *) pData) + (GPtrDiff_t)iBufYOff * nLineSpace,
-                            pabySrcBlock + nSrcByteOffset,
-                            (size_t)nLineSpace );
+                    memcpy(
+                        static_cast<GByte *>(pData)
+                        + static_cast<GPtrDiff_t>(iBufYOff) * nLineSpace,
+                        pabySrcBlock + nSrcByteOffset,
+                        static_cast<size_t>(nLineSpace) );
                 else
-                    memcpy( pabySrcBlock + nSrcByteOffset,
-                            ((GByte *) pData) + (GPtrDiff_t)iBufYOff * nLineSpace,
-                            (size_t)nLineSpace );
+                    memcpy(
+                        pabySrcBlock + nSrcByteOffset,
+                        static_cast<GByte *>(pData)
+                        + static_cast<GPtrDiff_t>(iBufYOff) * nLineSpace,
+                        static_cast<size_t>(nLineSpace) );
             }
             else
             {
-                /* type to type conversion */
+                // Type to type conversion.
 
                 if( eRWFlag == GF_Read )
-                    GDALCopyWords( pabySrcBlock + nSrcByteOffset,
-                                   eDataType, nBandDataSize,
-                                   ((GByte *) pData) + (GPtrDiff_t)iBufYOff * nLineSpace,
-                                   eBufType, (int)nPixelSpace, nBufXSize );
+                    GDALCopyWords(
+                        pabySrcBlock + nSrcByteOffset,
+                        eDataType, nBandDataSize,
+                        static_cast<GByte *>(pData)
+                        + static_cast<GPtrDiff_t>(iBufYOff) * nLineSpace,
+                        eBufType,
+                        static_cast<int>(nPixelSpace), nBufXSize );
                 else
-                    GDALCopyWords( ((GByte *) pData) + (GPtrDiff_t)iBufYOff * nLineSpace,
-                                   eBufType, (int)nPixelSpace,
-                                   pabySrcBlock + nSrcByteOffset,
-                                   eDataType, nBandDataSize, nBufXSize );
+                    GDALCopyWords(
+                        static_cast<GByte *>(pData)
+                        + static_cast<GPtrDiff_t>(iBufYOff) * nLineSpace,
+                        eBufType, static_cast<int>(nPixelSpace),
+                        pabySrcBlock + nSrcByteOffset,
+                        eDataType, nBandDataSize, nBufXSize );
             }
 
             if( psExtraArg->pfnProgress != NULL &&
@@ -204,23 +238,22 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if( (nBufXSize < nXSize || nBufYSize < nYSize)
         && GetOverviewCount() > 0 && eRWFlag == GF_Read )
     {
-        int         nOverview;
         GDALRasterIOExtraArg sExtraArg;
-
         GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
 
-        nOverview =
-            GDALBandGetBestOverviewLevel2(this, nXOff, nYOff, nXSize, nYSize,
-                                          nBufXSize, nBufYSize, &sExtraArg);
+        const int nOverview =
+            GDALBandGetBestOverviewLevel2( this, nXOff, nYOff, nXSize, nYSize,
+                                           nBufXSize, nBufYSize, &sExtraArg );
         if (nOverview >= 0)
         {
             GDALRasterBand* poOverviewBand = GetOverview(nOverview);
             if (poOverviewBand == NULL)
                 return CE_Failure;
 
-            return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
-                                            pData, nBufXSize, nBufYSize, eBufType,
-                                            nPixelSpace, nLineSpace, &sExtraArg );
+            return poOverviewBand->RasterIO(
+                eRWFlag, nXOff, nYOff, nXSize, nYSize,
+                pData, nBufXSize, nBufYSize, eBufType,
+                nPixelSpace, nLineSpace, &sExtraArg );
         }
     }
 
@@ -230,81 +263,90 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         nLineSpace == nPixelSpace * nBufXSize &&
         CPLTestBool(CPLGetConfigOption("GDAL_NO_COSTLY_OVERVIEW", "NO")) )
     {
-        memset(pData, 0, (size_t)(nLineSpace * nBufYSize));
+        memset( pData, 0, static_cast<size_t>(nLineSpace * nBufYSize) );
         return CE_None;
     }
 
-
 /* ==================================================================== */
 /*      The second case when we don't need subsample data but likely    */
 /*      need data type conversion.                                      */
 /* ==================================================================== */
-    int         iSrcX;
+    int iSrcX = 0;
 
-    if ( /* nPixelSpace == nBufDataSize
-            && */ nXSize == nBufXSize
-         && nYSize == nBufYSize )
+    if ( // nPixelSpace == nBufDataSize &&
+         nXSize == nBufXSize
+         && nYSize == nBufYSize
+         && bUseIntegerRequestCoords )
     {
-//        printf( "IRasterIO(%d,%d,%d,%d) rw=%d case 2\n",
-//                nXOff, nYOff, nXSize, nYSize,
-//                (int) eRWFlag );
+#if DEBUG_VERBOSE
+        printf( "IRasterIO(%d,%d,%d,%d) rw=%d case 2\n",/*ok*/
+                nXOff, nYOff, nXSize, nYSize,
+                static_cast<int>(eRWFlag) );
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Loop over buffer computing source locations.                    */
 /* -------------------------------------------------------------------- */
-        int     nLBlockXStart, nXSpanEnd;
-
         // Calculate starting values out of loop
-        nLBlockXStart = nXOff / nBlockXSize;
-        nXSpanEnd = nBufXSize + nXOff;
+        const int nLBlockXStart = nXOff / nBlockXSize;
+        const int nXSpanEnd = nBufXSize + nXOff;
 
         int nYInc = 0;
-        for( iBufYOff = 0, iSrcY = nYOff; iBufYOff < nBufYSize; iBufYOff+=nYInc, iSrcY+=nYInc )
+        for( iBufYOff = 0, iSrcY = nYOff;
+             iBufYOff < nBufYSize;
+             iBufYOff += nYInc, iSrcY += nYInc )
         {
-            GPtrDiff_t  iBufOffset;
-            GPtrDiff_t  iSrcOffset;
-            int     nXSpan;
+            GPtrDiff_t iSrcOffset = 0;
+            int nXSpan = 0;
 
-            iBufOffset = (GPtrDiff_t)iBufYOff * (GPtrDiff_t)nLineSpace;
+            GPtrDiff_t iBufOffset =
+                static_cast<GPtrDiff_t>(iBufYOff) *
+                static_cast<GPtrDiff_t>(nLineSpace);
             nLBlockY = iSrcY / nBlockYSize;
             nLBlockX = nLBlockXStart;
             iSrcX = nXOff;
             while( iSrcX < nXSpanEnd )
             {
-                int nXSpanSize;
-
-                nXSpan = (nLBlockX + 1) * nBlockXSize;
-                nXSpan = ( ( nXSpan < nXSpanEnd )?nXSpan:nXSpanEnd ) - iSrcX;
-                nXSpanSize = nXSpan * (int)nPixelSpace;
+                nXSpan = nLBlockX * nBlockXSize;
+                if( nXSpan < INT_MAX - nBlockXSize )
+                    nXSpan += nBlockXSize;
+                else
+                    nXSpan = INT_MAX;
+                const int nXRight = nXSpan;
+                nXSpan = ( nXSpan < nXSpanEnd ? nXSpan:nXSpanEnd ) - iSrcX;
+                const size_t nXSpanSize = nXSpan * static_cast<size_t>(nPixelSpace);
 
-                int bJustInitialize =
+                bool bJustInitialize =
                     eRWFlag == GF_Write
                     && nYOff <= nLBlockY * nBlockYSize
-                    && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize
+                    && nYOff + nYSize - nBlockYSize >= nLBlockY * nBlockYSize
                     && nXOff <= nLBlockX * nBlockXSize
-                    && nXOff + nXSize >= (nLBlockX+1) * nBlockXSize;
+                    && nXOff + nXSize >= nXRight;
 
-                /* Is this a partial tile at right and/or bottom edges of */
-                /* the raster, and that is going to be completely written? */
-                /* If so, do not load it from storage, but zero it so that */
-                /* the content outsize of the validity area is initialized. */
+                // Is this a partial tile at right and/or bottom edges of
+                // the raster, and that is going to be completely written?
+                // If so, do not load it from storage, but zero it so that
+                // the content outsize of the validity area is initialized.
                 bool bMemZeroBuffer = false;
                 if( eRWFlag == GF_Write && !bJustInitialize &&
                     nXOff <= nLBlockX * nBlockXSize &&
                     nYOff <= nLBlockY * nBlockYSize &&
-                    (nXOff + nXSize >= (nLBlockX+1) * nBlockXSize ||
-                     (nXOff + nXSize == GetXSize() && (nLBlockX+1) * nBlockXSize > GetXSize())) &&
-                    (nYOff + nYSize >= (nLBlockY+1) * nBlockYSize ||
-                     (nYOff + nYSize == GetYSize() && (nLBlockY+1) * nBlockYSize > GetYSize())) )
+                    (nXOff + nXSize >= nXRight ||
+                     (nXOff + nXSize == GetXSize() &&
+                      nXRight > GetXSize())) &&
+                    (nYOff + nYSize - nBlockYSize >= nLBlockY * nBlockYSize ||
+                     (nYOff + nYSize == GetYSize() &&
+                      nLBlockY * nBlockYSize > GetYSize() - nBlockYSize)) )
                 {
-                    bJustInitialize = TRUE;
+                    bJustInitialize = true;
                     bMemZeroBuffer = true;
                 }
 
 /* -------------------------------------------------------------------- */
 /*      Ensure we have the appropriate block loaded.                    */
 /* -------------------------------------------------------------------- */
-                poBlock = GetLockedBlockRef( nLBlockX, nLBlockY, bJustInitialize );
+                poBlock = GetLockedBlockRef( nLBlockX, nLBlockY,
+                                             bJustInitialize );
                 if( !poBlock )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
@@ -325,35 +367,50 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Copy over this chunk of data.                                   */
 /* -------------------------------------------------------------------- */
-                iSrcOffset = ((GPtrDiff_t)iSrcX - (GPtrDiff_t)nLBlockX*nBlockXSize
-                    + ((GPtrDiff_t)(iSrcY) - (GPtrDiff_t)nLBlockY*nBlockYSize) * nBlockXSize)*nBandDataSize;
-                /* Fill up as many rows as possible for the loaded block */
-                int kmax = MIN(nBlockYSize - (iSrcY % nBlockYSize), nBufYSize - iBufYOff);
+                iSrcOffset =
+                    (static_cast<GPtrDiff_t>(iSrcX)
+                     - static_cast<GPtrDiff_t>(nLBlockX * nBlockXSize)
+                     + (static_cast<GPtrDiff_t>(iSrcY)
+                       - static_cast<GPtrDiff_t>(nLBlockY) * nBlockYSize)
+                     * nBlockXSize)
+                    * nBandDataSize;
+                // Fill up as many rows as possible for the loaded block.
+                const int kmax = std::min(
+                    nBlockYSize - (iSrcY % nBlockYSize), nBufYSize - iBufYOff );
                 for(int k=0; k<kmax;k++)
                 {
                     if( eDataType == eBufType
                         && nPixelSpace == nBufDataSize )
                     {
                         if( eRWFlag == GF_Read )
-                            memcpy( ((GByte *) pData) + iBufOffset + (GPtrDiff_t)k * nLineSpace,
-                                    pabySrcBlock + iSrcOffset, nXSpanSize );
+                            memcpy( static_cast<GByte *>(pData) + iBufOffset
+                                    + static_cast<GPtrDiff_t>(k) * nLineSpace,
+                                    pabySrcBlock + iSrcOffset,
+                                    nXSpanSize );
                         else
                             memcpy( pabySrcBlock + iSrcOffset,
-                                    ((GByte *) pData) + iBufOffset + (GPtrDiff_t)k * nLineSpace, nXSpanSize );
+                                    static_cast<GByte *>(pData) + iBufOffset
+                                    + static_cast<GPtrDiff_t>(k) * nLineSpace,
+                                    nXSpanSize );
                     }
                     else
                     {
                         /* type to type conversion */
                         if( eRWFlag == GF_Read )
-                            GDALCopyWords( pabySrcBlock + iSrcOffset,
-                                        eDataType, nBandDataSize,
-                                        ((GByte *) pData) + iBufOffset + (GPtrDiff_t)k * nLineSpace,
-                                        eBufType, (int)nPixelSpace, nXSpan );
+                            GDALCopyWords(
+                                pabySrcBlock + iSrcOffset,
+                                eDataType, nBandDataSize,
+                                static_cast<GByte *>(pData) + iBufOffset
+                                + static_cast<GPtrDiff_t>(k) * nLineSpace,
+                                eBufType, static_cast<int>(nPixelSpace),
+                                nXSpan );
                         else
-                            GDALCopyWords( ((GByte *) pData) + iBufOffset + (GPtrDiff_t)k * nLineSpace,
-                                        eBufType, (int)nPixelSpace,
-                                        pabySrcBlock + iSrcOffset,
-                                        eDataType, nBandDataSize, nXSpan );
+                            GDALCopyWords(
+                                static_cast<GByte *>(pData) + iBufOffset +
+                                static_cast<GPtrDiff_t>(k) * nLineSpace,
+                                eBufType, static_cast<int>(nPixelSpace),
+                                pabySrcBlock + iSrcOffset,
+                                eDataType, nBandDataSize, nXSpan );
                     }
 
                     iSrcOffset += nBlockXSize * nBandDataSize;
@@ -371,8 +428,9 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             nYInc = nBlockYSize - (iSrcY % nBlockYSize);
 
             if( psExtraArg->pfnProgress != NULL &&
-                !psExtraArg->pfnProgress(1.0 * MIN(nBufYSize, iBufYOff + nYInc) / nBufYSize, "",
-                                         psExtraArg->pProgressData) )
+                !psExtraArg->pfnProgress(
+                    1.0 * std::min(nBufYSize, iBufYOff + nYInc) / nBufYSize, "",
+                    psExtraArg->pProgressData) )
             {
                 return CE_Failure;
             }
@@ -386,7 +444,10 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /*      request.  This is the most general implementation.              */
 /* ==================================================================== */
 
-    double dfXOff, dfYOff, dfXSize, dfYSize;
+    double dfXOff = nXOff;
+    double dfYOff = nYOff;
+    double dfXSize = nXSize;
+    double dfYSize = nYSize;
     if( psExtraArg->bFloatingPointWindowValidity )
     {
         dfXOff = psExtraArg->dfXOff;
@@ -398,19 +459,12 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
         CPLAssert(nXSize - dfXSize < 1.0);
         CPLAssert(nYSize - dfYSize < 1.0);
     }
-    else
-    {
-        dfXOff = nXOff;
-        dfYOff = nYOff;
-        dfXSize = nXSize;
-        dfYSize = nYSize;
-    }
+
 /* -------------------------------------------------------------------- */
 /*      Compute stepping increment.                                     */
 /* -------------------------------------------------------------------- */
-    double dfSrcXInc, dfSrcYInc;
-    dfSrcXInc = dfXSize / (double) nBufXSize;
-    dfSrcYInc = dfYSize / (double) nBufYSize;
+    const double dfSrcXInc = dfXSize / static_cast<double>( nBufXSize );
+    const double dfSrcYInc = dfYSize / static_cast<double>( nBufYSize );
     CPLErr eErr = CE_None;
 
     if (eRWFlag == GF_Write)
@@ -419,48 +473,54 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /*    Write case                                                        */
 /*    Loop over raster window computing source locations in the buffer. */
 /* -------------------------------------------------------------------- */
-        int iDstX, iDstY;
         GByte* pabyDstBlock = NULL;
 
-        for( iDstY = nYOff; iDstY < nYOff + nYSize; iDstY ++)
+        for( int iDstY = nYOff; iDstY < nYOff + nYSize; iDstY ++)
         {
-            GPtrDiff_t iBufOffset, iDstOffset;
-            iBufYOff = (int)((iDstY - nYOff) / dfSrcYInc);
+            GPtrDiff_t iBufOffset = 0;
+            GPtrDiff_t iDstOffset = 0;
+            iBufYOff = static_cast<int>((iDstY - nYOff) / dfSrcYInc);
 
-            for( iDstX = nXOff; iDstX < nXOff + nXSize; iDstX ++)
+            for( int iDstX = nXOff; iDstX < nXOff + nXSize; iDstX ++)
             {
-                iBufXOff = (int)((iDstX - nXOff) / dfSrcXInc);
-                iBufOffset = (GPtrDiff_t)iBufYOff * (GPtrDiff_t)nLineSpace + iBufXOff * (GPtrDiff_t)nPixelSpace;
-
-                // FIXME: this code likely doesn't work if the dirty block gets flushed
-                // to disk before being completely written.
-                // In the meantime, bJustInitialize should probably be set to FALSE
-                // even if it is not ideal performance wise, and for lossy compression
+                iBufXOff = static_cast<int>((iDstX - nXOff) / dfSrcXInc);
+                iBufOffset =
+                    static_cast<GPtrDiff_t>(iBufYOff)
+                    * static_cast<GPtrDiff_t>(nLineSpace)
+                    + iBufXOff * static_cast<GPtrDiff_t>(nPixelSpace);
+
+                // FIXME: this code likely doesn't work if the dirty block gets
+                // flushed to disk before being completely written.
+                // In the meantime, bJustInitialize should probably be set to
+                // FALSE even if it is not ideal performance wise, and for
+                // lossy compression.
 
     /* -------------------------------------------------------------------- */
     /*      Ensure we have the appropriate block loaded.                    */
     /* -------------------------------------------------------------------- */
                 if( iDstX < nLBlockX * nBlockXSize
-                    || iDstX >= (nLBlockX+1) * nBlockXSize
+                    || iDstX - nBlockXSize >= nLBlockX * nBlockXSize
                     || iDstY < nLBlockY * nBlockYSize
-                    || iDstY >= (nLBlockY+1) * nBlockYSize )
+                    || iDstY - nBlockYSize >= nLBlockY * nBlockYSize )
                 {
                     nLBlockX = iDstX / nBlockXSize;
                     nLBlockY = iDstY / nBlockYSize;
 
-                    int bJustInitialize =
-                           nYOff <= nLBlockY * nBlockYSize
-                        && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize
+                    const bool bJustInitialize =
+                        nYOff <= nLBlockY * nBlockYSize
+                        && nYOff + nYSize - nBlockYSize >= nLBlockY * nBlockYSize
                         && nXOff <= nLBlockX * nBlockXSize
-                        && nXOff + nXSize >= (nLBlockX+1) * nBlockXSize;
+                        && nXOff + nXSize - nBlockXSize >= nLBlockX * nBlockXSize;
                     /*bool bMemZeroBuffer = FALSE;
                     if( !bJustInitialize &&
                         nXOff <= nLBlockX * nBlockXSize &&
                         nYOff <= nLBlockY * nBlockYSize &&
                         (nXOff + nXSize >= (nLBlockX+1) * nBlockXSize ||
-                         (nXOff + nXSize == GetXSize() && (nLBlockX+1) * nBlockXSize > GetXSize())) &&
+                         (nXOff + nXSize == GetXSize() &&
+                         (nLBlockX+1) * nBlockXSize > GetXSize())) &&
                         (nYOff + nYSize >= (nLBlockY+1) * nBlockYSize ||
-                         (nYOff + nYSize == GetYSize() && (nLBlockY+1) * nBlockYSize > GetYSize())) )
+                         (nYOff + nYSize == GetYSize() &&
+                         (nLBlockY+1) * nBlockYSize > GetYSize())) )
                     {
                         bJustInitialize = TRUE;
                         bMemZeroBuffer = TRUE;
@@ -469,7 +529,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                         poBlock->DropLock();
 
                     poBlock = GetLockedBlockRef( nLBlockX, nLBlockY,
-                                                bJustInitialize );
+                                                 bJustInitialize );
                     if( poBlock == NULL )
                     {
                         return( CE_Failure );
@@ -488,7 +548,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 // To make Coverity happy. Should not happen by design.
                 if( pabyDstBlock == NULL )
                 {
-                    CPLAssert(FALSE);
+                    CPLAssert(false);
                     eErr = CE_Failure;
                     break;
                 }
@@ -496,22 +556,30 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     /* -------------------------------------------------------------------- */
     /*      Copy over this pixel of data.                                   */
     /* -------------------------------------------------------------------- */
-                iDstOffset = ((GPtrDiff_t)iDstX - (GPtrDiff_t)nLBlockX*nBlockXSize
-                    + ((GPtrDiff_t)iDstY - (GPtrDiff_t)nLBlockY*nBlockYSize) * nBlockXSize)*nBandDataSize;
+                iDstOffset =
+                    (static_cast<GPtrDiff_t>(iDstX)
+                     - static_cast<GPtrDiff_t>(nLBlockX) * nBlockXSize
+                     + (static_cast<GPtrDiff_t>(iDstY)
+                        - static_cast<GPtrDiff_t>(nLBlockY) * nBlockYSize)
+                     * nBlockXSize )
+                    * nBandDataSize;
 
                 if( eDataType == eBufType )
                 {
-                    memcpy( pabyDstBlock + iDstOffset,
-                            ((GByte *) pData) + iBufOffset, nBandDataSize );
+                    memcpy(
+                        pabyDstBlock + iDstOffset,
+                        static_cast<GByte *>(pData) + iBufOffset,
+                        nBandDataSize );
                 }
                 else
                 {
                     /* type to type conversion ... ouch, this is expensive way
                     of handling single words */
 
-                    GDALCopyWords( ((GByte *) pData) + iBufOffset, eBufType, 0,
-                                pabyDstBlock + iDstOffset, eDataType, 0,
-                                1 );
+                    GDALCopyWords(
+                        static_cast<GByte *>(pData) + iBufOffset, eBufType, 0,
+                        pabyDstBlock + iDstOffset, eDataType, 0,
+                        1 );
                 }
             }
 
@@ -541,9 +609,10 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             else if( psExtraArg->eResampleAlg == GRIORA_Gauss &&
                      GDALDataTypeIsComplex( eDataType ) )
             {
-                CPLError(CE_Warning, CPLE_NotSupported,
-                         "Resampling method not supported on complex data type band. "
-                         "Falling back to nearest neighbour");
+                CPLError(
+                    CE_Warning, CPLE_NotSupported,
+                    "Resampling method not supported on complex data type "
+                    "band. Falling back to nearest neighbour");
             }
             else
             {
@@ -556,10 +625,12 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
             }
         }
 
-        double      dfSrcX, dfSrcY;
-        int         nLimitBlockY = 0;
-        int         bByteCopy = ( eDataType == eBufType && nBandDataSize == 1);
+        double dfSrcX = 0.0;
+        double dfSrcY = 0.0;
+        int nLimitBlockY = 0;
+        const bool bByteCopy = eDataType == eBufType && nBandDataSize == 1;
         int nStartBlockX = -nBlockXSize;
+        const double EPS = 1e-10;
 
 /* -------------------------------------------------------------------- */
 /*      Read case                                                       */
@@ -567,28 +638,43 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
         for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
         {
-            GPtrDiff_t iBufOffset, iSrcOffset;
+            // Add small epsilon to avoid some numeric precision issues.
+            dfSrcY = (iBufYOff+0.5) * dfSrcYInc + dfYOff + EPS;
+            dfSrcX = 0.5 * dfSrcXInc + dfXOff + EPS;
+            iSrcY = static_cast<int>(dfSrcY);
 
-            dfSrcY = (iBufYOff+0.5) * dfSrcYInc + dfYOff;
-            dfSrcX = 0.5 * dfSrcXInc + dfXOff;
-            iSrcY = (int) dfSrcY;
-
-            iBufOffset = (GPtrDiff_t)iBufYOff * (GPtrDiff_t)nLineSpace;
+            GPtrDiff_t iBufOffset =
+                static_cast<GPtrDiff_t>(iBufYOff)
+                * static_cast<GPtrDiff_t>(nLineSpace);
 
             if( iSrcY >= nLimitBlockY )
             {
                 nLBlockY = iSrcY / nBlockYSize;
-                nLimitBlockY = (nLBlockY + 1) * nBlockYSize;
-                nStartBlockX = -nBlockXSize; /* make sure a new block is loaded */
+                nLimitBlockY = nLBlockY * nBlockYSize;
+                if( nLimitBlockY < INT_MAX - nBlockYSize )
+                    nLimitBlockY += nBlockYSize;
+                else
+                    nLimitBlockY = INT_MAX;
+                // Make sure a new block is loaded.
+                nStartBlockX = -nBlockXSize;
             }
-            else if( (int)dfSrcX < nStartBlockX )
-                nStartBlockX = -nBlockXSize; /* make sure a new block is loaded */
+            else if( static_cast<int>(dfSrcX) < nStartBlockX )
+            {
+                // Make sure a new block is loaded.
+                nStartBlockX = -nBlockXSize;
+            }
+
+            GPtrDiff_t iSrcOffsetCst =
+                (iSrcY - nLBlockY*nBlockYSize)
+                * static_cast<GPtrDiff_t>(nBlockXSize);
 
-            GPtrDiff_t iSrcOffsetCst = (iSrcY - nLBlockY*nBlockYSize) * (GPtrDiff_t)nBlockXSize;
+            GPtrDiff_t iSrcOffset = 0;
 
-            for( iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff++, dfSrcX += dfSrcXInc )
+            for( iBufXOff = 0;
+                 iBufXOff < nBufXSize;
+                 iBufXOff++, dfSrcX += dfSrcXInc )
             {
-                iSrcX = (int) dfSrcX;
+                iSrcX = static_cast<int>( dfSrcX );
                 int nDiffX = iSrcX - nStartBlockX;
 
     /* -------------------------------------------------------------------- */
@@ -603,8 +689,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                     if( poBlock != NULL )
                         poBlock->DropLock();
 
-                    poBlock = GetLockedBlockRef( nLBlockX, nLBlockY,
-                                                 FALSE );
+                    poBlock = GetLockedBlockRef( nLBlockX, nLBlockY, FALSE );
                     if( poBlock == NULL )
                     {
                         eErr = CE_Failure;
@@ -617,7 +702,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 // To make Coverity happy.  Should not happen by design.
                 if( pabySrcBlock == NULL )
                 {
-                    CPLAssert(FALSE);
+                    CPLAssert(false);
                     eErr = CE_Failure;
                     break;
                 }
@@ -628,25 +713,31 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                 if( bByteCopy )
                 {
                     iSrcOffset = (GPtrDiff_t)nDiffX + iSrcOffsetCst;
-                    ((GByte *) pData)[iBufOffset] = pabySrcBlock[iSrcOffset];
+                    static_cast<GByte *>(pData)[iBufOffset] =
+                        pabySrcBlock[iSrcOffset];
                 }
                 else if( eDataType == eBufType )
                 {
-                    iSrcOffset = ((GPtrDiff_t)nDiffX + iSrcOffsetCst)*nBandDataSize;
-                    memcpy( ((GByte *) pData) + iBufOffset,
+                    iSrcOffset =
+                        (static_cast<GPtrDiff_t>(nDiffX) + iSrcOffsetCst)
+                        * nBandDataSize;
+                    memcpy( static_cast<GByte *>(pData) + iBufOffset,
                             pabySrcBlock + iSrcOffset, nBandDataSize );
                 }
                 else
                 {
-                    /* type to type conversion ... ouch, this is expensive way
-                    of handling single words */
-                    iSrcOffset = ((GPtrDiff_t)nDiffX + iSrcOffsetCst)*nBandDataSize;
-                    GDALCopyWords( pabySrcBlock + iSrcOffset, eDataType, 0,
-                                ((GByte *) pData) + iBufOffset, eBufType, 0,
-                                1 );
+                    // Type to type conversion ... ouch, this is expensive way
+                    // of handling single words.
+                    iSrcOffset =
+                        (static_cast<GPtrDiff_t>(nDiffX) + iSrcOffsetCst)
+                        * nBandDataSize;
+                    GDALCopyWords(
+                        pabySrcBlock + iSrcOffset, eDataType, 0,
+                        static_cast<GByte *>(pData) + iBufOffset, eBufType, 0,
+                        1 );
                 }
 
-                iBufOffset += (int)nPixelSpace;
+                iBufOffset += static_cast<int>(nPixelSpace);
             }
             if( eErr == CE_Failure )
                 break;
@@ -664,7 +755,7 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
     if( poBlock != NULL )
         poBlock->DropLock();
 
-    return( eErr );
+    return eErr;
 }
 
 /************************************************************************/
@@ -673,17 +764,21 @@ CPLErr GDALRasterBand::IRasterIO( GDALRWFlag eRWFlag,
 
 typedef struct
 {
-    double dfXOff, dfYOff;
-    double dfXRatioDstToSrc, dfYRatioDstToSrc;
+    double dfXOff;
+    double dfYOff;
+    double dfXRatioDstToSrc;
+    double dfYRatioDstToSrc;
 } GDALRasterIOTransformerStruct;
 
 static int GDALRasterIOTransformer( void *pTransformerArg,
-                                    CPL_UNUSED int bDstToSrc, int nPointCount,
-                                    double *x, double *y, CPL_UNUSED double *z,
+                                    CPL_UNUSED int bDstToSrc,
+                                    int nPointCount,
+                                    double *x, double *y, double * /* z */,
                                     int *panSuccess )
 {
     CPLAssert(bDstToSrc);
-    GDALRasterIOTransformerStruct* psParams = (GDALRasterIOTransformerStruct*) pTransformerArg;
+    GDALRasterIOTransformerStruct* psParams =
+        static_cast<GDALRasterIOTransformerStruct *>( pTransformerArg );
     for(int i = 0; i < nPointCount; i++)
     {
         x[i] = x[i] * psParams->dfXRatioDstToSrc + psParams->dfXOff;
@@ -697,23 +792,24 @@ static int GDALRasterIOTransformer( void *pTransformerArg,
 /*                          RasterIOResampled()                         */
 /************************************************************************/
 
-CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
-                                  int nXOff, int nYOff, int nXSize, int nYSize,
-                                  void * pData, int nBufXSize, int nBufYSize,
-                                  GDALDataType eBufType,
-                                  GSpacing nPixelSpace, GSpacing nLineSpace,
-                                  GDALRasterIOExtraArg* psExtraArg )
+//! @cond Doxygen_Suppress
+CPLErr GDALRasterBand::RasterIOResampled(
+    GDALRWFlag /* eRWFlag */,
+    int nXOff, int nYOff, int nXSize, int nYSize,
+    void * pData, int nBufXSize, int nBufYSize,
+    GDALDataType eBufType,
+    GSpacing nPixelSpace, GSpacing nLineSpace,
+    GDALRasterIOExtraArg* psExtraArg )
 {
-    CPLErr eErr = CE_None;
-
     // Determine if we use warping resampling or overview resampling
-    int bUseWarp;
-    if( !GDALDataTypeIsComplex( eDataType ) )
-        bUseWarp = FALSE;
-    else
-        bUseWarp = TRUE;
-
-    double dfXOff, dfYOff, dfXSize, dfYSize;
+    bool bUseWarp = false;
+    if( GDALDataTypeIsComplex( eDataType ) )
+        bUseWarp = true;
+
+    double dfXOff = nXOff;
+    double dfYOff = nYOff;
+    double dfXSize = nXSize;
+    double dfYSize = nYSize;
     if( psExtraArg->bFloatingPointWindowValidity )
     {
         dfXOff = psExtraArg->dfXOff;
@@ -725,71 +821,85 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         CPLAssert(nXSize - dfXSize < 1.0);
         CPLAssert(nYSize - dfYSize < 1.0);
     }
-    else
-    {
-        dfXOff = nXOff;
-        dfYOff = nYOff;
-        dfXSize = nXSize;
-        dfYSize = nYSize;
-    }
 
-    double dfXRatioDstToSrc = dfXSize / nBufXSize;
-    double dfYRatioDstToSrc = dfYSize / nBufYSize;
+    const double dfXRatioDstToSrc = dfXSize / nBufXSize;
+    const double dfYRatioDstToSrc = dfYSize / nBufYSize;
 
-    /* Determine the coordinates in the "virtual" output raster to see */
-    /* if there are not integers, in which case we will use them as a shift */
-    /* so that subwindow extracts give the exact same results as entire raster */
-    /* scaling */
+    // Determine the coordinates in the "virtual" output raster to see
+    // if there are not integers, in which case we will use them as a shift
+    // so that subwindow extracts give the exact same results as entire raster
+    // scaling.
     double dfDestXOff = dfXOff / dfXRatioDstToSrc;
-    int bHasXOffVirtual = FALSE;
+    bool bHasXOffVirtual = false;
     int nDestXOffVirtual = 0;
-    if( fabs(dfDestXOff - (int)(dfDestXOff + 0.5)) < 1e-8 )
+    if( fabs(dfDestXOff - static_cast<int>(dfDestXOff + 0.5)) < 1e-8 )
     {
-        bHasXOffVirtual = TRUE;
+        bHasXOffVirtual = true;
         dfXOff = nXOff;
-        nDestXOffVirtual = (int)(dfDestXOff + 0.5);
+        nDestXOffVirtual = static_cast<int>(dfDestXOff + 0.5);
     }
 
     double dfDestYOff = dfYOff / dfYRatioDstToSrc;
-    int bHasYOffVirtual = FALSE;
+    bool bHasYOffVirtual = false;
     int nDestYOffVirtual = 0;
-    if( fabs(dfDestYOff - (int)(dfDestYOff + 0.5)) < 1e-8 )
+    if( fabs(dfDestYOff - static_cast<int>(dfDestYOff + 0.5)) < 1e-8 )
     {
-        bHasYOffVirtual = TRUE;
+        bHasYOffVirtual = true;
         dfYOff = nYOff;
-        nDestYOffVirtual = (int)(dfDestYOff + 0.5);
+        nDestYOffVirtual = static_cast<int>(dfDestYOff + 0.5);
     }
 
-    /* Create a MEM dataset that wraps the output buffer */
-    GDALDataset* poMEMDS = MEMDataset::Create("", nDestXOffVirtual + nBufXSize,
-                                              nDestYOffVirtual + nBufYSize, 0,
-                                              eBufType, NULL);
-    char szBuffer[64];
-    int nRet;
-
-    nRet = CPLPrintPointer(szBuffer, (GByte*)pData - nPixelSpace * nDestXOffVirtual
-                            - nLineSpace * nDestYOffVirtual, sizeof(szBuffer));
-    szBuffer[nRet] = 0;
+    // Create a MEM dataset that wraps the output buffer.
+    GDALDataset* poMEMDS;
+    void* pTempBuffer = NULL;
+    GSpacing nPSMem = nPixelSpace;
+    GSpacing nLSMem = nLineSpace;
+    void* pDataMem = pData;
+    GDALDataType eDTMem = eBufType;
+    if( eBufType != eDataType )
+    {
+        nPSMem = GDALGetDataTypeSizeBytes(eDataType);
+        nLSMem = nPSMem * nBufXSize;
+        pTempBuffer = VSI_MALLOC2_VERBOSE( nBufYSize, static_cast<size_t>(nLSMem) );
+        if( pTempBuffer == NULL )
+            return CE_Failure;
+        pDataMem = pTempBuffer;
+        eDTMem = eDataType;
+    }
 
-    char* apszOptions[4];
-    char szBuffer0[64], szBuffer1[64], szBuffer2[64];
+    poMEMDS = MEMDataset::Create( "", nDestXOffVirtual + nBufXSize,
+                                  nDestYOffVirtual + nBufYSize, 0,
+                                  eDTMem, NULL );
+    char szBuffer[64] = { '\0' };
+    int nRet =
+        CPLPrintPointer(
+            szBuffer, static_cast<GByte*>(pDataMem)
+            - nPSMem * nDestXOffVirtual
+            - nLSMem * nDestYOffVirtual, sizeof(szBuffer));
+    szBuffer[nRet] = '\0';
+
+    char szBuffer0[64] = { '\0' };
     snprintf(szBuffer0, sizeof(szBuffer0), "DATAPOINTER=%s", szBuffer);
-    snprintf(szBuffer1, sizeof(szBuffer1), "PIXELOFFSET=" CPL_FRMT_GIB, (GIntBig)nPixelSpace);
-    snprintf(szBuffer2, sizeof(szBuffer2), "LINEOFFSET=" CPL_FRMT_GIB, (GIntBig)nLineSpace);
-    apszOptions[0] = szBuffer0;
-    apszOptions[1] = szBuffer1;
-    apszOptions[2] = szBuffer2;
-    apszOptions[3] = NULL;
+    char szBuffer1[64] = { '\0' };
+    snprintf( szBuffer1, sizeof(szBuffer1),
+              "PIXELOFFSET=" CPL_FRMT_GIB, static_cast<GIntBig>(nPSMem) );
+    char szBuffer2[64] = { '\0' };
+    snprintf( szBuffer2, sizeof(szBuffer2),
+              "LINEOFFSET=" CPL_FRMT_GIB, static_cast<GIntBig>(nLSMem) );
+    char* apszOptions[4] = { szBuffer0, szBuffer1, szBuffer2, NULL };
 
-    poMEMDS->AddBand(eBufType, apszOptions);
+    poMEMDS->AddBand(eDTMem, apszOptions);
 
-    GDALRasterBandH hMEMBand = (GDALRasterBandH)poMEMDS->GetRasterBand(1);
+    GDALRasterBandH hMEMBand = poMEMDS->GetRasterBand(1);
 
     const char* pszNBITS = GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
     if( pszNBITS )
-        ((GDALRasterBand*)hMEMBand)->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
+        reinterpret_cast<GDALRasterBand *>(hMEMBand)->
+            SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
 
-    /* Do the resampling */
+    CPLErr eErr = CE_None;
+
+    // Do the resampling.
     if( bUseWarp )
     {
         VRTDatasetH hVRTDS = NULL;
@@ -800,8 +910,8 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
             hVRTDS = VRTCreate(nRasterXSize, nRasterYSize);
             VRTAddBand( hVRTDS, eDataType, NULL );
             hVRTBand = GDALGetRasterBand(hVRTDS, 1);
-            VRTAddSimpleSource( (VRTSourcedRasterBandH)hVRTBand,
-                                (GDALRasterBandH)this,
+            VRTAddSimpleSource( hVRTBand,
+                                this,
                                 0, 0,
                                 nRasterXSize, nRasterYSize,
                                 0, 0,
@@ -811,34 +921,45 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
             /* Add a mask band if needed */
             if( GetMaskFlags() != GMF_ALL_VALID )
             {
-                ((GDALDataset*)hVRTDS)->CreateMaskBand(0);
+              reinterpret_cast<GDALDataset *>(hVRTDS)->CreateMaskBand(0);
                 VRTSourcedRasterBand* poVRTMaskBand =
-                    (VRTSourcedRasterBand*)(((GDALRasterBand*)hVRTBand)->GetMaskBand());
+                    reinterpret_cast<VRTSourcedRasterBand *>(
+                        reinterpret_cast<GDALRasterBand *>(hVRTBand)->
+                            GetMaskBand());
                 poVRTMaskBand->
                     AddMaskBandSource( this,
-                                    0, 0,
-                                    nRasterXSize, nRasterYSize,
-                                    0, 0,
-                                    nRasterXSize, nRasterYSize);
+                                       0, 0,
+                                       nRasterXSize, nRasterYSize,
+                                       0, 0,
+                                       nRasterXSize, nRasterYSize );
             }
         }
 
         GDALWarpOptions* psWarpOptions = GDALCreateWarpOptions();
         switch(psExtraArg->eResampleAlg)
         {
-            case GRIORA_NearestNeighbour: psWarpOptions->eResampleAlg = GRA_NearestNeighbour; break;
-            case GRIORA_Bilinear:         psWarpOptions->eResampleAlg = GRA_Bilinear; break;
-            case GRIORA_Cubic:            psWarpOptions->eResampleAlg = GRA_Cubic; break;
-            case GRIORA_CubicSpline:      psWarpOptions->eResampleAlg = GRA_CubicSpline; break;
-            case GRIORA_Lanczos:          psWarpOptions->eResampleAlg = GRA_Lanczos; break;
-            case GRIORA_Average:          psWarpOptions->eResampleAlg = GRA_Average; break;
-            case GRIORA_Mode:             psWarpOptions->eResampleAlg = GRA_Mode; break;
-            default:                      CPLAssert(FALSE); psWarpOptions->eResampleAlg = GRA_NearestNeighbour; break;
+            case GRIORA_NearestNeighbour:
+                psWarpOptions->eResampleAlg = GRA_NearestNeighbour; break;
+            case GRIORA_Bilinear:
+                psWarpOptions->eResampleAlg = GRA_Bilinear; break;
+            case GRIORA_Cubic:
+                psWarpOptions->eResampleAlg = GRA_Cubic; break;
+            case GRIORA_CubicSpline:
+                psWarpOptions->eResampleAlg = GRA_CubicSpline; break;
+            case GRIORA_Lanczos:
+                psWarpOptions->eResampleAlg = GRA_Lanczos; break;
+            case GRIORA_Average:
+                psWarpOptions->eResampleAlg = GRA_Average; break;
+            case GRIORA_Mode:
+                psWarpOptions->eResampleAlg = GRA_Mode; break;
+            default:
+                CPLAssert(false);
+                psWarpOptions->eResampleAlg = GRA_NearestNeighbour; break;
         }
-        psWarpOptions->hSrcDS = (GDALDatasetH) (hVRTDS ? hVRTDS : GetDataset());
-        psWarpOptions->hDstDS = (GDALDatasetH) poMEMDS;
+        psWarpOptions->hSrcDS = hVRTDS ? hVRTDS : GetDataset();
+        psWarpOptions->hDstDS = poMEMDS;
         psWarpOptions->nBandCount = 1;
-        int nSrcBandNumber = (hVRTDS ? 1 : nBand);
+        int nSrcBandNumber = hVRTDS ? 1 : nBand;
         int nDstBandNumber = 1;
         psWarpOptions->panSrcBands = &nSrcBandNumber;
         psWarpOptions->panDstBands = &nDstBandNumber;
@@ -847,13 +968,14 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         psWarpOptions->pProgressArg = psExtraArg->pProgressData;
         psWarpOptions->pfnTransformer = GDALRasterIOTransformer;
         GDALRasterIOTransformerStruct sTransformer;
-        sTransformer.dfXOff = (bHasXOffVirtual) ? 0 : dfXOff;
-        sTransformer.dfYOff = (bHasYOffVirtual) ? 0 : dfYOff;
+        sTransformer.dfXOff = bHasXOffVirtual ? 0 : dfXOff;
+        sTransformer.dfYOff = bHasYOffVirtual ? 0 : dfYOff;
         sTransformer.dfXRatioDstToSrc = dfXRatioDstToSrc;
         sTransformer.dfYRatioDstToSrc = dfYRatioDstToSrc;
         psWarpOptions->pTransformerArg = &sTransformer;
 
-        GDALWarpOperationH hWarpOperation = GDALCreateWarpOperation(psWarpOptions);
+        GDALWarpOperationH hWarpOperation =
+            GDALCreateWarpOperation(psWarpOptions);
         eErr = GDALChunkAndWarpImage( hWarpOperation,
                                       nDestXOffVirtual, nDestYOffVirtual,
                                       nBufXSize, nBufYSize );
@@ -877,30 +999,34 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
             (psExtraArg->eResampleAlg == GRIORA_Mode) ? "MODE" :
             (psExtraArg->eResampleAlg == GRIORA_Gauss) ? "GAUSS" : "UNKNOWN";
 
-        int nKernelRadius;
+        int nKernelRadius = 0;
         GDALResampleFunction pfnResampleFunc =
                         GDALGetResampleFunction(pszResampling, &nKernelRadius);
         CPLAssert(pfnResampleFunc);
         GDALDataType eWrkDataType =
             GDALGetOvrWorkDataType(pszResampling, eDataType);
         int bHasNoData = FALSE;
-        float fNoDataValue = (float) GetNoDataValue(&bHasNoData);
+        float fNoDataValue = static_cast<float>( GetNoDataValue(&bHasNoData) );
         if( !bHasNoData )
             fNoDataValue = 0.0f;
 
         int nDstBlockXSize = nBufXSize;
         int nDstBlockYSize = nBufYSize;
-        int nFullResXChunk, nFullResYChunk;
+        int nFullResXChunk = 0;
+        int nFullResYChunk = 0;
         while( true )
         {
-            nFullResXChunk = 3 + (int)(nDstBlockXSize * dfXRatioDstToSrc);
-            nFullResYChunk = 3 + (int)(nDstBlockYSize * dfYRatioDstToSrc);
+            nFullResXChunk =
+                3 + static_cast<int>(nDstBlockXSize * dfXRatioDstToSrc);
+            nFullResYChunk =
+                3 + static_cast<int>(nDstBlockYSize * dfYRatioDstToSrc);
             if( (nDstBlockXSize == 1 && nDstBlockYSize == 1) ||
                 ((GIntBig)nFullResXChunk * nFullResYChunk <= 1024 * 1024) )
                 break;
-            /* When operating on the full width of a raster whose block width is */
-            /* the raster width, prefer doing chunks in height */
-            if( nFullResXChunk >= nXSize && nXSize == nBlockXSize && nDstBlockYSize > 1 )
+            // When operating on the full width of a raster whose block width is
+            // the raster width, prefer doing chunks in height.
+            if( nFullResXChunk >= nXSize && nXSize == nBlockXSize &&
+                nDstBlockYSize > 1 )
                 nDstBlockYSize /= 2;
             /* Otherwise cut the maximal dimension */
             else if( nDstBlockXSize > 1 && nFullResXChunk > nFullResYChunk )
@@ -909,35 +1035,35 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                 nDstBlockYSize /= 2;
         }
 
-        int nOvrFactor = MAX( (int)(0.5 + dfXRatioDstToSrc),
-                                (int)(0.5 + dfYRatioDstToSrc) );
+        int nOvrFactor = std::max( static_cast<int>(0.5 + dfXRatioDstToSrc),
+                                   static_cast<int>(0.5 + dfYRatioDstToSrc) );
         if( nOvrFactor == 0 ) nOvrFactor = 1;
-        int nFullResXSizeQueried = nFullResXChunk + 2 * nKernelRadius * nOvrFactor;
-        int nFullResYSizeQueried = nFullResYChunk + 2 * nKernelRadius * nOvrFactor;
+        int nFullResXSizeQueried =
+            nFullResXChunk + 2 * nKernelRadius * nOvrFactor;
+        int nFullResYSizeQueried =
+            nFullResYChunk + 2 * nKernelRadius * nOvrFactor;
 
         void * pChunk =
             VSI_MALLOC3_VERBOSE( GDALGetDataTypeSizeBytes(eWrkDataType),
                                  nFullResXSizeQueried, nFullResYSizeQueried );
         GByte * pabyChunkNoDataMask = NULL;
 
-        GDALRasterBand* poMaskBand = NULL;
-        int l_nMaskFlags = 0;
-        bool bUseNoDataMask = false;
-
-        poMaskBand = GetMaskBand();
-        l_nMaskFlags = GetMaskFlags();
+        GDALRasterBand* poMaskBand = GetMaskBand();
+        int l_nMaskFlags = GetMaskFlags();
 
-        bUseNoDataMask = ((l_nMaskFlags & GMF_ALL_VALID) == 0);
+        bool bUseNoDataMask = ((l_nMaskFlags & GMF_ALL_VALID) == 0);
         if (bUseNoDataMask)
         {
-            pabyChunkNoDataMask = (GByte *)
-                (GByte*) VSI_MALLOC2_VERBOSE( nFullResXSizeQueried, nFullResYSizeQueried );
+            pabyChunkNoDataMask = static_cast<GByte *>(
+                VSI_MALLOC2_VERBOSE( nFullResXSizeQueried,
+                                     nFullResYSizeQueried ) );
         }
         if( pChunk == NULL || (bUseNoDataMask && pabyChunkNoDataMask == NULL) )
         {
             GDALClose(poMEMDS);
             CPLFree(pChunk);
             CPLFree(pabyChunkNoDataMask);
+            VSIFree(pTempBuffer);
             return CE_Failure;
         }
 
@@ -955,8 +1081,12 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
             else
                 nDstYCount = nBufYSize - nDstYOff;
 
-            int nChunkYOff = nYOff + (int) (nDstYOff * dfYRatioDstToSrc);
-            int nChunkYOff2 = nYOff + 1 + (int) ceil((nDstYOff + nDstYCount) * dfYRatioDstToSrc);
+            int nChunkYOff =
+                nYOff + static_cast<int>(nDstYOff * dfYRatioDstToSrc);
+            int nChunkYOff2 =
+                nYOff + 1 +
+                static_cast<int>(
+                    ceil((nDstYOff + nDstYCount) * dfYRatioDstToSrc ) );
             if( nChunkYOff2 > nRasterYSize )
                 nChunkYOff2 = nRasterYSize;
             int nYCount = nChunkYOff2 - nChunkYOff;
@@ -973,25 +1103,30 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                 nChunkYSizeQueried = nRasterYSize - nChunkYOffQueried;
             CPLAssert(nChunkYSizeQueried <= nFullResYSizeQueried);
 
-            int nDstXOff;
+            int nDstXOff = 0;
             for( nDstXOff = 0; nDstXOff < nBufXSize && eErr == CE_None;
                 nDstXOff += nDstBlockXSize )
             {
-                int nDstXCount;
+                int nDstXCount = 0;
                 if  (nDstXOff + nDstBlockXSize <= nBufXSize)
                     nDstXCount = nDstBlockXSize;
                 else
                     nDstXCount = nBufXSize - nDstXOff;
 
-                int nChunkXOff = nXOff + (int) (nDstXOff * dfXRatioDstToSrc);
-                int nChunkXOff2 = nXOff + 1 + (int) ceil((nDstXOff + nDstXCount) * dfXRatioDstToSrc);
+                int nChunkXOff =
+                    nXOff + static_cast<int>(nDstXOff * dfXRatioDstToSrc);
+                int nChunkXOff2 =
+                    nXOff + 1 +
+                    static_cast<int>(
+                        ceil((nDstXOff + nDstXCount) * dfXRatioDstToSrc));
                 if( nChunkXOff2 > nRasterXSize )
                     nChunkXOff2 = nRasterXSize;
                 int nXCount = nChunkXOff2 - nChunkXOff;
                 CPLAssert(nXCount <= nFullResXChunk);
 
                 int nChunkXOffQueried = nChunkXOff - nKernelRadius * nOvrFactor;
-                int nChunkXSizeQueried = nXCount + 2 * nKernelRadius * nOvrFactor;
+                int nChunkXSizeQueried =
+                    nXCount + 2 * nKernelRadius * nOvrFactor;
                 if( nChunkXOffQueried < 0 )
                 {
                     nChunkXSizeQueried += nChunkXOffQueried;
@@ -1001,7 +1136,7 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                     nChunkXSizeQueried = nRasterXSize - nChunkXOffQueried;
                 CPLAssert(nChunkXSizeQueried <= nFullResXSizeQueried);
 
-                /* Read the source buffers */
+                // Read the source buffers.
                 eErr = RasterIO( GF_Read,
                                 nChunkXOffQueried, nChunkYOffQueried,
                                 nChunkXSizeQueried, nChunkYSizeQueried,
@@ -1010,7 +1145,7 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                                 eWrkDataType, 0, 0, NULL );
 
                 bool bSkipResample = false;
-                int bNoDataMaskFullyOpaque = FALSE;
+                bool bNoDataMaskFullyOpaque = false;
                 if (eErr == CE_None && bUseNoDataMask)
                 {
                     eErr = poMaskBand->RasterIO( GF_Read,
@@ -1038,49 +1173,55 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                         {
                             for(int j=0;j<nDstYCount;j++)
                             {
-                                GDALCopyWords(&fNoDataValue, GDT_Float32, 0,
-                                            (GByte*)pData + nLineSpace * (j + nDstYOff) +
-                                                        nDstXOff * nPixelSpace,
-                                            eBufType, (int)nPixelSpace,
-                                            nDstXCount);
+                                GDALCopyWords(
+                                    &fNoDataValue, GDT_Float32, 0,
+                                    static_cast<GByte*>(pData) +
+                                    nLineSpace * (j + nDstYOff) +
+                                    nDstXOff * nPixelSpace,
+                                    eBufType, static_cast<int>(nPixelSpace),
+                                    nDstXCount);
                             }
                             bSkipResample = true;
                         }
                         else
                         {
-                            bNoDataMaskFullyOpaque = TRUE;
+                            bNoDataMaskFullyOpaque = true;
                         }
                     }
                 }
 
                 if( !bSkipResample && eErr == CE_None )
                 {
-                    eErr = pfnResampleFunc( dfXRatioDstToSrc,
-                                            dfYRatioDstToSrc,
-                                            dfXOff - nXOff, /* == 0 if bHasXOffVirtual */
-                                            dfYOff - nYOff, /* == 0 if bHasYOffVirtual */
-                                            eWrkDataType,
-                                            pChunk,
-                                            (bNoDataMaskFullyOpaque) ? NULL : pabyChunkNoDataMask,
-                                            nChunkXOffQueried - ((bHasXOffVirtual) ? 0 : nXOff),
-                                            nChunkXSizeQueried,
-                                            nChunkYOffQueried - ((bHasYOffVirtual) ? 0 : nYOff),
-                                            nChunkYSizeQueried,
-                                            nDstXOff + nDestXOffVirtual,
-                                            nDstXOff + nDestXOffVirtual + nDstXCount,
-                                            nDstYOff + nDestYOffVirtual,
-                                            nDstYOff + nDestYOffVirtual + nDstYCount,
-                                            (GDALRasterBand *) hMEMBand,
-                                            pszResampling,
-                                            bHasNoData, fNoDataValue,
-                                            GetColorTable(),
-                                            eDataType );
+                    const bool bPropagateNoData = false;
+                    eErr = pfnResampleFunc(
+                        dfXRatioDstToSrc,
+                        dfYRatioDstToSrc,
+                        dfXOff - nXOff, /* == 0 if bHasXOffVirtual */
+                        dfYOff - nYOff, /* == 0 if bHasYOffVirtual */
+                        eWrkDataType,
+                        pChunk,
+                        bNoDataMaskFullyOpaque ? NULL : pabyChunkNoDataMask,
+                        nChunkXOffQueried - (bHasXOffVirtual ? 0 : nXOff),
+                        nChunkXSizeQueried,
+                        nChunkYOffQueried - (bHasYOffVirtual ? 0 : nYOff),
+                        nChunkYSizeQueried,
+                        nDstXOff + nDestXOffVirtual,
+                        nDstXOff + nDestXOffVirtual + nDstXCount,
+                        nDstYOff + nDestYOffVirtual,
+                        nDstYOff + nDestYOffVirtual + nDstYCount,
+                        (GDALRasterBand *) hMEMBand,
+                        pszResampling,
+                        bHasNoData, fNoDataValue,
+                        GetColorTable(),
+                        eDataType,
+                        bPropagateNoData);
                 }
 
                 nBlocksDone ++;
                 if( eErr == CE_None && psExtraArg->pfnProgress != NULL &&
-                    !psExtraArg->pfnProgress(1.0 * nBlocksDone / nTotalBlocks, "",
-                                             psExtraArg->pProgressData) )
+                    !psExtraArg->pfnProgress(
+                        1.0 * nBlocksDone / nTotalBlocks, "",
+                        psExtraArg->pProgressData) )
                 {
                     eErr = CE_Failure;
                 }
@@ -1091,7 +1232,19 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         CPLFree(pabyChunkNoDataMask);
     }
 
+    if( eBufType != eDataType )
+    {
+        CPL_IGNORE_RET_VAL(poMEMDS->GetRasterBand(1)->RasterIO(GF_Read,
+                          nDestXOffVirtual, nDestYOffVirtual,
+                          nBufXSize, nBufYSize,
+                          pData,
+                          nBufXSize, nBufYSize,
+                          eBufType,
+                          nPixelSpace, nLineSpace,
+                          NULL));
+    }
     GDALClose(poMEMDS);
+    VSIFree(pTempBuffer);
 
     return eErr;
 }
@@ -1100,28 +1253,28 @@ CPLErr GDALRasterBand::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
 /*                          RasterIOResampled()                         */
 /************************************************************************/
 
-CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
-                               int nXOff, int nYOff, int nXSize, int nYSize,
-                               void * pData, int nBufXSize, int nBufYSize,
-                               GDALDataType eBufType,
-                               int nBandCount, int *panBandMap,
-                               GSpacing nPixelSpace, GSpacing nLineSpace,
-                               GSpacing nBandSpace,
-                               GDALRasterIOExtraArg* psExtraArg )
+CPLErr GDALDataset::RasterIOResampled(
+    GDALRWFlag /* eRWFlag */,
+    int nXOff, int nYOff, int nXSize, int nYSize,
+    void *pData, int nBufXSize, int nBufYSize,
+    GDALDataType eBufType,
+    int nBandCount, int *panBandMap,
+    GSpacing nPixelSpace, GSpacing nLineSpace,
+    GSpacing nBandSpace,
+    GDALRasterIOExtraArg* psExtraArg )
 
 {
-    CPLErr eErr = CE_None;
-
 #if 0
     // Determine if we use warping resampling or overview resampling
-    int bUseWarp;
-    if( !GDALDataTypeIsComplex( eDataType ) )
-        bUseWarp = FALSE;
-    else
-        bUseWarp = TRUE;
+    bool bUseWarp = false;
+    if( GDALDataTypeIsComplex( eDataType ) )
+        bUseWarp = true;
 #endif
 
-    double dfXOff, dfYOff, dfXSize, dfYSize;
+    double dfXOff = nXOff;
+    double dfYOff = nYOff;
+    double dfXSize = nXSize;
+    double dfYSize = nYSize;
     if( psExtraArg->bFloatingPointWindowValidity )
     {
         dfXOff = psExtraArg->dfXOff;
@@ -1133,76 +1286,85 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         CPLAssert(nXSize - dfXSize < 1.0);
         CPLAssert(nYSize - dfYSize < 1.0);
     }
-    else
-    {
-        dfXOff = nXOff;
-        dfYOff = nYOff;
-        dfXSize = nXSize;
-        dfYSize = nYSize;
-    }
 
-    double dfXRatioDstToSrc = dfXSize / nBufXSize;
-    double dfYRatioDstToSrc = dfYSize / nBufYSize;
+    const double dfXRatioDstToSrc = dfXSize / nBufXSize;
+    const double dfYRatioDstToSrc = dfYSize / nBufYSize;
 
-    /* Determine the coordinates in the "virtual" output raster to see */
-    /* if there are not integers, in which case we will use them as a shift */
-    /* so that subwindow extracts give the exact same results as entire raster */
-    /* scaling */
+    // Determine the coordinates in the "virtual" output raster to see
+    // if there are not integers, in which case we will use them as a shift
+    // so that subwindow extracts give the exact same results as entire raster
+    // scaling.
     double dfDestXOff = dfXOff / dfXRatioDstToSrc;
     bool bHasXOffVirtual = false;
     int nDestXOffVirtual = 0;
-    if( fabs(dfDestXOff - (int)(dfDestXOff + 0.5)) < 1e-8 )
+    if( fabs(dfDestXOff - static_cast<int>(dfDestXOff + 0.5)) < 1e-8 )
     {
         bHasXOffVirtual = true;
         dfXOff = nXOff;
-        nDestXOffVirtual = (int)(dfDestXOff + 0.5);
+        nDestXOffVirtual = static_cast<int>(dfDestXOff + 0.5);
     }
 
     double dfDestYOff = dfYOff / dfYRatioDstToSrc;
     bool bHasYOffVirtual = false;
     int nDestYOffVirtual = 0;
-    if( fabs(dfDestYOff - (int)(dfDestYOff + 0.5)) < 1e-8 )
+    if( fabs(dfDestYOff - static_cast<int>(dfDestYOff + 0.5)) < 1e-8 )
     {
         bHasYOffVirtual = true;
         dfYOff = nYOff;
-        nDestYOffVirtual = (int)(dfDestYOff + 0.5);
+        nDestYOffVirtual = static_cast<int>(dfDestYOff + 0.5);
     }
 
-    /* Create a MEM dataset that wraps the output buffer */
-    GDALDataset* poMEMDS = MEMDataset::Create("", nDestXOffVirtual + nBufXSize,
-                                              nDestYOffVirtual + nBufYSize, 0,
-                                              eBufType, NULL);
-    GDALRasterBand** papoDstBands = (GDALRasterBand**) CPLMalloc( nBandCount * sizeof(GDALRasterBand*));
+    // Create a MEM dataset that wraps the output buffer.
+    GDALDataset* poMEMDS = MEMDataset::Create( "", nDestXOffVirtual + nBufXSize,
+                                               nDestYOffVirtual + nBufYSize, 0,
+                                               eBufType, NULL );
+    GDALRasterBand** papoDstBands =
+        static_cast<GDALRasterBand **>(
+            CPLMalloc( nBandCount * sizeof(GDALRasterBand*)) );
     for(int i=0;i<nBandCount;i++)
     {
-        char szBuffer[64];
-        int nRet;
-
-        nRet = CPLPrintPointer(szBuffer, (GByte*)pData - nPixelSpace * nDestXOffVirtual
-                                - nLineSpace * nDestYOffVirtual + nBandSpace * i, sizeof(szBuffer));
+        char szBuffer[64] = { '\0' };
+        int nRet = CPLPrintPointer(
+            szBuffer,
+            static_cast<GByte*>(pData) - nPixelSpace * nDestXOffVirtual
+            - nLineSpace * nDestYOffVirtual + nBandSpace * i, sizeof(szBuffer));
         szBuffer[nRet] = 0;
 
-        char* apszOptions[4];
-        char szBuffer0[64], szBuffer1[64], szBuffer2[64];
-        snprintf(szBuffer0, sizeof(szBuffer0), "DATAPOINTER=%s", szBuffer);
-        snprintf(szBuffer1, sizeof(szBuffer1), "PIXELOFFSET=" CPL_FRMT_GIB, (GIntBig)nPixelSpace);
-        snprintf(szBuffer2, sizeof(szBuffer2), "LINEOFFSET=" CPL_FRMT_GIB, (GIntBig)nLineSpace);
-        apszOptions[0] = szBuffer0;
-        apszOptions[1] = szBuffer1;
-        apszOptions[2] = szBuffer2;
-        apszOptions[3] = NULL;
+        char szBuffer0[64] = { '\0' };
+        snprintf( szBuffer0, sizeof(szBuffer0),
+                  "DATAPOINTER=%s", szBuffer );
+
+        char szBuffer1[64] = { '\0' };
+        snprintf( szBuffer1, sizeof(szBuffer1),
+                  "PIXELOFFSET=" CPL_FRMT_GIB,
+                  static_cast<GIntBig>(nPixelSpace) );
+
+        char szBuffer2[64] = { '\0' };
+        snprintf( szBuffer2, sizeof(szBuffer2),
+                  "LINEOFFSET=" CPL_FRMT_GIB,
+                  static_cast<GIntBig>(nLineSpace) );
+
+        char* apszOptions[4] = { szBuffer0, szBuffer1, szBuffer2, NULL };
 
         poMEMDS->AddBand(eBufType, apszOptions);
 
         GDALRasterBand* poSrcBand = GetRasterBand(panBandMap[i]);
         papoDstBands[i] = poMEMDS->GetRasterBand(i+1);
-        const char* pszNBITS = poSrcBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE");
+        const char* pszNBITS = poSrcBand->GetMetadataItem( "NBITS",
+                                                           "IMAGE_STRUCTURE" );
         if( pszNBITS )
-            poMEMDS->GetRasterBand(i+1)->SetMetadataItem("NBITS", pszNBITS, "IMAGE_STRUCTURE");
+            poMEMDS->GetRasterBand(i+1)->SetMetadataItem( "NBITS", pszNBITS,
+                                                          "IMAGE_STRUCTURE" );
     }
 
+    CPLErr eErr = CE_None;
+
+    // TODO(schwehr): Why disabled?  Why not just delete?
+    // Looks like this code was initially added as disable by copying
+    // from RasterIO here:
+    // https://trac.osgeo.org/gdal/changeset/29572
 #if 0
-    /* Do the resampling */
+    // Do the resampling.
     if( bUseWarp )
     {
         VRTDatasetH hVRTDS = NULL;
@@ -1250,8 +1412,8 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         psWarpOptions->pProgressArg = psExtraArg->pProgressData;
         psWarpOptions->pfnTransformer = GDALRasterIOTransformer;
         GDALRasterIOTransformerStruct sTransformer;
-        sTransformer.dfXOff = (bHasXOffVirtual) ? 0 : dfXOff;
-        sTransformer.dfYOff = (bHasYOffVirtual) ? 0 : dfYOff;
+        sTransformer.dfXOff = bHasXOffVirtual ? 0 : dfXOff;
+        sTransformer.dfYOff = bHasYOffVirtual ? 0 : dfYOff;
         sTransformer.dfXRatioDstToSrc = dfXRatioDstToSrc;
         sTransformer.dfYRatioDstToSrc = dfYRatioDstToSrc;
         psWarpOptions->pTransformerArg = &sTransformer;
@@ -1302,14 +1464,17 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
         int nFullResXChunk, nFullResYChunk;
         while( true )
         {
-            nFullResXChunk = 3 + (int)(nDstBlockXSize * dfXRatioDstToSrc);
-            nFullResYChunk = 3 + (int)(nDstBlockYSize * dfYRatioDstToSrc);
+            nFullResXChunk =
+                3 + static_cast<int>(nDstBlockXSize * dfXRatioDstToSrc);
+            nFullResYChunk =
+                3 + static_cast<int>(nDstBlockYSize * dfYRatioDstToSrc);
             if( (nDstBlockXSize == 1 && nDstBlockYSize == 1) ||
                 ((GIntBig)nFullResXChunk * nFullResYChunk <= 1024 * 1024) )
                 break;
-            /* When operating on the full width of a raster whose block width is */
-            /* the raster width, prefer doing chunks in height */
-            if( nFullResXChunk >= nXSize && nXSize == nBlockXSize && nDstBlockYSize > 1 )
+            // When operating on the full width of a raster whose block width is
+            // the raster width, prefer doing chunks in height.
+            if( nFullResXChunk >= nXSize && nXSize == nBlockXSize &&
+                nDstBlockYSize > 1 )
                 nDstBlockYSize /= 2;
             /* Otherwise cut the maximal dimension */
             else if( nDstBlockXSize > 1 && nFullResXChunk > nFullResYChunk )
@@ -1318,8 +1483,8 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                 nDstBlockYSize /= 2;
         }
 
-        int nOvrFactor = MAX( (int)(0.5 + dfXRatioDstToSrc),
-                                (int)(0.5 + dfYRatioDstToSrc) );
+        int nOvrFactor = std::max( static_cast<int>(0.5 + dfXRatioDstToSrc),
+                                   static_cast<int>(0.5 + dfYRatioDstToSrc) );
         if( nOvrFactor == 0 ) nOvrFactor = 1;
         int nFullResXSizeQueried = nFullResXChunk + 2 * nKernelRadius * nOvrFactor;
         int nFullResYSizeQueried = nFullResYChunk + 2 * nKernelRadius * nOvrFactor;
@@ -1330,14 +1495,10 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                 nFullResXSizeQueried, nFullResYSizeQueried );
         GByte * pabyChunkNoDataMask = NULL;
 
-        GDALRasterBand* poMaskBand = NULL;
-        int nMaskFlags = 0;
-        bool bUseNoDataMask = false;
+        GDALRasterBand* poMaskBand = poFirstSrcBand->GetMaskBand();
+        int nMaskFlags = poFirstSrcBand->GetMaskFlags();
 
-        poMaskBand = poFirstSrcBand->GetMaskBand();
-        nMaskFlags = poFirstSrcBand->GetMaskFlags();
-
-        bUseNoDataMask = ((nMaskFlags & GMF_ALL_VALID) == 0);
+        bool bUseNoDataMask = ((nMaskFlags & GMF_ALL_VALID) == 0);
         if (bUseNoDataMask)
         {
             pabyChunkNoDataMask = (GByte *)
@@ -1365,8 +1526,12 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
             else
                 nDstYCount = nBufYSize - nDstYOff;
 
-            int nChunkYOff = nYOff + (int) (nDstYOff * dfYRatioDstToSrc);
-            int nChunkYOff2 = nYOff + 1 + (int) ceil((nDstYOff + nDstYCount) * dfYRatioDstToSrc);
+            int nChunkYOff =
+                nYOff + static_cast<int>(nDstYOff * dfYRatioDstToSrc);
+            int nChunkYOff2 =
+                nYOff + 1 +
+                static_cast<int>(
+                    ceil((nDstYOff + nDstYCount) * dfYRatioDstToSrc) );
             if( nChunkYOff2 > nRasterYSize )
                 nChunkYOff2 = nRasterYSize;
             int nYCount = nChunkYOff2 - nChunkYOff;
@@ -1393,8 +1558,11 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                 else
                     nDstXCount = nBufXSize - nDstXOff;
 
-                int nChunkXOff = nXOff + (int) (nDstXOff * dfXRatioDstToSrc);
-                int nChunkXOff2 = nXOff + 1 + (int) ceil((nDstXOff + nDstXCount) * dfXRatioDstToSrc);
+                int nChunkXOff =
+                    nXOff + static_cast<int>(nDstXOff * dfXRatioDstToSrc);
+                int nChunkXOff2 =
+                    nXOff + 1 + static_cast<int>(
+                        ceil((nDstXOff + nDstXCount) * dfXRatioDstToSrc) );
                 if( nChunkXOff2 > nRasterXSize )
                     nChunkXOff2 = nRasterXSize;
                 int nXCount = nChunkXOff2 - nChunkXOff;
@@ -1412,7 +1580,7 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                 CPLAssert(nChunkXSizeQueried <= nFullResXSizeQueried);
 
                 bool bSkipResample = false;
-                int bNoDataMaskFullyOpaque = FALSE;
+                bool bNoDataMaskFullyOpaque = false;
                 if (eErr == CE_None && bUseNoDataMask)
                 {
                     eErr = poMaskBand->RasterIO( GF_Read,
@@ -1426,9 +1594,9 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                                                  GDT_Byte, 0, 0, NULL );
 
                     /* Optimizations if mask if fully opaque or transparent */
-                    int nPixels = nChunkXSizeQueried * nChunkYSizeQueried;
-                    GByte bVal = pabyChunkNoDataMask[0];
-                    int i = 1;
+                    const int nPixels = nChunkXSizeQueried * nChunkYSizeQueried;
+                    const GByte bVal = pabyChunkNoDataMask[0];
+                    int i = 1;  // Used after for.
                     for( ; i < nPixels; i++ )
                     {
                         if( pabyChunkNoDataMask[i] != bVal )
@@ -1438,24 +1606,27 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                     {
                         if( bVal == 0 )
                         {
-                            float fNoDataValue = 0.f;
-                            for(int iBand=0;iBand<nBandCount;iBand++)
+                            float fNoDataValue = 0.0f;
+                            for( int iBand = 0; iBand < nBandCount; iBand++ )
                             {
-                                for(int j=0;j<nDstYCount;j++)
+                                for( int j = 0; j < nDstYCount; j++ )
                                 {
-                                    GDALCopyWords(&fNoDataValue, GDT_Float32, 0,
-                                                (GByte*)pData + iBand * nBandSpace +
-                                                    nLineSpace * (j + nDstYOff) +
-                                                    nDstXOff * nPixelSpace,
-                                                eBufType, (int)nPixelSpace,
-                                                nDstXCount);
+                                    GDALCopyWords(
+                                        &fNoDataValue, GDT_Float32, 0,
+                                        static_cast<GByte *>(pData) +
+                                        iBand * nBandSpace +
+                                        nLineSpace * (j + nDstYOff) +
+                                        nDstXOff * nPixelSpace,
+                                        eBufType,
+                                        static_cast<int>(nPixelSpace),
+                                        nDstXCount);
                                 }
                             }
                             bSkipResample = true;
                         }
                         else
                         {
-                            bNoDataMaskFullyOpaque = TRUE;
+                            bNoDataMaskFullyOpaque = true;
                         }
                     }
                 }
@@ -1464,40 +1635,43 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                 {
                     /* Read the source buffers */
                     eErr = RasterIO( GF_Read,
-                                    nChunkXOffQueried, nChunkYOffQueried,
-                                    nChunkXSizeQueried, nChunkYSizeQueried,
-                                    pChunk,
-                                    nChunkXSizeQueried, nChunkYSizeQueried,
-                                    eWrkDataType,
-                                    nBandCount, panBandMap,
-                                    0, 0, 0, NULL );
+                                     nChunkXOffQueried, nChunkYOffQueried,
+                                     nChunkXSizeQueried, nChunkYSizeQueried,
+                                     pChunk,
+                                     nChunkXSizeQueried, nChunkYSizeQueried,
+                                     eWrkDataType,
+                                     nBandCount, panBandMap,
+                                     0, 0, 0, NULL );
                 }
 
 #ifdef GDAL_ENABLE_RESAMPLING_MULTIBAND
-                if( pfnResampleFuncMultiBands && !bSkipResample && eErr == CE_None )
+                if( pfnResampleFuncMultiBands &&
+                    !bSkipResample &&
+                    eErr == CE_None )
                 {
-                    eErr = pfnResampleFuncMultiBands( dfXRatioDstToSrc,
-                                                      dfYRatioDstToSrc,
-                                                      dfXOff - nXOff, /* == 0 if bHasXOffVirtual */
-                                                      dfYOff - nYOff, /* == 0 if bHasYOffVirtual */
-                                                      eWrkDataType,
-                                                      (GByte*)pChunk,
-                                                      nBandCount,
-                                                      (bNoDataMaskFullyOpaque) ? NULL : pabyChunkNoDataMask,
-                                                      nChunkXOffQueried - ((bHasXOffVirtual) ? 0 : nXOff),
-                                                      nChunkXSizeQueried,
-                                                      nChunkYOffQueried - ((bHasYOffVirtual) ? 0 : nYOff),
-                                                      nChunkYSizeQueried,
-                                                      nDstXOff + nDestXOffVirtual,
-                                                      nDstXOff + nDestXOffVirtual + nDstXCount,
-                                                      nDstYOff + nDestYOffVirtual,
-                                                      nDstYOff + nDestYOffVirtual + nDstYCount,
-                                                      papoDstBands,
-                                                      pszResampling,
-                                                      FALSE /*bHasNoData*/,
-                                                      0.f /* fNoDataValue */,
-                                                      NULL /* color table*/,
-                                                      eDataType );
+                    eErr = pfnResampleFuncMultiBands(
+                        dfXRatioDstToSrc,
+                        dfYRatioDstToSrc,
+                        dfXOff - nXOff, /* == 0 if bHasXOffVirtual */
+                        dfYOff - nYOff, /* == 0 if bHasYOffVirtual */
+                        eWrkDataType,
+                        (GByte*)pChunk,
+                        nBandCount,
+                        bNoDataMaskFullyOpaque ? NULL : pabyChunkNoDataMask,
+                        nChunkXOffQueried - (bHasXOffVirtual ? 0 : nXOff),
+                        nChunkXSizeQueried,
+                        nChunkYOffQueried - (bHasYOffVirtual ? 0 : nYOff),
+                        nChunkYSizeQueried,
+                        nDstXOff + nDestXOffVirtual,
+                        nDstXOff + nDestXOffVirtual + nDstXCount,
+                        nDstYOff + nDestYOffVirtual,
+                        nDstYOff + nDestYOffVirtual + nDstYCount,
+                        papoDstBands,
+                        pszResampling,
+                        FALSE /*bHasNoData*/,
+                        0.f /* fNoDataValue */,
+                        NULL /* color table*/,
+                        eDataType );
                 }
                 else
 #endif
@@ -1506,36 +1680,42 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
                         static_cast<size_t>(nChunkXSizeQueried) *
                         nChunkYSizeQueried *
                         GDALGetDataTypeSizeBytes(eWrkDataType);
-                    for(int i=0; i<nBandCount && !bSkipResample && eErr == CE_None; i++ )
+                    for( int i = 0;
+                         i < nBandCount && !bSkipResample && eErr == CE_None;
+                         i++ )
                     {
-                        eErr = pfnResampleFunc( dfXRatioDstToSrc,
-                                                dfYRatioDstToSrc,
-                                                dfXOff - nXOff, /* == 0 if bHasXOffVirtual */
-                                                dfYOff - nYOff, /* == 0 if bHasYOffVirtual */
-                                                eWrkDataType,
-                                                (GByte*)pChunk + i * nChunkBandOffset,
-                                                (bNoDataMaskFullyOpaque) ? NULL : pabyChunkNoDataMask,
-                                                nChunkXOffQueried - ((bHasXOffVirtual) ? 0 : nXOff),
-                                                nChunkXSizeQueried,
-                                                nChunkYOffQueried - ((bHasYOffVirtual) ? 0 : nYOff),
-                                                nChunkYSizeQueried,
-                                                nDstXOff + nDestXOffVirtual,
-                                                nDstXOff + nDestXOffVirtual + nDstXCount,
-                                                nDstYOff + nDestYOffVirtual,
-                                                nDstYOff + nDestYOffVirtual + nDstYCount,
-                                                poMEMDS->GetRasterBand(i+1),
-                                                pszResampling,
-                                                FALSE /*bHasNoData*/,
-                                                0.f /* fNoDataValue */,
-                                                NULL /* color table*/,
-                                                eDataType );
+                        const bool bPropagateNoData = false;
+                        eErr = pfnResampleFunc(
+                            dfXRatioDstToSrc,
+                            dfYRatioDstToSrc,
+                            dfXOff - nXOff, /* == 0 if bHasXOffVirtual */
+                            dfYOff - nYOff, /* == 0 if bHasYOffVirtual */
+                            eWrkDataType,
+                            (GByte*)pChunk + i * nChunkBandOffset,
+                            bNoDataMaskFullyOpaque ? NULL : pabyChunkNoDataMask,
+                            nChunkXOffQueried - (bHasXOffVirtual ? 0 : nXOff),
+                            nChunkXSizeQueried,
+                            nChunkYOffQueried - (bHasYOffVirtual ? 0 : nYOff),
+                            nChunkYSizeQueried,
+                            nDstXOff + nDestXOffVirtual,
+                            nDstXOff + nDestXOffVirtual + nDstXCount,
+                            nDstYOff + nDestYOffVirtual,
+                            nDstYOff + nDestYOffVirtual + nDstYCount,
+                            poMEMDS->GetRasterBand(i+1),
+                            pszResampling,
+                            FALSE /*bHasNoData*/,
+                            0.f /* fNoDataValue */,
+                            NULL /* color table*/,
+                            eDataType,
+                            bPropagateNoData );
                     }
                 }
 
                 nBlocksDone ++;
                 if( eErr == CE_None && psExtraArg->pfnProgress != NULL &&
-                    !psExtraArg->pfnProgress(1.0 * nBlocksDone / nTotalBlocks, "",
-                                             psExtraArg->pProgressData) )
+                    !psExtraArg->pfnProgress(
+                        1.0 * nBlocksDone / nTotalBlocks, "",
+                        psExtraArg->pProgressData) )
                 {
                     eErr = CE_Failure;
                 }
@@ -1551,6 +1731,7 @@ CPLErr GDALDataset::RasterIOResampled( CPL_UNUSED GDALRWFlag eRWFlag,
 
     return eErr;
 }
+//! @endcond
 
 /************************************************************************/
 /*                           GDALSwapWords()                            */
@@ -1580,8 +1761,7 @@ void CPL_STDCALL GDALSwapWords( void *pData, int nWordSize, int nWordCount,
     if (nWordCount > 0)
         VALIDATE_POINTER0( pData , "GDALSwapWords" );
 
-    int         i;
-    GByte       *pabyData = (GByte *) pData;
+    GByte *pabyData = static_cast<GByte *>( pData );
 
     switch( nWordSize )
     {
@@ -1590,64 +1770,57 @@ void CPL_STDCALL GDALSwapWords( void *pData, int nWordSize, int nWordCount,
 
       case 2:
         CPLAssert( nWordSkip >= 2 || nWordCount == 1 );
-        for( i = 0; i < nWordCount; i++ )
+        for( int i = 0; i < nWordCount; i++ )
         {
-            GByte       byTemp;
-
-            byTemp = pabyData[0];
-            pabyData[0] = pabyData[1];
-            pabyData[1] = byTemp;
-
+            CPL_SWAP16PTR(pabyData);
             pabyData += nWordSkip;
         }
         break;
 
       case 4:
         CPLAssert( nWordSkip >= 4 || nWordCount == 1 );
-        for( i = 0; i < nWordCount; i++ )
+        if( CPL_IS_ALIGNED(pabyData, 4) && (nWordSkip % 4) == 0 )
         {
-            GByte       byTemp;
-
-            byTemp = pabyData[0];
-            pabyData[0] = pabyData[3];
-            pabyData[3] = byTemp;
-
-            byTemp = pabyData[1];
-            pabyData[1] = pabyData[2];
-            pabyData[2] = byTemp;
-
-            pabyData += nWordSkip;
+            for( int i = 0; i < nWordCount; i++ )
+            {
+                *((GUInt32*)pabyData) = CPL_SWAP32(*((GUInt32*)pabyData));
+                pabyData += nWordSkip;
+            }
+        }
+        else
+        {
+            for( int i = 0; i < nWordCount; i++ )
+            {
+                CPL_SWAP32PTR(pabyData);
+                pabyData += nWordSkip;
+            }
         }
         break;
 
       case 8:
         CPLAssert( nWordSkip >= 8 || nWordCount == 1 );
-        for( i = 0; i < nWordCount; i++ )
+#ifdef CPL_HAS_GINT64
+        if( CPL_IS_ALIGNED(pabyData, 8) && (nWordSkip % 8) == 0 )
         {
-            GByte       byTemp;
-
-            byTemp = pabyData[0];
-            pabyData[0] = pabyData[7];
-            pabyData[7] = byTemp;
-
-            byTemp = pabyData[1];
-            pabyData[1] = pabyData[6];
-            pabyData[6] = byTemp;
-
-            byTemp = pabyData[2];
-            pabyData[2] = pabyData[5];
-            pabyData[5] = byTemp;
-
-            byTemp = pabyData[3];
-            pabyData[3] = pabyData[4];
-            pabyData[4] = byTemp;
-
-            pabyData += nWordSkip;
+            for( int i = 0; i < nWordCount; i++ )
+            {
+                *((GUInt64*)pabyData) = CPL_SWAP64(*((GUInt64*)pabyData));
+                pabyData += nWordSkip;
+            }
+        }
+        else
+#endif
+        {
+            for( int i = 0; i < nWordCount; i++ )
+            {
+                CPL_SWAP64PTR(pabyData);
+                pabyData += nWordSkip;
+            }
         }
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
     }
 }
 
@@ -1675,11 +1848,12 @@ void CPL_STDCALL GDALSwapWords( void *pData, int nWordSize, int nWordCount,
 void CPL_STDCALL GDALSwapWordsEx( void *pData, int nWordSize, size_t nWordCount,
                                   int nWordSkip )
 {
-    GByte* pabyData = reinterpret_cast<GByte*>(pData);
+    GByte* pabyData = static_cast<GByte*>(pData);
     while( nWordCount )
     {
-        /* Pick-up a multiple of 8 as max chunk size */
-        int nWordCountSmall = (nWordCount > (1 << 30)) ? (1 << 30) : static_cast<int>(nWordCount);
+        // Pick-up a multiple of 8 as max chunk size.
+        const int nWordCountSmall =
+            (nWordCount > (1 << 30)) ? (1 << 30) : static_cast<int>(nWordCount);
         GDALSwapWords(pabyData, nWordSize, nWordCountSmall, nWordSkip);
         pabyData += static_cast<size_t>(nWordSkip) * nWordCountSmall;
         nWordCount -= nWordCountSmall;
@@ -1715,13 +1889,14 @@ namespace {
  * @note
  * This is a private function, and should not be exposed outside of rasterio.cpp.
  * External users should call the GDALCopyWords driver function.
- * @note
  */
 
 template <class Tin, class Tout>
-static void GDALCopyWordsT(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
-                           Tout* const CPL_RESTRICT pDstData, int nDstPixelStride,
-                           int nWordCount)
+static void inline GDALCopyWordsGenericT( const Tin* const CPL_RESTRICT pSrcData,
+                            int nSrcPixelStride,
+                            Tout* const CPL_RESTRICT pDstData,
+                            int nDstPixelStride,
+                            int nWordCount)
 {
     std::ptrdiff_t nDstOffset = 0;
 
@@ -1729,8 +1904,10 @@ static void GDALCopyWordsT(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixel
     char* const pDstDataPtr = reinterpret_cast<char*>(pDstData);
     for (std::ptrdiff_t n = 0; n < nWordCount; n++  )
     {
-        const Tin tValue = *reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
-        Tout* const pOutPixel = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
+        const Tin tValue =
+            *reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
+        Tout* const pOutPixel =
+            reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
 
         GDALCopyWord(tValue, *pOutPixel);
 
@@ -1738,23 +1915,39 @@ static void GDALCopyWordsT(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixel
     }
 }
 
+template <class Tin, class Tout>
+static void inline GDALCopyWordsT( const Tin* const CPL_RESTRICT pSrcData,
+                            int nSrcPixelStride,
+                            Tout* const CPL_RESTRICT pDstData,
+                            int nDstPixelStride,
+                            int nWordCount)
+{
+    GDALCopyWordsGenericT(pSrcData, nSrcPixelStride,
+                          pDstData, nDstPixelStride,
+                          nWordCount);
+}
 
 template <class Tin, class Tout>
-static void GDALCopyWordsT_4atatime(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
-                           Tout* const CPL_RESTRICT pDstData, int nDstPixelStride,
-                           int nWordCount)
+static void inline GDALCopyWordsT_4atatime( const Tin* const CPL_RESTRICT pSrcData,
+                                     int nSrcPixelStride,
+                                     Tout* const CPL_RESTRICT pDstData,
+                                     int nDstPixelStride,
+                                     int nWordCount )
 {
     std::ptrdiff_t nDstOffset = 0;
 
     const char* const pSrcDataPtr = reinterpret_cast<const char*>(pSrcData);
     char* const pDstDataPtr = reinterpret_cast<char*>(pDstData);
     std::ptrdiff_t n = 0;
-    if( nSrcPixelStride == (int)sizeof(Tin) && nDstPixelStride == (int)sizeof(Tout) )
+    if( nSrcPixelStride == static_cast<int>(sizeof(Tin)) &&
+        nDstPixelStride == static_cast<int>(sizeof(Tout)) )
     {
         for (; n < nWordCount-3; n+=4)
         {
-            const Tin* pInValues = reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
-            Tout* const pOutPixels = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
+            const Tin* pInValues =
+                reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
+            Tout* const pOutPixels =
+                reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
 
             GDALCopy4Words(pInValues, pOutPixels);
 
@@ -1763,8 +1956,10 @@ static void GDALCopyWordsT_4atatime(const Tin* const CPL_RESTRICT pSrcData, int
     }
     for( ; n < nWordCount; n++  )
     {
-        const Tin tValue = *reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
-        Tout* const pOutPixel = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
+        const Tin tValue =
+            *reinterpret_cast<const Tin*>(pSrcDataPtr + (n * nSrcPixelStride));
+        Tout* const pOutPixel =
+            reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
 
         GDALCopyWord(tValue, *pOutPixel);
 
@@ -1772,28 +1967,129 @@ static void GDALCopyWordsT_4atatime(const Tin* const CPL_RESTRICT pSrcData, int
     }
 }
 
-static void GDALCopyWordsT(const float* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
-                           GByte* const CPL_RESTRICT pDstData, int nDstPixelStride,
-                           int nWordCount)
+#if defined(__x86_64) || defined(_M_X64)
+
+#include <emmintrin.h>
+
+template<> void GDALCopyWordsT( const GByte* const CPL_RESTRICT pSrcData,
+                                int nSrcPixelStride,
+                                int* const CPL_RESTRICT pDstData,
+                                int nDstPixelStride,
+                                int nWordCount )
 {
-    GDALCopyWordsT_4atatime(pSrcData, nSrcPixelStride,
-                            pDstData, nDstPixelStride, nWordCount);
+    if( nSrcPixelStride == static_cast<int>(sizeof(GByte)) &&
+        nDstPixelStride == static_cast<int>(sizeof(int)) )
+    {
+        int n = 0;
+        const __m128i xmm_zero = _mm_setzero_si128 ();
+        GByte* CPL_RESTRICT pabyDstDataPtr = reinterpret_cast<GByte*>(pDstData);
+        for (; n < nWordCount-15; n+=16)
+        {
+            __m128i xmm = _mm_loadu_si128( (const __m128i*) (pSrcData + n) );
+            __m128i xmm_low = _mm_unpacklo_epi8(xmm, xmm_zero);
+            __m128i xmm_high= _mm_unpackhi_epi8(xmm, xmm_zero);
+            __m128i xmm0 = _mm_unpacklo_epi16(xmm_low, xmm_zero);
+            __m128i xmm1 = _mm_unpackhi_epi16(xmm_low, xmm_zero);
+            __m128i xmm2 = _mm_unpacklo_epi16(xmm_high, xmm_zero);
+            __m128i xmm3 = _mm_unpackhi_epi16(xmm_high, xmm_zero);
+            _mm_storeu_si128( reinterpret_cast<__m128i*>(pabyDstDataPtr + n * 4),
+                              xmm0 );
+            _mm_storeu_si128( reinterpret_cast<__m128i*>(pabyDstDataPtr + n * 4 + 16),
+                              xmm1 );
+            _mm_storeu_si128( reinterpret_cast<__m128i*>(pabyDstDataPtr + n * 4 + 32),
+                              xmm2 );
+            _mm_storeu_si128( reinterpret_cast<__m128i*>(pabyDstDataPtr + n * 4 + 48),
+                              xmm3 );
+        }
+        for( ; n < nWordCount; n++  )
+        {
+            pDstData[n] = pSrcData[n];
+        }
+    }
+    else
+    {
+        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride,
+                              pDstData, nDstPixelStride,
+                              nWordCount);
+    }
 }
 
-static void GDALCopyWordsT(const float* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
-                           GInt16* const CPL_RESTRICT pDstData, int nDstPixelStride,
-                           int nWordCount)
+template<> void GDALCopyWordsT( const GByte* const CPL_RESTRICT pSrcData,
+                                int nSrcPixelStride,
+                                float* const CPL_RESTRICT pDstData,
+                                int nDstPixelStride,
+                                int nWordCount )
 {
-    GDALCopyWordsT_4atatime(pSrcData, nSrcPixelStride,
-                            pDstData, nDstPixelStride, nWordCount);
+    if( nSrcPixelStride == static_cast<int>(sizeof(GByte)) &&
+        nDstPixelStride == static_cast<int>(sizeof(float)) )
+    {
+        int n = 0;
+        const __m128i xmm_zero = _mm_setzero_si128 ();
+        GByte* CPL_RESTRICT pabyDstDataPtr = reinterpret_cast<GByte*>(pDstData);
+        for (; n < nWordCount-15; n+=16)
+        {
+            __m128i xmm = _mm_loadu_si128( (const __m128i*) (pSrcData + n) );
+            __m128i xmm_low = _mm_unpacklo_epi8(xmm, xmm_zero);
+            __m128i xmm_high= _mm_unpackhi_epi8(xmm, xmm_zero);
+            __m128i xmm0 = _mm_unpacklo_epi16(xmm_low, xmm_zero);
+            __m128i xmm1 = _mm_unpackhi_epi16(xmm_low, xmm_zero);
+            __m128i xmm2 = _mm_unpacklo_epi16(xmm_high, xmm_zero);
+            __m128i xmm3 = _mm_unpackhi_epi16(xmm_high, xmm_zero);
+            __m128 xmm0_f = _mm_cvtepi32_ps(xmm0);
+            __m128 xmm1_f = _mm_cvtepi32_ps(xmm1);
+            __m128 xmm2_f = _mm_cvtepi32_ps(xmm2);
+            __m128 xmm3_f = _mm_cvtepi32_ps(xmm3);
+            _mm_storeu_ps( reinterpret_cast<float*>(pabyDstDataPtr + n * 4),
+                           xmm0_f );
+            _mm_storeu_ps( reinterpret_cast<float*>(pabyDstDataPtr + n * 4 + 16),
+                           xmm1_f );
+            _mm_storeu_ps( reinterpret_cast<float*>(pabyDstDataPtr + n * 4 + 32),
+                           xmm2_f );
+            _mm_storeu_ps( reinterpret_cast<float*>(pabyDstDataPtr + n * 4 + 48),
+                           xmm3_f );
+        }
+        for( ; n < nWordCount; n++  )
+        {
+            pDstData[n] = pSrcData[n];
+        }
+    }
+    else
+    {
+        GDALCopyWordsGenericT(pSrcData, nSrcPixelStride,
+                              pDstData, nDstPixelStride,
+                              nWordCount);
+    }
 }
+#endif // defined(__x86_64) || defined(_M_X64)
 
-static void GDALCopyWordsT(const float* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
-                           GUInt16* const CPL_RESTRICT pDstData, int nDstPixelStride,
-                           int nWordCount)
+template<> void GDALCopyWordsT( const float* const CPL_RESTRICT pSrcData,
+                                int nSrcPixelStride,
+                                GByte* const CPL_RESTRICT pDstData,
+                                int nDstPixelStride,
+                                int nWordCount )
 {
-    GDALCopyWordsT_4atatime(pSrcData, nSrcPixelStride,
-                            pDstData, nDstPixelStride, nWordCount);
+    GDALCopyWordsT_4atatime( pSrcData, nSrcPixelStride,
+                             pDstData, nDstPixelStride, nWordCount );
+}
+
+template<> void GDALCopyWordsT( const float* const CPL_RESTRICT pSrcData,
+                                int nSrcPixelStride,
+                                GInt16* const CPL_RESTRICT pDstData,
+                                int nDstPixelStride,
+                                int nWordCount )
+{
+    GDALCopyWordsT_4atatime( pSrcData, nSrcPixelStride,
+                             pDstData, nDstPixelStride, nWordCount );
+}
+
+template<> void GDALCopyWordsT( const float* const CPL_RESTRICT pSrcData,
+                                int nSrcPixelStride,
+                                GUInt16* const CPL_RESTRICT pDstData,
+                                int nDstPixelStride,
+                                int nWordCount )
+{
+    GDALCopyWordsT_4atatime( pSrcData, nSrcPixelStride,
+                             pDstData, nDstPixelStride, nWordCount );
 }
 
 /************************************************************************/
@@ -1815,23 +2111,22 @@ static void GDALCopyWordsT(const float* const CPL_RESTRICT pSrcData, int nSrcPix
  *
  */
 template <class Tin, class Tout>
-inline void GDALCopyWordsComplexT(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
-                                  Tout* const CPL_RESTRICT pDstData, int nDstPixelStride,
-                                  int nWordCount)
+inline void GDALCopyWordsComplexT( const Tin* const CPL_RESTRICT pSrcData,
+                                   int nSrcPixelStride,
+                                   Tout* const CPL_RESTRICT pDstData,
+                                   int nDstPixelStride,
+                                   int nWordCount )
 {
     std::ptrdiff_t nDstOffset = 0;
     const char* const pSrcDataPtr = reinterpret_cast<const char*>(pSrcData);
     char* const pDstDataPtr = reinterpret_cast<char*>(pDstData);
 
-    // Determine the minimum and maximum value we can have based
-    // on the constraints of Tin and Tout.
-    Tin tMaxValue, tMinValue;
-    GDALGetDataLimits<Tin, Tout>(tMaxValue, tMinValue);
-
     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     {
-        const Tin* const pPixelIn = reinterpret_cast<const Tin*>(pSrcDataPtr + n * nSrcPixelStride);
-        Tout* const pPixelOut = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
+        const Tin* const pPixelIn =
+            reinterpret_cast<const Tin*>(pSrcDataPtr + n * nSrcPixelStride);
+        Tout* const pPixelOut =
+            reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
 
         GDALCopyWord(pPixelIn[0], pPixelOut[0]);
         GDALCopyWord(pPixelIn[1], pPixelOut[1]);
@@ -1859,9 +2154,11 @@ inline void GDALCopyWordsComplexT(const Tin* const CPL_RESTRICT pSrcData, int nS
  *
  */
 template <class Tin, class Tout>
-inline void GDALCopyWordsComplexOutT(const Tin* const CPL_RESTRICT pSrcData, int nSrcPixelStride,
-                                     Tout* const CPL_RESTRICT pDstData, int nDstPixelStride,
-                                     int nWordCount)
+inline void GDALCopyWordsComplexOutT( const Tin* const CPL_RESTRICT pSrcData,
+                                      int nSrcPixelStride,
+                                      Tout* const CPL_RESTRICT pDstData,
+                                      int nDstPixelStride,
+                                      int nWordCount )
 {
     std::ptrdiff_t nDstOffset = 0;
 
@@ -1872,8 +2169,10 @@ inline void GDALCopyWordsComplexOutT(const Tin* const CPL_RESTRICT pSrcData, int
 
     for (std::ptrdiff_t n = 0; n < nWordCount; n++)
     {
-        const Tin tValue = *reinterpret_cast<const Tin*>(pSrcDataPtr + n * nSrcPixelStride);
-        Tout* const pPixelOut = reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
+        const Tin tValue =
+            *reinterpret_cast<const Tin*>(pSrcDataPtr + n * nSrcPixelStride);
+        Tout* const pPixelOut =
+            reinterpret_cast<Tout*>(pDstDataPtr + nDstOffset);
         GDALCopyWord(tValue, *pPixelOut);
 
         pPixelOut[1] = tOutZero;
@@ -1899,106 +2198,116 @@ inline void GDALCopyWordsComplexOutT(const Tin* const CPL_RESTRICT pSrcData, int
  * @param nWordCount number of pixel words to be copied
  */
 template <class T>
-inline void GDALCopyWordsFromT(const T* const CPL_RESTRICT pSrcData, int nSrcPixelStride, bool bInComplex,
-                               void * CPL_RESTRICT pDstData, GDALDataType eDstType, int nDstPixelStride,
-                               int nWordCount)
+inline void GDALCopyWordsFromT( const T* const CPL_RESTRICT pSrcData,
+                                int nSrcPixelStride, bool bInComplex,
+                                void * CPL_RESTRICT pDstData,
+                                GDALDataType eDstType, int nDstPixelStride,
+                                int nWordCount )
 {
     switch (eDstType)
     {
     case GDT_Byte:
-        GDALCopyWordsT(pSrcData, nSrcPixelStride,
-                       static_cast<unsigned char*>(pDstData), nDstPixelStride,
-                       nWordCount);
+        GDALCopyWordsT( pSrcData, nSrcPixelStride,
+                        static_cast<unsigned char*>(pDstData), nDstPixelStride,
+                        nWordCount );
         break;
     case GDT_UInt16:
-        GDALCopyWordsT(pSrcData, nSrcPixelStride,
-                       static_cast<unsigned short*>(pDstData), nDstPixelStride,
-                       nWordCount);
+        GDALCopyWordsT( pSrcData, nSrcPixelStride,
+                        static_cast<unsigned short*>(pDstData), nDstPixelStride,
+                        nWordCount );
         break;
     case GDT_Int16:
-        GDALCopyWordsT(pSrcData, nSrcPixelStride,
-                       static_cast<short*>(pDstData), nDstPixelStride,
-                       nWordCount);
+        GDALCopyWordsT( pSrcData, nSrcPixelStride,
+                        static_cast<short*>(pDstData), nDstPixelStride,
+                        nWordCount );
         break;
     case GDT_UInt32:
-        GDALCopyWordsT(pSrcData, nSrcPixelStride,
-                       static_cast<unsigned int*>(pDstData), nDstPixelStride,
-                       nWordCount);
+        GDALCopyWordsT( pSrcData, nSrcPixelStride,
+                        static_cast<unsigned int*>(pDstData), nDstPixelStride,
+                        nWordCount );
         break;
     case GDT_Int32:
-        GDALCopyWordsT(pSrcData, nSrcPixelStride,
-                       static_cast<int*>(pDstData), nDstPixelStride,
-                       nWordCount);
+        GDALCopyWordsT( pSrcData, nSrcPixelStride,
+                        static_cast<int*>(pDstData), nDstPixelStride,
+                        nWordCount );
         break;
     case GDT_Float32:
-        GDALCopyWordsT(pSrcData, nSrcPixelStride,
-                       static_cast<float*>(pDstData), nDstPixelStride,
-                       nWordCount);
+        GDALCopyWordsT( pSrcData, nSrcPixelStride,
+                        static_cast<float*>(pDstData), nDstPixelStride,
+                        nWordCount );
         break;
     case GDT_Float64:
-        GDALCopyWordsT(pSrcData, nSrcPixelStride,
-                       static_cast<double*>(pDstData), nDstPixelStride,
-                       nWordCount);
+        GDALCopyWordsT( pSrcData, nSrcPixelStride,
+                        static_cast<double*>(pDstData), nDstPixelStride,
+                        nWordCount );
         break;
     case GDT_CInt16:
         if (bInComplex)
         {
-            GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
-                                  static_cast<short *>(pDstData), nDstPixelStride,
-                                  nWordCount);
+            GDALCopyWordsComplexT(
+                pSrcData, nSrcPixelStride,
+                static_cast<short *>(pDstData), nDstPixelStride,
+                nWordCount );
         }
         else // input is not complex, so we need to promote to a complex buffer
         {
-            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
-                                     static_cast<short *>(pDstData), nDstPixelStride,
-                                     nWordCount);
+            GDALCopyWordsComplexOutT(
+                pSrcData, nSrcPixelStride,
+                static_cast<short *>(pDstData), nDstPixelStride,
+                nWordCount );
         }
         break;
     case GDT_CInt32:
         if (bInComplex)
         {
-            GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
-                                  static_cast<int *>(pDstData), nDstPixelStride,
-                                  nWordCount);
+            GDALCopyWordsComplexT(
+                pSrcData, nSrcPixelStride,
+                static_cast<int *>(pDstData), nDstPixelStride,
+                nWordCount );
         }
         else // input is not complex, so we need to promote to a complex buffer
         {
-            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
-                                     static_cast<int *>(pDstData), nDstPixelStride,
-                                     nWordCount);
+            GDALCopyWordsComplexOutT(
+                pSrcData, nSrcPixelStride,
+                static_cast<int *>(pDstData), nDstPixelStride,
+                nWordCount );
         }
         break;
     case GDT_CFloat32:
         if (bInComplex)
         {
-            GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
-                                  static_cast<float *>(pDstData), nDstPixelStride,
-                                  nWordCount);
+            GDALCopyWordsComplexT(
+                pSrcData, nSrcPixelStride,
+                static_cast<float *>(pDstData), nDstPixelStride,
+                nWordCount );
         }
         else // input is not complex, so we need to promote to a complex buffer
         {
-            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
-                                     static_cast<float *>(pDstData), nDstPixelStride,
-                                     nWordCount);
+            GDALCopyWordsComplexOutT(
+                pSrcData, nSrcPixelStride,
+                static_cast<float *>(pDstData), nDstPixelStride,
+                nWordCount );
         }
         break;
     case GDT_CFloat64:
         if (bInComplex)
         {
-            GDALCopyWordsComplexT(pSrcData, nSrcPixelStride,
-                                  static_cast<double *>(pDstData), nDstPixelStride,
-                                  nWordCount);
+            GDALCopyWordsComplexT(
+                pSrcData, nSrcPixelStride,
+                static_cast<double *>(pDstData), nDstPixelStride,
+                nWordCount );
         }
         else // input is not complex, so we need to promote to a complex buffer
         {
-            GDALCopyWordsComplexOutT(pSrcData, nSrcPixelStride,
-                                     static_cast<double *>(pDstData), nDstPixelStride,
-                                     nWordCount);
+            GDALCopyWordsComplexOutT(
+                pSrcData, nSrcPixelStride,
+                static_cast<double *>(pDstData), nDstPixelStride,
+                nWordCount );
         }
         break;
     case GDT_Unknown:
     default:
-        CPLAssert(FALSE);
+        CPLAssert(false);
     }
 }
 
@@ -2009,23 +2318,26 @@ inline void GDALCopyWordsFromT(const T* const CPL_RESTRICT pSrcData, int nSrcPix
 /************************************************************************/
 
 static
-void GDALReplicateWord(const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType,
-                       void * CPL_RESTRICT pDstData, GDALDataType eDstType, int nDstPixelStride,
-                       int nWordCount)
+void GDALReplicateWord( const void * CPL_RESTRICT pSrcData,
+                        GDALDataType eSrcType,
+                        void * CPL_RESTRICT pDstData,
+                        GDALDataType eDstType,
+                        int nDstPixelStride,
+                        int nWordCount)
 {
 /* ----------------------------------------------------------------------- */
 /* Special case when the source data is always the same value              */
 /* (for VRTSourcedRasterBand::IRasterIO and VRTDerivedRasterBand::IRasterIO*/
 /*  for example)                                                           */
 /* ----------------------------------------------------------------------- */
-    /* Let the general translation case do the necessary conversions */
-    /* on the first destination element */
+    // Let the general translation case do the necessary conversions
+    // on the first destination element.
     GDALCopyWords((void*)pSrcData, eSrcType, 0,
                   pDstData, eDstType, 0,
                   1 );
 
-    /* Now copy the first element to the nWordCount - 1 following destination */
-    /* elements */
+    // Now copy the first element to the nWordCount - 1 following destination
+    // elements.
     nWordCount--;
     GByte *pabyDstWord = ((GByte *)pDstData) + nDstPixelStride;
 
@@ -2066,8 +2378,8 @@ void GDALReplicateWord(const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType
         CASE_DUPLICATE_SIMPLE(GDT_Int16,  GInt16)
         CASE_DUPLICATE_SIMPLE(GDT_UInt32, GUInt32)
         CASE_DUPLICATE_SIMPLE(GDT_Int32,  GInt32)
-        CASE_DUPLICATE_SIMPLE(GDT_Float32,float)
-        CASE_DUPLICATE_SIMPLE(GDT_Float64,double)
+        CASE_DUPLICATE_SIMPLE(GDT_Float32, float)
+        CASE_DUPLICATE_SIMPLE(GDT_Float64, double)
 
 #define CASE_DUPLICATE_COMPLEX(enum_type, c_type) \
         case enum_type:\
@@ -2089,102 +2401,229 @@ void GDALReplicateWord(const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType
         CASE_DUPLICATE_COMPLEX(GDT_CFloat64, double)
 
         default:
-            CPLAssert( FALSE );
+            CPLAssert( false );
     }
 }
 
 /************************************************************************/
-/*                        GDALUnrolledByteCopy()                        */
+/*                        GDALUnrolledCopy()                            */
 /************************************************************************/
 
-template<int srcStride, int dstStride>
-static inline void GDALUnrolledByteCopy(GByte* CPL_RESTRICT pabyDest,
-                                    const GByte* CPL_RESTRICT pabySrc,
-                                    int nIters)
+template<class T, int srcStride, int dstStride>
+static inline void GDALUnrolledCopyGeneric( T* CPL_RESTRICT pDest,
+                                     const T* CPL_RESTRICT pSrc,
+                                     int nIters )
 {
     if (nIters >= 16)
     {
         for ( int i = nIters / 16; i != 0; i -- )
         {
-            pabyDest[0*dstStride] = pabySrc[0*srcStride];
-            pabyDest[1*dstStride] = pabySrc[1*srcStride];
-            pabyDest[2*dstStride] = pabySrc[2*srcStride];
-            pabyDest[3*dstStride] = pabySrc[3*srcStride];
-            pabyDest[4*dstStride] = pabySrc[4*srcStride];
-            pabyDest[5*dstStride] = pabySrc[5*srcStride];
-            pabyDest[6*dstStride] = pabySrc[6*srcStride];
-            pabyDest[7*dstStride] = pabySrc[7*srcStride];
-            pabyDest[8*dstStride] = pabySrc[8*srcStride];
-            pabyDest[9*dstStride] = pabySrc[9*srcStride];
-            pabyDest[10*dstStride] = pabySrc[10*srcStride];
-            pabyDest[11*dstStride] = pabySrc[11*srcStride];
-            pabyDest[12*dstStride] = pabySrc[12*srcStride];
-            pabyDest[13*dstStride] = pabySrc[13*srcStride];
-            pabyDest[14*dstStride] = pabySrc[14*srcStride];
-            pabyDest[15*dstStride] = pabySrc[15*srcStride];
-            pabyDest += 16*dstStride;
-            pabySrc += 16*srcStride;
+            pDest[0*dstStride] = pSrc[0*srcStride];
+            pDest[1*dstStride] = pSrc[1*srcStride];
+            pDest[2*dstStride] = pSrc[2*srcStride];
+            pDest[3*dstStride] = pSrc[3*srcStride];
+            pDest[4*dstStride] = pSrc[4*srcStride];
+            pDest[5*dstStride] = pSrc[5*srcStride];
+            pDest[6*dstStride] = pSrc[6*srcStride];
+            pDest[7*dstStride] = pSrc[7*srcStride];
+            pDest[8*dstStride] = pSrc[8*srcStride];
+            pDest[9*dstStride] = pSrc[9*srcStride];
+            pDest[10*dstStride] = pSrc[10*srcStride];
+            pDest[11*dstStride] = pSrc[11*srcStride];
+            pDest[12*dstStride] = pSrc[12*srcStride];
+            pDest[13*dstStride] = pSrc[13*srcStride];
+            pDest[14*dstStride] = pSrc[14*srcStride];
+            pDest[15*dstStride] = pSrc[15*srcStride];
+            pDest += 16*dstStride;
+            pSrc += 16*srcStride;
         }
         nIters = nIters % 16;
     }
     for( int i = 0; i < nIters; i++ )
     {
-        pabyDest[i*dstStride] = *pabySrc;
-        pabySrc += srcStride;
+        pDest[i*dstStride] = *pSrc;
+        pSrc += srcStride;
+    }
+}
+
+template<class T, int srcStride, int dstStride>
+static inline void GDALUnrolledCopy( T* CPL_RESTRICT pDest,
+                                     const T* CPL_RESTRICT pSrc,
+                                     int nIters )
+{
+    GDALUnrolledCopyGeneric<T,srcStride,dstStride>(pDest, pSrc, nIters);
+}
+
+#if (defined(__x86_64) || defined(_M_X64)) &&  !(defined(__GNUC__) && __GNUC__ < 4)
+
+template<> void GDALUnrolledCopy<GByte,2,1>( GByte* CPL_RESTRICT pDest,
+                                             const GByte* CPL_RESTRICT pSrc,
+                                             int nIters )
+{
+    int i;
+    const __m128i xmm_mask = _mm_set1_epi16(0xff);
+    // If we were sure that there would always be 1 trailing byte, we could
+    // check against nIters - 15
+    for ( i = 0; i < nIters - 16; i += 16 )
+    {
+        __m128i xmm0 = _mm_loadu_si128( (__m128i const*) (pSrc + 0) );
+        __m128i xmm1 = _mm_loadu_si128( (__m128i const*) (pSrc + 16) );
+        // Set higher 8bit of each int16 packed word to 0
+        xmm0 = _mm_and_si128(xmm0, xmm_mask);
+        xmm1 = _mm_and_si128(xmm1, xmm_mask);
+        // Pack int16 to uint8
+        xmm0 = _mm_packus_epi16(xmm0, xmm0);
+        xmm1 = _mm_packus_epi16(xmm1, xmm1);
+        // Extract lower 64 bit word
+        GDALCopyXMMToInt64(xmm0, pDest + i + 0);
+        GDALCopyXMMToInt64(xmm1, pDest + i + 8);
+        pSrc += 2 * 16;
+    }
+    for( ; i < nIters; i++ )
+    {
+        pDest[i] = *pSrc;
+        pSrc += 2;
+    }
+}
+
+#ifdef HAVE_SSSE3_AT_COMPILE_TIME
+
+void GDALUnrolledCopy_GByte_3_1_SSSE3( GByte* CPL_RESTRICT pDest,
+                                             const GByte* CPL_RESTRICT pSrc,
+                                             int nIters );
+
+void GDALUnrolledCopy_GByte_4_1_SSSE3( GByte* CPL_RESTRICT pDest,
+                                             const GByte* CPL_RESTRICT pSrc,
+                                             int nIters );
+
+template<> void GDALUnrolledCopy<GByte,3,1>( GByte* CPL_RESTRICT pDest,
+                                             const GByte* CPL_RESTRICT pSrc,
+                                             int nIters )
+{
+    if( CPLHaveRuntimeSSSE3() )
+    {
+        GDALUnrolledCopy_GByte_3_1_SSSE3(pDest, pSrc, nIters);
+    }
+    else
+    {
+        GDALUnrolledCopyGeneric<GByte,3,1>(pDest, pSrc, nIters);
+    }
+}
+
+#endif
+
+template<> void GDALUnrolledCopy<GByte,4,1>( GByte* CPL_RESTRICT pDest,
+                                             const GByte* CPL_RESTRICT pSrc,
+                                             int nIters )
+{
+#ifdef HAVE_SSSE3_AT_COMPILE_TIME
+    if( CPLHaveRuntimeSSSE3() )
+    {
+        GDALUnrolledCopy_GByte_4_1_SSSE3(pDest, pSrc, nIters);
+        return;
+    }
+#endif
+
+    int i;
+    const __m128i xmm_mask = _mm_set1_epi32(0xff);
+    // If we were sure that there would always be 3 trailing bytes, we could
+    // check against nIters - 15
+    for ( i = 0; i < nIters - 16; i += 16 )
+    {
+        __m128i xmm0 = _mm_loadu_si128( (__m128i const*) (pSrc + 0) );
+        __m128i xmm1 = _mm_loadu_si128( (__m128i const*) (pSrc + 16) );
+        __m128i xmm2 = _mm_loadu_si128( (__m128i const*) (pSrc + 32) );
+        __m128i xmm3 = _mm_loadu_si128( (__m128i const*) (pSrc + 48) );
+        // Set higher 24bit of each int32 packed word to 0
+        xmm0 = _mm_and_si128(xmm0, xmm_mask);
+        xmm1 = _mm_and_si128(xmm1, xmm_mask);
+        xmm2 = _mm_and_si128(xmm2, xmm_mask);
+        xmm3 = _mm_and_si128(xmm3, xmm_mask);
+        // Pack int32 to int16
+        xmm0 = _mm_packs_epi32(xmm0, xmm0);
+        xmm1 = _mm_packs_epi32(xmm1, xmm1);
+        xmm2 = _mm_packs_epi32(xmm2, xmm2);
+        xmm3 = _mm_packs_epi32(xmm3, xmm3);
+        // Pack int16 to uint8
+        xmm0 = _mm_packus_epi16(xmm0, xmm0);
+        xmm1 = _mm_packus_epi16(xmm1, xmm1);
+        xmm2 = _mm_packus_epi16(xmm2, xmm2);
+        xmm3 = _mm_packus_epi16(xmm3, xmm3);
+        // Extract lower 32 bit word
+        GDALCopyXMMToInt32(xmm0, pDest + i + 0);
+        GDALCopyXMMToInt32(xmm1, pDest + i + 4);
+        GDALCopyXMMToInt32(xmm2, pDest + i + 8);
+        GDALCopyXMMToInt32(xmm3, pDest + i + 12);
+        pSrc += 4 * 16;
+    }
+    for( ; i < nIters; i++ )
+    {
+        pDest[i] = *pSrc;
+        pSrc += 4;
     }
 }
+#endif // defined(__x86_64) || defined(_M_X64)
 
 /************************************************************************/
-/*                         GDALFastByteCopy()                           */
+/*                         GDALFastCopy()                               */
 /************************************************************************/
 
-static inline void GDALFastByteCopy(GByte* CPL_RESTRICT pabyDest,
-                                    int nDestStride,
-                                    const GByte* CPL_RESTRICT pabySrc,
-                                    int nSrcStride,
-                                    int nIters)
+template<class T>
+static inline void GDALFastCopy( T* CPL_RESTRICT pDest,
+                                 int nDestStride,
+                                 const T* CPL_RESTRICT pSrc,
+                                 int nSrcStride,
+                                 int nIters )
 {
-    if( nDestStride == 1 )
+    if( nDestStride == static_cast<int>(sizeof(T)) )
     {
-        if( nSrcStride == 1 )
+        if( nSrcStride == static_cast<int>(sizeof(T)) )
         {
-            memcpy(pabyDest, pabySrc, nIters);
+            memcpy(pDest, pSrc, nIters * sizeof(T));
         }
-        else if( nSrcStride == 3 )
+        else if( nSrcStride == 2 * static_cast<int>(sizeof(T)) )
         {
-            GDALUnrolledByteCopy<3,1>(pabyDest, pabySrc, nIters);
+            GDALUnrolledCopy<T, 2,1>(pDest, pSrc, nIters);
         }
-        else if( nSrcStride == 4 )
+        else if( nSrcStride == 3 * static_cast<int>(sizeof(T)) )
         {
-            GDALUnrolledByteCopy<4,1>(pabyDest, pabySrc, nIters);
+            GDALUnrolledCopy<T, 3,1>(pDest, pSrc, nIters);
+        }
+        else if( nSrcStride == 4 * static_cast<int>(sizeof(T)) )
+        {
+            GDALUnrolledCopy<T, 4,1>(pDest, pSrc, nIters);
         }
         else
         {
             while( nIters-- > 0 )
             {
-                *pabyDest = *pabySrc;
-                pabySrc += nSrcStride;
-                pabyDest ++;
+                *pDest = *pSrc;
+                pSrc += nSrcStride / static_cast<int>(sizeof(T));
+                pDest ++;
             }
         }
     }
-    else if( nSrcStride == 1 )
+    else if( nSrcStride == static_cast<int>(sizeof(T))  )
     {
-        if( nDestStride == 3 )
+        if( nDestStride == 2 * static_cast<int>(sizeof(T)) )
         {
-            GDALUnrolledByteCopy<1,3>(pabyDest, pabySrc, nIters);
+            GDALUnrolledCopy<T, 1,2>(pDest, pSrc, nIters);
         }
-        else if( nDestStride == 4 )
+        else if( nDestStride == 3 * static_cast<int>(sizeof(T)) )
         {
-            GDALUnrolledByteCopy<1,4>(pabyDest, pabySrc, nIters);
+            GDALUnrolledCopy<T, 1,3>(pDest, pSrc, nIters);
+        }
+        else if( nDestStride == 4 * static_cast<int>(sizeof(T))  )
+        {
+            GDALUnrolledCopy<T, 1,4>(pDest, pSrc, nIters);
         }
         else
         {
             while( nIters-- > 0 )
             {
-                *pabyDest = *pabySrc;
-                pabySrc ++;
-                pabyDest += nDestStride;
+                *pDest = *pSrc;
+                pSrc ++;
+                pDest += nDestStride / static_cast<int>(sizeof(T));
             }
         }
     }
@@ -2192,9 +2631,9 @@ static inline void GDALFastByteCopy(GByte* CPL_RESTRICT pabyDest,
     {
         while( nIters-- > 0 )
         {
-            *pabyDest = *pabySrc;
-            pabySrc += nSrcStride;
-            pabyDest += nDestStride;
+            *pDest = *pSrc;
+            pSrc += nSrcStride / static_cast<int>(sizeof(T));
+            pDest += nDestStride / static_cast<int>(sizeof(T));
         }
     }
 }
@@ -2224,10 +2663,12 @@ static inline void GDALFastByteCopy(GByte* CPL_RESTRICT pabyDest,
  *
  * @param pSrcData Pointer to source data to be converted.
  * @param eSrcType the source data type (see GDALDataType enum)
- * @param nSrcPixelStride Source pixel stride (i.e. distance between 2 words), in bytes
+ * @param nSrcPixelStride Source pixel stride (i.e. distance between 2 words),
+ * in bytes
  * @param pDstData Pointer to buffer where destination data should go
  * @param eDstType the destination data type (see GDALDataType enum)
- * @param nDstPixelStride Destination pixel stride (i.e. distance between 2 words), in bytes
+ * @param nDstPixelStride Destination pixel stride (i.e. distance between 2
+ * words), in bytes
  * @param nWordCount number of words to be copied
  *
  * @note
@@ -2244,8 +2685,12 @@ static inline void GDALFastByteCopy(GByte* CPL_RESTRICT pabyDest,
  */
 
 void CPL_STDCALL
-GDALCopyWords( const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType, int nSrcPixelStride,
-               void * CPL_RESTRICT pDstData, GDALDataType eDstType, int nDstPixelStride,
+GDALCopyWords( const void * CPL_RESTRICT pSrcData,
+               GDALDataType eSrcType,
+               int nSrcPixelStride,
+               void * CPL_RESTRICT pDstData,
+               GDALDataType eDstType,
+               int nDstPixelStride,
                int nWordCount )
 
 {
@@ -2271,21 +2716,27 @@ GDALCopyWords( const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType, int nS
         else
         {
 #define ALIGN_PTR(ptr, align) ((ptr) + ((align) - ((size_t)(ptr) % (align))) % (align))
-            GByte abySrcBuffer[32]; /* the largest we need is for CFloat64 (16 bytes), so 32 bytes to be sure to get correctly aligned pointer */
+            // The largest we need is for CFloat64 (16 bytes), so 32 bytes to
+            // be sure to get correctly aligned pointer.
+            GByte abySrcBuffer[32];
             GByte abyDstBuffer[32];
             GByte* pabySrcBuffer = ALIGN_PTR(abySrcBuffer, nSrcDataTypeSize);
             GByte* pabyDstBuffer = ALIGN_PTR(abyDstBuffer, nDstDataTypeSize);
             for( int i = 0; i < nWordCount; i++ )
             {
-                memcpy(pabySrcBuffer, (GByte*)pSrcData + nSrcPixelStride * i, nSrcDataTypeSize);
+                memcpy( pabySrcBuffer,
+                        (GByte*)pSrcData + nSrcPixelStride * i,
+                        nSrcDataTypeSize );
                 GDALCopyWords( pabySrcBuffer,
-                            eSrcType,
-                            0,
-                            pabyDstBuffer,
-                            eDstType,
-                            0,
-                            1 );
-                memcpy( (GByte*)pDstData + nDstPixelStride * i, pabyDstBuffer, nDstDataTypeSize );
+                               eSrcType,
+                               0,
+                               pabyDstBuffer,
+                               eDstType,
+                               0,
+                               1 );
+                memcpy( (GByte*)pDstData + nDstPixelStride * i,
+                        pabyDstBuffer,
+                        nDstDataTypeSize );
             }
         }
         return;
@@ -2296,7 +2747,8 @@ GDALCopyWords( const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType, int nS
     // provided buffer
     if (nSrcPixelStride == 0 && nWordCount > 1)
     {
-        GDALReplicateWord(pSrcData, eSrcType, pDstData, eDstType, nDstPixelStride, nWordCount);
+        GDALReplicateWord( pSrcData, eSrcType, pDstData,
+                           eDstType, nDstPixelStride, nWordCount );
         return;
     }
 
@@ -2304,20 +2756,28 @@ GDALCopyWords( const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType, int nS
     {
         if( eSrcType == GDT_Byte )
         {
-            GDALFastByteCopy((GByte*)pDstData, nDstPixelStride,
-                             (const GByte*)pSrcData, nSrcPixelStride, nWordCount);
+            GDALFastCopy(
+                static_cast<GByte*>(pDstData), nDstPixelStride,
+                static_cast<const GByte*>(pSrcData), nSrcPixelStride, nWordCount );
+            return;
+        }
+
+        if( nSrcDataTypeSize == 2 && (nSrcPixelStride%2) == 0 &&
+            (nDstPixelStride%2) == 0 )
+        {
+            GDALFastCopy(
+                static_cast<short*>(pDstData), nDstPixelStride,
+                static_cast<const short*>(pSrcData), nSrcPixelStride, nWordCount );
             return;
         }
 
         if( nWordCount == 1 )
         {
-            if( eSrcType == GDT_Int16 || eSrcType == GDT_UInt16 )
+            if( nSrcDataTypeSize == 2 )
                 memcpy(pDstData, pSrcData, 2);
-            else if( eSrcType == GDT_Int32 || eSrcType == GDT_UInt32 ||
-                     eSrcType == GDT_Float32 || eSrcType == GDT_CInt16 )
+            else if( nSrcDataTypeSize == 4 )
                 memcpy(pDstData, pSrcData, 4);
-            else if( eSrcType == GDT_Float64 || eSrcType == GDT_CInt32 ||
-                     eSrcType == GDT_CFloat32 )
+            else if( nSrcDataTypeSize == 8 )
                 memcpy(pDstData, pSrcData, 8 );
             else /* if( eSrcType == GDT_CFloat64 ) */
                 memcpy(pDstData, pSrcData, 16);
@@ -2341,63 +2801,76 @@ GDALCopyWords( const void * CPL_RESTRICT pSrcData, GDALDataType eSrcType, int nS
     switch (eSrcType)
     {
     case GDT_Byte:
-        GDALCopyWordsFromT<unsigned char>(static_cast<const unsigned char *>(pSrcData), nSrcPixelStride, false,
-                                 pDstData, eDstType, nDstPixelStride,
-                                 nWordCount);
+        GDALCopyWordsFromT<unsigned char>(
+            static_cast<const unsigned char *>(pSrcData),
+            nSrcPixelStride, false,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_UInt16:
-        GDALCopyWordsFromT<unsigned short>(static_cast<const unsigned short *>(pSrcData), nSrcPixelStride, false,
-                                           pDstData, eDstType, nDstPixelStride,
-                                           nWordCount);
+        GDALCopyWordsFromT<unsigned short>(
+            static_cast<const unsigned short *>(pSrcData),
+            nSrcPixelStride, false,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_Int16:
-        GDALCopyWordsFromT<short>(static_cast<const short *>(pSrcData), nSrcPixelStride, false,
-                                  pDstData, eDstType, nDstPixelStride,
-                                  nWordCount);
+        GDALCopyWordsFromT<short>(
+            static_cast<const short *>(pSrcData), nSrcPixelStride, false,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_UInt32:
-        GDALCopyWordsFromT<unsigned int>(static_cast<const unsigned int *>(pSrcData), nSrcPixelStride, false,
-                                         pDstData, eDstType, nDstPixelStride,
-                                         nWordCount);
+        GDALCopyWordsFromT<unsigned int>(
+            static_cast<const unsigned int *>(pSrcData), nSrcPixelStride, false,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_Int32:
-        GDALCopyWordsFromT<int>(static_cast<const int *>(pSrcData), nSrcPixelStride, false,
-                                pDstData, eDstType, nDstPixelStride,
-                                nWordCount);
+        GDALCopyWordsFromT<int>(
+            static_cast<const int *>(pSrcData), nSrcPixelStride, false,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_Float32:
-        GDALCopyWordsFromT<float>(static_cast<const float *>(pSrcData), nSrcPixelStride, false,
-                                  pDstData, eDstType, nDstPixelStride,
-                                  nWordCount);
+        GDALCopyWordsFromT<float>(
+            static_cast<const float *>(pSrcData), nSrcPixelStride, false,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_Float64:
-        GDALCopyWordsFromT<double>(static_cast<const double *>(pSrcData), nSrcPixelStride, false,
-                                   pDstData, eDstType, nDstPixelStride,
-                                   nWordCount);
+        GDALCopyWordsFromT<double>(
+            static_cast<const double *>(pSrcData), nSrcPixelStride, false,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_CInt16:
-        GDALCopyWordsFromT<short>(static_cast<const short *>(pSrcData), nSrcPixelStride, true,
-                                 pDstData, eDstType, nDstPixelStride,
-                                 nWordCount);
+        GDALCopyWordsFromT<short>(
+            static_cast<const short *>(pSrcData), nSrcPixelStride, true,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_CInt32:
-        GDALCopyWordsFromT<int>(static_cast<const int *>(pSrcData), nSrcPixelStride, true,
-                                 pDstData, eDstType, nDstPixelStride,
-                                 nWordCount);
+        GDALCopyWordsFromT<int>(
+            static_cast<const int *>(pSrcData), nSrcPixelStride, true,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_CFloat32:
-        GDALCopyWordsFromT<float>(static_cast<const float *>(pSrcData), nSrcPixelStride, true,
-                                 pDstData, eDstType, nDstPixelStride,
-                                 nWordCount);
+        GDALCopyWordsFromT<float>(
+            static_cast<const float *>(pSrcData), nSrcPixelStride, true,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_CFloat64:
-        GDALCopyWordsFromT<double>(static_cast<const double *>(pSrcData), nSrcPixelStride, true,
-                                 pDstData, eDstType, nDstPixelStride,
-                                 nWordCount);
+        GDALCopyWordsFromT<double>(
+            static_cast<const double *>(pSrcData), nSrcPixelStride, true,
+            pDstData, eDstType, nDstPixelStride,
+            nWordCount );
         break;
     case GDT_Unknown:
     default:
-        CPLAssert(FALSE);
+        CPLAssert(false);
     }
 }
 
@@ -2443,12 +2916,9 @@ void GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep,
 {
     VALIDATE_POINTER0( pabySrcData, "GDALCopyBits" );
 
-    int iStep;
-    int iBit;
-
-    for( iStep = 0; iStep < nStepCount; iStep++ )
+    for( int iStep = 0; iStep < nStepCount; iStep++ )
     {
-        for( iBit = 0; iBit < nBitCount; iBit++ )
+        for( int iBit = 0; iBit < nBitCount; iBit++ )
         {
             if( pabySrcData[nSrcOffset>>3]
                 & (0x80 >>(nSrcOffset & 7)) )
@@ -2456,7 +2926,6 @@ void GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep,
             else
                 pabyDstData[nDstOffset>>3] &= ~(0x80 >> (nDstOffset & 7));
 
-
             nSrcOffset++;
             nDstOffset++;
         }
@@ -2474,32 +2943,33 @@ void GDALCopyBits( const GByte *pabySrcData, int nSrcOffset, int nSrcStep,
 /* returning a valid overview level                                     */
 /************************************************************************/
 
-int GDALBandGetBestOverviewLevel(GDALRasterBand* poBand,
-                                 int &nXOff, int &nYOff,
-                                 int &nXSize, int &nYSize,
-                                 int nBufXSize, int nBufYSize )
+int GDALBandGetBestOverviewLevel( GDALRasterBand* poBand,
+                                  int &nXOff, int &nYOff,
+                                  int &nXSize, int &nYSize,
+                                  int nBufXSize, int nBufYSize )
 {
-    return GDALBandGetBestOverviewLevel2(poBand, nXOff, nYOff, nXSize, nYSize,
-                                        nBufXSize, nBufYSize, NULL);
+    return GDALBandGetBestOverviewLevel2( poBand, nXOff, nYOff, nXSize, nYSize,
+                                          nBufXSize, nBufYSize, NULL );
 }
 
-int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
-                                  int &nXOff, int &nYOff,
-                                  int &nXSize, int &nYSize,
-                                  int nBufXSize, int nBufYSize,
-                                  GDALRasterIOExtraArg* psExtraArg )
+int GDALBandGetBestOverviewLevel2( GDALRasterBand* poBand,
+                                   int &nXOff, int &nYOff,
+                                   int &nXSize, int &nYSize,
+                                   int nBufXSize, int nBufYSize,
+                                   GDALRasterIOExtraArg* psExtraArg )
 {
-    double dfDesiredResolution;
+    double dfDesiredResolution = 0.0;
 /* -------------------------------------------------------------------- */
 /*      Compute the desired resolution.  The resolution is              */
 /*      based on the least reduced axis, and represents the number      */
 /*      of source pixels to one destination pixel.                      */
 /* -------------------------------------------------------------------- */
-    if( (nXSize / (double) nBufXSize) < (nYSize / (double) nBufYSize )
+    if( (nXSize / static_cast<double>(nBufXSize)) <
+        (nYSize / static_cast<double>(nBufYSize))
         || nBufYSize == 1 )
-        dfDesiredResolution = nXSize / (double) nBufXSize;
+        dfDesiredResolution = nXSize / static_cast<double>( nBufXSize );
     else
-        dfDesiredResolution = nYSize / (double) nBufYSize;
+        dfDesiredResolution = nYSize / static_cast<double>( nBufYSize );
 
 /* -------------------------------------------------------------------- */
 /*      Find the overview level that largest resolution value (most     */
@@ -2513,20 +2983,23 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
 
     for( int iOverview = 0; iOverview < nOverviewCount; iOverview++ )
     {
-        GDALRasterBand  *poOverview = poBand->GetOverview( iOverview );
+        GDALRasterBand *poOverview = poBand->GetOverview( iOverview );
         if (poOverview == NULL)
             continue;
 
-        double          dfResolution;
+        double dfResolution = 0.0;
 
         // What resolution is this?
-        if( (poBand->GetXSize() / (double) poOverview->GetXSize())
-            < (poBand->GetYSize() / (double) poOverview->GetYSize()) )
+        if( (poBand->GetXSize() / static_cast<double>(poOverview->GetXSize()))
+            < (poBand->GetYSize() /
+               static_cast<double>(poOverview->GetYSize())) )
             dfResolution =
-                poBand->GetXSize() / (double) poOverview->GetXSize();
+                poBand->GetXSize() /
+                static_cast<double>( poOverview->GetXSize() );
         else
             dfResolution =
-                poBand->GetYSize() / (double) poOverview->GetYSize();
+                poBand->GetYSize() /
+                static_cast<double>( poOverview->GetYSize() );
 
         // Is it nearly the requested resolution and better (lower) than
         // the current best resolution?
@@ -2538,7 +3011,8 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
         const char *pszResampling =
             poOverview->GetMetadataItem( "RESAMPLING" );
 
-        if( pszResampling != NULL && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2"))
+        if( pszResampling != NULL &&
+            STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
             continue;
 
         // OK, this is our new best overview.
@@ -2558,16 +3032,17 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
 /*      Recompute the source window in terms of the selected            */
 /*      overview.                                                       */
 /* -------------------------------------------------------------------- */
-    int         nOXOff, nOYOff, nOXSize, nOYSize;
-    double      dfXRes, dfYRes;
-
-    dfXRes = poBand->GetXSize() / (double) poBestOverview->GetXSize();
-    dfYRes = poBand->GetYSize() / (double) poBestOverview->GetYSize();
-
-    nOXOff = MIN(poBestOverview->GetXSize()-1,(int) (nXOff/dfXRes+0.5));
-    nOYOff = MIN(poBestOverview->GetYSize()-1,(int) (nYOff/dfYRes+0.5));
-    nOXSize = MAX(1,(int) (nXSize/dfXRes + 0.5));
-    nOYSize = MAX(1,(int) (nYSize/dfYRes + 0.5));
+    const double dfXRes =
+        poBand->GetXSize() / static_cast<double>( poBestOverview->GetXSize() );
+    const double dfYRes =
+        poBand->GetYSize() / static_cast<double>( poBestOverview->GetYSize() );
+
+    const int nOXOff = std::min( poBestOverview->GetXSize()-1,
+                                 static_cast<int>(nXOff / dfXRes + 0.5));
+    const int nOYOff = std::min( poBestOverview->GetYSize()-1,
+                                 static_cast<int>(nYOff / dfYRes + 0.5));
+    int nOXSize = std::max(1, static_cast<int>(nXSize / dfXRes + 0.5));
+    int nOYSize = std::max(1, static_cast<int>(nYSize / dfYRes + 0.5));
     if( nOXOff + nOXSize > poBestOverview->GetXSize() )
         nOXSize = poBestOverview->GetXSize() - nOXOff;
     if( nOYOff + nOYSize > poBestOverview->GetYSize() )
@@ -2589,7 +3064,6 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
     return nBestOverviewLevel;
 }
 
-
 /************************************************************************/
 /*                          OverviewRasterIO()                          */
 /*                                                                      */
@@ -2599,6 +3073,7 @@ int GDALBandGetBestOverviewLevel2(GDALRasterBand* poBand,
 /*      available but it doesn't emit any error messages.               */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 CPLErr GDALRasterBand::OverviewRasterIO( GDALRWFlag eRWFlag,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void * pData, int nBufXSize, int nBufYSize,
@@ -2606,16 +3081,13 @@ CPLErr GDALRasterBand::OverviewRasterIO( GDALRWFlag eRWFlag,
                                 GSpacing nPixelSpace, GSpacing nLineSpace,
                                 GDALRasterIOExtraArg* psExtraArg )
 
-
 {
-    int         nOverview;
     GDALRasterIOExtraArg sExtraArg;
-
     GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
 
-    nOverview =
-        GDALBandGetBestOverviewLevel2(this, nXOff, nYOff, nXSize, nYSize,
-                                      nBufXSize, nBufYSize, &sExtraArg);
+    const int nOverview =
+        GDALBandGetBestOverviewLevel2( this, nXOff, nYOff, nXSize, nYSize,
+                                       nBufXSize, nBufYSize, &sExtraArg );
     if (nOverview < 0)
         return CE_Failure;
 
@@ -2643,16 +3115,19 @@ CPLErr GDALRasterBand::TryOverviewRasterIO( GDALRWFlag eRWFlag,
                                             GDALRasterIOExtraArg* psExtraArg,
                                             int* pbTried )
 {
-    int nXOffMod = nXOff, nYOffMod = nYOff, nXSizeMod = nXSize, nYSizeMod = nYSize;
+    int nXOffMod = nXOff;
+    int nYOffMod = nYOff;
+    int nXSizeMod = nXSize;
+    int nYSizeMod = nYSize;
     GDALRasterIOExtraArg sExtraArg;
 
     GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
 
-    int iOvrLevel = GDALBandGetBestOverviewLevel2(this,
-                                                    nXOffMod, nYOffMod,
-                                                    nXSizeMod, nYSizeMod,
-                                                    nBufXSize, nBufYSize,
-                                                    &sExtraArg);
+    int iOvrLevel = GDALBandGetBestOverviewLevel2( this,
+                                                   nXOffMod, nYOffMod,
+                                                   nXSizeMod, nYSizeMod,
+                                                   nBufXSize, nBufYSize,
+                                                   &sExtraArg );
 
     if( iOvrLevel >= 0 )
     {
@@ -2685,16 +3160,18 @@ CPLErr GDALDataset::TryOverviewRasterIO( GDALRWFlag eRWFlag,
                                          GDALRasterIOExtraArg* psExtraArg,
                                          int* pbTried )
 {
-    int nXOffMod = nXOff, nYOffMod = nYOff, nXSizeMod = nXSize, nYSizeMod = nYSize;
+    int nXOffMod = nXOff;
+    int nYOffMod = nYOff;
+    int nXSizeMod = nXSize;
+    int nYSizeMod = nYSize;
     GDALRasterIOExtraArg sExtraArg;
-
     GDALCopyRasterIOExtraArg(&sExtraArg, psExtraArg);
 
-    int iOvrLevel = GDALBandGetBestOverviewLevel2(papoBands[0],
-                                                    nXOffMod, nYOffMod,
-                                                    nXSizeMod, nYSizeMod,
-                                                    nBufXSize, nBufYSize,
-                                                    &sExtraArg);
+    int iOvrLevel = GDALBandGetBestOverviewLevel2( papoBands[0],
+                                                   nXOffMod, nYOffMod,
+                                                   nXSizeMod, nYSizeMod,
+                                                   nBufXSize, nBufYSize,
+                                                   &sExtraArg );
 
     if( iOvrLevel >= 0 && papoBands[0]->GetOverview(iOvrLevel) != NULL &&
         papoBands[0]->GetOverview(iOvrLevel)->GetDataset() != NULL )
@@ -2703,7 +3180,8 @@ CPLErr GDALDataset::TryOverviewRasterIO( GDALRWFlag eRWFlag,
         return papoBands[0]->GetOverview(iOvrLevel)->GetDataset()->RasterIO(
             eRWFlag, nXOffMod, nYOffMod, nXSizeMod, nYSizeMod,
             pData, nBufXSize, nBufYSize, eBufType,
-            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace, &sExtraArg);
+            nBandCount, panBandMap, nPixelSpace, nLineSpace, nBandSpace,
+            &sExtraArg );
     }
     else
     {
@@ -2721,26 +3199,24 @@ CPLErr GDALDataset::TryOverviewRasterIO( GDALRWFlag eRWFlag,
 /************************************************************************/
 
 static
-int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
-                                    int &nXOff, int &nYOff,
-                                    int &nXSize, int &nYSize,
-                                    int nBufXSize, int nBufYSize,
-                                    int nBandCount, int *panBandMap)
+int GDALDatasetGetBestOverviewLevel( GDALDataset* poDS,
+                                     int &nXOff, int &nYOff,
+                                     int &nXSize, int &nYSize,
+                                     int nBufXSize, int nBufYSize,
+                                     int nBandCount, int *panBandMap )
 {
-    int iBand, iOverview;
     int nOverviewCount = 0;
     GDALRasterBand *poFirstBand = NULL;
 
-    if (nBandCount == 0)
-        return -1;
-
 /* -------------------------------------------------------------------- */
 /* Check that all bands have the same number of overviews and           */
 /* that they have all the same size and block dimensions                */
 /* -------------------------------------------------------------------- */
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
         GDALRasterBand *poBand = poDS->GetRasterBand( panBandMap[iBand] );
+        if ( poBand == NULL )
+            return -1;
         if (iBand == 0)
         {
             poFirstBand = poBand;
@@ -2755,7 +3231,7 @@ int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
         }
         else
         {
-            for(iOverview = 0; iOverview < nOverviewCount; iOverview++)
+            for( int iOverview = 0; iOverview < nOverviewCount; iOverview++ )
             {
                 GDALRasterBand* poOvrBand =
                     poBand->GetOverview(iOverview);
@@ -2772,25 +3248,34 @@ int GDALDatasetGetBestOverviewLevel(GDALDataset* poDS,
                               "mismatched overview sizes, use std method." );
                     return -1;
                 }
-                int nBlockXSizeFirst=0, nBlockYSizeFirst=0;
-                int nBlockXSizeCurrent=0, nBlockYSizeCurrent=0;
-                poOvrFirstBand->GetBlockSize(&nBlockXSizeFirst, &nBlockYSizeFirst);
-                poOvrBand->GetBlockSize(&nBlockXSizeCurrent, &nBlockYSizeCurrent);
+                int nBlockXSizeFirst = 0;
+                int nBlockYSizeFirst = 0;
+                poOvrFirstBand->GetBlockSize( &nBlockXSizeFirst,
+                                              &nBlockYSizeFirst );
+
+                int nBlockXSizeCurrent = 0;
+                int nBlockYSizeCurrent = 0;
+                poOvrBand->GetBlockSize( &nBlockXSizeCurrent,
+                                         &nBlockYSizeCurrent );
+
                 if (nBlockXSizeFirst != nBlockXSizeCurrent ||
                     nBlockYSizeFirst != nBlockYSizeCurrent)
                 {
-                    CPLDebug( "GDAL",
-                          "GDALDataset::GetBestOverviewLevel() ... "
-                          "mismatched block sizes, use std method." );
+                    CPLDebug(
+                        "GDAL",
+                        "GDALDataset::GetBestOverviewLevel() ... "
+                        "mismatched block sizes, use std method." );
                     return -1;
                 }
             }
         }
     }
+    if( poFirstBand == NULL )
+        return -1;
 
-    return GDALBandGetBestOverviewLevel2(poFirstBand,
-                                        nXOff, nYOff, nXSize, nYSize,
-                                        nBufXSize, nBufYSize, NULL);
+    return GDALBandGetBestOverviewLevel2( poFirstBand,
+                                          nXOff, nYOff, nXSize, nYSize,
+                                          nBufXSize, nBufYSize, NULL );
 }
 
 /************************************************************************/
@@ -2831,24 +3316,27 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
                                  GDALRasterIOExtraArg* psExtraArg )
 
 {
-    GByte      **papabySrcBlock = NULL;
+    CPLAssert( NULL != pData );
+
+    GByte **papabySrcBlock = NULL;
     GDALRasterBlock *poBlock = NULL;
     GDALRasterBlock **papoBlocks = NULL;
-    int         nLBlockX=-1, nLBlockY=-1, iBufYOff, iBufXOff, iSrcY, iBand;
-    int         nBlockXSize=1, nBlockYSize=1;
-    CPLErr      eErr = CE_None;
+    int nLBlockX = -1;
+    int nLBlockY = -1;
+    int iBufYOff;
+    int iBufXOff;
+    int iSrcY;
+    int nBlockXSize = 1;
+    int nBlockYSize = 1;
+    CPLErr eErr = CE_None;
     GDALDataType eDataType = GDT_Byte;
 
-    CPLAssert( NULL != pData );
-
 /* -------------------------------------------------------------------- */
 /*      Ensure that all bands share a common block size and data type.  */
 /* -------------------------------------------------------------------- */
-
-    for( iBand = 0; iBand < nBandCount; iBand++ )
+    for( int iBand = 0; iBand < nBandCount; iBand++ )
     {
         GDALRasterBand *poBand = GetRasterBand( panBandMap[iBand] );
-        int nThisBlockXSize, nThisBlockYSize;
 
         if( iBand == 0 )
         {
@@ -2857,6 +3345,8 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
         }
         else
         {
+          int nThisBlockXSize = 0;
+          int nThisBlockYSize = 0;
             poBand->GetBlockSize( &nThisBlockXSize, &nThisBlockYSize );
             if( nThisBlockXSize != nBlockXSize
                 || nThisBlockYSize != nBlockYSize )
@@ -2865,12 +3355,12 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
                           "GDALDataset::BlockBasedRasterIO() ... "
                           "mismatched block sizes, use std method." );
                 return BandBasedRasterIO( eRWFlag,
-                                               nXOff, nYOff, nXSize, nYSize,
-                                               pData, nBufXSize, nBufYSize,
-                                               eBufType,
-                                               nBandCount, panBandMap,
-                                               nPixelSpace, nLineSpace,
-                                               nBandSpace, psExtraArg );
+                                          nXOff, nYOff, nXSize, nYSize,
+                                          pData, nBufXSize, nBufYSize,
+                                          eBufType,
+                                          nBandCount, panBandMap,
+                                          nPixelSpace, nLineSpace,
+                                          nBandSpace, psExtraArg );
             }
 
             if( eDataType != poBand->GetRasterDataType()
@@ -2880,12 +3370,12 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
                           "GDALDataset::BlockBasedRasterIO() ... "
                           "mismatched band data types, use std method." );
                 return BandBasedRasterIO( eRWFlag,
-                                               nXOff, nYOff, nXSize, nYSize,
-                                               pData, nBufXSize, nBufYSize,
-                                               eBufType,
-                                               nBandCount, panBandMap,
-                                               nPixelSpace, nLineSpace,
-                                               nBandSpace, psExtraArg );
+                                          nXOff, nYOff, nXSize, nYSize,
+                                          pData, nBufXSize, nBufYSize,
+                                          eBufType,
+                                          nBandCount, panBandMap,
+                                          nPixelSpace, nLineSpace,
+                                          nBandSpace, psExtraArg );
             }
         }
     }
@@ -2902,11 +3392,12 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
         GDALRasterIOExtraArg sDummyExtraArg;
         INIT_RASTERIO_EXTRA_ARG(sDummyExtraArg);
 
-        int nChunkYSize, nChunkXSize, nChunkXOff, nChunkYOff;
+        int nChunkYSize = 0;
+        int nChunkXSize = 0;
 
         for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff += nChunkYSize )
         {
-            nChunkYOff = iBufYOff + nYOff;
+            const int nChunkYOff = iBufYOff + nYOff;
             nChunkYSize = nBlockYSize - (nChunkYOff % nBlockYSize);
             if( nChunkYSize == 0 )
                 nChunkYSize = nBlockYSize;
@@ -2915,20 +3406,19 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 
             for( iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff += nChunkXSize )
             {
-                nChunkXOff = iBufXOff + nXOff;
+                const int nChunkXOff = iBufXOff + nXOff;
                 nChunkXSize = nBlockXSize - (nChunkXOff % nBlockXSize);
                 if( nChunkXSize == 0 )
                     nChunkXSize = nBlockXSize;
                 if( nChunkXOff + nChunkXSize > nXOff + nXSize )
                     nChunkXSize = (nXOff + nXSize) - nChunkXOff;
 
-                GByte *pabyChunkData;
-
-                pabyChunkData = ((GByte *) pData)
+                GByte *pabyChunkData =
+                    static_cast<GByte *>(pData)
                     + iBufXOff * nPixelSpace
-                    + (GPtrDiff_t)iBufYOff * nLineSpace;
+                    + static_cast<GPtrDiff_t>(iBufYOff) * nLineSpace;
 
-                for( iBand = 0; iBand < nBandCount; iBand++ )
+                for( int iBand = 0; iBand < nBandCount; iBand++ )
                 {
                     GDALRasterBand *poBand = GetRasterBand(panBandMap[iBand]);
 
@@ -2936,7 +3426,8 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
                         poBand->GDALRasterBand::IRasterIO(
                             eRWFlag, nChunkXOff, nChunkYOff,
                             nChunkXSize, nChunkYSize,
-                            pabyChunkData + (GPtrDiff_t)iBand * nBandSpace,
+                            pabyChunkData +
+                            static_cast<GPtrDiff_t>(iBand) * nBandSpace,
                             nChunkXSize, nChunkYSize, eBufType,
                             nPixelSpace, nLineSpace, &sDummyExtraArg );
                     if( eErr != CE_None )
@@ -2945,7 +3436,10 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
             }
 
             if( psExtraArg->pfnProgress != NULL &&
-                !psExtraArg->pfnProgress(1.0 * MAX(nBufYSize,iBufYOff + nChunkYSize) / nBufYSize, "", psExtraArg->pProgressData) )
+                !psExtraArg->pfnProgress(
+                    1.0 * std::max(nBufYSize,
+                                   iBufYOff + nChunkYSize) /
+                    nBufYSize, "", psExtraArg->pProgressData) )
             {
                 return CE_Failure;
             }
@@ -2988,15 +3482,17 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
     const int nBandDataSize = GDALGetDataTypeSizeBytes( eDataType );
 
     papabySrcBlock = (GByte **) CPLCalloc(sizeof(GByte*),nBandCount);
-    papoBlocks = (GDALRasterBlock **) CPLCalloc(sizeof(void*),nBandCount);
+    papoBlocks = static_cast<GDALRasterBlock **>(
+        CPLCalloc(sizeof(void*), nBandCount) );
 
 /* -------------------------------------------------------------------- */
 /*      Select an overview level if appropriate.                        */
 /* -------------------------------------------------------------------- */
-    int nOverviewLevel = GDALDatasetGetBestOverviewLevel (this,
-                                               nXOff, nYOff, nXSize, nYSize,
-                                               nBufXSize, nBufYSize,
-                                               nBandCount, panBandMap);
+    const int nOverviewLevel =
+        GDALDatasetGetBestOverviewLevel( this,
+                                         nXOff, nYOff, nXSize, nYSize,
+                                         nBufXSize, nBufYSize,
+                                         nBandCount, panBandMap);
     if (nOverviewLevel >= 0)
     {
         GetRasterBand(panBandMap[0])->GetOverview(nOverviewLevel)->
@@ -3006,31 +3502,28 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 /* -------------------------------------------------------------------- */
 /*      Compute stepping increment.                                     */
 /* -------------------------------------------------------------------- */
-    double      dfSrcX, dfSrcY, dfSrcXInc, dfSrcYInc;
-
-    dfSrcXInc = nXSize / (double) nBufXSize;
-    dfSrcYInc = nYSize / (double) nBufYSize;
+    const double dfSrcXInc = nXSize / static_cast<double>( nBufXSize );
+    const double dfSrcYInc = nYSize / static_cast<double>( nBufYSize );
 
+    double dfSrcX = 0.0;
+    double dfSrcY = 0.0;
 /* -------------------------------------------------------------------- */
 /*      Loop over buffer computing source locations.                    */
 /* -------------------------------------------------------------------- */
     for( iBufYOff = 0; iBufYOff < nBufYSize; iBufYOff++ )
     {
-        GPtrDiff_t  iBufOffset;
         GPtrDiff_t  iSrcOffset;
 
-        dfSrcY = (iBufYOff+0.5) * dfSrcYInc + nYOff;
-        iSrcY = (int) dfSrcY;
+        dfSrcY = (iBufYOff + 0.5) * dfSrcYInc + nYOff;
+        iSrcY = static_cast<int>( dfSrcY );
 
-        iBufOffset = (GPtrDiff_t)iBufYOff * (GPtrDiff_t)nLineSpace;
+        GPtrDiff_t iBufOffset = (GPtrDiff_t)iBufYOff * (GPtrDiff_t)nLineSpace;
 
         for( iBufXOff = 0; iBufXOff < nBufXSize; iBufXOff++ )
         {
-            int iSrcX;
-
-            dfSrcX = (iBufXOff+0.5) * dfSrcXInc + nXOff;
+            dfSrcX = (iBufXOff + 0.5) * dfSrcXInc + nXOff;
 
-            iSrcX = (int) dfSrcX;
+            int iSrcX = static_cast<int>( dfSrcX );
 
             // FIXME: this code likely doesn't work if the dirty block gets flushed
             // to disk before being completely written.
@@ -3041,32 +3534,34 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
 /*      Ensure we have the appropriate block loaded.                    */
 /* -------------------------------------------------------------------- */
             if( iSrcX < nLBlockX * nBlockXSize
-                || iSrcX >= (nLBlockX+1) * nBlockXSize
+                || iSrcX - nBlockXSize >= nLBlockX * nBlockXSize
                 || iSrcY < nLBlockY * nBlockYSize
-                || iSrcY >= (nLBlockY+1) * nBlockYSize )
+                || iSrcY - nBlockYSize >= nLBlockY * nBlockYSize )
             {
                 nLBlockX = iSrcX / nBlockXSize;
                 nLBlockY = iSrcY / nBlockYSize;
 
-                int bJustInitialize =
+                const bool bJustInitialize =
                     eRWFlag == GF_Write
                     && nYOff <= nLBlockY * nBlockYSize
-                    && nYOff + nYSize >= (nLBlockY+1) * nBlockYSize
+                    && nYOff + nYSize - nBlockYSize >= nLBlockY * nBlockYSize
                     && nXOff <= nLBlockX * nBlockXSize
-                    && nXOff + nXSize >= (nLBlockX+1) * nBlockXSize;
+                    && nXOff + nXSize - nBlockXSize >= nLBlockX * nBlockXSize;
                 /*bool bMemZeroBuffer = FALSE;
                 if( eRWFlag == GF_Write && !bJustInitialize &&
                     nXOff <= nLBlockX * nBlockXSize &&
                     nYOff <= nLBlockY * nBlockYSize &&
                     (nXOff + nXSize >= (nLBlockX+1) * nBlockXSize ||
-                     (nXOff + nXSize == GetRasterXSize() && (nLBlockX+1) * nBlockXSize > GetRasterXSize())) &&
+                     (nXOff + nXSize == GetRasterXSize() &&
+                     (nLBlockX+1) * nBlockXSize > GetRasterXSize())) &&
                     (nYOff + nYSize >= (nLBlockY+1) * nBlockYSize ||
-                     (nYOff + nYSize == GetRasterYSize() && (nLBlockY+1) * nBlockYSize > GetRasterYSize())) )
+                     (nYOff + nYSize == GetRasterYSize() &&
+                     (nLBlockY+1) * nBlockYSize > GetRasterYSize())) )
                 {
                     bJustInitialize = TRUE;
                     bMemZeroBuffer = TRUE;
                 }*/
-                for( iBand = 0; iBand < nBandCount; iBand++ )
+                for( int iBand = 0; iBand < nBandCount; iBand++ )
                 {
                     GDALRasterBand *poBand = GetRasterBand( panBandMap[iBand]);
                     if (nOverviewLevel >= 0)
@@ -3102,7 +3597,7 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
             iSrcOffset = ((GPtrDiff_t)iSrcX - (GPtrDiff_t)nLBlockX*nBlockXSize
                 + ((GPtrDiff_t)iSrcY - (GPtrDiff_t)nLBlockY*nBlockYSize) * nBlockXSize)*nBandDataSize;
 
-            for( iBand = 0; iBand < nBandCount; iBand++ )
+            for( int iBand = 0; iBand < nBandCount; iBand++ )
             {
                 GByte *pabySrcBlock = papabySrcBlock[iBand];
                 GPtrDiff_t iBandBufOffset = iBufOffset + (GPtrDiff_t)iBand * (GPtrDiff_t)nBandSpace;
@@ -3133,7 +3628,7 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
                 }
             }
 
-            iBufOffset += (int)nPixelSpace;
+            iBufOffset += static_cast<int>(nPixelSpace);
         }
     }
 
@@ -3144,7 +3639,7 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
     CPLFree( papabySrcBlock );
     if( papoBlocks != NULL )
     {
-        for( iBand = 0; iBand < nBandCount; iBand++ )
+        for( int iBand = 0; iBand < nBandCount; iBand++ )
         {
             if( papoBlocks[iBand] != NULL )
                 papoBlocks[iBand]->DropLock();
@@ -3152,22 +3647,26 @@ GDALDataset::BlockBasedRasterIO( GDALRWFlag eRWFlag,
         CPLFree( papoBlocks );
     }
 
-    return( eErr );
+    return eErr;
 }
+//! @endcond
 
 /************************************************************************/
 /*                  GDALCopyWholeRasterGetSwathSize()                   */
 /************************************************************************/
 
-static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
-                                            GDALRasterBand *poDstPrototypeBand,
-                                            int nBandCount,
-                                            int bDstIsCompressed, int bInterleave,
-                                            int* pnSwathCols, int *pnSwathLines)
+static void GDALCopyWholeRasterGetSwathSize(
+    GDALRasterBand *poSrcPrototypeBand,
+    GDALRasterBand *poDstPrototypeBand,
+    int nBandCount,
+    int bDstIsCompressed, int bInterleave,
+    int* pnSwathCols, int *pnSwathLines )
 {
     GDALDataType eDT = poDstPrototypeBand->GetRasterDataType();
-    int nSrcBlockXSize, nSrcBlockYSize;
-    int nBlockXSize, nBlockYSize;
+    int nSrcBlockXSize = 0;
+    int nSrcBlockYSize = 0;
+    int nBlockXSize = 0;
+    int nBlockYSize = 0;
 
     int nXSize = poSrcPrototypeBand->GetXSize();
     int nYSize = poSrcPrototypeBand->GetYSize();
@@ -3175,8 +3674,8 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
     poSrcPrototypeBand->GetBlockSize( &nSrcBlockXSize, &nSrcBlockYSize );
     poDstPrototypeBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
 
-    int nMaxBlockXSize = MAX(nBlockXSize, nSrcBlockXSize);
-    int nMaxBlockYSize = MAX(nBlockYSize, nSrcBlockYSize);
+    const int nMaxBlockXSize = std::max(nBlockXSize, nSrcBlockXSize);
+    const int nMaxBlockYSize = std::max(nBlockYSize, nSrcBlockYSize);
 
     int nPixelSize = GDALGetDataTypeSizeBytes(eDT);
     if( bInterleave)
@@ -3192,56 +3691,68 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
 /* -------------------------------------------------------------------- */
 /*      What will our swath size be?                                    */
 /* -------------------------------------------------------------------- */
-    /* When writing interleaved data in a compressed format, we want to be sure */
-    /* that each block will only be written once, so the swath size must not be */
-    /* greater than the block cache. */
+    // When writing interleaved data in a compressed format, we want to be sure
+    // that each block will only be written once, so the swath size must not be
+    // greater than the block cache.
     const char* pszSwathSize = CPLGetConfigOption("GDAL_SWATH_SIZE", NULL);
     int nTargetSwathSize;
     if( pszSwathSize != NULL )
         nTargetSwathSize = atoi(pszSwathSize);
     else
     {
-        /* As a default, take one 1/4 of the cache size */
-        nTargetSwathSize = (int)MIN(INT_MAX, GDALGetCacheMax64() / 4);
-
-        /* but if the minimum idal swath buf size is less, then go for it to */
-        /* avoid unnecessarily abusing RAM usage */
-        GIntBig nIdealSwathBufSize = (GIntBig)nSwathCols * nSwathLines * nPixelSize;
+      // As a default, take one 1/4 of the cache size.
+        nTargetSwathSize =
+            std::min(INT_MAX,
+                     static_cast<int>(GDALGetCacheMax64() / 4));
+
+        // but if the minimum idal swath buf size is less, then go for it to
+        // avoid unnecessarily abusing RAM usage.
+        GIntBig nIdealSwathBufSize =
+            static_cast<GIntBig>(nSwathCols) * nSwathLines * nPixelSize;
         if( pszSrcCompression != NULL && EQUAL(pszSrcCompression, "JPEG2000") &&
-            (!bDstIsCompressed || ((nSrcBlockXSize % nBlockXSize) == 0 && (nSrcBlockYSize % nBlockYSize) == 0)) )
+            (!bDstIsCompressed || ((nSrcBlockXSize % nBlockXSize) == 0 &&
+                                   (nSrcBlockYSize % nBlockYSize) == 0)) )
         {
-            nIdealSwathBufSize = MAX(nIdealSwathBufSize,
-                                     (GIntBig)nSwathCols * nSrcBlockYSize * nPixelSize);
+            nIdealSwathBufSize =
+                std::max( nIdealSwathBufSize,
+                          static_cast<GIntBig>(nSwathCols) *
+                          nSrcBlockYSize * nPixelSize) ;
         }
         if( nTargetSwathSize > nIdealSwathBufSize )
-            nTargetSwathSize = (int)nIdealSwathBufSize;
+            nTargetSwathSize = static_cast<int>(nIdealSwathBufSize);
     }
 
     if (nTargetSwathSize < 1000000)
         nTargetSwathSize = 1000000;
 
     /* But let's check that  */
-    if (bDstIsCompressed && bInterleave && nTargetSwathSize > GDALGetCacheMax64())
+    if( bDstIsCompressed && bInterleave &&
+        nTargetSwathSize > GDALGetCacheMax64() )
     {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                 "When translating into a compressed interleave format, the block cache size (" CPL_FRMT_GIB ") "
-                 "should be at least the size of the swath (%d) (GDAL_SWATH_SIZE config. option)", GDALGetCacheMax64(), nTargetSwathSize);
+        CPLError(
+            CE_Warning, CPLE_AppDefined,
+            "When translating into a compressed interleave format, "
+            "the block cache size (" CPL_FRMT_GIB ") "
+            "should be at least the size of the swath (%d) "
+            "(GDAL_SWATH_SIZE config. option)",
+            GDALGetCacheMax64(), nTargetSwathSize);
     }
 
 #define IS_DIVIDER_OF(x,y) ((y)%(x) == 0)
 #define ROUND_TO(x,y) (((x)/(y))*(y))
 
-    /* if both input and output datasets are tiled, that the tile dimensions */
-    /* are "compatible", try to stick  to a swath dimension that is a multiple */
-    /* of input and output block dimensions */
+    // if both input and output datasets are tiled, that the tile dimensions
+    // are "compatible", try to stick  to a swath dimension that is a multiple
+    // of input and output block dimensions.
     if (nBlockXSize != nXSize && nSrcBlockXSize != nXSize &&
         IS_DIVIDER_OF(nBlockXSize, nMaxBlockXSize) &&
         IS_DIVIDER_OF(nSrcBlockXSize, nMaxBlockXSize) &&
         IS_DIVIDER_OF(nBlockYSize, nMaxBlockYSize) &&
         IS_DIVIDER_OF(nSrcBlockYSize, nMaxBlockYSize))
     {
-        if (((GIntBig)nMaxBlockXSize) * nMaxBlockYSize * nPixelSize <=
-                                                    (GIntBig)nTargetSwathSize)
+        if( static_cast<GIntBig>(nMaxBlockXSize) *
+            nMaxBlockYSize * nPixelSize <=
+            static_cast<GIntBig>(nTargetSwathSize) )
         {
             nSwathCols = nTargetSwathSize / (nMaxBlockYSize * nPixelSize);
             nSwathCols = ROUND_TO(nSwathCols, nMaxBlockXSize);
@@ -3252,7 +3763,7 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
             nSwathLines = nMaxBlockYSize;
 
             if (((GIntBig)nSwathCols) * nSwathLines * nPixelSize >
-                                                    (GIntBig)nTargetSwathSize)
+                (GIntBig)nTargetSwathSize)
             {
                 nSwathCols  = nXSize;
                 nSwathLines = nBlockYSize;
@@ -3260,32 +3771,37 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
         }
     }
 
-    int nMemoryPerCol = nSwathCols * nPixelSize;
-
-    /* Do the computation on a big int since for example when translating */
-    /* the JPL WMS layer, we overflow 32 bits*/
-    GIntBig nSwathBufSize = (GIntBig)nMemoryPerCol * nSwathLines;
-    if (nSwathBufSize > (GIntBig)nTargetSwathSize)
+    const GIntBig nMemoryPerCol = static_cast<GIntBig>(nSwathCols) * nPixelSize;
+    const GIntBig nSwathBufSize = nMemoryPerCol * nSwathLines;
+    if( nSwathBufSize > static_cast<GIntBig>(nTargetSwathSize) )
     {
-        nSwathLines = nTargetSwathSize / nMemoryPerCol;
+        nSwathLines = static_cast<int>(nTargetSwathSize / nMemoryPerCol);
         if (nSwathLines == 0)
             nSwathLines = 1;
 
-        CPLDebug( "GDAL",
-              "GDALCopyWholeRasterGetSwathSize(): adjusting to %d line swath "
-              "since requirement (" CPL_FRMT_GIB " bytes) exceed target swath size (%d bytes) (GDAL_SWATH_SIZE config. option)",
-              nSwathLines, (GIntBig)nBlockYSize * nMemoryPerCol, nTargetSwathSize);
+        CPLDebug(
+            "GDAL",
+            "GDALCopyWholeRasterGetSwathSize(): adjusting to %d line swath "
+            "since requirement (" CPL_FRMT_GIB " bytes) exceed target swath "
+            "size (%d bytes) (GDAL_SWATH_SIZE config. option)",
+            nSwathLines,
+            nBlockYSize * nMemoryPerCol,
+            nTargetSwathSize);
     }
     // If we are processing single scans, try to handle several at once.
     // If we are handling swaths already, only grow the swath if a row
     // of blocks is substantially less than our target buffer size.
     else if( nSwathLines == 1
-        || nMemoryPerCol * nSwathLines < nTargetSwathSize / 10 )
+        || nMemoryPerCol * nSwathLines <
+                        static_cast<GIntBig>(nTargetSwathSize) / 10 )
     {
-        nSwathLines = MIN(nYSize,MAX(1,nTargetSwathSize/nMemoryPerCol));
+        nSwathLines =
+            std::min(nYSize, std::max(1,
+                     static_cast<int>(nTargetSwathSize / nMemoryPerCol)));
 
         /* If possible try to align to source and target block height */
-        if ((nSwathLines % nMaxBlockYSize) != 0 && nSwathLines > nMaxBlockYSize &&
+        if ((nSwathLines % nMaxBlockYSize) != 0 &&
+            nSwathLines > nMaxBlockYSize &&
             IS_DIVIDER_OF(nBlockYSize, nMaxBlockYSize) &&
             IS_DIVIDER_OF(nSrcBlockYSize, nMaxBlockYSize))
             nSwathLines = ROUND_TO(nSwathLines, nMaxBlockYSize);
@@ -3296,12 +3812,12 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
             (IS_DIVIDER_OF(nBlockXSize, nSrcBlockXSize) &&
              IS_DIVIDER_OF(nBlockYSize, nSrcBlockYSize))) )
     {
-        /* Typical use case: converting from Pleaiades that is 2048x2048 tiled */
-        if (nSwathLines < nSrcBlockYSize)
+        // Typical use case: converting from Pleaiades that is 2048x2048 tiled.
+        if( nSwathLines < nSrcBlockYSize )
         {
             nSwathLines = nSrcBlockYSize;
 
-            /* Number of pixels that can be read/write simultaneously */
+            // Number of pixels that can be read/write simultaneously.
             nSwathCols = nTargetSwathSize / (nSrcBlockXSize * nPixelSize);
             nSwathCols = ROUND_TO(nSwathCols, nSrcBlockXSize);
             if (nSwathCols == 0)
@@ -3309,17 +3825,20 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
             if (nSwathCols > nXSize)
                 nSwathCols = nXSize;
 
-            CPLDebug( "GDAL",
-              "GDALCopyWholeRasterGetSwathSize(): because of compression and too high block,\n"
-              "use partial width at one time");
+            CPLDebug(
+                "GDAL",
+                "GDALCopyWholeRasterGetSwathSize(): because of compression and "
+                "too high block, "
+                "use partial width at one time" );
         }
         else if ((nSwathLines % nSrcBlockYSize) != 0)
         {
             /* Round on a multiple of nSrcBlockYSize */
             nSwathLines = ROUND_TO(nSwathLines, nSrcBlockYSize);
-            CPLDebug( "GDAL",
-              "GDALCopyWholeRasterGetSwathSize(): because of compression, \n"
-              "round nSwathLines to block height : %d", nSwathLines);
+            CPLDebug(
+                "GDAL",
+                "GDALCopyWholeRasterGetSwathSize(): because of compression, "
+                "round nSwathLines to block height : %d", nSwathLines);
         }
     }
     else if (bDstIsCompressed)
@@ -3328,7 +3847,7 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
         {
             nSwathLines = nBlockYSize;
 
-            /* Number of pixels that can be read/write simultaneously */
+            // Number of pixels that can be read/write simultaneously.
             nSwathCols = nTargetSwathSize / (nSwathLines * nPixelSize);
             nSwathCols = ROUND_TO(nSwathCols, nBlockXSize);
             if (nSwathCols == 0)
@@ -3336,17 +3855,20 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
             if (nSwathCols > nXSize)
                 nSwathCols = nXSize;
 
-            CPLDebug( "GDAL",
-              "GDALCopyWholeRasterGetSwathSize(): because of compression and too high block,\n"
-              "use partial width at one time");
+            CPLDebug(
+                "GDAL",
+                "GDALCopyWholeRasterGetSwathSize(): because of compression and "
+                "too high block, "
+                "use partial width at one time" );
         }
         else if ((nSwathLines % nBlockYSize) != 0)
         {
-            /* Round on a multiple of nBlockYSize */
+            // Round on a multiple of nBlockYSize.
             nSwathLines = ROUND_TO(nSwathLines, nBlockYSize);
-            CPLDebug( "GDAL",
-              "GDALCopyWholeRasterGetSwathSize(): because of compression, \n"
-              "round nSwathLines to block height : %d", nSwathLines);
+            CPLDebug(
+                "GDAL",
+                "GDALCopyWholeRasterGetSwathSize(): because of compression, "
+                "round nSwathLines to block height : %d", nSwathLines);
         }
     }
 
@@ -3371,10 +3893,15 @@ static void GDALCopyWholeRasterGetSwathSize(GDALRasterBand *poSrcPrototypeBand,
  * in particular "chunking" the copy in substantial blocks and, if appropriate,
  * performing the transfer in a pixel interleaved fashion.
  *
- * Currently the only papszOptions value supported are : "INTERLEAVE=PIXEL"
- * to force pixel interleaved operation and "COMPRESSED=YES" to force alignment
- * on target dataset block sizes to achieve best compression.  More options may be supported in
- * the future.
+ * Currently the only papszOptions value supported are :
+ * <ul>
+ * <li>"INTERLEAVE=PIXEL" to force pixel interleaved operation</li>
+ * <li>"COMPRESSED=YES" to force alignment on target dataset block sizes to
+ * achieve best compression.</li>
+ * <li>"SKIP_HOLES=YES" to skip chunks for which GDALGetDataCoverageStatus()
+ * returns GDAL_DATA_COVERAGE_STATUS_EMPTY (GDAL >= 2.2)</li>
+ * </ul>
+ * More options may be supported in the future.
  *
  * @param hSrcDS the source dataset
  * @param hDstDS the destination dataset
@@ -3395,7 +3922,6 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
 
     GDALDataset *poSrcDS = (GDALDataset *) hSrcDS;
     GDALDataset *poDstDS = (GDALDataset *) hDstDS;
-    CPLErr eErr = CE_None;
 
     if( pfnProgress == NULL )
         pfnProgress = GDALDummyProgress;
@@ -3403,9 +3929,9 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
 /* -------------------------------------------------------------------- */
 /*      Confirm the datasets match in size and band counts.             */
 /* -------------------------------------------------------------------- */
-    int nXSize = poDstDS->GetRasterXSize(),
-        nYSize = poDstDS->GetRasterYSize(),
-        nBandCount = poDstDS->GetRasterCount();
+    const int nXSize = poDstDS->GetRasterXSize();
+    const int nYSize = poDstDS->GetRasterYSize();
+    const int nBandCount = poDstDS->GetRasterCount();
 
     if( poSrcDS->GetRasterXSize() != nXSize
         || poSrcDS->GetRasterYSize() != nYSize
@@ -3442,43 +3968,46 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
 /*      Do we want to try and do the operation in a pixel               */
 /*      interleaved fashion?                                            */
 /* -------------------------------------------------------------------- */
-    int bInterleave = FALSE;
+    bool bInterleave = false;
     const char *pszInterleave = NULL;
 
     pszInterleave = poSrcDS->GetMetadataItem( "INTERLEAVE", "IMAGE_STRUCTURE");
     if( pszInterleave != NULL
         && (EQUAL(pszInterleave,"PIXEL") || EQUAL(pszInterleave,"LINE")) )
-        bInterleave = TRUE;
+        bInterleave = true;
 
     pszInterleave = poDstDS->GetMetadataItem( "INTERLEAVE", "IMAGE_STRUCTURE");
     if( pszInterleave != NULL
         && (EQUAL(pszInterleave,"PIXEL") || EQUAL(pszInterleave,"LINE")) )
-        bInterleave = TRUE;
+        bInterleave = true;
 
     pszInterleave = CSLFetchNameValue( papszOptions, "INTERLEAVE" );
     if( pszInterleave != NULL
-        && (EQUAL(pszInterleave,"PIXEL") || EQUAL(pszInterleave,"LINE")) )
-        bInterleave = TRUE;
-    else if( pszInterleave != NULL && EQUAL(pszInterleave,"BAND") )
-        bInterleave = FALSE;
-
-    /* If the destination is compressed, we must try to write blocks just once, to save */
-    /* disk space (GTiff case for example), and to avoid data loss (JPEG compression for example) */
-    int bDstIsCompressed = FALSE;
-    const char* pszDstCompressed= CSLFetchNameValue( papszOptions, "COMPRESSED" );
+        && (EQUAL(pszInterleave, "PIXEL") || EQUAL(pszInterleave, "LINE")) )
+        bInterleave = true;
+    else if( pszInterleave != NULL && EQUAL(pszInterleave, "BAND") )
+        bInterleave = false;
+
+    // If the destination is compressed, we must try to write blocks just once,
+    // to save disk space (GTiff case for example), and to avoid data loss
+    // (JPEG compression for example).
+    bool bDstIsCompressed = false;
+    const char* pszDstCompressed =
+        CSLFetchNameValue( papszOptions, "COMPRESSED" );
     if (pszDstCompressed != NULL && CPLTestBool(pszDstCompressed))
-        bDstIsCompressed = TRUE;
+        bDstIsCompressed = true;
 
 /* -------------------------------------------------------------------- */
 /*      What will our swath size be?                                    */
 /* -------------------------------------------------------------------- */
 
-    int nSwathCols, nSwathLines;
-    GDALCopyWholeRasterGetSwathSize(poSrcPrototypeBand,
-                                    poDstPrototypeBand,
-                                    nBandCount,
-                                    bDstIsCompressed, bInterleave,
-                                    &nSwathCols, &nSwathLines);
+    int nSwathCols = 0;
+    int nSwathLines = 0;
+    GDALCopyWholeRasterGetSwathSize( poSrcPrototypeBand,
+                                     poDstPrototypeBand,
+                                     nBandCount,
+                                     bDstIsCompressed, bInterleave,
+                                     &nSwathCols, &nSwathLines );
 
     int nPixelSize = GDALGetDataTypeSizeBytes(eDT);
     if( bInterleave)
@@ -3491,79 +4020,100 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
     }
 
     CPLDebug( "GDAL",
-            "GDALDatasetCopyWholeRaster(): %d*%d swaths, bInterleave=%d",
-            nSwathCols, nSwathLines, bInterleave );
+              "GDALDatasetCopyWholeRaster(): %d*%d swaths, bInterleave=%d",
+              nSwathCols, nSwathLines, static_cast<int>(bInterleave) );
 
     if( nSwathCols == nXSize && poSrcDS->GetDriver() != NULL &&
         EQUAL(poSrcDS->GetDriver()->GetDescription(), "ECW") )
     {
-        poSrcDS->AdviseRead(0, 0, nXSize, nYSize, nXSize, nYSize, eDT, nBandCount, NULL, NULL);
+        poSrcDS->AdviseRead( 0, 0, nXSize, nYSize, nXSize, nYSize, eDT,
+                             nBandCount, NULL, NULL);
     }
 
 /* ==================================================================== */
 /*      Band oriented (uninterleaved) case.                             */
 /* ==================================================================== */
+    CPLErr eErr = CE_None;
+    const bool bCheckHoles = CPLTestBool( CSLFetchNameValueDef(
+                                        papszOptions, "SKIP_HOLES", "NO" ) );
+
     if( !bInterleave )
     {
-        int iBand, iX, iY;
-
         GDALRasterIOExtraArg sExtraArg;
         INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
-        int nTotalBlocks = nBandCount *
-                           ((nYSize + nSwathLines - 1) / nSwathLines) *
-                           ((nXSize + nSwathCols - 1) / nSwathCols);
-        int nBlocksDone = 0;
+        const GIntBig nTotalBlocks =
+            static_cast<GIntBig>(nBandCount) *
+            DIV_ROUND_UP(nYSize, nSwathLines) *
+            DIV_ROUND_UP(nXSize, nSwathCols);
+        GIntBig nBlocksDone = 0;
 
-        for( iBand = 0; iBand < nBandCount && eErr == CE_None; iBand++ )
+        for( int iBand = 0; iBand < nBandCount && eErr == CE_None; iBand++ )
         {
-            int nBand = iBand+1;
+            int nBand = iBand + 1;
 
-            for( iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
+            for( int iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
             {
                 int nThisLines = nSwathLines;
 
                 if( iY + nThisLines > nYSize )
                     nThisLines = nYSize - iY;
 
-                for( iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
+                for( int iX = 0;
+                     iX < nXSize && eErr == CE_None;
+                     iX += nSwathCols )
                 {
                     int nThisCols = nSwathCols;
 
                     if( iX + nThisCols > nXSize )
                         nThisCols = nXSize - iX;
 
-                    sExtraArg.pfnProgress = GDALScaledProgress;
-                    sExtraArg.pProgressData =
-                        GDALCreateScaledProgress( nBlocksDone / (double)nTotalBlocks,
-                                                (nBlocksDone + 0.5) / (double)nTotalBlocks,
-                                                pfnProgress,
-                                                pProgressData );
-                    if( sExtraArg.pProgressData == NULL )
-                        sExtraArg.pfnProgress = NULL;
-
-                    eErr = poSrcDS->RasterIO( GF_Read,
-                                            iX, iY, nThisCols, nThisLines,
-                                            pSwathBuf, nThisCols, nThisLines,
-                                            eDT, 1, &nBand,
-                                            0, 0, 0, &sExtraArg );
-
-                    GDALDestroyScaledProgress( sExtraArg.pProgressData );
+                    int nStatus = GDAL_DATA_COVERAGE_STATUS_DATA;
+                    if( bCheckHoles )
+                    {
+                        nStatus = poSrcDS->GetRasterBand(nBand)->GetDataCoverageStatus(
+                              iX, iY, nThisCols, nThisLines,
+                              GDAL_DATA_COVERAGE_STATUS_DATA);
+                    }
+                    if( nStatus & GDAL_DATA_COVERAGE_STATUS_DATA )
+                    {
+                        sExtraArg.pfnProgress = GDALScaledProgress;
+                        sExtraArg.pProgressData =
+                            GDALCreateScaledProgress(
+                                nBlocksDone / static_cast<double>(nTotalBlocks),
+                                (nBlocksDone + 0.5) /
+                                static_cast<double>(nTotalBlocks),
+                                pfnProgress,
+                                pProgressData );
+                        if( sExtraArg.pProgressData == NULL )
+                            sExtraArg.pfnProgress = NULL;
+
+                        eErr = poSrcDS->RasterIO( GF_Read,
+                                                  iX, iY, nThisCols, nThisLines,
+                                                  pSwathBuf, nThisCols, nThisLines,
+                                                  eDT, 1, &nBand,
+                                                  0, 0, 0, &sExtraArg );
+
+                        GDALDestroyScaledProgress( sExtraArg.pProgressData );
+
+                        if( eErr == CE_None )
+                            eErr = poDstDS->RasterIO( GF_Write,
+                                                      iX, iY, nThisCols, nThisLines,
+                                                      pSwathBuf, nThisCols,
+                                                      nThisLines,
+                                                      eDT, 1, &nBand,
+                                                      0, 0, 0, NULL );
+                    }
 
-                    if( eErr == CE_None )
-                        eErr = poDstDS->RasterIO( GF_Write,
-                                                iX, iY, nThisCols, nThisLines,
-                                                pSwathBuf, nThisCols, nThisLines,
-                                                eDT, 1, &nBand,
-                                                0, 0, 0, NULL );
-                    nBlocksDone ++;
+                    nBlocksDone++;
                     if( eErr == CE_None
-                        && !pfnProgress( nBlocksDone / (double)nTotalBlocks,
-                                        NULL, pProgressData ) )
+                        && !pfnProgress(
+                            nBlocksDone / static_cast<double>(nTotalBlocks),
+                            NULL, pProgressData ) )
                     {
                         eErr = CE_Failure;
                         CPLError( CE_Failure, CPLE_UserInterrupt,
-                                "User terminated CreateCopy()" );
+                                  "User terminated CreateCopy()" );
                     }
                 }
             }
@@ -3575,57 +4125,73 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
 /* ==================================================================== */
     else /* if( bInterleave ) */
     {
-        int iY, iX;
-
         GDALRasterIOExtraArg sExtraArg;
         INIT_RASTERIO_EXTRA_ARG(sExtraArg);
 
-        int nTotalBlocks = ((nYSize + nSwathLines - 1) / nSwathLines) *
-                           ((nXSize + nSwathCols - 1) / nSwathCols);
-        int nBlocksDone = 0;
+        const GIntBig nTotalBlocks =
+            static_cast<GIntBig>(DIV_ROUND_UP(nYSize, nSwathLines)) *
+            DIV_ROUND_UP(nXSize, nSwathCols);
+        GIntBig nBlocksDone = 0;
 
-        for( iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
+        for( int iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
         {
             int nThisLines = nSwathLines;
 
             if( iY + nThisLines > nYSize )
                 nThisLines = nYSize - iY;
 
-            for( iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
+            for( int iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
             {
                 int nThisCols = nSwathCols;
 
                 if( iX + nThisCols > nXSize )
                     nThisCols = nXSize - iX;
 
-                sExtraArg.pfnProgress = GDALScaledProgress;
-                sExtraArg.pProgressData =
-                    GDALCreateScaledProgress( nBlocksDone / (double)nTotalBlocks,
-                                            (nBlocksDone + 0.5) / (double)nTotalBlocks,
-                                            pfnProgress,
-                                            pProgressData );
-                if( sExtraArg.pProgressData == NULL )
-                    sExtraArg.pfnProgress = NULL;
+                int nStatus = GDAL_DATA_COVERAGE_STATUS_DATA;
+                if( bCheckHoles )
+                {
+                    for( int iBand = 0; iBand < nBandCount; iBand++ )
+                    {
+                        nStatus |= poSrcDS->GetRasterBand(iBand+1)->GetDataCoverageStatus(
+                          iX, iY, nThisCols, nThisLines,
+                          GDAL_DATA_COVERAGE_STATUS_DATA);
+                        if( nStatus & GDAL_DATA_COVERAGE_STATUS_DATA )
+                            break;
+                    }
+                }
+                if( nStatus & GDAL_DATA_COVERAGE_STATUS_DATA )
+                {
+                    sExtraArg.pfnProgress = GDALScaledProgress;
+                    sExtraArg.pProgressData =
+                        GDALCreateScaledProgress(
+                            nBlocksDone / static_cast<double>(nTotalBlocks),
+                            (nBlocksDone + 0.5) / static_cast<double>(nTotalBlocks),
+                            pfnProgress,
+                            pProgressData );
+                    if( sExtraArg.pProgressData == NULL )
+                        sExtraArg.pfnProgress = NULL;
 
-                eErr = poSrcDS->RasterIO( GF_Read,
-                                        iX, iY, nThisCols, nThisLines,
-                                        pSwathBuf, nThisCols, nThisLines,
-                                        eDT, nBandCount, NULL,
-                                        0, 0, 0, &sExtraArg );
+                    eErr = poSrcDS->RasterIO( GF_Read,
+                                              iX, iY, nThisCols, nThisLines,
+                                              pSwathBuf, nThisCols, nThisLines,
+                                              eDT, nBandCount, NULL,
+                                              0, 0, 0, &sExtraArg );
 
-                GDALDestroyScaledProgress( sExtraArg.pProgressData );
+                    GDALDestroyScaledProgress( sExtraArg.pProgressData );
 
-                if( eErr == CE_None )
-                    eErr = poDstDS->RasterIO( GF_Write,
-                                            iX, iY, nThisCols, nThisLines,
-                                            pSwathBuf, nThisCols, nThisLines,
-                                            eDT, nBandCount, NULL,
-                                            0, 0, 0, NULL );
+                    if( eErr == CE_None )
+                        eErr = poDstDS->RasterIO( GF_Write,
+                                                  iX, iY, nThisCols, nThisLines,
+                                                  pSwathBuf, nThisCols, nThisLines,
+                                                  eDT, nBandCount, NULL,
+                                                  0, 0, 0, NULL );
+                }
 
-                nBlocksDone ++;
-                if( eErr == CE_None
-                    && !pfnProgress( nBlocksDone / (double)nTotalBlocks,
-                                    NULL, pProgressData ) )
+                nBlocksDone++;
+                if( eErr == CE_None &&
+                    !pfnProgress(
+                        nBlocksDone / static_cast<double>( nTotalBlocks ),
+                        NULL, pProgressData ) )
                 {
                     eErr = CE_Failure;
                     CPLError( CE_Failure, CPLE_UserInterrupt,
@@ -3643,7 +4209,6 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
     return eErr;
 }
 
-
 /************************************************************************/
 /*                     GDALRasterBandCopyWholeRaster()                  */
 /************************************************************************/
@@ -3659,9 +4224,13 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
  * It implements efficient copying, in particular "chunking" the copy in
  * substantial blocks.
  *
- * Currently the only papszOptions value supported is : "COMPRESSED=YES" to
- * force alignment on target dataset block sizes to achieve best compression.
- * More options may be supported in the future.
+ * Currently the only papszOptions value supported are :
+ * <ul>
+ * <li>"COMPRESSED=YES" to force alignment on target dataset block sizes to
+ * achieve best compression.</li>
+ * <li>"SKIP_HOLES=YES" to skip chunks for which GDALGetDataCoverageStatus()
+ * returns GDAL_DATA_COVERAGE_STATUS_EMPTY (GDAL >= 2.2)</li>
+ * </ul>
  *
  * @param hSrcBand the source band
  * @param hDstBand the destination band
@@ -3673,15 +4242,16 @@ CPLErr CPL_STDCALL GDALDatasetCopyWholeRaster(
  */
 
 CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
-    GDALRasterBandH hSrcBand, GDALRasterBandH hDstBand, char **papszOptions,
+    GDALRasterBandH hSrcBand, GDALRasterBandH hDstBand,
+    const char * const * const papszOptions,
     GDALProgressFunc pfnProgress, void *pProgressData )
 
 {
     VALIDATE_POINTER1( hSrcBand, "GDALRasterBandCopyWholeRaster", CE_Failure );
     VALIDATE_POINTER1( hDstBand, "GDALRasterBandCopyWholeRaster", CE_Failure );
 
-    GDALRasterBand *poSrcBand = (GDALRasterBand *) hSrcBand;
-    GDALRasterBand *poDstBand = (GDALRasterBand *) hDstBand;
+    GDALRasterBand *poSrcBand = static_cast<GDALRasterBand *>( hSrcBand );
+    GDALRasterBand *poDstBand = static_cast<GDALRasterBand *>( hDstBand );
     CPLErr eErr = CE_None;
 
     if( pfnProgress == NULL )
@@ -3690,8 +4260,8 @@ CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
 /* -------------------------------------------------------------------- */
 /*      Confirm the datasets match in size and band counts.             */
 /* -------------------------------------------------------------------- */
-    int nXSize = poSrcBand->GetXSize(),
-        nYSize = poSrcBand->GetYSize();
+    int nXSize = poSrcBand->GetXSize();
+    int nYSize = poSrcBand->GetYSize();
 
     if( poDstBand->GetXSize() != nXSize
         || poDstBand->GetYSize() != nYSize )
@@ -3714,23 +4284,26 @@ CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
 
     GDALDataType eDT = poDstBand->GetRasterDataType();
 
-    /* If the destination is compressed, we must try to write blocks just once, to save */
-    /* disk space (GTiff case for example), and to avoid data loss (JPEG compression for example) */
-    int bDstIsCompressed = FALSE;
-    const char* pszDstCompressed= CSLFetchNameValue( papszOptions, "COMPRESSED" );
+    // If the destination is compressed, we must try to write blocks just once,
+    // to save disk space (GTiff case for example), and to avoid data loss
+    // (JPEG compression for example).
+    bool bDstIsCompressed = false;
+    const char* pszDstCompressed =
+        CSLFetchNameValue( const_cast<char **>(papszOptions), "COMPRESSED" );
     if (pszDstCompressed != NULL && CPLTestBool(pszDstCompressed))
-        bDstIsCompressed = TRUE;
+        bDstIsCompressed = true;
 
 /* -------------------------------------------------------------------- */
 /*      What will our swath size be?                                    */
 /* -------------------------------------------------------------------- */
 
-    int nSwathCols, nSwathLines;
-    GDALCopyWholeRasterGetSwathSize(poSrcBand,
-                                    poDstBand,
-                                    1,
-                                    bDstIsCompressed, FALSE,
-                                    &nSwathCols, &nSwathLines);
+    int nSwathCols = 0;
+    int nSwathLines = 0;
+    GDALCopyWholeRasterGetSwathSize( poSrcBand,
+                                     poDstBand,
+                                     1,
+                                     bDstIsCompressed, FALSE,
+                                     &nSwathCols, &nSwathLines);
 
     const int nPixelSize = GDALGetDataTypeSizeBytes(eDT);
 
@@ -3741,48 +4314,59 @@ CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
     }
 
     CPLDebug( "GDAL",
-            "GDALRasterBandCopyWholeRaster(): %d*%d swaths",
-            nSwathCols, nSwathLines );
+              "GDALRasterBandCopyWholeRaster(): %d*%d swaths",
+              nSwathCols, nSwathLines );
+
+    const bool bCheckHoles = CPLTestBool( CSLFetchNameValueDef(
+                    papszOptions, "SKIP_HOLES", "NO" ) );
 
 /* ==================================================================== */
 /*      Band oriented (uninterleaved) case.                             */
 /* ==================================================================== */
 
-    int iX, iY;
-
-    for( iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
+    for( int iY = 0; iY < nYSize && eErr == CE_None; iY += nSwathLines )
     {
         int nThisLines = nSwathLines;
 
         if( iY + nThisLines > nYSize )
             nThisLines = nYSize - iY;
 
-        for( iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
+        for( int iX = 0; iX < nXSize && eErr == CE_None; iX += nSwathCols )
         {
             int nThisCols = nSwathCols;
 
             if( iX + nThisCols > nXSize )
                 nThisCols = nXSize - iX;
 
-            eErr = poSrcBand->RasterIO( GF_Read,
-                                    iX, iY, nThisCols, nThisLines,
-                                    pSwathBuf, nThisCols, nThisLines,
-                                    eDT, 0, 0, NULL );
+            int nStatus = GDAL_DATA_COVERAGE_STATUS_DATA;
+            if( bCheckHoles )
+            {
+                nStatus = poSrcBand->GetDataCoverageStatus(
+                        iX, iY, nThisCols, nThisLines,
+                        GDAL_DATA_COVERAGE_STATUS_DATA);
+            }
+            if( nStatus & GDAL_DATA_COVERAGE_STATUS_DATA )
+            {
+                eErr = poSrcBand->RasterIO( GF_Read,
+                                            iX, iY, nThisCols, nThisLines,
+                                            pSwathBuf, nThisCols, nThisLines,
+                                            eDT, 0, 0, NULL );
 
-            if( eErr == CE_None )
-                eErr = poDstBand->RasterIO( GF_Write,
-                                        iX, iY, nThisCols, nThisLines,
-                                        pSwathBuf, nThisCols, nThisLines,
-                                        eDT, 0, 0, NULL );
+                if( eErr == CE_None )
+                    eErr = poDstBand->RasterIO( GF_Write,
+                                                iX, iY, nThisCols, nThisLines,
+                                                pSwathBuf, nThisCols, nThisLines,
+                                                eDT, 0, 0, NULL );
+            }
 
             if( eErr == CE_None
                 && !pfnProgress(
-                    (iY+nThisLines) / (float) (nYSize),
+                    (iY + nThisLines) / static_cast<float>(nYSize),
                     NULL, pProgressData ) )
             {
                 eErr = CE_Failure;
                 CPLError( CE_Failure, CPLE_UserInterrupt,
-                        "User terminated CreateCopy()" );
+                          "User terminated CreateCopy()" );
             }
         }
     }
@@ -3795,13 +4379,12 @@ CPLErr CPL_STDCALL GDALRasterBandCopyWholeRaster(
     return eErr;
 }
 
-
 /************************************************************************/
 /*                      GDALCopyRasterIOExtraArg ()                     */
 /************************************************************************/
 
-void GDALCopyRasterIOExtraArg(GDALRasterIOExtraArg* psDestArg,
-                              GDALRasterIOExtraArg* psSrcArg)
+void GDALCopyRasterIOExtraArg( GDALRasterIOExtraArg* psDestArg,
+                               GDALRasterIOExtraArg* psSrcArg )
 {
     INIT_RASTERIO_EXTRA_ARG(*psDestArg);
     if( psSrcArg )
@@ -3809,7 +4392,8 @@ void GDALCopyRasterIOExtraArg(GDALRasterIOExtraArg* psDestArg,
         psDestArg->eResampleAlg = psSrcArg->eResampleAlg;
         psDestArg->pfnProgress = psSrcArg->pfnProgress;
         psDestArg->pProgressData = psSrcArg->pProgressData;
-        psDestArg->bFloatingPointWindowValidity = psSrcArg->bFloatingPointWindowValidity;
+        psDestArg->bFloatingPointWindowValidity =
+            psSrcArg->bFloatingPointWindowValidity;
         if( psSrcArg->bFloatingPointWindowValidity )
         {
             psDestArg->dfXOff = psSrcArg->dfXOff;
diff --git a/gcore/rasterio_ssse3.cpp b/gcore/rasterio_ssse3.cpp
new file mode 100644
index 0000000..bc7acc7
--- /dev/null
+++ b/gcore/rasterio_ssse3.cpp
@@ -0,0 +1,129 @@
+/******************************************************************************
+ *
+ * Project:  GDAL Core
+ * Purpose:  SSSE3 specializations
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_port.h"
+
+CPL_CVSID("$Id: rasterio_ssse3.cpp 35095 2016-08-13 23:35:28Z rouault $");
+
+#if defined(HAVE_SSSE3_AT_COMPILE_TIME) && ( defined(__x86_64) || defined(_M_X64) )
+
+#include <tmmintrin.h>
+#include "gdal_priv_templates.hpp"
+
+void GDALUnrolledCopy_GByte_3_1_SSSE3( GByte* CPL_RESTRICT pDest,
+                                             const GByte* CPL_RESTRICT pSrc,
+                                             int nIters );
+
+void GDALUnrolledCopy_GByte_4_1_SSSE3( GByte* CPL_RESTRICT pDest,
+                                             const GByte* CPL_RESTRICT pSrc,
+                                             int nIters );
+
+void GDALUnrolledCopy_GByte_3_1_SSSE3( GByte* CPL_RESTRICT pDest,
+                                             const GByte* CPL_RESTRICT pSrc,
+                                             int nIters )
+{
+    int i;
+    const __m128i xmm_shuffle0 = _mm_set_epi8(-1  ,-1  ,-1  ,-1,
+                                              -1  ,-1  ,-1  ,-1,
+                                              -1  ,-1  ,15  ,12,
+                                              9   ,6   ,3   ,0);
+    const __m128i xmm_shuffle1 = _mm_set_epi8(-1  ,-1  ,-1  ,-1,
+                                              -1  ,14  ,11  ,8,
+                                              5   ,2   ,-1  ,-1,
+                                              -1  ,-1  ,-1  ,-1);
+    const __m128i xmm_shuffle2 = _mm_set_epi8(13  ,10  ,7   ,4,
+                                              1   ,-1  ,-1  ,-1,
+                                              -1  ,-1  ,-1  ,-1,
+                                              -1  ,-1  ,-1  ,-1);
+    // If we were sure that there would always be 2 trailing bytes, we could
+    // check against nIters - 15
+    for ( i = 0; i < nIters - 16; i += 16 )
+    {
+        __m128i xmm0 = _mm_loadu_si128( (__m128i const*) (pSrc + 0) );
+        __m128i xmm1 = _mm_loadu_si128( (__m128i const*) (pSrc + 16) );
+        __m128i xmm2 = _mm_loadu_si128( (__m128i const*) (pSrc + 32) );
+
+        // From LSB to MSB:
+        // 0,x,x,1,x,x,2,x,x,3,x,x,4,x,x,5 --> 0,1,2,3,4,5,0,0,0,0,0,0,0,0,0
+        xmm0 = _mm_shuffle_epi8(xmm0, xmm_shuffle0);
+        // x,x,6,x,x,7,x,x,8,x,x,9,x,x,10,x --> 0,0,0,0,0,0,6,7,8,9,10,0,0,0,0,0
+        xmm1 = _mm_shuffle_epi8(xmm1, xmm_shuffle1);
+        // x,11,x,x,12,x,x,13,x,x,14,x,x,15,x,x --> 0,0,0,0,0,0,0,0,0,0,0,11,12,13,14,15
+        xmm2 = _mm_shuffle_epi8(xmm2, xmm_shuffle2);
+        xmm0 = _mm_or_si128(xmm0, xmm1);
+        xmm0 = _mm_or_si128(xmm0, xmm2);
+
+        _mm_storeu_si128( (__m128i*) (pDest + i), xmm0);
+
+        pSrc += 3 * 16;
+    }
+    for( ; i < nIters; i++ )
+    {
+        pDest[i] = *pSrc;
+        pSrc += 3;
+    }
+}
+
+void GDALUnrolledCopy_GByte_4_1_SSSE3( GByte* CPL_RESTRICT pDest,
+                                             const GByte* CPL_RESTRICT pSrc,
+                                             int nIters )
+{
+    int i;
+    const __m128i xmm_shuffle0 = _mm_set_epi8(-1  ,-1  ,-1  ,-1,
+                                              -1  ,-1  ,-1  ,-1,
+                                              -1  ,-1  ,-1  ,-1,
+                                              12  ,8   ,4   ,0);
+    // If we were sure that there would always be 3 trailing bytes, we could
+    // check against nIters - 15
+    for ( i = 0; i < nIters - 16; i += 16 )
+    {
+        __m128i xmm0 = _mm_loadu_si128( (__m128i const*) (pSrc + 0) );
+        __m128i xmm1 = _mm_loadu_si128( (__m128i const*) (pSrc + 16) );
+        __m128i xmm2 = _mm_loadu_si128( (__m128i const*) (pSrc + 32) );
+        __m128i xmm3 = _mm_loadu_si128( (__m128i const*) (pSrc + 48) );
+
+        xmm0 = _mm_shuffle_epi8(xmm0, xmm_shuffle0);
+        xmm1 = _mm_shuffle_epi8(xmm1, xmm_shuffle0);
+        xmm2 = _mm_shuffle_epi8(xmm2, xmm_shuffle0);
+        xmm3 = _mm_shuffle_epi8(xmm3, xmm_shuffle0);
+
+        // Extract lower 32 bit word
+        GDALCopyXMMToInt32(xmm0, pDest + i + 0);
+        GDALCopyXMMToInt32(xmm1, pDest + i + 4);
+        GDALCopyXMMToInt32(xmm2, pDest + i + 8);
+        GDALCopyXMMToInt32(xmm3, pDest + i + 12);
+        pSrc += 4 * 16;
+    }
+    for( ; i < nIters; i++ )
+    {
+        pDest[i] = *pSrc;
+        pSrc += 4;
+    }
+}
+
+#endif // HAVE_SSSE3_AT_COMPILE_TIME
diff --git a/gcore/statistics.txt b/gcore/statistics.txt
new file mode 100644
index 0000000..e902aa5
--- /dev/null
+++ b/gcore/statistics.txt
@@ -0,0 +1,549 @@
+Author: Even Rouault, 2016
+
+Speeding up raster statistics in GDAL using SSE2/AVX2
+-----------------------------------------------------
+
+GDAL offers a method ComputeStatistics() that given a raster band returns
+the minimum and maximum values of pixels, the mean value and the standard
+deviation.
+
+For those not remembering how to compute mean and standard deviations, the basic
+formulas for values indexed from 0 to N-1 are :
+mean = sum(value(i) for i = 0 to N-1) / N
+
+std_dev = square root of mean of the square of the differences of values to the mean
+std_dev = sqrt(sum(i = 0 to N-1, (value(i) - mean)^2)) / N)
+
+A very naive version would first compute the mean, and in a second pass compute
+the standard deviation.
+
+But it can be easily proven (by expanding the (value(i) - mean)^2 term),that it
+is also equivalent to :
+std_dev = sqrt(sum(i = 0 to N-1, value(i)^2)/N - mean^2)
+ie
+std_dev = sqrt(mean_of_square_values - square_of_mean)
+
+std_dev = sqrt(sum(i = 0 to N-1, value(i)^2)/N - (sum_of_values/N)^2)
+std_dev = sqrt(N^2 *(sum(i = 0 to N-1, value(i)^2)/N - (sum_of_values/N)^2)) / N
+std_dev = sqrt(N * sum_of_square_values - sum_of_values^2) / N
+
+A less naive implementation would compute the sum of values and the sum of
+square values in a single pass. However the standard deviation computed like that
+might be subject to numeric
+instability given that even if the result is small, sum_of_square_values and
+sum_of_values can be very big for a big number of pixels, and thus if
+represented with floating point numbers, the difference between both
+terms can be wrong.
+
+Welford algorithm
+-----------------
+
+So in recent GDAL versions, the computation of the mean and standard deviation
+is done in a progressive and numerically stable way, thanks to the Welford algorithm :
+https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
+
+The generic code is:
+
+    pixel_counter = 0
+    mean = 0
+    M2 = 0
+    foreach(value in all pixels):
+        if value < minimum or pixel_counter == 0: minimum = value
+        if value > maximum or pixel_counter == 0: maximum = value
+        pixel_counter = pixel_counter + 1
+        delta = value - mean
+        mean = mean + delta / pixel_counter
+        M2 = M2 + delta * (value - mean);
+
+    std_dev = sqrt( M2 / pixel_counter )
+
+Proof of Welford algorithm
+--------------------------
+
+(You can skip this paragraph and still follow the rest of this article)
+
+The magic of Welford algorithm lies in the following recurrence relations.
+
+For the mean, it is relatively obvious :
+N*mean(N) = sum(i = 0 to N-1, value(i))
+N*mean(N) = sum(i = 0 to N-2, value(i)) + value(N-1)
+N*mean(N) = (N-1) * mean(N-1) + value(N-1)
+mean(N) = (N-1)/N * mean(N-1) + value(N-1)/N
+mean(N) = mean(N-1) + (value(N-1) - mean(N-1)) / N
+Hence mean = mean + delta / pixel_counter
+
+For the standard deviation, the proof is a little bit more lengthy :
+
+N*stddev(N)^2 = sum(i=0 to N-1, (value(i) - mean(N))^2 )
+
+N*stddev(N)^2 = sum(i=0 to N-1, (value(i) - (mean(N-1) + (value(N-1) - mean(N-1)) / N))^2 )
+
+N*stddev(N)^2 = sum(i=0 to N-1, ((value(i) - mean(N-1)) - ((value(N-1) - mean(N-1)) / N))^2 )
+
+N*stddev(N)^2 = sum(i=0 to N-1, (value(i) - mean(N-1))^2 + ((value(N-1) - mean(N-1)) / N)^2
+                    - 2 * (value(i) - mean(N-1))*((value(N-1) - mean(N-1)) / N)  )
+
+N*stddev(N)^2 = sum(i=0 to N-1, (value(i) - mean(N-1))^2) + N * ((value(N-1) - mean(N-1)) / N)^2
+                    - 2 * sum(i=0 to N-1, (value(i) - mean(N-1)))*((value(N-1) - mean(N-1)) / N))
+
+N*stddev(N)^2 = (N-1)*stddev(N-1)^2 +  (value(N-1) - mean(N-1)) ^2
+                    +  N * ((value(N-1) - mean(N-1)) / N)^2
+                    - 2 * sum(i=0 to N-1, (value(i) - mean(N-1)))*((value(N-1) - mean(N-1)) / N))
+
+N*stddev(N)^2 = (N-1)*stddev(N-1)^2 + (value(N-1) - mean(N-1))^2 * (1 + 1 / N)
+                    - 2 * N( mean(N) - mean(N-1)) *((value(N-1) - mean(N-1)) / N))
+
+N*stddev(N)^2 = (N-1)*stddev(N-1)^2 + (value(N-1) - mean(N-1)) *
+            ((1 + 1 / N) *  (value(N-1) - mean(N-1)) - 2 * N( mean(N) - mean(N-1)) / N))
+
+N*stddev(N)^2 = (N-1)*stddev(N-1)^2 + (value(N-1) - mean(N-1)) *
+            ((value(N-1) - mean(N-1) + (value(N-1) - mean(N-1) / N - 2 * N( mean(N) - mean(N-1)) / N))
+
+N*stddev(N)^2 = (N-1)*stddev(N-1)^2 + (value(N-1) - mean(N-1)) *
+            ((value(N-1) - mean(N-1) - (mean(N) - mean(N-1))))
+
+N*stddev(N)^2 = (N-1)*stddev(N-1)^2 + (value(N-1) - mean(N-1)) * (value(N-1) - mean(N))
+Hence M2 = M2 + delta * (value - mean)
+
+Integer based computation of standard deviation
+-----------------------------------------------
+
+The Welford algorithm is good but it involves floating point operations for
+each pixel to compute the progressive mean and variance. Whereas fundamentally
+we would need those floating point operations only at the end if using the
+original formulas, and we could use integer arithmetics for the rest.
+Another drawback of Welford approach is that it prevents any
+parallelization whereas if you have a set of values, you can conceptually divide
+it in as many subsets you want, and for each subset compute its local minimum,
+maximum, sum of values and sum of square values. Merging subsets is then trivial:
+take the minimum of minimums, maximum of maximums, sums of sum of values and
+sums of sum of square values.
+
+Let us consider the case of pixels whose type is unsigned byte, ie with values in the
+range [0,255]. We want to compute
+std_dev = sqrt(N * sum_of_square_values - sum_of_values^2) / N
+
+For practical reasons, we want N, sum_of_square_values and sum_of_values to fit
+on a 64bit unsigned integer (uint64), which is the largest natural integral type that
+can be easily and efficiently used on today's CPUs.
+The most limiting factor will be sum_of_square_values. Given that in the worse
+case, a square value is equal to 255*255, the maximum number of pixels N we
+can address is (2^64-1) / (255*255) = 283 686 952 306 183, which is large
+enough to represent a raster of 16 million pixels x 16 million pixels. Good enough.
+
+We know need to be able to multiply two uint64 values and get the
+result as a uint128, and compute the difference of two uint128 values. The
+multiplication on Intel/AMD CPUs in 64bit mode natively yields to a 128 bit wide
+result.
+It is just that there is no standardized way in C/C++ how to get that result.
+For GCC compiler in 64 bit mode, the __uint128_t type can be used in a transparent way
+to do that :
+__uint128_t result = (__uint128_t)operand_64bit * other_operand_64bit
+
+For Visual Studio compilers in 64 bit mode, a special instruction _umul128() is available.
+
+What about non-Intel or non-64bit CPUs ? In that case, we have to do the
+multiplication at hand by decomposing each uint64 values into its lower uint32
+and uint32 parts, doing 4 uint32*uint32->uint64 multiplications, summing the
+intermediary results, handling the carries and building the resulting number.
+Not very efficient, but we do not really care about that, since it is just a
+final operation.
+
+To make it is easier, that partial 128 bit arithmetics is abstracted in a
+GDALUInt128 C++ class that has different implementations regarding the CPU and
+compiler support.
+
+https://github.com/OSGeo/gdal/blob/c905203b4b4a745d4f63a6738c17713bf8c81f95/gdal/gcore/gdalrasterband.cpp#L3589
+
+Now that we have solved the final part of the computation, we can then write
+the computation loop as following :
+
+    minimum = maximum = value[0]
+    foreach value:
+        if value < minimum: minimum = value
+        else if value > maximum: maximum = value
+        sum = sum + value
+        sum_square = sum_square + value * value
+
+Can we do better ? A bit of loop unrolling can help :
+
+    minimum = maximum = value[0]
+    foreach value pair (value1, value2):
+        if value1 < minimum: minimum = value1
+        else if value1 > maximum: maximum = value1
+        sum = sum + value1
+        sum_square = sum_square + value1 * value1
+        if value < minimum: minimum = value2
+        else if value > maximum: maximum = value2
+        sum = sum + value2
+        sum_square = sum_square + value2 * value2
+    (deal with potential remaining pixel if odd number of pixels)
+
+If we start with comparing value1 and value2, we can actually save a
+comparison (resulting in 3 comparisons instead of 4) :
+
+    minimum = maximum = value[0]
+    foreach value pair (value1, value2):
+        if value1 < value2:
+            if value1 < minimum: minimum = value1
+            if value2 > maximum: maximum = value2
+        else:
+            if value2 < minimum: minimum = value2
+            if value1 > maximum: maximum = value1
+        sum = sum + value1
+        sum_square = sum_square + value1 * value1
+        sum = sum + value2
+        sum_square = sum_square + value2 * value2
+    (deal with potential remaining pixel if odd number of pixels)
+
+This improvement can already dramatically reduce the computation time from
+1m10 to 7s, to compute 50 times the statistics on a 10000 x 10000 pixel raster.
+
+Parallelization with SSE2
+-------------------------
+
+We have not yet explored the parallelization of the algorithm. One way to do
+it would be to do multi-threading, but for Intel-compatible CPU, we can
+also explore the capabilities of the SIMD (Single Instruction/Multiple Data)
+instruction set. On 64bit Intel, the SSE2 instruction set, which offers
+vectorized operations on integers, is guaranteed to be always present.
+16 registers (XMM0 to XMM15) are available, each 128 bit wide.
+
+https://en.wikipedia.org/wiki/SSE2
+
+So each register is wide enough to hold 16 packed int8/uint8, 8 packed int16/uint16,
+4 packed int32/uint32 or 2 packed int64/uint64, depending on the wished representation.
+A diverse set of operations are offered and generally operate on the sub-parts
+of each register independently. For example c=_mm_add_epi8(a,b) will add
+independently c[i]=a[i]+b[i] for i=0 to 15, and that in just one CPU cycle.
+_mm_add_epi16() will work on packed uint16, etc. To add some salt, not all
+operators are available for all elementary subtypes however.
+
+Compilers are supposed to be able to automatically vectorize some C code, but
+in practice they rarely manage to do so for real world code, hence requiring
+the programmer to use the SIMD instruction set at hand.
+All major compilers (gcc, clang, Visual Studio C/C++) offer access to the SSE2
+instruction set through "intrinsics", which are C inline functions that wrap
+the corresponding assembly instructions, but while still being C/C++.
+This allows the compiler to do the register allocation and various other
+optimizations (such as re-ordering), which is a huge win over coding directly
+in assembly. The Intel intrinsics guide is a useful resource to find the
+appropriate intrinsics :
+https://software.intel.com/sites/landingpage/IntrinsicsGuide/#
+
+So a temptative vectorized version of our algorithm would be :
+
+    v_minimum = vector_of_16_bytes[0]
+    v_maximum = vector_of_16_bytes[0]
+    v_sum = vector_of_16_zeros
+    v_sum_square = vector_of_16_zeros
+
+    foreach vector_of_16_bytes v:
+        v_minimum = vector_minimum(v_minimum, v)
+        v_maximum = vector_maximum(v_maximum, v)
+        v_sum = vector_add(v_sum, v)
+        v_sum_square = vector_sum(v_sum_square, vector_mul(v, v))
+
+    minimum = minimum_of_16_values(v_minimum)
+    maximum = maximum_of_16_values(v_minimum)
+    sum = sum_of_X??_values(v_sum)
+    sum_square = sum_of_X??_values(v_sum_square)
+    (deal with potential remaining pixels if number of pixels is not multiple of 16)
+
+vector_minimum and vector_maximum do exist as _mm_min_epu8 and _mm_max_epu8.
+But for vector_add, which variant to use _mm_add_epi8, _mm_add_epi16, _mm_add_epi32
+or _mm_add_epi64 ? Well, none directly. We want to add uint8 values, but the
+result cannot fit on a uint8 (255+255=510). The same holds for sum_square. The result of
+each square multiplication requires at least a uint16, and we want to loop
+several times, so we need at least a width of uint32 to hold the accumulation.
+We designed the overall algorithm to be able to handle an accumulator of
+uint64, but this would decrease the performance of the vectorization if using
+that in the tigher loop. So we will decompose our loop into one upper loop and
+and one inner loop. The inner loop will do as many iterations as possible, while
+still not overflowing a uint32 accumulator. So (2^32-1)/(255*255) = 66051.xxxx
+iterations. Which we round down to the closest multiple of 16.
+
+So what about v_sum = vector_add(v_sum, v) ?
+The first idea would be to extract the 4 lowest order bytes of v, unpack them
+so that they fit each on a uint32 and then use _mm_add_epi32 to add them in
+the v_sum accumulator.
+
+    v_sum = _mm_add_epi32(v_sum, _mm_unpacklo_epi16(_mm_unpacklo_epi8(v, zero), zero)
+
+_mm_unpacklo_epi8(v, zero) expands the 8 lowest order bytes of v as 8 uint16.
+And similarly _mm_unpacklo_epi16(v, zero)  expands the 4 lowest order uint16 of v as 4 uint32.
+
+And then repeat that with the 3 other groups of 4 bytes :
+
+    v_sum = _mm_add_epi32(v_sum, _mm_unpacklo_epi16(_mm_unpacklo_epi8(_mm_shuffle_epi32(v, 1), zero), zero)
+    v_sum = _mm_add_epi32(v_sum, _mm_unpacklo_epi16(_mm_unpacklo_epi8(_mm_shuffle_epi32(v, 2), zero), zero)
+    v_sum = _mm_add_epi32(v_sum, _mm_unpacklo_epi16(_mm_unpacklo_epi8(_mm_shuffle_epi32(v, 3), zero), zero)
+
+But we can do better thans to the _mm_sad_epu8 intrinsics :
+https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=sad&techs=SSE2
+
+It is designed to "compute the absolute differences of packed unsigned 8-bit
+integers in a and b, then horizontally sum each consecutive 8 differences to
+produce two unsigned 16-bit integers, and pack these unsigned 16-bit integers
+in the low 16 bits of 64-bit elements in dst." If we notice that ABS(x-0) = x
+when x >= 0, then it does what we want.
+
+    v_sum = _mm_add_epi64(v_sum, _mm_sad_epu8(v, zero))
+
+Pedantic note: we can actually use _mm_add_epi32, since there is no risk of overflow :
+8 * 66051 * 255 fits on a uint32. The advantage of using _mm_add_epi32 is that as
+we will use it elsewhere, the compiler can re-order additions to group them in pairs
+and benefit from their 0.5 throughput.
+
+_mm_sad_epu8() has a relatively high latency (5 cycles), but it is still a big win
+since it replaces 14 intrinsics of our initial version.
+
+What about the computation of the square value ? There is no mnemonics to directly
+multiply packed bytes and get the resulting packed uint16 (or even better uint32,
+since that is the type we want to operate on eventually to be able to do several
+iterations of our loop!).
+One approach would be to take the 8 lowest order bytes, un-pack them to uint16,
+use the  _mm_mullo_epi16() intrinsics that does uint16 x uint16->uint16.
+Then you would take the 4 lowest order uint16
+of this intermediate result, un-pack them to uint32 and finally use _mm_add_epi32
+to accumulate them in v_sum_square.
+
+    v_low = _mm_unpacklo_epi8(v, zero)
+    v_low_square = _mm_mullo_epi16(v_low, v_low)
+    v_sum_square = _mm_add_epi32(v_sum_square, _mm_unpacklo_epi16(v_low_square, zero)
+
+Then repeat the operation with the 4 upper
+order uint16 of the intermediate result.
+
+    v_sum_square = _mm_add_epi32(v_sum_square,
+        _mm_unpacklo_epi16(_mm_shuffle_epi32(v_low_square, 2 | (3 <<2)), zero) )
+
+_mm_shuffle_epi32(v, 2 | (3 <<2) is a trick to replicate the high 64 bits of
+a XMM register into its low 64 bits. We don't care about the values of the
+resulting high 64 bits since they will be lost with the later unpack operations.
+
+And then repeat the whole process with the 8 highest order bytes.
+
+    v_high = _mm_unpacklo_epi8(_mm_shuffle_epi32(v, 2 | (3 <<2)), zero)
+    v_high_square = _mm_mullo_epi16(v_high, v_high)
+    v_sum_square = _mm_add_epi32(v_sum_square, _mm_unpacklo_epi16(v_high_square, zero)
+    v_sum_square = _mm_add_epi32(v_sum_square,
+        _mm_unpacklo_epi16(_mm_shuffle_epi32(v_high_square, 2 | (3 <<2)), zero) )
+
+We can actually do much better with the _mm_madd_epi16() mnemonics
+https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=madd&techs=SSE2
+that "Multiply packed signed 16-bit integers in a and b, producing intermediate
+signed 32-bit integers. Horizontally add adjacent pairs of intermediate 32-bit
+integers, and pack the results"
+This is really close to what we need. We just need to prepare uint16/int16 integers
+(the sign convention here does not matter since a uint8 zero-extended to 16 bit
+is both a uint16/int16)
+
+    v_low_16bit = _mm_unpacklo_epi8(v, zero)
+    v_sum_square = _mm_add_epi32(v_sum_square, _mm_madd_epi16(v_low_16bit, v_low_16bit))
+    v_high_16bit = _mm_unpacklo_epi8(_mm_shuffle_epi32(v, 2 | (3 <<2)), zero)
+    v_sum_square = _mm_add_epi32(v_sum_square, _mm_madd_epi16(v_high_16bit, v_high_16bit))
+
+The latencies and throughput of _mm_mullo_epi16 and _mm_madd_epi16 are the same,
+so the second version is clearly a big win.
+
+Use of AVX2
+-----------
+
+We can tweak performance a bit by doing a 2x loop unrolling, which will enable
+the compiler to re-order some operations so that those who have a throughput of
+0.5 cycle to be consecutive (such as _mm_add_epi32, _mm_unpacklo_epi8) and thus
+be able to executive 2 of them in a single cycle. When doing so, we can notice
+that we are operating on a virtual 256 bit register. But 256 bit registers do
+exist in the AVX2 instruction set, that was introduced in relatively recent
+hardware (2013 for Intel Haswell). AVX/AVX2 offer the YMM registers, equivalent of
+XMM registers but on a doubled bit width (the 128 bit low part of a YMM register
+is its corresponding XMM register). One particularity of the YMM register is
+that it operates on quite distinct "128 bit lanes", but you can still extract
+each lane.
+
+The port to AVX2 is quite straightforward :
+
+    v = _mm256_load_si256(data + i)
+    v_sum = _mm256_add_epi32(v_sum, _mm256_sad_epu8(v, zero))
+    v_low_16bit = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(v, 0));
+    v_sum_square = _mm256_add_epi32(v_sum_square, _mm256_madd_epi16(v_low_16bit, v_low_16bit))
+    v_high_16bit = _mm256_cvtepu8_epi16(_mm256_extracti128_si256(v, 1));
+    v_sum_square = _mm_add_epi32(v_sum_square, _mm_madd_epi16(v_high_16bit, v_high_16bit))
+
+_mm256_extracti128_si256(v,0) extracts the 128 bit lower part of the register,
+and _mm256_extracti128_si256(v,1) the 128 bit upper part.
+
+The good news is that we can have a single code base for the SSE2 and AVX2 variants,
+by using the AVX2 code. In the case of SSE2, we in fact define the _mm256 functions
+with their corresponding _mm 128bit functions operating on the low and high 128 bit
+parts. For example:
+
+static inline GDALm256i GDALmm256_add_epi32(GDALm256i r1, GDALm256i r2)
+{
+    GDALm256i reg;
+    reg.low = _mm_add_epi32(r1.low, r2.low);
+    reg.high = _mm_add_epi32(r1.high, r2.high);
+    return reg;
+}
+
+The AVX2-with-SSE2 emulation can be found in :
+https://github.com/OSGeo/gdal/blob/trunk/gdal/gcore/gdal_avx2_emulation.hpp
+
+Thanks to inlining and usual compiler optimizations, this will be equivalent to
+our hand 2x unrolled version !
+
+The final result is in :
+https://github.com/OSGeo/gdal/blob/c905203b4b4a745d4f63a6738c17713bf8c81f95/gdal/gcore/gdalrasterband.cpp#L4030
+
+Regarding timings, our SSE2-emulated AVX2 version runs in 1.6s, so roughly a 4x
+time improvement with respect to the portable optimized C version. On a hardware capable of AVX2,
+the pure AVX2 version is 15% faster than the SSE2-emulated version. So definitely
+not enough to justify a dedicated code path, but here as we have a unified one,
+it comes almost for free. Provided that the code is explicitly compiled to enable
+AVX2.
+
+Nodata values
+-------------
+
+Up to now, we have ignored the potential existence of nodata values. When computing
+statistics, we do not want pixels that match the nodata value to be taken into
+account in the minimum, maximum, mean or standard deviation.
+
+In the pure C approach, this is easy. Just ignore pixels that match the nodata value:
+
+    minimum = maximum = value[0]
+    foreach value:
+        if value != nodata:
+            valid_pixels = valid_pixels + 1
+            minimum = min(minimum, value)
+            maximum = max(minimum, value)
+            sum = sum + value
+            sum_square = sum_square + value * value
+
+We cannot directly translate that with SSE2/AVX2 mnemonics since the result
+of the value != nodata test can be different for each of the 32 packed bytes of
+the (virtual) AVX2 register, and making tests for each components of the vector
+register would kill performance to a point where it would be worse than the pure
+C approach !
+
+We can however rewrite the above in a vector friendly way with :
+
+    minimum = maximum = first value that is not nodata
+    neutral_value = minimum (or any value in final [min,max] range that is not nodata)
+    foreach value:
+        validity_flag = if (value != nodata) 0xFF else 0
+        value_potentially_set_to_zero = value & validity_flag
+        value_potentially_set_to_neutral = (value & validity_flag) | (neutral_value & ~validity_flag)
+        valid_pixels = valid_pixels + validity_flag / 255
+        minimum = min(minimum, value_potentially_set_to_neutral)
+        maximum = max(minimum, value_potentially_set_to_neutral)
+        sum = sum + value_potentially_set_to_zero
+        sum_square = sum_square + value_potentially_set_to_zero * value_potentially_set_to_zero
+
+(value & validity_flag) | (neutral_value & ~validity_flag) is a quite common pattern
+in SIMD code to implement a if/then/else pattern without branches.
+
+The only complication is that there is no SSE2 intrinsics for non-equality testing, so we have
+to transform that a bit to use equality testing only. And we will also remove
+the need for division in the loop :
+
+    foreach value:
+        invalidity_flag = if (value == nodata) 0xFF else 0
+        value_potentially_set_to_zero = value & ~invalidity_flag
+        value_potentially_set_to_neutral = (value & ~invalidity_flag) | (neutral_value & invalidity_flag)
+        invalid_pixels_mul_255 = invalid_pixels_mul_255 + invalidity_flag
+        minimum = min(minimum, value_potentially_set_to_neutral)
+        maximum = max(minimum, value_potentially_set_to_neutral)
+        sum = sum + value_potentially_set_to_zero
+        sum_square = sum_square + value_potentially_set_to_zero * value_potentially_set_to_zero
+
+    valid_pixels = total_pixels - invalid_pixels_mul_255 / 255
+
+The computation of invalid_pixels_mul_255 in a vectorized way is the same as
+v_sum, using the _mm_sad_epu8() trick. The resulting SSE2 code is :
+
+    foreach vector_of_16_bytes v:
+        v_invalidity_flag = _mm_cmpeq_epi8(v, v_nodata)
+        v_value_potentially_set_to_zero = _mm_andnot_si128(v_invalidity_flag, v)
+        v_value_potentially_set_to_neutral = _mm_or_si128(
+            v_value_potentially_set_to_zero, _mm_and_si128(v_invalidity_flag, v_neutral))
+        v_invalid_pixels_mul_255 = _mm_add_epi32(invalid_pixels_mul_255,
+                                        _mm_sad_epu8(v_invalidity_flag, zero))
+        [ code for min, max operating on v_value_potentially_set_to_neutral ]
+        [ code for sum and sum_square operating on v_value_potentially_set_to_zero ]
+
+The transposition to AVX2 is straightforward.
+
+The final result is in :
+https://github.com/OSGeo/gdal/blob/c905203b4b4a745d4f63a6738c17713bf8c81f95/gdal/gcore/gdalrasterband.cpp#L3901
+
+We can notice that this version that takes into account nodata value can only
+be used once we have hit a pixel that is not the nodata value, to be able to
+initialize the neutral value.
+
+What about uint16 rasters ?
+---------------------------
+
+The same general principles apply. If we still want to limit ourselves to
+operate with at most uint64 accumulators, given that the maximum square value
+of a uint16 is 65535*65535, this limits to rasters of 2^64/(65535*65535) ~=
+2 billion pixels, which remains acceptable for common use cases.
+
+One oddity of the SSE2 instruction set is that it includes only a _mm_min_epi16()/_mm_max_epi16()
+mnemonics, that is to say that operates on signed int16. The _mm_min_epu16() that
+operates on uint16 has been introduced in the later SSE4.1 instruction set (that is
+quite commonly found in not so recent CPUs).
+
+There are tricks to emulate _mm_min_epu16() in pure SSE2 using saturated
+subtraction and masking :
+
+    // if x <= y, then mask bits will be set to 1.
+    mask = _mm_cmpeq_epi16( _mm_subs_epu16(x, y), zero )
+
+    // select bits from x when mask is 1, y otherwise
+    min(x,y) = _mm_or_si128(_mm_and_si128(mask, x), _mm_andnot_si128(mask, y));
+
+Another way is to shift the unsigned values by -32768, so as to operate on
+signed 16bit values.
+
+This -32768 shift trick is also necessary since, like for the byte case, we want
+to still be able to use the _madd_epi16 intrinsics, which operates on signed int16,
+to compute the sum of square values. One subtelty to observe is that when you
+operate on 2 consecutive pixels at 0, _mm_madd_epi16 does :
+
+ (0 - 32768) * (0 - 32768) + (0 - 32768) * (0 - 32768)
+= 1073741824 + 1073741824
+= 2147483648 = 2^31
+
+Which actually overflows the range of signed int32 ( [-2^31, 2^31-1] ) ! The good
+news is that _mm_madd_epi16 does not saturate the result, so it will actually
+return 0x80000000 as a result. This should normally be interpreted as -2^31 in
+signed int32 convention, but as we know that the result of _madd_epi16(x,x) is
+necessary positive values, we can still correctly interpret the result as a uint32
+value. This is where you feel lucky that Intel chose two's complement convention
+for signed integers.
+
+To compute the sum of values, no nice trick equivalent to _mm_sad_epu8. So we just
+do it the boring way: unpack separately the 64bit low and high part of the value
+register from uint16 to uint32 and accumulate them with _mm_add_epi32.
+
+Exactly as for the byte case, the uint16 case can be easily transposed to AVX2 or
+emulated-AVX2.
+
+The final result is in :
+https://github.com/OSGeo/gdal/blob/c905203b4b4a745d4f63a6738c17713bf8c81f95/gdal/gcore/gdalrasterband.cpp#L4149
+
+
+Conclusion
+----------
+
+Conversion between integer and floating-point operations can be costly, so
+avoiding them as much as possible is a big win (provided that you make sure
+not to overflow your integer accumulators)
+
+In theory, the gains offered by a SSE2/AVX2 optimized version are at most
+limited to a factor of with_of_vector_register / with_of_elementary_type, so,
+for bytes and SSE2, to 16. But often the gain is lesser, so do that only when
+you have come to an already optimized portable C version (or if the SIMD instruction
+set includes a dedicated intrinsics that just do what you want)
diff --git a/generate_vcxproj.bat b/generate_vcxproj.bat
new file mode 100644
index 0000000..4e8f554
--- /dev/null
+++ b/generate_vcxproj.bat
@@ -0,0 +1,490 @@
+ at echo off
+
+:: ****************************************************************************
+::  $Id: $
+:: 
+::  Name:     generate_vcxproj.bat
+::  Project:  GDAL 
+::  Purpose:  Generate MS Visual C++ => 10.0 project files    
+::  Author:   Ivan Lucena, [ivan lucena at outlook dot com]
+:: 
+:: ****************************************************************************
+::  Copyright (c) 2007, Ivan Lucena    
+:: 
+::  Permission is hereby granted, free of charge, to any person obtaining a
+::  copy of this software and associated documentation files (the "Software"),
+::  to deal in the Software without restriction, including without limitation
+::  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+::  and/or sell copies of the Software, and to permit persons to whom the
+::  Software is furnished to do so, subject to the following conditions:
+:: 
+::  The above copyright notice and this permission notice shall be included
+::  in all copies or substantial portions of the Software.
+:: 
+::  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+::  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+::  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+::  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+::  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+::  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+::  DEALINGS IN THE SOFTWARE.
+:: ****************************************************************************
+setlocal
+
+if "%1"=="" (
+   goto :usage
+)
+
+if "%2"=="" (
+   goto :usage
+)
+
+if "%3"=="" (
+   goto :usage
+)
+
+::  *********************
+::  Get Visual C++ version
+::  *********************
+
+set _vcver_=%1
+
+set _clver_=1600
+set _vstoolset_=v100
+
+if "%_vcver_%"=="15.0" (
+	set _clver_=1910
+	set _vstoolset_=v141
+) else if "%_vcver_%"=="14.0" (
+	set _clver_=1900
+	set _vstoolset_=v140
+) else ( if "%_vcver_%"=="12.0" (
+	set _clver_=1800
+	set _vstoolset_=v120
+) else ( if "%_vcver_%"=="11.0" (
+	set _clver_=1700
+	set _vstoolset_=v110
+) else ( if "%_vcver_%"=="10.0" (
+	set _clver_=1600
+	set _vstoolset_=v100
+) else (
+    echo Wrong value for parameter 1. See usage:
+	goto :usage
+))))
+
+::  *********************
+::  Get Platform
+::  *********************
+
+set _platf_=%2
+set _buildplatf_=x86
+set _winver_=Win32
+set _nmake_opt_win64_=
+
+if not "%_platf_%"=="32" (
+    if not "%_platf_%"=="64" (
+	    echo Wrong value for parameter 2. See usage:
+	    goto :usage
+    )
+)
+
+if "%_platf_%"=="64" (
+    set _winver_=x64
+    set _buildplatf_=x64
+    set _nmake_opt_win64_=WIN64=1
+)
+
+goto :continue
+
+::  *********************
+:usage
+::  *********************
+
+echo Usage: generate_vcxproj ^<Visual C++ version^> [32^|64] ^<^(*^) project file name^>
+echo Parameters:
+echo    1 : Visual C++ version is not the same as Visual Studio version ^( =^> 10.0 ^)
+echo    2 : Windows platform 32 for Win32 and 64 for Win64
+echo    3 : Base file name, with no path and no extension ^(*^)
+echo Examples:
+echo    generate_vcxproj 10.1 32 gdal_vs2010
+echo    generate_vcxproj 11.0 64 gdal_vs2012
+echo    generate_vcxproj 12.0 64 gdal_vs2013
+echo    generate_vcxproj 14.0 64 gdal_vs2015
+echo    generate_vcxproj 15.0 64 gdal_vs2017
+
+goto :end
+
+::  *********************
+::  Set Project file names
+::  *********************
+
+:continue
+
+set _gdaldir_=%CD%
+set _testdir_=
+FOR /F %%i IN ("%_gdaldir_%\..\autotest\cpp") DO (
+    if exist "%%~fi" set _testdir_=%%~fi
+)
+
+set _gdalsln_=%_gdaldir_%\%3.sln
+set _gdalproj_=%_gdaldir_%\%3.vcxproj
+set _gdaluser_=%_gdalproj_%.user
+set _gdalfltr_=%_gdalproj_%.filters
+set _testproj_=%_testdir_%\%3_test.vcxproj
+set _testuser_=%_testproj_%.user
+set _testfltr_=%_testproj_%.filters
+
+:: Add quotes
+
+set _gdalproj_="%_gdalproj_%"
+set _gdaluser_="%_gdaluser_%"
+set _gdalfltr_="%_gdalfltr_%"
+set _testproj_="%_testproj_%"
+set _testuser_="%_testuser_%"
+set _testfltr_="%_testfltr_%"
+
+:: Progress message
+
+echo Generating:
+echo   %_gdalproj_%
+echo   %_gdaluser_%
+echo   %_gdalfltr_%
+
+if defined _testdir_ (
+    echo   %_testproj_%
+    echo   %_testuser_%
+    echo   %_testfltr_%
+)
+:: if defined _testdir_
+
+echo This might take a little while...
+
+:: Delete existing files
+
+if exist %_gdalproj_% (
+  del %_gdalproj_%
+)
+
+if exist %_gdaluser_% ( 
+  del %_gdaluser_%
+)
+
+if exist %_gdalfltr_% ( 
+  del %_gdalfltr_%
+)
+
+if exist %_testproj_% (
+  del %_testproj_%
+)
+
+if exist %_testuser_% ( 
+  del %_testuser_%
+)
+
+if exist %_testfltr_% ( 
+  del %_testfltr_%
+)
+
+:: **********************************************
+:: Generate project user files (.vcxproj.user)
+:: **********************************************
+
+echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_gdaluser_%
+echo ^<Project ToolsVersion="%_vcver_%" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>   >> %_gdaluser_%
+echo     ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>  >> %_gdaluser_%
+echo       ^<DebuggerFlavor^>WindowsLocalDebugger^</DebuggerFlavor^>                       >> %_gdaluser_%
+echo       ^<LocalDebuggerDebuggerType^>Auto^</LocalDebuggerDebuggerType^>                 >> %_gdaluser_%
+echo       ^<LocalDebuggerCommand^>%CD%\apps\gdal_translate.exe^</LocalDebuggerCommand^>   >> %_gdaluser_%
+echo       ^<LocalDebuggerCommandArguments^>--formats^</LocalDebuggerCommandArguments^>    >> %_gdaluser_%
+echo       ^<LocalDebuggerEnvironment^>CPL_DEBUG=ON                                        >> %_gdaluser_%
+echo       GDAL_DATA=%_gdaldir_%\data                                                      >> %_gdaluser_%
+echo       ^</LocalDebuggerEnvironment^>                                                   >> %_gdaluser_%
+echo     ^</PropertyGroup^>                                     >> %_gdaluser_%
+echo ^</Project^>                                               >> %_gdaluser_%
+
+if defined _testdir_ (
+echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_testuser_%
+echo ^<Project ToolsVersion="%_vcver_%" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>   >> %_testuser_%
+echo     ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>  >> %_testuser_%
+echo       ^<DebuggerFlavor^>WindowsLocalDebugger^</DebuggerFlavor^>                       >> %_testuser_%
+echo       ^<LocalDebuggerDebuggerType^>Auto^</LocalDebuggerDebuggerType^>                 >> %_testuser_%
+echo       ^<LocalDebuggerCommand^>%_testdir_%\gdal_unit_test.exe^</LocalDebuggerCommand^> >> %_testuser_%
+echo       ^<LocalDebuggerCommandArguments^>^</LocalDebuggerCommandArguments^>             >> %_testuser_%
+echo       ^<LocalDebuggerEnvironment^>CPL_DEBUG=ON                                        >> %_testuser_%
+echo       GDAL_DATA=%_gdaldir_%\data                                                      >> %_testuser_%
+echo       ^</LocalDebuggerEnvironment^>                                                   >> %_testuser_%
+echo     ^</PropertyGroup^>                                     >> %_testuser_%
+echo ^</Project^>                                               >> %_testuser_%
+)
+:: if defined _testdir_
+
+:: **********************************************
+:: Initialize filters files (.vcxproj.filters)
+:: **********************************************
+
+echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_gdalfltr_%
+echo ^<Project ToolsVersion="5.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>         >> %_gdalfltr_%
+
+:: **********************************************
+:: Main file generator (.vcxproj) and filters file (.vcxproj.filters)
+:: **********************************************
+
+echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_gdalproj_%
+echo ^<Project DefaultTargets="Build" ToolsVersion="%_vcver_%" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>          >> %_gdalproj_%
+echo   ^<ItemGroup Label="ProjectConfigurations"^>              >> %_gdalproj_%
+echo     ^<ProjectConfiguration Include="Debug|%_winver_%"^>    >> %_gdalproj_%
+echo       ^<Configuration^>Debug^</Configuration^>             >> %_gdalproj_%
+echo       ^<Platform^>%_winver_%^</Platform^>                  >> %_gdalproj_%
+echo     ^</ProjectConfiguration^>                              >> %_gdalproj_%
+echo     ^<ProjectConfiguration Include="Release|%_winver_%"^>  >> %_gdalproj_%
+echo       ^<Configuration^>Release^</Configuration^>           >> %_gdalproj_%
+echo       ^<Platform^>%_winver_%^</Platform^>                  >> %_gdalproj_%
+echo     ^</ProjectConfiguration^>                              >> %_gdalproj_%
+echo   ^</ItemGroup^>                                           >> %_gdalproj_% 
+echo   ^<PropertyGroup Label="Globals"^>                        >> %_gdalproj_%
+echo     ^<Keyword^>MakeFileProj^</Keyword^>                    >> %_gdalproj_%
+echo   ^</PropertyGroup^>                                       >> %_gdalproj_%
+echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /^>  >> %_gdalproj_%   
+echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'" Label="Configuration"^>    >> %_gdalproj_%
+echo     ^<ConfigurationType^>Makefile^</ConfigurationType^>    >> %_gdalproj_%
+echo     ^<UseDebugLibraries^>true^</UseDebugLibraries^>        >> %_gdalproj_%
+echo     ^<PlatformToolset^>%_vstoolset_%^</PlatformToolset^>            >> %_gdalproj_%
+echo   ^</PropertyGroup^>                                       >> %_gdalproj_%
+echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|%_winver_%'" Label="Configuration"^>  >> %_gdalproj_%
+echo     ^<ConfigurationType^>Makefile^</ConfigurationType^>    >> %_gdalproj_%
+echo     ^<UseDebugLibraries^>true^</UseDebugLibraries^>        >> %_gdalproj_%
+echo     ^<PlatformToolset^>%_vstoolset_%^</PlatformToolset^>            >> %_gdalproj_%
+echo   ^</PropertyGroup^>                                       >> %_gdalproj_%
+echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /^>      >> %_gdalproj_%
+echo   ^<ImportGroup Label="ExtensionSettings"^>                >> %_gdalproj_%  
+echo   ^</ImportGroup^>                                         >> %_gdalproj_%
+echo   ^<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>     >> %_gdalproj_% 
+echo     ^<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /^>    >> %_gdalproj_%
+echo   ^</ImportGroup^>                                         >> %_gdalproj_%
+echo   ^<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|%_winver_%'"^>  >> %_gdalproj_%
+echo     ^<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /^>     >> %_gdalproj_%
+echo   ^</ImportGroup^>                                         >> %_gdalproj_%
+echo   ^<PropertyGroup Label="UserMacros" /^>                   >> %_gdalproj_%
+echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>     >> %_gdalproj_%
+echo     ^<NMakeBuildCommandLine^>nmake -f makefile.vc MSVC_VER=%_clver_% %_nmake_opt_win64_% DEBUG=1 WITH_PDB=1^</NMakeBuildCommandLine^>            >> %_gdalproj_%
+echo     ^<NMakeOutput^>^</NMakeOutput^>                                                    >> %_gdalproj_%
+echo     ^<NMakeCleanCommandLine^>nmake -f makefile.vc MSVC_VER=%_clver_% %_nmake_opt_win64_% DEBUG=1 WITH_PDB=1 clean^</NMakeCleanCommandLine^>      >> %_gdalproj_%
+echo     ^<NMakeReBuildCommandLine^>nmake -f makefile.vc MSVC_VER=%_clver_% %_nmake_opt_win64_% DEBUG=1 WITH_PDB=1 clean ^&^& nmake -f makefile.vc MSVC_VER=%_clver_% %_nmake_opt_win64_% DEBUG=1 WITH_PDB=1^</NMakeReBuildCommandLine^>  >> %_gdalproj_%
+echo     ^<NMakePreprocessorDefinitions^>%_winver_%;_DEBUG;$(NMakePreprocessorDefinitions)^</NMakePreprocessorDefinitions^>   >> %_gdalproj_%
+echo     ^<LibraryPath^>$(VC_LibraryPath_%_buildplatf_%);$(WindowsSDK_LibraryPath_%_buildplatf_%);$(VC_SourcePath);^</LibraryPath^>   >> %_gdalproj_%
+echo   ^</PropertyGroup^>                                                                   >> %_gdalproj_%
+echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|%_winver_%'"^>   >> %_gdalproj_%
+echo     ^<NMakeBuildCommandLine^>nmake -f makefile.vc MSVC_VER=%_clver_% %_nmake_opt_win64_% ^</NMakeBuildCommandLine^>            >> %_gdalproj_%
+echo     ^<NMakeOutput^>^</NMakeOutput^>                                                    >> %_gdalproj_%
+echo     ^<NMakeCleanCommandLine^>nmake -f makefile.vc MSVC_VER=%_clver_% %_nmake_opt_win64_% clean^</NMakeCleanCommandLine^>      >> %_gdalproj_%
+echo     ^<NMakeReBuildCommandLine^>nmake -f makefile.vc MSVC_VER=%_clver_% %_nmake_opt_win64_% clean ^&^& nmake -f makefile.vc MSVC_VER=%_clver_%^</NMakeReBuildCommandLine^>  >> %_gdalproj_%
+echo     ^<NMakePreprocessorDefinitions^>%_winver_%;NDEBUG;$(NMakePreprocessorDefinitions)^</NMakePreprocessorDefinitions^>   >> %_gdalproj_%
+echo     ^<LibraryPath^>$(VC_LibraryPath_%_buildplatf_%);$(WindowsSDK_LibraryPath_%_buildplatf_%);$(VC_SourcePath);^</LibraryPath^>   >> %_gdalproj_%
+echo   ^</PropertyGroup^>                                                                   >> %_gdalproj_%
+echo   ^<ItemDefinitionGroup^>                                  >> %_gdalproj_%
+echo   ^</ItemDefinitionGroup^>                                 >> %_gdalproj_%
+
+:: create a root path with nmake files
+
+echo   ^<ItemGroup^>                                            >> %_gdalproj_%
+echo       ^<Test Include="%_gdaldir_%\nmake.local" /^>                     >> %_gdalproj_%
+echo       ^<Test Include="%_gdaldir_%\nmake.opt" /^>                       >> %_gdalproj_%
+echo   ^</ItemGroup^>                                           >> %_gdalproj_%
+
+echo   ^<ItemGroup^>                                            >> %_gdalfltr_%
+echo       ^<Test Include="%_gdaldir_%\nmake.local" /^>                     >> %_gdalfltr_%
+echo       ^<Test Include="%_gdaldir_%\nmake.opt" /^>                       >> %_gdalfltr_%
+echo   ^</ItemGroup^>                                           >> %_gdalfltr_%
+
+:: Use base of main .vcxproj and .filters as template for test project
+
+if defined _testdir_ (
+    copy /Y %_gdalproj_% %_testproj_% >NUL
+    copy /Y %_gdalfltr_% %_testfltr_% >NUL
+)
+:: if defined _testdir_
+
+:: create main project filters only
+
+echo   ^<ItemGroup^>                                            >> %_gdalfltr_%
+call :create_filter %_gdaldir_% "*.vc;" 1 "Make Files" "None" %_gdalproj_% %_gdalfltr_%
+call :create_filter %_gdaldir_% "*.h;*.hpp" 1 "Include Files" "ClInclude" %_gdalproj_% %_gdalfltr_%
+call :create_filter %_gdaldir_% "*.c;*.cpp" 1 "Source Files" "ClCompile" %_gdalproj_% %_gdalfltr_%
+echo   ^</ItemGroup^>                                           >> %_gdalfltr_%
+
+:: create test project filters only
+
+if defined _testdir_ (
+echo   ^<ItemGroup^>                                            >> %_testfltr_%
+call :create_filter %_testdir_% "*.vc;" 1 "Make Files" "None" %_testproj_% %_testfltr_%
+call :create_filter %_testdir_% "*.h;*.hpp" 1 "Include Files" "ClInclude" %_testproj_% %_testfltr_%
+call :create_filter %_testdir_% "*.c;*.cpp" 1 "Source Files" "ClCompile" %_testproj_% %_testfltr_%
+echo   ^</ItemGroup^>                                           >> %_testfltr_%
+)
+:: if defined _testdir_
+
+:: create main project and links to filters
+
+echo   ^<ItemGroup^>                                            >> %_gdalproj_%
+echo   ^<ItemGroup^>                                            >> %_gdalfltr_%
+call :create_filter %_gdaldir_% "*.vc" 0 "Make Files" "None" %_gdalproj_% %_gdalfltr_%
+echo   ^</ItemGroup^>                                           >> %_gdalproj_%
+echo   ^</ItemGroup^>                                           >> %_gdalfltr_%
+
+echo   ^<ItemGroup^>                                            >> %_gdalproj_%
+echo   ^<ItemGroup^>                                            >> %_gdalfltr_%
+call :create_filter %_gdaldir_% "*.h;*.hpp" 0 "Include Files" "ClInclude" %_gdalproj_% %_gdalfltr_%
+echo   ^</ItemGroup^>                                           >> %_gdalproj_%
+echo   ^</ItemGroup^>                                           >> %_gdalfltr_%
+
+echo   ^<ItemGroup^>                                            >> %_gdalproj_%
+echo   ^<ItemGroup^>                                            >> %_gdalfltr_%
+call :create_filter %_gdaldir_% "*.c;*.cpp" 0 "Source Files" "ClCompile" %_gdalproj_% %_gdalfltr_%
+echo   ^</ItemGroup^>                                           >> %_gdalproj_%
+echo   ^</ItemGroup^>                                           >> %_gdalfltr_%
+
+:: create test project and links to filters
+
+if defined _testdir_ (
+echo   ^<ItemGroup^>                                            >> %_testproj_%
+echo   ^<ItemGroup^>                                            >> %_testfltr_%
+call :create_filter %_testdir_% "*.vc" 0 "Make Files" "None" %_testproj_% %_testfltr_%
+echo   ^</ItemGroup^>                                           >> %_testproj_%
+echo   ^</ItemGroup^>                                           >> %_testfltr_%
+
+echo   ^<ItemGroup^>                                            >> %_testproj_%
+echo   ^<ItemGroup^>                                            >> %_testfltr_%
+call :create_filter %_testdir_% "*.h;*.hpp" 0 "Include Files" "ClInclude" %_testproj_% %_testfltr_%
+echo   ^</ItemGroup^>                                           >> %_testproj_%
+echo   ^</ItemGroup^>                                           >> %_testfltr_%
+
+echo   ^<ItemGroup^>                                            >> %_testproj_%
+echo   ^<ItemGroup^>                                            >> %_testfltr_%
+call :create_filter %_testdir_% "*.c;*.cpp" 0 "Source Files" "ClCompile" %_testproj_% %_testfltr_%
+echo   ^</ItemGroup^>                                           >> %_testproj_%
+echo   ^</ItemGroup^>                                           >> %_testfltr_%
+)
+:: if defined _testdir_
+
+:: **********************************************
+:: Finalize main and test projects
+:: **********************************************
+
+echo ^</Project^>                                               >> %_gdalfltr_%
+
+echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/^>  >> %_gdalproj_%
+echo ^</Project^>                                               >> %_gdalproj_%
+
+if defined _testdir_ (
+echo ^</Project^>                                               >> %_testfltr_%
+
+echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/^>  >> %_testproj_%
+echo ^</Project^>                                               >> %_testproj_%
+)
+:: if defined _testdir_ (
+
+:: *******************************************************
+:: Generate .sln file with main and test projects attached
+:: *******************************************************
+
+echo Projects done!
+
+echo Launch Visual Studio IDE
+echo * Open project %_gdalproj_%
+echo * Add  project %_testproj_%
+echo * Configure Build Dependencies to build the main project before the test project.
+echo * Save solution in .sln file
+echo Done!
+
+:: **********************************************
+:: The end
+:: **********************************************
+
+goto :end
+
+:: **********************************************
+:create_filter
+:: **********************************************
+
+    set _path_=%1
+    set _mask_=%2
+    set _fonly_=%3
+    set _name_=%4
+    set _item_=%5
+    set _proj_=%6
+    set _fltr_=%7
+    
+    ::  *********************
+    ::  Remove quotes 
+    ::  *********************
+    
+    set _name_=%_name_:"=%
+    set _mask_=%_mask_:"=% 
+    set _fonly_=%_fonly_:"=%
+    set _item_=%_item_:"=%
+  
+    ::  *********************
+    ::  Stop folders
+    ::  *********************
+    
+    set _folder_=%~nx1
+
+    for %%d in (ci data debian doc html m4 pymod scripts swig) do (
+        if "%_folder_%"=="%%d" (
+            goto :end
+        )
+    )
+    ::  *********************
+    ::  Check if a folde is empty
+    ::  *********************
+
+    set _find_=1
+    
+    for /R %%f in (%_mask_%) do (
+      goto :not_empty
+    )
+
+    set _find_=0
+  
+    :not_empty
+  
+    if %_find_%==0 (
+        goto :end
+    )
+
+    ::  *********************
+    ::  Add filters 
+    ::  *********************
+
+    if %_fonly_%==1 (
+        echo     ^<Filter Include="%_name_%"^>                   >> %_fltr_%
+        echo       ^<Extensions^>%_mask_%^</Extensions^>         >> %_fltr_%
+        echo     ^</Filter^>                                     >> %_fltr_%
+    )
+
+    ::  *********************
+    ::  Add files
+    ::  *********************
+    
+    if %_fonly_%==0 (
+        for %%f in (%_mask_%) do (
+            echo     ^<%_item_% Include="%_path_%\%%f"/^>        >> %_proj_%
+            echo     ^<%_item_% Include="%_path_%\%%f"^>         >> %_fltr_%
+            echo       ^<Filter^>%_name_%^</Filter^>             >> %_fltr_%
+            echo     ^</%_item_%^>                               >> %_fltr_% 
+        )
+    )
+  
+    ::  *********************
+    ::  Clib all the branches recursivelly
+    ::  *********************
+
+    for /D %%d in (%_path_%\*) do (
+        cd %%d
+        call :create_filter %%d "%_mask_%" %_fonly_% "%_name_%\%%~nxd" %_item_% %_proj_% %_fltr_%
+        cd ..
+    )
+
+:: **********************************************
+:end
+:: **********************************************
diff --git a/gnm/GNUmakefile b/gnm/GNUmakefile
index 7da2400..d5fe2cd 100644
--- a/gnm/GNUmakefile
+++ b/gnm/GNUmakefile
@@ -1,6 +1,8 @@
 
 include ../GDALmake.opt
 
+INST_H_FILES	=	gnm.h gnm_api.h gnmgraph.h
+
 OBJ	=	gnmnetwork.o gnmgenericnetwork.o gnmlayer.o gnmrule.o gnmresultlayer.o \
         gnmgraph.o
 
@@ -18,14 +20,16 @@ very-clean: clean
 
 lib:	sublibs $(OBJ:.o=.$(OBJ_EXT))
 
-$(OBJ): gnm.h gnm_priv.h 
+$(OBJ): gnm.h gnm_priv.h
 
 obj:	$(OBJ)
 
 sublibs:
 	(cd gnm_frmts; $(MAKE))
-	
-install:	;
+
+install:
+	for f in $(INST_H_FILES) ; \
+	    do $(INSTALL_DATA) $$f $(DESTDIR)$(INST_INCLUDE) ; \
+	done
 
 install-obj:	$(O_OBJ:.o=.$(OBJ_EXT))
-	
diff --git a/gnm/gnm.h b/gnm/gnm.h
index 97c5032..23793a6 100644
--- a/gnm/gnm.h
+++ b/gnm/gnm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gnm.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM general public declarations.
@@ -74,8 +74,8 @@ public:
     virtual ~GNMNetwork();
 
     // GDALDataset Interface
-    virtual const char *GetProjectionRef(void);
-    virtual char      **GetFileList(void);
+    virtual const char *GetProjectionRef(void) CPL_OVERRIDE;
+    virtual char      **GetFileList(void) CPL_OVERRIDE;
 
     // GNMNetwork Interface
 
@@ -145,8 +145,8 @@ public:
 
     /**
      * @brief Create path between start and end GFIDs.
-     * @param nStartGFID - start identificator
-     * @param nEndGFID - end identificator
+     * @param nStartFID - start identificator
+     * @param nEndFID - end identificator
      * @param eAlgorithm - The algorithm to get path
      * @param papszOptions - algorithm specific options
      * @return In memory OGRLayer pointer with features constituting
@@ -166,8 +166,10 @@ protected:
                                    char** papszOptions ) = 0;
 
 protected:
+//! @cond Doxygen_Suppress
     CPLString m_soName;
     CPLString m_soSRS;
+//! @endcond
 };
 
 class GNMRule;
@@ -187,25 +189,25 @@ public:
 
     // GDALDataset Interface
 
-    virtual int         GetLayerCount();
-    virtual OGRLayer    *GetLayer(int);
-    virtual OGRErr      DeleteLayer(int);
+    virtual int         GetLayerCount() CPL_OVERRIDE;
+    virtual OGRLayer    *GetLayer(int) CPL_OVERRIDE;
+    virtual OGRErr      DeleteLayer(int) CPL_OVERRIDE;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) CPL_OVERRIDE;
 
     virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer,
                                    const char *pszNewName,
-                                   char **papszOptions = NULL );
+                                   char **papszOptions = NULL ) CPL_OVERRIDE;
 
-    virtual int CloseDependentDatasets();
-    virtual void FlushCache(void);
+    virtual int CloseDependentDatasets() CPL_OVERRIDE;
+    virtual void FlushCache(void) CPL_OVERRIDE;
 
     // GNMNetwork Interface
 
-    virtual CPLErr Create( const char* pszFilename, char** papszOptions ) = 0;
-    virtual CPLErr Delete();
+    virtual CPLErr Create( const char* pszFilename, char** papszOptions ) CPL_OVERRIDE = 0;
+    virtual CPLErr Delete() CPL_OVERRIDE;
 
-    virtual int GetVersion() const;
+    virtual int GetVersion() const CPL_OVERRIDE;
     /**
      * @brief GetNewGlobalFID increase the global ID counter.
      * @return New global feature ID.
@@ -287,9 +289,9 @@ public:
                                       double dfInvCost = 1,
                                       GNMDirection eDir = GNM_EDGE_DIR_BOTH);
 
-    virtual CPLErr DisconnectAll();
+    virtual CPLErr DisconnectAll() CPL_OVERRIDE;
 
-    virtual OGRFeature *GetFeatureByGlobalFID(GNMGFID nFID);
+    virtual OGRFeature *GetFeatureByGlobalFID(GNMGFID nFID) CPL_OVERRIDE;
 
     /**
      * @brief Create network rule
@@ -304,13 +306,13 @@ public:
      * network objects. All the following combinations are available:
      *
      *  Notation:
-     *	layer1, layer2, layer3 - a layer names (the corresponding layers must be
+     *  layer1, layer2, layer3 - a layer names (the corresponding layers must be
      *                           exist;
-     *	field1 - a field name (field must be exist);
-     *	constant1 - any double constant;
-     *	string1 - any string;
+     *  field1 - a field name (field must be exist);
+     *  constant1 - any double constant;
+     *  string1 - any string;
      *
-     *	Rules describing which layer can be connected or not connected with each
+     *  Rules describing which layer can be connected or not connected with each
      *  other, and (optional) which layer must serve as a connector. By default
      *  all connections are forbidden. But while network creation process the
      *  rule to allow any connection added. During the connection process each
@@ -318,8 +320,8 @@ public:
      *
      *    "ALLOW CONNECTS ANY"
      *    "DENY CONNECTS ANY"
-     *	  "DENY CONNECTS layer1 WITH layer2"
-     *	  "ALLOW CONNECTS layer1 WITH layer2 VIA layer3"
+     *    "DENY CONNECTS layer1 WITH layer2"
+     *    "ALLOW CONNECTS layer1 WITH layer2 VIA layer3"
      *
      * @param pszRuleStr Rule string which will parsed. If the parsing was
      *        successful, the rule will start having effect immediately.
@@ -365,6 +367,9 @@ public:
      * @param papszLayerList A list of layers to connect. The list should be
      *                       freed via CSLDestroy.
      * @param dfTolerance Snapping tolerance.
+     * @param dfCost Direct cost.
+     * @param dfInvCost Inverse cost.
+     * @param eDir Direction.
      * @return CE_None on success
      */
     virtual CPLErr ConnectPointsByLines (char **papszLayerList,
@@ -392,7 +397,7 @@ public:
     virtual CPLErr ChangeAllBlockState (bool bIsBlock = false);
 
     virtual OGRLayer *GetPath (GNMGFID nStartFID, GNMGFID nEndFID,
-                     GNMGraphAlgorithmType eAlgorithm, char** papszOptions);
+                     GNMGraphAlgorithmType eAlgorithm, char** papszOptions) CPL_OVERRIDE;
 protected:
     /**
      * @brief Check or create layer OGR driver
@@ -409,6 +414,7 @@ protected:
      */
     virtual bool CheckStorageDriverSupport(const char* pszDriverName) = 0;
 protected:
+//! @cond Doxygen_Suppress
     virtual CPLErr CreateMetadataLayer( GDALDataset* const pDS, int nVersion,
                                      size_t nFieldSize = 1024 );
     virtual CPLErr StoreNetworkSrs();
@@ -444,7 +450,9 @@ protected:
     virtual void FillResultLayer(OGRGNMWrappedResultLayer* poResLayer,
                                  const GNMPATH &path, int nNoOfPath,
                                  bool bReturnVertices, bool bReturnEdges);
+//! @endcond
 protected:
+//! @cond Doxygen_Suppress
     int m_nVersion;
     GNMGFID m_nGID;
     GNMGFID m_nVirtualConnectionGID;
@@ -461,11 +469,12 @@ protected:
 
     GNMGraph m_oGraph;
     bool m_bIsGraphLoaded;
+//! @endcond
 };
 
 /**
  * GNM layer which represents a geography network layer of generic format.
- * The class override some OGRLayer methods to fulfill the network requirements.
+ * The class CPL_OVERRIDE some OGRLayer methods to fulfill the network requirements.
  *
  * @since GDAL 2.1
  */
@@ -478,117 +487,130 @@ public:
 
     // OGRLayer Interface
 
-    virtual OGRGeometry *GetSpatialFilter();
-    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual OGRGeometry *GetSpatialFilter() CPL_OVERRIDE;
+    virtual void        SetSpatialFilter( OGRGeometry * ) CPL_OVERRIDE;
     virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY );
+                                              double dfMaxX, double dfMaxY ) CPL_OVERRIDE;
 
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) CPL_OVERRIDE;
     virtual void        SetSpatialFilterRect( int iGeomField,
                                             double dfMinX, double dfMinY,
-                                            double dfMaxX, double dfMaxY );
+                                            double dfMaxX, double dfMaxY ) CPL_OVERRIDE;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) CPL_OVERRIDE;
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
+    virtual void        ResetReading() CPL_OVERRIDE;
+    virtual OGRFeature *GetNextFeature() CPL_OVERRIDE;
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) CPL_OVERRIDE;
 
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) CPL_OVERRIDE;
 
-    virtual const char *GetName();
-    virtual OGRwkbGeometryType GetGeomType();
-    virtual OGRFeatureDefn *GetLayerDefn();
-    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch );
+    virtual const char *GetName() CPL_OVERRIDE;
+    virtual OGRwkbGeometryType GetGeomType() CPL_OVERRIDE;
+    virtual OGRFeatureDefn *GetLayerDefn() CPL_OVERRIDE;
+    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch ) CPL_OVERRIDE;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() CPL_OVERRIDE;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) CPL_OVERRIDE;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) CPL_OVERRIDE;
     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent,
-                                  int bForce = TRUE);
+                                  int bForce = TRUE) CPL_OVERRIDE;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) CPL_OVERRIDE;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
+                                     int bApproxOK = TRUE ) CPL_OVERRIDE;
+    virtual OGRErr      DeleteField( int iField ) CPL_OVERRIDE;
+    virtual OGRErr      ReorderFields( int* panMap ) CPL_OVERRIDE;
     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
-                                        int nFlagsIn );
+                                        int nFlagsIn ) CPL_OVERRIDE;
 
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) CPL_OVERRIDE;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() CPL_OVERRIDE;
 
-    virtual OGRStyleTable *GetStyleTable();
-    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
+    virtual OGRStyleTable *GetStyleTable() CPL_OVERRIDE;
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable ) CPL_OVERRIDE;
 
-    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
+    virtual void        SetStyleTable(OGRStyleTable *poStyleTable) CPL_OVERRIDE;
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction() CPL_OVERRIDE;
+    virtual OGRErr      CommitTransaction() CPL_OVERRIDE;
+    virtual OGRErr      RollbackTransaction() CPL_OVERRIDE;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() CPL_OVERRIDE;
+    virtual const char *GetGeometryColumn() CPL_OVERRIDE;
 
-    virtual OGRErr      SetIgnoredFields( const char **papszFields );
+    virtual OGRErr      SetIgnoredFields( const char **papszFields ) CPL_OVERRIDE;
 
+    /** Intersection */
     OGRErr              Intersection( OGRLayer *pLayerMethod,
                                       OGRLayer *pLayerResult,
                                       char** papszOptions = NULL,
                                       GDALProgressFunc pfnProgress = NULL,
                                       void * pProgressArg = NULL );
+    /** Union */
     OGRErr              Union( OGRLayer *pLayerMethod,
                                OGRLayer *pLayerResult,
                                char** papszOptions = NULL,
                                GDALProgressFunc pfnProgress = NULL,
                                void * pProgressArg = NULL );
+    /** SymDifference */
     OGRErr              SymDifference( OGRLayer *pLayerMethod,
                                        OGRLayer *pLayerResult,
                                        char** papszOptions,
                                        GDALProgressFunc pfnProgress,
                                        void * pProgressArg );
+    /** Identity */
     OGRErr              Identity( OGRLayer *pLayerMethod,
                                   OGRLayer *pLayerResult,
                                   char** papszOptions = NULL,
                                   GDALProgressFunc pfnProgress = NULL,
                                   void * pProgressArg = NULL );
+    /** Update */
     OGRErr              Update( OGRLayer *pLayerMethod,
                                 OGRLayer *pLayerResult,
                                 char** papszOptions = NULL,
                                 GDALProgressFunc pfnProgress = NULL,
                                 void * pProgressArg = NULL );
+    /** Clip */
     OGRErr              Clip( OGRLayer *pLayerMethod,
                               OGRLayer *pLayerResult,
                               char** papszOptions = NULL,
                               GDALProgressFunc pfnProgress = NULL,
                               void * pProgressArg = NULL );
+    /** Erase */
     OGRErr              Erase( OGRLayer *pLayerMethod,
                                OGRLayer *pLayerResult,
                                char** papszOptions = NULL,
                                GDALProgressFunc pfnProgress = NULL,
                                void * pProgressArg = NULL );
 
+    /** GetFeaturesRead */
     GIntBig             GetFeaturesRead();
 
+    /** AttributeFilterEvaluationNeedsGeometry */
     int                 AttributeFilterEvaluationNeedsGeometry();
 
+//! @cond Doxygen_Suppress
     /* consider these private */
     OGRErr               InitializeIndexSupport( const char * );
     OGRLayerAttrIndex   *GetIndex();
+//! @endcond
 
 protected:
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+//! @cond Doxygen_Suppress
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) CPL_OVERRIDE;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) CPL_OVERRIDE;
 
 protected:
     CPLString m_soLayerName;
     OGRLayer *m_poLayer;
     GNMGenericNetwork* m_poNetwork;
     std::map<GNMGFID, GIntBig> m_mnFIDMap;
+//! @endcond
 };
 
 typedef enum
@@ -608,9 +630,13 @@ typedef enum
 class CPL_DLL GNMRule
 {
 public:
+    /** Constructor */
     GNMRule();
-    GNMRule(const std::string &oRule );
-    GNMRule(const char* pszRule);
+    /** Constructor */
+    explicit GNMRule(const std::string &oRule );
+    /** Constructor */
+    explicit GNMRule(const char* pszRule);
+    /** Constructor */
     GNMRule(const GNMRule &oRule);
     virtual ~GNMRule();
     /**
@@ -640,12 +666,18 @@ public:
     virtual bool CanConnect(const CPLString &soSrcLayerName,
                             const CPLString &soTgtLayerName,
                             const CPLString &soConnLayerName = "");
+    /** Return source layer name */
     virtual CPLString GetSourceLayerName() const;
+    /** Return target layer name */
     virtual CPLString GetTargetLayerName() const;
+    /** Return connector layer name */
     virtual CPLString GetConnectorLayerName() const;
+    /** Return rule as a string */
     const char* c_str() const;
+    /** Return rule as a string */
     operator const char* (void) const;
 protected:
+//! @cond Doxygen_Suppress
     virtual bool ParseRuleString();
 protected:
     CPLString m_soSrcLayerName;
@@ -655,6 +687,7 @@ protected:
     bool m_bValid;
     bool m_bAny;
     CPLString m_soRuleString;
+//! @endcond
 };
 
 /**
@@ -670,30 +703,32 @@ public:
     ~OGRGNMWrappedResultLayer();
 
     // OGRLayer
-    virtual void ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRErr SetNextByIndex( GIntBig nIndex );
-    virtual OGRFeature *GetFeature( GIntBig nFID );
-    virtual OGRFeatureDefn *GetLayerDefn();
-    virtual GIntBig GetFeatureCount( int bForce = TRUE );
-    virtual int TestCapability( const char * pszCap );
-    virtual OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
+    virtual void ResetReading() CPL_OVERRIDE;
+    virtual OGRFeature *GetNextFeature() CPL_OVERRIDE;
+    virtual OGRErr SetNextByIndex( GIntBig nIndex ) CPL_OVERRIDE;
+    virtual OGRFeature *GetFeature( GIntBig nFID ) CPL_OVERRIDE;
+    virtual OGRFeatureDefn *GetLayerDefn() CPL_OVERRIDE;
+    virtual GIntBig GetFeatureCount( int bForce = TRUE ) CPL_OVERRIDE;
+    virtual int TestCapability( const char * pszCap ) CPL_OVERRIDE;
+    virtual OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE ) CPL_OVERRIDE;
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
-    virtual OGRSpatialReference *GetSpatialRef();
+                                     int bApproxOK = TRUE ) CPL_OVERRIDE;
+    virtual const char *GetFIDColumn() CPL_OVERRIDE;
+    virtual const char *GetGeometryColumn() CPL_OVERRIDE;
+    virtual OGRSpatialReference *GetSpatialRef() CPL_OVERRIDE;
 
     // OGRGNMWrappedResultLayer
     virtual OGRErr InsertFeature(OGRFeature* poFeature,
                                 const CPLString &soLayerName, int nPathNo,
                                 bool bIsEdge);
 protected:
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) CPL_OVERRIDE;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) CPL_OVERRIDE;
 protected:
+//! @cond Doxygen_Suppress
     GDALDataset *poDS;
     OGRLayer    *poLayer;
+//! @endcond
 };
 
 #endif // GNM
diff --git a/gnm/gnm_api.h b/gnm/gnm_api.h
index cc80fa4..04f8a0f 100644
--- a/gnm/gnm_api.h
+++ b/gnm/gnm_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gnm_api.h 35902 2016-10-24 12:00:50Z goatbar $
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM C API.
@@ -51,8 +51,6 @@ OGRLayerH CPL_DLL CPL_STDCALL GNMGetPath (GNMNetworkH hNet, GNMGFID nStartFID,
                               GNMGFID nEndFID, GNMGraphAlgorithmType eAlgorithm,
                               char** papszOptions);
 
-
-
 CPLErr CPL_DLL CPL_STDCALL GNMConnectFeatures (GNMGenericNetworkH hNet,
                                                GNMGFID nSrcFID, GNMGFID nTgtFID,
                                                GNMGFID nConFID, double dfCost,
@@ -66,7 +64,6 @@ CPLErr CPL_DLL CPL_STDCALL GNMDisconnectFeatures (GNMGenericNetworkH hNet,
 CPLErr CPL_DLL CPL_STDCALL GNMDisconnectFeaturesWithId(GNMGenericNetworkH hNet,
                                                        GNMGFID nFID);
 
-
 CPLErr CPL_DLL CPL_STDCALL GNMReconnectFeatures (GNMGenericNetworkH hNet,
                                                  GNMGFID nSrcFID, GNMGFID nTgtFID,
                                                  GNMGFID nConFID, double dfCost,
diff --git a/gnm/gnm_frmts/db/gnmdb.h b/gnm/gnm_frmts/db/gnmdb.h
index 6bed277..e3a4601 100644
--- a/gnm/gnm_frmts/db/gnmdb.h
+++ b/gnm/gnm_frmts/db/gnmdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gnmdb.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM db based generic driver.
@@ -36,22 +36,22 @@ class GNMDatabaseNetwork : public GNMGenericNetwork
 public:
     GNMDatabaseNetwork();
     virtual ~GNMDatabaseNetwork();
-    virtual CPLErr Open( GDALOpenInfo* poOpenInfo );
-    virtual OGRErr      DeleteLayer(int);
-    virtual CPLErr Create( const char* pszFilename, char** papszOptions );
+    virtual CPLErr Open( GDALOpenInfo* poOpenInfo ) override;
+    virtual OGRErr      DeleteLayer(int) override;
+    virtual CPLErr Create( const char* pszFilename, char** papszOptions ) override;
 protected:
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                    OGRSpatialReference *poSpatialRef = NULL,
                                    OGRwkbGeometryType eGType = wkbUnknown,
-                                   char ** papszOptions = NULL );
-    virtual int CheckNetworkExist( const char* pszFilename, char** papszOptions );
+                                   char ** papszOptions = NULL ) override;
+    virtual int CheckNetworkExist( const char* pszFilename, char** papszOptions ) override;
 protected:
-    virtual CPLErr DeleteMetadataLayer();
-    virtual CPLErr DeleteGraphLayer();
-    virtual CPLErr DeleteFeaturesLayer();
-    virtual CPLErr DeleteNetworkLayers();
-    virtual CPLErr LoadNetworkLayer(const char* pszLayername);
-    virtual bool CheckStorageDriverSupport(const char* pszDriverName);
+    virtual CPLErr DeleteMetadataLayer() override;
+    virtual CPLErr DeleteGraphLayer() override;
+    virtual CPLErr DeleteFeaturesLayer() override;
+    virtual CPLErr DeleteNetworkLayers() override;
+    virtual CPLErr LoadNetworkLayer(const char* pszLayername) override;
+    virtual bool CheckStorageDriverSupport(const char* pszDriverName) override;
 protected:
     CPLErr FormName(const char* pszFilename, char** papszOptions);
     CPLErr DeleteLayerByName(const char* pszLayerName);
diff --git a/gnm/gnm_frmts/db/gnmdbdriver.cpp b/gnm/gnm_frmts/db/gnmdbdriver.cpp
index adb2496..1d352d2 100644
--- a/gnm/gnm_frmts/db/gnmdbdriver.cpp
+++ b/gnm/gnm_frmts/db/gnmdbdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM generic driver.
@@ -33,6 +32,8 @@
 #include "gnm_priv.h"
 #include "gnmdb.h"
 
+CPL_CVSID("$Id: gnmdbdriver.cpp 35902 2016-10-24 12:00:50Z goatbar $");
+
 static int GNMDBDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
@@ -64,7 +65,6 @@ static GDALDataset *GNMDBDriverOpen( GDALOpenInfo* poOpenInfo )
     return poFN;
 }
 
-
 static GDALDataset *GNMDBDriverCreate( const char * pszName,
                                         CPL_UNUSED int nBands,
                                         CPL_UNUSED int nXSize,
diff --git a/gnm/gnm_frmts/db/gnmdbnetwork.cpp b/gnm/gnm_frmts/db/gnmdbnetwork.cpp
index a77f536..f23da08 100644
--- a/gnm/gnm_frmts/db/gnmdbnetwork.cpp
+++ b/gnm/gnm_frmts/db/gnmdbnetwork.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM db based generic driver.
@@ -32,6 +31,8 @@
 #include "gnmdb.h"
 #include "gnm_priv.h"
 
+CPL_CVSID("$Id: gnmdbnetwork.cpp 35902 2016-10-24 12:00:50Z goatbar $");
+
 GNMDatabaseNetwork::GNMDatabaseNetwork() : GNMGenericNetwork()
 {
     m_poDS = NULL;
@@ -214,7 +215,7 @@ int GNMDatabaseNetwork::CheckNetworkExist(const char *pszFilename, char **papszO
                                       GDAL_OF_UPDATE, NULL, NULL, papszOptions );
     }
 
-    bool bOverwrite = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "OVERWRITE", FALSE));
+    const bool bOverwrite = CPLFetchBool(papszOptions, "OVERWRITE", false);
 
     std::vector<int> anDeleteLayers;
     int i;
@@ -235,7 +236,7 @@ int GNMDatabaseNetwork::CheckNetworkExist(const char *pszFilename, char **papszO
     if(anDeleteLayers.empty())
         return FALSE;
 
-    if(bOverwrite)
+    if( bOverwrite )
     {
         for(i = (int)anDeleteLayers.size(); i > 0; i--)
         {
@@ -249,8 +250,6 @@ int GNMDatabaseNetwork::CheckNetworkExist(const char *pszFilename, char **papszO
     {
         return TRUE;
     }
-
-    return FALSE;
 }
 
 CPLErr GNMDatabaseNetwork::DeleteMetadataLayer()
@@ -448,7 +447,6 @@ OGRLayer *GNMDatabaseNetwork::ICreateLayer(const char *pszName,
         return NULL;
     }
 
-
     OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
     if( poLayer->CreateField( &oFieldBlock ) != OGRERR_NONE )
     {
diff --git a/gnm/gnm_frmts/file/gnmfile.h b/gnm/gnm_frmts/file/gnmfile.h
index 7493874..9d51607 100644
--- a/gnm/gnm_frmts/file/gnmfile.h
+++ b/gnm/gnm_frmts/file/gnmfile.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gnmfile.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM file based generic driver.
@@ -38,32 +38,32 @@ class GNMFileNetwork : public GNMGenericNetwork
 public:
     GNMFileNetwork();
     virtual ~GNMFileNetwork();
-    virtual CPLErr Open( GDALOpenInfo* poOpenInfo );
-    virtual CPLErr Delete();
-    virtual int CloseDependentDatasets();
-    virtual OGRErr      DeleteLayer(int);
-    virtual CPLErr Create( const char* pszFilename, char** papszOptions );
+    virtual CPLErr Open( GDALOpenInfo* poOpenInfo ) override;
+    virtual CPLErr Delete() override;
+    virtual int CloseDependentDatasets() override;
+    virtual OGRErr      DeleteLayer(int) override;
+    virtual CPLErr Create( const char* pszFilename, char** papszOptions ) override;
 protected:
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                    OGRSpatialReference *poSpatialRef = NULL,
                                    OGRwkbGeometryType eGType = wkbUnknown,
-                                   char ** papszOptions = NULL );
-    virtual int CheckNetworkExist( const char* pszFilename, char** papszOptions );
+                                   char ** papszOptions = NULL ) override;
+    virtual int CheckNetworkExist( const char* pszFilename, char** papszOptions ) override;
 protected:
     virtual CPLErr CreateMetadataLayerFromFile( const char* pszFilename, int nVersion,
                                         char** papszOptions );
-    virtual CPLErr StoreNetworkSrs();
-    virtual CPLErr LoadNetworkSrs();
-    virtual CPLErr DeleteMetadataLayer();
+    virtual CPLErr StoreNetworkSrs() override;
+    virtual CPLErr LoadNetworkSrs() override;
+    virtual CPLErr DeleteMetadataLayer() override;
     virtual CPLErr CreateGraphLayerFromFile( const char* pszFilename,
                                      char** papszOptions );
-    virtual CPLErr DeleteGraphLayer();
+    virtual CPLErr DeleteGraphLayer() override;
     virtual CPLErr CreateFeaturesLayerFromFile( const char* pszFilename,
                                         char** papszOptions );
-    virtual CPLErr DeleteFeaturesLayer();
-    virtual CPLErr DeleteNetworkLayers();
-    virtual CPLErr LoadNetworkLayer(const char* pszLayername);
-    virtual bool CheckStorageDriverSupport(const char* pszDriverName);
+    virtual CPLErr DeleteFeaturesLayer() override;
+    virtual CPLErr DeleteNetworkLayers() override;
+    virtual CPLErr LoadNetworkLayer(const char* pszLayername) override;
+    virtual bool CheckStorageDriverSupport(const char* pszDriverName) override;
 protected:
     CPLErr FormPath(const char* pszFilename, char** papszOptions);
 protected:
diff --git a/gnm/gnm_frmts/file/gnmfiledriver.cpp b/gnm/gnm_frmts/file/gnmfiledriver.cpp
index 7c21dd3..ea92966 100644
--- a/gnm/gnm_frmts/file/gnmfiledriver.cpp
+++ b/gnm/gnm_frmts/file/gnmfiledriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM generic driver.
@@ -29,8 +28,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gnm_frmts.h"
 #include "gnmfile.h"
+#include "gnm_frmts.h"
+#include "gnm_priv.h"
+
+CPL_CVSID("$Id: gnmfiledriver.cpp 36302 2016-11-19 16:54:08Z bishop $");
 
 static int GNMFileDriverIdentify( GDALOpenInfo* poOpenInfo )
 
@@ -87,7 +89,6 @@ static GDALDataset *GNMFileDriverOpen( GDALOpenInfo* poOpenInfo )
     return poFN;
 }
 
-
 static GDALDataset *GNMFileDriverCreate( const char * pszName,
                                         CPL_UNUSED int nBands,
                                         CPL_UNUSED int nXSize,
diff --git a/gnm/gnm_frmts/file/gnmfilenetwork.cpp b/gnm/gnm_frmts/file/gnmfilenetwork.cpp
index 2f8af30..f92feaa 100644
--- a/gnm/gnm_frmts/file/gnmfilenetwork.cpp
+++ b/gnm/gnm_frmts/file/gnmfilenetwork.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM file based generic driver.
@@ -32,6 +31,8 @@
 #include "gnmfile.h"
 #include "gnm_priv.h"
 
+CPL_CVSID("$Id: gnmfilenetwork.cpp 36741 2016-12-07 16:22:35Z rouault $");
+
 GNMFileNetwork::GNMFileNetwork() : GNMGenericNetwork()
 {
     m_pMetadataDS = NULL;
@@ -43,6 +44,15 @@ GNMFileNetwork::~GNMFileNetwork()
 {
     FlushCache();
 
+    for (std::map<OGRLayer*, GDALDataset*>::iterator
+            it = m_mpLayerDatasetMap.begin();
+            it != m_mpLayerDatasetMap.end(); ++it)
+    {
+            GDALClose(it->second);
+    }
+
+    m_mpLayerDatasetMap.clear();
+
     GDALClose(m_pGraphDS);
     GDALClose(m_pFeaturesDS);
     GDALClose(m_pMetadataDS);
@@ -134,7 +144,7 @@ int GNMFileNetwork::CheckNetworkExist(const char *pszFilename, char **papszOptio
     // if path exist check if network already present and OVERWRITE option
     // else create the path
 
-    bool bOverwrite = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "OVERWRITE", FALSE));
+    const bool bOverwrite = CPLFetchBool(papszOptions, "OVERWRITE", false);
 
     if(m_soName.empty())
     {
@@ -170,7 +180,7 @@ int GNMFileNetwork::CheckNetworkExist(const char *pszFilename, char **papszOptio
                 EQUAL(CPLGetBasename(papszFiles[i]), GNM_SYSLAYER_FEATURES) ||
                 EQUAL(papszFiles[i], GNM_SRSFILENAME) )
             {
-                if(bOverwrite)
+                if( bOverwrite )
                 {
                     const char* pszDeleteFile = CPLFormFilename(
                                 m_soNetworkFullName, papszFiles[i], NULL);
@@ -546,7 +556,6 @@ OGRLayer *GNMFileNetwork::ICreateLayer(const char *pszName,
         return NULL;
     }
 
-
     OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
     if( poLayer->CreateField( &oFieldBlock ) != OGRERR_NONE )
     {
diff --git a/gnm/gnm_frmts/gnm_frmts.h b/gnm/gnm_frmts/gnm_frmts.h
index ec942ea..a7cec63 100644
--- a/gnm/gnm_frmts/gnm_frmts.h
+++ b/gnm/gnm_frmts/gnm_frmts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gnm_frmts.h 34522 2016-07-02 21:33:00Z goatbar $
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  Classes related to format registration, and file opening.
diff --git a/gnm/gnm_frmts/gnmregisterall.cpp b/gnm/gnm_frmts/gnmregisterall.cpp
index 2d830a8..9b7a984 100644
--- a/gnm/gnm_frmts/gnmregisterall.cpp
+++ b/gnm/gnm_frmts/gnmregisterall.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  Function to register all known OGR drivers.
@@ -31,7 +30,7 @@
 
 #include "gnm_frmts.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: gnmregisterall.cpp 34866 2016-08-02 18:43:34Z goatbar $");
 
 void GNMRegisterAllInternal()
 {
diff --git a/gnm/gnm_frmts/o/README.TXT b/gnm/gnm_frmts/o/README.TXT
index 2058412..84dd14c 100644
--- a/gnm/gnm_frmts/o/README.TXT
+++ b/gnm/gnm_frmts/o/README.TXT
@@ -4,4 +4,4 @@ gdal/frmts/o
 This directory is where object files are put from the various format
 drivers so they can be easily linked into GDAL.  This file is here to
 ensure that the "o" directory isn't lost when people do a cvs checkout
-with pruning. 
+with pruning.
diff --git a/gnm/gnm_priv.h b/gnm/gnm_priv.h
index 9b81e23..0e2495a 100644
--- a/gnm/gnm_priv.h
+++ b/gnm/gnm_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gnm_priv.h 36302 2016-11-19 16:54:08Z bishop $
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM private and internal declarations.
@@ -73,23 +73,15 @@
 #define GNM_RULEKW_DENY "DENY"
 #define GNM_RULEKW_ANY "ANY"
 
-// Graph constants
-#define GNM_EDGE_DIR_BOTH       0   // bidirectional
-#define GNM_EDGE_DIR_SRCTOTGT   1   // from source to target
-#define GNM_EDGE_DIR_TGTTOSRC   2   // from target to source
-
 #define GNM_BLOCK_NONE 0x0000  // no blocking (vertex or edge)
 #define GNM_BLOCK_SRC  0x0001  // the source vertex is blocked
 #define GNM_BLOCK_TGT  0x0002  // the target vertext is blocked
 #define GNM_BLOCK_CONN 0x0004  // the connection edge is blocked
 #define GNM_BLOCK_ALL GNM_BLOCK_SRC | GNM_BLOCK_TGT | GNM_BLOCK_CONN
 
-
 // Other string constants.
 #define GNM_SRSFILENAME "_gnm_srs.prj"
 
-// Alias for some big data type to store identificators.
-#define GNMGFID GIntBig
 // Corespondent datatype for identificator
 // (i.e. int -> OFTInteger -> GetFieldAsInteger and
 //       GUIntBig -> OFTInteger64 -> GetFieldAsInteger64)
@@ -98,4 +90,3 @@
 #define GNMGFIDFormat CPL_FRMT_GIB
 
 #endif // GNM_PRIV
-
diff --git a/gnm/gnm_tut.dox b/gnm/gnm_tut.dox
index 766ed9c..924c805 100644
--- a/gnm/gnm_tut.dox
+++ b/gnm/gnm_tut.dox
@@ -4,7 +4,7 @@ This document is intended to describe using the GNM C++ classes to work with net
 
 \section gnm_tut_manage Managing networks
 
-In the first example we will create a small water network on the base of the set of spatial data (two shapefiles: pipes and wells which are situated at the GDAL source tree: autotest\gnm\data). The use of the common network format - GNMGdalNetwork class - will allow us to select one of the GDAL-supported vector formats for our network - ESRI Shapefile. After the creation we will build a topology and add some additional data: pumps layer, in order to manually edit network topology.
+In the first example we will create a small water network on the base of the set of spatial data (two shapefiles: pipes and wells which are situated at the GDAL source tree: autotest\\gnm\\data). The use of the common network format - GNMGdalNetwork class - will allow us to select one of the GDAL-supported vector formats for our network - ESRI Shapefile. After the creation we will build a topology and add some additional data: pumps layer, in order to manually edit network topology.
 
 Initially we register GDAL drivers and create some options (string pairs), which will be passed as parameters during network creation. Here we create a network's name.
 
@@ -23,22 +23,22 @@ int main ()
     papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_FORMAT, "ESRI Shapefile");
 
 \endcode
-    
+
 Some options are obligatory. The following parameters must be specified during the network creation: the path/name; format of network storage; spatial reference system (EPSG, WKT, etc.). The according dataset with the "network part" will be created and the resulting network will be returned.
 
 \code
     GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("GNMFile");
     GNMGenericNetwork* poDS = (GNMGenericNetwork*) poDriver->Create( "..\\network_data", 0, 0, 0, GDT_Unknown,
-                                                       papszDSCO );    
+                                                       papszDSCO );
     CSLDestroy(papszDSCO);
 \endcode
 
-For now we have a void network consisted of only "system layers". We need to populate it with "class layers" full of features, so we open a certain foreign dataset and copy layers from it to our network. Note, that we use GDALDataset:: methods for working with "class layers", because GNMNetwork inherited from GDALDataset. 
+For now we have a void network consisted of only "system layers". We need to populate it with "class layers" full of features, so we open a certain foreign dataset and copy layers from it to our network. Note, that we use GDALDataset:: methods for working with "class layers", because GNMNetwork inherited from GDALDataset.
 
 \code
     GDALDataset *poSrcDS = (GDALDataset*) GDALOpenEx("..\\in_data",
                                     GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL, NULL, NULL );
-                                    
+
     OGRLayer *poSrcLayer1 = poSrcDS->GetLayerByName("pipes");
     OGRLayer *poSrcLayer2 = poSrcDS->GetLayerByName("wells");
 
@@ -58,7 +58,7 @@ After the successful copying we have the network full of features, but with no t
         OGRLayer* poLayer = poDS->GetLayer(i);
         papszLayers = CSLAddString(papszLayers, poLayer->GetName() );
     }
-    
+
     if(poGenericNetwork->ConnectPointsByLines(papszLayers, dfTolerance,
                                         dfDirCost, dfInvCost, eDir) != CE_None )
     {
@@ -74,21 +74,21 @@ After the successful copying we have the network full of features, but with no t
 At this point we have a ready network with topological and spatial data, which can be used now for different purposes (analysis, converting into different formats, etc). But sometimes it is necessary to modify some network's data. For example we need to add additional features and attach them to our built topology (modify topology). We create a new "class layer" in the network and add one feature to it.
 
 \code
-     
+
     OGRLayer *poNewLayer = poDS->CreateLayer("pumps", , NULL, wkbPoint, NULL );
     if( poNewLayer == NULL )
     {
         printf( "Layer creation failed.\n" );
         exit( 1 );
     }
-    
+
     OGRFieldDefn fieldDefn ("pressure",OFTReal);
     if( poNewLayer->CreateField( &fieldDefn ) != OGRERR_NONE )
     {
         printf( "Creating Name field failed.\n" );
         exit( 1 );
     }
-        
+
     OGRFeature *poFeature = OGRFeature::CreateFeature(poNewLayer->GetLayerDefn());
     OGRPoint pt;
     pt.setX(37.291466);
@@ -99,10 +99,10 @@ At this point we have a ready network with topological and spatial data, which c
         printf( "Failed to create feature.\n" );
         exit( 1 );
     }
-    
+
     GNMGFID gfid = poFeature->GetFID();
 
-    OGRFeature::DestroyFeature( poFeature );   
+    OGRFeature::DestroyFeature( poFeature );
 \endcode
 
 After the successful creation the feature will be registered in the network and we can connect it with others. There can be two possible ways to do this. In the first case we need a real feature which will be an edge in the connection, while in the second case we do not need such feature, and passing -1 into the ConnectFeatures() method means that the special system edge will be created for this connection and added to the graph automatically. In our case we had added only one point feat [...]
@@ -135,11 +135,11 @@ int main ()
     papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_SRS, "EPSG:4326");
     papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_DESCR, "My pipes network");
     papszDSCO = CSLAddNameValue(papszDSCO, GNM_MD_FORMAT, "ESRI Shapefile");
-    
-    
+
+
     GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("GNMFile");
     GNMGenericNetwork* poDS = (GNMGenericNetwork*) poDriver->Create( "..\\network_data", 0, 0, 0, GDT_Unknown,
-                                                       papszDSCO );    
+                                                       papszDSCO );
     CSLDestroy(papszDSCO);
     if (poDS == NULL)
     {
@@ -174,7 +174,7 @@ int main ()
         OGRLayer* poLayer = poDS->GetLayer(i);
         papszLayers = CSLAddString(papszLayers, poLayer->GetName() );
     }
-    
+
     if(poGenericNetwork->ConnectPointsByLines(papszLayers, dfTolerance,
                                         dfDirCost, dfInvCost, eDir) != CE_None )
     {
@@ -192,14 +192,14 @@ int main ()
         printf( "Layer creation failed.\n" );
         exit( 1 );
     }
-    
+
     OGRFieldDefn fieldDefn ("pressure",OFTReal);
     if( poNewLayer->CreateField( &fieldDefn ) != OGRERR_NONE )
     {
         printf( "Creating Name field failed.\n" );
         exit( 1 );
     }
-        
+
     OGRFeature *poFeature = OGRFeature::CreateFeature(poNewLayer->GetLayerDefn());
     OGRPoint pt;
     pt.setX(37.291466);
@@ -210,10 +210,10 @@ int main ()
         printf( "Failed to create feature.\n" );
         exit( 1 );
     }
-    
+
     GNMGFID gfid = poFeature->GetFID();
 
-    OGRFeature::DestroyFeature( poFeature );    
+    OGRFeature::DestroyFeature( poFeature );
 
     if (poDS->ConnectFeatures(gfid ,63, -1, 5.0, 5.0, GNMDirection_SrcToTgt) != GNMError_None)
     {
@@ -246,7 +246,7 @@ int main ()
     }
 \endcode
 
-Before any calculations we open the dataset which will hold the layer with the resulting path. 
+Before any calculations we open the dataset which will hold the layer with the resulting path.
 
 \code
     GDALDataset *poResDS;
@@ -294,14 +294,14 @@ int main ()
     GDALAllRegister();
 
     GNMGenericNetwork *poNet = (GNMGenericNetwork*) GDALOpenEx("..\\network_data",
-                                                     GDAL_OF_GNM | GDAL_OF_UPDATE, 
+                                                     GDAL_OF_GNM | GDAL_OF_UPDATE,
                                                      NULL, NULL, NULL );
     if(poSrcDS == NULL)
     {
         printf("Can not open source dataset at\n");
         exit(1);
     }
-    
+
     GDALDataset *poResDS;
     poResDS = (GDALDataset*) GDALOpenEx("..\\out_data",
                                         GDAL_OF_VECTOR | GDAL_OF_UPDATE,
diff --git a/gnm/gnmgenericnetwork.cpp b/gnm/gnmgenericnetwork.cpp
index 8864f7e..cbbb362 100644
--- a/gnm/gnmgenericnetwork.cpp
+++ b/gnm/gnmgenericnetwork.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM network class.
@@ -30,10 +29,14 @@
  ****************************************************************************/
 
 #include "gnm_api.h"
+#include "gnm_priv.h"
 #include "ogrsf_frmts.h"
 
 #include <set>
 
+CPL_CVSID("$Id: gnmgenericnetwork.cpp 36461 2016-11-23 12:05:14Z rouault $");
+
+//! @cond Doxygen_Suppress
 GNMGenericNetwork::GNMGenericNetwork() :
     GNMNetwork(),
     m_nVersion(0),
@@ -792,8 +795,8 @@ OGRLayer *GNMGenericNetwork::GetPath(GNMGFID nStartFID, GNMGFID nEndFID,
     OGRGNMWrappedResultLayer* poResLayer =
                               new OGRGNMWrappedResultLayer(poMEMDS, poMEMLayer);
 
-    bool bReturnEdges = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, GNM_MD_FETCHEDGES, TRUE));
-    bool bReturnVertices = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, GNM_MD_FETCHVERTEX, TRUE));
+    const bool bReturnEdges = CPLFetchBool(papszOptions, GNM_MD_FETCHEDGES, true);
+    const bool bReturnVertices = CPLFetchBool(papszOptions, GNM_MD_FETCHVERTEX, true);
 
     switch (eAlgorithm)
     {
@@ -1119,6 +1122,7 @@ CPLErr GNMGenericNetwork::CreateMetadataLayer(GDALDataset * const pDS, int nVers
     {
         if(m_soSRS.size() >= nFieldSize)
         {
+            // cppcheck-suppress knownConditionTrueFalse
             if(StoreNetworkSrs() != CE_None)
                 return CE_Failure;
         }
@@ -1254,7 +1258,7 @@ CPLErr GNMGenericNetwork::LoadMetadataLayer(GDALDataset * const pDS)
         }
         else if(EQUALN(pKey, GNM_MD_RULE, nRulePrefixLen))
         {
-            moRules[atoi(pKey + nRulePrefixLen)] = pValue;
+            moRules[atoi(pKey + nRulePrefixLen)] = GNMRule(pValue);
         }
 
         OGRFeature::DestroyFeature(poFeature);
@@ -1269,6 +1273,7 @@ CPLErr GNMGenericNetwork::LoadMetadataLayer(GDALDataset * const pDS)
 
     if(m_soSRS.empty())
     {
+        // cppcheck-suppress knownConditionTrueFalse
         if(LoadNetworkSrs() != CE_None)
             return CE_Failure;
     }
@@ -1449,10 +1454,8 @@ CPLErr CPL_STDCALL GNMDisconnectFeaturesWithId(GNMGenericNetworkH hNet,
     VALIDATE_POINTER1( hNet, "GNMDisconnectFeaturesWithId", CE_Failure );
 
     return ((GNMGenericNetwork*)hNet)->DisconnectFeaturesWithId(nFID);
-
 }
 
-
 CPLErr CPL_STDCALL GNMReconnectFeatures (GNMGenericNetworkH hNet,
                                          GNMGFID nSrcFID, GNMGFID nTgtFID,
                                          GNMGFID nConFID, double dfCost,
@@ -1462,7 +1465,6 @@ CPLErr CPL_STDCALL GNMReconnectFeatures (GNMGenericNetworkH hNet,
 
     return ((GNMGenericNetwork*)hNet)->ReconnectFeatures(nSrcFID, nTgtFID,
                                         nConFID, dfCost, dfInvCost, eDir);
-
 }
 
 CPLErr CPL_STDCALL GNMCreateRule (GNMGenericNetworkH hNet, const char *pszRuleStr)
@@ -1470,7 +1472,6 @@ CPLErr CPL_STDCALL GNMCreateRule (GNMGenericNetworkH hNet, const char *pszRuleSt
     VALIDATE_POINTER1( hNet, "GNMCreateRule", CE_Failure );
 
     return ((GNMGenericNetwork*)hNet)->CreateRule(pszRuleStr);
-
 }
 
 CPLErr CPL_STDCALL GNMDeleteAllRules(GNMGenericNetworkH hNet)
@@ -1524,3 +1525,4 @@ CPLErr CPL_STDCALL GNMChangeAllBlockState (GNMGenericNetworkH hNet,
 
     return ((GNMGenericNetwork*)hNet)->ChangeAllBlockState(bIsBlock == TRUE);
 }
+//! @endcond
diff --git a/gnm/gnmgraph.cpp b/gnm/gnmgraph.cpp
index 2b39ba8..31bd478 100644
--- a/gnm/gnmgraph.cpp
+++ b/gnm/gnmgraph.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM graph implementation.
@@ -30,18 +29,17 @@
  ****************************************************************************/
 
 #include "gnmgraph.h"
+#include "gnm_priv.h"
 #include <algorithm>
 #include <limits>
 #include <set>
 
-GNMGraph::GNMGraph()
-{
-}
+CPL_CVSID("$Id: gnmgraph.cpp 36449 2016-11-22 22:28:39Z rouault $");
 
-GNMGraph::~GNMGraph()
-{
+//! @cond Doxygen_Suppress
+GNMGraph::GNMGraph() {}
 
-}
+GNMGraph::~GNMGraph() {}
 
 void GNMGraph::AddVertex(GNMGFID nFID)
 {
@@ -244,7 +242,7 @@ std::vector<GNMPATH> GNMGraph::KShortestPaths(GNMGFID nStartFID, GNMGFID nEndFID
     // A will be sorted by the path costs' descending.
     std::vector<GNMPATH> A;
 
-    if (nK <= 0)
+    if (nK == 0)
         return A; // return empty array if K is incorrect.
 
     // Temporary array for storing paths-candidates.
@@ -275,7 +273,7 @@ std::vector<GNMPATH> GNMGraph::KShortestPaths(GNMGFID nStartFID, GNMGFID nEndFID
 
     for (k = 0; k < nK - 1; ++k) // -1 because we have already found one
     {
-        std::map<GNMGFID, double> mDeletedEdges; // for infinity costs assignement
+        std::map<GNMGFID, double> mDeletedEdges; // for infinity costs assignment
         itAk = A[k].begin();
 
         for (i = 0; i < A[k].size() - 1; ++i) // avoid end node
@@ -620,3 +618,4 @@ void GNMGraph::TraceTargets(std::queue<GNMGFID> &vertexQueue,
     if (!neighbours_queue.empty())
         TraceTargets(neighbours_queue, markedVertIds, connectedIds);
 }
+//! @endcond
diff --git a/gnm/gnmgraph.h b/gnm/gnmgraph.h
index 1795db0..8474ae0 100644
--- a/gnm/gnmgraph.h
+++ b/gnm/gnmgraph.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gnmgraph.h 36302 2016-11-19 16:54:08Z bishop $
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM graph implementation.
@@ -29,33 +29,42 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "gnm_priv.h"
-#include <vector>
+#include "cpl_port.h"
+#include <map>
 #include <queue>
 #include <set>
+#include <vector>
 
-// Types declarations.
+// Alias for some big data type to store identificators.
+#define GNMGFID GIntBig
+// Graph constants
+#define GNM_EDGE_DIR_BOTH       0   // bidirectional
+#define GNM_EDGE_DIR_SRCTOTGT   1   // from source to target
+#define GNM_EDGE_DIR_TGTTOSRC   2   // from target to source
 
+// Types declarations.
 typedef std::vector<GNMGFID> GNMVECTOR, *LPGNMVECTOR;
 typedef const std::vector<GNMGFID> GNMCONSTVECTOR;
 typedef const std::vector<GNMGFID>* LPGNMCONSTVECTOR;
 typedef std::pair<GNMGFID,GNMGFID> EDGEVERTEXPAIR;
 typedef std::vector< EDGEVERTEXPAIR > GNMPATH;
 
+/** Edge */
 struct GNMStdEdge
 {
-    GNMGFID nSrcVertexFID;
-    GNMGFID nTgtVertexFID;
-    bool bIsBidir;
-    double dfDirCost;
-    double dfInvCost;
-    bool bIsBloked;
+    GNMGFID nSrcVertexFID; /**< Source vertex FID */
+    GNMGFID nTgtVertexFID; /**< Target vertex FID */
+    bool bIsBidir;         /**< Whether the edge is bidirectonal */
+    double dfDirCost;      /**< Direct cost */
+    double dfInvCost;      /**< Inverse cost */
+    bool bIsBloked;        /**< Whether the edge is blocked */
 };
 
+/** Vertex */
 struct GNMStdVertex
 {
-    GNMVECTOR anOutEdgeFIDs;
-    bool bIsBloked;
+    GNMVECTOR anOutEdgeFIDs; /**< TODO */
+    bool bIsBloked;          /**< Whether the vertex is blocked */
 };
 
 /**
@@ -115,7 +124,7 @@ public:
 
     /**
      * @brief Change edge properties
-     * @param nConFID Edge identificator
+     * @param nFID Edge identificator
      * @param dfCost Cost
      * @param dfInvCost Inverse cost
      */
@@ -124,7 +133,7 @@ public:
     /**
      * @brief Change the block state of edge or vertex
      * @param nFID Identificator
-     * @param bIsBlock Block or unblock
+     * @param bBlock Block or unblock
      */
     virtual void ChangeBlockState (GNMGFID nFID, bool bBlock);
 
@@ -140,7 +149,7 @@ public:
      *
      * This is mainly use for unblock all vertices and edges.
      *
-     * @param bIsBlock Block or unblock
+     * @param bBlock Block or unblock
      */
     virtual void ChangeAllBlockState (bool bBlock = false);
 
@@ -172,7 +181,7 @@ public:
      * first in a pair is a vertex identificator and the second is an edge
      * identificator leading to this vertex. The elements in a path array are
      * sorted by the path segments order, i.e. the first is the pair (nStartFID,
-     * -1) and the last is (nEndFID, <some edge>).
+     * -1) and the last is (nEndFID, <some edge>).
      * If there is no any path between start and end vertex the returned array
      * of paths will be empty. Also the actual amount of paths in the returned
      * array can be less or equal than the nK parameter.
@@ -195,6 +204,7 @@ public:
      */
     virtual GNMPATH ConnectedComponents(const GNMVECTOR &anEmittersIDs);
 
+    /** Clear */
     virtual void Clear();
 protected:
     /**
@@ -205,9 +215,10 @@ protected:
      * state of features, i.e. the blocked features are the barriers during the
      * routing process.
      *
-     * @param nFID - Vertex identificator from which to start tree building.
-     * @param mnPathTree - means < vertex id, edge id >
-     * @return std::map where the first is vertex identificator and the second
+     * @param nFID - Vertex identificator from which to start tree building
+     * @param mstEdges - TODO
+     * @param mnPathTree - means < vertex id, edge id >.
+     * std::map where the first is vertex identificator and the second
      * is the edge identificator, which is the best way to the current vertex.
      * The identificator to the start vertex is -1. If the vertex is isolated
      * the returned map will be empty.
@@ -215,9 +226,10 @@ protected:
     virtual void DijkstraShortestPathTree(GNMGFID nFID,
                                   const std::map<GNMGFID, GNMStdEdge> &mstEdges,
                                         std::map<GNMGFID, GNMGFID> &mnPathTree);
+    /** DijkstraShortestPath */
     virtual GNMPATH DijkstraShortestPath(GNMGFID nStartFID, GNMGFID nEndFID,
                                  const std::map<GNMGFID, GNMStdEdge> &mstEdges);
-
+//! @cond Doxygen_Suppress
     virtual LPGNMCONSTVECTOR GetOutEdges(GNMGFID nFID) const;
     virtual GNMGFID GetOppositVertex(GNMGFID nEdgeFID, GNMGFID nVertexFID) const;
     virtual void TraceTargets(std::queue<GNMGFID> &vertexQueue,
@@ -226,4 +238,5 @@ protected:
 protected:
     std::map<GNMGFID, GNMStdVertex> m_mstVertices;
     std::map<GNMGFID, GNMStdEdge>   m_mstEdges;
+//! @endcond
 };
diff --git a/gnm/gnmlayer.cpp b/gnm/gnmlayer.cpp
index 9663242..c2279a8 100644
--- a/gnm/gnmlayer.cpp
+++ b/gnm/gnmlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM layer class.
@@ -31,24 +30,24 @@
 #include "gnm.h"
 #include "gnm_priv.h"
 
+CPL_CVSID("$Id: gnmlayer.cpp 36366 2016-11-21 01:21:43Z rouault $");
+
 /**
  * GNMGenericLayer
  */
 GNMGenericLayer::GNMGenericLayer(OGRLayer* poLayer,
-                                 GNMGenericNetwork* poNetwork) : OGRLayer()
+                                 GNMGenericNetwork* poNetwork) :
+    OGRLayer(),
+    m_soLayerName( poLayer->GetName() ),
+    m_poLayer( poLayer ),
+    m_poNetwork( poNetwork )
 {
-    m_poLayer = poLayer;
-    m_poNetwork = poNetwork;
-    m_soLayerName = poLayer->GetName();
 }
 
 /**
  * ~GNMGenericLayer
  */
-GNMGenericLayer::~GNMGenericLayer()
-{
-
-}
+GNMGenericLayer::~GNMGenericLayer() {}
 
 const char *GNMGenericLayer::GetFIDColumn()
 {
@@ -133,6 +132,7 @@ int GNMGenericLayer::AttributeFilterEvaluationNeedsGeometry()
     return m_poLayer->AttributeFilterEvaluationNeedsGeometry();
 }
 
+//! @cond Doxygen_Suppress
 OGRErr GNMGenericLayer::InitializeIndexSupport(const char *pszVal)
 {
     return m_poLayer->InitializeIndexSupport(pszVal);
@@ -171,6 +171,7 @@ OGRErr GNMGenericLayer::ICreateFeature(OGRFeature *poFeature)
         return OGRERR_FAILURE;
     return m_poLayer->CreateFeature(poFeature);
 }
+//! @endcond
 
 OGRGeometry *GNMGenericLayer::GetSpatialFilter()
 {
@@ -364,4 +365,3 @@ OGRFeatureDefn *GNMGenericLayer::GetLayerDefn()
     //TODO: hide GNM_SYSFIELD_GFID filed
     return m_poLayer->GetLayerDefn();
 }
-
diff --git a/gnm/gnmnetwork.cpp b/gnm/gnmnetwork.cpp
index 7b41e4c..dcbbf85 100644
--- a/gnm/gnmnetwork.cpp
+++ b/gnm/gnmnetwork.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM network class.
@@ -32,15 +31,11 @@
 #include "gnm_api.h"
 #include "ogrsf_frmts.h"
 
-GNMNetwork::GNMNetwork() : GDALDataset()
-{
-
-}
+CPL_CVSID("$Id: gnmnetwork.cpp 35932 2016-10-25 16:22:20Z goatbar $");
 
-GNMNetwork::~GNMNetwork()
-{
+GNMNetwork::GNMNetwork() : GDALDataset() {}
 
-}
+GNMNetwork::~GNMNetwork() {}
 
 const char *GNMNetwork::GetName() const
 {
@@ -78,7 +73,6 @@ CPLErr CPL_STDCALL GNMDisconnectAll (GNMNetworkH hNet)
     VALIDATE_POINTER1( hNet, "GNMDisconnectAll", CE_Failure );
 
     return ((GNMNetwork*)hNet)->DisconnectAll();
-
 }
 
 OGRFeatureH CPL_STDCALL GNMGetFeatureByGlobalFID (GNMNetworkH hNet, GNMGFID nGFID)
diff --git a/gnm/gnmresultlayer.cpp b/gnm/gnmresultlayer.cpp
index 989b719..cc2fb35 100644
--- a/gnm/gnmresultlayer.cpp
+++ b/gnm/gnmresultlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM result layer class.
@@ -31,6 +30,9 @@
 #include "gnm.h"
 #include "gnm_priv.h"
 
+CPL_CVSID("$Id: gnmresultlayer.cpp 34931 2016-08-05 17:13:05Z rouault $");
+
+/** Constructor */
 OGRGNMWrappedResultLayer::OGRGNMWrappedResultLayer(GDALDataset* poDSIn,
                                                    OGRLayer* poLayerIn)
 {
@@ -119,6 +121,7 @@ OGRSpatialReference *OGRGNMWrappedResultLayer::GetSpatialRef()
     return poLayer->GetSpatialRef();
 }
 
+/** Undocumented */
 OGRErr OGRGNMWrappedResultLayer::InsertFeature(OGRFeature *poFeature,
                                               const CPLString &soLayerName,
                                               int nPathNo, bool bIsEdge)
@@ -210,4 +213,3 @@ OGRErr OGRGNMWrappedResultLayer::ICreateFeature(OGRFeature *poFeature)
 {
     return poLayer->CreateFeature(poFeature);
 }
-
diff --git a/gnm/gnmrule.cpp b/gnm/gnmrule.cpp
index e033885..e1135b7 100644
--- a/gnm/gnmrule.cpp
+++ b/gnm/gnmrule.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  GDAL/OGR Geography Network support (Geographic Network Model)
  * Purpose:  GNM rule class.
@@ -31,7 +30,9 @@
 #include "gnm.h"
 #include "gnm_priv.h"
 
+CPL_CVSID("$Id: gnmrule.cpp 36366 2016-11-21 01:21:43Z rouault $");
 
+/*! @cond Doxygen_Suppress */
 GNMRule::GNMRule()
 {
     m_bValid = false;
@@ -39,33 +40,30 @@ GNMRule::GNMRule()
     m_bAny = false;
 }
 
-GNMRule::GNMRule(const std::string &oRule)
+GNMRule::GNMRule(const std::string &oRule) :
+    m_soRuleString( oRule )
 {
-    m_soRuleString = oRule;
     m_bValid = ParseRuleString();
 }
 
-GNMRule::GNMRule(const char *pszRule)
+GNMRule::GNMRule(const char *pszRule) :
+    m_soRuleString( pszRule )
 {
-    m_soRuleString = pszRule;
     m_bValid = ParseRuleString();
 }
 
-GNMRule::GNMRule(const GNMRule &oRule)
+GNMRule::GNMRule(const GNMRule &oRule) :
+    m_soSrcLayerName ( oRule.m_soSrcLayerName ),
+    m_soTgtLayerName ( oRule.m_soTgtLayerName ),
+    m_soConnLayerName ( oRule.m_soConnLayerName ),
+    m_bAllow ( oRule.m_bAllow ),
+    m_bValid ( oRule.m_bValid ),
+    m_bAny ( oRule.m_bAny ),
+    m_soRuleString ( oRule.m_soRuleString )
 {
-    m_soSrcLayerName = oRule.m_soSrcLayerName;
-    m_soTgtLayerName = oRule.m_soTgtLayerName;
-    m_soConnLayerName = oRule.m_soConnLayerName;
-    m_bAllow = oRule.m_bAllow;
-    m_bValid = oRule.m_bValid;
-    m_bAny = oRule.m_bAny;
-    m_soRuleString = oRule.m_soRuleString;
 }
 
-GNMRule::~GNMRule()
-{
-
-}
+GNMRule::~GNMRule() {}
 
 bool GNMRule::IsValid() const
 {
@@ -185,5 +183,4 @@ bool GNMRule::ParseRuleString()
 
     return true;
 }
-
-
+/*! @endcond */
diff --git a/gnm/makefile.vc b/gnm/makefile.vc
index c5de34e..6dc0b9f 100755
--- a/gnm/makefile.vc
+++ b/gnm/makefile.vc
@@ -1,11 +1,17 @@
 
-EXTRAFLAGS =	-DWIN32 -I. -Iogrsf_frmts -Iogrsf_frmts\mem -I..\frmts\gtiff\libgeotiff -I..\frmts\zlib \
+EXTRAFLAGS =	-DWIN32 -I. -Iogrsf_frmts -Iogrsf_frmts\mem -I..\frmts\gtiff\libgeotiff $(ZLIB_FLAGS) \
 		$(PROJ_FLAGS) $(PROJ_INCLUDE) $(GEOS_CFLAGS)
 
 GDAL_ROOT = 	..
 
 !INCLUDE ..\nmake.opt
 
+!IFDEF ZLIB_EXTERNAL_LIB
+ZLIB_FLAGS = $(ZLIB_INC)
+!ELSE
+ZLIB_FLAGS = -I..\frmts\zlib
+!ENDIF
+
 GNM_FRMTS =	gnm_frmts\gnm_frmts.lib
 OBJ_GNM	=	gnmnetwork.obj gnmgenericnetwork.obj gnmlayer.obj gnmrule.obj \
             gnmresultlayer.obj gnmgraph.obj
diff --git a/install-sh b/install-sh
index cb3cac1..8453248 100755
--- a/install-sh
+++ b/install-sh
@@ -120,7 +120,7 @@ fi
 if [ x"$dir_arg" != x ]; then
 	dst=$src
 	src=""
-	
+
 	if [ -d $dst ]; then
 		instcmd=:
 		chmodcmd=""
@@ -130,7 +130,7 @@ if [ x"$dir_arg" != x ]; then
 else
 
 # Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad 
+# might cause directories to be created, which would be especially bad
 # if $src (and thus $dsttmp) contains '*'.
 
 	if [ -f $src -o -d $src ]
@@ -140,7 +140,7 @@ else
 		echo "install:  $src does not exist"
 		exit 1
 	fi
-	
+
 	if [ x"$dst" = x ]
 	then
 		echo "install:	no destination specified"
@@ -168,7 +168,7 @@ dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
 
 # Skip lots of stat calls in the usual case.
 if [ ! -d "$dstdir" ]; then
-defaultIFS='	
+defaultIFS='
 '
 IFS="${IFS-${defaultIFS}}"
 
@@ -207,17 +207,17 @@ else
 
 # If we're going to rename the final executable, determine the name now.
 
-	if [ x"$transformarg" = x ] 
+	if [ x"$transformarg" = x ]
 	then
 		dstfile=`basename $dst`
 	else
-		dstfile=`basename $dst $transformbasename | 
+		dstfile=`basename $dst $transformbasename |
 			sed $transformarg`$transformbasename
 	fi
 
 # don't allow the sed command to completely eliminate the filename
 
-	if [ x"$dstfile" = x ] 
+	if [ x"$dstfile" = x ]
 	then
 		dstfile=`basename $dst`
 	else
@@ -248,7 +248,7 @@ else
 # Now rename the file to the real destination.
 
 	$doit $rmcmd -f $dstdir/$dstfile &&
-	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+	$doit $mvcmd $dsttmp $dstdir/$dstfile
 
 fi &&
 
diff --git a/m4/acinclude.m4 b/m4/acinclude.m4
index 38fa1c6..33736f2 100644
--- a/m4/acinclude.m4
+++ b/m4/acinclude.m4
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: acinclude.m4 31826 2015-11-29 15:39:57Z goatbar $
+dnl $Id: acinclude.m4 37079 2017-01-09 22:46:26Z rouault $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Configure extra local definitions.
@@ -323,7 +323,9 @@ AC_DEFUN([AC_LD_SHARED],
 
   if test "$with_ld_shared" != "" ; then
     if test "$with_ld_shared" = "no" ; then
-      echo "user disabled shared library support."	
+      echo "user disabled shared library support."
+    elif test "$with_ld_shared" = "yes" ; then
+      AC_MSG_ERROR([--with-ld-shared not supported])
     else
       echo "using user supplied .so link command ... $with_ld_shared"	
     fi
diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4
new file mode 100644
index 0000000..2c18e49
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx.m4
@@ -0,0 +1,562 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the specified
+#   version of the C++ standard.  If necessary, add switches to CXX and
+#   CXXCPP to enable support.  VERSION may be '11' (for the C++11 standard)
+#   or '14' (for the C++14 standard).
+#
+#   The second argument, if specified, indicates whether you insist on an
+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+#   -std=c++11).  If neither is specified, you get whatever works, with
+#   preference for an extended mode.
+#
+#   The third argument, if specified 'mandatory' or if left unspecified,
+#   indicates that baseline support for the specified C++ standard is
+#   required and that the macro should error out if no mode with that
+#   support is found.  If specified 'optional', then configuration proceeds
+#   regardless, after defining HAVE_CXX${VERSION} if and only if a
+#   supporting mode is found.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz at redhat.com>
+#   Copyright (c) 2012 Zack Weinberg <zackw at panix.com>
+#   Copyright (c) 2013 Roy Stogner <roystgnr at ices.utexas.edu>
+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov at google.com>
+#   Copyright (c) 2015 Paul Norman <penorman at mac.com>
+#   Copyright (c) 2015 Moritz Klammler <moritz at klammler.eu>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.  This file is offered as-is, without any
+#   warranty.
+
+#serial 4
+
+dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
+dnl  (serial version number 13).
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
+  m4_if([$1], [11], [],
+        [$1], [14], [],
+        [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])],
+        [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$2], [], [],
+        [$2], [ext], [],
+        [$2], [noext], [],
+        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
+        [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
+  AC_LANG_PUSH([C++])dnl
+  ac_success=no
+  AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
+  ax_cv_cxx_compile_cxx$1,
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+    [ax_cv_cxx_compile_cxx$1=yes],
+    [ax_cv_cxx_compile_cxx$1=no])])
+  if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
+    ac_success=yes
+  fi
+
+  m4_if([$2], [noext], [], [dnl
+  if test x$ac_success = xno; then
+    for switch in -std=gnu++$1 -std=gnu++0x; do
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                     $cachevar,
+        [ac_save_CXX="$CXX"
+         CXX="$CXX $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXX="$ac_save_CXX"])
+      if eval test x\$$cachevar = xyes; then
+        CXX="$CXX $switch"
+        if test -n "$CXXCPP" ; then
+          CXXCPP="$CXXCPP $switch"
+        fi
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+
+  m4_if([$2], [ext], [], [dnl
+  if test x$ac_success = xno; then
+    dnl HP's aCC needs +std=c++11 according to:
+    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+    dnl Cray's crayCC needs "-h std=c++11"
+    for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                     $cachevar,
+        [ac_save_CXX="$CXX"
+         CXX="$CXX $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXX="$ac_save_CXX"])
+      if eval test x\$$cachevar = xyes; then
+        CXX="$CXX $switch"
+        if test -n "$CXXCPP" ; then
+          CXXCPP="$CXXCPP $switch"
+        fi
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+  AC_LANG_POP([C++])
+  if test x$ax_cxx_compile_cxx$1_required = xtrue; then
+    if test x$ac_success = xno; then
+      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
+    fi
+  fi
+  if test x$ac_success = xno; then
+    HAVE_CXX$1=0
+    AC_MSG_NOTICE([No compiler with C++$1 support was found])
+  else
+    HAVE_CXX$1=1
+    AC_DEFINE(HAVE_CXX$1,1,
+              [define if the compiler supports basic C++$1 syntax])
+  fi
+  AC_SUBST(HAVE_CXX$1)
+])
+
+
+dnl  Test body for checking C++11 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+)
+
+
+dnl  Test body for checking C++14 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+)
+
+
+dnl  Tests for new features in C++11
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+]])
+
+
+dnl  Tests for new features in C++14
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
+
+// If the compiler admits that it is not ready for C++14, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201402L
+
+#error "This is not a C++14 compiler"
+
+#else
+
+namespace cxx14
+{
+
+  namespace test_polymorphic_lambdas
+  {
+
+    int
+    test()
+    {
+      const auto lambda = [](auto&&... args){
+        const auto istiny = [](auto x){
+          return (sizeof(x) == 1UL) ? 1 : 0;
+        };
+        const int aretiny[] = { istiny(args)... };
+        return aretiny[0];
+      };
+      return lambda(1, 1L, 1.0f, '1');
+    }
+
+  }
+
+  namespace test_binary_literals
+  {
+
+    constexpr auto ivii = 0b0000000000101010;
+    static_assert(ivii == 42, "wrong value");
+
+  }
+
+  namespace test_generalized_constexpr
+  {
+
+    template < typename CharT >
+    constexpr unsigned long
+    strlen_c(const CharT *const s) noexcept
+    {
+      auto length = 0UL;
+      for (auto p = s; *p; ++p)
+        ++length;
+      return length;
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("x") == 1UL, "");
+    static_assert(strlen_c("test") == 4UL, "");
+    static_assert(strlen_c("another\0test") == 7UL, "");
+
+  }
+
+  namespace test_lambda_init_capture
+  {
+
+    int
+    test()
+    {
+      auto x = 0;
+      const auto lambda1 = [a = x](int b){ return a + b; };
+      const auto lambda2 = [a = lambda1(x)](){ return a; };
+      return lambda2();
+    }
+
+  }
+
+  namespace test_digit_seperators
+  {
+
+    constexpr auto ten_million = 100'000'000;
+    static_assert(ten_million == 100000000, "");
+
+  }
+
+  namespace test_return_type_deduction
+  {
+
+    auto f(int& x) { return x; }
+    decltype(auto) g(int& x) { return x; }
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static constexpr auto value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static constexpr auto value = true;
+    };
+
+    int
+    test()
+    {
+      auto x = 0;
+      static_assert(is_same<int, decltype(f(x))>::value, "");
+      static_assert(is_same<int&, decltype(g(x))>::value, "");
+      return x;
+    }
+
+  }
+
+}  // namespace cxx14
+
+#endif  // __cplusplus >= 201402L
+
+]])
diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx_11.m4
new file mode 100644
index 0000000..0aadeaf
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx_11.m4
@@ -0,0 +1,39 @@
+# ============================================================================
+#  http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX_11([ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the C++11
+#   standard; if necessary, add switches to CXX and CXXCPP to enable
+#   support.
+#
+#   This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX
+#   macro with the version set to C++11.  The two optional arguments are
+#   forwarded literally as the second and third argument respectively.
+#   Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for
+#   more information.  If you want to use this macro, you also need to
+#   download the ax_cxx_compile_stdcxx.m4 file.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz at redhat.com>
+#   Copyright (c) 2012 Zack Weinberg <zackw at panix.com>
+#   Copyright (c) 2013 Roy Stogner <roystgnr at ices.utexas.edu>
+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov at google.com>
+#   Copyright (c) 2015 Paul Norman <penorman at mac.com>
+#   Copyright (c) 2015 Moritz Klammler <moritz at klammler.eu>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 17
+
+AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX])
+AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [AX_CXX_COMPILE_STDCXX([11], [$1], [$2])])
diff --git a/m4/ax_lib_libkml.m4 b/m4/ax_lib_libkml.m4
index f26a1dc..18604f4 100644
--- a/m4/ax_lib_libkml.m4
+++ b/m4/ax_lib_libkml.m4
@@ -1,4 +1,4 @@
-dnl $Id: ax_lib_libkml.m4 29715 2015-08-21 17:46:02Z rouault $
+dnl $Id: ax_lib_libkml.m4 36466 2016-11-23 14:51:29Z rouault $
 dnl
 dnl @synopsis AX_LIB_LIBKML([MINIMUM-VERSION])
 dnl
@@ -39,7 +39,7 @@ dnl
 dnl @category InstalledPackages
 dnl @category Cxx
 dnl @author Mateusz Loskot <mateusz at loskot.net>
-dnl @version $Date: 2015-08-21 10:46:02 -0700 (Fri, 21 Aug 2015) $
+dnl @version $Date: 2016-11-23 06:51:29 -0800 (Wed, 23 Nov 2016) $
 dnl @license AllPermissive
 dnl          Copying and distribution of this file, with or without modification,
 dnl          are permitted in any medium without royalty provided the copyright notice and
@@ -106,6 +106,39 @@ AC_DEFUN([AX_LIB_LIBKML],
         [LIBKML_VERSION=;])
 
     if test -n "$LIBKML_VERSION" -a -n "$libkml_prefix"; then
+        # Test that the package found is for the right architecture
+        saved_CPPFLAGS="$CPPFLAGS"
+        saved_LIBS="$LIBS"
+        CPPFLAGS="$CPPFLAGS $LIBKML_CFLAGS"
+        LIBS="$LIBKML_LIBS"
+
+        AC_MSG_CHECKING([if libkml can be linked])
+        AC_LANG_PUSH([C++])
+        AC_LINK_IFELSE([
+            AC_LANG_PROGRAM(
+                [[
+@%:@include <kml/dom.h>
+                        ]],
+                        [[
+kmldom::KmlFactory* factory = kmldom::KmlFactory::GetFactory();
+                ]]
+            )],
+            [
+            HAVE_LIBKML=yes
+            AC_MSG_RESULT([yes])
+            ],
+            [
+            HAVE_LIBKML=no
+            AC_MSG_RESULT([no])
+            ]
+        )
+        AC_LANG_POP([C++])
+
+        CPPFLAGS="$saved_CPPFLAGS"
+        LIBS="$saved_LIBS"
+    fi
+
+    if test "$HAVE_LIBKML" = "yes"; then
         HAVE_LIBKML="yes"
 
 	LIBKML_LDFLAGS="$LIBKML_LIBS"
diff --git a/m4/ax_lib_xerces.m4 b/m4/ax_lib_xerces.m4
index 0bd4c70..07db16f 100644
--- a/m4/ax_lib_xerces.m4
+++ b/m4/ax_lib_xerces.m4
@@ -1,4 +1,4 @@
-dnl $Id: ax_lib_xerces.m4 23370 2011-11-13 13:21:30Z rouault $
+dnl $Id: ax_lib_xerces.m4 35650 2016-10-08 10:17:38Z rouault $
 dnl
 dnl @synopsis AX_LIB_XERCES([MINIMUM-VERSION])
 dnl
@@ -28,7 +28,7 @@ dnl
 dnl @category InstalledPackages
 dnl @category Cxx
 dnl @author Mateusz Loskot <mateusz at loskot.net>
-dnl @version $Date: 2011-11-13 05:21:30 -0800 (Sun, 13 Nov 2011) $
+dnl @version $Date: 2016-10-08 03:17:38 -0700 (Sat, 08 Oct 2016) $
 dnl @license AllPermissive
 dnl          Copying and distribution of this file, with or without modification,
 dnl          are permitted in any medium without royalty provided the copyright notice and
@@ -121,7 +121,7 @@ AC_DEFUN([AX_LIB_XERCES],
         CPPFLAGS="$CPPFLAGS -I$xerces_include_dir -I$xerces_include_dir2"
 
         saved_LIBS="$LIBS"
-        LIBS="$LIBS $xerces_lib_flags"
+        LIBS="$xerces_lib_flags $LIBS"
 
         dnl
         dnl Check Xerces headers
@@ -191,13 +191,10 @@ XMLPlatformUtils::Initialize();
 
     if test "$run_xerces_test" = "yes"; then
         if test "$xerces_header_found" = "yes" -a "$xerces_lib_found" = "yes"; then
-
-            AC_SUBST([XERCES_CFLAGS])
-            AC_SUBST([XERCES_LDFLAGS])
-
             HAVE_XERCES="yes"
         else
             XERCES_CFLAGS=""
+            XERCES_LDFLAGS=""
             HAVE_XERCES="no"
         fi
 
@@ -248,7 +245,14 @@ XMLPlatformUtils::Initialize();
                         AC_MSG_RESULT([yes])
                     else
                         AC_MSG_RESULT([no])
-                        AC_MSG_WARN([Found Xerces C++ Parser $XERCES_VERSION, which is older than required. Possible compilation failure.])
+                        if test "$xerces_requested" = "yes"; then
+                            AC_MSG_ERROR([Found Xerces C++ Parser $XERCES_VERSION, which is older than required.])
+                        else
+                            AC_MSG_WARN([Found Xerces C++ Parser $XERCES_VERSION, which is older than required. Disabling it])
+                            XERCES_CFLAGS=""
+                            XERCES_LDFLAGS=""
+                            HAVE_XERCES="no"
+                        fi
                     fi
                 else
                     AC_MSG_RESULT([no])
@@ -257,6 +261,9 @@ XMLPlatformUtils::Initialize();
             fi
         fi
 
+        AC_SUBST([XERCES_CFLAGS])
+        AC_SUBST([XERCES_LDFLAGS])
+
     else
         HAVE_XERCES="no"
         AC_MSG_RESULT([$HAVE_XERCES])
diff --git a/m4/geos.m4 b/m4/geos.m4
index 386a2c8..c77b582 100644
--- a/m4/geos.m4
+++ b/m4/geos.m4
@@ -1,5 +1,5 @@
 dnl ***************************************************************************
-dnl $Id: geos.m4 23370 2011-11-13 13:21:30Z rouault $
+dnl $Id: geos.m4 35222 2016-08-28 06:06:11Z goatbar $
 dnl
 dnl Project:  GDAL
 dnl Purpose:  Test for GEOS library presence
@@ -33,16 +33,16 @@ dnl
 dnl GEOS_INIT (MINIMUM_VERSION)
 dnl
 dnl Test for GEOS: define HAVE_GEOS, GEOS_LIBS, GEOS_CFLAGS, GEOS_VERSION
-dnl 
+dnl
 dnl Call as GEOS_INIT or GEOS_INIT(minimum version) in configure.in. Test
-dnl HAVE_GEOS (yes|no) afterwards. If yes, all other vars above can be 
+dnl HAVE_GEOS (yes|no) afterwards. If yes, all other vars above can be
 dnl used in program.
 dnl
 
 AC_DEFUN([GEOS_INIT],[
   AC_SUBST(GEOS_LIBS)
   AC_SUBST(GEOS_CFLAGS)
-  AC_SUBST(HAVE_GEOS) 
+  AC_SUBST(HAVE_GEOS)
   AC_SUBST(GEOS_VERSION)
 
   AC_ARG_WITH(geos,
@@ -96,7 +96,7 @@ AC_DEFUN([GEOS_INIT],[
        sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
     req_micro=`echo $min_geos_version | \
        sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
-      
+
     version_ok="no"
     ac_req_version=`expr $req_major \* 100000 \+  $req_minor \* 100 \+ $req_micro`
     ac_geos_version=`expr $geos_major_version \* 100000 \+  $geos_minor_version \* 100 \+ $geos_micro_version`
@@ -118,7 +118,7 @@ AC_DEFUN([GEOS_INIT],[
       fi
 
     else
-      
+
       HAVE_GEOS="no"
 
       GEOS_LIBS="`${GEOS_CONFIG} --ldflags` -lgeos_c"
diff --git a/m4/sfcgal.m4 b/m4/sfcgal.m4
new file mode 100644
index 0000000..5e2775b
--- /dev/null
+++ b/m4/sfcgal.m4
@@ -0,0 +1,150 @@
+dnl ***************************************************************************
+dnl
+dnl Project:  GDAL
+dnl Purpose:  Test for SFCGAL library presence
+dnl Author:   Avyav Kumar Singh, avyavkumar at gmail.com
+dnl	          Ideas borrowed from the old GDAL test and from the m4 file
+dnl           gdal/m4/geos.m4 written by Andrey Kiselev for GEOS originally
+dnl
+dnl ***************************************************************************
+dnl Copyright (c) 2016, Avyav Kumar Singh
+dnl
+dnl Permission is hereby granted, free of charge, to any person obtaining a
+dnl copy of this software and associated documentation files (the "Software"),
+dnl to deal in the Software without restriction, including without limitation
+dnl the rights to use, copy, modify, merge, publish, distribute, sublicense,
+dnl and/or sell copies of the Software, and to permit persons to whom the
+dnl Software is furnished to do so, subject to the following conditions:
+dnl
+dnl The above copyright notice and this permission notice shall be included
+dnl in all copies or substantial portions of the Software.
+dnl
+dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+dnl OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+dnl FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+dnl THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+dnl DEALINGS IN THE SOFTWARE.
+dnl ***************************************************************************
+
+dnl
+dnl SFCGAL_INIT (MINIMUM_VERSION)
+dnl
+dnl Test for SFCGAL: define HAVE_SFCGAL, SFCGAL_LIBS, SFCGAL_CFLAGS, SFCGAL_VERSION
+dnl
+dnl Call as SFCGAL_INIT or SFCGAL_INIT(minimum version) in configure.in. Test
+dnl HAVE_SFCGAL (yes|no) afterwards. If yes, all other vars above can be
+dnl used in program.
+dnl
+
+AC_DEFUN([SFCGAL_INIT],[
+  AC_SUBST(SFCGAL_LIBS)
+  AC_SUBST(SFCGAL_CFLAGS)
+  AC_SUBST(HAVE_SFCGAL)
+  AC_SUBST(SFCGAL_VERSION)
+
+  AC_ARG_WITH(sfcgal,
+    AS_HELP_STRING([--with-sfcgal[=ARG]],
+                   [Include SFCGAL support (ARG=yes, no or sfcgal-config path)]),,)
+
+  ac_sfcgal_config_auto=no
+
+  if test x"$with_sfcgal" = x"no" ; then
+
+    AC_MSG_RESULT([SFCGAL support disabled])
+    SFCGAL_CONFIG=no
+
+  elif test x"$with_sfcgal" = x"yes" -o x"$with_sfcgal" = x"" ; then
+
+    AC_PATH_PROG(SFCGAL_CONFIG, sfcgal-config, no)
+    ac_sfcgal_config_auto=yes
+
+  else
+
+   ac_sfcgal_config=`basename "$with_sfcgal"`
+   ac_sfcgal_config_dir=`AS_DIRNAME(["$with_sfcgal"])`
+
+   AC_CHECK_PROG(
+        SFCGAL_CONFIG,
+        "$ac_sfcgal_config",
+        $with_sfcgal,
+        [no],
+        ["$ac_sfcgal_config_dir"],
+        []
+   )
+
+  fi
+
+  if test x"$SFCGAL_CONFIG" != x"no" ; then
+
+    min_sfcgal_version=ifelse([$1], ,1.2.2,$1)
+
+    AC_MSG_CHECKING(for SFCGAL version >= $min_sfcgal_version)
+
+    sfcgal_major_version=`$SFCGAL_CONFIG --version | \
+       sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
+    sfcgal_minor_version=`$SFCGAL_CONFIG --version | \
+       sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
+    sfcgal_micro_version=`$SFCGAL_CONFIG --version | \
+       sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
+
+    req_major=`echo $min_sfcgal_version | \
+       sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'`
+    req_minor=`echo $min_sfcgal_version | \
+       sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'`
+    req_micro=`echo $min_sfcgal_version | \
+       sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'`
+
+    version_ok="no"
+    ac_req_version=`expr $req_major \* 100000 \+  $req_minor \* 100 \+ $req_micro`
+    ac_sfcgal_version=`expr $sfcgal_major_version \* 100000 \+  $sfcgal_minor_version \* 100 \+ $sfcgal_micro_version`
+
+    if test $ac_req_version -le $ac_sfcgal_version; then
+        version_ok="yes"
+        AC_MSG_RESULT([yes])
+    fi
+
+    if test $version_ok = "no"; then
+
+      HAVE_SFCGAL="no"
+      AC_MSG_RESULT(no)
+
+      if test $ac_sfcgal_config_auto = "yes" ; then
+        AC_MSG_WARN([SFCGAL was found on your system, but sfcgal-config reports version ${sfcgal_major_version}.${sfcgal_minor_version}.${sfcgal_micro_version}, need at least $min_sfcgal_version. SFCGAL support disabled.])
+      else
+        AC_MSG_ERROR([sfcgal-config reports version ${sfcgal_major_version}.${sfcgal_minor_version}.${sfcgal_micro_version}, need at least $min_sfcgal_version or configure --without-sfcgal])
+      fi
+
+    else
+
+      HAVE_SFCGAL="no"
+
+      SFCGAL_LIBS="`${SFCGAL_CONFIG} --libs`"
+      SFCGAL_CFLAGS="`${SFCGAL_CONFIG} --cflags`"
+      SFCGAL_VERSION="`${SFCGAL_CONFIG} --version`"
+
+      ax_save_LIBS="${LIBS}"
+      LIBS=${SFCGAL_LIBS}
+      ax_save_CFLAGS="${CFLAGS}"
+      CFLAGS="${SFCGAL_CFLAGS}"
+
+      AC_CHECK_LIB([SFCGAL],
+        [sfcgal_version],
+        [HAVE_SFCGAL="yes"],
+        [HAVE_SFCGAL="no"],
+        []
+      )
+
+
+      if test x"$HAVE_SFCGAL" = "xno"; then
+          SFCGAL_CFLAGS=""
+      fi
+
+      CFLAGS="${ax_save_CFLAGS}"
+      LIBS="${ax_save_LIBS}"
+
+    fi
+
+  fi
+])
diff --git a/makefile.vc b/makefile.vc
index 3586315..7c8c0c4 100644
--- a/makefile.vc
+++ b/makefile.vc
@@ -3,13 +3,6 @@ GDAL_ROOT = .
 !INCLUDE nmake.opt
 
 ##############################################################################
-# We need to add vb6 support if STDCALL is defined. 
-!IF DEFINED(STDCALL) && $(MSVC_VER) < 1500
-VB6_OBJ = vb6\vb6_support.obj
-VB6_TARGET = vb6_dir
-!ENDIF
-
-##############################################################################
 # The following determines whether we are linking all the OGR formats 
 # into the DLL, or only the minimum spatial reference related stuff required
 # for a raster-gdal build.
@@ -24,7 +17,6 @@ OGR_BASE_INCLUDE = /INCLUDE:$(SYM_PREFIX)OSRValidate \
 		/INCLUDE:$(SYM_PREFIX)OGR_G_GetPointCount 
 
 
-CPPFLAGS = $(CPPFLAGS) -DOGR_ENABLED
 OGR_OBJ = ogr\ogrsf_frmts\ogrsf_frmts.lib ogr\ogr.lib
 OGR_INCLUDE = $(OGR_BASE_INCLUDE) \
 		/INCLUDE:$(SYM_PREFIX)OGRRegisterAll
@@ -35,15 +27,11 @@ CPPFLAGS = $(CPPFLAGS) -DGNM_ENABLED
 
 !IF DEFINED(STDCALL) && !DEFINED(WIN64)
 
-!IF $(MSVC_VER) < 1500
-VB6_SAFEARRAYSYM =	/INCLUDE:_vbSafeArrayToPtr at 16
-!ENDIF
-
 BASE_INCLUDE =	/INCLUDE:_GDALSimpleImageWarp at 36 \
 		/INCLUDE:_GDALReprojectImage at 48 \
 		/INCLUDE:_GDALComputeMedianCutPCT at 32 \
 		/INCLUDE:_GDALDitherRGB2PCT at 28 \
-		/INCLUDE:_OCTNewCoordinateTransformation at 8 $(VB6_SAFEARRAYSYM)
+		/INCLUDE:_OCTNewCoordinateTransformation at 8
 !ELSE
 BASE_INCLUDE =	/INCLUDE:$(SYM_PREFIX)GDALSimpleImageWarp \
 		/INCLUDE:$(SYM_PREFIX)GDALReprojectImage \
@@ -52,25 +40,34 @@ BASE_INCLUDE =	/INCLUDE:$(SYM_PREFIX)GDALSimpleImageWarp \
 		/INCLUDE:$(SYM_PREFIX)OCTNewCoordinateTransformation
 !ENDIF
 
-LIBOBJ = port\*.obj gcore\*.obj alg\*.obj frmts\o\*.obj $(OGR_OBJ) gnm\*.obj gnm\gnm_frmts\o\*.obj $(VB6_OBJ) \
-	 apps\commonutils.obj apps\gdalinfo_lib.obj apps\gdal_translate_lib.obj apps\gdalwarp_lib.obj apps\ogr2ogr_lib.obj \
+APPS_OBJ = apps\commonutils.obj apps\gdalinfo_lib.obj apps\gdal_translate_lib.obj apps\gdalwarp_lib.obj apps\ogr2ogr_lib.obj \
 	 apps\gdaldem_lib.obj apps\nearblack_lib.obj apps\gdal_grid_lib.obj apps\gdal_rasterize_lib.obj apps\gdalbuildvrt_lib.obj
-	
+
+LIBOBJ = port\*.obj gcore\*.obj alg\*.obj frmts\o\*.obj $(OGR_OBJ) gnm\*.obj gnm\gnm_frmts\o\*.obj $(APPS_OBJ)
+
+LIB_DEPENDS = port_dir core_dir ogr_dir gnm_dir frmts_dir appslib-target
+
 DISTDIR	=	gdal_$(VERSION)
 
-default:	port_dir ogr_dir gnm_dir core_dir frmts_dir appslib-target $(VB6_TARGET)$(GDAL_DLL) \
-		plugin_dir apps_dir 
+!IFDEF DLLBUILD
+TARGET_LIB = dll
+PLUGIN_TARGET = plugin_dir
+!ELSE
+TARGET_LIB = staticlib
+!ENDIF
+
+DEFAULT_TARGETS = 
 
-staticlib:
+default:	$(TARGET_LIB) $(PLUGIN_TARGET) apps_dir
+
+staticlib:      $(LIB_DEPENDS)
 	if exist gdal.lib del gdal.lib
 	lib /nologo /out:gdal.lib $(LIBOBJ)
 
 appslib-target:
 	cd apps
 	$(MAKE) /f makefile.vc appslib
-	cd ..	
-
-target-lib: port_dir ogr_dir gnm_dir core_dir frmts_dir appslib-target dll 
+	cd ..
 
 clean:	
 	cd port
@@ -97,9 +94,6 @@ clean:
 	cd swig
 	$(MAKE) /f makefile.vc clean
 	cd ..
-	cd vb6
-	$(MAKE) /f makefile.vc clean
-	cd ..
 	if exist gdal.lib del gdal.lib
 	if exist $(GDAL_DLL) del $(GDAL_DLL)
 	if exist $(GDAL_DLL).manifest del $(GDAL_DLL).manifest
@@ -117,7 +111,7 @@ ogr_min:
 	$(MAKE) /f makefile.vc ogr.lib
 	cd ..
 
-core_dir:
+core_dir: port_dir
 	cd gcore
 	$(MAKE) /f makefile.vc
 	cd ..\alg
@@ -129,7 +123,7 @@ frmts_dir:
 	$(MAKE) /f makefile.vc
 	cd ..
 
-plugin_dir:
+plugin_dir: dll
 	cd frmts
 	$(MAKE) /f makefile.vc plugindirs
 	cd ..
@@ -139,16 +133,11 @@ plugin_dir:
 	cd ..\..
 !ENDIF
 
-apps_dir:
+apps_dir:   $(TARGET_LIB)
 	cd apps
 	$(MAKE) /f makefile.vc
 	cd ..
 
-vb6_dir:
-	cd vb6
-	$(MAKE) /f makefile.vc
-	cd ..
-	
 ogr_dir:      port_dir
 	cd frmts/iso8211
 	$(MAKE) /f makefile.vc
@@ -169,7 +158,7 @@ lib_dist:	default
 	cp gdal.lib port\*.h gcore\*.h ogr\*.h $(DISTDIR)
 	zip -r $(DISTDIR).zip $(DISTDIR)
 
-$(GDAL_DLL): staticlib
+$(GDAL_DLL): $(LIB_DEPENDS)
 	link /nologo /dll $(OGR_INCLUDE) $(BASE_INCLUDE) $(LIBOBJ) \
 		$(EXTERNAL_LIBS) gcore\Version.res \
 		 /out:$(GDAL_DLL) /implib:gdal_i.lib $(LINKER_FLAGS)
@@ -177,10 +166,10 @@ $(GDAL_DLL): staticlib
 
 dll:	$(GDAL_DLL)
 
-install: $(GDAL_DLL) plugin_dir apps_dir 
+install: default
 	-mkdir $(BINDIR)
 	-mkdir $(DATADIR)
-	$(INSTALL) $(GDAL_DLL) $(BINDIR)
+	if exist $(GDAL_DLL) $(INSTALL) $(GDAL_DLL) $(BINDIR)
 	cd frmts
 	$(MAKE) /f makefile.vc plugins-install
 	cd ..\apps
@@ -195,9 +184,6 @@ install: $(GDAL_DLL) plugin_dir apps_dir
 	cd ..
 !ENDIF
 !IFDEF INCLUDE_OGR_FRMTS
-	cd ogr
-	$(MAKE) /f makefile.vc install
-	cd ..
 	cd ogr\ogrsf_frmts
 	$(MAKE) /f makefile.vc plugins-install
 !IFDEF HTMLDIR
@@ -205,15 +191,13 @@ install: $(GDAL_DLL) plugin_dir apps_dir
 !ENDIF
 	cd ..\..
 !ENDIF
-!IFDEF INCLUDE_GNM_FRMTS
-    cd gnm
-    $(MAKE) /f makefile.vc install
-    cd ..
-!ENDIF
 
-devinstall: install
-	-mkdir $(INCDIR)
+libinstall: $(GDALLIB)
 	-mkdir $(LIBDIR)
+	copy %|feF $(LIBDIR)
+
+devinstall: install libinstall
+	-mkdir $(INCDIR)
 	copy port\*.h $(INCDIR)
 	copy gcore\*.h $(INCDIR)
 	copy alg\*.h $(INCDIR)
@@ -225,8 +209,8 @@ devinstall: install
 	copy ogr\ogrsf_frmts\*.h $(INCDIR)
 !ENDIF
 !IFDEF INCLUDE_GNM_FRMTS
-	copy gnm\*.h $(INCDIR)
+	copy gnm\gnm.h $(INCDIR)
+	copy gnm\gnm_api.h $(INCDIR)
+    copy gnm\gnmgraph.h $(INCDIR)
 !ENDIF
 	copy apps\gdal_utils.h $(INCDIR)
-	copy gdal_i.lib $(LIBDIR)
-
diff --git a/makegdal_gen.bat b/makegdal_gen.bat
deleted file mode 100644
index 40a984e..0000000
--- a/makegdal_gen.bat
+++ /dev/null
@@ -1,369 +0,0 @@
- at echo off
-
-:: ****************************************************************************
-::  $Id: $
-:: 
-::  Name:     makegdal_gen.bat
-::  Project:  GDAL 
-::  Purpose:  Generate MS Visual C++ => 10.0 project files    
-::  Author:   Ivan Lucena, [ivan lucena at outlook dot com]
-:: 
-:: ****************************************************************************
-::  Copyright (c) 2007, Ivan Lucena    
-:: 
-::  Permission is hereby granted, free of charge, to any person obtaining a
-::  copy of this software and associated documentation files (the "Software"),
-::  to deal in the Software without restriction, including without limitation
-::  the rights to use, copy, modify, merge, publish, distribute, sublicense,
-::  and/or sell copies of the Software, and to permit persons to whom the
-::  Software is furnished to do so, subject to the following conditions:
-:: 
-::  The above copyright notice and this permission notice shall be included
-::  in all copies or substantial portions of the Software.
-:: 
-::  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-::  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-::  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-::  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-::  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-::  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-::  DEALINGS IN THE SOFTWARE.
-:: ****************************************************************************
-
-if "%1"=="" (
-   goto :usage
-)
-
-if "%2"=="" (
-   goto :usage
-)
-
-if "%3"=="" (
-   goto :usage
-)
-
-::  *********************
-::  Get Visual C++ version
-::  *********************
-
-set _vcver_=%1
-
-set _clver_=1600
-
-if "%_vcver_%"=="14.0" (
-	set _clver_=1900
-) else ( if "%_vcver_%"=="12.0" (
-	set _clver_=1800
-) else ( if "%_vcver_%"=="11.0" (
-	set _clver_=1700
-) else ( if "%_vcver_%"=="10.0" (
-	set _clver_=1600
-) else (
-    echo Wrong value for parameter 1. See usage:
-	goto :usage
-))))
-
-::  *********************
-::  Get Platform
-::  *********************
-
-set _platf_=%2
-set _winver_=Win32
-
-if not "%_platf_%"=="32" (
-    if not "%_platf_%"=="64" (
-	    echo Wrong value for parameter 2. See usage:
-	    goto :usage
-    )
-)
-
-if "%_platf_%"=="64" (
-    set _winver_=x64
-)
-
-goto :continue
-
-::  *********************
-:usage
-::  *********************
-
-echo Usage: makegdal_gen ^<Visual C++ version^> [32^|64] ^<^(*^) project file name^>
-echo Parameters:
-echo    1 : Visual C++ version is not the same as Visual Studio version ^( =^> 10.0 ^)
-echo    2 : Windows platform 32 for Win32 and 64 for Win64
-echo    3 : Base file name, with no path and no extension ^(*^)
-echo Examples:
-echo    makegdal_gen 10.1 32 makefileproj_vs10
-echo    makegdal_gen 11.0 64 makefileproj_vs11
-echo    makegdal_gen 12.0 64 makefileproj_vs12
-echo    makegdal_gen 14.0 64 makefileproj_vs14
-
-goto :end
-
-::  *********************
-::  Set Project file names
-::  *********************
-
-:continue
-
-set _mainfile_=%CD%\%3.vcxproj
-set _userfile_=%_mainfile_%.user
-set _ftrlfile_=%_mainfile_%.filters
-
-:: Add quotes
-
-set _mainfile_="%_mainfile_%"
-set _userfile_="%_userfile_%"
-set _ftrlfile_="%_ftrlfile_%"
-
-:: Progress message
-
-echo Generating:
-echo   %_mainfile_%
-echo   %_userfile_%
-echo   %_ftrlfile_%
-echo This might take a little while...
-
-:: Delete existing files
-
-if exist %_mainfile_% (
-  del %_mainfile_%
-)
-
-if exist %_userfile_% ( 
-  del %_userfile_%
-)
-
-if exist %_ftrlfile_% ( 
-  del %_ftrlfile_%
-)
-
-:: **********************************************
-:: Generate user file (.vcxproj.user)
-:: **********************************************
-
-echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_userfile_%
-echo ^<Project ToolsVersion="%_vcver_%" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>   >> %_userfile_%
-echo     ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>  >> %_userfile_%
-echo       ^<LocalDebuggerDebuggerType^>Auto^</LocalDebuggerDebuggerType^>                 >> %_userfile_%
-echo       ^<LocalDebuggerCommand^>%CD%\apps\gdal_translate.exe^</LocalDebuggerCommand^>   >> %_userfile_%
-echo       ^<LocalDebuggerCommandArguments^>--formats^</LocalDebuggerCommandArguments^>    >> %_userfile_%
-echo       ^<DebuggerFlavor^>WindowsLocalDebugger^</DebuggerFlavor^>                       >> %_userfile_%
-echo     ^</PropertyGroup^>                                     >> %_userfile_%
-echo ^</Project^>                                               >> %_userfile_%
-
-:: **********************************************
-:: Initialize filters file (.vcxproj.filters)
-:: **********************************************
-
-echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_ftrlfile_%
-echo ^<Project ToolsVersion="5.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>         >> %_ftrlfile_%
-
-:: **********************************************
-:: Main file generator (.vcxproj) and filters file (.vcxproj.filters)
-:: **********************************************
-
-echo ^<?xml version="1.0" encoding="utf-8"?^>                   >> %_mainfile_%
-echo ^<Project DefaultTargets="Build" ToolsVersion="%_vcver_%" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"^>          >> %_mainfile_%
-echo   ^<ItemGroup Label="ProjectConfigurations"^>              >> %_mainfile_%
-echo     ^<ProjectConfiguration Include="Debug|%_winver_%"^>    >> %_mainfile_%
-echo       ^<Configuration^>Debug^</Configuration^>             >> %_mainfile_%
-echo       ^<Platform^>%_winver_%^</Platform^>                  >> %_mainfile_%
-echo     ^</ProjectConfiguration^>                              >> %_mainfile_%
-echo     ^<ProjectConfiguration Include="Release|%_winver_%"^>  >> %_mainfile_%
-echo       ^<Configuration^>Release^</Configuration^>           >> %_mainfile_%
-echo       ^<Platform^>%_winver_%^</Platform^>                  >> %_mainfile_%
-echo     ^</ProjectConfiguration^>                              >> %_mainfile_%
-echo   ^</ItemGroup^>                                           >> %_mainfile_% 
-echo   ^<PropertyGroup Label="Globals"^>                        >> %_mainfile_%
-echo     ^<Keyword^>MakeFileProj^</Keyword^>                    >> %_mainfile_%
-echo   ^</PropertyGroup^>                                       >> %_mainfile_%
-echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /^>  >> %_mainfile_%   
-echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'" Label="Configuration"^>    >> %_mainfile_%
-echo     ^<ConfigurationType^>Makefile^</ConfigurationType^>    >> %_mainfile_%
-echo     ^<UseDebugLibraries^>true^</UseDebugLibraries^>        >> %_mainfile_%
-echo     ^<PlatformToolset^>v120^</PlatformToolset^>            >> %_mainfile_%
-echo   ^</PropertyGroup^>                                       >> %_mainfile_%
-echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|%_winver_%'" Label="Configuration"^>  >> %_mainfile_%
-echo     ^<ConfigurationType^>Makefile^</ConfigurationType^>    >> %_mainfile_%
-echo     ^<UseDebugLibraries^>true^</UseDebugLibraries^>        >> %_mainfile_%
-echo     ^<PlatformToolset^>v120^</PlatformToolset^>            >> %_mainfile_%
-echo   ^</PropertyGroup^>                                       >> %_mainfile_%
-echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /^>      >> %_mainfile_%
-echo   ^<ImportGroup Label="ExtensionSettings"^>                >> %_mainfile_%  
-echo   ^</ImportGroup^>                                         >> %_mainfile_%
-echo   ^<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>     >> %_mainfile_% 
-echo     ^<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /^>    >> %_mainfile_%
-echo   ^</ImportGroup^>                                         >> %_mainfile_%
-echo   ^<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|%_winver_%'"^>  >> %_mainfile_%
-echo     ^<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /^>     >> %_mainfile_%
-echo   ^</ImportGroup^>                                         >> %_mainfile_%
-echo   ^<PropertyGroup Label="UserMacros" /^>                   >> %_mainfile_%
-echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|%_winver_%'"^>     >> %_mainfile_%
-echo     ^<NMakeBuildCommandLine^>nmake -f makefile.vc^</NMakeBuildCommandLine^>            >> %_mainfile_%
-echo     ^<NMakeOutput^>^</NMakeOutput^>                                                    >> %_mainfile_%
-echo     ^<NMakeCleanCommandLine^>nmake -f makefile.vc clean^</NMakeCleanCommandLine^>      >> %_mainfile_%
-echo     ^<NMakeReBuildCommandLine^>nmake -f makefile.vc clean ^&^& nmake -f makefile.vc^</NMakeReBuildCommandLine^>  >> %_mainfile_%
-echo     ^<NMakePreprocessorDefinitions^>%_winver_%;_DEBUG;$(NMakePreprocessorDefinitions)^</NMakePreprocessorDefinitions^>   >> %_mainfile_%
-echo     ^<LibraryPath^>$(VC_LibraryPath_x%_platf_%);$(WindowsSDK_LibraryPath_x%_platf_%);$(VC_SourcePath);^</LibraryPath^>   >> %_mainfile_%
-echo   ^</PropertyGroup^>                                                                   >> %_mainfile_%
-echo   ^<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|%_winver_%'"^>   >> %_mainfile_%
-echo     ^<NMakeBuildCommandLine^>nmake -f makefile.vc^</NMakeBuildCommandLine^>            >> %_mainfile_%
-echo     ^<NMakeOutput^>^</NMakeOutput^>                                                    >> %_mainfile_%
-echo     ^<NMakeCleanCommandLine^>nmake -f makefile.vc clean^</NMakeCleanCommandLine^>      >> %_mainfile_%
-echo     ^<NMakeReBuildCommandLine^>nmake -f makefile.vc clean ^&^& nmake -f makefile.vc^</NMakeReBuildCommandLine^>  >> %_mainfile_%
-echo     ^<NMakePreprocessorDefinitions^>%_winver_%;NDEBUG;$(NMakePreprocessorDefinitions)^</NMakePreprocessorDefinitions^>   >> %_mainfile_%
-echo     ^<LibraryPath^>$(VC_LibraryPath_x%_platf_%);$(WindowsSDK_LibraryPath_x%_platf_%);$(VC_SourcePath);^</LibraryPath^>   >> %_mainfile_%
-echo   ^</PropertyGroup^>                                                                   >> %_mainfile_%
-echo   ^<ItemDefinitionGroup^>                                  >> %_mainfile_%
-echo   ^</ItemDefinitionGroup^>                                 >> %_mainfile_%
-
-:: create a root path with nmake files
-
-echo   ^<ItemGroup^>                                            >> %_mainfile_%
-echo       ^<Test Include="nmake.local" /^>                     >> %_mainfile_%
-echo       ^<Test Include="nmake.opt" /^>                       >> %_mainfile_%
-echo   ^</ItemGroup^>                                           >> %_mainfile_%
-
-echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
-echo       ^<Test Include="nmake.local" /^>                     >> %_ftrlfile_%
-echo       ^<Test Include="nmake.opt" /^>                       >> %_ftrlfile_%
-echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
-
-:: create filters only
-
-echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
-call :create_filter . "*.vc;" 1 "Make Files" "None"
-call :create_filter . "*.h;*.hpp" 1 "Include Files" "ClInclude"
-call :create_filter . "*.c;*.cpp" 1 "Source Files" "ClCompile"
-echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
-
-:: create main file and links to filters
-
-echo   ^<ItemGroup^>                                            >> %_mainfile_%
-echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
-call :create_filter . "*.vc" 0 "Make Files" "None"
-echo   ^</ItemGroup^>                                           >> %_mainfile_%
-echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
-
-echo   ^<ItemGroup^>                                            >> %_mainfile_%
-echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
-call :create_filter . "*.h;*.hpp" 0 "Include Files" "ClInclude"
-echo   ^</ItemGroup^>                                           >> %_mainfile_%
-echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
-
-echo   ^<ItemGroup^>                                            >> %_mainfile_%
-echo   ^<ItemGroup^>                                            >> %_ftrlfile_%
-call :create_filter . "*.c;*.cpp" 0 "Source Files" "ClCompile"
-echo   ^</ItemGroup^>                                           >> %_mainfile_%
-echo   ^</ItemGroup^>                                           >> %_ftrlfile_%
-
-:: **********************************************
-:: Finalize projects 
-:: **********************************************
-
-echo ^</Project^>                                               >> %_ftrlfile_%
-
-echo   ^<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/^>  >> %_mainfile_%
-echo ^</Project^>                                               >> %_mainfile_%
-
-echo Done!
-echo Edit nmake.local or nmake.opt:
-echo MSVCVER=%_clver_%
-if "%_platf_%"=="64" (
-    echo WIN64=YES
-) else (
-    echo #WIN64=YES
-)
-
-:: **********************************************
-:: The end
-:: **********************************************
-
-goto :end
-
-:: **********************************************
-:create_filter
-:: **********************************************
-
-    set _path_=%1
-    set _mask_=%2
-    set _fonly_=%3
-    set _name_=%4
-    set _item_=%5
-    
-    ::  *********************
-    ::  Remove quotes 
-    ::  *********************
-    
-    set _name_=%_name_:"=%
-    set _mask_=%_mask_:"=% 
-    set _fonly_=%_fonly_:"=%
-    set _item_=%_item_:"=%
-  
-    ::  *********************
-    ::  Stop folders
-    ::  *********************
-    
-    set _folder_=%~nx1
-  
-    for %%d in (data debian docs html m4 pymod swig bridge vb6) do (
-        if "%_folder_%"=="%%d" (
-            goto :end
-        )
-    )
-
-    ::  *********************
-    ::  Check if a folde is empty
-    ::  *********************
-
-    set _find_=1
-    
-    for /R %%f in (%_mask_%) do (
-      goto :not_empty
-    )
-
-    set _find_=0
-  
-    :not_empty
-  
-    if %_find_%==0 (
-        goto :end
-    )
-
-    ::  *********************
-    ::  Add filters 
-    ::  *********************
-    
-    if %_fonly_%==1 (
-        echo     ^<Filter Include="%_name_%"^>                   >> %_ftrlfile_%
-        echo       ^<Extensions^>%_mask_%^</Extensions^>         >> %_ftrlfile_%
-        echo     ^</Filter^>                                     >> %_ftrlfile_%
-    )
-  
-    ::  *********************
-    ::  Add files
-    ::  *********************
-    
-    if %_fonly_%==0 (
-        for %%f in (%_mask_%) do (
-            echo     ^<%_item_% Include="%_path_%\%%f"/^>        >> %_mainfile_%
-            echo     ^<%_item_% Include="%_path_%\%%f"^>         >> %_ftrlfile_%
-            echo       ^<Filter^>%_name_%^</Filter^>             >> %_ftrlfile_%
-            echo     ^</%_item_%^>                               >> %_ftrlfile_% 
-        )
-    )
-  
-    ::  *********************
-    ::  Clib all the branches recursivelly
-    ::  *********************
-    
-    for /D %%d in (*) do (
-        cd %%d
-        call :create_filter %_path_%\%%d "%_mask_%" %_fonly_% "%_name_%\%%d" %_item_%
-        cd ..
-    )
-    
-:: **********************************************
-:end
-:: **********************************************
diff --git a/man/man1/gdal-config.1 b/man/man1/gdal-config.1
index c02263b..4bd3ece 100644
--- a/man/man1/gdal-config.1
+++ b/man/man1/gdal-config.1
@@ -1,9 +1,8 @@
-.TH "gdal-config" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal-config" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal-config \- gdal-config 
-determines various information about a GDAL installation
+gdal-config \- Determines various information about a GDAL installation\&.
 .SH "SYNOPSIS"
 .PP
 .PP
diff --git a/man/man1/gdal2tiles.1 b/man/man1/gdal2tiles.1
index edbd4fe..cd745cc 100644
--- a/man/man1/gdal2tiles.1
+++ b/man/man1/gdal2tiles.1
@@ -1,9 +1,8 @@
-.TH "gdal2tiles" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal2tiles" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal2tiles \- gdal2tiles\&.py 
-generates directory with TMS tiles, KMLs and simple web viewers
+gdal2tiles \- Generates directory with TMS tiles, KMLs and simple web viewers\&.
 .SH "SYNOPSIS"
 .PP
 .PP
diff --git a/man/man1/gdal_calc.1 b/man/man1/gdal_calc.1
index aeefc6a..14813ce 100644
--- a/man/man1/gdal_calc.1
+++ b/man/man1/gdal_calc.1
@@ -1,37 +1,35 @@
-.TH "gdal_calc" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_calc" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_calc \- gdal_calc\&.py 
-Command line raster calculator with numpy syntax
+gdal_calc \- Command line raster calculator with numpy syntax\&.
 .SH "SYNOPSIS"
 .PP
 .PP
 .nf
-gdal_calc.py [-A <filename>] [--A_band] [-B...-Z filename] [other_options]
+gdal_calc.py --calc=expression --outfile=out_filename [-A filename]
+             [--A_band=n] [-B...-Z filename] [other_options]
 
 Options:
   -h, --help            show this help message and exit
-  --calc=CALC           calculation in gdalnumeric syntax using +-/* or any
-                        numpy array functions (i.e. logical_and())
-  -A A                  input gdal raster file, note you can use any letter
-                        A-Z
-  --A_band=A_BAND       number of raster band for file A (default 1)
-  --outfile=OUTF        output file to generate or fill
-  --NoDataValue=NODATAVALUE
-                        set output nodata value (Defaults to datatype specific
-                        value)
-  --type=TYPE           output datatype, must be one of ['Int32', 'Int16',
+  --calc=expression     calculation in gdalnumeric syntax using +-/* or any
+                        numpy array functions (i.e. log10())
+  -A filename           input gdal raster file, you can use any letter (A-Z)
+  --A_band=n            number of raster band for file A (default 1)
+  --outfile=filename    output file to generate or fill
+  --NoDataValue=value   output nodata value (default datatype specific value)
+  --type=datatype       output datatype, must be one of ['Int32', 'Int16',
                         'Float64', 'UInt16', 'Byte', 'UInt32', 'Float32']
-  --format=FORMAT       GDAL format for output file (default 'GTiff')
-  --creation-option=CREATION_OPTIONS, --co=CREATION_OPTIONS
+  --format=gdal_format  GDAL format for output file (default 'GTiff')
+  --creation-option=option, --co=option
                         Passes a creation option to the output format driver.
                         Multiple options may be listed. See format specific
                         documentation for legal creation options for each
                         format.
-  --allBands=ALLBANDS   process all bands of given raster (A-Z)
+  --allBands=[A-Z]      process all bands of given raster (A-Z)
   --overwrite           overwrite output file if it already exists
   --debug               print debugging information
+  --quiet               suppress progress messages
 .fi
 .PP
 .SH "DESCRIPTION"
@@ -64,4 +62,4 @@ gdal_calc.py -A input.tif --outfile=result.tif --calc="A*(A>0)" --NoDataValue=0
 .PP
 .SH "AUTHORS"
 .PP
-Chris Yesson <chris dot='' yesson='' at='' ioz='' dot='' ac='' dot='' uk>=''> Etienne Tourigny <etourigny dot='' dev='' at='' gmail='' dot='' com>=''> 
+Chris Yesson <chris dot yesson at ioz dot ac dot uk> Etienne Tourigny <etourigny dot dev at gmail dot com> 
diff --git a/man/man1/gdal_contour.1 b/man/man1/gdal_contour.1
index fd146b3..df968bd 100644
--- a/man/man1/gdal_contour.1
+++ b/man/man1/gdal_contour.1
@@ -1,9 +1,8 @@
-.TH "gdal_contour" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_contour" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_contour \- gdal_contour 
-builds vector contour lines from a raster elevation model
+gdal_contour \- Builds vector contour lines from a raster elevation model\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -13,7 +12,7 @@ Usage: gdal_contour [-b <band>] [-a <attribute_name>] [-3d] [-inodata]
                     [-f <formatname>] [[-dsco NAME=VALUE] ...] [[-lco NAME=VALUE] ...]
                     [-off <offset>] [-fl <level> <level>...]
                     [-nln <outlayername>]
-                    <src_filename> <dst_filename> 
+                    <src_filename> <dst_filename>
 .fi
 .PP
 .SH "DESCRIPTION"
diff --git a/man/man1/gdal_edit.1 b/man/man1/gdal_edit.1
index 3635a54..950bf3d 100644
--- a/man/man1/gdal_edit.1
+++ b/man/man1/gdal_edit.1
@@ -1,9 +1,8 @@
-.TH "gdal_edit" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_edit" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_edit \- gdal_edit\&.py 
-Edit in place various information of an existing GDAL dataset
+gdal_edit \- Edit in place various information of an existing GDAL dataset\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -11,6 +10,7 @@ Edit in place various information of an existing GDAL dataset
 gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]
           [-tr xres yres] [-unsetgt] [-a_nodata value] [-unsetnodata]
           [-unsetstats] [-stats] [-approx_stats]
+          [-scale value] [-offset value]
           [-gcp pixel line easting northing [elevation]]*
           [-unsetmd] [-oo NAME=VALUE]* [-mo "META-TAG=VALUE"]*  datasetname
 .fi
@@ -19,7 +19,10 @@ gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]
 .PP
 The gdal_edit\&.py script can be used to edit in place various information of an existing GDAL dataset (projection, geotransform, nodata, metadata)\&.
 .PP
-It works only with raster formats that support update access to existing datasets\&. 
+It works only with raster formats that support update access to existing datasets\&.
+.PP
+CAUTION: depending on the format, older values of the updated information might still be found in the file in a 'ghost' state, even if no longer accessible through the GDAL API\&. This is for example the case of the GTiff format (this is not a exhaustive list)
+.PP
 .IP "\fB\fB--help-general\fP:\fP" 1c
 Gives a brief usage message for the generic GDAL commandline options and exit\&. 
 .PP
@@ -28,7 +31,7 @@ Gives a brief usage message for the generic GDAL commandline options and exit\&.
 .PP
 .IP "\fB\fB-a_srs\fP \fIsrs_def\fP:\fP" 1c
 .PP
-Defines the target coordinate system\&. This coordinate system will be written to the dataset\&.
+Defines the target coordinate system\&. This coordinate system will be written to the dataset\&. If the empty string or None is specified, then the existing coordinate system will be removed (for TIFF/GeoTIFF, might not be well supported besides that)\&.
 .PP
 .IP "\fB\fB-a_ullr\fP \fIulx uly lrx lry\fP:\fP" 1c
 Assign/override the georeferenced bounds of the dataset\&.
@@ -54,6 +57,12 @@ Assign a specified nodata value to output bands\&.
 .IP "\fB\fB-unsetnodata\fP:\fP" 1c
 (GDAL >= 2\&.1) Remove existing nodata values\&.
 .PP
+.IP "\fB\fB-scale\fP \fIvalue\fP:\fP" 1c
+(GDAL >= 2\&.2) Assign a specified scale value to output bands\&. If no scale is needed, it it recommended to set the value to 1\&. Scale and Offset are generally used together\&. For example, scale and offset might be used to store elevations in a unsigned 16bit integer file with a precision of 0\&.1, and starting from -100\&. True values would be calculated as: true_value = (pixel_value * scale) + offset Note: these values can be applied using -unscale during a gdal_translate run\&.
+.PP
+.IP "\fB\fB-offset\fP \fIvalue\fP:\fP" 1c
+(GDAL >= 2\&.2) Assign a specified offset value to output bands\&. If no offset is needed, it recommended to set the value to 0\&. For more see scale\&.
+.PP
 .IP "\fB\fB-gcp\fP \fIpixel line easting northing [elevation]\fP:\fP" 1c
 Add the indicated ground control point to the dataset\&. This option may be provided multiple times to provide a set of GCPs\&. 
 .PP
@@ -80,4 +89,4 @@ gdal_edit -mo DATUM=WGS84 -mo PROJ=GEODETIC -a_ullr 7 47 8 46 test.ecw
 .PP
 .SH "AUTHORS"
 .PP
-Even Rouault <even dot='' rouault='' at='' mines='' dash='' paris='' dot='' org>=''> 
+Even Rouault <even dot rouault at mines dash paris dot org> 
diff --git a/man/man1/gdal_fillnodata.1 b/man/man1/gdal_fillnodata.1
index b1b55d3..ae9d423 100644
--- a/man/man1/gdal_fillnodata.1
+++ b/man/man1/gdal_fillnodata.1
@@ -1,9 +1,8 @@
-.TH "gdal_fillnodata" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_fillnodata" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_fillnodata \- gdal_fillnodata\&.py 
-fill raster regions by interpolation from edges
+gdal_fillnodata \- Fill raster regions by interpolation from edges\&.
 .SH "SYNOPSIS"
 .PP
 .PP
diff --git a/man/man1/gdal_grid.1 b/man/man1/gdal_grid.1
index 32e0d74..b54d759 100644
--- a/man/man1/gdal_grid.1
+++ b/man/man1/gdal_grid.1
@@ -1,9 +1,8 @@
-.TH "gdal_grid" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_grid" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_grid \- gdal_grid 
-creates regular grid from the scattered data
+gdal_grid \- Creates regular grid from the scattered data\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -83,7 +82,7 @@ An optional SQL WHERE style query expression to be applied to select features to
 An SQL statement to be evaluated against the datasource to produce a virtual layer of features to be processed\&.
 .PP
 .IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
-Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&.
+Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See \fCformat specific documentation for legal creation options for each format\fP\&.
 .PP
 .IP "\fB\fB-q\fP:\fP" 1c
 Suppress progress monitor and other non-error output\&.
@@ -123,6 +122,8 @@ NODATA marker to fill empty points (default 0\&.0)\&.
 .PP
 .IP "\fB\fIpower\fP: \fP" 1c
 Weighting power (default 2\&.0)\&. 
+.IP "\fB\fIsmoothing\fP: \fP" 1c
+Smoothing parameter (default 0\&.0)\&. 
 .IP "\fB\fIradius\fP: \fP" 1c
 The radius of the search circle, which should be non-zero\&. Default is 1\&.0\&. 
 .IP "\fB\fImax_points\fP: \fP" 1c
@@ -233,9 +234,9 @@ For above data we will create \fIdem\&.vrt\fP header with the following content:
 .nf
 <OGRVRTDataSource>
     <OGRVRTLayer name="dem">
-        <SrcDataSource>dem.csv</SrcDataSource> 
-        <GeometryType>wkbPoint</GeometryType> 
-        <GeometryField encoding="PointFromColumns" x="Easting" y="Northing" z="Elevation"/> 
+        <SrcDataSource>dem.csv</SrcDataSource>
+        <GeometryType>wkbPoint</GeometryType>
+        <GeometryField encoding="PointFromColumns" x="Easting" y="Northing" z="Elevation"/>
     </OGRVRTLayer>
 </OGRVRTDataSource>
 .fi
diff --git a/man/man1/gdal_merge.1 b/man/man1/gdal_merge.1
index 8d1c005..c6f150e 100644
--- a/man/man1/gdal_merge.1
+++ b/man/man1/gdal_merge.1
@@ -1,9 +1,8 @@
-.TH "gdal_merge" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_merge" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_merge \- gdal_merge\&.py 
-mosaics a set of images
+gdal_merge \- Mosaics a set of images\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -24,7 +23,7 @@ The name of the output file, which will be created if it does not already exist
 .IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
 Output format, defaults to GeoTIFF (GTiff)\&.  
 .IP "\fB\fB-co\fP \fINAME=VALUE\fP:\fP" 1c
-Creation option for output file\&. Multiple options can be specified\&.  
+Creation option for output file\&. Multiple options can be specified\&. See \fCformat specific documentation for legal creation options for each format\fP  
 .IP "\fB\fB-ot\fP \fIdatatype\fP:\fP" 1c
 Force the output image bands to have a specific type\&. Use type names (i\&.e\&. Byte, Int16,\&.\&.\&.)  
 .IP "\fB\fB-ps\fP \fIpixelsize_x pixelsize_y\fP:\fP" 1c
diff --git a/man/man1/gdal_pansharpen.1 b/man/man1/gdal_pansharpen.1
index 38dfaa3..97ed076 100644
--- a/man/man1/gdal_pansharpen.1
+++ b/man/man1/gdal_pansharpen.1
@@ -1,9 +1,8 @@
-.TH "gdal_pansharpen" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_pansharpen" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_pansharpen \- gdal_pansharpen\&.py 
-Perform a pansharpen operation\&.
+gdal_pansharpen \- Perform a pansharpen operation\&.
 .PP
 (Since GDAL 2\&.1)
 .SH "SYNOPSIS"
@@ -41,7 +40,7 @@ Specify nodata value for bands\&. Used for the resampling and pan-sharpening com
 .IP "\fB\fB-spat_adjust\fP \fI{union (default),intersection,none,nonewithoutwarning}\fP:\fP" 1c
 Select behaviour when bands have not the same extent\&. See \fISpatialExtentAdjustment\fP documentation in \fCVRT tutorial\fP 
 .IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
-Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&. 
+Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See \fCformat specific documentation for legal creation options for each format\fP\&. 
 .IP "\fB\fB-q\fP:\fP" 1c
 Suppress progress monitor and other non-error output\&. 
 .IP "\fB\fIpan_dataset\fP\fP" 1c
diff --git a/man/man1/gdal_polygonize.1 b/man/man1/gdal_polygonize.1
index 7a6f243..e32af86 100644
--- a/man/man1/gdal_polygonize.1
+++ b/man/man1/gdal_polygonize.1
@@ -1,9 +1,8 @@
-.TH "gdal_polygonize" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_polygonize" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_polygonize \- gdal_polygonize\&.py 
-produces a polygon feature layer from a raster
+gdal_polygonize \- Produces a polygon feature layer from a raster\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -27,13 +26,13 @@ The utility is based on the GDALPolygonize() function which has additional detai
 Do not use the default validity mask for the input band (such as nodata, or alpha masks)\&. 
 .PP
 .IP "\fB\fB-mask\fP \fIfilename\fP:\fP" 1c
-Use the first band of the specified file as a validity mask (zero is invalid, non-zero is valid)\&. 
+Use the first band of the specified file as a validity mask (zero is invalid, non-zero is valid)\&. If not specified, the default validity mask for the input band (such as nodata, or alpha masks) will be used (unless -nomask is specified) 
 .PP
 .IP "\fB\fIraster_file\fP\fP" 1c
 The source raster file from which polygons are derived\&.
 .PP
 .IP "\fB\fB-b\fP \fIband\fP: \fP" 1c
-The band on \fIraster_file\fP to build the polygons from\&. 
+The band on \fIraster_file\fP to build the polygons from\&. Starting with GDAL 2\&.2, the value can also be set to 'mask', to indicate that the mask band of the first band must be used (or 'mask,band_number' for the mask of a specified band) 
 .PP
 .IP "\fB\fB-f\fP \fIogr_format\fP\fP" 1c
 Select the output format of the file to be created\&. Default is GML\&. 
diff --git a/man/man1/gdal_proximity.1 b/man/man1/gdal_proximity.1
index 9b361aa..7ce8fe7 100644
--- a/man/man1/gdal_proximity.1
+++ b/man/man1/gdal_proximity.1
@@ -1,19 +1,18 @@
-.TH "gdal_proximity" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_proximity" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_proximity \- gdal_proximity\&.py 
-produces a raster proximity map
+gdal_proximity \- Produces a raster proximity map\&.
 .SH "SYNOPSIS"
 .PP
 .PP
 .nf
-gdal_proximity.py srcfile dstfile [-srcband n] [-dstband n] 
+gdal_proximity.py srcfile dstfile [-srcband n] [-dstband n]
                   [-of format] [-co name=value]*
                   [-ot Byte/Int16/Int32/Float32/etc]
                   [-values n,n,n] [-distunits PIXEL/GEO]
                   [-maxdist n] [-nodata n] [-use_input_nodata YES/NO]
-                  [-fixed-buf-val n] 
+                  [-fixed-buf-val n]
 .fi
 .PP
 .SH "DESCRIPTION"
diff --git a/man/man1/gdal_rasterize.1 b/man/man1/gdal_rasterize.1
index 0a35cab..1fdecb3 100644
--- a/man/man1/gdal_rasterize.1
+++ b/man/man1/gdal_rasterize.1
@@ -1,15 +1,14 @@
-.TH "gdal_rasterize" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_rasterize" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_rasterize \- gdal_rasterize 
-burns vector geometries into a raster
+gdal_rasterize \- Burns vector geometries into a raster\&.
 .SH "SYNOPSIS"
 .PP
 .PP
 .nf
 Usage: gdal_rasterize [-b band]* [-i] [-at]
-       [-burn value]* | [-a attribute_name] [-3d]
+       {[-burn value]* | [-a attribute_name] | [-3d]} [-add]
        [-l layername]* [-where expression] [-sql select_statement]
        [-dialect dialect] [-of format] [-a_srs srs_def]
        [-co "NAME=VALUE"]* [-a_nodata value] [-init value]*
@@ -31,7 +30,7 @@ Since GDAL 1\&.8\&.0, the target GDAL file can be created by gdal_rasterize\&. E
 The band(s) to burn values into\&. Multiple -b arguments may be used to burn into a list of bands\&. The default is to burn into band 1\&.
 .PP
 .IP "\fB\fB-i\fP: \fP" 1c
-Invert rasterization\&. Burn the fixed burn value, or the burn value associated with the first feature into all parts of the image \fInot\fP inside the provided a polygon\&.
+Invert rasterization\&. Burn the fixed burn value, or the burn value associated with the first feature into all parts of the image \fInot\fP inside the provided polygon\&.
 .PP
 .IP "\fB\fB-at\fP: \fP" 1c
 Enables the ALL_TOUCHED rasterization option so that all pixels touched by lines or polygons will be updated, not just those on the line render path, or whose center point is within the polygon\&. Defaults to disabled for normal rendering rules\&.
@@ -43,7 +42,10 @@ A fixed value to burn into a band for all objects\&. A list of -burn options can
 Identifies an attribute field on the features to be used for a burn-in value\&. The value will be burned into all output bands\&.
 .PP
 .IP "\fB\fB-3d\fP: \fP" 1c
-Indicates that a burn value should be extracted from the 'Z' values of the feature\&. These values are added to the burn value given by '-burn value' or '-a attribute_name' if provided\&. As of now, only points and lines are drawn in 3D\&.
+Indicates that a burn value should be extracted from the 'Z' values of the feature\&. As of now, only points and lines are drawn in 3D\&.
+.PP
+.IP "\fB\fB-add\fP: \fP" 1c
+Instead of burning a new value, this adds the new value to the existing raster\&. Suitable for heatmaps for instance\&.
 .PP
 .IP "\fB\fB-l\fP \fIlayername\fP: \fP" 1c
 Indicates the layer(s) from the datasource that will be used for input features\&. May be specified multiple times, but at least one layer name or a -sql option must be specified\&.
@@ -70,7 +72,7 @@ An SQL statement to be evaluated against the datasource to produce a virtual lay
 (GDAL >= 1\&.8\&.0) Override the projection for the output file\&. If not specified, the projection of the input vector file will be used if available\&. If incompatible projections between input and output files, no attempt will be made to reproject features\&. The \fIsrs_def\fP may be any of the usual GDAL/OGR forms, complete WKT, PROJ\&.4, EPSG:n or a file containing the WKT\&. 
 .PP
 .IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
-(GDAL >= 1\&.8\&.0) Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&.
+(GDAL >= 1\&.8\&.0) Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See \fCformat specific documentation for legal creation options for each format\fP\&.
 .PP
 .IP "\fB\fB-te\fP \fIxmin ymin xmax ymax\fP :\fP" 1c
 (GDAL >= 1\&.8\&.0) Set georeferenced extents\&. The values must be expressed in georeferenced units\&. If not specified, the extent of the output file will be the extent of the vector layers\&. 
diff --git a/man/man1/gdal_retile.1 b/man/man1/gdal_retile.1
index 3f7ff02..b95c701 100644
--- a/man/man1/gdal_retile.1
+++ b/man/man1/gdal_retile.1
@@ -1,15 +1,15 @@
-.TH "gdal_retile" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_retile" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_retile \- gdal_retile\&.py 
-gdal_retile\&.py retiles a set of tiles and/or build tiled pyramid levels
+gdal_retile \- Retiles a set of tiles and/or build tiled pyramid levels\&.
 .SH "SYNOPSIS"
 .PP
 .PP
 .PP
 .nf
 gdal_retile.py [-v] [-co NAME=VALUE]* [-of out_format] [-ps pixelWidth pixelHeight]
+               [-overlap val_in_pixel]
                [-ot  {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/
                       CInt16/CInt32/CFloat32/CFloat64}]'
                [ -tileIndex tileIndexName [-tileIndexField tileIndexFieldName]]
@@ -17,7 +17,7 @@ gdal_retile.py [-v] [-co NAME=VALUE]* [-of out_format] [-ps pixelWidth pixelHeig
                [-s_srs srs_def]  [-pyramidOnly]
                [-r {near/bilinear/cubic/cubicspline/lanczos}]
                -levels numberoflevels
-               [-useDirForEachRow]   
+               [-useDirForEachRow]
                -targetDir TileDirectory input_files.fi
 .PP
  
@@ -32,11 +32,13 @@ The directory where the tile result is created\&. Pyramids are stored in sub-dir
 .IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
 Output format, defaults to GeoTIFF (GTiff)\&.  
 .IP "\fB\fB-co\fP \fINAME=VALUE\fP:\fP" 1c
-Creation option for output file\&. Multiple options can be specified\&.  
+Creation option for output file\&. Multiple options can be specified\&. See \fCformat specific documentation for legal creation options for each format\fP  
 .IP "\fB\fB-ot\fP \fIdatatype\fP:\fP" 1c
 Force the output image bands to have a specific type\&. Use type names (i\&.e\&. Byte, Int16,\&.\&.\&.)  
 .IP "\fB\fB-ps\fP \fIpixelsize_x pixelsize_y\fP:\fP" 1c
 Pixel size to be used for the output file\&. If not specified, 256 x 256 is the default  
+.IP "\fB\fB-overlap\fP \fIval_in_pixel\fP:\fP" 1c
+(GDAL >= 2\&.2) Overlap in pixels between consecutive tiles\&. If not specified, 0 is the default  
 .IP "\fB\fB-levels\fP \fInumberOfLevels\fP:\fP" 1c
 Number of pyramids levels to build\&.  
 .IP "\fB\fB-v\fP:\fP" 1c
diff --git a/man/man1/gdal_sieve.1 b/man/man1/gdal_sieve.1
index 5f150e1..ccaed58 100644
--- a/man/man1/gdal_sieve.1
+++ b/man/man1/gdal_sieve.1
@@ -1,9 +1,8 @@
-.TH "gdal_sieve" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_sieve" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_sieve \- gdal_sieve\&.py 
-removes small raster polygons
+gdal_sieve \- Removes small raster polygons\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -16,6 +15,8 @@ gdal_sieve.py [-q] [-st threshold] [-4] [-8] [-o name=value]
 .PP
 The gdal_sieve\&.py script removes raster polygons smaller than a provided threshold size (in pixels) and replaces replaces them with the pixel value of the largest neighbour polygon\&. The result can be written back to the existing raster band, or copied into a new file\&.
 .PP
+The input dataset is read as integer data which means that floating point values are rounded to integers\&. Re-scaling source data may be necessary in some cases (e\&.g\&. 32-bit floating point data with min=0 and max=1)\&.
+.PP
 Additional details on the algorithm are available in the GDALSieveFilter() docs\&.
 .PP
 .IP "\fB\fB-q\fP:\fP" 1c
diff --git a/man/man1/gdal_translate.1 b/man/man1/gdal_translate.1
index 6cbd942..ea2e4ac 100644
--- a/man/man1/gdal_translate.1
+++ b/man/man1/gdal_translate.1
@@ -1,9 +1,8 @@
-.TH "gdal_translate" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_translate" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdal_translate \- gdal_translate 
-converts raster data between different formats
+gdal_translate \- Converts raster data between different formats\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -44,7 +43,7 @@ Select an input band \fIband\fP for output\&. Bands are numbered from 1\&. Multi
 .IP "\fB\fB-outsize\fP \fIxsize[%]|0 ysize[%]|0\fP:\fP" 1c
 Set the size of the output file\&. Outsize is in pixels and lines unless '%' is attached in which case it is as a fraction of the input image size\&. Starting with GDAL 2\&.0, if one of the 2 values is set to 0, its value will be determined from the other one, while maintaining the aspect ratio of the source dataset\&. 
 .IP "\fB\fB-tr\fP xres yres :\fP" 1c
-(starting with GDAL 2\&.0) set target resolution\&. The values must be expressed in georeferenced units\&. Both must be positive values\&. This is exclusive with -outsize and -a_ullr\&.  
+(starting with GDAL 2\&.0) set target resolution\&. The values must be expressed in georeferenced units\&. Both must be positive values\&. This is mutually exclusive with -outsize and -a_ullr\&.  
 .IP "\fB\fB-r\fP \fI{nearest (default),bilinear,cubic,cubicspline,lanczos,average,mode}\fP:\fP" 1c
 (GDAL >= 2\&.0) Select a resampling algorithm\&. 
 .IP "\fB\fB-scale\fP \fI[src_min src_max [dst_min dst_max]]\fP:\fP" 1c
@@ -56,7 +55,7 @@ Apply the scale/offset metadata for the bands to convert scaled values to unscal
 .IP "\fB\fB-srcwin\fP \fIxoff yoff xsize ysize\fP:\fP" 1c
 Selects a subwindow from the source image for copying based on pixel/line location\&.  
 .IP "\fB\fB-projwin\fP \fIulx uly lrx lry\fP:\fP" 1c
-Selects a subwindow from the source image for copying (like \fB-srcwin\fP) but with the corners given in georeferenced coordinates (by default expressed in the SRS of the dataset\&. Can be changed with -projwin_srs)\&. Note: in GDAL 2\&.1\&.0 and 2\&.1\&.1, using -projwin with coordinates not aligned with pixels will result in a sub-pixel shift\&. This has been corrected in later versions\&. When selecting non-nearest neighbour resampling, starting with GDAL 2\&.1\&.0, sub-pixel accuracy [...]
+Selects a subwindow from the source image for copying (like \fB-srcwin\fP) but with the corners given in georeferenced coordinates (by default expressed in the SRS of the dataset\&. Can be changed with -projwin_srs)\&. Note: in GDAL 2\&.1\&.0 and 2\&.1\&.1, using -projwin with coordinates not aligned with pixels will result in a sub-pixel shift\&. This has been corrected in later versions\&. When selecting non-nearest neighbour resampling, starting with GDAL 2\&.1\&.0, sub-pixel accuracy [...]
 .IP "\fB\fB-projwin_srs\fP \fIsrs_def\fP:\fP" 1c
 (GDAL >= 2\&.0) Specifies the SRS in which to interpret the coordinates given with -projwin\&. The \fIsrs_def\fP may be any of the usual GDAL/OGR forms, complete WKT, PROJ\&.4, EPSG:n or a file containing the WKT\&. Note that this does not cause reprojection of the dataset to the specified SRS\&.  
 .IP "\fB\fB-epo\fP: (Error when Partially Outside)\fP" 1c
@@ -72,7 +71,7 @@ Assign a specified nodata value to output bands\&. Starting with GDAL 1\&.8\&.0,
 .IP "\fB\fB-mo\fP \fI'META-TAG=VALUE'\fP:\fP" 1c
 Passes a metadata key and value to set on the output dataset if possible\&. 
 .IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
-Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&. 
+Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See \fCformat specific documentation for legal creation options for each format\fP\&. 
 .IP "\fB\fB-gcp\fP \fIpixel line easting northing elevation\fP:\fP" 1c
 Add the indicated ground control point to the output dataset\&. This option may be provided multiple times to provide a set of GCPs\&.  
 .IP "\fB\fB-q\fP:\fP" 1c
diff --git a/man/man1/gdal_utilities.1 b/man/man1/gdal_utilities.1
index 7d038c1..9363398 100644
--- a/man/man1/gdal_utilities.1
+++ b/man/man1/gdal_utilities.1
@@ -1,4 +1,4 @@
-.TH "gdal_utilities" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdal_utilities" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -9,7 +9,7 @@ The following utility programs are distributed with GDAL\&.
 .PP
 .PD 0
 .IP "\(bu" 2
-\fBgdalinfo\fP - report information about a file\&. 
+\fBgdalinfo\fP - Report information about a file\&. 
 .IP "\(bu" 2
 \fBgdal_translate\fP - Copy a raster file, with control of output format\&. 
 .IP "\(bu" 2
@@ -25,13 +25,13 @@ The following utility programs are distributed with GDAL\&.
 .IP "\(bu" 2
 \fBgdaldem\fP - Tools to analyze and visualize DEMs\&. 
 .IP "\(bu" 2
-\fBrgb2pct\&.py\fP - Convert a 24bit RGB image to 8bit paletted\&. 
+\fBrgb2pct\fP - Convert a 24bit RGB image to 8bit paletted\&. 
 .IP "\(bu" 2
-\fBpct2rgb\&.py\fP - Convert an 8bit paletted image to 24bit RGB\&. 
+\fBpct2rgb\fP - Convert an 8bit paletted image to 24bit RGB\&. 
 .IP "\(bu" 2
-\fBgdal_merge\&.py\fP - Build a quick mosaic from a set of images\&. 
+\fBgdal_merge\fP - Build a quick mosaic from a set of images\&. 
 .IP "\(bu" 2
-\fBgdal2tiles\&.py\fP - Create a TMS tile structure, KML and simple web viewer\&. 
+\fBgdal2tiles\fP - Create a TMS tile structure, KML and simple web viewer\&. 
 .IP "\(bu" 2
 \fBgdal_rasterize\fP - Rasterize vectors into raster file\&. 
 .IP "\(bu" 2
@@ -39,35 +39,35 @@ The following utility programs are distributed with GDAL\&.
 .IP "\(bu" 2
 \fBnearblack\fP - Convert nearly black/white borders to exact value\&. 
 .IP "\(bu" 2
-\fBgdal_retile\&.py\fP - Retiles a set of tiles and/or build tiled pyramid levels\&. 
+\fBgdal_retile\fP - Retiles a set of tiles and/or build tiled pyramid levels\&. 
 .IP "\(bu" 2
 \fBgdal_grid\fP - Create raster from the scattered data\&. 
 .IP "\(bu" 2
-\fBgdal_proximity\&.py\fP - Compute a raster proximity map\&. 
+\fBgdal_proximity\fP - Compute a raster proximity map\&. 
 .IP "\(bu" 2
-\fBgdal_polygonize\&.py\fP - Generate polygons from raster\&. 
+\fBgdal_polygonize\fP - Generate polygons from raster\&. 
 .IP "\(bu" 2
-\fBgdal_sieve\&.py\fP - Raster Sieve filter\&. 
+\fBgdal_sieve\fP - Raster Sieve filter\&. 
 .IP "\(bu" 2
-\fBgdal_fillnodata\&.py\fP - Interpolate in nodata regions\&. 
+\fBgdal_fillnodata\fP - Interpolate in nodata regions\&. 
 .IP "\(bu" 2
 \fBgdallocationinfo\fP - Query raster at a location\&. 
 .IP "\(bu" 2
 \fBgdalsrsinfo\fP - Report a given SRS in different formats\&. (GDAL >= 1\&.9\&.0) 
 .IP "\(bu" 2
-\fBgdalmove\&.py\fP - Transform the coordinate system of a file (GDAL >= 1\&.10) 
+\fBgdalmove\fP - Transform the coordinate system of a file (GDAL >= 1\&.10) 
 .IP "\(bu" 2
-\fBgdal_edit\&.py\fP - Edit in place various information of an existing GDAL dataset (projection, geotransform, nodata, metadata) 
+\fBgdal_edit\fP - Edit in place various information of an existing GDAL dataset (projection, geotransform, nodata, metadata) 
 .IP "\(bu" 2
-\fBgdal_calc\&.py\fP - Command line raster calculator with numpy syntax 
+\fBgdal_calc\fP - Command line raster calculator with numpy syntax 
 .IP "\(bu" 2
-\fBgdal_pansharpen\&.py\fP - Perform a pansharpen operation\&. 
+\fBgdal_pansharpen\fP - Perform a pansharpen operation\&. 
 .IP "\(bu" 2
 \fBgdal-config\fP - Get options required to build software using GDAL\&. 
 .IP "\(bu" 2
 \fBgdalmanage\fP - Identify, copy, rename and delete raster\&. 
 .IP "\(bu" 2
-\fBgdalcompare\&.py\fP - Compare two images and report on differences\&. 
+\fBgdalcompare\fP - Compare two images and report on differences\&. 
 .PP
 .SH "Creating New Files"
 .PP
@@ -81,7 +81,7 @@ Many utilities default to creating GeoTIFF files if a format is not specified\&.
 .IP "\fB\fB-co\fP \fINAME=VALUE\fP\fP" 1c
 Many formats have one or more optional creation options that can be used to control particulars about the file created\&. For instance, the GeoTIFF driver supports creation options to control compression, and whether the file should be tiled\&.
 .PP
-The creation options available vary by format driver, and some simple formats have no creation options at all\&. A list of options supported for a format can be listed with the '--format <format>' command line option but the web page for the format is the definitive source of information on driver creation options\&.
+The creation options available vary by format driver, and some simple formats have no creation options at all\&. A list of options supported for a format can be listed with the '--format <format>' command line option but the web page for the format is the definitive source of information on driver creation options\&. See \fCformat specific documentation for legal creation options for each format\fP
 .PP
 .PP
 .IP "\fB\fB-a_srs\fP \fISRS\fP\fP" 1c
diff --git a/man/man1/gdaladdo.1 b/man/man1/gdaladdo.1
index 761a8c6..607873d 100644
--- a/man/man1/gdaladdo.1
+++ b/man/man1/gdaladdo.1
@@ -1,9 +1,8 @@
-.TH "gdaladdo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdaladdo" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaladdo \- gdaladdo 
-builds or rebuilds overview images
+gdaladdo \- Builds or rebuilds overview images\&.
 .SH "SYNOPSIS"
 .PP
 .PP
diff --git a/man/man1/gdalbuildvrt.1 b/man/man1/gdalbuildvrt.1
index 48f426c..1499a47 100644
--- a/man/man1/gdalbuildvrt.1
+++ b/man/man1/gdalbuildvrt.1
@@ -1,9 +1,8 @@
-.TH "gdalbuildvrt" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalbuildvrt" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalbuildvrt \- gdalbuildvrt 
-Builds a VRT from a list of datasets\&. (compiled by default since GDAL 1\&.6\&.1)
+gdalbuildvrt \- Builds a VRT from a list of datasets\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -14,9 +13,10 @@ gdalbuildvrt [-tileindex field_name]
              [-separate] [-b band]* [-sd subdataset]
              [-allow_projection_difference] [-q]
              [-addalpha] [-hidenodata]
-             [-srcnodata "value [value...]"] [-vrtnodata "value [value...]"] 
+             [-srcnodata "value [value...]"] [-vrtnodata "value [value...]"]
              [-a_srs srs_def]
              [-r {nearest,bilinear,cubic,cubicspline,lanczos,average,mode}]
+             [-oo NAME=VALUE]*
              [-input_file_list my_list.txt] [-overwrite] output.vrt [gdalfile]*
 .fi
 .PP
@@ -79,6 +79,9 @@ In case the resolution of all input files is not the same, the -resolution flag
 .IP "\fB\fB-r\fP \fI{nearest (default),bilinear,cubic,cubicspline,lanczos,average,mode}\fP:\fP" 1c
 (GDAL >= 2\&.0) Select a resampling algorithm\&.
 .PP
+.IP "\fB\fB-oo\fP \fINAME=VALUE\fP:\fP" 1c
+(starting with GDAL 2\&.2) Dataset open option (format specific)
+.PP
 .IP "\fB\fB-input_file_list\fP:\fP" 1c
 To specify a text file with an input filename on each line 
 .PP
diff --git a/man/man1/gdalcompare.1 b/man/man1/gdalcompare.1
index 9a5a839..8ddb1a8 100644
--- a/man/man1/gdalcompare.1
+++ b/man/man1/gdalcompare.1
@@ -1,9 +1,8 @@
-.TH "gdalcompare" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalcompare" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalcompare \- gdalcompare\&.py 
-compare two images
+gdalcompare \- Compare two images\&.
 .SH "SYNOPSIS"
 .PP
 .PP
diff --git a/man/man1/gdaldem.1 b/man/man1/gdaldem.1
index 9c2c237..b1f8452 100644
--- a/man/man1/gdaldem.1
+++ b/man/man1/gdaldem.1
@@ -1,9 +1,8 @@
-.TH "gdaldem" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdaldem" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaldem \- gdaldem 
-Tools to analyze and visualize DEMs\&. (since GDAL 1\&.7\&.0)
+gdaldem \- Tools to analyze and visualize DEMs\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -13,7 +12,7 @@ Tools to analyze and visualize DEMs\&. (since GDAL 1\&.7\&.0)
     gdaldem hillshade input_dem output_hillshade
                 [-z ZFactor (default=1)] [-s scale* (default=1)]"
                 [-az Azimuth (default=315)] [-alt Altitude (default=45)]
-                [-alg ZevenbergenThorne] [-combined]
+                [-alg ZevenbergenThorne] [-combined | -multidirectional]
                 [-compute_edges] [-b Band (default=1)] [-of format] [-co "NAME=VALUE"]* [-q]
 
 - To generate a slope map from any GDAL-supported elevation raster :
@@ -34,15 +33,15 @@ Tools to analyze and visualize DEMs\&. (since GDAL 1\&.7\&.0)
                 [-alpha] [-exact_color_entry | -nearest_color_entry]
                 [-b Band (default=1)] [-of format] [-co "NAME=VALUE"]* [-q]
     where color_text_file contains lines of the format "elevation_value red green blue"
-    
+
 - To generate a Terrain Ruggedness Index (TRI) map from any GDAL-supported elevation raster:
     gdaldem TRI input_dem output_TRI_map
                 [-compute_edges] [-b Band (default=1)] [-of format] [-q]
-            
+
 - To generate a Topographic Position Index (TPI) map from any GDAL-supported elevation raster:
     gdaldem TPI input_dem output_TPI_map
                 [-compute_edges] [-b Band (default=1)] [-of format] [-q]
-            
+
 - To generate a roughness map from any GDAL-supported elevation raster:
     gdaldem roughness input_dem output_roughness_map
                 [-compute_edges] [-b Band (default=1)] [-of format] [-q]
@@ -50,10 +49,10 @@ Tools to analyze and visualize DEMs\&. (since GDAL 1\&.7\&.0)
 Notes :
   gdaldem generally assumes that x, y and z units are identical.  If x (east-west)
   and y (north-south) units are identical, but z (elevation) units are different, the
-  scale (-s) option can be used to set the ratio of vertical units to horizontal.  For 
-  LatLong projections near the equator, where units of latitude and units of 
+  scale (-s) option can be used to set the ratio of vertical units to horizontal.  For
+  LatLong projections near the equator, where units of latitude and units of
   longitude are similar, elevation (z) units can be converted to be compatible
-  by using scale=370400 (if elevation is in feet) or scale=111120 (if elevation is in 
+  by using scale=370400 (if elevation is in feet) or scale=111120 (if elevation is in
   meters).  For locations not near the equator, it would be best to reproject your
   grid using gdalwarp before using gdaldem..fi
 .PP
@@ -91,7 +90,7 @@ Select the output format\&. The default is GeoTIFF (GTiff)\&. Use the short form
 .IP "\fB\fB-b\fP \fIband\fP:\fP" 1c
 Select an input \fIband\fP to be processed\&. Bands are numbered from 1\&. 
 .IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
-Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&. 
+Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See \fCformat specific documentation for legal creation options for each format\fP 
 .IP "\fB\fB-q\fP:\fP" 1c
 Suppress progress monitor and other non-error output\&. 
 .PP
@@ -113,9 +112,13 @@ ratio of vertical units to horizontal\&. If the horizontal unit of the source DE
 azimuth of the light, in degrees\&. 0 if it comes from the top of the raster, 90 from the east, \&.\&.\&. The default value, 315, should rarely be changed as it is the value generally used to generate shaded maps\&. 
 .IP "\fB\fB-alt\fP \fIaltitude\fP:\fP" 1c
 altitude of the light, in degrees\&. 90 if the light comes from above the DEM, 0 if it is raking light\&. 
-.IP "\fB\fB-combined\fP \fIcombined shading\fP:\fP" 1c
-(starting with GDAL 1\&.10) a combination of slope and oblique shading\&. 
+.IP "\fB\fB-combined\fP:\fP" 1c
+(starting with GDAL 1\&.10) combined shading, a combination of slope and oblique shading\&. 
+.IP "\fB\fB-multidirectional\fP:\fP" 1c
+(starting with GDAL 2\&.2) multidirectional shading, a combination of hillshading illuminated from 225 deg, 270 deg, 315 deg, and 360 deg azimuth\&. 
+.PP
 .PP
+Multidirectional hillshading applies the formula of http://pubs.usgs.gov/of/1992/of92-422/of92-422.pdf\&.
 .SS "slope"
 This command will take a DEM raster and output a 32-bit float raster with slope values\&. You have the option of specifying the type of slope value you want: degrees or percent slope\&. In cases where the horizontal units differ from the vertical units, you can also supply a scaling factor\&.
 .PP
@@ -174,7 +177,7 @@ For example :
 50%   190 185 135
 700    240 250 150
 0      50  180  50
-nv     0   0   0   0 
+nv     0   0   0   0
 
 .fi
 .PP
diff --git a/man/man1/gdalinfo.1 b/man/man1/gdalinfo.1
index 792dcde..5c3ce47 100644
--- a/man/man1/gdalinfo.1
+++ b/man/man1/gdalinfo.1
@@ -1,9 +1,8 @@
-.TH "gdalinfo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalinfo" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalinfo \- gdalinfo 
-lists information about a raster dataset
+gdalinfo \- Lists information about a raster dataset\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -96,7 +95,7 @@ Starting with GDAL 2\&.1, this utility is also callable from C with GDALInfo()\&
 .PP
 .PP
 .nf
-gdalinfo ~/openev/utm.tif 
+gdalinfo ~/openev/utm.tif
 Driver: GTiff/GeoTIFF
 Size is 512, 512
 Coordinate System is:
diff --git a/man/man1/gdallocationinfo.1 b/man/man1/gdallocationinfo.1
index e156578..7b4f74b 100644
--- a/man/man1/gdallocationinfo.1
+++ b/man/man1/gdallocationinfo.1
@@ -1,4 +1,4 @@
-.TH "gdallocationinfo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdallocationinfo" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -17,7 +17,7 @@ Usage: gdallocationinfo [--help-general] [-xml] [-lifonly] [-valonly]
 .PP
 .SH "DESCRIPTION"
 .PP
-The gdallocationinfo utility provide a mechanism to query information about a pixel given it's location in one of a variety of coordinate systems\&. Several reporting options are provided\&.
+The gdallocationinfo utility provide a mechanism to query information about a pixel given its location in one of a variety of coordinate systems\&. Several reporting options are provided\&.
 .PP
 .IP "\fB\fB-xml\fP: \fP" 1c
 The output report will be XML formatted for convenient post processing\&.
diff --git a/man/man1/gdalmanage.1 b/man/man1/gdalmanage.1
index 5639c40..82b3984 100644
--- a/man/man1/gdalmanage.1
+++ b/man/man1/gdalmanage.1
@@ -1,9 +1,8 @@
-.TH "gdalmanage" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalmanage" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalmanage \- gdalmanage 
-Identify, delete, rename and copy raster data files
+gdalmanage \- Identify, delete, rename and copy raster data files\&.
 .SH "SYNOPSIS"
 .PP
 .PP
diff --git a/man/man1/gdalmove.1 b/man/man1/gdalmove.1
index 7c77b1f..733ad5d 100644
--- a/man/man1/gdalmove.1
+++ b/man/man1/gdalmove.1
@@ -1,9 +1,8 @@
-.TH "gdalmove" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalmove" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalmove \- gdalmove\&.py 
-Transform georeferencing of raster file in place
+gdalmove \- Transform georeferencing of raster file in place\&.
 .SH "SYNOPSIS"
 .PP
 .PP
diff --git a/man/man1/gdalsrsinfo.1 b/man/man1/gdalsrsinfo.1
index d83788d..ad8eb6d 100644
--- a/man/man1/gdalsrsinfo.1
+++ b/man/man1/gdalsrsinfo.1
@@ -1,9 +1,8 @@
-.TH "gdalsrsinfo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalsrsinfo" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdalsrsinfo \- gdalsrsinfo 
-lists info about a given SRS in number of formats (WKT, PROJ\&.4, etc\&.)
+gdalsrsinfo \- Lists info about a given SRS in number of formats (WKT, PROJ\&.4, etc\&.)
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -13,7 +12,7 @@ Usage: gdalsrsinfo [options] srs_def
 srs_def may be the filename of a dataset supported by GDAL/OGR from which to extract SRS information
 OR any of the usual GDAL/OGR forms (complete WKT, PROJ.4, EPSG:n or a file containing the SRS)
 
-Options: 
+Options:
    [--help-general] [-h]  Show help and exit
    [-p]                   Pretty-print where applicable (e.g. WKT)
    [-V]                   Validate SRS
diff --git a/man/man1/gdaltindex.1 b/man/man1/gdaltindex.1
index 5c8670b..d4323b5 100644
--- a/man/man1/gdaltindex.1
+++ b/man/man1/gdaltindex.1
@@ -1,9 +1,8 @@
-.TH "gdaltindex" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdaltindex" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaltindex \- gdaltindex 
-Builds a shapefile as a raster tileindex
+gdaltindex \- Builds a shapefile as a raster tileindex\&.
 .SH "SYNOPSIS"
 .PP
 .PP
diff --git a/man/man1/gdaltransform.1 b/man/man1/gdaltransform.1
index 49896ce..d4370cb 100644
--- a/man/man1/gdaltransform.1
+++ b/man/man1/gdaltransform.1
@@ -1,9 +1,8 @@
-.TH "gdaltransform" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdaltransform" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-gdaltransform \- gdaltransform 
-transforms coordinates
+gdaltransform \- Transforms coordinates\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -61,7 +60,7 @@ gdaltransform -s_srs EPSG:28992 -t_srs EPSG:31370
 .fi
 .PP
 .PP
-Produces the following output in meters in the 'Belge 1972 / Belgian Lambert 
+Produces the following output in meters in the 'Belge 1972 / Belgian Lambert
 72' projection:
 .PP
 .PP
@@ -69,14 +68,14 @@ Produces the following output in meters in the 'Belge 1972 / Belgian Lambert
 244510.77404604 166154.532871342 -1046.79270555763
 .fi
 .PP
-.SH "Reprojection Example"
+.SH "Image RPC Example"
 .PP
 The following command requests an RPC based transformation using the RPC model associated with the named file\&. Because the -i (inverse) flag is used, the transformation is from output georeferenced (WGS84) coordinates back to image coordinates\&.
 .PP
 .PP
 .nf
 gdaltransform -i -rpc 06OCT20025052-P2AS-005553965230_01_P001.TIF
-125.67206 39.85307 50                    
+125.67206 39.85307 50
 .fi
 .PP
 .PP
diff --git a/man/man1/gdalwarp.1 b/man/man1/gdalwarp.1
index 3c39dfc..4a0e94d 100644
--- a/man/man1/gdalwarp.1
+++ b/man/man1/gdalwarp.1
@@ -1,4 +1,4 @@
-.TH "gdalwarp" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gdalwarp" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -10,13 +10,14 @@ image reprojection and warping utility
 .PP
 .nf
 gdalwarp [--help-general] [--formats]
-    [-s_srs srs_def] [-t_srs srs_def] [-to "NAME=VALUE"]
+    [-s_srs srs_def] [-t_srs srs_def] [-to "NAME=VALUE"] [-novshiftgrid]
     [-order n | -tps | -rpc | -geoloc] [-et err_threshold]
     [-refine_gcps tolerance [minimum_gcps]]
     [-te xmin ymin xmax ymax] [-te_srs srs_def]
     [-tr xres yres] [-tap] [-ts width height]
     [-ovr level|AUTO|AUTO-n|NONE] [-wo "NAME=VALUE"] [-ot Byte/Int16/...] [-wt Byte/Int16]
-    [-srcnodata "value [value...]"] [-dstnodata "value [value...]"] -dstalpha
+    [-srcnodata "value [value...]"] [-dstnodata "value [value...]"]
+    [-srcalpha|-nosrcalpha] [-dstalpha]
     [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]
     [-cutline datasource] [-cl layer] [-cwhere expression]
     [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]
@@ -31,11 +32,13 @@ gdalwarp [--help-general] [--formats]
 The gdalwarp utility is an image mosaicing, reprojection and warping utility\&. The program can reproject to any supported projection, and can also apply GCPs stored with the image if the image is 'raw' with control information\&.
 .PP
 .IP "\fB\fB-s_srs\fP \fIsrs def\fP:\fP" 1c
-source spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (i\&.e\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prj file containing well known text\&. 
+source spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (i\&.e\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prj file containing well known text\&. Starting with GDAL 2\&.2, if the SRS has an explicit vertical datum that points to a PROJ\&.4 geoidgrids, and the input dataset is a single band dataset, a vertical correction will be applied  [...]
 .IP "\fB\fB-t_srs\fP \fIsrs_def\fP:\fP" 1c
-target spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (i\&.e\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prj file containing well known text\&. 
+target spatial reference set\&. The coordinate systems that can be passed are anything supported by the OGRSpatialReference\&.SetFromUserInput() call, which includes EPSG PCS and GCSes (i\&.e\&. EPSG:4296), PROJ\&.4 declarations (as above), or the name of a \&.prj file containing well known text\&. Starting with GDAL 2\&.2, if the SRS has an explicit vertical datum that points to a PROJ\&.4 geoidgrids, and the input dataset is a single band dataset, a vertical correction will be applied  [...]
 .IP "\fB\fB-to\fP \fINAME=VALUE\fP:\fP" 1c
 set a transformer option suitable to pass to GDALCreateGenImgProjTransformer2()\&.  
+.IP "\fB\fB-novshiftgrid\fP\fP" 1c
+(GDAL >= 2\&.2) Disable the use of vertical datum shift grids when one of the source or target SRS has an explicit vertical datum, and the input dataset is a single band dataset\&. 
 .IP "\fB\fB-order\fP \fIn\fP:\fP" 1c
 order of polynomial used for warping (1 to 3)\&. The default is to select a polynomial order based on the number of GCPs\&. 
 .IP "\fB\fB-tps\fP:\fP" 1c
@@ -97,6 +100,10 @@ third quartile resampling, selects the third quartile value of all non-NODATA co
 Set nodata masking values for input bands (different values can be supplied for each band)\&. If more than one value is supplied all values should be quoted to keep them together as a single operating system argument\&. Masked values will not be used in interpolation\&. Use a value of \fCNone\fP to ignore intrinsic nodata settings on the source dataset\&. 
 .IP "\fB\fB-dstnodata\fP \fIvalue [value\&.\&.\&.]\fP:\fP" 1c
 Set nodata values for output bands (different values can be supplied for each band)\&. If more than one value is supplied all values should be quoted to keep them together as a single operating system argument\&. New files will be initialized to this value and if possible the nodata value will be recorded in the output file\&. Use a value of \fCNone\fP to ensure that nodata is not defined (GDAL>=1\&.11)\&. If this argument is not used then nodata values will be copied from the source dat [...]
+.IP "\fB\fB-srcalpha\fP:\fP" 1c
+Force the last band of a source image to be considered as a source alpha band\&.  
+.IP "\fB\fB-nosrcalpha\fP:\fP" 1c
+Prevent the alpha band of a source image to be considered as such (it will be warped as a regular band) (GDAL>=2\&.2)\&.  
 .IP "\fB\fB-dstalpha\fP:\fP" 1c
 Create an output alpha band to identify nodata (unset/transparent) pixels\&.  
 .IP "\fB\fB-wm\fP \fImemory_in_mb\fP:\fP" 1c
@@ -108,7 +115,7 @@ Be quiet\&.
 .IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
 Select the output format\&. The default is GeoTIFF (GTiff)\&. Use the short format name\&.  
 .IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
-passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&. 
+passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See \fCformat specific documentation for legal creation options for each format\fP 
 .PP
 .IP "\fB\fB-cutline\fP \fIdatasource\fP:\fP" 1c
 Enable use of a blend cutline from the name OGR support datasource\&. 
@@ -144,21 +151,56 @@ The destination file name\&.
 Mosaicing into an existing output file is supported if the output file already exists\&. The spatial extent of the existing file will not be modified to accommodate new data, so you may have to remove it in that case, or use the -overwrite option\&.
 .PP
 Polygon cutlines may be used as a mask to restrict the area of the destination file that may be updated, including blending\&. If the OGR layer containing the cutline features has no explicit SRS, the cutline features must be in the SRS of the destination file\&. When writing to a not yet existing target dataset, its extent will be the one of the original raster unless -te or -crop_to_cutline are specified\&.
-.SH "EXAMPLE"
 .PP
+When doing vertical shift adjustments, the transformer option -to ERROR_ON_MISSING_VERT_SHIFT=YES can be used to error out as soon as a vertical shift value is missing (instead of 0 being used)\&.
+.SH "EXAMPLES"
+.PP
+.IP "\(bu" 2
 For instance, an eight bit spot scene stored in GeoTIFF with control points mapping the corners to lat/long could be warped to a UTM projection with a command like this:
 .PP
 .PP
+.PP
 .nf
-gdalwarp -t_srs '+proj=utm +zone=11 +datum=WGS84' raw_spot.tif utm11.tif
+gdalwarp -t_srs '+proj=utm +zone=11 +datum=WGS84' -overwrite raw_spot.tif utm11.tif
 .fi
 .PP
 .PP
+.IP "\(bu" 2
 For instance, the second channel of an ASTER image stored in HDF with control points mapping the corners to lat/long could be warped to a UTM projection with a command like this:
 .PP
 .PP
+.PP
+.nf
+gdalwarp -overwrite HDF4_SDS:ASTER_L1B:"pg-PR1B0000-2002031402_100_001":2 pg-PR1B0000-2002031402_100_001_2.tif
+.fi
+.PP
+.PP
+.IP "\(bu" 2
+(GDAL >= 2\&.2) To apply a cutline on a un-georeferenced image and clip from pixel (220,60) to pixel (1160,690):
+.PP
+.PP
+.PP
+.nf
+gdalwarp -overwrite -to SRC_METHOD=NO_GEOTRANSFORM -to DST_METHOD=NO_GEOTRANSFORM -te 220 60 1160 690 -cutline cutline.csv in.png out.tif
+.fi
+.PP
+.PP
+where cutline\&.csv content is like: 
+.PP
+.nf
+id,WKT
+1,"POLYGON((....))"
+
+.fi
+.PP
+.PP
+.IP "\(bu" 2
+(GDAL >= 2\&.2) To transform a DEM from geoid elevations (using EGM96) to WGS84 ellipsoidal heights:
+.PP
+.PP
+.PP
 .nf
-gdalwarp HDF4_SDS:ASTER_L1B:"pg-PR1B0000-2002031402_100_001":2 pg-PR1B0000-2002031402_100_001_2.tif
+gdalwarp -override in_dem.tif out_dem.tif -s_srs EPSG:4326+5773 -t_srs EPSG:4979
 .fi
 .PP
 .SH "SEE ALSO"
diff --git a/man/man1/gnm_utilities.1 b/man/man1/gnm_utilities.1
index 75e364c..60832eb 100644
--- a/man/man1/gnm_utilities.1
+++ b/man/man1/gnm_utilities.1
@@ -1,4 +1,4 @@
-.TH "gnm_utilities" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gnm_utilities" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnmanalyse.1 b/man/man1/gnmanalyse.1
index 8a56d71..5f14422 100644
--- a/man/man1/gnmanalyse.1
+++ b/man/man1/gnmanalyse.1
@@ -1,4 +1,4 @@
-.TH "gnmanalyse" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gnmanalyse" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/gnmmanage.1 b/man/man1/gnmmanage.1
index 54a970e..6b00bd5 100644
--- a/man/man1/gnmmanage.1
+++ b/man/man1/gnmmanage.1
@@ -1,4 +1,4 @@
-.TH "gnmmanage" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "gnmmanage" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
diff --git a/man/man1/nearblack.1 b/man/man1/nearblack.1
index 573041d..aaf9fca 100644
--- a/man/man1/nearblack.1
+++ b/man/man1/nearblack.1
@@ -1,9 +1,8 @@
-.TH "nearblack" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "nearblack" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-nearblack \- nearblack 
-convert nearly black/white borders to black
+nearblack \- Convert nearly black/white borders to black\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -21,7 +20,7 @@ The name of the output file to be created\&. Newly created files are created wit
 .IP "\fB\fB-of\fP \fIformat\fP:\fP" 1c
 (GDAL 1\&.8\&.0 or later) Select the output format\&. Use the short format name (GTiff for GeoTIFF for example)\&. 
 .IP "\fB\fB-co\fP \fI'NAME=VALUE'\fP:\fP" 1c
-(GDAL 1\&.8\&.0 or later) Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See format specific documentation for legal creation options for each format\&. Only valid when creating a new file 
+(GDAL 1\&.8\&.0 or later) Passes a creation option to the output format driver\&. Multiple \fB-co\fP options may be listed\&. See \fCformat specific documentation for legal creation options for each format\fP\&. Only valid when creating a new file 
 .IP "\fB\fB-white\fP:\fP" 1c
 Search for nearly white (255) pixels instead of nearly black pixels\&.  
 .IP "\fB\fB-color\fP \fIc1,c2,c3\&.\&.\&.cn\fP:\fP" 1c
diff --git a/man/man1/ogr2ogr.1 b/man/man1/ogr2ogr.1
index bfb4369..3cb6426 100644
--- a/man/man1/ogr2ogr.1
+++ b/man/man1/ogr2ogr.1
@@ -1,24 +1,23 @@
-.TH "ogr2ogr" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "ogr2ogr" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogr2ogr \- ogr2ogr 
-converts simple features data between file formats
+ogr2ogr \- Converts simple features data between file formats\&.
 .SH "SYNOPSIS"
 .PP
 .PP
 .PP
 .nf
 Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update]
-               [-select field_list] [-where restricted_where|@filename] 
-               [-progress] [-sql <sql statement>|@filename] [-dialect dialect]
-               [-preserve_fid] [-fid FID]
+               [-select field_list] [-where restricted_where|\@filename]
+               [-progress] [-sql <sql statement>|\@filename] [-dialect dialect]
+               [-preserve_fid] [-fid FID] [-limit nb_features]
                [-spat xmin ymin xmax ymax] [-spat_srs srs_def] [-geomfield field]
                [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]
                [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]
                dst_datasource_name src_datasource_name
                [-lco NAME=VALUE] [-nln name]
-               [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR]
+               [-nlt type|PROMOTE_TO_MULTI|CONVERT_TO_LINEAR|CONVERT_TO_CURVE]
                [-dim XY|XYZ|XYM|XYZM|2|3|layer_dim] [layer [layer ...]]
 
 Advanced options :
@@ -69,11 +68,11 @@ Comma-delimited list of fields from input layer to copy to the new layer\&. A fi
 .IP "\fB\fB-progress\fP:\fP" 1c
 (starting with GDAL 1\&.7\&.0) Display progress on terminal\&. Only works if input layers have the 'fast feature count' capability\&. 
 .IP "\fB\fB-sql\fP \fIsql_statement\fP:\fP" 1c
-SQL statement to execute\&. The resulting table/layer will be saved to the output\&. Starting with GDAL 2\&.1, the  syntax can be used to indicate that the content is in the pointed filename\&. 
+SQL statement to execute\&. The resulting table/layer will be saved to the output\&. Starting with GDAL 2\&.1, the @filename syntax can be used to indicate that the content is in the pointed filename\&. 
 .IP "\fB\fB-dialect\fP \fIdialect\fP:\fP" 1c
 SQL dialect\&. In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL\&. Starting with GDAL 1\&.10, the 'SQLITE' dialect can also be used with any datasource\&. 
 .IP "\fB\fB-where\fP\fI restricted_where\fP:\fP" 1c
-Attribute query (like SQL WHERE)\&. Starting with GDAL 2\&.1, the  syntax can be used to indicate that the content is in the pointed filename\&. 
+Attribute query (like SQL WHERE)\&. Starting with GDAL 2\&.1, the @filename syntax can be used to indicate that the content is in the pointed filename\&. 
 .IP "\fB\fB-skipfailures\fP:\fP" 1c
 Continue after a failure, skipping the failed feature\&. 
 .IP "\fB\fB-spat\fP\fI xmin ymin xmax ymax\fP:\fP" 1c
@@ -89,7 +88,7 @@ Layer creation option (format specific)
 .IP "\fB\fB-nln\fP\fI name\fP:\fP" 1c
 Assign an alternate name to the new layer 
 .IP "\fB\fB-nlt\fP\fI type\fP:\fP" 1c
-Define the geometry type for the created layer\&. One of NONE, GEOMETRY, POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT, MULTIPOLYGON or MULTILINESTRING\&. And CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON, MULTICURVE and MULTISURFACE for GDAL 2\&.0 non-linear geometry types\&. Add 'Z', 'M', or 'ZM' to the name to get coordinates with elevation, measure, or elevation and measure\&. Starting with GDAL 1\&.10, PROMOTE_TO_MULTI can be used to automatically promote layers that mix  [...]
+Define the geometry type for the created layer\&. One of NONE, GEOMETRY, POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT, MULTIPOLYGON or MULTILINESTRING\&. And CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON, MULTICURVE and MULTISURFACE for GDAL 2\&.0 non-linear geometry types\&. Add 'Z', 'M', or 'ZM' to the name to get coordinates with elevation, measure, or elevation and measure\&. Starting with GDAL 1\&.10, PROMOTE_TO_MULTI can be used to automatically promote layers that mix  [...]
 .IP "\fB\fB-dim\fP\fI val\fP:\fP" 1c
 (starting with GDAL 1\&.10) Force the coordinate dimension to val (valid values are XY, XYZ, XYM, and XYZM - for backwards compatibility 2 is an alias for XY and 3 is an alias for XYZ)\&. This affects both the layer geometry type, and feature geometries\&. Starting with GDAL 1\&.11, the value can be set to 'layer_dim' to instruct feature geometries to be promoted to the coordinate dimension declared by the layer\&. Support for M was added in GDAL 2\&.1 
 .IP "\fB\fB-a_srs\fP\fI srs_def\fP:\fP" 1c
@@ -102,6 +101,8 @@ Override source SRS
 Use the FID of the source features instead of letting the output driver to automatically assign a new one\&. Note: starting with GDAL 2\&.0, if not in append mode, this behaviour becomes the default if the output driver has a FID layer creation option\&. In which case the name of the source FID column will be used and source feature IDs will be attempted to be preserved\&. This behaviour can be disabled by setting -unsetFid 
 .IP "\fB\fB-fid\fP \fIfid\fP:\fP" 1c
 If provided, only the feature with this feature id will be reported\&. Operates exclusive of the spatial or attribute queries\&. Note: if you want to select several features based on their feature id, you can also use the fact the 'fid' is a special field recognized by OGR SQL\&. So, '-where 'fid in (1,3,5)'' would select features 1, 3 and 5\&. 
+.IP "\fB\fB-limit\fP \fInb_features\fP:\fP" 1c
+(starting with GDAL 2\&.2): to limit the number of features, per layer\&. 
 .PP
 .PP
 Srs_def can be a full WKT definition (hard to escape properly), or a well known definition (i\&.e\&. EPSG:4326) or a file with a WKT definition\&.
@@ -184,7 +185,7 @@ To be combined with -splitlistfields to limit the number of subfields created fo
 .PP
 When writing into transactional DBMS (SQLite/PostgreSQL,MySQL, etc\&.\&.\&.), it might be beneficial to increase the number of INSERT statements executed between BEGIN TRANSACTION and COMMIT TRANSACTION statements\&. This number is specified with the -gt option\&. For example, for SQLite, explicitly defining \fB-gt 65536\fP ensures optimal performance while populating some table containing many hundredth thousand or million rows\&. However, note that if there are failed insertions, the s [...]
 .PP
-For PostgreSQL, the PG_USE_COPY config option can be set to YES for significantly insertion performance boot\&. See the PG driver documentation page\&.
+For PostgreSQL, the PG_USE_COPY config option can be set to YES for a significant insertion performance boost\&. See the PG driver documentation page\&.
 .PP
 More generally, consult the documentation page of the input and output drivers for performance hints\&.
 .SH "C API"
diff --git a/man/man1/ogr_utilities.1 b/man/man1/ogr_utilities.1
index 236ee41..67efea3 100644
--- a/man/man1/ogr_utilities.1
+++ b/man/man1/ogr_utilities.1
@@ -1,4 +1,4 @@
-.TH "ogr_utilities" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "ogr_utilities" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
@@ -16,6 +16,8 @@ The following utilities are distributed as part of the OGR Simple Features toolk
 \fBogrtindex\fP - Creates a tileindex 
 .IP "\(bu" 2
 \fBogrlineref\fP - Create linear reference and provide some calculations using it 
+.IP "\(bu" 2
+\fBogrmerge\fP - Merge several vector datasets into a single one 
 .PP
 .SH "General Command Line Switches"
 .PP
diff --git a/man/man1/ogrinfo.1 b/man/man1/ogrinfo.1
index 0393af8..5383ae8 100644
--- a/man/man1/ogrinfo.1
+++ b/man/man1/ogrinfo.1
@@ -1,17 +1,16 @@
-.TH "ogrinfo" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "ogrinfo" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogrinfo \- ogrinfo 
-lists information about an OGR supported data source
+ogrinfo \- Lists information about an OGR supported data source\&.
 .SH "SYNOPSIS"
 .PP
 .PP
 .PP
 .nf
-ogrinfo [--help-general] [-ro] [-q] [-where restricted_where|@filename]
+ogrinfo [--help-general] [-ro] [-q] [-where restricted_where|\@filename]
         [-spat xmin ymin xmax ymax] [-geomfield field] [-fid fid]
-        [-sql statement|@filename] [-dialect dialect] [-al] [-so] [-fields={YES/NO}]
+        [-sql statement|\@filename] [-dialect dialect] [-al] [-rl] [-so] [-fields={YES/NO}]
         [-geom={YES/NO/SUMMARY/WKT/ISO_WKT}] [-formats] [[-oo NAME=VALUE] ...]
         [-nomd] [-listmdd] [-mdd domain|`all`]*
         [-nocount] [-noextent]
@@ -25,14 +24,16 @@ The ogrinfo program lists various information about an OGR supported data source
 Open the data source in read-only mode\&.  
 .IP "\fB\fB-al\fP:\fP" 1c
 List all features of all layers (used instead of having to give layer names as arguments)\&. 
+.IP "\fB\fB-rl\fP:\fP" 1c
+(Available in GDAL 2\&.2) Enable random layer reading mode, i\&.e\&. iterate over features in the order they are found in the dataset, and not layer per layer\&. This can be significantly faster for some formats (for example OSM, GMLAS)\&. 
 .IP "\fB\fB-so\fP:\fP" 1c
 Summary Only: suppress listing of features, show only the summary information like projection, schema, feature count and extents\&. 
 .IP "\fB\fB-q\fP:\fP" 1c
 Quiet verbose reporting of various information, including coordinate system, layer schema, extents, and feature count\&.  
 .IP "\fB\fB-where\fP \fIrestricted_where\fP:\fP" 1c
-An attribute query in a restricted form of the queries used in the SQL WHERE statement\&. Only features matching the attribute query will be reported\&. Starting with GDAL 2\&.1, the  syntax can be used to indicate that the content is in the pointed filename\&. 
+An attribute query in a restricted form of the queries used in the SQL WHERE statement\&. Only features matching the attribute query will be reported\&. Starting with GDAL 2\&.1, the \\filename syntax can be used to indicate that the content is in the pointed filename\&. 
 .IP "\fB\fB-sql\fP \fIstatement\fP:\fP" 1c
-Execute the indicated SQL statement and return the result\&. Starting with GDAL 2\&.1, the  syntax can be used to indicate that the content is in the pointed filename\&. 
+Execute the indicated SQL statement and return the result\&. Starting with GDAL 2\&.1, the @filename syntax can be used to indicate that the content is in the pointed filename\&. 
 .IP "\fB\fB-dialect\fP \fIdialect\fP:\fP" 1c
 SQL dialect\&. In some cases can be used to use (unoptimized) OGR SQL instead of the native SQL of an RDBMS by passing OGRSQL\&. Starting with GDAL 1\&.10, the 'SQLITE' dialect can also be used with any datasource\&. 
 .IP "\fB\fB-spat\fP \fIxmin ymin xmax ymax\fP:\fP" 1c
diff --git a/man/man1/ogrlineref.1 b/man/man1/ogrlineref.1
index 8c6921e..4042834 100644
--- a/man/man1/ogrlineref.1
+++ b/man/man1/ogrlineref.1
@@ -1,9 +1,8 @@
-.TH "ogrlineref" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "ogrlineref" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogrlineref \- ogrlineref 
-The utility can be used for:
+ogrlineref \- The utility can be used for:
 .IP "\(bu" 2
 create linear reference file from input data
 .IP "\(bu" 2
diff --git a/man/man1/ogrmerge.1 b/man/man1/ogrmerge.1
new file mode 100644
index 0000000..7c79a9f
--- /dev/null
+++ b/man/man1/ogrmerge.1
@@ -0,0 +1,146 @@
+.TH "ogrmerge" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
+.ad l
+.nh
+.SH NAME
+ogrmerge \- Merge several vector datasets into a single one\&.
+.SH "SYNOPSIS"
+.PP
+.PP
+.nf
+ogrmerge.py -o out_dsname src_dsname [src_dsname]*
+            [-f format] [-single] [-nln layer_name_template]
+            [-update | -overwrite_ds] [-append | -overwrite_layer]
+            [-src_geom_type geom_type_name[,geom_type_name]*]
+            [-dsco NAME=VALUE]* [-lco NAME=VALUE]*
+            [-s_srs srs_def] [-t_srs srs_def | -a_srs srs_def]
+            [-progress] [-skipfailures] [--help-general]
+
+Options specific to -single:
+            [-field_strategy FirstLayer|Union|Intersection]
+            [-src_layer_field_name name]
+            [-src_layer_field_content layer_name_template]
+.fi
+.PP
+.SH "DESCRIPTION"
+.PP
+(Available since GDAL 2\&.2)
+.PP
+The ogrmerge\&.py script takes as input several vector datasets, each of them having one or several vector layers, and copy them in a target dataset\&.
+.PP
+There are essential two modes :
+.IP "\(bu" 2
+the default one, where each input vector layer, is copied as a separate layer into the target dataset
+.IP "\(bu" 2
+another one, activated with the -single switch, where the content of all input vector layers is appended into a single target layer\&. This assumes that the schema of those vector layers is more or less the same\&.
+.PP
+.PP
+Internally this generates a \fCVRT\fP file, and if the output format is not VRT, final translation is done with ogr2ogr / gdal\&.VectorTranslate\&. So for advanced uses, output to VRT, potential manual editing of it and ogr2ogr can be done\&.
+.PP
+.IP "\fB\fB-o\fP \fIout_dsname\fP:\fP" 1c
+Output dataset name\&. Required\&. 
+.PP
+.IP "\fB\fIsrc_dsname\fP:\fP" 1c
+One or several input vector datasets\&. Required 
+.PP
+.IP "\fB\fB-f\fP \fIformat\fP:\fP" 1c
+Select the output format\&. VRT is a valid output format as well\&. Defaults to 'ESRI Shapefile'
+.PP
+.IP "\fB\fB-single\fP:\fP" 1c
+If specified, all input vector layers will be merged into a single one\&.
+.PP
+.IP "\fB\fB-nln\fP \fIlayer_name_template\fP:\fP" 1c
+Name of the output vector layer (in single mode, and the default is 'merged'), or template to name the output vector layers in default mode (the default value is '{AUTO_NAME}')\&. The template can be a string with the following variables that will be susbstitued with a value computed from the input layer being processed:
+.PP
+.IP "\(bu" 2
+{AUTO_NAME}: equivalent to {DS_BASENAME}_{LAYER_NAME} if both values are different, or {LAYER_NAME} when they are identical (case of shapefile)\&. 'different
+.IP "\(bu" 2
+{DS_NAME} : name of the source dataset
+.IP "\(bu" 2
+{DS_BASENAME}: base name of the source dataset
+.IP "\(bu" 2
+{DS_INDEX} : index of the source dataset
+.IP "\(bu" 2
+{LAYER_NAME} : name of the source layer
+.IP "\(bu" 2
+{LAYER_INDEX}: index of the source layer 
+.PP
+.PP
+.IP "\fB\fB-update\fP \fP" 1c
+Open an existing dataset in update mode\&.
+.PP
+.IP "\fB\fB-overwrite_ds\fP \fP" 1c
+Overwrite the existing dataset if it already exists (for file based datasets)
+.PP
+.IP "\fB\fB-append\fP \fP" 1c
+Open an existing dataset in update mode, and if output layers already exist, append the content of input layers to them\&. 
+.PP
+.IP "\fB\fB-overwrite_layer\fP \fP" 1c
+Open an existing dataset in update mode, and if output layers already exist, replace their content with the one of the input layer\&.
+.PP
+.IP "\fB\fB-src_geom_type\fP \fIgeom_type_name[,geom_type_name]*]\fP:\fP" 1c
+Only take into account input layers whose geometry type match the type(s) specified\&. Valid values for geom_type_name are GEOMETRY, POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOINT, GEOMETRYCOLLECTION, CIRCULARSTRING, CURVEPOLYGON, MULTICURVE, MULTISURFACE, CURVE, SURFACE, TRIANGLE, POLYHEDRALSURFACE and TIN\&.
+.PP
+.IP "\fB\fB-dsco\fP \fINAME=VALUE\fP:\fP" 1c
+Dataset creation option (format specific)
+.PP
+.IP "\fB\fB-lco\fP\fI NAME=VALUE\fP:\fP" 1c
+Layer creation option (format specific)
+.PP
+.IP "\fB\fB-a_srs\fP\fI srs_def\fP:\fP" 1c
+Assign an output SRS
+.PP
+.IP "\fB\fB-t_srs\fP\fI srs_def\fP:\fP" 1c
+Reproject/transform to this SRS on output
+.PP
+.IP "\fB\fB-s_srs\fP\fI srs_def\fP:\fP" 1c
+Override source SRS
+.PP
+.IP "\fB\fB-progress\fP:\fP" 1c
+Display progress on terminal\&. Only works if input layers have the 'fast feature count' capability\&.
+.PP
+.IP "\fB\fB-skipfailures\fP:\fP" 1c
+Continue after a failure, skipping the failed feature\&.
+.PP
+.IP "\fB\fB-field_strategy\fP\fI FirstLayer|Union|Intersection\fP:\fP" 1c
+Only used with -single\&. Determines how the schema of the target layer is built from the schemas of the input layers\&. May be FirstLayer to use the fields from the first layer found, Union to use a super-set of all the fields from all source layers, or Intersection to use a sub-set of all the common fields from all source layers\&. Defaults to Union\&.
+.PP
+.IP "\fB\fB-src_layer_field_name\fP\fI name\fP:\fP" 1c
+Only used with -single\&. If specified, the schema of the target layer will be extended with a new field 'name', whose content is determined by -src_layer_field_content\&.
+.PP
+.IP "\fB\fB-src_layer_field_content\fP\fI layer_name_template\fP:\fP" 1c
+Only used with -single\&. If specified, the schema of the target layer will be extended with a new field (whose name is given by -src_layer_field_name, or 'source_ds_lyr' otherwise), whose content is determined by layer_name_template\&. The syntax of layer_name_template is the same as for -nln\&. 
+.PP
+.PP
+.SH "EXAMPLES"
+.PP
+.IP "\(bu" 2
+Creates a VRT with a layer for each input shapefiles 
+.PP
+.nf
+ogrmerge.py -f VRT -o merged.vrt *.shp
+
+.fi
+.PP
+
+.IP "\(bu" 2
+Same, but creates a GeoPackage file 
+.PP
+.nf
+ogrmerge.py -f GPKG -o merged.gpkg *.shp
+
+.fi
+.PP
+
+.IP "\(bu" 2
+Concatenate the content of france\&.shp and germany\&.shp in merged\&.shp, and adds a 'country' field to each feature whose value is 'france' or 'germany' depending where it comes from\&. 
+.PP
+.nf
+ogrmerge.py -single -o merged.shp france.shp germany.shp -src_layer_field_name country
+
+.fi
+.PP
+
+.PP
+.SH "AUTHORS"
+.PP
+Even Rouault even.rouault at spatialys.com 
diff --git a/man/man1/ogrtindex.1 b/man/man1/ogrtindex.1
index 4c97ac8..d42733a 100644
--- a/man/man1/ogrtindex.1
+++ b/man/man1/ogrtindex.1
@@ -1,9 +1,8 @@
-.TH "ogrtindex" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "ogrtindex" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-ogrtindex \- ogrtindex 
-creates a tileindex
+ogrtindex \- Creates a tileindex\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -11,6 +10,9 @@ creates a tileindex
 .nf
 ogrtindex [-lnum n]... [-lname name]... [-f output_format]
           [-write_absolute_path] [-skip_different_projection]
+          [-t_srs target_srs]
+          [-src_srs_name field_name] [-src_srs_format [AUTO|WKT|EPSG|PROJ]
+          [-accept_different_schemas]
                  output_dataset src_dataset...
 .fi
 .PP
@@ -30,6 +32,21 @@ The name to use for the dataset name\&. Defaults to LOCATION\&.
 Filenames are written with absolute paths 
 .IP "\fB\fB-skip_different_projection\fP:\fP" 1c
 Only layers with same projection ref as layers already inserted in the tileindex will be inserted\&. 
+.IP "\fB\fB-t_srs\fP target_srs:\fP" 1c
+(GDAL >= 2\&.2) 
+.PP
+Extent of input files will be transformed to the desired target coordinate reference system\&. Using this option generates files that are not compatible with MapServer < 7\&.2\&. Default creates simple rectangular polygons in the same coordinate reference system as the input rasters\&.
+.PP
+.IP "\fB\fB-src_srs_name\fP field_name:\fP" 1c
+(GDAL >= 2\&.2) 
+.PP
+The name of the field to store the SRS of each tile\&. This field name can be used as the value of the TILESRS keyword in MapServer >= 7\&.2\&.
+.PP
+.IP "\fB\fB-src_srs_format\fP type:\fP" 1c
+(GDAL >= 2\&.2) 
+.PP
+The format in which the SRS of each tile must be written\&. Types can be AUTO, WKT, EPSG, PROJ\&.
+.PP
 .IP "\fB\fB-accept_different_schemas\fP:\fP" 1c
 By default ogrtindex checks that all layers inserted into the index have the same attribute schemas\&. If you specify this option, this test will be disabled\&. Be aware that resulting index may be incompatible with MapServer! 
 .PP
@@ -37,8 +54,6 @@ By default ogrtindex checks that all layers inserted into the index have the sam
 If no -lnum or -lname arguments are given it is assumed that all layers in source datasets should be added to the tile index as independent records\&.
 .PP
 If the tile index already exists it will be appended to, otherwise it will be created\&.
-.PP
-It is a flaw of the current ogrtindex program that no attempt is made to copy the coordinate system definition from the source datasets to the tile index (as is expected by MapServer when PROJECTION AUTO is in use)\&.
 .SH "EXAMPLE"
 .PP
 This example would create a shapefile (tindex\&.shp) containing a tile index of the BL2000_LINK layers in all the NTF files in the wrk directory: 
diff --git a/man/man1/pct2rgb.1 b/man/man1/pct2rgb.1
index 77da77b..601a249 100644
--- a/man/man1/pct2rgb.1
+++ b/man/man1/pct2rgb.1
@@ -1,9 +1,8 @@
-.TH "pct2rgb" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "pct2rgb" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-pct2rgb \- pct2rgb\&.py 
-Convert an 8bit paletted image to 24bit RGB
+pct2rgb \- Convert an 8bit paletted image to 24bit RGB\&.
 .SH "SYNOPSIS"
 .PP
 .PP
diff --git a/man/man1/rgb2pct.1 b/man/man1/rgb2pct.1
index 610242d..0580413 100644
--- a/man/man1/rgb2pct.1
+++ b/man/man1/rgb2pct.1
@@ -1,9 +1,8 @@
-.TH "rgb2pct" 1 "Fri Jan 20 2017" "GDAL" \" -*- nroff -*-
+.TH "rgb2pct" 1 "Fri Apr 14 2017" "GDAL" \" -*- nroff -*-
 .ad l
 .nh
 .SH NAME
-rgb2pct \- rgb2pct\&.py 
-Convert a 24bit RGB image to 8bit paletted
+rgb2pct \- Convert a 24bit RGB image to 8bit paletted\&.
 .SH "SYNOPSIS"
 .PP
 .PP
@@ -46,7 +45,7 @@ If it is desired to hand create the palette, likely the simplest text format is
       <Entry c1="229" c2="229" c3="229" c4="255"/>
     </ColorTable>
   </VRTRasterBand>
-</VRTDataset> 
+</VRTDataset>
 .fi
 .PP
 .SH "AUTHOR"
diff --git a/mkgdaldist.sh b/mkgdaldist.sh
index ca94245..1c5e15a 100755
--- a/mkgdaldist.sh
+++ b/mkgdaldist.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# $Id: mkgdaldist.sh 33096 2016-01-22 18:00:06Z rouault $
+# $Id: mkgdaldist.sh 37197 2017-01-21 12:58:43Z rouault $
 #
 # mkgdaldist.sh - prepares GDAL source distribution package
 #
@@ -30,7 +30,7 @@ fi
 GDAL_VERSION=$1
 COMPRESSED_VERSION=`echo $GDAL_VERSION | tr -d .`
 
-if test "$2" = "-date" ; then 
+if test "$2" = "-date" ; then
   forcedate=$3
   shift
   shift
@@ -45,7 +45,7 @@ if test "$2" = "-branch"; then
 else
   forcebranch="trunk"
 fi
- 
+
 if test "$2" = "-rc"; then
   RC=$3
   shift
@@ -53,12 +53,12 @@ if test "$2" = "-rc"; then
 else
   RC=""
 fi
- 
+
 #
 # Checkout GDAL sources from the repository
 #
 echo "* Downloading GDAL sources from SVN..."
-rm -rf dist_wrk  
+rm -rf dist_wrk
 mkdir dist_wrk
 cd dist_wrk
 
@@ -87,7 +87,7 @@ fi
 echo "* Updating release date..."
 if test "$forcedate" != "no" ; then
   echo "Forcing Date To: $forcedate"
-  rm -f gdal/gcore/gdal_new.h  
+  rm -f gdal/gcore/gdal_new.h
   sed -e "/define GDAL_RELEASE_DATE/s/20[0-9][0-9][0-9][0-9][0-9][0-9]/$forcedate/" gdal/gcore/gdal.h > gdal/gcore/gdal_new.h
   mv gdal/gcore/gdal_new.h gdal/gcore/gdal.h
 fi
@@ -111,16 +111,25 @@ fi
 if test ! -d "man"; then
     echo " make man failed"
 fi
+
+if test -f "doxygen_sqlite3.db"; then
+    rm -f doxygen_sqlite3.db
+fi
+
 cd ${CWD}
 
+# They currently require SWIG 1.3.X, which is not convenient as we need
+# newer SWIG for newer Python versions
+echo "SWIG C# interfaces *NOT* generated !"
+
 #
 # Generate SWIG interface for C#
 #
-echo "* Generating SWIG C# interfaces..."
-CWD=${PWD}
-cd gdal/swig/csharp
-./mkinterface.sh
-cd ${CWD}
+#echo "* Generating SWIG C# interfaces..."
+#CWD=${PWD}
+#cd gdal/swig/csharp
+#./mkinterface.sh
+#cd ${CWD}
 
 #
 # Generate SWIG interface for Perl
diff --git a/mktestdist.sh b/mktestdist.sh
index f181900..7c7bfa2 100755
--- a/mktestdist.sh
+++ b/mktestdist.sh
@@ -12,11 +12,11 @@ GDAL_VERSION=$1
 if test "$GDAL_VERSION" != "`cat VERSION`" ; then
   echo
   echo "NOTE: local VERSION file (`cat VERSION`) does not match supplied version ($GDAL_VERSION)."
-  echo "      Consider updating local VERSION file, and committing to CVS." 
+  echo "      Consider updating local VERSION file, and committing to CVS."
   echo
 fi
 
-rm -rf dist_wrk  
+rm -rf dist_wrk
 mkdir dist_wrk
 cd dist_wrk
 
diff --git a/nmake.opt b/nmake.opt
index 1a29cca..cca273a 100644
--- a/nmake.opt
+++ b/nmake.opt
@@ -1,4 +1,4 @@
-# $Id: nmake.opt 35970 2016-10-27 11:27:30Z jef $
+# $Id: nmake.opt 37968 2017-04-12 07:16:55Z rouault $
 #
 # nmake.opt - main configuration file for NMAKE makefiles.
 #
@@ -8,11 +8,13 @@
 # nmake -f makefile.vc MSVC_VER=1500 DEBUG=1
 # nmake -f makefile.vc MSVC_VER=1600 DEBUG=1 ANALYZE=1
 # nmake -f makefile.vc MSVC_VER=1600 DEBUG=1 ANALYZE=1 WITH_PDB=1
+# nmake -f makefile.vc MSVC_VER=1400 WIN64=1
 #
 # Options:
 #    DEBUG - set to disable optimizations and link with debug runtimes; also implies WITH_PDB.
 #  ANALYZE - set to enable code analysis output.
 # WITH_PDB - set to enable output of PDB files, supported for both debug and release modes.
+#    WIN64 - set to target 64-bit architecture.
 #
 ###############################################################################
 # For convenience, user may put custom settings in a local settings file
@@ -31,6 +33,7 @@
 # Check version of Visual C++ compiler:
 # nmake -f makefile.vc MSVC_VER=xxxx
 # where xxxx is one of following:
+# 1910 = 15.0(2017)
 # 1900 = 14.0(2015)
 # 1800 = 12.0(2013)
 # 1700 = 11.0(2012)
@@ -127,9 +130,9 @@ CXX_PDB_FLAGS=
 !IFNDEF OPTFLAGS
 !IF $(MSVC_VER) >= 1400
 !IFNDEF DEBUG
-OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MD /EHsc /Ox /FC /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DNDEBUG
+OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MP /MD /EHsc /Ox /FC /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DNDEBUG
 !ELSE
-OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MD /EHsc /FC /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DDEBUG
+OPTFLAGS= $(CXX_ANALYZE_FLAGS) $(CXX_PDB_FLAGS) /nologo /MP /MD /EHsc /FC /D_CRT_SECURE_NO_DEPRECATE /D_CRT_NONSTDC_NO_DEPRECATE /DDEBUG
 !ENDIF
 !ELSE
 !IFNDEF DEBUG
@@ -151,9 +154,19 @@ OPTFLAGS= $(CXX_PDB_FLAGS) /nologo /MD /EHsc /GR /FC /DDEBUG
 # 4100: 'identifier' : unreferenced formal parameter
 # 4245: 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
 # 4206: nonstandard extension used : translation unit is empty (only applies to C source code)
+# 4351: new behavior: elements of array 'array' will be default initialized (needed for https://trac.osgeo.org/gdal/changeset/35593)
 # 4611: interaction between '_setjmp' and C++ object destruction is non-portable
 # 
-WARNFLAGS =	/W4 /wd4127 /wd4251 /wd4275 /wd4786 /wd4100 /wd4245 /wd4206 /wd4611
+WARNFLAGS =	/W4 /wd4127 /wd4251 /wd4275 /wd4786 /wd4100 /wd4245 /wd4206 /wd4351 /wd4611
+
+!IF $(MSVC_VER) >= 1500
+!IF $(MSVC_VER) < 1700
+# VS 2008 / MSVC_VER = 1500 and VS 2010 / MSVC_VER = 1600 recognizes override, but as an extension.
+# warning C4481: nonstandard extension used: override specifier 'override'
+WARNFLAGS = $(WARNFLAGS) /wd4481
+!ENDIF
+!ENDIF
+
 !ENDIF
 
 # 
@@ -161,6 +174,7 @@ WARNFLAGS =	/W4 /wd4127 /wd4251 /wd4275 /wd4786 /wd4100 /wd4245 /wd4206 /wd4611
 # 
 !IFNDEF SSEFLAGS
 SSEFLAGS = /DHAVE_SSE_AT_COMPILE_TIME
+SSSE3FLAGS = /DHAVE_SSSE3_AT_COMPILE_TIME
 #SSE_ARCH_FLAGS = /arch:SSE
 !ENDIF
 
@@ -187,6 +201,10 @@ LDEBUG= /debug
 # (x64). You'll need to have PATH, INCLUDE and LIB set up for 64-bit
 # compiles.
 #WIN64=YES
+# Capture WIN64=1 if specified in NMAKE command line
+!IFDEF WIN64
+WIN64=YES
+!ENDIF
 
 # If you don't want some entry points to have STDCALL conventions, 
 # comment out the following and add -DCPL_DISABLE_STDCALL in OPTFLAGS.
@@ -196,7 +214,7 @@ STDCALL=YES
 # Version number embedded in DLL name. 
 # If GDAL version is X.Y.Z, VERSION = X * 100 + Y
 !IFNDEF VERSION
-VERSION =	201
+VERSION =	202
 !ENDIF
 
 # Comment the following out if you want PAM supported disabled
@@ -213,7 +231,7 @@ INCLUDE_OGR_FRMTS = YES
 
 # Enable all GNM formats?  Comment out to disable
 # gnm formats.
-#INCLUDE_GNM_FRMTS = YES
+INCLUDE_GNM_FRMTS = YES
 
 # To be enabled defined to point to setargv.obj from the Visual C++ directory,
 # when you want the utility programs to be able to expand wildcards. 
@@ -314,6 +332,18 @@ JPEG12_SUPPORTED = 1
 # resulting DLLs to an appropriate place.
 #ECW_PLUGIN = YES
 
+
+# Uncomment the following and update to enable JP2Lura driver
+#LURATECH_CFLAGS = -Ic:\jp2_csdk_2.16_win64\include
+#LURATECH_LIB = c:\jp2_csdk_2.16_win64\library\lwf_jp2.lib
+
+# To build JP2Lura support as a plugin uncomment the following, and make sure
+# to do "nmake /f makefile.vc plugin" in gdal/frmts/jp2lura and copy the two
+# resulting DLLs to an appropriate place.
+#JP2LURA_PLUGIN = YES
+
+
+
 # Uncomment the following and update to enable ECW support with the 3.3 SDK.
 # Significant adaption may be needed.
 #ECWDIR  = 	C:\warmerda\libecwj2-3.3
@@ -328,13 +358,24 @@ JPEG12_SUPPORTED = 1
 #TD_BASE = C:\warmerda\pkg\td_vc9
 #TD_FLAGS = -D_TOOLKIT_IN_DLL_
 #TD_INCLUDE = -I$(TD_BASE)\TD\Include -I$(TD_BASE)\TD\Extensions\ExServices
-#TD_LIBDIR = $(TD_BASE)\lib\vc9dll
+# The following works for Teigha 4.2.2
+#TD_INCLUDE = -I$(TD_BASE)\Core\Include -I$(TD_BASE)\Core\Extensions\ExServices -I$(TD_BASE)\Dgn\include -I$(TD_BASE)\Dgn\Extensions\ExServices
+#TD_LIBDIR = $(TD_BASE)\lib\vc14dll
+#TD_LIBS =  \
+#	$(TD_LIBDIR)/TD_Key.lib \
+#	$(TD_LIBDIR)/TD_ExamplesCommon.lib \
+#	$(TD_LIBDIR)/TD_Db.lib \
+#	$(TD_LIBDIR)/TD_DbRoot.lib \
+#	$(TD_LIBDIR)/TD_Root.lib \
+#	$(TD_LIBDIR)/TD_Ge.lib \
+#	$(TD_LIBDIR)/TD_Alloc.lib \
+#	$(TD_LIBDIR)/TG_Db.lib \
+#	$(TD_LIBDIR)/TG_ExamplesCommon.lib \
+#	advapi32.lib
+
+# Uncomment to build as a plugin
+#TD_PLUGIN = YES
 
-# DWG/DXF support via DWGdirect from Open Design Alliance
-
-#DWGDIRECT=C:\warmerda\DWGdirect
-#DWG_LIB_DIR=$(DWGDIRECT)\lib\VC6MD
-#DWG_LIB=$(DWG_LIB_DIR)\DD_AcisBuilder_dll.lib $(DWG_LIB_DIR)\DD_AcisRenderer_dll.lib $(DWG_LIB_DIR)\DD_Alloc_dll.lib $(DWG_LIB_DIR)\DD_BmpExport_dll.lib $(DWG_LIB_DIR)\DD_Br_dll.lib $(DWG_LIB_DIR)\DD_Db_dll.lib $(DWG_LIB_DIR)\DD_DwfExport_dll.lib $(DWG_LIB_DIR)\DD_DwfImport_dll.lib $(DWG_LIB_DIR)\DD_Ge_dll.lib $(DWG_LIB_DIR)\DD_Gi_dll.lib $(DWG_LIB_DIR)\DD_Gs_dll.lib $(DWG_LIB_DIR)\DD_ModelerGeometry_dll.lib $(DWG_LIB_DIR)\DD_Root_dll.lib $(DWG_LIB_DIR)\DD_Sm_dll.lib $(DWG_LIB_DIR)\DD_S [...]
 
 # Uncomment the following and update to enable OGDI support.
 #OGDIDIR =	D:\warmerda\iii\devdir
@@ -349,11 +390,11 @@ JPEG12_SUPPORTED = 1
 #EXPAT_LIB = $(EXPAT_DIR)/bin/libexpat.lib
 
 # Uncomment for Xerces based GML and ILI support.
-#XERCES_DIR =	c:\warmerda\supportlibs\xerces-c_2_6_0
+#XERCES_DIR =	c:\warmerda\supportlibs\xerces-c_3_1_3
 #XERCES_INCLUDE = -I$(XERCES_DIR)/include -I$(XERCES_DIR)/include/xercesc
-#XERCES_LIB = $(XERCES_DIR)/lib/xerces-c_2.lib
+#XERCES_LIB = $(XERCES_DIR)/lib/xerces-c_3.lib
 
-# Uncomment the following for Interlis support.  Note that a Xercex 2.x
+# Uncomment the following for Interlis support.  Note that a Xercex 3.x
 # is also required (see above).  Also, Interlis support only works with
 # Visual Studio.NET or newer, not VC6.
 #ILI_ENABLED = YES
@@ -378,6 +419,7 @@ JPEG12_SUPPORTED = 1
 #HDF4_PLUGIN = NO
 #HDF4_DIR =	D:\warmerda\HDF41r5
 #HDF4_LIB =	/LIBPATH:$(HDF4_DIR)\lib Ws2_32.lib
+#HDF4_INCLUDE = $(HDF4_DIR)\include
 # HDF4 library newer than 4.2.5 has a SDreset_maxopenfiles/SDget_maxopenfiles
 # interface which allows opening many HDF files simultaneously (the max
 # number of files was previously hardcoded and too low, smth. like 32).
@@ -444,7 +486,9 @@ INGRES_LIB = "$(INGRES_HOME)\lib\iilibapi.lib" \
 # For spatialite support, try this instead (assuming you grab the libspatialite-amalgamation-2.3.1 and installed it in osgeo4w):
 # The -DSPATIALITE_AMALGAMATION, which cause "spatialite/sqlite3.h" to be included instead of "sqlite3.h" might not be necessary
 # depending on the layout of the include directories. In case of compilation errors, remove it.
+# For RasterLite2 support, add something like -Ic:\install-rl2\include -DHAVE_RASTERLITE2
 #SQLITE_INC=-IC:\osgeo4w\include -DHAVE_SPATIALITE -DSPATIALITE_AMALGAMATION
+# For RasterLite2 support, add something like c:\install-rl2\lib\librasterlite2.lib
 #SQLITE_LIB=C:\osgeo4w\lib\spatialite_i.lib
 # Uncomment following line if libsqlite3 has been compiled with SQLITE_HAS_COLUMN_METADATA=yes
 #SQLITE_HAS_COLUMN_METADATA=yes
@@ -566,6 +610,11 @@ OCI_INCLUDE =	-I$(ORACLE_HOME)\oci\include
 # For OpenJpeg >= 2.1, uncomment
 #OPENJPEG_VERSION = 20100
 
+#if using an external zlib uncomment the following lines
+#ZLIB_EXTERNAL_LIB = 1
+#ZLIB_INC = -IC:\projects\zlib
+#ZLIB_LIB = C:\projects\lib\Release\zlib.lib
+
 # Uncomment for PDF support
 # Uncomment POPPLER_BASE_STREAM_HAS_TWO_ARGS = YES for Poppler >= 0.16.0
 # Uncomment POPPLER_0_20_OR_LATER = YES for Poppler >= 0.20.0
@@ -716,10 +765,6 @@ MSVC_VLD_LIB=/LIBPATH:$(MSVC_VLD_DIR)/lib/Win32
 !ENDIF
 !ENDIF
 
-!IFDEF INCLUDE_OGR_FRMTS
-OGR_FLAG = -DOGR_ENABLED
-!ENDIF
-
 !IFDEF INCLUDE_GNM_FRMTS
 GNM_FLAG = -DGNM_ENABLED
 !ENDIF
@@ -728,8 +773,8 @@ GNM_FLAG = -DGNM_ENABLED
 LINKER_FLAGS = $(EXTRA_LINKER_FLAGS) $(MSVC_VLD_LIB) $(LDEBUG)
 
 
-CFLAGS	=	$(OPTFLAGS) $(WARNFLAGS) $(USER_DEFS) $(SSEFLAGS) $(INC) $(AVXFLAGS) $(EXTRAFLAGS) $(OGR_FLAG) $(GNM_FLAG) $(MSVC_VLD_FLAGS) -DGDAL_COMPILATION
-CPPFLAGS = $(CFLAGS) 
+CFLAGS	=	$(OPTFLAGS) $(WARNFLAGS) $(USER_DEFS) $(SSEFLAGS) $(SSSE3FLAGS) $(INC) $(AVXFLAGS) $(EXTRAFLAGS) $(OGR_FLAG) $(GNM_FLAG) $(MSVC_VLD_FLAGS) -DGDAL_COMPILATION
+CPPFLAGS = $(CFLAGS) -DNOMINMAX
 MAKE	=	nmake /nologo
 
 !IFNDEF CC
@@ -771,6 +816,14 @@ ECW_LIB_LINK=
 !ENDIF
 !ENDIF
 
+!IFDEF LURATECH_CFLAGS
+!IF "$(JP2LURA_PLUGIN)" != "YES"
+LURATECH_LIB_LINK= $(LURATECH_LIB)
+!ELSE
+LURATECH_LIB_LINK=
+!ENDIF
+!ENDIF
+
 !IFDEF FITS_LIB
 !IF "$(FITS_PLUGIN)" != "YES"
 FITS_LIB_LINK = $(FITS_LIB)
@@ -855,6 +908,14 @@ MONGODB_LIB_LINK =
 NAS_ENABLED = YES
 !ENDIF
 
+!IFDEF TD_LIBS
+!IF "$(TD_PLUGIN)" != "YES"
+DWG_LIB_LINK = $(TD_LIBS)
+!ELSE
+DWG_LIB_LINK =
+!ENDIF
+!ENDIF
+
 # Under win64, symbols for function names lack the underscore prefix
 # present on win32. Also the STDCALL calling convention is not used.
 !IFDEF WIN64
@@ -864,12 +925,13 @@ SYM_PREFIX=_
 !ENDIF
 
 EXTERNAL_LIBS =	$(OGDILIB) $(XERCES_LIB) $(EXPAT_LIB) $(OCI_LIB) $(PG_LIB) \
-	$(ECW_LIB_LINK) $(HDF4_LIB_LINK) $(FME_LIB) $(MRSID_LIB_LINK) \
+	$(ECW_LIB_LINK) $(LURATECH_LIB_LINK) $(HDF4_LIB_LINK) $(FME_LIB) $(MRSID_LIB_LINK) \
 	$(FITS_LIB_LINK) $(JPEG_LIB) $(NETCDF_LIB_LINK) $(PROJ4_LIB) \
 	$(GEOTIFF_LIB) $(TIFF_LIB) $(PROJ_LIBRARY) $(SQLITE_LIB) \
-	$(MYSQL_LIB) $(GEOS_LIB) $(HDF5_LIB_LINK) $(KEA_LIB_LINK) $(SDE_LIB) $(ARCOBJECTS_LIB) $(DWG_LIB) \
+	$(MYSQL_LIB) $(GEOS_LIB) $(HDF5_LIB_LINK) $(KEA_LIB_LINK) $(SDE_LIB) $(ARCOBJECTS_LIB) $(DWG_LIB_LINK) \
 	$(IDB_LIB) $(CURL_LIB) $(DODS_LIB) $(KAKLIB) $(PCIDSK_LIB) \
-	$(ODBCLIB) $(JASPER_LIB) $(PNG_LIB) $(ADD_LIBS) $(OPENJPEG_LIB) \
+	$(ODBCLIB) $(JASPER_LIB) $(PNG_LIB) $(ZLIB_LIB) $(ADD_LIBS) $(OPENJPEG_LIB) \
 	$(MRSID_LIDAR_LIB) $(LIBKML_LIBS) $(SOSI_LIBS) $(PDF_LIB_LINK) $(LZMA_LIBS) \
 	$(LIBICONV_LIBRARY) $(WEBP_LIBS) $(FGDB_LIB_LINK) $(FREEXL_LIBS) $(GTA_LIBS) \
-	$(INGRES_LIB) $(LIBXML2_LIB) $(PCRE_LIB) $(MONGODB_LIB_LINK) $(CRYPTOPP_LIB) ws2_32.lib
+	$(INGRES_LIB) $(LIBXML2_LIB) $(PCRE_LIB) $(MONGODB_LIB_LINK) $(CRYPTOPP_LIB) ws2_32.lib \
+    kernel32.lib psapi.lib
diff --git a/ogr/Doxyfile b/ogr/Doxyfile
index 8ab3954..9b021fa 100644
--- a/ogr/Doxyfile
+++ b/ogr/Doxyfile
@@ -14,198 +14,198 @@
 # Project related configuration options
 #---------------------------------------------------------------------------
 
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
 # by quotes) that should identify the project.
 
 PROJECT_NAME           = OGR
 
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
-# This could be handy for archiving the generated documentation or 
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 
+PROJECT_NUMBER         =
 
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
 # where doxygen was started. If left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = 
+OUTPUT_DIRECTORY       =
 
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
-# 4096 sub-directories (in 2 levels) under the output directory of each output 
-# format and will distribute the generated files over these directories. 
-# Enabling this option can be useful when feeding doxygen a huge amount of 
-# source files, where putting all generated files in the same directory would 
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
 # otherwise cause performance problems for the file system.
 
 CREATE_SUBDIRS         = NO
 
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
-# documentation generated by doxygen is written. Doxygen will use this 
-# information to generate all constant output in the proper language. 
-# The default language is English, other supported languages are: 
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
-# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
-# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
-# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
 # Swedish, and Ukrainian.
 
 OUTPUT_LANGUAGE        = English
 
-# This tag can be used to specify the encoding used in the generated output. 
-# The encoding is not always determined by the language that is chosen, 
-# but also whether or not the output is meant for Windows or non-Windows users. 
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
-# forces the Windows encoding (this is the default for the Windows binary), 
-# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
 # all platforms other than Windows).
 
 USE_WINDOWS_ENCODING   = NO
 
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
-# include brief member descriptions after the members that are listed in 
-# the file and class documentation (similar to JavaDoc). 
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
 # Set to NO to disable this.
 
 BRIEF_MEMBER_DESC      = YES
 
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
-# the brief description of a member or function before the detailed description. 
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
 # brief descriptions will be completely suppressed.
 
 REPEAT_BRIEF           = YES
 
-# This tag implements a quasi-intelligent brief description abbreviator 
-# that is used to form the text in various listings. Each string 
-# in this list, if found as the leading text of the brief description, will be 
-# stripped from the text and the result after processing the whole list, is 
-# used as the annotated text. Otherwise, the brief description is used as-is. 
-# If left blank, the following values are used ("$name" is automatically 
-# replaced with the name of the entity): "The $name class" "The $name widget" 
-# "The $name file" "is" "provides" "specifies" "contains" 
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
 # "represents" "a" "an" "the"
 
-ABBREVIATE_BRIEF       = 
+ABBREVIATE_BRIEF       =
 
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
-# Doxygen will generate a detailed section even if there is only a brief 
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
 # description.
 
 ALWAYS_DETAILED_SEC    = NO
 
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
-# inherited members of a class in the documentation of that class as if those 
-# members were ordinary class members. Constructors, destructors and assignment 
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
 # operators of the base classes will not be shown.
 
 INLINE_INHERITED_MEMB  = NO
 
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
-# path before files name in the file list and in the header files. If set 
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
 # to NO the shortest path that makes the file name unique will be used.
 
 FULL_PATH_NAMES        = NO
 
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
-# can be used to strip a user-defined part of the path. Stripping is 
-# only done if one of the specified strings matches the left-hand part of 
-# the path. The tag can be used to show relative paths in the file list. 
-# If left blank the directory from which doxygen is run is used as the 
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
 # path to strip.
 
-STRIP_FROM_PATH        = 
+STRIP_FROM_PATH        =
 
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
-# the path mentioned in the documentation of a class, which tells 
-# the reader which header file to include in order to use a class. 
-# If left blank only the name of the header file containing the class 
-# definition is used. Otherwise one should specify the include paths that 
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
 # are normally passed to the compiler using the -I flag.
 
-STRIP_FROM_INC_PATH    = 
+STRIP_FROM_INC_PATH    =
 
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
-# (but less readable) file names. This can be useful is your file systems 
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
 # doesn't support long names like on DOS, Mac, or CD-ROM.
 
 SHORT_NAMES            = NO
 
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
-# will interpret the first line (until the first dot) of a JavaDoc-style 
-# comment as the brief description. If set to NO, the JavaDoc 
-# comments will behave just like the Qt-style comments (thus requiring an 
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
 # explicit @brief command for a brief description.
 
 JAVADOC_AUTOBRIEF      = NO
 
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
-# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
-# comments) as a brief description. This used to be the default behaviour. 
-# The new default is to treat a multi-line C++ comment block as a detailed 
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
 # description. Set this tag to YES if you prefer the old behaviour instead.
 
 MULTILINE_CPP_IS_BRIEF = NO
 
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
 # will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member 
+# If set to NO, the detailed description appears after the member
 # documentation.
 
 DETAILS_AT_TOP         = NO
 
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
-# member inherits the documentation from any documented member that it 
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
 # re-implements.
 
 INHERIT_DOCS           = YES
 
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
 # all members of a group must be documented explicitly.
 
 DISTRIBUTE_GROUP_DOC   = NO
 
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
-# a new page for each member. If set to NO, the documentation of a member will 
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
 # be part of the file/class/namespace that contains it.
 
 SEPARATE_MEMBER_PAGES  = NO
 
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
 # Doxygen uses this value to replace tabs by spaces in code fragments.
 
 TAB_SIZE               = 8
 
-# This tag can be used to specify a number of aliases that acts 
-# as commands in the documentation. An alias has the form "name=value". 
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
-# put the command \sideeffect (or @sideeffect) in the documentation, which 
-# will result in a user-defined paragraph with heading "Side Effects:". 
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
 # You can put \n's in the value part of an alias to insert newlines.
 
-ALIASES                = 
+ALIASES                =
 
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
-# sources only. Doxygen will then generate output that is more tailored for C. 
-# For instance, some of the names that are used will be different. The list 
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
 # of all members will be omitted, etc.
 
 OPTIMIZE_OUTPUT_FOR_C  = NO
 
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
-# only. Doxygen will then generate output that is more tailored for Java. 
-# For instance, namespaces will be presented as packages, qualified scopes 
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
 # will look different, etc.
 
 OPTIMIZE_OUTPUT_JAVA   = NO
 
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
-# the same type (for instance a group of public functions) to be put as a 
-# subgroup of that type (e.g. under the Public Functions section). Set it to 
-# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
 # the \nosubgrouping command.
 
 SUBGROUPING            = YES
@@ -214,240 +214,240 @@ SUBGROUPING            = YES
 # Build related configuration options
 #---------------------------------------------------------------------------
 
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
-# documentation are documented, even if no documentation was available. 
-# Private class members and static file members will be hidden unless 
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
 # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
 
 EXTRACT_ALL            = NO
 
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
 # will be included in the documentation.
 
 EXTRACT_PRIVATE        = NO
 
-# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
 # will be included in the documentation.
 
 EXTRACT_STATIC         = NO
 
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
-# defined locally in source files will be included in the documentation. 
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
 # If set to NO only classes defined in header files are included.
 
 EXTRACT_LOCAL_CLASSES  = YES
 
-# This flag is only useful for Objective-C code. When set to YES local 
-# methods, which are defined in the implementation section but not in 
-# the interface are included in the documentation. 
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
 # If set to NO (the default) only methods in the interface are included.
 
 EXTRACT_LOCAL_METHODS  = NO
 
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
-# undocumented members of documented classes, files or namespaces. 
-# If set to NO (the default) these members will be included in the 
-# various overviews, but no documentation section is generated. 
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
 # This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_MEMBERS     = YES
 
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
-# undocumented classes that are normally visible in the class hierarchy. 
-# If set to NO (the default) these classes will be included in the various 
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
 # overviews. This option has no effect if EXTRACT_ALL is enabled.
 
 HIDE_UNDOC_CLASSES     = NO
 
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
-# friend (class|struct|union) declarations. 
-# If set to NO (the default) these declarations will be included in the 
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
 # documentation.
 
 HIDE_FRIEND_COMPOUNDS  = NO
 
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
-# documentation blocks found inside the body of a function. 
-# If set to NO (the default) these blocks will be appended to the 
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
 # function's detailed documentation block.
 
 HIDE_IN_BODY_DOCS      = NO
 
-# The INTERNAL_DOCS tag determines if documentation 
-# that is typed after a \internal command is included. If the tag is set 
-# to NO (the default) then the documentation will be excluded. 
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
 # Set it to YES to include the internal documentation.
 
 INTERNAL_DOCS          = NO
 
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
-# file names in lower-case letters. If set to YES upper-case letters are also 
-# allowed. This is useful if you have classes or files whose names only differ 
-# in case and if your file system supports case sensitive file names. Windows 
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
 # and Mac users are advised to set this option to NO.
 
 CASE_SENSE_NAMES       = YES
 
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
-# will show members with their full class and namespace scopes in the 
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
 # documentation. If set to YES the scope will be hidden.
 
 HIDE_SCOPE_NAMES       = NO
 
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
-# will put a list of the files that are included by a file in the documentation 
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
 # of that file.
 
 SHOW_INCLUDE_FILES     = YES
 
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
 # is inserted in the documentation for inline members.
 
 INLINE_INFO            = YES
 
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
-# will sort the (detailed) documentation of file and class members 
-# alphabetically by member name. If set to NO the members will appear in 
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
 # declaration order.
 
 SORT_MEMBER_DOCS       = YES
 
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
-# brief documentation of file, namespace and class members alphabetically 
-# by member name. If set to NO (the default) the members will appear in 
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
 # declaration order.
 
 SORT_BRIEF_DOCS        = NO
 
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
-# sorted by fully-qualified names, including namespaces. If set to 
-# NO (the default), the class list will be sorted only by class name, 
-# not including the namespace part. 
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
 # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the 
+# Note: This option applies only to the class list, not to the
 # alphabetical list.
 
 SORT_BY_SCOPE_NAME     = NO
 
-# The GENERATE_TODOLIST tag can be used to enable (YES) or 
-# disable (NO) the todo list. This list is created by putting \todo 
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
 # commands in the documentation.
 
 GENERATE_TODOLIST      = YES
 
-# The GENERATE_TESTLIST tag can be used to enable (YES) or 
-# disable (NO) the test list. This list is created by putting \test 
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
 # commands in the documentation.
 
 GENERATE_TESTLIST      = YES
 
-# The GENERATE_BUGLIST tag can be used to enable (YES) or 
-# disable (NO) the bug list. This list is created by putting \bug 
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
 # commands in the documentation.
 
 GENERATE_BUGLIST       = YES
 
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
-# disable (NO) the deprecated list. This list is created by putting 
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
 # \deprecated commands in the documentation.
 
 GENERATE_DEPRECATEDLIST= YES
 
-# The ENABLED_SECTIONS tag can be used to enable conditional 
+# The ENABLED_SECTIONS tag can be used to enable conditional
 # documentation sections, marked by \if sectionname ... \endif.
 
-ENABLED_SECTIONS       = 
+ENABLED_SECTIONS       =
 
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
-# the initial value of a variable or define consists of for it to appear in 
-# the documentation. If the initializer consists of more lines than specified 
-# here it will be hidden. Use a value of 0 to hide initializers completely. 
-# The appearance of the initializer of individual variables and defines in the 
-# documentation can be controlled using \showinitializer or \hideinitializer 
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
 # command in the documentation regardless of this setting.
 
 MAX_INITIALIZER_LINES  = 30
 
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
-# at the bottom of the documentation of classes and structs. If set to YES the 
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
 # list will mention the files that were used to generate the documentation.
 
 SHOW_USED_FILES        = YES
 
-# If the sources in your project are distributed over multiple directories 
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
 # in the documentation.
 
 SHOW_DIRECTORIES       = YES
 
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
-# doxygen should invoke to get the current version for each file (typically from the 
-# version control system). Doxygen will invoke the program by executing (via 
-# popen()) the command <command> <input-file>, where <command> is the value of 
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
-# provided by doxygen. Whatever the progam writes to standard output 
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the progam writes to standard output
 # is used as the file version. See the manual for examples.
 
-FILE_VERSION_FILTER    = 
+FILE_VERSION_FILTER    =
 
 #---------------------------------------------------------------------------
 # configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
 
-# The QUIET tag can be used to turn on/off the messages that are generated 
+# The QUIET tag can be used to turn on/off the messages that are generated
 # by doxygen. Possible values are YES and NO. If left blank NO is used.
 
 QUIET                  = YES
 
-# The WARNINGS tag can be used to turn on/off the warning messages that are 
-# generated by doxygen. Possible values are YES and NO. If left blank 
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
 # NO is used.
 
 WARNINGS               = YES
 
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
 # automatically be disabled.
 
 WARN_IF_UNDOCUMENTED   = YES
 
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
-# potential errors in the documentation, such as not documenting some 
-# parameters in a documented function, or documenting parameters that 
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
 # don't exist or using markup commands wrongly.
 
 WARN_IF_DOC_ERROR      = YES
 
-# This WARN_NO_PARAMDOC option can be enabled to get warnings for 
-# functions that are documented, but have no documentation for their parameters 
-# or return value. If set to NO (the default) doxygen will only warn about 
-# wrong or incomplete parameter documentation, but not about the absence of 
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
 # documentation.
 
 WARN_NO_PARAMDOC       = NO
 
-# The WARN_FORMAT tag determines the format of the warning messages that 
-# doxygen can produce. The string should contain the $file, $line, and $text 
-# tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text. Optionally the format may contain 
-# $version, which will be replaced by the version of the file (if it could 
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
 # be obtained via FILE_VERSION_FILTER)
 
 WARN_FORMAT            = "$file:$line: $text"
 
-# The WARN_LOGFILE tag can be used to specify a file to which warning 
-# and error messages should be written. If left blank the output is written 
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
 # to stderr.
 
-WARN_LOGFILE           = 
+WARN_LOGFILE           =
 
 #---------------------------------------------------------------------------
 # configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag can be used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
 INPUT                  = . \
@@ -457,11 +457,11 @@ INPUT                  = . \
                          ogrsf_frmts/kml/ogr2kmlgeometry.cpp \
                          ../port
 
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank the following patterns are tested: 
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
 # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
 
 FILE_PATTERNS          = *.h \
@@ -469,77 +469,77 @@ FILE_PATTERNS          = *.h \
                          *.c \
                          *.dox
 
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
-# should be searched for input files as well. Possible values are YES and NO. 
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
 # If left blank NO is used.
 
 RECURSIVE              = NO
 
-# The EXCLUDE tag can be used to specify files and/or directories that should 
-# excluded from the INPUT source files. This way you can easily exclude a 
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
 # subdirectory from a directory tree whose root is specified with the INPUT tag.
 
-EXCLUDE                = 
+EXCLUDE                =
 
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
-# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
 # from the input.
 
 EXCLUDE_SYMLINKS       = NO
 
-# If the value of the INPUT tag contains directories, you can use the 
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
 # certain files from those directories.
 
-EXCLUDE_PATTERNS       = 
+EXCLUDE_PATTERNS       =
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
 # the \include command).
 
 EXAMPLE_PATH           = .
 
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
 # blank all files are included.
 
-EXAMPLE_PATTERNS       = 
+EXAMPLE_PATTERNS       =
 
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
-# searched for input files to be used with the \include or \dontinclude 
-# commands irrespective of the value of the RECURSIVE tag. 
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
 # Possible values are YES and NO. If left blank NO is used.
 
 EXAMPLE_RECURSIVE      = NO
 
-# The IMAGE_PATH tag can be used to specify one or more files or 
-# directories that contain image that are included in the documentation (see 
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
 # the \image command).
 
-IMAGE_PATH             = 
+IMAGE_PATH             =
 
-# The INPUT_FILTER tag can be used to specify a program that doxygen should 
-# invoke to filter for each input file. Doxygen will invoke the filter program 
-# by executing (via popen()) the command <filter> <input-file>, where <filter> 
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
-# input file. Doxygen will then use the output that the filter program writes 
-# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
 # ignored.
 
-INPUT_FILTER           = 
+INPUT_FILTER           =
 
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
-# basis.  Doxygen will compare the file name with each pattern and apply the 
-# filter if there is a match.  The filters are a list of the form: 
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.  Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.  The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
 # is applied to all files.
 
-FILTER_PATTERNS        = 
+FILTER_PATTERNS        =
 
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
-# INPUT_FILTER) will be used to filter the input files when producing source 
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
 # files to browse (i.e. when SOURCE_BROWSER is set to YES).
 
 FILTER_SOURCE_FILES    = NO
@@ -548,47 +548,47 @@ FILTER_SOURCE_FILES    = NO
 # configuration options related to source browsing
 #---------------------------------------------------------------------------
 
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-# Note: To get rid of all source code in the generated output, make sure also 
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
 # VERBATIM_HEADERS is set to NO.
 
 SOURCE_BROWSER         = NO
 
-# Setting the INLINE_SOURCES tag to YES will include the body 
+# Setting the INLINE_SOURCES tag to YES will include the body
 # of functions and classes directly in the documentation.
 
 INLINE_SOURCES         = NO
 
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
-# doxygen to hide any special comment blocks from generated source code 
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
 # fragments. Normal C and C++ comments will always remain visible.
 
 STRIP_CODE_COMMENTS    = YES
 
-# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
-# then for each documented function all documented 
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
 # functions referencing it will be listed.
 
 REFERENCED_BY_RELATION = YES
 
-# If the REFERENCES_RELATION tag is set to YES (the default) 
-# then for each documented function all documented entities 
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
 # called/used by that function will be listed.
 
 REFERENCES_RELATION    = YES
 
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
-# link to the source code.  Otherwise they will link to the documentation. 
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentation.
 #
 # http://trac.osgeo.org/gdal/ticket/2723
 
-REFERENCES_LINK_SOURCE = NO 
+REFERENCES_LINK_SOURCE = NO
 
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
-# will generate a verbatim copy of the header file for each class for 
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
 # which an include is specified. Set to NO to disable this.
 
 VERBATIM_HEADERS       = YES
@@ -597,133 +597,133 @@ VERBATIM_HEADERS       = YES
 # configuration options related to the alphabetical class index
 #---------------------------------------------------------------------------
 
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
-# of all compounds will be generated. Enable this if the project 
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
 # contains a lot of classes, structs, unions or interfaces.
 
 ALPHABETICAL_INDEX     = NO
 
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
 # in which this list will be split (can be a number in the range [1..20])
 
 COLS_IN_ALPHA_INDEX    = 5
 
-# In case all classes in a project start with a common prefix, all 
-# classes will be put under the same header in the alphabetical index. 
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
 # should be ignored while generating the index headers.
 
-IGNORE_PREFIX          = 
+IGNORE_PREFIX          =
 
 #---------------------------------------------------------------------------
 # configuration options related to the HTML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
 # generate HTML output.
 
 GENERATE_HTML          = YES
 
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `html' will be used as the default path.
 
-HTML_OUTPUT            = 
+HTML_OUTPUT            =
 
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
 # doxygen will generate files with .html extension.
 
 HTML_FILE_EXTENSION    = .html
 
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard header.
 
-HTML_HEADER            = 
+HTML_HEADER            =
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard footer.
 
 HTML_FOOTER            = ../doc/gdal_footer.html
 
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
-# style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet. Note that doxygen will try to copy 
-# the style sheet file to the HTML output directory, so don't put your own 
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
 # stylesheet in the HTML output directory as well, or it will be erased!
 
-HTML_STYLESHEET        = 
+HTML_STYLESHEET        =
 
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
 # NO a bullet list will be used.
 
 HTML_ALIGN_MEMBERS     = YES
 
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
-# will be generated that can be used as input for tools like the 
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
 # of the generated HTML documentation.
 
 GENERATE_HTMLHELP      = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
-# be used to specify the file name of the resulting .chm file. You 
-# can add a path in front of the file if the result should not be 
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
 # written to the html output directory.
 
-CHM_FILE               = 
+CHM_FILE               =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
-# be used to specify the location (absolute path including file name) of 
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
 # the HTML help compiler on the generated index.hhp.
 
-HHC_LOCATION           = 
+HHC_LOCATION           =
 
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
-# controls if a separate .chi index file is generated (YES) or that 
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
 # it should be included in the master .chm file (NO).
 
 GENERATE_CHI           = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
-# controls whether a binary table of contents is generated (YES) or a 
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
 # normal table of contents (NO) in the .chm file.
 
 BINARY_TOC             = NO
 
-# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
 # to the contents of the HTML help documentation and to the tree view.
 
 TOC_EXPAND             = NO
 
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
 # the value YES disables it.
 
 DISABLE_INDEX          = NO
 
-# This tag can be used to set the number of enum values (range [1..20]) 
+# This tag can be used to set the number of enum values (range [1..20])
 # that doxygen will group on one line in the generated HTML documentation.
 
 ENUM_VALUES_PER_LINE   = 4
 
 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that 
-# is generated for HTML Help). For this to work a browser that supports 
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
 # probably better off using the HTML help feature.
 
 GENERATE_TREEVIEW      = NO
 
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
-# used to set the initial width (in pixels) of the frame in which the tree 
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
 # is shown.
 
 TREEVIEW_WIDTH         = 250
@@ -732,74 +732,74 @@ TREEVIEW_WIDTH         = 250
 # configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
 # generate Latex output.
 
 GENERATE_LATEX         = NO
 
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `latex' will be used as the default path.
 
-LATEX_OUTPUT           = 
+LATEX_OUTPUT           =
 
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
 # invoked. If left blank `latex' will be used as the default command name.
 
 LATEX_CMD_NAME         = latex
 
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
-# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
 # default command name.
 
 MAKEINDEX_CMD_NAME     = makeindex
 
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
-# LaTeX documents. This may be useful for small projects and may help to 
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
 # save some trees in general.
 
 COMPACT_LATEX          = NO
 
-# The PAPER_TYPE tag can be used to set the paper type that is used 
-# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
 # executive. If left blank a4wide will be used.
 
 PAPER_TYPE             = a4wide
 
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
 # packages that should be included in the LaTeX output.
 
-EXTRA_PACKAGES         = 
+EXTRA_PACKAGES         =
 
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
-# the generated latex document. The header should contain everything until 
-# the first chapter. If it is left blank doxygen will generate a 
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
 # standard header. Notice: only use this tag if you know what you are doing!
 
-LATEX_HEADER           = 
+LATEX_HEADER           =
 
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
-# contain links (just like the HTML output) instead of page references 
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
 # This makes the output suitable for online browsing using a pdf viewer.
 
 PDF_HYPERLINKS         = NO
 
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
-# plain latex in the generated Makefile. Set this option to YES to get a 
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
 # higher quality PDF documentation.
 
 USE_PDFLATEX           = NO
 
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
-# command to the generated LaTeX files. This will instruct LaTeX to keep 
-# running if errors occur, instead of asking the user for help. 
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
 # This option is also used when generating formulas in HTML.
 
 LATEX_BATCHMODE        = NO
 
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
-# include the index chapters (such as File Index, Compound Index, etc.) 
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
 # in the output.
 
 LATEX_HIDE_INDICES     = NO
@@ -808,68 +808,68 @@ LATEX_HIDE_INDICES     = NO
 # configuration options related to the RTF output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
-# The RTF output is optimized for Word 97 and may not look very pretty with 
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
 # other RTF readers or editors.
 
 GENERATE_RTF           = NO
 
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `rtf' will be used as the default path.
 
 RTF_OUTPUT             = rtf
 
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
-# RTF documents. This may be useful for small projects and may help to 
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
 # save some trees in general.
 
 COMPACT_RTF            = NO
 
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
-# will contain hyperlink fields. The RTF file will 
-# contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using WORD or other 
-# programs which support those fields. 
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
 # Note: wordpad (write) and others do not support links.
 
 RTF_HYPERLINKS         = NO
 
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
-# config file, i.e. a series of assignments. You only have to provide 
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
 # replacements, missing definitions are set to their default value.
 
-RTF_STYLESHEET_FILE    = 
+RTF_STYLESHEET_FILE    =
 
-# Set optional variables used in the generation of an rtf document. 
+# Set optional variables used in the generation of an rtf document.
 # Syntax is similar to doxygen's config file.
 
-RTF_EXTENSIONS_FILE    = 
+RTF_EXTENSIONS_FILE    =
 
 #---------------------------------------------------------------------------
 # configuration options related to the man page output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
 # generate man pages
 
 GENERATE_MAN           = NO
 
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `man' will be used as the default path.
 
 MAN_OUTPUT             = man
 
-# The MAN_EXTENSION tag determines the extension that is added to 
+# The MAN_EXTENSION tag determines the extension that is added to
 # the generated man pages (default is the subroutine's section .3)
 
 MAN_EXTENSION          = .3
 
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
-# then it will generate one additional man file for each entity 
-# documented in the real man page(s). These additional files 
-# only source the real man page, but without them the man command 
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
 # would be unable to find the correct page. The default is NO.
 
 MAN_LINKS              = NO
@@ -878,33 +878,33 @@ MAN_LINKS              = NO
 # configuration options related to the XML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_XML tag is set to YES Doxygen will 
-# generate an XML file that captures the structure of 
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
 # the code including all documentation.
 
 GENERATE_XML           = NO
 
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
 # put in front of it. If left blank `xml' will be used as the default path.
 
 XML_OUTPUT             = xml
 
-# The XML_SCHEMA tag can be used to specify an XML schema, 
-# which can be used by a validating XML parser to check the 
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
 # syntax of the XML files.
 
-XML_SCHEMA             = 
+XML_SCHEMA             =
 
-# The XML_DTD tag can be used to specify an XML DTD, 
-# which can be used by a validating XML parser to check the 
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
 # syntax of the XML files.
 
-XML_DTD                = 
+XML_DTD                =
 
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
-# dump the program listings (including syntax highlighting 
-# and cross-referencing information) to the XML output. Note that 
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
 # enabling this will significantly increase the size of the XML output.
 
 XML_PROGRAMLISTING     = YES
@@ -913,10 +913,10 @@ XML_PROGRAMLISTING     = YES
 # configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
-# generate an AutoGen Definitions (see autogen.sf.net) file 
-# that captures the structure of the code including all 
-# documentation. Note that this feature is still experimental 
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
 # and incomplete at the moment.
 
 GENERATE_AUTOGEN_DEF   = NO
@@ -925,82 +925,82 @@ GENERATE_AUTOGEN_DEF   = NO
 # configuration options related to the Perl module output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
-# generate a Perl module file that captures the structure of 
-# the code including all documentation. Note that this 
-# feature is still experimental and incomplete at the 
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
 # moment.
 
 GENERATE_PERLMOD       = NO
 
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
 # to generate PDF and DVI output from the Perl module output.
 
 PERLMOD_LATEX          = NO
 
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
-# nicely formatted so it can be parsed by a human reader.  This is useful 
-# if you want to understand what is going on.  On the other hand, if this 
-# tag is set to NO the size of the Perl module output will be much smaller 
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
 # and Perl will parse it just the same.
 
 PERLMOD_PRETTY         = YES
 
-# The names of the make variables in the generated doxyrules.make file 
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
-# This is useful so different doxyrules.make files included by the same 
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
 # Makefile don't overwrite each other's variables.
 
-PERLMOD_MAKEVAR_PREFIX = 
+PERLMOD_MAKEVAR_PREFIX =
 
 #---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
+# Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
-# evaluate all C-preprocessor directives found in the sources and include 
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
 # files.
 
 ENABLE_PREPROCESSING   = YES
 
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
-# names in the source code. If set to NO (the default) only conditional 
-# compilation will be performed. Macro expansion can be done in a controlled 
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
 # way by setting EXPAND_ONLY_PREDEF to YES.
 
 MACRO_EXPANSION        = YES
 
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
-# then the macro expansion is limited to the macros specified with the 
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
 # PREDEFINED and EXPAND_AS_PREDEFINED tags.
 
 EXPAND_ONLY_PREDEF     = NO
 
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
 # in the INCLUDE_PATH (see below) will be search if a #include is found.
 
 SEARCH_INCLUDES        = YES
 
-# The INCLUDE_PATH tag can be used to specify one or more directories that 
-# contain include files that are not input files but should be processed by 
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
 # the preprocessor.
 
-INCLUDE_PATH           = 
+INCLUDE_PATH           =
 
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
-# patterns (like *.h and *.hpp) to filter out the header-files in the 
-# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
 # be used.
 
-INCLUDE_FILE_PATTERNS  = 
+INCLUDE_FILE_PATTERNS  =
 
-# The PREDEFINED tag can be used to specify one or more macro names that 
-# are defined before the preprocessor is started (similar to the -D option of 
-# gcc). The argument of the tag is a list of macros of the form: name 
-# or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed. To prevent a macro definition from being 
-# undefined via #undef or recursively expanded use the := operator 
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
 # instead of the = operator.
 
 PREDEFINED             = HAVE_DLFCN_H \
@@ -1011,231 +1011,231 @@ PREDEFINED             = HAVE_DLFCN_H \
                          DOXYGEN_SKIP \
                          HAVE_CURL
 
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
-# this tag can be used to specify a list of macro names that should be expanded. 
-# The macro definition that is found in the sources will be used. 
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
 # Use the PREDEFINED tag if you want to use a different macro definition.
 
 EXPAND_AS_DEFINED      = CPL_PRINT_FUNC_FORMAT
 
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
-# doxygen's preprocessor will remove all function-like macros that are alone 
-# on a line, have an all uppercase name, and do not end with a semicolon. Such 
-# function macros are typically used for boiler-plate code, and will confuse 
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
 # the parser if not removed.
 
 SKIP_FUNCTION_MACROS   = YES
 
 #---------------------------------------------------------------------------
-# Configuration::additions related to external references   
+# Configuration::additions related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES option can be used to specify one or more tagfiles. 
-# Optionally an initial location of the external documentation 
-# can be added for each tagfile. The format of a tag file without 
-# this location is as follows: 
-#   TAGFILES = file1 file2 ... 
-# Adding location for the tag files is done as follows: 
-#   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool 
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
 # does not have to be run to correct the links.
 # Note that each tag file must have a unique name
 # (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen 
+# If a tag file is not located in the directory in which doxygen
 # is run, you must also specify the path to the tagfile here.
 
-TAGFILES               = 
+TAGFILES               =
 
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
 # a tag file that is based on the input files it reads.
 
-GENERATE_TAGFILE       = 
+GENERATE_TAGFILE       =
 
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
-# in the class index. If set to NO only the inherited external classes 
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
 # will be listed.
 
 ALLEXTERNALS           = NO
 
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
-# in the modules index. If set to NO, only the current project's groups will 
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
 # be listed.
 
 EXTERNAL_GROUPS        = YES
 
-# The PERL_PATH should be the absolute path and name of the perl script 
+# The PERL_PATH should be the absolute path and name of the perl script
 # interpreter (i.e. the result of `which perl').
 
 PERL_PATH              = /usr/local/bin/perl
 
 #---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
+# Configuration options related to the dot tool
 #---------------------------------------------------------------------------
 
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
-# or super classes. Setting the tag to NO turns the diagrams off. Note that 
-# this option is superseded by the HAVE_DOT option below. This is only a 
-# fallback. It is recommended to install and use dot, since it yields more 
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
 # powerful graphs.
 
 CLASS_DIAGRAMS         = YES
 
-# If set to YES, the inheritance and collaboration graphs will hide 
-# inheritance and usage relations if the target is undocumented 
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
 # or is not a class.
 
 HIDE_UNDOC_RELATIONS   = YES
 
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
-# available from the path. This tool is part of Graphviz, a graph visualization 
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
 # have no effect if this option is set to NO (the default)
 
 HAVE_DOT               = NO
 
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect inheritance relations. Setting this tag to YES will force the 
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
 # the CLASS_DIAGRAMS tag to NO.
 
 CLASS_GRAPH            = YES
 
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect implementation dependencies (inheritance, containment, and 
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
 # class references variables) of the class with other documented classes.
 
 COLLABORATION_GRAPH    = YES
 
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
 # will generate a graph for groups, showing the direct groups dependencies
 
 GROUP_GRAPHS           = YES
 
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
-# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
 # Language.
 
 UML_LOOK               = NO
 
-# If set to YES, the inheritance and collaboration graphs will show the 
+# If set to YES, the inheritance and collaboration graphs will show the
 # relations between templates and their instances.
 
 TEMPLATE_RELATIONS     = NO
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
-# tags are set to YES then doxygen will generate a graph for each documented 
-# file showing the direct and indirect include dependencies of the file with 
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
 # other documented files.
 
 INCLUDE_GRAPH          = YES
 
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
-# documented header file showing the documented files that directly or 
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
 # indirectly include this file.
 
 INCLUDED_BY_GRAPH      = YES
 
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
-# generate a call dependency graph for every global function or class method. 
-# Note that enabling this option will significantly increase the time of a run. 
-# So in most cases it will be better to enable call graphs for selected 
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
 # functions only using the \callgraph command.
 
 CALL_GRAPH             = NO
 
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
 # will graphical hierarchy of all classes instead of a textual one.
 
 GRAPHICAL_HIERARCHY    = YES
 
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
-# then doxygen will show the dependencies a directory has on other directories 
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
 # in a graphical way. The dependency relations are determined by the #include
 # relations between the files in the directories.
 
 DIRECTORY_GRAPH        = YES
 
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
 # generated by dot. Possible values are png, jpg, or gif
 # If left blank png will be used.
 
 DOT_IMAGE_FORMAT       = png
 
-# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
 # found. If left blank, it is assumed the dot tool can be found in the path.
 
-DOT_PATH               = 
+DOT_PATH               =
 
-# The DOTFILE_DIRS tag can be used to specify one or more directories that 
-# contain dot files that are included in the documentation (see the 
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
 # \dotfile command).
 
-DOTFILE_DIRS           = 
+DOTFILE_DIRS           =
 
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
 # large images.
 
 MAX_DOT_GRAPH_WIDTH    = 1024
 
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
 # large images.
 
 MAX_DOT_GRAPH_HEIGHT   = 1024
 
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
-# graphs generated by dot. A depth value of 3 means that only nodes reachable 
-# from the root by following a path via at most 3 edges will be shown. Nodes 
-# that lay further from the root node will be omitted. Note that setting this 
-# option to 1 or 2 may greatly reduce the computation time needed for large 
-# code bases. Also note that a graph may be further truncated if the graph's 
-# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
-# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
 # the graph is not depth-constrained.
 
 MAX_DOT_GRAPH_DEPTH    = 0
 
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
-# background. This is disabled by default, which results in a white background. 
-# Warning: Depending on the platform used, enabling this option may lead to 
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to 
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
 # read).
 
 DOT_TRANSPARENT        = NO
 
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
-# files in one run (i.e. multiple -o and -T options on the command line). This 
-# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
 # support this, this feature is disabled by default.
 
 DOT_MULTI_TARGETS      = NO
 
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
-# generate a legend page explaining the meaning of the various boxes and 
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
 # arrows in the dot generated graphs.
 
 GENERATE_LEGEND        = YES
 
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
-# remove the intermediate dot files that are used to generate 
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
 # the various graphs.
 
 DOT_CLEANUP            = YES
 
 #---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
+# Configuration::additions related to the search engine
 #---------------------------------------------------------------------------
 
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# The SEARCHENGINE tag specifies whether or not a search engine should be
 # used. If set to NO the values of all tags below this one will be ignored.
 
 SEARCHENGINE           = NO
diff --git a/ogr/GNUmakefile b/ogr/GNUmakefile
index f09a398..928a511 100644
--- a/ogr/GNUmakefile
+++ b/ogr/GNUmakefile
@@ -11,19 +11,27 @@ ifeq ($(HAVE_GEOS),yes)
 CPPFLAGS 	:=	-DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
 endif
 
+ifeq ($(HAVE_SFCGAL),yes)
+CPPFLAGS 	:=	-DHAVE_SFCGAL=1 $(SFCGAL_CFLAGS) $(CPPFLAGS)
+endif
+
 CXXFLAGS 	:=	-DHAVE_MITAB $(CXXFLAGS)
 
 ifeq ($(HAVE_EXPAT),yes)
 CPPFLAGS 	:=	-DHAVE_EXPAT $(EXPAT_INCLUDE) $(CPPFLAGS)
 endif
 
+ifeq ($(HAVE_XERCES),yes)
+CPPFLAGS 	:=	-DHAVE_XERCES $(XERCES_INCLUDE) $(CPPFLAGS)
+endif
+
 ifeq ($(LIBZ_SETTING),internal)
 ZLIB_XTRA_OPT =      -I../frmts/zlib
 else
 ZLIB_XTRA_OPT =
 endif
 
-CPPFLAGS	:=	-Iogrsf_frmts -Iogrsf_frmts/mem -I.  $(PROJ_INCLUDE) $(PROJ_FLAGS) $(CPPFLAGS) $(ZLIB_XTRA_OPT)
+CPPFLAGS	:=	-Iogrsf_frmts -Iogrsf_frmts/mem -Iogrsf_frmts/geojson $(JSON_INCLUDE) -I.  $(PROJ_INCLUDE) $(PROJ_FLAGS) $(CPPFLAGS) $(ZLIB_XTRA_OPT)
 
 default:	lib
 
@@ -73,7 +81,7 @@ install:
 # that it helps gcc 4.1 generating correct code here...
 parser:
 	bison -p swq -d -oswq_parser.cpp swq_parser.y
-	sed "s/yytype_int16 yyssa\[YYINITDEPTH\];/yytype_int16 yyssa[YYINITDEPTH]; \/\* workaround bug with gcc 4.1 -O2 \*\/ memset(yyssa, 0, sizeof(yyssa));/" < swq_parser.cpp | sed "s/\*yyssp = yystate/\*yyssp = (yytype_int16)yystate/" > swq_parser.cpp.tmp
+	sed "s/yytype_int16 yyssa\[YYINITDEPTH\];/yytype_int16 yyssa[YYINITDEPTH]; \/\* workaround bug with gcc 4.1 -O2 \*\/ memset(yyssa, 0, sizeof(yyssa));/" < swq_parser.cpp | sed "s/\*yyssp = yystate/\*yyssp = (yytype_int16)yystate/" | sed "s/            \/\* Fall through\.  \*\//            CPL_FALLTHROUGH/" > swq_parser.cpp.tmp
 	mv swq_parser.cpp.tmp swq_parser.cpp
 
 # The sed hack is to please MSVC
diff --git a/ogr/file.lst b/ogr/file.lst
index d9db14e..d18c966 100644
--- a/ogr/file.lst
+++ b/ogr/file.lst
@@ -4,11 +4,14 @@ OBJ =	ogrgeometryfactory.o \
 	ogrlinestring.o \
 	ogrlinearring.o \
 	ogrpolygon.o \
+	ogrtriangle.o \
 	ogrutils.o \
 	ogrgeometry.o \
 	ogrgeometrycollection.o \
 	ogrmultipolygon.o \
 	ogrsurface.o \
+	ogrpolyhedralsurface.o \
+	ogrtriangulatedsurface.o \
 	ogrmultipoint.o \
 	ogrmultilinestring.o \
     ogrcircularstring.o \
@@ -54,4 +57,5 @@ OBJ =	ogrgeometryfactory.o \
     osr_cs_wkt.o \
 	osr_cs_wkt_parser.o \
     ogrgeomfielddefn.o \
-    ograpispy.o
+    ograpispy.o \
+    ogr_xerces.o
diff --git a/ogr/generate_encoding_table.c b/ogr/generate_encoding_table.c
index 903870d..ca2e707 100644
--- a/ogr/generate_encoding_table.c
+++ b/ogr/generate_encoding_table.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: generate_encoding_table.c 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: generate_encoding_table.c 36456 2016-11-22 23:34:00Z rouault $
  *
  * Project:  OGR
  * Purpose:  Generate a mapping table from a 1-byte encoding to unicode,
@@ -28,10 +28,10 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include <errno.h>
 #include <iconv.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
 #include <string.h>
 
 static unsigned utf8decode(const char* p, const char* end, int* len)
@@ -213,7 +213,6 @@ int main(int argc, char* argv[])
             printf("for(i = 0x%02X; i < 0x%02X; i++)\n", nLastIdentical, i);
             printf("    info->map[i] = i;\n");
         }
-        nLastIdentical = -1;
     }
 
     iconv_close( sConv );
diff --git a/ogr/gml2ogrgeometry.cpp b/ogr/gml2ogrgeometry.cpp
index f06ba00..ffa047a 100644
--- a/ogr/gml2ogrgeometry.cpp
+++ b/ogr/gml2ogrgeometry.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gml2ogrgeometry.cpp 37130 2017-01-12 21:15:22Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Code to translate between GML and OGR geometry forms.
@@ -39,45 +38,66 @@
  *
  */
 
-#include "cpl_minixml.h"
-#include "ogr_geometry.h"
+#include "cpl_port.h"
 #include "ogr_api.h"
+
+#include <cctype>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
 #include "cpl_error.h"
+#include "cpl_minixml.h"
 #include "cpl_string.h"
-#include <ctype.h>
+#include "ogr_core.h"
+#include "ogr_geometry.h"
 #include "ogr_p.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
 #include "ogrsf_frmts/xplane/ogr_xplane_geo_utils.h"
 
+CPL_CVSID("$Id: gml2ogrgeometry.cpp 37129 2017-01-12 21:15:15Z rouault $");
+
+#if HAVE_CXX11
+constexpr double kdfD2R = M_PI / 180.0;
+constexpr double kdf2PI = 2.0 * M_PI;
+#else
+static const double kdfD2R = M_PI / 180.0;
+static const double kdf2PI = 2.0 * M_PI;
+#endif
+
 /************************************************************************/
 /*                        GMLGetCoordTokenPos()                         */
 /************************************************************************/
 
-static const char* GMLGetCoordTokenPos(const char* pszStr,
-                                       const char** ppszNextToken)
+static const char* GMLGetCoordTokenPos( const char* pszStr,
+                                        const char** ppszNextToken )
 {
     char ch;
     while( true )
     {
         ch = *pszStr;
-        if (ch == '\0')
+        if( ch == '\0' )
         {
             *ppszNextToken = NULL;
             return NULL;
         }
-        else if (!(ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ' || ch == ','))
+        else if( !(ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ' ||
+                   ch == ',') )
             break;
-        pszStr ++;
+        pszStr++;
     }
 
     const char* pszToken = pszStr;
-    while((ch = *pszStr) != '\0')
+    while( (ch = *pszStr) != '\0' )
     {
-        if (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ' || ch == ',')
+        if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ' || ch == ',' )
         {
             *ppszNextToken = pszStr;
             return pszToken;
         }
-        pszStr ++;
+        pszStr++;
     }
     *ppszNextToken = NULL;
     return pszToken;
@@ -93,9 +113,7 @@ static const char* GMLGetCoordTokenPos(const char* pszStr,
 static const char *BareGMLElement( const char *pszInput )
 
 {
-    const char *pszReturn;
-
-    pszReturn = strchr( pszInput, ':' );
+    const char *pszReturn = strchr( pszInput, ':' );
     if( pszReturn == NULL )
         pszReturn = pszInput;
     else
@@ -190,8 +208,8 @@ static bool GetElementOrientation( const CPLXMLNode *psElement )
     while( psChild != NULL )
     {
         if( psChild->eType == CXT_Attribute &&
-            EQUAL(psChild->pszValue,"orientation") )
-                return EQUAL(psChild->psChild->pszValue,"+");
+            EQUAL(psChild->pszValue, "orientation") )
+                return EQUAL(psChild->psChild->pszValue, "+");
 
         psChild = psChild->psNext;
     }
@@ -212,12 +230,18 @@ static bool AddPoint( OGRGeometry *poGeometry,
     const OGRwkbGeometryType eType = wkbFlatten(poGeometry->getGeometryType());
     if( eType == wkbPoint )
     {
-        OGRPoint *poPoint = (OGRPoint *) poGeometry;
+        OGRPoint *poPoint = dynamic_cast<OGRPoint *>(poGeometry);
+        if( poPoint == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPoint.");
+            return false;
+        }
 
         if( !poPoint->IsEmpty() )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "More than one coordinate for <Point> element.");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "More than one coordinate for <Point> element.");
             return false;
         }
 
@@ -228,34 +252,39 @@ static bool AddPoint( OGRGeometry *poGeometry,
 
         return true;
     }
-
     else if( eType == wkbLineString ||
              eType == wkbCircularString )
     {
+        OGRSimpleCurve *poCurve = dynamic_cast<OGRSimpleCurve *>(poGeometry);
+        if( poCurve == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRSimpleCurve.");
+            return false;
+        }
         if( nDimension == 3 )
-            ((OGRSimpleCurve *) poGeometry)->addPoint( dfX, dfY, dfZ );
+            poCurve->addPoint(dfX, dfY, dfZ);
         else
-            ((OGRSimpleCurve *) poGeometry)->addPoint( dfX, dfY );
+            poCurve->addPoint(dfX, dfY);
 
         return true;
     }
 
-    else
-    {
-        CPLAssert( false );
-        return false;
-    }
+    CPLAssert( false );
+    return false;
 }
 
 /************************************************************************/
 /*                        ParseGMLCoordinates()                         */
 /************************************************************************/
 
-static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeometry,
+static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode,
+                                 OGRGeometry *poGeometry,
                                  int nSRSDimension )
 
 {
-    const CPLXMLNode *psCoordinates = FindBareXMLChild( psGeomNode, "coordinates" );
+    const CPLXMLNode *psCoordinates =
+        FindBareXMLChild( psGeomNode, "coordinates" );
     int iCoord = 0;
 
 /* -------------------------------------------------------------------- */
@@ -267,36 +296,44 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
     {
         const char *pszCoordString = GetElementText( psCoordinates );
 
-        const char *pszDecimal = CPLGetXMLValue( (CPLXMLNode*) psCoordinates, "decimal", NULL);
+        const char *pszDecimal =
+            CPLGetXMLValue(const_cast<CPLXMLNode *>(psCoordinates),
+                           "decimal", NULL);
         char chDecimal = '.';
         if( pszDecimal != NULL )
         {
-            if( strlen(pszDecimal) != 1 || (pszDecimal[0] >= '0' && pszDecimal[0] <= '9') )
+            if( strlen(pszDecimal) != 1 ||
+                (pszDecimal[0] >= '0' && pszDecimal[0] <= '9') )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, "Wrong value for decimal attribute");
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Wrong value for decimal attribute");
                 return false;
             }
             chDecimal = pszDecimal[0];
         }
 
-        const char *pszCS = CPLGetXMLValue( (CPLXMLNode*) psCoordinates, "cs", NULL);
+        const char *pszCS =
+            CPLGetXMLValue(const_cast<CPLXMLNode *>(psCoordinates), "cs", NULL);
         char chCS = ',';
         if( pszCS != NULL )
         {
             if( strlen(pszCS) != 1 || (pszCS[0] >= '0' && pszCS[0] <= '9') )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, "Wrong value for cs attribute");
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Wrong value for cs attribute");
                 return false;
             }
             chCS = pszCS[0];
         }
-        const char *pszTS = CPLGetXMLValue( (CPLXMLNode*) psCoordinates, "ts", NULL);
+        const char *pszTS =
+            CPLGetXMLValue(const_cast<CPLXMLNode *>(psCoordinates), "ts", NULL);
         char chTS = ' ';
         if( pszTS != NULL )
         {
             if( strlen(pszTS) != 1 || (pszTS[0] >= '0' && pszTS[0] <= '9') )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, "Wrong value for tes attribute");
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Wrong value for tes attribute");
                 return false;
             }
             chTS = pszTS[0];
@@ -310,14 +347,14 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
 
         while( *pszCoordString != '\0' )
         {
-            double dfX, dfY, dfZ = 0.0;
+            double dfX = 0.0;
             int nDimension = 2;
 
             // parse out 2 or 3 tuple.
             if( chDecimal == '.' )
                 dfX = OGRFastAtof( pszCoordString );
             else
-                dfX = CPLAtofDelim( pszCoordString, chDecimal) ;
+                dfX = CPLAtofDelim( pszCoordString, chDecimal);
             while( *pszCoordString != '\0'
                    && *pszCoordString != chCS
                    && !isspace((unsigned char)*pszCoordString) )
@@ -325,39 +362,46 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
 
             if( *pszCoordString == '\0' )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Corrupt <coordinates> value." );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Corrupt <coordinates> value.");
                 return false;
             }
-            else if( chCS == ',' && pszCS == NULL && isspace((unsigned char)*pszCoordString) )
+            else if( chCS == ',' && pszCS == NULL &&
+                     isspace((unsigned char)*pszCoordString) )
             {
-                /* In theory, the coordinates inside a coordinate tuple should be */
-                /* separated by a comma. However it has been found in the wild */
-                /* that the coordinates are in rare cases separated by a space, and the tuples by a comma */
-                /* See https://52north.org/twiki/bin/view/Processing/WPS-IDWExtension-ObservationCollectionExample */
-                /* or http://agisdemo.faa.gov/aixmServices/getAllFeaturesByLocatorId?locatorId=DFW */
+                // In theory, the coordinates inside a coordinate tuple should
+                // be separated by a comma. However it has been found in the
+                // wild that the coordinates are in rare cases separated by a
+                // space, and the tuples by a comma.
+                // See:
+                // https://52north.org/twiki/bin/view/Processing/WPS-IDWExtension-ObservationCollectionExample
+                // or
+                // http://agisdemo.faa.gov/aixmServices/getAllFeaturesByLocatorId?locatorId=DFW
                 chCS = ' ';
                 chTS = ',';
             }
 
             pszCoordString++;
+
+            double dfY = 0.0;
             if( chDecimal == '.' )
                 dfY = OGRFastAtof( pszCoordString );
             else
-                dfY = CPLAtofDelim( pszCoordString, chDecimal) ;
+                dfY = CPLAtofDelim( pszCoordString, chDecimal);
             while( *pszCoordString != '\0'
                    && *pszCoordString != chCS
                    && *pszCoordString != chTS
-                   && !isspace((unsigned char)*pszCoordString) )
+                   && !isspace(static_cast<unsigned char>(*pszCoordString)) )
                 pszCoordString++;
 
+            double dfZ = 0.0;
             if( *pszCoordString == chCS )
             {
                 pszCoordString++;
                 if( chDecimal == '.' )
                     dfZ = OGRFastAtof( pszCoordString );
                 else
-                    dfZ = CPLAtofDelim( pszCoordString, chDecimal) ;
+                    dfZ = CPLAtofDelim( pszCoordString, chDecimal);
                 nDimension = 3;
                 while( *pszCoordString != '\0'
                        && *pszCoordString != chCS
@@ -371,7 +415,7 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
                 pszCoordString++;
             }
 
-            while( isspace((unsigned char)*pszCoordString) )
+            while( isspace(static_cast<unsigned char>(*pszCoordString)) )
                 pszCoordString++;
 
             if( !AddPoint( poGeometry, dfX, dfY, dfZ, nDimension ) )
@@ -389,38 +433,39 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
 /*      the correct parsing of gml3.1.1 geometries such as linestring    */
 /*      defined with pos elements.                                      */
 /* -------------------------------------------------------------------- */
-    const CPLXMLNode *psPos;
-
     bool bHasFoundPosElement = false;
-    for( psPos = psGeomNode->psChild;
+    for( const CPLXMLNode *psPos = psGeomNode->psChild;
          psPos != NULL;
          psPos = psPos->psNext )
     {
-        if( psPos->eType != CXT_Element  )
+        if( psPos->eType != CXT_Element )
             continue;
 
         const char* pszSubElement = BareGMLElement(psPos->pszValue);
 
         if( EQUAL(pszSubElement, "pointProperty") )
         {
-            const CPLXMLNode *psPointPropertyIter;
-            for( psPointPropertyIter = psPos->psChild;
+            for( const CPLXMLNode *psPointPropertyIter = psPos->psChild;
                  psPointPropertyIter != NULL;
                  psPointPropertyIter = psPointPropertyIter->psNext )
             {
-                if( psPointPropertyIter->eType != CXT_Element  )
+                if( psPointPropertyIter->eType != CXT_Element )
                     continue;
 
-                const char* pszBareElement = BareGMLElement(psPointPropertyIter->pszValue);
-                if (EQUAL(pszBareElement,"Point") || EQUAL(pszBareElement,"ElevatedPoint") )
+                const char* pszBareElement =
+                    BareGMLElement(psPointPropertyIter->pszValue);
+                if( EQUAL(pszBareElement, "Point") ||
+                    EQUAL(pszBareElement, "ElevatedPoint") )
                 {
                     OGRPoint oPoint;
-                    if( ParseGMLCoordinates( psPointPropertyIter, &oPoint, nSRSDimension ) )
+                    if( ParseGMLCoordinates( psPointPropertyIter, &oPoint,
+                                             nSRSDimension ) )
                     {
-                        int bSuccess = AddPoint( poGeometry, oPoint.getX(),
-                                                 oPoint.getY(), oPoint.getZ(),
-                                                 oPoint.getCoordinateDimension() );
-                        if (bSuccess)
+                        const bool bSuccess =
+                            AddPoint( poGeometry, oPoint.getX(),
+                                      oPoint.getY(), oPoint.getZ(),
+                                      oPoint.getCoordinateDimension() );
+                        if( bSuccess )
                             bHasFoundPosElement = true;
                         else
                             return false;
@@ -433,18 +478,19 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
                 strcmp(psPos->psChild->pszValue, "xlink:href") == 0 )
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
-                         "Cannot resolve xlink:href='%s'. Try setting GML_SKIP_RESOLVE_ELEMS=NONE",
+                         "Cannot resolve xlink:href='%s'. "
+                         "Try setting GML_SKIP_RESOLVE_ELEMS=NONE",
                          psPos->psChild->psChild->pszValue);
             }
 
             continue;
         }
 
-        if( !EQUAL(pszSubElement,"pos") )
+        if( !EQUAL(pszSubElement, "pos") )
             continue;
 
         const char* pszPos = GetElementText( psPos );
-        if (pszPos == NULL)
+        if( pszPos == NULL )
         {
             poGeometry->empty();
             return true;
@@ -457,7 +503,7 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
         const char* pszZ = (pszCur != NULL) ?
                             GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
 
-        if (pszY == NULL)
+        if( pszY == NULL )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Did not get 2+ values in <gml:pos>%s</gml:pos> tuple.",
@@ -465,18 +511,19 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
             return false;
         }
 
-        double dfX = OGRFastAtof(pszX);
-        double dfY = OGRFastAtof(pszY);
-        double dfZ = (pszZ != NULL) ? OGRFastAtof(pszZ) : 0.0;
-        int bSuccess = AddPoint( poGeometry, dfX, dfY, dfZ, (pszZ != NULL) ? 3 : 2 );
+        const double dfX = OGRFastAtof(pszX);
+        const double dfY = OGRFastAtof(pszY);
+        const double dfZ = (pszZ != NULL) ? OGRFastAtof(pszZ) : 0.0;
+        const bool bSuccess =
+            AddPoint( poGeometry, dfX, dfY, dfZ, (pszZ != NULL) ? 3 : 2 );
 
-        if (bSuccess)
+        if( bSuccess )
             bHasFoundPosElement = true;
         else
             return false;
     }
 
-    if (bHasFoundPosElement)
+    if( bHasFoundPosElement )
         return true;
 
 /* -------------------------------------------------------------------- */
@@ -488,19 +535,24 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
     {
         int nDimension = 2;
 
-        /* Try to detect the presence of an srsDimension attribute */
-        /* This attribute is only available for gml3.1.1 but not */
-        /* available for gml3.1 SF*/
-        const char* pszSRSDimension = CPLGetXMLValue( (CPLXMLNode*) psPosList, "srsDimension", NULL);
-        /* If not found at the posList level, try on the enclosing element */
-        if (pszSRSDimension == NULL)
-            pszSRSDimension = CPLGetXMLValue( (CPLXMLNode*) psGeomNode, "srsDimension", NULL);
-        if (pszSRSDimension != NULL)
+        // Try to detect the presence of an srsDimension attribute
+        // This attribute is only available for gml3.1.1 but not
+        // available for gml3.1 SF.
+        const char* pszSRSDimension =
+            CPLGetXMLValue(const_cast<CPLXMLNode *>(psPosList),
+                           "srsDimension", NULL);
+        // If not found at the posList level, try on the enclosing element.
+        if( pszSRSDimension == NULL )
+            pszSRSDimension =
+                CPLGetXMLValue(const_cast<CPLXMLNode *>(psGeomNode),
+                               "srsDimension", NULL);
+        if( pszSRSDimension != NULL )
             nDimension = atoi(pszSRSDimension);
-        else if( nSRSDimension != 0 ) /* or use one coming from a still higher level element (#5606) */
+        else if( nSRSDimension != 0 )
+            // Or use one coming from a still higher level element (#5606).
             nDimension = nSRSDimension;
 
-        if (nDimension != 2 && nDimension != 3)
+        if( nDimension != 2 && nDimension != 3 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "srsDimension = %d not supported", nDimension);
@@ -508,7 +560,7 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
         }
 
         const char* pszPosList = GetElementText( psPosList );
-        if (pszPosList == NULL)
+        if( pszPosList == NULL )
         {
             poGeometry->empty();
             return true;
@@ -516,20 +568,20 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
 
         bool bSuccess = false;
         const char* pszCur = pszPosList;
-        while (true)
+        while( true )
         {
             const char* pszX = GMLGetCoordTokenPos(pszCur, &pszCur);
-            if (pszX == NULL && bSuccess)
+            if( pszX == NULL && bSuccess )
                 break;
             const char* pszY = (pszCur != NULL) ?
                     GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
             const char* pszZ = (nDimension == 3 && pszCur != NULL) ?
                     GMLGetCoordTokenPos(pszCur, &pszCur) : NULL;
 
-            if (pszY == NULL || (nDimension == 3 && pszZ == NULL))
+            if( pszY == NULL || (nDimension == 3 && pszZ == NULL) )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "Did not get at least %d values or invalid number of \n"
+                        "Did not get at least %d values or invalid number of "
                         "set of coordinates <gml:posList>%s</gml:posList>",
                         nDimension, pszPosList);
                 return false;
@@ -540,7 +592,7 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
             double dfZ = (pszZ != NULL) ? OGRFastAtof(pszZ) : 0.0;
             bSuccess = AddPoint( poGeometry, dfX, dfY, dfZ, nDimension );
 
-            if ( !bSuccess || pszCur == NULL)
+            if( !bSuccess || pszCur == NULL )
                 break;
         }
 
@@ -556,7 +608,7 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
          psCoordNode = psCoordNode->psNext )
     {
         if( psCoordNode->eType != CXT_Element
-            || !EQUAL(BareGMLElement(psCoordNode->pszValue),"coord") )
+            || !EQUAL(BareGMLElement(psCoordNode->pszValue), "coord") )
             continue;
 
         const CPLXMLNode *psXNode = FindBareXMLChild( psCoordNode, "X" );
@@ -590,7 +642,7 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
         iCoord++;
     }
 
-    return iCoord > 0.0;
+    return iCoord > 0;
 }
 
 #ifdef HAVE_GEOS
@@ -608,17 +660,25 @@ static bool ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGe
 
 static OGRPolygon *GML2FaceExtRing( OGRGeometry *poGeom )
 {
+    OGRGeometryCollection *poColl =
+        dynamic_cast<OGRGeometryCollection *>(poGeom);
+    if( poColl == NULL )
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRGeometryCollection.");
+        return NULL;
+    }
+
     OGRPolygon *poPolygon = NULL;
     bool bError = false;
-    OGRGeometryCollection *poColl = (OGRGeometryCollection *)poGeom;
     int iCount = poColl->getNumGeometries();
     int iExterior = 0;
     int iInterior = 0;
 
     for( int ig = 0; ig < iCount; ig++)
     {
-        /* a collection of Polygons is expected to be found */
-        OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(ig);
+        // A collection of Polygons is expected to be found.
+        OGRGeometry *poChild = poColl->getGeometryRef(ig);
         if( poChild == NULL)
         {
             bError = true;
@@ -626,34 +686,71 @@ static OGRPolygon *GML2FaceExtRing( OGRGeometry *poGeom )
         }
         if( wkbFlatten( poChild->getGeometryType()) == wkbPolygon )
         {
-            OGRPolygon *poPg = (OGRPolygon *)poChild;
+            OGRPolygon *poPg = dynamic_cast<OGRPolygon *>(poChild);
+            if( poPg == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRPolygon.");
+                return NULL;
+            }
             if( poPg->getNumInteriorRings() > 0 )
                 iExterior++;
             else
                 iInterior++;
         }
         else
+        {
             bError = true;
+        }
     }
 
     if( !bError && iCount > 0 )
     {
        if( iCount == 1 && iExterior == 0 && iInterior == 1)
         {
-            /* there is a single Polygon within the collection */
-            OGRPolygon * poPg = (OGRPolygon*)poColl->getGeometryRef(0 );
-            poPolygon = (OGRPolygon *)poPg->clone();
+            // There is a single Polygon within the collection.
+            OGRPolygon *poPg =
+                dynamic_cast<OGRPolygon *>(poColl->getGeometryRef(0));
+            if( poPg == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRPolygon.");
+                return NULL;
+            }
+            poPolygon = dynamic_cast<OGRPolygon *>(poPg->clone());
+            if( poPolygon == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRPolygon.");
+                return NULL;
+            }
         }
         else
         {
             if( iExterior == 1 && iInterior == iCount - 1 )
             {
-                /* searching the unique Polygon containing holes */
-                for ( int ig = 0; ig < iCount; ig++)
+                // Searching the unique Polygon containing holes.
+                for( int ig = 0; ig < iCount; ig++ )
                 {
-                    OGRPolygon * poPg = (OGRPolygon*)poColl->getGeometryRef(ig);
+                    OGRPolygon *poPg =
+                        dynamic_cast<OGRPolygon *>(poColl->getGeometryRef(ig));
+                    if( poPg == NULL )
+                    {
+                        CPLError(CE_Fatal, CPLE_AppDefined,
+                                 "dynamic_cast failed.  Expected OGRPolygon.");
+                        return NULL;
+                    }
                     if( poPg->getNumInteriorRings() > 0 )
-                        poPolygon = (OGRPolygon *)poPg->clone();
+                    {
+                        poPolygon = dynamic_cast<OGRPolygon *>(poPg->clone());
+                        if( poPolygon == NULL )
+                        {
+                            CPLError(
+                                CE_Fatal, CPLE_AppDefined,
+                                "dynamic_cast failed.  Expected OGRPolygon.");
+                            return NULL;
+                        }
+                    }
                 }
             }
         }
@@ -668,29 +765,36 @@ static OGRPolygon *GML2FaceExtRing( OGRGeometry *poGeom )
 /************************************************************************/
 
 static
-bool GML2OGRGeometry_AddToCompositeCurve(OGRCompoundCurve* poCC,
-                                        OGRGeometry* poGeom,
-                                        bool& bChildrenAreAllLineString)
+bool GML2OGRGeometry_AddToCompositeCurve( OGRCompoundCurve* poCC,
+                                          OGRGeometry* poGeom,
+                                          bool& bChildrenAreAllLineString )
 {
     if( poGeom == NULL ||
         !OGR_GT_IsCurve(poGeom->getGeometryType()) )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                "CompositeCurve: Got %.500s geometry as Member instead of a curve.",
-                poGeom ? poGeom->getGeometryName() : "NULL" );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "CompositeCurve: Got %.500s geometry as Member instead of a "
+                 "curve.",
+                 poGeom ? poGeom->getGeometryName() : "NULL" );
         return false;
     }
 
-    /* Crazy but allowed by GML: composite in composite */
+    // Crazy but allowed by GML: composite in composite.
     if( wkbFlatten(poGeom->getGeometryType()) == wkbCompoundCurve )
     {
-        OGRCompoundCurve* poCCChild = (OGRCompoundCurve* ) poGeom;
+        OGRCompoundCurve* poCCChild = dynamic_cast<OGRCompoundCurve *>(poGeom);
+        if( poCCChild == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRCompoundCurve.");
+            return false;
+        }
         while( poCCChild->getNumCurves() != 0 )
         {
             OGRCurve* poCurve = poCCChild->stealCurve(0);
             if( wkbFlatten(poCurve->getGeometryType()) != wkbLineString )
                 bChildrenAreAllLineString = false;
-            if( poCC->addCurveDirectly( poCurve ) != OGRERR_NONE )
+            if( poCC->addCurveDirectly(poCurve) != OGRERR_NONE )
             {
                 delete poCurve;
                 return false;
@@ -703,7 +807,15 @@ bool GML2OGRGeometry_AddToCompositeCurve(OGRCompoundCurve* poCC,
         if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
             bChildrenAreAllLineString = false;
 
-        if( poCC->addCurveDirectly( (OGRCurve*)poGeom ) != OGRERR_NONE )
+        OGRCurve *poCurve = dynamic_cast<OGRCurve *>(poGeom);
+        if( poCurve == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRCurve.");
+            return false;
+        }
+
+        if( poCC->addCurveDirectly( poCurve ) != OGRERR_NONE )
         {
             return false;
         }
@@ -716,15 +828,15 @@ bool GML2OGRGeometry_AddToCompositeCurve(OGRCompoundCurve* poCC,
 /************************************************************************/
 
 static
-bool GML2OGRGeometry_AddToMultiSurface(OGRMultiSurface* poMS,
-                                      OGRGeometry*& poGeom,
-                                      const char* pszMemberElement,
-                                      bool& bChildrenAreAllPolygons)
+bool GML2OGRGeometry_AddToMultiSurface( OGRMultiSurface* poMS,
+                                        OGRGeometry*& poGeom,
+                                        const char* pszMemberElement,
+                                        bool& bChildrenAreAllPolygons )
 {
-    if (poGeom == NULL)
+    if( poGeom == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Invalid %s",
-                    pszMemberElement );
+                  pszMemberElement );
         return false;
     }
 
@@ -739,13 +851,19 @@ bool GML2OGRGeometry_AddToMultiSurface(OGRMultiSurface* poMS,
             return false;
         }
     }
-    else if (eType == wkbMultiPolygon || eType == wkbMultiSurface)
+    else if( eType == wkbMultiPolygon || eType == wkbMultiSurface )
     {
-        OGRMultiSurface* poMS2 = (OGRMultiSurface*) poGeom;
-        int i;
-        for(i=0;i<poMS2->getNumGeometries();i++)
+        OGRMultiSurface* poMS2 = dynamic_cast<OGRMultiSurface *>(poGeom);
+        if( poMS2 == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRMultiSurface.");
+            return false;
+        }
+        for( int i = 0; i < poMS2->getNumGeometries(); i++ )
         {
-            if( wkbFlatten(poMS2->getGeometryRef(i)->getGeometryType()) != wkbPolygon )
+            if( wkbFlatten(poMS2->getGeometryRef(i)->getGeometryType()) !=
+                wkbPolygon )
                 bChildrenAreAllPolygons = false;
 
             if( poMS->addGeometry(poMS2->getGeometryRef(i)) != OGRERR_NONE )
@@ -775,14 +893,15 @@ bool GML2OGRGeometry_AddToMultiSurface(OGRMultiSurface* poMS,
 /************************************************************************/
 
 static
-OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
-                                               int nPseudoBoolGetSecondaryGeometryOption,
-                                               int nRecLevel,
-                                               int nSRSDimension,
-                                               const char* pszSRSName,
-                                               bool bIgnoreGSG = false,
-                                               bool bOrientation = true,
-                                               bool bFaceHoleNegative = false );
+OGRGeometry *GML2OGRGeometry_XMLNode_Internal(
+    const CPLXMLNode *psNode,
+    int nPseudoBoolGetSecondaryGeometryOption,
+    int nRecLevel,
+    int nSRSDimension,
+    const char* pszSRSName,
+    bool bIgnoreGSG = false,
+    bool bOrientation = true,
+    bool bFaceHoleNegative = false );
 
 OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                                       int nPseudoBoolGetSecondaryGeometryOption,
@@ -793,25 +912,28 @@ OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
                                       bool bFaceHoleNegative )
 
 {
-    return GML2OGRGeometry_XMLNode_Internal(psNode,
-                                            nPseudoBoolGetSecondaryGeometryOption,
-                                            nRecLevel, nSRSDimension,
-                                            NULL,
-                                            bIgnoreGSG, bOrientation,
-                                            bFaceHoleNegative);
+    return
+        GML2OGRGeometry_XMLNode_Internal(
+            psNode,
+            nPseudoBoolGetSecondaryGeometryOption,
+            nRecLevel, nSRSDimension,
+            NULL,
+            bIgnoreGSG, bOrientation,
+            bFaceHoleNegative);
 }
 
 static
-OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
-                                               int nPseudoBoolGetSecondaryGeometryOption,
-                                               int nRecLevel,
-                                               int nSRSDimension,
-                                               const char* pszSRSName,
-                                               bool bIgnoreGSG,
-                                               bool bOrientation,
-                                               bool bFaceHoleNegative )
+OGRGeometry *GML2OGRGeometry_XMLNode_Internal(
+    const CPLXMLNode *psNode,
+    int nPseudoBoolGetSecondaryGeometryOption,
+    int nRecLevel,
+    int nSRSDimension,
+    const char* pszSRSName,
+    bool bIgnoreGSG,
+    bool bOrientation,
+    bool bFaceHoleNegative )
 {
-    const bool bCastToLinearTypeIfPossible = true;     /* hard-coded for now */
+    const bool bCastToLinearTypeIfPossible = true;  // Hard-coded for now.
 
     if( psNode != NULL && strcmp(psNode->pszValue, "?xml") == 0 )
         psNode = psNode->psNext;
@@ -820,60 +942,63 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
     if( psNode == NULL )
         return NULL;
 
-    const char* pszSRSDimension = CPLGetXMLValue( (CPLXMLNode*) psNode, "srsDimension", NULL);
+    const char* pszSRSDimension =
+        CPLGetXMLValue(const_cast<CPLXMLNode *>(psNode), "srsDimension", NULL);
     if( pszSRSDimension != NULL )
         nSRSDimension = atoi(pszSRSDimension);
 
     if( pszSRSName == NULL )
-        pszSRSName = CPLGetXMLValue( (CPLXMLNode*) psNode, "srsName", NULL);
+        pszSRSName =
+            CPLGetXMLValue(const_cast<CPLXMLNode *>(psNode), "srsName", NULL);
 
     const char *pszBaseGeometry = BareGMLElement( psNode->pszValue );
-    if (nPseudoBoolGetSecondaryGeometryOption < 0)
-        nPseudoBoolGetSecondaryGeometryOption = CPLTestBool(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
-    bool bGetSecondaryGeometry = bIgnoreGSG ? false : CPL_TO_BOOL(nPseudoBoolGetSecondaryGeometryOption);
+    if( nPseudoBoolGetSecondaryGeometryOption < 0 )
+        nPseudoBoolGetSecondaryGeometryOption =
+            CPLTestBool(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
+    bool bGetSecondaryGeometry =
+        bIgnoreGSG ? false : CPL_TO_BOOL(nPseudoBoolGetSecondaryGeometryOption);
 
-    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    // Arbitrary value, but certainly large enough for reasonable usages.
     if( nRecLevel == 32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Too many recursion levels (%d) while parsing GML geometry.",
-                    nRecLevel );
+                  "Too many recursion levels (%d) while parsing GML geometry.",
+                  nRecLevel );
         return NULL;
     }
 
     if( bGetSecondaryGeometry )
-        if( !( EQUAL(pszBaseGeometry,"directedEdge") ||
-               EQUAL(pszBaseGeometry,"TopoCurve") ) )
+        if( !( EQUAL(pszBaseGeometry, "directedEdge") ||
+               EQUAL(pszBaseGeometry, "TopoCurve") ) )
             return NULL;
 
 /* -------------------------------------------------------------------- */
-/*      Polygon / PolygonPatch / Triangle / Rectangle                   */
+/*      Polygon / PolygonPatch / Rectangle                              */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"Polygon") ||
-        EQUAL(pszBaseGeometry,"PolygonPatch") ||
-        EQUAL(pszBaseGeometry,"Triangle") ||
-        EQUAL(pszBaseGeometry,"Rectangle"))
+    if( EQUAL(pszBaseGeometry, "Polygon") ||
+        EQUAL(pszBaseGeometry, "PolygonPatch") ||
+        EQUAL(pszBaseGeometry, "Rectangle"))
     {
-        const CPLXMLNode *psChild;
-
         // Find outer ring.
-        psChild = FindBareXMLChild( psNode, "outerBoundaryIs" );
-        if (psChild == NULL)
+        const CPLXMLNode *psChild =
+            FindBareXMLChild( psNode, "outerBoundaryIs" );
+        if( psChild == NULL )
            psChild = FindBareXMLChild( psNode, "exterior");
 
         psChild = GetChildElement(psChild);
         if( psChild == NULL )
         {
-            /* <gml:Polygon/> is invalid GML2, but valid GML3, so be tolerant */
+            // <gml:Polygon/> is invalid GML2, but valid GML3, so be tolerant.
             return new OGRPolygon();
         }
 
         // Translate outer ring and add to polygon.
         OGRGeometry* poGeom =
-            GML2OGRGeometry_XMLNode_Internal( psChild,
-                                              nPseudoBoolGetSecondaryGeometryOption,
-                                              nRecLevel + 1, nSRSDimension,
-                                              pszSRSName );
+            GML2OGRGeometry_XMLNode_Internal(
+                psChild,
+                nPseudoBoolGetSecondaryGeometryOption,
+                nRecLevel + 1, nSRSDimension,
+                pszSRSName );
         if( poGeom == NULL )
         {
             CPLError( CE_Failure, CPLE_AppDefined, "Invalid exterior ring");
@@ -892,11 +1017,17 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         if( wkbFlatten(poGeom->getGeometryType()) == wkbLineString &&
             !EQUAL(poGeom->getGeometryName(), "LINEARRING") )
         {
-            poGeom = OGRCurve::CastToLinearRing((OGRCurve*)poGeom);
+            OGRCurve *poCurve = dynamic_cast<OGRCurve *>(poGeom);
+            if( poCurve == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRCurve.");
+            }
+            poGeom = OGRCurve::CastToLinearRing(poCurve);
         }
 
-        OGRCurvePolygon *poCP;
-        bool bIsPolygon;
+        OGRCurvePolygon *poCP = NULL;
+        bool bIsPolygon = false;
         if( EQUAL(poGeom->getGeometryName(), "LINEARRING") )
         {
             poCP = new OGRPolygon();
@@ -908,11 +1039,19 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             bIsPolygon = false;
         }
 
-        if( poCP->addRingDirectly( (OGRCurve*)poGeom ) != OGRERR_NONE )
         {
-            delete poCP;
-            delete poGeom;
-            return NULL;
+            OGRCurve *poCurve = dynamic_cast<OGRCurve *>(poGeom);
+            if( poCurve == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRCurve.");
+            }
+            if( poCP->addRingDirectly(poCurve) != OGRERR_NONE )
+            {
+                delete poCP;
+                delete poGeom;
+                return NULL;
+            }
         }
 
         // Find all inner rings
@@ -921,22 +1060,25 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
              psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && (EQUAL(BareGMLElement(psChild->pszValue),"innerBoundaryIs") ||
-                    EQUAL(BareGMLElement(psChild->pszValue),"interior")))
+                && (EQUAL(BareGMLElement(psChild->pszValue),
+                          "innerBoundaryIs") ||
+                    EQUAL(BareGMLElement(psChild->pszValue), "interior")))
             {
                 const CPLXMLNode* psInteriorChild = GetChildElement(psChild);
-                if (psInteriorChild != NULL)
+                if( psInteriorChild != NULL )
                     poGeom =
-                        GML2OGRGeometry_XMLNode_Internal( psInteriorChild,
-                                                          nPseudoBoolGetSecondaryGeometryOption,
-                                                          nRecLevel + 1,
-                                                          nSRSDimension,
-                                                          pszSRSName );
+                        GML2OGRGeometry_XMLNode_Internal(
+                            psInteriorChild,
+                            nPseudoBoolGetSecondaryGeometryOption,
+                            nRecLevel + 1,
+                            nSRSDimension,
+                            pszSRSName );
                 else
                     poGeom = NULL;
-                if (poGeom == NULL)
+                if( poGeom == NULL )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, "Invalid interior ring");
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Invalid interior ring");
                     delete poCP;
                     return NULL;
                 }
@@ -955,17 +1097,33 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 {
                     if( !EQUAL(poGeom->getGeometryName(), "LINEARRING") )
                     {
-                        if (wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
+                        if( wkbFlatten(poGeom->getGeometryType()) ==
+                            wkbLineString )
                         {
-                            OGRLineString* poLS = (OGRLineString*)poGeom;
+                            OGRLineString* poLS =
+                                dynamic_cast<OGRLineString *>(poGeom);
+                            if( poLS == NULL )
+                            {
+                                CPLError(CE_Fatal, CPLE_AppDefined,
+                                         "dynamic_cast failed.  "
+                                         "Expected OGRLineString.");
+                            }
                             poGeom = OGRCurve::CastToLinearRing(poLS);
                         }
                         else
                         {
-                            /* Might fail if some rings are not closed */
-                            /* We used to be tolerant about that with Polygon */
-                            /* but we have become stricter with CurvePolygon */
-                            poCP = OGRSurface::CastToCurvePolygon( (OGRPolygon*)poCP );
+                            OGRPolygon *poPolygon =
+                                dynamic_cast<OGRPolygon *>(poCP);
+                            if( poPolygon == NULL )
+                            {
+                                CPLError(CE_Fatal, CPLE_AppDefined,
+                                         "dynamic_cast failed.  "
+                                         "Expected OGRPolygon.");
+                            }
+                            // Might fail if some rings are not closed.
+                            // We used to be tolerant about that with Polygon.
+                            // but we have become stricter with CurvePolygon.
+                            poCP = OGRSurface::CastToCurvePolygon(poPolygon);
                             if( poCP == NULL )
                             {
                                 delete poGeom;
@@ -978,9 +1136,25 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 else
                 {
                     if( EQUAL(poGeom->getGeometryName(), "LINEARRING") )
-                        poGeom = OGRCurve::CastToLineString( (OGRCurve*)poGeom );
+                    {
+                        OGRCurve *poCurve = dynamic_cast<OGRCurve*>(poGeom);
+                        if( poCurve == NULL )
+                        {
+                            CPLError(CE_Fatal, CPLE_AppDefined,
+                                     "dynamic_cast failed.  "
+                                     "Expected OGRCurve.");
+                        }
+                        poGeom = OGRCurve::CastToLineString(poCurve);
+                    }
+                }
+                OGRCurve *poCurve = dynamic_cast<OGRCurve*>(poGeom);
+                if( poCurve == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                             "dynamic_cast failed.  "
+                             "Expected OGRCurve.");
                 }
-                if( poCP->addRingDirectly( (OGRCurve*)poGeom ) != OGRERR_NONE )
+                if( poCP->addRingDirectly(poCurve) != OGRERR_NONE )
                 {
                     delete poCP;
                     delete poGeom;
@@ -993,11 +1167,79 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
     }
 
 /* -------------------------------------------------------------------- */
+/*      Triangle                                                        */
+/* -------------------------------------------------------------------- */
+
+    if( EQUAL(pszBaseGeometry, "Triangle"))
+    {
+        // Find outer ring.
+        const CPLXMLNode *psChild =
+            FindBareXMLChild( psNode, "outerBoundaryIs" );
+        if( psChild == NULL )
+           psChild = FindBareXMLChild( psNode, "exterior");
+
+        psChild = GetChildElement(psChild);
+        if( psChild == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Empty Triangle");
+            return new OGRTriangle();
+        }
+
+        // Translate outer ring and add to Triangle.
+        OGRGeometry* poGeom =
+            GML2OGRGeometry_XMLNode_Internal(
+                psChild,
+                nPseudoBoolGetSecondaryGeometryOption,
+                nRecLevel + 1, nSRSDimension,
+                pszSRSName);
+        if( poGeom == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid exterior ring");
+            return NULL;
+        }
+
+        if( !OGR_GT_IsCurve(poGeom->getGeometryType()) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "%s: Got %.500s geometry as outerBoundaryIs.",
+                      pszBaseGeometry, poGeom->getGeometryName() );
+            delete poGeom;
+            return NULL;
+        }
+
+        if( wkbFlatten(poGeom->getGeometryType()) == wkbLineString &&
+            !EQUAL(poGeom->getGeometryName(), "LINEARRING") )
+        {
+            poGeom = OGRCurve::CastToLinearRing((OGRCurve*)poGeom);
+        }
+
+        OGRTriangle *poTriangle;
+        if( EQUAL(poGeom->getGeometryName(), "LINEARRING") )
+        {
+            poTriangle = new OGRTriangle();
+        }
+        else
+        {
+            delete poGeom;
+            return NULL;
+        }
+
+        if( poTriangle->addRingDirectly( (OGRCurve*)poGeom ) != OGRERR_NONE )
+        {
+            delete poTriangle;
+            delete poGeom;
+            return NULL;
+        }
+
+        return poTriangle;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      LinearRing                                                      */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"LinearRing") )
+    if( EQUAL(pszBaseGeometry, "LinearRing") )
     {
-        OGRLinearRing   *poLinearRing = new OGRLinearRing();
+        OGRLinearRing *poLinearRing = new OGRLinearRing();
 
         if( !ParseGMLCoordinates( psNode, poLinearRing, nSRSDimension ) )
         {
@@ -1011,50 +1253,59 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      Ring GML3                                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"Ring") )
+    if( EQUAL(pszBaseGeometry, "Ring") )
     {
         OGRCurve* poRing = NULL;
-        OGRCompoundCurve   *poCC = NULL;
+        OGRCompoundCurve *poCC = NULL;
         bool bChildrenAreAllLineString = true;
-        const CPLXMLNode *psChild;
 
         bool bLastCurveWasApproximateArc = false;
         bool bLastCurveWasApproximateArcInvertedAxisOrder = false;
-        double dfLastCurveApproximateArcRadius = 0;
+        double dfLastCurveApproximateArcRadius = 0.0;
 
-        for( psChild = psNode->psChild;
-             psChild != NULL; psChild = psChild->psNext )
+        for( const CPLXMLNode *psChild = psNode->psChild;
+             psChild != NULL;
+             psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"curveMember") )
+                && EQUAL(BareGMLElement(psChild->pszValue), "curveMember") )
             {
                 const CPLXMLNode* psCurveChild = GetChildElement(psChild);
-                OGRGeometry* poGeom;
-                if (psCurveChild != NULL)
+                OGRGeometry* poGeom = NULL;
+                if( psCurveChild != NULL )
+                {
                     poGeom =
-                        GML2OGRGeometry_XMLNode_Internal( psCurveChild,
-                                                          nPseudoBoolGetSecondaryGeometryOption,
-                                                          nRecLevel + 1,
-                                                          nSRSDimension,
-                                                          pszSRSName );
+                        GML2OGRGeometry_XMLNode_Internal(
+                            psCurveChild,
+                            nPseudoBoolGetSecondaryGeometryOption,
+                            nRecLevel + 1,
+                            nSRSDimension,
+                            pszSRSName );
+                }
                 else
                 {
-                    if( psChild->psChild && psChild->psChild->eType == CXT_Attribute &&
+                    if( psChild->psChild && psChild->psChild->eType ==
+                        CXT_Attribute &&
                         psChild->psChild->psNext == NULL &&
                         strcmp(psChild->psChild->pszValue, "xlink:href") == 0 )
                     {
                         CPLError(CE_Warning, CPLE_AppDefined,
-                                "Cannot resolve xlink:href='%s'. Try setting GML_SKIP_RESOLVE_ELEMS=NONE",
-                                psChild->psChild->psChild->pszValue);
+                                 "Cannot resolve xlink:href='%s'. "
+                                 "Try setting GML_SKIP_RESOLVE_ELEMS=NONE",
+                                 psChild->psChild->psChild->pszValue);
                     }
-
-                    poGeom = NULL;
+                    delete poRing;
+                    delete poCC;
+                    delete poGeom;
+                    return NULL;
                 }
 
-                // try to join multiline string to one linestring
-                if( poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString )
+                // Try to join multiline string to one linestring.
+                if( poGeom && wkbFlatten(poGeom->getGeometryType()) ==
+                    wkbMultiLineString )
                 {
-                    poGeom = OGRGeometryFactory::forceToLineString( poGeom, false );
+                    poGeom =
+                        OGRGeometryFactory::forceToLineString(poGeom, false);
                 }
 
                 if( poGeom == NULL
@@ -1069,8 +1320,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
                     bChildrenAreAllLineString = false;
 
-                /* Ad-hoc logic to handle nicely connecting ArcByCenterPoint */
-                /* with consecutive curves, as found in some AIXM files */
+                // Ad-hoc logic to handle nicely connecting ArcByCenterPoint
+                // with consecutive curves, as found in some AIXM files.
                 bool bIsApproximateArc = false;
                 const CPLXMLNode* psChild2, *psChild3;
                 if( strcmp(psCurveChild->pszValue, "Curve") == 0 &&
@@ -1079,22 +1330,30 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     (psChild3 = GetChildElement(psChild2)) != NULL &&
                     strcmp(psChild3->pszValue, "ArcByCenterPoint") == 0 )
                 {
-                    const CPLXMLNode* psRadius = FindBareXMLChild( psChild3, "radius");
+                    const CPLXMLNode* psRadius =
+                        FindBareXMLChild(psChild3, "radius");
                     if( psRadius && psRadius->eType == CXT_Element )
                     {
-                        double dfRadius = CPLAtof(CPLGetXMLValue((CPLXMLNode*)psRadius, NULL, "0"));
-                        const char* pszUnits = CPLGetXMLValue((CPLXMLNode*)psRadius, "uom", NULL);
+                        double dfRadius = CPLAtof(CPLGetXMLValue(
+                            const_cast<CPLXMLNode *>(psRadius), NULL, "0"));
+                        const char* pszUnits = CPLGetXMLValue(
+                            const_cast<CPLXMLNode *>(psRadius), "uom", NULL);
                         bool bSRSUnitIsDegree = false;
                         bool bInvertedAxisOrder = false;
                         if( pszSRSName != NULL )
                         {
                             OGRSpatialReference oSRS;
-                            if( oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE )
+                            if( oSRS.SetFromUserInput(pszSRSName)
+                                == OGRERR_NONE )
                             {
                                 if( oSRS.IsGeographic() )
                                 {
-                                    bInvertedAxisOrder = CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong());
-                                    bSRSUnitIsDegree = fabs(oSRS.GetAngularUnits(NULL) - CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
+                                    bInvertedAxisOrder =
+                                        CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong());
+                                    bSRSUnitIsDegree =
+                                        fabs(oSRS.GetAngularUnits(NULL) -
+                                             CPLAtof(SRS_UA_DEGREE_CONV))
+                                        < 1e-8;
                                 }
                             }
                         }
@@ -1110,13 +1369,22 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                             else if( EQUAL(pszUnits, "ft") )
                                 dfRadius *= CPLAtof(SRS_UL_INTL_FOOT_CONV);
                             dfLastCurveApproximateArcRadius = dfRadius;
-                            bLastCurveWasApproximateArcInvertedAxisOrder = bInvertedAxisOrder;
+                            bLastCurveWasApproximateArcInvertedAxisOrder =
+                                bInvertedAxisOrder;
                         }
                     }
                 }
 
                 if( poCC == NULL && poRing == NULL )
-                    poRing = (OGRCurve*)poGeom;
+                {
+                    poRing = dynamic_cast<OGRCurve *>(poGeom);
+                    if( poRing == NULL )
+                    {
+                        CPLError(CE_Fatal, CPLE_AppDefined,
+                                 "dynamic_cast failed.  "
+                                 "Expected OGRCurve.");
+                    }
+                }
                 else
                 {
                     if( poCC == NULL )
@@ -1137,22 +1405,45 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     {
                         if( poGeom->getGeometryType() == wkbLineString )
                         {
-                            OGRCurve* poPreviousCurve = poCC->getCurve(poCC->getNumCurves()-1);
-                            OGRLineString* poLS = (OGRLineString*)poGeom;
-                            if( poPreviousCurve->getNumPoints() >= 2 && poLS->getNumPoints() >= 2 )
+                            OGRCurve* poPreviousCurve =
+                                poCC->getCurve(poCC->getNumCurves()-1);
+                            OGRLineString* poLS =
+                                dynamic_cast<OGRLineString *>(poGeom);
+                            if( poLS == NULL )
                             {
-                                OGRPoint p, p2;
+                                CPLError(CE_Fatal, CPLE_AppDefined,
+                                         "dynamic_cast failed.  "
+                                         "Expected OGRLineString.");
+                            }
+                            if( poPreviousCurve->getNumPoints() >= 2 &&
+                                poLS->getNumPoints() >= 2 )
+                            {
+                                OGRPoint p;
+                                OGRPoint p2;
                                 poPreviousCurve->EndPoint(&p);
                                 poLS->StartPoint(&p2);
-                                double dfDistance;
+                                double dfDistance = 0.0;
                                 if( bLastCurveWasApproximateArcInvertedAxisOrder )
-                                    dfDistance = OGRXPlane_Distance(p.getX(), p.getY(), p2.getX(), p2.getY());
+                                    dfDistance =
+                                        OGRXPlane_Distance(
+                                            p.getX(), p.getY(),
+                                            p2.getX(), p2.getY());
                                 else
-                                    dfDistance = OGRXPlane_Distance(p.getY(), p.getX(), p2.getY(), p2.getX());
-                                //CPLDebug("OGR", "%f %f\n", dfDistance, dfLastCurveApproximateArcRadius / 10 );
-                                if( dfDistance < dfLastCurveApproximateArcRadius / 5 )
+                                    dfDistance =
+                                        OGRXPlane_Distance(
+                                            p.getY(), p.getX(),
+                                            p2.getY(), p2.getX());
+                                // CPLDebug("OGR", "%f %f",
+                                //          dfDistance,
+                                //          dfLastCurveApproximateArcRadius
+                                //          / 10.0 );
+                                if( dfDistance <
+                                    dfLastCurveApproximateArcRadius / 5.0 )
                                 {
-                                    CPLDebug("OGR", "Moving approximate start of ArcByCenterPoint to end of previous curve");
+                                    CPLDebug("OGR",
+                                             "Moving approximate start of "
+                                             "ArcByCenterPoint to end of "
+                                             "previous curve");
                                     poLS->setPoint(0, &p);
                                 }
                             }
@@ -1160,38 +1451,82 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     }
                     else if( bLastCurveWasApproximateArc )
                     {
-                        OGRCurve* poPreviousCurve = poCC->getCurve(poCC->getNumCurves()-1);
-                        if( poPreviousCurve->getGeometryType() == wkbLineString )
+                        OGRCurve* poPreviousCurve =
+                            poCC->getCurve(poCC->getNumCurves()-1);
+                        if( poPreviousCurve->getGeometryType() ==
+                            wkbLineString )
                         {
-                            OGRLineString* poLS = (OGRLineString*)poPreviousCurve;
-                            if( poLS->getNumPoints() >= 2 && ((OGRCurve*)poGeom)->getNumPoints() >= 2 )
+                            OGRLineString* poLS =
+                                dynamic_cast<OGRLineString *>(poPreviousCurve);
+                            if( poLS == NULL )
                             {
-                                OGRPoint p, p2;
-                                ((OGRCurve*)poGeom)->StartPoint(&p);
+                                CPLError(CE_Fatal, CPLE_AppDefined,
+                                         "dynamic_cast failed.  "
+                                         "Expected OGRLineString.");
+                            }
+                            OGRCurve *poCurve =
+                                dynamic_cast<OGRCurve *>(poGeom);
+                            if( poCurve == NULL )
+                            {
+                                CPLError(CE_Fatal, CPLE_AppDefined,
+                                         "dynamic_cast failed.  "
+                                         "Expected OGRCurve.");
+                            }
+                            if( poLS->getNumPoints() >= 2 &&
+                                poCurve->getNumPoints() >= 2 )
+                            {
+                                OGRPoint p;
+                                OGRPoint p2;
+                                poCurve->StartPoint(&p);
                                 poLS->EndPoint(&p2);
-                                double dfDistance;
+                                double dfDistance = 0.0;
                                 if( bLastCurveWasApproximateArcInvertedAxisOrder )
-                                    dfDistance = OGRXPlane_Distance(p.getX(), p.getY(), p2.getX(), p2.getY());
+                                    dfDistance =
+                                        OGRXPlane_Distance(
+                                            p.getX(), p.getY(),
+                                            p2.getX(), p2.getY());
                                 else
-                                    dfDistance = OGRXPlane_Distance(p.getY(), p.getX(), p2.getY(), p2.getX());
-                                //CPLDebug("OGR", "%f %f\n", dfDistance, dfLastCurveApproximateArcRadius / 10 );
-                                // "A-311 WHEELER AFB OAHU, HI.xml" needs more than 10%
-                                if( dfDistance < dfLastCurveApproximateArcRadius / 5 )
+                                    dfDistance =
+                                        OGRXPlane_Distance(
+                                            p.getY(), p.getX(),
+                                            p2.getY(), p2.getX());
+                                // CPLDebug(
+                                //    "OGR", "%f %f",
+                                //    dfDistance,
+                                //    dfLastCurveApproximateArcRadius / 10.0 );
+
+                                // "A-311 WHEELER AFB OAHU, HI.xml" needs more
+                                // than 10%.
+                                if( dfDistance <
+                                    dfLastCurveApproximateArcRadius / 5.0 )
                                 {
-                                    CPLDebug("OGR", "Moving approximate end of last ArcByCenterPoint to start of current curve");
-                                    poLS->setPoint(poLS->getNumPoints()-1, &p);
+                                    CPLDebug(
+                                        "OGR",
+                                        "Moving approximate end of last "
+                                        "ArcByCenterPoint to start of the "
+                                        "current curve");
+                                    poLS->setPoint(poLS->getNumPoints() - 1,
+                                                   &p);
                                 }
                             }
                         }
                     }
 
+                    OGRCurve *poCurve = dynamic_cast<OGRCurve *>(poGeom);
+                    if( poCurve == NULL )
+                    {
+                        CPLError(CE_Fatal, CPLE_AppDefined,
+                                 "dynamic_cast failed.  Expected OGRCurve.");
+                    }
+
                     bool bIgnored = false;
                     if( !GML2OGRGeometry_AddToCompositeCurve( poCC,
-                                                              poGeom,
+                                                              poCurve,
                                                               bIgnored ) )
                     {
                         delete poGeom;
                         delete poCC;
+                        delete poRing;
                         return NULL;
                     }
                 }
@@ -1233,11 +1568,11 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      LineString                                                      */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"LineString")
-        || EQUAL(pszBaseGeometry,"LineStringSegment")
-        || EQUAL(pszBaseGeometry,"GeodesicString") )
+    if( EQUAL(pszBaseGeometry, "LineString")
+        || EQUAL(pszBaseGeometry, "LineStringSegment")
+        || EQUAL(pszBaseGeometry, "GeodesicString") )
     {
-        OGRLineString   *poLine = new OGRLineString();
+        OGRLineString *poLine = new OGRLineString();
 
         if( !ParseGMLCoordinates( psNode, poLine, nSRSDimension ) )
         {
@@ -1248,140 +1583,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         return poLine;
     }
 
-#if 0
-/* -------------------------------------------------------------------- */
-/*      Arc/Circle : we approximate them by linear segments             */
-/* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"Arc") ||
-        EQUAL(pszBaseGeometry,"Circle") )
-    {
-        OGRLineString   *poLine = new OGRLineString();
-
-        if( !ParseGMLCoordinates( psNode, poLine, nSRSDimension ) ||
-            poLine->getNumPoints() != 3 )
-        {
-            delete poLine;
-            return NULL;
-        }
-        double x0 = poLine->getX(0);
-        double y0 = poLine->getY(0);
-        double x1 = poLine->getX(1);
-        double y1 = poLine->getY(1);
-        double x2 = poLine->getX(2);
-        double y2 = poLine->getY(2);
-        double dx01 = x1 - x0;
-        double dy01 = y1 - y0;
-        double dx12 = x2 - x1;
-        double dy12 = y2 - y1;
-        double c01 = dx01 * (x0 + x1) / 2 + dy01 * (y0 + y1) / 2;
-        double c12 = dx12 * (x1 + x2) / 2 + dy12 * (y1 + y2) / 2;
-        double det = dx01 * dy12 - dx12 * dy01;
-        if (det == 0)
-        {
-            return poLine;
-        }
-        double cx =  (c01 * dy12 - c12 * dy01) / det;
-        double cy =  (- c01 * dx12 + c12 * dx01) / det;
-
-        double alpha0 = atan2(y0 - cy, x0 - cx);
-        double alpha1 = atan2(y1 - cy, x1 - cx);
-        double alpha2 = atan2(y2 - cy, x2 - cx);
-        double alpha3;
-        double R = sqrt((x0 - cx) * (x0 - cx) + (y0 - cy) * (y0 - cy));
-
-        /* if det is negative, the orientation if clockwise */
-        if (det < 0)
-        {
-            if (alpha1 > alpha0)
-                alpha1 -= 2 * M_PI;
-            if (alpha2 > alpha1)
-                alpha2 -= 2 * M_PI;
-            alpha3 = alpha0 - 2 * M_PI;
-        }
-        else
-        {
-            if (alpha1 < alpha0)
-                alpha1 += 2 * M_PI;
-            if (alpha2 < alpha1)
-                alpha2 += 2 * M_PI;
-            alpha3 = alpha0 + 2 * M_PI;
-        }
-
-        CPLAssert((alpha0 <= alpha1 && alpha1 <= alpha2 && alpha2 <= alpha3) ||
-                  (alpha0 >= alpha1 && alpha1 >= alpha2 && alpha2 >= alpha3));
-
-        int nSign = (det >= 0) ? 1 : -1;
-
-        double alpha, dfRemainder;
-        double dfStep = CPLAtof(CPLGetConfigOption("OGR_ARC_STEPSIZE","4")) / 180 * M_PI;
-
-        // make sure the segments are not too short
-        double dfMinStepLength = CPLAtof( CPLGetConfigOption("OGR_ARC_MINLENGTH","0") );
-        if ( dfMinStepLength > 0.0 && dfStep * R < dfMinStepLength )
-        {
-            CPLDebug( "GML", "Increasing arc step to %lf° (was %lf° with segment length %lf at radius %lf; min segment length is %lf)",
-                      dfMinStepLength * 180.0 / M_PI / R,
-                      dfStep * 180.0 / M_PI,
-                      dfStep * R,
-                      R,
-                      dfMinStepLength );
-            dfStep = dfMinStepLength / R;
-        }
-
-        if (dfStep < 4. / 180 * M_PI)
-        {
-            CPLDebug( "GML", "Increasing arc step to %lf° (was %lf° with length %lf at radius %lf).",
-                      4. / 180 * M_PI,
-                      dfStep * 180.0 / M_PI,
-                      dfStep * R,
-                      R );
-            dfStep = 4. / 180 * M_PI;
-        }
-
-        poLine->setNumPoints(0);
-
-        dfStep *= nSign;
-
-        dfRemainder = fmod(alpha1 - alpha0, dfStep) / 2.0;
-
-        poLine->addPoint(x0, y0);
-
-        for(alpha = alpha0 + dfStep + dfRemainder; (alpha + dfRemainder - alpha1) * nSign < 0; alpha += dfStep)
-        {
-            poLine->addPoint(cx + R * cos(alpha), cy + R * sin(alpha));
-        }
-
-        poLine->addPoint(x1, y1);
-
-        dfRemainder = fmod(alpha2 - alpha1, dfStep) / 2.0;
-
-        for(alpha = alpha1 + dfStep + dfRemainder; (alpha + dfRemainder - alpha2) * nSign < 0; alpha += dfStep)
-        {
-            poLine->addPoint(cx + R * cos(alpha), cy + R * sin(alpha));
-        }
-
-        if (EQUAL(pszBaseGeometry,"Circle"))
-        {
-            for(alpha = alpha2; (alpha - alpha3) * nSign < 0; alpha += dfStep)
-            {
-                poLine->addPoint(cx + R * cos(alpha), cy + R * sin(alpha));
-            }
-            poLine->addPoint(x0, y0);
-        }
-        else
-        {
-            poLine->addPoint(x2, y2);
-        }
-
-        return poLine;
-    }
-#endif
 /* -------------------------------------------------------------------- */
 /*      Arc                                                             */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"Arc") )
+    if( EQUAL(pszBaseGeometry, "Arc") )
     {
-        OGRCircularString   *poCC = new OGRCircularString();
+        OGRCircularString *poCC = new OGRCircularString();
 
         if( !ParseGMLCoordinates( psNode, poCC, nSRSDimension ) )
         {
@@ -1391,7 +1598,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
         if( poCC->getNumPoints() != 3 )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Bad number of points in Arc");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Bad number of points in Arc");
             delete poCC;
             return NULL;
         }
@@ -1402,9 +1610,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*     ArcString                                                        */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"ArcString") )
+    if( EQUAL(pszBaseGeometry, "ArcString") )
     {
-        OGRCircularString   *poCC = new OGRCircularString();
+        OGRCircularString *poCC = new OGRCircularString();
 
         if( !ParseGMLCoordinates( psNode, poCC, nSRSDimension ) )
         {
@@ -1414,7 +1622,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
         if( poCC->getNumPoints() < 3 || (poCC->getNumPoints() % 2) != 1 )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Bad number of points in ArcString");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Bad number of points in ArcString");
             delete poCC;
             return NULL;
         }
@@ -1425,9 +1634,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      Circle                                                          */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"Circle") )
+    if( EQUAL(pszBaseGeometry, "Circle") )
     {
-        OGRLineString   *poLine = new OGRLineString();
+        OGRLineString *poLine = new OGRLineString();
 
         if( !ParseGMLCoordinates( psNode, poLine, nSRSDimension ) )
         {
@@ -1437,12 +1646,18 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
         if( poLine->getNumPoints() != 3 )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Bad number of points in Circle");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Bad number of points in Circle");
             delete poLine;
             return NULL;
         }
 
-        double R, cx, cy, alpha0, alpha1, alpha2;
+        double R = 0.0;
+        double cx = 0.0;
+        double cy = 0.0;
+        double alpha0 = 0.0;
+        double alpha1 = 0.0;
+        double alpha2 = 0.0;
         if( !OGRGeometryFactory::GetCurveParmeters(
                                poLine->getX(0), poLine->getY(0),
                                poLine->getX(1), poLine->getY(1),
@@ -1453,7 +1668,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return NULL;
         }
 
-        OGRCircularString   *poCC = new OGRCircularString();
+        OGRCircularString *poCC = new OGRCircularString();
         OGRPoint p;
         poLine->getPoint(0, &p);
         poCC->addPoint(&p);
@@ -1461,10 +1676,11 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         poCC->addPoint(&p);
         poLine->getPoint(2, &p);
         poCC->addPoint(&p);
-        double alpha4 = (alpha2 > alpha0) ? alpha0 + 2 * M_PI : alpha0 - 2 * M_PI;
-        double alpha3 = (alpha2 + alpha4) / 2;
-        double x = cx + R * cos(alpha3);
-        double y = cy + R * sin(alpha3);
+        const double alpha4 =
+            alpha2 > alpha0 ? alpha0 + kdf2PI : alpha0 - kdf2PI;
+        const double alpha3 = (alpha2 + alpha4) / 2.0;
+        const double x = cx + R * cos(alpha3);
+        const double y = cy + R * sin(alpha3);
         if( poCC->getCoordinateDimension() == 3 )
             poCC->addPoint( x, y, p.getZ() );
         else
@@ -1478,18 +1694,16 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      ArcByBulge                                                      */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"ArcByBulge") )
+    if( EQUAL(pszBaseGeometry, "ArcByBulge") )
     {
-        const CPLXMLNode *psChild;
-
-        psChild = FindBareXMLChild( psNode, "bulge");
+        const CPLXMLNode *psChild = FindBareXMLChild( psNode, "bulge");
         if( psChild == NULL || psChild->eType != CXT_Element )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Missing bulge element." );
             return NULL;
         }
-        double dfBulge = CPLAtof(psChild->psChild->pszValue);
+        const double dfBulge = CPLAtof(psChild->psChild->pszValue);
 
         psChild = FindBareXMLChild( psNode, "normal");
         if( psChild == NULL || psChild->eType != CXT_Element )
@@ -1500,7 +1714,6 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         }
         double dfNormal = CPLAtof(psChild->psChild->pszValue);
 
-
         OGRLineString* poLS = new OGRLineString();
         if( !ParseGMLCoordinates( psNode, poLS, nSRSDimension ) )
         {
@@ -1510,30 +1723,31 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
         if( poLS->getNumPoints() != 2 )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Bad number of points in ArcByBulge");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Bad number of points in ArcByBulge");
             delete poLS;
             return NULL;
         }
 
-        OGRCircularString   *poCC = new OGRCircularString();
+        OGRCircularString *poCC = new OGRCircularString();
         OGRPoint p;
         poLS->getPoint(0, &p);
         poCC->addPoint(&p);
 
-        double dfMidX = (poLS->getX(0) + poLS->getX(1)) / 2;
-        double dfMidY = (poLS->getY(0) + poLS->getY(1)) / 2;
-        double dfDirX = (poLS->getX(1) - poLS->getX(0)) / 2;
-        double dfDirY = (poLS->getY(1) - poLS->getY(0)) / 2;
+        const double dfMidX = (poLS->getX(0) + poLS->getX(1)) / 2.0;
+        const double dfMidY = (poLS->getY(0) + poLS->getY(1)) / 2.0;
+        const double dfDirX = (poLS->getX(1) - poLS->getX(0)) / 2.0;
+        const double dfDirY = (poLS->getY(1) - poLS->getY(0)) / 2.0;
         double dfNormX = -dfDirY;
         double dfNormY = dfDirX;
-        double dfNorm = sqrt(dfNormX * dfNormX + dfNormY * dfNormY);
-        if( dfNorm )
+        const double dfNorm = sqrt(dfNormX * dfNormX + dfNormY * dfNormY);
+        if( dfNorm != 0.0 )
         {
             dfNormX /= dfNorm;
             dfNormY /= dfNorm;
         }
-        double dfNewX = dfMidX + dfNormX * dfBulge * dfNormal;
-        double dfNewY = dfMidY + dfNormY * dfBulge * dfNormal;
+        const double dfNewX = dfMidX + dfNormX * dfBulge * dfNormal;
+        const double dfNewY = dfMidY + dfNormY * dfBulge * dfNormal;
 
         if( poCC->getCoordinateDimension() == 3 )
             poCC->addPoint( dfNewX, dfNewY, p.getZ() );
@@ -1550,19 +1764,20 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      ArcByCenterPoint                                                */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"ArcByCenterPoint") )
+    if( EQUAL(pszBaseGeometry, "ArcByCenterPoint") )
     {
-        const CPLXMLNode *psChild;
-
-        psChild = FindBareXMLChild( psNode, "radius");
+        const CPLXMLNode *psChild = FindBareXMLChild( psNode, "radius");
         if( psChild == NULL || psChild->eType != CXT_Element )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Missing radius element." );
             return NULL;
         }
-        double dfRadius = CPLAtof(CPLGetXMLValue((CPLXMLNode*)psChild, NULL, "0"));
-        const char* pszUnits = CPLGetXMLValue((CPLXMLNode*)psChild, "uom", NULL);
+        const double dfRadius =
+            CPLAtof(CPLGetXMLValue(const_cast<CPLXMLNode *>(psChild),
+                                   NULL, "0"));
+        const char* pszUnits =
+            CPLGetXMLValue(const_cast<CPLXMLNode *>(psChild), "uom", NULL);
 
         psChild = FindBareXMLChild( psNode, "startAngle");
         if( psChild == NULL || psChild->eType != CXT_Element )
@@ -1571,7 +1786,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                       "Missing startAngle element." );
             return NULL;
         }
-        double dfStartAngle = CPLAtof(CPLGetXMLValue((CPLXMLNode*)psChild, NULL, "0"));
+        const double dfStartAngle =
+            CPLAtof(CPLGetXMLValue(const_cast<CPLXMLNode *>(psChild),
+                                   NULL, "0"));
 
         psChild = FindBareXMLChild( psNode, "endAngle");
         if( psChild == NULL || psChild->eType != CXT_Element )
@@ -1580,7 +1797,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                       "Missing endAngle element." );
             return NULL;
         }
-        double dfEndAngle = CPLAtof(CPLGetXMLValue((CPLXMLNode*)psChild, NULL, "0"));
+        const double dfEndAngle =
+            CPLAtof(CPLGetXMLValue(const_cast<CPLXMLNode *>(psChild),
+                                   NULL, "0"));
 
         OGRPoint p;
         if( !ParseGMLCoordinates( psNode, &p, nSRSDimension ) )
@@ -1597,21 +1816,24 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             {
                 if( oSRS.IsGeographic() )
                 {
-                    bInvertedAxisOrder = CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong());
-                    bSRSUnitIsDegree = fabs(oSRS.GetAngularUnits(NULL) - CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
+                    bInvertedAxisOrder =
+                        CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong());
+                    bSRSUnitIsDegree = fabs(oSRS.GetAngularUnits(NULL) -
+                                            CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
                 }
             }
         }
 
-        double dfCenterX = p.getX();
-        double dfCenterY = p.getY();
+        const double dfCenterX = p.getX();
+        const double dfCenterY = p.getY();
 
         if( bSRSUnitIsDegree && pszUnits != NULL &&
             (EQUAL(pszUnits, "m") || EQUAL(pszUnits, "nm") ||
              EQUAL(pszUnits, "mi") || EQUAL(pszUnits, "ft")) )
         {
             OGRLineString* poLS = new OGRLineString();
-            double dfStep = CPLAtof(CPLGetConfigOption("OGR_ARC_STEPSIZE","4"));
+            const double dfStep =
+                CPLAtof(CPLGetConfigOption("OGR_ARC_STEPSIZE", "4"));
             double dfDistance = dfRadius;
             if( EQUAL(pszUnits, "nm") )
                 dfDistance *= CPLAtof(SRS_UL_INTL_NAUT_MILE_CONV);
@@ -1619,15 +1841,21 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 dfDistance *= CPLAtof(SRS_UL_INTL_STAT_MILE_CONV);
             else if( EQUAL(pszUnits, "ft") )
                 dfDistance *= CPLAtof(SRS_UL_INTL_FOOT_CONV);
-            double dfSign = (dfStartAngle < dfEndAngle) ? 1 : -1;
-            for(double dfAngle = dfStartAngle; (dfAngle - dfEndAngle) * dfSign < 0; dfAngle += dfSign * dfStep)
+            const double dfSign = dfStartAngle < dfEndAngle ? 1 : -1;
+            for( double dfAngle = dfStartAngle;
+                 (dfAngle - dfEndAngle) * dfSign < 0;
+                 dfAngle += dfSign * dfStep)
             {
-                double dfLong, dfLat;
+                double dfLong = 0.0;
+                double dfLat = 0.0;
                 if( bInvertedAxisOrder )
                 {
-                    OGRXPlane_ExtendPosition(dfCenterX, dfCenterY,
-                                             dfDistance, 90-dfAngle, /* not sure of angle conversion here...*/
-                                             &dfLat, &dfLong);
+                    OGRXPlane_ExtendPosition(
+                       dfCenterX, dfCenterY,
+                       dfDistance,
+                       // Not sure of angle conversion here.
+                       90.0 - dfAngle,
+                       &dfLat, &dfLong);
                     p.setY( dfLat );
                     p.setX( dfLong );
                 }
@@ -1642,11 +1870,14 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 poLS->addPoint(&p);
             }
 
-            double dfLong, dfLat;
+            double dfLong = 0.0;
+            double dfLat = 0.0;
             if( bInvertedAxisOrder )
             {
                 OGRXPlane_ExtendPosition(dfCenterX, dfCenterY,
-                                         dfDistance, 90-dfEndAngle, /* not sure of angle conversion here...*/
+                                         dfDistance,
+                                         // Not sure of angle conversion here.
+                                         90.0 - dfEndAngle,
                                          &dfLat, &dfLong);
                 p.setY( dfLat );
                 p.setX( dfLong );
@@ -1664,15 +1895,16 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return poLS;
         }
 
-        OGRCircularString   *poCC = new OGRCircularString();
-        p.setX( dfCenterX + dfRadius * cos(dfStartAngle * M_PI / 180.0) );
-        p.setY( dfCenterY + dfRadius * sin(dfStartAngle * M_PI / 180.0) );
+        OGRCircularString *poCC = new OGRCircularString();
+        p.setX(dfCenterX + dfRadius * cos(dfStartAngle * kdfD2R));
+        p.setY(dfCenterY + dfRadius * sin(dfStartAngle * kdfD2R));
         poCC->addPoint(&p);
-        p.setX( dfCenterX + dfRadius * cos((dfStartAngle+dfEndAngle)/2 * M_PI / 180.0) );
-        p.setY( dfCenterY + dfRadius * sin((dfStartAngle+dfEndAngle)/2 * M_PI / 180.0) );
+        const double dfAverageAngle = (dfStartAngle + dfEndAngle) / 2.0;
+        p.setX(dfCenterX + dfRadius * cos(dfAverageAngle * kdfD2R));
+        p.setY(dfCenterY + dfRadius * sin(dfAverageAngle * kdfD2R));
         poCC->addPoint(&p);
-        p.setX( dfCenterX + dfRadius * cos(dfEndAngle * M_PI / 180.0) );
-        p.setY( dfCenterY + dfRadius * sin(dfEndAngle * M_PI / 180.0) );
+        p.setX(dfCenterX + dfRadius * cos(dfEndAngle * kdfD2R));
+        p.setY(dfCenterY + dfRadius * sin(dfEndAngle * kdfD2R));
         poCC->addPoint(&p);
         return poCC;
     }
@@ -1680,19 +1912,20 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      CircleByCenterPoint                                             */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"CircleByCenterPoint") )
+    if( EQUAL(pszBaseGeometry, "CircleByCenterPoint") )
     {
-        const CPLXMLNode *psChild;
-
-        psChild = FindBareXMLChild( psNode, "radius");
+        const CPLXMLNode *psChild = FindBareXMLChild( psNode, "radius");
         if( psChild == NULL || psChild->eType != CXT_Element )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Missing radius element." );
             return NULL;
         }
-        double dfRadius = CPLAtof(CPLGetXMLValue((CPLXMLNode*)psChild, NULL, "0"));
-        const char* pszUnits = CPLGetXMLValue((CPLXMLNode*)psChild, "uom", NULL);
+        const double dfRadius =
+            CPLAtof(CPLGetXMLValue(const_cast<CPLXMLNode *>(psChild),
+                                   NULL, "0"));
+        const char* pszUnits =
+            CPLGetXMLValue(const_cast<CPLXMLNode *>(psChild), "uom", NULL);
 
         OGRPoint p;
         if( !ParseGMLCoordinates( psNode, &p, nSRSDimension ) )
@@ -1709,21 +1942,24 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             {
                 if( oSRS.IsGeographic() )
                 {
-                    bInvertedAxisOrder = CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong());
-                    bSRSUnitIsDegree = fabs(oSRS.GetAngularUnits(NULL) - CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
+                    bInvertedAxisOrder =
+                        CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong());
+                    bSRSUnitIsDegree = fabs(oSRS.GetAngularUnits(NULL) -
+                                            CPLAtof(SRS_UA_DEGREE_CONV)) < 1e-8;
                 }
             }
         }
 
-        double dfCenterX = p.getX();
-        double dfCenterY = p.getY();
+        const double dfCenterX = p.getX();
+        const double dfCenterY = p.getY();
 
         if( bSRSUnitIsDegree && pszUnits != NULL &&
             (EQUAL(pszUnits, "m") || EQUAL(pszUnits, "nm") ||
              EQUAL(pszUnits, "mi") || EQUAL(pszUnits, "ft")) )
         {
             OGRLineString* poLS = new OGRLineString();
-            double dfStep = CPLAtof(CPLGetConfigOption("OGR_ARC_STEPSIZE","4"));
+            const double dfStep =
+                CPLAtof(CPLGetConfigOption("OGR_ARC_STEPSIZE", "4"));
             double dfDistance = dfRadius;
             if( EQUAL(pszUnits, "nm") )
                 dfDistance *= CPLAtof(SRS_UL_INTL_NAUT_MILE_CONV);
@@ -1731,9 +1967,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                 dfDistance *= CPLAtof(SRS_UL_INTL_STAT_MILE_CONV);
             else if( EQUAL(pszUnits, "ft") )
                 dfDistance *= CPLAtof(SRS_UL_INTL_FOOT_CONV);
-            for(double dfAngle = 0; dfAngle < 360; dfAngle += dfStep)
+            for( double dfAngle = 0; dfAngle < 360; dfAngle += dfStep )
             {
-                double dfLong, dfLat;
+                double dfLong = 0.0;
+                double dfLat = 0.0;
                 if( bInvertedAxisOrder )
                 {
                     OGRXPlane_ExtendPosition(dfCenterX, dfCenterY,
@@ -1757,7 +1994,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return poLS;
         }
 
-        OGRCircularString   *poCC = new OGRCircularString();
+        OGRCircularString *poCC = new OGRCircularString();
         p.setX( dfCenterX - dfRadius );
         p.setY( dfCenterY );
         poCC->addPoint(&p);
@@ -1773,9 +2010,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      PointType                                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"PointType")
-        || EQUAL(pszBaseGeometry,"Point")
-        || EQUAL(pszBaseGeometry,"ConnectionPoint") )
+    if( EQUAL(pszBaseGeometry, "PointType")
+        || EQUAL(pszBaseGeometry, "Point")
+        || EQUAL(pszBaseGeometry, "ConnectionPoint") )
     {
         OGRPoint *poPoint = new OGRPoint();
 
@@ -1791,9 +2028,9 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      Box                                                             */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"BoxType") || EQUAL(pszBaseGeometry,"Box") )
+    if( EQUAL(pszBaseGeometry, "BoxType") || EQUAL(pszBaseGeometry, "Box") )
     {
-        OGRLineString  oPoints;
+        OGRLineString oPoints;
 
         if( !ParseGMLCoordinates( psNode, &oPoints, nSRSDimension ) )
             return NULL;
@@ -1824,10 +2061,12 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      Envelope                                                        */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"Envelope") )
+    if( EQUAL(pszBaseGeometry, "Envelope") )
     {
-        const CPLXMLNode* psLowerCorner = FindBareXMLChild( psNode, "lowerCorner");
-        const CPLXMLNode* psUpperCorner = FindBareXMLChild( psNode, "upperCorner");
+        const CPLXMLNode* psLowerCorner =
+            FindBareXMLChild( psNode, "lowerCorner");
+        const CPLXMLNode* psUpperCorner =
+            FindBareXMLChild( psNode, "upperCorner");
         if( psLowerCorner == NULL || psUpperCorner == NULL )
             return NULL;
         const char* pszLowerCorner = GetElementText(psLowerCorner);
@@ -1836,8 +2075,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return NULL;
         char** papszLowerCorner = CSLTokenizeString(pszLowerCorner);
         char** papszUpperCorner = CSLTokenizeString(pszUpperCorner);
-        int nTokenCountLC = CSLCount(papszLowerCorner);
-        int nTokenCountUC = CSLCount(papszUpperCorner);
+        const int nTokenCountLC = CSLCount(papszLowerCorner);
+        const int nTokenCountUC = CSLCount(papszUpperCorner);
         if( nTokenCountLC < 2 || nTokenCountUC < 2 )
         {
             CSLDestroy(papszLowerCorner);
@@ -1845,10 +2084,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return NULL;
         }
 
-        double dfLLX = CPLAtof(papszLowerCorner[0]);
-        double dfLLY = CPLAtof(papszLowerCorner[1]);
-        double dfURX = CPLAtof(papszUpperCorner[0]);
-        double dfURY = CPLAtof(papszUpperCorner[1]);
+        const double dfLLX = CPLAtof(papszLowerCorner[0]);
+        const double dfLLY = CPLAtof(papszLowerCorner[1]);
+        const double dfURX = CPLAtof(papszUpperCorner[0]);
+        const double dfURY = CPLAtof(papszUpperCorner[1]);
         CSLDestroy(papszLowerCorner);
         CSLDestroy(papszUpperCorner);
 
@@ -1866,76 +2105,88 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         return poPoly;
     }
 
-/* ------------------------const CPLXMLNode *psChild;-------------------------------------------- */
-/*      MultiPolygon / MultiSurface / CompositeSurface                  */
-/*                                                                      */
-/* For CompositeSurface, this is a very rough approximation to deal with*/
-/* it as a MultiPolygon, because it can several faces of a 3D volume... */
-/* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"MultiPolygon") ||
-        EQUAL(pszBaseGeometry,"MultiSurface") ||
-        EQUAL(pszBaseGeometry,"CompositeSurface") )
+/* --------------------------------------------------------------------- */
+/*      MultiPolygon / MultiSurface / CompositeSurface                   */
+/*                                                                       */
+/* For CompositeSurface, this is a very rough approximation to deal with */
+/* it as a MultiPolygon, because it can several faces of a 3D volume.    */
+/* --------------------------------------------------------------------- */
+    if( EQUAL(pszBaseGeometry, "MultiPolygon") ||
+        EQUAL(pszBaseGeometry, "MultiSurface") ||
+        EQUAL(pszBaseGeometry, "CompositeSurface") )
     {
-        const CPLXMLNode *psChild;
-        OGRMultiSurface* poMS;
-        if( EQUAL(pszBaseGeometry,"MultiPolygon") )
-            poMS = new OGRMultiPolygon();
-        else
-            poMS = new OGRMultiSurface();
+        OGRMultiSurface* poMS =
+            EQUAL(pszBaseGeometry, "MultiPolygon")
+            ? new OGRMultiPolygon()
+            : new OGRMultiSurface();
         bool bReconstructTopology = false;
         bool bChildrenAreAllPolygons = true;
 
-        // Iterate over children
-        for( psChild = psNode->psChild;
+        // Iterate over children.
+        for( const CPLXMLNode *psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
         {
             const char* pszMemberElement = BareGMLElement(psChild->pszValue);
             if( psChild->eType == CXT_Element
-                && (EQUAL(pszMemberElement,"polygonMember") ||
-                    EQUAL(pszMemberElement,"surfaceMember")) )
+                && (EQUAL(pszMemberElement, "polygonMember") ||
+                    EQUAL(pszMemberElement, "surfaceMember")) )
             {
                 const CPLXMLNode* psSurfaceChild = GetChildElement(psChild);
 
-                if (psSurfaceChild != NULL)
+                if( psSurfaceChild != NULL )
                 {
-                    /* Cf #5421 where there are PolygonPatch with only inner rings */
-                    const CPLXMLNode* psPolygonPatch = GetChildElement(GetChildElement(psSurfaceChild));
-                    const CPLXMLNode* psPolygonPatchChild;
+                    // Cf #5421 where there are PolygonPatch with only inner
+                    // rings.
+                    const CPLXMLNode* psPolygonPatch =
+                        GetChildElement(GetChildElement(psSurfaceChild));
+                    const CPLXMLNode* psPolygonPatchChild = NULL;
                     if( psPolygonPatch != NULL &&
                         psPolygonPatch->eType == CXT_Element &&
-                        EQUAL(BareGMLElement(psPolygonPatch->pszValue),"PolygonPatch") &&
-                        (psPolygonPatchChild = GetChildElement(psPolygonPatch)) != NULL &&
-                        EQUAL(BareGMLElement(psPolygonPatchChild->pszValue),"interior") )
+                        EQUAL(BareGMLElement(psPolygonPatch->pszValue),
+                              "PolygonPatch") &&
+                        (psPolygonPatchChild = GetChildElement(psPolygonPatch))
+                        != NULL &&
+                        EQUAL(BareGMLElement(psPolygonPatchChild->pszValue),
+                              "interior") )
                     {
                         // Find all inner rings
-                        for( const CPLXMLNode* psChild2 = psPolygonPatch->psChild;
-                            psChild2 != NULL;
-                            psChild2 = psChild2->psNext )
+                        for( const CPLXMLNode* psChild2 =
+                                 psPolygonPatch->psChild;
+                             psChild2 != NULL;
+                             psChild2 = psChild2->psNext )
                         {
                             if( psChild2->eType == CXT_Element
-                                && (EQUAL(BareGMLElement(psChild2->pszValue),"interior")))
+                                && (EQUAL(BareGMLElement(psChild2->pszValue),
+                                          "interior")))
                             {
-                                const CPLXMLNode* psInteriorChild = GetChildElement(psChild2);
-                                OGRGeometry* poRing;
-                                if (psInteriorChild != NULL)
-                                    poRing =
-                                        GML2OGRGeometry_XMLNode_Internal(
-                                            psInteriorChild, nPseudoBoolGetSecondaryGeometryOption,
-                                            nRecLevel + 1, nSRSDimension, pszSRSName );
-                                else
-                                    poRing = NULL;
-                                if (poRing == NULL)
+                                const CPLXMLNode* psInteriorChild =
+                                    GetChildElement(psChild2);
+                                OGRGeometry* poRing =
+                                    psInteriorChild == NULL
+                                    ? NULL
+                                    : GML2OGRGeometry_XMLNode_Internal(
+                                          psInteriorChild,
+                                          nPseudoBoolGetSecondaryGeometryOption,
+                                          nRecLevel + 1,
+                                          nSRSDimension, pszSRSName );
+                                if( poRing == NULL )
                                 {
-                                    CPLError( CE_Failure, CPLE_AppDefined, "Invalid interior ring");
+                                    CPLError( CE_Failure, CPLE_AppDefined,
+                                              "Invalid interior ring");
                                     delete poMS;
                                     return NULL;
                                 }
-                                if( !EQUAL(poRing->getGeometryName(),"LINEARRING") )
+                                if( !EQUAL(poRing->getGeometryName(),
+                                           "LINEARRING") )
                                 {
-                                    CPLError( CE_Failure, CPLE_AppDefined,
-                                            "%s: Got %.500s geometry as innerBoundaryIs instead of LINEARRING.",
-                                            pszBaseGeometry, poRing->getGeometryName() );
+                                    CPLError(
+                                        CE_Failure, CPLE_AppDefined,
+                                        "%s: Got %.500s geometry as "
+                                        "innerBoundaryIs instead of "
+                                        "LINEARRING.",
+                                        pszBaseGeometry,
+                                        poRing->getGeometryName());
                                     delete poRing;
                                     delete poMS;
                                     return NULL;
@@ -1943,7 +2194,15 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
                                 bReconstructTopology = true;
                                 OGRPolygon *poPolygon = new OGRPolygon();
-                                poPolygon->addRingDirectly( (OGRLinearRing*)poRing );
+                                OGRLinearRing *poLinearRing =
+                                    dynamic_cast<OGRLinearRing *>(poRing);
+                                if( poLinearRing == NULL )
+                                {
+                                    CPLError(CE_Fatal, CPLE_AppDefined,
+                                             "dynamic_cast failed.  "
+                                             "Expected OGRLinearRing.");
+                                }
+                                poPolygon->addRingDirectly(poLinearRing);
                                 poMS->addGeometryDirectly( poPolygon );
                             }
                         }
@@ -1954,9 +2213,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                             GML2OGRGeometry_XMLNode_Internal( psSurfaceChild,
                                   nPseudoBoolGetSecondaryGeometryOption,
                                   nRecLevel + 1, nSRSDimension, pszSRSName );
-                        if( !GML2OGRGeometry_AddToMultiSurface(poMS, poGeom,
-                                                               pszMemberElement,
-                                                               bChildrenAreAllPolygons) )
+                        if( !GML2OGRGeometry_AddToMultiSurface(
+                                 poMS, poGeom,
+                                 pszMemberElement,
+                                 bChildrenAreAllPolygons) )
                         {
                             delete poGeom;
                             delete poMS;
@@ -1965,27 +2225,27 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     }
                 }
             }
-            else if (psChild->eType == CXT_Element
-                    && EQUAL(pszMemberElement,"surfaceMembers") )
+            else if( psChild->eType == CXT_Element
+                     && EQUAL(pszMemberElement, "surfaceMembers") )
             {
-                const CPLXMLNode *psChild2;
-                for( psChild2 = psChild->psChild;
+                for( const CPLXMLNode *psChild2 = psChild->psChild;
                      psChild2 != NULL;
                      psChild2 = psChild2->psNext )
                 {
                     pszMemberElement = BareGMLElement(psChild2->pszValue);
                     if( psChild2->eType == CXT_Element
-                        && (EQUAL(pszMemberElement,"Surface") ||
-                            EQUAL(pszMemberElement,"Polygon") ||
-                            EQUAL(pszMemberElement,"PolygonPatch") ||
-                            EQUAL(pszMemberElement,"CompositeSurface")) )
+                        && (EQUAL(pszMemberElement, "Surface") ||
+                            EQUAL(pszMemberElement, "Polygon") ||
+                            EQUAL(pszMemberElement, "PolygonPatch") ||
+                            EQUAL(pszMemberElement, "CompositeSurface")) )
                     {
                         OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
                             psChild2, nPseudoBoolGetSecondaryGeometryOption,
                             nRecLevel + 1, nSRSDimension, pszSRSName );
-                        if( !GML2OGRGeometry_AddToMultiSurface(poMS, poGeom,
-                                                               pszMemberElement,
-                                                               bChildrenAreAllPolygons) )
+                        if( !GML2OGRGeometry_AddToMultiSurface(
+                                poMS, poGeom,
+                                pszMemberElement,
+                                bChildrenAreAllPolygons) )
                         {
                             delete poGeom;
                             delete poMS;
@@ -1998,15 +2258,14 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
         if( bReconstructTopology && bChildrenAreAllPolygons )
         {
-            OGRMultiPolygon* poMPoly;
-            if( wkbFlatten(poMS->getGeometryType()) == wkbMultiSurface )
-                poMPoly = OGRMultiSurface::CastToMultiPolygon(poMS);
-            else
-                poMPoly = (OGRMultiPolygon*)poMS;
-            CPLAssert(poMPoly); /* that should not fail really ! */
-            int nPolygonCount = poMPoly->getNumGeometries();
+            OGRMultiPolygon* poMPoly =
+                wkbFlatten(poMS->getGeometryType()) == wkbMultiSurface
+                ? OGRMultiSurface::CastToMultiPolygon(poMS)
+                : dynamic_cast<OGRMultiPolygon *>(poMS);
+            CPLAssert(poMPoly);  // Should not fail.
+            const int nPolygonCount = poMPoly->getNumGeometries();
             OGRGeometry** papoPolygons = new OGRGeometry*[ nPolygonCount ];
-            for(int i=0;i<nPolygonCount;i++)
+            for( int i = 0; i < nPolygonCount; i++ )
             {
                 papoPolygons[i] = poMPoly->getGeometryRef(0);
                 poMPoly->removeGeometry(0, FALSE);
@@ -2026,42 +2285,43 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             {
                 return OGRMultiSurface::CastToMultiPolygon(poMS);
             }
-            else
-                return poMS;
+
+            return poMS;
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      MultiPoint                                                      */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"MultiPoint") )
+    if( EQUAL(pszBaseGeometry, "MultiPoint") )
     {
-        const CPLXMLNode *psChild;
         OGRMultiPoint *poMP = new OGRMultiPoint();
 
-        // collect points.
-        for( psChild = psNode->psChild;
+        // Collect points.
+        for( const CPLXMLNode *psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"pointMember") )
+                && EQUAL(BareGMLElement(psChild->pszValue), "pointMember") )
             {
                 const CPLXMLNode* psPointChild = GetChildElement(psChild);
-                OGRGeometry *poPointMember;
 
-                if (psPointChild != NULL)
+                if( psPointChild != NULL )
                 {
-                    poPointMember =
+                    OGRGeometry *poPointMember =
                         GML2OGRGeometry_XMLNode_Internal( psPointChild,
                               nPseudoBoolGetSecondaryGeometryOption,
                               nRecLevel + 1, nSRSDimension, pszSRSName );
-                    if( poPointMember == NULL
-                        || wkbFlatten(poPointMember->getGeometryType()) != wkbPoint )
+                    if( poPointMember == NULL ||
+                        wkbFlatten(poPointMember->getGeometryType()) !=
+                        wkbPoint )
                     {
                         CPLError( CE_Failure, CPLE_AppDefined,
-                                "MultiPoint: Got %.500s geometry as pointMember instead of POINT",
-                                poPointMember ? poPointMember->getGeometryName() : "NULL" );
+                                  "MultiPoint: Got %.500s geometry as "
+                                  "pointMember instead of POINT",
+                                  poPointMember
+                                  ? poPointMember->getGeometryName() : "NULL" );
                         delete poPointMember;
                         delete poMP;
                         return NULL;
@@ -2070,21 +2330,22 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     poMP->addGeometryDirectly( poPointMember );
                 }
             }
-            else if (psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"pointMembers") )
+            else if( psChild->eType == CXT_Element
+                     && EQUAL(BareGMLElement(psChild->pszValue),
+                              "pointMembers") )
             {
-                const CPLXMLNode *psChild2;
-                for( psChild2 = psChild->psChild;
+                for( const CPLXMLNode *psChild2 = psChild->psChild;
                      psChild2 != NULL;
                      psChild2 = psChild2->psNext )
                 {
                     if( psChild2->eType == CXT_Element
-                        && (EQUAL(BareGMLElement(psChild2->pszValue),"Point")) )
+                        && (EQUAL(BareGMLElement(psChild2->pszValue),
+                                  "Point")) )
                     {
                         OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
                             psChild2, nPseudoBoolGetSecondaryGeometryOption,
                             nRecLevel + 1, nSRSDimension, pszSRSName );
-                        if (poGeom == NULL)
+                        if( poGeom == NULL )
                         {
                             CPLError( CE_Failure, CPLE_AppDefined, "Invalid %s",
                                     BareGMLElement(psChild2->pszValue));
@@ -2092,15 +2353,24 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                             return NULL;
                         }
 
-                        if (wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
+                        if( wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
                         {
-                            poMP->addGeometryDirectly( (OGRPoint *)poGeom );
+                            OGRPoint *poPoint =
+                                dynamic_cast<OGRPoint *>(poGeom);
+                            if( poPoint == NULL )
+                            {
+                                CPLError(CE_Fatal, CPLE_AppDefined,
+                                         "dynamic_cast failed.  "
+                                         "Expected OGRCPoint.");
+                            }
+                            poMP->addGeometryDirectly( poPoint );
                         }
                         else
                         {
                             CPLError( CE_Failure, CPLE_AppDefined,
-                                    "Got %.500s geometry as pointMember instead of POINT.",
-                                    poGeom->getGeometryName() );
+                                      "Got %.500s geometry as pointMember "
+                                      "instead of POINT.",
+                                      poGeom->getGeometryName() );
                             delete poGeom;
                             delete poMP;
                             return NULL;
@@ -2116,34 +2386,34 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      MultiLineString                                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"MultiLineString") )
+    if( EQUAL(pszBaseGeometry, "MultiLineString") )
     {
-        const CPLXMLNode *psChild;
         OGRMultiLineString *poMLS = new OGRMultiLineString();
 
-        // collect lines
-        for( psChild = psNode->psChild;
+        // Collect lines.
+        for( const CPLXMLNode *psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"lineStringMember") )
+                && EQUAL(BareGMLElement(psChild->pszValue),
+                         "lineStringMember") )
             {
                 const CPLXMLNode* psLineStringChild = GetChildElement(psChild);
-                OGRGeometry *poGeom;
-
-                if (psLineStringChild != NULL)
-                    poGeom = GML2OGRGeometry_XMLNode_Internal( psLineStringChild,
+                OGRGeometry *poGeom =
+                    psLineStringChild == NULL
+                    ? NULL
+                    : GML2OGRGeometry_XMLNode_Internal(
+                          psLineStringChild,
                           nPseudoBoolGetSecondaryGeometryOption,
                           nRecLevel + 1, nSRSDimension, pszSRSName );
-                else
-                    poGeom = NULL;
                 if( poGeom == NULL
                     || wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "MultiLineString: Got %.500s geometry as Member instead of LINESTRING.",
-                              poGeom ? poGeom->getGeometryName() : "NULL" );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "MultiLineString: Got %.500s geometry as Member "
+                             "instead of LINESTRING.",
+                             poGeom ? poGeom->getGeometryName() : "NULL" );
                     delete poGeom;
                     delete poMLS;
                     return NULL;
@@ -2156,26 +2426,24 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         return poMLS;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      MultiCurve                                                      */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"MultiCurve") )
+    if( EQUAL(pszBaseGeometry, "MultiCurve") )
     {
-        const CPLXMLNode *psChild;
         OGRMultiCurve *poMC = new OGRMultiCurve();
         bool bChildrenAreAllLineString = true;
 
-        // collect curveMembers
-        for( psChild = psNode->psChild;
+        // Collect curveMembers.
+        for( const CPLXMLNode *psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"curveMember") )
+                && EQUAL(BareGMLElement(psChild->pszValue), "curveMember") )
             {
                 const CPLXMLNode *psChild2 = GetChildElement(psChild);
-                if( psChild2 != NULL ) /* empty curveMember is valid */
+                if( psChild2 != NULL )  // Empty curveMember is valid.
                 {
                     OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
                         psChild2, nPseudoBoolGetSecondaryGeometryOption,
@@ -2183,9 +2451,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     if( poGeom == NULL ||
                         !OGR_GT_IsCurve(poGeom->getGeometryType()) )
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                "MultiCurve: Got %.500s geometry as Member instead of a curve.",
-                                poGeom ? poGeom->getGeometryName() : "NULL" );
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "MultiCurve: Got %.500s geometry as Member "
+                                 "instead of a curve.",
+                                 poGeom ? poGeom->getGeometryName() : "NULL" );
                         if( poGeom != NULL ) delete poGeom;
                         delete poMC;
                         return NULL;
@@ -2200,11 +2469,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     }
             }
             }
-            else if (psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"curveMembers") )
+            else if( psChild->eType == CXT_Element &&
+                     EQUAL(BareGMLElement(psChild->pszValue), "curveMembers") )
             {
-                const CPLXMLNode *psChild2;
-                for( psChild2 = psChild->psChild;
+                for( const CPLXMLNode *psChild2 = psChild->psChild;
                      psChild2 != NULL;
                      psChild2 = psChild2->psNext )
                 {
@@ -2213,18 +2481,21 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                         OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
                             psChild2, nPseudoBoolGetSecondaryGeometryOption,
                             nRecLevel + 1, nSRSDimension, pszSRSName );
-                        if (poGeom == NULL ||
+                        if( poGeom == NULL ||
                             !OGR_GT_IsCurve(poGeom->getGeometryType()) )
                         {
-                            CPLError( CE_Failure, CPLE_AppDefined,
-                                    "MultiCurve: Got %.500s geometry as Member instead of a curve.",
-                                    poGeom ? poGeom->getGeometryName() : "NULL" );
+                            CPLError(
+                                CE_Failure, CPLE_AppDefined,
+                                "MultiCurve: Got %.500s geometry as "
+                                "Member instead of a curve.",
+                                poGeom ? poGeom->getGeometryName() : "NULL" );
                             if( poGeom != NULL ) delete poGeom;
                             delete poMC;
                             return NULL;
                         }
 
-                        if( wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
+                        if( wkbFlatten(poGeom->getGeometryType()) !=
+                            wkbLineString )
                             bChildrenAreAllLineString = false;
 
                         if( poMC->addGeometryDirectly( poGeom ) != OGRERR_NONE )
@@ -2240,36 +2511,34 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         {
             return OGRMultiCurve::CastToMultiLineString(poMC);
         }
-        else
-            return poMC;
-    }
 
+        return poMC;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      CompositeCurve                                                  */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"CompositeCurve") )
+    if( EQUAL(pszBaseGeometry, "CompositeCurve") )
     {
-        const CPLXMLNode *psChild;
         OGRCompoundCurve *poCC = new OGRCompoundCurve();
         bool bChildrenAreAllLineString = true;
 
-        // collect curveMembers
-        for( psChild = psNode->psChild;
+        // Collect curveMembers.
+        for( const CPLXMLNode *psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"curveMember") )
+                && EQUAL(BareGMLElement(psChild->pszValue), "curveMember") )
             {
                 const CPLXMLNode *psChild2 = GetChildElement(psChild);
-                if( psChild2 != NULL ) /* empty curveMember is valid */
+                if( psChild2 != NULL )  // Empty curveMember is valid.
                 {
                     OGRGeometry*poGeom = GML2OGRGeometry_XMLNode_Internal(
                         psChild2, nPseudoBoolGetSecondaryGeometryOption,
                         nRecLevel + 1, nSRSDimension, pszSRSName );
-                    if( !GML2OGRGeometry_AddToCompositeCurve(poCC, poGeom,
-                                                                bChildrenAreAllLineString) )
+                    if( !GML2OGRGeometry_AddToCompositeCurve(
+                             poCC, poGeom, bChildrenAreAllLineString) )
                     {
                         delete poGeom;
                         delete poCC;
@@ -2277,11 +2546,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     }
                 }
             }
-            else if (psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"curveMembers") )
+            else if( psChild->eType == CXT_Element &&
+                     EQUAL(BareGMLElement(psChild->pszValue), "curveMembers") )
             {
-                const CPLXMLNode *psChild2;
-                for( psChild2 = psChild->psChild;
+                for( const CPLXMLNode *psChild2 = psChild->psChild;
                      psChild2 != NULL;
                      psChild2 = psChild2->psNext )
                 {
@@ -2290,8 +2558,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                         OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
                             psChild2, nPseudoBoolGetSecondaryGeometryOption,
                             nRecLevel + 1, nSRSDimension, pszSRSName );
-                        if( !GML2OGRGeometry_AddToCompositeCurve(poCC, poGeom,
-                                                             bChildrenAreAllLineString) )
+                        if( !GML2OGRGeometry_AddToCompositeCurve(
+                                poCC, poGeom, bChildrenAreAllLineString) )
                         {
                             delete poGeom;
                             delete poCC;
@@ -2306,18 +2574,16 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         {
             return OGRCurve::CastToLineString(poCC);
         }
-        else
-            return poCC;
+
+        return poCC;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Curve                                                           */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"Curve") )
+    if( EQUAL(pszBaseGeometry, "Curve") )
     {
-        const CPLXMLNode *psChild;
-
-        psChild = FindBareXMLChild( psNode, "segments");
+        const CPLXMLNode *psChild = FindBareXMLChild( psNode, "segments");
         if( psChild == NULL )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -2325,11 +2591,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return NULL;
         }
 
-        OGRGeometry *poGeom;
-
-        poGeom = GML2OGRGeometry_XMLNode_Internal(
-            psChild, nPseudoBoolGetSecondaryGeometryOption,
-            nRecLevel + 1, nSRSDimension, pszSRSName );
+        OGRGeometry *poGeom =
+            GML2OGRGeometry_XMLNode_Internal(
+                psChild, nPseudoBoolGetSecondaryGeometryOption,
+                nRecLevel + 1, nSRSDimension, pszSRSName );
         if( poGeom == NULL ||
             !OGR_GT_IsCurve(poGeom->getGeometryType()) )
         {
@@ -2346,35 +2611,37 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      segments                                                        */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"segments") )
+    if( EQUAL(pszBaseGeometry, "segments") )
     {
-        const CPLXMLNode *psChild;
         OGRCurve* poCurve = NULL;
         OGRCompoundCurve *poCC = NULL;
         bool bChildrenAreAllLineString = true;
 
-        for( psChild = psNode->psChild;
+        for( const CPLXMLNode *psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
 
         {
             if( psChild->eType == CXT_Element
-                /*&& (EQUAL(BareGMLElement(psChild->pszValue),"LineStringSegment") ||
-                    EQUAL(BareGMLElement(psChild->pszValue),"GeodesicString") ||
-                    EQUAL(BareGMLElement(psChild->pszValue),"Arc") ||
-                    EQUAL(BareGMLElement(psChild->pszValue),"Circle"))*/ )
+                // && (EQUAL(BareGMLElement(psChild->pszValue),
+                //           "LineStringSegment") ||
+                //     EQUAL(BareGMLElement(psChild->pszValue),
+                //           "GeodesicString") ||
+                //    EQUAL(BareGMLElement(psChild->pszValue), "Arc") ||
+                //    EQUAL(BareGMLElement(psChild->pszValue), "Circle"))
+                )
             {
-                OGRGeometry *poGeom;
-
-                poGeom = GML2OGRGeometry_XMLNode_Internal(
-                    psChild, nPseudoBoolGetSecondaryGeometryOption,
-                    nRecLevel + 1, nSRSDimension, pszSRSName );
+                OGRGeometry *poGeom =
+                    GML2OGRGeometry_XMLNode_Internal(
+                        psChild, nPseudoBoolGetSecondaryGeometryOption,
+                        nRecLevel + 1, nSRSDimension, pszSRSName );
                 if( poGeom == NULL ||
                     !OGR_GT_IsCurve(poGeom->getGeometryType()) )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "segments: Got %.500s geometry as Member instead of curve.",
-                              poGeom ? poGeom->getGeometryName() : "NULL" );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "segments: Got %.500s geometry as Member "
+                             "instead of curve.",
+                             poGeom ? poGeom->getGeometryName() : "NULL");
                     delete poGeom;
                     delete poCurve;
                     delete poCC;
@@ -2385,7 +2652,15 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     bChildrenAreAllLineString = false;
 
                 if( poCC == NULL && poCurve == NULL )
-                    poCurve = (OGRCurve*)poGeom;
+                {
+                    poCurve = dynamic_cast<OGRCurve *>(poGeom);
+                    if( poCurve == NULL )
+                    {
+                        CPLError(CE_Fatal, CPLE_AppDefined,
+                                 "dynamic_cast failed.  Expected OGRCurve.");
+                    }
+
+                }
                 else
                 {
                     if( poCC == NULL )
@@ -2401,7 +2676,14 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                         poCurve = NULL;
                     }
 
-                    if( poCC->addCurveDirectly((OGRCurve*)poGeom) != OGRERR_NONE )
+                    OGRCurve *poAsCurve = dynamic_cast<OGRCurve *>(poGeom);
+                    if( poAsCurve == NULL )
+                    {
+                        CPLError(CE_Fatal, CPLE_AppDefined,
+                                 "dynamic_cast failed.  Expected OGRCurve.");
+                    }
+
+                    if( poCC->addCurveDirectly(poAsCurve) != OGRERR_NONE )
                     {
                         delete poGeom;
                         delete poCC;
@@ -2420,44 +2702,41 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         {
             return OGRCurve::CastToLineString(poCC);
         }
-        else
-        {
-            return poCC;
-        }
+
+        return poCC;
     }
 
 /* -------------------------------------------------------------------- */
 /*      MultiGeometry                                                   */
 /* CAUTION: OGR < 1.8.0 produced GML with GeometryCollection, which is  */
 /* not a valid GML 2 keyword! The right name is MultiGeometry. Let's be */
-/* tolerant with the non compliant files we produced...                 */
+/* tolerant with the non compliant files we produced.                   */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"MultiGeometry") ||
-        EQUAL(pszBaseGeometry,"GeometryCollection") )
+    if( EQUAL(pszBaseGeometry, "MultiGeometry") ||
+        EQUAL(pszBaseGeometry, "GeometryCollection") )
     {
-        const CPLXMLNode *psChild;
         OGRGeometryCollection *poGC = new OGRGeometryCollection();
 
-        // collect geoms
-        for( psChild = psNode->psChild;
+        // Collect geoms.
+        for( const CPLXMLNode *psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"geometryMember") )
+                && EQUAL(BareGMLElement(psChild->pszValue), "geometryMember") )
             {
                 const CPLXMLNode* psGeometryChild = GetChildElement(psChild);
-                OGRGeometry *poGeom;
 
-                if (psGeometryChild != NULL)
+                if( psGeometryChild != NULL )
                 {
-                    poGeom = GML2OGRGeometry_XMLNode_Internal(
+                    OGRGeometry *poGeom = GML2OGRGeometry_XMLNode_Internal(
                         psGeometryChild, nPseudoBoolGetSecondaryGeometryOption,
                         nRecLevel + 1, nSRSDimension, pszSRSName );
                     if( poGeom == NULL )
                     {
                         CPLError( CE_Failure, CPLE_AppDefined,
-                                "GeometryCollection: Failed to get geometry in geometryMember" );
+                                  "GeometryCollection: Failed to get geometry "
+                                  "in geometryMember" );
                         delete poGeom;
                         delete poGC;
                         return NULL;
@@ -2474,26 +2753,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      Directed Edge                                                   */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"directedEdge") )
+    if( EQUAL(pszBaseGeometry, "directedEdge") )
     {
-        const CPLXMLNode *psEdge,
-                         *psdirectedNode,
-                         *psNodeElement,
-                         *pspointProperty,
-                         *psPoint,
-                         *psCurveProperty,
-                         *psCurve;
-        bool              bEdgeOrientation = true;
-        bool              bNodeOrientation = true;
-        OGRGeometry      *poGeom;
-        OGRLineString    *poLineString;
-        OGRPoint         *poPositiveNode = NULL, *poNegativeNode = NULL;
-        OGRMultiPoint    *poMP;
-
-        bEdgeOrientation = GetElementOrientation(psNode);
-
-        //collect edge
-        psEdge = FindBareXMLChild(psNode,"Edge");
+        // Collect edge.
+        const CPLXMLNode *psEdge = FindBareXMLChild(psNode, "Edge");
         if( psEdge == NULL )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -2501,24 +2764,37 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return NULL;
         }
 
+        // TODO(schwehr): Localize vars after removing gotos.
+        OGRGeometry *poGeom = NULL;
+        const CPLXMLNode *psNodeElement = NULL;
+        const CPLXMLNode *psPointProperty = NULL;
+        const CPLXMLNode *psPoint = NULL;
+        bool bNodeOrientation = true;
+        OGRPoint *poPositiveNode = NULL;
+        OGRPoint *poNegativeNode = NULL;
+
+        const bool bEdgeOrientation = GetElementOrientation(psNode);
+
         if( bGetSecondaryGeometry )
         {
-            psdirectedNode = FindBareXMLChild(psEdge,"directedNode");
+            const CPLXMLNode *psdirectedNode =
+                FindBareXMLChild(psEdge, "directedNode");
             if( psdirectedNode == NULL ) goto nonode;
 
             bNodeOrientation = GetElementOrientation( psdirectedNode );
 
-            psNodeElement = FindBareXMLChild(psdirectedNode,"Node");
+            psNodeElement = FindBareXMLChild(psdirectedNode, "Node");
             if( psNodeElement == NULL ) goto nonode;
 
-            pspointProperty = FindBareXMLChild(psNodeElement,"pointProperty");
-            if( pspointProperty == NULL )
-                pspointProperty = FindBareXMLChild(psNodeElement,"connectionPointProperty");
-            if( pspointProperty == NULL ) goto nonode;
+            psPointProperty = FindBareXMLChild(psNodeElement, "pointProperty");
+            if( psPointProperty == NULL )
+                psPointProperty = FindBareXMLChild(psNodeElement,
+                                                   "connectionPointProperty");
+            if( psPointProperty == NULL ) goto nonode;
 
-            psPoint = FindBareXMLChild(pspointProperty,"Point");
+            psPoint = FindBareXMLChild(psPointProperty, "Point");
             if( psPoint == NULL )
-                psPoint = FindBareXMLChild(pspointProperty,"ConnectionPoint");
+                psPoint = FindBareXMLChild(psPointProperty, "ConnectionPoint");
             if( psPoint == NULL ) goto nonode;
 
             poGeom = GML2OGRGeometry_XMLNode_Internal(
@@ -2527,19 +2803,27 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             if( poGeom == NULL
                 || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
             {
-/*                CPLError( CE_Failure, CPLE_AppDefined,
-                      "Got %.500s geometry as Member instead of POINT.",
-                      poGeom ? poGeom->getGeometryName() : "NULL" );*/
+                // CPLError( CE_Failure, CPLE_AppDefined,
+                //           "Got %.500s geometry as Member instead of POINT.",
+                //           poGeom ? poGeom->getGeometryName() : "NULL" );
                 if( poGeom != NULL) delete poGeom;
                 goto nonode;
             }
 
-            if( ( bNodeOrientation == bEdgeOrientation ) != bOrientation )
-                poPositiveNode = (OGRPoint *)poGeom;
-            else
-                poNegativeNode = (OGRPoint *)poGeom;
+            {
+                OGRPoint *poPoint = dynamic_cast<OGRPoint *>(poGeom);
+                if( poPoint == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                             "dynamic_cast failed.  Expected OGRPoint.");
+                }
+                if( ( bNodeOrientation == bEdgeOrientation ) != bOrientation )
+                    poPositiveNode = poPoint;
+                else
+                    poNegativeNode = poPoint;
+            }
 
-            // look for the other node
+            // Look for the other node.
             psdirectedNode = psdirectedNode->psNext;
             while( psdirectedNode != NULL &&
                    !EQUAL( psdirectedNode->pszValue, "directedNode" ) )
@@ -2549,17 +2833,18 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             if( GetElementOrientation( psdirectedNode ) == bNodeOrientation )
                 goto nonode;
 
-            psNodeElement = FindBareXMLChild(psEdge,"Node");
+            psNodeElement = FindBareXMLChild(psEdge, "Node");
             if( psNodeElement == NULL ) goto nonode;
 
-            pspointProperty = FindBareXMLChild(psNodeElement,"pointProperty");
-            if( pspointProperty == NULL )
-                pspointProperty = FindBareXMLChild(psNodeElement,"connectionPointProperty");
-            if( pspointProperty == NULL ) goto nonode;
+            psPointProperty = FindBareXMLChild(psNodeElement, "pointProperty");
+            if( psPointProperty == NULL )
+                psPointProperty =
+                    FindBareXMLChild(psNodeElement, "connectionPointProperty");
+            if( psPointProperty == NULL ) goto nonode;
 
-            psPoint = FindBareXMLChild(pspointProperty,"Point");
+            psPoint = FindBareXMLChild(psPointProperty, "Point");
             if( psPoint == NULL )
-                psPoint = FindBareXMLChild(pspointProperty,"ConnectionPoint");
+                psPoint = FindBareXMLChild(psPointProperty, "ConnectionPoint");
             if( psPoint == NULL ) goto nonode;
 
             poGeom = GML2OGRGeometry_XMLNode_Internal(
@@ -2568,29 +2853,41 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             if( poGeom == NULL
                 || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
             {
-/*                CPLError( CE_Failure, CPLE_AppDefined,
-                      "Got %.500s geometry as Member instead of POINT.",
-                      poGeom ? poGeom->getGeometryName() : "NULL" );*/
+                // CPLError( CE_Failure, CPLE_AppDefined,
+                //           "Got %.500s geometry as Member instead of POINT.",
+                //           poGeom ? poGeom->getGeometryName() : "NULL" );
                 if( poGeom != NULL) delete poGeom;
                 goto nonode;
             }
 
-            if( ( bNodeOrientation == bEdgeOrientation ) != bOrientation )
-                poNegativeNode = (OGRPoint *)poGeom;
-            else
-                poPositiveNode = (OGRPoint *)poGeom;
-
-            poMP = new OGRMultiPoint();
-            poMP->addGeometryDirectly( poNegativeNode );
-            poMP->addGeometryDirectly( poPositiveNode );
+            {
+                OGRPoint *poPoint = dynamic_cast<OGRPoint *>(poGeom);
+                if( poPoint == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                             "dynamic_cast failed.  Expected OGRPoint.");
+                }
+                if( ( bNodeOrientation == bEdgeOrientation ) != bOrientation )
+                    poNegativeNode = poPoint;
+                else
+                    poPositiveNode = poPoint;
+             }
 
-            return poMP;
+            {
+                // Create a scope so that poMP can be initialized with goto
+                // above and label below.
+                OGRMultiPoint *poMP = new OGRMultiPoint();
+                poMP->addGeometryDirectly( poNegativeNode );
+                poMP->addGeometryDirectly( poPositiveNode );
 
+                return poMP;
+            }
             nonode:;
         }
 
-        // collect curveproperty
-        psCurveProperty = FindBareXMLChild(psEdge,"curveProperty");
+        // Collect curveproperty.
+        const CPLXMLNode *psCurveProperty =
+            FindBareXMLChild(psEdge, "curveProperty");
         if( psCurveProperty == NULL )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -2598,13 +2895,15 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return NULL;
         }
 
-        psCurve = FindBareXMLChild(psCurveProperty,"LineString");
+        const CPLXMLNode *psCurve =
+            FindBareXMLChild(psCurveProperty, "LineString");
         if( psCurve == NULL )
-            psCurve = FindBareXMLChild(psCurveProperty,"Curve");
+            psCurve = FindBareXMLChild(psCurveProperty, "Curve");
         if( psCurve == NULL )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "directedEdge: Failed to get LineString or Curve tag in curveProperty" );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "directedEdge: Failed to get LineString or "
+                     "Curve tag in curveProperty");
             return NULL;
         }
 
@@ -2612,19 +2911,28 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             psCurve, nPseudoBoolGetSecondaryGeometryOption,
             nRecLevel + 1, nSRSDimension, pszSRSName, true );
         if( poLineStringBeforeCast == NULL
-            || wkbFlatten(poLineStringBeforeCast->getGeometryType()) != wkbLineString )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Got %.500s geometry as Member instead of LINESTRING.",
-                      poLineStringBeforeCast ? poLineStringBeforeCast->getGeometryName() : "NULL" );
+            || wkbFlatten(poLineStringBeforeCast->getGeometryType()) !=
+            wkbLineString )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Got %.500s geometry as Member instead of LINESTRING.",
+                     poLineStringBeforeCast
+                     ? poLineStringBeforeCast->getGeometryName()
+                     : "NULL" );
             delete poLineStringBeforeCast;
             return NULL;
         }
-        poLineString = (OGRLineString *)poLineStringBeforeCast;
+        OGRLineString *poLineString =
+            dynamic_cast<OGRLineString *>(poLineStringBeforeCast);
+        if( poLineString == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRLineString.");
+        }
 
         if( bGetSecondaryGeometry )
         {
-            // choose a point based on the orientation
+            // Choose a point based on the orientation.
             poNegativeNode = new OGRPoint();
             poPositiveNode = new OGRPoint();
             if( bEdgeOrientation == bOrientation )
@@ -2639,7 +2947,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             }
             delete poLineString;
 
-            poMP = new OGRMultiPoint();
+            OGRMultiPoint *poMP = new OGRMultiPoint();
             poMP->addGeometryDirectly( poNegativeNode );
             poMP->addGeometryDirectly( poPositiveNode );
 
@@ -2649,7 +2957,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         // correct orientation of the line string
         if( bEdgeOrientation != bOrientation )
         {
-            int iStartCoord = 0, iEndCoord = poLineString->getNumPoints() - 1;
+            int iStartCoord = 0;
+            int iEndCoord = poLineString->getNumPoints() - 1;
             OGRPoint *poTempStartPoint = new OGRPoint();
             OGRPoint *poTempEndPoint = new OGRPoint();
             while( iStartCoord < iEndCoord )
@@ -2670,9 +2979,8 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      TopoCurve                                                       */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"TopoCurve") )
+    if( EQUAL(pszBaseGeometry, "TopoCurve") )
     {
-        const CPLXMLNode *psChild;
         OGRMultiLineString *poMLS = NULL;
         OGRMultiPoint *poMP = NULL;
 
@@ -2681,17 +2989,15 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         else
             poMLS = new OGRMultiLineString();
 
-        // collect directedEdges
-        for( psChild = psNode->psChild;
+        // Collect directedEdges.
+        for( const CPLXMLNode *psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"directedEdge"))
+                && EQUAL(BareGMLElement(psChild->pszValue), "directedEdge"))
             {
-                OGRGeometry *poGeom;
-
-                poGeom = GML2OGRGeometry_XMLNode_Internal(
+                OGRGeometry *poGeom = GML2OGRGeometry_XMLNode_Internal(
                     psChild, nPseudoBoolGetSecondaryGeometryOption,
                     nRecLevel + 1, nSRSDimension, pszSRSName );
                 if( poGeom == NULL )
@@ -2706,20 +3012,27 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     return NULL;
                 }
 
-                //Add the two points corresponding to the two nodes to poMP
+                // Add the two points corresponding to the two nodes to poMP.
                 if( bGetSecondaryGeometry &&
                      wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint )
                 {
+                    OGRMultiPoint *poMultiPoint =
+                        dynamic_cast<OGRMultiPoint *>(poGeom);
+                    if( poMultiPoint == NULL )
+                    {
+                        CPLError(CE_Fatal, CPLE_AppDefined,
+                                 "dynamic_cast failed.  "
+                                 "Expected OGRMultiPoint.");
+                    }
                     //TODO: TopoCurve geometries with more than one
                     //      directedEdge elements were not tested.
                     if( poMP->getNumGeometries() <= 0 ||
-                        !(poMP->getGeometryRef( poMP->getNumGeometries() - 1 )->Equals(((OGRMultiPoint *)poGeom)->getGeometryRef( 0 ) ) ))
+                        !(poMP->getGeometryRef( poMP->getNumGeometries() - 1 )->
+                          Equals(poMultiPoint->getGeometryRef(0))) )
                     {
-                        poMP->addGeometry(
-                            ( (OGRMultiPoint *)poGeom )->getGeometryRef( 0 ) );
+                        poMP->addGeometry(poMultiPoint->getGeometryRef(0) );
                     }
-                    poMP->addGeometry(
-                            ( (OGRMultiPoint *)poGeom )->getGeometryRef( 1 ) );
+                    poMP->addGeometry(poMultiPoint->getGeometryRef(1) );
                     delete poGeom;
                 }
                 else if( !bGetSecondaryGeometry &&
@@ -2745,14 +3058,14 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
         if( bGetSecondaryGeometry )
             return poMP;
-        else
-            return poMLS;
+
+        return poMLS;
     }
 
 /* -------------------------------------------------------------------- */
 /*      TopoSurface                                                     */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"TopoSurface") )
+    if( EQUAL(pszBaseGeometry, "TopoSurface") )
     {
         /****************************************************************/
         /* applying the FaceHoleNegative = false rules                  */
@@ -2777,78 +3090,80 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
 #ifndef HAVE_GEOS
             static bool bWarningAlreadyEmitted = false;
-            if (!bWarningAlreadyEmitted)
+            if( !bWarningAlreadyEmitted )
             {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Interpreating that GML TopoSurface geometry requires GDAL to be built with GEOS support.\n"
-                        "As a workaround, you can try defining the GML_FACE_HOLE_NEGATIVE configuration option\n"
-                        "to YES, so that the 'old' interpretation algorithm is used. But be warned that\n"
-                        "the result might be incorrect.\n");
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Interpreating that GML TopoSurface geometry requires GDAL "
+                    "to be built with GEOS support.  As a workaround, you can "
+                    "try defining the GML_FACE_HOLE_NEGATIVE configuration "
+                    "option to YES, so that the 'old' interpretation algorithm "
+                    "is used. But be warned that the result might be "
+                    "incorrect.");
                 bWarningAlreadyEmitted = true;
             }
             return NULL;
 #else
-            const CPLXMLNode *psChild, *psFaceChild, *psDirectedEdgeChild;
             OGRMultiPolygon *poTS = new OGRMultiPolygon();
 
-            // collect directed faces
-            for( psChild = psNode->psChild;
-                psChild != NULL;
-            psChild = psChild->psNext )
+            // Collect directed faces.
+            for( const CPLXMLNode *psChild = psNode->psChild;
+                 psChild != NULL;
+                 psChild = psChild->psNext )
             {
               if( psChild->eType == CXT_Element
-              && EQUAL(BareGMLElement(psChild->pszValue),"directedFace") )
+              && EQUAL(BareGMLElement(psChild->pszValue), "directedFace") )
               {
-                // collect next face (psChild->psChild)
-                psFaceChild = GetChildElement(psChild);
+                // Collect next face (psChild->psChild).
+                const CPLXMLNode *psFaceChild = GetChildElement(psChild);
 
                 while( psFaceChild != NULL &&
                        !(psFaceChild->eType == CXT_Element &&
-                         EQUAL(BareGMLElement(psFaceChild->pszValue),"Face")) )
+                         EQUAL(BareGMLElement(psFaceChild->pszValue), "Face")) )
                         psFaceChild = psFaceChild->psNext;
 
                 if( psFaceChild == NULL )
-                  continue;
+                    continue;
 
                 OGRMultiLineString *poCollectedGeom = new OGRMultiLineString();
 
-                // collect directed edges of the face
-                for( psDirectedEdgeChild = psFaceChild->psChild;
+                // Collect directed edges of the face.
+                for( const CPLXMLNode *psDirectedEdgeChild =
+                         psFaceChild->psChild;
                      psDirectedEdgeChild != NULL;
                      psDirectedEdgeChild = psDirectedEdgeChild->psNext )
                 {
                   if( psDirectedEdgeChild->eType == CXT_Element &&
-                      EQUAL(BareGMLElement(psDirectedEdgeChild->pszValue),"directedEdge") )
+                      EQUAL(BareGMLElement(psDirectedEdgeChild->pszValue),
+                            "directedEdge") )
                   {
-                    OGRGeometry *poEdgeGeom;
-
-                    poEdgeGeom = GML2OGRGeometry_XMLNode_Internal( psDirectedEdgeChild,
-                                                          nPseudoBoolGetSecondaryGeometryOption,
-                                                          nRecLevel + 1,
-                                                          nSRSDimension,
-                                                          pszSRSName,
-                                                          true );
-
-                    if( poEdgeGeom == NULL ||
-                        wkbFlatten(poEdgeGeom->getGeometryType()) != wkbLineString )
-                    {
-                      CPLError( CE_Failure, CPLE_AppDefined,
-                                "Failed to get geometry in directedEdge" );
-                      delete poEdgeGeom;
-                      delete poCollectedGeom;
-                      delete poTS;
-                      return NULL;
-                    }
-
-                    poCollectedGeom->addGeometryDirectly( poEdgeGeom );
+                      OGRGeometry *poEdgeGeom =
+                          GML2OGRGeometry_XMLNode_Internal(
+                              psDirectedEdgeChild,
+                              nPseudoBoolGetSecondaryGeometryOption,
+                              nRecLevel + 1,
+                              nSRSDimension,
+                              pszSRSName,
+                              true);
+
+                      if( poEdgeGeom == NULL ||
+                          wkbFlatten(poEdgeGeom->getGeometryType()) !=
+                          wkbLineString )
+                      {
+                          CPLError( CE_Failure, CPLE_AppDefined,
+                                    "Failed to get geometry in directedEdge" );
+                          delete poEdgeGeom;
+                          delete poCollectedGeom;
+                          delete poTS;
+                          return NULL;
+                      }
+
+                      poCollectedGeom->addGeometryDirectly( poEdgeGeom );
                   }
                 }
 
-                OGRGeometry *poFaceCollectionGeom = NULL;
-                OGRPolygon *poFaceGeom = NULL;
-
-//#ifdef HAVE_GEOS
-                poFaceCollectionGeom = poCollectedGeom->Polygonize();
+                OGRGeometry *poFaceCollectionGeom =
+                    poCollectedGeom->Polygonize();
                 if( poFaceCollectionGeom == NULL )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
@@ -2858,12 +3173,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     return NULL;
                 }
 
-                poFaceGeom = GML2FaceExtRing( poFaceCollectionGeom );
-//#else
-//                poFaceGeom = (OGRPolygon*) OGRBuildPolygonFromEdges(
-//                    (OGRGeometryH) poCollectedGeom,
-//                    FALSE, TRUE, 0, NULL);
-//#endif
+                OGRPolygon *poFaceGeom = GML2FaceExtRing(poFaceCollectionGeom);
 
                 if( poFaceGeom == NULL )
                 {
@@ -2878,33 +3188,44 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     int iCount = poTS->getNumGeometries();
                     if( iCount == 0)
                     {
-                        /* inserting the first Polygon */
+                        // Inserting the first Polygon.
                         poTS->addGeometryDirectly( poFaceGeom );
                     }
                     else
                     {
-                        /* using Union to add the current Polygon */
+                        // Using Union to add the current Polygon.
                         OGRGeometry *poUnion = poTS->Union( poFaceGeom );
                         delete poFaceGeom;
                         delete poTS;
                         if( poUnion == NULL )
                         {
                             CPLError( CE_Failure, CPLE_AppDefined,
-                                        "Failed Union for TopoSurface" );
+                                      "Failed Union for TopoSurface" );
                             return NULL;
                         }
-                        if( wkbFlatten( poUnion->getGeometryType()) == wkbPolygon )
+                        if( wkbFlatten(poUnion->getGeometryType()) ==
+                            wkbPolygon )
                         {
-                            /* forcing to be a MultiPolygon */
+                            // Forcing to be a MultiPolygon.
                             poTS = new OGRMultiPolygon();
                             poTS->addGeometryDirectly(poUnion);
                         }
-                        else if( wkbFlatten( poUnion->getGeometryType()) == wkbMultiPolygon )
-                            poTS = (OGRMultiPolygon *)poUnion;
+                        else if( wkbFlatten(poUnion->getGeometryType()) ==
+                                 wkbMultiPolygon )
+                        {
+                            poTS = dynamic_cast<OGRMultiPolygon *>(poUnion);
+                            if( poTS == NULL )
+                            {
+                                CPLError(CE_Fatal, CPLE_AppDefined,
+                                         "dynamic_cast failed.  "
+                                         "Expected OGRMultiPolygon.");
+                            }
+                        }
                         else
                         {
                             CPLError( CE_Failure, CPLE_AppDefined,
-                                        "Unexpected geometry type resulting from Union for TopoSurface" );
+                                      "Unexpected geometry type resulting "
+                                      "from Union for TopoSurface" );
                             delete poUnion;
                             return NULL;
                         }
@@ -2934,24 +3255,23 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         /****************************************************************/
         if( bGetSecondaryGeometry )
             return NULL;
-        const CPLXMLNode *psChild, *psFaceChild, *psDirectedEdgeChild;
         bool bFaceOrientation = true;
         OGRPolygon *poTS = new OGRPolygon();
 
-        // collect directed faces
-        for( psChild = psNode->psChild;
+        // Collect directed faces.
+        for( const CPLXMLNode *psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
         {
           if( psChild->eType == CXT_Element
-              && EQUAL(BareGMLElement(psChild->pszValue),"directedFace") )
+              && EQUAL(BareGMLElement(psChild->pszValue), "directedFace") )
           {
             bFaceOrientation = GetElementOrientation(psChild);
 
-            // collect next face (psChild->psChild)
-            psFaceChild = GetChildElement(psChild);
+            // Collect next face (psChild->psChild).
+            const CPLXMLNode *psFaceChild = GetChildElement(psChild);
             while( psFaceChild != NULL &&
-                   !EQUAL(BareGMLElement(psFaceChild->pszValue),"Face") )
+                   !EQUAL(BareGMLElement(psFaceChild->pszValue), "Face") )
                     psFaceChild = psFaceChild->psNext;
 
             if( psFaceChild == NULL )
@@ -2959,69 +3279,85 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
             OGRLinearRing *poFaceGeom = new OGRLinearRing();
 
-            // collect directed edges of the face
-            for( psDirectedEdgeChild = psFaceChild->psChild;
+            // Collect directed edges of the face.
+            for( const CPLXMLNode *psDirectedEdgeChild = psFaceChild->psChild;
                  psDirectedEdgeChild != NULL;
                  psDirectedEdgeChild = psDirectedEdgeChild->psNext )
             {
               if( psDirectedEdgeChild->eType == CXT_Element &&
-                  EQUAL(BareGMLElement(psDirectedEdgeChild->pszValue),"directedEdge") )
+                  EQUAL(BareGMLElement(psDirectedEdgeChild->pszValue),
+                        "directedEdge") )
               {
-                OGRGeometry *poEdgeGeom;
-
-                poEdgeGeom = GML2OGRGeometry_XMLNode_Internal( psDirectedEdgeChild,
-                                                      nPseudoBoolGetSecondaryGeometryOption,
-                                                      nRecLevel + 1,
-                                                      nSRSDimension,
-                                                      pszSRSName,
-                                                      true,
-                                                      bFaceOrientation );
+                OGRGeometry *poEdgeGeom =
+                    GML2OGRGeometry_XMLNode_Internal(
+                        psDirectedEdgeChild,
+                        nPseudoBoolGetSecondaryGeometryOption,
+                        nRecLevel + 1,
+                        nSRSDimension,
+                        pszSRSName,
+                        true,
+                        bFaceOrientation );
 
                 if( poEdgeGeom == NULL ||
                     wkbFlatten(poEdgeGeom->getGeometryType()) != wkbLineString )
                 {
-                  CPLError( CE_Failure, CPLE_AppDefined,
-                            "Failed to get geometry in directedEdge" );
-                  delete poEdgeGeom;
-                  delete poFaceGeom;
-                  delete poTS;
-                  return NULL;
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Failed to get geometry in directedEdge" );
+                    delete poEdgeGeom;
+                    delete poFaceGeom;
+                    delete poTS;
+                    return NULL;
+                }
+
+                OGRLineString *poEdgeGeomLS =
+                    dynamic_cast<OGRLineString *>(poEdgeGeom);
+                if( poEdgeGeomLS == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                                "dynamic_cast failed.  "
+                                "Expected OGRLineString.");
+                    delete poEdgeGeom;
+                    delete poFaceGeom;
+                    delete poTS;
+                    return NULL;
                 }
 
-                OGRLineString *poLS;
-                OGRLineString *poAddLS;
                 if( !bFaceOrientation )
                 {
-                  poLS = (OGRLineString *)poEdgeGeom;
-                  poAddLS = (OGRLineString *)poFaceGeom;
-                  if( poAddLS->getNumPoints() < 2 )
-                  {
-                      /* skip it */
-                  }
-                  else if( poLS->getNumPoints() > 0
-                      && fabs(poLS->getX(poLS->getNumPoints()-1)
-                              - poAddLS->getX(0)) < 1e-14
-                      && fabs(poLS->getY(poLS->getNumPoints()-1)
-                              - poAddLS->getY(0)) < 1e-14
-                      && fabs(poLS->getZ(poLS->getNumPoints()-1)
-                              - poAddLS->getZ(0)) < 1e-14)
-                  {
-                      // Skip the first point of the new linestring to avoid
-                      // invalidate duplicate points
-                      poLS->addSubLineString( poAddLS, 1 );
-                  }
-                  else
-                  {
-                      // Add the whole new line string
-                      poLS->addSubLineString( poAddLS );
-                  }
-                  poFaceGeom->empty();
+                    OGRLineString *poLS = poEdgeGeomLS;
+                    OGRLineString *poAddLS = poFaceGeom;
+
+                    // TODO(schwehr): Use AlmostEqual.
+                    const double epsilon = 1.0e-14;
+                    if( poAddLS->getNumPoints() < 2 )
+                    {
+                        // Skip it.
+                    }
+                    else if( poLS->getNumPoints() > 0
+                             && fabs(poLS->getX(poLS->getNumPoints() - 1)
+                                     - poAddLS->getX(0)) < epsilon
+                             && fabs(poLS->getY(poLS->getNumPoints() - 1)
+                                     - poAddLS->getY(0)) < epsilon
+                             && fabs(poLS->getZ(poLS->getNumPoints() - 1)
+                                     - poAddLS->getZ(0)) < epsilon )
+                    {
+                        // Skip the first point of the new linestring to avoid
+                        // invalidate duplicate points.
+                        poLS->addSubLineString( poAddLS, 1 );
+                    }
+                    else
+                    {
+                        // Add the whole new line string.
+                        poLS->addSubLineString( poAddLS );
+                    }
+                    poFaceGeom->empty();
                 }
-                poLS = (OGRLineString *)poFaceGeom;
-                poAddLS = (OGRLineString *)poEdgeGeom;
+                // TODO(schwehr): Suspicious that poLS overwritten without else.
+                OGRLineString *poLS = poFaceGeom;
+                OGRLineString *poAddLS = poEdgeGeomLS;
                 if( poAddLS->getNumPoints() < 2 )
                 {
-                    /* skip it */
+                    // Skip it.
                 }
                 else if( poLS->getNumPoints() > 0
                     && fabs(poLS->getX(poLS->getNumPoints()-1)
@@ -3032,37 +3368,37 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                             - poAddLS->getZ(0)) < 1e-14)
                 {
                     // Skip the first point of the new linestring to avoid
-                    // invalidate duplicate points
+                    // invalidate duplicate points.
                     poLS->addSubLineString( poAddLS, 1 );
                 }
                 else
                 {
-                    // Add the whole new line string
+                    // Add the whole new line string.
                     poLS->addSubLineString( poAddLS );
                 }
                 delete poEdgeGeom;
               }
             }
 
-/*            if( poFaceGeom == NULL )
-            {
-              CPLError( CE_Failure, CPLE_AppDefined,
-                        "Failed to get Face geometry in directedFace" );
-              delete poFaceGeom;
-              return NULL;
-            }*/
+            // if( poFaceGeom == NULL )
+            // {
+            //     CPLError( CE_Failure, CPLE_AppDefined,
+            //               "Failed to get Face geometry in directedFace" );
+            //     delete poFaceGeom;
+            //     return NULL;
+            // }
 
             poTS->addRingDirectly( poFaceGeom );
           }
         }
 
-/*        if( poTS == NULL )
-        {
-          CPLError( CE_Failure, CPLE_AppDefined,
-                    "Failed to get TopoSurface geometry" );
-          delete poTS;
-          return NULL;
-        }*/
+        // if( poTS == NULL )
+        // {
+        //     CPLError( CE_Failure, CPLE_AppDefined,
+        //               "Failed to get TopoSurface geometry" );
+        //     delete poTS;
+        //     return NULL;
+        // }
 
         return poTS;
     }
@@ -3070,12 +3406,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      Surface                                                         */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"Surface") )
+    if( EQUAL(pszBaseGeometry, "Surface") )
     {
-        const CPLXMLNode *psChild;
-
         // Find outer ring.
-        psChild = FindBareXMLChild( psNode, "patches" );
+        const CPLXMLNode *psChild = FindBareXMLChild( psNode, "patches" );
         if( psChild == NULL )
             psChild = FindBareXMLChild( psNode, "polygonPatches" );
         if( psChild == NULL )
@@ -3084,18 +3418,21 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         psChild = GetChildElement(psChild);
         if( psChild == NULL )
         {
-            /* <gml:Surface/> and <gml:Surface><gml:patches/></gml:Surface> are valid GML */
+            // <gml:Surface/> and <gml:Surface><gml:patches/></gml:Surface> are
+            // valid GML.
             return new OGRPolygon();
         }
 
         OGRMultiSurface* poMS = NULL;
-        OGRGeometry* poResult = NULL;
+        OGRGeometry* poResultPoly = NULL;
+        OGRGeometry* poResultTri = NULL;
+        OGRTriangulatedSurface *poTIN = NULL;
+        OGRGeometryCollection *poGC = NULL;
         for( ; psChild != NULL; psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && (EQUAL(BareGMLElement(psChild->pszValue),"PolygonPatch") ||
-                    EQUAL(BareGMLElement(psChild->pszValue),"Triangle") ||
-                    EQUAL(BareGMLElement(psChild->pszValue),"Rectangle")))
+                && (EQUAL(BareGMLElement(psChild->pszValue), "PolygonPatch") ||
+                    EQUAL(BareGMLElement(psChild->pszValue), "Rectangle")))
             {
                 OGRGeometry *poGeom =
                     GML2OGRGeometry_XMLNode_Internal(
@@ -3103,19 +3440,21 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                         nRecLevel + 1, nSRSDimension, pszSRSName );
                 if( poGeom == NULL )
                 {
-                    delete poResult;
+                    delete poResultPoly;
                     return NULL;
                 }
 
-                OGRwkbGeometryType eGeomType = wkbFlatten(poGeom->getGeometryType());
+                const OGRwkbGeometryType eGeomType =
+                    wkbFlatten(poGeom->getGeometryType());
 
-                if( poResult == NULL )
-                    poResult = poGeom;
+                if( poResultPoly == NULL )
+                    poResultPoly = poGeom;
                 else
                 {
                     if( poMS == NULL )
                     {
-                        if( wkbFlatten(poResult->getGeometryType()) == wkbPolygon &&
+                        if( wkbFlatten(poResultPoly->getGeometryType()) ==
+                            wkbPolygon &&
                             eGeomType == wkbPolygon )
                             poMS = new OGRMultiPolygon();
                         else
@@ -3123,15 +3462,24 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 #ifdef DEBUG
                         OGRErr eErr =
 #endif
-                          poMS->addGeometryDirectly( poResult );
+                          poMS->addGeometryDirectly( poResultPoly );
                         CPLAssert(eErr == OGRERR_NONE);
-                        poResult = poMS;
+                        poResultPoly = poMS;
                     }
                     else if( eGeomType != wkbPolygon &&
-                             wkbFlatten(poMS->getGeometryType()) == wkbMultiPolygon )
+                             wkbFlatten(poMS->getGeometryType()) ==
+                             wkbMultiPolygon )
                     {
-                        poMS = OGRMultiPolygon::CastToMultiSurface((OGRMultiPolygon*)poMS);
-                        poResult = poMS;
+                        OGRMultiPolygon *poMultiPoly =
+                            dynamic_cast<OGRMultiPolygon *>(poMS);
+                        if( poMultiPoly == NULL )
+                        {
+                            CPLError(CE_Fatal, CPLE_AppDefined,
+                                     "dynamic_cast failed.  "
+                                     "Expected OGRMultiPolygon.");
+                        }
+                        poMS = OGRMultiPolygon::CastToMultiSurface(poMultiPoly);
+                        poResultPoly = poMS;
                     }
 #ifdef DEBUG
                     OGRErr eErr =
@@ -3140,23 +3488,68 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
                     CPLAssert(eErr == OGRERR_NONE);
                 }
             }
+            else if( psChild->eType == CXT_Element
+                    && EQUAL(BareGMLElement(psChild->pszValue), "Triangle"))
+            {
+                OGRGeometry *poGeom =
+                    GML2OGRGeometry_XMLNode_Internal(
+                        psChild, nPseudoBoolGetSecondaryGeometryOption,
+                        nRecLevel + 1, nSRSDimension, pszSRSName );
+                if( poGeom == NULL )
+                {
+                    delete poResultTri;
+                    return NULL;
+                }
+
+                if( poResultTri == NULL )
+                    poResultTri = poGeom;
+                else
+                {
+                    if( poTIN == NULL )
+                    {
+                        poTIN = new OGRTriangulatedSurface();
+#ifdef DEBUG
+                        OGRErr eErr =
+#endif
+                          poTIN->addGeometryDirectly( poResultTri );
+                        CPLAssert(eErr == OGRERR_NONE);
+                        poResultTri = poTIN;
+                    }
+#ifdef DEBUG
+                    OGRErr eErr =
+#endif
+                      poTIN->addGeometryDirectly( poGeom );
+                    CPLAssert(eErr == OGRERR_NONE);
+                }
+            }
         }
 
-        return poResult;
+        if( poResultTri == NULL && poResultPoly == NULL )
+            return NULL;
+
+        if( poResultTri == NULL )
+            return poResultPoly;
+        else if( poResultPoly == NULL )
+            return poResultTri;
+        else if( poResultTri != NULL && poResultPoly != NULL )
+        {
+            poGC = new OGRGeometryCollection();
+            poGC->addGeometryDirectly(poResultTri);
+            poGC->addGeometryDirectly(poResultPoly);
+            return poGC;
+        }
     }
 
 /* -------------------------------------------------------------------- */
 /*      TriangulatedSurface                                             */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"TriangulatedSurface") ||
-        EQUAL(pszBaseGeometry,"Tin") )
+    if( EQUAL(pszBaseGeometry, "TriangulatedSurface") ||
+        EQUAL(pszBaseGeometry, "Tin") )
     {
-        const CPLXMLNode *psChild;
-        OGRGeometry *poResult = NULL;
-
-        // Find trianglePatches
-        psChild = FindBareXMLChild( psNode, "trianglePatches" );
-        if (psChild == NULL)
+        // Find trianglePatches.
+        const CPLXMLNode *psChild =
+            FindBareXMLChild( psNode, "trianglePatches" );
+        if( psChild == NULL )
             psChild = FindBareXMLChild( psNode, "patches" );
 
         psChild = GetChildElement(psChild);
@@ -3167,57 +3560,152 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
             return NULL;
         }
 
+        OGRTriangulatedSurface *poTIN = new OGRTriangulatedSurface();
         for( ; psChild != NULL; psChild = psChild->psNext )
         {
             if( psChild->eType == CXT_Element
-                && EQUAL(BareGMLElement(psChild->pszValue),"Triangle") )
+                && EQUAL(BareGMLElement(psChild->pszValue), "Triangle") )
             {
-                OGRGeometry *poPolygon =
+                OGRGeometry *poTriangle =
                     GML2OGRGeometry_XMLNode_Internal(
                         psChild, nPseudoBoolGetSecondaryGeometryOption,
                         nRecLevel + 1, nSRSDimension, pszSRSName );
-                if( poPolygon == NULL )
-                    return NULL;
-
-                if( poResult == NULL )
-                    poResult = poPolygon;
-                else if( wkbFlatten(poResult->getGeometryType()) == wkbPolygon )
+                if( poTriangle == NULL )
                 {
-                    OGRMultiPolygon *poMP = new OGRMultiPolygon();
-                    poMP->addGeometryDirectly( poResult );
-                    poMP->addGeometryDirectly( poPolygon );
-                    poResult = poMP;
+                    delete poTIN;
+                    return NULL;
                 }
                 else
                 {
-                    ((OGRMultiPolygon *) poResult)->addGeometryDirectly( poPolygon );
+                    poTIN->addGeometryDirectly( poTriangle );
                 }
             }
         }
 
-        return poResult;
+        return poTIN;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Solid                                                           */
+/*      PolyhedralSurface                                               */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"Solid") )
+    if( EQUAL(pszBaseGeometry, "PolyhedralSurface") )
     {
-        const CPLXMLNode *psChild;
-        OGRGeometry* poGeom;
+        // Find polygonPatches.
+        const CPLXMLNode *psParent =
+            FindBareXMLChild( psNode, "polygonPatches" );
+        if( psParent == NULL )
+        {
+            if( GetChildElement(psNode) == NULL )
+            {
+                // This is empty PolyhedralSurface.
+                return new OGRPolyhedralSurface();
+            }
+            else
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Missing <polygonPatches> for %s.", pszBaseGeometry );
+                return NULL;
+            }
+        }
 
-        // Find exterior element
-        psChild = FindBareXMLChild( psNode, "exterior");
+        const CPLXMLNode *psChild = GetChildElement(psParent);
+        if( psChild == NULL )
+        {
+            // This is empty PolyhedralSurface.
+            return new OGRPolyhedralSurface();
+        }
+        else if( psChild != NULL &&
+                 !EQUAL(BareGMLElement(psChild->pszValue), "PolygonPatch") )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Missing <PolygonPatch> for %s.", pszBaseGeometry );
+            return NULL;
+        }
+
+        // Each psParent has the tags corresponding to <gml:polygonPatches>
+        // Each psChild has the tags corresponding to <gml:PolygonPatch>
+        // Each PolygonPatch has a set of polygons enclosed in a
+        // OGRPolyhedralSurface.
+        OGRPolyhedralSurface *poPS = NULL;
+        OGRGeometryCollection *poGC = new OGRGeometryCollection();
+        OGRGeometry *poResult = NULL;
+        for( ; psParent != NULL; psParent = psParent->psNext )
+        {
+            poPS = new OGRPolyhedralSurface();
+            for( ; psChild != NULL; psChild = psChild->psNext )
+            {
+                if( psChild->eType == CXT_Element
+                    && EQUAL(BareGMLElement(psChild->pszValue), "PolygonPatch") )
+                {
+                    OGRGeometry *poPolygon =
+                        GML2OGRGeometry_XMLNode_Internal(
+                            psChild, nPseudoBoolGetSecondaryGeometryOption,
+                            nRecLevel + 1, nSRSDimension, pszSRSName );
+                    if( poPolygon == NULL )
+                    {
+                        delete poPS;
+                        delete poGC;
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Wrong geometry type for %s.",
+                                  pszBaseGeometry );
+                        return NULL;
+                    }
+
+                    else if( wkbFlatten(poPolygon->getGeometryType()) ==
+                             wkbPolygon )
+                    {
+                        poPS->addGeometryDirectly( poPolygon );
+                    }
+                    else
+                    {
+                        delete poPS;
+                        delete poGC;
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "Wrong geometry type for %s.",
+                                  pszBaseGeometry );
+                        return NULL;
+                    }
+                }
+            }
+            poGC->addGeometryDirectly(poPS);
+        }
+
+        if( poGC->getNumGeometries() == 0 )
+        {
+            delete poGC;
+            return NULL;
+        }
+        else if( poPS != NULL && poGC->getNumGeometries() == 1 )
+        {
+            poResult = poPS->clone();
+            delete poGC;
+            return poResult;
+        }
+        else
+        {
+            poResult = poGC;
+            return poResult;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Solid                                                           */
+/* -------------------------------------------------------------------- */
+    if( EQUAL(pszBaseGeometry, "Solid") )
+    {
+        // Find exterior element.
+        const CPLXMLNode *psChild = FindBareXMLChild( psNode, "exterior");
 
         psChild = GetChildElement(psChild);
         if( psChild == NULL )
         {
-            /* <gml:Solid/> and <gml:Solid><gml:exterior/></gml:Solid> are valid GML */
+            // <gml:Solid/> and <gml:Solid><gml:exterior/></gml:Solid> are valid
+            // GML.
             return new OGRPolygon();
         }
 
-        // Get the geometry inside <exterior>
-        poGeom = GML2OGRGeometry_XMLNode_Internal(
+        // Get the geometry inside <exterior>.
+        OGRGeometry* poGeom = GML2OGRGeometry_XMLNode_Internal(
             psChild, nPseudoBoolGetSecondaryGeometryOption,
             nRecLevel + 1, nSRSDimension, pszSRSName );
         if( poGeom == NULL )
@@ -3231,7 +3719,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         if( psChild != NULL )
         {
             static bool bWarnedOnce = false;
-            if (!bWarnedOnce)
+            if( !bWarnedOnce )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "<interior> elements of <Solid> are ignored");
@@ -3245,12 +3733,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /* -------------------------------------------------------------------- */
 /*      OrientableSurface                                               */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"OrientableSurface") )
+    if( EQUAL(pszBaseGeometry, "OrientableSurface") )
     {
-        const CPLXMLNode *psChild;
-
         // Find baseSurface.
-        psChild = FindBareXMLChild( psNode, "baseSurface" );
+        const CPLXMLNode *psChild = FindBareXMLChild( psNode, "baseSurface" );
 
         psChild = GetChildElement(psChild);
         if( psChild == NULL )
@@ -3269,11 +3755,10 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /*      SimplePolygon, SimpleRectangle, SimpleTriangle                  */
 /*      (GML 3.3 compact encoding)                                      */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"SimplePolygon") ||
-        EQUAL(pszBaseGeometry,"SimpleRectangle") ||
-        EQUAL(pszBaseGeometry,"SimpleTriangle") )
+    if( EQUAL(pszBaseGeometry, "SimplePolygon") ||
+        EQUAL(pszBaseGeometry, "SimpleRectangle") )
     {
-        OGRLinearRing   *poRing = new OGRLinearRing();
+        OGRLinearRing *poRing = new OGRLinearRing();
 
         if( !ParseGMLCoordinates( psNode, poRing, nSRSDimension ) )
         {
@@ -3288,12 +3773,29 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
         return poPolygon;
     }
 
+    if( EQUAL(pszBaseGeometry, "SimpleTriangle") )
+    {
+        OGRLinearRing *poRing = new OGRLinearRing();
+
+        if( !ParseGMLCoordinates( psNode, poRing, nSRSDimension ) )
+        {
+            delete poRing;
+            return NULL;
+        }
+
+        poRing->closeRings();
+
+        OGRTriangle* poTriangle = new OGRTriangle();
+        poTriangle->addRingDirectly(poRing);
+        return poTriangle;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      SimpleMultiPoint (GML 3.3 compact encoding)                     */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszBaseGeometry,"SimpleMultiPoint") )
+    if( EQUAL(pszBaseGeometry, "SimpleMultiPoint") )
     {
-        OGRLineString   *poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
 
         if( !ParseGMLCoordinates( psNode, poLS, nSRSDimension ) )
         {
@@ -3303,7 +3805,7 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 
         OGRMultiPoint* poMP = new OGRMultiPoint();
         int nPoints = poLS->getNumPoints();
-        for(int i = 0; i < nPoints; i++)
+        for( int i = 0; i < nPoints; i++ )
         {
             OGRPoint* poPoint = new OGRPoint();
             poLS->getPoint(i, poPoint);
@@ -3324,10 +3826,11 @@ OGRGeometry *GML2OGRGeometry_XMLNode_Internal( const CPLXMLNode *psNode,
 /*                      OGR_G_CreateFromGMLTree()                       */
 /************************************************************************/
 
+/** Create geometry from GML */
 OGRGeometryH OGR_G_CreateFromGMLTree( const CPLXMLNode *psTree )
 
 {
-    return (OGRGeometryH) GML2OGRGeometry_XMLNode( psTree, -1 );
+    return reinterpret_cast<OGRGeometryH>(GML2OGRGeometry_XMLNode(psTree, -1));
 }
 
 /************************************************************************/
@@ -3345,16 +3848,17 @@ OGRGeometryH OGR_G_CreateFromGMLTree( const CPLXMLNode *psTree )
  * The following GML2 elements are parsed : Point, LineString, Polygon,
  * MultiPoint, MultiLineString, MultiPolygon, MultiGeometry.
  *
- * (OGR >= 1.8.0) The following GML3 elements are parsed : Surface, MultiSurface,
- * PolygonPatch, Triangle, Rectangle, Curve, MultiCurve, CompositeCurve,
- * LineStringSegment, Arc, Circle, CompositeSurface, OrientableSurface, Solid,
- * Tin, TriangulatedSurface.
+ * (OGR >= 1.8.0) The following GML3 elements are parsed : Surface,
+ * MultiSurface, PolygonPatch, Triangle, Rectangle, Curve, MultiCurve,
+ * CompositeCurve, LineStringSegment, Arc, Circle, CompositeSurface,
+ * OrientableSurface, Solid, Tin, TriangulatedSurface.
  *
  * Arc and Circle elements are stroked to linestring, by using a
  * 4 degrees step, unless the user has overridden the value with the
  * OGR_ARC_STEPSIZE configuration variable.
  *
- * The C++ method OGRGeometryFactory::createFromGML() is the same as this function.
+ * The C++ method OGRGeometryFactory::createFromGML() is the same as
+ * this function.
  *
  * @param pszGML The GML fragment for the geometry.
  *
@@ -3371,7 +3875,7 @@ OGRGeometryH OGR_G_CreateFromGML( const char *pszGML )
         return NULL;
     }
 
-/* ------------------------------------------------------------ -------- */
+/* -------------------------------------------------------------------- */
 /*      Try to parse the XML snippet using the MiniXML API.  If this    */
 /*      fails, we assume the minixml api has already posted a CPL       */
 /*      error, and just return NULL.                                    */
@@ -3384,13 +3888,15 @@ OGRGeometryH OGR_G_CreateFromGML( const char *pszGML )
 /* -------------------------------------------------------------------- */
 /*      Convert geometry recursively.                                   */
 /* -------------------------------------------------------------------- */
-    OGRGeometry *poGeometry;
-
-    /* Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer() and GMLReader::GMLReader() */
-    bool bFaceHoleNegative = CPLTestBool(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
-    poGeometry = GML2OGRGeometry_XMLNode( psGML, -1, 0, 0, false, true, bFaceHoleNegative );
+    // Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer()
+    // and GMLReader::GMLReader().
+    const bool bFaceHoleNegative =
+         CPLTestBool(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
+    OGRGeometry *poGeometry =
+        GML2OGRGeometry_XMLNode( psGML, -1, 0, 0,
+                                 false, true, bFaceHoleNegative );
 
     CPLDestroyXMLNode( psGML );
 
-    return (OGRGeometryH) poGeometry;
+    return reinterpret_cast<OGRGeometryH>(poGeometry);
 }
diff --git a/ogr/makefile.vc b/ogr/makefile.vc
index dcfa4df..16d36d2 100644
--- a/ogr/makefile.vc
+++ b/ogr/makefile.vc
@@ -1,31 +1,36 @@
 
 LINKFLAGS =	/Zi /MTd
-EXTRAFLAGS =	-DWIN32 -I. -Iogrsf_frmts -Iogrsf_frmts\mem -I..\frmts\gtiff\libgeotiff -I..\frmts\zlib \
+EXTRAFLAGS =	-DWIN32 -I. -Iogrsf_frmts -Iogrsf_frmts\mem -Iogrsf_frmts\geojson -Iogrsf_frmts\geojson\libjson -I..\frmts\gtiff\libgeotiff $(ZLIB_FLAGS) \
 		$(PROJ_FLAGS) $(PROJ_INCLUDE) $(GEOS_CFLAGS)
 
 GDAL_ROOT = 	..
 
 !INCLUDE ..\nmake.opt
 
-!IFDEF INCLUDE_OGR_FRMTS
-EXTRAFLAGS = $(EXTRAFLAGS) -DOGR_ENABLED -DHAVE_MITAB
+!IFDEF ZLIB_EXTERNAL_LIB
+ZLIB_FLAGS = $(ZLIB_INC)
 !ELSE
-EXTRAFLAGS = $(EXTRAFLAGS) -DHAVE_MITAB
+ZLIB_FLAGS = -I..\frmts\zlib
 !ENDIF
 
+EXTRAFLAGS = $(EXTRAFLAGS) -DHAVE_MITAB
+
 !IFDEF EXPAT_DIR
 EXTRAFLAGS = $(EXTRAFLAGS) $(EXPAT_INCLUDE) -DHAVE_EXPAT
 !ENDIF
 
+!IFDEF XERCES_DIR
+EXTRAFLAGS = $(EXTRAFLAGS) $(XERCES_INCLUDE) -DHAVE_XERCES
+!ENDIF
 
 OGR_FRMTS =	ogrsf_frmts\ogrsf_frmts.lib ogrsf_frmts\ogrsf_frmts_sup.lib
 OBJ_OGR	=	ogrgeometryfactory.obj ogrpoint.obj ogrcurve.obj ogrsurface.obj ogr_api.obj \
-		ogrlinestring.obj ogrpolygon.obj ogrlinearring.obj \
+		ogrlinestring.obj ogrtriangle.obj ogrpolygon.obj ogrlinearring.obj \
 		ogrutils.obj ogrgeometry.obj ogrgeometrycollection.obj \
 		ogrmultipolygon.obj ogrmultilinestring.obj ogr_opt.obj \
 		ogrmultipoint.obj ogrcircularstring.obj ogrcompoundcurve.obj \
-		ogrcurvepolygon.obj ogrcurvecollection.obj ogrmultisurface.obj \
-		ogrmulticurve.obj ogrfeature.obj ogrfeaturedefn.obj \
+		ogrcurvepolygon.obj ogrtriangulatedsurface.obj ogrcurvecollection.obj ogrmultisurface.obj \
+		ogrmulticurve.obj ogrpolyhedralsurface.obj ogrfeature.obj ogrfeaturedefn.obj \
 		ogrfielddefn.obj ogr_srsnode.obj ogrspatialreference.obj \
 		ogr_srs_proj4.obj ogr_fromepsg.obj ogrct.obj \
 		ogrfeaturestyle.obj ogr_srs_esri.obj ogrfeaturequery.obj \
@@ -36,7 +41,8 @@ OBJ_OGR	=	ogrgeometryfactory.obj ogrpoint.obj ogrcurve.obj ogrsurface.obj ogr_ap
 		swq.obj swq_parser.obj swq_select.obj swq_op_registrar.obj \
 		swq_op_general.obj swq_expr_node.obj ogrpgeogeometry.obj \
 		ogrgeomediageometry.obj ogr_geocoding.obj osr_cs_wkt.obj \
-		osr_cs_wkt_parser.obj ogrgeomfielddefn.obj ograpispy.obj
+		osr_cs_wkt_parser.obj ogrgeomfielddefn.obj ograpispy.obj \
+		ogr_xerces.obj
 
 default:        ogr.lib 
 
diff --git a/ogr/ogr2gmlgeometry.cpp b/ogr/ogr2gmlgeometry.cpp
index 77f7db3..35088b1 100644
--- a/ogr/ogr2gmlgeometry.cpp
+++ b/ogr/ogr2gmlgeometry.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr2gmlgeometry.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  GML Translator
  * Purpose:  Code to translate OGRGeometry to GML string representation.
@@ -40,15 +39,35 @@
  *
  */
 
-#include "cpl_error.h"
+#include "cpl_port.h"
+#include "ogr_api.h"
+
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
-#include "ogr_api.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
 #include "ogr_p.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: ogr2gmlgeometry.cpp 36965 2016-12-19 17:27:33Z rouault $");
 
-#define SRSDIM_LOC_GEOMETRY (1 << 0)
-#define SRSDIM_LOC_POSLIST  (1 << 1)
+static const int SRSDIM_LOC_GEOMETRY = 1 << 0;
+static const int SRSDIM_LOC_POSLIST = 1 << 1;
+
+typedef enum
+{
+    SRSNAME_SHORT,
+    SRSNAME_OGC_URN,
+    SRSNAME_OGC_URL
+} GMLSRSNameFormat;
 
 /************************************************************************/
 /*                        MakeGMLCoordinate()                           */
@@ -65,32 +84,6 @@ static void MakeGMLCoordinate( char *pszTarget,
             *pszTarget = ',';
         pszTarget++;
     }
-
-#ifdef notdef
-    if( !b3D )
-    {
-        if( x == (int) x && y == (int) y )
-            sprintf( pszTarget, "%d,%d", (int) x, (int) y );
-        else if( fabs(x) < 370 && fabs(y) < 370 )
-            CPLsprintf( pszTarget, "%.16g,%.16g", x, y );
-        else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0 )
-            CPLsprintf( pszTarget, "%.16g,%.16g", x, y );
-        else
-            CPLsprintf( pszTarget, "%.3f,%.3f", x, y );
-    }
-    else
-    {
-        if( x == (int) x && y == (int) y && z == (int) z )
-            sprintf( pszTarget, "%d,%d,%d", (int) x, (int) y, (int) z );
-        else if( fabs(x) < 370 && fabs(y) < 370 )
-            CPLsprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
-        else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0
-                 || fabs(z) > 100000000.0 )
-            CPLsprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
-        else
-            CPLsprintf( pszTarget, "%.3f,%.3f,%.3f", x, y, z );
-    }
-#endif
 }
 
 /************************************************************************/
@@ -100,10 +93,10 @@ static void MakeGMLCoordinate( char *pszTarget,
 static void _GrowBuffer( size_t nNeeded, char **ppszText, size_t *pnMaxLength )
 
 {
-    if( nNeeded+1 >= *pnMaxLength )
+    if( nNeeded + 1 >= *pnMaxLength )
     {
-        *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
-        *ppszText = (char *) CPLRealloc(*ppszText, *pnMaxLength);
+        *pnMaxLength = std::max(*pnMaxLength * 2, nNeeded + 1);
+        *ppszText = static_cast<char *>(CPLRealloc(*ppszText, *pnMaxLength));
     }
 }
 
@@ -111,7 +104,8 @@ static void _GrowBuffer( size_t nNeeded, char **ppszText, size_t *pnMaxLength )
 /*                            AppendString()                            */
 /************************************************************************/
 
-static void AppendString( char **ppszText, size_t *pnLength, size_t *pnMaxLength,
+static void AppendString( char **ppszText, size_t *pnLength,
+                          size_t *pnMaxLength,
                           const char *pszTextToAppend )
 
 {
@@ -122,7 +116,6 @@ static void AppendString( char **ppszText, size_t *pnLength, size_t *pnMaxLength
     *pnLength += strlen( *ppszText + *pnLength );
 }
 
-
 /************************************************************************/
 /*                        AppendCoordinateList()                        */
 /************************************************************************/
@@ -132,8 +125,7 @@ static void AppendCoordinateList( OGRLineString *poLine,
                                   size_t *pnMaxLength )
 
 {
-    char        szCoordinate[256];
-    bool        b3D = wkbHasZ(poLine->getGeometryType()) != FALSE;
+    const bool b3D = wkbHasZ(poLine->getGeometryType()) != FALSE;
 
     *pnLength += strlen(*ppszText + *pnLength);
     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
@@ -141,6 +133,7 @@ static void AppendCoordinateList( OGRLineString *poLine,
     strcat( *ppszText + *pnLength, "<gml:coordinates>" );
     *pnLength += strlen(*ppszText + *pnLength);
 
+    char szCoordinate[256] = {};
     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     {
         MakeGMLCoordinate( szCoordinate,
@@ -148,7 +141,7 @@ static void AppendCoordinateList( OGRLineString *poLine,
                            poLine->getY(iPoint),
                            poLine->getZ(iPoint),
                            b3D );
-        _GrowBuffer( *pnLength + strlen(szCoordinate)+1,
+        _GrowBuffer( *pnLength + strlen(szCoordinate) + 1,
                      ppszText, pnMaxLength );
 
         if( iPoint != 0 )
@@ -174,13 +167,12 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
                                    const char* pszNamespaceDecl )
 
 {
-
 /* -------------------------------------------------------------------- */
 /*      Check for Spatial Reference System attached to given geometry   */
 /* -------------------------------------------------------------------- */
 
     // Buffer for xmlns:gml and srsName attributes (srsName="...")
-    char szAttributes[64] = { 0 };
+    char szAttributes[128] = {};
     size_t nAttrsLength = 0;
 
     szAttributes[0] = 0;
@@ -200,31 +192,18 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 
     if( NULL != poSRS && !bIsSubGeometry )
     {
-        const char* pszAuthName = NULL;
-        const char* pszAuthCode = NULL;
-        const char* pszTarget = NULL;
-
-        if (poSRS->IsProjected())
-            pszTarget = "PROJCS";
-        else
-            pszTarget = "GEOGCS";
-
-        pszAuthName = poSRS->GetAuthorityName( pszTarget );
-        if( NULL != pszAuthName )
+        const char* pszTarget = poSRS->IsProjected() ? "PROJCS" : "GEOGCS";
+        const char* pszAuthName = poSRS->GetAuthorityName( pszTarget );
+        const char* pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
+        if( NULL != pszAuthName && strlen(pszAuthName) < 10 &&
+            NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
         {
-            if( EQUAL( pszAuthName, "EPSG" ) )
-            {
-                pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
-                if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
-                {
-                    snprintf( szAttributes + nAttrsLength,
-                              sizeof(szAttributes) - nAttrsLength,
-                              " srsName=\"%s:%s\"",
-                              pszAuthName, pszAuthCode );
+            snprintf( szAttributes + nAttrsLength,
+                        sizeof(szAttributes) - nAttrsLength,
+                        " srsName=\"%s:%s\"",
+                        pszAuthName, pszAuthCode );
 
-                    nAttrsLength += strlen(szAttributes + nAttrsLength);
-                }
-            }
+            nAttrsLength += strlen(szAttributes + nAttrsLength);
         }
     }
 
@@ -236,18 +215,24 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     if( eType == wkbPoint )
     {
-        char    szCoordinate[256];
-        OGRPoint *poPoint = (OGRPoint *) poGeometry;
+        OGRPoint *poPoint = dynamic_cast<OGRPoint *>(poGeometry);
+        if( poPoint == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPoint.");
+        }
 
+        char szCoordinate[256] = {};
         MakeGMLCoordinate( szCoordinate,
                            poPoint->getX(), poPoint->getY(), 0.0, false );
 
         _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
                      ppszText, pnMaxLength );
 
-        snprintf( *ppszText + *pnLength, *pnMaxLength -  *pnLength,
-                "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
-                 szAttributes, szCoordinate );
+        snprintf(
+            *ppszText + *pnLength, *pnMaxLength - *pnLength,
+            "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
+            szAttributes, szCoordinate );
 
         *pnLength += strlen( *ppszText + *pnLength );
     }
@@ -256,9 +241,14 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     else if( eType == wkbPoint25D )
     {
-        char    szCoordinate[256];
-        OGRPoint *poPoint = (OGRPoint *) poGeometry;
+        OGRPoint *poPoint = dynamic_cast<OGRPoint *>(poGeometry);
+        if( poPoint == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPoint.");
+        }
 
+        char szCoordinate[256] = {};
         MakeGMLCoordinate( szCoordinate,
                            poPoint->getX(), poPoint->getY(), poPoint->getZ(),
                            true );
@@ -266,9 +256,10 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
                      ppszText, pnMaxLength );
 
-        snprintf( *ppszText + *pnLength, *pnMaxLength -  *pnLength,
-                "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
-                 szAttributes, szCoordinate );
+        snprintf(
+            *ppszText + *pnLength, *pnMaxLength - *pnLength,
+            "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
+            szAttributes, szCoordinate);
 
         *pnLength += strlen( *ppszText + *pnLength );
     }
@@ -278,34 +269,42 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     else if( eFType == wkbLineString )
     {
-        bool bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
+        bool bRing = EQUAL(poGeometry->getGeometryName(), "LINEARRING");
 
         // Buffer for tag name + srsName attribute if set
         const size_t nLineTagLength = 16;
-        char* pszLineTagName = NULL;
         const size_t nLineTagNameBufLen = nLineTagLength + nAttrsLength + 1;
-        pszLineTagName = (char *) CPLMalloc( nLineTagNameBufLen );
+        char* pszLineTagName =
+            static_cast<char *>(CPLMalloc(nLineTagNameBufLen));
 
         if( bRing )
         {
-            snprintf( pszLineTagName, nLineTagNameBufLen, "<gml:LinearRing%s>", szAttributes );
+            snprintf( pszLineTagName, nLineTagNameBufLen,
+                      "<gml:LinearRing%s>", szAttributes );
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           pszLineTagName );
         }
         else
         {
-            snprintf( pszLineTagName, nLineTagNameBufLen, "<gml:LineString%s>", szAttributes );
+            snprintf( pszLineTagName, nLineTagNameBufLen,
+                      "<gml:LineString%s>", szAttributes );
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           pszLineTagName );
         }
 
-        // FREE TAG BUFFER
+        // Free tag buffer.
         CPLFree( pszLineTagName );
 
-        AppendCoordinateList( (OGRLineString *) poGeometry,
-                              ppszText, pnLength, pnMaxLength );
+        OGRLineString *poLineString = dynamic_cast<OGRLineString *>(poGeometry);
+        if( poLineString == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRLineString.");
+        }
+
+        AppendCoordinateList( poLineString, ppszText, pnLength, pnMaxLength );
 
         if( bRing )
             AppendString( ppszText, pnLength, pnMaxLength,
@@ -320,25 +319,30 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     else if( eFType == wkbPolygon )
     {
-        OGRPolygon      *poPolygon = (OGRPolygon *) poGeometry;
+        OGRPolygon *poPolygon = dynamic_cast<OGRPolygon *>(poGeometry);
+        if( poPolygon == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPolygon.");
+        }
 
-        // Buffer for polygon tag name + srsName attribute if set
+        // Buffer for polygon tag name + srsName attribute if set.
         const size_t nPolyTagLength = 13;
-        char* pszPolyTagName = NULL;
         const size_t nPolyTagNameBufLen = nPolyTagLength + nAttrsLength + 1;
-        pszPolyTagName = (char *) CPLMalloc( nPolyTagNameBufLen );
+        char* pszPolyTagName =
+            static_cast<char *>(CPLMalloc(nPolyTagNameBufLen));
 
-        // Compose Polygon tag with or without srsName attribute
-        snprintf( pszPolyTagName, nPolyTagNameBufLen, "<gml:Polygon%s>", szAttributes );
+        // Compose Polygon tag with or without srsName attribute.
+        snprintf( pszPolyTagName, nPolyTagNameBufLen,
+                  "<gml:Polygon%s>", szAttributes );
 
         AppendString( ppszText, pnLength, pnMaxLength,
                       pszPolyTagName );
 
-        // FREE TAG BUFFER
+        // Free tag buffer.
         CPLFree( pszPolyTagName );
 
-        // Don't add srsName to polygon rings
-
+        // Don't add srsName to polygon rings.
         if( poPolygon->getExteriorRing() != NULL )
         {
             AppendString( ppszText, pnLength, pnMaxLength,
@@ -382,18 +386,23 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
              || eFType == wkbMultiPoint
              || eFType == wkbGeometryCollection )
     {
-        OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
-        int             iMember;
+        OGRGeometryCollection *poGC =
+            dynamic_cast<OGRGeometryCollection *>(poGeometry);
+        if( poGC == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRGeometryCollection.");
+        }
         const char *pszElemClose = NULL;
         const char *pszMemberElem = NULL;
 
-        // Buffer for opening tag + srsName attribute
+        // Buffer for opening tag + srsName attribute.
         char* pszElemOpen = NULL;
 
         if( eFType == wkbMultiPolygon )
         {
             const size_t nBufLen = 13 + nAttrsLength + 1;
-            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            pszElemOpen = static_cast<char *>(CPLMalloc( nBufLen ));
             snprintf( pszElemOpen, nBufLen, "MultiPolygon%s>", szAttributes );
 
             pszElemClose = "MultiPolygon>";
@@ -402,8 +411,9 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         else if( eFType == wkbMultiLineString )
         {
             const size_t nBufLen = 16 + nAttrsLength + 1;
-            pszElemOpen = (char *) CPLMalloc( nBufLen );
-            snprintf( pszElemOpen, nBufLen, "MultiLineString%s>", szAttributes );
+            pszElemOpen = static_cast<char *>(CPLMalloc( nBufLen ));
+            snprintf( pszElemOpen, nBufLen,
+                      "MultiLineString%s>", szAttributes );
 
             pszElemClose = "MultiLineString>";
             pszMemberElem = "lineStringMember>";
@@ -411,7 +421,7 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         else if( eFType == wkbMultiPoint )
         {
             const size_t nBufLen = 11 + nAttrsLength + 1;
-            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            pszElemOpen = static_cast<char *>(CPLMalloc( nBufLen ));
             snprintf( pszElemOpen, nBufLen, "MultiPoint%s>", szAttributes );
 
             pszElemClose = "MultiPoint>";
@@ -420,7 +430,7 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         else
         {
             const size_t nBufLen = 19 + nAttrsLength + 1;
-            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            pszElemOpen = static_cast<char *>(CPLMalloc( nBufLen ));
             snprintf( pszElemOpen, nBufLen, "MultiGeometry%s>", szAttributes );
 
             pszElemClose = "MultiGeometry>";
@@ -430,7 +440,7 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
         AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen );
 
-        for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
+        for( int iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
         {
             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
 
@@ -451,7 +461,7 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
         AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
         AppendString( ppszText, pnLength, pnMaxLength, pszElemClose );
 
-        // FREE TAG BUFFER
+        // Free tag buffer.
         CPLFree( pszElemOpen );
     }
     else
@@ -466,41 +476,46 @@ static bool OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
 
 /************************************************************************/
 /*                   OGR_G_ExportEnvelopeToGMLTree()                    */
-/*                                                                      */
-/*      Export the envelope of a geometry as a gml:Box.                 */
 /************************************************************************/
 
+/** Export the envelope of a geometry as a gml:Box. */
 CPLXMLNode *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH hGeometry )
 
 {
-    CPLXMLNode *psBox, *psCoord;
     OGREnvelope sEnvelope;
-    char        szCoordinate[256];
-    char       *pszY;
 
     memset( &sEnvelope, 0, sizeof(sEnvelope) );
-    ((OGRGeometry *) hGeometry)->getEnvelope( &sEnvelope );
+    reinterpret_cast<OGRGeometry *>(hGeometry)->getEnvelope( &sEnvelope );
 
-    if( sEnvelope.MinX == 0 && sEnvelope.MaxX == 0
-        && sEnvelope.MaxX == 0 && sEnvelope.MaxY == 0 )
+    if( sEnvelope.MinX == 0 && sEnvelope.MaxX == 0 &&
+        sEnvelope.MinY == 0 && sEnvelope.MaxY == 0 )
     {
-        /* there is apparently a special way of representing a null box
-           geometry ... we should use it here eventually. */
-
+        // TODO: There is apparently a special way of representing a null box
+        // geometry. Should use it here eventually.
         return NULL;
     }
 
-    psBox = CPLCreateXMLNode( NULL, CXT_Element, "gml:Box" );
+    CPLXMLNode *psBox = CPLCreateXMLNode( NULL, CXT_Element, "gml:Box" );
 
 /* -------------------------------------------------------------------- */
 /*      Add minxy coordinate.                                           */
 /* -------------------------------------------------------------------- */
-    psCoord = CPLCreateXMLNode( psBox, CXT_Element, "gml:coord" );
+    CPLXMLNode *psCoord = CPLCreateXMLNode( psBox, CXT_Element, "gml:coord" );
 
+    char szCoordinate[256] = {};
     MakeGMLCoordinate( szCoordinate, sEnvelope.MinX, sEnvelope.MinY, 0.0,
                        false );
-    pszY = strstr(szCoordinate,",") + 1;
-    pszY[-1] = '\0';
+    char *pszY = strstr(szCoordinate, ",");
+    // There must be more after the comma or we have an internal consistency
+    // bug in MakeGMLCoordinate.
+    if( pszY == NULL || strlen(pszY) < 2)
+    {
+        CPLError(CE_Failure, CPLE_AssertionFailed,
+                 "MakeGMLCoordinate failed." );
+        return NULL;
+    }
+    *pszY = '\0';
+    pszY++;
 
     CPLCreateXMLElementAndValue( psCoord, "gml:X", szCoordinate );
     CPLCreateXMLElementAndValue( psCoord, "gml:Y", pszY );
@@ -512,7 +527,7 @@ CPLXMLNode *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH hGeometry )
 
     MakeGMLCoordinate( szCoordinate, sEnvelope.MaxX, sEnvelope.MaxY, 0.0,
                        false );
-    pszY = strstr(szCoordinate,",") + 1;
+    pszY = strstr(szCoordinate, ",") + 1;
     pszY[-1] = '\0';
 
     CPLCreateXMLElementAndValue( psCoord, "gml:X", szCoordinate );
@@ -521,43 +536,44 @@ CPLXMLNode *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH hGeometry )
     return psBox;
 }
 
-
 /************************************************************************/
 /*                     AppendGML3CoordinateList()                       */
 /************************************************************************/
 
-static void AppendGML3CoordinateList( const OGRSimpleCurve *poLine, bool bCoordSwap,
+static void AppendGML3CoordinateList( const OGRSimpleCurve *poLine,
+                                      bool bCoordSwap,
                                       char **ppszText, size_t *pnLength,
-                                      size_t *pnMaxLength, int nSRSDimensionLocFlags )
+                                      size_t *pnMaxLength,
+                                      int nSRSDimensionLocFlags )
 
 {
-    char        szCoordinate[256];
-    int         b3D = wkbHasZ(poLine->getGeometryType());
+    bool b3D = wkbHasZ(poLine->getGeometryType());
 
     *pnLength += strlen(*ppszText + *pnLength);
     _GrowBuffer( *pnLength + 40, ppszText, pnMaxLength );
 
-    if (b3D && (nSRSDimensionLocFlags & SRSDIM_LOC_POSLIST) != 0)
+    if( b3D && (nSRSDimensionLocFlags & SRSDIM_LOC_POSLIST) != 0 )
         strcat( *ppszText + *pnLength, "<gml:posList srsDimension=\"3\">" );
     else
         strcat( *ppszText + *pnLength, "<gml:posList>" );
     *pnLength += strlen(*ppszText + *pnLength);
 
+    char szCoordinate[256] = {};
 
     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     {
-        if (bCoordSwap)
+        if( bCoordSwap )
             OGRMakeWktCoordinate( szCoordinate,
-                           poLine->getY(iPoint),
-                           poLine->getX(iPoint),
-                           poLine->getZ(iPoint),
-                           b3D ? 3 : 2 );
+                                  poLine->getY(iPoint),
+                                  poLine->getX(iPoint),
+                                  poLine->getZ(iPoint),
+                                  b3D ? 3 : 2 );
         else
             OGRMakeWktCoordinate( szCoordinate,
-                           poLine->getX(iPoint),
-                           poLine->getY(iPoint),
-                           poLine->getZ(iPoint),
-                           b3D ? 3 : 2 );
+                                  poLine->getX(iPoint),
+                                  poLine->getY(iPoint),
+                                  poLine->getZ(iPoint),
+                                  b3D ? 3 : 2 );
         _GrowBuffer( *pnLength + strlen(szCoordinate)+1,
                      ppszText, pnMaxLength );
 
@@ -582,12 +598,14 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
                                     char **ppszText, size_t *pnLength,
                                     size_t *pnMaxLength,
                                     bool bIsSubGeometry,
-                                    bool bLongSRS,
+                                    GMLSRSNameFormat eSRSNameFormat,
+                                    bool bCoordSwap,
                                     bool bLineStringAsCurve,
                                     const char* pszGMLId,
                                     int nSRSDimensionLocFlags,
                                     bool bForceLineStringAsLinearRing,
-                                    const char* pszNamespaceDecl)
+                                    const char* pszNamespaceDecl,
+                                    const char* pszOverriddenElementName )
 
 {
 
@@ -595,19 +613,14 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 /*      Check for Spatial Reference System attached to given geometry   */
 /* -------------------------------------------------------------------- */
 
-    // Buffer for srsName, xmlns:gml, srsDimension and gml:id attributes (srsName="..." gml:id="...")
-    char szAttributes[256];
-    size_t nAttrsLength = 0;
+    // Buffer for srsName, xmlns:gml, srsDimension and gml:id attributes
+    // (srsName="..." gml:id="...").
 
-    szAttributes[0] = 0;
+    const OGRSpatialReference* poSRS =
+         poParentSRS ? poParentSRS : poGeometry->getSpatialReference();
 
-    const OGRSpatialReference* poSRS = NULL;
-    if (poParentSRS)
-        poSRS = poParentSRS;
-    else
-        poSRS = poGeometry->getSpatialReference();
-
-    bool bCoordSwap = false;
+    char szAttributes[256] = {};
+    size_t nAttrsLength = 0;
 
     if( pszNamespaceDecl != NULL )
     {
@@ -621,54 +634,37 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 
     if( NULL != poSRS )
     {
-        const char* pszAuthName = NULL;
-        const char* pszAuthCode = NULL;
-        const char* pszTarget = NULL;
-
-        if (poSRS->IsProjected())
-            pszTarget = "PROJCS";
-        else
-            pszTarget = "GEOGCS";
-
-        pszAuthName = poSRS->GetAuthorityName( pszTarget );
-        if( NULL != pszAuthName )
+        const char* pszTarget = poSRS->IsProjected() ? "PROJCS" : "GEOGCS";
+        const char* pszAuthName = poSRS->GetAuthorityName( pszTarget );
+        const char* pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
+        if( NULL != pszAuthName && strlen(pszAuthName) < 10 &&
+            NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
         {
-            if( EQUAL( pszAuthName, "EPSG" ) )
+            if( !bIsSubGeometry )
             {
-                pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
-                if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
+                if (eSRSNameFormat == SRSNAME_OGC_URN)
                 {
-                    if (bLongSRS && !(((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong() ||
-                                      ((OGRSpatialReference*)poSRS)->EPSGTreatsAsNorthingEasting()))
-                    {
-                        OGRSpatialReference oSRS;
-                        if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
-                        {
-                            if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
-                                bCoordSwap = true;
-                        }
-                    }
-
-                    if (!bIsSubGeometry)
-                    {
-                        if (bLongSRS)
-                        {
-                            snprintf( szAttributes + nAttrsLength,
-                                      sizeof(szAttributes) - nAttrsLength,
-                                      " srsName=\"urn:ogc:def:crs:%s::%s\"",
-                                      pszAuthName, pszAuthCode );
-                        }
-                        else
-                        {
-                            snprintf( szAttributes + nAttrsLength,
-                                      sizeof(szAttributes) - nAttrsLength,
-                                      " srsName=\"%s:%s\"",
-                                      pszAuthName, pszAuthCode );
-                        }
-
-                        nAttrsLength += strlen(szAttributes + nAttrsLength);
-                    }
+                    snprintf( szAttributes + nAttrsLength,
+                              sizeof(szAttributes) - nAttrsLength,
+                              " srsName=\"urn:ogc:def:crs:%s::%s\"",
+                              pszAuthName, pszAuthCode );
+                }
+                else if (eSRSNameFormat == SRSNAME_SHORT)
+                {
+                    snprintf( szAttributes + nAttrsLength,
+                              sizeof(szAttributes) - nAttrsLength,
+                              " srsName=\"%s:%s\"",
+                              pszAuthName, pszAuthCode );
                 }
+                else if (eSRSNameFormat == SRSNAME_OGC_URL)
+                {
+                    snprintf(
+                        szAttributes + nAttrsLength,
+                        sizeof(szAttributes) - nAttrsLength,
+                        " srsName=\"http://www.opengis.net/def/crs/%s/0/%s\"",
+                        pszAuthName, pszAuthCode );
+                }
+                nAttrsLength += strlen(szAttributes + nAttrsLength);
             }
         }
     }
@@ -684,7 +680,8 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         nSRSDimensionLocFlags &= ~SRSDIM_LOC_GEOMETRY;
     }
 
-    if (pszGMLId != NULL && nAttrsLength + 9 + strlen(pszGMLId) + 1 < sizeof(szAttributes))
+    if( pszGMLId != NULL &&
+        nAttrsLength + 9 + strlen(pszGMLId) + 1 < sizeof(szAttributes) )
     {
         snprintf( szAttributes + nAttrsLength,
                   sizeof(szAttributes) - nAttrsLength,
@@ -693,30 +690,35 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         nAttrsLength += strlen(szAttributes + nAttrsLength);
     }
 
-    OGRwkbGeometryType eType = poGeometry->getGeometryType();
-    OGRwkbGeometryType eFType = wkbFlatten(eType);
+    const OGRwkbGeometryType eType = poGeometry->getGeometryType();
+    const OGRwkbGeometryType eFType = wkbFlatten(eType);
 
 /* -------------------------------------------------------------------- */
 /*      2D Point                                                        */
 /* -------------------------------------------------------------------- */
     if( eType == wkbPoint )
     {
-        char    szCoordinate[256];
-        OGRPoint *poPoint = (OGRPoint *) poGeometry;
+        const OGRPoint *poPoint = dynamic_cast<const OGRPoint *>(poGeometry);
+        if( poPoint == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPoint.");
+        }
 
-        if (bCoordSwap)
+        char szCoordinate[256] = {};
+        if( bCoordSwap )
             OGRMakeWktCoordinate( szCoordinate,
-                           poPoint->getY(), poPoint->getX(), 0.0, 2 );
+                                  poPoint->getY(), poPoint->getX(), 0.0, 2 );
         else
             OGRMakeWktCoordinate( szCoordinate,
-                           poPoint->getX(), poPoint->getY(), 0.0, 2 );
+                                  poPoint->getX(), poPoint->getY(), 0.0, 2 );
 
         _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
                      ppszText, pnMaxLength );
 
-        snprintf( *ppszText + *pnLength, *pnMaxLength -  *pnLength,
-                "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
-                 szAttributes, szCoordinate );
+        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength,
+                  "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
+                  szAttributes, szCoordinate );
 
         *pnLength += strlen( *ppszText + *pnLength );
     }
@@ -725,22 +727,30 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     else if( eType == wkbPoint25D )
     {
-        char    szCoordinate[256];
-        OGRPoint *poPoint = (OGRPoint *) poGeometry;
+        const OGRPoint *poPoint = dynamic_cast<const OGRPoint *>(poGeometry);
+        if( poPoint == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPoint.");
+            return false;
+        }
 
-        if (bCoordSwap)
-            OGRMakeWktCoordinate( szCoordinate,
-                           poPoint->getY(), poPoint->getX(), poPoint->getZ(), 3 );
+        char szCoordinate[256] = {};
+        if( bCoordSwap )
+            OGRMakeWktCoordinate(
+                szCoordinate,
+                poPoint->getY(), poPoint->getX(), poPoint->getZ(), 3 );
         else
-            OGRMakeWktCoordinate( szCoordinate,
-                           poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3 );
+            OGRMakeWktCoordinate(
+                szCoordinate,
+                poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3 );
 
         _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
                      ppszText, pnMaxLength );
 
-        snprintf( *ppszText + *pnLength, *pnMaxLength -  *pnLength,
-                "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
-                 szAttributes, szCoordinate );
+        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength,
+                  "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
+                  szAttributes, szCoordinate );
 
         *pnLength += strlen( *ppszText + *pnLength );
     }
@@ -750,9 +760,10 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     else if( eFType == wkbLineString )
     {
-        bool bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING") ||
-                    bForceLineStringAsLinearRing;
-        if (!bRing && bLineStringAsCurve)
+        const bool bRing =
+            EQUAL(poGeometry->getGeometryName(), "LINEARRING") ||
+            bForceLineStringAsLinearRing;
+        if( !bRing && bLineStringAsCurve )
         {
             AppendString( ppszText, pnLength, pnMaxLength,
                             "<gml:Curve" );
@@ -760,45 +771,65 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
                             szAttributes );
             AppendString( ppszText, pnLength, pnMaxLength,
                             "><gml:segments><gml:LineStringSegment>" );
-            AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap,
-                                ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
-            AppendString( ppszText, pnLength, pnMaxLength,
-                            "</gml:LineStringSegment></gml:segments></gml:Curve>" );
+            const OGRLineString *poLineString =
+                dynamic_cast<const OGRLineString *>(poGeometry);
+            if( poLineString == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRLineString.");
+            }
+            AppendGML3CoordinateList(
+                poLineString, bCoordSwap,
+                ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
+            AppendString(ppszText, pnLength, pnMaxLength,
+                         "</gml:LineStringSegment></gml:segments></gml:Curve>");
         }
         else
         {
-            // Buffer for tag name + srsName attribute if set
+            // Buffer for tag name + srsName attribute if set.
             const size_t nLineTagLength = 16;
-            char* pszLineTagName = NULL;
             const size_t nLineTagNameBufLen = nLineTagLength + nAttrsLength + 1;
-            pszLineTagName = (char *) CPLMalloc( nLineTagNameBufLen );
+            char* pszLineTagName =
+                static_cast<char *>(CPLMalloc(nLineTagNameBufLen));
 
             if( bRing )
             {
-                /* LinearRing isn't supposed to have srsName attribute according to GML3 SF-0 */
+                // LinearRing isn't supposed to have srsName attribute according
+                // to GML3 SF-0.
                 AppendString( ppszText, pnLength, pnMaxLength,
-                            "<gml:LinearRing>" );
+                              "<gml:LinearRing>" );
             }
             else
             {
-                snprintf( pszLineTagName, nLineTagNameBufLen, "<gml:LineString%s>", szAttributes );
+                snprintf( pszLineTagName, nLineTagNameBufLen,
+                          "<gml:LineString%s>", szAttributes );
 
                 AppendString( ppszText, pnLength, pnMaxLength,
-                            pszLineTagName );
+                              pszLineTagName );
             }
 
-            // FREE TAG BUFFER
+            // Free tag buffer.
             CPLFree( pszLineTagName );
 
-            AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap,
-                                ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
+            const OGRLineString *poLineString =
+                dynamic_cast<const OGRLineString *>(poGeometry);
+            if( poLineString == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRLineString.");
+                return false;
+            }
+
+            AppendGML3CoordinateList( poLineString, bCoordSwap,
+                                      ppszText, pnLength, pnMaxLength,
+                                      nSRSDimensionLocFlags );
 
             if( bRing )
                 AppendString( ppszText, pnLength, pnMaxLength,
-                            "</gml:LinearRing>" );
+                              "</gml:LinearRing>" );
             else
                 AppendString( ppszText, pnLength, pnMaxLength,
-                            "</gml:LineString>" );
+                              "</gml:LineString>" );
         }
     }
 
@@ -811,20 +842,27 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
                         "<gml:Curve" );
         AppendString( ppszText, pnLength, pnMaxLength,
                         szAttributes );
-        OGRSimpleCurve* poSC = (OGRSimpleCurve *) poGeometry;
-        /* SQL MM has a unique type for arc and circle, GML not */
+        const OGRSimpleCurve* poSC =
+            dynamic_cast<const OGRSimpleCurve *>(poGeometry);
+        if( poSC == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRSimpleCurve.");
+            return false;
+        }
+        // SQL MM has a unique type for arc and circle, GML does not.
         if( poSC->getNumPoints() == 3 &&
             poSC->getX(0) == poSC->getX(2) &&
             poSC->getY(0) == poSC->getY(2) )
         {
-            double dfMidX = (poSC->getX(0) + poSC->getX(1)) / 2;
-            double dfMidY = (poSC->getY(0) + poSC->getY(1)) / 2;
-            double dfDirX = (poSC->getX(1) - poSC->getX(0)) / 2;
-            double dfDirY = (poSC->getY(1) - poSC->getY(0)) / 2;
-            double dfNormX = -dfDirY;
-            double dfNormY = dfDirX;
-            double dfNewX = dfMidX + dfNormX;
-            double dfNewY = dfMidY + dfNormY;
+            const double dfMidX = (poSC->getX(0) + poSC->getX(1)) / 2.0;
+            const double dfMidY = (poSC->getY(0) + poSC->getY(1)) / 2.0;
+            const double dfDirX = (poSC->getX(1) - poSC->getX(0)) / 2.0;
+            const double dfDirY = (poSC->getY(1) - poSC->getY(0)) / 2.0;
+            const double dfNormX = -dfDirY;
+            const double dfNormY = dfDirX;
+            const double dfNewX = dfMidX + dfNormX;
+            const double dfNewY = dfMidY + dfNormY;
             OGRLineString* poLS = new OGRLineString();
             OGRPoint p;
             poSC->getPoint(0, &p);
@@ -836,21 +874,23 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
                 poLS->addPoint(dfNewX, dfNewY);
             poLS->addPoint(&p);
             AppendString( ppszText, pnLength, pnMaxLength,
-                            "><gml:segments><gml:Circle>" );
-            AppendGML3CoordinateList( poLS, bCoordSwap,
-                                ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
+                          "><gml:segments><gml:Circle>" );
+            AppendGML3CoordinateList(
+                poLS, bCoordSwap,
+                ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
             AppendString( ppszText, pnLength, pnMaxLength,
-                            "</gml:Circle></gml:segments></gml:Curve>" );
+                          "</gml:Circle></gml:segments></gml:Curve>" );
             delete poLS;
         }
         else
         {
             AppendString( ppszText, pnLength, pnMaxLength,
-                            "><gml:segments><gml:ArcString>" );
-            AppendGML3CoordinateList( poSC, bCoordSwap,
-                                ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
+                          "><gml:segments><gml:ArcString>" );
+            AppendGML3CoordinateList(
+                poSC, bCoordSwap,
+                ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
             AppendString( ppszText, pnLength, pnMaxLength,
-                            "</gml:ArcString></gml:segments></gml:Curve>" );
+                          "</gml:ArcString></gml:segments></gml:Curve>" );
         }
     }
 
@@ -859,21 +899,29 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     else if( eFType == wkbCompoundCurve )
     {
-        AppendString( ppszText, pnLength, pnMaxLength,
-                        "<gml:CompositeCurve" );
-        AppendString( ppszText, pnLength, pnMaxLength,
-                        szAttributes );
-        AppendString( ppszText, pnLength, pnMaxLength,">");
+        AppendString( ppszText, pnLength, pnMaxLength, "<gml:CompositeCurve" );
+        AppendString( ppszText, pnLength, pnMaxLength, szAttributes );
+        AppendString( ppszText, pnLength, pnMaxLength, ">");
 
-        OGRCompoundCurve* poCC = (OGRCompoundCurve*)poGeometry;
-        for(int i=0;i<poCC->getNumCurves();i++)
+        const OGRCompoundCurve* poCC =
+            dynamic_cast<const OGRCompoundCurve *>(poGeometry);
+        if( poCC == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRCompoundCurve.");
+            return false;
+        }
+        for( int i = 0; i < poCC->getNumCurves(); i++ )
         {
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<gml:curveMember>" );
-            if( !OGR2GML3GeometryAppend( poCC->getCurve(i), poSRS, ppszText, pnLength,
-                                         pnMaxLength, true, bLongSRS,
+            if( !OGR2GML3GeometryAppend( poCC->getCurve(i), poSRS,
+                                         ppszText, pnLength,
+                                         pnMaxLength, true, eSRSNameFormat,
+                                         bCoordSwap,
                                          bLineStringAsCurve,
-                                         NULL, nSRSDimensionLocFlags, false, NULL) )
+                                         NULL, nSRSDimensionLocFlags,
+                                         false, NULL, NULL) )
                 return false;
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</gml:curveMember>" );
@@ -887,24 +935,36 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 /* -------------------------------------------------------------------- */
     else if( eFType == wkbPolygon || eFType == wkbCurvePolygon )
     {
-        OGRCurvePolygon      *poCP = (OGRCurvePolygon *) poGeometry;
+        const OGRCurvePolygon *poCP =
+            dynamic_cast<const OGRCurvePolygon *>(poGeometry);
+        if( poCP == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRCurvePolygon.");
+            return false;
+        }
 
-        // Buffer for polygon tag name + srsName attribute if set
-        const size_t nPolyTagLength = 13;
-        char* pszPolyTagName = NULL;
+        // Buffer for polygon tag name + srsName attribute if set.
+        const char* pszElemName = pszOverriddenElementName ?
+                                        pszOverriddenElementName : "Polygon";
+        const size_t nPolyTagLength = 7 + strlen(pszElemName);
         const size_t nPolyTagNameBufLen = nPolyTagLength + nAttrsLength + 1;
-        pszPolyTagName = (char *) CPLMalloc( nPolyTagNameBufLen );
+        char* pszPolyTagName =
+            static_cast<char *>(CPLMalloc(nPolyTagNameBufLen));
 
-        // Compose Polygon tag with or without srsName attribute
-        snprintf( pszPolyTagName, nPolyTagNameBufLen, "<gml:Polygon%s>", szAttributes );
+        // Compose Polygon tag with or without srsName attribute.
+        snprintf( pszPolyTagName, nPolyTagNameBufLen,
+                  "<gml:%s%s>",
+                  pszElemName,
+                  szAttributes );
 
         AppendString( ppszText, pnLength, pnMaxLength,
                       pszPolyTagName );
 
-        // FREE TAG BUFFER
+        // Free tag buffer.
         CPLFree( pszPolyTagName );
 
-        // Don't add srsName to polygon rings
+        // Don't add srsName to polygon rings.
 
         if( poCP->getExteriorRingCurve() != NULL )
         {
@@ -913,8 +973,10 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 
             if( !OGR2GML3GeometryAppend( poCP->getExteriorRingCurve(), poSRS,
                                          ppszText, pnLength, pnMaxLength,
-                                         true, bLongSRS, bLineStringAsCurve,
-                                         NULL, nSRSDimensionLocFlags, true, NULL) )
+                                         true, eSRSNameFormat, bCoordSwap,
+                                         bLineStringAsCurve,
+                                         NULL, nSRSDimensionLocFlags,
+                                         true, NULL, NULL) )
             {
                 return false;
             }
@@ -925,23 +987,66 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 
         for( int iRing = 0; iRing < poCP->getNumInteriorRings(); iRing++ )
         {
-            OGRCurve *poRing = poCP->getInteriorRingCurve(iRing);
+            const OGRCurve *poRing = poCP->getInteriorRingCurve(iRing);
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           "<gml:interior>" );
 
             if( !OGR2GML3GeometryAppend( poRing, poSRS, ppszText, pnLength,
-                                         pnMaxLength, true, bLongSRS,
+                                         pnMaxLength, true, eSRSNameFormat,
+                                         bCoordSwap,
                                          bLineStringAsCurve,
-                                         NULL, nSRSDimensionLocFlags, true, NULL) )
+                                         NULL, nSRSDimensionLocFlags,
+                                         true, NULL, NULL) )
                 return false;
 
             AppendString( ppszText, pnLength, pnMaxLength,
                           "</gml:interior>" );
         }
 
+        AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
+        AppendString( ppszText, pnLength, pnMaxLength, pszElemName );
+        AppendString( ppszText, pnLength, pnMaxLength, ">" );
+    }
+
+/* -------------------------------------------------------------------- */
+/*     Triangle                                                         */
+/* -------------------------------------------------------------------- */
+    else if( eFType == wkbTriangle )
+    {
+        const OGRTriangle *poTri =
+                                dynamic_cast<const OGRTriangle *>(poGeometry);
+        if( poTri == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRTriangle.");
+            return false;
+        }
+
+        AppendString( ppszText, pnLength, pnMaxLength, "<gml:Triangle>" );
+
+        if( poTri->getExteriorRingCurve() != NULL )
+        {
+            AppendString( ppszText, pnLength, pnMaxLength,
+                          "<gml:exterior>" );
+
+            if( !OGR2GML3GeometryAppend( poTri->getExteriorRingCurve(), poSRS,
+                                         ppszText, pnLength,
+                                         pnMaxLength, true, eSRSNameFormat,
+                                         bCoordSwap,
+                                         bLineStringAsCurve,
+                                         NULL, nSRSDimensionLocFlags,
+                                         true, NULL, NULL) )
+            {
+                return false;
+            }
+
+            AppendString( ppszText, pnLength, pnMaxLength,
+                          "</gml:exterior>" );
+        }
+
         AppendString( ppszText, pnLength, pnMaxLength,
-                      "</gml:Polygon>" );
+                      "</gml:Triangle>" );
     }
 
 /* -------------------------------------------------------------------- */
@@ -954,18 +1059,24 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
              || eFType == wkbMultiPoint
              || eFType == wkbGeometryCollection )
     {
-        OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
-        int             iMember;
+        const OGRGeometryCollection *poGC =
+            dynamic_cast<const OGRGeometryCollection *>(poGeometry);
+        if( poGC == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRGeometryCollection.");
+            return false;
+        }
         const char *pszElemClose = NULL;
         const char *pszMemberElem = NULL;
 
-        // Buffer for opening tag + srsName attribute
+        // Buffer for opening tag + srsName attribute.
         char* pszElemOpen = NULL;
 
         if( eFType == wkbMultiPolygon || eFType == wkbMultiSurface )
         {
             const size_t nBufLen = 13 + nAttrsLength + 1;
-            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            pszElemOpen = static_cast<char *>(CPLMalloc(nBufLen));
             snprintf( pszElemOpen, nBufLen, "MultiSurface%s>", szAttributes );
 
             pszElemClose = "MultiSurface>";
@@ -974,7 +1085,7 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         else if( eFType == wkbMultiLineString || eFType == wkbMultiCurve )
         {
             const size_t nBufLen = 16 + nAttrsLength + 1;
-            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            pszElemOpen = static_cast<char *>(CPLMalloc(nBufLen));
             snprintf( pszElemOpen, nBufLen, "MultiCurve%s>", szAttributes );
 
             pszElemClose = "MultiCurve>";
@@ -983,7 +1094,7 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         else if( eFType == wkbMultiPoint )
         {
             const size_t nBufLen = 11 + nAttrsLength + 1;
-            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            pszElemOpen = static_cast<char *>(CPLMalloc(nBufLen));
             snprintf( pszElemOpen, nBufLen, "MultiPoint%s>", szAttributes );
 
             pszElemClose = "MultiPoint>";
@@ -992,7 +1103,7 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         else
         {
             const size_t nBufLen = 19 + nAttrsLength + 1;
-            pszElemOpen = (char *) CPLMalloc( nBufLen );
+            pszElemOpen = static_cast<char *>(CPLMalloc(nBufLen));
             snprintf( pszElemOpen, nBufLen, "MultiGeometry%s>", szAttributes );
 
             pszElemClose = "MultiGeometry>";
@@ -1002,21 +1113,23 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
         AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen );
 
-        for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
+        for( int iMember = 0; iMember < poGC->getNumGeometries(); iMember++ )
         {
-            OGRGeometry *poMember = poGC->getGeometryRef( iMember );
+            const OGRGeometry *poMember = poGC->getGeometryRef( iMember );
 
             AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
 
             char* pszGMLIdSub = NULL;
-            if (pszGMLId != NULL)
+            if( pszGMLId != NULL )
                 pszGMLIdSub = CPLStrdup(CPLSPrintf("%s.%d", pszGMLId, iMember));
 
             if( !OGR2GML3GeometryAppend( poMember, poSRS,
                                          ppszText, pnLength, pnMaxLength,
-                                         true, bLongSRS, bLineStringAsCurve,
-                                         pszGMLIdSub, nSRSDimensionLocFlags, false, NULL ) )
+                                         true, eSRSNameFormat, bCoordSwap,
+                                         bLineStringAsCurve,
+                                         pszGMLIdSub, nSRSDimensionLocFlags,
+                                         false, NULL, NULL ) )
             {
                 CPLFree(pszGMLIdSub);
                 return false;
@@ -1031,9 +1144,119 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
         AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
         AppendString( ppszText, pnLength, pnMaxLength, pszElemClose );
 
-        // FREE TAG BUFFER
+        // Free tag buffer.
         CPLFree( pszElemOpen );
     }
+
+/* -------------------------------------------------------------------- */
+/*      Polyhedral Surface                                              */
+/* -------------------------------------------------------------------- */
+    else if( eFType == wkbPolyhedralSurface)
+    {
+        // The patches enclosed in a single <gml:polygonPatches> tag need to be co-planar.
+        // TODO - enforce the condition within this implementation
+        const OGRPolyhedralSurface *poPS =
+            dynamic_cast<const OGRPolyhedralSurface *>(poGeometry);
+        if( poPS == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPolyhedralSurface.");
+            return false;
+        }
+
+        AppendString( ppszText, pnLength, pnMaxLength, "<gml:PolyhedralSurface" );
+        AppendString( ppszText, pnLength, pnMaxLength, szAttributes );
+        AppendString( ppszText, pnLength, pnMaxLength, "><gml:polygonPatches>" );
+
+        for( int iMember = 0; iMember < poPS->getNumGeometries(); iMember++)
+        {
+            const OGRGeometry *poMember = poPS->getGeometryRef( iMember );
+            char* pszGMLIdSub = NULL;
+            if (pszGMLId != NULL)
+                pszGMLIdSub = CPLStrdup(CPLSPrintf("%s.%d", pszGMLId, iMember));
+
+            if( !OGR2GML3GeometryAppend( poMember, poSRS,
+                                         ppszText, pnLength,
+                                         pnMaxLength, true, eSRSNameFormat,
+                                         bCoordSwap,
+                                         bLineStringAsCurve,
+                                         NULL, nSRSDimensionLocFlags,
+                                         false, NULL, "PolygonPatch" ) )
+            {
+                CPLFree(pszGMLIdSub);
+                return false;
+            }
+
+            CPLFree(pszGMLIdSub);
+        }
+
+        AppendString( ppszText, pnLength, pnMaxLength,
+                      "</gml:polygonPatches>" );
+        AppendString( ppszText, pnLength, pnMaxLength,
+                      "</gml:PolyhedralSurface>" );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      TIN                                                             */
+/* -------------------------------------------------------------------- */
+    else if( eFType == wkbTIN)
+    {
+        // OGR uses the following hierarchy for TriangulatedSurface -
+
+        // <gml:TriangulatedSurface>
+        //     <gml:patches>
+        //         <gml:Triangle>
+        //             <gml:exterior>
+        //                 <gml:LinearRing>
+        //                     <gml:posList srsDimension=...>...</gml:posList>
+        //                 </gml:LinearRing>
+        //             </gml:exterior>
+        //         </gml:Triangle>
+        //     </gml:patches>
+        // </gml:TriangulatedSurface>
+
+        // <gml:trianglePatches> is deprecated, so write feature is not enabled for <gml:trianglePatches>
+        const OGRTriangulatedSurface *poTIN =
+            dynamic_cast<const OGRTriangulatedSurface *>(poGeometry);
+        if( poTIN == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRTriangulatedSurface.");
+            return false;
+        }
+
+        AppendString( ppszText, pnLength, pnMaxLength, "<gml:TriangulatedSurface" );
+        AppendString( ppszText, pnLength, pnMaxLength, szAttributes );
+        AppendString( ppszText, pnLength, pnMaxLength, "><gml:patches>" );
+
+        for( int iMember = 0; iMember < poTIN->getNumGeometries(); iMember++)
+        {
+            const OGRGeometry *poMember = poTIN->getGeometryRef( iMember );
+
+            char* pszGMLIdSub = NULL;
+            if (pszGMLId != NULL)
+                pszGMLIdSub = CPLStrdup(CPLSPrintf("%s.%d", pszGMLId, iMember));
+
+            if( !OGR2GML3GeometryAppend( poMember, poSRS,
+                                         ppszText, pnLength,
+                                         pnMaxLength, true, eSRSNameFormat,
+                                         bCoordSwap,
+                                         bLineStringAsCurve,
+                                         NULL, nSRSDimensionLocFlags,
+                                         false, NULL, NULL) )
+            {
+                CPLFree(pszGMLIdSub);
+                return false;
+            }
+
+            CPLFree(pszGMLIdSub);
+        }
+
+        AppendString( ppszText, pnLength, pnMaxLength, "</gml:patches>" );
+        AppendString( ppszText, pnLength, pnMaxLength,
+                      "</gml:TriangulatedSurface>" );
+    }
+
     else
     {
         CPLError(CE_Failure, CPLE_NotSupported, "Unsupported geometry type %s",
@@ -1048,17 +1271,15 @@ static bool OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
 /*                       OGR_G_ExportToGMLTree()                        */
 /************************************************************************/
 
+/** Convert a geometry into GML format. */
 CPLXMLNode *OGR_G_ExportToGMLTree( OGRGeometryH hGeometry )
 
 {
-    char        *pszText;
-    CPLXMLNode  *psTree;
-
-    pszText = OGR_G_ExportToGML( hGeometry );
+    char *pszText = OGR_G_ExportToGML( hGeometry );
     if( pszText == NULL )
         return NULL;
 
-    psTree = CPLParseXMLString( pszText );
+    CPLXMLNode *psTree = CPLParseXMLString( pszText );
 
     CPLFree( pszText );
 
@@ -1101,22 +1322,45 @@ char *OGR_G_ExportToGML( OGRGeometryH hGeometry )
  *
  * The supported options are :
  * <ul>
- * <li> FORMAT=GML3 (GML2 or GML32 also accepted starting with GDAL 2.1). If not set, it will default to GML 2.1.2 output.
- * <li> GML3_LINESTRING_ELEMENT=curve. (Only valid for FORMAT=GML3) To use gml:Curve element for linestrings.
- *     Otherwise gml:LineString will be used .
- * <li> GML3_LONGSRS=YES/NO. (Only valid for FORMAT=GML3) Default to YES. If YES, SRS with EPSG authority will
- *      be written with the "urn:ogc:def:crs:EPSG::" prefix.
- *      In the case, if the SRS is a geographic SRS without explicit AXIS order, but that the same SRS authority code
- *      imported with ImportFromEPSGA() should be treated as lat/long, then the function will take care of coordinate order swapping.
- *      If set to NO, SRS with EPSG authority will be written with the "EPSG:" prefix, even if they are in lat/long order.
- * <li> GMLID=astring. If specified, a gml:id attribute will be written in the top-level geometry element with the provided value.
+ * <li> FORMAT=GML2/GML3/GML32 (GML2 or GML32 added in GDAL 2.1).
+ *      If not set, it will default to GML 2.1.2 output.
+ * <li> GML3_LINESTRING_ELEMENT=curve. (Only valid for FORMAT=GML3)
+ *      To use gml:Curve element for linestrings.
+ *      Otherwise gml:LineString will be used .
+ * <li> GML3_LONGSRS=YES/NO. (Only valid for FORMAT=GML3, deprecated by
+ *      SRSNAME_FORMAT in GDAL >=2.2). Defaults to YES.
+ *      If YES, SRS with EPSG authority will be written with the
+ *      "urn:ogc:def:crs:EPSG::" prefix.
+ *      In the case the SRS is a SRS without explicit AXIS order, but that the
+ *      same SRS authority code
+ *      imported with ImportFromEPSGA() should be treated as lat/long or
+ *      northing/easting, then the function will take care of coordinate order
+ *      swapping.
+ *      If set to NO, SRS with EPSG authority will be written with the "EPSG:"
+ *      prefix, even if they are in lat/long order.
+ * <li> SRSNAME_FORMAT=SHORT/OGC_URN/OGC_URL (Only valid for FORMAT=GML3, added
+ *      in GDAL 2.2). Defaults to OGC_URN.  If SHORT, then srsName will be in
+ *      the form AUTHORITY_NAME:AUTHORITY_CODE If OGC_URN, then srsName will be
+ *      in the form urn:ogc:def:crs:AUTHORITY_NAME::AUTHORITY_CODE If OGC_URL,
+ *      then srsName will be in the form
+ *      http://www.opengis.net/def/crs/AUTHORITY_NAME/0/AUTHORITY_CODE For
+ *      OGC_URN and OGC_URL, in the case the SRS is a SRS without explicit AXIS
+ *      order, but that the same SRS authority code imported with
+ *      ImportFromEPSGA() should be treated as lat/long or northing/easting,
+ *      then the function will take care of coordinate order swapping.
+ * <li> GMLID=astring. If specified, a gml:id attribute will be written in the
+ *      top-level geometry element with the provided value.
  *      Required for GML 3.2 compatibility.
- * <li> SRSDIMENSION_LOC=POSLIST/GEOMETRY/GEOMETRY,POSLIST. (Only valid for FORMAT=GML3, GDAL >= 2.0) Default to POSLIST.
- *      For 2.5D geometries, define the location where to attach the srsDimension attribute.
- *      There are diverging implementations. Some put in on the <gml:posList> element, other
- *      on the top geometry element.
- * <li> NAMESPACE_DECL=YES/NO. If set to YES, xmlns:gml="http://www.opengis.net/gml" will be added to the
- *      root node for GML < 3.2 or xmlns:gml="http://www.opengis.net/gml/3.2" for GML 3.2
+ * <li> SRSDIMENSION_LOC=POSLIST/GEOMETRY/GEOMETRY,POSLIST. (Only valid for
+ *      FORMAT=GML3/GML32, GDAL >= 2.0) Default to POSLIST.
+ *      For 2.5D geometries, define the location where to attach the
+ *      srsDimension attribute.
+ *      There are diverging implementations. Some put in on the
+ *      <gml:posList> element, other on the top geometry element.
+
+ * <li> NAMESPACE_DECL=YES/NO. If set to YES,
+ *      xmlns:gml="http://www.opengis.net/gml" will be added to the root node
+ *      for GML < 3.2 or xmlns:gml="http://www.opengis.net/gml/3.2" for GML 3.2
  * </ul>
  *
  * Note that curve geometries like CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
@@ -1134,29 +1378,68 @@ char *OGR_G_ExportToGML( OGRGeometryH hGeometry )
 char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
 
 {
-    char        *pszText;
-    size_t       nLength = 0, nMaxLength = 1;
-
     if( hGeometry == NULL )
         return CPLStrdup( "" );
 
-    pszText = (char *) CPLMalloc(nMaxLength);
+    // Do not use hGeometry after here.
+    OGRGeometry* poGeometry = reinterpret_cast<OGRGeometry*>(hGeometry);
+
+    size_t nLength = 0;
+    size_t nMaxLength = 1;
+
+    char *pszText = static_cast<char *>(CPLMalloc(nMaxLength));
     pszText[0] = '\0';
 
     const char* pszFormat = CSLFetchNameValue(papszOptions, "FORMAT");
-    bool bNamespaceDecl = CPLTestBool(CSLFetchNameValueDef(papszOptions, "NAMESPACE_DECL", "NO")) != FALSE;
-    if (pszFormat && (EQUAL(pszFormat, "GML3") || EQUAL(pszFormat, "GML32")) )
+    const bool bNamespaceDecl =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions,
+                                         "NAMESPACE_DECL", "NO")) != FALSE;
+    if( pszFormat && (EQUAL(pszFormat, "GML3") || EQUAL(pszFormat, "GML32")) )
     {
-        const char* pszLineStringElement = CSLFetchNameValue(papszOptions, "GML3_LINESTRING_ELEMENT");
-        bool bLineStringAsCurve = (pszLineStringElement && EQUAL(pszLineStringElement, "curve"));
-        bool bLongSRS = CPLTestBool(CSLFetchNameValueDef(papszOptions, "GML3_LONGSRS", "YES")) != FALSE;
+        const char* pszLineStringElement =
+            CSLFetchNameValue(papszOptions, "GML3_LINESTRING_ELEMENT");
+        const bool bLineStringAsCurve =
+            pszLineStringElement && EQUAL(pszLineStringElement, "curve");
+        const char* pszLongSRS =
+            CSLFetchNameValue(papszOptions, "GML3_LONGSRS");
+        const char* pszSRSNameFormat =
+            CSLFetchNameValue(papszOptions, "SRSNAME_FORMAT");
+        GMLSRSNameFormat eSRSNameFormat = SRSNAME_OGC_URN;
+        if( pszSRSNameFormat )
+        {
+            if( pszLongSRS )
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "Both GML3_LONGSRS and SRSNAME_FORMAT specified. "
+                         "Ignoring GML3_LONGSRS");
+            }
+            if( EQUAL(pszSRSNameFormat, "SHORT") )
+                eSRSNameFormat = SRSNAME_SHORT;
+            else if( EQUAL(pszSRSNameFormat, "OGC_URN") )
+                eSRSNameFormat = SRSNAME_OGC_URN;
+            else if( EQUAL(pszSRSNameFormat, "OGC_URL") )
+                eSRSNameFormat = SRSNAME_OGC_URL;
+            else
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "Invalid value for SRSNAME_FORMAT. "
+                         "Using SRSNAME_OGC_URN");
+            }
+        }
+        else if( pszLongSRS && !CPLTestBool(pszLongSRS) )
+            eSRSNameFormat = SRSNAME_SHORT;
+
         const char* pszGMLId = CSLFetchNameValue(papszOptions, "GMLID");
         if( pszGMLId == NULL && EQUAL(pszFormat, "GML32") )
-            CPLError(CE_Warning, CPLE_AppDefined, "FORMAT=GML32 specified but not GMLID set");
-        const char* pszSRSDimensionLoc = CSLFetchNameValueDef(papszOptions,"SRSDIMENSION_LOC","POSLIST");
-        char** papszSRSDimensionLoc = CSLTokenizeString2(pszSRSDimensionLoc, ",", 0);
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "FORMAT=GML32 specified but not GMLID set");
+        const char* pszSRSDimensionLoc =
+                CSLFetchNameValueDef(papszOptions, "SRSDIMENSION_LOC",
+                                     "POSLIST");
+        char** papszSRSDimensionLoc =
+            CSLTokenizeString2(pszSRSDimensionLoc, ",", 0);
         int nSRSDimensionLocFlags = 0;
-        for(int i=0; papszSRSDimensionLoc[i] != NULL; i++)
+        for( int i = 0; papszSRSDimensionLoc[i] != NULL; i++ )
         {
             if( EQUAL(papszSRSDimensionLoc[i], "POSLIST") )
                 nSRSDimensionLocFlags |= SRSDIM_LOC_POSLIST;
@@ -1172,28 +1455,68 @@ char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
             pszNamespaceDecl = "http://www.opengis.net/gml/3.2";
         else if( bNamespaceDecl )
             pszNamespaceDecl = "http://www.opengis.net/gml";
-        if( !OGR2GML3GeometryAppend( (OGRGeometry *) hGeometry, NULL, &pszText,
-                                     &nLength, &nMaxLength, false, bLongSRS,
-                                     bLineStringAsCurve, pszGMLId, nSRSDimensionLocFlags, false,
-                                     pszNamespaceDecl ))
+
+        bool bCoordSwap = false;
+        const char* pszCoordSwap =
+            CSLFetchNameValue(papszOptions, "COORD_SWAP");
+        if( pszCoordSwap )
+        {
+            bCoordSwap = CPLTestBool(pszCoordSwap);
+        }
+        else
+        {
+            const OGRSpatialReference* poSRS =
+                poGeometry->getSpatialReference();
+            if( poSRS != NULL )
+            {
+                const char* pszTarget =
+                    poSRS->IsProjected() ? "PROJCS" : "GEOGCS";
+                const char* pszAuthName = poSRS->GetAuthorityName( pszTarget );
+                const char* pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
+                if( NULL != pszAuthName && NULL != pszAuthCode &&
+                    EQUAL( pszAuthName, "EPSG" ) &&
+                    eSRSNameFormat != SRSNAME_SHORT &&
+                    !(((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong() ||
+                    ((OGRSpatialReference*)poSRS)->
+                          EPSGTreatsAsNorthingEasting()))
+                {
+                    OGRSpatialReference oSRS;
+                    if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
+                    {
+                        if (oSRS.EPSGTreatsAsLatLong() ||
+                            oSRS.EPSGTreatsAsNorthingEasting())
+                            bCoordSwap = true;
+                    }
+                }
+            }
+        }
+
+        if( !OGR2GML3GeometryAppend( poGeometry, NULL, &pszText,
+                                     &nLength, &nMaxLength, false,
+                                     eSRSNameFormat,
+                                     bCoordSwap,
+                                     bLineStringAsCurve, pszGMLId,
+                                     nSRSDimensionLocFlags, false,
+                                     pszNamespaceDecl, NULL ))
         {
             CPLFree( pszText );
             return NULL;
         }
-        else
-            return pszText;
+
+        return pszText;
     }
 
     const char* pszNamespaceDecl = NULL;
     if( bNamespaceDecl )
         pszNamespaceDecl = "http://www.opengis.net/gml";
-    if( !OGR2GMLGeometryAppend( (OGRGeometry *) hGeometry, &pszText,
-                                &nLength, &nMaxLength, false,
-                                pszNamespaceDecl ))
+    if( !OGR2GMLGeometryAppend(
+            poGeometry, &pszText,
+            &nLength, &nMaxLength, false,
+            pszNamespaceDecl) )
     {
         CPLFree( pszText );
         return NULL;
     }
-    else
-        return pszText;
+
+    return pszText;
 }
diff --git a/ogr/ogr_api.cpp b/ogr/ogr_api.cpp
index 27e96a4..d9d0706 100644
--- a/ogr/ogr_api.cpp
+++ b/ogr/ogr_api.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_api.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API Functions that don't correspond one-to-one with C++
@@ -29,9 +28,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_geometry.h"
+#include "cpl_port.h"
 #include "ogr_api.h"
+
+#include <cstddef>
+
 #include "cpl_error.h"
+#include "ogr_geometry.h"
+
+CPL_CVSID("$Id: ogr_api.cpp 36963 2016-12-19 15:38:17Z rouault $");
 
 static bool bNonLinearGeometriesEnabled = true;
 
@@ -53,15 +58,22 @@ int OGR_G_GetPointCount( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetPointCount", 0 );
 
-    OGRwkbGeometryType eGType = wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType());
+    const OGRwkbGeometryType eGType =
+        wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryType());
     if( eGType == wkbPoint )
+    {
         return 1;
+    }
     else if( OGR_GT_IsCurve(eGType) )
-        return ((OGRCurve *) hGeom)->getNumPoints();
+    {
+        return reinterpret_cast<OGRCurve *>(hGeom)->getNumPoints();
+    }
     else
     {
-        // autotest/pymod/ogrtest.py calls this method on any geometry. So keep silent
-        //CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        // autotest/pymod/ogrtest.py calls this method on any geometry. So keep
+        // silent.
+        // CPLError(CE_Failure, CPLE_NotSupported,
+        //          "Incompatible geometry for operation");
         return 0;
     }
 }
@@ -85,18 +97,20 @@ void OGR_G_SetPointCount( OGRGeometryH hGeom, int nNewPointCount )
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_SetPointCount" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbLineString:
       case wkbCircularString:
       {
-        OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
-        poSC->setNumPoints( nNewPointCount );
-        break;
+          OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
+          poSC->setNumPoints( nNewPointCount );
+          break;
       }
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        break;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          break;
     }
 }
 
@@ -116,15 +130,19 @@ double OGR_G_GetX( OGRGeometryH hGeom, int i )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetX", 0 );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
-              return ((OGRPoint *) hGeom)->getX();
+          {
+              return reinterpret_cast<OGRPoint *>(hGeom)->getX();
+          }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
               return 0.0;
           }
       }
@@ -132,8 +150,8 @@ double OGR_G_GetX( OGRGeometryH hGeom, int i )
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
-          if (i < 0 || i >= poSC->getNumPoints())
+          OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
+          if( i < 0 || i >= poSC->getNumPoints() )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return 0.0;
@@ -142,8 +160,9 @@ double OGR_G_GetX( OGRGeometryH hGeom, int i )
       }
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        return 0.0;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          return 0.0;
     }
 }
 
@@ -163,15 +182,19 @@ double OGR_G_GetY( OGRGeometryH hGeom, int i )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetY", 0 );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
-              return ((OGRPoint *) hGeom)->getY();
+          {
+              return reinterpret_cast<OGRPoint *>(hGeom)->getY();
+          }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
               return 0.0;
           }
       }
@@ -179,8 +202,8 @@ double OGR_G_GetY( OGRGeometryH hGeom, int i )
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
-          if (i < 0 || i >= poSC->getNumPoints())
+          OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
+          if( i < 0 || i >= poSC->getNumPoints() )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return 0.0;
@@ -189,7 +212,8 @@ double OGR_G_GetY( OGRGeometryH hGeom, int i )
       }
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Incompatible geometry for operation");
         return 0.0;
     }
 }
@@ -210,15 +234,19 @@ double OGR_G_GetZ( OGRGeometryH hGeom, int i )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetZ", 0 );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
-              return ((OGRPoint *) hGeom)->getZ();
+          {
+              return reinterpret_cast<OGRPoint *>(hGeom)->getZ();
+          }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
               return 0.0;
           }
       }
@@ -226,8 +254,8 @@ double OGR_G_GetZ( OGRGeometryH hGeom, int i )
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
-          if (i < 0 || i >= poSC->getNumPoints())
+          OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
+          if( i < 0 || i >= poSC->getNumPoints() )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return 0.0;
@@ -236,7 +264,8 @@ double OGR_G_GetZ( OGRGeometryH hGeom, int i )
       }
 
       default:
-          CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
           return 0.0;
     }
 }
@@ -257,15 +286,19 @@ double OGR_G_GetM( OGRGeometryH hGeom, int i )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetM", 0 );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
-              return ((OGRPoint *) hGeom)->getM();
+          {
+              return reinterpret_cast<OGRPoint *>(hGeom)->getM();
+          }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
               return 0.0;
           }
       }
@@ -273,8 +306,8 @@ double OGR_G_GetM( OGRGeometryH hGeom, int i )
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
-          if (i < 0 || i >= poSC->getNumPoints())
+          OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
+          if( i < 0 || i >= poSC->getNumPoints() )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return 0.0;
@@ -283,7 +316,8 @@ double OGR_G_GetM( OGRGeometryH hGeom, int i )
       }
 
       default:
-          CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
           return 0.0;
     }
 }
@@ -298,14 +332,18 @@ double OGR_G_GetM( OGRGeometryH hGeom, int i )
  * This method copies all points into user arrays. The user provides the
  * stride between 2 consecutive elements of the array.
  *
- * On some CPU architectures, care must be taken so that the arrays are properly aligned.
+ * On some CPU architectures, care must be taken so that the arrays are properly
+ * aligned.
  *
  * @param hGeom handle to the geometry from which to get the coordinates.
- * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount) bytes, may be NULL.
+ * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount)
+ * bytes, may be NULL.
  * @param nXStride the number of bytes between 2 elements of pabyX.
- * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount) bytes, may be NULL.
+ * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount)
+ * bytes, may be NULL.
  * @param nYStride the number of bytes between 2 elements of pabyY.
- * @param pabyZ a buffer of at last size (sizeof(double) * nZStride * nPointCount) bytes, may be NULL.
+ * @param pabyZ a buffer of at last size (sizeof(double) * nZStride *
+ * nPointCount) bytes, may be NULL.
  * @param nZStride the number of bytes between 2 elements of pabyZ.
  *
  * @return the number of points
@@ -316,32 +354,35 @@ double OGR_G_GetM( OGRGeometryH hGeom, int i )
 int OGR_G_GetPoints( OGRGeometryH hGeom,
                      void* pabyX, int nXStride,
                      void* pabyY, int nYStride,
-                     void* pabyZ, int nZStride)
+                     void* pabyZ, int nZStride )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetPoints", 0 );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
-        if (pabyX) *((double*)pabyX) = ((OGRPoint *)hGeom)->getX();
-        if (pabyY) *((double*)pabyY) = ((OGRPoint *)hGeom)->getY();
-        if (pabyZ) *((double*)pabyZ) = ((OGRPoint *)hGeom)->getZ();
-        return 1;
+          OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+          if( pabyX ) *(static_cast<double *>(pabyX)) = poPoint->getX();
+          if( pabyY ) *(static_cast<double *>(pabyY)) = poPoint->getY();
+          if( pabyZ ) *(static_cast<double *>(pabyZ)) = poPoint->getZ();
+          return 1;
       }
       break;
 
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+          OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
           poSC->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride);
           return poSC->getNumPoints();
       }
       break;
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Incompatible geometry for operation");
         return 0;
         break;
     }
@@ -357,16 +398,21 @@ int OGR_G_GetPoints( OGRGeometryH hGeom,
  * This method copies all points into user arrays. The user provides the
  * stride between 2 consecutive elements of the array.
  *
- * On some CPU architectures, care must be taken so that the arrays are properly aligned.
+ * On some CPU architectures, care must be taken so that the arrays are properly
+ * aligned.
  *
  * @param hGeom handle to the geometry from which to get the coordinates.
- * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount) bytes, may be NULL.
+ * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount)
+ * bytes, may be NULL.
  * @param nXStride the number of bytes between 2 elements of pabyX.
- * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount) bytes, may be NULL.
+ * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount)
+ * bytes, may be NULL.
  * @param nYStride the number of bytes between 2 elements of pabyY.
- * @param pabyZ a buffer of at last size (sizeof(double) * nZStride * nPointCount) bytes, may be NULL.
+ * @param pabyZ a buffer of at last size (sizeof(double) * nZStride *
+ * nPointCount) bytes, may be NULL.
  * @param nZStride the number of bytes between 2 elements of pabyZ.
- * @param pabyM a buffer of at last size (sizeof(double) * nMStride * nPointCount) bytes, may be NULL.
+ * @param pabyM a buffer of at last size (sizeof(double) * nMStride *
+ * nPointCount) bytes, may be NULL.
  * @param nMStride the number of bytes between 2 elements of pabyM.
  *
  * @return the number of points
@@ -378,35 +424,39 @@ int OGR_G_GetPointsZM( OGRGeometryH hGeom,
                        void* pabyX, int nXStride,
                        void* pabyY, int nYStride,
                        void* pabyZ, int nZStride,
-                       void* pabyM, int nMStride)
+                       void* pabyM, int nMStride )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetPointsZM", 0 );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
-        if (pabyX) *((double*)pabyX) = ((OGRPoint *)hGeom)->getX();
-        if (pabyY) *((double*)pabyY) = ((OGRPoint *)hGeom)->getY();
-        if (pabyZ) *((double*)pabyZ) = ((OGRPoint *)hGeom)->getZ();
-        if (pabyM) *((double*)pabyM) = ((OGRPoint *)hGeom)->getM();
-        return 1;
+          OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+          if( pabyX ) *static_cast<double *>(pabyX) = poPoint->getX();
+          if( pabyY ) *static_cast<double *>(pabyY) = poPoint->getY();
+          if( pabyZ ) *static_cast<double *>(pabyZ) = poPoint->getZ();
+          if( pabyM ) *static_cast<double *>(pabyM) = poPoint->getM();
+          return 1;
       }
       break;
 
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
-          poSC->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride, pabyM, nMStride);
+          OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
+          poSC->getPoints(pabyX, nXStride, pabyY, nYStride, pabyZ, nZStride,
+                          pabyM, nMStride);
           return poSC->getNumPoints();
       }
       break;
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        return 0;
-        break;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          return 0;
+          break;
     }
 }
 
@@ -430,20 +480,23 @@ void OGR_G_GetPoint( OGRGeometryH hGeom, int i,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_GetPoint" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
           {
-              *pdfX = ((OGRPoint *)hGeom)->getX();
-              *pdfY = ((OGRPoint *)hGeom)->getY();
+              OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+              *pdfX = poPoint->getX();
+              *pdfY = poPoint->getY();
               if( pdfZ != NULL )
-                  *pdfZ = ((OGRPoint *)hGeom)->getZ();
+                  *pdfZ = poPoint->getZ();
           }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
           }
       }
       break;
@@ -451,26 +504,28 @@ void OGR_G_GetPoint( OGRGeometryH hGeom, int i,
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
-          if (i < 0 || i >= poSC->getNumPoints())
+          OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
+          if( i < 0 || i >= poSC->getNumPoints() )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
-              *pdfX = *pdfY = 0;
+              *pdfX = 0.0;
+              *pdfY = 0.0;
               if( pdfZ != NULL )
-                  *pdfZ = 0;
+                  *pdfZ = 0.0;
           }
           else
           {
             *pdfX = poSC->getX( i );
             *pdfY = poSC->getY( i );
             if( pdfZ != NULL )
-                *pdfZ =  poSC->getZ( i );
+                *pdfZ = poSC->getZ( i );
           }
       }
       break;
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Incompatible geometry for operation");
         break;
     }
 }
@@ -496,22 +551,25 @@ void OGR_G_GetPointZM( OGRGeometryH hGeom, int i,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_GetPointZM" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
           {
-              *pdfX = ((OGRPoint *)hGeom)->getX();
-              *pdfY = ((OGRPoint *)hGeom)->getY();
+              OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+              *pdfX = poPoint->getX();
+              *pdfY = poPoint->getY();
               if( pdfZ != NULL )
-                  *pdfZ = ((OGRPoint *)hGeom)->getZ();
+                  *pdfZ = poPoint->getZ();
               if( pdfM != NULL )
-                  *pdfM = ((OGRPoint *)hGeom)->getM();
+                  *pdfM = poPoint->getM();
           }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
           }
       }
       break;
@@ -519,31 +577,33 @@ void OGR_G_GetPointZM( OGRGeometryH hGeom, int i,
       case wkbLineString:
       case wkbCircularString:
       {
-          OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
-          if (i < 0 || i >= poSC->getNumPoints())
+          OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
+          if( i < 0 || i >= poSC->getNumPoints() )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
-              *pdfX = *pdfY = 0;
+              *pdfX = 0.0;
+              *pdfY = 0.0;
               if( pdfZ != NULL )
-                  *pdfZ = 0;
+                  *pdfZ = 0.0;
               if( pdfM != NULL )
-                  *pdfM = 0;
+                  *pdfM = 0.0;
           }
           else
           {
-            *pdfX = poSC->getX( i );
-            *pdfY = poSC->getY( i );
-            if( pdfZ != NULL )
-                *pdfZ =  poSC->getZ( i );
-            if( pdfM != NULL )
-                *pdfM =  poSC->getM( i );
+              *pdfX = poSC->getX( i );
+              *pdfY = poSC->getY( i );
+              if( pdfZ != NULL )
+                  *pdfZ = poSC->getZ( i );
+              if( pdfM != NULL )
+                  *pdfM = poSC->getM( i );
           }
       }
       break;
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        break;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          break;
     }
 }
 
@@ -562,7 +622,8 @@ void OGR_G_GetPointZM( OGRGeometryH hGeom, int i,
  * @param nXStride the number of bytes between 2 elements of pabyX.
  * @param pabyY list of Y coordinates (double values) of points being assigned.
  * @param nYStride the number of bytes between 2 elements of pabyY.
- * @param pabyZ list of Z coordinates (double values) of points being assigned (defaults to NULL for 2D objects).
+ * @param pabyZ list of Z coordinates (double values) of points being assigned
+ * (defaults to NULL for 2D objects).
  * @param nZStride the number of bytes between 2 elements of pabyZ.
  */
 
@@ -576,43 +637,55 @@ void CPL_DLL OGR_G_SetPoints( OGRGeometryH hGeom, int nPointsIn,
 
     if( pabyX == NULL || pabyY == NULL )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "pabyX == NULL || pabyY == NULL");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "pabyX == NULL || pabyY == NULL");
         return;
     }
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    double * const padfX = static_cast<double *>(pabyX);
+    double * const padfY = static_cast<double *>(pabyY);
+    double * const padfZ = static_cast<double *>(pabyZ);
+
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
-        ((OGRPoint *) hGeom)->setX( *( (double *)pabyX ) );
-        ((OGRPoint *) hGeom)->setY( *( (double *)pabyY ) );
-        if( pabyZ != NULL )
-            ((OGRPoint *) hGeom)->setZ(*( (double *)pabyZ ) );
-        break;
+          OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+          poPoint->setX( *padfX );
+          poPoint->setY( *padfY );
+          if( pabyZ != NULL )
+              poPoint->setZ(*( padfZ ) );
+          break;
       }
       case wkbLineString:
       case wkbCircularString:
       {
-        OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
+        OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
 
-        if( nXStride == (int)sizeof(double) &&
-            nYStride == (int)sizeof(double) &&
+        const int nSizeDouble = (int)sizeof(double);
+        if( nXStride == nSizeDouble &&
+            nYStride == nSizeDouble &&
             ((nZStride == 0 && pabyZ == NULL) ||
-             (nZStride == (int)sizeof(double) && pabyZ != NULL)) )
+             (nZStride == nSizeDouble && pabyZ != NULL)) )
         {
-          poSC->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyZ );
+            poSC->setPoints(nPointsIn, padfX, padfY, padfZ);
         }
         else
         {
           poSC->setNumPoints( nPointsIn );
 
-          for (int i = 0; i < nPointsIn; ++i)
+          // TODO(schwehr): Create pasX and pasY.
+          for( int i = 0; i < nPointsIn; ++i )
           {
-            double x = *(double*)((char*)pabyX + i * nXStride);
-            double y = *(double*)((char*)pabyY + i * nYStride);
+            const double x = *reinterpret_cast<double *>(
+                reinterpret_cast<char *>(pabyX) + i * nXStride);
+            const double y = *reinterpret_cast<double *>(
+                reinterpret_cast<char *>(pabyY) + i * nYStride);
             if( pabyZ )
             {
-                double z = *(double*)((char*)pabyZ + i * nZStride);
+                const double z = *reinterpret_cast<double *>(
+                    reinterpret_cast<char *>(pabyZ) + i * nZStride);
                 poSC->setPoint( i, x, y, z );
             }
             else
@@ -624,7 +697,8 @@ void CPL_DLL OGR_G_SetPoints( OGRGeometryH hGeom, int nPointsIn,
         break;
       }
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Incompatible geometry for operation");
         break;
     }
 }
@@ -644,9 +718,11 @@ void CPL_DLL OGR_G_SetPoints( OGRGeometryH hGeom, int nPointsIn,
  * @param nXStride the number of bytes between 2 elements of pabyX.
  * @param pabyY list of Y coordinates (double values) of points being assigned.
  * @param nYStride the number of bytes between 2 elements of pabyY.
- * @param pabyZ list of Z coordinates (double values) of points being assigned (if not NULL, upgrades the geometry to have Z coordinate).
+ * @param pabyZ list of Z coordinates (double values) of points being assigned
+ * (if not NULL, upgrades the geometry to have Z coordinate).
  * @param nZStride the number of bytes between 2 elements of pabyZ.
- * @param pabyM list of M coordinates (double values) of points being assigned (if not NULL, upgrades the geometry to have M coordinate).
+ * @param pabyM list of M coordinates (double values) of points being assigned
+ * (if not NULL, upgrades the geometry to have M coordinate).
  * @param nMStride the number of bytes between 2 elements of pabyM.
  */
 
@@ -661,93 +737,115 @@ void CPL_DLL OGR_G_SetPointsZM( OGRGeometryH hGeom, int nPointsIn,
 
     if( pabyX == NULL || pabyY == NULL )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "pabyX == NULL || pabyY == NULL");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "pabyX == NULL || pabyY == NULL");
         return;
     }
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    double * const padfX = static_cast<double *>(pabyX);
+    double * const padfY = static_cast<double *>(pabyY);
+    double * const padfZ = static_cast<double *>(pabyZ);
+    double * const padfM = static_cast<double *>(pabyM);
+
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
-        ((OGRPoint *) hGeom)->setX( *( (double *)pabyX ) );
-        ((OGRPoint *) hGeom)->setY( *( (double *)pabyY ) );
-        if (pabyZ)
-            ((OGRPoint *) hGeom)->setZ( *(double *)pabyZ );
-        if (pabyM)
-            ((OGRPoint *) hGeom)->setM( *(double *)pabyM );
-        break;
+          OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+          poPoint->setX(*padfX);
+          poPoint->setY(*padfY);
+          if( pabyZ )
+              poPoint->setZ(*padfZ);
+          if( pabyM )
+              poPoint->setM(*padfM);
+          break;
       }
       case wkbLineString:
       case wkbCircularString:
       {
-        OGRSimpleCurve* poSC = (OGRSimpleCurve *)hGeom;
-
-        if(  nXStride == (int)sizeof(double) &&
-             nYStride == (int)sizeof(double) &&
-             ((nZStride == 0 && pabyZ == NULL) ||
-              (nZStride == (int)sizeof(double) && pabyZ != NULL)) &&
-             ((nMStride == 0 && pabyM == NULL) ||
-              (nMStride == (int)sizeof(double) && pabyM != NULL)) )
+        OGRSimpleCurve* poSC = reinterpret_cast<OGRSimpleCurve *>(hGeom);
+
+        const int nSizeDouble = static_cast<int>(sizeof(double));
+        if( nXStride == nSizeDouble &&
+            nYStride == nSizeDouble &&
+            ((nZStride == 0 && padfZ == NULL) ||
+             (nZStride == nSizeDouble && padfZ != NULL)) &&
+            ((nMStride == 0 && padfM == NULL) ||
+             (nMStride == nSizeDouble && padfM != NULL)) )
         {
-            if (!pabyZ && !pabyM)
-                poSC->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY );
-            else if (pabyZ && !pabyM)
-                poSC->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyZ );
-            else if (!pabyZ && pabyM)
-                poSC->setPointsM( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyM );
+            if( !padfZ && !padfM )
+                poSC->setPoints( nPointsIn, padfX, padfY );
+            else if( pabyZ && !pabyM )
+                poSC->setPoints( nPointsIn, padfX, padfY, padfZ );
+            else if( !pabyZ && pabyM )
+                poSC->setPointsM( nPointsIn, padfX, padfY, padfM );
             else
-                poSC->setPoints( nPointsIn, (double *)pabyX, (double *)pabyY, (double *)pabyZ, (double *)pabyM );
+                poSC->setPoints( nPointsIn, padfX, padfY, padfZ, padfM );
         }
         else
         {
           poSC->setNumPoints( nPointsIn );
 
-          if (!pabyZ && !pabyM)
+          // TODO(schwehr): Create pasX and pasY.
+          if( !pabyZ && !pabyM )
           {
-              for (int i = 0; i < nPointsIn; ++i)
+              for( int i = 0; i < nPointsIn; ++i )
               {
-                  double x = *(double*)((char*)pabyX + i * nXStride);
-                  double y = *(double*)((char*)pabyY + i * nYStride);
+                  const double x = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyX) + i * nXStride);
+                  const double y = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyY) + i * nYStride);
                   poSC->setPoint( i, x, y );
               }
           }
-          else if (pabyZ && !pabyM)
+          else if( pabyZ && !pabyM )
           {
-              for (int i = 0; i < nPointsIn; ++i)
+              for( int i = 0; i < nPointsIn; ++i )
               {
-                  double x = *(double*)((char*)pabyX + i * nXStride);
-                  double y = *(double*)((char*)pabyY + i * nYStride);
-                  double z = *(double*)((char*)pabyZ + i * nZStride);
+                  const double x = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyX) + i * nXStride);
+                  const double y = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyY) + i * nYStride);
+                  const double z = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyZ) + i * nZStride);
                   poSC->setPoint( i, x, y, z );
               }
           }
-          else if (!pabyZ && pabyM)
+          else if( !pabyZ && pabyM )
           {
-              for (int i = 0; i < nPointsIn; ++i)
+              for( int i = 0; i < nPointsIn; ++i )
               {
-                  double x = *(double*)((char*)pabyX + i * nXStride);
-                  double y = *(double*)((char*)pabyY + i * nYStride);
-                  double m = *(double*)((char*)pabyM + i * nMStride);
+                  const double x = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyX) + i * nXStride);
+                  const double y = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyY) + i * nYStride);
+                  const double m = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyM) + i * nMStride);
                   poSC->setPointM( i, x, y, m );
               }
           }
           else
           {
-              for (int i = 0; i < nPointsIn; ++i)
+              for( int i = 0; i < nPointsIn; ++i )
               {
-                  double x = *(double*)((char*)pabyX + i * nXStride);
-                  double y = *(double*)((char*)pabyY + i * nYStride);
-                  double z = *(double*)((char*)pabyZ + i * nZStride);
-                  double m = *(double*)((char*)pabyM + i * nMStride);
+                  const double x = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyX) + i * nXStride);
+                  const double y = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyY) + i * nYStride);
+                  const double z = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyZ) + i * nZStride);
+                  const double m = *reinterpret_cast<double *>(
+                      reinterpret_cast<char *>(pabyM) + i * nMStride);
                   poSC->setPoint( i, x, y, z, m );
               }
           }
-
         }
         break;
       }
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Incompatible geometry for operation");
         break;
     }
 }
@@ -776,19 +874,22 @@ void OGR_G_SetPoint( OGRGeometryH hGeom, int i,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_SetPoint" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
           {
-              ((OGRPoint *) hGeom)->setX( dfX );
-              ((OGRPoint *) hGeom)->setY( dfY );
-              ((OGRPoint *) hGeom)->setZ( dfZ );
+              OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+              poPoint->setX(dfX);
+              poPoint->setY(dfY);
+              poPoint->setZ(dfZ);
           }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
           }
       }
       break;
@@ -796,17 +897,18 @@ void OGR_G_SetPoint( OGRGeometryH hGeom, int i,
       case wkbLineString:
       case wkbCircularString:
       {
-          if (i < 0)
+          if( i < 0 )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return;
           }
-          ((OGRSimpleCurve *) hGeom)->setPoint( i, dfX, dfY, dfZ );
+          reinterpret_cast<OGRSimpleCurve *>(hGeom)->setPoint(i, dfX, dfY, dfZ);
           break;
       }
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
         break;
     }
 }
@@ -834,18 +936,21 @@ void OGR_G_SetPoint_2D( OGRGeometryH hGeom, int i,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_SetPoint_2D" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
           {
-              ((OGRPoint *) hGeom)->setX( dfX );
-              ((OGRPoint *) hGeom)->setY( dfY );
+              OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+              poPoint->setX(dfX);
+              poPoint->setY(dfY);
           }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
           }
       }
       break;
@@ -853,17 +958,18 @@ void OGR_G_SetPoint_2D( OGRGeometryH hGeom, int i,
       case wkbLineString:
       case wkbCircularString:
       {
-          if (i < 0)
+          if( i < 0 )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return;
           }
-          ((OGRSimpleCurve *) hGeom)->setPoint( i, dfX, dfY );
+          reinterpret_cast<OGRSimpleCurve *>(hGeom)->setPoint(i, dfX, dfY);
           break;
       }
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
         break;
     }
 }
@@ -892,19 +998,22 @@ void OGR_G_SetPointM( OGRGeometryH hGeom, int i,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_SetPointM" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
           {
-              ((OGRPoint *) hGeom)->setX( dfX );
-              ((OGRPoint *) hGeom)->setY( dfY );
-              ((OGRPoint *) hGeom)->setM( dfM );
+              OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+              poPoint->setX(dfX);
+              poPoint->setY(dfY);
+              poPoint->setM(dfM);
           }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
           }
       }
       break;
@@ -912,18 +1021,20 @@ void OGR_G_SetPointM( OGRGeometryH hGeom, int i,
       case wkbLineString:
       case wkbCircularString:
       {
-          if (i < 0)
+          if( i < 0 )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return;
           }
-          ((OGRSimpleCurve *) hGeom)->setPointM( i, dfX, dfY, dfM );
+          reinterpret_cast<OGRSimpleCurve *>(hGeom)->
+              setPointM(i, dfX, dfY, dfM);
           break;
       }
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        break;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          break;
     }
 }
 
@@ -952,20 +1063,23 @@ void OGR_G_SetPointZM( OGRGeometryH hGeom, int i,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_SetPointZM" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
           if( i == 0 )
           {
-              ((OGRPoint *) hGeom)->setX( dfX );
-              ((OGRPoint *) hGeom)->setY( dfY );
-              ((OGRPoint *) hGeom)->setZ( dfZ );
-              ((OGRPoint *) hGeom)->setM( dfM );
+              OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+              poPoint->setX(dfX);
+              poPoint->setY(dfY);
+              poPoint->setZ(dfZ);
+              poPoint->setM(dfM);
           }
           else
           {
-              CPLError(CE_Failure, CPLE_NotSupported, "Only i == 0 is supported");
+              CPLError(CE_Failure, CPLE_NotSupported,
+                       "Only i == 0 is supported");
           }
       }
       break;
@@ -973,18 +1087,20 @@ void OGR_G_SetPointZM( OGRGeometryH hGeom, int i,
       case wkbLineString:
       case wkbCircularString:
       {
-          if (i < 0)
+          if( i < 0 )
           {
               CPLError(CE_Failure, CPLE_NotSupported, "Index out of bounds");
               return;
           }
-          ((OGRSimpleCurve *) hGeom)->setPoint( i, dfX, dfY, dfZ, dfM );
+          reinterpret_cast<OGRSimpleCurve *>(hGeom)->
+              setPoint(i, dfX, dfY, dfZ, dfM);
           break;
       }
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        break;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          break;
     }
 }
 
@@ -1009,24 +1125,27 @@ void OGR_G_AddPoint( OGRGeometryH hGeom,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_AddPoint" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
-          ((OGRPoint *) hGeom)->setX( dfX );
-          ((OGRPoint *) hGeom)->setY( dfY );
-          ((OGRPoint *) hGeom)->setZ( dfZ );
+          OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+          poPoint->setX(dfX);
+          poPoint->setY(dfY);
+          poPoint->setZ(dfZ);
       }
       break;
 
       case wkbLineString:
       case wkbCircularString:
-        ((OGRSimpleCurve *) hGeom)->addPoint( dfX, dfY, dfZ );
-        break;
+          reinterpret_cast<OGRSimpleCurve *>(hGeom)->addPoint(dfX, dfY, dfZ);
+          break;
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        break;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          break;
     }
 }
 
@@ -1050,23 +1169,26 @@ void OGR_G_AddPoint_2D( OGRGeometryH hGeom,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_AddPoint_2D" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
-          ((OGRPoint *) hGeom)->setX( dfX );
-          ((OGRPoint *) hGeom)->setY( dfY );
+          OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+          poPoint->setX(dfX);
+          poPoint->setY(dfY);
       }
       break;
 
       case wkbLineString:
       case wkbCircularString:
-        ((OGRSimpleCurve *) hGeom)->addPoint( dfX, dfY );
-        break;
+          reinterpret_cast<OGRSimpleCurve *>(hGeom)->addPoint(dfX, dfY);
+          break;
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        break;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          break;
     }
 }
 
@@ -1091,24 +1213,27 @@ void OGR_G_AddPointM( OGRGeometryH hGeom,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_AddPointM" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
-          ((OGRPoint *) hGeom)->setX( dfX );
-          ((OGRPoint *) hGeom)->setY( dfY );
-          ((OGRPoint *) hGeom)->setM( dfM );
+          OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+          poPoint->setX(dfX);
+          poPoint->setY(dfY);
+          poPoint->setM(dfM);
       }
       break;
 
       case wkbLineString:
       case wkbCircularString:
-        ((OGRSimpleCurve *) hGeom)->addPointM( dfX, dfY, dfM );
-        break;
+          reinterpret_cast<OGRSimpleCurve *>(hGeom)->addPointM(dfX, dfY, dfM);
+          break;
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        break;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          break;
     }
 }
 
@@ -1134,25 +1259,29 @@ void OGR_G_AddPointZM( OGRGeometryH hGeom,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_AddPointZM" );
 
-    switch( wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType()) )
+    switch( wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
       case wkbPoint:
       {
-          ((OGRPoint *) hGeom)->setX( dfX );
-          ((OGRPoint *) hGeom)->setY( dfY );
-          ((OGRPoint *) hGeom)->setZ( dfZ );
-          ((OGRPoint *) hGeom)->setM( dfM );
+          OGRPoint *poPoint = reinterpret_cast<OGRPoint *>(hGeom);
+          poPoint->setX( dfX );
+          poPoint->setY( dfY );
+          poPoint->setZ( dfZ );
+          poPoint->setM( dfM );
       }
       break;
 
       case wkbLineString:
       case wkbCircularString:
-          ((OGRSimpleCurve *) hGeom)->addPoint( dfX, dfY, dfZ, dfM );
-        break;
+          reinterpret_cast<OGRSimpleCurve *>(hGeom)->
+              addPoint(dfX, dfY, dfZ, dfM);
+          break;
 
       default:
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
-        break;
+          CPLError(CE_Failure, CPLE_NotSupported,
+                   "Incompatible geometry for operation");
+          break;
     }
 }
 
@@ -1160,13 +1289,15 @@ void OGR_G_AddPointZM( OGRGeometryH hGeom,
 /*                       OGR_G_GetGeometryCount()                       */
 /************************************************************************/
 /**
- * \brief Fetch the number of elements in a geometry or number of geometries in container.
+ * \brief Fetch the number of elements in a geometry or number of geometries in
+ * container.
  *
- * Only geometries of type wkbPolygon[25D], wkbMultiPoint[25D], wkbMultiLineString[25D],
- * wkbMultiPolygon[25D] or wkbGeometryCollection[25D] may return a valid value.
- * Other geometry types will silently return 0.
+ * Only geometries of type wkbPolygon[25D], wkbMultiPoint[25D],
+ * wkbMultiLineString[25D], wkbMultiPolygon[25D] or wkbGeometryCollection[25D]
+ * may return a valid value.  Other geometry types will silently return 0.
  *
- * For a polygon, the returned number is the number of rings (exterior ring + interior rings).
+ * For a polygon, the returned number is the number of rings (exterior ring +
+ * interior rings).
  *
  * @param hGeom single geometry or geometry container from which to get
  * the number of elements.
@@ -1178,22 +1309,37 @@ int OGR_G_GetGeometryCount( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetGeometryCount", 0 );
 
-    OGRwkbGeometryType eType = wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType());
+    const OGRwkbGeometryType eType =
+        wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryType());
     if( OGR_GT_IsSubClassOf(eType, wkbCurvePolygon) )
     {
-        if( ((OGRCurvePolygon *)hGeom)->getExteriorRingCurve() == NULL )
+        if( reinterpret_cast<OGRCurvePolygon *>(hGeom)->
+                getExteriorRingCurve() == NULL )
             return 0;
         else
-            return ((OGRCurvePolygon *)hGeom)->getNumInteriorRings() + 1;
+            return reinterpret_cast<OGRCurvePolygon *>(hGeom)->
+                getNumInteriorRings() + 1;
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbCompoundCurve) )
-        return ((OGRCompoundCurve *)hGeom)->getNumCurves();
+    {
+        return reinterpret_cast<OGRCompoundCurve *>(hGeom)->getNumCurves();
+    }
     else if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) )
-        return ((OGRGeometryCollection *)hGeom)->getNumGeometries();
+    {
+        return reinterpret_cast<OGRGeometryCollection *>(hGeom)->
+            getNumGeometries();
+    }
+    else if( OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface) )
+    {
+        return reinterpret_cast<OGRPolyhedralSurface *>(hGeom)->
+            getNumGeometries();
+    }
     else
     {
-        // autotest/pymod/ogrtest.py calls this method on any geometry. So keep silent
-        //CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        // autotest/pymod/ogrtest.py calls this method on any geometry. So keep
+        // silent.
+        // CPLError(CE_Failure, CPLE_NotSupported,
+        //          "Incompatible geometry for operation");
         return 0;
     }
 }
@@ -1231,23 +1377,40 @@ OGRGeometryH OGR_G_GetGeometryRef( OGRGeometryH hGeom, int iSubGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetGeometryRef", NULL );
 
-    OGRwkbGeometryType eType = wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType());
+    const OGRwkbGeometryType eType =
+        wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryType());
     if( OGR_GT_IsSubClassOf(eType, wkbCurvePolygon) )
     {
         if( iSubGeom == 0 )
-            return (OGRGeometryH)
-                ((OGRCurvePolygon *)hGeom)->getExteriorRingCurve();
+            return reinterpret_cast<OGRGeometryH>(
+                reinterpret_cast<OGRCurvePolygon *>(hGeom)->
+                    getExteriorRingCurve());
         else
-            return (OGRGeometryH)
-                ((OGRCurvePolygon *)hGeom)->getInteriorRingCurve(iSubGeom-1);
+            return reinterpret_cast<OGRGeometryH>(
+                reinterpret_cast<OGRCurvePolygon *>(hGeom)->
+                    getInteriorRingCurve(iSubGeom - 1));
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbCompoundCurve) )
-        return (OGRGeometryH) ((OGRCompoundCurve *)hGeom)->getCurve(iSubGeom);
+    {
+      return reinterpret_cast<OGRGeometryH>(
+          reinterpret_cast<OGRCompoundCurve *>(hGeom)->getCurve(iSubGeom));
+    }
     else if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) )
-        return (OGRGeometryH) ((OGRGeometryCollection *)hGeom)->getGeometryRef( iSubGeom );
+    {
+        return reinterpret_cast<OGRGeometryH>(
+            reinterpret_cast<OGRGeometryCollection *>(hGeom)->
+                getGeometryRef(iSubGeom));
+    }
+    else if( OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface) )
+    {
+        return reinterpret_cast<OGRGeometryH> (
+            reinterpret_cast<OGRPolyhedralSurface *>(hGeom)->
+                getGeometryRef(iSubGeom));
+    }
     else
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "Incompatible geometry for operation");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Incompatible geometry for operation");
         return NULL;
     }
 }
@@ -1282,26 +1445,38 @@ OGRGeometryH OGR_G_GetGeometryRef( OGRGeometryH hGeom, int iSubGeom )
 OGRErr OGR_G_AddGeometry( OGRGeometryH hGeom, OGRGeometryH hNewSubGeom )
 
 {
-    VALIDATE_POINTER1( hGeom, "OGR_G_AddGeometry", OGRERR_UNSUPPORTED_OPERATION );
-    VALIDATE_POINTER1( hNewSubGeom, "OGR_G_AddGeometry", OGRERR_UNSUPPORTED_OPERATION );
+    VALIDATE_POINTER1( hGeom, "OGR_G_AddGeometry",
+                       OGRERR_UNSUPPORTED_OPERATION );
+    VALIDATE_POINTER1( hNewSubGeom, "OGR_G_AddGeometry",
+                       OGRERR_UNSUPPORTED_OPERATION );
 
     OGRErr eErr = OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
 
-    OGRwkbGeometryType eType = wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType());
+    const OGRwkbGeometryType eType =
+        wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryType());
     if( OGR_GT_IsSubClassOf(eType, wkbCurvePolygon) )
     {
-        if( OGR_GT_IsCurve( wkbFlatten(((OGRGeometry *) hNewSubGeom)->getGeometryType()) ) )
-            eErr = ((OGRCurvePolygon *)hGeom)->addRing( (OGRCurve *) hNewSubGeom );
+        if( OGR_GT_IsCurve( wkbFlatten(reinterpret_cast<OGRGeometry *>(
+                hNewSubGeom)->getGeometryType()) ) )
+            eErr = reinterpret_cast<OGRCurvePolygon *>(hGeom)->
+                addRing(reinterpret_cast<OGRCurve *>(hNewSubGeom));
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbCompoundCurve) )
     {
-        if( OGR_GT_IsCurve( wkbFlatten(((OGRGeometry *) hNewSubGeom)->getGeometryType()) ) )
-            eErr = ((OGRCompoundCurve *)hGeom)->addCurve( (OGRCurve *) hNewSubGeom );
+        if( OGR_GT_IsCurve( wkbFlatten(reinterpret_cast<OGRGeometry *>(
+                hNewSubGeom)->getGeometryType()) ) )
+            eErr = reinterpret_cast<OGRCompoundCurve *>(hGeom)->
+                addCurve(reinterpret_cast<OGRCurve *>(hNewSubGeom));
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) )
     {
-        eErr = ((OGRGeometryCollection *)hGeom)->addGeometry(
-                                                (OGRGeometry *) hNewSubGeom );
+        eErr = reinterpret_cast<OGRGeometryCollection *>(hGeom)->
+            addGeometry(reinterpret_cast<OGRGeometry *>(hNewSubGeom));
+    }
+    else if( OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface) )
+    {
+        eErr = reinterpret_cast<OGRPolyhedralSurface *>(hGeom)->
+            addGeometry(reinterpret_cast<OGRGeometry *>(hNewSubGeom));
     }
 
     return eErr;
@@ -1338,30 +1513,43 @@ OGRErr OGR_G_AddGeometryDirectly( OGRGeometryH hGeom,
                                   OGRGeometryH hNewSubGeom )
 
 {
-    VALIDATE_POINTER1( hGeom, "OGR_G_AddGeometryDirectly", OGRERR_UNSUPPORTED_OPERATION );
-    VALIDATE_POINTER1( hNewSubGeom, "OGR_G_AddGeometryDirectly", OGRERR_UNSUPPORTED_OPERATION );
+    VALIDATE_POINTER1( hGeom, "OGR_G_AddGeometryDirectly",
+                       OGRERR_UNSUPPORTED_OPERATION );
+    VALIDATE_POINTER1( hNewSubGeom, "OGR_G_AddGeometryDirectly",
+                       OGRERR_UNSUPPORTED_OPERATION );
 
     OGRErr eErr = OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
 
-    OGRwkbGeometryType eType = wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType());
+    const OGRwkbGeometryType eType =
+        wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryType());
+
     if( OGR_GT_IsSubClassOf(eType, wkbCurvePolygon) )
     {
-        if( OGR_GT_IsCurve( wkbFlatten(((OGRGeometry *) hNewSubGeom)->getGeometryType()) ) )
-            eErr = ((OGRCurvePolygon *)hGeom)->addRingDirectly( (OGRCurve *) hNewSubGeom );
+        if( OGR_GT_IsCurve( wkbFlatten(reinterpret_cast<OGRGeometry *>(
+                hNewSubGeom)->getGeometryType()) ) )
+            eErr = reinterpret_cast<OGRCurvePolygon *>(hGeom)->
+                addRingDirectly(reinterpret_cast<OGRCurve *>(hNewSubGeom));
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbCompoundCurve) )
     {
-        if( OGR_GT_IsCurve( wkbFlatten(((OGRGeometry *) hNewSubGeom)->getGeometryType()) ) )
-            eErr = ((OGRCompoundCurve *)hGeom)->addCurveDirectly( (OGRCurve *) hNewSubGeom );
+        if( OGR_GT_IsCurve( wkbFlatten(reinterpret_cast<OGRGeometry *>(
+                hNewSubGeom)->getGeometryType()) ) )
+            eErr = reinterpret_cast<OGRCompoundCurve *>(hGeom)->
+              addCurveDirectly(reinterpret_cast<OGRCurve *>(hNewSubGeom));
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) )
     {
-        eErr = ((OGRGeometryCollection *)hGeom)->addGeometryDirectly(
-                                                (OGRGeometry *) hNewSubGeom );
+        eErr = reinterpret_cast<OGRGeometryCollection *>(hGeom)->
+            addGeometryDirectly(reinterpret_cast<OGRGeometry *>(hNewSubGeom));
+    }
+    else if( OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface) )
+    {
+        eErr = reinterpret_cast<OGRPolyhedralSurface *>(hGeom)->
+            addGeometryDirectly(reinterpret_cast<OGRGeometry *>(hNewSubGeom));
     }
 
     if( eErr != OGRERR_NONE )
-        delete (OGRGeometry*)hNewSubGeom;
+        delete reinterpret_cast<OGRGeometry *>(hNewSubGeom);
 
     return eErr;
 }
@@ -1398,7 +1586,8 @@ OGRErr OGR_G_RemoveGeometry( OGRGeometryH hGeom, int iGeom, int bDelete )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_RemoveGeometry", OGRERR_FAILURE );
 
-    OGRwkbGeometryType eType = wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType());
+    const OGRwkbGeometryType eType =
+        wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryType());
     if( OGR_GT_IsSubClassOf(eType, wkbCurvePolygon) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1407,7 +1596,13 @@ OGRErr OGR_G_RemoveGeometry( OGRGeometryH hGeom, int iGeom, int bDelete )
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) )
     {
-        return ((OGRGeometryCollection *)hGeom)->removeGeometry( iGeom,bDelete);
+        return reinterpret_cast<OGRGeometryCollection *>(hGeom)->
+            removeGeometry(iGeom, bDelete);
+    }
+    else if( OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface) )
+    {
+        return reinterpret_cast<OGRPolyhedralSurface *>(hGeom)->
+            removeGeometry(iGeom, bDelete);
     }
     else
     {
@@ -1438,17 +1633,19 @@ double OGR_G_Length( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetLength", 0 );
 
-    double dfLength;
+    double dfLength = 0.0;
 
-    OGRwkbGeometryType eType = wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType());
+    const OGRwkbGeometryType eType =
+        wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryType());
     if( OGR_GT_IsCurve(eType) )
     {
-        dfLength = ((OGRCurve *) hGeom)->get_Length();
+        dfLength = reinterpret_cast<OGRCurve *>(hGeom)->get_Length();
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbMultiCurve) ||
              eType == wkbGeometryCollection )
     {
-        dfLength = ((OGRGeometryCollection *) hGeom)->get_Length();
+        dfLength = reinterpret_cast<OGRGeometryCollection *>(hGeom)->
+            get_Length();
     }
     else
     {
@@ -1484,21 +1681,22 @@ double OGR_G_Area( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_Area", 0 );
 
-    double dfArea;
+    double dfArea = 0.0;
 
-    OGRwkbGeometryType eType = wkbFlatten(((OGRGeometry *) hGeom)->getGeometryType());
+    const OGRwkbGeometryType eType =
+        wkbFlatten(reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryType());
     if( OGR_GT_IsSurface(eType) )
     {
-        dfArea = ((OGRSurface *) hGeom)->get_Area();
+        dfArea = reinterpret_cast<OGRSurface *>(hGeom)->get_Area();
     }
     else if( OGR_GT_IsCurve(eType) )
     {
-        dfArea = ((OGRCurve *) hGeom)->get_Area();
+        dfArea = reinterpret_cast<OGRCurve *>(hGeom)->get_Area();
     }
     else if( OGR_GT_IsSubClassOf(eType, wkbMultiSurface) ||
              eType == wkbGeometryCollection )
     {
-        dfArea = ((OGRGeometryCollection *) hGeom)->get_Area();
+        dfArea = reinterpret_cast<OGRGeometryCollection *>(hGeom)->get_Area();
     }
     else
     {
@@ -1532,20 +1730,21 @@ double OGR_G_GetArea( OGRGeometryH hGeom )
  *
  * Returns if a geometry is or has CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
  * MULTICURVE or MULTISURFACE in it.
-*
+ *
  * If bLookForNonLinear is set to TRUE, it will be actually looked if the
- * geometry or its subgeometries are or contain a non-linear geometry in them. In which
- * case, if the method returns TRUE, it means that OGR_G_GetLinearGeometry() would
- * return an approximate version of the geometry. Otherwise, OGR_G_GetLinearGeometry()
- * would do a conversion, but with just converting container type, like
- * COMPOUNDCURVE -> LINESTRING, MULTICURVE -> MULTILINESTRING or MULTISURFACE -> MULTIPOLYGON,
- * resulting in a "loss-less" conversion.
+ * geometry or its subgeometries are or contain a non-linear geometry in
+ * them. In which case, if the method returns TRUE, it means that
+ * OGR_G_GetLinearGeometry() would return an approximate version of the
+ * geometry. Otherwise, OGR_G_GetLinearGeometry() would do a conversion, but
+ * with just converting container type, like COMPOUNDCURVE -> LINESTRING,
+ * MULTICURVE -> MULTILINESTRING or MULTISURFACE -> MULTIPOLYGON, resulting in a
+ * "loss-less" conversion.
  *
  * This function is the same as C++ method OGRGeometry::hasCurveGeometry().
  *
  * @param hGeom the geometry to operate on.
- * @param bLookForNonLinear set it to TRUE to check if the geometry is or contains
- * a CIRCULARSTRING.
+ * @param bLookForNonLinear set it to TRUE to check if the geometry is or
+ * contains a CIRCULARSTRING.
  * @return TRUE if this geometry is or has curve geometry.
  *
  * @since GDAL 2.0
@@ -1554,7 +1753,8 @@ double OGR_G_GetArea( OGRGeometryH hGeom )
 int OGR_G_HasCurveGeometry( OGRGeometryH hGeom, int bLookForNonLinear )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_HasCurveGeometry", FALSE );
-    return ((OGRGeometry *) hGeom)->hasCurveGeometry(bLookForNonLinear);
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        hasCurveGeometry(bLookForNonLinear);
 }
 
 /************************************************************************/
@@ -1580,7 +1780,7 @@ int OGR_G_HasCurveGeometry( OGRGeometryH hGeom, int bLookForNonLinear )
  * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
  * arc, zero to use the default setting.
  * @param papszOptions options as a null-terminated list of strings or NULL.
- *                     See OGRGeometryFactory::curveToLineString() for valid options.
+ * See OGRGeometryFactory::curveToLineString() for valid options.
  *
  * @return a new geometry.
  *
@@ -1588,12 +1788,14 @@ int OGR_G_HasCurveGeometry( OGRGeometryH hGeom, int bLookForNonLinear )
  */
 
 OGRGeometryH CPL_DLL OGR_G_GetLinearGeometry( OGRGeometryH hGeom,
-                                                double dfMaxAngleStepSizeDegrees,
-                                                char** papszOptions )
+                                              double dfMaxAngleStepSizeDegrees,
+                                              char** papszOptions )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetLinearGeometry", NULL );
-    return (OGRGeometryH) ((OGRGeometry *) hGeom)->getLinearGeometry(dfMaxAngleStepSizeDegrees,
-                                                                       (const char* const*)papszOptions );
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hGeom)->
+            getLinearGeometry(dfMaxAngleStepSizeDegrees,
+                              papszOptions ));
 }
 
 /************************************************************************/
@@ -1603,8 +1805,9 @@ OGRGeometryH CPL_DLL OGR_G_GetLinearGeometry( OGRGeometryH hGeom,
 /**
  * \brief Return curve version of this geometry.
  *
- * Returns a geometry that has possibly CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
- * MULTICURVE or MULTISURFACE in it, by de-approximating linear into curve geometries.
+ * Returns a geometry that has possibly CIRCULARSTRING, COMPOUNDCURVE,
+ * CURVEPOLYGON, MULTICURVE or MULTISURFACE in it, by de-approximating linear
+ * into curve geometries.
  *
  * If the geometry has no curve portion, the returned geometry will be a clone
  * of it.
@@ -1628,7 +1831,10 @@ OGRGeometryH CPL_DLL OGR_G_GetCurveGeometry( OGRGeometryH hGeom,
                                              char** papszOptions )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetCurveGeometry", NULL );
-    return (OGRGeometryH) ((OGRGeometry *) hGeom)->getCurveGeometry((const char* const*)papszOptions);
+
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hGeom)->
+            getCurveGeometry(papszOptions));
 }
 
 /************************************************************************/
@@ -1654,16 +1860,15 @@ OGRGeometryH OGR_G_Value( OGRGeometryH hGeom, double dfDistance )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_Value", NULL );
 
-    if( OGR_GT_IsCurve(((OGRGeometry *) hGeom)->getGeometryType()) )
+    if( OGR_GT_IsCurve(reinterpret_cast<OGRGeometry *>(hGeom)->
+                           getGeometryType()) )
     {
         OGRPoint* p = new OGRPoint();
-        ((OGRCurve *) hGeom)->Value(dfDistance, p);
-        return (OGRGeometryH)p;
-    }
-    else
-    {
-        return NULL;
+        reinterpret_cast<OGRCurve *>(hGeom)->Value(dfDistance, p);
+        return reinterpret_cast<OGRGeometryH>(p);
     }
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -1671,15 +1876,17 @@ OGRGeometryH OGR_G_Value( OGRGeometryH hGeom, double dfDistance )
 /************************************************************************/
 
 /**
- * \brief Set flag to enable/disable returning non-linear geometries in the C API.
- *
- * This flag has only an effect on the OGR_F_GetGeometryRef(), OGR_F_GetGeomFieldRef(),
- * OGR_L_GetGeomType(), OGR_GFld_GetType() and OGR_FD_GetGeomType() C API, and
- * corresponding methods in the SWIG bindings. It is meant as making it simple
- * for applications using the OGR C API not to have to deal with non-linear geometries,
- * even if such geometries might be returned by drivers. In which case, they
- * will be transformed into their closest linear geometry, by doing linear
- * approximation, with OGR_G_ForceTo().
+ * \brief Set flag to enable/disable returning non-linear geometries in the C
+ * API.
+ *
+ * This flag has only an effect on the OGR_F_GetGeometryRef(),
+ * OGR_F_GetGeomFieldRef(), OGR_L_GetGeomType(), OGR_GFld_GetType() and
+ * OGR_FD_GetGeomType() C API, and corresponding methods in the SWIG
+ * bindings. It is meant as making it simple for applications using the OGR C
+ * API not to have to deal with non-linear geometries, even if such geometries
+ * might be returned by drivers. In which case, they will be transformed into
+ * their closest linear geometry, by doing linear approximation, with
+ * OGR_G_ForceTo().
  *
  * Libraries should generally *not* use that method, since that could interfere
  * with other libraries or applications.
@@ -1687,16 +1894,17 @@ OGRGeometryH OGR_G_Value( OGRGeometryH hGeom, double dfDistance )
  * Note that it *does* not affect the behaviour of the C++ API.
  *
  * @param bFlag TRUE if non-linear geometries might be returned (default value).
- *              FALSE to ask for non-linear geometries to be approximated as linear geometries.
+ *              FALSE to ask for non-linear geometries to be approximated as
+ *              linear geometries.
  *
  * @return a point or NULL.
  *
  * @since GDAL 2.0
  */
 
-void OGRSetNonLinearGeometriesEnabledFlag(int bFlag)
+void OGRSetNonLinearGeometriesEnabledFlag( int bFlag )
 {
-    bNonLinearGeometriesEnabled = (bFlag != FALSE);
+    bNonLinearGeometriesEnabled = bFlag != FALSE;
 }
 
 /************************************************************************/
@@ -1704,14 +1912,17 @@ void OGRSetNonLinearGeometriesEnabledFlag(int bFlag)
 /************************************************************************/
 
 /**
- * \brief Get flag to enable/disable returning non-linear geometries in the C API.
+ * \brief Get flag to enable/disable returning non-linear geometries in the C
+ * API.
  *
- * return TRUE if non-linear geometries might be returned (default value is TRUE)
+ * return TRUE if non-linear geometries might be returned (default value is
+ * TRUE).
  *
  * @since GDAL 2.0
  * @see OGRSetNonLinearGeometriesEnabledFlag()
  */
-int OGRGetNonLinearGeometriesEnabledFlag(void)
+
+int OGRGetNonLinearGeometriesEnabledFlag( void )
 {
     return bNonLinearGeometriesEnabled;
 }
diff --git a/ogr/ogr_api.h b/ogr/ogr_api.h
index cd3704e..1627ef0 100644
--- a/ogr/ogr_api.h
+++ b/ogr/ogr_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_api.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogr_api.h 37371 2017-02-13 11:41:59Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API for OGR Geometry, Feature, Layers, DataSource and drivers.
@@ -52,17 +52,22 @@ CPL_C_START
 #ifdef DEBUG
 typedef struct OGRGeometryHS *OGRGeometryH;
 #else
+/** Opaque type for a geometyr */
 typedef void *OGRGeometryH;
 #endif
 
 #ifndef DEFINED_OGRSpatialReferenceH
+/*! @cond Doxygen_Suppress */
 #define DEFINED_OGRSpatialReferenceH
+/*! @endcond */
 
 #ifdef DEBUG
 typedef struct OGRSpatialReferenceHS *OGRSpatialReferenceH;
 typedef struct OGRCoordinateTransformationHS *OGRCoordinateTransformationH;
 #else
+/** Opaque type for a spatial reference system */
 typedef void *OGRSpatialReferenceH;
+/** Opaque type for a coordinate transformation object */
 typedef void *OGRCoordinateTransformationH;
 #endif
 
@@ -132,6 +137,7 @@ char   CPL_DLL *OGR_G_ExportToKML( OGRGeometryH, const char* pszAltitudeMode ) C
 
 char   CPL_DLL *OGR_G_ExportToJson( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 char   CPL_DLL *OGR_G_ExportToJsonEx( OGRGeometryH, char** papszOptions ) CPL_WARN_UNUSED_RESULT;
+/** Create a OGR geometry from a GeoJSON geometry object */
 OGRGeometryH CPL_DLL OGR_G_CreateGeometryFromJson( const char* ) CPL_WARN_UNUSED_RESULT;
 
 void   CPL_DLL OGR_G_AssignSpatialReference( OGRGeometryH,
@@ -169,6 +175,7 @@ OGRGeometryH CPL_DLL OGR_G_PointOnSurface( OGRGeometryH ) CPL_WARN_UNUSED_RESULT
 OGRGeometryH CPL_DLL OGR_G_Difference( OGRGeometryH, OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 OGRGeometryH CPL_DLL OGR_G_SymDifference( OGRGeometryH, OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 double CPL_DLL OGR_G_Distance( OGRGeometryH, OGRGeometryH );
+double CPL_DLL OGR_G_Distance3D( OGRGeometryH, OGRGeometryH );
 double CPL_DLL OGR_G_Length( OGRGeometryH );
 double CPL_DLL OGR_G_Area( OGRGeometryH );
 int    CPL_DLL OGR_G_Centroid( OGRGeometryH, OGRGeometryH );
@@ -183,12 +190,14 @@ int    CPL_DLL OGR_G_IsRing( OGRGeometryH );
 
 OGRGeometryH CPL_DLL OGR_G_Polygonize( OGRGeometryH ) CPL_WARN_UNUSED_RESULT;
 
+/*! @cond Doxygen_Suppress */
 /* backward compatibility (non-standard methods) */
 int    CPL_DLL OGR_G_Intersect( OGRGeometryH, OGRGeometryH ) CPL_WARN_DEPRECATED("Non standard method. Use OGR_G_Intersects() instead");
 int    CPL_DLL OGR_G_Equal( OGRGeometryH, OGRGeometryH ) CPL_WARN_DEPRECATED("Non standard method. Use OGR_G_Equals() instead");
 OGRGeometryH CPL_DLL OGR_G_SymmetricDifference( OGRGeometryH, OGRGeometryH ) CPL_WARN_DEPRECATED("Non standard method. Use OGR_G_SymDifference() instead");
 double CPL_DLL OGR_G_GetArea( OGRGeometryH ) CPL_WARN_DEPRECATED("Non standard method. Use OGR_G_Area() instead");
 OGRGeometryH CPL_DLL OGR_G_GetBoundary( OGRGeometryH ) CPL_WARN_DEPRECATED("Non standard method. Use OGR_G_Boundary() instead");
+/*! @endcond */
 
 /* Methods for getting/setting vertices in points, line strings and rings */
 int    CPL_DLL OGR_G_GetPointCount( OGRGeometryH );
@@ -247,16 +256,19 @@ OGRGeometryH CPL_DLL OGR_G_GetLinearGeometry( OGRGeometryH hGeom,
 OGRGeometryH CPL_DLL OGR_G_GetCurveGeometry( OGRGeometryH hGeom,
                                              char** papszOptions ) CPL_WARN_UNUSED_RESULT;
 
-OGRGeometryH CPL_DLL OGRBuildPolygonFromEdges( OGRGeometryH hLinesAsCollection,
-                                       int bBestEffort,
-                                       int bAutoClose,
-                                       double dfTolerance,
-                                       OGRErr * peErr ) CPL_WARN_UNUSED_RESULT;
+OGRGeometryH CPL_DLL
+OGRBuildPolygonFromEdges( OGRGeometryH hLinesAsCollection,
+                          int bBestEffort,
+                          int bAutoClose,
+                          double dfTolerance,
+                          OGRErr * peErr ) CPL_WARN_UNUSED_RESULT;
 
+/*! @cond Doxygen_Suppress */
 OGRErr CPL_DLL OGRSetGenerate_DB2_V72_BYTE_ORDER(
     int bGenerate_DB2_V72_BYTE_ORDER );
 
 int CPL_DLL OGRGetGenerate_DB2_V72_BYTE_ORDER(void);
+/*! @endcond */
 
 void CPL_DLL OGRSetNonLinearGeometriesEnabledFlag(int bFlag);
 int CPL_DLL OGRGetNonLinearGeometriesEnabledFlag(void);
@@ -271,11 +283,16 @@ typedef struct OGRFeatureDefnHS *OGRFeatureDefnH;
 typedef struct OGRFeatureHS     *OGRFeatureH;
 typedef struct OGRStyleTableHS *OGRStyleTableH;
 #else
+/** Opaque type for a field definition (OGRFieldDefn) */
 typedef void *OGRFieldDefnH;
+/** Opaque type for a feature definition (OGRFeatureDefn) */
 typedef void *OGRFeatureDefnH;
+/** Opaque type for a feature (OGRFeature) */
 typedef void *OGRFeatureH;
+/** Opaque type for a style table (OGRStyleTable) */
 typedef void *OGRStyleTableH;
 #endif
+/** Opaque type for a geometry field definition (OGRGeomFieldDefn) */
 typedef struct OGRGeomFieldDefnHS *OGRGeomFieldDefnH;
 
 /* OGRFieldDefn */
@@ -384,8 +401,18 @@ int    CPL_DLL OGR_F_GetFieldIndex( OGRFeatureH, const char * );
 
 int    CPL_DLL OGR_F_IsFieldSet( OGRFeatureH, int );
 void   CPL_DLL OGR_F_UnsetField( OGRFeatureH, int );
+
+int    CPL_DLL OGR_F_IsFieldNull( OGRFeatureH, int );
+int    CPL_DLL OGR_F_IsFieldSetAndNotNull( OGRFeatureH, int );
+void   CPL_DLL OGR_F_SetFieldNull( OGRFeatureH, int );
+
 OGRField CPL_DLL *OGR_F_GetRawFieldRef( OGRFeatureH, int );
 
+int    CPL_DLL OGR_RawField_IsUnset( const OGRField* );
+int    CPL_DLL OGR_RawField_IsNull( const OGRField* );
+void   CPL_DLL OGR_RawField_SetUnset( OGRField* );
+void   CPL_DLL OGR_RawField_SetNull( OGRField* );
+
 int    CPL_DLL OGR_F_GetFieldAsInteger( OGRFeatureH, int );
 GIntBig CPL_DLL OGR_F_GetFieldAsInteger64( OGRFeatureH, int );
 double CPL_DLL OGR_F_GetFieldAsDouble( OGRFeatureH, int );
@@ -440,8 +467,11 @@ OGRErr CPL_DLL OGR_F_SetFromWithMap( OGRFeatureH, OGRFeatureH, int , int * );
 const char CPL_DLL *OGR_F_GetStyleString( OGRFeatureH );
 void   CPL_DLL OGR_F_SetStyleString( OGRFeatureH, const char * );
 void   CPL_DLL OGR_F_SetStyleStringDirectly( OGRFeatureH, char * );
+/** Return style table */
 OGRStyleTableH CPL_DLL OGR_F_GetStyleTable( OGRFeatureH );
+/** Set style table and take ownership */
 void   CPL_DLL OGR_F_SetStyleTableDirectly( OGRFeatureH, OGRStyleTableH );
+/** Set style table */
 void   CPL_DLL OGR_F_SetStyleTable( OGRFeatureH, OGRStyleTableH );
 
 const char CPL_DLL *OGR_F_GetNativeData( OGRFeatureH );
@@ -463,8 +493,11 @@ typedef struct OGRLayerHS      *OGRLayerH;
 typedef struct OGRDataSourceHS *OGRDataSourceH;
 typedef struct OGRDriverHS     *OGRSFDriverH;
 #else
+/** Opaque type for a layer (OGRLayer) */
 typedef void *OGRLayerH;
+/** Opaque type for a OGR datasource (OGRDataSource) */
 typedef void *OGRDataSourceH;
+/** Opaque type for a OGR driver (OGRSFDriver) */
 typedef void *OGRSFDriverH;
 #endif
 
@@ -507,15 +540,22 @@ OGRErr CPL_DLL OGR_L_AlterFieldDefn( OGRLayerH, int iField, OGRFieldDefnH hNewFi
 OGRErr CPL_DLL OGR_L_StartTransaction( OGRLayerH )  CPL_WARN_UNUSED_RESULT;
 OGRErr CPL_DLL OGR_L_CommitTransaction( OGRLayerH )  CPL_WARN_UNUSED_RESULT;
 OGRErr CPL_DLL OGR_L_RollbackTransaction( OGRLayerH );
+/*! @cond Doxygen_Suppress */
 int    CPL_DLL OGR_L_Reference( OGRLayerH );
 int    CPL_DLL OGR_L_Dereference( OGRLayerH );
 int    CPL_DLL OGR_L_GetRefCount( OGRLayerH );
+/*! @endcond */
 OGRErr CPL_DLL OGR_L_SyncToDisk( OGRLayerH );
+/*! @cond Doxygen_Suppress */
 GIntBig CPL_DLL OGR_L_GetFeaturesRead( OGRLayerH );
+/*! @endcond */
 const char CPL_DLL *OGR_L_GetFIDColumn( OGRLayerH );
 const char CPL_DLL *OGR_L_GetGeometryColumn( OGRLayerH );
+/** Get style table */
 OGRStyleTableH CPL_DLL OGR_L_GetStyleTable( OGRLayerH );
+/** Set style table (and take ownership) */
 void   CPL_DLL OGR_L_SetStyleTableDirectly( OGRLayerH, OGRStyleTableH );
+/** Set style table */
 void   CPL_DLL OGR_L_SetStyleTable( OGRLayerH, OGRStyleTableH );
 OGRErr CPL_DLL OGR_L_SetIgnoredFields( OGRLayerH, const char** );
 OGRErr CPL_DLL OGR_L_Intersection( OGRLayerH, OGRLayerH, OGRLayerH, char**, GDALProgressFunc, void * );
@@ -544,13 +584,19 @@ int    CPL_DLL OGR_DS_TestCapability( OGRDataSourceH, const char * );
 OGRLayerH CPL_DLL OGR_DS_ExecuteSQL( OGRDataSourceH, const char *,
                                      OGRGeometryH, const char * );
 void   CPL_DLL OGR_DS_ReleaseResultSet( OGRDataSourceH, OGRLayerH );
+/*! @cond Doxygen_Suppress */
 int    CPL_DLL OGR_DS_Reference( OGRDataSourceH );
 int    CPL_DLL OGR_DS_Dereference( OGRDataSourceH );
 int    CPL_DLL OGR_DS_GetRefCount( OGRDataSourceH );
 int    CPL_DLL OGR_DS_GetSummaryRefCount( OGRDataSourceH );
+/*! @endcond */
+/** Flush pending changes to disk. See GDALDataset::FlushCache() */
 OGRErr CPL_DLL OGR_DS_SyncToDisk( OGRDataSourceH );
+/** Get style table */
 OGRStyleTableH CPL_DLL OGR_DS_GetStyleTable( OGRDataSourceH );
+/** Set style table (and take ownership) */
 void   CPL_DLL OGR_DS_SetStyleTableDirectly( OGRDataSourceH, OGRStyleTableH );
+/** Set style table */
 void   CPL_DLL OGR_DS_SetStyleTable( OGRDataSourceH, OGRStyleTableH );
 
 /* OGRSFDriver */
@@ -569,17 +615,22 @@ OGRErr CPL_DLL OGR_Dr_DeleteDataSource( OGRSFDriverH, const char * );
 OGRDataSourceH CPL_DLL OGROpen( const char *, int, OGRSFDriverH * ) CPL_WARN_UNUSED_RESULT;
 OGRDataSourceH CPL_DLL OGROpenShared( const char *, int, OGRSFDriverH * ) CPL_WARN_UNUSED_RESULT;
 OGRErr  CPL_DLL OGRReleaseDataSource( OGRDataSourceH );
+/*! @cond Doxygen_Suppress */
 void    CPL_DLL OGRRegisterDriver( OGRSFDriverH );
 void    CPL_DLL OGRDeregisterDriver( OGRSFDriverH );
+/*! @endcond */
 int     CPL_DLL OGRGetDriverCount(void);
 OGRSFDriverH CPL_DLL OGRGetDriver( int );
 OGRSFDriverH CPL_DLL OGRGetDriverByName( const char * );
+/*! @cond Doxygen_Suppress */
 int     CPL_DLL OGRGetOpenDSCount(void);
 OGRDataSourceH CPL_DLL OGRGetOpenDS( int iDS );
-
+/*! @endcond */
 
 /* note: this is also declared in ogrsf_frmts.h */
 void CPL_DLL OGRRegisterAll(void);
+/** Clean-up all drivers (including raster ones starting with GDAL 2.0.
+ * See GDALDestroyDriverManager() */
 void CPL_DLL OGRCleanupAll(void);
 
 /* -------------------------------------------------------------------- */
@@ -590,7 +641,9 @@ void CPL_DLL OGRCleanupAll(void);
 typedef struct OGRStyleMgrHS *OGRStyleMgrH;
 typedef struct OGRStyleToolHS *OGRStyleToolH;
 #else
+/** Style manager opaque type */
 typedef void *OGRStyleMgrH;
+/** Style tool opaque type */
 typedef void *OGRStyleToolH;
 #endif
 
diff --git a/ogr/ogr_apitut.dox b/ogr/ogr_apitut.dox
index ed14e21..68cf85c 100644
--- a/ogr/ogr_apitut.dox
+++ b/ogr/ogr_apitut.dox
@@ -9,13 +9,13 @@ It also includes code snippets for the corresponding functions in C and Python.
 
 \section ogr_apitut_read Reading From OGR
 
-For purposes of demonstrating reading with OGR, we will construct a small 
+For purposes of demonstrating reading with OGR, we will construct a small
 utility for dumping point layers from an OGR data source to stdout in
-comma-delimited format. 
+comma-delimited format.
 
 Initially it is necessary to register all the format drivers that are desired.
 This is normally accomplished by calling GDALAllRegister() which registers
-all format drivers built into GDAL/OGR.  
+all format drivers built into GDAL/OGR.
 
 In C++ :
 \code
@@ -37,14 +37,14 @@ int main()
     GDALAllRegister();
 \endcode
 
-Next we need to open the input OGR datasource.  Datasources can be files, 
+Next we need to open the input OGR datasource.  Datasources can be files,
 RDBMSes, directories full of files, or even remote web services depending on
 the driver being used.  However, the datasource name is always a single
 string.  In this case we are hardcoded to open a particular shapefile.
-The second argument (GDAL_OF_VECTOR) tells the OGROpen() method 
+The second argument (GDAL_OF_VECTOR) tells the OGROpen() method
 that we want a vector driver to be use and that don't require update access.
 On failure NULL is returned, and
-we report an error. 
+we report an error.
 
 In C++ :
 \code
@@ -70,10 +70,10 @@ In C :
     }
 \endcode
 
-A GDALDataset can potentially have many layers associated with it.  The 
+A GDALDataset can potentially have many layers associated with it.  The
 number of layers available can be queried with GDALDataset::GetLayerCount()
-and individual layers fetched by index using GDALDataset::GetLayer().  
-However, we will just fetch the layer by name. 
+and individual layers fetched by index using GDALDataset::GetLayer().
+However, we will just fetch the layer by name.
 
 In C++ :
 \code
@@ -89,14 +89,14 @@ In C :
     hLayer = GDALDatasetGetLayerByName( hDS, "point" );
 \endcode
 
-Now we want to start reading features from the layer.  Before we start we 
+Now we want to start reading features from the layer.  Before we start we
 could assign an attribute or spatial filter to the layer to restrict the set
 of feature we get back, but for now we are interested in getting all features.
 
-While it isn't strictly necessary in this 
+While it isn't strictly necessary in this
 circumstance since we are starting fresh with the layer, it is often wise
 to call OGRLayer::ResetReading() to ensure we are starting at the beginning of
-the layer.  We iterate through all the features in the layer using 
+the layer.  We iterate through all the features in the layer using
 OGRLayer::GetNextFeature().  It will return NULL when we run out of features.
 
 In C++ :
@@ -120,7 +120,7 @@ In C :
 In order to dump all the attribute fields of the feature, it is helpful
 to get the OGRFeatureDefn.  This is an object, associated with the layer,
 containing the definitions of all the fields.  We loop over all the fields,
-and fetch and report the attributes based on their type.  
+and fetch and report the attributes based on their type.
 
 In C++ :
 \code
@@ -167,22 +167,22 @@ In C :
 \endcode
 
 There are a few more field types than those explicitly handled above, but
-a reasonable representation of them can be fetched with the 
+a reasonable representation of them can be fetched with the
 OGRFeature::GetFieldAsString() method.  In fact we could shorten the above
-by using OGRFeature::GetFieldAsString() for all the types. 
+by using OGRFeature::GetFieldAsString() for all the types.
 
 Next we want to extract the geometry from the feature, and write out the point
 geometry x and y.   Geometries are returned as a generic OGRGeometry pointer.
 We then determine the specific geometry type, and if it is a point, we
 cast it to point and operate on it.  If it is something else we write
-placeholders.  
+placeholders.
 
 In C++ :
 \code
     OGRGeometry *poGeometry;
 
     poGeometry = poFeature->GetGeometryRef();
-    if( poGeometry != NULL 
+    if( poGeometry != NULL
             && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
     {
         OGRPoint *poPoint = (OGRPoint *) poGeometry;
@@ -200,7 +200,7 @@ In C :
     OGRGeometryH hGeometry;
 
     hGeometry = OGR_F_GetGeometryRef(hFeature);
-    if( hGeometry != NULL 
+    if( hGeometry != NULL
             && wkbFlatten(OGR_G_GetGeometryType(hGeometry)) == wkbPoint )
     {
         printf( "%.3f,%3.f\n", OGR_G_GetX(hGeometry, 0), OGR_G_GetY(hGeometry, 0) );
@@ -211,11 +211,11 @@ In C :
     }
 \endcode
 
-The wkbFlatten() macro is used above to convert the type for a wkbPoint25D 
-(a point with a z coordinate) into the base 2D geometry type code (wkbPoint). 
+The wkbFlatten() macro is used above to convert the type for a wkbPoint25D
+(a point with a z coordinate) into the base 2D geometry type code (wkbPoint).
 For each 2D geometry type there is a corresponding 2.5D type code.  The 2D
 and 2.5D geometry cases are handled by the same C++ class, so our code will
-handle 2D or 3D cases properly.  
+handle 2D or 3D cases properly.
 
 Starting with OGR 1.11,
 <a href="http://trac.osgeo.org/gdal/wiki/rfc41_multiple_geometry_fields">
@@ -231,7 +231,7 @@ In C++ :
     for(iGeomField = 0; iGeomField < nGeomFieldCount; iGeomField ++ )
     {
         poGeometry = poFeature->GetGeomFieldRef(iGeomField);
-        if( poGeometry != NULL 
+        if( poGeometry != NULL
                 && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
         {
             OGRPoint *poPoint = (OGRPoint *) poGeometry;
@@ -255,7 +255,7 @@ In C :
     for(iGeomField = 0; iGeomField < nGeomFieldCount; iGeomField ++ )
     {
         hGeometry = OGR_F_GetGeomFieldRef(hFeature, iGeomField);
-        if( hGeometry != NULL 
+        if( hGeometry != NULL
                 && wkbFlatten(OGR_G_GetGeometryType(hGeometry)) == wkbPoint )
         {
             printf( "%.3f,%3.f\n", OGR_G_GetX(hGeometry, 0),
@@ -281,13 +281,13 @@ In Python:
 
 Note that OGRFeature::GetGeometryRef() and OGRFeature::GetGeomFieldRef()
 return a pointer to
-the internal geometry owned by the OGRFeature.  There we don't actually 
+the internal geometry owned by the OGRFeature.  There we don't actually
 deleted the return geometry.  However, the OGRLayer::GetNextFeature() method
 returns a copy of the feature that is now owned by us.  So at the end of
 use we must free the feature.  We could just "delete" it, but this can cause
 problems in windows builds where the GDAL DLL has a different "heap" from the
 main program.  To be on the safe side we use a GDAL function to delete the
-feature. 
+feature.
 
 In C++ :
 \code
@@ -304,8 +304,8 @@ In C :
 The OGRLayer returned by GDALDataset::GetLayerByName() is also a reference
 to an internal layer owned by the GDALDataset so we don't need to delete
 it.  But we do need to delete the datasource in order to close the input file.
-Once again we do this with a custom delete method to avoid special win32 
-heap issues. 
+Once again we do this with a custom delete method to avoid special win32
+heap issues.
 
 In C/C++ :
 \code
@@ -364,7 +364,7 @@ int main()
         OGRGeometry *poGeometry;
 
         poGeometry = poFeature->GetGeometryRef();
-        if( poGeometry != NULL 
+        if( poGeometry != NULL
                 && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint )
         {
             OGRPoint *poPoint = (OGRPoint *) poGeometry;
@@ -430,7 +430,7 @@ int main()
         }
 
         hGeometry = OGR_F_GetGeometryRef(hFeature);
-        if( hGeometry != NULL 
+        if( hGeometry != NULL
             && wkbFlatten(OGR_G_GetGeometryType(hGeometry)) == wkbPoint )
         {
             printf( "%.3f,%3.f\n", OGR_G_GetX(hGeometry, 0), OGR_G_GetY(hGeometry, 0) );
@@ -491,10 +491,10 @@ ds = None
 
 As an example of writing through OGR, we will do roughly the opposite of the
 above.  A short program that reads comma separated values from input text
-will be written to a point shapefile via OGR. 
+will be written to a point shapefile via OGR.
 
-As usual, we start by registering all the drivers, and then fetch the 
-Shapefile driver as we will need it to create our output file. 
+As usual, we start by registering all the drivers, and then fetch the
+Shapefile driver as we will need it to create our output file.
 
 In C++ :
 \code
@@ -539,9 +539,9 @@ a directory full of shapefiles, or a single shapefile as a datasource.  In
 this case we will explicitly create a single file by including the extension
 in the name.  Other drivers behave differently.
 The second, third, fourth and fifth argument are related to raster dimensions
-(in case the driver has raster capabilities). The last argument to 
+(in case the driver has raster capabilities). The last argument to
 the call is a list of option values, but we will just be using defaults in
-this case.  Details of the options supported are also format specific. 
+this case.  Details of the options supported are also format specific.
 
 In C ++ :
 \code
@@ -567,7 +567,7 @@ In C :
     }
 \endcode
 
-Now we create the output layer.  In this case since the datasource is a 
+Now we create the output layer.  In this case since the datasource is a
 single file, we can only have one layer.  We pass wkbPoint to specify the
 type of geometry supported by this layer.  In this case we aren't passing
 any coordinate system information or other special layer creation options.
@@ -600,7 +600,7 @@ Now that the layer exists, we need to create any attribute fields that should
 appear on the layer.  Fields must be added to the layer before any features
 are written.  To create a field we initialize an OGRField object with the
 information about the field.  In the case of Shapefiles, the field width and
-precision is significant in the creation of the output .dbf file, so we 
+precision is significant in the creation of the output .dbf file, so we
 set it specifically, though generally the defaults are OK.  For this example
 we will just have one attribute, a name string associated with the x,y point.
 
@@ -623,7 +623,7 @@ In C++:
 In C:
 \code
     OGRFieldDefnH hFieldDefn;
- 
+
     hFieldDefn = OGR_Fld_Create( "Name", OFTString );
 
     OGR_Fld_SetWidth( hFieldDefn, 32);
@@ -637,22 +637,22 @@ In C:
     OGR_Fld_Destroy(hFieldDefn);
 \endcode
 
-The following snipping loops reading lines of the form "x,y,name" from stdin, 
-and parsing them.  
+The following snipping loops reading lines of the form "x,y,name" from stdin,
+and parsing them.
 
 In C++ and in C :
 \code
     double x, y;
     char szName[33];
 
-    while( !feof(stdin) 
+    while( !feof(stdin)
            && fscanf( stdin, "%lf,%lf,%32s", &x, &y, szName ) == 3 )
     {
 \endcode
 
 To write a feature to disk, we must create a local OGRFeature, set attributes
-and attach geometry before trying to write it to the layer.  It is 
-imperative that this feature be instantiated from the OGRFeatureDefn 
+and attach geometry before trying to write it to the layer.  It is
+imperative that this feature be instantiated from the OGRFeatureDefn
 associated with the layer it will be written to.
 
 In C++ :
@@ -673,7 +673,7 @@ In C :
 
 We create a local geometry object, and assign its copy (indirectly) to the feature.
 The OGRFeature::SetGeometryDirectly() differs from OGRFeature::SetGeometry()
-in that the direct method gives ownership of the geometry to the feature. 
+in that the direct method gives ownership of the geometry to the feature.
 This is generally more efficient as it avoids an extra deep object copy
 of the geometry.
 
@@ -682,8 +682,8 @@ In C++ :
         OGRPoint pt;
         pt.setX( x );
         pt.setY( y );
-        
-        poFeature->SetGeometry( &pt ); 
+
+        poFeature->SetGeometry( &pt );
 \endcode
 
 In C :
@@ -691,13 +691,13 @@ In C :
         OGRGeometryH hPt;
         hPt = OGR_G_CreateGeometry(wkbPoint);
         OGR_G_SetPoint_2D(hPt, 0, x, y);
-        
-        OGR_F_SetGeometry( hFeature, hPt ); 
+
+        OGR_F_SetGeometry( hFeature, hPt );
         OGR_G_DestroyGeometry(hPt);
 \endcode
 
 Now we create a feature in the file.  The OGRLayer::CreateFeature() does not
-take ownership of our feature so we clean it up when done with it. 
+take ownership of our feature so we clean it up when done with it.
 
 In C++ :
 \code
@@ -783,7 +783,7 @@ int main()
     double x, y;
     char szName[33];
 
-    while( !feof(stdin) 
+    while( !feof(stdin)
            && fscanf( stdin, "%lf,%lf,%32s", &x, &y, szName ) == 3 )
     {
         OGRFeature *poFeature;
@@ -792,11 +792,11 @@ int main()
         poFeature->SetField( "Name", szName );
 
         OGRPoint pt;
-        
+
         pt.setX( x );
         pt.setY( y );
-    
-        poFeature->SetGeometry( &pt ); 
+
+        poFeature->SetGeometry( &pt );
 
         if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
         {
@@ -860,7 +860,7 @@ int main()
 
     OGR_Fld_Destroy(hFieldDefn);
 
-    while( !feof(stdin) 
+    while( !feof(stdin)
            && fscanf( stdin, "%lf,%lf,%32s", &x, &y, szName ) == 3 )
     {
         OGRFeatureH hFeature;
@@ -872,7 +872,7 @@ int main()
         hPt = OGR_G_CreateGeometry(wkbPoint);
         OGR_G_SetPoint_2D(hPt, 0, x, y);
 
-        OGR_F_SetGeometry( hFeature, hPt ); 
+        OGR_F_SetGeometry( hFeature, hPt );
         OGR_G_DestroyGeometry(hPt);
 
         if( OGR_L_CreateFeature( hLayer, hFeature ) != OGRERR_NONE )
@@ -962,19 +962,19 @@ In C++ :
     poSRS->importFromEPSG(4326);
     oPointField.SetSpatialRef(poSRS);
     poSRS->Release();
-    
+
     if( poLayer->CreateGeomField( &oPointField ) != OGRERR_NONE )
     {
         printf( "Creating field PointField failed.\n" );
         exit( 1 );
     }
-    
+
     OGRGeomFieldDefn oFieldPoint2( "PointField2", wkbPoint );
     poSRS = new OGRSpatialReference();
     poSRS->importFromEPSG(32631);
     oPointField2.SetSpatialRef(poSRS);
     poSRS->Release();
-    
+
     if( poLayer->CreateGeomField( &oPointField2 ) != OGRERR_NONE )
     {
         printf( "Creating field PointField2 failed.\n" );
@@ -993,32 +993,32 @@ In C :
     OSRImportFromEPSG(hSRS, 4326);
     OGR_GFld_SetSpatialRef(hPointField, hSRS);
     OSRRelease(hSRS);
-    
+
     if( OGR_L_CreateGeomField( hLayer, hPointField ) != OGRERR_NONE )
     {
         printf( "Creating field PointField failed.\n" );
         exit( 1 );
     }
-    
+
     OGR_GFld_Destroy( hPointField );
 
     hPointField2 = OGR_GFld_Create( "PointField2", wkbPoint );
     OSRImportFromEPSG(hSRS, 32631);
     OGR_GFld_SetSpatialRef(hPointField2, hSRS);
     OSRRelease(hSRS);
-    
+
     if( OGR_L_CreateGeomField( hLayer, hPointField2 ) != OGRERR_NONE )
     {
         printf( "Creating field PointField2 failed.\n" );
         exit( 1 );
     }
-    
+
     OGR_GFld_Destroy( hPointField2 );
 \endcode
 
 To write a feature to disk, we must create a local OGRFeature, set attributes
-and attach geometries before trying to write it to the layer.  It is 
-imperative that this feature be instantiated from the OGRFeatureDefn 
+and attach geometries before trying to write it to the layer.  It is
+imperative that this feature be instantiated from the OGRFeatureDefn
 associated with the layer it will be written to.
 
 In C++ :
@@ -1028,15 +1028,15 @@ In C++ :
         char* pszWKT;
 
         poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
-        
+
         pszWKT = (char*) "POINT (2 49)";
         OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeometry );
         poFeature->SetGeomFieldDirectly( "PointField", poGeometry );
-        
+
         pszWKT = (char*) "POINT (500000 4500000)";
         OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeometry );
         poFeature->SetGeomFieldDirectly( "PointField2", poGeometry );
-        
+
         if( poLayer->CreateFeature( poFeature ) != OGRERR_NONE )
         {
             printf( "Failed to create feature.\n" );
@@ -1053,17 +1053,17 @@ In C :
         char* pszWKT;
 
         poFeature = OGR_F_Create( OGR_L_GetLayerDefn(hLayer) );
-        
+
         pszWKT = (char*) "POINT (2 49)";
         OGR_G_CreateFromWkt( &pszWKT, NULL, &hGeometry );
         OGR_F_SetGeomFieldDirectly( hFeature,
             OGR_F_GetGeomFieldIndex(hFeature, "PointField"), hGeometry );
-        
+
         pszWKT = (char*) "POINT (500000 4500000)";
         OGR_G_CreateFromWkt( &pszWKT, NULL, &hGeometry );
         OGR_F_SetGeomFieldDirectly( hFeature,
             OGR_F_GetGeomFieldIndex(hFeature, "PointField2"), hGeometry );
-        
+
         if( OGR_L_CreateFeature( hFeature ) != OGRERR_NONE )
         {
             printf( "Failed to create feature.\n" );
@@ -1076,7 +1076,7 @@ In C :
 In Python :
 \code
         feat = ogr.Feature( lyr.GetLayerDefn() )
-        
+
         feat.SetGeomFieldDirectly( "PointField",
             ogr.CreateGeometryFromWkt( "POINT (2 49)" ) )
         feat.SetGeomFieldDirectly( "PointField2",
diff --git a/ogr/ogr_arch.dox b/ogr/ogr_arch.dox
index dc55b67..e71ea6d 100644
--- a/ogr/ogr_arch.dox
+++ b/ogr/ogr_arch.dox
@@ -10,49 +10,49 @@ simple features inspired API.<p>
 
 Because OGR is modeled on the OpenGIS simple features data model, it is
 very helpful to review the SFCOM, or other simple features interface
-specifications which can be retrieved from the 
+specifications which can be retrieved from the
 <a href="http://www.opengeospatial.org">Open Geospatial Consortium</a> web site.  Data
-types, and method names are modeled on those from the interface 
+types, and method names are modeled on those from the interface
 specifications.<p>
 
 \section ogr_arch_overview Class Overview
 
 <ul>
-<li> <b>Geometry</b> (<a href="ogr__geometry_8h_source.html">ogr_geometry.h</a>): 
-The geometry classes (OGRGeometry, etc) encapsulate the OpenGIS model vector 
+<li> <b>Geometry</b> (<a href="ogr__geometry_8h_source.html">ogr_geometry.h</a>):
+The geometry classes (OGRGeometry, etc) encapsulate the OpenGIS model vector
 data as well as providing some geometry operations, and translation to/from
 well known binary and text format.  A geometry includes a spatial reference
 system (projection).<p>
 
-<li> <b>Spatial Reference</b> 
+<li> <b>Spatial Reference</b>
 (<a href="ogr__spatialref_8h_source.html">ogr_spatialref.h</a>):
-An OGRSpatialReference encapsulates the definition of a projection and 
+An OGRSpatialReference encapsulates the definition of a projection and
 datum.<p>
 
 <li> <b>Feature</b> (<a href="ogr__feature_8h_source.html">ogr_feature.h</a>):
-The OGRFeature encapsulates the definition of a whole feature, that is a 
+The OGRFeature encapsulates the definition of a whole feature, that is a
 geometry and a set of attributes.<p>
 
 <li> <b>Feature Class Definition</b>
-(<a href="ogr__feature_8h_source.html">ogr_feature.h</a>): 
+(<a href="ogr__feature_8h_source.html">ogr_feature.h</a>):
 The OGRFeatureDefn class captures the schema (set of field definitions) for
 a group of related features (normally a whole layer).<p>
 
 <li> <b>Layer</b>
-(<a href="ogrsf__frmts_8h_source.html">ogrsf_frmts.h</a>): 
-OGRLayer is an abstract base class represent a layer of features in an 
+(<a href="ogrsf__frmts_8h_source.html">ogrsf_frmts.h</a>):
+OGRLayer is an abstract base class represent a layer of features in an
 GDALDataset.<p>
 
 <li> <b>Dataset</b>
-(<a href="gdal__priv_8h_source.html">gdal_priv.h</a>): 
+(<a href="gdal__priv_8h_source.html">gdal_priv.h</a>):
 A GDALDataset is an abstract base class
 representing a file or database containing one or more OGRLayer
 objects.<p>
 
-<li> <b>Drivers</b> 
+<li> <b>Drivers</b>
 (<a href="gdal__priv_8h_source.html">gdal_priv.h</a>):
 A GDALDriver represents a translator for a specific
-format, opening GDALDataset objects.  All available drivers are managed 
+format, opening GDALDataset objects.  All available drivers are managed
 by the GDALDriverManager.<p>
 
 </ul>
@@ -60,9 +60,9 @@ by the GDALDriverManager.<p>
 \section ogr_arch_geometry Geometry
 
 The geometry classes are represent various kinds of vector geometry.  All
-the geometry classes derived from OGRGeometry which defines the common 
+the geometry classes derived from OGRGeometry which defines the common
 services of all geometries.  Types of geometry include OGRPoint, OGRLineString,
-OGRPolygon, OGRGeometryCollection, OGRMultiPolygon, OGRMultiPoint, 
+OGRPolygon, OGRGeometryCollection, OGRMultiPolygon, OGRMultiPoint,
 and OGRMultiLineString.
 
 GDAL 2.0 extends those geometry type with non-linear geometries with the
@@ -71,9 +71,9 @@ OGRMultiSurface classes.
 
 Additional intermediate abstract base classes contain functionality that
 could eventually be implemented by other geometry types.  These include
-OGRCurve (base class for OGRLineString) and OGRSurface (base class for 
+OGRCurve (base class for OGRLineString) and OGRSurface (base class for
 OGRPolygon).  Some intermediate interfaces modeled in the simple features
-abstract model and SFCOM are not modeled in OGR at this time.  In most 
+abstract model and SFCOM are not modeled in OGR at this time.  In most
 cases the methods are aggregated into other classes.<p>
 
 The OGRGeometryFactory is used to convert well known text, and well known
@@ -82,8 +82,8 @@ formats for representing all the types of simple features geometries.<p>
 
 In a manner based on the geometry object in SFCOM, the OGRGeometry includes
 a reference to an OGRSpatialReference object, defining the spatial reference
-system of that geometry.  This is normally a reference to a shared 
-spatial reference object with reference counting for each of the 
+system of that geometry.  This is normally a reference to a shared
+spatial reference object with reference counting for each of the
 OGRGeometry objects using it.<p>
 
 Many of the spatial analysis methods (such as computing overlaps and so
@@ -109,39 +109,39 @@ also converted to their linear approximation if necessary.
 
 The OGRSpatialReference class is intended to store an OpenGIS Spatial
 Reference System definition.  Currently local, geographic and projected
-coordinate systems are supported.  Vertical coordinate systems, geocentric 
+coordinate systems are supported.  Vertical coordinate systems, geocentric
 coordinate systems, and compound (horizontal + vertical) coordinate systems
 are as well supported in recent GDAL versions.<p>
 
 The spatial coordinate system data model is inherited from the OpenGIS
 <b>Well Known Text</b> format.  A simple form of this is defined in the
-Simple Features specifications.  A more sophisticated form is found in 
+Simple Features specifications.  A more sophisticated form is found in
 the Coordinate Transformation specification.  The OGRSpatialReference is
 built on the features of the Coordinate Transformation specification but
 is intended to be compatible with the earlier simple features form.<p>
 
 There is also an associated OGRCoordinateTransformation class that
 encapsulates use of PROJ.4 for converting between different coordinate
-systems.  There is a <a href="osr_tutorial.html">tutorial</a> available 
+systems.  There is a <a href="osr_tutorial.html">tutorial</a> available
 describing how to use the OGRSpatialReference class.<p>
 
 \section ogr_arch_feature Feature / Feature Definition
 
-The OGRGeometry captures the geometry of a vector feature ... the 
-spatial position/region of a feature.  The OGRFeature contains this 
-geometry, and adds feature attributes, feature id, 
+The OGRGeometry captures the geometry of a vector feature ... the
+spatial position/region of a feature.  The OGRFeature contains this
+geometry, and adds feature attributes, feature id,
 and a feature class identifier. Starting with OGR 1.11,
 <a href="http://trac.osgeo.org/gdal/wiki/rfc41_multiple_geometry_fields">
 several geometries</a> can be associated to a OGRFeature.<p>
 
 The set of attributes, their types, names and so forth is represented
 via the OGRFeatureDefn class.  One OGRFeatureDefn normally exists for a
-layer of features.  The same definition is shared in a reference counted 
+layer of features.  The same definition is shared in a reference counted
 manner by the feature of that type (or feature class).<p>
 
 The feature id (FID) of a feature is intended to be a unique identifier for
 the feature within the layer it is a member of.  Freestanding features, or
-features not yet written to a layer may have a null (OGRNullFID) feature id. 
+features not yet written to a layer may have a null (OGRNullFID) feature id.
 The feature ids are modeled in OGR as a 64-bit integer (GDAL 2.0 or later);
 however, this is not sufficiently expressive to model the natural feature ids in some
 formats.  For instance, the GML feature id is a string.<p>
@@ -158,16 +158,16 @@ class. Each geometry field has its own indicator of geometry type allowed,
 returned by OGRGeomFieldDefn::GetType(), and its spatial reference system,
 returned by OGRGeomFieldDefn::GetSpatialRef().
 
-The OGRFeatureDefn also contains a feature class name (normally 
+The OGRFeatureDefn also contains a feature class name (normally
 used as a layer name).<p>
 
 
 \section ogr_arch_layer Layer
 
-An OGRLayer represents a layer of features within a data source.  All 
-features in an OGRLayer share a common schema and are of the same 
-OGRFeatureDefn.  An OGRLayer class also contains methods for reading 
-features from the data source. 
+An OGRLayer represents a layer of features within a data source.  All
+features in an OGRLayer share a common schema and are of the same
+OGRFeatureDefn.  An OGRLayer class also contains methods for reading
+features from the data source.
 The OGRLayer can be thought of as a gateway for reading and
 writing features from an underlying data source, normally a file format.
 In SFCOM and other table based simple features implementation an OGRLayer
@@ -184,7 +184,7 @@ One flaw in the
 current OGR architecture is that the spatial filter is set directly on
 the OGRLayer which is intended to be the only representative of a given
 layer in a data source.  This means it isn't possible to have multiple
-read operations active at one time with different spatial filters on 
+read operations active at one time with different spatial filters on
 each.  This aspect may be revised in the future to introduce an OGRLayerView
 class or something similar.<p>
 
@@ -202,26 +202,26 @@ layer in a data store. <p>
 fixed schema the way that the SFCOM and SFSQL models do.  The fact that
 features belong to a feature collection that is potentially not directly
 related to their current feature grouping may be important to implementing
-SFCORBA support using OGR. 
+SFCORBA support using OGR.
 
 </ol>
 
-The OGRLayer class is an abstract base class.  An implementation is 
-expected to be subclassed for each file format driver implemented. 
+The OGRLayer class is an abstract base class.  An implementation is
+expected to be subclassed for each file format driver implemented.
 OGRLayers are normally owned directly by their GDALDataset, and aren't
 instantiated or destroyed directly.<p>
 
 \section ogr_arch_dataset Dataset
 
-A GDALDataset represents a set of OGRLayer objects.  This usually 
+A GDALDataset represents a set of OGRLayer objects.  This usually
 represents a single file, set of files, database or gateway.  A GDALDataset
 has a list of OGRLayers which it owns but can return references to.<p>
 
-GDALDataset is an abstract base class.  An implementation is 
+GDALDataset is an abstract base class.  An implementation is
 expected to be subclassed for each file format driver implemented.
 GDALDataset objects are not normally instantiated directly but rather with
 the assistance of an GDALDriver.  Deleting an GDALDataset closes access
-to the underlying persistent data source, but does not normally result in 
+to the underlying persistent data source, but does not normally result in
 deletion of that file.<p>
 
 A GDALDataset has a name (usually a filename) that can be used to reopen
@@ -236,13 +236,13 @@ datasource. <p>
 
 \section ogr_arch_drivers Drivers
 
-A GDALDriver object is instantiated for each file format supported.  
+A GDALDriver object is instantiated for each file format supported.
 The GDALDriver objects are registered with the GDALDriverManager, a
 singleton class that is normally used to open new datasets.<p>
 
 It is intended that a new GDALDriver object is instantiated and define function
 pointers for operations like Identify(), Open() for each
-file format to be supported (along with a file format specific 
+file format to be supported (along with a file format specific
 GDALDataset, and OGRLayer classes).<p>
 
 On application startup registration
diff --git a/ogr/ogr_capi_test.c b/ogr/ogr_capi_test.c
index c21cf66..bd3f5a2 100644
--- a/ogr/ogr_capi_test.c
+++ b/ogr/ogr_capi_test.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: ogr_capi_test.c 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_capi_test.c 34523 2016-07-02 21:50:47Z goatbar $
  **********************************************************************
  * Copyright (c) 2003, Daniel Morissette
  *
diff --git a/ogr/ogr_core.h b/ogr/ogr_core.h
index 7818137..51fc4b0 100644
--- a/ogr/ogr_core.h
+++ b/ogr/ogr_core.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_core.h 33680 2016-03-08 09:59:03Z rouault $
+ * $Id: ogr_core.h 37856 2017-03-28 12:10:47Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Define some core portability services for cross-platform OGR code.
@@ -44,11 +44,20 @@
  * Simple container for a bounding region.
  */
 
-#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
+/*! @cond Doxygen_Suppress */
+#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) && !defined(DOXYGEN_SKIP)
+
+extern "C++"
+{
+#include <limits>
+
 class CPL_DLL OGREnvelope
 {
   public:
-        OGREnvelope() : MinX(0.0), MaxX(0.0), MinY(0.0), MaxY(0.0)
+        OGREnvelope() : MinX(std::numeric_limits<double>::infinity()),
+                        MaxX(-std::numeric_limits<double>::infinity()),
+                        MinY(std::numeric_limits<double>::infinity()),
+                        MaxY(-std::numeric_limits<double>::infinity())
         {
         }
 
@@ -66,41 +75,24 @@ class CPL_DLL OGREnvelope
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wfloat-equal"
 #endif
-    int  IsInit() const { return MinX != 0 || MinY != 0 || MaxX != 0 || MaxY != 0; }
+    int  IsInit() const { return MinX != std::numeric_limits<double>::infinity(); }
 
 #ifdef HAVE_GCC_DIAGNOSTIC_PUSH
 #pragma GCC diagnostic pop
 #endif
 
     void Merge( OGREnvelope const& sOther ) {
-        if( IsInit() )
-        {
-            MinX = MIN(MinX,sOther.MinX);
-            MaxX = MAX(MaxX,sOther.MaxX);
-            MinY = MIN(MinY,sOther.MinY);
-            MaxY = MAX(MaxY,sOther.MaxY);
-        }
-        else
-        {
-            MinX = sOther.MinX;
-            MaxX = sOther.MaxX;
-            MinY = sOther.MinY;
-            MaxY = sOther.MaxY;
-        }
+        MinX = MIN(MinX,sOther.MinX);
+        MaxX = MAX(MaxX,sOther.MaxX);
+        MinY = MIN(MinY,sOther.MinY);
+        MaxY = MAX(MaxY,sOther.MaxY);
     }
+
     void Merge( double dfX, double dfY ) {
-        if( IsInit() )
-        {
-            MinX = MIN(MinX,dfX);
-            MaxX = MAX(MaxX,dfX);
-            MinY = MIN(MinY,dfY);
-            MaxY = MAX(MaxY,dfY);
-        }
-        else
-        {
-            MinX = MaxX = dfX;
-            MinY = MaxY = dfY;
-        }
+        MinX = MIN(MinX,dfX);
+        MaxX = MAX(MaxX,dfX);
+        MinY = MIN(MinY,dfY);
+        MaxY = MAX(MaxY,dfY);
     }
 
     void Intersect( OGREnvelope const& sOther ) {
@@ -123,10 +115,7 @@ class CPL_DLL OGREnvelope
         }
         else
         {
-            MinX = 0;
-            MaxX = 0;
-            MinY = 0;
-            MaxY = 0;
+            *this = OGREnvelope();
         }
     }
 
@@ -142,6 +131,9 @@ class CPL_DLL OGREnvelope
                MaxX >= other.MaxX && MaxY >= other.MaxY;
     }
 };
+
+} // extern "C++"
+
 #else
 typedef struct
 {
@@ -152,16 +144,20 @@ typedef struct
 } OGREnvelope;
 #endif
 
-
 /**
  * Simple container for a bounding region in 3D.
  */
 
-#if defined(__cplusplus) && !defined(CPL_SURESS_CPLUSPLUS)
+#if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) && !defined(DOXYGEN_SKIP)
+
+extern "C++" {
+
 class CPL_DLL OGREnvelope3D : public OGREnvelope
 {
   public:
-        OGREnvelope3D() : OGREnvelope(), MinZ(0.0), MaxZ(0.0)
+        OGREnvelope3D() : OGREnvelope(),
+                          MinZ(std::numeric_limits<double>::infinity()),
+                          MaxZ(-std::numeric_limits<double>::infinity())
         {
         }
 
@@ -178,47 +174,27 @@ class CPL_DLL OGREnvelope3D : public OGREnvelope
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wfloat-equal"
 #endif
-    int  IsInit() const { return MinX != 0 || MinY != 0 || MaxX != 0 || MaxY != 0 || MinZ != 0 || MaxZ != 0; }
+    int  IsInit() const { return MinX != std::numeric_limits<double>::infinity(); }
 #ifdef HAVE_GCC_DIAGNOSTIC_PUSH
 #pragma GCC diagnostic pop
 #endif
 
     void Merge( OGREnvelope3D const& sOther ) {
-        if( IsInit() )
-        {
-            MinX = MIN(MinX,sOther.MinX);
-            MaxX = MAX(MaxX,sOther.MaxX);
-            MinY = MIN(MinY,sOther.MinY);
-            MaxY = MAX(MaxY,sOther.MaxY);
-            MinZ = MIN(MinZ,sOther.MinZ);
-            MaxZ = MAX(MaxZ,sOther.MaxZ);
-        }
-        else
-        {
-            MinX = sOther.MinX;
-            MaxX = sOther.MaxX;
-            MinY = sOther.MinY;
-            MaxY = sOther.MaxY;
-            MinZ = sOther.MinZ;
-            MaxZ = sOther.MaxZ;
-        }
+        MinX = MIN(MinX,sOther.MinX);
+        MaxX = MAX(MaxX,sOther.MaxX);
+        MinY = MIN(MinY,sOther.MinY);
+        MaxY = MAX(MaxY,sOther.MaxY);
+        MinZ = MIN(MinZ,sOther.MinZ);
+        MaxZ = MAX(MaxZ,sOther.MaxZ);
     }
+
     void Merge( double dfX, double dfY, double dfZ ) {
-        if( IsInit() )
-        {
-            MinX = MIN(MinX,dfX);
-            MaxX = MAX(MaxX,dfX);
-            MinY = MIN(MinY,dfY);
-            MaxY = MAX(MaxY,dfY);
-            MinZ = MIN(MinZ,dfZ);
-            MaxZ = MAX(MaxZ,dfZ);
-        }
-        else
-        {
-            MinX = MaxX = dfX;
-            MinY = MaxY = dfY;
-            MinZ = MaxZ = dfZ;
-        }
+        MinX = MIN(MinX,dfX);
+        MaxX = MAX(MaxX,dfX);
+        MinY = MIN(MinY,dfY);
+        MaxY = MAX(MaxY,dfY);
+        MinZ = MIN(MinZ,dfZ);
+        MaxZ = MAX(MaxZ,dfZ);
     }
 
     void Intersect( OGREnvelope3D const& sOther ) {
@@ -245,12 +221,7 @@ class CPL_DLL OGREnvelope3D : public OGREnvelope
         }
         else
         {
-            MinX = 0;
-            MaxX = 0;
-            MinY = 0;
-            MaxY = 0;
-            MinZ = 0;
-            MaxZ = 0;
+            *this = OGREnvelope3D();
         }
     }
 
@@ -268,6 +239,9 @@ class CPL_DLL OGREnvelope3D : public OGREnvelope
                MinZ <= other.MinZ && MaxZ >= other.MaxZ;
     }
 };
+
+} // extern "C++"
+
 #else
 typedef struct
 {
@@ -279,46 +253,51 @@ typedef struct
     double      MaxZ;
 } OGREnvelope3D;
 #endif
-
+/*! @endcond */
 
 CPL_C_START
 
-void CPL_DLL *OGRMalloc( size_t );
-void CPL_DLL *OGRCalloc( size_t, size_t );
-void CPL_DLL *OGRRealloc( void *, size_t );
-char CPL_DLL *OGRStrdup( const char * );
-void CPL_DLL OGRFree( void * );
+/*! @cond Doxygen_Suppress */
+void CPL_DLL *OGRMalloc( size_t ) CPL_WARN_DEPRECATED("Use CPLMalloc instead.");
+void CPL_DLL *OGRCalloc( size_t, size_t ) CPL_WARN_DEPRECATED("Use CPLCalloc instead.");
+void CPL_DLL *OGRRealloc( void *, size_t ) CPL_WARN_DEPRECATED("Use CPLRealloc instead.");
+char CPL_DLL *OGRStrdup( const char * ) CPL_WARN_DEPRECATED("Use CPLStrdup instead.");
+void CPL_DLL OGRFree( void * ) CPL_WARN_DEPRECATED("Use CPLFree instead.");
+/*! @endcond */
 
 #ifdef STRICT_OGRERR_TYPE
+/** Type for a OGR error */
 typedef enum
 {
-    OGRERR_NONE,
-    OGRERR_NOT_ENOUGH_DATA,
-    OGRERR_NOT_ENOUGH_MEMORY,
-    OGRERR_UNSUPPORTED_GEOMETRY_TYPE,
-    OGRERR_UNSUPPORTED_OPERATION,
-    OGRERR_CORRUPT_DATA,
-    OGRERR_FAILURE,
-    OGRERR_UNSUPPORTED_SRS,
-    OGRERR_INVALID_HANDLE,
-    OGRERR_NON_EXISTING_FEATURE
+    OGRERR_NONE,                       /**< Success */
+    OGRERR_NOT_ENOUGH_DATA,            /**< Not enough data to deserialize */
+    OGRERR_NOT_ENOUGH_MEMORY,          /**< Not enough memory */
+    OGRERR_UNSUPPORTED_GEOMETRY_TYPE,  /**< Unsupported geometry type */
+    OGRERR_UNSUPPORTED_OPERATION,      /**< Unsupported operation */
+    OGRERR_CORRUPT_DATA,               /**< Corrupt data */
+    OGRERR_FAILURE,                    /**< Failure */
+    OGRERR_UNSUPPORTED_SRS,            /**< Unsupported SRS */
+    OGRERR_INVALID_HANDLE,             /**< Invalid handle */
+    OGRERR_NON_EXISTING_FEATURE        /**< Non existing feature. Added in GDAL 2.0 */
 } OGRErr;
 #else
+/** Type for a OGR error */
 typedef int OGRErr;
 
-#define OGRERR_NONE                0
-#define OGRERR_NOT_ENOUGH_DATA     1    /* not enough data to deserialize */
-#define OGRERR_NOT_ENOUGH_MEMORY   2
-#define OGRERR_UNSUPPORTED_GEOMETRY_TYPE 3
-#define OGRERR_UNSUPPORTED_OPERATION 4
-#define OGRERR_CORRUPT_DATA        5
-#define OGRERR_FAILURE             6
-#define OGRERR_UNSUPPORTED_SRS     7
-#define OGRERR_INVALID_HANDLE      8
-#define OGRERR_NON_EXISTING_FEATURE 9   /* added in GDAL 2.0 */
+#define OGRERR_NONE                0       /**< Success */
+#define OGRERR_NOT_ENOUGH_DATA     1       /**< Not enough data to deserialize */
+#define OGRERR_NOT_ENOUGH_MEMORY   2       /**< Not enough memory */
+#define OGRERR_UNSUPPORTED_GEOMETRY_TYPE 3 /**< Unsupported geometry type */
+#define OGRERR_UNSUPPORTED_OPERATION 4     /**< Unsupported operation */
+#define OGRERR_CORRUPT_DATA        5       /**< Corrupt data */
+#define OGRERR_FAILURE             6       /**< Failure */
+#define OGRERR_UNSUPPORTED_SRS     7       /**< Unsupported SRS */
+#define OGRERR_INVALID_HANDLE      8       /**< Invalid handle */
+#define OGRERR_NON_EXISTING_FEATURE 9      /**< Non existing feature. Added in GDAL 2.0 */
 
 #endif
 
+/** Type for a OGR boolean */
 typedef int     OGRBoolean;
 
 /* -------------------------------------------------------------------- */
@@ -360,7 +339,7 @@ typedef enum
                                *   ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
     wkbTIN = 16,              /**< a PolyhedralSurface consisting only of Triangle patches
                                *    ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
-    wkbTriangle = 17,         /** < a Triangle. ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
+    wkbTriangle = 17,         /**< a Triangle. ISO SQL/MM Part 3. Reserved in GDAL >= 2.1 but not yet implemented */
 
     wkbNone = 100,          /**< non-standard, for pure attribute records */
     wkbLinearRing = 101,    /**< non-standard, just for createGeometry() */
@@ -443,9 +422,8 @@ typedef enum
     wkbVariantPostGIS1 /**< PostGIS 1.X has different codes for CurvePolygon, MultiCurve and MultiSurface */
 } OGRwkbVariant;
 
-
-/** @deprecated in GDAL 2.0. Use wkbHasZ() or wkbSetZ() instead */
 #ifndef GDAL_COMPILATION
+/** @deprecated in GDAL 2.0. Use wkbHasZ() or wkbSetZ() instead */
 #define wkb25DBit 0x80000000
 #endif
 
@@ -472,7 +450,9 @@ typedef enum
   */
 #define wkbSetM(x)     OGR_GT_SetM(x)
 
+#ifndef DOXYGEN_SKIP
 #define ogrZMarker 0x21125711
+#endif
 
 const char CPL_DLL * OGRGeometryTypeToName( OGRwkbGeometryType eType );
 OGRwkbGeometryType CPL_DLL OGRMergeGeometryTypes( OGRwkbGeometryType eMain,
@@ -495,12 +475,15 @@ OGRwkbGeometryType CPL_DLL OGR_GT_GetCollection( OGRwkbGeometryType eType );
 OGRwkbGeometryType CPL_DLL OGR_GT_GetCurve( OGRwkbGeometryType eType );
 OGRwkbGeometryType CPL_DLL OGR_GT_GetLinear( OGRwkbGeometryType eType );
 
+/** Enumeration to describe byte order */
 typedef enum
 {
-    wkbXDR = 0,         /* MSB/Sun/Motoroloa: Most Significant Byte First   */
-    wkbNDR = 1          /* LSB/Intel/Vax: Least Significant Byte First      */
+    wkbXDR = 0,         /**< MSB/Sun/Motoroloa: Most Significant Byte First   */
+    wkbNDR = 1          /**< LSB/Intel/Vax: Least Significant Byte First      */
 } OGRwkbByteOrder;
 
+#ifndef DOXYGEN_SKIP
+
 #ifndef NO_HACK_FOR_IBM_DB2_V72
 #  define HACK_FOR_IBM_DB2_V72
 #endif
@@ -513,6 +496,8 @@ typedef enum
 #  define DB2_V72_UNFIX_BYTE_ORDER(x) (x)
 #endif
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 /** Alter field name.
  * Used by OGR_L_AlterFieldDefn().
  */
@@ -545,7 +530,6 @@ typedef enum
  */
 #define ALTER_ALL_FLAG             (ALTER_NAME_FLAG | ALTER_TYPE_FLAG | ALTER_WIDTH_PRECISION_FLAG | ALTER_NULLABLE_FLAG | ALTER_DEFAULT_FLAG)
 
-
 /** Validate that fields respect not-null constraints.
  * Used by OGR_F_Validate().
  * @since GDAL 2.0
@@ -648,9 +632,24 @@ typedef enum
     OJRight = 2
 } OGRJustification;
 
+/** Special value for a unset FID */
 #define OGRNullFID            -1
+
+/** Special value set in OGRField.Set.nMarker1, nMarker2 and nMarker3 for
+ *  a unset field.
+ *  Direct use of this value is strongly discouraged.
+ *  Use OGR_RawField_SetUnset() or OGR_RawField_IsUnset() instead.
+ */
 #define OGRUnsetMarker        -21121
 
+/** Special value set in OGRField.Set.nMarker1, nMarker2 and nMarker3 for
+ *  a null field.
+ *  Direct use of this value is strongly discouraged.
+ *  Use OGR_RawField_SetNull() or OGR_RawField_IsNull() instead.
+ *  @since GDAL 2.2
+ */
+#define OGRNullMarker         -21122
+
 /************************************************************************/
 /*                               OGRField                               */
 /************************************************************************/
@@ -660,6 +659,7 @@ typedef enum
  */
 
 typedef union {
+/*! @cond Doxygen_Suppress */
     int         Integer;
     GIntBig     Integer64;
     double      Real;
@@ -693,6 +693,7 @@ typedef union {
     struct {
         int     nMarker1;
         int     nMarker2;
+        int     nMarker3;
     } Set;
 
     struct {
@@ -706,8 +707,10 @@ typedef union {
         GByte   Reserved; /* must be set to 0 */
         float   Second; /* with millisecond accuracy. at the end of the structure, so as to keep it 12 bytes on 32 bit */
     } Date;
+/*! @endcond */
 } OGRField;
 
+/** Return the number of milliseconds from a datetime with decimal seconds */
 #define OGR_GET_MS(floatingpoint_sec)   (int)(((floatingpoint_sec) - (int)(floatingpoint_sec)) * 1000 + 0.5)
 
 int CPL_DLL OGRParseDate( const char *pszInput, OGRField *psOutput,
@@ -716,35 +719,37 @@ int CPL_DLL OGRParseDate( const char *pszInput, OGRField *psOutput,
 /* -------------------------------------------------------------------- */
 /*      Constants from ogrsf_frmts.h for capabilities.                  */
 /* -------------------------------------------------------------------- */
-#define OLCRandomRead          "RandomRead"
-#define OLCSequentialWrite     "SequentialWrite"
-#define OLCRandomWrite         "RandomWrite"
-#define OLCFastSpatialFilter   "FastSpatialFilter"
-#define OLCFastFeatureCount    "FastFeatureCount"
-#define OLCFastGetExtent       "FastGetExtent"
-#define OLCCreateField         "CreateField"
-#define OLCDeleteField         "DeleteField"
-#define OLCReorderFields       "ReorderFields"
-#define OLCAlterFieldDefn      "AlterFieldDefn"
-#define OLCTransactions        "Transactions"
-#define OLCDeleteFeature       "DeleteFeature"
-#define OLCFastSetNextByIndex  "FastSetNextByIndex"
-#define OLCStringsAsUTF8       "StringsAsUTF8"
-#define OLCIgnoreFields        "IgnoreFields"
-#define OLCCreateGeomField     "CreateGeomField"
-#define OLCCurveGeometries     "CurveGeometries"
-#define OLCMeasuredGeometries  "MeasuredGeometries"
-
-#define ODsCCreateLayer        "CreateLayer"
-#define ODsCDeleteLayer        "DeleteLayer"
-#define ODsCCreateGeomFieldAfterCreateLayer   "CreateGeomFieldAfterCreateLayer"
-#define ODsCCurveGeometries    "CurveGeometries"
-#define ODsCTransactions       "Transactions"
-#define ODsCEmulatedTransactions "EmulatedTransactions"
-#define ODsCMeasuredGeometries "MeasuredGeometries"
-
-#define ODrCCreateDataSource   "CreateDataSource"
-#define ODrCDeleteDataSource   "DeleteDataSource"
+#define OLCRandomRead          "RandomRead"         /**< Layer capability for random read */
+#define OLCSequentialWrite     "SequentialWrite"    /**< Layer capability for sequential write */
+#define OLCRandomWrite         "RandomWrite"        /**< Layer capability for random write */
+#define OLCFastSpatialFilter   "FastSpatialFilter"  /**< Layer capability for fast spatial filter */
+#define OLCFastFeatureCount    "FastFeatureCount"   /**< Layer capability for fast feature count retrieval */
+#define OLCFastGetExtent       "FastGetExtent"      /**< Layer capability for fast extent retrieval */
+#define OLCCreateField         "CreateField"        /**< Layer capability for field creation */
+#define OLCDeleteField         "DeleteField"        /**< Layer capability for field deletion */
+#define OLCReorderFields       "ReorderFields"      /**< Layer capability for field reordering */
+#define OLCAlterFieldDefn      "AlterFieldDefn"     /**< Layer capability for field alteration */
+#define OLCTransactions        "Transactions"       /**< Layer capability for transactions */
+#define OLCDeleteFeature       "DeleteFeature"      /**< Layer capability for feature deletion */
+#define OLCFastSetNextByIndex  "FastSetNextByIndex" /**< Layer capability for setting next feature index */
+#define OLCStringsAsUTF8       "StringsAsUTF8"      /**< Layer capability for strings returned with UTF-8 encoding */
+#define OLCIgnoreFields        "IgnoreFields"       /**< Layer capability for field ignoring */
+#define OLCCreateGeomField     "CreateGeomField"    /**< Layer capability for geometry field creation */
+#define OLCCurveGeometries     "CurveGeometries"    /**< Layer capability for curve geometries support */
+#define OLCMeasuredGeometries  "MeasuredGeometries" /**< Layer capability for measured geometries support */
+
+#define ODsCCreateLayer        "CreateLayer"        /**< Dataset capability for layer creation */
+#define ODsCDeleteLayer        "DeleteLayer"        /**< Dataset capability for layer deletion */
+#define ODsCCreateGeomFieldAfterCreateLayer   "CreateGeomFieldAfterCreateLayer" /**< Dataset capability for geometry field creation support */
+#define ODsCCurveGeometries    "CurveGeometries"    /**< Dataset capability for curve geometries support */
+#define ODsCTransactions       "Transactions"       /**< Dataset capability for dataset transcations */
+#define ODsCEmulatedTransactions "EmulatedTransactions" /**< Dataset capability for emulated dataset transactions */
+#define ODsCMeasuredGeometries "MeasuredGeometries"     /**< Dataset capability for measured geometries support */
+#define ODsCRandomLayerRead     "RandomLayerRead"   /**< Dataset capability for GetNextFeature() returning features from random layers */
+#define ODsCRandomLayerWrite    "RandomLayerWrite " /**< Dataset capability for supporting CreateFeature on layer in random order */
+
+#define ODrCCreateDataSource   "CreateDataSource"   /**< Driver capability for datasource creation */
+#define ODrCDeleteDataSource   "DeleteDataSource"   /**< Driver capability for datasource deletion */
 
 /* -------------------------------------------------------------------- */
 /*      Layer metadata items.                                           */
@@ -765,12 +770,12 @@ int CPL_DLL OGRParseDate( const char *pszInput, OGRField *psOutput,
 
 typedef enum ogr_style_tool_class_id
 {
-    OGRSTCNone   = 0,
-    OGRSTCPen    = 1,
-    OGRSTCBrush  = 2,
-    OGRSTCSymbol = 3,
-    OGRSTCLabel  = 4,
-    OGRSTCVector = 5
+    OGRSTCNone   = 0, /**< None */
+    OGRSTCPen    = 1, /**< Pen */
+    OGRSTCBrush  = 2, /**< Brush */
+    OGRSTCSymbol = 3, /**< Symbol */
+    OGRSTCLabel  = 4, /**< Label */
+    OGRSTCVector = 5  /**< Vector */
 } OGRSTClassId;
 
 /**
@@ -778,12 +783,12 @@ typedef enum ogr_style_tool_class_id
  */
 typedef enum ogr_style_tool_units_id
 {
-    OGRSTUGround = 0,
-    OGRSTUPixel  = 1,
-    OGRSTUPoints = 2,
-    OGRSTUMM     = 3,
-    OGRSTUCM     = 4,
-    OGRSTUInches = 5
+    OGRSTUGround = 0, /**< Ground unit */
+    OGRSTUPixel  = 1, /**< Pixel */
+    OGRSTUPoints = 2, /**< Points */
+    OGRSTUMM     = 3, /**< Millimeter */
+    OGRSTUCM     = 4, /**< Centimeter */
+    OGRSTUInches = 5  /**< Inch */
 } OGRSTUnitId;
 
 /**
@@ -791,16 +796,17 @@ typedef enum ogr_style_tool_units_id
  */
 typedef enum ogr_style_tool_param_pen_id
 {
-    OGRSTPenColor       = 0,
-    OGRSTPenWidth       = 1,
-    OGRSTPenPattern     = 2,
-    OGRSTPenId          = 3,
-    OGRSTPenPerOffset   = 4,
-    OGRSTPenCap         = 5,
-    OGRSTPenJoin        = 6,
-    OGRSTPenPriority    = 7,
+    OGRSTPenColor       = 0, /**< Color */
+    OGRSTPenWidth       = 1, /**< Width */
+    OGRSTPenPattern     = 2, /**< Pattern */
+    OGRSTPenId          = 3, /**< Id */
+    OGRSTPenPerOffset   = 4, /**< Perpendicular offset */
+    OGRSTPenCap         = 5, /**< Cap */
+    OGRSTPenJoin        = 6, /**< Join */
+    OGRSTPenPriority    = 7, /**< Priority */
+#ifndef DOXYGEN_SKIP
     OGRSTPenLast        = 8
-
+#endif
 } OGRSTPenParam;
 
 /**
@@ -808,38 +814,40 @@ typedef enum ogr_style_tool_param_pen_id
  */
 typedef enum ogr_style_tool_param_brush_id
 {
-    OGRSTBrushFColor    = 0,
-    OGRSTBrushBColor    = 1,
-    OGRSTBrushId        = 2,
-    OGRSTBrushAngle     = 3,
-    OGRSTBrushSize      = 4,
-    OGRSTBrushDx        = 5,
-    OGRSTBrushDy        = 6,
-    OGRSTBrushPriority  = 7,
+    OGRSTBrushFColor    = 0, /**< Foreground color */
+    OGRSTBrushBColor    = 1, /**< Background color */
+    OGRSTBrushId        = 2, /**< Id */
+    OGRSTBrushAngle     = 3, /**< Angle */
+    OGRSTBrushSize      = 4, /**< Size */
+    OGRSTBrushDx        = 5, /**< Dx */
+    OGRSTBrushDy        = 6, /**< Dy */
+    OGRSTBrushPriority  = 7, /**< Priority */
+#ifndef DOXYGEN_SKIP
     OGRSTBrushLast      = 8
+#endif
 
 } OGRSTBrushParam;
 
-
 /**
  * List of parameters for use with OGRStyleSymbol.
  */
 typedef enum ogr_style_tool_param_symbol_id
 {
-    OGRSTSymbolId       = 0,
-    OGRSTSymbolAngle    = 1,
-    OGRSTSymbolColor    = 2,
-    OGRSTSymbolSize     = 3,
-    OGRSTSymbolDx       = 4,
-    OGRSTSymbolDy       = 5,
-    OGRSTSymbolStep     = 6,
-    OGRSTSymbolPerp     = 7,
-    OGRSTSymbolOffset   = 8,
-    OGRSTSymbolPriority = 9,
-    OGRSTSymbolFontName = 10,
-    OGRSTSymbolOColor   = 11,
+    OGRSTSymbolId       = 0, /**< Id */
+    OGRSTSymbolAngle    = 1, /**< Angle */
+    OGRSTSymbolColor    = 2, /**< Color */
+    OGRSTSymbolSize     = 3, /**< Size */
+    OGRSTSymbolDx       = 4, /**< Dx */
+    OGRSTSymbolDy       = 5, /**< Dy */
+    OGRSTSymbolStep     = 6, /**< Step */
+    OGRSTSymbolPerp     = 7, /**< Perpendicular */
+    OGRSTSymbolOffset   = 8, /**< Offset */
+    OGRSTSymbolPriority = 9, /**< Priority */
+    OGRSTSymbolFontName = 10, /**< Font name */
+    OGRSTSymbolOColor   = 11, /**< Outline color */
+#ifndef DOXYGEN_SKIP
     OGRSTSymbolLast     = 12
-
+#endif
 } OGRSTSymbolParam;
 
 /**
@@ -847,35 +855,38 @@ typedef enum ogr_style_tool_param_symbol_id
  */
 typedef enum ogr_style_tool_param_label_id
 {
-    OGRSTLabelFontName  = 0,
-    OGRSTLabelSize      = 1,
-    OGRSTLabelTextString = 2,
-    OGRSTLabelAngle     = 3,
-    OGRSTLabelFColor    = 4,
-    OGRSTLabelBColor    = 5,
-    OGRSTLabelPlacement = 6,
-    OGRSTLabelAnchor    = 7,
-    OGRSTLabelDx        = 8,
-    OGRSTLabelDy        = 9,
-    OGRSTLabelPerp      = 10,
-    OGRSTLabelBold      = 11,
-    OGRSTLabelItalic    = 12,
-    OGRSTLabelUnderline = 13,
-    OGRSTLabelPriority  = 14,
-    OGRSTLabelStrikeout = 15,
-    OGRSTLabelStretch   = 16,
-    OGRSTLabelAdjHor    = 17,
-    OGRSTLabelAdjVert   = 18,
-    OGRSTLabelHColor    = 19,
-    OGRSTLabelOColor    = 20,
+    OGRSTLabelFontName  = 0, /**< Font name */
+    OGRSTLabelSize      = 1, /**< Size */
+    OGRSTLabelTextString = 2, /**< Text string */
+    OGRSTLabelAngle     = 3, /**< Angle */
+    OGRSTLabelFColor    = 4, /**< Foreground color */
+    OGRSTLabelBColor    = 5, /**< Background color */
+    OGRSTLabelPlacement = 6, /**< Placement */
+    OGRSTLabelAnchor    = 7, /**< Anchor */
+    OGRSTLabelDx        = 8, /**< Dx */
+    OGRSTLabelDy        = 9, /**< Dy */
+    OGRSTLabelPerp      = 10, /**< Perpendicular */
+    OGRSTLabelBold      = 11, /**< Bold */
+    OGRSTLabelItalic    = 12, /**< Italic */
+    OGRSTLabelUnderline = 13, /**< Underline */
+    OGRSTLabelPriority  = 14, /**< Priority */
+    OGRSTLabelStrikeout = 15, /**< Strike out */
+    OGRSTLabelStretch   = 16, /**< Stretch */
+    OGRSTLabelAdjHor    = 17, /**< Horizontal adjustment */
+    OGRSTLabelAdjVert   = 18, /**< Vectical adjustment */
+    OGRSTLabelHColor    = 19, /**< Highlight color */
+    OGRSTLabelOColor    = 20, /**< Outline color */
+#ifndef DOXYGEN_SKIP
     OGRSTLabelLast      = 21
-
+#endif
 } OGRSTLabelParam;
 
 /* ------------------------------------------------------------------- */
 /*                        Version checking                             */
 /* -------------------------------------------------------------------- */
 
+#ifndef DOXYGEN_SKIP
+
 /* Note to developers : please keep this section in sync with gdal.h */
 
 #ifndef GDAL_VERSION_INFO_DEFINED
@@ -905,6 +916,8 @@ int CPL_DLL CPL_STDCALL GDALCheckVersion( int nVersionMajor, int nVersionMinor,
 
 #endif
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 CPL_C_END
 
 #endif /* ndef OGR_CORE_H_INCLUDED */
diff --git a/ogr/ogr_drivertut.dox b/ogr/ogr_drivertut.dox
index a1d3bec..e0893c8 100644
--- a/ogr/ogr_drivertut.dox
+++ b/ogr/ogr_drivertut.dox
@@ -1,5 +1,5 @@
 #ifndef DOXYGEN_SKIP
-/* $Id: gdal_drivertut.dox,v 1.4 2006/10/18 13:26:45 mloskot Exp $ */
+/* $Id: ogr_drivertut.dox 37444 2017-02-25 14:50:24Z goatbar $ */
 #endif /* DOXYGEN_SKIP */
 
 /*!
@@ -12,8 +12,8 @@ specific drivers with instantiating a GDALDriver and subclasses of
 GDALDataset and OGRLayer.  The GDALDriver instance is registered with
 the GDALDriverManager at runtime.
 
-Before following this tutorial to implement an OGR driver, please review 
-the <a href="ogr_arch.html">OGR Architecture</a> document carefully. 
+Before following this tutorial to implement an OGR driver, please review
+the <a href="ogr_arch.html">OGR Architecture</a> document carefully.
 
 The tutorial will be based on implementing a simple ascii point format.
 
@@ -29,41 +29,36 @@ The tutorial will be based on implementing a simple ascii point format.
 
 The format specific driver class is implemented as a instance of GDALDriver.
 One instance of the driver will normally be created, and registered with
-the GDALDriverManager.  The instantiation of the driver is normally 
+the GDALDriverManager.  The instantiation of the driver is normally
 handled by a global C callable registration function, similar to the
-following placed in the same file as the driver class. 
+following placed in the same file as the driver class.
 
 \code
 void RegisterOGRSPF()
-
 {
-    GDALDriver  *poDriver;
+    if( GDALGetDriverByName("SPF") != NULL )
+        return;
 
-    if( GDALGetDriverByName( "SPF" ) == NULL )
-    {
-        poDriver = new GDALDriver();
+    GDALDriver *poDriver = new GDALDriver();
 
-        poDriver->SetDescription( "SPF" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   "Long name for SPF driver" );
-        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "spf" );
-        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
-                                   "drv_spf.html" );
+    poDriver->SetDescription("SPF");
+    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "Long name for SPF driver");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "spf");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drv_spf.html");
 
-        poDriver->pfnOpen = OGRSPFDriverOpen;
-        poDriver->pfnIdentify = OGRSPFDriverIdentify;
-        poDriver->pfnCreate = OGRSPFDriverCreate;
+    poDriver->pfnOpen = OGRSPFDriverOpen;
+    poDriver->pfnIdentify = OGRSPFDriverIdentify;
+    poDriver->pfnCreate = OGRSPFDriverCreate;
 
-        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
 \endcode
 
-The SetDescription() sets the name of the driver.  This name is specified 
-on the commandline when creating datasources so it is generally good to keep 
+The SetDescription() sets the name of the driver.  This name is specified
+on the commandline when creating datasources so it is generally good to keep
 it short and without any special characters or spaces.
 
 SetMetadataItem( GDAL_DCAP_VECTOR, "YES" ) is specified to indicate that the driver
@@ -74,7 +69,7 @@ driver can deal with files opened with the VSI*L GDAL API.
 Otherwise this metadata item should not be defined.
 
 The driver declaration generally looks something like this for a
-format with read or read and update access (the Open() method) and creation 
+format with read or read and update access (the Open() method) and creation
 support (the Create() method).
 
 \code
@@ -86,10 +81,9 @@ static GDALDataset* OGRSPFDriverCreate(const char* pszName, int nXSize, int nYSi
 \endcode
 
 
-The Open() method is called by GDALOpenEx(). It should quietly return NULL if 
-the passed
-filename is not of the format supported by the driver.  If it is the target
-format, then a new GDALDataset object for the dataset should be returned.
+The Open() method is called by GDALOpenEx(). It should quietly return NULL if
+the passed filename is not of the format supported by the driver.  If it is the
+target format, then a new GDALDataset object for the dataset should be returned.
 
 It is common for the Open() method to be delegated to an Open() method on
 the actual format's GDALDataset class.
@@ -100,14 +94,14 @@ static GDALDataset *OGRSPFDriverOpen( GDALOpenInfo* poOpenInfo )
     if( !OGRSPFDriverIdentify(poOpenInfo) )
         return NULL;
 
-    OGRSPFDataSource   *poDS = new OGRSPFDataSource();
-    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update ) )
+    OGRSPFDataSource *poDS = new OGRSPFDataSource();
+    if( !poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update) )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 \endcode
 
@@ -116,29 +110,26 @@ The Identify() method is implemented as such :
 \code
 static int OGRSPFDriverIdentify( GDALOpenInfo* poOpenInfo )
 {
-// -------------------------------------------------------------------- 
-//      Does this appear to be an .spf file?                           
-// --------------------------------------------------------------------
-    return EQUAL( CPLGetExtension(poOpenInfo->pszFilename), "spf" );
+    // Does this appear to be an .spf file?
+    return EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "spf");
 }
 \endcode
 
-
-Examples of the Create() method is left for the section on creation and update. 
+Examples of the Create() method is left for the section on creation and update.
 
 \section odt_datasource_bro Basic Read Only Data Source
 
 We will start implementing a minimal read-only datasource.  No attempt is
 made to optimize operations, and default implementations of many methods
-inherited from GDALDataset are used.  
+inherited from GDALDataset are used.
 
 The primary responsibility of the datasource is to manage the list of layers.
 In the case of the SPF format a datasource is a single file representing one
-layer so there is at most one layer.  The "name" of a datasource should 
-generally be the name passed to the Open() method.  
+layer so there is at most one layer.  The "name" of a datasource should
+generally be the name passed to the Open() method.
 
 The Open() method below is not overriding a base class method, but we have
-it to implement the open operation delegated by the driver class. 
+it to implement the open operation delegated by the driver class.
 
 For this simple case we provide a stub TestCapability() that returns FALSE
 for all extended capabilities.  The TestCapability() method is pure virtual,
@@ -154,7 +145,7 @@ class OGRSPFDataSource : public GDALDataset
                         OGRSPFDataSource();
                         ~OGRSPFDataSource();
 
-    int                 Open( const char * pszFilename, int bUpdate );
+    int                 Open( const char *pszFilename, int bUpdate );
 
     int                 GetLayerCount() { return nLayers; }
     OGRLayer            *GetLayer( int );
@@ -165,22 +156,20 @@ class OGRSPFDataSource : public GDALDataset
 
 The constructor is a simple initializer to a default state.  The Open() will
 take care of actually attaching it to a file.  The destructor is responsible
-for orderly cleanup of layers.  
+for orderly cleanup of layers.
 
 \code
 OGRSPFDataSource::OGRSPFDataSource()
-
 {
     papoLayers = NULL;
     nLayers = 0;
 }
 
 OGRSPFDataSource::~OGRSPFDataSource()
-
 {
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
-    CPLFree( papoLayers );
+    CPLFree(papoLayers);
 }
 \endcode
 
@@ -188,36 +177,33 @@ The Open() method is the most important one on the datasource, though
 in this particular instance it passes most of it's work off to the
 OGRSPFLayer constructor if it believes the file is of the desired format.
 
-Note that Open() methods should try and determine that a file isn't of the 
-identified format as efficiently as possible, since many drivers may be 
-invoked with files of the wrong format before the correct driver is 
+Note that Open() methods should try and determine that a file isn't of the
+identified format as efficiently as possible, since many drivers may be
+invoked with files of the wrong format before the correct driver is
 reached.  In this particular Open() we just test the file extension but this
 is generally a poor way of identifying a file format.  If available, checking
 "magic header values" or something similar is preferable.
 
-In the case of the SPF format, update in place is not supported, 
-so we always fail if bUpdate is FALSE. 
+In the case of the SPF format, update in place is not supported,
+so we always fail if bUpdate is FALSE.
 
 \code
 int  OGRSPFDataSource::Open( const char *pszFilename, int bUpdate )
-
 {
     if( bUpdate )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed, 
-                  "Update access not supported by the SPF driver." );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Update access not supported by the SPF driver.");
         return FALSE;
     }
 
-// -------------------------------------------------------------------- 
-//      Create a corresponding layer.
-// --------------------------------------------------------------------
+    // Create a corresponding layer.
     nLayers = 1;
-    papoLayers = (OGRSPFLayer **) CPLMalloc(sizeof(void*));
-    
-    papoLayers[0] = new OGRSPFLayer( pszFilename );
+    papoLayers = static_cast<OGRSPFLayer **>(CPLMalloc(sizeof(void *)));
 
-    pszName = CPLStrdup( pszFilename );
+    papoLayers[0] = new OGRSPFLayer(pszFilename);
+
+    pszName = CPLStrdup(pszFilename);
 
     return TRUE;
 }
@@ -228,12 +214,11 @@ is created in the Open() this is just a lookup with some safety testing.
 
 \code
 OGRLayer *OGRSPFDataSource::GetLayer( int iLayer )
-
 {
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 \endcode
 
@@ -248,9 +233,7 @@ this:
 class OGRSPFLayer : public OGRLayer
 {
     OGRFeatureDefn     *poFeatureDefn;
-
     FILE               *fp;
-
     int                 nNextFID;
 
   public:
@@ -268,31 +251,30 @@ class OGRSPFLayer : public OGRLayer
 
 The layer constructor is responsible for initialization.  The most important
 initialization is setting up the OGRFeatureDefn for the layer.  This defines
-the list of fields and their types, the geometry type and the coordinate 
-system for the layer.  In the SPF format the set of fields is fixed - a 
-single string field and we have no coordinate system info to set. 
+the list of fields and their types, the geometry type and the coordinate
+system for the layer.  In the SPF format the set of fields is fixed - a
+single string field and we have no coordinate system info to set.
 
 Pay particular attention to the reference counting of the OGRFeatureDefn.
-As OGRFeature's for this layer will also take a reference to this definition
+As OGRFeature's for this layer will also take a reference to this definition,
 it is important that we also establish a reference on behalf of the layer
-itself. 
+itself.
 
 \code
 OGRSPFLayer::OGRSPFLayer( const char *pszFilename )
-
 {
     nNextFID = 0;
 
-    poFeatureDefn = new OGRFeatureDefn( CPLGetBasename( pszFilename ) );
+    poFeatureDefn = new OGRFeatureDefn(CPLGetBasename(pszFilename));
     SetDescription(poFeatureDefn->GetName());
     poFeatureDefn->Reference();
-    poFeatureDefn->SetGeomType( wkbPoint );
-   
-    OGRFieldDefn oFieldTemplate( "Name", OFTString );
+    poFeatureDefn->SetGeomType(wkbPoint);
 
-    poFeatureDefn->AddFieldDefn( &oFieldTemplate );
+    OGRFieldDefn oFieldTemplate("Name", OFTString);
 
-    fp = VSIFOpenL( pszFilename, "r" );
+    poFeatureDefn->AddFieldDefn(&oFieldTemplate);
+
+    fp = VSIFOpenL(pszFilename, "r");
     if( fp == NULL )
         return;
 }
@@ -302,93 +284,84 @@ Note that the destructor uses Release() on the OGRFeatureDefn.  This will
 destroy the feature definition if the reference count drops to zero, but if
 the application is still holding onto a feature from this layer, then that
 feature will hold a reference to the feature definition and it will not
-be destroyed here (which is good!).  
+be destroyed here (which is good!).
 
 \code
 OGRSPFLayer::~OGRSPFLayer()
-
 {
     poFeatureDefn->Release();
     if( fp != NULL )
-        VSIFCloseL( fp );
+        VSIFCloseL(fp);
 }
 \endcode
 
-The GetNextFeature() method is usually the work horse of OGRLayer 
+The GetNextFeature() method is usually the work horse of OGRLayer
 implementations.  It is responsible for reading the next feature according
-to the current spatial and attribute filters installed.  
+to the current spatial and attribute filters installed.
 
-The while() loop is present to loop until we find a satisfactory 
-feature.  The first section of code is for parsing a single line of 
+The while() loop is present to loop until we find a satisfactory
+feature.  The first section of code is for parsing a single line of
 the SPF text file and establishing the x, y and name for the line.
 
 \code
 OGRFeature *OGRSPFLayer::GetNextFeature()
-
 {
-    // --------------------------------------------------------------------
-    //	Loop till we find a feature matching our requirements.
-    // --------------------------------------------------------------------
-    while( TRUE )
+    // Loop till we find a feature matching our requirements.
+    while( true )
     {
-        const char *pszLine;
-        const char *pszName;
-    
-        pszLine = CPLReadLineL( fp );
+        const char *pszLine = CPLReadLineL(fp);
 
-        // Are we at end of file (out of features)? 
+        // Are we at end of file (out of features)?
         if( pszLine == NULL )
             return NULL;
 
-        double dfX;
-        double dfY;
+        const double dfX = atof(pszLine);
 
-        dfX = atof(pszLine);
-    
         pszLine = strstr(pszLine,"|");
         if( pszLine == NULL )
             continue; // we should issue an error!
         else
             pszLine++;
 
-        dfY = atof(pszLine);
-    
+        const double dfY = atof(pszLine);
+
         pszLine = strstr(pszLine,"|");
+
+        const char *pszName = NULL;
         if( pszLine == NULL )
             continue; // we should issue an error!
         else
-            pszName = pszLine+1;
-
+            pszName = pszLine + 1;
 \endcode
 
 The next section turns the x, y and name into a feature.  Also note that
 we assign a linearly incremented feature id.  In our case we started at
-zero for the first feature, though some drivers start at 1.  
+zero for the first feature, though some drivers start at 1.
 
 \code
-        OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-        
-        poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY ) );
-        poFeature->SetField( 0, pszName );
-        poFeature->SetFID( nNextFID++ );
+        OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
+
+        poFeature->SetGeometryDirectly(new OGRPoint(dfX, dfY));
+        poFeature->SetField(0, pszName);
+        poFeature->SetFID(nNextFID++);
 \endcode
 
-Next we check if the feature matches our current attribute or 
-spatial filter if we have them.  Methods on the OGRLayer base class 
+Next we check if the feature matches our current attribute or
+spatial filter if we have them.  Methods on the OGRLayer base class
 support maintain filters in the OGRLayer member fields m_poFilterGeom
 (spatial filter) and m_poAttrQuery (attribute filter) so we can just use
 these values here if they are non-NULL.  The following test is essentially
-"stock" and done the same in all formats.  Some formats also do some 
-spatial filtering ahead of time using a spatial index. 
+"stock" and done the same in all formats.  Some formats also do some
+spatial filtering ahead of time using a spatial index.
 
 If the feature meets our criteria we return it.  Otherwise we destroy it,
-and return to the top of the loop to fetch another to try.  
+and return to the top of the loop to fetch another to try.
 
 \code
-        if( (m_poFilterGeom == NULL
-             || FilterGeometry( poFeature->GetGeometryRef() ) )
-            && (m_poAttrQuery == NULL
-                || m_poAttrQuery->Evaluate( poFeature )) )
+        if( (m_poFilterGeom == NULL ||
+             FilterGeometry(poFeature->GetGeometryRef())) &&
+            (m_poAttrQuery == NULL ||
+             m_poAttrQuery->Evaluate(poFeature)) )
             return poFeature;
 
         delete poFeature;
@@ -399,23 +372,22 @@ and return to the top of the loop to fetch another to try.
 While in the middle of reading a feature set from a layer, or at any other
 time the application can call ResetReading() which is intended to restart
 reading at the beginning of the feature set.  We implement this by seeking
-back to the beginning of the file, and resetting our feature id counter. 
+back to the beginning of the file, and resetting our feature id counter.
 
 \code
 void OGRSPFLayer::ResetReading()
-
 {
-    VSIFSeekL( fp, 0, SEEK_SET );
+    VSIFSeekL(fp, 0, SEEK_SET);
     nNextFID = 0;
 }
 \endcode
 
 In this implementation we do not provide a custom implementation for the
 GetFeature() method.  This means an attempt to read a particular feature
-by it's feature id will result in many calls to GetNextFeature() till the 
+by it's feature id will result in many calls to GetNextFeature() until the
 desired feature is found.  However, in a sequential text format like spf
 there is little else we could do anyway.
 
-There! We have completed a simple read-only feature file format driver.  
+There! We have completed a simple read-only feature file format driver.
 
 */
diff --git a/ogr/ogr_expat.cpp b/ogr/ogr_expat.cpp
index f4f5352..71b271c 100644
--- a/ogr/ogr_expat.cpp
+++ b/ogr/ogr_expat.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_expat.cpp 30134 2015-09-05 14:27:57Z rouault $
  *
  * Project:  OGR
  * Purpose:  Convenience function for parsing with Expat library
@@ -29,55 +28,63 @@
 
 #ifdef HAVE_EXPAT
 
+#include "cpl_port.h"
 #include "ogr_expat.h"
+
+#include <cstddef>
+#include <cstdlib>
+
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: ogr_expat.cpp 30134 2015-09-05 14:27:57Z rouault $");
 
-#define OGR_EXPAT_MAX_ALLOWED_ALLOC 10000000
+CPL_CVSID("$Id: ogr_expat.cpp 36328 2016-11-20 13:44:29Z goatbar $");
+
+static const size_t OGR_EXPAT_MAX_ALLOWED_ALLOC = 10000000;
+
+static void* OGRExpatMalloc( size_t size ) CPL_WARN_UNUSED_RESULT;
+static void* OGRExpatRealloc( void *ptr, size_t size ) CPL_WARN_UNUSED_RESULT;
 
 /************************************************************************/
 /*                          OGRExpatMalloc()                            */
 /************************************************************************/
 
-static void* OGRExpatMalloc(size_t size)
+static void* OGRExpatMalloc( size_t size )
 {
-    if (size < OGR_EXPAT_MAX_ALLOWED_ALLOC)
+    if( size < OGR_EXPAT_MAX_ALLOWED_ALLOC )
         return malloc(size);
-    else
-    {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Expat tried to malloc %d bytes. File probably corrupted", (int)size);
-        return NULL;
-    }
+
+    CPLError(CE_Failure, CPLE_OutOfMemory,
+             "Expat tried to malloc %d bytes. File probably corrupted",
+             static_cast<int>(size));
+    return NULL;
 }
 
 /************************************************************************/
 /*                         OGRExpatRealloc()                            */
 /************************************************************************/
 
-static void* OGRExpatRealloc(void *ptr, size_t size)
+// Caller must replace the pointer with the returned pointer.
+// TODO(schwehr): Consider refactoring to be a void **ptr for safety.
+static void* OGRExpatRealloc( void *ptr, size_t size )
 {
-    if (size < OGR_EXPAT_MAX_ALLOWED_ALLOC)
+    if( size < OGR_EXPAT_MAX_ALLOWED_ALLOC )
         return realloc(ptr, size);
-    else
-    {
-        CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Expat tried to realloc %d bytes. File probably corrupted", (int)size);
-        free(ptr);
-        return NULL;
-    }
+
+    CPLError(CE_Failure, CPLE_OutOfMemory,
+             "Expat tried to realloc %d bytes. File probably corrupted",
+             static_cast<int>(size));
+    free(ptr);
+    return NULL;
 }
 
 /************************************************************************/
 /*                            FillWINDOWS1252()                         */
 /************************************************************************/
 
-static void FillWINDOWS1252(XML_Encoding *info)
+static void FillWINDOWS1252( XML_Encoding *info )
 {
-    /* Map CP1252 bytes to Unicode values */
-    int i;
-    for(i=0;i<0x80;i++)
+    // Map CP1252 bytes to Unicode values.
+    for( int i = 0; i < 0x80; ++i )
         info->map[i] = i;
 
     info->map[0x80] = 0x20AC;
@@ -113,7 +120,7 @@ static void FillWINDOWS1252(XML_Encoding *info)
     info->map[0x9E] = 0x017E;
     info->map[0x9F] = 0x0178;
 
-    for(i=0xA0;i<=0xFF;i++)
+    for( int i = 0xA0; i <= 0xFF; ++i )
         info->map[i] = i;
 }
 
@@ -121,30 +128,29 @@ static void FillWINDOWS1252(XML_Encoding *info)
 /*                             FillISO885915()                          */
 /************************************************************************/
 
-static void FillISO885915(XML_Encoding *info)
+static void FillISO885915( XML_Encoding *info )
 {
-    /* Map ISO-8859-15 bytes to Unicode values */
-    /* Generated by generate_encoding_table.c */
-    int i;
-    for(i = 0x00; i < 0xA4; i++)
+    // Map ISO-8859-15 bytes to Unicode values.
+    // Generated by generate_encoding_table.c.
+    for( int i = 0x00; i < 0xA4; ++i)
         info->map[i] = i;
     info->map[0xA4] = 0x20AC;
     info->map[0xA5] = 0xA5;
     info->map[0xA6] = 0x0160;
     info->map[0xA7] = 0xA7;
     info->map[0xA8] = 0x0161;
-    for(i = 0xA9; i < 0xB4; i++)
+    for( int i = 0xA9; i < 0xB4; ++i )
         info->map[i] = i;
     info->map[0xB4] = 0x017D;
-    for(i = 0xB5; i < 0xB8; i++)
+    for( int i = 0xB5; i < 0xB8; ++i )
         info->map[i] = i;
     info->map[0xB8] = 0x017E;
-    for(i = 0xB9; i < 0xBC; i++)
+    for( int i = 0xB9; i < 0xBC; ++i )
         info->map[i] = i;
     info->map[0xBC] = 0x0152;
     info->map[0xBD] = 0x0153;
     info->map[0xBE] = 0x0178;
-    for(i = 0xBF; i < 0x100; i++)
+    for( int i = 0xBF; i < 0x100; ++i )
         info->map[i] = i;
 }
 
@@ -152,9 +158,10 @@ static void FillISO885915(XML_Encoding *info)
 /*                  OGRExpatUnknownEncodingHandler()                    */
 /************************************************************************/
 
-static int OGRExpatUnknownEncodingHandler (CPL_UNUSED void *unused_encodingHandlerData,
-                                           const XML_Char *name,
-                                           XML_Encoding *info)
+static int OGRExpatUnknownEncodingHandler(
+    void * /* unused_encodingHandlerData */,
+    const XML_Char *name,
+    XML_Encoding *info )
 {
     if( EQUAL(name, "WINDOWS-1252") )
         FillWINDOWS1252(info);
@@ -192,4 +199,4 @@ XML_Parser OGRCreateExpatXMLParser()
     return hParser;
 }
 
-#endif
+#endif  // HAVE_EXPAT
diff --git a/ogr/ogr_expat.h b/ogr/ogr_expat.h
index c08ced0..97f6aa2 100644
--- a/ogr/ogr_expat.h
+++ b/ogr/ogr_expat.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_expat.h 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: ogr_expat.h 34523 2016-07-02 21:50:47Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Convenience function for parsing with Expat library
diff --git a/ogr/ogr_feature.h b/ogr/ogr_feature.h
index 454756c..18d28db 100644
--- a/ogr/ogr_feature.h
+++ b/ogr/ogr_feature.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_feature.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogr_feature.h 37371 2017-02-13 11:41:59Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Class for representing a whole feature, and layer schemas.
@@ -31,9 +31,9 @@
 #ifndef OGR_FEATURE_H_INCLUDED
 #define OGR_FEATURE_H_INCLUDED
 
-#include "ogr_geometry.h"
-#include "ogr_featurestyle.h"
 #include "cpl_atomic_ops.h"
+#include "ogr_featurestyle.h"
+#include "ogr_geometry.h"
 
 /**
  * \file ogr_feature.h
@@ -65,7 +65,7 @@ class CPL_DLL OGRFieldDefn
     char                *pszName;
     OGRFieldType        eType;
     OGRJustification    eJustify;
-    int                 nWidth;                 /* zero is variable */
+    int                 nWidth;  // Zero is variable.
     int                 nPrecision;
     char                *pszDefault;
 
@@ -74,32 +74,30 @@ class CPL_DLL OGRFieldDefn
 
     int                 bNullable;
 
-    void                Initialize( const char *, OGRFieldType );
-
   public:
                         OGRFieldDefn( const char *, OGRFieldType );
-                        OGRFieldDefn( OGRFieldDefn * );
+               explicit OGRFieldDefn( OGRFieldDefn * );
                         ~OGRFieldDefn();
 
     void                SetName( const char * );
     const char         *GetNameRef() { return pszName; }
 
-    OGRFieldType        GetType() { return eType; }
+    OGRFieldType        GetType() const { return eType; }
     void                SetType( OGRFieldType eTypeIn );
     static const char  *GetFieldTypeName( OGRFieldType );
 
-    OGRFieldSubType     GetSubType() { return eSubType; }
+    OGRFieldSubType     GetSubType() const { return eSubType; }
     void                SetSubType( OGRFieldSubType eSubTypeIn );
     static const char  *GetFieldSubTypeName( OGRFieldSubType );
 
-    OGRJustification    GetJustify() { return eJustify; }
+    OGRJustification    GetJustify() const { return eJustify; }
     void                SetJustify( OGRJustification eJustifyIn )
                                                 { eJustify = eJustifyIn; }
 
-    int                 GetWidth() { return nWidth; }
+    int                 GetWidth() const { return nWidth; }
     void                SetWidth( int nWidthIn ) { nWidth = MAX(0,nWidthIn); }
 
-    int                 GetPrecision() { return nPrecision; }
+    int                 GetPrecision() const { return nPrecision; }
     void                SetPrecision( int nPrecisionIn )
                                                 { nPrecision = nPrecisionIn; }
 
@@ -110,7 +108,7 @@ class CPL_DLL OGRFieldDefn
     const char         *GetDefault() const;
     int                 IsDefaultDriverSpecific() const;
 
-    int                 IsIgnored() { return bIgnore; }
+    int                 IsIgnored() const { return bIgnore; }
     void                SetIgnored( int bIgnoreIn ) { bIgnore = bIgnoreIn; }
 
     int                 IsNullable() const { return bNullable; }
@@ -119,7 +117,7 @@ class CPL_DLL OGRFieldDefn
     int                 IsSame( const OGRFieldDefn * ) const;
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(OGRFieldDefn);
+    CPL_DISALLOW_COPY_ASSIGN(OGRFieldDefn)
 };
 
 /************************************************************************/
@@ -143,6 +141,7 @@ class CPL_DLL OGRFieldDefn
 class CPL_DLL OGRGeomFieldDefn
 {
 protected:
+//! @cond Doxygen_Suppress
         char                *pszName;
         OGRwkbGeometryType   eGeomType; /* all values possible except wkbNone */
         OGRSpatialReference* poSRS;
@@ -151,32 +150,34 @@ protected:
         int                 bNullable;
 
         void                Initialize( const char *, OGRwkbGeometryType );
+//! @endcond
 
 public:
-                            OGRGeomFieldDefn(const char *pszNameIn,
-                                             OGRwkbGeometryType eGeomTypeIn);
-                            OGRGeomFieldDefn( OGRGeomFieldDefn * );
+                            OGRGeomFieldDefn( const char *pszNameIn,
+                                              OGRwkbGeometryType eGeomTypeIn );
+                  explicit OGRGeomFieldDefn( OGRGeomFieldDefn * );
         virtual            ~OGRGeomFieldDefn();
 
         void                SetName( const char * );
         const char         *GetNameRef() { return pszName; }
 
-        OGRwkbGeometryType  GetType() { return eGeomType; }
+        OGRwkbGeometryType  GetType() const { return eGeomType; }
         void                SetType( OGRwkbGeometryType eTypeIn );
 
         virtual OGRSpatialReference* GetSpatialRef();
-        void                 SetSpatialRef(OGRSpatialReference* poSRSIn);
+        void                 SetSpatialRef( OGRSpatialReference* poSRSIn );
 
-        int                 IsIgnored() { return bIgnore; }
+        int                 IsIgnored() const { return bIgnore; }
         void                SetIgnored( int bIgnoreIn ) { bIgnore = bIgnoreIn; }
 
         int                 IsNullable() const { return bNullable; }
-        void                SetNullable( int bNullableIn ) { bNullable = bNullableIn; }
+        void                SetNullable( int bNullableIn )
+            { bNullable = bNullableIn; }
 
         int                 IsSame( OGRGeomFieldDefn * );
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(OGRGeomFieldDefn);
+    CPL_DISALLOW_COPY_ASSIGN(OGRGeomFieldDefn)
 };
 
 /************************************************************************/
@@ -206,6 +207,7 @@ public:
 class CPL_DLL OGRFeatureDefn
 {
   protected:
+//! @cond Doxygen_Suppress
     volatile int nRefCount;
 
     int         nFieldCount;
@@ -217,9 +219,10 @@ class CPL_DLL OGRFeatureDefn
     char        *pszFeatureClassName;
 
     int         bIgnoreStyle;
+//! @endcond
 
   public:
-                OGRFeatureDefn( const char * pszName = NULL );
+       explicit OGRFeatureDefn( const char * pszName = NULL );
     virtual    ~OGRFeatureDefn();
 
     virtual const char  *GetName();
@@ -236,7 +239,8 @@ class CPL_DLL OGRFeatureDefn
     virtual OGRGeomFieldDefn *GetGeomFieldDefn( int i );
     virtual int         GetGeomFieldIndex( const char * );
 
-    virtual void        AddGeomFieldDefn( OGRGeomFieldDefn *, int bCopy = TRUE );
+    virtual void        AddGeomFieldDefn( OGRGeomFieldDefn *,
+                                          int bCopy = TRUE );
     virtual OGRErr      DeleteGeomFieldDefn( int iGeomField );
 
     virtual OGRwkbGeometryType GetGeomType();
@@ -251,8 +255,9 @@ class CPL_DLL OGRFeatureDefn
 
     virtual int         IsGeometryIgnored();
     virtual void        SetGeometryIgnored( int bIgnore );
-    virtual int        IsStyleIgnored() { return bIgnoreStyle; }
-    virtual void        SetStyleIgnored( int bIgnore ) { bIgnoreStyle = bIgnore; }
+    virtual int         IsStyleIgnored() const { return bIgnoreStyle; }
+    virtual void        SetStyleIgnored( int bIgnore )
+        { bIgnoreStyle = bIgnore; }
 
     virtual int         IsSame( OGRFeatureDefn * poOtherFeatureDefn );
 
@@ -260,7 +265,7 @@ class CPL_DLL OGRFeatureDefn
     static void         DestroyFeatureDefn( OGRFeatureDefn * );
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(OGRFeatureDefn);
+    CPL_DISALLOW_COPY_ASSIGN(OGRFeatureDefn)
 };
 
 /************************************************************************/
@@ -285,47 +290,56 @@ class CPL_DLL OGRFeature
     bool                SetFieldInternal( int i, OGRField * puValue );
 
   protected:
-    char *              m_pszStyleString;
+//! @cond Doxygen_Suppress
+    char                *m_pszStyleString;
     OGRStyleTable       *m_poStyleTable;
-    char *              m_pszTmpFieldValue;
+    char                *m_pszTmpFieldValue;
+//! @endcond
 
   public:
-                        OGRFeature( OGRFeatureDefn * );
+    explicit            OGRFeature( OGRFeatureDefn * );
     virtual            ~OGRFeature();
 
     OGRFeatureDefn     *GetDefnRef() { return poDefn; }
 
     OGRErr              SetGeometryDirectly( OGRGeometry * );
-    OGRErr              SetGeometry( OGRGeometry * );
+    OGRErr              SetGeometry( const OGRGeometry * );
     OGRGeometry        *GetGeometryRef();
     OGRGeometry        *StealGeometry() CPL_WARN_UNUSED_RESULT;
 
-    int                 GetGeomFieldCount()
+    int                 GetGeomFieldCount() const
                                 { return poDefn->GetGeomFieldCount(); }
     OGRGeomFieldDefn   *GetGeomFieldDefnRef( int iField )
                                 { return poDefn->GetGeomFieldDefn(iField); }
-    int                 GetGeomFieldIndex( const char * pszName)
+    int                 GetGeomFieldIndex( const char * pszName )
                                 { return poDefn->GetGeomFieldIndex(pszName); }
 
-    OGRGeometry*        GetGeomFieldRef(int iField);
-    OGRGeometry*        StealGeometry(int iField);
-    OGRGeometry*        GetGeomFieldRef(const char* pszFName);
+    OGRGeometry*        GetGeomFieldRef( int iField );
+    OGRGeometry*        StealGeometry( int iField );
+    OGRGeometry*        GetGeomFieldRef( const char* pszFName );
     OGRErr              SetGeomFieldDirectly( int iField, OGRGeometry * );
-    OGRErr              SetGeomField( int iField, OGRGeometry * );
+    OGRErr              SetGeomField( int iField, const OGRGeometry * );
 
     OGRFeature         *Clone() CPL_WARN_UNUSED_RESULT;
     virtual OGRBoolean  Equal( OGRFeature * poFeature );
 
-    int                 GetFieldCount() { return poDefn->GetFieldCount(); }
-    OGRFieldDefn       *GetFieldDefnRef( int iField )
+    int                 GetFieldCount() const
+        { return poDefn->GetFieldCount(); }
+    OGRFieldDefn       *GetFieldDefnRef( int iField ) const
                                       { return poDefn->GetFieldDefn(iField); }
-    int                 GetFieldIndex( const char * pszName)
-                                      { return poDefn->GetFieldIndex(pszName);}
+    int                 GetFieldIndex( const char * pszName )
+                                      { return poDefn->GetFieldIndex(pszName); }
 
     int                 IsFieldSet( int iField );
 
     void                UnsetField( int iField );
 
+    bool                IsFieldNull( int iField );
+
+    void                SetFieldNull( int iField );
+
+    bool                IsFieldSetAndNotNull( int iField );
+
     OGRField           *GetRawFieldRef( int i ) { return pauFields + i; }
 
     int                 GetFieldAsInteger( int i );
@@ -338,13 +352,18 @@ class CPL_DLL OGRFeature
     char              **GetFieldAsStringList( int i );
     GByte              *GetFieldAsBinary( int i, int *pnCount );
     int                 GetFieldAsDateTime( int i,
-                                     int *pnYear, int *pnMonth, int *pnDay,
-                                     int *pnHour, int *pnMinute, int *pnSecond,
-                                     int *pnTZFlag );
+                                            int *pnYear, int *pnMonth,
+                                            int *pnDay,
+                                            int *pnHour, int *pnMinute,
+                                            int *pnSecond,
+                                            int *pnTZFlag );
     int                 GetFieldAsDateTime( int i,
-                                     int *pnYear, int *pnMonth, int *pnDay,
-                                     int *pnHour, int *pnMinute, float *pfSecond,
-                                     int *pnTZFlag );
+                                            int *pnYear, int *pnMonth,
+                                            int *pnDay,
+                                            int *pnHour, int *pnMinute,
+                                            float *pfSecond,
+                                            int *pnTZFlag );
+    char               *GetFieldAsSerializedJSon( int i );
 
     int                 GetFieldAsInteger( const char *pszFName )
                       { return GetFieldAsInteger( GetFieldIndex(pszFName) ); }
@@ -374,7 +393,8 @@ class CPL_DLL OGRFeature
     void                SetField( int i, double dfValue );
     void                SetField( int i, const char * pszValue );
     void                SetField( int i, int nCount, int * panValues );
-    void                SetField( int i, int nCount, const GIntBig * panValues );
+    void                SetField( int i, int nCount,
+                                  const GIntBig * panValues );
     void                SetField( int i, int nCount, double * padfValues );
     void                SetField( int i, char ** papszValues );
     void                SetField( int i, OGRField * puValue );
@@ -389,17 +409,17 @@ class CPL_DLL OGRFeature
                            { SetField( GetFieldIndex(pszFName), nValue ); }
     void                SetField( const char *pszFName, double dfValue )
                            { SetField( GetFieldIndex(pszFName), dfValue ); }
-    void                SetField( const char *pszFName, const char * pszValue)
+    void                SetField( const char *pszFName, const char * pszValue )
                            { SetField( GetFieldIndex(pszFName), pszValue ); }
     void                SetField( const char *pszFName, int nCount,
                                   int * panValues )
-                         { SetField(GetFieldIndex(pszFName),nCount,panValues);}
+                         { SetField(GetFieldIndex(pszFName),nCount,panValues); }
     void                SetField( const char *pszFName, int nCount,
                                   const GIntBig * panValues )
-                         { SetField(GetFieldIndex(pszFName),nCount,panValues);}
+                         { SetField(GetFieldIndex(pszFName),nCount,panValues); }
     void                SetField( const char *pszFName, int nCount,
                                   double * padfValues )
-                         {SetField(GetFieldIndex(pszFName),nCount,padfValues);}
+                         {SetField(GetFieldIndex(pszFName),nCount,padfValues); }
     void                SetField( const char *pszFName, char ** papszValues )
                            { SetField( GetFieldIndex(pszFName), papszValues); }
     void                SetField( const char *pszFName, OGRField * puValue )
@@ -412,34 +432,41 @@ class CPL_DLL OGRFeature
                                        nYear, nMonth, nDay,
                                        nHour, nMinute, fSecond, nTZFlag ); }
 
-    GIntBig             GetFID() { return nFID; }
+    GIntBig             GetFID() const { return nFID; }
     virtual OGRErr      SetFID( GIntBig nFIDIn );
 
     void                DumpReadable( FILE *, char** papszOptions = NULL );
 
-    OGRErr              SetFrom( OGRFeature *, int = TRUE);
+    OGRErr              SetFrom( OGRFeature *, int = TRUE );
     OGRErr              SetFrom( OGRFeature *, int *, int = TRUE );
     OGRErr              SetFieldsFrom( OGRFeature *, int *, int = TRUE );
 
+//! @cond Doxygen_Suppress
     OGRErr              RemapFields( OGRFeatureDefn *poNewDefn,
                                      int *panRemapSource );
     OGRErr              RemapGeomFields( OGRFeatureDefn *poNewDefn,
                                      int *panRemapSource );
+//! @endcond
 
     int                 Validate( int nValidateFlags,
                                   int bEmitError );
-    void                FillUnsetWithDefault(int bNotNullableOnly,
-                                             char** papszOptions );
+    void                FillUnsetWithDefault( int bNotNullableOnly,
+                                              char** papszOptions );
 
     virtual const char *GetStyleString();
     virtual void        SetStyleString( const char * );
     virtual void        SetStyleStringDirectly( char * );
+
+    /** Return style table.
+     * @return style table.
+     */
     virtual OGRStyleTable *GetStyleTable() { return m_poStyleTable; }
-    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
-    virtual void        SetStyleTableDirectly(OGRStyleTable *poStyleTable);
+    virtual void        SetStyleTable( OGRStyleTable *poStyleTable );
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
 
     const char         *GetNativeData() const { return m_pszNativeData; }
-    const char         *GetNativeMediaType() const { return m_pszNativeMediaType; }
+    const char         *GetNativeMediaType() const
+        { return m_pszNativeMediaType; }
     void                SetNativeData( const char* pszNativeData );
     void                SetNativeMediaType( const char* pszNativeMediaType );
 
@@ -447,13 +474,14 @@ class CPL_DLL OGRFeature
     static void         DestroyFeature( OGRFeature * );
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(OGRFeature);
+    CPL_DISALLOW_COPY_ASSIGN(OGRFeature)
 };
 
 /************************************************************************/
 /*                           OGRFeatureQuery                            */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 class OGRLayer;
 class swq_expr_node;
 class swq_custom_func_registrar;
@@ -464,21 +492,24 @@ class CPL_DLL OGRFeatureQuery
     OGRFeatureDefn *poTargetDefn;
     void           *pSWQExpr;
 
-    char          **FieldCollector( void *, char ** );
+    char      **FieldCollector( void *, char ** );
 
-    GIntBig       *EvaluateAgainstIndices( swq_expr_node*, OGRLayer *, GIntBig& nFIDCount);
+    GIntBig    *EvaluateAgainstIndices( swq_expr_node*, OGRLayer *,
+                                           GIntBig& nFIDCount );
 
     int         CanUseIndex( swq_expr_node*, OGRLayer * );
 
   public:
                 OGRFeatureQuery();
-                ~OGRFeatureQuery();
+               ~OGRFeatureQuery();
 
     OGRErr      Compile( OGRFeatureDefn *, const char *,
-                         int bCheck = TRUE, swq_custom_func_registrar* poCustomFuncRegistrar = NULL );
+                         int bCheck = TRUE,
+                         swq_custom_func_registrar*
+                         poCustomFuncRegistrar = NULL );
     int         Evaluate( OGRFeature * );
 
-    GIntBig       *EvaluateAgainstIndices( OGRLayer *, OGRErr * );
+    GIntBig    *EvaluateAgainstIndices( OGRLayer *, OGRErr * );
 
     int         CanUseIndex( OGRLayer * );
 
@@ -486,5 +517,6 @@ class CPL_DLL OGRFeatureQuery
 
     void       *GetSWQExpr() { return pSWQExpr; }
 };
+//! @endcond
 
 #endif /* ndef OGR_FEATURE_H_INCLUDED */
diff --git a/ogr/ogr_feature_style.html b/ogr/ogr_feature_style.html
index c000031..e0e2e73 100644
--- a/ogr/ogr_feature_style.html
+++ b/ogr/ogr_feature_style.html
@@ -66,9 +66,7 @@ But then at the time such a dataset is opened through OGR, the name of
 the attribute that contains style information should either be specified
 in some metadata, or be specified by the user.
 <P>Also, in the SFCOM interface, the style information will be stored in
-an attribute just like the geometry is. Later in this document, we will
-define a kind of "WKT" format to be used when storing style information
-in text form.
+an attribute just like the geometry is.
 <H2>
 1.2 Feature Styles can be stored at 2 levels</H2>
 The style defines the way a feature should be drawn, but it is very common
@@ -206,15 +204,15 @@ The best way to get familiar with something is by example.
   A point symbol:
      "SYMBOL(c:#00FF00,id:"points.sym-45,ogr-sym-7")"
 
-  A text label, taking the text string from the "text_string"
+  A text label, taking the text string from the "text_attribute"
   attribute field:
-     "LABEL(f:"Times New Roman",s:12pt,t:{text_string})"</PRE>
+     "LABEL(f:"Times New Roman",s:12pt,t:{text_attribute})"</PRE>
 Here is what a style table that contains all the above styles could look
 like:
 <PRE>    road:      PEN(c:#FF0000,w:5px)
     lake:      BRUSH(fc:#0000FF);PEN(c:#000000)
     campsite:  SYMBOL(c:#00FF00,id:"points.sym-45,ogr-sym-7")
-    label:     LABEL(f:"Times New Roman",s:12pt,t:{text_string})</PRE>
+    label:     LABEL(f:"Times New Roman",s:12pt,t:{text_attribute})</PRE>
 
 And then individual features could refer to styles from the table above
 using the "@" character followed by the style name in their style property.
@@ -755,7 +753,7 @@ it is escaped with a antislash (\) character before it.
 <BR>
       LABEL(f:"Arial, Helvetica", s:12pt, t:"Hello World with escaped double-quote(\") character!")
 <BR>
-      LABEL(f:"Arial, Helvetica", s:12pt, t:{text_value})</TD>
+      LABEL(f:"Arial, Helvetica", s:12pt, t:{text_attribute})</TD>
   </TR>
 
   <TR>
@@ -904,7 +902,7 @@ This would apply to formats like ArcView Shapes.
     road:      PEN(c:#FF0000,w:5px)
     lake:      BRUSH(fc:#0000FF);PEN(c:#000000)
     campsite:  SYMBOL(c:#00FF00,id:"points.sym-45,ogr-sym-7")
-    label:     LABEL(f:"Times New Roman",s:12pt,t:{text_string})</PRE>
+    label:     LABEL(f:"Times New Roman",s:12pt,t:{text_attribute})</PRE>
 
 <P>
 <P>The first line is a signature with a version number.  Must be present
diff --git a/ogr/ogr_featurestyle.h b/ogr/ogr_featurestyle.h
index b3ef911..86f4593 100644
--- a/ogr/ogr_featurestyle.h
+++ b/ogr/ogr_featurestyle.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_featurestyle.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogr_featurestyle.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Define of Feature Representation
@@ -46,6 +46,7 @@ class OGRFeature;
  * All OGRStyleTool param lists are defined in ogr_core.h.
  */
 
+/** OGR Style type */
 typedef enum ogr_style_type
 {
     OGRSTypeString,
@@ -54,6 +55,7 @@ typedef enum ogr_style_type
     OGRSTypeBoolean
 }  OGRSType;
 
+//! @cond Doxygen_Suppress
 typedef struct ogr_style_param
 {
     int              eParam;
@@ -62,7 +64,6 @@ typedef struct ogr_style_param
     OGRSType         eType;
 } OGRStyleParamId;
 
-
 typedef struct ogr_style_value
 {
     char            *pszValue;
@@ -71,7 +72,7 @@ typedef struct ogr_style_value
     GBool            bValid;
     OGRSTUnitId      eUnit;
 } OGRStyleValue;
-
+//! @endcond
 
 // Every time a pszStyleString given in parameter is NULL,
 // the StyleString defined in the Mgr will be use.
@@ -107,7 +108,6 @@ class CPL_DLL OGRStyleTable
     const char *GetLastStyleName();
 };
 
-
 class OGRStyleTool;
 
 /**
@@ -120,7 +120,7 @@ class CPL_DLL OGRStyleMgr
     char            *m_pszStyleString;
 
   public:
-    OGRStyleMgr(OGRStyleTable *poDataSetStyleTable = NULL);
+    explicit OGRStyleMgr(OGRStyleTable *poDataSetStyleTable = NULL);
     ~OGRStyleMgr();
 
     GBool SetFeatureStyleString(OGRFeature *,const char *pszStyleString=NULL,
@@ -147,11 +147,11 @@ class CPL_DLL OGRStyleMgr
 
     /* It could have a reference counting process us for the OGRStyleTable, if
       needed. */
-
+//! @cond Doxygen_Suppress
     OGRStyleTable *GetDataSetStyleTable(){return m_poDataSetStyleTable;}
 
     OGRStyleTool *CreateStyleToolFromStyleString(const char *pszStyleString);
-
+//! @endcond
 };
 
 /**
@@ -170,29 +170,42 @@ class CPL_DLL OGRStyleTool
     virtual GBool Parse() = 0;
 
   protected:
+#ifndef DOXYGEN_SKIP
     GBool Parse(const OGRStyleParamId* pasStyle,
                 OGRStyleValue* pasValue,
                 int nCount);
+#endif
 
   public:
 
-    OGRStyleTool(){}
-    OGRStyleTool(OGRSTClassId eClassId);
+    OGRStyleTool() :
+        m_bModified(FALSE),
+        m_bParsed(FALSE),
+        m_dfScale(0.0),
+        m_eUnit(OGRSTUGround),
+        m_eClassId(OGRSTCNone),
+        m_pszStyleString(NULL)
+        {}
+    explicit OGRStyleTool(OGRSTClassId eClassId);
     virtual ~OGRStyleTool();
 
-    GBool GetRGBFromString(const char *pszColor, int &nRed, int &nGreen,
+    static GBool GetRGBFromString(const char *pszColor, int &nRed, int &nGreen,
                            int &nBlue, int &nTransparence);
-    int   GetSpecificId(const char *pszId, const char *pszWanted);
+    static int   GetSpecificId(const char *pszId, const char *pszWanted);
 
+#ifndef DOXYGEN_SKIP
     GBool IsStyleModified() {return m_bModified;}
     void  StyleModified() {m_bModified = TRUE;}
 
     GBool IsStyleParsed() {return m_bParsed;}
     void  StyleParsed() {m_bParsed = TRUE;}
+#endif
 
     OGRSTClassId GetType();
 
+#ifndef DOXYGEN_SKIP
     void SetInternalInputUnitFromParam(char *pszString);
+#endif
 
     void SetUnit(OGRSTUnitId,double dfScale = 1.0); //the dfScale will be
          //used if we are working with Ground Unit ( ground = paper * scale);
@@ -231,12 +244,14 @@ class CPL_DLL OGRStyleTool
     void SetParamDbl(const OGRStyleParamId &sStyleParam ,
                      OGRStyleValue &sStyleValue,
                      double dfParam);
-
+#ifndef DOXYGEN_SKIP
     double ComputeWithUnit(double, OGRSTUnitId);
     int    ComputeWithUnit(int , OGRSTUnitId);
-
+#endif
 };
 
+//! @cond Doxygen_Suppress
+
 /**
  * This class represents a style pen
  */
@@ -246,7 +261,7 @@ class CPL_DLL OGRStylePen : public OGRStyleTool
 
     OGRStyleValue    *m_pasStyleValue;
 
-    GBool Parse();
+    GBool Parse() CPL_OVERRIDE;
 
   public:
 
@@ -282,7 +297,7 @@ class CPL_DLL OGRStylePen : public OGRStyleTool
     void SetParamStr(OGRSTPenParam eParam, const char *pszParamString);
     void SetParamNum(OGRSTPenParam eParam, int nParam);
     void SetParamDbl(OGRSTPenParam eParam, double dfParam);
-    const char *GetStyleString();
+    const char *GetStyleString() CPL_OVERRIDE;
 };
 
 /**
@@ -294,7 +309,7 @@ class CPL_DLL OGRStyleBrush : public OGRStyleTool
 
     OGRStyleValue    *m_pasStyleValue;
 
-    GBool Parse();
+    GBool Parse() CPL_OVERRIDE;
 
   public:
 
@@ -328,7 +343,7 @@ class CPL_DLL OGRStyleBrush : public OGRStyleTool
      void SetParamStr(OGRSTBrushParam eParam, const char *pszParamString);
      void SetParamNum(OGRSTBrushParam eParam, int nParam);
      void SetParamDbl(OGRSTBrushParam eParam, double dfParam);
-     const char *GetStyleString();
+     const char *GetStyleString() CPL_OVERRIDE;
 };
 
 /**
@@ -340,7 +355,7 @@ class CPL_DLL OGRStyleSymbol : public OGRStyleTool
 
     OGRStyleValue    *m_pasStyleValue;
 
-    GBool Parse();
+    GBool Parse() CPL_OVERRIDE;
 
   public:
 
@@ -386,7 +401,7 @@ class CPL_DLL OGRStyleSymbol : public OGRStyleTool
      void SetParamStr(OGRSTSymbolParam eParam, const char *pszParamString);
      void SetParamNum(OGRSTSymbolParam eParam, int nParam);
      void SetParamDbl(OGRSTSymbolParam eParam, double dfParam);
-     const char *GetStyleString();
+     const char *GetStyleString() CPL_OVERRIDE;
 };
 
 /**
@@ -398,7 +413,7 @@ class CPL_DLL OGRStyleLabel : public OGRStyleTool
 
     OGRStyleValue    *m_pasStyleValue;
 
-    GBool Parse();
+    GBool Parse() CPL_OVERRIDE;
 
   public:
 
@@ -460,7 +475,9 @@ class CPL_DLL OGRStyleLabel : public OGRStyleTool
      void SetParamStr(OGRSTLabelParam eParam, const char *pszParamString);
      void SetParamNum(OGRSTLabelParam eParam, int nParam);
      void SetParamDbl(OGRSTLabelParam eParam, double dfParam);
-     const char *GetStyleString();
+     const char *GetStyleString() CPL_OVERRIDE;
 };
 
+//! @endcond
+
 #endif /* OGR_FEATURESTYLE_INCLUDE */
diff --git a/ogr/ogr_fromepsg.cpp b/ogr/ogr_fromepsg.cpp
index c4a8f44..6d30444 100644
--- a/ogr/ogr_fromepsg.cpp
+++ b/ogr/ogr_fromepsg.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_fromepsg.cpp 33605 2016-02-29 21:29:59Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Generate an OGRSpatialReference object based on an EPSG
@@ -29,13 +28,29 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_srs_api.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include <memory>
+#include <string>
+#include <vector>
+#include <limits>
+
+#include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
 #include "ogr_spatialref.h"
 
-#include <vector>
 
-CPL_CVSID("$Id: ogr_fromepsg.cpp 33605 2016-02-29 21:29:59Z goatbar $");
+CPL_CVSID("$Id: ogr_fromepsg.cpp 37723 2017-03-16 17:07:53Z rouault $");
 
 extern void OGRsnPrintDouble( char * pszStrBuf, size_t size, double dfValue );
 
@@ -69,7 +84,7 @@ void OGREPSGDatumNameMassage( char ** ppszDatum )
 {
     char *pszDatum = *ppszDatum;
 
-    if (pszDatum[0] == '\0')
+    if( pszDatum[0] == '\0' )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -89,7 +104,7 @@ void OGREPSGDatumNameMassage( char ** ppszDatum )
 /* -------------------------------------------------------------------- */
 /*      Remove repeated and trailing underscores.                       */
 /* -------------------------------------------------------------------- */
-    int j = 0; // Used after for loop.
+    int j = 0;  // Used after for loop.
     for( int i = 1; pszDatum[i] != '\0'; i++ )
     {
         if( pszDatum[j] == '_' && pszDatum[i] == '_' )
@@ -129,14 +144,13 @@ EPSGAngleStringToDD( const char * pszAngle, int nUOMAngle )
 {
     double dfAngle = 0.0;
 
-    if( nUOMAngle == 9110 )             /* DDD.MMSSsss */
+    if( nUOMAngle == 9110 )  // DDD.MMSSsss
     {
-        dfAngle = ABS(atoi(pszAngle));
-        const char *pszDecimal = strchr(pszAngle,'.');
+        dfAngle = std::abs(atoi(pszAngle));
+        const char *pszDecimal = strchr(pszAngle, '.');
         if( pszDecimal != NULL && strlen(pszDecimal) > 1 )
         {
             char szMinutes[3] = { '\0', '\0', '\0' };
-            char szSeconds[64] = { '\0' };
 
             szMinutes[0] = pszDecimal[1];
             if( pszDecimal[2] >= '0' && pszDecimal[2] <= '9' )
@@ -148,6 +162,7 @@ EPSGAngleStringToDD( const char * pszAngle, int nUOMAngle )
 
             if( strlen(pszDecimal) > 3 )
             {
+                char szSeconds[64] = { '\0' };
                 szSeconds[0] = pszDecimal[3];
                 if( pszDecimal[4] >= '0' && pszDecimal[4] <= '9' )
                 {
@@ -168,23 +183,23 @@ EPSGAngleStringToDD( const char * pszAngle, int nUOMAngle )
         if( pszAngle[0] == '-' )
             dfAngle *= -1;
     }
-    else if( nUOMAngle == 9105 || nUOMAngle == 9106 )   /* grad */
+    else if( nUOMAngle == 9105 || nUOMAngle == 9106 )   // Grad.
     {
-        dfAngle = 180 * (CPLAtof(pszAngle ) / 200);
+        dfAngle = 180.0 * (CPLAtof(pszAngle ) / 200.0);
     }
-    else if( nUOMAngle == 9101 )                        /* radians */
+    else if( nUOMAngle == 9101 )                        // Radians.
     {
-        dfAngle = 180 * (CPLAtof(pszAngle ) / M_PI);
+        dfAngle = 180.0 * (CPLAtof(pszAngle ) / M_PI);
     }
-    else if( nUOMAngle == 9103 )                        /* arc-minute */
+    else if( nUOMAngle == 9103 )                        // Arc-minute.
     {
-        dfAngle = CPLAtof(pszAngle) / 60;
+        dfAngle = CPLAtof(pszAngle) / 60.0;
     }
-    else if( nUOMAngle == 9104 )                        /* arc-second */
+    else if( nUOMAngle == 9104 )                        // Arc-second.
     {
-        dfAngle = CPLAtof(pszAngle) / 3600;
+        dfAngle = CPLAtof(pszAngle) / 3600.0;
     }
-    else /* decimal degrees ... some cases missing but seemingly never used */
+    else  // Decimal degrees.  Some cases missing, but seemingly never used.
     {
         CPLAssert( nUOMAngle == 9102 || nUOMAngle == 0 );
 
@@ -203,9 +218,9 @@ static bool EPSGGetUOMAngleInfo( int nUOMAngleCode,
                                  double * pdfInDegrees )
 
 {
-    /* We do a special override of some of the DMS formats name */
-    /* This will also solve accuracy problems when computing */
-    /* the dfInDegree value from the CSV values (#3643) */
+    // We do a special override of some of the DMS formats name
+    // This will also solve accuracy problems when computing
+    // the dfInDegree value from the CSV values (#3643).
     if( nUOMAngleCode == 9102 || nUOMAngleCode == 9107
         || nUOMAngleCode == 9108 || nUOMAngleCode == 9110
         || nUOMAngleCode == 9122 )
@@ -369,7 +384,7 @@ EPSGGetUOMLengthInfo( int nUOMLengthCode,
         const int iCFactorField = CSVGetFileFieldId( uom_filename, "FACTOR_C" );
 
         if( CPLAtof(CSLGetField(papszUnitsRecord, iCFactorField)) > 0.0 )
-            *pdfInMeters = CPLAtof(CSLGetField(papszUnitsRecord,iBFactorField))
+            *pdfInMeters = CPLAtof(CSLGetField(papszUnitsRecord, iBFactorField))
                 / CPLAtof(CSLGetField(papszUnitsRecord, iCFactorField));
         else
             *pdfInMeters = 0.0;
@@ -449,11 +464,11 @@ int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform )
 /*      Fetch the transformation parameters.                            */
 /* -------------------------------------------------------------------- */
     const int iDXField = CSVGetFileFieldId(pszFilename, "DX");
-    if (iDXField < 0 || CSLCount(papszLine) < iDXField + 7)
+    if( iDXField < 0 || CSLCount(papszLine) < iDXField + 7 )
         return FALSE;
 
     asTransform.resize(0);
-    for(int  iField = 0; iField < 7; iField++ )
+    for( int iField = 0; iField < 7; iField++ )
     {
         const char* pszValue = papszLine[iDXField+iField];
         if( pszValue[0] )
@@ -491,8 +506,8 @@ EPSGGetPMInfo( int nPMCode, char ** ppszName, double *pdfOffset )
 /* -------------------------------------------------------------------- */
 /*      Use a special short cut for Greenwich, since it is so common.   */
 /* -------------------------------------------------------------------- */
-    /* FIXME? Where does 7022 come from ? Let's keep it just in case */
-    /* 8901 is the official current code for Greenwich */
+    // FIXME? Where does 7022 come from ? Let's keep it just in case
+    // 8901 is the official current code for Greenwich.
     if( nPMCode == 7022 /* PM_Greenwich */ || nPMCode == 8901 )
     {
         if( pdfOffset != NULL )
@@ -559,7 +574,7 @@ EPSGGetGCSInfo( int nGCSCode, char ** ppszName,
 /* -------------------------------------------------------------------- */
 /*      Search the database for the corresponding datum code.           */
 /* -------------------------------------------------------------------- */
-    const char  *pszFilename = CSVFilename("gcs.override.csv");
+    const char *pszFilename = CSVFilename("gcs.override.csv");
     char szSearchKey[24] = { '\0' };
     snprintf( szSearchKey, sizeof(szSearchKey), "%d", nGCSCode );
 
@@ -705,7 +720,7 @@ OSRGetEllipsoidInfo( int nCode, char ** ppszName,
                                              CC_Integer,
                                              "UOM_CODE" ));
     double dfToMeters = 1.0;
-    if ( !EPSGGetUOMLengthInfo( nUOMLength, NULL, &dfToMeters ) )
+    if( !EPSGGetUOMLengthInfo( nUOMLength, NULL, &dfToMeters ) )
     {
         dfToMeters = 1.0;
     }
@@ -753,7 +768,7 @@ OSRGetEllipsoidInfo( int nCode, char ** ppszName,
     return OGRERR_NONE;
 }
 
-static const int CoLatConeAxis =        1036; /* see #4223 */
+static const int CoLatConeAxis =        1036;  // See #4223.
 static const int NatOriginLat =         8801;
 static const int NatOriginLong =        8802;
 static const int NatOriginScaleFactor = 8805;
@@ -824,7 +839,7 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
 /* -------------------------------------------------------------------- */
 /*      Get the parameters for this projection.                         */
 /* -------------------------------------------------------------------- */
-    double adfProjParms[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+    double adfProjParms[7] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
 
     for( int i = 0; i < 7; i++ )
     {
@@ -865,7 +880,9 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
             nUOM = 9201;
 
         if( nUOM >= 9100 && nUOM < 9200 )
+        {
             adfProjParms[i] = EPSGAngleStringToDD( pszValue, nUOM );
+        }
         else if( nUOM > 9000 && nUOM < 9100 )
         {
             double dfInMeters = 0.0;
@@ -874,11 +891,11 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
                 dfInMeters = 1.0;
             adfProjParms[i] = CPLAtof(pszValue) * dfInMeters;
         }
-        else if( EQUAL(pszValue,"") ) /* null field */
+        else if( EQUAL(pszValue, "") )  // Null field.
         {
             adfProjParms[i] = 0.0;
         }
-        else /* really we should consider looking up other scaling factors */
+        else // Really, should consider looking up other scaling factors.
         {
             if( nUOM != 9201 )
                 CPLDebug( "OGR",
@@ -905,7 +922,6 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
     return true;
 }
 
-
 /************************************************************************/
 /*                           EPSGGetPCSInfo()                           */
 /************************************************************************/
@@ -913,7 +929,8 @@ EPSGGetProjTRFInfo( int nPCS, int * pnProjMethod,
 static bool
 EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
                 int *pnUOMLengthCode, int *pnUOMAngleCode,
-                int *pnGeogCS, int *pnTRFCode, int *pnCoordSysCode )
+                int *pnGeogCS, int *pnTRFCode, int *pnCoordSysCode,
+                double* adfTOWGS84 )
 
 {
 
@@ -924,8 +941,8 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
     const char *pszFilename = CSVFilename( "pcs.override.csv" );
     char szSearchKey[24] = { '\0' };
     snprintf( szSearchKey, sizeof(szSearchKey), "%d", nPCSCode );
-    char  **papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
-                                             szSearchKey, CC_Integer );
+    char **papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
+                                            szSearchKey, CC_Integer );
 
     if( papszRecord == NULL )
     {
@@ -933,7 +950,6 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
         snprintf( szSearchKey, sizeof(szSearchKey), "%d", nPCSCode );
         papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
                                          szSearchKey, CC_Integer );
-
     }
 
     if( papszRecord == NULL )
@@ -967,7 +983,7 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
     {
         const char *pszValue =
             CSLGetField( papszRecord,
-                         CSVGetFileFieldId(pszFilename,"UOM_CODE"));
+                         CSVGetFileFieldId(pszFilename, "UOM_CODE"));
         if( atoi(pszValue) > 0 )
             *pnUOMLengthCode = atoi(pszValue);
         else
@@ -981,7 +997,7 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
     {
         const char *pszValue =
             CSLGetField( papszRecord,
-                         CSVGetFileFieldId(pszFilename,"UOM_ANGLE_CODE") );
+                         CSVGetFileFieldId(pszFilename, "UOM_ANGLE_CODE") );
 
         if( atoi(pszValue) > 0 )
             *pnUOMAngleCode = atoi(pszValue);
@@ -996,7 +1012,7 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
     {
         const char *pszValue =
             CSLGetField( papszRecord,
-                         CSVGetFileFieldId(pszFilename,"SOURCE_GEOGCRS_CODE"));
+                         CSVGetFileFieldId(pszFilename, "SOURCE_GEOGCRS_CODE"));
         if( atoi(pszValue) > 0 )
             *pnGeogCS = atoi(pszValue);
         else
@@ -1010,7 +1026,7 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
     {
         const char *pszValue =
             CSLGetField( papszRecord,
-                         CSVGetFileFieldId(pszFilename,"COORD_OP_CODE"));
+                         CSVGetFileFieldId(pszFilename, "COORD_OP_CODE"));
 
         if( atoi(pszValue) > 0 )
             *pnTRFCode = atoi(pszValue);
@@ -1028,6 +1044,23 @@ EPSGGetPCSInfo( int nPCSCode, char **ppszEPSGName,
     if( pnCoordSysCode != NULL )
         *pnCoordSysCode = nCSC;
 
+/* -------------------------------------------------------------------- */
+/*      Get the TOWGS84 (override) parameters                           */
+/* -------------------------------------------------------------------- */
+
+    const char *pszDX =
+        CSLGetField( papszRecord, CSVGetFileFieldId(pszFilename, "DX"));
+    if( pszDX[0] != '\0' )
+    {
+        adfTOWGS84[0] = CPLAtof(pszDX);
+        adfTOWGS84[1] = CPLAtof(CSLGetField( papszRecord, CSVGetFileFieldId(pszFilename, "DY")));
+        adfTOWGS84[2] = CPLAtof(CSLGetField( papszRecord, CSVGetFileFieldId(pszFilename, "DZ")));
+        adfTOWGS84[3] = CPLAtof(CSLGetField( papszRecord, CSVGetFileFieldId(pszFilename, "RX")));
+        adfTOWGS84[4] = CPLAtof(CSLGetField( papszRecord, CSVGetFileFieldId(pszFilename, "RY")));
+        adfTOWGS84[5] = CPLAtof(CSLGetField( papszRecord, CSVGetFileFieldId(pszFilename, "RZ")));
+        adfTOWGS84[6] = CPLAtof(CSLGetField( papszRecord, CSVGetFileFieldId(pszFilename, "DS")));
+    }
+
     return true;
 }
 
@@ -1078,7 +1111,7 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
         papszAxis1 = CSLDuplicate( papszRecord );
         papszRecord = CSVGetNextLine( pszFilename );
         if( CSLCount(papszRecord) > 0
-            && EQUAL(papszRecord[0],papszAxis1[0]) )
+            && EQUAL(papszRecord[0], papszAxis1[0]) )
             papszAxis2 = CSLDuplicate( papszRecord );
     }
 
@@ -1105,15 +1138,15 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
     const int iAxisNameCodeField =
         CSVGetFileFieldId( pszFilename, "coord_axis_name_code" );
 
-    /* Check that all fields are available and that the axis_order field */
-    /* is the one with highest index */
-    if ( !( iAxisOrientationField >= 0 &&
-            iAxisOrientationField < iAxisOrderField &&
-            iAxisAbbrevField >= 0 &&
-            iAxisAbbrevField < iAxisOrderField &&
-            iAxisOrderField >= 0 &&
-            iAxisNameCodeField >= 0 &&
-            iAxisNameCodeField < iAxisOrderField ) )
+    // Check that all fields are available and that the axis_order field
+    // is the one with highest index.
+    if( !(iAxisOrientationField >= 0 &&
+          iAxisOrientationField < iAxisOrderField &&
+          iAxisAbbrevField >= 0 &&
+          iAxisAbbrevField < iAxisOrderField &&
+          iAxisOrderField >= 0 &&
+          iAxisNameCodeField >= 0 &&
+          iAxisNameCodeField < iAxisOrderField) )
     {
         CSLDestroy( papszAxis1 );
         CSLDestroy( papszAxis2 );
@@ -1153,19 +1186,20 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
 
     for( int iAO = 0; iAO < 7; iAO++ )
     {
+        const OGRAxisOrientation eAO = static_cast<OGRAxisOrientation>(iAO);
         if( EQUAL(papszAxis1[iAxisOrientationField],
-                  OSRAxisEnumToName((OGRAxisOrientation) iAO)) )
-            eOAxis1 = (OGRAxisOrientation) iAO;
+                  OSRAxisEnumToName(eAO)) )
+            eOAxis1 = eAO;
         if( EQUAL(papszAxis2[iAxisOrientationField],
-                  OSRAxisEnumToName((OGRAxisOrientation) iAO)) )
-            eOAxis2 = (OGRAxisOrientation) iAO;
+                  OSRAxisEnumToName(eAO)) )
+            eOAxis2 = eAO;
 
         if( eOAxis1 == OAO_Other
             && anCodes[iAO] == atoi(papszAxis1[iAxisNameCodeField]) )
-            eOAxis1 = (OGRAxisOrientation) iAO;
+            eOAxis1 = eAO;
         if( eOAxis2 == OAO_Other
             && anCodes[iAO] == atoi(papszAxis2[iAxisNameCodeField]) )
-            eOAxis2 = (OGRAxisOrientation) iAO;
+            eOAxis2 = eAO;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1178,13 +1212,13 @@ static OGRErr SetEPSGAxisInfo( OGRSpatialReference *poSRS,
 
     for( int iAO = 0; iAO < 2; iAO++ )
     {
-        if( EQUAL(apszAxisName[iAO],"N") )
+        if( EQUAL(apszAxisName[iAO], "N") )
             apszAxisName[iAO] = "Northing";
-        else if( EQUAL(apszAxisName[iAO],"E") )
+        else if( EQUAL(apszAxisName[iAO], "E") )
             apszAxisName[iAO] = "Easting";
-        else if( EQUAL(apszAxisName[iAO],"S") )
+        else if( EQUAL(apszAxisName[iAO], "S") )
             apszAxisName[iAO] = "Southing";
-        else if( EQUAL(apszAxisName[iAO],"W") )
+        else if( EQUAL(apszAxisName[iAO], "W") )
             apszAxisName[iAO] = "Westing";
     }
 
@@ -1381,8 +1415,7 @@ static double OGR_FetchParm( double *padfProjParms,
     return dfResult;
 }
 
-#define OGR_FP(x) OGR_FetchParm( adfProjParms, anParmIds, (x), \
-                                 dfFromGreenwich )
+#define OGR_FP(x) OGR_FetchParm(adfProjParms, anParmIds, (x), dfFromGreenwich)
 
 /************************************************************************/
 /*                           SetEPSGProjCS()                            */
@@ -1397,10 +1430,17 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
     int nTRFCode = 0;
     int nCSC = 0;
     char *pszPCSName = NULL;
+    double adfTOWGS84[7] = { std::numeric_limits<double>::infinity(),
+                             std::numeric_limits<double>::infinity(),
+                             std::numeric_limits<double>::infinity(),
+                             std::numeric_limits<double>::infinity(),
+                             std::numeric_limits<double>::infinity(),
+                             std::numeric_limits<double>::infinity(),
+                             std::numeric_limits<double>::infinity() };
 
     if( !EPSGGetPCSInfo( nPCSCode, &pszPCSName,
                          &nUOMLength, &nUOMAngleCode,
-                         &nGCSCode, &nTRFCode, &nCSC ) )
+                         &nGCSCode, &nTRFCode, &nCSC, adfTOWGS84 ) )
     {
         CPLFree(pszPCSName);
         return OGRERR_UNSUPPORTED_SRS;
@@ -1418,6 +1458,21 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
         return nErr;
     }
 
+/* -------------------------------------------------------------------- */
+/*      Set overridden TOWGS84 parameters                               */
+/* -------------------------------------------------------------------- */
+    if( adfTOWGS84[0] != std::numeric_limits<double>::infinity() )
+    {
+        poSRS->SetTOWGS84( adfTOWGS84[0],
+                           adfTOWGS84[1],
+                           adfTOWGS84[2],
+                           adfTOWGS84[3],
+                           adfTOWGS84[4],
+                           adfTOWGS84[5],
+                           adfTOWGS84[6] );
+    }
+
+    // Used by OGR_FP macro
     const double dfFromGreenwich = poSRS->GetPrimeMeridian();
 
 /* -------------------------------------------------------------------- */
@@ -1442,8 +1497,8 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
 /*      Set projection and parameters.                                  */
 /* -------------------------------------------------------------------- */
     int nProjMethod = 0;
-    int anParmIds[7] = { 0 };
-    double adfProjParms[7] = { 0.0 };
+    int anParmIds[7] = {};
+    double adfProjParms[7] = {};
 
     if( !EPSGGetProjTRFInfo( nPCSCode, &nProjMethod, anParmIds, adfProjParms ))
         return OGRERR_UNSUPPORTED_SRS;
@@ -1451,7 +1506,7 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
     switch( nProjMethod )
     {
       case 9801:
-      case 9817: /* really LCC near conformal */
+      case 9817:  // Really LCC near conformal.
         poSRS->SetLCC1SP( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
                           OGR_FP( NatOriginScaleFactor ),
                           OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
@@ -1479,8 +1534,8 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
         break;
 
       case 9804:
-      case 9841: /* Mercator 1SP (Spherical) */
-      case 1024: /* Google Mercator */
+      case 9841:  // Mercator 1SP (Spherical).
+      case 1024:  // Google Mercator.
         poSRS->SetMercator( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
                             OGR_FP( NatOriginScaleFactor ),
                             OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
@@ -1545,9 +1600,8 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
         break;
       }
       case 9814:
-        /* NOTE: This is no longer used!  Swiss Oblique Mercator gets
-        ** implemented using 9815 instead.
-        */
+        // NOTE: This is no longer used.  Swiss Oblique Mercator gets
+        // implemented using 9815 instead.
         poSRS->SetSOC( OGR_FP( ProjCenterLat ), OGR_FP( ProjCenterLong ),
                        OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
@@ -1572,15 +1626,15 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
                              OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
-      case 1041: /* used by EPSG:5514 */
+      case 1041:  // Used by EPSG:5514.
       case 9819:
       {
           double dfCenterLong = OGR_FP( ProjCenterLong );
 
-          if( dfCenterLong == 0.0 ) // See ticket #2559
+          if( dfCenterLong == 0.0 )  // See ticket #2559.
               dfCenterLong = OGR_FP( PolarLongOrigin );
 
-          double dfAzimuth = OGR_FP( CoLatConeAxis ); // See ticket #4223
+          double dfAzimuth = OGR_FP( CoLatConeAxis );  // See ticket #4223.
           if( dfAzimuth == 0.0 )
               dfAzimuth = OGR_FP( Azimuth );
 
@@ -1594,20 +1648,20 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
       break;
 
       case 9820:
-      case 1027: /* used by EPSG:2163, 3408, 3409, 3973 and 3974 */
+      case 1027:  // Used by EPSG:2163, 3408, 3409, 3973 and 3974.
         poSRS->SetLAEA( OGR_FP( NatOriginLat ), OGR_FP( NatOriginLong ),
                         OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
-      case 9821: /* DEPRECATED : this is the spherical form, and really needs different
-                    equations which give different results but PROJ.4 doesn't
-                    seem to support the spherical form. */
+      case 9821: // DEPRECATED : this is the spherical form, and really needs
+                 // different equations which give different results but PROJ.4
+                 // doesn't seem to support the spherical form.
         poSRS->SetLAEA( OGR_FP( SphericalOriginLat ),
                         OGR_FP( SphericalOriginLong ),
                         OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
-      case 9822: /* Albers (Conic) Equal Area */
+      case 9822:  // Albers (Conic) Equal Area.
         poSRS->SetACEA( OGR_FP( StdParallel1Lat ),
                         OGR_FP( StdParallel2Lat ),
                         OGR_FP( FalseOriginLat ),
@@ -1616,7 +1670,7 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
                         OGR_FP( FalseOriginNorthing ) );
         break;
 
-      case 9823: /* Equidistant Cylindrical / Plate Carre / Equirectangular */
+      case 9823:  // Equidistant Cylindrical / Plate Carre / Equirectangular.
       case 9842:
       case 1028:
       case 1029:
@@ -1625,14 +1679,14 @@ static OGRErr SetEPSGProjCS( OGRSpatialReference * poSRS, int nPCSCode )
                                    0.0, 0.0 );
         break;
 
-      case 9829: /* Polar Stereographic (Variant B) */
+      case 9829:  // Polar Stereographic (Variant B).
         poSRS->SetPS( OGR_FP( PolarLatStdParallel ), OGR_FP(PolarLongOrigin),
                       1.0,
                       OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
 
-      case 9834: /* Lambert Cylindrical Equal Area (Spherical) bug #2659 */
-      case 9835: /* Lambert Cylindrical Equal Area (Ellipsoidal) */
+      case 9834: // Lambert Cylindrical Equal Area (Spherical) bug #2659.
+      case 9835: // Lambert Cylindrical Equal Area (Ellipsoidal).
         poSRS->SetCEA( OGR_FP( StdParallel1Lat ), OGR_FP( NatOriginLong ),
                        OGR_FP( FalseEasting ), OGR_FP( FalseNorthing ) );
         break;
@@ -1670,8 +1724,8 @@ static OGRErr SetEPSGVertCS( OGRSpatialReference * poSRS, int nVertCSCode )
 /* -------------------------------------------------------------------- */
 /*      Fetch record from the vertcs.csv or override file.              */
 /* -------------------------------------------------------------------- */
-    const char  *pszFilename = CSVFilename( "vertcs.override.csv" );
-    char szSearchKey[24] = { 0 };
+    const char *pszFilename = CSVFilename( "vertcs.override.csv" );
+    char szSearchKey[24] = {};
     snprintf( szSearchKey, sizeof(szSearchKey), "%d", nVertCSCode );
     char **papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
                                      szSearchKey, CC_Integer );
@@ -1702,12 +1756,12 @@ static OGRErr SetEPSGVertCS( OGRSpatialReference * poSRS, int nVertCSCode )
 /* -------------------------------------------------------------------- */
     const char *pszMethod =
         CSLGetField( papszRecord,
-                     CSVGetFileFieldId(pszFilename,"COORD_OP_METHOD_CODE_1"));
-    if( pszMethod && EQUAL(pszMethod,"9665") )
+                     CSVGetFileFieldId(pszFilename, "COORD_OP_METHOD_CODE_1"));
+    if( pszMethod && EQUAL(pszMethod, "9665") )
     {
         const char *pszParm11 =
             CSLGetField( papszRecord,
-                         CSVGetFileFieldId(pszFilename,"PARM_1_1"));
+                         CSVGetFileFieldId(pszFilename, "PARM_1_1"));
 
         poSRS->SetExtension( "VERT_CS|VERT_DATUM", "PROJ4_GRIDS", pszParm11 );
     }
@@ -1723,9 +1777,9 @@ static OGRErr SetEPSGVertCS( OGRSpatialReference * poSRS, int nVertCSCode )
 /* -------------------------------------------------------------------- */
 /*      Set linear units.                                               */
 /* -------------------------------------------------------------------- */
-    int nUOM_CODE = atoi(CSLGetField( papszRecord,
-                                      CSVGetFileFieldId(pszFilename,
-                                                        "UOM_CODE")));
+    const int nUOM_CODE =
+        atoi(CSLGetField( papszRecord,
+                          CSVGetFileFieldId(pszFilename, "UOM_CODE")));
 
     char *pszUOMLengthName = NULL;
     double dfInMeters = 0.0;
@@ -1761,7 +1815,7 @@ static OGRErr SetEPSGCompdCS( OGRSpatialReference * poSRS, int nCCSCode )
 /* -------------------------------------------------------------------- */
 /*      Fetch record from the compdcs.csv or override file.             */
 /* -------------------------------------------------------------------- */
-    char szSearchKey[24] = { 0 };
+    char szSearchKey[24] = {};
     snprintf( szSearchKey, sizeof(szSearchKey), "%d", nCCSCode );
 
 // So far no override file needed.
@@ -1770,7 +1824,7 @@ static OGRErr SetEPSGCompdCS( OGRSpatialReference * poSRS, int nCCSCode )
 //                                     szSearchKey, CC_Integer );
 
     //if( papszRecord == NULL )
-    const char  *pszFilename = CSVFilename( "compdcs.csv" );
+    const char *pszFilename = CSVFilename( "compdcs.csv" );
     char **papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
                                             szSearchKey, CC_Integer );
 
@@ -1781,12 +1835,14 @@ static OGRErr SetEPSGCompdCS( OGRSpatialReference * poSRS, int nCCSCode )
 /*      Fetch subinformation now before anything messes with the        */
 /*      last loaded record.                                             */
 /* -------------------------------------------------------------------- */
-    int nPCSCode = atoi(CSLGetField( papszRecord,
-                                     CSVGetFileFieldId(pszFilename,
-                                                       "CMPD_HORIZCRS_CODE")));
-    int nVertCSCode = atoi(CSLGetField( papszRecord,
-                                        CSVGetFileFieldId(pszFilename,
-                                                          "CMPD_VERTCRS_CODE")));
+    const int nPCSCode =
+        atoi(CSLGetField( papszRecord,
+                          CSVGetFileFieldId(pszFilename,
+                                            "CMPD_HORIZCRS_CODE")));
+    const int nVertCSCode =
+        atoi(CSLGetField( papszRecord,
+                          CSVGetFileFieldId(pszFilename,
+                                            "CMPD_VERTCRS_CODE")));
 
 /* -------------------------------------------------------------------- */
 /*      Set the COMPD_CS node with a name.                              */
@@ -1845,7 +1901,7 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 /* -------------------------------------------------------------------- */
 /*      Fetch record from the geoccs.csv or override file.              */
 /* -------------------------------------------------------------------- */
-    char szSearchKey[24] = { 0 };
+    char szSearchKey[24] = {};
     snprintf( szSearchKey, sizeof(szSearchKey), "%d", nGCSCode );
 
 // So far no override file needed.
@@ -1853,7 +1909,7 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 //    papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
 //                                     szSearchKey, CC_Integer );
 
-    //if( papszRecord == NULL )
+    // if( papszRecord == NULL )
     const char *pszFilename = CSVFilename( "geoccs.csv" );
     char **papszRecord = CSVScanFileByName( pszFilename, "COORD_REF_SYS_CODE",
                                             szSearchKey, CC_Integer );
@@ -1877,11 +1933,10 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
                                                                "DATUM_CODE")));
 
     char *pszDatumName =
-        CPLStrdup( CSLGetField( papszRecord,
-                                CSVGetFileFieldId(pszFilename,"DATUM_NAME") ) );
+        CPLStrdup( CSLGetField(papszRecord,
+                               CSVGetFileFieldId(pszFilename, "DATUM_NAME")) );
     OGREPSGDatumNameMassage( &pszDatumName );
 
-
     const int nEllipsoidCode = atoi(CSLGetField(
         papszRecord, CSVGetFileFieldId(pszFilename, "ELLIPSOID_CODE")));
 
@@ -1905,7 +1960,8 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 /*      Get the ellipsoid information.                                  */
 /* -------------------------------------------------------------------- */
     char *pszEllipsoidName = NULL;
-    double dfSemiMajor, dfInvFlattening;
+    double dfSemiMajor = 0.0;
+    double dfInvFlattening = 0.0;
 
     if( OSRGetEllipsoidInfo( nEllipsoidCode, &pszEllipsoidName,
                              &dfSemiMajor, &dfInvFlattening ) != OGRERR_NONE )
@@ -1921,7 +1977,7 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
     OGR_SRSNode *poSpheroid = new OGR_SRSNode( "SPHEROID" );
     poSpheroid->AddChild( new OGR_SRSNode( pszEllipsoidName ) );
 
-    char szValue[128] = { 0 };
+    char szValue[128] = {};
     OGRsnPrintDouble( szValue, sizeof(szValue), dfSemiMajor );
     poSpheroid->AddChild( new OGR_SRSNode(szValue) );
 
@@ -1963,13 +2019,14 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
 #if 0
     if( EPSGGetWGS84Transform( nGeogCS, adfBursaTransform ) )
     {
-        char szValue[100] = { 0 };
+        char szValue[100] = {};
 
         OGR_SRSNode *poWGS84 = new OGR_SRSNode( "TOWGS84" );
 
         for( int iCoeff = 0; iCoeff < 7; iCoeff++ )
         {
-            CPLsnprintf( szValue, sizeof(szValue), "%g", adfBursaTransform[iCoeff] );
+            CPLsnprintf( szValue, sizeof(szValue),
+                         "%g", adfBursaTransform[iCoeff] );
             poWGS84->AddChild( new OGR_SRSNode( szValue ) );
         }
 
@@ -2026,10 +2083,6 @@ static OGRErr SetEPSGGeocCS( OGRSpatialReference * poSRS, int nGCSCode )
     poSRS->SetAuthority( "DATUM", "EPSG", nDatumCode );
     poSRS->SetAuthority( "SPHEROID", "EPSG", nEllipsoidCode );
     poSRS->SetAuthority( "PRIMEM", "EPSG", nPMCode );
-
-//    if( nUOMAngle > 0 )
-//        poSRS->SetAuthority( "GEOGCS|UNIT", "EPSG", nUOMAngle );
-
     poSRS->SetAuthority( "GEOCCS", "EPSG", nGCSCode );
 
     return OGRERR_NONE;
@@ -2084,7 +2137,7 @@ OGRErr OGRSpatialReference::importFromEPSG( int nCode )
             poGEOGCS->StripNodes( "AXIS" );
 
         OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-        if (poPROJCS != NULL && EPSGTreatsAsNorthingEasting())
+        if( poPROJCS != NULL && EPSGTreatsAsNorthingEasting() )
             poPROJCS->StripNodes( "AXIS" );
     }
 
@@ -2120,12 +2173,13 @@ OGRErr CPL_STDCALL OSRImportFromEPSG( OGRSpatialReferenceH hSRS, int nCode )
  * This method will initialize the spatial reference based on the
  * passed in EPSG GCS or PCS code.
  *
- * This method is similar to importFromEPSG() except that EPSG preferred
- * axis ordering *will* be applied for geographic and projected coordinate systems.
- * EPSG normally defines geographic coordinate systems to use lat/long, and
- * also there are also a few projected coordinate systems that use northing/easting
- * order contrary to typical GIS use).  See OGRSpatialReference::importFromEPSG()
- * for more details on operation of this method.
+ * This method is similar to importFromEPSG() except that EPSG preferred axis
+ * ordering *will* be applied for geographic and projected coordinate systems.
+ * EPSG normally defines geographic coordinate systems to use lat/long, and also
+ * there are also a few projected coordinate systems that use northing/easting
+ * order contrary to typical GIS use).  See
+ * OGRSpatialReference::importFromEPSG() for more details on operation of this
+ * method.
  *
  * This method is the same as the C function OSRImportFromEPSGA().
  *
@@ -2137,6 +2191,10 @@ OGRErr CPL_STDCALL OSRImportFromEPSG( OGRSpatialReferenceH hSRS, int nCode )
 OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 
 {
+    const int nCodeIn = nCode;
+    // HACK to support 3D WGS84
+    if( nCode == 4979 )
+        nCode = 4326;
     bNormInfoSet = FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -2156,9 +2214,9 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
                            "4269", CC_Integer ) == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Unable to open EPSG support file %s.\n"
-                  "Try setting the GDAL_DATA environment variable to point to the\n"
-                  "directory containing EPSG csv files.",
+                  "Unable to open EPSG support file %s.  "
+                  "Try setting the GDAL_DATA environment variable to point to "
+                  "the directory containing EPSG csv files.",
                   CSVFilename( "gcs.csv" ) );
         return OGRERR_FAILURE;
     }
@@ -2193,12 +2251,12 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
 /* -------------------------------------------------------------------- */
     if( eErr == OGRERR_UNSUPPORTED_SRS )
     {
-        char szWrkDefn[100] = { 0 };
+        char szWrkDefn[100] = {};
         snprintf( szWrkDefn, sizeof(szWrkDefn), "+init=epsg:%d", nCode );
 
         char *pszNormalized = OCTProj4Normalize( szWrkDefn );
 
-        if( strstr(pszNormalized,"proj=") != NULL )
+        if( strstr(pszNormalized, "proj=") != NULL )
             eErr = importFromProj4( pszNormalized );
 
         CPLFree( pszNormalized );
@@ -2215,13 +2273,12 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
     else
         pszAuthName = GetAuthorityName( "GEOGCS" );
 
-
-    if( eErr == OGRERR_NONE && pszAuthName == NULL )
+    if( eErr == OGRERR_NONE && (pszAuthName == NULL || nCode != nCodeIn) )
     {
         if( IsProjected() )
-            SetAuthority( "PROJCS", "EPSG", nCode );
+            SetAuthority( "PROJCS", "EPSG", nCodeIn );
         else if( IsGeographic() )
-            SetAuthority( "GEOGCS", "EPSG", nCode );
+            SetAuthority( "GEOGCS", "EPSG", nCodeIn );
     }
 
 /* -------------------------------------------------------------------- */
@@ -2231,7 +2288,7 @@ OGRErr OGRSpatialReference::importFromEPSGA( int nCode )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "EPSG PCS/GCS code %d not found in EPSG support files.  "
-                  "Is this a valid\nEPSG coordinate system?",
+                  "Is this a valid EPSG coordinate system?",
                   nCode );
     }
 
@@ -2306,18 +2363,18 @@ OGRErr OGRSpatialReference::SetStatePlane( int nZone, int bNAD83,
 /* -------------------------------------------------------------------- */
 /*      Get the index id from stateplane.csv.                           */
 /* -------------------------------------------------------------------- */
-    int nAdjustedId = 0;
-    if( bNAD83 )
-        nAdjustedId = nZone;
-    else
-        nAdjustedId = nZone + 10000;
+
+    if( !bNAD83 && nZone > INT_MAX - 10000 )
+        return OGRERR_FAILURE;
+
+    const int nAdjustedId = bNAD83 ? nZone : nZone + 10000;
 
 /* -------------------------------------------------------------------- */
 /*      Turn this into a PCS code.  We assume there will only be one    */
 /*      PCS corresponding to each Proj_ code since the proj code        */
 /*      already effectively indicates NAD27 or NAD83.                   */
 /* -------------------------------------------------------------------- */
-    char szID[32] = { 0 };
+    char szID[32] = {};
     snprintf( szID, sizeof(szID), "%d", nAdjustedId );
     const int nPCSCode =
         atoi( CSVGetField( CSVFilename( "stateplane.csv" ),
@@ -2331,23 +2388,25 @@ OGRErr OGRSpatialReference::SetStatePlane( int nZone, int bNAD83,
         {
             bFailureReported = true;
             CPLError( CE_Warning, CPLE_OpenFailed,
-                      "Unable to find state plane zone in stateplane.csv,\n"
-                      "likely because the GDAL data files cannot be found.  Using\n"
-                      "incomplete definition of state plane zone.\n" );
+                      "Unable to find state plane zone in stateplane.csv, "
+                      "likely because the GDAL data files cannot be found.  "
+                      "Using incomplete definition of state plane zone." );
         }
 
         Clear();
         if( bNAD83 )
         {
-            char szName[128] = { 0 };
-            snprintf( szName, sizeof(szName), "State Plane Zone %d / NAD83", nZone );
+            char szName[128] = {};
+            snprintf( szName, sizeof(szName),
+                      "State Plane Zone %d / NAD83", nZone );
             SetLocalCS( szName );
             SetLinearUnits( SRS_UL_METER, 1.0 );
         }
         else
         {
-            char szName[128] = { 0 };
-            snprintf( szName, sizeof(szName), "State Plane Zone %d / NAD27", nZone );
+            char szName[128] = {};
+            snprintf( szName, sizeof(szName),
+                      "State Plane Zone %d / NAD27", nZone );
             SetLocalCS( szName );
             SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) );
         }
@@ -2435,14 +2494,16 @@ OGRErr OSRSetStatePlaneWithUnits( OGRSpatialReferenceH hSRS,
 
 /************************************************************************/
 /*                           GetEPSGGeogCS()                            */
-/*                                                                      */
-/*      Try to establish what the EPSG code for this coordinate         */
-/*      systems GEOGCS might be.  Returns -1 if no reasonable guess     */
-/*      can be made.                                                    */
-/*                                                                      */
-/*      TODO: We really need to do some name lookups.                   */
 /************************************************************************/
 
+/** Try to establish what the EPSG code for this coordinate systems
+ * GEOGCS might be.  Returns -1 if no reasonable guess can be made.
+ *
+ * @return EPSG code
+ */
+
+// TODO: We really need to do some name lookups.
+
 int OGRSpatialReference::GetEPSGGeogCS()
 
 {
@@ -2451,7 +2512,7 @@ int OGRSpatialReference::GetEPSGGeogCS()
 /* -------------------------------------------------------------------- */
 /*      Do we already have it?                                          */
 /* -------------------------------------------------------------------- */
-    if( pszAuthName != NULL && EQUAL(pszAuthName,"epsg") )
+    if( pszAuthName != NULL && EQUAL(pszAuthName, "epsg") )
         return atoi(GetAuthorityCode( "GEOGCS" ));
 
 /* -------------------------------------------------------------------- */
@@ -2467,30 +2528,30 @@ int OGRSpatialReference::GetEPSGGeogCS()
 /* -------------------------------------------------------------------- */
 /*      Is this a "well known" geographic coordinate system?            */
 /* -------------------------------------------------------------------- */
-    const int bWGS = strstr(pszGEOGCS,"WGS") != NULL
+    const bool bWGS = strstr(pszGEOGCS, "WGS") != NULL
         || strstr(pszDatum, "WGS")
-        || strstr(pszGEOGCS,"World Geodetic System")
-        || strstr(pszGEOGCS,"World_Geodetic_System")
+        || strstr(pszGEOGCS, "World Geodetic System")
+        || strstr(pszGEOGCS, "World_Geodetic_System")
         || strstr(pszDatum, "World Geodetic System")
         || strstr(pszDatum, "World_Geodetic_System");
 
-    const int bNAD = strstr(pszGEOGCS,"NAD") != NULL
+    const bool bNAD = strstr(pszGEOGCS, "NAD") != NULL
         || strstr(pszDatum, "NAD")
-        || strstr(pszGEOGCS,"North American")
-        || strstr(pszGEOGCS,"North_American")
+        || strstr(pszGEOGCS, "North American")
+        || strstr(pszGEOGCS, "North_American")
         || strstr(pszDatum, "North American")
         || strstr(pszDatum, "North_American");
 
-    if( bWGS && (strstr(pszGEOGCS,"84") || strstr(pszDatum,"84")) )
+    if( bWGS && (strstr(pszGEOGCS, "84") || strstr(pszDatum, "84")) )
         return 4326;
 
-    if( bWGS && (strstr(pszGEOGCS,"72") || strstr(pszDatum,"72")) )
+    if( bWGS && (strstr(pszGEOGCS, "72") || strstr(pszDatum, "72")) )
         return 4322;
 
-    if( bNAD && (strstr(pszGEOGCS,"83") || strstr(pszDatum,"83")) )
+    if( bNAD && (strstr(pszGEOGCS, "83") || strstr(pszDatum, "83")) )
         return 4269;
 
-    if( bNAD && (strstr(pszGEOGCS,"27") || strstr(pszDatum,"27")) )
+    if( bNAD && (strstr(pszGEOGCS, "27") || strstr(pszDatum, "27")) )
         return 4267;
 
 /* -------------------------------------------------------------------- */
@@ -2500,7 +2561,7 @@ int OGRSpatialReference::GetEPSGGeogCS()
     pszAuthName = GetAuthorityName( "GEOGCS|DATUM" );
 
     if( pszAuthName != NULL
-        && EQUAL(pszAuthName,"epsg")
+        && EQUAL(pszAuthName, "epsg")
         && GetPrimeMeridian() == 0.0 )
     {
         const int nDatum = atoi(GetAuthorityCode("GEOGCS|DATUM"));
@@ -2552,42 +2613,78 @@ OGRErr OGRSpatialReference::AutoIdentifyEPSG()
             SetAuthority( "GEOGCS", "EPSG", nGCS );
     }
 
+    if( IsProjected() && GetAuthorityCode( "PROJCS") == NULL )
+    {
+        const char *pszProjection = GetAttrValue( "PROJECTION" );
+
 /* -------------------------------------------------------------------- */
 /*      Is this a UTM coordinate system with a common GEOGCS?           */
 /* -------------------------------------------------------------------- */
-    int nZone = 0;
-    int bNorth = FALSE;
-    if( (nZone = GetUTMZone( &bNorth )) != 0
-        && GetAuthorityCode( "PROJCS") == NULL )
-    {
-        const char *pszAuthName, *pszAuthCode;
+        int nZone = 0;
+        int bNorth = FALSE;
+        if( (nZone = GetUTMZone( &bNorth )) != 0 )
+        {
+            const char *pszAuthName = GetAuthorityName( "PROJCS|GEOGCS" );
+            const char *pszAuthCode = GetAuthorityCode( "PROJCS|GEOGCS" );
 
-        pszAuthName = GetAuthorityName( "PROJCS|GEOGCS" );
-        pszAuthCode = GetAuthorityCode( "PROJCS|GEOGCS" );
+            if( pszAuthName == NULL || pszAuthCode == NULL )
+            {
+                // Don't exactly recognise datum.
+            }
+            else if( EQUAL(pszAuthName, "EPSG") && atoi(pszAuthCode) == 4326 )
+            {
+                // WGS84
+                if( bNorth )
+                    SetAuthority( "PROJCS", "EPSG", 32600 + nZone );
+                else
+                    SetAuthority( "PROJCS", "EPSG", 32700 + nZone );
+            }
+            else if( EQUAL(pszAuthName, "EPSG") && atoi(pszAuthCode) == 4267
+                    && nZone >= 3 && nZone <= 22 && bNorth )
+            {
+                SetAuthority( "PROJCS", "EPSG", 26700 + nZone ); // NAD27
+            }
+            else if( EQUAL(pszAuthName, "EPSG") && atoi(pszAuthCode) == 4269
+                    && nZone >= 3 && nZone <= 23 && bNorth )
+            {
+                SetAuthority( "PROJCS", "EPSG", 26900 + nZone ); // NAD83
+            }
+            else if( EQUAL(pszAuthName, "EPSG") && atoi(pszAuthCode) == 4322 )
+            { // WGS72
+                if( bNorth )
+                    SetAuthority( "PROJCS", "EPSG", 32200 + nZone );
+                else
+                    SetAuthority( "PROJCS", "EPSG", 32300 + nZone );
+            }
+        }
 
-        if( pszAuthName == NULL ||  pszAuthCode == NULL )
+/* -------------------------------------------------------------------- */
+/*      Is this a Polar Stereographic system on WGS 84 ?                */
+/* -------------------------------------------------------------------- */
+        else if ( pszProjection != NULL &&
+                  EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) )
         {
-            /* don't exactly recognise datum */
-        }
-        else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4326 )
-        { // WGS84
-            if( bNorth )
-                SetAuthority( "PROJCS", "EPSG", 32600 + nZone );
-            else
-                SetAuthority( "PROJCS", "EPSG", 32700 + nZone );
-        }
-        else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4267
-                 && nZone >= 3 && nZone <= 22 && bNorth )
-            SetAuthority( "PROJCS", "EPSG", 26700 + nZone ); // NAD27
-        else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4269
-                 && nZone >= 3 && nZone <= 23 && bNorth )
-            SetAuthority( "PROJCS", "EPSG", 26900 + nZone ); // NAD83
-        else if( EQUAL(pszAuthName,"EPSG") && atoi(pszAuthCode) == 4322 )
-        { // WGS72
-            if( bNorth )
-                SetAuthority( "PROJCS", "EPSG", 32200 + nZone );
-            else
-                SetAuthority( "PROJCS", "EPSG", 32300 + nZone );
+            const char *pszAuthName = GetAuthorityName( "PROJCS|GEOGCS" );
+            const char *pszAuthCode = GetAuthorityCode( "PROJCS|GEOGCS" );
+            const double dfLatOrigin = GetNormProjParm(
+                                            SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
+
+            if( pszAuthName != NULL && EQUAL(pszAuthName, "EPSG") &&
+                pszAuthCode != NULL && atoi(pszAuthCode) == 4326 &&
+                fabs( fabs(dfLatOrigin ) - 71.0 ) < 1e-15 &&
+                fabs(GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 )) < 1e-15 &&
+                fabs(GetProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) - 1.0) < 1e-15 &&
+                fabs(GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 )) < 1e-15 &&
+                fabs(GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 )) < 1e-15 &&
+                fabs(GetLinearUnits() - 1.0) < 1e-15 )
+            {
+                if( dfLatOrigin > 0 )
+                    // Arctic Polar Stereographic
+                    SetAuthority( "PROJCS", "EPSG", 3995 );
+                else
+                    // Antarctic Polar Stereographic
+                    SetAuthority( "PROJCS", "EPSG", 3031 );
+            }
         }
     }
 
@@ -2650,7 +2747,7 @@ int OGRSpatialReference::EPSGTreatsAsLatLong()
 
     const char *pszAuth = GetAuthorityName( "GEOGCS" );
 
-    if( pszAuth == NULL || !EQUAL(pszAuth,"EPSG") )
+    if( pszAuth == NULL || !EQUAL(pszAuth, "EPSG") )
         return FALSE;
 
     OGR_SRSNode * const poFirstAxis = GetAttrNode( "GEOGCS|AXIS" );
@@ -2659,7 +2756,7 @@ int OGRSpatialReference::EPSGTreatsAsLatLong()
         return FALSE;
 
     if( poFirstAxis->GetChildCount() >= 2
-        && EQUAL(poFirstAxis->GetChild(1)->GetValue(),"NORTH") )
+        && EQUAL(poFirstAxis->GetChild(1)->GetValue(), "NORTH") )
         return TRUE;
 
     return FALSE;
@@ -2713,7 +2810,7 @@ int OGRSpatialReference::EPSGTreatsAsNorthingEasting()
 
     const char *pszAuth = GetAuthorityName( "PROJCS" );
 
-    if( pszAuth == NULL || !EQUAL(pszAuth,"EPSG") )
+    if( pszAuth == NULL || !EQUAL(pszAuth, "EPSG") )
         return FALSE;
 
     OGR_SRSNode * const poFirstAxis = GetAttrNode( "PROJCS|AXIS" );
@@ -2722,7 +2819,7 @@ int OGRSpatialReference::EPSGTreatsAsNorthingEasting()
         return FALSE;
 
     if( poFirstAxis->GetChildCount() >= 2
-        && EQUAL(poFirstAxis->GetChild(1)->GetValue(),"NORTH") )
+        && EQUAL(poFirstAxis->GetChild(1)->GetValue(), "NORTH") )
         return TRUE;
 
     return FALSE;
diff --git a/ogr/ogr_geocoding.cpp b/ogr/ogr_geocoding.cpp
index 736e7d9..56128df 100644
--- a/ogr/ogr_geocoding.cpp
+++ b/ogr/ogr_geocoding.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_geocoding.cpp 33757 2016-03-20 20:22:33Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Client of geocoding service.
@@ -27,57 +26,67 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_geocoding.h"
+
+#include <cstddef>
+#include <cstring>
+#include <string>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_http.h"
-#include "cpl_multiproc.h"
 #include "cpl_minixml.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
+#include "ogr_mem.h"
+#include "ogrsf_frmts.h"
 
-/* Emulation of gettimeofday() for Windows */
+
+// Emulation of gettimeofday() for Windows.
 #ifdef WIN32
 
 #include <time.h>
 #include <windows.h>
 
-/* Recent mingw define struct timezone */
+// Recent mingw define struct timezone.
 #if !(defined(__GNUC__) && defined(_TIMEZONE_DEFINED))
 struct timezone
 {
-  int  tz_minuteswest; /* minutes W of Greenwich */
-  int  tz_dsttime;     /* type of DST correction */
+    int tz_minuteswest; // Minutes W of Greenwich.
+    int tz_dsttime;     // Type of DST correction.
 };
 #endif
 
-#define MICROSEC_IN_SEC   1000000
+static const int MICROSEC_IN_SEC = 1000000;
 
 static
-int OGR_gettimeofday(struct timeval *tv, CPL_UNUSED struct timezone *tzIgnored)
+int OGR_gettimeofday( struct timeval *tv, struct timezone * /* tzIgnored */ )
 {
     FILETIME ft;
     GetSystemTimeAsFileTime(&ft);
 
-    /* In 100-nanosecond intervals since January 1, 1601 (UTC). */
+    // In 100-nanosecond intervals since January 1, 1601 (UTC).
     GUIntBig nVal = (((GUIntBig)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
-    nVal /= 10; /* to microseconds */
-    /* There are 11 644 473 600 seconds between 1601 and 1970 */
-    nVal -= ((GUIntBig)116444736) * 100 * MICROSEC_IN_SEC;
-    tv->tv_sec = (long)(nVal / MICROSEC_IN_SEC);
-    tv->tv_usec = (long)(nVal % MICROSEC_IN_SEC);
+    nVal /= 10;  // To microseconds.
+    // There are 11 644 473 600 seconds between 1601 and 1970.
+    nVal -= static_cast<GUIntBig>(116444736) * 100 * MICROSEC_IN_SEC;
+    tv->tv_sec = static_cast<long>(nVal / MICROSEC_IN_SEC);
+    tv->tv_usec = static_cast<long>(nVal % MICROSEC_IN_SEC);
 
     return 0;
 }
 
 #define gettimeofday OGR_gettimeofday
 
-#else
+#else  // !defined WIN32
 #include <sys/time.h>
-#endif
-
-
-#include "ogr_geocoding.h"
-#include "ogr_mem.h"
-#include "ogrsf_frmts.h"
+#endif  // WIN32
 
-CPL_CVSID("$Id: ogr_geocoding.cpp 33757 2016-03-20 20:22:33Z goatbar $");
+CPL_CVSID("$Id: ogr_geocoding.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 struct _OGRGeocodingSessionHS
 {
@@ -90,8 +99,8 @@ struct _OGRGeocodingSessionHS
     char*  pszLanguage;
     char*  pszQueryTemplate;
     char*  pszReverseQueryTemplate;
-    int    bReadCache;
-    int    bWriteCache;
+    bool   bReadCache;
+    bool   bWriteCache;
     double dfDelayBetweenQueries;
     OGRDataSource* poDS;
 };
@@ -100,33 +109,43 @@ static CPLMutex* hMutex = NULL;
 static double dfLastQueryTimeStampOSMNominatim = 0.0;
 static double dfLastQueryTimeStampMapQuestNominatim = 0.0;
 
-#define OSM_NOMINATIM_QUERY      "http://nominatim.openstreetmap.org/search?q=%s&format=xml&polygon_text=1"
-#define MAPQUEST_NOMINATIM_QUERY "http://open.mapquestapi.com/nominatim/v1/search.php?q=%s&format=xml"
-#define YAHOO_QUERY              "http://where.yahooapis.com/geocode?q=%s"
-#define GEONAMES_QUERY           "http://api.geonames.org/search?q=%s&style=LONG"
-#define BING_QUERY               "http://dev.virtualearth.net/REST/v1/Locations?q=%s&o=xml"
-
-#define OSM_NOMINATIM_REVERSE_QUERY      "http://nominatim.openstreetmap.org/reverse?format=xml&lat={lat}&lon={lon}"
-#define MAPQUEST_NOMINATIM_REVERSE_QUERY "http://open.mapquestapi.com/nominatim/v1/reverse.php?format=xml&lat={lat}&lon={lon}"
-#define YAHOO_REVERSE_QUERY              "http://where.yahooapis.com/geocode?q={lat},{lon}&gflags=R"
-#define GEONAMES_REVERSE_QUERY           "http://api.geonames.org/findNearby?lat={lat}&lng={lon}&style=LONG"
-#define BING_REVERSE_QUERY               "http://dev.virtualearth.net/REST/v1/Locations/{lat},{lon}?includeEntityTypes=countryRegion&o=xml"
-
-#define CACHE_LAYER_NAME         "ogr_geocode_cache"
-#define DEFAULT_CACHE_SQLITE     "ogr_geocode_cache.sqlite"
-#define DEFAULT_CACHE_CSV        "ogr_geocode_cache.csv"
-
-#define FIELD_URL                "url"
-#define FIELD_BLOB               "blob"
-
+static const char OSM_NOMINATIM_QUERY[] =
+    "http://nominatim.openstreetmap.org/search?q=%s&format=xml&polygon_text=1";
+static const char MAPQUEST_NOMINATIM_QUERY[] =
+    "http://open.mapquestapi.com/nominatim/v1/search.php?q=%s&format=xml";
+static const char YAHOO_QUERY[] = "http://where.yahooapis.com/geocode?q=%s";
+static const char GEONAMES_QUERY[] =
+    "http://api.geonames.org/search?q=%s&style=LONG";
+static const char BING_QUERY[] =
+    "http://dev.virtualearth.net/REST/v1/Locations?q=%s&o=xml";
+
+static const char OSM_NOMINATIM_REVERSE_QUERY[] =
+    "http://nominatim.openstreetmap.org/reverse?format=xml&lat={lat}&lon={lon}";
+static const char MAPQUEST_NOMINATIM_REVERSE_QUERY[] =
+    "http://open.mapquestapi.com/nominatim/v1/"
+    "reverse.php?format=xml&lat={lat}&lon={lon}";
+static const char YAHOO_REVERSE_QUERY[] =
+    "http://where.yahooapis.com/geocode?q={lat},{lon}&gflags=R";
+static const char GEONAMES_REVERSE_QUERY[] =
+    "http://api.geonames.org/findNearby?lat={lat}&lng={lon}&style=LONG";
+static const char BING_REVERSE_QUERY[] =
+    "http://dev.virtualearth.net/REST/v1/Locations/"
+    "{lat},{lon}?includeEntityTypes=countryRegion&o=xml";
+
+static const char CACHE_LAYER_NAME[] = "ogr_geocode_cache";
+static const char DEFAULT_CACHE_SQLITE[] = "ogr_geocode_cache.sqlite";
+static const char DEFAULT_CACHE_CSV[] = "ogr_geocode_cache.csv";
+
+static const char FIELD_URL[] = "url";
+static const char FIELD_BLOB[] = "blob";
 
 /************************************************************************/
 /*                       OGRGeocodeGetParameter()                       */
 /************************************************************************/
 
 static
-const char* OGRGeocodeGetParameter(char** papszOptions, const char* pszKey,
-                                   const char* pszDefaultValue)
+const char* OGRGeocodeGetParameter( char** papszOptions, const char* pszKey,
+                                    const char* pszDefaultValue )
 {
     const char* pszRet = CSLFetchNameValue(papszOptions, pszKey);
     if( pszRet != NULL )
@@ -140,12 +159,12 @@ const char* OGRGeocodeGetParameter(char** papszOptions, const char* pszKey,
 /*                      OGRGeocodeHasStringValidFormat()                */
 /************************************************************************/
 
-/* Checks that pszQueryTemplate has one and only one occurrence of %s in it. */
+// Checks that pszQueryTemplate has one and only one occurrence of %s in it.
 static
-int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
+bool OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
 {
     const char* pszIter = pszQueryTemplate;
-    int bValidFormat = TRUE;
+    bool bValidFormat = true;
     bool bFoundPctS = false;
     while( *pszIter != '\0' )
     {
@@ -153,31 +172,30 @@ int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
         {
             if( pszIter[1] == '%' )
             {
-                pszIter ++;
+                ++pszIter;
             }
             else if( pszIter[1] == 's' )
             {
                 if( bFoundPctS )
                 {
-                    bValidFormat = FALSE;
+                    bValidFormat = false;
                     break;
                 }
                 bFoundPctS = true;
             }
             else
             {
-                bValidFormat = FALSE;
+                bValidFormat = false;
                 break;
             }
         }
-        pszIter ++;
+        ++pszIter;
     }
     if( !bFoundPctS )
-        bValidFormat = FALSE;
+        bValidFormat = false;
     return bValidFormat;
 }
 
-
 /************************************************************************/
 /*                       OGRGeocodeCreateSession()                      */
 /************************************************************************/
@@ -214,9 +232,10 @@ int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
  *       SERVICE=OSM_NOMINATIM, MAPQUEST_NOMINATIM, YAHOO, GEONAMES or BING,
  *       the URL template is hard-coded.
  * <li> "REVERSE_QUERY_TEMPLATE": URL template for GET requests for reverse
- *       geocoding. Must contain one and only one occurrence of {lon} and {lat} in it.
- *       If not specified, for SERVICE=OSM_NOMINATIM, MAPQUEST_NOMINATIM, YAHOO,
- *       GEONAMES or BING, the URL template is hard-coded.
+ *       geocoding. Must contain one and only one occurrence of {lon} and {lat}
+ *       in it.  If not specified, for SERVICE=OSM_NOMINATIM,
+ *       MAPQUEST_NOMINATIM, YAHOO, GEONAMES or BING, the URL template is
+ *       hard-coded.
  * </ul>
  *
  * All the above options can also be set by defining the configuration option
@@ -225,16 +244,16 @@ int OGRGeocodeHasStringValidFormat(const char* pszQueryTemplate)
  *
  * @param papszOptions NULL, or a NULL-terminated list of string options.
  *
- * @return an handle that should be freed with OGRGeocodeDestroySession(), or NULL
- *         in case of failure.
+ * @return an handle that should be freed with OGRGeocodeDestroySession(), or
+ *         NULL in case of failure.
  *
  * @since GDAL 1.10
  */
 
-OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
+OGRGeocodingSessionH OGRGeocodeCreateSession( char** papszOptions )
 {
-    OGRGeocodingSessionH hSession =
-        (OGRGeocodingSessionH)CPLCalloc(1, sizeof(_OGRGeocodingSessionHS));
+    OGRGeocodingSessionH hSession = static_cast<OGRGeocodingSessionH>(
+        CPLCalloc(1, sizeof(_OGRGeocodingSessionHS)) );
 
     const char* pszCacheFilename = OGRGeocodeGetParameter(papszOptions,
                                                           "CACHE_FILE",
@@ -263,7 +282,8 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
     const char* pszEmail = OGRGeocodeGetParameter(papszOptions, "EMAIL", NULL);
     hSession->pszEmail = pszEmail ? CPLStrdup(pszEmail) : NULL;
 
-    const char* pszUserName = OGRGeocodeGetParameter(papszOptions, "USERNAME", NULL);
+    const char* pszUserName =
+        OGRGeocodeGetParameter(papszOptions, "USERNAME", NULL);
     hSession->pszUserName = pszUserName ? CPLStrdup(pszUserName) : NULL;
 
     const char* pszKey = OGRGeocodeGetParameter(papszOptions, "KEY", NULL);
@@ -309,9 +329,10 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
         pszQueryTemplateDefault = GEONAMES_QUERY;
     else if( EQUAL(pszGeocodingService, "BING") )
         pszQueryTemplateDefault = BING_QUERY;
-    const char* pszQueryTemplate = OGRGeocodeGetParameter(papszOptions,
-                                                          "QUERY_TEMPLATE",
-                                                          pszQueryTemplateDefault);
+    const char* pszQueryTemplate =
+        OGRGeocodeGetParameter(papszOptions,
+                               "QUERY_TEMPLATE",
+                               pszQueryTemplateDefault);
 
     if( pszQueryTemplate != NULL &&
         !OGRGeocodeHasStringValidFormat(pszQueryTemplate) )
@@ -336,9 +357,10 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
         pszReverseQueryTemplateDefault = GEONAMES_REVERSE_QUERY;
     else if( EQUAL(pszGeocodingService, "BING") )
         pszReverseQueryTemplateDefault = BING_REVERSE_QUERY;
-    const char* pszReverseQueryTemplate = OGRGeocodeGetParameter(papszOptions,
-                                                          "REVERSE_QUERY_TEMPLATE",
-                                                          pszReverseQueryTemplateDefault);
+    const char* pszReverseQueryTemplate =
+        OGRGeocodeGetParameter(papszOptions,
+                               "REVERSE_QUERY_TEMPLATE",
+                               pszReverseQueryTemplateDefault);
 
     if( pszReverseQueryTemplate != NULL &&
         (strstr(pszReverseQueryTemplate, "{lat}") == NULL ||
@@ -367,7 +389,7 @@ OGRGeocodingSessionH OGRGeocodeCreateSession(char** papszOptions)
  *
  * @since GDAL 1.10
  */
-void OGRGeocodeDestroySession(OGRGeocodingSessionH hSession)
+void OGRGeocodeDestroySession( OGRGeocodingSessionH hSession )
 {
     if( hSession == NULL )
         return;
@@ -381,18 +403,17 @@ void OGRGeocodeDestroySession(OGRGeocodingSessionH hSession)
     CPLFree(hSession->pszQueryTemplate);
     CPLFree(hSession->pszReverseQueryTemplate);
     if( hSession->poDS )
-        OGRReleaseDataSource((OGRDataSourceH) hSession->poDS);
+        OGRReleaseDataSource(reinterpret_cast<OGRDataSourceH>(hSession->poDS));
     CPLFree(hSession);
 }
 
-
 /************************************************************************/
 /*                        OGRGeocodeGetCacheLayer()                     */
 /************************************************************************/
 
-static OGRLayer* OGRGeocodeGetCacheLayer(OGRGeocodingSessionH hSession,
-                                         int bCreateIfNecessary,
-                                         int* pnIdxBlob)
+static OGRLayer* OGRGeocodeGetCacheLayer( OGRGeocodingSessionH hSession,
+                                          bool bCreateIfNecessary,
+                                          int* pnIdxBlob )
 {
     OGRDataSource* poDS = hSession->poDS;
     CPLString osExt = CPLGetExtension(hSession->pszCacheFilename);
@@ -402,12 +423,14 @@ static OGRLayer* OGRGeocodeGetCacheLayer(OGRGeocodingSessionH hSession,
         if( OGRGetDriverCount() == 0 )
             OGRRegisterAll();
 
-        bool bHadValue = (CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) != NULL);
+        const bool bHadValue =
+            CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) != NULL;
         std::string oOldVal(CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", ""));
 
         CPLSetThreadLocalConfigOption("OGR_SQLITE_SYNCHRONOUS", "OFF");
 
-        poDS = (OGRDataSource*) OGROpen(hSession->pszCacheFilename, TRUE, NULL);
+        poDS = reinterpret_cast<OGRDataSource *>(
+            OGROpen(hSession->pszCacheFilename, TRUE, NULL) );
         if( poDS == NULL &&
             EQUAL(hSession->pszCacheFilename, DEFAULT_CACHE_SQLITE) )
         {
@@ -445,8 +468,9 @@ static OGRLayer* OGRGeocodeGetCacheLayer(OGRGeocodingSessionH hSession,
                                                    "METADATA", "FALSE");
                 }
 
-                poDS = (OGRDataSource*) OGR_Dr_CreateDataSource(
-                            hDriver, hSession->pszCacheFilename, papszOptions);
+                poDS = reinterpret_cast<OGRDataSource *>(
+                    OGR_Dr_CreateDataSource(
+                        hDriver, hSession->pszCacheFilename, papszOptions));
 
                 if( poDS == NULL &&
                     (EQUAL(osExt, "SQLITE") || EQUAL(osExt, "CSV")))
@@ -456,16 +480,18 @@ static OGRLayer* OGRGeocodeGetCacheLayer(OGRGeocodingSessionH hSession,
                         CPLSPrintf("/vsimem/%s.%s",
                                    CACHE_LAYER_NAME, osExt.c_str()));
                     CPLDebug("OGR", "Switch geocode cache file to %s",
-                         hSession->pszCacheFilename);
-                    poDS = (OGRDataSource*) OGR_Dr_CreateDataSource(
-                            hDriver, hSession->pszCacheFilename, papszOptions);
+                             hSession->pszCacheFilename);
+                    poDS = reinterpret_cast<OGRDataSource *>(
+                        OGR_Dr_CreateDataSource(
+                            hDriver, hSession->pszCacheFilename, papszOptions));
                 }
 
                 CSLDestroy(papszOptions);
             }
         }
 
-        CPLSetThreadLocalConfigOption("OGR_SQLITE_SYNCHRONOUS", bHadValue ? oOldVal.c_str() : NULL);
+        CPLSetThreadLocalConfigOption("OGR_SQLITE_SYNCHRONOUS",
+                                      bHadValue ? oOldVal.c_str() : NULL);
 
         if( poDS == NULL )
             return NULL;
@@ -525,8 +551,8 @@ static OGRLayer* OGRGeocodeGetCacheLayer(OGRGeocodingSessionH hSession,
 /*                        OGRGeocodeGetFromCache()                      */
 /************************************************************************/
 
-static char* OGRGeocodeGetFromCache(OGRGeocodingSessionH hSession,
-                                    const char* pszURL)
+static char* OGRGeocodeGetFromCache( OGRGeocodingSessionH hSession,
+                                     const char* pszURL )
 {
     CPLMutexHolderD(&hMutex);
 
@@ -536,14 +562,15 @@ static char* OGRGeocodeGetFromCache(OGRGeocodingSessionH hSession,
         return NULL;
 
     char* pszSQLEscapedURL = CPLEscapeString(pszURL, -1, CPLES_SQL);
-    poLayer->SetAttributeFilter(CPLSPrintf("%s='%s'", FIELD_URL, pszSQLEscapedURL));
+    poLayer->SetAttributeFilter(
+        CPLSPrintf("%s='%s'", FIELD_URL, pszSQLEscapedURL));
     CPLFree(pszSQLEscapedURL);
 
     char* pszRet = NULL;
     OGRFeature* poFeature = poLayer->GetNextFeature();
     if( poFeature != NULL )
     {
-        if( poFeature->IsFieldSet(nIdxBlob) )
+        if( poFeature->IsFieldSetAndNotNull(nIdxBlob) )
             pszRet = CPLStrdup(poFeature->GetFieldAsString(nIdxBlob));
         OGRFeature::DestroyFeature(poFeature);
     }
@@ -555,9 +582,9 @@ static char* OGRGeocodeGetFromCache(OGRGeocodingSessionH hSession,
 /*                        OGRGeocodePutIntoCache()                      */
 /************************************************************************/
 
-static bool OGRGeocodePutIntoCache(OGRGeocodingSessionH hSession,
-                                  const char* pszURL,
-                                  const char* pszContent)
+static bool OGRGeocodePutIntoCache( OGRGeocodingSessionH hSession,
+                                    const char* pszURL,
+                                    const char* pszContent )
 {
     CPLMutexHolderD(&hMutex);
 
@@ -569,7 +596,7 @@ static bool OGRGeocodePutIntoCache(OGRGeocodingSessionH hSession,
     OGRFeature* poFeature = new OGRFeature(poLayer->GetLayerDefn());
     poFeature->SetField(FIELD_URL, pszURL);
     poFeature->SetField(FIELD_BLOB, pszContent);
-    bool bRet = poLayer->CreateFeature(poFeature) == OGRERR_NONE;
+    const bool bRet = poLayer->CreateFeature(poFeature) == OGRERR_NONE;
     delete poFeature;
 
     return bRet;
@@ -579,7 +606,7 @@ static bool OGRGeocodePutIntoCache(OGRGeocodingSessionH hSession,
 /*                        OGRGeocodeMakeRawLayer()                      */
 /************************************************************************/
 
-static OGRLayerH OGRGeocodeMakeRawLayer(const char* pszContent)
+static OGRLayerH OGRGeocodeMakeRawLayer( const char* pszContent )
 {
     OGRMemLayer* poLayer = new OGRMemLayer( "result", NULL, wkbNone );
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
@@ -589,33 +616,34 @@ static OGRLayerH OGRGeocodeMakeRawLayer(const char* pszContent)
     poFeature->SetField("raw", pszContent);
     CPL_IGNORE_RET_VAL(poLayer->CreateFeature(poFeature));
     delete poFeature;
-    return (OGRLayerH) poLayer;
+    return reinterpret_cast<OGRLayerH>( poLayer );
 }
 
 /************************************************************************/
 /*                  OGRGeocodeBuildLayerNominatim()                     */
 /************************************************************************/
 
-static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
-                                               CPL_UNUSED const char* pszContent,
-                                               int bAddRawFeature)
+static OGRLayerH OGRGeocodeBuildLayerNominatim(
+    CPLXMLNode* psSearchResults, const char* /* pszContent */,
+    const bool bAddRawFeature )
 {
     OGRMemLayer* poLayer = new OGRMemLayer( "place", NULL, wkbUnknown );
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
 
     CPLXMLNode* psPlace = psSearchResults->psChild;
-    /* First iteration to add fields */
+    // First iteration to add fields.
     while( psPlace != NULL )
     {
         if( psPlace->eType == CXT_Element &&
-            (strcmp(psPlace->pszValue, "place") == 0 || /* Nominatim */
-             strcmp(psPlace->pszValue, "geoname") == 0 /* Geonames */) )
+            (strcmp(psPlace->pszValue, "place") == 0 ||  // Nominatim.
+             strcmp(psPlace->pszValue, "geoname") == 0) )
         {
             CPLXMLNode* psChild = psPlace->psChild;
             while( psChild != NULL )
             {
                 const char* pszName = psChild->pszValue;
-                if( (psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) &&
+                if( (psChild->eType == CXT_Element ||
+                     psChild->eType == CXT_Attribute) &&
                     poFDefn->GetFieldIndex(pszName) < 0 &&
                     strcmp(pszName, "geotext") != 0 )
                 {
@@ -628,8 +656,8 @@ static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
                     {
                         oFieldDefn.SetType(OFTReal);
                     }
-                    else if( strcmp(pszName, "lon") == 0 ||  /* Nominatim */
-                            strcmp(pszName, "lng") == 0 /* Geonames */ )
+                    else if( strcmp(pszName, "lon") == 0 ||  // Nominatim.
+                             strcmp(pszName, "lng") == 0 )  // Geonames.
                     {
                         oFieldDefn.SetType(OFTReal);
                     }
@@ -651,23 +679,26 @@ static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
     while( psPlace != NULL )
     {
         if( psPlace->eType == CXT_Element &&
-            (strcmp(psPlace->pszValue, "place") == 0 || /* Nominatim */
-             strcmp(psPlace->pszValue, "geoname") == 0 /* Geonames */) )
+            (strcmp(psPlace->pszValue, "place") == 0 ||  // Nominatim.
+             strcmp(psPlace->pszValue, "geoname") == 0 ) )  // Geonames.
         {
-            bool bFoundLat = false, bFoundLon = false;
-            double dfLat = 0.0, dfLon = 0.0;
+            bool bFoundLat = false;
+            bool bFoundLon = false;
+            double dfLat = 0.0;
+            double dfLon = 0.0;
 
-            /* Iteration to fill the feature */
+            // Iteration to fill the feature.
             OGRFeature* poFeature = new OGRFeature(poFDefn);
             CPLXMLNode* psChild = psPlace->psChild;
             while( psChild != NULL )
             {
-                int nIdx;
+                int nIdx = 0;
                 const char* pszName = psChild->pszValue;
                 const char* pszVal = CPLGetXMLValue(psChild, NULL, NULL);
-                if( !(psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) )
+                if( !(psChild->eType == CXT_Element ||
+                      psChild->eType == CXT_Attribute) )
                 {
-                    // do nothing
+                    // Do nothing.
                 }
                 else if( (nIdx = poFDefn->GetFieldIndex(pszName)) >= 0 )
                 {
@@ -679,8 +710,8 @@ static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
                             bFoundLat = true;
                             dfLat = CPLAtofM(pszVal);
                         }
-                        else if( strcmp(pszName, "lon") == 0 ||  /* Nominatim */
-                                 strcmp(pszName, "lng") == 0 /* Geonames */ )
+                        else if( strcmp(pszName, "lon") == 0 ||  // Nominatim.
+                                 strcmp(pszName, "lng") == 0 )  // Geonames.
                         {
                             bFoundLon = true;
                             dfLon = CPLAtofM(pszVal);
@@ -689,7 +720,7 @@ static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
                 }
                 else if( strcmp(pszName, "geotext") == 0 )
                 {
-                    char* pszWKT = (char*) pszVal;
+                    char* pszWKT = const_cast<char *>( pszVal );
                     if( pszWKT != NULL )
                     {
                         OGRGeometry* poGeometry = NULL;
@@ -713,8 +744,8 @@ static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
                 CPLFree(pszXML);
             }
 
-            /* If we didn't found an explicit geometry, build it from */
-            /* the 'lon' and 'lat' attributes. */
+            // If we did not find an explicit geometry, build it from
+            // the 'lon' and 'lat' attributes.
             if( poFeature->GetGeometryRef() == NULL && bFoundLon && bFoundLat )
                 poFeature->SetGeometryDirectly(new OGRPoint(dfLon, dfLat));
 
@@ -723,19 +754,19 @@ static OGRLayerH OGRGeocodeBuildLayerNominatim(CPLXMLNode* psSearchResults,
         }
         psPlace = psPlace->psNext;
     }
-    return (OGRLayerH) poLayer;
+    return reinterpret_cast<OGRLayerH>( poLayer );
 }
 
 /************************************************************************/
 /*               OGRGeocodeReverseBuildLayerNominatim()                 */
 /************************************************************************/
 
-static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeocode,
-                                                      const char* pszContent,
-                                                      int bAddRawFeature)
+static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(
+    CPLXMLNode* psReverseGeocode, const char* pszContent, bool bAddRawFeature )
 {
     CPLXMLNode* psResult = CPLGetXMLNode(psReverseGeocode, "result");
-    CPLXMLNode* psAddressParts = CPLGetXMLNode(psReverseGeocode, "addressparts");
+    CPLXMLNode* psAddressParts =
+        CPLGetXMLNode(psReverseGeocode, "addressparts");
     if( psResult == NULL || psAddressParts == NULL )
     {
         return NULL;
@@ -744,16 +775,19 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
     OGRMemLayer* poLayer = new OGRMemLayer( "result", NULL, wkbNone );
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
 
-    bool bFoundLat = false, bFoundLon = false;
-    double dfLat = 0.0, dfLon = 0.0;
+    bool bFoundLat = false;
+    bool bFoundLon = false;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
 
-    /* First iteration to add fields */
+    // First iteration to add fields.
     CPLXMLNode* psChild = psResult->psChild;
     while( psChild != NULL )
     {
         const char* pszName = psChild->pszValue;
         const char* pszVal = CPLGetXMLValue(psChild, NULL, NULL);
-        if( (psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) &&
+        if( (psChild->eType == CXT_Element ||
+             psChild->eType == CXT_Attribute) &&
             poFDefn->GetFieldIndex(pszName) < 0 )
         {
             OGRFieldDefn oFieldDefn(pszName, OFTString);
@@ -789,7 +823,8 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
     while( psChild != NULL )
     {
         const char* pszName = psChild->pszValue;
-        if( (psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) &&
+        if( (psChild->eType == CXT_Element ||
+             psChild->eType == CXT_Attribute) &&
             poFDefn->GetFieldIndex(pszName) < 0 )
         {
             OGRFieldDefn oFieldDefn(pszName, OFTString);
@@ -804,15 +839,16 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
         poLayer->CreateField(&oFieldDefnRaw);
     }
 
-    /* Second iteration to fill the feature */
+    // Second iteration to fill the feature.
     OGRFeature* poFeature = new OGRFeature(poFDefn);
     psChild = psResult->psChild;
     while( psChild != NULL )
     {
-        int nIdx;
+        int nIdx = 0;
         const char* pszName = psChild->pszValue;
         const char* pszVal = CPLGetXMLValue(psChild, NULL, NULL);
-        if( (psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) &&
+        if( (psChild->eType == CXT_Element ||
+             psChild->eType == CXT_Attribute) &&
             (nIdx = poFDefn->GetFieldIndex(pszName)) >= 0 )
         {
             if( pszVal != NULL )
@@ -828,10 +864,11 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
     psChild = psAddressParts->psChild;
     while( psChild != NULL )
     {
-        int nIdx;
+        int nIdx = 0;
         const char* pszName = psChild->pszValue;
         pszVal = CPLGetXMLValue(psChild, NULL, NULL);
-        if( (psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) &&
+        if( (psChild->eType == CXT_Element ||
+             psChild->eType == CXT_Attribute) &&
             (nIdx = poFDefn->GetFieldIndex(pszName)) >= 0 )
         {
             if( pszVal != NULL )
@@ -845,29 +882,29 @@ static OGRLayerH OGRGeocodeReverseBuildLayerNominatim(CPLXMLNode* psReverseGeoco
         poFeature->SetField("raw", pszContent);
     }
 
-    /* If we didn't found an explicit geometry, build it from */
-    /* the 'lon' and 'lat' attributes. */
+    // If we did not find an explicit geometry, build it from
+    // the 'lon' and 'lat' attributes.
     if( poFeature->GetGeometryRef() == NULL && bFoundLon && bFoundLat )
         poFeature->SetGeometryDirectly(new OGRPoint(dfLon, dfLat));
 
     CPL_IGNORE_RET_VAL(poLayer->CreateFeature(poFeature));
     delete poFeature;
 
-    return (OGRLayerH) poLayer;
+    return reinterpret_cast<OGRLayerH>( poLayer );
 }
 
 /************************************************************************/
 /*                   OGRGeocodeBuildLayerYahoo()                        */
 /************************************************************************/
 
-static OGRLayerH OGRGeocodeBuildLayerYahoo(CPLXMLNode* psResultSet,
-                                           CPL_UNUSED const char* pszContent,
-                                           int bAddRawFeature)
+static OGRLayerH OGRGeocodeBuildLayerYahoo( CPLXMLNode* psResultSet,
+                                            const char* /* pszContent */,
+                                            bool bAddRawFeature )
 {
     OGRMemLayer* poLayer = new OGRMemLayer( "place", NULL, wkbPoint );
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
 
-    /* First iteration to add fields */
+    // First iteration to add fields.
     CPLXMLNode* psPlace = psResultSet->psChild;
     while( psPlace != NULL )
     {
@@ -878,7 +915,8 @@ static OGRLayerH OGRGeocodeBuildLayerYahoo(CPLXMLNode* psResultSet,
             while( psChild != NULL )
             {
                 const char* pszName = psChild->pszValue;
-                if( (psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) &&
+                if( (psChild->eType == CXT_Element ||
+                     psChild->eType == CXT_Attribute) &&
                     poFDefn->GetFieldIndex(pszName) < 0 )
                 {
                     OGRFieldDefn oFieldDefn(pszName, OFTString);
@@ -914,20 +952,23 @@ static OGRLayerH OGRGeocodeBuildLayerYahoo(CPLXMLNode* psResultSet,
         if( psPlace->eType == CXT_Element &&
             strcmp(psPlace->pszValue, "Result") == 0 )
         {
-            bool bFoundLat = false, bFoundLon = false;
-            double dfLat = 0.0, dfLon = 0.0;
+            bool bFoundLat = false;
+            bool bFoundLon = false;
+            double dfLat = 0.0;
+            double dfLon = 0.0;
 
-            /* Second iteration to fill the feature */
+            // Second iteration to fill the feature.
             OGRFeature* poFeature = new OGRFeature(poFDefn);
             CPLXMLNode* psChild = psPlace->psChild;
             while( psChild != NULL )
             {
-                int nIdx;
+                int nIdx = 0;
                 const char* pszName = psChild->pszValue;
                 const char* pszVal = CPLGetXMLValue(psChild, NULL, NULL);
-                if( !(psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) )
+                if( !(psChild->eType == CXT_Element ||
+                      psChild->eType == CXT_Attribute) )
                 {
-                    // do nothing
+                    // Do nothing.
                 }
                 else if( (nIdx = poFDefn->GetFieldIndex(pszName)) >= 0 )
                 {
@@ -950,14 +991,15 @@ static OGRLayerH OGRGeocodeBuildLayerYahoo(CPLXMLNode* psResultSet,
             }
 
             CPLString osDisplayName;
-            for(int i=1;;i++)
+            for( int i = 1; ; ++i )
             {
-                int nIdx = poFDefn->GetFieldIndex(CPLSPrintf("line%d", i));
+                const int nIdx =
+                    poFDefn->GetFieldIndex(CPLSPrintf("line%d", i));
                 if( nIdx < 0 )
                     break;
-                if( poFeature->IsFieldSet(nIdx) )
+                if( poFeature->IsFieldSetAndNotNull(nIdx) )
                 {
-                    if( osDisplayName.size() )
+                    if( !osDisplayName.empty() )
                         osDisplayName += ", ";
                     osDisplayName += poFeature->GetFieldAsString(nIdx);
                 }
@@ -975,7 +1017,7 @@ static OGRLayerH OGRGeocodeBuildLayerYahoo(CPLXMLNode* psResultSet,
                 CPLFree(pszXML);
             }
 
-            /* Build geometry from the 'lon' and 'lat' attributes. */
+            // Build geometry from the 'lon' and 'lat' attributes.
             if( bFoundLon && bFoundLat )
                 poFeature->SetGeometryDirectly(new OGRPoint(dfLon, dfLat));
 
@@ -984,25 +1026,26 @@ static OGRLayerH OGRGeocodeBuildLayerYahoo(CPLXMLNode* psResultSet,
         }
         psPlace = psPlace->psNext;
     }
-    return (OGRLayerH) poLayer;
+    return reinterpret_cast<OGRLayerH>( poLayer );
 }
 
 /************************************************************************/
 /*                   OGRGeocodeBuildLayerBing()                         */
 /************************************************************************/
 
-static OGRLayerH OGRGeocodeBuildLayerBing (CPLXMLNode* psResponse,
-                                           CPL_UNUSED const char* pszContent,
-                                           int bAddRawFeature)
+static OGRLayerH OGRGeocodeBuildLayerBing( CPLXMLNode* psResponse,
+                                           const char* /* pszContent */,
+                                           bool bAddRawFeature )
 {
-    CPLXMLNode* psResources = CPLGetXMLNode(psResponse, "ResourceSets.ResourceSet.Resources");
+    CPLXMLNode* psResources =
+        CPLGetXMLNode(psResponse, "ResourceSets.ResourceSet.Resources");
     if( psResources == NULL )
         return NULL;
 
     OGRMemLayer* poLayer = new OGRMemLayer( "place", NULL, wkbPoint );
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
 
-    /* First iteration to add fields  */
+    // First iteration to add fields.
     CPLXMLNode* psPlace = psResources->psChild;
     while( psPlace != NULL )
     {
@@ -1013,7 +1056,8 @@ static OGRLayerH OGRGeocodeBuildLayerBing (CPLXMLNode* psResponse,
             while( psChild != NULL )
             {
                 const char* pszName = psChild->pszValue;
-                if( (psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) &&
+                if( (psChild->eType == CXT_Element ||
+                     psChild->eType == CXT_Attribute) &&
                     strcmp(pszName, "BoundingBox") != 0 &&
                     strcmp(pszName, "GeocodePoint") != 0 &&
                     poFDefn->GetFieldIndex(pszName) < 0 )
@@ -1061,26 +1105,29 @@ static OGRLayerH OGRGeocodeBuildLayerBing (CPLXMLNode* psResponse,
         poLayer->CreateField(&oFieldDefnRaw);
     }
 
-    /* Iteration to fill the feature */
+    // Iteration to fill the feature.
     psPlace = psResources->psChild;
     while( psPlace != NULL )
     {
         if( psPlace->eType == CXT_Element &&
             strcmp(psPlace->pszValue, "Location") == 0 )
         {
-            bool bFoundLat = false, bFoundLon = false;
-            double dfLat = 0.0, dfLon = 0.0;
+            bool bFoundLat = false;
+            bool bFoundLon = false;
+            double dfLat = 0.0;
+            double dfLon = 0.0;
 
             OGRFeature* poFeature = new OGRFeature(poFDefn);
             CPLXMLNode* psChild = psPlace->psChild;
             while( psChild != NULL )
             {
-                int nIdx;
+                int nIdx = 0;
                 const char* pszName = psChild->pszValue;
                 const char* pszVal = CPLGetXMLValue(psChild, NULL, NULL);
-                if( !(psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) )
+                if( !(psChild->eType == CXT_Element ||
+                      psChild->eType == CXT_Attribute) )
                 {
-                    // do nothing
+                    // Do nothing.
                 }
                 else if( (nIdx = poFDefn->GetFieldIndex(pszName)) >= 0 )
                 {
@@ -1133,7 +1180,7 @@ static OGRLayerH OGRGeocodeBuildLayerBing (CPLXMLNode* psResponse,
                 CPLFree(pszXML);
             }
 
-            /* Build geometry from the 'lon' and 'lat' attributes. */
+            // Build geometry from the 'lon' and 'lat' attributes.
             if( bFoundLon && bFoundLat )
                 poFeature->SetGeometryDirectly(new OGRPoint(dfLon, dfLat));
 
@@ -1142,47 +1189,48 @@ static OGRLayerH OGRGeocodeBuildLayerBing (CPLXMLNode* psResponse,
         }
         psPlace = psPlace->psNext;
     }
-    return (OGRLayerH) poLayer;
+
+    return reinterpret_cast<OGRLayerH>(poLayer);
 }
 
 /************************************************************************/
 /*                         OGRGeocodeBuildLayer()                       */
 /************************************************************************/
 
-static OGRLayerH OGRGeocodeBuildLayer(const char* pszContent,
-                                      int bAddRawFeature)
+static OGRLayerH OGRGeocodeBuildLayer( const char* pszContent,
+                                       bool bAddRawFeature )
 {
     OGRLayerH hLayer = NULL;
     CPLXMLNode* psRoot = CPLParseXMLString( pszContent );
     if( psRoot != NULL )
     {
-        CPLXMLNode* psSearchResults;
-        CPLXMLNode* psReverseGeocode;
-        CPLXMLNode* psGeonames;
-        CPLXMLNode* psResultSet;
-        CPLXMLNode* psResponse;
+        CPLXMLNode* psSearchResults = NULL;
+        CPLXMLNode* psReverseGeocode = NULL;
+        CPLXMLNode* psGeonames = NULL;
+        CPLXMLNode* psResultSet = NULL;
+        CPLXMLNode* psResponse = NULL;
         if( (psSearchResults =
-                        CPLSearchXMLNode(psRoot, "=searchresults")) != NULL )
+                      CPLSearchXMLNode(psRoot, "=searchresults")) != NULL )
             hLayer = OGRGeocodeBuildLayerNominatim(psSearchResults,
                                                    pszContent,
                                                    bAddRawFeature);
         else if( (psReverseGeocode =
-                    CPLSearchXMLNode(psRoot, "=reversegeocode")) != NULL )
+                      CPLSearchXMLNode(psRoot, "=reversegeocode")) != NULL )
             hLayer = OGRGeocodeReverseBuildLayerNominatim(psReverseGeocode,
                                                           pszContent,
                                                           bAddRawFeature);
         else if( (psGeonames =
-                        CPLSearchXMLNode(psRoot, "=geonames")) != NULL )
+                      CPLSearchXMLNode(psRoot, "=geonames")) != NULL )
             hLayer = OGRGeocodeBuildLayerNominatim(psGeonames,
                                                    pszContent,
                                                    bAddRawFeature);
         else if( (psResultSet =
-                        CPLSearchXMLNode(psRoot, "=ResultSet")) != NULL )
+                      CPLSearchXMLNode(psRoot, "=ResultSet")) != NULL )
             hLayer = OGRGeocodeBuildLayerYahoo(psResultSet,
                                                pszContent,
                                                bAddRawFeature);
         else if( (psResponse =
-                    CPLSearchXMLNode(psRoot, "=Response")) != NULL )
+                      CPLSearchXMLNode(psRoot, "=Response")) != NULL )
             hLayer = OGRGeocodeBuildLayerBing (psResponse,
                                                pszContent,
                                                bAddRawFeature);
@@ -1197,19 +1245,19 @@ static OGRLayerH OGRGeocodeBuildLayer(const char* pszContent,
 /*                         OGRGeocodeCommon()                           */
 /************************************************************************/
 
-static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
-                                  CPLString osURL,
-                                  char** papszOptions)
+static OGRLayerH OGRGeocodeCommon( OGRGeocodingSessionH hSession,
+                                   CPLString osURL,
+                                   char** papszOptions )
 {
-    /* Only documented to work with OSM Nominatim. */
+    // Only documented to work with OSM Nominatim.
     if( hSession->pszLanguage != NULL )
     {
         osURL += "&accept-language=";
         osURL += hSession->pszLanguage;
     }
 
-    const char* pszExtraQueryParameters = OGRGeocodeGetParameter(
-                                papszOptions, "EXTRA_QUERY_PARAMETERS", NULL);
+    const char* pszExtraQueryParameters =
+        OGRGeocodeGetParameter(papszOptions, "EXTRA_QUERY_PARAMETERS", NULL);
     if( pszExtraQueryParameters != NULL )
     {
         osURL += "&";
@@ -1220,29 +1268,29 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
     if( EQUAL(hSession->pszGeocodingService, "OSM_NOMINATIM") &&
         hSession->pszEmail != NULL )
     {
-        char* pszEscapedEmail = CPLEscapeString(hSession->pszEmail,
-                                                -1, CPLES_URL);
+        char * const pszEscapedEmail = CPLEscapeString(hSession->pszEmail,
+                                                       -1, CPLES_URL);
         osURLWithEmail = osURL + "&email=" + pszEscapedEmail;
         CPLFree(pszEscapedEmail);
     }
     else if( EQUAL(hSession->pszGeocodingService, "GEONAMES") &&
              hSession->pszUserName != NULL )
     {
-        char* pszEscaped = CPLEscapeString(hSession->pszUserName,
-                                                -1, CPLES_URL);
+        char * const pszEscaped = CPLEscapeString(hSession->pszUserName,
+                                                  -1, CPLES_URL);
         osURLWithEmail = osURL + "&username=" + pszEscaped;
         CPLFree(pszEscaped);
     }
     else if( EQUAL(hSession->pszGeocodingService, "BING") &&
              hSession->pszKey != NULL )
     {
-        char* pszEscaped = CPLEscapeString(hSession->pszKey,
-                                                -1, CPLES_URL);
+        char * const pszEscaped = CPLEscapeString(hSession->pszKey,
+                                                  -1, CPLES_URL);
         osURLWithEmail = osURL + "&key=" + pszEscaped;
         CPLFree(pszEscaped);
     }
 
-    int bAddRawFeature =
+    const bool bAddRawFeature =
         CPLTestBool(OGRGeocodeGetParameter(papszOptions, "RAW_FEATURE", "NO"));
 
     OGRLayerH hLayer = NULL;
@@ -1252,26 +1300,23 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
         pszCachedResult = OGRGeocodeGetFromCache(hSession, osURL);
     if( pszCachedResult == NULL )
     {
-        CPLHTTPResult* psResult;
-
         double* pdfLastQueryTime = NULL;
         if( EQUAL(hSession->pszGeocodingService, "OSM_NOMINATIM") )
             pdfLastQueryTime = &dfLastQueryTimeStampOSMNominatim;
         else if( EQUAL(hSession->pszGeocodingService, "MAPQUEST_NOMINATIM") )
             pdfLastQueryTime = &dfLastQueryTimeStampMapQuestNominatim;
 
-        char** papszHTTPOptions = NULL;
-        CPLString osHeaders;
-        osHeaders = "User-Agent: ";
+        CPLString osHeaders = "User-Agent: ";
         osHeaders += hSession->pszApplication;
         if( hSession->pszLanguage != NULL )
         {
             osHeaders += "\r\nAccept-Language: ";
             osHeaders += hSession->pszLanguage;
         }
-        papszHTTPOptions = CSLAddNameValue(papszHTTPOptions, "HEADERS",
-                                           osHeaders.c_str());
+        char** papszHTTPOptions = CSLAddNameValue(NULL, "HEADERS",
+                                                  osHeaders.c_str());
 
+        CPLHTTPResult* psResult = NULL;
         if( pdfLastQueryTime != NULL )
         {
             CPLMutexHolderD(&hMutex);
@@ -1286,13 +1331,15 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
                          dfCurrentTime);
             }
 
-            psResult = CPLHTTPFetch( osURLWithEmail,  papszHTTPOptions );
+            psResult = CPLHTTPFetch( osURLWithEmail, papszHTTPOptions );
 
             gettimeofday(&tv, NULL);
             *pdfLastQueryTime = tv.tv_sec + tv.tv_usec / 1e6;
         }
         else
-            psResult = CPLHTTPFetch( osURLWithEmail,  papszHTTPOptions );
+        {
+            psResult = CPLHTTPFetch( osURLWithEmail, papszHTTPOptions );
+        }
 
         CSLDestroy(papszHTTPOptions);
         papszHTTPOptions = NULL;
@@ -1309,7 +1356,7 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
             {
                 if( hSession->bWriteCache )
                 {
-                    /* coverity[tainted_data] */
+                    // coverity[tainted_data]
                     OGRGeocodePutIntoCache(hSession, osURL, pszResult);
                 }
                 hLayer = OGRGeocodeBuildLayer(pszResult, bAddRawFeature);
@@ -1326,7 +1373,6 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
     return hLayer;
 }
 
-
 /************************************************************************/
 /*                              OGRGeocode()                            */
 /************************************************************************/
@@ -1344,9 +1390,9 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
  * means.
  *
  * In case of success, the return of this function is a OGR layer that contain
- * zero, one or several features matching the query. Note that the geometry of the
- * features is not necessarily a point.  The returned layer must be freed with
- * OGRGeocodeFreeResult().
+ * zero, one or several features matching the query. Note that the geometry of
+ * the features is not necessarily a point.  The returned layer must be freed
+ * with OGRGeocodeFreeResult().
  *
  * Note: this function is also available as the SQL
  * <a href="ogr_sql_sqlite.html#ogr_sql_sqlite_ogr_geocode_function">ogr_geocode()</a>
@@ -1358,12 +1404,14 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
  *     Defaults to 1. (Known to work with OSM and MapQuest Nominatim)
  * <li>COUNTRYCODES=code1,code2,...codeN: Limit search results to a specific
  *     country (or a list of countries). The codes must fellow ISO 3166-1, i.e.
- *     gb for United Kingdom, de for Germany, etc.. (Known to work with OSM and MapQuest Nominatim)
- * <li>LIMIT=number: the number of records to return. Unlimited if not specified.
- *     (Known to work with OSM and MapQuest Nominatim)
- * <li>RAW_FEATURE=YES: to specify that a 'raw' field must be added to the returned
- *     feature with the raw XML content.
- * <li> EXTRA_QUERY_PARAMETERS=params: additionnal parameters for the GET request.
+ *     gb for United Kingdom, de for Germany, etc.. (Known to work with OSM and
+ *     MapQuest Nominatim)
+ * <li>LIMIT=number: the number of records to return. Unlimited if not
+ *     specified.  (Known to work with OSM and MapQuest Nominatim)
+ * <li>RAW_FEATURE=YES: to specify that a 'raw' field must be added to the
+ *     returned feature with the raw XML content.
+ * <li>EXTRA_QUERY_PARAMETERS=params: additional parameters for the GET
+ *     request.
  * </ul>
  *
  * @param hSession the geocoding session handle.
@@ -1376,10 +1424,10 @@ static OGRLayerH OGRGeocodeCommon(OGRGeocodingSessionH hSession,
  *
  * @since GDAL 1.10
  */
-OGRLayerH OGRGeocode(OGRGeocodingSessionH hSession,
-                     const char* pszQuery,
-                     char** papszStructuredQuery,
-                     char** papszOptions)
+OGRLayerH OGRGeocode( OGRGeocodingSessionH hSession,
+                      const char* pszQuery,
+                      char** papszStructuredQuery,
+                      char** papszOptions )
 {
     VALIDATE_POINTER1( hSession, "OGRGeocode", NULL );
     if( (pszQuery == NULL && papszStructuredQuery == NULL) ||
@@ -1411,18 +1459,21 @@ OGRLayerH OGRGeocode(OGRGeocodingSessionH hSession,
     if( EQUAL(hSession->pszGeocodingService, "OSM_NOMINATIM") ||
         EQUAL(hSession->pszGeocodingService, "MAPQUEST_NOMINATIM") )
     {
-        const char* pszAddressDetails = OGRGeocodeGetParameter(papszOptions, "ADDRESSDETAILS", "1");
+        const char* pszAddressDetails =
+            OGRGeocodeGetParameter(papszOptions, "ADDRESSDETAILS", "1");
         osURL += "&addressdetails=";
         osURL += pszAddressDetails;
 
-        const char* pszCountryCodes = OGRGeocodeGetParameter(papszOptions, "COUNTRYCODES", NULL);
+        const char* pszCountryCodes =
+            OGRGeocodeGetParameter(papszOptions, "COUNTRYCODES", NULL);
         if( pszCountryCodes != NULL )
         {
             osURL += "&countrycodes=";
             osURL += pszCountryCodes;
         }
 
-        const char* pszLimit = OGRGeocodeGetParameter(papszOptions, "LIMIT", NULL);
+        const char* pszLimit =
+            OGRGeocodeGetParameter(papszOptions, "LIMIT", NULL);
         if( pszLimit != NULL && *pszLimit != '\0' )
         {
             osURL += "&limit=";
@@ -1430,23 +1481,22 @@ OGRLayerH OGRGeocode(OGRGeocodingSessionH hSession,
         }
     }
 
-    /* coverity[tainted_data] */
+    // coverity[tainted_data]
     return OGRGeocodeCommon(hSession, osURL, papszOptions);
 }
 
-
 /************************************************************************/
 /*                      OGRGeocodeReverseSubstitute()                   */
 /************************************************************************/
 
-static CPLString OGRGeocodeReverseSubstitute(CPLString osURL,
-                                             double dfLon, double dfLat)
+static CPLString OGRGeocodeReverseSubstitute( CPLString osURL,
+                                              double dfLon, double dfLat )
 {
     size_t iPos = osURL.find("{lon}");
     if( iPos != std::string::npos )
     {
-        CPLString osEnd(osURL.substr(iPos + 5));
-        osURL = osURL.substr(0,iPos);
+        const CPLString osEnd(osURL.substr(iPos + 5));
+        osURL = osURL.substr(0, iPos);
         osURL += CPLSPrintf("%.8f", dfLon);
         osURL += osEnd;
     }
@@ -1454,8 +1504,8 @@ static CPLString OGRGeocodeReverseSubstitute(CPLString osURL,
     iPos = osURL.find("{lat}");
     if( iPos != std::string::npos )
     {
-        CPLString osEnd(osURL.substr(iPos + 5));
-        osURL = osURL.substr(0,iPos);
+        const CPLString osEnd(osURL.substr(iPos + 5));
+        osURL = osURL.substr(0, iPos);
         osURL += CPLSPrintf("%.8f", dfLat);
         osURL += osEnd;
     }
@@ -1463,7 +1513,6 @@ static CPLString OGRGeocodeReverseSubstitute(CPLString osURL,
     return osURL;
 }
 
-
 /************************************************************************/
 /*                         OGRGeocodeReverse()                          */
 /************************************************************************/
@@ -1481,8 +1530,8 @@ static CPLString OGRGeocodeReverseSubstitute(CPLString osURL,
  * means.
  *
  * In case of success, the return of this function is a OGR layer that contain
- * zero, one or several features matching the query. The returned layer must be freed with
- * OGRGeocodeFreeResult().
+ * zero, one or several features matching the query. The returned layer must be
+ * freed with OGRGeocodeFreeResult().
  *
  * Note: this function is also available as the SQL
  * <a href="ogr_sql_sqlite.html#ogr_sql_sqlite_ogr_geocode_function">ogr_geocode_reverse()</a>
@@ -1490,10 +1539,11 @@ static CPLString OGRGeocodeReverseSubstitute(CPLString osURL,
  *
  * The list of recognized options is :
  * <ul>
- * <li>ZOOM=a_level: to query a specific zoom level. Only understood by the OSM Nominatim service.
- * <li>RAW_FEATURE=YES: to specify that a 'raw' field must be added to the returned
- *     feature with the raw XML content.
- * <li>EXTRA_QUERY_PARAMETERS=params: additionnal parameters for the GET request
+ * <li>ZOOM=a_level: to query a specific zoom level. Only understood by the OSM
+ *     Nominatim service.
+ * <li>RAW_FEATURE=YES: to specify that a 'raw' field must be added to the
+ *     returned feature with the raw XML content.
+ * <li>EXTRA_QUERY_PARAMETERS=params: additional parameters for the GET request
  *     for reverse geocoding.
  * </ul>
  *
@@ -1507,9 +1557,9 @@ static CPLString OGRGeocodeReverseSubstitute(CPLString osURL,
  *
  * @since GDAL 1.10
  */
-OGRLayerH OGRGeocodeReverse(OGRGeocodingSessionH hSession,
-                            double dfLon, double dfLat,
-                            char** papszOptions)
+OGRLayerH OGRGeocodeReverse( OGRGeocodingSessionH hSession,
+                             double dfLon, double dfLat,
+                             char** papszOptions )
 {
     VALIDATE_POINTER1( hSession, "OGRGeocodeReverse", NULL );
 
@@ -1525,14 +1575,15 @@ OGRLayerH OGRGeocodeReverse(OGRGeocodingSessionH hSession,
 
     if( EQUAL(hSession->pszGeocodingService, "OSM_NOMINATIM") )
     {
-        const char* pszZoomLevel = OGRGeocodeGetParameter(papszOptions, "ZOOM", NULL);
+        const char* pszZoomLevel =
+            OGRGeocodeGetParameter(papszOptions, "ZOOM", NULL);
         if( pszZoomLevel != NULL )
         {
             osURL = osURL + "&zoom=" + pszZoomLevel;
         }
     }
 
-    /* coverity[tainted_data] */
+    // coverity[tainted_data]
     return OGRGeocodeCommon(hSession, osURL, papszOptions);
 }
 
@@ -1548,7 +1599,7 @@ OGRLayerH OGRGeocodeReverse(OGRGeocodingSessionH hSession,
  *
  * @since GDAL 1.10
  */
-void OGRGeocodeFreeResult(OGRLayerH hLayer)
+void OGRGeocodeFreeResult( OGRLayerH hLayer )
 {
-    delete (OGRLayer*) hLayer;
+    delete reinterpret_cast<OGRLayer *>(hLayer);
 }
diff --git a/ogr/ogr_geocoding.h b/ogr/ogr_geocoding.h
index 6ed9d50..24712b8 100644
--- a/ogr/ogr_geocoding.h
+++ b/ogr/ogr_geocoding.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geocoding.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogr_geocoding.h 34931 2016-08-05 17:13:05Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Client of geocoding service.
@@ -41,6 +41,7 @@
 
 CPL_C_START
 
+/** Opaque type for a geocoding session */
 typedef struct _OGRGeocodingSessionHS *OGRGeocodingSessionH;
 
 OGRGeocodingSessionH CPL_DLL OGRGeocodeCreateSession(char** papszOptions);
diff --git a/ogr/ogr_geometry.h b/ogr/ogr_geometry.h
index 0024396..81ce2ad 100644
--- a/ogr/ogr_geometry.h
+++ b/ogr/ogr_geometry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geometry.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogr_geometry.h 37472 2017-02-26 02:47:45Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes for manipulating simple features that is not specific
@@ -47,18 +47,24 @@
 class OGRRawPoint
 {
   public:
-          OGRRawPoint()
-          {
-                  x = y = 0.0;
-          }
+          /** Constructor */
+          OGRRawPoint() : x(0.0), y(0.0) {}
 
+          /** Constructor */
           OGRRawPoint(double xIn, double yIn) : x(xIn), y(yIn) {}
+
+    /** x */
     double      x;
+    /** y */
     double      y;
 };
 
+/** GEOS geometry type */
 typedef struct GEOSGeom_t *GEOSGeom;
+/** GEOS context handle type */
 typedef struct GEOSContextHandle_HS *GEOSContextHandle_t;
+/** SFCGAL geometry type */
+typedef void sfcgal_geometry_t;
 
 class OGRPoint;
 class OGRCurve;
@@ -72,12 +78,18 @@ class OGRMultiSurface;
 class OGRMultiPolygon;
 class OGRMultiCurve;
 class OGRMultiLineString;
+class OGRTriangle;
+class OGRPolyhedralSurface;
+class OGRTriangulatedSurface;
 
+//! @cond Doxygen_Suppress
 typedef OGRLineString* (*OGRCurveCasterToLineString)(OGRCurve*);
 typedef OGRLinearRing* (*OGRCurveCasterToLinearRing)(OGRCurve*);
 
 typedef OGRPolygon*      (*OGRSurfaceCasterToPolygon)(OGRSurface*);
 typedef OGRCurvePolygon* (*OGRSurfaceCasterToCurvePolygon)(OGRSurface*);
+typedef OGRMultiPolygon* (*OGRPolyhedralSurfaceCastToMultiPolygon)(OGRPolyhedralSurface*);
+//! @endcond
 
 /************************************************************************/
 /*                             OGRGeometry                              */
@@ -87,17 +99,19 @@ typedef OGRCurvePolygon* (*OGRSurfaceCasterToCurvePolygon)(OGRSurface*);
  * Abstract base class for all geometry classes.
  *
  * Some spatial analysis methods require that OGR is built on the GEOS library
- * to work properly. The precise meaning of methods that describe spatial relationships
- * between geometries is described in the SFCOM, or other simple features interface
- * specifications, like "OpenGIS® Implementation Specification for
- * Geographic information - Simple feature access - Part 1: Common architecture"
+ * to work properly. The precise meaning of methods that describe spatial
+ * relationships between geometries is described in the SFCOM, or other simple
+ * features interface specifications, like "OpenGIS® Implementation
+ * Specification for Geographic information - Simple feature access - Part 1:
+ * Common architecture"
  * (<a href="http://www.opengeospatial.org/standards/sfa">OGC 06-103r4</a>)
  *
  * In GDAL 2.0, the hierarchy of classes has been extended with
  * <a href="https://portal.opengeospatial.org/files/?artifact_id=32024">
  * (working draft) ISO SQL/MM Part 3 (ISO/IEC 13249-3)</a> curve geometries :
  * CIRCULARSTRING (OGRCircularString), COMPOUNDCURVE (OGRCompoundCurve),
- * CURVEPOLYGON (OGRCurvePolygon), MULTICURVE (OGRMultiCurve) and MULTISURFACE (OGRMultiSurface).
+ * CURVEPOLYGON (OGRCurvePolygon), MULTICURVE (OGRMultiCurve) and
+ *  MULTISURFACE (OGRMultiSurface).
  *
  */
 
@@ -107,32 +121,37 @@ class CPL_DLL OGRGeometry
     OGRSpatialReference * poSRS;                // may be NULL
 
   protected:
+//! @cond Doxygen_Suppress
     friend class OGRCurveCollection;
 
-    unsigned int          flags;
-
-    OGRErr                importPreambuleFromWkt( char ** ppszInput,
-                                                  int* pbHasZ, int* pbHasM,
-                                                  bool* pbIsEmpty );
-    OGRErr                importCurveCollectionFromWkt( char ** ppszInput,
-                                                  int bAllowEmptyComponent,
-                                                  int bAllowLineString,
-                                                  int bAllowCurve,
-                                                  int bAllowCompoundCurve,
-                                                  OGRErr (*pfnAddCurveDirectly)(OGRGeometry* poSelf, OGRCurve* poCurve) );
-    OGRErr                importPreambuleFromWkb( unsigned char * pabyData,
-                                                  int nSize,
-                                                  OGRwkbByteOrder& eByteOrder,
-                                                  OGRwkbVariant eWkbVariant );
-    OGRErr                importPreambuleOfCollectionFromWkb(
-                                                        unsigned char * pabyData,
-                                                        int& nSize,
-                                                        int& nDataOffset,
-                                                        OGRwkbByteOrder& eByteOrder,
-                                                        int nMinSubGeomSize,
-                                                        int& nGeomCount,
-                                                        OGRwkbVariant eWkbVariant );
-    OGRErr                PointOnSurfaceInternal( OGRPoint * poPoint ) const;
+    unsigned int flags;
+
+    OGRErr       importPreambuleFromWkt( char ** ppszInput,
+                                         int* pbHasZ, int* pbHasM,
+                                         bool* pbIsEmpty );
+    OGRErr       importCurveCollectionFromWkt(
+                     char ** ppszInput,
+                     int bAllowEmptyComponent,
+                     int bAllowLineString,
+                     int bAllowCurve,
+                     int bAllowCompoundCurve,
+                     OGRErr (*pfnAddCurveDirectly)(OGRGeometry* poSelf,
+                                                   OGRCurve* poCurve) );
+    OGRErr       importPreambuleFromWkb( unsigned char * pabyData,
+                                         int nSize,
+                                         OGRwkbByteOrder& eByteOrder,
+                                         OGRwkbVariant eWkbVariant );
+    OGRErr       importPreambuleOfCollectionFromWkb(
+                     unsigned char * pabyData,
+                     int& nSize,
+                     int& nDataOffset,
+                     OGRwkbByteOrder& eByteOrder,
+                     int nMinSubGeomSize,
+                     int& nGeomCount,
+                     OGRwkbVariant eWkbVariant );
+    OGRErr       PointOnSurfaceInternal( OGRPoint * poPoint ) const;
+    OGRBoolean   IsSFCGALCompatible() const;
+//! @endcond
 
   public:
 
@@ -143,9 +162,11 @@ class CPL_DLL OGRGeometry
 /*          Use Is3D, IsMeasured, set3D, and setMeasured instead        */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
     static const unsigned int OGR_G_NOT_EMPTY_POINT = 0x1;
     static const unsigned int OGR_G_3D = 0x2;
     static const unsigned int OGR_G_MEASURED = 0x4;
+//! @endcond
 
                 OGRGeometry();
                 OGRGeometry( const OGRGeometry& other );
@@ -153,14 +174,16 @@ class CPL_DLL OGRGeometry
 
     OGRGeometry& operator=( const OGRGeometry& other );
 
-    // standard IGeometry
+    // Standard IGeometry.
     virtual int getDimension() const = 0;
     virtual int getCoordinateDimension() const;
     int CoordinateDimension() const;
-    virtual OGRBoolean  IsEmpty() const;
+    virtual OGRBoolean  IsEmpty() const = 0;
     virtual OGRBoolean  IsValid() const;
     virtual OGRBoolean  IsSimple() const;
+    /*! Returns whether the geometry has a Z component. */
     OGRBoolean  Is3D() const { return flags & OGR_G_3D; }
+    /*! Returns whether the geometry has a M component. */
     OGRBoolean  IsMeasured() const { return flags & OGR_G_MEASURED; }
     virtual OGRBoolean  IsRing() const;
     virtual void        empty() = 0;
@@ -168,31 +191,43 @@ class CPL_DLL OGRGeometry
     virtual void getEnvelope( OGREnvelope * psEnvelope ) const = 0;
     virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const = 0;
 
-    // IWks Interface
+    // IWks Interface.
     virtual int WkbSize() const = 0;
-    virtual OGRErr importFromWkb( unsigned char *, int=-1, OGRwkbVariant=wkbVariantOldOgc )=0;
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const = 0;
+    virtual OGRErr importFromWkb( unsigned char *, int=-1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) = 0;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc ) const = 0;
     virtual OGRErr importFromWkt( char ** ppszInput ) = 0;
-    virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const = 0;
+    virtual OGRErr exportToWkt( char ** ppszDstText,
+                                OGRwkbVariant=wkbVariantOldOgc ) const = 0;
 
-    // non-standard
+    // Non-standard.
     virtual OGRwkbGeometryType getGeometryType() const = 0;
     OGRwkbGeometryType    getIsoGeometryType() const;
     virtual const char *getGeometryName() const = 0;
-    virtual void   dumpReadable( FILE *, const char * = NULL, char** papszOptions = NULL ) const;
+    virtual void   dumpReadable( FILE *, const char * = NULL
+                                 , char** papszOptions = NULL ) const;
     virtual void   flattenTo2D() = 0;
     virtual char * exportToGML( const char* const * papszOptions = NULL ) const;
     virtual char * exportToKML() const;
     virtual char * exportToJson() const;
 
     static GEOSContextHandle_t createGEOSContext();
-    static void freeGEOSContext(GEOSContextHandle_t hGEOSCtxt);
-    virtual GEOSGeom exportToGEOS(GEOSContextHandle_t hGEOSCtxt) const CPL_WARN_UNUSED_RESULT;
+    static void freeGEOSContext( GEOSContextHandle_t hGEOSCtxt );
+    virtual GEOSGeom exportToGEOS( GEOSContextHandle_t hGEOSCtxt )
+        const CPL_WARN_UNUSED_RESULT;
     virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
-    virtual OGRGeometry* getCurveGeometry(const char* const* papszOptions = NULL) const CPL_WARN_UNUSED_RESULT;
-    virtual OGRGeometry* getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
-                                             const char* const* papszOptions = NULL) const CPL_WARN_UNUSED_RESULT;
-
+    virtual OGRGeometry* getCurveGeometry(
+        const char* const* papszOptions = NULL ) const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry* getLinearGeometry(
+        double dfMaxAngleStepSizeDegrees = 0,
+        const char* const* papszOptions = NULL ) const CPL_WARN_UNUSED_RESULT;
+
+    // SFCGAL interfacing methods.
+//! @cond Doxygen_Suppress
+    static sfcgal_geometry_t* OGRexportToSFCGAL( OGRGeometry *poGeom );
+    static OGRGeometry* SFCGALexportToOGR( sfcgal_geometry_t* _geometry );
+//! @endcond
     virtual void closeRings();
 
     virtual void setCoordinateDimension( int nDimension );
@@ -223,32 +258,55 @@ class CPL_DLL OGRGeometry
     virtual OGRGeometry *Boundary() const CPL_WARN_UNUSED_RESULT;
     virtual double  Distance( const OGRGeometry * ) const ;
     virtual OGRGeometry *ConvexHull() const CPL_WARN_UNUSED_RESULT;
-    virtual OGRGeometry *Buffer( double dfDist, int nQuadSegs = 30 ) const CPL_WARN_UNUSED_RESULT;
-    virtual OGRGeometry *Intersection( const OGRGeometry *) const CPL_WARN_UNUSED_RESULT;
-    virtual OGRGeometry *Union( const OGRGeometry * ) const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *Buffer( double dfDist, int nQuadSegs = 30 )
+        const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *Intersection( const OGRGeometry *)
+        const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *Union( const OGRGeometry * )
+        const CPL_WARN_UNUSED_RESULT;
     virtual OGRGeometry *UnionCascaded() const CPL_WARN_UNUSED_RESULT;
-    virtual OGRGeometry *Difference( const OGRGeometry * ) const CPL_WARN_UNUSED_RESULT;
-    virtual OGRGeometry *SymDifference( const OGRGeometry * ) const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *Difference( const OGRGeometry * )
+        const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *SymDifference( const OGRGeometry * )
+        const CPL_WARN_UNUSED_RESULT;
     virtual OGRErr       Centroid( OGRPoint * poPoint ) const;
-    virtual OGRGeometry *Simplify(double dTolerance) const CPL_WARN_UNUSED_RESULT;
-    OGRGeometry *SimplifyPreserveTopology(double dTolerance) const CPL_WARN_UNUSED_RESULT;
-    virtual OGRGeometry *DelaunayTriangulation(double dfTolerance, int bOnlyEdges) const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *Simplify(double dTolerance)
+        const CPL_WARN_UNUSED_RESULT;
+    OGRGeometry *SimplifyPreserveTopology(double dTolerance)
+        const CPL_WARN_UNUSED_RESULT;
+    virtual OGRGeometry *DelaunayTriangulation(
+        double dfTolerance, int bOnlyEdges ) const CPL_WARN_UNUSED_RESULT;
 
     virtual OGRGeometry *Polygonize() const CPL_WARN_UNUSED_RESULT;
 
-    // backward compatibility to non-standard method names.
-    OGRBoolean  Intersect( OGRGeometry * ) const CPL_WARN_DEPRECATED("Non standard method. Use Intersects() instead");
-    OGRBoolean  Equal( OGRGeometry * ) const CPL_WARN_DEPRECATED("Non standard method. Use Equals() instead");
-    OGRGeometry *SymmetricDifference( const OGRGeometry * ) const CPL_WARN_DEPRECATED("Non standard method. Use SymDifference() instead");
-    OGRGeometry *getBoundary() const CPL_WARN_DEPRECATED("Non standard method. Use Boundary() instead");
+    virtual double Distance3D( const OGRGeometry *poOtherGeom ) const;
 
+//! @cond Doxygen_Suppress
+    // backward compatibility to non-standard method names.
+    OGRBoolean  Intersect( OGRGeometry * )
+        const CPL_WARN_DEPRECATED("Non standard method. "
+                                  "Use Intersects() instead");
+    OGRBoolean  Equal( OGRGeometry * )
+        const CPL_WARN_DEPRECATED("Non standard method. "
+                                  "Use Equals() instead");
+    OGRGeometry *SymmetricDifference( const OGRGeometry * )
+        const CPL_WARN_DEPRECATED("Non standard method. "
+                                  "Use SymDifference() instead");
+    OGRGeometry *getBoundary()
+        const CPL_WARN_DEPRECATED("Non standard method. "
+                                  "Use Boundary() instead");
+//! @endcond
+
+//! @cond Doxygen_Suppress
     // Special HACK for DB2 7.2 support
     static int bGenerate_DB2_V72_BYTE_ORDER;
+//! @endcond
 
     virtual void        swapXY();
-
-    static OGRGeometry* CastToIdentity(OGRGeometry* poGeom) { return poGeom; }
-    static OGRGeometry* CastToError(OGRGeometry* poGeom);
+//! @cond Doxygen_Suppress
+    static OGRGeometry* CastToIdentity( OGRGeometry* poGeom ) { return poGeom; }
+    static OGRGeometry* CastToError( OGRGeometry* poGeom );
+//! @endcond
 };
 
 /************************************************************************/
@@ -279,45 +337,69 @@ class CPL_DLL OGRPoint : public OGRGeometry
     OGRPoint& operator=( const OGRPoint& other );
 
     // IWks Interface
-    virtual int WkbSize() const;
-    virtual OGRErr importFromWkb( unsigned char *, int=-1, OGRwkbVariant=wkbVariantOldOgc );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const;
+    virtual int WkbSize() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkb( unsigned char *, int=-1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char ** ppszDstText,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
 
     // IGeometry
-    virtual int getDimension() const;
-    virtual OGRGeometry *clone() const;
-    virtual void empty();
-    virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
-    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
-    virtual OGRBoolean  IsEmpty() const { return !(flags & OGR_G_NOT_EMPTY_POINT); }
+    virtual int getDimension() const CPL_OVERRIDE;
+    virtual OGRGeometry *clone() const CPL_OVERRIDE;
+    virtual void empty() CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope * psEnvelope ) const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const CPL_OVERRIDE;
+    virtual OGRBoolean  IsEmpty() const CPL_OVERRIDE
+        { return !(flags & OGR_G_NOT_EMPTY_POINT); }
 
     // IPoint
+    /** Return x */
     double      getX() const { return x; }
+    /** Return y */
     double      getY() const { return y; }
+    /** Return z */
     double      getZ() const { return z; }
+    /** Return m */
     double      getM() const { return m; }
 
     // Non standard
-    virtual void setCoordinateDimension( int nDimension );
+    virtual void setCoordinateDimension( int nDimension ) CPL_OVERRIDE;
+    /** Set x
+     * @param xIn x
+     */
     void        setX( double xIn ) { x = xIn; flags |= OGR_G_NOT_EMPTY_POINT; }
+    /** Set y
+     * @param yIn y
+     */
     void        setY( double yIn ) { y = yIn; flags |= OGR_G_NOT_EMPTY_POINT; }
-    void        setZ( double zIn ) { z = zIn; flags |= (OGR_G_NOT_EMPTY_POINT | OGR_G_3D); }
-    void        setM( double mIn ) { m = mIn; flags |= (OGR_G_NOT_EMPTY_POINT | OGR_G_MEASURED); }
+    /** Set z
+     * @param zIn z
+     */
+    void        setZ( double zIn )
+        { z = zIn; flags |= (OGR_G_NOT_EMPTY_POINT | OGR_G_3D); }
+    /** Set m
+     * @param mIn m
+     */
+    void        setM( double mIn )
+        { m = mIn; flags |= (OGR_G_NOT_EMPTY_POINT | OGR_G_MEASURED); }
 
     // ISpatialRelation
-    virtual OGRBoolean  Equals( OGRGeometry * ) const;
-    virtual OGRBoolean  Intersects( const OGRGeometry * ) const;
-    virtual OGRBoolean  Within( const OGRGeometry * ) const;
+    virtual OGRBoolean  Equals( OGRGeometry * ) const CPL_OVERRIDE;
+    virtual OGRBoolean  Intersects( const OGRGeometry * ) const CPL_OVERRIDE;
+    virtual OGRBoolean  Within( const OGRGeometry * ) const CPL_OVERRIDE;
 
     // Non standard from OGRGeometry
-    virtual const char *getGeometryName() const;
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual OGRErr  transform( OGRCoordinateTransformation *poCT );
-    virtual void flattenTo2D();
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual OGRErr  transform( OGRCoordinateTransformation *poCT ) CPL_OVERRIDE;
+    virtual void flattenTo2D() CPL_OVERRIDE;
 
-    virtual void        swapXY();
+    virtual void        swapXY() CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -334,9 +416,9 @@ class CPL_DLL OGRPointIterator
 {
     public:
         virtual ~OGRPointIterator();
-        virtual OGRBoolean getNextPoint(OGRPoint* p) = 0;
+        virtual OGRBoolean getNextPoint( OGRPoint* p ) = 0;
 
-        static void destroy(OGRPointIterator*);
+        static void destroy( OGRPointIterator* );
 };
 
 /************************************************************************/
@@ -351,6 +433,7 @@ class CPL_DLL OGRPointIterator
 class CPL_DLL OGRCurve : public OGRGeometry
 {
   protected:
+//! @cond Doxygen_Suppress
             OGRCurve();
             OGRCurve( const OGRCurve& other );
 
@@ -359,23 +442,27 @@ class CPL_DLL OGRCurve : public OGRGeometry
 
     friend class OGRCurvePolygon;
     friend class OGRCompoundCurve;
+//! @endcond
     virtual int    ContainsPoint( const OGRPoint* p ) const;
     virtual double get_AreaOfCurveSegments() const = 0;
 
   public:
     virtual ~OGRCurve();
 
+//! @cond Doxygen_Suppress
     OGRCurve& operator=( const OGRCurve& other );
+//! @endcond
 
     // ICurve methods
     virtual double get_Length() const = 0;
-    virtual void StartPoint(OGRPoint *) const = 0;
-    virtual void EndPoint(OGRPoint *) const = 0;
+    virtual void StartPoint( OGRPoint * ) const = 0;
+    virtual void EndPoint( OGRPoint * ) const = 0;
     virtual int  get_IsClosed() const;
     virtual void Value( double, OGRPoint * ) const = 0;
-    virtual OGRLineString* CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
-                                       const char* const* papszOptions = NULL) const = 0;
-    virtual int getDimension() const;
+    virtual OGRLineString* CurveToLine( double dfMaxAngleStepSizeDegrees = 0,
+                                        const char* const* papszOptions = NULL)
+        const = 0;
+    virtual int getDimension() const CPL_OVERRIDE;
 
     // non standard
     virtual int getNumPoints() const = 0;
@@ -383,9 +470,9 @@ class CPL_DLL OGRCurve : public OGRGeometry
     virtual OGRBoolean IsConvex() const;
     virtual double get_Area() const = 0;
 
-    static OGRCompoundCurve* CastToCompoundCurve(OGRCurve* puCurve);
-    static OGRLineString*    CastToLineString(OGRCurve* poCurve);
-    static OGRLinearRing*    CastToLinearRing(OGRCurve* poCurve);
+    static OGRCompoundCurve* CastToCompoundCurve( OGRCurve* puCurve );
+    static OGRLineString*    CastToLineString( OGRCurve* poCurve );
+    static OGRLinearRing*    CastToLinearRing( OGRCurve* poCurve );
 };
 
 /************************************************************************/
@@ -404,6 +491,7 @@ class CPL_DLL OGRCurve : public OGRGeometry
 class CPL_DLL OGRSimpleCurve: public OGRCurve
 {
   protected:
+//! @cond Doxygen_Suppress
     friend class OGRGeometry;
 
     int         nPointCount;
@@ -417,9 +505,12 @@ class CPL_DLL OGRSimpleCurve: public OGRCurve
     void        AddM();
 
     OGRErr      importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHasM,
-                                       OGRRawPoint*& paoPointsIn, int& nMaxPoints,
+                                       OGRRawPoint*& paoPointsIn,
+                                       int& nMaxPoints,
                                        double*& padfZIn );
 
+//! @endcond
+
     virtual double get_LinearArea() const;
 
                 OGRSimpleCurve();
@@ -430,30 +521,35 @@ class CPL_DLL OGRSimpleCurve: public OGRCurve
 
     OGRSimpleCurve& operator=( const OGRSimpleCurve& other );
 
-    // IWks Interface
-    virtual int WkbSize() const;
-    virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const;
-
-    // IGeometry interface
-    virtual OGRGeometry *clone() const;
-    virtual void empty();
-    virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
-    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
-    virtual OGRBoolean  IsEmpty() const;
-
-    // ICurve methods
-    virtual double get_Length() const;
-    virtual void StartPoint(OGRPoint *) const;
-    virtual void EndPoint(OGRPoint *) const;
-    virtual void Value( double, OGRPoint * ) const;
-    virtual double Project(const OGRPoint *) const;
-    virtual OGRLineString* getSubLine(double, double, int) const;
-
-    // ILineString methods
-    virtual int getNumPoints() const { return nPointCount; }
+    // IWks Interface.
+    virtual int WkbSize() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkb( unsigned char *, int = -1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char ** ppszDstText,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+
+    // IGeometry interface.
+    virtual OGRGeometry *clone() const CPL_OVERRIDE;
+    virtual void empty() CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope * psEnvelope ) const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const CPL_OVERRIDE;
+    virtual OGRBoolean  IsEmpty() const CPL_OVERRIDE;
+
+    // ICurve methods.
+    virtual double get_Length() const CPL_OVERRIDE;
+    virtual void StartPoint( OGRPoint * ) const CPL_OVERRIDE;
+    virtual void EndPoint( OGRPoint * ) const CPL_OVERRIDE;
+    virtual void Value( double, OGRPoint * ) const CPL_OVERRIDE;
+    virtual double Project( const OGRPoint * ) const;
+    virtual OGRLineString* getSubLine( double, double, int ) const;
+
+    // ILineString methods.
+    virtual int getNumPoints() const CPL_OVERRIDE { return nPointCount; }
     void        getPoint( int, OGRPoint * ) const;
     double      getX( int i ) const { return paoPoints[i].x; }
     double      getY( int i ) const { return paoPoints[i].y; }
@@ -461,13 +557,14 @@ class CPL_DLL OGRSimpleCurve: public OGRCurve
     double      getM( int i ) const;
 
     // ISpatialRelation
-    virtual OGRBoolean  Equals( OGRGeometry * ) const;
+    virtual OGRBoolean  Equals( OGRGeometry * ) const CPL_OVERRIDE;
 
     // non standard.
-    virtual void setCoordinateDimension( int nDimension );
-    virtual void set3D( OGRBoolean bIs3D );
-    virtual void setMeasured( OGRBoolean bIsMeasured );
-    void        setNumPoints( int nNewPointCount, int bZeroizeNewContent = TRUE );
+    virtual void setCoordinateDimension( int nDimension ) CPL_OVERRIDE;
+    virtual void set3D( OGRBoolean bIs3D ) CPL_OVERRIDE;
+    virtual void setMeasured( OGRBoolean bIsMeasured ) CPL_OVERRIDE;
+    void        setNumPoints( int nNewPointCount,
+                              int bZeroizeNewContent = TRUE );
     void        setPoint( int, OGRPoint * );
     void        setPoint( int, double, double );
     void        setZ( int, double );
@@ -484,14 +581,13 @@ class CPL_DLL OGRSimpleCurve: public OGRCurve
                             double *padfMIn = NULL );
     void        setPoints( int, double * padfX, double * padfY,
                            double *padfZIn, double *padfMIn );
-    void        addPoint( OGRPoint * );
+    void        addPoint( const OGRPoint * );
     void        addPoint( double, double );
     void        addPoint( double, double, double );
     void        addPointM( double, double, double );
     void        addPoint( double, double, double, double );
 
     void        getPoints( OGRRawPoint *, double * = NULL ) const;
-    void        getPoints( OGRRawPoint *, double *, double * ) const;
     void        getPoints( void* pabyX, int nXStride,
                            void* pabyY, int nYStride,
                            void* pabyZ = NULL, int nZStride = 0 ) const;
@@ -503,14 +599,14 @@ class CPL_DLL OGRSimpleCurve: public OGRCurve
     void        addSubLineString( const OGRLineString *,
                                   int nStartVertex = 0, int nEndVertex = -1 );
     void        reversePoints( void );
-    virtual OGRPointIterator* getPointIterator() const;
+    virtual OGRPointIterator* getPointIterator() const CPL_OVERRIDE;
 
     // non-standard from OGRGeometry
-    virtual OGRErr  transform( OGRCoordinateTransformation *poCT );
-    virtual void flattenTo2D();
-    virtual void segmentize(double dfMaxLength);
+    virtual OGRErr  transform( OGRCoordinateTransformation *poCT ) CPL_OVERRIDE;
+    virtual void flattenTo2D() CPL_OVERRIDE;
+    virtual void segmentize(double dfMaxLength) CPL_OVERRIDE;
 
-    virtual void        swapXY();
+    virtual void        swapXY() CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -520,39 +616,45 @@ class CPL_DLL OGRSimpleCurve: public OGRCurve
 /**
  * Concrete representation of a multi-vertex line.
  *
- * Note: for implementation convenience, we make it inherit from OGRSimpleCurve whereas
- * SFSQL and SQL/MM only make it inherits from OGRCurve.
+ * Note: for implementation convenience, we make it inherit from OGRSimpleCurve
+ * whereas SFSQL and SQL/MM only make it inherits from OGRCurve.
  */
 
 class CPL_DLL OGRLineString : public OGRSimpleCurve
 {
   protected:
+//! @cond Doxygen_Suppress
     static OGRLineString* TransferMembersAndDestroy(
                                             OGRLineString* poSrc,
                                             OGRLineString* poDst);
 
-    static OGRLinearRing* CastToLinearRing(OGRLineString* poLS);
+    virtual OGRCurveCasterToLineString GetCasterToLineString()
+        const CPL_OVERRIDE;
+    virtual OGRCurveCasterToLinearRing GetCasterToLinearRing()
+        const CPL_OVERRIDE;
 
-    virtual OGRCurveCasterToLineString GetCasterToLineString() const;
-    virtual OGRCurveCasterToLinearRing GetCasterToLinearRing() const;
+    virtual double get_AreaOfCurveSegments() const CPL_OVERRIDE;
+//! @endcond
 
-    virtual double get_AreaOfCurveSegments() const;
+    static OGRLinearRing* CastToLinearRing( OGRLineString* poLS );
 
   public:
                 OGRLineString();
-                OGRLineString(const OGRLineString& other);
+                OGRLineString( const OGRLineString& other );
     virtual    ~OGRLineString();
 
     OGRLineString& operator=(const OGRLineString& other);
 
-    virtual OGRLineString* CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
-                                       const char* const* papszOptions = NULL) const;
-    virtual OGRGeometry* getCurveGeometry(const char* const* papszOptions = NULL) const;
-    virtual double get_Area() const;
+    virtual OGRLineString* CurveToLine( double dfMaxAngleStepSizeDegrees = 0,
+                                        const char* const* papszOptions = NULL )
+        const CPL_OVERRIDE;
+    virtual OGRGeometry* getCurveGeometry(
+        const char* const* papszOptions = NULL ) const CPL_OVERRIDE;
+    virtual double get_Area() const CPL_OVERRIDE;
 
-    // non-standard from OGRGeometry
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual const char *getGeometryName() const;
+    // Non-standard from OGRGeometry.
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -582,7 +684,9 @@ class CPL_DLL OGRLineString : public OGRSimpleCurve
 class CPL_DLL OGRLinearRing : public OGRLineString
 {
   protected:
+//! @cond Doxygen_Suppress
     friend class OGRPolygon;
+    friend class OGRTriangle;
 
     // These are not IWks compatible ... just a convenience for OGRPolygon.
     virtual int _WkbSize( int _flags ) const;
@@ -591,34 +695,43 @@ class CPL_DLL OGRLinearRing : public OGRLineString
     virtual OGRErr _exportToWkb( OGRwkbByteOrder, int _flags,
                                  unsigned char * ) const;
 
-    static OGRLineString* CastToLineString(OGRLinearRing* poLR);
+    virtual OGRCurveCasterToLineString GetCasterToLineString()
+        const CPL_OVERRIDE;
+    virtual OGRCurveCasterToLinearRing GetCasterToLinearRing()
+        const CPL_OVERRIDE;
+//! @endcond
 
-    virtual OGRCurveCasterToLineString GetCasterToLineString() const;
-    virtual OGRCurveCasterToLinearRing GetCasterToLinearRing() const;
+    static OGRLineString* CastToLineString( OGRLinearRing* poLR );
 
   public:
                         OGRLinearRing();
-                        OGRLinearRing(const OGRLinearRing& other);
-                        OGRLinearRing( OGRLinearRing * );
+                        OGRLinearRing( const OGRLinearRing& other );
+               explicit OGRLinearRing( OGRLinearRing * );
     virtual            ~OGRLinearRing();
 
-    OGRLinearRing& operator=(const OGRLinearRing& other);
+    OGRLinearRing& operator=( const OGRLinearRing& other );
 
     // Non standard.
-    virtual const char *getGeometryName() const;
-    virtual OGRGeometry *clone() const;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRGeometry *clone() const CPL_OVERRIDE;
     virtual int isClockwise() const;
     virtual void reverseWindingOrder();
-    virtual void closeRings();
-    OGRBoolean isPointInRing(const OGRPoint* pt, int bTestEnvelope = TRUE) const;
-    OGRBoolean isPointOnRingBoundary(const OGRPoint* pt, int bTestEnvelope = TRUE) const;
+    virtual void closeRings() CPL_OVERRIDE;
+    OGRBoolean isPointInRing( const OGRPoint* pt,
+                              int bTestEnvelope = TRUE ) const;
+    OGRBoolean isPointOnRingBoundary( const OGRPoint* pt,
+                                      int bTestEnvelope = TRUE ) const;
+    virtual OGRErr  transform( OGRCoordinateTransformation *poCT ) CPL_OVERRIDE;
 
     // IWks Interface - Note this isn't really a first class object
     // for the purposes of WKB form.  These methods always fail since this
     // object can't be serialized on its own.
-    virtual int WkbSize() const;
-    virtual OGRErr importFromWkb( unsigned char *, int=-1, OGRwkbVariant=wkbVariantOldOgc );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
+    virtual int WkbSize() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkb( unsigned char *, int=-1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -629,8 +742,8 @@ class CPL_DLL OGRLinearRing : public OGRLineString
  * Concrete representation of a circular string, that is to say a curve made
  * of one or several arc circles.
  *
- * Note: for implementation convenience, we make it inherit from OGRSimpleCurve whereas
- * SQL/MM only makes it inherits from OGRCurve.
+ * Note: for implementation convenience, we make it inherit from OGRSimpleCurve
+ * whereas SQL/MM only makes it inherits from OGRCurve.
  *
  * Compatibility: ISO SQL/MM Part 3.
  *
@@ -645,10 +758,14 @@ class CPL_DLL OGRCircularString : public OGRSimpleCurve
     int         IsFullCircle( double& cx, double& cy, double& square_R ) const;
 
   protected:
-    virtual OGRCurveCasterToLineString GetCasterToLineString() const;
-    virtual OGRCurveCasterToLinearRing GetCasterToLinearRing() const;
-    virtual int    ContainsPoint( const OGRPoint* p ) const;
-    virtual double get_AreaOfCurveSegments() const;
+//! @cond Doxygen_Suppress
+    virtual OGRCurveCasterToLineString GetCasterToLineString()
+        const CPL_OVERRIDE;
+    virtual OGRCurveCasterToLinearRing GetCasterToLinearRing()
+        const CPL_OVERRIDE;
+    virtual int    ContainsPoint( const OGRPoint* p ) const CPL_OVERRIDE;
+    virtual double get_AreaOfCurveSegments() const CPL_OVERRIDE;
+//! @endcond
 
   public:
                 OGRCircularString();
@@ -657,31 +774,39 @@ class CPL_DLL OGRCircularString : public OGRSimpleCurve
 
     OGRCircularString& operator=(const OGRCircularString& other);
 
-    // IWks Interface
-    virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const;
-
-    // IGeometry interface
-    virtual OGRBoolean  IsValid() const;
-    virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
-    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
-
-    // ICurve methods
-    virtual double get_Length() const;
-    virtual OGRLineString* CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
-                                       const char* const* papszOptions = NULL) const;
-    virtual void Value( double, OGRPoint * ) const;
-    virtual double get_Area() const;
-
-    // non-standard from OGRGeometry
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual const char *getGeometryName() const;
-    virtual void segmentize(double dfMaxLength);
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
-    virtual OGRGeometry* getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
-                                             const char* const* papszOptions = NULL) const;
+    // IWks Interface.
+    virtual OGRErr importFromWkb( unsigned char *, int = -1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char ** ppszDstText,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+
+    // IGeometry interface.
+    virtual OGRBoolean  IsValid() const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope * psEnvelope ) const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const CPL_OVERRIDE;
+
+    // ICurve methods.
+    virtual double get_Length() const CPL_OVERRIDE;
+    virtual OGRLineString* CurveToLine( double dfMaxAngleStepSizeDegrees = 0,
+                                        const char* const* papszOptions = NULL )
+        const CPL_OVERRIDE;
+    virtual void Value( double, OGRPoint * ) const CPL_OVERRIDE;
+    virtual double get_Area() const CPL_OVERRIDE;
+
+    // Non-standard from OGRGeometry.
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual void segmentize( double dfMaxLength ) CPL_OVERRIDE;
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
+    virtual OGRGeometry* getLinearGeometry(
+        double dfMaxAngleStepSizeDegrees = 0,
+        const char* const* papszOptions = NULL) const CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -698,12 +823,14 @@ class CPL_DLL OGRCircularString : public OGRSimpleCurve
  * @since GDAL 2.0
  */
 
+//! @cond Doxygen_Suppress
 class CPL_DLL OGRCurveCollection
 {
   protected:
     friend class OGRCompoundCurve;
     friend class OGRCurvePolygon;
     friend class OGRPolygon;
+    friend class OGRTriangle;
 
     int         nCurveCount;
     OGRCurve  **papoCurves;
@@ -730,18 +857,23 @@ class CPL_DLL OGRCurveCollection
                                             OGRwkbByteOrder& eByteOrder,
                                             int nMinSubGeomSize,
                                             OGRwkbVariant eWkVariant );
-    OGRErr          importBodyFromWkb( OGRGeometry* poGeom,
-                                       unsigned char * pabyData,
-                                       int nSize,
-                                       int nDataOffset,
-                                       int bAcceptCompoundCurve,
-                                       OGRErr (*pfnAddCurveDirectlyFromWkb)(OGRGeometry* poGeom, OGRCurve* poCurve),
+    OGRErr      importBodyFromWkb(
+                    OGRGeometry* poGeom,
+                    unsigned char * pabyData,
+                    int nSize,
+                    int nDataOffset,
+                    int bAcceptCompoundCurve,
+                    OGRErr (*pfnAddCurveDirectlyFromWkb)( OGRGeometry* poGeom,
+                                                          OGRCurve* poCurve ),
                                        OGRwkbVariant eWkVariant );
-    OGRErr          exportToWkt( const OGRGeometry* poGeom, char ** ppszDstText ) const;
+    OGRErr          exportToWkt( const OGRGeometry* poGeom,
+                                 char ** ppszDstText ) const;
     OGRErr          exportToWkb( const OGRGeometry* poGeom, OGRwkbByteOrder,
-                                 unsigned char *, OGRwkbVariant eWkbVariant ) const;
+                                 unsigned char *,
+                                 OGRwkbVariant eWkbVariant ) const;
     OGRBoolean      Equals(OGRCurveCollection *poOCC) const;
-    void            setCoordinateDimension( OGRGeometry* poGeom, int nNewDimension );
+    void            setCoordinateDimension( OGRGeometry* poGeom,
+                                            int nNewDimension );
     void            set3D( OGRGeometry* poGeom, OGRBoolean bIs3D );
     void            setMeasured( OGRGeometry* poGeom, OGRBoolean bIsMeasured );
     int             getNumCurves() const;
@@ -750,11 +882,12 @@ class CPL_DLL OGRCurveCollection
     OGRCurve       *stealCurve( int );
     OGRErr          transform( OGRGeometry* poGeom,
                                OGRCoordinateTransformation *poCT );
-    void            flattenTo2D(OGRGeometry* poGeom);
-    void            segmentize(double dfMaxLength);
+    void            flattenTo2D( OGRGeometry* poGeom );
+    void            segmentize( double dfMaxLength );
     void            swapXY();
     OGRBoolean      hasCurveGeometry(int bLookForNonLinear) const;
 };
+//! @endcond
 
 /************************************************************************/
 /*                            OGRCompoundCurve                          */
@@ -778,81 +911,95 @@ class CPL_DLL OGRCompoundCurve : public OGRCurve
     OGRErr      addCurveDirectlyInternal( OGRCurve* poCurve,
                                           double dfToleranceEps,
                                           int bNeedRealloc );
-    static OGRErr addCurveDirectlyFromWkt( OGRGeometry* poSelf, OGRCurve* poCurve );
-    static OGRErr addCurveDirectlyFromWkb( OGRGeometry* poSelf, OGRCurve* poCurve );
-    OGRLineString* CurveToLineInternal(double dfMaxAngleStepSizeDegrees,
-                                       const char* const* papszOptions,
-                                       int bIsLinearRing) const;
+    static OGRErr addCurveDirectlyFromWkt( OGRGeometry* poSelf,
+                                           OGRCurve* poCurve );
+    static OGRErr addCurveDirectlyFromWkb( OGRGeometry* poSelf,
+                                           OGRCurve* poCurve );
+    OGRLineString* CurveToLineInternal( double dfMaxAngleStepSizeDegrees,
+                                        const char* const* papszOptions,
+                                        int bIsLinearRing ) const;
 
   protected:
-    static OGRLineString* CastToLineString(OGRCompoundCurve* poCC);
-    static OGRLinearRing* CastToLinearRing(OGRCompoundCurve* poCC);
+//! @cond Doxygen_Suppress
+    static OGRLineString* CastToLineString( OGRCompoundCurve* poCC );
+    static OGRLinearRing* CastToLinearRing( OGRCompoundCurve* poCC );
 
-    virtual OGRCurveCasterToLineString GetCasterToLineString() const;
-    virtual OGRCurveCasterToLinearRing GetCasterToLinearRing() const;
+    virtual OGRCurveCasterToLineString GetCasterToLineString()
+        const CPL_OVERRIDE;
+    virtual OGRCurveCasterToLinearRing GetCasterToLinearRing()
+        const CPL_OVERRIDE;
+//! @endcond
 
   public:
                 OGRCompoundCurve();
-                OGRCompoundCurve(const OGRCompoundCurve& other);
+                OGRCompoundCurve( const OGRCompoundCurve& other );
     virtual     ~OGRCompoundCurve();
 
-    OGRCompoundCurve& operator=(const OGRCompoundCurve& other);
+    OGRCompoundCurve& operator=( const OGRCompoundCurve& other );
 
     // IWks Interface
-    virtual int WkbSize() const;
-    virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const;
-
-    // IGeometry interface
-    virtual OGRGeometry *clone() const;
-    virtual void empty();
-    virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
-    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
-    virtual OGRBoolean  IsEmpty() const;
-
-    // ICurve methods
-    virtual double get_Length() const;
-    virtual void StartPoint(OGRPoint *) const;
-    virtual void EndPoint(OGRPoint *) const;
-    virtual void Value( double, OGRPoint * ) const;
-    virtual OGRLineString* CurveToLine(double dfMaxAngleStepSizeDegrees = 0,
-                                       const char* const* papszOptions = NULL) const;
-
-    virtual int getNumPoints() const;
-    virtual double get_AreaOfCurveSegments() const;
-    virtual double get_Area() const;
-
-    // ISpatialRelation
-    virtual OGRBoolean  Equals( OGRGeometry * ) const;
-
-    // ICompoundCurve method
+    virtual int WkbSize() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkb( unsigned char *, int = -1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char ** ppszDstText,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+
+    // IGeometry interface.
+    virtual OGRGeometry *clone() const CPL_OVERRIDE;
+    virtual void empty() CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope * psEnvelope ) const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const CPL_OVERRIDE;
+    virtual OGRBoolean  IsEmpty() const CPL_OVERRIDE;
+
+    // ICurve methods.
+    virtual double get_Length() const CPL_OVERRIDE;
+    virtual void StartPoint( OGRPoint * ) const CPL_OVERRIDE;
+    virtual void EndPoint( OGRPoint * ) const CPL_OVERRIDE;
+    virtual void Value( double, OGRPoint * ) const CPL_OVERRIDE;
+    virtual OGRLineString* CurveToLine( double dfMaxAngleStepSizeDegrees = 0,
+                                        const char* const* papszOptions = NULL )
+        const CPL_OVERRIDE;
+
+    virtual int getNumPoints() const CPL_OVERRIDE;
+    virtual double get_AreaOfCurveSegments() const CPL_OVERRIDE;
+    virtual double get_Area() const CPL_OVERRIDE;
+
+    // ISpatialRelation.
+    virtual OGRBoolean  Equals( OGRGeometry * ) const CPL_OVERRIDE;
+
+    // ICompoundCurve method.
     int             getNumCurves() const;
     OGRCurve       *getCurve( int );
     const OGRCurve *getCurve( int ) const;
 
-    // non standard.
-    virtual void setCoordinateDimension( int nDimension );
-    virtual void set3D( OGRBoolean bIs3D );
-    virtual void setMeasured( OGRBoolean bIsMeasured );
+    // Non-standard.
+    virtual void setCoordinateDimension( int nDimension ) CPL_OVERRIDE;
+    virtual void set3D( OGRBoolean bIs3D ) CPL_OVERRIDE;
+    virtual void setMeasured( OGRBoolean bIsMeasured ) CPL_OVERRIDE;
 
     OGRErr         addCurve( OGRCurve*, double dfToleranceEps = 1e-14  );
     OGRErr         addCurveDirectly( OGRCurve*, double dfToleranceEps = 1e-14 );
     OGRCurve      *stealCurve( int );
-    virtual OGRPointIterator* getPointIterator() const;
-
-    // non-standard from OGRGeometry
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual const char *getGeometryName() const;
-    virtual OGRErr  transform( OGRCoordinateTransformation *poCT );
-    virtual void flattenTo2D();
-    virtual void segmentize(double dfMaxLength);
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
-    virtual OGRGeometry* getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
-                                             const char* const* papszOptions = NULL) const;
-
-    virtual void        swapXY();
+    virtual OGRPointIterator* getPointIterator() const CPL_OVERRIDE;
+
+    // Non-standard from OGRGeometry.
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRErr  transform( OGRCoordinateTransformation *poCT ) CPL_OVERRIDE;
+    virtual void flattenTo2D() CPL_OVERRIDE;
+    virtual void segmentize(double dfMaxLength) CPL_OVERRIDE;
+    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE)
+        const CPL_OVERRIDE;
+    virtual OGRGeometry* getLinearGeometry(
+        double dfMaxAngleStepSizeDegrees = 0,
+        const char* const* papszOptions = NULL) const CPL_OVERRIDE;
+
+    virtual void        swapXY() CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -860,25 +1007,27 @@ class CPL_DLL OGRCompoundCurve : public OGRCurve
 /************************************************************************/
 
 /**
- * Abstract base class for 2 dimensional objects like polygons or curve polygons.
+ * Abstract base class for 2 dimensional objects like polygons or curve
+ * polygons.
  */
 
 class CPL_DLL OGRSurface : public OGRGeometry
 {
   protected:
-
+//! @cond Doxygen_Suppress
     virtual OGRSurfaceCasterToPolygon      GetCasterToPolygon() const = 0;
     virtual OGRSurfaceCasterToCurvePolygon GetCasterToCurvePolygon() const = 0;
+//! @endcond
 
   public:
     virtual double      get_Area() const = 0;
     virtual OGRErr      PointOnSurface( OGRPoint * poPoint ) const = 0;
-
+//! @cond Doxygen_Suppress
     static OGRPolygon*      CastToPolygon(OGRSurface* poSurface);
     static OGRCurvePolygon* CastToCurvePolygon(OGRSurface* poSurface);
+//! @endcond
 };
 
-
 /************************************************************************/
 /*                          OGRCurvePolygon                             */
 /************************************************************************/
@@ -901,71 +1050,87 @@ class CPL_DLL OGRCurvePolygon : public OGRSurface
   private:
     OGRBoolean      ContainsPoint( const OGRPoint* p ) const;
     virtual int   checkRing( OGRCurve * poNewRing ) const;
-    OGRErr        addRingDirectlyInternal( OGRCurve* poCurve, int bNeedRealloc );
-    static OGRErr addCurveDirectlyFromWkt( OGRGeometry* poSelf, OGRCurve* poCurve );
-    static OGRErr addCurveDirectlyFromWkb( OGRGeometry* poSelf, OGRCurve* poCurve );
+    OGRErr        addRingDirectlyInternal( OGRCurve* poCurve,
+                                           int bNeedRealloc );
+    static OGRErr addCurveDirectlyFromWkt( OGRGeometry* poSelf,
+                                           OGRCurve* poCurve );
+    static OGRErr addCurveDirectlyFromWkb( OGRGeometry* poSelf,
+                                           OGRCurve* poCurve );
 
   protected:
+//! @cond Doxygen_Suppress
     friend class OGRPolygon;
+    friend class OGRTriangle;
     OGRCurveCollection oCC;
 
-    static OGRPolygon* CastToPolygon(OGRCurvePolygon* poCP);
+    virtual OGRSurfaceCasterToPolygon      GetCasterToPolygon()
+        const CPL_OVERRIDE;
+    virtual OGRSurfaceCasterToCurvePolygon GetCasterToCurvePolygon()
+        const CPL_OVERRIDE;
+//! @endcond
 
-    virtual OGRSurfaceCasterToPolygon      GetCasterToPolygon() const;
-    virtual OGRSurfaceCasterToCurvePolygon GetCasterToCurvePolygon() const;
+    static OGRPolygon* CastToPolygon( OGRCurvePolygon* poCP );
 
   public:
                 OGRCurvePolygon();
-                OGRCurvePolygon(const OGRCurvePolygon&);
+                OGRCurvePolygon( const OGRCurvePolygon& );
     virtual    ~OGRCurvePolygon();
 
-    OGRCurvePolygon& operator=(const OGRCurvePolygon& other);
+    OGRCurvePolygon& operator=( const OGRCurvePolygon& other );
 
     // Non standard (OGRGeometry).
-    virtual const char *getGeometryName() const;
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual OGRGeometry *clone() const;
-    virtual void empty();
-    virtual OGRErr  transform( OGRCoordinateTransformation *poCT );
-    virtual void flattenTo2D();
-    virtual OGRBoolean  IsEmpty() const;
-    virtual void segmentize(double dfMaxLength);
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
-    virtual OGRGeometry* getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
-                                             const char* const* papszOptions = NULL) const;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual OGRGeometry *clone() const CPL_OVERRIDE;
+    virtual void empty() CPL_OVERRIDE;
+    virtual OGRErr  transform( OGRCoordinateTransformation *poCT ) CPL_OVERRIDE;
+    virtual void flattenTo2D() CPL_OVERRIDE;
+    virtual OGRBoolean  IsEmpty() const CPL_OVERRIDE;
+    virtual void segmentize( double dfMaxLength ) CPL_OVERRIDE;
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
+    virtual OGRGeometry* getLinearGeometry(
+        double dfMaxAngleStepSizeDegrees = 0,
+        const char* const* papszOptions = NULL ) const CPL_OVERRIDE;
 
     // ISurface Interface
-    virtual double      get_Area() const;
-    virtual OGRErr      PointOnSurface( OGRPoint * poPoint ) const;
+    virtual double      get_Area() const CPL_OVERRIDE;
+    virtual OGRErr      PointOnSurface( OGRPoint * poPoint ) const CPL_OVERRIDE;
 
     // IWks Interface
-    virtual int WkbSize() const;
-    virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant eWkbVariant = wkbVariantOldOgc ) const;
+    virtual int WkbSize() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkb( unsigned char *, int = -1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char ** ppszDstText,
+                                OGRwkbVariant eWkbVariant = wkbVariantOldOgc )
+        const CPL_OVERRIDE;
 
     // IGeometry
-    virtual int getDimension() const;
-    virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
-    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
+    virtual int getDimension() const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope * psEnvelope ) const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const CPL_OVERRIDE;
 
     // ICurvePolygon
-    virtual OGRPolygon* CurvePolyToPoly(double dfMaxAngleStepSizeDegrees = 0,
-                                        const char* const* papszOptions = NULL) const;
+    virtual OGRPolygon* CurvePolyToPoly(
+        double dfMaxAngleStepSizeDegrees = 0,
+        const char* const* papszOptions = NULL ) const;
 
     // ISpatialRelation
-    virtual OGRBoolean  Equals( OGRGeometry * ) const;
-    virtual OGRBoolean  Intersects( const OGRGeometry * ) const;
-    virtual OGRBoolean  Contains( const OGRGeometry * ) const;
+    virtual OGRBoolean  Equals( OGRGeometry * ) const CPL_OVERRIDE;
+    virtual OGRBoolean  Intersects( const OGRGeometry * ) const CPL_OVERRIDE;
+    virtual OGRBoolean  Contains( const OGRGeometry * ) const CPL_OVERRIDE;
 
     // Non standard
-    virtual void setCoordinateDimension( int nDimension );
-    virtual void set3D( OGRBoolean bIs3D );
-    virtual void setMeasured( OGRBoolean bIsMeasured );
+    virtual void setCoordinateDimension( int nDimension ) CPL_OVERRIDE;
+    virtual void set3D( OGRBoolean bIs3D ) CPL_OVERRIDE;
+    virtual void setMeasured( OGRBoolean bIsMeasured ) CPL_OVERRIDE;
 
-    OGRErr        addRing( OGRCurve * );
-    OGRErr        addRingDirectly( OGRCurve * );
+    virtual OGRErr addRing( OGRCurve * );
+    virtual OGRErr addRingDirectly( OGRCurve * );
 
     OGRCurve *getExteriorRingCurve();
     const OGRCurve *getExteriorRingCurve() const;
@@ -975,7 +1140,7 @@ class CPL_DLL OGRCurvePolygon : public OGRSurface
 
     OGRCurve *stealExteriorRingCurve();
 
-    virtual void        swapXY();
+    virtual void        swapXY() CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -985,26 +1150,34 @@ class CPL_DLL OGRCurvePolygon : public OGRSurface
 /**
  * Concrete class representing polygons.
  *
- * Note that the OpenGIS simple features polygons consist of one outer
- * ring (linearring), and zero or more inner rings.  A polygon cannot represent disconnected
- * regions (such as multiple islands in a political body).  The
+ * Note that the OpenGIS simple features polygons consist of one outer ring
+ * (linearring), and zero or more inner rings.  A polygon cannot represent
+ * disconnected regions (such as multiple islands in a political body).  The
  * OGRMultiPolygon must be used for this.
  */
 
 class CPL_DLL OGRPolygon : public OGRCurvePolygon
 {
   protected:
+//! @cond Doxygen_Suppress
     friend class OGRMultiSurface;
+    friend class OGRPolyhedralSurface;
+    friend class OGRTriangulatedSurface;
 
-    virtual int checkRing( OGRCurve * poNewRing ) const;
-    OGRErr      importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHasM,
-                                       OGRRawPoint*& paoPoints, int& nMaxPoints,
-                                       double*& padfZ );
+    virtual int checkRing( OGRCurve * poNewRing ) const CPL_OVERRIDE;
+    virtual OGRErr importFromWKTListOnly( char ** ppszInput,
+                                          int bHasZ, int bHasM,
+                                          OGRRawPoint*& paoPoints,
+                                          int& nMaxPoints,
+                                          double*& padfZ );
 
     static OGRCurvePolygon* CastToCurvePolygon(OGRPolygon* poPoly);
 
-    virtual OGRSurfaceCasterToPolygon      GetCasterToPolygon() const;
-    virtual OGRSurfaceCasterToCurvePolygon GetCasterToCurvePolygon() const;
+    virtual OGRSurfaceCasterToPolygon      GetCasterToPolygon()
+        const CPL_OVERRIDE;
+    virtual OGRSurfaceCasterToCurvePolygon GetCasterToCurvePolygon()
+        const CPL_OVERRIDE;
+//! @endcond
 
   public:
                 OGRPolygon();
@@ -1013,39 +1186,96 @@ class CPL_DLL OGRPolygon : public OGRCurvePolygon
 
     OGRPolygon& operator=(const OGRPolygon& other);
 
-    // Non standard (OGRGeometry).
-    virtual const char *getGeometryName() const;
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
-    virtual OGRGeometry* getCurveGeometry(const char* const* papszOptions = NULL) const;
-    virtual OGRGeometry* getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0,
-                                             const char* const* papszOptions = NULL) const;
-
-    // ISurface Interface
-    virtual OGRErr        PointOnSurface( OGRPoint * poPoint ) const;
-
-    // IWks Interface
-    virtual int WkbSize() const;
-    virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const;
-
-    // ICurvePolygon
-    virtual OGRPolygon* CurvePolyToPoly(double dfMaxAngleStepSizeDegrees = 0,
-                                        const char* const* papszOptions = NULL) const;
+    // Non-standard (OGRGeometry).
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
+    virtual OGRGeometry* getCurveGeometry(
+    const char* const* papszOptions = NULL ) const CPL_OVERRIDE;
+    virtual OGRGeometry* getLinearGeometry(
+        double dfMaxAngleStepSizeDegrees = 0,
+        const char* const* papszOptions = NULL) const CPL_OVERRIDE;
+
+    // ISurface Interface.
+    virtual OGRErr        PointOnSurface( OGRPoint * poPoint )
+        const CPL_OVERRIDE;
+
+    // IWks Interface.
+    virtual int WkbSize() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkb( unsigned char *, int = -1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char ** ppszDstText,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+
+    // ICurvePolygon.
+    virtual OGRPolygon* CurvePolyToPoly(
+        double dfMaxAngleStepSizeDegrees = 0,
+        const char* const* papszOptions = NULL ) const CPL_OVERRIDE;
 
     OGRLinearRing *getExteriorRing();
     const OGRLinearRing *getExteriorRing() const;
-    OGRLinearRing *getInteriorRing( int );
-    const OGRLinearRing *getInteriorRing( int ) const;
+    virtual OGRLinearRing *getInteriorRing( int );
+    virtual const OGRLinearRing *getInteriorRing( int ) const;
 
     OGRLinearRing *stealExteriorRing();
-    OGRLinearRing *stealInteriorRing(int);
+    virtual OGRLinearRing *stealInteriorRing(int);
 
     OGRBoolean IsPointOnSurface( const OGRPoint * ) const;
 
-    virtual void closeRings();
+    virtual void closeRings() CPL_OVERRIDE;
+};
+
+/************************************************************************/
+/*                              OGRTriangle                             */
+/************************************************************************/
+
+/**
+ * Triangle class.
+ *
+ * @since GDAL 2.2
+ */
+
+class CPL_DLL OGRTriangle : public OGRPolygon
+{
+  private:
+    bool quickValidityCheck() const;
+
+  protected:
+//! @cond Doxygen_Suppress
+    virtual OGRSurfaceCasterToPolygon   GetCasterToPolygon() const CPL_OVERRIDE;
+    virtual OGRErr importFromWKTListOnly( char ** ppszInput,
+                                          int bHasZ, int bHasM,
+                                          OGRRawPoint*& paoPoints,
+                                          int& nMaxPoints,
+                                          double*& padfZ ) CPL_OVERRIDE;
+//! @endcond
+
+  public:
+    OGRTriangle();
+    OGRTriangle( const OGRPoint &p, const OGRPoint &q, const OGRPoint &r );
+    OGRTriangle( const OGRTriangle &other );
+    OGRTriangle( const OGRPolygon &other, OGRErr &eErr );
+    OGRTriangle& operator=( const OGRTriangle& other );
+    virtual ~OGRTriangle();
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+
+    // IWks Interface.
+    virtual OGRErr importFromWkb( unsigned char *, int = -1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+
+    // New methods rewritten from OGRPolygon/OGRCurvePolygon/OGRGeometry.
+    virtual OGRErr addRingDirectly( OGRCurve * poNewRing ) CPL_OVERRIDE;
+
+//! @cond Doxygen_Suppress
+    static OGRGeometry* CastToPolygon( OGRGeometry* poGeom );
+//! @endcond
 };
 
 /************************************************************************/
@@ -1061,56 +1291,68 @@ class CPL_DLL OGRPolygon : public OGRCurvePolygon
 
 class CPL_DLL OGRGeometryCollection : public OGRGeometry
 {
-    OGRErr      importFromWkbInternal( unsigned char * pabyData, int nSize, int nRecLevel,
+    OGRErr      importFromWkbInternal( unsigned char * pabyData, int nSize,
+                                       int nRecLevel,
                                        OGRwkbVariant );
     OGRErr      importFromWktInternal( char **ppszInput, int nRecLevel );
 
   protected:
+//! @cond Doxygen_Suppress
     int         nGeomCount;
     OGRGeometry **papoGeoms;
 
-    OGRErr                      exportToWktInternal( char ** ppszDstText,
-                                                     OGRwkbVariant eWkbVariant,
-                                                     const char* pszSkipPrefix ) const;
+    OGRErr              exportToWktInternal( char ** ppszDstText,
+                                             OGRwkbVariant eWkbVariant,
+                                             const char* pszSkipPrefix ) const;
+    static OGRGeometryCollection* TransferMembersAndDestroy(
+        OGRGeometryCollection* poSrc,
+        OGRGeometryCollection* poDst );
+//! @endcond
     virtual OGRBoolean         isCompatibleSubType( OGRwkbGeometryType ) const;
 
-    static OGRGeometryCollection* TransferMembersAndDestroy(OGRGeometryCollection* poSrc,
-                                                  OGRGeometryCollection* poDst);
-
   public:
                 OGRGeometryCollection();
-                OGRGeometryCollection(const OGRGeometryCollection& other);
+                OGRGeometryCollection( const OGRGeometryCollection& other );
     virtual     ~OGRGeometryCollection();
 
-    OGRGeometryCollection& operator=(const OGRGeometryCollection& other);
+    OGRGeometryCollection& operator=( const OGRGeometryCollection& other );
 
     // Non standard (OGRGeometry).
-    virtual const char *getGeometryName() const;
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual OGRGeometry *clone() const;
-    virtual void empty();
-    virtual OGRErr  transform( OGRCoordinateTransformation *poCT );
-    virtual void flattenTo2D();
-    virtual OGRBoolean  IsEmpty() const;
-    virtual void segmentize(double dfMaxLength);
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
-    virtual OGRGeometry* getCurveGeometry(const char* const* papszOptions = NULL) const;
-    virtual OGRGeometry* getLinearGeometry(double dfMaxAngleStepSizeDegrees = 0, const char* const* papszOptions = NULL) const;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual OGRGeometry *clone() const CPL_OVERRIDE;
+    virtual void empty() CPL_OVERRIDE;
+    virtual OGRErr  transform( OGRCoordinateTransformation *poCT ) CPL_OVERRIDE;
+    virtual void flattenTo2D() CPL_OVERRIDE;
+    virtual OGRBoolean  IsEmpty() const CPL_OVERRIDE;
+    virtual void segmentize(double dfMaxLength) CPL_OVERRIDE;
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
+    virtual OGRGeometry* getCurveGeometry(
+        const char* const* papszOptions = NULL ) const CPL_OVERRIDE;
+    virtual OGRGeometry* getLinearGeometry(
+        double dfMaxAngleStepSizeDegrees = 0,
+        const char* const* papszOptions = NULL ) const CPL_OVERRIDE;
 
     // IWks Interface
-    virtual int WkbSize() const;
-    virtual OGRErr importFromWkb( unsigned char *, int = -1, OGRwkbVariant=wkbVariantOldOgc );
-    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *, OGRwkbVariant=wkbVariantOldOgc ) const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char ** ppszDstText, OGRwkbVariant=wkbVariantOldOgc ) const;
+    virtual int WkbSize() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkb( unsigned char *, int = -1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char ** ppszDstText,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
 
     virtual double get_Length() const;
     virtual double get_Area() const;
 
     // IGeometry methods
-    virtual int getDimension() const;
-    virtual void getEnvelope( OGREnvelope * psEnvelope ) const;
-    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const;
+    virtual int getDimension() const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope * psEnvelope ) const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const CPL_OVERRIDE;
 
     // IGeometryCollection
     int         getNumGeometries() const;
@@ -1118,19 +1360,22 @@ class CPL_DLL OGRGeometryCollection : public OGRGeometry
     const OGRGeometry *getGeometryRef( int ) const;
 
     // ISpatialRelation
-    virtual OGRBoolean  Equals( OGRGeometry * ) const;
+    virtual OGRBoolean  Equals( OGRGeometry * ) const CPL_OVERRIDE;
 
     // Non standard
-    virtual void setCoordinateDimension( int nDimension );
-    virtual void set3D( OGRBoolean bIs3D );
-    virtual void setMeasured( OGRBoolean bIsMeasured );
+    virtual void setCoordinateDimension( int nDimension ) CPL_OVERRIDE;
+    virtual void set3D( OGRBoolean bIs3D ) CPL_OVERRIDE;
+    virtual void setMeasured( OGRBoolean bIsMeasured ) CPL_OVERRIDE;
     virtual OGRErr addGeometry( const OGRGeometry * );
     virtual OGRErr addGeometryDirectly( OGRGeometry * );
     virtual OGRErr removeGeometry( int iIndex, int bDelete = TRUE );
 
-    void closeRings();
+    void closeRings() CPL_OVERRIDE;
 
-    virtual void        swapXY();
+    virtual void swapXY() CPL_OVERRIDE;
+
+    static OGRGeometryCollection* CastToGeometryCollection(
+        OGRGeometryCollection* poSrc );
 };
 
 /************************************************************************/
@@ -1146,31 +1391,34 @@ class CPL_DLL OGRGeometryCollection : public OGRGeometry
 class CPL_DLL OGRMultiSurface : public OGRGeometryCollection
 {
   protected:
-    virtual OGRBoolean  isCompatibleSubType( OGRwkbGeometryType ) const;
+    virtual OGRBoolean isCompatibleSubType( OGRwkbGeometryType )
+        const CPL_OVERRIDE;
 
   public:
             OGRMultiSurface();
-            OGRMultiSurface(const OGRMultiSurface& other);
+            OGRMultiSurface( const OGRMultiSurface& other );
     virtual ~OGRMultiSurface();
 
-    OGRMultiSurface& operator=(const OGRMultiSurface& other);
+    OGRMultiSurface& operator=( const OGRMultiSurface& other );
 
     // Non standard (OGRGeometry).
-    virtual const char *getGeometryName() const;
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc ) const;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
 
     // IMultiSurface methods
-    virtual OGRErr      PointOnSurface( OGRPoint * poPoint ) const;
+    virtual OGRErr PointOnSurface( OGRPoint * poPoint ) const;
 
     // IGeometry methods
-    virtual int getDimension() const;
+    virtual int getDimension() const CPL_OVERRIDE;
 
     // Non standard
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
 
-    static OGRMultiPolygon* CastToMultiPolygon(OGRMultiSurface* poMS);
+    static OGRMultiPolygon* CastToMultiPolygon( OGRMultiSurface* poMS );
 };
 
 /************************************************************************/
@@ -1184,7 +1432,21 @@ class CPL_DLL OGRMultiSurface : public OGRGeometryCollection
 class CPL_DLL OGRMultiPolygon : public OGRMultiSurface
 {
   protected:
-    virtual OGRBoolean  isCompatibleSubType( OGRwkbGeometryType ) const;
+    virtual OGRBoolean isCompatibleSubType( OGRwkbGeometryType )
+        const CPL_OVERRIDE;
+    friend class OGRPolyhedralSurface;
+    friend class OGRTriangulatedSurface;
+
+  private:
+//! @cond Doxygen_Suppress
+            OGRErr _addGeometryWithExpectedSubGeometryType(
+                const OGRGeometry * poNewGeom,
+                OGRwkbGeometryType eSubGeometryType );
+            OGRErr _addGeometryDirectlyWithExpectedSubGeometryType(
+                OGRGeometry * poNewGeom,
+                OGRwkbGeometryType eSubGeometryType );
+//! @endcond
+
 
   public:
             OGRMultiPolygon();
@@ -1193,18 +1455,144 @@ class CPL_DLL OGRMultiPolygon : public OGRMultiSurface
 
     OGRMultiPolygon& operator=(const OGRMultiPolygon& other);
 
-    // Non standard (OGRGeometry).
-    virtual const char *getGeometryName() const;
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc ) const;
+    // Non-standard (OGRGeometry).
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
 
     // IMultiSurface methods
-    virtual OGRErr      PointOnSurface( OGRPoint * poPoint ) const;
+    virtual OGRErr      PointOnSurface( OGRPoint * poPoint ) const CPL_OVERRIDE;
 
     // Non standard
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
+
+    static OGRMultiSurface* CastToMultiSurface( OGRMultiPolygon* poMP );
+};
+
+/************************************************************************/
+/*                         OGRPolyhedralSurface                         */
+/************************************************************************/
 
-    static OGRMultiSurface* CastToMultiSurface(OGRMultiPolygon* poMP);
+/**
+ * PolyhedralSurface class.
+ *
+ * @since GDAL 2.2
+ */
+
+class CPL_DLL OGRPolyhedralSurface : public OGRSurface
+{
+  protected:
+//! @cond Doxygen_Suppress
+    friend class OGRTriangulatedSurface;
+    OGRMultiPolygon oMP;
+    virtual OGRSurfaceCasterToPolygon      GetCasterToPolygon()
+        const CPL_OVERRIDE;
+    virtual OGRSurfaceCasterToCurvePolygon GetCasterToCurvePolygon()
+      const CPL_OVERRIDE;
+    virtual OGRBoolean         isCompatibleSubType( OGRwkbGeometryType ) const;
+    virtual const char*        getSubGeometryName() const;
+    virtual OGRwkbGeometryType getSubGeometryType() const;
+    OGRErr exportToWktInternal (char ** ppszDstText, OGRwkbVariant eWkbVariant,
+                                const char* pszSkipPrefix ) const;
+
+    virtual OGRPolyhedralSurfaceCastToMultiPolygon GetCasterToMultiPolygon()
+        const;
+    static OGRMultiPolygon* CastToMultiPolygonImpl(OGRPolyhedralSurface* poPS);
+//! @endcond
+
+  public:
+    OGRPolyhedralSurface();
+    OGRPolyhedralSurface(const OGRPolyhedralSurface &poGeom);
+    virtual ~OGRPolyhedralSurface();
+    OGRPolyhedralSurface& operator=(const OGRPolyhedralSurface& other);
+
+    // IWks Interface.
+    virtual int WkbSize() const CPL_OVERRIDE;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const  CPL_OVERRIDE;
+    virtual OGRErr importFromWkb( unsigned char *, int=-1,
+                                  OGRwkbVariant=wkbVariantOldOgc ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkb( OGRwkbByteOrder, unsigned char *,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char ** ppszDstText,
+                                OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
+
+    // IGeometry methods.
+    virtual int getDimension() const CPL_OVERRIDE;
+
+    virtual void empty() CPL_OVERRIDE;
+
+    virtual OGRGeometry *clone() const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope * psEnvelope ) const CPL_OVERRIDE;
+    virtual void getEnvelope( OGREnvelope3D * psEnvelope ) const CPL_OVERRIDE;
+
+    virtual void flattenTo2D() CPL_OVERRIDE;
+    virtual OGRErr transform( OGRCoordinateTransformation* ) CPL_OVERRIDE;
+    virtual OGRBoolean Equals( OGRGeometry* ) const CPL_OVERRIDE;
+    virtual double get_Area() const CPL_OVERRIDE;
+    virtual OGRErr PointOnSurface( OGRPoint* ) const CPL_OVERRIDE;
+
+    static OGRMultiPolygon* CastToMultiPolygon( OGRPolyhedralSurface* poPS );
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
+    virtual OGRErr addGeometry( const OGRGeometry * );
+    OGRErr addGeometryDirectly( OGRGeometry *poNewGeom );
+    int getNumGeometries() const;
+    OGRGeometry* getGeometryRef(int i);
+    const OGRGeometry* getGeometryRef(int i) const;
+
+    virtual OGRBoolean  IsEmpty() const CPL_OVERRIDE;
+    virtual void setCoordinateDimension( int nDimension ) CPL_OVERRIDE;
+    virtual void set3D( OGRBoolean bIs3D ) CPL_OVERRIDE;
+    virtual void setMeasured( OGRBoolean bIsMeasured ) CPL_OVERRIDE;
+    virtual void swapXY() CPL_OVERRIDE;
+    OGRErr removeGeometry( int iIndex, int bDelete = TRUE );
+};
+
+/************************************************************************/
+/*                        OGRTriangulatedSurface                        */
+/************************************************************************/
+
+/**
+ * TriangulatedSurface class.
+ *
+ * @since GDAL 2.2
+ */
+
+class CPL_DLL OGRTriangulatedSurface : public OGRPolyhedralSurface
+{
+  protected:
+//! @cond Doxygen_Suppress
+    virtual OGRBoolean         isCompatibleSubType( OGRwkbGeometryType )
+        const CPL_OVERRIDE;
+    virtual const char*        getSubGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getSubGeometryType() const CPL_OVERRIDE;
+
+    virtual OGRPolyhedralSurfaceCastToMultiPolygon GetCasterToMultiPolygon()
+        const CPL_OVERRIDE;
+    static OGRMultiPolygon *
+        CastToMultiPolygonImpl( OGRPolyhedralSurface* poPS );
+//! @endcond
+
+  public:
+    OGRTriangulatedSurface();
+    OGRTriangulatedSurface( const OGRTriangulatedSurface &other );
+    ~OGRTriangulatedSurface();
+
+    OGRTriangulatedSurface& operator=( const OGRTriangulatedSurface& other );
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+
+    // IWks Interface.
+    virtual OGRErr addGeometry( const OGRGeometry * ) CPL_OVERRIDE;
+
+    static OGRPolyhedralSurface *
+        CastToPolyhedralSurface( OGRTriangulatedSurface* poTS );
 };
 
 /************************************************************************/
@@ -1221,7 +1609,8 @@ class CPL_DLL OGRMultiPoint : public OGRGeometryCollection
     OGRErr  importFromWkt_Bracketed( char **, int bHasM, int bHasZ );
 
   protected:
-    virtual OGRBoolean  isCompatibleSubType( OGRwkbGeometryType ) const;
+    virtual OGRBoolean  isCompatibleSubType( OGRwkbGeometryType )
+        const CPL_OVERRIDE;
 
   public:
             OGRMultiPoint();
@@ -1230,17 +1619,19 @@ class CPL_DLL OGRMultiPoint : public OGRGeometryCollection
 
     OGRMultiPoint& operator=(const OGRMultiPoint& other);
 
-    // Non standard (OGRGeometry).
-    virtual const char *getGeometryName() const;
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc ) const;
+    // Non-standard (OGRGeometry).
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
 
-    // IGeometry methods
-    virtual int getDimension() const;
+    // IGeometry methods.
+    virtual int getDimension() const CPL_OVERRIDE;
 
-    // Non standard
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
+    // Non-standard.
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
 };
 
 /************************************************************************/
@@ -1256,27 +1647,33 @@ class CPL_DLL OGRMultiPoint : public OGRGeometryCollection
 class CPL_DLL OGRMultiCurve : public OGRGeometryCollection
 {
   protected:
-    static OGRErr addCurveDirectlyFromWkt( OGRGeometry* poSelf, OGRCurve* poCurve );
-    virtual OGRBoolean  isCompatibleSubType( OGRwkbGeometryType ) const;
+//! @cond Doxygen_Suppress
+    static OGRErr addCurveDirectlyFromWkt( OGRGeometry* poSelf,
+                                           OGRCurve* poCurve );
+//! @endcond
+    virtual OGRBoolean isCompatibleSubType( OGRwkbGeometryType )
+        const CPL_OVERRIDE;
 
   public:
             OGRMultiCurve();
-            OGRMultiCurve(const OGRMultiCurve& other);
+            OGRMultiCurve( const OGRMultiCurve& other );
     virtual ~OGRMultiCurve();
 
-    OGRMultiCurve& operator=(const OGRMultiCurve& other);
+    OGRMultiCurve& operator=( const OGRMultiCurve& other );
 
     // Non standard (OGRGeometry).
-    virtual const char *getGeometryName() const;
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual OGRErr importFromWkt( char ** );
-    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc ) const;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual OGRErr importFromWkt( char ** ) CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
 
-    // IGeometry methods
-    virtual int getDimension() const;
+    // IGeometry methods.
+    virtual int getDimension() const CPL_OVERRIDE;
 
-    // Non standard
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
+    // Non-standard.
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
 
     static OGRMultiLineString* CastToMultiLineString(OGRMultiCurve* poMC);
 };
@@ -1292,27 +1689,29 @@ class CPL_DLL OGRMultiCurve : public OGRGeometryCollection
 class CPL_DLL OGRMultiLineString : public OGRMultiCurve
 {
   protected:
-    virtual OGRBoolean  isCompatibleSubType( OGRwkbGeometryType ) const;
+    virtual OGRBoolean  isCompatibleSubType( OGRwkbGeometryType )
+        const CPL_OVERRIDE;
 
   public:
             OGRMultiLineString();
-            OGRMultiLineString(const OGRMultiLineString& other);
+            OGRMultiLineString( const OGRMultiLineString& other );
     virtual ~OGRMultiLineString();
 
-    OGRMultiLineString& operator=(const OGRMultiLineString& other);
+    OGRMultiLineString& operator=( const OGRMultiLineString& other );
 
     // Non standard (OGRGeometry).
-    virtual const char *getGeometryName() const;
-    virtual OGRwkbGeometryType getGeometryType() const;
-    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc ) const;
+    virtual const char *getGeometryName() const CPL_OVERRIDE;
+    virtual OGRwkbGeometryType getGeometryType() const CPL_OVERRIDE;
+    virtual OGRErr exportToWkt( char **, OGRwkbVariant=wkbVariantOldOgc )
+        const CPL_OVERRIDE;
 
     // Non standard
-    virtual OGRBoolean hasCurveGeometry(int bLookForNonLinear = FALSE) const;
+    virtual OGRBoolean hasCurveGeometry( int bLookForNonLinear = FALSE )
+        const CPL_OVERRIDE;
 
-    static OGRMultiCurve* CastToMultiCurve(OGRMultiLineString* poMLS);
+    static OGRMultiCurve* CastToMultiCurve( OGRMultiLineString* poMLS );
 };
 
-
 /************************************************************************/
 /*                          OGRGeometryFactory                          */
 /************************************************************************/
@@ -1331,19 +1730,22 @@ class CPL_DLL OGRGeometryFactory
                                          int nRecLevel );
   public:
     static OGRErr createFromWkb( unsigned char *, OGRSpatialReference *,
-                                 OGRGeometry **, int = -1, OGRwkbVariant=wkbVariantOldOgc );
+                                 OGRGeometry **, int = -1,
+                                 OGRwkbVariant=wkbVariantOldOgc );
     static OGRErr createFromWkt( char **, OGRSpatialReference *,
                                  OGRGeometry ** );
     static OGRErr createFromFgf( unsigned char *, OGRSpatialReference *,
                                  OGRGeometry **, int = -1, int * = NULL );
     static OGRGeometry *createFromGML( const char * );
-    static OGRGeometry *createFromGEOS( GEOSContextHandle_t hGEOSCtxt, GEOSGeom );
+    static OGRGeometry *createFromGEOS( GEOSContextHandle_t hGEOSCtxt,
+                                        GEOSGeom );
 
     static void   destroyGeometry( OGRGeometry * );
     static OGRGeometry *createGeometry( OGRwkbGeometryType );
 
     static OGRGeometry * forceToPolygon( OGRGeometry * );
-    static OGRGeometry * forceToLineString( OGRGeometry *, bool bOnlyInOrder = true );
+    static OGRGeometry * forceToLineString( OGRGeometry *,
+                                            bool bOnlyInOrder = true );
     static OGRGeometry * forceToMultiPolygon( OGRGeometry * );
     static OGRGeometry * forceToMultiPoint( OGRGeometry * );
     static OGRGeometry * forceToMultiLineString( OGRGeometry * );
@@ -1356,7 +1758,7 @@ class CPL_DLL OGRGeometryFactory
                                            int nPolygonCount,
                                            int *pbResultValidGeometry,
                                            const char **papszOptions = NULL);
-    static int haveGEOS();
+    static bool haveGEOS();
 
     static OGRGeometry* transformWithOptions( const OGRGeometry* poSrcGeom,
                                               OGRCoordinateTransformation *poCT,
@@ -1369,25 +1771,28 @@ class CPL_DLL OGRGeometryFactory
                               double dfStartAngle, double dfEndAngle,
                               double dfMaxAngleStepSizeDegrees );
 
-    static int GetCurveParmeters(double x0, double y0,
-                                 double x1, double y1,
-                                 double x2, double y2,
-                                 double& R, double& cx, double& cy,
-                                 double& alpha0, double& alpha1, double& alpha2 );
-    static OGRLineString* curveToLineString( double x0, double y0, double z0,
-                                             double x1, double y1, double z1,
-                                             double x2, double y2, double z2,
-                                             int bHasZ,
-                                             double dfMaxAngleStepSizeDegrees,
-                                             const char*const* papszOptions = NULL );
-    static OGRCurve* curveFromLineString(const OGRLineString* poLS,
-                                         const char*const* papszOptions = NULL);
+    static int GetCurveParmeters( double x0, double y0,
+                                  double x1, double y1,
+                                  double x2, double y2,
+                                  double& R, double& cx, double& cy,
+                                  double& alpha0, double& alpha1,
+                                  double& alpha2 );
+    static OGRLineString* curveToLineString(
+        double x0, double y0, double z0,
+        double x1, double y1, double z1,
+        double x2, double y2, double z2,
+        int bHasZ,
+        double dfMaxAngleStepSizeDegrees,
+        const char* const * papszOptions = NULL );
+    static OGRCurve* curveFromLineString(
+        const OGRLineString* poLS,
+        const char* const * papszOptions = NULL);
 };
 
 OGRwkbGeometryType CPL_DLL OGRFromOGCGeomType( const char *pszGeomType );
 const char CPL_DLL * OGRToOGCGeomType( OGRwkbGeometryType eGeomType );
 
-/* Prepared geometry API (needs GEOS >= 3.1.0) */
+/** Prepared geometry API (needs GEOS >= 3.1.0) */
 typedef struct _OGRPreparedGeometry OGRPreparedGeometry;
 int OGRHasPreparedGeometrySupport();
 OGRPreparedGeometry* OGRCreatePreparedGeometry( const OGRGeometry* poGeom );
diff --git a/ogr/ogr_geos.h b/ogr/ogr_geos.h
index 19e75e4..b47a821 100644
--- a/ogr/ogr_geos.h
+++ b/ogr/ogr_geos.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geos.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogr_geos.h 34523 2016-07-02 21:50:47Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Definitions related to support for use of GEOS in OGR.
diff --git a/ogr/ogr_json_header.h b/ogr/ogr_json_header.h
new file mode 100644
index 0000000..c9a1b98
--- /dev/null
+++ b/ogr/ogr_json_header.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes json-c header
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef OGR_JSON_HEADER_H
+#define OGR_JSON_HEADER_H
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+#include <json.h>
+
+#endif /* OGR_JSON_HEADER_H */
diff --git a/ogr/ogr_libs.h b/ogr/ogr_libs.h
new file mode 100644
index 0000000..30e2cb3
--- /dev/null
+++ b/ogr/ogr_libs.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * $Id: ogr_libs.h 36883 2016-12-15 13:31:12Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Definitions related to support for use of SFCGAL and GEOS in OGR.
+ *           This file is only intended to be pulled in by OGR implementation
+ *           code directly accessing SFCGAL and/or GEOS.
+ * Author:   Avyav Kumar Singh <avyavkumar at gmail dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Avyav Kumar Singh <avyavkumar at gmail dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef HAVE_GEOS
+#define UNUSED_IF_NO_GEOS CPL_UNUSED
+#else
+#define UNUSED_IF_NO_GEOS
+#endif
+
+#ifndef HAVE_SFCGAL
+#define UNUSED_IF_NO_SFCGAL CPL_UNUSED
+#else
+#define UNUSED_IF_NO_SFCGAL
+#endif
+
+#ifndef UNUSED_PARAMETER
+
+#ifdef HAVE_GEOS
+#ifndef HAVE_SFCGAL
+#define UNUSED_PARAMETER UNUSED_IF_NO_SFCGAL    // SFCGAL no and GEOS yes - GEOS methods always work
+#else
+#define UNUSED_PARAMETER                        // Both libraries are present
+#endif
+#endif
+
+#ifndef HAVE_GEOS
+#ifdef HAVE_SFCGAL
+#define UNUSED_PARAMETER UNUSED_IF_NO_GEOS      // SFCGAL yes and GEOS no - SFCGAL methods always work
+#else
+#define UNUSED_PARAMETER CPL_UNUSED             // Neither of the libraries have support enabled
+#endif
+#endif
+
+#endif
diff --git a/ogr/ogr_opt.cpp b/ogr/ogr_opt.cpp
index 38acf73..e424a9e 100644
--- a/ogr/ogr_opt.cpp
+++ b/ogr/ogr_opt.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_opt.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features
  * Purpose:  Functions for getting list of projection types, and their parms.
@@ -28,10 +27,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_srs_api.h"
+
+#include <cstddef>
+
+#include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogr_opt.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogr_opt.cpp 36290 2016-11-19 06:42:09Z goatbar $");
 
 static const char * const papszParameterDefinitions[] = {
     SRS_PP_CENTRAL_MERIDIAN,    "Central Meridian",     "Long",  "0.0",
@@ -61,7 +65,6 @@ static const char * const papszParameterDefinitions[] = {
 };
 
 static const char * const papszProjectionDefinitions[] = {
-
     "*",
     SRS_PT_TRANSVERSE_MERCATOR,
     "Transverse Mercator",
@@ -489,9 +492,6 @@ static const char * const papszProjectionDefinitions[] = {
     NULL
 };
 
-
-
-
 /************************************************************************/
 /*                      OPTGetProjectionMethods()                       */
 /************************************************************************/
@@ -506,13 +506,12 @@ static const char * const papszProjectionDefinitions[] = {
 char **OPTGetProjectionMethods()
 
 {
-    int         i;
-    char        **papszList = NULL;
+    char **papszList = NULL;
 
-    for( i = 1; papszProjectionDefinitions[i] != NULL; i++ )
+    for( int i = 1; papszProjectionDefinitions[i] != NULL; ++i )
     {
-        if( EQUAL(papszProjectionDefinitions[i-1],"*") )
-            papszList = CSLAddString(papszList,papszProjectionDefinitions[i]);
+        if( EQUAL(papszProjectionDefinitions[i-1], "*") )
+            papszList = CSLAddString(papszList, papszProjectionDefinitions[i]);
     }
 
     return papszList;
@@ -543,28 +542,28 @@ char **OPTGetParameterList( const char *pszProjectionMethod,
 
 {
     char **papszList = NULL;
-    int  i;
 
-    for( i = 1; papszProjectionDefinitions[i] != NULL; i++ )
+    for( int i = 1; papszProjectionDefinitions[i] != NULL; ++i )
     {
         if( papszProjectionDefinitions[i-1][0] == '*'
-            && EQUAL(papszProjectionDefinitions[i],pszProjectionMethod) )
+            && EQUAL(papszProjectionDefinitions[i], pszProjectionMethod) )
         {
-            i++;
+            ++i;
 
             if( ppszUserName != NULL )
                 *ppszUserName = (char *)papszProjectionDefinitions[i];
 
-            i++;
+            ++i;
             while( papszProjectionDefinitions[i] != NULL
                    && papszProjectionDefinitions[i][0] != '*' )
             {
                 papszList = CSLAddString( papszList,
                                           papszProjectionDefinitions[i] );
-                i++;
+                ++i;
             }
-            if( papszList == NULL) /* IGH has no parameter, so return an empty list instead of NULL */
-                papszList = (char**) CPLCalloc(1, sizeof(char*));
+            // IGH has no parameter, so return an empty list instead of NULL.
+            if( papszList == NULL)
+                papszList = static_cast<char**>( CPLCalloc(1, sizeof(char*)) );
             return papszList;
         }
     }
@@ -592,7 +591,7 @@ char **OPTGetParameterList( const char *pszProjectionMethod,
  * returned name should not be modified or freed.
  *
  * @param ppszType location at which to return the parameter type for
- * the parameter.  This pointer may be NULL to skip.  The  returned type
+ * the parameter.  This pointer may be NULL to skip.  The returned type
  * should not be modified or freed.  The type values are described above.
  *
  * @param pdfDefaultValue location at which to put the default value for
@@ -601,25 +600,22 @@ char **OPTGetParameterList( const char *pszProjectionMethod,
  * @return TRUE if parameter found, or FALSE otherwise.
  */
 
-int OPTGetParameterInfo( const char * pszProjectionMethod,
+int OPTGetParameterInfo( CPL_UNUSED const char * pszProjectionMethod,
                          const char * pszParameterName,
                          char ** ppszUserName,
                          char ** ppszType,
                          double *pdfDefaultValue )
 
 {
-    int         i;
-
-    (void) pszProjectionMethod;
-
-    for( i = 0; papszParameterDefinitions[i] != NULL; i += 4 )
+    for( int i = 0; papszParameterDefinitions[i] != NULL; i += 4 )
     {
-        if( EQUAL(papszParameterDefinitions[i],pszParameterName) )
+        if( EQUAL(papszParameterDefinitions[i], pszParameterName) )
         {
             if( ppszUserName != NULL )
-                *ppszUserName = (char *)papszParameterDefinitions[i+1];
+                *ppszUserName =
+                    const_cast<char *>(papszParameterDefinitions[i+1]);
             if( ppszType != NULL )
-                *ppszType = (char *)papszParameterDefinitions[i+2];
+                *ppszType = const_cast<char *>(papszParameterDefinitions[i+2]);
             if( pdfDefaultValue != NULL )
                 *pdfDefaultValue = CPLAtof(papszParameterDefinitions[i+3]);
 
diff --git a/ogr/ogr_p.h b/ogr/ogr_p.h
index 359df8b..d17138a 100644
--- a/ogr/ogr_p.h
+++ b/ogr/ogr_p.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_p.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogr_p.h 37564 2017-03-03 09:09:26Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Some private helper functions and stuff for OGR implementation.
@@ -109,8 +109,8 @@ char CPL_DLL * OGRGetRFC822DateTime(const OGRField* psField);
 char CPL_DLL * OGRGetXMLDateTime(const OGRField* psField);
 char CPL_DLL * OGRGetXML_UTF8_EscapedString(const char* pszString);
 
-int OGRCompareDate(   OGRField *psFirstTuple,
-                      OGRField *psSecondTuple ); /* used by ogr_gensql.cpp and ogrfeaturequery.cpp */
+int OGRCompareDate(const OGRField *psFirstTuple,
+                   const OGRField *psSecondTuple ); /* used by ogr_gensql.cpp and ogrfeaturequery.cpp */
 
 /* General utility option processing. */
 int CPL_DLL OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions );
diff --git a/ogr/ogr_sfcgal.h b/ogr/ogr_sfcgal.h
new file mode 100644
index 0000000..91b7835
--- /dev/null
+++ b/ogr/ogr_sfcgal.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * $Id: ogr_sfcgal.h 36883 2016-12-15 13:31:12Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Definitions related to support for use of SFCGAL in OGR.
+ *           This file is only intended to be pulled in by OGR implementation
+ *           code directly accessing SFCGAL.
+ * Author:   Avyav Kumar Singh <avyavkumar at gmail dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Avyav Kumar Singh <avyavkumar at gmail dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifdef HAVE_SFCGAL
+
+#include <SFCGAL/capi/sfcgal_c.h>
+
+#endif
diff --git a/ogr/ogr_spatialref.h b/ogr/ogr_spatialref.h
index f12ff22..da841f5 100644
--- a/ogr/ogr_spatialref.h
+++ b/ogr/ogr_spatialref.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_spatialref.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogr_spatialref.h 36411 2016-11-21 22:03:48Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes for manipulating spatial reference systems in a
@@ -70,9 +70,12 @@ class CPL_DLL OGR_SRSNode
     OGRErr      importFromWkt( char **, int nRecLevel, int* pnNodes );
 
   public:
-                OGR_SRSNode(const char * = NULL);
+    explicit     OGR_SRSNode(const char * = NULL);
                 ~OGR_SRSNode();
 
+    /** Return whether this is a leaf node.
+     * @return TRUE or FALSE
+     */
     int         IsLeafNode() const { return nChildren == 0; }
 
     int         GetChildCount() const { return nChildren; }
@@ -151,7 +154,7 @@ class CPL_DLL OGRSpatialReference
                                   const char* pszURN);
   public:
                 OGRSpatialReference(const OGRSpatialReference&);
-                OGRSpatialReference(const char * = NULL);
+    explicit    OGRSpatialReference(const char * = NULL);
 
     virtual    ~OGRSpatialReference();
 
@@ -186,9 +189,10 @@ class CPL_DLL OGRSpatialReference
     OGRErr      importFromESRI( char ** );
     OGRErr      importFromPCI( const char *, const char * = NULL,
                                double * = NULL );
-#define USGS_ANGLE_DECIMALDEGREES 0
-#define USGS_ANGLE_PACKEDDMS      TRUE /* 1 */
-#define USGS_ANGLE_RADIANS        2
+
+#define USGS_ANGLE_DECIMALDEGREES 0     /**< Angle is in decimal degrees. */
+#define USGS_ANGLE_PACKEDDMS      TRUE  /**< Angle is in packed degree minute second. */
+#define USGS_ANGLE_RADIANS        2     /**< Angle is in radians. */
     OGRErr      importFromUSGS( long iProjSys, long iZone,
                                 double *padfPrjParams, long iDatum,
                                 int nUSGSAngleFormat = USGS_ANGLE_PACKEDDMS );
@@ -224,7 +228,10 @@ class CPL_DLL OGRSpatialReference
                          OGRAxisOrientation eYAxisOrientation );
 
     // Machinery for accessing parse nodes
+
+    //! Return root node
     OGR_SRSNode *GetRoot() { return poRoot; }
+    //! Return root node
     const OGR_SRSNode *GetRoot() const { return poRoot; }
     void        SetRoot( OGR_SRSNode * );
 
@@ -347,13 +354,15 @@ class CPL_DLL OGRSpatialReference
                        double dfCenterLat, double dfCenterLong,
                        double dfFalseEasting, double dfFalseNorthing );
 
-    /** Eckert I-VI */
+    /** Eckert I */
     OGRErr      SetEckert( int nVariation, double dfCentralMeridian,
                            double dfFalseEasting, double dfFalseNorthing );
 
+    /** Eckert IV */
     OGRErr      SetEckertIV( double dfCentralMeridian,
                              double dfFalseEasting, double dfFalseNorthing );
 
+    /** Eckert VI */
     OGRErr      SetEckertVI( double dfCentralMeridian,
                              double dfFalseEasting, double dfFalseNorthing );
 
@@ -395,12 +404,14 @@ class CPL_DLL OGRSpatialReference
                         double dfScale,
                         double dfFalseEasting, double dfFalseNorthing );
 
+    /**  Hotine Oblique Mercator 2 points */
     OGRErr      SetHOM2PNO( double dfCenterLat,
                             double dfLat1, double dfLong1,
                             double dfLat2, double dfLong2,
                             double dfScale,
                             double dfFalseEasting, double dfFalseNorthing );
 
+    /** Oblique Mercator */
     OGRErr      SetOM( double dfCenterLat, double dfCenterLong,
                        double dfAzimuth, double dfRectToSkew,
                        double dfScale,
@@ -447,11 +458,12 @@ class CPL_DLL OGRSpatialReference
     OGRErr      SetMC( double dfCenterLat, double dfCenterLong,
                        double dfFalseEasting, double dfFalseNorthing );
 
-    /** Mercator */
+    /** Mercator 1SP */
     OGRErr      SetMercator( double dfCenterLat, double dfCenterLong,
                              double dfScale,
                              double dfFalseEasting, double dfFalseNorthing );
 
+    /** Mercator 2SP */
     OGRErr      SetMercator2SP( double dfStdP1,
                                 double dfCenterLat, double dfCenterLong,
                                 double dfFalseEasting, double dfFalseNorthing );
@@ -547,9 +559,12 @@ class CPL_DLL OGRSpatialReference
                                const char *pszOverrideUnitName = NULL,
                                double dfOverrideUnit = 0.0 );
 
+    /** ImportFromESRIStatePlaneWKT */
     OGRErr      ImportFromESRIStatePlaneWKT(
         int nCode, const char* pszDatumName, const char* pszUnitsName,
         int nPCSCode, const char* pszCSName = NULL );
+
+    /** ImportFromESRIWisconsinWKT */
     OGRErr      ImportFromESRIWisconsinWKT(
         const char* pszPrjName, double dfCentralMeridian, double dfLatOfOrigin,
         const char* pszUnitsName, const char* pszCSName = NULL );
@@ -588,6 +603,12 @@ public:
     /** Fetch internal target coordinate system. */
     virtual OGRSpatialReference *GetTargetCS() = 0;
 
+    /** Whether the transformer will emit CPLError */
+    virtual bool GetEmitErrors() { return false; }
+
+    /** Set if the transformer must emit CPLError */
+    virtual void SetEmitErrors(bool /*bEmitErrors*/) {}
+
     // From CT_MathTransform
 
     /**
@@ -626,7 +647,6 @@ public:
     virtual int TransformEx( int nCount,
                              double *x, double *y, double *z = NULL,
                              int *pabSuccess = NULL ) = 0;
-
 };
 
 OGRCoordinateTransformation CPL_DLL *
diff --git a/ogr/ogr_sql.dox b/ogr/ogr_sql.dox
index 6840078..9f7cacd 100644
--- a/ogr/ogr_sql.dox
+++ b/ogr/ogr_sql.dox
@@ -1,24 +1,24 @@
 /*! \page ogr_sql OGR SQL
 
 The GDALDataset supports executing commands against a datasource via the
-GDALDataset::ExecuteSQL() method.  While in theory 
-any sort of command could be handled this way, in practice the mechanism is 
-used to provide a subset of SQL SELECT capability to applications.  This 
-page discusses the generic SQL implementation implemented within OGR, and 
+GDALDataset::ExecuteSQL() method.  While in theory
+any sort of command could be handled this way, in practice the mechanism is
+used to provide a subset of SQL SELECT capability to applications.  This
+page discusses the generic SQL implementation implemented within OGR, and
 issue with driver specific SQL support.<p>
 
 Since GDAL/OGR 1.10, an alternate "dialect", the SQLite dialect, can be used
 instead of the OGRSQL dialect. Refer to the
 <b><a href="ogr_sql_sqlite.html">SQLite SQL dialect</a></b> page for more details.<p>
 
-The OGRLayer class also supports applying an attribute query filter to 
+The OGRLayer class also supports applying an attribute query filter to
 features returned using the OGRLayer::SetAttributeFilter() method.  The
-syntax for the attribute filter is the same as the WHERE clause in the 
-OGR SQL SELECT statement.  So everything here with regard to the WHERE 
+syntax for the attribute filter is the same as the WHERE clause in the
+OGR SQL SELECT statement.  So everything here with regard to the WHERE
 clause applies in the context of the SetAttributeFilter() method.<p>
 
 NOTE: OGR SQL has been reimplemented for GDAL/OGR 1.8.0.  Many features
-discussed below, notably arithmetic expressions, and expressions in the 
+discussed below, notably arithmetic expressions, and expressions in the
 field list, were not support in GDAL/OGR 1.7.x and earlier.  See RFC 28 for
 details of the new features in GDAL/OGR 1.8.0.
 
@@ -26,7 +26,7 @@ details of the new features in GDAL/OGR 1.8.0.
 
 The SELECT statement is used to fetch layer features (analogous to table
 rows in an RDBMS) with the result of the query represented as a temporary layer
-of features.   The layers of the datasource are analogous to tables in an 
+of features.   The layers of the datasource are analogous to tables in an
 RDBMS and feature attributes are analogous to column values.  The simplest
 form of OGR SQL SELECT statement looks like this:
 
@@ -35,9 +35,9 @@ SELECT * FROM polylayer
 \endcode
 
 In this case all features are fetched from the layer named "polylayer", and
-all attributes of those features are returned.  This is essentially 
-equivalent to accessing the layer directly.  In this example the "*" 
-is the list of fields to fetch from the layer, with "*" meaning that all 
+all attributes of those features are returned.  This is essentially
+equivalent to accessing the layer directly.  In this example the "*"
+is the list of fields to fetch from the layer, with "*" meaning that all
 fields should be fetched.
 
 This slightly more sophisticated form still pulls all features from the layer
@@ -57,12 +57,20 @@ SELECT * from polylayer WHERE prop_value > 220000.0 ORDER BY prop_value DESC
 
 This select statement will produce a table with just one feature, with one
 attribute (named something like "count_eas_id") containing the number of
-distinct values of the eas_id attribute. 
+distinct values of the eas_id attribute.
 
 \code
 SELECT COUNT(DISTINCT eas_id) FROM polylayer
 \endcode
 
+\subsection ogr_sql_select_syntax General syntax
+
+The general syntax of a SELECT statement is:
+
+\code
+SELECT [fields] FROM layer_name [JOIN ...] [WHERE ...] [ORDER BY ...] [LIMIT ...] [OFFSET ...]
+\endcode
+
 \subsection ogr_sql_flist_ops Field List Operators
 
 The field list is a comma separate list of the fields to be carried into
@@ -70,14 +78,14 @@ the output features from the source layer.  They will appear on output features
 in the order they appear on in the field list, so the field list may be used
 to re-order the fields.<p>
 
-A special form of the field list uses the DISTINCT keyword.  This returns a 
-list of all the distinct values of the named attribute.  When the DISTINCT 
+A special form of the field list uses the DISTINCT keyword.  This returns a
+list of all the distinct values of the named attribute.  When the DISTINCT
 keyword is used, only one attribute may appear in the field list.  The DISTINCT
 keyword may be used against any type of field.  Currently the distinctness
 test against a string value is case insensitive in OGR SQL.  The result of
 a SELECT with a DISTINCT keyword is a layer with one column (named the same
 as the field operated on), and one feature per distinct value.  Geometries
-are discarded.  The distinct values are assembled in memory, so a lot of 
+are discarded.  The distinct values are assembled in memory, so a lot of
 memory may be used for datasets with a large number of distinct values.
 
 \code
@@ -87,13 +95,13 @@ SELECT DISTINCT areacode FROM polylayer
 There are also several summarization operators that may be applied to columns.
 When a summarization operator is applied to any field, then all fields must
 have summarization operators applied.   The summarization operators are
-COUNT (a count of instances), AVG (numerical average), SUM (numerical sum), 
-MIN (lexical or numerical minimum), and MAX (lexical or numerical maximum). 
+COUNT (a count of instances), AVG (numerical average), SUM (numerical sum),
+MIN (lexical or numerical minimum), and MAX (lexical or numerical maximum).
 This example produces a variety of summarization information on parcel
 property values:
 
 \code
-SELECT MIN(prop_value), MAX(prop_value), AVG(prop_value), SUM(prop_value), 
+SELECT MIN(prop_value), MAX(prop_value), AVG(prop_value), SUM(prop_value),
        COUNT(prop_value) FROM polylayer WHERE prov_name = 'Ontario'
 \endcode
 
@@ -116,12 +124,12 @@ SELECT COUNT(*) FROM polylayer
 \endcode
 
 
-Field names can also be prefixed by a table name though this is only 
-really meaningful when performing joins.  It is further demonstrated in 
+Field names can also be prefixed by a table name though this is only
+really meaningful when performing joins.  It is further demonstrated in
 the JOIN section.
 
-Field definitions can also be complex expressions using arithmetic, and 
-functional operators.   However, the DISTINCT keyword, and summarization 
+Field definitions can also be complex expressions using arithmetic, and
+functional operators.   However, the DISTINCT keyword, and summarization
 operators like MIN, MAX, AVG and SUM may not be applied to expression fields.
 Starting with GDAL 2.0, boolean resulting expressions (comparisons, logical
 operators) can also be used.
@@ -207,8 +215,8 @@ Currently casting to the following target types are supported:
 
 Specifying the field_length and/or the field_precision is optional.  An
 explicit value of zero can be used as the width for character() to indicate
-variable width.  Conversion to the 'integer list', 'double list' 
-and 'string list' OGR data types are not supported, which doesn't conform to 
+variable width.  Conversion to the 'integer list', 'double list'
+and 'string list' OGR data types are not supported, which doesn't conform to
 the SQL92 specification.
 
 While the CAST operator can be applied anywhere in an expression, including
@@ -236,28 +244,28 @@ be surrounded with double-quote characters. e.g. WHERE "from" = 5.
 
 \subsection ogr_sql_where WHERE
 
-The argument to the WHERE clause is a logical expression used select records 
-from the source layer.  In addition to its use within the WHERE statement, 
-the WHERE clause handling is also used for OGR attribute queries on regular 
+The argument to the WHERE clause is a logical expression used select records
+from the source layer.  In addition to its use within the WHERE statement,
+the WHERE clause handling is also used for OGR attribute queries on regular
 layers via OGRLayer::SetAttributeFilter().
 
 In addition to the arithmetic and other functional operators available in
-expressions in the field selection clause of the SELECT statement, in the 
+expressions in the field selection clause of the SELECT statement, in the
 WHERE context logical operators are also available and the evaluated value
 of the expression should be logical (true or false).
 
-The available logical operators are 
-<b>=</b>, 
-<b>!=</b>, 
-<b><></b>, 
-<b><</b>, 
-<b>></b>, 
-<b><=</b>, 
-<b>>=</b>, 
-<b>LIKE</b> and 
+The available logical operators are
+<b>=</b>,
+<b>!=</b>,
+<b><></b>,
+<b><</b>,
+<b>></b>,
+<b><=</b>,
+<b>>=</b>,
+<b>LIKE</b> and
 <b>ILIKE</b>,
 <b>BETWEEN</b> and
-<b>IN</b>. 
+<b>IN</b>.
 Most of the operators are self explanatory, but it is worth noting that <b>
 !=</b> is the same as <b><></b>, the string equality is
 case insensitive, but the <b><</b>, <b>></b>, <b><=</b> and <b>>=</b> operators <i>are</i> case sensitive.  Both the LIKE and ILIKE operators are case insensitive.
@@ -283,7 +291,7 @@ as regular characters, by being preceded with the escape_char.
 \endcode
 
 The <b>IN</b> takes a list of values as it's argument and tests the attribute
-value for membership in the provided set.  
+value for membership in the provided set.
 
 \code
     Value              Value Set            Matches?
@@ -299,10 +307,10 @@ and it is equivalent to "field_name >= value1 AND field_name <= value2".
 
 In addition to the above binary operators, there are additional operators
 for testing if a field is null or not. These are the <b>IS NULL</b>
-and <b>IS NOT NULL</b> operators. 
+and <b>IS NOT NULL</b> operators.
 
 Basic field tests can be combined in more complicated predicates using logical
-operators include <b>AND</b>, <b>OR</b>, and the unary logical <b>NOT</b>.  
+operators include <b>AND</b>, <b>OR</b>, and the unary logical <b>NOT</b>.
 Subexpressions should be bracketed to make precedence
 clear.  Some more complicated predicates are:
 
@@ -323,13 +331,13 @@ clause).
 \subsection ogr_sql_order_by ORDER BY
 
 The <b>ORDER BY</b> clause is used force the returned features to be reordered
-into sorted order (ascending or descending) on one of the field values.  
+into sorted order (ascending or descending) on one of the field values.
 Ascending (increasing) order is the default if neither the ASC or DESC keyword
 is provided.  For example:
 
 \code
 SELECT * FROM property WHERE class_code = 7 ORDER BY prop_value DESC
-SELECT * FROM property ORDER BY prop_value 
+SELECT * FROM property ORDER BY prop_value
 SELECT * FROM property ORDER BY prop_value ASC
 SELECT DISTINCT zip_code FROM property ORDER BY zip_code
 \endcode
@@ -338,11 +346,34 @@ Note that ORDER BY clauses cause two passes through the feature set.  One to
 build an in-memory table of field values corresponded with feature ids, and
 a second pass to fetch the features by feature id in the sorted order. For
 formats which cannot efficiently randomly read features by feature id this can
-be a very expensive operation.  
+be a very expensive operation.
 
 Sorting of string field values is case sensitive, not case insensitive like in
 most other parts of OGR SQL.
 
+\subsection ogr_sql_limit_offset LIMIT and OFFSET
+
+Starting with GDAL 2.2, the <b>LIMIT</b> clause can be used to limit the
+number of features returned. For example
+
+\code
+SELECT * FROM poly LIMIT 5
+\endcode
+
+The <b>OFFSET</b> clause can be used to skip the first features of the result
+set. The value after OFFSET is the number of features skipped. For example, to
+skip the first 3 features from the result set:
+
+\code
+SELECT * FROM poly OFFSET 3
+\endcode
+
+Both clauses can be combined:
+
+\code
+SELECT * FROM poly LIMIT 5 OFFSET 3
+\endcode
+
 \subsection ogr_sql_joins JOINs
 
 OGR SQL supports a limited form of one to one JOIN.  This allows records from
@@ -353,34 +384,34 @@ secondary <em>nation</em> table to fetch a nation name.  A joined query might
 look like:
 
 \code
-SELECT city.*, nation.name FROM city 
+SELECT city.*, nation.name FROM city
      LEFT JOIN nation ON city.nation_id = nation.id
 \endcode
 
 This query would result in a table with all the fields from the city table,
 and an additional "nation.name" field with the nation name pulled from the
 nation table by looking for the record in the nation table that has the "id"
-field with the same value as the city.nation_id field. 
+field with the same value as the city.nation_id field.
 
 Joins introduce a number of additional issues.  One is the concept of table
 qualifiers on field names.  For instance, referring to city.nation_id instead
 of just nation_id to indicate the nation_id field from the city layer.  The
-table name qualifiers may only be used in the field list, and within the 
-<b>ON</b> clause of the join.  
+table name qualifiers may only be used in the field list, and within the
+<b>ON</b> clause of the join.
 
-Wildcards are also somewhat more involved.  All fields from the primary table 
+Wildcards are also somewhat more involved.  All fields from the primary table
 (<em>city</em> in this case) and the secondary table (<em>nation</em> in this
 case) may be selected using the usual <b>*</b> wildcard.  But the fields of
 just one of the primary or secondary table may be selected by prefixing the
-asterix with the table name.  
+asterix with the table name.
 
 The field names in the resulting query layer will be qualified by the table
 name, if the table name is given as a qualifier in the field list.  In addition
-field names will be qualified with a table name if they would conflict with 
+field names will be qualified with a table name if they would conflict with
 earlier fields.  For instance, the following select would result might result
 in a results set with a <em>name, nation_id, nation.nation_id</em> and <em>
-nation.name</em> field if the city and nation tables both have the 
-<em>nation_id</em> and <em>name</em> fieldnames.  
+nation.name</em> field if the city and nation tables both have the
+<em>nation_id</em> and <em>name</em> fieldnames.
 
 \code
 SELECT * FROM city LEFT JOIN nation ON city.nation_id = nation.nation_id
@@ -389,35 +420,35 @@ SELECT * FROM city LEFT JOIN nation ON city.nation_id = nation.nation_id
 On the other hand if the nation table had a <em>continent_id</em> field, but
 the city table did not, then that field would not need to be qualified in
 the result set.  However, if the selected instead looked like the following
-statement, all result fields would be qualified by the table name. 
+statement, all result fields would be qualified by the table name.
 
 \code
-SELECT city.*, nation.* FROM city 
+SELECT city.*, nation.* FROM city
     LEFT JOIN nation ON city.nation_id = nation.nation_id
 \endcode
 
-In the above examples, the <em>nation</em> table was found in the same 
+In the above examples, the <em>nation</em> table was found in the same
 datasource as the <em>city</em> table.   However, the OGR join support
-includes the ability to join against a table in a different data source, 
-potentially of a different format.  This is indicated by qualifying the 
+includes the ability to join against a table in a different data source,
+potentially of a different format.  This is indicated by qualifying the
 secondary table name with a datasource name.  In this case the secondary
 datasource is opened using normal OGR semantics and utilized to access the
 secondary table until the query result is no longer needed.
 
 \code
-SELECT * FROM city 
+SELECT * FROM city
   LEFT JOIN '/usr2/data/nation.dbf'.nation ON city.nation_id = nation.nation_id
 \endcode
 
 While not necessarily very useful, it is also possible to introduce table
-aliases to simplify some SELECT statements.  This can also be useful to 
-disambiguate situations where tables of the same name are being used from 
+aliases to simplify some SELECT statements.  This can also be useful to
+disambiguate situations where tables of the same name are being used from
 different data sources.  For instance, if the actual
 tables names were messy we might want to do something like:
 
 \code
 SELECT c.name, n.name FROM project_615_city c
-  LEFT JOIN '/usr2/data/project_615_nation.dbf'.project_615_nation n 
+  LEFT JOIN '/usr2/data/project_615_nation.dbf'.project_615_nation n
             ON c.nation_id = n.nation_id
 \endcode
 
@@ -442,21 +473,21 @@ after FROM) and the table of the active JOIN.
 
 <ol>
 <li> Joins can be very expensive operations if the secondary table is not
-indexed on the key field being used. 
+indexed on the key field being used.
 <li> Joined fields may not be used in WHERE clauses, or ORDER BY clauses
-at this time.  The join is essentially evaluated after all primary table 
+at this time.  The join is essentially evaluated after all primary table
 subsetting is complete, and after the ORDER BY pass.
 <li> Joined fields may not be used as keys in later joins.  So you could not
 use the province id in a city to lookup the province record, and then use a
 nation id from the province id to lookup the nation record.  This is a sensible
 thing to want and could be implemented, but is not currently supported.
-<li> Datasource names for joined tables are evaluated relative to the 
+<li> Datasource names for joined tables are evaluated relative to the
 current processes working directory, not the path to the primary datasource.
 <li> These are not true LEFT or RIGHT joins in the RDBMS sense.  Whether
 or not a secondary record exists for the join key or not, one and only one
 copy of the primary record is returned in the result set.  If a secondary
 record cannot be found, the secondary derived fields will be NULL.  If more
-than one matching secondary field is found only the first will be used. 
+than one matching secondary field is found only the first will be used.
 </ol>
 
 \section ogr_sql_union_all UNION ALL
@@ -486,17 +517,17 @@ not at the level of the result of the union.
 
 The OGR SQL query processor treats some of the attributes of the features as
 built-in special fields can be used in the SQL statements likewise the
-other fields. These fields can be placed in the select list, the WHERE clause 
+other fields. These fields can be placed in the select list, the WHERE clause
 and the ORDER BY clause respectively. The special field will not be included
 in the result by default but it may be explicitly included by adding it to
 the select list.
 When accessing the field values the special fields will take precedence over
-the other fields with the same names in the data source. 
+the other fields with the same names in the data source.
 
 \subsection ogr_sql_fid FID
 
 Normally the feature id is a special property of a feature and not treated
-as an attribute of the feature.  In some cases it is convenient to be able to 
+as an attribute of the feature.  In some cases it is convenient to be able to
 utilize the feature id in queries and result sets as a regular field.  To do
 so use the name <b>FID</b>.  The field wildcard expansions will not include
 the feature id, but it may be explicitly included using a syntax like:
@@ -510,7 +541,7 @@ SELECT FID, * FROM nation
 Some of the data sources (like MapInfo tab) can handle geometries of different
 types within the same layer. The <b>OGR_GEOMETRY</b> special field represents
 the geometry type returned by OGRGeometry::getGeometryName() and can be used to
-distinguish the various types. By using this field one can select particular 
+distinguish the various types. By using this field one can select particular
 types of the geometries like:
 
 \code
@@ -533,22 +564,22 @@ clause we can get similar effect as using OGR_GEOMETRY:
 \code
 SELECT OGR_GEOM_WKT, * FROM nation WHERE OGR_GEOM_WKT
    LIKE 'POINT%' OR OGR_GEOM_WKT LIKE 'POLYGON%'
-\endcode 
+\endcode
 
 \subsection ogr_sql_geom_area OGR_GEOM_AREA
 
 (Since GDAL 1.7.0)
 
-The <b>OGR_GEOM_AREA</b> special field returns the area of the feature's 
-geometry computed by the OGRSurface::get_Area() method. For 
-OGRGeometryCollection and OGRMultiPolygon the value is the sum of the 
+The <b>OGR_GEOM_AREA</b> special field returns the area of the feature's
+geometry computed by the OGRSurface::get_Area() method. For
+OGRGeometryCollection and OGRMultiPolygon the value is the sum of the
 areas of its members. For non-surface geometries the returned area is 0.0.
 
 For example, to select only polygon features larger than a given area:
 
 \code
 SELECT * FROM nation WHERE OGR_GEOM_AREA > 10000000
-\endcode 
+\endcode
 
 \subsection ogr_sql_style OGR_STYLE
 
@@ -559,7 +590,7 @@ For example we can select the annotation features as:
 
 \code
 SELECT * FROM nation WHERE OGR_STYLE LIKE 'LABEL%'
-\endcode 
+\endcode
 
 \section ogr_sql_create_index CREATE INDEX
 
@@ -581,7 +612,7 @@ removed from a layer.
 <li> Very long strings (longer than 256 characters?) cannot currently be
 indexed.
 <li> To recreate an index it is necessary to drop all indexes on a layer and
-then recreate all the indexes. 
+then recreate all the indexes.
 <li> Indexes are not used in any complex queries.   Currently the only
 query the will accelerate is a simple "field = value" query.
 </ol>
@@ -589,7 +620,7 @@ query the will accelerate is a simple "field = value" query.
 \section ogr_sql_drop_index DROP INDEX
 
 The OGR SQL DROP INDEX command can be used to drop all indexes on a particular
-table, or just the index for a particular column. 
+table, or just the index for a particular column.
 
 \code
 DROP INDEX ON nation USING nation_id
@@ -645,27 +676,27 @@ different command languages against a provider, but for now applications
 should always pass an empty (not NULL) string to get the default dialect.<p>
 
 The poSpatialFilter argument is a geometry used to select a bounding rectangle
-for features to be returned in a manner similar to the 
+for features to be returned in a manner similar to the
 OGRLayer::SetSpatialFilter() method.  It may be NULL for no special spatial
 restriction.<p>
 
 The result of an ExecuteSQL() call is usually a temporary OGRLayer representing
 the results set from the statement.  This is the case for a SELECT statement
-for instance.  The returned temporary layer should be released with 
+for instance.  The returned temporary layer should be released with
 GDALDataset::ReleaseResultsSet() method when no longer needed.  Failure
 to release it before the datasource is destroyed may result in a crash.<p>
 
 \section ogr_sql_non_ogr_sql Non-OGR SQL
 
-All OGR drivers for database systems: <a href="/ogr/drv_mysql.html">MySQL</a>, 
-PostgreSQL and PostGIS (<a href="/ogr/drv_pg.html">PG</a>), 
-Oracle (<a href="/ogr/drv_oci.html">OCI</a>), 
-<a href="/ogr/drv_sqlite.html">SQLite</a>, 
+All OGR drivers for database systems: <a href="/ogr/drv_mysql.html">MySQL</a>,
+PostgreSQL and PostGIS (<a href="/ogr/drv_pg.html">PG</a>),
+Oracle (<a href="/ogr/drv_oci.html">OCI</a>),
+<a href="/ogr/drv_sqlite.html">SQLite</a>,
 <a href="/ogr/drv_odbc.html">ODBC</a>,
 ESRI Personal Geodatabase (<a href="/ogr/drv_pgeo.html">PGeo</a>) and
 MS SQL Spatial (<a href="/ogr/drv_mssqlspatial.html">MSSQLSpatial</a>),
-override the GDALDataset::ExecuteSQL() function with dedicated implementation 
-and, by default, pass the SQL statements directly to the underlying RDBMS. 
+override the GDALDataset::ExecuteSQL() function with dedicated implementation
+and, by default, pass the SQL statements directly to the underlying RDBMS.
 In these cases the SQL syntax varies in some particulars from OGR SQL.
 Also, anything possible in SQL can then be accomplished for these particular
 databases.  Only the result of SQL WHERE statements will be returned as
diff --git a/ogr/ogr_sql_sqlite.dox b/ogr/ogr_sql_sqlite.dox
index 4bf6e26..5d9ce82 100644
--- a/ogr/ogr_sql_sqlite.dox
+++ b/ogr/ogr_sql_sqlite.dox
@@ -26,7 +26,7 @@ refer to the following pages:
 
 The SELECT statement is used to fetch layer features (analogous to table
 rows in an RDBMS) with the result of the query represented as a temporary layer
-of features.   The layers of the datasource are analogous to tables in an 
+of features.   The layers of the datasource are analogous to tables in an
 RDBMS and feature attributes are analogous to column values.  The simplest
 form of OGR SQLITE SELECT statement looks like this:
 
@@ -56,6 +56,24 @@ translated, as far as possible, as attribute filters that are applied on the
 underlying OGR layers. Joins can be very expensive operations if the secondary table is not
 indexed on the key field being used.<p>
 
+\subsection ogr_sql_sqlite_delimited_identifiers Delimited identifiers
+
+If names of layers or attributes are reserved keywords in SQL like 'FROM' or they
+begin with a number or underscore they must be handled as "delimited identifiers" and
+enclosed between double quotation marks in queries. Double quotas can be used even when
+they are not strictly needed.
+
+\code
+SELECT "p"."geometry", "p"."FROM", "p"."3D" FROM "poly" p
+\endcode
+
+When SQL statements are used in the command shell and the statement itself is put
+between double quotes, the internal double quotes must be escaped with \
+
+\code
+ogrinfo p.shp -sql "SELECT geometry \"FROM\", \"3D\" FROM p"
+\endcode
+
 \subsection ogr_sql_sqlite_geometry Geometry field
 
 The <b>GEOMETRY</b> special field represents the geometry of the feature
@@ -75,7 +93,7 @@ returns:
 OGRFeature(SELECT):0
   EAS_ID (Real) = 168
   POLYGON ((479819.84375 4765180.5,479690.1875 4765259.5,[...],479819.84375 4765180.5))
-\endcode 
+\endcode
 
 \code
 SELECT * FROM poly
@@ -87,7 +105,7 @@ OGRFeature(SELECT):0
   EAS_ID (Real) = 168
   PRFEDEA (String) = 35043411
   POLYGON ((479819.84375 4765180.5,479690.1875 4765259.5,[...],479819.84375 4765180.5))
-\endcode 
+\endcode
 
 \subsection ogr_sql_sqlite_style OGR_STYLE special field
 
@@ -98,7 +116,7 @@ For example we can select the annotation features as:
 
 \code
 SELECT * FROM nation WHERE OGR_STYLE LIKE 'LABEL%'
-\endcode 
+\endcode
 
 \subsection ogr_sql_sqlite_spatialite Spatialite SQL functions
 
@@ -289,7 +307,7 @@ of the layers to limit the number of actual geometry intersection computations :
 SELECT city_name, region_name FROM cities, regions WHERE
     ST_Area(ST_Intersection(cities.geometry, regions.geometry)) > 0 AND
     regions.rowid IN (
-        SELECT pkid FROM idx_regions_geometry WHERE 
+        SELECT pkid FROM idx_regions_geometry WHERE
             xmax >= MbrMinX(cities.geometry) AND xmin <= MbrMaxX(cities.geometry) AND
             ymax >= MbrMinY(cities.geometry) AND ymin <= MbrMaxY(cities.geometry))
 \endcode
diff --git a/ogr/ogr_srs_api.h b/ogr/ogr_srs_api.h
index ca961ec..24450f8 100644
--- a/ogr/ogr_srs_api.h
+++ b/ogr/ogr_srs_api.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_srs_api.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogr_srs_api.h 35912 2016-10-24 16:41:45Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  C API and constant declarations for OGR Spatial References.
@@ -44,17 +44,15 @@ CPL_C_START
  * See also: ogr_spatialref.h
  */
 
-/* -------------------------------------------------------------------- */
-/*      Axis orientations (corresponds to CS_AxisOrientationEnum).      */
-/* -------------------------------------------------------------------- */
+/** Axis orientations (corresponds to CS_AxisOrientationEnum). */
 typedef enum {
-    OAO_Other=0,
-    OAO_North=1,
-    OAO_South=2,
-    OAO_East=3,
-    OAO_West=4,
-    OAO_Up=5,
-    OAO_Down=6
+    OAO_Other=0, /**< Other */
+    OAO_North=1, /**< North */
+    OAO_South=2, /**< South */
+    OAO_East=3,  /**< East */
+    OAO_West=4,  /**< West */
+    OAO_Up=5,    /**< Up (to space) */
+    OAO_Down=6   /**< Down (to Earth center) */
 } OGRAxisOrientation;
 
 const char CPL_DLL *OSRAxisEnumToName( OGRAxisOrientation eOrientation );
@@ -63,6 +61,8 @@ const char CPL_DLL *OSRAxisEnumToName( OGRAxisOrientation eOrientation );
 /*      Datum types (corresponds to CS_DatumType).                      */
 /* -------------------------------------------------------------------- */
 
+/*! @cond Doxygen_Suppress */
+// Unused in the code base. TODO: remove
 typedef enum {
     ODT_HD_Min=1000,
     ODT_HD_Other=1000,
@@ -81,6 +81,7 @@ typedef enum {
     ODT_LD_Min=10000,
     ODT_LD_Max=32767
 } OGRDatumType;
+/*! @endcond */
 
 #endif // ndef SWIG
 
@@ -88,214 +89,379 @@ typedef enum {
 /*      Some standard WKT geographic coordinate systems.                */
 /* ==================================================================== */
 
+/** WGS 84 geodetic (long/lat) WKT / EPSG:4326 with long,lat ordering */
 #define SRS_WKT_WGS84 "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"
 
 /* ==================================================================== */
 /*      Some "standard" strings.                                        */
 /* ==================================================================== */
 
+/** Albers_Conic_Equal_Area projection */
 #define SRS_PT_ALBERS_CONIC_EQUAL_AREA                                  \
                                 "Albers_Conic_Equal_Area"
+/** Azimuthal_Equidistant projection */
 #define SRS_PT_AZIMUTHAL_EQUIDISTANT "Azimuthal_Equidistant"
+/** Cassini_Soldner projection */
 #define SRS_PT_CASSINI_SOLDNER  "Cassini_Soldner"
+/** Cylindrical_Equal_Area projection */
 #define SRS_PT_CYLINDRICAL_EQUAL_AREA "Cylindrical_Equal_Area"
+/** Cylindrical_Equal_Area projection */
 #define SRS_PT_BONNE            "Bonne"
+/** Eckert_I projection */
 #define SRS_PT_ECKERT_I         "Eckert_I"
+/** Eckert_II projection */
 #define SRS_PT_ECKERT_II        "Eckert_II"
+/** Eckert_III projection */
 #define SRS_PT_ECKERT_III       "Eckert_III"
+/** Eckert_IV projection */
 #define SRS_PT_ECKERT_IV        "Eckert_IV"
+/** Eckert_V projection */
 #define SRS_PT_ECKERT_V         "Eckert_V"
+/** Eckert_VI projection */
 #define SRS_PT_ECKERT_VI        "Eckert_VI"
+/** Equidistant_Conic projection */
 #define SRS_PT_EQUIDISTANT_CONIC                                        \
                                 "Equidistant_Conic"
+/** Equirectangular projection */
 #define SRS_PT_EQUIRECTANGULAR  "Equirectangular"
+/** Gall_Stereographic projection */
 #define SRS_PT_GALL_STEREOGRAPHIC                                       \
                                 "Gall_Stereographic"
+/** Gauss_Schreiber_Transverse_Mercator projection */
 #define SRS_PT_GAUSSSCHREIBERTMERCATOR                                      \
                                 "Gauss_Schreiber_Transverse_Mercator"
+/** Geostationary_Satellite projection */
 #define SRS_PT_GEOSTATIONARY_SATELLITE                                  \
                                 "Geostationary_Satellite"
+/** Goode_Homolosine projection */
 #define SRS_PT_GOODE_HOMOLOSINE "Goode_Homolosine"
+/** Interrupted_Goode_Homolosine projection */
 #define SRS_PT_IGH              "Interrupted_Goode_Homolosine"
+/** Gnomonic projection */
 #define SRS_PT_GNOMONIC         "Gnomonic"
+/** Hotine_Oblique_Mercator_Azimuth_Center projection */
 #define SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER                   \
                                 "Hotine_Oblique_Mercator_Azimuth_Center"
+/** Hotine_Oblique_Mercator projection */
 #define SRS_PT_HOTINE_OBLIQUE_MERCATOR                                  \
                                 "Hotine_Oblique_Mercator"
+/** Hotine_Oblique_Mercator_Two_Point_Natural_Origin projection */
 #define SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN         \
                             "Hotine_Oblique_Mercator_Two_Point_Natural_Origin"
+/** Laborde_Oblique_Mercator projection */
 #define SRS_PT_LABORDE_OBLIQUE_MERCATOR                                 \
                                 "Laborde_Oblique_Mercator"
+/** Lambert_Conformal_Conic_1SP projection */
 #define SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP                              \
                                 "Lambert_Conformal_Conic_1SP"
+/** Lambert_Conformal_Conic_2SP projection */
 #define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP                              \
                                 "Lambert_Conformal_Conic_2SP"
+/** Lambert_Conformal_Conic_2SP_Belgium projection */
 #define SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM                      \
                                 "Lambert_Conformal_Conic_2SP_Belgium"
+/** Lambert_Azimuthal_Equal_Area projection */
 #define SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA                     \
                                 "Lambert_Azimuthal_Equal_Area"
+/** Mercator_1SP projection */
 #define SRS_PT_MERCATOR_1SP     "Mercator_1SP"
+/** Mercator_2SP projection */
 #define SRS_PT_MERCATOR_2SP     "Mercator_2SP"
-// Mercator_Auxiliary_Sphere is used used by ESRI to mean EPSG:3875
+/** Mercator_Auxiliary_Sphere is used used by ESRI to mean EPSG:3875 */
 #define SRS_PT_MERCATOR_AUXILIARY_SPHERE                                 \
                                 "Mercator_Auxiliary_Sphere"
+/** Miller_Cylindrical projection */
 #define SRS_PT_MILLER_CYLINDRICAL "Miller_Cylindrical"
+/** Mollweide projection */
 #define SRS_PT_MOLLWEIDE        "Mollweide"
+/** New_Zealand_Map_Grid projection */
 #define SRS_PT_NEW_ZEALAND_MAP_GRID                                     \
                                 "New_Zealand_Map_Grid"
+/** Oblique_Stereographic projection */
 #define SRS_PT_OBLIQUE_STEREOGRAPHIC                                    \
                                 "Oblique_Stereographic"
+/** Orthographic projection */
 #define SRS_PT_ORTHOGRAPHIC     "Orthographic"
+/** Polar_Stereographic projection */
 #define SRS_PT_POLAR_STEREOGRAPHIC                                      \
                                 "Polar_Stereographic"
+/** Polyconic projection */
 #define SRS_PT_POLYCONIC        "Polyconic"
+/** Robinson projection */
 #define SRS_PT_ROBINSON         "Robinson"
+/** Sinusoidal projection */
 #define SRS_PT_SINUSOIDAL       "Sinusoidal"
+/** Stereographic projection */
 #define SRS_PT_STEREOGRAPHIC    "Stereographic"
+/** Swiss_Oblique_Cylindrical projection */
 #define SRS_PT_SWISS_OBLIQUE_CYLINDRICAL                                \
                                 "Swiss_Oblique_Cylindrical"
+/** Transverse_Mercator projection */
 #define SRS_PT_TRANSVERSE_MERCATOR                                      \
                                 "Transverse_Mercator"
+/** Transverse_Mercator_South_Orientated projection */
 #define SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED                       \
                                 "Transverse_Mercator_South_Orientated"
 
 /* special mapinfo variants on Transverse Mercator */
+/** Transverse_Mercator_MapInfo_21 projection */
 #define SRS_PT_TRANSVERSE_MERCATOR_MI_21 \
                                 "Transverse_Mercator_MapInfo_21"
+/** Transverse_Mercator_MapInfo_22 projection */
 #define SRS_PT_TRANSVERSE_MERCATOR_MI_22 \
                                 "Transverse_Mercator_MapInfo_22"
+/** Transverse_Mercator_MapInfo_23 projection */
 #define SRS_PT_TRANSVERSE_MERCATOR_MI_23 \
                                 "Transverse_Mercator_MapInfo_23"
+/** Transverse_Mercator_MapInfo_24 projection */
 #define SRS_PT_TRANSVERSE_MERCATOR_MI_24 \
                                 "Transverse_Mercator_MapInfo_24"
+/** Transverse_Mercator_MapInfo_25 projection */
 #define SRS_PT_TRANSVERSE_MERCATOR_MI_25 \
                                 "Transverse_Mercator_MapInfo_25"
 
+/** Tunisia_Mining_Grid projection */
 #define SRS_PT_TUNISIA_MINING_GRID                                      \
                                 "Tunisia_Mining_Grid"
+/** Two_Point_Equidistant projection */
 #define SRS_PT_TWO_POINT_EQUIDISTANT                                    \
                                 "Two_Point_Equidistant"
+/** VanDerGrinten projection */
 #define SRS_PT_VANDERGRINTEN    "VanDerGrinten"
+/** Krovak projection */
 #define SRS_PT_KROVAK           "Krovak"
+/** International_Map_of_the_World_Polyconic projection */
 #define SRS_PT_IMW_POLYCONIC    "International_Map_of_the_World_Polyconic"
+/** Wagner_I projection */
 #define SRS_PT_WAGNER_I         "Wagner_I"
+/** Wagner_II projection */
 #define SRS_PT_WAGNER_II        "Wagner_II"
+/** Wagner_III projection */
 #define SRS_PT_WAGNER_III       "Wagner_III"
+/** Wagner_IV projection */
 #define SRS_PT_WAGNER_IV        "Wagner_IV"
+/** Wagner_V projection */
 #define SRS_PT_WAGNER_V         "Wagner_V"
+/** Wagner_VI projection */
 #define SRS_PT_WAGNER_VI        "Wagner_VI"
+/** Wagner_VII projection */
 #define SRS_PT_WAGNER_VII       "Wagner_VII"
+/** Quadrilateralized_Spherical_Cube projection */
 #define SRS_PT_QSC              "Quadrilateralized_Spherical_Cube"
+/** Aitoff projection */
 #define SRS_PT_AITOFF           "Aitoff"
+/** Winkel_I projection */
 #define SRS_PT_WINKEL_I         "Winkel_I"
+/** Winkel_II projection */
 #define SRS_PT_WINKEL_II        "Winkel_II"
+/** Winkel_Tripel projection */
 #define SRS_PT_WINKEL_TRIPEL    "Winkel_Tripel"
+/** Craster_Parabolic projection */
 #define SRS_PT_CRASTER_PARABOLIC    "Craster_Parabolic"
+/** Loximuthal projection */
 #define SRS_PT_LOXIMUTHAL        "Loximuthal"
+/** Quartic_Authalic projection */
 #define SRS_PT_QUARTIC_AUTHALIC  "Quartic_Authalic"
+/** Spherical_Cross_Track_Height projection */
 #define SRS_PT_SCH              "Spherical_Cross_Track_Height"
 
+/** central_meridian projection parameter */
 #define SRS_PP_CENTRAL_MERIDIAN         "central_meridian"
+/** scale_factor projection parameter */
 #define SRS_PP_SCALE_FACTOR             "scale_factor"
+/** standard_parallel_1 projection parameter */
 #define SRS_PP_STANDARD_PARALLEL_1      "standard_parallel_1"
+/** standard_parallel_2 projection parameter */
 #define SRS_PP_STANDARD_PARALLEL_2      "standard_parallel_2"
+/** pseudo_standard_parallel_1 projection parameter */
 #define SRS_PP_PSEUDO_STD_PARALLEL_1    "pseudo_standard_parallel_1"
+/** longitude_of_center projection parameter */
 #define SRS_PP_LONGITUDE_OF_CENTER      "longitude_of_center"
+/** latitude_of_center projection parameter */
 #define SRS_PP_LATITUDE_OF_CENTER       "latitude_of_center"
+/** longitude_of_origin projection parameter */
 #define SRS_PP_LONGITUDE_OF_ORIGIN      "longitude_of_origin"
+/** latitude_of_origin projection parameter */
 #define SRS_PP_LATITUDE_OF_ORIGIN       "latitude_of_origin"
+/** false_easting projection parameter */
 #define SRS_PP_FALSE_EASTING            "false_easting"
+/** false_northing projection parameter */
 #define SRS_PP_FALSE_NORTHING           "false_northing"
+/** azimuth projection parameter */
 #define SRS_PP_AZIMUTH                  "azimuth"
+/** longitude_of_point_1 projection parameter */
 #define SRS_PP_LONGITUDE_OF_POINT_1     "longitude_of_point_1"
+/** latitude_of_point_1 projection parameter */
 #define SRS_PP_LATITUDE_OF_POINT_1      "latitude_of_point_1"
+/** longitude_of_point_2 projection parameter */
 #define SRS_PP_LONGITUDE_OF_POINT_2     "longitude_of_point_2"
+/** latitude_of_point_2 projection parameter */
 #define SRS_PP_LATITUDE_OF_POINT_2      "latitude_of_point_2"
+/** longitude_of_point_3 projection parameter */
 #define SRS_PP_LONGITUDE_OF_POINT_3     "longitude_of_point_3"
+/** latitude_of_point_3 projection parameter */
 #define SRS_PP_LATITUDE_OF_POINT_3      "latitude_of_point_3"
+/** rectified_grid_angle projection parameter */
 #define SRS_PP_RECTIFIED_GRID_ANGLE     "rectified_grid_angle"
+/** landsat_number projection parameter */
 #define SRS_PP_LANDSAT_NUMBER           "landsat_number"
+/** path_number projection parameter */
 #define SRS_PP_PATH_NUMBER              "path_number"
+/** perspective_point_height projection parameter */
 #define SRS_PP_PERSPECTIVE_POINT_HEIGHT "perspective_point_height"
+/** satellite_height projection parameter */
 #define SRS_PP_SATELLITE_HEIGHT         "satellite_height"
+/** fipszone projection parameter */
 #define SRS_PP_FIPSZONE                 "fipszone"
+/** zone projection parameter */
 #define SRS_PP_ZONE                     "zone"
+/** Latitude_Of_1st_Point projection parameter */
 #define SRS_PP_LATITUDE_OF_1ST_POINT    "Latitude_Of_1st_Point"
+/** Longitude_Of_1st_Point projection parameter */
 #define SRS_PP_LONGITUDE_OF_1ST_POINT   "Longitude_Of_1st_Point"
+/** Latitude_Of_2nd_Point projection parameter */
 #define SRS_PP_LATITUDE_OF_2ND_POINT    "Latitude_Of_2nd_Point"
+/** Longitude_Of_2nd_Point projection parameter */
 #define SRS_PP_LONGITUDE_OF_2ND_POINT   "Longitude_Of_2nd_Point"
+/** peg_point_latitude projection parameter */
 #define SRS_PP_PEG_POINT_LATITUDE       "peg_point_latitude"
+/** peg_point_longitude projection parameter */
 #define SRS_PP_PEG_POINT_LONGITUDE      "peg_point_longitude"
+/** peg_point_heading projection parameter */
 #define SRS_PP_PEG_POINT_HEADING        "peg_point_heading"
+/** peg_point_height projection parameter */
 #define SRS_PP_PEG_POINT_HEIGHT         "peg_point_height"
 
+/** Linear unit Meter */
 #define SRS_UL_METER            "Meter"
+/** Linear unit Foot (International) */
 #define SRS_UL_FOOT             "Foot (International)" /* or just "FOOT"? */
+/** Linear unit Foot (International) conversion factor to meter*/
 #define SRS_UL_FOOT_CONV                    "0.3048"
+/** Linear unit Foot */
 #define SRS_UL_US_FOOT          "Foot_US" /* or "US survey foot" from EPSG */
+/** Linear unit Foot conversion factor to meter */
 #define SRS_UL_US_FOOT_CONV                 "0.3048006096012192"
+/** Linear unit Nautical Mile */
 #define SRS_UL_NAUTICAL_MILE    "Nautical Mile"
+/** Linear unit Nautical Mile conversion factor to meter */
 #define SRS_UL_NAUTICAL_MILE_CONV           "1852.0"
+/** Linear unit Link */
 #define SRS_UL_LINK             "Link"          /* Based on US Foot */
+/** Linear unit Link conversion factor to meter */
 #define SRS_UL_LINK_CONV                    "0.20116684023368047"
+/** Linear unit Chain */
 #define SRS_UL_CHAIN            "Chain"         /* based on US Foot */
+/** Linear unit Chain conversion factor to meter */
 #define SRS_UL_CHAIN_CONV                   "20.116684023368047"
+/** Linear unit Rod */
 #define SRS_UL_ROD              "Rod"           /* based on US Foot */
+/** Linear unit Rod conversion factor to meter */
 #define SRS_UL_ROD_CONV                     "5.02921005842012"
+/** Linear unit Link_Clarke */
 #define SRS_UL_LINK_Clarke      "Link_Clarke"
+/** Linear unit Link_Clarke conversion factor to meter */
 #define SRS_UL_LINK_Clarke_CONV              "0.2011661949"
 
+/** Linear unit Kilometer */
 #define SRS_UL_KILOMETER        "Kilometer"
+/** Linear unit Kilometer conversion factor to meter */
 #define SRS_UL_KILOMETER_CONV                "1000."
+/** Linear unit Decimeter */
 #define SRS_UL_DECIMETER        "Decimeter"
+/** Linear unit Decimeter conversion factor to meter */
 #define SRS_UL_DECIMETER_CONV                "0.1"
+/** Linear unit Decimeter */
 #define SRS_UL_CENTIMETER       "Centimeter"
+/** Linear unit Decimeter conversion factor to meter */
 #define SRS_UL_CENTIMETER_CONV               "0.01"
+/** Linear unit Millimeter */
 #define SRS_UL_MILLIMETER       "Millimeter"
+/** Linear unit Millimeter conversion factor to meter */
 #define SRS_UL_MILLIMETER_CONV               "0.001"
+/** Linear unit Nautical_Mile_International */
 #define SRS_UL_INTL_NAUT_MILE   "Nautical_Mile_International"
+/** Linear unit Nautical_Mile_International conversion factor to meter */
 #define SRS_UL_INTL_NAUT_MILE_CONV           "1852.0"
+/** Linear unit Inch_International */
 #define SRS_UL_INTL_INCH        "Inch_International"
+/** Linear unit Inch_International conversion factor to meter */
 #define SRS_UL_INTL_INCH_CONV                "0.0254"
+/** Linear unit Foot_International */
 #define SRS_UL_INTL_FOOT        "Foot_International"
+/** Linear unit Foot_International conversion factor to meter */
 #define SRS_UL_INTL_FOOT_CONV                    "0.3048"
+/** Linear unit Yard_International */
 #define SRS_UL_INTL_YARD        "Yard_International"
+/** Linear unit Yard_International conversion factor to meter */
 #define SRS_UL_INTL_YARD_CONV                "0.9144"
+/** Linear unit Statute_Mile_International */
 #define SRS_UL_INTL_STAT_MILE   "Statute_Mile_International"
+/** Linear unit Statute_Mile_Internationalconversion factor to meter */
 #define SRS_UL_INTL_STAT_MILE_CONV           "1609.344"
+/** Linear unit Fathom_International */
 #define SRS_UL_INTL_FATHOM      "Fathom_International"
+/** Linear unit Fathom_International conversion factor to meter */
 #define SRS_UL_INTL_FATHOM_CONV              "1.8288"
+/** Linear unit Chain_International */
 #define SRS_UL_INTL_CHAIN       "Chain_International"
+/** Linear unit Chain_International conversion factor to meter */
 #define SRS_UL_INTL_CHAIN_CONV               "20.1168"
+/** Linear unit Link_International */
 #define SRS_UL_INTL_LINK        "Link_International"
+/** Linear unit Link_International conversion factor to meter */
 #define SRS_UL_INTL_LINK_CONV                "0.201168"
+/** Linear unit Inch_US_Surveyor */
 #define SRS_UL_US_INCH          "Inch_US_Surveyor"
+/** Linear unit Inch_US_Surveyor conversion factor to meter */
 #define SRS_UL_US_INCH_CONV                  "0.025400050800101603"
+/** Linear unit Yard_US_Surveyor */
 #define SRS_UL_US_YARD          "Yard_US_Surveyor"
+/** Linear unit Yard_US_Surveyor conversion factor to meter */
 #define SRS_UL_US_YARD_CONV                  "0.914401828803658"
+/** Linear unit Chain_US_Surveyor */
 #define SRS_UL_US_CHAIN         "Chain_US_Surveyor"
+/** Linear unit Chain_US_Surveyor conversion factor to meter */
 #define SRS_UL_US_CHAIN_CONV                 "20.11684023368047"
+/** Linear unit Statute_Mile_US_Surveyor */
 #define SRS_UL_US_STAT_MILE     "Statute_Mile_US_Surveyor"
+/** Linear unit Statute_Mile_US_Surveyor conversion factor to meter */
 #define SRS_UL_US_STAT_MILE_CONV             "1609.347218694437"
+/** Linear unit Yard_Indian */
 #define SRS_UL_INDIAN_YARD      "Yard_Indian"
+/** Linear unit Yard_Indian conversion factor to meter */
 #define SRS_UL_INDIAN_YARD_CONV              "0.91439523"
+/** Linear unit Foot_Indian */
 #define SRS_UL_INDIAN_FOOT      "Foot_Indian"
+/** Linear unit Foot_Indian conversion factor to meter */
 #define SRS_UL_INDIAN_FOOT_CONV              "0.30479841"
+/** Linear unit Chain_Indian */
 #define SRS_UL_INDIAN_CHAIN     "Chain_Indian"
+/** Linear unit Chain_Indian conversion factor to meter */
 #define SRS_UL_INDIAN_CHAIN_CONV             "20.11669506"
 
+/** Angular unit degree */
 #define SRS_UA_DEGREE           "degree"
+/** Angular unit degree conversion factor to radians */
 #define SRS_UA_DEGREE_CONV                  "0.0174532925199433"
+/** Angular unit radian */
 #define SRS_UA_RADIAN           "radian"
 
+/** Prime meridian Greenwich */
 #define SRS_PM_GREENWICH        "Greenwich"
 
+/** North_American_Datum_1927 datum name */
 #define SRS_DN_NAD27            "North_American_Datum_1927"
+/** North_American_Datum_1983 datum name */
 #define SRS_DN_NAD83            "North_American_Datum_1983"
+/** WGS_1972 datum name */
 #define SRS_DN_WGS72            "WGS_1972"
+/** WGS_1984 datum name */
 #define SRS_DN_WGS84            "WGS_1984"
 
+/** Semi-major axis of the WGS84 ellipsoid */
 #define SRS_WGS84_SEMIMAJOR     6378137.0
+/** Inverse flattening of the WGS84 ellipsoid */
 #define SRS_WGS84_INVFLATTENING 298.257223563
 
 #ifndef SWIG
@@ -303,19 +469,22 @@ typedef enum {
 /*      C Wrappers for C++ objects and methods.                         */
 /* -------------------------------------------------------------------- */
 #ifndef DEFINED_OGRSpatialReferenceH
+/*! @cond Doxygen_Suppress */
 #define DEFINED_OGRSpatialReferenceH
+/*! @endcond */
 
 #ifdef DEBUG
 typedef struct OGRSpatialReferenceHS *OGRSpatialReferenceH;
 typedef struct OGRCoordinateTransformationHS *OGRCoordinateTransformationH;
 #else
+/** Opaque type for a Spatial Reference object */
 typedef void *OGRSpatialReferenceH;
+/** Opaque type for a coordinate transformation object */
 typedef void *OGRCoordinateTransformationH;
 #endif
 
 #endif
 
-
 OGRSpatialReferenceH CPL_DLL CPL_STDCALL
       OSRNewSpatialReference( const char * /* = NULL */);
 OGRSpatialReferenceH CPL_DLL CPL_STDCALL OSRCloneGeogCS( OGRSpatialReferenceH );
@@ -626,6 +795,8 @@ OGRErr CPL_DLL OSRSetMercator( OGRSpatialReferenceH hSRS,
                                double dfCenterLat, double dfCenterLong,
                                double dfScale,
                                double dfFalseEasting, double dfFalseNorthing );
+
+/** Mercator 2SP */
 OGRErr CPL_DLL OSRSetMercator2SP( OGRSpatialReferenceH hSRS,
                           double dfStdP1,
                           double dfCenterLat, double dfCenterLong,
@@ -717,6 +888,7 @@ OGRErr CPL_DLL OSRSetTMSO( OGRSpatialReferenceH hSRS,
                            double dfScale,
                            double dfFalseEasting, double dfFalseNorthing );
 
+/** TPED (Two Point Equi Distant) */
 OGRErr CPL_DLL OSRSetTPED( OGRSpatialReferenceH hSRS,
                    double dfLat1, double dfLong1,
                    double dfLat2, double dfLong2,
@@ -742,7 +914,6 @@ OGRErr CPL_DLL OSRSetSCH( OGRSpatialReferenceH hSRS,
                               double dfPegLat, double dfPegLong,
                               double dfPegHeading, double dfPegHgt);
 
-
 double CPL_DLL OSRCalcInvFlattening( double dfSemiMajor, double dfSemiMinor );
 double CPL_DLL OSRCalcSemiMinorFromInvFlattening( double dfSemiMajor, double dfInvFlattening );
 
@@ -766,10 +937,12 @@ OCTTransformEx( OGRCoordinateTransformationH hCT,
                 int nCount, double *x, double *y, double *z,
                 int *pabSuccess );
 
+/*! @cond Doxygen_Suppress */
 /* this is really private to OGR. */
 char *OCTProj4Normalize( const char *pszProj4Src );
 
 void OCTCleanupProjMutex( void );
+/*! @endcond */
 
 /* -------------------------------------------------------------------- */
 /*      Projection transform dictionary query.                          */
diff --git a/ogr/ogr_srs_dict.cpp b/ogr/ogr_srs_dict.cpp
index f0969c1..e5f9f83 100644
--- a/ogr/ogr_srs_dict.cpp
+++ b/ogr/ogr_srs_dict.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_dict.cpp 33632 2016-03-04 06:51:02Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implement importFromDict() method to read a WKT SRS from a
@@ -28,11 +27,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_spatialref.h"
+
+#include <cstring>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_vsi.h"
-#include "ogr_spatialref.h"
+#include "ogr_core.h"
+#include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogr_srs_dict.cpp 33632 2016-03-04 06:51:02Z goatbar $");
+CPL_CVSID("$Id: ogr_srs_dict.cpp 36289 2016-11-19 06:41:23Z goatbar $");
 
 /************************************************************************/
 /*                           importFromDict()                           */
@@ -95,10 +101,10 @@ OGRErr OGRSpatialReference::importFromDict( const char *pszDictFile,
             continue;
         }
 
-        if( strstr(pszLine,",") == NULL )
+        if( strstr(pszLine, ",") == NULL )
             continue;
 
-        if( EQUALN(pszLine,pszCode,strlen(pszCode))
+        if( EQUALN(pszLine, pszCode, strlen(pszCode))
             && pszLine[strlen(pszCode)] == ',' )
         {
             char *pszWKT = const_cast<char *>(pszLine) + strlen(pszCode)+1;
@@ -120,6 +126,31 @@ OGRErr OGRSpatialReference::importFromDict( const char *pszDictFile,
 /*                         OSRImportFromDict()                          */
 /************************************************************************/
 
+/**
+ * Read SRS from WKT dictionary.
+ *
+ * This method will attempt to find the indicated coordinate system identity
+ * in the indicated dictionary file.  If found, the WKT representation is
+ * imported and used to initialize this OGRSpatialReference.
+ *
+ * More complete information on the format of the dictionary files can
+ * be found in the epsg.wkt file in the GDAL data tree.  The dictionary
+ * files are searched for in the "GDAL" domain using CPLFindFile().  Normally
+ * this results in searching /usr/local/share/gdal or somewhere similar.
+ *
+ * This method is the same as the C++ method
+ * OGRSpatialReference::importFromDict().
+ *
+ * @param hSRS spatial reference system handle.
+ *
+ * @param pszDictFile the name of the dictionary file to load.
+ *
+ * @param pszCode the code to lookup in the dictionary.
+ *
+ * @return OGRERR_NONE on success, or OGRERR_SRS_UNSUPPORTED if the code isn't
+ * found, and OGRERR_SRS_FAILURE if something more dramatic goes wrong.
+ */
+
 OGRErr OSRImportFromDict( OGRSpatialReferenceH hSRS,
                           const char *pszDictFile,
                           const char *pszCode )
diff --git a/ogr/ogr_srs_erm.cpp b/ogr/ogr_srs_erm.cpp
index 435a67f..b41a6bc 100644
--- a/ogr/ogr_srs_erm.cpp
+++ b/ogr/ogr_srs_erm.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_erm.cpp 33553 2016-02-25 14:05:00Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implement ERMapper projection conversions.
@@ -28,10 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
+#include "cpl_port.h"
+#include "ogr_srs_api.h"
+
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "ogr_core.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogr_srs_erm.cpp 33553 2016-02-25 14:05:00Z goatbar $");
+CPL_CVSID("$Id: ogr_srs_erm.cpp 36677 2016-12-04 13:42:55Z rouault $");
 
 /************************************************************************/
 /*                         OSRImportFromERM()                           */
@@ -49,9 +58,8 @@ OGRErr OSRImportFromERM( OGRSpatialReferenceH hSRS, const char *pszProj,
 {
     VALIDATE_POINTER1( hSRS, "OSRImportFromERM", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->importFromERM( pszProj,
-                                                          pszDatum,
-                                                          pszUnits );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        importFromERM(pszProj, pszDatum, pszUnits);
 }
 
 /************************************************************************/
@@ -82,7 +90,7 @@ OGRErr OGRSpatialReference::importFromERM( const char *pszProj,
 /* -------------------------------------------------------------------- */
 /*      do we have projection and datum?                                */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszProj,"RAW") )
+    if( EQUAL(pszProj, "RAW") )
         return OGRERR_NONE;
 
 /* -------------------------------------------------------------------- */
@@ -92,25 +100,19 @@ OGRErr OGRSpatialReference::importFromERM( const char *pszProj,
     if( STARTS_WITH_CI(pszProj, "EPSG:") )
         return importFromEPSG( atoi(pszProj+5) );
 
-
     if( STARTS_WITH_CI(pszDatum, "EPSG:") )
         return importFromEPSG( atoi(pszDatum+5) );
 
 /* -------------------------------------------------------------------- */
 /*      Set projection if we have it.                                   */
 /* -------------------------------------------------------------------- */
-    OGRErr eErr;
-
-    if( EQUAL(pszProj,"GEODETIC") )
+    if( !EQUAL(pszProj, "GEODETIC") )
     {
-    }
-    else
-    {
-        eErr = importFromDict( "ecw_cs.wkt", pszProj );
+        const OGRErr eErr = importFromDict( "ecw_cs.wkt", pszProj );
         if( eErr != OGRERR_NONE )
             return eErr;
 
-        if( EQUAL(pszUnits,"FEET") )
+        if( EQUAL(pszUnits, "FEET") )
             SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV));
         else
             SetLinearUnits( SRS_UL_METER, 1.0 );
@@ -121,7 +123,7 @@ OGRErr OGRSpatialReference::importFromERM( const char *pszProj,
 /* -------------------------------------------------------------------- */
     OGRSpatialReference oGeogCS;
 
-    eErr = oGeogCS.importFromDict( "ecw_cs.wkt", pszDatum );
+    const OGRErr eErr = oGeogCS.importFromDict( "ecw_cs.wkt", pszDatum );
     if( eErr != OGRERR_NONE )
     {
         Clear();
@@ -148,8 +150,8 @@ OGRErr OSRExportToERM( OGRSpatialReferenceH hSRS,
 {
     VALIDATE_POINTER1( hSRS, "OSRExportToERM", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->exportToERM( pszProj, pszDatum,
-                                                        pszUnits );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        exportToERM(pszProj, pszDatum, pszUnits);
 }
 
 /************************************************************************/
@@ -171,6 +173,7 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
                                          char *pszUnits )
 
 {
+    const int BUFFER_SIZE = 32;
     strcpy( pszProj, "RAW" );
     strcpy( pszDatum, "RAW" );
     strcpy( pszUnits, "METERS" );
@@ -187,7 +190,7 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
     {
         const char *pszAuthName = GetAuthorityName( "PROJCS" );
 
-        if( pszAuthName != NULL && EQUAL(pszAuthName,"epsg") )
+        if( pszAuthName != NULL && EQUAL(pszAuthName, "epsg") )
         {
             nEPSGCode = atoi(GetAuthorityCode( "PROJCS" ));
         }
@@ -196,7 +199,7 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
     {
         const char *pszAuthName = GetAuthorityName( "GEOGCS" );
 
-        if( pszAuthName != NULL && EQUAL(pszAuthName,"epsg") )
+        if( pszAuthName != NULL && EQUAL(pszAuthName, "epsg") )
         {
             nEPSGCode = atoi(GetAuthorityCode( "GEOGCS" ));
         }
@@ -211,14 +214,14 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
     if( pszWKTDatum != NULL
         && oSRSWork.importFromDict( "ecw_cs.wkt", pszWKTDatum ) == OGRERR_NONE)
     {
-        strncpy( pszDatum, pszWKTDatum, 32 );
-        pszDatum[31] = '\0';
+        strncpy( pszDatum, pszWKTDatum, BUFFER_SIZE );
+        pszDatum[BUFFER_SIZE-1] = '\0';
     }
 
 /* -------------------------------------------------------------------- */
 /*      Is this a "well known" geographic coordinate system?            */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszDatum,"RAW") )
+    if( EQUAL(pszDatum, "RAW") )
     {
         int nEPSGGCSCode = GetEPSGGeogCS();
 
@@ -271,7 +274,7 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
 
     if( IsGeographic() )
     {
-        if( EQUAL(pszDatum,"RAW") )
+        if( EQUAL(pszDatum, "RAW") )
             return OGRERR_UNSUPPORTED_SRS;
         else
         {
@@ -283,21 +286,22 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
 /* -------------------------------------------------------------------- */
 /*      Is this a UTM projection?                                       */
 /* -------------------------------------------------------------------- */
-    int bNorth, nZone;
+    int bNorth = FALSE;
+    int nZone = 0;
 
     nZone = GetUTMZone( &bNorth );
     if( nZone > 0 )
     {
-        if( EQUAL(pszDatum,"GDA94") && !bNorth && nZone >= 48 && nZone <= 58)
+        if( EQUAL(pszDatum, "GDA94") && !bNorth && nZone >= 48 && nZone <= 58)
         {
-            snprintf( pszProj, 32, "MGA%02d", nZone );
+            snprintf( pszProj, BUFFER_SIZE, "MGA%02d", nZone );
         }
         else
         {
             if( bNorth )
-                snprintf( pszProj, 32, "NUTM%02d", nZone );
+                snprintf( pszProj, BUFFER_SIZE, "NUTM%02d", nZone );
             else
-                snprintf( pszProj, 32, "SUTM%02d", nZone );
+                snprintf( pszProj, BUFFER_SIZE, "SUTM%02d", nZone );
         }
     }
 
@@ -312,8 +316,8 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
             && oSRSWork.importFromDict( "ecw_cs.wkt", pszPROJCS ) == OGRERR_NONE
             && oSRSWork.IsProjected() )
         {
-            strncpy( pszProj, pszPROJCS, 32 );
-            pszProj[31] = '\0';
+            strncpy( pszProj, pszPROJCS, BUFFER_SIZE );
+            pszProj[BUFFER_SIZE-1] = '\0';
         }
     }
 
@@ -321,24 +325,24 @@ OGRErr OGRSpatialReference::exportToERM( char *pszProj, char *pszDatum,
 /*      If we have not translated it yet, but we have an EPSG code      */
 /*      then use EPSG:n notation.                                       */
 /* -------------------------------------------------------------------- */
-    if( (EQUAL(pszDatum,"RAW") || EQUAL(pszProj,"RAW")) && nEPSGCode != 0 )
+    if( (EQUAL(pszDatum, "RAW") || EQUAL(pszProj, "RAW")) && nEPSGCode != 0 )
     {
-        snprintf( pszProj, 32, "EPSG:%d", nEPSGCode );
-        snprintf( pszDatum, 32, "EPSG:%d", nEPSGCode );
+        snprintf( pszProj, BUFFER_SIZE, "EPSG:%d", nEPSGCode );
+        snprintf( pszDatum, BUFFER_SIZE, "EPSG:%d", nEPSGCode );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Handle the units.                                               */
 /* -------------------------------------------------------------------- */
-    double dfUnits = GetLinearUnits();
+    const double dfUnits = GetLinearUnits();
 
     if( fabs(dfUnits-0.3048) < 0.0001 )
         strcpy( pszUnits, "FEET" );
     else
         strcpy( pszUnits, "METERS" );
 
-    if( EQUAL(pszProj,"RAW") )
+    if( EQUAL(pszProj, "RAW") )
         return OGRERR_UNSUPPORTED_SRS;
-    else
-        return OGRERR_NONE;
+
+    return OGRERR_NONE;
 }
diff --git a/ogr/ogr_srs_esri.cpp b/ogr/ogr_srs_esri.cpp
index f988cbc..bd03faa 100644
--- a/ogr/ogr_srs_esri.cpp
+++ b/ogr/ogr_srs_esri.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_esri.cpp 34495 2016-07-01 10:16:03Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from ESRI .prj definitions.
@@ -29,44 +28,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_esri_names.h"
+
+#include <cmath>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
 #include "cpl_vsi.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
-#include "ogr_spatialref.h"
-
-#include "ogr_srs_esri_names.h"
+#include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogr_srs_esri.cpp 34495 2016-07-01 10:16:03Z rouault $");
-
-void  SetNewName( OGRSpatialReference* pOgr, const char* keyName, const char* newName );
-int   RemapImgWGSProjcsName(OGRSpatialReference* pOgr, const char* pszProjCSName,
-                            const char* pszProgCSName);
-int   RemapImgUTMNames(OGRSpatialReference* pOgr, const char* pszProjCSName,
-                       const char* pszProgCSName, char **mappingTable);
-int   RemapNameBasedOnKeyName(OGRSpatialReference* pOgr, const char* pszName,
-                             const char* pszkeyName, char **mappingTable);
-int   RemapNamesBasedOnTwo(OGRSpatialReference* pOgr, const char* name1, const char* name2,
-                             char **mappingTable, int nTableStepSize,
-                             char** pszkeyNames, long nKeys);
-int   RemapPValuesBasedOnProjCSAndPName(OGRSpatialReference* pOgr,
-                             const char* pszProgCSName, char **mappingTable);
-int   RemapPNamesBasedOnProjCSAndPName(OGRSpatialReference* pOgr,
-                             const char* pszProgCSName, char **mappingTable);
-int   DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr,
-                             const char* pszProjectionName, char **mappingTable);
-int   AddParamBasedOnPrjName( OGRSpatialReference* pOgr,
-                             const char* pszProjectionName, char **mappingTable);
-int   RemapGeogCSName(OGRSpatialReference* pOgr, const char *pszGeogCSName);
+CPL_CVSID("$Id: ogr_srs_esri.cpp 36472 2016-11-23 16:38:20Z rouault $");
 
 extern void OGREPSGDatumNameMassage( char ** ppszDatum );
 
 CPL_C_START
-void CleanupESRIDatumMappingTable(void);
+void CleanupESRIDatumMappingTable( void );
 CPL_C_END
 
-static int   FindCodeFromDict( const char* pszDictFile, const char* CSName, char* code );
-
 static const char * const apszProjMapping[] = {
     "Albers", SRS_PT_ALBERS_CONIC_EQUAL_AREA,
     "Cassini", SRS_PT_CASSINI_SOLDNER,
@@ -285,20 +276,39 @@ static const int anUsgsEsriZones[] =
 /* -------------------------------------------------------------------- */
 /*      Datum Mapping functions and definitions                         */
 /* -------------------------------------------------------------------- */
-/* TODO adapt existing code and test */
-#define DM_IDX_EPSG_CODE            0
-#define DM_IDX_ESRI_NAME            1
-#define DM_IDX_EPSG_NAME            2
-#define DM_ELT_SIZE                 3
+// TODO: adapt existing code and test.
+#define DM_IDX_EPSG_CODE 0
+#define DM_IDX_ESRI_NAME 1
+#define DM_IDX_EPSG_NAME 2
+#define DM_ELT_SIZE      3
 
-#define DM_GET_EPSG_CODE(map, i)          map[(i)*DM_ELT_SIZE + DM_IDX_EPSG_CODE]
-#define DM_GET_ESRI_NAME(map, i)          map[(i)*DM_ELT_SIZE + DM_IDX_ESRI_NAME]
-#define DM_GET_EPSG_NAME(map, i)          map[(i)*DM_ELT_SIZE + DM_IDX_EPSG_NAME]
+#define DM_GET_EPSG_CODE(map, i) map[(i)*DM_ELT_SIZE + DM_IDX_EPSG_CODE]
+#define DM_GET_ESRI_NAME(map, i) map[(i)*DM_ELT_SIZE + DM_IDX_ESRI_NAME]
 
-static char *DMGetEPSGCode(int i) { return DM_GET_EPSG_CODE(papszDatumMapping, i); }
-static char *DMGetESRIName(int i) { return DM_GET_ESRI_NAME(papszDatumMapping, i); }
-/* static char *DMGetEPSGName(int i) { return DM_GET_EPSG_NAME(papszDatumMapping, i); } */
+static char *DMGetEPSGCode( int i ) {
+    return DM_GET_EPSG_CODE(papszDatumMapping, i);
+}
+
+static char *DMGetESRIName( int i ) {
+    return DM_GET_ESRI_NAME(papszDatumMapping, i);
+}
 
+/************************************************************************/
+/*                           SetNewName()                               */
+/*                                                                      */
+/*      Set an esri name                                                */
+/************************************************************************/
+static
+void SetNewName( OGRSpatialReference* pOgr, const char* keyName,
+                 const char* newName )
+{
+    OGR_SRSNode *poNode = pOgr->GetAttrNode( keyName );
+    OGR_SRSNode *poNodeChild = NULL;
+    if( poNode )
+        poNodeChild = poNode->GetChild(0);
+    if( poNodeChild)
+        poNodeChild->SetValue( newName);
+}
 
 /************************************************************************/
 /*                           ESRIToUSGSZone()                           */
@@ -310,7 +320,10 @@ static char *DMGetESRIName(int i) { return DM_GET_ESRI_NAME(papszDatumMapping, i
 static int ESRIToUSGSZone( int nESRIZone )
 
 {
-    const int nPairs = sizeof(anUsgsEsriZones) / (2*sizeof(int));
+    // anUsgsEsriZones is a series of ints where 2 consecutive integers
+    // are used to map from USGS to ESRI state plane zones.
+    // TODO(schwehr): Would be better as a std::map.
+    const int nPairs = sizeof(anUsgsEsriZones) / (2 * sizeof(int));
 
     for( int i = 0; i < nPairs; i++ )
     {
@@ -331,9 +344,9 @@ static int ESRIToUSGSZone( int nESRIZone )
 static void MorphNameToESRI( char ** ppszName )
 
 {
-    char        *pszName = *ppszName;
+    char *pszName = *ppszName;
 
-    if (pszName[0] == '\0')
+    if( pszName[0] == '\0' )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -406,7 +419,7 @@ static void InitDatumMappingTable()
 /* -------------------------------------------------------------------- */
 /*      Try to open the datum.csv file.                                 */
 /* -------------------------------------------------------------------- */
-    const char  *pszFilename = CSVFilename("gdal_datum.csv");
+    const char *pszFilename = CSVFilename("gdal_datum.csv");
     VSILFILE *fp = VSIFOpenL( pszFilename, "rb" );
 
 /* -------------------------------------------------------------------- */
@@ -446,8 +459,9 @@ static void InitDatumMappingTable()
     int nMappingCount = 0;
     const int nMaxDatumMappings = 1000;
     char **papszFields = NULL;
+    // TODO(schwehr): Explain the 3.
     papszDatumMapping = static_cast<char **>(
-        CPLCalloc(sizeof(char*),nMaxDatumMappings*3) );
+        CPLCalloc(sizeof(char*), nMaxDatumMappings*3) );
 
     for( papszFields = CSVReadParseLineL( fp );
          papszFields != NULL;
@@ -457,7 +471,7 @@ static void InitDatumMappingTable()
 
         CPLAssert( nMappingCount+1 < nMaxDatumMappings );
 
-        if( MAX(nEPSGNameField,MAX(nDatumCodeField,nESRINameField))
+        if( std::max(nEPSGNameField, std::max(nDatumCodeField, nESRINameField))
             < nFieldCount
             && nMaxDatumMappings > nMappingCount+1 )
         {
@@ -481,7 +495,6 @@ static void InitDatumMappingTable()
     papszDatumMapping[nMappingCount*3+2] = NULL;
 }
 
-
 /************************************************************************/
 /*                         OSRImportFromESRI()                          */
 /************************************************************************/
@@ -489,7 +502,8 @@ static void InitDatumMappingTable()
 /**
  * \brief Import coordinate system from ESRI .prj format(s).
  *
- * This function is the same as the C++ method OGRSpatialReference::importFromESRI()
+ * This function is the same as the C++ method
+ * OGRSpatialReference::importFromESRI().
  */
 OGRErr OSRImportFromESRI( OGRSpatialReferenceH hSRS, char **papszPrj )
 
@@ -517,13 +531,13 @@ static double OSR_GDV( char **papszNV, const char * pszField,
 
     if( STARTS_WITH_CI(pszField, "PARAM_") )
     {
-        int iLine = 0;  // iLine is used after the for loop.
+        int iLine = 0;  // Used after for loop.
         for( ;
              papszNV[iLine] != NULL &&
                  !STARTS_WITH_CI(papszNV[iLine], "Paramet");
              iLine++ ) {}
 
-        for( int nOffset=atoi(pszField+6);
+        for( int nOffset = atoi(pszField+6);
              papszNV[iLine] != NULL && nOffset > 0;
              iLine++ )
         {
@@ -549,13 +563,14 @@ static double OSR_GDV( char **papszNV, const char * pszField,
             char **papszTokens = CSLTokenizeString(papszNV[iLine]);
             if( CSLCount(papszTokens) == 3 )
             {
-                /* http://agdcftp1.wr.usgs.gov/pub/projects/lcc/akcan_lcc/akcan.tar.gz contains */
-                /* weird values for the second. Ignore it and the result looks correct */
+                // http://agdcftp1.wr.usgs.gov/pub/projects/lcc/akcan_lcc/akcan.tar.gz
+                // contains weird values for the second. Ignore it and
+                // the result looks correct.
                 double dfSecond = CPLAtof(papszTokens[2]);
-                if (dfSecond < 0.0 || dfSecond >= 60.0)
+                if( dfSecond < 0.0 || dfSecond >= 60.0 )
                     dfSecond = 0.0;
 
-                dfValue = ABS(CPLAtof(papszTokens[0]))
+                dfValue = std::abs(CPLAtof(papszTokens[0]))
                     + CPLAtof(papszTokens[1]) / 60.0
                     + dfSecond / 3600.0;
 
@@ -563,9 +578,13 @@ static double OSR_GDV( char **papszNV, const char * pszField,
                     dfValue *= -1;
             }
             else if( CSLCount(papszTokens) > 0 )
+            {
                 dfValue = CPLAtof(papszTokens[0]);
+            }
             else
+            {
                 dfValue = dfDefaultValue;
+            }
 
             CSLDestroy( papszTokens );
 
@@ -575,10 +594,10 @@ static double OSR_GDV( char **papszNV, const char * pszField,
         return dfDefaultValue;
     }
 
-    int iLine = 0;  // iLine used after for loop.
+    int iLine = 0;  // Used after for loop.
     for( ;
          papszNV[iLine] != NULL &&
-             !EQUALN(papszNV[iLine],pszField,strlen(pszField));
+             !EQUALN(papszNV[iLine], pszField, strlen(pszField));
          iLine++ ) {}
 
     if( papszNV[iLine] == NULL )
@@ -598,10 +617,10 @@ static CPLString OSR_GDS( char **papszNV, const char * pszField,
     if( papszNV == NULL || papszNV[0] == NULL )
         return pszDefaultValue;
 
-    int iLine = 0;  // iLine used after for loop.
+    int iLine = 0;  // Used after for loop.
     for( ;
          papszNV[iLine] != NULL &&
-             !EQUALN(papszNV[iLine],pszField,strlen(pszField));
+             !EQUALN(papszNV[iLine], pszField, strlen(pszField));
          iLine++ ) {}
 
     if( papszNV[iLine] == NULL )
@@ -609,17 +628,54 @@ static CPLString OSR_GDS( char **papszNV, const char * pszField,
 
     char **papszTokens = CSLTokenizeString(papszNV[iLine]);
 
-    CPLString osResult;
-    if( CSLCount(papszTokens) > 1 )
-        osResult = papszTokens[1];
-    else
-        osResult = pszDefaultValue;
+    CPLString osResult =
+        CSLCount(papszTokens) > 1 ? papszTokens[1] : pszDefaultValue;
 
     CSLDestroy( papszTokens );
     return osResult;
 }
 
 /************************************************************************/
+/*                  RemapPNamesBasedOnProjCSAndPName()                  */
+/*                                                                      */
+/*      Convert a parameters to ESRI style name                         */
+/************************************************************************/
+
+static
+int RemapPNamesBasedOnProjCSAndPName( OGRSpatialReference* pOgr,
+                                      const char* pszProgCSName,
+                                      char **mappingTable )
+{
+  int ret = 0;
+  OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
+  for( int i = 0; mappingTable[i] != NULL; i += 3 )
+  {
+    while( mappingTable[i] != NULL &&
+           EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
+    {
+      const char* pszParamName = mappingTable[i+1];
+      for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
+      {
+          OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
+
+          if( EQUAL(poParm->GetValue(), "PARAMETER")
+              && poParm->GetChildCount() == 2
+              && EQUAL(poParm->GetChild(0)->GetValue(), pszParamName) )
+          {
+              poParm->GetChild(0)->SetValue( mappingTable[i+2] );
+              break;
+          }
+      }
+      ret++;
+      i += 3;
+    }
+    if( ret > 0 )
+      break;
+  }
+  return ret;
+}
+
+/************************************************************************/
 /*                          importFromESRI()                            */
 /************************************************************************/
 
@@ -670,7 +726,7 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
         for( int i = 1; papszPrj[i] != NULL; i++ )
         {
             pszWKT = static_cast<char *>(
-                CPLRealloc(pszWKT,strlen(pszWKT)+strlen(papszPrj[i])+1) );
+                CPLRealloc(pszWKT, strlen(pszWKT)+strlen(papszPrj[i]) + 1));
             strcat( pszWKT, papszPrj[i] );
         }
         char *pszWKT2 = pszWKT;
@@ -687,38 +743,35 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 /* -------------------------------------------------------------------- */
     CPLString osProj = OSR_GDS( papszPrj, "Projection", "" );
 
-    if( EQUAL(osProj,"") )
+    if( EQUAL(osProj, "") )
     {
-        CPLDebug( "OGR_ESRI", "Can't find Projection\n" );
+        CPLDebug( "OGR_ESRI", "Can't find Projection" );
         return OGRERR_CORRUPT_DATA;
     }
-
-    else if( EQUAL(osProj,"GEOGRAPHIC") )
+    else if( EQUAL(osProj, "GEOGRAPHIC") )
     {
         // Nothing to do.
     }
-
-    else if( EQUAL(osProj,"utm") )
+    else if( EQUAL(osProj, "utm") )
     {
-        if( static_cast<int>( OSR_GDV( papszPrj, "zone", 0.0 ) ) != 0 )
+        if( static_cast<int>(OSR_GDV(papszPrj, "zone", 0.0)) != 0 )
         {
-            const double dfYShift = OSR_GDV( papszPrj, "Yshift", 0.0 );
+            const double dfYShift = OSR_GDV(papszPrj, "Yshift", 0.0);
 
-            SetUTM( static_cast<int>( OSR_GDV( papszPrj, "zone", 0.0 ) ),
+            SetUTM( static_cast<int>(OSR_GDV(papszPrj, "zone", 0.0)),
                     dfYShift == 0.0 );
         }
         else
         {
-            const double dfCentralMeridian = OSR_GDV( papszPrj, "PARAM_1", 0.0 );
-            const double dfRefLat = OSR_GDV( papszPrj, "PARAM_2", 0.0 );
+            const double dfCentralMeridian = OSR_GDV(papszPrj, "PARAM_1", 0.0);
+            const double dfRefLat = OSR_GDV(papszPrj, "PARAM_2", 0.0);
 
             const int nZone = static_cast<int>(
-                (dfCentralMeridian+183) / 6.0 + 0.0000001 );
+                (dfCentralMeridian + 183.0) / 6.0 + 0.0000001 );
             SetUTM( nZone, dfRefLat >= 0.0 );
         }
     }
-
-    else if( EQUAL(osProj,"STATEPLANE") )
+    else if( EQUAL(osProj, "STATEPLANE") )
     {
         int nZone = static_cast<int>( OSR_GDV( papszPrj, "zone", 0.0 ) );
         if( nZone != 0 )
@@ -728,23 +781,30 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 
         if( nZone != 0 )
         {
-            if( EQUAL(OSR_GDS( papszPrj, "Datum", "NAD83"),"NAD27") )
+            if( EQUAL(OSR_GDS( papszPrj, "Datum", "NAD83"), "NAD27") )
                 SetStatePlane( nZone, FALSE );
             else
                 SetStatePlane( nZone, TRUE );
         }
     }
-
-    else if( EQUAL(osProj,"GREATBRITIAN_GRID")
-             || EQUAL(osProj,"GREATBRITAIN_GRID") )
+    else if( EQUAL(osProj, "GREATBRITIAN_GRID")
+             || EQUAL(osProj, "GREATBRITAIN_GRID") )
     {
         const char *pszWkt =
-            "PROJCS[\"OSGB 1936 / British National Grid\",GEOGCS[\"OSGB 1936\",DATUM[\"OSGB_1936\",SPHEROID[\"Airy 1830\",6377563.396,299.3249646]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",49],PARAMETER[\"central_meridian\",-2],PARAMETER[\"scale_factor\",0.999601272],PARAMETER[\"false_easting\",400000],PARAMETER[\"false_northing\",-100000],UNIT[\"metre\",1]]";
+            "PROJCS[\"OSGB 1936 / British National Grid\","
+            "GEOGCS[\"OSGB 1936\",DATUM[\"OSGB_1936\","
+            "SPHEROID[\"Airy 1830\",6377563.396,299.3249646]],"
+            "PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],"
+            "PROJECTION[\"Transverse_Mercator\"],"
+            "PARAMETER[\"latitude_of_origin\",49],"
+            "PARAMETER[\"central_meridian\",-2],"
+            "PARAMETER[\"scale_factor\",0.999601272],"
+            "PARAMETER[\"false_easting\",400000],"
+            "PARAMETER[\"false_northing\",-100000],UNIT[\"metre\",1]]";
 
-        importFromWkt( (char **) &pszWkt );
+        importFromWkt( const_cast<char **>(&pszWkt) );
     }
-
-    else if( EQUAL(osProj,"ALBERS") )
+    else if( EQUAL(osProj, "ALBERS") )
     {
         SetACEA( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
                  OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
@@ -753,8 +813,7 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                  OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
                  OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
     }
-
-    else if( EQUAL(osProj,"LAMBERT") )
+    else if( EQUAL(osProj, "LAMBERT") )
     {
         SetLCC( OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
                 OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
@@ -763,16 +822,14 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                 OSR_GDV( papszPrj, "PARAM_5", 0.0 ),
                 OSR_GDV( papszPrj, "PARAM_6", 0.0 ) );
     }
-
-    else if( EQUAL(osProj,"LAMBERT_AZIMUTHAL") )
+    else if( EQUAL(osProj, "LAMBERT_AZIMUTHAL") )
     {
         SetLAEA( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
                  OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
                  OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
                  OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
     }
-
-    else if( EQUAL(osProj,"EQUIDISTANT_CONIC") )
+    else if( EQUAL(osProj, "EQUIDISTANT_CONIC") )
     {
         const int nStdPCount = static_cast<int>(
             OSR_GDV( papszPrj, "PARAM_1", 0.0 ) );
@@ -796,8 +853,7 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                    OSR_GDV( papszPrj, "PARAM_7", 0.0 ) );
         }
     }
-
-    else if( EQUAL(osProj,"TRANSVERSE") )
+    else if( EQUAL(osProj, "TRANSVERSE") )
     {
         SetTM( OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
                OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
@@ -805,8 +861,7 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                OSR_GDV( papszPrj, "PARAM_4", 0.0 ),
                OSR_GDV( papszPrj, "PARAM_5", 0.0 ) );
     }
-
-    else if( EQUAL(osProj,"POLAR") )
+    else if( EQUAL(osProj, "POLAR") )
     {
         SetPS( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
                OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
@@ -814,8 +869,7 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
                OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
     }
-
-    else if( EQUAL(osProj,"MERCATOR") )
+    else if( EQUAL(osProj, "MERCATOR") )
     {
         SetMercator( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
                      OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
@@ -823,22 +877,19 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                      OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
                      OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
     }
-
     else if( EQUAL(osProj, SRS_PT_MERCATOR_AUXILIARY_SPHERE) )
     {
        // This is EPSG:3875 Pseudo Mercator. We might as well import it from
        // the EPSG spec.
        importFromEPSG(3857);
     }
-
-    else if( EQUAL(osProj,"POLYCONIC") )
+    else if( EQUAL(osProj, "POLYCONIC") )
     {
         SetPolyconic( OSR_GDV( papszPrj, "PARAM_2", 0.0 ),
                       OSR_GDV( papszPrj, "PARAM_1", 0.0 ),
                       OSR_GDV( papszPrj, "PARAM_3", 0.0 ),
                       OSR_GDV( papszPrj, "PARAM_4", 0.0 ) );
     }
-
     else
     {
         CPLDebug( "OGR_ESRI", "Unsupported projection: %s", osProj.c_str() );
@@ -850,10 +901,10 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 /* -------------------------------------------------------------------- */
     if( !IsLocal() && GetAttrNode( "GEOGCS" ) == NULL )
     {
-        CPLString osDatum = OSR_GDS( papszPrj, "Datum", "");
+        const CPLString osDatum = OSR_GDS( papszPrj, "Datum", "");
 
-        if( EQUAL(osDatum,"NAD27") || EQUAL(osDatum,"NAD83")
-            || EQUAL(osDatum,"WGS84") || EQUAL(osDatum,"WGS72") )
+        if( EQUAL(osDatum, "NAD27") || EQUAL(osDatum, "NAD83")
+            || EQUAL(osDatum, "WGS84") || EQUAL(osDatum, "WGS72") )
         {
             SetWellKnownGeogCS( osDatum );
         }
@@ -870,40 +921,40 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
         {
             CPLString osSpheroid = OSR_GDS( papszPrj, "Spheroid", "");
 
-            if( EQUAL(osSpheroid,"INT1909")
-                || EQUAL(osSpheroid,"INTERNATIONAL1909") )
+            if( EQUAL(osSpheroid, "INT1909")
+                || EQUAL(osSpheroid, "INTERNATIONAL1909") )
             {
                 OGRSpatialReference oGCS;
                 oGCS.importFromEPSG( 4022 );
                 CopyGeogCSFrom( &oGCS );
             }
-            else if( EQUAL(osSpheroid,"AIRY") )
+            else if( EQUAL(osSpheroid, "AIRY") )
             {
                 OGRSpatialReference oGCS;
                 oGCS.importFromEPSG( 4001 );
                 CopyGeogCSFrom( &oGCS );
             }
-            else if( EQUAL(osSpheroid,"CLARKE1866") )
+            else if( EQUAL(osSpheroid, "CLARKE1866") )
             {
                 OGRSpatialReference oGCS;
                 oGCS.importFromEPSG( 4008 );
                 CopyGeogCSFrom( &oGCS );
             }
-            else if( EQUAL(osSpheroid,"GRS80") )
+            else if( EQUAL(osSpheroid, "GRS80") )
             {
                 OGRSpatialReference oGCS;
                 oGCS.importFromEPSG( 4019 );
                 CopyGeogCSFrom( &oGCS );
             }
-            else if( EQUAL(osSpheroid,"KRASOVSKY")
-                     || EQUAL(osSpheroid,"KRASSOVSKY")
-                     || EQUAL(osSpheroid,"KRASSOWSKY") )
+            else if( EQUAL(osSpheroid, "KRASOVSKY")
+                     || EQUAL(osSpheroid, "KRASSOVSKY")
+                     || EQUAL(osSpheroid, "KRASSOWSKY") )
             {
                 OGRSpatialReference oGCS;
                 oGCS.importFromEPSG( 4024 );
                 CopyGeogCSFrom( &oGCS );
             }
-            else if( EQUAL(osSpheroid,"Bessel") )
+            else if( EQUAL(osSpheroid, "Bessel") )
             {
                 OGRSpatialReference oGCS;
                 oGCS.importFromEPSG( 4004 );
@@ -914,15 +965,18 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
                 bool bFoundParameters = false;
                 for( int iLine = 0; papszPrj[iLine] != NULL; iLine++ )
                 {
-                    if( STARTS_WITH_CI(papszPrj[iLine],"Parameters") )
+                    if( STARTS_WITH_CI(papszPrj[iLine], "Parameters") )
                     {
-                        char** papszTokens = CSLTokenizeString(papszPrj[iLine] + strlen("Parameters"));
+                        char** papszTokens =
+                            CSLTokenizeString(papszPrj[iLine] +
+                                              strlen("Parameters"));
                         if( CSLCount(papszTokens) == 2 )
                         {
                             OGRSpatialReference oGCS;
-                            const double dfSemiMajor = CPLAtof( papszTokens[0] );
-                            const double dfSemiMinor = CPLAtof( papszTokens[1] );
-                            const double dfInvFlattening = OSRCalcInvFlattening( dfSemiMajor, dfSemiMinor );
+                            const double dfSemiMajor = CPLAtof(papszTokens[0]);
+                            const double dfSemiMinor = CPLAtof(papszTokens[1]);
+                            const double dfInvFlattening =
+                                OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
                             oGCS.SetGeogCS( "unknown", "unknown", "unknown",
                                             dfSemiMajor, dfInvFlattening );
                             CopyGeogCSFrom( &oGCS );
@@ -946,12 +1000,12 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 /* -------------------------------------------------------------------- */
     if( IsLocal() || IsProjected() )
     {
-        double dfOldUnits = GetLinearUnits();
-        CPLString osValue = OSR_GDS( papszPrj, "Units", "" );
+        const double dfOldUnits = GetLinearUnits();
+        const CPLString osValue = OSR_GDS( papszPrj, "Units", "" );
 
         if( EQUAL(osValue, "" ) )
             SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1.0 );
-        else if( EQUAL(osValue,"FEET") )
+        else if( EQUAL(osValue, "FEET") )
             SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT,
                                                CPLAtof(SRS_UL_US_FOOT_CONV) );
         else if( CPLAtof(osValue) != 0.0 )
@@ -962,8 +1016,8 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 
         // If we have reset the linear units we should clear any authority
         // nodes on the PROJCS.  This especially applies to state plane
-        // per bug 1697
-        double dfNewUnits = GetLinearUnits();
+        // per bug #1697.
+        const double dfNewUnits = GetLinearUnits();
         if( dfOldUnits != 0.0
             && (dfNewUnits / dfOldUnits < 0.9999999
                 || dfNewUnits / dfOldUnits > 1.0000001) )
@@ -977,123 +1031,389 @@ OGRErr OGRSpatialReference::importFromESRI( char **papszPrj )
 }
 
 /************************************************************************/
-/*                            morphToESRI()                             */
+/*                RemapPValuesBasedOnProjCSAndPName()                   */
+/*                                                                      */
+/*      Convert a parameters to ESRI style name                         */
 /************************************************************************/
-/**
- * \brief Convert in place to ESRI WKT format.
- *
- * The value nodes of this coordinate system are modified in various manners
- * more closely map onto the ESRI concept of WKT format.  This includes
- * renaming a variety of projections and arguments, and stripping out
- * nodes note recognised by ESRI (like AUTHORITY and AXIS).
- *
- * This does the same as the C function OSRMorphToESRI().
- *
- * @return OGRERR_NONE unless something goes badly wrong.
- */
-
-OGRErr OGRSpatialReference::morphToESRI()
 
+static
+int RemapPValuesBasedOnProjCSAndPName( OGRSpatialReference* pOgr,
+                                       const char* pszProgCSName,
+                                       char **mappingTable )
 {
-/* -------------------------------------------------------------------- */
-/*      Special case for EPSG:3857. Hard to deal with in the general    */
-/*      case as GDAL (at the time of writing) uses regular Mercator_1SP */
-/*      to model it.                                                    */
-/* -------------------------------------------------------------------- */
-    const char* pszAuthName = GetAuthorityName(NULL);
-    const char* pszAuthCode = GetAuthorityCode(NULL);
-    if( (pszAuthName != NULL && EQUAL(pszAuthName,"EPSG") && pszAuthCode != NULL &&
-         atoi(pszAuthCode) == 3857) ||
-        (GetAttrValue("PROJCS") != NULL && EQUAL(GetAttrValue("PROJCS"), "WGS 84 / Pseudo-Mercator")) )
-    {
-        Clear();
-        const char* pszESRI_PE_WebMercator = "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\",GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\",SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Mercator_Auxiliary_Sphere\"],PARAMETER[\"False_Easting\",0.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0],PARAMETER[\"Standard_Parallel_1\",0.0],PARAMETER[\"Auxiliary_Sphere_Type\",0.0],UNIT[\"Meter\",1.0]]";
-        return importFromWkt( (char**) &pszESRI_PE_WebMercator );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Fixup ordering, missing linear units, etc.                      */
-/* -------------------------------------------------------------------- */
+    int ret = 0;
+    OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
+    for( int i = 0; mappingTable[i] != NULL; i += 4 )
     {
-        const OGRErr eErr = Fixup();
-        if( eErr != OGRERR_NONE )
-            return eErr;
-    }
+        while( mappingTable[i] != NULL &&
+               EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
+        {
+            const char* pszParamName = mappingTable[i+1];
+            const char* pszParamValue = mappingTable[i+2];
+            for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
+            {
+                OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
 
-/* -------------------------------------------------------------------- */
-/*      Strip all CT parameters (AXIS, AUTHORITY, TOWGS84, etc).        */
-/* -------------------------------------------------------------------- */
-    {
-        const OGRErr eErr = StripCTParms();
-        if( eErr != OGRERR_NONE )
-            return eErr;
+                if( EQUAL(poParm->GetValue(), "PARAMETER")
+                    && poParm->GetChildCount() == 2
+                    && EQUAL(poParm->GetChild(0)->GetValue(), pszParamName)
+                    && EQUALN(poParm->GetChild(1)->GetValue(),
+                              pszParamValue, strlen(pszParamValue) ) )
+                {
+                    poParm->GetChild(1)->SetValue( mappingTable[i+3] );
+                    break;
+                }
+            }
+            ret++;
+            i += 4;
+        }
+        if( ret > 0 )
+            break;
     }
+    return ret;
+}
 
-    if( GetRoot() == NULL )
-        return OGRERR_NONE;
-
-/* -------------------------------------------------------------------- */
-/*      There is a special case for Hotine Oblique Mercator to split    */
-/*      out the case with an angle to rectified grid.  Bug 423          */
-/* -------------------------------------------------------------------- */
-    const char *pszProjection = GetAttrValue("PROJECTION");
+/************************************************************************/
+/*                          AddParamBasedOnPrjName()                    */
+/*                                                                      */
+/*      Add ESRI style parameters                                       */
+/************************************************************************/
 
-    if( pszProjection != NULL
-        && EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR)
-        && fabs(GetProjParm(SRS_PP_AZIMUTH, 0.0 )-90) < 0.0001
-        && fabs(GetProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 0.0 )-90) < 0.0001 )
+static
+int AddParamBasedOnPrjName( OGRSpatialReference* pOgr,
+                            const char* pszProjectionName,
+                            char **mappingTable )
+{
+    int ret = -1;
+    OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
+    for( int i = 0; mappingTable[i] != NULL; i += 3 )
     {
-        SetNode( "PROJCS|PROJECTION",
-                 "Hotine_Oblique_Mercator_Azimuth_Center" );
-
-        /* ideally we should strip out of the rectified_grid_angle */
-        // strip off rectified_grid_angle -- I hope it is 90!
-        OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-        const int iRGAChild = FindProjParm( "rectified_grid_angle", poPROJCS );
-        if( iRGAChild != -1 )
-            poPROJCS->DestroyChild( iRGAChild);
+        if( EQUALN(pszProjectionName, mappingTable[i],
+                   strlen(mappingTable[i])) )
+        {
+            bool exist = false;
+            for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
+            {
+                OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
 
-        pszProjection = GetAttrValue("PROJECTION");
+                if( EQUAL(poParm->GetValue(), "PARAMETER")
+                    && poParm->GetChildCount() == 2
+                    && EQUAL(poParm->GetChild(0)->GetValue(),
+                             mappingTable[i+1]) )
+                    exist = true;
+            }
+            if( !exist )
+            {
+                OGR_SRSNode *poParm = new OGR_SRSNode( "PARAMETER" );
+                poParm->AddChild( new OGR_SRSNode( mappingTable[i+1] ) );
+                poParm->AddChild( new OGR_SRSNode( mappingTable[i+2] ) );
+                poPROJCS->AddChild( poParm );
+                ret++;
+            }
+        }
     }
+    return ret;
+}
 
-/* -------------------------------------------------------------------- */
-/*      Polar_Stereographic maps to ESRI codes                          */
-/*      Stereographic_South_Pole or Stereographic_North_Pole based      */
-/*      on latitude.                                                    */
-/* -------------------------------------------------------------------- */
-    if( pszProjection != NULL
-        && ( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) ))
+/************************************************************************/
+/*                        DeleteParamBasedOnPrjName                     */
+/*                                                                      */
+/*      Delete non-ESRI parameters                                      */
+/************************************************************************/
+
+static
+int DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr,
+                               const char* pszProjectionName,
+                               char **mappingTable )
+{
+    int ret = -1;
+    for( int i = 0; mappingTable[i] != NULL; i += 2 )
     {
-        if( GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) < 0.0 )
-        {
-            SetNode( "PROJCS|PROJECTION",
-                     "Stereographic_South_Pole" );
-            pszProjection = GetAttrValue("PROJECTION");
-        }
-        else
+        if( EQUALN(pszProjectionName, mappingTable[i],
+                   strlen(mappingTable[i])) )
         {
-            SetNode( "PROJCS|PROJECTION",
-                     "Stereographic_North_Pole" );
-            pszProjection = GetAttrValue("PROJECTION");
+            OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
+            const char* pszParamName = mappingTable[i+1];
+            int iIndex = -1;
+            for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
+            {
+                OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
+
+                if( EQUAL(poParm->GetValue(), "PARAMETER")
+                    && poParm->GetChildCount() == 2
+                    && EQUAL(poParm->GetChild(0)->GetValue(), pszParamName) )
+                {
+                    iIndex = iChild;
+                    break;
+                }
+            }
+            if( iIndex >= 0 )
+            {
+                poPROJCS->DestroyChild( iIndex );
+                ret++;
+            }
         }
     }
+    return ret;
+}
 
-/* -------------------------------------------------------------------- */
-/*      OBLIQUE_STEREOGRAPHIC maps to ESRI Double_Stereographic         */
-/* -------------------------------------------------------------------- */
-    if( pszProjection != NULL
-        && ( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) ))
-    {
-        SetNode( "PROJCS|PROJECTION", "Double_Stereographic" );
-    }
+/************************************************************************/
+/*                     RemapNamesBasedOnTwo()                           */
+/*                                                                      */
+/*      Convert a name to ESRI style name                               */
+/************************************************************************/
 
-/* -------------------------------------------------------------------- */
-/*      Translate PROJECTION keywords that are misnamed.                */
-/* -------------------------------------------------------------------- */
-    // TODO(schwehr): How is applyRemapper safe with
+static
+int RemapNamesBasedOnTwo( OGRSpatialReference* pOgr, const char* name1,
+                          const char* name2,
+                          char **mappingTable, int nTableStepSize,
+                          char** pszkeyNames, long nKeys )
+{
+    int iIndex = -1;
+    for( int i = 0; mappingTable[i] != NULL; i += nTableStepSize )
+    {
+        const size_t n = std::min(strlen(name1), strlen(mappingTable[i]));
+        if( EQUALN(name1, mappingTable[i], n) )
+        {
+            int j = i;
+            while( mappingTable[j] != NULL &&
+                   EQUAL(mappingTable[i], mappingTable[j]) )
+            {
+                // TODO(warmerdam): Explain what is going on here from r15992.
+                if( EQUALN(name2, mappingTable[j+1],
+                           strlen(mappingTable[j+1])) )
+                {
+                    iIndex = j;
+                    break;
+                }
+                j += 3;
+            }
+            if( iIndex >= 0 )
+                break;
+        }
+    }
+    if( iIndex >= 0 )
+    {
+        for( int i = 0; i < nKeys; i ++ )
+        {
+            OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyNames[i] );
+            OGR_SRSNode *poNodeChild = NULL;
+            if( poNode )
+                poNodeChild = poNode->GetChild(0);
+            if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
+                poNodeChild->SetValue( mappingTable[iIndex+i+2]);
+        }
+    }
+    return iIndex;
+}
+
+/************************************************************************/
+/*                           RemapNameBasedOnKeyName()                  */
+/*                                                                      */
+/*      Convert a name to ESRI style name                               */
+/************************************************************************/
+
+static
+int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName,
+                             const char* pszkeyName,
+                             char **mappingTable )
+{
+    int iIndex = -1;
+    for( int i = 0; mappingTable[i] != NULL; i += 2 )
+    {
+        if( EQUAL(pszName, mappingTable[i]) )
+        {
+            iIndex = i;
+            break;
+        }
+    }
+    if( iIndex >= 0 )
+    {
+        OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyName );
+        OGR_SRSNode *poNodeChild = NULL;
+        if( poNode )
+            poNodeChild = poNode->GetChild(0);
+        if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
+            poNodeChild->SetValue( mappingTable[iIndex+1]);
+    }
+    return iIndex;
+}
+
+/************************************************************************/
+/*                                   RemapGeogCSName()                  */
+/*                                                                      */
+/*      Convert names to ESRI style                                     */
+/************************************************************************/
+static
+int RemapGeogCSName( OGRSpatialReference* pOgr, const char *pszGeogCSName )
+{
+    static const char * const keyNamesG[] = { "GEOGCS" };
+    int ret = -1;
+
+    const char* pszUnitName = pOgr->GetAttrValue( "GEOGCS|UNIT");
+    if( pszUnitName )
+    {
+        // TODO(schwehr): Figure out a safer way to rename.
+        //   The casting away const here looks dangerous.
+        ret = RemapNamesBasedOnTwo(
+            pOgr, pszGeogCSName+4, pszUnitName,
+            const_cast<char**>(apszGcsNameMappingBasedOnUnit),
+            3, const_cast<char**>(keyNamesG), 1);
+    }
+
+    if( ret < 0 )
+    {
+        const char* pszPrimeName = pOgr->GetAttrValue("PRIMEM");
+        if( pszPrimeName )
+            ret = RemapNamesBasedOnTwo(
+                pOgr, pszGeogCSName+4, pszPrimeName,
+                const_cast<char**>(apszGcsNameMappingBasedPrime),
+                3, const_cast<char**>(keyNamesG), 1);
+        if( ret < 0 )
+            ret = RemapNameBasedOnKeyName(
+                pOgr, pszGeogCSName+4, "GEOGCS",
+                const_cast<char**>(apszGcsNameMapping) );
+    }
+    if( ret < 0 )
+    {
+        const char* pszProjCS = pOgr->GetAttrValue( "PROJCS" );
+        ret = RemapNamesBasedOnTwo(
+            pOgr, pszProjCS, pszGeogCSName,
+            const_cast<char**>(apszGcsNameMappingBasedOnProjCS),
+            3, const_cast<char**>(keyNamesG), 1);
+    }
+    return ret;
+}
+
+/************************************************************************/
+/*                            morphToESRI()                             */
+/************************************************************************/
+/**
+ * \brief Convert in place to ESRI WKT format.
+ *
+ * The value nodes of this coordinate system are modified in various manners
+ * more closely map onto the ESRI concept of WKT format.  This includes
+ * renaming a variety of projections and arguments, and stripping out
+ * nodes note recognised by ESRI (like AUTHORITY and AXIS).
+ *
+ * This does the same as the C function OSRMorphToESRI().
+ *
+ * @return OGRERR_NONE unless something goes badly wrong.
+ */
+
+OGRErr OGRSpatialReference::morphToESRI()
+
+{
+/* -------------------------------------------------------------------- */
+/*      Special case for EPSG:3857. Hard to deal with in the general    */
+/*      case as GDAL (at the time of writing) uses regular Mercator_1SP */
+/*      to model it.                                                    */
+/* -------------------------------------------------------------------- */
+    const char* pszAuthName = GetAuthorityName(NULL);
+    const char* pszAuthCode = GetAuthorityCode(NULL);
+    if( (pszAuthName != NULL && EQUAL(pszAuthName, "EPSG") &&
+         pszAuthCode != NULL && atoi(pszAuthCode) == 3857) ||
+        (GetAttrValue("PROJCS") != NULL &&
+         EQUAL(GetAttrValue("PROJCS"), "WGS 84 / Pseudo-Mercator")) )
+    {
+        Clear();
+        const char* pszESRI_PE_WebMercator =
+            "PROJCS[\"WGS_1984_Web_Mercator_Auxiliary_Sphere\","
+            "GEOGCS[\"GCS_WGS_1984\",DATUM[\"D_WGS_1984\","
+            "SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],"
+            "PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],"
+            "PROJECTION[\"Mercator_Auxiliary_Sphere\"],"
+            "PARAMETER[\"False_Easting\",0.0],"
+            "PARAMETER[\"False_Northing\",0.0],"
+            "PARAMETER[\"Central_Meridian\",0.0],"
+            "PARAMETER[\"Standard_Parallel_1\",0.0],"
+            "PARAMETER[\"Auxiliary_Sphere_Type\",0.0],UNIT[\"Meter\",1.0]]";
+        return importFromWkt( (char**) &pszESRI_PE_WebMercator );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Fixup ordering, missing linear units, etc.                      */
+/* -------------------------------------------------------------------- */
+    {
+        const OGRErr eErr = Fixup();
+        if( eErr != OGRERR_NONE )
+            return eErr;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Strip all CT parameters (AXIS, AUTHORITY, TOWGS84, etc).        */
+/* -------------------------------------------------------------------- */
+    {
+        const OGRErr eErr = StripCTParms();
+        if( eErr != OGRERR_NONE )
+            return eErr;
+    }
+
+    if( GetRoot() == NULL )
+        return OGRERR_NONE;
+
+/* -------------------------------------------------------------------- */
+/*      There is a special case for Hotine Oblique Mercator to split    */
+/*      out the case with an angle to rectified grid.  Bug 423          */
+/* -------------------------------------------------------------------- */
+    const char *pszProjection = GetAttrValue("PROJECTION");
+
+    if( pszProjection != NULL
+        && EQUAL(pszProjection, SRS_PT_HOTINE_OBLIQUE_MERCATOR)
+        && fabs(GetProjParm(SRS_PP_AZIMUTH, 0.0) - 90) < 0.0001
+        && fabs(GetProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 0.0) - 90) < 0.0001 )
+    {
+        SetNode( "PROJCS|PROJECTION",
+                 "Hotine_Oblique_Mercator_Azimuth_Center" );
+
+        // Ideally we should strip out of the rectified_grid_angle.
+        // Strip off rectified_grid_angle -- Hope it is 90!
+        OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
+        const int iRGAChild = FindProjParm( "rectified_grid_angle", poPROJCS );
+        if( iRGAChild != -1 )
+            poPROJCS->DestroyChild( iRGAChild);
+
+        pszProjection = GetAttrValue("PROJECTION");
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Polar_Stereographic maps to ESRI codes                          */
+/*      Stereographic_South_Pole or Stereographic_North_Pole based      */
+/*      on latitude.                                                    */
+/* -------------------------------------------------------------------- */
+    if( pszProjection != NULL
+        && ( EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) ))
+    {
+        if( GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) < 0.0 )
+        {
+            SetNode( "PROJCS|PROJECTION",
+                     "Stereographic_South_Pole" );
+            pszProjection = GetAttrValue("PROJECTION");
+        }
+        else
+        {
+            SetNode( "PROJCS|PROJECTION",
+                     "Stereographic_North_Pole" );
+            pszProjection = GetAttrValue("PROJECTION");
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      OBLIQUE_STEREOGRAPHIC maps to ESRI Double_Stereographic         */
+/* -------------------------------------------------------------------- */
+    if( pszProjection != NULL
+        && ( EQUAL(pszProjection, SRS_PT_OBLIQUE_STEREOGRAPHIC) ))
+    {
+        SetNode( "PROJCS|PROJECTION", "Double_Stereographic" );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Translate PROJECTION keywords that are misnamed.                */
+/* -------------------------------------------------------------------- */
+    // TODO(schwehr): How is applyRemapper safe with
     //   static const char * const apszProjMapping[]?
     GetRoot()->applyRemapper( "PROJECTION",
-                              const_cast<char **>(apszProjMapping+1),
+                              const_cast<char **>(apszProjMapping + 1),
                               const_cast<char **>(apszProjMapping),
                               2 );
     pszProjection = GetAttrValue("PROJECTION");
@@ -1104,10 +1424,9 @@ OGRErr OGRSpatialReference::morphToESRI()
     InitDatumMappingTable();
 
     GetRoot()->applyRemapper( "DATUM",
-                              papszDatumMapping+2, papszDatumMapping+1, 3 );
+                              papszDatumMapping + 2, papszDatumMapping + 1, 3 );
 
     const char *pszProjCSName      = NULL;
-    const char *pszGcsName         = NULL;
     OGR_SRSNode *poProjCS          = NULL;
     OGR_SRSNode *poProjCSNodeChild = NULL;
 
@@ -1123,47 +1442,47 @@ OGRErr OGRSpatialReference::morphToESRI()
         const char *pszUTMPrefix = NULL;
         int nGCSCode = -1;
 
-        if( pszAuthName != NULL && EQUAL(pszAuthName,"EPSG") )
+        if( pszAuthName != NULL && EQUAL(pszAuthName, "EPSG") )
             nGCSCode = atoi(GetAuthorityCode("GEOGCS"));
 
         if( nGCSCode == 4326
-            || EQUAL(pszGeogCSName,"WGS84")
-            || EQUAL(pszGeogCSName,"WGS 84") )
+            || EQUAL(pszGeogCSName, "WGS84")
+            || EQUAL(pszGeogCSName, "WGS 84") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_WGS_1984" );
             pszUTMPrefix = "WGS_1984";
         }
         else if( nGCSCode == 4322
-            || EQUAL(pszGeogCSName,"WGS72")
-            || EQUAL(pszGeogCSName,"WGS 72") )
+            || EQUAL(pszGeogCSName, "WGS72")
+            || EQUAL(pszGeogCSName, "WGS 72") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_WGS_1972" );
             pszUTMPrefix = "WGS_1972";
         }
         else if( nGCSCode == 4267
-                 || EQUAL(pszGeogCSName,"NAD27")
-                 || EQUAL(pszGeogCSName,"NAD 27") )
+                 || EQUAL(pszGeogCSName, "NAD27")
+                 || EQUAL(pszGeogCSName, "NAD 27") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1927" );
             pszUTMPrefix = "NAD_1927";
         }
         else if( nGCSCode == 4269
-                 || EQUAL(pszGeogCSName,"NAD83")
-                 || EQUAL(pszGeogCSName,"NAD 83") )
+                 || EQUAL(pszGeogCSName, "NAD83")
+                 || EQUAL(pszGeogCSName, "NAD 83") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_North_American_1983" );
             pszUTMPrefix = "NAD_1983";
         }
         else if( nGCSCode == 4167
-                 || EQUAL(pszGeogCSName,"NZGD2000")
-                 || EQUAL(pszGeogCSName,"NZGD 2000") )
+                 || EQUAL(pszGeogCSName, "NZGD2000")
+                 || EQUAL(pszGeogCSName, "NZGD 2000") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_NZGD_2000" );
             pszUTMPrefix = "NZGD_2000";
         }
         else if( nGCSCode == 4272
-                 || EQUAL(pszGeogCSName,"NZGD49")
-                 || EQUAL(pszGeogCSName,"NZGD 49") )
+                 || EQUAL(pszGeogCSName, "NZGD49")
+                 || EQUAL(pszGeogCSName, "NZGD 49") )
         {
             poGeogCS->GetChild(0)->SetValue( "GCS_New_Zealand_1949" );
             pszUTMPrefix = "NZGD_1949";
@@ -1177,21 +1496,13 @@ OGRErr OGRSpatialReference::morphToESRI()
             NULL, NULL
         };
 
-        GetRoot()->applyRemapper( "PROJCS",
-                                  (char **)apszUnknownMapping+1,
-                                  (char **)apszUnknownMapping+0, 2 );
-        GetRoot()->applyRemapper( "GEOGCS",
-                                  (char **)apszUnknownMapping+1,
-                                  (char **)apszUnknownMapping+0, 2 );
-        GetRoot()->applyRemapper( "DATUM",
-                                  (char **)apszUnknownMapping+1,
-                                  (char **)apszUnknownMapping+0, 2 );
-        GetRoot()->applyRemapper( "SPHEROID",
-                                  (char **)apszUnknownMapping+1,
-                                  (char **)apszUnknownMapping+0, 2 );
-        GetRoot()->applyRemapper( "PRIMEM",
-                                  (char **)apszUnknownMapping+1,
-                                  (char **)apszUnknownMapping+0, 2 );
+        char **apszMap = const_cast<char **>(apszUnknownMapping);
+
+        GetRoot()->applyRemapper("PROJCS", apszMap + 1, apszMap + 0, 2);
+        GetRoot()->applyRemapper("GEOGCS", apszMap + 1, apszMap + 0, 2);
+        GetRoot()->applyRemapper("DATUM", apszMap + 1, apszMap + 0, 2);
+        GetRoot()->applyRemapper("SPHEROID", apszMap + 1, apszMap + 0, 2);
+        GetRoot()->applyRemapper("PRIMEM", apszMap + 1, apszMap + 0, 2);
 
 /* -------------------------------------------------------------------- */
 /*      If the PROJCS name is unset, use the PROJECTION name in         */
@@ -1211,9 +1522,9 @@ OGRErr OGRSpatialReference::morphToESRI()
         }
 
         if( pszProjCSName != NULL
-            && ( EQUAL(pszProjCSName,"unnamed")
-                 || EQUAL(pszProjCSName,"unknown")
-                 || EQUAL(pszProjCSName,"") ) )
+            && ( EQUAL(pszProjCSName, "unnamed")
+                 || EQUAL(pszProjCSName, "unknown")
+                 || EQUAL(pszProjCSName, "") ) )
         {
             if( GetAttrValue( "PROJECTION", 0 ) != NULL )
             {
@@ -1226,10 +1537,10 @@ OGRErr OGRSpatialReference::morphToESRI()
 /*      Prepare very specific PROJCS names for UTM coordinate           */
 /*      systems.                                                        */
 /* -------------------------------------------------------------------- */
-        int bNorth = 0;
-        int nZone  = 0;
+        int bNorth = FALSE;
+        int nZone = 0;
 
-        /* get zone from name first */
+        // Get zone from name first.
         if( pszProjCSName && STARTS_WITH_CI(pszProjCSName, "UTM Zone ") )
         {
             nZone = atoi(pszProjCSName+9);
@@ -1237,17 +1548,19 @@ OGRErr OGRSpatialReference::morphToESRI()
                 bNorth = TRUE;
         }
 
-        /* if can not get from the name, from the parameters */
+        // If can not get from the name, from the parameters.
         if( nZone <= 0 )
             nZone = GetUTMZone( &bNorth );
 
         if( nZone > 0 && pszUTMPrefix )
         {
-            char szUTMName[128];
+            char szUTMName[128] = {};
             if( bNorth )
-                snprintf( szUTMName, sizeof(szUTMName), "%s_UTM_Zone_%dN", pszUTMPrefix, nZone );
+                snprintf( szUTMName, sizeof(szUTMName),
+                          "%s_UTM_Zone_%dN", pszUTMPrefix, nZone );
             else
-                snprintf( szUTMName, sizeof(szUTMName), "%s_UTM_Zone_%dS", pszUTMPrefix, nZone );
+                snprintf( szUTMName, sizeof(szUTMName),
+                          "%s_UTM_Zone_%dS", pszUTMPrefix, nZone );
 
             if( poProjCSNodeChild )
                 poProjCSNodeChild->SetValue( szUTMName );
@@ -1259,7 +1572,7 @@ OGRErr OGRSpatialReference::morphToESRI()
 /*      case.                                                           */
 /* -------------------------------------------------------------------- */
     GetRoot()->applyRemapper( "UNIT",
-                              const_cast<char **>(apszUnitMapping+1),
+                              const_cast<char **>(apszUnitMapping + 1),
                               const_cast<char **>(apszUnitMapping),
                               2 );
 
@@ -1270,7 +1583,7 @@ OGRErr OGRSpatialReference::morphToESRI()
     OGR_SRSNode *poUnit = GetAttrNode( "GEOGCS|UNIT" );
 
     if( poUnit != NULL && poUnit->GetChildCount() >= 2
-        && ABS(GetAngularUnits()-0.0174532925199433) < 0.00000000001 )
+        && std::abs(GetAngularUnits()-0.0174532925199433) < 0.00000000001 )
     {
         poUnit->GetChild(0)->SetValue("Degree");
         poUnit->GetChild(1)->SetValue("0.017453292519943295");
@@ -1282,7 +1595,7 @@ OGRErr OGRSpatialReference::morphToESRI()
     poUnit = GetAttrNode( "PROJCS|UNIT" );
 
     if( poUnit != NULL && poUnit->GetChildCount() >= 2
-        && ABS(GetLinearUnits()- 0.30480060960121924) < 0.000000000000001)
+        && std::abs(GetLinearUnits()- 0.30480060960121924) < 0.000000000000001)
     {
         poUnit->GetChild(0)->SetValue("Foot_US");
         poUnit->GetChild(1)->SetValue("0.30480060960121924");
@@ -1297,17 +1610,17 @@ OGRErr OGRSpatialReference::morphToESRI()
     pszProjection = GetAttrValue("PROJECTION");
     poProjCS = GetAttrNode( "PROJCS" );
 
-    if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
+    if( pszProjection != NULL && EQUAL(pszProjection, "Albers") )
         GetRoot()->applyRemapper(
             "PARAMETER", const_cast<char **>(apszAlbersMapping + 1),
             const_cast<char **>(apszAlbersMapping + 0), 2 );
 
     if( pszProjection != NULL
-        && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
-            EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
-            EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
-            EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
-            EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
+        && (EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC) ||
+            EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
+            EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
+            EQUAL(pszProjection, SRS_PT_SINUSOIDAL) ||
+            EQUAL(pszProjection, SRS_PT_ROBINSON) ) )
         GetRoot()->applyRemapper(
             "PARAMETER", const_cast<char **>(apszECMapping + 1),
             const_cast<char **>(apszECMapping + 0), 2 );
@@ -1318,23 +1631,23 @@ OGRErr OGRSpatialReference::morphToESRI()
         GetRoot()->applyRemapper(
             "PARAMETER",
             const_cast<char **>(apszPolarStereographicMapping + 1),
-            const_cast<char **>(apszPolarStereographicMapping + 0), 2 );
+            const_cast<char **>(apszPolarStereographicMapping + 0), 2);
 
-    if( pszProjection != NULL && EQUAL(pszProjection,"Plate_Carree") )
-        if(FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS ) < 0)
+    if( pszProjection != NULL && EQUAL(pszProjection, "Plate_Carree") )
+        if( FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS ) < 0 )
             GetRoot()->applyRemapper(
                 "PARAMETER",
                 const_cast<char **>(apszPolarStereographicMapping + 1),
-                const_cast<char **>(apszPolarStereographicMapping + 0), 2 );
+                const_cast<char **>(apszPolarStereographicMapping + 0), 2);
 
 /* -------------------------------------------------------------------- */
 /*      ESRI's Equidistant_Cylindrical does not support the             */
 /*      latitude_of_origin keyword.                                     */
 /* -------------------------------------------------------------------- */
     if( pszProjection != NULL
-        && EQUAL(pszProjection,"Equidistant_Cylindrical") )
+        && EQUAL(pszProjection, "Equidistant_Cylindrical") )
     {
-        if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) != 0.0 )
+        if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0) != 0.0 )
         {
             CPLDebug( "OGR_ESRI",
                       "Equirectangular with non-zero latitude of origin - "
@@ -1349,28 +1662,30 @@ OGRErr OGRSpatialReference::morphToESRI()
         }
     }
 
-    /* See #4861 */
-    if( pszProjection != NULL && EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
+    // See #4861.
+    if( pszProjection != NULL && EQUAL(pszProjection, SRS_PT_MERCATOR_2SP) )
     {
         SetNode( "PROJCS|PROJECTION", "Mercator" );
     }
 
-    /* See #4861 */
-    else if( pszProjection != NULL && EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
+    // See #4861.
+    else if( pszProjection != NULL &&
+             EQUAL(pszProjection, SRS_PT_MERCATOR_1SP) )
     {
         SetNode( "PROJCS|PROJECTION", "Mercator" );
 
         const double dfK0 = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
 
-        const double dfInvFlattening = GetInvFlattening();;
+        const double dfInvFlattening = GetInvFlattening();
         double e2 = 0.0;
         if( dfInvFlattening != 0.0 )
         {
-            double f = 1 / dfInvFlattening;
-            e2 = 2 *f - f*f;
+            const double f = 1.0 / dfInvFlattening;
+            e2 = 2 * f - f * f;
         }
         const double dfStdP1Lat =
-            acos( sqrt( (1 - e2) / ((1 / (dfK0 * dfK0)) - e2)) ) / M_PI * 180.0;
+            acos( sqrt( (1.0 - e2) / ((1.0 / (dfK0 * dfK0)) - e2)) ) /
+            M_PI * 180.0;
         if( poProjCS )
         {
             const int iScaleFactorChild =
@@ -1401,10 +1716,10 @@ OGRErr OGRSpatialReference::morphToESRI()
         poSpheroidChild->SetValue( pszNewValue );
         CPLFree( pszNewValue );
 
-        GetRoot()->applyRemapper( "SPHEROID",
-                                  const_cast<char **>(apszSpheroidMapping+0),
-                                  const_cast<char **>(apszSpheroidMapping+1),
-                                  2 );
+        GetRoot()->applyRemapper("SPHEROID",
+                                 const_cast<char **>(apszSpheroidMapping + 0),
+                                 const_cast<char **>(apszSpheroidMapping + 1),
+                                 2);
     }
 
     if( poSpheroid != NULL )
@@ -1449,12 +1764,12 @@ OGRErr OGRSpatialReference::morphToESRI()
 /*                        final check names                             */
 /* -------------------------------------------------------------------- */
     if( poProjCSNodeChild )
-      pszProjCSName = poProjCSNodeChild->GetValue();
+        pszProjCSName = poProjCSNodeChild->GetValue();
 
     if( pszProjCSName )
     {
-      pszGcsName = GetAttrValue( "GEOGCS" );
-      if(pszGcsName && !STARTS_WITH_CI(pszGcsName, "GCS_") )
+      const char *pszGcsName = GetAttrValue( "GEOGCS" );
+      if( pszGcsName && !STARTS_WITH_CI(pszGcsName, "GCS_") )
       {
         char* newGcsName = static_cast<char *>(
             CPLMalloc(strlen(pszGcsName) + 5) );
@@ -1468,11 +1783,11 @@ OGRErr OGRSpatialReference::morphToESRI()
 
       // Specific processing and remapping
       pszProjection = GetAttrValue("PROJECTION");
-      if(pszProjection)
+      if( pszProjection )
       {
-        if(EQUAL(pszProjection,"Lambert_Conformal_Conic"))
+        if( EQUAL(pszProjection, "Lambert_Conformal_Conic") )
         {
-          if(FindProjParm( SRS_PP_STANDARD_PARALLEL_2, poProjCS ) < 0 )
+          if( FindProjParm( SRS_PP_STANDARD_PARALLEL_2, poProjCS ) < 0 )
           {
             int iChild = FindProjParm( SRS_PP_LATITUDE_OF_ORIGIN, poProjCS );
             int iChild1 = FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS );
@@ -1491,26 +1806,36 @@ OGRErr OGRSpatialReference::morphToESRI()
           }
         }
 
-        if(EQUAL(pszProjection,"Plate_Carree"))
+        if( EQUAL(pszProjection, "Plate_Carree") )
         {
           int iChild = FindProjParm( SRS_PP_STANDARD_PARALLEL_1, poProjCS );
-          if(iChild < 0)
+          if( iChild < 0 )
             iChild = FindProjParm( SRS_PP_PSEUDO_STD_PARALLEL_1, poProjCS );
 
-          if(iChild >= 0)
+          if( iChild >= 0 )
           {
             const OGR_SRSNode *poParameter = poProjCS->GetChild(iChild);
-            if(!EQUAL(poParameter->GetChild(1)->GetValue(), "0.0") && !EQUAL(poParameter->GetChild(1)->GetValue(), "0"))
+            if( !EQUAL(poParameter->GetChild(1)->GetValue(), "0.0") &&
+                !EQUAL(poParameter->GetChild(1)->GetValue(), "0") )
             {
               SetNode( "PROJCS|PROJECTION", "Equidistant_Cylindrical" );
               pszProjection = GetAttrValue("PROJECTION");
             }
           }
         }
-        DeleteParamBasedOnPrjName( this, pszProjection, (char **)apszDeleteParametersBasedOnProjection);
-        AddParamBasedOnPrjName( this, pszProjection, (char **)apszAddParametersBasedOnProjection);
-        RemapPValuesBasedOnProjCSAndPName( this, pszProjection, (char **)apszParamValueMapping);
-        RemapPNamesBasedOnProjCSAndPName( this, pszProjection, (char **)apszParamNameMapping);
+
+        DeleteParamBasedOnPrjName(
+            this, pszProjection,
+            const_cast<char **>(apszDeleteParametersBasedOnProjection));
+        AddParamBasedOnPrjName(
+            this, pszProjection,
+            const_cast<char **>(apszAddParametersBasedOnProjection));
+        RemapPValuesBasedOnProjCSAndPName(
+            this, pszProjection,
+            const_cast<char **>(apszParamValueMapping));
+        RemapPNamesBasedOnProjCSAndPName(
+            this, pszProjection,
+            const_cast<char **>(apszParamNameMapping));
       }
     }
 
@@ -1524,7 +1849,8 @@ OGRErr OGRSpatialReference::morphToESRI()
 /**
  * \brief Convert in place to ESRI WKT format.
  *
- * This function is the same as the C++ method OGRSpatialReference::morphToESRI()
+ * This function is the same as the C++ method
+ * OGRSpatialReference::morphToESRI().
  */
 OGRErr OSRMorphToESRI( OGRSpatialReferenceH hSRS )
 
@@ -1639,7 +1965,7 @@ OGRErr OGRSpatialReference::morphFromESRI()
     const char *pszProjection = GetAttrValue("PROJECTION");
 
     if( pszProjection != NULL
-        && EQUAL(pszProjection,"Lambert_Conformal_Conic") )
+        && EQUAL(pszProjection, "Lambert_Conformal_Conic") )
     {
         if( GetProjParm( SRS_PP_STANDARD_PARALLEL_1, 1000.0 ) != 1000.0
             && GetProjParm( SRS_PP_STANDARD_PARALLEL_2, 1000.0 ) != 1000.0 )
@@ -1665,7 +1991,7 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /*      I guess.                                                        */
 /* -------------------------------------------------------------------- */
     if( pszProjection != NULL
-        && EQUAL(pszProjection,"Hotine_Oblique_Mercator_Azimuth_Center") )
+        && EQUAL(pszProjection, "Hotine_Oblique_Mercator_Azimuth_Center") )
     {
         SetProjParm( SRS_PP_RECTIFIED_GRID_ANGLE ,
                      GetProjParm( SRS_PP_AZIMUTH, 0.0 ) );
@@ -1675,22 +2001,22 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /* -------------------------------------------------------------------- */
 /*      Remap Albers, Mercator and Polar Stereographic parameters.      */
 /* -------------------------------------------------------------------- */
-    if( pszProjection != NULL && EQUAL(pszProjection,"Albers") )
+    if( pszProjection != NULL && EQUAL(pszProjection, "Albers") )
         GetRoot()->applyRemapper(
             "PARAMETER", (char **)apszAlbersMapping + 0,
             (char **)apszAlbersMapping + 1, 2 );
 
     if( pszProjection != NULL
-        && (EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) ||
-            EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
-            EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
-            EQUAL(pszProjection,SRS_PT_SINUSOIDAL) ||
-            EQUAL(pszProjection,SRS_PT_ROBINSON) ) )
+        && (EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC) ||
+            EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) ||
+            EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT) ||
+            EQUAL(pszProjection, SRS_PT_SINUSOIDAL) ||
+            EQUAL(pszProjection, SRS_PT_ROBINSON) ) )
         GetRoot()->applyRemapper(
             "PARAMETER", const_cast<char **>(apszECMapping + 0),
             const_cast<char **>(apszECMapping + 1), 2 );
 
-    if( pszProjection != NULL && EQUAL(pszProjection,"Orthographic") )
+    if( pszProjection != NULL && EQUAL(pszProjection, "Orthographic") )
         GetRoot()->applyRemapper(
             "PARAMETER", const_cast<char **>(apszOrthographicMapping + 0),
             const_cast<char **>(apszOrthographicMapping + 1), 2 );
@@ -1718,7 +2044,7 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /*      Remap Double_Stereographic to Oblique_Stereographic.            */
 /* -------------------------------------------------------------------- */
     if( pszProjection != NULL
-        && EQUAL(pszProjection,"Double_Stereographic") )
+        && EQUAL(pszProjection, "Double_Stereographic") )
     {
         SetNode( "PROJCS|PROJECTION", SRS_PT_OBLIQUE_STEREOGRAPHIC );
         pszProjection = GetAttrValue("PROJECTION");
@@ -1728,8 +2054,9 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /*      Remap Equidistant_Cylindrical parameter. It is same as          */
 /*      Stereographic                                                   */
 /* -------------------------------------------------------------------- */
-#ifdef notdef
-    if( pszProjection != NULL && EQUAL(pszProjection,"Equidistant_Cylindrical") )
+#if 0
+    if( pszProjection != NULL &&
+        EQUAL(pszProjection, "Equidistant_Cylindrical") )
         GetRoot()->applyRemapper(
             "PARAMETER",
             const_cast<char **>(apszPolarStereographicMapping + 0),
@@ -1739,9 +2066,9 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /* -------------------------------------------------------------------- */
 /*      Remap Mercator to Mercator_2SP (#4861)                          */
 /* -------------------------------------------------------------------- */
-    if( pszProjection != NULL && EQUAL(pszProjection,"Mercator") )
+    if( pszProjection != NULL && EQUAL(pszProjection, "Mercator") )
     {
-        /* Such as found in #6134 */
+        // Such as found in #6134.
         if( GetAttrValue("PROJCS") != NULL &&
             EQUAL(GetAttrValue("PROJCS"), "WGS_84_Pseudo_Mercator"))
         {
@@ -1753,10 +2080,8 @@ OGRErr OGRSpatialReference::morphFromESRI()
         pszProjection = GetAttrValue("PROJECTION");
     }
 
-    /*
-    ** Handle the value of Central_Parallel -> latitude_of_center.
-    ** See ticket #3191.  Other mappings probably need to be added.
-    */
+    // Handle the value of Central_Parallel -> latitude_of_center.
+    // See ticket #3191.  Other mappings probably need to be added.
     if( pszProjection != NULL &&
         ( EQUAL( pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP ) ||
           EQUAL( pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP ) ) )
@@ -1773,11 +2098,13 @@ OGRErr OGRSpatialReference::morphFromESRI()
         if( EQUAL( pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP ) )
         {
             OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-            int iSP1Child = FindProjParm( "Standard_Parallel_1", poPROJCS );
-            int iLatOrigChild = FindProjParm( "Latitude_Of_Origin", poPROJCS );
+            const int iSP1Child =
+                FindProjParm( "Standard_Parallel_1", poPROJCS );
+            const int iLatOrigChild =
+                FindProjParm( "Latitude_Of_Origin", poPROJCS );
             if( iSP1Child != -1 && iLatOrigChild != 1 )
             {
-                /* Do a sanity check before removing Standard_Parallel_1 */
+                // Do a sanity check before removing Standard_Parallel_1.
                 if( EQUAL(poPROJCS->GetChild(iSP1Child)->GetValue(),
                           poPROJCS->GetChild(iLatOrigChild)->GetValue()) )
                 {
@@ -1826,59 +2153,65 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /* -------------------------------------------------------------------- */
 /*      Fix TOWGS84, DATUM or GEOGCS                                    */
 /* -------------------------------------------------------------------- */
-    /* TODO test more ESRI WKT; also add PROJCS */
+    // TODO test more ESRI WKT; also add PROJCS.
 
-    // Check GDAL_FIX_ESRI_WKT config option (default=NO); if YES, set to DATUM
+    // Check GDAL_FIX_ESRI_WKT config option (default=NO); if YES, set to DATUM.
     const char *pszFixWktConfig=CPLGetConfigOption( "GDAL_FIX_ESRI_WKT", "NO" );
-    if ( EQUAL(pszFixWktConfig,"YES") )
+    if( EQUAL(pszFixWktConfig, "YES") )
         pszFixWktConfig = "DATUM";
 
-    if( !EQUAL(pszFixWktConfig, "NO") && poDatum != NULL && pszDatumOrig != NULL )
+    if( !EQUAL(pszFixWktConfig, "NO") &&
+        poDatum != NULL && pszDatumOrig != NULL )
     {
         CPLDebug( "OGR_ESRI",
                   "morphFromESRI() looking for missing TOWGS84, datum=%s, "
                   "config=%s",
                   pszDatumOrig, pszFixWktConfig );
 
-        /* Special case for WGS84 and other common GCS? */
-
+        // Special case for WGS84 and other common GCS?
         for( int i = 0; DMGetESRIName(i) != NULL; i++ )
         {
-            /* we found the ESRI datum name in the map */
-            if( EQUAL(DMGetESRIName(i),pszDatumOrig) )
+            // Found the ESRI datum name in the map.
+            if( EQUAL(DMGetESRIName(i), pszDatumOrig) )
             {
                 const char *pszFilename = NULL;
                 char **papszRecord = NULL;
 
-                /* look for GEOGCS corresponding to this datum */
+                // Look for GEOGCS corresponding to this datum.
                 pszFilename = CSVFilename("gcs.csv");
                 papszRecord = CSVScanFileByName( pszFilename, "DATUM_CODE",
                                                  DMGetEPSGCode(i), CC_Integer );
-                if ( papszRecord != NULL )
+                if( papszRecord != NULL )
                 {
-                    /* skip the SIRGAS-Chile record for Peru96 related SRS */
-                    if( bPeru96Datum && EQUAL(CSLGetField( papszRecord,
-                                    CSVGetFileFieldId(pszFilename,"DATUM_NAME")), "SIRGAS-Chile") )
+                    // Skip the SIRGAS-Chile record for Peru96 related SRS.
+                    if( bPeru96Datum &&
+                        EQUAL(CSLGetField(papszRecord,
+                                          CSVGetFileFieldId(pszFilename,
+                                                            "DATUM_NAME")),
+                              "SIRGAS-Chile") )
                         continue;
 
-                    /* make sure we got a valid EPSG code and it is not DEPRECATED */
-                    int nGeogCS = atoi( CSLGetField( papszRecord,
-                                                     CSVGetFileFieldId(pszFilename,"COORD_REF_SYS_CODE")) );
-                    // int bDeprecated = atoi( CSLGetField( papszRecord,
-                    //                                      CSVGetFileFieldId(pszFilename,"DEPRECATED")) );
+                    // Ensure we got a valid EPSG code and it is not DEPRECATED.
+                    const int nGeogCS = atoi(
+                        CSLGetField(papszRecord,
+                                    CSVGetFileFieldId(pszFilename,
+                                                      "COORD_REF_SYS_CODE")));
+                    // int bDeprecated =
+                    //     atoi( CSLGetField( papszRecord,
+                    //                        CSVGetFileFieldId(pszFilename,
+                    //                        "DEPRECATED")) );
 
                     CPLDebug( "OGR_ESRI", "morphFromESRI() got GEOGCS node #%d",
                               nGeogCS );
 
-                    // if ( nGeogCS >= 1 && bDeprecated == 0 )
-                    if ( nGeogCS >= 1 )
+                    // if( nGeogCS >= 1 && bDeprecated == 0 )
+                    if( nGeogCS >= 1 )
                     {
                         OGRSpatialReference oSRSTemp;
-                        if ( oSRSTemp.importFromEPSG( nGeogCS ) == OGRERR_NONE )
+                        if( oSRSTemp.importFromEPSG( nGeogCS ) == OGRERR_NONE )
                         {
                             // Clone of GEOGCS and strip CT parms for testing.
                             char *pszOtherValue = NULL;
-                            double dfThisValue, dfOtherValue;
                             OGR_SRSNode *poNode = NULL;
 
                             OGRSpatialReference *poSRSTemp2 =
@@ -1887,112 +2220,132 @@ OGRErr OGRSpatialReference::morphFromESRI()
                             bool bIsSame =
                                 CPL_TO_BOOL(IsSameGeogCS( poSRSTemp2 ));
                             exportToWkt ( &pszOtherValue );
-                            CPLDebug( "OGR_ESRI",
-                                      "morphFromESRI() got SRS %s, matching: %d",
-                                      pszOtherValue, static_cast<int>(bIsSame) );
+                            CPLDebug("OGR_ESRI",
+                                     "morphFromESRI() got SRS %s, matching: %d",
+                                     pszOtherValue, static_cast<int>(bIsSame));
                             CPLFree( pszOtherValue );
                             delete poSRSTemp2;
 
                             // Clone GEOGCS from original if they match and if
                             // allowed.
-                            if ( EQUAL(pszFixWktConfig,"GEOGCS")
+                            if( EQUAL(pszFixWktConfig, "GEOGCS")
                                  && bIsSame )
                             {
-                                this->CopyGeogCSFrom( &oSRSTemp );
+                                CopyGeogCSFrom( &oSRSTemp );
                                 CPLDebug( "OGR_ESRI",
                                           "morphFromESRI() cloned GEOGCS "
                                           "from EPSG:%d",
                                           nGeogCS );
-                                /* exit loop */
+                                // Exit loop.
                                 break;
                             }
-                            /* else try to copy only DATUM or TOWGS84
-                               we got here either because of config option or
-                               GEOGCS are not strictly equal */
-                            else if ( EQUAL(pszFixWktConfig,"GEOGCS") ||
-                                      EQUAL(pszFixWktConfig,"DATUM") ||
-                                      EQUAL(pszFixWktConfig,"TOWGS84") )
+                            // Else try to copy only DATUM or TOWGS84.  We got
+                            // here either because of config option or GEOGCS
+                            // are not strictly equal.
+                            else if( EQUAL(pszFixWktConfig, "GEOGCS") ||
+                                     EQUAL(pszFixWktConfig, "DATUM") ||
+                                     EQUAL(pszFixWktConfig, "TOWGS84") )
                             {
-                                /* test for matching SPHEROID, because there can be 2 datums with same ESRI name
-                                   but different spheroids (e.g. EPSG:4618 and EPSG:4291) - see bug #4345 */
-                                /* instead of testing for matching SPHEROID name (which can be error-prone), test
-                                   for matching parameters (semi-major and inverse flattening ) - see bug #4673 */
+                                // Test for matching SPHEROID, because there can
+                                // be 2 datums with same ESRI name but different
+                                // spheroids (e.g. EPSG:4618 and EPSG:4291).
+                                // See bug #4345.
+
+                                // Instead of testing for matching SPHEROID name
+                                // (which can be error-prone), test for matching
+                                // parameters (semi-major and inverse
+                                // flattening).  See bug #4673
                                 bIsSame = true;
-                                dfThisValue = this->GetSemiMajor();
-                                dfOtherValue = oSRSTemp.GetSemiMajor();
-                                if ( ABS( dfThisValue - dfOtherValue ) > 0.01 )
+                                double dfThisValue = GetSemiMajor();
+                                double dfOtherValue = oSRSTemp.GetSemiMajor();
+                                if( std::abs( dfThisValue -
+                                              dfOtherValue ) > 0.01 )
                                     bIsSame = false;
                                 CPLDebug( "OGR_ESRI",
                                           "morphFromESRI() SemiMajor: "
                                           "this = %.15g other = %.15g",
                                           dfThisValue, dfOtherValue );
-                                dfThisValue = this->GetInvFlattening();
+                                dfThisValue = GetInvFlattening();
                                 dfOtherValue = oSRSTemp.GetInvFlattening();
-                                if ( ABS( dfThisValue - dfOtherValue ) > 0.0001 )
+                                if( std::abs( dfThisValue -
+                                              dfOtherValue ) > 0.0001 )
                                     bIsSame = false;
                                 CPLDebug( "OGR_ESRI",
                                           "morphFromESRI() InvFlattening: "
                                           "this = %g other = %g",
                                           dfThisValue, dfOtherValue );
 
-                                if ( bIsSame )
+                                if( bIsSame )
                                 {
-                                    /* test for matching PRIMEM, because there can be 2 datums with same ESRI name
-                                       but different prime meridian (e.g. EPSG:4218 and EPSG:4802)  - see bug #4378 */
-                                    /* instead of testing for matching PRIMEM name (which can be error-prone), test
-                                       for matching value - see bug #4673 */
-                                    dfThisValue = this->GetPrimeMeridian();
+                                    // Test for matching PRIMEM, because there
+                                    // can be 2 datums with same ESRI name but
+                                    // different prime meridian (e.g. EPSG:4218
+                                    // and EPSG:4802) - see bug #4378.
+
+                                    // Instead of testing for matching PRIMEM
+                                    // name (which can be error-prone), test for
+                                    // matching value - see bug #4673.
+                                    dfThisValue = GetPrimeMeridian();
                                     dfOtherValue = oSRSTemp.GetPrimeMeridian();
                                     CPLDebug( "OGR_ESRI",
                                               "morphFromESRI() PRIMEM: "
                                               "this = %.15g other = %.15g",
                                               dfThisValue, dfOtherValue );
-                                    if ( ABS( dfThisValue - dfOtherValue )
-                                         > 0.0001 )
+                                    if( std::abs( dfThisValue - dfOtherValue )
+                                        > 0.0001 )
                                         bIsSame = false;
                                 }
 
-                                /* found a matching spheroid */
-                                if ( bIsSame )
+                                // Found a matching spheroid.
+                                if( bIsSame )
                                 {
-                                    /* clone DATUM */
-                                    if ( EQUAL(pszFixWktConfig,"GEOGCS") ||
-                                         EQUAL(pszFixWktConfig,"DATUM")  )
+                                    // Clone DATUM.
+                                    if( EQUAL(pszFixWktConfig, "GEOGCS") ||
+                                        EQUAL(pszFixWktConfig, "DATUM") )
                                     {
-                                        OGR_SRSNode *poGeogCS = this->GetAttrNode( "GEOGCS" );
+                                        OGR_SRSNode *poGeogCS =
+                                            GetAttrNode("GEOGCS");
                                         const OGR_SRSNode *poDatumOther =
                                             oSRSTemp.GetAttrNode( "DATUM" );
-                                        if ( poGeogCS && poDatumOther )
+                                        if( poGeogCS && poDatumOther )
                                         {
-                                            /* make sure we preserve the position of the DATUM node */
+                                            // Make sure we preserve the
+                                            // position of the DATUM node.
                                             const int nPos =
                                                 poGeogCS->FindChild( "DATUM" );
-                                            if ( nPos >= 0 )
+                                            if( nPos >= 0 )
                                             {
                                                 poGeogCS->DestroyChild( nPos );
                                                 poGeogCS->InsertChild(
                                                     poDatumOther->Clone(),
                                                     nPos );
-                                                CPLDebug( "OGR_ESRI",
-                                                          "morphFromESRI() cloned DATUM from EPSG:%d",
-                                                          nGeogCS );
+                                                CPLDebug(
+                                                    "OGR_ESRI",
+                                                    "morphFromESRI() cloned "
+                                                    "DATUM from EPSG:%d",
+                                                    nGeogCS );
                                             }
                                         }
                                     }
-                                    /* just copy TOWGS84 */
-                                    else if ( EQUAL(pszFixWktConfig,"TOWGS84") )
+                                    // Just copy TOWGS84.
+                                    else if( EQUAL(pszFixWktConfig, "TOWGS84") )
                                     {
-                                        poNode=oSRSTemp.GetAttrNode( "DATUM|TOWGS84" );
-                                        if ( poNode )
+                                        poNode =
+                                            oSRSTemp.GetAttrNode(
+                                                "DATUM|TOWGS84");
+                                        if( poNode )
                                         {
                                             poNode=poNode->Clone();
-                                            GetAttrNode( "DATUM" )->AddChild( poNode );
-                                            CPLDebug( "OGR_ESRI",
-                                                      "morphFromESRI() found missing TOWGS84 from EPSG:%d",
-                                                      nGeogCS );
+                                            GetAttrNode("DATUM")->
+                                                AddChild(poNode);
+                                            CPLDebug(
+                                                "OGR_ESRI",
+                                                "morphFromESRI() found missing "
+                                                "TOWGS84 from EPSG:%d",
+                                                nGeogCS );
                                         }
                                     }
-                                    /* exit loop */
+                                    // Exit loop.
                                     break;
                                 }
                             }
@@ -2016,7 +2369,8 @@ OGRErr OGRSpatialReference::morphFromESRI()
 /**
  * \brief Convert in place from ESRI WKT format.
  *
- * This function is the same as the C++ method OGRSpatialReference::morphFromESRI()
+ * This function is the same as the C++ method
+ * OGRSpatialReference::morphFromESRI().
  */
 OGRErr OSRMorphFromESRI( OGRSpatialReferenceH hSRS )
 
@@ -2027,372 +2381,54 @@ OGRErr OSRMorphFromESRI( OGRSpatialReferenceH hSRS )
 }
 
 /************************************************************************/
-/*                           SetNewName()                               */
+/*                       FindCodeFromDict()                             */
 /*                                                                      */
-/*      Set an esri name                                                */
+/*      Find the code from a dict file.                                 */
 /************************************************************************/
-void SetNewName( OGRSpatialReference* pOgr, const char* keyName,
-                 const char* newName )
+static int FindCodeFromDict( const char* pszDictFile, const char* CSName,
+                             char* code )
 {
-    OGR_SRSNode *poNode = pOgr->GetAttrNode( keyName );
-    OGR_SRSNode *poNodeChild = NULL;
-    if(poNode)
-        poNodeChild = poNode->GetChild(0);
-    if( poNodeChild)
-        poNodeChild->SetValue( newName);
-}
+/* -------------------------------------------------------------------- */
+/*      Find and open file.                                             */
+/* -------------------------------------------------------------------- */
+    const char *pszFilename = CPLFindFile( "gdal", pszDictFile );
+    if( pszFilename == NULL )
+        return OGRERR_UNSUPPORTED_SRS;
 
-/************************************************************************/
-/*                           RemapImgWGSProjcsName()                    */
-/*                                                                      */
-/*      Convert Img projcs names to ESRI style                          */
-/************************************************************************/
-int RemapImgWGSProjcsName( OGRSpatialReference* pOgr, const char* pszProjCSName,
-                           const char* pszProgCSName )
-{
-    if(EQUAL(pszProgCSName, "WGS_1972") || EQUAL(pszProgCSName, "WGS_1984") )
-    {
-        char* newName = static_cast<char *>(
-            CPLMalloc(strlen(pszProjCSName) + 10) );
-        snprintf( newName, strlen(pszProjCSName) + 10, "%s_", pszProgCSName );
-        strcat(newName, pszProjCSName);
-        SetNewName( pOgr, "PROJCS", newName );
-        CPLFree( newName );
-        return 1;
-    }
-    return -1;
-}
+    VSILFILE *fp = VSIFOpenL( pszFilename, "rb" );
+    if( fp == NULL )
+        return OGRERR_UNSUPPORTED_SRS;
 
-/************************************************************************/
-/*                           RemapImgUTMNames()                         */
-/*                                                                      */
-/*      Convert Img UTM names to ESRI style                             */
-/************************************************************************/
+/* -------------------------------------------------------------------- */
+/*      Process lines.                                                  */
+/* -------------------------------------------------------------------- */
+    OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
+    const char *pszLine = NULL;
 
-int RemapImgUTMNames( OGRSpatialReference* pOgr, const char* pszProjCSName,
-                      const char* pszProgCSName,
-                      char **mappingTable )
-{
-    int iIndex = -1;
-    for( int i = 0; mappingTable[i] != NULL; i += 5 )
+    while( (pszLine = CPLReadLineL(fp)) != NULL )
     {
-        if( EQUAL(pszProjCSName, mappingTable[i]) )
+        if( pszLine[0] == '#' )
+            continue;
+
+        if( strstr(pszLine, CSName) )
         {
-            int j = i;
-            while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
+            const char* pComma = strchr(pszLine, ',');
+            if( pComma )
             {
-                if( EQUAL(pszProgCSName, mappingTable[j+1]) )
-                {
-                    iIndex = j;
-                    break;
-                }
-                j += 5;
-            }
-            if (iIndex >= 0)
-                break;
-        }
-    }
-    if(iIndex >= 0)
-    {
-        OGR_SRSNode *poNode = pOgr->GetAttrNode( "PROJCS" );
-        OGR_SRSNode *poNodeChild = NULL;
-        if(poNode)
-            poNodeChild = poNode->GetChild(0);
-        if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
-            poNodeChild->SetValue( mappingTable[iIndex+2]);
-
-        poNode = pOgr->GetAttrNode( "GEOGCS" );
-        poNodeChild = NULL;
-        if(poNode)
-            poNodeChild = poNode->GetChild(0);
-        if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
-            poNodeChild->SetValue( mappingTable[iIndex+3]);
-
-        poNode = pOgr->GetAttrNode( "DATUM" );
-        poNodeChild = NULL;
-        if(poNode)
-            poNodeChild = poNode->GetChild(0);
-        if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
-            poNodeChild->SetValue( mappingTable[iIndex+4]);
-    }
-    return iIndex;
-}
-
-/************************************************************************/
-/*                           RemapNameBasedOnKeyName()                  */
-/*                                                                      */
-/*      Convert a name to ESRI style name                               */
-/************************************************************************/
-
-int RemapNameBasedOnKeyName( OGRSpatialReference* pOgr, const char* pszName,
-                             const char* pszkeyName,
-                             char **mappingTable )
-{
-    int iIndex = -1;
-    for( int i = 0; mappingTable[i] != NULL; i += 2 )
-    {
-        if( EQUAL(pszName, mappingTable[i]) )
-        {
-            iIndex = i;
-            break;
-        }
-    }
-    if(iIndex >= 0)
-    {
-        OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyName );
-        OGR_SRSNode *poNodeChild = NULL;
-        if(poNode)
-            poNodeChild = poNode->GetChild(0);
-        if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
-            poNodeChild->SetValue( mappingTable[iIndex+1]);
-    }
-    return iIndex;
-}
-
-/************************************************************************/
-/*                     RemapNamesBasedOnTwo()                           */
-/*                                                                      */
-/*      Convert a name to ESRI style name                               */
-/************************************************************************/
-
-int RemapNamesBasedOnTwo( OGRSpatialReference* pOgr, const char* name1,
-                          const char* name2,
-                          char **mappingTable, int nTableStepSize,
-                          char** pszkeyNames, long nKeys )
-{
-    int iIndex = -1;
-    for( int i = 0; mappingTable[i] != NULL; i += nTableStepSize )
-    {
-        const size_t n = strlen(name1);
-        const size_t n1 = strlen(mappingTable[i]);
-        if( EQUALN(name1, mappingTable[i], n1<=n? n1 : n) )
-        {
-            int j = i;
-            while(mappingTable[j] != NULL && EQUAL(mappingTable[i], mappingTable[j]))
-            {
-                if( EQUALN(name2, mappingTable[j+1], strlen(mappingTable[j+1])) )
-                {
-                    iIndex = j;
-                    break;
-                }
-                j += 3;
-            }
-            if (iIndex >= 0)
-                break;
-        }
-    }
-    if(iIndex >= 0)
-    {
-        for( int i = 0; i < nKeys; i ++ )
-        {
-            OGR_SRSNode *poNode = pOgr->GetAttrNode( pszkeyNames[i] );
-            OGR_SRSNode *poNodeChild = NULL;
-            if(poNode)
-                poNodeChild = poNode->GetChild(0);
-            if( poNodeChild && strlen(poNodeChild->GetValue()) > 0 )
-                poNodeChild->SetValue( mappingTable[iIndex+i+2]);
-        }
-
-    }
-    return iIndex;
-}
-
-/************************************************************************/
-/*                RemapPValuesBasedOnProjCSAndPName()                   */
-/*                                                                      */
-/*      Convert a parameters to ESRI style name                         */
-/************************************************************************/
-
-int RemapPValuesBasedOnProjCSAndPName( OGRSpatialReference* pOgr,
-                                       const char* pszProgCSName,
-                                       char **mappingTable )
-{
-    int ret = 0;
-    OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
-    for( int i = 0; mappingTable[i] != NULL; i += 4 )
-    {
-        while( mappingTable[i] != NULL &&
-               EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
-        {
-            const char* pszParamName = mappingTable[i+1];
-            const char* pszParamValue = mappingTable[i+2];
-            for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
-            {
-                OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
-
-                if( EQUAL(poParm->GetValue(),"PARAMETER")
-                    && poParm->GetChildCount() == 2
-                    && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName)
-                    && EQUALN(poParm->GetChild(1)->GetValue(),pszParamValue, strlen(pszParamValue) ) )
-                {
-                    poParm->GetChild(1)->SetValue( mappingTable[i+3] );
-                    break;
-                }
+                strncpy( code, pszLine, pComma - pszLine);
+                code[pComma - pszLine] = '\0';
+                eErr = OGRERR_NONE;
             }
-            ret ++;
-            i += 4;
-        }
-        if (ret > 0)
             break;
-    }
-    return ret;
-}
-
-/************************************************************************/
-/*                  RemapPNamesBasedOnProjCSAndPName()                  */
-/*                                                                      */
-/*      Convert a parameters to ESRI style name                         */
-/************************************************************************/
-
-int RemapPNamesBasedOnProjCSAndPName( OGRSpatialReference* pOgr,
-                                      const char* pszProgCSName,
-                                      char **mappingTable )
-{
-  int ret = 0;
-  OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
-  for( int i = 0; mappingTable[i] != NULL; i += 3 )
-  {
-    while( mappingTable[i] != NULL &&
-           EQUALN(pszProgCSName, mappingTable[i], strlen(mappingTable[i])) )
-    {
-      const char* pszParamName = mappingTable[i+1];
-      for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
-      {
-          OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
-
-          if( EQUAL(poParm->GetValue(),"PARAMETER")
-              && poParm->GetChildCount() == 2
-              && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
-          {
-              poParm->GetChild(0)->SetValue( mappingTable[i+2] );
-              break;
-          }
-      }
-      ret ++;
-      i += 3;
-    }
-    if (ret > 0)
-      break;
-  }
-  return ret;
-}
-
-/************************************************************************/
-/*                        DeleteParamBasedOnPrjName                     */
-/*                                                                      */
-/*      Delete non-ESRI parameters                                      */
-/************************************************************************/
-int DeleteParamBasedOnPrjName( OGRSpatialReference* pOgr,
-                               const char* pszProjectionName,
-                               char **mappingTable )
-{
-    int ret = -1;
-    for( int i = 0; mappingTable[i] != NULL; i += 2 )
-    {
-        if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
-        {
-            OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
-            const char* pszParamName = mappingTable[i+1];
-            int iIndex = -1;
-            for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
-            {
-                OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
-
-                if( EQUAL(poParm->GetValue(),"PARAMETER")
-                    && poParm->GetChildCount() == 2
-                    && EQUAL(poParm->GetChild(0)->GetValue(),pszParamName) )
-                {
-                    iIndex = iChild;
-                    break;
-                }
-            }
-            if(iIndex >= 0)
-            {
-                poPROJCS->DestroyChild( iIndex );
-                ret ++;
-            }
         }
     }
-    return ret;
-}
-/************************************************************************/
-/*                          AddParamBasedOnPrjName()                    */
-/*                                                                      */
-/*      Add ESRI style parameters                                       */
-/************************************************************************/
-int AddParamBasedOnPrjName( OGRSpatialReference* pOgr, const char* pszProjectionName,
-                            char **mappingTable )
-{
-    int ret = -1;
-    OGR_SRSNode *poPROJCS = pOgr->GetAttrNode( "PROJCS" );
-    for( int i = 0; mappingTable[i] != NULL; i += 3 )
-    {
-        if( EQUALN(pszProjectionName, mappingTable[i], strlen(mappingTable[i])) )
-        {
-            bool exist = false;
-            for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
-            {
-                OGR_SRSNode *poParm = poPROJCS->GetChild( iChild );
 
-                if( EQUAL(poParm->GetValue(),"PARAMETER")
-                    && poParm->GetChildCount() == 2
-                    && EQUAL(poParm->GetChild(0)->GetValue(),mappingTable[i+1]) )
-                    exist = true;
-            }
-            if( !exist )
-            {
-                OGR_SRSNode *poParm = new OGR_SRSNode( "PARAMETER" );
-                poParm->AddChild( new OGR_SRSNode( mappingTable[i+1] ) );
-                poParm->AddChild( new OGR_SRSNode( mappingTable[i+2] ) );
-                poPROJCS->AddChild( poParm );
-                ret ++;
-            }
-        }
-    }
-    return ret;
-}
-
-/************************************************************************/
-/*                                   RemapGeogCSName()                  */
-/*                                                                      */
-/*      Convert names to ESRI style                                     */
-/************************************************************************/
-int RemapGeogCSName( OGRSpatialReference* pOgr, const char *pszGeogCSName )
-{
-    static const char * const keyNamesG[] = {
-        "GEOGCS"};
-    int ret = -1;
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    VSIFCloseL( fp );
 
-    const char* pszUnitName = pOgr->GetAttrValue( "GEOGCS|UNIT");
-    if(pszUnitName)
-        // TODO(schwehr): Figure out a safer way to rename.
-        //   The casting away const here looks dangerous.
-        ret = RemapNamesBasedOnTwo(
-            pOgr, pszGeogCSName+4, pszUnitName,
-            const_cast<char**>(apszGcsNameMappingBasedOnUnit),
-            3, const_cast<char**>(keyNamesG), 1);
-    if(ret < 0)
-    {
-        const char* pszPrimeName = pOgr->GetAttrValue("PRIMEM");
-        if(pszPrimeName)
-            ret = RemapNamesBasedOnTwo(
-                pOgr, pszGeogCSName+4, pszPrimeName,
-                const_cast<char**>(apszGcsNameMappingBasedPrime),
-                3, const_cast<char**>(keyNamesG), 1);
-        if(ret < 0)
-            ret = RemapNameBasedOnKeyName(
-                pOgr, pszGeogCSName+4, "GEOGCS",
-                const_cast<char**>(apszGcsNameMapping) );
-    }
-    if(ret < 0)
-    {
-        const char* pszProjCS = pOgr->GetAttrValue( "PROJCS" );
-        ret = RemapNamesBasedOnTwo(
-            pOgr, pszProjCS, pszGeogCSName,
-            const_cast<char**>(apszGcsNameMappingBasedOnProjCS),
-            3, const_cast<char**>(keyNamesG), 1);
-    }
-    return ret;
+    return eErr;
 }
 
 /************************************************************************/
@@ -2405,12 +2441,12 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(
     int code, const char* datumName, const char* unitsName,
     int pcsCode, const char* csName )
 {
-    /* if the CS name is known */
-    if (code == 0 && !datumName && !unitsName && pcsCode == 32767 && csName)
+    // If the CS name is known.
+    if( code == 0 && !datumName && !unitsName && pcsCode == 32767 && csName )
     {
-        char codeS[10];
-        if (FindCodeFromDict( "esri_StatePlane_extra.wkt", csName, codeS )
-            != OGRERR_NONE)
+        char codeS[10] = {};
+        if( FindCodeFromDict( "esri_StatePlane_extra.wkt", csName, codeS )
+            != OGRERR_NONE )
             return OGRERR_FAILURE;
         return importFromDict( "esri_StatePlane_extra.wkt", codeS);
     }
@@ -2419,7 +2455,7 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(
     if( unitsName == NULL )
         unitsName = "";
 
-    /* Find state plane prj str by pcs code only */
+    // Find state plane prj str by pcs code only.
     if( code == 0 && !datumName && pcsCode != 32767 )
     {
         int unitCode = 1;
@@ -2428,41 +2464,42 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(
         else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
             unitCode = 2;
 
-        for(int i=0; statePlanePcsCodeToZoneCode[i] != 0; i+=2)
+        for( int i = 0; statePlanePcsCodeToZoneCode[i] != 0; i += 2 )
         {
             if( pcsCode == statePlanePcsCodeToZoneCode[i] )
             {
                 searchCode = statePlanePcsCodeToZoneCode[i+1];
-                int unitIndex =  searchCode % 10;
+                const int unitIndex = searchCode % 10;
                 if( (unitCode == 1 && !(unitIndex == 0 || unitIndex == 1))
-                    || (unitCode == 2 && !(unitIndex == 2 || unitIndex == 3 || unitIndex == 4 ))
+                    || (unitCode == 2 && !(unitIndex == 2 || unitIndex == 3 ||
+                                           unitIndex == 4 ))
                     || (unitCode == 3 && !(unitIndex == 5 || unitIndex == 6 )) )
                 {
                     searchCode -= unitIndex;
-                    switch (unitIndex)
+                    switch( unitIndex )
                     {
                       case 0:
                       case 3:
                       case 5:
-                        if(unitCode == 2)
+                        if( unitCode == 2 )
                             searchCode += 3;
-                        else if(unitCode == 3)
+                        else if( unitCode == 3 )
                             searchCode += 5;
                         break;
                       case 1:
                       case 2:
                       case 6:
-                        if(unitCode == 1)
+                        if( unitCode == 1 )
                             searchCode += 1;
-                        if(unitCode == 2)
+                        if( unitCode == 2 )
                             searchCode += 2;
-                        else if(unitCode == 3)
+                        else if( unitCode == 3 )
                             searchCode += 6;
                         break;
                       case 4:
-                        // FIXME? The following cond is not possible
-                        /*if(unitCode == 2)
-                            searchCode += 4;*/
+                        // FIXME? The following cond is not possible:
+                        // if( unitCode == 2 )
+                        //     searchCode += 4;
                         break;
                     }
                 }
@@ -2470,13 +2507,13 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(
             }
         }
     }
-    else /* Find state plane prj str by all inputs. */
+    else // Find state plane prj str by all inputs.
     {
         if( code < 0 || code > INT_MAX / 10 )
             return OGRERR_FAILURE;
 
-        /* Need to have a special EPSG-ESRI zone code mapping first. */
-        for(int i=0; statePlaneZoneMapping[i] != 0; i+=3)
+        // Need to have a special EPSG-ESRI zone code mapping first.
+        for( int i = 0; statePlaneZoneMapping[i] != 0; i += 3 )
         {
             if( code == statePlaneZoneMapping[i]
                 && (statePlaneZoneMapping[i+1] == -1 ||
@@ -2487,19 +2524,19 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(
             }
         }
         searchCode = code * 10;
-        if (!datumName)
+        if( !datumName )
         {
             CPLError( CE_Failure, CPLE_AppDefined, "datumName is NULL.");
             return OGRERR_FAILURE;
         }
-        if(EQUAL(datumName, "HARN"))
+        if( EQUAL(datumName, "HARN") )
         {
             if( EQUAL(unitsName, "international_feet") )
                 searchCode += 5;
             else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
                 searchCode += 3;
         }
-        else if(strstr(datumName, "NAD") && strstr(datumName, "83"))
+        else if( strstr(datumName, "NAD") && strstr(datumName, "83") )
         {
             if( EQUAL(unitsName, "meters") )
                 searchCode += 1;
@@ -2508,16 +2545,17 @@ OGRErr OGRSpatialReference::ImportFromESRIStatePlaneWKT(
             else if( strstr(unitsName, "feet") || strstr(unitsName, "foot") )
                 searchCode += 2;
         }
-        else if(strstr(datumName, "NAD") && strstr(datumName, "27") && !EQUAL(unitsName, "meters"))
+        else if( strstr(datumName, "NAD") && strstr(datumName, "27") &&
+                 !EQUAL(unitsName, "meters") )
         {
             searchCode += 4;
         }
         else
             searchCode = -1;
     }
-    if(searchCode > 0)
+    if( searchCode > 0 )
     {
-        char codeS[10];
+        char codeS[10] = {};
         snprintf(codeS, sizeof(codeS), "%d", (int)searchCode);
         return importFromDict( "esri_StatePlane_extra.wkt", codeS);
     }
@@ -2534,88 +2572,39 @@ OGRErr OGRSpatialReference::ImportFromESRIWisconsinWKT(
     const char* prjName, double centralMeridian, double latOfOrigin,
     const char* unitsName, const char* csName )
 {
-    /* if the CS name is known */
-    if (!prjName && !unitsName && csName)
+    // If the CS name is known.
+    if( !prjName && !unitsName && csName )
     {
-        char codeS[10];
-        if (FindCodeFromDict( "esri_Wisconsin_extra.wkt", csName, codeS ) != OGRERR_NONE)
+        char codeS[10] = {};
+        if( FindCodeFromDict( "esri_Wisconsin_extra.wkt", csName,
+                              codeS ) != OGRERR_NONE )
             return OGRERR_FAILURE;
-        return importFromDict( "esri_Wisconsin_extra.wkt", codeS);
+        return importFromDict("esri_Wisconsin_extra.wkt", codeS);
     }
     const double* tableWISCRS = NULL;
-    if(prjName != NULL && STARTS_WITH_CI(prjName, "Lambert_Conformal_Conic"))
+    if( prjName != NULL && STARTS_WITH_CI(prjName, "Lambert_Conformal_Conic") )
         tableWISCRS = apszWISCRS_LCC_meter;
-    else if(prjName != NULL && EQUAL(prjName, SRS_PT_TRANSVERSE_MERCATOR))
+    else if( prjName != NULL && EQUAL(prjName, SRS_PT_TRANSVERSE_MERCATOR) )
         tableWISCRS = apszWISCRS_TM_meter;
     else
         return OGRERR_FAILURE;
     int k = -1;
-    for(int i=0; tableWISCRS[i] != 0; i+=3)
+    for( int i = 0; tableWISCRS[i] != 0; i += 3 )
     {
         if( fabs(centralMeridian - tableWISCRS[i]) <= 0.0000000001 &&
             fabs(latOfOrigin - tableWISCRS[i+1]) <= 0.0000000001 )
         {
-            k = static_cast<int>(tableWISCRS[i+2]); // double to int ?
+            k = static_cast<int>(tableWISCRS[i+2]); // double to int?
             break;
         }
     }
-    if(k > 0)
+    if( k > 0 )
     {
-        if(unitsName != NULL && !EQUAL(unitsName, "meters"))
+        if( unitsName != NULL && !EQUAL(unitsName, "meters") )
             k += 100;
-        char codeS[10] = { '\0' };
+        char codeS[15] = { '\0' };
         snprintf(codeS, sizeof(codeS), "%d", k);
         return importFromDict( "esri_Wisconsin_extra.wkt", codeS);
     }
     return OGRERR_FAILURE;
 }
-
-/************************************************************************/
-/*                       FindCodeFromDict()                             */
-/*                                                                      */
-/*      Find the code from a dict file.                                 */
-/************************************************************************/
-static int FindCodeFromDict( const char* pszDictFile, const char* CSName, char* code )
-{
-/* -------------------------------------------------------------------- */
-/*      Find and open file.                                             */
-/* -------------------------------------------------------------------- */
-    const char *pszFilename = CPLFindFile( "gdal", pszDictFile );
-    if( pszFilename == NULL )
-        return OGRERR_UNSUPPORTED_SRS;
-
-    VSILFILE *fp = VSIFOpenL( pszFilename, "rb" );
-    if( fp == NULL )
-        return OGRERR_UNSUPPORTED_SRS;
-
-/* -------------------------------------------------------------------- */
-/*      Process lines.                                                  */
-/* -------------------------------------------------------------------- */
-    OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
-    const char *pszLine = NULL;
-
-    while( (pszLine = CPLReadLineL(fp)) != NULL )
-    {
-        if( pszLine[0] == '#' )
-            /* do nothing */;
-
-        else if( strstr(pszLine,CSName) )
-        {
-          const char* pComma = strchr(pszLine, ',');
-          if( pComma )
-          {
-            strncpy( code, pszLine, pComma - pszLine);
-            code[pComma - pszLine] = '\0';
-            eErr = OGRERR_NONE;
-          }
-          break;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup                                                         */
-/* -------------------------------------------------------------------- */
-    VSIFCloseL( fp );
-
-    return eErr;
-}
diff --git a/ogr/ogr_srs_esri_names.h b/ogr/ogr_srs_esri_names.h
index 2a7181b..9479a37 100644
--- a/ogr/ogr_srs_esri_names.h
+++ b/ogr/ogr_srs_esri_names.h
@@ -120,8 +120,6 @@ static const char * const apszGcsNameMappingBasedOnProjCS[] = {
 "MONREF_1997_UTM_Zone_47N", "GCS_ITRF_2000", "GCS_MONREF_1997",
 NULL, NULL, NULL};
 
-
-
 static const char * const apszGcsNameMappingBasedOnUnit[] = {
 "Voirol_Unifie_1960", "Degree", "GCS_Voirol_Unifie_1960_Degree",
 "Voirol_1960", "Degree", "GCS_Voirol_Unifie_1960_Degree",
@@ -202,7 +200,7 @@ static const char * const apszParamValueMapping[] = {
 "Lambert_Conformal_Conic", "central_meridian", "-76.83333333333334", "-76.83333333333333",
 "Krovak", "longitude_of_center", "24.83333333333334", "24.83333333333333",
 "Hotine_Oblique_Mercator_Azimuth_Center", "longitude_of_center", "7.439583333333334", "7.439583333333333",
-"Hotine_Oblique_Mercator_Azimuth_Center", "latitude_of_center",	"46.95240555555557", "46.95240555555556",
+"Hotine_Oblique_Mercator_Azimuth_Center", "latitude_of_center", "46.95240555555557", "46.95240555555556",
 NULL, NULL, NULL, NULL};
 
 static const char * const apszParamNameMapping[] = {
@@ -291,7 +289,7 @@ static const int statePlaneZoneMapping[] = {
  4451, -1,    2403,
  4476, 32100, 2500,
  4476, -1,    2501,
- 4701, 32111,	2900,
+ 4701, 32111, 2900,
  4801, 2260,  3101,
  4801, 32115, 3101,
  4526, -1,    2503,
diff --git a/ogr/ogr_srs_ozi.cpp b/ogr/ogr_srs_ozi.cpp
index 9e2840f..c9e85d7 100644
--- a/ogr/ogr_srs_ozi.cpp
+++ b/ogr/ogr_srs_ozi.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_ozi.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation from OziExplorer
@@ -29,11 +28,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_spatialref.h"
+
+#include <cstdlib>
+#include <cstring>
+
 #include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
+#include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogr_srs_ozi.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogr_srs_ozi.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 /************************************************************************/
 /*                          OSRImportFromOzi()                          */
@@ -86,108 +94,108 @@ OGRErr OSRImportFromOzi( OGRSpatialReferenceH hSRS,
 
 OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
 {
-    int iLine;
-    const char *pszDatum, *pszProj = NULL, *pszProjParms = NULL;
+    const char *pszDatum;
+    const char *pszProj = NULL;
+    const char *pszProjParms = NULL;
 
     Clear();
 
-    int nLines = CSLCount((char**)papszLines);
+    const int nLines = CSLCount((char**)papszLines);
     if( nLines < 5 )
         return OGRERR_NOT_ENOUGH_DATA;
 
     pszDatum = papszLines[4];
 
-    for ( iLine = 5; iLine < nLines; iLine++ )
+    for( int iLine = 5; iLine < nLines; iLine++ )
     {
-        if ( STARTS_WITH_CI(papszLines[iLine], "Map Projection") )
+        if( STARTS_WITH_CI(papszLines[iLine], "Map Projection") )
         {
             pszProj = papszLines[iLine];
         }
-        else if ( STARTS_WITH_CI(papszLines[iLine], "Projection Setup") )
+        else if( STARTS_WITH_CI(papszLines[iLine], "Projection Setup") )
         {
             pszProjParms = papszLines[iLine];
         }
     }
 
-    if ( ! ( pszDatum && pszProj && pszProjParms ) )
+    if( !(pszDatum && pszProj && pszProjParms) )
         return OGRERR_NOT_ENOUGH_DATA;
 
 /* -------------------------------------------------------------------- */
 /*      Operate on the basis of the projection name.                    */
 /* -------------------------------------------------------------------- */
-    char    **papszProj = CSLTokenizeStringComplex( pszProj, ",", TRUE, TRUE );
-    char    **papszProjParms = CSLTokenizeStringComplex( pszProjParms, ",",
-                                                         TRUE, TRUE );
-    char    **papszDatum = NULL;
+    char **papszProj = CSLTokenizeStringComplex( pszProj, ",", TRUE, TRUE );
+    char **papszProjParms = CSLTokenizeStringComplex( pszProjParms, ",",
+                                                      TRUE, TRUE );
+    char **papszDatum = NULL;
 
-    if (CSLCount(papszProj) < 2)
+    if( CSLCount(papszProj) < 2 )
     {
         goto not_enough_data;
     }
 
-    if ( STARTS_WITH_CI(papszProj[1], "Latitude/Longitude") )
+    if( STARTS_WITH_CI(papszProj[1], "Latitude/Longitude") )
     {
+        // Do nothing.
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Mercator") )
+    else if( STARTS_WITH_CI(papszProj[1], "Mercator") )
     {
-        if (CSLCount(papszProjParms) < 6) goto not_enough_data;
+        if( CSLCount(papszProjParms) < 6 ) goto not_enough_data;
         double dfScale = CPLAtof(papszProjParms[3]);
-        if (papszProjParms[3][0] == 0) dfScale = 1; /* if unset, default to scale = 1 */
+        // If unset, default to scale = 1.
+        if( papszProjParms[3][0] == 0 ) dfScale = 1;
         SetMercator( CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
                      dfScale,
                      CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Transverse Mercator") )
+    else if( STARTS_WITH_CI(papszProj[1], "Transverse Mercator") )
     {
-        if (CSLCount(papszProjParms) < 6) goto not_enough_data;
+        if( CSLCount(papszProjParms) < 6 ) goto not_enough_data;
         SetTM( CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
                CPLAtof(papszProjParms[3]),
                CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Lambert Conformal Conic") )
+    else if( STARTS_WITH_CI(papszProj[1], "Lambert Conformal Conic") )
     {
-        if (CSLCount(papszProjParms) < 8) goto not_enough_data;
+        if( CSLCount(papszProjParms) < 8 ) goto not_enough_data;
         SetLCC( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
                 CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
                 CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Sinusoidal") )
+    else if( STARTS_WITH_CI(papszProj[1], "Sinusoidal") )
     {
-        if (CSLCount(papszProjParms) < 6) goto not_enough_data;
+        if( CSLCount(papszProjParms) < 6 ) goto not_enough_data;
         SetSinusoidal( CPLAtof(papszProjParms[2]),
                        CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Albers Equal Area") )
+    else if( STARTS_WITH_CI(papszProj[1], "Albers Equal Area") )
     {
-        if (CSLCount(papszProjParms) < 8) goto not_enough_data;
+        if( CSLCount(papszProjParms) < 8 ) goto not_enough_data;
         SetACEA( CPLAtof(papszProjParms[6]), CPLAtof(papszProjParms[7]),
                  CPLAtof(papszProjParms[1]), CPLAtof(papszProjParms[2]),
                  CPLAtof(papszProjParms[4]), CPLAtof(papszProjParms[5]) );
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(UTM) Universal Transverse Mercator") && nLines > 5 )
+    else if( STARTS_WITH_CI(
+                 papszProj[1], "(UTM) Universal Transverse Mercator") &&
+             nLines > 5 )
     {
-        /* Look for the UTM zone in the calibration point data */
-        for ( iLine = 5; iLine < nLines; iLine++ )
+        // Look for the UTM zone in the calibration point data.
+        int iLine = 5;  // Used after for.
+        for( ; iLine < nLines; iLine++ )
         {
-            if ( STARTS_WITH_CI(papszLines[iLine], "Point") )
+            if( STARTS_WITH_CI(papszLines[iLine], "Point") )
             {
-                char    **papszTok = NULL;
-                papszTok = CSLTokenizeString2( papszLines[iLine], ",",
-                                               CSLT_ALLOWEMPTYTOKENS
-                                               | CSLT_STRIPLEADSPACES
-                                               | CSLT_STRIPENDSPACES );
-                if ( CSLCount(papszTok) < 17
-                     || EQUAL(papszTok[2], "")
-                     || EQUAL(papszTok[13], "")
-                     || EQUAL(papszTok[14], "")
-                     || EQUAL(papszTok[15], "")
-                     || EQUAL(papszTok[16], "") )
+                char **papszTok =
+                    CSLTokenizeString2(papszLines[iLine], ",",
+                                       CSLT_ALLOWEMPTYTOKENS
+                                       | CSLT_STRIPLEADSPACES
+                                       | CSLT_STRIPENDSPACES);
+                if( CSLCount(papszTok) < 17
+                    || EQUAL(papszTok[2], "")
+                    || EQUAL(papszTok[13], "")
+                    || EQUAL(papszTok[14], "")
+                    || EQUAL(papszTok[15], "")
+                    || EQUAL(papszTok[16], "") )
                 {
                     CSLDestroy(papszTok);
                     continue;
@@ -197,170 +205,157 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
                 break;
             }
         }
-        if ( iLine == nLines )    /* Try to guess the UTM zone */
+        if( iLine == nLines )  // Try to guess the UTM zone.
         {
             float fMinLongitude = 1000.0f;
-            float fMaxLongitude = -1000.0f;;
+            float fMaxLongitude = -1000.0f;
             float fMinLatitude = 1000.0f;
             float fMaxLatitude = -1000.0f;
             bool bFoundMMPLL = false;
-            for ( iLine = 5; iLine < nLines; iLine++ )
+            for( iLine = 5; iLine < nLines; iLine++ )
             {
-                if ( STARTS_WITH_CI(papszLines[iLine], "MMPLL") )
+                if( STARTS_WITH_CI(papszLines[iLine], "MMPLL") )
                 {
-                    char    **papszTok = NULL;
-                    papszTok = CSLTokenizeString2( papszLines[iLine], ",",
-                                                   CSLT_ALLOWEMPTYTOKENS
-                                                   | CSLT_STRIPLEADSPACES
-                                                   | CSLT_STRIPENDSPACES );
-                    if ( CSLCount(papszTok) < 4 )
+                    char **papszTok =
+                        CSLTokenizeString2(papszLines[iLine], ",",
+                                           CSLT_ALLOWEMPTYTOKENS
+                                           | CSLT_STRIPLEADSPACES
+                                           | CSLT_STRIPENDSPACES);
+                    if( CSLCount(papszTok) < 4 )
                     {
                         CSLDestroy(papszTok);
                         continue;
                     }
-                    float fLongitude = static_cast<float>(CPLAtofM(papszTok[2]));
-                    float fLatitude = static_cast<float>(CPLAtofM(papszTok[3]));
+                    const float fLongitude =
+                        static_cast<float>(CPLAtofM(papszTok[2]));
+                    const float fLatitude =
+                        static_cast<float>(CPLAtofM(papszTok[3]));
                     CSLDestroy(papszTok);
 
                     bFoundMMPLL = true;
 
-                    if ( fMinLongitude > fLongitude )
+                    if( fMinLongitude > fLongitude )
                         fMinLongitude = fLongitude;
-                    if ( fMaxLongitude < fLongitude )
+                    if( fMaxLongitude < fLongitude )
                         fMaxLongitude = fLongitude;
-                    if ( fMinLatitude > fLatitude )
+                    if( fMinLatitude > fLatitude )
                         fMinLatitude = fLatitude;
-                    if ( fMaxLatitude < fLatitude )
+                    if( fMaxLatitude < fLatitude )
                         fMaxLatitude = fLatitude;
                 }
             }
-            float fMedianLatitude = ( fMinLatitude + fMaxLatitude ) / 2;
-            float fMedianLongitude = ( fMinLongitude + fMaxLongitude ) / 2;
-            if ( bFoundMMPLL && fMaxLatitude <= 90 )
+            const float fMedianLatitude = (fMinLatitude + fMaxLatitude) / 2;
+            const float fMedianLongitude = (fMinLongitude + fMaxLongitude) / 2;
+            if( bFoundMMPLL && fMaxLatitude <= 90 )
             {
-                int nUtmZone;
-                if ( fMedianLatitude >= 56 && fMedianLatitude <= 64 &&
-                     fMedianLongitude >= 3 && fMedianLongitude <= 12 )
-                    nUtmZone = 32;                                             /* Norway exception */
-                else if ( fMedianLatitude >= 72 && fMedianLatitude <= 84 &&
+                int nUtmZone = 0;
+                if( fMedianLatitude >= 56 && fMedianLatitude <= 64 &&
+                    fMedianLongitude >= 3 && fMedianLongitude <= 12 )
+                    nUtmZone = 32;  // Norway exception.
+                else if( fMedianLatitude >= 72 && fMedianLatitude <= 84 &&
                          fMedianLongitude >= 0 && fMedianLongitude <= 42 )
-                    nUtmZone = (int) ((fMedianLongitude + 3 ) / 12) * 2 + 31;  /* Svalbard exception */
+                    // Svalbard exception.
+                    nUtmZone =
+                        static_cast<int>((fMedianLongitude + 3) / 12) * 2 + 31;
                 else
-                    nUtmZone = (int) ((fMedianLongitude + 180 ) / 6) + 1;
+                    nUtmZone =
+                        static_cast<int>((fMedianLongitude + 180 ) / 6) + 1;
                 SetUTM( nUtmZone, fMedianLatitude >= 0 );
             }
             else
+            {
                 CPLDebug( "OSR_Ozi", "UTM Zone not found");
+            }
         }
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(I) France Zone I") )
+    else if( STARTS_WITH_CI(papszProj[1], "(I) France Zone I") )
     {
         SetLCC1SP( 49.5, 2.337229167, 0.99987734, 600000, 1200000 );
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(II) France Zone II") )
+    else if( STARTS_WITH_CI(papszProj[1], "(II) France Zone II") )
     {
         SetLCC1SP( 46.8, 2.337229167, 0.99987742, 600000, 2200000 );
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(III) France Zone III") )
+    else if( STARTS_WITH_CI(papszProj[1], "(III) France Zone III") )
     {
         SetLCC1SP( 44.1, 2.337229167, 0.99987750, 600000, 3200000 );
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(IV) France Zone IV") )
+    else if( STARTS_WITH_CI(papszProj[1], "(IV) France Zone IV") )
     {
         SetLCC1SP( 42.165, 2.337229167, 0.99994471, 234.358, 4185861.369 );
     }
 
 /*
- *  Note : The following projections have not been implemented yet
+ *  Note: The following projections have not been implemented yet
  *
  */
 
 /*
-    else if ( STARTS_WITH_CI(papszProj[1], "(BNG) British National Grid") )
+    else if( STARTS_WITH_CI(papszProj[1], "(BNG) British National Grid") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(IG) Irish Grid") )
+    else if( STARTS_WITH_CI(papszProj[1], "(IG) Irish Grid") )
     {
     }
 
-    else if ( STARTS_WITH_CI(papszProj[1], "(NZG) New Zealand Grid") )
+    else if( STARTS_WITH_CI(papszProj[1], "(NZG) New Zealand Grid") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(NZTM2) New Zealand TM 2000") )
+    else if( STARTS_WITH_CI(papszProj[1], "(NZTM2) New Zealand TM 2000") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(SG) Swedish Grid") )
+    else if( STARTS_WITH_CI(papszProj[1], "(SG) Swedish Grid") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(SUI) Swiss Grid") )
+    else if( STARTS_WITH_CI(papszProj[1], "(SUI) Swiss Grid") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(A)Lambert Azimuthual Equal Area") )
+    else if( STARTS_WITH_CI(papszProj[1], "(A)Lambert Azimuthual Equal Area") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(EQC) Equidistant Conic") )
+    else if( STARTS_WITH_CI(papszProj[1], "(EQC) Equidistant Conic") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Polyconic (American)") )
+    else if( STARTS_WITH_CI(papszProj[1], "Polyconic (American)") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Van Der Grinten") )
+    else if( STARTS_WITH_CI(papszProj[1], "Van Der Grinten") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Vertical Near-Sided Perspective") )
+    else if( STARTS_WITH_CI(papszProj[1], "Vertical Near-Sided Perspective") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(WIV) Wagner IV") )
+    else if( STARTS_WITH_CI(papszProj[1], "(WIV) Wagner IV") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Bonne") )
+    else if( STARTS_WITH_CI(papszProj[1], "Bonne") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(MT0) Montana State Plane Zone 2500") )
+    else if( STARTS_WITH_CI(papszProj[1],
+                            "(MT0) Montana State Plane Zone 2500") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "ITA1) Italy Grid Zone 1") )
+    else if( STARTS_WITH_CI(papszProj[1], "ITA1) Italy Grid Zone 1") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "ITA2) Italy Grid Zone 2") )
+    else if( STARTS_WITH_CI(papszProj[1], "ITA2) Italy Grid Zone 2") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(VICMAP-TM) Victoria Aust.(pseudo AMG)") )
+    else if( STARTS_WITH_CI(papszProj[1],
+                            "(VICMAP-TM) Victoria Aust.(pseudo AMG)") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "VICGRID) Victoria Australia") )
+    else if( STARTS_WITH_CI(papszProj[1], "VICGRID) Victoria Australia") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "(VG94) VICGRID94 Victoria Australia") )
+    else if( STARTS_WITH_CI(papszProj[1],
+                            "(VG94) VICGRID94 Victoria Australia") )
     {
     }
-
-    else if ( STARTS_WITH_CI(papszProj[1], "Gnomonic") )
+    else if( STARTS_WITH_CI(papszProj[1], "Gnomonic") )
     {
     }
 */
-
     else
     {
         CPLDebug( "OSR_Ozi", "Unsupported projection: \"%s\"", papszProj[1] );
@@ -372,27 +367,26 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
 /*      Try to translate the datum/spheroid.                            */
 /* -------------------------------------------------------------------- */
     papszDatum = CSLTokenizeString2( pszDatum, ",",
-                                               CSLT_ALLOWEMPTYTOKENS
-                                               | CSLT_STRIPLEADSPACES
-                                               | CSLT_STRIPENDSPACES );
-    if ( papszDatum == NULL)
+                                     CSLT_ALLOWEMPTYTOKENS
+                                     | CSLT_STRIPLEADSPACES
+                                     | CSLT_STRIPENDSPACES );
+    if( papszDatum == NULL )
         goto not_enough_data;
 
-    if ( !IsLocal() )
+    if( !IsLocal() )
     {
-
 /* -------------------------------------------------------------------- */
 /*      Verify that we can find the CSV file containing the datums      */
 /* -------------------------------------------------------------------- */
         if( CSVScanFileByName( CSVFilename( "ozi_datum.csv" ),
-                            "EPSG_DATUM_CODE",
-                            "4326", CC_Integer ) == NULL )
+                               "EPSG_DATUM_CODE",
+                               "4326", CC_Integer ) == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                    "Unable to open OZI support file %s.\n"
-                    "Try setting the GDAL_DATA environment variable to point\n"
-                    "to the directory containing OZI csv files.",
-                    CSVFilename( "ozi_datum.csv" ) );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Unable to open OZI support file %s.  "
+                     "Try setting the GDAL_DATA environment variable to point "
+                     "to the directory containing OZI csv files.",
+                     CSVFilename( "ozi_datum.csv" ));
             goto other_error;
         }
 
@@ -402,7 +396,7 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
         const char *pszOziDatum = CSVFilename( "ozi_datum.csv" );
         CPLString osDName = CSVGetField( pszOziDatum, "NAME", papszDatum[0],
                                     CC_ApproxString, "NAME" );
-        if( strlen(osDName) == 0 )
+        if( osDName.empty() )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                     "Failed to find datum %s in ozi_datum.csv.",
@@ -410,10 +404,11 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
             goto other_error;
         }
 
-        int nDatumCode = atoi( CSVGetField( pszOziDatum, "NAME", papszDatum[0],
-                                            CC_ApproxString, "EPSG_DATUM_CODE" ) );
+        const int nDatumCode =
+            atoi( CSVGetField( pszOziDatum, "NAME", papszDatum[0],
+                               CC_ApproxString, "EPSG_DATUM_CODE" ) );
 
-        if ( nDatumCode > 0 ) // There is a matching EPSG code
+        if( nDatumCode > 0 ) // There is a matching EPSG code
         {
             OGRSpatialReference oGCS;
             oGCS.importFromEPSG( nDatumCode );
@@ -421,26 +416,30 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
         }
         else // We use the parameters from the CSV files
         {
-            CPLString osEllipseCode = CSVGetField( pszOziDatum, "NAME", papszDatum[0],
-                                                CC_ApproxString, "ELLIPSOID_CODE" );
-            double dfDeltaX = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
-                                                CC_ApproxString, "DELTAX" ) );
-            double dfDeltaY = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
-                                                CC_ApproxString, "DELTAY" ) );
-            double dfDeltaZ = CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
-                                                CC_ApproxString, "DELTAZ" ) );
-
+            CPLString osEllipseCode =
+                CSVGetField( pszOziDatum, "NAME", papszDatum[0],
+                             CC_ApproxString, "ELLIPSOID_CODE" );
+            const double dfDeltaX =
+                CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
+                                     CC_ApproxString, "DELTAX" ) );
+            const double dfDeltaY =
+                CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
+                                     CC_ApproxString, "DELTAY" ) );
+            const double dfDeltaZ =
+                CPLAtof(CSVGetField( pszOziDatum, "NAME", papszDatum[0],
+                                     CC_ApproxString, "DELTAZ" ) );
 
     /* -------------------------------------------------------------------- */
-    /*      Verify that we can find the CSV file containing the ellipsoids  */
+    /*     Verify that we can find the CSV file containing the ellipsoids.  */
     /* -------------------------------------------------------------------- */
             if( CSVScanFileByName( CSVFilename( "ozi_ellips.csv" ),
-                                "ELLIPSOID_CODE",
-                                "20", CC_Integer ) == NULL )
+                                   "ELLIPSOID_CODE",
+                                   "20", CC_Integer ) == NULL )
             {
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                    "Unable to open OZI support file %s.\n"
-                    "Try setting the GDAL_DATA environment variable to point\n"
+                CPLError(
+                    CE_Failure, CPLE_OpenFailed,
+                    "Unable to open OZI support file %s.  "
+                    "Try setting the GDAL_DATA environment variable to point "
                     "to the directory containing OZI csv files.",
                     CSVFilename( "ozi_ellips.csv" ) );
                 goto other_error;
@@ -451,9 +450,10 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
     /* -------------------------------------------------------------------- */
             const char *pszOziEllipse = CSVFilename( "ozi_ellips.csv" );
 
-            CPLString osEName = CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
-                                        CC_ApproxString, "NAME" );
-            if( strlen(osEName) == 0 )
+            CPLString osEName =
+                CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
+                             CC_ApproxString, "NAME" );
+            if( osEName.empty() )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Failed to find ellipsoid %s in ozi_ellips.csv.",
@@ -461,18 +461,18 @@ OGRErr OGRSpatialReference::importFromOzi( const char * const* papszLines )
                 goto other_error;
             }
 
-            double dfA = CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
-                                        CC_ApproxString, "A" ));
-            double dfInvF = CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE", osEllipseCode,
-                                            CC_ApproxString, "INVF" ));
+            const double dfA =
+                CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE",
+                                     osEllipseCode, CC_ApproxString, "A" ));
+            const double dfInvF =
+                CPLAtof(CSVGetField( pszOziEllipse, "ELLIPSOID_CODE",
+                                     osEllipseCode, CC_ApproxString, "INVF" ));
 
     /* -------------------------------------------------------------------- */
     /*      Create geographic coordinate system.                            */
     /* -------------------------------------------------------------------- */
-
             SetGeogCS( osDName, osDName, osEName, dfA, dfInvF );
             SetTOWGS84( dfDeltaX, dfDeltaY, dfDeltaZ );
-
         }
     }
 
diff --git a/ogr/ogr_srs_panorama.cpp b/ogr/ogr_srs_panorama.cpp
index 0c2ef90..b7d1fcb 100644
--- a/ogr/ogr_srs_panorama.cpp
+++ b/ogr/ogr_srs_panorama.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_panorama.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from "Panorama" GIS
@@ -30,14 +29,14 @@
  ****************************************************************************/
 
 #include "ogr_spatialref.h"
-#include "ogr_p.h"
 #include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "ogr_p.h"
 
-CPL_CVSID("$Id: ogr_srs_panorama.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogr_srs_panorama.cpp 36238 2016-11-14 20:52:13Z goatbar $");
 
-#define TO_DEGREES 57.2957795130823208766
-#define TO_RADIANS 0.017453292519943295769
+static const double TO_DEGREES = 57.2957795130823208766;
+static const double TO_RADIANS = 0.017453292519943295769;
 
 // XXX: this macro computes zone number from the central meridian parameter.
 // Note, that "Panorama" parameters are set in radians.
@@ -45,52 +44,56 @@ CPL_CVSID("$Id: ogr_srs_panorama.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 //
 //              zone = (central_meridian + 3) / 6
 //
-#define TO_ZONE(x) (((x) + 0.05235987755982989) / 0.1047197551196597 + 0.5)
+static int TO_ZONE( double x )
+{
+  return
+      static_cast<int>((x + 0.05235987755982989) / 0.1047197551196597 + 0.5);
+}
 
 /************************************************************************/
 /*  "Panorama" projection codes.                                        */
 /************************************************************************/
 
-#define PAN_PROJ_NONE   -1L
-#define PAN_PROJ_TM     1L      // Gauss-Kruger (Transverse Mercator)
-#define PAN_PROJ_LCC    2L      // Lambert Conformal Conic 2SP
-#define PAN_PROJ_STEREO 5L      // Stereographic
-#define PAN_PROJ_AE     6L      // Azimuthal Equidistant (Postel)
-#define PAN_PROJ_MERCAT 8L      // Mercator
-#define PAN_PROJ_POLYC  10L     // Polyconic
-#define PAN_PROJ_PS     13L     // Polar Stereographic
-#define PAN_PROJ_GNOMON 15L     // Gnomonic
-#define PAN_PROJ_UTM    17L     // Universal Transverse Mercator (UTM)
-#define PAN_PROJ_WAG1   18L     // Wagner I (Kavraisky VI)
-#define PAN_PROJ_MOLL   19L     // Mollweide
-#define PAN_PROJ_EC     20L     // Equidistant Conic
-#define PAN_PROJ_LAEA   24L     // Lambert Azimuthal Equal Area
-#define PAN_PROJ_EQC    27L     // Equirectangular
-#define PAN_PROJ_CEA    28L     // Cylindrical Equal Area (Lambert)
-#define PAN_PROJ_IMWP   29L     // International Map of the World Polyconic
-#define PAN_PROJ_MILLER 34L     // Miller
+static const long PAN_PROJ_NONE   = -1L;
+static const long PAN_PROJ_TM     = 1L;   // Gauss-Kruger (Transverse Mercator)
+static const long PAN_PROJ_LCC    = 2L;   // Lambert Conformal Conic 2SP
+static const long PAN_PROJ_STEREO = 5L;   // Stereographic
+static const long PAN_PROJ_AE     = 6L;   // Azimuthal Equidistant (Postel)
+static const long PAN_PROJ_MERCAT = 8L;   // Mercator
+static const long PAN_PROJ_POLYC  = 10L;  // Polyconic
+static const long PAN_PROJ_PS     = 13L;  // Polar Stereographic
+static const long PAN_PROJ_GNOMON = 15L;  // Gnomonic
+static const long PAN_PROJ_UTM    = 17L;  // Universal Transverse Mercator (UTM)
+static const long PAN_PROJ_WAG1   = 18L;  // Wagner I (Kavraisky VI)
+static const long PAN_PROJ_MOLL   = 19L;  // Mollweide
+static const long PAN_PROJ_EC     = 20L;  // Equidistant Conic
+static const long PAN_PROJ_LAEA   = 24L;  // Lambert Azimuthal Equal Area
+static const long PAN_PROJ_EQC    = 27L;  // Equirectangular
+static const long PAN_PROJ_CEA    = 28L;  // Cylindrical Equal Area (Lambert)
+static const long PAN_PROJ_IMWP   = 29L;  // International Map of the World Polyconic
+static const long PAN_PROJ_MILLER = 34L;  // Miller
 /************************************************************************/
 /*  "Panorama" datum codes.                                             */
 /************************************************************************/
 
-#define PAN_DATUM_NONE      -1L
-#define PAN_DATUM_PULKOVO42 1L  // Pulkovo 1942
-#define PAN_DATUM_WGS84     2L  // WGS84
+static const long PAN_DATUM_NONE      = -1L;
+static const long PAN_DATUM_PULKOVO42 = 1L;  // Pulkovo 1942
+static const long PAN_DATUM_WGS84     = 2L;  // WGS84
 
 /************************************************************************/
 /*  "Panorama" ellipsoid codes.                                         */
 /************************************************************************/
 
-#define PAN_ELLIPSOID_NONE          -1L
-#define PAN_ELLIPSOID_KRASSOVSKY    1L  // Krassovsky, 1940
-#define PAN_ELLIPSOID_WGS72         2L  // WGS, 1972
-#define PAN_ELLIPSOID_INT1924       3L  // International, 1924 (Hayford, 1909)
-#define PAN_ELLIPSOID_CLARCKE1880   4L  // Clarke, 1880
-#define PAN_ELLIPSOID_CLARCKE1866   5L  // Clarke, 1866 (NAD1927)
-#define PAN_ELLIPSOID_EVEREST1830   6L  // Everest, 1830
-#define PAN_ELLIPSOID_BESSEL1841    7L  // Bessel, 1841
-#define PAN_ELLIPSOID_AIRY1830      8L  // Airy, 1830
-#define PAN_ELLIPSOID_WGS84         9L  // WGS, 1984 (GPS)
+static const long PAN_ELLIPSOID_NONE        = -1L;
+static const long PAN_ELLIPSOID_KRASSOVSKY  = 1L;  // Krassovsky, 1940
+// static const long PAN_ELLIPSOID_WGS72       = 2L;  // WGS, 1972
+// static const long PAN_ELLIPSOID_INT1924     = 3L;  // International, 1924 (Hayford, 1909)
+// static const long PAN_ELLIPSOID_CLARCKE1880 = 4L;  // Clarke, 1880
+// static const long PAN_ELLIPSOID_CLARCKE1866 = 5L;  // Clarke, 1866 (NAD1927)
+// static const long PAN_ELLIPSOID_EVEREST1830 = 6L;  // Everest, 1830
+// static const long PAN_ELLIPSOID_BESSEL1841  = 7L;  // Bessel, 1841
+// static const long PAN_ELLIPSOID_AIRY1830    = 8L;  // Airy, 1830
+static const long PAN_ELLIPSOID_WGS84       = 9L;  // WGS, 1984 (GPS)
 
 /************************************************************************/
 /*  Correspondence between "Panorama" and EPSG datum codes.             */
@@ -141,12 +144,18 @@ static const int aoEllips[] =
     7003   // Australian National, 1965
 };
 
-#define NUMBER_OF_ELLIPSOIDS    static_cast<int>(sizeof(aoEllips)/sizeof(aoEllips[0]))
+static const int NUMBER_OF_ELLIPSOIDS =
+    static_cast<int>(sizeof(aoEllips)/sizeof(aoEllips[0]));
 
 /************************************************************************/
 /*                        OSRImportFromPanorama()                       */
 /************************************************************************/
 
+/** Import coordinate system from "Panorama" GIS projection definition.
+ *
+ * See OGRSpatialReference::importFromPanorama()
+ */
+
 OGRErr OSRImportFromPanorama( OGRSpatialReferenceH hSRS,
                               long iProjSys, long iDatum, long iEllips,
                               double *padfPrjParams )
@@ -154,9 +163,10 @@ OGRErr OSRImportFromPanorama( OGRSpatialReferenceH hSRS,
 {
     VALIDATE_POINTER1( hSRS, "OSRImportFromPanorama", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->importFromPanorama( iProjSys,
-                                                               iDatum,iEllips,
-                                                               padfPrjParams );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        importFromPanorama( iProjSys,
+                            iDatum, iEllips,
+                            padfPrjParams );
 }
 
 /************************************************************************/
@@ -248,16 +258,14 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
 /* -------------------------------------------------------------------- */
 /*      Use safe defaults if projection parameters are not supplied.    */
 /* -------------------------------------------------------------------- */
-    int bProjAllocated = false;
+    bool bProjAllocated = false;
 
     if( padfPrjParams == NULL )
     {
-        int     i;
-
-        padfPrjParams = (double *)CPLMalloc( 8 * sizeof(double) );
-        if ( !padfPrjParams )
+        padfPrjParams = static_cast<double *>(CPLMalloc(8 * sizeof(double)));
+        if( !padfPrjParams )
             return OGRERR_NOT_ENOUGH_MEMORY;
-        for ( i = 0; i < 7; i++ )
+        for( int i = 0; i < 7; i++ )
             padfPrjParams[i] = 0.0;
         bProjAllocated = true;
     }
@@ -265,19 +273,17 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
 /* -------------------------------------------------------------------- */
 /*      Operate on the basis of the projection code.                    */
 /* -------------------------------------------------------------------- */
-    switch ( iProjSys )
+    switch( iProjSys )
     {
         case PAN_PROJ_NONE:
             break;
 
         case PAN_PROJ_UTM:
             {
-                int nZone;
-
-                if ( padfPrjParams[7] == 0.0 )
-                    nZone = (int) TO_ZONE(padfPrjParams[3]);
-                else
-                    nZone = (int) padfPrjParams[7];
+                const int nZone =
+                    padfPrjParams[7] == 0.0
+                    ? TO_ZONE(padfPrjParams[3])
+                    : static_cast<int>(padfPrjParams[7]);
 
                 // XXX: no way to determine south hemisphere. Always assume
                 // northern hemisphere.
@@ -332,18 +338,18 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
                 // parameter, because usually it is not contained in the
                 // "Panorama" projection definition.
                 // FIXME: what to do with negative values?
-                int    nZone;
-                double  dfCenterLong;
+                int nZone = 0;
+                double dfCenterLong = 0.0;
 
-                if ( padfPrjParams[7] == 0.0 )
+                if( padfPrjParams[7] == 0.0 )
                 {
-                    nZone = (int)TO_ZONE(padfPrjParams[3]);
+                    nZone = TO_ZONE(padfPrjParams[3]);
                     dfCenterLong = TO_DEGREES * padfPrjParams[3];
                 }
                 else
                 {
-                    nZone = (int) padfPrjParams[7];
-                    dfCenterLong = 6 * (double)nZone - 3;
+                    nZone = static_cast<int>(padfPrjParams[7]);
+                    dfCenterLong = 6.0 * nZone - 3.0;
                 }
 
                 padfPrjParams[5] = nZone * 1000000.0 + 500000.0;
@@ -415,59 +421,58 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
             SetLocalCS( CPLString().Printf("\"Panorama\" projection number %ld",
                                    iProjSys) );
             break;
-
     }
 
 /* -------------------------------------------------------------------- */
 /*      Try to translate the datum/spheroid.                            */
 /* -------------------------------------------------------------------- */
 
-    if ( !IsLocal() )
+    if( !IsLocal() )
     {
-        if ( iDatum > 0 && iDatum < NUMBER_OF_DATUMS && aoDatums[iDatum] )
+        if( iDatum > 0 && iDatum < NUMBER_OF_DATUMS && aoDatums[iDatum] )
         {
             OGRSpatialReference oGCS;
             oGCS.importFromEPSG( aoDatums[iDatum] );
             CopyGeogCSFrom( &oGCS );
         }
-
-        else if ( iEllips > 0
-                  && iEllips < NUMBER_OF_ELLIPSOIDS
-                  && aoEllips[iEllips] )
+        else if( iEllips > 0
+                 && iEllips < NUMBER_OF_ELLIPSOIDS
+                 && aoEllips[iEllips] )
         {
-            char    *pszName = NULL;
-            double  dfSemiMajor, dfInvFlattening;
+            char *pszName = NULL;
+            double dfSemiMajor = 0.0;
+            double dfInvFlattening = 0.0;
 
-            if ( OSRGetEllipsoidInfo( aoEllips[iEllips], &pszName,
-                            &dfSemiMajor, &dfInvFlattening ) == OGRERR_NONE )
+            if( OSRGetEllipsoidInfo( aoEllips[iEllips], &pszName,
+                                     &dfSemiMajor,
+                                     &dfInvFlattening ) == OGRERR_NONE )
             {
-                SetGeogCS( CPLString().Printf(
-                            "Unknown datum based upon the %s ellipsoid",
-                            pszName ),
-                           CPLString().Printf(
-                            "Not specified (based on %s spheroid)", pszName ),
-                           pszName, dfSemiMajor, dfInvFlattening,
-                           NULL, 0.0, NULL, 0.0 );
+                SetGeogCS(
+                   CPLString().Printf(
+                       "Unknown datum based upon the %s ellipsoid",
+                       pszName ),
+                   CPLString().Printf(
+                       "Not specified (based on %s spheroid)", pszName ),
+                   pszName, dfSemiMajor, dfInvFlattening,
+                   NULL, 0.0, NULL, 0.0 );
                 SetAuthority( "SPHEROID", "EPSG", aoEllips[iEllips] );
             }
             else
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                          "Failed to lookup ellipsoid code %ld, likely due to"
-                          " missing GDAL gcs.csv\n"
-                          " file.  Falling back to use Pulkovo 42.", iEllips );
+                          "Failed to lookup ellipsoid code %ld, likely due to "
+                          "missing GDAL gcs.csv "
+                          "file.  Falling back to use Pulkovo 42.", iEllips );
                 SetWellKnownGeogCS( "EPSG:4284" );
             }
 
-            if ( pszName )
-                CPLFree( pszName );
+            CPLFree( pszName );
         }
-
         else
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Wrong datum code %ld. Supported datums are 1--%ld only.\n"
-                      "Falling back to use Pulkovo 42.",
+                      "Wrong datum code %ld. Supported datums are 1--%ld "
+                      "only.  Falling back to use Pulkovo 42.",
                       iDatum, NUMBER_OF_DATUMS - 1 );
             SetWellKnownGeogCS( "EPSG:4284" );
         }
@@ -481,7 +486,7 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
 
     FixupOrdering();
 
-    if ( bProjAllocated && padfPrjParams )
+    if( bProjAllocated && padfPrjParams )
         CPLFree( padfPrjParams );
 
     return OGRERR_NONE;
@@ -491,6 +496,11 @@ OGRErr OGRSpatialReference::importFromPanorama( long iProjSys, long iDatum,
 /*                      OSRExportToPanorama()                           */
 /************************************************************************/
 
+/** Export coordinate system in "Panorama" GIS projection definition.
+ *
+ * See OGRSpatialReference::exportToPanorama()
+ */
+
 OGRErr OSRExportToPanorama( OGRSpatialReferenceH hSRS,
                             long *piProjSys, long *piDatum, long *piEllips,
                             long *piZone, double *padfPrjParams )
@@ -502,10 +512,11 @@ OGRErr OSRExportToPanorama( OGRSpatialReferenceH hSRS,
     VALIDATE_POINTER1( piEllips, "OSRExportToPanorama", OGRERR_FAILURE );
     VALIDATE_POINTER1( padfPrjParams, "OSRExportToPanorama", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->exportToPanorama( piProjSys,
-                                                             piDatum, piEllips,
-                                                             piZone,
-                                                             padfPrjParams );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        exportToPanorama( piProjSys,
+                          piDatum, piEllips,
+                          piZone,
+                          padfPrjParams );
 }
 
 /************************************************************************/
@@ -543,25 +554,24 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
 {
     CPLAssert( padfPrjParams );
 
-    const char  *pszProjection = GetAttrValue("PROJECTION");
+    const char *pszProjection = GetAttrValue("PROJECTION");
 
 /* -------------------------------------------------------------------- */
 /*      Fill all projection parameters with zero.                       */
 /* -------------------------------------------------------------------- */
-    int     i;
-
     *piDatum = 0L;
     *piEllips = 0L;
     *piZone = 0L;
-    for ( i = 0; i < 7; i++ )
+    for( int i = 0; i < 7; i++ )
         padfPrjParams[i] = 0.0;
 
 /* ==================================================================== */
 /*      Handle the projection definition.                               */
 /* ==================================================================== */
     if( IsLocal() )
+    {
         *piProjSys = PAN_PROJ_NONE;
-
+    }
     else if( pszProjection == NULL )
     {
 #ifdef DEBUG
@@ -570,7 +580,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
 #endif
         *piProjSys = PAN_PROJ_NONE;
     }
-
     else if( EQUAL(pszProjection, SRS_PT_MERCATOR_1SP) )
     {
         *piProjSys = PAN_PROJ_MERCAT;
@@ -582,7 +591,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) )
     {
         *piProjSys = PAN_PROJ_PS;
@@ -594,7 +602,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_POLYCONIC) )
     {
         *piProjSys = PAN_PROJ_POLYC;
@@ -605,7 +612,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC) )
     {
         *piProjSys = PAN_PROJ_EC;
@@ -620,7 +626,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
     {
         *piProjSys = PAN_PROJ_LCC;
@@ -635,10 +640,9 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR) )
     {
-        int bNorth;
+        int bNorth = FALSE;
 
         *piZone = GetUTMZone( &bNorth );
 
@@ -663,14 +667,12 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
                 GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
         }
     }
-
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_I) )
     {
         *piProjSys = PAN_PROJ_WAG1;
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC) )
     {
         *piProjSys = PAN_PROJ_STEREO;
@@ -682,7 +684,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     {
         *piProjSys = PAN_PROJ_AE;
@@ -693,7 +694,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_GNOMONIC) )
     {
         *piProjSys = PAN_PROJ_GNOMON;
@@ -704,7 +704,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_MOLLWEIDE) )
     {
         *piProjSys = PAN_PROJ_MOLL;
@@ -713,7 +712,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
         *piProjSys = PAN_PROJ_LAEA;
@@ -724,7 +722,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR) )
     {
         *piProjSys = PAN_PROJ_EQC;
@@ -735,7 +732,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_CYLINDRICAL_EQUAL_AREA) )
     {
         *piProjSys = PAN_PROJ_CEA;
@@ -746,7 +742,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_IMW_POLYCONIC) )
     {
         *piProjSys = PAN_PROJ_IMWP;
@@ -759,7 +754,6 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         padfPrjParams[5] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         padfPrjParams[6] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     // Projection unsupported by "Panorama" GIS
     else
     {
@@ -772,14 +766,14 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
 /* -------------------------------------------------------------------- */
 /*      Translate the datum.                                            */
 /* -------------------------------------------------------------------- */
-    const char  *pszDatum = GetAttrValue( "DATUM" );
+    const char *pszDatum = GetAttrValue( "DATUM" );
 
-    if ( pszDatum == NULL )
+    if( pszDatum == NULL )
     {
         *piDatum = PAN_DATUM_NONE;
         *piEllips = PAN_ELLIPSOID_NONE;
     }
-    else if ( EQUAL( pszDatum, "Pulkovo_1942" ) )
+    else if( EQUAL( pszDatum, "Pulkovo_1942" ) )
     {
         *piDatum = PAN_DATUM_PULKOVO42;
         *piEllips = PAN_ELLIPSOID_KRASSOVSKY;
@@ -790,11 +784,11 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
         *piEllips = PAN_ELLIPSOID_WGS84;
     }
 
-    // If not found well known datum, translate ellipsoid
+    // If not found well known datum, translate ellipsoid.
     else
     {
-        double      dfSemiMajor = GetSemiMajor();
-        double      dfInvFlattening = GetInvFlattening();
+        const double dfSemiMajor = GetSemiMajor();
+        const double dfInvFlattening = GetInvFlattening();
 
 #ifdef DEBUG
         CPLDebug( "OSR_Panorama",
@@ -802,17 +796,18 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
                   "Trying to translate an ellipsoid definition.", pszDatum );
 #endif
 
-        for ( i = 0; i < NUMBER_OF_ELLIPSOIDS; i++ )
+        int i = 0;  // Used after for.
+        for( ; i < NUMBER_OF_ELLIPSOIDS; i++ )
         {
-            if ( aoEllips[i] )
+            if( aoEllips[i] )
             {
-                double  dfSM = 0.0;
-                double  dfIF = 1.0;
+                double dfSM = 0.0;
+                double dfIF = 1.0;
 
-                if ( OSRGetEllipsoidInfo( aoEllips[i], NULL,
-                                          &dfSM, &dfIF ) == OGRERR_NONE
-                     && CPLIsEqual(dfSemiMajor, dfSM)
-                     && CPLIsEqual(dfInvFlattening, dfIF) )
+                if( OSRGetEllipsoidInfo( aoEllips[i], NULL,
+                                         &dfSM, &dfIF ) == OGRERR_NONE
+                    && CPLIsEqual(dfSemiMajor, dfSM)
+                    && CPLIsEqual(dfInvFlattening, dfIF) )
                 {
                     *piEllips = i;
                     break;
@@ -820,7 +815,7 @@ OGRErr OGRSpatialReference::exportToPanorama( long *piProjSys, long *piDatum,
             }
         }
 
-        if ( i == NUMBER_OF_ELLIPSOIDS )    // Didn't found matches.
+        if( i == NUMBER_OF_ELLIPSOIDS )  // Didn't found matches.
         {
 #ifdef DEBUG
             CPLDebug( "OSR_Panorama",
diff --git a/ogr/ogr_srs_pci.cpp b/ogr/ogr_srs_pci.cpp
index 3af8cfa..a4a8c2d 100644
--- a/ogr/ogr_srs_pci.cpp
+++ b/ogr/ogr_srs_pci.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_pci.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from PCI georeferencing
@@ -29,17 +28,32 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
-#include "ogr_p.h"
+#include "cpl_port.h"
+#include "ogr_srs_api.h"
+
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
 #include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogr_srs_pci.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogr_srs_pci.cpp 37248 2017-01-31 02:17:16Z goatbar $");
+
+// PCI uses a 16-character string for coordinate system and datum/ellipsoid.
+static const int knProjSize = 16;
 
 typedef struct
 {
-    const char  *pszPCIDatum;
-    int         nEPSGCode;
+    const char *pszPCIDatum;
+    int        nEPSGCode;
 } PCIDatums;
 
 static const PCIDatums asDatums[] =
@@ -195,8 +209,11 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 {
     Clear();
 
-    if( pszProj == NULL || CPLStrnlen(pszProj, 16) < 16 )
+    if( pszProj == NULL ||
+        CPLStrnlen(pszProj, knProjSize) < static_cast<size_t>(knProjSize) )
+    {
         return OGRERR_CORRUPT_DATA;
+    }
 
     CPLDebug( "OSR_PCI", "Trying to import projection \"%s\"", pszProj );
 
@@ -207,12 +224,10 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 
     if( padfPrjParams == NULL )
     {
-        int     i;
-
-        padfPrjParams = (double *)CPLMalloc( 17 * sizeof(double) );
-        if ( !padfPrjParams )
+        padfPrjParams = static_cast<double *>(CPLMalloc( 17 * sizeof(double) ));
+        if( !padfPrjParams )
             return OGRERR_NOT_ENOUGH_MEMORY;
-        for ( i = 0; i < 17; i++ )
+        for( int i = 0; i < 17; i++ )
             padfPrjParams[i] = 0.0;
         bProjAllocated = true;
     }
@@ -221,12 +236,10 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 /*      Extract and "normalize" the earthmodel to look like E001,       */
 /*      D-02 or D109.                                                   */
 /* -------------------------------------------------------------------- */
-    char szEarthModel[5];
-    const char *pszEM;
-    int bIsNAD27 = FALSE;
+    char szEarthModel[5] = {};
 
     strcpy( szEarthModel, "" );
-    pszEM = pszProj + strlen(pszProj) - 1;
+    const char *pszEM = pszProj + strlen(pszProj) - 1;
     while( pszEM != pszProj )
     {
         if( *pszEM == 'e' || *pszEM == 'E' || *pszEM == 'd' || *pszEM == 'D' )
@@ -234,7 +247,8 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             int nCode = atoi(pszEM+1);
 
             if( nCode >= -99 && nCode <= 999 )
-                snprintf( szEarthModel, sizeof(szEarthModel), "%c%03d", toupper(*pszEM), nCode );
+                snprintf( szEarthModel, sizeof(szEarthModel),
+                          "%c%03d", toupper(*pszEM), nCode );
 
             break;
         }
@@ -242,63 +256,58 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
         pszEM--;
     }
 
-    if( EQUAL(pszEM,"E000")
-        || EQUAL(pszEM,"D-01")
-        || EQUAL(pszEM,"D-03")
-        || EQUAL(pszEM,"D-07")
-        || EQUAL(pszEM,"D-09")
-        || EQUAL(pszEM,"D-11")
-        || EQUAL(pszEM,"D-13")
-        || EQUAL(pszEM,"D-17") )
-        bIsNAD27 = TRUE;
+    const bool bIsNAD27 =
+        EQUAL(pszEM, "E000")
+        || EQUAL(pszEM, "D-01")
+        || EQUAL(pszEM, "D-03")
+        || EQUAL(pszEM, "D-07")
+        || EQUAL(pszEM, "D-09")
+        || EQUAL(pszEM, "D-11")
+        || EQUAL(pszEM, "D-13")
+        || EQUAL(pszEM, "D-17");
+
 
 /* -------------------------------------------------------------------- */
 /*      Operate on the basis of the projection name.                    */
 /* -------------------------------------------------------------------- */
     if( STARTS_WITH_CI(pszProj, "LONG/LAT") )
     {
+        // TODO(schwehr): A NOP is okay?
     }
-
     else if( STARTS_WITH_CI(pszProj, "METER")
              || STARTS_WITH_CI(pszProj, "METRE") )
     {
         SetLocalCS( "METER" );
         SetLinearUnits( "METER", 1.0 );
     }
-
     else if( STARTS_WITH_CI(pszProj, "FEET")
              || STARTS_WITH_CI(pszProj, "FOOT") )
     {
         SetLocalCS( "FEET" );
         SetLinearUnits( "FEET", CPLAtof(SRS_UL_FOOT_CONV) );
     }
-
     else if( STARTS_WITH_CI(pszProj, "ACEA") )
     {
         SetACEA( padfPrjParams[4], padfPrjParams[5],
                  padfPrjParams[3], padfPrjParams[2],
                  padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "AE") )
     {
         SetAE( padfPrjParams[3], padfPrjParams[2],
                padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "CASS ") )
     {
         SetCS( padfPrjParams[3], padfPrjParams[2],
                padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "EC") )
     {
         SetEC( padfPrjParams[4], padfPrjParams[5],
                padfPrjParams[3], padfPrjParams[2],
                padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "ER") )
     {
         // PCI and GCTP don't support natural origin lat.
@@ -306,56 +315,46 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                              padfPrjParams[3],
                              padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "GNO") )
     {
         SetGnomonic( padfPrjParams[3], padfPrjParams[2],
                      padfPrjParams[6], padfPrjParams[7] );
     }
-
-    // FIXME: GVNP --- General Vertical Near- Side Perspective skipped
-
-    // FIXME: GOOD -- our Goode's is not the interrupted version from pci
-
+    // FIXME: GVNP --- General Vertical Near- Side Perspective skipped.
+    // FIXME: GOOD -- Our Goode's is not the interrupted version from PCI.
     else if( STARTS_WITH_CI(pszProj, "LAEA") )
     {
         SetLAEA( padfPrjParams[3], padfPrjParams[2],
                  padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "LCC ") )
     {
         SetLCC( padfPrjParams[4], padfPrjParams[5],
                 padfPrjParams[3], padfPrjParams[2],
                 padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "LCC_1SP ") )
     {
         SetLCC1SP( padfPrjParams[3], padfPrjParams[2],
                    padfPrjParams[8],
                    padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "MC") )
     {
         SetMC( padfPrjParams[3], padfPrjParams[2],
                padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "MER") )
     {
         SetMercator( padfPrjParams[3], padfPrjParams[2],
                      (padfPrjParams[8] != 0.0) ? padfPrjParams[8] : 1.0,
                      padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "OG") )
     {
         SetOrthographic( padfPrjParams[3], padfPrjParams[2],
                          padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "OM ") )
     {
         if( padfPrjParams[10] == 0.0
@@ -365,7 +364,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
         {
             SetHOM( padfPrjParams[3], padfPrjParams[2],
                     padfPrjParams[14],
-                    padfPrjParams[14], // use azimuth for grid angle
+                    padfPrjParams[14], // Use azimuth for grid angle.
                     padfPrjParams[8],
                     padfPrjParams[6], padfPrjParams[7] );
         }
@@ -378,20 +377,17 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                         padfPrjParams[6], padfPrjParams[7] );
         }
     }
-
     else if( STARTS_WITH_CI(pszProj, "PC") )
     {
         SetPolyconic( padfPrjParams[3], padfPrjParams[2],
                       padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "PS") )
     {
         SetPS( padfPrjParams[3], padfPrjParams[2],
                (padfPrjParams[8] != 0.0) ? padfPrjParams[8] : 1.0,
                padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "ROB") )
     {
         SetRobinson( padfPrjParams[2],
@@ -404,54 +400,44 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                (padfPrjParams[8] != 0.0) ? padfPrjParams[8] : 1.0,
                padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "SG") )
     {
         SetStereographic( padfPrjParams[3], padfPrjParams[2],
                           (padfPrjParams[8] != 0.0) ? padfPrjParams[8] : 1.0,
                           padfPrjParams[6], padfPrjParams[7] );
     }
-
     else if( STARTS_WITH_CI(pszProj, "SIN") )
     {
         SetSinusoidal( padfPrjParams[2],
                        padfPrjParams[6], padfPrjParams[7] );
     }
-
-    // FIXME: SOM --- Space Oblique Mercator skipped
-
+    // FIXME: SOM --- Space Oblique Mercator skipped.
     else if( STARTS_WITH_CI(pszProj, "SPCS") )
     {
-        int     iZone;
-
-        iZone = (int)CPLScanLong( (char *)pszProj + 5, 4 );
+        const int iZone =
+            static_cast<int>(CPLScanLong( const_cast<char *>(pszProj) + 5, 4 ));
 
         SetStatePlane( iZone, !bIsNAD27 );
         SetLinearUnitsAndUpdateParameters( SRS_UL_METER, 1.0 );
     }
-
     else if( STARTS_WITH_CI(pszProj, "SPIF") )
     {
-        int     iZone;
-
-        iZone = (int)CPLScanLong( (char *)pszProj + 5, 4 );
+        const int iZone =
+            static_cast<int>(CPLScanLong( const_cast<char *>(pszProj) + 5, 4 ));
 
         SetStatePlane( iZone, !bIsNAD27 );
         SetLinearUnitsAndUpdateParameters( SRS_UL_FOOT,
                                            CPLAtof(SRS_UL_FOOT_CONV) );
     }
-
     else if( STARTS_WITH_CI(pszProj, "SPAF") )
     {
-        int     iZone;
-
-        iZone = (int)CPLScanLong( (char *)pszProj + 5, 4 );
+        const int iZone =
+            static_cast<int>(CPLScanLong( const_cast<char *>(pszProj) + 5, 4 ));
 
         SetStatePlane( iZone, !bIsNAD27 );
         SetLinearUnitsAndUpdateParameters( SRS_UL_US_FOOT,
                                            CPLAtof(SRS_UL_US_FOOT_CONV) );
     }
-
     else if( STARTS_WITH_CI(pszProj, "TM") )
     {
         SetTM( padfPrjParams[3], padfPrjParams[2],
@@ -461,52 +447,51 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 
     else if( STARTS_WITH_CI(pszProj, "UTM") )
     {
-        int     iZone, bNorth = TRUE;
+        bool bNorth = true;
 
-        iZone = (int)CPLScanLong( (char *)pszProj + 4, 5 );;
-        if ( iZone < 0 )
+        int iZone =
+            static_cast<int>(CPLScanLong( const_cast<char *>(pszProj) + 4, 5 ));
+        if( iZone < 0 )
         {
             iZone = -iZone;
-            bNorth = FALSE;
+            bNorth = false;
         }
 
         // Check for a zone letter. PCI uses, accidentally, MGRS
-        // type row lettering in its UTM projection
+        // type row lettering in its UTM projection.
         char byZoneID = 0;
 
         if( strlen(pszProj) > 10 && pszProj[10] != ' ' )
             byZoneID = pszProj[10];
 
-        // Determine if the MGRS zone falls above or below the equator
-        if (byZoneID != 0 )
+        // Determine if the MGRS zone falls above or below the equator.
+        if( byZoneID != 0 )
         {
             CPLDebug("OSR_PCI", "Found MGRS zone in UTM projection string: %c",
-                byZoneID);
+                     byZoneID);
 
-            if (byZoneID >= 'N' && byZoneID <= 'X')
+            if( byZoneID >= 'N' && byZoneID <= 'X' )
             {
-                bNorth = TRUE;
+                bNorth = true;
             }
-            else if (byZoneID >= 'C' && byZoneID <= 'M')
+            else if( byZoneID >= 'C' && byZoneID <= 'M' )
             {
-                bNorth = FALSE;
+                bNorth = false;
             }
             else
             {
-                // yikes, most likely we got something that was not really
+                // Yikes.  Most likely we got something that was not really
                 // an MGRS zone code so we ignore it.
             }
         }
 
         SetUTM( iZone, bNorth );
     }
-
     else if( STARTS_WITH_CI(pszProj, "VDG") )
     {
         SetVDG( padfPrjParams[2],
                 padfPrjParams[6], padfPrjParams[7] );
     }
-
     else
     {
         CPLDebug( "OSR_PCI", "Unsupported projection: %s", pszProj );
@@ -523,10 +508,10 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
     if( strlen(szEarthModel) > 0
         && (poRoot == NULL || IsProjected() || IsGeographic()) )
     {
-        const PCIDatums   *pasDatum = asDatums;
+        const PCIDatums *pasDatum = asDatums;
 
-        // Search for matching datum
-        while ( pasDatum->pszPCIDatum )
+        // Search for matching datum.
+        while( pasDatum->pszPCIDatum )
         {
             if( EQUALN( szEarthModel, pasDatum->pszPCIDatum, 4 ) )
             {
@@ -548,52 +533,51 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
         if( !pasDatum->pszPCIDatum && szEarthModel[0] == 'D' )
         {
             const char *pszDatumCSV = CSVFilename( "pci_datum.txt" );
-            FILE *fp = NULL;
-
-            if( pszDatumCSV )
-                fp = VSIFOpen( pszDatumCSV, "r" );
+            VSILFILE *fp = pszDatumCSV ? VSIFOpenL( pszDatumCSV, "r" ) : NULL;
 
             if( fp != NULL )
             {
                 char **papszLineItems = NULL;
 
-                while( (papszLineItems = CSVReadParseLine( fp )) != NULL )
+                while( (papszLineItems = CSVReadParseLineL( fp )) != NULL )
                 {
                     if( CSLCount(papszLineItems) > 3
-                        && EQUALN(papszLineItems[0],szEarthModel,4) )
+                        && EQUALN(papszLineItems[0], szEarthModel,
+                                  sizeof(szEarthModel)-1) )
                     {
                         papszDatumDefn = papszLineItems;
-                        strncpy( szEarthModel, papszLineItems[2], 4 );
+                        strncpy( szEarthModel, papszLineItems[2],
+                                 sizeof(szEarthModel)-1 );
                         break;
                     }
                     CSLDestroy( papszLineItems );
                 }
 
-                VSIFClose( fp );
+                VSIFCloseL( fp );
             }
         }
 
 /* -------------------------------------------------------------------- */
 /*      If not, look in the ellipsoid/EPSG matching list.               */
 /* -------------------------------------------------------------------- */
-        if ( !pasDatum->pszPCIDatum )  // No matching; search for ellipsoids
+        if( !pasDatum->pszPCIDatum )  // No matching; search for ellipsoids.
         {
-            char    *pszName = NULL;
-            double  dfSemiMajor = 0.0;
-            double  dfInvFlattening = 0.0;
-            int     nEPSGCode = 0;
+            char *pszName = NULL;
+            double dfSemiMajor = 0.0;
+            double dfInvFlattening = 0.0;
+            int nEPSGCode = 0;
 
             pasDatum = asEllips;
 
-            while ( pasDatum->pszPCIDatum )
+            while( pasDatum->pszPCIDatum )
             {
                 if( EQUALN( szEarthModel, pasDatum->pszPCIDatum, 4 ) )
                 {
                     nEPSGCode = pasDatum->nEPSGCode;
-                    CPL_IGNORE_RET_VAL(OSRGetEllipsoidInfo( pasDatum->nEPSGCode, &pszName,
-                                         &dfSemiMajor, &dfInvFlattening ));
+                    CPL_IGNORE_RET_VAL(
+                        OSRGetEllipsoidInfo( pasDatum->nEPSGCode, &pszName,
+                                             &dfSemiMajor, &dfInvFlattening ));
                     break;
-
                 }
                 pasDatum++;
             }
@@ -605,30 +589,29 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             if( !pasDatum->pszPCIDatum && szEarthModel[0] == 'E' )
             {
                 const char *pszCSV = CSVFilename( "pci_ellips.txt" );
-                FILE *fp = NULL;
-
-                if( pszCSV )
-                    fp = VSIFOpen( pszCSV, "r" );
+                VSILFILE *fp = pszCSV ? VSIFOpenL( pszCSV, "r" ) : NULL;
 
                 if( fp != NULL )
                 {
                     char **papszLineItems = NULL;
 
-                    while( (papszLineItems = CSVReadParseLine( fp )) != NULL )
+                    while( (papszLineItems = CSVReadParseLineL( fp )) != NULL )
                     {
                         if( CSLCount(papszLineItems) > 3
-                            && EQUALN(papszLineItems[0],szEarthModel,4) )
+                            && EQUALN(papszLineItems[0], szEarthModel, 4) )
                         {
                             dfSemiMajor = CPLAtof( papszLineItems[2] );
-                            double dfSemiMinor = CPLAtof( papszLineItems[3] );
-                            dfInvFlattening = OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
+                            const double dfSemiMinor =
+                                CPLAtof( papszLineItems[3] );
+                            dfInvFlattening =
+                                OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
                             break;
                         }
                         CSLDestroy( papszLineItems );
                     }
                     CSLDestroy( papszLineItems );
 
-                    VSIFClose( fp );
+                    VSIFCloseL( fp );
                 }
             }
 
@@ -640,7 +623,8 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
             {
                 dfSemiMajor = padfPrjParams[0];
                 double dfSemiMinor = padfPrjParams[1];
-                dfInvFlattening = OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
+                dfInvFlattening =
+                    OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
             }
 
 /* -------------------------------------------------------------------- */
@@ -655,19 +639,21 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 /* -------------------------------------------------------------------- */
 /*      Now try to put this all together into a GEOGCS definition.      */
 /* -------------------------------------------------------------------- */
-            CPLString osGCSName, osDatumName, osEllipseName;
 
+            CPLString osEllipseName;
             if( pszName )
                 osEllipseName = pszName;
             else
                 osEllipseName.Printf( "Unknown - PCI %s", szEarthModel );
             CPLFree( pszName );
 
+            CPLString osDatumName;
             if( papszDatumDefn )
                 osDatumName = papszDatumDefn[1];
             else
                 osDatumName.Printf( "Unknown - PCI %s", szEarthModel );
-            osGCSName = osDatumName;
+
+            const CPLString osGCSName = osDatumName;
 
             SetGeogCS( osGCSName, osDatumName, osEllipseName,
                        dfSemiMajor, dfInvFlattening );
@@ -686,7 +672,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
                 // we want scale in parts per million off 1.0
                 // but pci uses a mix of forms.
                 if( dfScale >= 0.999 && dfScale <= 1.001 )
-                    dfScale = (dfScale-1.0) * 1000000.0;
+                    dfScale = (dfScale - 1.0) * 1000000.0;
 
                 SetTOWGS84( CPLAtof(papszDatumDefn[3]),
                             CPLAtof(papszDatumDefn[4]),
@@ -728,7 +714,7 @@ OGRErr OGRSpatialReference::importFromPCI( const char *pszProj,
 
     FixupOrdering();
 
-    if ( bProjAllocated && padfPrjParams )
+    if( bProjAllocated && padfPrjParams )
         CPLFree( padfPrjParams );
 
     return OGRERR_NONE;
@@ -791,15 +777,13 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
                                          double **ppadfPrjParams ) const
 
 {
-    const char  *pszProjection = GetAttrValue("PROJECTION");
+    const char *pszProjection = GetAttrValue("PROJECTION");
 
 /* -------------------------------------------------------------------- */
 /*      Fill all projection parameters with zero.                       */
 /* -------------------------------------------------------------------- */
-    int         i;
-
-    *ppadfPrjParams = (double *)CPLMalloc( 17 * sizeof(double) );
-    for ( i = 0; i < 17; i++ )
+    *ppadfPrjParams = static_cast<double *>(CPLMalloc( 17 * sizeof(double) ));
+    for( int i = 0; i < 17; i++ )
         (*ppadfPrjParams)[i] = 0.0;
 
 /* -------------------------------------------------------------------- */
@@ -819,26 +803,22 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
 /* ==================================================================== */
 /*      Handle the projection definition.                               */
 /* ==================================================================== */
-    char        szProj[17];
-
-    memset( szProj, 0, sizeof(szProj) );
+    char szProj[knProjSize + 1] = {};
 
     if( IsLocal() )
     {
         if( GetLinearUnits() > 0.30479999 && GetLinearUnits() < 0.3048010 )
-            CPLPrintStringFill( szProj, "FEET", 17 );
+            CPLPrintStringFill( szProj, "FEET", knProjSize );
         else
-            CPLPrintStringFill( szProj, "METER", 17 );
+            CPLPrintStringFill( szProj, "METER", knProjSize );
     }
-
     else if( pszProjection == NULL )
     {
-        CPLPrintStringFill( szProj, "LONG/LAT", 16 );
+        CPLPrintStringFill( szProj, "LONG/LAT", knProjSize );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
     {
-        CPLPrintStringFill( szProj, "ACEA", 16 );
+        CPLPrintStringFill( szProj, "ACEA", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
@@ -849,30 +829,27 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT) )
     {
-        CPLPrintStringFill( szProj, "AE", 16 );
+        CPLPrintStringFill( szProj, "AE", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_CASSINI_SOLDNER) )
     {
-        CPLPrintStringFill( szProj, "CASS", 16 );
+        CPLPrintStringFill( szProj, "CASS", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC) )
     {
-        CPLPrintStringFill( szProj, "EC", 16 );
+        CPLPrintStringFill( szProj, "EC", knProjSize );
         (*ppadfPrjParams)[2] =
             GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 );
         (*ppadfPrjParams)[3] =
@@ -884,40 +861,36 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR) )
     {
-        CPLPrintStringFill( szProj, "ER", 16 );
+        CPLPrintStringFill( szProj, "ER", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_GNOMONIC) )
     {
-        CPLPrintStringFill( szProj, "GNO", 16 );
+        CPLPrintStringFill( szProj, "GNO", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
     {
-        CPLPrintStringFill( szProj, "LAEA", 16 );
+        CPLPrintStringFill( szProj, "LAEA", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP) )
     {
-        CPLPrintStringFill( szProj, "LCC", 16 );
+        CPLPrintStringFill( szProj, "LCC", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
@@ -928,10 +901,9 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
     {
-        CPLPrintStringFill( szProj, "LCC_1SP", 16 );
+        CPLPrintStringFill( szProj, "LCC_1SP", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
@@ -939,20 +911,18 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_MILLER_CYLINDRICAL) )
     {
-        CPLPrintStringFill( szProj, "MC", 16 );
+        CPLPrintStringFill( szProj, "MC", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_MERCATOR_1SP) )
     {
-        CPLPrintStringFill( szProj, "MER", 16 );
+        CPLPrintStringFill( szProj, "MER", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
@@ -960,55 +930,56 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
         (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_ORTHOGRAPHIC) )
     {
-        CPLPrintStringFill( szProj, "OG", 16 );
+        CPLPrintStringFill( szProj, "OG", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
     {
-        CPLPrintStringFill( szProj, "OM", 16 );
-        (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER,0.0);
+        CPLPrintStringFill( szProj, "OM", knProjSize );
+        (*ppadfPrjParams)[2] =
+            GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0);
         (*ppadfPrjParams)[3] = GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0);
         (*ppadfPrjParams)[14] = GetNormProjParm( SRS_PP_AZIMUTH, 0.0);
-        // note we are ignoring rectified_grid_angle which has no pci analog.
+        // Note: Ignoring rectified_grid_angle which has no PCI analog.
         (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 0.0);
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
-    else if( EQUAL(pszProjection, SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
+    else if( EQUAL(pszProjection,
+                   SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
     {
-        CPLPrintStringFill( szProj, "OM", 16 );
+        CPLPrintStringFill( szProj, "OM", knProjSize );
         (*ppadfPrjParams)[3] = GetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, 0.0);
-        (*ppadfPrjParams)[11] = GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1,0.0);
-        (*ppadfPrjParams)[10] = GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1,0.0);
-        (*ppadfPrjParams)[13] = GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2,0.0);
-        (*ppadfPrjParams)[12] = GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2,0.0);
+        (*ppadfPrjParams)[11] =
+            GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1, 0.0);
+        (*ppadfPrjParams)[10] =
+            GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1, 0.0);
+        (*ppadfPrjParams)[13] =
+            GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2, 0.0);
+        (*ppadfPrjParams)[12] =
+            GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2, 0.0);
         (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 0.0);
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_POLYCONIC) )
     {
-        CPLPrintStringFill( szProj, "PC", 16 );
+        CPLPrintStringFill( szProj, "PC", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) )
     {
-        CPLPrintStringFill( szProj, "PS", 16 );
+        CPLPrintStringFill( szProj, "PS", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
@@ -1016,18 +987,16 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
         (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_ROBINSON) )
     {
-        CPLPrintStringFill( szProj, "ROB", 16 );
+        CPLPrintStringFill( szProj, "ROB", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_OBLIQUE_STEREOGRAPHIC) )
     {
-        CPLPrintStringFill( szProj, "SGDO", 16 );
+        CPLPrintStringFill( szProj, "SGDO", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
@@ -1035,10 +1004,9 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
         (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC) )
     {
-        CPLPrintStringFill( szProj, "SG", 16 );
+        CPLPrintStringFill( szProj, "SG", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[3] =
             GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 );
@@ -1046,24 +1014,22 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
         (*ppadfPrjParams)[8] = GetNormProjParm( SRS_PP_SCALE_FACTOR, 1.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_SINUSOIDAL) )
     {
-        CPLPrintStringFill( szProj, "SIN", 16 );
+        CPLPrintStringFill( szProj, "SIN", knProjSize );
         (*ppadfPrjParams)[2] =
             GetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR) )
     {
-        int bNorth;
+        int bNorth = FALSE;
         int nZone = GetUTMZone( &bNorth );
 
         if( nZone != 0 )
         {
-            CPLPrintStringFill( szProj, "UTM", 16 );
+            CPLPrintStringFill( szProj, "UTM", knProjSize );
             if( bNorth )
                 CPLPrintInt32( szProj + 5, nZone, 4 );
             else
@@ -1071,7 +1037,7 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
         }
         else
         {
-            CPLPrintStringFill( szProj, "TM", 16 );
+            CPLPrintStringFill( szProj, "TM", knProjSize );
             (*ppadfPrjParams)[2] =
                 GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
             (*ppadfPrjParams)[3] =
@@ -1081,22 +1047,20 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
             (*ppadfPrjParams)[8] = GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0);
         }
     }
-
     else if( EQUAL(pszProjection, SRS_PT_VANDERGRINTEN) )
     {
-        CPLPrintStringFill( szProj, "VDG", 16 );
+        CPLPrintStringFill( szProj, "VDG", knProjSize );
         (*ppadfPrjParams)[2] = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0 );
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
-    // Projection unsupported by PCI
+    // Projection unsupported by PCI.
     else
     {
         CPLDebug( "OSR_PCI",
                   "Projection \"%s\" unsupported by PCI. "
                   "PIXEL value will be used.", pszProjection );
-        CPLPrintStringFill( szProj, "PIXEL", 16 );
+        CPLPrintStringFill( szProj, "PIXEL", knProjSize );
     }
 
 /* ==================================================================== */
@@ -1106,21 +1070,25 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
 /* -------------------------------------------------------------------- */
 /*      Is this a well known datum?                                     */
 /* -------------------------------------------------------------------- */
-    const char  *pszDatum = GetAttrValue( "DATUM" );
-    char szEarthModel[5];
-
-    memset( szEarthModel, 0, sizeof(szEarthModel) );
+    const char *pszDatum = GetAttrValue( "DATUM" );
+    char szEarthModel[5] = {};
 
     if( pszDatum == NULL || strlen(pszDatum) == 0 )
-        /* do nothing */;
+    {
+        // Do nothing.
+    }
     else if( EQUAL( pszDatum, SRS_DN_NAD27 ) )
+    {
         CPLPrintStringFill( szEarthModel, "D-01", 4 );
-
+    }
     else if( EQUAL( pszDatum, SRS_DN_NAD83 ) )
+    {
         CPLPrintStringFill( szEarthModel, "D-02", 4 );
-
+    }
     else if( EQUAL( pszDatum, SRS_DN_WGS84 ) )
+    {
         CPLPrintStringFill( szEarthModel, "D000", 4 );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      If not a very well known datum, try for an EPSG based           */
@@ -1130,15 +1098,16 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
     {
         const char *pszAuthority = GetAuthorityName("GEOGCS");
 
-        if( pszAuthority && EQUAL(pszAuthority,"EPSG") )
+        if( pszAuthority && EQUAL(pszAuthority, "EPSG") )
         {
-            int nGCS_EPSG = atoi(GetAuthorityCode("GEOGCS"));
+            const int nGCS_EPSG = atoi(GetAuthorityCode("GEOGCS"));
 
-            for( i = 0; asDatums[i].nEPSGCode != 0; i++ )
+            for( int i = 0; asDatums[i].nEPSGCode != 0; i++ )
             {
                 if( asDatums[i].nEPSGCode == nGCS_EPSG )
                 {
-                    strncpy( szEarthModel, asDatums[i].pszPCIDatum, 5 );
+                    snprintf( szEarthModel, sizeof(szEarthModel), "%s",
+                              asDatums[i].pszPCIDatum );
                     break;
                 }
             }
@@ -1151,20 +1120,20 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
 /* -------------------------------------------------------------------- */
     if( szEarthModel[0] == '\0' )
     {
-        double      dfSemiMajor = GetSemiMajor();
-        double      dfInvFlattening = GetInvFlattening();
+        const double dfSemiMajor = GetSemiMajor();
+        const double dfInvFlattening = GetInvFlattening();
 
-        const PCIDatums   *pasDatum = asEllips;
+        const PCIDatums *pasDatum = asEllips;
 
-        while ( pasDatum->pszPCIDatum )
+        while( pasDatum->pszPCIDatum )
         {
-            double  dfSM;
-            double  dfIF;
+            double dfSM = 0.0;
+            double dfIF = 0.0;
 
-            if ( OSRGetEllipsoidInfo( pasDatum->nEPSGCode, NULL,
-                                      &dfSM, &dfIF ) == OGRERR_NONE
-                 && CPLIsEqual( dfSemiMajor, dfSM )
-                 && CPLIsEqual( dfInvFlattening, dfIF ) )
+            if( OSRGetEllipsoidInfo( pasDatum->nEPSGCode, NULL,
+                                     &dfSM, &dfIF ) == OGRERR_NONE
+                && CPLIsEqual( dfSemiMajor, dfSM )
+                && CPLIsEqual( dfInvFlattening, dfIF ) )
             {
                 CPLPrintStringFill( szEarthModel, pasDatum->pszPCIDatum, 4 );
                 break;
@@ -1173,28 +1142,27 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
             pasDatum++;
         }
 
-        // Try to find in pci_ellips.txt
+        // Try to find in pci_ellips.txt.
         if( szEarthModel[0] == '\0' )
         {
             const char *pszCSV = CSVFilename( "pci_ellips.txt" );
-            FILE *fp = NULL;
-            double dfSemiMinor = OSRCalcSemiMinorFromInvFlattening(dfSemiMajor, dfInvFlattening);
+            const double dfSemiMinor =
+                OSRCalcSemiMinorFromInvFlattening(dfSemiMajor, dfInvFlattening);
 
-            if( pszCSV )
-                fp = VSIFOpen( pszCSV, "r" );
+            VSILFILE *fp = pszCSV ? VSIFOpenL( pszCSV, "r" ) : NULL;
 
             if( fp != NULL )
             {
                 char **papszLineItems = NULL;
 
-                while( (papszLineItems = CSVReadParseLine( fp )) != NULL )
+                while( (papszLineItems = CSVReadParseLineL( fp )) != NULL )
                 {
                     if( CSLCount(papszLineItems) >= 4
-                        && CPLIsEqual(dfSemiMajor,CPLAtof(papszLineItems[2]))
-                        && CPLIsEqual(dfSemiMinor,CPLAtof(papszLineItems[3])) )
+                        && CPLIsEqual(dfSemiMajor, CPLAtof(papszLineItems[2]))
+                        && CPLIsEqual(dfSemiMinor, CPLAtof(papszLineItems[3])) )
                     {
-                        strncpy( szEarthModel, papszLineItems[0], 5 );
-                        szEarthModel[4] = '\0';
+                        snprintf( szEarthModel, sizeof(szEarthModel), "%s",
+                                  papszLineItems[0] );
                         break;
                     }
 
@@ -1202,16 +1170,17 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
                 }
 
                 CSLDestroy( papszLineItems );
-                VSIFClose( fp );
+                VSIFCloseL( fp );
             }
         }
 
-        // custom ellipsoid parameters
+        // Custom ellipsoid parameters.
         if( szEarthModel[0] == '\0' )
         {
             CPLPrintStringFill( szEarthModel, "E999", 4 );
             (*ppadfPrjParams)[0] = dfSemiMajor;
-            (*ppadfPrjParams)[1] = OSRCalcSemiMinorFromInvFlattening(dfSemiMajor, dfInvFlattening);
+            (*ppadfPrjParams)[1] =
+                OSRCalcSemiMinorFromInvFlattening(dfSemiMajor, dfInvFlattening);
         }
     }
 
@@ -1220,77 +1189,77 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
 /*      pci_datum.txt for a match.                                      */
 /* -------------------------------------------------------------------- */
     if( szEarthModel[0] == 'E'
-        && !EQUAL(szEarthModel,"E999")
+        && !EQUAL(szEarthModel, "E999")
         && pszDatum != NULL )
     {
         const char *pszDatumCSV = CSVFilename( "pci_datum.txt" );
-        FILE *fp = NULL;
-        double adfTOWGS84[7];
-        int    bHaveTOWGS84;
-
-        bHaveTOWGS84 = (GetTOWGS84( adfTOWGS84, 7 ) == OGRERR_NONE);
+        double adfTOWGS84[7] = {};
+        const bool bHaveTOWGS84 = GetTOWGS84(adfTOWGS84, 7) == OGRERR_NONE;
 
-        if( pszDatumCSV )
-            fp = VSIFOpen( pszDatumCSV, "r" );
+        VSILFILE *fp = pszDatumCSV ? VSIFOpenL( pszDatumCSV, "r" ) : NULL;
 
         if( fp != NULL )
         {
             char **papszLineItems = NULL;
 
-            while( (papszLineItems = CSVReadParseLine( fp )) != NULL )
+            while( (papszLineItems = CSVReadParseLineL( fp )) != NULL )
             {
                 // Compare based on datum name.  This is mostly for
                 // PCI round-tripping.  We won't usually get exact matches
                 // from other sources.
                 if( CSLCount(papszLineItems) > 3
-                    && EQUAL(papszLineItems[1],pszDatum)
-                    && EQUAL(papszLineItems[2],szEarthModel) )
+                    && EQUAL(papszLineItems[1], pszDatum)
+                    && EQUAL(papszLineItems[2], szEarthModel) )
                 {
-                    strncpy( szEarthModel, papszLineItems[0], 5 );
-                    szEarthModel[4] = '\0';
+                    snprintf( szEarthModel, sizeof(szEarthModel), "%s",
+                              papszLineItems[0] );
                     break;
                 }
 
-                int bTOWGS84Match = bHaveTOWGS84;
+                bool bTOWGS84Match = bHaveTOWGS84;
 
                 if( CSLCount(papszLineItems) < 11 )
-                    bTOWGS84Match = FALSE;
+                    bTOWGS84Match = false;
 
                 if( bTOWGS84Match
-                    && (!CPLIsEqual(adfTOWGS84[0],CPLAtof(papszLineItems[3]))
-                        || !CPLIsEqual(adfTOWGS84[1],CPLAtof(papszLineItems[4]))
-                        || !CPLIsEqual(adfTOWGS84[2],CPLAtof(papszLineItems[5]))))
-                    bTOWGS84Match = FALSE;
+                    && (!CPLIsEqual(adfTOWGS84[0], CPLAtof(papszLineItems[3]))
+                        || !CPLIsEqual(adfTOWGS84[1],
+                                       CPLAtof(papszLineItems[4]))
+                        || !CPLIsEqual(adfTOWGS84[2],
+                                       CPLAtof(papszLineItems[5]))))
+                    bTOWGS84Match = false;
 
                 if( bTOWGS84Match && CSLCount(papszLineItems) >= 15
-                    && (!CPLIsEqual(adfTOWGS84[3],CPLAtof(papszLineItems[11]))
-                        || !CPLIsEqual(adfTOWGS84[4],CPLAtof(papszLineItems[12]))
-                        || !CPLIsEqual(adfTOWGS84[5],CPLAtof(papszLineItems[13]))))
-                    bTOWGS84Match = FALSE;
+                    && (!CPLIsEqual(adfTOWGS84[3], CPLAtof(papszLineItems[11]))
+                        || !CPLIsEqual(adfTOWGS84[4],
+                                       CPLAtof(papszLineItems[12]))
+                        || !CPLIsEqual(adfTOWGS84[5],
+                                       CPLAtof(papszLineItems[13]))))
+                    bTOWGS84Match = false;
 
                 if( bTOWGS84Match && CSLCount(papszLineItems) >= 15 )
                 {
                     double dfScale = CPLAtof(papszLineItems[14]);
 
-                    // convert to parts per million if is a 1 based scaling.
+                    // Convert to parts per million if is a 1 based scaling.
                     if( dfScale >= 0.999 && dfScale <= 1.001 )
                         dfScale = (dfScale-1.0) * 1000000.0;
 
-                    if( !CPLIsEqual(adfTOWGS84[6],dfScale) )
-                        bTOWGS84Match = FALSE;
+                    if( !CPLIsEqual(adfTOWGS84[6], dfScale) )
+                        bTOWGS84Match = false;
                 }
 
                 if( bTOWGS84Match && CSLCount(papszLineItems) < 15
-                    && (!CPLIsEqual(adfTOWGS84[3],0.0)
-                        || !CPLIsEqual(adfTOWGS84[4],0.0)
-                        || !CPLIsEqual(adfTOWGS84[5],0.0)
-                        || !CPLIsEqual(adfTOWGS84[6],0.0)) )
-                    bTOWGS84Match = FALSE;
+                    && (!CPLIsEqual(adfTOWGS84[3], 0.0)
+                        || !CPLIsEqual(adfTOWGS84[4], 0.0)
+                        || !CPLIsEqual(adfTOWGS84[5], 0.0)
+                        || !CPLIsEqual(adfTOWGS84[6], 0.0)) )
+                    bTOWGS84Match = false;
 
                 if( bTOWGS84Match )
                 {
-                    strncpy( szEarthModel, papszLineItems[0], 5 );
-                    szEarthModel[4] = '\0';
+                    snprintf( szEarthModel, sizeof(szEarthModel), "%s",
+                              papszLineItems[0] );
                     break;
                 }
 
@@ -1298,28 +1267,24 @@ OGRErr OGRSpatialReference::exportToPCI( char **ppszProj, char **ppszUnits,
             }
 
             CSLDestroy( papszLineItems );
-            VSIFClose( fp );
+            VSIFCloseL( fp );
         }
     }
 
     CPLPrintStringFill( szProj + 12, szEarthModel, 4 );
 
-    CPLDebug( "OSR_PCI", "Translated as '%s'", szProj  );
+    CPLDebug( "OSR_PCI", "Translated as '%s'", szProj );
 
 /* -------------------------------------------------------------------- */
 /*      Translate the linear units.                                     */
 /* -------------------------------------------------------------------- */
-    const char  *pszUnits;
-
-    if( STARTS_WITH_CI(szProj, "LONG/LAT") )
-        pszUnits = "DEGREE";
-    else
-        pszUnits = "METRE";
+    const char *pszUnits =
+        STARTS_WITH_CI(szProj, "LONG/LAT") ? "DEGREE" : "METRE";
 
 /* -------------------------------------------------------------------- */
 /*      Report results.                                                 */
 /* -------------------------------------------------------------------- */
-    szProj[16] = '\0';
+    szProj[knProjSize] = '\0';
     *ppszProj = CPLStrdup( szProj );
 
     *ppszUnits = CPLStrdup( pszUnits );
diff --git a/ogr/ogr_srs_proj4.cpp b/ogr/ogr_srs_proj4.cpp
index 74941f4..2c750dc 100644
--- a/ogr/ogr_srs_proj4.cpp
+++ b/ogr/ogr_srs_proj4.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_proj4.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference interface to PROJ.4.
@@ -29,14 +28,28 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
-#include "ogr_p.h"
-#include "cpl_conv.h"
+#include "cpl_port.h"
+#include "ogr_srs_api.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+#include <string>
 #include <vector>
 
-extern int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform );
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogr_srs_proj4.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+extern
+int EPSGGetWGS84Transform( int nGeogCS, std::vector<CPLString>& asTransform );
+
+CPL_CVSID("$Id: ogr_srs_proj4.cpp 36850 2016-12-13 23:53:14Z rouault $");
 
 /* -------------------------------------------------------------------- */
 /*      The following list comes from osrs/proj/src/pj_ellps.c.         */
@@ -96,8 +109,8 @@ typedef struct
     int         nGCS;
 } OGRProj4Datum;
 
-/* Derived from proj/src/pj_datum.c */
-/* WGS84, NAD27 and NAD83 are directly hard-coded in the code */
+// Derived from proj/src/pj_datum.c.
+// WGS84, NAD27 and NAD83 are directly hard-coded in the code.
 static const OGRProj4Datum ogr_pj_datums[] = {
     { "GGRS87", "Greek_Geodetic_Reference_System_1987", 4121, 6121},
     { "potsdam", "Deutsches_Hauptdreiecksnetz", 4314, 6314},
@@ -116,7 +129,7 @@ typedef struct
     int         nPMCode;
 } OGRProj4PM;
 
-/* Derived from pj_datums.c */
+// Derived from pj_datums.c.
 static const OGRProj4PM ogr_pj_pms [] = {
     { "greenwich", "Greenwich", "0dE",               8901 },
     { "lisbon",    "Lisbon",    "9d07'54.862\"W",    8902 },
@@ -133,13 +146,13 @@ static const OGRProj4PM ogr_pj_pms [] = {
     { "oslo",      "Oslo",      "10d43'22.5\"E",     8913 }
 };
 
-static const char* OGRGetProj4Datum(const char* pszDatum,
-                                    int nEPSGDatum)
+static const char* OGRGetProj4Datum( const char* pszDatum,
+                                     int nEPSGDatum )
 {
-    for(size_t i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
+    for( size_t i = 0; i < CPL_ARRAYSIZE(ogr_pj_datums); i++ )
     {
-        if (nEPSGDatum == ogr_pj_datums[i].nGCS ||
-            EQUAL(pszDatum, ogr_pj_datums[i].pszOGR))
+        if( nEPSGDatum == ogr_pj_datums[i].nGCS ||
+            EQUAL(pszDatum, ogr_pj_datums[i].pszOGR) )
         {
             return ogr_pj_datums[i].pszPJ;
         }
@@ -147,11 +160,12 @@ static const char* OGRGetProj4Datum(const char* pszDatum,
     return NULL;
 }
 
-static const OGRProj4PM* OGRGetProj4PMFromProj4Name(const char* pszProj4PMName)
+static
+const OGRProj4PM* OGRGetProj4PMFromProj4Name( const char* pszProj4PMName )
 {
-    for(size_t i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
+    for( size_t i = 0; i < CPL_ARRAYSIZE(ogr_pj_pms); i++ )
     {
-        if (EQUAL(pszProj4PMName, ogr_pj_pms[i].pszProj4PMName))
+        if( EQUAL(pszProj4PMName, ogr_pj_pms[i].pszProj4PMName) )
         {
             return &ogr_pj_pms[i];
         }
@@ -159,11 +173,11 @@ static const OGRProj4PM* OGRGetProj4PMFromProj4Name(const char* pszProj4PMName)
     return NULL;
 }
 
-static const OGRProj4PM* OGRGetProj4PMFromCode(int nPMCode)
+static const OGRProj4PM* OGRGetProj4PMFromCode( int nPMCode )
 {
-    for(size_t i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
+    for( size_t i = 0; i < CPL_ARRAYSIZE(ogr_pj_pms); i++ )
     {
-        if (nPMCode == ogr_pj_pms[i].nPMCode)
+        if( nPMCode == ogr_pj_pms[i].nPMCode )
         {
             return &ogr_pj_pms[i];
         }
@@ -171,12 +185,12 @@ static const OGRProj4PM* OGRGetProj4PMFromCode(int nPMCode)
     return NULL;
 }
 
-static const OGRProj4PM* OGRGetProj4PMFromVal(double dfVal)
+static const OGRProj4PM* OGRGetProj4PMFromVal( double dfVal )
 {
-    unsigned int i;
-    for(i=0;i<sizeof(ogr_pj_pms)/sizeof(ogr_pj_pms[0]);i++)
+    for( unsigned int i = 0; i < CPL_ARRAYSIZE(ogr_pj_pms); i++ )
     {
-        if (fabs(dfVal - CPLDMSToDec(ogr_pj_pms[i].pszFromGreenwich)) < 1e-10)
+        // TODO(schwehr): Use an almost equal call.
+        if( fabs(dfVal - CPLDMSToDec(ogr_pj_pms[i].pszFromGreenwich)) < 1e-10 )
         {
             return &ogr_pj_pms[i];
         }
@@ -197,13 +211,16 @@ static const LinearUnitsStruct asLinearUnits [] =
 { SRS_UL_METER, "1.0", "meter" }, // alias of former
 { SRS_UL_METER, "1.0", "metre" }, // alias of former
 { "metre", "1.0", "m" }, // alias of former
-{ "kilometre", SRS_UL_KILOMETER_CONV, "km" }, // Leave as 'kilometre' instead of SRS_UL_KILOMETER due to historical usage
+ // Leave as 'kilometre' instead of SRS_UL_KILOMETER due to historical usage.
+{ "kilometre", SRS_UL_KILOMETER_CONV, "km" },
 { SRS_UL_KILOMETER, SRS_UL_KILOMETER_CONV, "km" }, // alias of former
 { SRS_UL_DECIMETER, SRS_UL_DECIMETER_CONV, "dm" },
 { SRS_UL_CENTIMETER, SRS_UL_CENTIMETER_CONV, "cm" },
 { SRS_UL_MILLIMETER, SRS_UL_MILLIMETER_CONV, "mm" },
 
-{ SRS_UL_FOOT, SRS_UL_FOOT_CONV, "ft" }, // Leave as 'Foot (International)' or SRS_UL_FOOT instead of SRS_UL_INTL_FOOT due to historical usage
+ // Leave as 'Foot (International)' or SRS_UL_FOOT instead of SRS_UL_INTL_FOOT
+// due to historical usage.
+{ SRS_UL_FOOT, SRS_UL_FOOT_CONV, "ft" },
 { SRS_UL_INTL_FOOT, SRS_UL_INTL_FOOT_CONV, "ft" }, // alias of former
 { SRS_UL_US_FOOT, SRS_UL_US_FOOT_CONV, "us-ft" },
 { SRS_UL_INDIAN_FOOT, SRS_UL_INDIAN_FOOT_CONV, "ind-ft" },
@@ -241,14 +258,16 @@ static const LinearUnitsStruct asLinearUnits [] =
 /************************************************************************/
 
 static const LinearUnitsStruct *GetLinearFromLinearConvOrName(
-                                                  double dfLinearConv,
-                                                  const char *pszLinearUnits )
+    double dfLinearConv,
+    const char *pszLinearUnits )
 
 {
-    for( size_t i=0; i < sizeof(asLinearUnits) / sizeof(asLinearUnits[0]); i++ )
+    for( size_t i = 0; i < CPL_ARRAYSIZE(asLinearUnits); i++ )
     {
-        if( (pszLinearUnits != NULL && EQUAL(pszLinearUnits, asLinearUnits[i].pszWKTName)) ||
-            fabs(dfLinearConv - CPLAtof(asLinearUnits[i].pszValueInMeter)) < 0.00000001 )
+        if( (pszLinearUnits != NULL &&
+             EQUAL(pszLinearUnits, asLinearUnits[i].pszWKTName)) ||
+            fabs(dfLinearConv -
+                 CPLAtof(asLinearUnits[i].pszValueInMeter)) < 0.00000001 )
         {
             return &(asLinearUnits[i]);
         }
@@ -263,7 +282,7 @@ static const LinearUnitsStruct *GetLinearFromLinearConvOrName(
 static const LinearUnitsStruct* GetLinearFromProjName( const char* pszProjName )
 
 {
-    for( size_t i=0; i < sizeof(asLinearUnits) / sizeof(asLinearUnits[0]); i++ )
+    for( size_t i = 0; i < CPL_ARRAYSIZE(asLinearUnits); i++ )
     {
         if( EQUAL(pszProjName, asLinearUnits[i].pszProjName) )
         {
@@ -300,7 +319,7 @@ static char **OSRProj4Tokenize( const char *pszFull )
             {
                 if( pszStart != NULL )
                 {
-                    if( strstr(pszStart,"=") != NULL )
+                    if( strstr(pszStart, "=") != NULL )
                         papszTokens = CSLAddString( papszTokens, pszStart );
                     else
                     {
@@ -332,7 +351,6 @@ static char **OSRProj4Tokenize( const char *pszFull )
     return papszTokens;
 }
 
-
 /************************************************************************/
 /*                         OSRImportFromProj4()                         */
 /************************************************************************/
@@ -346,7 +364,8 @@ OGRErr OSRImportFromProj4( OGRSpatialReferenceH hSRS, const char *pszProj4 )
 {
     VALIDATE_POINTER1( hSRS, "OSRImportFromProj4", OGRERR_FAILURE );
 
-    return ((OGRSpatialReference *) hSRS)->importFromProj4( pszProj4 );
+    return reinterpret_cast<OGRSpatialReference *>(hSRS)->
+        importFromProj4( pszProj4 );
 }
 
 /************************************************************************/
@@ -363,14 +382,14 @@ static double OSR_GDV( char **papszNV, const char * pszField,
 {
     const char *pszValue = CSLFetchNameValue( papszNV, pszField );
 
-    // special hack to use k_0 if available.
-    if( pszValue == NULL && EQUAL(pszField,"k") )
+    // Special hack to use k_0 if available.
+    if( pszValue == NULL && EQUAL(pszField, "k") )
         pszValue = CSLFetchNameValue( papszNV, "k_0" );
 
     if( pszValue == NULL )
         return dfDefaultValue;
-    else
-        return CPLDMSToDec(pszValue);
+
+    return CPLDMSToDec(pszValue);
 }
 
 /************************************************************************/
@@ -477,13 +496,22 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
             pszCleanCopy[i] = ' ';
     }
 
+    const char* pszInitEpsgCleanCopy = strstr(pszCleanCopy, "init=epsg:");
+    bool bSetAuthorityCode = true;
+    // If there's an override, then drop the authority code.
+    if( pszInitEpsgCleanCopy != NULL &&
+        strchr(pszInitEpsgCleanCopy, '+') != NULL )
+    {
+        bSetAuthorityCode = false;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Try to normalize the definition.  This should expand +init=     */
 /*      clauses and so forth.                                           */
 /* -------------------------------------------------------------------- */
     char *pszNormalized = OCTProj4Normalize( pszCleanCopy );
 
-    /* Workaround proj.4 bug (#239) by manually re-adding no_off/no_uoff */
+    // Workaround proj.4 bug (#239) by manually re-adding no_off/no_uoff.
     if( strstr(pszCleanCopy, "+no_off") != NULL &&
         strstr(pszNormalized, "+no_off") == NULL )
     {
@@ -504,18 +532,25 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /* -------------------------------------------------------------------- */
 /*      If we have an EPSG based init string, and no existing +proj     */
 /*      portion then try to normalize into into a PROJ.4 string.        */
+/*      This can happen if the proj.4 epsg dictionary is missing.      */
 /* -------------------------------------------------------------------- */
-    if( strstr(pszNormalized,"init=epsg:") != NULL
-        && strstr(pszNormalized,"proj=") == NULL )
+    const char* pszInitEpsg = strstr(pszNormalized, "init=epsg:");
+    if( pszInitEpsg != NULL
+        && strstr(pszNormalized, "proj=") == NULL )
     {
-        const char *pszNumber = strstr(pszNormalized,"init=epsg:") + 10;
+        const char *pszNumber = pszInitEpsg + strlen("init=epsg:");
 
-        OGRErr eErr = importFromEPSG( atoi(pszNumber) );
-        if( eErr == OGRERR_NONE )
+        const OGRErr eErr = importFromEPSG( atoi(pszNumber) );
+        if( eErr != OGRERR_NONE || strchr(pszNumber, '+') == NULL )
         {
             CPLFree( pszNormalized );
             return eErr;
         }
+        const int nIdx = GetRoot()->FindChild("AUTHORITY");
+        if( nIdx >= 0 )
+        {
+            GetRoot()->DestroyChild( nIdx );
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -528,7 +563,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 
     for( int i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
     {
-        char *pszEqual = strstr(papszTokens[i],"=");
+        char *pszEqual = strstr(papszTokens[i], "=");
 
         if( pszEqual == NULL )
             papszNV = CSLAddNameValue(papszNV, papszTokens[i], "" );
@@ -546,16 +581,14 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /* -------------------------------------------------------------------- */
     const char *pszPM = CSLFetchNameValue( papszNV, "pm" );
     double l_dfFromGreenwich = 0.0;
-    /* int    nPMCode = -1; */
 
     if( pszPM != NULL )
     {
         const OGRProj4PM* psProj4PM = OGRGetProj4PMFromProj4Name(pszPM);
-        if (psProj4PM)
+        if( psProj4PM )
         {
             l_dfFromGreenwich = CPLDMSToDec(psProj4PM->pszFromGreenwich);
             pszPM = psProj4PM->pszWKTPMName;
-            /* nPMCode = psProj4PM->nPMCode; */
         }
         else
         {
@@ -564,12 +597,14 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         }
     }
     else
+    {
         pszPM = "Greenwich";
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Operate on the basis of the projection name.                    */
 /* -------------------------------------------------------------------- */
-    const char *pszProj = CSLFetchNameValue(papszNV,"proj");
+    const char *pszProj = CSLFetchNameValue(papszNV, "proj");
     bool bAddProj4Extension = false;
 
     if( pszProj == NULL )
@@ -578,53 +613,46 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         CSLDestroy( papszNV );
         return OGRERR_CORRUPT_DATA;
     }
-
-    else if( EQUAL(pszProj,"longlat") || EQUAL(pszProj,"latlong") )
+    else if( EQUAL(pszProj, "longlat") || EQUAL(pszProj, "latlong") )
     {
     }
-
-    else if( EQUAL(pszProj,"geocent") )
+    else if( EQUAL(pszProj, "geocent") )
     {
         SetGeocCS( "Geocentric" );
     }
-
-    else if( EQUAL(pszProj,"bonne") )
+    else if( EQUAL(pszProj, "bonne") )
     {
         SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ),
                   OSR_GDV( papszNV, "lon_0", 0.0 ),
                   OSR_GDV( papszNV, "x_0", 0.0 ),
                   OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"cass") )
+    else if( EQUAL(pszProj, "cass") )
     {
         SetCS( OSR_GDV( papszNV, "lat_0", 0.0 ),
                OSR_GDV( papszNV, "lon_0", 0.0 ),
                OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"nzmg") )
+    else if( EQUAL(pszProj, "nzmg") )
     {
         SetNZMG( OSR_GDV( papszNV, "lat_0", -41.0 ),
                  OSR_GDV( papszNV, "lon_0", 173.0 ),
                  OSR_GDV( papszNV, "x_0", 2510000.0 ),
                  OSR_GDV( papszNV, "y_0", 6023150.0 ) );
     }
-
-    else if( EQUAL(pszProj,"cea") )
+    else if( EQUAL(pszProj, "cea") )
     {
         SetCEA( OSR_GDV( papszNV, "lat_ts", 0.0 ),
                 OSR_GDV( papszNV, "lon_0", 0.0 ),
                 OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"tmerc") )
+    else if( EQUAL(pszProj, "tmerc") )
     {
         const char *pszAxis = CSLFetchNameValue( papszNV, "axis" );
 
-        if( pszAxis == NULL || !EQUAL(pszAxis,"wsu") )
+        if( pszAxis == NULL || !EQUAL(pszAxis, "wsu") )
             SetTM( OSR_GDV( papszNV, "lat_0", 0.0 ),
                    OSR_GDV( papszNV, "lon_0", 0.0 ),
                    OSR_GDV( papszNV, "k", 1.0 ),
@@ -637,11 +665,10 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                      OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    /* For etmerc, we translate it into standard TM for the WKT */
-    /* point of view, but make sure that the original proj.4 */
-    /* definition is preserved for accurate reprojection */
-    else if( EQUAL(pszProj,"etmerc") &&
+    // For etmerc, we translate it into standard TM for the WKT
+    // point of view, but make sure that the original proj.4
+    // definition is preserved for accurate reprojection.
+    else if( EQUAL(pszProj, "etmerc") &&
              CSLFetchNameValue( papszNV, "axis" ) == NULL )
     {
         bAddProj4Extension = true;
@@ -652,14 +679,12 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                 OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"utm") )
+    else if( EQUAL(pszProj, "utm") )
     {
-        SetUTM( (int) OSR_GDV( papszNV, "zone", 0.0 ),
-                (int) OSR_GDV( papszNV, "south", 1.0 ) );
+        SetUTM(static_cast<int>(OSR_GDV( papszNV, "zone", 0.0)),
+               static_cast<int>(OSR_GDV( papszNV, "south", 1.0)) );
     }
-
-    else if( EQUAL(pszProj,"merc") /* 2SP form */
+    else if( EQUAL(pszProj, "merc")  // 2SP form.
              && OSR_GDV(papszNV, "lat_ts", 1000.0) < 999.0 )
     {
         SetMercator2SP( OSR_GDV( papszNV, "lat_ts", 0.0 ),
@@ -668,8 +693,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                         OSR_GDV( papszNV, "x_0", 0.0 ),
                         OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"merc") ) /* 1SP form */
+    else if( EQUAL(pszProj, "merc") )  // 1SP form.
     {
         SetMercator( 0.0,
                      OSR_GDV( papszNV, "lon_0", 0.0 ),
@@ -677,9 +701,8 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                      OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"stere")
-             && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) - 90) < 0.001 )
+    else if( EQUAL(pszProj, "stere")
+             && std::abs(OSR_GDV( papszNV, "lat_0", 0.0 ) - 90) < 0.001 )
     {
         SetPS( OSR_GDV( papszNV, "lat_ts", 90.0 ),
                OSR_GDV( papszNV, "lon_0", 0.0 ),
@@ -687,9 +710,8 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"stere")
-             && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) + 90) < 0.001 )
+    else if( EQUAL(pszProj, "stere")
+             && std::abs(OSR_GDV( papszNV, "lat_0", 0.0 ) + 90) < 0.001 )
     {
         SetPS( OSR_GDV( papszNV, "lat_ts", -90.0 ),
                OSR_GDV( papszNV, "lon_0", 0.0 ),
@@ -697,8 +719,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"sterea") )
+    else if( EQUAL(pszProj, "sterea") )
     {
         SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ),
                OSR_GDV( papszNV, "lon_0", 0.0 ),
@@ -706,8 +727,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"stere") )
+    else if( EQUAL(pszProj, "stere") )
     {
         SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ),
                           OSR_GDV( papszNV, "lon_0", 0.0 ),
@@ -715,8 +735,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                           OSR_GDV( papszNV, "x_0", 0.0 ),
                           OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"eqc") )
+    else if( EQUAL(pszProj, "eqc") )
     {
         if( OSR_GDV( papszNV, "lat_ts", 0.0 ) != 0.0 )
           SetEquirectangular2( OSR_GDV( papszNV, "lat_0", 0.0 ),
@@ -730,8 +749,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                               OSR_GDV( papszNV, "x_0", 0.0 ),
                               OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"gstmerc") )
+    else if( EQUAL(pszProj, "gstmerc") )
     {
         SetGaussSchreiberTMercator( OSR_GDV( papszNV, "lat_0", -21.116666667 ),
                                     OSR_GDV( papszNV, "lon_0", 55.53333333309),
@@ -739,40 +757,35 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                                     OSR_GDV( papszNV, "x_0", 160000.000 ),
                                     OSR_GDV( papszNV, "y_0", 50000.000 ) );
     }
-
-    else if( EQUAL(pszProj,"gnom") )
+    else if( EQUAL(pszProj, "gnom") )
     {
         SetGnomonic( OSR_GDV( papszNV, "lat_0", 0.0 ),
                      OSR_GDV( papszNV, "lon_0", 0.0 ),
                      OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"ortho") )
+    else if( EQUAL(pszProj, "ortho") )
     {
         SetOrthographic( OSR_GDV( papszNV, "lat_0", 0.0 ),
                          OSR_GDV( papszNV, "lon_0", 0.0 ),
                          OSR_GDV( papszNV, "x_0", 0.0 ),
                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"laea") )
+    else if( EQUAL(pszProj, "laea") )
     {
         SetLAEA( OSR_GDV( papszNV, "lat_0", 0.0 ),
                  OSR_GDV( papszNV, "lon_0", 0.0 ),
                  OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"aeqd") )
+    else if( EQUAL(pszProj, "aeqd") )
     {
         SetAE( OSR_GDV( papszNV, "lat_0", 0.0 ),
                OSR_GDV( papszNV, "lon_0", 0.0 ),
                OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"eqdc") )
+    else if( EQUAL(pszProj, "eqdc") )
     {
         SetEC( OSR_GDV( papszNV, "lat_1", 0.0 ),
                OSR_GDV( papszNV, "lat_2", 0.0 ),
@@ -781,40 +794,36 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"mill") )
+    else if( EQUAL(pszProj, "mill") )
     {
         SetMC( OSR_GDV( papszNV, "lat_0", 0.0 ),
                OSR_GDV( papszNV, "lon_0", 0.0 ),
                OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"moll") )
+    else if( EQUAL(pszProj, "moll") )
     {
         SetMollweide( OSR_GDV( papszNV, "lon_0", 0.0 ),
                       OSR_GDV( papszNV, "x_0", 0.0 ),
                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"eck1") || EQUAL(pszProj,"eck2") || EQUAL(pszProj,"eck3") ||
-             EQUAL(pszProj,"eck4") || EQUAL(pszProj,"eck5") || EQUAL(pszProj,"eck6"))
+    else if( EQUAL(pszProj, "eck1") || EQUAL(pszProj, "eck2") ||
+             EQUAL(pszProj, "eck3") || EQUAL(pszProj, "eck4") ||
+             EQUAL(pszProj, "eck5") || EQUAL(pszProj, "eck6") )
     {
-        SetEckert(   pszProj[3] - '0',
-                     OSR_GDV( papszNV, "lon_0", 0.0 ),
-                     OSR_GDV( papszNV, "x_0", 0.0 ),
-                     OSR_GDV( papszNV, "y_0", 0.0 ) );
+        SetEckert( pszProj[3] - '0',  // TODO(schwehr): Symbolic const for 3.
+                   OSR_GDV( papszNV, "lon_0", 0.0 ),
+                   OSR_GDV( papszNV, "x_0", 0.0 ),
+                   OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"poly") )
+    else if( EQUAL(pszProj, "poly") )
     {
         SetPolyconic( OSR_GDV( papszNV, "lat_0", 0.0 ),
                       OSR_GDV( papszNV, "lon_0", 0.0 ),
                       OSR_GDV( papszNV, "x_0", 0.0 ),
                       OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"aea") )
+    else if( EQUAL(pszProj, "aea") )
     {
         SetACEA( OSR_GDV( papszNV, "lat_1", 0.0 ),
                  OSR_GDV( papszNV, "lat_2", 0.0 ),
@@ -823,48 +832,41 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                  OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"robin") )
+    else if( EQUAL(pszProj, "robin") )
     {
         SetRobinson( OSR_GDV( papszNV, "lon_0", 0.0 ),
                      OSR_GDV( papszNV, "x_0", 0.0 ),
                      OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"vandg") )
+    else if( EQUAL(pszProj, "vandg") )
     {
         SetVDG( OSR_GDV( papszNV, "lon_0", 0.0 ),
                 OSR_GDV( papszNV, "x_0", 0.0 ),
                 OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"sinu") )
+    else if( EQUAL(pszProj, "sinu") )
     {
         SetSinusoidal( OSR_GDV( papszNV, "lon_0", 0.0 ),
                        OSR_GDV( papszNV, "x_0", 0.0 ),
                        OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"gall") )
+    else if( EQUAL(pszProj, "gall") )
     {
         SetGS( OSR_GDV( papszNV, "lon_0", 0.0 ),
                OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"goode") )
+    else if( EQUAL(pszProj, "goode") )
     {
         SetGH( OSR_GDV( papszNV, "lon_0", 0.0 ),
                OSR_GDV( papszNV, "x_0", 0.0 ),
                OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"igh") )
+    else if( EQUAL(pszProj, "igh") )
     {
         SetIGH();
     }
-
-    else if( EQUAL(pszProj,"geos") )
+    else if( EQUAL(pszProj, "geos") )
     {
         SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ),
                  OSR_GDV( papszNV, "h", 35785831.0 ),
@@ -874,14 +876,13 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         if( EQUAL(CSLFetchNameValueDef( papszNV, "sweep", "y" ), "x") )
             bAddProj4Extension = true;
     }
-
-    else if( EQUAL(pszProj,"lcc") )
+    else if( EQUAL(pszProj, "lcc") )
     {
         if( OSR_GDV(papszNV, "lat_0", 0.0 )
             == OSR_GDV(papszNV, "lat_1", 0.0 ) &&
             CSLFetchNameValue( papszNV, "lat_2" ) == NULL )
         {
-            /* 1SP form */
+            // 1SP form.
             SetLCC1SP( OSR_GDV( papszNV, "lat_0", 0.0 ),
                        OSR_GDV( papszNV, "lon_0", 0.0 ),
                        OSR_GDV( papszNV, "k_0", 1.0 ),
@@ -890,7 +891,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         }
         else
         {
-            /* 2SP form */
+            // 2SP form.
             SetLCC( OSR_GDV( papszNV, "lat_1", 0.0 ),
                     OSR_GDV( papszNV, "lat_2", 0.0 ),
                     OSR_GDV( papszNV, "lat_0", 0.0 ),
@@ -899,23 +900,24 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                     OSR_GDV( papszNV, "y_0", 0.0 ) );
         }
     }
-
-    else if( EQUAL(pszProj,"omerc") )
+    else if( EQUAL(pszProj, "omerc") )
     {
-        if( CSLFetchNameValue(papszNV,"no_uoff") != NULL
-            || CSLFetchNameValue(papszNV,"no_off") != NULL )
+        if( CSLFetchNameValue(papszNV, "no_uoff") != NULL
+            || CSLFetchNameValue(papszNV, "no_off") != NULL )
         {
-            /* From PJ_omerc, when alpha is defined but not gamma */
-            /* the default gamma value is alpha */
-            /*  if (alp || gam) {
-                    if (alp) {
-                        gamma0 = asin(sin(alpha_c) / D);
-                    if (!gam)
-                        gamma = alpha_c; */
+            // From PJ_omerc, when alpha is defined but not gamma
+            // the default gamma value is alpha.
+            // if( alp || gam )
+            // {
+            //     if( alp )
+            //     {
+            //         gamma0 = asin(sin(alpha_c) / D);
+            //         if( !gam )
+            //             gamma = alpha_c;
             SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ),
                     OSR_GDV( papszNV, "lonc", 0.0 ),
                     OSR_GDV( papszNV, "alpha", 0.0 ),
-                    OSR_GDV( papszNV, "gamma", OSR_GDV( papszNV, "alpha", 0.0 ) ),
+                    OSR_GDV( papszNV, "gamma", OSR_GDV(papszNV, "alpha", 0.0 )),
                     OSR_GDV( papszNV, "k", 1.0 ),
                     OSR_GDV( papszNV, "x_0", 0.0 ),
                     OSR_GDV( papszNV, "y_0", 0.0 ) );
@@ -925,34 +927,31 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
             SetHOMAC( OSR_GDV( papszNV, "lat_0", 0.0 ),
                    OSR_GDV( papszNV, "lonc", 0.0 ),
                    OSR_GDV( papszNV, "alpha", 0.0 ),
-                   OSR_GDV( papszNV, "gamma", OSR_GDV( papszNV, "alpha", 0.0 ) ),
+                   OSR_GDV( papszNV, "gamma", OSR_GDV(papszNV, "alpha", 0.0 )),
                    OSR_GDV( papszNV, "k", 1.0 ),
                    OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
         }
     }
-
-    else if( EQUAL(pszProj,"somerc") )
+    else if( EQUAL(pszProj, "somerc") )
     {
         SetHOMAC( OSR_GDV( papszNV, "lat_0", 0.0 ),
                   OSR_GDV( papszNV, "lon_0", 0.0 ),
-                  90.0,  90.0,
+                  90.0, 90.0,
                   OSR_GDV( papszNV, "k", 1.0 ),
                   OSR_GDV( papszNV, "x_0", 0.0 ),
                   OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"krovak") )
+    else if( EQUAL(pszProj, "krovak") )
     {
         SetKrovak( OSR_GDV( papszNV, "lat_0", 0.0 ),
                    OSR_GDV( papszNV, "lon_0", 0.0 ),
                    OSR_GDV( papszNV, "alpha", 0.0 ),
-                   0.0, // pseudo_standard_parallel_1
+                   0.0,  // Pseudo_standard_parallel_1.
                    OSR_GDV( papszNV, "k", 1.0 ),
                    OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
     else if( EQUAL(pszProj, "iwm_p") )
     {
         SetIWMPolyconic( OSR_GDV( papszNV, "lat_1", 0.0 ),
@@ -961,21 +960,18 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                          OSR_GDV( papszNV, "x_0", 0.0 ),
                          OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
     else if( EQUAL(pszProj, "wag1") )
     {
         SetWagner( 1, 0.0,
                    OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
     else if( EQUAL(pszProj, "wag2") )
     {
         SetWagner( 2, 0.0,
                    OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
     else if( EQUAL(pszProj, "wag3") )
     {
         SetWagner( 3,
@@ -983,49 +979,43 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                    OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
     else if( EQUAL(pszProj, "wag4") )
     {
         SetWagner( 4, 0.0,
                    OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
     else if( EQUAL(pszProj, "wag5") )
     {
         SetWagner( 5, 0.0,
                    OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
     else if( EQUAL(pszProj, "wag6") )
     {
         SetWagner( 6, 0.0,
                    OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
     else if( EQUAL(pszProj, "wag7") )
     {
         SetWagner( 7, 0.0,
                    OSR_GDV( papszNV, "x_0", 0.0 ),
                    OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( EQUAL(pszProj,"qsc") )
+    else if( EQUAL(pszProj, "qsc") )
     {
         SetQSC( OSR_GDV( papszNV, "lat_0", 0.0 ),
                 OSR_GDV( papszNV, "lon_0", 0.0 ) );
     }
-    else if( EQUAL(pszProj,"sch") )
+    else if( EQUAL(pszProj, "sch") )
     {
         SetSCH( OSR_GDV( papszNV, "plat_0", 0.0 ),
                 OSR_GDV( papszNV, "plon_0", 0.0 ),
                 OSR_GDV( papszNV, "phdg_0", 0.0 ),
                 OSR_GDV( papszNV, "h_0", 0.0) );
     }
-
-    else if( EQUAL(pszProj,"tpeqd") )
+    else if( EQUAL(pszProj, "tpeqd") )
     {
         SetTPED( OSR_GDV( papszNV, "lat_1", 0.0 ),
                  OSR_GDV( papszNV, "lon_1", 0.0 ),
@@ -1034,15 +1024,13 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                  OSR_GDV( papszNV, "x_0", 0.0 ),
                  OSR_GDV( papszNV, "y_0", 0.0 ) );
     }
-
-    else if( strstr(pszProj4,"wktext") != NULL )
+    else if( strstr(pszProj4, "wktext") != NULL )
     {
         // Fake out a projected coordinate system for otherwise
         // unrecognized projections for which we are already planning
         // to embed the actual PROJ.4 string via extension node.
         SetProjection( "custom_proj4" );
     }
-
     else
     {
         CPLDebug( "OGR_PROJ4", "Unsupported projection: %s", pszProj );
@@ -1058,10 +1046,10 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     const char *pszValue = CSLFetchNameValue(papszNV, "datum");
     if( pszValue == NULL )
     {
-        /* do nothing */
+        // Do nothing.
     }
-    else if( (EQUAL(pszValue,"NAD27") || EQUAL(pszValue,"NAD83")
-              || EQUAL(pszValue,"WGS84") || EQUAL(pszValue,"WGS72"))
+    else if( (EQUAL(pszValue, "NAD27") || EQUAL(pszValue, "NAD83")
+              || EQUAL(pszValue, "WGS84") || EQUAL(pszValue, "WGS72"))
              && l_dfFromGreenwich == 0.0 )
     {
         SetWellKnownGeogCS( pszValue );
@@ -1069,9 +1057,9 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     }
     else
     {
-        for(size_t i=0;i<sizeof(ogr_pj_datums)/sizeof(ogr_pj_datums[0]);i++)
+        for( size_t i = 0; i < CPL_ARRAYSIZE(ogr_pj_datums); i++ )
         {
-            if ( EQUAL(pszValue, ogr_pj_datums[i].pszPJ) )
+            if( EQUAL(pszValue, ogr_pj_datums[i].pszPJ) )
             {
                 OGRSpatialReference oGCS;
                 oGCS.importFromEPSG( ogr_pj_datums[i].nEPSG );
@@ -1081,20 +1069,22 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
             }
         }
 
-        /* If we don't recognise the datum, we ignore it */
+        // If we don't recognise the datum, we ignore it.
     }
 
 /* -------------------------------------------------------------------- */
 /*      Set the ellipsoid information.                                   */
 /* -------------------------------------------------------------------- */
-    double dfSemiMajor, dfInvFlattening, dfSemiMinor;
+    double dfSemiMajor = 0.0;
+    double dfInvFlattening = 0.0;
+    double dfSemiMinor = 0.0;
 
     pszValue = CSLFetchNameValue(papszNV, "ellps");
     if( pszValue != NULL && !bFullyDefined )
     {
         for( int i = 0; ogr_pj_ellps[i] != NULL; i += 4 )
         {
-            if( !EQUAL(ogr_pj_ellps[i],pszValue) )
+            if( !EQUAL(ogr_pj_ellps[i], pszValue) )
                 continue;
 
             CPLAssert( STARTS_WITH_CI(ogr_pj_ellps[i+1], "a=") );
@@ -1106,7 +1096,8 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
             {
                 CPLAssert( STARTS_WITH_CI(ogr_pj_ellps[i+2], "b=") );
                 dfSemiMinor = CPLAtof(ogr_pj_ellps[i+2]+2);
-                dfInvFlattening = OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
+                dfInvFlattening =
+                    OSRCalcInvFlattening(dfSemiMajor, dfSemiMinor);
             }
 
             SetGeogCS( ogr_pj_ellps[i+3], "unknown", ogr_pj_ellps[i],
@@ -1131,8 +1122,9 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
             }
             else
             {
-                CPLDebug( "OGR_PROJ4", "Can't find ellipse definition, default to WGS84:\n%s",
-                          pszProj4 );
+                CPLDebug("OGR_PROJ4",
+                         "Can't find ellipse definition, default to WGS84:\n%s",
+                         pszProj4);
 
                 dfSemiMajor = SRS_WGS84_SEMIMAJOR;
                 dfSemiMinor = -1.0;
@@ -1143,12 +1135,12 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         {
             dfSemiMinor = OSR_GDV( papszNV, "b", -1.0 );
             dfInvFlattening = OSR_GDV( papszNV, "rf", -1.0 );
-            if ( dfSemiMinor == -1.0 && dfInvFlattening == -1.0 )
+            if( dfSemiMinor == -1.0 && dfInvFlattening == -1.0 )
             {
-                double dfFlattening = OSR_GDV( papszNV, "f", -1.0 );
-                if ( dfFlattening == 0.0 )
+                const double dfFlattening = OSR_GDV( papszNV, "f", -1.0 );
+                if( dfFlattening == 0.0 )
                     dfSemiMinor = dfSemiMajor;
-                else if ( dfFlattening != -1.0 )
+                else if( dfFlattening != -1.0 )
                     dfInvFlattening = 1.0 / dfFlattening;
             }
         }
@@ -1170,7 +1162,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
                    dfSemiMajor, dfInvFlattening,
                    pszPM, l_dfFromGreenwich );
 
-        /*bFullyDefined = true;*/
+        // bFullyDefined = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1179,13 +1171,13 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
     pszValue = CSLFetchNameValue(papszNV, "towgs84");
     // Make sure that we do not include a useless TOWGS84 node if the datum
     // is WGS84.  Depending on the proj.4 version +datum=WGS84 might be
-    // expanded with a +towgs84=0,0,0 or not
-    if(pszValue!=NULL &&
+    // expanded with a +towgs84=0,0,0 or not.
+    if( pszValue != NULL &&
         !( EQUAL(CSLFetchNameValueDef(papszNV, "datum", ""), "WGS84")
            && EQUAL(pszValue, "0,0,0")) )
     {
-        char **papszToWGS84 = CSLTokenizeStringComplex( pszValue, ",",
-                                                        FALSE, TRUE );
+        char **papszToWGS84 =
+            CSLTokenizeStringComplex( pszValue, ",", FALSE, TRUE );
 
         if( CSLCount(papszToWGS84) >= 7 )
             SetTOWGS84( CPLAtof(papszToWGS84[0]),
@@ -1227,7 +1219,8 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
         {
             const double dfValue = CPLAtofM(pszValue);
-            const LinearUnitsStruct* psLinearUnits = GetLinearFromLinearConvOrName( dfValue, pszValue );
+            const LinearUnitsStruct* psLinearUnits =
+                GetLinearFromLinearConvOrName( dfValue, pszValue );
             if( psLinearUnits != NULL )
             {
                 SetLinearUnits( psLinearUnits->pszWKTName,
@@ -1236,19 +1229,22 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
             else
                 SetLinearUnits( "unknown", CPLAtofM(pszValue) );
         }
-        /*
-        ** All units reported by cs2cs -lu are supported, fall back to meter.
-        */
+
+        // All units reported by cs2cs -lu are supported, fall back to meter.
         else if( (pszValue = CSLFetchNameValue(papszNV, "units")) != NULL )
         {
-            const LinearUnitsStruct* psLinearUnits = GetLinearFromProjName( pszValue );
+            const LinearUnitsStruct* psLinearUnits =
+                GetLinearFromProjName( pszValue );
             if( psLinearUnits != NULL )
             {
                 SetLinearUnits( psLinearUnits->pszWKTName,
                                 CPLAtof(psLinearUnits->pszValueInMeter) );
             }
-            else // This case is untranslatable.  Should add all proj.4 unts
+            else
+            {
+                // This case is untranslatable.  Should add all proj.4 unts.
                 SetLinearUnits( pszValue, 1.0 );
+            }
         }
     }
 
@@ -1263,14 +1259,14 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         for( int i = 0; i < poPROJCS->GetChildCount(); i++ )
         {
             OGR_SRSNode *poParm = poPROJCS->GetChild(i);
-            if( !EQUAL(poParm->GetValue(),"PARAMETER")
+            if( !EQUAL(poParm->GetValue(), "PARAMETER")
                 || poParm->GetChildCount() != 2 )
                 continue;
 
             const char *pszParmName = poParm->GetChild(0)->GetValue();
 
             if( IsLinearParameter(pszParmName) )
-                SetNormProjParm(pszParmName,GetProjParm(pszParmName));
+                SetNormProjParm(pszParmName, GetProjParm(pszParmName));
         }
     }
 
@@ -1318,10 +1314,11 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         if( pszValue != NULL && CPLAtofM(pszValue) > 0.0 )
         {
             const double dfValue = CPLAtofM(pszValue);
-            const LinearUnitsStruct* psLinearUnits = GetLinearFromLinearConvOrName( dfValue, pszValue );
+            const LinearUnitsStruct* psLinearUnits =
+                GetLinearFromLinearConvOrName( dfValue, pszValue );
             if( psLinearUnits != NULL )
             {
-                pszUnitName = psLinearUnits->pszWKTName,
+                pszUnitName = psLinearUnits->pszWKTName;
                 pszUnitConv = psLinearUnits->pszValueInMeter;
             }
             else
@@ -1332,10 +1329,11 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         }
         else if( (pszValue = CSLFetchNameValue(papszNV, "vunits")) != NULL )
         {
-            const LinearUnitsStruct* psLinearUnits = GetLinearFromProjName( pszValue );
+            const LinearUnitsStruct* psLinearUnits =
+                GetLinearFromProjName( pszValue );
             if( psLinearUnits != NULL )
             {
-                pszUnitName = psLinearUnits->pszWKTName,
+                pszUnitName = psLinearUnits->pszWKTName;
                 pszUnitConv = psLinearUnits->pszValueInMeter;
             }
             else
@@ -1355,7 +1353,7 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
         }
     }
 
-    /* Add AXIS to VERT_CS node */
+    // Add AXIS to VERT_CS node.
     if( poVERT_CS != NULL )
     {
         OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
@@ -1369,19 +1367,21 @@ OGRErr OGRSpatialReference::importFromProj4( const char * pszProj4 )
 /* -------------------------------------------------------------------- */
 /*      do we want to insert a PROJ.4 EXTENSION item?                   */
 /* -------------------------------------------------------------------- */
-    if( strstr(pszProj4,"wktext") != NULL || bAddProj4Extension )
+    if( strstr(pszProj4, "wktext") != NULL || bAddProj4Extension )
         SetExtension( GetRoot()->GetValue(), "PROJ4", pszProj4 );
 
 /* -------------------------------------------------------------------- */
 /*      Preserve authority (for example IGNF)                           */
 /* -------------------------------------------------------------------- */
-    const char *pszINIT = CSLFetchNameValue(papszNV,"init");
-    const char *pszColumn;
-    if( pszINIT != NULL && (pszColumn = strchr(pszINIT, ':')) != NULL &&
+    const char *pszINIT = CSLFetchNameValue(papszNV, "init");
+    const char *pszColumn = NULL;
+    if( bSetAuthorityCode &&
+        pszINIT != NULL && (pszColumn = strchr(pszINIT, ':')) != NULL &&
         GetRoot()->FindChild( "AUTHORITY" ) < 0 )
     {
         CPLString osAuthority;
         osAuthority.assign(pszINIT, pszColumn - pszINIT);
+        osAuthority.toupper();
         OGR_SRSNode* poAuthNode = new OGR_SRSNode( "AUTHORITY" );
         poAuthNode->AddChild( new OGR_SRSNode( osAuthority ) );
         poAuthNode->AddChild( new OGR_SRSNode( pszColumn + 1 ) );
@@ -1417,12 +1417,14 @@ OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS,
 /*                           exportToProj4()                            */
 /************************************************************************/
 
-#define SAFE_PROJ4_STRCAT(szNewStr)  do { \
-    if(CPLStrlcat(szProj4, szNewStr, sizeof(szProj4)) >= sizeof(szProj4)) { \
-        CPLError(CE_Failure, CPLE_AppDefined, "String overflow when formatting proj.4 string"); \
+// TODO(schwehr): Un-macrofy this.
+#define SAFE_PROJ4_STRCAT(szNewStr) do { \
+    if( CPLStrlcat(szProj4, szNewStr, sizeof(szProj4)) >= sizeof(szProj4) ) { \
+        CPLError(CE_Failure, CPLE_AppDefined, \
+                 "String overflow when formatting proj.4 string"); \
         *ppszProj4 = CPLStrdup(""); \
         return OGRERR_FAILURE; \
-    } } while(0);
+    } } while( false );
 
 /**
  * \brief Export coordinate system in PROJ.4 format.
@@ -1434,12 +1436,16 @@ OGRErr CPL_STDCALL OSRExportToProj4( OGRSpatialReferenceH hSRS,
  * LOCAL_CS coordinate systems are not translatable.  An empty string
  * will be returned along with OGRERR_NONE.
  *
- * Special processing for Transverse Mercator with GDAL >= 1.10 and PROJ >= 4.8 :
- * if the OSR_USE_ETMERC configuration option is set to YES, the PROJ.4
+ * Special processing for Transverse Mercator with GDAL >= 1.10 and PROJ
+ * >= 4.8 :
+ * If the OSR_USE_ETMERC configuration option is set to YES, the PROJ.4
  * definition built from the SRS will use the 'etmerc' projection method,
  * rather than the default 'tmerc'. This will give better accuracy (at the
  * expense of computational speed) when reprojection occurs near the edges
  * of the validity area for the projection.
+ * Starting with GDAL >= 2.2, setting OSR_USE_ETMERC to NO will expand to the
+ * 'tmerc' projection method (useful with PROJ >= 4.9.3, where utm uses
+ * etmerc)
  *
  * This method is the equivalent of the C function OSRExportToProj4().
  *
@@ -1489,16 +1495,20 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     const char *pszProjection = GetAttrValue("PROJECTION");
 
-    char szProj4[512];
-    szProj4[0] = '\0';
+    char szProj4[512] = {};
 
+    // TODO(schwehr): Cleanup CPLsnprintf calls to do less pointer arithmetic.
     if( pszProjection == NULL && IsGeographic() )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+proj=longlat " );
+        CPLsnprintf(szProj4 + strlen(szProj4),
+                    sizeof(szProj4) - strlen(szProj4),
+                    "+proj=longlat ");
     }
     else if( IsGeocentric() )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+proj=geocent " );
+        CPLsnprintf(szProj4 + strlen(szProj4)
+                    , sizeof(szProj4) - strlen(szProj4),
+                    "+proj=geocent ");
     }
 
     else if( pszProjection == NULL && !IsGeographic() )
@@ -1507,754 +1517,816 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         *ppszProj4 = CPLStrdup("");
         return OGRERR_NONE;
     }
-    else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
+    else if( EQUAL(pszProjection, SRS_PT_CYLINDRICAL_EQUAL_AREA) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=cea +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=cea +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
 
-    else if( EQUAL(pszProjection,SRS_PT_BONNE) )
+    else if( EQUAL(pszProjection, SRS_PT_BONNE) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=bonne +lon_0=%.16g +lat_1=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=bonne +lon_0=%.16g +lat_1=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
 
-    else if( EQUAL(pszProjection,SRS_PT_CASSINI_SOLDNER) )
+    else if( EQUAL(pszProjection, SRS_PT_CASSINI_SOLDNER) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=cass +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=cass +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
 
-    else if( EQUAL(pszProjection,SRS_PT_NEW_ZEALAND_MAP_GRID) )
+    else if( EQUAL(pszProjection, SRS_PT_NEW_ZEALAND_MAP_GRID) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=nzmg +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=nzmg +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
 
-    else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) ||
-             EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_21) ||
-             EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_22) ||
-             EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_23) ||
-             EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_24) ||
-             EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_MI_25) )
+    else if( EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR) ||
+             EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR_MI_21) ||
+             EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR_MI_22) ||
+             EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR_MI_23) ||
+             EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR_MI_24) ||
+             EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR_MI_25) )
     {
-        int bNorth;
+        int bNorth = FALSE;
         const int nZone = GetUTMZone( &bNorth );
 
-        if( CPLTestBool(CPLGetConfigOption("OSR_USE_ETMERC", "FALSE")) )
+        const char* pszUseETMERC = CPLGetConfigOption("OSR_USE_ETMERC", NULL);
+        if( pszUseETMERC && CPLTestBool(pszUseETMERC) )
+        {
+            CPLsnprintf( szProj4 + strlen(szProj4),
+                         sizeof(szProj4) - strlen(szProj4),
+                         "+proj=etmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g "
+                         "+x_0=%.16g +y_0=%.16g ",
+                         GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                         GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                         GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                         GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                         GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+        }
+        else if( pszUseETMERC && !CPLTestBool(pszUseETMERC) )
         {
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=etmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
-                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+            CPLsnprintf( szProj4 + strlen(szProj4),
+                         sizeof(szProj4) - strlen(szProj4),
+                         "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g "
+                         "+x_0=%.16g +y_0=%.16g ",
+                         GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                         GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                         GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                         GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                         GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
         }
         else if( nZone != 0 )
         {
             if( bNorth )
-                CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+proj=utm +zone=%d ",
-                         nZone );
+                CPLsnprintf( szProj4 + strlen(szProj4),
+                             sizeof(szProj4) - strlen(szProj4),
+                             "+proj=utm +zone=%d ",
+                             nZone );
             else
-                CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),"+proj=utm +zone=%d +south ",
-                         nZone );
+                CPLsnprintf( szProj4 + strlen(szProj4),
+                             sizeof(szProj4) - strlen(szProj4),
+                             "+proj=utm +zone=%d +south ",
+                             nZone );
         }
         else
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
-                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g +axis=wsu ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_MERCATOR_1SP) )
-    {
-        if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) == 0.0 )
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=merc +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-        else if( GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0) == 1.0 )
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+            CPLsnprintf( szProj4 + strlen(szProj4),
+                         sizeof(szProj4) - strlen(szProj4),
+                         "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g "
+                         "+x_0=%.16g +y_0=%.16g ",
+                         GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                         GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                         GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                         GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                         GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED) )
+    {
+        CPLsnprintf( szProj4 + strlen(szProj4),
+                     sizeof(szProj4) - strlen(szProj4),
+                     "+proj=tmerc +lat_0=%.16g +lon_0=%.16g +k=%.16g "
+                     "+x_0=%.16g +y_0=%.16g +axis=wsu ",
+                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                     GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                     GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                     GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_MERCATOR_1SP) )
+    {
+        if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0) == 0.0 )
+            CPLsnprintf( szProj4 + strlen(szProj4),
+                         sizeof(szProj4) - strlen(szProj4),
+                         "+proj=merc +lon_0=%.16g +k=%.16g +x_0=%.16g "
+                         "+y_0=%.16g ",
+                         GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                         GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                         GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                         GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+        else if( GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0) == 1.0 )
+            CPLsnprintf( szProj4 + strlen(szProj4),
+                         sizeof(szProj4) - strlen(szProj4),
+                         "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g "
+                         "+y_0=%.16g ",
+                         GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                         GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                         GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                         GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
         else
         {
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "Mercator_1SP with scale != 1.0 and latitude of origin != 0, not supported by PROJ.4." );
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Mercator_1SP with scale != 1.0 and "
+                     "latitude of origin != 0, not supported by PROJ.4.");
             *ppszProj4 = CPLStrdup("");
             return OGRERR_UNSUPPORTED_SRS;
         }
     }
-
-    else if( EQUAL(pszProjection,SRS_PT_MERCATOR_2SP) )
+    else if( EQUAL(pszProjection, SRS_PT_MERCATOR_2SP) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=merc +lon_0=%.16g +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
-
-    else if( EQUAL(pszProjection,SRS_PT_MERCATOR_AUXILIARY_SPHERE) )
+    else if( EQUAL(pszProjection, SRS_PT_MERCATOR_AUXILIARY_SPHERE) )
     {
        // This is EPSG:3875 Pseudo Mercator. No point in trying to parse the
        // rest of the parameters, since we know pretty much everything at this
        // stage.
-       CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-		"+proj=merc +a=%.16g +b=%.16g +lat_ts=%.16g"
-		" +lon_0=%.16g +x_0=%.16g +y_0=%.16g +k=%.16g +units=m"
-		" +nadgrids=@null +wktext  +no_defs",
-		GetSemiMajor(), GetSemiMajor(),
-		GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-		GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-		GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-		GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0),
-		GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0) );
+       CPLsnprintf( szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+                    "+proj=merc +a=%.16g +b=%.16g +lat_ts=%.16g "
+                    "+lon_0=%.16g +x_0=%.16g +y_0=%.16g +k=%.16g +units=m "
+                    "+nadgrids=@null +wktext  +no_defs",
+                    GetSemiMajor(), GetSemiMajor(),
+                    GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+                    GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                    GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                    GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0),
+                    GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0) );
        *ppszProj4 = CPLStrdup( szProj4 );
 
        return OGRERR_NONE;
     }
-
-    else if( EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=sterea +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
-//         "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_STEREOGRAPHIC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_POLAR_STEREOGRAPHIC) )
-    {
-        if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0) >= 0.0 )
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=stere +lat_0=90 +lat_ts=%.16g +lon_0=%.16g "
-                     "+k=%.16g +x_0=%.16g +y_0=%.16g ",
-                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,90.0),
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+    else if( EQUAL(pszProjection, SRS_PT_OBLIQUE_STEREOGRAPHIC) )
+    {
+        CPLsnprintf(
+           szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+           "+proj=sterea +lat_0=%.16g +lon_0=%.16g +k=%.16g "
+           "+x_0=%.16g +y_0=%.16g ",
+           GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+           GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+           GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+           GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+           GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_STEREOGRAPHIC) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=stere +lat_0=%.16g +lon_0=%.16g +k=%.16g "
+            "+x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_POLAR_STEREOGRAPHIC) )
+    {
+        if( GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0) >= 0.0 )
+            CPLsnprintf(
+                szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+                "+proj=stere +lat_0=90 +lat_ts=%.16g +lon_0=%.16g "
+                "+k=%.16g +x_0=%.16g +y_0=%.16g ",
+                GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 90.0),
+                GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
         else
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=stere +lat_0=-90 +lat_ts=%.16g +lon_0=%.16g "
-                     "+k=%.16g +x_0=%.16g +y_0=%.16g ",
-                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-90.0),
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_EQUIRECTANGULAR) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=eqc +lat_ts=%.16g +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_GAUSSSCHREIBERTMERCATOR) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=gstmerc +lat_0=%.16g +lon_0=%.16g"
-                 " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,-21.116666667),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,55.53333333309),
-                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,160000.000),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,50000.000) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_GNOMONIC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=gnom +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_ORTHOGRAPHIC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=ortho +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=laea +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_AZIMUTHAL_EQUIDISTANT) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=aeqd +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_EQUIDISTANT_CONIC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=eqdc +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g +lat_2=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0),
-                 GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_MILLER_CYLINDRICAL) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=mill +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_MOLLWEIDE) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=moll +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_ECKERT_I) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=eck1 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_ECKERT_II) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=eck2 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_ECKERT_III) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=eck3 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_ECKERT_IV) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=eck4 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_ECKERT_V) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=eck5 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_ECKERT_VI) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=eck6 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_POLYCONIC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=poly +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=aea +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_ROBINSON) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=robin +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_VANDERGRINTEN) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=vandg +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_SINUSOIDAL) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=sinu +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_GALL_STEREOGRAPHIC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=gall +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_GOODE_HOMOLOSINE) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=goode +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_IGH) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+proj=igh " );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_GEOSTATIONARY_SATELLITE) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=geos +lon_0=%.16g +h=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_SATELLITE_HEIGHT,35785831.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP)
-             || EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=lcc +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2,0.0),
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=lcc +lat_1=%.16g +lat_0=%.16g +lon_0=%.16g"
-                 " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
-    {
-        /* special case for swiss oblique mercator : see bug 423 */
-        if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001
-            && fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,0.0)-90.0) < 0.0001 )
+            CPLsnprintf(
+                szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+                "+proj=stere +lat_0=-90 +lat_ts=%.16g +lon_0=%.16g "
+                "+k=%.16g +x_0=%.16g +y_0=%.16g ",
+                GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, -90.0),
+                GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_EQUIRECTANGULAR) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=eqc +lat_ts=%.16g +lat_0=%.16g +lon_0=%.16g "
+            "+x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_GAUSSSCHREIBERTMERCATOR) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=gstmerc +lat_0=%.16g +lon_0=%.16g "
+            "+k_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, -21.116666667),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 55.53333333309),
+            GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 160000.000),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 50000.000) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_GNOMONIC) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=gnom +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_ORTHOGRAPHIC) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=ortho +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=laea +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_AZIMUTHAL_EQUIDISTANT) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=aeqd +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_EQUIDISTANT_CONIC) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=eqdc +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g +lat_2=%.16g "
+            "+x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0),
+            GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0),
+            GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+            GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_MILLER_CYLINDRICAL) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=mill +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
+            GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_MOLLWEIDE) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=moll +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_ECKERT_I) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=eck1 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_ECKERT_II) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=eck2 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_ECKERT_III) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=eck3 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_ECKERT_IV) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=eck4 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_ECKERT_V) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=eck5 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_ECKERT_VI) )
+    {
+        CPLsnprintf(
+            szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+            "+proj=eck6 +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+            GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+            GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_POLYCONIC) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=poly +lat_0=%.16g +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_ALBERS_CONIC_EQUAL_AREA) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=aea +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+             GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0),
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_ROBINSON) )
+    {
+        // Workaround a bug in proj.4 :
+        // https://github.com/OSGeo/proj.4/commit/
+        //                              bc7453d1a75aab05bdff2c51ed78c908e3efa3cd
+        const double dfLon0 = GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
+        const double dfX0 = GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0);
+        const double dfY0 = GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0);
+        if( CPLIsNan(dfLon0) || CPLIsNan(dfX0) || CPLIsNan(dfY0) )
         {
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
-                     " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+            return OGRERR_FAILURE;
+        }
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=robin +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+             dfLon0,
+             dfX0,
+             dfY0 );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_VANDERGRINTEN) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=vandg +lon_0=%.16g +x_0=%.16g +y_0=%.16g +R_A ",
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_SINUSOIDAL) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=sinu +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_GALL_STEREOGRAPHIC) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=gall +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_GOODE_HOMOLOSINE) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=goode +lon_0=%.16g +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_IGH) )
+    {
+        CPLsnprintf( szProj4 + strlen(szProj4),
+                     sizeof(szProj4) - strlen(szProj4),
+                     "+proj=igh " );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_GEOSTATIONARY_SATELLITE) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=geos +lon_0=%.16g +h=%.16g +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_SATELLITE_HEIGHT, 35785831.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP)
+             || EQUAL(pszProjection,
+                      SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=lcc +lat_1=%.16g +lat_2=%.16g +lat_0=%.16g +lon_0=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 0.0),
+             GetNormProjParm(SRS_PP_STANDARD_PARALLEL_2, 0.0),
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=lcc +lat_1=%.16g +lat_0=%.16g +lon_0=%.16g "
+             "+k_0=%.16g +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_HOTINE_OBLIQUE_MERCATOR) )
+    {
+        // Special case for swiss oblique mercator: see bug 423.
+        if( fabs(GetNormProjParm(SRS_PP_AZIMUTH, 0.0) - 90.0) < 0.0001
+            && fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 0.0)
+                    - 90.0) < 0.0001 )
+        {
+            CPLsnprintf(
+                 szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+                 "+proj=somerc +lat_0=%.16g +lon_0=%.16g "
+                 "+k_0=%.16g +x_0=%.16g +y_0=%.16g ",
+                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                 GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
         }
         else
         {
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g"
-                     " +k=%.16g +x_0=%.16g +y_0=%.16g +no_uoff ",
-                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_AZIMUTH,0.0),
-                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-
-            // RSO variant - http://trac.osgeo.org/proj/ticket/62
+            CPLsnprintf(
+                 szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+                 "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g "
+                 "+k=%.16g +x_0=%.16g +y_0=%.16g +no_uoff ",
+                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                 GetNormProjParm(SRS_PP_AZIMUTH, 0.0),
+                 GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+
+            // RSO variant: http://trac.osgeo.org/proj/ticket/62
             // Note that gamma is only supported by PROJ 4.8.0 and later.
-            if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0) != 1000.0 )
+            if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 1000.0) != 1000.0 )
             {
-                CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+gamma=%.16g ",
-                         GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0));
+                CPLsnprintf(
+                     szProj4 + strlen(szProj4),
+                     sizeof(szProj4) - strlen(szProj4),
+                     "+gamma=%.16g ",
+                     GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 1000.0));
             }
         }
     }
-
-    else if( EQUAL(pszProjection,SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER))
+    else if( EQUAL(pszProjection,
+                   SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER) )
     {
-        /* special case for swiss oblique mercator : see bug 423 */
-        if( fabs(GetNormProjParm(SRS_PP_AZIMUTH,0.0) - 90.0) < 0.0001
-            && fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,0.0)-90.0) < 0.0001 )
+        // Special case for swiss oblique mercator: see bug 423.
+        if( fabs(GetNormProjParm(SRS_PP_AZIMUTH, 0.0) - 90.0) < 0.0001 &&
+            fabs(GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 0.0)
+                 - 90.0) < 0.0001 )
         {
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
-                     " +k_0=%.16g +x_0=%.16g +y_0=%.16g ",
-                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+            CPLsnprintf(
+                 szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+                 "+proj=somerc +lat_0=%.16g +lon_0=%.16g "
+                 "+k_0=%.16g +x_0=%.16g +y_0=%.16g ",
+                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                 GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
         }
         else
         {
-            CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                     "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g"
-                     " +k=%.16g +x_0=%.16g +y_0=%.16g ",
-                     GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                     GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                     GetNormProjParm(SRS_PP_AZIMUTH,0.0),
-                     GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                     GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                     GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-
-            // RSO variant - http://trac.osgeo.org/proj/ticket/62
+            CPLsnprintf(
+                 szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+                 "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g "
+                 "+k=%.16g +x_0=%.16g +y_0=%.16g ",
+                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+                 GetNormProjParm(SRS_PP_AZIMUTH, 0.0),
+                 GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+
+            // RSO variant: http://trac.osgeo.org/proj/ticket/62
             // Note that gamma is only supported by PROJ 4.8.0 and later.
-            if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0) != 1000.0 )
+            if( GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE, 1000.0) != 1000.0 )
             {
-                CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4), "+gamma=%.16g ",
-                         GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,1000.0));
+                CPLsnprintf(szProj4 + strlen(szProj4),
+                            sizeof(szProj4) - strlen(szProj4),
+                            "+gamma=%.16g ",
+                            GetNormProjParm(SRS_PP_RECTIFIED_GRID_ANGLE,
+                                            1000.0));
             }
         }
     }
-
     else if( EQUAL(pszProjection,
                    SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN) )
     {
         // Not really clear which of Point_1/1st_Point convention is the
-        // "normalized" one, so accept both
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=omerc +lat_0=%.16g"
-                 " +lon_1=%.16g +lat_1=%.16g +lon_2=%.16g +lat_2=%.16g"
-                 " +k=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1,GetNormProjParm(SRS_PP_LONGITUDE_OF_1ST_POINT,0.0)),
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1,GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT,0.0)),
-                 GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2,GetNormProjParm(SRS_PP_LONGITUDE_OF_2ND_POINT,0.0)),
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2,GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT,0.0)),
-                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_KROVAK) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=krovak +lat_0=%.16g +lon_0=%.16g +alpha=%.16g"
-                 " +k=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER,0.0),
-                 GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER,0.0),
-                 GetNormProjParm(SRS_PP_AZIMUTH,0.0),
-                 GetNormProjParm(SRS_PP_SCALE_FACTOR,1.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_TWO_POINT_EQUIDISTANT) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=tpeqd +lat_1=%.16g +lon_1=%.16g "
-                 "+lat_2=%.16g +lon_2=%.16g "
-                 "+x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT,0.0),
-                 GetNormProjParm(SRS_PP_LONGITUDE_OF_1ST_POINT,0.0),
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT,0.0),
-                 GetNormProjParm(SRS_PP_LONGITUDE_OF_2ND_POINT,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
+        // "normalized" one, so accept both.
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=omerc +lat_0=%.16g "
+             "+lon_1=%.16g +lat_1=%.16g +lon_2=%.16g +lat_2=%.16g "
+             "+k=%.16g +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_1,
+                             GetNormProjParm(SRS_PP_LONGITUDE_OF_1ST_POINT,
+                                             0.0)),
+             GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_1,
+                             GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT,
+                                             0.0)),
+             GetNormProjParm(SRS_PP_LONGITUDE_OF_POINT_2,
+                             GetNormProjParm(SRS_PP_LONGITUDE_OF_2ND_POINT,
+                                             0.0)),
+             GetNormProjParm(SRS_PP_LATITUDE_OF_POINT_2,
+                             GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT,
+                                             0.0)),
+             GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_KROVAK) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=krovak +lat_0=%.16g +lon_0=%.16g +alpha=%.16g "
+             "+k=%.16g +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_CENTER, 0.0),
+             GetNormProjParm(SRS_PP_LONGITUDE_OF_CENTER, 0.0),
+             GetNormProjParm(SRS_PP_AZIMUTH, 0.0),
+             GetNormProjParm(SRS_PP_SCALE_FACTOR, 1.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_TWO_POINT_EQUIDISTANT) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=tpeqd +lat_1=%.16g +lon_1=%.16g "
+             "+lat_2=%.16g +lon_2=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT, 0.0),
+             GetNormProjParm(SRS_PP_LONGITUDE_OF_1ST_POINT, 0.0),
+             GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT, 0.0),
+             GetNormProjParm(SRS_PP_LONGITUDE_OF_2ND_POINT, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_IMW_POLYCONIC) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=iwm_p +lat_1=%.16g +lat_2=%.16g +lon_0=%.16g "
-                 "+x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT, 0.0),
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT, 0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=iwm_p +lat_1=%.16g +lat_2=%.16g +lon_0=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_1ST_POINT, 0.0),
+             GetNormProjParm(SRS_PP_LATITUDE_OF_2ND_POINT, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_I) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wag1 +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wag1 +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_II) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wag2 +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wag2 +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_III) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wag3 +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wag3 +lat_ts=%.16g +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_IV) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wag4 +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wag4 +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_V) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wag5 +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wag5 +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_VI) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wag6 +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wag6 +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
     }
-
     else if( EQUAL(pszProjection, SRS_PT_WAGNER_VII) )
     {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wag7 +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_QSC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=qsc +lat_0=%.16g +lon_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0) );
-    }
-
-    else if ( EQUAL(pszProjection, SRS_PT_SCH) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                "+proj=sch +plat_0=%.16g +plon_0=%.16g +phdg_0=%.16g +h_0=%.16g ",
-                GetNormProjParm(SRS_PP_PEG_POINT_LATITUDE, 0.0),
-                GetNormProjParm(SRS_PP_PEG_POINT_LONGITUDE, 0.0),
-                GetNormProjParm(SRS_PP_PEG_POINT_HEADING, 0.0),
-                GetNormProjParm(SRS_PP_PEG_POINT_HEIGHT, 0.0) );
-    }
-
-    /* Note: This never really gets used currently.  See bug 423 */
-    else if( EQUAL(pszProjection,SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=somerc +lat_0=%.16g +lon_0=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-    else if( EQUAL(pszProjection,SRS_PT_AITOFF) )
-    {
-        //+lat_ts=0.0
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=aitoff +lat_0=%.16g +lon_0=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0) );
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_WINKEL_I) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wink1 +lat_0=%.16g +lon_0=%.16g lat_ts=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,45.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0));
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_WINKEL_II) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wink2 +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,40.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0));
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wag7 +x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_QSC) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=qsc +lat_0=%.16g +lon_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_SCH) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=sch +plat_0=%.16g +plon_0=%.16g +phdg_0=%.16g +h_0=%.16g ",
+             GetNormProjParm(SRS_PP_PEG_POINT_LATITUDE, 0.0),
+             GetNormProjParm(SRS_PP_PEG_POINT_LONGITUDE, 0.0),
+             GetNormProjParm(SRS_PP_PEG_POINT_HEADING, 0.0),
+             GetNormProjParm(SRS_PP_PEG_POINT_HEIGHT, 0.0) );
+    }
+    // Note: This never really gets used currently.  See bug 423.
+    else if( EQUAL(pszProjection, SRS_PT_SWISS_OBLIQUE_CYLINDRICAL) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=somerc +lat_0=%.16g +lon_0=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_AITOFF) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=aitoff +lat_0=%.16g +lon_0=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0) );
+    }
+    else if( EQUAL(pszProjection, SRS_PT_WINKEL_I) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wink1 +lat_0=%.16g +lon_0=%.16g lat_ts=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 45.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
+    }
+    else if( EQUAL(pszProjection, SRS_PT_WINKEL_II) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wink2 +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 40.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
+    }
+    else if( EQUAL(pszProjection, SRS_PT_WINKEL_TRIPEL) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=wintri +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1, 40.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
+    }
+    else if( EQUAL(pszProjection, SRS_PT_CRASTER_PARABOLIC) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=crast +lat_0=%.16g +lon_0=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
+    }
+    else if( EQUAL(pszProjection, SRS_PT_LOXIMUTHAL) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=loxim +lon_0=%.16g +lat_1=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 40.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
+    }
+    else if( EQUAL(pszProjection, SRS_PT_QUARTIC_AUTHALIC) )
+    {
+        CPLsnprintf(
+             szProj4 + strlen(szProj4), sizeof(szProj4) - strlen(szProj4),
+             "+proj=qua_aut +lat_0=%.16g +lon_0=%.16g "
+             "+x_0=%.16g +y_0=%.16g ",
+             GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0),
+             GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_EASTING, 0.0),
+             GetNormProjParm(SRS_PP_FALSE_NORTHING, 0.0));
     }
-
-    else if( EQUAL(pszProjection,SRS_PT_WINKEL_TRIPEL) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=wintri +lat_0=%.16g +lon_0=%.16g +lat_1=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_STANDARD_PARALLEL_1,40.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0));
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_CRASTER_PARABOLIC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=crast +lat_0=%.16g +lon_0=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0));
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_LOXIMUTHAL) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=loxim +lon_0=%.16g +lat_1=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,40.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0));
-    }
-
-    else if( EQUAL(pszProjection,SRS_PT_QUARTIC_AUTHALIC) )
-    {
-        CPLsnprintf( szProj4+strlen(szProj4), sizeof(szProj4)-strlen(szProj4),
-                 "+proj=qua_aut +lat_0=%.16g +lon_0=%.16g"
-                 " +x_0=%.16g +y_0=%.16g ",
-                 GetNormProjParm(SRS_PP_LATITUDE_OF_ORIGIN,0.0),
-                 GetNormProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_EASTING,0.0),
-                 GetNormProjParm(SRS_PP_FALSE_NORTHING,0.0));
-    }
-
     else
     {
         CPLError( CE_Failure, CPLE_NotSupported,
@@ -2268,117 +2340,117 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 /*      Handle earth model.  For now we just always emit the user       */
 /*      defined ellipsoid parameters.                                   */
 /* -------------------------------------------------------------------- */
-    const double      dfSemiMajor = GetSemiMajor();
-    const double      dfInvFlattening = GetInvFlattening();
-    const char  *pszPROJ4Ellipse = NULL;
-    const char  *pszDatum = GetAttrValue("DATUM");
+    const double dfSemiMajor = GetSemiMajor();
+    const double dfInvFlattening = GetInvFlattening();
+    const char *pszPROJ4Ellipse = NULL;
+    const char *pszDatum = GetAttrValue("DATUM");
 
-    if( ABS(dfSemiMajor-6378249.145) < 0.01
-        && ABS(dfInvFlattening-293.465) < 0.0001 )
+    if( std::abs(dfSemiMajor-6378249.145) < 0.01
+        && std::abs(dfInvFlattening-293.465) < 0.0001 )
     {
-        pszPROJ4Ellipse = "clrk80";     /* Clark 1880 */
+        pszPROJ4Ellipse = "clrk80";     // Clark 1880
     }
-    else if( ABS(dfSemiMajor-6378245.0) < 0.01
-             && ABS(dfInvFlattening-298.3) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378245.0) < 0.01
+             && std::abs(dfInvFlattening-298.3) < 0.0001 )
     {
-        pszPROJ4Ellipse = "krass";      /* Krassovsky */
+        pszPROJ4Ellipse = "krass";      // Krassovsky
     }
-    else if( ABS(dfSemiMajor-6378388.0) < 0.01
-             && ABS(dfInvFlattening-297.0) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378388.0) < 0.01
+             && std::abs(dfInvFlattening-297.0) < 0.0001 )
     {
-        pszPROJ4Ellipse = "intl";       /* International 1924 */
+        pszPROJ4Ellipse = "intl";       // International 1924
     }
-    else if( ABS(dfSemiMajor-6378160.0) < 0.01
-             && ABS(dfInvFlattening-298.25) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378160.0) < 0.01
+             && std::abs(dfInvFlattening-298.25) < 0.0001 )
     {
-        pszPROJ4Ellipse = "aust_SA";    /* Australian */
+        pszPROJ4Ellipse = "aust_SA";    // Australian
     }
-    else if( ABS(dfSemiMajor-6377397.155) < 0.01
-             && ABS(dfInvFlattening-299.1528128) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6377397.155) < 0.01
+             && std::abs(dfInvFlattening-299.1528128) < 0.0001 )
     {
-        pszPROJ4Ellipse = "bessel";     /* Bessel 1841 */
+        pszPROJ4Ellipse = "bessel";     // Bessel 1841
     }
-    else if( ABS(dfSemiMajor-6377483.865) < 0.01
-             && ABS(dfInvFlattening-299.1528128) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6377483.865) < 0.01
+             && std::abs(dfInvFlattening-299.1528128) < 0.0001 )
     {
-        pszPROJ4Ellipse = "bess_nam";   /* Bessel 1841 (Namibia / Schwarzeck)*/
+        pszPROJ4Ellipse = "bess_nam";   // Bessel 1841 (Namibia / Schwarzeck)
     }
-    else if( ABS(dfSemiMajor-6378160.0) < 0.01
-             && ABS(dfInvFlattening-298.247167427) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378160.0) < 0.01
+             && std::abs(dfInvFlattening-298.247167427) < 0.0001 )
     {
-        pszPROJ4Ellipse = "GRS67";      /* GRS 1967 */
+        pszPROJ4Ellipse = "GRS67";      // GRS 1967
     }
-    else if( ABS(dfSemiMajor-6378137) < 0.01
-             && ABS(dfInvFlattening-298.257222101) < 0.000001 )
+    else if( std::abs(dfSemiMajor-6378137) < 0.01
+             && std::abs(dfInvFlattening-298.257222101) < 0.000001 )
     {
-        pszPROJ4Ellipse = "GRS80";      /* GRS 1980 */
+        pszPROJ4Ellipse = "GRS80";      // GRS 1980
     }
-    else if( ABS(dfSemiMajor-6378206.4) < 0.01
-             && ABS(dfInvFlattening-294.9786982) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378206.4) < 0.01
+             && std::abs(dfInvFlattening-294.9786982) < 0.0001 )
     {
-        pszPROJ4Ellipse = "clrk66";     /* Clarke 1866 */
+        pszPROJ4Ellipse = "clrk66";     // Clarke 1866
     }
-    else if( ABS(dfSemiMajor-6377340.189) < 0.01
-             && ABS(dfInvFlattening-299.3249646) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6377340.189) < 0.01
+             && std::abs(dfInvFlattening-299.3249646) < 0.0001 )
     {
-        pszPROJ4Ellipse = "mod_airy";   /* Modified Airy */
+        pszPROJ4Ellipse = "mod_airy";   // Modified Airy
     }
-    else if( ABS(dfSemiMajor-6377563.396) < 0.01
-             && ABS(dfInvFlattening-299.3249646) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6377563.396) < 0.01
+             && std::abs(dfInvFlattening-299.3249646) < 0.0001 )
     {
-        pszPROJ4Ellipse = "airy";       /* Airy */
+        pszPROJ4Ellipse = "airy";       // Airy
     }
-    else if( ABS(dfSemiMajor-6378200) < 0.01
-             && ABS(dfInvFlattening-298.3) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378200) < 0.01
+             && std::abs(dfInvFlattening-298.3) < 0.0001 )
     {
-        pszPROJ4Ellipse = "helmert";    /* Helmert 1906 */
+        pszPROJ4Ellipse = "helmert";    // Helmert 1906
     }
-    else if( ABS(dfSemiMajor-6378155) < 0.01
-             && ABS(dfInvFlattening-298.3) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378155) < 0.01
+             && std::abs(dfInvFlattening-298.3) < 0.0001 )
     {
-        pszPROJ4Ellipse = "fschr60m";   /* Modified Fischer 1960 */
+        pszPROJ4Ellipse = "fschr60m";   // Modified Fischer 1960
     }
-    else if( ABS(dfSemiMajor-6377298.556) < 0.01
-             && ABS(dfInvFlattening-300.8017) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6377298.556) < 0.01
+             && std::abs(dfInvFlattening-300.8017) < 0.0001 )
     {
-        pszPROJ4Ellipse = "evrstSS";    /* Everest (Sabah & Sarawak) */
+        pszPROJ4Ellipse = "evrstSS";    // Everest (Sabah & Sarawak)
     }
-    else if( ABS(dfSemiMajor-6378165.0) < 0.01
-             && ABS(dfInvFlattening-298.3) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378165.0) < 0.01
+             && std::abs(dfInvFlattening-298.3) < 0.0001 )
     {
         pszPROJ4Ellipse = "WGS60";
     }
-    else if( ABS(dfSemiMajor-6378145.0) < 0.01
-             && ABS(dfInvFlattening-298.25) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378145.0) < 0.01
+             && std::abs(dfInvFlattening-298.25) < 0.0001 )
     {
         pszPROJ4Ellipse = "WGS66";
     }
-    else if( ABS(dfSemiMajor-6378135.0) < 0.01
-             && ABS(dfInvFlattening-298.26) < 0.0001 )
+    else if( std::abs(dfSemiMajor-6378135.0) < 0.01
+             && std::abs(dfInvFlattening-298.26) < 0.0001 )
     {
         pszPROJ4Ellipse = "WGS72";
     }
-    else if( ABS(dfSemiMajor-6378137.0) < 0.01
-             && ABS(dfInvFlattening-298.257223563) < 0.000001 )
+    else if( std::abs(dfSemiMajor-6378137.0) < 0.01
+             && std::abs(dfInvFlattening-298.257223563) < 0.000001 )
     {
         pszPROJ4Ellipse = "WGS84";
     }
-    else if( pszDatum != NULL && EQUAL(pszDatum,"North_American_Datum_1927") )
+    else if( pszDatum != NULL && EQUAL(pszDatum, "North_American_Datum_1927") )
     {
-//        pszPROJ4Ellipse = "clrk66:+datum=nad27"; /* NAD 27 */
+        // pszPROJ4Ellipse = "clrk66:+datum=nad27";  // NAD 27
         pszPROJ4Ellipse = "clrk66";
     }
-    else if( pszDatum != NULL && EQUAL(pszDatum,"North_American_Datum_1983") )
+    else if( pszDatum != NULL && EQUAL(pszDatum, "North_American_Datum_1983") )
     {
-//        pszPROJ4Ellipse = "GRS80:+datum=nad83";       /* NAD 83 */
+        // pszPROJ4Ellipse = "GRS80:+datum=nad83";  // NAD 83
         pszPROJ4Ellipse = "GRS80";
     }
 
-    char szEllipseDef[128];
+    char szEllipseDef[128] = {};
 
     if( pszPROJ4Ellipse == NULL )
-      CPLsnprintf( szEllipseDef, sizeof(szEllipseDef), "+a=%.16g +b=%.16g ",
-                 GetSemiMajor(), GetSemiMinor() );
+        CPLsnprintf( szEllipseDef, sizeof(szEllipseDef), "+a=%.16g +b=%.16g ",
+                     GetSemiMajor(), GetSemiMinor() );
     else
         CPLsnprintf( szEllipseDef, sizeof(szEllipseDef), "+ellps=%s ",
                  pszPROJ4Ellipse );
@@ -2394,29 +2466,33 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
     const char *pszAuthority = GetAuthorityName( "DATUM" );
 
-    if( pszAuthority != NULL && EQUAL(pszAuthority,"EPSG") )
+    if( pszAuthority != NULL && EQUAL(pszAuthority, "EPSG") )
         nEPSGDatum = atoi(GetAuthorityCode( "DATUM" ));
 
     const char *pszGeogCSAuthority = GetAuthorityName( "GEOGCS" );
 
-    if( pszGeogCSAuthority != NULL && EQUAL(pszGeogCSAuthority,"EPSG") )
+    if( pszGeogCSAuthority != NULL && EQUAL(pszGeogCSAuthority, "EPSG") )
         nEPSGGeogCS = atoi(GetAuthorityCode( "GEOGCS" ));
 
     if( pszDatum == NULL )
-        /* nothing */;
-
-    else if( EQUAL(pszDatum,SRS_DN_NAD27) || nEPSGDatum == 6267 )
+    {
+        // Nothing.
+    }
+    else if( EQUAL(pszDatum, SRS_DN_NAD27) || nEPSGDatum == 6267 )
+    {
         pszPROJ4Datum = "NAD27";
-
-    else if( EQUAL(pszDatum,SRS_DN_NAD83) || nEPSGDatum == 6269 )
+    }
+    else if( EQUAL(pszDatum, SRS_DN_NAD83) || nEPSGDatum == 6269 )
+    {
         pszPROJ4Datum = "NAD83";
-
-    else if( EQUAL(pszDatum,SRS_DN_WGS84) || nEPSGDatum == 6326 )
+    }
+    else if( EQUAL(pszDatum, SRS_DN_WGS84) || nEPSGDatum == 6326 )
+    {
         pszPROJ4Datum = "WGS84";
-
+    }
     else if( (pszPROJ4Datum = OGRGetProj4Datum(pszDatum, nEPSGDatum)) != NULL )
     {
-        /* nothing */
+        // Nothing.
     }
 
     if( pszProj4Grids != NULL )
@@ -2425,30 +2501,30 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         szEllipseDef[0] = '\0';
         SAFE_PROJ4_STRCAT( "+nadgrids=" );
         SAFE_PROJ4_STRCAT( pszProj4Grids );
-        SAFE_PROJ4_STRCAT(  " " );
+        SAFE_PROJ4_STRCAT( " " );
         pszPROJ4Datum = NULL;
     }
 
     if( pszPROJ4Datum == NULL
-        || CPLTestBool(CPLGetConfigOption("OVERRIDE_PROJ_DATUM_WITH_TOWGS84", "YES")) )
+        || CPLTestBool(CPLGetConfigOption("OVERRIDE_PROJ_DATUM_WITH_TOWGS84",
+                                          "YES")) )
     {
         if( poTOWGS84 != NULL )
         {
-            int iChild;
             if( poTOWGS84->GetChildCount() >= 3
                 && (poTOWGS84->GetChildCount() < 7
-                    || (EQUAL(poTOWGS84->GetChild(3)->GetValue(),"")
-                        && EQUAL(poTOWGS84->GetChild(4)->GetValue(),"")
-                        && EQUAL(poTOWGS84->GetChild(5)->GetValue(),"")
-                        && EQUAL(poTOWGS84->GetChild(6)->GetValue(),""))) )
+                    || (EQUAL(poTOWGS84->GetChild(3)->GetValue(), "")
+                        && EQUAL(poTOWGS84->GetChild(4)->GetValue(), "")
+                        && EQUAL(poTOWGS84->GetChild(5)->GetValue(), "")
+                        && EQUAL(poTOWGS84->GetChild(6)->GetValue(), ""))) )
             {
                 SAFE_PROJ4_STRCAT( szEllipseDef );
                 szEllipseDef[0] = '\0';
                 SAFE_PROJ4_STRCAT( "+towgs84=");
-                for(iChild = 0; iChild < 3; iChild ++)
+                for( int iChild = 0; iChild < 3; iChild++ )
                 {
-                    if (iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
-                    SAFE_PROJ4_STRCAT( poTOWGS84->GetChild(iChild)->GetValue() );
+                    if( iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
+                    SAFE_PROJ4_STRCAT(poTOWGS84->GetChild(iChild)->GetValue());
                 }
                 SAFE_PROJ4_STRCAT( " " );
                 pszPROJ4Datum = NULL;
@@ -2458,16 +2534,15 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
                 SAFE_PROJ4_STRCAT( szEllipseDef );
                 szEllipseDef[0] = '\0';
                 SAFE_PROJ4_STRCAT( "+towgs84=");
-                for(iChild = 0; iChild < 7; iChild ++)
+                for( int iChild = 0; iChild < 7; iChild++ )
                 {
-                    if (iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
-                    SAFE_PROJ4_STRCAT( poTOWGS84->GetChild(iChild)->GetValue() );
+                    if( iChild > 0 ) SAFE_PROJ4_STRCAT( "," );
+                    SAFE_PROJ4_STRCAT(poTOWGS84->GetChild(iChild)->GetValue());
                 }
                 SAFE_PROJ4_STRCAT( " " );
                 pszPROJ4Datum = NULL;
             }
         }
-
         // If we don't know the datum, trying looking up TOWGS84 parameters
         // based on the EPSG GCS code.
         else if( nEPSGGeogCS != -1 && pszPROJ4Datum == NULL )
@@ -2475,7 +2550,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
             std::vector<CPLString> asBursaTransform;
             if( EPSGGetWGS84Transform( nEPSGGeogCS, asBursaTransform ) )
             {
-                char szTOWGS84[256];
+                char szTOWGS84[256] = {};
                 CPLsnprintf( szTOWGS84, sizeof(szTOWGS84),
                              "+towgs84=%s,%s,%s,%s,%s,%s,%s",
                              asBursaTransform[0].c_str(),
@@ -2501,11 +2576,12 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         SAFE_PROJ4_STRCAT( pszPROJ4Datum );
         SAFE_PROJ4_STRCAT( " " );
     }
-    else // The ellipsedef may already have been appended and will now
-         // be empty, otherwise append now.
+    else
     {
+        // The ellipsedef may already have been appended and will now
+        // be empty, otherwise append now.
         SAFE_PROJ4_STRCAT( szEllipseDef );
-        szEllipseDef[0] = '\0';
+        // szEllipseDef[0] = '\0';
     }
 
 /* -------------------------------------------------------------------- */
@@ -2515,25 +2591,26 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
         && CPLAtof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
     {
         pszAuthority = GetAuthorityName( "PRIMEM" );
-        int  nCode = -1;
-
-        if( pszAuthority != NULL && EQUAL(pszAuthority,"EPSG") )
-            nCode = atoi(GetAuthorityCode( "PRIMEM" ));
+        const int nCode =
+            pszAuthority != NULL && EQUAL(pszAuthority, "EPSG")
+            ? atoi(GetAuthorityCode( "PRIMEM" ))
+            : -1;
 
         const OGRProj4PM* psProj4PM = NULL;
-        if (nCode > 0)
+        if( nCode > 0 )
             psProj4PM = OGRGetProj4PMFromCode(nCode);
-        if (psProj4PM == NULL)
+        if( psProj4PM == NULL )
             psProj4PM = OGRGetProj4PMFromVal(l_dfFromGreenwich);
 
-        char szPMValue[128];
-        if (psProj4PM != NULL)
+        char szPMValue[128] = {};
+        if( psProj4PM != NULL )
         {
             strcpy( szPMValue, psProj4PM->pszProj4PMName );
         }
         else
         {
-            CPLsnprintf( szPMValue, sizeof(szPMValue), "%.16g", l_dfFromGreenwich );
+            CPLsnprintf( szPMValue, sizeof(szPMValue),
+                         "%.16g", l_dfFromGreenwich );
         }
 
         SAFE_PROJ4_STRCAT( "+pm=" );
@@ -2544,16 +2621,18 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 /* -------------------------------------------------------------------- */
 /*      Handle linear units.                                            */
 /* -------------------------------------------------------------------- */
-    const char  *pszPROJ4Units=NULL;
-    char        *pszLinearUnits = NULL;
-    double      dfLinearConv = GetLinearUnits( &pszLinearUnits );
+    const char *pszPROJ4Units=NULL;
+    char *pszLinearUnits = NULL;
+    double dfLinearConv = GetLinearUnits( &pszLinearUnits );
 
-    if( strstr(szProj4,"longlat") != NULL )
+    if( strstr(szProj4, "longlat") != NULL )
+    {
         pszPROJ4Units = NULL;
+    }
     else
     {
-        const LinearUnitsStruct* psLinearUnits = GetLinearFromLinearConvOrName(
-                                                dfLinearConv, pszLinearUnits );
+        const LinearUnitsStruct* psLinearUnits =
+            GetLinearFromLinearConvOrName( dfLinearConv, pszLinearUnits );
         if( psLinearUnits != NULL )
             pszPROJ4Units = psLinearUnits->pszProjName;
         else
@@ -2561,8 +2640,9 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
         if( pszPROJ4Units == NULL )
         {
-            char szLinearConv[128];
-            CPLsnprintf( szLinearConv, sizeof(szLinearConv), "%.16g", dfLinearConv );
+            char szLinearConv[128] = {};
+            CPLsnprintf( szLinearConv, sizeof(szLinearConv),
+                         "%.16g", dfLinearConv );
             SAFE_PROJ4_STRCAT( "+to_meter=" );
             SAFE_PROJ4_STRCAT( szLinearConv );
             SAFE_PROJ4_STRCAT( " " );
@@ -2577,7 +2657,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we have vertical datum grids, attach them to the proj.4 string.*/
+/*   If we have vertical datum grids, attach them to the proj.4 string. */
 /* -------------------------------------------------------------------- */
     const char *pszProj4Geoids = GetExtension( "VERT_DATUM", "PROJ4_GRIDS" );
 
@@ -2585,7 +2665,7 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
     {
         SAFE_PROJ4_STRCAT( "+geoidgrids=" );
         SAFE_PROJ4_STRCAT( pszProj4Geoids );
-        SAFE_PROJ4_STRCAT(  " " );
+        SAFE_PROJ4_STRCAT( " " );
     }
 
 /* -------------------------------------------------------------------- */
@@ -2603,9 +2683,9 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
         dfLinearConv = CPLAtof( poVUNITS->GetChild(1)->GetValue() );
 
-        const LinearUnitsStruct* psLinearUnits = GetLinearFromLinearConvOrName(
-                                                dfLinearConv,
-                                                poVUNITS->GetChild(0)->GetValue() );
+        const LinearUnitsStruct* psLinearUnits =
+            GetLinearFromLinearConvOrName(dfLinearConv,
+                                          poVUNITS->GetChild(0)->GetValue());
         if( psLinearUnits != NULL )
             pszPROJ4Units = psLinearUnits->pszProjName;
         else
@@ -2613,8 +2693,9 @@ OGRErr OGRSpatialReference::exportToProj4( char ** ppszProj4 ) const
 
         if( pszPROJ4Units == NULL )
         {
-            char szLinearConv[128];
-            CPLsnprintf( szLinearConv, sizeof(szLinearConv), "%.16g", dfLinearConv );
+            char szLinearConv[128] = {};
+            CPLsnprintf( szLinearConv, sizeof(szLinearConv),
+                         "%.16g", dfLinearConv );
             SAFE_PROJ4_STRCAT( "+vto_meter=" );
             SAFE_PROJ4_STRCAT( szLinearConv );
             SAFE_PROJ4_STRCAT( " " );
diff --git a/ogr/ogr_srs_usgs.cpp b/ogr/ogr_srs_usgs.cpp
index d8e6881..07c8088 100644
--- a/ogr/ogr_srs_usgs.cpp
+++ b/ogr/ogr_srs_usgs.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_usgs.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference translation to/from USGS georeferencing
@@ -29,80 +28,89 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
-#include "ogr_p.h"
+#include "cpl_port.h"
+#include "ogr_srs_api.h"
+
+#include <cmath>
+#include <cstddef>
+
 #include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogr_srs_usgs.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogr_srs_usgs.cpp 36305 2016-11-19 21:59:12Z goatbar $");
 
 /************************************************************************/
 /*  GCTP projection codes.                                              */
 /************************************************************************/
 
-#define GEO     0L      // Geographic
-#define UTM     1L      // Universal Transverse Mercator (UTM)
-#define SPCS    2L      // State Plane Coordinates
-#define ALBERS  3L      // Albers Conical Equal Area
-#define LAMCC   4L      // Lambert Conformal Conic
-#define MERCAT  5L      // Mercator
-#define PS      6L      // Polar Stereographic
-#define POLYC   7L      // Polyconic
-#define EQUIDC  8L      // Equidistant Conic
-#define TM      9L      // Transverse Mercator
-#define STEREO  10L     // Stereographic
-#define LAMAZ   11L     // Lambert Azimuthal Equal Area
-#define AZMEQD  12L     // Azimuthal Equidistant
-#define GNOMON  13L     // Gnomonic
-#define ORTHO   14L     // Orthographic
-#define GVNSP   15L     // General Vertical Near-Side Perspective
-#define SNSOID  16L     // Sinusiodal
-#define EQRECT  17L     // Equirectangular
-#define MILLER  18L     // Miller Cylindrical
-#define VGRINT  19L     // Van der Grinten
-#define HOM     20L     // (Hotine) Oblique Mercator
-#define ROBIN   21L     // Robinson
-#define SOM     22L     // Space Oblique Mercator (SOM)
-#define ALASKA  23L     // Alaska Conformal
-#define GOODE   24L     // Interrupted Goode Homolosine
-#define MOLL    25L     // Mollweide
-#define IMOLL   26L     // Interrupted Mollweide
-#define HAMMER  27L     // Hammer
-#define WAGIV   28L     // Wagner IV
-#define WAGVII  29L     // Wagner VII
-#define OBEQA   30L     // Oblated Equal Area
-#define ISINUS1 31L     // Integerized Sinusoidal Grid (the same as 99)
-#define CEA     97L     // Cylindrical Equal Area (Grid corners set
-                        // in meters for EASE grid)
-#define BCEA    98L     // Cylindrical Equal Area (Grid corners set
-                        // in DMS degs for EASE grid)
-#define ISINUS  99L     // Integerized Sinusoidal Grid
-                        // (added by Raj Gejjagaraguppe ARC for MODIS)
+static const long GEO    = 0L;   // Geographic
+static const long UTM    = 1L;   // Universal Transverse Mercator (UTM)
+static const long SPCS   = 2L;   // State Plane Coordinates
+static const long ALBERS = 3L;   // Albers Conical Equal Area
+static const long LAMCC  = 4L;   // Lambert Conformal Conic
+static const long MERCAT = 5L;   // Mercator
+static const long PS     = 6L;   // Polar Stereographic
+static const long POLYC  = 7L;   // Polyconic
+static const long EQUIDC = 8L;   // Equidistant Conic
+static const long TM     = 9L;   // Transverse Mercator
+static const long STEREO = 10L;  // Stereographic
+static const long LAMAZ  = 11L;  // Lambert Azimuthal Equal Area
+static const long AZMEQD = 12L;  // Azimuthal Equidistant
+static const long GNOMON = 13L;  // Gnomonic
+static const long ORTHO  = 14L;  // Orthographic
+// static const long GVNSP  = 15L;  // General Vertical Near-Side Perspective
+static const long SNSOID = 16L;  // Sinusiodal
+static const long EQRECT = 17L;  // Equirectangular
+static const long MILLER = 18L;  // Miller Cylindrical
+static const long VGRINT = 19L;  // Van der Grinten
+static const long HOM    = 20L;  // (Hotine) Oblique Mercator
+static const long ROBIN  = 21L;  // Robinson
+// static const long SOM    = 22L;  // Space Oblique Mercator (SOM)
+// static const long ALASKA = 23L;  // Alaska Conformal
+// static const long GOODE  = 24L;  // Interrupted Goode Homolosine
+static const long MOLL   = 25L;  // Mollweide
+// static const long IMOLL  = 26L;  // Interrupted Mollweide
+// static const long HAMMER = 27L;  // Hammer
+static const long WAGIV  = 28L;  // Wagner IV
+static const long WAGVII = 29L;  // Wagner VII
+// static const long OBEQA  = 30L;  // Oblated Equal Area
+// static const long ISINUS1 = 31L; // Integerized Sinusoidal Grid (the same as 99)
+// static const long CEA    = 97L;  // Cylindrical Equal Area (Grid corners set
+                                 // in meters for EASE grid)
+// static const long BCEA   = 98L;  // Cylindrical Equal Area (Grid corners set
+                                 // in DMS degs for EASE grid)
+// static const long ISINUS = 99L;  // Integerized Sinusoidal Grid
+                                 // (added by Raj Gejjagaraguppe ARC for MODIS)
 
 /************************************************************************/
 /*  GCTP ellipsoid codes.                                               */
 /************************************************************************/
 
-#define CLARKE1866          0L
-#define CLARKE1880          1L
-#define BESSEL              2L
-#define INTERNATIONAL1967   3L
-#define INTERNATIONAL1909   4L
-#define WGS72               5L
-#define EVEREST             6L
-#define WGS66               7L
-#define GRS1980             8L
-#define AIRY                9L
-#define MODIFIED_EVEREST    10L
-#define MODIFIED_AIRY       11L
-#define WGS84               12L
-#define SOUTHEAST_ASIA      13L
-#define AUSTRALIAN_NATIONAL 14L
-#define KRASSOVSKY          15L
-#define HOUGH               16L
-#define MERCURY1960         17L
-#define MODIFIED_MERCURY    18L
-#define SPHERE              19L
+static const long CLARKE1866         = 0L;
+// static const long CLARKE1880         = 1L;
+// static const long BESSEL             = 2L;
+// static const long INTERNATIONAL1967  = 3L;
+// static const long INTERNATIONAL1909  = 4L;
+// static const long WGS72              = 5L;
+// static const long EVEREST            = 6L;
+// static const long WGS66              = 7L;
+static const long GRS1980            = 8L;
+// static const long AIRY               = 9L;
+// static const long MODIFIED_EVEREST   = 10L;
+// static const long MODIFIED_AIRY      = 11L;
+static const long WGS84              = 12L;
+// static const long SOUTHEAST_ASIA     = 13L;
+// static const long AUSTRALIAN_NATIONAL= 14L;
+// static const long KRASSOVSKY         = 15L;
+// static const long HOUGH              = 16L;
+// static const long MERCURY1960        = 17L;
+// static const long MODIFIED_MERCURY   = 18L;
+// static const long SPHERE             = 19L;
 
 /************************************************************************/
 /*  Correspondence between GCTP and EPSG ellipsoid codes.               */
@@ -113,7 +121,7 @@ static const int aoEllips[] =
     7008,   // Clarke, 1866 (NAD1927)
     7034,   // Clarke, 1880
     7004,   // Bessel, 1841
-    0,// FIXME: New International, 1967 --- skipped
+    0,      // FIXME: New International, 1967 --- skipped
     7022,   // International, 1924 (Hayford, 1909) XXX?
     7043,   // WGS, 1972
     7042,   // Everest, 1830
@@ -123,24 +131,24 @@ static const int aoEllips[] =
     7018,   // Modified Everest
     7002,   // Modified Airy
     7030,   // WGS, 1984 (GPS)
-    0,// FIXME: Southeast Asia --- skipped
+    0,      // FIXME: Southeast Asia --- skipped
     7003,   // Australian National, 1965
     7024,   // Krassovsky, 1940
     7053,   // Hough
-    0,// FIXME: Mercury, 1960 --- skipped
-    0,// FIXME: Modified Mercury, 1968 --- skipped
+    0,      // FIXME: Mercury, 1960 --- skipped
+    0,      // FIXME: Modified Mercury, 1968 --- skipped
     7047,   // Sphere, rad 6370997 m (normal sphere)
     7006,   // Bessel, 1841 (Namibia)
     7016,   // Everest (Sabah & Sarawak)
     7044,   // Everest, 1956
     7056,   // Everest, Malaysia 1969
     7018,   // Everest, Malay & Singapr 1948
-    0,// FIXME: Everest, Pakistan --- skipped
+    0,      // FIXME: Everest, Pakistan --- skipped
     7022,   // Hayford (International 1924) XXX?
     7020,   // Helmert 1906
     7021,   // Indonesian, 1974
     7036,   // South American, 1969
-    0// FIXME: WGS 60 --- skipped
+    0       // FIXME: WGS 60 --- skipped
 };
 
 #define NUMBER_OF_ELLIPSOIDS    (int)(sizeof(aoEllips)/sizeof(aoEllips[0]))
@@ -165,14 +173,14 @@ OGRErr OSRImportFromUSGS( OGRSpatialReferenceH hSRS, long iProjsys,
                                                            iDatum );
 }
 
-static double OGRSpatialReferenceUSGSUnpackNoOp(double dfVal)
+static double OGRSpatialReferenceUSGSUnpackNoOp( double dfVal )
 {
     return dfVal;
 }
 
-static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
+static double OGRSpatialReferenceUSGSUnpackRadian( double dfVal )
 {
-    return (dfVal * 180.0 / M_PI);
+    return dfVal * 180.0 / M_PI;
 }
 
 /************************************************************************/
@@ -403,7 +411,9 @@ static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
  *      19: Sphere of Radius 6370997 meters
  * </pre>
  *
- * @param nUSGSAngleFormat one of USGS_ANGLE_DECIMALDEGREES, USGS_ANGLE_PACKEDDMS, or USGS_ANGLE_RADIANS (default is USGS_ANGLE_PACKEDDMS).
+ * @param nUSGSAngleFormat one of USGS_ANGLE_DECIMALDEGREES,
+ *    USGS_ANGLE_PACKEDDMS, or USGS_ANGLE_RADIANS (default is
+ *    USGS_ANGLE_PACKEDDMS).
  *
  * @return OGRERR_NONE on success or an error code in case of failure.
  */
@@ -411,7 +421,7 @@ static double OGRSpatialReferenceUSGSUnpackRadian(double dfVal)
 OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
                                             double *padfPrjParams,
                                             long iDatum,
-                                            int nUSGSAngleFormat  )
+                                            int nUSGSAngleFormat )
 
 {
     if( !padfPrjParams )
@@ -419,9 +429,9 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
 
     double (*pfnUnpackAnglesFn)(double) = NULL;
 
-    if (nUSGSAngleFormat == USGS_ANGLE_DECIMALDEGREES )
+    if( nUSGSAngleFormat == USGS_ANGLE_DECIMALDEGREES )
         pfnUnpackAnglesFn = OGRSpatialReferenceUSGSUnpackNoOp;
-    else if (nUSGSAngleFormat == USGS_ANGLE_RADIANS )
+    else if( nUSGSAngleFormat == USGS_ANGLE_RADIANS )
         pfnUnpackAnglesFn = OGRSpatialReferenceUSGSUnpackRadian;
     else
         pfnUnpackAnglesFn = CPLPackedDMSToDec;
@@ -429,7 +439,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
 /* -------------------------------------------------------------------- */
 /*      Operate on the basis of the projection code.                    */
 /* -------------------------------------------------------------------- */
-    switch ( iProjSys )
+    switch( iProjSys )
     {
         case GEO:
             break;
@@ -438,25 +448,30 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
             {
                 int bNorth = TRUE;
 
-                if ( !iZone )
+                if( !iZone )
                 {
-                    if ( padfPrjParams[2] != 0.0 )
-                        iZone = (long) padfPrjParams[2];
-                    else if (padfPrjParams[0] != 0.0 && padfPrjParams[1] != 0.0)
+                    if( padfPrjParams[2] != 0.0 )
+                    {
+                        iZone = static_cast<long>(padfPrjParams[2]);
+                    }
+                    else if( padfPrjParams[0] != 0.0 &&
+                             padfPrjParams[1] != 0.0 )
                     {
-                        iZone = (long)(((pfnUnpackAnglesFn(padfPrjParams[0])
-                                         + 180.0) / 6.0) + 1.0);
-                        if ( pfnUnpackAnglesFn(padfPrjParams[0]) < 0 )
+                        const double dfUnpackedAngle =
+                            pfnUnpackAnglesFn(padfPrjParams[0]);
+                        iZone = static_cast<long>(
+                            ((dfUnpackedAngle + 180.0) / 6.0) + 1.0);
+                        if( dfUnpackedAngle < 0 )
                             bNorth = FALSE;
                     }
                 }
 
-                if ( iZone < 0 )
+                if( iZone < 0 )
                 {
                     iZone = -iZone;
                     bNorth = FALSE;
                 }
-                SetUTM( (int)iZone, bNorth );
+                SetUTM( static_cast<int>(iZone), bNorth );
             }
             break;
 
@@ -464,14 +479,14 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
             {
                 int bNAD83 = TRUE;
 
-                if ( iDatum == 0 )
+                if( iDatum == 0 )
                     bNAD83 = FALSE;
-                else if ( iDatum != 8 )
+                else if( iDatum != 8 )
                     CPLError( CE_Warning, CPLE_AppDefined,
                               "Wrong datum for State Plane projection %d. "
-                              "Should be 0 or 8.", (int) iDatum );
+                              "Should be 0 or 8.", static_cast<int>(iDatum) );
 
-                SetStatePlane( (int)iZone, bNAD83 );
+                SetStatePlane( static_cast<int>(iZone), bNAD83 );
             }
             break;
 
@@ -513,7 +528,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
             break;
 
         case EQUIDC:
-            if ( padfPrjParams[8] )
+            if( padfPrjParams[8] != 0.0 )
             {
                 SetEC( pfnUnpackAnglesFn(padfPrjParams[2]),
                        pfnUnpackAnglesFn(padfPrjParams[3]),
@@ -569,7 +584,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
                              padfPrjParams[6], padfPrjParams[7] );
             break;
 
-        // FIXME: GVNSP --- General Vertical Near-Side Perspective skipped
+        // FIXME: GVNSP --- General Vertical Near-Side Perspective skipped.
 
         case SNSOID:
             SetSinusoidal( pfnUnpackAnglesFn(padfPrjParams[4]),
@@ -595,13 +610,13 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
             break;
 
         case HOM:
-            if ( padfPrjParams[12] )
+            if( padfPrjParams[12] != 0.0 )
             {
                 SetHOM( pfnUnpackAnglesFn(padfPrjParams[5]),
                         pfnUnpackAnglesFn(padfPrjParams[4]),
                         pfnUnpackAnglesFn(padfPrjParams[3]),
                         0.0, padfPrjParams[2],
-                        padfPrjParams[6],  padfPrjParams[7] );
+                        padfPrjParams[6], padfPrjParams[7] );
             }
             else
             {
@@ -611,7 +626,7 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
                             pfnUnpackAnglesFn(padfPrjParams[11]),
                             pfnUnpackAnglesFn(padfPrjParams[10]),
                             padfPrjParams[2],
-                            padfPrjParams[6],  padfPrjParams[7] );
+                            padfPrjParams[6], padfPrjParams[7] );
             }
             break;
 
@@ -620,20 +635,17 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
                          padfPrjParams[6], padfPrjParams[7] );
             break;
 
-        // FIXME: SOM --- Space Oblique Mercator skipped
-
-        // FIXME: ALASKA --- Alaska Conformal skipped
-
-        // FIXME: GOODE --- Interrupted Goode skipped
+        // FIXME: SOM --- Space Oblique Mercator skipped.
+        // FIXME: ALASKA --- Alaska Conformal skipped.
+        // FIXME: GOODE --- Interrupted Goode skipped.
 
         case MOLL:
             SetMollweide( pfnUnpackAnglesFn(padfPrjParams[4]),
                           padfPrjParams[6], padfPrjParams[7] );
             break;
 
-        // FIXME: IMOLL --- Interrupted Mollweide skipped
-
-        // FIXME: HAMMER --- Hammer skipped
+        // FIXME: IMOLL --- Interrupted Mollweide skipped.
+        // FIXME: HAMMER --- Hammer skipped.
 
         case WAGIV:
             SetWagner( 4, 0.0, padfPrjParams[6], padfPrjParams[7] );
@@ -643,56 +655,58 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
             SetWagner( 7, 0.0, padfPrjParams[6], padfPrjParams[7] );
             break;
 
-        // FIXME: OBEQA --- Oblated Equal Area skipped
-
-        // FIXME: ISINUS1 --- Integerized Sinusoidal Grid (the same as 99) skipped
-
-        // FIXME: CEA --- Cylindrical Equal Area skipped (Grid corners set in meters for EASE grid)
-
-        // FIXME: BCEA --- Cylindrical Equal Area skipped (Grid corners set in DMS degs for EASE grid)
-
-        // FIXME: ISINUS --- Integrized Sinusoidal skipped
+        // FIXME: OBEQA --- Oblated Equal Area skipped.
+        // FIXME: ISINUS1 --- Integerized Sinusoidal Grid (the same as 99).
+        // FIXME: CEA --- Cylindrical Equal Area skipped (Grid corners set in
+        // meters for EASE grid).
+        // FIXME: BCEA --- Cylindrical Equal Area skipped (Grid corners set in
+        // DMS degs for EASE grid).
+        // FIXME: ISINUS --- Integrized Sinusoidal skipped.
 
         default:
             CPLDebug( "OSR_USGS", "Unsupported projection: %ld", iProjSys );
-            SetLocalCS( CPLString().Printf("GCTP projection number %ld", iProjSys) );
+            SetLocalCS( CPLString().Printf("GCTP projection number %ld",
+                                           iProjSys) );
             break;
-
     }
 
 /* -------------------------------------------------------------------- */
 /*      Try to translate the datum/spheroid.                            */
 /* -------------------------------------------------------------------- */
 
-    if ( !IsLocal() )
+    if( !IsLocal() )
     {
-        char    *pszName = NULL;
-        double  dfSemiMajor, dfInvFlattening;
+        char *pszName = NULL;
+        double dfSemiMajor = 0.0;
+        double dfInvFlattening = 0.0;
 
-        if ( iDatum < 0  ) // Use specified ellipsoid parameters
+        if( iDatum < 0 ) // Use specified ellipsoid parameters.
         {
-            if ( padfPrjParams[0] > 0.0 )
+            if( padfPrjParams[0] > 0.0 )
             {
-                if ( padfPrjParams[1] > 1.0 )
+                if( padfPrjParams[1] > 1.0 )
                 {
-                    dfInvFlattening = OSRCalcInvFlattening(padfPrjParams[0], padfPrjParams[1] );
+                    dfInvFlattening = OSRCalcInvFlattening(padfPrjParams[0],
+                                                           padfPrjParams[1]);
                 }
-                else if ( padfPrjParams[1] > 0.0 )
+                else if( padfPrjParams[1] > 0.0 )
                 {
                     dfInvFlattening =
                         1.0 / ( 1.0 - sqrt(1.0 - padfPrjParams[1]) );
                 }
                 else
+                {
                     dfInvFlattening = 0.0;
+                }
 
                 SetGeogCS( "Unknown datum based upon the custom spheroid",
                            "Not specified (based on custom spheroid)",
                            "Custom spheroid", padfPrjParams[0], dfInvFlattening,
                            NULL, 0, NULL, 0 );
             }
-            else if ( padfPrjParams[1] > 0.0 )  // Clarke 1866
+            else if( padfPrjParams[1] > 0.0 )  // Clarke 1866.
             {
-                if ( OSRGetEllipsoidInfo( 7008, &pszName, &dfSemiMajor,
+                if( OSRGetEllipsoidInfo( 7008, &pszName, &dfSemiMajor,
                                           &dfInvFlattening ) == OGRERR_NONE )
                 {
                     SetGeogCS( CPLString().Printf(
@@ -708,8 +722,8 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
             }
             else                              // Sphere, rad 6370997 m
             {
-                if ( OSRGetEllipsoidInfo( 7047, &pszName, &dfSemiMajor,
-                                     &dfInvFlattening ) == OGRERR_NONE )
+                if( OSRGetEllipsoidInfo( 7047, &pszName, &dfSemiMajor,
+                                         &dfInvFlattening ) == OGRERR_NONE )
                 {
                     SetGeogCS( CPLString().Printf(
                                     "Unknown datum based upon the %s ellipsoid",
@@ -722,17 +736,19 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
                     SetAuthority( "SPHEROID", "EPSG", 7047 );
                 }
             }
-
         }
-        else if ( iDatum < NUMBER_OF_ELLIPSOIDS && aoEllips[iDatum] )
+        else if( iDatum < NUMBER_OF_ELLIPSOIDS && aoEllips[iDatum] )
         {
             if( OSRGetEllipsoidInfo( aoEllips[iDatum], &pszName,
-                                     &dfSemiMajor, &dfInvFlattening ) == OGRERR_NONE )
+                                     &dfSemiMajor,
+                                     &dfInvFlattening ) == OGRERR_NONE )
             {
-                SetGeogCS( CPLString().Printf("Unknown datum based upon the %s ellipsoid",
-                                              pszName ),
-                           CPLString().Printf( "Not specified (based on %s spheroid)",
-                                               pszName ),
+                SetGeogCS( CPLString().Printf(
+                               "Unknown datum based upon the %s ellipsoid",
+                               pszName),
+                           CPLString().Printf(
+                               "Not specified (based on %s spheroid)",
+                               pszName),
                            pszName, dfSemiMajor, dfInvFlattening,
                            NULL, 0.0, NULL, 0.0 );
                 SetAuthority( "SPHEROID", "EPSG", aoEllips[iDatum] );
@@ -740,23 +756,23 @@ OGRErr OGRSpatialReference::importFromUSGS( long iProjSys, long iZone,
             else
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                          "Failed to lookup datum code %d, likely due to missing GDAL gcs.csv\n"
-                          " file.  Falling back to use WGS84.",
-                          (int) iDatum );
-                SetWellKnownGeogCS("WGS84" );
+                          "Failed to lookup datum code %d, likely due to "
+                          "missing GDAL gcs.csv file.  "
+                          "Falling back to use WGS84.",
+                          static_cast<int>(iDatum) );
+                SetWellKnownGeogCS("WGS84");
             }
         }
         else
         {
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Wrong datum code %d. Supported datums 0--%d only.\n"
+                      "Wrong datum code %d. Supported datums 0--%d only.  "
                       "Setting WGS84 as a fallback.",
-                      (int) iDatum, NUMBER_OF_ELLIPSOIDS );
+                      static_cast<int>(iDatum), NUMBER_OF_ELLIPSOIDS );
             SetWellKnownGeogCS( "WGS84" );
         }
 
-        if ( pszName )
-            CPLFree( pszName );
+        CPLFree( pszName );
     }
 
 /* -------------------------------------------------------------------- */
@@ -823,15 +839,13 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
                                           long *piDatum ) const
 
 {
-    const char  *pszProjection = GetAttrValue("PROJECTION");
+    const char *pszProjection = GetAttrValue("PROJECTION");
 
 /* -------------------------------------------------------------------- */
 /*      Fill all projection parameters with zero.                       */
 /* -------------------------------------------------------------------- */
-    int         i;
-
-    *ppadfPrjParams = (double *)CPLMalloc( 15 * sizeof(double) );
-    for ( i = 0; i < 15; i++ )
+    *ppadfPrjParams = static_cast<double *>(CPLMalloc(15 * sizeof(double)));
+    for( int i = 0; i < 15; i++ )
         (*ppadfPrjParams)[i] = 0.0;
 
     *piZone = 0L;
@@ -1118,8 +1132,7 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
         (*ppadfPrjParams)[6] = GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 );
         (*ppadfPrjParams)[7] = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0 );
     }
-
-    // Projection unsupported by GCTP
+    // Projection unsupported by GCTP.
     else
     {
         CPLDebug( "OSR_USGS",
@@ -1131,24 +1144,27 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
 /* -------------------------------------------------------------------- */
 /*      Translate the datum.                                            */
 /* -------------------------------------------------------------------- */
-    const char  *pszDatum = GetAttrValue( "DATUM" );
+    const char *pszDatum = GetAttrValue( "DATUM" );
 
-    if ( pszDatum )
+    if( pszDatum )
     {
         if( EQUAL( pszDatum, SRS_DN_NAD27 ) )
+        {
             *piDatum = CLARKE1866;
-
+        }
         else if( EQUAL( pszDatum, SRS_DN_NAD83 ) )
+        {
             *piDatum = GRS1980;
-
+        }
         else if( EQUAL( pszDatum, SRS_DN_WGS84 ) )
+        {
             *piDatum = WGS84;
-
-        // If not found well known datum, translate ellipsoid
+        }
+        // If not found well known datum, translate ellipsoid.
         else
         {
-            double      dfSemiMajor = GetSemiMajor();
-            double      dfInvFlattening = GetInvFlattening();
+            const double dfSemiMajor = GetSemiMajor();
+            const double dfInvFlattening = GetInvFlattening();
 
 #ifdef DEBUG
             CPLDebug( "OSR_USGS",
@@ -1156,13 +1172,14 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
                       "Try to translate ellipsoid definition.", pszDatum );
 #endif
 
-            for ( i = 0; i < NUMBER_OF_ELLIPSOIDS; i++ )
+            int i = 0;  // Used after for.
+            for( ; i < NUMBER_OF_ELLIPSOIDS; i++ )
             {
-                double  dfSM;
-                double  dfIF;
+                double dfSM = 0.0;
+                double dfIF = 0.0;
 
-                if ( OSRGetEllipsoidInfo( aoEllips[i], NULL,
-                                          &dfSM, &dfIF ) == OGRERR_NONE
+                if( OSRGetEllipsoidInfo( aoEllips[i], NULL,
+                                         &dfSM, &dfIF ) == OGRERR_NONE
                     && CPLIsEqual( dfSemiMajor, dfSM )
                     && CPLIsEqual( dfInvFlattening, dfIF ) )
                 {
@@ -1171,8 +1188,8 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
                 }
             }
 
-            if ( i == NUMBER_OF_ELLIPSOIDS )    // Didn't found matches; set
-            {                                   // custom ellipsoid parameters
+            if( i == NUMBER_OF_ELLIPSOIDS )  // Didn't found matches; set
+            {                                // custom ellipsoid parameters.
 #ifdef DEBUG
                 CPLDebug( "OSR_USGS",
                           "Ellipsoid \"%s\" unsupported by USGS GCTP. "
@@ -1181,7 +1198,7 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
 #endif
                 *piDatum = -1;
                 (*ppadfPrjParams)[0] = dfSemiMajor;
-                if ( ABS( dfInvFlattening ) < 0.000000000001 )
+                if( std::abs( dfInvFlattening ) < 0.000000000001 )
                 {
                     (*ppadfPrjParams)[1] = dfSemiMajor;
                 }
@@ -1194,7 +1211,9 @@ OGRErr OGRSpatialReference::exportToUSGS( long *piProjSys, long *piZone,
         }
     }
     else
+    {
         *piDatum = -1;
+    }
 
     return OGRERR_NONE;
 }
diff --git a/ogr/ogr_srs_validate.cpp b/ogr/ogr_srs_validate.cpp
index ac7180a..9807505 100644
--- a/ogr/ogr_srs_validate.cpp
+++ b/ogr/ogr_srs_validate.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_validate.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of the OGRSpatialReference::Validate() method and
@@ -29,14 +28,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
+#include "cpl_port.h"
+#include "ogr_srs_api.h"
+
+#include <cstdlib>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
+#include "ogr_spatialref.h"
 #include "osr_cs_wkt.h"
 
-CPL_CVSID("$Id: ogr_srs_validate.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogr_srs_validate.cpp 36541 2016-11-28 18:32:25Z goatbar $");
 
-/* why would fipszone and zone be parameters when they relate to a composite
-   projection which renders done into a non-zoned projection? */
+// Why would fipszone and zone be parameters when they relate to a composite
+// projection which renders down into a non-zoned projection?
 
 static const char * const papszParameters[] =
 {
@@ -69,14 +77,14 @@ static const char * const papszParameters[] =
     SRS_PP_LONGITUDE_OF_1ST_POINT,
     SRS_PP_LATITUDE_OF_2ND_POINT,
     SRS_PP_LONGITUDE_OF_2ND_POINT,
-    SRS_PP_PEG_POINT_LATITUDE, /* for SCH */
-    SRS_PP_PEG_POINT_LONGITUDE, /* for SCH */
-    SRS_PP_PEG_POINT_HEADING, /* for SCH */
-    SRS_PP_PEG_POINT_HEIGHT, /* for SCH */
+    SRS_PP_PEG_POINT_LATITUDE,   // For SCH.
+    SRS_PP_PEG_POINT_LONGITUDE,  // For SCH.
+    SRS_PP_PEG_POINT_HEADING,    // For SCH.
+    SRS_PP_PEG_POINT_HEIGHT,     // For SCH.
     NULL
 };
 
-// the following projection lists are incomplete.  they will likely
+// The following projection lists are incomplete.  They will likely
 // change after the CT RPF response.  Examples show alternate forms with
 // underscores instead of spaces.  Should we use the EPSG names were available?
 // Plate-Caree has an accent in the spec!
@@ -148,9 +156,7 @@ static const char * const papszProjectionUnsupported[] =
     NULL
 };
 
-/*
-** List of supported projections with the PARAMETERS[] acceptable for each.
-*/
+// List of supported projections with the PARAMETERS[] acceptable for each.
 static const char * const papszProjWithParms[] = {
 
     SRS_PT_TRANSVERSE_MERCATOR,
@@ -555,7 +561,6 @@ static const char * const papszAliasGroupList[] = {
     NULL
 };
 
-
 /************************************************************************/
 /*                              Validate()                              */
 /************************************************************************/
@@ -582,26 +587,25 @@ OGRErr OGRSpatialReference::Validate()
 /* -------------------------------------------------------------------- */
     if( poRoot == NULL )
     {
-        CPLDebug( "OGRSpatialReference::Validate",
-                  "No root pointer.\n" );
+        CPLDebug( "OGRSpatialReference::Validate", "No root pointer." );
         return OGRERR_CORRUPT_DATA;
     }
 
     OGRErr eErr = Validate(poRoot);
 
-    /* Even if hand-validation has succeeded, try a more formal validation */
-    /* using the CT spec grammar */
+    // Even if hand-validation has succeeded, try a more formal validation
+    // using the CT spec grammar.
     static int bUseCTGrammar = -1;
     if( bUseCTGrammar < 0 )
-        bUseCTGrammar = CPLTestBool(CPLGetConfigOption("OSR_USE_CT_GRAMMAR", "TRUE"));
+        bUseCTGrammar =
+            CPLTestBool(CPLGetConfigOption("OSR_USE_CT_GRAMMAR", "TRUE"));
 
     if( eErr == OGRERR_NONE && bUseCTGrammar )
     {
-        osr_cs_wkt_parse_context sContext;
         char* pszWKT = NULL;
-
         exportToWkt(&pszWKT);
 
+        osr_cs_wkt_parse_context sContext;
         sContext.pszInput = pszWKT;
         sContext.pszLastSuccess = pszWKT;
         sContext.pszNext = pszWKT;
@@ -619,18 +623,17 @@ OGRErr OGRSpatialReference::Validate()
     return eErr;
 }
 
-
 OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 {
-    if( !EQUAL(poRoot->GetValue(),"GEOGCS")
-        && !EQUAL(poRoot->GetValue(),"PROJCS")
-        && !EQUAL(poRoot->GetValue(),"LOCAL_CS")
-        && !EQUAL(poRoot->GetValue(),"GEOCCS")
-        && !EQUAL(poRoot->GetValue(),"VERT_CS")
-        && !EQUAL(poRoot->GetValue(),"COMPD_CS"))
+    if( !EQUAL(poRoot->GetValue(), "GEOGCS")
+        && !EQUAL(poRoot->GetValue(), "PROJCS")
+        && !EQUAL(poRoot->GetValue(), "LOCAL_CS")
+        && !EQUAL(poRoot->GetValue(), "GEOCCS")
+        && !EQUAL(poRoot->GetValue(), "VERT_CS")
+        && !EQUAL(poRoot->GetValue(), "COMPD_CS"))
     {
         CPLDebug( "OGRSpatialReference::Validate",
-                  "Unrecognized root node `%s'\n",
+                  "Unrecognized root node `%s'",
                   poRoot->GetValue() );
         return OGRERR_CORRUPT_DATA;
     }
@@ -638,33 +641,30 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 /* -------------------------------------------------------------------- */
 /*      For a COMPD_CS, validate subparameters and head & tail cs       */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
+    if( EQUAL(poRoot->GetValue(), "COMPD_CS") )
     {
-        OGR_SRSNode     *poNode;
-        int             i;
-
-        for( i = 1; i < poRoot->GetChildCount(); i++ )
+        for( int i = 1; i < poRoot->GetChildCount(); i++ )
         {
-            poNode = poRoot->GetChild(i);
-
-            if( EQUAL(poNode->GetValue(),"GEOGCS") ||
-                EQUAL(poNode->GetValue(),"PROJCS") ||
-                EQUAL(poNode->GetValue(),"LOCAL_CS") ||
-                EQUAL(poNode->GetValue(),"GEOCCS") ||
-                EQUAL(poNode->GetValue(),"VERT_CS") ||
-                EQUAL(poNode->GetValue(),"COMPD_CS") )
+            OGR_SRSNode *poNode = poRoot->GetChild(i);
+
+            if( EQUAL(poNode->GetValue(), "GEOGCS") ||
+                EQUAL(poNode->GetValue(), "PROJCS") ||
+                EQUAL(poNode->GetValue(), "LOCAL_CS") ||
+                EQUAL(poNode->GetValue(), "GEOCCS") ||
+                EQUAL(poNode->GetValue(), "VERT_CS") ||
+                EQUAL(poNode->GetValue(), "COMPD_CS") )
             {
                 OGRErr eErr = Validate(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
-            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
+            else if( EQUAL(poNode->GetValue(), "AUTHORITY") )
             {
                 OGRErr eErr = ValidateAuthority(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
-            else if( EQUAL(poNode->GetValue(),"EXTENSION") )
+            else if( EQUAL(poNode->GetValue(), "EXTENSION") )
             {
                 // We do not try to control the sub-organization of
                 // EXTENSION nodes.
@@ -672,7 +672,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             else
             {
                 CPLDebug( "OGRSpatialReference::Validate",
-                          "Unexpected child for COMPD_CS `%s'.\n",
+                          "Unexpected child for COMPD_CS `%s'.",
                           poNode->GetValue() );
 
                 return OGRERR_CORRUPT_DATA;
@@ -685,75 +685,73 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 /* -------------------------------------------------------------------- */
 /*      Validate VERT_CS                                                */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(poRoot->GetValue(),"VERT_CS") )
+    if( EQUAL(poRoot->GetValue(), "VERT_CS") )
     {
-        OGR_SRSNode     *poNode;
-        int             i;
-        bool            bGotVertDatum = false;
-        bool            bGotUnit = false;
-        int             nCountAxis = 0;
+        bool bGotVertDatum = false;
+        bool bGotUnit = false;
+        int nCountAxis = 0;
 
-        for( i = 1; i < poRoot->GetChildCount(); i++ )
+        for( int i = 1; i < poRoot->GetChildCount(); i++ )
         {
-            poNode = poRoot->GetChild(i);
+            OGR_SRSNode *poNode = poRoot->GetChild(i);
 
-            if( EQUAL(poNode->GetValue(),"VERT_DATUM") )
+            if( EQUAL(poNode->GetValue(), "VERT_DATUM") )
             {
                 OGRErr eErr = ValidateVertDatum(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
                 bGotVertDatum = true;
             }
-            else if( EQUAL(poNode->GetValue(),"UNIT") )
+            else if( EQUAL(poNode->GetValue(), "UNIT") )
             {
                 OGRErr eErr = ValidateUnit(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
                 bGotUnit = true;
             }
-            else if( EQUAL(poNode->GetValue(),"AXIS") )
+            else if( EQUAL(poNode->GetValue(), "AXIS") )
             {
                 OGRErr eErr = ValidateAxis(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
-                nCountAxis ++;
+                nCountAxis++;
             }
-            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
+            else if( EQUAL(poNode->GetValue(), "AUTHORITY") )
             {
                 OGRErr eErr = ValidateAuthority(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
             else
             {
                 CPLDebug( "OGRSpatialReference::Validate",
-                          "Unexpected child for VERT_CS `%s'.\n",
+                          "Unexpected child for VERT_CS `%s'.",
                           poNode->GetValue() );
 
                 return OGRERR_CORRUPT_DATA;
             }
         }
 
-        if (!bGotVertDatum)
+        if( !bGotVertDatum )
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "No VERT_DATUM child in VERT_CS.\n" );
+                      "No VERT_DATUM child in VERT_CS." );
 
             return OGRERR_CORRUPT_DATA;
         }
 
-        if (!bGotUnit)
+        if( !bGotUnit )
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "No UNIT child in VERT_CS.\n" );
+                      "No UNIT child in VERT_CS." );
 
             return OGRERR_CORRUPT_DATA;
         }
 
-        if (nCountAxis > 1)
+        if( nCountAxis > 1 )
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "Too many AXIS children in VERT_CS.\n" );
+                      "Too many AXIS children in VERT_CS." );
 
             return OGRERR_CORRUPT_DATA;
         }
@@ -763,24 +761,22 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 /* -------------------------------------------------------------------- */
 /*      Validate GEOCCS                                                 */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(poRoot->GetValue(),"GEOCCS") )
+    if( EQUAL(poRoot->GetValue(), "GEOCCS") )
     {
-        OGR_SRSNode     *poNode;
-        int             i;
-        bool            bGotDatum = false;
-        bool            bGotPrimeM = false;
-        bool            bGotUnit = false;
-        int             nCountAxis = 0;
-
-        for( i = 1; i < poRoot->GetChildCount(); i++ )
+        bool bGotDatum = false;
+        bool bGotPrimeM = false;
+        bool bGotUnit = false;
+        int nCountAxis = 0;
+
+        for( int i = 1; i < poRoot->GetChildCount(); i++ )
         {
-            poNode = poRoot->GetChild(i);
+            OGR_SRSNode *poNode = poRoot->GetChild(i);
 
-            if( EQUAL(poNode->GetValue(),"DATUM") )
+            if( EQUAL(poNode->GetValue(), "DATUM") )
             {
                 bGotDatum = true;
             }
-            else if( EQUAL(poNode->GetValue(),"PRIMEM") )
+            else if( EQUAL(poNode->GetValue(), "PRIMEM") )
             {
                 bGotPrimeM = true;
 
@@ -788,71 +784,71 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                     || poNode->GetChildCount() > 3 )
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "PRIMEM has wrong number of children (%d),"
-                              "not 2 or 3 as expected.\n",
+                              "PRIMEM has wrong number of children (%d), "
+                              "not 2 or 3 as expected.",
                               poNode->GetChildCount() );
 
                     return OGRERR_CORRUPT_DATA;
                 }
             }
-            else if( EQUAL(poNode->GetValue(),"UNIT") )
+            else if( EQUAL(poNode->GetValue(), "UNIT") )
             {
                 OGRErr eErr = ValidateUnit(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
                 bGotUnit = true;
             }
-            else if( EQUAL(poNode->GetValue(),"AXIS") )
+            else if( EQUAL(poNode->GetValue(), "AXIS") )
             {
                 OGRErr eErr = ValidateAxis(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
-                nCountAxis ++;
+                nCountAxis++;
             }
-            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
+            else if( EQUAL(poNode->GetValue(), "AUTHORITY") )
             {
                 OGRErr eErr = ValidateAuthority(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
             else
             {
                 CPLDebug( "OGRSpatialReference::Validate",
-                          "Unexpected child for GEOCCS `%s'.\n",
+                          "Unexpected child for GEOCCS `%s'.",
                           poNode->GetValue() );
 
                 return OGRERR_CORRUPT_DATA;
             }
         }
 
-        if (!bGotDatum)
+        if( !bGotDatum )
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "No DATUM child in GEOCCS.\n" );
+                      "No DATUM child in GEOCCS." );
 
             return OGRERR_CORRUPT_DATA;
         }
 
-        if (!bGotPrimeM)
+        if( !bGotPrimeM )
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "No PRIMEM child in GEOCCS.\n" );
+                      "No PRIMEM child in GEOCCS." );
 
             return OGRERR_CORRUPT_DATA;
         }
 
-        if (!bGotUnit)
+        if( !bGotUnit )
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "No UNIT child in GEOCCS.\n" );
+                      "No UNIT child in GEOCCS." );
 
             return OGRERR_CORRUPT_DATA;
         }
 
-        if (nCountAxis != 0 && nCountAxis != 3 )
+        if( nCountAxis != 0 && nCountAxis != 3 )
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "Wrong number of AXIS children in GEOCCS.\n" );
+                      "Wrong number of AXIS children in GEOCCS." );
 
             return OGRERR_CORRUPT_DATA;
         }
@@ -861,32 +857,29 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 /* -------------------------------------------------------------------- */
 /*      For a PROJCS, validate subparameters (other than GEOGCS).       */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(poRoot->GetValue(),"PROJCS") )
+    if( EQUAL(poRoot->GetValue(), "PROJCS") )
     {
-        OGR_SRSNode     *poNode;
-        int             i;
-
-        for( i = 1; i < poRoot->GetChildCount(); i++ )
+        for( int i = 1; i < poRoot->GetChildCount(); i++ )
         {
-            poNode = poRoot->GetChild(i);
+            OGR_SRSNode *poNode = poRoot->GetChild(i);
 
-            if( EQUAL(poNode->GetValue(),"GEOGCS") )
+            if( EQUAL(poNode->GetValue(), "GEOGCS") )
             {
-                /* validated elsewhere */
+                // Validated elsewhere.
             }
-            else if( EQUAL(poNode->GetValue(),"UNIT") )
+            else if( EQUAL(poNode->GetValue(), "UNIT") )
             {
                 OGRErr eErr = ValidateUnit(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
-            else if( EQUAL(poNode->GetValue(),"PARAMETER") )
+            else if( EQUAL(poNode->GetValue(), "PARAMETER") )
             {
                 if( poNode->GetChildCount() != 2 )
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "PARAMETER has wrong number of children (%d),"
-                              "not 2 as expected.\n",
+                              "PARAMETER has wrong number of children (%d), "
+                              "not 2 as expected.",
                               poNode->GetChildCount() );
 
                     return OGRERR_CORRUPT_DATA;
@@ -895,76 +888,77 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                                         poNode->GetChild(0)->GetValue()) == -1)
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "Unrecognized PARAMETER `%s'.\n",
+                              "Unrecognized PARAMETER `%s'.",
                               poNode->GetChild(0)->GetValue() );
 
                     return OGRERR_UNSUPPORTED_SRS;
                 }
             }
-            else if( EQUAL(poNode->GetValue(),"PROJECTION") )
+            else if( EQUAL(poNode->GetValue(), "PROJECTION") )
             {
-                if( poNode->GetChildCount() != 1 && poNode->GetChildCount() != 2 )
+                if( poNode->GetChildCount() != 1 &&
+                    poNode->GetChildCount() != 2 )
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "PROJECTION has wrong number of children (%d),"
-                              "not 1 or 2 as expected.\n",
+                              "PROJECTION has wrong number of children (%d), "
+                              "not 1 or 2 as expected.",
                               poNode->GetChildCount() );
 
                     return OGRERR_CORRUPT_DATA;
                 }
-                else if( CSLFindString( (char **)papszProjectionSupported,
+                else if( CSLFindString( papszProjectionSupported,
                                         poNode->GetChild(0)->GetValue()) == -1
-                      && CSLFindString( (char **)papszProjectionUnsupported,
+                      && CSLFindString( papszProjectionUnsupported,
                                         poNode->GetChild(0)->GetValue()) == -1)
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "Unrecognized PROJECTION `%s'.\n",
+                              "Unrecognized PROJECTION `%s'.",
                               poNode->GetChild(0)->GetValue() );
 
                     return OGRERR_UNSUPPORTED_SRS;
                 }
-                else if( CSLFindString( (char **)papszProjectionSupported,
+                else if( CSLFindString( papszProjectionSupported,
                                         poNode->GetChild(0)->GetValue()) == -1)
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "Unsupported, but recognized PROJECTION `%s'.\n",
+                              "Unsupported, but recognized PROJECTION `%s'.",
                               poNode->GetChild(0)->GetValue() );
 
                     return OGRERR_UNSUPPORTED_SRS;
                 }
 
-                if (poNode->GetChildCount() == 2)
+                if( poNode->GetChildCount() == 2 )
                 {
                     poNode = poNode->GetChild(1);
-                    if( EQUAL(poNode->GetValue(),"AUTHORITY") )
+                    if( EQUAL(poNode->GetValue(), "AUTHORITY") )
                     {
-                        OGRErr eErr = ValidateAuthority(poNode);
-                        if (eErr != OGRERR_NONE)
+                        const OGRErr eErr = ValidateAuthority(poNode);
+                        if( eErr != OGRERR_NONE )
                             return eErr;
                     }
                     else
                     {
                         CPLDebug( "OGRSpatialReference::Validate",
-                                "Unexpected child for PROJECTION `%s'.\n",
-                                poNode->GetValue() );
+                                  "Unexpected child for PROJECTION `%s'.",
+                                  poNode->GetValue() );
 
                         return OGRERR_CORRUPT_DATA;
                     }
                 }
             }
-            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
+            else if( EQUAL(poNode->GetValue(), "AUTHORITY") )
             {
                 OGRErr eErr = ValidateAuthority(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
-            else if( EQUAL(poNode->GetValue(),"AXIS") )
+            else if( EQUAL(poNode->GetValue(), "AXIS") )
             {
                 OGRErr eErr = ValidateAxis(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
-            else if( EQUAL(poNode->GetValue(),"EXTENSION") )
+            else if( EQUAL(poNode->GetValue(), "EXTENSION") )
             {
                 // We do not try to control the sub-organization of
                 // EXTENSION nodes.
@@ -972,7 +966,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             else
             {
                 CPLDebug( "OGRSpatialReference::Validate",
-                          "Unexpected child for PROJCS `%s'.\n",
+                          "Unexpected child for PROJCS `%s'.",
                           poNode->GetValue() );
 
                 return OGRERR_CORRUPT_DATA;
@@ -987,57 +981,54 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 
     if( poGEOGCS != NULL )
     {
-        OGR_SRSNode     *poNode;
-        int             i;
-
-        for( i = 1; i < poGEOGCS->GetChildCount(); i++ )
+        for( int i = 1; i < poGEOGCS->GetChildCount(); i++ )
         {
-            poNode = poGEOGCS->GetChild(i);
+            OGR_SRSNode *poNode = poGEOGCS->GetChild(i);
 
-            if( EQUAL(poNode->GetValue(),"DATUM") )
+            if( EQUAL(poNode->GetValue(), "DATUM") )
             {
-                /* validated elsewhere */
+                // Validated elsewhere.
             }
-            else if( EQUAL(poNode->GetValue(),"PRIMEM") )
+            else if( EQUAL(poNode->GetValue(), "PRIMEM") )
             {
                 if( poNode->GetChildCount() < 2
                     || poNode->GetChildCount() > 3 )
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "PRIMEM has wrong number of children (%d),"
-                              "not 2 or 3 as expected.\n",
+                              "PRIMEM has wrong number of children (%d), "
+                              "not 2 or 3 as expected.",
                               poNode->GetChildCount() );
 
                     return OGRERR_CORRUPT_DATA;
                 }
             }
-            else if( EQUAL(poNode->GetValue(),"UNIT") )
+            else if( EQUAL(poNode->GetValue(), "UNIT") )
             {
-                OGRErr eErr = ValidateUnit(poNode);
-                if (eErr != OGRERR_NONE)
+                const OGRErr eErr = ValidateUnit(poNode);
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
-            else if( EQUAL(poNode->GetValue(),"AXIS") )
+            else if( EQUAL(poNode->GetValue(), "AXIS") )
             {
-                OGRErr eErr = ValidateAxis(poNode);
-                if (eErr != OGRERR_NONE)
+                const OGRErr eErr = ValidateAxis(poNode);
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
-            else if( EQUAL(poNode->GetValue(),"EXTENSION") )
+            else if( EQUAL(poNode->GetValue(), "EXTENSION") )
             {
                 // We do not try to control the sub-organization of
                 // EXTENSION nodes.
             }
-            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
+            else if( EQUAL(poNode->GetValue(), "AUTHORITY") )
             {
                 OGRErr eErr = ValidateAuthority(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
             else
             {
                 CPLDebug( "OGRSpatialReference::Validate",
-                          "Unexpected child for GEOGCS `%s'.\n",
+                          "Unexpected child for GEOGCS `%s'.",
                           poNode->GetValue() );
 
                 return OGRERR_CORRUPT_DATA;
@@ -1047,7 +1038,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
         if( poGEOGCS->GetNode("DATUM") == NULL )
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "No DATUM child in GEOGCS.\n" );
+                      "No DATUM child in GEOGCS." );
 
             return OGRERR_CORRUPT_DATA;
         }
@@ -1060,10 +1051,6 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 
     if( poDATUM != NULL )
     {
-        OGR_SRSNode     *poSPHEROID;
-        bool            bGotSpheroid = false;
-        int             i;
-
         if( poDATUM->GetChildCount() == 0 )
         {
             CPLDebug( "OGRSpatialReference::Validate",
@@ -1072,22 +1059,23 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             return OGRERR_CORRUPT_DATA;
         }
 
-        for( i = 1; i < poDATUM->GetChildCount(); i++ )
+        bool bGotSpheroid = false;
+
+        for( int i = 1; i < poDATUM->GetChildCount(); i++ )
         {
-            OGR_SRSNode *poNode;
-            poNode = poDATUM->GetChild(i);
+            OGR_SRSNode *poNode = poDATUM->GetChild(i);
 
-            if( EQUAL(poNode->GetValue(),"SPHEROID") )
+            if( EQUAL(poNode->GetValue(), "SPHEROID") )
             {
-                poSPHEROID = poDATUM->GetChild(1);
+                OGR_SRSNode *poSPHEROID = poDATUM->GetChild(1);
                 bGotSpheroid = true;
 
                 if( poSPHEROID->GetChildCount() != 3
                     && poSPHEROID->GetChildCount() != 4 )
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "SPHEROID has wrong number of children (%d),"
-                              "not 3 or 4 as expected.\n",
+                              "SPHEROID has wrong number of children (%d), "
+                              "not 3 or 4 as expected.",
                               poSPHEROID->GetChildCount() );
 
                     return OGRERR_CORRUPT_DATA;
@@ -1095,29 +1083,30 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
                 else if( CPLAtof(poSPHEROID->GetChild(1)->GetValue()) == 0.0 )
                 {
                     CPLDebug( "OGRSpatialReference::Validate",
-                              "SPHEROID semi-major axis is zero (%s)!\n",
+                              "SPHEROID semi-major axis is zero (%s)!",
                               poSPHEROID->GetChild(1)->GetValue() );
                     return OGRERR_CORRUPT_DATA;
                 }
             }
-            else if( EQUAL(poNode->GetValue(),"AUTHORITY") )
+            else if( EQUAL(poNode->GetValue(), "AUTHORITY") )
             {
                 OGRErr eErr = ValidateAuthority(poNode);
-                if (eErr != OGRERR_NONE)
+                if( eErr != OGRERR_NONE )
                     return eErr;
             }
-            else if( EQUAL(poNode->GetValue(),"TOWGS84") )
+            else if( EQUAL(poNode->GetValue(), "TOWGS84") )
             {
                 if( poNode->GetChildCount() != 3
                     && poNode->GetChildCount() != 7)
                 {
-                    CPLDebug( "OGRSpatialReference::Validate",
-                   "TOWGS84 has wrong number of children (%d), not 3 or 7.\n",
-                              poNode->GetChildCount() );
+                    CPLDebug("OGRSpatialReference::Validate",
+                             "TOWGS84 has wrong number of children (%d), "
+                             "not 3 or 7.",
+                             poNode->GetChildCount() );
                     return OGRERR_CORRUPT_DATA;
                 }
             }
-            else if( EQUAL(poNode->GetValue(),"EXTENSION") )
+            else if( EQUAL(poNode->GetValue(), "EXTENSION") )
             {
                 // We do not try to control the sub-organization of
                 // EXTENSION nodes.
@@ -1125,7 +1114,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
             else
             {
                 CPLDebug( "OGRSpatialReference::Validate",
-                          "Unexpected child for DATUM `%s'.\n",
+                          "Unexpected child for DATUM `%s'.",
                           poNode->GetValue() );
 
                 return OGRERR_CORRUPT_DATA;
@@ -1135,7 +1124,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
         if( !bGotSpheroid )
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "No SPHEROID child in DATUM.\n" );
+                      "No SPHEROID child in DATUM." );
 
             return OGRERR_CORRUPT_DATA;
         }
@@ -1145,9 +1134,7 @@ OGRErr OGRSpatialReference::Validate(OGR_SRSNode *poRoot)
 /*      If this is projected, try to validate the detailed set of       */
 /*      parameters used for the projection.                             */
 /* -------------------------------------------------------------------- */
-    OGRErr  eErr;
-
-    eErr = ValidateProjection(poRoot);
+    const OGRErr eErr = ValidateProjection(poRoot);
     if( eErr != OGRERR_NONE )
         return eErr;
 
@@ -1181,24 +1168,24 @@ OGRErr OSRValidate( OGRSpatialReferenceH hSRS )
  * @param pszParm1 first string
  * @param pszParm2 second string
  *
- * @return TRUE if both strings are aliases according to the AliasGroupList, FALSE otherwise
+ * @return TRUE if both strings are aliases according to the
+ * AliasGroupList, FALSE otherwise
  */
 int OGRSpatialReference::IsAliasFor( const char *pszParm1,
                                      const char *pszParm2 )
 
 {
-    int         iGroup;
-
 /* -------------------------------------------------------------------- */
 /*      Look for a group containing pszParm1.                           */
 /* -------------------------------------------------------------------- */
-    for( iGroup = 0; papszAliasGroupList[iGroup] != NULL; iGroup++ )
+    int iGroup = 0;  // Used after for.
+    for( ; papszAliasGroupList[iGroup] != NULL; iGroup++ )
     {
-        int     i;
+        int i = iGroup;  // Used after for.
 
-        for( i = iGroup; papszAliasGroupList[i] != NULL; i++ )
+        for( ; papszAliasGroupList[i] != NULL; i++ )
         {
-            if( EQUAL(pszParm1,papszAliasGroupList[i]) )
+            if( EQUAL(pszParm1, papszAliasGroupList[i]) )
                 break;
         }
 
@@ -1213,7 +1200,7 @@ int OGRSpatialReference::IsAliasFor( const char *pszParm1,
 /* -------------------------------------------------------------------- */
     while( papszAliasGroupList[iGroup] != NULL )
     {
-        if( EQUAL(papszAliasGroupList[iGroup++],pszParm2) )
+        if( EQUAL(papszAliasGroupList[iGroup++], pszParm2) )
             return TRUE;
     }
 
@@ -1234,7 +1221,7 @@ OGRErr OGRSpatialReference::ValidateProjection(OGR_SRSNode *poRoot)
 {
     OGR_SRSNode *poPROJCS = poRoot->GetNode( "PROJCS" );
 
-    if( poPROJCS == NULL  )
+    if( poPROJCS == NULL )
         return OGRERR_NONE;
 
     if( poPROJCS->GetNode( "PROJECTION" ) == NULL )
@@ -1247,14 +1234,13 @@ OGRErr OGRSpatialReference::ValidateProjection(OGR_SRSNode *poRoot)
 /* -------------------------------------------------------------------- */
 /*      Find the matching group in the proj and parms table.            */
 /* -------------------------------------------------------------------- */
-    const char *pszProjection;
-    int        iOffset;
-
-    pszProjection = poPROJCS->GetNode("PROJECTION")->GetChild(0)->GetValue();
+    const char *pszProjection =
+        poPROJCS->GetNode("PROJECTION")->GetChild(0)->GetValue();
 
-    for( iOffset = 0;
+    int iOffset = 0;  // Used after for.
+    for( ;
          papszProjWithParms[iOffset] != NULL
-             && !EQUAL(papszProjWithParms[iOffset],pszProjection); )
+             && !EQUAL(papszProjWithParms[iOffset], pszProjection); )
     {
         while( papszProjWithParms[iOffset] != NULL )
             iOffset++;
@@ -1270,31 +1256,28 @@ OGRErr OGRSpatialReference::ValidateProjection(OGR_SRSNode *poRoot)
 /*      Check all parameters, and verify they are in the permitted      */
 /*      list.                                                           */
 /* -------------------------------------------------------------------- */
-    int iNode;
-
-    for( iNode = 0; iNode < poPROJCS->GetChildCount(); iNode++ )
+    for( int iNode = 0; iNode < poPROJCS->GetChildCount(); iNode++ )
     {
         OGR_SRSNode *poParm = poPROJCS->GetChild(iNode);
-        int          i;
-        const char  *pszParmName;
 
-        if( !EQUAL(poParm->GetValue(),"PARAMETER") )
+        if( !EQUAL(poParm->GetValue(), "PARAMETER") )
             continue;
 
-        pszParmName = poParm->GetChild(0)->GetValue();
+        const char *pszParmName = poParm->GetChild(0)->GetValue();
 
-        for( i = iOffset; papszProjWithParms[i] != NULL; i++ )
+        int i = iOffset;  // Used after for.
+        for( ; papszProjWithParms[i] != NULL; i++ )
         {
-            if( EQUAL(papszProjWithParms[i],pszParmName) )
+            if( EQUAL(papszProjWithParms[i], pszParmName) )
                 break;
         }
 
-        /* This parameter is not an exact match, is it an alias? */
+        // This parameter is not an exact match, is it an alias?
         if( papszProjWithParms[i] == NULL )
         {
             for( i = iOffset; papszProjWithParms[i] != NULL; i++ )
             {
-                if( IsAliasFor(papszProjWithParms[i],pszParmName) )
+                if( IsAliasFor(papszProjWithParms[i], pszParmName) )
                     break;
             }
 
@@ -1329,40 +1312,37 @@ OGRErr OGRSpatialReference::ValidateProjection(OGR_SRSNode *poRoot)
  * @return OGRERR_NONE if the VERT_DATUM's arguments validate, an error code
  *         otherwise
  */
-OGRErr OGRSpatialReference::ValidateVertDatum(OGR_SRSNode *poRoot)
+OGRErr OGRSpatialReference::ValidateVertDatum( OGR_SRSNode *poRoot )
 {
-    if ( !EQUAL(poRoot->GetValue(), "VERT_DATUM") )
+    if( !EQUAL(poRoot->GetValue(), "VERT_DATUM") )
         return OGRERR_NONE;
 
-    if (poRoot->GetChildCount() < 2 )
+    if( poRoot->GetChildCount() < 2 )
     {
         CPLDebug( "OGRSpatialReference::Validate",
                   "Invalid number of children : %d", poRoot->GetChildCount() );
         return OGRERR_CORRUPT_DATA;
     }
 
-    if (atoi(poRoot->GetChild(1)->GetValue()) == 0)
+    if( atoi(poRoot->GetChild(1)->GetValue()) == 0 )
     {
         CPLDebug( "OGRSpatialReference::Validate",
-                  "Invalid value for datum type (%s) : must be a number\n",
+                  "Invalid value for datum type (%s) : must be a number",
                   poRoot->GetChild(1)->GetValue());
         return OGRERR_CORRUPT_DATA;
     }
 
-    OGR_SRSNode     *poNode;
-    int             i;
-
-    for( i = 2; i < poRoot->GetChildCount(); i++ )
+    for( int i = 2; i < poRoot->GetChildCount(); i++ )
     {
-        poNode = poRoot->GetChild(i);
+        OGR_SRSNode *poNode = poRoot->GetChild(i);
 
-        if( EQUAL(poNode->GetValue(),"AUTHORITY") )
+        if( EQUAL(poNode->GetValue(), "AUTHORITY") )
         {
             OGRErr eErr = ValidateAuthority(poNode);
-            if (eErr != OGRERR_NONE)
+            if( eErr != OGRERR_NONE )
                 return eErr;
         }
-        else if( EQUAL(poNode->GetValue(),"EXTENSION") )
+        else if( EQUAL(poNode->GetValue(), "EXTENSION") )
         {
             // We do not try to control the sub-organization of
             // EXTENSION nodes.
@@ -1370,7 +1350,7 @@ OGRErr OGRSpatialReference::ValidateVertDatum(OGR_SRSNode *poRoot)
         else
         {
             CPLDebug( "OGRSpatialReference::Validate",
-                      "Unexpected child for VERT_DATUM `%s'.\n",
+                      "Unexpected child for VERT_DATUM `%s'.",
                       poNode->GetValue() );
 
             return OGRERR_CORRUPT_DATA;
@@ -1390,16 +1370,16 @@ OGRErr OGRSpatialReference::ValidateVertDatum(OGR_SRSNode *poRoot)
  * @return OGRERR_NONE if the AUTHORITY's arguments validate, an error code
  *         otherwise
  */
-OGRErr OGRSpatialReference::ValidateAuthority(OGR_SRSNode *poRoot)
+OGRErr OGRSpatialReference::ValidateAuthority( OGR_SRSNode *poRoot )
 {
-    if ( !EQUAL(poRoot->GetValue(), "AUTHORITY") )
+    if( !EQUAL(poRoot->GetValue(), "AUTHORITY") )
         return OGRERR_NONE;
 
     if( poRoot->GetChildCount() != 2 )
     {
         CPLDebug( "OGRSpatialReference::Validate",
-                    "AUTHORITY has wrong number of children (%d), not 2.\n",
-                    poRoot->GetChildCount() );
+                  "AUTHORITY has wrong number of children (%d), not 2.",
+                  poRoot->GetChildCount() );
         return OGRERR_CORRUPT_DATA;
     }
 
@@ -1416,15 +1396,15 @@ OGRErr OGRSpatialReference::ValidateAuthority(OGR_SRSNode *poRoot)
  * @return OGRERR_NONE if the AXIS's arguments validate, an error code
  *         otherwise
  */
-OGRErr OGRSpatialReference::ValidateAxis(OGR_SRSNode *poRoot)
+OGRErr OGRSpatialReference::ValidateAxis( OGR_SRSNode *poRoot )
 {
-    if ( !EQUAL(poRoot->GetValue(), "AXIS") )
+    if( !EQUAL(poRoot->GetValue(), "AXIS") )
         return OGRERR_NONE;
 
     if( poRoot->GetChildCount() != 2 )
     {
         CPLDebug( "OGRSpatialReference::Validate",
-                    "AXIS has wrong number of children (%d), not 2.\n",
+                    "AXIS has wrong number of children (%d), not 2.",
                     poRoot->GetChildCount() );
         return OGRERR_CORRUPT_DATA;
     }
@@ -1432,7 +1412,6 @@ OGRErr OGRSpatialReference::ValidateAxis(OGR_SRSNode *poRoot)
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           ValidateUnit()                             */
 /************************************************************************/
@@ -1443,25 +1422,25 @@ OGRErr OGRSpatialReference::ValidateAxis(OGR_SRSNode *poRoot)
  * @return OGRERR_NONE if the UNIT's arguments validate, an error code
  *         otherwise
  */
-OGRErr OGRSpatialReference::ValidateUnit(OGR_SRSNode *poRoot)
+OGRErr OGRSpatialReference::ValidateUnit( OGR_SRSNode *poRoot )
 {
-    if ( !EQUAL(poRoot->GetValue(), "UNIT") )
+    if( !EQUAL(poRoot->GetValue(), "UNIT") )
         return OGRERR_NONE;
 
     if( poRoot->GetChildCount() != 2
         && poRoot->GetChildCount() != 3 )
     {
         CPLDebug( "OGRSpatialReference::Validate",
-                    "UNIT has wrong number of children (%d), not 2.\n",
-                    poRoot->GetChildCount() );
+                  "UNIT has wrong number of children (%d), not 2.",
+                  poRoot->GetChildCount() );
         return OGRERR_CORRUPT_DATA;
     }
     else if( CPLAtof(poRoot->GetChild(1)->GetValue()) == 0.0 )
     {
         CPLDebug( "OGRSpatialReference::Validate",
-                    "UNIT does not appear to have meaningful"
-                    "coefficient (%s).\n",
-                    poRoot->GetChild(1)->GetValue() );
+                  "UNIT does not appear to have meaningful"
+                  "coefficient (%s).",
+                  poRoot->GetChild(1)->GetValue() );
         return OGRERR_CORRUPT_DATA;
     }
 
diff --git a/ogr/ogr_srs_xml.cpp b/ogr/ogr_srs_xml.cpp
index 2765f8b..a7bbcfe 100644
--- a/ogr/ogr_srs_xml.cpp
+++ b/ogr/ogr_srs_xml.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srs_xml.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGRSpatialReference interface to OGC XML (014r4).
@@ -28,10 +27,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
-#include "ogr_p.h"
+#include "cpl_port.h"
+#include "ogr_srs_api.h"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: ogr_srs_xml.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 /************************************************************************/
 /*                              parseURN()                              */
@@ -69,7 +81,7 @@ static bool parseURN( char *pszURN,
     if( ppszObjectType != NULL )
         *ppszObjectType = (const char *) pszURN + 12;
 
-    int  i = 12;
+    int i = 12;
     while( pszURN[i] != ':' && pszURN[i] != '\0' )
         i++;
 
@@ -132,14 +144,16 @@ static void addURN( CPLXMLNode *psTarget,
     if( pszVersion == NULL )
         pszVersion = "";
 
-    char szURN[200];
-    CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
+    char szURN[200] = {};
+    CPLAssert( strlen(pszAuthority) + strlen(pszObjectType) <
+               sizeof(szURN) - 30 );
 
     snprintf( szURN, sizeof(szURN), "urn:ogc:def:%s:%s:%s:",
-             pszObjectType, pszAuthority, pszVersion );
+              pszObjectType, pszAuthority, pszVersion );
 
     if( nCode != 0 )
-        snprintf( szURN + strlen(szURN), sizeof(szURN) - strlen(szURN), "%d", nCode );
+        snprintf( szURN + strlen(szURN), sizeof(szURN) - strlen(szURN),
+                  "%d", nCode );
 
     CPLCreateXMLNode(
         CPLCreateXMLNode( psTarget, CXT_Attribute, "xlink:href" ),
@@ -178,11 +192,11 @@ AddValueIDWithURN( CPLXMLNode *psTarget,
 /*      </srsId>                                                        */
 /************************************************************************/
 static CPLXMLNode *addAuthorityIDBlock( CPLXMLNode *psTarget,
-                                     const char *pszElement,
-                                     const char *pszAuthority,
-                                     const char *pszObjectType,
-                                     int nCode,
-                                     const char *pszVersion = "" )
+                                        const char *pszElement,
+                                        const char *pszAuthority,
+                                        const char *pszObjectType,
+                                        int nCode,
+                                        const char *pszVersion = "" )
 
 {
 /* -------------------------------------------------------------------- */
@@ -191,11 +205,12 @@ static CPLXMLNode *addAuthorityIDBlock( CPLXMLNode *psTarget,
     if( pszVersion == NULL )
         pszVersion = "";
 
-    char szURN[200];
-    CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
+    char szURN[200] = {};
+    CPLAssert( strlen(pszAuthority) + strlen(pszObjectType) <
+               sizeof(szURN) - 30 );
 
     snprintf( szURN, sizeof(szURN), "urn:ogc:def:%s:%s:%s:",
-             pszObjectType, pszAuthority, pszVersion );
+              pszObjectType, pszAuthority, pszVersion );
 
 /* -------------------------------------------------------------------- */
 /*      Prepare the base name, eg. <srsID>.                             */
@@ -219,7 +234,7 @@ static CPLXMLNode *addAuthorityIDBlock( CPLXMLNode *psTarget,
 /* -------------------------------------------------------------------- */
 /*      Attach code value to name node.                                 */
 /* -------------------------------------------------------------------- */
-    char szCode[32];
+    char szCode[32] = {};
     snprintf( szCode, sizeof(szCode), "%d", nCode );
 
     CPLCreateXMLNode( psName, CXT_Text, szCode );
@@ -236,13 +251,11 @@ static void addGMLId( CPLXMLNode *psParent )
     static CPLMutex *hGMLIdMutex = NULL;
     CPLMutexHolderD( &hGMLIdMutex );
 
-    /* CPLXMLNode *psId; */
     static int nNextGMLId = 1;
-    char   szIdText[40];
+    char szIdText[40] = {};
 
     snprintf( szIdText, sizeof(szIdText), "ogrcrs%d", nNextGMLId++ );
 
-    /* psId =  */
     CPLCreateXMLNode(
         CPLCreateXMLNode( psParent, CXT_Attribute, "gml:id" ),
         CXT_Text, szIdText );
@@ -259,25 +272,21 @@ static CPLXMLNode *exportAuthorityToXML( const OGR_SRSNode *poAuthParent,
                                          int bUseSubName = TRUE )
 
 {
-    const OGR_SRSNode *poAuthority;
-
 /* -------------------------------------------------------------------- */
 /*      Get authority node from parent.                                 */
 /* -------------------------------------------------------------------- */
     if( poAuthParent->FindChild( "AUTHORITY" ) == -1 )
         return NULL;
 
-    poAuthority = poAuthParent->GetChild(
+    const OGR_SRSNode *poAuthority = poAuthParent->GetChild(
         poAuthParent->FindChild( "AUTHORITY" ));
 
 /* -------------------------------------------------------------------- */
 /*      Create identification.                                          */
 /* -------------------------------------------------------------------- */
-    const char *pszCode, *pszCodeSpace, *pszEdition;
-
-    pszCode = poAuthority->GetChild(1)->GetValue();
-    pszCodeSpace = poAuthority->GetChild(0)->GetValue();
-    pszEdition = NULL;
+    const char *pszCode = poAuthority->GetChild(1)->GetValue();
+    const char *pszCodeSpace = poAuthority->GetChild(0)->GetValue();
+    const char *pszEdition = NULL;
 
     if( bUseSubName )
         return addAuthorityIDBlock( psXMLParent, pszTagName, pszCodeSpace,
@@ -296,21 +305,16 @@ static void addProjArg( const OGRSpatialReference *poSRS, CPLXMLNode *psBase,
                         int nParameterID, const char *pszWKTName )
 
 {
-    CPLXMLNode *psNode
-        = CPLCreateXMLNode( psBase, CXT_Element, "gml:usesValue" );
+    CPLXMLNode *psNode = CPLCreateXMLNode(psBase, CXT_Element, "gml:usesValue");
 
 /* -------------------------------------------------------------------- */
 /*      Handle the UOM.                                                 */
 /* -------------------------------------------------------------------- */
-    const char *pszUOMValue;
+    const char *pszUOMValue = EQUAL(pszMeasureType, "Angular")
+        ? "urn:ogc:def:uom:EPSG::9102"
+        : "urn:ogc:def:uom:EPSG::9001";
 
-    if( EQUAL(pszMeasureType,"Angular") )
-        pszUOMValue = "urn:ogc:def:uom:EPSG::9102";
-    else
-        pszUOMValue = "urn:ogc:def:uom:EPSG::9001";
-
-    CPLXMLNode *psValue
-        = CPLCreateXMLNode( psNode, CXT_Element, "gml:value" );
+    CPLXMLNode *psValue = CPLCreateXMLNode(psNode, CXT_Element, "gml:value");
 
     CPLCreateXMLNode(
         CPLCreateXMLNode( psValue, CXT_Attribute, "uom" ),
@@ -319,8 +323,7 @@ static void addProjArg( const OGRSpatialReference *poSRS, CPLXMLNode *psBase,
 /* -------------------------------------------------------------------- */
 /*      Add the parameter value itself.                                 */
 /* -------------------------------------------------------------------- */
-    double dfParmValue
-        = poSRS->GetNormProjParm( pszWKTName, dfDefault, NULL );
+    double dfParmValue = poSRS->GetNormProjParm( pszWKTName, dfDefault, NULL );
 
     CPLCreateXMLNode( psValue, CXT_Text,
                       CPLString().Printf( "%.16g", dfParmValue ) );
@@ -347,14 +350,14 @@ static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
         CPLCreateXMLNode(
             CPLCreateXMLNode( psXMLParent, CXT_Element, "gml:usesAxis" ),
             CXT_Element, "gml:CoordinateSystemAxis" );
-    if (!psAxisXML)
+    if( !psAxisXML )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "addAxis failed." );
         return NULL;
     }
     addGMLId( psAxisXML );
 
-    if( EQUAL(pszAxis,"Lat") )
+    if( EQUAL(pszAxis, "Lat") )
     {
         CPLCreateXMLNode(
             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
@@ -366,7 +369,7 @@ static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "Lat" );
         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "north" );
     }
-    else if( EQUAL(pszAxis,"Long") )
+    else if( EQUAL(pszAxis, "Long") )
     {
         CPLCreateXMLNode(
             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
@@ -378,7 +381,7 @@ static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "Lon" );
         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "east" );
     }
-    else if( EQUAL(pszAxis,"E") )
+    else if( EQUAL(pszAxis, "E") )
     {
         CPLCreateXMLNode(
             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
@@ -389,7 +392,7 @@ static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "E" );
         CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "east" );
     }
-    else if( EQUAL(pszAxis,"N") )
+    else if( EQUAL(pszAxis, "N") )
     {
         CPLCreateXMLNode(
             CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
@@ -402,7 +405,7 @@ static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
     }
     else
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
     }
 
     return psAxisXML;
@@ -423,8 +426,8 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
 /* -------------------------------------------------------------------- */
 /*      Establish initial infrastructure.                               */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode  *psGCS_XML
-        = CPLCreateXMLNode( NULL, CXT_Element, "gml:GeographicCRS" );
+    CPLXMLNode *psGCS_XML =
+        CPLCreateXMLNode( NULL, CXT_Element, "gml:GeographicCRS" );
     addGMLId( psGCS_XML );
 
 /* -------------------------------------------------------------------- */
@@ -444,12 +447,12 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
 /*      ellipsoidalCS.  Basically this defines the axes and their       */
 /*      units.                                                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psECS
-        = CPLCreateXMLNode(
-        CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesEllipsoidalCS" ),
-        CXT_Element, "gml:EllipsoidalCS" );
+    CPLXMLNode *psECS =
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesEllipsoidalCS" ),
+            CXT_Element, "gml:EllipsoidalCS" );
 
-    addGMLId( psECS  );
+    addGMLId( psECS );
 
     CPLCreateXMLElementAndValue( psECS, "gml:csName", "ellipsoidal" );
 
@@ -461,7 +464,7 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
 /* -------------------------------------------------------------------- */
 /*      Start with the datum.                                           */
 /* -------------------------------------------------------------------- */
-    const OGR_SRSNode    *poDatum = poGeogCS->GetNode( "DATUM" );
+    const OGR_SRSNode *poDatum = poGeogCS->GetNode( "DATUM" );
 
     if( poDatum == NULL )
     {
@@ -469,10 +472,10 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
         return NULL;
     }
 
-    CPLXMLNode *psDatumXML
-        = CPLCreateXMLNode(
-        CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesGeodeticDatum" ),
-        CXT_Element, "gml:GeodeticDatum" );
+    CPLXMLNode *psDatumXML =
+        CPLCreateXMLNode(
+            CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesGeodeticDatum" ),
+            CXT_Element, "gml:GeodeticDatum" );
 
     addGMLId( psDatumXML );
 
@@ -494,10 +497,10 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
     char *pszPMName = (char* ) "Greenwich";
     double dfPMOffset = poSRS->GetPrimeMeridian( &pszPMName );
 
-    CPLXMLNode *psPM
-        = CPLCreateXMLNode(
-        CPLCreateXMLNode( psDatumXML, CXT_Element, "gml:usesPrimeMeridian" ),
-        CXT_Element, "gml:PrimeMeridian" );
+    CPLXMLNode *psPM =
+        CPLCreateXMLNode(
+            CPLCreateXMLNode(psDatumXML, CXT_Element, "gml:usesPrimeMeridian"),
+            CXT_Element, "gml:PrimeMeridian");
 
     addGMLId( psPM );
 
@@ -506,8 +509,8 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
     if( poPMNode )
         exportAuthorityToXML( poPMNode, "gml:meridianID", psPM, "meridian" );
 
-    CPLXMLNode *psAngle
-        = CPLCreateXMLNode(
+    CPLXMLNode *psAngle =
+        CPLCreateXMLNode(
             CPLCreateXMLNode( psPM, CXT_Element, "gml:greenwichLongitude" ),
             CXT_Element, "gml:angle" );
 
@@ -524,9 +527,9 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
 
     if( poEllipsoid != NULL )
     {
-        CPLXMLNode *psEllipseXML
-            = CPLCreateXMLNode(
-                CPLCreateXMLNode(psDatumXML,CXT_Element,"gml:usesEllipsoid" ),
+        CPLXMLNode *psEllipseXML =
+            CPLCreateXMLNode(
+                CPLCreateXMLNode(psDatumXML, CXT_Element, "gml:usesEllipsoid" ),
                 CXT_Element, "gml:Ellipsoid" );
 
         addGMLId( psEllipseXML );
@@ -537,11 +540,10 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
         exportAuthorityToXML( poEllipsoid, "gml:ellipsoidID", psEllipseXML,
                               "ellipsoid");
 
-        CPLXMLNode *psParmXML
-            = CPLCreateXMLNode( psEllipseXML, CXT_Element,
-                                      "gml:semiMajorAxis" );
+        CPLXMLNode *psParmXML =
+            CPLCreateXMLNode( psEllipseXML, CXT_Element, "gml:semiMajorAxis" );
 
-        CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"uom"),
+        CPLCreateXMLNode( CPLCreateXMLNode(psParmXML, CXT_Attribute, "uom"),
                           CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
 
         CPLCreateXMLNode( psParmXML, CXT_Text,
@@ -553,7 +555,7 @@ static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
                                   "gml:secondDefiningParameter" ),
                 CXT_Element, "gml:inverseFlattening" );
 
-        CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"uom"),
+        CPLCreateXMLNode( CPLCreateXMLNode(psParmXML, CXT_Attribute, "uom"),
                           CXT_Text, "urn:ogc:def:uom:EPSG::9201" );
 
         CPLCreateXMLNode( psParmXML, CXT_Text,
@@ -578,8 +580,8 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
 /* -------------------------------------------------------------------- */
 /*      Establish initial infrastructure.                               */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode   *psCRS_XML
-        = CPLCreateXMLNode( NULL, CXT_Element, "gml:ProjectedCRS" );
+    CPLXMLNode *psCRS_XML =
+        CPLCreateXMLNode( NULL, CXT_Element, "gml:ProjectedCRS" );
     addGMLId( psCRS_XML );
 
 /* -------------------------------------------------------------------- */
@@ -604,28 +606,27 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
 /* -------------------------------------------------------------------- */
 /*      Our projected coordinate system is "defined by Conversion".     */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psDefinedBy
-        = CPLCreateXMLNode( psCRS_XML, CXT_Element,
-                                    "gml:definedByConversion" );
+    CPLXMLNode *psDefinedBy =
+        CPLCreateXMLNode( psCRS_XML, CXT_Element, "gml:definedByConversion" );
 
 /* -------------------------------------------------------------------- */
 /*      Projections are handled as ParameterizedTransformations.        */
 /* -------------------------------------------------------------------- */
     const char *pszProjection = poSRS->GetAttrValue("PROJECTION");
-    CPLXMLNode *psConv
-        = CPLCreateXMLNode( psDefinedBy, CXT_Element, "gml:Conversion");
+    CPLXMLNode *psConv =
+        CPLCreateXMLNode( psDefinedBy, CXT_Element, "gml:Conversion");
     addGMLId( psConv );
 
-    CPLCreateXMLNode(CPLCreateXMLNode(psConv, CXT_Element, "gml:coordinateOperationName"),
-                     CXT_Text, pszProjection);
+    CPLCreateXMLNode(
+        CPLCreateXMLNode(psConv, CXT_Element, "gml:coordinateOperationName"),
+        CXT_Text, pszProjection);
 
 /* -------------------------------------------------------------------- */
 /*      Transverse Mercator                                             */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
+    if( EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR) )
     {
-        AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method",
-                           9807 );
+        AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method", 9807 );
 
         addProjArg( poSRS, psConv, "Angular", 0.0,
                     8801, SRS_PP_LATITUDE_OF_ORIGIN );
@@ -638,7 +639,6 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
         addProjArg( poSRS, psConv, "Linear", 0.0,
                     8807, SRS_PP_FALSE_NORTHING );
     }
-
 /* -------------------------------------------------------------------- */
 /*      Lambert Conformal Conic                                         */
 /* -------------------------------------------------------------------- */
@@ -667,8 +667,8 @@ static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
 /* -------------------------------------------------------------------- */
 /*      Define the cartesian coordinate system.                         */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode  *psCCS
-        = CPLCreateXMLNode(
+    CPLXMLNode *psCCS =
+        CPLCreateXMLNode(
             CPLCreateXMLNode( psCRS_XML, CXT_Element, "gml:usesCartesianCS" ),
             CXT_Element, "gml:CartesianCS" );
 
@@ -755,35 +755,38 @@ static void importXMLUnits( CPLXMLNode *psSrcXML, const char *pszClass,
                             OGRSpatialReference *poSRS, const char *pszTarget)
 
 {
-    const char *pszUnitName, *pszUnitsPer;
     OGR_SRSNode *poNode = poSRS->GetAttrNode( pszTarget );
-    OGR_SRSNode *poUnits;
 
-    CPLAssert( EQUAL(pszClass,"AngularUnit")
-               || EQUAL(pszClass,"LinearUnit") );
+    CPLAssert( EQUAL(pszClass, "AngularUnit")
+               || EQUAL(pszClass, "LinearUnit") );
 
     psSrcXML = CPLGetXMLNode( psSrcXML, pszClass );
+
+    OGR_SRSNode *poUnits = NULL;
+    const char *pszUnitName = NULL;
+    const char *pszUnitsPer = NULL;
+
+    // TODO(schwehr): Remove the goto.
     if( psSrcXML == NULL )
         goto DefaultTarget;
 
-    pszUnitName = CPLGetXMLValue( psSrcXML, "NameSet.name", "unnamed" );
-    if( EQUAL(pszClass,"AngularUnit") )
-        pszUnitsPer = CPLGetXMLValue( psSrcXML, "radiansPerUnit", NULL );
-    else
-        pszUnitsPer = CPLGetXMLValue( psSrcXML, "metresPerUnit", NULL );
+    pszUnitName =
+        CPLGetXMLValue( psSrcXML, "NameSet.name", "unnamed" );
+
+    pszUnitsPer =
+        EQUAL(pszClass, "AngularUnit")
+        ? CPLGetXMLValue( psSrcXML, "radiansPerUnit", NULL )
+        : CPLGetXMLValue( psSrcXML, "metresPerUnit", NULL );
 
     if( pszUnitsPer == NULL )
     {
-        CPLDebug( "OGR_SRS_XML",
-                  "Missing PerUnit value for %s.",
-                  pszClass );
+        CPLDebug( "OGR_SRS_XML", "Missing PerUnit value for %s.", pszClass );
         goto DefaultTarget;
     }
 
     if( poNode == NULL )
     {
-        CPLDebug( "OGR_SRS_XML", "Can't find %s in importXMLUnits.",
-                  pszTarget );
+        CPLDebug("OGR_SRS_XML", "Can't find %s in importXMLUnits.", pszTarget);
         goto DefaultTarget;
     }
 
@@ -805,7 +808,7 @@ static void importXMLUnits( CPLXMLNode *psSrcXML, const char *pszClass,
 
   DefaultTarget:
     poUnits = new OGR_SRSNode( "UNIT" );
-    if( EQUAL(pszClass,"AngularUnit") )
+    if( EQUAL(pszClass, "AngularUnit") )
     {
         poUnits->AddChild( new OGR_SRSNode( SRS_UA_DEGREE ) );
         poUnits->AddChild( new OGR_SRSNode( SRS_UA_DEGREE_CONV ) );
@@ -849,9 +852,7 @@ static void importXMLAuthority( CPLXMLNode *psSrcXML,
     if( strlen(pszCode) == 0 )
         pszCode = (char *) CPLGetXMLValue( psNameNode, "", "" );
 
-    int nCode = 0;
-    if( pszCode != NULL )
-        nCode = atoi(pszCode);
+    const int nCode = pszCode != NULL ? atoi(pszCode) :0;
 
     if( nCode != 0 )
         poSRS->SetAuthority( pszTargetKey, pszAuthority, nCode );
@@ -867,10 +868,10 @@ static void importXMLAuthority( CPLXMLNode *psSrcXML,
 /************************************************************************/
 
 static bool ParseOGCDefURN( const char *pszURN,
-                           CPLString *poObjectType,
-                           CPLString *poAuthority,
-                           CPLString *poVersion,
-                           CPLString *poValue )
+                            CPLString *poObjectType,
+                            CPLString *poAuthority,
+                            CPLString *poVersion,
+                            CPLString *poValue )
 
 {
     if( poObjectType != NULL )
@@ -930,19 +931,21 @@ static int getEPSGObjectCodeValue( CPLXMLNode *psNode,
         return nDefault;
 
     const char* pszHrefVal = CPLGetXMLValue( psNode, "xlink:href", NULL );
-    if (pszHrefVal == NULL)
+    if( pszHrefVal == NULL )
         pszHrefVal = CPLGetXMLValue( psNode, "href", NULL );
 
-    CPLString osObjectType, osAuthority, osValue;
+    CPLString osObjectType;
+    CPLString osAuthority;
+    CPLString osValue;
     if( !ParseOGCDefURN( pszHrefVal,
                          &osObjectType, &osAuthority, NULL, &osValue ) )
         return nDefault;
 
-    if( !EQUAL(osAuthority,"EPSG")
+    if( !EQUAL(osAuthority, "EPSG")
         || !EQUAL(osObjectType, pszEPSGObjectType) )
         return nDefault;
 
-    if( strlen(osValue) > 0 )
+    if( !osValue.empty() )
         return atoi(osValue);
 
     const char *pszValue = CPLGetXMLValue( psNode, "", NULL);
@@ -962,17 +965,15 @@ static double getProjectionParm( CPLXMLNode *psRootNode,
                                  double dfDefault )
 
 {
-    CPLXMLNode *psUsesParameter;
-
-    for( psUsesParameter = psRootNode->psChild;
+    for( CPLXMLNode *psUsesParameter = psRootNode->psChild;
          psUsesParameter != NULL;
          psUsesParameter = psUsesParameter->psNext )
     {
         if( psUsesParameter->eType != CXT_Element )
             continue;
 
-        if( !EQUAL(psUsesParameter->pszValue,"usesParameterValue")
-            && !EQUAL(psUsesParameter->pszValue,"usesValue") )
+        if( !EQUAL(psUsesParameter->pszValue, "usesParameterValue")
+            && !EQUAL(psUsesParameter->pszValue, "usesValue") )
             continue;
 
         if( getEPSGObjectCodeValue( CPLGetXMLNode(psUsesParameter,
@@ -982,10 +983,10 @@ static double getProjectionParm( CPLXMLNode *psRootNode,
             const char *pszValue = CPLGetXMLValue( psUsesParameter, "value",
                                                    NULL );
 
-            if( pszValue != NULL )
-                return CPLAtof(pszValue);
-            else
+            if( pszValue == NULL )
                 return dfDefault;
+
+            return CPLAtof(pszValue);
         }
     }
 
@@ -1004,18 +1005,15 @@ static double getNormalizedValue( CPLXMLNode *psNode, const char *pszPath,
                                   double dfDefault )
 
 {
-    CPLXMLNode *psTargetNode;
-    CPLXMLNode *psValueNode;
-
-    if( pszPath == NULL || strlen(pszPath) == 0 )
-        psTargetNode = psNode;
-    else
-        psTargetNode = CPLGetXMLNode( psNode, pszPath );
+    CPLXMLNode *psTargetNode = pszPath == NULL || strlen(pszPath) == 0
+        ? psNode
+        : CPLGetXMLNode( psNode, pszPath );
 
     if( psTargetNode == NULL )
         return dfDefault;
 
-    for( psValueNode = psTargetNode->psChild;
+    CPLXMLNode *psValueNode = psTargetNode->psChild;  // Used after for.
+    for( ;
          psValueNode != NULL && psValueNode->eType != CXT_Text;
          psValueNode = psValueNode->psNext ) {}
 
@@ -1035,22 +1033,18 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
                                    CPLXMLNode *psCRS )
 
 {
-    const char     *pszGeogName, *pszDatumName, *pszEllipsoidName, *pszPMName;
-    double         dfSemiMajor, dfInvFlattening, dfPMOffset = 0.0;
-
 /* -------------------------------------------------------------------- */
 /*      Set the GEOGCS name from the srsName.                           */
 /* -------------------------------------------------------------------- */
-    pszGeogName =
+    const char *pszGeogName =
         CPLGetXMLValue( psCRS, "srsName", "Unnamed GeogCS" );
 
 /* -------------------------------------------------------------------- */
 /*      If we don't seem to have a detailed coordinate system           */
 /*      definition, check if we can define based on an EPSG code.       */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode     *psDatum;
-
-    psDatum = CPLGetXMLNode( psCRS, "usesGeodeticDatum.GeodeticDatum" );
+    CPLXMLNode *psDatum =
+        CPLGetXMLNode( psCRS, "usesGeodeticDatum.GeodeticDatum" );
 
     if( psDatum == NULL )
     {
@@ -1061,7 +1055,7 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 
         if( oIdSRS.GetAuthorityCode( "LOCAL_CS" ) != NULL
             && oIdSRS.GetAuthorityName( "LOCAL_CS" ) != NULL
-            && EQUAL(oIdSRS.GetAuthorityName("LOCAL_CS"),"EPSG") )
+            && EQUAL(oIdSRS.GetAuthorityName("LOCAL_CS"), "EPSG") )
         {
             return poSRS->importFromEPSG(
                 atoi(oIdSRS.GetAuthorityCode("LOCAL_CS")) );
@@ -1071,22 +1065,21 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
 /*      Get datum name.                                                 */
 /* -------------------------------------------------------------------- */
-    pszDatumName =
+    const char *pszDatumName =
         CPLGetXMLValue( psDatum, "datumName", "Unnamed Datum" );
 
 /* -------------------------------------------------------------------- */
 /*      Get ellipsoid information.                                      */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psE;
-
-    psE = CPLGetXMLNode( psDatum, "usesEllipsoid.Ellipsoid" );
-    pszEllipsoidName =
+    CPLXMLNode *psE = CPLGetXMLNode( psDatum, "usesEllipsoid.Ellipsoid" );
+    const char *pszEllipsoidName =
         CPLGetXMLValue( psE, "ellipsoidName", "Unnamed Ellipsoid" );
 
-    dfSemiMajor = getNormalizedValue( psE, "semiMajorAxis", "Linear",
-                                      SRS_WGS84_SEMIMAJOR );
+    const double dfSemiMajor =
+        getNormalizedValue( psE, "semiMajorAxis", "Linear",
+                            SRS_WGS84_SEMIMAJOR );
 
-    dfInvFlattening =
+    const double dfInvFlattening =
         getNormalizedValue( psE, "secondDefiningParameter.inverseFlattening",
                             "Unitless", 0.0 );
 
@@ -1100,9 +1093,11 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 /* -------------------------------------------------------------------- */
 /*      Get the prime meridian.                                         */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psPM;
+    const char *pszPMName = NULL;
+    double dfPMOffset = 0.0;
 
-    psPM = CPLGetXMLNode( psDatum, "usesPrimeMeridian.PrimeMeridian" );
+    CPLXMLNode *psPM =
+        CPLGetXMLNode( psDatum, "usesPrimeMeridian.PrimeMeridian" );
     if( psPM == NULL )
     {
         pszPMName = "Greenwich";
@@ -1128,11 +1123,10 @@ static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
 /*      Look for angular units.  We don't check that all axes match     */
 /*      at this time.                                                   */
 /* -------------------------------------------------------------------- */
-#ifdef notdef
-    CPLXMLNode *psAxis;
-
-    psAxis = CPLGetXMLNode( psGeo2DCRS,
-                            "EllipsoidalCoordinateSystem.CoordinateAxis" );
+#if 0  // Does not compile.
+    CPLXMLNode *psAxis =
+        CPLGetXMLNode( psGeo2DCRS,
+                       "EllipsoidalCoordinateSystem.CoordinateAxis" );
     importXMLUnits( psAxis, "AngularUnit", poSRS, "GEOGCS" );
 #endif
 
@@ -1160,9 +1154,6 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
                                    CPLXMLNode *psCRS )
 
 {
-    CPLXMLNode *psSubXML;
-    OGRErr eErr;
-
 /* -------------------------------------------------------------------- */
 /*      Setup the PROJCS node with a name.                              */
 /* -------------------------------------------------------------------- */
@@ -1177,7 +1168,7 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
 
     if( poSRS->GetAuthorityCode( "PROJCS" ) != NULL
         && poSRS->GetAuthorityName( "PROJCS" ) != NULL
-        && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG")
+        && EQUAL(poSRS->GetAuthorityName("PROJCS"), "EPSG")
         && (CPLGetXMLNode( psCRS, "definedByConversion.Conversion" ) == NULL
             || CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" ) == NULL) )
     {
@@ -1188,10 +1179,10 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
 /*      Try to set the GEOGCS info.                                     */
 /* -------------------------------------------------------------------- */
 
-    psSubXML = CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" );
+    CPLXMLNode *psSubXML = CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" );
     if( psSubXML != NULL )
     {
-        eErr = importGeogCSFromXML( poSRS, psSubXML );
+        const OGRErr eErr = importGeogCSFromXML( poSRS, psSubXML );
         if( eErr != OGRERR_NONE )
             return eErr;
     }
@@ -1200,22 +1191,21 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
 /*      Get the conversion node.  It should be the only child of the    */
 /*      definedByConversion node.                                       */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psConv = NULL;
-
-    psConv = CPLGetXMLNode( psCRS, "definedByConversion.Conversion" );
+    CPLXMLNode *psConv = CPLGetXMLNode(psCRS, "definedByConversion.Conversion");
     if( psConv == NULL || psConv->eType != CXT_Element )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to find a conversion node under the definedByConversion\n"
-                  "node of the ProjectedCRS." );
+                  "Unable to find a conversion node under the "
+                  "definedByConversion node of the ProjectedCRS." );
         return OGRERR_CORRUPT_DATA;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Determine the conversion method in effect.                      */
 /* -------------------------------------------------------------------- */
-    int nMethod = getEPSGObjectCodeValue( CPLGetXMLNode( psConv, "usesMethod"),
-                                          "method", 0 );
+    const int nMethod =
+        getEPSGObjectCodeValue( CPLGetXMLNode( psConv, "usesMethod"),
+                                "method", 0 );
 
 /* -------------------------------------------------------------------- */
 /*      Transverse Mercator.                                            */
@@ -1241,7 +1231,6 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
         return OGRERR_CORRUPT_DATA;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Cleanup and return.                                             */
 /* -------------------------------------------------------------------- */
@@ -1266,15 +1255,12 @@ static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
 OGRErr OGRSpatialReference::importFromXML( const char *pszXML )
 
 {
-    CPLXMLNode *psTree;
-    OGRErr  eErr = OGRERR_UNSUPPORTED_SRS;
-
-    this->Clear();
+    Clear();
 
 /* -------------------------------------------------------------------- */
 /*      Parse the XML.                                                  */
 /* -------------------------------------------------------------------- */
-    psTree = CPLParseXMLString( pszXML );
+    CPLXMLNode *psTree = CPLParseXMLString( pszXML );
 
     if( psTree == NULL )
         return OGRERR_CORRUPT_DATA;
@@ -1286,15 +1272,17 @@ OGRErr OGRSpatialReference::importFromXML( const char *pszXML )
 /*      root elements as there is sometimes prefix stuff like           */
 /*      <?xml>.                                                         */
 /* -------------------------------------------------------------------- */
+    OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
+
     for( CPLXMLNode* psNode = psTree; psNode != NULL; psNode = psNode->psNext )
     {
-        if( EQUAL(psNode->pszValue,"GeographicCRS") )
+        if( EQUAL(psNode->pszValue, "GeographicCRS") )
         {
             eErr = importGeogCSFromXML( this, psNode );
             break;
         }
 
-        else if( EQUAL(psNode->pszValue,"ProjectedCRS") )
+        else if( EQUAL(psNode->pszValue, "ProjectedCRS") )
         {
             eErr = importProjCSFromXML( this, psNode );
             break;
diff --git a/ogr/ogr_srsnode.cpp b/ogr/ogr_srsnode.cpp
index be870eb..9797d7b 100644
--- a/ogr/ogr_srsnode.cpp
+++ b/ogr/ogr_srsnode.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_srsnode.cpp 33674 2016-03-07 20:58:21Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGR_SRSNode class.
@@ -28,10 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_p.h"
+#include "cpl_port.h"
 #include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogr_srsnode.cpp 33674 2016-03-07 20:58:21Z goatbar $");
+#include <cctype>
+#include <cstddef>
+#include <cstring>
+
+#include "ogr_core.h"
+#include "ogr_p.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogr_srsnode.cpp 36328 2016-11-20 13:44:29Z goatbar $");
 
 /************************************************************************/
 /*                            OGR_SRSNode()                             */
@@ -68,6 +77,8 @@ OGR_SRSNode::~OGR_SRSNode()
 /*                           ClearChildren()                            */
 /************************************************************************/
 
+/** Clear children nodes
+ */
 void OGR_SRSNode::ClearChildren()
 
 {
@@ -117,6 +128,16 @@ OGR_SRSNode *OGR_SRSNode::GetChild( int iChild )
     return papoChildNodes[iChild];
 }
 
+/**
+ * Fetch requested child.
+ *
+ * @param iChild the index of the child to fetch, from 0 to
+ * GetChildCount() - 1.
+ *
+ * @return a pointer to the child OGR_SRSNode, or NULL if there is no such
+ * child.
+ */
+
 const OGR_SRSNode *OGR_SRSNode::GetChild( int iChild ) const
 
 {
@@ -150,7 +171,7 @@ const OGR_SRSNode *OGR_SRSNode::GetChild( int iChild ) const
 OGR_SRSNode *OGR_SRSNode::GetNode( const char * pszName )
 
 {
-    if( nChildren > 0 && EQUAL(pszName,pszValue) )
+    if( nChildren > 0 && EQUAL(pszName, pszValue) )
         return this;
 
 /* -------------------------------------------------------------------- */
@@ -159,7 +180,7 @@ OGR_SRSNode *OGR_SRSNode::GetNode( const char * pszName )
 /* -------------------------------------------------------------------- */
     for( int i = 0; i < nChildren; i++ )
     {
-        if( EQUAL(papoChildNodes[i]->pszValue,pszName)
+        if( EQUAL(papoChildNodes[i]->pszValue, pszName)
             && papoChildNodes[i]->nChildren > 0 )
             return papoChildNodes[i];
     }
@@ -177,6 +198,23 @@ OGR_SRSNode *OGR_SRSNode::GetNode( const char * pszName )
     return NULL;
 }
 
+/**
+ * Find named node in tree.
+ *
+ * This method does a pre-order traversal of the node tree searching for
+ * a node with this exact value (case insensitive), and returns it.  Leaf
+ * nodes are not considered, under the assumption that they are just
+ * attribute value nodes.
+ *
+ * If a node appears more than once in the tree (such as UNIT for instance),
+ * the first encountered will be returned.  Use GetNode() on a subtree to be
+ * more specific.
+ *
+ * @param pszName the name of the node to search for.
+ *
+ * @return a pointer to the node found, or NULL if none.
+ */
+
 const OGR_SRSNode *OGR_SRSNode::GetNode( const char * pszName ) const
 
 {
@@ -356,7 +394,7 @@ OGR_SRSNode *OGR_SRSNode::Clone() const
 int OGR_SRSNode::NeedsQuoting() const
 
 {
-    // non-terminals are never quoted.
+    // Non-terminals are never quoted.
     if( GetChildCount() != 0 )
         return FALSE;
 
@@ -397,7 +435,7 @@ int OGR_SRSNode::NeedsQuoting() const
 /**
  * Convert this tree of nodes into WKT format.
  *
- * Note that the returned WKT string should be freed with OGRFree() or
+ * Note that the returned WKT string should be freed with
  * CPLFree() when no longer needed.  It is the responsibility of the caller.
  *
  * @param ppszResult the resulting string is returned in this pointer.
@@ -406,7 +444,6 @@ int OGR_SRSNode::NeedsQuoting() const
  * is possible error conditions will develop.
  */
 
-
 OGRErr OGR_SRSNode::exportToWkt( char ** ppszResult ) const
 
 {
@@ -414,8 +451,8 @@ OGRErr OGR_SRSNode::exportToWkt( char ** ppszResult ) const
 /*      Build a list of the WKT format for the children.                */
 /* -------------------------------------------------------------------- */
     char **papszChildrenWkt = static_cast<char **>(
-        CPLCalloc(sizeof(char*),(nChildren+1)) );
-    size_t nLength = strlen(pszValue)+4;
+        CPLCalloc(sizeof(char*), nChildren + 1) );
+    size_t nLength = strlen(pszValue) + 4;
 
     for( int i = 0; i < nChildren; i++ )
     {
@@ -437,7 +474,7 @@ OGRErr OGR_SRSNode::exportToWkt( char ** ppszResult ) const
     if( NeedsQuoting() )
     {
         strcat( *ppszResult, "\"" );
-        strcat( *ppszResult, pszValue ); /* should we do quoting? */
+        strcat( *ppszResult, pszValue );  // Should we do quoting?
         strcat( *ppszResult, "\"" );
     }
     else
@@ -452,7 +489,7 @@ OGRErr OGR_SRSNode::exportToWkt( char ** ppszResult ) const
     for( int i = 0; i < nChildren; i++ )
     {
         strcat( *ppszResult, papszChildrenWkt[i] );
-        if( i == nChildren-1 )
+        if( i == nChildren - 1 )
             strcat( *ppszResult, "]" );
         else
             strcat( *ppszResult, "," );
@@ -467,6 +504,20 @@ OGRErr OGR_SRSNode::exportToWkt( char ** ppszResult ) const
 /*                         exportToPrettyWkt()                          */
 /************************************************************************/
 
+/**
+ * Convert this tree of nodes into pretty WKT format.
+ *
+ * Note that the returned WKT string should be freed with
+ * CPLFree() when no longer needed.  It is the responsibility of the caller.
+ *
+ * @param ppszResult the resulting string is returned in this pointer.
+ *
+ * @param nDepth depth of the node
+ *
+ * @return currently OGRERR_NONE is always returned, but the future it
+ * is possible error conditions will develop.
+ */
+
 OGRErr OGR_SRSNode::exportToPrettyWkt( char ** ppszResult, int nDepth ) const
 
 {
@@ -474,8 +525,8 @@ OGRErr OGR_SRSNode::exportToPrettyWkt( char ** ppszResult, int nDepth ) const
 /*      Build a list of the WKT format for the children.                */
 /* -------------------------------------------------------------------- */
     char **papszChildrenWkt = static_cast<char **>(
-        CPLCalloc(sizeof(char*),(nChildren+1)) );
-    size_t nLength = strlen(pszValue)+4;
+        CPLCalloc(sizeof(char*), nChildren + 1) );
+    size_t nLength = strlen(pszValue) + 4;
 
     for( int i = 0; i < nChildren; i++ )
     {
@@ -498,11 +549,13 @@ OGRErr OGR_SRSNode::exportToPrettyWkt( char ** ppszResult, int nDepth ) const
     if( NeedsQuoting() )
     {
         strcat( *ppszResult, "\"" );
-        strcat( *ppszResult, pszValue ); /* should we do quoting? */
+        strcat( *ppszResult, pszValue );  // Should we do quoting?
         strcat( *ppszResult, "\"" );
     }
     else
+    {
         strcat( *ppszResult, pszValue );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Add the children strings with appropriate brackets and commas.  */
@@ -563,13 +616,11 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput )
     return importFromWkt( ppszInput, 0, &nNodes );
 }
 
-OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNodes )
+OGRErr OGR_SRSNode::importFromWkt( char **ppszInput, int nRecLevel,
+                                   int* pnNodes )
 
 {
-    const char  *pszInput = *ppszInput;
-    bool bInQuotedString = false;
-
-    /* Sanity checks */
+    // Sanity checks.
     if( nRecLevel == 10 )
     {
         return OGRERR_CORRUPT_DATA;
@@ -579,6 +630,9 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
         return OGRERR_CORRUPT_DATA;
     }
 
+    const char *pszInput = *ppszInput;
+    bool bInQuotedString = false;
+
 /* -------------------------------------------------------------------- */
 /*      Clear any existing children of this node.                       */
 /* -------------------------------------------------------------------- */
@@ -587,42 +641,43 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
 /* -------------------------------------------------------------------- */
 /*      Read the ``value'' for this node.                               */
 /* -------------------------------------------------------------------- */
-    char        szToken[512];
-    szToken[0] = '\0';
-    size_t nTokenLen = 0;
-
-    while( *pszInput != '\0' &&
-           nTokenLen + 1 < sizeof(szToken) )
     {
-        if( *pszInput == '"' )
-        {
-            bInQuotedString = !bInQuotedString;
-        }
-        else if( !bInQuotedString
-              && (*pszInput == '[' || *pszInput == ']' || *pszInput == ','
-                  || *pszInput == '(' || *pszInput == ')' ) )
-        {
-            break;
-        }
-        else if( !bInQuotedString
-                 && (*pszInput == ' ' || *pszInput == '\t'
-                     || *pszInput == 10 || *pszInput == 13) )
-        {
-            /* just skip over whitespace */
-        }
-        else
+        char szToken[512] = {};
+        size_t nTokenLen = 0;
+
+        while( *pszInput != '\0' &&
+               nTokenLen + 1 < sizeof(szToken) )
         {
-            szToken[nTokenLen++] = *pszInput;
-        }
+            if( *pszInput == '"' )
+            {
+                bInQuotedString = !bInQuotedString;
+            }
+            else if( !bInQuotedString
+                  && (*pszInput == '[' || *pszInput == ']' || *pszInput == ','
+                      || *pszInput == '(' || *pszInput == ')' ) )
+            {
+                break;
+            }
+            else if( !bInQuotedString
+                     && (*pszInput == ' ' || *pszInput == '\t'
+                         || *pszInput == 10 || *pszInput == 13) )
+            {
+                // Skip over whitespace.
+            }
+            else
+            {
+                szToken[nTokenLen++] = *pszInput;
+            }
 
-        pszInput++;
-    }
+            pszInput++;
+        }
 
-    if( *pszInput == '\0' || nTokenLen == sizeof(szToken) - 1 )
-        return OGRERR_CORRUPT_DATA;
+        if( *pszInput == '\0' || nTokenLen == sizeof(szToken) - 1 )
+            return OGRERR_CORRUPT_DATA;
 
-    szToken[nTokenLen++] = '\0';
-    SetValue( szToken );
+        szToken[nTokenLen++] = '\0';
+        SetValue( szToken );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Read children, if we have a sublist.                            */
@@ -631,12 +686,11 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
     {
         do
         {
-
             pszInput++; // Skip bracket or comma.
 
             OGR_SRSNode *poNewChild = new OGR_SRSNode();
 
-            (*pnNodes) ++;
+            (*pnNodes)++;
             const OGRErr eErr =
                 poNewChild->importFromWkt(
                     const_cast<char **>( &pszInput ),
@@ -649,10 +703,9 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
 
             AddChild( poNewChild );
 
-            // swallow whitespace
+            // Swallow whitespace.
             while( isspace(*pszInput) )
                 pszInput++;
-
         } while( *pszInput == ',' );
 
         if( *pszInput != ')' && *pszInput != ']' )
@@ -661,7 +714,7 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
         pszInput++;
     }
 
-    *ppszInput = (char *) pszInput;
+    *ppszInput = const_cast<char *>(pszInput);
 
     return OGRERR_NONE;
 }
@@ -677,7 +730,6 @@ OGRErr OGR_SRSNode::importFromWkt( char ** ppszInput, int nRecLevel, int* pnNode
  * The operation is also applies to all subnodes of the current node.
  */
 
-
 void OGR_SRSNode::MakeValueSafe()
 
 {
@@ -769,8 +821,8 @@ OGRErr OGR_SRSNode::applyRemapper( const char *pszNode,
     {
         for( int i = 0; papszSrcValues[i] != NULL; i += nStepSize )
         {
-            if( EQUAL(papszSrcValues[i],pszValue) &&
-                ! EQUAL(papszDstValues[i],"") )
+            if( EQUAL(papszSrcValues[i], pszValue) &&
+                !EQUAL(papszDstValues[i], "") )
             {
                 SetValue( papszDstValues[i] );
                 break;
@@ -782,7 +834,7 @@ OGRErr OGR_SRSNode::applyRemapper( const char *pszNode,
 /*      Is this the target node?                                        */
 /* -------------------------------------------------------------------- */
     if( pszNode != NULL )
-        bChildOfHit = EQUAL(pszValue,pszNode);
+        bChildOfHit = EQUAL(pszValue, pszNode);
 
 /* -------------------------------------------------------------------- */
 /*      Recurse                                                         */
@@ -829,7 +881,7 @@ void OGR_SRSNode::StripNodes( const char * pszName )
 /*                           FixupOrdering()                            */
 /************************************************************************/
 
-/* EXTENSION ... being a OSR extension... is arbitrary placed before the AUTHORITY */
+// EXTENSION, being a OSR extension, is arbitrary placed before the AUTHORITY.
 static const char * const apszPROJCSRule[] =
 { "PROJCS", "GEOGCS", "PROJECTION", "PARAMETER", "UNIT", "AXIS", "EXTENSION",
   "AUTHORITY", NULL };
@@ -884,7 +936,7 @@ OGRErr OGR_SRSNode::FixupOrdering()
 
     for( int i = 0; apszOrderingRules[i] != NULL; i++ )
     {
-        if( EQUAL(apszOrderingRules[i][0],pszValue) )
+        if( EQUAL(apszOrderingRules[i][0], pszValue) )
         {
             papszRule = apszOrderingRules[i] + 1;
             break;
@@ -899,7 +951,7 @@ OGRErr OGR_SRSNode::FixupOrdering()
 /*      (panChildPr) with the priority code for each child (derived     */
 /*      from the rule) and we then bubble sort based on this.           */
 /* -------------------------------------------------------------------- */
-    int  *panChildKey = static_cast<int *>(
+    int *panChildKey = static_cast<int *>(
         CPLCalloc(sizeof(int), GetChildCount()));
 
     for( int i = 1; i < GetChildCount(); i++ )
diff --git a/ogr/ogr_xerces.cpp b/ogr/ogr_xerces.cpp
new file mode 100644
index 0000000..f4a049a
--- /dev/null
+++ b/ogr/ogr_xerces.cpp
@@ -0,0 +1,185 @@
+/******************************************************************************
+ *
+ * Project:  GML Reader
+ * Purpose:  Convenience functions for parsing with Xerces-C library
+ *           Functions for translating back and forth between XMLCh and char.
+ *           We assume that XMLCh is a simple numeric type that we can
+ *           correspond 1:1 with char values, but that it likely is larger
+ *           than a char.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ * Author:   Even Rouault, <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Frank Warmerdam
+ * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_xerces.h"
+
+#include "cpl_port.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogr_xerces.cpp 36163 2016-11-08 15:46:28Z goatbar $");
+
+#ifdef HAVE_XERCES
+
+static CPLMutex* hMutex = NULL;
+static int nCounter = 0;
+
+/************************************************************************/
+/*                        OGRInitializeXerces()                         */
+/************************************************************************/
+
+bool OGRInitializeXerces(void)
+{
+    CPLMutexHolderD(&hMutex);
+    if( nCounter > 0 )
+    {
+        nCounter++;
+        return true;
+    }
+
+    try
+    {
+        CPLDebug("OGR", "XMLPlatformUtils::Initialize()");
+        XMLPlatformUtils::Initialize();
+        nCounter ++;
+        return true;
+    }
+    catch (const XMLException& toCatch)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Exception initializing Xerces: %s",
+                  transcode(toCatch.getMessage()).c_str() );
+        return false;
+    }
+}
+
+/************************************************************************/
+/*                       OGRDeinitializeXerces()                        */
+/************************************************************************/
+
+void OGRDeinitializeXerces(void)
+{
+    CPLMutexHolderD(&hMutex);
+    if( nCounter == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unpaired OGRInitializeXerces / OGRDeinitializeXerces calls");
+        return;
+    }
+    nCounter--;
+    if( nCounter == 0 )
+    {
+        if( CPLTestBool(CPLGetConfigOption("OGR_XERCES_TERMINATE", "YES")) )
+        {
+            CPLDebug("OGR", "XMLPlatformUtils::Terminate()");
+            XMLPlatformUtils::Terminate();
+        }
+    }
+}
+
+/************************************************************************/
+/*                       OGRCleanupXercesMutex()                        */
+/************************************************************************/
+
+void OGRCleanupXercesMutex(void)
+{
+    if( hMutex != NULL )
+        CPLDestroyMutex(hMutex);
+    hMutex = NULL;
+}
+
+namespace OGR
+{
+
+/************************************************************************/
+/*                            transcode()                               */
+/************************************************************************/
+
+CPLString transcode( const XMLCh *panXMLString, int nLimitingChars )
+{
+    CPLString osRet;
+    transcode( panXMLString, osRet, nLimitingChars );
+    return osRet;
+}
+
+CPLString& transcode( const XMLCh *panXMLString, CPLString& osRet,
+                      int nLimitingChars )
+{
+    if( panXMLString == NULL )
+    {
+        osRet = "(null)";
+        return osRet;
+    }
+
+    osRet.clear();
+    if( nLimitingChars > 0 )
+        osRet.reserve(nLimitingChars);
+
+    bool bSimpleASCII = true;
+    int nChars = 0;
+    for( int i = 0; panXMLString[i] != 0 &&
+           (nLimitingChars < 0 || i < nLimitingChars); i++ )
+    {
+        if( panXMLString[i] > 127 )
+        {
+            bSimpleASCII = false;
+        }
+        osRet += static_cast<char>(panXMLString[i]);
+        nChars++;
+    }
+
+    if( bSimpleASCII )
+        return osRet;
+
+/* -------------------------------------------------------------------- */
+/*      The simple translation was wrong, because the source is not     */
+/*      all simple ASCII characters.  Redo using the more expensive     */
+/*      recoding API.                                                   */
+/* -------------------------------------------------------------------- */
+    wchar_t *pwszSource =
+        static_cast<wchar_t *>(CPLMalloc(sizeof(wchar_t) * (nChars+1) ));
+    for( int i = 0 ; i < nChars; i++ )
+        pwszSource[i] = panXMLString[i];
+    pwszSource[nChars] = 0;
+
+    char *pszResult = CPLRecodeFromWChar( pwszSource,
+                                          "WCHAR_T", CPL_ENC_UTF8 );
+
+    osRet = pszResult;
+
+    CPLFree( pwszSource );
+    CPLFree( pszResult );
+
+    return osRet;
+}
+
+}
+
+#else // HAVE_XERCES
+
+void OGRCleanupXercesMutex(void) {}
+
+#endif // HAVE_XERCES
diff --git a/ogr/ogr_xerces.h b/ogr/ogr_xerces.h
new file mode 100644
index 0000000..ab6d93a
--- /dev/null
+++ b/ogr/ogr_xerces.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  Convenience functions for parsing with Xerces-C library
+ * Author:   Even Rouault, <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_XERCES_INCLUDED
+#define OGR_XERCES_INCLUDED
+
+// Must be first for DEBUG_BOOL case
+#ifdef HAVE_XERCES
+#include "ogr_xerces_headers.h"
+#endif
+
+#include "cpl_port.h"
+#include "cpl_string.h"
+
+#ifdef HAVE_XERCES
+
+/* All those functions are for in-tree drivers use only ! */
+
+/* Thread-safe initialization/de-initialization. Calls should be paired */
+bool CPL_DLL OGRInitializeXerces(void);
+void CPL_DLL OGRDeinitializeXerces(void);
+
+namespace OGR
+{
+CPLString CPL_DLL transcode( const XMLCh *panXMLString, int nLimitingChars = -1 );
+CPLString CPL_DLL &transcode( const XMLCh *panXMLString, CPLString& osRet,
+                              int nLimitingChars = -1 );
+}
+
+#ifndef OGR_USING
+using OGR::transcode;
+#endif
+
+#endif /* HAVE_XERCES */
+
+void OGRCleanupXercesMutex(void);
+
+#endif /* OGR_XERCES_INCLUDED */
diff --git a/ogr/ogr_xerces_headers.h b/ogr/ogr_xerces_headers.h
new file mode 100644
index 0000000..5efbb2c
--- /dev/null
+++ b/ogr/ogr_xerces_headers.h
@@ -0,0 +1,42 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes Xerces-C headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef OGR_XERCES_HEADERS_H
+#define OGR_XERCES_HEADERS_H
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+#include <util/PlatformUtils.hpp>
+
+#ifdef XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_USE
+#endif
+
+#endif /* OGR_XERCES_HEADERS_H */
diff --git a/ogr/ograpispy.cpp b/ogr/ograpispy.cpp
index 5d7be0c..9bb5970 100644
--- a/ogr/ograpispy.cpp
+++ b/ogr/ograpispy.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ograpispy.cpp 33680 2016-03-08 09:59:03Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGR C API "Spy"
@@ -28,60 +27,68 @@
  ****************************************************************************/
 
 #include "cpl_port.h"
+#include "ograpispy.h"
 
-#include <stdio.h>
+#include <cstdio>
 #include <map>
 #include <set>
 
-#include "ograpispy.h"
-
+#include "cpl_string.h"
 #include "gdal.h"
-#include "ogr_spatialref.h"
 #include "ogr_geometry.h"
 #include "ogr_feature.h"
+#include "ogr_spatialref.h"
 #include "ogrsf_frmts.h"
-#include "cpl_string.h"
+
+CPL_CVSID("$Id: ograpispy.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 #ifdef OGRAPISPY_ENABLED
 
 int bOGRAPISpyEnabled = FALSE;
-static CPLString osSnapshotPath, osSpyFile;
+static CPLString osSnapshotPath;
+static CPLString osSpyFile;
 static FILE* fpSpyFile = NULL;
 extern "C" int CPL_DLL GDALIsInGlobalDestructor(void);
 
+namespace
+{
+
 class LayerDescription
 {
-    public:
-        int iLayer;
+  public:
+    int iLayer;
 
-        LayerDescription(): iLayer(-1) {}
-        LayerDescription(int iLayerIn): iLayer(iLayerIn) {}
+    LayerDescription(): iLayer(-1) {}
+    explicit LayerDescription( int iLayerIn ): iLayer(iLayerIn) {}
 };
 
 class DatasetDescription
 {
-    public:
-        int iDS;
-        std::map<OGRLayerH, LayerDescription> oMapLayer;
+  public:
+    int iDS;
+    std::map<OGRLayerH, LayerDescription> oMapLayer;
 
-        DatasetDescription() : iDS(-1) {}
-        DatasetDescription(int iDSIn) : iDS(iDSIn) {}
-        ~DatasetDescription();
+    DatasetDescription() : iDS(-1) {}
+    explicit DatasetDescription( int iDSIn ) : iDS(iDSIn) {}
+    ~DatasetDescription();
 };
 
 class FeatureDefnDescription
 {
-    public:
-        OGRFeatureDefnH hFDefn;
-        int iUniqueNumber;
-        std::map<OGRFieldDefnH, int> oMapFieldDefn;
-        std::map<OGRGeomFieldDefnH, int> oMapGeomFieldDefn;
+  public:
+    OGRFeatureDefnH hFDefn;
+    int iUniqueNumber;
+    std::map<OGRFieldDefnH, int> oMapFieldDefn;
+    std::map<OGRGeomFieldDefnH, int> oMapGeomFieldDefn;
 
-        FeatureDefnDescription(): hFDefn(NULL), iUniqueNumber(-1) {}
-        FeatureDefnDescription(OGRFeatureDefnH hFDefnIn, int iUniqueNumberIn): hFDefn(hFDefnIn), iUniqueNumber(iUniqueNumberIn) {}
-        void Free();
+    FeatureDefnDescription(): hFDefn(NULL), iUniqueNumber(-1) {}
+    FeatureDefnDescription( OGRFeatureDefnH hFDefnIn, int iUniqueNumberIn ):
+        hFDefn(hFDefnIn), iUniqueNumber(iUniqueNumberIn) {}
+    void Free();
 };
 
+}  // namespace
+
 static std::map<OGRDataSourceH, DatasetDescription> oMapDS;
 static std::map<OGRLayerH, CPLString> oGlobalMapLayer;
 static OGRLayerH hLayerGetNextFeature = NULL;
@@ -96,21 +103,24 @@ static std::map<OGRFieldDefnH, CPLString> oGlobalMapFieldDefn;
 void FeatureDefnDescription::Free()
 {
     {
-        std::map<OGRGeomFieldDefnH, int>::iterator oIter = oMapGeomFieldDefn.begin();
-        for(; oIter != oMapGeomFieldDefn.end(); ++oIter)
+        std::map<OGRGeomFieldDefnH, int>::iterator oIter =
+            oMapGeomFieldDefn.begin();
+        for( ; oIter != oMapGeomFieldDefn.end(); ++oIter )
             oGlobalMapGeomFieldDefn.erase(oIter->first);
     }
     {
-        std::map<OGRFieldDefnH, int>::iterator oIter = oMapFieldDefn.begin();
-        for(; oIter != oMapFieldDefn.end(); ++oIter)
+        std::map<OGRFieldDefnH, int>::iterator oIter =
+            oMapFieldDefn.begin();
+        for( ; oIter != oMapFieldDefn.end(); ++oIter )
             oGlobalMapFieldDefn.erase(oIter->first);
     }
 }
 
 DatasetDescription::~DatasetDescription()
 {
-    std::map<OGRLayerH, LayerDescription>::iterator oIter = oMapLayer.begin();
-    for(; oIter != oMapLayer.end(); ++oIter)
+    std::map<OGRLayerH, LayerDescription>::iterator oIter =
+        oMapLayer.begin();
+    for( ; oIter != oMapLayer.end(); ++oIter )
         oGlobalMapLayer.erase(oIter->first);
 }
 
@@ -136,19 +146,20 @@ static void OGRAPISpyFileClose()
 static bool OGRAPISpyEnabled()
 {
     const char* pszSpyFile = CPLGetConfigOption("OGR_API_SPY_FILE", NULL);
-    bOGRAPISpyEnabled = (pszSpyFile != NULL);
+    bOGRAPISpyEnabled = pszSpyFile != NULL;
     if( !bOGRAPISpyEnabled )
     {
         osSpyFile.resize(0);
         aoSetCreatedDS.clear();
         return false;
     }
-    if( osSpyFile.size() )
+    if( !osSpyFile.empty() )
         return true;
 
     osSpyFile = pszSpyFile;
 
-    const char* pszSnapshotPath = CPLGetConfigOption("OGR_API_SPY_SNAPSHOT_PATH", ".");
+    const char* pszSnapshotPath =
+        CPLGetConfigOption("OGR_API_SPY_SNAPSHOT_PATH", ".");
     if( EQUAL(pszSnapshotPath, "NO") )
         osSnapshotPath = "";
     else
@@ -163,43 +174,42 @@ static bool OGRAPISpyEnabled()
     if( fpSpyFile == NULL )
         fpSpyFile = stderr;
 
-    fprintf(fpSpyFile, "# This file is generated by the OGR_API_SPY mechanism.\n");
+    fprintf(fpSpyFile,
+            "# This file is generated by the OGR_API_SPY mechanism.\n");
     fprintf(fpSpyFile, "from osgeo import ogr\n");
     fprintf(fpSpyFile, "from osgeo import osr\n");
     fprintf(fpSpyFile, "import os\n");
     fprintf(fpSpyFile, "import shutil\n");
-    fprintf(fpSpyFile, "os.access\n"); // to make pyflakes happy in case it's unused later
-    fprintf(fpSpyFile, "shutil.copy\n"); // same here
+    // To make pyflakes happy in case it's unused later.
+    fprintf(fpSpyFile, "os.access\n");
+    fprintf(fpSpyFile, "shutil.copy\n");  // Same here.
     fprintf(fpSpyFile, "\n");
 
     return true;
 }
 
-static CPLString OGRAPISpyGetOptions(char** papszOptions)
+static CPLString OGRAPISpyGetOptions( char** papszOptions )
 {
-    CPLString options;
     if( papszOptions == NULL )
     {
-        options = "[]";
+        return "[]";
     }
-    else
+
+    CPLString options = "[";
+    for( char** papszIter = papszOptions; *papszIter != NULL; papszIter++ )
     {
-        options = "[";
-        for(char** papszIter = papszOptions; *papszIter != NULL; papszIter++)
-        {
-            if( papszIter != papszOptions )
-                options += ", ";
-            options += "'";
-            options += *papszIter;
-            options += "'";
-        }
-        options += "]";
+        if( papszIter != papszOptions )
+            options += ", ";
+        options += "'";
+        options += *papszIter;
+        options += "'";
     }
+    options += "]";
 
     return options;
 }
 
-static CPLString OGRAPISpyGetString(const char* pszStr)
+static CPLString OGRAPISpyGetString( const char* pszStr )
 {
     if( pszStr == NULL )
         return "None";
@@ -212,60 +222,63 @@ static CPLString OGRAPISpyGetString(const char* pszStr)
             osRet += "\\\\";
         else
             osRet += *pszStr;
-        pszStr ++;
+        pszStr++;
     }
     osRet += "'";
     return osRet;
 }
 
-static CPLString OGRAPISpyGetDSVar(OGRDataSourceH hDS)
+static CPLString OGRAPISpyGetDSVar( OGRDataSourceH hDS )
 {
     if( hDS && oMapDS.find(hDS) == oMapDS.end() )
     {
-        int i = (int)oMapDS.size() + 1;
+        int i = static_cast<int>(oMapDS.size()) + 1;
         oMapDS[hDS] = DatasetDescription(i);
     }
-    return CPLSPrintf("ds%d", (hDS) ? oMapDS[hDS].iDS : 0);
+    return CPLSPrintf("ds%d", hDS ? oMapDS[hDS].iDS : 0);
 }
 
-static CPLString OGRAPISpyGetLayerVar(OGRLayerH hLayer)
+static CPLString OGRAPISpyGetLayerVar( OGRLayerH hLayer )
 {
     return oGlobalMapLayer[hLayer];
 }
 
-static CPLString OGRAPISpyGetAndRegisterLayerVar(OGRDataSourceH hDS,
-                                                 OGRLayerH hLayer)
+static CPLString OGRAPISpyGetAndRegisterLayerVar( OGRDataSourceH hDS,
+                                                  OGRLayerH hLayer )
 {
     DatasetDescription& dd = oMapDS[hDS];
     if( hLayer && dd.oMapLayer.find(hLayer) == dd.oMapLayer.end() )
     {
-        int i = (int)dd.oMapLayer.size() + 1;
-        dd.oMapLayer[hLayer] = i;
-        oGlobalMapLayer[hLayer] = OGRAPISpyGetDSVar(hDS) + "_" + CPLSPrintf("lyr%d", i);
+        const int i = static_cast<int>(dd.oMapLayer.size()) + 1;
+        dd.oMapLayer[hLayer] = LayerDescription(i);
+        oGlobalMapLayer[hLayer] =
+            OGRAPISpyGetDSVar(hDS) + "_" + CPLSPrintf("lyr%d", i);
     }
+
     return OGRAPISpyGetDSVar(hDS) + "_" +
-           CPLSPrintf("lyr%d", (hLayer) ? dd.oMapLayer[hLayer].iLayer : 0);
+           CPLSPrintf("lyr%d", hLayer ? dd.oMapLayer[hLayer].iLayer : 0);
 }
 
-static CPLString OGRAPISpyGetSRS(OGRSpatialReferenceH hSpatialRef)
+static CPLString OGRAPISpyGetSRS( OGRSpatialReferenceH hSpatialRef )
 {
-    if (hSpatialRef == NULL)
+    if( hSpatialRef == NULL )
         return "None";
 
     char* pszWKT = NULL;
-    ((OGRSpatialReference*)hSpatialRef)->exportToWkt(&pszWKT);
-    const char* pszRet = CPLSPrintf("osr.SpatialReference(\"\"\"%s\"\"\")", pszWKT);
+    reinterpret_cast<OGRSpatialReference*>(hSpatialRef)->exportToWkt(&pszWKT);
+    const char* pszRet =
+        CPLSPrintf("osr.SpatialReference(\"\"\"%s\"\"\")", pszWKT);
     CPLFree(pszWKT);
     return pszRet;
 }
 
-static CPLString OGRAPISpyGetGeom(OGRGeometryH hGeom)
+static CPLString OGRAPISpyGetGeom( OGRGeometryH hGeom )
 {
-    if (hGeom == NULL)
+    if( hGeom == NULL )
         return "None";
 
     char* pszWKT = NULL;
-    ((OGRGeometry*)hGeom)->exportToWkt(&pszWKT);
+    reinterpret_cast<OGRGeometry *>(hGeom)->exportToWkt(&pszWKT);
     const char* pszRet = CPLSPrintf("ogr.CreateGeometryFromWkt('%s')", pszWKT);
     CPLFree(pszWKT);
     return pszRet;
@@ -273,9 +286,9 @@ static CPLString OGRAPISpyGetGeom(OGRGeometryH hGeom)
 
 #define casePrefixOgrDot(x)  case x: return "ogr." #x;
 
-static CPLString OGRAPISpyGetGeomType(OGRwkbGeometryType eType)
+static CPLString OGRAPISpyGetGeomType( OGRwkbGeometryType eType )
 {
-    switch(eType)
+    switch( eType )
     {
         casePrefixOgrDot(wkbUnknown)
         casePrefixOgrDot(wkbPoint)
@@ -355,7 +368,7 @@ static CPLString OGRAPISpyGetGeomType(OGRwkbGeometryType eType)
 
 static CPLString OGRAPISpyGetFieldType(OGRFieldType eType)
 {
-    switch(eType)
+    switch( eType )
     {
         casePrefixOgrDot(OFTInteger)
         casePrefixOgrDot(OFTInteger64)
@@ -375,18 +388,25 @@ static CPLString OGRAPISpyGetFieldType(OGRFieldType eType)
     return "error";
 }
 
-static CPLString OGRAPISpyGetFeatureDefnVar(OGRFeatureDefnH hFDefn)
+#undef casePrefixOgrDot
+
+static CPLString OGRAPISpyGetFeatureDefnVar( OGRFeatureDefnH hFDefn )
 {
-    std::map<OGRFeatureDefnH, FeatureDefnDescription>::iterator oIter = oMapFDefn.find(hFDefn);
-    int i;
+    std::map<OGRFeatureDefnH, FeatureDefnDescription>::iterator oIter =
+        oMapFDefn.find(hFDefn);
+    int i = 0;
     if( oIter == oMapFDefn.end() )
     {
-        i = (int)oMapFDefn.size() + 1;
+        i = static_cast<int>(oMapFDefn.size()) + 1;
         oMapFDefn[hFDefn] = FeatureDefnDescription(hFDefn, i);
-        ((OGRFeatureDefn*)hFDefn)->Reference(); // so that we can check when they are no longer used
+
+        // So that we can check when they are no longer used.
+        reinterpret_cast<OGRFeatureDefn *>(hFDefn)->Reference();
     }
     else
+    {
         i = oIter->second.iUniqueNumber;
+    }
     return CPLSPrintf("fdefn%d", i);
 }
 
@@ -395,7 +415,10 @@ static void OGRAPISpyFlushDefered()
     OGRAPISpyFileReopen();
     if( hLayerGetLayerDefn != NULL )
     {
-        OGRFeatureDefnH hDefn = (OGRFeatureDefnH)(((OGRLayer*)hLayerGetLayerDefn)->GetLayerDefn());
+        OGRFeatureDefnH hDefn =
+            reinterpret_cast<OGRFeatureDefnH>(
+                reinterpret_cast<OGRLayer *>(hLayerGetLayerDefn)->
+                    GetLayerDefn());
         fprintf(fpSpyFile, "%s = %s.GetLayerDefn()\n",
             OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
             OGRAPISpyGetLayerVar(hLayerGetLayerDefn).c_str());
@@ -427,9 +450,9 @@ static void OGRAPISpyFlushDefered()
     }
 }
 
-int OGRAPISpyOpenTakeSnapshot(const char* pszName, int bUpdate)
+int OGRAPISpyOpenTakeSnapshot( const char* pszName, int bUpdate )
 {
-    if( !OGRAPISpyEnabled() || !bUpdate || osSnapshotPath.size() == 0 ||
+    if( !OGRAPISpyEnabled() || !bUpdate || osSnapshotPath.empty() ||
         aoSetCreatedDS.find(pszName) != aoSetCreatedDS.end() )
         return -1;
     OGRAPISpyFlushDefered();
@@ -437,10 +460,12 @@ int OGRAPISpyOpenTakeSnapshot(const char* pszName, int bUpdate)
     VSIStatBufL sStat;
     if( VSIStatL( pszName, &sStat ) == 0 )
     {
-        GDALDatasetH hDS = GDALOpenEx(pszName, GDAL_OF_VECTOR, NULL, NULL, NULL);
+        GDALDatasetH hDS =
+            GDALOpenEx(pszName, GDAL_OF_VECTOR, NULL, NULL, NULL);
         if( hDS )
         {
-            char** papszFileList = ((GDALDataset*)hDS)->GetFileList();
+            char** papszFileList =
+                reinterpret_cast<GDALDataset *>(hDS)->GetFileList();
             GDALClose(hDS);
             if( papszFileList )
             {
@@ -450,7 +475,8 @@ int OGRAPISpyOpenTakeSnapshot(const char* pszName, int bUpdate)
                 CPLString osWorkingDir;
                 while( true )
                 {
-                    osBaseDir = CPLFormFilename(osSnapshotPath,
+                    osBaseDir =
+                        CPLFormFilename(osSnapshotPath,
                                         CPLSPrintf("snapshot_%d", i), NULL );
                     if( VSIStatL( osBaseDir, &sStat ) != 0 )
                         break;
@@ -463,11 +489,12 @@ int OGRAPISpyOpenTakeSnapshot(const char* pszName, int bUpdate)
                 VSIMkdir( osWorkingDir, 0777 );
                 fprintf(fpSpyFile, "# Take snapshot of %s\n", pszName);
                 fprintf(fpSpyFile, "try:\n");
-                fprintf(fpSpyFile, "    shutil.rmtree('%s')\n", osWorkingDir.c_str());
+                fprintf(fpSpyFile, "    shutil.rmtree('%s')\n",
+                        osWorkingDir.c_str());
                 fprintf(fpSpyFile, "except:\n");
                 fprintf(fpSpyFile, "    pass\n");
                 fprintf(fpSpyFile, "os.mkdir('%s')\n", osWorkingDir.c_str());
-                for(char** papszIter = papszFileList; *papszIter; papszIter++)
+                for( char** papszIter = papszFileList; *papszIter; papszIter++ )
                 {
                     CPLString osSnapshotSrcFile = CPLFormFilename(
                             osSrcDir, CPLGetFilename(*papszIter), NULL);
@@ -487,7 +514,8 @@ int OGRAPISpyOpenTakeSnapshot(const char* pszName, int bUpdate)
     return -1;
 }
 
-void OGRAPISpyOpen(const char* pszName, int bUpdate, int iSnapshot, GDALDatasetH* phDS)
+void OGRAPISpyOpen( const char* pszName, int bUpdate, int iSnapshot,
+                    GDALDatasetH* phDS )
 {
     if( !OGRAPISpyEnabled() ) return;
     OGRAPISpyFlushDefered();
@@ -495,27 +523,33 @@ void OGRAPISpyOpen(const char* pszName, int bUpdate, int iSnapshot, GDALDatasetH
     CPLString osName;
     if( iSnapshot > 0 )
     {
-        CPLString osBaseDir = CPLFormFilename(osSnapshotPath,
-                                   CPLSPrintf("snapshot_%d", iSnapshot), NULL );
+        CPLString osBaseDir =
+            CPLFormFilename(osSnapshotPath,
+                            CPLSPrintf("snapshot_%d", iSnapshot), NULL );
         CPLString osWorkingDir = CPLFormFilename( osBaseDir, "working", NULL );
         osName = CPLFormFilename(osWorkingDir, CPLGetFilename(pszName), NULL);
         pszName = osName.c_str();
 
         if( *phDS != NULL )
         {
-            GDALClose( (GDALDatasetH) *phDS );
-            *phDS = GDALOpenEx(pszName, GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL);
+            GDALClose( reinterpret_cast<GDALDatasetH>(*phDS) );
+            *phDS = GDALOpenEx(pszName,
+                               GDAL_OF_VECTOR | GDAL_OF_UPDATE,
+                               NULL, NULL, NULL);
         }
     }
 
     if( *phDS != NULL )
-        fprintf(fpSpyFile, "%s = ", OGRAPISpyGetDSVar((OGRDataSourceH) *phDS).c_str());
+        fprintf(fpSpyFile,
+                "%s = ",
+                OGRAPISpyGetDSVar(
+                    reinterpret_cast<OGRDataSourceH>(*phDS)).c_str());
     fprintf(fpSpyFile, "ogr.Open(%s, update = %d)\n",
             OGRAPISpyGetString(pszName).c_str(), bUpdate);
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpyPreClose(OGRDataSourceH hDS)
+void OGRAPISpyPreClose( OGRDataSourceH hDS )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "ds%d = None\n", oMapDS[hDS].iDS);
@@ -528,19 +562,21 @@ void OGRAPISpyPostClose()
     if( !GDALIsInGlobalDestructor() )
     {
         std::map<OGRFeatureDefnH, FeatureDefnDescription>::iterator oIter =
-                                                                oMapFDefn.begin();
+            oMapFDefn.begin();
         std::vector<OGRFeatureDefnH> oArray;
-        for(; oIter != oMapFDefn.end(); ++oIter)
+        for( ; oIter != oMapFDefn.end(); ++oIter )
         {
             FeatureDefnDescription& featureDefnDescription = oIter->second;
-            if( ((OGRFeatureDefn*)featureDefnDescription.hFDefn)->GetReferenceCount() == 1 )
+            if( ((OGRFeatureDefn*)featureDefnDescription.hFDefn)->
+                GetReferenceCount() == 1 )
             {
                 oArray.push_back(featureDefnDescription.hFDefn);
             }
         }
-        for(size_t i = 0; i < oArray.size(); i++)
+        for( size_t i = 0; i < oArray.size(); i++ )
         {
-            FeatureDefnDescription& featureDefnDescription = oMapFDefn[oArray[i]];
+            FeatureDefnDescription& featureDefnDescription =
+                oMapFDefn[oArray[i]];
             ((OGRFeatureDefn*)featureDefnDescription.hFDefn)->Release();
             featureDefnDescription.Free();
             oMapFDefn.erase(oArray[i]);
@@ -548,15 +584,16 @@ void OGRAPISpyPostClose()
     }
 }
 
-void OGRAPISpyCreateDataSource(OGRSFDriverH hDriver, const char* pszName,
-                               char** papszOptions, OGRDataSourceH hDS)
+void OGRAPISpyCreateDataSource( OGRSFDriverH hDriver, const char* pszName,
+                                char** papszOptions, OGRDataSourceH hDS )
 {
     if( !OGRAPISpyEnabled() ) return;
     OGRAPISpyFlushDefered();
     if( hDS != NULL )
         fprintf(fpSpyFile, "%s = ", OGRAPISpyGetDSVar(hDS).c_str());
-    fprintf(fpSpyFile, "ogr.GetDriverByName('%s').CreateDataSource(%s, options = %s)\n",
-            GDALGetDriverShortName((GDALDriverH)hDriver),
+    fprintf(fpSpyFile,
+            "ogr.GetDriverByName('%s').CreateDataSource(%s, options = %s)\n",
+            GDALGetDriverShortName(reinterpret_cast<GDALDriverH>(hDriver)),
             OGRAPISpyGetString(pszName).c_str(),
             OGRAPISpyGetOptions(papszOptions).c_str());
     if( hDS != NULL )
@@ -566,12 +603,12 @@ void OGRAPISpyCreateDataSource(OGRSFDriverH hDriver, const char* pszName,
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpyDeleteDataSource(OGRSFDriverH hDriver, const char* pszName)
+void OGRAPISpyDeleteDataSource( OGRSFDriverH hDriver, const char* pszName )
 {
     if( !OGRAPISpyEnabled() ) return;
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "ogr.GetDriverByName('%s').DeleteDataSource(%s)\n",
-            GDALGetDriverShortName((GDALDriverH)hDriver),
+            GDALGetDriverShortName(reinterpret_cast<GDALDriverH>(hDriver)),
             OGRAPISpyGetString(pszName).c_str());
     aoSetCreatedDS.erase(pszName);
     OGRAPISpyFileClose();
@@ -613,7 +650,7 @@ void OGRAPISpy_DS_ExecuteSQL( OGRDataSourceH hDS,
                               const char *pszStatement,
                               OGRGeometryH hSpatialFilter,
                               const char *pszDialect,
-                              OGRLayerH hLayer)
+                              OGRLayerH hLayer )
 {
     OGRAPISpyFlushDefered();
     if( hLayer != NULL )
@@ -627,7 +664,7 @@ void OGRAPISpy_DS_ExecuteSQL( OGRDataSourceH hDS,
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_DS_ReleaseResultSet( OGRDataSourceH hDS, OGRLayerH hLayer)
+void OGRAPISpy_DS_ReleaseResultSet( OGRDataSourceH hDS, OGRLayerH hLayer )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.ReleaseResultSet(%s)\n",
@@ -646,13 +683,14 @@ void OGRAPISpy_DS_CreateLayer( OGRDataSourceH hDS,
                                OGRSpatialReferenceH hSpatialRef,
                                OGRwkbGeometryType eType,
                                char ** papszOptions,
-                               OGRLayerH hLayer)
+                               OGRLayerH hLayer )
 {
     OGRAPISpyFlushDefered();
     if( hLayer != NULL )
         fprintf(fpSpyFile, "%s = ",
             OGRAPISpyGetAndRegisterLayerVar(hDS, hLayer).c_str());
-    fprintf(fpSpyFile, "%s.CreateLayer(%s, srs = %s, geom_type = %s, options = %s)\n",
+    fprintf(fpSpyFile,
+            "%s.CreateLayer(%s, srs = %s, geom_type = %s, options = %s)\n",
             OGRAPISpyGetDSVar(hDS).c_str(),
             OGRAPISpyGetString(pszName).c_str(),
             OGRAPISpyGetSRS(hSpatialRef).c_str(),
@@ -666,7 +704,7 @@ void OGRAPISpy_DS_DeleteLayer( OGRDataSourceH hDS, int iLayer )
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.DeleteLayer(%d)\n",
             OGRAPISpyGetDSVar(hDS).c_str(), iLayer);
-    // Should perhaps remove from the maps
+    // Should perhaps remove from the maps.
     OGRAPISpyFileClose();
 }
 
@@ -674,7 +712,8 @@ void OGRAPISpy_Dataset_StartTransaction( GDALDatasetH hDS, int bForce )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.StartTransaction(%d)\n",
-            OGRAPISpyGetDSVar((OGRDataSourceH)hDS).c_str(), bForce);
+            OGRAPISpyGetDSVar(reinterpret_cast<OGRDataSourceH>(hDS)).c_str(),
+                              bForce);
     OGRAPISpyFileClose();
 }
 
@@ -682,7 +721,7 @@ void OGRAPISpy_Dataset_CommitTransaction( GDALDatasetH hDS )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.CommitTransaction()\n",
-            OGRAPISpyGetDSVar((OGRDataSourceH)hDS).c_str());
+            OGRAPISpyGetDSVar(reinterpret_cast<OGRDataSourceH>(hDS)).c_str());
     OGRAPISpyFileClose();
 }
 
@@ -690,7 +729,7 @@ void OGRAPISpy_Dataset_RollbackTransaction( GDALDatasetH hDS )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.RollbackTransaction()\n",
-            OGRAPISpyGetDSVar((OGRDataSourceH)hDS).c_str());
+            OGRAPISpyGetDSVar(reinterpret_cast<OGRDataSourceH>(hDS)).c_str());
     OGRAPISpyFileClose();
 }
 
@@ -756,37 +795,53 @@ void OGRAPISpy_L_GetNextFeature( OGRLayerH hLayer )
 
 static void OGRAPISpyDumpFeature( OGRFeatureH hFeat )
 {
-    OGRFeature* poFeature = (OGRFeature*) hFeat;
+    OGRFeature* poFeature = reinterpret_cast<OGRFeature *>(hFeat);
 
     fprintf(fpSpyFile, "f = ogr.Feature(%s)\n",
-            OGRAPISpyGetFeatureDefnVar((OGRFeatureDefnH)(poFeature->GetDefnRef())).c_str());
+            OGRAPISpyGetFeatureDefnVar(
+               reinterpret_cast<OGRFeatureDefnH>(poFeature->
+                   GetDefnRef())).c_str());
     if( poFeature->GetFID() != -1 )
         fprintf(fpSpyFile, "f.SetFID(" CPL_FRMT_GIB ")\n", poFeature->GetFID());
-    int i;
-    for(i = 0; i < poFeature->GetFieldCount(); i++)
+    for( int i = 0; i < poFeature->GetFieldCount(); i++ )
     {
-        if( poFeature->IsFieldSet(i) )
+        if( poFeature->IsFieldNull(i) )
+        {
+            fprintf(fpSpyFile, "f.SetFieldNull(%d)\n", i);
+        }
+        else if( poFeature->IsFieldSet(i) )
         {
             switch( poFeature->GetFieldDefnRef(i)->GetType())
             {
-                case OFTInteger: fprintf(fpSpyFile, "f.SetField(%d, %d)\n", i,
-                    poFeature->GetFieldAsInteger(i)); break;
-                case OFTReal: fprintf(fpSpyFile, "%s", CPLSPrintf("f.SetField(%d, %.16g)\n", i,
-                    poFeature->GetFieldAsDouble(i))); break;
-                case OFTString: fprintf(fpSpyFile, "f.SetField(%d, %s)\n", i,
-                    OGRAPISpyGetString(poFeature->GetFieldAsString(i)).c_str()); break;
-                default: fprintf(fpSpyFile, "f.SetField(%d, %s) #FIXME\n", i,
-                    OGRAPISpyGetString(poFeature->GetFieldAsString(i)).c_str()); break;
+                case OFTInteger:
+                    fprintf(fpSpyFile, "f.SetField(%d, %d)\n", i,
+                    poFeature->GetFieldAsInteger(i));
+                    break;
+                case OFTReal:
+                    fprintf(fpSpyFile,
+                            "%s", CPLSPrintf("f.SetField(%d, %.16g)\n", i,
+                    poFeature->GetFieldAsDouble(i)));
+                    break;
+                case OFTString:
+                    fprintf(fpSpyFile, "f.SetField(%d, %s)\n", i,
+                    OGRAPISpyGetString(poFeature->GetFieldAsString(i)).c_str());
+                    break;
+                default:
+                    fprintf(fpSpyFile, "f.SetField(%d, %s) #FIXME\n", i,
+                    OGRAPISpyGetString(poFeature->GetFieldAsString(i)).c_str());
+                    break;
             }
         }
     }
-    for(i = 0; i < poFeature->GetGeomFieldCount(); i++)
+    for( int i = 0; i < poFeature->GetGeomFieldCount(); i++ )
     {
         OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
         if( poGeom != NULL )
         {
-            fprintf(fpSpyFile, "f.SetGeomField(%d, %s)\n", i, OGRAPISpyGetGeom(
-                (OGRGeometryH)poGeom ).c_str() );
+            fprintf(fpSpyFile, "f.SetGeomField(%d, %s)\n",
+                    i,
+                    OGRAPISpyGetGeom(
+                       reinterpret_cast<OGRGeometryH>(poGeom)).c_str());
         }
     }
     const char* pszStyleString = poFeature->GetStyleString();
@@ -801,7 +856,8 @@ void OGRAPISpy_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
     OGRAPISpyDumpFeature(hFeat);
     fprintf(fpSpyFile, "%s.SetFeature(f)\n",
             OGRAPISpyGetLayerVar(hLayer).c_str());
-    fprintf(fpSpyFile, "f = None\n"); /* in case layer defn is changed afterwards */
+    // In case layer defn is changed afterwards.
+    fprintf(fpSpyFile, "f = None\n");
     OGRAPISpyFileClose();
 }
 
@@ -811,7 +867,8 @@ void OGRAPISpy_L_CreateFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
     OGRAPISpyDumpFeature(hFeat);
     fprintf(fpSpyFile, "%s.CreateFeature(f)\n",
             OGRAPISpyGetLayerVar(hLayer).c_str());
-    fprintf(fpSpyFile, "f = None\n"); /* in case layer defn is changed afterwards */
+    // In case layer defn is changed afterwards.
+    fprintf(fpSpyFile, "f = None\n");
     OGRAPISpyFileClose();
 }
 
@@ -823,7 +880,8 @@ static void OGRAPISpyDumpFieldDefn( OGRFieldDefn* poFieldDefn )
     if( poFieldDefn->GetWidth() > 0 )
         fprintf(fpSpyFile, "fd.SetWidth(%d)\n", poFieldDefn->GetWidth() );
     if( poFieldDefn->GetPrecision() > 0 )
-        fprintf(fpSpyFile, "fd.SetPrecision(%d)\n", poFieldDefn->GetPrecision() );
+        fprintf(fpSpyFile, "fd.SetPrecision(%d)\n",
+                poFieldDefn->GetPrecision() );
     if( !poFieldDefn->IsNullable() )
         fprintf(fpSpyFile, "fd.SetNullable(0)\n");
     if( poFieldDefn->GetDefault() != NULL )
@@ -853,7 +911,7 @@ void OGRAPISpy_L_DeleteField( OGRLayerH hLayer, int iField )
 void OGRAPISpy_L_ReorderFields( OGRLayerH hLayer, int* panMap )
 {
     OGRAPISpyFlushDefered();
-    OGRLayer* poLayer = (OGRLayer*) hLayer;
+    OGRLayer* poLayer = reinterpret_cast<OGRLayer *>(hLayer);
     fprintf(fpSpyFile, "%s.ReorderFields([",
             OGRAPISpyGetLayerVar(hLayer).c_str());
     for( int i = 0; i < poLayer->GetLayerDefn()->GetFieldCount(); i++ )
@@ -889,13 +947,18 @@ void OGRAPISpy_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
                                   int bApproxOK )
 {
     OGRAPISpyFlushDefered();
-    OGRGeomFieldDefn* poGeomFieldDefn = (OGRGeomFieldDefn*) hField;
+    OGRGeomFieldDefn* poGeomFieldDefn =
+        reinterpret_cast<OGRGeomFieldDefn *>(hField);
+
     fprintf(fpSpyFile, "geom_fd = ogr.GeomFieldDefn(%s, %s)\n",
             OGRAPISpyGetString(poGeomFieldDefn->GetNameRef()).c_str(),
             OGRAPISpyGetGeomType(poGeomFieldDefn->GetType()).c_str());
     if( poGeomFieldDefn->GetSpatialRef() != NULL )
-        fprintf(fpSpyFile, "geom_fd.SetSpatialRef(%s)\n", OGRAPISpyGetSRS(
-            (OGRSpatialReferenceH)poGeomFieldDefn->GetSpatialRef()).c_str() );
+        fprintf(
+            fpSpyFile, "geom_fd.SetSpatialRef(%s)\n",
+            OGRAPISpyGetSRS(
+                reinterpret_cast<OGRSpatialReferenceH>
+                    (poGeomFieldDefn->GetSpatialRef())).c_str() );
     if( !poGeomFieldDefn->IsNullable() )
         fprintf(fpSpyFile, "geom_fd.SetNullable(0)\n");
     fprintf(fpSpyFile, "%s.CreateGeomField(geom_fd, approx_ok = %d)\n",
@@ -906,13 +969,17 @@ void OGRAPISpy_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
 static void OGRAPISpy_L_Op( OGRLayerH hLayer, const char* pszMethod )
 {
     OGRAPISpyFlushDefered();
-    fprintf(fpSpyFile, "%s.%s()\n", OGRAPISpyGetLayerVar(hLayer).c_str(), pszMethod);
+    fprintf(fpSpyFile, "%s.%s()\n",
+            OGRAPISpyGetLayerVar(hLayer).c_str(), pszMethod);
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_L_StartTransaction( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "StartTransaction"); }
-void OGRAPISpy_L_CommitTransaction( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "CommitTransaction"); }
-void OGRAPISpy_L_RollbackTransaction( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "RollbackTransaction"); }
+void OGRAPISpy_L_StartTransaction( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "StartTransaction"); }
+void OGRAPISpy_L_CommitTransaction( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "CommitTransaction"); }
+void OGRAPISpy_L_RollbackTransaction( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "RollbackTransaction"); }
 
 void OGRAPISpy_L_GetLayerDefn( OGRLayerH hLayer )
 {
@@ -924,14 +991,22 @@ void OGRAPISpy_L_GetLayerDefn( OGRLayerH hLayer )
     }
 }
 
-void OGRAPISpy_L_GetSpatialRef( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "GetSpatialRef"); }
-void OGRAPISpy_L_GetSpatialFilter( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "GetSpatialFilter"); }
-void OGRAPISpy_L_ResetReading( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "ResetReading"); }
-void OGRAPISpy_L_SyncToDisk( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "SyncToDisk"); }
-void OGRAPISpy_L_GetFIDColumn( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "GetFIDColumn"); }
-void OGRAPISpy_L_GetGeometryColumn( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "GetGeometryColumn"); }
-void OGRAPISpy_L_GetName( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "GetName"); }
-void OGRAPISpy_L_GetGeomType( OGRLayerH hLayer ) { OGRAPISpy_L_Op(hLayer, "GetGeomType"); }
+void OGRAPISpy_L_GetSpatialRef( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "GetSpatialRef"); }
+void OGRAPISpy_L_GetSpatialFilter( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "GetSpatialFilter"); }
+void OGRAPISpy_L_ResetReading( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "ResetReading"); }
+void OGRAPISpy_L_SyncToDisk( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "SyncToDisk"); }
+void OGRAPISpy_L_GetFIDColumn( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "GetFIDColumn"); }
+void OGRAPISpy_L_GetGeometryColumn( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "GetGeometryColumn"); }
+void OGRAPISpy_L_GetName( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "GetName"); }
+void OGRAPISpy_L_GetGeomType( OGRLayerH hLayer )
+    { OGRAPISpy_L_Op(hLayer, "GetGeomType"); }
 
 void OGRAPISpy_L_FindFieldIndex( OGRLayerH hLayer, const char *pszFieldName,
                                  int bExactMatch )
@@ -974,10 +1049,11 @@ void OGRAPISpy_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField,
 
 void OGRAPISpy_L_SetSpatialFilterRect( OGRLayerH hLayer,
                                        double dfMinX, double dfMinY,
-                                       double dfMaxX, double dfMaxY)
+                                       double dfMaxX, double dfMaxY )
 {
     OGRAPISpyFlushDefered();
-    fprintf(fpSpyFile, "%s", CPLSPrintf("%s.SetSpatialFilterRect(%.16g, %.16g, %.16g, %.16g)\n",
+    fprintf(fpSpyFile, "%s",
+            CPLSPrintf("%s.SetSpatialFilterRect(%.16g, %.16g, %.16g, %.16g)\n",
             OGRAPISpyGetLayerVar(hLayer).c_str(),
             dfMinX, dfMinY, dfMaxX, dfMaxY));
     OGRAPISpyFileClose();
@@ -985,7 +1061,7 @@ void OGRAPISpy_L_SetSpatialFilterRect( OGRLayerH hLayer,
 
 void OGRAPISpy_L_SetSpatialFilterRectEx( OGRLayerH hLayer, int iGeomField,
                                          double dfMinX, double dfMinY,
-                                         double dfMaxX, double dfMaxY)
+                                         double dfMaxX, double dfMaxY )
 {
 
     OGRAPISpyFlushDefered();
@@ -1011,11 +1087,12 @@ void OGRAPISpy_L_SetIgnoredFields( OGRLayerH hLayer,
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.SetIgnoredFields(%s)\n",
             OGRAPISpyGetLayerVar(hLayer).c_str(),
-            OGRAPISpyGetOptions((char**)papszIgnoredFields).c_str());
+            OGRAPISpyGetOptions(
+                const_cast<char **>(papszIgnoredFields)).c_str());
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_FD_GetGeomType(OGRFeatureDefnH hDefn)
+void OGRAPISpy_FD_GetGeomType( OGRFeatureDefnH hDefn )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.GetGeomType()\n",
@@ -1023,10 +1100,13 @@ void OGRAPISpy_FD_GetGeomType(OGRFeatureDefnH hDefn)
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_FD_GetFieldCount(OGRFeatureDefnH hDefn)
+void OGRAPISpy_FD_GetFieldCount( OGRFeatureDefnH hDefn )
 {
     if( hLayerGetLayerDefn != NULL &&
-        (OGRFeatureDefnH)(((OGRLayer*)hLayerGetLayerDefn)->GetLayerDefn()) == hDefn )
+        reinterpret_cast<OGRFeatureDefnH>(
+            reinterpret_cast<OGRLayer *>(
+                hLayerGetLayerDefn)->GetLayerDefn()) ==
+        hDefn )
     {
         bDeferGetFieldCount = true;
     }
@@ -1039,8 +1119,8 @@ void OGRAPISpy_FD_GetFieldCount(OGRFeatureDefnH hDefn)
     }
 }
 
-void OGRAPISpy_FD_GetFieldDefn(OGRFeatureDefnH hDefn, int iField,
-                               OGRFieldDefnH hField)
+void OGRAPISpy_FD_GetFieldDefn( OGRFeatureDefnH hDefn, int iField,
+                                OGRFieldDefnH hField )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s_fielddefn%d = %s.GetFieldDefn(%d)\n",
@@ -1054,15 +1134,17 @@ void OGRAPISpy_FD_GetFieldDefn(OGRFeatureDefnH hDefn, int iField,
     if( oIter == oGlobalMapFieldDefn.end() )
     {
         oMapFDefn[hDefn].oMapFieldDefn[hField] = iField;
-        oGlobalMapFieldDefn[hField] = CPLSPrintf("%s_fielddefn%d",
-                                                     OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
-                                                     iField);
+        oGlobalMapFieldDefn[hField] =
+            CPLSPrintf("%s_fielddefn%d",
+                       OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
+                       iField);
     }
 
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_FD_GetFieldIndex(OGRFeatureDefnH hDefn, const char* pszFieldName)
+void OGRAPISpy_FD_GetFieldIndex( OGRFeatureDefnH hDefn,
+                                 const char* pszFieldName )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.GetFieldIndex(%s)\n",
@@ -1071,7 +1153,7 @@ void OGRAPISpy_FD_GetFieldIndex(OGRFeatureDefnH hDefn, const char* pszFieldName)
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_Fld_GetXXXX(OGRFieldDefnH hField, const char* pszOp)
+void OGRAPISpy_Fld_GetXXXX( OGRFieldDefnH hField, const char* pszOp )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.%s()\n",
@@ -1079,7 +1161,7 @@ void OGRAPISpy_Fld_GetXXXX(OGRFieldDefnH hField, const char* pszOp)
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_FD_GetGeomFieldCount(OGRFeatureDefnH hDefn)
+void OGRAPISpy_FD_GetGeomFieldCount( OGRFeatureDefnH hDefn )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.GetGeomFieldCount()\n",
@@ -1087,8 +1169,8 @@ void OGRAPISpy_FD_GetGeomFieldCount(OGRFeatureDefnH hDefn)
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_FD_GetGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField,
-                                   OGRGeomFieldDefnH hGeomField)
+void OGRAPISpy_FD_GetGeomFieldDefn( OGRFeatureDefnH hDefn, int iGeomField,
+                                    OGRGeomFieldDefnH hGeomField )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s_geomfielddefn%d = %s.GetGeomFieldDefn(%d)\n",
@@ -1102,15 +1184,17 @@ void OGRAPISpy_FD_GetGeomFieldDefn(OGRFeatureDefnH hDefn, int iGeomField,
     if( oIter == oGlobalMapGeomFieldDefn.end() )
     {
         oMapFDefn[hDefn].oMapGeomFieldDefn[hGeomField] = iGeomField;
-        oGlobalMapGeomFieldDefn[hGeomField] = CPLSPrintf("%s_geomfielddefn%d",
-                                                     OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
-                                                     iGeomField);
+        oGlobalMapGeomFieldDefn[hGeomField] =
+            CPLSPrintf("%s_geomfielddefn%d",
+                       OGRAPISpyGetFeatureDefnVar(hDefn).c_str(),
+                       iGeomField);
     }
 
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_FD_GetGeomFieldIndex(OGRFeatureDefnH hDefn, const char* pszFieldName)
+void OGRAPISpy_FD_GetGeomFieldIndex( OGRFeatureDefnH hDefn,
+                                     const char* pszFieldName )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.GetGeomFieldIndex(%s)\n",
@@ -1119,7 +1203,7 @@ void OGRAPISpy_FD_GetGeomFieldIndex(OGRFeatureDefnH hDefn, const char* pszFieldN
     OGRAPISpyFileClose();
 }
 
-void OGRAPISpy_GFld_GetXXXX(OGRGeomFieldDefnH hGeomField, const char* pszOp)
+void OGRAPISpy_GFld_GetXXXX( OGRGeomFieldDefnH hGeomField, const char* pszOp )
 {
     OGRAPISpyFlushDefered();
     fprintf(fpSpyFile, "%s.%s()\n",
@@ -1127,4 +1211,4 @@ void OGRAPISpy_GFld_GetXXXX(OGRGeomFieldDefnH hGeomField, const char* pszOp)
     OGRAPISpyFileClose();
 }
 
-#endif /* OGRAPISPY_ENABLED */
+#endif  // OGRAPISPY_ENABLED
diff --git a/ogr/ograpispy.h b/ogr/ograpispy.h
index d2d21e7..457c4cc 100644
--- a/ogr/ograpispy.h
+++ b/ogr/ograpispy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ograpispy.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ograpispy.h 35912 2016-10-24 16:41:45Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGR C API "Spy"
@@ -61,7 +61,6 @@
  * @since GDAL 2.0
  */
 
-
 #ifdef DEBUG
 #define OGRAPISPY_ENABLED
 #endif
diff --git a/ogr/ograssemblepolygon.cpp b/ogr/ograssemblepolygon.cpp
index 2b91b15..074b433 100644
--- a/ogr/ograssemblepolygon.cpp
+++ b/ogr/ograssemblepolygon.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ograssemblepolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  S-57 Reader
  * Purpose:  Implements polygon assembly from a bunch of arcs.
@@ -28,12 +27,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_api.h"
+
+#include <cmath>
+#include <cstddef>
 #include <vector>
+
+#include "ogr_core.h"
 #include "ogr_geometry.h"
-#include "ogr_api.h"
 #include "cpl_conv.h"
+#include "cpl_error.h"
 
-CPL_CVSID("$Id: ograssemblepolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ograssemblepolygon.cpp 36328 2016-11-20 13:44:29Z goatbar $");
 
 /************************************************************************/
 /*                            CheckPoints()                             */
@@ -43,32 +49,31 @@ CPL_CVSID("$Id: ograssemblepolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $");
 /************************************************************************/
 
 static bool CheckPoints( OGRLineString *poLine1, int iPoint1,
-                        OGRLineString *poLine2, int iPoint2,
-                        double *pdfDistance )
+                         OGRLineString *poLine2, int iPoint2,
+                         double *pdfDistance )
 
 {
     if( pdfDistance == NULL || *pdfDistance == 0 )
         return poLine1->getX(iPoint1) == poLine2->getX(iPoint2)
             && poLine1->getY(iPoint1) == poLine2->getY(iPoint2);
 
-    double dfDeltaX = poLine1->getX(iPoint1) - poLine2->getX(iPoint2);
-    double dfDeltaY = poLine1->getY(iPoint1) - poLine2->getY(iPoint2);
-
-    dfDeltaX = ABS(dfDeltaX);
-    dfDeltaY = ABS(dfDeltaY);
+    const double dfDeltaX =
+        std::abs(poLine1->getX(iPoint1) - poLine2->getX(iPoint2));
+    const double dfDeltaY =
+        std::abs(poLine1->getY(iPoint1) - poLine2->getY(iPoint2));
 
     if( dfDeltaX > *pdfDistance || dfDeltaY > *pdfDistance )
         return false;
 
-    double dfDistance = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
+    const double dfDistance = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
 
     if( dfDistance < *pdfDistance )
     {
         *pdfDistance = dfDistance;
         return true;
     }
-    else
-        return false;
+
+    return false;
 }
 
 /************************************************************************/
@@ -76,27 +81,17 @@ static bool CheckPoints( OGRLineString *poLine1, int iPoint1,
 /************************************************************************/
 
 static void AddEdgeToRing( OGRLinearRing * poRing, OGRLineString * poLine,
-                           int bReverse )
+                           bool bReverse )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Establish order and range of traverse.                          */
 /* -------------------------------------------------------------------- */
-    int         iStart=0, iEnd=0, iStep=0;
-    int         nVertToAdd = poLine->getNumPoints();
+    const int nVertToAdd = poLine->getNumPoints();
 
-    if( !bReverse )
-    {
-        iStart = 0;
-        iEnd = nVertToAdd - 1;
-        iStep = 1;
-    }
-    else
-    {
-        iStart = nVertToAdd - 1;
-        iEnd = 0;
-        iStep = -1;
-    }
+    int iStart = bReverse ? nVertToAdd - 1 : 0;
+    const int iEnd = bReverse ? 0 : nVertToAdd - 1;
+    const int iStep = bReverse ? -1 : 1;
 
 /* -------------------------------------------------------------------- */
 /*      Should we skip a repeating vertex?                              */
@@ -118,7 +113,8 @@ static void AddEdgeToRing( OGRLinearRing * poRing, OGRLineString * poLine,
 /**
  * Build a ring from a bunch of arcs.
  *
- * @param hLines handle to an OGRGeometryCollection (or OGRMultiLineString) containing the line string geometries to be built into rings.
+ * @param hLines handle to an OGRGeometryCollection (or OGRMultiLineString)
+ * containing the line string geometries to be built into rings.
  * @param bBestEffort not yet implemented???.
  * @param bAutoClose indicates if the ring should be close when first and
  * last points of the ring are the same.
@@ -130,7 +126,7 @@ static void AddEdgeToRing( OGRLinearRing * poRing, OGRLineString * poLine,
  */
 
 OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
-                                       int bBestEffort,
+                                       CPL_UNUSED int bBestEffort,
                                        int bAutoClose,
                                        double dfTolerance,
                                        OGRErr * peErr )
@@ -138,7 +134,7 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 {
     if( hLines == NULL )
     {
-        if (peErr != NULL)
+        if( peErr != NULL )
             *peErr = OGRERR_NONE;
         return NULL;
     }
@@ -147,31 +143,32 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 /*      Check for the case of a geometrycollection that can be          */
 /*      promoted to MultiLineString.                                    */
 /* -------------------------------------------------------------------- */
-    OGRGeometry* poGeom = (OGRGeometry*) hLines;
+    OGRGeometry* poGeom = reinterpret_cast<OGRGeometry *>(hLines);
     if( wkbFlatten(poGeom->getGeometryType()) == wkbGeometryCollection )
     {
-        int iGeom;
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
 
-        for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
+        for( int iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
         {
             if( wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType())
                 != wkbLineString )
             {
-                if (peErr != NULL)
+                if( peErr != NULL )
                     *peErr = OGRERR_FAILURE;
                 CPLError(CE_Failure, CPLE_NotSupported,
-                         "The geometry collection contains non line string geometries");
+                         "The geometry collection contains "
+                         "non-line string geometries");
                 return NULL;
             }
         }
     }
-    else if (wkbFlatten(poGeom->getGeometryType()) != wkbMultiLineString )
+    else if( wkbFlatten(poGeom->getGeometryType()) != wkbMultiLineString )
     {
-        if (peErr != NULL)
+        if( peErr != NULL )
             *peErr = OGRERR_FAILURE;
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "The passed geometry is not an OGRGeometryCollection (or OGRMultiLineString) "
+                 "The passed geometry is not an OGRGeometryCollection "
+                 "(or OGRMultiLineString) "
                  "containing line string geometries");
         return NULL;
     }
@@ -180,36 +177,38 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
     OGRGeometryCollection *poLines = (OGRGeometryCollection *) hLines;
     std::vector<OGRLinearRing*> aoRings;
 
-    (void) bBestEffort;
-
 /* -------------------------------------------------------------------- */
 /*      Setup array of line markers indicating if they have been        */
 /*      added to a ring yet.                                            */
 /* -------------------------------------------------------------------- */
-    int         nEdges = poLines->getNumGeometries();
-    int         *panEdgeConsumed, nRemainingEdges = nEdges;
-
-    panEdgeConsumed = (int *) CPLCalloc(sizeof(int),nEdges);
+    const int nEdges = poLines->getNumGeometries();
+    int nRemainingEdges = nEdges;
+    std::vector<bool> oEdgeConsumed(nEdges, false);
 
 /* ==================================================================== */
 /*      Loop generating rings.                                          */
 /* ==================================================================== */
     while( nRemainingEdges > 0 )
     {
-        int             iEdge;
-        OGRLineString   *poLine;
-
 /* -------------------------------------------------------------------- */
 /*      Find the first unconsumed edge.                                 */
 /* -------------------------------------------------------------------- */
-        for( iEdge = 0; panEdgeConsumed[iEdge]; iEdge++ ) {}
+        int iFirstEdge = 0;  // Used after for.
+        for( ; oEdgeConsumed[iFirstEdge]; iFirstEdge++ ) {}
 
-        poLine = (OGRLineString *) poLines->getGeometryRef(iEdge);
+        OGRLineString *poLine =
+            dynamic_cast<OGRLineString *>(poLines->getGeometryRef(iFirstEdge));
+        if( poLine == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRLineString.");
+            return NULL;
+        }
 
-        panEdgeConsumed[iEdge] = TRUE;
+        oEdgeConsumed[iFirstEdge] = true;
         nRemainingEdges--;
 
-        if (poLine->getNumPoints() < 2)
+        if( poLine->getNumPoints() < 2 )
         {
             continue;
         }
@@ -217,7 +216,7 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 /* -------------------------------------------------------------------- */
 /*      Start a new ring, copying in the current line directly          */
 /* -------------------------------------------------------------------- */
-        OGRLinearRing   *poRing = new OGRLinearRing();
+        OGRLinearRing *poRing = new OGRLinearRing();
 
         AddEdgeToRing( poRing, poLine, FALSE );
 
@@ -225,15 +224,14 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 /*      Loop adding edges to this ring until we make a whole pass       */
 /*      within finding anything to add.                                 */
 /* ==================================================================== */
-        bool            bWorkDone = true;
-        double          dfBestDist = dfTolerance;
+        bool bWorkDone = true;
+        double dfBestDist = dfTolerance;
 
-        while( !CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,NULL)
+        while( !CheckPoints(poRing, 0, poRing, poRing->getNumPoints() - 1, NULL)
                && nRemainingEdges > 0
                && bWorkDone )
         {
-            int         iBestEdge = -1;
-            int         bReverse = FALSE;
+            bool bReverse = false;
 
             bWorkDone = false;
             dfBestDist = dfTolerance;
@@ -241,45 +239,60 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
             // We consider linking the end to the beginning.  If this is
             // closer than any other option we will just close the loop.
 
-            //CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,&dfBestDist);
+            // CheckPoints(poRing, 0, poRing, poRing->getNumPoints()-1,
+            //             &dfBestDist);
 
             // Find unused edge with end point closest to our loose end.
-            for( iEdge = 0; iEdge < nEdges; iEdge++ )
+            int iBestEdge = -1;
+            for( int iEdge = 0; iEdge < nEdges; iEdge++ )
             {
-                if( panEdgeConsumed[iEdge] )
+                if( oEdgeConsumed[iEdge] )
                     continue;
 
-                poLine = (OGRLineString *) poLines->getGeometryRef(iEdge);
-                if (poLine->getNumPoints() < 2)
+                poLine = dynamic_cast<OGRLineString *>(
+                    poLines->getGeometryRef(iEdge));
+                if( poLine == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                             "dynamic_cast failed.  Expected OGRLineString.");
+                    return NULL;
+                }
+                if( poLine->getNumPoints() < 2 )
                     continue;
 
-                if( CheckPoints(poLine,0,poRing,poRing->getNumPoints()-1,
+                if( CheckPoints(poLine, 0, poRing, poRing->getNumPoints() - 1,
                                 &dfBestDist) )
                 {
                     iBestEdge = iEdge;
-                    bReverse = FALSE;
+                    bReverse = false;
                 }
-                if( CheckPoints(poLine,poLine->getNumPoints()-1,
-                                poRing,poRing->getNumPoints()-1,
+                if( CheckPoints(poLine, poLine->getNumPoints() - 1,
+                                poRing, poRing->getNumPoints() - 1,
                                 &dfBestDist) )
                 {
                     iBestEdge = iEdge;
-                    bReverse = TRUE;
+                    bReverse = true;
                 }
 
-                // if we use exact comparison, jump now
-                if (dfTolerance == 0.0 && iBestEdge != -1) break;
+                // If we use exact comparison, jump now.
+                if( dfTolerance == 0.0 && iBestEdge != -1 ) break;
             }
 
             // We found one within tolerance - add it.
             if( iBestEdge != -1 )
             {
-                poLine = (OGRLineString *)
-                    poLines->getGeometryRef(iBestEdge);
+                poLine = dynamic_cast<OGRLineString *>(
+                    poLines->getGeometryRef(iBestEdge));
+                if( poLine == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                             "dynamic_cast failed.  Expected OGRLineString.");
+                    return NULL;
+                }
 
                 AddEdgeToRing( poRing, poLine, bReverse );
 
-                panEdgeConsumed[iBestEdge] = TRUE;
+                oEdgeConsumed[iBestEdge] = true;
                 nRemainingEdges--;
                 bWorkDone = true;
             }
@@ -290,16 +303,16 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 /* -------------------------------------------------------------------- */
         dfBestDist = dfTolerance;
 
-        if( !CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,
+        if( !CheckPoints(poRing, 0, poRing, poRing->getNumPoints() - 1,
                          &dfBestDist) )
         {
             CPLDebug( "OGR",
                       "Failed to close ring %d.\n"
-                      "End Points are: (%.8f,%.7f) and (%.7f,%.7f)\n",
-                      (int)aoRings.size(),
+                      "End Points are: (%.8f,%.7f) and (%.7f,%.7f)",
+                      static_cast<int>(aoRings.size()),
                       poRing->getX(0), poRing->getY(0),
-                      poRing->getX(poRing->getNumPoints()-1),
-                      poRing->getY(poRing->getNumPoints()-1) );
+                      poRing->getX(poRing->getNumPoints() - 1),
+                      poRing->getY(poRing->getNumPoints() - 1) );
 
             bSuccess = false;
         }
@@ -307,59 +320,51 @@ OGRGeometryH OGRBuildPolygonFromEdges( OGRGeometryH hLines,
 /* -------------------------------------------------------------------- */
 /*      Do we need to auto-close this ring?                             */
 /* -------------------------------------------------------------------- */
-        if( bAutoClose
-            && !CheckPoints(poRing,0,poRing,poRing->getNumPoints()-1,NULL) )
+        if( bAutoClose &&
+            !CheckPoints(poRing, 0, poRing, poRing->getNumPoints() - 1, NULL) )
         {
-            poRing->addPoint( poRing->getX(0),
-                              poRing->getY(0),
-                              poRing->getZ(0));
+            poRing->addPoint(poRing->getX(0),
+                             poRing->getY(0),
+                             poRing->getZ(0));
         }
 
         aoRings.push_back(poRing);
-    } /* next ring */
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup.                                                        */
-/* -------------------------------------------------------------------- */
-    CPLFree( panEdgeConsumed );
+    }  // Next ring.
 
 /* -------------------------------------------------------------------- */
 /*      Identify exterior ring - it will be the largest.  #3610         */
 /* -------------------------------------------------------------------- */
     double maxarea = 0.0;
-    int maxring = -1, rn;
+    int maxring = -1;
     OGREnvelope tenv;
 
-    for (rn = 0; rn < (int)aoRings.size(); ++rn)
+    for( int rn = 0; rn < static_cast<int>(aoRings.size()); ++rn )
     {
         aoRings[rn]->getEnvelope(&tenv);
-        double tarea = (tenv.MaxX - tenv.MinX) * (tenv.MaxY - tenv.MinY);
-        if (tarea > maxarea)
+        const double tarea = (tenv.MaxX - tenv.MinX) * (tenv.MaxY - tenv.MinY);
+        if( tarea > maxarea )
         {
             maxarea = tarea;
             maxring = rn;
         }
     }
 
-    OGRPolygon  *poPolygon = new OGRPolygon();
+    OGRPolygon *poPolygon = new OGRPolygon();
 
-    if (maxring != -1)
+    if( maxring != -1 )
     {
         poPolygon->addRingDirectly(aoRings[maxring]);
-        for (rn = 0; rn < (int)aoRings.size(); ++rn)
+        for( int rn = 0; rn < static_cast<int>(aoRings.size()); ++rn )
         {
-            if (rn == maxring) continue;
+            if( rn == maxring ) continue;
             poPolygon->addRingDirectly(aoRings[rn]);
         }
     }
 
     if( peErr != NULL )
     {
-        if( bSuccess )
-            *peErr = OGRERR_NONE;
-        else
-            *peErr = OGRERR_FAILURE;
+        *peErr = bSuccess ? OGRERR_NONE : OGRERR_FAILURE;
     }
 
-    return (OGRGeometryH) poPolygon;
+    return reinterpret_cast<OGRGeometryH>(poPolygon);
 }
diff --git a/ogr/ogrcircularstring.cpp b/ogr/ogrcircularstring.cpp
index 5276986..7085ca5 100644
--- a/ogr/ogrcircularstring.cpp
+++ b/ogr/ogrcircularstring.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcircularstring.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRCircularString geometry class.
@@ -27,12 +26,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
-#include "ogr_p.h"
-#include <assert.h>
+
+#include <cmath>
+#include <cstring>
+
+#include <algorithm>
 #include <vector>
 
-CPL_CVSID("$Id");
+#include "cpl_error.h"
+#include "ogr_core.h"
+#include "ogr_geometry.h"
+#include "ogr_p.h"
+
+CPL_CVSID("$Id: ogrcircularstring.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+static inline double dist(double x0, double y0, double x1, double y1)
+{
+    return std::sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
+}
 
 /************************************************************************/
 /*                         OGRCircularString()                          */
@@ -42,10 +55,7 @@ CPL_CVSID("$Id");
  * \brief Create an empty circular string.
  */
 
-OGRCircularString::OGRCircularString()
-
-{
-}
+OGRCircularString::OGRCircularString() {}
 
 /************************************************************************/
 /*              OGRCircularString( const OGRCircularString& )           */
@@ -62,17 +72,13 @@ OGRCircularString::OGRCircularString()
 
 OGRCircularString::OGRCircularString( const OGRCircularString& other ) :
     OGRSimpleCurve( other )
-{
-}
+{}
 
 /************************************************************************/
 /*                        ~OGRCircularString()                          */
 /************************************************************************/
 
-OGRCircularString::~OGRCircularString()
-
-{
-}
+OGRCircularString::~OGRCircularString() {}
 
 /************************************************************************/
 /*                  operator=( const OGRCircularString& )               */
@@ -87,7 +93,8 @@ OGRCircularString::~OGRCircularString()
  * @since GDAL 2.1
  */
 
-OGRCircularString& OGRCircularString::operator=( const OGRCircularString& other )
+OGRCircularString&
+OGRCircularString::operator=( const OGRCircularString& other )
 {
     if( this != &other)
     {
@@ -105,7 +112,7 @@ OGRwkbGeometryType OGRCircularString::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbCircularStringZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbCircularStringM;
     else if( flags & OGR_G_3D )
         return wkbCircularStringZ;
@@ -136,9 +143,9 @@ OGRErr OGRCircularString::importFromWkb( unsigned char * pabyData,
 
 {
     OGRErr eErr = OGRSimpleCurve::importFromWkb(pabyData, nSize, eWkbVariant);
-    if (eErr == OGRERR_NONE)
+    if( eErr == OGRERR_NONE )
     {
-        if (!IsValidFast())
+        if( !IsValidFast() )
         {
             empty();
             return OGRERR_CORRUPT_DATA;
@@ -153,17 +160,18 @@ OGRErr OGRCircularString::importFromWkb( unsigned char * pabyData,
 /*      Build a well known binary representation of this object.        */
 /************************************************************************/
 
-OGRErr  OGRCircularString::exportToWkb( OGRwkbByteOrder eByteOrder,
-                                        unsigned char * pabyData,
-                                        OGRwkbVariant eWkbVariant  ) const
+OGRErr OGRCircularString::exportToWkb( OGRwkbByteOrder eByteOrder,
+                                       unsigned char * pabyData,
+                                       OGRwkbVariant eWkbVariant ) const
 
 {
-    if (!IsValidFast())
+    if( !IsValidFast() )
     {
         return OGRERR_FAILURE;
     }
 
-    if( eWkbVariant == wkbVariantOldOgc ) /* does not make sense for new geometries, so patch it */
+    // Does not make sense for new geometries, so patch it.
+    if( eWkbVariant == wkbVariantOldOgc )
         eWkbVariant = wkbVariantIso;
     return OGRSimpleCurve::exportToWkb(eByteOrder, pabyData, eWkbVariant);
 }
@@ -178,10 +186,10 @@ OGRErr  OGRCircularString::exportToWkb( OGRwkbByteOrder eByteOrder,
 OGRErr OGRCircularString::importFromWkt( char ** ppszInput )
 
 {
-    OGRErr eErr = OGRSimpleCurve::importFromWkt(ppszInput);
-    if (eErr == OGRERR_NONE)
+    const OGRErr eErr = OGRSimpleCurve::importFromWkt(ppszInput);
+    if( eErr == OGRERR_NONE )
     {
-        if (!IsValidFast())
+        if( !IsValidFast() )
         {
             empty();
             return OGRERR_CORRUPT_DATA;
@@ -194,11 +202,12 @@ OGRErr OGRCircularString::importFromWkt( char ** ppszInput )
 /*                            exportToWkt()                             */
 /************************************************************************/
 
-OGRErr OGRCircularString::exportToWkt( char ** ppszDstText,
-                                       CPL_UNUSED OGRwkbVariant eWkbVariant ) const
+OGRErr
+OGRCircularString::exportToWkt( char ** ppszDstText,
+                                CPL_UNUSED OGRwkbVariant eWkbVariant ) const
 
 {
-    if (!IsValidFast())
+    if( !IsValidFast() )
     {
         return OGRERR_FAILURE;
     }
@@ -216,21 +225,29 @@ double OGRCircularString::get_Length() const
 
 {
     double dfLength = 0.0;
-    double R, cx, cy, alpha0, alpha1, alpha2;
-    int i;
-    for(i=0;i<nPointCount-2;i+=2)
+    for( int i = 0; i < nPointCount-2; i += 2 )
     {
-        double x0 = paoPoints[i].x, y0 = paoPoints[i].y,
-               x1 = paoPoints[i+1].x, y1 = paoPoints[i+1].y,
-               x2 = paoPoints[i+2].x, y2 = paoPoints[i+2].y;
+        const double x0 = paoPoints[i].x;
+        const double y0 = paoPoints[i].y;
+        const double x1 = paoPoints[i+1].x;
+        const double y1 = paoPoints[i+1].y;
+        const double x2 = paoPoints[i+2].x;
+        const double y2 = paoPoints[i+2].y;
+        double R = 0.0;
+        double cx = 0.0;
+        double cy = 0.0;
+        double alpha0 = 0.0;
+        double alpha1 = 0.0;
+        double alpha2 = 0.0;
         if( OGRGeometryFactory::GetCurveParmeters(x0, y0, x1, y1, x2, y2,
-                                            R, cx, cy, alpha0, alpha1, alpha2) )
+                                                  R, cx, cy,
+                                                  alpha0, alpha1, alpha2) )
         {
             dfLength += fabs(alpha2 - alpha0) * R;
         }
         else
         {
-            dfLength += sqrt((x2-x0)*(x2-x0)+(y2-y0)*(y2-y0));
+            dfLength += dist(x0, y0, x2, y2);
         }
     }
     return dfLength;
@@ -240,49 +257,58 @@ double OGRCircularString::get_Length() const
 /*                       ExtendEnvelopeWithCircular()                   */
 /************************************************************************/
 
-void OGRCircularString::ExtendEnvelopeWithCircular( OGREnvelope * psEnvelope ) const
+void OGRCircularString::ExtendEnvelopeWithCircular(
+    OGREnvelope * psEnvelope ) const
 {
     if( !IsValidFast() || nPointCount == 0 )
         return;
 
-    /* Loop through circular portions and determine if they include some */
-    /* extremities of the circle */
-    for(int i=0;i<nPointCount-2;i+=2)
+    // Loop through circular portions and determine if they include some
+    // extremities of the circle.
+    for( int i = 0; i < nPointCount - 2; i += 2 )
     {
-        double x0 = paoPoints[i].x, y0 = paoPoints[i].y,
-               x1 = paoPoints[i+1].x, y1 = paoPoints[i+1].y,
-               x2 = paoPoints[i+2].x, y2 = paoPoints[i+2].y;
-        double R, cx, cy, alpha0, alpha1, alpha2;
+        double x0 = paoPoints[i].x;
+        const double y0 = paoPoints[i].y;
+        const double x1 = paoPoints[i+1].x;
+        const double y1 = paoPoints[i+1].y;
+        const double x2 = paoPoints[i+2].x;
+        const double y2 = paoPoints[i+2].y;
+        double R = 0.0;
+        double cx = 0.0;
+        double cy = 0.0;
+        double alpha0 = 0.0;
+        double alpha1 = 0.0;
+        double alpha2 = 0.0;
         if( OGRGeometryFactory::GetCurveParmeters(x0, y0, x1, y1, x2, y2,
-                                            R, cx, cy, alpha0, alpha1, alpha2))
+                                                  R, cx, cy,
+                                                  alpha0, alpha1, alpha2))
         {
-            int quadrantStart = (int)floor(alpha0 / (M_PI / 2));
-            int quadrantEnd  = (int)floor(alpha2 / (M_PI / 2));
+            int quadrantStart =
+                static_cast<int>(std::floor(alpha0 / (M_PI / 2)));
+            int quadrantEnd = static_cast<int>(std::floor(alpha2 / (M_PI / 2)));
             if( quadrantStart > quadrantEnd )
             {
-                int tmp = quadrantStart;
-                quadrantStart = quadrantEnd;
-                quadrantEnd = tmp;
+                std::swap(quadrantStart, quadrantEnd);
             }
-            /* Transition trough quadrants in counter-clock wise direction */
-            for( int j=quadrantStart+1; j<=quadrantEnd; j++)
+            // Transition trough quadrants in counter-clock wise direction.
+            for( int j = quadrantStart + 1; j <= quadrantEnd; ++j )
             {
-                switch( ((j+8)%4) )
+                switch( (j + 8) % 4 )
                 {
                     case 0:
-                        psEnvelope->MaxX = MAX(psEnvelope->MaxX, cx + R);
+                        psEnvelope->MaxX = std::max(psEnvelope->MaxX, cx + R);
                         break;
                     case 1:
-                        psEnvelope->MaxY = MAX(psEnvelope->MaxY, cy + R);
+                        psEnvelope->MaxY = std::max(psEnvelope->MaxY, cy + R);
                         break;
                     case 2:
-                        psEnvelope->MinX = MIN(psEnvelope->MinX, cx - R);
+                        psEnvelope->MinX = std::min(psEnvelope->MinX, cx - R);
                         break;
                     case 3:
-                        psEnvelope->MinY = MIN(psEnvelope->MaxY, cy - R);
+                        psEnvelope->MinY = std::min(psEnvelope->MaxY, cy - R);
                         break;
                     default:
-                        CPLAssert(FALSE);
+                        CPLAssert(false);
                         break;
                 }
             }
@@ -321,11 +347,11 @@ void OGRCircularString::segmentize( double dfMaxLength )
     if( !IsValidFast() || nPointCount == 0 )
         return;
 
-    /* So as to make sure that the same line followed in both directions */
-    /* result in the same segmentized line */
-    if ( paoPoints[0].x < paoPoints[nPointCount - 1].x ||
-         (paoPoints[0].x == paoPoints[nPointCount - 1].x &&
-          paoPoints[0].y < paoPoints[nPointCount - 1].y) )
+    // So as to make sure that the same line followed in both directions
+    // result in the same segmentized line.
+    if( paoPoints[0].x < paoPoints[nPointCount - 1].x ||
+        (paoPoints[0].x == paoPoints[nPointCount - 1].x &&
+         paoPoints[0].y < paoPoints[nPointCount - 1].y) )
     {
         reversePoints();
         segmentize(dfMaxLength);
@@ -334,58 +360,85 @@ void OGRCircularString::segmentize( double dfMaxLength )
 
     std::vector<OGRRawPoint> aoRawPoint;
     std::vector<double> adfZ;
-    for(int i=0;i<nPointCount-2;i+=2)
+    for( int i = 0; i < nPointCount - 2; i += 2 )
     {
-        double x0 = paoPoints[i].x, y0 = paoPoints[i].y,
-               x1 = paoPoints[i+1].x, y1 = paoPoints[i+1].y,
-               x2 = paoPoints[i+2].x, y2 = paoPoints[i+2].y;
-        double R, cx, cy, alpha0, alpha1, alpha2;
-
-        aoRawPoint.push_back(OGRRawPoint(x0,y0));
+        const double x0 = paoPoints[i].x;
+        const double y0 = paoPoints[i].y;
+        const double x1 = paoPoints[i+1].x;
+        const double y1 = paoPoints[i+1].y;
+        const double x2 = paoPoints[i+2].x;
+        const double y2 = paoPoints[i+2].y;
+        double R = 0.0;
+        double cx = 0.0;
+        double cy = 0.0;
+        double alpha0 = 0.0;
+        double alpha1 = 0.0;
+        double alpha2 = 0.0;
+
+        aoRawPoint.push_back(OGRRawPoint(x0, y0));
         if( padfZ )
             adfZ.push_back(padfZ[i]);
 
-        /* We have strong constraints on the number of intermediate points */
-        /* we can add */
+        // We have strong constraints on the number of intermediate points
+        // we can add.
 
         if( OGRGeometryFactory::GetCurveParmeters(x0, y0, x1, y1, x2, y2,
-                                            R, cx, cy, alpha0, alpha1, alpha2) )
+                                                  R, cx, cy,
+                                                  alpha0, alpha1, alpha2) )
         {
-            /* It is an arc circle */
-            double dfSegmentLength1 = fabs(alpha1 - alpha0) * R;
-            double dfSegmentLength2 = fabs(alpha2 - alpha1) * R;
-            if( dfSegmentLength1 > dfMaxLength || dfSegmentLength2 > dfMaxLength )
+            // It is an arc circle.
+            const double dfSegmentLength1 = fabs(alpha1 - alpha0) * R;
+            const double dfSegmentLength2 = fabs(alpha2 - alpha1) * R;
+            if( dfSegmentLength1 > dfMaxLength ||
+                dfSegmentLength2 > dfMaxLength )
             {
-                int nIntermediatePoints = 1 + 2 * (int)floor(dfSegmentLength1 / dfMaxLength / 2);
-                double dfStep = (alpha1 - alpha0) / (nIntermediatePoints + 1);
-                for(int j=1;j<=nIntermediatePoints;j++)
+                const int nIntermediatePoints =
+                    1 +
+                    2 * static_cast<int>(std::floor(dfSegmentLength1
+                                                    / dfMaxLength / 2.0));
+                const double dfStep =
+                    (alpha1 - alpha0) / (nIntermediatePoints + 1);
+                for( int j = 1; j <= nIntermediatePoints; ++j )
                 {
                     double alpha = alpha0 + dfStep * j;
-                    double x = cx + R * cos(alpha), y = cy + R * sin(alpha);
-                    aoRawPoint.push_back(OGRRawPoint(x,y));
+                    const double x = cx + R * cos(alpha);
+                    const double y = cy + R * sin(alpha);
+                    aoRawPoint.push_back(OGRRawPoint(x, y));
                     if( padfZ )
                     {
-                        double z = padfZ[i] + (padfZ[i+1] - padfZ[i]) * (alpha - alpha0) / (alpha1 - alpha0);
+                        const double z =
+                            padfZ[i] +
+                            (padfZ[i+1] - padfZ[i]) * (alpha - alpha0) /
+                            (alpha1 - alpha0);
                         adfZ.push_back(z);
                     }
                 }
             }
-            aoRawPoint.push_back(OGRRawPoint(x1,y1));
+            aoRawPoint.push_back(OGRRawPoint(x1, y1));
             if( padfZ )
                 adfZ.push_back(padfZ[i+1]);
 
-            if( dfSegmentLength1 > dfMaxLength || dfSegmentLength2 > dfMaxLength )
+            if( dfSegmentLength1 > dfMaxLength ||
+                dfSegmentLength2 > dfMaxLength )
             {
-                int nIntermediatePoints = 1 + 2 * (int)floor(dfSegmentLength2 / dfMaxLength / 2);
-                double dfStep = (alpha2 - alpha1) / (nIntermediatePoints + 1);
-                for(int j=1;j<=nIntermediatePoints;j++)
+                int nIntermediatePoints =
+                    1 +
+                    2 * static_cast<int>(std::floor(dfSegmentLength2
+                                                    / dfMaxLength / 2.0));
+                const double dfStep =
+                    (alpha2 - alpha1) / (nIntermediatePoints + 1);
+                for( int j = 1; j <= nIntermediatePoints; ++j )
                 {
-                    double alpha = alpha1 + dfStep * j;
-                    double x = cx + R * cos(alpha), y = cy + R * sin(alpha);
-                    aoRawPoint.push_back(OGRRawPoint(x,y));
+                    const double alpha = alpha1 + dfStep * j;
+                    const double x = cx + R * cos(alpha);
+                    const double y = cy + R * sin(alpha);
+                    aoRawPoint.push_back(OGRRawPoint(x, y));
                     if( padfZ )
                     {
-                        double z = padfZ[i+1] + (padfZ[i+2] - padfZ[i+1]) * (alpha - alpha1) / (alpha2 - alpha1);
+                        const double z =
+                            padfZ[i+1] +
+                            (padfZ[i+2] - padfZ[i+1]) *
+                            (alpha - alpha1) / (alpha2 - alpha1);
                         adfZ.push_back(z);
                     }
                 }
@@ -393,36 +446,44 @@ void OGRCircularString::segmentize( double dfMaxLength )
         }
         else
         {
-            /* It is a straight line */
-            double dfSegmentLength1 = sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0));
-            double dfSegmentLength2 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
-            if( dfSegmentLength1 > dfMaxLength || dfSegmentLength2 > dfMaxLength )
+            // It is a straight line.
+            const double dfSegmentLength1 = dist(x0, y0, x1, y1);
+            const double dfSegmentLength2 = dist(x1, y1, x2, y2);
+            if( dfSegmentLength1 > dfMaxLength ||
+                dfSegmentLength2 > dfMaxLength )
             {
-                int nIntermediatePoints = 1 + 2 * (int)ceil(dfSegmentLength1 / dfMaxLength / 2);
-                for(int j=1;j<=nIntermediatePoints;j++)
+                int nIntermediatePoints =
+                    1 + 2 * static_cast<int>(ceil(dfSegmentLength1 /
+                                                  dfMaxLength / 2.0));
+                for( int j = 1; j <= nIntermediatePoints; ++j )
                 {
                     aoRawPoint.push_back(OGRRawPoint(
                             x0 + j * (x1-x0) / (nIntermediatePoints + 1),
                             y0 + j * (y1-y0) / (nIntermediatePoints + 1)));
                     if( padfZ )
-                        adfZ.push_back(padfZ[i] + j * (padfZ[i+1]-padfZ[i]) / (nIntermediatePoints + 1));
+                        adfZ.push_back(padfZ[i] + j * (padfZ[i+1]-padfZ[i]) /
+                                       (nIntermediatePoints + 1));
                 }
             }
 
-            aoRawPoint.push_back(OGRRawPoint(x1,y1));
+            aoRawPoint.push_back(OGRRawPoint(x1, y1));
             if( padfZ )
                 adfZ.push_back(padfZ[i+1]);
 
-            if( dfSegmentLength1 > dfMaxLength || dfSegmentLength2 > dfMaxLength )
+            if( dfSegmentLength1 > dfMaxLength ||
+                dfSegmentLength2 > dfMaxLength )
             {
-                int nIntermediatePoints = 1 + 2 * (int)ceil(dfSegmentLength2 / dfMaxLength / 2);
-                for(int j=1;j<=nIntermediatePoints;j++)
+                const int nIntermediatePoints =
+                    1 + 2 * static_cast<int>(ceil(dfSegmentLength2 /
+                                                  dfMaxLength / 2.0));
+                for( int j = 1; j <= nIntermediatePoints; ++j )
                 {
                     aoRawPoint.push_back(OGRRawPoint(
                             x1 + j * (x2-x1) / (nIntermediatePoints + 1),
                             y1 + j * (y2-y1) / (nIntermediatePoints + 1)));
                     if( padfZ )
-                        adfZ.push_back(padfZ[i+1] + j * (padfZ[i+2]-padfZ[i+1]) / (nIntermediatePoints + 1));
+                        adfZ.push_back(padfZ[i+1] + j * (padfZ[i+2]-padfZ[i+1])
+                                       / (nIntermediatePoints + 1));
                 }
             }
         }
@@ -431,22 +492,24 @@ void OGRCircularString::segmentize( double dfMaxLength )
     if( padfZ )
         adfZ.push_back(padfZ[nPointCount-1]);
 
-    CPLAssert(aoRawPoint.size() == 0 || (aoRawPoint.size() >= 3 && (aoRawPoint.size() % 2) == 1));
+    CPLAssert(aoRawPoint.empty() ||
+              (aoRawPoint.size() >= 3 && (aoRawPoint.size() % 2) == 1));
     if( padfZ )
     {
         CPLAssert(adfZ.size() == aoRawPoint.size());
     }
 
-    /* Is there actually something to modify ? */
-    if( nPointCount < (int)aoRawPoint.size() )
+    // Is there actually something to modify?
+    if( nPointCount < static_cast<int>(aoRawPoint.size()) )
     {
-        nPointCount = (int)aoRawPoint.size();
-        paoPoints = (OGRRawPoint *)
-                OGRRealloc(paoPoints, sizeof(OGRRawPoint) * nPointCount);
+        nPointCount = static_cast<int>(aoRawPoint.size());
+        paoPoints = static_cast<OGRRawPoint *>(
+                CPLRealloc(paoPoints, sizeof(OGRRawPoint) * nPointCount));
         memcpy(paoPoints, &aoRawPoint[0], sizeof(OGRRawPoint) * nPointCount);
         if( padfZ )
         {
-            padfZ = (double*) OGRRealloc(padfZ, sizeof(double) * aoRawPoint.size());
+            padfZ = static_cast<double *>(
+                CPLRealloc(padfZ, sizeof(double) * aoRawPoint.size()));
             memcpy(padfZ, &adfZ[0], sizeof(double) * nPointCount);
         }
     }
@@ -461,41 +524,50 @@ void OGRCircularString::segmentize( double dfMaxLength )
 void OGRCircularString::Value( double dfDistance, OGRPoint * poPoint ) const
 
 {
-    double      dfLength = 0;
-    int         i;
-
     if( dfDistance < 0 )
     {
         StartPoint( poPoint );
         return;
     }
 
-    for(i=0;i<nPointCount-2;i+=2)
-    {
-        double x0 = paoPoints[i].x, y0 = paoPoints[i].y,
-               x1 = paoPoints[i+1].x, y1 = paoPoints[i+1].y,
-               x2 = paoPoints[i+2].x, y2 = paoPoints[i+2].y;
-        double R, cx, cy, alpha0, alpha1, alpha2;
+    double dfLength = 0;
 
-        /* We have strong constraints on the number of intermediate points */
-        /* we can add */
+    for( int i = 0; i < nPointCount - 2; i += 2 )
+    {
+        const double x0 = paoPoints[i].x;
+        const double y0 = paoPoints[i].y;
+        const double x1 = paoPoints[i+1].x;
+        const double y1 = paoPoints[i+1].y;
+        const double x2 = paoPoints[i+2].x;
+        const double y2 = paoPoints[i+2].y;
+        double R = 0.0;
+        double cx = 0.0;
+        double cy = 0.0;
+        double alpha0 = 0.0;
+        double alpha1 = 0.0;
+        double alpha2 = 0.0;
+
+        // We have strong constraints on the number of intermediate points
+        // we can add.
 
         if( OGRGeometryFactory::GetCurveParmeters(x0, y0, x1, y1, x2, y2,
-                                            R, cx, cy, alpha0, alpha1, alpha2) )
+                                                  R, cx, cy,
+                                                  alpha0, alpha1, alpha2) )
         {
-            /* It is an arc circle */
-            double dfSegLength = fabs(alpha2 - alpha0) * R;
-            if (dfSegLength > 0)
+            // It is an arc circle.
+            const double dfSegLength = fabs(alpha2 - alpha0) * R;
+            if( dfSegLength > 0 )
             {
                 if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                                 dfDistance) )
                 {
-                    double      dfRatio;
-
-                    dfRatio = (dfDistance - dfLength) / dfSegLength;
+                    const double dfRatio =
+                        (dfDistance - dfLength) / dfSegLength;
 
-                    double alpha = alpha0 * (1 - dfRatio) + alpha2 * dfRatio;
-                    double x = cx + R * cos(alpha), y = cy + R * sin(alpha);
+                    const double alpha =
+                        alpha0 * (1 - dfRatio) + alpha2 * dfRatio;
+                    const double x = cx + R * cos(alpha);
+                    const double y = cy + R * sin(alpha);
 
                     poPoint->setX( x );
                     poPoint->setY( y );
@@ -512,16 +584,15 @@ void OGRCircularString::Value( double dfDistance, OGRPoint * poPoint ) const
         }
         else
         {
-            /* It is a straight line */
-            double dfSegLength = sqrt((x2-x0)*(x2-x0)+(y2-y0)*(y2-y0));
-            if (dfSegLength > 0)
+            // It is a straight line.
+            const double dfSegLength = dist(x0, y0, x2, y2);
+            if( dfSegLength > 0 )
             {
                 if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                                 dfDistance) )
                 {
-                    double      dfRatio;
-
-                    dfRatio = (dfDistance - dfLength) / dfSegLength;
+                    const double dfRatio =
+                        (dfDistance - dfLength) / dfSegLength;
 
                     poPoint->setX( paoPoints[i].x * (1 - dfRatio)
                                 + paoPoints[i+2].x * dfRatio );
@@ -547,23 +618,22 @@ void OGRCircularString::Value( double dfDistance, OGRPoint * poPoint ) const
 /*                          CurveToLine()                               */
 /************************************************************************/
 
-OGRLineString* OGRCircularString::CurveToLine(double dfMaxAngleStepSizeDegrees,
-                                              const char* const* papszOptions) const
+OGRLineString* OGRCircularString::CurveToLine(
+    double dfMaxAngleStepSizeDegrees, const char* const* papszOptions ) const
 {
     OGRLineString* poLine = new OGRLineString();
     poLine->assignSpatialReference(getSpatialReference());
 
-    int bHasZ = (getCoordinateDimension() == 3);
-    int i;
-    for(i=0;i<nPointCount-2;i+=2)
+    const bool bHasZ = getCoordinateDimension() == 3;
+    for( int i = 0; i < nPointCount - 2; i += 2 )
     {
         OGRLineString* poArc = OGRGeometryFactory::curveToLineString(
-                paoPoints[i].x, paoPoints[i].y, padfZ ? padfZ[i] : 0.0,
-                paoPoints[i+1].x, paoPoints[i+1].y, padfZ ? padfZ[i+1] : 0.0,
-                paoPoints[i+2].x, paoPoints[i+2].y, padfZ ? padfZ[i+2] : 0.0,
-                bHasZ,
-                dfMaxAngleStepSizeDegrees,
-                papszOptions);
+            paoPoints[i].x, paoPoints[i].y, padfZ ? padfZ[i] : 0.0,
+            paoPoints[i+1].x, paoPoints[i+1].y, padfZ ? padfZ[i+1] : 0.0,
+            paoPoints[i+2].x, paoPoints[i+2].y, padfZ ? padfZ[i+2] : 0.0,
+            bHasZ,
+            dfMaxAngleStepSizeDegrees,
+            papszOptions);
         poLine->addSubLineString(poArc, (i == 0) ? 0 : 1);
         delete poArc;
     }
@@ -574,11 +644,11 @@ OGRLineString* OGRCircularString::CurveToLine(double dfMaxAngleStepSizeDegrees,
 /*                        IsValidFast()                                 */
 /************************************************************************/
 
-OGRBoolean OGRCircularString::IsValidFast(  ) const
+OGRBoolean OGRCircularString::IsValidFast() const
 
 {
-    if (nPointCount == 1 || nPointCount == 2 ||
-        (nPointCount >= 3 && (nPointCount % 2) == 0))
+    if( nPointCount == 1 || nPointCount == 2 ||
+        (nPointCount >= 3 && (nPointCount % 2) == 0) )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Bad number of points in circular string : %d", nPointCount);
@@ -591,7 +661,7 @@ OGRBoolean OGRCircularString::IsValidFast(  ) const
 /*                            IsValid()                                 */
 /************************************************************************/
 
-OGRBoolean OGRCircularString::IsValid(  ) const
+OGRBoolean OGRCircularString::IsValid() const
 
 {
     return IsValidFast() && OGRGeometry::IsValid();
@@ -601,7 +671,8 @@ OGRBoolean OGRCircularString::IsValid(  ) const
 /*                         hasCurveGeometry()                           */
 /************************************************************************/
 
-OGRBoolean OGRCircularString::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear) const
+OGRBoolean
+OGRCircularString::hasCurveGeometry( int /* bLookForNonLinear */ ) const
 {
     return TRUE;
 }
@@ -610,12 +681,14 @@ OGRBoolean OGRCircularString::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear)
 /*                         getLinearGeometry()                        */
 /************************************************************************/
 
-OGRGeometry* OGRCircularString::getLinearGeometry(double dfMaxAngleStepSizeDegrees,
-                                                    const char* const* papszOptions) const
+OGRGeometry*
+OGRCircularString::getLinearGeometry( double dfMaxAngleStepSizeDegrees,
+                                      const char* const* papszOptions) const
 {
     return CurveToLine(dfMaxAngleStepSizeDegrees, papszOptions);
 }
 
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                     GetCasterToLineString()                          */
 /************************************************************************/
@@ -631,29 +704,41 @@ OGRCurveCasterToLineString OGRCircularString::GetCasterToLineString() const {
 OGRCurveCasterToLinearRing OGRCircularString::GetCasterToLinearRing() const {
     return (OGRCurveCasterToLinearRing) OGRGeometry::CastToError;
 }
+//! @endcond
 
 /************************************************************************/
 /*                            IsFullCircle()                            */
 /************************************************************************/
 
-int OGRCircularString::IsFullCircle( double& cx, double& cy, double& square_R ) const
+int OGRCircularString::IsFullCircle( double& cx, double& cy,
+                                     double& square_R ) const
 {
     if( getNumPoints() == 3 && get_IsClosed() )
     {
-        double x0 = getX(0);
-        double y0 = getY(0);
-        double x1 = getX(1);
-        double y1 = getY(1);
+        const double x0 = getX(0);
+        const double y0 = getY(0);
+        const double x1 = getX(1);
+        const double y1 = getY(1);
         cx = (x0 + x1) / 2;
         cy = (y0 + y1) / 2;
-        square_R = (x1-cx)*(x1-cx)+(y1-cy)*(y1-cy);
+        square_R = (x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy);
         return TRUE;
     }
-    /* Full circle defined by 2 arcs ? */
+    // Full circle defined by 2 arcs?
     else if( getNumPoints() == 5 && get_IsClosed() )
     {
-        double R_1, cx_1, cy_1, alpha0_1, alpha1_1, alpha2_1;
-        double R_2, cx_2, cy_2, alpha0_2, alpha1_2, alpha2_2;
+        double R_1 = 0.0;
+        double cx_1 = 0.0;
+        double cy_1 = 0.0;
+        double alpha0_1 = 0.0;
+        double alpha1_1 = 0.0;
+        double alpha2_1 = 0.0;
+        double R_2 = 0.0;
+        double cx_2 = 0.0;
+        double cy_2 = 0.0;
+        double alpha0_2 = 0.0;
+        double alpha1_2 = 0.0;
+        double alpha2_2 = 0.0;
         if( OGRGeometryFactory::GetCurveParmeters(
                 getX(0), getY(0),
                 getX(1), getY(1),
@@ -682,28 +767,39 @@ int OGRCircularString::IsFullCircle( double& cx, double& cy, double& square_R )
 /*                       get_AreaOfCurveSegments()                      */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 double OGRCircularString::get_AreaOfCurveSegments() const
 {
-    double dfArea = 0;
-    for( int i=0; i < getNumPoints() - 2; i += 2 )
+    double dfArea = 0.0;
+    for( int i = 0; i < getNumPoints() - 2; i += 2 )
     {
-        double x0 = getX(i), y0 = getY(i),
-               x1 = getX(i+1), y1 = getY(i+1),
-               x2 = getX(i+2), y2 = getY(i+2);
-        double R, cx, cy, alpha0, alpha1, alpha2;
+        const double x0 = getX(i);
+        const double y0 = getY(i);
+        const double x1 = getX(i+1);
+        const double y1 = getY(i+1);
+        const double x2 = getX(i+2);
+        const double y2 = getY(i+2);
+        double R = 0.0;
+        double cx = 0.0;
+        double cy = 0.0;
+        double alpha0 = 0.0;
+        double alpha1 = 0.0;
+        double alpha2 = 0.0;
         if( OGRGeometryFactory::GetCurveParmeters(x0, y0, x1, y1, x2, y2,
-                                            R, cx, cy, alpha0, alpha1, alpha2))
+                                                  R, cx, cy,
+                                                  alpha0, alpha1, alpha2))
         {
-            double delta_alpha01 = alpha1 - alpha0; /* should be <= PI in absolute value */
-            double delta_alpha12 = alpha2 - alpha1; /* same */
-            /* This is my maths, but wikipedia confirms it... */
-            /* Cf http://en.wikipedia.org/wiki/Circular_segment */
+            // Should be <= PI in absolute value.
+            const double delta_alpha01 = alpha1 - alpha0;
+            const double delta_alpha12 = alpha2 - alpha1; // Same.
+            // http://en.wikipedia.org/wiki/Circular_segment
             dfArea += 0.5 * R * R * fabs( delta_alpha01 - sin(delta_alpha01) +
                                           delta_alpha12 - sin(delta_alpha12) );
         }
     }
     return dfArea;
 }
+//! @endcond
 
 /************************************************************************/
 /*                           get_Area()                                 */
@@ -711,49 +807,54 @@ double OGRCircularString::get_AreaOfCurveSegments() const
 
 double OGRCircularString::get_Area() const
 {
-    double cx, cy, square_R;
-
     if( IsEmpty() || !get_IsClosed() )
         return 0;
 
+    double cx = 0.0;
+    double cy = 0.0;
+    double square_R = 0.0;
+
     if( IsFullCircle(cx, cy, square_R) )
     {
         return M_PI * square_R;
     }
 
-    /* Optimization for convex rings */
+    // Optimization for convex rings.
     if( IsConvex() )
     {
-        /* Compute area of shape without the circular segments */
+        // Compute area of shape without the circular segments.
         double dfArea = get_LinearArea();
 
-        /* Add the area of the spherical segments */
+        // Add the area of the spherical segments.
         dfArea += get_AreaOfCurveSegments();
 
         return dfArea;
     }
-    else
-    {
-        OGRLineString* poLS = CurveToLine();
-        double dfArea = poLS->get_Area();
-        delete poLS;
 
-        return dfArea;
-    }
+    OGRLineString* poLS = CurveToLine();
+    const double dfArea = poLS->get_Area();
+    delete poLS;
+
+    return dfArea;
 }
 
 /************************************************************************/
 /*                           ContainsPoint()                            */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 int OGRCircularString::ContainsPoint( const OGRPoint* p ) const
 {
-    double cx, cy, square_R;
+    double cx = 0.0;
+    double cy = 0.0;
+    double square_R = 0.0;
     if( IsFullCircle(cx, cy, square_R) )
     {
-        double square_dist = (p->getX()- cx)*(p->getX()- cx)+
-                             (p->getY()- cy)*(p->getY()- cy);
+        const double square_dist =
+            (p->getX() - cx) * (p->getX() - cx) +
+            (p->getY() - cy) * (p->getY() - cy);
         return square_dist <= square_R;
     }
     return -1;
 }
+//! @endcond
diff --git a/ogr/ogrcompoundcurve.cpp b/ogr/ogrcompoundcurve.cpp
index a1eb484..9d07918 100644
--- a/ogr/ogrcompoundcurve.cpp
+++ b/ogr/ogrcompoundcurve.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcompoundcurve.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRCompoundCurve geometry class.
@@ -27,11 +26,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_geometry.h"
+
+#include <cmath>
+#include <cstddef>
+
+#include "cpl_error.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
 #include "ogr_p.h"
-#include <assert.h>
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: ogrcompoundcurve.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 /************************************************************************/
 /*                         OGRCompoundCurve()                           */
@@ -41,10 +48,7 @@ CPL_CVSID("$Id");
  * \brief Create an empty compound curve.
  */
 
-OGRCompoundCurve::OGRCompoundCurve()
-
-{
-}
+OGRCompoundCurve::OGRCompoundCurve() {}
 
 /************************************************************************/
 /*             OGRCompoundCurve( const OGRCompoundCurve& )              */
@@ -62,17 +66,13 @@ OGRCompoundCurve::OGRCompoundCurve()
 OGRCompoundCurve::OGRCompoundCurve( const OGRCompoundCurve& other ) :
     OGRCurve(other),
     oCC(other.oCC)
-{
-}
+{}
 
 /************************************************************************/
 /*                         ~OGRCompoundCurve()                          */
 /************************************************************************/
 
-OGRCompoundCurve::~OGRCompoundCurve()
-
-{
-}
+OGRCompoundCurve::~OGRCompoundCurve() {}
 
 /************************************************************************/
 /*                 operator=( const OGRCompoundCurve&)                  */
@@ -107,7 +107,7 @@ OGRwkbGeometryType OGRCompoundCurve::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbCompoundCurveZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbCompoundCurveM;
     else if( flags & OGR_G_3D )
         return wkbCompoundCurveZ;
@@ -152,16 +152,17 @@ OGRErr OGRCompoundCurve::importFromWkb( unsigned char * pabyData,
                                         int nSize,
                                         OGRwkbVariant eWkbVariant )
 {
-    OGRwkbByteOrder eByteOrder;
+    OGRwkbByteOrder eByteOrder = wkbNDR;
     int nDataOffset = 0;
-    /* coverity[tainted_data] */
+    // coverity[tainted_data]
     OGRErr eErr = oCC.importPreambuleFromWkb(this, pabyData, nSize, nDataOffset,
                                              eByteOrder, 9, eWkbVariant);
     if( eErr != OGRERR_NONE )
         return eErr;
 
     return oCC.importBodyFromWkb(this, pabyData, nSize, nDataOffset,
-                                 FALSE /* bAcceptCompoundCurve */, addCurveDirectlyFromWkb,
+                                 FALSE,  // bAcceptCompoundCurve
+                                 addCurveDirectlyFromWkb,
                                  eWkbVariant);
 }
 
@@ -170,9 +171,10 @@ OGRErr OGRCompoundCurve::importFromWkb( unsigned char * pabyData,
 /************************************************************************/
 OGRErr OGRCompoundCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
                                       unsigned char * pabyData,
-                                      OGRwkbVariant eWkbVariant  ) const
+                                      OGRwkbVariant eWkbVariant ) const
 {
-    if( eWkbVariant == wkbVariantOldOgc ) /* does not make sense for new geometries, so patch it */
+    // Does not make sense for new geometries, so patch it.
+    if( eWkbVariant == wkbVariantOldOgc )
         eWkbVariant = wkbVariantIso;
     return oCC.exportToWkb(this, eByteOrder, pabyData, eWkbVariant);
 }
@@ -181,7 +183,8 @@ OGRErr OGRCompoundCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
 /*                       addCurveDirectlyFromWkt()                      */
 /************************************************************************/
 
-OGRErr OGRCompoundCurve::addCurveDirectlyFromWkt( OGRGeometry* poSelf, OGRCurve* poCurve )
+OGRErr OGRCompoundCurve::addCurveDirectlyFromWkt( OGRGeometry* poSelf,
+                                                  OGRCurve* poCurve )
 {
     return ((OGRCompoundCurve*)poSelf)->addCurveDirectly(poCurve);
 }
@@ -193,10 +196,10 @@ OGRErr OGRCompoundCurve::addCurveDirectlyFromWkt( OGRGeometry* poSelf, OGRCurve*
 OGRErr OGRCompoundCurve::importFromWkt( char ** ppszInput )
 {
     return importCurveCollectionFromWkt( ppszInput,
-                                         FALSE, /* bAllowEmptyComponent */
-                                         TRUE, /* bAllowLineString */
-                                         TRUE, /* bAllowCurve */
-                                         FALSE, /* bAllowCompoundCurve */
+                                         FALSE, // bAllowEmptyComponent
+                                         TRUE, // bAllowLineString
+                                         TRUE, // bAllowCurve
+                                         FALSE, // bAllowCompoundCurve
                                          addCurveDirectlyFromWkt );
 }
 
@@ -204,7 +207,7 @@ OGRErr OGRCompoundCurve::importFromWkt( char ** ppszInput )
 /*                            exportToWkt()                             */
 /************************************************************************/
 OGRErr OGRCompoundCurve::exportToWkt( char ** ppszDstText,
-                                      CPL_UNUSED OGRwkbVariant eWkbVariant ) const
+                                      OGRwkbVariant /* eWkbVariant */ ) const
 
 {
     return oCC.exportToWkt(this, ppszDstText);
@@ -216,9 +219,7 @@ OGRErr OGRCompoundCurve::exportToWkt( char ** ppszDstText,
 
 OGRGeometry *OGRCompoundCurve::clone() const
 {
-    OGRCompoundCurve       *poNewCC;
-
-    poNewCC = new OGRCompoundCurve;
+    OGRCompoundCurve *poNewCC = new OGRCompoundCurve;
     poNewCC->assignSpatialReference( getSpatialReference() );
     poNewCC->flags = flags;
 
@@ -313,11 +314,11 @@ void OGRCompoundCurve::Value( double dfDistance, OGRPoint *poPoint ) const
         return;
     }
 
-    double dfLength = 0;
+    double dfLength = 0.0;
     for( int iGeom = 0; iGeom < oCC.nCurveCount; iGeom++ )
     {
-        double dfSegLength = oCC.papoCurves[iGeom]->get_Length();
-        if (dfSegLength > 0)
+        const double dfSegLength = oCC.papoCurves[iGeom]->get_Length();
+        if( dfSegLength > 0 )
         {
             if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                              dfDistance) )
@@ -338,20 +339,20 @@ void OGRCompoundCurve::Value( double dfDistance, OGRPoint *poPoint ) const
 /*                         CurveToLineInternal()                        */
 /************************************************************************/
 
-OGRLineString* OGRCompoundCurve::CurveToLineInternal(double dfMaxAngleStepSizeDegrees,
-                                                     const char* const* papszOptions,
-                                                     int bIsLinearRing) const
+OGRLineString *
+OGRCompoundCurve::CurveToLineInternal( double dfMaxAngleStepSizeDegrees,
+                                       const char* const* papszOptions,
+                                       int bIsLinearRing ) const
 {
-    OGRLineString* poLine;
-    if( bIsLinearRing )
-        poLine = new OGRLinearRing();
-    else
-        poLine = new OGRLineString();
+    OGRLineString* const poLine = bIsLinearRing
+        ? new OGRLinearRing()
+        : new OGRLineString();
     poLine->assignSpatialReference(getSpatialReference());
     for( int iGeom = 0; iGeom < oCC.nCurveCount; iGeom++ )
     {
-        OGRLineString* poSubLS = oCC.papoCurves[iGeom]->CurveToLine(dfMaxAngleStepSizeDegrees,
-                                                                    papszOptions);
+        OGRLineString* poSubLS =
+            oCC.papoCurves[iGeom]->CurveToLine(dfMaxAngleStepSizeDegrees,
+                                               papszOptions);
         poLine->addSubLineString(poSubLS, (iGeom == 0) ? 0 : 1);
         delete poSubLS;
     }
@@ -362,8 +363,9 @@ OGRLineString* OGRCompoundCurve::CurveToLineInternal(double dfMaxAngleStepSizeDe
 /*                          CurveToLine()                               */
 /************************************************************************/
 
-OGRLineString* OGRCompoundCurve::CurveToLine(double dfMaxAngleStepSizeDegrees,
-                                             const char* const* papszOptions) const
+OGRLineString *
+OGRCompoundCurve::CurveToLine( double dfMaxAngleStepSizeDegrees,
+                               const char* const* papszOptions ) const
 {
     return CurveToLineInternal(dfMaxAngleStepSizeDegrees, papszOptions, FALSE);
 }
@@ -372,7 +374,7 @@ OGRLineString* OGRCompoundCurve::CurveToLine(double dfMaxAngleStepSizeDegrees,
 /*                               Equals()                                */
 /************************************************************************/
 
-OGRBoolean  OGRCompoundCurve::Equals( OGRGeometry *poOther ) const
+OGRBoolean OGRCompoundCurve::Equals( OGRGeometry *poOther ) const
 {
     if( poOther == this )
         return TRUE;
@@ -417,7 +419,7 @@ void OGRCompoundCurve::setMeasured( OGRBoolean bIsMeasured )
  * @return number of curves.
  */
 
-int          OGRCompoundCurve::getNumCurves() const
+int OGRCompoundCurve::getNumCurves() const
 {
     return oCC.nCurveCount;
 }
@@ -429,11 +431,10 @@ int          OGRCompoundCurve::getNumCurves() const
 /**
  * \brief Fetch reference to indicated internal ring.
  *
- * Note that the returned curve pointer is to an internal data object of
- * the OGRCompoundCurve.  It should not be modified or deleted by the application,
- * and the pointer is only valid till the polygon is next modified.  Use
- * the OGRGeometry::clone() method to make a separate copy within the
- * application.
+ * Note that the returned curve pointer is to an internal data object of the
+ * OGRCompoundCurve.  It should not be modified or deleted by the application,
+ * and the pointer is only valid till the polygon is next modified.  Use the
+ * OGRGeometry::clone() method to make a separate copy within the application.
  *
  * Relates to the ISO SQL/MM ST_CurveN() function.
  *
@@ -442,7 +443,7 @@ int          OGRCompoundCurve::getNumCurves() const
  * @return pointer to curve.  May be NULL.
  */
 
-OGRCurve    *OGRCompoundCurve::getCurve( int iRing )
+OGRCurve *OGRCompoundCurve::getCurve( int iRing )
 {
     return oCC.getCurve(iRing);
 }
@@ -454,31 +455,38 @@ OGRCurve    *OGRCompoundCurve::getCurve( int iRing )
 /**
  * \brief Fetch reference to indicated internal ring.
  *
- * Note that the returned curve pointer is to an internal data object of
- * the OGRCompoundCurve.  It should not be modified or deleted by the application,
- * and the pointer is only valid till the polygon is next modified.  Use
- * the OGRGeometry::clone() method to make a separate copy within the
- * application.
+ * Note that the returned curve pointer is to an internal data object of the
+ * OGRCompoundCurve.  It should not be modified or deleted by the application,
+ * and the pointer is only valid till the polygon is next modified.  Use the
+ * OGRGeometry::clone() method to make a separate copy within the application.
  *
  * Relates to the ISO SQL/MM ST_CurveN() function.
  *
- * @param iRing curve index from 0 to getNumCurves() - 1.
+ * @param iCurve curve index from 0 to getNumCurves() - 1.
  *
  * @return pointer to curve.  May be NULL.
  */
 
-const OGRCurve *OGRCompoundCurve::getCurve( int iRing ) const
+const OGRCurve *OGRCompoundCurve::getCurve( int iCurve ) const
 {
-    return oCC.getCurve(iRing);
+    return oCC.getCurve(iCurve);
 }
 
 /************************************************************************/
 /*                           stealCurve()                               */
 /************************************************************************/
 
-OGRCurve* OGRCompoundCurve::stealCurve( int i )
+/**
+ * \brief "Steal" reference to curve.
+ *
+ * @param iCurve curve index from 0 to getNumCurves() - 1.
+ *
+ * @return pointer to curve.  May be NULL.
+ */
+
+OGRCurve* OGRCompoundCurve::stealCurve( int iCurve )
 {
-    return oCC.stealCurve(i);
+    return oCC.stealCurve(iCurve);
 }
 
 /************************************************************************/
@@ -506,7 +514,7 @@ OGRCurve* OGRCompoundCurve::stealCurve( int i )
 OGRErr OGRCompoundCurve::addCurve( OGRCurve* poCurve, double dfToleranceEps )
 {
     OGRCurve* poClonedCurve = (OGRCurve*)poCurve->clone();
-    OGRErr eErr = addCurveDirectly( poClonedCurve, dfToleranceEps );
+    const OGRErr eErr = addCurveDirectly( poClonedCurve, dfToleranceEps );
     if( eErr != OGRERR_NONE )
         delete poClonedCurve;
     return eErr;
@@ -546,11 +554,13 @@ OGRErr OGRCompoundCurve::addCurveDirectlyInternal( OGRCurve* poCurve,
 {
     if( poCurve->getNumPoints() == 1 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Invalid curve: not enough points");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Invalid curve: not enough points");
         return OGRERR_FAILURE;
     }
 
-    OGRwkbGeometryType eCurveType = wkbFlatten(poCurve->getGeometryType());
+    const OGRwkbGeometryType eCurveType =
+        wkbFlatten(poCurve->getGeometryType());
     if( EQUAL(poCurve->getGeometryName(), "LINEARRING") )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Linearring not allowed.");
@@ -558,7 +568,8 @@ OGRErr OGRCompoundCurve::addCurveDirectlyInternal( OGRCurve* poCurve,
     }
     else if( eCurveType == wkbCompoundCurve )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot add a compound curve inside a compound curve");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot add a compound curve inside a compound curve");
         return OGRERR_FAILURE;
     }
 
@@ -571,7 +582,8 @@ OGRErr OGRCompoundCurve::addCurveDirectlyInternal( OGRCurve* poCurve,
             return OGRERR_FAILURE;
         }
 
-        OGRPoint end, start;
+        OGRPoint end;
+        OGRPoint start;
         oCC.papoCurves[oCC.nCurveCount-1]->EndPoint(&end);
         poCurve->StartPoint(&start);
         if( fabs(end.getX() - start.getX()) > dfToleranceEps ||
@@ -581,7 +593,8 @@ OGRErr OGRCompoundCurve::addCurveDirectlyInternal( OGRCurve* poCurve,
             CPLError(CE_Failure, CPLE_AppDefined, "Non contiguous curves");
             return OGRERR_FAILURE;
         }
-        ((OGRSimpleCurve*)poCurve)->setPoint(0, &end); /* patch so that it matches exactly */
+        // Patch so that it matches exactly.
+        ((OGRSimpleCurve*)poCurve)->setPoint(0, &end);
     }
 
     return oCC.addCurveDirectly(this, poCurve, bNeedRealloc);
@@ -591,7 +604,7 @@ OGRErr OGRCompoundCurve::addCurveDirectlyInternal( OGRCurve* poCurve,
 /*                             transform()                              */
 /************************************************************************/
 
-OGRErr  OGRCompoundCurve::transform( OGRCoordinateTransformation *poCT )
+OGRErr OGRCompoundCurve::transform( OGRCoordinateTransformation *poCT )
 {
     return oCC.transform(this, poCT);
 }
@@ -609,7 +622,7 @@ void OGRCompoundCurve::flattenTo2D()
 /*                              segmentize()                            */
 /************************************************************************/
 
-void OGRCompoundCurve::segmentize(double dfMaxLength)
+void OGRCompoundCurve::segmentize( double dfMaxLength )
 {
     oCC.segmentize(dfMaxLength);
 }
@@ -627,22 +640,23 @@ void OGRCompoundCurve::swapXY()
 /*                         hasCurveGeometry()                           */
 /************************************************************************/
 
-OGRBoolean OGRCompoundCurve::hasCurveGeometry(int bLookForNonLinear) const
+OGRBoolean OGRCompoundCurve::hasCurveGeometry( int bLookForNonLinear ) const
 {
     if( bLookForNonLinear )
     {
         return oCC.hasCurveGeometry(bLookForNonLinear);
     }
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
 /*                         getLinearGeometry()                        */
 /************************************************************************/
 
-OGRGeometry* OGRCompoundCurve::getLinearGeometry(double dfMaxAngleStepSizeDegrees,
-                                                   const char* const* papszOptions) const
+OGRGeometry *
+OGRCompoundCurve::getLinearGeometry( double dfMaxAngleStepSizeDegrees,
+                                     const char* const* papszOptions ) const
 {
     return CurveToLine(dfMaxAngleStepSizeDegrees, papszOptions);
 }
@@ -658,7 +672,7 @@ int OGRCompoundCurve::getNumPoints() const
     {
         nPoints += oCC.papoCurves[i]->getNumPoints();
         if( i != 0 )
-            nPoints --;
+            nPoints--;
     }
     return nPoints;
 }
@@ -674,18 +688,18 @@ class OGRCompoundCurvePointIterator: public OGRPointIterator
         OGRPointIterator       *poCurveIter;
 
     public:
-        OGRCompoundCurvePointIterator(const OGRCompoundCurve* poCCIn) :
-                            poCC(poCCIn), iCurCurve(0), poCurveIter(NULL) {}
-       ~OGRCompoundCurvePointIterator() { delete poCurveIter; }
+        explicit OGRCompoundCurvePointIterator( const OGRCompoundCurve* poCCIn ) :
+            poCC(poCCIn), iCurCurve(0), poCurveIter(NULL) {}
+        virtual ~OGRCompoundCurvePointIterator() { delete poCurveIter; }
 
-        virtual OGRBoolean getNextPoint(OGRPoint* p);
+        virtual OGRBoolean getNextPoint( OGRPoint* p ) override;
 };
 
 /************************************************************************/
 /*                            getNextPoint()                            */
 /************************************************************************/
 
-OGRBoolean OGRCompoundCurvePointIterator::getNextPoint(OGRPoint* p)
+OGRBoolean OGRCompoundCurvePointIterator::getNextPoint( OGRPoint* p )
 {
     if( iCurCurve == poCC->getNumCurves() )
         return FALSE;
@@ -693,12 +707,12 @@ OGRBoolean OGRCompoundCurvePointIterator::getNextPoint(OGRPoint* p)
         poCurveIter = poCC->getCurve(0)->getPointIterator();
     if( !poCurveIter->getNextPoint(p) )
     {
-        iCurCurve ++;
+        iCurCurve++;
         if( iCurCurve == poCC->getNumCurves() )
             return FALSE;
         delete poCurveIter;
         poCurveIter = poCC->getCurve(iCurCurve)->getPointIterator();
-        /* skip first point */
+        // Skip first point.
         return poCurveIter->getNextPoint(p) &&
                poCurveIter->getNextPoint(p);
     }
@@ -718,11 +732,13 @@ OGRPointIterator* OGRCompoundCurve::getPointIterator() const
 /*                         CastToLineString()                        */
 /************************************************************************/
 
-OGRLineString* OGRCompoundCurve::CastToLineString(OGRCompoundCurve* poCC)
+//! @cond Doxygen_Suppress
+OGRLineString* OGRCompoundCurve::CastToLineString( OGRCompoundCurve* poCC )
 {
-    for(int i=0;i<poCC->oCC.nCurveCount;i++)
+    for( int i = 0; i < poCC->oCC.nCurveCount; i++ )
     {
-        poCC->oCC.papoCurves[i] = OGRCurve::CastToLineString(poCC->oCC.papoCurves[i]);
+        poCC->oCC.papoCurves[i] =
+            OGRCurve::CastToLineString(poCC->oCC.papoCurves[i]);
         if( poCC->oCC.papoCurves[i] == NULL )
         {
             delete poCC;
@@ -758,11 +774,12 @@ OGRLineString* OGRCompoundCurve::CastToLineString(OGRCompoundCurve* poCC)
  * @return new geometry.
  */
 
-OGRLinearRing* OGRCompoundCurve::CastToLinearRing(OGRCompoundCurve* poCC)
+OGRLinearRing* OGRCompoundCurve::CastToLinearRing( OGRCompoundCurve* poCC )
 {
-    for(int i=0;i<poCC->oCC.nCurveCount;i++)
+    for( int i = 0; i < poCC->oCC.nCurveCount; i++ )
     {
-        poCC->oCC.papoCurves[i] = OGRCurve::CastToLineString(poCC->oCC.papoCurves[i]);
+        poCC->oCC.papoCurves[i] =
+            OGRCurve::CastToLineString(poCC->oCC.papoCurves[i]);
         if( poCC->oCC.papoCurves[i] == NULL )
         {
             delete poCC;
@@ -772,7 +789,8 @@ OGRLinearRing* OGRCompoundCurve::CastToLinearRing(OGRCompoundCurve* poCC)
 
     if( poCC->oCC.nCurveCount == 1 )
     {
-        OGRLinearRing* poLR = OGRCurve::CastToLinearRing( poCC->oCC.papoCurves[0] );
+        OGRLinearRing* poLR =
+            OGRCurve::CastToLinearRing( poCC->oCC.papoCurves[0] );
         if( poLR != NULL )
         {
             poLR->assignSpatialReference(poCC->getSpatialReference());
@@ -782,7 +800,8 @@ OGRLinearRing* OGRCompoundCurve::CastToLinearRing(OGRCompoundCurve* poCC)
         return poLR;
     }
 
-    OGRLinearRing* poLR = (OGRLinearRing*)poCC->CurveToLineInternal(0, NULL, TRUE);
+    OGRLinearRing* poLR =
+        (OGRLinearRing *) poCC->CurveToLineInternal(0, NULL, TRUE);
     delete poCC;
     return poLR;
 }
@@ -802,6 +821,7 @@ OGRCurveCasterToLineString OGRCompoundCurve::GetCasterToLineString() const {
 OGRCurveCasterToLinearRing OGRCompoundCurve::GetCasterToLinearRing() const {
     return (OGRCurveCasterToLinearRing) OGRCompoundCurve::CastToLinearRing;
 }
+//! @endcond
 
 /************************************************************************/
 /*                           get_Area()                                 */
@@ -812,40 +832,41 @@ double OGRCompoundCurve::get_Area() const
     if( IsEmpty() || !get_IsClosed() )
         return 0;
 
-    /* Optimization for convex rings */
+    // Optimization for convex rings.
     if( IsConvex() )
     {
-        /* Compute area of shape without the circular segments */
+        // Compute area of shape without the circular segments.
         OGRPointIterator* poIter = getPointIterator();
         OGRLineString oLS;
         oLS.setNumPoints( getNumPoints() );
         OGRPoint p;
-        for(int i = 0; poIter->getNextPoint(&p); i++ )
+        for( int i = 0; poIter->getNextPoint(&p); i++ )
         {
             oLS.setPoint( i, p.getX(), p.getY() );
         }
         double dfArea = oLS.get_Area();
         delete poIter;
 
-        /* Add the area of the spherical segments */
+        // Add the area of the spherical segments.
         dfArea += get_AreaOfCurveSegments();
 
         return dfArea;
     }
-    else
-    {
-        OGRLineString* poLS = CurveToLine();
-        double dfArea = poLS->get_Area();
-        delete poLS;
 
-        return dfArea;
-    }
+    OGRLineString* poLS = CurveToLine();
+    double dfArea = poLS->get_Area();
+    delete poLS;
+
+    return dfArea;
 }
 
 /************************************************************************/
 /*                       get_AreaOfCurveSegments()                      */
 /************************************************************************/
 
+/** Return area of curve segments
+ * @return area.
+ */
 double OGRCompoundCurve::get_AreaOfCurveSegments() const
 {
     double dfArea = 0;
diff --git a/ogr/ogrct.cpp b/ogr/ogrct.cpp
index 47d93bc..d5c3287 100644
--- a/ogr/ogrct.cpp
+++ b/ogr/ogrct.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrct.cpp 37167 2017-01-17 16:38:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSCoordinateTransformation class.
@@ -28,29 +27,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_spatialref.h"
 #include "cpl_port.h"
-#include "cpl_error.h"
+#include "ogr_spatialref.h"
+
+#include <cmath>
+#include <cstring>
+
 #include "cpl_conv.h"
-#include "cpl_string.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
+#include "ogr_srs_api.h"
 
 #ifdef PROJ_STATIC
 #include "proj_api.h"
 #endif
 
-CPL_CVSID("$Id: ogrct.cpp 37167 2017-01-17 16:38:55Z rouault $");
+CPL_CVSID("$Id: ogrct.cpp 37166 2017-01-17 16:38:53Z rouault $");
 
 /* ==================================================================== */
 /*      PROJ.4 interface stuff.                                         */
 /* ==================================================================== */
 #ifndef PROJ_STATIC
-typedef struct { double u, v; } projUV;
-
 #define projPJ void *
 #define projCtx void *
-#define RAD_TO_DEG      57.29577951308232
-#define DEG_TO_RAD      .0174532925199432958
+static const double RAD_TO_DEG = 57.29577951308232;
+static const double DEG_TO_RAD = 0.0174532925199432958;
 
 #else
 
@@ -62,30 +65,30 @@ typedef struct { double u, v; } projUV;
 
 static CPLMutex *hPROJMutex = NULL;
 
-static projPJ       (*pfn_pj_init_plus)(const char *) = NULL;
-static projPJ       (*pfn_pj_init)(int, char**) = NULL;
-static void     (*pfn_pj_free)(projPJ) = NULL;
-static int      (*pfn_pj_transform)(projPJ, projPJ, long, int,
-                                    double *, double *, double * ) = NULL;
-static int         *(*pfn_pj_get_errno_ref)(void) = NULL;
-static char        *(*pfn_pj_strerrno)(int) = NULL;
-static char        *(*pfn_pj_get_def)(projPJ,int) = NULL;
-static void         (*pfn_pj_dalloc)(void *) = NULL;
+static projPJ   (*pfn_pj_init_plus)( const char * ) = NULL;
+static projPJ   (*pfn_pj_init)( int, char** ) = NULL;
+static void     (*pfn_pj_free)( projPJ ) = NULL;
+static int      (*pfn_pj_transform)( projPJ, projPJ, long, int,
+                                     double *, double *, double * ) = NULL;
+static int      *(*pfn_pj_get_errno_ref)( void ) = NULL;
+static char     *(*pfn_pj_strerrno)( int ) = NULL;
+static char     *(*pfn_pj_get_def)( projPJ, int ) = NULL;
+static void     (*pfn_pj_dalloc)( void * ) = NULL;
 
 static projPJ (*pfn_pj_init_plus_ctx)( projCtx, const char * ) = NULL;
 static int (*pfn_pj_ctx_get_errno)( projCtx ) = NULL;
-static projCtx (*pfn_pj_ctx_alloc)(void) = NULL;
+static projCtx (*pfn_pj_ctx_alloc)() = NULL;
 static void    (*pfn_pj_ctx_free)( projCtx ) = NULL;
 
-// Locale-safe proj starts with 4.10
+// Locale-safe proj starts with 4.10.
 #if defined(PJ_LOCALE_SAFE)
-static bool      bProjLocaleSafe = PJ_LOCALE_SAFE;
+static bool      bProjLocaleSafe = PJ_LOCALE_SAFE != 0;
 #else
 static bool      bProjLocaleSafe = false;
 #endif
 
 #if defined(WIN32) && !defined(__MINGW32__)
-#  define LIBNAME      "proj.dll"
+#  define LIBNAME "proj.dll"
 #elif defined(__MINGW32__)
 // XXX: If PROJ.4 library was properly built using libtool in Cygwin or MinGW
 // environments it has the interface version number embedded in the file name
@@ -93,13 +96,13 @@ static bool      bProjLocaleSafe = false;
 // build) it can be named either way, so use PROJSO environment variable to
 // specify the right library name. By default assume that in Cygwin/MinGW all
 // components were built in the same way.
-#  define LIBNAME      "libproj-0.dll"
+#  define LIBNAME "libproj-9.dll"
 #elif defined(__CYGWIN__)
-#  define LIBNAME      "cygproj-0.dll"
+#  define LIBNAME "cygproj-9.dll"
 #elif defined(__APPLE__)
-#  define LIBNAME      "libproj.dylib"
+#  define LIBNAME "libproj.dylib"
 #else
-#  define LIBNAME      "libproj.so"
+#  define LIBNAME "libproj.so"
 #endif
 
 /************************************************************************/
@@ -123,25 +126,24 @@ class OGRProj4CT : public OGRCoordinateTransformation
 {
     OGRSpatialReference *poSRSSource;
     void        *psPJSource;
-    int         bSourceLatLong;
+    bool        bSourceLatLong;
     double      dfSourceToRadians;
-    int         bSourceWrap;
+    bool        bSourceWrap;
     double      dfSourceWrapLong;
 
     OGRSpatialReference *poSRSTarget;
     void        *psPJTarget;
-    int         bTargetLatLong;
+    bool        bTargetLatLong;
     double      dfTargetFromRadians;
-    int         bTargetWrap;
+    bool        bTargetWrap;
     double      dfTargetWrapLong;
 
-    int         bIdentityTransform;
-    //int         bWGS84ToWebMercator;
-    int         bWebMercatorToWGS84;
+    bool        bIdentityTransform;
+    bool        bWebMercatorToWGS84;
 
     int         nErrorCount;
 
-    int         bCheckWithInvertProj;
+    bool        bCheckWithInvertProj;
     double      dfThreshold;
 
     projCtx     pjctx;
@@ -157,6 +159,8 @@ class OGRProj4CT : public OGRCoordinateTransformation
     double     *padfTargetY;
     double     *padfTargetZ;
 
+    bool        m_bEmitErrors;
+
     bool        bNoTransform;
 
 public:
@@ -166,13 +170,18 @@ public:
     int         Initialize( OGRSpatialReference *poSource,
                             OGRSpatialReference *poTarget );
 
-    virtual OGRSpatialReference *GetSourceCS();
-    virtual OGRSpatialReference *GetTargetCS();
+    virtual OGRSpatialReference *GetSourceCS() override;
+    virtual OGRSpatialReference *GetTargetCS() override;
     virtual int Transform( int nCount,
-                           double *x, double *y, double *z = NULL );
+                           double *x, double *y, double *z = NULL ) override;
     virtual int TransformEx( int nCount,
                              double *x, double *y, double *z = NULL,
-                             int *panSuccess = NULL );
+                             int *panSuccess = NULL ) override;
+
+    // TODO(schwehr): Make GetEmitErrors const.
+    virtual bool GetEmitErrors() override { return m_bEmitErrors; }
+    virtual void SetEmitErrors( bool bEmitErrors ) override
+        { m_bEmitErrors = bEmitErrors; }
 };
 
 /************************************************************************/
@@ -182,8 +191,8 @@ public:
 static const char* GetProjLibraryName()
 {
     const char *pszLibName = LIBNAME;
-    if( CPLGetConfigOption("PROJSO",NULL) != NULL )
-        pszLibName = CPLGetConfigOption("PROJSO",NULL);
+    if( CPLGetConfigOption("PROJSO", NULL) != NULL )
+        pszLibName = CPLGetConfigOption("PROJSO", NULL);
     return pszLibName;
 }
 
@@ -195,14 +204,13 @@ static bool LoadProjLibrary_unlocked()
 
 {
     static bool bTriedToLoad = false;
-    const char *pszLibName;
 
     if( bTriedToLoad )
-        return( pfn_pj_transform != NULL );
+        return pfn_pj_transform != NULL;
 
     bTriedToLoad = true;
 
-    pszLibName = GetProjLibraryName();
+    const char *pszLibName = GetProjLibraryName();
 
 #ifdef PROJ_STATIC
     pfn_pj_init = pj_init;
@@ -224,9 +232,9 @@ static bool LoadProjLibrary_unlocked()
 #else
     CPLPushErrorHandler( CPLQuietErrorHandler );
 
-    /* coverity[tainted_string] */
+    // coverity[tainted_string]
     pfn_pj_init = (projPJ (*)(int, char**)) CPLGetSymbol( pszLibName,
-                                                       "pj_init" );
+                                                          "pj_init" );
     CPLPopErrorHandler();
 
     if( pfn_pj_init == NULL )
@@ -236,21 +244,21 @@ static bool LoadProjLibrary_unlocked()
         CPLGetSymbol( pszLibName, "pj_init_plus" );
     pfn_pj_free = (void (*)(projPJ))
         CPLGetSymbol( pszLibName, "pj_free" );
-    pfn_pj_transform = (int (*)(projPJ,projPJ,long,int,double*,
-                                double*,double*))
-                        CPLGetSymbol( pszLibName, "pj_transform" );
+    pfn_pj_transform = (int (*)(projPJ, projPJ, long, int, double *,
+                                double *, double *))
+        CPLGetSymbol( pszLibName, "pj_transform" );
     pfn_pj_get_errno_ref = (int *(*)(void))
         CPLGetSymbol( pszLibName, "pj_get_errno_ref" );
     pfn_pj_strerrno = (char *(*)(int))
         CPLGetSymbol( pszLibName, "pj_strerrno" );
 
     CPLPushErrorHandler( CPLQuietErrorHandler );
-    pfn_pj_get_def = (char *(*)(projPJ,int))
+    pfn_pj_get_def = (char *(*)(projPJ, int))
         CPLGetSymbol( pszLibName, "pj_get_def" );
     pfn_pj_dalloc = (void (*)(void*))
         CPLGetSymbol( pszLibName, "pj_dalloc" );
 
-    /* PROJ 4.8.0 symbols */
+    // PROJ 4.8.0 symbols.
     pfn_pj_ctx_alloc = (projCtx (*)( void ))
         CPLGetSymbol( pszLibName, "pj_ctx_alloc" );
     pfn_pj_ctx_free = (void (*)( projCtx ))
@@ -266,11 +274,11 @@ static bool LoadProjLibrary_unlocked()
     CPLErrorReset();
 #endif
 
-    if (pfn_pj_ctx_alloc != NULL &&
+    if( pfn_pj_ctx_alloc != NULL &&
         pfn_pj_ctx_free != NULL &&
         pfn_pj_init_plus_ctx != NULL &&
         pfn_pj_ctx_get_errno != NULL &&
-        CSLTestBoolean(CPLGetConfigOption("USE_PROJ_480_FEATURES", "YES")))
+        CPLTestBool(CPLGetConfigOption("USE_PROJ_480_FEATURES", "YES")) )
     {
         CPLDebug("OGRCT", "PROJ >= 4.8.0 features enabled");
     }
@@ -288,7 +296,7 @@ static bool LoadProjLibrary_unlocked()
     if( pfn_pj_transform == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to load %s, but couldn't find pj_transform.\n"
+                  "Attempt to load %s, but couldn't find pj_transform.  "
                   "Please upgrade to PROJ 4.1.2 or later.",
                   pszLibName );
 
@@ -307,31 +315,28 @@ static bool LoadProjLibrary()
 
 /************************************************************************/
 /*                         OCTProj4Normalize()                          */
-/*                                                                      */
-/*      This function is really just here since we already have all     */
-/*      the code to load libproj.so.  It is intended to "normalize"     */
-/*      a proj.4 definition, expanding +init= definitions and so        */
-/*      forth as possible.                                              */
 /************************************************************************/
 
+/** This function is really just here since we already have all
+ * the code to load libproj.so.  It is intended to "normalize"
+ * a proj.4 definition, expanding +init= definitions and so
+ * forth as possible.
+ */
 static char *OCTProj4NormalizeInternal( const char *pszProj4Src )
 {
-    char        *pszNewProj4Def, *pszCopy;
-    projPJ      psPJSource = NULL;
-
-    psPJSource = pfn_pj_init_plus( pszProj4Src );
+    projPJ psPJSource = pfn_pj_init_plus( pszProj4Src );
 
     if( psPJSource == NULL )
         return CPLStrdup( pszProj4Src );
 
-    pszNewProj4Def = pfn_pj_get_def( psPJSource, 0 );
+    char *pszNewProj4Def = pfn_pj_get_def( psPJSource, 0 );
 
     pfn_pj_free( psPJSource );
 
     if( pszNewProj4Def == NULL )
         return CPLStrdup( pszProj4Src );
 
-    pszCopy = CPLStrdup( pszNewProj4Def );
+    char *pszCopy = CPLStrdup( pszNewProj4Def );
     pfn_pj_dalloc( pszNewProj4Def );
 
     return pszCopy;
@@ -342,17 +347,19 @@ char *OCTProj4Normalize( const char *pszProj4Src )
 {
     CPLMutexHolderD( &hPROJMutex );
 
-    if( !LoadProjLibrary_unlocked() || pfn_pj_dalloc == NULL || pfn_pj_get_def == NULL )
+    if( !LoadProjLibrary_unlocked() || pfn_pj_dalloc == NULL ||
+        pfn_pj_get_def == NULL )
         return CPLStrdup( pszProj4Src );
 
     if( bProjLocaleSafe )
+    {
         return OCTProj4NormalizeInternal(pszProj4Src);
+    }
     else
     {
-        CPLLocaleC  oLocaleEnforcer;
+        CPLLocaleC oLocaleEnforcer;
         return OCTProj4NormalizeInternal(pszProj4Src);
     }
-
 }
 
 /************************************************************************/
@@ -381,7 +388,8 @@ OCTDestroyCoordinateTransformation( OGRCoordinateTransformationH hCT )
 /**
  * \brief OGRCoordinateTransformation destructor.
  *
- * This function is the same as OGRCoordinateTransformation::~OGRCoordinateTransformation()
+ * This function is the same as
+ * OGRCoordinateTransformation::~OGRCoordinateTransformation()
  * and OCTDestroyCoordinateTransformation()
  *
  * This static method will destroy a OGRCoordinateTransformation.  It is
@@ -394,7 +402,7 @@ OCTDestroyCoordinateTransformation( OGRCoordinateTransformationH hCT )
  * @since GDAL 1.7.0
  */
 
-void OGRCoordinateTransformation::DestroyCT(OGRCoordinateTransformation* poCT)
+void OGRCoordinateTransformation::DestroyCT( OGRCoordinateTransformation* poCT )
 {
     delete poCT;
 }
@@ -426,28 +434,24 @@ OGRCreateCoordinateTransformation( OGRSpatialReference *poSource,
                                    OGRSpatialReference *poTarget )
 
 {
-    OGRProj4CT  *poCT;
-
     if( pfn_pj_init == NULL && !LoadProjLibrary() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Unable to load PROJ.4 library (%s), creation of\n"
+                  "Unable to load PROJ.4 library (%s), creation of "
                   "OGRCoordinateTransformation failed.",
                   GetProjLibraryName() );
         return NULL;
     }
 
-    poCT = new OGRProj4CT();
+    OGRProj4CT *poCT = new OGRProj4CT();
 
     if( !poCT->Initialize( poSource, poTarget ) )
     {
         delete poCT;
         return NULL;
     }
-    else
-    {
-        return poCT;
-    }
+
+    return poCT;
 }
 
 /************************************************************************/
@@ -477,10 +481,10 @@ OCTNewCoordinateTransformation(
     OGRSpatialReferenceH hSourceSRS, OGRSpatialReferenceH hTargetSRS )
 
 {
-    return (OGRCoordinateTransformationH)
+    return reinterpret_cast<OGRCoordinateTransformationH>(
         OGRCreateCoordinateTransformation(
-            (OGRSpatialReference *) hSourceSRS,
-            (OGRSpatialReference *) hTargetSRS );
+            reinterpret_cast<OGRSpatialReference *>(hSourceSRS),
+            reinterpret_cast<OGRSpatialReference *>(hTargetSRS)));
 }
 
 /************************************************************************/
@@ -488,16 +492,35 @@ OCTNewCoordinateTransformation(
 /************************************************************************/
 
 OGRProj4CT::OGRProj4CT() :
-    poSRSSource(NULL), psPJSource(NULL), bSourceLatLong(FALSE),
-    dfSourceToRadians(0.0), bSourceWrap(FALSE), dfSourceWrapLong(0.0),
-    poSRSTarget(NULL), psPJTarget(NULL), bTargetLatLong(FALSE),
-    dfTargetFromRadians(0.0), bTargetWrap(FALSE), dfTargetWrapLong(0.0),
-    bIdentityTransform(FALSE), bWebMercatorToWGS84(FALSE), nErrorCount(0),
-    bCheckWithInvertProj(FALSE), dfThreshold(0.0), pjctx(NULL), nMaxCount(0),
-    padfOriX(NULL), padfOriY(NULL), padfOriZ(NULL), padfTargetX(NULL),
-    padfTargetY(NULL), padfTargetZ(NULL)
+    poSRSSource(NULL),
+    psPJSource(NULL),
+    bSourceLatLong(false),
+    dfSourceToRadians(0.0),
+    bSourceWrap(false),
+    dfSourceWrapLong(0.0),
+    poSRSTarget(NULL),
+    psPJTarget(NULL),
+    bTargetLatLong(false),
+    dfTargetFromRadians(0.0),
+    bTargetWrap(false),
+    dfTargetWrapLong(0.0),
+    bIdentityTransform(false),
+    bWebMercatorToWGS84(false),
+    nErrorCount(0),
+    bCheckWithInvertProj(false),
+    dfThreshold(0.0),
+    pjctx(NULL),
+    nMaxCount(0),
+    padfOriX(NULL),
+    padfOriY(NULL),
+    padfOriZ(NULL),
+    padfTargetX(NULL),
+    padfTargetY(NULL),
+    padfTargetZ(NULL),
+    m_bEmitErrors(true),
+    bNoTransform(false)
 {
-    if (pfn_pj_ctx_alloc != NULL)
+    if( pfn_pj_ctx_alloc != NULL )
         pjctx = pfn_pj_ctx_alloc();
 }
 
@@ -520,7 +543,7 @@ OGRProj4CT::~OGRProj4CT()
             delete poSRSTarget;
     }
 
-    if (pjctx != NULL)
+    if( pjctx != NULL )
     {
         pfn_pj_ctx_free(pjctx);
 
@@ -562,8 +585,8 @@ int OGRProj4CT::Initialize( OGRSpatialReference * poSourceIn,
         return InitializeNoLock(poSourceIn, poTargetIn);
     }
 
-    CPLLocaleC  oLocaleEnforcer;
-    if (pjctx != NULL)
+    CPLLocaleC oLocaleEnforcer;
+    if( pjctx != NULL )
     {
         return InitializeNoLock(poSourceIn, poTargetIn);
     }
@@ -586,15 +609,15 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     poSRSSource = poSourceIn->Clone();
     poSRSTarget = poTargetIn->Clone();
 
-    bSourceLatLong = poSRSSource->IsGeographic();
-    bTargetLatLong = poSRSTarget->IsGeographic();
+    bSourceLatLong = CPL_TO_BOOL(poSRSSource->IsGeographic());
+    bTargetLatLong = CPL_TO_BOOL(poSRSTarget->IsGeographic());
 
 /* -------------------------------------------------------------------- */
 /*      Setup source and target translations to radians for lat/long    */
 /*      systems.                                                        */
 /* -------------------------------------------------------------------- */
     dfSourceToRadians = DEG_TO_RAD;
-    bSourceWrap = FALSE;
+    bSourceWrap = false;
     dfSourceWrapLong = 0.0;
 
     if( bSourceLatLong )
@@ -609,7 +632,7 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     }
 
     dfTargetFromRadians = RAD_TO_DEG;
-    bTargetWrap = FALSE;
+    bTargetWrap = false;
     dfTargetWrapLong = 0.0;
 
     if( bTargetLatLong )
@@ -617,7 +640,8 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
         OGR_SRSNode *poUNITS = poSRSTarget->GetAttrNode( "GEOGCS|UNIT" );
         if( poUNITS && poUNITS->GetChildCount() >= 2 )
         {
-            double dfTargetToRadians = CPLAtof(poUNITS->GetChild(1)->GetValue());
+            const double dfTargetToRadians =
+                CPLAtof(poUNITS->GetChild(1)->GetValue());
             if( dfTargetToRadians != 0.0 )
                 dfTargetFromRadians = 1 / dfTargetToRadians;
         }
@@ -626,21 +650,21 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
 /* -------------------------------------------------------------------- */
 /*      Preliminary logic to setup wrapping.                            */
 /* -------------------------------------------------------------------- */
-    const char *pszCENTER_LONG;
-
     if( CPLGetConfigOption( "CENTER_LONG", NULL ) != NULL )
     {
-        bSourceWrap = bTargetWrap = TRUE;
+        bSourceWrap = true;
+        bTargetWrap = true;
         dfSourceWrapLong = dfTargetWrapLong =
             CPLAtof(CPLGetConfigOption( "CENTER_LONG", "" ));
         CPLDebug( "OGRCT", "Wrap at %g.", dfSourceWrapLong );
     }
 
-    pszCENTER_LONG = poSRSSource->GetExtension( "GEOGCS", "CENTER_LONG" );
+    const char *pszCENTER_LONG =
+        poSRSSource->GetExtension( "GEOGCS", "CENTER_LONG" );
     if( pszCENTER_LONG != NULL )
     {
         dfSourceWrapLong = CPLAtof(pszCENTER_LONG);
-        bSourceWrap = TRUE;
+        bSourceWrap = true;
         CPLDebug( "OGRCT", "Wrap source at %g.", dfSourceWrapLong );
     }
 
@@ -648,26 +672,27 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     if( pszCENTER_LONG != NULL )
     {
         dfTargetWrapLong = CPLAtof(pszCENTER_LONG);
-        bTargetWrap = TRUE;
+        bTargetWrap = true;
         CPLDebug( "OGRCT", "Wrap target at %g.", dfTargetWrapLong );
     }
 
-    bCheckWithInvertProj = CSLTestBoolean(CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", "NO" ));
+    bCheckWithInvertProj =
+        CPLTestBool(CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", "NO" ));
 
-    /* The threshold is rather experimental... Works well with the cases of ticket #2305 */
-    if (bSourceLatLong)
+    // The threshold is experimental. Works well with the cases of ticket #2305.
+    if( bSourceLatLong )
         dfThreshold = CPLAtof(CPLGetConfigOption( "THRESHOLD", ".1" ));
     else
-        /* 1 works well for most projections, except for +proj=aeqd that requires */
-        /* a tolerance of 10000 */
+        // 1 works well for most projections, except for +proj=aeqd that
+        // requires a tolerance of 10000.
         dfThreshold = CPLAtof(CPLGetConfigOption( "THRESHOLD", "10000" ));
 
     // OGRThreadSafety: The following variable is not a thread safety issue
     // since the only issue is incrementing while accessing which at worse
     // means debug output could be one "increment" late.
-    static int   nDebugReportCount = 0;
+    static int nDebugReportCount = 0;
 
-    char        *pszSrcProj4Defn = NULL;
+    char *pszSrcProj4Defn = NULL;
 
     if( poSRSSource->exportToProj4( &pszSrcProj4Defn ) != OGRERR_NONE )
     {
@@ -679,12 +704,12 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     {
         CPLFree( pszSrcProj4Defn );
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "No PROJ.4 translation for source SRS, coordinate\n"
+                  "No PROJ.4 translation for source SRS, coordinate "
                   "transformation initialization has failed." );
         return FALSE;
     }
 
-    char        *pszDstProj4Defn = NULL;
+    char *pszDstProj4Defn = NULL;
 
     if( poSRSTarget->exportToProj4( &pszDstProj4Defn ) != OGRERR_NONE )
     {
@@ -698,7 +723,7 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
         CPLFree( pszSrcProj4Defn );
         CPLFree( pszDstProj4Defn );
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "No PROJ.4 translation for destination SRS, coordinate\n"
+                  "No PROJ.4 translation for destination SRS, coordinate "
                   "transformation initialization has failed." );
         return FALSE;
     }
@@ -719,22 +744,24 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
         memmove(pszNeedle, pszNeedle + 1, strlen(pszNeedle + 1)+1);
 
     if( (strstr(pszSrcProj4Defn, "+datum=WGS84") != NULL ||
-         strstr(pszSrcProj4Defn, "+ellps=WGS84 +towgs84=0,0,0,0,0,0,0 ") != NULL) &&
+         strstr(pszSrcProj4Defn,
+                "+ellps=WGS84 +towgs84=0,0,0,0,0,0,0 ") != NULL) &&
         strstr(pszDstProj4Defn, "+nadgrids=@null ") != NULL &&
         strstr(pszDstProj4Defn, "+towgs84") == NULL )
     {
         char* pszDst = strstr(pszSrcProj4Defn, "+towgs84=0,0,0,0,0,0,0 ");
-        char* pszSrc;
         if( pszDst != NULL )
         {
-            pszSrc = pszDst + strlen("+towgs84=0,0,0,0,0,0,0 ");
+            char *pszSrc = pszDst + strlen("+towgs84=0,0,0,0,0,0,0 ");
             memmove(pszDst, pszSrc, strlen(pszSrc)+1);
         }
         else
+        {
             memcpy(strstr(pszSrcProj4Defn, "+datum=WGS84"), "+ellps", 6);
+        }
 
         pszDst = strstr(pszDstProj4Defn, "+nadgrids=@null ");
-        pszSrc = pszDst + strlen("+nadgrids=@null ");
+        char *pszSrc = pszDst + strlen("+nadgrids=@null ");
         memmove(pszDst, pszSrc, strlen(pszSrc)+1);
 
         pszDst = strstr(pszDstProj4Defn, "+wktext ");
@@ -743,29 +770,27 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
             pszSrc = pszDst + strlen("+wktext ");
             memmove(pszDst, pszSrc, strlen(pszSrc)+1);
         }
-
-        //bWGS84ToWebMercator =
-        //    strcmp(pszSrcProj4Defn, "+proj=longlat +ellps=WGS84 +no_defs") == 0 &&
-        //    strcmp(pszDstProj4Defn, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +no_defs") == 0;
     }
     else
     if( (strstr(pszDstProj4Defn, "+datum=WGS84") != NULL ||
-         strstr(pszDstProj4Defn, "+ellps=WGS84 +towgs84=0,0,0,0,0,0,0 ") != NULL) &&
+         strstr(pszDstProj4Defn,
+                "+ellps=WGS84 +towgs84=0,0,0,0,0,0,0 ") != NULL) &&
         strstr(pszSrcProj4Defn, "+nadgrids=@null ") != NULL &&
         strstr(pszSrcProj4Defn, "+towgs84") == NULL )
     {
         char* pszDst = strstr(pszDstProj4Defn, "+towgs84=0,0,0,0,0,0,0 ");
-        char* pszSrc;
         if( pszDst != NULL)
         {
-            pszSrc = pszDst + strlen("+towgs84=0,0,0,0,0,0,0 ");
+            char* pszSrc = pszDst + strlen("+towgs84=0,0,0,0,0,0,0 ");
             memmove(pszDst, pszSrc, strlen(pszSrc)+1);
         }
         else
+        {
             memcpy(strstr(pszDstProj4Defn, "+datum=WGS84"), "+ellps", 6);
+        }
 
         pszDst = strstr(pszSrcProj4Defn, "+nadgrids=@null ");
-        pszSrc = pszDst + strlen("+nadgrids=@null ");
+        char* pszSrc = pszDst + strlen("+nadgrids=@null ");
         memmove(pszDst, pszSrc, strlen(pszSrc)+1);
 
         pszDst = strstr(pszSrcProj4Defn, "+wktext ");
@@ -775,8 +800,11 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
             memmove(pszDst, pszSrc, strlen(pszSrc)+1);
         }
         bWebMercatorToWGS84 =
-            strcmp(pszDstProj4Defn, "+proj=longlat +ellps=WGS84 +no_defs") == 0 &&
-            strcmp(pszSrcProj4Defn, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +no_defs") == 0;
+            strcmp(pszDstProj4Defn,
+                   "+proj=longlat +ellps=WGS84 +no_defs") == 0 &&
+            strcmp(pszSrcProj4Defn,
+                   "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 "
+                   "+x_0=0.0 +y_0=0 +k=1.0 +units=m +no_defs") == 0;
     }
 
 /* -------------------------------------------------------------------- */
@@ -784,7 +812,7 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
 /* -------------------------------------------------------------------- */
     if( !bWebMercatorToWGS84 )
     {
-        if (pjctx)
+        if( pjctx )
             psPJSource = pfn_pj_init_plus_ctx( pjctx, pszSrcProj4Defn );
         else
             psPJSource = pfn_pj_init_plus( pszSrcProj4Defn );
@@ -793,28 +821,28 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
         {
             if( pjctx != NULL)
             {
-                int pj_errno = pfn_pj_ctx_get_errno(pjctx);
+                const int l_pj_errno = pfn_pj_ctx_get_errno(pjctx);
 
-                /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
+                // pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0.
                 CPLMutexHolderD(&hPROJMutex);
                 CPLError( CE_Failure, CPLE_NotSupported,
-                        "Failed to initialize PROJ.4 with `%s'.\n%s",
-                        pszSrcProj4Defn, pfn_pj_strerrno(pj_errno) );
+                          "Failed to initialize PROJ.4 with `%s'.\n%s",
+                          pszSrcProj4Defn, pfn_pj_strerrno(l_pj_errno) );
             }
             else if( pfn_pj_get_errno_ref != NULL
                 && pfn_pj_strerrno != NULL )
             {
-                int *p_pj_errno = pfn_pj_get_errno_ref();
+                const int *p_pj_errno = pfn_pj_get_errno_ref();
 
                 CPLError( CE_Failure, CPLE_NotSupported,
-                        "Failed to initialize PROJ.4 with `%s'.\n%s",
-                        pszSrcProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
+                          "Failed to initialize PROJ.4 with `%s'.\n%s",
+                          pszSrcProj4Defn, pfn_pj_strerrno(*p_pj_errno) );
             }
             else
             {
                 CPLError( CE_Failure, CPLE_NotSupported,
-                        "Failed to initialize PROJ.4 with `%s'.\n",
-                        pszSrcProj4Defn );
+                          "Failed to initialize PROJ.4 with `%s'.",
+                          pszSrcProj4Defn );
             }
         }
     }
@@ -834,15 +862,15 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
 /* -------------------------------------------------------------------- */
     if( !bWebMercatorToWGS84 )
     {
-        if (pjctx)
+        if( pjctx )
             psPJTarget = pfn_pj_init_plus_ctx( pjctx, pszDstProj4Defn );
         else
             psPJTarget = pfn_pj_init_plus( pszDstProj4Defn );
 
         if( psPJTarget == NULL )
             CPLError( CE_Failure, CPLE_NotSupported,
-                    "Failed to initialize PROJ.4 with `%s'.",
-                    pszDstProj4Defn );
+                      "Failed to initialize PROJ.4 with `%s'.",
+                      pszDstProj4Defn );
     }
     if( nDebugReportCount < 10 )
     {
@@ -861,12 +889,12 @@ int OGRProj4CT::InitializeNoLock( OGRSpatialReference * poSourceIn,
     // (but we may have a unit transformation to do)
     bIdentityTransform = strcmp(pszSrcProj4Defn, pszDstProj4Defn) == 0;
 
-    // Determine if we can skip the tranformation completely.
+    // Determine if we can skip the transformation completely.
     // Assume that source and target units are defined with at least
     // 10 correct significant digits; hence the 1E-9 tolerance used.
     bNoTransform = bIdentityTransform && bSourceLatLong && !bSourceWrap &&
-                   bTargetLatLong && !bTargetWrap &&
-                   fabs(dfSourceToRadians * dfTargetFromRadians - 1.0) < 1E-9;
+                    bTargetLatLong && !bTargetWrap &&
+                    fabs(dfSourceToRadians * dfTargetFromRadians - 1.0) < 1E-9;
 
     CPLFree( pszSrcProj4Defn );
     CPLFree( pszDstProj4Defn );
@@ -903,16 +931,16 @@ OGRSpatialReference *OGRProj4CT::GetTargetCS()
 int OGRProj4CT::Transform( int nCount, double *x, double *y, double *z )
 
 {
-    int *pabSuccess = (int *) CPLMalloc(sizeof(int) * nCount );
-    int bOverallSuccess, i;
+    int *pabSuccess = static_cast<int *>(CPLMalloc(sizeof(int) * nCount));
 
-    bOverallSuccess = TransformEx( nCount, x, y, z, pabSuccess );
+    bool bOverallSuccess =
+        CPL_TO_BOOL(TransformEx( nCount, x, y, z, pabSuccess ));
 
-    for( i = 0; i < nCount; i++ )
+    for( int i = 0; i < nCount; i++ )
     {
         if( !pabSuccess[i] )
         {
-            bOverallSuccess = FALSE;
+            bOverallSuccess = false;
             break;
         }
     }
@@ -926,6 +954,15 @@ int OGRProj4CT::Transform( int nCount, double *x, double *y, double *z )
 /*                            OCTTransform()                            */
 /************************************************************************/
 
+/** Transform an array of points
+ *
+ * @param hTransform Transformation object
+ * @param nCount Number of points
+ * @param x Array of nCount x values.
+ * @param y Array of nCount y values.
+ * @param z Array of nCount z values.
+ * @return TRUE or FALSE
+ */
 int CPL_STDCALL OCTTransform( OGRCoordinateTransformationH hTransform,
                               int nCount, double *x, double *y, double *z )
 
@@ -933,13 +970,22 @@ int CPL_STDCALL OCTTransform( OGRCoordinateTransformationH hTransform,
     VALIDATE_POINTER1( hTransform, "OCTTransform", FALSE );
 
     return ((OGRCoordinateTransformation*) hTransform)->
-        Transform( nCount, x, y,z );
+        Transform( nCount, x, y, z );
 }
 
 /************************************************************************/
 /*                            TransformEx()                             */
 /************************************************************************/
 
+/** Transform an array of points
+ *
+ * @param nCount Number of points
+ * @param x Array of nCount x values.
+ * @param y Array of nCount y values.
+ * @param z Array of nCount z values.
+ * @param pabSuccess Output array of nCount value that will be set to TRUE/FALSE
+ * @return TRUE or FALSE
+ */
 int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
                              int *pabSuccess )
 
@@ -957,8 +1003,17 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
         return TRUE;
     }
 
-
-    int   err, i;
+    // Workaround potential bugs in proj.4 such as
+    // the one of https://github.com/OSGeo/proj.4/commit/
+    //                              bc7453d1a75aab05bdff2c51ed78c908e3efa3cd
+    for( int i = 0; i < nCount; i++ )
+    {
+        if( CPLIsNan(x[i]) || CPLIsNan(y[i]) )
+        {
+            x[i] = HUGE_VAL;
+            y[i] = HUGE_VAL;
+        }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Potentially transform to radians.                               */
@@ -967,7 +1022,7 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
     {
         if( bSourceWrap )
         {
-            for( i = 0; i < nCount; i++ )
+            for( int i = 0; i < nCount; i++ )
             {
                 if( x[i] != HUGE_VAL && y[i] != HUGE_VAL )
                 {
@@ -979,7 +1034,7 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
             }
         }
 
-        for( i = 0; i < nCount; i++ )
+        for( int i = 0; i < nCount; i++ )
         {
             if( x[i] != HUGE_VAL )
             {
@@ -995,10 +1050,10 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
     bool bTransformDone = false;
     if( bWebMercatorToWGS84 )
     {
-#define REVERSE_SPHERE_RADIUS  (1. / 6378137.)
+        static const double REVERSE_SPHERE_RADIUS = 1.0 / 6378137.0;
 
         double y0 = y[0];
-        for( i = 0; i < nCount; i++ )
+        for( int i = 0; i < nCount; i++ )
         {
             if( x[i] != HUGE_VAL )
             {
@@ -1006,10 +1061,13 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
                 if( x[i] > M_PI )
                 {
                     if( x[i] < M_PI+1e-14 )
+                    {
                         x[i] = M_PI;
-                    else if (bCheckWithInvertProj)
+                    }
+                    else if( bCheckWithInvertProj )
                     {
-                        x[i] = y[i] = HUGE_VAL;
+                        x[i] = HUGE_VAL;
+                        y[i] = HUGE_VAL;
                         y0 = HUGE_VAL;
                         continue;
                     }
@@ -1017,16 +1075,19 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
                     {
                         do {
                             x[i] -= 2 * M_PI;
-                        } while ( x[i] > M_PI );
+                        } while( x[i] > M_PI );
                     }
                 }
                 else if( x[i] < -M_PI )
                 {
                     if( x[i] > -M_PI-1e-14 )
+                    {
                         x[i] = -M_PI;
-                    else if (bCheckWithInvertProj)
+                    }
+                    else if( bCheckWithInvertProj )
                     {
-                        x[i] = y[i] = HUGE_VAL;
+                        x[i] = HUGE_VAL;
+                        y[i] = HUGE_VAL;
                         y0 = HUGE_VAL;
                         continue;
                     }
@@ -1037,69 +1098,84 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
                         } while( x[i] < -M_PI );
                     }
                 }
-                 // Optimization for the case where we are provided a whole line of same northing
+                 // Optimization for the case where we are provided a whole line
+                 // of same northing.
                 if( i > 0 && y[i] == y0 )
                     y[i] = y[0];
                 else
-                    y[i] = M_PI / 2 - 2. * atan(exp(-y[i] * REVERSE_SPHERE_RADIUS));
+                    y[i] =
+                        M_PI / 2.0 -
+                        2.0 * atan(exp(-y[i] * REVERSE_SPHERE_RADIUS));
             }
         }
 
         bTransformDone = true;
     }
     else if( bIdentityTransform )
+    {
         bTransformDone = true;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Do the transformation (or not...) using PROJ.4.                 */
 /* -------------------------------------------------------------------- */
     if( !bTransformDone && pjctx == NULL )
     {
-        /* The mutex has already been created */
+        // The mutex has already been created.
         CPLAssert(hPROJMutex != NULL);
         CPLAcquireMutex(hPROJMutex, 1000.0);
     }
 
+    int err = 0;
     if( bTransformDone )
-        err = 0;
-    else if (bCheckWithInvertProj)
     {
-        /* For some projections, we cannot detect if we are trying to reproject */
-        /* coordinates outside the validity area of the projection. So let's do */
-        /* the reverse reprojection and compare with the source coordinates */
-        if (nCount > nMaxCount)
+        // err = 0;
+    }
+    else if( bCheckWithInvertProj )
+    {
+        // For some projections, we cannot detect if we are trying to reproject
+        // coordinates outside the validity area of the projection. So let's do
+        // the reverse reprojection and compare with the source coordinates.
+        if( nCount > nMaxCount )
         {
             nMaxCount = nCount;
-            padfOriX = (double*) CPLRealloc(padfOriX, sizeof(double)*nCount);
-            padfOriY = (double*) CPLRealloc(padfOriY, sizeof(double)*nCount);
-            padfOriZ = (double*) CPLRealloc(padfOriZ, sizeof(double)*nCount);
-            padfTargetX = (double*) CPLRealloc(padfTargetX, sizeof(double)*nCount);
-            padfTargetY = (double*) CPLRealloc(padfTargetY, sizeof(double)*nCount);
-            padfTargetZ = (double*) CPLRealloc(padfTargetZ, sizeof(double)*nCount);
+            padfOriX = static_cast<double*>(
+                CPLRealloc(padfOriX, sizeof(double) * nCount));
+            padfOriY = static_cast<double*>(
+                CPLRealloc(padfOriY, sizeof(double)*nCount));
+            padfOriZ = static_cast<double*>(
+                CPLRealloc(padfOriZ, sizeof(double)*nCount));
+            padfTargetX = static_cast<double*>(
+                CPLRealloc(padfTargetX, sizeof(double)*nCount));
+            padfTargetY = static_cast<double*>(
+                CPLRealloc(padfTargetY, sizeof(double)*nCount));
+            padfTargetZ = static_cast<double*>(
+                CPLRealloc(padfTargetZ, sizeof(double)*nCount));
         }
-        memcpy(padfOriX, x, sizeof(double)*nCount);
-        memcpy(padfOriY, y, sizeof(double)*nCount);
-        if (z)
+        memcpy(padfOriX, x, sizeof(double) * nCount);
+        memcpy(padfOriY, y, sizeof(double) * nCount);
+        if( z )
         {
             memcpy(padfOriZ, z, sizeof(double)*nCount);
         }
         err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z );
-        if (err == 0)
+        if( err == 0 )
         {
-            memcpy(padfTargetX, x, sizeof(double)*nCount);
-            memcpy(padfTargetY, y, sizeof(double)*nCount);
-            if (z)
+            memcpy(padfTargetX, x, sizeof(double) * nCount);
+            memcpy(padfTargetY, y, sizeof(double) * nCount);
+            if( z )
             {
-                memcpy(padfTargetZ, z, sizeof(double)*nCount);
+                memcpy(padfTargetZ, z, sizeof(double) * nCount);
             }
 
             err = pfn_pj_transform( psPJTarget, psPJSource , nCount, 1,
-                                    padfTargetX, padfTargetY, (z) ? padfTargetZ : NULL);
-            if (err == 0)
+                                    padfTargetX, padfTargetY,
+                                    z ? padfTargetZ : NULL);
+            if( err == 0 )
             {
-                for( i = 0; i < nCount; i++ )
+                for( int i = 0; i < nCount; i++ )
                 {
-                    if ( x[i] != HUGE_VAL && y[i] != HUGE_VAL &&
+                    if( x[i] != HUGE_VAL && y[i] != HUGE_VAL &&
                         (fabs(padfTargetX[i] - padfOriX[i]) > dfThreshold ||
                          fabs(padfTargetY[i] - padfOriY[i]) > dfThreshold) )
                     {
@@ -1117,8 +1193,8 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
 
 /* -------------------------------------------------------------------- */
 /*      Try to report an error through CPL.  Get proj.4 error string    */
-/*      if possible.  Try to avoid reporting thousands of error         */
-/*      ... suppress further error reporting on this OGRProj4CT if we   */
+/*      if possible.  Try to avoid reporting thousands of errors.       */
+/*      Suppress further error reporting on this OGRProj4CT if we       */
 /*      have already reported 20 errors.                                */
 /* -------------------------------------------------------------------- */
     if( err != 0 )
@@ -1126,10 +1202,10 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
         if( pabSuccess )
             memset( pabSuccess, 0, sizeof(int) * nCount );
 
-        if( ++nErrorCount < 20 )
+        if( m_bEmitErrors && ++nErrorCount < 20 )
         {
-            if (pjctx != NULL)
-                /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
+            if( pjctx != NULL )
+                // pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0.
                 CPLAcquireMutex(hPROJMutex, 1000.0);
 
             const char *pszError = NULL;
@@ -1143,18 +1219,19 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
             else
                 CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
 
-            if (pjctx != NULL)
-                /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */
+            if( pjctx != NULL )
+                // pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0.
                 CPLReleaseMutex(hPROJMutex);
         }
         else if( nErrorCount == 20 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Reprojection failed, err = %d, further errors will be suppressed on the transform object.",
+                      "Reprojection failed, err = %d, further errors will be "
+                      "suppressed on the transform object.",
                       err );
         }
 
-        if (pjctx == NULL)
+        if( pjctx == NULL )
             CPLReleaseMutex(hPROJMutex);
         return FALSE;
     }
@@ -1167,7 +1244,7 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
 /* -------------------------------------------------------------------- */
     if( bTargetLatLong )
     {
-        for( i = 0; i < nCount; i++ )
+        for( int i = 0; i < nCount; i++ )
         {
             if( x[i] != HUGE_VAL && y[i] != HUGE_VAL )
             {
@@ -1178,7 +1255,7 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
 
         if( bTargetWrap )
         {
-            for( i = 0; i < nCount; i++ )
+            for( int i = 0; i < nCount; i++ )
             {
                 if( x[i] != HUGE_VAL && y[i] != HUGE_VAL )
                 {
@@ -1196,7 +1273,7 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
 /* -------------------------------------------------------------------- */
     if( pabSuccess )
     {
-        for( i = 0; i < nCount; i++ )
+        for( int i = 0; i < nCount; i++ )
         {
             if( x[i] == HUGE_VAL || y[i] == HUGE_VAL )
                 pabSuccess[i] = FALSE;
@@ -1212,6 +1289,16 @@ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z,
 /*                           OCTTransformEx()                           */
 /************************************************************************/
 
+/** Transform an array of points
+ *
+ * @param hTransform Transformation object
+ * @param nCount Number of points
+ * @param x Array of nCount x values.
+ * @param y Array of nCount y values.
+ * @param z Array of nCount z values.
+ * @param pabSuccess Output array of nCount value that will be set to TRUE/FALSE
+ * @return TRUE or FALSE
+ */
 int CPL_STDCALL OCTTransformEx( OGRCoordinateTransformationH hTransform,
                                 int nCount, double *x, double *y, double *z,
                                 int *pabSuccess )
diff --git a/ogr/ogrcurve.cpp b/ogr/ogrcurve.cpp
index f77cf6c..e06aeb7 100644
--- a/ogr/ogrcurve.cpp
+++ b/ogr/ogrcurve.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcurve.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRCurve geometry class.
@@ -30,23 +29,21 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrcurve.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrcurve.cpp 36883 2016-12-15 13:31:12Z rouault $");
+
+//! @cond Doxygen_Suppress
 
 /************************************************************************/
 /*                                OGRCurve()                            */
 /************************************************************************/
 
-OGRCurve::OGRCurve()
-{
-}
+OGRCurve::OGRCurve() {}
 
 /************************************************************************/
 /*                               ~OGRCurve()                            */
 /************************************************************************/
 
-OGRCurve::~OGRCurve()
-{
-}
+OGRCurve::~OGRCurve() {}
 
 /************************************************************************/
 /*                       OGRCurve( const OGRCurve& )                    */
@@ -54,8 +51,7 @@ OGRCurve::~OGRCurve()
 
 OGRCurve::OGRCurve( const OGRCurve& other ) :
     OGRGeometry( other )
-{
-}
+{}
 
 /************************************************************************/
 /*                       operator=( const OGRCurve& )                   */
@@ -69,6 +65,7 @@ OGRCurve& OGRCurve::operator=( const OGRCurve& other )
     }
     return *this;
 }
+//! @endcond
 
 /************************************************************************/
 /*                            getDimension()                            */
@@ -98,20 +95,72 @@ int OGRCurve::getDimension() const
 int OGRCurve::get_IsClosed() const
 
 {
-    OGRPoint            oStartPoint, oEndPoint;
-
+    OGRPoint oStartPoint;
     StartPoint( &oStartPoint );
+
+    OGRPoint oEndPoint;
     EndPoint( &oEndPoint );
 
-    if( oStartPoint.getX() == oEndPoint.getX()
-        && oStartPoint.getY() == oEndPoint.getY() )
+    if (oStartPoint.IsMeasured() && oEndPoint.IsMeasured())
+    {
+        // XYZM type
+        if (oStartPoint.Is3D() && oEndPoint.Is3D())
+        {
+            if( oStartPoint.getX() == oEndPoint.getX() && oStartPoint.getY() == oEndPoint.getY()
+                && oStartPoint.getZ() == oEndPoint.getZ() && oStartPoint.getM() == oEndPoint.getM())
+            {
+                return TRUE;
+            }
+            else
+                return FALSE;
+        }
+        // XYM type
+        else
+        {
+            if( oStartPoint.getX() == oEndPoint.getX() && oStartPoint.getY() == oEndPoint.getY()
+                && oStartPoint.getM() == oEndPoint.getM())
+            {
+                return TRUE;
+            }
+            else
+                return FALSE;
+        }
+    }
+
+    else if (oStartPoint.Is3D() && oEndPoint.Is3D())
     {
-        return TRUE;
+        // XYZ type
+        if( oStartPoint.getX() == oEndPoint.getX() && oStartPoint.getY() == oEndPoint.getY()
+            && oStartPoint.getZ() == oEndPoint.getZ())
+        {
+            return TRUE;
+        }
+        else
+            return FALSE;
     }
-    else
+
+    // one of the points is 3D
+    else if (((oStartPoint.Is3D() & oEndPoint.Is3D()) == 0) &&
+             ((oStartPoint.Is3D() | oEndPoint.Is3D()) == 1))
     {
         return FALSE;
     }
+
+    // one of the points is Measured
+    else if (((oStartPoint.IsMeasured() & oEndPoint.IsMeasured()) == 0) &&
+             ((oStartPoint.IsMeasured() | oEndPoint.IsMeasured()) == 1))
+    {
+        return FALSE;
+    }
+
+    else
+    {
+        // XY type
+        if( oStartPoint.getX() == oEndPoint.getX() && oStartPoint.getY() == oEndPoint.getY() )
+            return TRUE;
+        else
+            return FALSE;
+    }
 }
 
 /**
@@ -161,7 +210,8 @@ int OGRCurve::get_IsClosed() const
  */
 
 /**
- * \fn OGRLineString* OGRCurve::CurveToLine( double dfMaxAngleStepSizeDegrees, const char* const* papszOptions ) const;
+ * \fn OGRLineString* OGRCurve::CurveToLine( double dfMaxAngleStepSizeDegrees,
+ *     const char* const* papszOptions ) const;
  *
  * \brief Return a linestring from a curve geometry.
  *
@@ -178,7 +228,8 @@ int OGRCurve::get_IsClosed() const
  * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
  * arc, zero to use the default setting.
  * @param papszOptions options as a null-terminated list of strings or NULL.
- *                     See OGRGeometryFactory::curveToLineString() for valid options.
+ *                     See OGRGeometryFactory::curveToLineString() for valid
+ *                     options.
  *
  * @return a line string approximating the curve
  *
@@ -257,19 +308,22 @@ int OGRCurve::get_IsClosed() const
 
 OGRBoolean OGRCurve::IsConvex() const
 {
-    OGRBoolean bRet = TRUE;
+    bool bRet = true;
     OGRPointIterator* poPointIter = getPointIterator();
-    OGRPoint p1, p2, p3;
+    OGRPoint p1;
+    OGRPoint p2;
     if( poPointIter->getNextPoint(&p1) &&
         poPointIter->getNextPoint(&p2) )
     {
+        OGRPoint p3;
         while( poPointIter->getNextPoint(&p3) )
         {
-            double crossproduct = (p2.getX() - p1.getX()) * (p3.getY() - p2.getY()) -
-                                  (p2.getY() - p1.getY()) * (p3.getX() - p2.getX());
+            const double crossproduct =
+                (p2.getX() - p1.getX()) * (p3.getY() - p2.getY()) -
+                (p2.getY() - p1.getY()) * (p3.getX() - p2.getX());
             if( crossproduct > 0 )
             {
-                bRet = FALSE;
+                bRet = false;
                 break;
             }
             p1.setX(p2.getX());
@@ -298,7 +352,7 @@ OGRBoolean OGRCurve::IsConvex() const
  * @since GDAL 2.0
  */
 
-OGRCompoundCurve* OGRCurve::CastToCompoundCurve(OGRCurve* poCurve)
+OGRCompoundCurve* OGRCurve::CastToCompoundCurve( OGRCurve* poCurve )
 {
     OGRCompoundCurve* poCC = new OGRCompoundCurve();
     if( poCurve->getGeometryType() == wkbLineString )
@@ -329,7 +383,7 @@ OGRCompoundCurve* OGRCurve::CastToCompoundCurve(OGRCurve* poCurve)
  * @since GDAL 2.0
  */
 
-OGRLineString* OGRCurve::CastToLineString(OGRCurve* poCurve)
+OGRLineString* OGRCurve::CastToLineString( OGRCurve* poCurve )
 {
     OGRCurveCasterToLineString pfn = poCurve->GetCasterToLineString();
     return pfn(poCurve);
@@ -351,7 +405,7 @@ OGRLineString* OGRCurve::CastToLineString(OGRCurve* poCurve)
  * @since GDAL 2.0
  */
 
-OGRLinearRing* OGRCurve::CastToLinearRing(OGRCurve* poCurve)
+OGRLinearRing* OGRCurve::CastToLinearRing( OGRCurve* poCurve )
 {
     OGRCurveCasterToLinearRing pfn = poCurve->GetCasterToLinearRing();
     return pfn(poCurve);
@@ -372,7 +426,7 @@ OGRLinearRing* OGRCurve::CastToLinearRing(OGRCurve* poCurve)
  * @since GDAL 2.0
  */
 
-int OGRCurve::ContainsPoint( CPL_UNUSED const OGRPoint* p ) const
+int OGRCurve::ContainsPoint( const OGRPoint* /* p */ ) const
 {
     return -1;
 }
@@ -381,9 +435,7 @@ int OGRCurve::ContainsPoint( CPL_UNUSED const OGRPoint* p ) const
 /*                          ~OGRPointIterator()                         */
 /************************************************************************/
 
-OGRPointIterator::~OGRPointIterator()
-{
-}
+OGRPointIterator::~OGRPointIterator() {}
 
 /**
  * \fn OGRBoolean OGRPointIterator::getNextPoint(OGRPoint* p);
@@ -406,7 +458,7 @@ OGRPointIterator::~OGRPointIterator()
  *
  * @since GDAL 2.0
  */
-void OGRPointIterator::destroy(OGRPointIterator* poIter)
+void OGRPointIterator::destroy( OGRPointIterator* poIter )
 {
     delete poIter;
 }
diff --git a/ogr/ogrcurvecollection.cpp b/ogr/ogrcurvecollection.cpp
index 023b5c9..1a6cda4 100644
--- a/ogr/ogrcurvecollection.cpp
+++ b/ogr/ogrcurvecollection.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcurvecollection.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRCurveCollection class.
@@ -27,11 +26,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
+
+#include <cstddef>
+#include <cstring>
+
+#include "ogr_core.h"
 #include "ogr_p.h"
-#include <assert.h>
+#include "ogr_spatialref.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: ogrcurvecollection.cpp 37852 2017-03-27 15:31:30Z rouault $");
+
+//! @cond Doxygen_Suppress
 
 /************************************************************************/
 /*                         OGRCurveCollection()                         */
@@ -58,19 +69,27 @@ OGRCurveCollection::OGRCurveCollection()
  */
 
 OGRCurveCollection::OGRCurveCollection( const OGRCurveCollection& other ) :
-    nCurveCount( 0 ),
-    papoCurves( NULL )
+    nCurveCount(0),
+    papoCurves(NULL)
 {
     if( other.nCurveCount > 0 )
     {
         nCurveCount = other.nCurveCount;
-        papoCurves = (OGRCurve **) VSI_CALLOC_VERBOSE(sizeof(void*), nCurveCount);
+        papoCurves = static_cast<OGRCurve **>(
+            VSI_CALLOC_VERBOSE(sizeof(void*), nCurveCount));
 
         if( papoCurves )
         {
             for( int i = 0; i < nCurveCount; i++ )
             {
-                papoCurves[i] = (OGRCurve*)other.papoCurves[i]->clone();
+                OGRCurve *poCurve =
+                    dynamic_cast<OGRCurve *>(other.papoCurves[i]->clone());
+                if( poCurve == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                             "dynamic_cast failed.  Expected OGRCurve.");
+                }
+                papoCurves[i] = poCurve;
             }
         }
     }
@@ -99,7 +118,8 @@ OGRCurveCollection::~OGRCurveCollection()
  * @since GDAL 2.1
  */
 
-OGRCurveCollection& OGRCurveCollection::operator=( const OGRCurveCollection& other )
+OGRCurveCollection&
+OGRCurveCollection::operator=( const OGRCurveCollection& other )
 {
     if( this != &other)
     {
@@ -108,13 +128,22 @@ OGRCurveCollection& OGRCurveCollection::operator=( const OGRCurveCollection& oth
         if( other.nCurveCount > 0 )
         {
             nCurveCount = other.nCurveCount;
-            papoCurves = (OGRCurve **) VSI_MALLOC2_VERBOSE(sizeof(void*), nCurveCount);
+            papoCurves = static_cast<OGRCurve **>(
+                VSI_MALLOC2_VERBOSE(sizeof(void*), nCurveCount));
 
             if( papoCurves )
             {
                 for( int i = 0; i < nCurveCount; i++ )
                 {
-                    papoCurves[i] = (OGRCurve*)other.papoCurves[i]->clone();
+                    OGRCurve *poCurve =
+                        dynamic_cast<OGRCurve *>(other.papoCurves[i]->clone());
+                    if( poCurve == NULL )
+                    {
+                        CPLError(CE_Fatal, CPLE_AppDefined,
+                                 "dynamic_cast failed.  Expected OGRCurve.");
+                    }
+
+                    papoCurves[i] = poCurve;
                 }
             }
         }
@@ -128,7 +157,7 @@ OGRCurveCollection& OGRCurveCollection::operator=( const OGRCurveCollection& oth
 
 int OGRCurveCollection::WkbSize() const
 {
-    int         nSize = 9;
+    int nSize = 9;
 
     for( int i = 0; i < nCurveCount; i++ )
     {
@@ -164,8 +193,9 @@ OGRErr OGRCurveCollection::addCurveDirectly( OGRGeometry* poGeom,
 
     if( bNeedRealloc )
     {
-        OGRCurve** papoNewCurves = (OGRCurve **) VSI_REALLOC_VERBOSE( papoCurves,
-                                             sizeof(OGRCurve*) * (nCurveCount+1) );
+        OGRCurve** papoNewCurves = static_cast<OGRCurve **>(
+            VSI_REALLOC_VERBOSE(papoCurves,
+                                sizeof(OGRCurve*) * (nCurveCount + 1)));
         if( papoNewCurves == NULL )
             return OGRERR_FAILURE;
         papoCurves = papoNewCurves;
@@ -201,9 +231,10 @@ OGRErr OGRCurveCollection::importPreambuleFromWkb( OGRGeometry* poGeom,
     if( eErr != OGRERR_NONE )
         return eErr;
 
-    /* coverity[tainted_data] */
-    papoCurves = (OGRCurve **) VSI_CALLOC_VERBOSE(sizeof(void*), nCurveCount);
-    if (nCurveCount != 0 && papoCurves == NULL)
+    // coverity[tainted_data]
+    papoCurves = static_cast<OGRCurve **>(
+        VSI_CALLOC_VERBOSE(sizeof(void*), nCurveCount));
+    if( nCurveCount != 0 && papoCurves == NULL )
     {
         nCurveCount = 0;
         return OGRERR_NOT_ENOUGH_MEMORY;
@@ -216,35 +247,39 @@ OGRErr OGRCurveCollection::importPreambuleFromWkb( OGRGeometry* poGeom,
 /*                       importBodyFromWkb()                            */
 /************************************************************************/
 
-OGRErr OGRCurveCollection::importBodyFromWkb( OGRGeometry* poGeom,
-                                       unsigned char * pabyData,
-                                       int nSize,
-                                       int nDataOffset,
-                                       int bAcceptCompoundCurve,
-                                       OGRErr (*pfnAddCurveDirectlyFromWkb)(OGRGeometry* poGeom, OGRCurve* poCurve),
-                                       OGRwkbVariant eWkbVariant )
+OGRErr OGRCurveCollection::importBodyFromWkb(
+    OGRGeometry* poGeom,
+    unsigned char * pabyData,
+    int nSize,
+    int nDataOffset,
+    int bAcceptCompoundCurve,
+    OGRErr (*pfnAddCurveDirectlyFromWkb)(OGRGeometry* poGeom,
+                                         OGRCurve* poCurve),
+    OGRwkbVariant eWkbVariant )
 {
 
 /* -------------------------------------------------------------------- */
 /*      Get the Geoms.                                                  */
 /* -------------------------------------------------------------------- */
-    int nIter = nCurveCount;
+    const int nIter = nCurveCount;
     nCurveCount = 0;
     for( int iGeom = 0; iGeom < nIter; iGeom++ )
     {
-        OGRErr  eErr;
         OGRGeometry* poSubGeom = NULL;
 
-        /* Parses sub-geometry */
+        // Parses sub-geometry.
         unsigned char* pabySubData = pabyData + nDataOffset;
         if( nSize < 9 && nSize != -1 )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        OGRwkbGeometryType eSubGeomType;
-        if ( OGRReadWKBGeometryType( pabySubData, eWkbVariant, &eSubGeomType ) != OGRERR_NONE )
+        OGRwkbGeometryType eSubGeomType = wkbUnknown;
+        if( OGRReadWKBGeometryType( pabySubData, eWkbVariant,
+                                    &eSubGeomType ) != OGRERR_NONE )
             return OGRERR_FAILURE;
 
-        if( (eSubGeomType != wkbCompoundCurve && OGR_GT_IsCurve(eSubGeomType)) ||
+        OGRErr eErr = OGRERR_NONE;
+        if( (eSubGeomType != wkbCompoundCurve &&
+             OGR_GT_IsCurve(eSubGeomType)) ||
             (bAcceptCompoundCurve && eSubGeomType == wkbCompoundCurve) )
         {
             eErr = OGRGeometryFactory::
@@ -253,20 +288,30 @@ OGRErr OGRCurveCollection::importBodyFromWkb( OGRGeometry* poGeom,
         }
         else
         {
-            CPLDebug("OGR", "Cannot add geometry of type (%d) to geometry of type (%d)",
-                     eSubGeomType, poGeom->getGeometryType());
+            CPLDebug(
+                "OGR",
+                "Cannot add geometry of type (%d) to geometry of type (%d)",
+                eSubGeomType, poGeom->getGeometryType());
             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
         }
 
         if( eErr == OGRERR_NONE )
-            eErr = pfnAddCurveDirectlyFromWkb(poGeom, (OGRCurve*)poSubGeom);
+        {
+            OGRCurve *poCurve = dynamic_cast<OGRCurve *>(poSubGeom);
+            if( poCurve == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRCurve.");
+            }
+            eErr = pfnAddCurveDirectlyFromWkb(poGeom, poCurve);
+        }
         if( eErr != OGRERR_NONE )
         {
             delete poSubGeom;
             return eErr;
         }
 
-        int nSubGeomWkbSize = poSubGeom->WkbSize();
+        const int nSubGeomWkbSize = poSubGeom->WkbSize();
         if( nSize != -1 )
             nSize -= nSubGeomWkbSize;
 
@@ -284,22 +329,17 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
                                         char ** ppszDstText ) const
 
 {
-    char        **papszGeoms;
-    int         iGeom;
-    size_t      nCumulativeLength = 0;
-    OGRErr      eErr;
-
     if( nCurveCount == 0 )
     {
         CPLString osEmpty;
         if( poGeom->Is3D() && poGeom->IsMeasured() )
-            osEmpty.Printf("%s ZM EMPTY",poGeom->getGeometryName());
+            osEmpty.Printf("%s ZM EMPTY", poGeom->getGeometryName());
         else if( poGeom->IsMeasured() )
-            osEmpty.Printf("%s M EMPTY",poGeom->getGeometryName());
+            osEmpty.Printf("%s M EMPTY", poGeom->getGeometryName());
         else if( poGeom->Is3D() )
-            osEmpty.Printf("%s Z EMPTY",poGeom->getGeometryName());
+            osEmpty.Printf("%s Z EMPTY", poGeom->getGeometryName());
         else
-            osEmpty.Printf("%s EMPTY",poGeom->getGeometryName());
+            osEmpty.Printf("%s EMPTY", poGeom->getGeometryName());
         *ppszDstText = CPLStrdup(osEmpty);
         return OGRERR_NONE;
     }
@@ -307,11 +347,15 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
 /* -------------------------------------------------------------------- */
 /*      Build a list of strings containing the stuff for each Geom.     */
 /* -------------------------------------------------------------------- */
-    papszGeoms = (char **) CPLCalloc(sizeof(char *),nCurveCount);
+    char **papszGeoms =
+        static_cast<char **>(CPLCalloc(sizeof(char *), nCurveCount));
+    OGRErr eErr = OGRERR_NONE;
+    size_t nCumulativeLength = 0;
 
-    for( iGeom = 0; iGeom < nCurveCount; iGeom++ )
+    for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
     {
-        eErr = papoCurves[iGeom]->exportToWkt( &(papszGeoms[iGeom]), wkbVariantIso );
+        eErr = papoCurves[iGeom]->exportToWkt( &(papszGeoms[iGeom]),
+                                               wkbVariantIso );
         if( eErr != OGRERR_NONE )
             goto error;
 
@@ -321,8 +365,9 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
 /* -------------------------------------------------------------------- */
 /*      Allocate the right amount of space for the aggregated string    */
 /* -------------------------------------------------------------------- */
-    *ppszDstText = (char *) VSI_MALLOC_VERBOSE(nCumulativeLength + nCurveCount +
-                                    strlen(poGeom->getGeometryName()) + 10);
+    *ppszDstText = static_cast<char *>(
+        VSI_MALLOC_VERBOSE(nCumulativeLength + nCurveCount +
+                           strlen(poGeom->getGeometryName()) + 10));
 
     if( *ppszDstText == NULL )
     {
@@ -343,12 +388,12 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
     strcat( *ppszDstText, " (" );
     nCumulativeLength = strlen(*ppszDstText);
 
-    for( iGeom = 0; iGeom < nCurveCount; iGeom++ )
+    for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
     {
         if( iGeom > 0 )
             (*ppszDstText)[nCumulativeLength++] = ',';
 
-        /* We must strip the explicit "LINESTRING " prefix */
+        // We must strip the explicit "LINESTRING " prefix.
         size_t nSkip = 0;
         if( !papoCurves[iGeom]->IsEmpty() &&
             STARTS_WITH_CI(papszGeoms[iGeom], "LINESTRING ") )
@@ -362,8 +407,10 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
                 nSkip += 2;
         }
 
-        size_t nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
-        memcpy( *ppszDstText + nCumulativeLength, papszGeoms[iGeom] + nSkip, nGeomLength );
+        const size_t nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
+        memcpy( *ppszDstText + nCumulativeLength,
+                papszGeoms[iGeom] + nSkip,
+                nGeomLength );
         nCumulativeLength += nGeomLength;
         VSIFree( papszGeoms[iGeom] );
     }
@@ -376,7 +423,7 @@ OGRErr OGRCurveCollection::exportToWkt( const OGRGeometry* poGeom,
     return OGRERR_NONE;
 
 error:
-    for( iGeom = 0; iGeom < nCurveCount; iGeom++ )
+    for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
         CPLFree( papszGeoms[iGeom] );
     CPLFree( papszGeoms );
     return eErr;
@@ -391,8 +438,6 @@ OGRErr OGRCurveCollection::exportToWkb( const OGRGeometry* poGeom,
                                         unsigned char * pabyData,
                                         OGRwkbVariant eWkbVariant ) const
 {
-    int         nOffset;
-
 /* -------------------------------------------------------------------- */
 /*      Set the byte order.                                             */
 /* -------------------------------------------------------------------- */
@@ -405,18 +450,20 @@ OGRErr OGRCurveCollection::exportToWkb( const OGRGeometry* poGeom,
     GUInt32 nGType = poGeom->getIsoGeometryType();
     if( eWkbVariant == wkbVariantPostGIS1 )
     {
-        int bIs3D = wkbHasZ((OGRwkbGeometryType)nGType);
+        const bool bIs3D = wkbHasZ(static_cast<OGRwkbGeometryType>(nGType));
         nGType = wkbFlatten(nGType);
         if( nGType == wkbCurvePolygon )
             nGType = POSTGIS15_CURVEPOLYGON;
         if( bIs3D )
-            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
+            // Explicitly set wkb25DBit.
+            // TODO(schwehr): Clean up the casting.
+            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse);
     }
 
-    if( eByteOrder == wkbNDR )
-        nGType = CPL_LSBWORD32( nGType );
-    else
-        nGType = CPL_MSBWORD32( nGType );
+    if( OGR_SWAP( eByteOrder ) )
+    {
+        nGType = CPL_SWAP32(nGType);
+    }
 
     memcpy( pabyData + 1, &nGType, 4 );
 
@@ -425,9 +472,7 @@ OGRErr OGRCurveCollection::exportToWkb( const OGRGeometry* poGeom,
 /* -------------------------------------------------------------------- */
     if( OGR_SWAP( eByteOrder ) )
     {
-        int     nCount;
-
-        nCount = CPL_SWAP32( nCurveCount );
+        const int nCount = CPL_SWAP32( nCurveCount );
         memcpy( pabyData+5, &nCount, 4 );
     }
     else
@@ -435,14 +480,16 @@ OGRErr OGRCurveCollection::exportToWkb( const OGRGeometry* poGeom,
         memcpy( pabyData+5, &nCurveCount, 4 );
     }
 
-    nOffset = 9;
+    // TODO(schwehr): Where do these 9 values come from?
+    int nOffset = 9;
 
 /* ==================================================================== */
 /*      Serialize each of the Geoms.                                    */
 /* ==================================================================== */
     for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
     {
-        papoCurves[iGeom]->exportToWkb( eByteOrder, pabyData + nOffset, eWkbVariant );
+        papoCurves[iGeom]->exportToWkb( eByteOrder, pabyData + nOffset,
+                                        eWkbVariant );
 
         nOffset += papoCurves[iGeom]->WkbSize();
     }
@@ -454,7 +501,7 @@ OGRErr OGRCurveCollection::exportToWkb( const OGRGeometry* poGeom,
 /*                               empty()                                */
 /************************************************************************/
 
-void OGRCurveCollection::empty(OGRGeometry* poGeom)
+void OGRCurveCollection::empty( OGRGeometry* poGeom )
 {
     if( papoCurves != NULL )
     {
@@ -462,7 +509,7 @@ void OGRCurveCollection::empty(OGRGeometry* poGeom)
         {
             delete papoCurves[i];
         }
-        OGRFree( papoCurves );
+        CPLFree( papoCurves );
     }
 
     nCurveCount = 0;
@@ -477,7 +524,7 @@ void OGRCurveCollection::empty(OGRGeometry* poGeom)
 
 void OGRCurveCollection::getEnvelope( OGREnvelope * psEnvelope ) const
 {
-    OGREnvelope3D         oEnv3D;
+    OGREnvelope3D oEnv3D;
     getEnvelope(&oEnv3D);
     psEnvelope->MinX = oEnv3D.MinX;
     psEnvelope->MinY = oEnv3D.MinY;
@@ -491,30 +538,29 @@ void OGRCurveCollection::getEnvelope( OGREnvelope * psEnvelope ) const
 
 void OGRCurveCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
 {
-    OGREnvelope3D       oGeomEnv;
-    bool                bExtentSet = false;
+    OGREnvelope3D oGeomEnv;
+    bool bExtentSet = false;
 
+    *psEnvelope = OGREnvelope3D();
     for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
     {
-        if (!papoCurves[iGeom]->IsEmpty())
+        if( !papoCurves[iGeom]->IsEmpty() )
         {
-            if (!bExtentSet)
-            {
-                papoCurves[iGeom]->getEnvelope( psEnvelope );
-                bExtentSet = true;
-            }
-            else
-            {
-                papoCurves[iGeom]->getEnvelope( &oGeomEnv );
-                psEnvelope->Merge( oGeomEnv );
-            }
+            bExtentSet = true;
+            papoCurves[iGeom]->getEnvelope( &oGeomEnv );
+            psEnvelope->Merge( oGeomEnv );
         }
     }
 
-    if (!bExtentSet)
+    if( !bExtentSet )
     {
-        psEnvelope->MinX = psEnvelope->MinY = psEnvelope->MinZ = 0;
-        psEnvelope->MaxX = psEnvelope->MaxY = psEnvelope->MaxZ = 0;
+        // To be backward compatible when called on empty geom
+        psEnvelope->MinX = 0.0;
+        psEnvelope->MinY = 0.0;
+        psEnvelope->MinZ = 0.0;
+        psEnvelope->MaxX = 0.0;
+        psEnvelope->MaxY = 0.0;
+        psEnvelope->MaxZ = 0.0;
     }
 }
 
@@ -524,19 +570,24 @@ void OGRCurveCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
 
 OGRBoolean OGRCurveCollection::IsEmpty() const
 {
-    return nCurveCount == 0;
+    for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
+    {
+        if( !papoCurves[iGeom]->IsEmpty() )
+            return FALSE;
+    }
+    return TRUE;
 }
 
 /************************************************************************/
 /*                               Equals()                                */
 /************************************************************************/
 
-OGRBoolean  OGRCurveCollection::Equals( OGRCurveCollection *poOCC ) const
+OGRBoolean OGRCurveCollection::Equals( OGRCurveCollection *poOCC ) const
 {
     if( getNumCurves() != poOCC->getNumCurves() )
         return FALSE;
 
-    // we should eventually test the SRS.
+    // Should eventually test the SRS.
 
     for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
     {
@@ -572,7 +623,8 @@ void OGRCurveCollection::set3D( OGRGeometry* poGeom, OGRBoolean bIs3D )
     poGeom->OGRGeometry::set3D( bIs3D );
 }
 
-void OGRCurveCollection::setMeasured( OGRGeometry* poGeom, OGRBoolean bIsMeasured )
+void OGRCurveCollection::setMeasured( OGRGeometry* poGeom,
+                                      OGRBoolean bIsMeasured )
 {
     for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
     {
@@ -586,7 +638,7 @@ void OGRCurveCollection::setMeasured( OGRGeometry* poGeom, OGRBoolean bIsMeasure
 /*                          getNumCurves()                              */
 /************************************************************************/
 
-int          OGRCurveCollection::getNumCurves() const
+int OGRCurveCollection::getNumCurves() const
 {
     return nCurveCount;
 }
@@ -595,7 +647,7 @@ int          OGRCurveCollection::getNumCurves() const
 /*                           getCurve()                                 */
 /************************************************************************/
 
-OGRCurve    *OGRCurveCollection::getCurve( int i )
+OGRCurve *OGRCurveCollection::getCurve( int i )
 {
     if( i < 0 || i >= nCurveCount )
         return NULL;
@@ -624,9 +676,11 @@ OGRCurve* OGRCurveCollection::stealCurve( int i )
     OGRCurve* poRet = papoCurves[i];
     if( i < nCurveCount - 1 )
     {
-        memmove(papoCurves + i, papoCurves + i + 1, (nCurveCount - i - 1) * sizeof(OGRCurve*));
+        memmove(papoCurves + i,
+                papoCurves + i + 1,
+                (nCurveCount - i - 1) * sizeof(OGRCurve*));
     }
-    nCurveCount --;
+    nCurveCount--;
     return poRet;
 }
 
@@ -634,25 +688,20 @@ OGRCurve* OGRCurveCollection::stealCurve( int i )
 /*                             transform()                              */
 /************************************************************************/
 
-OGRErr  OGRCurveCollection::transform( OGRGeometry* poGeom,
-                                       OGRCoordinateTransformation *poCT )
+OGRErr OGRCurveCollection::transform( OGRGeometry* poGeom,
+                                      OGRCoordinateTransformation *poCT )
 {
-#ifdef DISABLE_OGRGEOM_TRANSFORM
-    return OGRERR_FAILURE;
-#else
     for( int iGeom = 0; iGeom < nCurveCount; iGeom++ )
     {
-        OGRErr  eErr;
-
-        eErr = papoCurves[iGeom]->transform( poCT );
+        const OGRErr eErr = papoCurves[iGeom]->transform( poCT );
         if( eErr != OGRERR_NONE )
         {
             if( iGeom != 0 )
             {
                 CPLDebug("OGR",
-                         "OGRCurveCollection::transform() failed for a geometry other\n"
-                         "than the first, meaning some geometries are transformed\n"
-                         "and some are not!\n" );
+                         "OGRCurveCollection::transform() failed for a "
+                         "geometry other than the first, meaning some "
+                         "geometries are transformed and some are not!" );
 
                 return OGRERR_FAILURE;
             }
@@ -664,7 +713,6 @@ OGRErr  OGRCurveCollection::transform( OGRGeometry* poGeom,
     poGeom->assignSpatialReference( poCT->GetTargetCS() );
 
     return OGRERR_NONE;
-#endif
 }
 
 /************************************************************************/
@@ -712,3 +760,5 @@ OGRBoolean OGRCurveCollection::hasCurveGeometry(int bLookForNonLinear) const
     }
     return FALSE;
 }
+
+//! @endcond
diff --git a/ogr/ogrcurvepolygon.cpp b/ogr/ogrcurvepolygon.cpp
index 276c349..65dd21d 100644
--- a/ogr/ogrcurvepolygon.cpp
+++ b/ogr/ogrcurvepolygon.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRCurvePolygon geometry class.
@@ -27,12 +26,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
-#include "ogr_p.h"
-#include "ogr_geos.h"
+
+#include <cstddef>
+
+#include "cpl_error.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_geos.h"
+#include "ogr_sfcgal.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogrcurvepolygon.cpp 36883 2016-12-15 13:31:12Z rouault $");
 
 /************************************************************************/
 /*                            OGRCurvePolygon()                         */
@@ -42,10 +49,7 @@ CPL_CVSID("$Id$");
  * \brief Create an empty curve polygon.
  */
 
-OGRCurvePolygon::OGRCurvePolygon()
-
-{
-}
+OGRCurvePolygon::OGRCurvePolygon() {}
 
 /************************************************************************/
 /*               OGRCurvePolygon( const OGRCurvePolygon& )              */
@@ -63,17 +67,13 @@ OGRCurvePolygon::OGRCurvePolygon()
 OGRCurvePolygon::OGRCurvePolygon( const OGRCurvePolygon& other ) :
     OGRSurface(other),
     oCC(other.oCC)
-{
-}
+{}
 
 /************************************************************************/
 /*                           ~OGRCurvePolygon()                         */
 /************************************************************************/
 
-OGRCurvePolygon::~OGRCurvePolygon()
-
-{
-}
+OGRCurvePolygon::~OGRCurvePolygon() {}
 
 /************************************************************************/
 /*                 operator=( const OGRCurvePolygon&)                  */
@@ -90,7 +90,7 @@ OGRCurvePolygon::~OGRCurvePolygon()
 
 OGRCurvePolygon& OGRCurvePolygon::operator=( const OGRCurvePolygon& other )
 {
-    if( this != &other)
+    if( this != &other )
     {
         OGRSurface::operator=( other );
 
@@ -106,10 +106,8 @@ OGRCurvePolygon& OGRCurvePolygon::operator=( const OGRCurvePolygon& other )
 OGRGeometry *OGRCurvePolygon::clone() const
 
 {
-    OGRCurvePolygon  *poNewPolygon;
-
-    poNewPolygon = (OGRCurvePolygon*)
-            OGRGeometryFactory::createGeometry(getGeometryType());
+    OGRCurvePolygon *poNewPolygon = dynamic_cast<OGRCurvePolygon *>(
+        OGRGeometryFactory::createGeometry(getGeometryType()));
     if( poNewPolygon == NULL )
         return NULL;
     poNewPolygon->assignSpatialReference( getSpatialReference() );
@@ -146,7 +144,7 @@ OGRwkbGeometryType OGRCurvePolygon::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbCurvePolygonZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbCurvePolygonM;
     else if( flags & OGR_G_3D )
         return wkbCurvePolygonZ;
@@ -191,15 +189,17 @@ const char * OGRCurvePolygon::getGeometryName() const
 /**
  * \brief Fetch reference to external polygon ring.
  *
- * Note that the returned ring pointer is to an internal data object of
- * the OGRCurvePolygon.  It should not be modified or deleted by the application,
- * and the pointer is only valid till the polygon is next modified.  Use
- * the OGRGeometry::clone() method to make a separate copy within the
- * application.
+ * Note that the returned ring pointer is to an internal data object of the
+ * OGRCurvePolygon.  It should not be modified or deleted by the application,
+ * and the pointer is only valid till the polygon is next modified.  Use the
+ * OGRGeometry::clone() method to make a separate copy within the application.
  *
- * Relates to the SFCOM IPolygon::get_ExteriorRing() method.
+ * Relates to the Simple Features for COM (SFCOM) IPolygon::get_ExteriorRing()
+ * method.
+ * TODO(rouault): What does that mean?
  *
- * @return pointer to external ring.  May be NULL if the OGRCurvePolygon is empty.
+ * @return pointer to external ring.  May be NULL if the OGRCurvePolygon is
+ * empty.
  */
 
 OGRCurve *OGRCurvePolygon::getExteriorRingCurve()
@@ -208,6 +208,19 @@ OGRCurve *OGRCurvePolygon::getExteriorRingCurve()
     return oCC.getCurve(0);
 }
 
+/**
+ * \brief Fetch reference to external polygon ring.
+ *
+ * Note that the returned ring pointer is to an internal data object of the
+ * OGRCurvePolygon.  It should not be modified or deleted by the application,
+ * and the pointer is only valid till the polygon is next modified.  Use the
+ * OGRGeometry::clone() method to make a separate copy within the application.
+ *
+ * Relates to the SFCOM IPolygon::get_ExteriorRing() method.
+ *
+ * @return pointer to external ring.  May be NULL if the OGRCurvePolygon is
+ * empty.
+ */
 const OGRCurve *OGRCurvePolygon::getExteriorRingCurve() const
 
 {
@@ -226,7 +239,6 @@ const OGRCurve *OGRCurvePolygon::getExteriorRingCurve() const
  * @return count of internal rings, zero or more.
  */
 
-
 int OGRCurvePolygon::getNumInteriorRings() const
 
 {
@@ -243,15 +255,14 @@ int OGRCurvePolygon::getNumInteriorRings() const
 /**
  * \brief Fetch reference to indicated internal ring.
  *
- * Note that the returned ring pointer is to an internal data object of
- * the OGRCurvePolygon.  It should not be modified or deleted by the application,
- * and the pointer is only valid till the polygon is next modified.  Use
- * the OGRGeometry::clone() method to make a separate copy within the
- * application.
+ * Note that the returned ring pointer is to an internal data object of the
+ * OGRCurvePolygon.  It should not be modified or deleted by the application,
+ * and the pointer is only valid till the polygon is next modified.  Use the
+ * OGRGeometry::clone() method to make a separate copy within the application.
  *
  * Relates to the SFCOM IPolygon::get_InternalRing() method.
  *
- * @param iRing internal ring index from 0 to getNumInternalRings() - 1.
+ * @param iRing internal ring index from 0 to getNumInteriorRings() - 1.
  *
  * @return pointer to interior ring.  May be NULL.
  */
@@ -262,6 +273,21 @@ OGRCurve *OGRCurvePolygon::getInteriorRingCurve( int iRing )
     return oCC.getCurve(iRing + 1);
 }
 
+/**
+ * \brief Fetch reference to indicated internal ring.
+ *
+ * Note that the returned ring pointer is to an internal data object of the
+ * OGRCurvePolygon.  It should not be modified or deleted by the application,
+ * and the pointer is only valid till the polygon is next modified.  Use the
+ * OGRGeometry::clone() method to make a separate copy within the application.
+ *
+ * Relates to the SFCOM IPolygon::get_InternalRing() method.
+ *
+ * @param iRing internal ring index from 0 to getNumInteriorRings() - 1.
+ *
+ * @return pointer to interior ring.  May be NULL.
+ */
+
 const OGRCurve *OGRCurvePolygon::getInteriorRingCurve( int iRing ) const
 
 {
@@ -278,7 +304,8 @@ const OGRCurve *OGRCurvePolygon::getInteriorRingCurve( int iRing ) const
  * After the call to that function, only call to stealInteriorRing() or
  * destruction of the OGRCurvePolygon is valid. Other operations may crash.
  *
- * @return pointer to external ring.  May be NULL if the OGRCurvePolygon is empty.
+ * @return pointer to external ring.  May be NULL if the OGRCurvePolygon is
+ * empty.
  */
 
 OGRCurve *OGRCurvePolygon::stealExteriorRingCurve()
@@ -311,7 +338,7 @@ OGRCurve *OGRCurvePolygon::stealExteriorRingCurve()
 OGRErr OGRCurvePolygon::addRing( OGRCurve * poNewRing )
 
 {
-    OGRCurve* poNewRingCloned = (OGRCurve* )poNewRing->clone();
+    OGRCurve* poNewRingCloned = dynamic_cast<OGRCurve *>(poNewRing->clone());
     if( poNewRingCloned == NULL )
         return OGRERR_FAILURE;
     OGRErr eErr = addRingDirectly(poNewRingCloned);
@@ -334,7 +361,7 @@ int OGRCurvePolygon::checkRing( OGRCurve * poNewRing ) const
 
     if( wkbFlatten(poNewRing->getGeometryType()) == wkbLineString )
     {
-        if( poNewRing->getNumPoints() == 0 || poNewRing->getNumPoints() < 4 )
+        if( poNewRing->getNumPoints() < 4 )
         {
             return FALSE;
         }
@@ -395,13 +422,19 @@ int OGRCurvePolygon::WkbSize() const
 }
 
 /************************************************************************/
-/*                       addCurveDirectlyFromWkt()                      */
+/*                       addCurveDirectlyFromWkb()                      */
 /************************************************************************/
 
 OGRErr OGRCurvePolygon::addCurveDirectlyFromWkb( OGRGeometry* poSelf,
                                                  OGRCurve* poCurve )
 {
-    OGRCurvePolygon* poCP = (OGRCurvePolygon*)poSelf;
+    OGRCurvePolygon* poCP = dynamic_cast<OGRCurvePolygon *>(poSelf);
+    if( poCP == NULL )
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRCurvePolygon.");
+        return OGRERR_FAILURE;
+    }
     return poCP->addRingDirectlyInternal( poCurve, FALSE );
 }
 
@@ -419,14 +452,15 @@ OGRErr OGRCurvePolygon::importFromWkb( unsigned char * pabyData,
 {
     OGRwkbByteOrder eByteOrder;
     int nDataOffset = 0;
-    /* coverity[tainted_data] */
+    // coverity[tainted_data]
     OGRErr eErr = oCC.importPreambuleFromWkb(this, pabyData, nSize, nDataOffset,
                                              eByteOrder, 9, eWkbVariant);
     if( eErr != OGRERR_NONE )
         return eErr;
 
     return oCC.importBodyFromWkb(this, pabyData, nSize, nDataOffset,
-                                 TRUE /* bAcceptCompoundCurve */, addCurveDirectlyFromWkb,
+                                 TRUE,  // bAcceptCompoundCurve
+                                 addCurveDirectlyFromWkb,
                                  eWkbVariant);
 }
 
@@ -436,12 +470,13 @@ OGRErr OGRCurvePolygon::importFromWkb( unsigned char * pabyData,
 /*      Build a well known binary representation of this object.        */
 /************************************************************************/
 
-OGRErr  OGRCurvePolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
-                                      unsigned char * pabyData,
-                                      OGRwkbVariant eWkbVariant ) const
+OGRErr OGRCurvePolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
+                                     unsigned char * pabyData,
+                                     OGRwkbVariant eWkbVariant ) const
 
 {
-    if( eWkbVariant == wkbVariantOldOgc ) /* does not make sense for new geometries, so patch it */
+    if( eWkbVariant == wkbVariantOldOgc )
+        // Does not make sense for new geometries, so patch it.
         eWkbVariant = wkbVariantIso;
     return oCC.exportToWkb(this, eByteOrder, pabyData, eWkbVariant);
 }
@@ -450,9 +485,17 @@ OGRErr  OGRCurvePolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
 /*                       addCurveDirectlyFromWkt()                      */
 /************************************************************************/
 
-OGRErr OGRCurvePolygon::addCurveDirectlyFromWkt( OGRGeometry* poSelf, OGRCurve* poCurve )
+OGRErr OGRCurvePolygon::addCurveDirectlyFromWkt( OGRGeometry* poSelf,
+                                                 OGRCurve* poCurve )
 {
-    return ((OGRCurvePolygon*)poSelf)->addRingDirectly(poCurve);
+    OGRCurvePolygon *poCP = dynamic_cast<OGRCurvePolygon *>(poSelf);
+    if( poCP == NULL )
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRCurvePolygon.");
+        return OGRERR_FAILURE;
+    }
+    return poCP->addRingDirectly(poCurve);
 }
 
 /************************************************************************/
@@ -465,10 +508,10 @@ OGRErr OGRCurvePolygon::importFromWkt( char ** ppszInput )
 
 {
     return importCurveCollectionFromWkt( ppszInput,
-                                         FALSE, /* bAllowEmptyComponent */
-                                         TRUE, /* bAllowLineString */
-                                         TRUE, /* bAllowCurve */
-                                         TRUE, /* bAllowCompoundCurve */
+                                         FALSE,  // bAllowEmptyComponent
+                                         TRUE,  // bAllowLineString
+                                         TRUE,  // bAllowCurve
+                                         TRUE,  // bAllowCompoundCurve
                                          addCurveDirectlyFromWkt );
 }
 
@@ -476,8 +519,9 @@ OGRErr OGRCurvePolygon::importFromWkt( char ** ppszInput )
 /*                            exportToWkt()                             */
 /************************************************************************/
 
-OGRErr OGRCurvePolygon::exportToWkt( char ** ppszDstText,
-                                CPL_UNUSED OGRwkbVariant eWkbVariant ) const
+OGRErr
+OGRCurvePolygon::exportToWkt( char ** ppszDstText,
+                              OGRwkbVariant /* eWkbVariant */ ) const
 
 {
     return oCC.exportToWkt(this, ppszDstText);
@@ -492,7 +536,8 @@ OGRErr OGRCurvePolygon::exportToWkt( char ** ppszDstText,
  *
  * This method is the same as C function OGR_G_CurvePolyToPoly().
  *
- * The returned geometry is a new instance whose ownership belongs to the caller.
+ * The returned geometry is a new instance whose ownership belongs to
+ * the caller.
  *
  * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
  * arc, zero to use the default setting.
@@ -504,15 +549,17 @@ OGRErr OGRCurvePolygon::exportToWkt( char ** ppszDstText,
  * @since OGR 2.0
  */
 
-OGRPolygon* OGRCurvePolygon::CurvePolyToPoly(double dfMaxAngleStepSizeDegrees,
-                                             const char* const* papszOptions) const
+OGRPolygon *
+OGRCurvePolygon::CurvePolyToPoly( double dfMaxAngleStepSizeDegrees,
+                                  const char* const* papszOptions ) const
 {
     OGRPolygon* poPoly = new OGRPolygon();
     poPoly->assignSpatialReference(getSpatialReference());
     for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
     {
-        OGRLineString* poLS = oCC.papoCurves[iRing]->CurveToLine(dfMaxAngleStepSizeDegrees,
-                                                                 papszOptions);
+        OGRLineString* poLS =
+            oCC.papoCurves[iRing]->CurveToLine(dfMaxAngleStepSizeDegrees,
+                                               papszOptions);
         poPoly->addRingDirectly(OGRCurve::CastToLinearRing(poLS));
     }
     return poPoly;
@@ -522,22 +569,23 @@ OGRPolygon* OGRCurvePolygon::CurvePolyToPoly(double dfMaxAngleStepSizeDegrees,
 /*                         hasCurveGeometry()                           */
 /************************************************************************/
 
-OGRBoolean OGRCurvePolygon::hasCurveGeometry(int bLookForNonLinear) const
+OGRBoolean OGRCurvePolygon::hasCurveGeometry( int bLookForNonLinear ) const
 {
     if( bLookForNonLinear )
     {
         return oCC.hasCurveGeometry(bLookForNonLinear);
     }
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
 /*                         getLinearGeometry()                        */
 /************************************************************************/
 
-OGRGeometry* OGRCurvePolygon::getLinearGeometry(double dfMaxAngleStepSizeDegrees,
-                                                  const char* const* papszOptions) const
+OGRGeometry *
+OGRCurvePolygon::getLinearGeometry( double dfMaxAngleStepSizeDegrees,
+                                    const char* const* papszOptions ) const
 {
     return CurvePolyToPoly(dfMaxAngleStepSizeDegrees, papszOptions);
 }
@@ -573,7 +621,7 @@ void OGRCurvePolygon::getEnvelope( OGREnvelope3D * psEnvelope ) const
 }
 
 /************************************************************************/
-/*                               Equal()                                */
+/*                               Equals()                               */
 /************************************************************************/
 
 OGRBoolean OGRCurvePolygon::Equals( OGRGeometry * poOther ) const
@@ -585,10 +633,16 @@ OGRBoolean OGRCurvePolygon::Equals( OGRGeometry * poOther ) const
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
-    if ( IsEmpty() && poOther->IsEmpty() )
+    if( IsEmpty() && poOther->IsEmpty() )
         return TRUE;
 
-    OGRCurvePolygon *poOPoly = (OGRCurvePolygon *) poOther;
+    OGRCurvePolygon *poOPoly = dynamic_cast<OGRCurvePolygon *>(poOther);
+    if( poOPoly == NULL )
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRCurvePolygon.");
+        return FALSE;
+    }
     return oCC.Equals( &(poOPoly->oCC) );
 }
 
@@ -609,18 +663,14 @@ OGRErr OGRCurvePolygon::transform( OGRCoordinateTransformation *poCT )
 double OGRCurvePolygon::get_Area() const
 
 {
-    double dfArea = 0.0;
-
-    if( getExteriorRingCurve() != NULL )
-    {
-        int iRing;
+    if( getExteriorRingCurve() == NULL )
+        return 0.0;
 
-        dfArea = getExteriorRingCurve()->get_Area();
+    double dfArea = getExteriorRingCurve()->get_Area();
 
-        for( iRing = 0; iRing < getNumInteriorRings(); iRing++ )
-        {
-            dfArea -= getInteriorRingCurve(iRing)->get_Area();
-        }
+    for( int iRing = 0; iRing < getNumInteriorRings(); iRing++ )
+    {
+        dfArea -= getInteriorRingCurve(iRing)->get_Area();
     }
 
     return dfArea;
@@ -650,7 +700,7 @@ void OGRCurvePolygon::setMeasured( OGRBoolean bIsMeasured )
 /*                               IsEmpty()                              */
 /************************************************************************/
 
-OGRBoolean OGRCurvePolygon::IsEmpty(  ) const
+OGRBoolean OGRCurvePolygon::IsEmpty() const
 {
     return oCC.IsEmpty();
 }
@@ -661,6 +711,11 @@ OGRBoolean OGRCurvePolygon::IsEmpty(  ) const
 
 void OGRCurvePolygon::segmentize( double dfMaxLength )
 {
+    if (EQUAL(getGeometryName(), "TRIANGLE"))
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "segmentize() is not valid for Triangle");
+        return;
+    }
     oCC.segmentize(dfMaxLength);
 }
 
@@ -682,10 +737,11 @@ OGRBoolean OGRCurvePolygon::ContainsPoint( const OGRPoint* p ) const
     if( getExteriorRingCurve() != NULL &&
         getNumInteriorRings() == 0 )
     {
-        int nRet = getExteriorRingCurve()->ContainsPoint(p);
+        const int nRet = getExteriorRingCurve()->ContainsPoint(p);
         if( nRet >= 0 )
             return nRet;
     }
+
     return OGRGeometry::Contains(p);
 }
 
@@ -699,10 +755,17 @@ OGRBoolean OGRCurvePolygon::Contains( const OGRGeometry *poOtherGeom ) const
     if( !IsEmpty() && poOtherGeom != NULL &&
         wkbFlatten(poOtherGeom->getGeometryType()) == wkbPoint )
     {
-        return ContainsPoint((OGRPoint*)poOtherGeom);
+        const OGRPoint *poPoint = dynamic_cast<const OGRPoint *>(poOtherGeom);
+        if( poPoint == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPoint.");
+            return FALSE;
+        }
+        return ContainsPoint(poPoint);
     }
-    else
-        return OGRGeometry::Contains(poOtherGeom);
+
+    return OGRGeometry::Contains(poOtherGeom);
 }
 
 /************************************************************************/
@@ -715,10 +778,17 @@ OGRBoolean OGRCurvePolygon::Intersects( const OGRGeometry *poOtherGeom ) const
     if( !IsEmpty() && poOtherGeom != NULL &&
         wkbFlatten(poOtherGeom->getGeometryType()) == wkbPoint )
     {
-        return ContainsPoint((OGRPoint*)poOtherGeom);
+        const OGRPoint *poPoint = dynamic_cast<const OGRPoint *>(poOtherGeom);
+        if( poPoint == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPoint.");
+            return FALSE;
+        }
+        return ContainsPoint(poPoint);
     }
-    else
-        return OGRGeometry::Intersects(poOtherGeom);
+
+    return OGRGeometry::Intersects(poOtherGeom);
 }
 
 /************************************************************************/
@@ -742,9 +812,10 @@ OGRBoolean OGRCurvePolygon::Intersects( const OGRGeometry *poOtherGeom ) const
 
 OGRPolygon* OGRCurvePolygon::CastToPolygon(OGRCurvePolygon* poCP)
 {
-    for(int i=0;i<poCP->oCC.nCurveCount;i++)
+    for( int i = 0; i < poCP->oCC.nCurveCount; i++ )
     {
-        poCP->oCC.papoCurves[i] = OGRCurve::CastToLinearRing(poCP->oCC.papoCurves[i]);
+        poCP->oCC.papoCurves[i] =
+            OGRCurve::CastToLinearRing(poCP->oCC.papoCurves[i]);
         if( poCP->oCC.papoCurves[i] == NULL )
         {
             delete poCP;
@@ -762,18 +833,22 @@ OGRPolygon* OGRCurvePolygon::CastToPolygon(OGRCurvePolygon* poCP)
     return poPoly;
 }
 
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                      GetCasterToPolygon()                            */
 /************************************************************************/
 
-OGRSurfaceCasterToPolygon OGRCurvePolygon::GetCasterToPolygon() const {
+OGRSurfaceCasterToPolygon OGRCurvePolygon::GetCasterToPolygon() const
+{
     return (OGRSurfaceCasterToPolygon) OGRCurvePolygon::CastToPolygon;
 }
 
 /************************************************************************/
-/*                      OGRSurfaceCasterToCurvePolygon()                */
+/*                      GetCasterToCurvePolygon()                       */
 /************************************************************************/
 
-OGRSurfaceCasterToCurvePolygon OGRCurvePolygon::GetCasterToCurvePolygon() const {
+OGRSurfaceCasterToCurvePolygon OGRCurvePolygon::GetCasterToCurvePolygon() const
+{
     return (OGRSurfaceCasterToCurvePolygon) OGRGeometry::CastToIdentity;
 }
+//! @endcond
diff --git a/ogr/ogrfeature.cpp b/ogr/ogrfeature.cpp
index 40beeaa..7a41bc0 100644
--- a/ogr/ogrfeature.cpp
+++ b/ogr/ogrfeature.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfeature.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFeature class implementation.
@@ -28,15 +27,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_feature.h"
+#include "cpl_port.h"
 #include "ogr_api.h"
-#include "ogr_p.h"
-#include "cpl_time.h"
-#include <vector>
-#include <errno.h>
+#include "ogr_feature.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+
 #include <new>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_time.h"
+#include "cpl_vsi.h"
+#include "ogr_core.h"
+#include "ogr_featurestyle.h"
+#include "ogr_geometry.h"
+#include "ogr_p.h"
+#include "ogrgeojsonreader.h"
+
+#include "ogr_json_header.h"
 
-CPL_CVSID("$Id: ogrfeature.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrfeature.cpp 37471 2017-02-26 02:25:37Z goatbar $");
 
 /************************************************************************/
 /*                             OGRFeature()                             */
@@ -57,29 +75,31 @@ CPL_CVSID("$Id: ogrfeature.cpp 33631 2016-03-04 06:28:09Z goatbar $");
  */
 
 OGRFeature::OGRFeature( OGRFeatureDefn * poDefnIn ) :
-            nFID(OGRNullFID),
-            poDefn(poDefnIn),
-            m_pszNativeData(NULL),
-            m_pszNativeMediaType(NULL),
-            m_pszStyleString(NULL),
-            m_poStyleTable(NULL),
-            m_pszTmpFieldValue(NULL)
+    nFID(OGRNullFID),
+    poDefn(poDefnIn),
+    papoGeometries(NULL),
+    pauFields(NULL),
+    m_pszNativeData(NULL),
+    m_pszNativeMediaType(NULL),
+    m_pszStyleString(NULL),
+    m_poStyleTable(NULL),
+    m_pszTmpFieldValue(NULL)
 {
     poDefnIn->Reference();
 
-    // Allocate array of fields and initialize them to the unset special value
-    pauFields = (OGRField *) VSI_MALLOC_VERBOSE( poDefn->GetFieldCount() *
-                                        sizeof(OGRField) );
+    pauFields = static_cast<OGRField *>(
+        VSI_MALLOC_VERBOSE(poDefn->GetFieldCount() * sizeof(OGRField)));
 
-    papoGeometries = (OGRGeometry **) VSI_CALLOC_VERBOSE( poDefn->GetGeomFieldCount(),
-                                        sizeof(OGRGeometry*) );
+    papoGeometries = static_cast<OGRGeometry **>(
+        VSI_CALLOC_VERBOSE(poDefn->GetGeomFieldCount(),
+                           sizeof(OGRGeometry*)));
 
+    // Initialize array to the unset special value.
     if( pauFields != NULL )
     {
         for( int i = 0; i < poDefn->GetFieldCount(); i++ )
         {
-            pauFields[i].Set.nMarker1 = OGRUnsetMarker;
-            pauFields[i].Set.nMarker2 = OGRUnsetMarker;
+            OGR_RawField_SetUnset(&pauFields[i]);
         }
     }
 }
@@ -100,15 +120,16 @@ OGRFeature::OGRFeature( OGRFeatureDefn * poDefnIn ) :
  * @param hDefn handle to the feature class (layer) definition to
  * which the feature will adhere.
  *
- * @return an handle to the new feature object with null fields and
- * no geometry, or, starting with GDAL 2.1, NULL in case out of memory situation.
+ * @return an handle to the new feature object with null fields and no geometry,
+ * or, starting with GDAL 2.1, NULL in case out of memory situation.
  */
 
 OGRFeatureH OGR_F_Create( OGRFeatureDefnH hDefn )
 
 {
     VALIDATE_POINTER1( hDefn, "OGR_F_Create", NULL );
-    return (OGRFeatureH) OGRFeature::CreateFeature( (OGRFeatureDefn*) hDefn );
+    return reinterpret_cast<OGRFeatureH>(
+        OGRFeature::CreateFeature(reinterpret_cast<OGRFeatureDefn *>(hDefn)));
 }
 
 /************************************************************************/
@@ -118,58 +139,63 @@ OGRFeatureH OGR_F_Create( OGRFeatureDefnH hDefn )
 OGRFeature::~OGRFeature()
 
 {
-    int i;
-
-    int nFieldcount = ( pauFields != NULL ) ? poDefn->GetFieldCount() : 0;
-    for( i = 0; i < nFieldcount; i++ )
+    if( pauFields != NULL )
     {
-        OGRFieldDefn    *poFDefn = poDefn->GetFieldDefn(i);
+        const int nFieldcount = poDefn->GetFieldCount();
+        for( int i = 0; i < nFieldcount; i++ )
+        {
+            OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(i);
 
-        if( !IsFieldSet(i) )
-            continue;
+            if( !IsFieldSetAndNotNull(i) )
+                continue;
 
-        switch( poFDefn->GetType() )
-        {
-          case OFTString:
-            if( pauFields[i].String != NULL )
-                VSIFree( pauFields[i].String );
-            break;
+            switch( poFDefn->GetType() )
+            {
+              case OFTString:
+                if( pauFields[i].String != NULL )
+                    VSIFree( pauFields[i].String );
+                break;
 
-          case OFTBinary:
-            if( pauFields[i].Binary.paData != NULL )
-                VSIFree( pauFields[i].Binary.paData );
-            break;
+              case OFTBinary:
+                if( pauFields[i].Binary.paData != NULL )
+                    VSIFree( pauFields[i].Binary.paData );
+                break;
 
-          case OFTStringList:
-            CSLDestroy( pauFields[i].StringList.paList );
-            break;
+              case OFTStringList:
+                CSLDestroy( pauFields[i].StringList.paList );
+                break;
 
-          case OFTIntegerList:
-          case OFTInteger64List:
-          case OFTRealList:
-            CPLFree( pauFields[i].IntegerList.paList );
-            break;
+              case OFTIntegerList:
+              case OFTInteger64List:
+              case OFTRealList:
+                CPLFree( pauFields[i].IntegerList.paList );
+                break;
 
-          default:
-            // should add support for wide strings.
-            break;
+              default:
+                // TODO(schwehr): Add support for wide strings.
+                break;
+            }
         }
     }
 
-    int nGeomFieldCount = (papoGeometries != NULL) ? poDefn->GetGeomFieldCount() : 0;
-    for( i = 0; i < nGeomFieldCount; i++ )
+    if( papoGeometries != NULL )
     {
-        delete papoGeometries[i];
+        const int nGeomFieldCount = poDefn->GetGeomFieldCount();
+
+        for( int i = 0; i < nGeomFieldCount; i++ )
+        {
+            delete papoGeometries[i];
+        }
     }
 
     poDefn->Release();
 
-    CPLFree( pauFields );
-    CPLFree( papoGeometries );
+    CPLFree(pauFields);
+    CPLFree(papoGeometries);
     CPLFree(m_pszStyleString);
     CPLFree(m_pszTmpFieldValue);
-    CPLFree( m_pszNativeData );
-    CPLFree( m_pszNativeMediaType );
+    CPLFree(m_pszNativeData);
+    CPLFree(m_pszNativeMediaType);
 }
 
 /************************************************************************/
@@ -192,7 +218,7 @@ OGRFeature::~OGRFeature()
 void OGR_F_Destroy( OGRFeatureH hFeat )
 
 {
-    delete (OGRFeature *) hFeat;
+    delete reinterpret_cast<OGRFeature *>(hFeat);
 }
 
 /************************************************************************/
@@ -210,9 +236,9 @@ void OGR_F_Destroy( OGRFeatureH hFeat )
  *
  * @param poDefn Feature definition defining schema.
  *
- * @return new feature object with null fields and no geometry, or, starting with
- * GDAL 2.1, NULL in case of out of memory situation.  May be
- * deleted with DestroyFeature().
+ * @return new feature object with null fields and no geometry, or, starting
+ * with GDAL 2.1, NULL in case of out of memory situation.  May be deleted with
+ * DestroyFeature().
  */
 
 OGRFeature *OGRFeature::CreateFeature( OGRFeatureDefn *poDefn )
@@ -221,12 +247,15 @@ OGRFeature *OGRFeature::CreateFeature( OGRFeatureDefn *poDefn )
     OGRFeature* poFeature = new (std::nothrow) OGRFeature( poDefn );
     if( poFeature == NULL )
         return NULL;
+
     if( (poFeature->pauFields == NULL && poDefn->GetFieldCount() != 0) ||
-        (poFeature->papoGeometries == NULL && poDefn->GetGeomFieldCount() != 0) )
+        (poFeature->papoGeometries == NULL &&
+         poDefn->GetGeomFieldCount() != 0) )
     {
         delete poFeature;
         return NULL;
     }
+
     return poFeature;
 }
 
@@ -288,7 +317,8 @@ OGRFeatureDefnH OGR_F_GetDefnRef( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetDefnRef", NULL );
 
-    return (OGRFeatureDefnH) ((OGRFeature *) hFeat)->GetDefnRef();
+    return reinterpret_cast<OGRFeatureDefnH>(
+        reinterpret_cast<OGRFeature *>(hFeat)->GetDefnRef());
 }
 
 /************************************************************************/
@@ -304,6 +334,11 @@ OGRFeatureDefnH OGR_F_GetDefnRef( OGRFeatureH hFeat )
  *
  * This method is the same as the C function OGR_F_SetGeometryDirectly().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param poGeomIn new geometry to apply to feature. Passing NULL value here
  * is correct and it will result in deallocation of currently assigned geometry
  * without assigning new one.
@@ -318,11 +353,9 @@ OGRErr OGRFeature::SetGeometryDirectly( OGRGeometry * poGeomIn )
 {
     if( GetGeomFieldCount() > 0 )
         return SetGeomFieldDirectly(0, poGeomIn);
-    else
-    {
-        delete poGeomIn;
-        return OGRERR_FAILURE;
-    }
+
+    delete poGeomIn;
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -339,6 +372,11 @@ OGRErr OGRFeature::SetGeometryDirectly( OGRGeometry * poGeomIn )
  * This function is the same as the C++ method
  * OGRFeature::SetGeometryDirectly.
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature on which to apply the geometry.
  * @param hGeom handle to the new geometry to apply to feature.
  *
@@ -352,7 +390,8 @@ OGRErr OGR_F_SetGeometryDirectly( OGRFeatureH hFeat, OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_SetGeometryDirectly", OGRERR_FAILURE );
 
-    return ((OGRFeature *) hFeat)->SetGeometryDirectly((OGRGeometry *) hGeom);
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        SetGeometryDirectly(reinterpret_cast<OGRGeometry *>(hGeom));
 }
 
 /************************************************************************/
@@ -368,6 +407,11 @@ OGRErr OGR_F_SetGeometryDirectly( OGRFeatureH hFeat, OGRGeometryH hGeom )
  *
  * This method is the same as the C function OGR_F_SetGeometry().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param poGeomIn new geometry to apply to feature. Passing NULL value here
  * is correct and it will result in deallocation of currently assigned geometry
  * without assigning new one.
@@ -377,13 +421,13 @@ OGRErr OGR_F_SetGeometryDirectly( OGRFeatureH hFeat, OGRGeometryH hGeom )
  * implemented).
  */
 
-OGRErr OGRFeature::SetGeometry( OGRGeometry * poGeomIn )
+OGRErr OGRFeature::SetGeometry( const OGRGeometry * poGeomIn )
 
 {
-    if( GetGeomFieldCount() > 0 )
-        return SetGeomField(0, poGeomIn);
-    else
+    if( GetGeomFieldCount() < 1 )
         return OGRERR_FAILURE;
+
+    return SetGeomField(0, poGeomIn);
 }
 
 /************************************************************************/
@@ -399,6 +443,11 @@ OGRErr OGRFeature::SetGeometry( OGRGeometry * poGeomIn )
  *
  * This function is the same as the C++ OGRFeature::SetGeometry().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature on which new geometry is applied to.
  * @param hGeom handle to the new geometry to apply to feature.
  *
@@ -412,7 +461,8 @@ OGRErr OGR_F_SetGeometry( OGRFeatureH hFeat, OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_SetGeometry", OGRERR_FAILURE );
 
-    return ((OGRFeature *) hFeat)->SetGeometry((OGRGeometry *) hGeom);
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        SetGeometry(reinterpret_cast<OGRGeometry *>(hGeom));
 }
 
 /************************************************************************/
@@ -441,11 +491,26 @@ OGRGeometry *OGRFeature::StealGeometry()
         papoGeometries[0] = NULL;
         return poReturn;
     }
-    else
-        return NULL;
+
+    return NULL;
 }
 
-OGRGeometry *OGRFeature::StealGeometry(int iGeomField)
+/**
+ * \brief Take away ownership of geometry.
+ *
+ * Fetch the geometry from this feature, and clear the reference to the
+ * geometry on the feature.  This is a mechanism for the application to
+ * take over ownership of the geometry from the feature without copying.
+ * Sort of an inverse to SetGeometryDirectly().
+ *
+ * After this call the OGRFeature will have a NULL geometry.
+ *
+ * @param iGeomField index of the geometry field.
+ *
+ * @return the pointer to the geometry.
+ */
+
+OGRGeometry *OGRFeature::StealGeometry( int iGeomField )
 
 {
     if( iGeomField >= 0 && iGeomField < GetGeomFieldCount() )
@@ -454,8 +519,8 @@ OGRGeometry *OGRFeature::StealGeometry(int iGeomField)
         papoGeometries[iGeomField] = NULL;
         return poReturn;
     }
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -480,7 +545,8 @@ OGRGeometryH OGR_F_StealGeometry( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_StealGeometry", NULL );
 
-    return (OGRGeometryH) ((OGRFeature *) hFeat)->StealGeometry();
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRFeature *>(hFeat)->StealGeometry());
 }
 
 /************************************************************************/
@@ -505,8 +571,8 @@ OGRGeometry *OGRFeature::GetGeometryRef()
 {
     if( GetGeomFieldCount() > 0 )
         return GetGeomFieldRef(0);
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -528,22 +594,23 @@ OGRGeometryH OGR_F_GetGeometryRef( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetGeometryRef", NULL );
 
-    OGRFeature* poFeature = (OGRFeature *) hFeat;
+    OGRFeature* poFeature = reinterpret_cast<OGRFeature *>(hFeat);
     OGRGeometry* poGeom = poFeature->GetGeometryRef();
 
     if( !OGRGetNonLinearGeometriesEnabledFlag() && poGeom != NULL &&
         OGR_GT_IsNonLinear(poGeom->getGeometryType()) )
     {
-        OGRwkbGeometryType eTargetType = OGR_GT_GetLinear(poGeom->getGeometryType());
-        poGeom = OGRGeometryFactory::forceTo(poFeature->StealGeometry(), eTargetType);
+        const OGRwkbGeometryType eTargetType =
+            OGR_GT_GetLinear(poGeom->getGeometryType());
+        poGeom = OGRGeometryFactory::forceTo(poFeature->StealGeometry(),
+                                             eTargetType);
         poFeature->SetGeomFieldDirectly(0, poGeom);
         poGeom = poFeature->GetGeometryRef();
     }
 
-    return (OGRGeometryH)poGeom;
+    return reinterpret_cast<OGRGeometryH>(poGeom);
 }
 
-
 /************************************************************************/
 /*                           GetGeomFieldRef()                          */
 /************************************************************************/
@@ -560,7 +627,7 @@ OGRGeometryH OGR_F_GetGeometryRef( OGRFeatureH hFeat )
  *
  * @since GDAL 1.11
  */
-OGRGeometry *OGRFeature::GetGeomFieldRef(int iField)
+OGRGeometry *OGRFeature::GetGeomFieldRef( int iField )
 
 {
     if( iField < 0 || iField >= GetGeomFieldCount() )
@@ -583,14 +650,14 @@ OGRGeometry *OGRFeature::GetGeomFieldRef(int iField)
  *
  * @since GDAL 1.11
  */
-OGRGeometry *OGRFeature::GetGeomFieldRef(const char* pszFName)
+OGRGeometry *OGRFeature::GetGeomFieldRef( const char* pszFName )
 
 {
-    int iField = GetGeomFieldIndex(pszFName);
+    const int iField = GetGeomFieldIndex(pszFName);
     if( iField < 0 )
         return NULL;
-    else
-        return papoGeometries[iField];
+
+    return papoGeometries[iField];
 }
 
 /************************************************************************/
@@ -615,19 +682,21 @@ OGRGeometryH OGR_F_GetGeomFieldRef( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetGeomFieldRef", NULL );
 
-    OGRFeature* poFeature = (OGRFeature *) hFeat;
+    OGRFeature* poFeature = reinterpret_cast<OGRFeature *>(hFeat);
     OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iField);
 
     if( !OGRGetNonLinearGeometriesEnabledFlag() && poGeom != NULL &&
         OGR_GT_IsNonLinear(poGeom->getGeometryType()) )
     {
-        OGRwkbGeometryType eTargetType = OGR_GT_GetLinear(poGeom->getGeometryType());
-        poGeom = OGRGeometryFactory::forceTo(poFeature->StealGeometry(iField), eTargetType);
+        const OGRwkbGeometryType eTargetType =
+            OGR_GT_GetLinear(poGeom->getGeometryType());
+        poGeom = OGRGeometryFactory::forceTo(poFeature->StealGeometry(iField),
+                                             eTargetType);
         poFeature->SetGeomFieldDirectly(iField, poGeom);
         poGeom = poFeature->GetGeomFieldRef(iField);
     }
 
-    return (OGRGeometryH)poGeom;
+    return reinterpret_cast<OGRGeometryH>(poGeom);
 }
 
 /************************************************************************/
@@ -664,40 +733,6 @@ OGRErr OGRFeature::SetGeomFieldDirectly( int iField, OGRGeometry * poGeomIn )
         return OGRERR_FAILURE;
     }
 
-    /*
-    // (Verify the type) and set/unset flags.
-    OGRwkbGeometryType eMyGeomType = poDefn->GetGeomFieldDefn(iField)->GetType();
-
-    if( eMyGeomType != wkbUnknown )
-    {
-        OGRwkbGeometryType eGeomInType = poGeomIn->getGeometryType();
-
-          This leads to segfaults in tests probably because issues with simple vs multi geometries
-          if( wkbFlatten(eGeomInType) != wkbFlatten(eMyGeomType) )
-          {
-          delete poGeomIn;
-          return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
-          }
-
-        if( wkbHasZ(eMyGeomType) && !wkbHasZ(eGeomInType) )
-        {
-            poGeomIn->set3D(TRUE);
-        }
-        else if( !wkbHasZ(eMyGeomType) && wkbHasZ(eGeomInType) )
-        {
-            poGeomIn->set3D(FALSE);
-        }
-        if( wkbHasM(eMyGeomType) && !wkbHasM(eGeomInType) )
-        {
-            poGeomIn->setMeasured(TRUE);
-        }
-        else if( !wkbHasM(eMyGeomType) && wkbHasM(eGeomInType) )
-        {
-            poGeomIn->setMeasured(FALSE);
-        }
-    }
-    */
-
     if( papoGeometries[iField] != poGeomIn )
     {
         delete papoGeometries[iField];
@@ -738,8 +773,8 @@ OGRErr OGR_F_SetGeomFieldDirectly( OGRFeatureH hFeat, int iField,
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_SetGeomFieldDirectly", OGRERR_FAILURE );
 
-    return ((OGRFeature *) hFeat)->SetGeomFieldDirectly(iField,
-                                                        (OGRGeometry *) hGeom);
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        SetGeomFieldDirectly(iField, reinterpret_cast<OGRGeometry *>(hGeom));
 }
 
 /************************************************************************/
@@ -767,7 +802,7 @@ OGRErr OGR_F_SetGeomFieldDirectly( OGRFeatureH hFeat, int iField,
  * @since GDAL 1.11
  */
 
-OGRErr OGRFeature::SetGeomField( int iField, OGRGeometry * poGeomIn )
+OGRErr OGRFeature::SetGeomField( int iField, const OGRGeometry * poGeomIn )
 
 {
     if( iField < 0 || iField >= GetGeomFieldCount() )
@@ -783,7 +818,7 @@ OGRErr OGRFeature::SetGeomField( int iField, OGRGeometry * poGeomIn )
             papoGeometries[iField] = NULL;
     }
 
-    // I should be verifying that the geometry matches the defn's type.
+    // TODO(schwehr): Verify that the geometry matches the defn's type.
 
     return OGRERR_NONE;
 }
@@ -815,7 +850,8 @@ OGRErr OGR_F_SetGeomField( OGRFeatureH hFeat, int iField, OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_SetGeomField", OGRERR_FAILURE );
 
-    return ((OGRFeature *) hFeat)->SetGeomField(iField, (OGRGeometry *) hGeom);
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        SetGeomField(iField, reinterpret_cast<OGRGeometry *>(hGeom));
 }
 
 /************************************************************************/
@@ -830,19 +866,18 @@ OGRErr OGR_F_SetGeomField( OGRFeatureH hFeat, int iField, OGRGeometryH hGeom )
  *
  * This method is the same as the C function OGR_F_Clone().
  *
- * @return new feature, exactly matching this feature. Or, starting with GDAL 2.1,
- *         NULL in case of out of memory situation.
+ * @return new feature, exactly matching this feature. Or, starting with GDAL
+ * 2.1, NULL in case of out of memory situation.
  */
 
 OGRFeature *OGRFeature::Clone()
 
 {
-    int i;
-    OGRFeature  *poNew = CreateFeature( poDefn );
+    OGRFeature *poNew = CreateFeature( poDefn );
     if( poNew == NULL )
         return NULL;
 
-    for( i = 0; i < poDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poDefn->GetFieldCount(); i++ )
     {
         if( !poNew->SetFieldInternal( i, pauFields + i ) )
         {
@@ -850,7 +885,7 @@ OGRFeature *OGRFeature::Clone()
             return NULL;
         }
     }
-    for( i = 0; i < poDefn->GetGeomFieldCount(); i++ )
+    for( int i = 0; i < poDefn->GetGeomFieldCount(); i++ )
     {
         if( papoGeometries[i] != NULL )
         {
@@ -919,7 +954,8 @@ OGRFeatureH OGR_F_Clone( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_Clone", NULL );
 
-    return (OGRFeatureH) ((OGRFeature *) hFeat)->Clone();
+    return reinterpret_cast<OGRFeatureH>(
+        reinterpret_cast<OGRFeature *>(hFeat)->Clone());
 }
 
 /************************************************************************/
@@ -927,7 +963,7 @@ OGRFeatureH OGR_F_Clone( OGRFeatureH hFeat )
 /************************************************************************/
 
 /**
- * \fn int OGRFeature::GetFieldCount();
+ * \fn int OGRFeature::GetFieldCount() const;
  *
  * \brief Fetch number of fields on this feature.
  * This will always be the same
@@ -958,7 +994,7 @@ int OGR_F_GetFieldCount( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldCount", 0 );
 
-    return ((OGRFeature *) hFeat)->GetFieldCount();
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetFieldCount();
 }
 
 /************************************************************************/
@@ -966,7 +1002,7 @@ int OGR_F_GetFieldCount( OGRFeatureH hFeat )
 /************************************************************************/
 
 /**
- * \fn OGRFieldDefn *OGRFeature::GetFieldDefnRef( int iField );
+ * \fn OGRFieldDefn *OGRFeature::GetFieldDefnRef( int iField ) const;
  *
  * \brief Fetch definition for this field.
  *
@@ -999,13 +1035,15 @@ OGRFieldDefnH OGR_F_GetFieldDefnRef( OGRFeatureH hFeat, int i )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldDefnRef", NULL );
 
-    if( i < 0 || i >= ((OGRFeature *) hFeat)->GetFieldCount() )
+    OGRFeature *poFeat = reinterpret_cast<OGRFeature *>(hFeat);
+
+    if( i < 0 || i >= poFeat->GetFieldCount() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", i);
         return NULL;
     }
 
-    return (OGRFieldDefnH) ((OGRFeature *) hFeat)->GetFieldDefnRef(i);
+    return reinterpret_cast<OGRFieldDefnH>(poFeat->GetFieldDefnRef(i));
 }
 
 /************************************************************************/
@@ -1048,16 +1086,15 @@ int OGR_F_GetFieldIndex( OGRFeatureH hFeat, const char *pszName )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldIndex", 0 );
 
-    return ((OGRFeature *) hFeat)->GetFieldIndex( pszName );
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetFieldIndex( pszName );
 }
 
-
 /************************************************************************/
 /*                         GetGeomFieldCount()                          */
 /************************************************************************/
 
 /**
- * \fn int OGRFeature::GetGeomFieldCount();
+ * \fn int OGRFeature::GetGeomFieldCount() const;
  *
  * \brief Fetch number of geometry fields on this feature.
  * This will always be the same
@@ -1092,7 +1129,7 @@ int OGR_F_GetGeomFieldCount( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetGeomFieldCount", 0 );
 
-    return ((OGRFeature *) hFeat)->GetGeomFieldCount();
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetGeomFieldCount();
 }
 
 /************************************************************************/
@@ -1121,7 +1158,8 @@ int OGR_F_GetGeomFieldCount( OGRFeatureH hFeat )
 /**
  * \brief Fetch definition for this geometry field.
  *
- * This function is the same as the C++ method OGRFeature::GetGeomFieldDefnRef().
+ * This function is the same as the C++ method
+ * OGRFeature::GetGeomFieldDefnRef().
  *
  * @param hFeat handle to the feature on which the field is found.
  * @param i the field to fetch, from 0 to GetGeomFieldCount()-1.
@@ -1137,7 +1175,8 @@ OGRGeomFieldDefnH OGR_F_GetGeomFieldDefnRef( OGRFeatureH hFeat, int i )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetGeomFieldDefnRef", NULL );
 
-    return (OGRGeomFieldDefnH) ((OGRFeature *) hFeat)->GetGeomFieldDefnRef(i);
+    return reinterpret_cast<OGRGeomFieldDefnH>(
+        reinterpret_cast<OGRFeature *>(hFeat)->GetGeomFieldDefnRef(i));
 }
 
 /************************************************************************/
@@ -1155,7 +1194,8 @@ OGRGeomFieldDefnH OGR_F_GetGeomFieldDefnRef( OGRFeatureH hFeat, int i )
  *
  * @param pszName the name of the geometry field to search for.
  *
- * @return the geometry field index, or -1 if no matching geometry field is found.
+ * @return the geometry field index, or -1 if no matching geometry field is
+ * found.
  *
  * @since GDAL 1.11
  */
@@ -1174,7 +1214,8 @@ OGRGeomFieldDefnH OGR_F_GetGeomFieldDefnRef( OGRFeatureH hFeat, int i )
  * @param hFeat handle to the feature on which the geometry field is found.
  * @param pszName the name of the geometry field to search for.
  *
- * @return the geometry field index, or -1 if no matching geometry field is found.
+ * @return the geometry field index, or -1 if no matching geometry field is
+ * found.
  *
  * @since GDAL 1.11
  */
@@ -1184,17 +1225,14 @@ int OGR_F_GetGeomFieldIndex( OGRFeatureH hFeat, const char *pszName )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetGeomFieldIndex", 0 );
 
-    return ((OGRFeature *) hFeat)->GetGeomFieldIndex( pszName );
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetGeomFieldIndex( pszName );
 }
 
-
 /************************************************************************/
 /*                             IsFieldSet()                             */
 /************************************************************************/
 
 /**
- * \fn int OGRFeature::IsFieldSet( int iField ) const;
- *
  * \brief Test if a field has ever been assigned a value or not.
  *
  * This method is the same as the C function OGR_F_IsFieldSet().
@@ -1207,27 +1245,28 @@ int OGR_F_GetGeomFieldIndex( OGRFeatureH hFeat, const char *pszName )
 int OGRFeature::IsFieldSet( int iField )
 
 {
-    int iSpecialField = iField - poDefn->GetFieldCount();
-    if (iSpecialField >= 0)
+    const int iSpecialField = iField - poDefn->GetFieldCount();
+    if( iSpecialField >= 0 )
     {
-        // special field value accessors
-        switch (iSpecialField)
+        // Special field value accessors.
+        switch( iSpecialField )
         {
           case SPF_FID:
-            return ((OGRFeature *)this)->GetFID() != OGRNullFID;
+            return GetFID() != OGRNullFID;
 
           case SPF_OGR_GEOM_WKT:
           case SPF_OGR_GEOMETRY:
             return GetGeomFieldCount() > 0 && papoGeometries[0] != NULL;
 
           case SPF_OGR_STYLE:
-            return ((OGRFeature *)this)->GetStyleString() != NULL;
+            return GetStyleString() != NULL;
 
           case SPF_OGR_GEOM_AREA:
             if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return FALSE;
 
-            return OGR_G_Area((OGRGeometryH)papoGeometries[0]) != 0.0;
+            return OGR_G_Area(
+                reinterpret_cast<OGRGeometryH>(papoGeometries[0])) != 0.0;
 
           default:
             return FALSE;
@@ -1235,8 +1274,7 @@ int OGRFeature::IsFieldSet( int iField )
     }
     else
     {
-        return pauFields[iField].Set.nMarker1 != OGRUnsetMarker
-            || pauFields[iField].Set.nMarker2 != OGRUnsetMarker;
+        return !OGR_RawField_IsUnset(&pauFields[iField]);
     }
 }
 
@@ -1260,9 +1298,9 @@ int OGR_F_IsFieldSet( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_IsFieldSet", 0 );
 
-    OGRFeature* poFeature = (OGRFeature* )hFeat;
+    OGRFeature* poFeature = reinterpret_cast<OGRFeature *>(hFeat);
 
-    if (iField < 0 || iField >= poFeature->GetFieldCount())
+    if( iField < 0 || iField >= poFeature->GetFieldCount() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
         return FALSE;
@@ -1286,37 +1324,39 @@ int OGR_F_IsFieldSet( OGRFeatureH hFeat, int iField )
 void OGRFeature::UnsetField( int iField )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL || !IsFieldSet(iField) )
         return;
 
-    switch( poFDefn->GetType() )
+    if( !IsFieldNull(iField) )
     {
-      case OFTRealList:
-      case OFTIntegerList:
-      case OFTInteger64List:
-        CPLFree( pauFields[iField].IntegerList.paList );
-        break;
+        switch( poFDefn->GetType() )
+        {
+            case OFTRealList:
+            case OFTIntegerList:
+            case OFTInteger64List:
+                CPLFree( pauFields[iField].IntegerList.paList );
+                break;
 
-      case OFTStringList:
-        CSLDestroy( pauFields[iField].StringList.paList );
-        break;
+            case OFTStringList:
+                CSLDestroy( pauFields[iField].StringList.paList );
+                break;
 
-      case OFTString:
-        CPLFree( pauFields[iField].String );
-        break;
+            case OFTString:
+                CPLFree( pauFields[iField].String );
+                break;
 
-      case OFTBinary:
-        CPLFree( pauFields[iField].Binary.paData );
-        break;
+            case OFTBinary:
+                CPLFree( pauFields[iField].Binary.paData );
+                break;
 
-      default:
-        break;
+            default:
+                break;
+        }
     }
 
-    pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-    pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+    OGR_RawField_SetUnset(&pauFields[iField]);
 }
 
 /************************************************************************/
@@ -1337,7 +1377,211 @@ void OGR_F_UnsetField( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_UnsetField" );
 
-    ((OGRFeature *) hFeat)->UnsetField( iField );
+    reinterpret_cast<OGRFeature *>(hFeat)->UnsetField( iField );
+}
+
+
+/************************************************************************/
+/*                            IsFieldNull()                             */
+/************************************************************************/
+
+/**
+ * \brief Test if a field is null.
+ *
+ * This method is the same as the C function OGR_F_IsFieldNull().
+ *
+ * @param iField the field to test.
+ *
+ * @return TRUE if the field is null, otherwise false.
+ *
+ * @since GDAL 2.2
+ */
+
+bool OGRFeature::IsFieldNull( int iField )
+
+{
+    const int iSpecialField = iField - poDefn->GetFieldCount();
+    if( iSpecialField >= 0 )
+    {
+        // FIXME?
+        return false;
+    }
+    else
+    {
+        return CPL_TO_BOOL(OGR_RawField_IsNull(&pauFields[iField]));
+    }
+}
+
+/************************************************************************/
+/*                          OGR_F_IsFieldNull()                         */
+/************************************************************************/
+
+/**
+ * \brief Test if a field is null.
+ *
+ * This function is the same as the C++ method OGRFeature::IsFieldNull().
+ *
+ * @param hFeat handle to the feature on which the field is.
+ * @param iField the field to test.
+ *
+ * @return TRUE if the field is null, otherwise false.
+*
+ * @since GDAL 2.2
+ */
+
+int OGR_F_IsFieldNull( OGRFeatureH hFeat, int iField )
+
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_IsFieldNull", 0 );
+
+    OGRFeature* poFeature = reinterpret_cast<OGRFeature *>(hFeat);
+
+    if( iField < 0 || iField >= poFeature->GetFieldCount() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
+        return FALSE;
+    }
+
+    return poFeature->IsFieldNull( iField );
+}
+
+/************************************************************************/
+/*                       IsFieldSetAndNull()                            */
+/************************************************************************/
+
+/**
+ * \brief Test if a field is set and not null.
+ *
+ * This method is the same as the C function OGR_F_IsFieldSetAndNotNull().
+ *
+ * @param iField the field to test.
+ *
+ * @return TRUE if the field is set and not null, otherwise false.
+ *
+ * @since GDAL 2.2
+ */
+
+bool OGRFeature::IsFieldSetAndNotNull( int iField )
+
+{
+    const int iSpecialField = iField - poDefn->GetFieldCount();
+    if( iSpecialField >= 0 )
+    {
+        return CPL_TO_BOOL(IsFieldSet(iField));
+    }
+    else
+    {
+        return !OGR_RawField_IsUnset(&pauFields[iField]) &&
+               !OGR_RawField_IsNull(&pauFields[iField]);
+    }
+}
+
+/************************************************************************/
+/*                      OGR_F_IsFieldSetAndNotNull()                    */
+/************************************************************************/
+
+/**
+ * \brief Test if a field is set and not null.
+ *
+ * This function is the same as the C++ method OGRFeature::IsFieldSetAndNotNull().
+ *
+ * @param hFeat handle to the feature on which the field is.
+ * @param iField the field to test.
+ *
+ * @return TRUE if the field is set and not null, otherwise false.
+*
+ * @since GDAL 2.2
+ */
+
+int OGR_F_IsFieldSetAndNotNull( OGRFeatureH hFeat, int iField )
+
+{
+    VALIDATE_POINTER1( hFeat, "OGR_F_IsFieldSetAndNotNull", 0 );
+
+    OGRFeature* poFeature = reinterpret_cast<OGRFeature *>(hFeat);
+
+    if( iField < 0 || iField >= poFeature->GetFieldCount() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid index : %d", iField);
+        return FALSE;
+    }
+
+    return poFeature->IsFieldSetAndNotNull( iField );
+}
+
+/************************************************************************/
+/*                             SetFieldNull()                           */
+/************************************************************************/
+
+/**
+ * \brief Clear a field, marking it as null.
+ *
+ * This method is the same as the C function OGR_F_SetFieldNull().
+ *
+ * @param iField the field to set to null.
+ *
+ * @since GDAL 2.2
+ */
+
+void OGRFeature::SetFieldNull( int iField )
+
+{
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
+
+    if( poFDefn == NULL || IsFieldNull(iField) )
+        return;
+
+    if( IsFieldSet(iField) )
+    {
+        switch( poFDefn->GetType() )
+        {
+            case OFTRealList:
+            case OFTIntegerList:
+            case OFTInteger64List:
+                CPLFree( pauFields[iField].IntegerList.paList );
+                break;
+
+            case OFTStringList:
+                CSLDestroy( pauFields[iField].StringList.paList );
+                break;
+
+            case OFTString:
+                CPLFree( pauFields[iField].String );
+                break;
+
+            case OFTBinary:
+                CPLFree( pauFields[iField].Binary.paData );
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    OGR_RawField_SetNull(&pauFields[iField]);
+}
+
+/************************************************************************/
+/*                          OGR_F_SetFieldNull()                        */
+/************************************************************************/
+
+/**
+ * \brief Clear a field, marking it as null.
+ *
+ * This function is the same as the C++ method OGRFeature::SetFieldNull().
+ *
+ * @param hFeat handle to the feature on which the field is.
+ * @param iField the field to set to null.
+ *
+ * @since GDAL 2.2
+ */
+
+void OGR_F_SetFieldNull( OGRFeatureH hFeat, int iField )
+
+{
+    VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldNull" );
+
+    reinterpret_cast<OGRFeature *>(hFeat)->SetFieldNull( iField );
 }
 
 /************************************************************************/
@@ -1378,7 +1622,7 @@ OGRField *OGR_F_GetRawFieldRef( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetRawFieldRef", NULL );
 
-    return ((OGRFeature *)hFeat)->GetRawFieldRef( iField );
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetRawFieldRef( iField );
 }
 
 /************************************************************************/
@@ -1386,6 +1630,20 @@ OGRField *OGR_F_GetRawFieldRef( OGRFeatureH hFeat, int iField )
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::GetFieldAsInteger( const char* pszFName )
+ * \brief Fetch field value as integer.
+ *
+ * OFTString features will be translated using atoi().  OFTReal fields
+ * will be cast to integer. OFTInteger64 are demoted to 32 bit, with
+ * clamping if out-of-range. Other field types, or errors will result in
+ * a return value of zero.
+ *
+ * @param pszFName the name of the field to fetch.
+ *
+ * @return the field value.
+ */
+
+/**
  * \brief Fetch field value as integer.
  *
  * OFTString features will be translated using atoi().  OFTReal fields
@@ -1404,17 +1662,18 @@ int OGRFeature::GetFieldAsInteger( int iField )
 
 {
     int iSpecialField = iField - poDefn->GetFieldCount();
-    if (iSpecialField >= 0)
+    if( iSpecialField >= 0 )
     {
-    // special field value accessors
-        switch (iSpecialField)
+        // Special field value accessors.
+        switch( iSpecialField )
         {
         case SPF_FID:
         {
-            int nVal = (nFID > INT_MAX) ? INT_MAX :
-                (nFID < INT_MIN) ? INT_MIN : (int) nFID;
+            const int nVal =
+                nFID > INT_MAX ? INT_MAX :
+                nFID < INT_MIN ? INT_MIN : static_cast<int>(nFID);
 
-            if( (GIntBig)nVal != nFID )
+            if( static_cast<GIntBig>(nVal) != nFID )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Integer overflow occurred when trying to return "
@@ -1426,31 +1685,35 @@ int OGRFeature::GetFieldAsInteger( int iField )
         case SPF_OGR_GEOM_AREA:
             if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return 0;
-            return (int)OGR_G_Area((OGRGeometryH)papoGeometries[0]);
+            return static_cast<int>(
+                OGR_G_Area(reinterpret_cast<OGRGeometryH>(papoGeometries[0])));
 
         default:
             return 0;
         }
     }
 
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return 0;
 
-    if( !IsFieldSet(iField) )
+    if( !IsFieldSetAndNotNull(iField) )
         return 0;
 
-    OGRFieldType eType = poFDefn->GetType();
+    const OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTInteger )
+    {
         return pauFields[iField].Integer;
+    }
     else if( eType == OFTInteger64 )
     {
-        GIntBig nVal64 = pauFields[iField].Integer64;
-        int nVal = (nVal64 > INT_MAX) ? INT_MAX :
-            (nVal64 < INT_MIN) ? INT_MIN : (int) nVal64;
+        const GIntBig nVal64 = pauFields[iField].Integer64;
+        const int nVal =
+            nVal64 > INT_MAX ? INT_MAX :
+            nVal64 < INT_MIN ? INT_MIN : static_cast<int>(nVal64);
 
-        if( (GIntBig)nVal != nVal64 )
+        if( static_cast<GIntBig>(nVal) != nVal64 )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Integer overflow occurred when trying to return 64bit "
@@ -1459,16 +1722,18 @@ int OGRFeature::GetFieldAsInteger( int iField )
         return nVal;
     }
     else if( eType == OFTReal )
-        return (int) pauFields[iField].Real;
+    {
+        return static_cast<int>(pauFields[iField].Real);
+    }
     else if( eType == OFTString )
     {
         if( pauFields[iField].String == NULL )
             return 0;
         else
             return atoi(pauFields[iField].String);
-    }
-    else
-        return 0;
+    }
+
+    return 0;
 }
 
 /************************************************************************/
@@ -1495,7 +1760,7 @@ int OGR_F_GetFieldAsInteger( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsInteger", 0 );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsInteger(iField);
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetFieldAsInteger(iField);
 }
 
 /************************************************************************/
@@ -1503,6 +1768,20 @@ int OGR_F_GetFieldAsInteger( OGRFeatureH hFeat, int iField )
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::GetFieldAsInteger64( const char* pszFName )
+ * \brief Fetch field value as integer 64 bit.
+ *
+ * OFTInteger are promoted to 64 bit.
+ * OFTString features will be translated using CPLAtoGIntBig().  OFTReal fields
+ * will be cast to integer.   Other field types, or errors will result in
+ * a return value of zero.
+ *
+ * @param pszFName the name of the field to fetch.
+ *
+ * @return the field value.
+ */
+
+/**
  * \brief Fetch field value as integer 64 bit.
  *
  * OFTInteger are promoted to 64 bit.
@@ -1521,11 +1800,11 @@ int OGR_F_GetFieldAsInteger( OGRFeatureH hFeat, int iField )
 GIntBig OGRFeature::GetFieldAsInteger64( int iField )
 
 {
-    int iSpecialField = iField - poDefn->GetFieldCount();
-    if (iSpecialField >= 0)
+    const int iSpecialField = iField - poDefn->GetFieldCount();
+    if( iSpecialField >= 0 )
     {
-    // special field value accessors
-        switch (iSpecialField)
+        // Special field value accessors.
+        switch( iSpecialField )
         {
         case SPF_FID:
             return nFID;
@@ -1533,28 +1812,35 @@ GIntBig OGRFeature::GetFieldAsInteger64( int iField )
         case SPF_OGR_GEOM_AREA:
             if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return 0;
-            return (int)OGR_G_Area((OGRGeometryH)papoGeometries[0]);
+            return static_cast<int>(
+                OGR_G_Area(reinterpret_cast<OGRGeometryH>(papoGeometries[0])));
 
         default:
             return 0;
         }
     }
 
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return 0;
 
-    if( !IsFieldSet(iField) )
+    if( !IsFieldSetAndNotNull(iField) )
         return 0;
 
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTInteger )
-        return (GIntBig) pauFields[iField].Integer;
+    {
+        return static_cast<GIntBig>(pauFields[iField].Integer);
+    }
     else if( eType == OFTInteger64 )
+    {
         return pauFields[iField].Integer64;
+    }
     else if( eType == OFTReal )
-        return (GIntBig) pauFields[iField].Real;
+    {
+        return static_cast<GIntBig>(pauFields[iField].Real);
+    }
     else if( eType == OFTString )
     {
         if( pauFields[iField].String == NULL )
@@ -1564,8 +1850,8 @@ GIntBig OGRFeature::GetFieldAsInteger64( int iField )
             return CPLAtoGIntBigEx(pauFields[iField].String, TRUE, NULL);
         }
     }
-    else
-        return 0;
+
+    return 0;
 }
 
 /************************************************************************/
@@ -1580,7 +1866,8 @@ GIntBig OGRFeature::GetFieldAsInteger64( int iField )
  * will be cast to integer.   Other field types, or errors will result in
  * a return value of zero.
  *
- * This function is the same as the C++ method OGRFeature::GetFieldAsInteger64().
+ * This function is the same as the C++ method
+ * OGRFeature::GetFieldAsInteger64().
  *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
@@ -1594,7 +1881,7 @@ GIntBig OGR_F_GetFieldAsInteger64( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsInteger64", 0 );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsInteger64(iField);
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetFieldAsInteger64(iField);
 }
 
 /************************************************************************/
@@ -1602,11 +1889,24 @@ GIntBig OGR_F_GetFieldAsInteger64( OGRFeatureH hFeat, int iField )
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::GetFieldAsDouble( const char* pszFName )
  * \brief Fetch field value as a double.
  *
- * OFTString features will be translated using CPLAtof().  OFTInteger and OFTInteger64 fields
- * will be cast to double.   Other field types, or errors will result in
- * a return value of zero.
+ * OFTString features will be translated using CPLAtof().  OFTInteger and
+ * OFTInteger64 fields will be cast to double.  Other field types, or errors
+ * will result in a return value of zero.
+ *
+ * @param pszFName the name of the field to fetch.
+ *
+ * @return the field value.
+ */
+
+/**
+ * \brief Fetch field value as a double.
+ *
+ * OFTString features will be translated using CPLAtof().  OFTInteger and
+ * OFTInteger64 fields will be cast to double.  Other field types, or errors
+ * will result in a return value of zero.
  *
  * This method is the same as the C function OGR_F_GetFieldAsDouble().
  *
@@ -1618,40 +1918,47 @@ GIntBig OGR_F_GetFieldAsInteger64( OGRFeatureH hFeat, int iField )
 double OGRFeature::GetFieldAsDouble( int iField )
 
 {
-    int iSpecialField = iField - poDefn->GetFieldCount();
-    if (iSpecialField >= 0)
+    const int iSpecialField = iField - poDefn->GetFieldCount();
+    if( iSpecialField >= 0 )
     {
-    // special field value accessors
-        switch (iSpecialField)
+        // Special field value accessors.
+        switch( iSpecialField )
         {
         case SPF_FID:
-            return (double)GetFID();
+            return static_cast<double>(GetFID());
 
         case SPF_OGR_GEOM_AREA:
             if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return 0.0;
-            return OGR_G_Area((OGRGeometryH)papoGeometries[0]);
+            return
+                OGR_G_Area(reinterpret_cast<OGRGeometryH>(papoGeometries[0]));
 
         default:
             return 0.0;
         }
     }
 
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return 0.0;
 
-    if( !IsFieldSet(iField) )
+    if( !IsFieldSetAndNotNull(iField) )
         return 0.0;
 
-    OGRFieldType eType = poFDefn->GetType();
+    const OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTReal )
+    {
         return pauFields[iField].Real;
+    }
     else if( eType == OFTInteger )
+    {
         return pauFields[iField].Integer;
+    }
     else if( eType == OFTInteger64 )
-        return (double) pauFields[iField].Integer64;
+    {
+        return static_cast<double>(pauFields[iField].Integer64);
+    }
     else if( eType == OFTString )
     {
         if( pauFields[iField].String == NULL )
@@ -1659,8 +1966,8 @@ double OGRFeature::GetFieldAsDouble( int iField )
         else
             return CPLAtof(pauFields[iField].String);
     }
-    else
-        return 0.0;
+
+    return 0.0;
 }
 
 /************************************************************************/
@@ -1687,60 +1994,63 @@ double OGR_F_GetFieldAsDouble( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsDouble", 0 );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsDouble(iField);
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetFieldAsDouble(iField);
 }
 
 /************************************************************************/
 /*                      OGRFeatureFormatDateTimeBuffer()                */
 /************************************************************************/
 
-#define TEMP_BUFFER_SIZE 80
-static void OGRFeatureFormatDateTimeBuffer(char szTempBuffer[TEMP_BUFFER_SIZE],
-                                           int nYear, int nMonth, int nDay,
-                                           int nHour, int nMinute, float fSecond,
-                                           int nTZFlag )
+static const int TEMP_BUFFER_SIZE = 80;
+static void OGRFeatureFormatDateTimeBuffer( char szTempBuffer[TEMP_BUFFER_SIZE],
+                                            int nYear, int nMonth, int nDay,
+                                            int nHour, int nMinute,
+                                            float fSecond,
+                                            int nTZFlag )
 {
-    int ms = OGR_GET_MS(fSecond);
+    const int ms = OGR_GET_MS(fSecond);
     if( ms != 0 )
+        CPLsnprintf( szTempBuffer, TEMP_BUFFER_SIZE,
+                  "%04d/%02d/%02d %02d:%02d:%06.3f",
+                  nYear,
+                  nMonth,
+                  nDay,
+                  nHour,
+                  nMinute,
+                  fSecond );
+    else  // Default format.
         snprintf( szTempBuffer, TEMP_BUFFER_SIZE,
-                "%04d/%02d/%02d %02d:%02d:%06.3f",
-                nYear,
-                nMonth,
-                nDay,
-                nHour,
-                nMinute,
-                fSecond );
-    else /* default format */
-        snprintf( szTempBuffer, TEMP_BUFFER_SIZE,
-                "%04d/%02d/%02d %02d:%02d:%02d",
-                nYear,
-                nMonth,
-                nDay,
-                nHour,
-                nMinute,
-                (int)fSecond );
-
+                  "%04d/%02d/%02d %02d:%02d:%02d",
+                  nYear,
+                  nMonth,
+                  nDay,
+                  nHour,
+                  nMinute,
+                  static_cast<int>(fSecond) );
 
     if( nTZFlag > 1 )
     {
-        int nOffset = (nTZFlag - 100) * 15;
-        int nHours = (int) (nOffset / 60);  // round towards zero
-        int nMinutes = ABS(nOffset - nHours * 60);
+        const int nOffset = (nTZFlag - 100) * 15;
+        int nHours = static_cast<int>(nOffset / 60);  // Round towards zero.
+        const int nMinutes = std::abs(nOffset - nHours * 60);
 
         if( nOffset < 0 )
         {
             strcat( szTempBuffer, "-" );
-            nHours = ABS(nHours);
+            nHours = std::abs(nHours);
         }
         else
+        {
             strcat( szTempBuffer, "+" );
+        }
 
         if( nMinutes == 0 )
             snprintf( szTempBuffer+strlen(szTempBuffer),
-                    TEMP_BUFFER_SIZE-strlen(szTempBuffer), "%02d", nHours );
+                      TEMP_BUFFER_SIZE-strlen(szTempBuffer), "%02d", nHours );
         else
             snprintf( szTempBuffer+strlen(szTempBuffer),
-                    TEMP_BUFFER_SIZE-strlen(szTempBuffer), "%02d%02d", nHours, nMinutes );
+                      TEMP_BUFFER_SIZE-strlen(szTempBuffer),
+                      "%02d%02d", nHours, nMinutes );
     }
 }
 
@@ -1749,6 +2059,20 @@ static void OGRFeatureFormatDateTimeBuffer(char szTempBuffer[TEMP_BUFFER_SIZE],
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::GetFieldAsString( const char* pszFName )
+ * \brief Fetch field value as a string.
+ *
+ * OFTReal and OFTInteger fields will be translated to string using
+ * sprintf(), but not necessarily using the established formatting rules.
+ * Other field types, or errors will result in a return value of zero.
+ *
+ * @param pszFName the name of the field to fetch.
+ *
+ * @return the field value.  This string is internal, and should not be
+ * modified, or freed.  Its lifetime may be very brief.
+ */
+
+/**
  * \brief Fetch field value as a string.
  *
  * OFTReal and OFTInteger fields will be translated to string using
@@ -1766,19 +2090,19 @@ static void OGRFeatureFormatDateTimeBuffer(char szTempBuffer[TEMP_BUFFER_SIZE],
 const char *OGRFeature::GetFieldAsString( int iField )
 
 {
-    char         szTempBuffer[TEMP_BUFFER_SIZE];
+    char szTempBuffer[TEMP_BUFFER_SIZE] = {};
 
     CPLFree(m_pszTmpFieldValue);
     m_pszTmpFieldValue = NULL;
 
-    int iSpecialField = iField - poDefn->GetFieldCount();
-    if (iSpecialField >= 0)
+    const int iSpecialField = iField - poDefn->GetFieldCount();
+    if( iSpecialField >= 0 )
     {
-        // special field value accessors
-        switch (iSpecialField)
+        // Special field value accessors.
+        switch( iSpecialField )
         {
           case SPF_FID:
-            snprintf( szTempBuffer, TEMP_BUFFER_SIZE, CPL_FRMT_GIB, GetFID() );
+            CPLsnprintf( szTempBuffer, TEMP_BUFFER_SIZE, CPL_FRMT_GIB, GetFID() );
             m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
             if( m_pszTmpFieldValue == NULL )
                 return "";
@@ -1801,7 +2125,8 @@ const char *OGRFeature::GetFieldAsString( int iField )
               if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                   return "";
 
-              if (papoGeometries[0]->exportToWkt( &m_pszTmpFieldValue ) == OGRERR_NONE )
+              if( papoGeometries[0]->exportToWkt( &m_pszTmpFieldValue ) ==
+                  OGRERR_NONE )
                   return m_pszTmpFieldValue;
               else
                   return "";
@@ -1811,8 +2136,9 @@ const char *OGRFeature::GetFieldAsString( int iField )
             if( GetGeomFieldCount() == 0 || papoGeometries[0] == NULL )
                 return "";
 
-            CPLsnprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%.16g",
-                      OGR_G_Area((OGRGeometryH)papoGeometries[0]) );
+            CPLsnprintf(
+                szTempBuffer, TEMP_BUFFER_SIZE, "%.16g",
+                OGR_G_Area(reinterpret_cast<OGRGeometryH>(papoGeometries[0])));
             m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
             if( m_pszTmpFieldValue == NULL )
                 return "";
@@ -1823,12 +2149,12 @@ const char *OGRFeature::GetFieldAsString( int iField )
         }
     }
 
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return "";
 
-    if( !IsFieldSet(iField) )
+    if( !IsFieldSetAndNotNull(iField) )
         return "";
 
     OGRFieldType eType = poFDefn->GetType();
@@ -1850,7 +2176,7 @@ const char *OGRFeature::GetFieldAsString( int iField )
     }
     else if( eType == OFTInteger64 )
     {
-        snprintf( szTempBuffer, TEMP_BUFFER_SIZE,
+        CPLsnprintf( szTempBuffer, TEMP_BUFFER_SIZE,
                   CPL_FRMT_GIB, pauFields[iField].Integer64 );
         m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
         if( m_pszTmpFieldValue == NULL )
@@ -1859,7 +2185,7 @@ const char *OGRFeature::GetFieldAsString( int iField )
     }
     else if( eType == OFTReal )
     {
-        char    szFormat[64];
+        char szFormat[64] = {};
 
         if( poFDefn->GetWidth() != 0 )
         {
@@ -1867,7 +2193,9 @@ const char *OGRFeature::GetFieldAsString( int iField )
                 poFDefn->GetPrecision() );
         }
         else
+        {
             strcpy( szFormat, "%.15g" );
+        }
 
         CPLsnprintf( szTempBuffer, TEMP_BUFFER_SIZE,
                   szFormat, pauFields[iField].Real );
@@ -1907,17 +2235,19 @@ const char *OGRFeature::GetFieldAsString( int iField )
     }
     else if( eType == OFTTime )
     {
-        int ms = OGR_GET_MS(pauFields[iField].Date.Second);
+        const int ms = OGR_GET_MS(pauFields[iField].Date.Second);
         if( ms != 0 )
-            snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%02d:%02d:%06.3f",
-                  pauFields[iField].Date.Hour,
-                  pauFields[iField].Date.Minute,
-                  pauFields[iField].Date.Second );
+            snprintf(
+                szTempBuffer, TEMP_BUFFER_SIZE, "%02d:%02d:%06.3f",
+                pauFields[iField].Date.Hour,
+                pauFields[iField].Date.Minute,
+                pauFields[iField].Date.Second );
         else
-            snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "%02d:%02d:%02d",
-                  pauFields[iField].Date.Hour,
-                  pauFields[iField].Date.Minute,
-                  (int)pauFields[iField].Date.Second );
+            snprintf(
+                szTempBuffer, TEMP_BUFFER_SIZE, "%02d:%02d:%02d",
+                pauFields[iField].Date.Hour,
+                pauFields[iField].Date.Minute,
+                static_cast<int>(pauFields[iField].Date.Second) );
 
         m_pszTmpFieldValue = VSI_STRDUP_VERBOSE( szTempBuffer );
         if( m_pszTmpFieldValue == NULL )
@@ -1926,11 +2256,12 @@ const char *OGRFeature::GetFieldAsString( int iField )
     }
     else if( eType == OFTIntegerList )
     {
-        char    szItem[32];
-        int     i, nCount = pauFields[iField].IntegerList.nCount;
+        char szItem[32] = {};
+        const int nCount = pauFields[iField].IntegerList.nCount;
 
         snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "(%d:", nCount );
-        for( i = 0; i < nCount; i++ )
+        int i = 0;  // Used after for.
+        for( ; i < nCount; i++ )
         {
             snprintf( szItem, sizeof(szItem), "%d",
                       pauFields[iField].IntegerList.paList[i] );
@@ -1958,13 +2289,14 @@ const char *OGRFeature::GetFieldAsString( int iField )
     }
     else if( eType == OFTInteger64List )
     {
-        char    szItem[32];
-        int     i, nCount = pauFields[iField].Integer64List.nCount;
+        char szItem[32] = {};
+        const int nCount = pauFields[iField].Integer64List.nCount;
 
         snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "(%d:", nCount );
-        for( i = 0; i < nCount; i++ )
+        int i = 0;  // Used after for.
+        for( ; i < nCount; i++ )
         {
-            snprintf( szItem, sizeof(szItem), CPL_FRMT_GIB,
+            CPLsnprintf( szItem, sizeof(szItem), CPL_FRMT_GIB,
                       pauFields[iField].Integer64List.paList[i] );
             if( strlen(szTempBuffer) + strlen(szItem) + 6
                 >= sizeof(szTempBuffer) )
@@ -1990,9 +2322,9 @@ const char *OGRFeature::GetFieldAsString( int iField )
     }
     else if( eType == OFTRealList )
     {
-        char    szItem[40];
-        char    szFormat[64];
-        int     i, nCount = pauFields[iField].RealList.nCount;
+        char szItem[40] = {};
+        char szFormat[64] = {};
+        const int nCount = pauFields[iField].RealList.nCount;
 
         if( poFDefn->GetWidth() != 0 )
         {
@@ -2003,7 +2335,8 @@ const char *OGRFeature::GetFieldAsString( int iField )
             strcpy( szFormat, "%.16g" );
 
         snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "(%d:", nCount );
-        for( i = 0; i < nCount; i++ )
+        int i = 0;  // Used after for.
+        for( ; i < nCount; i++ )
         {
             CPLsnprintf( szItem, sizeof(szItem), szFormat,
                       pauFields[iField].RealList.paList[i] );
@@ -2031,14 +2364,15 @@ const char *OGRFeature::GetFieldAsString( int iField )
     }
     else if( eType == OFTStringList )
     {
-        int     i, nCount = pauFields[iField].StringList.nCount;
+        const int nCount = pauFields[iField].StringList.nCount;
 
         snprintf( szTempBuffer, TEMP_BUFFER_SIZE, "(%d:", nCount );
-        for( i = 0; i < nCount; i++ )
+        int i = 0;  // Used after for.
+        for( ; i < nCount; i++ )
         {
-            const char  *pszItem = pauFields[iField].StringList.paList[i];
+            const char *pszItem = pauFields[iField].StringList.paList[i];
 
-            if( strlen(szTempBuffer) + strlen(pszItem)  + 6
+            if( strlen(szTempBuffer) + strlen(pszItem) + 6
                 >= sizeof(szTempBuffer) )
             {
                 break;
@@ -2062,13 +2396,13 @@ const char *OGRFeature::GetFieldAsString( int iField )
     }
     else if( eType == OFTBinary )
     {
-        int     nCount = pauFields[iField].Binary.nCount;
-        char    *pszHex;
+        int nCount = pauFields[iField].Binary.nCount;
 
-        if( nCount > (int) sizeof(szTempBuffer) / 2 - 4 )
+        if( nCount > static_cast<int>(sizeof(szTempBuffer)) / 2 - 4 )
             nCount = sizeof(szTempBuffer) / 2 - 4;
 
-        pszHex = CPLBinaryToHex( nCount, pauFields[iField].Binary.paData );
+        char *pszHex =
+            CPLBinaryToHex( nCount, pauFields[iField].Binary.paData );
 
         memcpy( szTempBuffer, pszHex, 2 * nCount );
         szTempBuffer[nCount*2] = '\0';
@@ -2082,8 +2416,8 @@ const char *OGRFeature::GetFieldAsString( int iField )
             return "";
         return m_pszTmpFieldValue;
     }
-    else
-        return "";
+
+    return "";
 }
 
 /************************************************************************/
@@ -2111,7 +2445,7 @@ const char *OGR_F_GetFieldAsString( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsString", NULL );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsString(iField);
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetFieldAsString(iField);
 }
 
 /************************************************************************/
@@ -2119,6 +2453,23 @@ const char *OGR_F_GetFieldAsString( OGRFeatureH hFeat, int iField )
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::GetFieldAsIntegerList( const char* pszFName, int *pnCount )
+ * \brief Fetch field value as a list of integers.
+ *
+ * Currently this method only works for OFTIntegerList fields.
+
+ * @param pszFName the name of the field to fetch.
+ * @param pnCount an integer to put the list count (number of integers) into.
+ *
+ * @return the field value.  This list is internal, and should not be
+ * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
+ * on return the returned pointer may be NULL or non-NULL.
+ * OFTReal and OFTInteger fields will be translated to string using
+ * sprintf(), but not necessarily using the established formatting rules.
+ * Other field types, or errors will result in a return value of zero.
+ */
+
+/**
  * \brief Fetch field value as a list of integers.
  *
  * Currently this method only works for OFTIntegerList fields.
@@ -2136,9 +2487,9 @@ const char *OGR_F_GetFieldAsString( OGRFeatureH hFeat, int iField )
 const int *OGRFeature::GetFieldAsIntegerList( int iField, int *pnCount )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
-    if( poFDefn != NULL && IsFieldSet(iField) &&
+    if( poFDefn != NULL && IsFieldSetAndNotNull(iField) &&
         poFDefn->GetType() == OFTIntegerList )
     {
         if( pnCount != NULL )
@@ -2146,13 +2497,11 @@ const int *OGRFeature::GetFieldAsIntegerList( int iField, int *pnCount )
 
         return pauFields[iField].IntegerList.paList;
     }
-    else
-    {
-        if( pnCount != NULL )
-            *pnCount = 0;
 
-        return NULL;
-    }
+    if( pnCount != NULL )
+        *pnCount = 0;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -2177,17 +2526,32 @@ const int *OGRFeature::GetFieldAsIntegerList( int iField, int *pnCount )
  */
 
 const int *OGR_F_GetFieldAsIntegerList( OGRFeatureH hFeat, int iField,
-                                  int *pnCount )
+                                        int *pnCount )
 
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsIntegerList", NULL );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsIntegerList(iField, pnCount);
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        GetFieldAsIntegerList(iField, pnCount);
 }
 
 /************************************************************************/
 /*                      GetFieldAsInteger64List()                       */
 /************************************************************************/
+/**
+ * \fn OGRFeature::GetFieldAsInteger64List( const char* pszFName, int *pnCount )
+ * \brief Fetch field value as a list of 64 bit integers.
+ *
+ * Currently this method only works for OFTInteger64List fields.
+
+ * @param pszFName the name of the field to fetch.
+ * @param pnCount an integer to put the list count (number of integers) into.
+ *
+ * @return the field value.  This list is internal, and should not be
+ * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
+ * on return the returned pointer may be NULL or non-NULL.
+ * @since GDAL 2.0
+ */
 
 /**
  * \brief Fetch field value as a list of 64 bit integers.
@@ -2208,9 +2572,9 @@ const int *OGR_F_GetFieldAsIntegerList( OGRFeatureH hFeat, int iField,
 const GIntBig *OGRFeature::GetFieldAsInteger64List( int iField, int *pnCount )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
-    if( poFDefn != NULL && IsFieldSet(iField) &&
+    if( poFDefn != NULL && IsFieldSetAndNotNull(iField) &&
         poFDefn->GetType() == OFTInteger64List )
     {
         if( pnCount != NULL )
@@ -2218,13 +2582,11 @@ const GIntBig *OGRFeature::GetFieldAsInteger64List( int iField, int *pnCount )
 
         return pauFields[iField].Integer64List.paList;
     }
-    else
-    {
-        if( pnCount != NULL )
-            *pnCount = 0;
 
-        return NULL;
-    }
+    if( pnCount != NULL )
+        *pnCount = 0;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -2250,17 +2612,31 @@ const GIntBig *OGRFeature::GetFieldAsInteger64List( int iField, int *pnCount )
  */
 
 const GIntBig *OGR_F_GetFieldAsInteger64List( OGRFeatureH hFeat, int iField,
-                                  int *pnCount )
+                                              int *pnCount )
 
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsInteger64List", NULL );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsInteger64List(iField, pnCount);
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        GetFieldAsInteger64List(iField, pnCount);
 }
 
 /************************************************************************/
 /*                        GetFieldAsDoubleList()                        */
 /************************************************************************/
+/**
+ * \fn OGRFeature::GetFieldAsDoubleList( const char* pszFName, int *pnCount )
+ * \brief Fetch field value as a list of doubles.
+ *
+ * Currently this method only works for OFTRealList fields.
+
+ * @param pszFName the name of the field to fetch.
+ * @param pnCount an integer to put the list count (number of doubles) into.
+ *
+ * @return the field value.  This list is internal, and should not be
+ * modified, or freed.  Its lifetime may be very brief.  If *pnCount is zero
+ * on return the returned pointer may be NULL or non-NULL.
+ */
 
 /**
  * \brief Fetch field value as a list of doubles.
@@ -2280,9 +2656,9 @@ const GIntBig *OGR_F_GetFieldAsInteger64List( OGRFeatureH hFeat, int iField,
 const double *OGRFeature::GetFieldAsDoubleList( int iField, int *pnCount )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
-    if( poFDefn != NULL && IsFieldSet(iField) &&
+    if( poFDefn != NULL && IsFieldSetAndNotNull(iField) &&
         poFDefn->GetType() == OFTRealList )
     {
         if( pnCount != NULL )
@@ -2290,13 +2666,11 @@ const double *OGRFeature::GetFieldAsDoubleList( int iField, int *pnCount )
 
         return pauFields[iField].RealList.paList;
     }
-    else
-    {
-        if( pnCount != NULL )
-            *pnCount = 0;
 
-        return NULL;
-    }
+    if( pnCount != NULL )
+        *pnCount = 0;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -2326,12 +2700,27 @@ const double *OGR_F_GetFieldAsDoubleList( OGRFeatureH hFeat, int iField,
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsDoubleList", NULL );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsDoubleList(iField, pnCount);
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        GetFieldAsDoubleList(iField, pnCount);
 }
 
 /************************************************************************/
 /*                        GetFieldAsStringList()                        */
 /************************************************************************/
+/**
+ * \fn OGRFeature::GetFieldAsStringList( const char* pszFName )
+ * \brief Fetch field value as a list of strings.
+ *
+ * Currently this method only works for OFTStringList fields.
+ *
+ * The returned list is terminated by a NULL pointer. The number of
+ * elements can also be calculated using CSLCount().
+ *
+ * @param pszFName the name of the field to fetch.
+ *
+ * @return the field value.  This list is internal, and should not be
+ * modified, or freed.  Its lifetime may be very brief.
+ */
 
 /**
  * \brief Fetch field value as a list of strings.
@@ -2352,22 +2741,20 @@ const double *OGR_F_GetFieldAsDoubleList( OGRFeatureH hFeat, int iField,
 char **OGRFeature::GetFieldAsStringList( int iField )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return NULL;
 
-    if( !IsFieldSet(iField) )
+    if( !IsFieldSetAndNotNull(iField) )
         return NULL;
 
     if( poFDefn->GetType() == OFTStringList )
     {
         return pauFields[iField].StringList.paList;
     }
-    else
-    {
-        return NULL;
-    }
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -2397,7 +2784,7 @@ char **OGR_F_GetFieldAsStringList( OGRFeatureH hFeat, int iField )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsStringList", NULL );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsStringList(iField);
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetFieldAsStringList(iField);
 }
 
 /************************************************************************/
@@ -2421,14 +2808,14 @@ char **OGR_F_GetFieldAsStringList( OGRFeatureH hFeat, int iField )
 GByte *OGRFeature::GetFieldAsBinary( int iField, int *pnBytes )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     *pnBytes = 0;
 
     if( poFDefn == NULL )
         return NULL;
 
-    if( !IsFieldSet(iField) )
+    if( !IsFieldSetAndNotNull(iField) )
         return NULL;
 
     if( poFDefn->GetType() == OFTBinary )
@@ -2438,13 +2825,11 @@ GByte *OGRFeature::GetFieldAsBinary( int iField, int *pnBytes )
     }
     else if( poFDefn->GetType() == OFTString )
     {
-        *pnBytes = (int)strlen(pauFields[iField].String);
-        return (GByte*)pauFields[iField].String;
-    }
-    else
-    {
-        return NULL;
+        *pnBytes = static_cast<int>(strlen(pauFields[iField].String));
+        return reinterpret_cast<GByte *>(pauFields[iField].String);
     }
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -2473,7 +2858,8 @@ GByte *OGR_F_GetFieldAsBinary( OGRFeatureH hFeat, int iField, int *pnBytes )
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsBinary", NULL );
     VALIDATE_POINTER1( pnBytes, "OGR_F_GetFieldAsBinary", NULL );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsBinary(iField,pnBytes);
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        GetFieldAsBinary(iField, pnBytes);
 }
 
 /************************************************************************/
@@ -2505,18 +2891,17 @@ int OGRFeature::GetFieldAsDateTime( int iField,
                                     int *pnTZFlag )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return FALSE;
 
-    if( !IsFieldSet(iField) )
+    if( !IsFieldSetAndNotNull(iField) )
         return FALSE;
 
     if( poFDefn->GetType() == OFTDate
         || poFDefn->GetType() == OFTTime
         || poFDefn->GetType() == OFTDateTime )
-
     {
         if( pnYear )
             *pnYear = pauFields[iField].Date.Year;
@@ -2535,21 +2920,39 @@ int OGRFeature::GetFieldAsDateTime( int iField,
 
         return TRUE;
     }
-    else
-    {
-        return FALSE;
-    }
+
+    return FALSE;
 }
 
+/**
+ * \brief Fetch field value as date and time.
+ *
+ * Currently this method only works for OFTDate, OFTTime and OFTDateTime fields.
+ *
+ * This method is the same as the C function OGR_F_GetFieldAsDateTime().
+ *
+ * @param iField the field to fetch, from 0 to GetFieldCount()-1.
+ * @param pnYear (including century)
+ * @param pnMonth (1-12)
+ * @param pnDay (1-31)
+ * @param pnHour (0-23)
+ * @param pnMinute (0-59)
+ * @param pnSecond (0-59)
+ * @param pnTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
+ *
+ * @return TRUE on success or FALSE on failure.
+ */
+
 int OGRFeature::GetFieldAsDateTime( int iField,
                                     int *pnYear, int *pnMonth, int *pnDay,
                                     int *pnHour, int *pnMinute, int *pnSecond,
                                     int *pnTZFlag )
 {
-    float fSecond;
-    int bRet = GetFieldAsDateTime( iField, pnYear, pnMonth, pnDay, pnHour, pnMinute,
-                                   &fSecond, pnTZFlag);
-    if( bRet && pnSecond ) *pnSecond = (int)fSecond;
+    float fSecond = 0.0f;
+    const bool bRet = CPL_TO_BOOL(
+        GetFieldAsDateTime( iField, pnYear, pnMonth, pnDay, pnHour, pnMinute,
+                            &fSecond, pnTZFlag));
+    if( bRet && pnSecond ) *pnSecond = static_cast<int>(fSecond);
     return bRet;
 }
 
@@ -2588,12 +2991,13 @@ int OGR_F_GetFieldAsDateTime( OGRFeatureH hFeat, int iField,
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsDateTime", 0 );
 
-    float fSecond;
-    int bRet =((OGRFeature *)hFeat)->GetFieldAsDateTime( iField,
-                                                      pnYear, pnMonth, pnDay,
-                                                      pnHour, pnMinute,&fSecond,
-                                                      pnTZFlag );
-    if( bRet && pnSecond ) *pnSecond = (int)fSecond;
+    float fSecond = 0.0f;
+    const bool bRet = CPL_TO_BOOL(reinterpret_cast<OGRFeature *>(hFeat)->
+        GetFieldAsDateTime( iField,
+                            pnYear, pnMonth, pnDay,
+                            pnHour, pnMinute, &fSecond,
+                            pnTZFlag ));
+    if( bRet && pnSecond ) *pnSecond = static_cast<int>(fSecond);
     return bRet;
 }
 
@@ -2631,17 +3035,19 @@ int OGR_F_GetFieldAsDateTimeEx( OGRFeatureH hFeat, int iField,
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFieldAsDateTimeEx", 0 );
 
-    return ((OGRFeature *)hFeat)->GetFieldAsDateTime( iField,
-                                                      pnYear, pnMonth, pnDay,
-                                                      pnHour, pnMinute,pfSecond,
-                                                      pnTZFlag );
+    return
+        reinterpret_cast<OGRFeature *>(hFeat)->
+            GetFieldAsDateTime(iField,
+                               pnYear, pnMonth, pnDay,
+                               pnHour, pnMinute, pfSecond,
+                               pnTZFlag);
 }
 
 /************************************************************************/
 /*                        OGRFeatureGetIntegerValue()                   */
 /************************************************************************/
 
-static int OGRFeatureGetIntegerValue(OGRFieldDefn *poFDefn, int nValue)
+static int OGRFeatureGetIntegerValue( OGRFieldDefn *poFDefn, int nValue )
 {
     if( poFDefn->GetSubType() == OFSTBoolean && nValue != 0 && nValue != 1 )
     {
@@ -2655,15 +3061,15 @@ static int OGRFeatureGetIntegerValue(OGRFieldDefn *poFDefn, int nValue)
         if( nValue < -32768 )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
-                    "Out-of-range value for a OFSTInt16 subtype. "
-                    "Considering this value as -32768.");
+                     "Out-of-range value for a OFSTInt16 subtype. "
+                     "Considering this value as -32768.");
             nValue = -32768;
         }
         else if( nValue > 32767 )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
-                    "Out-of-range value for a OFSTInt16 subtype. "
-                    "Considering this value as 32767.");
+                     "Out-of-range value for a OFSTInt16 subtype. "
+                     "Considering this value as 32767.");
             nValue = 32767;
         }
     }
@@ -2671,19 +3077,130 @@ static int OGRFeatureGetIntegerValue(OGRFieldDefn *poFDefn, int nValue)
 }
 
 /************************************************************************/
+/*                        GetFieldAsSerializedJSon()                   */
+/************************************************************************/
+
+/**
+ * \brief Fetch field value as a serialized JSon object.
+ *
+ * Currently this method only works for OFTStringList, OFTIntegerList,
+ * OFTInteger64List and OFTRealList
+ *
+ * @param iField the field to fetch, from 0 to GetFieldCount()-1.
+ *
+ * @return a string that must be de-allocate with CPLFree()
+ * @since GDAL 2.2
+ */
+char* OGRFeature::GetFieldAsSerializedJSon( int iField )
+
+{
+    const int iSpecialField = iField - poDefn->GetFieldCount();
+    if( iSpecialField >= 0 )
+    {
+        return NULL;
+    }
+
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
+
+    if( poFDefn == NULL )
+        return NULL;
+
+    if( !IsFieldSetAndNotNull(iField) )
+        return NULL;
+
+    char* pszRet = NULL;
+    OGRFieldType eType = poFDefn->GetType();
+    if( eType == OFTStringList )
+    {
+        json_object* poObj = json_object_new_array();
+        char** papszValues = GetFieldAsStringList(iField);
+        for( int i=0; papszValues[i] != NULL; i++)
+        {
+            json_object_array_add( poObj,
+                                   json_object_new_string(papszValues[i]) );
+        }
+        pszRet = CPLStrdup( json_object_to_json_string(poObj) );
+        json_object_put(poObj);
+    }
+    else if( eType == OFTIntegerList )
+    {
+        json_object* poObj = json_object_new_array();
+        int nCount = 0;
+        const int* panValues = GetFieldAsIntegerList(iField, &nCount);
+        for( int i = 0; i < nCount; i++ )
+        {
+            json_object_array_add( poObj,
+                                   json_object_new_int(panValues[i]) );
+        }
+        pszRet = CPLStrdup( json_object_to_json_string(poObj) );
+        json_object_put(poObj);
+    }
+    else if( eType == OFTInteger64List )
+    {
+        json_object* poObj = json_object_new_array();
+        int nCount = 0;
+        const GIntBig* panValues = GetFieldAsInteger64List(iField, &nCount);
+        for( int i = 0; i < nCount; i++ )
+        {
+            json_object_array_add( poObj,
+                                   json_object_new_int64(panValues[i]) );
+        }
+        pszRet = CPLStrdup( json_object_to_json_string(poObj) );
+        json_object_put(poObj);
+    }
+    else if( eType == OFTRealList )
+    {
+        json_object* poObj = json_object_new_array();
+        int nCount = 0;
+        const double* padfValues = GetFieldAsDoubleList(iField, &nCount);
+        for( int i = 0; i < nCount; i++ )
+        {
+            json_object_array_add( poObj,
+                            json_object_new_double(padfValues[i]) );
+        }
+        pszRet = CPLStrdup( json_object_to_json_string(poObj) );
+        json_object_put(poObj);
+    }
+
+    return pszRet;
+}
+
+/************************************************************************/
 /*                              SetField()                              */
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName, int nValue )
+ * \brief Set field to integer value.
+ * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
+ * fields will be assigned a string representation of the value, but not
+ * necessarily taking into account formatting constraints on this field.  Other
+ * field types may be unaffected.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param nValue the value to assign.
+ */
+
+/**
  * \brief Set field to integer value.
  *
- * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
- * will be assigned a string representation of the value, but not necessarily
- * taking into account formatting constraints on this field.  Other field
- * types may be unaffected.
+ * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
+ * fields will be assigned a string representation of the value, but not
+ * necessarily taking into account formatting constraints on this field.  Other
+ * field types may be unaffected.
  *
  * This method is the same as the C function OGR_F_SetFieldInteger().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param nValue the value to assign.
  */
@@ -2691,7 +3208,7 @@ static int OGRFeatureGetIntegerValue(OGRFieldDefn *poFDefn, int nValue)
 void OGRFeature::SetField( int iField, int nValue )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return;
@@ -2701,10 +3218,12 @@ void OGRFeature::SetField( int iField, int nValue )
     {
         pauFields[iField].Integer = OGRFeatureGetIntegerValue(poFDefn, nValue);
         pauFields[iField].Set.nMarker2 = 0;
+        pauFields[iField].Set.nMarker3 = 0;
     }
     else if( eType == OFTInteger64 )
     {
-        pauFields[iField].Integer64 = OGRFeatureGetIntegerValue(poFDefn, nValue);
+        pauFields[iField].Integer64 =
+            OGRFeatureGetIntegerValue(poFDefn, nValue);
     }
     else if( eType == OFTReal )
     {
@@ -2726,33 +3245,30 @@ void OGRFeature::SetField( int iField, int nValue )
     }
     else if( eType == OFTString )
     {
-        char    szTempBuffer[64];
+        char szTempBuffer[64] = {};
 
         snprintf( szTempBuffer, sizeof(szTempBuffer), "%d", nValue );
 
-        if( IsFieldSet( iField) )
+        if( IsFieldSetAndNotNull(iField) )
             CPLFree( pauFields[iField].String );
 
         pauFields[iField].String = VSI_STRDUP_VERBOSE( szTempBuffer );
         if( pauFields[iField].String == NULL )
         {
-            pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-            pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+            OGR_RawField_SetUnset(&pauFields[iField]);
         }
     }
     else if( eType == OFTStringList )
     {
-        char    szTempBuffer[64];
+        char szTempBuffer[64] = {};
 
         snprintf( szTempBuffer, sizeof(szTempBuffer), "%d", nValue );
-        char   *apszValues[2];
-        apszValues[0] = szTempBuffer;
-        apszValues[1] = NULL;
+        char *apszValues[2] = { szTempBuffer, NULL };
         SetField( iField, apszValues);
     }
     else
     {
-        /* do nothing for other field types */
+        // Do nothing for other field types.
     }
 }
 
@@ -2763,13 +3279,18 @@ void OGRFeature::SetField( int iField, int nValue )
 /**
  * \brief Set field to integer value.
  *
- * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
- * will be assigned a string representation of the value, but not necessarily
- * taking into account formatting constraints on this field.  Other field
- * types may be unaffected.
+ * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
+ * fields will be assigned a string representation of the value, but not
+ * necessarily taking into account formatting constraints on this field.  Other
+ * field types may be unaffected.
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param nValue the value to assign.
@@ -2780,7 +3301,7 @@ void OGR_F_SetFieldInteger( OGRFeatureH hFeat, int iField, int nValue )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldInteger" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, nValue );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetField( iField, nValue );
 }
 
 /************************************************************************/
@@ -2788,15 +3309,37 @@ void OGR_F_SetFieldInteger( OGRFeatureH hFeat, int iField, int nValue )
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName, GIntBig nValue )
+ * \brief Set field to 64 bit integer value.
+ * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
+ * fields will be assigned a string representation of the value, but not
+ * necessarily taking into account formatting constraints on this field.  Other
+ * field types may be unaffected.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param nValue the value to assign.
+ */
+
+/**
  * \brief Set field to 64 bit integer value.
  *
- * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
- * will be assigned a string representation of the value, but not necessarily
- * taking into account formatting constraints on this field.  Other field
- * types may be unaffected.
+ * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
+ * fields will be assigned a string representation of the value, but not
+ * necessarily taking into account formatting constraints on this field.  Other
+ * field types may be unaffected.
  *
  * This method is the same as the C function OGR_F_SetFieldInteger64().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param nValue the value to assign.
  * @since GDAL 2.0
@@ -2805,7 +3348,7 @@ void OGR_F_SetFieldInteger( OGRFeatureH hFeat, int iField, int nValue )
 void OGRFeature::SetField( int iField, GIntBig nValue )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return;
@@ -2813,10 +3356,11 @@ void OGRFeature::SetField( int iField, GIntBig nValue )
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTInteger )
     {
-        int nVal32 = (nValue < INT_MIN ) ? INT_MIN :
-            (nValue > INT_MAX) ? INT_MAX : (int)nValue;
+        const int nVal32 =
+            nValue < INT_MIN ? INT_MIN :
+            nValue > INT_MAX ? INT_MAX : static_cast<int>(nValue);
 
-        if( (GIntBig)nVal32 != nValue )
+        if( static_cast<GIntBig>(nVal32) != nValue )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Integer overflow occurred when trying to set "
@@ -2830,14 +3374,15 @@ void OGRFeature::SetField( int iField, GIntBig nValue )
     }
     else if( eType == OFTReal )
     {
-        pauFields[iField].Real = (double) nValue;
+        pauFields[iField].Real = static_cast<double>(nValue);
     }
     else if( eType == OFTIntegerList )
     {
-        int nVal32 = (nValue < INT_MIN ) ? INT_MIN :
-            (nValue > INT_MAX) ? INT_MAX : (int)nValue;
+        int nVal32 =
+            nValue < INT_MIN ? INT_MIN :
+            nValue > INT_MAX ? INT_MAX : static_cast<int>(nValue);
 
-        if( (GIntBig)nVal32 != nValue )
+        if( static_cast<GIntBig>(nVal32) != nValue )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Integer overflow occurred when trying to set "
@@ -2851,38 +3396,35 @@ void OGRFeature::SetField( int iField, GIntBig nValue )
     }
     else if( eType == OFTRealList )
     {
-        double dfValue = (double) nValue;
+        double dfValue = static_cast<double>(nValue);
         SetField( iField, 1, &dfValue );
     }
     else if( eType == OFTString )
     {
-        char    szTempBuffer[64];
+        char szTempBuffer[64] = {};
 
-        snprintf( szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue );
+        CPLsnprintf( szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue );
 
-        if( IsFieldSet( iField) )
+        if( IsFieldSetAndNotNull(iField) )
             CPLFree( pauFields[iField].String );
 
         pauFields[iField].String = VSI_STRDUP_VERBOSE( szTempBuffer );
         if( pauFields[iField].String == NULL )
         {
-            pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-            pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+            OGR_RawField_SetUnset(&pauFields[iField]);
         }
     }
     else if( eType == OFTStringList )
     {
-        char    szTempBuffer[64];
+        char szTempBuffer[64] = {};
 
-        snprintf( szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue );
-        char   *apszValues[2];
-        apszValues[0] = szTempBuffer;
-        apszValues[1] = NULL;
+        CPLsnprintf( szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB, nValue );
+        char *apszValues[2] = { szTempBuffer, NULL };
         SetField( iField, apszValues);
     }
     else
     {
-        /* do nothing for other field types */
+        // Do nothing for other field types.
     }
 }
 
@@ -2893,13 +3435,18 @@ void OGRFeature::SetField( int iField, GIntBig nValue )
 /**
  * \brief Set field to 64 bit integer value.
  *
- * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
- * will be assigned a string representation of the value, but not necessarily
- * taking into account formatting constraints on this field.  Other field
- * types may be unaffected.
+ * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
+ * fields will be assigned a string representation of the value, but not
+ * necessarily taking into account formatting constraints on this field.  Other
+ * field types may be unaffected.
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param nValue the value to assign.
@@ -2911,7 +3458,7 @@ void OGR_F_SetFieldInteger64( OGRFeatureH hFeat, int iField, GIntBig nValue )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldInteger64" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, nValue );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetField( iField, nValue );
 }
 
 /************************************************************************/
@@ -2919,15 +3466,38 @@ void OGR_F_SetFieldInteger64( OGRFeatureH hFeat, int iField, GIntBig nValue )
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName, double dfValue )
+ * \brief Set field to double value.
+ *
+ * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
+ * fields will be assigned a string representation of the value, but not
+ * necessarily taking into account formatting constraints on this field.  Other
+ * field types may be unaffected.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param dfValue the value to assign.
+ */
+
+/**
  * \brief Set field to double value.
  *
- * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
- * will be assigned a string representation of the value, but not necessarily
- * taking into account formatting constraints on this field.  Other field
- * types may be unaffected.
+ * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
+ * fields will be assigned a string representation of the value, but not
+ * necessarily taking into account formatting constraints on this field.  Other
+ * field types may be unaffected.
  *
  * This method is the same as the C function OGR_F_SetFieldDouble().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param dfValue the value to assign.
  */
@@ -2943,22 +3513,26 @@ void OGRFeature::SetField( int iField, double dfValue )
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTReal )
     {
-        /*if( poFDefn->GetSubType() == OFSTFloat32 && dfValue != (double)(float)dfValue )
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                 "Passed value cannot be exactly representing as a single-precision floating point value.");
-            dfValue = (double)(float)dfValue;
-        }*/
+        // if( poFDefn->GetSubType() == OFSTFloat32 &&
+        //     dfValue != (double)(float)dfValue )
+        // {
+        //     CPLError(CE_Warning, CPLE_AppDefined,
+        //              "Passed value cannot be exactly representing as "
+        //              "a single-precision floating point value.");
+        //     dfValue = (double)(float)dfValue;
+        // }
         pauFields[iField].Real = dfValue;
     }
     else if( eType == OFTInteger )
     {
-        pauFields[iField].Integer = (int) dfValue;
+        pauFields[iField].Integer = static_cast<int>(dfValue);
         pauFields[iField].Set.nMarker2 = 0;
+        pauFields[iField].Set.nMarker3 = 0;
     }
     else if( eType == OFTInteger64 )
     {
-        pauFields[iField].Integer64 = (GIntBig) dfValue;
+      pauFields[iField].Integer64 = static_cast<GIntBig>(dfValue);
+      pauFields[iField].Set.nMarker3 = 0;
     }
     else if( eType == OFTRealList )
     {
@@ -2966,41 +3540,40 @@ void OGRFeature::SetField( int iField, double dfValue )
     }
     else if( eType == OFTIntegerList )
     {
-        int nValue = (int) dfValue;
+        int nValue = static_cast<int>(dfValue);
         SetField( iField, 1, &nValue );
     }
     else if( eType == OFTInteger64List )
     {
-        GIntBig nValue = (GIntBig) dfValue;
+        GIntBig nValue = static_cast<GIntBig>(dfValue);
         SetField( iField, 1, &nValue );
     }
     else if( eType == OFTString )
     {
-        char    szTempBuffer[128];
+        char szTempBuffer[128] = {};
 
         CPLsnprintf( szTempBuffer, sizeof(szTempBuffer), "%.16g", dfValue );
 
-        if( IsFieldSet( iField) )
+        if( IsFieldSetAndNotNull(iField) )
             CPLFree( pauFields[iField].String );
 
         pauFields[iField].String = VSI_STRDUP_VERBOSE( szTempBuffer );
         if( pauFields[iField].String == NULL )
         {
-            pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-            pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+            OGR_RawField_SetUnset(&pauFields[iField]);
         }
     }
     else if( eType == OFTStringList )
     {
-        char    szTempBuffer[64];
+        char szTempBuffer[64] = {};
 
         CPLsnprintf( szTempBuffer, sizeof(szTempBuffer), "%.16g", dfValue );
-        char   *apszValues[2] = {szTempBuffer, NULL};
+        char *apszValues[2] = { szTempBuffer, NULL };
         SetField( iField, apszValues);
     }
     else
     {
-        /* do nothing for other field types */
+        // Do nothing for other field types.
     }
 }
 
@@ -3011,13 +3584,18 @@ void OGRFeature::SetField( int iField, double dfValue )
 /**
  * \brief Set field to double value.
  *
- * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString fields
- * will be assigned a string representation of the value, but not necessarily
- * taking into account formatting constraints on this field.  Other field
- * types may be unaffected.
+ * OFTInteger, OFTInteger64 and OFTReal fields will be set directly.  OFTString
+ * fields will be assigned a string representation of the value, but not
+ * necessarily taking into account formatting constraints on this field.  Other
+ * field types may be unaffected.
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param dfValue the value to assign.
@@ -3028,7 +3606,7 @@ void OGR_F_SetFieldDouble( OGRFeatureH hFeat, int iField, double dfValue )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldDouble" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, dfValue );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetField( iField, dfValue );
 }
 
 /************************************************************************/
@@ -3036,15 +3614,38 @@ void OGR_F_SetFieldDouble( OGRFeatureH hFeat, int iField, double dfValue )
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName, const char * pszValue )
+ * \brief Set field to string value.
+ *
+ * OFTInteger fields will be set based on an atoi() conversion of the string.
+ * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
+ * string.  OFTReal fields will be set based on an CPLAtof() conversion of the
+ * string.  Other field types may be unaffected.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param pszValue the value to assign.
+ */
+
+/**
  * \brief Set field to string value.
  *
  * OFTInteger fields will be set based on an atoi() conversion of the string.
- * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the string.
- * OFTReal fields will be set based on an CPLAtof() conversion of the string.
- * Other field types may be unaffected.
+ * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
+ * string.  OFTReal fields will be set based on an CPLAtof() conversion of the
+ * string.  Other field types may be unaffected.
  *
  * This method is the same as the C function OGR_F_SetFieldString().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param pszValue the value to assign.
  */
@@ -3053,51 +3654,63 @@ void OGRFeature::SetField( int iField, const char * pszValue )
 
 {
     static int bWarn = -1;
-    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
-    char *pszLast = NULL;
-
     if( bWarn < 0 )
-        bWarn = CSLTestBoolean( CPLGetConfigOption( "OGR_SETFIELD_NUMERIC_WARNING", "YES" ) );
+        bWarn = CPLTestBool( CPLGetConfigOption( "OGR_SETFIELD_NUMERIC_WARNING",
+                                                 "YES" ) );
 
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
     if( poFDefn == NULL )
         return;
 
+    char *pszLast = NULL;
+
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTString )
     {
-        if( IsFieldSet(iField) )
+        if( IsFieldSetAndNotNull(iField) )
             CPLFree( pauFields[iField].String );
 
-        pauFields[iField].String = VSI_STRDUP_VERBOSE( pszValue ? pszValue : "" );
+        pauFields[iField].String = VSI_STRDUP_VERBOSE(pszValue ? pszValue : "");
         if( pauFields[iField].String == NULL )
         {
-            pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-            pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+            OGR_RawField_SetUnset(&pauFields[iField]);
         }
     }
     else if( eType == OFTInteger )
     {
-        errno = 0; /* As allowed by C standard, some systems like MSVC doesn't reset errno */
+        // As allowed by C standard, some systems like MSVC do not reset errno.
+        errno = 0;
+
         long nVal = strtol(pszValue, &pszLast, 10);
-        nVal = OGRFeatureGetIntegerValue(poFDefn, (int)nVal);
-        pauFields[iField].Integer = (nVal > INT_MAX) ? INT_MAX : (nVal < INT_MIN) ? INT_MIN : (int) nVal;
-        if( bWarn && (errno == ERANGE || nVal != (long)pauFields[iField].Integer || !pszLast || *pszLast ) )
-            CPLError(CE_Warning, CPLE_AppDefined,
-                     "Value '%s' of field %s.%s parsed incompletely to integer %d.",
-                     pszValue, poDefn->GetName(), poFDefn->GetNameRef(), pauFields[iField].Integer );
-        pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+        nVal = OGRFeatureGetIntegerValue(poFDefn, static_cast<int>(nVal));
+        pauFields[iField].Integer =
+            nVal > INT_MAX ? INT_MAX :
+            nVal < INT_MIN ? INT_MIN : static_cast<int>(nVal);
+        if( bWarn && (errno == ERANGE ||
+                      nVal != static_cast<long>(pauFields[iField].Integer) ||
+                      !pszLast || *pszLast ) )
+            CPLError(
+                CE_Warning, CPLE_AppDefined,
+                "Value '%s' of field %s.%s parsed incompletely to integer %d.",
+                pszValue, poDefn->GetName(), poFDefn->GetNameRef(),
+                pauFields[iField].Integer );
+        pauFields[iField].Set.nMarker2 = 0;
+        pauFields[iField].Set.nMarker3 = 0;
     }
     else if( eType == OFTInteger64 )
     {
         pauFields[iField].Integer64 = CPLAtoGIntBigEx(pszValue, bWarn, NULL);
+        pauFields[iField].Set.nMarker3 = 0;
     }
     else if( eType == OFTReal )
     {
         pauFields[iField].Real = CPLStrtod(pszValue, &pszLast);
         if( bWarn && ( !pszLast || *pszLast ) )
-             CPLError(CE_Warning, CPLE_AppDefined,
-                      "Value '%s' of field %s.%s parsed incompletely to real %.16g.",
-                      pszValue, poDefn->GetName(), poFDefn->GetNameRef(), pauFields[iField].Real );
+             CPLError(
+                 CE_Warning, CPLE_AppDefined,
+                 "Value '%s' of field %s.%s parsed incompletely to real %.16g.",
+                 pszValue, poDefn->GetName(), poFDefn->GetNameRef(),
+                 pauFields[iField].Real );
     }
     else if( eType == OFTDate
              || eType == OFTTime
@@ -3112,98 +3725,166 @@ void OGRFeature::SetField( int iField, const char * pszValue )
              || eType == OFTInteger64List
              || eType == OFTRealList )
     {
-        char **papszValueList = NULL;
-
-        if( pszValue[0] == '(' && strchr(pszValue,':') != NULL )
+        json_object* poJSonObj = NULL;
+        if( pszValue[0] == '[' && pszValue[strlen(pszValue)-1] == ']' &&
+            OGRJSonParse(pszValue, &poJSonObj, false) )
         {
-            papszValueList = CSLTokenizeString2(
-                pszValue, ",:()", 0 );
-        }
+            const int nLength = json_object_array_length(poJSonObj);
+            if( eType == OFTIntegerList && nLength > 0 )
+            {
+                std::vector<int> anValues;
+                for( int i = 0; i < nLength; i++ )
+                {
+                    json_object* poItem =
+                        json_object_array_get_idx(poJSonObj, i);
+                    anValues.push_back( json_object_get_int( poItem ) );
+                }
+                SetField( iField, nLength, &(anValues[0]) );
+            }
+            else if( eType == OFTInteger64List && nLength > 0 )
+            {
+                std::vector<GIntBig> anValues;
+                for( int i = 0; i < nLength; i++ )
+                {
+                    json_object* poItem =
+                        json_object_array_get_idx(poJSonObj, i);
+                    anValues.push_back( json_object_get_int64( poItem ) );
+                }
+                SetField( iField, nLength, &(anValues[0]) );
+            }
+            else if( eType == OFTRealList && nLength > 0 )
+            {
+                std::vector<double> adfValues;
+                for( int i = 0; i < nLength; i++ )
+                {
+                    json_object* poItem =
+                        json_object_array_get_idx(poJSonObj, i);
+                    adfValues.push_back( json_object_get_double( poItem ) );
+                }
+                SetField( iField, nLength, &(adfValues[0]) );
+            }
 
-        if( papszValueList == NULL || *papszValueList == NULL
-            || atoi(papszValueList[0]) != CSLCount(papszValueList)-1 )
-        {
-            /* do nothing - the count does not match entries */
+            json_object_put(poJSonObj);
         }
-        else if( eType == OFTIntegerList )
+        else
         {
-            int i, nCount = atoi(papszValueList[0]);
-            std::vector<int> anValues;
-            if( nCount == CSLCount(papszValueList)-1 )
+            char **papszValueList = NULL;
+
+            if( pszValue[0] == '(' && strchr(pszValue, ':') != NULL )
+            {
+                papszValueList = CSLTokenizeString2(
+                    pszValue, ",:()", 0 );
+            }
+
+            if( papszValueList == NULL || *papszValueList == NULL
+                || atoi(papszValueList[0]) != CSLCount(papszValueList)-1 )
+            {
+                // Do nothing - the count does not match entries.
+            }
+            else if( eType == OFTIntegerList )
             {
-                for( i=0; i < nCount; i++ )
+                const int nCount = atoi(papszValueList[0]);
+                std::vector<int> anValues;
+                if( nCount == CSLCount(papszValueList)-1 )
                 {
-                    errno = 0; /* As allowed by C standard, some systems like MSVC doesn't reset errno */
-                    int nVal = atoi(papszValueList[i+1]);
-                    if( errno == ERANGE )
+                    for( int i = 0; i < nCount; i++ )
                     {
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                 "32 bit integer overflow when converting %s",
-                                 pszValue);
+                        // As allowed by C standard, some systems like
+                        // MSVC do not reset errno.
+                        errno = 0;
+                        int nVal = atoi(papszValueList[i+1]);
+                        if( errno == ERANGE )
+                        {
+                            CPLError(
+                                CE_Warning, CPLE_AppDefined,
+                                "32 bit integer overflow when converting %s",
+                                pszValue);
+                        }
+                        anValues.push_back( nVal );
                     }
-                    anValues.push_back( nVal );
+                    SetField( iField, nCount, &(anValues[0]) );
                 }
-                SetField( iField, nCount, &(anValues[0]) );
             }
-        }
-        else if( eType == OFTInteger64List )
-        {
-            int i, nCount = atoi(papszValueList[0]);
-            std::vector<GIntBig> anValues;
-            if( nCount == CSLCount(papszValueList)-1 )
+            else if( eType == OFTInteger64List )
             {
-                for( i=0; i < nCount; i++ )
+                const int nCount = atoi(papszValueList[0]);
+                std::vector<GIntBig> anValues;
+                if( nCount == CSLCount(papszValueList)-1 )
                 {
-                    GIntBig nVal = CPLAtoGIntBigEx(papszValueList[i+1], TRUE, NULL);
-                    anValues.push_back( nVal );
+                    for( int i = 0; i < nCount; i++ )
+                    {
+                        const GIntBig nVal =
+                            CPLAtoGIntBigEx(papszValueList[i+1], TRUE, NULL);
+                        anValues.push_back( nVal );
+                    }
+                    SetField( iField, nCount, &(anValues[0]) );
                 }
-                SetField( iField, nCount, &(anValues[0]) );
             }
-        }
-        else if( eType == OFTRealList )
-        {
-            int i, nCount = atoi(papszValueList[0]);
-            std::vector<double> adfValues;
-            if( nCount == CSLCount(papszValueList)-1 )
+            else if( eType == OFTRealList )
             {
-                for( i=0; i < nCount; i++ )
-                    adfValues.push_back( CPLAtof(papszValueList[i+1]) );
-                SetField( iField, nCount, &(adfValues[0]) );
+                int nCount = atoi(papszValueList[0]);
+                std::vector<double> adfValues;
+                if( nCount == CSLCount(papszValueList)-1 )
+                {
+                    for( int i = 0; i < nCount; i++ )
+                        adfValues.push_back( CPLAtof(papszValueList[i+1]) );
+                    SetField( iField, nCount, &(adfValues[0]) );
+                }
             }
-        }
 
-        CSLDestroy(papszValueList);
+            CSLDestroy(papszValueList);
+        }
     }
-    else if ( eType == OFTStringList )
+    else if( eType == OFTStringList )
     {
         if( pszValue && *pszValue )
         {
-            if( pszValue[0] == '(' && strchr(pszValue,':') != NULL &&
+            json_object* poJSonObj = NULL;
+            if( pszValue[0] == '(' && strchr(pszValue, ':') != NULL &&
                 pszValue[strlen(pszValue)-1] == ')' )
             {
-                char** papszValueList = CSLTokenizeString2(
-                                                        pszValue, ",:()", 0 );
-                int i, nCount = atoi(papszValueList[0]);
+                char** papszValueList =
+                    CSLTokenizeString2(pszValue, ",:()", 0);
+                int nCount = atoi(papszValueList[0]);
                 std::vector<char*> aosValues;
                 if( nCount == CSLCount(papszValueList)-1 )
                 {
-                    for( i=0; i < nCount; i++ )
+                    for( int i = 0; i < nCount; i++ )
                         aosValues.push_back( papszValueList[i+1] );
                     aosValues.push_back( NULL );
                     SetField( iField, &(aosValues[0]) );
                 }
                 CSLDestroy(papszValueList);
             }
+            // Is this a JSon array?
+            else if( pszValue[0] == '[' &&
+                     pszValue[strlen(pszValue)-1] == ']' &&
+                     OGRJSonParse(pszValue, &poJSonObj, false) )
+            {
+                CPLStringList aoList;
+                const int nLength = json_object_array_length(poJSonObj);
+                for( int i = 0; i < nLength; i++ )
+                {
+                    json_object* poItem =
+                        json_object_array_get_idx(poJSonObj, i);
+                    if( !poItem )
+                        aoList.AddString("");
+                    else
+                        aoList.AddString( json_object_get_string(poItem) );
+                }
+                SetField( iField, aoList.List() );
+                json_object_put(poJSonObj);
+            }
             else
             {
                 const char *papszValues[2] = { pszValue, NULL };
-                SetField( iField, (char **) papszValues );
+                SetField( iField, const_cast<char **>(papszValues) );
             }
         }
     }
     else
     {
-        /* do nothing for other field types */;
+        // Do nothing for other field types.
     }
 }
 
@@ -3215,12 +3896,17 @@ void OGRFeature::SetField( int iField, const char * pszValue )
  * \brief Set field to string value.
  *
  * OFTInteger fields will be set based on an atoi() conversion of the string.
- * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the string.
- * OFTReal fields will be set based on an CPLAtof() conversion of the string.
- * Other field types may be unaffected.
+ * OFTInteger64 fields will be set based on an CPLAtoGIntBig() conversion of the
+ * string.  OFTReal fields will be set based on an CPLAtof() conversion of the
+ * string.  Other field types may be unaffected.
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param pszValue the value to assign.
@@ -3231,7 +3917,7 @@ void OGR_F_SetFieldString( OGRFeatureH hFeat, int iField, const char *pszValue)
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldString" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, pszValue );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetField( iField, pszValue );
 }
 
 /************************************************************************/
@@ -3239,6 +3925,23 @@ void OGR_F_SetFieldString( OGRFeatureH hFeat, int iField, const char *pszValue)
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName, int nCount, int *panValues )
+ * \brief Set field to list of integers value.
+ *
+ * This method currently on has an effect of OFTIntegerList, OFTInteger64List
+ * and OFTRealList fields.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param nCount the number of values in the list being assigned.
+ * @param panValues the values to assign.
+ */
+
+/**
  * \brief Set field to list of integers value.
  *
  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
@@ -3246,6 +3949,11 @@ void OGR_F_SetFieldString( OGRFeatureH hFeat, int iField, const char *pszValue)
  *
  * This method is the same as the C function OGR_F_SetFieldIntegerList().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nCount the number of values in the list being assigned.
  * @param panValues the values to assign.
@@ -3254,7 +3962,7 @@ void OGR_F_SetFieldString( OGRFeatureH hFeat, int iField, const char *pszValue)
 void OGRFeature::SetField( int iField, int nCount, int *panValues )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return;
@@ -3262,19 +3970,21 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTIntegerList )
     {
-        OGRField        uField;
-        int            *panValuesMod = NULL;
+        OGRField uField;
+        int *panValuesMod = NULL;
 
-        if( poFDefn->GetSubType() == OFSTBoolean || poFDefn->GetSubType() == OFSTInt16 )
+        if( poFDefn->GetSubType() == OFSTBoolean ||
+            poFDefn->GetSubType() == OFSTInt16 )
         {
-            for( int i=0;i<nCount;i++)
+            for( int i = 0; i < nCount; i++ )
             {
                 int nVal = OGRFeatureGetIntegerValue(poFDefn, panValues[i]);
                 if( panValues[i] != nVal )
                 {
                     if( panValuesMod == NULL )
                     {
-                        panValuesMod = (int*)VSI_MALLOC_VERBOSE(nCount * sizeof(int));
+                        panValuesMod = static_cast<int *>(
+                            VSI_MALLOC_VERBOSE(nCount * sizeof(int)) );
                         if( panValuesMod == NULL )
                             return;
                         memcpy(panValuesMod, panValues, nCount * sizeof(int));
@@ -3286,6 +3996,7 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
 
         uField.IntegerList.nCount = nCount;
         uField.Set.nMarker2 = 0;
+        uField.Set.nMarker3 = 0;
         uField.IntegerList.paList = panValuesMod ? panValuesMod : panValues;
 
         SetField( iField, &uField );
@@ -3295,7 +4006,7 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
     {
         std::vector<GIntBig> anValues;
 
-        for( int i=0; i < nCount; i++ )
+        for( int i = 0; i < nCount; i++ )
             anValues.push_back( panValues[i] );
 
         SetField( iField, nCount, &anValues[0] );
@@ -3304,8 +4015,8 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
     {
         std::vector<double> adfValues;
 
-        for( int i=0; i < nCount; i++ )
-            adfValues.push_back( (double) panValues[i] );
+        for( int i = 0; i < nCount; i++ )
+            adfValues.push_back( static_cast<double>(panValues[i]) );
 
         SetField( iField, nCount, &adfValues[0] );
     }
@@ -3318,10 +4029,11 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
     }
     else if( eType == OFTStringList )
     {
-        char** papszValues = (char**)VSI_MALLOC_VERBOSE((nCount+1) * sizeof(char*));
+        char** papszValues = static_cast<char **>(
+            VSI_MALLOC_VERBOSE((nCount+1) * sizeof(char*)) );
         if( papszValues == NULL )
             return;
-        for( int i=0; i < nCount; i++ )
+        for( int i = 0; i < nCount; i++ )
             papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf("%d", panValues[i]));
         papszValues[nCount] = NULL;
         SetField( iField, papszValues);
@@ -3341,6 +4053,11 @@ void OGRFeature::SetField( int iField, int nCount, int *panValues )
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nCount the number of values in the list being assigned.
@@ -3353,7 +4070,8 @@ void OGR_F_SetFieldIntegerList( OGRFeatureH hFeat, int iField,
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldIntegerList" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, nCount, panValues );
+    reinterpret_cast<OGRFeature *>(hFeat)->
+        SetField( iField, nCount, panValues );
 }
 
 /************************************************************************/
@@ -3361,6 +4079,24 @@ void OGR_F_SetFieldIntegerList( OGRFeatureH hFeat, int iField,
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName, int nCount, const GIntBig
+ * *panValues )
+ * \brief Set field to list of 64 bit integers value.
+ *
+ * This method currently on has an effect of OFTIntegerList, OFTInteger64List
+ * and OFTRealList fields.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param nCount the number of values in the list being assigned.
+ * @param panValues the values to assign.
+ */
+
+/**
  * \brief Set field to list of 64 bit integers value.
  *
  * This method currently on has an effect of OFTIntegerList, OFTInteger64List
@@ -3368,6 +4104,11 @@ void OGR_F_SetFieldIntegerList( OGRFeatureH hFeat, int iField,
  *
  * This method is the same as the C function OGR_F_SetFieldIntege64rList().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nCount the number of values in the list being assigned.
  * @param panValues the values to assign.
@@ -3377,7 +4118,7 @@ void OGR_F_SetFieldIntegerList( OGRFeatureH hFeat, int iField,
 void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return;
@@ -3387,13 +4128,14 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
     {
         std::vector<int> anValues;
 
-        for( int i=0; i < nCount; i++ )
+        for( int i = 0; i < nCount; i++ )
         {
-            GIntBig nValue = panValues[i];
-            int nVal32 = (nValue < INT_MIN ) ? INT_MIN :
-                (nValue > INT_MAX) ? INT_MAX : (int)nValue;
+            const GIntBig nValue = panValues[i];
+            const int nVal32 =
+                nValue < INT_MIN ? INT_MIN :
+                nValue > INT_MAX ? INT_MAX : static_cast<int>(nValue);
 
-            if( (GIntBig)nVal32 != nValue )
+            if( static_cast<GIntBig>(nVal32) != nValue )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Integer overflow occurred when trying to set "
@@ -3409,7 +4151,8 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
         OGRField uField;
         uField.Integer64List.nCount = nCount;
         uField.Set.nMarker2 = 0;
-        uField.Integer64List.paList = (GIntBig*) panValues;
+        uField.Set.nMarker3 = 0;
+        uField.Integer64List.paList = const_cast<GIntBig *>(panValues);
 
         SetField( iField, &uField );
     }
@@ -3417,8 +4160,8 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
     {
         std::vector<double> adfValues;
 
-        for( int i=0; i < nCount; i++ )
-            adfValues.push_back( (double) panValues[i] );
+        for( int i = 0; i < nCount; i++ )
+            adfValues.push_back( static_cast<double>(panValues[i]) );
 
         SetField( iField, nCount, &adfValues[0] );
     }
@@ -3431,11 +4174,13 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
     }
     else if( eType == OFTStringList )
     {
-        char** papszValues = (char**)VSI_MALLOC_VERBOSE((nCount+1) * sizeof(char*));
+        char** papszValues = static_cast<char **>(
+            VSI_MALLOC_VERBOSE((nCount+1) * sizeof(char*)) );
         if( papszValues == NULL )
             return;
-        for( int i=0; i < nCount; i++ )
-            papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf(CPL_FRMT_GIB, panValues[i]));
+        for( int i = 0; i < nCount; i++ )
+            papszValues[i] =
+                VSI_STRDUP_VERBOSE(CPLSPrintf(CPL_FRMT_GIB, panValues[i]));
         papszValues[nCount] = NULL;
         SetField( iField, papszValues);
         CSLDestroy(papszValues);
@@ -3454,6 +4199,11 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nCount the number of values in the list being assigned.
@@ -3462,12 +4212,12 @@ void OGRFeature::SetField( int iField, int nCount, const GIntBig *panValues )
  */
 
 void OGR_F_SetFieldInteger64List( OGRFeatureH hFeat, int iField,
-                                int nCount, const GIntBig *panValues )
+                                  int nCount, const GIntBig *panValues )
 
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldInteger64List" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, nCount, panValues );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetField(iField, nCount, panValues);
 }
 
 /************************************************************************/
@@ -3475,6 +4225,23 @@ void OGR_F_SetFieldInteger64List( OGRFeatureH hFeat, int iField,
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName, int nCount, double * padfValues )
+ * \brief Set field to list of doubles value.
+ *
+ * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
+ * OFTRealList fields.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param nCount the number of values in the list being assigned.
+ * @param padfValues the values to assign.
+ */
+
+/**
  * \brief Set field to list of doubles value.
  *
  * This method currently on has an effect of OFTIntegerList, OFTInteger64List,
@@ -3482,6 +4249,11 @@ void OGR_F_SetFieldInteger64List( OGRFeatureH hFeat, int iField,
  *
  * This method is the same as the C function OGR_F_SetFieldDoubleList().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nCount the number of values in the list being assigned.
  * @param padfValues the values to assign.
@@ -3490,7 +4262,7 @@ void OGR_F_SetFieldInteger64List( OGRFeatureH hFeat, int iField,
 void OGRFeature::SetField( int iField, int nCount, double * padfValues )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return;
@@ -3498,10 +4270,11 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTRealList )
     {
-        OGRField        uField;
+        OGRField uField;
 
         uField.RealList.nCount = nCount;
         uField.Set.nMarker2 = 0;
+        uField.Set.nMarker3 = 0;
         uField.RealList.paList = padfValues;
 
         SetField( iField, &uField );
@@ -3510,8 +4283,8 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
     {
         std::vector<int> anValues;
 
-        for( int i=0; i < nCount; i++ )
-            anValues.push_back( (int) padfValues[i] );
+        for( int i = 0; i < nCount; i++ )
+            anValues.push_back( static_cast<int>(padfValues[i]) );
 
         SetField( iField, nCount, &anValues[0] );
     }
@@ -3519,8 +4292,8 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
     {
         std::vector<GIntBig> anValues;
 
-        for( int i=0; i < nCount; i++ )
-            anValues.push_back( (GIntBig) padfValues[i] );
+        for( int i = 0; i < nCount; i++ )
+            anValues.push_back( static_cast<GIntBig>(padfValues[i]) );
 
         SetField( iField, nCount, &anValues[0] );
     }
@@ -3533,11 +4306,13 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
     }
     else if( eType == OFTStringList )
     {
-        char** papszValues = (char**)VSI_MALLOC_VERBOSE((nCount+1) * sizeof(char*));
+        char** papszValues = static_cast<char **>(
+            VSI_MALLOC_VERBOSE((nCount+1) * sizeof(char*)) );
         if( papszValues == NULL )
             return;
-        for( int i=0; i < nCount; i++ )
-            papszValues[i] = VSI_STRDUP_VERBOSE(CPLSPrintf("%.16g", padfValues[i]));
+        for( int i = 0; i < nCount; i++ )
+            papszValues[i] =
+                VSI_STRDUP_VERBOSE(CPLSPrintf("%.16g", padfValues[i]));
         papszValues[nCount] = NULL;
         SetField( iField, papszValues);
         CSLDestroy(papszValues);
@@ -3556,6 +4331,11 @@ void OGRFeature::SetField( int iField, int nCount, double * padfValues )
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nCount the number of values in the list being assigned.
@@ -3568,7 +4348,7 @@ void OGR_F_SetFieldDoubleList( OGRFeatureH hFeat, int iField,
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldDoubleList" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, nCount, padfValues );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetField(iField, nCount, padfValues);
 }
 
 /************************************************************************/
@@ -3576,12 +4356,32 @@ void OGR_F_SetFieldDoubleList( OGRFeatureH hFeat, int iField,
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName,  char ** papszValues )
+ * \brief Set field to list of strings value.
+ *
+ * This method currently on has an effect of OFTStringList fields.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param papszValues the values to assign.
+ */
+
+/**
  * \brief Set field to list of strings value.
  *
  * This method currently on has an effect of OFTStringList fields.
  *
  * This method is the same as the C function OGR_F_SetFieldStringList().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param papszValues the values to assign.
  */
@@ -3589,7 +4389,7 @@ void OGR_F_SetFieldDoubleList( OGRFeatureH hFeat, int iField,
 void OGRFeature::SetField( int iField, char ** papszValues )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return;
@@ -3597,23 +4397,28 @@ void OGRFeature::SetField( int iField, char ** papszValues )
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTStringList )
     {
-        OGRField        uField;
+        OGRField uField;
 
         uField.StringList.nCount = CSLCount(papszValues);
         uField.Set.nMarker2 = 0;
+        uField.Set.nMarker3 = 0;
         uField.StringList.paList = papszValues;
 
         SetField( iField, &uField );
     }
     else if( eType == OFTIntegerList )
     {
-        int nValues = CSLCount(papszValues);
-        int* panValues = (int*)VSI_MALLOC_VERBOSE(nValues * sizeof(int));
+        const int nValues = CSLCount(papszValues);
+        int* panValues = static_cast<int *>(
+            VSI_MALLOC_VERBOSE(nValues * sizeof(int)) );
         if( panValues == NULL )
             return;
-        for(int i=0;i<nValues;i++)
+        for( int i = 0; i < nValues; i++ )
         {
-            errno = 0; /* As allowed by C standard, some systems like MSVC doesn't reset errno */
+            // As allowed by C standard, some systems like MSVC do not
+            // reset errno.
+            errno = 0;
+
             int nVal = atoi(papszValues[i]);
             if( errno == ERANGE )
             {
@@ -3632,11 +4437,12 @@ void OGRFeature::SetField( int iField, char ** papszValues )
     }
     else if( eType == OFTInteger64List )
     {
-        int nValues = CSLCount(papszValues);
-        GIntBig* panValues = (GIntBig*)VSI_MALLOC_VERBOSE(nValues * sizeof(GIntBig));
+        const int nValues = CSLCount(papszValues);
+        GIntBig* panValues = static_cast<GIntBig *>(
+            VSI_MALLOC_VERBOSE(nValues * sizeof(GIntBig)) );
         if( panValues == NULL )
             return;
-        for(int i=0;i<nValues;i++)
+        for( int i = 0; i < nValues; i++ )
         {
             panValues[i] = CPLAtoGIntBigEx(papszValues[i], TRUE, NULL);
         }
@@ -3645,11 +4451,12 @@ void OGRFeature::SetField( int iField, char ** papszValues )
     }
     else if( eType == OFTRealList )
     {
-        int nValues = CSLCount(papszValues);
-        double* padfValues = (double*)VSI_MALLOC_VERBOSE(nValues * sizeof(double));
+        const int nValues = CSLCount(papszValues);
+        double* padfValues = static_cast<double *>(
+            VSI_MALLOC_VERBOSE(nValues * sizeof(double)) );
         if( padfValues == NULL )
             return;
-        for(int i=0;i<nValues;i++)
+        for( int i = 0; i < nValues; i++ )
         {
             padfValues[i] = CPLAtof(papszValues[i]);
         }
@@ -3669,6 +4476,11 @@ void OGRFeature::SetField( int iField, char ** papszValues )
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param papszValues the values to assign.
@@ -3680,7 +4492,7 @@ void OGR_F_SetFieldStringList( OGRFeatureH hFeat, int iField,
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldStringList" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, papszValues );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetField( iField, papszValues );
 }
 
 /************************************************************************/
@@ -3694,6 +4506,11 @@ void OGR_F_SetFieldStringList( OGRFeatureH hFeat, int iField,
  *
  * This method is the same as the C function OGR_F_SetFieldBinary().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nBytes bytes of data being set.
  * @param pabyData the raw data being applied.
@@ -3702,7 +4519,7 @@ void OGR_F_SetFieldStringList( OGRFeatureH hFeat, int iField,
 void OGRFeature::SetField( int iField, int nBytes, GByte *pabyData )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return;
@@ -3710,17 +4527,18 @@ void OGRFeature::SetField( int iField, int nBytes, GByte *pabyData )
     OGRFieldType eType = poFDefn->GetType();
     if( eType == OFTBinary )
     {
-        OGRField        uField;
+        OGRField uField;
 
         uField.Binary.nCount = nBytes;
         uField.Set.nMarker2 = 0;
+        uField.Set.nMarker3 = 0;
         uField.Binary.paData = pabyData;
 
         SetField( iField, &uField );
     }
     else if( eType == OFTString || eType == OFTStringList )
     {
-        char* pszStr = (char*)VSI_MALLOC_VERBOSE(nBytes + 1);
+        char* pszStr = static_cast<char *>( VSI_MALLOC_VERBOSE(nBytes + 1) );
         if( pszStr == NULL )
             return;
         memcpy(pszStr, pabyData, nBytes);
@@ -3741,6 +4559,11 @@ void OGRFeature::SetField( int iField, int nBytes, GByte *pabyData )
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nBytes the number of bytes in pabyData array.
@@ -3753,7 +4576,7 @@ void OGR_F_SetFieldBinary( OGRFeatureH hFeat, int iField,
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldBinary" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, nBytes, pabyData );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetField( iField, nBytes, pabyData );
 }
 
 /************************************************************************/
@@ -3761,6 +4584,30 @@ void OGR_F_SetFieldBinary( OGRFeatureH hFeat, int iField,
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName, int nYear, int nMonth,
+ *                           int nDay, int nHour, int nMinute, float fSecond,
+ *                           int nTZFlag )
+ * \brief Set field to date.
+ *
+ * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
+ * fields.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param nYear (including century)
+ * @param nMonth (1-12)
+ * @param nDay (1-31)
+ * @param nHour (0-23)
+ * @param nMinute (0-59)
+ * @param fSecond (0-59, with millisecond accuracy)
+ * @param nTZFlag (0=unknown, 1=localtime, 100=GMT, see data model for details)
+ */
+
+/**
  * \brief Set field to date.
  *
  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
@@ -3768,6 +4615,11 @@ void OGR_F_SetFieldBinary( OGRFeatureH hFeat, int iField,
  *
  * This method is the same as the C function OGR_F_SetFieldDateTime().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nYear (including century)
  * @param nMonth (1-12)
@@ -3783,7 +4635,7 @@ void OGRFeature::SetField( int iField, int nYear, int nMonth, int nDay,
                            int nTZFlag )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
 
     if( poFDefn == NULL )
         return;
@@ -3793,24 +4645,24 @@ void OGRFeature::SetField( int iField, int nYear, int nMonth, int nDay,
         || eType == OFTTime
         || eType == OFTDateTime )
     {
-        if( (GInt16)nYear != nYear )
+        if( static_cast<GInt16>(nYear) != nYear )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Years < -32768 or > 32767 are not supported");
             return;
         }
 
-        pauFields[iField].Date.Year = (GInt16)nYear;
-        pauFields[iField].Date.Month = (GByte)nMonth;
-        pauFields[iField].Date.Day = (GByte)nDay;
-        pauFields[iField].Date.Hour = (GByte)nHour;
-        pauFields[iField].Date.Minute = (GByte)nMinute;
+        pauFields[iField].Date.Year = static_cast<GInt16>(nYear);
+        pauFields[iField].Date.Month = static_cast<GByte>(nMonth);
+        pauFields[iField].Date.Day = static_cast<GByte>(nDay);
+        pauFields[iField].Date.Hour = static_cast<GByte>(nHour);
+        pauFields[iField].Date.Minute = static_cast<GByte>(nMinute);
         pauFields[iField].Date.Second = fSecond;
-        pauFields[iField].Date.TZFlag = (GByte)nTZFlag;
+        pauFields[iField].Date.TZFlag = static_cast<GByte>(nTZFlag);
     }
     else if( eType == OFTString || eType == OFTStringList )
     {
-        char szTempBuffer[TEMP_BUFFER_SIZE];
+        char szTempBuffer[TEMP_BUFFER_SIZE] = {};
         OGRFeatureFormatDateTimeBuffer(szTempBuffer,
                                        nYear,
                                        nMonth,
@@ -3833,6 +4685,11 @@ void OGRFeature::SetField( int iField, int nYear, int nMonth, int nDay,
  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
  * fields.
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nYear (including century)
@@ -3851,12 +4708,12 @@ void OGR_F_SetFieldDateTime( OGRFeatureH hFeat, int iField,
                              int nHour, int nMinute, int nSecond,
                              int nTZFlag )
 
-
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldDateTime" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, nYear, nMonth, nDay,
-                                     nHour, nMinute, static_cast<float>(nSecond), nTZFlag );
+    reinterpret_cast<OGRFeature *>(hFeat)->
+        SetField( iField, nYear, nMonth, nDay,
+                  nHour, nMinute, static_cast<float>(nSecond), nTZFlag );
 }
 
 /************************************************************************/
@@ -3869,6 +4726,11 @@ void OGR_F_SetFieldDateTime( OGRFeatureH hFeat, int iField,
  * This method currently only has an effect for OFTDate, OFTTime and OFTDateTime
  * fields.
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to set, from 0 to GetFieldCount()-1.
  * @param nYear (including century)
@@ -3883,16 +4745,16 @@ void OGR_F_SetFieldDateTime( OGRFeatureH hFeat, int iField,
  */
 
 void OGR_F_SetFieldDateTimeEx( OGRFeatureH hFeat, int iField,
-                             int nYear, int nMonth, int nDay,
-                             int nHour, int nMinute, float fSecond,
-                             int nTZFlag )
-
+                               int nYear, int nMonth, int nDay,
+                               int nHour, int nMinute, float fSecond,
+                               int nTZFlag )
 
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldDateTimeEx" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, nYear, nMonth, nDay,
-                                     nHour, nMinute, fSecond, nTZFlag );
+    reinterpret_cast<OGRFeature *>(hFeat)->
+        SetField( iField, nYear, nMonth, nDay,
+                  nHour, nMinute, fSecond, nTZFlag );
 }
 
 /************************************************************************/
@@ -3900,6 +4762,24 @@ void OGR_F_SetFieldDateTimeEx( OGRFeatureH hFeat, int iField,
 /************************************************************************/
 
 /**
+ * \fn OGRFeature::SetField( const char* pszFName, OGRField * puValue )
+ * \brief Set field.
+ *
+ * The passed value OGRField must be of exactly the same type as the
+ * target field, or an application crash may occur.  The passed value
+ * is copied, and will not be affected.  It remains the responsibility of
+ * the caller.
+ *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
+ * @param pszFName the name of the field to set.
+ * @param puValue the value to assign.
+ */
+
+/**
  * \brief Set field.
  *
  * The passed value OGRField must be of exactly the same type as the
@@ -3909,6 +4789,11 @@ void OGR_F_SetFieldDateTimeEx( OGRFeatureH hFeat, int iField,
  *
  * This method is the same as the C function OGR_F_SetFieldRaw().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param puValue the value to assign.
  */
@@ -3922,7 +4807,7 @@ void OGRFeature::SetField( int iField, OGRField * puValue )
 bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
 
 {
-    OGRFieldDefn        *poFDefn = poDefn->GetFieldDefn( iField );
+    OGRFieldDefn *poFDefn = poDefn->GetFieldDefn( iField );
     if( poFDefn == NULL )
         return false;
 
@@ -3934,31 +4819,26 @@ bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
     {
         pauFields[iField] = *puValue;
     }
-    else if( poFDefn->GetType() == OFTInteger64 )
-    {
-        pauFields[iField] = *puValue;
-    }
     else if( poFDefn->GetType() == OFTReal )
     {
         pauFields[iField] = *puValue;
     }
     else if( poFDefn->GetType() == OFTString )
     {
-        if( IsFieldSet( iField ) )
+        if( IsFieldSetAndNotNull(iField) )
             CPLFree( pauFields[iField].String );
 
         if( puValue->String == NULL )
             pauFields[iField].String = NULL;
-        else if( puValue->Set.nMarker1 == OGRUnsetMarker
-                 && puValue->Set.nMarker2 == OGRUnsetMarker )
+        else if( OGR_RawField_IsUnset(puValue) ||
+                 OGR_RawField_IsNull(puValue) )
             pauFields[iField] = *puValue;
         else
         {
             pauFields[iField].String = VSI_STRDUP_VERBOSE( puValue->String );
             if( pauFields[iField].String == NULL )
             {
-                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                OGR_RawField_SetUnset(&pauFields[iField]);
                 return false;
             }
         }
@@ -3971,24 +4851,23 @@ bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
     }
     else if( poFDefn->GetType() == OFTIntegerList )
     {
-        int     nCount = puValue->IntegerList.nCount;
+        const int nCount = puValue->IntegerList.nCount;
 
-        if( IsFieldSet( iField ) )
+        if( IsFieldSetAndNotNull(iField) )
             CPLFree( pauFields[iField].IntegerList.paList );
 
-        if( puValue->Set.nMarker1 == OGRUnsetMarker
-            && puValue->Set.nMarker2 == OGRUnsetMarker )
+        if( OGR_RawField_IsUnset(puValue) ||
+            OGR_RawField_IsNull(puValue) )
         {
             pauFields[iField] = *puValue;
         }
         else
         {
             pauFields[iField].IntegerList.paList =
-                (int *) VSI_MALLOC_VERBOSE(sizeof(int) * nCount);
+                static_cast<int *>( VSI_MALLOC_VERBOSE(sizeof(int) * nCount) );
             if( pauFields[iField].IntegerList.paList == NULL )
             {
-                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                OGR_RawField_SetUnset(&pauFields[iField]);
                 return false;
             }
             memcpy( pauFields[iField].IntegerList.paList,
@@ -3999,24 +4878,23 @@ bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
     }
     else if( poFDefn->GetType() == OFTInteger64List )
     {
-        int     nCount = puValue->Integer64List.nCount;
+        const int nCount = puValue->Integer64List.nCount;
 
-        if( IsFieldSet( iField ) )
+        if( IsFieldSetAndNotNull(iField) )
             CPLFree( pauFields[iField].Integer64List.paList );
 
-        if( puValue->Set.nMarker1 == OGRUnsetMarker
-            && puValue->Set.nMarker2 == OGRUnsetMarker )
+        if( OGR_RawField_IsUnset(puValue) ||
+            OGR_RawField_IsNull(puValue) )
         {
             pauFields[iField] = *puValue;
         }
         else
         {
-            pauFields[iField].Integer64List.paList =
-                (GIntBig *) VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nCount);
+            pauFields[iField].Integer64List.paList = static_cast<GIntBig *>(
+                VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nCount) );
             if( pauFields[iField].Integer64List.paList == NULL )
             {
-                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                OGR_RawField_SetUnset(&pauFields[iField]);
                 return false;
             }
             memcpy( pauFields[iField].Integer64List.paList,
@@ -4027,24 +4905,23 @@ bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
     }
     else if( poFDefn->GetType() == OFTRealList )
     {
-        int     nCount = puValue->RealList.nCount;
+        const int nCount = puValue->RealList.nCount;
 
-        if( IsFieldSet( iField ) )
+        if( IsFieldSetAndNotNull(iField) )
             CPLFree( pauFields[iField].RealList.paList );
 
-        if( puValue->Set.nMarker1 == OGRUnsetMarker
-            && puValue->Set.nMarker2 == OGRUnsetMarker )
+        if( OGR_RawField_IsUnset(puValue) ||
+            OGR_RawField_IsNull(puValue) )
         {
             pauFields[iField] = *puValue;
         }
         else
         {
-            pauFields[iField].RealList.paList =
-                (double *) VSI_MALLOC_VERBOSE(sizeof(double) * nCount);
+            pauFields[iField].RealList.paList = static_cast<double *>(
+                VSI_MALLOC_VERBOSE(sizeof(double) * nCount) );
             if( pauFields[iField].RealList.paList == NULL )
             {
-                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                OGR_RawField_SetUnset(&pauFields[iField]);
                 return false;
             }
             memcpy( pauFields[iField].RealList.paList,
@@ -4055,26 +4932,27 @@ bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
     }
     else if( poFDefn->GetType() == OFTStringList )
     {
-        if( IsFieldSet( iField ) )
+        if( IsFieldSetAndNotNull(iField) )
             CSLDestroy( pauFields[iField].StringList.paList );
 
-        if( puValue->Set.nMarker1 == OGRUnsetMarker
-            && puValue->Set.nMarker2 == OGRUnsetMarker )
+        if( OGR_RawField_IsUnset(puValue) ||
+            OGR_RawField_IsNull(puValue) )
         {
             pauFields[iField] = *puValue;
         }
         else
         {
             char** papszNewList = NULL;
-            char** papszIter = puValue->StringList.paList;
-            for(; papszIter != NULL && *papszIter != NULL; ++papszIter )
+            for( char** papszIter = puValue->StringList.paList;
+                 papszIter != NULL && *papszIter != NULL;
+                 ++papszIter )
             {
-                char** papszNewList2 = CSLAddStringMayFail(papszNewList, *papszIter);
+                char** papszNewList2 =
+                    CSLAddStringMayFail(papszNewList, *papszIter);
                 if( papszNewList2 == NULL )
                 {
                     CSLDestroy(papszNewList);
-                    pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-                    pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                    OGR_RawField_SetUnset(&pauFields[iField]);
                     return false;
                 }
                 papszNewList = papszNewList2;
@@ -4087,22 +4965,21 @@ bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
     }
     else if( poFDefn->GetType() == OFTBinary )
     {
-        if( IsFieldSet( iField ) )
+        if( IsFieldSetAndNotNull(iField) )
             CPLFree( pauFields[iField].Binary.paData );
 
-        if( puValue->Set.nMarker1 == OGRUnsetMarker
-            && puValue->Set.nMarker2 == OGRUnsetMarker )
+        if( OGR_RawField_IsUnset(puValue) ||
+            OGR_RawField_IsNull(puValue) )
         {
             pauFields[iField] = *puValue;
         }
         else
         {
-            pauFields[iField].Binary.paData =
-                (GByte *) VSI_MALLOC_VERBOSE(puValue->Binary.nCount);
+            pauFields[iField].Binary.paData = static_cast<GByte *>(
+                VSI_MALLOC_VERBOSE(puValue->Binary.nCount) );
             if( pauFields[iField].Binary.paData == NULL )
             {
-                pauFields[iField].Set.nMarker1 = OGRUnsetMarker;
-                pauFields[iField].Set.nMarker2 = OGRUnsetMarker;
+                OGR_RawField_SetUnset(&pauFields[iField]);
                 return false;
             }
             memcpy( pauFields[iField].Binary.paData,
@@ -4113,7 +4990,7 @@ bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
     }
     else
     {
-        /* do nothing for other field types */
+        // Do nothing for other field types.
     }
     return true;
 }
@@ -4132,6 +5009,11 @@ bool OGRFeature::SetFieldInternal( int iField, OGRField * puValue )
  *
  * This function is the same as the C++ method OGRFeature::SetField().
  *
+ * @note This method has only an effect on the in-memory feature object. If
+ * this object comes from a layer and the modifications must be serialized back
+ * to the datasource, OGR_L_SetFeature() must be used afterwards. Or if this is
+ * a new feature, OGR_L_CreateFeature() must be used afterwards.
+ *
  * @param hFeat handle to the feature that owned the field.
  * @param iField the field to fetch, from 0 to GetFieldCount()-1.
  * @param psValue handle on the value to assign.
@@ -4142,7 +5024,7 @@ void OGR_F_SetFieldRaw( OGRFeatureH hFeat, int iField, OGRField *psValue )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetFieldRaw" );
 
-    ((OGRFeature *)hFeat)->SetField( iField, psValue );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetField( iField, psValue );
 }
 
 /************************************************************************/
@@ -4177,62 +5059,68 @@ void OGRFeature::DumpReadable( FILE * fpOut, char** papszOptions )
     if( fpOut == NULL )
         fpOut = stdout;
 
-    fprintf( fpOut, "OGRFeature(%s):" CPL_FRMT_GIB "\n", poDefn->GetName(), GetFID() );
+    char szFID[32];
+    CPLsnprintf(szFID, sizeof(szFID), CPL_FRMT_GIB, GetFID());
+    fprintf( fpOut,
+             "OGRFeature(%s):%s\n", poDefn->GetName(), szFID );
 
     const char* pszDisplayFields =
-            CSLFetchNameValue(papszOptions, "DISPLAY_FIELDS");
-    if (pszDisplayFields == NULL || CSLTestBoolean(pszDisplayFields))
+        CSLFetchNameValue(papszOptions, "DISPLAY_FIELDS");
+    if( pszDisplayFields == NULL || CPLTestBool(pszDisplayFields) )
     {
         for( int iField = 0; iField < GetFieldCount(); iField++ )
         {
-            OGRFieldDefn    *poFDefn = poDefn->GetFieldDefn(iField);
+            if( !IsFieldSet( iField) )
+                continue;
+            OGRFieldDefn *poFDefn = poDefn->GetFieldDefn(iField);
 
             const char* pszType = (poFDefn->GetSubType() != OFSTNone) ?
-                CPLSPrintf("%s(%s)",
-                           poFDefn->GetFieldTypeName( poFDefn->GetType() ),
-                           poFDefn->GetFieldSubTypeName(poFDefn->GetSubType())) :
-                poFDefn->GetFieldTypeName( poFDefn->GetType() );
+                CPLSPrintf(
+                    "%s(%s)",
+                    poFDefn->GetFieldTypeName( poFDefn->GetType() ),
+                    poFDefn->GetFieldSubTypeName(poFDefn->GetSubType())) :
+                    poFDefn->GetFieldTypeName( poFDefn->GetType() );
 
             fprintf( fpOut, "  %s (%s) = ",
                     poFDefn->GetNameRef(),
                     pszType );
 
-            if( IsFieldSet( iField ) )
-                fprintf( fpOut, "%s\n", GetFieldAsString( iField ) );
-            else
+            if( IsFieldNull( iField) )
                 fprintf( fpOut, "(null)\n" );
-
+            else
+                fprintf( fpOut, "%s\n", GetFieldAsString( iField ) );
         }
     }
 
-
     if( GetStyleString() != NULL )
     {
         const char* pszDisplayStyle =
             CSLFetchNameValue(papszOptions, "DISPLAY_STYLE");
-        if (pszDisplayStyle == NULL || CSLTestBoolean(pszDisplayStyle))
+        if( pszDisplayStyle == NULL || CPLTestBool(pszDisplayStyle) )
         {
             fprintf( fpOut, "  Style = %s\n", GetStyleString() );
         }
     }
 
-    int nGeomFieldCount = GetGeomFieldCount();
+    const int nGeomFieldCount = GetGeomFieldCount();
     if( nGeomFieldCount > 0 )
     {
         const char* pszDisplayGeometry =
-                CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
-        if ( ! (pszDisplayGeometry != NULL && EQUAL(pszDisplayGeometry, "NO") ) )
+            CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
+        if( !(pszDisplayGeometry != NULL && EQUAL(pszDisplayGeometry, "NO")) )
         {
             for( int iField = 0; iField < nGeomFieldCount; iField++ )
             {
-                OGRGeomFieldDefn    *poFDefn = poDefn->GetGeomFieldDefn(iField);
+                OGRGeomFieldDefn *poFDefn = poDefn->GetGeomFieldDefn(iField);
 
                 if( papoGeometries[iField] != NULL )
                 {
                     fprintf( fpOut, "  " );
-                    if( strlen(poFDefn->GetNameRef()) > 0 && GetGeomFieldCount() > 1 )
+                    if( strlen(poFDefn->GetNameRef()) > 0 &&
+                        GetGeomFieldCount() > 1 )
                         fprintf( fpOut, "%s = ", poFDefn->GetNameRef() );
-                    papoGeometries[iField]->dumpReadable( fpOut, "", papszOptions );
+                    papoGeometries[iField]->dumpReadable( fpOut, "",
+                                                          papszOptions );
                 }
             }
         }
@@ -4263,7 +5151,7 @@ void OGR_F_DumpReadable( OGRFeatureH hFeat, FILE *fpOut )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_DumpReadable" );
 
-    ((OGRFeature *) hFeat)->DumpReadable( fpOut );
+    reinterpret_cast<OGRFeature *>(hFeat)->DumpReadable( fpOut );
 }
 
 /************************************************************************/
@@ -4271,7 +5159,7 @@ void OGR_F_DumpReadable( OGRFeatureH hFeat, FILE *fpOut )
 /************************************************************************/
 
 /**
- * \fn GIntBig OGRFeature::GetFID();
+ * \fn GIntBig OGRFeature::GetFID() const;
  *
  * \brief Get feature identifier.
  *
@@ -4301,7 +5189,7 @@ GIntBig OGR_F_GetFID( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetFID", 0 );
 
-    return ((OGRFeature *) hFeat)->GetFID();
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetFID();
 }
 
 /************************************************************************/
@@ -4356,7 +5244,7 @@ OGRErr OGR_F_SetFID( OGRFeatureH hFeat, GIntBig nFID )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_SetFID", OGRERR_FAILURE );
 
-    return ((OGRFeature *) hFeat)->SetFID(nFID);
+    return reinterpret_cast<OGRFeature *>(hFeat)->SetFID(nFID);
 }
 
 /************************************************************************/
@@ -4389,17 +5277,17 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
     if( GetDefnRef() != poFeature->GetDefnRef() )
         return FALSE;
 
-    int i;
-    int nFields = GetDefnRef()->GetFieldCount();
-    for(i=0; i<nFields; i++)
+    const int nFields = GetDefnRef()->GetFieldCount();
+    for( int i = 0; i < nFields; i++ )
     {
         if( IsFieldSet(i) != poFeature->IsFieldSet(i) )
             return FALSE;
-
-        if( !IsFieldSet(i) )
+        if( IsFieldNull(i) != poFeature->IsFieldNull(i) )
+            return FALSE;
+        if( !IsFieldSetAndNotNull(i) )
             continue;
 
-        switch (GetDefnRef()->GetFieldDefn(i)->GetType() )
+        switch( GetDefnRef()->GetFieldDefn(i)->GetType() )
         {
             case OFTInteger:
                 if( GetFieldAsInteger(i) !=
@@ -4420,21 +5308,21 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
                 break;
 
             case OFTString:
-                if ( strcmp(GetFieldAsString(i),
-                            poFeature->GetFieldAsString(i)) != 0 )
+                if( strcmp(GetFieldAsString(i),
+                           poFeature->GetFieldAsString(i)) != 0 )
                     return FALSE;
                 break;
 
             case OFTIntegerList:
             {
-                int nCount1, nCount2;
+                int nCount1 = 0;
+                int nCount2 = 0;
                 const int* pnList1 = GetFieldAsIntegerList(i, &nCount1);
                 const int* pnList2 =
-                          poFeature->GetFieldAsIntegerList(i, &nCount2);
+                    poFeature->GetFieldAsIntegerList(i, &nCount2);
                 if( nCount1 != nCount2 )
                     return FALSE;
-                int j;
-                for(j=0;j<nCount1;j++)
+                for( int j = 0; j < nCount1; j++ )
                 {
                     if( pnList1[j] != pnList2[j] )
                         return FALSE;
@@ -4444,14 +5332,14 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
 
             case OFTInteger64List:
             {
-                int nCount1, nCount2;
+                int nCount1 = 0;
+                int nCount2 = 0;
                 const GIntBig* pnList1 = GetFieldAsInteger64List(i, &nCount1);
                 const GIntBig* pnList2 =
-                          poFeature->GetFieldAsInteger64List(i, &nCount2);
+                    poFeature->GetFieldAsInteger64List(i, &nCount2);
                 if( nCount1 != nCount2 )
                     return FALSE;
-                int j;
-                for(j=0;j<nCount1;j++)
+                for( int j = 0; j < nCount1; j++ )
                 {
                     if( pnList1[j] != pnList2[j] )
                         return FALSE;
@@ -4461,15 +5349,14 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
 
             case OFTRealList:
             {
-                int nCount1, nCount2;
-                const double* padfList1 =
-                                   GetFieldAsDoubleList(i, &nCount1);
+                int nCount1 = 0;
+                int nCount2 = 0;
+                const double* padfList1 = GetFieldAsDoubleList(i, &nCount1);
                 const double* padfList2 =
-                        poFeature->GetFieldAsDoubleList(i, &nCount2);
+                    poFeature->GetFieldAsDoubleList(i, &nCount2);
                 if( nCount1 != nCount2 )
                     return FALSE;
-                int j;
-                for(j=0;j<nCount1;j++)
+                for( int j = 0; j < nCount1; j++ )
                 {
                     if( padfList1[j] != padfList2[j] )
                         return FALSE;
@@ -4479,15 +5366,15 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
 
             case OFTStringList:
             {
-                int nCount1, nCount2;
+                int nCount1 = 0;
+                int nCount2 = 0;
                 char** papszList1 = GetFieldAsStringList(i);
                 char** papszList2 = poFeature->GetFieldAsStringList(i);
                 nCount1 = CSLCount(papszList1);
                 nCount2 = CSLCount(papszList2);
                 if( nCount1 != nCount2 )
                     return FALSE;
-                int j;
-                for(j=0;j<nCount1;j++)
+                for( int j = 0; j < nCount1; j++ )
                 {
                     if( strcmp(papszList1[j], papszList2[j]) != 0 )
                         return FALSE;
@@ -4499,11 +5386,20 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
             case OFTDate:
             case OFTDateTime:
             {
-                int nYear1, nMonth1, nDay1, nHour1,
-                    nMinute1, nTZFlag1;
-                int nYear2, nMonth2, nDay2, nHour2,
-                    nMinute2, nTZFlag2;
-                float fSecond1, fSecond2;
+                int nYear1 = 0;
+                int nMonth1 = 0;
+                int nDay1 = 0;
+                int nHour1 = 0;
+                int nMinute1 = 0;
+                int nTZFlag1 = 0;
+                int nYear2 = 0;
+                int nMonth2 = 0;
+                int nDay2 = 0;
+                int nHour2 = 0;
+                int nMinute2 = 0;
+                int nTZFlag2 = 0;
+                float fSecond1 = 0.0f;
+                float fSecond2 = 0.0f;
                 GetFieldAsDateTime(i, &nYear1, &nMonth1, &nDay1,
                               &nHour1, &nMinute1, &fSecond1, &nTZFlag1);
                 poFeature->GetFieldAsDateTime(i, &nYear2, &nMonth2, &nDay2,
@@ -4519,7 +5415,8 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
 
             case OFTBinary:
             {
-                int nCount1, nCount2;
+                int nCount1 = 0;
+                int nCount2 = 0;
                 GByte* pabyData1 = GetFieldAsBinary(i, &nCount1);
                 GByte* pabyData2 = poFeature->GetFieldAsBinary(i, &nCount2);
                 if( nCount1 != nCount2 )
@@ -4537,8 +5434,8 @@ OGRBoolean OGRFeature::Equal( OGRFeature * poFeature )
         }
     }
 
-    int nGeomFieldCount = GetGeomFieldCount();
-    for( i = 0; i < nGeomFieldCount; i ++ )
+    const int nGeomFieldCount = GetGeomFieldCount();
+    for( int i = 0; i < nGeomFieldCount; i++ )
     {
         OGRGeometry* poThisGeom = GetGeomFieldRef(i);
         OGRGeometry* poOtherGeom = poFeature->GetGeomFieldRef(i);
@@ -4582,10 +5479,10 @@ int OGR_F_Equal( OGRFeatureH hFeat, OGRFeatureH hOtherFeat )
     VALIDATE_POINTER1( hFeat, "OGR_F_Equal", 0 );
     VALIDATE_POINTER1( hOtherFeat, "OGR_F_Equal", 0 );
 
-    return ((OGRFeature *) hFeat)->Equal( (OGRFeature *) hOtherFeat );
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        Equal( reinterpret_cast<OGRFeature *>(hOtherFeat) );
 }
 
-
 /************************************************************************/
 /*                              SetFrom()                               */
 /************************************************************************/
@@ -4617,13 +5514,11 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int bForgiving )
 /* -------------------------------------------------------------------- */
 /*      Retrieve the field ids by name.                                 */
 /* -------------------------------------------------------------------- */
-    int         iField, *panMap;
-    OGRErr      eErr;
-
-    panMap = (int *) VSI_MALLOC_VERBOSE( sizeof(int) * poSrcFeature->GetFieldCount() );
+    int *panMap = static_cast<int *>(
+        VSI_MALLOC_VERBOSE( sizeof(int) * poSrcFeature->GetFieldCount() ) );
     if( panMap == NULL )
         return OGRERR_FAILURE;
-    for( iField = 0; iField < poSrcFeature->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poSrcFeature->GetFieldCount(); iField++ )
     {
         panMap[iField] = GetFieldIndex(
             poSrcFeature->GetFieldDefnRef(iField)->GetNameRef() );
@@ -4640,7 +5535,7 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int bForgiving )
         }
     }
 
-    eErr = SetFrom( poSrcFeature, panMap, bForgiving );
+    const OGRErr eErr = SetFrom( poSrcFeature, panMap, bForgiving );
 
     VSIFree(panMap);
 
@@ -4680,8 +5575,10 @@ OGRErr OGR_F_SetFrom( OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
     VALIDATE_POINTER1( hFeat, "OGR_F_SetFrom", OGRERR_FAILURE );
     VALIDATE_POINTER1( hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE );
 
-    return ((OGRFeature *) hFeat)->SetFrom( (OGRFeature *) hOtherFeat,
-                                           bForgiving );
+    return
+        reinterpret_cast<OGRFeature *>(hFeat)->
+            SetFrom( reinterpret_cast<OGRFeature *>(hOtherFeat),
+                     bForgiving );
 }
 
 /************************************************************************/
@@ -4720,8 +5617,6 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
                             int bForgiving )
 
 {
-    OGRErr      eErr;
-
     if( poSrcFeature == this )
         return OGRERR_FAILURE;
 
@@ -4739,18 +5634,18 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
         if( iSrc >= 0 )
             SetGeomField( 0, poSrcFeature->GetGeomFieldRef(iSrc) );
         else
-            /* whatever the geometry field names are. For backward compatibility */
+            // Whatever the geometry field names are.  For backward
+            // compatibility.
             SetGeomField( 0, poSrcFeature->GetGeomFieldRef(0) );
     }
     else
     {
-        int i;
-        for(i = 0; i < GetGeomFieldCount(); i++)
+        for( int i = 0; i < GetGeomFieldCount(); i++ )
         {
             OGRGeomFieldDefn* poGFieldDefn = GetGeomFieldDefnRef(i);
 
-            int iSrc = poSrcFeature->GetGeomFieldIndex(
-                                        poGFieldDefn->GetNameRef());
+            const int iSrc =
+                poSrcFeature->GetGeomFieldIndex(poGFieldDefn->GetNameRef());
             if( iSrc >= 0 )
                 SetGeomField( i, poSrcFeature->GetGeomFieldRef(iSrc) );
             else
@@ -4773,7 +5668,7 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
 /*      Set the fields by name.                                         */
 /* -------------------------------------------------------------------- */
 
-    eErr = SetFieldsFrom( poSrcFeature, panMap, bForgiving );
+    const OGRErr eErr = SetFieldsFrom( poSrcFeature, panMap, bForgiving );
     if( eErr != OGRERR_NONE )
         return eErr;
 
@@ -4814,15 +5709,16 @@ OGRErr OGRFeature::SetFrom( OGRFeature * poSrcFeature, int *panMap ,
  */
 
 OGRErr OGR_F_SetFromWithMap( OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
-                      int bForgiving, int *panMap )
+                             int bForgiving, int *panMap )
 
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_SetFrom", OGRERR_FAILURE );
     VALIDATE_POINTER1( hOtherFeat, "OGR_F_SetFrom", OGRERR_FAILURE );
     VALIDATE_POINTER1( panMap, "OGR_F_SetFrom", OGRERR_FAILURE);
 
-    return ((OGRFeature *) hFeat)->SetFrom( (OGRFeature *) hOtherFeat,
-                                           panMap, bForgiving );
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+      SetFrom( reinterpret_cast<OGRFeature *>(hOtherFeat),
+                 panMap, bForgiving );
 }
 
 /************************************************************************/
@@ -4856,15 +5752,13 @@ OGRErr OGR_F_SetFromWithMap( OGRFeatureH hFeat, OGRFeatureH hOtherFeat,
  * not transferred, otherwise an error code.
  */
 
-OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
+OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap,
                                   int bForgiving )
 
 {
-    int         iField, iDstField;
-
-    for( iField = 0; iField < poSrcFeature->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poSrcFeature->GetFieldCount(); iField++ )
     {
-        iDstField = panMap[iField];
+        const int iDstField = panMap[iField];
 
         if( iDstField < 0 )
             continue;
@@ -4878,6 +5772,12 @@ OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
             continue;
         }
 
+        if( poSrcFeature->IsFieldNull(iField) )
+        {
+            SetFieldNull( iDstField );
+            continue;
+        }
+
         switch( poSrcFeature->GetFieldDefnRef(iField)->GetType() )
         {
           case OFTInteger:
@@ -4898,29 +5798,31 @@ OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
 
           case OFTIntegerList:
           {
-              if (GetFieldDefnRef(iDstField)->GetType() == OFTString)
+              if( GetFieldDefnRef(iDstField)->GetType() == OFTString )
               {
                   SetField( iDstField, poSrcFeature->GetFieldAsString(iField) );
               }
               else
               {
-                  int nCount;
-                  const int *panValues = poSrcFeature->GetFieldAsIntegerList( iField, &nCount);
-                  SetField( iDstField, nCount, (int*) panValues );
+                  int nCount = 0;
+                  const int *panValues =
+                      poSrcFeature->GetFieldAsIntegerList( iField, &nCount);
+                  SetField(iDstField, nCount, const_cast<int *>(panValues));
               }
           }
           break;
 
           case OFTInteger64List:
           {
-              if (GetFieldDefnRef(iDstField)->GetType() == OFTString)
+              if( GetFieldDefnRef(iDstField)->GetType() == OFTString )
               {
                   SetField( iDstField, poSrcFeature->GetFieldAsString(iField) );
               }
               else
               {
-                  int nCount;
-                  const GIntBig *panValues = poSrcFeature->GetFieldAsInteger64List( iField, &nCount);
+                  int nCount = 0;
+                  const GIntBig *panValues =
+                      poSrcFeature->GetFieldAsInteger64List( iField, &nCount);
                   SetField( iDstField, nCount, panValues );
               }
           }
@@ -4928,15 +5830,16 @@ OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
 
           case OFTRealList:
           {
-              if (GetFieldDefnRef(iDstField)->GetType() == OFTString)
+              if( GetFieldDefnRef(iDstField)->GetType() == OFTString )
               {
                   SetField( iDstField, poSrcFeature->GetFieldAsString(iField) );
               }
               else
               {
-                  int nCount;
-                  const double *padfValues = poSrcFeature->GetFieldAsDoubleList( iField, &nCount);
-                  SetField( iDstField, nCount, (double*) padfValues );
+                  int nCount = 0;
+                  const double *padfValues =
+                      poSrcFeature->GetFieldAsDoubleList( iField, &nCount);
+                  SetField(iDstField, nCount, const_cast<double *>(padfValues));
               }
           }
           break;
@@ -4946,7 +5849,7 @@ OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
           case OFTTime:
           {
             OGRFieldType eDstFieldType = GetFieldDefnRef(iDstField)->GetType();
-            if (eDstFieldType == OFTDate ||
+            if( eDstFieldType == OFTDate ||
                 eDstFieldType == OFTTime ||
                 eDstFieldType == OFTDateTime )
             {
@@ -4965,11 +5868,12 @@ OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
           default:
           {
             OGRFieldType eDstFieldType = GetFieldDefnRef(iDstField)->GetType();
-            if( poSrcFeature->GetFieldDefnRef(iField)->GetType() == eDstFieldType )
+            if( poSrcFeature->GetFieldDefnRef(iField)->GetType()
+                == eDstFieldType )
             {
                 SetField( iDstField, poSrcFeature->GetRawFieldRef(iField) );
             }
-            else if (eDstFieldType == OFTString ||
+            else if( eDstFieldType == OFTString ||
                      eDstFieldType == OFTStringList )
             {
                 SetField( iDstField, poSrcFeature->GetFieldAsString( iField ) );
@@ -5002,13 +5906,11 @@ OGRErr OGRFeature::SetFieldsFrom( OGRFeature * poSrcFeature, int *panMap ,
 
 const char *OGRFeature::GetStyleString()
 {
-    int  iStyleFieldIndex;
-
-    if (m_pszStyleString)
+    if( m_pszStyleString )
         return m_pszStyleString;
 
-    iStyleFieldIndex = GetFieldIndex("OGR_STYLE");
-    if (iStyleFieldIndex >= 0)
+    const int iStyleFieldIndex = GetFieldIndex("OGR_STYLE");
+    if( iStyleFieldIndex >= 0 )
         return GetFieldAsString(iStyleFieldIndex);
 
     return NULL;
@@ -5035,7 +5937,7 @@ const char *OGR_F_GetStyleString( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetStyleString", NULL );
 
-    return ((OGRFeature *)hFeat)->GetStyleString();
+    return reinterpret_cast<OGRFeature *>(hFeat)->GetStyleString();
 }
 
 /************************************************************************/
@@ -5044,9 +5946,10 @@ const char *OGR_F_GetStyleString( OGRFeatureH hFeat )
 
 /**
  * \brief Set feature style string.
- * This method operate exactly as
- * OGRFeature::SetStyleStringDirectly() except that it does not assume
- * ownership of the passed string, but instead makes a copy of it.
+ *
+ * This method operate exactly as OGRFeature::SetStyleStringDirectly() except
+ * that it does not assume ownership of the passed string, but instead makes a
+ * copy of it.
  *
  * This method is the same as the C function OGR_F_SetStyleString().
  *
@@ -5055,7 +5958,7 @@ const char *OGR_F_GetStyleString( OGRFeatureH hFeat )
 
 void OGRFeature::SetStyleString(const char *pszString)
 {
-    if (m_pszStyleString)
+    if( m_pszStyleString )
     {
         CPLFree(m_pszStyleString);
         m_pszStyleString = NULL;
@@ -5071,9 +5974,10 @@ void OGRFeature::SetStyleString(const char *pszString)
 
 /**
  * \brief Set feature style string.
- * This method operate exactly as
- * OGR_F_SetStyleStringDirectly() except that it does not assume ownership
- * of the passed string, but instead makes a copy of it.
+ *
+ * This method operate exactly as OGR_F_SetStyleStringDirectly() except that it
+ * does not assume ownership of the passed string, but instead makes a copy of
+ * it.
  *
  * This function is the same as the C++ method OGRFeature::SetStyleString().
  *
@@ -5086,7 +5990,7 @@ void OGR_F_SetStyleString( OGRFeatureH hFeat, const char *pszStyle )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetStyleString" );
 
-    ((OGRFeature *)hFeat)->SetStyleString( pszStyle );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetStyleString(pszStyle);
 }
 
 /************************************************************************/
@@ -5095,19 +5999,18 @@ void OGR_F_SetStyleString( OGRFeatureH hFeat, const char *pszStyle )
 
 /**
  * \brief Set feature style string.
- * This method operate exactly as
- * OGRFeature::SetStyleString() except that it assumes ownership of the passed
- * string.
+ *
+ * This method operate exactly as OGRFeature::SetStyleString() except that it
+ * assumes ownership of the passed string.
  *
  * This method is the same as the C function OGR_F_SetStyleStringDirectly().
  *
  * @param pszString the style string to apply to this feature, cannot be NULL.
  */
 
-void OGRFeature::SetStyleStringDirectly(char *pszString)
+void OGRFeature::SetStyleStringDirectly( char *pszString )
 {
-    if (m_pszStyleString)
-        CPLFree(m_pszStyleString);
+    CPLFree(m_pszStyleString);
     m_pszStyleString = pszString;
 }
 
@@ -5117,9 +6020,9 @@ void OGRFeature::SetStyleStringDirectly(char *pszString)
 
 /**
  * \brief Set feature style string.
- * This method operate exactly as
- * OGR_F_SetStyleString() except that it assumes ownership of the passed
- * string.
+ *
+ * This method operate exactly as OGR_F_SetStyleString() except that it assumes
+ * ownership of the passed string.
  *
  * This function is the same as the C++ method
  * OGRFeature::SetStyleStringDirectly().
@@ -5133,30 +6036,39 @@ void OGR_F_SetStyleStringDirectly( OGRFeatureH hFeat, char *pszStyle )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetStyleStringDirectly" );
 
-    ((OGRFeature *)hFeat)->SetStyleStringDirectly( pszStyle );
+    reinterpret_cast<OGRFeature *>(hFeat)->SetStyleStringDirectly(pszStyle);
 }
 
 //************************************************************************/
 /*                           SetStyleTable()                            */
 /************************************************************************/
-void OGRFeature::SetStyleTable(OGRStyleTable *poStyleTable)
+
+/** Set style table.
+ * @param poStyleTable new style table (will be cloned)
+ */
+void OGRFeature::SetStyleTable( OGRStyleTable *poStyleTable )
 {
-    if ( m_poStyleTable )
+    if( m_poStyleTable )
         delete m_poStyleTable;
-    m_poStyleTable = ( poStyleTable ) ? poStyleTable->Clone() : NULL;
+    m_poStyleTable = poStyleTable ? poStyleTable->Clone() : NULL;
 }
 
 //************************************************************************/
 /*                          SetStyleTableDirectly()                      */
 /************************************************************************/
 
-void OGRFeature::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
+/** Set style table.
+ * @param poStyleTable new style table (ownership transferred to the object)
+ */
+void OGRFeature::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
 {
-    if ( m_poStyleTable )
+    if( m_poStyleTable )
         delete m_poStyleTable;
     m_poStyleTable = poStyleTable;
 }
 
+//! @cond Doxygen_Suppress
+
 /************************************************************************/
 /*                            RemapFields()                             */
 /*                                                                      */
@@ -5168,21 +6080,17 @@ OGRErr OGRFeature::RemapFields( OGRFeatureDefn *poNewDefn,
                                 int *panRemapSource )
 
 {
-    int  iDstField;
-    OGRField *pauNewFields;
-
     if( poNewDefn == NULL )
         poNewDefn = poDefn;
 
-    pauNewFields = (OGRField *) CPLCalloc( poNewDefn->GetFieldCount(),
-                                           sizeof(OGRField) );
+    OGRField *pauNewFields = static_cast<OGRField *>(
+        CPLCalloc( poNewDefn->GetFieldCount(), sizeof(OGRField) ) );
 
-    for( iDstField = 0; iDstField < poDefn->GetFieldCount(); iDstField++ )
+    for( int iDstField = 0; iDstField < poDefn->GetFieldCount(); iDstField++ )
     {
         if( panRemapSource[iDstField] == -1 )
         {
-            pauNewFields[iDstField].Set.nMarker1 = OGRUnsetMarker;
-            pauNewFields[iDstField].Set.nMarker2 = OGRUnsetMarker;
+            OGR_RawField_SetUnset(&pauNewFields[iDstField]);
         }
         else
         {
@@ -5192,11 +6100,9 @@ OGRErr OGRFeature::RemapFields( OGRFeatureDefn *poNewDefn,
         }
     }
 
-    /*
-    ** We really should be freeing memory for old columns that
-    ** are no longer present.  We don't for now because it is a bit messy
-    ** and would take too long to test.
-    */
+    // We really should be freeing memory for old columns that
+    // are no longer present.  We don't for now because it is a bit messy
+    // and would take too long to test.
 
 /* -------------------------------------------------------------------- */
 /*      Apply new definition and fields.                                */
@@ -5220,16 +6126,15 @@ OGRErr OGRFeature::RemapGeomFields( OGRFeatureDefn *poNewDefn,
                                     int *panRemapSource )
 
 {
-    int  iDstField;
-    OGRGeometry** papoNewGeomFields;
-
     if( poNewDefn == NULL )
         poNewDefn = poDefn;
 
-    papoNewGeomFields = (OGRGeometry **) CPLCalloc( poNewDefn->GetGeomFieldCount(),
-                                           sizeof(OGRGeometry*) );
+    OGRGeometry** papoNewGeomFields = static_cast<OGRGeometry **>(
+        CPLCalloc( poNewDefn->GetGeomFieldCount(), sizeof(OGRGeometry*) ) );
 
-    for( iDstField = 0; iDstField < poDefn->GetGeomFieldCount(); iDstField++ )
+    for( int iDstField = 0;
+         iDstField < poDefn->GetGeomFieldCount();
+         iDstField++ )
     {
         if( panRemapSource[iDstField] == -1 )
         {
@@ -5242,11 +6147,9 @@ OGRErr OGRFeature::RemapGeomFields( OGRFeatureDefn *poNewDefn,
         }
     }
 
-    /*
-    ** We really should be freeing memory for old columns that
-    ** are no longer present.  We don't for now because it is a bit messy
-    ** and would take too long to test.
-    */
+    // We really should be freeing memory for old columns that
+    // are no longer present.  We don't for now because it is a bit messy
+    // and would take too long to test.
 
 /* -------------------------------------------------------------------- */
 /*      Apply new definition and fields.                                */
@@ -5258,6 +6161,7 @@ OGRErr OGRFeature::RemapGeomFields( OGRFeatureDefn *poNewDefn,
 
     return OGRERR_NONE;
 }
+//! @endcond
 
 /************************************************************************/
 /*                         OGR_F_GetStyleTable()                        */
@@ -5268,7 +6172,8 @@ OGRStyleTableH OGR_F_GetStyleTable( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetStyleTable", NULL );
 
-    return (OGRStyleTableH) ((OGRFeature *) hFeat)->GetStyleTable( );
+    return reinterpret_cast<OGRStyleTableH>(
+        reinterpret_cast<OGRFeature *>(hFeat)->GetStyleTable());
 }
 
 /************************************************************************/
@@ -5281,7 +6186,8 @@ void OGR_F_SetStyleTableDirectly( OGRFeatureH hFeat,
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetStyleTableDirectly" );
 
-    ((OGRFeature *) hFeat)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
+    reinterpret_cast<OGRFeature *>(hFeat)->
+        SetStyleTableDirectly(reinterpret_cast<OGRStyleTable *>(hStyleTable));
 }
 
 /************************************************************************/
@@ -5295,7 +6201,8 @@ void OGR_F_SetStyleTable( OGRFeatureH hFeat,
     VALIDATE_POINTER0( hFeat, "OGR_F_SetStyleTable" );
     VALIDATE_POINTER0( hStyleTable, "OGR_F_SetStyleTable" );
 
-    ((OGRFeature *) hFeat)->SetStyleTable( (OGRStyleTable *) hStyleTable);
+    reinterpret_cast<OGRFeature *>(hFeat)->
+        SetStyleTable(reinterpret_cast<OGRStyleTable *>(hStyleTable));
 }
 
 /************************************************************************/
@@ -5313,11 +6220,11 @@ void OGR_F_SetStyleTable( OGRFeatureH hFeat,
  * @since GDAL 2.0
  */
 
-void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
-                                      CPL_UNUSED char** papszOptions)
+void OGRFeature::FillUnsetWithDefault( int bNotNullableOnly,
+                                       CPL_UNUSED char** papszOptions)
 {
-    int nFieldCount = poDefn->GetFieldCount();
-    for(int i = 0; i < nFieldCount; i ++ )
+    const int nFieldCount = poDefn->GetFieldCount();
+    for( int i = 0; i < nFieldCount; i++ )
     {
         if( IsFieldSet(i) )
             continue;
@@ -5344,8 +6251,12 @@ void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
                 }
                 else
                 {
-                    int nYear, nMonth, nDay, nHour, nMinute;
-                    float fSecond;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMinute = 0;
+                    float fSecond = 0.0f;
                     if( sscanf(pszDefault, "'%d/%d/%d %d:%d:%f'",
                                &nYear, &nMonth, &nDay,
                                &nHour, &nMinute, &fSecond) == 6 )
@@ -5378,7 +6289,8 @@ void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
 /**
  * \brief Fill unset fields with default values that might be defined.
  *
- * This function is the same as the C++ method OGRFeature::FillUnsetWithDefault().
+ * This function is the same as the C++ method
+ * OGRFeature::FillUnsetWithDefault().
  *
  * @param hFeat handle to the feature.
  * @param bNotNullableOnly if we should fill only unset fields with a not-null
@@ -5389,12 +6301,13 @@ void OGRFeature::FillUnsetWithDefault(int bNotNullableOnly,
 
 void OGR_F_FillUnsetWithDefault( OGRFeatureH hFeat,
                                  int bNotNullableOnly,
-                                 char** papszOptions)
+                                 char** papszOptions )
 
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_FillUnsetWithDefault" );
 
-    ((OGRFeature *) hFeat)->FillUnsetWithDefault( bNotNullableOnly, papszOptions );
+    reinterpret_cast<OGRFeature *>(hFeat)->
+        FillUnsetWithDefault( bNotNullableOnly, papszOptions );
 }
 
 /************************************************************************/
@@ -5406,17 +6319,17 @@ void OGR_F_FillUnsetWithDefault( OGRFeatureH hFeat,
  *
  * The scope of test is specified with the nValidateFlags parameter.
  *
- * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must
- * be interpreted as the number of UTF-8 characters. Some drivers might interpret
+ * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
+ * interpreted as the number of UTF-8 characters. Some drivers might interpret
  * the width as the number of bytes instead. So this test is rather conservative
  * (if it fails, then it will fail for all interpretations).
  *
  * This method is the same as the C function OGR_F_Validate().
  *
  * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
- *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT,
- *                       OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM
- *                       with '|' operator
+ *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
+ *                       OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT,
+ *                       OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM with '|' operator
  * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
  * @return TRUE if all enabled validation tests pass.
  * @since GDAL 2.0
@@ -5425,22 +6338,22 @@ void OGR_F_FillUnsetWithDefault( OGRFeatureH hFeat,
 int OGRFeature::Validate( int nValidateFlags, int bEmitError )
 
 {
-    int bRet = TRUE;
+    bool bRet = true;
 
-    int i;
-    int nGeomFieldCount = poDefn->GetGeomFieldCount();
-    for(i = 0; i < nGeomFieldCount; i ++ )
+    const int nGeomFieldCount = poDefn->GetGeomFieldCount();
+    for( int i = 0; i < nGeomFieldCount; i++ )
     {
         if( (nValidateFlags & OGR_F_VAL_NULL) &&
             !poDefn->GetGeomFieldDefn(i)->IsNullable() &&
             GetGeomFieldRef(i) == NULL )
         {
-            bRet = FALSE;
+            bRet = false;
             if( bEmitError )
             {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                            "Geometry field %s has a NULL content which is not allowed",
-                            poDefn->GetGeomFieldDefn(i)->GetNameRef());
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Geometry field %s has a NULL content which is not allowed",
+                    poDefn->GetGeomFieldDefn(i)->GetNameRef());
             }
         }
         if( (nValidateFlags & OGR_F_VAL_GEOM_TYPE) &&
@@ -5449,22 +6362,24 @@ int OGRFeature::Validate( int nValidateFlags, int bEmitError )
             OGRGeometry* poGeom = GetGeomFieldRef(i);
             if( poGeom != NULL )
             {
-                OGRwkbGeometryType eType = poDefn->GetGeomFieldDefn(i)->GetType();
-                OGRwkbGeometryType eFType = poGeom->getGeometryType();
+                const OGRwkbGeometryType eType =
+                    poDefn->GetGeomFieldDefn(i)->GetType();
+                const OGRwkbGeometryType eFType = poGeom->getGeometryType();
                 if( (nValidateFlags & OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM) &&
                     (wkbFlatten(eFType) == wkbFlatten(eType) ||
                      wkbFlatten(eType) == wkbUnknown) )
                 {
-                    /* ok */
+                    // Ok.
                 }
                 else if( (eType == wkbSetZ(wkbUnknown) && !wkbHasZ(eFType)) ||
                          (eType != wkbSetZ(wkbUnknown) && eFType != eType) )
                 {
-                    bRet = FALSE;
+                    bRet = false;
                     if( bEmitError )
                     {
                         CPLError(CE_Failure, CPLE_AppDefined,
-                                 "Geometry field %s has a %s geometry whereas %s is expected",
+                                 "Geometry field %s has a %s geometry whereas "
+                                 "%s is expected",
                                  poDefn->GetGeomFieldDefn(i)->GetNameRef(),
                                  OGRGeometryTypeToName(eFType),
                                  OGRGeometryTypeToName(eType));
@@ -5473,8 +6388,8 @@ int OGRFeature::Validate( int nValidateFlags, int bEmitError )
             }
         }
     }
-    int nFieldCount = poDefn->GetFieldCount();
-    for(i = 0; i < nFieldCount; i ++ )
+    const int nFieldCount = poDefn->GetFieldCount();
+    for( int i = 0; i < nFieldCount; i++ )
     {
         if( (nValidateFlags & OGR_F_VAL_NULL) &&
             !poDefn->GetFieldDefn(i)->IsNullable() &&
@@ -5482,7 +6397,7 @@ int OGRFeature::Validate( int nValidateFlags, int bEmitError )
             (!(nValidateFlags & OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT) ||
                poDefn->GetFieldDefn(i)->GetDefault() == NULL))
         {
-            bRet = FALSE;
+            bRet = false;
             if( bEmitError )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
@@ -5495,13 +6410,15 @@ int OGRFeature::Validate( int nValidateFlags, int bEmitError )
             poDefn->GetFieldDefn(i)->GetType() == OFTString &&
             IsFieldSet(i) &&
             CPLIsUTF8(GetFieldAsString(i), -1) &&
-            CPLStrlenUTF8(GetFieldAsString(i)) > poDefn->GetFieldDefn(i)->GetWidth())
+            CPLStrlenUTF8(GetFieldAsString(i)) >
+            poDefn->GetFieldDefn(i)->GetWidth())
         {
-            bRet = FALSE;
+            bRet = false;
             if( bEmitError )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
-                         "Field %s has a %d UTF-8 characters whereas a maximum of %d is allowed",
+                         "Field %s has a %d UTF-8 characters whereas "
+                         "a maximum of %d is allowed",
                          poDefn->GetFieldDefn(i)->GetNameRef(),
                          CPLStrlenUTF8(GetFieldAsString(i)),
                          poDefn->GetFieldDefn(i)->GetWidth());
@@ -5521,8 +6438,8 @@ int OGRFeature::Validate( int nValidateFlags, int bEmitError )
  *
  * The scope of test is specified with the nValidateFlags parameter.
  *
- * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must
- * be interpreted as the number of UTF-8 characters. Some drivers might interpret
+ * Regarding OGR_F_VAL_WIDTH, the test is done assuming the string width must be
+ * interpreted as the number of UTF-8 characters. Some drivers might interpret
  * the width as the number of bytes instead. So this test is rather conservative
  * (if it fails, then it will fail for all interpretations).
  *
@@ -5531,8 +6448,8 @@ int OGRFeature::Validate( int nValidateFlags, int bEmitError )
  *
  * @param hFeat handle to the feature to validate.
  * @param nValidateFlags OGR_F_VAL_ALL or combination of OGR_F_VAL_NULL,
- *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT
- *                       with '|' operator
+ *                       OGR_F_VAL_GEOM_TYPE, OGR_F_VAL_WIDTH and
+ *                       OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT with '|' operator
  * @param bEmitError TRUE if a CPLError() must be emitted when a check fails
  * @return TRUE if all enabled validation tests pass.
  * @since GDAL 2.0
@@ -5543,7 +6460,8 @@ int OGR_F_Validate( OGRFeatureH hFeat, int nValidateFlags, int bEmitError )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_Validate", FALSE );
 
-    return ((OGRFeature *) hFeat)->Validate( nValidateFlags, bEmitError );
+    return reinterpret_cast<OGRFeature *>(hFeat)->
+        Validate( nValidateFlags, bEmitError );
 }
 
 /************************************************************************/
@@ -5564,8 +6482,8 @@ int OGR_F_Validate( OGRFeatureH hFeat, int nValidateFlags, int bEmitError )
  * object, and if they do, generally the NATIVE_DATA open option must be passed
  * at dataset opening.
  *
- * The "native data" does not imply it is something more performant or powerful than
- * what can be obtained with the rest of the API, but it may be useful in
+ * The "native data" does not imply it is something more performant or powerful
+ * than what can be obtained with the rest of the API, but it may be useful in
  * round-tripping scenarios where some characteristics of the underlying format
  * are not captured otherwise by the OGR abstraction.
  *
@@ -5579,7 +6497,7 @@ int OGR_F_Validate( OGRFeatureH hFeat, int nValidateFlags, int bEmitError )
  */
 
 /************************************************************************/
-/*                      ,  OGR_F_GetNativeData()                        */
+/*                         OGR_F_GetNativeData()                        */
 /************************************************************************/
 
 /**
@@ -5594,8 +6512,8 @@ int OGR_F_Validate( OGRFeatureH hFeat, int nValidateFlags, int bEmitError )
  * object, and if they do, generally the NATIVE_DATA open option must be passed
  * at dataset opening.
  *
- * The "native data" does not imply it is something more performant or powerful than
- * what can be obtained with the rest of the API, but it may be useful in
+ * The "native data" does not imply it is something more performant or powerful
+ * than what can be obtained with the rest of the API, but it may be useful in
  * round-tripping scenarios where some characteristics of the underlying format
  * are not captured otherwise by the OGR abstraction.
  *
@@ -5614,7 +6532,7 @@ const char *OGR_F_GetNativeData( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetNativeData", NULL );
 
-    return ((const OGRFeature *) hFeat)->GetNativeData();
+    return reinterpret_cast<const OGRFeature *>(hFeat)->GetNativeData();
 }
 
 /************************************************************************/
@@ -5664,11 +6582,11 @@ const char *OGR_F_GetNativeMediaType( OGRFeatureH hFeat )
 {
     VALIDATE_POINTER1( hFeat, "OGR_F_GetNativeMediaType", NULL );
 
-    return ((const OGRFeature *) hFeat)->GetNativeMediaType();
+    return reinterpret_cast<const OGRFeature *>(hFeat)->GetNativeMediaType();
 }
 
 /************************************************************************/
-/*                      ,    SetNativeData()                            */
+/*                           SetNativeData()                            */
 /************************************************************************/
 
 /**
@@ -5691,11 +6609,11 @@ const char *OGR_F_GetNativeMediaType( OGRFeatureH hFeat )
 void OGRFeature::SetNativeData( const char* pszNativeData )
 {
     CPLFree( m_pszNativeData );
-    m_pszNativeData = ( pszNativeData ) ? VSI_STRDUP_VERBOSE( pszNativeData ) : NULL;
+    m_pszNativeData = pszNativeData ? VSI_STRDUP_VERBOSE(pszNativeData) : NULL;
 }
 
 /************************************************************************/
-/*                      ,   OGR_F_SetNativeData()                       */
+/*                          OGR_F_SetNativeData()                       */
 /************************************************************************/
 
 /**
@@ -5720,11 +6638,11 @@ void OGR_F_SetNativeData( OGRFeatureH hFeat, const char* pszNativeData )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetNativeData" );
 
-    ((OGRFeature *) hFeat)->SetNativeData(pszNativeData);
+    reinterpret_cast<OGRFeature *>(hFeat)->SetNativeData(pszNativeData);
 }
 
 /************************************************************************/
-/*                      ,  SetNativeMediaType()                         */
+/*                         SetNativeMediaType()                         */
 /************************************************************************/
 
 /**
@@ -5737,7 +6655,8 @@ void OGR_F_SetNativeData( OGRFeatureH hFeat, const char* pszNativeData )
  * This function is the same as the C function
  * OGR_F_SetNativeMediaType().
  *
- * @param pszNativeMediaType a string with the native media type, or NULL if there is none.
+ * @param pszNativeMediaType a string with the native media type, or NULL if
+ * there is none.
  * @since GDAL 2.1
  *
  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
@@ -5746,11 +6665,12 @@ void OGR_F_SetNativeData( OGRFeatureH hFeat, const char* pszNativeData )
 void OGRFeature::SetNativeMediaType( const char* pszNativeMediaType )
 {
     CPLFree( m_pszNativeMediaType );
-    m_pszNativeMediaType = ( pszNativeMediaType ) ? VSI_STRDUP_VERBOSE( pszNativeMediaType ) : NULL;
+    m_pszNativeMediaType =
+        pszNativeMediaType ? VSI_STRDUP_VERBOSE(pszNativeMediaType) : NULL;
 }
 
 /************************************************************************/
-/*                        , OGR_F_SetNativeMediaType()                  */
+/*                          OGR_F_SetNativeMediaType()                  */
 /************************************************************************/
 
 /**
@@ -5764,15 +6684,108 @@ void OGRFeature::SetNativeMediaType( const char* pszNativeMediaType )
  * OGRFeature::SetNativeMediaType().
  *
  * @param hFeat handle to the feature.
- * @param pszNativeMediaType a string with the native media type, or NULL if there is none.
+ * @param pszNativeMediaType a string with the native media type, or NULL if
+ * there is none.
  * @since GDAL 2.1
  *
  * @see https://trac.osgeo.org/gdal/wiki/rfc60_improved_roundtripping_in_ogr
  */
 
-void OGR_F_SetNativeMediaType( OGRFeatureH hFeat, const char* pszNativeMediaType )
+void OGR_F_SetNativeMediaType( OGRFeatureH hFeat,
+                               const char* pszNativeMediaType )
 {
     VALIDATE_POINTER0( hFeat, "OGR_F_SetNativeMediaType" );
 
-    ((OGRFeature *) hFeat)->SetNativeMediaType(pszNativeMediaType);
+    reinterpret_cast<OGRFeature *>(hFeat)->
+        SetNativeMediaType(pszNativeMediaType);
+}
+
+/************************************************************************/
+/*                           OGR_RawField_IsUnset()                     */
+/************************************************************************/
+
+/**
+ * \brief Returns whether a raw field is unset.
+ *
+ * Note: this function is rather low-level and should be rarely used in client
+ * code. Use instead OGR_F_IsFieldSet().
+ *
+ * @param puField pointer to raw field.
+ * @since GDAL 2.2
+ */
+
+int OGR_RawField_IsUnset( const OGRField* puField )
+{
+    return puField->Set.nMarker1 == OGRUnsetMarker &&
+           puField->Set.nMarker2 == OGRUnsetMarker &&
+           puField->Set.nMarker3 == OGRUnsetMarker;
+}
+
+/************************************************************************/
+/*                           OGR_RawField_IsNull()                      */
+/************************************************************************/
+
+/**
+ * \brief Returns whether a raw field is null.
+ *
+ * Note: this function is rather low-level and should be rarely used in client
+ * code. Use instead OGR_F_IsFieldNull().
+ *
+ * @param puField pointer to raw field.
+ * @since GDAL 2.2
+ */
+
+int OGR_RawField_IsNull( const OGRField* puField )
+{
+    return puField->Set.nMarker1 == OGRNullMarker &&
+           puField->Set.nMarker2 == OGRNullMarker &&
+           puField->Set.nMarker3 == OGRNullMarker;
+}
+
+/************************************************************************/
+/*                          OGR_RawField_SetUnset()                     */
+/************************************************************************/
+
+/**
+ * \brief Mark a raw field as unset.
+ *
+ * This should be called on a un-initialized field. In particular this will not
+ * free any memory dynamically allocated.
+ *
+ * Note: this function is rather low-level and should be rarely used in client
+ * code. Use instead OGR_F_UnsetField().
+ *
+ * @param puField pointer to raw field.
+ * @since GDAL 2.2
+ */
+
+void OGR_RawField_SetUnset( OGRField* puField )
+{
+    puField->Set.nMarker1 = OGRUnsetMarker;
+    puField->Set.nMarker2 = OGRUnsetMarker;
+    puField->Set.nMarker3 = OGRUnsetMarker;
+}
+
+/************************************************************************/
+/*                          OGR_RawField_SetNull()                      */
+/************************************************************************/
+
+/**
+ * \brief Mark a raw field as null.
+ *
+ * This should be called on a un-initialized field. In particular this will not
+ * free any memory dynamically allocated.
+ *
+ * Note: this function is rather low-level and should be rarely used in client
+ * code. Use instead OGR_F_SetFieldNull().
+ *
+ * @param puField pointer to raw field.
+ * @since GDAL 2.2
+ */
+
+void OGR_RawField_SetNull( OGRField* puField )
+{
+    puField->Set.nMarker1 = OGRNullMarker;
+    puField->Set.nMarker2 = OGRNullMarker;
+    puField->Set.nMarker3 = OGRNullMarker;
 }
diff --git a/ogr/ogrfeaturedefn.cpp b/ogr/ogrfeaturedefn.cpp
index cfc05d5..9f33b6a 100644
--- a/ogr/ogrfeaturedefn.cpp
+++ b/ogr/ogrfeaturedefn.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfeaturedefn.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFeatureDefn class implementation.
@@ -28,12 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_feature.h"
+
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrfeaturedefn.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrfeaturedefn.cpp 37440 2017-02-24 23:07:56Z goatbar $");
 
 /************************************************************************/
 /*                           OGRFeatureDefn()                           */
@@ -62,7 +69,8 @@ OGRFeatureDefn::OGRFeatureDefn( const char * pszName ) :
     bIgnoreStyle(FALSE)
 {
     pszFeatureClassName = CPLStrdup( pszName );
-    papoGeomFieldDefn = (OGRGeomFieldDefn**) CPLMalloc(sizeof(OGRGeomFieldDefn*));
+    papoGeomFieldDefn =
+        static_cast<OGRGeomFieldDefn**>(CPLMalloc(sizeof(OGRGeomFieldDefn*)));
     papoGeomFieldDefn[0] = new OGRGeomFieldDefn("", wkbUnknown);
 }
 
@@ -86,10 +94,9 @@ OGRFeatureDefn::OGRFeatureDefn( const char * pszName ) :
 OGRFeatureDefnH OGR_FD_Create( const char *pszName )
 
 {
-    return (OGRFeatureDefnH) new OGRFeatureDefn( pszName );
+    return reinterpret_cast<OGRFeatureDefnH>(new OGRFeatureDefn(pszName));
 }
 
-
 /************************************************************************/
 /*                          ~OGRFeatureDefn()                           */
 /************************************************************************/
@@ -100,7 +107,7 @@ OGRFeatureDefn::~OGRFeatureDefn()
     if( nRefCount != 0 )
     {
         CPLDebug( "OGRFeatureDefn",
-                  "OGRFeatureDefn %s with a ref count of %d deleted!\n",
+                  "OGRFeatureDefn %s with a ref count of %d deleted!",
                   pszFeatureClassName, nRefCount );
     }
 
@@ -125,7 +132,8 @@ OGRFeatureDefn::~OGRFeatureDefn()
 /*                           OGR_FD_Destroy()                           */
 /************************************************************************/
 /**
- * \brief Destroy a feature definition object and release all memory associated with it.
+ * \brief Destroy a feature definition object and release all memory associated
+ * with it.
  *
  * This function is the same as the C++ method
  * OGRFeatureDefn::~OGRFeatureDefn().
@@ -136,7 +144,7 @@ OGRFeatureDefn::~OGRFeatureDefn()
 void OGR_FD_Destroy( OGRFeatureDefnH hDefn )
 
 {
-    delete (OGRFeatureDefn *) hDefn;
+    delete reinterpret_cast<OGRFeatureDefn *>(hDefn);
 }
 
 /************************************************************************/
@@ -173,7 +181,7 @@ void OGRFeatureDefn::Release()
 void OGR_FD_Release( OGRFeatureDefnH hDefn )
 
 {
-    ((OGRFeatureDefn *) hDefn)->Release();
+    reinterpret_cast<OGRFeatureDefn *>(hDefn)->Release();
 }
 
 /************************************************************************/
@@ -193,19 +201,16 @@ void OGR_FD_Release( OGRFeatureDefnH hDefn )
 OGRFeatureDefn *OGRFeatureDefn::Clone()
 
 {
-    int i;
-    OGRFeatureDefn *poCopy;
-
-    poCopy = new OGRFeatureDefn( GetName() );
+    OGRFeatureDefn *poCopy = new OGRFeatureDefn( GetName() );
 
     GetFieldCount();
-    for( i = 0; i < nFieldCount; i++ )
+    for( int i = 0; i < nFieldCount; i++ )
         poCopy->AddFieldDefn( GetFieldDefn( i ) );
 
-    // There is a default geometry field created at OGRFeatureDefn instantiation
+    // Remove the default geometry field created instantiation.
     poCopy->DeleteGeomFieldDefn(0);
     GetGeomFieldCount();
-    for( i = 0; i < nGeomFieldCount; i++ )
+    for( int i = 0; i < nGeomFieldCount; i++ )
         poCopy->AddGeomFieldDefn( GetGeomFieldDefn( i ) );
 
     return poCopy;
@@ -246,7 +251,7 @@ const char * OGRFeatureDefn::GetName()
 const char *OGR_FD_GetName( OGRFeatureDefnH hDefn )
 
 {
-    return ((OGRFeatureDefn *) hDefn)->GetName();
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->GetName();
 }
 
 /************************************************************************/
@@ -288,7 +293,7 @@ int OGR_FD_GetFieldCount( OGRFeatureDefnH hDefn )
         OGRAPISpy_FD_GetFieldCount(hDefn);
 #endif
 
-    return ((OGRFeatureDefn *) hDefn)->GetFieldCount();
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->GetFieldCount();
 }
 
 /************************************************************************/
@@ -303,10 +308,10 @@ int OGR_FD_GetFieldCount( OGRFeatureDefnH hDefn )
  * Starting with GDAL 1.7.0, this method will also issue an error if the index
  * is not valid.
  *
- * @param iField the field to fetch, between 0 and GetFieldCount()-1.
+ * @param iField the field to fetch, between 0 and GetFieldCount() - 1.
  *
- * @return a pointer to an internal field definition object or NULL if invalid index.
- * This object should not be modified or freed by the application.
+ * @return a pointer to an internal field definition object or NULL if invalid
+ * index.  This object should not be modified or freed by the application.
  */
 
 OGRFieldDefn *OGRFeatureDefn::GetFieldDefn( int iField )
@@ -338,14 +343,17 @@ OGRFieldDefn *OGRFeatureDefn::GetFieldDefn( int iField )
  * from.
  * @param iField the field to fetch, between 0 and GetFieldCount()-1.
  *
- * @return an handle to an internal field definition object or NULL if invalid index.
- * This object should not be modified or freed by the application.
+ * @return an handle to an internal field definition object or NULL if invalid
+ * index.  This object should not be modified or freed by the application.
  */
 
 OGRFieldDefnH OGR_FD_GetFieldDefn( OGRFeatureDefnH hDefn, int iField )
 
 {
-    OGRFieldDefnH hFieldDefnH = (OGRFieldDefnH) ((OGRFeatureDefn *) hDefn)->GetFieldDefn( iField );
+    OGRFieldDefnH hFieldDefnH =
+        reinterpret_cast<OGRFieldDefnH>(
+            reinterpret_cast<OGRFeatureDefn *>(hDefn)->GetFieldDefn(iField));
+
 #ifdef OGRAPISPY_ENABLED
     if( bOGRAPISpyEnabled )
         OGRAPISpy_FD_GetFieldDefn(hDefn, iField, hFieldDefnH);
@@ -377,8 +385,8 @@ void OGRFeatureDefn::AddFieldDefn( OGRFieldDefn * poNewDefn )
 
 {
     GetFieldCount();
-    papoFieldDefn = (OGRFieldDefn **)
-        CPLRealloc( papoFieldDefn, sizeof(void*)*(nFieldCount+1) );
+    papoFieldDefn = static_cast<OGRFieldDefn **>(
+        CPLRealloc(papoFieldDefn, sizeof(void *) * (nFieldCount + 1)));
 
     papoFieldDefn[nFieldCount] = new OGRFieldDefn( poNewDefn );
     nFieldCount++;
@@ -394,7 +402,7 @@ void OGRFeatureDefn::AddFieldDefn( OGRFieldDefn * poNewDefn )
  * To add a new field definition to a layer definition, do not use this
  * function directly, but use OGR_L_CreateField() instead.
  *
- * This function  should only be called while there are no OGRFeature
+ * This function should only be called while there are no OGRFeature
  * objects in existence based on this OGRFeatureDefn.  The OGRFieldDefn
  * passed in is copied, and remains the responsibility of the caller.
  *
@@ -408,7 +416,8 @@ void OGRFeatureDefn::AddFieldDefn( OGRFieldDefn * poNewDefn )
 void OGR_FD_AddFieldDefn( OGRFeatureDefnH hDefn, OGRFieldDefnH hNewField )
 
 {
-    ((OGRFeatureDefn *) hDefn)->AddFieldDefn( (OGRFieldDefn *) hNewField );
+    reinterpret_cast<OGRFeatureDefn *>(hDefn)->
+        AddFieldDefn( reinterpret_cast<OGRFieldDefn *>(hNewField));
 }
 
 /************************************************************************/
@@ -434,17 +443,17 @@ void OGR_FD_AddFieldDefn( OGRFeatureDefnH hDefn, OGRFieldDefnH hNewField )
 OGRErr OGRFeatureDefn::DeleteFieldDefn( int iField )
 
 {
-    if (iField < 0 || iField >= GetFieldCount())
+    if( iField < 0 || iField >= GetFieldCount() )
         return OGRERR_FAILURE;
 
     delete papoFieldDefn[iField];
     papoFieldDefn[iField] = NULL;
 
-    if (iField < nFieldCount - 1)
+    if( iField < nFieldCount - 1 )
     {
         memmove(papoFieldDefn + iField,
                 papoFieldDefn + iField + 1,
-                (nFieldCount - 1 - iField) * sizeof(void*));
+                (nFieldCount - 1 - iField) * sizeof(void *));
     }
 
     nFieldCount--;
@@ -459,8 +468,8 @@ OGRErr OGRFeatureDefn::DeleteFieldDefn( int iField )
 /**
  * \brief Delete an existing field definition.
  *
- * To delete an existing field definition from a layer definition, do not use this
- * function directly, but use OGR_L_DeleteField() instead.
+ * To delete an existing field definition from a layer definition, do not use
+ * this function directly, but use OGR_L_DeleteField() instead.
  *
  * This method should only be called while there are no OGRFeature
  * objects in existence based on this OGRFeatureDefn.
@@ -476,7 +485,7 @@ OGRErr OGRFeatureDefn::DeleteFieldDefn( int iField )
 OGRErr OGR_FD_DeleteFieldDefn( OGRFeatureDefnH hDefn, int iField )
 
 {
-    return ((OGRFeatureDefn *) hDefn)->DeleteFieldDefn( iField );
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->DeleteFieldDefn(iField);
 }
 
 /************************************************************************/
@@ -505,17 +514,17 @@ OGRErr OGR_FD_DeleteFieldDefn( OGRFeatureDefnH hDefn, int iField )
 OGRErr OGRFeatureDefn::ReorderFieldDefns( int* panMap )
 
 {
-    if (GetFieldCount() == 0)
+    if( GetFieldCount() == 0 )
         return OGRERR_NONE;
 
-    OGRErr eErr = OGRCheckPermutation(panMap, nFieldCount);
-    if (eErr != OGRERR_NONE)
+    const OGRErr eErr = OGRCheckPermutation(panMap, nFieldCount);
+    if( eErr != OGRERR_NONE )
         return eErr;
 
-    OGRFieldDefn** papoFieldDefnNew = (OGRFieldDefn**)
-        CPLMalloc(sizeof(OGRFieldDefn*) * nFieldCount);
+    OGRFieldDefn** papoFieldDefnNew = static_cast<OGRFieldDefn**>(
+        CPLMalloc(sizeof(OGRFieldDefn*) * nFieldCount));
 
-    for(int i=0;i<nFieldCount;i++)
+    for( int i = 0; i < nFieldCount; i++ )
     {
         papoFieldDefnNew[i] = papoFieldDefn[panMap[i]];
     }
@@ -554,10 +563,9 @@ OGRErr OGRFeatureDefn::ReorderFieldDefns( int* panMap )
 OGRErr OGR_FD_ReorderFieldDefns( OGRFeatureDefnH hDefn, int* panMap )
 
 {
-    return ((OGRFeatureDefn *) hDefn)->ReorderFieldDefns( panMap );
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->ReorderFieldDefns(panMap);
 }
 
-
 /************************************************************************/
 /*                         GetGeomFieldCount()                          */
 /************************************************************************/
@@ -600,7 +608,7 @@ int OGR_FD_GetGeomFieldCount( OGRFeatureDefnH hDefn )
         OGRAPISpy_FD_GetGeomFieldCount(hDefn);
 #endif
 
-    return ((OGRFeatureDefn *) hDefn)->GetGeomFieldCount();
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->GetGeomFieldCount();
 }
 
 /************************************************************************/
@@ -612,10 +620,11 @@ int OGR_FD_GetGeomFieldCount( OGRFeatureDefnH hDefn )
  *
  * This method is the same as the C function OGR_FD_GetGeomFieldDefn().
  *
- * @param iGeomField the geometry field to fetch, between 0 and GetGeomFieldCount()-1.
+ * @param iGeomField the geometry field to fetch, between 0 and
+ * GetGeomFieldCount() - 1.
  *
- * @return a pointer to an internal field definition object or NULL if invalid index.
- * This object should not be modified or freed by the application.
+ * @return a pointer to an internal field definition object or NULL if invalid
+ * index.  This object should not be modified or freed by the application.
  *
  * @since GDAL 1.11
  */
@@ -644,19 +653,23 @@ OGRGeomFieldDefn *OGRFeatureDefn::GetGeomFieldDefn( int iGeomField )
  *
  * @param hDefn handle to the feature definition to get the field definition
  * from.
- * @param iGeomField the geometry field to fetch, between 0 and GetGeomFieldCount()-1.
+ * @param iGeomField the geometry field to fetch, between 0 and
+ * GetGeomFieldCount() - 1.
  *
- * @return an handle to an internal field definition object or NULL if invalid index.
- * This object should not be modified or freed by the application.
+ * @return an handle to an internal field definition object or NULL if invalid
+ * index.  This object should not be modified or freed by the application.
  *
  * @since GDAL 1.11
  */
 
-OGRGeomFieldDefnH OGR_FD_GetGeomFieldDefn( OGRFeatureDefnH hDefn, int iGeomField )
+OGRGeomFieldDefnH OGR_FD_GetGeomFieldDefn( OGRFeatureDefnH hDefn,
+                                           int iGeomField )
 
 {
     OGRGeomFieldDefnH hGeomField =
-        (OGRGeomFieldDefnH) ((OGRFeatureDefn *) hDefn)->GetGeomFieldDefn( iGeomField );
+        reinterpret_cast<OGRGeomFieldDefnH>(
+            reinterpret_cast<OGRFeatureDefn *>(hDefn)->
+                GetGeomFieldDefn(iGeomField));
 
 #ifdef OGRAPISPY_ENABLED
     if( bOGRAPISpyEnabled )
@@ -696,10 +709,10 @@ void OGRFeatureDefn::AddGeomFieldDefn( OGRGeomFieldDefn * poNewDefn,
                                        int bCopy )
 {
     GetGeomFieldCount();
-    papoGeomFieldDefn = (OGRGeomFieldDefn **)
-        CPLRealloc( papoGeomFieldDefn, sizeof(void*)*(nGeomFieldCount+1) );
+    papoGeomFieldDefn = static_cast<OGRGeomFieldDefn **>(
+        CPLRealloc( papoGeomFieldDefn, sizeof(void*) * (nGeomFieldCount + 1) ));
 
-    papoGeomFieldDefn[nGeomFieldCount] = (bCopy) ?
+    papoGeomFieldDefn[nGeomFieldCount] = bCopy ?
         new OGRGeomFieldDefn( poNewDefn ) : poNewDefn;
     nGeomFieldCount++;
 }
@@ -714,7 +727,7 @@ void OGRFeatureDefn::AddGeomFieldDefn( OGRGeomFieldDefn * poNewDefn,
  * To add a new field definition to a layer definition, do not use this
  * function directly, but use OGR_L_CreateGeomField() instead.
  *
- * This function  should only be called while there are no OGRFeature
+ * This function should only be called while there are no OGRFeature
  * objects in existence based on this OGRFeatureDefn.  The OGRGeomFieldDefn
  * passed in is copied, and remains the responsibility of the caller.
  *
@@ -732,7 +745,8 @@ void OGR_FD_AddGeomFieldDefn( OGRFeatureDefnH hDefn,
                               OGRGeomFieldDefnH hNewGeomField )
 
 {
-    ((OGRFeatureDefn *) hDefn)->AddGeomFieldDefn( (OGRGeomFieldDefn *) hNewGeomField );
+    reinterpret_cast<OGRFeatureDefn *>(hDefn)->AddGeomFieldDefn(
+        reinterpret_cast<OGRGeomFieldDefn *>(hNewGeomField));
 }
 
 /************************************************************************/
@@ -759,13 +773,13 @@ void OGR_FD_AddGeomFieldDefn( OGRFeatureDefnH hDefn,
 OGRErr OGRFeatureDefn::DeleteGeomFieldDefn( int iGeomField )
 
 {
-    if (iGeomField < 0 || iGeomField >= GetGeomFieldCount())
+    if( iGeomField < 0 || iGeomField >= GetGeomFieldCount() )
         return OGRERR_FAILURE;
 
     delete papoGeomFieldDefn[iGeomField];
     papoGeomFieldDefn[iGeomField] = NULL;
 
-    if (iGeomField < nGeomFieldCount - 1)
+    if( iGeomField < nGeomFieldCount - 1 )
     {
         memmove(papoGeomFieldDefn + iGeomField,
                 papoGeomFieldDefn + iGeomField + 1,
@@ -804,10 +818,10 @@ OGRErr OGRFeatureDefn::DeleteGeomFieldDefn( int iGeomField )
 OGRErr OGR_FD_DeleteGeomFieldDefn( OGRFeatureDefnH hDefn, int iGeomField )
 
 {
-    return ((OGRFeatureDefn *) hDefn)->DeleteGeomFieldDefn( iGeomField );
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->
+        DeleteGeomFieldDefn(iGeomField);
 }
 
-
 /************************************************************************/
 /*                         GetGeomFieldIndex()                          */
 /************************************************************************/
@@ -825,7 +839,6 @@ OGRErr OGR_FD_DeleteGeomFieldDefn( OGRFeatureDefnH hDefn, int iGeomField )
  * @return the geometry field index, or -1 if no match found.
  */
 
-
 int OGRFeatureDefn::GetGeomFieldIndex( const char * pszGeomFieldName )
 
 {
@@ -833,7 +846,8 @@ int OGRFeatureDefn::GetGeomFieldIndex( const char * pszGeomFieldName )
     for( int i = 0; i < nGeomFieldCount; i++ )
     {
         OGRGeomFieldDefn* poGFldDefn = GetGeomFieldDefn(i);
-        if( poGFldDefn != NULL && EQUAL(pszGeomFieldName, poGFldDefn->GetNameRef() ) )
+        if( poGFldDefn != NULL && EQUAL(pszGeomFieldName,
+                                        poGFldDefn->GetNameRef() ) )
             return i;
     }
 
@@ -849,7 +863,8 @@ int OGRFeatureDefn::GetGeomFieldIndex( const char * pszGeomFieldName )
  * The geometry field index of the first geometry field matching the passed
  * field name (case insensitively) is returned.
  *
- * This function is the same as the C++ method OGRFeatureDefn::GetGeomFieldIndex.
+ * This function is the same as the C++ method
+ * OGRFeatureDefn::GetGeomFieldIndex.
  *
  * @param hDefn handle to the feature definition to get field index from.
  * @param pszGeomFieldName the geometry field name to search for.
@@ -866,10 +881,10 @@ int OGR_FD_GetGeomFieldIndex( OGRFeatureDefnH hDefn,
         OGRAPISpy_FD_GetGeomFieldIndex(hDefn, pszGeomFieldName);
 #endif
 
-    return ((OGRFeatureDefn *)hDefn)->GetGeomFieldIndex( pszGeomFieldName );
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->
+        GetGeomFieldIndex(pszGeomFieldName);
 }
 
-
 /************************************************************************/
 /*                            GetGeomType()                             */
 /************************************************************************/
@@ -900,7 +915,8 @@ OGRwkbGeometryType OGRFeatureDefn::GetGeomType()
     if( poGFldDefn == NULL )
         return wkbNone;
     OGRwkbGeometryType eType = poGFldDefn->GetType();
-    if( eType == (wkbUnknown | wkb25DBitInternalUse) && CSLTestBoolean(CPLGetConfigOption("QGIS_HACK", "NO")) )
+    if( eType == (wkbUnknown | wkb25DBitInternalUse) &&
+        CPLTestBool(CPLGetConfigOption("QGIS_HACK", "NO")) )
         eType = wkbUnknown;
     return eType;
 }
@@ -922,7 +938,8 @@ OGRwkbGeometryType OGRFeatureDefn::GetGeomType()
 OGRwkbGeometryType OGR_FD_GetGeomType( OGRFeatureDefnH hDefn )
 
 {
-    OGRwkbGeometryType eType = ((OGRFeatureDefn *) hDefn)->GetGeomType();
+    OGRwkbGeometryType eType =
+        reinterpret_cast<OGRFeatureDefn *>(hDefn)->GetGeomType();
     if( OGR_GT_IsNonLinear(eType) && !OGRGetNonLinearGeometriesEnabledFlag() )
     {
         eType = OGR_GT_GetLinear(eType);
@@ -976,7 +993,8 @@ void OGRFeatureDefn::SetGeomType( OGRwkbGeometryType eNewType )
 /************************************************************************/
 
 /**
- * \brief Assign the base geometry type for the passed layer (the same as the feature definition).
+ * \brief Assign the base geometry type for the passed layer (the same as the
+ * feature definition).
  *
  * All geometry objects using this type must be of the defined type or
  * a derived type.  The default upon creation is wkbUnknown which allows for
@@ -995,7 +1013,7 @@ void OGRFeatureDefn::SetGeomType( OGRwkbGeometryType eNewType )
 void OGR_FD_SetGeomType( OGRFeatureDefnH hDefn, OGRwkbGeometryType eType )
 
 {
-    ((OGRFeatureDefn *) hDefn)->SetGeomType( eType );
+    reinterpret_cast<OGRFeatureDefn *>(hDefn)->SetGeomType(eType);
 }
 
 /************************************************************************/
@@ -1034,7 +1052,7 @@ void OGR_FD_SetGeomType( OGRFeatureDefnH hDefn, OGRwkbGeometryType eType )
 int OGR_FD_Reference( OGRFeatureDefnH hDefn )
 
 {
-    return ((OGRFeatureDefn *) hDefn)->Reference();
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->Reference();
 }
 
 /************************************************************************/
@@ -1068,7 +1086,7 @@ int OGR_FD_Reference( OGRFeatureDefnH hDefn )
 int OGR_FD_Dereference( OGRFeatureDefnH hDefn )
 
 {
-    return ((OGRFeatureDefn *) hDefn)->Dereference();
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->Dereference();
 }
 
 /************************************************************************/
@@ -1103,7 +1121,7 @@ int OGR_FD_Dereference( OGRFeatureDefnH hDefn )
 int OGR_FD_GetReferenceCount( OGRFeatureDefnH hDefn )
 
 {
-    return ((OGRFeatureDefn *) hDefn)->GetReferenceCount();
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->GetReferenceCount();
 }
 
 /************************************************************************/
@@ -1123,7 +1141,6 @@ int OGR_FD_GetReferenceCount( OGRFeatureDefnH hDefn )
  * @return the field index, or -1 if no match found.
  */
 
-
 int OGRFeatureDefn::GetFieldIndex( const char * pszFieldName )
 
 {
@@ -1163,7 +1180,8 @@ int OGR_FD_GetFieldIndex( OGRFeatureDefnH hDefn, const char *pszFieldName )
         OGRAPISpy_FD_GetFieldIndex(hDefn, pszFieldName);
 #endif
 
-    return ((OGRFeatureDefn *)hDefn)->GetFieldIndex( pszFieldName );
+    return
+        reinterpret_cast<OGRFeatureDefn *>(hDefn)->GetFieldIndex(pszFieldName);
 }
 
 /************************************************************************/
@@ -1177,7 +1195,8 @@ int OGR_FD_GetFieldIndex( OGRFeatureDefnH hDefn, const char *pszFieldName )
  *
  * This method is the same as the C function OGR_FD_IsGeometryIgnored().
  *
- * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->IsIgnored().
+ * Starting with GDAL 1.11, this method returns
+ * GetGeomFieldDefn(0)->IsIgnored().
  *
  * @return ignore state
  */
@@ -1202,7 +1221,8 @@ int OGRFeatureDefn::IsGeometryIgnored()
  * This function is the same as the C++ method
  * OGRFeatureDefn::IsGeometryIgnored().
  *
- * Starting with GDAL 1.11, this method returns GetGeomFieldDefn(0)->IsIgnored().
+ * Starting with GDAL 1.11, this method returns
+ * GetGeomFieldDefn(0)->IsIgnored().
  *
  * @param hDefn handle to the feature definition on witch OGRFeature are
  * based on.
@@ -1211,7 +1231,7 @@ int OGRFeatureDefn::IsGeometryIgnored()
 
 int OGR_FD_IsGeometryIgnored( OGRFeatureDefnH hDefn )
 {
-    return ((OGRFeatureDefn *) hDefn)->IsGeometryIgnored();
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->IsGeometryIgnored();
 }
 
 /************************************************************************/
@@ -1259,7 +1279,7 @@ void OGRFeatureDefn::SetGeometryIgnored( int bIgnore )
 
 void OGR_FD_SetGeometryIgnored( OGRFeatureDefnH hDefn, int bIgnore )
 {
-    ((OGRFeatureDefn *) hDefn)->SetGeometryIgnored( bIgnore );
+    reinterpret_cast<OGRFeatureDefn *>(hDefn)->SetGeometryIgnored( bIgnore );
 }
 
 /************************************************************************/
@@ -1267,7 +1287,7 @@ void OGR_FD_SetGeometryIgnored( OGRFeatureDefnH hDefn, int bIgnore )
 /************************************************************************/
 
 /**
- * \fn int OGRFeatureDefn::IsStyleIgnored();
+ * \fn int OGRFeatureDefn::IsStyleIgnored() const;
  *
  * \brief Determine whether the style can be omitted when fetching features
  *
@@ -1293,7 +1313,7 @@ void OGR_FD_SetGeometryIgnored( OGRFeatureDefnH hDefn, int bIgnore )
 
 int OGR_FD_IsStyleIgnored( OGRFeatureDefnH hDefn )
 {
-    return ((OGRFeatureDefn *) hDefn)->IsStyleIgnored();
+    return reinterpret_cast<OGRFeatureDefn *>(hDefn)->IsStyleIgnored();
 }
 
 /************************************************************************/
@@ -1327,13 +1347,17 @@ int OGR_FD_IsStyleIgnored( OGRFeatureDefnH hDefn )
 
 void OGR_FD_SetStyleIgnored( OGRFeatureDefnH hDefn, int bIgnore )
 {
-    ((OGRFeatureDefn *) hDefn)->SetStyleIgnored( bIgnore );
+    reinterpret_cast<OGRFeatureDefn *>(hDefn)->SetStyleIgnored(bIgnore);
 }
 
 /************************************************************************/
 /*                         CreateFeatureDefn()                          */
 /************************************************************************/
 
+/** Create a new feature definition object.
+ * @param pszName name
+ * @return new feature definition object.
+ */
 OGRFeatureDefn *OGRFeatureDefn::CreateFeatureDefn( const char *pszName )
 
 {
@@ -1344,6 +1368,9 @@ OGRFeatureDefn *OGRFeatureDefn::CreateFeatureDefn( const char *pszName )
 /*                         DestroyFeatureDefn()                         */
 /************************************************************************/
 
+/** Destroy a feature definition.
+ * @param poDefn feature definition.
+ */
 void OGRFeatureDefn::DestroyFeatureDefn( OGRFeatureDefn *poDefn )
 
 {
@@ -1363,26 +1390,26 @@ void OGRFeatureDefn::DestroyFeatureDefn( OGRFeatureDefn *poDefn )
 
 int OGRFeatureDefn::IsSame( OGRFeatureDefn * poOtherFeatureDefn )
 {
-    if (strcmp(GetName(), poOtherFeatureDefn->GetName()) == 0 &&
+    if( strcmp(GetName(), poOtherFeatureDefn->GetName()) == 0 &&
         GetFieldCount() == poOtherFeatureDefn->GetFieldCount() &&
-        GetGeomFieldCount() == poOtherFeatureDefn->GetGeomFieldCount())
+        GetGeomFieldCount() == poOtherFeatureDefn->GetGeomFieldCount() )
     {
-        int i;
-        for(i=0;i<nFieldCount;i++)
+        for( int i = 0; i < nFieldCount; i++ )
         {
             const OGRFieldDefn* poFldDefn = GetFieldDefn(i);
-            const OGRFieldDefn* poOtherFldDefn = poOtherFeatureDefn->GetFieldDefn(i);
-            if (!poFldDefn->IsSame(poOtherFldDefn))
+            const OGRFieldDefn* poOtherFldDefn =
+                poOtherFeatureDefn->GetFieldDefn(i);
+            if( !poFldDefn->IsSame(poOtherFldDefn) )
             {
                 return FALSE;
             }
         }
-        for(i=0;i<nGeomFieldCount;i++)
+        for( int i = 0; i < nGeomFieldCount; i++ )
         {
             OGRGeomFieldDefn* poGFldDefn = GetGeomFieldDefn(i);
             OGRGeomFieldDefn* poOtherGFldDefn =
                 poOtherFeatureDefn->GetGeomFieldDefn(i);
-            if (!poGFldDefn->IsSame(poOtherGFldDefn))
+            if( !poGFldDefn->IsSame(poOtherGFldDefn) )
             {
                 return FALSE;
             }
@@ -1411,5 +1438,7 @@ int OGR_FD_IsSame( OGRFeatureDefnH hFDefn, OGRFeatureDefnH hOtherFDefn )
 {
     VALIDATE_POINTER1( hFDefn, "OGR_FD_IsSame", FALSE );
     VALIDATE_POINTER1( hOtherFDefn, "OGR_FD_IsSame", FALSE );
-    return ((OGRFeatureDefn*)hFDefn)->IsSame((OGRFeatureDefn*)hOtherFDefn);
+
+    return reinterpret_cast<OGRFeatureDefn *>(hFDefn)->
+        IsSame(reinterpret_cast<OGRFeatureDefn *>(hOtherFDefn));
 }
diff --git a/ogr/ogrfeaturequery.cpp b/ogr/ogrfeaturequery.cpp
index 7f0997a..24c7209 100644
--- a/ogr/ogrfeaturequery.cpp
+++ b/ogr/ogrfeaturequery.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfeaturequery.cpp 34092 2016-04-25 09:09:46Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of simple SQL WHERE style attributes queries
@@ -29,33 +28,43 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <assert.h>
-#include "swq.h"
+#include "cpl_port.h"
 #include "ogr_feature.h"
-#include "ogr_p.h"
+#include "swq.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
 #include "ogr_attrind.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
+#include "ogrsf_frmts.h"
+
+//! @cond Doxygen_Suppress
 
-CPL_CVSID("$Id: ogrfeaturequery.cpp 34092 2016-04-25 09:09:46Z rouault $");
+CPL_CVSID("$Id: ogrfeaturequery.cpp 37501 2017-02-28 06:50:54Z goatbar $");
 
 /************************************************************************/
 /*     Support for special attributes (feature query and selection)     */
 /************************************************************************/
 
-const char* const SpecialFieldNames[SPECIAL_FIELD_COUNT]
-= {"FID", "OGR_GEOMETRY", "OGR_STYLE", "OGR_GEOM_WKT", "OGR_GEOM_AREA"};
-const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT]
-= {SWQ_INTEGER, SWQ_STRING, SWQ_STRING, SWQ_STRING, SWQ_FLOAT};
+const char *const SpecialFieldNames[SPECIAL_FIELD_COUNT] = {
+    "FID", "OGR_GEOMETRY", "OGR_STYLE", "OGR_GEOM_WKT", "OGR_GEOM_AREA"};
+const swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT] = {
+    SWQ_INTEGER, SWQ_STRING, SWQ_STRING, SWQ_STRING, SWQ_FLOAT};
 
 /************************************************************************/
 /*                          OGRFeatureQuery()                           */
 /************************************************************************/
 
-OGRFeatureQuery::OGRFeatureQuery()
-
-{
-    poTargetDefn = NULL;
-    pSWQExpr = NULL;
-}
+OGRFeatureQuery::OGRFeatureQuery() :
+    poTargetDefn(NULL),
+    pSWQExpr(NULL)
+{}
 
 /************************************************************************/
 /*                          ~OGRFeatureQuery()                          */
@@ -64,47 +73,42 @@ OGRFeatureQuery::OGRFeatureQuery()
 OGRFeatureQuery::~OGRFeatureQuery()
 
 {
-    delete (swq_expr_node *) pSWQExpr;
+    delete static_cast<swq_expr_node *>(pSWQExpr);
 }
 
 /************************************************************************/
 /*                                Parse                                 */
 /************************************************************************/
 
-OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
-                                 const char * pszExpression,
-                                 int bCheck,
-                                 swq_custom_func_registrar* poCustomFuncRegistrar )
+OGRErr
+OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
+                          const char * pszExpression,
+                          int bCheck,
+                          swq_custom_func_registrar *poCustomFuncRegistrar )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Clear any existing expression.                                  */
-/* -------------------------------------------------------------------- */
+    // Clear any existing expression.
     if( pSWQExpr != NULL )
     {
-        delete (swq_expr_node *) pSWQExpr;
+        delete static_cast<swq_expr_node *>(pSWQExpr);
         pSWQExpr = NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Build list of fields.                                           */
-/* -------------------------------------------------------------------- */
-    char        **papszFieldNames;
-    swq_field_type *paeFieldTypes;
-    int         iField;
-    int         nFieldCount = poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT +
-                              poDefn->GetGeomFieldCount();
-
-    papszFieldNames = (char **)
-        CPLMalloc(sizeof(char *) * nFieldCount );
-    paeFieldTypes = (swq_field_type *)
-        CPLMalloc(sizeof(swq_field_type) * nFieldCount );
-
-    for( iField = 0; iField < poDefn->GetFieldCount(); iField++ )
+    // Build list of fields.
+    const int nFieldCount =
+        poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT +
+        poDefn->GetGeomFieldCount();
+
+    char **papszFieldNames = static_cast<char **>(
+        CPLMalloc(sizeof(char *) * nFieldCount ));
+    swq_field_type *paeFieldTypes = static_cast<swq_field_type *>(
+        CPLMalloc(sizeof(swq_field_type) * nFieldCount));
+
+    for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
     {
-        OGRFieldDefn    *poField = poDefn->GetFieldDefn( iField );
+        OGRFieldDefn *poField = poDefn->GetFieldDefn(iField);
 
-        papszFieldNames[iField] = (char *) poField->GetNameRef();
+        papszFieldNames[iField] = const_cast<char *>(poField->GetNameRef());
 
         switch( poField->GetType() )
         {
@@ -146,46 +150,47 @@ OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
         }
     }
 
-    iField = 0;
-    while (iField < SPECIAL_FIELD_COUNT)
+    int iField = 0;
+    while( iField < SPECIAL_FIELD_COUNT )
     {
-        papszFieldNames[poDefn->GetFieldCount() + iField] = (char *) SpecialFieldNames[iField];
-        paeFieldTypes[poDefn->GetFieldCount() + iField] = (iField == SPF_FID) ? SWQ_INTEGER64 : SpecialFieldTypes[iField];
+        papszFieldNames[poDefn->GetFieldCount() + iField] =
+            const_cast<char *>(SpecialFieldNames[iField]);
+        paeFieldTypes[poDefn->GetFieldCount() + iField] =
+            (iField == SPF_FID) ? SWQ_INTEGER64 : SpecialFieldTypes[iField];
         ++iField;
     }
 
     for( iField = 0; iField < poDefn->GetGeomFieldCount(); iField++ )
     {
-        OGRGeomFieldDefn    *poField = poDefn->GetGeomFieldDefn( iField );
-        int iDstField = poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT + iField;
+        OGRGeomFieldDefn *poField = poDefn->GetGeomFieldDefn(iField);
+        const int iDstField =
+            poDefn->GetFieldCount() + SPECIAL_FIELD_COUNT + iField;
 
-        papszFieldNames[iDstField] = (char *) poField->GetNameRef();
+        papszFieldNames[iDstField] = const_cast<char *>(poField->GetNameRef());
         if( *papszFieldNames[iDstField] == '\0' )
-            papszFieldNames[iDstField] = (char*) OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME;
+            papszFieldNames[iDstField] =
+                const_cast<char *>(OGR_GEOMETRY_DEFAULT_NON_EMPTY_NAME);
         paeFieldTypes[iDstField] = SWQ_GEOMETRY;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Try to parse.                                                   */
-/* -------------------------------------------------------------------- */
-    OGRErr      eErr = OGRERR_NONE;
-    CPLErr      eCPLErr;
-
+    // Try to parse.
     poTargetDefn = poDefn;
-    eCPLErr = swq_expr_compile( pszExpression, nFieldCount,
-                                papszFieldNames, paeFieldTypes,
-                                bCheck,
-                                poCustomFuncRegistrar,
-                                (swq_expr_node **) &pSWQExpr );
+    const CPLErr eCPLErr =
+        swq_expr_compile(pszExpression, nFieldCount,
+                         papszFieldNames, paeFieldTypes,
+                         bCheck,
+                         poCustomFuncRegistrar,
+                         reinterpret_cast<swq_expr_node **>(&pSWQExpr));
+
+    OGRErr eErr = OGRERR_NONE;
     if( eCPLErr != CE_None )
     {
         eErr = OGRERR_CORRUPT_DATA;
         pSWQExpr = NULL;
     }
 
-    CPLFree( papszFieldNames );
-    CPLFree( paeFieldTypes );
-
+    CPLFree(papszFieldNames);
+    CPLFree(paeFieldTypes);
 
     return eErr;
 }
@@ -197,16 +202,19 @@ OGRErr OGRFeatureQuery::Compile( OGRFeatureDefn *poDefn,
 static swq_expr_node *OGRFeatureFetcher( swq_expr_node *op, void *pFeatureIn )
 
 {
-    OGRFeature *poFeature = (OGRFeature *) pFeatureIn;
-    swq_expr_node *poRetNode = NULL;
+    OGRFeature *poFeature = static_cast<OGRFeature *>(pFeatureIn);
 
     if( op->field_type == SWQ_GEOMETRY )
     {
-        int iField = op->field_index - (poFeature->GetFieldCount() + SPECIAL_FIELD_COUNT);
-        poRetNode = new swq_expr_node( poFeature->GetGeomFieldRef(iField) );
+        const int iField =
+            op->field_index -
+            (poFeature->GetFieldCount() + SPECIAL_FIELD_COUNT);
+        swq_expr_node *poRetNode =
+            new swq_expr_node(poFeature->GetGeomFieldRef(iField));
         return poRetNode;
     }
 
+    swq_expr_node *poRetNode = NULL;
     switch( op->field_type )
     {
       case SWQ_INTEGER:
@@ -225,13 +233,19 @@ static swq_expr_node *OGRFeatureFetcher( swq_expr_node *op, void *pFeatureIn )
             poFeature->GetFieldAsDouble(op->field_index) );
         break;
 
+      case SWQ_TIMESTAMP:
+        poRetNode = new swq_expr_node(
+            poFeature->GetFieldAsString(op->field_index) );
+        poRetNode->MarkAsTimestamp();
+        break;
+
       default:
         poRetNode = new swq_expr_node(
             poFeature->GetFieldAsString(op->field_index) );
         break;
     }
 
-    poRetNode->is_null = !(poFeature->IsFieldSet(op->field_index));
+    poRetNode->is_null = !(poFeature->IsFieldSetAndNotNull(op->field_index));
 
     return poRetNode;
 }
@@ -246,19 +260,18 @@ int OGRFeatureQuery::Evaluate( OGRFeature *poFeature )
     if( pSWQExpr == NULL )
         return FALSE;
 
-    swq_expr_node *poResult;
-
-    poResult = ((swq_expr_node *) pSWQExpr)->Evaluate( OGRFeatureFetcher,
-                                                       (void *) poFeature );
+    swq_expr_node *poResult =
+        static_cast<swq_expr_node *>(pSWQExpr)->
+            Evaluate(OGRFeatureFetcher, poFeature);
 
     if( poResult == NULL )
         return FALSE;
 
-    int bLogicalResult = FALSE;
+    bool bLogicalResult = false;
     if( poResult->field_type == SWQ_INTEGER ||
         poResult->field_type == SWQ_INTEGER64 ||
         poResult->field_type == SWQ_BOOLEAN )
-        bLogicalResult = (int)poResult->int_value;
+        bLogicalResult = CPL_TO_BOOL(static_cast<int>(poResult->int_value));
 
     delete poResult;
 
@@ -271,34 +284,27 @@ int OGRFeatureQuery::Evaluate( OGRFeature *poFeature )
 
 int OGRFeatureQuery::CanUseIndex( OGRLayer *poLayer )
 {
-    swq_expr_node *psExpr = (swq_expr_node *) pSWQExpr;
+    swq_expr_node *psExpr = static_cast<swq_expr_node *>(pSWQExpr);
 
-/* -------------------------------------------------------------------- */
-/*      Do we have an index on the targeted layer?                      */
-/* -------------------------------------------------------------------- */
-    if ( poLayer->GetIndex() == NULL )
+    // Do we have an index on the targeted layer?
+    if( poLayer->GetIndex() == NULL )
         return FALSE;
 
-    return CanUseIndex( psExpr, poLayer );
+    return CanUseIndex(psExpr, poLayer);
 }
 
 int OGRFeatureQuery::CanUseIndex( swq_expr_node *psExpr,
                                   OGRLayer *poLayer )
 {
-    OGRAttrIndex *poIndex;
-
-/* -------------------------------------------------------------------- */
-/*      Does the expression meet our requirements?                      */
-/* -------------------------------------------------------------------- */
-    if( psExpr == NULL ||
-        psExpr->eNodeType != SNT_OPERATION )
+    // Does the expression meet our requirements?
+    if( psExpr == NULL || psExpr->eNodeType != SNT_OPERATION )
         return FALSE;
 
-    if ((psExpr->nOperation == SWQ_OR || psExpr->nOperation == SWQ_AND) &&
-         psExpr->nSubExprCount == 2)
+    if( (psExpr->nOperation == SWQ_OR || psExpr->nOperation == SWQ_AND) &&
+         psExpr->nSubExprCount == 2 )
     {
-        return CanUseIndex( psExpr->papoSubExpr[0], poLayer ) &&
-               CanUseIndex( psExpr->papoSubExpr[1], poLayer );
+        return CanUseIndex(psExpr->papoSubExpr[0], poLayer) &&
+               CanUseIndex(psExpr->papoSubExpr[1], poLayer);
     }
 
     if( !(psExpr->nOperation == SWQ_EQ || psExpr->nOperation == SWQ_IN)
@@ -312,13 +318,12 @@ int OGRFeatureQuery::CanUseIndex( swq_expr_node *psExpr,
         || poValue->eNodeType != SNT_CONSTANT )
         return FALSE;
 
-    poIndex = poLayer->GetIndex()->GetFieldIndex( poColumn->field_index );
+    OGRAttrIndex *poIndex =
+        poLayer->GetIndex()->GetFieldIndex(poColumn->field_index);
     if( poIndex == NULL )
         return FALSE;
 
-/* -------------------------------------------------------------------- */
-/*      OK, we have an index                                            */
-/* -------------------------------------------------------------------- */
+    // Have an index.
     return TRUE;
 }
 
@@ -336,10 +341,10 @@ int OGRFeatureQuery::CanUseIndex( swq_expr_node *psExpr,
 /*      multi-part queries with ranges.                                 */
 /************************************************************************/
 
-static int CompareGIntBig(const void *pa, const void *pb)
+static int CompareGIntBig( const void *pa, const void *pb )
 {
-    GIntBig a = *((const GIntBig*)pa);
-    GIntBig b = *((const GIntBig*)pb);
+    const GIntBig a = *(reinterpret_cast<const GIntBig *>(pa));
+    const GIntBig b = *(reinterpret_cast<const GIntBig *>(pb));
     if( a < b )
         return -1;
     else if( a > b )
@@ -349,89 +354,87 @@ static int CompareGIntBig(const void *pa, const void *pb)
 }
 
 GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( OGRLayer *poLayer,
-                                               OGRErr *peErr )
+                                                  OGRErr *peErr )
 
 {
-    swq_expr_node *psExpr = (swq_expr_node *) pSWQExpr;
+    swq_expr_node *psExpr = static_cast<swq_expr_node *>(pSWQExpr);
 
     if( peErr != NULL )
         *peErr = OGRERR_NONE;
 
-/* -------------------------------------------------------------------- */
-/*      Do we have an index on the targeted layer?                      */
-/* -------------------------------------------------------------------- */
-    if ( poLayer->GetIndex() == NULL )
+    // Do we have an index on the targeted layer?
+    if( poLayer->GetIndex() == NULL )
         return NULL;
 
     GIntBig nFIDCount = 0;
     return EvaluateAgainstIndices(psExpr, poLayer, nFIDCount);
 }
 
-/* The input arrays must be sorted ! */
+// The input arrays must be sorted.
 static
-GIntBig* OGRORGIntBigArray(GIntBig panFIDList1[], GIntBig nFIDCount1,
-                           GIntBig panFIDList2[], GIntBig nFIDCount2,
-                           GIntBig& nFIDCount)
+GIntBig* OGRORGIntBigArray( GIntBig panFIDList1[], GIntBig nFIDCount1,
+                            GIntBig panFIDList2[], GIntBig nFIDCount2,
+                            GIntBig& nFIDCount )
 {
-    GIntBig nMaxCount = nFIDCount1 + nFIDCount2;
-    GIntBig* panFIDList = (GIntBig*) CPLMalloc((size_t)(nMaxCount+1) * sizeof(GIntBig));
+    const GIntBig nMaxCount = nFIDCount1 + nFIDCount2;
+    GIntBig* panFIDList = static_cast<GIntBig *>(
+        CPLMalloc(static_cast<size_t>(nMaxCount + 1) * sizeof(GIntBig)));
     nFIDCount = 0;
 
-    GIntBig i1 = 0, i2 =0;
-    for(;i1<nFIDCount1 || i2<nFIDCount2;)
+    for( GIntBig i1 = 0, i2 = 0; i1<nFIDCount1 || i2<nFIDCount2; )
     {
-        if (i1 < nFIDCount1 && i2 < nFIDCount2)
+        if( i1 < nFIDCount1 && i2 < nFIDCount2 )
         {
-            GIntBig nVal1 = panFIDList1[i1];
-            GIntBig nVal2 = panFIDList2[i2];
-            if (nVal1 < nVal2)
+            const GIntBig nVal1 = panFIDList1[i1];
+            const GIntBig nVal2 = panFIDList2[i2];
+            if( nVal1 < nVal2 )
             {
-                if (i1+1 < nFIDCount1 && panFIDList1[i1+1] <= nVal2)
+                if( i1 + 1 < nFIDCount1 && panFIDList1[i1+1] <= nVal2 )
                 {
-                    panFIDList[nFIDCount ++] = nVal1;
-                    i1 ++;
+                    panFIDList[nFIDCount++] = nVal1;
+                    i1++;
                 }
                 else
                 {
-                    panFIDList[nFIDCount ++] = nVal1;
-                    panFIDList[nFIDCount ++] = nVal2;
-                    i1 ++;
-                    i2 ++;
+                    panFIDList[nFIDCount++] = nVal1;
+                    panFIDList[nFIDCount++] = nVal2;
+                    i1++;
+                    i2++;
                 }
             }
-            else if (nVal1 == nVal2)
+            else if( nVal1 == nVal2 )
             {
-                panFIDList[nFIDCount ++] = nVal1;
-                i1 ++;
-                i2 ++;
+                panFIDList[nFIDCount++] = nVal1;
+                i1++;
+                i2++;
             }
             else
             {
-                if (i2+1 < nFIDCount2 && panFIDList2[i2+1] <= nVal1)
+                if( i2 + 1 < nFIDCount2 && panFIDList2[i2+1] <= nVal1 )
                 {
-                    panFIDList[nFIDCount ++] = nVal2;
-                    i2 ++;
+                    panFIDList[nFIDCount++] = nVal2;
+                    i2++;
                 }
                 else
                 {
-                    panFIDList[nFIDCount ++] = nVal2;
-                    panFIDList[nFIDCount ++] = nVal1;
-                    i1 ++;
-                    i2 ++;
+                    panFIDList[nFIDCount++] = nVal2;
+                    panFIDList[nFIDCount++] = nVal1;
+                    i1++;
+                    i2++;
                 }
             }
         }
-        else if (i1 < nFIDCount1)
+        else if( i1 < nFIDCount1 )
         {
-            GIntBig nVal1 = panFIDList1[i1];
-            panFIDList[nFIDCount ++] = nVal1;
-            i1 ++;
+            const GIntBig nVal1 = panFIDList1[i1];
+            panFIDList[nFIDCount++] = nVal1;
+            i1++;
         }
-        else if (i2 < nFIDCount2)
+        else if( i2 < nFIDCount2 )
         {
-            GIntBig nVal2 = panFIDList2[i2];
-            panFIDList[nFIDCount ++] = nVal2;
-            i2 ++;
+            const GIntBig nVal2 = panFIDList2[i2];
+            panFIDList[nFIDCount++] = nVal2;
+            i2++;
         }
     }
 
@@ -440,49 +443,49 @@ GIntBig* OGRORGIntBigArray(GIntBig panFIDList1[], GIntBig nFIDCount1,
     return panFIDList;
 }
 
-/* The input arrays must be sorted ! */
+// The input arrays must be sorted.
 static
-GIntBig* OGRANDGIntBigArray(GIntBig panFIDList1[], GIntBig nFIDCount1,
-                            GIntBig panFIDList2[], GIntBig nFIDCount2,
-                            GIntBig& nFIDCount)
+GIntBig* OGRANDGIntBigArray( GIntBig panFIDList1[], GIntBig nFIDCount1,
+                             GIntBig panFIDList2[], GIntBig nFIDCount2,
+                             GIntBig& nFIDCount )
 {
-    GIntBig nMaxCount = MAX(nFIDCount1, nFIDCount2);
-    GIntBig* panFIDList = (GIntBig*) CPLMalloc((size_t)(nMaxCount+1) * sizeof(GIntBig));
+    GIntBig nMaxCount = std::max(nFIDCount1, nFIDCount2);
+    GIntBig* panFIDList = static_cast<GIntBig *>(
+        CPLMalloc(static_cast<size_t>(nMaxCount + 1) * sizeof(GIntBig)));
     nFIDCount = 0;
 
-    GIntBig i1 = 0, i2 =0;
-    for(;i1<nFIDCount1 && i2<nFIDCount2;)
+    for( GIntBig i1 = 0, i2 = 0; i1 < nFIDCount1 && i2 < nFIDCount2; )
     {
-        GIntBig nVal1 = panFIDList1[i1];
-        GIntBig nVal2 = panFIDList2[i2];
-        if (nVal1 < nVal2)
+        const GIntBig nVal1 = panFIDList1[i1];
+        const GIntBig nVal2 = panFIDList2[i2];
+        if( nVal1 < nVal2 )
         {
-            if (i1+1 < nFIDCount1 && panFIDList1[i1+1] <= nVal2)
+            if( i1+1 < nFIDCount1 && panFIDList1[i1+1] <= nVal2 )
             {
-                i1 ++;
+                i1++;
             }
             else
             {
-                i1 ++;
-                i2 ++;
+                i1++;
+                i2++;
             }
         }
-        else if (nVal1 == nVal2)
+        else if( nVal1 == nVal2 )
         {
-            panFIDList[nFIDCount ++] = nVal1;
-            i1 ++;
-            i2 ++;
+            panFIDList[nFIDCount++] = nVal1;
+            i1++;
+            i2++;
         }
         else
         {
-            if (i2+1 < nFIDCount2 && panFIDList2[i2+1] <= nVal1)
+            if( i2 + 1 < nFIDCount2 && panFIDList2[i2+1] <= nVal1 )
             {
-                i2 ++;
+                i2++;
             }
             else
             {
-                i1 ++;
-                i2 ++;
+                i1++;
+                i2++;
             }
         }
     }
@@ -496,32 +499,30 @@ GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( swq_expr_node *psExpr,
                                                   OGRLayer *poLayer,
                                                   GIntBig& nFIDCount )
 {
-    OGRAttrIndex *poIndex;
-
-/* -------------------------------------------------------------------- */
-/*      Does the expression meet our requirements?                      */
-/* -------------------------------------------------------------------- */
+    // Does the expression meet our requirements?
     if( psExpr == NULL ||
         psExpr->eNodeType != SNT_OPERATION )
         return NULL;
 
-    if ((psExpr->nOperation == SWQ_OR || psExpr->nOperation == SWQ_AND) &&
-         psExpr->nSubExprCount == 2)
+    if( (psExpr->nOperation == SWQ_OR || psExpr->nOperation == SWQ_AND) &&
+         psExpr->nSubExprCount == 2 )
     {
-        GIntBig nFIDCount1 = 0, nFIDCount2 = 0;
-        GIntBig* panFIDList1 = EvaluateAgainstIndices( psExpr->papoSubExpr[0], poLayer, nFIDCount1 );
-        GIntBig* panFIDList2 = panFIDList1 == NULL ? NULL :
-                            EvaluateAgainstIndices( psExpr->papoSubExpr[1], poLayer, nFIDCount2 );
+        GIntBig nFIDCount1 = 0;
+        GIntBig nFIDCount2 = 0;
+        GIntBig* panFIDList1 =
+            EvaluateAgainstIndices(psExpr->papoSubExpr[0], poLayer, nFIDCount1);
+        GIntBig* panFIDList2 =
+            panFIDList1 == NULL ? NULL :
+            EvaluateAgainstIndices(psExpr->papoSubExpr[1], poLayer, nFIDCount2);
         GIntBig* panFIDList = NULL;
-        if (panFIDList1 != NULL && panFIDList2 != NULL)
+        if( panFIDList1 != NULL && panFIDList2 != NULL )
         {
-            if (psExpr->nOperation == SWQ_OR )
+            if( psExpr->nOperation == SWQ_OR )
                 panFIDList = OGRORGIntBigArray(panFIDList1, nFIDCount1,
                                             panFIDList2, nFIDCount2, nFIDCount);
-            else if (psExpr->nOperation == SWQ_AND )
+            else if( psExpr->nOperation == SWQ_AND )
                 panFIDList = OGRANDGIntBigArray(panFIDList1, nFIDCount1,
                                             panFIDList2, nFIDCount2, nFIDCount);
-
         }
         CPLFree(panFIDList1);
         CPLFree(panFIDList2);
@@ -539,41 +540,40 @@ GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( swq_expr_node *psExpr,
         || poValue->eNodeType != SNT_CONSTANT )
         return NULL;
 
-    poIndex = poLayer->GetIndex()->GetFieldIndex( poColumn->field_index );
+    OGRAttrIndex *poIndex =
+        poLayer->GetIndex()->GetFieldIndex(poColumn->field_index);
     if( poIndex == NULL )
         return NULL;
 
-/* -------------------------------------------------------------------- */
-/*      OK, we have an index, now we need to query it.                  */
-/* -------------------------------------------------------------------- */
+    // Have an index, now we need to query it.
     OGRField sValue;
-    OGRFieldDefn *poFieldDefn;
-
-    poFieldDefn = poLayer->GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+    OGRFieldDefn *poFieldDefn =
+        poLayer->GetLayerDefn()->GetFieldDefn(poColumn->field_index);
 
-/* -------------------------------------------------------------------- */
-/*      Handle the case of an IN operation.                             */
-/* -------------------------------------------------------------------- */
-    if (psExpr->nOperation == SWQ_IN)
+    // Handle the case of an IN operation.
+    if( psExpr->nOperation == SWQ_IN )
     {
-        int nLength;
+        int nLength = 0;
         GIntBig *panFIDs = NULL;
-        int iIN;
+        nFIDCount = 0;
 
-        for( iIN = 1; iIN < psExpr->nSubExprCount; iIN++ )
+        for( int iIN = 1; iIN < psExpr->nSubExprCount; iIN++ )
         {
             switch( poFieldDefn->GetType() )
             {
               case OFTInteger:
-                if (psExpr->papoSubExpr[iIN]->field_type == SWQ_FLOAT)
-                    sValue.Integer = (int) psExpr->papoSubExpr[iIN]->float_value;
+                if( psExpr->papoSubExpr[iIN]->field_type == SWQ_FLOAT )
+                    sValue.Integer =
+                        static_cast<int>(psExpr->papoSubExpr[iIN]->float_value);
                 else
-                    sValue.Integer = (int) psExpr->papoSubExpr[iIN]->int_value;
+                    sValue.Integer =
+                        static_cast<int>(psExpr->papoSubExpr[iIN]->int_value);
                 break;
 
               case OFTInteger64:
-                if (psExpr->papoSubExpr[iIN]->field_type == SWQ_FLOAT)
-                    sValue.Integer64 = (GIntBig) psExpr->papoSubExpr[iIN]->float_value;
+                if( psExpr->papoSubExpr[iIN]->field_type == SWQ_FLOAT )
+                    sValue.Integer64 = static_cast<GIntBig>(
+                        psExpr->papoSubExpr[iIN]->float_value);
                 else
                     sValue.Integer64 = psExpr->papoSubExpr[iIN]->int_value;
                 break;
@@ -587,38 +587,38 @@ GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( swq_expr_node *psExpr,
                 break;
 
               default:
-                CPLAssert( FALSE );
+                CPLAssert(false);
                 return NULL;
             }
 
-            int nFIDCount32 = 0;
-            panFIDs = poIndex->GetAllMatches( &sValue, panFIDs, &nFIDCount32, &nLength );
+            int nFIDCount32 = static_cast<int>(nFIDCount);
+            panFIDs = poIndex->GetAllMatches(&sValue, panFIDs,
+                                             &nFIDCount32, &nLength);
             nFIDCount = nFIDCount32;
         }
 
-        if (nFIDCount > 1)
+        if( nFIDCount > 1 )
         {
-            /* the returned FIDs are expected to be in sorted order */
-            qsort(panFIDs, (size_t)nFIDCount, sizeof(GIntBig), CompareGIntBig);
+            // The returned FIDs are expected to be in sorted order.
+            qsort(panFIDs, static_cast<size_t>(nFIDCount),
+                  sizeof(GIntBig), CompareGIntBig);
         }
         return panFIDs;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Handle equality test.                                           */
-/* -------------------------------------------------------------------- */
+    // Handle equality test.
     switch( poFieldDefn->GetType() )
     {
       case OFTInteger:
-        if (poValue->field_type == SWQ_FLOAT)
-            sValue.Integer = (int) poValue->float_value;
+        if( poValue->field_type == SWQ_FLOAT )
+            sValue.Integer = static_cast<int>(poValue->float_value);
         else
-            sValue.Integer = (int) poValue->int_value;
+            sValue.Integer = static_cast<int>(poValue->int_value);
         break;
 
       case OFTInteger64:
-        if (poValue->field_type == SWQ_FLOAT)
-            sValue.Integer64 = (GIntBig) poValue->float_value;
+        if( poValue->field_type == SWQ_FLOAT )
+            sValue.Integer64 = static_cast<GIntBig>(poValue->float_value);
         else
             sValue.Integer64 = poValue->int_value;
         break;
@@ -632,18 +632,21 @@ GIntBig *OGRFeatureQuery::EvaluateAgainstIndices( swq_expr_node *psExpr,
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert(false);
         return NULL;
     }
 
     int nLength = 0;
     int nFIDCount32 = 0;
-    GIntBig* panFIDs = poIndex->GetAllMatches( &sValue, NULL, &nFIDCount32, &nLength );
+    GIntBig* panFIDs =
+        poIndex->GetAllMatches(&sValue, NULL, &nFIDCount32, &nLength);
     nFIDCount = nFIDCount32;
-    if (nFIDCount > 1)
+    if( nFIDCount > 1 )
     {
-        /* the returned FIDs are expected to be in sorted order */
-        qsort(panFIDs, (size_t)nFIDCount, sizeof(GIntBig), CompareGIntBig);
+        // The returned FIDs are expected to be sorted.
+        // TODO(schwehr): Use std::sort.
+        qsort(panFIDs, static_cast<size_t>(nFIDCount),
+              sizeof(GIntBig), CompareGIntBig);
     }
     return panFIDs;
 }
@@ -659,12 +662,10 @@ char **OGRFeatureQuery::FieldCollector( void *pBareOp,
                                         char **papszList )
 
 {
-    swq_expr_node *op = (swq_expr_node *) pBareOp;
+    swq_expr_node *op = static_cast<swq_expr_node *>(pBareOp);
 
-/* -------------------------------------------------------------------- */
-/*      References to tables other than the primarily are currently     */
-/*      unsupported. Error out.                                         */
-/* -------------------------------------------------------------------- */
+    // References to tables other than the primarily are currently unsupported.
+    // Error out.
     if( op->eNodeType == SNT_COLUMN )
     {
         if( op->table_index != 0 )
@@ -673,36 +674,39 @@ char **OGRFeatureQuery::FieldCollector( void *pBareOp,
             return NULL;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Add the field name into our list if it is not already there.    */
-/* -------------------------------------------------------------------- */
-        const char *pszFieldName;
+        // Add the field name into our list if it is not already there.
+        const char *pszFieldName = NULL;
 
         if( op->field_index >= poTargetDefn->GetFieldCount()
-            && op->field_index < poTargetDefn->GetFieldCount() + SPECIAL_FIELD_COUNT)
-            pszFieldName = SpecialFieldNames[op->field_index - poTargetDefn->GetFieldCount()];
+            && op->field_index <
+            poTargetDefn->GetFieldCount() + SPECIAL_FIELD_COUNT )
+        {
+            pszFieldName =
+                SpecialFieldNames[op->field_index -
+                                  poTargetDefn->GetFieldCount()];
+        }
         else if( op->field_index >= 0
                  && op->field_index < poTargetDefn->GetFieldCount() )
+        {
             pszFieldName =
                 poTargetDefn->GetFieldDefn(op->field_index)->GetNameRef();
+        }
         else
         {
-            CSLDestroy( papszList );
+            CSLDestroy(papszList);
             return NULL;
         }
 
-        if( CSLFindString( papszList, pszFieldName ) == -1 )
-            papszList = CSLAddString( papszList, pszFieldName );
+        if( CSLFindString(papszList, pszFieldName) == -1 )
+            papszList = CSLAddString(papszList, pszFieldName);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Add in fields from subexpressions.                              */
-/* -------------------------------------------------------------------- */
+    // Add in fields from subexpressions.
     if( op->eNodeType == SNT_OPERATION )
     {
         for( int iSubExpr = 0; iSubExpr < op->nSubExprCount; iSubExpr++ )
         {
-            papszList = FieldCollector( op->papoSubExpr[iSubExpr], papszList );
+            papszList = FieldCollector(op->papoSubExpr[iSubExpr], papszList);
         }
     }
 
@@ -738,3 +742,5 @@ char **OGRFeatureQuery::GetUsedFields( )
 
     return FieldCollector( pSWQExpr, NULL );
 }
+
+//! @endcond
diff --git a/ogr/ogrfeaturestyle.cpp b/ogr/ogrfeaturestyle.cpp
index 30e07bc..f5e45ec 100644
--- a/ogr/ogrfeaturestyle.cpp
+++ b/ogr/ogrfeaturestyle.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfeaturestyle.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Feature Representation string API
@@ -28,82 +27,95 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_featurestyle.h"
+
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <string>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
-#include "ogr_feature.h"
-#include "ogr_featurestyle.h"
+#include "cpl_vsi.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
 
-CPL_CVSID("$Id: ogrfeaturestyle.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrfeaturestyle.cpp 36396 2016-11-21 14:53:59Z rouault $");
 
 /****************************************************************************/
 /*                Class Parameter (used in the String)                      */
 /*                                                                          */
-/*      The order of all parameter MUST be the same than in the definition  */
+/*      The order of all parameter MUST be the same than in the definition. */
 /****************************************************************************/
 static const OGRStyleParamId asStylePen[] =
 {
-    {OGRSTPenColor,"c",FALSE,OGRSTypeString},
-    {OGRSTPenWidth,"w",TRUE,OGRSTypeDouble},
-    {OGRSTPenPattern,"p",FALSE,OGRSTypeString}, // georefed,but multiple times.
-    {OGRSTPenId,"id",FALSE,OGRSTypeString},
-    {OGRSTPenPerOffset,"dp",TRUE,OGRSTypeDouble},
-    {OGRSTPenCap,"cap",FALSE,OGRSTypeString},
-    {OGRSTPenJoin,"j",FALSE,OGRSTypeString},
-    {OGRSTPenPriority, "l", FALSE, OGRSTypeInteger}
+    {OGRSTPenColor, "c", FALSE, OGRSTypeString},
+    {OGRSTPenWidth, "w", TRUE, OGRSTypeDouble},
+    // Georefed, but multiple times.
+    {OGRSTPenPattern, "p", FALSE, OGRSTypeString},
+    {OGRSTPenId, "id", FALSE, OGRSTypeString},
+    {OGRSTPenPerOffset, "dp", TRUE, OGRSTypeDouble},
+    {OGRSTPenCap, "cap", FALSE, OGRSTypeString},
+    {OGRSTPenJoin, "j", FALSE, OGRSTypeString},
+    {OGRSTPenPriority,  "l",  FALSE,  OGRSTypeInteger}
 };
 
 static const OGRStyleParamId asStyleBrush[] =
 {
-    {OGRSTBrushFColor,"fc",FALSE,OGRSTypeString},
-    {OGRSTBrushBColor,"bc",FALSE,OGRSTypeString},
-    {OGRSTBrushId,"id",FALSE,OGRSTypeString},
-    {OGRSTBrushAngle,"a",FALSE,OGRSTypeDouble},
-    {OGRSTBrushSize,"s",TRUE,OGRSTypeDouble},
-    {OGRSTBrushDx,"dx",TRUE,OGRSTypeDouble},
-    {OGRSTBrushDy,"dy",TRUE,OGRSTypeDouble},
-    {OGRSTBrushPriority,"l",FALSE,OGRSTypeInteger}
+    {OGRSTBrushFColor, "fc", FALSE, OGRSTypeString},
+    {OGRSTBrushBColor, "bc", FALSE, OGRSTypeString},
+    {OGRSTBrushId, "id", FALSE, OGRSTypeString},
+    {OGRSTBrushAngle, "a", FALSE, OGRSTypeDouble},
+    {OGRSTBrushSize, "s", TRUE, OGRSTypeDouble},
+    {OGRSTBrushDx, "dx", TRUE, OGRSTypeDouble},
+    {OGRSTBrushDy, "dy", TRUE, OGRSTypeDouble},
+    {OGRSTBrushPriority, "l", FALSE, OGRSTypeInteger}
 };
 
 static const OGRStyleParamId asStyleSymbol[] =
 {
-    {OGRSTSymbolId,"id",FALSE,OGRSTypeString},
-    {OGRSTSymbolAngle,"a",FALSE,OGRSTypeDouble},
-    {OGRSTSymbolColor,"c",FALSE,OGRSTypeString},
-    {OGRSTSymbolSize,"s",TRUE,OGRSTypeDouble},
-    {OGRSTSymbolDx,"dx",TRUE,OGRSTypeDouble},
-    {OGRSTSymbolDy,"dy",TRUE,OGRSTypeDouble},
-    {OGRSTSymbolStep,"ds",TRUE,OGRSTypeDouble},
-    {OGRSTSymbolPerp,"dp",TRUE,OGRSTypeDouble},
-    {OGRSTSymbolOffset,"di",TRUE,OGRSTypeDouble},
-    {OGRSTSymbolPriority,"l",FALSE,OGRSTypeInteger},
-    {OGRSTSymbolFontName,"f",FALSE,OGRSTypeString},
-    {OGRSTSymbolOColor,"o",FALSE,OGRSTypeString}
+    {OGRSTSymbolId, "id", FALSE, OGRSTypeString},
+    {OGRSTSymbolAngle, "a", FALSE, OGRSTypeDouble},
+    {OGRSTSymbolColor, "c", FALSE, OGRSTypeString},
+    {OGRSTSymbolSize, "s", TRUE, OGRSTypeDouble},
+    {OGRSTSymbolDx, "dx", TRUE, OGRSTypeDouble},
+    {OGRSTSymbolDy, "dy", TRUE, OGRSTypeDouble},
+    {OGRSTSymbolStep, "ds", TRUE, OGRSTypeDouble},
+    {OGRSTSymbolPerp, "dp", TRUE, OGRSTypeDouble},
+    {OGRSTSymbolOffset, "di", TRUE, OGRSTypeDouble},
+    {OGRSTSymbolPriority, "l", FALSE, OGRSTypeInteger},
+    {OGRSTSymbolFontName, "f", FALSE, OGRSTypeString},
+    {OGRSTSymbolOColor, "o", FALSE, OGRSTypeString}
 };
 
 static const OGRStyleParamId asStyleLabel[] =
 {
-    {OGRSTLabelFontName,"f",FALSE,OGRSTypeString},
-    {OGRSTLabelSize,"s",TRUE,OGRSTypeDouble},
-    {OGRSTLabelTextString,"t",FALSE, OGRSTypeString},
-    {OGRSTLabelAngle,"a",FALSE,OGRSTypeDouble},
-    {OGRSTLabelFColor,"c",FALSE,OGRSTypeString},
-    {OGRSTLabelBColor,"b",FALSE,OGRSTypeString},
-    {OGRSTLabelPlacement,"m",FALSE, OGRSTypeString},
-    {OGRSTLabelAnchor,"p",FALSE,OGRSTypeInteger},
-    {OGRSTLabelDx,"dx",TRUE,OGRSTypeDouble},
-    {OGRSTLabelDy,"dy",TRUE,OGRSTypeDouble},
-    {OGRSTLabelPerp,"dp",TRUE,OGRSTypeDouble},
-    {OGRSTLabelBold,"bo",FALSE,OGRSTypeBoolean},
-    {OGRSTLabelItalic,"it",FALSE,OGRSTypeBoolean},
-    {OGRSTLabelUnderline,"un",FALSE, OGRSTypeBoolean},
-    {OGRSTLabelPriority,"l",FALSE, OGRSTypeInteger},
-    {OGRSTLabelStrikeout,"st",FALSE, OGRSTypeBoolean},
-    {OGRSTLabelStretch,"w",FALSE, OGRSTypeDouble},
-    {OGRSTLabelAdjHor,"ah",FALSE, OGRSTypeString},
-    {OGRSTLabelAdjVert,"av",FALSE, OGRSTypeString},
-    {OGRSTLabelHColor,"h",FALSE,OGRSTypeString},
-    {OGRSTLabelOColor,"o",FALSE,OGRSTypeString}
+    {OGRSTLabelFontName, "f", FALSE, OGRSTypeString},
+    {OGRSTLabelSize, "s", TRUE, OGRSTypeDouble},
+    {OGRSTLabelTextString, "t", FALSE, OGRSTypeString},
+    {OGRSTLabelAngle, "a", FALSE, OGRSTypeDouble},
+    {OGRSTLabelFColor, "c", FALSE, OGRSTypeString},
+    {OGRSTLabelBColor, "b", FALSE, OGRSTypeString},
+    {OGRSTLabelPlacement, "m", FALSE, OGRSTypeString},
+    {OGRSTLabelAnchor, "p", FALSE, OGRSTypeInteger},
+    {OGRSTLabelDx, "dx", TRUE, OGRSTypeDouble},
+    {OGRSTLabelDy, "dy", TRUE, OGRSTypeDouble},
+    {OGRSTLabelPerp, "dp", TRUE, OGRSTypeDouble},
+    {OGRSTLabelBold, "bo", FALSE, OGRSTypeBoolean},
+    {OGRSTLabelItalic, "it", FALSE, OGRSTypeBoolean},
+    {OGRSTLabelUnderline, "un", FALSE, OGRSTypeBoolean},
+    {OGRSTLabelPriority, "l", FALSE, OGRSTypeInteger},
+    {OGRSTLabelStrikeout, "st", FALSE, OGRSTypeBoolean},
+    {OGRSTLabelStretch, "w", FALSE, OGRSTypeDouble},
+    {OGRSTLabelAdjHor, "ah", FALSE, OGRSTypeString},
+    {OGRSTLabelAdjVert, "av", FALSE, OGRSTypeString},
+    {OGRSTLabelHColor, "h", FALSE, OGRSTypeString},
+    {OGRSTLabelOColor, "o", FALSE, OGRSTypeString}
 };
 
 /* ======================================================================== */
@@ -119,10 +131,10 @@ static const OGRStyleParamId asStyleLabel[] =
  *
  * This method is the same as the C function OGR_SM_Create()
  *
- * @param poDataSetStyleTable (currently unused, reserved for future use), pointer
- * to OGRStyleTable. Pass NULL for now.
+ * @param poDataSetStyleTable (currently unused, reserved for future use),
+ * pointer to OGRStyleTable. Pass NULL for now.
  */
-OGRStyleMgr::OGRStyleMgr(OGRStyleTable *poDataSetStyleTable)
+OGRStyleMgr::OGRStyleMgr( OGRStyleTable *poDataSetStyleTable )
 {
     m_poDataSetStyleTable = poDataSetStyleTable;
     m_pszStyleString = NULL;
@@ -145,10 +157,10 @@ OGRStyleMgr::OGRStyleMgr(OGRStyleTable *poDataSetStyleTable)
 OGRStyleMgrH OGR_SM_Create( OGRStyleTableH hStyleTable )
 
 {
-    return (OGRStyleMgrH) new OGRStyleMgr( (OGRStyleTable *) hStyleTable );
+    return reinterpret_cast<OGRStyleMgrH>(
+        new OGRStyleMgr(reinterpret_cast<OGRStyleTable *>(hStyleTable)));
 }
 
-
 /****************************************************************************/
 /*             OGRStyleMgr::~OGRStyleMgr()                                  */
 /*                                                                          */
@@ -160,8 +172,7 @@ OGRStyleMgrH OGR_SM_Create( OGRStyleTableH hStyleTable )
  */
 OGRStyleMgr::~OGRStyleMgr()
 {
-    if ( m_pszStyleString )
-        CPLFree(m_pszStyleString);
+    CPLFree(m_pszStyleString);
 }
 
 /************************************************************************/
@@ -178,10 +189,9 @@ OGRStyleMgr::~OGRStyleMgr()
 void OGR_SM_Destroy( OGRStyleMgrH hSM )
 
 {
-    delete (OGRStyleMgr *) hSM;
+    delete reinterpret_cast<OGRStyleMgr *>(hSM);
 }
 
-
 /****************************************************************************/
 /*      GBool OGRStyleMgr::SetFeatureStyleString(OGRFeature *poFeature,     */
 /*                                       char *pszStyleString,              */
@@ -202,22 +212,23 @@ void OGR_SM_Destroy( OGRStyleMgrH hSM )
  * @return TRUE on success, FALSE on error.
  */
 
-GBool OGRStyleMgr::SetFeatureStyleString(OGRFeature *poFeature,
-                                         const char *pszStyleString,
-                                         GBool bNoMatching)
+GBool OGRStyleMgr::SetFeatureStyleString( OGRFeature *poFeature,
+                                          const char *pszStyleString,
+                                          GBool bNoMatching )
 {
-    const char *pszName;
-    if (poFeature == NULL)
-      return FALSE;
+    if( poFeature == NULL )
+        return FALSE;
+
+    const char *pszName = NULL;
 
-    if (pszStyleString == NULL)
-      poFeature->SetStyleString("");
-    else if (bNoMatching == TRUE)
-      poFeature->SetStyleString(pszStyleString);
-    else if ((pszName = GetStyleName(pszStyleString)) != NULL)
-      poFeature->SetStyleString(pszName);
+    if( pszStyleString == NULL )
+        poFeature->SetStyleString("");
+    else if( bNoMatching == TRUE )
+        poFeature->SetStyleString(pszStyleString);
+    else if( (pszName = GetStyleName(pszStyleString)) != NULL )
+        poFeature->SetStyleString(pszName);
     else
-      poFeature->SetStyleString(pszStyleString);
+        poFeature->SetStyleString(pszStyleString);
 
     return TRUE;
 }
@@ -238,18 +249,17 @@ GBool OGRStyleMgr::SetFeatureStyleString(OGRFeature *poFeature,
  * in case of error..
  */
 
-const char *OGRStyleMgr::InitFromFeature(OGRFeature *poFeature)
+const char *OGRStyleMgr::InitFromFeature( OGRFeature *poFeature )
 {
     CPLFree(m_pszStyleString);
     m_pszStyleString = NULL;
 
-    if (poFeature)
-      InitStyleString(poFeature->GetStyleString());
+    if( poFeature )
+        InitStyleString(poFeature->GetStyleString());
     else
-      m_pszStyleString = NULL;
+        m_pszStyleString = NULL;
 
     return m_pszStyleString;
-
 }
 
 /************************************************************************/
@@ -269,14 +279,14 @@ const char *OGRStyleMgr::InitFromFeature(OGRFeature *poFeature)
  * in case of error.
  */
 
-const char *OGR_SM_InitFromFeature(OGRStyleMgrH hSM,
-                                           OGRFeatureH hFeat)
+const char *OGR_SM_InitFromFeature( OGRStyleMgrH hSM, OGRFeatureH hFeat )
 
 {
     VALIDATE_POINTER1( hSM, "OGR_SM_InitFromFeature", NULL );
     VALIDATE_POINTER1( hFeat, "OGR_SM_InitFromFeature", NULL );
 
-    return ((OGRStyleMgr *) hSM)->InitFromFeature((OGRFeature *)hFeat);
+    return reinterpret_cast<OGRStyleMgr *>(hSM)->
+        InitFromFeature(reinterpret_cast<OGRFeature *>(hFeat));
 }
 
 /****************************************************************************/
@@ -293,18 +303,18 @@ const char *OGR_SM_InitFromFeature(OGRStyleMgrH hSM,
  *
  * @return TRUE on success, FALSE on errors.
  */
-GBool OGRStyleMgr::InitStyleString(const char *pszStyleString)
+GBool OGRStyleMgr::InitStyleString( const char *pszStyleString )
 {
     CPLFree(m_pszStyleString);
     m_pszStyleString = NULL;
 
-    if (pszStyleString && pszStyleString[0] == '@')
-      m_pszStyleString = CPLStrdup(GetStyleByName(pszStyleString));
+    if( pszStyleString && pszStyleString[0] == '@' )
+        m_pszStyleString = CPLStrdup(GetStyleByName(pszStyleString));
     else
-      m_pszStyleString = NULL;
+        m_pszStyleString = NULL;
 
-    if (m_pszStyleString == NULL && pszStyleString)
-      m_pszStyleString = CPLStrdup(pszStyleString);
+    if( m_pszStyleString == NULL && pszStyleString )
+        m_pszStyleString = CPLStrdup(pszStyleString);
 
     return TRUE;
 }
@@ -324,46 +334,39 @@ GBool OGRStyleMgr::InitStyleString(const char *pszStyleString)
  * @return TRUE on success, FALSE on errors.
  */
 
-int OGR_SM_InitStyleString(OGRStyleMgrH hSM, const char *pszStyleString)
+int OGR_SM_InitStyleString( OGRStyleMgrH hSM, const char *pszStyleString )
 
 {
     VALIDATE_POINTER1( hSM, "OGR_SM_InitStyleString", FALSE );
 
-    return ((OGRStyleMgr *) hSM)->InitStyleString(pszStyleString);
+    return reinterpret_cast<OGRStyleMgr *>(hSM)->
+        InitStyleString(pszStyleString);
 }
 
-
 /****************************************************************************/
 /*      const char *OGRStyleMgr::GetStyleName(const char *pszStyleString)   */
-/*                                                                          */
 /****************************************************************************/
 
 /**
  * \brief Get the name of a style from the style table.
  *
- * @param pszStyleString  the style to search for, or NULL to use the style
+ * @param pszStyleString the style to search for, or NULL to use the style
  *   currently stored in the manager.
  *
  * @return The name if found, or NULL on error.
  */
 
-const char *OGRStyleMgr::GetStyleName(const char *pszStyleString)
+const char *OGRStyleMgr::GetStyleName( const char *pszStyleString )
 {
-
     // SECURITY: The unit and the value for all parameter should be the same,
     // a text comparison is executed.
 
-    const char *pszStyle;
+    const char *pszStyle = pszStyleString ? pszStyleString : m_pszStyleString;
 
-    if (pszStyleString)
-      pszStyle = pszStyleString;
-    else
-      pszStyle = m_pszStyleString;
-
-    if (pszStyle)
+    if( pszStyle )
     {
-        if (m_poDataSetStyleTable)
-          return  m_poDataSetStyleTable->GetStyleName(pszStyle);
+        if( m_poDataSetStyleTable )
+            return m_poDataSetStyleTable->GetStyleName(pszStyle);
     }
     return NULL;
 }
@@ -380,11 +383,11 @@ const char *OGRStyleMgr::GetStyleName(const char *pszStyleString)
  *
  * @return the style string matching the name or NULL if not found or error.
  */
-const char *OGRStyleMgr::GetStyleByName(const char *pszStyleName)
+const char *OGRStyleMgr::GetStyleByName( const char *pszStyleName )
 {
-    if (m_poDataSetStyleTable)
+    if( m_poDataSetStyleTable )
     {
-        return  m_poDataSetStyleTable->Find(pszStyleName);
+        return m_poDataSetStyleTable->Find(pszStyleName);
     }
     return NULL;
 }
@@ -407,24 +410,18 @@ const char *OGRStyleMgr::GetStyleByName(const char *pszStyleName)
  * @return TRUE on success, FALSE on errors.
  */
 
-GBool OGRStyleMgr::AddStyle(const char *pszStyleName,
-                            const char *pszStyleString)
+GBool OGRStyleMgr::AddStyle( const char *pszStyleName,
+                             const char *pszStyleString )
 {
-    const char *pszStyle;
+    const char *pszStyle = pszStyleString ? pszStyleString : m_pszStyleString;
 
-    if (pszStyleString)
-      pszStyle = pszStyleString;
-    else
-      pszStyle = m_pszStyleString;
-
-    if (m_poDataSetStyleTable)
+    if( m_poDataSetStyleTable )
     {
         return m_poDataSetStyleTable->AddStyle(pszStyleName, pszStyle);
     }
     return FALSE;
 }
 
-
 /************************************************************************/
 /*                     OGR_SM_AddStyle()                         */
 /************************************************************************/
@@ -442,16 +439,16 @@ GBool OGRStyleMgr::AddStyle(const char *pszStyleName,
  * @return TRUE on success, FALSE on errors.
  */
 
-int OGR_SM_AddStyle(OGRStyleMgrH hSM, const char *pszStyleName,
-                    const char *pszStyleString)
+int OGR_SM_AddStyle( OGRStyleMgrH hSM, const char *pszStyleName,
+                     const char *pszStyleString )
 {
     VALIDATE_POINTER1( hSM, "OGR_SM_AddStyle", FALSE );
     VALIDATE_POINTER1( pszStyleName, "OGR_SM_AddStyle", FALSE );
 
-    return ((OGRStyleMgr *) hSM)->AddStyle( pszStyleName, pszStyleString);
+    return reinterpret_cast<OGRStyleMgr *>(hSM)->
+        AddStyle( pszStyleName, pszStyleString);
 }
 
-
 /****************************************************************************/
 /*            const char *OGRStyleMgr::GetStyleString(OGRFeature *)         */
 /*                                                                          */
@@ -470,12 +467,12 @@ int OGR_SM_AddStyle(OGRStyleMgrH hSM, const char *pszStyleName,
  *       not NULL and replace the style string stored in the style manager
  */
 
-const char *OGRStyleMgr::GetStyleString(OGRFeature *poFeature)
+const char *OGRStyleMgr::GetStyleString( OGRFeature *poFeature )
 {
-    if (poFeature == NULL)
-      return m_pszStyleString;
-    else
-      return InitFromFeature(poFeature);
+    if( poFeature == NULL )
+        return m_pszStyleString;
+
+    return InitFromFeature(poFeature);
 }
 
 /****************************************************************************/
@@ -491,28 +488,25 @@ const char *OGRStyleMgr::GetStyleString(OGRFeature *poFeature)
  * @return TRUE on success, FALSE on errors.
  */
 
-GBool OGRStyleMgr::AddPart(const char *pszPart)
+GBool OGRStyleMgr::AddPart( const char *pszPart )
 {
-    char *pszTmp;
-    if (pszPart)
+    if( pszPart == NULL )
+        return FALSE;
+
+    if( m_pszStyleString )
     {
-        if (m_pszStyleString)
-        {
-            pszTmp = CPLStrdup(CPLString().Printf("%s;%s",m_pszStyleString,
-                                          pszPart));
-            CPLFree(m_pszStyleString);
-            m_pszStyleString = pszTmp;
-        }
-        else
-        {
-              pszTmp= CPLStrdup(CPLString().Printf("%s",pszPart));
-              CPLFree(m_pszStyleString);
-              m_pszStyleString = pszTmp;
-        }
-        return TRUE;
+        char *pszTmp =
+            CPLStrdup(CPLString().Printf("%s;%s", m_pszStyleString, pszPart));
+        CPLFree(m_pszStyleString);
+        m_pszStyleString = pszTmp;
     }
-
-    return FALSE;
+    else
+    {
+        char *pszTmp = CPLStrdup(CPLString().Printf("%s", pszPart));
+        CPLFree(m_pszStyleString);
+        m_pszStyleString = pszTmp;
+    }
+    return TRUE;
 }
 
 /****************************************************************************/
@@ -530,29 +524,28 @@ GBool OGRStyleMgr::AddPart(const char *pszPart)
  * @return TRUE on success, FALSE on errors.
  */
 
-GBool OGRStyleMgr::AddPart(OGRStyleTool *poStyleTool)
+GBool OGRStyleMgr::AddPart( OGRStyleTool *poStyleTool )
 {
-    char *pszTmp;
-    if (poStyleTool && poStyleTool->GetStyleString())
+    if( poStyleTool == NULL || !poStyleTool->GetStyleString() )
+        return FALSE;
+
+    if( m_pszStyleString )
     {
-        if (m_pszStyleString)
-        {
-            pszTmp = CPLStrdup(CPLString().Printf("%s;%s",m_pszStyleString,
-                                        poStyleTool->GetStyleString()));
-            CPLFree(m_pszStyleString);
-            m_pszStyleString = pszTmp;
-        }
-        else
-        {
-              pszTmp= CPLStrdup(CPLString().Printf("%s",
-                                        poStyleTool->GetStyleString()));
-              CPLFree(m_pszStyleString);
-              m_pszStyleString = pszTmp;
-        }
-        return TRUE;
+        char *pszTmp =
+            CPLStrdup(CPLString().Printf("%s;%s", m_pszStyleString,
+                                         poStyleTool->GetStyleString()));
+        CPLFree(m_pszStyleString);
+        m_pszStyleString = pszTmp;
     }
-
-    return FALSE;
+    else
+    {
+        char *pszTmp =
+            CPLStrdup(CPLString().Printf("%s",
+                                         poStyleTool->GetStyleString()));
+          CPLFree(m_pszStyleString);
+          m_pszStyleString = pszTmp;
+    }
+    return TRUE;
 }
 
 /************************************************************************/
@@ -570,16 +563,16 @@ GBool OGRStyleMgr::AddPart(OGRStyleTool *poStyleTool)
  * @return TRUE on success, FALSE on errors.
  */
 
-int OGR_SM_AddPart(OGRStyleMgrH hSM, OGRStyleToolH hST)
+int OGR_SM_AddPart( OGRStyleMgrH hSM, OGRStyleToolH hST )
 
 {
     VALIDATE_POINTER1( hSM, "OGR_SM_InitStyleString", FALSE );
     VALIDATE_POINTER1( hST, "OGR_SM_InitStyleString", FALSE );
 
-    return ((OGRStyleMgr *) hSM)->AddPart((OGRStyleTool *)hST);
+    return reinterpret_cast<OGRStyleMgr *>(hSM)->
+        AddPart(reinterpret_cast<OGRStyleTool *>(hST));
 }
 
-
 /****************************************************************************/
 /*            int OGRStyleMgr::GetPartCount(const char *pszStyleString)     */
 /*            return the number of part in the stylestring                  */
@@ -598,25 +591,21 @@ int OGR_SM_AddPart(OGRStyleMgrH hSM, OGRStyleToolH hST)
  * @return the number of parts (style tools) in the style.
  */
 
-int OGRStyleMgr::GetPartCount(const char *pszStyleString)
+int OGRStyleMgr::GetPartCount( const char *pszStyleString )
 {
-    const char *pszPart;
-    int nPartCount = 1;
-    const char *pszString;
-    const char *pszStrTmp;
-
-    if (pszStyleString != NULL)
-      pszString = pszStyleString;
-    else
-      pszString = m_pszStyleString;
+    const char *pszString = pszStyleString != NULL
+        ? pszStyleString
+        : m_pszStyleString;
 
-    if (pszString == NULL)
+    if( pszString == NULL )
       return 0;
 
-    pszStrTmp = pszString;
+    int nPartCount = 1;
+    const char *pszStrTmp = pszString;
     // Search for parts separated by semicolons not counting the possible
     // semicolon at the and of string.
-    while ((pszPart = strstr(pszStrTmp, ";")) != NULL && pszPart[1] != '\0')
+    const char *pszPart = NULL;
+    while( (pszPart = strstr(pszStrTmp, ";")) != NULL && pszPart[1] != '\0' )
     {
         pszStrTmp = &pszPart[1];
         nPartCount++;
@@ -640,15 +629,14 @@ int OGRStyleMgr::GetPartCount(const char *pszStyleString)
  * @return the number of parts (style tools) in the style.
  */
 
-int OGR_SM_GetPartCount(OGRStyleMgrH hSM, const char *pszStyleString)
+int OGR_SM_GetPartCount( OGRStyleMgrH hSM, const char *pszStyleString )
 
 {
     VALIDATE_POINTER1( hSM, "OGR_SM_InitStyleString", FALSE );
 
-    return ((OGRStyleMgr *) hSM)->GetPartCount(pszStyleString);
+    return reinterpret_cast<OGRStyleMgr *>(hSM)->GetPartCount(pszStyleString);
 }
 
-
 /****************************************************************************/
 /*            OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,               */
 /*                                 const char *pszStyleString)              */
@@ -671,33 +659,27 @@ int OGR_SM_GetPartCount(OGRStyleMgrH hSM, const char *pszStyleString)
  * @return OGRStyleTool of the requested part (style tools) or NULL on error.
  */
 
-OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,
-                                   const char *pszStyleString)
+OGRStyleTool *OGRStyleMgr::GetPart( int nPartId,
+                                    const char *pszStyleString )
 {
-    char **papszStyleString;
-    const char *pszStyle;
-    const char *pszString;
-    OGRStyleTool    *poStyleTool = NULL;
-
-    if (pszStyleString)
-      pszStyle = pszStyleString;
-    else
-      pszStyle = m_pszStyleString;
+    const char *pszStyle = pszStyleString ? pszStyleString : m_pszStyleString;
 
-    if (pszStyle == NULL)
+    if( pszStyle == NULL )
       return NULL;
 
-    papszStyleString = CSLTokenizeString2(pszStyle, ";",
-                                          CSLT_HONOURSTRINGS
-                                          | CSLT_PRESERVEQUOTES
-                                          | CSLT_PRESERVEESCAPES );
+    char **papszStyleString =
+        CSLTokenizeString2(pszStyle, ";",
+                           CSLT_HONOURSTRINGS
+                           | CSLT_PRESERVEQUOTES
+                           | CSLT_PRESERVEESCAPES );
 
-    pszString = CSLGetField( papszStyleString, nPartId );
+    const char *pszString = CSLGetField( papszStyleString, nPartId );
 
-    if ( strlen(pszString) > 0 )
+    OGRStyleTool *poStyleTool = NULL;
+    if( strlen(pszString) > 0 )
     {
         poStyleTool = CreateStyleToolFromStyleString(pszString);
-        if ( poStyleTool )
+        if( poStyleTool )
             poStyleTool->SetStyleString(pszString);
     }
 
@@ -726,40 +708,44 @@ OGRStyleTool *OGRStyleMgr::GetPart(int nPartId,
  * @return OGRStyleToolH of the requested part (style tools) or NULL on error.
  */
 
-OGRStyleToolH OGR_SM_GetPart(OGRStyleMgrH hSM, int nPartId,
-                             const char *pszStyleString)
+OGRStyleToolH OGR_SM_GetPart( OGRStyleMgrH hSM, int nPartId,
+                              const char *pszStyleString )
 
 {
     VALIDATE_POINTER1( hSM, "OGR_SM_InitStyleString", NULL );
 
-    return (OGRStyleToolH) ((OGRStyleMgr *) hSM)->GetPart(nPartId, pszStyleString);
+    return
+        reinterpret_cast<OGRStyleToolH>(
+            reinterpret_cast<OGRStyleMgr *>(hSM)->
+                GetPart(nPartId, pszStyleString));
 }
 
-
 /****************************************************************************/
 /* OGRStyleTool *CreateStyleToolFromStyleString(const char *pszStyleString) */
 /*                                                                          */
 /* create a Style tool from the given StyleString, it should contain only a */
 /* part of a StyleString.                                                    */
 /****************************************************************************/
-OGRStyleTool *OGRStyleMgr::CreateStyleToolFromStyleString(const char *
-                                                          pszStyleString)
+
+//! @cond Doxygen_Suppress
+OGRStyleTool *
+OGRStyleMgr::CreateStyleToolFromStyleString( const char *pszStyleString )
 {
-    char **papszToken = CSLTokenizeString2(pszStyleString,"();",
+    char **papszToken = CSLTokenizeString2(pszStyleString, "();",
                                            CSLT_HONOURSTRINGS
                                            | CSLT_PRESERVEQUOTES
                                            | CSLT_PRESERVEESCAPES );
-    OGRStyleTool   *poStyleTool;
+    OGRStyleTool *poStyleTool = NULL;
 
-    if (CSLCount(papszToken) <2)
+    if( CSLCount(papszToken) < 2 )
         poStyleTool = NULL;
-    else if (EQUAL(papszToken[0],"PEN"))
+    else if( EQUAL(papszToken[0], "PEN") )
         poStyleTool = new OGRStylePen();
-    else if (EQUAL(papszToken[0],"BRUSH"))
+    else if( EQUAL(papszToken[0], "BRUSH") )
         poStyleTool = new OGRStyleBrush();
-    else if (EQUAL(papszToken[0],"SYMBOL"))
+    else if( EQUAL(papszToken[0], "SYMBOL") )
         poStyleTool = new OGRStyleSymbol();
-    else if (EQUAL(papszToken[0],"LABEL"))
+    else if( EQUAL(papszToken[0], "LABEL") )
         poStyleTool = new OGRStyleLabel();
     else
         poStyleTool = NULL;
@@ -768,13 +754,13 @@ OGRStyleTool *OGRStyleMgr::CreateStyleToolFromStyleString(const char *
 
     return poStyleTool;
 }
+//! @endcond
 
 /* ======================================================================== */
 /*                OGRStyleTable                                             */
 /*     Object Used to manage and store a styletable                         */
 /* ======================================================================== */
 
-
 /****************************************************************************/
 /*              OGRStyleTable::OGRStyleTable()                              */
 /*                                                                          */
@@ -800,7 +786,7 @@ OGRStyleTable::OGRStyleTable()
 OGRStyleTableH OGR_STBL_Create( void )
 
 {
-    return (OGRStyleTableH) new OGRStyleTable( );
+    return reinterpret_cast<OGRStyleTableH>(new OGRStyleTable());
 }
 
 /****************************************************************************/
@@ -815,7 +801,7 @@ OGRStyleTableH OGR_STBL_Create( void )
 
 void OGRStyleTable::Clear()
 {
-    if (m_papszStyleTable)
+    if( m_papszStyleTable )
       CSLDestroy(m_papszStyleTable);
     m_papszStyleTable = NULL;
 }
@@ -829,7 +815,6 @@ OGRStyleTable::~OGRStyleTable()
     Clear();
 }
 
-
 /************************************************************************/
 /*                           OGR_STBL_Destroy()                            */
 /************************************************************************/
@@ -842,7 +827,7 @@ OGRStyleTable::~OGRStyleTable()
 void OGR_STBL_Destroy( OGRStyleTableH hSTBL )
 
 {
-    delete (OGRStyleTable *) hSTBL;
+    delete reinterpret_cast<OGRStyleTable *>(hSTBL);
 }
 
 /****************************************************************************/
@@ -859,25 +844,21 @@ void OGR_STBL_Destroy( OGRStyleTableH hSTBL )
  * @return the Name of the matching style string or NULL on error.
  */
 
-const char *OGRStyleTable::GetStyleName(const char *pszStyleString)
+const char *OGRStyleTable::GetStyleName( const char *pszStyleString )
 {
-    int i;
-    const char *pszStyleStringBegin;
-
-    for (i=0;i<CSLCount(m_papszStyleTable);i++)
+    for( int i = 0; i < CSLCount(m_papszStyleTable); i++ )
     {
-        pszStyleStringBegin = strstr(m_papszStyleTable[i],":");
+        const char *pszStyleStringBegin =
+            strstr(m_papszStyleTable[i], ":");
 
-        if (pszStyleStringBegin && EQUAL(&pszStyleStringBegin[1],
-                                         pszStyleString))
+        if( pszStyleStringBegin && EQUAL(&pszStyleStringBegin[1],
+                                         pszStyleString) )
         {
-            size_t nColon;
-
             osLastRequestedStyleName = m_papszStyleTable[i];
-            nColon = osLastRequestedStyleName.find( ':' );
+            const size_t nColon = osLastRequestedStyleName.find( ':' );
             if( nColon != std::string::npos )
                 osLastRequestedStyleName =
-                    osLastRequestedStyleName.substr(0,nColon);
+                    osLastRequestedStyleName.substr(0, nColon);
 
             return osLastRequestedStyleName;
         }
@@ -890,7 +871,7 @@ const char *OGRStyleTable::GetStyleName(const char *pszStyleString)
 /*            GBool OGRStyleTable::AddStyle(char *pszName,                  */
 /*                                          char *pszStyleString)           */
 /*                                                                          */
-/*   Add a new style in the table, no comparison will be done on the       */
+/*   Add a new style in the table, no comparison will be done on the        */
 /*   Style string, only on the name, TRUE success, FALSE error              */
 /****************************************************************************/
 
@@ -905,20 +886,19 @@ const char *OGRStyleTable::GetStyleName(const char *pszStyleString)
  * @return TRUE on success, FALSE on error
  */
 
-GBool OGRStyleTable::AddStyle(const char *pszName, const char *pszStyleString)
+GBool OGRStyleTable::AddStyle( const char *pszName, const char *pszStyleString )
 {
-    int nPos;
+    if( pszName == NULL || pszStyleString == NULL )
+        return FALSE;
 
-    if (pszName && pszStyleString)
-    {
-        if ((nPos = IsExist(pszName)) != -1)
-          return FALSE;
+    const int nPos = IsExist(pszName);
+    if( nPos != -1 )
+      return FALSE;
 
-        m_papszStyleTable = CSLAddString(m_papszStyleTable,
-                              CPLString().Printf("%s:%s",pszName,pszStyleString));
-        return TRUE;
-    }
-    return FALSE;
+    m_papszStyleTable =
+        CSLAddString(m_papszStyleTable,
+                     CPLString().Printf("%s:%s", pszName, pszStyleString));
+    return TRUE;
 }
 
 /************************************************************************/
@@ -939,11 +919,12 @@ GBool OGRStyleTable::AddStyle(const char *pszName, const char *pszStyleString)
  */
 
 int OGR_STBL_AddStyle( OGRStyleTableH hStyleTable,
-                       const char *pszName, const char *pszStyleString)
+                       const char *pszName, const char *pszStyleString )
 {
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_AddStyle", FALSE );
 
-    return ((OGRStyleTable *) hStyleTable)->AddStyle( pszName, pszStyleString );
+    return reinterpret_cast<OGRStyleTable *>(hStyleTable)->
+        AddStyle(pszName, pszStyleString);
 }
 
 /****************************************************************************/
@@ -961,15 +942,14 @@ int OGR_STBL_AddStyle( OGRStyleTableH hStyleTable,
  * @return TRUE on success, FALSE on error
  */
 
-GBool OGRStyleTable::RemoveStyle(const char *pszName)
+GBool OGRStyleTable::RemoveStyle( const char *pszName )
 {
-    int nPos;
-    if ((nPos = IsExist(pszName)) != -1)
-    {
-        m_papszStyleTable = CSLRemoveStrings(m_papszStyleTable,nPos,1,NULL);
-        return TRUE;
-    }
-    return FALSE;
+    const int nPos = IsExist(pszName);
+    if( nPos == -1 )
+        return FALSE;
+
+    m_papszStyleTable = CSLRemoveStrings(m_papszStyleTable, nPos, 1, NULL);
+    return TRUE;
 }
 
 /****************************************************************************/
@@ -990,15 +970,14 @@ GBool OGRStyleTable::RemoveStyle(const char *pszName)
  * @return TRUE on success, FALSE on error
  */
 
-GBool OGRStyleTable::ModifyStyle(const char *pszName,
-                                 const char * pszStyleString)
+GBool OGRStyleTable::ModifyStyle( const char *pszName,
+                                  const char * pszStyleString )
 {
-    if (pszName == NULL || pszStyleString == NULL)
+    if( pszName == NULL || pszStyleString == NULL )
       return FALSE;
 
     RemoveStyle(pszName);
     return AddStyle(pszName, pszStyleString);
-
 }
 
 /****************************************************************************/
@@ -1016,15 +995,15 @@ GBool OGRStyleTable::ModifyStyle(const char *pszName,
  * @return TRUE on success, FALSE on error
  */
 
-GBool OGRStyleTable::SaveStyleTable(const char *pszFilename)
+GBool OGRStyleTable::SaveStyleTable( const char *pszFilename )
 {
-    if (pszFilename == NULL)
+    if( pszFilename == NULL )
       return FALSE;
 
-    if (CSLSave(m_papszStyleTable,pszFilename) == 0)
+    if( CSLSave(m_papszStyleTable, pszFilename) == 0 )
       return FALSE;
-    else
-      return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -1048,7 +1027,8 @@ int OGR_STBL_SaveStyleTable( OGRStyleTableH hStyleTable,
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_SaveStyleTable", FALSE );
     VALIDATE_POINTER1( pszFilename, "OGR_STBL_SaveStyleTable", FALSE );
 
-    return ((OGRStyleTable *) hStyleTable)->SaveStyleTable( pszFilename );
+    return reinterpret_cast<OGRStyleTable *>(hStyleTable)->
+        SaveStyleTable( pszFilename );
 }
 
 /****************************************************************************/
@@ -1066,19 +1046,16 @@ int OGR_STBL_SaveStyleTable( OGRStyleTableH hStyleTable,
  * @return TRUE on success, FALSE on error
  */
 
-GBool OGRStyleTable::LoadStyleTable(const char *pszFilename)
+GBool OGRStyleTable::LoadStyleTable( const char *pszFilename )
 {
-    if (pszFilename == NULL)
+    if( pszFilename == NULL )
       return FALSE;
 
     CSLDestroy(m_papszStyleTable);
 
     m_papszStyleTable = CSLLoad(pszFilename);
 
-    if (m_papszStyleTable == NULL)
-      return FALSE;
-    else
-      return TRUE;
+    return m_papszStyleTable != NULL;
 }
 
 /************************************************************************/
@@ -1102,7 +1079,8 @@ int OGR_STBL_LoadStyleTable( OGRStyleTableH hStyleTable,
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_LoadStyleTable", FALSE );
     VALIDATE_POINTER1( pszFilename, "OGR_STBL_LoadStyleTable", FALSE );
 
-    return ((OGRStyleTable *) hStyleTable)->LoadStyleTable( pszFilename );
+    return reinterpret_cast<OGRStyleTable *>(hStyleTable)->
+        LoadStyleTable( pszFilename );
 }
 
 /****************************************************************************/
@@ -1122,21 +1100,18 @@ int OGR_STBL_LoadStyleTable( OGRStyleTableH hStyleTable,
 
 const char *OGRStyleTable::Find(const char *pszName)
 {
-    const char *pszDash = NULL;
-    const char *pszOutput = NULL;
+    const int nPos = IsExist(pszName);
+    if( nPos == -1 )
+        return NULL;
 
-    int nPos;
-    if ((nPos = IsExist(pszName)) != -1)
-    {
+    const char *pszOutput = CSLGetField(m_papszStyleTable, nPos);
 
-        pszOutput = CSLGetField(m_papszStyleTable,nPos);
+    const char *pszDash = strstr(pszOutput, ":");
 
-        pszDash = strstr(pszOutput,":");
+    if( pszDash == NULL )
+        return NULL;
 
-        if (pszDash)
-          return &pszDash[1];
-    }
-    return NULL;
+    return &pszDash[1];
 }
 
 /************************************************************************/
@@ -1159,7 +1134,7 @@ const char *OGR_STBL_Find( OGRStyleTableH hStyleTable, const char *pszName )
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_Find", NULL );
     VALIDATE_POINTER1( pszName, "OGR_STBL_Find", NULL );
 
-    return ((OGRStyleTable *) hStyleTable)->Find( pszName );
+    return reinterpret_cast<OGRStyleTable *>(hStyleTable)->Find(pszName);
 }
 
 /****************************************************************************/
@@ -1174,19 +1149,19 @@ const char *OGR_STBL_Find( OGRStyleTableH hStyleTable, const char *pszName )
  *
  */
 
-void OGRStyleTable::Print(FILE *fpOut)
+void OGRStyleTable::Print( FILE *fpOut )
 {
 
-    CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut,"#OFS-Version: 1.0\n"));
-    CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut,"#StyleField: style\n"));
-    if (m_papszStyleTable)
+    CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "#OFS-Version: 1.0\n"));
+    CPL_IGNORE_RET_VAL(VSIFPrintf(fpOut, "#StyleField: style\n"));
+    if( m_papszStyleTable )
     {
-        CSLPrint(m_papszStyleTable,fpOut);
+        CSLPrint(m_papszStyleTable, fpOut);
     }
 }
 
 /****************************************************************************/
-/*             int OGRStyleTable::IsExist(const char *pszName)            */
+/*             int OGRStyleTable::IsExist(const char *pszName)              */
 /*                                                                          */
 /*   return a index of the style in the table otherwise return -1           */
 /****************************************************************************/
@@ -1199,21 +1174,17 @@ void OGRStyleTable::Print(FILE *fpOut)
  * @return The index of the style if found, -1 if not found or error.
  */
 
-int OGRStyleTable::IsExist(const char *pszName)
+int OGRStyleTable::IsExist( const char *pszName )
 {
-    int i;
-    int nCount;
-    const char *pszNewString;
-
-    if (pszName == NULL)
+    if( pszName == NULL )
       return -1;
 
-    nCount = CSLCount(m_papszStyleTable);
-    pszNewString = CPLSPrintf("%s:",pszName);
+    const int nCount = CSLCount(m_papszStyleTable);
+    const char *pszNewString = CPLSPrintf("%s:", pszName);
 
-    for (i=0;i<nCount;i++)
+    for( int i = 0; i < nCount; i++ )
     {
-        if (strstr(m_papszStyleTable[i],pszNewString) != NULL)
+        if( strstr(m_papszStyleTable[i], pszNewString) != NULL )
         {
             return i;
         }
@@ -1249,6 +1220,7 @@ OGRStyleTable *OGRStyleTable::Clone()
 /*                            ResetStyleStringReading()                 */
 /************************************************************************/
 
+/** Reset the next style pointer to 0 */
 void OGRStyleTable::ResetStyleStringReading()
 
 {
@@ -1273,35 +1245,36 @@ void OGR_STBL_ResetStyleStringReading( OGRStyleTableH hStyleTable )
 {
     VALIDATE_POINTER0( hStyleTable, "OGR_STBL_ResetStyleStringReading" );
 
-    ((OGRStyleTable *) hStyleTable)->ResetStyleStringReading();
+    reinterpret_cast<OGRStyleTable *>(hStyleTable)->ResetStyleStringReading();
 }
 
 /************************************************************************/
 /*                           GetNextStyle()                             */
 /************************************************************************/
 
+/**
+ * \brief Get the next style string from the table.
+ *
+ * @return the next style string or NULL on error.
+ */
+
 const char *OGRStyleTable::GetNextStyle()
 {
-    const char *pszDash = NULL;
-    const char *pszOutput = NULL;
-
     while( iNextStyle < CSLCount(m_papszStyleTable) )
     {
-
-        if ( NULL == (pszOutput = CSLGetField(m_papszStyleTable,iNextStyle++)))
+        const char *pszOutput = CSLGetField(m_papszStyleTable, iNextStyle++);
+        if( pszOutput == NULL )
             continue;
 
-        pszDash = strstr(pszOutput,":");
-
-        size_t nColon;
+        const char *pszDash = strstr(pszOutput, ":");
 
         osLastRequestedStyleName = pszOutput;
-        nColon = osLastRequestedStyleName.find( ':' );
+        const size_t nColon = osLastRequestedStyleName.find( ':' );
         if( nColon != std::string::npos )
             osLastRequestedStyleName =
-                osLastRequestedStyleName.substr(0,nColon);
+                osLastRequestedStyleName.substr(0, nColon);
 
-        if (pszDash)
+        if( pszDash )
             return pszDash + 1;
     }
     return NULL;
@@ -1325,13 +1298,20 @@ const char *OGR_STBL_GetNextStyle( OGRStyleTableH hStyleTable)
 {
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_GetNextStyle", NULL );
 
-    return ((OGRStyleTable *) hStyleTable)->GetNextStyle();
+    return reinterpret_cast<OGRStyleTable *>(hStyleTable)->GetNextStyle();
 }
 
 /************************************************************************/
 /*                           GetLastStyleName()                         */
 /************************************************************************/
 
+/**
+ * Get the style name of the last style string fetched with
+ * OGR_STBL_GetNextStyle.
+ *
+ * @return the Name of the last style string or NULL on error.
+ */
+
 const char *OGRStyleTable::GetLastStyleName()
 {
     return osLastRequestedStyleName;
@@ -1356,22 +1336,23 @@ const char *OGR_STBL_GetLastStyleName( OGRStyleTableH hStyleTable)
 {
     VALIDATE_POINTER1( hStyleTable, "OGR_STBL_GetLastStyleName", NULL );
 
-    return ((OGRStyleTable *) hStyleTable)->GetLastStyleName();
+    return reinterpret_cast<OGRStyleTable *>(hStyleTable)->GetLastStyleName();
 }
 
-
 /****************************************************************************/
 /*                          OGRStyleTool::OGRStyleTool()                    */
 /*                                                                          */
 /****************************************************************************/
-OGRStyleTool::OGRStyleTool(OGRSTClassId eClassId)
+
+/** Constructor */
+OGRStyleTool::OGRStyleTool( OGRSTClassId eClassId ) :
+    m_bModified(FALSE),
+    m_bParsed(FALSE),
+    m_dfScale(1.0),
+    m_eUnit(OGRSTUMM),
+    m_eClassId(eClassId),
+    m_pszStyleString(NULL)
 {
-    m_eClassId = eClassId;
-    m_dfScale = 1.0;
-    m_eUnit = OGRSTUMM;
-    m_pszStyleString = NULL;
-    m_bModified = FALSE;
-    m_bParsed = FALSE;
 }
 
 /************************************************************************/
@@ -1395,13 +1376,13 @@ OGRStyleToolH OGR_ST_Create( OGRSTClassId eClassId )
     switch( eClassId )
     {
       case OGRSTCPen:
-        return (OGRStyleToolH) new OGRStylePen();
+        return reinterpret_cast<OGRStyleToolH>(new OGRStylePen());
       case OGRSTCBrush:
-        return (OGRStyleToolH) new OGRStyleBrush();
+        return reinterpret_cast<OGRStyleToolH>(new OGRStyleBrush());
       case OGRSTCSymbol:
-        return (OGRStyleToolH) new OGRStyleSymbol();
+        return reinterpret_cast<OGRStyleToolH>(new OGRStyleSymbol());
       case OGRSTCLabel:
-        return (OGRStyleToolH) new OGRStyleLabel();
+        return reinterpret_cast<OGRStyleToolH>(new OGRStyleLabel());
       default:
         return NULL;
     }
@@ -1428,38 +1409,44 @@ OGRStyleTool::~OGRStyleTool()
 void OGR_ST_Destroy( OGRStyleToolH hST )
 
 {
-    delete (OGRStyleTool *) hST;
+    delete reinterpret_cast<OGRStyleTool *>(hST);
 }
 
-
 /****************************************************************************/
 /*      void OGRStyleTool::SetStyleString(const char *pszStyleString)       */
 /*                                                                          */
 /****************************************************************************/
-void OGRStyleTool::SetStyleString(const char *pszStyleString)
+
+/** Undocumented
+ * @param pszStyleString undocumented.
+ */
+void OGRStyleTool::SetStyleString( const char *pszStyleString )
 {
     m_pszStyleString = CPLStrdup(pszStyleString);
 }
 
 /****************************************************************************/
-/*const char *OGRStyleTool::GetStyleString( OGRStyleParamId *pasStyleParam ,*/
+/*const char *OGRStyleTool::GetStyleString( OGRStyleParamId *pasStyleParam, */
 /*                          OGRStyleValue *pasStyleValue, int nSize)        */
 /*                                                                          */
 /****************************************************************************/
-const char *OGRStyleTool::GetStyleString(const OGRStyleParamId *pasStyleParam,
-                                         OGRStyleValue *pasStyleValue,
-                                         int nSize)
+
+/** Undocumented
+ * @param pasStyleParam undocumented.
+ * @param pasStyleValue undocumented.
+ * @param nSize undocumented.
+ * @return undocumented.
+ */
+const char *OGRStyleTool::GetStyleString( const OGRStyleParamId *pasStyleParam,
+                                          OGRStyleValue *pasStyleValue,
+                                          int nSize )
 {
-    if (IsStyleModified())
+    if( IsStyleModified() )
     {
-        int i;
-        GBool bFound;
-        const char *pszClass;
-        CPLString osCurrent;
-
         CPLFree(m_pszStyleString);
 
-        switch (GetType())
+        const char *pszClass = NULL;
+        switch( GetType() )
         {
           case OGRSTCPen:
             pszClass = "PEN(";
@@ -1477,36 +1464,37 @@ const char *OGRStyleTool::GetStyleString(const OGRStyleParamId *pasStyleParam,
             pszClass = "UNKNOWN(";
         }
 
-        osCurrent = pszClass;
+        CPLString osCurrent = pszClass;
 
-        bFound = FALSE;
-        for (i=0;i< nSize;i++)
+        bool bFound = false;
+        for( int i = 0; i < nSize; i++ )
         {
-            if (pasStyleValue[i].bValid == FALSE)
-              continue;
+            if( !pasStyleValue[i].bValid )
+                continue;
 
-            if (bFound)
-              osCurrent += ",";
-            bFound = TRUE;
+            if( bFound )
+                osCurrent += ",";
+            bFound = true;
 
             osCurrent += pasStyleParam[i].pszToken;
-            switch (pasStyleParam[i].eType)
+            switch( pasStyleParam[i].eType )
             {
               case OGRSTypeString:
                 osCurrent += ":";
                 osCurrent += pasStyleValue[i].pszValue;
                 break;
               case OGRSTypeDouble:
-                osCurrent += CPLString().Printf(":%f",pasStyleValue[i].dfValue);
+                osCurrent +=
+                    CPLString().Printf(":%f", pasStyleValue[i].dfValue);
                 break;
               case OGRSTypeInteger:
-                osCurrent += CPLString().Printf(":%d",pasStyleValue[i].nValue);
+                osCurrent += CPLString().Printf(":%d", pasStyleValue[i].nValue);
                 break;
               default:
                 break;
             }
-            if (pasStyleParam[i].bGeoref)
-              switch (pasStyleValue[i].eUnit)
+            if( pasStyleParam[i].bGeoref )
+              switch( pasStyleValue[i].eUnit )
               {
                 case OGRSTUGround:
                   osCurrent += "g";
@@ -1542,24 +1530,44 @@ const char *OGRStyleTool::GetStyleString(const OGRStyleParamId *pasStyleParam,
 /************************************************************************/
 /*                          GetRGBFromString()                          */
 /************************************************************************/
-
-GBool OGRStyleTool::GetRGBFromString(const char *pszColor, int &nRed,
-                                     int &nGreen ,int & nBlue,
-                                     int &nTransparance)
+/**
+ * \brief Return the r,g,b,a components of a color encoded in \#RRGGBB[AA]
+ * format.
+ *
+ * Maps to OGRStyleTool::GetRGBFromString().
+ *
+ * @param pszColor the color to parse
+ * @param nRed reference to an int in which the red value will be returned.
+ * @param nGreen reference to an int in which the green value will be returned.
+ * @param nBlue reference to an int in which the blue value will be returned.
+ * @param nTransparance reference to an int in which the (optional) alpha value
+ * will be returned.
+ *
+ * @return TRUE if the color could be successfully parsed, or FALSE in case of
+ * errors.
+ */
+GBool OGRStyleTool::GetRGBFromString( const char *pszColor, int &nRed,
+                                      int &nGreen, int &nBlue,
+                                      int &nTransparance )
 {
-   int nCount=0;
+   int nCount = 0;
 
    nTransparance = 255;
 
    // FIXME: should we really use sscanf here?
-   if (pszColor)
-       nCount  = sscanf(pszColor,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue,
-                        &nTransparance);
-
-   if (nCount >=3)
-     return TRUE;
-   else
-     return FALSE;
+   unsigned int unRed = 0;
+   unsigned int unGreen = 0;
+   unsigned int unBlue = 0;
+   unsigned int unTransparance = 0;
+   if( pszColor )
+       nCount = sscanf(pszColor, "#%2x%2x%2x%2x",
+                       &unRed, &unGreen, &unBlue, &unTransparance);
+   nRed = static_cast<int>(unRed);
+   nGreen = static_cast<int>(unGreen);
+   nBlue = static_cast<int>(unBlue);
+   if( nCount == 4 )
+        nTransparance = static_cast<int>(unTransparance);
+   return nCount >= 3;
 }
 
 /************************************************************************/
@@ -1570,34 +1578,46 @@ GBool OGRStyleTool::GetRGBFromString(const char *pszColor, int &nRed,
 /*      sensitive)                                                      */
 /************************************************************************/
 
-int OGRStyleTool::GetSpecificId(const char *pszId, const char *pszWanted)
+/** Undocumented
+ * @param pszId Undocumented
+ * @param pszWanted Undocumented
+ * @return Undocumented
+ */
+int OGRStyleTool::GetSpecificId( const char *pszId, const char *pszWanted )
 {
     const char *pszRealWanted = pszWanted;
-    const char *pszFound;
-    int nValue  = -1;
 
-    if (pszWanted == NULL || strlen(pszWanted) == 0)
-      pszRealWanted = "ogr-pen";
+    if( pszWanted == NULL || strlen(pszWanted) == 0 )
+        pszRealWanted = "ogr-pen";
 
-    if (pszId == NULL)
-      return -1;
+    if( pszId == NULL )
+        return -1;
 
-    if ((pszFound = strstr(pszId, pszRealWanted)) != NULL)
+    int nValue = -1;
+    const char *pszFound = strstr(pszId, pszRealWanted);
+    if( pszFound != NULL )
     {
-        // We found the string, it could be no value after it, use default one
+        // We found the string, it could be no value after it, use default one.
         nValue = 0;
 
-        if (pszFound[strlen(pszRealWanted)] == '-' )
-          nValue =atoi(&pszFound[strlen(pszRealWanted)+1]);
+        if( pszFound[strlen(pszRealWanted)] == '-' )
+            nValue =atoi(&pszFound[strlen(pszRealWanted)+1]);
     }
 
     return nValue;
-
 }
 
 /************************************************************************/
 /*                              GetType()                               */
 /************************************************************************/
+
+/**
+ * \brief Determine type of Style Tool
+ *
+ * @return the style tool type, one of OGRSTCPen (1), OGRSTCBrush (2),
+ * OGRSTCSymbol (3) or OGRSTCLabel (4). Returns OGRSTCNone (0) if the
+ * OGRStyleToolH is invalid.
+ */
 OGRSTClassId OGRStyleTool::GetType()
 {
     return m_eClassId;
@@ -1620,13 +1640,20 @@ OGRSTClassId OGR_ST_GetType( OGRStyleToolH hST )
 
 {
     VALIDATE_POINTER1( hST, "OGR_ST_GetType", OGRSTCNone );
-    return ((OGRStyleTool *) hST)->GetType();
+    return reinterpret_cast<OGRStyleTool *>(hST)->GetType();
 }
 
-
 /************************************************************************/
 /*                           OGR_ST_GetUnit()                           */
 /************************************************************************/
+
+/**
+ * \fn OGRStyleTool::GetUnit()
+ * \brief Get Style Tool units
+ *
+ * @return the style tool units.
+ */
+
 /**
  * \brief Get Style Tool units
  *
@@ -1639,17 +1666,24 @@ OGRSTUnitId OGR_ST_GetUnit( OGRStyleToolH hST )
 
 {
     VALIDATE_POINTER1( hST, "OGR_ST_GetUnit", OGRSTUGround );
-    return ((OGRStyleTool *) hST)->GetUnit();
+    return reinterpret_cast<OGRStyleTool *>(hST)->GetUnit();
 }
 
-
 /************************************************************************/
 /*                              SetUnit()                               */
 /************************************************************************/
-void OGRStyleTool::SetUnit(OGRSTUnitId eUnit,double dfScale)
+
+/**
+ * \brief Set Style Tool units
+ *
+ * @param eUnit the new unit.
+ * @param dfGroundPaperScale ground to paper scale factor.
+ *
+ */
+void OGRStyleTool::SetUnit( OGRSTUnitId eUnit, double dfGroundPaperScale )
 {
-    m_dfScale = dfScale;
     m_eUnit = eUnit;
+    m_dfScale = dfGroundPaperScale;
 }
 
 /************************************************************************/
@@ -1671,59 +1705,59 @@ void OGR_ST_SetUnit( OGRStyleToolH hST, OGRSTUnitId eUnit,
 
 {
     VALIDATE_POINTER0( hST, "OGR_ST_SetUnit" );
-    ((OGRStyleTool *) hST)->SetUnit(eUnit, dfGroundPaperScale);
+    reinterpret_cast<OGRStyleTool *>(hST)->SetUnit(eUnit, dfGroundPaperScale);
 }
 
 /************************************************************************/
 /*                               Parse()                                */
 /************************************************************************/
-GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
-                          OGRStyleValue *pasValue,
-                          int nCount)
-{
-    char **papszToken; // Token to contains StyleString Type and content
-    char **papszToken2; // Token that will contains StyleString elements
-
 
-    OGRSTUnitId  eLastUnit;
-
-    if (IsStyleParsed() == TRUE)
-      return TRUE;
+//! @cond Doxygen_Suppress
+GBool OGRStyleTool::Parse( const OGRStyleParamId *pasStyle,
+                           OGRStyleValue *pasValue,
+                           int nCount )
+{
+    if( IsStyleParsed() )
+        return TRUE;
 
     StyleParsed();
 
-    if (m_pszStyleString == NULL)
-      return FALSE;
+    if( m_pszStyleString == NULL )
+        return FALSE;
 
+    // Token to contains StyleString Type and content.
     // Tokenize the String to get the Type and the content
     // Example: Type(elem1:val2,elem2:val2)
-    papszToken  = CSLTokenizeString2(m_pszStyleString,"()",
-                                     CSLT_HONOURSTRINGS
-                                     | CSLT_PRESERVEQUOTES
-                                     | CSLT_PRESERVEESCAPES );
+    char **papszToken =
+        CSLTokenizeString2(m_pszStyleString, "()",
+                           CSLT_HONOURSTRINGS
+                           | CSLT_PRESERVEQUOTES
+                           | CSLT_PRESERVEESCAPES );
 
-    if (CSLCount(papszToken) > 2 || CSLCount(papszToken) == 0)
+    if( CSLCount(papszToken) > 2 || CSLCount(papszToken) == 0 )
     {
         CSLDestroy( papszToken );
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Error in the format of the StyleTool %s\n",m_pszStyleString);
+                 "Error in the format of the StyleTool %s", m_pszStyleString);
         return FALSE;
     }
 
+    // Token that will contains StyleString elements.
     // Tokenize the content of the StyleString to get paired components in it.
-    papszToken2 = CSLTokenizeString2( papszToken[1], ",",
-                                      CSLT_HONOURSTRINGS
-                                      | CSLT_PRESERVEQUOTES
-                                      | CSLT_PRESERVEESCAPES );
+    char **papszToken2 =
+        CSLTokenizeString2( papszToken[1], ",",
+                            CSLT_HONOURSTRINGS
+                            | CSLT_PRESERVEQUOTES
+                            | CSLT_PRESERVEESCAPES );
 
     // Valid that we have the right StyleString for this feature type.
-    switch (GetType())
+    switch( GetType() )
     {
       case OGRSTCPen:
-        if (!EQUAL(papszToken[0],"PEN"))
+        if( !EQUAL(papszToken[0],"PEN") )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Error in the Type of StyleTool %s should be a PEN Type\n",
+                     "Error in the Type of StyleTool %s should be a PEN Type",
                      papszToken[0]);
             CSLDestroy( papszToken );
             CSLDestroy( papszToken2 );
@@ -1731,10 +1765,10 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
         }
         break;
       case OGRSTCBrush:
-        if (!EQUAL(papszToken[0],"BRUSH"))
+        if( !EQUAL(papszToken[0], "BRUSH") )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Error in the Type of StyleTool %s should be a BRUSH Type\n",
+                     "Error in the Type of StyleTool %s should be a BRUSH Type",
                      papszToken[0]);
             CSLDestroy( papszToken );
             CSLDestroy( papszToken2 );
@@ -1742,10 +1776,11 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
         }
         break;
       case OGRSTCSymbol:
-        if (!EQUAL(papszToken[0],"SYMBOL"))
+        if( !EQUAL(papszToken[0], "SYMBOL") )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Error in the Type of StyleTool %s should be a SYMBOL Type\n",
+                     "Error in the Type of StyleTool %s should be "
+                     "a SYMBOL Type",
                      papszToken[0]);
             CSLDestroy( papszToken );
             CSLDestroy( papszToken2 );
@@ -1753,10 +1788,10 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
         }
         break;
       case OGRSTCLabel:
-        if (!EQUAL(papszToken[0],"LABEL"))
+        if( !EQUAL(papszToken[0], "LABEL") )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Error in the Type of StyleTool %s should be a LABEL Type\n",
+                     "Error in the Type of StyleTool %s should be a LABEL Type",
                      papszToken[0]);
             CSLDestroy( papszToken );
             CSLDestroy( papszToken2 );
@@ -1765,7 +1800,7 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
         break;
       default:
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Error in the Type of StyleTool, Type undetermined\n");
+                 "Error in the Type of StyleTool, Type undetermined");
         CSLDestroy( papszToken );
         CSLDestroy( papszToken2 );
         return FALSE;
@@ -1793,23 +1828,23 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
     ////////////////////////////////////////////////////////////////////////
 
     // Save Scale and output Units because the parsing code will alter
-    // the values
-    eLastUnit = m_eUnit;
-    double  dSavedScale = m_dfScale;
-    int     i, nElements = CSLCount(papszToken2);
+    // the values.
+    OGRSTUnitId eLastUnit = m_eUnit;
+    double dSavedScale = m_dfScale;
+    const int nElements = CSLCount(papszToken2);
 
-    for ( i = 0; i < nElements; i++ )
+    for( int i = 0; i < nElements; i++ )
     {
-        char    **papszStylePair =
+        char **papszStylePair =
             CSLTokenizeString2( papszToken2[i], ":",
                                 CSLT_HONOURSTRINGS
                                 | CSLT_STRIPLEADSPACES
                                 | CSLT_STRIPENDSPACES
                                 | CSLT_ALLOWEMPTYTOKENS );
 
-        int     j, nTokens = CSLCount(papszStylePair);
+        const int nTokens = CSLCount(papszStylePair);
 
-        if ( nTokens < 1 || nTokens > 2 )
+        if( nTokens < 1 || nTokens > 2 )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Error in the StyleTool String %s", m_pszStyleString );
@@ -1820,19 +1855,20 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
             continue;
         }
 
-        for ( j = 0; j < nCount; j++ )
+        for( int j = 0; j < nCount; j++ )
         {
-            if ( EQUAL(pasStyle[j].pszToken, papszStylePair[0]) )
+            if( EQUAL(pasStyle[j].pszToken, papszStylePair[0]) )
             {
-                if (papszStylePair[1] != NULL && pasStyle[j].bGeoref == TRUE)
+                if( papszStylePair[1] != NULL && pasStyle[j].bGeoref == TRUE )
                     SetInternalInputUnitFromParam(papszStylePair[1]);
 
                 // Set either the actual value of style parameter or "1"
                 // for boolean parameters which do not have values.
                 // "1" means that boolean parameter is present in the style
                 // string.
-                OGRStyleTool::SetParamStr( pasStyle[j], pasValue[j],
-                                    (papszStylePair[1] != NULL) ? papszStylePair[1] : "1" );
+                OGRStyleTool::SetParamStr(
+                    pasStyle[j], pasValue[j],
+                    papszStylePair[1] != NULL ? papszStylePair[1] : "1" );
 
                 break;
             }
@@ -1849,55 +1885,55 @@ GBool OGRStyleTool::Parse(const OGRStyleParamId *pasStyle,
 
     return TRUE;
 }
+//! @endcond
 
 /************************************************************************/
 /*                   SetInternalInputUnitFromParam()                    */
 /************************************************************************/
 
-void OGRStyleTool::SetInternalInputUnitFromParam(char *pszString)
+//! @cond Doxygen_Suppress
+void OGRStyleTool::SetInternalInputUnitFromParam( char *pszString )
 {
+    if( pszString == NULL )
+        return;
 
-    char *pszUnit;
-
-    if (pszString == NULL)
-      return;
-    pszUnit = strstr(pszString,"g");
-    if (pszUnit)
+    char *pszUnit = strstr(pszString, "g");
+    if( pszUnit )
     {
         SetUnit(OGRSTUGround);
         pszUnit[0]= '\0';
         return;
     }
-    pszUnit = strstr(pszString,"px");
-    if (pszUnit)
+    pszUnit = strstr(pszString, "px");
+    if( pszUnit )
     {
         SetUnit(OGRSTUPixel);
         pszUnit[0]= '\0';
         return;
     }
-    pszUnit = strstr(pszString,"pt");
-    if (pszUnit)
+    pszUnit = strstr(pszString, "pt");
+    if( pszUnit )
     {
         SetUnit(OGRSTUPoints);
         pszUnit[0]= '\0';
         return;
     }
-    pszUnit = strstr(pszString,"mm");
-    if (pszUnit)
+    pszUnit = strstr(pszString, "mm");
+    if( pszUnit )
     {
         SetUnit(OGRSTUMM);
         pszUnit[0]= '\0';
         return;
     }
-    pszUnit = strstr(pszString,"cm");
-    if (pszUnit)
+    pszUnit = strstr(pszString, "cm");
+    if( pszUnit )
     {
         SetUnit(OGRSTUCM);
         pszUnit[0]= '\0';
         return;
     }
-    pszUnit = strstr(pszString,"in");
-    if (pszUnit)
+    pszUnit = strstr(pszString, "in");
+    if( pszUnit )
     {
         SetUnit(OGRSTUInches);
         pszUnit[0]= '\0';
@@ -1910,17 +1946,16 @@ void OGRStyleTool::SetInternalInputUnitFromParam(char *pszString)
 /************************************************************************/
 /*                          ComputeWithUnit()                           */
 /************************************************************************/
-double OGRStyleTool::ComputeWithUnit(double dfValue, OGRSTUnitId eInputUnit)
+double OGRStyleTool::ComputeWithUnit( double dfValue, OGRSTUnitId eInputUnit )
 {
     OGRSTUnitId eOutputUnit = GetUnit();
 
-    double dfNewValue = dfValue;        // dfValue in  Meter;
-
+    double dfNewValue = dfValue;  // dfValue in meters;
 
-    if (eOutputUnit == eInputUnit)
-      return dfValue;
+    if( eOutputUnit == eInputUnit )
+        return dfValue;
 
-    switch (eInputUnit)
+    switch( eInputUnit )
     {
       case OGRSTUGround:
         dfNewValue = dfValue / m_dfScale;
@@ -1941,19 +1976,19 @@ double OGRStyleTool::ComputeWithUnit(double dfValue, OGRSTUnitId eInputUnit)
         dfNewValue = dfValue / 39.37;
         break;
       default:
-        break;    //imp
+        break;  // imp.
     }
 
-    switch (eOutputUnit)
+    switch( eOutputUnit )
     {
       case OGRSTUGround:
         dfNewValue *= m_dfScale;
         break;
       case OGRSTUPixel:
-        dfNewValue *= (72.0 * 39.37);
+        dfNewValue *= 72.0 * 39.37;
         break;
       case OGRSTUPoints:
-        dfNewValue *= (72.0 * 39.37);
+        dfNewValue *= 72.0 * 39.37;
         break;
       case OGRSTUMM:
         dfNewValue *= 1000.0;
@@ -1965,7 +2000,7 @@ double OGRStyleTool::ComputeWithUnit(double dfValue, OGRSTUnitId eInputUnit)
         dfNewValue *= 39.37;
         break;
       default:
-        break;  // imp
+        break;  // imp.
     }
     return dfNewValue;
 }
@@ -1973,20 +2008,28 @@ double OGRStyleTool::ComputeWithUnit(double dfValue, OGRSTUnitId eInputUnit)
 /************************************************************************/
 /*                          ComputeWithUnit()                           */
 /************************************************************************/
-int   OGRStyleTool::ComputeWithUnit(int nValue, OGRSTUnitId eUnit)
+int OGRStyleTool::ComputeWithUnit( int nValue, OGRSTUnitId eUnit )
 {
-    return (int) ComputeWithUnit((double )nValue, eUnit);
+    return
+        static_cast<int>(ComputeWithUnit(static_cast<double>(nValue), eUnit));
 }
+//! @endcond
 
 /************************************************************************/
 /*                            GetParamStr()                             */
 /************************************************************************/
-const char *OGRStyleTool::GetParamStr(const OGRStyleParamId &sStyleParam ,
-                                      OGRStyleValue &sStyleValue,
-                                      GBool &bValueIsNull)
-{
 
-    if (!Parse())
+/** Undocumented
+ * @param sStyleParam undocumented.
+ * @param sStyleValue undocumented.
+ * @param bValueIsNull undocumented.
+ * @return Undocumented.
+ */
+const char *OGRStyleTool::GetParamStr( const OGRStyleParamId &sStyleParam ,
+                                       OGRStyleValue &sStyleValue,
+                                       GBool &bValueIsNull )
+{
+    if( !Parse() )
     {
         bValueIsNull = TRUE;
         return NULL;
@@ -1994,30 +2037,29 @@ const char *OGRStyleTool::GetParamStr(const OGRStyleParamId &sStyleParam ,
 
     bValueIsNull = !sStyleValue.bValid;
 
-    if (bValueIsNull == TRUE)
-      return NULL;
+    if( bValueIsNull == TRUE )
+        return NULL;
 
-    switch (sStyleParam.eType)
+    switch( sStyleParam.eType )
     {
-
-        // if sStyleParam.bGeoref == TRUE , need to convert to output value;
+      // If sStyleParam.bGeoref == TRUE, need to convert to output value.
       case OGRSTypeString:
         return sStyleValue.pszValue;
       case OGRSTypeDouble:
-        if (sStyleParam.bGeoref)
-          return CPLSPrintf("%f",ComputeWithUnit(sStyleValue.dfValue,
-                                                 sStyleValue.eUnit));
+        if( sStyleParam.bGeoref )
+          return CPLSPrintf("%f", ComputeWithUnit(sStyleValue.dfValue,
+                                                  sStyleValue.eUnit));
         else
-          return CPLSPrintf("%f",sStyleValue.dfValue);
+          return CPLSPrintf("%f", sStyleValue.dfValue);
 
       case OGRSTypeInteger:
-        if (sStyleParam.bGeoref)
-          return CPLSPrintf("%d",ComputeWithUnit(sStyleValue.nValue,
-                                                 sStyleValue.eUnit));
+        if( sStyleParam.bGeoref )
+          return CPLSPrintf("%d", ComputeWithUnit(sStyleValue.nValue,
+                                                  sStyleValue.eUnit));
         else
-          return CPLSPrintf("%d",sStyleValue.nValue);
+          return CPLSPrintf("%d", sStyleValue.nValue);
       case OGRSTypeBoolean:
-        return CPLSPrintf("%d",sStyleValue.nValue);
+        return CPLSPrintf("%d", sStyleValue.nValue);
       default:
         bValueIsNull = TRUE;
         return NULL;
@@ -2030,11 +2072,19 @@ const char *OGRStyleTool::GetParamStr(const OGRStyleParamId &sStyleParam ,
 /*                               GBool &bValueIsNull)                       */
 /*                                                                          */
 /****************************************************************************/
-int OGRStyleTool::GetParamNum(const OGRStyleParamId &sStyleParam ,
-                              OGRStyleValue &sStyleValue,
-                              GBool &bValueIsNull)
+
+/** Undocumented
+ * @param sStyleParam undocumented.
+ * @param sStyleValue undocumented.
+ * @param bValueIsNull undocumented.
+ * @return Undocumented.
+ */
+int OGRStyleTool::GetParamNum( const OGRStyleParamId &sStyleParam ,
+                               OGRStyleValue &sStyleValue,
+                               GBool &bValueIsNull )
 {
-    return (int)GetParamDbl(sStyleParam,sStyleValue,bValueIsNull);
+    return
+        static_cast<int>(GetParamDbl(sStyleParam, sStyleValue, bValueIsNull));
 }
 
 /****************************************************************************/
@@ -2043,47 +2093,55 @@ int OGRStyleTool::GetParamNum(const OGRStyleParamId &sStyleParam ,
 /*                               GBool &bValueIsNull)                       */
 /*                                                                          */
 /****************************************************************************/
-double OGRStyleTool::GetParamDbl(const OGRStyleParamId &sStyleParam ,
-                                 OGRStyleValue &sStyleValue,
-                                 GBool &bValueIsNull)
+
+/** Undocumented
+ * @param sStyleParam undocumented.
+ * @param sStyleValue undocumented.
+ * @param bValueIsNull undocumented.
+ * @return Undocumented.
+ */
+double OGRStyleTool::GetParamDbl( const OGRStyleParamId &sStyleParam ,
+                                  OGRStyleValue &sStyleValue,
+                                  GBool &bValueIsNull )
 {
-    if (!Parse())
+    if( !Parse() )
     {
         bValueIsNull = TRUE;
-        return 0;
+        return 0.0;
     }
 
     bValueIsNull = !sStyleValue.bValid;
 
-    if (bValueIsNull == TRUE)
-      return 0;
+    if( bValueIsNull == TRUE )
+        return 0.0;
 
-    switch (sStyleParam.eType)
+    switch( sStyleParam.eType )
     {
-        // if sStyleParam.bGeoref == TRUE , need to convert to output value;
+      // if sStyleParam.bGeoref == TRUE, need to convert to output value.
       case OGRSTypeString:
-        if (sStyleParam.bGeoref)
+        if( sStyleParam.bGeoref )
           return ComputeWithUnit(CPLAtof(sStyleValue.pszValue),
                                  sStyleValue.eUnit);
         else
           return CPLAtof(sStyleValue.pszValue);
       case OGRSTypeDouble:
-        if (sStyleParam.bGeoref)
+        if( sStyleParam.bGeoref )
           return ComputeWithUnit(sStyleValue.dfValue,
-                                      sStyleValue.eUnit);
+                                 sStyleValue.eUnit);
         else
           return sStyleValue.dfValue;
       case OGRSTypeInteger:
-        if (sStyleParam.bGeoref)
-          return (double)ComputeWithUnit(sStyleValue.nValue,
-                                         sStyleValue.eUnit);
+        if( sStyleParam.bGeoref )
+          return static_cast<double>(
+              ComputeWithUnit(sStyleValue.nValue,
+                              sStyleValue.eUnit));
         else
-          return (double)sStyleValue.nValue;
+          return static_cast<double>(sStyleValue.nValue);
       case OGRSTypeBoolean:
-        return (double)sStyleValue.nValue;
+        return static_cast<double>(sStyleValue.nValue);
       default:
         bValueIsNull = TRUE;
-        return 0;
+        return 0.0;
     }
 }
 
@@ -2093,17 +2151,23 @@ double OGRStyleTool::GetParamDbl(const OGRStyleParamId &sStyleParam ,
 /*                             const char *pszParamString)                  */
 /*                                                                          */
 /****************************************************************************/
-void OGRStyleTool::SetParamStr(const OGRStyleParamId &sStyleParam ,
-                               OGRStyleValue &sStyleValue,
-                               const char *pszParamString)
+
+/** Undocumented
+ * @param sStyleParam undocumented.
+ * @param sStyleValue undocumented.
+ * @param pszParamString undocumented.
+ */
+void OGRStyleTool::SetParamStr( const OGRStyleParamId &sStyleParam ,
+                                OGRStyleValue &sStyleValue,
+                                const char *pszParamString )
 {
     Parse();
     StyleModified();
     sStyleValue.bValid = TRUE;
     sStyleValue.eUnit = GetUnit();
-    switch (sStyleParam.eType)
+    switch( sStyleParam.eType )
     {
-        // if sStyleParam.bGeoref == TRUE , need to convert to output value;
+      // If sStyleParam.bGeoref == TRUE, need to convert to output value;
       case OGRSTypeString:
         sStyleValue.pszValue = CPLStrdup(pszParamString);
         break;
@@ -2112,7 +2176,7 @@ void OGRStyleTool::SetParamStr(const OGRStyleParamId &sStyleParam ,
         break;
       case OGRSTypeInteger:
       case OGRSTypeBoolean:
-        sStyleValue.nValue  = atoi(pszParamString);
+        sStyleValue.nValue = atoi(pszParamString);
         break;
       default:
         sStyleValue.bValid = FALSE;
@@ -2126,27 +2190,33 @@ void OGRStyleTool::SetParamStr(const OGRStyleParamId &sStyleParam ,
 /*                             int nParam)                                  */
 /*                                                                          */
 /****************************************************************************/
-void OGRStyleTool::SetParamNum(const OGRStyleParamId &sStyleParam ,
-                               OGRStyleValue &sStyleValue,
-                               int nParam)
+
+/** Undocumented
+ * @param sStyleParam undocumented.
+ * @param sStyleValue undocumented.
+ * @param nParam undocumented.
+ */
+void OGRStyleTool::SetParamNum( const OGRStyleParamId &sStyleParam ,
+                                OGRStyleValue &sStyleValue,
+                                int nParam )
 {
     Parse();
     StyleModified();
     sStyleValue.bValid = TRUE;
     sStyleValue.eUnit = GetUnit();
-    switch (sStyleParam.eType)
+    switch( sStyleParam.eType )
     {
 
-        // if sStyleParam.bGeoref == TRUE , need to convert to output value;
+      // If sStyleParam.bGeoref == TRUE, need to convert to output value;
       case OGRSTypeString:
-        sStyleValue.pszValue = CPLStrdup(CPLString().Printf("%d",nParam));
+        sStyleValue.pszValue = CPLStrdup(CPLString().Printf("%d", nParam));
         break;
       case OGRSTypeDouble:
-        sStyleValue.dfValue = (double)nParam;
+        sStyleValue.dfValue = static_cast<double>(nParam);
         break;
       case OGRSTypeInteger:
       case OGRSTypeBoolean:
-        sStyleValue.nValue  = nParam;
+        sStyleValue.nValue = nParam;
         break;
       default:
         sStyleValue.bValid = FALSE;
@@ -2160,26 +2230,32 @@ void OGRStyleTool::SetParamNum(const OGRStyleParamId &sStyleParam ,
 /*                             double dfParam)                              */
 /*                                                                          */
 /****************************************************************************/
-void OGRStyleTool::SetParamDbl(const OGRStyleParamId &sStyleParam ,
-                               OGRStyleValue &sStyleValue,
-                               double dfParam)
+
+/** Undocumented
+ * @param sStyleParam undocumented.
+ * @param sStyleValue undocumented.
+ * @param dfParam undocumented.
+ */
+void OGRStyleTool::SetParamDbl( const OGRStyleParamId &sStyleParam,
+                                OGRStyleValue &sStyleValue,
+                                double dfParam )
 {
     Parse();
     StyleModified();
     sStyleValue.bValid = TRUE;
     sStyleValue.eUnit = GetUnit();
-    switch (sStyleParam.eType)
+    switch( sStyleParam.eType )
     {
-        // if sStyleParam.bGeoref == TRUE , need to convert to output value;
+      // If sStyleParam.bGeoref == TRUE, need to convert to output value;
       case OGRSTypeString:
-        sStyleValue.pszValue = CPLStrdup(CPLString().Printf("%f",dfParam));
+        sStyleValue.pszValue = CPLStrdup(CPLString().Printf("%f", dfParam));
         break;
       case OGRSTypeDouble:
         sStyleValue.dfValue = dfParam;
         break;
       case OGRSTypeInteger:
       case OGRSTypeBoolean:
-        sStyleValue.nValue  = (int)dfParam;
+        sStyleValue.nValue = static_cast<int>(dfParam);
         break;
       default:
         sStyleValue.bValid = FALSE;
@@ -2205,33 +2281,34 @@ void OGRStyleTool::SetParamDbl(const OGRStyleParamId &sStyleParam ,
  * @return the parameter value as string and sets bValueIsNull.
  */
 
-const char *OGR_ST_GetParamStr( OGRStyleToolH hST, int eParam, int *bValueIsNull )
+const char *OGR_ST_GetParamStr( OGRStyleToolH hST, int eParam,
+                                int *bValueIsNull )
 {
-    GBool bIsNull = TRUE;
-    const char *pszVal = "";
-
     VALIDATE_POINTER1( hST, "OGR_ST_GetParamStr", "" );
     VALIDATE_POINTER1( bValueIsNull, "OGR_ST_GetParamStr", "" );
 
-    switch( ((OGRStyleTool *) hST)->GetType() )
+    GBool bIsNull = TRUE;
+    const char *pszVal = "";
+
+    switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
     {
-      case OGRSTCPen:
-        pszVal = ((OGRStylePen *) hST)->GetParamStr((OGRSTPenParam)eParam,
-                                                    bIsNull);
+    case OGRSTCPen:
+        pszVal = reinterpret_cast<OGRStylePen *>(hST)->
+            GetParamStr(static_cast<OGRSTPenParam>(eParam), bIsNull);
         break;
-      case OGRSTCBrush:
-        pszVal = ((OGRStyleBrush *) hST)->GetParamStr((OGRSTBrushParam)eParam,
-                                                      bIsNull);
+    case OGRSTCBrush:
+        pszVal = reinterpret_cast<OGRStyleBrush *>(hST)->
+            GetParamStr(static_cast<OGRSTBrushParam>(eParam), bIsNull);
         break;
-      case OGRSTCSymbol:
-        pszVal = ((OGRStyleSymbol *) hST)->GetParamStr((OGRSTSymbolParam)eParam,
-                                                       bIsNull);
+    case OGRSTCSymbol:
+        pszVal = reinterpret_cast<OGRStyleSymbol *>(hST)->
+            GetParamStr(static_cast<OGRSTSymbolParam>(eParam), bIsNull);
         break;
-      case OGRSTCLabel:
-        pszVal = ((OGRStyleLabel *) hST)->GetParamStr((OGRSTLabelParam)eParam,
-                                                      bIsNull);
+    case OGRSTCLabel:
+        pszVal = reinterpret_cast<OGRStyleLabel *>(hST)->
+            GetParamStr(static_cast<OGRSTLabelParam>(eParam), bIsNull);
         break;
-      default:
+    default:
         break;
     }
 
@@ -2259,31 +2336,31 @@ const char *OGR_ST_GetParamStr( OGRStyleToolH hST, int eParam, int *bValueIsNull
 
 int OGR_ST_GetParamNum( OGRStyleToolH hST, int eParam, int *bValueIsNull )
 {
-    GBool bIsNull = TRUE;
-    int nVal = 0;
-
     VALIDATE_POINTER1( hST, "OGR_ST_GetParamNum", 0 );
     VALIDATE_POINTER1( bValueIsNull, "OGR_ST_GetParamNum", 0 );
 
-    switch( ((OGRStyleTool *) hST)->GetType() )
+    GBool bIsNull = TRUE;
+    int nVal = 0;
+
+    switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
     {
-      case OGRSTCPen:
-        nVal = ((OGRStylePen *) hST)->GetParamNum((OGRSTPenParam)eParam,
-                                                    bIsNull);
+    case OGRSTCPen:
+        nVal = reinterpret_cast<OGRStylePen *>(hST)->
+            GetParamNum(static_cast<OGRSTPenParam>(eParam), bIsNull);
         break;
-      case OGRSTCBrush:
-        nVal = ((OGRStyleBrush *) hST)->GetParamNum((OGRSTBrushParam)eParam,
-                                                      bIsNull);
+    case OGRSTCBrush:
+        nVal = reinterpret_cast<OGRStyleBrush *>(hST)->
+            GetParamNum(static_cast<OGRSTBrushParam>(eParam), bIsNull);
         break;
-      case OGRSTCSymbol:
-        nVal = ((OGRStyleSymbol *) hST)->GetParamNum((OGRSTSymbolParam)eParam,
-                                                       bIsNull);
+    case OGRSTCSymbol:
+        nVal = reinterpret_cast<OGRStyleSymbol *>(hST)->
+            GetParamNum(static_cast<OGRSTSymbolParam>(eParam), bIsNull);
         break;
-      case OGRSTCLabel:
-        nVal = ((OGRStyleLabel *) hST)->GetParamNum((OGRSTLabelParam)eParam,
-                                                      bIsNull);
+    case OGRSTCLabel:
+        nVal = reinterpret_cast<OGRStyleLabel *>(hST)->
+            GetParamNum(static_cast<OGRSTLabelParam>(eParam), bIsNull);
         break;
-      default:
+    default:
         break;
     }
 
@@ -2311,31 +2388,31 @@ int OGR_ST_GetParamNum( OGRStyleToolH hST, int eParam, int *bValueIsNull )
 
 double OGR_ST_GetParamDbl( OGRStyleToolH hST, int eParam, int *bValueIsNull )
 {
-    GBool bIsNull = TRUE;
-    double dfVal = 0.0;
-
     VALIDATE_POINTER1( hST, "OGR_ST_GetParamDbl", 0.0 );
     VALIDATE_POINTER1( bValueIsNull, "OGR_ST_GetParamDbl", 0.0 );
 
-    switch( ((OGRStyleTool *) hST)->GetType() )
+    GBool bIsNull = TRUE;
+    double dfVal = 0.0;
+
+    switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
     {
-      case OGRSTCPen:
-        dfVal = ((OGRStylePen *) hST)->GetParamDbl((OGRSTPenParam)eParam,
-                                                  bIsNull);
+    case OGRSTCPen:
+        dfVal = reinterpret_cast<OGRStylePen *>(hST)->
+            GetParamDbl(static_cast<OGRSTPenParam>(eParam), bIsNull);
         break;
-      case OGRSTCBrush:
-        dfVal = ((OGRStyleBrush *) hST)->GetParamDbl((OGRSTBrushParam)eParam,
-                                                    bIsNull);
+    case OGRSTCBrush:
+        dfVal = reinterpret_cast<OGRStyleBrush *>(hST)->
+            GetParamDbl(static_cast<OGRSTBrushParam>(eParam), bIsNull);
         break;
-      case OGRSTCSymbol:
-        dfVal = ((OGRStyleSymbol *) hST)->GetParamDbl((OGRSTSymbolParam)eParam,
-                                                     bIsNull);
+    case OGRSTCSymbol:
+        dfVal = reinterpret_cast<OGRStyleSymbol *>(hST)->
+            GetParamDbl(static_cast<OGRSTSymbolParam>(eParam), bIsNull);
         break;
-      case OGRSTCLabel:
-        dfVal = ((OGRStyleLabel *) hST)->GetParamDbl((OGRSTLabelParam)eParam,
-                                                    bIsNull);
+    case OGRSTCLabel:
+        dfVal = reinterpret_cast<OGRStyleLabel *>(hST)->
+            GetParamDbl(static_cast<OGRSTLabelParam>(eParam), bIsNull);
         break;
-      default:
+    default:
         break;
     }
 
@@ -2343,7 +2420,6 @@ double OGR_ST_GetParamDbl( OGRStyleToolH hST, int eParam, int *bValueIsNull )
     return dfVal;
 }
 
-
 /************************************************************************/
 /*                           OGR_ST_SetParamStr()                       */
 /************************************************************************/
@@ -2365,30 +2441,29 @@ void OGR_ST_SetParamStr( OGRStyleToolH hST, int eParam, const char *pszValue )
     VALIDATE_POINTER0( hST, "OGR_ST_SetParamStr" );
     VALIDATE_POINTER0( pszValue, "OGR_ST_SetParamStr" );
 
-    switch( ((OGRStyleTool *) hST)->GetType() )
+    switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
     {
-      case OGRSTCPen:
-        ((OGRStylePen *) hST)->SetParamStr((OGRSTPenParam)eParam,
-                                           pszValue);
+    case OGRSTCPen:
+        reinterpret_cast<OGRStylePen *>(hST)->
+            SetParamStr(static_cast<OGRSTPenParam>(eParam), pszValue);
         break;
-      case OGRSTCBrush:
-        ((OGRStyleBrush *) hST)->SetParamStr((OGRSTBrushParam)eParam,
-                                             pszValue);
+    case OGRSTCBrush:
+        reinterpret_cast<OGRStyleBrush *>(hST)->
+            SetParamStr(static_cast<OGRSTBrushParam>(eParam), pszValue);
         break;
-      case OGRSTCSymbol:
-        ((OGRStyleSymbol *) hST)->SetParamStr((OGRSTSymbolParam)eParam,
-                                              pszValue);
+    case OGRSTCSymbol:
+        reinterpret_cast<OGRStyleSymbol *>(hST)->
+            SetParamStr(static_cast<OGRSTSymbolParam>(eParam), pszValue);
         break;
-      case OGRSTCLabel:
-        ((OGRStyleLabel *) hST)->SetParamStr((OGRSTLabelParam)eParam,
-                                             pszValue);
+    case OGRSTCLabel:
+        reinterpret_cast<OGRStyleLabel *>(hST)->
+            SetParamStr(static_cast<OGRSTLabelParam>(eParam), pszValue);
         break;
-      default:
+    default:
         break;
     }
 }
 
-
 /************************************************************************/
 /*                           OGR_ST_SetParamNum()                       */
 /************************************************************************/
@@ -2409,25 +2484,25 @@ void OGR_ST_SetParamNum( OGRStyleToolH hST, int eParam, int nValue )
 {
     VALIDATE_POINTER0( hST, "OGR_ST_SetParamNum" );
 
-    switch( ((OGRStyleTool *) hST)->GetType() )
+    switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
     {
-      case OGRSTCPen:
-        ((OGRStylePen *) hST)->SetParamNum((OGRSTPenParam)eParam,
-                                           nValue);
+    case OGRSTCPen:
+        reinterpret_cast<OGRStylePen *>(hST)->
+            SetParamNum(static_cast<OGRSTPenParam>(eParam), nValue);
         break;
-      case OGRSTCBrush:
-        ((OGRStyleBrush *) hST)->SetParamNum((OGRSTBrushParam)eParam,
-                                             nValue);
+    case OGRSTCBrush:
+        reinterpret_cast<OGRStyleBrush *>(hST)->
+            SetParamNum(static_cast<OGRSTBrushParam>(eParam), nValue);
         break;
-      case OGRSTCSymbol:
-        ((OGRStyleSymbol *) hST)->SetParamNum((OGRSTSymbolParam)eParam,
-                                              nValue);
+    case OGRSTCSymbol:
+        reinterpret_cast<OGRStyleSymbol *>(hST)->
+            SetParamNum(static_cast<OGRSTSymbolParam>(eParam), nValue);
         break;
-      case OGRSTCLabel:
-        ((OGRStyleLabel *) hST)->SetParamNum((OGRSTLabelParam)eParam,
-                                             nValue);
+    case OGRSTCLabel:
+        reinterpret_cast<OGRStyleLabel *>(hST)->
+            SetParamNum(static_cast<OGRSTLabelParam>(eParam), nValue);
         break;
-      default:
+    default:
         break;
     }
 }
@@ -2452,33 +2527,42 @@ void OGR_ST_SetParamDbl( OGRStyleToolH hST, int eParam, double dfValue )
 {
     VALIDATE_POINTER0( hST, "OGR_ST_SetParamDbl" );
 
-    switch( ((OGRStyleTool *) hST)->GetType() )
+    switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
     {
-      case OGRSTCPen:
-        ((OGRStylePen *) hST)->SetParamDbl((OGRSTPenParam)eParam,
-                                           dfValue);
+    case OGRSTCPen:
+        reinterpret_cast<OGRStylePen *>(hST)->
+            SetParamDbl(static_cast<OGRSTPenParam>(eParam), dfValue);
         break;
-      case OGRSTCBrush:
-        ((OGRStyleBrush *) hST)->SetParamDbl((OGRSTBrushParam)eParam,
-                                             dfValue);
+    case OGRSTCBrush:
+        reinterpret_cast<OGRStyleBrush *>(hST)->
+            SetParamDbl(static_cast<OGRSTBrushParam>(eParam), dfValue);
         break;
-      case OGRSTCSymbol:
-        ((OGRStyleSymbol *) hST)->SetParamDbl((OGRSTSymbolParam)eParam,
-                                              dfValue);
+    case OGRSTCSymbol:
+        reinterpret_cast<OGRStyleSymbol *>(hST)->
+            SetParamDbl(static_cast<OGRSTSymbolParam>(eParam), dfValue);
         break;
-      case OGRSTCLabel:
-        ((OGRStyleLabel *) hST)->SetParamDbl((OGRSTLabelParam)eParam,
-                                             dfValue);
+    case OGRSTCLabel:
+        reinterpret_cast<OGRStyleLabel *>(hST)->
+            SetParamDbl(static_cast<OGRSTLabelParam>(eParam), dfValue);
         break;
-      default:
+    default:
         break;
     }
 }
 
-
 /************************************************************************/
 /*                           OGR_ST_GetStyleString()                    */
 /************************************************************************/
+
+/**
+ * \fn OGRStyleTool::GetStyleString()
+ * \brief Get the style string for this Style Tool
+ *
+ * Maps to the OGRStyleTool subclasses' GetStyleString() methods.
+ *
+ * @return the style string for this style tool or "" if the hST is invalid.
+ */
+
 /**
  * \brief Get the style string for this Style Tool
  *
@@ -2495,19 +2579,19 @@ const char *OGR_ST_GetStyleString( OGRStyleToolH hST )
 
     VALIDATE_POINTER1( hST, "OGR_ST_GetStyleString", "" );
 
-    switch( ((OGRStyleTool *) hST)->GetType() )
+    switch( reinterpret_cast<OGRStyleTool *>(hST)->GetType() )
     {
       case OGRSTCPen:
-        pszVal = ((OGRStylePen *) hST)->GetStyleString();
+        pszVal = reinterpret_cast<OGRStylePen *>(hST)->GetStyleString();
         break;
       case OGRSTCBrush:
-        pszVal = ((OGRStyleBrush *) hST)->GetStyleString();
+        pszVal = reinterpret_cast<OGRStyleBrush *>(hST)->GetStyleString();
         break;
       case OGRSTCSymbol:
-        pszVal = ((OGRStyleSymbol *) hST)->GetStyleString();
+        pszVal = reinterpret_cast<OGRStyleSymbol *>(hST)->GetStyleString();
         break;
       case OGRSTCLabel:
-        pszVal = ((OGRStyleLabel *) hST)->GetStyleString();
+        pszVal = reinterpret_cast<OGRStyleLabel *>(hST)->GetStyleString();
         break;
       default:
         break;
@@ -2520,7 +2604,8 @@ const char *OGR_ST_GetStyleString( OGRStyleToolH hST )
 /*                           OGR_ST_GetRGBFromString()                  */
 /************************************************************************/
 /**
- * \brief Return the r,g,b,a components of a color encoded in \#RRGGBB[AA] format
+ * \brief Return the r,g,b,a components of a color encoded in \#RRGGBB[AA]
+ * format.
  *
  * Maps to OGRStyleTool::GetRGBFromString().
  *
@@ -2547,39 +2632,36 @@ int OGR_ST_GetRGBFromString( OGRStyleToolH hST, const char *pszColor,
     VALIDATE_POINTER1( pnBlue, "OGR_ST_GetRGBFromString", FALSE );
     VALIDATE_POINTER1( pnAlpha, "OGR_ST_GetRGBFromString", FALSE );
 
-    return ((OGRStyleTool *) hST)->GetRGBFromString(pszColor, *pnRed, *pnGreen,
-                                                    *pnBlue, *pnAlpha );
+    return reinterpret_cast<OGRStyleTool *>(hST)->
+        GetRGBFromString(pszColor, *pnRed, *pnGreen,
+                         *pnBlue, *pnAlpha );
 }
 
-
+//! @cond Doxygen_Suppress
 /* ======================================================================== */
 /*                OGRStylePen                                               */
 /*       Specific parameter (Set/Get) for the StylePen                      */
 /* ======================================================================== */
 
-
 /****************************************************************************/
 /*                      OGRStylePen::OGRStylePen()                          */
 /*                                                                          */
 /****************************************************************************/
 OGRStylePen::OGRStylePen() : OGRStyleTool(OGRSTCPen)
 {
-    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTPenLast,
-                                                 sizeof(OGRStyleValue));
+    m_pasStyleValue = static_cast<OGRStyleValue *>(
+        CPLCalloc(OGRSTPenLast, sizeof(OGRStyleValue)));
 }
 
-
-
-
 /****************************************************************************/
 /*                      OGRStylePen::~OGRStylePen()                         */
 /*                                                                          */
 /****************************************************************************/
 OGRStylePen::~OGRStylePen()
 {
-    for (int i = 0; i < OGRSTPenLast; i++)
+    for( int i = 0; i < OGRSTPenLast; i++ )
     {
-        if (m_pasStyleValue[i].pszValue != NULL)
+        if( m_pasStyleValue[i].pszValue != NULL )
         {
             CPLFree(m_pasStyleValue[i].pszValue);
             m_pasStyleValue[i].pszValue = NULL;
@@ -2595,13 +2677,15 @@ OGRStylePen::~OGRStylePen()
 GBool OGRStylePen::Parse()
 
 {
-    return OGRStyleTool::Parse(asStylePen,m_pasStyleValue,(int)OGRSTPenLast);
+    return OGRStyleTool::Parse(asStylePen, m_pasStyleValue,
+                               static_cast<int>(OGRSTPenLast));
 }
 
 /************************************************************************/
 /*                            GetParamStr()                             */
 /************************************************************************/
-const char *OGRStylePen::GetParamStr(OGRSTPenParam eParam, GBool &bValueIsNull)
+const char *OGRStylePen::GetParamStr( OGRSTPenParam eParam,
+                                      GBool &bValueIsNull )
 {
     return OGRStyleTool::GetParamStr(asStylePen[eParam],
                                      m_pasStyleValue[eParam],
@@ -2611,47 +2695,48 @@ const char *OGRStylePen::GetParamStr(OGRSTPenParam eParam, GBool &bValueIsNull)
 /************************************************************************/
 /*                            GetParamNum()                             */
 /************************************************************************/
-int OGRStylePen::GetParamNum(OGRSTPenParam eParam,GBool &bValueIsNull)
+int OGRStylePen::GetParamNum( OGRSTPenParam eParam, GBool &bValueIsNull )
 {
     return OGRStyleTool::GetParamNum(asStylePen[eParam],
-                                     m_pasStyleValue[eParam],bValueIsNull);
+                                     m_pasStyleValue[eParam], bValueIsNull);
 }
 
 /************************************************************************/
 /*                            GetParamDbl()                             */
 /************************************************************************/
-double OGRStylePen::GetParamDbl(OGRSTPenParam eParam,GBool &bValueIsNull)
+double OGRStylePen::GetParamDbl( OGRSTPenParam eParam, GBool &bValueIsNull )
 {
     return OGRStyleTool::GetParamDbl(asStylePen[eParam],
-                                     m_pasStyleValue[eParam],bValueIsNull);
+                                     m_pasStyleValue[eParam], bValueIsNull);
 }
 
 /************************************************************************/
 /*                            SetParamStr()                             */
 /************************************************************************/
 
-void OGRStylePen::SetParamStr(OGRSTPenParam eParam, const char *pszParamString)
+void OGRStylePen::SetParamStr( OGRSTPenParam eParam,
+                               const char *pszParamString )
 {
-    OGRStyleTool::SetParamStr(asStylePen[eParam],m_pasStyleValue[eParam],
+    OGRStyleTool::SetParamStr(asStylePen[eParam], m_pasStyleValue[eParam],
                               pszParamString);
 }
 
 /************************************************************************/
 /*                            SetParamNum()                             */
 /************************************************************************/
-void OGRStylePen::SetParamNum(OGRSTPenParam eParam, int nParam)
+void OGRStylePen::SetParamNum( OGRSTPenParam eParam, int nParam )
 {
     OGRStyleTool::SetParamNum(asStylePen[eParam],
-                              m_pasStyleValue[eParam],nParam);
+                              m_pasStyleValue[eParam], nParam);
 }
 
 /************************************************************************/
 /*                            SetParamDbl()                             */
 /************************************************************************/
-void OGRStylePen::SetParamDbl(OGRSTPenParam eParam, double dfParam)
+void OGRStylePen::SetParamDbl( OGRSTPenParam eParam, double dfParam )
 {
     OGRStyleTool::SetParamDbl(asStylePen[eParam],
-                              m_pasStyleValue[eParam],dfParam);
+                              m_pasStyleValue[eParam], dfParam);
 }
 
 /************************************************************************/
@@ -2659,8 +2744,8 @@ void OGRStylePen::SetParamDbl(OGRSTPenParam eParam, double dfParam)
 /************************************************************************/
 const char *OGRStylePen::GetStyleString()
 {
-    return OGRStyleTool::GetStyleString(asStylePen,m_pasStyleValue,
-                                        (int)OGRSTPenLast);
+    return OGRStyleTool::GetStyleString(asStylePen, m_pasStyleValue,
+                                        static_cast<int>(OGRSTPenLast));
 }
 
 /****************************************************************************/
@@ -2669,8 +2754,8 @@ const char *OGRStylePen::GetStyleString()
 /****************************************************************************/
 OGRStyleBrush::OGRStyleBrush() : OGRStyleTool(OGRSTCBrush)
 {
-    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTBrushLast,
-                                                 sizeof(OGRStyleValue));
+    m_pasStyleValue = static_cast<OGRStyleValue *>(
+        CPLCalloc(OGRSTBrushLast, sizeof(OGRStyleValue)));
 }
 
 /****************************************************************************/
@@ -2679,9 +2764,9 @@ OGRStyleBrush::OGRStyleBrush() : OGRStyleTool(OGRSTCBrush)
 /****************************************************************************/
 OGRStyleBrush::~OGRStyleBrush()
 {
-    for (int i = 0; i < OGRSTBrushLast; i++)
+    for( int i = 0; i < OGRSTBrushLast; i++ )
     {
-        if (m_pasStyleValue[i].pszValue != NULL)
+        if( m_pasStyleValue[i].pszValue != NULL )
         {
             CPLFree(m_pasStyleValue[i].pszValue);
             m_pasStyleValue[i].pszValue = NULL;
@@ -2696,14 +2781,15 @@ OGRStyleBrush::~OGRStyleBrush()
 /************************************************************************/
 GBool OGRStyleBrush::Parse()
 {
-    return OGRStyleTool::Parse(asStyleBrush,m_pasStyleValue,
-                               (int)OGRSTBrushLast);
+    return OGRStyleTool::Parse(asStyleBrush, m_pasStyleValue,
+                               static_cast<int>(OGRSTBrushLast));
 }
 
 /************************************************************************/
 /*                            GetParamStr()                             */
 /************************************************************************/
-const char *OGRStyleBrush::GetParamStr(OGRSTBrushParam eParam, GBool &bValueIsNull)
+const char *OGRStyleBrush::GetParamStr( OGRSTBrushParam eParam,
+                                        GBool &bValueIsNull )
 {
     return OGRStyleTool::GetParamStr(asStyleBrush[eParam],
                                      m_pasStyleValue[eParam],
@@ -2713,46 +2799,47 @@ const char *OGRStyleBrush::GetParamStr(OGRSTBrushParam eParam, GBool &bValueIsNu
 /************************************************************************/
 /*                            GetParamNum()                             */
 /************************************************************************/
-int OGRStyleBrush::GetParamNum(OGRSTBrushParam eParam,GBool &bValueIsNull)
+int OGRStyleBrush::GetParamNum( OGRSTBrushParam eParam, GBool &bValueIsNull )
 {
     return OGRStyleTool::GetParamNum(asStyleBrush[eParam],
-                                     m_pasStyleValue[eParam],bValueIsNull);
+                                     m_pasStyleValue[eParam], bValueIsNull);
 }
 
 /************************************************************************/
 /*                            GetParamDbl()                             */
 /************************************************************************/
-double OGRStyleBrush::GetParamDbl(OGRSTBrushParam eParam,GBool &bValueIsNull)
+double OGRStyleBrush::GetParamDbl( OGRSTBrushParam eParam, GBool &bValueIsNull )
 {
     return OGRStyleTool::GetParamDbl(asStyleBrush[eParam],
-                                     m_pasStyleValue[eParam],bValueIsNull);
+                                     m_pasStyleValue[eParam], bValueIsNull);
 }
 
 /************************************************************************/
 /*                            SetParamStr()                             */
 /************************************************************************/
-void OGRStyleBrush::SetParamStr(OGRSTBrushParam eParam, const char *pszParamString)
+void OGRStyleBrush::SetParamStr( OGRSTBrushParam eParam,
+                                 const char *pszParamString )
 {
-    OGRStyleTool::SetParamStr(asStyleBrush[eParam],m_pasStyleValue[eParam],
+    OGRStyleTool::SetParamStr(asStyleBrush[eParam], m_pasStyleValue[eParam],
                               pszParamString);
 }
 
 /************************************************************************/
 /*                            SetParamNum()                             */
 /************************************************************************/
-void OGRStyleBrush::SetParamNum(OGRSTBrushParam eParam, int nParam)
+void OGRStyleBrush::SetParamNum( OGRSTBrushParam eParam, int nParam )
 {
     OGRStyleTool::SetParamNum(asStyleBrush[eParam],
-                              m_pasStyleValue[eParam],nParam);
+                              m_pasStyleValue[eParam], nParam);
 }
 
 /************************************************************************/
 /*                            SetParamDbl()                             */
 /************************************************************************/
-void OGRStyleBrush::SetParamDbl(OGRSTBrushParam eParam, double dfParam)
+void OGRStyleBrush::SetParamDbl( OGRSTBrushParam eParam, double dfParam )
 {
     OGRStyleTool::SetParamDbl(asStyleBrush[eParam],
-                              m_pasStyleValue[eParam],dfParam);
+                              m_pasStyleValue[eParam], dfParam);
 }
 
 /************************************************************************/
@@ -2760,8 +2847,8 @@ void OGRStyleBrush::SetParamDbl(OGRSTBrushParam eParam, double dfParam)
 /************************************************************************/
 const char *OGRStyleBrush::GetStyleString()
 {
-    return OGRStyleTool::GetStyleString(asStyleBrush,m_pasStyleValue,
-                                        (int)OGRSTBrushLast);
+    return OGRStyleTool::GetStyleString(asStyleBrush, m_pasStyleValue,
+                                        static_cast<int>(OGRSTBrushLast));
 }
 
 /****************************************************************************/
@@ -2769,8 +2856,8 @@ const char *OGRStyleBrush::GetStyleString()
 /****************************************************************************/
 OGRStyleSymbol::OGRStyleSymbol() : OGRStyleTool(OGRSTCSymbol)
 {
-    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTSymbolLast,
-                                                 sizeof(OGRStyleValue));
+    m_pasStyleValue = static_cast<OGRStyleValue *>(
+        CPLCalloc(OGRSTSymbolLast, sizeof(OGRStyleValue)));
 }
 
 /****************************************************************************/
@@ -2779,9 +2866,9 @@ OGRStyleSymbol::OGRStyleSymbol() : OGRStyleTool(OGRSTCSymbol)
 /****************************************************************************/
 OGRStyleSymbol::~OGRStyleSymbol()
 {
-    for (int i = 0; i < OGRSTSymbolLast; i++)
+    for( int i = 0; i < OGRSTSymbolLast; i++ )
     {
-        if (m_pasStyleValue[i].pszValue != NULL)
+        if( m_pasStyleValue[i].pszValue != NULL )
         {
             CPLFree(m_pasStyleValue[i].pszValue);
             m_pasStyleValue[i].pszValue = NULL;
@@ -2796,74 +2883,82 @@ OGRStyleSymbol::~OGRStyleSymbol()
 /************************************************************************/
 GBool OGRStyleSymbol::Parse()
 {
-    return OGRStyleTool::Parse(asStyleSymbol,m_pasStyleValue,
-                               (int)OGRSTSymbolLast);
+    return OGRStyleTool::Parse(asStyleSymbol, m_pasStyleValue,
+                               static_cast<int>(OGRSTSymbolLast));
 }
 
 /************************************************************************/
 /*                            GetParamStr()                             */
 /************************************************************************/
-const char *OGRStyleSymbol::GetParamStr(OGRSTSymbolParam eParam, GBool &bValueIsNull)
-{   return OGRStyleTool::GetParamStr(asStyleSymbol[eParam],
+const char *OGRStyleSymbol::GetParamStr( OGRSTSymbolParam eParam,
+                                         GBool &bValueIsNull )
+{
+    return OGRStyleTool::GetParamStr(asStyleSymbol[eParam],
                                      m_pasStyleValue[eParam],
                                      bValueIsNull);
 }
 /************************************************************************/
 /*                            GetParamNum()                             */
 /************************************************************************/
-int OGRStyleSymbol::GetParamNum(OGRSTSymbolParam eParam,GBool &bValueIsNull)
-{  return OGRStyleTool::GetParamNum(asStyleSymbol[eParam],
-                                    m_pasStyleValue[eParam],bValueIsNull);
+int OGRStyleSymbol::GetParamNum( OGRSTSymbolParam eParam, GBool &bValueIsNull )
+{
+    return OGRStyleTool::GetParamNum(asStyleSymbol[eParam],
+                                     m_pasStyleValue[eParam], bValueIsNull);
 }
 /************************************************************************/
 /*                            GetParamDbl()                             */
 /************************************************************************/
-double OGRStyleSymbol::GetParamDbl(OGRSTSymbolParam eParam,GBool &bValueIsNull)
-{  return OGRStyleTool::GetParamDbl(asStyleSymbol[eParam],
-                                    m_pasStyleValue[eParam],bValueIsNull);
+double OGRStyleSymbol::GetParamDbl( OGRSTSymbolParam eParam,
+                                    GBool &bValueIsNull )
+{
+    return OGRStyleTool::GetParamDbl(asStyleSymbol[eParam],
+                                     m_pasStyleValue[eParam], bValueIsNull);
 }
 
 /************************************************************************/
 /*                            SetParamStr()                             */
 /************************************************************************/
-void OGRStyleSymbol::SetParamStr(OGRSTSymbolParam eParam, const char *pszParamString)
-{   OGRStyleTool::SetParamStr(asStyleSymbol[eParam],m_pasStyleValue[eParam],
+void OGRStyleSymbol::SetParamStr( OGRSTSymbolParam eParam,
+                                  const char *pszParamString )
+{
+    OGRStyleTool::SetParamStr(asStyleSymbol[eParam], m_pasStyleValue[eParam],
                               pszParamString);
 }
 
 /************************************************************************/
 /*                            SetParamNum()                             */
 /************************************************************************/
-void OGRStyleSymbol::SetParamNum(OGRSTSymbolParam eParam, int nParam)
-{  OGRStyleTool::SetParamNum(asStyleSymbol[eParam],
-                             m_pasStyleValue[eParam],nParam);
+void OGRStyleSymbol::SetParamNum( OGRSTSymbolParam eParam, int nParam )
+{
+    OGRStyleTool::SetParamNum(asStyleSymbol[eParam],
+                              m_pasStyleValue[eParam], nParam);
 }
 
 /************************************************************************/
 /*                            SetParamDbl()                             */
 /************************************************************************/
-void OGRStyleSymbol::SetParamDbl(OGRSTSymbolParam eParam, double dfParam)
-        {   OGRStyleTool::SetParamDbl(asStyleSymbol[eParam],
-                                      m_pasStyleValue[eParam],dfParam);
-        }
+void OGRStyleSymbol::SetParamDbl( OGRSTSymbolParam eParam, double dfParam )
+{
+    OGRStyleTool::SetParamDbl(asStyleSymbol[eParam],
+                              m_pasStyleValue[eParam], dfParam);
+}
 /************************************************************************/
 /*                           GetStyleString()                           */
 /************************************************************************/
 const char *OGRStyleSymbol::GetStyleString()
 {
-    return OGRStyleTool::GetStyleString(asStyleSymbol,m_pasStyleValue,
-                                        (int)OGRSTSymbolLast);
+    return OGRStyleTool::GetStyleString(asStyleSymbol, m_pasStyleValue,
+                                        static_cast<int>(OGRSTSymbolLast));
 }
 
-
 /****************************************************************************/
 /*                      OGRStyleLabel::OGRStyleLabel()                      */
 /*                                                                          */
 /****************************************************************************/
 OGRStyleLabel::OGRStyleLabel() : OGRStyleTool(OGRSTCLabel)
 {
-    m_pasStyleValue = (OGRStyleValue *)CPLCalloc(OGRSTLabelLast,
-                                                 sizeof(OGRStyleValue));
+    m_pasStyleValue = static_cast<OGRStyleValue *>(
+        CPLCalloc(OGRSTLabelLast, sizeof(OGRStyleValue)));
 }
 
 /****************************************************************************/
@@ -2872,9 +2967,9 @@ OGRStyleLabel::OGRStyleLabel() : OGRStyleTool(OGRSTCLabel)
 /****************************************************************************/
 OGRStyleLabel::~OGRStyleLabel()
 {
-    for (int i = 0; i < OGRSTLabelLast; i++)
+    for( int i = 0; i < OGRSTLabelLast; i++ )
     {
-        if (m_pasStyleValue[i].pszValue != NULL)
+        if( m_pasStyleValue[i].pszValue != NULL )
         {
             CPLFree(m_pasStyleValue[i].pszValue);
             m_pasStyleValue[i].pszValue = NULL;
@@ -2888,58 +2983,71 @@ OGRStyleLabel::~OGRStyleLabel()
 /*                               Parse()                                */
 /************************************************************************/
 GBool OGRStyleLabel::Parse()
-{ return OGRStyleTool::Parse(asStyleLabel,m_pasStyleValue,
-                             (int)OGRSTLabelLast);
+{
+    return OGRStyleTool::Parse(asStyleLabel, m_pasStyleValue,
+                               static_cast<int>(OGRSTLabelLast));
 }
 
 /************************************************************************/
 /*                            GetParamStr()                             */
 /************************************************************************/
-const char *OGRStyleLabel::GetParamStr(OGRSTLabelParam eParam, GBool &bValueIsNull)
-{   return OGRStyleTool::GetParamStr(asStyleLabel[eParam],
+const char *OGRStyleLabel::GetParamStr( OGRSTLabelParam eParam,
+                                        GBool &bValueIsNull )
+{
+    return OGRStyleTool::GetParamStr(asStyleLabel[eParam],
                                      m_pasStyleValue[eParam],
                                      bValueIsNull);
 }
 /************************************************************************/
 /*                            GetParamNum()                             */
 /************************************************************************/
-int OGRStyleLabel::GetParamNum(OGRSTLabelParam eParam,GBool &bValueIsNull)
-{  return OGRStyleTool::GetParamNum(asStyleLabel[eParam],
-                                    m_pasStyleValue[eParam],bValueIsNull);
+int OGRStyleLabel::GetParamNum( OGRSTLabelParam eParam,
+                                GBool &bValueIsNull )
+{
+    return OGRStyleTool::GetParamNum(asStyleLabel[eParam],
+                                     m_pasStyleValue[eParam], bValueIsNull);
 }
 /************************************************************************/
 /*                            GetParamDbl()                             */
 /************************************************************************/
-double OGRStyleLabel::GetParamDbl(OGRSTLabelParam eParam,GBool &bValueIsNull)
-{  return OGRStyleTool::GetParamDbl(asStyleLabel[eParam],
-                                    m_pasStyleValue[eParam],bValueIsNull);
+double OGRStyleLabel::GetParamDbl( OGRSTLabelParam eParam,
+                                   GBool &bValueIsNull )
+{
+    return OGRStyleTool::GetParamDbl(asStyleLabel[eParam],
+                                     m_pasStyleValue[eParam], bValueIsNull);
 }
 /************************************************************************/
 /*                            SetParamStr()                             */
 /************************************************************************/
-void OGRStyleLabel::SetParamStr(OGRSTLabelParam eParam, const char *pszParamString)
-{   OGRStyleTool::SetParamStr(asStyleLabel[eParam],m_pasStyleValue[eParam],
+void OGRStyleLabel::SetParamStr( OGRSTLabelParam eParam,
+                                 const char *pszParamString )
+{
+    OGRStyleTool::SetParamStr(asStyleLabel[eParam], m_pasStyleValue[eParam],
                               pszParamString);
 }
 /************************************************************************/
 /*                            SetParamNum()                             */
 /************************************************************************/
-void OGRStyleLabel::SetParamNum(OGRSTLabelParam eParam, int nParam)
-{  OGRStyleTool::SetParamNum(asStyleLabel[eParam],
-                             m_pasStyleValue[eParam],nParam);
+void OGRStyleLabel::SetParamNum( OGRSTLabelParam eParam, int nParam )
+{
+    OGRStyleTool::SetParamNum(asStyleLabel[eParam],
+                              m_pasStyleValue[eParam], nParam);
 }
 
 /************************************************************************/
 /*                            SetParamDbl()                             */
 /************************************************************************/
-void OGRStyleLabel::SetParamDbl(OGRSTLabelParam eParam, double dfParam)
-{   OGRStyleTool::SetParamDbl(asStyleLabel[eParam],
-                              m_pasStyleValue[eParam],dfParam);
+void OGRStyleLabel::SetParamDbl( OGRSTLabelParam eParam, double dfParam )
+{
+    OGRStyleTool::SetParamDbl(asStyleLabel[eParam],
+                              m_pasStyleValue[eParam], dfParam);
 }
 /************************************************************************/
 /*                           GetStyleString()                           */
 /************************************************************************/
 const char *OGRStyleLabel::GetStyleString()
-{   return OGRStyleTool::GetStyleString(asStyleLabel,m_pasStyleValue,
-                                        (int)OGRSTLabelLast);
+{
+    return OGRStyleTool::GetStyleString(asStyleLabel, m_pasStyleValue,
+                                        static_cast<int>(OGRSTLabelLast));
 }
+//! @endcond
diff --git a/ogr/ogrfielddefn.cpp b/ogr/ogrfielddefn.cpp
index 3c78aac..85305e9 100644
--- a/ogr/ogrfielddefn.cpp
+++ b/ogr/ogrfielddefn.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfielddefn.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRFieldDefn class implementation.
@@ -28,12 +27,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_feature.h"
+
+#include <cstring>
+
 #include "ogr_api.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
 #include "ograpispy.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrfielddefn.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+
+CPL_CVSID("$Id: ogrfielddefn.cpp 37441 2017-02-24 23:16:17Z goatbar $");
 
 /************************************************************************/
 /*                            OGRFieldDefn()                            */
@@ -48,11 +56,18 @@ CPL_CVSID("$Id: ogrfielddefn.cpp 33631 2016-03-04 06:28:09Z goatbar $");
  * @param eTypeIn the type of the new field.
  */
 
-OGRFieldDefn::OGRFieldDefn( const char * pszNameIn, OGRFieldType eTypeIn )
-
-{
-    Initialize( pszNameIn, eTypeIn );
-}
+OGRFieldDefn::OGRFieldDefn( const char * pszNameIn, OGRFieldType eTypeIn ) :
+    pszName(CPLStrdup(pszNameIn)),
+    eType(eTypeIn),
+    eJustify(OJUndefined),
+    // Should nWidth & nPrecision be defined in some particular way for numbers?
+    nWidth(0),
+    nPrecision(0),
+    pszDefault(NULL),
+    bIgnore(FALSE),
+    eSubType(OFSTNone),
+    bNullable(TRUE)
+{}
 
 /************************************************************************/
 /*                            OGRFieldDefn()                            */
@@ -66,17 +81,18 @@ OGRFieldDefn::OGRFieldDefn( const char * pszNameIn, OGRFieldType eTypeIn )
  * @param poPrototype the field definition to clone.
  */
 
-OGRFieldDefn::OGRFieldDefn( OGRFieldDefn *poPrototype )
-
+OGRFieldDefn::OGRFieldDefn( OGRFieldDefn *poPrototype ) :
+    pszName(CPLStrdup(poPrototype->GetNameRef())),
+    eType(poPrototype->GetType()),
+    eJustify(poPrototype->GetJustify()),
+    nWidth(poPrototype->GetWidth()),
+    nPrecision(poPrototype->GetPrecision()),
+    pszDefault(NULL),
+    bIgnore(FALSE),  // TODO(schwehr): Can we use IsIgnored()?
+    eSubType(poPrototype->GetSubType()),
+    bNullable(poPrototype->IsNullable())
 {
-    Initialize( poPrototype->GetNameRef(), poPrototype->GetType() );
-
-    SetJustify( poPrototype->GetJustify() );
-    SetWidth( poPrototype->GetWidth() );
-    SetPrecision( poPrototype->GetPrecision() );
-    SetSubType( poPrototype->GetSubType() );
-    SetNullable( poPrototype->IsNullable() );
-    SetDefault( poPrototype->GetDefault() );
+    SetDefault(poPrototype->GetDefault());
 }
 
 /************************************************************************/
@@ -97,27 +113,7 @@ OGRFieldDefn::OGRFieldDefn( OGRFieldDefn *poPrototype )
 OGRFieldDefnH OGR_Fld_Create( const char *pszName, OGRFieldType eType )
 
 {
-    return (OGRFieldDefnH) (new OGRFieldDefn(pszName,eType));
-}
-
-/************************************************************************/
-/*                             Initialize()                             */
-/************************************************************************/
-
-void OGRFieldDefn::Initialize( const char * pszNameIn, OGRFieldType eTypeIn )
-
-{
-    pszName = CPLStrdup( pszNameIn );
-    eType = eTypeIn;
-    eJustify = OJUndefined;
-
-    nWidth = 0;         // should these be defined in some particular way
-    nPrecision = 0;     // for numbers?
-
-    pszDefault = NULL;
-    bIgnore = FALSE;
-    eSubType = OFSTNone;
-    bNullable = TRUE;
+    return reinterpret_cast<OGRFieldDefnH>(new OGRFieldDefn(pszName, eType));
 }
 
 /************************************************************************/
@@ -127,8 +123,8 @@ void OGRFieldDefn::Initialize( const char * pszNameIn, OGRFieldType eTypeIn )
 OGRFieldDefn::~OGRFieldDefn()
 
 {
-    CPLFree( pszName );
-    CPLFree( pszDefault );
+    CPLFree(pszName);
+    CPLFree(pszDefault);
 }
 
 /************************************************************************/
@@ -143,7 +139,7 @@ OGRFieldDefn::~OGRFieldDefn()
 void OGR_Fld_Destroy( OGRFieldDefnH hDefn )
 
 {
-    delete (OGRFieldDefn *) hDefn;
+    delete reinterpret_cast<OGRFieldDefn *>(hDefn);
 }
 
 /************************************************************************/
@@ -161,8 +157,11 @@ void OGR_Fld_Destroy( OGRFieldDefnH hDefn )
 void OGRFieldDefn::SetName( const char * pszNameIn )
 
 {
-    CPLFree( pszName );
-    pszName = CPLStrdup( pszNameIn );
+    if( pszName != pszNameIn )
+    {
+        CPLFree(pszName);
+        pszName = CPLStrdup(pszNameIn);
+    }
 }
 
 /************************************************************************/
@@ -180,7 +179,7 @@ void OGRFieldDefn::SetName( const char * pszNameIn )
 void OGR_Fld_SetName( OGRFieldDefnH hDefn, const char *pszName )
 
 {
-    ((OGRFieldDefn *) hDefn)->SetName( pszName );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->SetName(pszName);
 }
 
 /************************************************************************/
@@ -220,7 +219,7 @@ const char *OGR_Fld_GetNameRef( OGRFieldDefnH hDefn )
         OGRAPISpy_Fld_GetXXXX(hDefn, "GetNameRef");
 #endif
 
-    return ((OGRFieldDefn *) hDefn)->GetNameRef();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->GetNameRef();
 }
 
 /************************************************************************/
@@ -228,7 +227,7 @@ const char *OGR_Fld_GetNameRef( OGRFieldDefnH hDefn )
 /************************************************************************/
 
 /**
- * \fn OGRFieldType OGRFieldDefn::GetType();
+ * \fn OGRFieldType OGRFieldDefn::GetType() const;
  *
  * \brief Fetch type of this field.
  *
@@ -258,7 +257,7 @@ OGRFieldType OGR_Fld_GetType( OGRFieldDefnH hDefn )
         OGRAPISpy_Fld_GetXXXX(hDefn, "GetType");
 #endif
 
-    return ((OGRFieldDefn *) hDefn)->GetType();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->GetType();
 }
 
 /************************************************************************/
@@ -280,13 +279,13 @@ void OGRFieldDefn::SetType( OGRFieldType eTypeIn )
     if( !OGR_AreTypeSubTypeCompatible(eTypeIn, eSubType) )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
-                 "Type and subtype of field definition are not compatible. Reseting to OFSTNone");
+                 "Type and subtype of field definition are not compatible. "
+                 "Resetting to OFSTNone");
         eSubType = OFSTNone;
     }
     eType = eTypeIn;
 }
 
-
 /************************************************************************/
 /*                          OGR_Fld_SetType()                           */
 /************************************************************************/
@@ -304,7 +303,7 @@ void OGRFieldDefn::SetType( OGRFieldType eTypeIn )
 void OGR_Fld_SetType( OGRFieldDefnH hDefn, OGRFieldType eType )
 
 {
-    ((OGRFieldDefn *) hDefn)->SetType( eType );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->SetType(eType);
 }
 
 /************************************************************************/
@@ -312,7 +311,7 @@ void OGR_Fld_SetType( OGRFieldDefnH hDefn, OGRFieldType eType )
 /************************************************************************/
 
 /**
- * \fn OGRFieldSubType OGRFieldDefn::GetSubType();
+ * \fn OGRFieldSubType OGRFieldDefn::GetSubType() const;
  *
  * \brief Fetch subtype of this field.
  *
@@ -344,7 +343,7 @@ OGRFieldSubType OGR_Fld_GetSubType( OGRFieldDefnH hDefn )
         OGRAPISpy_Fld_GetXXXX(hDefn, "GetSubType");
 #endif
 
-    return ((OGRFieldDefn *) hDefn)->GetSubType();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->GetSubType();
 }
 
 /************************************************************************/
@@ -366,7 +365,8 @@ void OGRFieldDefn::SetSubType( OGRFieldSubType eSubTypeIn )
     if( !OGR_AreTypeSubTypeCompatible(eType, eSubTypeIn) )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
-                 "Type and subtype of field definition are not compatible. Reseting to OFSTNone");
+                 "Type and subtype of field definition are not compatible. "
+                 "Resetting to OFSTNone");
         eSubType = OFSTNone;
     }
     else
@@ -393,7 +393,7 @@ void OGRFieldDefn::SetSubType( OGRFieldSubType eSubTypeIn )
 void OGR_Fld_SetSubType( OGRFieldDefnH hDefn, OGRFieldSubType eSubType )
 
 {
-    ((OGRFieldDefn *) hDefn)->SetSubType( eSubType );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->SetSubType(eSubType);
 }
 
 /************************************************************************/
@@ -403,12 +403,12 @@ void OGR_Fld_SetSubType( OGRFieldDefnH hDefn, OGRFieldSubType eSubType )
 /**
  * \brief Set default field value.
  *
- * The default field value is taken into account by drivers (generally those with
- * a SQL interface) that support it at field creation time. OGR will generally not
- * automatically set the default field value to null fields by itself when calling
- * OGRFeature::CreateFeature() / OGRFeature::SetFeature(), but will let the
- * low-level layers to do the job. So retrieving the feature from the layer is
- * recommended.
+ * The default field value is taken into account by drivers (generally those
+ * with a SQL interface) that support it at field creation time. OGR will
+ * generally not automatically set the default field value to null fields by
+ * itself when calling OGRFeature::CreateFeature() / OGRFeature::SetFeature(),
+ * but will let the low-level layers to do the job. So retrieving the feature
+ * from the layer is recommended.
  *
  * The accepted values are NULL, a numeric value, a literal value enclosed
  * between single quote characters (and inner single quote characters escaped by
@@ -438,11 +438,12 @@ void OGRFieldDefn::SetDefault( const char* pszDefaultIn )
     {
         if( pszDefaultIn[strlen(pszDefaultIn)-1] != '\'' )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Incorrectly quoted string literal");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Incorrectly quoted string literal");
             return;
         }
-        const char* pszPtr = pszDefaultIn + 1;
-        for(; *pszPtr != '\0'; pszPtr ++ )
+        const char* pszPtr = pszDefaultIn + 1;  // Used after for.
+        for( ; *pszPtr != '\0'; pszPtr++ )
         {
             if( *pszPtr == '\'' )
             {
@@ -450,15 +451,17 @@ void OGRFieldDefn::SetDefault( const char* pszDefaultIn )
                     break;
                 if( pszPtr[1] != '\'' )
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined, "Incorrectly quoted string literal");
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Incorrectly quoted string literal");
                     return;
                 }
-                pszPtr ++;
+                pszPtr++;
             }
         }
         if( *pszPtr == '\0' )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Incorrectly quoted string literal");
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Incorrectly quoted string literal");
             return;
         }
     }
@@ -473,12 +476,12 @@ void OGRFieldDefn::SetDefault( const char* pszDefaultIn )
 /**
  * \brief Set default field value.
  *
- * The default field value is taken into account by drivers (generally those with
- * a SQL interface) that support it at field creation time. OGR will generally not
- * automatically set the default field value to null fields by itself when calling
- * OGRFeature::CreateFeature() / OGRFeature::SetFeature(), but will let the
- * low-level layers to do the job. So retrieving the feature from the layer is
- * recommended.
+ * The default field value is taken into account by drivers (generally those
+ * with a SQL interface) that support it at field creation time. OGR will
+ * generally not automatically set the default field value to null fields by
+ * itself when calling OGRFeature::CreateFeature() / OGRFeature::SetFeature(),
+ * but will let the low-level layers to do the job. So retrieving the feature
+ * from the layer is recommended.
  *
  * The accepted values are NULL, a numeric value, a literal value enclosed
  * between single quote characters (and inner single quote characters escaped by
@@ -499,9 +502,9 @@ void OGRFieldDefn::SetDefault( const char* pszDefaultIn )
  * @since GDAL 2.0
  */
 
-void   CPL_DLL OGR_Fld_SetDefault( OGRFieldDefnH hDefn, const char* pszDefault )
+void CPL_DLL OGR_Fld_SetDefault( OGRFieldDefnH hDefn, const char* pszDefault )
 {
-    ((OGRFieldDefn *) hDefn)->SetDefault( pszDefault );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->SetDefault(pszDefault);
 }
 
 /************************************************************************/
@@ -539,7 +542,7 @@ const char* OGRFieldDefn::GetDefault() const
 
 const char *OGR_Fld_GetDefault( OGRFieldDefnH hDefn )
 {
-    return ((OGRFieldDefn *) hDefn)->GetDefault();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->GetDefault();
 }
 
 /************************************************************************/
@@ -605,7 +608,7 @@ int OGRFieldDefn::IsDefaultDriverSpecific() const
 
 int OGR_Fld_IsDefaultDriverSpecific( OGRFieldDefnH hDefn )
 {
-    return ((OGRFieldDefn *) hDefn)->IsDefaultDriverSpecific();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->IsDefaultDriverSpecific();
 }
 
 /************************************************************************/
@@ -685,7 +688,7 @@ const char * OGRFieldDefn::GetFieldTypeName( OGRFieldType eType )
 const char *OGR_GetFieldTypeName( OGRFieldType eType )
 
 {
-    return OGRFieldDefn::GetFieldTypeName( eType );
+    return OGRFieldDefn::GetFieldTypeName(eType);
 }
 
 /************************************************************************/
@@ -745,7 +748,7 @@ const char * OGRFieldDefn::GetFieldSubTypeName( OGRFieldSubType eSubType )
 const char *OGR_GetFieldSubTypeName( OGRFieldSubType eSubType )
 
 {
-    return OGRFieldDefn::GetFieldSubTypeName( eSubType );
+    return OGRFieldDefn::GetFieldSubTypeName(eSubType);
 }
 
 /************************************************************************/
@@ -777,7 +780,7 @@ int OGR_AreTypeSubTypeCompatible( OGRFieldType eType, OGRFieldSubType eSubType )
 /************************************************************************/
 
 /**
- * \fn OGRJustification OGRFieldDefn::GetJustify();
+ * \fn OGRJustification OGRFieldDefn::GetJustify() const;
  *
  * \brief Get the justification for this field.
  *
@@ -805,7 +808,7 @@ int OGR_AreTypeSubTypeCompatible( OGRFieldType eType, OGRFieldSubType eSubType )
 OGRJustification OGR_Fld_GetJustify( OGRFieldDefnH hDefn )
 
 {
-    return ((OGRFieldDefn *) hDefn)->GetJustify();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->GetJustify();
 }
 
 /************************************************************************/
@@ -841,7 +844,7 @@ OGRJustification OGR_Fld_GetJustify( OGRFieldDefnH hDefn )
 void OGR_Fld_SetJustify( OGRFieldDefnH hDefn, OGRJustification eJustify )
 
 {
-    ((OGRFieldDefn *) hDefn)->SetJustify( eJustify );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->SetJustify(eJustify);
 }
 
 /************************************************************************/
@@ -849,7 +852,7 @@ void OGR_Fld_SetJustify( OGRFieldDefnH hDefn, OGRJustification eJustify )
 /************************************************************************/
 
 /**
- * \fn int OGRFieldDefn::GetWidth();
+ * \fn int OGRFieldDefn::GetWidth() const;
  *
  * \brief Get the formatting width for this field.
  *
@@ -873,7 +876,7 @@ void OGR_Fld_SetJustify( OGRFieldDefnH hDefn, OGRJustification eJustify )
 int OGR_Fld_GetWidth( OGRFieldDefnH hDefn )
 
 {
-    return ((OGRFieldDefn *) hDefn)->GetWidth();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->GetWidth();
 }
 
 /************************************************************************/
@@ -905,7 +908,7 @@ int OGR_Fld_GetWidth( OGRFieldDefnH hDefn )
 void OGR_Fld_SetWidth( OGRFieldDefnH hDefn, int nNewWidth )
 
 {
-    ((OGRFieldDefn *) hDefn)->SetWidth( nNewWidth );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->SetWidth(nNewWidth);
 }
 
 /************************************************************************/
@@ -913,7 +916,7 @@ void OGR_Fld_SetWidth( OGRFieldDefnH hDefn, int nNewWidth )
 /************************************************************************/
 
 /**
- * \fn int OGRFieldDefn::GetPrecision();
+ * \fn int OGRFieldDefn::GetPrecision() const;
  *
  * \brief Get the formatting precision for this field.
  * This should normally be
@@ -941,7 +944,7 @@ void OGR_Fld_SetWidth( OGRFieldDefnH hDefn, int nNewWidth )
 int OGR_Fld_GetPrecision( OGRFieldDefnH hDefn )
 
 {
-    return ((OGRFieldDefn *) hDefn)->GetPrecision();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->GetPrecision();
 }
 
 /************************************************************************/
@@ -977,7 +980,7 @@ int OGR_Fld_GetPrecision( OGRFieldDefnH hDefn )
 void OGR_Fld_SetPrecision( OGRFieldDefnH hDefn, int nPrecision )
 
 {
-    ((OGRFieldDefn *) hDefn)->SetPrecision( nPrecision );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->SetPrecision( nPrecision );
 }
 
 /************************************************************************/
@@ -1004,11 +1007,11 @@ void OGRFieldDefn::Set( const char *pszNameIn,
                         int nWidthIn, int nPrecisionIn,
                         OGRJustification eJustifyIn )
 {
-    SetName( pszNameIn );
-    SetType( eTypeIn );
-    SetWidth( nWidthIn );
-    SetPrecision( nPrecisionIn );
-    SetJustify( eJustifyIn );
+    SetName(pszNameIn);
+    SetType(eTypeIn);
+    SetWidth(nWidthIn);
+    SetPrecision(nPrecisionIn);
+    SetJustify(eJustifyIn);
 }
 
 /************************************************************************/
@@ -1031,13 +1034,13 @@ void OGRFieldDefn::Set( const char *pszNameIn,
  */
 
 void OGR_Fld_Set( OGRFieldDefnH hDefn, const char *pszNameIn,
-                        OGRFieldType eTypeIn,
-                        int nWidthIn, int nPrecisionIn,
-                        OGRJustification eJustifyIn )
+                  OGRFieldType eTypeIn,
+                  int nWidthIn, int nPrecisionIn,
+                  OGRJustification eJustifyIn )
 
 {
-    ((OGRFieldDefn *) hDefn)->Set( pszNameIn, eTypeIn, nWidthIn,
-                                   nPrecisionIn, eJustifyIn );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->
+        Set(pszNameIn, eTypeIn, nWidthIn, nPrecisionIn, eJustifyIn);
 }
 
 /************************************************************************/
@@ -1045,7 +1048,7 @@ void OGR_Fld_Set( OGRFieldDefnH hDefn, const char *pszNameIn,
 /************************************************************************/
 
 /**
- * \fn int OGRFieldDefn::IsIgnored();
+ * \fn int OGRFieldDefn::IsIgnored() const;
  *
  * \brief Return whether this field should be omitted when fetching features
  *
@@ -1069,7 +1072,7 @@ void OGR_Fld_Set( OGRFieldDefnH hDefn, const char *pszNameIn,
 
 int OGR_Fld_IsIgnored( OGRFieldDefnH hDefn )
 {
-    return ((OGRFieldDefn *) hDefn)->IsIgnored();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->IsIgnored();
 }
 
 /************************************************************************/
@@ -1101,7 +1104,7 @@ int OGR_Fld_IsIgnored( OGRFieldDefnH hDefn )
 
 void OGR_Fld_SetIgnored( OGRFieldDefnH hDefn, int ignore )
 {
-    ((OGRFieldDefn *) hDefn)->SetIgnored( ignore );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->SetIgnored(ignore);
 }
 
 /************************************************************************/
@@ -1117,12 +1120,13 @@ void OGR_Fld_SetIgnored( OGRFieldDefnH hDefn, int ignore )
 
 int OGRFieldDefn::IsSame( const OGRFieldDefn * poOtherFieldDefn ) const
 {
-    return (strcmp(pszName, poOtherFieldDefn->pszName) == 0 &&
-            eType == poOtherFieldDefn->eType &&
-            eSubType == poOtherFieldDefn->eSubType &&
-            nWidth == poOtherFieldDefn->nWidth &&
-            nPrecision == poOtherFieldDefn->nPrecision &&
-            bNullable == poOtherFieldDefn->bNullable);
+    return
+        strcmp(pszName, poOtherFieldDefn->pszName) == 0 &&
+        eType == poOtherFieldDefn->eType &&
+        eSubType == poOtherFieldDefn->eSubType &&
+        nWidth == poOtherFieldDefn->nWidth &&
+        nPrecision == poOtherFieldDefn->nPrecision &&
+        bNullable == poOtherFieldDefn->bNullable;
 }
 
 /************************************************************************/
@@ -1170,7 +1174,7 @@ int OGRFieldDefn::IsSame( const OGRFieldDefn * poOtherFieldDefn ) const
 
 int OGR_Fld_IsNullable( OGRFieldDefnH hDefn )
 {
-    return ((OGRFieldDefn *) hDefn)->IsNullable();
+    return reinterpret_cast<OGRFieldDefn *>(hDefn)->IsNullable();
 }
 
 /************************************************************************/
@@ -1182,8 +1186,8 @@ int OGR_Fld_IsNullable( OGRFieldDefnH hDefn )
  *
  * \brief Set whether this field can receive null values.
  *
- * By default, fields are nullable, so this method is generally called with FALSE
- * to set a not-null constraint.
+ * By default, fields are nullable, so this method is generally called with
+ * FALSE to set a not-null constraint.
  *
  * Drivers that support writing not-null constraint will advertize the
  * GDAL_DCAP_NOTNULL_FIELDS driver metadata item.
@@ -1201,8 +1205,8 @@ int OGR_Fld_IsNullable( OGRFieldDefnH hDefn )
 /**
  * \brief Set whether this field can receive null values.
  *
- * By default, fields are nullable, so this method is generally called with FALSE
- * to set a not-null constraint.
+ * By default, fields are nullable, so this method is generally called with
+ * FALSE to set a not-null constraint.
  *
  * Drivers that support writing not-null constraint will advertize the
  * GDAL_DCAP_NOTNULL_FIELDS driver metadata item.
@@ -1216,16 +1220,16 @@ int OGR_Fld_IsNullable( OGRFieldDefnH hDefn )
 
 void OGR_Fld_SetNullable( OGRFieldDefnH hDefn, int bNullableIn )
 {
-    ((OGRFieldDefn *) hDefn)->SetNullable( bNullableIn );
+    reinterpret_cast<OGRFieldDefn *>(hDefn)->SetNullable(bNullableIn);
 }
 
-
 /************************************************************************/
 /*                        OGRUpdateFieldType()                          */
 /************************************************************************/
 
 /**
- * \brief Update the type of a field definition by "merging" its existing type with a new type.
+ * \brief Update the type of a field definition by "merging" its existing type
+ * with a new type.
  *
  * The update is done such as broadening the type. For example a OFTInteger
  * updated with OFTInteger64 will be promoted to OFTInteger64.
diff --git a/ogr/ogrgeomediageometry.cpp b/ogr/ogrgeomediageometry.cpp
index 94fc4eb..30991cf 100644
--- a/ogr/ogrgeomediageometry.cpp
+++ b/ogr/ogrgeomediageometry.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeomediageometry.cpp 30352 2015-09-14 01:12:29Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of geomedia geometry blobs
@@ -30,16 +29,16 @@
 #include "ogrgeomediageometry.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrgeomediageometry.cpp 30352 2015-09-14 01:12:29Z goatbar $");
+CPL_CVSID("$Id: ogrgeomediageometry.cpp 36272 2016-11-18 01:20:28Z goatbar $");
 
-#define GEOMEDIA_POINT          0xC0
-#define GEOMEDIA_ORIENTED_POINT 0xC8
-#define GEOMEDIA_POLYLINE       0xC2
-#define GEOMEDIA_POLYGON        0xC3
-#define GEOMEDIA_BOUNDARY       0xC5
-#define GEOMEDIA_COLLECTION     0xC6
-#define GEOMEDIA_MULTILINE      0xCB
-#define GEOMEDIA_MULTIPOLYGON   0xCC
+static const int GEOMEDIA_POINT          = 0xC0;
+static const int GEOMEDIA_ORIENTED_POINT = 0xC8;
+static const int GEOMEDIA_POLYLINE       = 0xC2;
+static const int GEOMEDIA_POLYGON        = 0xC3;
+static const int GEOMEDIA_BOUNDARY       = 0xC5;
+static const int GEOMEDIA_COLLECTION     = 0xC6;
+static const int GEOMEDIA_MULTILINE      = 0xCB;
+static const int GEOMEDIA_MULTIPOLYGON   = 0xCC;
 
 /************************************************************************/
 /*                       OGRCreateFromGeomedia()                        */
@@ -65,14 +64,16 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
     if( nGeomType == GEOMEDIA_POINT ||
         nGeomType == GEOMEDIA_ORIENTED_POINT )
     {
-        if (nBytes < 3 * 8)
+        if( nBytes < 3 * 8 )
             return OGRERR_FAILURE;
 
-        double dfX, dfY, dfZ;
+        double dfX = 0.0;
         memcpy(&dfX, pabyGeom, 8);
         CPL_LSBPTR64(&dfX);
+        double dfY = 0.0;
         memcpy(&dfY, pabyGeom + 8, 8);
         CPL_LSBPTR64(&dfY);
+        double dfZ = 0.0;
         memcpy(&dfZ, pabyGeom + 16, 8);
         CPL_LSBPTR64(&dfZ);
 
@@ -80,30 +81,32 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
 
          return OGRERR_NONE;
     }
-    else if ( nGeomType == GEOMEDIA_POLYLINE )
+    else if( nGeomType == GEOMEDIA_POLYLINE )
     {
-        if (nBytes < 4)
+        if( nBytes < 4 )
             return OGRERR_FAILURE;
 
-        int nPoints;
+        int nPoints = 0;
         memcpy(&nPoints, pabyGeom, 4);
         CPL_LSBPTR32(&nPoints);
 
         pabyGeom += 4;
         nBytes -= 4;
 
-        if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
+        if( nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24 )
             return OGRERR_FAILURE;
 
         OGRLineString* poLS = new OGRLineString();
         poLS->setNumPoints(nPoints);
-        for(int i=0;i<nPoints;i++)
+        for( int i = 0; i < nPoints; i++ )
         {
-            double dfX, dfY, dfZ;
+            double dfX = 0.0;
             memcpy(&dfX, pabyGeom, 8);
             CPL_LSBPTR64(&dfX);
+            double dfY = 0.0;
             memcpy(&dfY, pabyGeom + 8, 8);
             CPL_LSBPTR64(&dfY);
+            double dfZ = 0.0;
             memcpy(&dfZ, pabyGeom + 16, 8);
             CPL_LSBPTR64(&dfZ);
 
@@ -116,24 +119,24 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
 
         return OGRERR_NONE;
     }
-    else if ( nGeomType == GEOMEDIA_POLYGON )
+    else if( nGeomType == GEOMEDIA_POLYGON )
     {
-        if (nBytes < 4)
+        if( nBytes < 4 )
             return OGRERR_FAILURE;
 
-        int nPoints;
+        int nPoints = 0;
         memcpy(&nPoints, pabyGeom, 4);
         CPL_LSBPTR32(&nPoints);
 
         pabyGeom += 4;
         nBytes -= 4;
 
-        if (nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24)
+        if( nPoints < 0 || nPoints > INT_MAX / 24 || nBytes < nPoints * 24 )
             return OGRERR_FAILURE;
 
         OGRLinearRing* poRing = new OGRLinearRing();
         poRing->setNumPoints(nPoints);
-        for(int i=0;i<nPoints;i++)
+        for( int i = 0; i < nPoints; i++ )
         {
             double dfX, dfY, dfZ;
             memcpy(&dfX, pabyGeom, 8);
@@ -154,9 +157,9 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
 
         return OGRERR_NONE;
     }
-    else if ( nGeomType == GEOMEDIA_BOUNDARY )
+    else if( nGeomType == GEOMEDIA_BOUNDARY )
     {
-        if (nBytes < 4)
+        if( nBytes < 4 )
             return OGRERR_FAILURE;
 
         int nExteriorSize;
@@ -166,14 +169,15 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
         pabyGeom += 4;
         nBytes -= 4;
 
-        if (nBytes < nExteriorSize)
+        if( nBytes < nExteriorSize )
             return OGRERR_FAILURE;
 
         OGRGeometry* poExteriorGeom = NULL;
-        if (OGRCreateFromGeomedia( pabyGeom, &poExteriorGeom, nExteriorSize ) != OGRERR_NONE)
+        if( OGRCreateFromGeomedia( pabyGeom, &poExteriorGeom,
+                                   nExteriorSize ) != OGRERR_NONE )
             return OGRERR_FAILURE;
 
-        if ( wkbFlatten( poExteriorGeom->getGeometryType() ) != wkbPolygon )
+        if( wkbFlatten( poExteriorGeom->getGeometryType() ) != wkbPolygon )
         {
             delete poExteriorGeom;
             return OGRERR_FAILURE;
@@ -182,7 +186,7 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
         pabyGeom += nExteriorSize;
         nBytes -= nExteriorSize;
 
-        if (nBytes < 4)
+        if( nBytes < 4 )
         {
             delete poExteriorGeom;
             return OGRERR_FAILURE;
@@ -195,28 +199,31 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
         pabyGeom += 4;
         nBytes -= 4;
 
-        if (nBytes < nInteriorSize)
+        if( nBytes < nInteriorSize )
         {
             delete poExteriorGeom;
             return OGRERR_FAILURE;
         }
 
         OGRGeometry* poInteriorGeom = NULL;
-        if (OGRCreateFromGeomedia( pabyGeom, &poInteriorGeom, nInteriorSize ) != OGRERR_NONE)
+        if( OGRCreateFromGeomedia( pabyGeom, &poInteriorGeom,
+                                   nInteriorSize ) != OGRERR_NONE )
         {
             delete poExteriorGeom;
             return OGRERR_FAILURE;
         }
 
-        OGRwkbGeometryType interiorGeomType = wkbFlatten( poInteriorGeom->getGeometryType() );
-        if ( interiorGeomType == wkbPolygon )
+        const OGRwkbGeometryType interiorGeomType =
+            wkbFlatten( poInteriorGeom->getGeometryType() );
+        if( interiorGeomType == wkbPolygon )
         {
-            ((OGRPolygon*)poExteriorGeom)->addRing(((OGRPolygon*)poInteriorGeom)->getExteriorRing());
+            ((OGRPolygon*)poExteriorGeom)->
+                addRing(((OGRPolygon*)poInteriorGeom)->getExteriorRing());
         }
-        else if ( interiorGeomType == wkbMultiPolygon )
+        else if( interiorGeomType == wkbMultiPolygon )
         {
             const int numGeom = ((OGRMultiPolygon*)poInteriorGeom)->getNumGeometries();
-            for ( int i = 0; i < numGeom; ++i )
+            for( int i = 0; i < numGeom; ++i )
             {
                 OGRPolygon* poInteriorPolygon =
                     (OGRPolygon*)((OGRMultiPolygon*)poInteriorGeom)->getGeometryRef(i);
@@ -235,11 +242,11 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
 
         return OGRERR_NONE;
     }
-    else if ( nGeomType == GEOMEDIA_COLLECTION ||
-              nGeomType == GEOMEDIA_MULTILINE ||
-              nGeomType == GEOMEDIA_MULTIPOLYGON )
+    else if( nGeomType == GEOMEDIA_COLLECTION ||
+             nGeomType == GEOMEDIA_MULTILINE ||
+             nGeomType == GEOMEDIA_MULTIPOLYGON )
     {
-        if (nBytes < 4)
+        if( nBytes < 4 )
             return OGRERR_FAILURE;
 
         int nParts;
@@ -249,11 +256,12 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
         pabyGeom += 4;
         nBytes -= 4;
 
-        if (nParts < 0 || nParts > INT_MAX / (4 + 16) || nBytes < nParts * (4 + 16))
+        if( nParts < 0 || nParts > INT_MAX / (4 + 16) ||
+            nBytes < nParts * (4 + 16) )
             return OGRERR_FAILURE;
 
-        /* Can this collection be considered as a multipolyline or multipolygon ? */
-        if ( nGeomType == GEOMEDIA_COLLECTION )
+        // Can this collection be considered as a multipolyline or multipolygon?
+        if( nGeomType == GEOMEDIA_COLLECTION )
         {
             GByte* pabyGeomBackup = pabyGeom;
             int nBytesBackup = nBytes;
@@ -261,15 +269,15 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
             bool bAllPolyline = true;
             bool bAllPolygon = true;
 
-            for(int i=0;i<nParts;i++)
+            for( int i = 0; i < nParts; i++ )
             {
-                if (nBytes < 4)
+                if( nBytes < 4 )
                     return OGRERR_FAILURE;
-                int nSubBytes;
+                int nSubBytes = 0;
                 memcpy(&nSubBytes, pabyGeom, 4);
                 CPL_LSBPTR32(&nSubBytes);
 
-                if (nSubBytes < 0)
+                if( nSubBytes < 0 )
                 {
                     return OGRERR_FAILURE;
                 }
@@ -277,7 +285,7 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
                 pabyGeom += 4;
                 nBytes -= 4;
 
-                if (nBytes < nSubBytes)
+                if( nBytes < nSubBytes )
                 {
                     return OGRERR_FAILURE;
                 }
@@ -285,13 +293,14 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
                 if( nSubBytes < 16 )
                     return OGRERR_FAILURE;
 
-                if( !(pabyGeom[1] == 0xFF && pabyGeom[2] == 0xD2 && pabyGeom[3] == 0x0F) )
+                if( !(pabyGeom[1] == 0xFF && pabyGeom[2] ==
+                      0xD2 && pabyGeom[3] == 0x0F) )
                     return OGRERR_FAILURE;
 
                 int nSubGeomType = pabyGeom[0];
-                if ( nSubGeomType != GEOMEDIA_POLYLINE )
+                if( nSubGeomType != GEOMEDIA_POLYLINE )
                     bAllPolyline = false;
-                if ( nSubGeomType != GEOMEDIA_POLYGON )
+                if( nSubGeomType != GEOMEDIA_POLYGON )
                     bAllPolygon = false;
 
                 pabyGeom += nSubBytes;
@@ -301,19 +310,20 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
             pabyGeom = pabyGeomBackup;
             nBytes = nBytesBackup;
 
-            if (bAllPolyline)
+            if( bAllPolyline )
                 nGeomType = GEOMEDIA_MULTILINE;
-            else if (bAllPolygon)
+            else if( bAllPolygon )
                 nGeomType = GEOMEDIA_MULTIPOLYGON;
         }
 
-        OGRGeometryCollection* poColl = (nGeomType == GEOMEDIA_MULTILINE) ? new OGRMultiLineString() :
-                                        (nGeomType == GEOMEDIA_MULTIPOLYGON) ? new OGRMultiPolygon() :
-                                                              new OGRGeometryCollection();
+        OGRGeometryCollection* poColl =
+            nGeomType == GEOMEDIA_MULTILINE ? new OGRMultiLineString() :
+            nGeomType == GEOMEDIA_MULTIPOLYGON ? new OGRMultiPolygon() :
+            new OGRGeometryCollection();
 
-        for(int i=0;i<nParts;i++)
+        for( int i = 0; i < nParts; i++ )
         {
-            if (nBytes < 4)
+            if( nBytes < 4 )
             {
                 delete poColl;
                 return OGRERR_FAILURE;
@@ -322,7 +332,7 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
             memcpy(&nSubBytes, pabyGeom, 4);
             CPL_LSBPTR32(&nSubBytes);
 
-            if (nSubBytes < 0)
+            if( nSubBytes < 0 )
             {
                 delete poColl;
                 return OGRERR_FAILURE;
@@ -331,17 +341,18 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
             pabyGeom += 4;
             nBytes -= 4;
 
-            if (nBytes < nSubBytes)
+            if( nBytes < nSubBytes )
             {
                 delete poColl;
                 return OGRERR_FAILURE;
             }
 
             OGRGeometry* poSubGeom = NULL;
-            if (OGRCreateFromGeomedia( pabyGeom, &poSubGeom, nSubBytes ) == OGRERR_NONE)
+            if( OGRCreateFromGeomedia( pabyGeom, &poSubGeom,
+                                       nSubBytes ) == OGRERR_NONE )
             {
-                if (wkbFlatten(poColl->getGeometryType()) == wkbMultiPolygon &&
-                    wkbFlatten(poSubGeom->getGeometryType()) == wkbLineString)
+                if( wkbFlatten(poColl->getGeometryType()) == wkbMultiPolygon &&
+                    wkbFlatten(poSubGeom->getGeometryType()) == wkbLineString )
                 {
                     OGRPolygon* poPoly = new OGRPolygon();
                     OGRLinearRing* poRing = new OGRLinearRing();
@@ -351,7 +362,7 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
                     poSubGeom = poPoly;
                 }
 
-                if (poColl->addGeometryDirectly(poSubGeom) != OGRERR_NONE)
+                if( poColl->addGeometryDirectly(poSubGeom) != OGRERR_NONE )
                 {
                     delete poSubGeom;
                 }
@@ -373,43 +384,41 @@ OGRErr OGRCreateFromGeomedia( GByte *pabyGeom,
     return OGRERR_FAILURE;
 }
 
-
 /************************************************************************/
 /*                         OGRGetGeomediaSRS()                          */
 /************************************************************************/
 
 OGRSpatialReference* OGRGetGeomediaSRS(OGRFeature* poFeature)
 {
-    if (poFeature == NULL)
+    if( poFeature == NULL )
         return NULL;
 
-    int nGeodeticDatum = poFeature->GetFieldAsInteger("GeodeticDatum");
-    int nEllipsoid = poFeature->GetFieldAsInteger("Ellipsoid");
-    int nProjAlgorithm = poFeature->GetFieldAsInteger("ProjAlgorithm");
+    const int nGeodeticDatum = poFeature->GetFieldAsInteger("GeodeticDatum");
+    const int nEllipsoid = poFeature->GetFieldAsInteger("Ellipsoid");
+    const int nProjAlgorithm = poFeature->GetFieldAsInteger("ProjAlgorithm");
 
-    if (nGeodeticDatum == 17 && nEllipsoid == 22)
-    {
-        if (nProjAlgorithm == 12)
-        {
-            OGRSpatialReference* poSRS = new OGRSpatialReference();
-
-            const char* pszDescription = poFeature->GetFieldAsString("Description");
-            if (pszDescription && pszDescription[0] != 0)
-                poSRS->SetNode( "PROJCS", pszDescription );
-            poSRS->SetWellKnownGeogCS("WGS84");
-
-            double dfStdP1 = poFeature->GetFieldAsDouble("StandPar1");
-            double dfStdP2 = poFeature->GetFieldAsDouble("StandPar2");
-            double dfCenterLat = poFeature->GetFieldAsDouble("LatOfOrigin");
-            double dfCenterLong = poFeature->GetFieldAsDouble("LonOfOrigin");
-            double dfFalseEasting = poFeature->GetFieldAsDouble("FalseX");
-            double dfFalseNorthing = poFeature->GetFieldAsDouble("FalseY");
-            poSRS->SetACEA( dfStdP1, dfStdP2,
-                            dfCenterLat, dfCenterLong,
-                            dfFalseEasting, dfFalseNorthing );
-            return poSRS;
-        }
-    }
+    if( !(nGeodeticDatum == 17 && nEllipsoid == 22) )
+        return NULL;
+
+    if( nProjAlgorithm != 12 )
+        return NULL;
 
-    return NULL;
+    OGRSpatialReference* poSRS = new OGRSpatialReference();
+
+    const char* pszDescription =
+        poFeature->GetFieldAsString("Description");
+    if( pszDescription && pszDescription[0] != 0 )
+        poSRS->SetNode( "PROJCS", pszDescription );
+    poSRS->SetWellKnownGeogCS("WGS84");
+
+    const double dfStdP1 = poFeature->GetFieldAsDouble("StandPar1");
+    const double dfStdP2 = poFeature->GetFieldAsDouble("StandPar2");
+    const double dfCenterLat = poFeature->GetFieldAsDouble("LatOfOrigin");
+    const double dfCenterLong = poFeature->GetFieldAsDouble("LonOfOrigin");
+    const double dfFalseEasting = poFeature->GetFieldAsDouble("FalseX");
+    const double dfFalseNorthing = poFeature->GetFieldAsDouble("FalseY");
+    poSRS->SetACEA( dfStdP1, dfStdP2,
+                    dfCenterLat, dfCenterLong,
+                    dfFalseEasting, dfFalseNorthing );
+    return poSRS;
 }
diff --git a/ogr/ogrgeometry.cpp b/ogr/ogrgeometry.cpp
index 23f2511..d65f202 100644
--- a/ogr/ogrgeometry.cpp
+++ b/ogr/ogrgeometry.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeometry.cpp 35500 2016-09-23 14:10:22Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements a few base methods on OGRGeometry.
@@ -28,12 +27,28 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
+
+#include <climits>
+#include <cstdarg>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
 #include "ogr_api.h"
-#include "ogr_p.h"
+#include "ogr_core.h"
 #include "ogr_geos.h"
-#include "cpl_multiproc.h"
-#include <assert.h>
+#include "ogr_sfcgal.h"
+#include "ogr_libs.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
 
 #ifndef HAVE_GEOS
 #define UNUSED_IF_NO_GEOS CPL_UNUSED
@@ -41,9 +56,11 @@
 #define UNUSED_IF_NO_GEOS
 #endif
 
-CPL_CVSID("$Id: ogrgeometry.cpp 35500 2016-09-23 14:10:22Z rouault $");
+CPL_CVSID("$Id: ogrgeometry.cpp 37004 2016-12-23 14:57:46Z goatbar $");
 
+//! @cond Doxygen_Suppress
 int OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER = FALSE;
+//! @endcond
 
 #ifdef HAVE_GEOS
 static void OGRGEOSErrorHandler(const char *fmt, ...)
@@ -132,16 +149,6 @@ OGRGeometry& OGRGeometry::operator=( const OGRGeometry& other )
 }
 
 /************************************************************************/
-/*                               IsEmpty()                              */
-/************************************************************************/
-
-OGRBoolean OGRGeometry::IsEmpty() const
-{
-    fprintf(stderr, "Missing IsEmpty method for a class.\n");
-    exit(1);
-}
-
-/************************************************************************/
 /*                            dumpReadable()                            */
 /************************************************************************/
 
@@ -162,11 +169,10 @@ OGRBoolean OGRGeometry::IsEmpty() const
  * @param papszOptions NULL terminated list of options (may be NULL)
  */
 
-void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszOptions ) const
+void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix,
+                                char** papszOptions ) const
 
 {
-    char        *pszWkt = NULL;
-
     if( pszPrefix == NULL )
         pszPrefix = "";
 
@@ -174,13 +180,9 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
         fp = stdout;
 
     const char* pszDisplayGeometry =
-                CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
-    if (pszDisplayGeometry != NULL && EQUAL(pszDisplayGeometry, "SUMMARY"))
+        CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
+    if( pszDisplayGeometry != NULL && EQUAL(pszDisplayGeometry, "SUMMARY") )
     {
-        OGRLineString *poLine;
-        OGRCurvePolygon *poPoly;
-        OGRCurve *poRing;
-        OGRGeometryCollection *poColl;
         fprintf( fp, "%s%s : ", pszPrefix, getGeometryName() );
         switch( getGeometryType() )
         {
@@ -190,20 +192,27 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
             case wkbPoint25D:
             case wkbPointM:
             case wkbPointZM:
-            case wkbPolyhedralSurface: /* not yet implemented */
-            case wkbTIN: /* not yet implemented */
-            case wkbPolyhedralSurfaceZ: /* not yet implemented */
-            case wkbTINZ: /* not yet implemented */
-            case wkbPolyhedralSurfaceM: /* not yet implemented */
-            case wkbTINM: /* not yet implemented */
-            case wkbPolyhedralSurfaceZM: /* not yet implemented */
-            case wkbTINZM: /* not yet implemented */
-            case wkbTriangle: /* not yet implemented */
-            case wkbTriangleZ: /* not yet implemented */
-            case wkbTriangleM: /* not yet implemented */
-            case wkbTriangleZM: /* not yet implemented */
-                fprintf( fp, "\n");
                 break;
+            case wkbPolyhedralSurface:
+            case wkbTIN:
+            case wkbPolyhedralSurfaceZ:
+            case wkbTINZ:
+            case wkbPolyhedralSurfaceM:
+            case wkbTINM:
+            case wkbPolyhedralSurfaceZM:
+            case wkbTINZM:
+            {
+                int ig;
+                OGRPolyhedralSurface* poPS = (OGRPolyhedralSurface *)this;
+                fprintf( fp, "%d geometries:\n", poPS->getNumGeometries() );
+                for ( ig = 0; ig < poPS->getNumGeometries(); ig++)
+                {
+                    const OGRGeometry *poChild = poPS->getGeometryRef(ig);
+                    fprintf( fp, "%s", pszPrefix);
+                    poChild->dumpReadable( fp, pszPrefix, papszOptions );
+                }
+                break;
+            }
             case wkbLineString:
             case wkbLineString25D:
             case wkbLineStringM:
@@ -212,10 +221,23 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
             case wkbCircularStringZ:
             case wkbCircularStringM:
             case wkbCircularStringZM:
-                poLine = (OGRLineString*)this;
+            {
+                OGRLineString *poLine = dynamic_cast<OGRLineString *>(
+                    const_cast<OGRGeometry *>(this));
+                if( poLine == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                             "dynamic_cast failed.  Expected OGRLineString.");
+                    return;
+                }
                 fprintf( fp, "%d points\n", poLine->getNumPoints() );
                 break;
+            }
             case wkbPolygon:
+            case wkbTriangle:
+            case wkbTriangleZ:
+            case wkbTriangleM:
+            case wkbTriangleZM:
             case wkbPolygon25D:
             case wkbPolygonM:
             case wkbPolygonZM:
@@ -224,32 +246,42 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
             case wkbCurvePolygonM:
             case wkbCurvePolygonZM:
             {
-                int ir;
-                int nRings;
-                poPoly = (OGRCurvePolygon*)this;
-                poRing = poPoly->getExteriorRingCurve();
-                nRings = poPoly->getNumInteriorRings();
-                if (poRing == NULL)
+                OGRCurvePolygon *poPoly = dynamic_cast<OGRCurvePolygon *>(
+                    const_cast<OGRGeometry *>(this));
+                if( poPoly == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                             "dynamic_cast failed.  Expected OGRCurvePolygon.");
+                    return;
+                }
+
+                OGRCurve *poRing = poPoly->getExteriorRingCurve();
+                const int nRings = poPoly->getNumInteriorRings();
+                if( poRing == NULL )
+                {
                     fprintf( fp, "empty");
+                }
                 else
                 {
                     fprintf( fp, "%d points", poRing->getNumPoints() );
-                    if( wkbFlatten(poRing->getGeometryType()) == wkbCompoundCurve )
+                    if( wkbFlatten(poRing->getGeometryType()) ==
+                        wkbCompoundCurve )
                     {
                         fprintf( fp, " (");
                         poRing->dumpReadable(fp, NULL, papszOptions);
                         fprintf( fp, ")");
                     }
-                    if (nRings)
+                    if( nRings )
                     {
                         fprintf( fp, ", %d inner rings (", nRings);
-                        for( ir = 0; ir < nRings; ir++)
+                        for( int ir = 0; ir < nRings; ir++ )
                         {
                             poRing = poPoly->getInteriorRingCurve(ir);
-                            if (ir)
+                            if( ir )
                                 fprintf( fp, ", ");
                             fprintf( fp, "%d points", poRing->getNumPoints() );
-                            if( wkbFlatten(poRing->getGeometryType()) == wkbCompoundCurve )
+                            if( wkbFlatten(poRing->getGeometryType()) ==
+                                wkbCompoundCurve )
                             {
                                 fprintf( fp, " (");
                                 poRing->dumpReadable(fp, NULL, papszOptions);
@@ -267,14 +299,24 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
             case wkbCompoundCurveM:
             case wkbCompoundCurveZM:
             {
-                OGRCompoundCurve* poCC = (OGRCompoundCurve* )this;
+                OGRCompoundCurve* poCC = dynamic_cast<OGRCompoundCurve *>(
+                    const_cast<OGRGeometry *>(this));
+                if( poCC == NULL )
+                {
+                    CPLError(
+                        CE_Fatal, CPLE_AppDefined,
+                        "dynamic_cast failed.  Expected OGRCompoundCurve.");
+                    return;
+                }
                 if( poCC->getNumCurves() == 0 )
+                {
                     fprintf( fp, "empty");
+                }
                 else
                 {
-                    for(int i=0;i<poCC->getNumCurves();i++)
+                    for( int i = 0; i < poCC->getNumCurves(); i++ )
                     {
-                        if (i)
+                        if( i )
                             fprintf( fp, ", ");
                         fprintf( fp, "%s (%d points)",
                                  poCC->getCurve(i)->getGeometryName(),
@@ -309,12 +351,20 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
             case wkbMultiSurfaceZM:
             case wkbGeometryCollectionZM:
             {
-                int ig;
-                poColl = (OGRGeometryCollection*)this;
+                OGRGeometryCollection *poColl =
+                    dynamic_cast<OGRGeometryCollection *>(
+                        const_cast<OGRGeometry *>(this));
+                if( poColl == NULL )
+                {
+                    CPLError(CE_Fatal, CPLE_AppDefined,
+                             "dynamic_cast failed.  "
+                             "Expected OGRGeometryCollection.");
+                    return;
+                }
                 fprintf( fp, "%d geometries:\n", poColl->getNumGeometries() );
-                for ( ig = 0; ig < poColl->getNumGeometries(); ig++)
+                for( int ig = 0; ig < poColl->getNumGeometries(); ig++ )
                 {
-                    OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(ig);
+                    OGRGeometry *poChild = poColl->getGeometryRef(ig);
                     fprintf( fp, "%s", pszPrefix);
                     poChild->dumpReadable( fp, pszPrefix, papszOptions );
                 }
@@ -332,17 +382,20 @@ void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszO
                 break;
         }
     }
-    else if (pszDisplayGeometry != NULL && EQUAL(pszDisplayGeometry, "WKT"))
+    else if( pszDisplayGeometry != NULL && EQUAL(pszDisplayGeometry, "WKT") )
     {
+        char *pszWkt = NULL;
         if( exportToWkt( &pszWkt ) == OGRERR_NONE )
         {
             fprintf( fp, "%s%s\n", pszPrefix, pszWkt );
             CPLFree( pszWkt );
         }
     }
-    else if (pszDisplayGeometry == NULL || CSLTestBoolean(pszDisplayGeometry) ||
-             EQUAL(pszDisplayGeometry, "ISO_WKT"))
+    else if( pszDisplayGeometry == NULL ||
+             CPLTestBool(pszDisplayGeometry) ||
+             EQUAL(pszDisplayGeometry, "ISO_WKT") )
     {
+        char *pszWkt = NULL;
         if( exportToWkt( &pszWkt, wkbVariantIso ) == OGRERR_NONE )
         {
             fprintf( fp, "%s%s\n", pszPrefix, pszWkt );
@@ -369,7 +422,7 @@ void OGR_G_DumpReadable( OGRGeometryH hGeom, FILE *fp, const char *pszPrefix )
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_DumpReadable" );
 
-    ((OGRGeometry *) hGeom)->dumpReadable( fp, pszPrefix );
+    reinterpret_cast<OGRGeometry *>(hGeom)->dumpReadable( fp, pszPrefix );
 }
 
 /************************************************************************/
@@ -424,7 +477,7 @@ void OGRGeometry::assignSpatialReference( OGRSpatialReference * poSR )
  *
  * @param hGeom handle on the geometry to apply the new spatial reference
  * system.
- * @param hSRS handle on the  new spatial reference system to apply.
+ * @param hSRS handle on the new spatial reference system to apply.
  */
 
 void OGR_G_AssignSpatialReference( OGRGeometryH hGeom,
@@ -433,8 +486,8 @@ void OGR_G_AssignSpatialReference( OGRGeometryH hGeom,
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_AssignSpatialReference" );
 
-    ((OGRGeometry *) hGeom)->assignSpatialReference( (OGRSpatialReference *)
-                                                     hSRS );
+    reinterpret_cast<OGRGeometry *>(hGeom)->
+        assignSpatialReference(reinterpret_cast<OGRSpatialReference *>(hSRS));
 }
 
 /************************************************************************/
@@ -462,12 +515,13 @@ void OGR_G_AssignSpatialReference( OGRGeometryH hGeom,
 OGRBoolean OGRGeometry::Intersects( const OGRGeometry *poOtherGeom ) const
 
 {
-    OGREnvelope         oEnv1, oEnv2;
-
     if( poOtherGeom == NULL )
         return TRUE;
 
-    this->getEnvelope( &oEnv1 );
+    OGREnvelope oEnv1;
+    getEnvelope( &oEnv1 );
+
+    OGREnvelope oEnv2;
     poOtherGeom->getEnvelope( &oEnv2 );
 
     if( oEnv1.MaxX < oEnv2.MinX
@@ -482,20 +536,16 @@ OGRBoolean OGRGeometry::Intersects( const OGRGeometry *poOtherGeom ) const
     return TRUE;
 #else
 
-    GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hOtherGeosGeom = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
-    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
+    GEOSGeom hThisGeosGeom  = exportToGEOS(hGEOSCtxt);
+    GEOSGeom hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
 
     OGRBoolean bResult = FALSE;
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        if( GEOSIntersects_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom ) != 0 )
-            bResult = TRUE;
-        else
-            bResult = FALSE;
+        bResult =
+            GEOSIntersects_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom ) != 0;
     }
 
     GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
@@ -503,16 +553,18 @@ OGRBoolean OGRGeometry::Intersects( const OGRGeometry *poOtherGeom ) const
     freeGEOSContext( hGEOSCtxt );
 
     return bResult;
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 // Old API compatibility function.
 
+//! @cond Doxygen_Suppress
 OGRBoolean OGRGeometry::Intersect( OGRGeometry *poOtherGeom ) const
 
 {
     return Intersects( poOtherGeom );
 }
+//! @endcond
 
 /************************************************************************/
 /*                          OGR_G_Intersects()                          */
@@ -538,17 +590,21 @@ int OGR_G_Intersects( OGRGeometryH hGeom, OGRGeometryH hOtherGeom )
     VALIDATE_POINTER1( hGeom, "OGR_G_Intersects", FALSE );
     VALIDATE_POINTER1( hOtherGeom, "OGR_G_Intersects", FALSE );
 
-    return ((OGRGeometry *) hGeom)->Intersects( (const OGRGeometry *) hOtherGeom );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        Intersects( reinterpret_cast<OGRGeometry *>(hOtherGeom) );
 }
 
+//! @cond Doxygen_Suppress
 int OGR_G_Intersect( OGRGeometryH hGeom, OGRGeometryH hOtherGeom )
 
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_Intersect", FALSE );
     VALIDATE_POINTER1( hOtherGeom, "OGR_G_Intersect", FALSE );
 
-    return ((OGRGeometry *) hGeom)->Intersects( (const OGRGeometry *) hOtherGeom );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        Intersects( reinterpret_cast<OGRGeometry *>(hOtherGeom));
 }
+//! @endcond
 
 /************************************************************************/
 /*                            transformTo()                             */
@@ -583,25 +639,19 @@ int OGR_G_Intersect( OGRGeometryH hGeom, OGRGeometryH hOtherGeom )
 OGRErr OGRGeometry::transformTo( OGRSpatialReference *poSR )
 
 {
-#ifdef DISABLE_OGRGEOM_TRANSFORM
-    return OGRERR_FAILURE;
-#else
-    OGRCoordinateTransformation *poCT;
-    OGRErr eErr;
-
     if( getSpatialReference() == NULL || poSR == NULL )
         return OGRERR_FAILURE;
 
-    poCT = OGRCreateCoordinateTransformation( getSpatialReference(), poSR );
+    OGRCoordinateTransformation *poCT =
+        OGRCreateCoordinateTransformation( getSpatialReference(), poSR );
     if( poCT == NULL )
         return OGRERR_FAILURE;
 
-    eErr = transform( poCT );
+    const OGRErr eErr = transform( poCT );
 
     delete poCT;
 
     return eErr;
-#endif
 }
 
 /************************************************************************/
@@ -639,7 +689,8 @@ OGRErr OGR_G_TransformTo( OGRGeometryH hGeom, OGRSpatialReferenceH hSRS )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_TransformTo", OGRERR_FAILURE );
 
-    return ((OGRGeometry *) hGeom)->transformTo((OGRSpatialReference *) hSRS);
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        transformTo(reinterpret_cast<OGRSpatialReference *>(hSRS));
 }
 
 /**
@@ -698,8 +749,8 @@ OGRErr OGR_G_Transform( OGRGeometryH hGeom,
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_Transform", OGRERR_FAILURE );
 
-    return ((OGRGeometry *) hGeom)->transform(
-        (OGRCoordinateTransformation *) hTransform );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        transform(reinterpret_cast<OGRCoordinateTransformation *>(hTransform));
 }
 
 /**
@@ -717,7 +768,6 @@ OGRErr OGR_G_Transform( OGRGeometryH hGeom,
  * @return 0 for points, 1 for lines and 2 for surfaces.
  */
 
-
 /**
  * \brief Get the geometry type that conforms with ISO SQL/MM Part3
  *
@@ -727,10 +777,10 @@ OGRwkbGeometryType OGRGeometry::getIsoGeometryType() const
 {
     OGRwkbGeometryType nGType = wkbFlatten(getGeometryType());
 
-    if ( flags & OGR_G_3D )
-        nGType = (OGRwkbGeometryType)(nGType + 1000);
-    if ( flags & OGR_G_MEASURED )
-        nGType = (OGRwkbGeometryType)(nGType + 2000);
+    if( flags & OGR_G_3D )
+        nGType = static_cast<OGRwkbGeometryType>(nGType + 1000);
+    if( flags & OGR_G_MEASURED )
+        nGType = static_cast<OGRwkbGeometryType>(nGType + 2000);
 
     return nGType;
 }
@@ -740,7 +790,8 @@ OGRwkbGeometryType OGRGeometry::getIsoGeometryType() const
 /************************************************************************/
 /**
  *
- * \brief Modify the geometry such it has no segment longer then the given distance.
+ * \brief Modify the geometry such it has no segment longer then the
+ * given distance.
  *
  * Interpolated points will have Z and M values (if needed) set to 0.
  * Distance computation is performed in 2d only
@@ -752,7 +803,7 @@ OGRwkbGeometryType OGRGeometry::getIsoGeometryType() const
 
 void OGRGeometry::segmentize( CPL_UNUSED double dfMaxLength )
 {
-    /* Do nothing */
+    // Do nothing.
 }
 
 /************************************************************************/
@@ -761,10 +812,11 @@ void OGRGeometry::segmentize( CPL_UNUSED double dfMaxLength )
 
 /**
  *
- * \brief Modify the geometry such it has no segment longer then the given distance.
+ * \brief Modify the geometry such it has no segment longer then the given
+ * distance.
  *
  * Interpolated points will have Z and M values (if needed) set to 0.
- * Distance computation is performed in 2d only
+ * Distance computation is performed in 2d only.
  *
  * This function is the same as the CPP method OGRGeometry::segmentize().
  *
@@ -772,17 +824,17 @@ void OGRGeometry::segmentize( CPL_UNUSED double dfMaxLength )
  * @param dfMaxLength the maximum distance between 2 points after segmentization
  */
 
-void   CPL_DLL OGR_G_Segmentize(OGRGeometryH hGeom, double dfMaxLength )
+void CPL_DLL OGR_G_Segmentize( OGRGeometryH hGeom, double dfMaxLength )
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_Segmentize" );
 
-    if (dfMaxLength <= 0)
+    if( dfMaxLength <= 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "dfMaxLength must be strictly positive");
         return;
     }
-    ((OGRGeometry *) hGeom)->segmentize( dfMaxLength );
+    reinterpret_cast<OGRGeometry *>(hGeom)->segmentize( dfMaxLength );
 }
 
 /************************************************************************/
@@ -808,7 +860,7 @@ int OGR_G_GetDimension( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetDimension", 0 );
 
-    return ((OGRGeometry *) hGeom)->getDimension();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->getDimension();
 }
 
 /************************************************************************/
@@ -867,7 +919,8 @@ int OGRGeometry::CoordinateDimension() const
  * @param hGeom handle on the geometry to get the dimension of the
  * coordinates from.
  *
- * @deprecated use OGR_G_CoordinateDimension(), OGR_G_Is3D(), or OGR_G_IsMeasured().
+ * @deprecated use OGR_G_CoordinateDimension(), OGR_G_Is3D(), or
+ * OGR_G_IsMeasured().
  *
  * @return this will return 2 or 3.
  */
@@ -877,7 +930,7 @@ int OGR_G_GetCoordinateDimension( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetCoordinateDimension", 0 );
 
-    return ((OGRGeometry *) hGeom)->getCoordinateDimension();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->getCoordinateDimension();
 }
 
 /************************************************************************/
@@ -903,7 +956,7 @@ int OGR_G_CoordinateDimension( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_CoordinateDimension", 0 );
 
-    return ((OGRGeometry *) hGeom)->CoordinateDimension();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->CoordinateDimension();
 }
 
 /**
@@ -924,7 +977,7 @@ int OGR_G_Is3D( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_Is3D", 0 );
 
-    return ((OGRGeometry *) hGeom)->Is3D();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->Is3D();
 }
 
 /**
@@ -945,7 +998,7 @@ int OGR_G_IsMeasured( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_IsMeasured", 0 );
 
-    return ((OGRGeometry *) hGeom)->IsMeasured();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->IsMeasured();
 }
 
 /************************************************************************/
@@ -992,7 +1045,7 @@ void OGRGeometry::setCoordinateDimension( int nNewDimension )
 void OGRGeometry::set3D( OGRBoolean bIs3D )
 
 {
-    if (bIs3D)
+    if( bIs3D )
         flags |= OGR_G_3D;
     else
         flags &= ~OGR_G_3D;
@@ -1007,14 +1060,15 @@ void OGRGeometry::set3D( OGRBoolean bIs3D )
  * collection, a compound curve, a polygon, etc.  will affect the
  * children geometries.
  *
- * @param bIsMeasured Should the geometry have a M dimension, either TRUE or FALSE.
+ * @param bIsMeasured Should the geometry have a M dimension, either
+ * TRUE or FALSE.
  * @since GDAL 2.1
  */
 
 void OGRGeometry::setMeasured( OGRBoolean bIsMeasured )
 
 {
-    if (bIsMeasured)
+    if( bIsMeasured )
         flags |= OGR_G_MEASURED;
     else
         flags &= ~OGR_G_MEASURED;
@@ -1045,7 +1099,8 @@ void OGR_G_SetCoordinateDimension( OGRGeometryH hGeom, int nNewDimension)
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_SetCoordinateDimension" );
 
-    ((OGRGeometry *) hGeom)->setCoordinateDimension( nNewDimension );
+    reinterpret_cast<OGRGeometry *>(hGeom)->
+        setCoordinateDimension(nNewDimension);
 }
 
 /************************************************************************/
@@ -1071,7 +1126,7 @@ void OGR_G_Set3D( OGRGeometryH hGeom, int bIs3D)
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_Set3D" );
 
-    ((OGRGeometry *) hGeom)->set3D( bIs3D );
+    reinterpret_cast<OGRGeometry *>(hGeom)->set3D(bIs3D);
 }
 
 /************************************************************************/
@@ -1079,8 +1134,6 @@ void OGR_G_Set3D( OGRGeometryH hGeom, int bIs3D)
 /************************************************************************/
 
 /**
- * \brief Set the coordinate dimension.
- *
  * \brief Add or remove the M coordinate dimension.
  *
  * This method adds or removes the explicit M coordinate dimension.
@@ -1090,16 +1143,17 @@ void OGR_G_Set3D( OGRGeometryH hGeom, int bIs3D)
  * children geometries.
  *
  * @param hGeom handle on the geometry to set or unset the M dimension.
- * @param bIsMeasured Should the geometry have a M dimension, either TRUE or FALSE.
+ * @param bIsMeasured Should the geometry have a M dimension, either
+ * TRUE or FALSE.
  * @since GDAL 2.1
  */
 
-void OGR_G_SetMeasured( OGRGeometryH hGeom, int bIsMeasured)
+void OGR_G_SetMeasured( OGRGeometryH hGeom, int bIsMeasured )
 
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_SetMeasured" );
 
-    ((OGRGeometry *) hGeom)->setMeasured( bIsMeasured );
+    reinterpret_cast<OGRGeometry *>(hGeom)->setMeasured(bIsMeasured);
 }
 
 /**
@@ -1107,18 +1161,29 @@ void OGR_G_SetMeasured( OGRGeometryH hGeom, int bIsMeasured)
  *
  * \brief Returns TRUE if two geometries are equivalent.
  *
+ * This operation implements the SQL/MM ST_OrderingEquals() operation.
+ *
+ * The comparison is done in a structural way, that is to say that the geometry
+ * types must be identical, as well as the number and ordering of sub-geometries
+ * and vertices.
+ * Or equivalently, two geometries are considered equal by this method if their
+ * WKT/WKB representation is equal.
+ * Note: this must be distinguished for equality in a spatial way (which is
+ * the purpose of the ST_Equals() operation).
+ *
  * This method is the same as the C function OGR_G_Equals().
  *
  * @return TRUE if equivalent or FALSE otherwise.
  */
 
-
 // Backward compatibility method.
 
+//! @cond Doxygen_Suppress
 int OGRGeometry::Equal( OGRGeometry *poOtherGeom ) const
 {
     return Equals( poOtherGeom );
 }
+//! @endcond
 
 /************************************************************************/
 /*                            OGR_G_Equals()                            */
@@ -1127,6 +1192,16 @@ int OGRGeometry::Equal( OGRGeometry *poOtherGeom ) const
 /**
  * \brief Returns TRUE if two geometries are equivalent.
  *
+ * This operation implements the SQL/MM ST_OrderingEquals() operation.
+ *
+ * The comparison is done in a structural way, that is to say that the geometry
+ * types must be identical, as well as the number and ordering of sub-geometries
+ * and vertices.
+ * Or equivalently, two geometries are considered equal by this method if their
+ * WKT/WKB representation is equal.
+ * Note: this must be distinguished for equality in a spatial way (which is
+ * the purpose of the ST_Equals() operation).
+ *
  * This function is the same as the CPP method OGRGeometry::Equals() method.
  *
  * @param hGeom handle on the first geometry.
@@ -1139,30 +1214,39 @@ int OGR_G_Equals( OGRGeometryH hGeom, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_Equals", FALSE );
 
-    if (hOther == NULL) {
-        CPLError ( CE_Failure, CPLE_ObjectNull, "hOther was NULL in OGR_G_Equals");
+    if( hOther == NULL )
+    {
+        CPLError ( CE_Failure, CPLE_ObjectNull,
+                   "hOther was NULL in OGR_G_Equals");
         return 0;
     }
 
-    return ((OGRGeometry *) hGeom)->Equals( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        Equals(reinterpret_cast<OGRGeometry *>(hOther));
 }
 
+//! @cond Doxygen_Suppress
 int OGR_G_Equal( OGRGeometryH hGeom, OGRGeometryH hOther )
 
 {
-    if (hGeom == NULL) {
-        CPLError ( CE_Failure, CPLE_ObjectNull, "hGeom was NULL in OGR_G_Equal");
+    if( hGeom == NULL )
+    {
+        CPLError(CE_Failure, CPLE_ObjectNull,
+                  "hGeom was NULL in OGR_G_Equal");
         return 0;
     }
 
-    if (hOther == NULL) {
-        CPLError ( CE_Failure, CPLE_ObjectNull, "hOther was NULL in OGR_G_Equal");
+    if( hOther == NULL )
+    {
+        CPLError(CE_Failure, CPLE_ObjectNull,
+                 "hOther was NULL in OGR_G_Equal");
         return 0;
     }
 
-    return ((OGRGeometry *) hGeom)->Equals( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        Equals(reinterpret_cast<OGRGeometry *>(hOther));
 }
-
+//! @endcond
 
 /**
  * \fn int OGRGeometry::WkbSize() const;
@@ -1203,13 +1287,14 @@ int OGR_G_WkbSize( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_WkbSize", 0 );
 
-    return ((OGRGeometry *) hGeom)->WkbSize();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->WkbSize();
 }
 
 /**
  * \fn void OGRGeometry::getEnvelope(OGREnvelope *psEnvelope) const;
  *
- * \brief Computes and returns the bounding envelope for this geometry in the passed psEnvelope structure.
+ * \brief Computes and returns the bounding envelope for this geometry
+ * in the passed psEnvelope structure.
  *
  * This method is the same as the C function OGR_G_GetEnvelope().
  *
@@ -1220,7 +1305,8 @@ int OGR_G_WkbSize( OGRGeometryH hGeom )
 /*                         OGR_G_GetEnvelope()                          */
 /************************************************************************/
 /**
- * \brief Computes and returns the bounding envelope for this geometry in the passed psEnvelope structure.
+ * \brief Computes and returns the bounding envelope for this geometry
+ * in the passed psEnvelope structure.
  *
  * This function is the same as the CPP method OGRGeometry::getEnvelope().
  *
@@ -1233,13 +1319,14 @@ void OGR_G_GetEnvelope( OGRGeometryH hGeom, OGREnvelope *psEnvelope )
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_GetEnvelope" );
 
-    ((OGRGeometry *) hGeom)->getEnvelope( psEnvelope );
+    reinterpret_cast<OGRGeometry *>(hGeom)->getEnvelope( psEnvelope );
 }
 
 /**
  * \fn void OGRGeometry::getEnvelope(OGREnvelope3D *psEnvelope) const;
  *
- * \brief Computes and returns the bounding envelope (3D) for this geometry in the passed psEnvelope structure.
+ * \brief Computes and returns the bounding envelope (3D) for this
+ * geometry in the passed psEnvelope structure.
  *
  * This method is the same as the C function OGR_G_GetEnvelope3D().
  *
@@ -1252,7 +1339,8 @@ void OGR_G_GetEnvelope( OGRGeometryH hGeom, OGREnvelope *psEnvelope )
 /*                        OGR_G_GetEnvelope3D()                         */
 /************************************************************************/
 /**
- * \brief Computes and returns the bounding envelope (3D) for this geometry in the passed psEnvelope structure.
+ * \brief Computes and returns the bounding envelope (3D) for this
+ * geometry in the passed psEnvelope structure.
  *
  * This function is the same as the CPP method OGRGeometry::getEnvelope().
  *
@@ -1267,11 +1355,12 @@ void OGR_G_GetEnvelope3D( OGRGeometryH hGeom, OGREnvelope3D *psEnvelope )
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_GetEnvelope3D" );
 
-    ((OGRGeometry *) hGeom)->getEnvelope( psEnvelope );
+    reinterpret_cast<OGRGeometry *>(hGeom)->getEnvelope( psEnvelope );
 }
 
 /**
- * \fn OGRErr OGRGeometry::importFromWkb( unsigned char * pabyData, int nSize, OGRwkbVariant eWkbVariant =wkbVariantOldOgc );
+ * \fn OGRErr OGRGeometry::importFromWkb( unsigned char * pabyData,
+ * int nSize, OGRwkbVariant eWkbVariant =wkbVariantOldOgc );
  *
  * \brief Assign geometry from well known binary data.
  *
@@ -1286,7 +1375,8 @@ void OGR_G_GetEnvelope3D( OGRGeometryH hGeom, OGREnvelope3D *psEnvelope )
  *
  * @param pabyData the binary input data.
  * @param nSize the size of pabyData in bytes, or zero if not known.
- * @param eWkbVariant if wkbVariantPostGIS1, special interpretation is done for curve geometries code
+ * @param eWkbVariant if wkbVariantPostGIS1, special interpretation is
+ * done for curve geometries code
  *
  * @return OGRERR_NONE if all goes well, otherwise any of
  * OGRERR_NOT_ENOUGH_DATA, OGRERR_UNSUPPORTED_GEOMETRY_TYPE, or
@@ -1321,7 +1411,8 @@ OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom,
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_ImportFromWkb", OGRERR_FAILURE );
 
-    return ((OGRGeometry *) hGeom)->importFromWkb( pabyData, nSize );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        importFromWkb( pabyData, nSize );
 }
 
 /**
@@ -1333,19 +1424,20 @@ OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom,
  *
  * This method relates to the SFCOM IWks::ExportToWKB() method.
  *
- * This method is the same as the C function OGR_G_ExportToWkb() or OGR_G_ExportToIsoWkb(),
- * depending on the value of eWkbVariant.
+ * This method is the same as the C function OGR_G_ExportToWkb() or
+ * OGR_G_ExportToIsoWkb(), depending on the value of eWkbVariant.
  *
  * @param eByteOrder One of wkbXDR or wkbNDR indicating MSB or LSB byte order
  *               respectively.
  * @param pabyData a buffer into which the binary representation is
  *                      written.  This buffer must be at least
  *                      OGRGeometry::WkbSize() byte in size.
- * @param eWkbVariant What standard to use when exporting geometries with
- *                      three dimensions (or more). The default wkbVariantOldOgc is
- *                      the historical OGR variant. wkbVariantIso is the
- *                      variant defined in ISO SQL/MM and adopted by OGC
- *                      for SFSQL 1.2.
+ * @param eWkbVariant What standard to use when exporting geometries
+ *                      with three dimensions (or more). The default
+ *                      wkbVariantOldOgc is the historical OGR
+ *                      variant. wkbVariantIso is the variant defined
+ *                      in ISO SQL/MM and adopted by OGC for SFSQL
+ *                      1.2.
  *
  * @return Currently OGRERR_NONE is always returned.
  */
@@ -1363,8 +1455,9 @@ OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom,
  * MultiPoint, MultiLineString, MultiPolygon and GeometryCollection.
  * For other geometry types, it is equivalent to OGR_G_ExportToIsoWkb().
  *
- * This function is the same as the CPP method OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *, OGRwkbVariant)
- * with eWkbVariant = wkbVariantOldOgc.
+ * This function is the same as the CPP method
+ * OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *,
+ * OGRwkbVariant) with eWkbVariant = wkbVariantOldOgc.
  *
  * @param hGeom handle on the geometry to convert to a well know binary
  * data from.
@@ -1383,19 +1476,23 @@ OGRErr OGR_G_ExportToWkb( OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_ExportToWkb", OGRERR_FAILURE );
 
-    return ((OGRGeometry *) hGeom)->exportToWkb( eOrder, pabyDstBuffer );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        exportToWkb( eOrder, pabyDstBuffer );
 }
 
 /************************************************************************/
 /*                        OGR_G_ExportToIsoWkb()                        */
 /************************************************************************/
 /**
- * \brief Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known binary format
+ * \brief Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known
+ * binary format
  *
  * This function relates to the SFCOM IWks::ExportToWKB() method.
- * It exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M) WKB types
+ * It exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M) WKB
+ * types.
  *
- * This function is the same as the CPP method  OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *, OGRwkbVariant)
+ * This function is the same as the CPP method
+ * OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *, OGRwkbVariant)
  * with eWkbVariant = wkbVariantIso.
  *
  * @param hGeom handle on the geometry to convert to a well know binary
@@ -1412,12 +1509,13 @@ OGRErr OGR_G_ExportToWkb( OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
  */
 
 OGRErr OGR_G_ExportToIsoWkb( OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
-                          unsigned char *pabyDstBuffer )
+                             unsigned char *pabyDstBuffer )
 
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_ExportToIsoWkb", OGRERR_FAILURE );
 
-    return ((OGRGeometry *) hGeom)->exportToWkb( eOrder, pabyDstBuffer, wkbVariantIso );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        exportToWkb( eOrder, pabyDstBuffer, wkbVariantIso );
 }
 
 /**
@@ -1455,7 +1553,7 @@ OGRErr OGR_G_ExportToIsoWkb( OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
  *
  * This function is the same as the CPP method OGRGeometry::importFromWkt().
  *
- * @param hGeom handle on the  geometry to assign well know text data to.
+ * @param hGeom handle on the geometry to assign well know text data to.
  * @param ppszSrcText pointer to a pointer to the source text.  The pointer is
  *                    updated to pointer after the consumed text.
  *
@@ -1469,21 +1567,20 @@ OGRErr OGR_G_ImportFromWkt( OGRGeometryH hGeom, char ** ppszSrcText )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_ImportFromWkt", OGRERR_FAILURE );
 
-    return ((OGRGeometry *) hGeom)->importFromWkt( ppszSrcText );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->importFromWkt( ppszSrcText );
 }
 
-
 /************************************************************************/
 /*                        importPreambuleFromWkt()                      */
 /************************************************************************/
 
-/* Returns -1 if processing must continue */
+// Returns -1 if processing must continue.
+//! @cond Doxygen_Suppress
 OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
                                             int* pbHasZ, int* pbHasM,
                                             bool* pbIsEmpty )
 {
-    char        szToken[OGR_WKT_TOKEN_MAX];
-    const char  *pszInput = *ppszInput;
+    const char *pszInput = *ppszInput;
 
 /* -------------------------------------------------------------------- */
 /*      Clear existing Geoms.                                           */
@@ -1491,74 +1588,73 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
     empty();
     *pbIsEmpty = false;
 
-    int bHasZ = FALSE, bHasM = FALSE;
-    bool bIsoWKT = true;
-
 /* -------------------------------------------------------------------- */
 /*      Read and verify the type keyword, and ensure it matches the     */
 /*      actual type of this container.                                  */
 /* -------------------------------------------------------------------- */
+    bool bHasM = false;
+    bool bHasZ = false;
+    bool bIsoWKT = true;
+
+    char szToken[OGR_WKT_TOKEN_MAX] = {};
     pszInput = OGRWktReadToken( pszInput, szToken );
     if( szToken[0] != '\0' )
     {
-        // Postgis EWKT : POINTM instead of POINT M
+        // Postgis EWKT: POINTM instead of POINT M.
         const size_t nTokenLen = strlen(szToken);
         if( szToken[nTokenLen-1] == 'M' )
         {
             szToken[nTokenLen-1] = '\0';
-            bHasM = TRUE;
+            bHasM = true;
             bIsoWKT = false;
         }
     }
 
-    if( !EQUAL(szToken,getGeometryName()) )
+    if( !EQUAL(szToken, getGeometryName()) )
         return OGRERR_CORRUPT_DATA;
 
 /* -------------------------------------------------------------------- */
 /*      Check for EMPTY ...                                             */
 /* -------------------------------------------------------------------- */
-    const char *pszPreScan;
-
-    pszPreScan = OGRWktReadToken( pszInput, szToken );
+    const char *pszPreScan = OGRWktReadToken( pszInput, szToken );
     if( !bIsoWKT )
     {
-        /* go on */
+        // Go on.
     }
-    else if( EQUAL(szToken,"EMPTY") )
+    else if( EQUAL(szToken, "EMPTY") )
     {
-        *ppszInput = (char *) pszPreScan;
+        *ppszInput = const_cast<char *>(pszPreScan);
         *pbIsEmpty = true;
         *pbHasM = bHasM;
         empty();
         return OGRERR_NONE;
     }
-
 /* -------------------------------------------------------------------- */
 /*      Check for Z, M or ZM. Will ignore the Measure                   */
 /* -------------------------------------------------------------------- */
-    else if( EQUAL(szToken,"Z") )
+    else if( EQUAL(szToken, "Z") )
     {
-        bHasZ = TRUE;
+        bHasZ = true;
     }
-    else if( EQUAL(szToken,"M") )
+    else if( EQUAL(szToken, "M") )
     {
-        bHasM = TRUE;
+        bHasM = true;
     }
-    else if( EQUAL(szToken,"ZM") )
+    else if( EQUAL(szToken, "ZM") )
     {
-        bHasZ = TRUE;
-        bHasM = TRUE;
+        bHasZ = true;
+        bHasM = true;
     }
     *pbHasZ = bHasZ;
     *pbHasM = bHasM;
 
-    if ( bIsoWKT && (bHasZ || bHasM) )
+    if( bIsoWKT && (bHasZ || bHasM) )
     {
         pszInput = pszPreScan;
         pszPreScan = OGRWktReadToken( pszInput, szToken );
-        if( EQUAL(szToken,"EMPTY") )
+        if( EQUAL(szToken, "EMPTY") )
         {
-            *ppszInput = (char *) pszPreScan;
+            *ppszInput = const_cast<char *>(pszPreScan);
             empty();
             if( bHasZ )
                 set3D(TRUE);
@@ -1569,26 +1665,28 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
         }
     }
 
-    if( !EQUAL(szToken,"(") )
+    if( !EQUAL(szToken, "(") )
         return OGRERR_CORRUPT_DATA;
 
-    if ( !bHasZ && !bHasM )
+    if( !bHasZ && !bHasM )
     {
-        /* Test for old-style XXXXXXXXX(EMPTY) */
+        // Test for old-style XXXXXXXXX(EMPTY).
         pszPreScan = OGRWktReadToken( pszPreScan, szToken );
-        if( EQUAL(szToken,"EMPTY") )
+        if( EQUAL(szToken, "EMPTY") )
         {
             pszPreScan = OGRWktReadToken( pszPreScan, szToken );
 
-            if( EQUAL(szToken,",") )
+            if( EQUAL(szToken, ",") )
             {
-                /* This is OK according to SFSQL SPEC. */
+                // This is OK according to SFSQL SPEC.
             }
-            else if( !EQUAL(szToken,")") )
+            else if( !EQUAL(szToken, ")") )
+            {
                 return OGRERR_CORRUPT_DATA;
+            }
             else
             {
-                *ppszInput = (char *) pszPreScan;
+                *ppszInput = const_cast<char *>(pszPreScan);
                 empty();
                 *pbIsEmpty = true;
                 return OGRERR_NONE;
@@ -1596,14 +1694,15 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
         }
     }
 
-    *ppszInput = (char*) pszInput;
+    *ppszInput = const_cast<char *>(pszInput);
 
     return OGRERR_NONE;
 }
-
+//! @endcond
 
 /**
- * \fn OGRErr OGRGeometry::exportToWkt( char ** ppszDstText, OGRwkbVariant eWkbVariant = wkbVariantOldOgc ) const;
+ * \fn OGRErr OGRGeometry::exportToWkt( char ** ppszDstText,
+ * OGRwkbVariant eWkbVariant = wkbVariantOldOgc ) const;
  *
  * \brief Convert a geometry into well known text format.
  *
@@ -1613,9 +1712,10 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
  *
  * @param ppszDstText a text buffer is allocated by the program, and assigned
  *                    to the passed pointer. After use, *ppszDstText should be
- *                    freed with OGRFree().
+ *                    freed with CPLFree().
  * @param eWkbVariant the specification that must be conformed too :
- *                    - wbkVariantOgc for old-style 99-402 extended dimension (Z) WKB types
+ *                    - wbkVariantOgc for old-style 99-402 extended
+ *                      dimension (Z) WKB types
  *                    - wbkVariantIso for SFSQL 1.2 and ISO SQL/MM Part 3
  *
  * @return Currently OGRERR_NONE is always returned.
@@ -1640,7 +1740,7 @@ OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
  * @param hGeom handle on the geometry to convert to a text format from.
  * @param ppszSrcText a text buffer is allocated by the program, and assigned
  *                    to the passed pointer. After use, *ppszDstText should be
- *                    freed with OGRFree().
+ *                    freed with CPLFree().
  *
  * @return Currently OGRERR_NONE is always returned.
  */
@@ -1650,7 +1750,7 @@ OGRErr OGR_G_ExportToWkt( OGRGeometryH hGeom, char **ppszSrcText )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_ExportToWkt", OGRERR_FAILURE );
 
-    return ((OGRGeometry *) hGeom)->exportToWkt( ppszSrcText );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->exportToWkt( ppszSrcText );
 }
 
 /************************************************************************/
@@ -1658,17 +1758,20 @@ OGRErr OGR_G_ExportToWkt( OGRGeometryH hGeom, char **ppszSrcText )
 /************************************************************************/
 
 /**
- * \brief Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known text format
+ * \brief Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well
+ * known text format.
  *
  * This function relates to the SFCOM IWks::ExportToWKT() method.
- * It exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M) WKB types
+ * It exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension
+ * (Z&M) WKB types.
  *
- * This function is the same as the CPP method OGRGeometry::exportToWkt(,wkbVariantIso).
+ * This function is the same as the CPP method
+ * OGRGeometry::exportToWkt(wkbVariantIso).
  *
  * @param hGeom handle on the geometry to convert to a text format from.
  * @param ppszSrcText a text buffer is allocated by the program, and assigned
  *                    to the passed pointer. After use, *ppszDstText should be
- *                    freed with OGRFree().
+ *                    freed with CPLFree().
  *
  * @return Currently OGRERR_NONE is always returned.
  *
@@ -1680,7 +1783,8 @@ OGRErr OGR_G_ExportToIsoWkt( OGRGeometryH hGeom, char **ppszSrcText )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_ExportToIsoWkt", OGRERR_FAILURE );
 
-    return ((OGRGeometry *) hGeom)->exportToWkt( ppszSrcText, wkbVariantIso );
+    return reinterpret_cast<OGRGeometry *>(hGeom)->
+        exportToWkt( ppszSrcText, wkbVariantIso );
 }
 
 /**
@@ -1718,7 +1822,7 @@ OGRwkbGeometryType OGR_G_GetGeometryType( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetGeometryType", wkbUnknown );
 
-    return ((OGRGeometry *) hGeom)->getGeometryType();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryType();
 }
 
 /**
@@ -1754,7 +1858,7 @@ const char *OGR_G_GetGeometryName( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetGeometryName", "" );
 
-    return ((OGRGeometry *) hGeom)->getGeometryName();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->getGeometryName();
 }
 
 /**
@@ -1781,7 +1885,7 @@ const char *OGR_G_GetGeometryName( OGRGeometryH hGeom )
  * This function is the same as the CPP method OGRGeometry::clone().
  *
  * @param hGeom handle on the geometry to clone from.
- * @return an handle on the  copy of the geometry with the spatial
+ * @return an handle on the copy of the geometry with the spatial
  * reference system as the original.
  */
 
@@ -1790,7 +1894,8 @@ OGRGeometryH OGR_G_Clone( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_Clone", NULL );
 
-    return (OGRGeometryH) ((OGRGeometry *) hGeom)->clone();
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hGeom)->clone());
 }
 
 /**
@@ -1826,8 +1931,8 @@ OGRSpatialReferenceH OGR_G_GetSpatialReference( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_GetSpatialReference", NULL );
 
-    return (OGRSpatialReferenceH)
-        ((OGRGeometry *) hGeom)->getSpatialReference();
+    return reinterpret_cast<OGRSpatialReferenceH>(
+        reinterpret_cast<OGRGeometry *>(hGeom)->getSpatialReference());
 }
 
 /**
@@ -1862,7 +1967,7 @@ void OGR_G_Empty( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_Empty" );
 
-    ((OGRGeometry *) hGeom)->empty();
+    reinterpret_cast<OGRGeometry *>(hGeom)->empty();
 }
 
 /**
@@ -1898,7 +2003,7 @@ int OGR_G_IsEmpty( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_IsEmpty", TRUE );
 
-    return ((OGRGeometry *) hGeom)->IsEmpty();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->IsEmpty();
 }
 
 /************************************************************************/
@@ -1920,31 +2025,55 @@ int OGR_G_IsEmpty( OGRGeometryH hGeom )
  */
 
 OGRBoolean
-OGRGeometry::IsValid(  ) const
+OGRGeometry::IsValid() const
 
 {
+    if( IsSFCGALCompatible() )
+    {
+#ifndef HAVE_SFCGAL
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "SFCGAL support not enabled." );
+        return FALSE;
+#else
+        sfcgal_init();
+        sfcgal_geometry_t *poThis =
+            OGRGeometry::OGRexportToSFCGAL(const_cast<OGRGeometry *>(this));
+        if (poThis == NULL)
+        {
+            CPLError( CE_Failure, CPLE_IllegalArg,
+                      "SFCGAL geometry returned is NULL" );
+            return FALSE;
+        }
+
+        const int res = sfcgal_geometry_is_valid(poThis);
+        sfcgal_geometry_delete(poThis);
+        return res == 1;
+#endif
+    }
+
+    else
+    {
 #ifndef HAVE_GEOS
 
-    return FALSE;
+        return FALSE;
 
 #else
+        OGRBoolean bResult = FALSE;
 
-    OGRBoolean bResult = FALSE;
-    GEOSGeom hThisGeosGeom = NULL;
-
-    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+        GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+        GEOSGeom hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
-    if( hThisGeosGeom != NULL  )
-    {
-        bResult = GEOSisValid_r( hGEOSCtxt, hThisGeosGeom );
-        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
-    }
-    freeGEOSContext( hGEOSCtxt );
+        if( hThisGeosGeom != NULL  )
+        {
+            bResult = GEOSisValid_r( hGEOSCtxt, hThisGeosGeom );
+            GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+        }
+        freeGEOSContext( hGEOSCtxt );
 
-    return bResult;
+        return bResult;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
+    }
 }
 
 /************************************************************************/
@@ -1971,7 +2100,7 @@ int OGR_G_IsValid( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_IsValid", FALSE );
 
-    return ((OGRGeometry *) hGeom)->IsValid();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->IsValid();
 }
 
 /************************************************************************/
@@ -1993,7 +2122,7 @@ int OGR_G_IsValid( OGRGeometryH hGeom )
  */
 
 OGRBoolean
-OGRGeometry::IsSimple(  ) const
+OGRGeometry::IsSimple() const
 
 {
 #ifndef HAVE_GEOS
@@ -2003,12 +2132,11 @@ OGRGeometry::IsSimple(  ) const
 #else
 
     OGRBoolean bResult = FALSE;
-    GEOSGeom hThisGeosGeom = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    GEOSGeom hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
-    if( hThisGeosGeom != NULL  )
+    if( hThisGeosGeom != NULL )
     {
         bResult = GEOSisSimple_r( hGEOSCtxt, hThisGeosGeom );
         GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
@@ -2017,10 +2145,9 @@ OGRGeometry::IsSimple(  ) const
 
     return bResult;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
-
 /**
  * \brief Returns TRUE if the geometry is simple.
  *
@@ -2029,7 +2156,7 @@ OGRGeometry::IsSimple(  ) const
  * instantiable geometric class will include the specific conditions that
  * cause an instance of that class to be classified as not simple.
  *
- * This function is the same as the c++ method OGRGeometry::IsSimple() method.
+ * This function is the same as the C++ method OGRGeometry::IsSimple() method.
  *
  * If OGR is built without the GEOS library, this function will always return
  * FALSE.
@@ -2044,7 +2171,7 @@ int OGR_G_IsSimple( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_IsSimple", TRUE );
 
-    return ((OGRGeometry *) hGeom)->IsSimple();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->IsSimple();
 }
 
 /************************************************************************/
@@ -2066,7 +2193,7 @@ int OGR_G_IsSimple( OGRGeometryH hGeom )
  */
 
 OGRBoolean
-OGRGeometry::IsRing(  ) const
+OGRGeometry::IsRing() const
 
 {
 #ifndef HAVE_GEOS
@@ -2076,12 +2203,11 @@ OGRGeometry::IsRing(  ) const
 #else
 
     OGRBoolean bResult = FALSE;
-    GEOSGeom hThisGeosGeom = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    GEOSGeom hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
-    if( hThisGeosGeom != NULL  )
+    if( hThisGeosGeom != NULL )
     {
         bResult = GEOSisRing_r( hGEOSCtxt, hThisGeosGeom );
         GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
@@ -2090,7 +2216,7 @@ OGRGeometry::IsRing(  ) const
 
     return bResult;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -2117,18 +2243,20 @@ int OGR_G_IsRing( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_IsRing", FALSE );
 
-    return ((OGRGeometry *) hGeom)->IsRing();
+    return reinterpret_cast<OGRGeometry *>(hGeom)->IsRing();
 }
 
 /************************************************************************/
 /*                     OGRFromOGCGeomType()                             */
-/*      Map OGCgeometry format type to corresponding                    */
-/*      OGR constants.                                                  */
 /************************************************************************/
 
+/** Map OGCgeometry format type to corresponding OGR constants.
+ * @param pszGeomType POINT[ ][Z][M], LINESTRING[ ][Z][M], etc...
+ * @return OGR constant.
+ */
 OGRwkbGeometryType OGRFromOGCGeomType( const char *pszGeomType )
 {
-    OGRwkbGeometryType eType;
+    OGRwkbGeometryType eType = wkbUnknown;
     bool bConvertTo3D = false;
     bool bIsMeasured = false;
     if( *pszGeomType != '\0' )
@@ -2145,33 +2273,40 @@ OGRwkbGeometryType OGRFromOGCGeomType( const char *pszGeomType )
             bConvertTo3D = true;
         }
     }
-    if ( STARTS_WITH_CI(pszGeomType, "POINT") )
+
+    if( STARTS_WITH_CI(pszGeomType, "POINT") )
         eType = wkbPoint;
-    else if ( STARTS_WITH_CI(pszGeomType, "LINESTRING") )
+    else if( STARTS_WITH_CI(pszGeomType, "LINESTRING") )
         eType = wkbLineString;
-    else if ( STARTS_WITH_CI(pszGeomType, "POLYGON") )
+    else if( STARTS_WITH_CI(pszGeomType, "POLYGON") )
         eType = wkbPolygon;
-    else if ( STARTS_WITH_CI(pszGeomType, "MULTIPOINT") )
+    else if( STARTS_WITH_CI(pszGeomType, "MULTIPOINT") )
         eType = wkbMultiPoint;
-    else if ( STARTS_WITH_CI(pszGeomType, "MULTILINESTRING") )
+    else if( STARTS_WITH_CI(pszGeomType, "MULTILINESTRING") )
         eType = wkbMultiLineString;
-    else if ( STARTS_WITH_CI(pszGeomType, "MULTIPOLYGON") )
+    else if( STARTS_WITH_CI(pszGeomType, "MULTIPOLYGON") )
         eType = wkbMultiPolygon;
-    else if ( STARTS_WITH_CI(pszGeomType, "GEOMETRYCOLLECTION") )
+    else if( STARTS_WITH_CI(pszGeomType, "GEOMETRYCOLLECTION") )
         eType = wkbGeometryCollection;
-    else if ( STARTS_WITH_CI(pszGeomType, "CIRCULARSTRING") )
+    else if( STARTS_WITH_CI(pszGeomType, "CIRCULARSTRING") )
         eType = wkbCircularString;
-    else if ( STARTS_WITH_CI(pszGeomType, "COMPOUNDCURVE") )
+    else if( STARTS_WITH_CI(pszGeomType, "COMPOUNDCURVE") )
         eType = wkbCompoundCurve;
-    else if ( STARTS_WITH_CI(pszGeomType, "CURVEPOLYGON") )
+    else if( STARTS_WITH_CI(pszGeomType, "CURVEPOLYGON") )
         eType = wkbCurvePolygon;
-    else if ( STARTS_WITH_CI(pszGeomType, "MULTICURVE") )
+    else if( STARTS_WITH_CI(pszGeomType, "MULTICURVE") )
         eType = wkbMultiCurve;
-    else if ( STARTS_WITH_CI(pszGeomType, "MULTISURFACE") )
+    else if( STARTS_WITH_CI(pszGeomType, "MULTISURFACE") )
         eType = wkbMultiSurface;
+    else if ( STARTS_WITH_CI(pszGeomType, "TRIANGLE") )
+        eType = wkbTriangle;
+    else if ( STARTS_WITH_CI(pszGeomType, "POLYHEDRALSURFACE") )
+        eType = wkbPolyhedralSurface;
+    else if ( STARTS_WITH_CI(pszGeomType, "TIN") )
+        eType = wkbTIN;
     else if ( STARTS_WITH_CI(pszGeomType, "CURVE") )
         eType = wkbCurve;
-    else if ( STARTS_WITH_CI(pszGeomType, "SURFACE") )
+    else if( STARTS_WITH_CI(pszGeomType, "SURFACE") )
         eType = wkbSurface;
     else
         eType = wkbUnknown;
@@ -2186,13 +2321,15 @@ OGRwkbGeometryType OGRFromOGCGeomType( const char *pszGeomType )
 
 /************************************************************************/
 /*                     OGRToOGCGeomType()                               */
-/*      Map OGR geometry format constants to corresponding              */
-/*      OGC geometry type                                               */
 /************************************************************************/
 
+/** Map OGR geometry format constants to corresponding OGC geometry type.
+ * @param eGeomType OGR geometry type
+ * @return string with OGC geometry type (without dimensionality)
+ */
 const char * OGRToOGCGeomType( OGRwkbGeometryType eGeomType )
 {
-    switch ( wkbFlatten(eGeomType) )
+    switch( wkbFlatten(eGeomType) )
     {
         case wkbUnknown:
             return "GEOMETRY";
@@ -2220,6 +2357,12 @@ const char * OGRToOGCGeomType( OGRwkbGeometryType eGeomType )
             return "MULTICURVE";
         case wkbMultiSurface:
             return "MULTISURFACE";
+        case wkbTriangle:
+            return "TRIANGLE";
+        case wkbPolyhedralSurface:
+            return "POLYHEDRALSURFACE";
+        case wkbTIN:
+            return "TIN";
         case wkbCurve:
             return "CURVE";
         case wkbSurface:
@@ -2234,8 +2377,9 @@ const char * OGRToOGCGeomType( OGRwkbGeometryType eGeomType )
 /************************************************************************/
 
 /**
- * \brief Fetch a human readable name corresponding to an OGRwkbGeometryType value.
- * The returned value should not be modified, or freed by the application.
+ * \brief Fetch a human readable name corresponding to an OGRwkbGeometryType
+ * value.  The returned value should not be modified, or freed by the
+ * application.
  *
  * This function is C callable.
  *
@@ -2253,161 +2397,191 @@ const char *OGRGeometryTypeToName( OGRwkbGeometryType eType )
     switch( wkbFlatten(eType) )
     {
         case wkbUnknown:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Unknown (any)";
-            else if (b3D)
+            else if( b3D )
                 return "3D Unknown (any)";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Unknown (any)";
             else
                 return "Unknown (any)";
 
         case wkbPoint:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Point";
-            else if (b3D)
+            else if( b3D )
                 return "3D Point";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Point";
             else
                 return "Point";
 
         case wkbLineString:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Line String";
-            else if (b3D)
+            else if( b3D )
                 return "3D Line String";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Line String";
             else
                 return "Line String";
 
         case wkbPolygon:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Polygon";
-            else if (b3D)
+            else if( b3D )
                 return "3D Polygon";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Polygon";
             else
                 return "Polygon";
 
         case wkbMultiPoint:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Multi Point";
-            else if (b3D)
+            else if( b3D )
                 return "3D Multi Point";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Multi Point";
             else
                 return "Multi Point";
 
         case wkbMultiLineString:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Multi Line String";
-            else if (b3D)
+            else if( b3D )
                 return "3D Multi Line String";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Multi Line String";
             else
                 return "Multi Line String";
 
         case wkbMultiPolygon:
-          if (b3D && bMeasured)
+          if( b3D && bMeasured )
                 return "3D Measured Multi Polygon";
-            else if (b3D)
+            else if( b3D )
                 return "3D Multi Polygon";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Multi Polygon";
             else
                 return "Multi Polygon";
 
         case wkbGeometryCollection:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Geometry Collection";
-            else if (b3D)
+            else if( b3D )
                 return "3D Geometry Collection";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Geometry Collection";
             else
                 return "Geometry Collection";
 
         case wkbCircularString:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Circular String";
-            else if (b3D)
+            else if( b3D )
                 return "3D Circular String";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Circular String";
             else
                 return "Circular String";
 
         case wkbCompoundCurve:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Compound Curve";
-            else if (b3D)
+            else if( b3D )
                 return "3D Compound Curve";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Compound Curve";
             else
                 return "Compound Curve";
 
         case wkbCurvePolygon:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Curve Polygon";
-            else if (b3D)
+            else if( b3D )
                 return "3D Curve Polygon";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Curve Polygon";
             else
                 return "Curve Polygon";
 
         case wkbMultiCurve:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Multi Curve";
-            else if (b3D)
+            else if( b3D )
                 return "3D Multi Curve";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Multi Curve";
             else
                 return "Multi Curve";
 
         case wkbMultiSurface:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Multi Surface";
-            else if (b3D)
+            else if( b3D )
                 return "3D Multi Surface";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Multi Surface";
             else
                 return "Multi Surface";
 
         case wkbCurve:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Curve";
-            else if (b3D)
+            else if( b3D )
                 return "3D Curve";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Curve";
             else
                 return "Curve";
 
         case wkbSurface:
-            if (b3D && bMeasured)
+            if( b3D && bMeasured )
                 return "3D Measured Surface";
-            else if (b3D)
+            else if( b3D )
                 return "3D Surface";
-            else if (bMeasured)
+            else if( bMeasured )
                 return "Measured Surface";
             else
                 return "Surface";
 
+        case wkbTriangle:
+            if (b3D && bMeasured)
+                return "3D Measured Triangle";
+            else if (b3D)
+                return "3D Triangle";
+            else if (bMeasured)
+                return "Measured Triangle";
+            else
+                return "Triangle";
+
+        case wkbPolyhedralSurface:
+            if (b3D && bMeasured)
+                return "3D Measured PolyhedralSurface";
+            else if (b3D)
+                return "3D PolyhedralSurface";
+            else if (bMeasured)
+                return "Measured PolyhedralSurface";
+            else
+                return "PolyhedralSurface";
+
+        case wkbTIN:
+            if (b3D && bMeasured)
+                return "3D Measured TIN";
+            else if (b3D)
+                return "3D TIN";
+            else if (bMeasured)
+                return "Measured TIN";
+            else
+                return "TIN";
+
         case wkbNone:
             return "None";
 
         default:
         {
-            return CPLSPrintf( "Unrecognized: %d", (int) eType );
+            return CPLSPrintf("Unrecognized: %d", static_cast<int>(eType));
         }
     }
 }
@@ -2465,7 +2639,8 @@ OGRMergeGeometryTypes( OGRwkbGeometryType eMain,
  *
  * @param eMain the first input geometry type.
  * @param eExtra the second input geometry type.
- * @param bAllowPromotingToCurves determine if promotion to curve type must be done.
+ * @param bAllowPromotingToCurves determine if promotion to curve type
+ * must be done.
  *
  * @return the merged geometry type.
  *
@@ -2557,7 +2732,7 @@ OGRMergeGeometryTypesEx( OGRwkbGeometryType eMain,
 void OGR_G_FlattenTo2D( OGRGeometryH hGeom )
 
 {
-    ((OGRGeometry *) hGeom)->flattenTo2D();
+    reinterpret_cast<OGRGeometry *>(hGeom)->flattenTo2D();
 }
 
 /************************************************************************/
@@ -2565,7 +2740,8 @@ void OGR_G_FlattenTo2D( OGRGeometryH hGeom )
 /************************************************************************/
 
 /**
- * \fn char *OGRGeometry::exportToGML( const char* const * papszOptions = NULL ) const;
+ * \fn char *OGRGeometry::exportToGML( const char* const *
+ * papszOptions = NULL ) const;
  *
  * \brief Convert a geometry into GML format.
  *
@@ -2576,13 +2752,18 @@ void OGR_G_FlattenTo2D( OGRGeometryH hGeom )
  * The supported options in OGR 1.8.0 are :
  * <ul>
  * <li> FORMAT=GML3. Otherwise it will default to GML 2.1.2 output.
- * <li> GML3_LINESTRING_ELEMENT=curve. (Only valid for FORMAT=GML3) To use gml:Curve element for linestrings.
- *     Otherwise gml:LineString will be used .
- * <li> GML3_LONGSRS=YES/NO. (Only valid for FORMAT=GML3) Default to YES. If YES, SRS with EPSG authority will
- *      be written with the "urn:ogc:def:crs:EPSG::" prefix.
- *      In the case, if the SRS is a geographic SRS without explicit AXIS order, but that the same SRS authority code
- *      imported with ImportFromEPSGA() should be treated as lat/long, then the function will take care of coordinate order swapping.
- *      If set to NO, SRS with EPSG authority will be written with the "EPSG:" prefix, even if they are in lat/long order.
+ * <li> GML3_LINESTRING_ELEMENT=curve. (Only valid for FORMAT=GML3) To
+ *     use gml:Curve element for linestrings.  Otherwise
+ *     gml:LineString will be used .
+ * <li> GML3_LONGSRS=YES/NO. (Only valid for FORMAT=GML3) Default to
+ *      YES. If YES, SRS with EPSG authority will be written with the
+ *      "urn:ogc:def:crs:EPSG::" prefix.  In the case, if the SRS is a
+ *      geographic SRS without explicit AXIS order, but that the same
+ *      SRS authority code imported with ImportFromEPSGA() should be
+ *      treated as lat/long, then the function will take care of
+ *      coordinate order swapping.  If set to NO, SRS with EPSG
+ *      authority will be written with the "EPSG:" prefix, even if
+ *      they are in lat/long order.
  * </ul>
  *
  * This method is the same as the C function OGR_G_ExportToGMLEx().
@@ -2593,7 +2774,9 @@ void OGR_G_FlattenTo2D( OGRGeometryH hGeom )
 
 char *OGRGeometry::exportToGML( const char* const * papszOptions ) const
 {
-    return OGR_G_ExportToGMLEx( (OGRGeometryH) this, (char**)papszOptions );
+    return OGR_G_ExportToGMLEx(
+        reinterpret_cast<OGRGeometryH>(const_cast<OGRGeometry *>(this)),
+        const_cast<char **>(papszOptions));
 }
 
 /************************************************************************/
@@ -2614,7 +2797,8 @@ char *OGRGeometry::exportToGML( const char* const * papszOptions ) const
 
 char *OGRGeometry::exportToKML() const
 {
-    return OGR_G_ExportToKML( (OGRGeometryH) this, NULL );
+    return OGR_G_ExportToKML(
+        reinterpret_cast<OGRGeometryH>(const_cast<OGRGeometry *>(this)), NULL);
 }
 
 /************************************************************************/
@@ -2636,7 +2820,7 @@ char *OGRGeometry::exportToKML() const
 char *OGRGeometry::exportToJson() const
 {
     OGRGeometry* poGeometry = const_cast<OGRGeometry*>(this);
-    return OGR_G_ExportToJson( (OGRGeometryH) (poGeometry) );
+    return OGR_G_ExportToJson( reinterpret_cast<OGRGeometryH>(poGeometry) );
 }
 
 /************************************************************************/
@@ -2644,11 +2828,12 @@ char *OGRGeometry::exportToJson() const
 /************************************************************************/
 
 /**
-  * \brief Special entry point to enable the hack for generating DB2 V7.2 style WKB.
+  * \brief Special entry point to enable the hack for generating DB2 V7.2 style
+  * WKB.
   *
-  * DB2 seems to have placed  (and require) an extra 0x30 or'ed with the byte order in
-  * WKB.  This entry point is used to turn on or off the
-  * generation of such WKB.
+  * DB2 seems to have placed (and require) an extra 0x30 or'ed with the byte
+  * order in WKB.  This entry point is used to turn on or off the generation of
+  * such WKB.
   */
 OGRErr OGRSetGenerate_DB2_V72_BYTE_ORDER( int bGenerate_DB2_V72_BYTE_ORDER )
 
@@ -2678,6 +2863,9 @@ int OGRGetGenerate_DB2_V72_BYTE_ORDER()
 /*                          createGEOSContext()                         */
 /************************************************************************/
 
+/** Create a new GEOS context.
+ * @return a new GEOS context.
+ */
 GEOSContextHandle_t OGRGeometry::createGEOSContext()
 {
 #ifndef HAVE_GEOS
@@ -2693,7 +2881,11 @@ GEOSContextHandle_t OGRGeometry::createGEOSContext()
 /*                          freeGEOSContext()                           */
 /************************************************************************/
 
-void OGRGeometry::freeGEOSContext(UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtxt)
+/** Destroy a GEOS context.
+ * @param hGEOSCtxt GEOS context
+ */
+void OGRGeometry::freeGEOSContext(
+    UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtxt)
 {
 #ifdef HAVE_GEOS
     if( hGEOSCtxt != NULL )
@@ -2707,7 +2899,13 @@ void OGRGeometry::freeGEOSContext(UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtx
 /*                            exportToGEOS()                            */
 /************************************************************************/
 
-GEOSGeom OGRGeometry::exportToGEOS(UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtxt) const
+/** Returns a GEOSGeom object corresponding to the geometry.
+ *
+ * @param hGEOSCtxt GEOS context
+ * @return a GEOSGeom object corresponding to the geometry.
+ */
+GEOSGeom OGRGeometry::exportToGEOS(
+    UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtxt) const
 
 {
 #ifndef HAVE_GEOS
@@ -2721,17 +2919,15 @@ GEOSGeom OGRGeometry::exportToGEOS(UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCt
     if( hGEOSCtxt == NULL )
         return NULL;
 
-    /* POINT EMPTY is exported to WKB as if it were POINT(0 0) */
-    /* so that particular case is necessary */
-    if (wkbFlatten(getGeometryType()) == wkbPoint &&
-        IsEmpty())
+    // POINT EMPTY is exported to WKB as if it were POINT(0 0),
+    // so that particular case is necessary.
+    const OGRwkbGeometryType eType = wkbFlatten(getGeometryType());
+    if( eType == wkbPoint && IsEmpty() )
     {
         return GEOSGeomFromWKT_r(hGEOSCtxt, "POINT EMPTY");
     }
 
     GEOSGeom hGeom = NULL;
-    size_t nDataSize;
-    unsigned char *pabyData = NULL;
 
     OGRGeometry* poLinearGeom = NULL;
     if( hasCurveGeometry() )
@@ -2749,9 +2945,64 @@ GEOSGeom OGRGeometry::exportToGEOS(UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCt
             poLinearGeom->setMeasured(FALSE);
         }
     }
-    nDataSize = poLinearGeom->WkbSize();
-    pabyData = (unsigned char *) CPLMalloc(nDataSize);
-    if( poLinearGeom->exportToWkb( wkbNDR, pabyData ) == OGRERR_NONE )
+    const size_t nDataSize = poLinearGeom->WkbSize();
+    unsigned char *pabyData =
+        static_cast<unsigned char *>(CPLMalloc(nDataSize));
+    if (eType == wkbTriangle)
+    {
+        OGRPolygon poPolygon(*((OGRPolygon *)poLinearGeom));
+        if( poPolygon.exportToWkb( wkbNDR, pabyData ) == OGRERR_NONE )
+            hGeom = GEOSGeomFromWKB_buf_r( hGEOSCtxt, pabyData, nDataSize );
+    }
+    else if ( eType == wkbPolyhedralSurface || eType == wkbTIN )
+    {
+        OGRGeometry *poGC = OGRGeometryFactory::forceTo(
+                        poLinearGeom->clone(), wkbGeometryCollection, NULL );
+        OGRErr eErr = poGC->exportToWkb( wkbNDR, pabyData );
+        if( eErr == OGRERR_NONE )
+            hGeom = GEOSGeomFromWKB_buf_r( hGEOSCtxt, pabyData, nDataSize );
+        delete poGC;
+    }
+    else if ( eType == wkbGeometryCollection )
+    {
+        bool bCanConvertToMultiPoly = true;
+        bool bMustConvertToMultiPoly = true;
+        OGRGeometryCollection* poGC = dynamic_cast<OGRGeometryCollection*>(
+                                                                poLinearGeom);
+        for( int iGeom = 0; poGC != NULL && iGeom < poGC->getNumGeometries();
+             iGeom++ )
+        {
+            OGRwkbGeometryType eSubGeomType =
+                wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType());
+            if( eSubGeomType == wkbPolyhedralSurface || eSubGeomType == wkbTIN )
+            {
+                bMustConvertToMultiPoly = true;
+            }
+            else if( eSubGeomType != wkbMultiPolygon &&
+                     eSubGeomType != wkbPolygon )
+            {
+                bCanConvertToMultiPoly = false;
+                break;
+            }
+        }
+        if( bCanConvertToMultiPoly && bMustConvertToMultiPoly )
+        {
+            OGRGeometry *poMultiPolygon = OGRGeometryFactory::forceTo(
+                                poLinearGeom->clone(), wkbMultiPolygon, NULL );
+            OGRGeometry* poGCDest = OGRGeometryFactory::forceTo(
+                                poMultiPolygon, wkbGeometryCollection, NULL );
+            OGRErr eErr = poGCDest->exportToWkb( wkbNDR, pabyData );
+            if( eErr == OGRERR_NONE )
+                hGeom = GEOSGeomFromWKB_buf_r( hGEOSCtxt, pabyData, nDataSize );
+            delete poGCDest;
+        }
+        else
+        {
+            if( poLinearGeom->exportToWkb( wkbNDR, pabyData ) == OGRERR_NONE )
+                hGeom = GEOSGeomFromWKB_buf_r( hGEOSCtxt, pabyData, nDataSize );
+        }
+    }
+    else if( poLinearGeom->exportToWkb( wkbNDR, pabyData ) == OGRERR_NONE )
         hGeom = GEOSGeomFromWKB_buf_r( hGEOSCtxt, pabyData, nDataSize );
 
     CPLFree( pabyData );
@@ -2761,7 +3012,7 @@ GEOSGeom OGRGeometry::exportToGEOS(UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCt
 
     return hGeom;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -2771,28 +3022,31 @@ GEOSGeom OGRGeometry::exportToGEOS(UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCt
 /**
  * \brief Returns if this geometry is or has curve geometry.
  *
- * Returns if a geometry is, contains or may contain a CIRCULARSTRING, COMPOUNDCURVE,
- * CURVEPOLYGON, MULTICURVE or MULTISURFACE.
+ * Returns if a geometry is, contains or may contain a CIRCULARSTRING,
+ * COMPOUNDCURVE, CURVEPOLYGON, MULTICURVE or MULTISURFACE.
  *
- * If bLookForNonLinear is set to TRUE, it will be actually looked if the
- * geometry or its subgeometries are or contain a non-linear geometry in them. In which
- * case, if the method returns TRUE, it means that getLinearGeometry() would
- * return an approximate version of the geometry. Otherwise, getLinearGeometry()
- * would do a conversion, but with just converting container type, like
- * COMPOUNDCURVE -> LINESTRING, MULTICURVE -> MULTILINESTRING or MULTISURFACE -> MULTIPOLYGON,
- * resulting in a "loss-less" conversion.
+ * If bLookForNonLinear is set to TRUE, it will be actually looked if
+ * the geometry or its subgeometries are or contain a non-linear
+ * geometry in them. In which case, if the method returns TRUE, it
+ * means that getLinearGeometry() would return an approximate version
+ * of the geometry. Otherwise, getLinearGeometry() would do a
+ * conversion, but with just converting container type, like
+ * COMPOUNDCURVE -> LINESTRING, MULTICURVE -> MULTILINESTRING or
+ * MULTISURFACE -> MULTIPOLYGON, resulting in a "loss-less"
+ * conversion.
  *
  * This method is the same as the C function OGR_G_HasCurveGeometry().
  *
- * @param bLookForNonLinear set it to TRUE to check if the geometry is or contains
- * a CIRCULARSTRING.
+ * @param bLookForNonLinear set it to TRUE to check if the geometry is
+ * or contains a CIRCULARSTRING.
  *
  * @return TRUE if this geometry is or has curve geometry.
  *
  * @since GDAL 2.0
  */
 
-OGRBoolean OGRGeometry::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear) const
+OGRBoolean OGRGeometry::hasCurveGeometry(
+    CPL_UNUSED int bLookForNonLinear ) const
 {
     return FALSE;
 }
@@ -2816,15 +3070,17 @@ OGRBoolean OGRGeometry::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear) const
  * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
  * arc, zero to use the default setting.
  * @param papszOptions options as a null-terminated list of strings.
- *                     See OGRGeometryFactory::curveToLineString() for valid options.
+ *                     See OGRGeometryFactory::curveToLineString() for
+ *                     valid options.
  *
  * @return a new geometry.
  *
  * @since GDAL 2.0
  */
 
-OGRGeometry* OGRGeometry::getLinearGeometry(CPL_UNUSED double dfMaxAngleStepSizeDegrees,
-                                            CPL_UNUSED const char* const* papszOptions) const
+OGRGeometry* OGRGeometry::getLinearGeometry(
+    CPL_UNUSED double dfMaxAngleStepSizeDegrees,
+    CPL_UNUSED const char* const* papszOptions) const
 {
     return clone();
 }
@@ -2836,8 +3092,9 @@ OGRGeometry* OGRGeometry::getLinearGeometry(CPL_UNUSED double dfMaxAngleStepSize
 /**
  * \brief Return curve version of this geometry.
  *
- * Returns a geometry that has possibly CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
- * MULTICURVE or MULTISURFACE in it, by de-approximating curve geometries.
+ * Returns a geometry that has possibly CIRCULARSTRING, COMPOUNDCURVE,
+ * CURVEPOLYGON, MULTICURVE or MULTISURFACE in it, by de-approximating
+ * curve geometries.
  *
  * If the geometry has no curve portion, the returned geometry will be a clone
  * of it.
@@ -2856,7 +3113,8 @@ OGRGeometry* OGRGeometry::getLinearGeometry(CPL_UNUSED double dfMaxAngleStepSize
  * @since GDAL 2.0
  */
 
-OGRGeometry* OGRGeometry::getCurveGeometry(CPL_UNUSED const char* const* papszOptions) const
+OGRGeometry* OGRGeometry::getCurveGeometry(
+    CPL_UNUSED const char* const* papszOptions) const
 {
     return clone();
 }
@@ -2888,47 +3146,79 @@ double OGRGeometry::Distance( const OGRGeometry *poOtherGeom ) const
 {
     if( NULL == poOtherGeom )
     {
-        CPLDebug( "OGR", "OGRGeometry::Distance called with NULL geometry pointer" );
+        CPLDebug( "OGR",
+                  "OGRGeometry::Distance called with NULL geometry pointer" );
         return -1.0;
     }
 
-#ifndef HAVE_GEOS
+    if (IsSFCGALCompatible() || poOtherGeom->IsSFCGALCompatible())
+    {
+    #ifndef HAVE_SFCGAL
 
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "GEOS support not enabled." );
-    return -1.0;
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "SFCGAL support not enabled." );
+        return -1.0;
 
-#else
+    #else
 
-    // GEOSGeom is a pointer
-    GEOSGeom hThis = NULL;
-    GEOSGeom hOther = NULL;
+        sfcgal_geometry_t *poThis =
+            OGRGeometry::OGRexportToSFCGAL(const_cast<OGRGeometry *>(this));
+        if (poThis == NULL)
+            return -1.0;
 
-    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hOther = poOtherGeom->exportToGEOS(hGEOSCtxt);
-    hThis = exportToGEOS(hGEOSCtxt);
+        sfcgal_geometry_t *poOther =
+            OGRGeometry::OGRexportToSFCGAL(
+                const_cast<OGRGeometry *>(poOtherGeom));
+        if (poOther == NULL)
+            return -1.0;
 
-    int bIsErr = 0;
-    double dfDistance = 0.0;
+        const double dfDistance = sfcgal_geometry_distance(poThis, poOther);
 
-    if( hThis != NULL && hOther != NULL )
-    {
-        bIsErr = GEOSDistance_r( hGEOSCtxt, hThis, hOther, &dfDistance );
-    }
+        sfcgal_geometry_delete(poThis);
+        sfcgal_geometry_delete(poOther);
 
-    GEOSGeom_destroy_r( hGEOSCtxt, hThis );
-    GEOSGeom_destroy_r( hGEOSCtxt, hOther );
-    freeGEOSContext( hGEOSCtxt );
+        return dfDistance > 0.0 ? dfDistance : -1.0;
 
-    if ( bIsErr > 0 )
-    {
-        return dfDistance;
+    #endif
     }
 
-    /* Calculations error */
-    return -1.0;
+    else
+    {
+    #ifndef HAVE_GEOS
 
-#endif /* HAVE_GEOS */
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "GEOS support not enabled." );
+        return -1.0;
+
+    #else
+
+        GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+        // GEOSGeom is a pointer
+        GEOSGeom hOther = poOtherGeom->exportToGEOS(hGEOSCtxt);
+        GEOSGeom hThis = exportToGEOS(hGEOSCtxt);
+
+        int bIsErr = 0;
+        double dfDistance = 0.0;
+
+        if( hThis != NULL && hOther != NULL )
+        {
+            bIsErr = GEOSDistance_r( hGEOSCtxt, hThis, hOther, &dfDistance );
+        }
+
+        GEOSGeom_destroy_r( hGEOSCtxt, hThis );
+        GEOSGeom_destroy_r( hGEOSCtxt, hOther );
+        freeGEOSContext( hGEOSCtxt );
+
+        if ( bIsErr > 0 )
+        {
+            return dfDistance;
+        }
+
+        /* Calculations error */
+        return -1.0;
+
+    #endif /* HAVE_GEOS */
+    }
 }
 
 /************************************************************************/
@@ -2953,36 +3243,141 @@ double OGRGeometry::Distance( const OGRGeometry *poOtherGeom ) const
  * @return the distance between the geometries or -1 if an error occurs.
  */
 
-
 double OGR_G_Distance( OGRGeometryH hFirst, OGRGeometryH hOther )
 
 {
     VALIDATE_POINTER1( hFirst, "OGR_G_Distance", 0.0 );
 
-    return ((OGRGeometry *) hFirst)->Distance( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometry *>(hFirst)->
+        Distance(reinterpret_cast<OGRGeometry *>(hOther));
 }
 
 /************************************************************************/
-/*                       OGRGeometryRebuildCurves()                     */
+/*                             Distance3D()                             */
 /************************************************************************/
 
-#ifdef HAVE_GEOS
-static OGRGeometry* OGRGeometryRebuildCurves(const OGRGeometry* poGeom,
-                                             const OGRGeometry* poOtherGeom,
-                                             OGRGeometry* poOGRProduct)
+/**
+ * \brief Returns the 3D distance between two geometries
+ *
+ * The distance is expressed into the same unit as the coordinates of the
+ * geometries.
+ *
+ * This method is built on the SFCGAL library, check it for the definition
+ * of the geometry operation.
+ * If OGR is built without the SFCGAL library, this method will always return
+ * -1.0
+ *
+ * This function is the same as the C function OGR_G_Distance3D().
+ *
+ * @return distance between the two geometries
+ * @since GDAL 2.2
+ */
+
+double OGRGeometry::Distance3D(
+    UNUSED_IF_NO_SFCGAL const OGRGeometry *poOtherGeom ) const
 {
-    if( poOGRProduct != NULL &&
-        wkbFlatten(poOGRProduct->getGeometryType()) != wkbPoint &&
-        (poGeom->hasCurveGeometry() ||
-         (poOtherGeom && poOtherGeom->hasCurveGeometry())) )
+    if( poOtherGeom == NULL )
     {
-        OGRGeometry* poCurveGeom = poOGRProduct->getCurveGeometry();
-        delete poOGRProduct;
-        return poCurveGeom;
+        CPLDebug( "OGR",
+                  "OGRTriangle::Distance3D called with NULL geometry pointer" );
+        return -1.0;
     }
-    return poOGRProduct;
-}
-#endif
+
+    if( !(poOtherGeom->Is3D() && Is3D()) )
+    {
+        CPLDebug( "OGR",
+                  "OGRGeometry::Distance3D called with two dimensional "
+                  "geometry(geometries)" );
+        return -1.0;
+    }
+
+#ifndef HAVE_SFCGAL
+
+    CPLError( CE_Failure, CPLE_NotSupported, "SFCGAL support not enabled." );
+    return -1.0;
+
+#else
+
+    sfcgal_init();
+    sfcgal_geometry_t *poThis =
+        OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)this);
+    if( poThis == NULL )
+        return -1.0;
+
+    sfcgal_geometry_t *poOther =
+        OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)poOtherGeom);
+    if( poOther == NULL )
+    {
+        sfcgal_geometry_delete(poThis);
+        return -1.0;
+    }
+
+    const double dfDistance = sfcgal_geometry_distance_3d(poThis, poOther);
+
+    sfcgal_geometry_delete(poThis);
+    sfcgal_geometry_delete(poOther);
+
+    return dfDistance > 0 ? dfDistance : -1.0;
+
+#endif
+}
+
+/************************************************************************/
+/*                           OGR_G_Distance3D()                         */
+/************************************************************************/
+/**
+ * \brief Returns the 3D distance between two geometries
+ *
+ * The distance is expressed into the same unit as the coordinates of the
+ * geometries.
+ *
+ * This method is built on the SFCGAL library, check it for the definition
+ * of the geometry operation.
+ * If OGR is built without the SFCGAL library, this method will always return
+ * -1.0
+ *
+ * This function is the same as the C++ method OGRGeometry::Distance3D().
+ *
+ * @param hFirst the first geometry to compare against.
+ * @param hOther the other geometry to compare against.
+ * @return distance between the two geometries
+ * @since GDAL 2.2
+ *
+ * @return the distance between the geometries or -1 if an error occurs.
+ */
+
+
+double OGR_G_Distance3D( OGRGeometryH hFirst, OGRGeometryH hOther )
+
+{
+    VALIDATE_POINTER1( hFirst, "OGR_G_Distance3D", 0.0 );
+
+    return
+        reinterpret_cast<OGRGeometry *>(hFirst)->
+            Distance3D(reinterpret_cast<OGRGeometry *>(hOther));
+}
+
+/************************************************************************/
+/*                       OGRGeometryRebuildCurves()                     */
+/************************************************************************/
+
+#ifdef HAVE_GEOS
+static OGRGeometry* OGRGeometryRebuildCurves( const OGRGeometry* poGeom,
+                                              const OGRGeometry* poOtherGeom,
+                                              OGRGeometry* poOGRProduct )
+{
+    if( poOGRProduct != NULL &&
+        wkbFlatten(poOGRProduct->getGeometryType()) != wkbPoint &&
+        (poGeom->hasCurveGeometry() ||
+         (poOtherGeom && poOtherGeom->hasCurveGeometry())) )
+    {
+        OGRGeometry* poCurveGeom = poOGRProduct->getCurveGeometry();
+        delete poOGRProduct;
+        return poCurveGeom;
+    }
+    return poOGRProduct;
+}
+#endif
 
 /************************************************************************/
 /*                             ConvexHull()                             */
@@ -3001,45 +3396,77 @@ static OGRGeometry* OGRGeometryRebuildCurves(const OGRGeometry* poGeom,
  * If OGR is built without the GEOS library, this method will always fail,
  * issuing a CPLE_NotSupported error.
  *
- * @return a newly allocated geometry now owned by the caller, or NULL on failure.
+ * @return a newly allocated geometry now owned by the caller, or NULL
+ * on failure.
  */
 
 OGRGeometry *OGRGeometry::ConvexHull() const
 
 {
-#ifndef HAVE_GEOS
+    if( IsSFCGALCompatible() )
+    {
+#ifndef HAVE_SFCGAL
 
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "GEOS support not enabled." );
-    return NULL;
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "SFCGAL support not enabled." );
+        return NULL;
 
 #else
 
-    GEOSGeom hGeosGeom = NULL;
-    GEOSGeom hGeosHull = NULL;
-    OGRGeometry *poOGRProduct = NULL;
+        sfcgal_geometry_t *poThis =
+            OGRGeometry::OGRexportToSFCGAL(const_cast<OGRGeometry *>(this));
+        if (poThis == NULL)
+            return FALSE;
 
-    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hGeosGeom = exportToGEOS(hGEOSCtxt);
-    if( hGeosGeom != NULL )
+        sfcgal_geometry_t *poRes = sfcgal_geometry_convexhull_3d(poThis);
+        OGRGeometry *h_prodGeom = SFCGALexportToOGR(poRes);
+
+        h_prodGeom->assignSpatialReference(getSpatialReference());
+
+        sfcgal_geometry_delete(poThis);
+        sfcgal_geometry_delete(poRes);
+
+        return h_prodGeom;
+
+#endif
+    }
+
+    else
     {
-        hGeosHull = GEOSConvexHull_r( hGEOSCtxt, hGeosGeom );
-        GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
+#ifndef HAVE_GEOS
+
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "GEOS support not enabled." );
+        return NULL;
+
+#else
+
+        OGRGeometry *poOGRProduct = NULL;
 
-        if( hGeosHull != NULL )
+        GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+        GEOSGeom hGeosGeom = exportToGEOS(hGEOSCtxt);
+        if( hGeosGeom != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosHull);
-            if( poOGRProduct != NULL && getSpatialReference() != NULL )
-                poOGRProduct->assignSpatialReference(getSpatialReference());
-            poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
-            GEOSGeom_destroy_r( hGEOSCtxt, hGeosHull);
+            GEOSGeom hGeosHull = GEOSConvexHull_r( hGEOSCtxt, hGeosGeom );
+            GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
+
+            if( hGeosHull != NULL )
+            {
+                poOGRProduct =
+                    OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosHull);
+                if( poOGRProduct != NULL && getSpatialReference() != NULL )
+                    poOGRProduct->assignSpatialReference(getSpatialReference());
+                poOGRProduct =
+                    OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
+                GEOSGeom_destroy_r( hGEOSCtxt, hGeosHull);
+            }
         }
-    }
-    freeGEOSContext( hGEOSCtxt );
+        freeGEOSContext( hGEOSCtxt );
 
-    return poOGRProduct;
+        return poOGRProduct;
 
 #endif /* HAVE_GEOS */
+    }
 }
 
 /************************************************************************/
@@ -3069,7 +3496,8 @@ OGRGeometryH OGR_G_ConvexHull( OGRGeometryH hTarget )
 {
     VALIDATE_POINTER1( hTarget, "OGR_G_ConvexHull", NULL );
 
-    return (OGRGeometryH) ((OGRGeometry *) hTarget)->ConvexHull();
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hTarget)->ConvexHull());
 }
 
 /************************************************************************/
@@ -3089,7 +3517,8 @@ OGRGeometryH OGR_G_ConvexHull( OGRGeometryH hTarget )
  * If OGR is built without the GEOS library, this method will always fail,
  * issuing a CPLE_NotSupported error.
  *
- * @return a newly allocated geometry now owned by the caller, or NULL on failure.
+ * @return a newly allocated geometry now owned by the caller, or NULL
+ * on failure.
  *
  * @since OGR 1.8.0
  */
@@ -3106,19 +3535,19 @@ OGRGeometry *OGRGeometry::Boundary() const
 #else
 
     GEOSGeom hGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hGeosGeom != NULL )
     {
-        hGeosProduct = GEOSBoundary_r( hGEOSCtxt, hGeosGeom );
+        GEOSGeom hGeosProduct = GEOSBoundary_r( hGEOSCtxt, hGeosGeom );
         GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
+            poOGRProduct =
+                OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
@@ -3129,10 +3558,10 @@ OGRGeometry *OGRGeometry::Boundary() const
 
     return poOGRProduct;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
-
+//! @cond Doxygen_Suppress
 /**
  * \brief Compute boundary (deprecated)
  *
@@ -3145,6 +3574,7 @@ OGRGeometry *OGRGeometry::getBoundary() const
 {
     return Boundary();
 }
+//! @endcond
 
 /************************************************************************/
 /*                         OGR_G_Boundary()                             */
@@ -3174,7 +3604,8 @@ OGRGeometryH OGR_G_Boundary( OGRGeometryH hTarget )
 {
     VALIDATE_POINTER1( hTarget, "OGR_G_Boundary", NULL );
 
-    return (OGRGeometryH) ((OGRGeometry *) hTarget)->Boundary();
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hTarget)->Boundary());
 }
 
 /**
@@ -3189,7 +3620,8 @@ OGRGeometryH OGR_G_GetBoundary( OGRGeometryH hTarget )
 {
     VALIDATE_POINTER1( hTarget, "OGR_G_GetBoundary", NULL );
 
-    return (OGRGeometryH) ((OGRGeometry *) hTarget)->Boundary();
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hTarget)->Boundary());
 }
 
 /************************************************************************/
@@ -3220,8 +3652,8 @@ OGRGeometryH OGR_G_GetBoundary( OGRGeometryH hTarget )
  * @param dfDist the buffer distance to be applied. Should be expressed into
  *               the same unit as the coordinates of the geometry.
  *
- * @param nQuadSegs the number of segments used to approximate a 90 degree (quadrant) of
- * curvature.
+ * @param nQuadSegs the number of segments used to approximate a 90
+ * degree (quadrant) of curvature.
  *
  * @return the newly created geometry, or NULL if an error occurs.
  */
@@ -3239,19 +3671,20 @@ OGRGeometry *OGRGeometry::Buffer( UNUSED_IF_NO_GEOS double dfDist,
 #else
 
     GEOSGeom hGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hGeosGeom != NULL )
     {
-        hGeosProduct = GEOSBuffer_r( hGEOSCtxt, hGeosGeom, dfDist, nQuadSegs );
+        GEOSGeom hGeosProduct =
+            GEOSBuffer_r( hGEOSCtxt, hGeosGeom, dfDist, nQuadSegs );
         GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
+            poOGRProduct =
+                OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
@@ -3262,7 +3695,7 @@ OGRGeometry *OGRGeometry::Buffer( UNUSED_IF_NO_GEOS double dfDist,
 
     return poOGRProduct;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -3305,7 +3738,8 @@ OGRGeometryH OGR_G_Buffer( OGRGeometryH hTarget, double dfDist, int nQuadSegs )
 {
     VALIDATE_POINTER1( hTarget, "OGR_G_Buffer", NULL );
 
-    return (OGRGeometryH) ((OGRGeometry *) hTarget)->Buffer( dfDist, nQuadSegs );
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hTarget)->Buffer( dfDist, nQuadSegs ));
 }
 
 /************************************************************************/
@@ -3332,49 +3766,87 @@ OGRGeometryH OGR_G_Buffer( OGRGeometryH hTarget, double dfDist, int nQuadSegs )
  * no intersection or an error occurs.
  */
 
-OGRGeometry *OGRGeometry::Intersection( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
+OGRGeometry *OGRGeometry::Intersection(
+    UNUSED_PARAMETER const OGRGeometry *poOtherGeom ) const
 
 {
-#ifndef HAVE_GEOS
+    if (IsSFCGALCompatible() || poOtherGeom->IsSFCGALCompatible())
+    {
+    #ifndef HAVE_SFCGAL
 
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "GEOS support not enabled." );
-    return NULL;
+        CPLError( CE_Failure, CPLE_NotSupported, "SFCGAL support not enabled." );
+        return NULL;
 
-#else
+    #else
 
-    GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hOtherGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
-    OGRGeometry *poOGRProduct = NULL;
+        sfcgal_geometry_t *poThis = OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)this);
+        if (poThis == NULL)
+            return FALSE;
 
-    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
-    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
-    if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
+        sfcgal_geometry_t *poOther = OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)poOtherGeom);
+        if (poThis == NULL)
+            return FALSE;
+
+        sfcgal_geometry_t *poRes = sfcgal_geometry_intersection_3d(poThis, poOther);
+        OGRGeometry *h_prodGeom = SFCGALexportToOGR(poRes);
+
+        if (h_prodGeom != NULL && getSpatialReference() != NULL
+            && poOtherGeom->getSpatialReference() != NULL
+            && poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()))
+            h_prodGeom->assignSpatialReference(getSpatialReference());
+
+        sfcgal_geometry_delete(poThis);
+        sfcgal_geometry_delete(poOther);
+        sfcgal_geometry_delete(poRes);
+
+        return h_prodGeom;
+
+    #endif
+    }
+
+    else
     {
-        hGeosProduct = GEOSIntersection_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
+    #ifndef HAVE_GEOS
 
-        if( hGeosProduct != NULL )
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "GEOS support not enabled." );
+        return NULL;
+
+    #else
+
+        GEOSGeom hThisGeosGeom = NULL;
+        GEOSGeom hOtherGeosGeom = NULL;
+        GEOSGeom hGeosProduct = NULL;
+        OGRGeometry *poOGRProduct = NULL;
+
+        GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+        hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+        hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
+        if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
-            if( poOGRProduct != NULL && getSpatialReference() != NULL &&
-                poOtherGeom->getSpatialReference() != NULL &&
-                poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
+            hGeosProduct = GEOSIntersection_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
+
+            if( hGeosProduct != NULL )
             {
-                poOGRProduct->assignSpatialReference(getSpatialReference());
+                poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
+                if( poOGRProduct != NULL && getSpatialReference() != NULL &&
+                    poOtherGeom->getSpatialReference() != NULL &&
+                    poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
+                {
+                    poOGRProduct->assignSpatialReference(getSpatialReference());
+                }
+                poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
+                GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
             }
-            poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
-            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
-    }
-    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
-    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
-    freeGEOSContext( hGEOSCtxt );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+        freeGEOSContext( hGEOSCtxt );
 
-    return poOGRProduct;
+        return poOGRProduct;
 
-#endif /* HAVE_GEOS */
+    #endif /* HAVE_GEOS */
+    }
 }
 
 /************************************************************************/
@@ -3407,8 +3879,9 @@ OGRGeometryH OGR_G_Intersection( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Intersection", NULL );
 
-    return (OGRGeometryH)
-        ((OGRGeometry *) hThis)->Intersection( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hThis)->
+            Intersection(reinterpret_cast<OGRGeometry *>(hOther)));
 }
 
 /************************************************************************/
@@ -3433,49 +3906,91 @@ OGRGeometryH OGR_G_Intersection( OGRGeometryH hThis, OGRGeometryH hOther )
  * @return a new geometry representing the union or NULL if an error occurs.
  */
 
-OGRGeometry *OGRGeometry::Union( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
+OGRGeometry *OGRGeometry::Union(
+    UNUSED_PARAMETER const OGRGeometry *poOtherGeom ) const
 
 {
-#ifndef HAVE_GEOS
+    if (IsSFCGALCompatible() || poOtherGeom->IsSFCGALCompatible())
+    {
+    #ifndef HAVE_SFCGAL
 
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "GEOS support not enabled." );
-    return NULL;
+        CPLError( CE_Failure, CPLE_NotSupported, "SFCGAL support not enabled." );
+        return NULL;
 
-#else
+    #else
 
-    GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hOtherGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
-    OGRGeometry *poOGRProduct = NULL;
+        sfcgal_geometry_t *poThis = OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)this);
+        if (poThis == NULL)
+            return NULL;
 
-    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
-    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
-    if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
+        sfcgal_geometry_t *poOther = OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)poOtherGeom);
+        if (poOther == NULL)
+            return NULL;
+
+        sfcgal_geometry_t *poRes = sfcgal_geometry_union_3d(poThis, poOther);
+        if (poRes == NULL)
+            return NULL;
+
+        OGRGeometry *h_prodGeom = OGRGeometry::SFCGALexportToOGR(poRes);
+        if (h_prodGeom == NULL)
+            return NULL;
+
+        if (h_prodGeom != NULL && getSpatialReference() != NULL
+            && poOtherGeom->getSpatialReference() != NULL
+            && poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()))
+            h_prodGeom->assignSpatialReference(getSpatialReference());
+
+        sfcgal_geometry_delete(poThis);
+        sfcgal_geometry_delete(poOther);
+
+        return h_prodGeom;
+
+    #endif
+    }
+
+    else
     {
-        hGeosProduct = GEOSUnion_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
+    #ifndef HAVE_GEOS
 
-        if( hGeosProduct != NULL )
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "GEOS support not enabled." );
+        return NULL;
+
+    #else
+
+        GEOSGeom hThisGeosGeom = NULL;
+        GEOSGeom hOtherGeosGeom = NULL;
+        GEOSGeom hGeosProduct = NULL;
+        OGRGeometry *poOGRProduct = NULL;
+
+        GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+        hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+        hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
+        if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
-            if( poOGRProduct != NULL && getSpatialReference() != NULL &&
-                poOtherGeom->getSpatialReference() != NULL &&
-                poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
+            hGeosProduct = GEOSUnion_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
+
+            if( hGeosProduct != NULL )
             {
-                poOGRProduct->assignSpatialReference(getSpatialReference());
+                poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
+                if( poOGRProduct != NULL && getSpatialReference() != NULL &&
+                    poOtherGeom->getSpatialReference() != NULL &&
+                    poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
+                {
+                    poOGRProduct->assignSpatialReference(getSpatialReference());
+                }
+                poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
+                GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
             }
-            poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
-            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
-    }
-    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
-    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
-    freeGEOSContext( hGEOSCtxt );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+        freeGEOSContext( hGEOSCtxt );
 
-    return poOGRProduct;
+        return poOGRProduct;
 
-#endif /* HAVE_GEOS */
+    #endif /* HAVE_GEOS */
+    }
 }
 
 /************************************************************************/
@@ -3506,8 +4021,9 @@ OGRGeometryH OGR_G_Union( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Union", NULL );
 
-    return (OGRGeometryH)
-        ((OGRGeometry *) hThis)->Union( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hThis)->
+          Union(reinterpret_cast<OGRGeometry *>(hOther)));
 }
 
 /************************************************************************/
@@ -3539,19 +4055,19 @@ OGRGeometry *OGRGeometry::UnionCascaded() const
     return NULL;
 #else
     GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL )
     {
-        hGeosProduct = GEOSUnionCascaded_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom hGeosProduct = GEOSUnionCascaded_r(hGEOSCtxt, hThisGeosGeom);
         GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
+            poOGRProduct =
+                OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
@@ -3562,7 +4078,7 @@ OGRGeometry *OGRGeometry::UnionCascaded() const
 
     return poOGRProduct;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -3589,8 +4105,8 @@ OGRGeometryH OGR_G_UnionCascaded( OGRGeometryH hThis )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_UnionCascaded", NULL );
 
-    return (OGRGeometryH)
-        ((OGRGeometry *) hThis)->UnionCascaded();
+    return reinterpret_cast<OGRGeometryH>(
+      reinterpret_cast<OGRGeometry *>(hThis)->UnionCascaded());
 }
 
 /************************************************************************/
@@ -3616,49 +4132,90 @@ OGRGeometryH OGR_G_UnionCascaded( OGRGeometryH hThis )
  * difference is empty or an error occurs.
  */
 
-OGRGeometry *OGRGeometry::Difference( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
+OGRGeometry *OGRGeometry::Difference(
+    UNUSED_PARAMETER const OGRGeometry *poOtherGeom ) const
 
 {
-#ifndef HAVE_GEOS
+    if (IsSFCGALCompatible() || poOtherGeom->IsSFCGALCompatible())
+    {
+    #ifndef HAVE_SFCGAL
 
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "GEOS support not enabled." );
-    return NULL;
+        CPLError( CE_Failure, CPLE_NotSupported, "SFCGAL support not enabled." );
+        return NULL;
 
-#else
+    #else
 
-    GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hOtherGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
-    OGRGeometry *poOGRProduct = NULL;
+        sfcgal_geometry_t *poThis = OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)this);
+        if (poThis == NULL)
+            return NULL;
 
-    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
-    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
-    if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
+        sfcgal_geometry_t *poOther = OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)poOtherGeom);
+        if (poOther == NULL)
+            return NULL;
+
+        sfcgal_geometry_t *poRes = sfcgal_geometry_difference_3d(poThis, poOther);
+        OGRGeometry *h_prodGeom = OGRGeometry::SFCGALexportToOGR(poRes);
+
+        if (h_prodGeom == NULL)
+            return NULL;
+
+        if (h_prodGeom != NULL && getSpatialReference() != NULL
+            && poOtherGeom->getSpatialReference() != NULL
+            && poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()))
+            h_prodGeom->assignSpatialReference(getSpatialReference());
+
+        sfcgal_geometry_delete(poThis);
+        sfcgal_geometry_delete(poOther);
+        sfcgal_geometry_delete(poRes);
+
+        return h_prodGeom;
+
+    #endif
+    }
+
+    else
     {
-        hGeosProduct = GEOSDifference_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
+    #ifndef HAVE_GEOS
 
-        if( hGeosProduct != NULL )
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "GEOS support not enabled." );
+        return NULL;
+
+    #else
+
+        GEOSGeom hThisGeosGeom = NULL;
+        GEOSGeom hOtherGeosGeom = NULL;
+        GEOSGeom hGeosProduct = NULL;
+        OGRGeometry *poOGRProduct = NULL;
+
+        GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+        hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+        hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
+        if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
-            if( poOGRProduct != NULL && getSpatialReference() != NULL &&
-                poOtherGeom->getSpatialReference() != NULL &&
-                poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
+            hGeosProduct = GEOSDifference_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
+
+            if( hGeosProduct != NULL )
             {
-                poOGRProduct->assignSpatialReference(getSpatialReference());
+                poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
+                if( poOGRProduct != NULL && getSpatialReference() != NULL &&
+                    poOtherGeom->getSpatialReference() != NULL &&
+                    poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
+                {
+                    poOGRProduct->assignSpatialReference(getSpatialReference());
+                }
+                poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
+                GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
             }
-            poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
-            GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
-    }
-    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
-    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
-    freeGEOSContext( hGEOSCtxt );
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+        freeGEOSContext( hGEOSCtxt );
 
-    return poOGRProduct;
+        return poOGRProduct;
 
-#endif /* HAVE_GEOS */
+    #endif /* HAVE_GEOS */
+    }
 }
 
 /************************************************************************/
@@ -3690,8 +4247,9 @@ OGRGeometryH OGR_G_Difference( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Difference", NULL );
 
-    return (OGRGeometryH)
-        ((OGRGeometry *) hThis)->Difference( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hThis)->
+        Difference(reinterpret_cast<OGRGeometry *>(hOther)));
 }
 
 /************************************************************************/
@@ -3720,9 +4278,34 @@ OGRGeometryH OGR_G_Difference( OGRGeometryH hThis, OGRGeometryH hOther )
  */
 
 OGRGeometry *
-OGRGeometry::SymDifference( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
+OGRGeometry::SymDifference(
+    UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
 {
+    if (IsSFCGALCompatible() || poOtherGeom->IsSFCGALCompatible())
+    {
+#ifndef HAVE_SFCGAL
+        CPLError( CE_Failure, CPLE_NotSupported, "SFCGAL support not enabled." );
+        return NULL;
+#else
+        OGRGeometry* poFirstDifference = Difference(poOtherGeom);
+        if (poFirstDifference == NULL)
+            return NULL;
+
+        OGRGeometry* poOtherDifference = poOtherGeom->Difference(this);
+        if (poOtherDifference == NULL)
+        {
+            delete poFirstDifference;
+            return NULL;
+        }
+
+        OGRGeometry* poSymDiff = poFirstDifference->Union(poOtherDifference);
+        delete poFirstDifference;
+        delete poOtherDifference;
+        return poSymDiff;
+#endif
+    }
+
 #ifndef HAVE_GEOS
 
     CPLError( CE_Failure, CPLE_NotSupported,
@@ -3733,7 +4316,6 @@ OGRGeometry::SymDifference( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) c
 
     GEOSGeom hThisGeosGeom = NULL;
     GEOSGeom hOtherGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
@@ -3741,18 +4323,22 @@ OGRGeometry::SymDifference( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) c
     hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
     {
-        hGeosProduct = GEOSSymDifference_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
+        GEOSGeom hGeosProduct =
+            GEOSSymDifference_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
 
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
+            poOGRProduct =
+                OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
             if( poOGRProduct != NULL && getSpatialReference() != NULL &&
                 poOtherGeom->getSpatialReference() != NULL &&
-                poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
+                poOtherGeom->getSpatialReference()->
+                    IsSame(getSpatialReference()) )
             {
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             }
-            poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
+            poOGRProduct =
+                OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
             GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
         }
     }
@@ -3762,10 +4348,10 @@ OGRGeometry::SymDifference( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) c
 
     return poOGRProduct;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
-
+//! @cond Doxygen_Suppress
 /**
  * \brief Compute symmetric difference (deprecated)
  *
@@ -3779,6 +4365,7 @@ OGRGeometry::SymmetricDifference( const OGRGeometry *poOtherGeom ) const
 {
     return SymDifference( poOtherGeom );
 }
+//! @endcond
 
 /************************************************************************/
 /*                      OGR_G_SymDifference()                           */
@@ -3790,7 +4377,8 @@ OGRGeometry::SymmetricDifference( const OGRGeometry *poOtherGeom ) const
  * Generates a new geometry which is the symmetric difference of this
  * geometry and the other geometry.
  *
- * This function is the same as the C++ method OGRGeometry::SymmetricDifference().
+ * This function is the same as the C++ method
+ * OGRGeometry::SymmetricDifference().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
@@ -3811,8 +4399,9 @@ OGRGeometryH OGR_G_SymDifference( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_SymDifference", NULL );
 
-    return (OGRGeometryH)
-        ((OGRGeometry *) hThis)->SymDifference( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hThis)->
+            SymDifference(reinterpret_cast<OGRGeometry *>(hOther)));
 }
 
 /**
@@ -3822,13 +4411,15 @@ OGRGeometryH OGR_G_SymDifference( OGRGeometryH hThis, OGRGeometryH hOther )
  *
  * @see OGR_G_SymmetricDifference()
  */
-OGRGeometryH OGR_G_SymmetricDifference( OGRGeometryH hThis, OGRGeometryH hOther )
+OGRGeometryH OGR_G_SymmetricDifference( OGRGeometryH hThis,
+                                        OGRGeometryH hOther )
 
 {
     VALIDATE_POINTER1( hThis, "OGR_G_SymmetricDifference", NULL );
 
-    return (OGRGeometryH)
-        ((OGRGeometry *) hThis)->SymDifference( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hThis)->
+        SymDifference(reinterpret_cast<OGRGeometry *>(hOther)));
 }
 
 /************************************************************************/
@@ -3881,7 +4472,7 @@ OGRGeometry::Disjoint( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
     return bResult;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -3910,7 +4501,8 @@ int OGR_G_Disjoint( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Disjoint", FALSE );
 
-    return ((OGRGeometry *) hThis)->Disjoint( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometry *>(hThis)->
+        Disjoint(reinterpret_cast<OGRGeometry *>(hOther));
 }
 
 /************************************************************************/
@@ -3964,7 +4556,7 @@ OGRGeometry::Touches( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
     return bResult;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -3993,7 +4585,8 @@ int OGR_G_Touches( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Touches", FALSE );
 
-    return ((OGRGeometry *) hThis)->Touches( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometry *>(hThis)->
+        Touches(reinterpret_cast<OGRGeometry *>(hOther));
 }
 
 /************************************************************************/
@@ -4018,36 +4611,67 @@ int OGR_G_Touches( OGRGeometryH hThis, OGRGeometryH hOther )
  */
 
 OGRBoolean
-OGRGeometry::Crosses( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
+OGRGeometry::Crosses( UNUSED_PARAMETER const OGRGeometry *poOtherGeom ) const
 
 {
-#ifndef HAVE_GEOS
+    if (IsSFCGALCompatible() || poOtherGeom->IsSFCGALCompatible())
+    {
+    #ifndef HAVE_SFCGAL
 
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "GEOS support not enabled." );
-    return FALSE;
+        CPLError( CE_Failure, CPLE_NotSupported, "SFCGAL support not enabled." );
+        return FALSE;
 
-#else
+    #else
 
-    GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hOtherGeosGeom = NULL;
-    OGRBoolean bResult = FALSE;
+        sfcgal_geometry_t *poThis = OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)this);
+        if (poThis == NULL)
+            return FALSE;
 
-    GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
-    hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
+        sfcgal_geometry_t *poOther = OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)poOtherGeom);
+        if (poOther == NULL)
+            return FALSE;
 
-    if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
-    {
-        bResult = GEOSCrosses_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
+        int res = sfcgal_geometry_intersects_3d(poThis, poOther);
+
+        sfcgal_geometry_delete(poThis);
+        sfcgal_geometry_delete(poOther);
+
+        return (res == 1)? TRUE: FALSE;
+
+    #endif
     }
-    GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
-    GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
-    freeGEOSContext( hGEOSCtxt );
 
-    return bResult;
+    else
+    {
 
-#endif /* HAVE_GEOS */
+    #ifndef HAVE_GEOS
+
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "GEOS support not enabled." );
+        return FALSE;
+
+    #else
+
+        GEOSGeom hThisGeosGeom = NULL;
+        GEOSGeom hOtherGeosGeom = NULL;
+        OGRBoolean bResult = FALSE;
+
+        GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
+        hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+        hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
+
+        if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
+        {
+            bResult = GEOSCrosses_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
+        }
+        GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
+        freeGEOSContext( hGEOSCtxt );
+
+        return bResult;
+
+    #endif /* HAVE_GEOS */
+    }
 }
 
 /************************************************************************/
@@ -4076,7 +4700,8 @@ int OGR_G_Crosses( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Crosses", FALSE );
 
-    return ((OGRGeometry *) hThis)->Crosses( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometry *>(hThis)->
+      Crosses(reinterpret_cast<OGRGeometry *>(hOther));
 }
 
 /************************************************************************/
@@ -4129,7 +4754,7 @@ OGRGeometry::Within( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
     return bResult;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -4158,7 +4783,8 @@ int OGR_G_Within( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Within", FALSE );
 
-    return ((OGRGeometry *) hThis)->Within( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometry *>(hThis)->
+        Within(reinterpret_cast<OGRGeometry *>(hOther));
 }
 
 /************************************************************************/
@@ -4211,7 +4837,7 @@ OGRGeometry::Contains( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
     return bResult;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -4240,7 +4866,8 @@ int OGR_G_Contains( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Contains", FALSE );
 
-    return ((OGRGeometry *) hThis)->Contains( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometry *>(hThis)->
+      Contains(reinterpret_cast<OGRGeometry *>(hOther));
 }
 
 /************************************************************************/
@@ -4294,7 +4921,7 @@ OGRGeometry::Overlaps( UNUSED_IF_NO_GEOS const OGRGeometry *poOtherGeom ) const
 
     return bResult;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -4324,7 +4951,8 @@ int OGR_G_Overlaps( OGRGeometryH hThis, OGRGeometryH hOther )
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Overlaps", FALSE );
 
-    return ((OGRGeometry *) hThis)->Overlaps( (OGRGeometry *) hOther );
+    return reinterpret_cast<OGRGeometry *>(hThis)->
+        Overlaps(reinterpret_cast<OGRGeometry *>(hOther));
 }
 
 /************************************************************************/
@@ -4339,10 +4967,7 @@ int OGR_G_Overlaps( OGRGeometryH hThis, OGRGeometryH hOther )
  * the end.
  */
 
-void OGRGeometry::closeRings()
-
-{
-}
+void OGRGeometry::closeRings() {}
 
 /************************************************************************/
 /*                          OGR_G_CloseRings()                          */
@@ -4363,7 +4988,7 @@ void OGR_G_CloseRings( OGRGeometryH hGeom )
 {
     VALIDATE_POINTER0( hGeom, "OGR_G_CloseRings" );
 
-    ((OGRGeometry *) hGeom)->closeRings();
+    reinterpret_cast<OGRGeometry *>(hGeom)->closeRings();
 }
 
 /************************************************************************/
@@ -4381,7 +5006,8 @@ void OGR_G_CloseRings( OGRGeometryH hGeom )
  * geometry types such as multipoint, linestring, geometrycollection such as
  * multipolygons.
  * OGC SF SQL 1.1 defines the operation for surfaces (polygons).
- * SQL/MM-Part 3 defines the operation for surfaces and multisurfaces (multipolygons).
+ * SQL/MM-Part 3 defines the operation for surfaces and multisurfaces
+ * (multipolygons).
  *
  * This function is the same as the C function OGR_G_Centroid().
  *
@@ -4392,7 +5018,8 @@ void OGR_G_CloseRings( OGRGeometryH hGeom )
  *
  * @return OGRERR_NONE on success or OGRERR_FAILURE on error.
  *
- * @since OGR 1.8.0 as a OGRGeometry method (previously was restricted to OGRPolygon)
+ * @since OGR 1.8.0 as a OGRGeometry method (previously was restricted
+ * to OGRPolygon)
  */
 
 OGRErr OGRGeometry::Centroid( OGRPoint *poPoint ) const
@@ -4402,7 +5029,6 @@ OGRErr OGRGeometry::Centroid( OGRPoint *poPoint ) const
         return OGRERR_FAILURE;
 
 #ifndef HAVE_GEOS
-    // notdef ... not implemented yet.
     CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return OGRERR_FAILURE;
@@ -4410,14 +5036,13 @@ OGRErr OGRGeometry::Centroid( OGRPoint *poPoint ) const
 #else
 
     GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hOtherGeosGeom = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
 
     if( hThisGeosGeom != NULL )
     {
-    	hOtherGeosGeom = GEOSGetCentroid_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom hOtherGeosGeom = GEOSGetCentroid_r( hGEOSCtxt, hThisGeosGeom );
         GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
 
         if( hOtherGeosGeom == NULL )
@@ -4427,16 +5052,16 @@ OGRErr OGRGeometry::Centroid( OGRPoint *poPoint ) const
         }
 
         OGRGeometry *poCentroidGeom =
-            OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hOtherGeosGeom );
+            OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hOtherGeosGeom );
 
         GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
 
-        if (poCentroidGeom == NULL)
+        if( poCentroidGeom == NULL )
         {
             freeGEOSContext( hGEOSCtxt );
             return OGRERR_FAILURE;
         }
-        if (wkbFlatten(poCentroidGeom->getGeometryType()) != wkbPoint)
+        if( wkbFlatten(poCentroidGeom->getGeometryType()) != wkbPoint )
         {
             delete poCentroidGeom;
             freeGEOSContext( hGEOSCtxt );
@@ -4446,7 +5071,16 @@ OGRErr OGRGeometry::Centroid( OGRPoint *poPoint ) const
         if( poCentroidGeom != NULL && getSpatialReference() != NULL )
             poCentroidGeom->assignSpatialReference(getSpatialReference());
 
-        OGRPoint *poCentroid = (OGRPoint *) poCentroidGeom;
+        OGRPoint *poCentroid = dynamic_cast<OGRPoint *>(poCentroidGeom);
+        if( poCentroid == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRPoint.");
+            delete poCentroidGeom;
+            freeGEOSContext( hGEOSCtxt );
+            return OGRERR_FAILURE;
+        }
+
         if( !poCentroid->IsEmpty() )
         {
             poPoint->setX( poCentroid->getX() );
@@ -4460,15 +5094,15 @@ OGRErr OGRGeometry::Centroid( OGRPoint *poPoint ) const
         delete poCentroidGeom;
 
         freeGEOSContext( hGEOSCtxt );
-    	return OGRERR_NONE;
+        return OGRERR_NONE;
     }
     else
     {
         freeGEOSContext( hGEOSCtxt );
-    	return OGRERR_FAILURE;
+        return OGRERR_FAILURE;
     }
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -4503,8 +5137,8 @@ int OGR_G_Centroid( OGRGeometryH hGeom, OGRGeometryH hCentroidPoint )
 {
     VALIDATE_POINTER1( hGeom, "OGR_G_Centroid", OGRERR_FAILURE );
 
-    OGRGeometry *poGeom = ((OGRGeometry *) hGeom);
-    OGRPoint *poCentroid = ((OGRPoint *) hCentroidPoint);
+    OGRGeometry *poGeom = reinterpret_cast<OGRGeometry *>(hGeom);
+    OGRPoint *poCentroid = reinterpret_cast<OGRPoint *>(hCentroidPoint);
 
     if( poCentroid == NULL )
         return OGRERR_FAILURE;
@@ -4554,15 +5188,15 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
     return NULL;
 #else
     GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hOtherGeosGeom = NULL;
-    OGRGeometry* poThis = (OGRGeometry*) hGeom;
+    OGRGeometry* poThis = reinterpret_cast<OGRGeometry *>(hGeom);
 
     GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
     hThisGeosGeom = poThis->exportToGEOS(hGEOSCtxt);
 
     if( hThisGeosGeom != NULL )
     {
-        hOtherGeosGeom = GEOSPointOnSurface_r( hGEOSCtxt, hThisGeosGeom );
+        GEOSGeom hOtherGeosGeom =
+            GEOSPointOnSurface_r( hGEOSCtxt, hThisGeosGeom );
         GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
 
         if( hOtherGeosGeom == NULL )
@@ -4571,17 +5205,17 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
             return NULL;
         }
 
-        OGRGeometry *poInsidePointGeom = (OGRGeometry *)
-            OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hOtherGeosGeom );
+        OGRGeometry *poInsidePointGeom =
+            OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hOtherGeosGeom );
 
         GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
 
-        if (poInsidePointGeom == NULL)
+        if( poInsidePointGeom == NULL )
         {
             OGRGeometry::freeGEOSContext( hGEOSCtxt );
             return NULL;
         }
-        if (wkbFlatten(poInsidePointGeom->getGeometryType()) != wkbPoint)
+        if( wkbFlatten(poInsidePointGeom->getGeometryType()) != wkbPoint )
         {
             delete poInsidePointGeom;
             OGRGeometry::freeGEOSContext( hGEOSCtxt );
@@ -4589,16 +5223,15 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
         }
 
         if( poInsidePointGeom != NULL && poThis->getSpatialReference() != NULL )
-            poInsidePointGeom->assignSpatialReference(poThis->getSpatialReference());
+            poInsidePointGeom->
+                assignSpatialReference(poThis->getSpatialReference());
 
         OGRGeometry::freeGEOSContext( hGEOSCtxt );
-        return (OGRGeometryH) poInsidePointGeom;
-    }
-    else
-    {
-        OGRGeometry::freeGEOSContext( hGEOSCtxt );
-        return NULL;
+        return reinterpret_cast<OGRGeometryH>(poInsidePointGeom);
     }
+
+    OGRGeometry::freeGEOSContext( hGEOSCtxt );
+    return NULL;
 #endif
 }
 
@@ -4606,18 +5239,23 @@ OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
 /*                          PointOnSurfaceInternal()                    */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 OGRErr OGRGeometry::PointOnSurfaceInternal( OGRPoint * poPoint ) const
 {
     if( poPoint == NULL || poPoint->IsEmpty() )
         return OGRERR_FAILURE;
 
-    OGRGeometryH hInsidePoint = OGR_G_PointOnSurface( (OGRGeometryH) this );
+    OGRGeometryH hInsidePoint =
+      OGR_G_PointOnSurface(
+          reinterpret_cast<OGRGeometryH>(const_cast<OGRGeometry *>(this)));
     if( hInsidePoint == NULL )
         return OGRERR_FAILURE;
 
-    OGRPoint *poInsidePoint = (OGRPoint *) hInsidePoint;
+    OGRPoint *poInsidePoint = reinterpret_cast<OGRPoint *>(hInsidePoint);
     if( poInsidePoint->IsEmpty() )
+    {
         poPoint->empty();
+    }
     else
     {
         poPoint->setX( poInsidePoint->getX() );
@@ -4626,6 +5264,7 @@ OGRErr OGRGeometry::PointOnSurfaceInternal( OGRPoint * poPoint ) const
 
     return OGRERR_NONE;
 }
+//! @endcond
 
 /************************************************************************/
 /*                              Simplify()                              */
@@ -4648,7 +5287,7 @@ OGRErr OGRGeometry::PointOnSurfaceInternal( OGRPoint * poPoint ) const
  * @since OGR 1.8.0
  */
 
-OGRGeometry *OGRGeometry::Simplify(UNUSED_IF_NO_GEOS double dTolerance) const
+OGRGeometry *OGRGeometry::Simplify( UNUSED_IF_NO_GEOS double dTolerance ) const
 
 {
 #ifndef HAVE_GEOS
@@ -4658,19 +5297,19 @@ OGRGeometry *OGRGeometry::Simplify(UNUSED_IF_NO_GEOS double dTolerance) const
     return NULL;
 
 #else
-    GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
-    hThisGeosGeom = exportToGEOS(hGEOSCtxt);
+    GEOSGeom hThisGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL )
     {
-        hGeosProduct = GEOSSimplify_r( hGEOSCtxt, hThisGeosGeom, dTolerance );
+        GEOSGeom hGeosProduct =
+            GEOSSimplify_r( hGEOSCtxt, hThisGeosGeom, dTolerance );
         GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hGeosProduct );
+            poOGRProduct =
+                OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct );
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
@@ -4680,8 +5319,7 @@ OGRGeometry *OGRGeometry::Simplify(UNUSED_IF_NO_GEOS double dTolerance) const
     freeGEOSContext( hGEOSCtxt );
     return poOGRProduct;
 
-#endif /* HAVE_GEOS */
-
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -4710,7 +5348,8 @@ OGRGeometryH OGR_G_Simplify( OGRGeometryH hThis, double dTolerance )
 
 {
     VALIDATE_POINTER1( hThis, "OGR_G_Simplify", NULL );
-    return (OGRGeometryH) ((OGRGeometry *) hThis)->Simplify( dTolerance );
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hThis)->Simplify(dTolerance));
 }
 
 /************************************************************************/
@@ -4734,7 +5373,8 @@ OGRGeometryH OGR_G_Simplify( OGRGeometryH hThis, double dTolerance )
  * @since OGR 1.9.0
  */
 
-OGRGeometry *OGRGeometry::SimplifyPreserveTopology(UNUSED_IF_NO_GEOS double dTolerance) const
+OGRGeometry *OGRGeometry::SimplifyPreserveTopology(
+    UNUSED_IF_NO_GEOS double dTolerance ) const
 
 {
 #ifndef HAVE_GEOS
@@ -4745,18 +5385,20 @@ OGRGeometry *OGRGeometry::SimplifyPreserveTopology(UNUSED_IF_NO_GEOS double dTol
 
 #else
     GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL )
     {
-        hGeosProduct = GEOSTopologyPreserveSimplify_r( hGEOSCtxt, hThisGeosGeom, dTolerance );
+        GEOSGeom hGeosProduct =
+            GEOSTopologyPreserveSimplify_r( hGEOSCtxt, hThisGeosGeom,
+                                            dTolerance );
         GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hGeosProduct );
+            poOGRProduct =
+                OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct );
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
@@ -4766,8 +5408,7 @@ OGRGeometry *OGRGeometry::SimplifyPreserveTopology(UNUSED_IF_NO_GEOS double dTol
     freeGEOSContext( hGEOSCtxt );
     return poOGRProduct;
 
-#endif /* HAVE_GEOS */
-
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -4777,7 +5418,8 @@ OGRGeometry *OGRGeometry::SimplifyPreserveTopology(UNUSED_IF_NO_GEOS double dTol
 /**
  * \brief Simplify the geometry while preserving topology.
  *
- * This function is the same as the C++ method OGRGeometry::SimplifyPreserveTopology().
+ * This function is the same as the C++ method
+ * OGRGeometry::SimplifyPreserveTopology().
  *
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
@@ -4792,11 +5434,14 @@ OGRGeometry *OGRGeometry::SimplifyPreserveTopology(UNUSED_IF_NO_GEOS double dTol
  * @since OGR 1.9.0
  */
 
-OGRGeometryH OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis, double dTolerance )
+OGRGeometryH OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis,
+                                             double dTolerance )
 
 {
     VALIDATE_POINTER1( hThis, "OGR_G_SimplifyPreserveTopology", NULL );
-    return (OGRGeometryH) ((OGRGeometry *) hThis)->SimplifyPreserveTopology( dTolerance );
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hThis)->
+            SimplifyPreserveTopology(dTolerance));
 }
 
 /************************************************************************/
@@ -4816,41 +5461,48 @@ OGRGeometryH OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis, double dToleran
  * @param bOnlyEdges if TRUE, will return a MULTILINESTRING, otherwise it will
  *                   return a GEOMETRYCOLLECTION containing triangular POLYGONs.
  *
- * @return the geometry resulting from the Delaunay triangulation or NULL if an error occurs.
+ * @return the geometry resulting from the Delaunay triangulation or
+ * NULL if an error occurs.
  *
  * @since OGR 2.1
  */
 
 #ifndef HAVE_GEOS
-OGRGeometry *OGRGeometry::DelaunayTriangulation(double /*dfTolerance*/, int /*bOnlyEdges*/) const
+OGRGeometry *OGRGeometry::DelaunayTriangulation(double /*dfTolerance*/,
+                                                int /*bOnlyEdges*/) const
 {
     CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS support not enabled." );
     return NULL;
 }
-#elif GEOS_VERSION_MAJOR < 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 4)
-OGRGeometry *OGRGeometry::DelaunayTriangulation(double /*dfTolerance*/, int /*bOnlyEdges*/) const
+#elif GEOS_VERSION_MAJOR < 3 || \
+    (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 4)
+OGRGeometry *OGRGeometry::DelaunayTriangulation(double /*dfTolerance*/,
+                                                int /*bOnlyEdges*/) const
 {
     CPLError( CE_Failure, CPLE_NotSupported,
               "GEOS 3.4 or later needed for DelaunayTriangulation." );
     return NULL;
 }
 #else
-OGRGeometry *OGRGeometry::DelaunayTriangulation(double dfTolerance, int bOnlyEdges) const
+OGRGeometry *OGRGeometry::DelaunayTriangulation( double dfTolerance,
+                                                 int bOnlyEdges ) const
 {
     GEOSGeom hThisGeosGeom = NULL;
-    GEOSGeom hGeosProduct = NULL;
     OGRGeometry *poOGRProduct = NULL;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
     if( hThisGeosGeom != NULL )
     {
-        hGeosProduct = GEOSDelaunayTriangulation_r( hGEOSCtxt, hThisGeosGeom, dfTolerance, bOnlyEdges );
+        GEOSGeom hGeosProduct =
+            GEOSDelaunayTriangulation_r( hGEOSCtxt, hThisGeosGeom, dfTolerance,
+                                         bOnlyEdges );
         GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
         if( hGeosProduct != NULL )
         {
-            poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt,  hGeosProduct );
+            poOGRProduct =
+                OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct );
             if( poOGRProduct != NULL && getSpatialReference() != NULL )
                 poOGRProduct->assignSpatialReference(getSpatialReference());
             GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
@@ -4868,7 +5520,8 @@ OGRGeometry *OGRGeometry::DelaunayTriangulation(double dfTolerance, int bOnlyEdg
 /**
  * \brief Return a Delaunay triangulation of the vertices of the geometry.
  *
- * This function is the same as the C++ method OGRGeometry::DelaunayTriangulation().
+ * This function is the same as the C++ method
+ * OGRGeometry::DelaunayTriangulation().
  *
  * This function is built on the GEOS library, v3.4 or above.
  * If OGR is built without the GEOS library, this function will always fail,
@@ -4879,16 +5532,22 @@ OGRGeometry *OGRGeometry::DelaunayTriangulation(double dfTolerance, int bOnlyEdg
  * @param bOnlyEdges if TRUE, will return a MULTILINESTRING, otherwise it will
  *                   return a GEOMETRYCOLLECTION containing triangular POLYGONs.
  *
- * @return the geometry resulting from the Delaunay triangulation or NULL if an error occurs.
+ * @return the geometry resulting from the Delaunay triangulation or
+ * NULL if an error occurs.
  *
  * @since OGR 2.1
  */
 
-OGRGeometryH OGR_G_DelaunayTriangulation( OGRGeometryH hThis, double dfTolerance, int bOnlyEdges )
+OGRGeometryH OGR_G_DelaunayTriangulation( OGRGeometryH hThis,
+                                          double dfTolerance,
+                                          int bOnlyEdges )
 
 {
     VALIDATE_POINTER1( hThis, "OGR_G_DelaunayTriangulation", NULL );
-    return (OGRGeometryH) ((OGRGeometry *) hThis)->DelaunayTriangulation( dfTolerance, bOnlyEdges );
+
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hThis)->
+            DelaunayTriangulation(dfTolerance, bOnlyEdges));
 }
 
 /************************************************************************/
@@ -4915,7 +5574,8 @@ OGRGeometryH OGR_G_DelaunayTriangulation( OGRGeometryH hThis, double dfTolerance
  * If OGR is built without the GEOS library, this method will always fail,
  * issuing a CPLE_NotSupported error.
  *
- * @return a newly allocated geometry now owned by the caller, or NULL on failure.
+ * @return a newly allocated geometry now owned by the caller, or NULL
+ * on failure.
  *
  * @since OGR 1.9.0
  */
@@ -4923,6 +5583,12 @@ OGRGeometryH OGR_G_DelaunayTriangulation( OGRGeometryH hThis, double dfTolerance
 OGRGeometry *OGRGeometry::Polygonize() const
 
 {
+    if (EQUAL(getGeometryName(), "TRIANGLE"))
+    {
+        OGRPolygon *poPolygon = new OGRPolygon(*((OGRPolygon *)this));
+        return poPolygon;
+    }
+
 #ifndef HAVE_GEOS
 
     CPLError( CE_Failure, CPLE_NotSupported,
@@ -4941,17 +5607,16 @@ OGRGeometry *OGRGeometry::Polygonize() const
     int iCount = poColl->getNumGeometries();
 
     GEOSGeom *hGeosGeomList = NULL;
-    GEOSGeom hGeosPolygs = NULL;
     OGRGeometry *poPolygsOGRGeom = NULL;
     bool bError = false;
 
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
 
     hGeosGeomList = new GEOSGeom [iCount];
-    for ( int ig = 0; ig < iCount; ig++)
+    for( int ig = 0; ig < iCount; ig++ )
     {
         GEOSGeom hGeosGeom = NULL;
-        OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(ig);
+        OGRGeometry *poChild = poColl->getGeometryRef(ig);
         if( poChild == NULL ||
             wkbFlatten(poChild->getGeometryType()) != wkbLineString )
             bError = true;
@@ -4966,18 +5631,20 @@ OGRGeometry *OGRGeometry::Polygonize() const
 
     if( !bError )
     {
-        hGeosPolygs = GEOSPolygonize_r( hGEOSCtxt, hGeosGeomList, iCount );
+        GEOSGeom hGeosPolygs =
+            GEOSPolygonize_r(hGEOSCtxt, hGeosGeomList, iCount);
 
         if( hGeosPolygs != NULL )
         {
-            poPolygsOGRGeom = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosPolygs);
+            poPolygsOGRGeom =
+                OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosPolygs);
             if( poPolygsOGRGeom != NULL && getSpatialReference() != NULL )
                 poPolygsOGRGeom->assignSpatialReference(getSpatialReference());
             GEOSGeom_destroy_r( hGEOSCtxt, hGeosPolygs);
         }
     }
 
-    for ( int ig = 0; ig < iCount; ig++)
+    for( int ig = 0; ig < iCount; ig++ )
     {
         GEOSGeom hGeosGeom = *(hGeosGeomList + ig);
         if( hGeosGeom != NULL)
@@ -4988,7 +5655,7 @@ OGRGeometry *OGRGeometry::Polygonize() const
 
     return poPolygsOGRGeom;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -5022,7 +5689,8 @@ OGRGeometryH OGR_G_Polygonize( OGRGeometryH hTarget )
 {
     VALIDATE_POINTER1( hTarget, "OGR_G_Polygonize", NULL );
 
-    return (OGRGeometryH) ((OGRGeometry *) hTarget)->Polygonize();
+    return reinterpret_cast<OGRGeometryH>(
+        reinterpret_cast<OGRGeometry *>(hTarget)->Polygonize());
 }
 
 /************************************************************************/
@@ -5062,6 +5730,9 @@ struct _OGRPreparedGeometry
 /*                       OGRHasPreparedGeometrySupport()                */
 /************************************************************************/
 
+/** Returns if GEOS has prepared geometry support.
+ * @return TRUE or FALSE
+ */
 int OGRHasPreparedGeometrySupport()
 {
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
@@ -5075,6 +5746,13 @@ int OGRHasPreparedGeometrySupport()
 /*                         OGRCreatePreparedGeometry()                  */
 /************************************************************************/
 
+/** Creates a prepared geometry.
+ *
+ * To free with OGRDestroyPreparedGeometry()
+ *
+ * @param poGeom input geometry to prepare.
+ * @return handle to a prepared geometry.
+ */
 OGRPreparedGeometry* OGRCreatePreparedGeometry( UNUSED_IF_NO_GEOS const OGRGeometry* poGeom )
 {
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
@@ -5108,6 +5786,9 @@ OGRPreparedGeometry* OGRCreatePreparedGeometry( UNUSED_IF_NO_GEOS const OGRGeome
 /*                        OGRDestroyPreparedGeometry()                  */
 /************************************************************************/
 
+/** Destroys a prepared geometry.
+ * @param poPreparedGeom preprated geometry.
+ */
 void OGRDestroyPreparedGeometry( UNUSED_IF_NO_GEOS OGRPreparedGeometry* poPreparedGeom )
 {
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
@@ -5125,20 +5806,28 @@ void OGRDestroyPreparedGeometry( UNUSED_IF_NO_GEOS OGRPreparedGeometry* poPrepar
 /*                      OGRPreparedGeometryIntersects()                 */
 /************************************************************************/
 
-int OGRPreparedGeometryIntersects( UNUSED_IF_NO_GEOS const OGRPreparedGeometry* poPreparedGeom,
-                                   UNUSED_IF_NO_GEOS const OGRGeometry* poOtherGeom )
+/** Returns whether a prepared geometry intersects with a geometry.
+ * @param poPreparedGeom prepared geometry.
+ * @param poOtherGeom other geometry.
+ * @return TRUE or FALSE.
+ */
+int OGRPreparedGeometryIntersects(
+    UNUSED_IF_NO_GEOS const OGRPreparedGeometry* poPreparedGeom,
+    UNUSED_IF_NO_GEOS const OGRGeometry* poOtherGeom )
 {
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
     if( poPreparedGeom == NULL || poOtherGeom == NULL )
         return FALSE;
 
-    GEOSGeom hGEOSOtherGeom = poOtherGeom->exportToGEOS(poPreparedGeom->hGEOSCtxt);
+    GEOSGeom hGEOSOtherGeom =
+        poOtherGeom->exportToGEOS(poPreparedGeom->hGEOSCtxt);
     if( hGEOSOtherGeom == NULL )
         return FALSE;
 
-    int bRet = GEOSPreparedIntersects_r(poPreparedGeom->hGEOSCtxt,
-                                        poPreparedGeom->poPreparedGEOSGeom,
-                                        hGEOSOtherGeom);
+    const bool bRet = CPL_TO_BOOL(
+        GEOSPreparedIntersects_r(poPreparedGeom->hGEOSCtxt,
+                                 poPreparedGeom->poPreparedGEOSGeom,
+                                 hGEOSOtherGeom));
     GEOSGeom_destroy_r( poPreparedGeom->hGEOSCtxt, hGEOSOtherGeom );
 
     return bRet;
@@ -5147,20 +5836,28 @@ int OGRPreparedGeometryIntersects( UNUSED_IF_NO_GEOS const OGRPreparedGeometry*
 #endif
 }
 
-int OGRPreparedGeometryContains( UNUSED_IF_NO_GEOS const OGRPreparedGeometry* poPreparedGeom,
-                                 UNUSED_IF_NO_GEOS const OGRGeometry* poOtherGeom )
+/** Returns whether a prepared geometry contains a geometry.
+ * @param poPreparedGeom prepared geometry.
+ * @param poOtherGeom other geometry.
+ * @return TRUE or FALSE.
+ */
+int OGRPreparedGeometryContains(
+    UNUSED_IF_NO_GEOS const OGRPreparedGeometry* poPreparedGeom,
+    UNUSED_IF_NO_GEOS const OGRGeometry* poOtherGeom )
 {
 #ifdef HAVE_GEOS_PREPARED_GEOMETRY
     if( poPreparedGeom == NULL || poOtherGeom == NULL )
         return FALSE;
 
-    GEOSGeom hGEOSOtherGeom = poOtherGeom->exportToGEOS(poPreparedGeom->hGEOSCtxt);
+    GEOSGeom hGEOSOtherGeom =
+        poOtherGeom->exportToGEOS(poPreparedGeom->hGEOSCtxt);
     if( hGEOSOtherGeom == NULL )
         return FALSE;
 
-    int bRet = GEOSPreparedContains_r(poPreparedGeom->hGEOSCtxt,
-                                      poPreparedGeom->poPreparedGEOSGeom,
-                                      hGEOSOtherGeom);
+    const bool bRet = CPL_TO_BOOL(
+        GEOSPreparedContains_r(poPreparedGeom->hGEOSCtxt,
+                               poPreparedGeom->poPreparedGEOSGeom,
+                               hGEOSOtherGeom));
     GEOSGeom_destroy_r( poPreparedGeom->hGEOSCtxt, hGEOSOtherGeom );
 
     return bRet;
@@ -5174,10 +5871,10 @@ int OGRPreparedGeometryContains( UNUSED_IF_NO_GEOS const OGRPreparedGeometry* po
 /************************************************************************/
 
 /* Flags for creating WKB format for PostGIS */
-#define WKBZOFFSET 0x80000000
-#define WKBMOFFSET 0x40000000
+// #define WKBZOFFSET 0x80000000
+// #define WKBMOFFSET 0x40000000
 #define WKBSRIDFLAG 0x20000000
-#define WKBBBOXFLAG 0x10000000
+// #define WKBBBOXFLAG 0x10000000
 
 OGRGeometry *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID,
                                   int bIsPostGIS1_EWKB )
@@ -5185,7 +5882,7 @@ OGRGeometry *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID,
 {
     OGRGeometry *poGeometry = NULL;
 
-    if (nLength < 5)
+    if( nLength < 5 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid EWKB content : %d bytes", nLength );
@@ -5198,7 +5895,7 @@ OGRGeometry *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID,
     OGRwkbByteOrder eByteOrder = (pabyWKB[0] == 0 ? wkbXDR : wkbNDR);
 
 /* -------------------------------------------------------------------- */
-/*      PostGIS EWKB format includes an  SRID, but this won't be        */
+/*      PostGIS EWKB format includes an SRID, but this won't be         */
 /*      understood by OGR, so if the SRID flag is set, we remove the    */
 /*      SRID (bytes at offset 5 to 8).                                  */
 /* -------------------------------------------------------------------- */
@@ -5234,19 +5931,17 @@ OGRGeometry *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID,
 /************************************************************************/
 
 OGRGeometry *OGRGeometryFromHexEWKB( const char *pszBytea, int* pnSRID,
-                                     int bIsPostGIS1_EWKB  )
+                                     int bIsPostGIS1_EWKB )
 
 {
-    GByte   *pabyWKB;
-    int     nWKBLength=0;
-    OGRGeometry *poGeometry;
-
     if( pszBytea == NULL )
         return NULL;
 
-    pabyWKB = CPLHexToBinary(pszBytea, &nWKBLength);
+    int nWKBLength = 0;
+    GByte *pabyWKB = CPLHexToBinary(pszBytea, &nWKBLength);
 
-    poGeometry = OGRGeometryFromEWKB(pabyWKB, nWKBLength, pnSRID, bIsPostGIS1_EWKB);
+    OGRGeometry *poGeometry =
+        OGRGeometryFromEWKB(pabyWKB, nWKBLength, pnSRID, bIsPostGIS1_EWKB);
 
     CPLFree(pabyWKB);
 
@@ -5260,19 +5955,15 @@ OGRGeometry *OGRGeometryFromHexEWKB( const char *pszBytea, int* pnSRID,
 char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
                             int nPostGISMajor, int nPostGISMinor )
 {
-    GByte       *pabyWKB;
-    char        *pszTextBuf;
-    char        *pszTextBufCurrent;
-    char        *pszHex;
-
-    int nWkbSize = poGeometry->WkbSize();
-    pabyWKB = (GByte *) CPLMalloc(nWkbSize);
+    const int nWkbSize = poGeometry->WkbSize();
+    GByte *pabyWKB = static_cast<GByte *>(CPLMalloc(nWkbSize));
 
     if( (nPostGISMajor > 2 || (nPostGISMajor == 2 && nPostGISMinor >= 2)) &&
         wkbFlatten(poGeometry->getGeometryType()) == wkbPoint &&
         poGeometry->IsEmpty() )
     {
-        if( poGeometry->exportToWkb( wkbNDR, pabyWKB, wkbVariantIso ) != OGRERR_NONE )
+        if( poGeometry->exportToWkb( wkbNDR, pabyWKB,
+                                     wkbVariantIso ) != OGRERR_NONE )
         {
             CPLFree( pabyWKB );
             return CPLStrdup("");
@@ -5285,52 +5976,52 @@ char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
         return CPLStrdup("");
     }
 
-    /* When converting to hex, each byte takes 2 hex characters.  In addition
-       we add in 8 characters to represent the SRID integer in hex, and
-       one for a null terminator */
+    // When converting to hex, each byte takes 2 hex characters.  In addition
+    // we add in 8 characters to represent the SRID integer in hex, and
+    // one for a null terminator.
 
-    int pszSize = nWkbSize*2 + 8 + 1;
-    pszTextBuf = (char *) CPLMalloc(pszSize);
-    pszTextBufCurrent = pszTextBuf;
+    const int pszSize = nWkbSize * 2 + 8 + 1;
+    char *pszTextBuf = static_cast<char *>(CPLMalloc(pszSize));
+    char *pszTextBufCurrent = pszTextBuf;
 
-    /* Convert the 1st byte, which is the endianness flag, to hex. */
-    pszHex = CPLBinaryToHex( 1, pabyWKB );
+    // Convert the 1st byte, which is the endianness flag, to hex.
+    char *pszHex = CPLBinaryToHex( 1, pabyWKB );
     strcpy(pszTextBufCurrent, pszHex );
     CPLFree ( pszHex );
     pszTextBufCurrent += 2;
 
-    /* Next, get the geom type which is bytes 2 through 5 */
+    // Next, get the geom type which is bytes 2 through 5.
     GUInt32 geomType;
     memcpy( &geomType, pabyWKB+1, 4 );
 
-    /* Now add the SRID flag if an SRID is provided */
-    if (nSRSId > 0)
+    // Now add the SRID flag if an SRID is provided.
+    if( nSRSId > 0 )
     {
-        /* Change the flag to wkbNDR (little) endianness */
+        // Change the flag to wkbNDR (little) endianness.
         GUInt32 nGSrsFlag = CPL_LSBWORD32( WKBSRIDFLAG );
-        /* Apply the flag */
+        // Apply the flag.
         geomType = geomType | nGSrsFlag;
     }
 
-    /* Now write the geom type which is 4 bytes */
+    // Now write the geom type which is 4 bytes.
     pszHex = CPLBinaryToHex( 4, (GByte*) &geomType );
     strcpy(pszTextBufCurrent, pszHex );
     CPLFree ( pszHex );
     pszTextBufCurrent += 8;
 
-    /* Now include SRID if provided */
-    if (nSRSId > 0)
+    // Now include SRID if provided.
+    if( nSRSId > 0 )
     {
-        /* Force the srsid to wkbNDR (little) endianness */
-        GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );
-        pszHex = CPLBinaryToHex( sizeof(nGSRSId),(GByte*) &nGSRSId );
+        // Force the srsid to wkbNDR (little) endianness.
+        const GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );
+        pszHex = CPLBinaryToHex( sizeof(nGSRSId), (GByte*) &nGSRSId );
         strcpy(pszTextBufCurrent, pszHex );
         CPLFree ( pszHex );
         pszTextBufCurrent += 8;
     }
 
-    /* Copy the rest of the data over - subtract
-       5 since we already copied 5 bytes above */
+    // Copy the rest of the data over - subtract
+    // 5 since we already copied 5 bytes above.
     pszHex = CPLBinaryToHex( nWkbSize - 5, pabyWKB + 5 );
     strcpy(pszTextBufCurrent, pszHex );
     CPLFree ( pszHex );
@@ -5352,11 +6043,11 @@ char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
  * @param dfMaxLength maximum length between 2 consecutive vertices.
  */
 
-
 /************************************************************************/
 /*                       importPreambuleFromWkb()                       */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 OGRErr OGRGeometry::importPreambuleFromWkb( unsigned char * pabyData,
                                             int nSize,
                                             OGRwkbByteOrder& eByteOrder,
@@ -5369,7 +6060,7 @@ OGRErr OGRGeometry::importPreambuleFromWkb( unsigned char * pabyData,
 /*      Get the byte order byte.                                        */
 /* -------------------------------------------------------------------- */
     int nByteOrder = DB2_V72_FIX_BYTE_ORDER(*pabyData);
-    if (!( nByteOrder == wkbXDR || nByteOrder == wkbNDR ))
+    if( !( nByteOrder == wkbXDR || nByteOrder == wkbNDR ) )
         return OGRERR_CORRUPT_DATA;
     eByteOrder = (OGRwkbByteOrder) nByteOrder;
 
@@ -5377,7 +6068,8 @@ OGRErr OGRGeometry::importPreambuleFromWkb( unsigned char * pabyData,
 /*      Get the geometry feature type.                                  */
 /* -------------------------------------------------------------------- */
     OGRwkbGeometryType eGeometryType;
-    OGRErr err = OGRReadWKBGeometryType( pabyData, eWkbVariant, &eGeometryType );
+    const OGRErr err =
+        OGRReadWKBGeometryType( pabyData, eWkbVariant, &eGeometryType );
     if( wkbHasZ(eGeometryType) )
         flags |= OGR_G_3D;
     if( wkbHasM(eGeometryType) )
@@ -5430,14 +6122,14 @@ OGRErr OGRGeometry::importPreambuleOfCollectionFromWkb( unsigned char * pabyData
     if( OGR_SWAP( eByteOrder ) )
         nGeomCount = CPL_SWAP32(nGeomCount);
 
-    if (nGeomCount < 0 || nGeomCount > INT_MAX / 4)
+    if( nGeomCount < 0 || nGeomCount > INT_MAX / 4 )
     {
         nGeomCount = 0;
         return OGRERR_CORRUPT_DATA;
     }
 
-    /* Each ring has a minimum of nMinSubGeomSize bytes */
-    if (nSize != -1 && nSize - 9 < nGeomCount * nMinSubGeomSize)
+    // Each ring has a minimum of nMinSubGeomSize bytes.
+    if( nSize != -1 && nSize - 9 < nGeomCount * nMinSubGeomSize )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Length of input WKB is too small" );
@@ -5459,17 +6151,19 @@ OGRErr OGRGeometry::importPreambuleOfCollectionFromWkb( unsigned char * pabyData
 /*      OGRMultiCurve.                                                  */
 /************************************************************************/
 
-OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
-                                                  int bAllowEmptyComponent,
-                                                  int bAllowLineString,
-                                                  int bAllowCurve,
-                                                  int bAllowCompoundCurve,
-                                                  OGRErr (*pfnAddCurveDirectly)(OGRGeometry* poSelf, OGRCurve* poCurve) )
+OGRErr OGRGeometry::importCurveCollectionFromWkt(
+    char ** ppszInput,
+    int bAllowEmptyComponent,
+    int bAllowLineString,
+    int bAllowCurve,
+    int bAllowCompoundCurve,
+    OGRErr (*pfnAddCurveDirectly)(OGRGeometry* poSelf, OGRCurve* poCurve) )
 
 {
-    int bHasZ = FALSE, bHasM = FALSE;
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
     bool bIsEmpty = false;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    OGRErr eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     flags = 0;
     if( eErr != OGRERR_NONE )
         return eErr;
@@ -5478,21 +6172,21 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
     if( bIsEmpty )
         return OGRERR_NONE;
 
-    char        szToken[OGR_WKT_TOKEN_MAX];
-    const char  *pszInput = *ppszInput;
+    char szToken[OGR_WKT_TOKEN_MAX];
+    const char *pszInput = *ppszInput;
     eErr = OGRERR_NONE;
 
-    /* Skip first '(' */
+    // Skip first '('.
     pszInput = OGRWktReadToken( pszInput, szToken );
 
 /* ==================================================================== */
-/*      Read each curve in turn.   Note that we try to reuse the same   */
+/*      Read each curve in turn.  Note that we try to reuse the same    */
 /*      point list buffer from curve to curve to cut down on            */
 /*      allocate/deallocate overhead.                                   */
 /* ==================================================================== */
     OGRRawPoint *paoPoints = NULL;
-    int          nMaxPoints = 0;
-    double      *padfZ = NULL;
+    int nMaxPoints = 0;
+    double *padfZ = NULL;
 
     do
     {
@@ -5507,38 +6201,49 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
     /*      Do the import.                                                  */
     /* -------------------------------------------------------------------- */
         OGRCurve* poCurve = NULL;
-        if (EQUAL(szToken,"("))
+        if( EQUAL(szToken, "(") )
         {
             OGRLineString* poLine = new OGRLineString();
             poCurve = poLine;
             pszInput = pszInputBefore;
-            eErr = poLine->importFromWKTListOnly( (char**)&pszInput, bHasZ, bHasM,
-                                                   paoPoints, nMaxPoints, padfZ );
+            eErr = poLine->importFromWKTListOnly(
+                const_cast<char **>(&pszInput),
+                bHasZ, bHasM,
+                paoPoints, nMaxPoints,
+                padfZ );
         }
-        else if (bAllowEmptyComponent && EQUAL(szToken, "EMPTY") )
+        else if( bAllowEmptyComponent && EQUAL(szToken, "EMPTY") )
         {
             poCurve = new OGRLineString();
         }
-        /* We accept LINESTRING() but this is an extension to the BNF, also */
-        /* accepted by PostGIS */
-        else if ( (bAllowLineString && EQUAL(szToken,"LINESTRING")) ||
-                  (bAllowCurve && !EQUAL(szToken,"LINESTRING") &&
-                   !EQUAL(szToken,"COMPOUNDCURVE") && OGR_GT_IsCurve(OGRFromOGCGeomType(szToken))) ||
-                  (bAllowCompoundCurve && EQUAL(szToken,"COMPOUNDCURVE")) )
+        // Accept LINESTRING(), but this is an extension to the BNF, also
+        // accepted by PostGIS.
+        else if( (bAllowLineString && EQUAL(szToken, "LINESTRING")) ||
+                 (bAllowCurve && !EQUAL(szToken, "LINESTRING") &&
+                  !EQUAL(szToken, "COMPOUNDCURVE") &&
+                  OGR_GT_IsCurve(OGRFromOGCGeomType(szToken))) ||
+                 (bAllowCompoundCurve && EQUAL(szToken, "COMPOUNDCURVE")) )
         {
             OGRGeometry* poGeom = NULL;
             pszInput = pszInputBefore;
-            eErr = OGRGeometryFactory::createFromWkt( (char **) &pszInput,
-                                                       NULL, &poGeom );
-            poCurve = (OGRCurve*) poGeom;
+            eErr = OGRGeometryFactory::createFromWkt(
+                const_cast<char **>(&pszInput),
+                NULL, &poGeom );
+            poCurve = dynamic_cast<OGRCurve *>(poGeom);
+            if( poCurve == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRCurve.");
+            }
         }
         else
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Unexpected token : %s", szToken);
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unexpected token : %s", szToken);
             eErr = OGRERR_CORRUPT_DATA;
         }
 
-        /* if this has M it is an error if poGeom does not have M */
+        // If this has M it is an error if poGeom does not have M.
         if( poCurve && !Is3D() && IsMeasured() && !poCurve->IsMeasured() )
             eErr = OGRERR_CORRUPT_DATA;
 
@@ -5554,7 +6259,6 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
 /*      Read the delimiter following the surface.                       */
 /* -------------------------------------------------------------------- */
         pszInput = OGRWktReadToken( pszInput, szToken );
-
     } while( szToken[0] == ',' && eErr == OGRERR_NONE );
 
     CPLFree( paoPoints );
@@ -5573,12 +6277,14 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
     *ppszInput = (char *) pszInput;
     return OGRERR_NONE;
 }
+//! @endcond
 
 /************************************************************************/
 /*                          OGR_GT_Flatten()                            */
 /************************************************************************/
 /**
- * \brief Returns the 2D geometry type corresponding to the passed geometry type.
+ * \brief Returns the 2D geometry type corresponding to the passed geometry
+ * type.
  *
  * This function is intended to work with geometry types as old-style 99-402
  * extended dimension (Z) WKB types, as well as with newer SFSQL 1.2 and
@@ -5594,11 +6300,11 @@ OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
 OGRwkbGeometryType OGR_GT_Flatten( OGRwkbGeometryType eType )
 {
     eType = (OGRwkbGeometryType) (eType & (~wkb25DBitInternalUse));
-    if( eType >= 1000 && eType < 2000 ) /* ISO Z */
+    if( eType >= 1000 && eType < 2000 )  // ISO Z.
         return (OGRwkbGeometryType) (eType - 1000);
-    if( eType >= 2000 && eType < 3000 ) /* ISO M */
+    if( eType >= 2000 && eType < 3000 )  // ISO M.
         return (OGRwkbGeometryType) (eType - 2000);
-    if( eType >= 3000 && eType < 4000 ) /* ISO ZM */
+    if( eType >= 3000 && eType < 4000 )  // ISO ZM.
         return (OGRwkbGeometryType) (eType - 3000);
     return eType;
 }
@@ -5620,9 +6326,9 @@ int OGR_GT_HasZ( OGRwkbGeometryType eType )
 {
     if( eType & wkb25DBitInternalUse )
         return TRUE;
-    if( eType >= 1000 && eType < 2000 ) /* we accept 1000 for wkbUnknownZ */
+    if( eType >= 1000 && eType < 2000 )  // Accept 1000 for wkbUnknownZ.
         return TRUE;
-    if( eType >= 3000 && eType < 4000 ) /* we accept 3000 for wkbUnknownZM */
+    if( eType >= 3000 && eType < 4000 )  // Accept 3000 for wkbUnknownZM.
         return TRUE;
     return FALSE;
 }
@@ -5642,9 +6348,9 @@ int OGR_GT_HasZ( OGRwkbGeometryType eType )
 
 int OGR_GT_HasM( OGRwkbGeometryType eType )
 {
-    if( eType >= 2000 && eType < 3000 ) /* we accept 2000 for wkbUnknownM */
+    if( eType >= 2000 && eType < 3000 )  // Accept 2000 for wkbUnknownM.
         return TRUE;
-    if( eType >= 3000 && eType < 4000 ) /* we accept 3000 for wkbUnknownZM */
+    if( eType >= 3000 && eType < 4000 )  // Accept 3000 for wkbUnknownZM.
         return TRUE;
     return FALSE;
 }
@@ -5754,7 +6460,7 @@ int OGR_GT_IsSubClassOf( OGRwkbGeometryType eType,
                eType == wkbMultiSurface;
 
     if( eSuperType == wkbCurvePolygon )
-        return eType == wkbPolygon;
+        return eType == wkbPolygon || eType == wkbTriangle;
 
     if( eSuperType == wkbMultiCurve )
         return eType == wkbMultiLineString;
@@ -5767,7 +6473,15 @@ int OGR_GT_IsSubClassOf( OGRwkbGeometryType eType,
                eType == wkbCompoundCurve;
 
     if( eSuperType == wkbSurface )
-        return eType == wkbCurvePolygon || eType == wkbPolygon;
+        return eType == wkbCurvePolygon || eType == wkbPolygon ||
+               eType == wkbTriangle ||
+               eType == wkbPolyhedralSurface || eType == wkbTIN;
+
+    if( eSuperType == wkbPolygon )
+        return eType == wkbTriangle;
+
+    if (eSuperType == wkbPolyhedralSurface)
+        return eType == wkbTIN;
 
     return FALSE;
 }
@@ -5779,7 +6493,8 @@ int OGR_GT_IsSubClassOf( OGRwkbGeometryType eType,
  * \brief Returns the collection type that can contain the passed geometry type
  *
  * Handled conversions are : wkbNone->wkbNone, wkbPoint -> wkbMultiPoint,
- * wkbLineString->wkbMultiLineString, wkbPolygon->wkbMultiPolygon,
+ * wkbLineString->wkbMultiLineString,
+ * wkbPolygon/wkbTriangle/wkbPolyhedralSurface/wkbTIN->wkbMultiPolygon,
  * wkbCircularString->wkbMultiCurve, wkbCompoundCurve->wkbMultiCurve,
  * wkbCurvePolygon->wkbMultiSurface.
  * In other cases, wkbUnknown is returned
@@ -5810,6 +6525,9 @@ OGRwkbGeometryType OGR_GT_GetCollection( OGRwkbGeometryType eType )
     else if( eFGType == wkbPolygon )
         eType = wkbMultiPolygon;
 
+    else if( eFGType == wkbTriangle )
+        eType = wkbTIN;
+
     else if( OGR_GT_IsCurve(eFGType) )
         eType = wkbMultiCurve;
 
@@ -5859,6 +6577,9 @@ OGRwkbGeometryType OGR_GT_GetCurve( OGRwkbGeometryType eType )
     else if( eFGType == wkbPolygon )
         eType = wkbCurvePolygon;
 
+    else if( eFGType == wkbTriangle )
+        eType = wkbCurvePolygon;
+
     else if( eFGType == wkbMultiLineString )
         eType = wkbMultiCurve;
 
@@ -5991,6 +6712,7 @@ int OGR_GT_IsNonLinear( OGRwkbGeometryType eGeomType )
 /*                          CastToError()                               */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 OGRGeometry* OGRGeometry::CastToError(OGRGeometry* poGeom)
 {
     CPLError(CE_Failure, CPLE_AppDefined,
@@ -5998,3 +6720,222 @@ OGRGeometry* OGRGeometry::CastToError(OGRGeometry* poGeom)
     delete poGeom;
     return NULL;
 }
+//! @endcond
+
+/************************************************************************/
+/*                          OGRexportToSFCGAL()                         */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+sfcgal_geometry_t* OGRGeometry::OGRexportToSFCGAL(UNUSED_IF_NO_SFCGAL OGRGeometry *poGeom)
+{
+#ifdef HAVE_SFCGAL
+    sfcgal_init();
+    char *buffer;
+
+    // special cases - LinearRing, Circular String, Compound Curve, Curve Polygon
+
+    if (EQUAL(poGeom->getGeometryName(), "LINEARRING"))
+    {
+        // cast it to LineString and get the WKT
+        OGRLineString *poLineString = OGRCurve::CastToLineString((OGRCurve *)poGeom);
+        if (poLineString->exportToWkt(&buffer) == OGRERR_NONE)
+        {
+            size_t length = 0;
+            while(buffer[length++] != '\0');
+            length--;
+            sfcgal_geometry_t *_geometry = sfcgal_io_read_wkt(buffer,length);
+            free(buffer);
+            return _geometry;
+        }
+        else
+            return NULL;
+    }
+    else if (EQUAL(poGeom->getGeometryName(), "CIRCULARSTRING"))
+    {
+        // cast it to LineString and get the WKT
+        OGRLineString *poLineString = OGRCurve::CastToLineString((OGRCurve *)poGeom);
+        if (poLineString->exportToWkt(&buffer) == OGRERR_NONE)
+        {
+            size_t length = 0;
+            while(buffer[length++] != '\0');
+            length--;
+            sfcgal_geometry_t *_geometry = sfcgal_io_read_wkt(buffer,length);
+            free(buffer);
+            return _geometry;
+        }
+        else
+            return NULL;
+    }
+    else if (EQUAL(poGeom->getGeometryName(), "COMPOUNDCURVE"))
+    {
+        // cast it to LineString and get the WKT
+        OGRLineString *poLineString = OGRCurve::CastToLineString((OGRCompoundCurve *)poGeom);
+        if (poLineString->exportToWkt(&buffer) == OGRERR_NONE)
+        {
+            size_t length = 0;
+            while(buffer[length++] != '\0');
+            length--;
+            sfcgal_geometry_t *_geometry = sfcgal_io_read_wkt(buffer,length);
+            free(buffer);
+            return _geometry;
+        }
+        else
+            return NULL;
+    }
+    else if (EQUAL(poGeom->getGeometryName(), "CURVEPOLYGON"))
+    {
+        // cast it to Polygon and get the WKT
+        OGRPolygon *poPolygon = (OGRPolygon *)OGRGeometryFactory::forceToPolygon((OGRCurvePolygon *)poGeom);
+        if (poPolygon->exportToWkt(&buffer) == OGRERR_NONE)
+        {
+            size_t length = 0;
+            while(buffer[length++] != '\0');
+            length--;
+            sfcgal_geometry_t *_geometry = sfcgal_io_read_wkt(buffer,length);
+            free(buffer);
+            return _geometry;
+        }
+        else
+            return NULL;
+    }
+    else if (poGeom->exportToWkt(&buffer) == OGRERR_NONE)
+    {
+        size_t length = 0;
+        while(buffer[length++] != '\0');
+        length--;
+        sfcgal_geometry_t *_geometry = sfcgal_io_read_wkt(buffer,length);
+        free(buffer);
+        return _geometry;
+    }
+    else
+        return NULL;
+#else
+    CPLError( CE_Failure, CPLE_NotSupported, "SFCGAL support not enabled." );
+    return NULL;
+#endif
+}
+//! @endcond
+
+/************************************************************************/
+/*                          SFCGALexportToOGR()                         */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRGeometry* OGRGeometry::SFCGALexportToOGR(
+    UNUSED_IF_NO_SFCGAL sfcgal_geometry_t* geometry )
+{
+#ifdef HAVE_SFCGAL
+
+    sfcgal_init();
+    char* pabySFCGALWKT = NULL;
+    size_t nLength = 0;
+    sfcgal_geometry_as_text_decim(geometry, 19, &pabySFCGALWKT, &nLength);
+    char* pszWKT = static_cast<char*>(CPLMalloc(nLength + 1));
+    memcpy(pszWKT, pabySFCGALWKT, nLength);
+    pszWKT[nLength] = 0;
+    free(pabySFCGALWKT);
+    char *pszTmpWKT = pszWKT;
+
+    sfcgal_geometry_type_t geom_type = sfcgal_geometry_type_id (geometry);
+
+    OGRGeometry *poGeom = NULL;
+    if( geom_type == SFCGAL_TYPE_POINT )
+    {
+        poGeom = new OGRPoint();
+    }
+    else if( geom_type == SFCGAL_TYPE_LINESTRING )
+    {
+        poGeom = new OGRLineString();
+    }
+    else if( geom_type == SFCGAL_TYPE_POLYGON )
+    {
+        poGeom = new OGRPolygon();
+    }
+    else if( geom_type == SFCGAL_TYPE_MULTIPOINT )
+    {
+        poGeom = new OGRMultiPoint();
+    }
+    else if( geom_type == SFCGAL_TYPE_MULTILINESTRING )
+    {
+        poGeom = new OGRMultiLineString();
+    }
+    else if( geom_type == SFCGAL_TYPE_MULTIPOLYGON )
+    {
+        poGeom = new OGRMultiPolygon();
+    }
+    else if( geom_type == SFCGAL_TYPE_GEOMETRYCOLLECTION )
+    {
+        poGeom = new OGRGeometryCollection();
+    }
+    else if( geom_type == SFCGAL_TYPE_TRIANGLE )
+    {
+        poGeom = new OGRTriangle();
+    }
+    else if( geom_type == SFCGAL_TYPE_POLYHEDRALSURFACE )
+    {
+        poGeom = new OGRPolyhedralSurface();
+    }
+    else if( geom_type == SFCGAL_TYPE_TRIANGULATEDSURFACE )
+    {
+        poGeom = new OGRTriangulatedSurface();
+    }
+    else
+    {
+        return NULL;
+    }
+
+    if( poGeom->importFromWkt(&pszTmpWKT) == OGRERR_NONE )
+    {
+        CPLFree(pszWKT);
+        return poGeom;
+    }
+    else
+    {
+        delete poGeom;
+        CPLFree(pszWKT);
+        return NULL;
+    }
+
+#else
+    CPLError( CE_Failure, CPLE_NotSupported, "SFCGAL support not enabled." );
+    return NULL;
+#endif
+}
+//! @endcond
+
+//! @cond Doxygen_Suppress
+OGRBoolean OGRGeometry::IsSFCGALCompatible() const
+{
+    const OGRwkbGeometryType eGType = wkbFlatten(getGeometryType());
+    if( eGType== wkbTriangle || eGType == wkbPolyhedralSurface ||
+        eGType == wkbTIN )
+    {
+        return TRUE;
+    }
+    if( eGType == wkbGeometryCollection || eGType == wkbMultiSurface )
+    {
+        const OGRGeometryCollection *poGC =
+                            dynamic_cast<const OGRGeometryCollection *>(this);
+        bool bIsSFCGALCompatible = false;
+        for( int iGeom = 0; poGC != NULL &&
+                            iGeom < poGC->getNumGeometries(); iGeom++ )
+        {
+            OGRwkbGeometryType eSubGeomType =
+                wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType());
+            if( eSubGeomType == wkbTIN ||
+                eSubGeomType == wkbPolyhedralSurface )
+            {
+                bIsSFCGALCompatible = true;
+            }
+            else if( eSubGeomType != wkbMultiPolygon )
+            {
+                bIsSFCGALCompatible = false;
+                break;
+            }
+        }
+        return bIsSFCGALCompatible;
+    }
+    return FALSE;
+}
+//! @endcond
diff --git a/ogr/ogrgeometrycollection.cpp b/ogr/ogrgeometrycollection.cpp
index 420d37b..fd58c3b 100644
--- a/ogr/ogrgeometrycollection.cpp
+++ b/ogr/ogrgeometrycollection.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeometrycollection.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRGeometryCollection class.
@@ -28,11 +27,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
-#include "ogr_p.h"
+
+#include <cstddef>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
 
-CPL_CVSID("$Id: ogrgeometrycollection.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrgeometrycollection.cpp 37821 2017-03-21 13:15:44Z rouault $");
 
 /************************************************************************/
 /*                       OGRGeometryCollection()                        */
@@ -62,10 +72,11 @@ OGRGeometryCollection::OGRGeometryCollection()
  * @since GDAL 2.1
  */
 
-OGRGeometryCollection::OGRGeometryCollection( const OGRGeometryCollection& other ) :
-    OGRGeometry( other ),
-    nGeomCount( 0 ),
-    papoGeoms( NULL )
+OGRGeometryCollection::OGRGeometryCollection(
+    const OGRGeometryCollection& other ) :
+    OGRGeometry(other),
+    nGeomCount(0),
+    papoGeoms(NULL)
 {
     for( int i = 0; i < other.nGeomCount; i++ )
     {
@@ -96,7 +107,8 @@ OGRGeometryCollection::~OGRGeometryCollection()
  * @since GDAL 2.1
  */
 
-OGRGeometryCollection& OGRGeometryCollection::operator=( const OGRGeometryCollection& other )
+OGRGeometryCollection& OGRGeometryCollection::operator=(
+    const OGRGeometryCollection& other )
 {
     if( this != &other)
     {
@@ -125,7 +137,7 @@ void OGRGeometryCollection::empty()
         {
             delete papoGeoms[i];
         }
-        OGRFree( papoGeoms );
+        CPLFree( papoGeoms );
     }
 
     nGeomCount = 0;
@@ -139,10 +151,8 @@ void OGRGeometryCollection::empty()
 OGRGeometry *OGRGeometryCollection::clone() const
 
 {
-    OGRGeometryCollection       *poNewGC;
-
-    poNewGC = (OGRGeometryCollection*)
-            OGRGeometryFactory::createGeometry(getGeometryType());
+    OGRGeometryCollection *poNewGC = dynamic_cast<OGRGeometryCollection *>(
+        OGRGeometryFactory::createGeometry(getGeometryType()));
     if( poNewGC == NULL )
         return NULL;
     poNewGC->assignSpatialReference( getSpatialReference() );
@@ -185,8 +195,8 @@ int OGRGeometryCollection::getDimension() const
 
 {
     int nDimension = 0;
-    /* FIXME? Not sure if it is really appropriate to take the max in case */
-    /* of geometries of different dimension... */
+    // FIXME? Not sure if it is really appropriate to take the max in case
+    // of geometries of different dimension.
     for( int i = 0; i < nGeomCount; i++ )
     {
         int nSubGeomDimension = papoGeoms[i]->getDimension();
@@ -250,7 +260,7 @@ int OGRGeometryCollection::getNumGeometries() const
 /**
  * \brief Fetch geometry from container.
  *
- * This method returns a pointer to an geometry within the container.  The
+ * This method returns a pointer to a geometry within the container.  The
  * returned geometry remains owned by the container, and should not be
  * modified.  The pointer is only valid until the next change to the
  * geometry container.  Use IGeometry::clone() to make a copy.
@@ -267,17 +277,32 @@ OGRGeometry * OGRGeometryCollection::getGeometryRef( int i )
 {
     if( i < 0 || i >= nGeomCount )
         return NULL;
-    else
-        return papoGeoms[i];
+
+    return papoGeoms[i];
 }
 
+/**
+ * \brief Fetch geometry from container.
+ *
+ * This method returns a pointer to a geometry within the container.  The
+ * returned geometry remains owned by the container, and should not be
+ * modified.  The pointer is only valid until the next change to the
+ * geometry container.  Use IGeometry::clone() to make a copy.
+ *
+ * This method relates to the SFCOM IGeometryCollection::get_Geometry() method.
+ *
+ * @param i the index of the geometry to fetch, between 0 and
+ *          getNumGeometries() - 1.
+ * @return pointer to requested geometry.
+ */
+
 const OGRGeometry * OGRGeometryCollection::getGeometryRef( int i ) const
 
 {
     if( i < 0 || i >= nGeomCount )
         return NULL;
-    else
-        return papoGeoms[i];
+
+    return papoGeoms[i];
 }
 
 /************************************************************************/
@@ -309,11 +334,10 @@ OGRErr OGRGeometryCollection::addGeometry( const OGRGeometry * poNewGeom )
 
 {
     OGRGeometry *poClone = poNewGeom->clone();
-    OGRErr      eErr;
-
     if( poClone == NULL )
         return OGRERR_FAILURE;
-    eErr = addGeometryDirectly( poClone );
+
+    const OGRErr eErr = addGeometryDirectly( poClone );
     if( eErr != OGRERR_NONE )
         delete poClone;
 
@@ -353,27 +377,23 @@ OGRErr OGRGeometryCollection::addGeometryDirectly( OGRGeometry * poNewGeom )
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
 
     if( poNewGeom->Is3D() && !Is3D() )
-
         set3D(TRUE);
 
     if( poNewGeom->IsMeasured() && !IsMeasured() )
-
         setMeasured(TRUE);
 
     if( !poNewGeom->Is3D() && Is3D() )
-
         poNewGeom->set3D(TRUE);
 
     if( !poNewGeom->IsMeasured() && IsMeasured() )
-
         poNewGeom->setMeasured(TRUE);
 
-    OGRGeometry** papoNewGeoms = (OGRGeometry **) VSI_REALLOC_VERBOSE( papoGeoms,
-                                             sizeof(void*) * (nGeomCount+1) );
+    OGRGeometry** papoNewGeoms = static_cast<OGRGeometry **>(
+        VSI_REALLOC_VERBOSE(papoGeoms, sizeof(void*) * (nGeomCount + 1)));
     if( papoNewGeoms == NULL )
         return OGRERR_FAILURE;
-    papoGeoms = papoNewGeoms;
 
+    papoGeoms = papoNewGeoms;
     papoGeoms[nGeomCount] = poNewGeom;
 
     nGeomCount++;
@@ -441,7 +461,7 @@ OGRErr OGRGeometryCollection::removeGeometry( int iGeom, int bDelete )
 int OGRGeometryCollection::WkbSize() const
 
 {
-    int         nSize = 9;
+    int nSize = 9;
 
     for( int i = 0; i < nGeomCount; i++ )
     {
@@ -460,7 +480,7 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
                                                      OGRwkbVariant eWkbVariant )
 
 {
-    /* Arbitrary value, but certainly large enough for reasonable use cases. */
+    // Arbitrary value, but certainly large enough for reasonable use cases.
     if( nRecLevel == 32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -483,9 +503,10 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
     if( eErr != OGRERR_NONE )
         return eErr;
 
-    /* coverity[tainted_data] */
-    papoGeoms = (OGRGeometry **) VSI_CALLOC_VERBOSE(sizeof(void*), nGeomCount);
-    if (nGeomCount != 0 && papoGeoms == NULL)
+    // coverity[tainted_data]
+    papoGeoms = static_cast<OGRGeometry **>(
+        VSI_CALLOC_VERBOSE(sizeof(void*), nGeomCount));
+    if( nGeomCount != 0 && papoGeoms == NULL )
     {
         nGeomCount = 0;
         return OGRERR_NOT_ENOUGH_MEMORY;
@@ -496,21 +517,24 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
 /* -------------------------------------------------------------------- */
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
-        /* Parses sub-geometry */
+        // Parses sub-geometry.
         unsigned char* pabySubData = pabyData + nDataOffset;
         if( nSize < 9 && nSize != -1 )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        OGRwkbGeometryType eSubGeomType;
-        eErr = OGRReadWKBGeometryType( pabySubData, eWkbVariant, &eSubGeomType );
+        OGRwkbGeometryType eSubGeomType = wkbUnknown;
+        eErr = OGRReadWKBGeometryType( pabySubData, eWkbVariant,
+                                       &eSubGeomType );
         if( eErr != OGRERR_NONE )
             return eErr;
 
         if( !isCompatibleSubType(eSubGeomType) )
         {
             nGeomCount = iGeom;
-            CPLDebug("OGR", "Cannot add geometry of type (%d) to geometry of type (%d)",
-                     eSubGeomType, getGeometryType());
+            CPLDebug(
+                "OGR",
+                "Cannot add geometry of type (%d) to geometry of type (%d)",
+                eSubGeomType, getGeometryType());
             return OGRERR_CORRUPT_DATA;
         }
 
@@ -522,7 +546,8 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
                 eErr = OGRERR_FAILURE;
             else
                 eErr = ((OGRGeometryCollection*)poSubGeom)->
-                        importFromWkbInternal( pabySubData, nSize, nRecLevel + 1, eWkbVariant );
+                        importFromWkbInternal( pabySubData, nSize,
+                                               nRecLevel + 1, eWkbVariant );
         }
         else
         {
@@ -540,12 +565,12 @@ OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
 
         papoGeoms[iGeom] = poSubGeom;
 
-        if (papoGeoms[iGeom]->Is3D())
+        if( papoGeoms[iGeom]->Is3D() )
             flags |= OGR_G_3D;
-        if (papoGeoms[iGeom]->IsMeasured())
+        if( papoGeoms[iGeom]->IsMeasured() )
             flags |= OGR_G_MEASURED;
 
-        int nSubGeomWkbSize = papoGeoms[iGeom]->WkbSize();
+        const int nSubGeomWkbSize = papoGeoms[iGeom]->WkbSize();
         if( nSize != -1 )
             nSize -= nSubGeomWkbSize;
 
@@ -576,15 +601,16 @@ OGRErr OGRGeometryCollection::importFromWkb( unsigned char * pabyData,
 /*      Build a well known binary representation of this object.        */
 /************************************************************************/
 
-OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
-                                            unsigned char * pabyData,
-                                            OGRwkbVariant eWkbVariant ) const
+OGRErr OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
+                                           unsigned char * pabyData,
+                                           OGRwkbVariant eWkbVariant ) const
 
 {
     if( eWkbVariant == wkbVariantOldOgc &&
         (wkbFlatten(getGeometryType()) == wkbMultiCurve ||
-         wkbFlatten(getGeometryType()) == wkbMultiSurface) ) /* does not make sense for new geometries, so patch it */
+         wkbFlatten(getGeometryType()) == wkbMultiSurface) )
     {
+        // Does not make sense for new geometries, so patch it.
         eWkbVariant = wkbVariantIso;
     }
 
@@ -599,24 +625,25 @@ OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* -------------------------------------------------------------------- */
     GUInt32 nGType = getGeometryType();
 
-    if ( eWkbVariant == wkbVariantIso )
+    if( eWkbVariant == wkbVariantIso )
         nGType = getIsoGeometryType();
     else if( eWkbVariant == wkbVariantPostGIS1 )
     {
-        int bIs3D = wkbHasZ((OGRwkbGeometryType)nGType);
+        const bool bIs3D = wkbHasZ(static_cast<OGRwkbGeometryType>(nGType));
         nGType = wkbFlatten(nGType);
         if( nGType == wkbMultiCurve )
             nGType = POSTGIS15_MULTICURVE;
         else if( nGType == wkbMultiSurface )
             nGType = POSTGIS15_MULTISURFACE;
         if( bIs3D )
-            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
+            // Yes, explicitly set wkb25DBit.
+            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse);
     }
 
-    if( eByteOrder == wkbNDR )
-        nGType = CPL_LSBWORD32( nGType );
-    else
-        nGType = CPL_MSBWORD32( nGType );
+    if( OGR_SWAP( eByteOrder ) )
+    {
+        nGType = CPL_SWAP32(nGType);
+    }
 
     memcpy( pabyData + 1, &nGType, 4 );
 
@@ -640,16 +667,19 @@ OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* ==================================================================== */
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
-        papoGeoms[iGeom]->exportToWkb( eByteOrder, pabyData + nOffset, eWkbVariant );
-        // Should normally not happen if everyone else does its job
-        // but has happened sometimes (#6332)
-        if( papoGeoms[iGeom]->getCoordinateDimension() != getCoordinateDimension() )
+        papoGeoms[iGeom]->exportToWkb( eByteOrder, pabyData + nOffset,
+                                       eWkbVariant );
+        // Should normally not happen if everyone else does its job,
+        // but has happened sometimes. (#6332)
+        if( papoGeoms[iGeom]->getCoordinateDimension() !=
+            getCoordinateDimension() )
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Sub-geometry %d has coordinate dimension %d, but container has %d",
-                      iGeom,
-                      papoGeoms[iGeom]->getCoordinateDimension(),
-                      getCoordinateDimension() );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Sub-geometry %d has coordinate dimension %d, "
+                     "but container has %d",
+                     iGeom,
+                     papoGeoms[iGeom]->getCoordinateDimension(),
+                     getCoordinateDimension() );
         }
 
         nOffset += papoGeoms[iGeom]->WkbSize();
@@ -662,10 +692,11 @@ OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
 /*                       importFromWktInternal()                        */
 /************************************************************************/
 
-OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRecLevel )
+OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput,
+                                                     int nRecLevel )
 
 {
-    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    // Arbitrary value, but certainly large enough for reasonable usages.
     if( nRecLevel == 32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -674,9 +705,10 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
         return OGRERR_CORRUPT_DATA;
     }
 
-    int bHasZ = FALSE, bHasM = FALSE;
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
     bool bIsEmpty = false;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    OGRErr eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     if( eErr != OGRERR_NONE )
         return eErr;
     if( bHasZ ) flags |= OGR_G_3D;
@@ -684,10 +716,10 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
     if( bIsEmpty )
         return OGRERR_NONE;
 
-    char        szToken[OGR_WKT_TOKEN_MAX];
-    const char  *pszInput = *ppszInput;
+    char szToken[OGR_WKT_TOKEN_MAX] = {};
+    const char *pszInput = *ppszInput;
 
-    /* Skip first '(' */
+    // Skip first '('.
     pszInput = OGRWktReadToken( pszInput, szToken );
 
 /* ==================================================================== */
@@ -705,11 +737,12 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
     /* -------------------------------------------------------------------- */
     /*      Do the import.                                                  */
     /* -------------------------------------------------------------------- */
-        if (EQUAL(szToken,"GEOMETRYCOLLECTION"))
+        if( EQUAL(szToken, "GEOMETRYCOLLECTION") )
         {
             poGeom = new OGRGeometryCollection();
             eErr = ((OGRGeometryCollection*)poGeom)->
-                        importFromWktInternal( (char **) &pszInput, nRecLevel + 1 );
+                        importFromWktInternal( (char **) &pszInput,
+                                               nRecLevel + 1 );
         }
         else
             eErr = OGRGeometryFactory::createFromWkt( (char **) &pszInput,
@@ -717,7 +750,8 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
 
         if( eErr == OGRERR_NONE )
         {
-            /* if this has M but not Z it is an error if poGeom does not have M */
+            // If this has M, but not Z, it is an error if poGeom does
+            // not have M.
             if( !Is3D() && IsMeasured() && !poGeom->IsMeasured() )
                 eErr = OGRERR_CORRUPT_DATA;
             else
@@ -734,7 +768,6 @@ OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRec
 /* -------------------------------------------------------------------- */
 
         pszInput = OGRWktReadToken( pszInput, szToken );
-
     } while( szToken[0] == ',' );
 
 /* -------------------------------------------------------------------- */
@@ -762,7 +795,7 @@ OGRErr OGRGeometryCollection::importFromWkt( char ** ppszInput )
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
-/*      equivalent.  This could be made a lot more CPU efficient!        */
+/*      equivalent.  This could be made a lot more CPU efficient.       */
 /************************************************************************/
 
 OGRErr OGRGeometryCollection::exportToWkt( char ** ppszDstText,
@@ -771,25 +804,28 @@ OGRErr OGRGeometryCollection::exportToWkt( char ** ppszDstText,
     return exportToWktInternal(ppszDstText, eWkbVariant, NULL);
 }
 
-OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
-                                           OGRwkbVariant eWkbVariant,
-                                           const char* pszSkipPrefix ) const
+//! @cond Doxygen_Suppress
+OGRErr
+OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
+                                            OGRwkbVariant eWkbVariant,
+                                            const char* pszSkipPrefix ) const
 
 {
-    char        **papszGeoms;
-    int         iGeom;
-    size_t      nCumulativeLength = 0;
-    OGRErr      eErr;
+    size_t nCumulativeLength = 0;
+    OGRErr eErr = OGRERR_NONE;
     bool bMustWriteComma = false;
 
 /* -------------------------------------------------------------------- */
 /*      Build a list of strings containing the stuff for each Geom.     */
 /* -------------------------------------------------------------------- */
-    papszGeoms = (nGeomCount) ? (char **) CPLCalloc(sizeof(char *),nGeomCount) : NULL;
+    char **papszGeoms =
+        nGeomCount
+        ? static_cast<char **>(CPLCalloc(sizeof(char *), nGeomCount))
+        : NULL;
 
-    for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+    for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
-        eErr = papoGeoms[iGeom]->exportToWkt( &(papszGeoms[iGeom]), eWkbVariant );
+        eErr = papoGeoms[iGeom]->exportToWkt(&(papszGeoms[iGeom]), eWkbVariant);
         if( eErr != OGRERR_NONE )
             goto error;
 
@@ -806,10 +842,11 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
             if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "Z ") )
                 nSkip += 2;
 
-            /* skip empty subgeoms */
+            // Skip empty subgeoms.
             if( papszGeoms[iGeom][nSkip] != '(' )
             {
-                CPLDebug( "OGR", "OGRGeometryCollection::exportToWkt() - skipping %s.",
+                CPLDebug( "OGR",
+                          "OGRGeometryCollection::exportToWkt() - skipping %s.",
                           papszGeoms[iGeom] );
                 CPLFree( papszGeoms[iGeom] );
                 papszGeoms[iGeom] = NULL;
@@ -818,9 +855,12 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
         }
         else if( eWkbVariant != wkbVariantIso )
         {
-            char *substr;
+            char *substr = NULL;
+            // TODO(schwehr): Looks dangerous.  Cleanup.
             if( (substr = strstr(papszGeoms[iGeom], " Z")) != NULL )
-                memmove(substr, substr+strlen(" Z"), 1+strlen(substr+strlen(" Z")));
+                memmove(substr,
+                        substr + strlen(" Z"),
+                        1 + strlen(substr + strlen(" Z")));
         }
 
         nCumulativeLength += strlen(papszGeoms[iGeom] + nSkip);
@@ -836,16 +876,18 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
         if( eWkbVariant == wkbVariantIso )
         {
             if( Is3D() && IsMeasured() )
-                osEmpty.Printf("%s ZM EMPTY",getGeometryName());
+                osEmpty.Printf("%s ZM EMPTY", getGeometryName());
             else if( IsMeasured() )
-                osEmpty.Printf("%s M EMPTY",getGeometryName());
+                osEmpty.Printf("%s M EMPTY", getGeometryName());
             else if( Is3D() )
-                osEmpty.Printf("%s Z EMPTY",getGeometryName());
+                osEmpty.Printf("%s Z EMPTY", getGeometryName());
             else
-                osEmpty.Printf("%s EMPTY",getGeometryName());
+                osEmpty.Printf("%s EMPTY", getGeometryName());
         }
         else
-            osEmpty.Printf("%s EMPTY",getGeometryName());
+        {
+            osEmpty.Printf("%s EMPTY", getGeometryName());
+        }
         *ppszDstText = CPLStrdup(osEmpty);
         return OGRERR_NONE;
     }
@@ -853,7 +895,8 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
 /* -------------------------------------------------------------------- */
 /*      Allocate the right amount of space for the aggregated string    */
 /* -------------------------------------------------------------------- */
-    *ppszDstText = (char *) VSI_MALLOC_VERBOSE(nCumulativeLength + nGeomCount + 26);
+    *ppszDstText = static_cast<char *>(
+        VSI_MALLOC_VERBOSE(nCumulativeLength + nGeomCount + 26));
 
     if( *ppszDstText == NULL )
     {
@@ -877,7 +920,7 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
     strcat( *ppszDstText, " (" );
     nCumulativeLength = strlen(*ppszDstText);
 
-    for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+    for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
         if( papszGeoms[iGeom] == NULL )
             continue;
@@ -900,8 +943,10 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
                 nSkip += 2;
         }
 
-        size_t nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
-        memcpy( *ppszDstText + nCumulativeLength, papszGeoms[iGeom] + nSkip, nGeomLength );
+        const size_t nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
+        memcpy( *ppszDstText + nCumulativeLength,
+                papszGeoms[iGeom] + nSkip,
+                nGeomLength );
         nCumulativeLength += nGeomLength;
         VSIFree( papszGeoms[iGeom] );
     }
@@ -914,11 +959,12 @@ OGRErr OGRGeometryCollection::exportToWktInternal( char ** ppszDstText,
     return OGRERR_NONE;
 
 error:
-    for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+    for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
         CPLFree( papszGeoms[iGeom] );
     CPLFree( papszGeoms );
     return eErr;
 }
+//! @endcond
 
 /************************************************************************/
 /*                            getEnvelope()                             */
@@ -927,7 +973,7 @@ error:
 void OGRGeometryCollection::getEnvelope( OGREnvelope * psEnvelope ) const
 
 {
-    OGREnvelope3D         oEnv3D;
+    OGREnvelope3D oEnv3D;
     getEnvelope(&oEnv3D);
     psEnvelope->MinX = oEnv3D.MinX;
     psEnvelope->MinY = oEnv3D.MinY;
@@ -942,30 +988,29 @@ void OGRGeometryCollection::getEnvelope( OGREnvelope * psEnvelope ) const
 void OGRGeometryCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
 
 {
-    OGREnvelope3D       oGeomEnv;
-    bool                bExtentSet = false;
+    OGREnvelope3D oGeomEnv;
+    bool bExtentSet = false;
 
+    *psEnvelope = OGREnvelope3D();
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
-        if (!papoGeoms[iGeom]->IsEmpty())
+        if( !papoGeoms[iGeom]->IsEmpty() )
         {
-            if (!bExtentSet)
-            {
-                papoGeoms[iGeom]->getEnvelope( psEnvelope );
-                bExtentSet = true;
-            }
-            else
-            {
-                papoGeoms[iGeom]->getEnvelope( &oGeomEnv );
-                psEnvelope->Merge( oGeomEnv );
-            }
+            bExtentSet = true;
+            papoGeoms[iGeom]->getEnvelope( &oGeomEnv );
+            psEnvelope->Merge( oGeomEnv );
         }
     }
 
-    if (!bExtentSet)
+    if( !bExtentSet )
     {
-        psEnvelope->MinX = psEnvelope->MinY = psEnvelope->MinZ = 0;
-        psEnvelope->MaxX = psEnvelope->MaxY = psEnvelope->MaxZ = 0;
+        // To be backward compatible when called on empty geom
+        psEnvelope->MinX = 0.0;
+        psEnvelope->MinY = 0.0;
+        psEnvelope->MinZ = 0.0;
+        psEnvelope->MaxX = 0.0;
+        psEnvelope->MaxY = 0.0;
+        psEnvelope->MaxZ = 0.0;
     }
 }
 
@@ -982,14 +1027,14 @@ OGRBoolean OGRGeometryCollection::Equals( OGRGeometry * poOther ) const
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
-    if ( IsEmpty() && poOther->IsEmpty() )
+    if( IsEmpty() && poOther->IsEmpty() )
         return TRUE;
 
     OGRGeometryCollection *poOGC = (OGRGeometryCollection *) poOther;
     if( getNumGeometries() != poOGC->getNumGeometries() )
         return FALSE;
 
-    // we should eventually test the SRS.
+    // TODO(schwehr): Should test the SRS.
 
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
@@ -1007,22 +1052,17 @@ OGRBoolean OGRGeometryCollection::Equals( OGRGeometry * poOther ) const
 OGRErr OGRGeometryCollection::transform( OGRCoordinateTransformation *poCT )
 
 {
-#ifdef DISABLE_OGRGEOM_TRANSFORM
-    return OGRERR_FAILURE;
-#else
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
-        OGRErr  eErr;
-
-        eErr = papoGeoms[iGeom]->transform( poCT );
+        const OGRErr eErr = papoGeoms[iGeom]->transform( poCT );
         if( eErr != OGRERR_NONE )
         {
             if( iGeom != 0 )
             {
                 CPLDebug("OGR",
-                         "OGRGeometryCollection::transform() failed for a geometry other\n"
-                         "than the first, meaning some geometries are transformed\n"
-                         "and some are not!\n" );
+                         "OGRGeometryCollection::transform() failed for a "
+                         "geometry other than the first, meaning some "
+                         "geometries are transformed and some are not." );
 
                 return OGRERR_FAILURE;
             }
@@ -1034,7 +1074,6 @@ OGRErr OGRGeometryCollection::transform( OGRCoordinateTransformation *poCT )
     assignSpatialReference( poCT->GetTargetCS() );
 
     return OGRERR_NONE;
-#endif
 }
 
 /************************************************************************/
@@ -1047,7 +1086,16 @@ void OGRGeometryCollection::closeRings()
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
         if( wkbFlatten(papoGeoms[iGeom]->getGeometryType()) == wkbPolygon )
-            ((OGRPolygon *) papoGeoms[iGeom])->closeRings();
+        {
+            OGRPolygon *poPoly = dynamic_cast<OGRPolygon *>(papoGeoms[iGeom]);
+            if( poPoly == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRPolygon.");
+                return;
+            }
+            poPoly->closeRings();
+        }
     }
 }
 
@@ -1086,7 +1134,6 @@ void OGRGeometryCollection::setMeasured( OGRBoolean bIsMeasured )
     OGRGeometry::setMeasured( bIsMeasured );
 }
 
-
 /************************************************************************/
 /*                              get_Length()                            */
 /************************************************************************/
@@ -1100,7 +1147,7 @@ void OGRGeometryCollection::setMeasured( OGRBoolean bIsMeasured )
  * @note No warning will be issued if a member of the collection does not
  *       support the get_Length method.
  *
- * @return computed area.
+ * @return computed length.
  */
 
 double OGRGeometryCollection::get_Length() const
@@ -1109,15 +1156,31 @@ double OGRGeometryCollection::get_Length() const
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
         OGRGeometry* geom = papoGeoms[iGeom];
-        OGRwkbGeometryType eType = wkbFlatten(geom->getGeometryType());
+        const OGRwkbGeometryType eType = wkbFlatten(geom->getGeometryType());
         if( OGR_GT_IsCurve(eType) )
         {
-            dfLength += ((OGRCurve *) geom)->get_Length();
+            OGRCurve *poCurve = dynamic_cast<OGRCurve *>(geom);
+            if( poCurve == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRCurve.");
+                return 0.0;
+            }
+            dfLength += poCurve->get_Length();
         }
         else if( OGR_GT_IsSubClassOf(eType, wkbMultiCurve) ||
-                eType == wkbGeometryCollection )
+                 eType == wkbGeometryCollection )
         {
-            dfLength += ((OGRGeometryCollection *) geom)->get_Length();
+            OGRGeometryCollection *poColl =
+                dynamic_cast<OGRGeometryCollection *>(geom);
+            if( poColl == NULL )
+            {
+                CPLError(
+                    CE_Fatal, CPLE_AppDefined,
+                    "dynamic_cast failed.  Expected OGRGeometryCollection.");
+                return 0.0;
+            }
+            dfLength += poColl->get_Length();
         }
     }
 
@@ -1149,11 +1212,25 @@ double OGRGeometryCollection::get_Area() const
         OGRwkbGeometryType eType = wkbFlatten(geom->getGeometryType());
         if( OGR_GT_IsSurface(eType) )
         {
-            dfArea += ((OGRSurface *) geom)->get_Area();
+            OGRSurface *poSurface = dynamic_cast<OGRSurface *>(geom);
+            if( poSurface == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRSurface.");
+                return 0.0;
+            }
+            dfArea += poSurface->get_Area();
         }
         else if( OGR_GT_IsCurve(eType) )
         {
-            dfArea += ((OGRCurve *) geom)->get_Area();
+            OGRCurve *poCurve = dynamic_cast<OGRCurve *>(geom);
+            if( poCurve == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRCurve.");
+                return 0.0;
+            }
+            dfArea += poCurve->get_Area();
         }
         else if( OGR_GT_IsSubClassOf(eType, wkbMultiSurface) ||
                 eType == wkbGeometryCollection )
@@ -1169,10 +1246,10 @@ double OGRGeometryCollection::get_Area() const
 /*                               IsEmpty()                              */
 /************************************************************************/
 
-OGRBoolean OGRGeometryCollection::IsEmpty(  ) const
+OGRBoolean OGRGeometryCollection::IsEmpty() const
 {
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
-        if (papoGeoms[iGeom]->IsEmpty() == FALSE)
+        if( papoGeoms[iGeom]->IsEmpty() == FALSE )
             return FALSE;
     return TRUE;
 }
@@ -1201,9 +1278,17 @@ void OGRGeometryCollection::swapXY()
 /*                          isCompatibleSubType()                       */
 /************************************************************************/
 
-OGRBoolean OGRGeometryCollection::isCompatibleSubType( OGRwkbGeometryType ) const
+/** Returns whether a geometry of the specified geometry type can be a
+ * member of this collection.
+ *
+ * @param eSubType type of the potential member
+ * @return TRUE or FALSE
+ */
+
+OGRBoolean OGRGeometryCollection::isCompatibleSubType(
+    CPL_UNUSED OGRwkbGeometryType eSubType ) const
 {
-    /* We accept all geometries as sub-geometries */
+    // Accept all geometries as sub-geometries.
     return TRUE;
 }
 
@@ -1211,7 +1296,8 @@ OGRBoolean OGRGeometryCollection::isCompatibleSubType( OGRwkbGeometryType ) cons
 /*                         hasCurveGeometry()                           */
 /************************************************************************/
 
-OGRBoolean OGRGeometryCollection::hasCurveGeometry(int bLookForNonLinear) const
+OGRBoolean OGRGeometryCollection::hasCurveGeometry(
+    int bLookForNonLinear ) const
 {
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
@@ -1225,8 +1311,9 @@ OGRBoolean OGRGeometryCollection::hasCurveGeometry(int bLookForNonLinear) const
 /*                         getLinearGeometry()                        */
 /************************************************************************/
 
-OGRGeometry* OGRGeometryCollection::getLinearGeometry(double dfMaxAngleStepSizeDegrees,
-                                                        const char* const* papszOptions) const
+OGRGeometry* OGRGeometryCollection::getLinearGeometry(
+    double dfMaxAngleStepSizeDegrees,
+    const char* const* papszOptions ) const
 {
     OGRGeometryCollection* poGC = (OGRGeometryCollection*)
         OGRGeometryFactory::createGeometry(OGR_GT_GetLinear(getGeometryType()));
@@ -1235,8 +1322,9 @@ OGRGeometry* OGRGeometryCollection::getLinearGeometry(double dfMaxAngleStepSizeD
     poGC->assignSpatialReference( getSpatialReference() );
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
-        OGRGeometry* poSubGeom = papoGeoms[iGeom]->getLinearGeometry(dfMaxAngleStepSizeDegrees,
-                                                                       papszOptions);
+        OGRGeometry* poSubGeom =
+            papoGeoms[iGeom]->getLinearGeometry(dfMaxAngleStepSizeDegrees,
+                                                papszOptions);
         poGC->addGeometryDirectly( poSubGeom );
     }
     return poGC;
@@ -1246,7 +1334,8 @@ OGRGeometry* OGRGeometryCollection::getLinearGeometry(double dfMaxAngleStepSizeD
 /*                             getCurveGeometry()                       */
 /************************************************************************/
 
-OGRGeometry* OGRGeometryCollection::getCurveGeometry(const char* const* papszOptions) const
+OGRGeometry* OGRGeometryCollection::getCurveGeometry(
+    const char* const* papszOptions) const
 {
     OGRGeometryCollection* poGC = (OGRGeometryCollection*)
         OGRGeometryFactory::createGeometry(OGR_GT_GetCurve(getGeometryType()));
@@ -1256,7 +1345,8 @@ OGRGeometry* OGRGeometryCollection::getCurveGeometry(const char* const* papszOpt
     bool bHasCurveGeometry = false;
     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     {
-        OGRGeometry* poSubGeom = papoGeoms[iGeom]->getCurveGeometry(papszOptions);
+        OGRGeometry* poSubGeom =
+            papoGeoms[iGeom]->getCurveGeometry(papszOptions);
         if( poSubGeom->hasCurveGeometry() )
             bHasCurveGeometry = true;
         poGC->addGeometryDirectly( poSubGeom );
@@ -1273,9 +1363,10 @@ OGRGeometry* OGRGeometryCollection::getCurveGeometry(const char* const* papszOpt
 /*                      TransferMembersAndDestroy()                     */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 OGRGeometryCollection* OGRGeometryCollection::TransferMembersAndDestroy(
-                                            OGRGeometryCollection* poSrc,
-                                            OGRGeometryCollection* poDst)
+    OGRGeometryCollection* poSrc,
+    OGRGeometryCollection* poDst )
 {
     poDst->assignSpatialReference(poSrc->getSpatialReference());
     poDst->set3D(poSrc->Is3D());
@@ -1287,3 +1378,30 @@ OGRGeometryCollection* OGRGeometryCollection::TransferMembersAndDestroy(
     delete poSrc;
     return poDst;
 }
+//! @endcond
+
+/************************************************************************/
+/*                        CastToGeometryCollection()                    */
+/************************************************************************/
+
+/**
+ * \brief Cast to geometry collection.
+ *
+ * This methods cast a derived class of geometry collection to a plain
+ * geometry collection.
+ *
+ * The passed in geometry is consumed and a new one returned (or NULL in case
+ * of failure).
+ *
+ * @param poSrc the input geometry - ownership is passed to the method.
+ * @return new geometry.
+ * @since GDAL 2.2
+ */
+
+OGRGeometryCollection* OGRGeometryCollection::CastToGeometryCollection(
+                                                OGRGeometryCollection* poSrc )
+{
+    if( wkbFlatten(poSrc->getGeometryType()) == wkbGeometryCollection )
+        return poSrc;
+    return TransferMembersAndDestroy(poSrc, new OGRGeometryCollection());
+}
diff --git a/ogr/ogrgeometryfactory.cpp b/ogr/ogrgeometryfactory.cpp
index 1097319..81fbe6b 100644
--- a/ogr/ogrgeometryfactory.cpp
+++ b/ogr/ogrgeometryfactory.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeometryfactory.cpp 37132 2017-01-12 21:29:13Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Factory for converting geometry to and from well known binary
@@ -29,11 +28,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
 #include "ogr_geometry.h"
 #include "ogr_api.h"
-#include "ogr_p.h"
+#include "ogr_core.h"
 #include "ogr_geos.h"
+#include "ogr_sfcgal.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
+#ifdef HAVE_GEOS
+#include "geos_c.h"
+#endif
+
+#include <climits>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+#include <cstddef>
+
+#include <algorithm>
 #include <new>
+#include <utility>
+#include <vector>
 
 #ifndef HAVE_GEOS
 #define UNUSED_IF_NO_GEOS CPL_UNUSED
@@ -41,14 +62,15 @@
 #define UNUSED_IF_NO_GEOS
 #endif
 
-CPL_CVSID("$Id: ogrgeometryfactory.cpp 37132 2017-01-12 21:29:13Z rouault $");
+CPL_CVSID("$Id: ogrgeometryfactory.cpp 37865 2017-03-30 20:13:32Z rouault $");
 
 /************************************************************************/
 /*                           createFromWkb()                            */
 /************************************************************************/
 
 /**
- * \brief Create a geometry object of the appropriate type from it's well known binary representation.
+ * \brief Create a geometry object of the appropriate type from it's
+ * well known binary representation.
  *
  * Note that if nBytes is passed as zero, no checking can be done on whether
  * the pabyData is sufficient.  This can result in a crash if the input
@@ -78,18 +100,13 @@ CPL_CVSID("$Id: ogrgeometryfactory.cpp 37132 2017-01-12 21:29:13Z rouault $");
  * OGRERR_CORRUPT_DATA may be returned.
  */
 
-OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
-                                         OGRSpatialReference * poSR,
-                                         OGRGeometry **ppoReturn,
-                                         int nBytes,
-                                         OGRwkbVariant eWkbVariant )
+OGRErr OGRGeometryFactory::createFromWkb( unsigned char *pabyData,
+                                          OGRSpatialReference * poSR,
+                                          OGRGeometry **ppoReturn,
+                                          int nBytes,
+                                          OGRwkbVariant eWkbVariant )
 
 {
-    OGRwkbGeometryType eGeometryType;
-    int             nByteOrder;
-    OGRErr      eErr;
-    OGRGeometry *poGeom;
-
     *ppoReturn = NULL;
 
     if( nBytes < 9 && nBytes != -1 )
@@ -99,12 +116,12 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
 /*      Get the byte order byte.  The extra tests are to work around    */
 /*      bug sin the WKB of DB2 v7.2 as identified by Safe Software.     */
 /* -------------------------------------------------------------------- */
-    nByteOrder = DB2_V72_FIX_BYTE_ORDER(*pabyData);
+    const int nByteOrder = DB2_V72_FIX_BYTE_ORDER(*pabyData);
     if( nByteOrder != wkbXDR && nByteOrder != wkbNDR )
     {
         CPLDebug( "OGR",
                   "OGRGeometryFactory::createFromWkb() - got corrupt data.\n"
-                  "%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
+                  "%02X%02X%02X%02X%02X%02X%02X%02X%02X",
                   pabyData[0],
                   pabyData[1],
                   pabyData[2],
@@ -123,17 +140,18 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
 /*      one byte.                                                       */
 /* -------------------------------------------------------------------- */
 
-    OGRErr err = OGRReadWKBGeometryType( pabyData, eWkbVariant, &eGeometryType );
+    OGRwkbGeometryType eGeometryType = wkbUnknown;
+    const OGRErr err =
+        OGRReadWKBGeometryType( pabyData, eWkbVariant, &eGeometryType );
 
     if( err != OGRERR_NONE )
         return err;
 
-
 /* -------------------------------------------------------------------- */
 /*      Instantiate a geometry of the appropriate type, and             */
 /*      initialize from the input stream.                               */
 /* -------------------------------------------------------------------- */
-    poGeom = createGeometry( eGeometryType );
+    OGRGeometry *poGeom = createGeometry( eGeometryType );
 
     if( poGeom == NULL )
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
@@ -141,36 +159,36 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
 /*      Import from binary.                                             */
 /* -------------------------------------------------------------------- */
-    eErr = poGeom->importFromWkb( pabyData, nBytes, eWkbVariant );
+    const OGRErr eErr = poGeom->importFromWkb( pabyData, nBytes, eWkbVariant );
+    if( eErr != OGRERR_NONE )
+    {
+        delete poGeom;
+        return eErr;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Assign spatial reference system.                                */
 /* -------------------------------------------------------------------- */
-    if( eErr == OGRERR_NONE )
-    {
-        if ( poGeom->hasCurveGeometry() &&
-             CSLTestBoolean(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE")) )
-        {
-            OGRGeometry* poNewGeom = poGeom->getLinearGeometry();
-            delete poGeom;
-            poGeom = poNewGeom;
-        }
-        poGeom->assignSpatialReference( poSR );
-        *ppoReturn = poGeom;
-    }
-    else
+
+    if( poGeom->hasCurveGeometry() &&
+        CPLTestBool(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE")) )
     {
+        OGRGeometry* poNewGeom = poGeom->getLinearGeometry();
         delete poGeom;
+        poGeom = poNewGeom;
     }
+    poGeom->assignSpatialReference( poSR );
+    *ppoReturn = poGeom;
 
-    return eErr;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
 /*                        OGR_G_CreateFromWkb()                         */
 /************************************************************************/
 /**
- * \brief Create a geometry object of the appropriate type from it's well known binary representation.
+ * \brief Create a geometry object of the appropriate type from it's
+ * well known binary representation.
  *
  * Note that if nBytes is passed as zero, no checking can be done on whether
  * the pabyData is sufficient.  This can result in a crash if the input
@@ -179,7 +197,7 @@ OGRErr OGRGeometryFactory::createFromWkb(unsigned char *pabyData,
  * geometry object.  Use OGR_G_WkbSize() on the returned geometry to
  * establish the number of bytes it required in WKB format.
  *
- * The OGRGeometryFactory::createFromWkb() CPP method  is the same as this
+ * The OGRGeometryFactory::createFromWkb() CPP method is the same as this
  * function.
  *
  * @param pabyData pointer to the input BLOB data.
@@ -203,10 +221,11 @@ OGRErr CPL_DLL OGR_G_CreateFromWkb( unsigned char *pabyData,
                                     int nBytes )
 
 {
-    return OGRGeometryFactory::createFromWkb( pabyData,
-                                              (OGRSpatialReference *) hSRS,
-                                              (OGRGeometry **) phGeometry,
-                                              nBytes );
+    return OGRGeometryFactory::createFromWkb(
+        pabyData,
+        reinterpret_cast<OGRSpatialReference *>(hSRS),
+        reinterpret_cast<OGRGeometry **>(phGeometry),
+        nBytes );
 }
 
 /************************************************************************/
@@ -214,7 +233,8 @@ OGRErr CPL_DLL OGR_G_CreateFromWkb( unsigned char *pabyData,
 /************************************************************************/
 
 /**
- * \brief Create a geometry object of the appropriate type from it's well known text representation.
+ * \brief Create a geometry object of the appropriate type from it's
+ * well known text representation.
  *
  * The C function OGR_G_CreateFromWkt() is the same as this method.
  *
@@ -252,82 +272,83 @@ OGRErr OGRGeometryFactory::createFromWkt(char **ppszData,
                                          OGRGeometry **ppoReturn )
 
 {
-    OGRErr      eErr;
-    char        szToken[OGR_WKT_TOKEN_MAX];
-    char        *pszInput = *ppszData;
-    OGRGeometry *poGeom;
-
+    char *pszInput = *ppszData;
     *ppoReturn = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Get the first token, which should be the geometry type.         */
 /* -------------------------------------------------------------------- */
+    char szToken[OGR_WKT_TOKEN_MAX] = {};
     if( OGRWktReadToken( pszInput, szToken ) == NULL )
         return OGRERR_CORRUPT_DATA;
 
 /* -------------------------------------------------------------------- */
 /*      Instantiate a geometry of the appropriate type.                 */
 /* -------------------------------------------------------------------- */
-    if( STARTS_WITH_CI(szToken,"POINT") )
+    OGRGeometry *poGeom = NULL;
+    if( STARTS_WITH_CI(szToken, "POINT") )
     {
         poGeom = new OGRPoint();
     }
-
-    else if( STARTS_WITH_CI(szToken,"LINESTRING") )
+    else if( STARTS_WITH_CI(szToken, "LINESTRING") )
     {
         poGeom = new OGRLineString();
     }
-
-    else if( STARTS_WITH_CI(szToken,"POLYGON") )
+    else if( STARTS_WITH_CI(szToken, "POLYGON") )
     {
         poGeom = new OGRPolygon();
     }
-
-    else if( STARTS_WITH_CI(szToken,"GEOMETRYCOLLECTION") )
+    else if( STARTS_WITH_CI(szToken,"TRIANGLE") )
+    {
+        poGeom = new OGRTriangle();
+    }
+    else if( STARTS_WITH_CI(szToken, "GEOMETRYCOLLECTION") )
     {
         poGeom = new OGRGeometryCollection();
     }
-
-    else if( STARTS_WITH_CI(szToken,"MULTIPOLYGON") )
+    else if( STARTS_WITH_CI(szToken, "MULTIPOLYGON") )
     {
         poGeom = new OGRMultiPolygon();
     }
-
-    else if( STARTS_WITH_CI(szToken,"MULTIPOINT") )
+    else if( STARTS_WITH_CI(szToken, "MULTIPOINT") )
     {
         poGeom = new OGRMultiPoint();
     }
-
-    else if( STARTS_WITH_CI(szToken,"MULTILINESTRING") )
+    else if( STARTS_WITH_CI(szToken, "MULTILINESTRING") )
     {
         poGeom = new OGRMultiLineString();
     }
-
-    else if( STARTS_WITH_CI(szToken,"CIRCULARSTRING") )
+    else if( STARTS_WITH_CI(szToken, "CIRCULARSTRING") )
     {
         poGeom = new OGRCircularString();
     }
-
-    else if( STARTS_WITH_CI(szToken,"COMPOUNDCURVE") )
+    else if( STARTS_WITH_CI(szToken, "COMPOUNDCURVE") )
     {
         poGeom = new OGRCompoundCurve();
     }
-
-    else if( STARTS_WITH_CI(szToken,"CURVEPOLYGON") )
+    else if( STARTS_WITH_CI(szToken, "CURVEPOLYGON") )
     {
         poGeom = new OGRCurvePolygon();
     }
-
-    else if( STARTS_WITH_CI(szToken,"MULTICURVE") )
+    else if( STARTS_WITH_CI(szToken, "MULTICURVE") )
     {
         poGeom = new OGRMultiCurve();
     }
-
-    else if( STARTS_WITH_CI(szToken,"MULTISURFACE") )
+    else if( STARTS_WITH_CI(szToken, "MULTISURFACE") )
     {
         poGeom = new OGRMultiSurface();
     }
 
+    else if( STARTS_WITH_CI(szToken,"POLYHEDRALSURFACE") )
+    {
+        poGeom = new OGRPolyhedralSurface();
+    }
+
+    else if( STARTS_WITH_CI(szToken,"TIN") )
+    {
+        poGeom = new OGRTriangulatedSurface();
+    }
+
     else
     {
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
@@ -336,15 +357,15 @@ OGRErr OGRGeometryFactory::createFromWkt(char **ppszData,
 /* -------------------------------------------------------------------- */
 /*      Do the import.                                                  */
 /* -------------------------------------------------------------------- */
-    eErr = poGeom->importFromWkt( &pszInput );
+    const OGRErr eErr = poGeom->importFromWkt( &pszInput );
 
 /* -------------------------------------------------------------------- */
 /*      Assign spatial reference system.                                */
 /* -------------------------------------------------------------------- */
     if( eErr == OGRERR_NONE )
     {
-        if ( poGeom->hasCurveGeometry() &&
-             CSLTestBoolean(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE")) )
+        if( poGeom->hasCurveGeometry() &&
+            CPLTestBool(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE")) )
         {
             OGRGeometry* poNewGeom = poGeom->getLinearGeometry();
             delete poGeom;
@@ -366,7 +387,8 @@ OGRErr OGRGeometryFactory::createFromWkt(char **ppszData,
 /*                        OGR_G_CreateFromWkt()                         */
 /************************************************************************/
 /**
- * \brief Create a geometry object of the appropriate type from it's well known text representation.
+ * \brief Create a geometry object of the appropriate type from it's well known
+ * text representation.
  *
  * The OGRGeometryFactory::createFromWkt CPP method is the same as this
  * function.
@@ -391,9 +413,10 @@ OGRErr CPL_DLL OGR_G_CreateFromWkt( char **ppszData,
                                     OGRGeometryH *phGeometry )
 
 {
-    return OGRGeometryFactory::createFromWkt( ppszData,
-                                              (OGRSpatialReference *) hSRS,
-                                              (OGRGeometry **) phGeometry );
+    return OGRGeometryFactory::createFromWkt(
+        ppszData,
+        reinterpret_cast<OGRSpatialReference *>(hSRS),
+        reinterpret_cast<OGRGeometry **>(phGeometry));
 }
 
 /************************************************************************/
@@ -460,6 +483,15 @@ OGRGeometryFactory::createGeometry( OGRwkbGeometryType eGeometryType )
       case wkbMultiSurface:
           return new (std::nothrow) OGRMultiSurface();
 
+      case wkbTriangle:
+          return new (std::nothrow) OGRTriangle();
+
+      case wkbPolyhedralSurface:
+          return new (std::nothrow) OGRPolyhedralSurface();
+
+      case wkbTIN:
+          return new (std::nothrow) OGRTriangulatedSurface();
+
       default:
           return NULL;
     }
@@ -480,17 +512,17 @@ OGRGeometryFactory::createGeometry( OGRwkbGeometryType eGeometryType )
  *
  * @param eGeometryType the type code of the geometry to be created.
  *
- * @return handle to the newly create geometry or NULL on failure. Should be freed with
- *         OGR_G_DestroyGeometry() after use.
+ * @return handle to the newly create geometry or NULL on failure. Should be
+ *         freed with OGR_G_DestroyGeometry() after use.
  */
 
 OGRGeometryH OGR_G_CreateGeometry( OGRwkbGeometryType eGeometryType )
 
 {
-    return (OGRGeometryH) OGRGeometryFactory::createGeometry( eGeometryType );
+    return reinterpret_cast<OGRGeometryH>(
+        OGRGeometryFactory::createGeometry(eGeometryType));
 }
 
-
 /************************************************************************/
 /*                          destroyGeometry()                           */
 /************************************************************************/
@@ -512,7 +544,6 @@ void OGRGeometryFactory::destroyGeometry( OGRGeometry *poGeom )
     delete poGeom;
 }
 
-
 /************************************************************************/
 /*                        OGR_G_DestroyGeometry()                       */
 /************************************************************************/
@@ -531,7 +562,7 @@ void OGRGeometryFactory::destroyGeometry( OGRGeometry *poGeom )
 void OGR_G_DestroyGeometry( OGRGeometryH hGeom )
 
 {
-    OGRGeometryFactory::destroyGeometry( (OGRGeometry *) hGeom );
+    OGRGeometryFactory::destroyGeometry(reinterpret_cast<OGRGeometry *>(hGeom));
 }
 
 /************************************************************************/
@@ -543,8 +574,9 @@ void OGR_G_DestroyGeometry( OGRGeometryH hGeom )
  *
  * Tries to force the provided geometry to be a polygon. This effects a change
  * on multipolygons.
- * Starting with GDAL 2.0, curve polygons or closed curves will be changed to polygons.
- * The passed in geometry is consumed and a new one returned (or potentially the same one).
+ * Starting with GDAL 2.0, curve polygons or closed curves will be changed to
+ * polygons.  The passed in geometry is consumed and a new one returned (or
+ * potentially the same one).
  *
  * @param poGeom the input geometry - ownership is passed to the method.
  * @return new geometry.
@@ -560,14 +592,28 @@ OGRGeometry *OGRGeometryFactory::forceToPolygon( OGRGeometry *poGeom )
 
     if( eGeomType == wkbCurvePolygon )
     {
+        OGRCurvePolygon *poCurve = dynamic_cast<OGRCurvePolygon *>(poGeom);
+        if( poCurve == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRCurvePolygon.");
+            return NULL;
+        }
+
         if( !poGeom->hasCurveGeometry(TRUE) )
-            return OGRSurface::CastToPolygon(((OGRCurvePolygon*)poGeom));
+            return OGRSurface::CastToPolygon(poCurve);
 
-        OGRPolygon* poPoly = ((OGRCurvePolygon*)poGeom)->CurvePolyToPoly();
+        OGRPolygon* poPoly = poCurve->CurvePolyToPoly();
         delete poGeom;
         return poPoly;
     }
 
+    // base polygon or triangle
+    if( OGR_GT_IsSubClassOf( eGeomType, wkbPolygon ) )
+    {
+        return OGRSurface::CastToPolygon((OGRSurface*)poGeom);
+    }
+
     if( OGR_GT_IsCurve(eGeomType) &&
         ((OGRCurve*)poGeom)->getNumPoints() >= 3 &&
         ((OGRCurve*)poGeom)->get_IsClosed() )
@@ -577,7 +623,8 @@ OGRGeometry *OGRGeometryFactory::forceToPolygon( OGRGeometry *poGeom )
 
         if( !poGeom->hasCurveGeometry(TRUE) )
         {
-            poPolygon->addRingDirectly( OGRCurve::CastToLinearRing((OGRCurve*)poGeom) );
+            poPolygon->addRingDirectly(
+                OGRCurve::CastToLinearRing((OGRCurve*)poGeom) );
         }
         else
         {
@@ -588,39 +635,52 @@ OGRGeometry *OGRGeometryFactory::forceToPolygon( OGRGeometry *poGeom )
         return poPolygon;
     }
 
+    if( OGR_GT_IsSubClassOf(eGeomType, wkbPolyhedralSurface) )
+    {
+        OGRPolyhedralSurface* poPS = reinterpret_cast<OGRPolyhedralSurface*>(
+                                                                       poGeom);
+        if( poPS->getNumGeometries() == 1 )
+        {
+            poGeom = OGRSurface::CastToPolygon(
+              reinterpret_cast<OGRSurface*>(poPS->getGeometryRef(0)->clone()));
+            delete poPS;
+            return poGeom;
+        }
+    }
+
     if( eGeomType != wkbGeometryCollection
         && eGeomType != wkbMultiPolygon
         && eGeomType != wkbMultiSurface )
         return poGeom;
 
-    // build an aggregated polygon from all the polygon rings in the container.
+    // Build an aggregated polygon from all the polygon rings in the container.
     OGRPolygon *poPolygon = new OGRPolygon();
     OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
     if( poGeom->hasCurveGeometry() )
     {
-        OGRGeometryCollection *poNewGC = (OGRGeometryCollection *) poGC->getLinearGeometry();
+        OGRGeometryCollection *poNewGC =
+            (OGRGeometryCollection *) poGC->getLinearGeometry();
         delete poGC;
-        poGeom = poGC = poNewGC;
+        poGeom = poNewGC;
+        poGC = poNewGC;
     }
 
     poPolygon->assignSpatialReference(poGeom->getSpatialReference());
-    int iGeom;
 
-    for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
+    for( int iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
     {
         if( wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType())
             != wkbPolygon )
             continue;
 
         OGRPolygon *poOldPoly = (OGRPolygon *) poGC->getGeometryRef(iGeom);
-        int   iRing;
 
         if( poOldPoly->getExteriorRing() == NULL )
             continue;
 
         poPolygon->addRingDirectly( poOldPoly->stealExteriorRing() );
 
-        for( iRing = 0; iRing < poOldPoly->getNumInteriorRings(); iRing++ )
+        for( int iRing = 0; iRing < poOldPoly->getNumInteriorRings(); iRing++ )
             poPolygon->addRingDirectly( poOldPoly->stealInteriorRing( iRing ) );
     }
 
@@ -648,8 +708,9 @@ OGRGeometry *OGRGeometryFactory::forceToPolygon( OGRGeometry *poGeom )
 OGRGeometryH OGR_G_ForceToPolygon( OGRGeometryH hGeom )
 
 {
-    return (OGRGeometryH)
-        OGRGeometryFactory::forceToPolygon( (OGRGeometry *) hGeom );
+    return reinterpret_cast<OGRGeometryH>(
+        OGRGeometryFactory::forceToPolygon(
+            reinterpret_cast<OGRGeometry *>(hGeom)));
 }
 
 /************************************************************************/
@@ -699,24 +760,32 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPolygon( OGRGeometry *poGeom )
     if( eGeomType == wkbGeometryCollection ||
         eGeomType == wkbMultiSurface )
     {
-        int iGeom;
         bool bAllPoly = true;
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
         if( poGeom->hasCurveGeometry() )
         {
-            OGRGeometryCollection *poNewGC = (OGRGeometryCollection *) poGC->getLinearGeometry();
+            OGRGeometryCollection *poNewGC =
+                (OGRGeometryCollection *) poGC->getLinearGeometry();
             delete poGC;
-            poGeom = poGC = poNewGC;
+            poGeom = poNewGC;
+            poGC = poNewGC;
         }
 
-        for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
+        bool bCanConvertToMultiPoly = true;
+        for( int iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
         {
-            OGRwkbGeometryType eSubGeomType = wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType());
+            OGRwkbGeometryType eSubGeomType =
+                wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType());
             if( eSubGeomType != wkbPolygon )
                 bAllPoly = false;
+            if( eSubGeomType != wkbMultiPolygon && eSubGeomType != wkbPolygon &&
+                eSubGeomType != wkbPolyhedralSurface && eSubGeomType != wkbTIN )
+            {
+                bCanConvertToMultiPoly = false;
+            }
         }
 
-        if( !bAllPoly )
+        if( !bCanConvertToMultiPoly )
             return poGeom;
 
         OGRMultiPolygon *poMP = new OGRMultiPolygon();
@@ -724,8 +793,24 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPolygon( OGRGeometry *poGeom )
 
         while( poGC->getNumGeometries() > 0 )
         {
-            poMP->addGeometryDirectly( poGC->getGeometryRef(0) );
+            OGRGeometry* poSubGeom = poGC->getGeometryRef(0);
             poGC->removeGeometry( 0, FALSE );
+            if( bAllPoly )
+            {
+                poMP->addGeometryDirectly( poSubGeom );
+            }
+            else
+            {
+                poSubGeom = forceToMultiPolygon( poSubGeom );
+                OGRMultiPolygon* poSubMP = dynamic_cast<OGRMultiPolygon*>(
+                                                                    poSubGeom);
+                while( poSubMP != NULL && poSubMP->getNumGeometries() > 0 )
+                {
+                    poMP->addGeometryDirectly( poSubMP->getGeometryRef(0) );
+                    poSubMP->removeGeometry( 0, FALSE );
+                }
+                delete poSubMP;
+            }
         }
 
         delete poGC;
@@ -744,6 +829,20 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPolygon( OGRGeometry *poGeom )
     }
 
 /* -------------------------------------------------------------------- */
+/*      If it is PolyhedralSurface or TIN, then pretend it is a         */
+/*      multipolygon.                                                   */
+/* -------------------------------------------------------------------- */
+    if( OGR_GT_IsSubClassOf(eGeomType, wkbPolyhedralSurface) )
+    {
+        return OGRPolyhedralSurface::CastToMultiPolygon((OGRPolyhedralSurface*)poGeom);
+    }
+
+    if( eGeomType == wkbTriangle )
+    {
+        return forceToMultiPolygon( forceToPolygon( poGeom ) );
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Eventually we should try to split the polygon into component    */
 /*      island polygons.  But that is a lot of work and can be put off. */
 /* -------------------------------------------------------------------- */
@@ -776,8 +875,9 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPolygon( OGRGeometry *poGeom )
 OGRGeometryH OGR_G_ForceToMultiPolygon( OGRGeometryH hGeom )
 
 {
-    return (OGRGeometryH)
-        OGRGeometryFactory::forceToMultiPolygon( (OGRGeometry *) hGeom );
+    return reinterpret_cast<OGRGeometryH>(
+        OGRGeometryFactory::forceToMultiPolygon(
+            reinterpret_cast<OGRGeometry *>(hGeom)));
 }
 
 /************************************************************************/
@@ -817,11 +917,10 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPoint( OGRGeometry *poGeom )
 /* -------------------------------------------------------------------- */
     if( eGeomType == wkbGeometryCollection )
     {
-        int iGeom;
         bool bAllPoint = true;
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
 
-        for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
+        for( int iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
         {
             if( wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType())
                 != wkbPoint )
@@ -874,8 +973,9 @@ OGRGeometry *OGRGeometryFactory::forceToMultiPoint( OGRGeometry *poGeom )
 OGRGeometryH OGR_G_ForceToMultiPoint( OGRGeometryH hGeom )
 
 {
-    return (OGRGeometryH)
-        OGRGeometryFactory::forceToMultiPoint( (OGRGeometry *) hGeom );
+    return reinterpret_cast<OGRGeometryH>(
+        OGRGeometryFactory::forceToMultiPoint(
+            reinterpret_cast<OGRGeometry *>(hGeom)));
 }
 
 /************************************************************************/
@@ -893,7 +993,8 @@ OGRGeometryH OGR_G_ForceToMultiPoint( OGRGeometryH hGeom )
  * - geometry collections will be converted to multilinestring if they only
  * contain linestrings.
  * - polygons will be changed to a collection of linestrings (one per ring).
- * - curvepolygons will be approximated and changed to a collection of linestrings (one per ring).
+ * - curvepolygons will be approximated and changed to a collection of
+ ( linestrings (one per ring).
  *
  * The passed in geometry is
  * consumed and a new one returned (or potentially the same one).
@@ -923,17 +1024,18 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
 /* -------------------------------------------------------------------- */
     if( eGeomType == wkbGeometryCollection )
     {
-        int iGeom;
         bool bAllLines = true;
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
         if( poGeom->hasCurveGeometry() )
         {
-            OGRGeometryCollection *poNewGC = (OGRGeometryCollection *) poGC->getLinearGeometry();
+            OGRGeometryCollection *poNewGC =
+                (OGRGeometryCollection *) poGC->getLinearGeometry();
             delete poGC;
-            poGeom = poGC = poNewGC;
+            poGeom = poNewGC;
+            poGC = poNewGC;
         }
 
-        for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
+        for( int iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
         {
             if( poGC->getGeometryRef(iGeom)->getGeometryType() != wkbLineString )
                 bAllLines = false;
@@ -970,11 +1072,11 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
 /* -------------------------------------------------------------------- */
 /*      Convert polygons into a multilinestring.                        */
 /* -------------------------------------------------------------------- */
-    if( eGeomType == wkbPolygon || eGeomType == wkbCurvePolygon )
+    if( OGR_GT_IsSubClassOf(eGeomType, wkbCurvePolygon ) )
     {
         OGRMultiLineString *poMP = new OGRMultiLineString();
-        OGRPolygon *poPoly;
-        if( eGeomType == wkbPolygon )
+        OGRPolygon *poPoly = NULL;
+        if( OGR_GT_IsSubClassOf(eGeomType, wkbPolygon) )
             poPoly = (OGRPolygon *) poGeom;
         else
         {
@@ -982,11 +1084,10 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
             delete poGeom;
             poGeom = poPoly;
         }
-        int iRing;
 
         poMP->assignSpatialReference(poGeom->getSpatialReference());
 
-        for( iRing = 0; iRing < poPoly->getNumInteriorRings()+1; iRing++ )
+        for( int iRing = 0; iRing < poPoly->getNumInteriorRings()+1; iRing++ )
         {
             OGRLineString *poNewLS, *poLR;
 
@@ -999,7 +1100,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
             else
                 poLR = poPoly->getInteriorRing(iRing-1);
 
-            if (poLR == NULL || poLR->getNumPoints() == 0)
+            if( poLR == NULL || poLR->getNumPoints() == 0 )
                 continue;
 
             poNewLS = new OGRLineString();
@@ -1013,12 +1114,22 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
     }
 
 /* -------------------------------------------------------------------- */
+/*      If it is PolyhedralSurface or TIN, then pretend it is a         */
+/*      multipolygon.                                                   */
+/* -------------------------------------------------------------------- */
+    if( OGR_GT_IsSubClassOf(eGeomType, wkbPolyhedralSurface) )
+    {
+        poGeom = forceToMultiPolygon(poGeom);
+        eGeomType = wkbMultiPolygon;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Convert multi-polygons into a multilinestring.                  */
 /* -------------------------------------------------------------------- */
     if( eGeomType == wkbMultiPolygon || eGeomType == wkbMultiSurface )
     {
         OGRMultiLineString *poMP = new OGRMultiLineString();
-        OGRMultiPolygon *poMPoly;
+        OGRMultiPolygon *poMPoly = NULL;
         if( eGeomType == wkbMultiPolygon )
             poMPoly = (OGRMultiPolygon *) poGeom;
         else
@@ -1027,16 +1138,16 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
             delete poGeom;
             poGeom = poMPoly;
         }
-        int iPoly;
 
         poMP->assignSpatialReference(poGeom->getSpatialReference());
 
-        for( iPoly = 0; iPoly < poMPoly->getNumGeometries(); iPoly++ )
+        for( int iPoly = 0; iPoly < poMPoly->getNumGeometries(); iPoly++ )
         {
             OGRPolygon *poPoly = (OGRPolygon*) poMPoly->getGeometryRef(iPoly);
-            int iRing;
 
-            for( iRing = 0; iRing < poPoly->getNumInteriorRings()+1; iRing++ )
+            for( int iRing = 0;
+                 iRing < poPoly->getNumInteriorRings()+1;
+                 iRing++ )
             {
                 OGRLineString *poNewLS, *poLR;
 
@@ -1049,7 +1160,7 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
                 else
                     poLR = poPoly->getInteriorRing(iRing-1);
 
-                if (poLR == NULL || poLR->getNumPoints() == 0)
+                if( poLR == NULL || poLR->getNumPoints() == 0 )
                     continue;
 
                 poNewLS = new OGRLineString();
@@ -1091,7 +1202,8 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
     if( eGeomType == wkbMultiCurve )
     {
         OGRGeometry* poNewGeom = poGeom->getLinearGeometry();
-        CPLAssert( wkbFlatten(poNewGeom->getGeometryType()) == wkbMultiLineString );
+        CPLAssert( wkbFlatten(poNewGeom->getGeometryType()) ==
+                   wkbMultiLineString );
         delete poGeom;
         return (OGRMultiLineString*) poNewGeom;
     }
@@ -1118,8 +1230,9 @@ OGRGeometry *OGRGeometryFactory::forceToMultiLineString( OGRGeometry *poGeom )
 OGRGeometryH OGR_G_ForceToMultiLineString( OGRGeometryH hGeom )
 
 {
-    return (OGRGeometryH)
-        OGRGeometryFactory::forceToMultiLineString( (OGRGeometry *) hGeom );
+    return reinterpret_cast<OGRGeometryH>(
+        OGRGeometryFactory::forceToMultiLineString(
+            reinterpret_cast<OGRGeometry *>(hGeom)));
 }
 
 /************************************************************************/
@@ -1130,24 +1243,26 @@ typedef struct _sPolyExtended sPolyExtended;
 
 struct _sPolyExtended
 {
-    OGRPolygon*     poPolygon;
+    OGRGeometry* poGeometry;
+    OGRCurvePolygon* poPolygon;
     OGREnvelope     sEnvelope;
-    OGRLinearRing*  poExteriorRing;
+    OGRCurve*  poExteriorRing;
     OGRPoint        poAPoint;
     int             nInitialIndex;
-    int             bIsTopLevel;
-    OGRPolygon*     poEnclosingPolygon;
+    OGRCurvePolygon*     poEnclosingPolygon;
     double          dfArea;
-    int             bIsCW;
+    bool            bIsTopLevel;
+    bool            bIsCW;
+    bool            bIsPolygon;
 };
 
 static int OGRGeometryFactoryCompareArea(const void* p1, const void* p2)
 {
     const sPolyExtended* psPoly1 = (const sPolyExtended*) p1;
     const sPolyExtended* psPoly2 = (const sPolyExtended*) p2;
-    if (psPoly2->dfArea < psPoly1->dfArea)
+    if( psPoly2->dfArea < psPoly1->dfArea )
         return -1;
-    else if (psPoly2->dfArea > psPoly1->dfArea)
+    else if( psPoly2->dfArea > psPoly1->dfArea )
         return 1;
     else
         return 0;
@@ -1157,15 +1272,15 @@ static int OGRGeometryFactoryCompareByIndex(const void* p1, const void* p2)
 {
     const sPolyExtended* psPoly1 = (const sPolyExtended*) p1;
     const sPolyExtended* psPoly2 = (const sPolyExtended*) p2;
-    if (psPoly1->nInitialIndex < psPoly2->nInitialIndex)
+    if( psPoly1->nInitialIndex < psPoly2->nInitialIndex )
         return -1;
-    else if (psPoly1->nInitialIndex > psPoly2->nInitialIndex)
+    else if( psPoly1->nInitialIndex > psPoly2->nInitialIndex )
         return 1;
     else
         return 0;
 }
 
-#define N_CRITICAL_PART_NUMBER   100
+static const int N_CRITICAL_PART_NUMBER = 100;
 
 typedef enum
 {
@@ -1183,7 +1298,7 @@ typedef enum
  * (or a MultiPolygon if dealing with more than one polygon) that follow the
  * OGC Simple Feature specification.
  *
- * All the input geometries must be OGRPolygons with only a valid exterior
+ * All the input geometries must be OGRPolygon/OGRCurvePolygon with only a valid exterior
  * ring (at least 4 points) and no interior rings.
  *
  * The passed in geometries become the responsibility of the method, but the
@@ -1221,7 +1336,8 @@ typedef enum
  * FALSE otherwise.
  * @param papszOptions a list of strings for passing options
  *
- * @return a single resulting geometry (either OGRPolygon or OGRMultiPolygon).
+ * @return a single resulting geometry (either OGRPolygon, OGRCurvePolygon,
+ * OGRMultiPolygon, OGRMultiSurface or OGRGeometryCollection).
  */
 
 OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
@@ -1229,15 +1345,14 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
                                                    int *pbIsValidGeometry,
                                                    const char** papszOptions )
 {
-    int bUseFastVersion;
-    int i, j;
     OGRGeometry* geom = NULL;
     OrganizePolygonMethod method = METHOD_NORMAL;
+    bool bHasCurves = false;
 
 /* -------------------------------------------------------------------- */
 /*      Trivial case of a single polygon.                               */
 /* -------------------------------------------------------------------- */
-    if (nPolygonCount == 1)
+    if( nPolygonCount == 1 )
     {
         geom = papoPolygons[0];
         papoPolygons[0] = NULL;
@@ -1248,88 +1363,116 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
         return geom;
     }
 
-    if (CSLTestBoolean(CPLGetConfigOption("OGR_DEBUG_ORGANIZE_POLYGONS", "NO")))
+    bool bUseFastVersion = TRUE;
+    if( CPLTestBool(CPLGetConfigOption("OGR_DEBUG_ORGANIZE_POLYGONS",
+                                       "NO")) )
     {
-        /* -------------------------------------------------------------------- */
-        /*      A wee bit of a warning.                                         */
-        /* -------------------------------------------------------------------- */
+        /* ------------------------------------------------------------------ */
+        /*      A wee bit of a warning.                                       */
+        /* ------------------------------------------------------------------ */
         static int firstTime = 1;
-        if (!haveGEOS() && firstTime)
+        // cppcheck-suppress knownConditionTrueFalse
+        if( !haveGEOS() && firstTime )
         {
-            CPLDebug("OGR",
-                    "In OGR_DEBUG_ORGANIZE_POLYGONS mode, GDAL should be built with GEOS support enabled in order "
-                    "OGRGeometryFactory::organizePolygons to provide reliable results on complex polygons.");
+            CPLDebug(
+                "OGR",
+                "In OGR_DEBUG_ORGANIZE_POLYGONS mode, GDAL should be built "
+                "with GEOS support enabled in order "
+                "OGRGeometryFactory::organizePolygons to provide reliable "
+                "results on complex polygons.");
             firstTime = 0;
         }
+        // cppcheck-suppress knownConditionTrueFalse
         bUseFastVersion = !haveGEOS();
     }
-    else
-    {
-        bUseFastVersion = TRUE;
-    }
 
 /* -------------------------------------------------------------------- */
 /*      Setup per polygon envelope and area information.                */
 /* -------------------------------------------------------------------- */
     sPolyExtended* asPolyEx = new sPolyExtended[nPolygonCount];
 
-    bool go_on = true;
+    bool bValidTopology = true;
     bool bMixedUpGeometries = false;
     bool bNonPolygon = false;
     bool bFoundCCW = false;
 
-    const char* pszMethodValue = CSLFetchNameValue( (char**)papszOptions, "METHOD" );
-    const char* pszMethodValueOption = CPLGetConfigOption("OGR_ORGANIZE_POLYGONS", NULL);
-    if (pszMethodValueOption != NULL && pszMethodValueOption[0] != '\0')
+    const char* pszMethodValue =
+        CSLFetchNameValue( (char**)papszOptions, "METHOD" );
+    const char* pszMethodValueOption =
+        CPLGetConfigOption("OGR_ORGANIZE_POLYGONS", NULL);
+    if( pszMethodValueOption != NULL && pszMethodValueOption[0] != '\0' )
         pszMethodValue = pszMethodValueOption;
 
-    if (pszMethodValue != NULL)
+    if( pszMethodValue != NULL )
     {
-        if (EQUAL(pszMethodValue, "SKIP"))
+        if( EQUAL(pszMethodValue, "SKIP") )
         {
             method = METHOD_SKIP;
             bMixedUpGeometries = true;
         }
-        else if (EQUAL(pszMethodValue, "ONLY_CCW"))
+        else if( EQUAL(pszMethodValue, "ONLY_CCW") )
         {
             method = METHOD_ONLY_CCW;
         }
-        else if (EQUAL(pszMethodValue, "CCW_INNER_JUST_AFTER_CW_OUTER"))
+        else if( EQUAL(pszMethodValue, "CCW_INNER_JUST_AFTER_CW_OUTER") )
         {
             method = METHOD_CCW_INNER_JUST_AFTER_CW_OUTER;
         }
-        else if (!EQUAL(pszMethodValue, "DEFAULT"))
+        else if( !EQUAL(pszMethodValue, "DEFAULT") )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
-                     "Unrecognized value for METHOD option : %s", pszMethodValue);
+                     "Unrecognized value for METHOD option : %s",
+                     pszMethodValue);
         }
     }
 
     int nCountCWPolygon = 0;
     int indexOfCWPolygon = -1;
 
-    for(i=0;i<nPolygonCount;i++)
+    for( int i = 0; i < nPolygonCount; i++ )
     {
         asPolyEx[i].nInitialIndex = i;
-        asPolyEx[i].poPolygon = (OGRPolygon*)papoPolygons[i];
+        asPolyEx[i].poGeometry = papoPolygons[i];
+        asPolyEx[i].poPolygon = dynamic_cast<OGRCurvePolygon*>(papoPolygons[i]);
         papoPolygons[i]->getEnvelope(&asPolyEx[i].sEnvelope);
 
-        if( wkbFlatten(papoPolygons[i]->getGeometryType()) == wkbPolygon
-            && ((OGRPolygon *) papoPolygons[i])->getNumInteriorRings() == 0
-            && ((OGRPolygon *)papoPolygons[i])->getExteriorRing()->getNumPoints() >= 4)
+        OGRwkbGeometryType eType =
+            wkbFlatten(papoPolygons[i]->getGeometryType());
+        if( eType == wkbCurvePolygon )
+            bHasCurves = true;
+        if( asPolyEx[i].poPolygon != NULL
+            && asPolyEx[i].poPolygon->getNumInteriorRings() == 0
+            && asPolyEx[i].poPolygon->
+                getExteriorRingCurve()->getNumPoints() >= 4)
         {
             if( method != METHOD_CCW_INNER_JUST_AFTER_CW_OUTER )
                 asPolyEx[i].dfArea = asPolyEx[i].poPolygon->get_Area();
-            asPolyEx[i].poExteriorRing = asPolyEx[i].poPolygon->getExteriorRing();
-            asPolyEx[i].poExteriorRing->getPoint(0, &asPolyEx[i].poAPoint);
-            asPolyEx[i].bIsCW = asPolyEx[i].poExteriorRing->isClockwise();
-            if (asPolyEx[i].bIsCW)
+            asPolyEx[i].poExteriorRing =
+                asPolyEx[i].poPolygon->getExteriorRingCurve();
+            asPolyEx[i].poExteriorRing->StartPoint(&asPolyEx[i].poAPoint);
+            if( eType == wkbPolygon )
+            {
+                asPolyEx[i].bIsCW =
+                    CPL_TO_BOOL(reinterpret_cast<OGRLinearRing*>(
+                        asPolyEx[i].poExteriorRing)->isClockwise());
+                asPolyEx[i].bIsPolygon = true;
+            }
+            else
+            {
+                OGRLineString* poLS = asPolyEx[i].poExteriorRing->CurveToLine();
+                OGRLinearRing oLR;
+                oLR.addSubLineString(poLS);
+                asPolyEx[i].bIsCW = CPL_TO_BOOL(oLR.isClockwise());
+                asPolyEx[i].bIsPolygon = false;
+                delete poLS;
+            }
+            if( asPolyEx[i].bIsCW )
             {
                 indexOfCWPolygon = i;
-                nCountCWPolygon ++;
+                nCountCWPolygon++;
             }
-            if (!bFoundCCW)
-                bFoundCCW = ! (asPolyEx[i].bIsCW);
+            if( !bFoundCCW )
+                bFoundCCW = !(asPolyEx[i].bIsCW);
         }
         else
         {
@@ -1337,52 +1480,60 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
             {
                 CPLError(
                     CE_Warning, CPLE_AppDefined,
-                    "organizePolygons() received an unexpected geometry.\n"
-                    "Either a polygon with interior rings, or a polygon with less than 4 points,\n"
-                    "or a non-Polygon geometry.  Return arguments as a collection." );
+                    "organizePolygons() received an unexpected geometry.  "
+                    "Either a polygon with interior rings, or a polygon "
+                    "with less than 4 points, or a non-Polygon geometry.  "
+                    "Return arguments as a collection." );
                 bMixedUpGeometries = true;
             }
-            if( wkbFlatten(papoPolygons[i]->getGeometryType()) != wkbPolygon )
+            if( eType != wkbPolygon && eType != wkbCurvePolygon )
                 bNonPolygon = true;
         }
     }
 
-    /* If we are in ONLY_CCW mode and that we have found that there is only one outer ring, */
-    /* then it is pretty easy : we can assume that all other rings are inside */
-    if ((method == METHOD_ONLY_CCW || method == METHOD_CCW_INNER_JUST_AFTER_CW_OUTER) &&
+    // If we are in ONLY_CCW mode and that we have found that there is only one
+    // outer ring, then it is pretty easy : we can assume that all other rings
+    // are inside.
+    if( (method == METHOD_ONLY_CCW ||
+         method == METHOD_CCW_INNER_JUST_AFTER_CW_OUTER) &&
         nCountCWPolygon == 1 && bUseFastVersion && !bNonPolygon )
     {
-        geom = asPolyEx[indexOfCWPolygon].poPolygon;
-        for(i=0; i<nPolygonCount; i++)
+        OGRCurvePolygon* poCP = asPolyEx[indexOfCWPolygon].poPolygon;
+        for( int i = 0; i < nPolygonCount; i++ )
         {
-            if (i != indexOfCWPolygon)
+            if( i != indexOfCWPolygon )
             {
-                ((OGRPolygon*)geom)->addRingDirectly(asPolyEx[i].poPolygon->stealExteriorRing());
+                poCP->addRingDirectly(
+                    asPolyEx[i].poPolygon->stealExteriorRingCurve());
                 delete asPolyEx[i].poPolygon;
             }
         }
         delete [] asPolyEx;
-        if (pbIsValidGeometry)
+        if( pbIsValidGeometry )
             *pbIsValidGeometry = TRUE;
-        return geom;
+        return poCP;
     }
 
-    if( method == METHOD_CCW_INNER_JUST_AFTER_CW_OUTER && !bNonPolygon && asPolyEx[0].bIsCW )
+    if( method == METHOD_CCW_INNER_JUST_AFTER_CW_OUTER &&
+        !bNonPolygon && asPolyEx[0].bIsCW )
     {
-        /* Inner rings are CCW oriented and follow immediately the outer */
-        /* ring (that is CW oriented) in which they are included */
-        OGRMultiPolygon* poMulti = NULL;
-        OGRPolygon* poCur = asPolyEx[0].poPolygon;
+        // Inner rings are CCW oriented and follow immediately the outer
+        // ring (that is CW oriented) in which they are included.
+        OGRMultiSurface* poMulti = NULL;
+        OGRCurvePolygon* poCur = asPolyEx[0].poPolygon;
         OGRGeometry* poRet = poCur;
-        /* We have already checked that the first ring is CW */
+        // We have already checked that the first ring is CW.
         OGREnvelope* psEnvelope = &(asPolyEx[0].sEnvelope);
-        for(i=1;i<nPolygonCount;i++)
+        for( int i = 1; i < nPolygonCount; i++ )
         {
             if( asPolyEx[i].bIsCW )
             {
                 if( poMulti == NULL )
                 {
-                    poMulti = new OGRMultiPolygon();
+                    if( bHasCurves )
+                        poMulti = new OGRMultiSurface();
+                    else
+                        poMulti = new OGRMultiPolygon();
                     poRet = poMulti;
                     poMulti->addGeometryDirectly(poCur);
                 }
@@ -1392,60 +1543,67 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
             }
             else
             {
-                poCur->addRingDirectly(asPolyEx[i].poPolygon->stealExteriorRing());
-                if(!(asPolyEx[i].poAPoint.getX() >= psEnvelope->MinX &&
-                     asPolyEx[i].poAPoint.getX() <= psEnvelope->MaxX &&
-                     asPolyEx[i].poAPoint.getY() >= psEnvelope->MinY &&
-                     asPolyEx[i].poAPoint.getY() <= psEnvelope->MaxY))
+                poCur->addRingDirectly(
+                    asPolyEx[i].poPolygon->stealExteriorRingCurve());
+                if( !(asPolyEx[i].poAPoint.getX() >= psEnvelope->MinX &&
+                      asPolyEx[i].poAPoint.getX() <= psEnvelope->MaxX &&
+                      asPolyEx[i].poAPoint.getY() >= psEnvelope->MinY &&
+                      asPolyEx[i].poAPoint.getY() <= psEnvelope->MaxY) )
                 {
                     CPLError(CE_Warning, CPLE_AppDefined,
-                             "Part %d does not respect CCW_INNER_JUST_AFTER_CW_OUTER rule", i);
+                             "Part %d does not respect "
+                             "CCW_INNER_JUST_AFTER_CW_OUTER rule",
+                             i);
                 }
                 delete asPolyEx[i].poPolygon;
             }
         }
         delete [] asPolyEx;
-        if (pbIsValidGeometry)
+        if( pbIsValidGeometry )
             *pbIsValidGeometry = TRUE;
         return poRet;
     }
     else if( method == METHOD_CCW_INNER_JUST_AFTER_CW_OUTER && !bNonPolygon )
     {
         method = METHOD_ONLY_CCW;
-        for(i=0;i<nPolygonCount;i++)
+        for( int i = 0; i < nPolygonCount; i++ )
             asPolyEx[i].dfArea = asPolyEx[i].poPolygon->get_Area();
     }
 
-    /* Emits a warning if the number of parts is sufficiently big to anticipate for */
-    /* very long computation time, and the user didn't specify an explicit method */
-    if (nPolygonCount > N_CRITICAL_PART_NUMBER && method == METHOD_NORMAL && pszMethodValue == NULL)
+    // Emits a warning if the number of parts is sufficiently big to anticipate
+    // for very long computation time, and the user didn't specify an explicit
+    // method.
+    if( nPolygonCount > N_CRITICAL_PART_NUMBER &&
+        method == METHOD_NORMAL && pszMethodValue == NULL )
     {
         static int firstTime = 1;
-        if (firstTime)
+        if( firstTime )
         {
-            if (bFoundCCW)
+            if( bFoundCCW )
             {
-                CPLError( CE_Warning, CPLE_AppDefined,
-                     "organizePolygons() received a polygon with more than %d parts. "
-                     "The processing may be really slow.\n"
-                     "You can skip the processing by setting METHOD=SKIP, "
-                     "or only make it analyze counter-clock wise parts by setting "
-                     "METHOD=ONLY_CCW if you can assume that the "
-                     "outline of holes is counter-clock wise defined", N_CRITICAL_PART_NUMBER);
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "organizePolygons() received a polygon with more than %d "
+                    "parts. The processing may be really slow.  "
+                    "You can skip the processing by setting METHOD=SKIP, "
+                    "or only make it analyze counter-clock wise parts by "
+                    "setting METHOD=ONLY_CCW if you can assume that the "
+                    "outline of holes is counter-clock wise defined",
+                    N_CRITICAL_PART_NUMBER);
             }
             else
             {
-                CPLError( CE_Warning, CPLE_AppDefined,
-                        "organizePolygons() received a polygon with more than %d parts. "
-                        "The processing may be really slow.\n"
-                        "You can skip the processing by setting METHOD=SKIP.",
-                        N_CRITICAL_PART_NUMBER);
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "organizePolygons() received a polygon with more than %d "
+                    "parts.  The processing may be really slow.  "
+                    "You can skip the processing by setting METHOD=SKIP.",
+                    N_CRITICAL_PART_NUMBER);
             }
             firstTime = 0;
         }
     }
 
-
     /* This a nulti-step algorithm :
        1) Sort polygons by descending areas
        2) For each polygon of rank i, find its smallest enclosing polygon
@@ -1477,158 +1635,194 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
        no full geometry intersection or inclusion test is done
     */
 
-    if (!bMixedUpGeometries)
+    if( !bMixedUpGeometries )
     {
-        /* STEP 1 : Sort polygons by descending area */
-        qsort(asPolyEx, nPolygonCount, sizeof(sPolyExtended), OGRGeometryFactoryCompareArea);
+        // STEP 1: Sort polygons by descending area.
+        // TODO(schwehr): Use std::sort.
+        qsort(asPolyEx, nPolygonCount, sizeof(sPolyExtended),
+              OGRGeometryFactoryCompareArea);
     }
-    papoPolygons = NULL; /* just to use to avoid it afterwards */
+    papoPolygons = NULL;  // Just to use to avoid it afterwards.
 
 /* -------------------------------------------------------------------- */
 /*      Compute relationships, if things seem well structured.          */
 /* -------------------------------------------------------------------- */
 
-    /* The first (largest) polygon is necessarily top-level */
-    asPolyEx[0].bIsTopLevel = TRUE;
+    // The first (largest) polygon is necessarily top-level.
+    asPolyEx[0].bIsTopLevel = true;
     asPolyEx[0].poEnclosingPolygon = NULL;
 
     int nCountTopLevel = 1;
 
-    /* STEP 2 */
-    for(i=1; !bMixedUpGeometries && go_on && i<nPolygonCount; i++)
+    // STEP 2.
+    for( int i = 1;
+         !bMixedUpGeometries && bValidTopology && i<nPolygonCount;
+         i++ )
     {
-        if (method == METHOD_ONLY_CCW && asPolyEx[i].bIsCW)
+        if( method == METHOD_ONLY_CCW && asPolyEx[i].bIsCW )
         {
-            nCountTopLevel ++;
-            asPolyEx[i].bIsTopLevel = TRUE;
+            nCountTopLevel++;
+            asPolyEx[i].bIsTopLevel = true;
             asPolyEx[i].poEnclosingPolygon = NULL;
             continue;
         }
 
-        for(j=i-1; go_on && j>=0;j--)
+        int j = i - 1;  // Used after for.
+        for( ; bValidTopology && j >= 0; j-- )
         {
             bool b_i_inside_j = false;
 
-            if (method == METHOD_ONLY_CCW && asPolyEx[j].bIsCW == FALSE)
+            if( method == METHOD_ONLY_CCW && asPolyEx[j].bIsCW == FALSE )
             {
-                /* In that mode, i which is CCW if we reach here can only be */
-                /* included in a CW polygon */
+                // In that mode, i which is CCW if we reach here can only be
+                // included in a CW polygon.
                 continue;
             }
 
-            if (asPolyEx[j].sEnvelope.Contains(asPolyEx[i].sEnvelope))
+            if( asPolyEx[j].sEnvelope.Contains(asPolyEx[i].sEnvelope) )
             {
-                if (bUseFastVersion)
+                if( bUseFastVersion )
                 {
                     if( method == METHOD_ONLY_CCW && j == 0 )
                     {
-                        /* We are testing if a CCW ring is in the biggest CW ring */
-                        /* It *must* be inside as this is the last candidate, otherwise */
-                        /* the winding order rules is broken */
+                        // We are testing if a CCW ring is in the biggest CW
+                        // ring It *must* be inside as this is the last
+                        // candidate, otherwise the winding order rules is
+                        // broken.
                         b_i_inside_j = true;
                     }
-                    else if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&asPolyEx[i].poAPoint, FALSE))
+                    else if( asPolyEx[i].bIsPolygon &&
+                             asPolyEx[j].bIsPolygon &&
+                             reinterpret_cast<OGRLinearRing*>(
+                                 asPolyEx[j].poExteriorRing)->
+                                     isPointOnRingBoundary(
+                                         &asPolyEx[i].poAPoint, FALSE) )
                     {
-                        /* If the point of i is on the boundary of j, we will iterate over the other points of i */
-                        int k, nPoints = asPolyEx[i].poExteriorRing->getNumPoints();
-                        for(k=1;k<nPoints;k++)
+                        OGRLinearRing* poLR_i =
+                            reinterpret_cast<OGRLinearRing*>(
+                                asPolyEx[i].poExteriorRing);
+                        OGRLinearRing* poLR_j =
+                            reinterpret_cast<OGRLinearRing*>(
+                                asPolyEx[j].poExteriorRing);
+                        // If the point of i is on the boundary of j, we will
+                        // iterate over the other points of i.
+                        const int nPoints = poLR_i->getNumPoints();
+                        int k = 1;  // Used after for.
+                        for( ; k < nPoints; k++ )
                         {
                             OGRPoint point;
-                            asPolyEx[i].poExteriorRing->getPoint(k, &point);
-                            if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&point, FALSE))
+                            poLR_i->getPoint(k, &point);
+                            if( poLR_j->isPointOnRingBoundary(&point, FALSE) )
                             {
-                                /* If it is on the boundary of j, iterate again */
+                                // If it is on the boundary of j, iterate again.
                             }
-                            else if (asPolyEx[j].poExteriorRing->isPointInRing(&point, FALSE))
+                            else if( poLR_j->isPointInRing(&point, FALSE) )
                             {
-                                /* If then point is strictly included in j, then i is considered inside j */
+                                // If then point is strictly included in j, then
+                                // i is considered inside j.
                                 b_i_inside_j = true;
                                 break;
                             }
                             else
                             {
-                                /* If it is outside, then i cannot be inside j */
+                                // If it is outside, then i cannot be inside j.
                                 break;
                             }
                         }
                         if( !b_i_inside_j && k == nPoints && nPoints > 2 )
                         {
-                            /* all points of i are on the boundary of j ... */
-                            /* take a point in the middle of a segment of i and */
-                            /* test it against j */
-                            for(k=0;k<nPoints-1;k++)
+                            // All points of i are on the boundary of j.
+                            // Take a point in the middle of a segment of i and
+                            // test it against j.
+                            for( k = 0; k < nPoints - 1; k++ )
                             {
-                                OGRPoint point1, point2, pointMiddle;
-                                asPolyEx[i].poExteriorRing->getPoint(k, &point1);
-                                asPolyEx[i].poExteriorRing->getPoint(k+1, &point2);
-                                pointMiddle.setX((point1.getX() + point2.getX()) / 2);
-                                pointMiddle.setY((point1.getY() + point2.getY()) / 2);
-                                if (asPolyEx[j].poExteriorRing->isPointOnRingBoundary(&pointMiddle, FALSE))
+                                OGRPoint point1;
+                                OGRPoint point2;
+                                OGRPoint pointMiddle;
+                                poLR_i->getPoint(k, &point1);
+                                poLR_i->getPoint(k+1, &point2);
+                                pointMiddle.setX((point1.getX() +
+                                                  point2.getX()) / 2);
+                                pointMiddle.setY((point1.getY() +
+                                                  point2.getY()) / 2);
+                                if( poLR_j->isPointOnRingBoundary(&pointMiddle,
+                                                                  FALSE) )
                                 {
-                                    /* If it is on the boundary of j, iterate again */
+                                    // If it is on the boundary of j, iterate
+                                    // again.
                                 }
-                                else if (asPolyEx[j].poExteriorRing->isPointInRing(&pointMiddle, FALSE))
+                                else if( poLR_j->isPointInRing(&pointMiddle,
+                                                               FALSE) )
                                 {
-                                    /* If then point is strictly included in j, then i is considered inside j */
+                                    // If then point is strictly included in j,
+                                    // then i is considered inside j.
                                     b_i_inside_j = true;
                                     break;
                                 }
                                 else
                                 {
-                                    /* If it is outside, then i cannot be inside j */
+                                    // If it is outside, then i cannot be inside
+                                    // j.
                                     break;
                                 }
                             }
                         }
                     }
-                    /* Note that isPointInRing only test strict inclusion in the ring */
-                    else if (asPolyEx[j].poExteriorRing->isPointInRing(&asPolyEx[i].poAPoint, FALSE))
+                    // Note that isPointInRing only test strict inclusion in the
+                    // ring.
+                    else if( asPolyEx[i].bIsPolygon &&
+                             asPolyEx[j].bIsPolygon &&
+                             reinterpret_cast<OGRLinearRing*>(
+                                 asPolyEx[j].poExteriorRing)->
+                                     isPointInRing(&asPolyEx[i].poAPoint,
+                                                   FALSE) )
                     {
                         b_i_inside_j = true;
                     }
                 }
-                else if (asPolyEx[j].poPolygon->Contains(asPolyEx[i].poPolygon))
+                else if( asPolyEx[j].poPolygon->
+                             Contains(asPolyEx[i].poPolygon) )
                 {
                     b_i_inside_j = true;
                 }
             }
 
-
-            if (b_i_inside_j)
+            if( b_i_inside_j )
             {
-                if (asPolyEx[j].bIsTopLevel)
+                if( asPolyEx[j].bIsTopLevel )
                 {
-                    /* We are a lake */
-                    asPolyEx[i].bIsTopLevel = FALSE;
+                    // We are a lake.
+                    asPolyEx[i].bIsTopLevel = false;
                     asPolyEx[i].poEnclosingPolygon = asPolyEx[j].poPolygon;
                 }
                 else
                 {
-                    /* We are included in a something not toplevel (a lake), */
-                    /* so in OGCSF we are considered as toplevel too */
-                    nCountTopLevel ++;
-                    asPolyEx[i].bIsTopLevel = TRUE;
+                    // We are included in a something not toplevel (a lake),
+                    // so in OGCSF we are considered as toplevel too.
+                    nCountTopLevel++;
+                    asPolyEx[i].bIsTopLevel = true;
                     asPolyEx[i].poEnclosingPolygon = NULL;
                 }
                 break;
             }
-            /* We use Overlaps instead of Intersects to be more
-               tolerant about touching polygons */
-            else if ( bUseFastVersion || !asPolyEx[i].sEnvelope.Intersects(asPolyEx[j].sEnvelope)
-                     || !asPolyEx[i].poPolygon->Overlaps(asPolyEx[j].poPolygon) )
+            // Use Overlaps instead of Intersects to be more
+            // tolerant about touching polygons.
+            else if( bUseFastVersion ||
+                     !asPolyEx[i].sEnvelope.Intersects(asPolyEx[j].sEnvelope) ||
+                     !asPolyEx[i].poPolygon->Overlaps(asPolyEx[j].poPolygon) )
             {
 
             }
             else
             {
-                /* Bad... The polygons are intersecting but no one is
-                   contained inside the other one. This is a really broken
-                   case. We just make a multipolygon with the whole set of
-                   polygons */
-                go_on = false;
+                // Bad... The polygons are intersecting but no one is
+                // contained inside the other one. This is a really broken
+                // case. We just make a multipolygon with the whole set of
+                // polygons.
+                bValidTopology = false;
 #ifdef DEBUG
-                char* wkt1;
-                char* wkt2;
+                char* wkt1 = NULL;
+                char* wkt2 = NULL;
                 asPolyEx[i].poPolygon->exportToWkt(&wkt1);
                 asPolyEx[j].poPolygon->exportToWkt(&wkt2);
                 CPLDebug( "OGR",
@@ -1642,33 +1836,36 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
             }
         }
 
-        if (j < 0)
+        if( j < 0 )
         {
-            /* We come here because we are not included in anything */
-            /* We are toplevel */
-            nCountTopLevel ++;
-            asPolyEx[i].bIsTopLevel = TRUE;
+            // We come here because we are not included in anything.
+            // We are toplevel.
+            nCountTopLevel++;
+            asPolyEx[i].bIsTopLevel = true;
             asPolyEx[i].poEnclosingPolygon = NULL;
         }
     }
 
-    if (pbIsValidGeometry)
-        *pbIsValidGeometry = go_on && !bMixedUpGeometries;
+    if( pbIsValidGeometry )
+        *pbIsValidGeometry = bValidTopology && !bMixedUpGeometries;
 
 /* -------------------------------------------------------------------- */
 /*      Things broke down - just turn everything into a multipolygon.   */
 /* -------------------------------------------------------------------- */
-    if ( !go_on || bMixedUpGeometries )
+    if( !bValidTopology || bMixedUpGeometries )
     {
+        OGRGeometryCollection* poGC = NULL;
         if( bNonPolygon )
-            geom = new OGRGeometryCollection();
+            poGC = new OGRGeometryCollection();
+        else if( bHasCurves )
+            poGC = new OGRMultiSurface();
         else
-            geom = new OGRMultiPolygon();
+            poGC = new OGRMultiPolygon();
+        geom = poGC;
 
-        for( i=0; i < nPolygonCount; i++ )
+        for( int i = 0; i < nPolygonCount; i++ )
         {
-            ((OGRGeometryCollection*)geom)->
-                addGeometryDirectly( asPolyEx[i].poPolygon );
+            poGC->addGeometryDirectly( asPolyEx[i].poGeometry );
         }
     }
 
@@ -1678,42 +1875,44 @@ OGRGeometry* OGRGeometryFactory::organizePolygons( OGRGeometry **papoPolygons,
 /* -------------------------------------------------------------------- */
     else
     {
-        /* STEP 3: Resort in initial order */
-        qsort(asPolyEx, nPolygonCount, sizeof(sPolyExtended), OGRGeometryFactoryCompareByIndex);
+        // STEP 3: Sort again in initial order.
+        qsort(asPolyEx, nPolygonCount, sizeof(sPolyExtended),
+              OGRGeometryFactoryCompareByIndex);
 
-        /* STEP 4: Add holes as rings of their enclosing polygon */
-        for(i=0;i<nPolygonCount;i++)
+        // STEP 4: Add holes as rings of their enclosing polygon.
+        for( int i = 0; i < nPolygonCount; i++ )
         {
-            if (asPolyEx[i].bIsTopLevel == FALSE)
+            if( asPolyEx[i].bIsTopLevel == false )
             {
                 asPolyEx[i].poEnclosingPolygon->addRingDirectly(
-                    asPolyEx[i].poPolygon->stealExteriorRing());
+                    asPolyEx[i].poPolygon->stealExteriorRingCurve());
                 delete asPolyEx[i].poPolygon;
             }
-            else if (nCountTopLevel == 1)
+            else if( nCountTopLevel == 1 )
             {
                 geom = asPolyEx[i].poPolygon;
             }
         }
 
-        /* STEP 5: Add toplevel polygons */
-        if (nCountTopLevel > 1)
+        // STEP 5: Add toplevel polygons.
+        if( nCountTopLevel > 1 )
         {
-            for(i=0;i<nPolygonCount;i++)
+            OGRGeometryCollection* poGC = NULL;
+            for( int i = 0; i < nPolygonCount; i++ )
             {
-                if (asPolyEx[i].bIsTopLevel)
+                if( asPolyEx[i].bIsTopLevel )
                 {
-                    if (geom == NULL)
-                    {
-                        geom = new OGRMultiPolygon();
-                        ((OGRMultiPolygon*)geom)->addGeometryDirectly(asPolyEx[i].poPolygon);
-                    }
-                    else
+                    if( poGC == NULL )
                     {
-                        ((OGRMultiPolygon*)geom)->addGeometryDirectly(asPolyEx[i].poPolygon);
+                        if( bHasCurves )
+                            poGC = new OGRMultiSurface();
+                        else
+                            poGC = new OGRMultiPolygon();
                     }
+                    poGC->addGeometryDirectly(asPolyEx[i].poPolygon);
                 }
             }
+            geom = poGC;
         }
     }
 
@@ -1766,9 +1965,15 @@ OGRGeometry *OGRGeometryFactory::createFromGML( const char *pszData )
 /*                           createFromGEOS()                           */
 /************************************************************************/
 
+/** Builds a OGRGeometry* from a GEOSGeom.
+ * @param hGEOSCtxt GEOS context
+ * @param geosGeom GEOS geometry
+ * @return a OGRGeometry*
+ */
 OGRGeometry *
-OGRGeometryFactory::createFromGEOS( UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtxt,
-                                    UNUSED_IF_NO_GEOS GEOSGeom geosGeom )
+OGRGeometryFactory::createFromGEOS(
+    UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSCtxt,
+    UNUSED_IF_NO_GEOS GEOSGeom geosGeom )
 
 {
 #ifndef HAVE_GEOS
@@ -1783,14 +1988,15 @@ OGRGeometryFactory::createFromGEOS( UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSC
     unsigned char *pabyBuf = NULL;
     OGRGeometry *poGeometry = NULL;
 
-    /* Special case as POINT EMPTY cannot be translated to WKB */
-    if (GEOSGeomTypeId_r(hGEOSCtxt, geosGeom) == GEOS_POINT &&
-        GEOSisEmpty_r(hGEOSCtxt, geosGeom))
+    // Special case as POINT EMPTY cannot be translated to WKB.
+    if( GEOSGeomTypeId_r(hGEOSCtxt, geosGeom) == GEOS_POINT &&
+        GEOSisEmpty_r(hGEOSCtxt, geosGeom) )
         return new OGRPoint();
 
 #if GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 3)
-    /* GEOSGeom_getCoordinateDimension only available in GEOS 3.3.0 (unreleased at time of writing) */
-    int nCoordDim = GEOSGeom_getCoordinateDimension_r(hGEOSCtxt, geosGeom);
+    // GEOSGeom_getCoordinateDimension only available in GEOS 3.3.0.
+    const int nCoordDim =
+        GEOSGeom_getCoordinateDimension_r(hGEOSCtxt, geosGeom);
     GEOSWKBWriter* wkbwriter = GEOSWKBWriter_create_r(hGEOSCtxt);
     GEOSWKBWriter_setOutputDimension_r(hGEOSCtxt, wkbwriter, nCoordDim);
     pabyBuf = GEOSWKBWriter_write_r(hGEOSCtxt, wkbwriter, geosGeom, &nSize );
@@ -1804,7 +2010,8 @@ OGRGeometryFactory::createFromGEOS( UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSC
     }
 
     if( OGRGeometryFactory::createFromWkb( (unsigned char *) pabyBuf,
-                                           NULL, &poGeometry, (int) nSize )
+                                           NULL, &poGeometry,
+                                           static_cast<int>(nSize) )
         != OGRERR_NONE )
     {
         poGeometry = NULL;
@@ -1812,8 +2019,9 @@ OGRGeometryFactory::createFromGEOS( UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSC
 
     if( pabyBuf != NULL )
     {
-        /* Since GEOS 3.1.1, so we test 3.2.0 */
-#if GEOS_CAPI_VERSION_MAJOR >= 2 || (GEOS_CAPI_VERSION_MAJOR == 1 && GEOS_CAPI_VERSION_MINOR >= 6)
+        // Since GEOS 3.1.1, so we test 3.2.0.
+#if GEOS_CAPI_VERSION_MAJOR >= 2 || \
+    (GEOS_CAPI_VERSION_MAJOR == 1 && GEOS_CAPI_VERSION_MINOR >= 6)
         GEOSFree_r( hGEOSCtxt, pabyBuf );
 #else
         free( pabyBuf );
@@ -1822,7 +2030,7 @@ OGRGeometryFactory::createFromGEOS( UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSC
 
     return poGeometry;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
@@ -1838,13 +2046,13 @@ OGRGeometryFactory::createFromGEOS( UNUSED_IF_NO_GEOS GEOSContextHandle_t hGEOSC
  * @return TRUE if available, otherwise FALSE.
  */
 
-int OGRGeometryFactory::haveGEOS()
+bool OGRGeometryFactory::haveGEOS()
 
 {
 #ifndef HAVE_GEOS
-    return FALSE;
+    return false;
 #else
-    return TRUE;
+    return true;
 #endif
 }
 
@@ -1886,7 +2094,6 @@ OGRErr OGRGeometryFactory::createFromFgf( unsigned char *pabyData,
                                  pnBytesConsumed, 0);
 }
 
-
 /************************************************************************/
 /*                       createFromFgfInternal()                        */
 /************************************************************************/
@@ -1898,7 +2105,7 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
                                                   int *pnBytesConsumed,
                                                   int nRecLevel )
 {
-    /* Arbitrary value, but certainly large enough for reasonable usages ! */
+    // Arbitrary value, but certainly large enough for reasonable usages.
     if( nRecLevel == 32 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1915,7 +2122,7 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
 /*      Decode the geometry type.                                       */
 /* -------------------------------------------------------------------- */
-    GInt32 nGType;
+    GInt32 nGType = 0;
     memcpy( &nGType, pabyData + 0, 4 );
     CPL_LSBPTR32( &nGType );
 
@@ -1925,7 +2132,6 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
 /*      Decode the dimensionality if appropriate.                       */
 /* -------------------------------------------------------------------- */
-    OGRGeometry *poGeom = NULL;
     int          nTupleSize = 0;
     GInt32       nGDim = 0;
 
@@ -1956,6 +2162,8 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
         break;
     }
 
+    OGRGeometry *poGeom = NULL;
+
 /* -------------------------------------------------------------------- */
 /*      None                                                            */
 /* -------------------------------------------------------------------- */
@@ -1973,7 +2181,7 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
         if( nBytes < nTupleSize * 8 + 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        double  adfTuple[4];
+        double adfTuple[4] = { 0.0, 0.0, 0.0, 0.0 };
         memcpy( adfTuple, pabyData + 8, nTupleSize*8 );
 #ifdef CPL_MSB
         for( int iOrdinal = 0; iOrdinal < nTupleSize; iOrdinal++ )
@@ -1996,11 +2204,11 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
         if( nBytes < 12 )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        GInt32 nPointCount;
+        GInt32 nPointCount = 0;
         memcpy( &nPointCount, pabyData + 8, 4 );
         CPL_LSBPTR32( &nPointCount );
 
-        if (nPointCount < 0 || nPointCount > INT_MAX / (nTupleSize * 8))
+        if( nPointCount < 0 || nPointCount > INT_MAX / (nTupleSize * 8) )
             return OGRERR_CORRUPT_DATA;
 
         if( nBytes - 12 < nTupleSize * 8 * nPointCount )
@@ -2012,7 +2220,7 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 
         for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
-            double adfTuple[4];
+            double adfTuple[4] = { 0.0, 0.0, 0.0, 0.0 };
             memcpy( adfTuple, pabyData + 12 + 8*nTupleSize*iPoint,
                     nTupleSize*8 );
 #ifdef CPL_MSB
@@ -2037,15 +2245,15 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
         if( nBytes < 12 )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        GInt32 nRingCount;
+        GInt32 nRingCount = 0;
         memcpy( &nRingCount, pabyData + 8, 4 );
         CPL_LSBPTR32( &nRingCount );
 
-        if (nRingCount < 0 || nRingCount > INT_MAX / 4)
+        if( nRingCount < 0 || nRingCount > INT_MAX / 4 )
             return OGRERR_CORRUPT_DATA;
 
-        /* Each ring takes at least 4 bytes */
-        if (nBytes - 12 < nRingCount * 4)
+        // Each ring takes at least 4 bytes.
+        if( nBytes - 12 < nRingCount * 4 )
             return OGRERR_NOT_ENOUGH_DATA;
 
         int nNextByte = 12;
@@ -2061,11 +2269,11 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            GInt32 nPointCount;
+            GInt32 nPointCount = 0;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             CPL_LSBPTR32( &nPointCount );
 
-            if (nPointCount < 0 || nPointCount > INT_MAX / (nTupleSize * 8))
+            if( nPointCount < 0 || nPointCount > INT_MAX / (nTupleSize * 8) )
             {
                 delete poGeom;
                 return OGRERR_CORRUPT_DATA;
@@ -2084,7 +2292,7 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 
             for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
-                double adfTuple[4];
+                double adfTuple[4] = { 0.0, 0.0, 0.0, 0.0 };
                 memcpy( adfTuple, pabyData + nNextByte, nTupleSize*8 );
                 nNextByte += nTupleSize * 8;
 
@@ -2093,7 +2301,8 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
                     CPL_SWAP64PTR( adfTuple + iOrdinal );
 #endif
                 if( nTupleSize > 2 )
-                    poLR->setPoint( iPoint, adfTuple[0], adfTuple[1], adfTuple[2] );
+                    poLR->setPoint( iPoint, adfTuple[0],
+                                    adfTuple[1], adfTuple[2] );
                 else
                     poLR->setPoint( iPoint, adfTuple[0], adfTuple[1] );
             }
@@ -2108,23 +2317,23 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /* -------------------------------------------------------------------- */
 /*      GeometryCollections of various kinds.                           */
 /* -------------------------------------------------------------------- */
-    else if( nGType == 4         // MultiPoint
-             || nGType == 5      // MultiLineString
-             || nGType == 6      // MultiPolygon
-             || nGType == 7 )    // MultiGeometry
+    else if( nGType == 4       // MultiPoint
+             || nGType == 5    // MultiLineString
+             || nGType == 6    // MultiPolygon
+             || nGType == 7 )  // MultiGeometry
     {
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        GInt32 nGeomCount;
+        GInt32 nGeomCount = 0;
         memcpy( &nGeomCount, pabyData + 4, 4 );
         CPL_LSBPTR32( &nGeomCount );
 
-        if (nGeomCount < 0 || nGeomCount > INT_MAX / 4)
+        if( nGeomCount < 0 || nGeomCount > INT_MAX / 4 )
             return OGRERR_CORRUPT_DATA;
 
-        /* Each geometry takes at least 4 bytes */
-        if (nBytes - 8 < 4 * nGeomCount)
+        // Each geometry takes at least 4 bytes.
+        if( nBytes - 8 < 4 * nGeomCount )
             return OGRERR_NOT_ENOUGH_DATA;
 
         OGRGeometryCollection *poGC = NULL;
@@ -2141,11 +2350,13 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 
         for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
         {
-            int nThisGeomSize;
+            int nThisGeomSize = 0;
             OGRGeometry *poThisGeom = NULL;
 
-            OGRErr eErr = createFromFgfInternal( pabyData + nBytesUsed, poSR, &poThisGeom,
-                                                 nBytes - nBytesUsed, &nThisGeomSize, nRecLevel + 1);
+            const OGRErr eErr =
+                createFromFgfInternal(pabyData + nBytesUsed, poSR, &poThisGeom,
+                                      nBytes - nBytesUsed, &nThisGeomSize,
+                                      nRecLevel + 1);
             if( eErr != OGRERR_NONE )
             {
                 delete poGC;
@@ -2155,12 +2366,12 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
             nBytesUsed += nThisGeomSize;
             if( poThisGeom != NULL )
             {
-                eErr = poGC->addGeometryDirectly( poThisGeom );
-                if( eErr != OGRERR_NONE )
+                const OGRErr eErr2 = poGC->addGeometryDirectly( poThisGeom );
+                if( eErr2 != OGRERR_NONE )
                 {
                     delete poGC;
                     delete poThisGeom;
-                    return eErr;
+                    return eErr2;
                 }
             }
         }
@@ -2194,6 +2405,11 @@ OGRErr OGRGeometryFactory::createFromFgfInternal( unsigned char *pabyData,
 /*                        OGR_G_CreateFromFgf()                         */
 /************************************************************************/
 
+/**
+ * \brief Create a geometry object of the appropriate type from it's FGF
+ * (FDO Geometry Format) binary representation.
+ *
+ * See OGRGeometryFactory::createFromFgf() */
 OGRErr CPL_DLL OGR_G_CreateFromFgf( unsigned char *pabyData,
                                     OGRSpatialReferenceH hSRS,
                                     OGRGeometryH *phGeometry,
@@ -2210,35 +2426,33 @@ OGRErr CPL_DLL OGR_G_CreateFromFgf( unsigned char *pabyData,
 /*                SplitLineStringAtDateline()                           */
 /************************************************************************/
 
-#define SWAP_DBL(a,b) do { double tmp = a; a = b; b = tmp; } while(0)
-
 static void SplitLineStringAtDateline(OGRGeometryCollection* poMulti,
                                       const OGRLineString* poLS,
-                                      double dfDateLineOffset)
+                                      double dfDateLineOffset,
+                                      double dfXOffset)
 {
-    double dfLeftBorderX = 180 - dfDateLineOffset;
-    double dfRightBorderX = -180 + dfDateLineOffset;
-    double dfDiffSpace = 360 - dfDateLineOffset;
+    const double dfLeftBorderX = 180 - dfDateLineOffset;
+    const double dfRightBorderX = -180 + dfDateLineOffset;
+    const double dfDiffSpace = 360 - dfDateLineOffset;
 
-    int i;
-    int bIs3D = poLS->getCoordinateDimension() == 3;
+    const bool bIs3D = poLS->getCoordinateDimension() == 3;
     OGRLineString* poNewLS = new OGRLineString();
     poMulti->addGeometryDirectly(poNewLS);
-    for(i=0;i<poLS->getNumPoints();i++)
+    for( int i = 0; i < poLS->getNumPoints(); i++ )
     {
-        double dfX = poLS->getX(i);
-        if (i > 0 && fabs(dfX - poLS->getX(i-1)) > dfDiffSpace)
+        const double dfX = poLS->getX(i) + dfXOffset;
+        if( i > 0 && fabs(dfX - (poLS->getX(i-1) + dfXOffset)) > dfDiffSpace )
         {
-            double dfX1 = poLS->getX(i-1);
+            double dfX1 = poLS->getX(i-1) + dfXOffset;
             double dfY1 = poLS->getY(i-1);
             double dfZ1 = poLS->getY(i-1);
-            double dfX2 = poLS->getX(i);
+            double dfX2 = poLS->getX(i) + dfXOffset;
             double dfY2 = poLS->getY(i);
             double dfZ2 = poLS->getY(i);
 
-            if (dfX1 > -180 && dfX1 < dfRightBorderX && dfX2 == 180 &&
+            if( dfX1 > -180 && dfX1 < dfRightBorderX && dfX2 == 180 &&
                 i+1 < poLS->getNumPoints() &&
-                poLS->getX(i+1) > -180 && poLS->getX(i+1) < dfRightBorderX)
+                poLS->getX(i+1) + dfXOffset > -180 && poLS->getX(i+1) + dfXOffset < dfRightBorderX )
             {
                 if( bIs3D )
                     poNewLS->addPoint(-180, poLS->getY(i), poLS->getZ(i));
@@ -2248,14 +2462,15 @@ static void SplitLineStringAtDateline(OGRGeometryCollection* poMulti,
                 i++;
 
                 if( bIs3D )
-                    poNewLS->addPoint(poLS->getX(i), poLS->getY(i), poLS->getZ(i));
+                    poNewLS->addPoint(poLS->getX(i) + dfXOffset, poLS->getY(i),
+                                      poLS->getZ(i));
                 else
-                    poNewLS->addPoint(poLS->getX(i), poLS->getY(i));
+                    poNewLS->addPoint(poLS->getX(i) + dfXOffset, poLS->getY(i));
                 continue;
             }
-            else if (dfX1 > dfLeftBorderX && dfX1 < 180 && dfX2 == -180 &&
+            else if( dfX1 > dfLeftBorderX && dfX1 < 180 && dfX2 == -180 &&
                      i+1 < poLS->getNumPoints() &&
-                     poLS->getX(i+1) > dfLeftBorderX && poLS->getX(i+1) < 180)
+                     poLS->getX(i+1) + dfXOffset > dfLeftBorderX && poLS->getX(i+1) + dfXOffset < 180 )
             {
                 if( bIs3D )
                     poNewLS->addPoint(180, poLS->getY(i), poLS->getZ(i));
@@ -2265,35 +2480,40 @@ static void SplitLineStringAtDateline(OGRGeometryCollection* poMulti,
                 i++;
 
                 if( bIs3D )
-                    poNewLS->addPoint(poLS->getX(i), poLS->getY(i), poLS->getZ(i));
+                    poNewLS->addPoint(poLS->getX(i) + dfXOffset, poLS->getY(i),
+                                      poLS->getZ(i));
                 else
-                    poNewLS->addPoint(poLS->getX(i), poLS->getY(i));
+                    poNewLS->addPoint(poLS->getX(i) + dfXOffset, poLS->getY(i));
                 continue;
             }
 
-            if (dfX1 < dfRightBorderX && dfX2 > dfLeftBorderX)
+            if( dfX1 < dfRightBorderX && dfX2 > dfLeftBorderX )
             {
-                SWAP_DBL(dfX1, dfX2);
-                SWAP_DBL(dfY1, dfY2);
-                SWAP_DBL(dfZ1, dfZ2);
+                std::swap(dfX1, dfX2);
+                std::swap(dfY1, dfY2);
+                std::swap(dfZ1, dfZ2);
             }
-            if (dfX1 > dfLeftBorderX && dfX2 < dfRightBorderX)
+            if( dfX1 > dfLeftBorderX && dfX2 < dfRightBorderX )
                 dfX2 += 360;
 
-            if (dfX1 <= 180 && dfX2 >= 180 && dfX1 < dfX2)
+            if( dfX1 <= 180 && dfX2 >= 180 && dfX1 < dfX2 )
             {
-                double dfRatio = (180 - dfX1) / (dfX2 - dfX1);
-                double dfY = dfRatio * dfY2 + (1 - dfRatio) * dfY1;
-                double dfZ = dfRatio * dfZ2 + (1 - dfRatio) * dfZ1;
+                const double dfRatio = (180 - dfX1) / (dfX2 - dfX1);
+                const double dfY = dfRatio * dfY2 + (1 - dfRatio) * dfY1;
+                const double dfZ = dfRatio * dfZ2 + (1 - dfRatio) * dfZ1;
                 if( bIs3D )
-                    poNewLS->addPoint(poLS->getX(i-1) > dfLeftBorderX ? 180 : -180, dfY, dfZ);
+                    poNewLS->addPoint(
+                        poLS->getX(i-1) + dfXOffset > dfLeftBorderX ? 180 : -180, dfY, dfZ);
                 else
-                    poNewLS->addPoint(poLS->getX(i-1) > dfLeftBorderX ? 180 : -180, dfY);
+                    poNewLS->addPoint(
+                        poLS->getX(i-1) + dfXOffset > dfLeftBorderX ? 180 : -180, dfY);
                 poNewLS = new OGRLineString();
                 if( bIs3D )
-                    poNewLS->addPoint(poLS->getX(i-1) > dfLeftBorderX ? -180 : 180, dfY, dfZ);
+                    poNewLS->addPoint(
+                        poLS->getX(i-1) + dfXOffset > dfLeftBorderX ? -180 : 180, dfY, dfZ);
                 else
-                    poNewLS->addPoint(poLS->getX(i-1) > dfLeftBorderX ? -180 : 180, dfY);
+                    poNewLS->addPoint(
+                        poLS->getX(i-1) + dfXOffset > dfLeftBorderX ? -180 : 180, dfY);
                 poMulti->addGeometryDirectly(poNewLS);
             }
             else
@@ -2314,27 +2534,28 @@ static void SplitLineStringAtDateline(OGRGeometryCollection* poMulti,
 /************************************************************************/
 
 #ifdef HAVE_GEOS
-static void FixPolygonCoordinatesAtDateLine(OGRPolygon* poPoly, double dfDateLineOffset)
+static void FixPolygonCoordinatesAtDateLine(OGRPolygon* poPoly,
+                                            double dfDateLineOffset)
 {
-    double dfLeftBorderX = 180 - dfDateLineOffset;
-    double dfRightBorderX = -180 + dfDateLineOffset;
-    double dfDiffSpace = 360 - dfDateLineOffset;
+    const double dfLeftBorderX = 180 - dfDateLineOffset;
+    const double dfRightBorderX = -180 + dfDateLineOffset;
+    const double dfDiffSpace = 360 - dfDateLineOffset;
 
-    int i, iPart;
-    for(iPart = 0; iPart < 1 + poPoly->getNumInteriorRings(); iPart++)
+    for( int iPart = 0; iPart < 1 + poPoly->getNumInteriorRings(); iPart++)
     {
         OGRLineString* poLS = (iPart == 0) ? poPoly->getExteriorRing() :
                                              poPoly->getInteriorRing(iPart-1);
         bool bGoEast = false;
-        int bIs3D = poLS->getCoordinateDimension() == 3;
-        for(i=1;i<poLS->getNumPoints();i++)
+        const bool bIs3D = poLS->getCoordinateDimension() == 3;
+        for( int i = 1; i < poLS->getNumPoints(); i++ )
         {
             double dfX = poLS->getX(i);
-            double dfPrevX = poLS->getX(i-1);
-            double dfDiffLong = fabs(dfX - dfPrevX);
-            if (dfDiffLong > dfDiffSpace)
+            const double dfPrevX = poLS->getX(i-1);
+            const double dfDiffLong = fabs(dfX - dfPrevX);
+            if( dfDiffLong > dfDiffSpace )
             {
-                if ((dfPrevX > dfLeftBorderX && dfX < dfRightBorderX) || (dfX < 0 && bGoEast))
+                if( (dfPrevX > dfLeftBorderX && dfX < dfRightBorderX) ||
+                    (dfX < 0 && bGoEast) )
                 {
                     dfX += 360;
                     bGoEast = true;
@@ -2343,16 +2564,16 @@ static void FixPolygonCoordinatesAtDateLine(OGRPolygon* poPoly, double dfDateLin
                     else
                         poLS->setPoint(i, dfX, poLS->getY(i));
                 }
-                else if (dfPrevX < dfRightBorderX && dfX > dfLeftBorderX)
+                else if( dfPrevX < dfRightBorderX && dfX > dfLeftBorderX )
                 {
-                    int j;
-                    for(j=i-1;j>=0;j--)
+                    for( int j = i - 1; j >= 0; j-- )
                     {
                         dfX = poLS->getX(j);
-                        if (dfX < 0)
+                        if( dfX < 0 )
                         {
                             if( bIs3D )
-                                poLS->setPoint(j, dfX + 360, poLS->getY(j), poLS->getZ(j));
+                                poLS->setPoint(j, dfX + 360, poLS->getY(j),
+                                               poLS->getZ(j));
                             else
                                 poLS->setPoint(j, dfX + 360, poLS->getY(j));
                         }
@@ -2370,22 +2591,28 @@ static void FixPolygonCoordinatesAtDateLine(OGRPolygon* poPoly, double dfDateLin
 #endif
 
 /************************************************************************/
-/*                            Sub360ToLon()                             */
+/*                            AddOffsetToLon()                          */
 /************************************************************************/
 
-static void Sub360ToLon( OGRGeometry* poGeom )
+static void AddOffsetToLon( OGRGeometry* poGeom, double dfOffset )
 {
-    switch (wkbFlatten(poGeom->getGeometryType()))
+    switch( wkbFlatten(poGeom->getGeometryType()) )
     {
         case wkbPolygon:
         case wkbMultiLineString:
         case wkbMultiPolygon:
         case wkbGeometryCollection:
         {
-            int nSubGeomCount = OGR_G_GetGeometryCount((OGRGeometryH)poGeom);
+            const int nSubGeomCount =
+                OGR_G_GetGeometryCount(reinterpret_cast<OGRGeometryH>(poGeom));
             for( int iGeom = 0; iGeom < nSubGeomCount; iGeom++ )
             {
-                Sub360ToLon((OGRGeometry*)OGR_G_GetGeometryRef((OGRGeometryH)poGeom, iGeom));
+                AddOffsetToLon(
+                    reinterpret_cast<OGRGeometry*>(
+                        OGR_G_GetGeometryRef(
+                            reinterpret_cast<OGRGeometryH>(poGeom),
+                            iGeom)),
+                    dfOffset);
             }
 
             break;
@@ -2394,17 +2621,17 @@ static void Sub360ToLon( OGRGeometry* poGeom )
         case wkbLineString:
         {
             OGRLineString* poLineString = (OGRLineString* )poGeom;
-            int nPointCount = poLineString->getNumPoints();
-            int nCoordDim = poLineString->getCoordinateDimension();
+            const int nPointCount = poLineString->getNumPoints();
+            const int nCoordDim = poLineString->getCoordinateDimension();
             for( int iPoint = 0; iPoint < nPointCount; iPoint++)
             {
-                if (nCoordDim == 2)
+                if( nCoordDim == 2 )
                     poLineString->setPoint(iPoint,
-                                     poLineString->getX(iPoint) - 360,
+                                     poLineString->getX(iPoint) + dfOffset,
                                      poLineString->getY(iPoint));
                 else
                     poLineString->setPoint(iPoint,
-                                     poLineString->getX(iPoint) - 360,
+                                     poLineString->getX(iPoint) + dfOffset,
                                      poLineString->getY(iPoint),
                                      poLineString->getZ(iPoint));
             }
@@ -2420,10 +2647,11 @@ static void Sub360ToLon( OGRGeometry* poGeom )
 /*                        AddSimpleGeomToMulti()                        */
 /************************************************************************/
 
-static void AddSimpleGeomToMulti(OGRGeometryCollection* poMulti,
-                                 const OGRGeometry* poGeom)
+#ifdef HAVE_GEOS
+static void AddSimpleGeomToMulti( OGRGeometryCollection* poMulti,
+                                  const OGRGeometry* poGeom )
 {
-    switch (wkbFlatten(poGeom->getGeometryType()))
+    switch( wkbFlatten(poGeom->getGeometryType()) )
     {
         case wkbPolygon:
         case wkbLineString:
@@ -2434,11 +2662,18 @@ static void AddSimpleGeomToMulti(OGRGeometryCollection* poMulti,
         case wkbMultiPolygon:
         case wkbGeometryCollection:
         {
-            int nSubGeomCount = OGR_G_GetGeometryCount((OGRGeometryH)poGeom);
+            // TODO(schwehr): Can the const_casts be removed or improved?
+            const int nSubGeomCount =
+                OGR_G_GetGeometryCount(reinterpret_cast<OGRGeometryH>(
+                    const_cast<OGRGeometry *>(poGeom)));
             for( int iGeom = 0; iGeom < nSubGeomCount; iGeom++ )
             {
                 OGRGeometry* poSubGeom =
-                    (OGRGeometry*)OGR_G_GetGeometryRef((OGRGeometryH)poGeom, iGeom);
+                    reinterpret_cast<OGRGeometry *>(
+                        OGR_G_GetGeometryRef(
+                            reinterpret_cast<OGRGeometryH>(
+                                const_cast<OGRGeometry *>(poGeom)),
+                            iGeom));
                 AddSimpleGeomToMulti(poMulti, poSubGeom);
             }
             break;
@@ -2448,35 +2683,41 @@ static void AddSimpleGeomToMulti(OGRGeometryCollection* poMulti,
             break;
     }
 }
+#endif // #ifdef HAVE_GEOS
 
 /************************************************************************/
 /*                 CutGeometryOnDateLineAndAddToMulti()                 */
 /************************************************************************/
 
-static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
-                                               const OGRGeometry* poGeom,
-                                               double dfDateLineOffset)
+static void CutGeometryOnDateLineAndAddToMulti( OGRGeometryCollection* poMulti,
+                                                const OGRGeometry* poGeom,
+                                                double dfDateLineOffset )
 {
-    OGRwkbGeometryType eGeomType = wkbFlatten(poGeom->getGeometryType());
-    switch (eGeomType)
+    const OGRwkbGeometryType eGeomType = wkbFlatten(poGeom->getGeometryType());
+    switch( eGeomType )
     {
         case wkbPolygon:
         case wkbLineString:
         {
-            bool bWrapDateline = false;
             bool bSplitLineStringAtDateline = false;
             OGREnvelope oEnvelope;
 
             poGeom->getEnvelope(&oEnvelope);
+            const bool bAroundMinus180 = (oEnvelope.MinX < -180.0);
 
-            /* Naive heuristics... Place to improvement... */
+            // Naive heuristics... Place to improve.
+#ifdef HAVE_GEOS
             OGRGeometry* poDupGeom = NULL;
+            bool bWrapDateline = false;
+#endif
 
-            double dfLeftBorderX = 180 - dfDateLineOffset;
-            double dfRightBorderX = -180 + dfDateLineOffset;
-            double dfDiffSpace = 360 - dfDateLineOffset;
+            const double dfLeftBorderX = 180 - dfDateLineOffset;
+            const double dfRightBorderX = -180 + dfDateLineOffset;
+            const double dfDiffSpace = 360 - dfDateLineOffset;
 
-            if (oEnvelope.MinX > dfLeftBorderX && oEnvelope.MaxX > 180)
+            const double dfXOffset = (bAroundMinus180) ? 360.0 : 0.0;
+            if( oEnvelope.MinX + dfXOffset > dfLeftBorderX &&
+                oEnvelope.MaxX + dfXOffset > 180 )
             {
 #ifndef HAVE_GEOS
                 CPLError( CE_Failure, CPLE_NotSupported,
@@ -2487,31 +2728,31 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
             }
             else
             {
-                OGRLineString* poLS;
-                if (eGeomType == wkbPolygon)
-                    poLS = ((OGRPolygon*)poGeom)->getExteriorRing();
-                else
-                    poLS = (OGRLineString*)poGeom;
-                if (poLS)
+                OGRLineString* poLS = eGeomType == wkbPolygon
+                    ? ((OGRPolygon*)poGeom)->getExteriorRing()
+                    : (OGRLineString*)poGeom;
+                if( poLS )
                 {
-                    int i;
                     double dfMaxSmallDiffLong = 0;
                     bool bHasBigDiff = false;
-                    /* Detect big gaps in longitude */
-                    for(i=1;i<poLS->getNumPoints();i++)
+                    // Detect big gaps in longitude.
+                    for( int i = 1; i < poLS->getNumPoints(); i++ )
                     {
-                        double dfPrevX = poLS->getX(i-1);
-                        double dfX = poLS->getX(i);
-                        double dfDiffLong = fabs(dfX - dfPrevX);
-                        if (dfDiffLong > dfDiffSpace &&
-                            ((dfX > dfLeftBorderX && dfPrevX < dfRightBorderX) || (dfPrevX > dfLeftBorderX && dfX < dfRightBorderX)))
+                        const double dfPrevX = poLS->getX(i-1) + dfXOffset;
+                        const double dfX = poLS->getX(i) + dfXOffset;
+                        const double dfDiffLong = fabs(dfX - dfPrevX);
+                        if( dfDiffLong > dfDiffSpace &&
+                            ((dfX > dfLeftBorderX &&
+                              dfPrevX < dfRightBorderX) ||
+                             (dfPrevX > dfLeftBorderX &&
+                              dfX < dfRightBorderX)) )
                             bHasBigDiff = true;
-                        else if (dfDiffLong > dfMaxSmallDiffLong)
+                        else if( dfDiffLong > dfMaxSmallDiffLong )
                             dfMaxSmallDiffLong = dfDiffLong;
                     }
-                    if (bHasBigDiff && dfMaxSmallDiffLong < dfDateLineOffset)
+                    if( bHasBigDiff && dfMaxSmallDiffLong < dfDateLineOffset )
                     {
-                        if (eGeomType == wkbLineString)
+                        if( eGeomType == wkbLineString )
                             bSplitLineStringAtDateline = true;
                         else
                         {
@@ -2521,35 +2762,46 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
 #else
                             bWrapDateline = true;
                             poDupGeom = poGeom->clone();
-                            FixPolygonCoordinatesAtDateLine((OGRPolygon*)poDupGeom, dfDateLineOffset);
+                            FixPolygonCoordinatesAtDateLine(
+                                (OGRPolygon*)poDupGeom, dfDateLineOffset);
 #endif
                         }
                     }
                 }
             }
 
-            if (bSplitLineStringAtDateline)
+            if( bSplitLineStringAtDateline )
             {
-                SplitLineStringAtDateline(poMulti, (OGRLineString*)poGeom, dfDateLineOffset);
+                SplitLineStringAtDateline(poMulti, (OGRLineString*)poGeom,
+                                          dfDateLineOffset,
+                                          ( bAroundMinus180 ) ? 360.0 : 0.0 );
             }
-            else if (bWrapDateline)
+#ifdef HAVE_GEOS
+            else if( bWrapDateline )
             {
-                const OGRGeometry* poWorkGeom = (poDupGeom) ? poDupGeom : poGeom;
+                const OGRGeometry* poWorkGeom =
+                    poDupGeom ? poDupGeom : poGeom;
                 OGRGeometry* poRectangle1 = NULL;
                 OGRGeometry* poRectangle2 = NULL;
-                const char* pszWKT1 = "POLYGON((0 90,180 90,180 -90,0 -90,0 90))";
-                const char* pszWKT2 = "POLYGON((180 90,360 90,360 -90,180 -90,180 90))";
-                OGRGeometryFactory::createFromWkt((char**)&pszWKT1, NULL, &poRectangle1);
-                OGRGeometryFactory::createFromWkt((char**)&pszWKT2, NULL, &poRectangle2);
+                const char* pszWKT1 = !bAroundMinus180 ?
+                    "POLYGON((0 90,180 90,180 -90,0 -90,0 90))" :
+                    "POLYGON((0 90,-180 90,-180 -90,0 -90,0 90))";
+                const char* pszWKT2 = !bAroundMinus180 ?
+                    "POLYGON((180 90,360 90,360 -90,180 -90,180 90))" :
+                    "POLYGON((-180 90,-360 90,-360 -90,-180 -90,-180 90))";
+                OGRGeometryFactory::createFromWkt((char**)&pszWKT1, NULL,
+                                                  &poRectangle1);
+                OGRGeometryFactory::createFromWkt((char**)&pszWKT2, NULL,
+                                                  &poRectangle2);
                 OGRGeometry* poGeom1 = poWorkGeom->Intersection(poRectangle1);
                 OGRGeometry* poGeom2 = poWorkGeom->Intersection(poRectangle2);
                 delete poRectangle1;
                 delete poRectangle2;
 
-                if (poGeom1 != NULL && poGeom2 != NULL)
+                if( poGeom1 != NULL && poGeom2 != NULL )
                 {
                     AddSimpleGeomToMulti(poMulti, poGeom1);
-                    Sub360ToLon(poGeom2);
+                    AddOffsetToLon(poGeom2, !bAroundMinus180 ? -360.0 : 360.0);
                     AddSimpleGeomToMulti(poMulti, poGeom2);
                 }
                 else
@@ -2561,6 +2813,7 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
                 delete poGeom2;
                 delete poDupGeom;
             }
+#endif
             else
             {
                 poMulti->addGeometry(poGeom);
@@ -2572,12 +2825,19 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
         case wkbMultiPolygon:
         case wkbGeometryCollection:
         {
-            int nSubGeomCount = OGR_G_GetGeometryCount((OGRGeometryH)poGeom);
+            // TODO(schwehr): Fix the const_cast.
+            int nSubGeomCount =
+              OGR_G_GetGeometryCount(reinterpret_cast<OGRGeometryH>(
+                  const_cast<OGRGeometry *>(poGeom)));
             for( int iGeom = 0; iGeom < nSubGeomCount; iGeom++ )
             {
                 OGRGeometry* poSubGeom =
-                    (OGRGeometry*)OGR_G_GetGeometryRef((OGRGeometryH)poGeom, iGeom);
-                CutGeometryOnDateLineAndAddToMulti(poMulti, poSubGeom, dfDateLineOffset);
+                    reinterpret_cast<OGRGeometry *>(OGR_G_GetGeometryRef(
+                        reinterpret_cast<OGRGeometryH>(
+                            const_cast<OGRGeometry *>(poGeom)),
+                        iGeom));
+                CutGeometryOnDateLineAndAddToMulti(poMulti, poSubGeom,
+                                                   dfDateLineOffset);
             }
             break;
         }
@@ -2587,84 +2847,893 @@ static void CutGeometryOnDateLineAndAddToMulti(OGRGeometryCollection* poMulti,
     }
 }
 
+#ifdef HAVE_GEOS
+
 /************************************************************************/
-/*                       transformWithOptions()                         */
+/*                             RemovePoint()                            */
 /************************************************************************/
 
-OGRGeometry* OGRGeometryFactory::transformWithOptions( const OGRGeometry* poSrcGeom,
-                                                       OGRCoordinateTransformation *poCT,
-                                                       char** papszOptions )
+static void RemovePoint(OGRGeometry* poGeom, OGRPoint* poPoint)
 {
-    OGRGeometry* poDstGeom = poSrcGeom->clone();
-    if (poCT != NULL)
+    const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
+    switch( eType )
     {
-        OGRErr eErr = poDstGeom->transform(poCT);
-        if (eErr != OGRERR_NONE)
+        case wkbLineString:
         {
-            delete poDstGeom;
-            return NULL;
+            OGRLineString* poLS = reinterpret_cast<OGRLineString*>(poGeom);
+            const bool bIs3D = ( poLS->getCoordinateDimension() == 3 );
+            int j = 0;
+            for( int i = 0; i < poLS->getNumPoints(); i++ )
+            {
+                if( poLS->getX(i) != poPoint->getX() ||
+                    poLS->getY(i) != poPoint->getY() )
+                {
+                    if( i > j )
+                    {
+                        if( bIs3D )
+                        {
+                            poLS->setPoint( j, poLS->getX(i), poLS->getY(i),
+                                            poLS->getZ(i) );
+                        }
+                        else
+                        {
+                            poLS->setPoint( j, poLS->getX(i), poLS->getY(i) );
+                        }
+                    }
+                    j++;
+                }
+            }
+            poLS->setNumPoints(j);
+            break;
         }
-    }
 
-    if (CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "WRAPDATELINE", "NO")))
-    {
-        OGRwkbGeometryType eType = wkbFlatten(poSrcGeom->getGeometryType());
-        OGRwkbGeometryType eNewType;
-        if (eType == wkbPolygon || eType == wkbMultiPolygon)
-            eNewType = wkbMultiPolygon;
-        else if (eType == wkbLineString || eType == wkbMultiLineString)
-            eNewType = wkbMultiLineString;
-        else
-            eNewType = wkbGeometryCollection;
+        case wkbPolygon:
+        {
+            OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(poGeom);
+            if( poPoly->getExteriorRing() != NULL )
+            {
+                RemovePoint(poPoly->getExteriorRing(), poPoint);
+                for( int i=0; i<poPoly->getNumInteriorRings(); ++i )
+                {
+                    RemovePoint(poPoly->getInteriorRing(i), poPoint);
+                }
+            }
+            break;
+        }
 
-        OGRGeometryCollection* poMulti =
-            (OGRGeometryCollection* )createGeometry(eNewType);
+        case wkbMultiLineString:
+        case wkbMultiPolygon:
+        case wkbGeometryCollection:
+        {
+            OGRGeometryCollection* poGC =
+                            reinterpret_cast<OGRGeometryCollection*>(poGeom);
+            for( int i=0; i<poGC->getNumGeometries(); ++i )
+            {
+                RemovePoint(poGC->getGeometryRef(i), poPoint);
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+}
+
+/************************************************************************/
+/*                              GetDist()                               */
+/************************************************************************/
 
-        double dfDateLineOffset = CPLAtofM(CSLFetchNameValueDef(papszOptions, "DATELINEOFFSET", "10"));
-        if(dfDateLineOffset <= 0 || dfDateLineOffset >= 360)
-            dfDateLineOffset = 10;
+static double GetDist(double dfDeltaX, double dfDeltaY)
+{
+    return sqrt(dfDeltaX * dfDeltaX + dfDeltaY * dfDeltaY);
+}
 
-        CutGeometryOnDateLineAndAddToMulti(poMulti, poDstGeom, dfDateLineOffset);
+/************************************************************************/
+/*                             AlterPole()                              */
+/*                                                                      */
+/* Replace and point at the pole by points really close to the pole,    */
+/* but on the previous and later segments.                              */
+/************************************************************************/
 
-        if (poMulti->getNumGeometries() == 0)
+static void AlterPole(OGRGeometry* poGeom, OGRPoint* poPole,
+                      bool bIsRing = false)
+{
+    const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
+    switch( eType )
+    {
+        case wkbLineString:
         {
-            delete poMulti;
+            if( !bIsRing )
+                return;
+            OGRLineString* poLS = reinterpret_cast<OGRLineString*>(poGeom);
+            const int nNumPoints = poLS->getNumPoints();
+            if( nNumPoints >= 4 )
+            {
+                const bool bIs3D = ( poLS->getCoordinateDimension() == 3 );
+                std::vector<OGRRawPoint> aoPoints;
+                std::vector<double> adfZ;
+                bool bMustClose = false;
+                for( int i = 0; i < nNumPoints; i++ )
+                {
+                    const double dfX = poLS->getX(i);
+                    const double dfY = poLS->getY(i);
+                    if( dfX == poPole->getX() && dfY == poPole->getY() )
+                    {
+                        // Replace the pole by points really close to it
+                        if( i == 0 )
+                            bMustClose = true;
+                        if( i == nNumPoints - 1 )
+                            continue;
+                        const int iBefore = i > 0 ? i - 1: nNumPoints - 2;
+                        double dfXBefore = poLS->getX(iBefore);
+                        double dfYBefore = poLS->getY(iBefore);
+                        double dfNorm = GetDist(dfXBefore - dfX,
+                                                dfYBefore - dfY);
+                        double dfXInterp =
+                            dfX + (dfXBefore - dfX) / dfNorm * 1.0e-7;
+                        double dfYInterp =
+                            dfY + (dfYBefore - dfY) / dfNorm * 1.0e-7;
+                        OGRRawPoint oPoint;
+                        oPoint.x = dfXInterp;
+                        oPoint.y = dfYInterp;
+                        aoPoints.push_back(oPoint);
+                        adfZ.push_back(poLS->getZ(i));
+
+                        const int iAfter = i+1;
+                        double dfXAfter = poLS->getX(iAfter);
+                        double dfYAfter = poLS->getY(iAfter);
+                        dfNorm = GetDist(dfXAfter - dfX, dfYAfter - dfY);
+                        dfXInterp = dfX + (dfXAfter - dfX) / dfNorm * 1e-7;
+                        dfYInterp = dfY + (dfYAfter - dfY) / dfNorm * 1e-7;
+                        oPoint.x = dfXInterp;
+                        oPoint.y = dfYInterp;
+                        aoPoints.push_back(oPoint);
+                        adfZ.push_back(poLS->getZ(i));
+                    }
+                    else
+                    {
+                        OGRRawPoint oPoint;
+                        oPoint.x = dfX;
+                        oPoint.y = dfY;
+                        aoPoints.push_back(oPoint);
+                        adfZ.push_back(poLS->getZ(i));
+                    }
+                }
+                if( bMustClose )
+                {
+                    aoPoints.push_back(aoPoints[0]);
+                    adfZ.push_back(adfZ[0]);
+                }
+
+                poLS->setPoints(static_cast<int>(aoPoints.size()),
+                                &(aoPoints[0]),
+                                bIs3D ? &adfZ[0] : (double*)NULL);
+            }
+            break;
         }
-        else if (poMulti->getNumGeometries() == 1)
+
+        case wkbPolygon:
         {
-            delete poDstGeom;
-            poDstGeom = poMulti->getGeometryRef(0)->clone();
-            delete poMulti;
+            OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(poGeom);
+            if( poPoly->getExteriorRing() != NULL )
+            {
+                AlterPole(poPoly->getExteriorRing(), poPole, true);
+                for( int i=0; i<poPoly->getNumInteriorRings(); ++i )
+                {
+                    AlterPole(poPoly->getInteriorRing(i), poPole, true);
+                }
+            }
+            break;
         }
-        else
+
+        case wkbMultiLineString:
+        case wkbMultiPolygon:
+        case wkbGeometryCollection:
         {
-            delete poDstGeom;
-            poDstGeom = poMulti;
+            OGRGeometryCollection* poGC =
+                            reinterpret_cast<OGRGeometryCollection*>(poGeom);
+            for( int i=0; i<poGC->getNumGeometries(); ++i )
+            {
+                AlterPole(poGC->getGeometryRef(i), poPole);
+            }
+            break;
         }
-    }
 
-    return poDstGeom;
+        default:
+            break;
+    }
 }
 
 /************************************************************************/
-/*                       OGRGF_GetDefaultStepSize()                     */
+/*                          IsPolarToWGS84()                            */
+/*                                                                      */
+/* Returns true if poCT transforms from a projection that includes one  */
+/* of the pole in a continuous way.                                     */
 /************************************************************************/
 
-static double OGRGF_GetDefaultStepSize()
+static bool IsPolarToWGS84( OGRCoordinateTransformation* poCT,
+                            OGRCoordinateTransformation* poRevCT,
+                            bool& bIsNorthPolarOut )
 {
-    return CPLAtofM(CPLGetConfigOption("OGR_ARC_STEPSIZE","4"));
+    bool bIsNorthPolar = false;
+    bool bIsSouthPolar = false;
+    double x = 0.0;
+    double y = 90.0;
+
+    const bool bBackupEmitErrors = poCT->GetEmitErrors();
+    poRevCT->SetEmitErrors(false);
+    poCT->SetEmitErrors(false);
+
+    if( poRevCT->Transform( 1, &x, &y ) &&
+        // Surprisingly, pole south projects correctly back &
+        // forth for antarctic polar stereographic.  Therefore, check that
+        // the projected value is not too big.
+        fabs(x) < 1e10 && fabs(y) < 1e10 &&
+        poCT->Transform(1, &x, &y) &&
+        fabs(y - 90.0) < 1e-10 )
+    {
+        bIsNorthPolar = true;
+    }
+
+    x = 0.0;
+    y = -90.0;
+    if( poRevCT->Transform( 1, &x, &y ) &&
+        fabs(x) < 1e10 && fabs(y) < 1e10 &&
+        poCT->Transform(1, &x, &y) &&
+        fabs(y - (-90.0)) < 1e-10 )
+    {
+        bIsSouthPolar = true;
+    }
+
+    poCT->SetEmitErrors(bBackupEmitErrors);
+
+    if( bIsNorthPolar && bIsSouthPolar )
+    {
+        bIsNorthPolar = false;
+        bIsSouthPolar = false;
+    }
+
+    bIsNorthPolarOut = bIsNorthPolar;
+    return bIsNorthPolar || bIsSouthPolar;
 }
 
 /************************************************************************/
-/*                        approximateArcAngles()                        */
+/*                     TransformBeforePolarToWGS84()                    */
+/*                                                                      */
+/* Transform the geometry (by intersection), so as to cut each geometry */
+/* that crosses the pole, in 2 parts. Do also tricks for geometries     */
+/* that just touch the pole.                                            */
 /************************************************************************/
 
-/**
- * Stroke arc to linestring.
- *
- * Stroke an arc of a circle to a linestring based on a center
- * point, radius, start angle and end angle, all angles in degrees.
- *
+static OGRGeometry* TransformBeforePolarToWGS84(
+                                        OGRCoordinateTransformation* poRevCT,
+                                        bool bIsNorthPolar,
+                                        OGRGeometry* poDstGeom,
+                                        bool& bNeedPostCorrectionOut )
+{
+    const int nSign = (bIsNorthPolar) ? 1 : -1;
+
+    // Does the geometry fully contains the pole ? */
+    double dfXPole = 0.0;
+    double dfYPole = nSign * 90.0;
+    poRevCT->Transform( 1, &dfXPole, &dfYPole );
+    OGRPoint oPole(dfXPole, dfYPole);
+    const bool bContainsPole =
+                CPL_TO_BOOL(poDstGeom->Contains(&oPole));
+
+    const double EPS = 1e-9;
+
+    // Does the geometry touches the pole and intersects the antimeridian ?
+    double dfNearPoleAntiMeridianX = 180.0;
+    double dfNearPoleAntiMeridianY = nSign*(90.0 - EPS);
+    poRevCT->Transform( 1,
+                        &dfNearPoleAntiMeridianX,
+                        &dfNearPoleAntiMeridianY );
+    OGRPoint oNearPoleAntimeridian(dfNearPoleAntiMeridianX,
+                                    dfNearPoleAntiMeridianY);
+    const bool bContainsNearPoleAntimeridian = CPL_TO_BOOL(
+        poDstGeom->Contains(&oNearPoleAntimeridian));
+
+    // Does the geometry touches the pole (but not intersect the antimeridian) ?
+    const bool bRegularTouchesPole =
+        !bContainsPole &&
+        !bContainsNearPoleAntimeridian &&
+        CPL_TO_BOOL(poDstGeom->Touches(&oPole));
+
+    // Create a polygon of nearly a full hemisphere, but excluding the anti
+    // meridian and the pole.
+    OGRPolygon oCutter;
+    OGRLinearRing* poRing = new OGRLinearRing();
+    poRing->addPoint(180.0 - EPS, 0);
+    poRing->addPoint(180.0 - EPS, nSign*(90.0 - EPS));
+    // If the geometry doesn't contain the pole, then we add it to the cutter
+    // geometry, but will later remove it completely (geometry touching the
+    // pole but intersecting the antimeridian), or will replace it by 2
+    // close points (geometry touching the pole without intersecting the
+    // antimeridian)
+    if( !bContainsPole )
+        poRing->addPoint(180.0, nSign*90);
+    poRing->addPoint(-180.0 + EPS, nSign*(90.0 - EPS));
+    poRing->addPoint(-180.0 + EPS, 0);
+    poRing->addPoint(180.0 - EPS, 0);
+    oCutter.addRingDirectly(poRing);
+
+    if( oCutter.transform(poRevCT) == OGRERR_NONE &&
+        // Check that longitudes +/- 180 are continuous
+        // in the polar projection
+        fabs(poRing->getX(0) -
+                poRing->getX(poRing->getNumPoints()-2)) < 1 &&
+        (bContainsPole || bContainsNearPoleAntimeridian ||
+            bRegularTouchesPole) )
+    {
+        if( bContainsPole || bContainsNearPoleAntimeridian )
+        {
+            OGRGeometry* poNewGeom =
+                            poDstGeom->Difference(&oCutter);
+            if( poNewGeom )
+            {
+                if( bContainsNearPoleAntimeridian )
+                    RemovePoint(poNewGeom, &oPole);
+                delete poDstGeom;
+                poDstGeom = poNewGeom;
+            }
+        }
+
+        if( bRegularTouchesPole )
+        {
+            AlterPole(poDstGeom, &oPole);
+        }
+
+        bNeedPostCorrectionOut = true;
+    }
+    return poDstGeom;
+}
+
+/************************************************************************/
+/*                        IsAntimeridianProjToWGS84()                   */
+/*                                                                      */
+/* Returns true if poCT transforms from a projection that includes the  */
+/* antimeridian in a continuous way.                                    */
+/************************************************************************/
+
+static bool IsAntimeridianProjToWGS84( OGRCoordinateTransformation* poCT,
+                                       OGRCoordinateTransformation* poRevCT,
+                                       OGRGeometry* poDstGeometry )
+{
+    const bool bBackupEmitErrors = poCT->GetEmitErrors();
+    poRevCT->SetEmitErrors(false);
+    poCT->SetEmitErrors(false);
+
+    // Find a reasonable latitude for the geometry
+    OGREnvelope sEnvelope;
+    poDstGeometry->getEnvelope(&sEnvelope);
+    OGRPoint pMean( sEnvelope.MinX, (sEnvelope.MinY + sEnvelope.MaxY) / 2 );
+    if( pMean.transform(poCT) != OGRERR_NONE )
+    {
+        poCT->SetEmitErrors(bBackupEmitErrors);
+        return false;
+    }
+    const double dfMeanLat = pMean.getY();
+
+    // Check that close points on each side of the antimeridian in (long, lat)
+    // project to close points in the source projection, and check that they
+    // roundtrip correctly.
+    const double EPS = 1.0e-8;
+    double x1 = 180 - EPS;
+    double y1 = dfMeanLat;
+    double x2 = -180 + EPS;
+    double y2 = dfMeanLat;
+    if( !poRevCT->Transform( 1, &x1, &y1 ) ||
+        !poRevCT->Transform( 1, &x2, &y2 ) ||
+        GetDist(x2-x1, y2-y1) > 1 ||
+        !poCT->Transform( 1, &x1, &y1 ) ||
+        !poCT->Transform( 1, &x2, &y2 ) ||
+        GetDist(x1 - (180 - EPS), y1 - dfMeanLat) > 2 * EPS ||
+        GetDist(x2 - (-180 + EPS), y2 - dfMeanLat) > 2 * EPS )
+    {
+        poCT->SetEmitErrors(bBackupEmitErrors);
+        return false;
+    }
+
+    poCT->SetEmitErrors(bBackupEmitErrors);
+
+    return true;
+}
+
+/************************************************************************/
+/*                      CollectPointsOnAntimeridian()                   */
+/*                                                                      */
+/* Collect points that are the intersection of the lines of the geometry*/
+/* with the antimeridian.                                               */
+/************************************************************************/
+
+static void CollectPointsOnAntimeridian(OGRGeometry* poGeom,
+                                        OGRCoordinateTransformation* poCT,
+                                        OGRCoordinateTransformation* poRevCT,
+                                        std::vector<OGRRawPoint>& aoPoints )
+{
+    const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
+    switch( eType )
+    {
+        case wkbLineString:
+        {
+            OGRLineString* poLS = reinterpret_cast<OGRLineString*>(poGeom);
+            const int nNumPoints = poLS->getNumPoints();
+            for( int i = 0; i < nNumPoints-1; i++ )
+            {
+                const double dfX = poLS->getX(i);
+                const double dfY = poLS->getY(i);
+                const double dfX2 = poLS->getX(i+1);
+                const double dfY2 = poLS->getY(i+1);
+                double dfXTrans = dfX;
+                double dfYTrans = dfY;
+                double dfX2Trans = dfX2;
+                double dfY2Trans = dfY2;
+                poCT->Transform(1, &dfXTrans, &dfYTrans);
+                poCT->Transform(1, &dfX2Trans, &dfY2Trans);
+                // Are we crossing the antimeridian ? (detecting by inversion of
+                // sign of X)
+                if( (dfX2 - dfX) * (dfX2Trans - dfXTrans) < 0 )
+                {
+                    double dfXStart = dfX;
+                    double dfYStart = dfY;
+                    double dfXEnd = dfX2;
+                    double dfYEnd = dfY2;
+                    double dfXStartTrans = dfXTrans;
+                    double dfXEndTrans = dfX2Trans;
+                    int iIter = 0;
+                    const double EPS = 1e-8;
+                    // Find point of the segment intersecting the antimeridian
+                    // by dichotomy
+                    for( ;
+                         iIter < 50 &&
+                           (fabs(fabs(dfXStartTrans) - 180) > EPS ||
+                            fabs(fabs(dfXEndTrans) - 180) > EPS);
+                         ++iIter )
+                    {
+                        double dfXMid = (dfXStart + dfXEnd) / 2;
+                        double dfYMid = (dfYStart + dfYEnd) / 2;
+                        double dfXMidTrans = dfXMid;
+                        double dfYMidTrans = dfYMid;
+                        poCT->Transform(1, &dfXMidTrans, &dfYMidTrans);
+                        if( (dfXMid - dfXStart) *
+                                        (dfXMidTrans - dfXStartTrans) < 0 )
+                        {
+                            dfXEnd = dfXMid;
+                            dfYEnd = dfYMid;
+                            dfXEndTrans = dfXMidTrans;
+                        }
+                        else
+                        {
+                            dfXStart = dfXMid;
+                            dfYStart = dfYMid;
+                            dfXStartTrans = dfXMidTrans;
+                        }
+                    }
+                    if( iIter < 50 )
+                    {
+                        OGRRawPoint oPoint;
+                        oPoint.x = (dfXStart + dfXEnd) / 2;
+                        oPoint.y = (dfYStart + dfYEnd) / 2;
+                        poCT->Transform(1, &(oPoint.x), &(oPoint.y));
+                        oPoint.x = 180.0;
+                        aoPoints.push_back(oPoint);
+                    }
+                }
+            }
+            break;
+        }
+
+        case wkbPolygon:
+        {
+            OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(poGeom);
+            if( poPoly->getExteriorRing() != NULL )
+            {
+                CollectPointsOnAntimeridian(poPoly->getExteriorRing(),
+                                            poCT, poRevCT, aoPoints);
+                for( int i=0; i<poPoly->getNumInteriorRings(); ++i )
+                {
+                    CollectPointsOnAntimeridian(poPoly->getInteriorRing(i),
+                                                poCT, poRevCT, aoPoints);
+                }
+            }
+            break;
+        }
+
+        case wkbMultiLineString:
+        case wkbMultiPolygon:
+        case wkbGeometryCollection:
+        {
+            OGRGeometryCollection* poGC =
+                            reinterpret_cast<OGRGeometryCollection*>(poGeom);
+            for( int i=0; i<poGC->getNumGeometries(); ++i )
+            {
+                CollectPointsOnAntimeridian(poGC->getGeometryRef(i),
+                                            poCT, poRevCT, aoPoints);
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+}
+
+/************************************************************************/
+/*                         SortPointsByAscendingY()                     */
+/************************************************************************/
+
+struct SortPointsByAscendingY
+{
+    bool operator()(const OGRRawPoint& a, const OGRRawPoint& b)
+    {
+        return a.y < b.y;
+    }
+};
+
+/************************************************************************/
+/*                  TransformBeforeAntimeridianToWGS84()                */
+/*                                                                      */
+/* Transform the geometry (by intersection), so as to cut each geometry */
+/* that crosses the antimeridian, in 2 parts.                           */
+/************************************************************************/
+
+static OGRGeometry* TransformBeforeAntimeridianToWGS84(
+                                        OGRCoordinateTransformation* poCT,
+                                        OGRCoordinateTransformation* poRevCT,
+                                        OGRGeometry* poDstGeom,
+                                        bool& bNeedPostCorrectionOut )
+{
+    OGREnvelope sEnvelope;
+    poDstGeom->getEnvelope(&sEnvelope);
+    OGRPoint pMean( sEnvelope.MinX, (sEnvelope.MinY + sEnvelope.MaxY) / 2 );
+    pMean.transform(poCT);
+    const double dfMeanLat = pMean.getY();
+    pMean.setX( 180.0 );
+    pMean.setY( dfMeanLat );
+    pMean.transform(poRevCT);
+    // Check if the antimeridian crosses the bbox of our geometry
+    if( !(pMean.getX() >= sEnvelope.MinX && pMean.getY() >= sEnvelope.MinY &&
+          pMean.getX() <= sEnvelope.MaxX && pMean.getY() <= sEnvelope.MaxY) )
+    {
+        return poDstGeom;
+    }
+
+    // Collect points that are the intersection of the lines of the geometry
+    // with the antimeridian
+    std::vector<OGRRawPoint> aoPoints;
+    CollectPointsOnAntimeridian(poDstGeom, poCT, poRevCT, aoPoints);
+    if( aoPoints.empty() )
+        return poDstGeom;
+
+    SortPointsByAscendingY sortFunc;
+    std::sort( aoPoints.begin(), aoPoints.end(), sortFunc );
+
+    const double EPS = 1e-9;
+
+    // Build a multipolygon (in projected space) with 2 parts: one part left
+    // of the antimeridian, one part east
+    const OGRwkbGeometryType eType = wkbFlatten(poDstGeom->getGeometryType());
+
+    // If we have lines, then to get better accuracy of the intersection with
+    // the main geometry, we need to add extra points
+    const bool bHasLines = (eType == wkbLineString ||
+                            eType == wkbMultiLineString);
+
+    OGRLinearRing* poLR1 = new OGRLinearRing();
+    poLR1->addPoint( sEnvelope.MinX, sEnvelope.MinY );
+    if( bHasLines )
+    {
+        double x = 180.0 - EPS;
+        double y = aoPoints[0].y-EPS;
+        poRevCT->Transform(1, &x, &y);
+        poLR1->addPoint( x, y );
+    }
+    for( size_t i = 0; i < aoPoints.size(); ++i )
+    {
+        double x = 180.0 - EPS;
+        double y = aoPoints[i].y;
+        poRevCT->Transform(1, &x, &y);
+        poLR1->addPoint( x, y );
+    }
+    if( bHasLines )
+    {
+        double x = 180.0 - EPS;
+        double y = aoPoints.back().y+EPS;
+        poRevCT->Transform(1, &x, &y);
+        poLR1->addPoint( x, y );
+    }
+    poLR1->addPoint( sEnvelope.MinX, sEnvelope.MaxY );
+    poLR1->addPoint( sEnvelope.MinX, sEnvelope.MinY );
+    OGRPolygon* poPoly1 = new OGRPolygon();
+    poPoly1->addRingDirectly( poLR1 );
+
+
+    OGRLinearRing* poLR2 = new OGRLinearRing();
+    poLR2->addPoint( sEnvelope.MaxX, sEnvelope.MinY );
+    if( bHasLines )
+    {
+        double x = -180.0 + EPS;
+        double y = aoPoints[0].y-EPS;
+        poRevCT->Transform(1, &x, &y);
+        poLR2->addPoint( x, y );
+    }
+    for( size_t i = 0; i < aoPoints.size(); ++i )
+    {
+        double x = -180.0 + EPS;
+        double y = aoPoints[i].y;
+        poRevCT->Transform(1, &x, &y);
+        poLR2->addPoint( x, y );
+    }
+    if( bHasLines )
+    {
+        double x = -180.0 + EPS;
+        double y = aoPoints.back().y+EPS;
+        poRevCT->Transform(1, &x, &y);
+        poLR2->addPoint( x, y );
+    }
+    poLR2->addPoint( sEnvelope.MaxX, sEnvelope.MaxY );
+    poLR2->addPoint( sEnvelope.MaxX, sEnvelope.MinY );
+    OGRPolygon* poPoly2 = new OGRPolygon();
+    poPoly2->addRingDirectly( poLR2 );
+
+    OGRMultiPolygon oMP;
+    oMP.addGeometryDirectly(poPoly1);
+    oMP.addGeometryDirectly(poPoly2);
+
+#if DEBUG_VERBOSE
+    char* pszWKT = NULL;
+    oMP.exportToWkt(&pszWKT);
+    CPLDebug("OGR", "MP without antimeridian: %s", pszWKT);
+    CPLFree(pszWKT);
+#endif
+
+    // Get the geometry without the antimeridian
+    OGRGeometry* poInter = poDstGeom->Intersection(&oMP);
+    if( poInter != NULL )
+    {
+        delete poDstGeom;
+        poDstGeom = poInter;
+    }
+
+    bNeedPostCorrectionOut = true;
+    return poDstGeom;
+}
+
+/************************************************************************/
+/*                 SnapCoordsCloseToLatLongBounds()                     */
+/*                                                                      */
+/* This function snaps points really close to the antimerdian or poles  */
+/* to their exact longitudes/latitudes.                                 */
+/************************************************************************/
+
+static void SnapCoordsCloseToLatLongBounds(OGRGeometry* poGeom)
+{
+    const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
+    switch( eType )
+    {
+        case wkbLineString:
+        {
+            OGRLineString* poLS = reinterpret_cast<OGRLineString*>(poGeom);
+            const double EPS = 1e-8;
+            for( int i = 0; i < poLS->getNumPoints(); i++ )
+            {
+                OGRPoint p;
+                poLS->getPoint(i, &p);
+                if( fabs( p.getX() - 180.0 ) < EPS )
+                {
+                    p.setX(180.0);
+                    poLS->setPoint(i, &p);
+                }
+                else if( fabs( p.getX() - -180.0 ) < EPS )
+                {
+                    p.setX(-180.0);
+                    poLS->setPoint(i, &p);
+                }
+
+                if( fabs( p.getY() - 90.0 ) < EPS )
+                {
+                    p.setY(90.0);
+                    poLS->setPoint(i, &p);
+                }
+                else if( fabs( p.getY() - -90.0 ) < EPS )
+                {
+                    p.setY(-90.0);
+                    poLS->setPoint(i, &p);
+                }
+            }
+            break;
+        }
+
+        case wkbPolygon:
+        {
+            OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(poGeom);
+            if( poPoly->getExteriorRing() != NULL )
+            {
+                SnapCoordsCloseToLatLongBounds(poPoly->getExteriorRing());
+                for( int i=0; i<poPoly->getNumInteriorRings(); ++i )
+                {
+                    SnapCoordsCloseToLatLongBounds(poPoly->getInteriorRing(i));
+                }
+            }
+            break;
+        }
+
+        case wkbMultiLineString:
+        case wkbMultiPolygon:
+        case wkbGeometryCollection:
+        {
+            OGRGeometryCollection* poGC =
+                            reinterpret_cast<OGRGeometryCollection*>(poGeom);
+            for( int i=0; i<poGC->getNumGeometries(); ++i )
+            {
+                SnapCoordsCloseToLatLongBounds(poGC->getGeometryRef(i));
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+}
+
+#endif
+
+/************************************************************************/
+/*                       transformWithOptions()                         */
+/************************************************************************/
+
+/** Transform a geometry.
+ * @param poSrcGeom source geometry
+ * @param poCT coordinate transformation object.
+ * @param papszOptions options. Including WRAPDATELINE=YES.
+ * @return (new) transformed geometry.
+ */
+OGRGeometry* OGRGeometryFactory::transformWithOptions(
+    const OGRGeometry* poSrcGeom,
+    OGRCoordinateTransformation *poCT,
+    char** papszOptions )
+{
+    OGRGeometry* poDstGeom = poSrcGeom->clone();
+    if( poCT != NULL )
+    {
+#ifdef HAVE_GEOS
+        bool bNeedPostCorrection = false;
+
+        if( poCT->GetSourceCS() != NULL &&
+            poCT->GetTargetCS() != NULL )
+        {
+            OGRSpatialReference oSRSWGS84;
+            oSRSWGS84.SetWellKnownGeogCS( "WGS84" );
+            if( poCT->GetTargetCS()->IsSame(&oSRSWGS84) )
+            {
+                OGRCoordinateTransformation* poRevCT =
+                    OGRCreateCoordinateTransformation( &oSRSWGS84,
+                                                       poCT->GetSourceCS() );
+                if( poRevCT != NULL )
+                {
+                    bool bIsNorthPolar = false;
+                    if( IsPolarToWGS84(poCT, poRevCT, bIsNorthPolar) )
+                    {
+                        poDstGeom = TransformBeforePolarToWGS84(
+                                        poRevCT, bIsNorthPolar, poDstGeom,
+                                        bNeedPostCorrection);
+                    }
+                    else if( IsAntimeridianProjToWGS84(poCT, poRevCT,
+                                                       poDstGeom) )
+                    {
+                        poDstGeom = TransformBeforeAntimeridianToWGS84(
+                                        poCT, poRevCT, poDstGeom,
+                                        bNeedPostCorrection);
+                    }
+
+                    delete poRevCT;
+                }
+            }
+        }
+#endif
+        OGRErr eErr = poDstGeom->transform(poCT);
+        if( eErr != OGRERR_NONE )
+        {
+            delete poDstGeom;
+            return NULL;
+        }
+#ifdef HAVE_GEOS
+        if( bNeedPostCorrection )
+        {
+            SnapCoordsCloseToLatLongBounds(poDstGeom);
+        }
+#endif
+    }
+
+    if( CPLTestBool(CSLFetchNameValueDef(papszOptions, "WRAPDATELINE", "NO")) )
+    {
+        const OGRwkbGeometryType eType =
+            wkbFlatten(poDstGeom->getGeometryType());
+        if( eType == wkbPoint )
+        {
+            OGRPoint* poDstPoint = reinterpret_cast<OGRPoint*>(poDstGeom);
+            if( poDstPoint->getX() > 180 )
+            {
+                poDstPoint->setX(fmod(poDstPoint->getX() + 180, 360) - 180);
+            }
+            else if( poDstPoint->getX() < -180 )
+            {
+                poDstPoint->setX(-(fmod(-poDstPoint->getX() + 180, 360) - 180));
+            }
+        }
+        else
+        {
+            OGREnvelope sEnvelope;
+            poDstGeom->getEnvelope(&sEnvelope);
+            if( sEnvelope.MinX >= -360.0 && sEnvelope.MaxX <= -180.0 )
+                AddOffsetToLon( poDstGeom, 360.0 );
+            else if( sEnvelope.MinX >= 180.0 && sEnvelope.MaxX <= 360.0 )
+                AddOffsetToLon( poDstGeom, -360.0 );
+            else
+            {
+                OGRwkbGeometryType eNewType;
+                if( eType == wkbPolygon || eType == wkbMultiPolygon )
+                    eNewType = wkbMultiPolygon;
+                else if( eType == wkbLineString || eType == wkbMultiLineString )
+                    eNewType = wkbMultiLineString;
+                else
+                    eNewType = wkbGeometryCollection;
+
+                OGRGeometry* poMultiGeom = createGeometry(eNewType);
+                OGRGeometryCollection* poMulti =
+                    reinterpret_cast<OGRGeometryCollection*>(poMultiGeom);
+
+                double dfDateLineOffset =
+                    CPLAtofM(CSLFetchNameValueDef(papszOptions,
+                                                "DATELINEOFFSET", "10"));
+                if( dfDateLineOffset <= 0.0 || dfDateLineOffset >= 360.0 )
+                    dfDateLineOffset = 10.0;
+
+                CutGeometryOnDateLineAndAddToMulti(poMulti, poDstGeom,
+                                                dfDateLineOffset);
+
+                if( poMulti->getNumGeometries() == 0 )
+                {
+                    delete poMultiGeom;
+                }
+                else if( poMulti->getNumGeometries() == 1 )
+                {
+                    delete poDstGeom;
+                    poDstGeom = poMulti->getGeometryRef(0)->clone();
+                    delete poMultiGeom;
+                }
+                else
+                {
+                    delete poDstGeom;
+                    poDstGeom = poMultiGeom;
+                }
+            }
+        }
+    }
+
+    return poDstGeom;
+}
+
+/************************************************************************/
+/*                       OGRGF_GetDefaultStepSize()                     */
+/************************************************************************/
+
+static double OGRGF_GetDefaultStepSize()
+{
+    return CPLAtofM(CPLGetConfigOption("OGR_ARC_STEPSIZE", "4"));
+}
+
+/************************************************************************/
+/*                        approximateArcAngles()                        */
+/************************************************************************/
+
+/**
+ * Stroke arc to linestring.
+ *
+ * Stroke an arc of a circle to a linestring based on a center
+ * point, radius, start angle and end angle, all angles in degrees.
+ *
  * If the dfMaxAngleStepSizeDegrees is zero, then a default value will be
  * used.  This is currently 4 degrees unless the user has overridden the
  * value with the OGR_ARC_STEPSIZE configuration variable.
@@ -2694,47 +3763,41 @@ OGRGeometry* OGRGeometryFactory::approximateArcAngles(
     double dfMaxAngleStepSizeDegrees )
 
 {
-    double             dfSlice;
-    int                iPoint, nVertexCount;
-    OGRLineString     *poLine = new OGRLineString();
-    double             dfRotationRadians = dfRotation * M_PI / 180.0;
+    OGRLineString *poLine = new OGRLineString();
+    const double dfRotationRadians = dfRotation * M_PI / 180.0;
 
-    // support default arc step setting.
+    // Support default arc step setting.
     if( dfMaxAngleStepSizeDegrees < 1e-6 )
     {
         dfMaxAngleStepSizeDegrees = OGRGF_GetDefaultStepSize();
     }
 
-    // switch direction
+    // Switch direction.
     dfStartAngle *= -1;
     dfEndAngle *= -1;
 
     // Figure out the number of slices to make this into.
-    nVertexCount = (int)
-        ceil(fabs(dfEndAngle - dfStartAngle)/dfMaxAngleStepSizeDegrees) + 1;
-    nVertexCount = MAX(2,nVertexCount);
-    dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
+    const int nVertexCount = std::max(2, static_cast<int>(
+        ceil(fabs(dfEndAngle - dfStartAngle)/dfMaxAngleStepSizeDegrees) + 1));
+    const double dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
 
 /* -------------------------------------------------------------------- */
 /*      Compute the interpolated points.                                */
 /* -------------------------------------------------------------------- */
-    for( iPoint=0; iPoint < nVertexCount; iPoint++ )
+    for( int iPoint = 0; iPoint < nVertexCount; iPoint++ )
     {
-        double      dfAngleOnEllipse;
-        double      dfArcX, dfArcY;
-        double      dfEllipseX, dfEllipseY;
-
-        dfAngleOnEllipse = (dfStartAngle + iPoint * dfSlice) * M_PI / 180.0;
+        const double dfAngleOnEllipse =
+            (dfStartAngle + iPoint * dfSlice) * M_PI / 180.0;
 
         // Compute position on the unrotated ellipse.
-        dfEllipseX = cos(dfAngleOnEllipse) * dfPrimaryRadius;
-        dfEllipseY = sin(dfAngleOnEllipse) * dfSecondaryRadius;
+        const double dfEllipseX = cos(dfAngleOnEllipse) * dfPrimaryRadius;
+        const double dfEllipseY = sin(dfAngleOnEllipse) * dfSecondaryRadius;
 
         // Rotate this position around the center of the ellipse.
-        dfArcX = dfCenterX
+        const double dfArcX = dfCenterX
             + dfEllipseX * cos(dfRotationRadians)
             + dfEllipseY * sin(dfRotationRadians);
-        dfArcY = dfCenterY
+        const double dfArcY = dfCenterY
             - dfEllipseX * sin(dfRotationRadians)
             + dfEllipseY * cos(dfRotationRadians);
 
@@ -2784,10 +3847,11 @@ OGR_G_ApproximateArcAngles(
     double dfMaxAngleStepSizeDegrees )
 
 {
-    return (OGRGeometryH) OGRGeometryFactory::approximateArcAngles(
-        dfCenterX, dfCenterY, dfZ,
-        dfPrimaryRadius, dfSecondaryRadius, dfRotation,
-        dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees );
+    return reinterpret_cast<OGRGeometryH>(
+        OGRGeometryFactory::approximateArcAngles(
+            dfCenterX, dfCenterY, dfZ,
+            dfPrimaryRadius, dfSecondaryRadius, dfRotation,
+            dfStartAngle, dfEndAngle, dfMaxAngleStepSizeDegrees));
 }
 
 /************************************************************************/
@@ -2815,20 +3879,21 @@ OGR_G_ApproximateArcAngles(
  * @return new geometry.
  */
 
-OGRGeometry *OGRGeometryFactory::forceToLineString( OGRGeometry *poGeom, bool bOnlyInOrder )
+OGRGeometry *OGRGeometryFactory::forceToLineString( OGRGeometry *poGeom,
+                                                    bool bOnlyInOrder )
 
 {
     if( poGeom == NULL )
         return NULL;
 
-    OGRwkbGeometryType eGeomType = wkbFlatten(poGeom->getGeometryType());
+    const OGRwkbGeometryType eGeomType = wkbFlatten(poGeom->getGeometryType());
 
 /* -------------------------------------------------------------------- */
 /*      If this is already a LineString, nothing to do                  */
 /* -------------------------------------------------------------------- */
     if( eGeomType == wkbLineString )
     {
-        /* except if it is a linearring */
+        // Except if it is a linearring.
         poGeom = OGRCurve::CastToLineString((OGRCurve*)poGeom);
 
         return poGeom;
@@ -2860,17 +3925,17 @@ OGRGeometry *OGRGeometryFactory::forceToLineString( OGRGeometry *poGeom, bool bO
         return poNewGeom;
     }
 
-
     if( eGeomType != wkbGeometryCollection
         && eGeomType != wkbMultiLineString
         && eGeomType != wkbMultiCurve )
         return poGeom;
 
-    // build an aggregated linestring from all the linestrings in the container.
+    // Build an aggregated linestring from all the linestrings in the container.
     OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
     if( poGeom->hasCurveGeometry() )
     {
-        OGRGeometryCollection *poNewGC = (OGRGeometryCollection *) poGC->getLinearGeometry();
+        OGRGeometryCollection *poNewGC =
+            (OGRGeometryCollection *) poGC->getLinearGeometry();
         delete poGC;
         poGC = poNewGC;
     }
@@ -2893,41 +3958,46 @@ OGRGeometry *OGRGeometryFactory::forceToLineString( OGRGeometry *poGeom, bool bO
             continue;
         }
 
-        OGRLineString *poLineString0 = (OGRLineString *) poGC->getGeometryRef(iGeom0);
+        OGRLineString *poLineString0 =
+            (OGRLineString *) poGC->getGeometryRef(iGeom0);
         if( poLineString0->getNumPoints() < 2 )
         {
             iGeom0++;
             continue;
         }
 
-        OGRPoint pointStart0, pointEnd0;
+        OGRPoint pointStart0;
         poLineString0->StartPoint( &pointStart0 );
+        OGRPoint pointEnd0;
         poLineString0->EndPoint( &pointEnd0 );
 
-        int iGeom1;
-        for( iGeom1 = iGeom0 + 1; iGeom1 < poGC->getNumGeometries(); iGeom1++ )
+        int iGeom1 = iGeom0 + 1;  // Used after for.
+        for( ; iGeom1 < poGC->getNumGeometries(); iGeom1++ )
         {
             if( wkbFlatten(poGC->getGeometryRef(iGeom1)->getGeometryType())
                 != wkbLineString )
                 continue;
 
-            OGRLineString *poLineString1 = (OGRLineString *) poGC->getGeometryRef(iGeom1);
+            OGRLineString *poLineString1 =
+                (OGRLineString *) poGC->getGeometryRef(iGeom1);
             if( poLineString1->getNumPoints() < 2 )
                 continue;
 
-            OGRPoint pointStart1, pointEnd1;
+            OGRPoint pointStart1;
             poLineString1->StartPoint( &pointStart1 );
+            OGRPoint pointEnd1;
             poLineString1->EndPoint( &pointEnd1 );
 
-            if ( !bOnlyInOrder &&
-                 ( pointEnd0.Equals( &pointEnd1 ) || pointStart0.Equals( &pointStart1 ) ) )
+            if( !bOnlyInOrder &&
+                (pointEnd0.Equals( &pointEnd1 ) ||
+                 pointStart0.Equals( &pointStart1 )) )
             {
                 poLineString1->reversePoints();
                 poLineString1->StartPoint( &pointStart1 );
                 poLineString1->EndPoint( &pointEnd1 );
             }
 
-            if ( pointEnd0.Equals( &pointStart1 ) )
+            if( pointEnd0.Equals( &pointStart1 ) )
             {
                 poLineString0->addSubLineString( poLineString1, 1 );
                 poGC->removeGeometry( iGeom1 );
@@ -2942,13 +4012,13 @@ OGRGeometry *OGRGeometryFactory::forceToLineString( OGRGeometry *poGeom, bool bO
             }
         }
 
-        if ( iGeom1 == poGC->getNumGeometries() )
+        if( iGeom1 == poGC->getNumGeometries() )
         {
             iGeom0++;
         }
     }
 
-    if ( poGC->getNumGeometries() == 1 )
+    if( poGC->getNumGeometries() == 1 )
     {
         OGRGeometry *poSingleGeom = poGC->getGeometryRef(0);
         poGC->removeGeometry( 0, FALSE );
@@ -2979,11 +4049,11 @@ OGRGeometry *OGRGeometryFactory::forceToLineString( OGRGeometry *poGeom, bool bO
 OGRGeometryH OGR_G_ForceToLineString( OGRGeometryH hGeom )
 
 {
-    return (OGRGeometryH)
-        OGRGeometryFactory::forceToLineString( (OGRGeometry *) hGeom );
+    return reinterpret_cast<OGRGeometryH>(
+        OGRGeometryFactory::forceToLineString(
+            reinterpret_cast<OGRGeometry *>(hGeom)));
 }
 
-
 /************************************************************************/
 /*                           forceTo()                                  */
 /************************************************************************/
@@ -2996,13 +4066,13 @@ OGRGeometryH OGR_G_ForceToLineString( OGRGeometryH hGeom )
  * It can promote 'single' geometry type to their corresponding collection type
  * (see OGR_GT_GetCollection()) or the reverse. non-linear geometry type to
  * their corresponding linear geometry type (see OGR_GT_GetLinear()), by
- * possibly approximating circular arcs they may contain.
- * Regarding conversion from linear geometry types to curve geometry types, only
- * "wraping" will be done. No attempt to retrieve potential circular arcs by
- * de-approximating stroking will be done. For that, OGRGeometry::getCurveGeometry()
- * can be used.
+ * possibly approximating circular arcs they may contain.  Regarding conversion
+ * from linear geometry types to curve geometry types, only "wraping" will be
+ * done. No attempt to retrieve potential circular arcs by de-approximating
+ * stroking will be done. For that, OGRGeometry::getCurveGeometry() can be used.
  *
- * The passed in geometry is consumed and a new one returned (or potentially the same one).
+ * The passed in geometry is consumed and a new one returned (or potentially the
+ * same one).
  *
  * @param poGeom the input geometry - ownership is passed to the method.
  * @param eTargetType target output geometry type.
@@ -3033,7 +4103,175 @@ OGRGeometry * OGRGeometryFactory::forceTo( OGRGeometry* poGeom,
         return poRet;
     }
 
-    /* Promote single to multi */
+    if( OGR_GT_IsSubClassOf(eType, wkbPolyhedralSurface) &&
+        (eTargetType == wkbMultiSurface ||
+         eTargetType == wkbGeometryCollection) )
+    {
+        return forceTo( forceTo( poGeom, wkbMultiPolygon, papszOptions),
+                        eTargetType, papszOptions );
+    }
+
+    if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) &&
+        eTargetType == wkbGeometryCollection )
+    {
+        OGRGeometryCollection* poGC =
+                        dynamic_cast<OGRGeometryCollection*>(poGeom);
+        if( poGC == NULL )
+            return poGeom;
+        return OGRGeometryCollection::CastToGeometryCollection(poGC);
+    }
+
+    if( eType == wkbTriangle && eTargetType == wkbPolyhedralSurface )
+    {
+        OGRPolyhedralSurface* poPS = new OGRPolyhedralSurface();
+        poPS->assignSpatialReference( poGeom->getSpatialReference() );
+        poPS->addGeometryDirectly( OGRTriangle::CastToPolygon(poGeom) );
+        return poPS;
+    }
+    else if( eType == wkbPolygon && eTargetType == wkbPolyhedralSurface )
+    {
+        OGRPolyhedralSurface* poPS = new OGRPolyhedralSurface();
+        poPS->assignSpatialReference( poGeom->getSpatialReference() );
+        poPS->addGeometryDirectly( poGeom );
+        return poPS;
+    }
+    else if( eType == wkbMultiPolygon && eTargetType == wkbPolyhedralSurface )
+    {
+        OGRMultiPolygon* poMP = reinterpret_cast<OGRMultiPolygon*>(poGeom);
+        OGRPolyhedralSurface* poPS = new OGRPolyhedralSurface();
+        for( int i = 0; i < poMP->getNumGeometries(); ++i )
+        {
+            poPS->addGeometry( poMP->getGeometryRef(i) );
+        }
+        delete poGeom;
+        return poPS;
+    }
+    else if( eType == wkbTIN && eTargetType == wkbPolyhedralSurface )
+    {
+        poGeom = OGRTriangulatedSurface::CastToPolyhedralSurface(
+                    (OGRTriangulatedSurface*)poGeom);
+    }
+    else if( eType == wkbCurvePolygon && eTargetType == wkbPolyhedralSurface )
+    {
+        return forceTo( forceTo( poGeom, wkbPolygon, papszOptions ),
+                        eTargetType, papszOptions );
+    }
+    else if( eType == wkbMultiSurface && eTargetType == wkbPolyhedralSurface )
+    {
+        return forceTo( forceTo( poGeom, wkbMultiPolygon, papszOptions ),
+                        eTargetType, papszOptions );
+    }
+
+    else if( eType == wkbTriangle && eTargetType == wkbTIN )
+    {
+        OGRTriangulatedSurface* poTS = new OGRTriangulatedSurface();
+        poTS->assignSpatialReference( poGeom->getSpatialReference() );
+        poTS->addGeometryDirectly( poGeom );
+        return poTS;
+    }
+    else if( eType == wkbPolygon && eTargetType == wkbTIN )
+    {
+        OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(poGeom);
+        OGRLinearRing* poLR = poPoly->getExteriorRing();
+        if( !(poLR != NULL && poLR->getNumPoints() == 4 &&
+                poPoly->getNumInteriorRings() == 0) )
+        {
+            return poGeom;
+        }
+        OGRErr eErr = OGRERR_NONE;
+        OGRTriangle* poTriangle = new OGRTriangle(*poPoly, eErr);
+        OGRTriangulatedSurface* poTS = new OGRTriangulatedSurface();
+        poTS->assignSpatialReference( poGeom->getSpatialReference() );
+        poTS->addGeometryDirectly( poTriangle );
+        delete poGeom;
+        return poTS;
+    }
+    else if( eType == wkbMultiPolygon && eTargetType == wkbTIN )
+    {
+        OGRMultiPolygon* poMP = reinterpret_cast<OGRMultiPolygon*>(poGeom);
+        for( int i = 0; i < poMP->getNumGeometries(); ++i )
+        {
+            OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(
+                                                    poMP->getGeometryRef(i) );
+            OGRLinearRing* poLR = poPoly->getExteriorRing();
+            if( !(poLR != NULL && poLR->getNumPoints() == 4 &&
+                  poPoly->getNumInteriorRings() == 0) )
+            {
+                return poGeom;
+            }
+        }
+        OGRTriangulatedSurface* poTS = new OGRTriangulatedSurface();
+        poTS->assignSpatialReference( poGeom->getSpatialReference() );
+        for( int i = 0; i < poMP->getNumGeometries(); ++i )
+        {
+            OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(
+                                                    poMP->getGeometryRef(i) );
+            OGRErr eErr = OGRERR_NONE;
+            poTS->addGeometryDirectly( new OGRTriangle(*poPoly, eErr) );
+        }
+        delete poGeom;
+        return poTS;
+    }
+    else if( eType == wkbPolyhedralSurface && eTargetType == wkbTIN )
+    {
+        OGRPolyhedralSurface* poPS = reinterpret_cast<OGRPolyhedralSurface*>(poGeom);
+        for( int i = 0; i < poPS->getNumGeometries(); ++i )
+        {
+            OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(
+                                                    poPS->getGeometryRef(i) );
+            OGRLinearRing* poLR = poPoly->getExteriorRing();
+            if( !(poLR != NULL && poLR->getNumPoints() == 4 &&
+                  poPoly->getNumInteriorRings() == 0) )
+            {
+                return poGeom;
+            }
+        }
+        OGRTriangulatedSurface* poTS = new OGRTriangulatedSurface();
+        poTS->assignSpatialReference( poGeom->getSpatialReference() );
+        for( int i = 0; i < poPS->getNumGeometries(); ++i )
+        {
+            OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(
+                                                    poPS->getGeometryRef(i) );
+            OGRErr eErr = OGRERR_NONE;
+            poTS->addGeometryDirectly( new OGRTriangle(*poPoly, eErr) );
+        }
+        delete poGeom;
+        return poTS;
+    }
+
+    else if( eType == wkbPolygon && eTargetType == wkbTriangle )
+    {
+        OGRPolygon* poPoly = reinterpret_cast<OGRPolygon*>(poGeom);
+        OGRLinearRing* poLR = poPoly->getExteriorRing();
+        if( !(poLR != NULL && poLR->getNumPoints() == 4 &&
+                poPoly->getNumInteriorRings() == 0) )
+        {
+            return poGeom;
+        }
+        OGRErr eErr = OGRERR_NONE;
+        OGRTriangle* poTriangle = new OGRTriangle(*poPoly, eErr);
+        delete poGeom;
+        return poTriangle;
+    }
+
+    if( eTargetType == wkbTriangle || eTargetType == wkbTIN ||
+        eTargetType == wkbPolyhedralSurface )
+    {
+        OGRGeometry* poPoly = forceTo( poGeom, wkbPolygon, papszOptions );
+        if( poPoly == poGeom )
+            return poGeom;
+        return forceTo( poPoly, eTargetType, papszOptions );
+    }
+
+    if( eType == wkbTriangle && eTargetType == wkbGeometryCollection )
+    {
+        OGRGeometryCollection* poGC = new OGRGeometryCollection();
+        poGC->assignSpatialReference(poGeom->getSpatialReference());
+        poGC->addGeometryDirectly(poGeom);
+        return poGC;
+    }
+
+    // Promote single to multi.
     if( !OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) &&
          OGR_GT_IsSubClassOf(OGR_GT_GetCollection(eType), eTargetType) )
     {
@@ -3050,7 +4288,7 @@ OGRGeometry * OGRGeometryFactory::forceTo( OGRGeometry* poGeom,
         return poRet;
     }
 
-    int bIsCurve = OGR_GT_IsCurve(eType);
+    const bool bIsCurve = CPL_TO_BOOL(OGR_GT_IsCurve(eType));
     if( bIsCurve && eTargetType == wkbCompoundCurve )
     {
         return OGRCurve::CastToCompoundCurve((OGRCurve*)poGeom);
@@ -3091,7 +4329,12 @@ OGRGeometry * OGRGeometryFactory::forceTo( OGRGeometry* poGeom,
         if( wkbFlatten(poTmp->getGeometryType()) != eType)
             return forceTo(poTmp, eTargetType, papszOptions);
     }
-    else if (eType == wkbPolygon && eTargetType == wkbCurvePolygon)
+    else if( eType == wkbTriangle && eTargetType == wkbCurvePolygon )
+    {
+        return OGRSurface::CastToCurvePolygon(
+            reinterpret_cast<OGRSurface*>(OGRTriangle::CastToPolygon(poGeom)) );
+    }
+    else if( eType == wkbPolygon && eTargetType == wkbCurvePolygon )
     {
         return OGRSurface::CastToCurvePolygon((OGRPolygon*)poGeom);
     }
@@ -3108,25 +4351,28 @@ OGRGeometry * OGRGeometryFactory::forceTo( OGRGeometry* poGeom,
             return forceTo(poRet, eTargetType, papszOptions);
         }
     }
-    else if ( eType == wkbMultiPolygon && eTargetType == wkbMultiSurface )
+    else if( eType == wkbMultiPolygon && eTargetType == wkbMultiSurface )
     {
         return OGRMultiPolygon::CastToMultiSurface((OGRMultiPolygon*)poGeom);
     }
-    else if ( eType == wkbMultiLineString && eTargetType == wkbMultiCurve )
+    else if( eType == wkbMultiLineString && eTargetType == wkbMultiCurve )
     {
-        return OGRMultiLineString::CastToMultiCurve((OGRMultiLineString*)poGeom);
+        return
+            OGRMultiLineString::CastToMultiCurve((OGRMultiLineString*)poGeom);
     }
-    else if ( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) )
+    else if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) )
     {
         OGRGeometryCollection* poGC = (OGRGeometryCollection*)poGeom;
         if( poGC->getNumGeometries() == 1 )
         {
             OGRGeometry* poSubGeom = poGC->getGeometryRef(0);
             if( poSubGeom )
-                poSubGeom->assignSpatialReference(poGeom->getSpatialReference());
+                poSubGeom->assignSpatialReference(
+                    poGeom->getSpatialReference());
             poGC->removeGeometry(0, FALSE);
             OGRGeometry* poRet = forceTo(poSubGeom, eTargetType, papszOptions);
-            if( OGR_GT_IsSubClassOf(wkbFlatten(poRet->getGeometryType()), eTargetType) )
+            if( OGR_GT_IsSubClassOf(wkbFlatten(poRet->getGeometryType()),
+                                    eTargetType) )
             {
                 delete poGC;
                 return poRet;
@@ -3152,7 +4398,9 @@ OGRGeometry * OGRGeometryFactory::forceTo( OGRGeometry* poGeom,
                 return poRet;
             }
             else
+            {
                 delete poRet;
+            }
         }
     }
 
@@ -3180,7 +4428,6 @@ OGRGeometry * OGRGeometryFactory::forceTo( OGRGeometry* poGeom,
     return poGeom;
 }
 
-
 /************************************************************************/
 /*                          OGR_G_ForceTo()                             */
 /************************************************************************/
@@ -3203,54 +4450,58 @@ OGRGeometryH OGR_G_ForceTo( OGRGeometryH hGeom,
                             char** papszOptions )
 
 {
-    return (OGRGeometryH)
-        OGRGeometryFactory::forceTo( (OGRGeometry *) hGeom, eTargetType,
-                                     (const char* const*)papszOptions );
+    return reinterpret_cast<OGRGeometryH>(
+        OGRGeometryFactory::forceTo(
+            reinterpret_cast<OGRGeometry *>(hGeom), eTargetType,
+            papszOptions));
 }
 
-
 /************************************************************************/
 /*                         GetCurveParmeters()                          */
 /************************************************************************/
 
+static inline double DISTANCE(double x1, double y1, double x2, double y2)
+{
+    return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
+}
+
 /**
  * \brief Returns the parameter of an arc circle.
  *
+ * Angles are return in radians, with trigonometic convention (counter clock
+ * wise)
+ * 
  * @param x0 x of first point
  * @param y0 y of first point
- * @param z0 z of first point
  * @param x1 x of intermediate point
  * @param y1 y of intermediate point
- * @param z1 z of intermediate point
  * @param x2 x of final point
  * @param y2 y of final point
- * @param z2 z of final point
  * @param R radius (output)
  * @param cx x of arc center (output)
- * @param cx y of arc center (output)
- * @param alpha0 angle between center and first point (output)
- * @param alpha1 angle between center and intermediate point (output)
- * @param alpha2 angle between center and final point (output)
+ * @param cy y of arc center (output)
+ * @param alpha0 angle between center and first point, in radians (output)
+ * @param alpha1 angle between center and intermediate point, in radians (output)
+ * @param alpha2 angle between center and final point, in radians (output)
  * @return TRUE if the points are not aligned and define an arc circle.
  *
  * @since GDAL 2.0
  */
 
-#define DISTANCE(x1,y1,x2,y2) sqrt(((x2)-(x1))*((x2)-(x1))+((y2)-(y1))*((y2)-(y1)))
-
 int OGRGeometryFactory::GetCurveParmeters(
     double x0, double y0, double x1, double y1, double x2, double y2,
-    double& R, double& cx, double& cy, double& alpha0, double& alpha1, double& alpha2 )
+    double& R, double& cx, double& cy,
+    double& alpha0, double& alpha1, double& alpha2 )
 {
-    /* Circle */
+    // Circle.
     if( x0 == x2 && y0 == y2 )
     {
-        if (x0 != x1 || y0 != y1)
+        if( x0 != x1 || y0 != y1 )
         {
             cx = (x0 + x1) / 2;
             cy = (y0 + y1) / 2;
-            R = DISTANCE(cx,cy,x0,y0);
-            /* Arbitrarily pick counter-clock-wise order (like PostGIS does) */
+            R = DISTANCE(cx, cy, x0, y0);
+            // Arbitrarily pick counter-clock-wise order (like PostGIS does).
             alpha0 = atan2(y0 - cy, x0 - cx);
             alpha1 = alpha0 + M_PI;
             alpha2 = alpha0 + 2 * M_PI;
@@ -3267,117 +4518,98 @@ int OGRGeometryFactory::GetCurveParmeters(
     double dx12 = x2 - x1;
     double dy12 = y2 - y1;
 
-    /* Normalize above values so as to make sure we don't end up with */
-    /* computing a difference of too big values */
+    // Normalize above values so as to make sure we don't end up with
+    // computing a difference of too big values.
     double dfScale = fabs(dx01);
     if( fabs(dy01) > dfScale ) dfScale = fabs(dy01);
     if( fabs(dx12) > dfScale ) dfScale = fabs(dx12);
     if( fabs(dy12) > dfScale ) dfScale = fabs(dy12);
-    double dfInvScale = 1.0 / dfScale;
+    const double dfInvScale = 1.0 / dfScale;
     dx01 *= dfInvScale;
     dy01 *= dfInvScale;
     dx12 *= dfInvScale;
     dy12 *= dfInvScale;
 
-    double det = dx01 * dy12 - dx12 * dy01;
-    if( fabs(det) < 1e-8 )
+    const double det = dx01 * dy12 - dx12 * dy01;
+    if( fabs(det) < 1.0e-8 )
     {
         return FALSE;
     }
-    double x01_mid = (x0 + x1) * dfInvScale;
-    double x12_mid = (x1 + x2) * dfInvScale;
-    double y01_mid = (y0 + y1) * dfInvScale;
-    double y12_mid = (y1 + y2) * dfInvScale;
-    double c01 = dx01 * x01_mid + dy01 * y01_mid;
-    double c12 = dx12 * x12_mid + dy12 * y12_mid;
-    cx =  0.5 * dfScale * (c01 * dy12 - c12 * dy01) / det;
-    cy =  0.5 * dfScale * (- c01 * dx12 + c12 * dx01) / det;
+    const double x01_mid = (x0 + x1) * dfInvScale;
+    const double x12_mid = (x1 + x2) * dfInvScale;
+    const double y01_mid = (y0 + y1) * dfInvScale;
+    const double y12_mid = (y1 + y2) * dfInvScale;
+    const double c01 = dx01 * x01_mid + dy01 * y01_mid;
+    const double c12 = dx12 * x12_mid + dy12 * y12_mid;
+    cx = 0.5 * dfScale * (c01 * dy12 - c12 * dy01) / det;
+    cy = 0.5 * dfScale * (-c01 * dx12 + c12 * dx01) / det;
 
     alpha0 = atan2((y0 - cy) * dfInvScale, (x0 - cx) * dfInvScale);
     alpha1 = atan2((y1 - cy) * dfInvScale, (x1 - cx) * dfInvScale);
     alpha2 = atan2((y2 - cy) * dfInvScale, (x2 - cx) * dfInvScale);
-    R = DISTANCE(cx,cy,x0,y0);
+    R = DISTANCE(cx, cy, x0, y0);
 
-    /* if det is negative, the orientation if clockwise */
-    if (det < 0)
+    // If det is negative, the orientation if clockwise.
+    if( det < 0 )
     {
-        if (alpha1 > alpha0)
+        if( alpha1 > alpha0 )
             alpha1 -= 2 * M_PI;
-        if (alpha2 > alpha1)
+        if( alpha2 > alpha1 )
             alpha2 -= 2 * M_PI;
     }
     else
     {
-        if (alpha1 < alpha0)
+        if( alpha1 < alpha0 )
             alpha1 += 2 * M_PI;
-        if (alpha2 < alpha1)
+        if( alpha2 < alpha1 )
             alpha2 += 2 * M_PI;
     }
 
     CPLAssert((alpha0 <= alpha1 && alpha1 <= alpha2) ||
-                (alpha0 >= alpha1 && alpha1 >= alpha2));
+              (alpha0 >= alpha1 && alpha1 >= alpha2));
 
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                      OGRGeometryFactoryStrokeArc()                   */
 /************************************************************************/
 
-//#define ROUND_ANGLE_METHOD
-
-static void OGRGeometryFactoryStrokeArc(OGRLineString* poLine,
-                                        double cx, double cy, double R,
-                                        double z0, double z1, int bHasZ,
-                                        double alpha0, double alpha1,
-                                        double dfStep,
-                                        int bStealthConstraints)
+static void OGRGeometryFactoryStrokeArc( OGRLineString* poLine,
+                                         double cx, double cy, double R,
+                                         double z0, double z1, int bHasZ,
+                                         double alpha0, double alpha1,
+                                         double dfStep,
+                                         int bStealthConstraints )
 {
-    double alpha;
-
-    int nSign = (dfStep > 0) ? 1 : -1;
+    const int nSign = dfStep > 0 ? 1 : -1;
 
-#ifdef ROUND_ANGLE_METHOD
-    /* Initial approach: no longer used */
-    /* Discretize on angles that are multiple of dfStep so as to not */
-    /* depend on winding order. */
-    if (dfStep > 0 )
-    {
-        alpha = floor(alpha0  / dfStep) * dfStep;
-        if( alpha <= alpha0 )
-            alpha += dfStep;
-    }
-    else
-    {
-        alpha = ceil(alpha0  / dfStep) * dfStep;
-        if( alpha >= alpha0 )
-            alpha += dfStep;
-    }
-#else
-    /* Constant angle between all points, so as to not depend on winding order */
-    int nSteps = (int)(fabs((alpha1 - alpha0) / dfStep)+0.5);
+    // Constant angle between all points, so as to not depend on winding order.
+    int nSteps = static_cast<int>(fabs((alpha1 - alpha0) / dfStep) + 0.5);
     if( bStealthConstraints )
     {
-        /* We need at least 6 intermediate vertex, and if more additional */
-        /* multiples of 2 */
+        // We need at least 6 intermediate vertex, and if more additional
+        // multiples of 2.
         if( nSteps < 1+6 )
             nSteps = 1+6;
         else
             nSteps = 1+6 + 2 * ((nSteps - (1+6) + (2-1)) / 2);
     }
     else if( nSteps < 4 )
+    {
         nSteps = 4;
+    }
     dfStep = nSign * fabs((alpha1 - alpha0) / nSteps);
-    alpha = alpha0 + dfStep;
-#endif
+    double alpha = alpha0 + dfStep;
 
-    for(; (alpha - alpha1) * nSign < -1e-8; alpha += dfStep)
+    for( ; (alpha - alpha1) * nSign < -1e-8; alpha += dfStep )
     {
-        double dfX = cx + R * cos(alpha), dfY = cy + R * sin(alpha);
+        const double dfX = cx + R * cos(alpha);
+        const double dfY = cy + R * sin(alpha);
         if( bHasZ )
         {
-            double z = z0 + (z1 - z0) * (alpha - alpha0) / (alpha1 - alpha0);
+            const double z =
+                z0 + (z1 - z0) * (alpha - alpha0) / (alpha1 - alpha0);
             poLine->addPoint(dfX, dfY, z);
         }
         else
@@ -3389,29 +4621,31 @@ static void OGRGeometryFactoryStrokeArc(OGRLineString* poLine,
 /*                         OGRGF_SetHiddenValue()                       */
 /************************************************************************/
 
-#define HIDDEN_ALPHA_WIDTH        32
-#define HIDDEN_ALPHA_SCALE        (GUInt32)((((GUIntBig)1) << HIDDEN_ALPHA_WIDTH)-2)
-#define HIDDEN_ALPHA_HALF_WIDTH   (HIDDEN_ALPHA_WIDTH / 2)
-#define HIDDEN_ALPHA_HALF_MASK    ((1 << HIDDEN_ALPHA_HALF_WIDTH)-1)
+// TODO(schwehr): Cleanup these static constants.
+static const int HIDDEN_ALPHA_WIDTH = 32;
+static const GUInt32 HIDDEN_ALPHA_SCALE =
+    static_cast<GUInt32>((static_cast<GUIntBig>(1) << HIDDEN_ALPHA_WIDTH) - 2);
+static const int HIDDEN_ALPHA_HALF_WIDTH = (HIDDEN_ALPHA_WIDTH / 2);
+static const int HIDDEN_ALPHA_HALF_MASK = (1 << HIDDEN_ALPHA_HALF_WIDTH) - 1;
 
-/* Encode 16-bit nValue in the 8-lsb of dfX and dfY */
+// Encode 16-bit nValue in the 8-lsb of dfX and dfY.
 
 #ifdef CPL_LSB
-#define DOUBLE_LSB_OFFSET   0
+static const int DOUBLE_LSB_OFFSET = 0;
 #else
-#define DOUBLE_LSB_OFFSET   7
+static const int DOUBLE_LSB_OFFSET = 7;
 #endif
 
-static void OGRGF_SetHiddenValue(GUInt16 nValue, double& dfX, double &dfY)
+static void OGRGF_SetHiddenValue( GUInt16 nValue, double& dfX, double &dfY )
 {
-    GByte abyData[8];
+    GByte abyData[8] = {};
 
     memcpy(abyData, &dfX, sizeof(double));
-    abyData[DOUBLE_LSB_OFFSET] = (GByte)(nValue & 0xFF);
+    abyData[DOUBLE_LSB_OFFSET] = static_cast<GByte>(nValue & 0xFF);
     memcpy(&dfX, abyData, sizeof(double));
 
     memcpy(abyData, &dfY, sizeof(double));
-    abyData[DOUBLE_LSB_OFFSET] = (GByte)(nValue >> 8);
+    abyData[DOUBLE_LSB_OFFSET] = static_cast<GByte>(nValue >> 8);
     memcpy(&dfY, abyData, sizeof(double));
 }
 
@@ -3419,14 +4653,12 @@ static void OGRGF_SetHiddenValue(GUInt16 nValue, double& dfX, double &dfY)
 /*                         OGRGF_GetHiddenValue()                       */
 /************************************************************************/
 
-/* Decode 16-bit nValue from the 8-lsb of dfX and dfY */
-static GUInt16 OGRGF_GetHiddenValue(double dfX, double dfY)
+// Decode 16-bit nValue from the 8-lsb of dfX and dfY.
+static GUInt16 OGRGF_GetHiddenValue( double dfX, double dfY )
 {
-    GUInt16 nValue;
-
-    GByte abyData[8];
+    GByte abyData[8] = {};
     memcpy(abyData, &dfX, sizeof(double));
-    nValue = abyData[DOUBLE_LSB_OFFSET];
+    GUInt16 nValue = abyData[DOUBLE_LSB_OFFSET];
     memcpy(abyData, &dfY, sizeof(double));
     nValue |= (abyData[DOUBLE_LSB_OFFSET] << 8);
 
@@ -3437,12 +4669,12 @@ static GUInt16 OGRGF_GetHiddenValue(double dfX, double dfY)
 /*                     OGRGF_NeedSwithArcOrder()                        */
 /************************************************************************/
 
-/* We need to define a full ordering between starting point and ending point */
-/* whatever it is */
-static bool OGRGF_NeedSwithArcOrder(double x0, double y0,
-                                    double x2, double y2)
+// We need to define a full ordering between starting point and ending point
+// whatever it is.
+static bool OGRGF_NeedSwithArcOrder( double x0, double y0,
+                                     double x2, double y2 )
 {
-    return ( x0 < x2 || (x0 == x2 && y0 < y2) );
+    return x0 < x2 || (x0 == x2 && y0 < y2);
 }
 
 /************************************************************************/
@@ -3472,19 +4704,21 @@ static bool OGRGF_NeedSwithArcOrder(double x0, double y0,
  * @param y2 y of final point
  * @param z2 z of final point
  * @param bHasZ TRUE if z must be taken into account
- * @param dfMaxAngleStepSizeDegrees  the largest step in degrees along the
+ * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
  * arc, zero to use the default setting.
  * @param papszOptions options as a null-terminated list of strings or NULL.
  * Recognized options:
  * <ul>
  * <li>ADD_INTERMEDIATE_POINT=STEALTH/YES/NO (Default to STEALTH).
- *         Determine if and how the intermediate point must be output in the linestring.
- *         If set to STEALTH, no explicit intermediate point is added but its
- *         properties are encoded in low significant bits of intermediate points
- *         and OGRGeometryFactory::curveFromLineString() can decode them.
- *         This is the best compromise for round-tripping in OGR and better results
- *         with PostGIS <a href="http://postgis.org/docs/ST_LineToCurve.html">ST_LineToCurve()</a>
- *         If set to YES, the intermediate point is explicitly added to the linestring.
+ *         Determine if and how the intermediate point must be output in the
+ *         linestring.  If set to STEALTH, no explicit intermediate point is
+ *         added but its properties are encoded in low significant bits of
+ *         intermediate points and OGRGeometryFactory::curveFromLineString() can
+ *         decode them.  This is the best compromise for round-tripping in OGR
+ *         and better results with PostGIS
+ *         <a href="http://postgis.org/docs/ST_LineToCurve.html">ST_LineToCurve()</a>
+ *         If set to YES, the intermediate point is explicitly added to the
+ *         linestring.
  *         If set to NO, the intermediate point is not explicitly added.
  * </li>
  * </ul>
@@ -3495,36 +4729,47 @@ static bool OGRGF_NeedSwithArcOrder(double x0, double y0,
  */
 
 OGRLineString* OGRGeometryFactory::curveToLineString(
-                                            double x0, double y0, double z0,
-                                            double x1, double y1, double z1,
-                                            double x2, double y2, double z2,
-                                            int bHasZ,
-                                            double dfMaxAngleStepSizeDegrees,
-                                            const char*const* papszOptions )
+    double x0, double y0, double z0,
+    double x1, double y1, double z1,
+    double x2, double y2, double z2,
+    int bHasZ,
+    double dfMaxAngleStepSizeDegrees,
+    const char*const* papszOptions )
 {
-    double R, cx, cy, alpha0, alpha1, alpha2;
-
-    /* So as to make sure the same curve followed in both direction results */
-    /* in perfectly(=binary identical) symmetrical points. */
-    if( OGRGF_NeedSwithArcOrder(x0,y0,x2,y2) )
+    // So as to make sure the same curve followed in both direction results
+    // in perfectly(=binary identical) symmetrical points.
+    if( OGRGF_NeedSwithArcOrder(x0, y0, x2, y2) )
     {
-        OGRLineString* poLS = curveToLineString(x2,y2,z2,x1,y1,z1,x0,y0,z0,
-                                                bHasZ, dfMaxAngleStepSizeDegrees,
-                                                papszOptions);
+        OGRLineString* poLS =
+            curveToLineString(x2, y2, z2, x1, y1, z1, x0, y0, z0,
+                              bHasZ, dfMaxAngleStepSizeDegrees,
+                              papszOptions);
         poLS->reversePoints();
         return poLS;
     }
 
+    double R = 0.0;
+    double cx = 0.0;
+    double cy = 0.0;
+    double alpha0 = 0.0;
+    double alpha1 = 0.0;
+    double alpha2 = 0.0;
+
     OGRLineString* poLine = new OGRLineString();
     bool bIsArc = true;
     if( !GetCurveParmeters(x0, y0, x1, y1, x2, y2,
                            R, cx, cy, alpha0, alpha1, alpha2))
     {
         bIsArc = false;
-        cx = cy = R = alpha0 = alpha1 = alpha2 = 0.0;
+        cx = 0.0;
+        cy = 0.0;
+        R = 0.0;
+        alpha0 = 0.0;
+        alpha1 = 0.0;
+        alpha2 = 0.0;
     }
 
-    int nSign = (alpha1 >= alpha0) ? 1 : -1;
+    const int nSign = alpha1 >= alpha0 ? 1 : -1;
 
     // support default arc step setting.
     if( dfMaxAngleStepSizeDegrees < 1e-6 )
@@ -3532,9 +4777,8 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
         dfMaxAngleStepSizeDegrees = OGRGF_GetDefaultStepSize();
     }
 
-    double dfStep =
-        dfMaxAngleStepSizeDegrees / 180 * M_PI;
-    if (dfStep <= 0.01 / 180 * M_PI)
+    double dfStep = dfMaxAngleStepSizeDegrees / 180 * M_PI;
+    if( dfStep <= 0.01 / 180 * M_PI )
     {
         CPLDebug("OGR", "Too small arc step size: limiting to 0.01 degree.");
         dfStep = 0.01 / 180 * M_PI;
@@ -3548,32 +4792,36 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
         poLine->addPoint(x0, y0);
 
     bool bAddIntermediatePoint = false;
-    int bStealth = TRUE;
-    for(const char* const* papszIter = papszOptions; papszIter && *papszIter; papszIter++)
+    bool bStealth = true;
+    for( const char* const* papszIter = papszOptions;
+         papszIter && *papszIter;
+         papszIter++ )
     {
         char* pszKey = NULL;
         const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
         if( pszKey != NULL && EQUAL(pszKey, "ADD_INTERMEDIATE_POINT") )
         {
-            if( EQUAL(pszValue, "YES") || EQUAL(pszValue, "TRUE") || EQUAL(pszValue, "ON") )
+            if( EQUAL(pszValue, "YES") || EQUAL(pszValue, "TRUE") ||
+                EQUAL(pszValue, "ON") )
             {
                 bAddIntermediatePoint = true;
-                bStealth = FALSE;
+                bStealth = false;
             }
-            else if( EQUAL(pszValue, "NO") || EQUAL(pszValue, "FALSE") || EQUAL(pszValue, "OFF") )
+            else if( EQUAL(pszValue, "NO") || EQUAL(pszValue, "FALSE") ||
+                     EQUAL(pszValue, "OFF") )
             {
                 bAddIntermediatePoint = false;
-                bStealth = FALSE;
+                bStealth = false;
             }
             else if( EQUAL(pszValue, "STEALTH") )
             {
-                /* default */
+                // default.
             }
         }
         else
         {
             CPLError(CE_Warning, CPLE_NotSupported, "Unsupported option: %s",
-                        *papszIter);
+                     *papszIter);
         }
         CPLFree(pszKey);
     }
@@ -3604,27 +4852,30 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
 
         if( bStealth && poLine->getNumPoints() > 6 )
         {
-            /* 'Hide' the angle of the intermediate point in the 8 low-significant */
-            /* bits of the x,y of the first 2 computed points (so 32 bits), */
-            /* then put 0xFF, and on the last couple points put again the */
-            /* angle but in reverse order, so that overall the low-significant bits */
-            /* of all the points are symmetrical w.r.t the mid-point */
-            double dfRatio = (alpha1 - alpha0) / (alpha2 - alpha0);
-            GUInt32 nAlphaRatio = (GUInt32)(0.5 + HIDDEN_ALPHA_SCALE * dfRatio);
-            GUInt16 nAlphaRatioLow = nAlphaRatio & HIDDEN_ALPHA_HALF_MASK;
-            GUInt16 nAlphaRatioHigh = nAlphaRatio >> HIDDEN_ALPHA_HALF_WIDTH;
-            /*printf("alpha0=%f, alpha1=%f, alpha2=%f, dfRatio=%f, nAlphaRatio = %u\n",
-                   alpha0, alpha1, alpha2, dfRatio, nAlphaRatio);*/
+            // 'Hide' the angle of the intermediate point in the 8
+            // low-significant bits of the x, y of the first 2 computed points
+            // (so 32 bits), then put 0xFF, and on the last couple points put
+            // again the angle but in reverse order, so that overall the
+            // low-significant bits of all the points are symmetrical w.r.t the
+            // mid-point.
+            const double dfRatio = (alpha1 - alpha0) / (alpha2 - alpha0);
+            const GUInt32 nAlphaRatio =
+                static_cast<GUInt32>(0.5 + HIDDEN_ALPHA_SCALE * dfRatio);
+            const GUInt16 nAlphaRatioLow = nAlphaRatio & HIDDEN_ALPHA_HALF_MASK;
+            const GUInt16 nAlphaRatioHigh =
+                nAlphaRatio >> HIDDEN_ALPHA_HALF_WIDTH;
+            // printf("alpha0=%f, alpha1=%f, alpha2=%f, dfRatio=%f, "/*ok*/
+            //        "nAlphaRatio = %u\n",
+            //        alpha0, alpha1, alpha2, dfRatio, nAlphaRatio);
 
             CPLAssert( ((poLine->getNumPoints()-1 - 6) % 2) == 0 );
 
-            for(int i=1;i+1<poLine->getNumPoints();i+=2)
+            for( int i = 1; i + 1 < poLine->getNumPoints(); i += 2 )
             {
-                double dfX, dfY;
                 GUInt16 nVal = 0xFFFF;
 
-                dfX = poLine->getX(i);
-                dfY = poLine->getY(i);
+                double dfX = poLine->getX(i);
+                double dfY = poLine->getY(i);
                 if( i == 1 )
                     nVal = nAlphaRatioLow;
                 else if( i == poLine->getNumPoints() - 2 )
@@ -3656,9 +4907,10 @@ OGRLineString* OGRGeometryFactory::curveToLineString(
 /*                         OGRGF_FixAngle()                             */
 /************************************************************************/
 
-/* Fix dfAngle by offsets of 2 PI so that it lies between dfAngleStart and */
-/* dfAngleStop, whatever their respective order. */
-static double OGRGF_FixAngle(double dfAngleStart, double dfAngleStop, double dfAngle)
+// Fix dfAngle by offsets of 2 PI so that it lies between dfAngleStart and
+// dfAngleStop, whatever their respective order.
+static double OGRGF_FixAngle( double dfAngleStart, double dfAngleStop,
+                              double dfAngle )
 {
     if( dfAngleStart < dfAngleStop )
     {
@@ -3679,59 +4931,72 @@ static double OGRGF_FixAngle(double dfAngleStart, double dfAngleStop, double dfA
 
 //#define VERBOSE_DEBUG_CURVEFROMLINESTRING
 
-static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
-                           OGRCompoundCurve*& poCC,
-                           OGRCircularString*& poCS,
-                           OGRLineString*& poLSNew)
+static inline bool IS_ALMOST_INTEGER(double x)
+{
+    const double val = fabs(x - floor(x + 0.5));
+    return val < 1.0e-8;
+}
+
+static int OGRGF_DetectArc( const OGRLineString* poLS, int i,
+                            OGRCompoundCurve*& poCC,
+                            OGRCircularString*& poCS,
+                            OGRLineString*& poLSNew )
 {
-    OGRPoint p0, p1, p2, p3;
     if( i + 3 >= poLS->getNumPoints() )
         return -1;
 
+    OGRPoint p0;
+    OGRPoint p1;
+    OGRPoint p2;
     poLS->getPoint(i, &p0);
     poLS->getPoint(i+1, &p1);
     poLS->getPoint(i+2, &p2);
-    double R_1, cx_1, cy_1, alpha0_1, alpha1_1, alpha2_1;
+    double R_1 = 0.0;
+    double cx_1 = 0.0;
+    double cy_1 = 0.0;
+    double alpha0_1 = 0.0;
+    double alpha1_1 = 0.0;
+    double alpha2_1 = 0.0;
     if( !(OGRGeometryFactory::GetCurveParmeters(p0.getX(), p0.getY(),
                             p1.getX(), p1.getY(),
                             p2.getX(), p2.getY(),
                             R_1, cx_1, cy_1,
                             alpha0_1, alpha1_1, alpha2_1) &&
-          fabs(alpha2_1 - alpha0_1) < 2 * 20.0 / 180.0 * M_PI) )
+          fabs(alpha2_1 - alpha0_1) < 2.0 * 20.0 / 180.0 * M_PI) )
     {
         return -1;
     }
 
-    int j;
-    double dfDeltaAlpha10 = alpha1_1 - alpha0_1;
-    double dfDeltaAlpha21 = alpha2_1 - alpha1_1;
-    double dfMaxDeltaAlpha = MAX(fabs(dfDeltaAlpha10),
-                                    fabs(dfDeltaAlpha21));
+    const double dfDeltaAlpha10 = alpha1_1 - alpha0_1;
+    const double dfDeltaAlpha21 = alpha2_1 - alpha1_1;
+    const double dfMaxDeltaAlpha = std::max(fabs(dfDeltaAlpha10),
+                                            fabs(dfDeltaAlpha21));
     GUInt32 nAlphaRatioRef =
-            OGRGF_GetHiddenValue(p1.getX(), p1.getY()) |
+        OGRGF_GetHiddenValue(p1.getX(), p1.getY()) |
         (OGRGF_GetHiddenValue(p2.getX(), p2.getY()) << HIDDEN_ALPHA_HALF_WIDTH);
     bool bFoundFFFFFFFFPattern = false;
     bool bFoundReversedAlphaRatioRef = false;
-    int bValidAlphaRatio = (nAlphaRatioRef > 0 && nAlphaRatioRef < 0xFFFFFFFF);
+    bool bValidAlphaRatio = nAlphaRatioRef > 0 && nAlphaRatioRef < 0xFFFFFFFF;
     int nCountValidAlphaRatio = 1;
 
-    double dfScale = MAX(1, R_1);
-    dfScale = MAX(dfScale, fabs(cx_1));
-    dfScale = MAX(dfScale, fabs(cy_1));
+    double dfScale = std::max(1.0, R_1);
+    dfScale = std::max(dfScale, fabs(cx_1));
+    dfScale = std::max(dfScale, fabs(cy_1));
     dfScale = pow(10.0, ceil(log10(dfScale)));
-    double dfInvScale  = 1.0 / dfScale ;
+    const double dfInvScale = 1.0 / dfScale;
 
-    int bInitialConstantStep =
-        (fabs(dfDeltaAlpha10 - dfDeltaAlpha21) / dfMaxDeltaAlpha) < 1e-4;
-    double dfDeltaEpsilon = ( bInitialConstantStep ) ?
+    const int bInitialConstantStep =
+        (fabs(dfDeltaAlpha10 - dfDeltaAlpha21) / dfMaxDeltaAlpha) < 1.0e-4;
+    const double dfDeltaEpsilon = bInitialConstantStep ?
         dfMaxDeltaAlpha * 1e-4 : dfMaxDeltaAlpha/10;
+
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-    printf("----------------------------\n");
-    printf("Curve beginning at offset i = %d\n", i);
-    printf("Initial alpha ratio = %u\n", nAlphaRatioRef);
-    printf("Initial R = %.16g, cx = %.16g, cy = %.16g\n", R_1, cx_1, cy_1);
-    printf("dfScale = %f\n", dfScale);
-    printf("bInitialConstantStep = %d, "
+    printf("----------------------------\n");/*ok*/
+    printf("Curve beginning at offset i = %d\n", i);/*ok*/
+    printf("Initial alpha ratio = %u\n", nAlphaRatioRef);/*ok*/
+    printf("Initial R = %.16g, cx = %.16g, cy = %.16g\n", R_1, cx_1, cy_1);/*ok*/
+    printf("dfScale = %f\n", dfScale);/*ok*/
+    printf("bInitialConstantStep = %d, "/*ok*/
             "fabs(dfDeltaAlpha10 - dfDeltaAlpha21)=%.8g, "
             "dfMaxDeltaAlpha = %.8f, "
             "dfDeltaEpsilon = %.8f (%.8f)\n",
@@ -3745,14 +5010,21 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
 
     double dfLastLogRelDiff = 0;
 
-    for(j = i + 1; j + 2 < poLS->getNumPoints(); j++ )
+    OGRPoint p3;
+    int j = i + 1;  // Used after for.
+    for( ; j + 2 < poLS->getNumPoints(); j++ )
     {
         poLS->getPoint(j, &p1);
         poLS->getPoint(j+1, &p2);
         poLS->getPoint(j+2, &p3);
-        double R_2, cx_2, cy_2, alpha0_2, alpha1_2, alpha2_2;
-        /* Check that the new candidate arc shares the same */
-        /* radius, center and winding order */
+        double R_2 = 0.0;
+        double cx_2 = 0.0;
+        double cy_2 = 0.0;
+        double alpha0_2 = 0.0;
+        double alpha1_2 = 0.0;
+        double alpha2_2 = 0.0;
+        // Check that the new candidate arc shares the same
+        // radius, center and winding order.
         if( !(OGRGeometryFactory::GetCurveParmeters(p1.getX(), p1.getY(),
                                 p2.getX(), p2.getY(),
                                 p3.getX(), p3.getY(),
@@ -3760,45 +5032,48 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
                                 alpha0_2, alpha1_2, alpha2_2)) )
         {
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-            printf("End of curve at j=%d\n : straight line", j);
+            printf("End of curve at j=%d\n : straight line", j);/*ok*/
 #endif
             break;
         }
 
-        double dfRelDiffR = fabs(R_1 - R_2) * dfInvScale;
-        double dfRelDiffCx = fabs(cx_1 - cx_2) * dfInvScale;
-        double dfRelDiffCy = fabs(cy_1 - cy_2) * dfInvScale;
+        const double dfRelDiffR = fabs(R_1 - R_2) * dfInvScale;
+        const double dfRelDiffCx = fabs(cx_1 - cx_2) * dfInvScale;
+        const double dfRelDiffCy = fabs(cy_1 - cy_2) * dfInvScale;
+
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-        printf("j=%d: R = %.16g, cx = %.16g, cy = %.16g, "
-                "rel_diff_R=%.8g rel_diff_cx=%.8g rel_diff_cy=%.8g\n",
-                j, R_2, cx_2, cy_2, dfRelDiffR, dfRelDiffCx, dfRelDiffCy);
+        printf("j=%d: R = %.16g, cx = %.16g, cy = %.16g, "/*ok*/
+               "rel_diff_R=%.8g rel_diff_cx=%.8g rel_diff_cy=%.8g\n",
+               j, R_2, cx_2, cy_2, dfRelDiffR, dfRelDiffCx, dfRelDiffCy);
 #endif
 
-        if( //(dfRelDiffR > 1e-8 || dfRelDiffCx > 1e-8 || dfRelDiffCy > 1e-8) ||
-            (dfRelDiffR > 1e-6 && dfRelDiffCx > 1e-6 && dfRelDiffCy > 1e-6) ||
-            dfDeltaAlpha10 * (alpha1_2 - alpha0_2) < 0 )
+        if( (dfRelDiffR > 1.0e-6 &&
+             dfRelDiffCx > 1.0e-6 &&
+             dfRelDiffCy > 1.0e-6) ||
+            dfDeltaAlpha10 * (alpha1_2 - alpha0_2) < 0.0 )
         {
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-            printf("End of curve at j=%d\n", j);
+            printf("End of curve at j=%d\n", j);/*ok*/
 #endif
             break;
         }
 
-        if( dfRelDiffR > 0 && dfRelDiffCx > 0 && dfRelDiffCy > 0 )
+        if( dfRelDiffR > 0.0 && dfRelDiffCx > 0.0 && dfRelDiffCy > 0.0 )
         {
-            double dfLogRelDiff = MIN(MIN(fabs(log10(dfRelDiffR)),
-                                          fabs(log10(dfRelDiffCx))),
-                                      fabs(log10(dfRelDiffCy)));
-            /*printf("dfLogRelDiff = %f, dfLastLogRelDiff=%f, "
-                     "dfLogRelDiff - dfLastLogRelDiff=%f\n",
-                     dfLogRelDiff, dfLastLogRelDiff,
-                     dfLogRelDiff - dfLastLogRelDiff);*/
-            if( dfLogRelDiff > 0 && dfLastLogRelDiff > 0 &&
-                dfLastLogRelDiff >= 8 && dfLogRelDiff <= 8 &&
-                dfLogRelDiff < dfLastLogRelDiff - 2 )
+            const double dfLogRelDiff =
+                std::min(std::min(fabs(log10(dfRelDiffR)),
+                                  fabs(log10(dfRelDiffCx))),
+                         fabs(log10(dfRelDiffCy)));
+            // printf("dfLogRelDiff = %f, dfLastLogRelDiff=%f, "/*ok*/
+            //        "dfLogRelDiff - dfLastLogRelDiff=%f\n",
+            //         dfLogRelDiff, dfLastLogRelDiff,
+            //         dfLogRelDiff - dfLastLogRelDiff);
+            if( dfLogRelDiff > 0.0 && dfLastLogRelDiff > 0.0 &&
+                dfLastLogRelDiff >= 8.0 && dfLogRelDiff <= 8.0 &&
+                dfLogRelDiff < dfLastLogRelDiff - 2.0 )
             {
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                printf("End of curve at j=%d. Significant different in "
+                printf("End of curve at j=%d. Significant different in "/*ok*/
                        "relative error w.r.t previous points\n", j);
 #endif
                 break;
@@ -3806,43 +5081,45 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
             dfLastLogRelDiff = dfLogRelDiff;
         }
 
-        double dfStep10 = fabs(alpha1_2 - alpha0_2);
-        double dfStep21 = fabs(alpha2_2 - alpha1_2);
-        /* Check that the angle step is consistent with the original */
-        /* step. */
-        if( !(dfStep10 < 2 * dfMaxDeltaAlpha && dfStep21 < 2 * dfMaxDeltaAlpha) )
+        const double dfStep10 = fabs(alpha1_2 - alpha0_2);
+        const double dfStep21 = fabs(alpha2_2 - alpha1_2);
+        // Check that the angle step is consistent with the original step.
+        if( !(dfStep10 < 2.0 * dfMaxDeltaAlpha &&
+              dfStep21 < 2.0 * dfMaxDeltaAlpha) )
         {
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-            printf("End of curve at j=%d: dfStep10=%f, dfStep21=%f, 2*dfMaxDeltaAlpha=%f\n",
-                    j, dfStep10, dfStep21, 2 * dfMaxDeltaAlpha);
+            printf("End of curve at j=%d: dfStep10=%f, dfStep21=%f, "/*ok*/
+                   "2*dfMaxDeltaAlpha=%f\n",
+                   j, dfStep10, dfStep21, 2 * dfMaxDeltaAlpha);
 #endif
             break;
         }
 
         if( bValidAlphaRatio && j > i + 1 && (i % 2) != (j % 2 ) )
         {
-            GUInt32 nAlphaRatioReversed =
-                (OGRGF_GetHiddenValue(p1.getX(), p1.getY()) << HIDDEN_ALPHA_HALF_WIDTH) |
+            const GUInt32 nAlphaRatioReversed =
+                (OGRGF_GetHiddenValue(p1.getX(),
+                                      p1.getY()) << HIDDEN_ALPHA_HALF_WIDTH) |
                 (OGRGF_GetHiddenValue(p2.getX(), p2.getY()));
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-            printf("j=%d, nAlphaRatioReversed = %u\n",
-                        j, nAlphaRatioReversed);
+            printf("j=%d, nAlphaRatioReversed = %u\n",/*ok*/
+                   j, nAlphaRatioReversed);
 #endif
             if( !bFoundFFFFFFFFPattern && nAlphaRatioReversed == 0xFFFFFFFF )
             {
                 bFoundFFFFFFFFPattern = true;
-                nCountValidAlphaRatio ++;
+                nCountValidAlphaRatio++;
             }
             else if( bFoundFFFFFFFFPattern && !bFoundReversedAlphaRatioRef &&
                         nAlphaRatioReversed == 0xFFFFFFFF )
             {
-                nCountValidAlphaRatio ++;
+                nCountValidAlphaRatio++;
             }
             else if( bFoundFFFFFFFFPattern && !bFoundReversedAlphaRatioRef &&
                         nAlphaRatioReversed == nAlphaRatioRef )
             {
                 bFoundReversedAlphaRatioRef = true;
-                nCountValidAlphaRatio ++;
+                nCountValidAlphaRatio++;
             }
             else
             {
@@ -3851,34 +5128,36 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
                     nCountValidAlphaRatio > 10 )
                 {
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                    printf("End of curve at j=%d: "
-                            "fabs(dfLastValidAlpha - alpha0_1)=%f, "
-                            "nCountValidAlphaRatio=%d\n",
-                            j,
-                            fabs(dfLastValidAlpha - alpha0_1),
-                            nCountValidAlphaRatio);
+                    printf("End of curve at j=%d: "/*ok*/
+                           "fabs(dfLastValidAlpha - alpha0_1)=%f, "
+                           "nCountValidAlphaRatio=%d\n",
+                           j,
+                           fabs(dfLastValidAlpha - alpha0_1),
+                           nCountValidAlphaRatio);
 #endif
                     if( dfLastValidAlpha - alpha0_1 > 0 )
                     {
-                        while( dfLastValidAlpha - alpha0_1 - dfMaxDeltaAlpha - M_PI > -dfMaxDeltaAlpha/10 )
+                        while( dfLastValidAlpha - alpha0_1 - dfMaxDeltaAlpha -
+                               M_PI > -dfMaxDeltaAlpha/10 )
                         {
                             dfLastValidAlpha -= dfMaxDeltaAlpha;
-                            j --;
+                            j--;
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                            printf( "--> corrected as fabs(dfLastValidAlpha - "
-                                    "alpha0_1)=%f, j=%d\n",
-                                    fabs(dfLastValidAlpha - alpha0_1), j);
+                            printf("--> corrected as fabs(dfLastValidAlpha - "/*ok*/
+                                   "alpha0_1)=%f, j=%d\n",
+                                   fabs(dfLastValidAlpha - alpha0_1), j);
 #endif
                         }
                     }
                     else
                     {
-                        while( dfLastValidAlpha - alpha0_1 + dfMaxDeltaAlpha + M_PI < dfMaxDeltaAlpha/10 )
+                        while( dfLastValidAlpha - alpha0_1 + dfMaxDeltaAlpha +
+                               M_PI < dfMaxDeltaAlpha/10 )
                         {
                             dfLastValidAlpha += dfMaxDeltaAlpha;
-                            j --;
+                            j--;
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                            printf( "--> corrected as fabs(dfLastValidAlpha - "
+                            printf( "--> corrected as fabs(dfLastValidAlpha - "/*ok*/
                                     "alpha0_1)=%f, j=%d\n",
                                     fabs(dfLastValidAlpha - alpha0_1), j);
 #endif
@@ -3889,26 +5168,28 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
                 }
 
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                printf( "j=%d, nAlphaRatioReversed = %u --> inconsistent "
+                printf( "j=%d, nAlphaRatioReversed = %u --> inconsistent "/*ok*/
                         "values across arc. Don't use it\n",
                         j, nAlphaRatioReversed);
 #endif
-                bValidAlphaRatio = FALSE;
+                bValidAlphaRatio = false;
             }
         }
 
-        /* Correct current end angle, consistently with start angle */
+        // Correct current end angle, consistently with start angle.
         dfLastValidAlpha = OGRGF_FixAngle(alpha0_1, alpha1_1, alpha2_2);
 
-        /* Try to detect the precise intermediate point of the */
-        /* arc circle by detecting irregular angle step */
-        /* This is OK if we don't detect the right point or fail */
-        /* to detect it */
+        // Try to detect the precise intermediate point of the
+        // arc circle by detecting irregular angle step
+        // This is OK if we don't detect the right point or fail
+        // to detect it.
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-        printf("j=%d A(0,1)-maxDelta=%.8f A(1,2)-maxDelta=%.8f "
-                "x1=%.8f y1=%.8f x2=%.8f y2=%.8f x3=%.8f y3=%.8f\n",
-                j, fabs(dfStep10 - dfMaxDeltaAlpha), fabs(dfStep21 - dfMaxDeltaAlpha),
-                p1.getX(), p1.getY(), p2.getX(), p2.getY(), p3.getX(), p3.getY());
+        printf("j=%d A(0,1)-maxDelta=%.8f A(1,2)-maxDelta=%.8f "/*ok*/
+               "x1=%.8f y1=%.8f x2=%.8f y2=%.8f x3=%.8f y3=%.8f\n",
+               j, fabs(dfStep10 - dfMaxDeltaAlpha),
+               fabs(dfStep21 - dfMaxDeltaAlpha),
+               p1.getX(), p1.getY(), p2.getX(), p2.getY(),
+               p3.getX(), p3.getY());
 #endif
         if( j > i + 1 && iMidPoint < 0 && dfDeltaEpsilon < 1.0 / 180.0 * M_PI )
         {
@@ -3921,34 +5202,41 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
             {
                 OGRPoint pMid;
                 poLS->getPoint(iMidPoint, &pMid);
-                printf("Midpoint detected at j = %d, iMidPoint = %d, x=%.8f y=%.8f\n",
-                        j, iMidPoint, pMid.getX(), pMid.getY());
+                printf("Midpoint detected at j = %d, iMidPoint = %d, "/*ok*/
+                       "x=%.8f y=%.8f\n",
+                       j, iMidPoint, pMid.getX(), pMid.getY());
             }
 #endif
         }
     }
 
-    /* Take a minimum threshold of consecutive points */
-    /* on the arc to avoid false positives */
+    // Take a minimum threshold of consecutive points
+    // on the arc to avoid false positives.
     if( j < i + 3 )
         return -1;
 
-    bValidAlphaRatio &= (bFoundFFFFFFFFPattern && bFoundReversedAlphaRatioRef );
+    bValidAlphaRatio &= bFoundFFFFFFFFPattern && bFoundReversedAlphaRatioRef;
 
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-    printf("bValidAlphaRatio=%d bFoundFFFFFFFFPattern=%d, bFoundReversedAlphaRatioRef=%d\n",
-            bValidAlphaRatio, bFoundFFFFFFFFPattern, bFoundReversedAlphaRatioRef);
-    printf("alpha0_1=%f dfLastValidAlpha=%f\n",
+    printf("bValidAlphaRatio=%d bFoundFFFFFFFFPattern=%d, "/*ok*/
+           "bFoundReversedAlphaRatioRef=%d\n",
+           static_cast<int>(bValidAlphaRatio),
+           static_cast<int>(bFoundFFFFFFFFPattern),
+           static_cast<int>(bFoundReversedAlphaRatioRef));
+    printf("alpha0_1=%f dfLastValidAlpha=%f\n",/*ok*/
             alpha0_1, dfLastValidAlpha);
 #endif
 
     if( poLSNew != NULL )
     {
-        double dfScale2 = MAX(1, fabs(p0.getX()));
-        dfScale2 = MAX(dfScale2, fabs(p0.getY()));
-        /* Not strictly necessary, but helps having 'clean' lines without duplicated points */
-        if( fabs(poLSNew->getX(poLSNew->getNumPoints()-1) - p0.getX()) / dfScale2 > 1e-8 ||
-            fabs(poLSNew->getY(poLSNew->getNumPoints()-1) - p0.getY()) / dfScale2 > 1e-8 )
+        double dfScale2 = std::max(1.0, fabs(p0.getX()));
+        dfScale2 = std::max(dfScale2, fabs(p0.getY()));
+        // Not strictly necessary, but helps having 'clean' lines without
+        // duplicated points.
+        if( fabs(poLSNew->getX(poLSNew->getNumPoints()-1) -
+                 p0.getX()) / dfScale2 > 1.0e-8 ||
+            fabs(poLSNew->getY(poLSNew->getNumPoints()-1) -
+                 p0.getY()) / dfScale2 > 1.0e-8 )
             poLSNew->addPoint(&p0);
         if( poLSNew->getNumPoints() >= 2 )
         {
@@ -3970,19 +5258,21 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
     OGRPoint* poFinalPoint =
             ( j + 2 >= poLS->getNumPoints() ) ? &p3 : &p2;
 
-    double dfXMid = 0.0, dfYMid = 0.0, dfZMid = 0.0;
+    double dfXMid = 0.0;
+    double dfYMid = 0.0;
+    double dfZMid = 0.0;
     if( bValidAlphaRatio )
     {
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-        printf("Using alpha ratio...\n");
+        printf("Using alpha ratio...\n");/*ok*/
 #endif
-        double dfAlphaMid;
-        if( OGRGF_NeedSwithArcOrder(p0.getX(),p0.getY(),
+        double dfAlphaMid = 0.0;
+        if( OGRGF_NeedSwithArcOrder(p0.getX(), p0.getY(),
                                     poFinalPoint->getX(),
                                     poFinalPoint->getY()) )
         {
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-            printf("Switching angles\n");
+            printf("Switching angles\n");/*ok*/
 #endif
             dfAlphaMid = dfLastValidAlpha + nAlphaRatioRef *
                     (alpha0_1 - dfLastValidAlpha) / HIDDEN_ALPHA_SCALE;
@@ -3997,23 +5287,23 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
         dfXMid = cx_1 + R_1 * cos(dfAlphaMid);
         dfYMid = cy_1 + R_1 * sin(dfAlphaMid);
 
-#define IS_ALMOST_INTEGER(x)  ((fabs((x)-floor((x)+0.5)))<1e-8)
-
         if( poLS->getCoordinateDimension() == 3 )
         {
             double dfLastAlpha = 0.0;
             double dfLastZ = 0.0;
-            int k;
-            for( k = i; k < j+2; k++ )
+            int k = i;  // Used after for.
+            for( ; k < j+2; k++ )
             {
                 OGRPoint p;
                 poLS->getPoint(k, &p);
                 double dfAlpha = atan2(p.getY() - cy_1, p.getX() - cx_1);
                 dfAlpha = OGRGF_FixAngle(alpha0_1, dfLastValidAlpha, dfAlpha);
-                if( k > i && ((dfAlpha < dfLastValidAlpha && dfAlphaMid < dfAlpha) ||
-                              (dfAlpha > dfLastValidAlpha && dfAlphaMid > dfAlpha)) )
+                if( k > i &&
+                    ((dfAlpha < dfLastValidAlpha && dfAlphaMid < dfAlpha) ||
+                     (dfAlpha > dfLastValidAlpha && dfAlphaMid > dfAlpha)) )
                 {
-                    double dfRatio = ( dfAlphaMid - dfLastAlpha ) / ( dfAlpha - dfLastAlpha );
+                    const double dfRatio =
+                        (dfAlphaMid - dfLastAlpha) / (dfAlpha - dfLastAlpha);
                     dfZMid = (1 - dfRatio) * dfLastZ + dfRatio * p.getZ();
                     break;
                 }
@@ -4023,62 +5313,75 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
             if( k == j + 2 )
                 dfZMid = dfLastZ;
             if( IS_ALMOST_INTEGER(dfZMid) )
-                dfZMid = (int)floor(dfZMid+0.5);
+                dfZMid = static_cast<int>(floor(dfZMid + 0.5));
         }
 
-        /* A few rounding strategies in case the mid point was at "exact" coordinates */
+        // A few rounding strategies in case the mid point was at "exact"
+        // coordinates.
         if( R_1 > 1e-5 )
         {
-            int bStartEndInteger = ( IS_ALMOST_INTEGER(p0.getX()) &&
-                                     IS_ALMOST_INTEGER(p0.getY()) &&
-                                     IS_ALMOST_INTEGER(poFinalPoint->getX()) &&
-                                     IS_ALMOST_INTEGER(poFinalPoint->getY()) );
+            const bool bStartEndInteger =
+                IS_ALMOST_INTEGER(p0.getX()) &&
+                IS_ALMOST_INTEGER(p0.getY()) &&
+                IS_ALMOST_INTEGER(poFinalPoint->getX()) &&
+                IS_ALMOST_INTEGER(poFinalPoint->getY());
             if( bStartEndInteger &&
-                fabs(dfXMid - floor(dfXMid+0.5)) / dfScale < 1e-4 &&
-                fabs(dfYMid - floor(dfYMid+0.5)) / dfScale < 1e-4 )
+                fabs(dfXMid - floor(dfXMid + 0.5)) / dfScale < 1e-4 &&
+                fabs(dfYMid - floor(dfYMid + 0.5)) / dfScale < 1e-4 )
             {
-                dfXMid = (int)floor(dfXMid+0.5);
-                dfYMid = (int)floor(dfYMid+0.5);
+                dfXMid = static_cast<int>(floor(dfXMid + 0.5));
+                dfYMid = static_cast<int>(floor(dfYMid + 0.5));
                 // Sometimes rounding to closest is not best approach
                 // Try neighbouring integers to look for the one that
                 // minimize the error w.r.t to the arc center
                 // But only do that if the radius is greater than
-                // the magnitude of the delta that we will try !
-                double dfBestRError = fabs(R_1 - DISTANCE(dfXMid,dfYMid,cx_1,cy_1));
-                int iBestX = 0, iBestY = 0;
+                // the magnitude of the delta that we will try!
+                double dfBestRError =
+                    fabs(R_1 - DISTANCE(dfXMid, dfYMid, cx_1, cy_1));
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                printf("initial_error=%f\n", dfBestRError);
+                printf("initial_error=%f\n", dfBestRError);/*ok*/
 #endif
+                int iBestX = 0;
+                int iBestY = 0;
                 if( dfBestRError > 0.001 && R_1 > 2 )
                 {
                     int nSearchRadius = 1;
                     // Extend the search radius if the arc circle radius
-                    // is much higher than the coordinate values
-                    double dfMaxCoords = MAX(fabs(p0.getX()), fabs(p0.getY()));
-                    dfMaxCoords = MAX(dfMaxCoords, poFinalPoint->getX());
-                    dfMaxCoords = MAX(dfMaxCoords, poFinalPoint->getY());
-                    dfMaxCoords = MAX(dfMaxCoords, dfXMid);
-                    dfMaxCoords = MAX(dfMaxCoords, dfYMid);
+                    // is much higher than the coordinate values.
+                    double dfMaxCoords =
+                        std::max(fabs(p0.getX()), fabs(p0.getY()));
+                    dfMaxCoords = std::max(dfMaxCoords, poFinalPoint->getX());
+                    dfMaxCoords = std::max(dfMaxCoords, poFinalPoint->getY());
+                    dfMaxCoords = std::max(dfMaxCoords, dfXMid);
+                    dfMaxCoords = std::max(dfMaxCoords, dfYMid);
                     if( R_1 > dfMaxCoords * 1000 )
                         nSearchRadius = 100;
                     else if( R_1 > dfMaxCoords * 10 )
                         nSearchRadius = 10;
-                    for(int iY=-nSearchRadius;iY<=nSearchRadius;iY++)
+                    for( int iY = -nSearchRadius; iY <= nSearchRadius; iY++ )
                     {
-                        for(int iX=-nSearchRadius;iX<=nSearchRadius;iX ++)
+                        for( int iX = -nSearchRadius;
+                             iX <= nSearchRadius;
+                             iX++ )
                         {
-                            double dfCandidateX = dfXMid+iX;
-                            double dfCandidateY = dfYMid+iY;
+                            const double dfCandidateX = dfXMid+iX;
+                            const double dfCandidateY = dfYMid+iY;
                             if( fabs(dfCandidateX - p0.getX()) < 1e-8 &&
                                 fabs(dfCandidateY - p0.getY()) < 1e-8 )
                                 continue;
-                            if( fabs(dfCandidateX - poFinalPoint->getX()) < 1e-8 &&
-                                fabs(dfCandidateY - poFinalPoint->getY()) < 1e-8 )
+                            if( fabs(dfCandidateX -
+                                     poFinalPoint->getX()) < 1e-8 &&
+                                fabs(dfCandidateY -
+                                     poFinalPoint->getY()) < 1e-8 )
                                 continue;
-                            double dfRError = fabs(R_1 - DISTANCE(dfCandidateX,dfCandidateY,cx_1,cy_1));
+                            const double dfRError =
+                                fabs(R_1 - DISTANCE(dfCandidateX, dfCandidateY,
+                                                    cx_1, cy_1));
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-                            printf("x=%d y=%d error=%f besterror=%f\n",
-                                    (int)(dfXMid+iX),(int)(dfYMid+iY),dfRError,dfBestRError);
+                            printf("x=%d y=%d error=%f besterror=%f\n",/*ok*/
+                                   static_cast<int>(dfXMid + iX),
+                                   static_cast<int>(dfYMid + iY),
+                                   dfRError, dfBestRError);
 #endif
                             if( dfRError < dfBestRError )
                             {
@@ -4094,30 +5397,34 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
             }
             else
             {
-                /* Limit the number of significant figures in decimal representation */
-                if( fabs(dfXMid) < 100000000 )
+                // Limit the number of significant figures in decimal
+                // representation.
+                if( fabs(dfXMid) < 100000000.0 )
                 {
-                    dfXMid = ((GIntBig)floor(dfXMid * 100000000+0.5)) / 100000000.0;
+                    dfXMid =
+                        ((GIntBig)floor(dfXMid * 100000000+0.5)) / 100000000.0;
                 }
-                if( fabs(dfYMid) < 100000000 )
+                if( fabs(dfYMid) < 100000000.0 )
                 {
-                    dfYMid = ((GIntBig)floor(dfYMid * 100000000+0.5)) / 100000000.0;
+                    dfYMid =
+                        ((GIntBig)floor(dfYMid * 100000000+0.5)) / 100000000.0;
                 }
             }
         }
 
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-        printf("dfAlphaMid=%f, x_mid = %f, y_mid = %f\n", dfLastValidAlpha, dfXMid, dfYMid);
+        printf("dfAlphaMid=%f, x_mid = %f, y_mid = %f\n",/*ok*/
+               dfLastValidAlpha, dfXMid, dfYMid);
 #endif
     }
 
-    /* If this is a full circle of a non-polygonal zone, we must */
-    /* use a 5-point representation to keep the winding order */
+    // If this is a full circle of a non-polygonal zone, we must
+    // use a 5-point representation to keep the winding order.
     if( p0.Equals(poFinalPoint) &&
         !EQUAL(poLS->getGeometryName(), "LINEARRING") )
     {
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-        printf("Full circle of a non-polygonal zone\n");
+        printf("Full circle of a non-polygonal zone\n");/*ok*/
 #endif
         poLS->getPoint((i + j + 2) / 4, &p1);
         poCS->addPoint(&p1);
@@ -4146,31 +5453,32 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
         poCS->addPoint(&p1);
     }
 
-    /* If we have found a candidate for a precise intermediate */
-    /* point, use it */
+    // If we have found a candidate for a precise intermediate
+    // point, use it.
     else if( iMidPoint >= 1 && iMidPoint < j )
     {
         poLS->getPoint(iMidPoint, &p1);
         poCS->addPoint(&p1);
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-        printf("Using detected midpoint...\n");
-        printf("x_mid = %f, y_mid = %f\n", p1.getX(), p1.getY());
+        printf("Using detected midpoint...\n");/*ok*/
+        printf("x_mid = %f, y_mid = %f\n", p1.getX(), p1.getY());/*ok*/
 #endif
         }
-        /* Otherwise pick up the mid point between both extremities */
+        // Otherwise pick up the mid point between both extremities.
         else
         {
             poLS->getPoint((i + j + 1) / 2, &p1);
             poCS->addPoint(&p1);
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-            printf("Pickup 'random' midpoint at index=%d...\n", (i + j + 1) / 2);
-            printf("x_mid = %f, y_mid = %f\n", p1.getX(), p1.getY());
+            printf("Pickup 'random' midpoint at index=%d...\n",/*ok*/
+                   (i + j + 1) / 2);
+            printf("x_mid = %f, y_mid = %f\n", p1.getX(), p1.getY());/*ok*/
 #endif
         }
         poCS->addPoint(poFinalPoint);
 
 #ifdef VERBOSE_DEBUG_CURVEFROMLINESTRING
-    printf("----------------------------\n");
+    printf("----------------------------\n");/*ok*/
 #endif
 
     if( j + 2 >= poLS->getNumPoints() )
@@ -4198,15 +5506,16 @@ static int OGRGF_DetectArc(const OGRLineString* poLS, int i,
  * @since GDAL 2.0
  */
 
-OGRCurve* OGRGeometryFactory::curveFromLineString(const OGRLineString* poLS,
-                                                  CPL_UNUSED const char*const* papszOptions)
+OGRCurve* OGRGeometryFactory::curveFromLineString(
+    const OGRLineString* poLS,
+    CPL_UNUSED const char * const * papszOptions)
 {
     OGRCompoundCurve* poCC = NULL;
     OGRCircularString* poCS = NULL;
     OGRLineString* poLSNew = NULL;
-    for(int i=0; i< poLS->getNumPoints(); /* nothing */)
+    for( int i = 0; i < poLS->getNumPoints(); /* nothing */ )
     {
-        int iNewI = OGRGF_DetectArc(poLS, i, poCC, poCS, poLSNew);
+        const int iNewI = OGRGF_DetectArc(poLS, i, poCC, poCS, poLSNew);
         if( iNewI == -2 )
             break;
         if( iNewI >= 0 )
@@ -4230,22 +5539,25 @@ OGRCurve* OGRGeometryFactory::curveFromLineString(const OGRLineString* poLS,
             poLSNew = new OGRLineString();
             poLSNew->addPoint(&p);
         }
-        /* Not strictly necessary, but helps having 'clean' lines without duplicated points */
+        // Not strictly necessary, but helps having 'clean' lines without
+        // duplicated points.
         else
         {
-            double dfScale = MAX(1, fabs(p.getX()));
-            dfScale = MAX(dfScale, fabs(p.getY()));
-            if( fabs(poLSNew->getX(poLSNew->getNumPoints()-1) - p.getX()) / dfScale > 1e-8 ||
-                fabs(poLSNew->getY(poLSNew->getNumPoints()-1) - p.getY()) / dfScale > 1e-8 )
+            double dfScale = std::max(1.0, fabs(p.getX()));
+            dfScale = std::max(dfScale, fabs(p.getY()));
+            if( fabs(poLSNew->getX(poLSNew->getNumPoints()-1) -
+                     p.getX()) / dfScale > 1e-8 ||
+                fabs(poLSNew->getY(poLSNew->getNumPoints()-1) -
+                     p.getY()) / dfScale > 1e-8 )
             {
                 poLSNew->addPoint(&p);
             }
         }
 
-        i++ ;
+        i++;
     }
 
-    OGRCurve* poRet;
+    OGRCurve* poRet = NULL;
 
     if( poLSNew != NULL && poLSNew->getNumPoints() < 2 )
     {
diff --git a/ogr/ogrgeomfielddefn.cpp b/ogr/ogrgeomfielddefn.cpp
index 167f04a..e5a433b 100644
--- a/ogr/ogrgeomfielddefn.cpp
+++ b/ogr/ogrgeomfielddefn.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeomfielddefn.cpp 28806 2015-03-28 14:37:47Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRGeomFieldDefn class implementation.
@@ -27,12 +26,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_feature.h"
+#include "cpl_port.h"
 #include "ogr_api.h"
+
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
 #include "ogr_p.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrgeomfielddefn.cpp 28806 2015-03-28 14:37:47Z rouault $");
+CPL_CVSID("$Id: ogrgeomfielddefn.cpp 36705 2016-12-05 18:05:08Z rouault $");
 
 /************************************************************************/
 /*                         OGRGeomFieldDefn()                           */
@@ -82,7 +90,8 @@ OGRGeomFieldDefn::OGRGeomFieldDefn( OGRGeomFieldDefn *poPrototype )
 /**
  * \brief Create a new field geometry definition.
  *
- * This function is the same as the CPP method OGRGeomFieldDefn::OGRGeomFieldDefn().
+ * This function is the same as the CPP method
+ * OGRGeomFieldDefn::OGRGeomFieldDefn().
  *
  * @param pszName the name of the new field definition.
  * @param eType the type of the new field definition.
@@ -95,13 +104,15 @@ OGRGeomFieldDefnH OGR_GFld_Create( const char *pszName,
                                    OGRwkbGeometryType eType )
 
 {
-    return (OGRGeomFieldDefnH) (new OGRGeomFieldDefn(pszName,eType));
+  return
+      reinterpret_cast<OGRGeomFieldDefnH>(new OGRGeomFieldDefn(pszName, eType));
 }
 
 /************************************************************************/
 /*                             Initialize()                             */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 void OGRGeomFieldDefn::Initialize( const char * pszNameIn,
                                    OGRwkbGeometryType eTypeIn )
 
@@ -112,6 +123,7 @@ void OGRGeomFieldDefn::Initialize( const char * pszNameIn,
     bIgnore = FALSE;
     bNullable = TRUE;
 }
+//! @endcond
 
 /************************************************************************/
 /*                         ~OGRGeomFieldDefn()                          */
@@ -141,7 +153,8 @@ void OGR_GFld_Destroy( OGRGeomFieldDefnH hDefn )
 
 {
     VALIDATE_POINTER0( hDefn, "OGR_GFld_Destroy" );
-    delete (OGRGeomFieldDefn *) hDefn;
+
+    delete reinterpret_cast<OGRGeomFieldDefn *>(hDefn);
 }
 
 /************************************************************************/
@@ -161,8 +174,11 @@ void OGR_GFld_Destroy( OGRGeomFieldDefnH hDefn )
 void OGRGeomFieldDefn::SetName( const char * pszNameIn )
 
 {
-    CPLFree( pszName );
-    pszName = CPLStrdup( pszNameIn );
+    if( pszName != pszNameIn )
+    {
+        CPLFree( pszName );
+        pszName = CPLStrdup( pszNameIn );
+    }
 }
 
 /************************************************************************/
@@ -173,7 +189,8 @@ void OGRGeomFieldDefn::SetName( const char * pszNameIn )
  *
  * This function is the same as the CPP method OGRGeomFieldDefn::SetName().
  *
- * @param hDefn handle to the geometry field definition to apply the new name to.
+ * @param hDefn handle to the geometry field definition to apply the
+ * new name to.
  * @param pszName the new name to apply.
  *
  * @since GDAL 1.11
@@ -183,7 +200,8 @@ void OGR_GFld_SetName( OGRGeomFieldDefnH hDefn, const char *pszName )
 
 {
     VALIDATE_POINTER0( hDefn, "OGR_GFld_SetName" );
-    ((OGRGeomFieldDefn *) hDefn)->SetName( pszName );
+
+    reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->SetName(pszName);
 }
 
 /************************************************************************/
@@ -227,7 +245,7 @@ const char *OGR_GFld_GetNameRef( OGRGeomFieldDefnH hDefn )
         OGRAPISpy_GFld_GetXXXX(hDefn, "GetNameRef");
 #endif
 
-    return ((OGRGeomFieldDefn *) hDefn)->GetNameRef();
+    return reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->GetNameRef();
 }
 
 /************************************************************************/
@@ -235,7 +253,7 @@ const char *OGR_GFld_GetNameRef( OGRGeomFieldDefnH hDefn )
 /************************************************************************/
 
 /**
- * \fn OGRwkbGeometryType OGRGeomFieldDefn::GetType();
+ * \fn OGRwkbGeometryType OGRGeomFieldDefn::GetType() const;
  *
  * \brief Fetch geometry type of this field.
  *
@@ -270,7 +288,8 @@ OGRwkbGeometryType OGR_GFld_GetType( OGRGeomFieldDefnH hDefn )
         OGRAPISpy_GFld_GetXXXX(hDefn, "GetType");
 #endif
 
-    OGRwkbGeometryType eType = ((OGRGeomFieldDefn *) hDefn)->GetType();
+    OGRwkbGeometryType eType =
+        reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->GetType();
     if( OGR_GT_IsNonLinear(eType) && !OGRGetNonLinearGeometriesEnabledFlag() )
     {
         eType = OGR_GT_GetLinear(eType);
@@ -283,15 +302,13 @@ OGRwkbGeometryType OGR_GFld_GetType( OGRGeomFieldDefnH hDefn )
 /************************************************************************/
 
 /**
- * \fn void OGRGeomFieldDefn::SetType( OGRwkbGeometryType eType );
- *
  * \brief Set the geometry type of this field.
  * This should never be done to an OGRGeomFieldDefn
  * that is already part of an OGRFeatureDefn.
  *
  * This method is the same as the C function OGR_GFld_SetType().
  *
- * @param eType the new field geometry type.
+ * @param eTypeIn the new field geometry type.
  *
  * @since GDAL 1.11
  */
@@ -322,7 +339,8 @@ void OGR_GFld_SetType( OGRGeomFieldDefnH hDefn, OGRwkbGeometryType eType )
 
 {
     VALIDATE_POINTER0( hDefn, "OGR_GFld_SetType" );
-    ((OGRGeomFieldDefn *) hDefn)->SetType( eType );
+
+    reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->SetType(eType);
 }
 
 /************************************************************************/
@@ -330,7 +348,7 @@ void OGR_GFld_SetType( OGRGeomFieldDefnH hDefn, OGRwkbGeometryType eType )
 /************************************************************************/
 
 /**
- * \fn int OGRGeomFieldDefn::IsIgnored();
+ * \fn int OGRGeomFieldDefn::IsIgnored() const;
  *
  * \brief Return whether this field should be omitted when fetching features
  *
@@ -359,7 +377,8 @@ void OGR_GFld_SetType( OGRGeomFieldDefnH hDefn, OGRwkbGeometryType eType )
 int OGR_GFld_IsIgnored( OGRGeomFieldDefnH hDefn )
 {
     VALIDATE_POINTER1( hDefn, "OGR_GFld_IsIgnored", FALSE );
-    return ((OGRGeomFieldDefn *) hDefn)->IsIgnored();
+
+    return reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->IsIgnored();
 }
 
 /************************************************************************/
@@ -396,7 +415,8 @@ int OGR_GFld_IsIgnored( OGRGeomFieldDefnH hDefn )
 void OGR_GFld_SetIgnored( OGRGeomFieldDefnH hDefn, int ignore )
 {
     VALIDATE_POINTER0( hDefn, "OGR_GFld_SetIgnored" );
-    ((OGRGeomFieldDefn *) hDefn)->SetIgnored( ignore );
+
+    reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->SetIgnored(ignore);
 }
 
 /************************************************************************/
@@ -424,7 +444,8 @@ OGRSpatialReference* OGRGeomFieldDefn::GetSpatialRef()
 /**
  * \brief Fetch spatial reference system of this field.
  *
- * This function is the same as the C++ method OGRGeomFieldDefn::GetSpatialRef().
+ * This function is the same as the C++ method
+ * OGRGeomFieldDefn::GetSpatialRef().
  *
  * @param hDefn handle to the geometry field definition
  *
@@ -442,7 +463,8 @@ OGRSpatialReferenceH OGR_GFld_GetSpatialRef( OGRGeomFieldDefnH hDefn )
         OGRAPISpy_GFld_GetXXXX(hDefn, "GetSpatialRef");
 #endif
 
-    return (OGRSpatialReferenceH) ((OGRGeomFieldDefn *) hDefn)->GetSpatialRef();
+    return reinterpret_cast<OGRSpatialReferenceH>(
+        reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->GetSpatialRef());
 }
 
 /************************************************************************/
@@ -477,7 +499,8 @@ void OGRGeomFieldDefn::SetSpatialRef(OGRSpatialReference* poSRSIn)
 /**
  * \brief Set the spatial reference of this field.
  *
- * This function is the same as the C++ method OGRGeomFieldDefn::SetSpatialRef().
+ * This function is the same as the C++ method
+ * OGRGeomFieldDefn::SetSpatialRef().
  *
  * This function drops the reference of the previously set SRS object and
  * acquires a new reference on the passed object (if non-NULL).
@@ -488,10 +511,13 @@ void OGRGeomFieldDefn::SetSpatialRef(OGRSpatialReference* poSRSIn)
  * @since GDAL 1.11
  */
 
-void OGR_GFld_SetSpatialRef( OGRGeomFieldDefnH hDefn, OGRSpatialReferenceH hSRS )
+void OGR_GFld_SetSpatialRef( OGRGeomFieldDefnH hDefn,
+                             OGRSpatialReferenceH hSRS )
 {
     VALIDATE_POINTER0( hDefn, "OGR_GFld_SetSpatialRef" );
-    ((OGRGeomFieldDefn *) hDefn)->SetSpatialRef( (OGRSpatialReference*) hSRS );
+
+    reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->
+        SetSpatialRef(reinterpret_cast<OGRSpatialReference *>(hSRS));
 }
 
 /************************************************************************/
@@ -569,7 +595,7 @@ int OGRGeomFieldDefn::IsSame( OGRGeomFieldDefn * poOtherFieldDefn )
 
 int OGR_GFld_IsNullable( OGRGeomFieldDefnH hDefn )
 {
-    return ((OGRGeomFieldDefn *) hDefn)->IsNullable();
+    return reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->IsNullable();
 }
 
 /************************************************************************/
@@ -581,8 +607,8 @@ int OGR_GFld_IsNullable( OGRGeomFieldDefnH hDefn )
  *
  * \brief Set whether this geometry field can receive null values.
  *
- * By default, fields are nullable, so this method is generally called with FALSE
- * to set a not-null constraint.
+ * By default, fields are nullable, so this method is generally called with
+ * FALSE to set a not-null constraint.
  *
  * Drivers that support writing not-null constraint will advertize the
  * GDAL_DCAP_NOTNULL_GEOMFIELDS driver metadata item.
@@ -600,8 +626,8 @@ int OGR_GFld_IsNullable( OGRGeomFieldDefnH hDefn )
 /**
  * \brief Set whether this geometry field can receive null values.
  *
- * By default, fields are nullable, so this method is generally called with FALSE
- * to set a not-null constraint.
+ * By default, fields are nullable, so this method is generally called with
+ * FALSE to set a not-null constraint.
  *
  * Drivers that support writing not-null constraint will advertize the
  * GDAL_DCAP_NOTNULL_GEOMFIELDS driver metadata item.
@@ -615,5 +641,5 @@ int OGR_GFld_IsNullable( OGRGeomFieldDefnH hDefn )
 
 void OGR_GFld_SetNullable( OGRGeomFieldDefnH hDefn, int bNullableIn )
 {
-    ((OGRGeomFieldDefn *) hDefn)->SetNullable( bNullableIn );
+    reinterpret_cast<OGRGeomFieldDefn *>(hDefn)->SetNullable(bNullableIn);
 }
diff --git a/ogr/ogrlinearring.cpp b/ogr/ogrlinearring.cpp
index 6d45078..a4026ae 100644
--- a/ogr/ogrlinearring.cpp
+++ b/ogr/ogrlinearring.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrlinearring.cpp 34469 2016-06-30 08:52:13Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRLinearRing geometry class.
@@ -28,19 +27,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_geometry.h"
+
+#include <climits>
+#include <cmath>
+#include <cstring>
+
+#include "cpl_error.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrlinearring.cpp 34469 2016-06-30 08:52:13Z rouault $");
+CPL_CVSID("$Id: ogrlinearring.cpp 37113 2017-01-12 11:47:03Z rouault $");
 
 /************************************************************************/
 /*                           OGRLinearRing()                            */
 /************************************************************************/
 
-OGRLinearRing::OGRLinearRing()
-
-{
-}
+/** Constructor */
+OGRLinearRing::OGRLinearRing() {}
 
 /************************************************************************/
 /*                  OGRLinearRing( const OGRLinearRing& )               */
@@ -57,28 +63,29 @@ OGRLinearRing::OGRLinearRing()
 
 OGRLinearRing::OGRLinearRing( const OGRLinearRing& other ) :
     OGRLineString( other )
-{
-}
+{}
 
 /************************************************************************/
 /*                          ~OGRLinearRing()                            */
 /************************************************************************/
 
-OGRLinearRing::~OGRLinearRing()
-
-{
-}
+OGRLinearRing::~OGRLinearRing() {}
 
 /************************************************************************/
 /*                           OGRLinearRing()                            */
 /************************************************************************/
 
+/** Constructor
+ * @param poSrcRing source ring.
+ */
 OGRLinearRing::OGRLinearRing( OGRLinearRing * poSrcRing )
 
 {
     if( poSrcRing == NULL )
     {
-        CPLDebug( "OGR", "OGRLinearRing::OGRLinearRing(OGRLinearRing*poSrcRing) - passed in ring is NULL!" );
+        CPLDebug( "OGR",
+                  "OGRLinearRing::OGRLinearRing(OGRLinearRing*poSrcRing) - "
+                  "passed in ring is NULL!" );
         return;
     }
 
@@ -145,7 +152,7 @@ int OGRLinearRing::WkbSize() const
 /************************************************************************/
 
 OGRErr OGRLinearRing::importFromWkb( CPL_UNUSED unsigned char *pabyData,
-                                     CPL_UNUSED  int nSize,
+                                     CPL_UNUSED int nSize,
                                      CPL_UNUSED OGRwkbVariant eWkbVariant )
 
 {
@@ -170,9 +177,10 @@ OGRErr OGRLinearRing::exportToWkb( CPL_UNUSED OGRwkbByteOrder eByteOrder,
 /*                           _importFromWkb()                           */
 /*                                                                      */
 /*      Helper method for OGRPolygon.  NOT A NORMAL importFromWkb()     */
-/*      method!                                                         */
+/*      method.                                                         */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int _flags,
                                       unsigned char * pabyData,
                                       int nBytesAvailable )
@@ -184,25 +192,24 @@ OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int _flags,
 /* -------------------------------------------------------------------- */
 /*      Get the vertex count.                                           */
 /* -------------------------------------------------------------------- */
-    int         nNewNumPoints;
+    int nNewNumPoints = 0;
 
     memcpy( &nNewNumPoints, pabyData, 4 );
 
     if( OGR_SWAP( eByteOrder ) )
         nNewNumPoints = CPL_SWAP32(nNewNumPoints);
 
-    /* Check if the wkb stream buffer is big enough to store
-     * fetched number of points.
-     * 16, 24, or 32 - size of point structure
-     */
-    int nPointSize;
+    // Check if the wkb stream buffer is big enough to store
+    // fetched number of points.
+    // 16, 24, or 32 - size of point structure.
+    int nPointSize = 0;
     if( (_flags & OGR_G_3D) && (_flags & OGR_G_MEASURED) )
         nPointSize = 32;
     else if( (_flags & OGR_G_3D) || (_flags & OGR_G_MEASURED) )
         nPointSize = 24;
     else
         nPointSize = 16;
-    if (nNewNumPoints < 0 || nNewNumPoints > INT_MAX / nPointSize)
+    if( nNewNumPoints < 0 || nNewNumPoints > INT_MAX / nPointSize )
         return OGRERR_CORRUPT_DATA;
     int nBufferMinSize = nPointSize * nNewNumPoints;
 
@@ -213,7 +220,7 @@ OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int _flags,
         return OGRERR_NOT_ENOUGH_DATA;
     }
 
-    /* (Re)Allocation of paoPoints buffer. */
+    // (Re)Allocation of paoPoints buffer.
     setNumPoints( nNewNumPoints, FALSE );
 
     if( _flags & OGR_G_3D )
@@ -290,14 +297,13 @@ OGRErr OGRLinearRing::_importFromWkb( OGRwkbByteOrder eByteOrder, int _flags,
 /*                            _exportToWkb()                            */
 /*                                                                      */
 /*      Helper method for OGRPolygon.  THIS IS NOT THE NORMAL           */
-/*      exportToWkb() METHOD!                                           */
+/*      exportToWkb() METHOD.                                           */
 /************************************************************************/
 
-OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int _flags,
-                                     unsigned char * pabyData ) const
+OGRErr OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int _flags,
+                                    unsigned char * pabyData ) const
 
 {
-    int   i, nWords;
 
 /* -------------------------------------------------------------------- */
 /*      Copy in the raw data.                                           */
@@ -307,10 +313,11 @@ OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int _flags,
 /* -------------------------------------------------------------------- */
 /*      Copy in the raw data.                                           */
 /* -------------------------------------------------------------------- */
+    int nWords = 0;
     if( (_flags & OGR_G_3D) && (_flags & OGR_G_MEASURED) )
     {
         nWords = 4 * nPointCount;
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             memcpy( pabyData+4+i*32, &(paoPoints[i].x), 8 );
             memcpy( pabyData+4+i*32+8, &(paoPoints[i].y), 8 );
@@ -327,7 +334,7 @@ OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int _flags,
     else if( _flags & OGR_G_MEASURED )
     {
         nWords = 3 * nPointCount;
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             memcpy( pabyData+4+i*24, &(paoPoints[i].x), 8 );
             memcpy( pabyData+4+i*24+8, &(paoPoints[i].y), 8 );
@@ -340,7 +347,7 @@ OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int _flags,
     else if( _flags & OGR_G_3D )
     {
         nWords = 3 * nPointCount;
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             memcpy( pabyData+4+i*24, &(paoPoints[i].x), 8 );
             memcpy( pabyData+4+i*24+8, &(paoPoints[i].y), 8 );
@@ -361,12 +368,10 @@ OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int _flags,
 /* -------------------------------------------------------------------- */
     if( OGR_SWAP( eByteOrder ) )
     {
-        int     nCount;
-
-        nCount = CPL_SWAP32( nPointCount );
+        int nCount = CPL_SWAP32( nPointCount );
         memcpy( pabyData, &nCount, 4 );
 
-        for( i = 0; i < nWords; i++ )
+        for( int i = 0; i < nWords; i++ )
         {
             CPL_SWAPDOUBLE( pabyData + 4 + 8 * i );
         }
@@ -378,7 +383,7 @@ OGRErr  OGRLinearRing::_exportToWkb( OGRwkbByteOrder eByteOrder, int _flags,
 /************************************************************************/
 /*                              _WkbSize()                              */
 /*                                                                      */
-/*      Helper method for OGRPolygon.  NOT THE NORMAL WkbSize() METHOD! */
+/*      Helper method for OGRPolygon.  NOT THE NORMAL WkbSize() METHOD. */
 /************************************************************************/
 
 int OGRLinearRing::_WkbSize( int _flags ) const
@@ -391,6 +396,7 @@ int OGRLinearRing::_WkbSize( int _flags ) const
     else
         return 4 + 16 * nPointCount;
 }
+//! @endcond
 
 /************************************************************************/
 /*                               clone()                                */
@@ -402,9 +408,7 @@ int OGRLinearRing::_WkbSize( int _flags ) const
 OGRGeometry *OGRLinearRing::clone() const
 
 {
-    OGRLinearRing       *poNewLinearRing;
-
-    poNewLinearRing = new OGRLinearRing();
+    OGRLinearRing *poNewLinearRing = new OGRLinearRing();
     poNewLinearRing->assignSpatialReference( getSpatialReference() );
 
     poNewLinearRing->setPoints( nPointCount, paoPoints, padfZ, padfM );
@@ -413,7 +417,6 @@ OGRGeometry *OGRLinearRing::clone() const
     return poNewLinearRing;
 }
 
-
 /************************************************************************/
 /*                            epsilonEqual()                            */
 /************************************************************************/
@@ -438,37 +441,35 @@ static inline bool epsilonEqual(double a, double b, double eps)
 int OGRLinearRing::isClockwise() const
 
 {
-    int    i, v, next;
-    double  dx0, dy0, dx1, dy1, crossproduct;
-    bool bUseFallback = false;
-
     if( nPointCount < 2 )
         return TRUE;
 
-    /* Find the lowest rightmost vertex */
-    v = 0;
-    for ( i = 1; i < nPointCount - 1; i++ )
+    bool bUseFallback = false;
+
+    // Find the lowest rightmost vertex.
+    int v = 0;  // Used after for.
+    for( int i = 1; i < nPointCount - 1; i++ )
     {
-        /* => v < end */
-        if ( paoPoints[i].y< paoPoints[v].y ||
-             ( paoPoints[i].y== paoPoints[v].y &&
-               paoPoints[i].x > paoPoints[v].x ) )
+        // => v < end.
+        if( paoPoints[i].y< paoPoints[v].y ||
+            ( paoPoints[i].y== paoPoints[v].y &&
+              paoPoints[i].x > paoPoints[v].x ) )
         {
             v = i;
             bUseFallback = false;
         }
-        else if ( paoPoints[i].y == paoPoints[v].y &&
-                  paoPoints[i].x == paoPoints[v].x )
+        else if( paoPoints[i].y == paoPoints[v].y &&
+                 paoPoints[i].x == paoPoints[v].x )
         {
-            /* Two vertex with same coordinates are the lowest rightmost */
-            /* vertex! We cannot use that point as the pivot (#5342) */
+            // Two vertex with same coordinates are the lowest rightmost
+            // vertex.  Cannot use that point as the pivot (#5342).
             bUseFallback = true;
         }
     }
 
-    /* previous */
-    next = v - 1;
-    if ( next < 0 )
+    // Previous.
+    int next = v - 1;
+    if( next < 0 )
     {
         next = nPointCount - 1 - 1;
     }
@@ -476,17 +477,17 @@ int OGRLinearRing::isClockwise() const
     if( epsilonEqual(paoPoints[next].x, paoPoints[v].x, EPSILON) &&
         epsilonEqual(paoPoints[next].y, paoPoints[v].y, EPSILON) )
     {
-        /* Don't try to be too clever by retrying with a next point */
-        /* This can lead to false results as in the case of #3356 */
+        // Don't try to be too clever by retrying with a next point.
+        // This can lead to false results as in the case of #3356.
         bUseFallback = true;
     }
 
-    dx0 = paoPoints[next].x - paoPoints[v].x;
-    dy0 = paoPoints[next].y - paoPoints[v].y;
+    const double dx0 = paoPoints[next].x - paoPoints[v].x;
+    const double dy0 = paoPoints[next].y - paoPoints[v].y;
 
-    /* following */
+    // Following.
     next = v + 1;
-    if ( next >= nPointCount - 1 )
+    if( next >= nPointCount - 1 )
     {
         next = 0;
     }
@@ -494,36 +495,40 @@ int OGRLinearRing::isClockwise() const
     if( epsilonEqual(paoPoints[next].x, paoPoints[v].x, EPSILON) &&
         epsilonEqual(paoPoints[next].y, paoPoints[v].y, EPSILON) )
     {
-        /* Don't try to be too clever by retrying with a next point */
-        /* This can lead to false results as in the case of #3356 */
+        // Don't try to be too clever by retrying with a next point.
+        // This can lead to false results as in the case of #3356.
         bUseFallback = true;
     }
 
-    dx1 = paoPoints[next].x - paoPoints[v].x;
-    dy1 = paoPoints[next].y - paoPoints[v].y;
+    const double dx1 = paoPoints[next].x - paoPoints[v].x;
+    const double dy1 = paoPoints[next].y - paoPoints[v].y;
 
-    crossproduct = dx1 * dy0 - dx0 * dy1;
+    const double crossproduct = dx1 * dy0 - dx0 * dy1;
 
-    if (!bUseFallback)
+    if( !bUseFallback )
     {
-        if ( crossproduct > 0 )      /* CCW */
+        if( crossproduct > 0 )       // CCW
             return FALSE;
-        else if ( crossproduct < 0 )  /* CW */
+        else if( crossproduct < 0 )  // CW
             return TRUE;
     }
 
-    /* ok, this is a degenerate case : the extent of the polygon is less than EPSILON */
-    /* or 2 nearly identical points were found */
-    /* Try with Green Formula as a fallback, but this is not a guarantee */
-    /* as we'll probably be affected by numerical instabilities */
+    // This is a degenerate case: the extent of the polygon is less than EPSILON
+    // or 2 nearly identical points were found.
+    // Try with Green Formula as a fallback, but this is not a guarantee
+    // as we'll probably be affected by numerical instabilities.
 
-    double dfSum = paoPoints[0].x * (paoPoints[1].y - paoPoints[nPointCount-1].y);
+    double dfSum =
+        paoPoints[0].x * (paoPoints[1].y - paoPoints[nPointCount-1].y);
 
-    for (i=1; i<nPointCount-1; i++) {
+    for( int i = 1; i < nPointCount-1; i++ )
+    {
         dfSum += paoPoints[i].x * (paoPoints[i+1].y - paoPoints[i-1].y);
     }
 
-    dfSum += paoPoints[nPointCount-1].x * (paoPoints[0].y - paoPoints[nPointCount-2].y);
+    dfSum +=
+        paoPoints[nPointCount-1].x *
+        (paoPoints[0].y - paoPoints[nPointCount-2].y);
 
     return dfSum < 0;
 }
@@ -532,16 +537,18 @@ int OGRLinearRing::isClockwise() const
 /*                             reverseWindingOrder()                    */
 /************************************************************************/
 
+/** Reverse order of points.
+ */
 void OGRLinearRing::reverseWindingOrder()
 
 {
-    int pos = 0;
-    OGRPoint pointA, pointB;
+    OGRPoint pointA;
+    OGRPoint pointB;
 
     for( int i = 0; i < nPointCount / 2; i++ )
     {
         getPoint( i, &pointA );
-        pos = nPointCount - i - 1;
+        const int pos = nPointCount - i - 1;
         getPoint( pos, &pointB );
         setPoint( i, &pointB );
         setPoint( pos, &pointA );
@@ -572,43 +579,52 @@ void OGRLinearRing::closeRings()
 /*                              isPointInRing()                         */
 /************************************************************************/
 
-OGRBoolean OGRLinearRing::isPointInRing(const OGRPoint* poPoint, int bTestEnvelope) const
+/** Returns whether the point is inside the ring.
+ * @param poPoint point
+ * @param bTestEnvelope set to TRUE if the presence of the point inside the
+ *                      ring envelope must be checked first.
+ * @return TRUE or FALSE.
+ */
+OGRBoolean OGRLinearRing::isPointInRing(const OGRPoint* poPoint,
+                                        int bTestEnvelope) const
 {
-    if ( NULL == poPoint )
+    if( NULL == poPoint )
     {
-        CPLDebug( "OGR", "OGRLinearRing::isPointInRing(const  OGRPoint* poPoint) - passed point is NULL!" );
+        CPLDebug( "OGR",
+                  "OGRLinearRing::isPointInRing(const OGRPoint* poPoint) - "
+                  "passed point is NULL!" );
         return 0;
     }
 
     const int iNumPoints = getNumPoints();
 
     // Simple validation
-    if ( iNumPoints < 4 )
+    if( iNumPoints < 4 )
         return 0;
 
     const double dfTestX = poPoint->getX();
     const double dfTestY = poPoint->getY();
 
-    // Fast test if point is inside extent of the ring
-    if (bTestEnvelope)
+    // Fast test if point is inside extent of the ring.
+    if( bTestEnvelope )
     {
         OGREnvelope extent;
         getEnvelope(&extent);
-        if ( !( dfTestX >= extent.MinX && dfTestX <= extent.MaxX
-            && dfTestY >= extent.MinY && dfTestY <= extent.MaxY ) )
+        if( !( dfTestX >= extent.MinX && dfTestX <= extent.MaxX
+               && dfTestY >= extent.MinY && dfTestY <= extent.MaxY ) )
         {
             return 0;
         }
     }
 
-	// For every point p in ring,
+    // For every point p in ring,
     // test if ray starting from given point crosses segment (p - 1, p)
     int iNumCrossings = 0;
 
     double prev_diff_x = getX(0) - dfTestX;
     double prev_diff_y = getY(0) - dfTestY;
 
-    for ( int iPoint = 1; iPoint < iNumPoints; iPoint++ )
+    for( int iPoint = 1; iPoint < iNumPoints; iPoint++ )
     {
         const double x1 = getX(iPoint) - dfTestX;
         const double y1 = getY(iPoint) - dfTestY;
@@ -620,7 +636,7 @@ OGRBoolean OGRLinearRing::isPointInRing(const OGRPoint* poPoint, int bTestEnvelo
         {
             // Check if ray intersects with segment of the ring
             const double dfIntersection = ( x1 * y2 - x2 * y1 ) / (y2 - y1);
-            if ( 0.0 < dfIntersection )
+            if( 0.0 < dfIntersection )
             {
                 // Count intersections
                 iNumCrossings++;
@@ -633,25 +649,34 @@ OGRBoolean OGRLinearRing::isPointInRing(const OGRPoint* poPoint, int bTestEnvelo
 
     // If iNumCrossings number is even, given point is outside the ring,
     // when the crossings number is odd, the point is inside the ring.
-    return ( ( iNumCrossings % 2 ) == 1 ? 1 : 0 );
+    return iNumCrossings % 2;  // OGRBoolean
 }
 
 /************************************************************************/
 /*                       isPointOnRingBoundary()                        */
 /************************************************************************/
 
-OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTestEnvelope) const
+/** Returns whether the point is on the ring boundary.
+ * @param poPoint point
+ * @param bTestEnvelope set to TRUE if the presence of the point inside the
+ *                      ring envelope must be checked first.
+ * @return TRUE or FALSE.
+ */
+OGRBoolean OGRLinearRing::isPointOnRingBoundary( const OGRPoint* poPoint,
+                                                 int bTestEnvelope ) const
 {
-    if ( NULL == poPoint )
+    if( NULL == poPoint )
     {
-        CPLDebug( "OGR", "OGRLinearRing::isPointOnRingBoundary(const  OGRPoint* poPoint) - passed point is NULL!" );
+        CPLDebug( "OGR",
+                  "OGRLinearRing::isPointOnRingBoundary(const OGRPoint* "
+                  "poPoint) - passed point is NULL!" );
         return 0;
     }
 
     const int iNumPoints = getNumPoints();
 
-    // Simple validation
-    if ( iNumPoints < 4 )
+    // Simple validation.
+    if( iNumPoints < 4 )
         return 0;
 
     const double dfTestX = poPoint->getX();
@@ -662,8 +687,8 @@ OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTe
     {
         OGREnvelope extent;
         getEnvelope(&extent);
-        if ( !( dfTestX >= extent.MinX && dfTestX <= extent.MaxX
-            && dfTestY >= extent.MinY && dfTestY <= extent.MaxY ) )
+        if( !( dfTestX >= extent.MinX && dfTestX <= extent.MaxX
+               && dfTestY >= extent.MinY && dfTestY <= extent.MaxY ) )
         {
             return 0;
         }
@@ -672,7 +697,7 @@ OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTe
     double prev_diff_x = getX(0) - dfTestX;
     double prev_diff_y = getY(0) - dfTestY;
 
-    for ( int iPoint = 1; iPoint < iNumPoints; iPoint++ )
+    for( int iPoint = 1; iPoint < iNumPoints; iPoint++ )
     {
         const double x1 = getX(iPoint) - dfTestX;
         const double y1 = getY(iPoint) - dfTestY;
@@ -680,15 +705,15 @@ OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTe
         const double x2 = prev_diff_x;
         const double y2 = prev_diff_y;
 
-        /* If the point is on the segment, return immediately. */
-        /* FIXME? If the test point is not exactly identical to one of */
-        /* the vertices of the ring, but somewhere on a segment, there's */
-        /* little chance that we get 0. So that should be tested against some */
-        /* epsilon. */
+        // If the point is on the segment, return immediately.
+        // FIXME? If the test point is not exactly identical to one of
+        // the vertices of the ring, but somewhere on a segment, there's
+        // little chance that we get 0. So that should be tested against some
+        // epsilon.
 
-        if ( x1 * y2 - x2 * y1 == 0 )
+        if( x1 * y2 - x2 * y1 == 0 )
         {
-            /* If iPoint and iPointPrev are the same, go on */
+            // If iPoint and iPointPrev are the same, go on.
             if( !(x1 == x2 && y1 == y2) )
             {
                 return 1;
@@ -703,6 +728,33 @@ OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTe
 }
 
 /************************************************************************/
+/*                             transform()                              */
+/************************************************************************/
+
+OGRErr OGRLinearRing::transform( OGRCoordinateTransformation *poCT )
+
+{
+    const bool bIsClosed = getNumPoints() > 2 && CPL_TO_BOOL(get_IsClosed());
+    OGRErr eErr = OGRLineString::transform(poCT);
+    if( bIsClosed && eErr == OGRERR_NONE && !get_IsClosed() )
+    {
+        CPLDebug("OGR", "Linearring is not closed after coordinate "
+                  "transformation. Forcing last point to be identical to "
+                  "first one");
+        // Force last point to be identical to first point.
+        // This is a safety belt in case the reprojection of the same coordinate
+        // isn't perfectly stable. This can for example happen in very rare cases
+        // when reprojecting a cutline with a RPC transform with a DEM that
+        // is a VRT whose sources are resampled...
+        OGRPoint oStartPoint;
+        StartPoint( &oStartPoint );
+
+        setPoint( getNumPoints()-1, &oStartPoint);
+    }
+    return eErr;
+}
+
+/************************************************************************/
 /*                          CastToLineString()                          */
 /************************************************************************/
 
@@ -715,16 +767,18 @@ OGRBoolean OGRLinearRing::isPointOnRingBoundary(const OGRPoint* poPoint, int bTe
  * @return new geometry.
  */
 
-OGRLineString* OGRLinearRing::CastToLineString(OGRLinearRing* poLR)
+OGRLineString* OGRLinearRing::CastToLineString( OGRLinearRing* poLR )
 {
     return TransferMembersAndDestroy(poLR, new OGRLineString());
 }
 
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                     GetCasterToLineString()                          */
 /************************************************************************/
 
-OGRCurveCasterToLineString OGRLinearRing::GetCasterToLineString() const {
+OGRCurveCasterToLineString OGRLinearRing::GetCasterToLineString() const
+{
     return (OGRCurveCasterToLineString) OGRLinearRing::CastToLineString;
 }
 
@@ -732,6 +786,8 @@ OGRCurveCasterToLineString OGRLinearRing::GetCasterToLineString() const {
 /*                        GetCasterToLinearRing()                       */
 /************************************************************************/
 
-OGRCurveCasterToLinearRing OGRLinearRing::GetCasterToLinearRing() const {
+OGRCurveCasterToLinearRing OGRLinearRing::GetCasterToLinearRing() const
+{
     return (OGRCurveCasterToLinearRing) OGRGeometry::CastToIdentity;
 }
+//! @endcond
diff --git a/ogr/ogrlinestring.cpp b/ogr/ogrlinestring.cpp
index c8cd107..807f89d 100644
--- a/ogr/ogrlinestring.cpp
+++ b/ogr/ogrlinestring.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrlinestring.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSimpleCurve and OGRLineString geometry classes.
@@ -29,19 +28,25 @@
  ****************************************************************************/
 
 #include "ogr_geometry.h"
-#include "ogr_p.h"
-#include <assert.h>
 #include "ogr_geos.h"
+#include "ogr_p.h"
+
+#include <cstdlib>
+#include <algorithm>
 
-CPL_CVSID("$Id: ogrlinestring.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrlinestring.cpp 36883 2016-12-15 13:31:12Z rouault $");
 
 /************************************************************************/
 /*                           OGRSimpleCurve()                           */
 /************************************************************************/
 
+/** Constructor */
 OGRSimpleCurve::OGRSimpleCurve() :
-    nPointCount(0), paoPoints(NULL), padfZ(NULL), padfM(NULL)
-{ }
+    nPointCount(0),
+    paoPoints(NULL),
+    padfZ(NULL),
+    padfM(NULL)
+{}
 
 /************************************************************************/
 /*                OGRSimpleCurve( const OGRSimpleCurve& )               */
@@ -57,11 +62,11 @@ OGRSimpleCurve::OGRSimpleCurve() :
  */
 
 OGRSimpleCurve::OGRSimpleCurve( const OGRSimpleCurve& other ) :
-    OGRCurve( other ),
-    nPointCount( 0 ),
-    paoPoints( NULL ),
-    padfZ( NULL ),
-    padfM( NULL )
+    OGRCurve(other),
+    nPointCount(0),
+    paoPoints(NULL),
+    padfZ(NULL),
+    padfM(NULL)
 {
     setPoints( other.nPointCount, other.paoPoints, other.padfZ, other.padfM );
 }
@@ -73,12 +78,9 @@ OGRSimpleCurve::OGRSimpleCurve( const OGRSimpleCurve& other ) :
 OGRSimpleCurve::~OGRSimpleCurve()
 
 {
-    if( paoPoints != NULL )
-        OGRFree( paoPoints );
-    if( padfZ != NULL )
-        OGRFree( padfZ );
-    if( padfM != NULL )
-        OGRFree( padfM );
+    CPLFree( paoPoints );
+    CPLFree( padfZ );
+    CPLFree( padfM );
 }
 
 /************************************************************************/
@@ -96,12 +98,13 @@ OGRSimpleCurve::~OGRSimpleCurve()
 
 OGRSimpleCurve& OGRSimpleCurve::operator=( const OGRSimpleCurve& other )
 {
-    if( this != &other)
-    {
-        OGRCurve::operator=( other );
+    if( this == &other)
+        return *this;
+
+    OGRCurve::operator=( other );
+
+    setPoints(other.nPointCount, other.paoPoints, other.padfZ, other.padfM);
 
-        setPoints( other.nPointCount, other.paoPoints, other.padfZ, other.padfM );
-    }
     return *this;
 }
 
@@ -123,10 +126,8 @@ void OGRSimpleCurve::flattenTo2D()
 OGRGeometry *OGRSimpleCurve::clone() const
 
 {
-    OGRSimpleCurve       *poCurve;
-
-    poCurve = (OGRSimpleCurve*)
-            OGRGeometryFactory::createGeometry(getGeometryType());
+    OGRSimpleCurve *poCurve = dynamic_cast<OGRSimpleCurve *>(
+            OGRGeometryFactory::createGeometry(getGeometryType()));
     if( poCurve == NULL )
         return NULL;
 
@@ -169,7 +170,7 @@ void OGRSimpleCurve::setCoordinateDimension( int nNewDimension )
 void OGRSimpleCurve::set3D( OGRBoolean bIs3D )
 
 {
-    if (bIs3D)
+    if( bIs3D )
         Make3D();
     else
         Make2D();
@@ -178,7 +179,7 @@ void OGRSimpleCurve::set3D( OGRBoolean bIs3D )
 void OGRSimpleCurve::setMeasured( OGRBoolean bIsMeasured )
 
 {
-    if (bIsMeasured)
+    if( bIsMeasured )
         AddM();
     else
         RemoveM();
@@ -197,6 +198,8 @@ int OGRSimpleCurve::WkbSize() const
     return 5 + 4 + 8 * nPointCount * CoordinateDimension();
 }
 
+//! @cond Doxygen_Suppress
+
 /************************************************************************/
 /*                               Make2D()                               */
 /************************************************************************/
@@ -206,7 +209,7 @@ void OGRSimpleCurve::Make2D()
 {
     if( padfZ != NULL )
     {
-        OGRFree( padfZ );
+        CPLFree( padfZ );
         padfZ = NULL;
     }
     flags &= ~OGR_G_3D;
@@ -222,9 +225,11 @@ void OGRSimpleCurve::Make3D()
     if( padfZ == NULL )
     {
         if( nPointCount == 0 )
-            padfZ = (double *) VSI_CALLOC_VERBOSE(sizeof(double),1);
+            padfZ =
+                static_cast<double *>(VSI_CALLOC_VERBOSE(sizeof(double), 1));
         else
-            padfZ = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nPointCount);
+            padfZ = static_cast<double *>(VSI_CALLOC_VERBOSE(
+                sizeof(double), nPointCount));
         if( padfZ == NULL )
         {
             flags &= ~OGR_G_3D;
@@ -245,7 +250,7 @@ void OGRSimpleCurve::RemoveM()
 {
     if( padfM != NULL )
     {
-        OGRFree( padfM );
+        CPLFree( padfM );
         padfM = NULL;
     }
     flags &= ~OGR_G_MEASURED;
@@ -261,9 +266,11 @@ void OGRSimpleCurve::AddM()
     if( padfM == NULL )
     {
         if( nPointCount == 0 )
-            padfM = (double *) VSI_CALLOC_VERBOSE(sizeof(double),1);
+            padfM =
+                static_cast<double *>(VSI_CALLOC_VERBOSE(sizeof(double), 1));
         else
-            padfM = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nPointCount);
+            padfM = static_cast<double *>(
+                VSI_CALLOC_VERBOSE(sizeof(double), nPointCount));
         if( padfM == NULL )
         {
             flags &= ~OGR_G_MEASURED;
@@ -275,6 +282,8 @@ void OGRSimpleCurve::AddM()
     flags |= OGR_G_MEASURED;
 }
 
+//! @endcond
+
 /************************************************************************/
 /*                              getPoint()                              */
 /************************************************************************/
@@ -288,12 +297,12 @@ void OGRSimpleCurve::AddM()
  * @param poPoint a point to initialize with the fetched point.
  */
 
-void    OGRSimpleCurve::getPoint( int i, OGRPoint * poPoint ) const
+void OGRSimpleCurve::getPoint( int i, OGRPoint * poPoint ) const
 
 {
-    assert( i >= 0 );
-    assert( i < nPointCount );
-    assert( poPoint != NULL );
+    CPLAssert( i >= 0 );
+    CPLAssert( i < nPointCount );
+    CPLAssert( poPoint != NULL );
 
     poPoint->setX( paoPoints[i].x );
     poPoint->setY( paoPoints[i].y );
@@ -417,13 +426,13 @@ void OGRSimpleCurve::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
 
     if( nNewPointCount == 0 )
     {
-        OGRFree( paoPoints );
+        CPLFree( paoPoints );
         paoPoints = NULL;
 
-        OGRFree( padfZ );
+        CPLFree( padfZ );
         padfZ = NULL;
 
-        OGRFree( padfM );
+        CPLFree( padfM );
         padfM = NULL;
 
         nPointCount = 0;
@@ -432,9 +441,10 @@ void OGRSimpleCurve::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
 
     if( nNewPointCount > nPointCount )
     {
-        OGRRawPoint* paoNewPoints = (OGRRawPoint *)
-            VSI_REALLOC_VERBOSE(paoPoints, sizeof(OGRRawPoint) * nNewPointCount);
-        if (paoNewPoints == NULL)
+        OGRRawPoint* paoNewPoints = static_cast<OGRRawPoint *>(
+            VSI_REALLOC_VERBOSE(paoPoints,
+                                sizeof(OGRRawPoint) * nNewPointCount));
+        if( paoNewPoints == NULL )
         {
             return;
         }
@@ -446,9 +456,9 @@ void OGRSimpleCurve::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
 
         if( flags & OGR_G_3D )
         {
-            double* padfNewZ = (double *)
-                VSI_REALLOC_VERBOSE( padfZ, sizeof(double)*nNewPointCount );
-            if (padfNewZ == NULL)
+            double* padfNewZ = static_cast<double *>(
+                VSI_REALLOC_VERBOSE(padfZ, sizeof(double) * nNewPointCount));
+            if( padfNewZ == NULL )
             {
                 return;
             }
@@ -460,9 +470,9 @@ void OGRSimpleCurve::setNumPoints( int nNewPointCount, int bZeroizeNewContent )
 
         if( flags & OGR_G_MEASURED )
         {
-            double* padfNewM = (double *)
-                VSI_REALLOC_VERBOSE( padfM, sizeof(double)*nNewPointCount );
-            if (padfNewM == NULL)
+            double* padfNewM = static_cast<double *>(
+                VSI_REALLOC_VERBOSE(padfM, sizeof(double) * nNewPointCount));
+            if( padfNewM == NULL )
             {
                 return;
             }
@@ -534,7 +544,7 @@ void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn, double zIn )
     if( iPoint >= nPointCount )
     {
         setNumPoints( iPoint+1 );
-        if (nPointCount < iPoint + 1)
+        if( nPointCount < iPoint + 1 )
             return;
     }
 #ifdef DEBUG
@@ -551,6 +561,21 @@ void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn, double zIn )
     }
 }
 
+/**
+ * \brief Set the location of a vertex in line string.
+ *
+ * If iPoint is larger than the number of necessary the number of existing
+ * points in the line string, the point count will be increased to
+ * accommodate the request.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param iPoint the index of the vertex to assign (zero based).
+ * @param xIn input X coordinate to assign.
+ * @param yIn input Y coordinate to assign.
+ * @param mIn input M coordinate to assign (defaults to zero).
+ */
+
 void OGRSimpleCurve::setPointM( int iPoint, double xIn, double yIn, double mIn )
 
 {
@@ -560,7 +585,7 @@ void OGRSimpleCurve::setPointM( int iPoint, double xIn, double yIn, double mIn )
     if( iPoint >= nPointCount )
     {
         setNumPoints( iPoint+1 );
-        if (nPointCount < iPoint + 1)
+        if( nPointCount < iPoint + 1 )
             return;
     }
 #ifdef DEBUG
@@ -577,7 +602,24 @@ void OGRSimpleCurve::setPointM( int iPoint, double xIn, double yIn, double mIn )
     }
 }
 
-void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn, double zIn, double mIn )
+/**
+ * \brief Set the location of a vertex in line string.
+ *
+ * If iPoint is larger than the number of necessary the number of existing
+ * points in the line string, the point count will be increased to
+ * accommodate the request.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param iPoint the index of the vertex to assign (zero based).
+ * @param xIn input X coordinate to assign.
+ * @param yIn input Y coordinate to assign.
+ * @param zIn input Z coordinate to assign (defaults to zero).
+ * @param mIn input M coordinate to assign (defaults to zero).
+ */
+
+void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn,
+                               double zIn, double mIn )
 
 {
     if( !(flags & OGR_G_3D) )
@@ -588,7 +630,7 @@ void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn, double zIn, d
     if( iPoint >= nPointCount )
     {
         setNumPoints( iPoint+1 );
-        if (nPointCount < iPoint + 1)
+        if( nPointCount < iPoint + 1 )
             return;
     }
 #ifdef DEBUG
@@ -609,13 +651,27 @@ void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn, double zIn, d
     }
 }
 
+/**
+ * \brief Set the location of a vertex in line string.
+ *
+ * If iPoint is larger than the number of necessary the number of existing
+ * points in the line string, the point count will be increased to
+ * accommodate the request.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param iPoint the index of the vertex to assign (zero based).
+ * @param xIn input X coordinate to assign.
+ * @param yIn input Y coordinate to assign.
+ */
+
 void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn )
 
 {
     if( iPoint >= nPointCount )
     {
         setNumPoints( iPoint+1 );
-        if (nPointCount < iPoint + 1)
+        if( nPointCount < iPoint + 1 )
             return;
     }
 
@@ -627,6 +683,19 @@ void OGRSimpleCurve::setPoint( int iPoint, double xIn, double yIn )
 /*                                setZ()                                */
 /************************************************************************/
 
+/**
+ * \brief Set the Z of a vertex in line string.
+ *
+ * If iPoint is larger than the number of necessary the number of existing
+ * points in the line string, the point count will be increased to
+ * accommodate the request.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param iPoint the index of the vertex to assign (zero based).
+ * @param zIn input Z coordinate to assign.
+ */
+
 void OGRSimpleCurve::setZ( int iPoint, double zIn )
 {
     if( getCoordinateDimension() == 2 )
@@ -635,7 +704,7 @@ void OGRSimpleCurve::setZ( int iPoint, double zIn )
     if( iPoint >= nPointCount )
     {
         setNumPoints( iPoint+1 );
-        if (nPointCount < iPoint + 1)
+        if( nPointCount < iPoint + 1 )
             return;
     }
 
@@ -647,6 +716,19 @@ void OGRSimpleCurve::setZ( int iPoint, double zIn )
 /*                                setM()                                */
 /************************************************************************/
 
+/**
+ * \brief Set the M of a vertex in line string.
+ *
+ * If iPoint is larger than the number of necessary the number of existing
+ * points in the line string, the point count will be increased to
+ * accommodate the request.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param iPoint the index of the vertex to assign (zero based).
+ * @param mIn input M coordinate to assign.
+ */
+
 void OGRSimpleCurve::setM( int iPoint, double mIn )
 {
     if( !(flags & OGR_G_MEASURED) )
@@ -655,7 +737,7 @@ void OGRSimpleCurve::setM( int iPoint, double mIn )
     if( iPoint >= nPointCount )
     {
         setNumPoints( iPoint+1 );
-        if (nPointCount < iPoint + 1)
+        if( nPointCount < iPoint + 1 )
             return;
     }
 
@@ -678,10 +760,10 @@ void OGRSimpleCurve::setM( int iPoint, double mIn )
  * @param poPoint the point to assign to the new vertex.
  */
 
-void OGRSimpleCurve::addPoint( OGRPoint * poPoint )
+void OGRSimpleCurve::addPoint( const OGRPoint * poPoint )
 
 {
-    if ( poPoint->getCoordinateDimension() < 3 )
+    if( poPoint->getCoordinateDimension() < 3 )
         setPoint( nPointCount, poPoint->getX(), poPoint->getY() );
     else
         setPoint( nPointCount, poPoint->getX(), poPoint->getY(), poPoint->getZ() );
@@ -702,6 +784,7 @@ void OGRSimpleCurve::addPoint( OGRPoint * poPoint )
  * @param x the X coordinate to assign to the new point.
  * @param y the Y coordinate to assign to the new point.
  * @param z the Z coordinate to assign to the new point (defaults to zero).
+ * @param m the M coordinate to assign to the new point (defaults to zero).
  */
 
 void OGRSimpleCurve::addPoint( double x, double y, double z, double m )
@@ -710,12 +793,37 @@ void OGRSimpleCurve::addPoint( double x, double y, double z, double m )
     setPoint( nPointCount, x, y, z, m );
 }
 
+/**
+ * \brief Add a point to a line string.
+ *
+ * The vertex count of the line string is increased by one, and assigned from
+ * the passed location value.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param x the X coordinate to assign to the new point.
+ * @param y the Y coordinate to assign to the new point.
+ * @param z the Z coordinate to assign to the new point (defaults to zero).
+ */
+
 void OGRSimpleCurve::addPoint( double x, double y, double z )
 
 {
     setPoint( nPointCount, x, y, z );
 }
 
+/**
+ * \brief Add a point to a line string.
+ *
+ * The vertex count of the line string is increased by one, and assigned from
+ * the passed location value.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param x the X coordinate to assign to the new point.
+ * @param y the Y coordinate to assign to the new point.
+ */
+
 void OGRSimpleCurve::addPoint( double x, double y )
 
 {
@@ -756,7 +864,7 @@ void OGRSimpleCurve::addPointM( double x, double y, double m )
  *
  * @param nPointsIn number of points being passed in paoPointsIn
  * @param paoPointsIn list of points being assigned.
- * @param padfM the M values that go with the points.
+ * @param padfMIn the M values that go with the points.
  */
 
 void OGRSimpleCurve::setPointsM( int nPointsIn, OGRRawPoint * paoPointsIn,
@@ -764,7 +872,7 @@ void OGRSimpleCurve::setPointsM( int nPointsIn, OGRRawPoint * paoPointsIn,
 
 {
     setNumPoints( nPointsIn, FALSE );
-    if (nPointCount < nPointsIn
+    if( nPointCount < nPointsIn
 #ifdef DEBUG
         || paoPoints == NULL
 #endif
@@ -804,8 +912,8 @@ void OGRSimpleCurve::setPointsM( int nPointsIn, OGRRawPoint * paoPointsIn,
  *
  * @param nPointsIn number of points being passed in paoPointsIn
  * @param paoPointsIn list of points being assigned.
- * @param padfZ the Z values that go with the points.
- * @param padfM the M values that go with the points.
+ * @param padfZIn the Z values that go with the points.
+ * @param padfMIn the M values that go with the points.
  */
 
 void OGRSimpleCurve::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
@@ -813,7 +921,7 @@ void OGRSimpleCurve::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
 
 {
     setNumPoints( nPointsIn, FALSE );
-    if (nPointCount < nPointsIn
+    if( nPointCount < nPointsIn
 #ifdef DEBUG
         || paoPoints == NULL
 #endif
@@ -867,7 +975,7 @@ void OGRSimpleCurve::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
  *
  * @param nPointsIn number of points being passed in paoPointsIn
  * @param paoPointsIn list of points being assigned.
- * @param padfZ the Z values that go with the points (optional, may be NULL).
+ * @param padfZIn the Z values that go with the points (optional, may be NULL).
  */
 
 void OGRSimpleCurve::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
@@ -875,7 +983,7 @@ void OGRSimpleCurve::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
 
 {
     setNumPoints( nPointsIn, FALSE );
-    if (nPointCount < nPointsIn
+    if( nPointCount < nPointsIn
 #ifdef DEBUG
         || paoPoints == NULL
 #endif
@@ -915,7 +1023,7 @@ void OGRSimpleCurve::setPoints( int nPointsIn, OGRRawPoint * paoPointsIn,
  * @param nPointsIn number of points being passed in padfX and padfY.
  * @param padfX list of X coordinates of points being assigned.
  * @param padfY list of Y coordinates of points being assigned.
- * @param padfZ list of Z coordinates of points being assigned (defaults to
+ * @param padfZIn list of Z coordinates of points being assigned (defaults to
  * NULL for 2D objects).
  */
 
@@ -935,7 +1043,7 @@ void OGRSimpleCurve::setPoints( int nPointsIn, double * padfX, double * padfY,
 /*      Assign values.                                                  */
 /* -------------------------------------------------------------------- */
     setNumPoints( nPointsIn, FALSE );
-    if (nPointCount < nPointsIn)
+    if( nPointCount < nPointsIn )
         return;
 
     for( int i = 0; i < nPointsIn; i++ )
@@ -967,7 +1075,7 @@ void OGRSimpleCurve::setPoints( int nPointsIn, double * padfX, double * padfY,
  * @param nPointsIn number of points being passed in padfX and padfY.
  * @param padfX list of X coordinates of points being assigned.
  * @param padfY list of Y coordinates of points being assigned.
- * @param padfM list of M coordinates of points being assigned.
+ * @param padfMIn list of M coordinates of points being assigned.
  */
 
 void OGRSimpleCurve::setPointsM( int nPointsIn, double * padfX, double * padfY,
@@ -986,7 +1094,7 @@ void OGRSimpleCurve::setPointsM( int nPointsIn, double * padfX, double * padfY,
 /*      Assign values.                                                  */
 /* -------------------------------------------------------------------- */
     setNumPoints( nPointsIn, FALSE );
-    if (nPointCount < nPointsIn)
+    if( nPointCount < nPointsIn )
         return;
 
     for( int i = 0; i < nPointsIn; i++ )
@@ -1018,8 +1126,8 @@ void OGRSimpleCurve::setPointsM( int nPointsIn, double * padfX, double * padfY,
  * @param nPointsIn number of points being passed in padfX and padfY.
  * @param padfX list of X coordinates of points being assigned.
  * @param padfY list of Y coordinates of points being assigned.
- * @param padfZ list of Z coordinates of points being assigned.
- * @param padfM list of M coordinates of points being assigned.
+ * @param padfZIn list of Z coordinates of points being assigned.
+ * @param padfMIn list of M coordinates of points being assigned.
  */
 
 void OGRSimpleCurve::setPoints( int nPointsIn, double * padfX, double * padfY,
@@ -1046,7 +1154,7 @@ void OGRSimpleCurve::setPoints( int nPointsIn, double * padfX, double * padfY,
 /*      Assign values.                                                  */
 /* -------------------------------------------------------------------- */
     setNumPoints( nPointsIn, FALSE );
-    if (nPointCount < nPointsIn)
+    if( nPointCount < nPointsIn )
         return;
 
     for( int i = 0; i < nPointsIn; i++ )
@@ -1078,9 +1186,10 @@ void OGRSimpleCurve::setPoints( int nPointsIn, double * padfX, double * padfY,
  * @param padfZOut the Z values that go with the points (optional, may be NULL).
  */
 
-void OGRSimpleCurve::getPoints( OGRRawPoint * paoPointsOut, double * padfZOut ) const
+void OGRSimpleCurve::getPoints( OGRRawPoint * paoPointsOut,
+                                double * padfZOut ) const
 {
-    if ( ! paoPointsOut || nPointCount == 0 )
+    if( !paoPointsOut || nPointCount == 0 )
         return;
 
     memcpy( paoPointsOut, paoPoints, sizeof(OGRRawPoint) * nPointCount );
@@ -1090,14 +1199,13 @@ void OGRSimpleCurve::getPoints( OGRRawPoint * paoPointsOut, double * padfZOut )
 /* -------------------------------------------------------------------- */
     if( padfZOut )
     {
-        if ( padfZ )
+        if( padfZ )
             memcpy( padfZOut, padfZ, sizeof(double) * nPointCount );
         else
             memset( padfZOut, 0, sizeof(double) * nPointCount );
     }
 }
 
-
 /************************************************************************/
 /*                          getPoints()                                 */
 /************************************************************************/
@@ -1108,84 +1216,113 @@ void OGRSimpleCurve::getPoints( OGRRawPoint * paoPointsOut, double * padfZOut )
  * This method copies all points into user arrays. The user provides the
  * stride between 2 consecutive elements of the array.
  *
- * On some CPU architectures, care must be taken so that the arrays are properly aligned.
+ * On some CPU architectures, care must be taken so that the arrays are properly
+ * aligned.
  *
  * There is no SFCOM analog to this method.
  *
- * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount) bytes, may be NULL.
+ * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount)
+ * bytes, may be NULL.
  * @param nXStride the number of bytes between 2 elements of pabyX.
- * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount) bytes, may be NULL.
+ * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount)
+ * bytes, may be NULL.
  * @param nYStride the number of bytes between 2 elements of pabyY.
- * @param pabyZ a buffer of at last size (sizeof(double) * nZStride * nPointCount) bytes, may be NULL.
+ * @param pabyZ a buffer of at last size (sizeof(double) * nZStride *
+ * nPointCount) bytes, may be NULL.
  * @param nZStride the number of bytes between 2 elements of pabyZ.
  *
  * @since OGR 1.9.0
  */
 
 void OGRSimpleCurve::getPoints( void* pabyX, int nXStride,
-                               void* pabyY, int nYStride,
-                               void* pabyZ, int nZStride)  const
+                                void* pabyY, int nYStride,
+                                void* pabyZ, int nZStride ) const
 {
-    int i;
-    if (pabyX != NULL && nXStride == 0)
+    if( pabyX != NULL && nXStride == 0 )
         return;
-    if (pabyY != NULL && nYStride == 0)
+    if( pabyY != NULL && nYStride == 0 )
         return;
-    if (pabyZ != NULL && nZStride == 0)
+    if( pabyZ != NULL && nZStride == 0 )
         return;
-    if (nXStride == 2 * sizeof(double) &&
+    if( nXStride == 2 * sizeof(double) &&
         nYStride == 2 * sizeof(double) &&
-        (char*)pabyY == (char*)pabyX + sizeof(double) &&
-        (pabyZ == NULL || nZStride == sizeof(double)))
+        static_cast<char *>(pabyY) ==
+        static_cast<char *>(pabyX) + sizeof(double) &&
+        (pabyZ == NULL || nZStride == sizeof(double)) )
     {
-        getPoints((OGRRawPoint *)pabyX, (double*)pabyZ);
+        getPoints(static_cast<OGRRawPoint *>(pabyX),
+                  static_cast<double *>(pabyZ));
         return;
     }
-    for(i=0;i<nPointCount;i++)
+    for( int i = 0; i < nPointCount; i++ )
     {
-        if (pabyX) *(double*)((char*)pabyX + i * nXStride) = paoPoints[i].x;
-        if (pabyY) *(double*)((char*)pabyY + i * nYStride) = paoPoints[i].y;
+        if( pabyX )
+            *(double*)(static_cast<char*>(pabyX) + i * nXStride) = paoPoints[i].x;
+        if( pabyY )
+            *(double*)(static_cast<char*>(pabyY) + i * nYStride) = paoPoints[i].y;
     }
 
-    if (pabyZ)
+    if( pabyZ )
     {
-        for(i=0;i<nPointCount;i++)
+        for( int i = 0; i < nPointCount; i++ )
         {
-            *(double*)((char*)pabyZ + i * nZStride) = (padfZ) ? padfZ[i] : 0.0;
+            *(double*)(static_cast<char*>(pabyZ) + i * nZStride) =
+                padfZ ? padfZ[i] : 0.0;
         }
     }
 }
 
+/**
+ * \brief Returns all points of line string.
+ *
+ * This method copies all points into user arrays. The user provides the
+ * stride between 2 consecutive elements of the array.
+ *
+ * On some CPU architectures, care must be taken so that the arrays are properly aligned.
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param pabyX a buffer of at least (sizeof(double) * nXStride * nPointCount) bytes, may be NULL.
+ * @param nXStride the number of bytes between 2 elements of pabyX.
+ * @param pabyY a buffer of at least (sizeof(double) * nYStride * nPointCount) bytes, may be NULL.
+ * @param nYStride the number of bytes between 2 elements of pabyY.
+ * @param pabyZ a buffer of at last size (sizeof(double) * nZStride * nPointCount) bytes, may be NULL.
+ * @param nZStride the number of bytes between 2 elements of pabyZ.
+ * @param pabyM a buffer of at last size (sizeof(double) * nMStride * nPointCount) bytes, may be NULL.
+ * @param nMStride the number of bytes between 2 elements of pabyM.
+ *
+ * @since OGR 2.1.0
+ */
+
 void OGRSimpleCurve::getPoints( void* pabyX, int nXStride,
                                 void* pabyY, int nYStride,
                                 void* pabyZ, int nZStride,
-                                void* pabyM, int nMStride)  const
+                                void* pabyM, int nMStride ) const
 {
-    int i;
-    if (pabyX != NULL && nXStride == 0)
+    if( pabyX != NULL && nXStride == 0 )
         return;
-    if (pabyY != NULL && nYStride == 0)
+    if( pabyY != NULL && nYStride == 0 )
         return;
-    if (pabyZ != NULL && nZStride == 0)
+    if( pabyZ != NULL && nZStride == 0 )
         return;
-    if (pabyM != NULL && nMStride == 0)
+    if( pabyM != NULL && nMStride == 0 )
         return;
-    for(i=0;i<nPointCount;i++)
+    for( int i = 0; i < nPointCount; i++ )
     {
-        if (pabyX) *(double*)((char*)pabyX + i * nXStride) = paoPoints[i].x;
-        if (pabyY) *(double*)((char*)pabyY + i * nYStride) = paoPoints[i].y;
+        if( pabyX ) *(double*)((char*)pabyX + i * nXStride) = paoPoints[i].x;
+        if( pabyY ) *(double*)((char*)pabyY + i * nYStride) = paoPoints[i].y;
     }
 
-    if (pabyZ)
+    if( pabyZ )
     {
-        for(i=0;i<nPointCount;i++)
+        for( int i = 0; i < nPointCount; i++ )
         {
             *(double*)((char*)pabyZ + i * nZStride) = (padfZ) ? padfZ[i] : 0.0;
         }
     }
-    if (pabyM)
+    if( pabyM )
     {
-        for(i=0;i<nPointCount;i++)
+        for( int i = 0; i < nPointCount; i++ )
         {
             *(double*)((char*)pabyM + i * nZStride) = (padfM) ? padfM[i] : 0.0;
         }
@@ -1206,18 +1343,16 @@ void OGRSimpleCurve::getPoints( void* pabyX, int nXStride,
 void OGRSimpleCurve::reversePoints()
 
 {
-    int i;
-
-    for( i = 0; i < nPointCount/2; i++ )
+    for( int i = 0; i < nPointCount/2; i++ )
     {
-        OGRRawPoint sPointTemp = paoPoints[i];
+        const OGRRawPoint sPointTemp = paoPoints[i];
 
         paoPoints[i] = paoPoints[nPointCount-i-1];
         paoPoints[nPointCount-i-1] = sPointTemp;
 
         if( padfZ )
         {
-            double dfZTemp = padfZ[i];
+            const double dfZTemp = padfZ[i];
 
             padfZ[i] = padfZ[nPointCount-i-1];
             padfZ[nPointCount-i-1] = dfZTemp;
@@ -1248,7 +1383,7 @@ void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
 
 {
     int nOtherLineNumPoints = poOtherLine->getNumPoints();
-    if (nOtherLineNumPoints == 0)
+    if( nOtherLineNumPoints == 0 )
         return;
 
 /* -------------------------------------------------------------------- */
@@ -1261,7 +1396,7 @@ void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
         || nStartVertex >= nOtherLineNumPoints
         || nEndVertex >= nOtherLineNumPoints )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return;
     }
 
@@ -1269,10 +1404,10 @@ void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
 /*      Grow this linestring to hold the additional points.             */
 /* -------------------------------------------------------------------- */
     int nOldPoints = nPointCount;
-    int nPointsToAdd = ABS(nEndVertex-nStartVertex) + 1;
+    int nPointsToAdd = std::abs(nEndVertex - nStartVertex) + 1;
 
     setNumPoints( nPointsToAdd + nOldPoints, FALSE );
-    if (nPointCount < nPointsToAdd + nOldPoints
+    if( nPointCount < nPointsToAdd + nOldPoints
 #ifdef DEBUG
         || paoPoints == NULL
 #endif
@@ -1303,9 +1438,7 @@ void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
 /* -------------------------------------------------------------------- */
     else
     {
-        int i;
-
-        for( i = 0; i < nPointsToAdd; i++ )
+        for( int i = 0; i < nPointsToAdd; i++ )
         {
             paoPoints[i+nOldPoints].x =
                 poOtherLine->paoPoints[nStartVertex-i].x;
@@ -1318,7 +1451,7 @@ void OGRSimpleCurve::addSubLineString( const OGRLineString *poOtherLine,
             Make3D();
             if( padfZ != NULL )
             {
-                for( i = 0; i < nPointsToAdd; i++ )
+                for( int i = 0; i < nPointsToAdd; i++ )
                 {
                     padfZ[i+nOldPoints] = poOtherLine->padfZ[nStartVertex-i];
                 }
@@ -1353,12 +1486,11 @@ OGRErr OGRSimpleCurve::importFromWkb( unsigned char * pabyData,
     if( eErr != OGRERR_NONE )
         return eErr;
 
-    /* Check if the wkb stream buffer is big enough to store
-     * fetched number of points.
-     */
-    int dim = CoordinateDimension();
+    // Check if the wkb stream buffer is big enough to store
+    // fetched number of points.
+    const int dim = CoordinateDimension();
     int nPointSize = dim*sizeof(double);
-    if (nNewNumPoints < 0 || nNewNumPoints > INT_MAX / nPointSize)
+    if( nNewNumPoints < 0 || nNewNumPoints > INT_MAX / nPointSize )
         return OGRERR_CORRUPT_DATA;
     int nBufferMinSize = nPointSize * nNewNumPoints;
 
@@ -1370,7 +1502,7 @@ OGRErr OGRSimpleCurve::importFromWkb( unsigned char * pabyData,
     }
 
     setNumPoints( nNewNumPoints, FALSE );
-    if (nPointCount < nNewNumPoints)
+    if( nPointCount < nNewNumPoints )
         return OGRERR_FAILURE;
 
 /* -------------------------------------------------------------------- */
@@ -1445,7 +1577,7 @@ OGRErr OGRSimpleCurve::importFromWkb( unsigned char * pabyData,
 /*      Build a well known binary representation of this object.        */
 /************************************************************************/
 
-OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
+OGRErr OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
                                     unsigned char * pabyData,
                                     OGRwkbVariant eWkbVariant ) const
 
@@ -1464,11 +1596,12 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
     {
         nGType = wkbFlatten(nGType);
         if( Is3D() )
-            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
+            // Explicitly set wkb25DBit.
+            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse);
         if( IsMeasured() )
             nGType = (OGRwkbGeometryType)(nGType | 0x40000000);
     }
-    else if ( eWkbVariant == wkbVariantIso )
+    else if( eWkbVariant == wkbVariantIso )
         nGType = getIsoGeometryType();
 
     if( eByteOrder == wkbNDR )
@@ -1486,11 +1619,9 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* -------------------------------------------------------------------- */
 /*      Copy in the raw data.                                           */
 /* -------------------------------------------------------------------- */
-    int         i;
-
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             memcpy( pabyData + 9 + 32*i, paoPoints+i, 16 );
             memcpy( pabyData + 9 + 16 + 32*i, padfZ+i, 8 );
@@ -1499,7 +1630,7 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
     }
     else if( flags & OGR_G_MEASURED )
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             memcpy( pabyData + 9 + 24*i, paoPoints+i, 16 );
             memcpy( pabyData + 9 + 16 + 24*i, padfM+i, 8 );
@@ -1507,7 +1638,7 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
     }
     else if( flags & OGR_G_3D )
     {
-        for( i = 0; i < nPointCount; i++ )
+        for( int i = 0; i < nPointCount; i++ )
         {
             memcpy( pabyData + 9 + 24*i, paoPoints+i, 16 );
             memcpy( pabyData + 9 + 16 + 24*i, padfZ+i, 8 );
@@ -1521,12 +1652,10 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* -------------------------------------------------------------------- */
     if( OGR_SWAP( eByteOrder ) )
     {
-        int     nCount;
-
-        nCount = CPL_SWAP32( nPointCount );
+        int nCount = CPL_SWAP32( nPointCount );
         memcpy( pabyData+5, &nCount, 4 );
 
-        for( i = CoordinateDimension() * nPointCount - 1; i >= 0; i-- )
+        for( int i = CoordinateDimension() * nPointCount - 1; i >= 0; i-- )
         {
             CPL_SWAP64PTR( pabyData + 9 + 8 * i );
         }
@@ -1545,9 +1674,11 @@ OGRErr  OGRSimpleCurve::exportToWkb( OGRwkbByteOrder eByteOrder,
 OGRErr OGRSimpleCurve::importFromWkt( char ** ppszInput )
 
 {
-    int bHasZ = FALSE, bHasM = FALSE;
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
     bool bIsEmpty = false;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    const OGRErr eErr =
+        importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     flags = 0;
     if( eErr != OGRERR_NONE )
         return eErr;
@@ -1561,7 +1692,7 @@ OGRErr OGRSimpleCurve::importFromWkt( char ** ppszInput )
         return OGRERR_NONE;
     }
 
-    const char  *pszInput = *ppszInput;
+    const char *pszInput = *ppszInput;
 
 /* -------------------------------------------------------------------- */
 /*      Read the point list.                                            */
@@ -1570,7 +1701,8 @@ OGRErr OGRSimpleCurve::importFromWkt( char ** ppszInput )
     nPointCount = 0;
 
     int nMaxPoints = 0;
-    pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM, &flagsFromInput,
+    pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM,
+                                  &flagsFromInput,
                                   &nMaxPoints, &nPointCount );
     if( pszInput == NULL )
         return OGRERR_CORRUPT_DATA;
@@ -1589,18 +1721,21 @@ OGRErr OGRSimpleCurve::importFromWkt( char ** ppszInput )
     return OGRERR_NONE;
 }
 
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                        importFromWKTListOnly()                       */
 /*                                                                      */
 /*      Instantiate from "(x y, x y, ...)"                              */
 /************************************************************************/
 
-OGRErr OGRSimpleCurve::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHasM,
-                                              OGRRawPoint*& paoPointsIn, int& nMaxPointsIn,
+OGRErr OGRSimpleCurve::importFromWKTListOnly( char ** ppszInput,
+                                              int bHasZ, int bHasM,
+                                              OGRRawPoint*& paoPointsIn,
+                                              int& nMaxPointsIn,
                                               double*& padfZIn )
 
 {
-    const char  *pszInput = *ppszInput;
+    const char *pszInput = *ppszInput;
 
 /* -------------------------------------------------------------------- */
 /*      Read the point list.                                            */
@@ -1608,7 +1743,7 @@ OGRErr OGRSimpleCurve::importFromWKTListOnly( char ** ppszInput, int bHasZ, int
     int flagsFromInput = flags;
     int nPointCountRead = 0;
     double *padfMIn = NULL;
-    if( flagsFromInput == 0 ) /* flags was not set, this is not called by us */
+    if( flagsFromInput == 0 )  // Flags was not set, this is not called by us.
     {
         if( bHasM )
             flagsFromInput |= OGR_G_MEASURED;
@@ -1616,12 +1751,13 @@ OGRErr OGRSimpleCurve::importFromWKTListOnly( char ** ppszInput, int bHasZ, int
             flagsFromInput |= OGR_G_3D;
     }
 
-    pszInput = OGRWktReadPointsM( pszInput, &paoPointsIn, &padfZIn, &padfMIn, &flagsFromInput,
+    pszInput = OGRWktReadPointsM( pszInput, &paoPointsIn, &padfZIn, &padfMIn,
+                                  &flagsFromInput,
                                   &nMaxPointsIn, &nPointCountRead );
 
     if( pszInput == NULL )
     {
-        OGRFree( padfMIn );
+        CPLFree( padfMIn );
         return OGRERR_CORRUPT_DATA;
     }
     if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
@@ -1637,9 +1773,9 @@ OGRErr OGRSimpleCurve::importFromWKTListOnly( char ** ppszInput, int bHasZ, int
 
     *ppszInput = (char *) pszInput;
 
-    if (bHasM && bHasZ)
+    if( bHasM && bHasZ )
         setPoints( nPointCountRead, paoPointsIn, padfZIn, padfMIn );
-    else if (bHasM && !bHasZ)
+    else if( bHasM && !bHasZ )
         setPointsM( nPointCountRead, paoPointsIn, padfMIn );
     else
         setPoints( nPointCountRead, paoPointsIn, padfZIn );
@@ -1648,20 +1784,20 @@ OGRErr OGRSimpleCurve::importFromWKTListOnly( char ** ppszInput, int bHasZ, int
 
     return OGRERR_NONE;
 }
+//! @endcond
 
 /************************************************************************/
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
-/*      equivalent.  This could be made a lot more CPU efficient!        */
+/*      equivalent.  This could be made a lot more CPU efficient.       */
 /************************************************************************/
 
 OGRErr OGRSimpleCurve::exportToWkt( char ** ppszDstText,
                                    OGRwkbVariant eWkbVariant ) const
 
 {
-    size_t      nMaxString = static_cast<size_t>(nPointCount) * 40 * 4 + 26;
-    size_t      nRetLen = 0;
+    const size_t nMaxString = static_cast<size_t>(nPointCount) * 40 * 4 + 26;
 
 /* -------------------------------------------------------------------- */
 /*      Handle special empty case.                                      */
@@ -1672,16 +1808,16 @@ OGRErr OGRSimpleCurve::exportToWkt( char ** ppszDstText,
         if( eWkbVariant == wkbVariantIso )
         {
             if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
-                osEmpty.Printf("%s ZM EMPTY",getGeometryName());
+                osEmpty.Printf("%s ZM EMPTY", getGeometryName());
             else if( flags & OGR_G_MEASURED )
-                osEmpty.Printf("%s M EMPTY",getGeometryName());
+                osEmpty.Printf("%s M EMPTY", getGeometryName());
             else if( flags & OGR_G_3D )
-                osEmpty.Printf("%s Z EMPTY",getGeometryName());
+                osEmpty.Printf("%s Z EMPTY", getGeometryName());
             else
-                osEmpty.Printf("%s EMPTY",getGeometryName());
+                osEmpty.Printf("%s EMPTY", getGeometryName());
         }
         else
-            osEmpty.Printf("%s EMPTY",getGeometryName());
+            osEmpty.Printf("%s EMPTY", getGeometryName());
         *ppszDstText = CPLStrdup(osEmpty);
         return OGRERR_NONE;
     }
@@ -1689,7 +1825,7 @@ OGRErr OGRSimpleCurve::exportToWkt( char ** ppszDstText,
 /* -------------------------------------------------------------------- */
 /*      General case.                                                   */
 /* -------------------------------------------------------------------- */
-    *ppszDstText = (char *) VSI_MALLOC_VERBOSE( nMaxString );
+    *ppszDstText = static_cast<char *>(VSI_MALLOC_VERBOSE( nMaxString ));
     if( *ppszDstText == NULL )
         return OGRERR_NOT_ENOUGH_MEMORY;
 
@@ -1712,6 +1848,8 @@ OGRErr OGRSimpleCurve::exportToWkt( char ** ppszDstText,
     if( eWkbVariant != wkbVariantIso )
         hasM = FALSE;
 
+    size_t nRetLen = 0;
+
     for( int i = 0; i < nPointCount; i++ )
     {
         if( nMaxString <= strlen(*ppszDstText+nRetLen) + 32 + nRetLen )
@@ -1756,15 +1894,13 @@ OGRErr OGRSimpleCurve::exportToWkt( char ** ppszDstText,
 double OGRSimpleCurve::get_Length() const
 
 {
-    double      dfLength = 0;
-    int         i;
+    double dfLength = 0.0;
 
-    for( i = 0; i < nPointCount-1; i++ )
+    for( int i = 0; i < nPointCount-1; i++ )
     {
-        double      dfDeltaX, dfDeltaY;
 
-        dfDeltaX = paoPoints[i+1].x - paoPoints[i].x;
-        dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
+        const double dfDeltaX = paoPoints[i+1].x - paoPoints[i].x;
+        const double dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
         dfLength += sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
     }
 
@@ -1800,31 +1936,26 @@ void OGRSimpleCurve::EndPoint( OGRPoint * poPoint ) const
 void OGRSimpleCurve::Value( double dfDistance, OGRPoint * poPoint ) const
 
 {
-    double      dfLength = 0;
-    int         i;
-
     if( dfDistance < 0 )
     {
         StartPoint( poPoint );
         return;
     }
 
-    for( i = 0; i < nPointCount-1; i++ )
-    {
-        double      dfDeltaX, dfDeltaY, dfSegLength;
+    double dfLength = 0.0;
 
-        dfDeltaX = paoPoints[i+1].x - paoPoints[i].x;
-        dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
-        dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
+    for( int i = 0; i < nPointCount-1; i++ )
+    {
+        const double dfDeltaX = paoPoints[i+1].x - paoPoints[i].x;
+        const double dfDeltaY = paoPoints[i+1].y - paoPoints[i].y;
+        const double dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
 
-        if (dfSegLength > 0)
+        if( dfSegLength > 0 )
         {
             if( (dfLength <= dfDistance) && ((dfLength + dfSegLength) >=
                                              dfDistance) )
             {
-                double      dfRatio;
-
-                dfRatio = (dfDistance - dfLength) / dfSegLength;
+                double dfRatio = (dfDistance - dfLength) / dfSegLength;
 
                 poPoint->setX( paoPoints[i].x * (1 - dfRatio)
                                + paoPoints[i+1].x * dfRatio );
@@ -1848,7 +1979,7 @@ void OGRSimpleCurve::Value( double dfDistance, OGRPoint * poPoint ) const
 /************************************************************************/
 /*                              Project()                               */
 /*                                                                      */
-/* Return distance of point projected on line from origin of this line  */
+/* Return distance of point projected on line from origin of this line. */
 /************************************************************************/
 
 /**
@@ -1868,14 +1999,13 @@ void OGRSimpleCurve::Value( double dfDistance, OGRPoint * poPoint ) const
 * @since OGR 1.11.0
 */
 
-/* GEOS >= 3.2.0 for project capability */
+// GEOS >= 3.2.0 for project capability.
 #if defined(HAVE_GEOS)
 #if GEOS_VERSION_MAJOR > 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR >= 2)
 #define HAVE_GEOS_PROJECT
 #endif
 #endif
 
-
 double OGRSimpleCurve::Project(const OGRPoint *
 #ifdef HAVE_GEOS_PROJECT
                                 poPoint
@@ -1885,12 +2015,9 @@ double OGRSimpleCurve::Project(const OGRPoint *
 {
     double dfResult = -1;
 #ifndef HAVE_GEOS_PROJECT
-
-
     CPLError(CE_Failure, CPLE_NotSupported,
         "GEOS support not enabled.");
     return dfResult;
-
 #else
     GEOSGeom hThisGeosGeom = NULL;
     GEOSGeom hPointGeosGeom = NULL;
@@ -1898,7 +2025,7 @@ double OGRSimpleCurve::Project(const OGRPoint *
     GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
     hThisGeosGeom = exportToGEOS(hGEOSCtxt);
     hPointGeosGeom = poPoint->exportToGEOS(hGEOSCtxt);
-    if (hThisGeosGeom != NULL && hPointGeosGeom != NULL)
+    if( hThisGeosGeom != NULL && hPointGeosGeom != NULL )
     {
         dfResult = GEOSProject_r(hGEOSCtxt, hThisGeosGeom, hPointGeosGeom);
     }
@@ -1908,16 +2035,15 @@ double OGRSimpleCurve::Project(const OGRPoint *
 
     return dfResult;
 
-#endif /* HAVE_GEOS */
+#endif  // HAVE_GEOS
 }
 
 /************************************************************************/
 /*                            getSubLine()                              */
 /*                                                                      */
-/*  Extracts a portion of this OGRLineString into a new OGRLineString   */
+/*  Extracts a portion of this OGRLineString into a new OGRLineString.  */
 /************************************************************************/
 
-
 /**
 * \brief Get the portion of linestring.
 *
@@ -1934,78 +2060,73 @@ double OGRSimpleCurve::Project(const OGRPoint *
 * @since OGR 1.11.0
 */
 
-
-OGRLineString* OGRSimpleCurve::getSubLine(double dfDistanceFrom, double dfDistanceTo, int bAsRatio) const
+OGRLineString* OGRSimpleCurve::getSubLine(double dfDistanceFrom,
+                                          double dfDistanceTo,
+                                          int bAsRatio) const
 
 {
-    OGRLineString       *poNewLineString;
-    double      dfLength = 0;
-    int         i;
-
-    poNewLineString = new OGRLineString();
+    OGRLineString *poNewLineString = new OGRLineString();
 
     poNewLineString->assignSpatialReference(getSpatialReference());
-    //poNewLineString->setPoints(nPointCount, paoPoints, padfZ);
     poNewLineString->setCoordinateDimension(getCoordinateDimension());
 
-    double dfLen = get_Length();
-    if (bAsRatio == TRUE)
+    const double dfLen = get_Length();
+    if( bAsRatio == TRUE )
     {
-        //convert to real distance
+        // Convert to real distance.
         dfDistanceFrom *= dfLen;
         dfDistanceTo *= dfLen;
     }
 
-    if (dfDistanceFrom < 0)
+    if( dfDistanceFrom < 0 )
         dfDistanceFrom = 0;
-    if (dfDistanceTo > dfLen)
+    if( dfDistanceTo > dfLen )
         dfDistanceTo = dfLen;
 
-    if ( dfDistanceFrom > dfDistanceTo || dfDistanceFrom >= dfLen)
+    if( dfDistanceFrom > dfDistanceTo || dfDistanceFrom >= dfLen )
     {
         CPLError(CE_Failure, CPLE_IllegalArg, "Input distances are invalid.");
 
         return NULL;
     }
 
-    //get first point
+    double dfLength = 0.0;
 
-    if (dfDistanceFrom == 0)
+    // Get first point.
+
+    int i = 0;  // Used after if blocks.
+    if( dfDistanceFrom == 0 )
     {
-        if (getCoordinateDimension() == 3)
+        if( getCoordinateDimension() == 3 )
             poNewLineString->addPoint(paoPoints[0].x, paoPoints[0].y, padfZ[0]);
         else
             poNewLineString->addPoint(paoPoints[0].x, paoPoints[0].y);
-
-        i = 0;
     }
     else
     {
-        for (i = 0; i < nPointCount - 1; i++)
+        for( i = 0; i < nPointCount - 1; i++ )
         {
-            double      dfDeltaX, dfDeltaY, dfSegLength;
-
-            dfDeltaX = paoPoints[i + 1].x - paoPoints[i].x;
-            dfDeltaY = paoPoints[i + 1].y - paoPoints[i].y;
-            dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
+            const double dfDeltaX = paoPoints[i + 1].x - paoPoints[i].x;
+            const double dfDeltaY = paoPoints[i + 1].y - paoPoints[i].y;
+            const double dfSegLength =
+                sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
 
-            double dfX, dfY, dfRatio;
-
-            if (dfSegLength > 0)
+            if( dfSegLength > 0 )
             {
-                if ((dfLength <= dfDistanceFrom) && ((dfLength + dfSegLength) >=
-                    dfDistanceFrom))
+                if( (dfLength <= dfDistanceFrom) && ((dfLength + dfSegLength) >=
+                    dfDistanceFrom) )
                 {
-                    dfRatio = (dfDistanceFrom - dfLength) / dfSegLength;
+                    double dfRatio = (dfDistanceFrom - dfLength) / dfSegLength;
 
-                    dfX = paoPoints[i].x * (1 - dfRatio)
+                    double dfX = paoPoints[i].x * (1 - dfRatio)
                         + paoPoints[i + 1].x * dfRatio;
-                    dfY = paoPoints[i].y * (1 - dfRatio)
+                    double dfY = paoPoints[i].y * (1 - dfRatio)
                         + paoPoints[i + 1].y * dfRatio;
 
-                    if (getCoordinateDimension() == 3)
+                    if( getCoordinateDimension() == 3 )
                     {
-                        poNewLineString->addPoint(dfX, dfY, padfZ[i] * (1 - dfRatio)
+                        poNewLineString->
+                            addPoint(dfX, dfY, padfZ[i] * (1 - dfRatio)
                         + padfZ[i+1] * dfRatio);
                     }
                     else
@@ -2013,9 +2134,9 @@ OGRLineString* OGRSimpleCurve::getSubLine(double dfDistanceFrom, double dfDistan
                         poNewLineString->addPoint(dfX, dfY);
                     }
 
-                    //check if dfDistanceTo is in same segment
-                    if ((dfLength <= dfDistanceTo) && ((dfLength + dfSegLength) >=
-                        dfDistanceTo))
+                    // Check if dfDistanceTo is in same segment.
+                    if( dfLength <= dfDistanceTo &&
+                        (dfLength + dfSegLength) >= dfDistanceTo )
                     {
                         dfRatio = (dfDistanceTo - dfLength) / dfSegLength;
 
@@ -2024,17 +2145,18 @@ OGRLineString* OGRSimpleCurve::getSubLine(double dfDistanceFrom, double dfDistan
                         dfY = paoPoints[i].y * (1 - dfRatio)
                             + paoPoints[i + 1].y * dfRatio;
 
-                        if (getCoordinateDimension() == 3)
+                        if( getCoordinateDimension() == 3 )
                         {
-                            poNewLineString->addPoint(dfX, dfY, padfZ[i] * (1 - dfRatio)
-                                + padfZ[i + 1] * dfRatio);
+                            poNewLineString->
+                                addPoint(dfX, dfY, padfZ[i] * (1 - dfRatio)
+                                         + padfZ[i + 1] * dfRatio);
                         }
                         else
                         {
                             poNewLineString->addPoint(dfX, dfY);
                         }
 
-                        if (poNewLineString->getNumPoints() < 2)
+                        if( poNewLineString->getNumPoints() < 2 )
                         {
                             delete poNewLineString;
                             poNewLineString = NULL;
@@ -2052,35 +2174,31 @@ OGRLineString* OGRSimpleCurve::getSubLine(double dfDistanceFrom, double dfDistan
         }
     }
 
-    //add points
-    for (; i < nPointCount - 1; i++)
+    // Add points.
+    for( ; i < nPointCount - 1; i++ )
     {
-        double      dfDeltaX, dfDeltaY, dfSegLength;
-
-        if (getCoordinateDimension() == 3)
+        if( getCoordinateDimension() == 3 )
             poNewLineString->addPoint(paoPoints[i].x, paoPoints[i].y, padfZ[i]);
         else
             poNewLineString->addPoint(paoPoints[i].x, paoPoints[i].y);
 
-        dfDeltaX = paoPoints[i + 1].x - paoPoints[i].x;
-        dfDeltaY = paoPoints[i + 1].y - paoPoints[i].y;
-        dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
-
-        double dfX, dfY, dfRatio;
+        const double dfDeltaX = paoPoints[i + 1].x - paoPoints[i].x;
+        const double dfDeltaY = paoPoints[i + 1].y - paoPoints[i].y;
+        const double dfSegLength = sqrt(dfDeltaX*dfDeltaX + dfDeltaY*dfDeltaY);
 
-        if (dfSegLength > 0)
+        if( dfSegLength > 0 )
         {
-            if ((dfLength <= dfDistanceTo) && ((dfLength + dfSegLength) >=
-                dfDistanceTo))
+            if( (dfLength <= dfDistanceTo) && ((dfLength + dfSegLength) >=
+                dfDistanceTo) )
             {
-                dfRatio = (dfDistanceTo - dfLength) / dfSegLength;
+                const double dfRatio = (dfDistanceTo - dfLength) / dfSegLength;
 
-                dfX = paoPoints[i].x * (1 - dfRatio)
+                const double dfX = paoPoints[i].x * (1 - dfRatio)
                     + paoPoints[i + 1].x * dfRatio;
-                dfY = paoPoints[i].y * (1 - dfRatio)
+                const double dfY = paoPoints[i].y * (1 - dfRatio)
                     + paoPoints[i + 1].y * dfRatio;
 
-                if (getCoordinateDimension() == 3)
+                if( getCoordinateDimension() == 3 )
                     poNewLineString->addPoint(dfX, dfY, padfZ[i] * (1 - dfRatio)
                     + padfZ[i + 1] * dfRatio);
                 else
@@ -2093,13 +2211,17 @@ OGRLineString* OGRSimpleCurve::getSubLine(double dfDistanceFrom, double dfDistan
         }
     }
 
-
-    if (getCoordinateDimension() == 3)
-        poNewLineString->addPoint(paoPoints[nPointCount - 1].x, paoPoints[nPointCount - 1].y, padfZ[nPointCount - 1]);
+    if( getCoordinateDimension() == 3 )
+        poNewLineString->
+            addPoint(paoPoints[nPointCount - 1].x,
+                     paoPoints[nPointCount - 1].y,
+                     padfZ[nPointCount - 1]);
     else
-        poNewLineString->addPoint(paoPoints[nPointCount - 1].x, paoPoints[nPointCount - 1].y);
+        poNewLineString->
+            addPoint(paoPoints[nPointCount - 1].x,
+                     paoPoints[nPointCount - 1].y);
 
-    if (poNewLineString->getNumPoints() < 2)
+    if( poNewLineString->getNumPoints() < 2 )
     {
         delete poNewLineString;
         poNewLineString = NULL;
@@ -2115,19 +2237,19 @@ OGRLineString* OGRSimpleCurve::getSubLine(double dfDistanceFrom, double dfDistan
 void OGRSimpleCurve::getEnvelope( OGREnvelope * psEnvelope ) const
 
 {
-    double      dfMinX, dfMinY, dfMaxX, dfMaxY;
-
     if( IsEmpty() )
     {
-        psEnvelope->MinX = 0;
-        psEnvelope->MaxX = 0;
-        psEnvelope->MinY = 0;
-        psEnvelope->MaxY = 0;
+        psEnvelope->MinX = 0.0;
+        psEnvelope->MaxX = 0.0;
+        psEnvelope->MinY = 0.0;
+        psEnvelope->MaxY = 0.0;
         return;
     }
 
-    dfMinX = dfMaxX = paoPoints[0].x;
-    dfMinY = dfMaxY = paoPoints[0].y;
+    double dfMinX = paoPoints[0].x;
+    double dfMaxX = paoPoints[0].x;
+    double dfMinY = paoPoints[0].y;
+    double dfMaxY = paoPoints[0].y;
 
     for( int iPoint = 1; iPoint < nPointCount; iPoint++ )
     {
@@ -2147,7 +2269,6 @@ void OGRSimpleCurve::getEnvelope( OGREnvelope * psEnvelope ) const
     psEnvelope->MaxY = dfMaxY;
 }
 
-
 /************************************************************************/
 /*                            getEnvelope()                             */
 /************************************************************************/
@@ -2157,16 +2278,15 @@ void OGRSimpleCurve::getEnvelope( OGREnvelope3D * psEnvelope ) const
 {
     getEnvelope((OGREnvelope*)psEnvelope);
 
-    double      dfMinZ, dfMaxZ;
-
     if( IsEmpty() || padfZ == NULL )
     {
-        psEnvelope->MinZ = 0;
-        psEnvelope->MaxZ = 0;
+        psEnvelope->MinZ = 0.0;
+        psEnvelope->MaxZ = 0.0;
         return;
     }
 
-    dfMinZ = dfMaxZ = padfZ[0];
+    double dfMinZ = padfZ[0];
+    double dfMaxZ = padfZ[0];
 
     for( int iPoint = 1; iPoint < nPointCount; iPoint++ )
     {
@@ -2196,9 +2316,9 @@ OGRBoolean OGRSimpleCurve::Equals( OGRGeometry * poOther ) const
     if( IsEmpty() && poOther->IsEmpty() )
         return TRUE;
 
-    // we should eventually test the SRS.
+    // TODO(schwehr): Test the SRS.
 
-    OGRSimpleCurve       *poOLine = (OGRSimpleCurve *) poOther;
+    OGRSimpleCurve *poOLine = (OGRSimpleCurve *) poOther;
     if( getNumPoints() != poOLine->getNumPoints() )
         return FALSE;
 
@@ -2220,21 +2340,16 @@ OGRBoolean OGRSimpleCurve::Equals( OGRGeometry * poOther ) const
 OGRErr OGRSimpleCurve::transform( OGRCoordinateTransformation *poCT )
 
 {
-#ifdef DISABLE_OGRGEOM_TRANSFORM
-    return OGRERR_FAILURE;
-#else
-    double      *xyz;
-    int         *pabSuccess;
-    int         i, j;
-
 /* -------------------------------------------------------------------- */
 /*   Make a copy of the points to operate on, so as to be able to       */
 /*   keep only valid reprojected points if partial reprojection enabled */
 /*   or keeping intact the original geometry if only full reprojection  */
 /*   allowed.                                                           */
 /* -------------------------------------------------------------------- */
-    xyz = (double *) VSI_MALLOC_VERBOSE(sizeof(double) * nPointCount * 3);
-    pabSuccess = (int *) VSI_CALLOC_VERBOSE(sizeof(int), nPointCount);
+    double *xyz = static_cast<double *>(
+        VSI_MALLOC_VERBOSE(sizeof(double) * nPointCount * 3));
+    int *pabSuccess = static_cast<int *>(
+        VSI_CALLOC_VERBOSE(sizeof(int), nPointCount));
     if( xyz == NULL || pabSuccess == NULL )
     {
         VSIFree(xyz);
@@ -2242,9 +2357,9 @@ OGRErr OGRSimpleCurve::transform( OGRCoordinateTransformation *poCT )
         return OGRERR_NOT_ENOUGH_MEMORY;
     }
 
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
-        xyz[i  ] = paoPoints[i].x;
+        xyz[i] = paoPoints[i].x;
         xyz[i+nPointCount] = paoPoints[i].y;
         if( padfZ )
             xyz[i+nPointCount*2] = padfZ[i];
@@ -2260,39 +2375,43 @@ OGRErr OGRSimpleCurve::transform( OGRCoordinateTransformation *poCT )
 
     const char* pszEnablePartialReprojection = NULL;
 
-    for( i = 0, j = 0; i < nPointCount; i++ )
+    int j = 0;  // Used after for.
+    for( int i = 0; i < nPointCount; i++ )
     {
-        if (pabSuccess[i])
+        if( pabSuccess[i] )
         {
             xyz[j] = xyz[i];
             xyz[j+nPointCount] = xyz[i+nPointCount];
             xyz[j+2*nPointCount] = xyz[i+2*nPointCount];
-            j ++;
+            j++;
         }
         else
         {
-            if (pszEnablePartialReprojection == NULL)
+            if( pszEnablePartialReprojection == NULL )
                 pszEnablePartialReprojection =
                     CPLGetConfigOption("OGR_ENABLE_PARTIAL_REPROJECTION", NULL);
-            if (pszEnablePartialReprojection == NULL)
+            if( pszEnablePartialReprojection == NULL )
             {
                 static bool bHasWarned = false;
-                if (!bHasWarned)
+                if( !bHasWarned )
                 {
-                    /* Check that there is at least one valid reprojected point */
-                    /* and issue an error giving an hint to use OGR_ENABLE_PARTIAL_REPROJECTION */
-                    bool bHasOneValidPoint = (j != 0);
+                    // Check that there is at least one valid reprojected point
+                    // and issue an error giving an hint to use
+                    // OGR_ENABLE_PARTIAL_REPROJECTION.
+                    bool bHasOneValidPoint = j != 0;
                     for( ; i < nPointCount && !bHasOneValidPoint; i++ )
                     {
-                        if (pabSuccess[i])
+                        if( pabSuccess[i] )
                             bHasOneValidPoint = true;
                     }
-                    if (bHasOneValidPoint)
+                    if( bHasOneValidPoint )
                     {
                         bHasWarned = true;
                         CPLError(CE_Failure, CPLE_AppDefined,
-                                "Full reprojection failed, but partial is possible if you define "
-                                "OGR_ENABLE_PARTIAL_REPROJECTION configuration option to TRUE");
+                                 "Full reprojection failed, but partial is "
+                                 "possible if you define "
+                                 "OGR_ENABLE_PARTIAL_REPROJECTION "
+                                 "configuration option to TRUE");
                     }
                 }
 
@@ -2300,7 +2419,7 @@ OGRErr OGRSimpleCurve::transform( OGRCoordinateTransformation *poCT )
                 CPLFree( pabSuccess );
                 return OGRERR_FAILURE;
             }
-            else if (!CSLTestBoolean(pszEnablePartialReprojection))
+            else if( !CPLTestBool(pszEnablePartialReprojection) )
             {
                 CPLFree( xyz );
                 CPLFree( pabSuccess );
@@ -2309,7 +2428,7 @@ OGRErr OGRSimpleCurve::transform( OGRCoordinateTransformation *poCT )
         }
     }
 
-    if (j == 0 && nPointCount != 0)
+    if( j == 0 && nPointCount != 0 )
     {
         CPLFree( xyz );
         CPLFree( pabSuccess );
@@ -2324,14 +2443,13 @@ OGRErr OGRSimpleCurve::transform( OGRCoordinateTransformation *poCT )
     assignSpatialReference( poCT->GetTargetCS() );
 
     return OGRERR_NONE;
-#endif
 }
 
 /************************************************************************/
 /*                               IsEmpty()                              */
 /************************************************************************/
 
-OGRBoolean OGRSimpleCurve::IsEmpty(  ) const
+OGRBoolean OGRSimpleCurve::IsEmpty() const
 {
     return (nPointCount == 0);
 }
@@ -2342,7 +2460,7 @@ OGRBoolean OGRSimpleCurve::IsEmpty(  ) const
 
 void OGRSimpleCurve::segmentize( double dfMaxLength )
 {
-    if (dfMaxLength <= 0)
+    if( dfMaxLength <= 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "dfMaxLength must be strictly positive");
@@ -2351,65 +2469,71 @@ void OGRSimpleCurve::segmentize( double dfMaxLength )
     if( nPointCount < 2 )
         return;
 
-    /* So as to make sure that the same line followed in both directions */
-    /* result in the same segmentized line */
-    if ( paoPoints[0].x < paoPoints[nPointCount - 1].x ||
-         (paoPoints[0].x == paoPoints[nPointCount - 1].x &&
-          paoPoints[0].y < paoPoints[nPointCount - 1].y) )
+    // So as to make sure that the same line followed in both directions
+    // result in the same segmentized line.
+    if( paoPoints[0].x < paoPoints[nPointCount - 1].x ||
+        (paoPoints[0].x == paoPoints[nPointCount - 1].x &&
+         paoPoints[0].y < paoPoints[nPointCount - 1].y) )
     {
         reversePoints();
         segmentize(dfMaxLength);
         reversePoints();
     }
 
-    int i;
     OGRRawPoint* paoNewPoints = NULL;
     double* padfNewZ = NULL;
     int nNewPointCount = 0;
-    double dfSquareMaxLength = dfMaxLength * dfMaxLength;
+    const double dfSquareMaxLength = dfMaxLength * dfMaxLength;
     const int nCoordinateDimension = getCoordinateDimension();
 
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
-        paoNewPoints = (OGRRawPoint *)
-            OGRRealloc(paoNewPoints, sizeof(OGRRawPoint) * (nNewPointCount + 1));
+        paoNewPoints = static_cast<OGRRawPoint *>(
+            CPLRealloc(paoNewPoints,
+                       sizeof(OGRRawPoint) * (nNewPointCount + 1)));
         paoNewPoints[nNewPointCount] = paoPoints[i];
 
         if( nCoordinateDimension == 3 )
         {
-            padfNewZ = (double *)
-                OGRRealloc(padfNewZ, sizeof(double) * (nNewPointCount + 1));
+            padfNewZ = static_cast<double *>(
+                CPLRealloc(padfNewZ, sizeof(double) * (nNewPointCount + 1)));
             padfNewZ[nNewPointCount] = padfZ[i];
         }
 
         nNewPointCount++;
 
-        if (i == nPointCount - 1)
+        if( i == nPointCount - 1 )
             break;
 
-        double dfX = paoPoints[i+1].x - paoPoints[i].x;
-        double dfY = paoPoints[i+1].y - paoPoints[i].y;
-        double dfSquareDist = dfX * dfX + dfY * dfY;
-        if (dfSquareDist > dfSquareMaxLength)
+        const double dfX = paoPoints[i+1].x - paoPoints[i].x;
+        const double dfY = paoPoints[i+1].y - paoPoints[i].y;
+        const double dfSquareDist = dfX * dfX + dfY * dfY;
+        if( dfSquareDist > dfSquareMaxLength )
         {
-            int nIntermediatePoints = (int)floor(sqrt(dfSquareDist / dfSquareMaxLength));
-            int j;
+            const int nIntermediatePoints =
+                static_cast<int>(floor(sqrt(dfSquareDist / dfSquareMaxLength)));
 
-            paoNewPoints = (OGRRawPoint *)
-                OGRRealloc(paoNewPoints, sizeof(OGRRawPoint) * (nNewPointCount + nIntermediatePoints));
+            paoNewPoints = static_cast<OGRRawPoint *>(
+                CPLRealloc(paoNewPoints,
+                           sizeof(OGRRawPoint) * (nNewPointCount +
+                                                  nIntermediatePoints)));
             if( nCoordinateDimension == 3 )
             {
-                padfNewZ = (double *)
-                    OGRRealloc(padfNewZ, sizeof(double) * (nNewPointCount + nIntermediatePoints));
+                padfNewZ = static_cast<double *>(
+                    CPLRealloc(padfNewZ,
+                               sizeof(double) * (nNewPointCount +
+                                                 nIntermediatePoints)));
             }
 
-            for(j=1;j<=nIntermediatePoints;j++)
+            for( int j = 1; j <= nIntermediatePoints; j++ )
             {
-                paoNewPoints[nNewPointCount + j - 1].x = paoPoints[i].x + j * dfX / (nIntermediatePoints + 1);
-                paoNewPoints[nNewPointCount + j - 1].y = paoPoints[i].y + j * dfY / (nIntermediatePoints + 1);
+                paoNewPoints[nNewPointCount + j - 1].x =
+                    paoPoints[i].x + j * dfX / (nIntermediatePoints + 1);
+                paoNewPoints[nNewPointCount + j - 1].y =
+                    paoPoints[i].y + j * dfY / (nIntermediatePoints + 1);
                 if( nCoordinateDimension == 3 )
                 {
-                    /* No interpolation */
+                    // No interpolation.
                     padfNewZ[nNewPointCount + j - 1] = padfZ[i];
                 }
             }
@@ -2418,13 +2542,13 @@ void OGRSimpleCurve::segmentize( double dfMaxLength )
         }
     }
 
-    OGRFree(paoPoints);
+    CPLFree(paoPoints);
     paoPoints = paoNewPoints;
     nPointCount = nNewPointCount;
 
     if( nCoordinateDimension == 3 )
     {
-        OGRFree(padfZ);
+        CPLFree(padfZ);
         padfZ = padfNewZ;
     }
 }
@@ -2435,12 +2559,9 @@ void OGRSimpleCurve::segmentize( double dfMaxLength )
 
 void OGRSimpleCurve::swapXY()
 {
-    int i;
-    for( i = 0; i < nPointCount; i++ )
+    for( int i = 0; i < nPointCount; i++ )
     {
-        double dfTemp = paoPoints[i].x;
-        paoPoints[i].x = paoPoints[i].y;
-        paoPoints[i].y = dfTemp;
+        std::swap(paoPoints[i].x, paoPoints[i].y);
     }
 }
 
@@ -2454,9 +2575,11 @@ class OGRSimpleCurvePointIterator: public OGRPointIterator
         int                   iCurPoint;
 
     public:
-        OGRSimpleCurvePointIterator(const OGRSimpleCurve* poSCIn) : poSC(poSCIn), iCurPoint(0) {}
+        explicit OGRSimpleCurvePointIterator(const OGRSimpleCurve* poSCIn) :
+            poSC(poSCIn),
+            iCurPoint(0) {}
 
-        virtual OGRBoolean getNextPoint(OGRPoint* p);
+        virtual OGRBoolean getNextPoint( OGRPoint* p ) override;
 };
 
 /************************************************************************/
@@ -2468,7 +2591,7 @@ OGRBoolean OGRSimpleCurvePointIterator::getNextPoint(OGRPoint* p)
     if( iCurPoint >= poSC->getNumPoints() )
         return FALSE;
     poSC->getPoint(iCurPoint, p);
-    iCurPoint ++;
+    iCurPoint++;
     return TRUE;
 }
 
@@ -2489,10 +2612,7 @@ OGRPointIterator* OGRSimpleCurve::getPointIterator() const
  * \brief Create an empty line string.
  */
 
-OGRLineString::OGRLineString()
-
-{
-}
+OGRLineString::OGRLineString() {}
 
 /************************************************************************/
 /*                  OGRLineString( const OGRLineString& )               */
@@ -2509,17 +2629,13 @@ OGRLineString::OGRLineString()
 
 OGRLineString::OGRLineString( const OGRLineString& other ) :
     OGRSimpleCurve( other )
-{
-}
+{}
 
 /************************************************************************/
 /*                          ~OGRLineString()                            */
 /************************************************************************/
 
-OGRLineString::~OGRLineString()
-
-{
-}
+OGRLineString::~OGRLineString() {}
 
 /************************************************************************/
 /*                    operator=( const OGRLineString& )                 */
@@ -2552,7 +2668,7 @@ OGRwkbGeometryType OGRLineString::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbLineStringZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbLineStringM;
     else if( flags & OGR_G_3D )
         return wkbLineString25D;
@@ -2574,10 +2690,18 @@ const char * OGRLineString::getGeometryName() const
 /*                          curveToLine()                               */
 /************************************************************************/
 
-OGRLineString* OGRLineString::CurveToLine(CPL_UNUSED double dfMaxAngleStepSizeDegrees,
-                                          CPL_UNUSED const char* const* papszOptions) const
+OGRLineString* OGRLineString::CurveToLine(
+    CPL_UNUSED double /* dfMaxAngleStepSizeDegrees */,
+    CPL_UNUSED const char* const* /* papszOptions */ ) const
 {
-    return (OGRLineString*)clone();
+    // Downcast.
+    OGRLineString * poLineString = dynamic_cast<OGRLineString *>(clone());
+    if( poLineString == NULL )
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRLineString.");
+    }
+    return poLineString;
 }
 
 /************************************************************************/
@@ -2598,20 +2722,20 @@ OGRLineString* OGRLineString::CurveToLine(CPL_UNUSED double dfMaxAngleStepSizeDe
 double OGRSimpleCurve::get_LinearArea() const
 
 {
-    double dfAreaSum;
-    int i;
-
     if( nPointCount < 2 )
         return 0;
 
-    dfAreaSum = paoPoints[0].x * (paoPoints[1].y - paoPoints[nPointCount-1].y);
+    double dfAreaSum =
+        paoPoints[0].x * (paoPoints[1].y - paoPoints[nPointCount-1].y);
 
-    for( i = 1; i < nPointCount-1; i++ )
+    for( int i = 1; i < nPointCount-1; i++ )
     {
         dfAreaSum += paoPoints[i].x * (paoPoints[i+1].y - paoPoints[i-1].y);
     }
 
-    dfAreaSum += paoPoints[nPointCount-1].x * (paoPoints[0].y - paoPoints[nPointCount-2].y);
+    dfAreaSum +=
+        paoPoints[nPointCount-1].x *
+        (paoPoints[0].y - paoPoints[nPointCount-2].y);
 
     return 0.5 * fabs(dfAreaSum);
 }
@@ -2620,7 +2744,8 @@ double OGRSimpleCurve::get_LinearArea() const
 /*                             getCurveGeometry()                       */
 /************************************************************************/
 
-OGRGeometry* OGRLineString::getCurveGeometry(const char* const* papszOptions) const
+OGRGeometry *
+OGRLineString::getCurveGeometry( const char* const* papszOptions ) const
 {
     return OGRGeometryFactory::curveFromLineString(this, papszOptions);
 }
@@ -2628,10 +2753,10 @@ OGRGeometry* OGRLineString::getCurveGeometry(const char* const* papszOptions) co
 /************************************************************************/
 /*                      TransferMembersAndDestroy()                     */
 /************************************************************************/
-
+//! @cond Doxygen_Suppress
 OGRLineString* OGRLineString::TransferMembersAndDestroy(
-                                            OGRLineString* poSrc,
-                                            OGRLineString* poDst)
+    OGRLineString* poSrc,
+    OGRLineString* poDst )
 {
     poDst->set3D(poSrc->Is3D());
     poDst->setMeasured(poSrc->IsMeasured());
@@ -2645,7 +2770,7 @@ OGRLineString* OGRLineString::TransferMembersAndDestroy(
     delete poSrc;
     return poDst;
 }
-
+//! @endcond
 /************************************************************************/
 /*                         CastToLinearRing()                           */
 /************************************************************************/
@@ -2660,22 +2785,34 @@ OGRLineString* OGRLineString::TransferMembersAndDestroy(
  * @return new geometry.
  */
 
-OGRLinearRing* OGRLineString::CastToLinearRing(OGRLineString* poLS)
+OGRLinearRing* OGRLineString::CastToLinearRing( OGRLineString* poLS )
 {
     if( poLS->nPointCount < 2 || !poLS->get_IsClosed() )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot convert non-closed linestring to linearring");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot convert non-closed linestring to linearring");
         delete poLS;
         return NULL;
     }
-    return (OGRLinearRing*)TransferMembersAndDestroy(poLS, new OGRLinearRing());
+    // Downcast.
+    OGRLinearRing * poRing = dynamic_cast<OGRLinearRing *>(
+        TransferMembersAndDestroy(poLS, new OGRLinearRing()));
+    if( poRing == NULL )
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRLinearRing.");
+    }
+    return poRing;
 }
 
+//! @cond Doxygen_Suppress
+
 /************************************************************************/
 /*                     GetCasterToLineString()                          */
 /************************************************************************/
 
-OGRCurveCasterToLineString OGRLineString::GetCasterToLineString() const {
+OGRCurveCasterToLineString OGRLineString::GetCasterToLineString() const
+{
     return (OGRCurveCasterToLineString) OGRGeometry::CastToIdentity;
 }
 
@@ -2683,7 +2820,8 @@ OGRCurveCasterToLineString OGRLineString::GetCasterToLineString() const {
 /*                        GetCasterToLinearRing()                       */
 /************************************************************************/
 
-OGRCurveCasterToLinearRing OGRLineString::GetCasterToLinearRing() const {
+OGRCurveCasterToLinearRing OGRLineString::GetCasterToLinearRing() const
+{
     return (OGRCurveCasterToLinearRing) OGRLineString::CastToLinearRing;
 }
 
@@ -2704,3 +2842,4 @@ double OGRLineString::get_AreaOfCurveSegments() const
 {
     return 0;
 }
+//! @endcond
diff --git a/ogr/ogrmulticurve.cpp b/ogr/ogrmulticurve.cpp
index 6ab41bc..b05b2a9 100644
--- a/ogr/ogrmulticurve.cpp
+++ b/ogr/ogrmulticurve.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmulticurve.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiCurve class.
@@ -27,11 +26,17 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
-#include "ogr_p.h"
+
+#include <cstddef>
+
+#include "cpl_error.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmulticurve.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrmulticurve.cpp 36328 2016-11-20 13:44:29Z goatbar $");
 
 /************************************************************************/
 /*                            OGRMultiCurve()                           */
@@ -41,9 +46,7 @@ CPL_CVSID("$Id: ogrmulticurve.cpp 33631 2016-03-04 06:28:09Z goatbar $");
  * \brief Create an empty multi curve collection.
  */
 
-OGRMultiCurve::OGRMultiCurve()
-{
-}
+OGRMultiCurve::OGRMultiCurve() {}
 
 /************************************************************************/
 /*                OGRMultiCurve( const OGRMultiCurve& )                 */
@@ -60,16 +63,13 @@ OGRMultiCurve::OGRMultiCurve()
 
 OGRMultiCurve::OGRMultiCurve( const OGRMultiCurve& other ) :
     OGRGeometryCollection(other)
-{
-}
+{}
 
 /************************************************************************/
 /*                           ~OGRMultiCurve()                           */
 /************************************************************************/
 
-OGRMultiCurve::~OGRMultiCurve()
-{
-}
+OGRMultiCurve::~OGRMultiCurve() {}
 
 /************************************************************************/
 /*                  operator=( const OGRMultiCurve&)                    */
@@ -86,7 +86,7 @@ OGRMultiCurve::~OGRMultiCurve()
 
 OGRMultiCurve& OGRMultiCurve::operator=( const OGRMultiCurve& other )
 {
-    if( this != &other)
+    if( this != &other )
     {
         OGRGeometryCollection::operator=( other );
     }
@@ -102,7 +102,7 @@ OGRwkbGeometryType OGRMultiCurve::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbMultiCurveZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbMultiCurveM;
     else if( flags & OGR_G_3D )
         return wkbMultiCurveZ;
@@ -134,19 +134,28 @@ const char * OGRMultiCurve::getGeometryName() const
 /*                          isCompatibleSubType()                       */
 /************************************************************************/
 
-OGRBoolean OGRMultiCurve::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
+OGRBoolean OGRMultiCurve::isCompatibleSubType(
+    OGRwkbGeometryType eGeomType ) const
 {
     return OGR_GT_IsCurve(eGeomType);
 }
 
+/*! @cond Doxygen_Suppress */
 /************************************************************************/
 /*                       addCurveDirectlyFromWkt()                      */
 /************************************************************************/
 
-OGRErr OGRMultiCurve::addCurveDirectlyFromWkt( OGRGeometry* poSelf, OGRCurve* poCurve )
+OGRErr OGRMultiCurve::addCurveDirectlyFromWkt( OGRGeometry* poSelf,
+                                               OGRCurve* poCurve )
 {
-    return ((OGRMultiCurve*)poSelf)->addGeometryDirectly(poCurve);
+    OGRMultiCurve *poGeometry = dynamic_cast<OGRMultiCurve *>(poSelf);
+    if( poGeometry == NULL )
+    {
+        return OGRERR_FAILURE;
+    }
+    return poGeometry->addGeometryDirectly(poCurve);
 }
+/*! @endcond */
 
 /************************************************************************/
 /*                           importFromWkt()                            */
@@ -157,12 +166,12 @@ OGRErr OGRMultiCurve::addCurveDirectlyFromWkt( OGRGeometry* poSelf, OGRCurve* po
 OGRErr OGRMultiCurve::importFromWkt( char ** ppszInput )
 
 {
-    int bIsMultiCurve = (wkbFlatten(getGeometryType()) == wkbMultiCurve);
+    const bool bIsMultiCurve = wkbFlatten(getGeometryType()) == wkbMultiCurve;
     return importCurveCollectionFromWkt( ppszInput,
-                                         TRUE, /* bAllowEmptyComponent */
-                                         bIsMultiCurve, /* bAllowLineString */
-                                         bIsMultiCurve, /* bAllowCurve */
-                                         bIsMultiCurve, /* bAllowCompoundCurve */
+                                         TRUE,  // bAllowEmptyComponent.
+                                         bIsMultiCurve,  // bAllowLineString.
+                                         bIsMultiCurve,  // bAllowCurve.
+                                         bIsMultiCurve,  // bAllowCompoundCurve.
                                          addCurveDirectlyFromWkt );
 }
 
@@ -171,7 +180,7 @@ OGRErr OGRMultiCurve::importFromWkt( char ** ppszInput )
 /************************************************************************/
 
 OGRErr OGRMultiCurve::exportToWkt( char ** ppszDstText,
-                                   CPL_UNUSED OGRwkbVariant eWkbVariant ) const
+                                   OGRwkbVariant /* eWkbVariant */ ) const
 
 {
     return exportToWktInternal( ppszDstText, wkbVariantIso, "LINESTRING" );
@@ -181,11 +190,11 @@ OGRErr OGRMultiCurve::exportToWkt( char ** ppszDstText,
 /*                         hasCurveGeometry()                           */
 /************************************************************************/
 
-OGRBoolean OGRMultiCurve::hasCurveGeometry(int bLookForNonLinear) const
+OGRBoolean OGRMultiCurve::hasCurveGeometry( int bLookForNonLinear ) const
 {
     if( bLookForNonLinear )
         return OGRGeometryCollection::hasCurveGeometry(TRUE);
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -207,16 +216,23 @@ OGRBoolean OGRMultiCurve::hasCurveGeometry(int bLookForNonLinear) const
  * @return new geometry.
  */
 
-OGRMultiLineString* OGRMultiCurve::CastToMultiLineString(OGRMultiCurve* poMC)
+OGRMultiLineString* OGRMultiCurve::CastToMultiLineString( OGRMultiCurve* poMC )
 {
-    for(int i=0;i<poMC->nGeomCount;i++)
+    for( int i = 0; i < poMC->nGeomCount; ++i )
     {
-        poMC->papoGeoms[i] = OGRCurve::CastToLineString( (OGRCurve*)poMC->papoGeoms[i] );
+        OGRCurve * const poCurve = dynamic_cast<OGRCurve *>(poMC->papoGeoms[i]);
+        if( poCurve == NULL ) {
+            CPLError(
+                  CE_Fatal, CPLE_AssertionFailed, "dynamic_cast failed." );
+            continue;
+        }
+        poMC->papoGeoms[i] = OGRCurve::CastToLineString( poCurve );
         if( poMC->papoGeoms[i] == NULL )
         {
             delete poMC;
             return NULL;
         }
     }
-    return (OGRMultiLineString*) TransferMembersAndDestroy(poMC, new OGRMultiLineString());
+    return dynamic_cast<OGRMultiLineString *>(
+        TransferMembersAndDestroy(poMC, new OGRMultiLineString()) );
 }
diff --git a/ogr/ogrmultilinestring.cpp b/ogr/ogrmultilinestring.cpp
index 2a44c29..5c25dee 100644
--- a/ogr/ogrmultilinestring.cpp
+++ b/ogr/ogrmultilinestring.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmultilinestring.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiLineString class.
@@ -28,10 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
+
+#include <cstddef>
+
+#include "cpl_error.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmultilinestring.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrmultilinestring.cpp 36328 2016-11-20 13:44:29Z goatbar $");
 
 /************************************************************************/
 /*                        OGRMultiLineString()                          */
@@ -41,9 +46,7 @@ CPL_CVSID("$Id: ogrmultilinestring.cpp 33631 2016-03-04 06:28:09Z goatbar $");
  * \brief Create an empty multi line string collection.
  */
 
-OGRMultiLineString::OGRMultiLineString()
-{
-}
+OGRMultiLineString::OGRMultiLineString() {}
 
 /************************************************************************/
 /*           OGRMultiLineString( const OGRMultiLineString& )            */
@@ -60,16 +63,13 @@ OGRMultiLineString::OGRMultiLineString()
 
 OGRMultiLineString::OGRMultiLineString( const OGRMultiLineString& other ) :
     OGRMultiCurve(other)
-{
-}
+{}
 
 /************************************************************************/
 /*                       ~OGRMultiLineString()                          */
 /************************************************************************/
 
-OGRMultiLineString::~OGRMultiLineString()
-{
-}
+OGRMultiLineString::~OGRMultiLineString() {}
 
 /************************************************************************/
 /*                  operator=( const OGRMultiCurve&)                    */
@@ -84,16 +84,16 @@ OGRMultiLineString::~OGRMultiLineString()
  * @since GDAL 2.1
  */
 
-OGRMultiLineString& OGRMultiLineString::operator=( const OGRMultiLineString& other )
+OGRMultiLineString &
+OGRMultiLineString::operator=( const OGRMultiLineString& other )
 {
-    if( this != &other)
+    if( this != &other )
     {
         OGRMultiCurve::operator=( other );
     }
     return *this;
 }
 
-
 /************************************************************************/
 /*                          getGeometryType()                           */
 /************************************************************************/
@@ -103,7 +103,7 @@ OGRwkbGeometryType OGRMultiLineString::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbMultiLineStringZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbMultiLineStringM;
     else if( flags & OGR_G_3D )
         return wkbMultiLineString25D;
@@ -125,7 +125,8 @@ const char * OGRMultiLineString::getGeometryName() const
 /*                          isCompatibleSubType()                       */
 /************************************************************************/
 
-OGRBoolean OGRMultiLineString::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
+OGRBoolean
+OGRMultiLineString::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
 {
     return wkbFlatten(eGeomType) == wkbLineString;
 }
@@ -145,9 +146,10 @@ OGRErr OGRMultiLineString::exportToWkt( char ** ppszDstText,
 /*                         hasCurveGeometry()                           */
 /************************************************************************/
 
-OGRBoolean OGRMultiLineString::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear) const
+OGRBoolean OGRMultiLineString::hasCurveGeometry(
+    int /* bLookForNonLinear */ ) const
 {
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -157,13 +159,22 @@ OGRBoolean OGRMultiLineString::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear
 /**
  * \brief Cast to multicurve.
  *
- * The passed in geometry is consumed and a new one returned .
+ * The passed in geometry is consumed and a new one returned.
  *
  * @param poMLS the input geometry - ownership is passed to the method.
  * @return new geometry.
  */
 
-OGRMultiCurve* OGRMultiLineString::CastToMultiCurve(OGRMultiLineString* poMLS)
+OGRMultiCurve* OGRMultiLineString::CastToMultiCurve( OGRMultiLineString* poMLS )
 {
-    return (OGRMultiCurve*) TransferMembersAndDestroy(poMLS, new OGRMultiCurve());
+    OGRMultiCurve *poMultiCurve = dynamic_cast<OGRMultiCurve *>(
+        TransferMembersAndDestroy(poMLS, new OGRMultiCurve()) );
+    if( poMultiCurve == NULL )
+    {
+        CPLError( CE_Fatal, CPLE_AppDefined,
+                  "OGRMultiCurve dynamic_cast failed." );
+        return NULL;
+    }
+
+    return poMultiCurve;
 }
diff --git a/ogr/ogrmultipoint.cpp b/ogr/ogrmultipoint.cpp
index 663c1e4..a8ce342 100644
--- a/ogr/ogrmultipoint.cpp
+++ b/ogr/ogrmultipoint.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmultipoint.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiPoint class.
@@ -28,11 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
+
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
-#include <assert.h>
 
-CPL_CVSID("$Id: ogrmultipoint.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrmultipoint.cpp 36328 2016-11-20 13:44:29Z goatbar $");
 
 /************************************************************************/
 /*                           OGRMultiPoint()                            */
@@ -42,9 +50,7 @@ CPL_CVSID("$Id: ogrmultipoint.cpp 33631 2016-03-04 06:28:09Z goatbar $");
  * \brief Create an empty multi point collection.
  */
 
-OGRMultiPoint::OGRMultiPoint()
-{
-}
+OGRMultiPoint::OGRMultiPoint() {}
 
 /************************************************************************/
 /*                OGRMultiPoint( const OGRMultiPoint& )                 */
@@ -61,16 +67,13 @@ OGRMultiPoint::OGRMultiPoint()
 
 OGRMultiPoint::OGRMultiPoint( const OGRMultiPoint& other ) :
     OGRGeometryCollection(other)
-{
-}
+{}
 
 /************************************************************************/
 /*                          ~OGRMultiPoint()                            */
 /************************************************************************/
 
-OGRMultiPoint::~OGRMultiPoint()
-{
-}
+OGRMultiPoint::~OGRMultiPoint() {}
 
 /************************************************************************/
 /*                  operator=( const OGRMultiPoint&)                    */
@@ -103,7 +106,7 @@ OGRwkbGeometryType OGRMultiPoint::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbMultiPointZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbMultiPointM;
     else if( flags & OGR_G_3D )
         return wkbMultiPoint25D;
@@ -135,7 +138,8 @@ const char * OGRMultiPoint::getGeometryName() const
 /*                          isCompatibleSubType()                       */
 /************************************************************************/
 
-OGRBoolean OGRMultiPoint::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
+OGRBoolean
+OGRMultiPoint::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
 {
     return wkbFlatten(eGeomType) == wkbPoint;
 }
@@ -144,15 +148,15 @@ OGRBoolean OGRMultiPoint::isCompatibleSubType( OGRwkbGeometryType eGeomType ) co
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
-/*      equivalent.  This could be made a lot more CPU efficient!        */
+/*      equivalent.  This could be made a lot more CPU efficient.       */
 /************************************************************************/
 
 OGRErr OGRMultiPoint::exportToWkt( char ** ppszDstText,
                                    OGRwkbVariant eWkbVariant ) const
 
 {
-    size_t      nMaxString = static_cast<size_t>(getNumGeometries()) * 22 + 130;
-    size_t      nRetLen = 0;
+    size_t nMaxString = static_cast<size_t>(getNumGeometries()) * 22 + 130;
+    size_t nRetLen = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Return MULTIPOINT EMPTY if we get no valid points.              */
@@ -175,7 +179,7 @@ OGRErr OGRMultiPoint::exportToWkt( char ** ppszDstText,
         return OGRERR_NONE;
     }
 
-    *ppszDstText = (char *) VSI_MALLOC_VERBOSE( nMaxString );
+    *ppszDstText = static_cast<char *>(VSI_MALLOC_VERBOSE( nMaxString ));
     if( *ppszDstText == NULL )
         return OGRERR_NOT_ENOUGH_MEMORY;
 
@@ -196,11 +200,12 @@ OGRErr OGRMultiPoint::exportToWkt( char ** ppszDstText,
     bool bMustWriteComma = false;
     for( int i = 0; i < getNumGeometries(); i++ )
     {
-        OGRPoint        *poPoint = (OGRPoint *) getGeometryRef( i );
+        OGRPoint *poPoint = (OGRPoint *) getGeometryRef( i );
 
-        if (poPoint->IsEmpty())
+        if( poPoint->IsEmpty() )
         {
-            CPLDebug( "OGR", "OGRMultiPoint::exportToWkt() - skipping POINT EMPTY.");
+            CPLDebug("OGR",
+                     "OGRMultiPoint::exportToWkt() - skipping POINT EMPTY.");
             continue;
         }
 
@@ -213,27 +218,29 @@ OGRErr OGRMultiPoint::exportToWkt( char ** ppszDstText,
         if( nMaxString < nRetLen + 100 )
         {
             nMaxString = nMaxString * 2;
-            *ppszDstText = (char *) CPLRealloc(*ppszDstText,nMaxString);
+            *ppszDstText =
+                static_cast<char *>(CPLRealloc(*ppszDstText, nMaxString));
         }
 
         if( eWkbVariant == wkbVariantIso )
         {
             strcat( *ppszDstText + nRetLen, "(" );
-            nRetLen ++;
+            nRetLen++;
         }
 
-        OGRMakeWktCoordinateM( *ppszDstText + nRetLen,
-                               poPoint->getX(),
-                               poPoint->getY(),
-                               poPoint->getZ(),
-                               poPoint->getM(),
-                               poPoint->Is3D(),
-                               poPoint->IsMeasured() && (eWkbVariant == wkbVariantIso) );
+        OGRMakeWktCoordinateM(
+            *ppszDstText + nRetLen,
+            poPoint->getX(),
+            poPoint->getY(),
+            poPoint->getZ(),
+            poPoint->getM(),
+            poPoint->Is3D(),
+            poPoint->IsMeasured() && (eWkbVariant == wkbVariantIso));
 
         if( eWkbVariant == wkbVariantIso )
         {
             strcat( *ppszDstText + nRetLen, ")" );
-            nRetLen ++;
+            nRetLen++;
         }
     }
 
@@ -250,9 +257,10 @@ OGRErr OGRMultiPoint::importFromWkt( char ** ppszInput )
 
 {
     const char *pszInputBefore = *ppszInput;
-    int bHasZ = FALSE, bHasM = FALSE;
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
     bool bIsEmpty = false;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    OGRErr eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     flags = 0;
     if( eErr != OGRERR_NONE )
         return eErr;
@@ -261,22 +269,21 @@ OGRErr OGRMultiPoint::importFromWkt( char ** ppszInput )
     if( bIsEmpty )
         return OGRERR_NONE;
 
-    char        szToken[OGR_WKT_TOKEN_MAX];
-    const char  *pszInput = *ppszInput;
-    int         iGeom;
+    char szToken[OGR_WKT_TOKEN_MAX] = {};
+    const char *pszInput = *ppszInput;
     eErr = OGRERR_NONE;
 
     const char* pszPreScan = OGRWktReadToken( pszInput, szToken );
     OGRWktReadToken( pszPreScan, szToken );
 
     // Do we have an inner bracket?
-    if (EQUAL(szToken,"(") || EQUAL(szToken, "EMPTY") )
+    if( EQUAL(szToken,"(") || EQUAL(szToken, "EMPTY") )
     {
-        *ppszInput = (char*) pszInputBefore;
+        *ppszInput = const_cast<char *>(pszInputBefore);
         return importFromWkt_Bracketed( ppszInput, bHasM, bHasZ );
     }
 
-    if (bHasZ || bHasM)
+    if( bHasZ || bHasM )
     {
         return OGRERR_CORRUPT_DATA;
     }
@@ -284,20 +291,21 @@ OGRErr OGRMultiPoint::importFromWkt( char ** ppszInput )
 /* -------------------------------------------------------------------- */
 /*      Read the point list which should consist of exactly one point.  */
 /* -------------------------------------------------------------------- */
-    int                 nMaxPoint = 0;
-    int                 nPointCount = 0;
-    OGRRawPoint         *paoPoints = NULL;
-    double              *padfZ = NULL;
-    double              *padfM = NULL;
-    int                 flagsFromInput = flags;
-
-    pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM, &flagsFromInput,
+    OGRRawPoint *paoPoints = NULL;
+    double *padfZ = NULL;
+    double *padfM = NULL;
+    int flagsFromInput = flags;
+    int nMaxPoint = 0;
+    int nPointCount = 0;
+
+    pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM,
+                                  &flagsFromInput,
                                   &nMaxPoint, &nPointCount );
     if( pszInput == NULL )
     {
-        OGRFree( paoPoints );
-        OGRFree( padfZ );
-        OGRFree( padfM );
+        CPLFree( paoPoints );
+        CPLFree( padfZ );
+        CPLFree( padfM );
         return OGRERR_CORRUPT_DATA;
     }
     if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
@@ -314,51 +322,48 @@ OGRErr OGRMultiPoint::importFromWkt( char ** ppszInput )
 /* -------------------------------------------------------------------- */
 /*      Transform raw points into point objects.                        */
 /* -------------------------------------------------------------------- */
-    for( iGeom = 0; iGeom < nPointCount && eErr == OGRERR_NONE; iGeom++ )
+    for( int iGeom = 0; iGeom < nPointCount && eErr == OGRERR_NONE; iGeom++ )
     {
-        OGRGeometry     *poGeom = new OGRPoint( paoPoints[iGeom].x,
-                                                paoPoints[iGeom].y );
+        OGRPoint *poPoint =
+            new OGRPoint(paoPoints[iGeom].x, paoPoints[iGeom].y);
         if( bHasM )
         {
             if( padfM != NULL )
-                ((OGRPoint*)poGeom)->setM(padfM[iGeom]);
+                poPoint->setM(padfM[iGeom]);
             else
-                ((OGRPoint*)poGeom)->setM(0.0);
+                poPoint->setM(0.0);
         }
         if( bHasZ )
         {
             if( padfZ != NULL )
-                ((OGRPoint*)poGeom)->setZ(padfZ[iGeom]);
+                poPoint->setZ(padfZ[iGeom]);
             else
-                ((OGRPoint*)poGeom)->setZ(0.0);
+                poPoint->setZ(0.0);
         }
 
-        eErr = addGeometryDirectly( poGeom );
+        eErr = addGeometryDirectly( poPoint );
         if( eErr != OGRERR_NONE )
         {
-            OGRFree( paoPoints );
-            OGRFree( padfZ );
-            OGRFree( padfM );
-            delete poGeom;
+            CPLFree( paoPoints );
+            CPLFree( padfZ );
+            CPLFree( padfM );
+            delete poPoint;
             return eErr;
         }
     }
 
-    OGRFree( paoPoints );
-    if( padfZ )
-        OGRFree( padfZ );
-    if( padfM )
-        OGRFree( padfM );
+    CPLFree( paoPoints );
+    CPLFree( padfZ );
+    CPLFree( padfM );
 
     if( eErr != OGRERR_NONE )
         return eErr;
 
-    *ppszInput = (char *) pszInput;
+    *ppszInput = const_cast<char *>(pszInput);
 
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                      importFromWkt_Bracketed()                       */
 /*                                                                      */
@@ -368,19 +373,20 @@ OGRErr OGRMultiPoint::importFromWkt( char ** ppszInput )
 /*      importFromWkt().                                                */
 /************************************************************************/
 
-OGRErr OGRMultiPoint::importFromWkt_Bracketed( char ** ppszInput, int bHasM, int bHasZ )
+OGRErr OGRMultiPoint::importFromWkt_Bracketed( char ** ppszInput,
+                                               int bHasM, int bHasZ )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Skip MULTIPOINT keyword.                                        */
 /* -------------------------------------------------------------------- */
-    char        szToken[OGR_WKT_TOKEN_MAX];
-    const char  *pszInput = *ppszInput;
+    char szToken[OGR_WKT_TOKEN_MAX] = {};
+    const char *pszInput = *ppszInput;
     pszInput = OGRWktReadToken( pszInput, szToken );
 
-    if (bHasZ || bHasM)
+    if( bHasZ || bHasM )
     {
-        /* Skip Z, M or ZM */
+        // Skip Z, M or ZM.
         pszInput = OGRWktReadToken( pszInput, szToken );
     }
 
@@ -388,22 +394,22 @@ OGRErr OGRMultiPoint::importFromWkt_Bracketed( char ** ppszInput, int bHasM, int
 /*      Read points till we get to the closing bracket.                 */
 /* -------------------------------------------------------------------- */
 
-    OGRRawPoint         *paoPoints = NULL;
-    double              *padfZ = NULL;
-    double              *padfM = NULL;
+    OGRRawPoint *paoPoints = NULL;
+    double *padfZ = NULL;
+    double *padfM = NULL;
 
     while( (pszInput = OGRWktReadToken( pszInput, szToken )) != NULL
-           && (EQUAL(szToken,"(") || EQUAL(szToken,",")) )
+           && (EQUAL(szToken, "(") || EQUAL(szToken, ",")) )
     {
         const char* pszNext = OGRWktReadToken( pszInput, szToken );
-        if (EQUAL(szToken,"EMPTY"))
+        if( EQUAL(szToken, "EMPTY") )
         {
-            OGRGeometry *poGeom = new OGRPoint(0,0);
+            OGRPoint *poGeom = new OGRPoint(0.0, 0.0);
             poGeom->empty();
-            OGRErr eErr = addGeometryDirectly( poGeom );
+            const OGRErr eErr = addGeometryDirectly( poGeom );
             if( eErr != OGRERR_NONE )
             {
-                OGRFree( paoPoints );
+                CPLFree( paoPoints );
                 delete poGeom;
                 return eErr;
             }
@@ -413,17 +419,18 @@ OGRErr OGRMultiPoint::importFromWkt_Bracketed( char ** ppszInput, int bHasM, int
             continue;
         }
 
+        int flagsFromInput = flags;
         int nMaxPoint = 0;
         int nPointCount = 0;
-        int flagsFromInput = flags;
-        pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM, &flagsFromInput,
+        pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM,
+                                      &flagsFromInput,
                                       &nMaxPoint, &nPointCount );
 
         if( pszInput == NULL || nPointCount != 1 )
         {
-            OGRFree( paoPoints );
-            OGRFree( padfZ );
-            OGRFree( padfM );
+            CPLFree( paoPoints );
+            CPLFree( padfZ );
+            CPLFree( padfM );
             return OGRERR_CORRUPT_DATA;
         }
         if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) )
@@ -437,30 +444,29 @@ OGRErr OGRMultiPoint::importFromWkt_Bracketed( char ** ppszInput, int bHasM, int
             bHasM = TRUE;
         }
 
-        OGRGeometry *poGeom = new OGRPoint( paoPoints[0].x,
-                                            paoPoints[0].y );
+        OGRPoint *poPoint = new OGRPoint(paoPoints[0].x, paoPoints[0].y);
         if( bHasM )
         {
             if( padfM != NULL )
-                ((OGRPoint*)poGeom)->setM(padfM[0]);
+                poPoint->setM(padfM[0]);
             else
-                ((OGRPoint*)poGeom)->setM(0.0);
+                poPoint->setM(0.0);
         }
         if( bHasZ )
         {
             if( padfZ != NULL )
-                ((OGRPoint*)poGeom)->setZ(padfZ[0]);
+                poPoint->setZ(padfZ[0]);
             else
-                ((OGRPoint*)poGeom)->setZ(0.0);
+                poPoint->setZ(0.0);
         }
 
-        OGRErr eErr = addGeometryDirectly( poGeom );
+        const OGRErr eErr = addGeometryDirectly( poPoint );
         if( eErr != OGRERR_NONE )
         {
-            OGRFree( paoPoints );
-            OGRFree( padfZ );
-            OGRFree( padfM );
-            delete poGeom;
+            CPLFree( paoPoints );
+            CPLFree( padfZ );
+            CPLFree( padfM );
+            delete poPoint;
             return eErr;
         }
     }
@@ -468,14 +474,14 @@ OGRErr OGRMultiPoint::importFromWkt_Bracketed( char ** ppszInput, int bHasM, int
 /* -------------------------------------------------------------------- */
 /*      Cleanup.                                                        */
 /* -------------------------------------------------------------------- */
-    OGRFree( paoPoints );
-    OGRFree( padfZ );
-    OGRFree( padfM );
+    CPLFree( paoPoints );
+    CPLFree( padfZ );
+    CPLFree( padfM );
 
-    if( !EQUAL(szToken,")") )
+    if( !EQUAL(szToken, ")") )
         return OGRERR_CORRUPT_DATA;
 
-    *ppszInput = (char *) pszInput;
+    *ppszInput = const_cast<char *>(pszInput);
 
     return OGRERR_NONE;
 }
@@ -484,7 +490,7 @@ OGRErr OGRMultiPoint::importFromWkt_Bracketed( char ** ppszInput, int bHasM, int
 /*                         hasCurveGeometry()                           */
 /************************************************************************/
 
-OGRBoolean OGRMultiPoint::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear) const
+OGRBoolean OGRMultiPoint::hasCurveGeometry( int /* bLookForNonLinear */ ) const
 {
     return FALSE;
 }
diff --git a/ogr/ogrmultipolygon.cpp b/ogr/ogrmultipolygon.cpp
index 168ce57..73d9924 100644
--- a/ogr/ogrmultipolygon.cpp
+++ b/ogr/ogrmultipolygon.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmultipolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiPolygon class.
@@ -28,11 +27,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
+
 #include "ogr_api.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmultipolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrmultipolygon.cpp 36883 2016-12-15 13:31:12Z rouault $");
 
 /************************************************************************/
 /*                          OGRMultiPolygon()                           */
@@ -42,9 +44,7 @@ CPL_CVSID("$Id: ogrmultipolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $");
  * \brief Create an empty multi polygon collection.
  */
 
-OGRMultiPolygon::OGRMultiPolygon()
-{
-}
+OGRMultiPolygon::OGRMultiPolygon() {}
 
 /************************************************************************/
 /*              OGRMultiPolygon( const OGRMultiPolygon& )               */
@@ -61,16 +61,13 @@ OGRMultiPolygon::OGRMultiPolygon()
 
 OGRMultiPolygon::OGRMultiPolygon( const OGRMultiPolygon& other ) :
     OGRMultiSurface(other)
-{
-}
+{}
 
 /************************************************************************/
 /*                         ~OGRMultiPolygon()                           */
 /************************************************************************/
 
-OGRMultiPolygon::~OGRMultiPolygon()
-{
-}
+OGRMultiPolygon::~OGRMultiPolygon() {}
 
 /************************************************************************/
 /*                  operator=( const OGRMultiPolygon&)                    */
@@ -103,7 +100,7 @@ OGRwkbGeometryType OGRMultiPolygon::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbMultiPolygonZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbMultiPolygonM;
     else if( flags & OGR_G_3D )
         return wkbMultiPolygon25D;
@@ -125,7 +122,8 @@ const char * OGRMultiPolygon::getGeometryName() const
 /*                          isCompatibleSubType()                       */
 /************************************************************************/
 
-OGRBoolean OGRMultiPolygon::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
+OGRBoolean
+OGRMultiPolygon::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
 {
     return wkbFlatten(eGeomType) == wkbPolygon;
 }
@@ -135,7 +133,7 @@ OGRBoolean OGRMultiPolygon::isCompatibleSubType( OGRwkbGeometryType eGeomType )
 /************************************************************************/
 
 OGRErr OGRMultiPolygon::exportToWkt( char ** ppszDstText,
-                                        OGRwkbVariant eWkbVariant ) const
+                                     OGRwkbVariant eWkbVariant ) const
 
 {
     return exportToWktInternal( ppszDstText, eWkbVariant, "POLYGON" );
@@ -145,7 +143,8 @@ OGRErr OGRMultiPolygon::exportToWkt( char ** ppszDstText,
 /*                         hasCurveGeometry()                           */
 /************************************************************************/
 
-OGRBoolean OGRMultiPolygon::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear) const
+OGRBoolean
+OGRMultiPolygon::hasCurveGeometry( int /* bLookForNonLinear */ ) const
 {
     return FALSE;
 }
@@ -172,7 +171,83 @@ OGRErr OGRMultiPolygon::PointOnSurface( OGRPoint * poPoint ) const
  * @return new geometry.
  */
 
-OGRMultiSurface* OGRMultiPolygon::CastToMultiSurface(OGRMultiPolygon* poMP)
+OGRMultiSurface* OGRMultiPolygon::CastToMultiSurface( OGRMultiPolygon* poMP )
 {
-    return (OGRMultiSurface*) TransferMembersAndDestroy(poMP, new OGRMultiSurface());
+    OGRGeometryCollection *poGC =
+        TransferMembersAndDestroy(poMP, new OGRMultiSurface());
+
+    OGRMultiSurface* poMultiSurface = dynamic_cast<OGRMultiSurface *>(poGC);
+    if( poMultiSurface == NULL )
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRMultiSurface.");
+    }
+
+    return poMultiSurface;
 }
+
+
+/************************************************************************/
+/*               _addGeometryWithExpectedSubGeometryType()              */
+/*      Only to be used in conjunction with OGRPolyhedralSurface.       */
+/*                        DO NOT USE IT ELSEWHERE.                      */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRErr OGRMultiPolygon::_addGeometryWithExpectedSubGeometryType(
+                                      const OGRGeometry * poNewGeom,
+                                      OGRwkbGeometryType eSubGeometryType )
+
+{
+    OGRGeometry *poClone = poNewGeom->clone();
+    OGRErr      eErr;
+
+    if( poClone == NULL )
+        return OGRERR_FAILURE;
+    eErr = _addGeometryDirectlyWithExpectedSubGeometryType( poClone, eSubGeometryType );
+    if( eErr != OGRERR_NONE )
+        delete poClone;
+
+    return eErr;
+}
+//! @endcond
+
+/************************************************************************/
+/*                 _addGeometryDirectlyWithExpectedSubGeometryType()    */
+/*      Only to be used in conjunction with OGRPolyhedralSurface.       */
+/*                        DO NOT USE IT ELSEWHERE.                      */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRErr OGRMultiPolygon::_addGeometryDirectlyWithExpectedSubGeometryType(
+                                      OGRGeometry * poNewGeom,
+                                      OGRwkbGeometryType eSubGeometryType )
+{
+    if ( wkbFlatten(poNewGeom->getGeometryType()) != eSubGeometryType)
+        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+
+    if( poNewGeom->Is3D() && !Is3D() )
+        set3D(TRUE);
+
+    if( poNewGeom->IsMeasured() && !IsMeasured() )
+        setMeasured(TRUE);
+
+    if( !poNewGeom->Is3D() && Is3D() )
+        poNewGeom->set3D(TRUE);
+
+    if( !poNewGeom->IsMeasured() && IsMeasured() )
+        poNewGeom->setMeasured(TRUE);
+
+    OGRGeometry** papoNewGeoms = (OGRGeometry **) VSI_REALLOC_VERBOSE( papoGeoms,
+                                             sizeof(void*) * (nGeomCount+1) );
+    if( papoNewGeoms == NULL )
+        return OGRERR_FAILURE;
+
+    papoGeoms = papoNewGeoms;
+    papoGeoms[nGeomCount] = poNewGeom;
+    nGeomCount++;
+
+    return OGRERR_NONE;
+}
+//! @endcond
+
diff --git a/ogr/ogrmultisurface.cpp b/ogr/ogrmultisurface.cpp
index b49df39..c06b976 100644
--- a/ogr/ogrmultisurface.cpp
+++ b/ogr/ogrmultisurface.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmultisurface.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRMultiSurface class.
@@ -27,11 +26,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
-#include "ogr_p.h"
+
+#include <cstddef>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmultisurface.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrmultisurface.cpp 36379 2016-11-21 09:38:41Z rouault $");
 
 /************************************************************************/
 /*                          OGRMultiSurface()                           */
@@ -41,17 +47,13 @@ CPL_CVSID("$Id: ogrmultisurface.cpp 33631 2016-03-04 06:28:09Z goatbar $");
  * \brief Create an empty multi surface collection.
  */
 
-OGRMultiSurface::OGRMultiSurface()
-{
-}
+OGRMultiSurface::OGRMultiSurface() {}
 
 /************************************************************************/
 /*                         ~OGRMultiSurface()                           */
 /************************************************************************/
 
-OGRMultiSurface::~OGRMultiSurface()
-{
-}
+OGRMultiSurface::~OGRMultiSurface() {}
 
 /************************************************************************/
 /*              OGRMultiSurface( const OGRMultiSurface& )               */
@@ -68,8 +70,7 @@ OGRMultiSurface::~OGRMultiSurface()
 
 OGRMultiSurface::OGRMultiSurface( const OGRMultiSurface& other ) :
     OGRGeometryCollection(other)
-{
-}
+{}
 
 /************************************************************************/
 /*                  operator=( const OGRMultiCurve&)                    */
@@ -102,7 +103,7 @@ OGRwkbGeometryType OGRMultiSurface::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbMultiSurfaceZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbMultiSurfaceM;
     else if( flags & OGR_G_3D )
         return wkbMultiSurfaceZ;
@@ -134,7 +135,8 @@ const char * OGRMultiSurface::getGeometryName() const
 /*                          isCompatibleSubType()                       */
 /************************************************************************/
 
-OGRBoolean OGRMultiSurface::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
+OGRBoolean
+OGRMultiSurface::isCompatibleSubType( OGRwkbGeometryType eGeomType ) const
 {
     return OGR_GT_IsSurface(eGeomType);
 }
@@ -148,9 +150,10 @@ OGRBoolean OGRMultiSurface::isCompatibleSubType( OGRwkbGeometryType eGeomType )
 OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
 
 {
-    int bHasZ = FALSE, bHasM = FALSE;
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
     bool bIsEmpty = false;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    OGRErr eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     flags = 0;
     if( eErr != OGRERR_NONE )
         return eErr;
@@ -159,11 +162,11 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
     if( bIsEmpty )
         return OGRERR_NONE;
 
-    char        szToken[OGR_WKT_TOKEN_MAX];
-    const char  *pszInput = *ppszInput;
+    char szToken[OGR_WKT_TOKEN_MAX] = {};
+    const char *pszInput = *ppszInput;
     eErr = OGRERR_NONE;
 
-    /* Skip first '(' */
+    // Skip first '('.
     pszInput = OGRWktReadToken( pszInput, szToken );
 
 /* ==================================================================== */
@@ -177,44 +180,50 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
 
     do
     {
-
     /* -------------------------------------------------------------------- */
     /*      Get the first token, which should be the geometry type.         */
     /* -------------------------------------------------------------------- */
         const char* pszInputBefore = pszInput;
         pszInput = OGRWktReadToken( pszInput, szToken );
 
-        OGRSurface* poSurface;
+        OGRSurface* poSurface = NULL;
 
     /* -------------------------------------------------------------------- */
     /*      Do the import.                                                  */
     /* -------------------------------------------------------------------- */
-        if (EQUAL(szToken,"("))
+        if( EQUAL(szToken, "(") )
         {
-            OGRPolygon      *poPolygon = new OGRPolygon();
+            OGRPolygon *poPolygon = new OGRPolygon();
             poSurface = poPolygon;
             pszInput = pszInputBefore;
-            eErr = poPolygon->importFromWKTListOnly( (char**)&pszInput, bHasZ, bHasM,
-                                                     paoPoints, nMaxPoints, padfZ );
+            eErr = poPolygon->importFromWKTListOnly(
+                const_cast<char **>(&pszInput), bHasZ, bHasM,
+                paoPoints, nMaxPoints, padfZ );
         }
-        else if (EQUAL(szToken, "EMPTY") )
+        else if( EQUAL(szToken, "EMPTY") )
         {
             poSurface = new OGRPolygon();
         }
-        /* We accept POLYGON() but this is an extension to the BNF, also */
-        /* accepted by PostGIS */
-        else if ((EQUAL(szToken,"POLYGON") ||
-                  EQUAL(szToken,"CURVEPOLYGON")))
+        // We accept POLYGON() but this is an extension to the BNF, also
+        // accepted by PostGIS.
+        else if( EQUAL(szToken, "POLYGON") ||
+                 EQUAL(szToken, "CURVEPOLYGON") )
         {
             OGRGeometry* poGeom = NULL;
             pszInput = pszInputBefore;
-            eErr = OGRGeometryFactory::createFromWkt( (char **) &pszInput,
-                                                       NULL, &poGeom );
-            poSurface = (OGRSurface*) poGeom;
+            eErr = OGRGeometryFactory::createFromWkt(
+                const_cast<char **>(&pszInput), NULL, &poGeom );
+            poSurface = dynamic_cast<OGRSurface*>(poGeom);
+            if( poSurface == NULL )
+            {
+                CPLError(CE_Fatal, CPLE_AppDefined,
+                         "dynamic_cast failed.  Expected OGRSurface.");
+            }
         }
         else
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Unexpected token : %s", szToken);
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unexpected token : %s", szToken);
             eErr = OGRERR_CORRUPT_DATA;
             break;
         }
@@ -231,7 +240,6 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
 /*      Read the delimiter following the surface.                       */
 /* -------------------------------------------------------------------- */
         pszInput = OGRWktReadToken( pszInput, szToken );
-
     } while( szToken[0] == ',' && eErr == OGRERR_NONE );
 
     CPLFree( paoPoints );
@@ -247,7 +255,7 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
     if( szToken[0] != ')' )
         return OGRERR_CORRUPT_DATA;
 
-    *ppszInput = (char *) pszInput;
+    *ppszInput = const_cast<char *>(pszInput);
     return OGRERR_NONE;
 }
 
@@ -256,7 +264,7 @@ OGRErr OGRMultiSurface::importFromWkt( char ** ppszInput )
 /************************************************************************/
 
 OGRErr OGRMultiSurface::exportToWkt( char ** ppszDstText,
-                                     CPL_UNUSED OGRwkbVariant eWkbVariant ) const
+                                     OGRwkbVariant /* eWkbVariant */ ) const
 
 {
     return exportToWktInternal( ppszDstText, wkbVariantIso, "POLYGON" );
@@ -266,7 +274,7 @@ OGRErr OGRMultiSurface::exportToWkt( char ** ppszDstText,
 /*                         hasCurveGeometry()                           */
 /************************************************************************/
 
-OGRBoolean OGRMultiSurface::hasCurveGeometry(int bLookForNonLinear) const
+OGRBoolean OGRMultiSurface::hasCurveGeometry( int bLookForNonLinear ) const
 {
     if( bLookForNonLinear )
         return OGRGeometryCollection::hasCurveGeometry(TRUE);
@@ -277,7 +285,8 @@ OGRBoolean OGRMultiSurface::hasCurveGeometry(int bLookForNonLinear) const
 /*                            PointOnSurface()                          */
 /************************************************************************/
 
-/** \brief This method relates to the SFCOM IMultiSurface::get_PointOnSurface() method.
+/** \brief This method relates to the SFCOM
+ * IMultiSurface::get_PointOnSurface() method.
  *
  * NOTE: Only implemented when GEOS included in build.
  *
@@ -310,16 +319,33 @@ OGRErr OGRMultiSurface::PointOnSurface( OGRPoint * poPoint ) const
  * @return new geometry.
  */
 
-OGRMultiPolygon* OGRMultiSurface::CastToMultiPolygon(OGRMultiSurface* poMS)
+OGRMultiPolygon* OGRMultiSurface::CastToMultiPolygon( OGRMultiSurface* poMS )
 {
-    for(int i=0;i<poMS->nGeomCount;i++)
+    for( int i = 0; i < poMS->nGeomCount; i++ )
     {
-        poMS->papoGeoms[i] = OGRSurface::CastToPolygon( (OGRSurface*)poMS->papoGeoms[i] );
+        OGRSurface* poSurface = dynamic_cast<OGRSurface *>(poMS->papoGeoms[i]);
+        if( poSurface == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRSurface.");
+            delete poMS;
+            return NULL;
+        }
+        poMS->papoGeoms[i] = OGRSurface::CastToPolygon(poSurface);
         if( poMS->papoGeoms[i] == NULL )
         {
             delete poMS;
             return NULL;
         }
     }
-    return (OGRMultiPolygon*) TransferMembersAndDestroy(poMS, new OGRMultiPolygon());
+
+    OGRGeometryCollection *poGC =
+           TransferMembersAndDestroy(poMS, new OGRMultiPolygon());
+    OGRMultiPolygon* poMultiPolygon = dynamic_cast<OGRMultiPolygon *>(poGC);
+    if( poMultiPolygon == NULL )
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRMultiPolygon.");
+    }
+    return poMultiPolygon;
 }
diff --git a/ogr/ogrpgeogeometry.cpp b/ogr/ogrpgeogeometry.cpp
index 8baf13a..1911785 100644
--- a/ogr/ogrpgeogeometry.cpp
+++ b/ogr/ogrpgeogeometry.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgeogeometry.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of shapebin geometry for PGeo
@@ -30,114 +29,206 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+// PGeo == ESRI Personal GeoDatabase.
+
+#include "cpl_port.h"
 #include "ogrpgeogeometry.h"
-#include "ogr_p.h"
-#include "cpl_string.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstring>
 #include <limits>
+#include <map>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpgeogeometry.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrpgeogeometry.cpp 37654 2017-03-09 07:42:07Z rouault $");
 
-#define SHPP_TRISTRIP   0
-#define SHPP_TRIFAN     1
-#define SHPP_OUTERRING  2
-#define SHPP_INNERRING  3
-#define SHPP_FIRSTRING  4
-#define SHPP_RING       5
-#define SHPP_TRIANGLES  6 /* Multipatch 9.0 specific */
+static const int SHPP_TRISTRIP  = 0;
+static const int SHPP_TRIFAN    = 1;
+static const int SHPP_OUTERRING = 2;
+static const int SHPP_INNERRING = 3;
+static const int SHPP_FIRSTRING = 4;
+static const int SHPP_RING      = 5;
+static const int SHPP_TRIANGLES = 6;  // Multipatch 9.0 specific.
 
+typedef enum
+{
+    CURVE_ARC_INTERIOR_POINT,
+    CURVE_ARC_CENTER_POINT,
+    CURVE_BEZIER,
+    CURVE_ELLIPSE_BY_CENTER
+} CurveType;
+
+namespace {
+typedef struct
+{
+    int       nStartPointIdx;
+    CurveType eType;
+    union
+    {
+        // Arc defined by an intermediate point.
+        struct
+        {
+            double dfX;
+            double dfY;
+        } ArcByIntermediatePoint;
+
+        // Deprecated way of defining circular arc by its center and
+        // winding order.
+        struct
+        {
+            double dfX;
+            double dfY;
+            EMULATED_BOOL bIsCCW;
+        } ArcByCenterPoint;
+
+        struct
+        {
+            double dfX1;
+            double dfY1;
+            double dfX2;
+            double dfY2;
+        } Bezier;
+
+        struct
+        {
+            double dfX;
+            double dfY;
+            double dfRotationDeg;
+            double dfSemiMajor;
+            double dfRatioSemiMinor;
+            EMULATED_BOOL bIsMinor;
+            EMULATED_BOOL bIsComplete;
+        } EllipseByCenter;
+    } u;
+} CurveSegment;
+} /* namespace */
+
+static const int EXT_SHAPE_SEGMENT_ARC = 1;
+static const int EXT_SHAPE_SEGMENT_BEZIER = 4;
+static const int EXT_SHAPE_SEGMENT_ELLIPSE = 5;
+
+static const int EXT_SHAPE_ARC_EMPTY = 0x1;
+static const int EXT_SHAPE_ARC_CCW   = 0x8;
+#ifdef DEBUG_VERBOSE
+static const int EXT_SHAPE_ARC_MINOR = 0x10;
+#endif
+static const int EXT_SHAPE_ARC_LINE  = 0x20;
+static const int EXT_SHAPE_ARC_POINT = 0x40;
+static const int EXT_SHAPE_ARC_IP    = 0x80;
+
+#ifdef DEBUG_VERBOSE
+static const int EXT_SHAPE_ELLIPSE_EMPTY       = 0x1;
+static const int EXT_SHAPE_ELLIPSE_LINE        = 0x40;
+static const int EXT_SHAPE_ELLIPSE_POINT       = 0x80;
+static const int EXT_SHAPE_ELLIPSE_CIRCULAR    = 0x100;
+static const int EXT_SHAPE_ELLIPSE_CCW         = 0x800;
+#endif
+
+static const int EXT_SHAPE_ELLIPSE_CENTER_TO   = 0x200;
+static const int EXT_SHAPE_ELLIPSE_CENTER_FROM = 0x400;
+static const int EXT_SHAPE_ELLIPSE_MINOR       = 0x1000;
+static const int EXT_SHAPE_ELLIPSE_COMPLETE    = 0x2000;
 
 /************************************************************************/
 /*                  OGRCreateFromMultiPatchPart()                       */
 /************************************************************************/
 
-void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
-                                 OGRPolygon*& poLastPoly,
-                                 int nPartType,
-                                 int nPartPoints,
-                                 double* padfX,
-                                 double* padfY,
-                                 double* padfZ)
+static
+void OGRCreateFromMultiPatchPart( OGRGeometryCollection *poGC,
+                                  OGRMultiPolygon*& poMP,
+                                  OGRPolygon*& poLastPoly,
+                                  int nPartType,
+                                  int nPartPoints,
+                                  const double* padfX,
+                                  const double* padfY,
+                                  const double* padfZ )
 {
     nPartType &= 0xf;
 
     if( nPartType == SHPP_TRISTRIP )
     {
-        if( poLastPoly != NULL )
+        if( poMP != NULL && poLastPoly != NULL )
         {
             poMP->addGeometryDirectly( poLastPoly );
             poLastPoly = NULL;
         }
 
+        OGRTriangulatedSurface* poTIN = new OGRTriangulatedSurface();
         for( int iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
         {
-            OGRPolygon *poPoly = new OGRPolygon();
-            OGRLinearRing *poRing = new OGRLinearRing();
-            int iSrcVert = iBaseVert;
-
-            poRing->setPoint( 0,
-                            padfX[iSrcVert],
-                            padfY[iSrcVert],
-                            padfZ[iSrcVert] );
-            poRing->setPoint( 1,
-                            padfX[iSrcVert+1],
-                            padfY[iSrcVert+1],
-                            padfZ[iSrcVert+1] );
-
-            poRing->setPoint( 2,
-                            padfX[iSrcVert+2],
-                            padfY[iSrcVert+2],
-                            padfZ[iSrcVert+2] );
-            poRing->setPoint( 3,
-                            padfX[iSrcVert],
-                            padfY[iSrcVert],
-                            padfZ[iSrcVert] );
-
-            poPoly->addRingDirectly( poRing );
-            poMP->addGeometryDirectly( poPoly );
+            const int iSrcVert = iBaseVert;
+
+            OGRPoint oPoint1  (padfX[iSrcVert],
+                               padfY[iSrcVert],
+                               padfZ[iSrcVert]);
+
+            OGRPoint oPoint2  (padfX[iSrcVert+1],
+                               padfY[iSrcVert+1],
+                               padfZ[iSrcVert+1]);
+
+            OGRPoint oPoint3  (padfX[iSrcVert+2],
+                               padfY[iSrcVert+2],
+                               padfZ[iSrcVert+2]);
+
+            OGRTriangle *poTriangle =
+                            new OGRTriangle(oPoint1, oPoint2, oPoint3);
+
+            poTIN->addGeometryDirectly( poTriangle );
         }
+        poGC->addGeometryDirectly(poTIN);
     }
     else if( nPartType == SHPP_TRIFAN )
     {
-        if( poLastPoly != NULL )
+        if( poMP != NULL && poLastPoly != NULL )
         {
             poMP->addGeometryDirectly( poLastPoly );
             poLastPoly = NULL;
         }
 
+        OGRTriangulatedSurface* poTIN = new OGRTriangulatedSurface();
         for( int iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
         {
-            OGRPolygon *poPoly = new OGRPolygon();
-            OGRLinearRing *poRing = new OGRLinearRing();
-            int iSrcVert = iBaseVert;
-
-            poRing->setPoint( 0,
-                            padfX[0],
-                            padfY[0],
-                            padfZ[0] );
-            poRing->setPoint( 1,
-                            padfX[iSrcVert+1],
-                            padfY[iSrcVert+1],
-                            padfZ[iSrcVert+1] );
-
-            poRing->setPoint( 2,
-                            padfX[iSrcVert+2],
-                            padfY[iSrcVert+2],
-                            padfZ[iSrcVert+2] );
-            poRing->setPoint( 3,
-                            padfX[0],
-                            padfY[0],
-                            padfZ[0] );
-
-            poPoly->addRingDirectly( poRing );
-            poMP->addGeometryDirectly( poPoly );
+            const int iSrcVert = iBaseVert;
+
+            OGRPoint oPoint1  (padfX[0], padfY[0], padfZ[0]);
+
+            OGRPoint oPoint2  (padfX[iSrcVert+1],
+                               padfY[iSrcVert+1],
+                               padfZ[iSrcVert+1]);
+
+            OGRPoint oPoint3  (padfX[iSrcVert+2],
+                               padfY[iSrcVert+2],
+                               padfZ[iSrcVert+2]);
+
+            OGRTriangle *poTriangle =
+                            new OGRTriangle(oPoint1, oPoint2, oPoint3);
+
+            poTIN->addGeometryDirectly( poTriangle );
         }
+        poGC->addGeometryDirectly(poTIN);
     }
     else if( nPartType == SHPP_OUTERRING
             || nPartType == SHPP_INNERRING
             || nPartType == SHPP_FIRSTRING
             || nPartType == SHPP_RING )
     {
-        if( poLastPoly != NULL
+        if( poMP == NULL )
+        {
+            poMP = new OGRMultiPolygon();
+        }
+
+        if( poMP != NULL && poLastPoly != NULL
             && (nPartType == SHPP_OUTERRING
                 || nPartType == SHPP_FIRSTRING) )
         {
@@ -151,83 +242,307 @@ void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
         OGRLinearRing *poRing = new OGRLinearRing;
 
         poRing->setPoints( nPartPoints,
-                            padfX,
-                            padfY,
-                            padfZ );
+                            const_cast<double*>(padfX),
+                            const_cast<double*>(padfY),
+                            const_cast<double*>(padfZ) );
 
         poRing->closeRings();
 
         poLastPoly->addRingDirectly( poRing );
     }
-    else if ( nPartType == SHPP_TRIANGLES )
+    else if( nPartType == SHPP_TRIANGLES )
     {
-        if( poLastPoly != NULL )
+        if( poMP != NULL && poLastPoly != NULL )
         {
             poMP->addGeometryDirectly( poLastPoly );
             poLastPoly = NULL;
         }
 
+        OGRTriangulatedSurface* poTIN = new OGRTriangulatedSurface();
         for( int iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert+=3 )
         {
-            OGRPolygon *poPoly = new OGRPolygon();
-            OGRLinearRing *poRing = new OGRLinearRing();
-            int iSrcVert = iBaseVert;
-
-            poRing->setPoint( 0,
-                            padfX[iSrcVert],
-                            padfY[iSrcVert],
-                            padfZ[iSrcVert] );
-            poRing->setPoint( 1,
-                            padfX[iSrcVert+1],
-                            padfY[iSrcVert+1],
-                            padfZ[iSrcVert+1] );
-
-            poRing->setPoint( 2,
-                            padfX[iSrcVert+2],
-                            padfY[iSrcVert+2],
-                            padfZ[iSrcVert+2] );
-            poRing->setPoint( 3,
-                            padfX[iSrcVert],
-                            padfY[iSrcVert],
-                            padfZ[iSrcVert] );
-
-            poPoly->addRingDirectly( poRing );
-            poMP->addGeometryDirectly( poPoly );
+            const int iSrcVert = iBaseVert;
+
+            OGRPoint oPoint1  (padfX[iSrcVert],
+                               padfY[iSrcVert],
+                               padfZ[iSrcVert]);
+
+            OGRPoint oPoint2  (padfX[iSrcVert+1],
+                               padfY[iSrcVert+1],
+                               padfZ[iSrcVert+1]);
+
+            OGRPoint oPoint3  (padfX[iSrcVert+2],
+                               padfY[iSrcVert+2],
+                               padfZ[iSrcVert+2]);
+
+            OGRTriangle *poTriangle =
+                            new OGRTriangle(oPoint1, oPoint2, oPoint3);
+
+            poTIN->addGeometryDirectly( poTriangle );
         }
+        poGC->addGeometryDirectly(poTIN);
     }
     else
         CPLDebug( "OGR", "Unrecognized parttype %d, ignored.",
                   nPartType );
 }
 
+static bool RegisterEdge(
+            const double* padfX,
+            const double* padfY,
+            const double* padfZ,
+            int nPart,
+            std::map< std::vector<double>, std::pair<int,int> >& oMapEdges )
+{
+    int idx = 0;
+    if( padfX[0] > padfX[1] )
+    {
+        idx = 1;
+    }
+    else if( padfX[0] == padfX[1] )
+    {
+        if( padfY[0] > padfY[1] )
+        {
+            idx = 1;
+        }
+        else if( padfY[0] == padfY[1] )
+        {
+            if( padfZ[0] > padfZ[1] )
+            {
+                idx = 1;
+            }
+        }
+    }
+    std::vector<double> oVector;
+    oVector.push_back(padfX[idx]);
+    oVector.push_back(padfY[idx]);
+    oVector.push_back(padfZ[idx]);
+    oVector.push_back(padfX[1-idx]);
+    oVector.push_back(padfY[1-idx]);
+    oVector.push_back(padfZ[1-idx]);
+    std::map< std::vector<double>, std::pair<int,int> >::iterator oIter =
+        oMapEdges.find(oVector);
+    if( oIter == oMapEdges.end() )
+    {
+        oMapEdges[oVector] = std::pair<int,int>(nPart, -1);
+    }
+    else
+    {
+        CPLAssert(oIter->second.first >= 0);
+        if( oIter->second.second < 0 )
+            oIter->second.second = nPart;
+        else
+            return false;
+    }
+    return true;
+}
+
+static const std::pair<int,int>& GetEdgeOwners(
+        const double* padfX,
+        const double* padfY,
+        const double* padfZ,
+        const std::map< std::vector<double>, std::pair<int,int> >& oMapEdges )
+{
+    int idx = 0;
+    if( padfX[0] > padfX[1] )
+    {
+        idx = 1;
+    }
+    else if( padfX[0] == padfX[1] )
+    {
+        if( padfY[0] > padfY[1] )
+        {
+            idx = 1;
+        }
+        else if( padfY[0] == padfY[1] )
+        {
+            if( padfZ[0] > padfZ[1] )
+            {
+                idx = 1;
+            }
+        }
+    }
+    std::vector<double> oVector;
+    oVector.push_back(padfX[idx]);
+    oVector.push_back(padfY[idx]);
+    oVector.push_back(padfZ[idx]);
+    oVector.push_back(padfX[1-idx]);
+    oVector.push_back(padfY[1-idx]);
+    oVector.push_back(padfZ[1-idx]);
+    std::map< std::vector<double>, std::pair<int,int> >::const_iterator oIter =
+        oMapEdges.find(oVector);
+    CPLAssert( oIter != oMapEdges.end() );
+    return oIter->second;
+}
+
 /************************************************************************/
 /*                     OGRCreateFromMultiPatch()                        */
 /*                                                                      */
 /*      Translate a multipatch representation to an OGR geometry        */
-/*      Mostly copied from shape2ogr.cpp                                */
 /************************************************************************/
 
-static OGRGeometry* OGRCreateFromMultiPatch(int nParts,
-                                            GInt32* panPartStart,
-                                            GInt32* panPartType,
-                                            int nPoints,
-                                            double* padfX,
-                                            double* padfY,
-                                            double* padfZ)
+OGRGeometry* OGRCreateFromMultiPatch       ( int nParts,
+                                             const GInt32* panPartStart,
+                                             const GInt32* panPartType,
+                                             int nPoints,
+                                             const double* padfX,
+                                             const double* padfY,
+                                             const double* padfZ)
 {
-    OGRMultiPolygon *poMP = new OGRMultiPolygon();
-    int iPart;
-    OGRPolygon *poLastPoly = NULL;
+    // Deal with particular case of a patch of OuterRing of 4 points
+    // that form a TIN. And be robust to consecutive duplicated triangles !
+    std::map< std::vector<double>, std::pair<int,int> > oMapEdges;
+    bool bTINCandidate = nParts >= 2;
+    std::set<int> oSetDuplicated;
+    for( int iPart = 0; iPart < nParts && panPartStart != NULL; iPart++ )
+    {
+        int nPartPoints = 0;
 
-    for( iPart = 0; iPart < nParts; iPart++ )
+        // Figure out details about this part's vertex list.
+        if( iPart == nParts - 1 )
+            nPartPoints =
+                nPoints - panPartStart[iPart];
+        else
+            nPartPoints = panPartStart[iPart+1]
+                - panPartStart[iPart];
+        const int nPartStart = panPartStart[iPart];
+
+        if( panPartType[iPart] == SHPP_OUTERRING &&
+            nPartPoints == 4 &&
+            padfX[nPartStart] == padfX[nPartStart + 3] &&
+            padfY[nPartStart] == padfY[nPartStart + 3] &&
+            padfZ[nPartStart] == padfZ[nPartStart + 3] )
+        {
+            bool bDuplicate = false;
+            if( iPart > 0 )
+            {
+                bDuplicate = true;
+                const int nPrevPartStart = panPartStart[iPart-1];
+                for( int j = 0; j < 3; j++ )
+                {
+                    if( padfX[nPartStart + j] == padfX[nPrevPartStart + j] &&
+                        padfY[nPartStart + j] == padfY[nPrevPartStart + j] &&
+                        padfZ[nPartStart + j] == padfZ[nPrevPartStart + j] )
+                    {
+                    }
+                    else
+                    {
+                        bDuplicate = false;
+                        break;
+                    }
+                }
+            }
+            if( bDuplicate )
+            {
+                oSetDuplicated.insert(iPart);
+            }
+            else
+            if ( RegisterEdge( padfX + nPartStart,
+                               padfY + nPartStart,
+                               padfZ + nPartStart,
+                               iPart,
+                               oMapEdges ) &&
+                 RegisterEdge( padfX + nPartStart + 1,
+                               padfY + nPartStart + 1,
+                               padfZ + nPartStart + 1,
+                               iPart,
+                               oMapEdges ) &&
+                 RegisterEdge( padfX + nPartStart + 2,
+                               padfY + nPartStart + 2,
+                               padfZ + nPartStart + 2,
+                               iPart,
+                               oMapEdges ) )
+            {
+                // ok
+            }
+            else
+            {
+                bTINCandidate = false;
+                break;
+            }
+        }
+        else
+        {
+            bTINCandidate = false;
+            break;
+        }
+    }
+    if( bTINCandidate && panPartStart != NULL )
     {
-        int nPartPoints, nPartStart;
+        std::set<int> oVisitedParts;
+        std::set<int> oToBeVisitedParts;
+        oToBeVisitedParts.insert(0);
+        while( !oToBeVisitedParts.empty() )
+        {
+            const int iPart = *(oToBeVisitedParts.begin());
+            oVisitedParts.insert(iPart);
+            oToBeVisitedParts.erase(iPart);
+
+            const int nPartStart = panPartStart[iPart];
+            for( int j = 0; j < 3; j++ )
+            {
+                const std::pair<int,int>& oPair =
+                    GetEdgeOwners( padfX + nPartStart + j,
+                                   padfY + nPartStart + j,
+                                   padfZ + nPartStart + j,
+                                   oMapEdges );
+                const int iOtherPart = ( oPair.first == iPart ) ?
+                                         oPair.second : oPair.first;
+                if( iOtherPart >= 0 &&
+                    oVisitedParts.find(iOtherPart) == oVisitedParts.end() )
+                {
+                    oToBeVisitedParts.insert(iOtherPart);
+                }
+            }
+        }
+        if( static_cast<int>(oVisitedParts.size()) ==
+                            nParts - static_cast<int>(oSetDuplicated.size()) )
+        {
+            OGRTriangulatedSurface* poTIN = new OGRTriangulatedSurface();
+            for( int iPart = 0; iPart < nParts; iPart++ )
+            {
+                if( oSetDuplicated.find(iPart) != oSetDuplicated.end() )
+                    continue;
+
+                int nPartStart = 0;
+                if( panPartStart != NULL )
+                {
+                    nPartStart = panPartStart[iPart];
+                }
+
+                OGRPoint oPoint1  (padfX[nPartStart],
+                                   padfY[nPartStart],
+                                   padfZ[nPartStart]);
+
+                OGRPoint oPoint2  (padfX[nPartStart+1],
+                                   padfY[nPartStart+1],
+                                   padfZ[nPartStart+1]);
+
+                OGRPoint oPoint3  (padfX[nPartStart+2],
+                                   padfY[nPartStart+2],
+                                   padfZ[nPartStart+2]);
+
+                OGRTriangle *poTriangle =
+                                new OGRTriangle(oPoint1, oPoint2, oPoint3);
+
+                poTIN->addGeometryDirectly( poTriangle );
+            }
+            return poTIN;
+        }
+    }
+
+    OGRGeometryCollection *poGC = new OGRGeometryCollection();
+    OGRMultiPolygon *poMP = NULL;
+    OGRPolygon *poLastPoly = NULL;
+    for( int iPart = 0; iPart < nParts; iPart++ )
+    {
+        int nPartPoints = 0;
+        int nPartStart = 0;
 
         // Figure out details about this part's vertex list.
         if( panPartStart == NULL )
         {
             nPartPoints = nPoints;
-            nPartStart = 0;
         }
         else
         {
@@ -241,7 +556,8 @@ static OGRGeometry* OGRCreateFromMultiPatch(int nParts,
             nPartStart = panPartStart[iPart];
         }
 
-        OGRCreateFromMultiPatchPart(poMP,
+        OGRCreateFromMultiPatchPart(poGC,
+                                    poMP,
                                     poLastPoly,
                                     panPartType[iPart],
                                     nPartPoints,
@@ -250,15 +566,26 @@ static OGRGeometry* OGRCreateFromMultiPatch(int nParts,
                                     padfZ + nPartStart);
     }
 
-    if( poLastPoly != NULL )
+
+    if( poMP != NULL && poLastPoly != NULL )
     {
         poMP->addGeometryDirectly( poLastPoly );
-        poLastPoly = NULL;
+        // poLastPoly = NULL;
     }
+    if( poMP != NULL )
+        poGC->addGeometryDirectly(poMP);
 
-    return poMP;
-}
+    if (poGC->getNumGeometries() == 1)
+    {
+        OGRGeometry *poResultGeom = poGC->getGeometryRef(0);
+        poGC->removeGeometry( 0, FALSE );
+        delete poGC;
+        return poResultGeom;
+    }
 
+    else
+        return poGC;
+}
 
 /************************************************************************/
 /*                      OGRWriteToShapeBin()                            */
@@ -270,17 +597,14 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                            GByte **ppabyShape,
                            int *pnBytes )
 {
-    int nShpSize = 4; /* All types start with integer type number */
-    int nShpZSize = 0; /* Z gets tacked onto the end */
-    GUInt32 nPoints = 0;
-    GUInt32 nParts = 0;
+    int nShpSize = 4;  // All types start with integer type number.
 
 /* -------------------------------------------------------------------- */
 /*      Null or Empty input maps to SHPT_NULL.                          */
 /* -------------------------------------------------------------------- */
-    if ( ! poGeom || poGeom->IsEmpty() )
+    if( !poGeom || poGeom->IsEmpty() )
     {
-        *ppabyShape = (GByte*)VSI_MALLOC_VERBOSE(nShpSize);
+        *ppabyShape = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nShpSize));
         if( *ppabyShape == NULL )
             return OGRERR_FAILURE;
         GUInt32 zero = SHPT_NULL;
@@ -289,86 +613,89 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         return OGRERR_NONE;
     }
 
-    OGRwkbGeometryType nOGRType = wkbFlatten(poGeom->getGeometryType());
+    const OGRwkbGeometryType nOGRType = wkbFlatten(poGeom->getGeometryType());
     const bool b3d = wkbHasZ(poGeom->getGeometryType());
     const bool bHasM = wkbHasM(poGeom->getGeometryType());
     const int nCoordDims = poGeom->CoordinateDimension();
 
+    int nShpZSize = 0;  // Z gets tacked onto the end.
+    GUInt32 nPoints = 0;
+    GUInt32 nParts = 0;
+
 /* -------------------------------------------------------------------- */
 /*      Calculate the shape buffer size                                 */
 /* -------------------------------------------------------------------- */
-    if ( nOGRType == wkbPoint )
+    if( nOGRType == wkbPoint )
     {
         nShpSize += 8 * nCoordDims;
     }
-    else if ( nOGRType == wkbLineString )
+    else if( nOGRType == wkbLineString )
     {
         OGRLineString *poLine = (OGRLineString*)poGeom;
         nPoints = poLine->getNumPoints();
         nParts = 1;
-        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
-        nShpSize += 4; /* nparts */
-        nShpSize += 4; /* npoints */
-        nShpSize += 4; /* parts[1] */
-        nShpSize += 8 * nCoordDims * nPoints; /* points */
+        nShpSize += 16 * nCoordDims;  // xy(z)(m) box.
+        nShpSize += 4;  // nparts.
+        nShpSize += 4;  // npoints.
+        nShpSize += 4;  // Parts[1].
+        nShpSize += 8 * nCoordDims * nPoints;  // Points.
         nShpZSize = 16 + 8 * nPoints;
     }
-    else if ( nOGRType == wkbPolygon )
+    else if( nOGRType == wkbPolygon )
     {
         poGeom->closeRings();
         OGRPolygon *poPoly = (OGRPolygon*)poGeom;
         nParts = poPoly->getNumInteriorRings() + 1;
-        for ( GUInt32 i = 0; i < nParts; i++ )
+        for( GUInt32 i = 0; i < nParts; i++ )
         {
-            OGRLinearRing *poRing;
-            if ( i == 0 )
-                poRing = poPoly->getExteriorRing();
-            else
-                poRing = poPoly->getInteriorRing(i-1);
+            OGRLinearRing *poRing = i == 0
+                ? poPoly->getExteriorRing()
+                : poPoly->getInteriorRing(i-1);
             nPoints += poRing->getNumPoints();
         }
-        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
-        nShpSize += 4; /* nparts */
-        nShpSize += 4; /* npoints */
-        nShpSize += 4 * nParts; /* parts[nparts] */
-        nShpSize += 8 * nCoordDims * nPoints; /* points */
+        nShpSize += 16 * nCoordDims;  // xy(z)(m) box.
+        nShpSize += 4;  // nparts.
+        nShpSize += 4;  // npoints.
+        nShpSize += 4 * nParts;  // parts[nparts]
+        nShpSize += 8 * nCoordDims * nPoints;  // Points.
         nShpZSize = 16 + 8 * nPoints;
     }
-    else if ( nOGRType == wkbMultiPoint )
+    else if( nOGRType == wkbMultiPoint )
     {
         OGRMultiPoint *poMPoint = (OGRMultiPoint*)poGeom;
-        for ( int i = 0; i < poMPoint->getNumGeometries(); i++ )
+        for( int i = 0; i < poMPoint->getNumGeometries(); i++ )
         {
             OGRPoint *poPoint = (OGRPoint*)(poMPoint->getGeometryRef(i));
-            if ( poPoint->IsEmpty() )
+            if( poPoint->IsEmpty() )
                 continue;
             nPoints++;
         }
-        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
-        nShpSize += 4; /* npoints */
-        nShpSize += 8 * nCoordDims * nPoints; /* points */
+        nShpSize += 16 * nCoordDims;  // xy(z)(m) box.
+        nShpSize += 4;  // npoints.
+        nShpSize += 8 * nCoordDims * nPoints; // Points.
         nShpZSize = 16 + 8 * nPoints;
     }
-    else if ( nOGRType == wkbMultiLineString )
+    else if( nOGRType == wkbMultiLineString )
     {
         OGRMultiLineString *poMLine = (OGRMultiLineString*)poGeom;
-        for ( int i = 0; i < poMLine->getNumGeometries(); i++ )
+        for( int i = 0; i < poMLine->getNumGeometries(); i++ )
         {
-            OGRLineString *poLine = (OGRLineString*)(poMLine->getGeometryRef(i));
-            /* Skip empties */
-            if ( poLine->IsEmpty() )
+            OGRLineString *poLine =
+                (OGRLineString*)(poMLine->getGeometryRef(i));
+            // Skip empties.
+            if( poLine->IsEmpty() )
                 continue;
             nParts++;
             nPoints += poLine->getNumPoints();
         }
-        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
-        nShpSize += 4; /* nparts */
-        nShpSize += 4; /* npoints */
-        nShpSize += 4 * nParts; /* parts[nparts] */
-        nShpSize += 8 * nCoordDims * nPoints ; /* points */
+        nShpSize += 16 * nCoordDims;  //* xy(z)(m) box.
+        nShpSize += 4;  // nparts.
+        nShpSize += 4;  // npoints.
+        nShpSize += 4 * nParts;  // parts[nparts].
+        nShpSize += 8 * nCoordDims * nPoints;  // Points.
         nShpZSize = 16 + 8 * nPoints;
     }
-    else if ( nOGRType == wkbMultiPolygon )
+    else if( nOGRType == wkbMultiPolygon )
     {
         poGeom->closeRings();
         OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
@@ -377,26 +704,24 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             OGRPolygon *poPoly = (OGRPolygon*)(poMPoly->getGeometryRef(j));
             int nRings = poPoly->getNumInteriorRings() + 1;
 
-            /* Skip empties */
-            if ( poPoly->IsEmpty() )
+            // Skip empties.
+            if( poPoly->IsEmpty() )
                 continue;
 
             nParts += nRings;
-            for ( int i = 0; i < nRings; i++ )
+            for( int i = 0; i < nRings; i++ )
             {
-                OGRLinearRing *poRing;
-                if ( i == 0 )
-                    poRing = poPoly->getExteriorRing();
-                else
-                    poRing = poPoly->getInteriorRing(i-1);
+                OGRLinearRing *poRing = i == 0
+                    ? poPoly->getExteriorRing()
+                    : poPoly->getInteriorRing(i-1);
                 nPoints += poRing->getNumPoints();
             }
         }
-        nShpSize += 16 * nCoordDims; /* xy(z)(m) box */
-        nShpSize += 4; /* nparts */
-        nShpSize += 4; /* npoints */
-        nShpSize += 4 * nParts; /* parts[nparts] */
-        nShpSize += 8 * nCoordDims * nPoints ; /* points */
+        nShpSize += 16 * nCoordDims;  // xy(z)(m) box.
+        nShpSize += 4; // nparts.
+        nShpSize += 4; // npoints.
+        nShpSize += 4 * nParts;  // parts[nparts].
+        nShpSize += 8 * nCoordDims * nPoints;  // Points.
         nShpZSize = 16 + 8 * nPoints;
     }
     else
@@ -404,21 +729,102 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         return OGRERR_UNSUPPORTED_OPERATION;
     }
 
-    /* Allocate our shape buffer */
-    *ppabyShape = (GByte*)VSI_MALLOC_VERBOSE(nShpSize);
-    if ( ! *ppabyShape )
+//#define WRITE_ARC_HACK
+#ifdef WRITE_ARC_HACK
+    int nShpSizeBeforeCurve = nShpSize;
+    nShpSize += 4 + 4 + 4 + 20;
+#endif
+    // Allocate our shape buffer.
+    *ppabyShape = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nShpSize));
+    if( !*ppabyShape )
         return OGRERR_FAILURE;
 
-    /* Fill in the output size. */
+#ifdef WRITE_ARC_HACK
+    /* To be used with:
+id,WKT
+1,"LINESTRING (1 0,0 1)"
+2,"LINESTRING (5 1,6 0)"
+3,"LINESTRING (10 1,11 0)"
+4,"LINESTRING (16 0,15 1)"
+5,"LINESTRING (21 0,20 1)"
+6,"LINESTRING (31 0,30 2)" <-- not constant radius
+    */
+
+    GUInt32 nTmp = 1;
+    memcpy((*ppabyShape) + nShpSizeBeforeCurve, &nTmp, 4);
+    nTmp = 0;
+    memcpy((*ppabyShape) + nShpSizeBeforeCurve + 4, &nTmp, 4);
+    nTmp = EXT_SHAPE_SEGMENT_ARC;
+    memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8, &nTmp, 4);
+    static int nCounter = 0;
+    nCounter++;
+    if( nCounter == 1 )
+    {
+        double dfVal = 0;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4, &dfVal, 8);
+        dfVal = 0;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 8, &dfVal, 8);
+        nTmp = 0;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 16, &nTmp, 4);
+    }
+    else if( nCounter == 2 )
+    {
+        double dfVal = 5;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4, &dfVal, 8);
+        dfVal = 0;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 8, &dfVal, 8);
+        nTmp = EXT_SHAPE_ARC_MINOR;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 16, &nTmp, 4);
+    }
+    else if( nCounter == 3 )
+    {
+        double dfVal = 10;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4, &dfVal, 8);
+        dfVal = 0;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 8, &dfVal, 8);
+        nTmp = EXT_SHAPE_ARC_CCW;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 16, &nTmp, 4);
+    }
+    else if( nCounter == 4 )
+    {
+        double dfVal = 15;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4, &dfVal, 8);
+        dfVal = 0;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 8, &dfVal, 8);
+        nTmp = EXT_SHAPE_ARC_CCW | EXT_SHAPE_ARC_MINOR;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 16, &nTmp, 4);
+    }
+    else if( nCounter == 5 )
+    {
+        double dfVal = 20;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4, &dfVal, 8);
+        dfVal = 0;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 8, &dfVal, 8);
+         // Inconsistent with SP and EP. Only the CCW/not CCW is taken into
+         // account by ArcGIS.
+        nTmp = EXT_SHAPE_ARC_MINOR;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 16, &nTmp, 4);
+    }
+    else if( nCounter == 6 )
+    {
+        double dfVal = 30; // Radius inconsistent with SP and EP.
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4, &dfVal, 8);
+        dfVal = 0;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 8, &dfVal, 8);
+        nTmp = EXT_SHAPE_ARC_MINOR;
+        memcpy((*ppabyShape) + nShpSizeBeforeCurve + 8 + 4 + 16, &nTmp, 4);
+    }
+#endif
+
+    // Fill in the output size.
     *pnBytes = nShpSize;
 
-    /* Set up write pointers */
+    // Set up write pointers.
     unsigned char *pabyPtr = *ppabyShape;
+    unsigned char *pabyPtrM = bHasM ? pabyPtr + nShpSize - nShpZSize : NULL;
+
     unsigned char *pabyPtrZ = NULL;
-    unsigned char *pabyPtrM = NULL;
-    if( bHasM )
-        pabyPtrM = pabyPtr + nShpSize - nShpZSize;
-    if ( b3d )
+    if( b3d )
     {
         if( bHasM )
             pabyPtrZ = pabyPtrM - nShpZSize;
@@ -431,7 +837,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 /* -------------------------------------------------------------------- */
     GUInt32 nGType = SHPT_NULL;
 
-    switch(nOGRType)
+    switch( nOGRType )
     {
         case wkbPoint:
         {
@@ -472,22 +878,25 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             return OGRERR_UNSUPPORTED_OPERATION;
         }
     }
-    /* Write in the type number and advance the pointer */
-    nGType = CPL_LSBWORD32( nGType );
+    // Write in the type number and advance the pointer.
+#ifdef WRITE_ARC_HACK
+    nGType = SHPT_GENERALPOLYLINE | 0x20000000;
+#endif
+
+    CPL_LSBPTR32( &nGType );
     memcpy( pabyPtr, &nGType, 4 );
     pabyPtr += 4;
 
-
 /* -------------------------------------------------------------------- */
 /*      POINT and POINTZ                                                */
 /* -------------------------------------------------------------------- */
-    if ( nOGRType == wkbPoint )
+    if( nOGRType == wkbPoint )
     {
         OGRPoint *poPoint = (OGRPoint*)poGeom;
-        double x = poPoint->getX();
-        double y = poPoint->getY();
+        const double x = poPoint->getX();
+        const double y = poPoint->getY();
 
-        /* Copy in the raw data. */
+        // Copy in the raw data.
         memcpy( pabyPtr, &x, 8 );
         memcpy( pabyPtr+8, &y, 8 );
         if( b3d )
@@ -501,7 +910,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             memcpy( pabyPtr+8+((b3d) ? 16 : 8), &m, 8 );
         }
 
-        /* Swap if needed. Shape doubles always LSB */
+        // Swap if needed. Shape doubles always LSB.
         if( OGR_SWAP( wkbNDR ) )
         {
             CPL_SWAPDOUBLE( pabyPtr );
@@ -525,34 +934,34 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
     memcpy( pabyPtr+8+8, &(envelope.MaxX), 8 );
     memcpy( pabyPtr+8+8+8, &(envelope.MaxY), 8 );
 
-    /* Swap box if needed. Shape doubles are always LSB */
+    // Swap box if needed. Shape doubles are always LSB.
     if( OGR_SWAP( wkbNDR ) )
     {
-        for ( int i = 0; i < 4; i++ )
+        for( int i = 0; i < 4; i++ )
             CPL_SWAPDOUBLE( pabyPtr + 8*i );
     }
     pabyPtr += 32;
 
-    /* Write in the Z bounds at the end of the XY buffer */
-    if ( b3d )
+    // Write in the Z bounds at the end of the XY buffer.
+    if( b3d )
     {
         memcpy( pabyPtrZ, &(envelope.MinZ), 8 );
         memcpy( pabyPtrZ+8, &(envelope.MaxZ), 8 );
 
-        /* Swap Z bounds if necessary */
+        // Swap Z bounds if necessary.
         if( OGR_SWAP( wkbNDR ) )
         {
-            for ( int i = 0; i < 2; i++ )
+            for( int i = 0; i < 2; i++ )
                 CPL_SWAPDOUBLE( pabyPtrZ + 8*i );
         }
         pabyPtrZ += 16;
     }
 
-    /* Reserve space for the M bounds at the end of the XY buffer */
+    // Reserve space for the M bounds at the end of the XY buffer.
     GByte* pabyPtrMBounds = NULL;
     double dfMinM = std::numeric_limits<double>::max();
     double dfMaxM = -dfMinM;
-    if ( bHasM )
+    if( bHasM )
     {
         pabyPtrMBounds = pabyPtrM;
         pabyPtrM += 16;
@@ -561,26 +970,26 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 /* -------------------------------------------------------------------- */
 /*      LINESTRING and LINESTRINGZ                                      */
 /* -------------------------------------------------------------------- */
-    if ( nOGRType == wkbLineString )
+    if( nOGRType == wkbLineString )
     {
         const OGRLineString *poLine = (OGRLineString*)poGeom;
 
-        /* Write in the nparts (1) */
-        GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
+        // Write in the nparts (1).
+        const GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
         memcpy( pabyPtr, &nPartsLsb, 4 );
         pabyPtr += 4;
 
-        /* Write in the npoints */
+        // Write in the npoints.
         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
         memcpy( pabyPtr, &nPointsLsb, 4 );
         pabyPtr += 4;
 
-        /* Write in the part index (0) */
+        // Write in the part index (0).
         GUInt32 nPartIndex = 0;
         memcpy( pabyPtr, &nPartIndex, 4 );
         pabyPtr += 4;
 
-        /* Write in the point data */
+        // Write in the point data.
         poLine->getPoints((OGRRawPoint*)pabyPtr, (double*)pabyPtrZ);
         if( bHasM )
         {
@@ -593,8 +1002,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             }
         }
 
-
-        /* Swap if necessary */
+        // Swap if necessary.
         if( OGR_SWAP( wkbNDR ) )
         {
             for( GUInt32 k = 0; k < nPoints; k++ )
@@ -611,16 +1019,16 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 /* -------------------------------------------------------------------- */
 /*      POLYGON and POLYGONZ                                            */
 /* -------------------------------------------------------------------- */
-    else if ( nOGRType == wkbPolygon )
+    else if( nOGRType == wkbPolygon )
     {
         OGRPolygon *poPoly = (OGRPolygon*)poGeom;
 
-        /* Write in the part count */
+        // Write in the part count.
         GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
         memcpy( pabyPtr, &nPartsLsb, 4 );
         pabyPtr += 4;
 
-        /* Write in the total point count */
+        // Write in the total point count.
         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
         memcpy( pabyPtr, &nPointsLsb, 4 );
         pabyPtr += 4;
@@ -634,41 +1042,43 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 /*      pabyPtrZ writes the z coordinates                               */
 /* -------------------------------------------------------------------- */
 
-        /* Just past the partindex[nparts] array */
+        // Just past the partindex[nparts] array.
         unsigned char* pabyPoints = pabyPtr + 4*nParts;
 
         int nPointIndexCount = 0;
 
         for( GUInt32 i = 0; i < nParts; i++ )
         {
-            /* Check our Ring and condition it */
-            OGRLinearRing *poRing;
-            if ( i == 0 )
+            // Check our Ring and condition it.
+            OGRLinearRing *poRing = NULL;
+            if( i == 0 )
             {
                 poRing = poPoly->getExteriorRing();
-                /* Outer ring must be clockwise */
-                if ( ! poRing->isClockwise() )
+                // Outer ring must be clockwise.
+                if( !poRing->isClockwise() )
                     poRing->reverseWindingOrder();
             }
             else
             {
                 poRing = poPoly->getInteriorRing(i-1);
-                /* Inner rings should be anti-clockwise */
-                if ( poRing->isClockwise() )
+                // Inner rings should be anti-clockwise.
+                if( poRing->isClockwise() )
                     poRing->reverseWindingOrder();
             }
 
             int nRingNumPoints = poRing->getNumPoints();
 
-            /* Cannot write un-closed rings to shape */
-            if( nRingNumPoints <= 2 || ! poRing->get_IsClosed() )
+#ifndef WRITE_ARC_HACK
+            // Cannot write un-closed rings to shape.
+            if( nRingNumPoints <= 2 || !poRing->get_IsClosed() )
                 return OGRERR_FAILURE;
+#endif
 
-            /* Write in the part index */
+            // Write in the part index.
             GUInt32 nPartIndex = CPL_LSBWORD32( nPointIndexCount );
             memcpy( pabyPtr, &nPartIndex, 4 );
 
-            /* Write in the point data */
+            // Write in the point data.
             poRing->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
             if( bHasM )
             {
@@ -681,7 +1091,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 }
             }
 
-            /* Swap if necessary */
+            // Swap if necessary.
             if( OGR_SWAP( wkbNDR ) )
             {
                 for( int k = 0; k < nRingNumPoints; k++ )
@@ -696,23 +1106,23 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
             }
 
             nPointIndexCount += nRingNumPoints;
-            /* Advance the write pointers */
+            // Advance the write pointers.
             pabyPtr += 4;
             pabyPoints += 16 * nRingNumPoints;
-            if ( b3d )
+            if( b3d )
                 pabyPtrZ += 8 * nRingNumPoints;
-            if ( bHasM )
+            if( bHasM )
                 pabyPtrM += 8 * nRingNumPoints;
         }
     }
 /* -------------------------------------------------------------------- */
 /*      MULTIPOINT and MULTIPOINTZ                                      */
 /* -------------------------------------------------------------------- */
-    else if ( nOGRType == wkbMultiPoint )
+    else if( nOGRType == wkbMultiPoint )
     {
         OGRMultiPoint *poMPoint = (OGRMultiPoint*)poGeom;
 
-        /* Write in the total point count */
+        // Write in the total point count.
         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
         memcpy( pabyPtr, &nPointsLsb, 4 );
         pabyPtr += 4;
@@ -728,21 +1138,21 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         {
             const OGRPoint *poPt = (OGRPoint*)(poMPoint->getGeometryRef(i));
 
-            /* Skip empties */
-            if ( poPt->IsEmpty() )
+            // Skip empties.
+            if( poPt->IsEmpty() )
                 continue;
 
-            /* Write the coordinates */
+            // Write the coordinates.
             double x = poPt->getX();
             double y = poPt->getY();
             memcpy(pabyPtr, &x, 8);
             memcpy(pabyPtr+8, &y, 8);
-            if ( b3d )
+            if( b3d )
             {
                 double z = poPt->getZ();
                 memcpy(pabyPtrZ, &z, 8);
             }
-            if ( bHasM )
+            if( bHasM )
             {
                 double dfM = poPt->getM();
                 memcpy(pabyPtrM, &dfM, 8);
@@ -750,7 +1160,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 if( dfM > dfMaxM ) dfMaxM = dfM;
             }
 
-            /* Swap if necessary */
+            // Swap if necessary.
             if( OGR_SWAP( wkbNDR ) )
             {
                 CPL_SWAPDOUBLE( pabyPtr );
@@ -761,11 +1171,11 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                     CPL_SWAPDOUBLE( pabyPtrM );
             }
 
-            /* Advance the write pointers */
+            // Advance the write pointers.
             pabyPtr += 16;
-            if ( b3d )
+            if( b3d )
                 pabyPtrZ += 8;
-            if ( bHasM )
+            if( bHasM )
                 pabyPtrM += 8;
         }
     }
@@ -773,40 +1183,41 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 /* -------------------------------------------------------------------- */
 /*      MULTILINESTRING and MULTILINESTRINGZ                            */
 /* -------------------------------------------------------------------- */
-    else if ( nOGRType == wkbMultiLineString )
+    else if( nOGRType == wkbMultiLineString )
     {
         OGRMultiLineString *poMLine = (OGRMultiLineString*)poGeom;
 
-        /* Write in the part count */
+        // Write in the part count.
         GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
         memcpy( pabyPtr, &nPartsLsb, 4 );
         pabyPtr += 4;
 
-        /* Write in the total point count */
+        // Write in the total point count.
         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
         memcpy( pabyPtr, &nPointsLsb, 4 );
         pabyPtr += 4;
 
-        /* Just past the partindex[nparts] array */
+        // Just past the partindex[nparts] array.
         unsigned char* pabyPoints = pabyPtr + 4*nParts;
 
         int nPointIndexCount = 0;
 
         for( GUInt32 i = 0; i < nParts; i++ )
         {
-            const OGRLineString *poLine = (OGRLineString*)(poMLine->getGeometryRef(i));
+            const OGRLineString *poLine =
+                (OGRLineString*)(poMLine->getGeometryRef(i));
 
-            /* Skip empties */
-            if ( poLine->IsEmpty() )
+            // Skip empties.
+            if( poLine->IsEmpty() )
                 continue;
 
             int nLineNumPoints = poLine->getNumPoints();
 
-            /* Write in the part index */
+            // Write in the part index.
             GUInt32 nPartIndex = CPL_LSBWORD32( nPointIndexCount );
             memcpy( pabyPtr, &nPartIndex, 4 );
 
-            /* Write in the point data */
+            // Write in the point data.
             poLine->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
             if( bHasM )
             {
@@ -819,7 +1230,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 }
             }
 
-            /* Swap if necessary */
+            // Swap if necessary.
             if( OGR_SWAP( wkbNDR ) )
             {
                 for( int k = 0; k < nLineNumPoints; k++ )
@@ -835,28 +1246,28 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 
             nPointIndexCount += nLineNumPoints;
 
-            /* Advance the write pointers */
+            // Advance the write pointers.
             pabyPtr += 4;
             pabyPoints += 16 * nLineNumPoints;
-            if ( b3d )
+            if( b3d )
                 pabyPtrZ += 8 * nLineNumPoints;
-            if ( bHasM )
+            if( bHasM )
                 pabyPtrM += 8 * nLineNumPoints;
         }
     }
 /* -------------------------------------------------------------------- */
 /*      MULTIPOLYGON and MULTIPOLYGONZ                                  */
 /* -------------------------------------------------------------------- */
-    else /* if ( nOGRType == wkbMultiPolygon ) */
+    else  // if( nOGRType == wkbMultiPolygon )
     {
         OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
 
-        /* Write in the part count */
+        // Write in the part count.
         GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
         memcpy( pabyPtr, &nPartsLsb, 4 );
         pabyPtr += 4;
 
-        /* Write in the total point count */
+        // Write in the total point count.
         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
         memcpy( pabyPtr, &nPointsLsb, 4 );
         pabyPtr += 4;
@@ -870,7 +1281,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
 /*      pabyPtrZ writes the z coordinates                               */
 /* -------------------------------------------------------------------- */
 
-        /* Just past the partindex[nparts] array */
+        // Just past the partindex[nparts] array.
         unsigned char* pabyPoints = pabyPtr + 4*nParts;
 
         int nPointIndexCount = 0;
@@ -879,42 +1290,42 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         {
             OGRPolygon *poPoly = (OGRPolygon*)(poMPoly->getGeometryRef(i));
 
-            /* Skip empties */
-            if ( poPoly->IsEmpty() )
+            // Skip empties.
+            if( poPoly->IsEmpty() )
                 continue;
 
             int nRings = 1 + poPoly->getNumInteriorRings();
 
             for( int j = 0; j < nRings; j++ )
             {
-                /* Check our Ring and condition it */
-                OGRLinearRing *poRing;
-                if ( j == 0 )
+                // Check our Ring and condition it.
+                OGRLinearRing *poRing = NULL;
+                if( j == 0 )
                 {
                     poRing = poPoly->getExteriorRing();
-                    /* Outer ring must be clockwise */
-                    if ( ! poRing->isClockwise() )
+                    // Outer ring must be clockwise.
+                    if( !poRing->isClockwise() )
                         poRing->reverseWindingOrder();
                 }
                 else
                 {
                     poRing = poPoly->getInteriorRing(j-1);
-                    /* Inner rings should be anti-clockwise */
-                    if ( poRing->isClockwise() )
+                    // Inner rings should be anti-clockwise.
+                    if( poRing->isClockwise() )
                         poRing->reverseWindingOrder();
                 }
 
                 int nRingNumPoints = poRing->getNumPoints();
 
-                /* Cannot write closed rings to shape */
-                if( nRingNumPoints <= 2 || ! poRing->get_IsClosed() )
+                // Cannot write closed rings to shape.
+                if( nRingNumPoints <= 2 || !poRing->get_IsClosed() )
                     return OGRERR_FAILURE;
 
-                /* Write in the part index */
+                // Write in the part index.
                 GUInt32 nPartIndex = CPL_LSBWORD32( nPointIndexCount );
                 memcpy( pabyPtr, &nPartIndex, 4 );
 
-                /* Write in the point data */
+                // Write in the point data.
                 poRing->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
                 if( bHasM )
                 {
@@ -927,7 +1338,7 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                     }
                 }
 
-                /* Swap if necessary */
+                // Swap if necessary.
                 if( OGR_SWAP( wkbNDR ) )
                 {
                     for( int k = 0; k < nRingNumPoints; k++ )
@@ -942,18 +1353,18 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
                 }
 
                 nPointIndexCount += nRingNumPoints;
-                /* Advance the write pointers */
+                // Advance the write pointers.
                 pabyPtr += 4;
                 pabyPoints += 16 * nRingNumPoints;
-                if ( b3d )
+                if( b3d )
                     pabyPtrZ += 8 * nRingNumPoints;
-                if ( bHasM )
+                if( bHasM )
                     pabyPtrM += 8 * nRingNumPoints;
             }
         }
     }
 
-    if ( bHasM )
+    if( bHasM )
     {
         if( dfMinM > dfMaxM )
         {
@@ -963,10 +1374,10 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
         memcpy( pabyPtrMBounds, &(dfMinM), 8 );
         memcpy( pabyPtrMBounds+8, &(dfMaxM), 8 );
 
-        /* Swap M bounds if necessary */
+        // Swap M bounds if necessary.
         if( OGR_SWAP( wkbNDR ) )
         {
-            for ( int i = 0; i < 2; i++ )
+            for( int i = 0; i < 2; i++ )
                 CPL_SWAPDOUBLE( pabyPtrMBounds + 8*i );
         }
     }
@@ -974,114 +1385,165 @@ OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom,
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
-/*                   OGRWriteMultiPatchToShapeBin()                     */
+/*                         OGRCreateMultiPatch()                        */
 /************************************************************************/
 
-OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
-                                     GByte **ppabyShape,
-                                     int *pnBytes )
+OGRErr OGRCreateMultiPatch( OGRGeometry *poGeom,
+                            int bAllowSHPTTriangle,
+                            int& nParts,
+                            int*& panPartStart,
+                            int*& panPartType,
+                            int& nPoints,
+                            OGRRawPoint*& poPoints,
+                            double*& padfZ )
 {
-    if( wkbFlatten(poGeom->getGeometryType()) != wkbMultiPolygon )
+    const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
+    if( eType != wkbPolygon && eType != wkbTriangle &&
+        eType != wkbMultiPolygon && eType != wkbMultiSurface &&
+        eType != wkbTIN &&
+        eType != wkbPolyhedralSurface && eType != wkbGeometryCollection )
+    {
         return OGRERR_UNSUPPORTED_OPERATION;
+    }
 
     poGeom->closeRings();
-    OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
-    int nParts = 0;
-    int* panPartStart = NULL;
-    int* panPartType = NULL;
-    int nPoints = 0;
-    OGRRawPoint* poPoints = NULL;
-    double* padfZ = NULL;
-    int nBeginLastPart = 0;
 
+    OGRMultiPolygon *poMPoly;
+    OGRGeometry* poGeomToDelete = NULL;
+    if( eType == wkbMultiPolygon )
+        poMPoly = dynamic_cast<OGRMultiPolygon*>(poGeom);
+    else
+    {
+        poGeomToDelete =
+                OGRGeometryFactory::forceToMultiPolygon(poGeom->clone());
+        poMPoly = dynamic_cast<OGRMultiPolygon*>(poGeomToDelete);
+    }
+    if( poMPoly == NULL )
+    {
+        delete poGeomToDelete;
+        return OGRERR_UNSUPPORTED_OPERATION;
+    }
+
+    nParts = 0;
+    panPartStart = NULL;
+    panPartType = NULL;
+    nPoints = 0;
+    poPoints = NULL;
+    padfZ = NULL;
+    int nBeginLastPart = 0;
     for( int j = 0; j < poMPoly->getNumGeometries(); j++ )
     {
         OGRPolygon *poPoly = (OGRPolygon*)(poMPoly->getGeometryRef(j));
         int nRings = poPoly->getNumInteriorRings() + 1;
 
-        /* Skip empties */
-        if ( poPoly->IsEmpty() )
+        // Skip empties.
+        if( poPoly->IsEmpty() )
             continue;
 
         OGRLinearRing *poRing = poPoly->getExteriorRing();
         if( nRings == 1 && poRing->getNumPoints() == 4 )
         {
+            int nCorrectedPoints = nPoints;
             if( nParts > 0 && poPoints != NULL &&
-                ((panPartType[nParts-1] == SHPP_TRIANGLES && nPoints - panPartStart[nParts-1] == 3) ||
+                panPartType[nParts-1] == SHPP_OUTERRING &&
+                nPoints - panPartStart[nParts-1] == 4 )
+            {
+                nCorrectedPoints--;
+            }
+
+            if( nParts > 0 && poPoints != NULL &&
+                ((panPartType[nParts-1] == SHPP_TRIANGLES &&
+                  nPoints - panPartStart[nParts-1] == 3) ||
+                 (panPartType[nParts-1] == SHPP_OUTERRING &&
+                  nPoints - panPartStart[nParts-1] == 4) ||
                  panPartType[nParts-1] == SHPP_TRIFAN) &&
                 poRing->getX(0) == poPoints[nBeginLastPart].x &&
                 poRing->getY(0) == poPoints[nBeginLastPart].y &&
                 poRing->getZ(0) == padfZ[nBeginLastPart] &&
-                poRing->getX(1) == poPoints[nPoints-1].x &&
-                poRing->getY(1) == poPoints[nPoints-1].y &&
-                poRing->getZ(1) == padfZ[nPoints-1] )
+                poRing->getX(1) == poPoints[nCorrectedPoints-1].x &&
+                poRing->getY(1) == poPoints[nCorrectedPoints-1].y &&
+                poRing->getZ(1) == padfZ[nCorrectedPoints-1] )
             {
+                nPoints  = nCorrectedPoints;
                 panPartType[nParts-1] = SHPP_TRIFAN;
 
-                poPoints = (OGRRawPoint*)CPLRealloc(poPoints,
-                                            (nPoints + 1) * sizeof(OGRRawPoint));
-                padfZ = (double*)CPLRealloc(padfZ, (nPoints + 1) * sizeof(double));
+                poPoints = static_cast<OGRRawPoint *>(
+                    CPLRealloc(poPoints, (nPoints + 1) * sizeof(OGRRawPoint)));
+                padfZ = static_cast<double *>(
+                    CPLRealloc(padfZ, (nPoints + 1) * sizeof(double)));
                 poPoints[nPoints].x = poRing->getX(2);
                 poPoints[nPoints].y = poRing->getY(2);
                 padfZ[nPoints] = poRing->getZ(2);
-                nPoints ++;
+                nPoints++;
             }
             else if( nParts > 0 && poPoints != NULL &&
-                ((panPartType[nParts-1] == SHPP_TRIANGLES && nPoints - panPartStart[nParts-1] == 3) ||
+                ((panPartType[nParts-1] == SHPP_TRIANGLES &&
+                  nPoints - panPartStart[nParts-1] == 3)||
+                 (panPartType[nParts-1] == SHPP_OUTERRING &&
+                  nPoints - panPartStart[nParts-1] == 4) ||
                  panPartType[nParts-1] == SHPP_TRISTRIP) &&
-                poRing->getX(0) == poPoints[nPoints-2].x &&
-                poRing->getY(0) == poPoints[nPoints-2].y &&
-                poRing->getZ(0) == padfZ[nPoints-2] &&
-                poRing->getX(1) == poPoints[nPoints-1].x &&
-                poRing->getY(1) == poPoints[nPoints-1].y &&
-                poRing->getZ(1) == padfZ[nPoints-1] )
+                poRing->getX(0) == poPoints[nCorrectedPoints-2].x &&
+                poRing->getY(0) == poPoints[nCorrectedPoints-2].y &&
+                poRing->getZ(0) == padfZ[nCorrectedPoints-2] &&
+                poRing->getX(1) == poPoints[nCorrectedPoints-1].x &&
+                poRing->getY(1) == poPoints[nCorrectedPoints-1].y &&
+                poRing->getZ(1) == padfZ[nCorrectedPoints-1] )
             {
+                nPoints  = nCorrectedPoints;
                 panPartType[nParts-1] = SHPP_TRISTRIP;
 
-                poPoints = (OGRRawPoint*)CPLRealloc(poPoints,
-                                            (nPoints + 1) * sizeof(OGRRawPoint));
-                padfZ = (double*)CPLRealloc(padfZ, (nPoints + 1) * sizeof(double));
+                poPoints = static_cast<OGRRawPoint *>(
+                    CPLRealloc(poPoints, (nPoints + 1) * sizeof(OGRRawPoint)));
+                padfZ = static_cast<double *>(
+                    CPLRealloc(padfZ, (nPoints + 1) * sizeof(double)));
                 poPoints[nPoints].x = poRing->getX(2);
                 poPoints[nPoints].y = poRing->getY(2);
                 padfZ[nPoints] = poRing->getZ(2);
-                nPoints ++;
+                nPoints++;
             }
             else
             {
-                if( nParts == 0 || panPartType[nParts-1] != SHPP_TRIANGLES )
+                if( nParts == 0 ||
+                    panPartType[nParts-1] != SHPP_TRIANGLES ||
+                    !bAllowSHPTTriangle )
                 {
                     nBeginLastPart = nPoints;
 
-                    panPartStart = (int*)CPLRealloc(panPartStart, (nParts + 1) * sizeof(int));
-                    panPartType = (int*)CPLRealloc(panPartType, (nParts + 1) * sizeof(int));
+                    panPartStart = static_cast<int *>(
+                        CPLRealloc(panPartStart, (nParts + 1) * sizeof(int)));
+                    panPartType = static_cast<int *>(
+                        CPLRealloc(panPartType, (nParts + 1) * sizeof(int)));
                     panPartStart[nParts] = nPoints;
-                    panPartType[nParts] = SHPP_TRIANGLES;
-                    nParts ++;
+                    panPartType[nParts] = bAllowSHPTTriangle ? SHPP_TRIANGLES :
+                                                               SHPP_OUTERRING;
+                    nParts++;
                 }
 
-                poPoints = (OGRRawPoint*)CPLRealloc(poPoints,
-                                        (nPoints + 3) * sizeof(OGRRawPoint));
-                padfZ = (double*)CPLRealloc(padfZ, (nPoints + 3) * sizeof(double));
-                for(int i=0;i<3;i++)
+                poPoints = static_cast<OGRRawPoint *>(
+                    CPLRealloc(poPoints, (nPoints + 4) * sizeof(OGRRawPoint)));
+                padfZ = static_cast<double *>(
+                    CPLRealloc(padfZ, (nPoints + 4) * sizeof(double)));
+                for( int i = 0; i < 4; i++ )
                 {
                     poPoints[nPoints+i].x = poRing->getX(i);
                     poPoints[nPoints+i].y = poRing->getY(i);
                     padfZ[nPoints+i] = poRing->getZ(i);
                 }
-                nPoints += 3;
+                nPoints += bAllowSHPTTriangle ? 3 : 4;
             }
         }
         else
         {
-            panPartStart = (int*)CPLRealloc(panPartStart, (nParts + nRings) * sizeof(int));
-            panPartType = (int*)CPLRealloc(panPartType, (nParts + nRings) * sizeof(int));
+            panPartStart = static_cast<int *>(
+                CPLRealloc(panPartStart, (nParts + nRings) * sizeof(int)));
+            panPartType = static_cast<int *>(
+                CPLRealloc(panPartType, (nParts + nRings) * sizeof(int)));
 
-            for ( int i = 0; i < nRings; i++ )
+            for( int i = 0; i < nRings; i++ )
             {
                 panPartStart[nParts + i] = nPoints;
-                if ( i == 0 )
+                if( i == 0 )
                 {
                     poRing = poPoly->getExteriorRing();
                     panPartType[nParts + i] = SHPP_OUTERRING;
@@ -1091,10 +1553,14 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
                     poRing = poPoly->getInteriorRing(i-1);
                     panPartType[nParts + i] = SHPP_INNERRING;
                 }
-                poPoints = (OGRRawPoint*)CPLRealloc(poPoints,
-                        (nPoints + poRing->getNumPoints()) * sizeof(OGRRawPoint));
-                padfZ = (double*)CPLRealloc(padfZ,
-                        (nPoints + poRing->getNumPoints()) * sizeof(double));
+                poPoints = static_cast<OGRRawPoint *>(
+                    CPLRealloc(poPoints,
+                               (nPoints +
+                                poRing->getNumPoints()) * sizeof(OGRRawPoint)));
+                padfZ = static_cast<double *>(
+                    CPLRealloc(padfZ,
+                               (nPoints +
+                                poRing->getNumPoints()) * sizeof(double)));
                 for( int k = 0; k < poRing->getNumPoints(); k++ )
                 {
                     poPoints[nPoints+k].x = poRing->getX(k);
@@ -1108,22 +1574,59 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
         }
     }
 
-    int nShpSize = 4; /* All types start with integer type number */
-    nShpSize += 16 * 2; /* xy bbox */
-    nShpSize += 4; /* nparts */
-    nShpSize += 4; /* npoints */
-    nShpSize += 4 * nParts; /* panPartStart[nparts] */
-    nShpSize += 4 * nParts; /* panPartType[nparts] */
-    nShpSize += 8 * 2 * nPoints; /* xy points */
-    nShpSize += 16; /* z bbox */
-    nShpSize += 8 * nPoints; /* z points */
+    if( nParts == 1 && panPartType[0] == SHPP_OUTERRING &&
+        nPoints == 4 )
+    {
+        panPartType[0] = SHPP_TRIFAN;
+        nPoints = 3;
+    }
+
+    delete poGeomToDelete;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                   OGRWriteMultiPatchToShapeBin()                     */
+/************************************************************************/
+
+OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
+                                     GByte **ppabyShape,
+                                     int *pnBytes )
+{
+    int nParts = 0;
+    int* panPartStart = NULL;
+    int* panPartType = NULL;
+    int nPoints = 0;
+    OGRRawPoint* poPoints = NULL;
+    double* padfZ = NULL;
+    OGRErr eErr = OGRCreateMultiPatch( poGeom,
+                                       TRUE,
+                                       nParts,
+                                       panPartStart,
+                                       panPartType,
+                                       nPoints,
+                                       poPoints,
+                                       padfZ );
+    if( eErr != OGRERR_NONE )
+        return eErr;
+
+    int nShpSize = 4;  // All types start with integer type number.
+    nShpSize += 16 * 2;  // xy bbox.
+    nShpSize += 4;  // nparts.
+    nShpSize += 4;  // npoints.
+    nShpSize += 4 * nParts;  // panPartStart[nparts].
+    nShpSize += 4 * nParts;  // panPartType[nparts].
+    nShpSize += 8 * 2 * nPoints;  // xy points.
+    nShpSize += 16;  // z bbox.
+    nShpSize += 8 * nPoints;  // z points.
 
     *pnBytes = nShpSize;
-    *ppabyShape = (GByte*) CPLMalloc(nShpSize);
+    *ppabyShape = static_cast<GByte *>(CPLMalloc(nShpSize));
 
     GByte* pabyPtr = *ppabyShape;
 
-    /* Write in the type number and advance the pointer */
+    // Write in the type number and advance the pointer.
     GUInt32 nGType = CPL_LSBWORD32( SHPT_MULTIPATCH );
     memcpy( pabyPtr, &nGType, 4 );
     pabyPtr += 4;
@@ -1135,32 +1638,31 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
     memcpy( pabyPtr+8+8, &(envelope.MaxX), 8 );
     memcpy( pabyPtr+8+8+8, &(envelope.MaxY), 8 );
 
-    int i;
-    /* Swap box if needed. Shape doubles are always LSB */
+    // Swap box if needed. Shape doubles are always LSB.
     if( OGR_SWAP( wkbNDR ) )
     {
-        for ( i = 0; i < 4; i++ )
+        for( int i = 0; i < 4; i++ )
             CPL_SWAPDOUBLE( pabyPtr + 8*i );
     }
     pabyPtr += 32;
 
-    /* Write in the part count */
+    // Write in the part count.
     GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
     memcpy( pabyPtr, &nPartsLsb, 4 );
     pabyPtr += 4;
 
-    /* Write in the total point count */
+    // Write in the total point count.
     GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
     memcpy( pabyPtr, &nPointsLsb, 4 );
     pabyPtr += 4;
 
-    for( i = 0; i < nParts; i ++ )
+    for( int i = 0; i < nParts; i ++ )
     {
         int nPartStart = CPL_LSBWORD32(panPartStart[i]);
         memcpy( pabyPtr, &nPartStart, 4 );
         pabyPtr += 4;
     }
-    for( i = 0; i < nParts; i ++ )
+    for( int i = 0; i < nParts; i ++ )
     {
         int nPartType = CPL_LSBWORD32(panPartType[i]);
         memcpy( pabyPtr, &nPartType, 4 );
@@ -1170,10 +1672,10 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
     if( poPoints != NULL )
         memcpy(pabyPtr, poPoints, 2 * 8 * nPoints);
 
-    /* Swap box if needed. Shape doubles are always LSB */
+    // Swap box if needed. Shape doubles are always LSB.
     if( OGR_SWAP( wkbNDR ) )
     {
-        for ( i = 0; i < 2 * nPoints; i++ )
+        for( int i = 0; i < 2 * nPoints; i++ )
             CPL_SWAPDOUBLE( pabyPtr + 8*i );
     }
     pabyPtr += 2 * 8 * nPoints;
@@ -1182,20 +1684,20 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
     memcpy( pabyPtr+8, &(envelope.MaxZ), 8 );
     if( OGR_SWAP( wkbNDR ) )
     {
-        for ( i = 0; i < 2; i++ )
+        for( int i = 0; i < 2; i++ )
             CPL_SWAPDOUBLE( pabyPtr + 8*i );
     }
     pabyPtr += 16;
 
     if( padfZ != NULL )
         memcpy(pabyPtr, padfZ, 8 * nPoints);
-    /* Swap box if needed. Shape doubles are always LSB */
+    // Swap box if needed. Shape doubles are always LSB.
     if( OGR_SWAP( wkbNDR ) )
     {
-        for ( i = 0; i < nPoints; i++ )
+        for( int i = 0; i < nPoints; i++ )
             CPL_SWAPDOUBLE( pabyPtr + 8*i );
     }
-    //pabyPtr +=  8 * nPoints;
+    // pabyPtr += 8 * nPoints;
 
     CPLFree(panPartStart);
     CPLFree(panPartType);
@@ -1206,6 +1708,351 @@ OGRErr OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
 }
 
 /************************************************************************/
+/*                           GetAngleOnEllipse()                        */
+/************************************************************************/
+
+// Return the angle in deg [0, 360] of dfArcX,dfArcY regarding the
+// ellipse semi-major axis.
+static double GetAngleOnEllipse( double dfPointOnArcX,
+                                 double dfPointOnArcY,
+                                 double dfCenterX,
+                                 double dfCenterY,
+                                 double dfRotationDeg,  // Ellipse rotation.
+                                 double dfSemiMajor,
+                                 double dfSemiMinor )
+{
+    // Invert the following equation where cosA, sinA are unknown:
+    //   dfPointOnArcX-dfCenterX = cosA*M*cosRot + sinA*m*sinRot
+    //   dfPointOnArcY-dfCenterY = -cosA*M*sinRot + sinA*m*cosRot
+
+    const double dfRotationRadians = dfRotationDeg * M_PI / 180.0;
+    const double dfCosRot = cos(dfRotationRadians);
+    const double dfSinRot = sin(dfRotationRadians);
+    const double dfDeltaX = dfPointOnArcX - dfCenterX;
+    const double dfDeltaY = dfPointOnArcY - dfCenterY;
+    const double dfCosA =
+        (dfCosRot * dfDeltaX - dfSinRot * dfDeltaY) / dfSemiMajor;
+    const double dfSinA =
+        (dfSinRot * dfDeltaX + dfCosRot * dfDeltaY) / dfSemiMinor;
+    // We could check that dfCosA^2 + dfSinA^2 ~= 1 to verify that the point
+    // is on the ellipse.
+    const double dfAngle = atan2( dfSinA, dfCosA ) / M_PI * 180;
+    if( dfAngle < -180 )
+        return dfAngle + 360;
+    return dfAngle;
+}
+
+/************************************************************************/
+/*                    OGRShapeCreateCompoundCurve()                     */
+/************************************************************************/
+
+static OGRCurve* OGRShapeCreateCompoundCurve( int nPartStartIdx,
+                                              int nPartPoints,
+                                              const CurveSegment* pasCurves,
+                                              int nCurves,
+                                              int nFirstCurveIdx,
+                                              /* const */ double* padfX,
+                                              /* const */ double* padfY,
+                                              /* const */ double* padfZ,
+                                              /* const */ double* padfM,
+                                              int* pnLastCurveIdx )
+{
+    OGRCompoundCurve* poCC = new OGRCompoundCurve();
+    int nLastPointIdx = nPartStartIdx;
+    bool bHasCircularArcs = false;
+    int i = nFirstCurveIdx;  // Used after for.
+    for( ; i < nCurves; i ++ )
+    {
+        const int nStartPointIdx = pasCurves[i].nStartPointIdx;
+
+        if( nStartPointIdx < nPartStartIdx )
+        {
+            // Shouldn't happen normally, but who knows.
+            continue;
+        }
+
+        // For a multi-part geometry, stop when the start index of the curve
+        // exceeds the last point index of the part
+        if( nStartPointIdx >= nPartStartIdx + nPartPoints )
+        {
+            if( pnLastCurveIdx )
+                *pnLastCurveIdx = i;
+            break;
+        }
+
+        // Add linear segments between end of last curve portion (or beginning
+        // of the part) and start of current curve.
+        if( nStartPointIdx > nLastPointIdx )
+        {
+            OGRLineString *poLine = new OGRLineString();
+            poLine->setPoints( nStartPointIdx - nLastPointIdx + 1,
+                               padfX + nLastPointIdx,
+                               padfY + nLastPointIdx,
+                               padfZ != NULL ? padfZ + nLastPointIdx : NULL,
+                               padfM != NULL ? padfM + nLastPointIdx : NULL );
+            poCC->addCurveDirectly(poLine);
+        }
+
+        if( pasCurves[i].eType == CURVE_ARC_INTERIOR_POINT &&
+            nStartPointIdx+1 < nPartStartIdx + nPartPoints )
+        {
+            OGRPoint p1( padfX[nStartPointIdx], padfY[nStartPointIdx],
+                         padfZ != NULL ? padfZ[nStartPointIdx] : 0.0,
+                         padfM != NULL ? padfM[nStartPointIdx] : 0.0 );
+            OGRPoint p2( pasCurves[i].u.ArcByIntermediatePoint.dfX,
+                         pasCurves[i].u.ArcByIntermediatePoint.dfY,
+                         padfZ != NULL ?  padfZ[nStartPointIdx] : 0.0 );
+            OGRPoint p3( padfX[nStartPointIdx+1], padfY[nStartPointIdx+1],
+                         padfZ != NULL ? padfZ[nStartPointIdx+1] : 0.0,
+                         padfM != NULL ? padfM[nStartPointIdx+1] : 0.0 );
+
+            // Some software (like QGIS, see https://hub.qgis.org/issues/15116)
+            // do not like 3-point circles, so use a 5 point variant.
+            if( p1.getX() == p3.getX() && p1.getY() == p3.getY() )
+            {
+                if( p1.getX() != p2.getX() || p1.getY() != p2.getY() )
+                {
+                    bHasCircularArcs = true;
+                    OGRCircularString* poCS = new OGRCircularString();
+                    const double dfCenterX = (p1.getX() + p2.getX()) / 2;
+                    const double dfCenterY = (p1.getY() + p2.getY()) / 2;
+                    poCS->addPoint( &p1 );
+                    OGRPoint pInterm1(
+                        dfCenterX - ( p2.getY() - dfCenterY ),
+                        dfCenterY + ( p1.getX() - dfCenterX ),
+                        padfZ != NULL ? padfZ[nStartPointIdx] : 0.0 );
+                    poCS->addPoint( &pInterm1 );
+                    poCS->addPoint( &p2 );
+                    OGRPoint pInterm2(
+                        dfCenterX + ( p2.getY() - dfCenterY ),
+                        dfCenterY - ( p1.getX() - dfCenterX ),
+                        padfZ != NULL ? padfZ[nStartPointIdx] : 0.0 );
+                    poCS->addPoint( &pInterm2 );
+                    poCS->addPoint( &p3 );
+                    poCS->set3D( padfZ != NULL );
+                    poCS->setMeasured( padfM != NULL );
+                    poCC->addCurveDirectly(poCS);
+                }
+            }
+            else
+            {
+                bHasCircularArcs = true;
+                OGRCircularString* poCS = new OGRCircularString();
+                poCS->addPoint( &p1 );
+                poCS->addPoint( &p2 );
+                poCS->addPoint( &p3 );
+                poCS->set3D( padfZ != NULL );
+                poCS->setMeasured( padfM != NULL );
+                poCC->addCurveDirectly(poCS);
+            }
+        }
+
+        else if( pasCurves[i].eType == CURVE_ARC_CENTER_POINT &&
+            nStartPointIdx+1 < nPartStartIdx + nPartPoints )
+        {
+            const double dfCenterX = pasCurves[i].u.ArcByCenterPoint.dfX;
+            const double dfCenterY = pasCurves[i].u.ArcByCenterPoint.dfY;
+            double dfDeltaY = padfY[nStartPointIdx] - dfCenterY;
+            double dfDeltaX = padfX[nStartPointIdx] - dfCenterX;
+            double dfAngleStart = atan2(dfDeltaY, dfDeltaX);
+            dfDeltaY = padfY[nStartPointIdx+1] - dfCenterY;
+            dfDeltaX = padfX[nStartPointIdx+1] - dfCenterX;
+            double dfAngleEnd = atan2(dfDeltaY, dfDeltaX);
+            // Note: This definition from center and 2 points may be
+            // not a circle.
+            double dfRadius = sqrt( dfDeltaX * dfDeltaX + dfDeltaY * dfDeltaY );
+            if( pasCurves[i].u.ArcByCenterPoint.bIsCCW )
+            {
+                if( dfAngleStart >= dfAngleEnd )
+                    dfAngleEnd += 2 * M_PI;
+            }
+            else
+            {
+                if( dfAngleStart <= dfAngleEnd )
+                    dfAngleEnd -= 2 * M_PI;
+            }
+            const double dfMidAngle = (dfAngleStart + dfAngleEnd) / 2;
+            OGRPoint p1( padfX[nStartPointIdx], padfY[nStartPointIdx],
+                         padfZ != NULL ? padfZ[nStartPointIdx] : 0.0,
+                         padfM != NULL ? padfM[nStartPointIdx] : 0.0 );
+            OGRPoint p2( dfCenterX + dfRadius * cos(dfMidAngle),
+                         dfCenterY + dfRadius * sin(dfMidAngle),
+                         padfZ != NULL ?  padfZ[nStartPointIdx] : 0.0 );
+            OGRPoint p3( padfX[nStartPointIdx+1], padfY[nStartPointIdx+1],
+                         padfZ != NULL ? padfZ[nStartPointIdx+1] : 0.0,
+                         padfM != NULL ? padfM[nStartPointIdx+1] : 0.0 );
+
+            bHasCircularArcs = true;
+            OGRCircularString* poCS = new OGRCircularString();
+            poCS->addPoint( &p1 );
+            poCS->addPoint( &p2 );
+            poCS->addPoint( &p3 );
+            poCS->set3D( padfZ != NULL );
+            poCS->setMeasured( padfM != NULL );
+            poCC->addCurveDirectly(poCS);
+        }
+
+        else if( pasCurves[i].eType == CURVE_BEZIER &&
+                  nStartPointIdx+1 < nPartStartIdx + nPartPoints )
+        {
+            const int nSteps = 100;
+            OGRLineString *poLine = new OGRLineString();
+            poLine->setNumPoints(nSteps + 1);
+            const double dfX0 = padfX[nStartPointIdx];
+            const double dfY0 = padfY[nStartPointIdx];
+            const double dfX1 = pasCurves[i].u.Bezier.dfX1;
+            const double dfY1 = pasCurves[i].u.Bezier.dfY1;
+            const double dfX2 = pasCurves[i].u.Bezier.dfX2;
+            const double dfY2 = pasCurves[i].u.Bezier.dfY2;
+            const double dfX3 = padfX[nStartPointIdx+1];
+            const double dfY3 = padfY[nStartPointIdx+1];
+            poLine->setPoint(0, dfX0, dfY0,
+                             padfZ != NULL ? padfZ[nStartPointIdx] : 0.0,
+                             padfM != NULL ? padfM[nStartPointIdx] : 0.0);
+            for( int j = 1; j < nSteps; j++ )
+            {
+                const double t = static_cast<double>(j) / nSteps;
+                // Third-order Bezier interpolation.
+                poLine->setPoint(j,
+                                 (1-t)*(1-t)*(1-t)*dfX0 + 3*(1-t)*(1-t)*t*dfX1 +
+                                 3*(1-t)*t*t*dfX2 + t*t*t*dfX3,
+                                 (1-t)*(1-t)*(1-t)*dfY0 + 3*(1-t)*(1-t)*t*dfY1 +
+                                 3*(1-t)*t*t*dfY2 + t*t*t*dfY3);
+            }
+            poLine->setPoint(nSteps, dfX3, dfY3,
+                             padfZ != NULL ? padfZ[nStartPointIdx+1] : 0.0,
+                             padfM != NULL ? padfM[nStartPointIdx+1] : 0.0);
+            poLine->set3D( padfZ != NULL );
+            poLine->setMeasured( padfM != NULL );
+            poCC->addCurveDirectly(poLine);
+        }
+
+        else if( pasCurves[i].eType == CURVE_ELLIPSE_BY_CENTER &&
+                 nStartPointIdx+1 < nPartStartIdx + nPartPoints )
+        {
+            const double dfSemiMinor =
+              pasCurves[i].u.EllipseByCenter.dfSemiMajor *
+              pasCurves[i].u.EllipseByCenter.dfRatioSemiMinor;
+            // Different sign conventions between ext shape
+            // (trigonometric, CCW) and approximateArcAngles (CW).
+            const double dfRotationDeg =
+                -pasCurves[i].u.EllipseByCenter.dfRotationDeg;
+            const double dfAngleStart = GetAngleOnEllipse(
+                    padfX[nStartPointIdx],
+                    padfY[nStartPointIdx],
+                    pasCurves[i].u.EllipseByCenter.dfX,
+                    pasCurves[i].u.EllipseByCenter.dfY,
+                    dfRotationDeg,
+                    pasCurves[i].u.EllipseByCenter.dfSemiMajor,
+                    dfSemiMinor);
+            const double dfAngleEnd = GetAngleOnEllipse(
+                    padfX[nStartPointIdx+1],
+                    padfY[nStartPointIdx+1],
+                    pasCurves[i].u.EllipseByCenter.dfX,
+                    pasCurves[i].u.EllipseByCenter.dfY,
+                    dfRotationDeg,
+                    pasCurves[i].u.EllipseByCenter.dfSemiMajor,
+                    dfSemiMinor);
+            // CPLDebug("OGR", "Start angle=%f, End angle=%f",
+            //          dfAngleStart, dfAngleEnd);
+            // Approximatearcangles() use CW.
+            double dfAngleStartForApprox = -dfAngleStart;
+            double dfAngleEndForApprox = -dfAngleEnd;
+            if( pasCurves[i].u.EllipseByCenter.bIsComplete )
+            {
+                dfAngleEndForApprox = dfAngleStartForApprox + 360;
+            }
+            else if( pasCurves[i].u.EllipseByCenter.bIsMinor )
+            {
+                if( dfAngleEndForApprox > dfAngleStartForApprox + 180 )
+                {
+                    dfAngleEndForApprox -= 360;
+                }
+                else if( dfAngleEndForApprox < dfAngleStartForApprox - 180 )
+                {
+                    dfAngleEndForApprox += 360;
+                }
+            }
+            else
+            {
+                if( dfAngleEndForApprox > dfAngleStartForApprox &&
+                    dfAngleEndForApprox < dfAngleStartForApprox + 180 )
+                {
+                    dfAngleEndForApprox -= 360;
+                }
+                else if( dfAngleEndForApprox < dfAngleStartForApprox &&
+                         dfAngleEndForApprox > dfAngleStartForApprox - 180 )
+                {
+                    dfAngleEndForApprox += 360;
+                }
+            }
+            OGRLineString* poLine = reinterpret_cast<OGRLineString*>(
+              OGRGeometryFactory::approximateArcAngles(
+                  pasCurves[i].u.EllipseByCenter.dfX,
+                  pasCurves[i].u.EllipseByCenter.dfY,
+                  padfZ != NULL ? padfZ[nStartPointIdx] : 0.0,
+                  pasCurves[i].u.EllipseByCenter.dfSemiMajor,
+                  dfSemiMinor,
+                  dfRotationDeg,
+                  dfAngleStartForApprox,
+                  dfAngleEndForApprox, 0 ) );
+             if( poLine->getNumPoints() >= 2 )
+             {
+                poLine->setPoint(0,
+                                 padfX[nStartPointIdx],
+                                 padfY[nStartPointIdx],
+                                 padfZ != NULL ? padfZ[nStartPointIdx] : 0.0,
+                                 padfM != NULL ? padfM[nStartPointIdx] : 0.0);
+                poLine->setPoint(poLine->getNumPoints()-1,
+                                 padfX[nStartPointIdx+1],
+                                 padfY[nStartPointIdx+1],
+                                 padfZ != NULL ? padfZ[nStartPointIdx+1] : 0.0,
+                                 padfM != NULL ? padfM[nStartPointIdx+1] : 0.0);
+             }
+             poLine->set3D( padfZ != NULL );
+             poLine->setMeasured( padfM != NULL );
+             poCC->addCurveDirectly(poLine);
+        }
+
+        // Should not happen normally.
+        else if( nStartPointIdx+1 < nPartStartIdx + nPartPoints )
+        {
+            OGRLineString *poLine = new OGRLineString();
+            poLine->setPoints( 2,
+                                padfX + nStartPointIdx,
+                                padfY + nStartPointIdx,
+                                padfZ != NULL ? padfZ + nStartPointIdx : NULL,
+                                padfM != NULL ? padfM + nStartPointIdx : NULL );
+            poCC->addCurveDirectly(poLine);
+        }
+        nLastPointIdx = nStartPointIdx + 1;
+    }
+    if( i == nCurves )
+    {
+        if( pnLastCurveIdx )
+            *pnLastCurveIdx = i;
+    }
+
+    // Add terminating linear segments
+    if( nLastPointIdx < nPartStartIdx+nPartPoints-1 )
+    {
+        OGRLineString *poLine = new OGRLineString();
+        poLine->setPoints( nPartStartIdx+nPartPoints-1 - nLastPointIdx + 1,
+                            padfX + nLastPointIdx,
+                            padfY + nLastPointIdx,
+                            padfZ != NULL ? padfZ + nLastPointIdx : NULL,
+                            padfM != NULL ? padfM + nLastPointIdx : NULL );
+        poCC->addCurveDirectly(poLine);
+    }
+
+    if( !bHasCircularArcs )
+        return reinterpret_cast<OGRCurve*>(OGR_G_ForceTo(
+            reinterpret_cast<OGRGeometryH>(poCC), wkbLineString, NULL));
+    else
+        return poCC;
+}
+
+/************************************************************************/
 /*                      OGRCreateFromShapeBin()                         */
 /*                                                                      */
 /*      Translate shapefile binary representation to an OGR             */
@@ -1230,21 +2077,23 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /* -------------------------------------------------------------------- */
 /*  Detect zlib compressed shapes and uncompress buffer if necessary    */
 /*  NOTE: this seems to be an undocumented feature, even in the         */
-/*  extended_shapefile_format.pdf found in the FileGDB API documentation*/
+/*  extended_shapefile_format.pdf found in the FileGDB API              */
+/*  documentation.                                                      */
 /* -------------------------------------------------------------------- */
     if( nBytes >= 14 &&
-        pabyShape[12] == 0x78 && pabyShape[13] == 0xDA /* zlib marker */)
+        pabyShape[12] == 0x78 && pabyShape[13] == 0xDA /* zlib marker */ )
     {
-        GInt32 nUncompressedSize, nCompressedSize;
+        GInt32 nUncompressedSize = 0;
+        GInt32 nCompressedSize = 0;
         memcpy( &nUncompressedSize, pabyShape + 4, 4 );
         memcpy( &nCompressedSize, pabyShape + 8, 4 );
         CPL_LSBPTR32( &nUncompressedSize );
         CPL_LSBPTR32( &nCompressedSize );
-        if (nCompressedSize + 12 == nBytes &&
-            nUncompressedSize > 0)
+        if( nCompressedSize + 12 == nBytes && nUncompressedSize > 0 )
         {
-            GByte* pabyUncompressedBuffer = (GByte*)VSI_MALLOC_VERBOSE(nUncompressedSize);
-            if (pabyUncompressedBuffer == NULL)
+            GByte* pabyUncompressedBuffer =
+                static_cast<GByte *>(VSI_MALLOC_VERBOSE(nUncompressedSize));
+            if( pabyUncompressedBuffer == NULL )
             {
                 return OGRERR_FAILURE;
             }
@@ -1260,9 +2109,10 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
                 return OGRERR_FAILURE;
             }
 
-            OGRErr eErr = OGRCreateFromShapeBin(pabyUncompressedBuffer,
-                                                ppoGeom,
-                                                static_cast<int>(nRealUncompressedSize));
+            const OGRErr eErr =
+                OGRCreateFromShapeBin(pabyUncompressedBuffer,
+                                      ppoGeom,
+                                      static_cast<int>(nRealUncompressedSize));
 
             VSIFree(pabyUncompressedBuffer);
 
@@ -1277,17 +2127,20 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /*      Watch out, null return does not mean "bad data" it means        */
 /*      "no geometry here". Watch the OGRErr for the error status       */
 /* -------------------------------------------------------------------- */
-    if ( nSHPType == SHPT_NULL )
+    if( nSHPType == SHPT_NULL )
     {
-      *ppoGeom = NULL;
-      return OGRERR_NONE;
+        *ppoGeom = NULL;
+        return OGRERR_NONE;
     }
 
-//    CPLDebug( "PGeo",
-//              "Shape type read from PGeo data is nSHPType = %d",
-//              nSHPType );
+#if DEBUG_VERBOSE
+    CPLDebug("PGeo",
+             "Shape type read from PGeo data is nSHPType = %d",
+             nSHPType);
+#endif
 
-    const bool bIsExtended = ( nSHPType >= SHPT_GENERALPOLYLINE && nSHPType <= SHPT_GENERALMULTIPATCH );
+    const bool bIsExtended =
+        nSHPType >= SHPT_GENERALPOLYLINE && nSHPType <= SHPT_GENERALMULTIPATCH;
 
     const bool bHasZ = (
                    nSHPType == SHPT_POINTZ
@@ -1314,12 +2167,8 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
                 || nSHPType == SHPT_MULTIPATCHM
                 || (bIsExtended && (pabyShape[3] & 0x40) != 0 ) );
 
-/* -------------------------------------------------------------------- */
-/*      TODO: These types include additional attributes including       */
-/*      non-linear segments and such. They should be handled.           */
-/*      This is documented in the extended_shapefile_format.pdf         */
-/*      from the FileGDB API                                            */
-/* -------------------------------------------------------------------- */
+    const bool bHasCurves = (bIsExtended && (pabyShape[3] & 0x20) != 0 );
+
     switch( nSHPType )
     {
       case SHPT_GENERALPOLYLINE:
@@ -1339,7 +2188,7 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
     }
 
 /* ==================================================================== */
-/*  Extract vertices for a Polygon or Arc.              */
+/*     Extract vertices for a Polygon or Arc.                           */
 /* ==================================================================== */
     if(    nSHPType == SHPT_ARC
         || nSHPType == SHPT_ARCZ
@@ -1352,15 +2201,11 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
         || nSHPType == SHPT_MULTIPATCH
         || nSHPType == SHPT_MULTIPATCHM)
     {
-        GInt32         nPoints, nParts;
-        int            i, nOffset;
-        GInt32         *panPartStart;
-        GInt32         *panPartType = NULL;
-
-        if (nBytes < 44)
+        if( nBytes < 44 )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
+                     "Corrupted Shape : nBytes=%d, nSHPType=%d",
+                     nBytes, nSHPType);
             return OGRERR_FAILURE;
         }
 
@@ -1368,31 +2213,35 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /*      Extract part/point count, and build vertex and part arrays      */
 /*      to proper size.                                                 */
 /* -------------------------------------------------------------------- */
+        GInt32 nPoints = 0;
         memcpy( &nPoints, pabyShape + 40, 4 );
+        GInt32 nParts = 0;
         memcpy( &nParts, pabyShape + 36, 4 );
 
         CPL_LSBPTR32( &nPoints );
         CPL_LSBPTR32( &nParts );
 
-        if (nPoints < 0 || nParts < 0 ||
-            nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
+        if( nPoints < 0 || nParts < 0 ||
+            nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000 )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d, nParts=%d.",
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Corrupted Shape : nPoints=%d, nParts=%d.",
                      nPoints, nParts);
             return OGRERR_FAILURE;
         }
 
-        int bIsMultiPatch = ( nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM );
+        const bool bIsMultiPatch =
+            nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM;
 
-        /* With the previous checks on nPoints and nParts, */
-        /* we should not overflow here and after */
-        /* since 50 M * (16 + 8 + 8) = 1 600 MB */
+        // With the previous checks on nPoints and nParts,
+        // we should not overflow here and after
+        // since 50 M * (16 + 8 + 8) = 1 600 MB.
         int nRequiredSize = 44 + 4 * nParts + 16 * nPoints;
-        if ( bHasZ )
+        if( bHasZ )
         {
             nRequiredSize += 16 + 8 * nPoints;
         }
-        if ( bHasM )
+        if( bHasM )
         {
             nRequiredSize += 16 + 8 * nPoints;
         }
@@ -1400,16 +2249,18 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
         {
             nRequiredSize += 4 * nParts;
         }
-        if (nRequiredSize > nBytes)
+        if( nRequiredSize > nBytes )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, nSHPType=%d, nRequiredSize=%d",
+                     "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, "
+                     "nSHPType=%d, nRequiredSize=%d",
                      nPoints, nParts, nBytes, nSHPType, nRequiredSize);
             return OGRERR_FAILURE;
         }
 
-        panPartStart = (GInt32 *) VSI_CALLOC_VERBOSE(nParts,sizeof(GInt32));
-        if (panPartStart == NULL)
+        GInt32 *panPartStart =
+            static_cast<GInt32 *>(VSI_MALLOC2_VERBOSE(nParts, sizeof(GInt32)));
+        if( nParts != 0 && panPartStart == NULL )
         {
             return OGRERR_FAILURE;
         }
@@ -1418,46 +2269,51 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /*      Copy out the part array from the record.                        */
 /* -------------------------------------------------------------------- */
         memcpy( panPartStart, pabyShape + 44, 4 * nParts );
-        for( i = 0; i < nParts; i++ )
+        for( int i = 0; i < nParts; i++ )
         {
             CPL_LSBPTR32( panPartStart + i );
 
-            /* We check that the offset is inside the vertex array */
-            if (panPartStart[i] < 0 ||
-                panPartStart[i] >= nPoints)
+            // Check that the offset is inside the vertex array.
+            if( panPartStart[i] < 0 ||
+                panPartStart[i] >= nPoints )
             {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Corrupted Shape : panPartStart[%d] = %d, nPoints = %d",
-                        i, panPartStart[i], nPoints);
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Corrupted Shape : panPartStart[%d] = %d, nPoints = %d",
+                    i, panPartStart[i], nPoints);
                 CPLFree(panPartStart);
                 return OGRERR_FAILURE;
             }
-            if (i > 0 && panPartStart[i] <= panPartStart[i-1])
+            if( i > 0 && panPartStart[i] <= panPartStart[i-1] )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
-                        "Corrupted Shape : panPartStart[%d] = %d, panPartStart[%d] = %d",
-                        i, panPartStart[i], i - 1, panPartStart[i - 1]);
+                         "Corrupted Shape : panPartStart[%d] = %d, "
+                         "panPartStart[%d] = %d",
+                         i, panPartStart[i], i - 1, panPartStart[i - 1]);
                 CPLFree(panPartStart);
                 return OGRERR_FAILURE;
             }
         }
 
-        nOffset = 44 + 4*nParts;
+        int nOffset = 44 + 4 * nParts;
 
 /* -------------------------------------------------------------------- */
 /*      If this is a multipatch, we will also have parts types.         */
 /* -------------------------------------------------------------------- */
+        GInt32 *panPartType = NULL;
+
         if( bIsMultiPatch )
         {
-            panPartType = (GInt32 *) VSI_CALLOC_VERBOSE(nParts,sizeof(GInt32));
-            if (panPartType == NULL)
+            panPartType = static_cast<GInt32 *>(
+                VSI_MALLOC2_VERBOSE(nParts, sizeof(GInt32)));
+            if( panPartType == NULL )
             {
                 CPLFree(panPartStart);
                 return OGRERR_FAILURE;
             }
 
             memcpy( panPartType, pabyShape + nOffset, 4*nParts );
-            for( i = 0; i < nParts; i++ )
+            for( int i = 0; i < nParts; i++ )
             {
                 CPL_LSBPTR32( panPartType + i );
             }
@@ -1467,11 +2323,17 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /* -------------------------------------------------------------------- */
 /*      Copy out the vertices from the record.                          */
 /* -------------------------------------------------------------------- */
-        double *padfX = (double *) VSI_MALLOC_VERBOSE(sizeof(double)*nPoints);
-        double *padfY = (double *) VSI_MALLOC_VERBOSE(sizeof(double)*nPoints);
-        double *padfZ = (double *) VSI_CALLOC_VERBOSE(sizeof(double),nPoints);
-        double *padfM = (double *) (bHasM ? VSI_CALLOC_VERBOSE(sizeof(double),nPoints) : NULL);
-        if (padfX == NULL || padfY == NULL || padfZ == NULL || (bHasM && padfM == NULL))
+        double *padfX =
+            static_cast<double *>(VSI_MALLOC_VERBOSE(sizeof(double) * nPoints));
+        double *padfY =
+            static_cast<double *>(VSI_MALLOC_VERBOSE(sizeof(double) * nPoints));
+        double *padfZ =
+            static_cast<double *>(VSI_CALLOC_VERBOSE(sizeof(double), nPoints));
+        double *padfM = static_cast<double *>(
+            bHasM ? VSI_CALLOC_VERBOSE(sizeof(double), nPoints) : NULL);
+
+        if( nPoints != 0 && (padfX == NULL || padfY == NULL || padfZ == NULL ||
+                             (bHasM && padfM == NULL)) )
         {
             CPLFree( panPartStart );
             CPLFree( panPartType );
@@ -1482,7 +2344,7 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
             return OGRERR_FAILURE;
         }
 
-        for( i = 0; i < nPoints; i++ )
+        for( int i = 0; i < nPoints; i++ )
         {
             memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 );
             memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 );
@@ -1497,7 +2359,7 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /* -------------------------------------------------------------------- */
         if( bHasZ )
         {
-            for( i = 0; i < nPoints; i++ )
+            for( int i = 0; i < nPoints; i++ )
             {
                 memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 );
                 CPL_LSBPTR64( padfZ + i );
@@ -1511,14 +2373,251 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /* -------------------------------------------------------------------- */
         if( bHasM )
         {
-            for( i = 0; i < nPoints; i++ )
+            for( int i = 0; i < nPoints; i++ )
             {
                 memcpy( padfM + i, pabyShape + nOffset + 16 + i*8, 8 );
                 CPL_LSBPTR64( padfM + i );
             }
 
-            //nOffset += 16 + 8*nPoints;
+            nOffset += 16 + 8*nPoints;
         }
+
+/* -------------------------------------------------------------------- */
+/*      If we have curves, collect them now.                            */
+/* -------------------------------------------------------------------- */
+        int nCurves = 0;
+        CurveSegment* pasCurves = NULL;
+        if( bHasCurves && nOffset + 4 <= nBytes )
+        {
+            memcpy( &nCurves, pabyShape + nOffset, 4 );
+            CPL_LSBPTR32(&nCurves);
+            nOffset += 4;
+#ifdef DEBUG_VERBOSE
+            CPLDebug("OGR", "nCurves = %d", nCurves);
+#endif
+            if( nCurves < 0 || nCurves > (nBytes - nOffset) / (8 + 20) )
+            {
+                CPLDebug("OGR", "Invalid nCurves = %d", nCurves);
+                nCurves = 0;
+            }
+            pasCurves = static_cast<CurveSegment *>(
+                VSI_MALLOC2_VERBOSE(sizeof(CurveSegment), nCurves));
+            if( pasCurves == NULL )
+            {
+                nCurves = 0;
+            }
+            int iCurve = 0;
+            for( int i = 0; i < nCurves; i++ )
+            {
+                if( nOffset + 8 > nBytes )
+                {
+                    CPLDebug("OGR", "Not enough bytes");
+                    break;
+                }
+                int nStartPointIdx = 0;
+                memcpy( &nStartPointIdx, pabyShape + nOffset, 4 );
+                CPL_LSBPTR32(&nStartPointIdx);
+                nOffset += 4;
+                int nSegmentType = 0;
+                memcpy( &nSegmentType, pabyShape + nOffset, 4 );
+                CPL_LSBPTR32(&nSegmentType);
+                nOffset += 4;
+#ifdef DEBUG_VERBOSE
+                CPLDebug("OGR", "[%d] nStartPointIdx = %d, segmentType = %d",
+                         i, nSegmentType, nSegmentType);
+#endif
+                if( nStartPointIdx < 0 || nStartPointIdx >= nPoints ||
+                    (iCurve > 0 && nStartPointIdx <=
+                     pasCurves[iCurve-1].nStartPointIdx) )
+                {
+                    CPLDebug("OGR", "Invalid nStartPointIdx = %d",
+                             nStartPointIdx);
+                    break;
+                }
+                pasCurves[iCurve].nStartPointIdx = nStartPointIdx;
+                if( nSegmentType == EXT_SHAPE_SEGMENT_ARC )
+                {
+                    if( nOffset + 20 > nBytes )
+                    {
+                        CPLDebug("OGR", "Not enough bytes");
+                        break;
+                    }
+                    double dfVal1 = 0.0;
+                    double dfVal2 = 0.0;
+                    memcpy( &dfVal1, pabyShape + nOffset + 0, 8 );
+                    CPL_LSBPTR64(&dfVal1);
+                    memcpy( &dfVal2, pabyShape + nOffset + 8, 8 );
+                    CPL_LSBPTR64(&dfVal2);
+                    int nBits = 0;
+                    memcpy( &nBits, pabyShape + nOffset + 16, 4 );
+                    CPL_LSBPTR32(&nBits);
+
+#ifdef DEBUG_VERBOSE
+                    CPLDebug("OGR", "Arc: ");
+                    CPLDebug("OGR", " dfVal1 = %f, dfVal2 = %f, nBits=%X",
+                             dfVal1, dfVal2, nBits);
+                    if( nBits & EXT_SHAPE_ARC_EMPTY )
+                        CPLDebug("OGR", "  IsEmpty");
+                    if( nBits & EXT_SHAPE_ARC_CCW )
+                        CPLDebug("OGR", "  IsCCW");
+                    if( nBits & EXT_SHAPE_ARC_MINOR )
+                        CPLDebug("OGR", " IsMinor");
+                    if( nBits & EXT_SHAPE_ARC_LINE )
+                        CPLDebug("OGR", "  IsLine");
+                    if( nBits & EXT_SHAPE_ARC_POINT )
+                        CPLDebug("OGR", "  IsPoint");
+                    if( nBits & EXT_SHAPE_ARC_IP )
+                        CPLDebug("OGR", "  DefinedIP");
+#endif
+                    if( (nBits & EXT_SHAPE_ARC_IP) != 0 )
+                    {
+                        pasCurves[iCurve].eType = CURVE_ARC_INTERIOR_POINT;
+                        pasCurves[iCurve].u.ArcByIntermediatePoint.dfX = dfVal1;
+                        pasCurves[iCurve].u.ArcByIntermediatePoint.dfY = dfVal2;
+                        iCurve++;
+                    }
+                    else if( (nBits & EXT_SHAPE_ARC_EMPTY) == 0 &&
+                             (nBits & EXT_SHAPE_ARC_LINE) == 0 &&
+                             (nBits & EXT_SHAPE_ARC_POINT) == 0 )
+                    {
+                        // This is the old deprecated way
+                        pasCurves[iCurve].eType = CURVE_ARC_CENTER_POINT;
+                        pasCurves[iCurve].u.ArcByCenterPoint.dfX = dfVal1;
+                        pasCurves[iCurve].u.ArcByCenterPoint.dfY = dfVal2;
+                        pasCurves[iCurve].u.ArcByCenterPoint.bIsCCW =
+                            (nBits & EXT_SHAPE_ARC_CCW) != 0;
+                        iCurve++;
+                    }
+                    nOffset += 16 + 4;
+                }
+                else if( nSegmentType == EXT_SHAPE_SEGMENT_BEZIER )
+                {
+                    if( nOffset + 32 > nBytes )
+                    {
+                        CPLDebug("OGR", "Not enough bytes");
+                        break;
+                    }
+                    double dfX1 = 0.0;
+                    double dfY1 = 0.0;
+                    memcpy( &dfX1, pabyShape + nOffset + 0, 8 );
+                    CPL_LSBPTR64(&dfX1);
+                    memcpy( &dfY1, pabyShape + nOffset + 8, 8 );
+                    CPL_LSBPTR64(&dfY1);
+                    double dfX2 = 0.0;
+                    double dfY2 = 0.0;
+                    memcpy( &dfX2, pabyShape + nOffset + 16, 8 );
+                    CPL_LSBPTR64(&dfX2);
+                    memcpy( &dfY2, pabyShape + nOffset + 24, 8 );
+                    CPL_LSBPTR64(&dfY2);
+#ifdef DEBUG_VERBOSE
+                    CPLDebug("OGR", "Bezier:");
+                    CPLDebug("OGR", "  dfX1 = %f, dfY1 = %f", dfX1, dfY1);
+                    CPLDebug("OGR", "  dfX2 = %f, dfY2 = %f", dfX2, dfY2);
+#endif
+                    pasCurves[iCurve].eType = CURVE_BEZIER;
+                    pasCurves[iCurve].u.Bezier.dfX1 = dfX1;
+                    pasCurves[iCurve].u.Bezier.dfY1 = dfY1;
+                    pasCurves[iCurve].u.Bezier.dfX2 = dfX2;
+                    pasCurves[iCurve].u.Bezier.dfY2 = dfY2;
+                    iCurve++;
+                    nOffset += 32;
+                }
+                else if( nSegmentType == EXT_SHAPE_SEGMENT_ELLIPSE )
+                {
+                    if( nOffset + 44 > nBytes )
+                    {
+                        CPLDebug("OGR", "Not enough bytes");
+                        break;
+                    }
+                    double dfVS0 = 0.0;
+                    memcpy( &dfVS0, pabyShape + nOffset, 8 );
+                    nOffset += 8;
+                    CPL_LSBPTR64(&dfVS0);
+
+                    double dfVS1 = 0.0;
+                    memcpy( &dfVS1, pabyShape + nOffset, 8 );
+                    nOffset += 8;
+                    CPL_LSBPTR64(&dfVS1);
+
+                    double dfRotationOrFromV = 0.0;
+                    memcpy( &dfRotationOrFromV, pabyShape + nOffset, 8 );
+                    nOffset += 8;
+                    CPL_LSBPTR64(&dfRotationOrFromV);
+
+                    double dfSemiMajor = 0.0;
+                    memcpy( &dfSemiMajor, pabyShape + nOffset, 8 );
+                    nOffset += 8;
+                    CPL_LSBPTR64(&dfSemiMajor);
+
+                    double dfMinorMajorRatioOrDeltaV = 0.0;
+                    memcpy(&dfMinorMajorRatioOrDeltaV, pabyShape + nOffset, 8);
+                    nOffset += 8;
+                    CPL_LSBPTR64(&dfMinorMajorRatioOrDeltaV);
+
+                    int nBits = 0;
+                    memcpy( &nBits, pabyShape + nOffset, 4 );
+                    CPL_LSBPTR32(&nBits);
+                    nOffset += 4;
+
+#ifdef DEBUG_VERBOSE
+                    CPLDebug("OGR", "Ellipse:");
+                    CPLDebug("OGR", "  dfVS0 = %f", dfVS0);
+                    CPLDebug("OGR", "  dfVS1 = %f", dfVS1);
+                    CPLDebug("OGR", "  dfRotationOrFromV = %f",
+                             dfRotationOrFromV);
+                    CPLDebug("OGR", "  dfSemiMajor = %f", dfSemiMajor);
+                    CPLDebug("OGR", "  dfMinorMajorRatioOrDeltaV = %f",
+                             dfMinorMajorRatioOrDeltaV);
+                    CPLDebug("OGR", "  nBits=%X", nBits);
+
+                    if( nBits & EXT_SHAPE_ELLIPSE_EMPTY )
+                        CPLDebug("OGR", "   IsEmpty");
+                    if( nBits & EXT_SHAPE_ELLIPSE_LINE )
+                        CPLDebug("OGR", "   IsLine");
+                    if( nBits & EXT_SHAPE_ELLIPSE_POINT )
+                        CPLDebug("OGR", "   IsPoint");
+                    if( nBits & EXT_SHAPE_ELLIPSE_CIRCULAR )
+                        CPLDebug("OGR", "   IsCircular");
+                    if( nBits & EXT_SHAPE_ELLIPSE_CENTER_TO )
+                        CPLDebug("OGR", "   CenterTo");
+                    if( nBits & EXT_SHAPE_ELLIPSE_CENTER_FROM )
+                        CPLDebug("OGR", "   CenterFrom");
+                    if( nBits & EXT_SHAPE_ELLIPSE_CCW )
+                        CPLDebug("OGR", "   IsCCW");
+                    if( nBits & EXT_SHAPE_ELLIPSE_MINOR )
+                        CPLDebug("OGR", "   IsMinor");
+                    if( nBits & EXT_SHAPE_ELLIPSE_COMPLETE )
+                        CPLDebug("OGR", "   IsComplete");
+#endif
+
+                    if( (nBits & EXT_SHAPE_ELLIPSE_CENTER_TO) == 0 &&
+                        (nBits & EXT_SHAPE_ELLIPSE_CENTER_FROM) == 0 )
+                    {
+                        pasCurves[iCurve].eType = CURVE_ELLIPSE_BY_CENTER;
+                        pasCurves[iCurve].u.EllipseByCenter.dfX = dfVS0;
+                        pasCurves[iCurve].u.EllipseByCenter.dfY = dfVS1;
+                        pasCurves[iCurve].u.EllipseByCenter.dfRotationDeg =
+                            dfRotationOrFromV / M_PI * 180;
+                        pasCurves[iCurve].u.EllipseByCenter.dfSemiMajor =
+                            dfSemiMajor;
+                        pasCurves[iCurve].u.EllipseByCenter.dfRatioSemiMinor =
+                            dfMinorMajorRatioOrDeltaV;
+                        pasCurves[iCurve].u.EllipseByCenter.bIsMinor =
+                            ((nBits & EXT_SHAPE_ELLIPSE_MINOR) != 0);
+                        pasCurves[iCurve].u.EllipseByCenter.bIsComplete =
+                            ((nBits & EXT_SHAPE_ELLIPSE_COMPLETE) != 0);
+                        iCurve++;
+                    }
+                }
+                else
+                {
+                    CPLDebug("OGR", "unhandled segmentType = %d", nSegmentType);
+                }
+            }
+
+            nCurves = iCurve;
+        }
+
 /* -------------------------------------------------------------------- */
 /*      Build corresponding OGR objects.                                */
 /* -------------------------------------------------------------------- */
@@ -1532,10 +2631,19 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /* -------------------------------------------------------------------- */
             if( nParts == 1 )
             {
-                OGRLineString *poLine = new OGRLineString();
-                *ppoGeom = poLine;
+                if( nCurves > 0 )
+                {
+                    *ppoGeom = OGRShapeCreateCompoundCurve(
+                      0, nPoints, pasCurves, nCurves, 0,
+                      padfX, padfY, bHasZ ? padfZ : NULL, padfM, NULL);
+                }
+                else
+                {
+                    OGRLineString *poLine = new OGRLineString();
+                    *ppoGeom = poLine;
 
-                poLine->setPoints( nPoints, padfX, padfY, padfZ, padfM );
+                    poLine->setPoints( nPoints, padfX, padfY, padfZ, padfM );
+                }
             }
 
 /* -------------------------------------------------------------------- */
@@ -1543,30 +2651,52 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
 /* -------------------------------------------------------------------- */
             else
             {
-                OGRMultiLineString *poMulti = new OGRMultiLineString;
-                *ppoGeom = poMulti;
-
-                for( i = 0; i < nParts; i++ )
+                if( nCurves > 0 )
                 {
-                    OGRLineString *poLine = new OGRLineString;
-                    int nVerticesInThisPart;
-
-                    if( i == nParts-1 )
-                        nVerticesInThisPart = nPoints - panPartStart[i];
-                    else
-                        nVerticesInThisPart =
-                            panPartStart[i+1] - panPartStart[i];
+                    OGRMultiCurve *poMulti = new OGRMultiCurve;
+                    *ppoGeom = poMulti;
 
-                    poLine->setPoints( nVerticesInThisPart,
-                                       padfX + panPartStart[i],
-                                       padfY + panPartStart[i],
-                                       padfZ + panPartStart[i],
-                                       (padfM != NULL) ? padfM + panPartStart[i] : NULL );
+                    int iCurveIdx = 0;
+                    for( int i = 0; i < nParts; i++ )
+                    {
+                        const int nVerticesInThisPart =
+                            i == nParts - 1
+                            ? nPoints - panPartStart[i]
+                            : panPartStart[i+1] - panPartStart[i];
+
+                        poMulti->addGeometryDirectly(
+                            OGRShapeCreateCompoundCurve(
+                                panPartStart[i], nVerticesInThisPart,
+                                pasCurves, nCurves, iCurveIdx,
+                                padfX, padfY, bHasZ ? padfZ : NULL, padfM,
+                                &iCurveIdx));
+                    }
+                }
+                else
+                {
+                    OGRMultiLineString *poMulti = new OGRMultiLineString;
+                    *ppoGeom = poMulti;
 
-                    poMulti->addGeometryDirectly( poLine );
+                    for( int i = 0; i < nParts; i++ )
+                    {
+                        OGRLineString *poLine = new OGRLineString;
+                        const int nVerticesInThisPart =
+                            i == nParts-1
+                            ? nPoints - panPartStart[i]
+                            : panPartStart[i+1] - panPartStart[i];
+
+                        poLine->setPoints(
+                            nVerticesInThisPart,
+                            padfX + panPartStart[i],
+                            padfY + panPartStart[i],
+                            padfZ + panPartStart[i],
+                            padfM != NULL ? padfM + panPartStart[i] : NULL );
+
+                        poMulti->addGeometryDirectly( poLine );
+                    }
                 }
             }
-        } /* ARC */
+        }  // ARC.
 
 /* -------------------------------------------------------------------- */
 /*      Polygon                                                         */
@@ -1576,65 +2706,161 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
                  || nSHPType == SHPT_POLYGONM
                  || nSHPType == SHPT_POLYGONZM )
         {
-            if (nParts != 0)
+            if( nCurves > 0 && nParts != 0)
+            {
+                if( nParts == 1 )
+                {
+                    OGRCurvePolygon *poOGRPoly = new OGRCurvePolygon;
+                    *ppoGeom = poOGRPoly;
+                    const int nVerticesInThisPart = nPoints - panPartStart[0];
+
+                    OGRCurve* poRing = OGRShapeCreateCompoundCurve(
+                        panPartStart[0], nVerticesInThisPart,
+                        pasCurves, nCurves, 0,
+                        padfX, padfY, bHasZ ? padfZ : NULL, padfM, NULL);
+                    if( poOGRPoly->addRingDirectly( poRing ) != OGRERR_NONE )
+                    {
+                        delete poRing;
+                        delete poOGRPoly;
+                        *ppoGeom = NULL;
+                    }
+                }
+                else
+                {
+                    OGRGeometry *poOGR = NULL;
+                    OGRCurvePolygon** tabPolygons =
+                        new OGRCurvePolygon*[nParts];
+
+                    int iCurveIdx = 0;
+                    for( int i = 0; i < nParts; i++ )
+                    {
+                        tabPolygons[i] = new OGRCurvePolygon();
+                        const int nVerticesInThisPart =
+                            i == nParts-1
+                            ? nPoints - panPartStart[i]
+                            : panPartStart[i+1] - panPartStart[i];
+
+                        OGRCurve* poRing = OGRShapeCreateCompoundCurve(
+                            panPartStart[i], nVerticesInThisPart,
+                            pasCurves, nCurves, iCurveIdx,
+                            padfX, padfY, bHasZ ? padfZ : NULL, padfM,
+                            &iCurveIdx );
+                        if( tabPolygons[i]->addRingDirectly( poRing ) !=
+                            OGRERR_NONE )
+                        {
+                            delete poRing;
+                            for( ; i >= 0; --i )
+                                delete tabPolygons[i];
+                            delete[] tabPolygons;
+                            tabPolygons = NULL;
+                            *ppoGeom = NULL;
+                            break;
+                        }
+                    }
+
+                    if( tabPolygons != NULL )
+                    {
+                        int isValidGeometry = FALSE;
+                        const char* papszOptions[] =
+                            { "METHOD=ONLY_CCW", NULL  };
+                        poOGR = OGRGeometryFactory::organizePolygons(
+                            reinterpret_cast<OGRGeometry **>(tabPolygons),
+                            nParts,
+                            &isValidGeometry, papszOptions );
+
+                        if( !isValidGeometry )
+                        {
+                            CPLError(CE_Warning, CPLE_AppDefined,
+                                     "Geometry of polygon cannot be translated "
+                                     "to Simple Geometry.  All polygons will "
+                                     "be contained in a multipolygon.");
+                        }
+
+                        *ppoGeom = poOGR;
+                        delete[] tabPolygons;
+                    }
+                }
+            }
+            else if( nParts != 0 )
             {
-                if (nParts == 1)
+                if( nParts == 1 )
                 {
                     OGRPolygon *poOGRPoly = new OGRPolygon;
                     *ppoGeom = poOGRPoly;
                     OGRLinearRing *poRing = new OGRLinearRing;
                     int nVerticesInThisPart = nPoints - panPartStart[0];
 
-                    poRing->setPoints( nVerticesInThisPart,
-                                       padfX + panPartStart[0],
-                                       padfY + panPartStart[0],
-                                       padfZ + panPartStart[0],
-                                       (padfM != NULL) ? padfM + panPartStart[0] : NULL );
+                    poRing->setPoints(
+                        nVerticesInThisPart,
+                        padfX + panPartStart[0],
+                        padfY + panPartStart[0],
+                        padfZ + panPartStart[0],
+                        padfM != NULL ? padfM + panPartStart[0] : NULL);
 
-                    poOGRPoly->addRingDirectly( poRing );
+                    if( poOGRPoly->addRingDirectly( poRing ) != OGRERR_NONE )
+                    {
+                        delete poRing;
+                        delete poOGRPoly;
+                        *ppoGeom = NULL;
+                    }
                 }
                 else
                 {
                     OGRGeometry *poOGR = NULL;
                     OGRPolygon** tabPolygons = new OGRPolygon*[nParts];
 
-                    for( i = 0; i < nParts; i++ )
+                    for( int i = 0; i < nParts; i++ )
                     {
                         tabPolygons[i] = new OGRPolygon();
                         OGRLinearRing *poRing = new OGRLinearRing;
-                        int nVerticesInThisPart;
-
-                        if( i == nParts-1 )
-                            nVerticesInThisPart = nPoints - panPartStart[i];
-                        else
-                            nVerticesInThisPart =
-                                panPartStart[i+1] - panPartStart[i];
-
-                        poRing->setPoints( nVerticesInThisPart,
-                                           padfX + panPartStart[i],
-                                           padfY + panPartStart[i],
-                                           padfZ + panPartStart[i],
-                                           (padfM != NULL) ? padfM + panPartStart[i] : NULL );
-                        tabPolygons[i]->addRingDirectly(poRing);
+                        const int nVerticesInThisPart =
+                            i == nParts - 1
+                            ? nPoints - panPartStart[i]
+                            : panPartStart[i+1] - panPartStart[i];
+
+                        poRing->setPoints(
+                            nVerticesInThisPart,
+                            padfX + panPartStart[i],
+                            padfY + panPartStart[i],
+                            padfZ + panPartStart[i],
+                            padfM != NULL ? padfM + panPartStart[i] : NULL );
+                        if( tabPolygons[i]->addRingDirectly(poRing) !=
+                            OGRERR_NONE )
+                        {
+                            delete poRing;
+                            for( ; i >= 0; --i )
+                                delete tabPolygons[i];
+                            delete[] tabPolygons;
+                            tabPolygons = NULL;
+                            *ppoGeom = NULL;
+                            break;
+                        }
                     }
 
-                    int isValidGeometry;
-                    const char* papszOptions[] = { "METHOD=ONLY_CCW", NULL };
-                    poOGR = OGRGeometryFactory::organizePolygons(
-                        (OGRGeometry**)tabPolygons, nParts, &isValidGeometry, papszOptions );
-
-                    if (!isValidGeometry)
+                    if( tabPolygons != NULL )
                     {
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                 "Geometry of polygon cannot be translated to Simple Geometry. "
-                                 "All polygons will be contained in a multipolygon.\n");
+                        int isValidGeometry = FALSE;
+                        const char* papszOptions[] =
+                            { "METHOD=ONLY_CCW", NULL };
+                        poOGR = OGRGeometryFactory::organizePolygons(
+                            reinterpret_cast<OGRGeometry **>(tabPolygons),
+                            nParts,
+                            &isValidGeometry, papszOptions );
+
+                        if( !isValidGeometry )
+                        {
+                            CPLError(CE_Warning, CPLE_AppDefined,
+                                     "Geometry of polygon cannot be translated "
+                                     "to Simple Geometry. All polygons will be "
+                                     "contained in a multipolygon.");
+                        }
+
+                        *ppoGeom = poOGR;
+                        delete[] tabPolygons;
                     }
-
-                    *ppoGeom = poOGR;
-                    delete[] tabPolygons;
                 }
             }
-        } /* polygon */
+        }  // Polygon.
 
 /* -------------------------------------------------------------------- */
 /*      Multipatch                                                      */
@@ -1656,74 +2882,73 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
         CPLFree( padfY );
         CPLFree( padfZ );
         CPLFree( padfM );
+        CPLFree( pasCurves );
 
-        if (*ppoGeom != NULL)
+        if( *ppoGeom != NULL )
         {
             if( !bHasZ )
                 (*ppoGeom)->set3D(FALSE);
         }
 
-        return OGRERR_NONE;
+        return *ppoGeom != NULL ? OGRERR_NONE : OGRERR_FAILURE;
     }
 
 /* ==================================================================== */
-/*  Extract vertices for a MultiPoint.                  */
+/*     Extract vertices for a MultiPoint.                               */
 /* ==================================================================== */
     else if(    nSHPType == SHPT_MULTIPOINT
              || nSHPType == SHPT_MULTIPOINTM
              || nSHPType == SHPT_MULTIPOINTZ
              || nSHPType == SHPT_MULTIPOINTZM )
     {
-      GInt32 nPoints;
-      GInt32 nOffsetZ;
-      GInt32 nOffsetM = 0;
-      int i;
-
+      GInt32 nPoints = 0;
       memcpy( &nPoints, pabyShape + 36, 4 );
       CPL_LSBPTR32( &nPoints );
 
-      if (nPoints < 0 || nPoints > 50 * 1000 * 1000 )
+      if( nPoints < 0 || nPoints > 50 * 1000 * 1000 )
       {
           CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d.",
                    nPoints);
           return OGRERR_FAILURE;
       }
 
-      nOffsetZ = 40 + 2*8*nPoints + 2*8;
+      const GInt32 nOffsetZ = 40 + 2*8*nPoints + 2*8;
+      GInt32 nOffsetM = 0;
       if( bHasM )
-          nOffsetM = (bHasZ) ? nOffsetZ + 2*8 * 8*nPoints : nOffsetZ;
+          nOffsetM = bHasZ ? nOffsetZ + 2 * 8 * 8 * nPoints : nOffsetZ;
 
       OGRMultiPoint *poMultiPt = new OGRMultiPoint;
       *ppoGeom = poMultiPt;
 
-      for( i = 0; i < nPoints; i++ )
+      for( int i = 0; i < nPoints; i++ )
       {
-          double x, y;
           OGRPoint *poPt = new OGRPoint;
 
-          /* Copy X */
+          // Copy X.
+          double x = 0.0;
           memcpy(&x, pabyShape + 40 + i*16, 8);
           CPL_LSBPTR64(&x);
           poPt->setX(x);
 
-          /* Copy Y */
+          // Copy Y.
+          double y = 0.0;
           memcpy(&y, pabyShape + 40 + i*16 + 8, 8);
           CPL_LSBPTR64(&y);
           poPt->setY(y);
 
-          /* Copy Z */
-          if ( bHasZ )
+          // Copy Z.
+          if( bHasZ )
           {
-            double z;
+            double z = 0.0;
             memcpy(&z, pabyShape + nOffsetZ + i*8, 8);
             CPL_LSBPTR64(&z);
             poPt->setZ(z);
           }
 
-          /* Copy M */
-          if ( bHasM )
+          // Copy M.
+          if( bHasM )
           {
-            double m;
+            double m = 0.0;
             memcpy(&m, pabyShape + nOffsetM + i*8, 8);
             CPL_LSBPTR64(&m);
             poPt->setM(m);
@@ -1746,29 +2971,32 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
              || nSHPType == SHPT_POINTZ
              || nSHPType == SHPT_POINTZM )
     {
-        /* int nOffset; */
-        double  dfX, dfY, dfZ = 0, dfM = 0;
-
-        if (nBytes < 4 + 8 + 8 + ((bHasZ) ? 8 : 0) + ((bHasM) ? 8 : 0))
+        if( nBytes < 4 + 8 + 8 + ((bHasZ) ? 8 : 0) + ((bHasM) ? 8 : 0) )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
+                     "Corrupted Shape : nBytes=%d, nSHPType=%d",
+                     nBytes, nSHPType);
             return OGRERR_FAILURE;
         }
 
+        double dfX = 0.0;
+        double dfY = 0.0;
+
         memcpy( &dfX, pabyShape + 4, 8 );
         memcpy( &dfY, pabyShape + 4 + 8, 8 );
 
         CPL_LSBPTR64( &dfX );
         CPL_LSBPTR64( &dfY );
-        /* nOffset = 20 + 8; */
+        // int nOffset = 20 + 8;
 
+        double dfZ = 0.0;
         if( bHasZ )
         {
             memcpy( &dfZ, pabyShape + 4 + 16, 8 );
             CPL_LSBPTR64( &dfZ );
         }
 
+        double dfM = 0.0;
         if( bHasM )
         {
             memcpy( &dfM, pabyShape + 4 + 16 + ((bHasZ) ? 8 : 0), 8 );
@@ -1776,9 +3004,13 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
         }
 
         if( bHasZ && bHasM )
+        {
             *ppoGeom = new OGRPoint( dfX, dfY, dfZ, dfM );
+        }
         else if( bHasZ )
+        {
             *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
+        }
         else if( bHasM )
         {
             OGRPoint* poPoint = new OGRPoint( dfX, dfY );
@@ -1786,14 +3018,16 @@ OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
             *ppoGeom = poPoint;
         }
         else
+        {
             *ppoGeom = new OGRPoint( dfX, dfY );
+        }
 
         return OGRERR_NONE;
     }
 
     CPLError(CE_Failure, CPLE_AppDefined,
              "Unsupported geometry type: %d",
-              nSHPType );
+             nSHPType );
 
     return OGRERR_FAILURE;
 }
diff --git a/ogr/ogrpgeogeometry.h b/ogr/ogrpgeogeometry.h
index c883875..61ee0f8 100644
--- a/ogr/ogrpgeogeometry.h
+++ b/ogr/ogrpgeogeometry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgeogeometry.h 33631 2016-03-04 06:28:09Z goatbar $
+ * $Id: ogrpgeogeometry.h 36883 2016-12-15 13:31:12Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements decoder of shapebin geometry for PGeo
@@ -35,6 +35,7 @@
 
 #define SHPT_NULL          0
 
+#ifndef SHPT_POINT
 #define SHPT_POINT         1
 #define SHPT_POINTM       21
 #define SHPT_POINTZM      11
@@ -57,6 +58,7 @@
 
 #define SHPT_MULTIPATCHM  31
 #define SHPT_MULTIPATCH   32
+#endif // SHPT_POINT
 
 #define SHPT_GENERALPOLYLINE    50
 #define SHPT_GENERALPOLYGON     51
@@ -73,13 +75,13 @@
 #define ESRI_LAYERGEOMTYPE_POLYGON       4
 #define ESRI_LAYERGEOMTYPE_MULTIPATCH    9
 
-void OGRCreateFromMultiPatchPart(OGRMultiPolygon *poMP,
-                                 OGRPolygon*& poLastPoly,
-                                 int nPartType,
-                                 int nPartPoints,
-                                 double* padfX,
-                                 double* padfY,
-                                 double* padfZ);
+OGRGeometry* OGRCreateFromMultiPatch( int nParts,
+                                      const GInt32* panPartStart,
+                                      const GInt32* panPartType,
+                                      int nPoints,
+                                      const double* padfX,
+                                      const double* padfY,
+                                      const double* padfZ );
 
 OGRErr CPL_DLL OGRCreateFromShapeBin( GByte *pabyShape,
                               OGRGeometry **ppoGeom,
@@ -89,6 +91,15 @@ OGRErr CPL_DLL OGRWriteToShapeBin( OGRGeometry *poGeom,
                            GByte **ppabyShape,
                            int *pnBytes );
 
+OGRErr OGRCreateMultiPatch( OGRGeometry *poGeom,
+                            int bAllowSHPTTriangle,
+                            int& nParts,
+                            int*& panPartStart,
+                            int*& panPartType,
+                            int& nPoints,
+                            OGRRawPoint*& poPoints,
+                            double*& padfZ );
+
 OGRErr CPL_DLL OGRWriteMultiPatchToShapeBin( OGRGeometry *poGeom,
                            GByte **ppabyShape,
                            int *pnBytes );
diff --git a/ogr/ogrpoint.cpp b/ogr/ogrpoint.cpp
index 03ec928..91dc8cd 100644
--- a/ogr/ogrpoint.cpp
+++ b/ogr/ogrpoint.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpoint.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The Point geometry class.
@@ -28,14 +27,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
-#include "ogr_p.h"
 
-/* for std::numeric_limits */
+#include <cstdio>
+#include <cstring>
+#include <algorithm>
 #include <limits>
 #include <new>
 
-CPL_CVSID("$Id: ogrpoint.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+#include "cpl_conv.h"
+#include "ogr_core.h"
+#include "ogr_p.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: ogrpoint.cpp 36324 2016-11-20 02:28:41Z goatbar $");
 
 /************************************************************************/
 /*                              OGRPoint()                              */
@@ -54,49 +60,61 @@ OGRPoint::OGRPoint()
 
 /************************************************************************/
 /*                              OGRPoint()                              */
-/*                                                                      */
-/*      Initialize point to value.                                      */
 /************************************************************************/
 
-OGRPoint::OGRPoint( double xIn, double yIn, double zIn )
+/**
+ * \brief Create a point.
+ * @param xIn x
+ * @param yIn y
+ * @param zIn z
+ */
 
+OGRPoint::OGRPoint( double xIn, double yIn, double zIn ) :
+    x(xIn),
+    y(yIn),
+    z(zIn),
+    m(0.0)
 {
-    x = xIn;
-    y = yIn;
-    z = zIn;
-    m = 0.0;
     flags = OGR_G_NOT_EMPTY_POINT | OGR_G_3D;
 }
 
 /************************************************************************/
 /*                              OGRPoint()                              */
-/*                                                                      */
-/*      Initialize point to value.                                      */
 /************************************************************************/
 
-OGRPoint::OGRPoint( double xIn, double yIn )
+/**
+ * \brief Create a point.
+ * @param xIn x
+ * @param yIn y
+ */
 
+OGRPoint::OGRPoint( double xIn, double yIn ) :
+    x(xIn),
+    y(yIn),
+    z(0.0),
+    m(0.0)
 {
-    x = xIn;
-    y = yIn;
-    z = 0.0;
-    m = 0.0;
     flags = OGR_G_NOT_EMPTY_POINT;
 }
 
 /************************************************************************/
 /*                              OGRPoint()                              */
-/*                                                                      */
-/*      Initialize point to value.                                      */
 /************************************************************************/
 
-OGRPoint::OGRPoint( double xIn, double yIn, double zIn, double mIn )
+/**
+ * \brief Create a point.
+ * @param xIn x
+ * @param yIn y
+ * @param zIn z
+ * @param mIn m
+ */
 
+OGRPoint::OGRPoint( double xIn, double yIn, double zIn, double mIn ) :
+    x(xIn),
+    y(yIn),
+    z(zIn),
+    m(mIn)
 {
-    x = xIn;
-    y = yIn;
-    z = zIn;
-    m = mIn;
     flags = OGR_G_NOT_EMPTY_POINT | OGR_G_3D | OGR_G_MEASURED;
 }
 
@@ -126,10 +144,7 @@ OGRPoint::OGRPoint( const OGRPoint& other ) :
 /*                             ~OGRPoint()                              */
 /************************************************************************/
 
-OGRPoint::~OGRPoint()
-
-{
-}
+OGRPoint::~OGRPoint() {}
 
 /************************************************************************/
 /*                       operator=( const OGRPoint& )                   */
@@ -167,7 +182,7 @@ OGRPoint& OGRPoint::operator=( const OGRPoint& other )
 OGRGeometry *OGRPoint::clone() const
 
 {
-    OGRPoint    *poNewPoint = new (std::nothrow) OGRPoint( x, y, z, m );
+    OGRPoint *poNewPoint = new (std::nothrow) OGRPoint( x, y, z, m );
     if( poNewPoint == NULL )
         return NULL;
 
@@ -183,7 +198,10 @@ OGRGeometry *OGRPoint::clone() const
 void OGRPoint::empty()
 
 {
-    x = y = z = m = 0.0;
+    x = 0.0;
+    y = 0.0;
+    z = 0.0;
+    m = 0.0;
     flags &= ~OGR_G_NOT_EMPTY_POINT;
 }
 
@@ -231,7 +249,8 @@ const char * OGRPoint::getGeometryName() const
 void OGRPoint::flattenTo2D()
 
 {
-    z = m = 0;
+    z = 0.0;
+    m = 0.0;
     flags &= ~OGR_G_3D;
     setMeasured(FALSE);
 }
@@ -281,10 +300,11 @@ OGRErr OGRPoint::importFromWkb( unsigned char * pabyData,
                                 OGRwkbVariant eWkbVariant )
 
 {
-    OGRwkbByteOrder     eByteOrder;
+    OGRwkbByteOrder eByteOrder = wkbNDR;
 
     flags = 0;
-    OGRErr eErr = importPreambuleFromWkb( pabyData, nSize, eByteOrder, eWkbVariant );
+    OGRErr eErr =
+        importPreambuleFromWkb( pabyData, nSize, eByteOrder, eWkbVariant );
     pabyData += 5;
     if( eErr != OGRERR_NONE )
         return eErr;
@@ -293,7 +313,8 @@ OGRErr OGRPoint::importFromWkb( unsigned char * pabyData,
     {
         if( (nSize < 37) && ((flags & OGR_G_3D) && (flags & OGR_G_MEASURED)) )
             return OGRERR_NOT_ENOUGH_DATA;
-        else if( (nSize < 29) && ((flags & OGR_G_3D) || (flags & OGR_G_MEASURED)) )
+        else if( (nSize < 29) && ((flags & OGR_G_3D) ||
+                                  (flags & OGR_G_MEASURED)) )
             return OGRERR_NOT_ENOUGH_DATA;
         else if( nSize < 21 )
             return OGRERR_NOT_ENOUGH_DATA;
@@ -338,8 +359,8 @@ OGRErr OGRPoint::importFromWkb( unsigned char * pabyData,
         m = 0;
     }
 
-    /* Detect coordinates are not NaN --> NOT EMPTY */
-    if(!( x != x && y != y ))
+    // Detect coordinates are not NaN --> NOT EMPTY.
+    if( !(CPLIsNan(x) && CPLIsNan(y)) )
         flags |= OGR_G_NOT_EMPTY_POINT;
 
     return OGRERR_NONE;
@@ -351,15 +372,16 @@ OGRErr OGRPoint::importFromWkb( unsigned char * pabyData,
 /*      Build a well known binary representation of this object.        */
 /************************************************************************/
 
-OGRErr  OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
-                               unsigned char * pabyData,
-                               OGRwkbVariant eWkbVariant ) const
+OGRErr OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
+                              unsigned char * pabyData,
+                              OGRwkbVariant eWkbVariant ) const
 
 {
 /* -------------------------------------------------------------------- */
 /*      Set the byte order.                                             */
 /* -------------------------------------------------------------------- */
-    pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
+    pabyData[0] =
+        DB2_V72_UNFIX_BYTE_ORDER(static_cast<unsigned char>(eByteOrder));
     pabyData += 1;
 
 /* -------------------------------------------------------------------- */
@@ -372,12 +394,16 @@ OGRErr  OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
     {
         nGType = wkbFlatten(nGType);
         if( Is3D() )
-            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
+            // Explicitly set wkb25DBit.
+            nGType =
+                static_cast<OGRwkbGeometryType>(nGType | wkb25DBitInternalUse);
         if( IsMeasured() )
-            nGType = (OGRwkbGeometryType)(nGType | 0x40000000);
+            nGType = static_cast<OGRwkbGeometryType>(nGType | 0x40000000);
     }
-    else if ( eWkbVariant == wkbVariantIso )
+    else if( eWkbVariant == wkbVariantIso )
+    {
         nGType = getIsoGeometryType();
+    }
 
     if( eByteOrder == wkbNDR )
         nGType = CPL_LSBWORD32( nGType );
@@ -391,9 +417,9 @@ OGRErr  OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
 /*      Copy in the raw data. Swap if needed.                           */
 /* -------------------------------------------------------------------- */
 
-    if ( IsEmpty() && eWkbVariant == wkbVariantIso )
+    if( IsEmpty() && eWkbVariant == wkbVariantIso )
     {
-        double dNan = std::numeric_limits<double>::quiet_NaN();
+        const double dNan = std::numeric_limits<double>::quiet_NaN();
         memcpy( pabyData, &dNan, 8 );
         if( OGR_SWAP( eByteOrder ) )
             CPL_SWAPDOUBLE( pabyData );
@@ -451,9 +477,10 @@ OGRErr  OGRPoint::exportToWkb( OGRwkbByteOrder eByteOrder,
 OGRErr OGRPoint::importFromWkt( char ** ppszInput )
 
 {
-    int bHasZ = FALSE, bHasM = FALSE;
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
     bool bIsEmpty = false;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    OGRErr eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     flags = 0;
     if( eErr != OGRERR_NONE )
         return eErr;
@@ -461,25 +488,30 @@ OGRErr OGRPoint::importFromWkt( char ** ppszInput )
     if( bHasM ) flags |= OGR_G_MEASURED;
     if( bIsEmpty )
     {
-        // we should be at the end
+        // Should be at the end.
         if( !((*ppszInput[0] == '\000') || (*ppszInput[0] == ',')) )
             return OGRERR_CORRUPT_DATA;
         return OGRERR_NONE;
-    } else
+    }
+    else
+    {
         flags |= OGR_G_NOT_EMPTY_POINT;
+    }
 
-    const char  *pszInput = *ppszInput;
+    const char *pszInput = *ppszInput;
 
 /* -------------------------------------------------------------------- */
 /*      Read the point list which should consist of exactly one point.  */
 /* -------------------------------------------------------------------- */
-    OGRRawPoint         *poPoints = NULL;
-    double              *padfZ = NULL;
-    double              *padfM = NULL;
-    int                 nMaxPoint = 0, nPoints = 0;
-    int                 flagsFromInput = flags;
-
-    pszInput = OGRWktReadPointsM( pszInput, &poPoints, &padfZ, &padfM, &flagsFromInput,
+    OGRRawPoint *poPoints = NULL;
+    double *padfZ = NULL;
+    double *padfM = NULL;
+    int nMaxPoint = 0;
+    int nPoints = 0;
+    int flagsFromInput = flags;
+
+    pszInput = OGRWktReadPointsM( pszInput, &poPoints, &padfZ, &padfM,
+                                  &flagsFromInput,
                                   &nMaxPoint, &nPoints );
     if( pszInput == NULL || nPoints != 1 )
     {
@@ -514,12 +546,11 @@ OGRErr OGRPoint::importFromWkt( char ** ppszInput )
         if( padfM != NULL )
             m = padfM[0];
     }
-    if( padfZ != NULL )
-        CPLFree( padfZ );
-    if( padfM != NULL )
-        CPLFree( padfM );
 
-    *ppszInput = (char *) pszInput;
+    CPLFree( padfZ );
+    CPLFree( padfM );
+
+    *ppszInput = const_cast<char *>(pszInput);
 
     return OGRERR_NONE;
 }
@@ -535,10 +566,7 @@ OGRErr OGRPoint::exportToWkt( char ** ppszDstText,
                               OGRwkbVariant eWkbVariant ) const
 
 {
-    char        szTextEquiv[180];
-    char        szCoordinate[80];
-
-    if ( IsEmpty() )
+    if( IsEmpty() )
     {
         if( eWkbVariant == wkbVariantIso )
         {
@@ -552,25 +580,37 @@ OGRErr OGRPoint::exportToWkt( char ** ppszDstText,
                 *ppszDstText = CPLStrdup("POINT EMPTY");
         }
         else
+        {
             *ppszDstText = CPLStrdup("POINT EMPTY");
+        }
     }
     else
     {
+        char szTextEquiv[180] = {};
         if( eWkbVariant == wkbVariantIso )
         {
-            OGRMakeWktCoordinateM(szCoordinate, x, y, z, m, Is3D(), IsMeasured());
+            char szCoordinate[80] = {};
+            OGRMakeWktCoordinateM(szCoordinate, x, y, z, m,
+                                  Is3D(), IsMeasured());
             if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
-                snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT ZM (%s)", szCoordinate);
+                snprintf(szTextEquiv, sizeof(szTextEquiv),
+                         "POINT ZM (%s)", szCoordinate);
             else if( flags & OGR_G_MEASURED )
-                snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT M (%s)", szCoordinate);
+                snprintf(szTextEquiv, sizeof(szTextEquiv),
+                         "POINT M (%s)", szCoordinate);
             else if( flags & OGR_G_3D )
-                snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT Z (%s)", szCoordinate);
+                snprintf(szTextEquiv, sizeof(szTextEquiv),
+                         "POINT Z (%s)", szCoordinate);
             else
-                snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT (%s)", szCoordinate);
+                snprintf(szTextEquiv, sizeof(szTextEquiv),
+                         "POINT (%s)", szCoordinate);
         }
-        else {
+        else
+        {
+            char szCoordinate[80] = {};
             OGRMakeWktCoordinateM(szCoordinate, x, y, z, m, Is3D(), FALSE);
-            snprintf( szTextEquiv, sizeof(szTextEquiv), "POINT (%s)", szCoordinate );
+            snprintf( szTextEquiv, sizeof(szTextEquiv),
+                      "POINT (%s)", szCoordinate );
         }
         *ppszDstText = CPLStrdup( szTextEquiv );
     }
@@ -585,8 +625,10 @@ OGRErr OGRPoint::exportToWkt( char ** ppszDstText,
 void OGRPoint::getEnvelope( OGREnvelope * psEnvelope ) const
 
 {
-    psEnvelope->MinX = psEnvelope->MaxX = getX();
-    psEnvelope->MinY = psEnvelope->MaxY = getY();
+    psEnvelope->MinX = getX();
+    psEnvelope->MaxX = getX();
+    psEnvelope->MinY = getY();
+    psEnvelope->MaxY = getY();
 }
 
 /************************************************************************/
@@ -596,12 +638,14 @@ void OGRPoint::getEnvelope( OGREnvelope * psEnvelope ) const
 void OGRPoint::getEnvelope( OGREnvelope3D * psEnvelope ) const
 
 {
-    psEnvelope->MinX = psEnvelope->MaxX = getX();
-    psEnvelope->MinY = psEnvelope->MaxY = getY();
-    psEnvelope->MinZ = psEnvelope->MaxZ = getZ();
+    psEnvelope->MinX = getX();
+    psEnvelope->MaxX = getX();
+    psEnvelope->MinY = getY();
+    psEnvelope->MaxY = getY();
+    psEnvelope->MinZ = getZ();
+    psEnvelope->MaxZ = getZ();
 }
 
-
 /**
  * \fn double OGRPoint::getX() const;
  *
@@ -671,20 +715,26 @@ OGRBoolean OGRPoint::Equals( OGRGeometry * poOther ) const
     if( poOther->getGeometryType() != getGeometryType() )
         return FALSE;
 
-    OGRPoint    *poOPoint = (OGRPoint *) poOther;
-    if ( flags != poOPoint->flags )
+    OGRPoint *poOPoint = dynamic_cast<OGRPoint *>(poOther);
+    if( poOPoint == NULL )
+    {
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "dynamic_cast failed.  Expected OGRPoint.");
+        return FALSE;
+    }
+    if( flags != poOPoint->flags )
         return FALSE;
 
-    if ( IsEmpty() )
+    if( IsEmpty() )
         return TRUE;
 
-    // we should eventually test the SRS.
+    // Should eventually test the SRS.
     if( poOPoint->getX() != getX()
         || poOPoint->getY() != getY()
         || poOPoint->getZ() != getZ() )
         return FALSE;
-    else
-        return TRUE;
+
+    return TRUE;
 }
 
 /************************************************************************/
@@ -694,17 +744,13 @@ OGRBoolean OGRPoint::Equals( OGRGeometry * poOther ) const
 OGRErr OGRPoint::transform( OGRCoordinateTransformation *poCT )
 
 {
-#ifdef DISABLE_OGRGEOM_TRANSFORM
-    return OGRERR_FAILURE;
-#else
     if( poCT->Transform( 1, &x, &y, &z ) )
     {
         assignSpatialReference( poCT->GetTargetCS() );
         return OGRERR_NONE;
     }
-    else
-        return OGRERR_FAILURE;
-#endif
+
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -713,9 +759,7 @@ OGRErr OGRPoint::transform( OGRCoordinateTransformation *poCT )
 
 void OGRPoint::swapXY()
 {
-    double dfTemp = x;
-    x = y;
-    y = dfTemp;
+    std::swap(x, y);
 }
 
 /************************************************************************/
@@ -728,10 +772,18 @@ OGRBoolean OGRPoint::Within( const OGRGeometry *poOtherGeom ) const
     if( !IsEmpty() && poOtherGeom != NULL &&
         wkbFlatten(poOtherGeom->getGeometryType()) == wkbCurvePolygon )
     {
-        return ((OGRCurvePolygon*)poOtherGeom)->Contains(this);
+        const OGRCurvePolygon *poCurve =
+            dynamic_cast<const OGRCurvePolygon *>(poOtherGeom);
+        if( poCurve == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRCurvePolygon.");
+            return FALSE;
+        }
+        return poCurve->Contains(this);
     }
-    else
-        return OGRGeometry::Within(poOtherGeom);
+
+    return OGRGeometry::Within(poOtherGeom);
 }
 
 /************************************************************************/
@@ -744,8 +796,16 @@ OGRBoolean OGRPoint::Intersects( const OGRGeometry *poOtherGeom ) const
     if( !IsEmpty() && poOtherGeom != NULL &&
         wkbFlatten(poOtherGeom->getGeometryType()) == wkbCurvePolygon )
     {
-        return ((OGRCurvePolygon*)poOtherGeom)->Intersects(this);
+        const OGRCurvePolygon *poCurve =
+            dynamic_cast<const OGRCurvePolygon *>(poOtherGeom);
+        if( poCurve == NULL )
+        {
+            CPLError(CE_Fatal, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected OGRCurvePolygon.");
+            return FALSE;
+        }
+        return poCurve->Intersects(this);
     }
-    else
-        return OGRGeometry::Intersects(poOtherGeom);
+
+    return OGRGeometry::Intersects(poOtherGeom);
 }
diff --git a/ogr/ogrpolygon.cpp b/ogr/ogrpolygon.cpp
index f3868bb..6497903 100644
--- a/ogr/ogrpolygon.cpp
+++ b/ogr/ogrpolygon.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRPolygon geometry class.
@@ -28,12 +27,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
-#include "ogr_p.h"
-#include "ogr_geos.h"
+
+#include <cstring>
+#include <cstddef>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_geos.h"
+#include "ogr_sfcgal.h"
+#include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $");
+CPL_CVSID("$Id: ogrpolygon.cpp 36883 2016-12-15 13:31:12Z rouault $");
 
 /************************************************************************/
 /*                             OGRPolygon()                             */
@@ -43,10 +52,7 @@ CPL_CVSID("$Id: ogrpolygon.cpp 33631 2016-03-04 06:28:09Z goatbar $");
  * \brief Create an empty polygon.
  */
 
-OGRPolygon::OGRPolygon()
-
-{
-}
+OGRPolygon::OGRPolygon() {}
 
 /************************************************************************/
 /*                     OGRPolygon( const OGRPolygon& )                  */
@@ -63,17 +69,13 @@ OGRPolygon::OGRPolygon()
 
 OGRPolygon::OGRPolygon( const OGRPolygon& other ) :
     OGRCurvePolygon(other)
-{
-}
+{}
 
 /************************************************************************/
 /*                            ~OGRPolygon()                             */
 /************************************************************************/
 
-OGRPolygon::~OGRPolygon()
-
-{
-}
+OGRPolygon::~OGRPolygon() {}
 
 /************************************************************************/
 /*                     operator=( const OGRPolygon&)                    */
@@ -106,7 +108,7 @@ OGRwkbGeometryType OGRPolygon::getGeometryType() const
 {
     if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
         return wkbPolygonZM;
-    else if( flags & OGR_G_MEASURED  )
+    else if( flags & OGR_G_MEASURED )
         return wkbPolygonM;
     else if( flags & OGR_G_3D )
         return wkbPolygon25D;
@@ -147,17 +149,31 @@ OGRLinearRing *OGRPolygon::getExteriorRing()
 {
     if( oCC.nCurveCount > 0 )
         return (OGRLinearRing*) oCC.papoCurves[0];
-    else
-        return NULL;
+
+    return NULL;
 }
 
+/**
+ * \brief Fetch reference to external polygon ring.
+ *
+ * Note that the returned ring pointer is to an internal data object of
+ * the OGRPolygon.  It should not be modified or deleted by the application,
+ * and the pointer is only valid till the polygon is next modified.  Use
+ * the OGRGeometry::clone() method to make a separate copy within the
+ * application.
+ *
+ * Relates to the SFCOM IPolygon::get_ExteriorRing() method.
+ *
+ * @return pointer to external ring.  May be NULL if the OGRPolygon is empty.
+ */
+
 const OGRLinearRing *OGRPolygon::getExteriorRing() const
 
 {
     if( oCC.nCurveCount > 0 )
         return (OGRLinearRing*) oCC.papoCurves[0];
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -193,7 +209,7 @@ OGRLinearRing *OGRPolygon::stealExteriorRing()
  *
  * Relates to the SFCOM IPolygon::get_InternalRing() method.
  *
- * @param iRing internal ring index from 0 to getNumInternalRings() - 1.
+ * @param iRing internal ring index from 0 to getNumInteriorRings() - 1.
  *
  * @return pointer to interior ring.  May be NULL.
  */
@@ -203,17 +219,33 @@ OGRLinearRing *OGRPolygon::getInteriorRing( int iRing )
 {
     if( iRing < 0 || iRing >= oCC.nCurveCount-1 )
         return NULL;
-    else
-        return (OGRLinearRing*) oCC.papoCurves[iRing+1];
+
+    return (OGRLinearRing*) oCC.papoCurves[iRing+1];
 }
 
+/**
+ * \brief Fetch reference to indicated internal ring.
+ *
+ * Note that the returned ring pointer is to an internal data object of
+ * the OGRPolygon.  It should not be modified or deleted by the application,
+ * and the pointer is only valid till the polygon is next modified.  Use
+ * the OGRGeometry::clone() method to make a separate copy within the
+ * application.
+ *
+ * Relates to the SFCOM IPolygon::get_InternalRing() method.
+ *
+ * @param iRing internal ring index from 0 to getNumInteriorRings() - 1.
+ *
+ * @return pointer to interior ring.  May be NULL.
+ */
+
 const OGRLinearRing *OGRPolygon::getInteriorRing( int iRing ) const
 
 {
     if( iRing < 0 || iRing >= oCC.nCurveCount-1 )
         return NULL;
-    else
-        return (OGRLinearRing*) oCC.papoCurves[iRing+1];
+
+    return (OGRLinearRing*) oCC.papoCurves[iRing+1];
 }
 
 /************************************************************************/
@@ -226,11 +258,11 @@ const OGRLinearRing *OGRPolygon::getInteriorRing( int iRing ) const
  * After the call to that function, only call to stealInteriorRing() or
  * destruction of the OGRPolygon is valid. Other operations may crash.
  *
- * @param iRing internal ring index from 0 to getNumInternalRings() - 1.
+ * @param iRing internal ring index from 0 to getNumInteriorRings() - 1.
  * @return pointer to interior ring.  May be NULL.
  */
 
-OGRLinearRing *OGRPolygon::stealInteriorRing(int iRing)
+OGRLinearRing *OGRPolygon::stealInteriorRing( int iRing )
 {
     if( iRing < 0 || iRing >= oCC.nCurveCount-1 )
         return NULL;
@@ -239,20 +271,23 @@ OGRLinearRing *OGRPolygon::stealInteriorRing(int iRing)
     return poRet;
 }
 
+/*! @cond Doxygen_Suppress */
 /************************************************************************/
 /*                            checkRing()                               */
 /************************************************************************/
 
 int OGRPolygon::checkRing( OGRCurve * poNewRing ) const
 {
-    if ( !(EQUAL(poNewRing->getGeometryName(), "LINEARRING")) )
+    if( !(EQUAL(poNewRing->getGeometryName(), "LINEARRING")) )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Wrong curve type. Expected LINEARRING.");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Wrong curve type. Expected LINEARRING.");
         return FALSE;
     }
 
     return TRUE;
 }
+/*! @endcond */
 
 /************************************************************************/
 /*                              WkbSize()                               */
@@ -264,7 +299,7 @@ int OGRPolygon::checkRing( OGRCurve * poNewRing ) const
 int OGRPolygon::WkbSize() const
 
 {
-    int         nSize = 9;
+    int nSize = 9;
 
     for( int i = 0; i < oCC.nCurveCount; i++ )
     {
@@ -286,9 +321,9 @@ OGRErr OGRPolygon::importFromWkb( unsigned char * pabyData,
                                   OGRwkbVariant eWkbVariant )
 
 {
-    OGRwkbByteOrder eByteOrder;
+    OGRwkbByteOrder eByteOrder = wkbNDR;
     int nDataOffset = 0;
-    /* coverity[tainted_data] */
+    // coverity[tainted_data]
     OGRErr eErr = oCC.importPreambuleFromWkb(this, pabyData, nSize, nDataOffset,
                                              eByteOrder, 4, eWkbVariant);
     if( eErr != OGRERR_NONE )
@@ -326,16 +361,17 @@ OGRErr OGRPolygon::importFromWkb( unsigned char * pabyData,
 /*      Build a well known binary representation of this object.        */
 /************************************************************************/
 
-OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
-                                 unsigned char * pabyData,
-                                 OGRwkbVariant eWkbVariant ) const
+OGRErr OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
+                                unsigned char * pabyData,
+                                OGRwkbVariant eWkbVariant ) const
 
 {
 
 /* -------------------------------------------------------------------- */
 /*      Set the byte order.                                             */
 /* -------------------------------------------------------------------- */
-    pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
+    pabyData[0] =
+        DB2_V72_UNFIX_BYTE_ORDER(static_cast<unsigned char>(eByteOrder));
 
 /* -------------------------------------------------------------------- */
 /*      Set the geometry feature type.                                  */
@@ -346,17 +382,19 @@ OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
     {
         nGType = wkbFlatten(nGType);
         if( Is3D() )
-            nGType = (OGRwkbGeometryType)(nGType | wkb25DBitInternalUse); /* yes we explicitly set wkb25DBit */
+            // Explicitly set wkb25DBit.
+            nGType =
+                static_cast<OGRwkbGeometryType>(nGType | wkb25DBitInternalUse);
         if( IsMeasured() )
-            nGType = (OGRwkbGeometryType)(nGType | 0x40000000);
+            nGType = static_cast<OGRwkbGeometryType>(nGType | 0x40000000);
     }
-    else if ( eWkbVariant == wkbVariantIso )
+    else if( eWkbVariant == wkbVariantIso )
         nGType = getIsoGeometryType();
 
-    if( eByteOrder == wkbNDR )
-        nGType = CPL_LSBWORD32( nGType );
-    else
-        nGType = CPL_MSBWORD32( nGType );
+    if( OGR_SWAP( eByteOrder ) )
+    {
+        nGType = CPL_SWAP32(nGType);
+    }
 
     memcpy( pabyData + 1, &nGType, 4 );
 
@@ -365,9 +403,7 @@ OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
 /* -------------------------------------------------------------------- */
     if( OGR_SWAP( eByteOrder ) )
     {
-        int     nCount;
-
-        nCount = CPL_SWAP32( oCC.nCurveCount );
+        const int nCount = CPL_SWAP32( oCC.nCurveCount );
         memcpy( pabyData+5, &nCount, 4 );
     }
     else
@@ -384,7 +420,7 @@ OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
     {
         OGRLinearRing* poLR = (OGRLinearRing*) oCC.papoCurves[iRing];
         poLR->_exportToWkb( eByteOrder, flags,
-                                        pabyData + nOffset );
+                            pabyData + nOffset );
 
         nOffset += poLR->_WkbSize( flags );
     }
@@ -402,9 +438,10 @@ OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
 OGRErr OGRPolygon::importFromWkt( char ** ppszInput )
 
 {
-    int bHasZ = FALSE, bHasM = FALSE;
+    int bHasZ = FALSE;
+    int bHasM = FALSE;
     bool bIsEmpty = false;
-    OGRErr      eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    OGRErr eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM, &bIsEmpty);
     flags = 0;
     if( eErr != OGRERR_NONE )
         return eErr;
@@ -414,8 +451,8 @@ OGRErr OGRPolygon::importFromWkt( char ** ppszInput )
         return OGRERR_NONE;
 
     OGRRawPoint *paoPoints = NULL;
-    int          nMaxPoints = 0;
-    double      *padfZ = NULL;
+    int nMaxPoints = 0;
+    double *padfZ = NULL;
 
     eErr = importFromWKTListOnly( ppszInput, bHasZ, bHasM,
                                   paoPoints, nMaxPoints, padfZ );
@@ -426,21 +463,24 @@ OGRErr OGRPolygon::importFromWkt( char ** ppszInput )
     return eErr;
 }
 
+/*! @cond Doxygen_Suppress */
 /************************************************************************/
 /*                        importFromWKTListOnly()                       */
 /*                                                                      */
 /*      Instantiate from "((x y, x y, ...),(x y, ...),...)"             */
 /************************************************************************/
 
-OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHasM,
-                                          OGRRawPoint*& paoPoints, int& nMaxPoints,
+OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput,
+                                          int bHasZ, int bHasM,
+                                          OGRRawPoint*& paoPoints,
+                                          int& nMaxPoints,
                                           double*& padfZ )
 
 {
-    char        szToken[OGR_WKT_TOKEN_MAX];
-    const char  *pszInput = *ppszInput;
+    char szToken[OGR_WKT_TOKEN_MAX] = {};
+    const char *pszInput = *ppszInput;
 
-    /* Skip first '(' */
+    // Skip first '('.
     pszInput = OGRWktReadToken( pszInput, szToken );
     if( EQUAL(szToken, "EMPTY") )
     {
@@ -455,14 +495,13 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
 /*      point list buffer from ring to ring to cut down on              */
 /*      allocate/deallocate overhead.                                   */
 /* ==================================================================== */
-    int         nMaxRings = 0;
-    double      *padfM = NULL;
+    int nMaxRings = 0;
+    double *padfM = NULL;
 
     do
     {
-
         const char* pszNext = OGRWktReadToken( pszInput, szToken );
-        if (EQUAL(szToken,"EMPTY"))
+        if( EQUAL(szToken, "EMPTY") )
         {
 /* -------------------------------------------------------------------- */
 /*      Do we need to grow the ring array?                              */
@@ -470,14 +509,15 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
             if( oCC.nCurveCount == nMaxRings )
             {
                 nMaxRings = nMaxRings * 2 + 1;
-                oCC.papoCurves = (OGRCurve **)
-                    CPLRealloc(oCC.papoCurves, nMaxRings * sizeof(OGRLinearRing*));
+                oCC.papoCurves = static_cast<OGRCurve **>(
+                    CPLRealloc(oCC.papoCurves,
+                               nMaxRings * sizeof(OGRLinearRing*)));
             }
             oCC.papoCurves[oCC.nCurveCount] = new OGRLinearRing();
             oCC.nCurveCount++;
 
             pszInput = OGRWktReadToken( pszNext, szToken );
-            if ( !EQUAL(szToken, ",") )
+            if( !EQUAL(szToken, ",") )
                 break;
 
             continue;
@@ -488,15 +528,17 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
 /* -------------------------------------------------------------------- */
         int nPoints = 0;
         int flagsFromInput = flags;
-        if( flagsFromInput == 0 ) /* flags was not set, this is not called by us */
+        if( flagsFromInput == 0 )
         {
+            // Flags was not set, this is not called by us.
             if( bHasM )
                 flagsFromInput |= OGR_G_MEASURED;
             if( bHasZ )
                 flagsFromInput |= OGR_G_3D;
         }
 
-        pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM, &flagsFromInput,
+        pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM,
+                                      &flagsFromInput,
                                       &nMaxPoints, &nPoints );
         if( pszInput == NULL || nPoints == 0 )
         {
@@ -519,8 +561,8 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
         if( oCC.nCurveCount == nMaxRings )
         {
             nMaxRings = nMaxRings * 2 + 1;
-            oCC.papoCurves = (OGRCurve **)
-                CPLRealloc(oCC.papoCurves, nMaxRings * sizeof(OGRLinearRing*));
+            oCC.papoCurves = static_cast<OGRCurve **>(
+                CPLRealloc(oCC.papoCurves, nMaxRings * sizeof(OGRLinearRing*)));
         }
 
 /* -------------------------------------------------------------------- */
@@ -529,14 +571,14 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
         OGRLinearRing* poLR = new OGRLinearRing();
         oCC.papoCurves[oCC.nCurveCount] = poLR;
 
-        if (bHasM && bHasZ)
-            poLR->setPoints( nPoints, paoPoints, padfZ, padfM );
-        else if (bHasM)
-            poLR->setPointsM( nPoints, paoPoints, padfM );
-        else if (bHasZ)
-            poLR->setPoints( nPoints, paoPoints, padfZ );
+        if( bHasM && bHasZ )
+            poLR->setPoints(nPoints, paoPoints, padfZ, padfM);
+        else if( bHasM )
+            poLR->setPointsM(nPoints, paoPoints, padfM);
+        else if( bHasZ )
+            poLR->setPoints(nPoints, paoPoints, padfZ);
         else
-            poLR->setPoints( nPoints, paoPoints, padfZ );
+            poLR->setPoints(nPoints, paoPoints);
 
         oCC.nCurveCount++;
 
@@ -556,54 +598,57 @@ OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHas
     if( szToken[0] != ')' )
         return OGRERR_CORRUPT_DATA;
 
-    *ppszInput = (char *) pszInput;
+    *ppszInput = const_cast<char *>(pszInput);
     return OGRERR_NONE;
 }
+/*! @endcond */
 
 /************************************************************************/
 /*                            exportToWkt()                             */
 /*                                                                      */
 /*      Translate this structure into it's well known text format       */
-/*      equivalent.  This could be made a lot more CPU efficient!        */
+/*      equivalent.  This could be made a lot more CPU efficient.       */
 /************************************************************************/
 
 OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
                                 OGRwkbVariant eWkbVariant ) const
 
 {
-    OGRErr      eErr;
-    bool        bMustWriteComma = false;
+    bool bMustWriteComma = false;
 
 /* -------------------------------------------------------------------- */
 /*      If we have no valid exterior ring, return POLYGON EMPTY.        */
 /* -------------------------------------------------------------------- */
-    if (getExteriorRing() == NULL ||
+    if( getExteriorRing() == NULL ||
         getExteriorRing()->IsEmpty() )
     {
         if( eWkbVariant == wkbVariantIso )
         {
             if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
-                *ppszDstText = CPLStrdup("POLYGON ZM EMPTY");
+                *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " ZM EMPTY").c_str());
             else if( flags & OGR_G_MEASURED )
-                *ppszDstText = CPLStrdup("POLYGON M EMPTY");
+                *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " M EMPTY").c_str());
             else if( flags & OGR_G_3D )
-                *ppszDstText = CPLStrdup("POLYGON Z EMPTY");
+                *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " Z EMPTY").c_str());
             else
-                *ppszDstText = CPLStrdup("POLYGON EMPTY");
+                *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " EMPTY").c_str());
         }
         else
-            *ppszDstText = CPLStrdup("POLYGON EMPTY");
+            *ppszDstText = CPLStrdup((CPLString(getGeometryName()) + " EMPTY").c_str());
         return OGRERR_NONE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Build a list of strings containing the stuff for each ring.     */
 /* -------------------------------------------------------------------- */
-    char **papszRings = (char **) CPLCalloc(sizeof(char *),oCC.nCurveCount);
+    char **papszRings =
+        static_cast<char **>(CPLCalloc(sizeof(char *), oCC.nCurveCount));
     size_t nCumulativeLength = 0;
     size_t nNonEmptyRings = 0;
-    size_t *pnRingBeginning = (size_t *) CPLCalloc(sizeof(size_t),oCC.nCurveCount);
+    size_t *pnRingBeginning =
+        static_cast<size_t *>(CPLCalloc(sizeof(size_t), oCC.nCurveCount));
 
+    OGRErr eErr;
     for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
     {
         OGRLinearRing* poLR = (OGRLinearRing*) oCC.papoCurves[iRing];
@@ -630,7 +675,7 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
             pnRingBeginning[iRing] = 11;
         else
         {
-            CPLAssert( 0 );
+            CPLAssert(false);
         }
 
         nCumulativeLength += strlen(papszRings[iRing] + pnRingBeginning[iRing]);
@@ -642,7 +687,8 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
 /*      Allocate exactly the right amount of space for the              */
 /*      aggregated string.                                              */
 /* -------------------------------------------------------------------- */
-    *ppszDstText = (char *) VSI_MALLOC_VERBOSE(nCumulativeLength + nNonEmptyRings + 16);
+    *ppszDstText = (char *) VSI_MALLOC_VERBOSE(
+        nCumulativeLength + nNonEmptyRings + strlen(getGeometryName()) + strlen(" ZM ()") + 1);
 
     if( *ppszDstText == NULL )
     {
@@ -656,23 +702,24 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
     if( eWkbVariant == wkbVariantIso )
     {
         if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
-            strcpy( *ppszDstText, "POLYGON ZM (" );
+            strcpy( *ppszDstText, (CPLString(getGeometryName()) + " ZM (").c_str() );
         else if( flags & OGR_G_MEASURED )
-            strcpy( *ppszDstText, "POLYGON M (" );
+            strcpy( *ppszDstText, (CPLString(getGeometryName()) + " M (").c_str() );
         else if( flags & OGR_G_3D )
-            strcpy( *ppszDstText, "POLYGON Z (" );
+            strcpy( *ppszDstText, (CPLString(getGeometryName()) + " Z (").c_str() );
         else
-            strcpy( *ppszDstText, "POLYGON (" );
+            strcpy( *ppszDstText, (CPLString(getGeometryName()) + " (").c_str() );
     }
     else
-        strcpy( *ppszDstText, "POLYGON (" );
+        strcpy( *ppszDstText, (CPLString(getGeometryName()) + " (").c_str() );
     nCumulativeLength = strlen(*ppszDstText);
 
     for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
     {
         if( papszRings[iRing] == NULL )
         {
-            CPLDebug( "OGR", "OGRPolygon::exportToWkt() - skipping empty ring.");
+            CPLDebug( "OGR",
+                      "OGRPolygon::exportToWkt() - skipping empty ring.");
             continue;
         }
 
@@ -681,7 +728,9 @@ OGRErr OGRPolygon::exportToWkt( char ** ppszDstText,
         bMustWriteComma = true;
 
         size_t nRingLen = strlen(papszRings[iRing] + pnRingBeginning[iRing]);
-        memcpy( *ppszDstText + nCumulativeLength, papszRings[iRing] + pnRingBeginning[iRing], nRingLen );
+        memcpy( *ppszDstText + nCumulativeLength,
+                papszRings[iRing] + pnRingBeginning[iRing],
+                nRingLen );
         nCumulativeLength += nRingLen;
         VSIFree( papszRings[iRing] );
     }
@@ -715,20 +764,23 @@ OGRErr OGRPolygon::PointOnSurface( OGRPoint *poPoint ) const
 /*                           IsPointOnSurface()                           */
 /************************************************************************/
 
-OGRBoolean OGRPolygon::IsPointOnSurface( const OGRPoint * pt) const
+/** Return whether the point is on the surface.
+ * @return TRUE or FALSE
+ */
+OGRBoolean OGRPolygon::IsPointOnSurface( const OGRPoint * pt ) const
 {
-    if ( NULL == pt)
-        return 0;
+    if( NULL == pt)
+        return FALSE;
 
     for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
     {
-        if ( ((OGRLinearRing*)oCC.papoCurves[iRing])->isPointInRing(pt) )
+        if( ((OGRLinearRing*)oCC.papoCurves[iRing])->isPointInRing(pt) )
         {
-            return 1;
+            return TRUE;
         }
     }
 
-    return 0;
+    return FALSE;
 }
 
 /************************************************************************/
@@ -746,8 +798,9 @@ void OGRPolygon::closeRings()
 /*                           CurvePolyToPoly()                          */
 /************************************************************************/
 
-OGRPolygon* OGRPolygon::CurvePolyToPoly(CPL_UNUSED double dfMaxAngleStepSizeDegrees,
-                                        CPL_UNUSED const char* const* papszOptions) const
+OGRPolygon* OGRPolygon::CurvePolyToPoly(
+    CPL_UNUSED double dfMaxAngleStepSizeDegrees,
+    CPL_UNUSED const char* const* papszOptions ) const
 {
     return (OGRPolygon*) clone();
 }
@@ -765,24 +818,28 @@ OGRBoolean OGRPolygon::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear) const
 /*                         getLinearGeometry()                        */
 /************************************************************************/
 
-OGRGeometry* OGRPolygon::getLinearGeometry(double dfMaxAngleStepSizeDegrees,
-                                             const char* const* papszOptions) const
+OGRGeometry* OGRPolygon::getLinearGeometry(
+    double dfMaxAngleStepSizeDegrees,
+    const char* const* papszOptions ) const
 {
-    return OGRGeometry::getLinearGeometry(dfMaxAngleStepSizeDegrees, papszOptions);
+    return
+        OGRGeometry::getLinearGeometry(dfMaxAngleStepSizeDegrees, papszOptions);
 }
 
 /************************************************************************/
 /*                             getCurveGeometry()                       */
 /************************************************************************/
 
-OGRGeometry* OGRPolygon::getCurveGeometry(const char* const* papszOptions) const
+OGRGeometry *
+OGRPolygon::getCurveGeometry( const char* const* papszOptions ) const
 {
     OGRCurvePolygon* poCC = new OGRCurvePolygon();
     poCC->assignSpatialReference( getSpatialReference() );
     bool bHasCurveGeometry = false;
     for( int iRing = 0; iRing < oCC.nCurveCount; iRing++ )
     {
-        OGRCurve* poSubGeom = (OGRCurve* )oCC.papoCurves[iRing]->getCurveGeometry(papszOptions);
+        OGRCurve* poSubGeom =
+            (OGRCurve* )oCC.papoCurves[iRing]->getCurveGeometry(papszOptions);
         if( wkbFlatten(poSubGeom->getGeometryType()) != wkbLineString )
             bHasCurveGeometry = true;
         poCC->addRingDirectly( poSubGeom );
@@ -795,6 +852,7 @@ OGRGeometry* OGRPolygon::getCurveGeometry(const char* const* papszOptions) const
     return poCC;
 }
 
+/*! @cond Doxygen_Suppress */
 /************************************************************************/
 /*                        CastToCurvePolygon()                          */
 /************************************************************************/
@@ -808,7 +866,7 @@ OGRGeometry* OGRPolygon::getCurveGeometry(const char* const* papszOptions) const
  * @return new geometry.
  */
 
-OGRCurvePolygon* OGRPolygon::CastToCurvePolygon(OGRPolygon* poPoly)
+OGRCurvePolygon* OGRPolygon::CastToCurvePolygon( OGRPolygon* poPoly )
 {
     OGRCurvePolygon* poCP = new OGRCurvePolygon();
     poCP->set3D(poPoly->Is3D());
@@ -821,8 +879,9 @@ OGRCurvePolygon* OGRPolygon::CastToCurvePolygon(OGRPolygon* poPoly)
 
     for( int iRing = 0; iRing < poCP->oCC.nCurveCount; iRing++ )
     {
-        poCP->oCC.papoCurves[iRing] = OGRLinearRing::CastToLineString(
-                                    (OGRLinearRing*)poCP->oCC.papoCurves[iRing] );
+        poCP->oCC.papoCurves[iRing] =
+            OGRLinearRing::CastToLineString(
+                (OGRLinearRing*)poCP->oCC.papoCurves[iRing] );
     }
 
     delete poPoly;
@@ -833,7 +892,8 @@ OGRCurvePolygon* OGRPolygon::CastToCurvePolygon(OGRPolygon* poPoly)
 /*                      GetCasterToPolygon()                            */
 /************************************************************************/
 
-OGRSurfaceCasterToPolygon OGRPolygon::GetCasterToPolygon() const {
+OGRSurfaceCasterToPolygon OGRPolygon::GetCasterToPolygon() const
+{
     return (OGRSurfaceCasterToPolygon) OGRGeometry::CastToIdentity;
 }
 
@@ -841,6 +901,8 @@ OGRSurfaceCasterToPolygon OGRPolygon::GetCasterToPolygon() const {
 /*                      OGRSurfaceCasterToCurvePolygon()                */
 /************************************************************************/
 
-OGRSurfaceCasterToCurvePolygon OGRPolygon::GetCasterToCurvePolygon() const {
+OGRSurfaceCasterToCurvePolygon OGRPolygon::GetCasterToCurvePolygon() const
+{
     return (OGRSurfaceCasterToCurvePolygon) OGRPolygon::CastToCurvePolygon;
 }
+/*! @endcond */
diff --git a/ogr/ogrpolyhedralsurface.cpp b/ogr/ogrpolyhedralsurface.cpp
new file mode 100644
index 0000000..245e12d
--- /dev/null
+++ b/ogr/ogrpolyhedralsurface.cpp
@@ -0,0 +1,1076 @@
+/******************************************************************************
+ * $Id: ogrpolyhedralsurface.cpp 36963 2016-12-19 15:38:17Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  The OGRPolyhedralSurface geometry class.
+ * Author:   Avyav Kumar Singh <avyavkumar at gmail dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Avyav Kumar Singh <avyavkumar at gmail dot com>
+ * Copyright (c) 2016, Even Rouault <even.roauult at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_geometry.h"
+#include "ogr_p.h"
+#include "ogr_sfcgal.h"
+#include "ogr_api.h"
+#include "ogr_libs.h"
+
+CPL_CVSID("$Id: ogrpolyhedralsurface.cpp 36963 2016-12-19 15:38:17Z rouault $");
+
+/************************************************************************/
+/*                         OGRPolyhedralSurface()                       */
+/************************************************************************/
+
+/**
+ * \brief Create an empty PolyhedralSurface
+ */
+
+OGRPolyhedralSurface::OGRPolyhedralSurface()
+
+{ }
+
+/************************************************************************/
+/*         OGRPolyhedralSurface( const OGRPolyhedralSurface& )          */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ */
+
+OGRPolyhedralSurface::OGRPolyhedralSurface( const OGRPolyhedralSurface& other ) :
+    OGRSurface(other),
+    oMP(other.oMP)
+{ }
+
+/************************************************************************/
+/*                        ~OGRPolyhedralSurface()                       */
+/************************************************************************/
+
+/**
+ * \brief Destructor
+ *
+ */
+
+OGRPolyhedralSurface::~OGRPolyhedralSurface()
+
+{ }
+
+/************************************************************************/
+/*                 operator=( const OGRPolyhedralSurface&)              */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ */
+
+OGRPolyhedralSurface& OGRPolyhedralSurface::operator=(
+                                            const OGRPolyhedralSurface& other )
+{
+    if( this != &other)
+    {
+        OGRSurface::operator=( other );
+        oMP = other.oMP;
+    }
+    return *this;
+}
+
+/************************************************************************/
+/*                          getGeometryName()                           */
+/************************************************************************/
+
+const char* OGRPolyhedralSurface::getGeometryName() const
+{
+    return "POLYHEDRALSURFACE" ;
+}
+
+/************************************************************************/
+/*                          getGeometryType()                           */
+/************************************************************************/
+
+/**
+ * \brief Returns the WKB Type of PolyhedralSurface
+ *
+ */
+
+OGRwkbGeometryType OGRPolyhedralSurface::getGeometryType() const
+{
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbPolyhedralSurfaceZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbPolyhedralSurfaceM;
+    else if( flags & OGR_G_3D )
+        return wkbPolyhedralSurfaceZ;
+    else
+        return wkbPolyhedralSurface;
+}
+
+/************************************************************************/
+/*                              WkbSize()                               */
+/************************************************************************/
+
+int OGRPolyhedralSurface::WkbSize() const
+{
+    int nSize = 9;
+    for( int i = 0; i < oMP.nGeomCount; i++ )
+        nSize += oMP.papoGeoms[i]->WkbSize();
+    return nSize;
+}
+
+/************************************************************************/
+/*                            getDimension()                            */
+/************************************************************************/
+
+int OGRPolyhedralSurface::getDimension() const
+{
+    return 2;
+}
+
+/************************************************************************/
+/*                               empty()                                */
+/************************************************************************/
+
+void OGRPolyhedralSurface::empty()
+{
+    if( oMP.papoGeoms != NULL )
+    {
+        for( int i = 0; i < oMP.nGeomCount; i++ )
+            delete oMP.papoGeoms[i];
+        CPLFree(oMP.papoGeoms);
+    }
+    oMP.nGeomCount = 0;
+    oMP.papoGeoms = NULL;
+}
+
+/************************************************************************/
+/*                               clone()                                */
+/************************************************************************/
+
+OGRGeometry* OGRPolyhedralSurface::clone() const
+{
+    OGRPolyhedralSurface *poNewPS;
+    poNewPS = dynamic_cast<OGRPolyhedralSurface*>(
+                        OGRGeometryFactory::createGeometry(getGeometryType()));
+    if( poNewPS == NULL )
+        return NULL;
+
+    poNewPS->assignSpatialReference(getSpatialReference());
+    poNewPS->flags = flags;
+
+    for( int i = 0; i < oMP.nGeomCount; i++ )
+    {
+        if( poNewPS->oMP._addGeometryWithExpectedSubGeometryType(
+                      oMP.papoGeoms[i], getSubGeometryType()) != OGRERR_NONE )
+        {
+            delete poNewPS;
+            return NULL;
+        }
+    }
+
+    return poNewPS;
+}
+
+/************************************************************************/
+/*                            getEnvelope()                             */
+/************************************************************************/
+
+
+void OGRPolyhedralSurface::getEnvelope( OGREnvelope * psEnvelope ) const
+{
+    oMP.getEnvelope(psEnvelope);
+}
+
+/************************************************************************/
+/*                            getEnvelope()                             */
+/************************************************************************/
+
+void OGRPolyhedralSurface::getEnvelope( OGREnvelope3D * psEnvelope ) const
+{
+    oMP.getEnvelope(psEnvelope);
+}
+
+/************************************************************************/
+/*                           importFromWkb()                            */
+/************************************************************************/
+
+OGRErr OGRPolyhedralSurface::importFromWkb ( unsigned char * pabyData,
+                                             int nSize,
+                                             OGRwkbVariant eWkbVariant )
+{
+    oMP.nGeomCount = 0;
+    OGRwkbByteOrder eByteOrder = wkbXDR;
+    int nDataOffset = 0;
+    OGRErr eErr = importPreambuleOfCollectionFromWkb( pabyData,
+                                                      nSize,
+                                                      nDataOffset,
+                                                      eByteOrder,
+                                                      9,
+                                                      oMP.nGeomCount,
+                                                      eWkbVariant );
+
+    if( eErr != OGRERR_NONE )
+        return eErr;
+
+
+    oMP.papoGeoms = reinterpret_cast<OGRGeometry **>(
+                            VSI_CALLOC_VERBOSE(sizeof(void*), oMP.nGeomCount));
+    if (oMP.nGeomCount != 0 && oMP.papoGeoms == NULL)
+    {
+        oMP.nGeomCount = 0;
+        return OGRERR_NOT_ENOUGH_MEMORY;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Get the Geoms.                                                  */
+/* -------------------------------------------------------------------- */
+    for( int iGeom = 0; iGeom < oMP.nGeomCount; iGeom++ )
+    {
+        // Parse the polygons
+        unsigned char* pabySubData = pabyData + nDataOffset;
+        if( nSize < 9 && nSize != -1 )
+            return OGRERR_NOT_ENOUGH_DATA;
+
+        OGRwkbGeometryType eSubGeomType;
+        eErr = OGRReadWKBGeometryType( pabySubData, eWkbVariant, &eSubGeomType );
+        if( eErr != OGRERR_NONE )
+            return eErr;
+
+        if( !isCompatibleSubType(eSubGeomType) )
+        {
+            oMP.nGeomCount = iGeom;
+            CPLDebug("OGR", "Cannot add geometry of type (%d) to "
+                     "geometry of type (%d)",
+                     eSubGeomType, getGeometryType());
+            return OGRERR_CORRUPT_DATA;
+        }
+
+        OGRGeometry* poSubGeom = NULL;
+        eErr = OGRGeometryFactory::createFromWkb( pabySubData, NULL,
+                                                  &poSubGeom, nSize,
+                                                  eWkbVariant );
+
+        if( eErr != OGRERR_NONE )
+        {
+            oMP.nGeomCount = iGeom;
+            delete poSubGeom;
+            return eErr;
+        }
+
+        oMP.papoGeoms[iGeom] = poSubGeom;
+
+        if (oMP.papoGeoms[iGeom]->Is3D())
+            flags |= OGR_G_3D;
+        if (oMP.papoGeoms[iGeom]->IsMeasured())
+            flags |= OGR_G_MEASURED;
+
+        int nSubGeomWkbSize = oMP.papoGeoms[iGeom]->WkbSize();
+        if( nSize != -1 )
+            nSize -= nSubGeomWkbSize;
+
+        nDataOffset += nSubGeomWkbSize;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                            exportToWkb()                             */
+/************************************************************************/
+
+OGRErr  OGRPolyhedralSurface::exportToWkb ( OGRwkbByteOrder eByteOrder,
+                                            unsigned char * pabyData,
+                                            OGRwkbVariant /*eWkbVariant*/ ) const
+
+{
+/* -------------------------------------------------------------------- */
+/*      Set the byte order.                                             */
+/* -------------------------------------------------------------------- */
+    pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
+
+/* -------------------------------------------------------------------- */
+/*      Set the geometry feature type, ensuring that 3D flag is         */
+/*      preserved.                                                      */
+/* -------------------------------------------------------------------- */
+    GUInt32 nGType = getIsoGeometryType();
+
+    if( OGR_SWAP( eByteOrder ) )
+    {
+        nGType = CPL_SWAP32(nGType);
+    }
+
+    memcpy( pabyData + 1, &nGType, 4 );
+
+    // Copy the raw data
+    if( OGR_SWAP( eByteOrder ) )
+    {
+        int nCount = CPL_SWAP32( oMP.nGeomCount );
+        memcpy( pabyData+5, &nCount, 4 );
+    }
+    else
+        memcpy( pabyData+5, &oMP.nGeomCount, 4 );
+
+    int nOffset = 9;
+
+    // serialize each of the geometries
+    for( int iGeom = 0; iGeom < oMP.nGeomCount; iGeom++ )
+    {
+        oMP.papoGeoms[iGeom]->exportToWkb( eByteOrder, pabyData + nOffset,
+                                           wkbVariantIso );
+        nOffset += oMP.papoGeoms[iGeom]->WkbSize();
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           importFromWkt()                            */
+/*              Instantiate from well known text format.                */
+/************************************************************************/
+
+OGRErr OGRPolyhedralSurface::importFromWkt( char ** ppszInput )
+{
+    int bHasZ = FALSE, bHasM = FALSE;
+    bool bIsEmpty = false;
+    OGRErr      eErr = importPreambuleFromWkt(
+                                        ppszInput, &bHasZ, &bHasM, &bIsEmpty);
+    flags = 0;
+    if( eErr != OGRERR_NONE )
+        return eErr;
+    if( bHasZ ) flags |= OGR_G_3D;
+    if( bHasM ) flags |= OGR_G_MEASURED;
+    if( bIsEmpty )
+        return OGRERR_NONE;
+
+    char        szToken[OGR_WKT_TOKEN_MAX];
+    const char  *pszInput = *ppszInput;
+    eErr = OGRERR_NONE;
+
+    /* Skip first '(' */
+    pszInput = OGRWktReadToken( pszInput, szToken );
+
+/* ==================================================================== */
+/*      Read each surface in turn.  Note that we try to reuse the same  */
+/*      point list buffer from ring to ring to cut down on              */
+/*      allocate/deallocate overhead.                                   */
+/* ==================================================================== */
+    OGRRawPoint *paoPoints = NULL;
+    int          nMaxPoints = 0;
+    double      *padfZ = NULL;
+
+    do
+    {
+
+    /* -------------------------------------------------------------------- */
+    /*      Get the first token, which should be the geometry type.         */
+    /* -------------------------------------------------------------------- */
+        const char* pszInputBefore = pszInput;
+        pszInput = OGRWktReadToken( pszInput, szToken );
+
+        OGRSurface* poSurface;
+
+    /* -------------------------------------------------------------------- */
+    /*      Do the import.                                                  */
+    /* -------------------------------------------------------------------- */
+        if (EQUAL(szToken,"("))
+        {
+            OGRPolygon *poPolygon = reinterpret_cast<OGRPolygon*>(
+                  OGRGeometryFactory::createGeometry( getSubGeometryType() ));
+            poSurface = poPolygon;
+            pszInput = pszInputBefore;
+            eErr = poPolygon->importFromWKTListOnly(
+                            (char**)&pszInput, bHasZ, bHasM,
+                            paoPoints, nMaxPoints, padfZ );
+        }
+        else if (EQUAL(szToken, "EMPTY") )
+        {
+            poSurface = reinterpret_cast<OGRSurface*>(
+                  OGRGeometryFactory::createGeometry( getSubGeometryType() ));
+        }
+
+        /* We accept POLYGON() but this is an extension to the BNF, also */
+        /* accepted by PostGIS */
+        else if (EQUAL(szToken,getSubGeometryName()))
+        {
+            OGRGeometry* poGeom = NULL;
+            pszInput = pszInputBefore;
+            eErr = OGRGeometryFactory::createFromWkt(
+                    const_cast<char **>(&pszInput), NULL, &poGeom );
+            poSurface = reinterpret_cast<OGRSurface*>(poGeom);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unexpected token : %s", szToken);
+            eErr = OGRERR_CORRUPT_DATA;
+            break;
+        }
+
+        if( eErr == OGRERR_NONE )
+            eErr = oMP._addGeometryDirectlyWithExpectedSubGeometryType(
+                                                      poSurface,
+                                                      getSubGeometryType() );
+        if( eErr != OGRERR_NONE )
+        {
+            delete poSurface;
+            break;
+        }
+
+        // Read the delimiter following the surface.
+        pszInput = OGRWktReadToken( pszInput, szToken );
+
+    } while( szToken[0] == ',' && eErr == OGRERR_NONE );
+
+    CPLFree( paoPoints );
+    CPLFree( padfZ );
+
+    // Check for a closing bracket
+    if( eErr != OGRERR_NONE )
+        return eErr;
+
+    if( szToken[0] != ')' )
+        return OGRERR_CORRUPT_DATA;
+
+    *ppszInput = (char *) pszInput;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                            exportToWkt()                             */
+/************************************************************************/
+
+
+OGRErr OGRPolyhedralSurface::exportToWkt ( char ** ppszDstText,
+                                           OGRwkbVariant ) const
+{
+    return exportToWktInternal(ppszDstText, wkbVariantIso, getSubGeometryName());
+}
+
+//! @cond Doxygen_Suppress
+OGRErr OGRPolyhedralSurface::exportToWktInternal ( char ** ppszDstText,
+                                                   OGRwkbVariant eWkbVariant,
+                                                   const char* pszSkipPrefix ) const
+{
+    char        **papszGeoms;
+    int         iGeom;
+    size_t      nCumulativeLength = 0;
+    OGRErr      eErr;
+    bool bMustWriteComma = false;
+
+/* -------------------------------------------------------------------- */
+/*      Build a list of strings containing the stuff for each Geom.     */
+/* -------------------------------------------------------------------- */
+    papszGeoms = (oMP.nGeomCount) ? (char **) CPLCalloc(sizeof(char *),
+                                                        oMP.nGeomCount) : NULL;
+
+    for( iGeom = 0; iGeom < oMP.nGeomCount; iGeom++ )
+    {
+        eErr = oMP.papoGeoms[iGeom]->exportToWkt( &(papszGeoms[iGeom]),
+                                                  eWkbVariant );
+        if( eErr != OGRERR_NONE )
+            goto error;
+
+        size_t nSkip = 0;
+        if( pszSkipPrefix != NULL &&
+            EQUALN(papszGeoms[iGeom], pszSkipPrefix, strlen(pszSkipPrefix)) &&
+            papszGeoms[iGeom][strlen(pszSkipPrefix)] == ' ' )
+        {
+            nSkip = strlen(pszSkipPrefix) + 1;
+            if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "ZM ") )
+                nSkip += 3;
+            else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "M ") )
+                nSkip += 2;
+            if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "Z ") )
+                nSkip += 2;
+
+            /* skip empty subgeoms */
+            if( papszGeoms[iGeom][nSkip] != '(' )
+            {
+                CPLDebug( "OGR", "OGR%s::exportToWkt() - skipping %s.",
+                          getGeometryName(), papszGeoms[iGeom] );
+                CPLFree( papszGeoms[iGeom] );
+                papszGeoms[iGeom] = NULL;
+                continue;
+            }
+        }
+        else if( eWkbVariant != wkbVariantIso )
+        {
+            char *substr;
+            if( (substr = strstr(papszGeoms[iGeom], " Z")) != NULL )
+                memmove(substr, substr+strlen(" Z"),
+                        1 + strlen(substr+strlen(" Z")));
+        }
+
+        nCumulativeLength += strlen(papszGeoms[iGeom] + nSkip);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Return XXXXXXXXXXXXXXX EMPTY if we get no valid line string.    */
+/* -------------------------------------------------------------------- */
+    if( nCumulativeLength == 0 )
+    {
+        CPLFree( papszGeoms );
+        CPLString osEmpty;
+        if( eWkbVariant == wkbVariantIso )
+        {
+            if( Is3D() && IsMeasured() )
+                osEmpty.Printf("%s ZM EMPTY",getGeometryName());
+            else if( IsMeasured() )
+                osEmpty.Printf("%s M EMPTY",getGeometryName());
+            else if( Is3D() )
+                osEmpty.Printf("%s Z EMPTY",getGeometryName());
+            else
+                osEmpty.Printf("%s EMPTY",getGeometryName());
+        }
+        else
+            osEmpty.Printf("%s EMPTY",getGeometryName());
+        *ppszDstText = CPLStrdup(osEmpty);
+        return OGRERR_NONE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Allocate the right amount of space for the aggregated string    */
+/* -------------------------------------------------------------------- */
+    *ppszDstText = (char *) VSI_MALLOC_VERBOSE(
+                                   nCumulativeLength + oMP.nGeomCount + 26);
+
+    if( *ppszDstText == NULL )
+    {
+        eErr = OGRERR_NOT_ENOUGH_MEMORY;
+        goto error;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Build up the string, freeing temporary strings as we go.        */
+/* -------------------------------------------------------------------- */
+    strcpy( *ppszDstText, getGeometryName() );
+    if( eWkbVariant == wkbVariantIso )
+    {
+        if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+            strcat( *ppszDstText, " ZM" );
+        else if( flags & OGR_G_3D )
+            strcat( *ppszDstText, " Z" );
+        else if( flags & OGR_G_MEASURED )
+            strcat( *ppszDstText, " M" );
+    }
+    strcat( *ppszDstText, " (" );
+    nCumulativeLength = strlen(*ppszDstText);
+
+    for( iGeom = 0; iGeom < oMP.nGeomCount; iGeom++ )
+    {
+        if( papszGeoms[iGeom] == NULL )
+            continue;
+
+        if( bMustWriteComma )
+            (*ppszDstText)[nCumulativeLength++] = ',';
+        bMustWriteComma = true;
+
+        size_t nSkip = 0;
+        if( pszSkipPrefix != NULL &&
+            EQUALN(papszGeoms[iGeom], pszSkipPrefix, strlen(pszSkipPrefix)) &&
+            papszGeoms[iGeom][strlen(pszSkipPrefix)] == ' ' )
+        {
+            nSkip = strlen(pszSkipPrefix) + 1;
+            if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "ZM ") )
+                nSkip += 3;
+            else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "M ") )
+                nSkip += 2;
+            else if( STARTS_WITH_CI(papszGeoms[iGeom] + nSkip, "Z ") )
+                nSkip += 2;
+        }
+
+        size_t nGeomLength = strlen(papszGeoms[iGeom] + nSkip);
+        memcpy( *ppszDstText + nCumulativeLength, papszGeoms[iGeom] + nSkip,
+                nGeomLength );
+        nCumulativeLength += nGeomLength;
+        VSIFree( papszGeoms[iGeom] );
+    }
+
+    (*ppszDstText)[nCumulativeLength++] = ')';
+    (*ppszDstText)[nCumulativeLength] = '\0';
+
+    CPLFree( papszGeoms );
+
+    return OGRERR_NONE;
+
+error:
+    for( iGeom = 0; iGeom < oMP.nGeomCount; iGeom++ )
+        CPLFree( papszGeoms[iGeom] );
+    CPLFree( papszGeoms );
+    return eErr;
+}
+//! @endcond
+
+/************************************************************************/
+/*                            flattenTo2D()                             */
+/************************************************************************/
+
+void OGRPolyhedralSurface::flattenTo2D()
+{
+    oMP.flattenTo2D();
+
+    flags &= ~OGR_G_3D;
+    flags &= ~OGR_G_MEASURED;
+}
+
+/************************************************************************/
+/*                             transform()                              */
+/************************************************************************/
+
+OGRErr OGRPolyhedralSurface::transform( OGRCoordinateTransformation *poCT )
+{
+    return oMP.transform(poCT);
+}
+
+/************************************************************************/
+/*                      GetCasterToPolygon()                            */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRSurfaceCasterToPolygon OGRPolyhedralSurface::GetCasterToPolygon() const
+{
+    return (OGRSurfaceCasterToPolygon) OGRGeometry::CastToError;
+}
+//! @endcond
+
+/************************************************************************/
+/*                      OGRSurfaceCasterToCurvePolygon()                */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRSurfaceCasterToCurvePolygon OGRPolyhedralSurface::GetCasterToCurvePolygon() const
+{
+    return (OGRSurfaceCasterToCurvePolygon) OGRGeometry::CastToError;
+}
+//! @endcond
+
+
+/************************************************************************/
+/*                         isCompatibleSubType()                        */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRBoolean OGRPolyhedralSurface::isCompatibleSubType( OGRwkbGeometryType eSubType ) const
+{
+    return wkbFlatten( eSubType ) == wkbPolygon;
+}
+//! @endcond
+
+/************************************************************************/
+/*                         getSubGeometryName()                         */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+const char* OGRPolyhedralSurface::getSubGeometryName() const
+{
+    return "POLYGON";
+}
+//! @endcond
+
+/************************************************************************/
+/*                         getSubGeometryType()                         */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRwkbGeometryType OGRPolyhedralSurface::getSubGeometryType() const
+{
+    return wkbPolygon;
+}
+//! @endcond
+
+/************************************************************************/
+/*                               Equals()                               */
+/************************************************************************/
+
+OGRBoolean OGRPolyhedralSurface::Equals(OGRGeometry * poOther) const
+{
+
+    if( poOther == this )
+        return TRUE;
+
+    if( poOther->getGeometryType() != getGeometryType() )
+        return FALSE;
+
+    if ( IsEmpty() && poOther->IsEmpty() )
+        return TRUE;
+
+    OGRPolyhedralSurface *poOMP = (OGRPolyhedralSurface *) poOther;
+    if( oMP.getNumGeometries() != poOMP->oMP.getNumGeometries() )
+        return FALSE;
+
+    for( int iGeom = 0; iGeom < oMP.nGeomCount; iGeom++ )
+    {
+        if( !oMP.getGeometryRef(iGeom)->Equals(poOMP->oMP.getGeometryRef(iGeom)) )
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                              get_Area()                              */
+/************************************************************************/
+
+/**
+ * \brief Returns the area enclosed
+ *
+ * This method is built on the SFCGAL library, check it for the definition
+ * of the geometry operation.
+ * If OGR is built without the SFCGAL library, this method will always return
+ * -1.0
+ *
+ * @return area enclosed by the PolyhedralSurface
+ */
+
+double OGRPolyhedralSurface::get_Area() const
+{
+#ifndef HAVE_SFCGAL
+
+    CPLError( CE_Failure, CPLE_NotSupported, "SFCGAL support not enabled." );
+    return -1.0;
+
+#else
+
+    sfcgal_init();
+    sfcgal_geometry_t *poThis = OGRGeometry::OGRexportToSFCGAL((OGRGeometry *)this);
+    if (poThis == NULL)
+        return -1.0;
+
+    double area = sfcgal_geometry_area_3d(poThis);
+
+    sfcgal_geometry_delete(poThis);
+
+    return (area > 0)? area: -1.0;
+
+#endif
+}
+
+/************************************************************************/
+/*                           PointOnSurface()                           */
+/************************************************************************/
+
+OGRErr OGRPolyhedralSurface::PointOnSurface(OGRPoint *poPoint) const
+{
+    return PointOnSurfaceInternal(poPoint);
+}
+
+/************************************************************************/
+/*                     GetCasterToMultiPolygon()                        */
+/************************************************************************/
+//! @cond Doxygen_Suppress
+OGRPolyhedralSurfaceCastToMultiPolygon
+                            OGRPolyhedralSurface::GetCasterToMultiPolygon() const
+{
+    return OGRPolyhedralSurface::CastToMultiPolygonImpl;
+}
+
+/************************************************************************/
+/*                      CastToMultiPolygonImpl()                        */
+/************************************************************************/
+
+OGRMultiPolygon* OGRPolyhedralSurface::CastToMultiPolygonImpl(
+                                                    OGRPolyhedralSurface* poPS)
+{
+    OGRMultiPolygon *poMultiPolygon = new OGRMultiPolygon(poPS->oMP);
+    poMultiPolygon->assignSpatialReference(poPS->getSpatialReference());
+    delete poPS;
+    return poMultiPolygon;
+}
+//! @endcond
+
+/************************************************************************/
+/*                         CastToMultiPolygon()                         */
+/************************************************************************/
+
+/**
+ * \brief Casts the OGRPolyhedralSurface to an OGRMultiPolygon
+ *
+ * The passed in geometry is consumed and a new one returned (or NULL in case
+ * of failure)
+ *
+ * @param poPS the input geometry - ownership is passed to the method.
+ * @return new geometry.
+ */
+
+
+OGRMultiPolygon* OGRPolyhedralSurface::CastToMultiPolygon(
+                                                    OGRPolyhedralSurface* poPS)
+{
+    OGRPolyhedralSurfaceCastToMultiPolygon pfn =
+                                            poPS->GetCasterToMultiPolygon();
+    return pfn(poPS);
+}
+
+
+/************************************************************************/
+/*                            addGeometry()                             */
+/************************************************************************/
+
+/**
+ * \brief Add a new geometry to a collection.
+ *
+ * Only a POLYGON can be added to a POLYHEDRALSURFACE.
+ *
+ * @return OGRErr OGRERR_NONE if the polygon is successfully added
+ */
+
+OGRErr OGRPolyhedralSurface::addGeometry (const OGRGeometry *poNewGeom)
+{
+    if (!isCompatibleSubType(poNewGeom->getGeometryType()))
+        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+
+    OGRGeometry *poClone = poNewGeom->clone();
+    OGRErr      eErr;
+
+    if (poClone == NULL)
+        return OGRERR_FAILURE;
+
+    eErr = addGeometryDirectly(poClone);
+
+    if( eErr != OGRERR_NONE )
+        delete poClone;
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                        addGeometryDirectly()                         */
+/************************************************************************/
+
+/**
+ * \brief Add a geometry directly to the container.
+ *
+ * This method is the same as the C function OGR_G_AddGeometryDirectly().
+ *
+ * There is no SFCOM analog to this method.
+ *
+ * @param poNewGeom geometry to add to the container.
+ *
+ * @return OGRERR_NONE if successful, or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if
+ * the geometry type is illegal for the type of geometry container.
+ */
+
+OGRErr OGRPolyhedralSurface::addGeometryDirectly (OGRGeometry *poNewGeom)
+{
+    if (!isCompatibleSubType(poNewGeom->getGeometryType()))
+    {
+        return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+    }
+
+    if( poNewGeom->Is3D() && !Is3D() )
+        set3D(TRUE);
+
+    if( poNewGeom->IsMeasured() && !IsMeasured() )
+        setMeasured(TRUE);
+
+    if( !poNewGeom->Is3D() && Is3D() )
+        poNewGeom->set3D(TRUE);
+
+    if( !poNewGeom->IsMeasured() && IsMeasured() )
+        poNewGeom->setMeasured(TRUE);
+
+    OGRGeometry** papoNewGeoms = (OGRGeometry **) VSI_REALLOC_VERBOSE(
+                                        oMP.papoGeoms,
+                                        sizeof(void*) * (oMP.nGeomCount+1) );
+    if( papoNewGeoms == NULL )
+        return OGRERR_FAILURE;
+
+    oMP.papoGeoms = papoNewGeoms;
+    oMP.papoGeoms[oMP.nGeomCount] = poNewGeom;
+    oMP.nGeomCount++;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          getNumGeometries()                          */
+/************************************************************************/
+
+/**
+ * \brief Fetch number of geometries in PolyhedralSurface
+ *
+ * @return count of children geometries.  May be zero.
+ */
+
+int OGRPolyhedralSurface::getNumGeometries() const
+{
+    return oMP.nGeomCount;
+}
+
+/************************************************************************/
+/*                         getGeometryRef()                             */
+/************************************************************************/
+
+/**
+ * \brief Fetch geometry from container.
+ *
+ * This method returns a pointer to an geometry within the container.  The
+ * returned geometry remains owned by the container, and should not be
+ * modified.  The pointer is only valid until the next change to the
+ * geometry container.  Use IGeometry::clone() to make a copy.
+ *
+ * @param i the index of the geometry to fetch, between 0 and
+ *          getNumGeometries() - 1.
+ * @return pointer to requested geometry.
+ */
+
+OGRGeometry* OGRPolyhedralSurface::getGeometryRef(int i)
+{
+    return oMP.papoGeoms[i];
+}
+
+/************************************************************************/
+/*                         getGeometryRef()                             */
+/************************************************************************/
+
+/**
+ * \brief Fetch geometry from container.
+ *
+ * This method returns a pointer to an geometry within the container.  The
+ * returned geometry remains owned by the container, and should not be
+ * modified.  The pointer is only valid until the next change to the
+ * geometry container.  Use IGeometry::clone() to make a copy.
+ *
+ * @param i the index of the geometry to fetch, between 0 and
+ *          getNumGeometries() - 1.
+ * @return pointer to requested geometry.
+ */
+
+const OGRGeometry* OGRPolyhedralSurface::getGeometryRef(int i) const
+{
+    return oMP.papoGeoms[i];
+}
+
+/************************************************************************/
+/*                               IsEmpty()                              */
+/************************************************************************/
+
+/**
+ * \brief Checks if the PolyhedralSurface is empty
+ *
+ * @return TRUE if the PolyhedralSurface is empty, FALSE otherwise
+ */
+
+OGRBoolean  OGRPolyhedralSurface::IsEmpty() const
+{
+    return oMP.IsEmpty();
+}
+
+/************************************************************************/
+/*                                 set3D()                              */
+/************************************************************************/
+
+/**
+ * \brief Set the type as 3D geometry
+ */
+
+void OGRPolyhedralSurface::set3D (OGRBoolean bIs3D)
+{
+    oMP.set3D(bIs3D);
+
+    OGRGeometry::set3D( bIs3D );
+}
+
+/************************************************************************/
+/*                             setMeasured()                            */
+/************************************************************************/
+
+/**
+ * \brief Set the type as Measured
+ */
+
+void OGRPolyhedralSurface::setMeasured (OGRBoolean bIsMeasured)
+{
+    oMP.setMeasured(bIsMeasured);
+
+    OGRGeometry::setMeasured( bIsMeasured );
+}
+
+/************************************************************************/
+/*                       setCoordinateDimension()                       */
+/************************************************************************/
+
+/**
+ * \brief Set the coordinate dimension.
+ *
+ * This method sets the explicit coordinate dimension.  Setting the coordinate
+ * dimension of a geometry to 2 should zero out any existing Z values.
+ * This will also remove the M dimension if present before this call.
+ *
+ * @param nNewDimension New coordinate dimension value, either 2 or 3.
+ */
+
+void OGRPolyhedralSurface::setCoordinateDimension (int nNewDimension)
+{
+    oMP.setCoordinateDimension(nNewDimension);
+
+    OGRGeometry::setCoordinateDimension( nNewDimension );
+}
+
+/************************************************************************/
+/*                               swapXY()                               */
+/************************************************************************/
+
+/**
+ * \brief Swap x and y coordinates.
+ */
+
+void OGRPolyhedralSurface::swapXY()
+{
+    oMP.swapXY();
+}
+
+/************************************************************************/
+/*                         hasCurveGeometry()                           */
+/************************************************************************/
+
+
+OGRBoolean OGRPolyhedralSurface::hasCurveGeometry(int) const
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          removeGeometry()                            */
+/************************************************************************/
+
+/**
+ * \brief Remove a geometry from the container.
+ *
+ * Removing a geometry will cause the geometry count to drop by one, and all
+ * "higher" geometries will shuffle down one in index.
+ *
+ * @param iGeom the index of the geometry to delete.  A value of -1 is a
+ * special flag meaning that all geometries should be removed.
+ *
+ * @param bDelete if TRUE the geometry will be deallocated, otherwise it will
+ * not.  The default is TRUE as the container is considered to own the
+ * geometries in it.
+ *
+ * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
+ * out of range.
+ */
+
+OGRErr OGRPolyhedralSurface::removeGeometry(int iGeom, int bDelete)
+{
+    return oMP.removeGeometry(iGeom,bDelete);
+}
diff --git a/ogr/ogrsf_frmts/GNUmakefile b/ogr/ogrsf_frmts/GNUmakefile
index de61e6e..bae92d8 100644
--- a/ogr/ogrsf_frmts/GNUmakefile
+++ b/ogr/ogrsf_frmts/GNUmakefile
@@ -9,11 +9,13 @@ SUBDIRS-yes	:= \
 	arcgen segukooa segy sxf openfilegdb wasp selafin jml vdv
 
 SUBDIRS-$(HAVE_DODS)	+= dods
-SUBDIRS-$(HAVE_DWGDIRECT) += dxfdwg
+SUBDIRS-$(HAVE_TEIGHA)  += dwg
+SUBDIRS-$(HAVE_CAD)	+= cad
 SUBDIRS-$(HAVE_FME)	+= fme
 SUBDIRS-$(HAVE_GRASS)	+= grass
 SUBDIRS-$(HAVE_IDB)	+= idb
 SUBDIRS-$(HAVE_XERCES)	+= ili
+SUBDIRS-$(HAVE_XERCES)	+= gmlas
 SUBDIRS-$(HAVE_NAS)	+= nas
 SUBDIRS-$(HAVE_MYSQL)	+= mysql
 SUBDIRS-$(ODBC_SETTING)	+= odbc pgeo mssqlspatial geomedia walk
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h b/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h
index 1183aa1..c688cca 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h
+++ b/ogr/ogrsf_frmts/aeronavfaa/ogr_aeronavfaa.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_aeronavfaa.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogr_aeronavfaa.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Definition of classes for OGR AeronavFAA driver.
@@ -32,7 +32,6 @@
 
 #include "ogrsf_frmts.h"
 
-
 typedef struct
 {
     const char* pszFieldName;
@@ -49,8 +48,6 @@ typedef struct
     int              nLonStartCol; /* starting at 1 */
 } RecordDesc;
 
-
-
 /************************************************************************/
 /*                         OGRAeronavFAALayer                           */
 /************************************************************************/
@@ -62,7 +59,7 @@ protected:
     OGRSpatialReference *poSRS;
 
     VSILFILE*          fpAeronavFAA;
-    int                bEOF;
+    bool               bEOF;
 
     int                nNextFID;
 
@@ -72,15 +69,14 @@ protected:
 
   public:
                         OGRAeronavFAALayer(VSILFILE* fp, const char* pszLayerName);
-                        ~OGRAeronavFAALayer();
+                        virtual ~OGRAeronavFAALayer();
 
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -90,10 +86,10 @@ protected:
 class OGRAeronavFAADOFLayer : public OGRAeronavFAALayer
 {
   private:
-    int GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon);
+    static int GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon);
 
   protected:
-    virtual OGRFeature *       GetNextRawFeature();
+    virtual OGRFeature *       GetNextRawFeature() override;
 
   public:
                         OGRAeronavFAADOFLayer(VSILFILE* fp, const char* pszLayerName);
@@ -106,10 +102,10 @@ class OGRAeronavFAADOFLayer : public OGRAeronavFAALayer
 class OGRAeronavFAANAVAIDLayer : public OGRAeronavFAALayer
 {
   private:
-    int GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon);
+    static int GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon);
 
   protected:
-    virtual OGRFeature *       GetNextRawFeature();
+    virtual OGRFeature *       GetNextRawFeature() override;
 
   public:
                         OGRAeronavFAANAVAIDLayer(VSILFILE* fp, const char* pszLayerName);
@@ -126,15 +122,15 @@ class OGRAeronavFAARouteLayer : public OGRAeronavFAALayer
     CPLString osLastReadLine;
     CPLString osAPTName;
     CPLString osStateName;
-    int GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon);
+    static int GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon);
 
   protected:
-    virtual OGRFeature *       GetNextRawFeature();
+    virtual OGRFeature *       GetNextRawFeature() override;
 
   public:
                         OGRAeronavFAARouteLayer(VSILFILE* fp, const char* pszLayerName, int bIsDPOrSTARS);
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 };
 
 /************************************************************************/
@@ -148,15 +144,15 @@ class OGRAeronavFAAIAPLayer : public OGRAeronavFAALayer
     CPLString osStateName;
     CPLString osAPTName;
     CPLString osAPTId;
-    int GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon);
+    static int GetLatLon(const char* pszLat, const char* pszLon, double& dfLat, double& dfLon);
 
   protected:
-    virtual OGRFeature *       GetNextRawFeature();
+    virtual OGRFeature *       GetNextRawFeature() override;
 
   public:
                         OGRAeronavFAAIAPLayer(VSILFILE* fp, const char* pszLayerName);
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 };
 
 /************************************************************************/
@@ -172,17 +168,16 @@ class OGRAeronavFAADataSource : public OGRDataSource
 
   public:
                         OGRAeronavFAADataSource();
-                        ~OGRAeronavFAADataSource();
+                        virtual ~OGRAeronavFAADataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
-
 #endif /* ndef OGR_AeronavFAA_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
index d6ade08..14bd828 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ograeronavfaadatasource.cpp 32247 2015-12-19 07:05:52Z goatbar $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAADataSource class
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ograeronavfaadatasource.cpp 32247 2015-12-19 07:05:52Z goatbar $");
+CPL_CVSID("$Id: ograeronavfaadatasource.cpp 35686 2016-10-10 23:47:00Z goatbar $");
 
 /************************************************************************/
 /*                      OGRAeronavFAADataSource()                       */
@@ -97,39 +96,52 @@ int OGRAeronavFAADataSource::Open( const char * pszFilename )
         return FALSE;
 
     char szBuffer[10000];
-    int nbRead = (int)VSIFReadL(szBuffer, 1, sizeof(szBuffer) - 1, fp);
+    const int nbRead = static_cast<int>(
+        VSIFReadL(szBuffer, 1, sizeof(szBuffer) - 1, fp));
     szBuffer[nbRead] = '\0';
 
-    int bIsDOF = (szBuffer[128] == 13 && szBuffer[128+1] == 10 &&
-                  szBuffer[130+128] == 13 && szBuffer[130+129] == 10 &&
-                  szBuffer[2*130+128] == 13 && szBuffer[2*130+129] == 10 &&
-                  STARTS_WITH(szBuffer + 3 * 130, "------------------------------------------------------------------------------------------------------------------------- "));
-
-    int bIsNAVAID = (szBuffer[132] == 13 && szBuffer[132+1] == 10 &&
-                     STARTS_WITH(szBuffer + 20 - 1, "CREATION DATE") &&
-                     szBuffer[134 + 132] == 13 && szBuffer[134 + 132+1] == 10);
-
-    int bIsROUTE = STARTS_WITH(szBuffer, "           UNITED STATES GOVERNMENT FLIGHT INFORMATION PUBLICATION             149343") &&
-                   szBuffer[85] == 13 && szBuffer[85+1] == 10;
-
-    int bIsIAP = strstr(szBuffer, "INSTRUMENT APPROACH PROCEDURE NAVAID & FIX DATA") != NULL &&
-                   szBuffer[85] == 13 && szBuffer[85+1] == 10;
-    if (bIsIAP)
-        bIsROUTE = FALSE;
-
-    if (bIsDOF)
+    const bool bIsDOF =
+        szBuffer[128] == 13 && szBuffer[128+1] == 10 &&
+        szBuffer[130+128] == 13 && szBuffer[130+129] == 10 &&
+        szBuffer[2*130+128] == 13 && szBuffer[2*130+129] == 10 &&
+        STARTS_WITH(
+            szBuffer + 3 * 130,
+            "-----------------------------------------------------------------"
+            "-------------------------------------------------------- ");
+
+    const bool bIsNAVAID =
+        szBuffer[132] == 13 && szBuffer[132+1] == 10 &&
+        STARTS_WITH(szBuffer + 20 - 1, "CREATION DATE") &&
+        szBuffer[134 + 132] == 13 && szBuffer[134 + 132+1] == 10;
+
+    const bool bIsIAP =
+        strstr(szBuffer,
+               "INSTRUMENT APPROACH PROCEDURE NAVAID & FIX DATA") != NULL &&
+        szBuffer[85] == 13 && szBuffer[85+1] == 10;
+
+    bool bIsROUTE = STARTS_WITH(
+        szBuffer,
+        "           UNITED STATES GOVERNMENT FLIGHT INFORMATION PUBLICATION"
+        "             149343") &&
+        szBuffer[85] == 13 && szBuffer[85+1] == 10;
+
+    // TODO(schwehr): Fold into bool bIsROUTE so it can be const.
+    if( bIsIAP )
+        bIsROUTE = false;
+
+    if( bIsDOF )
     {
         VSIFSeekL( fp, 0, SEEK_SET );
         nLayers = 1;
-        papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
+        papoLayers = static_cast<OGRLayer **>(CPLMalloc(sizeof(OGRLayer*)));
         papoLayers[0] = new OGRAeronavFAADOFLayer(fp, CPLGetBasename(pszFilename));
         return TRUE;
     }
-    else if (bIsNAVAID)
+    else if( bIsNAVAID )
     {
         VSIFSeekL( fp, 0, SEEK_SET );
         nLayers = 1;
-        papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
+        papoLayers = static_cast<OGRLayer **>(CPLMalloc(sizeof(OGRLayer*)));
         papoLayers[0] = new OGRAeronavFAANAVAIDLayer(fp, CPLGetBasename(pszFilename));
         return TRUE;
     }
@@ -137,17 +149,18 @@ int OGRAeronavFAADataSource::Open( const char * pszFilename )
     {
         VSIFSeekL( fp, 0, SEEK_SET );
         nLayers = 1;
-        papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
+        papoLayers = static_cast<OGRLayer **>(CPLMalloc(sizeof(OGRLayer*)));
         papoLayers[0] = new OGRAeronavFAAIAPLayer(fp, CPLGetBasename(pszFilename));
         return TRUE;
     }
     else if (bIsROUTE)
     {
-        int bIsDPOrSTARS = strstr(szBuffer, "DPs - DEPARTURE PROCEDURES") != NULL ||
-                           strstr(szBuffer, "STARS - STANDARD TERMINAL ARRIVALS") != NULL;
+        const bool bIsDPOrSTARS =
+            strstr(szBuffer, "DPs - DEPARTURE PROCEDURES") != NULL ||
+            strstr(szBuffer, "STARS - STANDARD TERMINAL ARRIVALS") != NULL;
         VSIFSeekL( fp, 0, SEEK_SET );
         nLayers = 1;
-        papoLayers = (OGRLayer**) CPLMalloc(sizeof(OGRLayer*));
+        papoLayers = static_cast<OGRLayer **>(CPLMalloc(sizeof(OGRLayer*)));
         papoLayers[0] = new OGRAeronavFAARouteLayer(fp, CPLGetBasename(pszFilename), bIsDPOrSTARS);
         return TRUE;
     }
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp
index 54c9123..3fe1d36 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaadriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ograeronavfaadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAADriver.
@@ -30,13 +29,12 @@
 #include "ogr_aeronavfaa.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ograeronavfaadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ograeronavfaadriver.cpp 35903 2016-10-24 12:09:43Z goatbar $");
 
 // g++ ogr/ogrsf_frmts/aeronavfaa/*.cpp -Wall -g -fPIC -shared -o ogr_AeronavFAA.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts/aernovfaa -Iogr/ogrsf_frmts
 
 extern "C" void RegisterOGRAeronavFAA();
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -84,4 +82,3 @@ void RegisterOGRAeronavFAA()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp
index e411c9c..1120573 100644
--- a/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp
+++ b/ogr/ogrsf_frmts/aeronavfaa/ograeronavfaalayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ograeronavfaalayer.cpp 32381 2015-12-20 21:37:32Z goatbar $
  *
  * Project:  AeronavFAA Translator
  * Purpose:  Implements OGRAeronavFAALayer class.
@@ -33,7 +32,9 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ograeronavfaalayer.cpp 32381 2015-12-20 21:37:32Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ograeronavfaalayer.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /************************************************************************/
 /*                        OGRAeronavFAALayer()                          */
@@ -44,7 +45,7 @@ OGRAeronavFAALayer::OGRAeronavFAALayer( VSILFILE* fp,
     poFeatureDefn(new OGRFeatureDefn(pszLayerName)),
     poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
     fpAeronavFAA(fp),
-    bEOF(FALSE),
+    bEOF(false),
     nNextFID(0),
     psRecordDesc(NULL)
 {
@@ -68,7 +69,6 @@ OGRAeronavFAALayer::~OGRAeronavFAALayer()
     VSIFCloseL( fpAeronavFAA );
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -77,25 +77,22 @@ void OGRAeronavFAALayer::ResetReading()
 
 {
     nNextFID = 0;
-    bEOF = FALSE;
+    bEOF = false;
     VSIFSeekL( fpAeronavFAA, 0, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
 OGRFeature *OGRAeronavFAALayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
     while( true )
     {
-        if (bEOF)
+        if( bEOF )
             return NULL;
 
-        poFeature = GetNextRawFeature();
+        OGRFeature  *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -120,8 +117,6 @@ int OGRAeronavFAALayer::TestCapability( CPL_UNUSED const char * pszCap )
     return FALSE;
 }
 
-
-
 static const RecordFieldDesc DOFFields [] =
 {
     { "ORS_CODE",  1, 2, OFTString },
@@ -145,7 +140,6 @@ static const RecordFieldDesc DOFFields [] =
 
 static const RecordDesc DOF = { sizeof(DOFFields)/sizeof(DOFFields[0]), DOFFields, 36, 49 };
 
-
 /************************************************************************/
 /*                       OGRAeronavFAADOFLayer()                        */
 /************************************************************************/
@@ -179,15 +173,11 @@ static int GetLatLon(const char* pszLat,
                      int         nSecLen,
                      double& dfLat, double& dfLon)
 {
-    char szDeg[4], szMin[3], szSec[10];
-    szDeg[0] = pszLat[0];
-    szDeg[1] = pszLat[1];
-    szDeg[2] = 0;
-    szMin[0] = pszLat[3];
-    szMin[1] = pszLat[4];
-    szMin[2] = 0;
-    memcpy(szSec, pszLat + 6, MAX((int)sizeof(szSec) - 1, nSecLen));
-    szSec[MAX((int)sizeof(szSec) - 1, nSecLen)] = 0;
+    char szDeg[4] = { pszLat[0], pszLat[1], 0 };
+    char szMin[3] = { pszLat[3], pszLat[4], 0 };
+    char szSec[10];
+    memcpy(szSec, pszLat + 6, std::max((int)sizeof(szSec) - 1, nSecLen));
+    szSec[std::max((int)sizeof(szSec) - 1, nSecLen)] = 0;
 
     dfLat = atoi(szDeg) + atoi(szMin) / 60. + CPLAtof(szSec) / 3600.;
     if (chLatHemisphere == 'S')
@@ -200,8 +190,8 @@ static int GetLatLon(const char* pszLat,
     szMin[0] = pszLon[4];
     szMin[1] = pszLon[5];
     szMin[2] = 0;
-    memcpy(szSec, pszLon + 7, MAX((int)sizeof(szSec) - 1, nSecLen));
-    szSec[MAX((int)sizeof(szSec) - 1, nSecLen)] = 0;
+    memcpy(szSec, pszLon + 7, std::max((int)sizeof(szSec) - 1, nSecLen));
+    szSec[std::max((int)sizeof(szSec) - 1, nSecLen)] = 0;
 
     dfLon = atoi(szDeg) + atoi(szMin) / 60. + CPLAtof(szSec) / 3600.;
     if (chLonHemisphere == ' ' || chLonHemisphere == 'W')
@@ -210,7 +200,6 @@ static int GetLatLon(const char* pszLat,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                              GetLatLon()                             */
 /************************************************************************/
@@ -226,15 +215,14 @@ int OGRAeronavFAADOFLayer::GetLatLon(const char* pszLat, const char* pszLon, dou
 
 OGRFeature *OGRAeronavFAADOFLayer::GetNextRawFeature()
 {
-    const char* pszLine;
     char szBuffer[130];
 
     while( true )
     {
-        pszLine = CPLReadLine2L(fpAeronavFAA, 130, NULL);
+        const char* pszLine = CPLReadLine2L(fpAeronavFAA, 130, NULL);
         if (pszLine == NULL)
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
         if (strlen(pszLine) != 128)
@@ -260,7 +248,8 @@ OGRFeature *OGRAeronavFAADOFLayer::GetNextRawFeature()
                 poFeature->SetField(i, szBuffer);
         }
 
-        double dfLat, dfLon;
+        double dfLat = 0.0;
+        double dfLon = 0.0;
         GetLatLon(pszLine + psRecordDesc->nLatStartCol - 1,
                   pszLine + psRecordDesc->nLonStartCol - 1,
                   dfLat,
@@ -273,8 +262,6 @@ OGRFeature *OGRAeronavFAADOFLayer::GetNextRawFeature()
     }
 }
 
-
-
 static const RecordFieldDesc NAVAIDFields [] =
 {
     { "ID", 2, 6, OFTString },
@@ -293,7 +280,6 @@ static const RecordFieldDesc NAVAIDFields [] =
 
 static const RecordDesc NAVAID = { sizeof(NAVAIDFields)/sizeof(NAVAIDFields[0]), NAVAIDFields, 17, 30 };
 
-
 /************************************************************************/
 /*                    OGRAeronavFAANAVAIDLayer()                        */
 /************************************************************************/
@@ -316,7 +302,6 @@ OGRAeronavFAANAVAIDLayer::OGRAeronavFAANAVAIDLayer( VSILFILE* fp,
     }
 }
 
-
 /************************************************************************/
 /*                              GetLatLon()                             */
 /************************************************************************/
@@ -332,15 +317,14 @@ int OGRAeronavFAANAVAIDLayer::GetLatLon(const char* pszLat, const char* pszLon,
 
 OGRFeature *OGRAeronavFAANAVAIDLayer::GetNextRawFeature()
 {
-    const char* pszLine;
     char szBuffer[134];
 
     while( true )
     {
-        pszLine = CPLReadLine2L(fpAeronavFAA, 134, NULL);
+        const char* pszLine = CPLReadLine2L(fpAeronavFAA, 134, NULL);
         if (pszLine == NULL)
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
         if (strlen(pszLine) != 132)
@@ -369,7 +353,8 @@ OGRFeature *OGRAeronavFAANAVAIDLayer::GetNextRawFeature()
                 poFeature->SetField(i, szBuffer);
         }
 
-        double dfLat, dfLon;
+        double dfLat = 0.0;
+        double dfLon = 0.0;
         GetLatLon(pszLine + psRecordDesc->nLatStartCol - 1,
                   pszLine + psRecordDesc->nLonStartCol - 1,
                   dfLat,
@@ -382,8 +367,6 @@ OGRFeature *OGRAeronavFAANAVAIDLayer::GetNextRawFeature()
     }
 }
 
-
-
 /************************************************************************/
 /*                    OGRAeronavFAARouteLayer()                        */
 /************************************************************************/
@@ -393,7 +376,7 @@ OGRAeronavFAARouteLayer::OGRAeronavFAARouteLayer( VSILFILE* fp,
                                                   int bIsDPOrSTARSIn ) :
     OGRAeronavFAALayer(fp, pszLayerName)
 {
-    this->bIsDPOrSTARS = bIsDPOrSTARSIn;
+    bIsDPOrSTARS = bIsDPOrSTARSIn;
 
     poFeatureDefn->SetGeomType( wkbLineString );
 
@@ -416,7 +399,6 @@ OGRAeronavFAARouteLayer::OGRAeronavFAARouteLayer( VSILFILE* fp,
     }
 }
 
-
 /************************************************************************/
 /*                              GetLatLon()                             */
 /************************************************************************/
@@ -432,13 +414,13 @@ int OGRAeronavFAARouteLayer::GetLatLon(const char* pszLat, const char* pszLon, d
 
 OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
 {
-    const char* pszLine;
     OGRFeature* poFeature = NULL;
     OGRLineString* poLS = NULL;
 
     while( true )
     {
-        if (osLastReadLine.size() != 0)
+        const char* pszLine = NULL;
+        if (!osLastReadLine.empty())
             pszLine = osLastReadLine.c_str();
         else
             pszLine = CPLReadLine2L(fpAeronavFAA, 87, NULL);
@@ -446,7 +428,7 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
 
         if (pszLine == NULL)
         {
-            bEOF = TRUE;
+            bEOF = true;
             break;
         }
         if (strlen(pszLine) != 85)
@@ -480,7 +462,7 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
 
         if (strcmp(pszLine, "================================DELETIONS LIST=================================198326") == 0)
         {
-            bEOF = TRUE;
+            bEOF = true;
             break;
         }
 
@@ -496,14 +478,14 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
             {
                 CPLString osName = pszLine + 2;
                 osName.resize(60);
-                while(osName.size() > 0 && osName[osName.size()-1] == ' ')
+                while(!osName.empty() && osName.back() == ' ')
                 {
                     osName.resize(osName.size()-1);
                 }
 
                 if (strcmp(osName.c_str(), "(DELETIONS LIST)") == 0)
                 {
-                    bEOF = TRUE;
+                    bEOF = true;
                     return NULL;
                 }
 
@@ -538,7 +520,8 @@ OGRFeature *OGRAeronavFAARouteLayer::GetNextRawFeature()
             break;
         }
 
-        double dfLat, dfLon;
+        double dfLat = 0.0;
+        double dfLon = 0.0;
         GetLatLon(pszLine + 29 - 1,
                   pszLine + 42 - 1,
                   dfLat,
@@ -564,19 +547,16 @@ void OGRAeronavFAARouteLayer::ResetReading()
     osStateName = "";
 }
 
-
 static const RecordFieldDesc IAPFields [] =
 {
     { "LOC_ID",  4, 8, OFTString },
     { "MAG_VAR"  ,  52, 54, OFTInteger, },
     { "ELEVATION", 62, 67, OFTInteger },
     { "TYPE", 71, 77, OFTString  },
-
 };
 
 static const RecordDesc IAP = { sizeof(IAPFields)/sizeof(IAPFields[0]), IAPFields, -1, -1 };
 
-
 /************************************************************************/
 /*                     OGRAeronavFAAIAPLayer()                          */
 /************************************************************************/
@@ -612,10 +592,8 @@ OGRAeronavFAAIAPLayer::OGRAeronavFAAIAPLayer( VSILFILE* fp,
         oField.SetWidth(psRecordDesc->pasFields[i].nLastCol - psRecordDesc->pasFields[i].nStartCol + 1);
         poFeatureDefn->AddFieldDefn( &oField );
     }
-
 }
 
-
 /************************************************************************/
 /*                              GetLatLon()                             */
 /************************************************************************/
@@ -631,16 +609,15 @@ int OGRAeronavFAAIAPLayer::GetLatLon(const char* pszLat, const char* pszLon, dou
 
 OGRFeature *OGRAeronavFAAIAPLayer::GetNextRawFeature()
 {
-    const char* pszLine;
     char szBuffer[87];
     int nCountUnderscoreLines = 0;
 
     while( true )
     {
-        pszLine = CPLReadLine2L(fpAeronavFAA, 87, NULL);
+        const char* pszLine = CPLReadLine2L(fpAeronavFAA, 87, NULL);
         if (pszLine == NULL)
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
         if (strlen(pszLine) != 85)
@@ -648,7 +625,7 @@ OGRFeature *OGRAeronavFAAIAPLayer::GetNextRawFeature()
 
         if (STARTS_WITH(pszLine, "DELETIONS"))
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
 
@@ -678,7 +655,7 @@ OGRFeature *OGRAeronavFAAIAPLayer::GetNextRawFeature()
             osCityName.resize(pszComma - pszBegin);
             osStateName = pszComma + 2;
             osStateName.resize(78 - (pszComma + 2 - pszLine));
-            while(osStateName.size() > 0 && osStateName[osStateName.size()-1] == ' ')
+            while(!osStateName.empty() && osStateName.back() == ' ')
             {
                 osStateName.resize(osStateName.size()-1);
             }
@@ -726,7 +703,8 @@ OGRFeature *OGRAeronavFAAIAPLayer::GetNextRawFeature()
                 poFeature->SetField(i + 4, szBuffer);
         }
 
-        double dfLat, dfLon;
+        double dfLat = 0.0;
+        double dfLon = 0.0;
         GetLatLon(pszLine + 16 - 1,
                   (pszLine[34 - 1] != ' ') ? pszLine + 34 - 1 : pszLine + 35 - 1,
                   dfLat,
diff --git a/ogr/ogrsf_frmts/amigocloud/GNUmakefile b/ogr/ogrsf_frmts/amigocloud/GNUmakefile
index 6953a5f..d72902c 100644
--- a/ogr/ogrsf_frmts/amigocloud/GNUmakefile
+++ b/ogr/ogrsf_frmts/amigocloud/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogramigoclouddriver.o ogramigoclouddatasource.o ogramigocloudlayer.o ogramigocloudtablelayer.o ogramigocloudresultlayer.o
 
-CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. -I../pgdump $(CPPFLAGS)
+CPPFLAGS	:=	-I../geojson $(JSON_INCLUDE) -I.. -I../.. -I../pgdump $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/amigocloud/drv_amigocloud.html b/ogr/ogrsf_frmts/amigocloud/drv_amigocloud.html
index b0ea785..8974e56 100644
--- a/ogr/ogrsf_frmts/amigocloud/drv_amigocloud.html
+++ b/ogr/ogrsf_frmts/amigocloud/drv_amigocloud.html
@@ -19,12 +19,12 @@ The driver supports read and write operations.<p>
 
 The minimal syntax to open a AmigoCloud datasource is : <pre>AmigoCloud:[project_id]</pre><p>
 
-Additionnal optional parameters can be specified after the ':' sign.
+Additional optional parameters can be specified after the ':' sign.
 Currently the following one is supported :<p>
 
 <ul>
-<li> <b>tables=dataset_id1[,dataset_id2]*</b>: A list of AmigoCloud dataset IDs.
-This is necessary when you need to access a particular AmigoCloud datasets.
+<li> <b>datasets=dataset_id1[,dataset_id2, ..]</b>: A list of AmigoCloud dataset IDs.
+This is necessary when you need to access a particular AmigoCloud dataset.
 </ul>
 
 If several parameters are specified, they must be separated by a space.<p>
@@ -35,8 +35,6 @@ The following configuration options are available :
 <ul>
 <li>AMIGOCLOUD_API_URL: defaults to https://www.amigocloud.com/api/v1.
 Can be used to point to another server.</li>
-<li>AMIGOCLOUD_HTTPS: can be set to NO to use http:// protocol instead of
-https:// (only if AMIGOCLOUD_API_URL is not defined).</li>
 <li>AMIGOCLOUD_API_KEY: see following paragraph.</li>
 </ul>
 
@@ -60,12 +58,6 @@ The driver will forward any spatial filter set with SetSpatialFilter() to
 the server. It also makes the same for attribute
 filters set with SetAttributeFilter().<p>
 
-<h2>Paging</h2>
-
-Features are retrieved from the server by chunks of 500 by default.
-This number can be altered with the AMIGOCLOUD_PAGE_SIZE
-configuration option.<p>
-
 <h2>Write support</h2>
 
 Dataset creation and deletion is possible.<p>
@@ -107,7 +99,7 @@ can be NULL. Defaults to YES.</li>
 <li>
 Acceccing data from a public table:
 <pre>
-ogrinfo -ro "AmigoCloud:1234 tables=1234,1235"
+ogrinfo -ro "AmigoCloud:1234 datasets=1234,1235"
 </pre>
 <p>
 
diff --git a/ogr/ogrsf_frmts/amigocloud/makefile.vc b/ogr/ogrsf_frmts/amigocloud/makefile.vc
index d85663c..00e9938 100644
--- a/ogr/ogrsf_frmts/amigocloud/makefile.vc
+++ b/ogr/ogrsf_frmts/amigocloud/makefile.vc
@@ -1,5 +1,5 @@
 OBJ	=	ogramigoclouddriver.obj ogramigoclouddatasource.obj ogramigocloudlayer.obj ogramigocloudtablelayer.obj ogramigocloudresultlayer.obj
-EXTRAFLAGS =	-I.. -I..\.. -I..\geojson\libjson -I..\pgdump 
+EXTRAFLAGS =	-I.. -I..\.. -I..\geojson -I..\geojson\libjson -I..\pgdump 
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/amigocloud/ogr_amigocloud.h b/ogr/ogrsf_frmts/amigocloud/ogr_amigocloud.h
index 7952663..0484550 100644
--- a/ogr/ogrsf_frmts/amigocloud/ogr_amigocloud.h
+++ b/ogr/ogrsf_frmts/amigocloud/ogr_amigocloud.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: ogr_amigocloud.h 36687 2016-12-04 22:28:14Z rouault $
  *
  * Project:  AMIGOCLOUD Translator
  * Purpose:  Definition of classes for OGR AmigoCloud driver.
@@ -35,7 +35,9 @@
 
 #include <vector>
 #include <string>
-#include <json.h>
+
+#include "ogr_json_header.h"
+
 #include <cpl_hash_set.h>
 #include <cstdlib>
 
@@ -65,11 +67,11 @@ class OGRAmigoCloudFID
         GIntBig iFID;
         std::string osAmigoId;
 
-        OGRAmigoCloudFID(const std::string &amigo_id, GIntBig index)
+        OGRAmigoCloudFID(const std::string &amigo_id, GIntBig index) :
+            iIndex( index ),
+            iFID( std::abs((long)CPLHashSetHashStr(amigo_id.c_str())) ),
+            osAmigoId( amigo_id )
         {
-            iIndex = index;
-            OGRAmigoCloudFID::osAmigoId = amigo_id.c_str();
-            iFID = std::abs((long)CPLHashSetHashStr(amigo_id.c_str()));
         }
 
         OGRAmigoCloudFID()
@@ -78,11 +80,11 @@ class OGRAmigoCloudFID
             iFID=0;
         }
 
-        OGRAmigoCloudFID(const OGRAmigoCloudFID& fid)
+        OGRAmigoCloudFID(const OGRAmigoCloudFID& fid) :
+            iIndex( fid.iIndex ),
+            iFID( fid.iFID ),
+            osAmigoId( fid.osAmigoId.c_str() )
         {
-            iIndex = fid.iIndex;
-            iFID = fid.iFID;
-            osAmigoId = fid.osAmigoId.c_str();
         }
 };
 
@@ -117,24 +119,23 @@ class OGRAmigoCloudLayer : public OGRLayer
         virtual CPLString    GetSRS_SQL(const char* pszGeomCol) = 0;
 
     public:
-         OGRAmigoCloudLayer(OGRAmigoCloudDataSource* poDS);
-        ~OGRAmigoCloudLayer();
+        explicit OGRAmigoCloudLayer(OGRAmigoCloudDataSource* poDS);
+        virtual ~OGRAmigoCloudLayer();
 
-        virtual void                ResetReading();
-        virtual OGRFeature *        GetNextFeature();
+        virtual void                ResetReading() override;
+        virtual OGRFeature *        GetNextFeature() override;
 
-        virtual OGRFeatureDefn *    GetLayerDefn();
+        virtual OGRFeatureDefn *    GetLayerDefn() override;
         virtual OGRFeatureDefn *    GetLayerDefnInternal(json_object* poObjIn) = 0;
         virtual json_object*        FetchNewFeatures(GIntBig iNext);
 
-        virtual const char*         GetFIDColumn() { return osFIDColName.c_str(); }
+        virtual const char*         GetFIDColumn() override { return osFIDColName.c_str(); }
 
-        virtual int                 TestCapability( const char * );
+        virtual int                 TestCapability( const char * ) override;
 
-        int                         GetFeaturesToFetch() { return atoi(CPLGetConfigOption("AMIGOCLOUD_PAGE_SIZE", "500")); }
+        static  int                 GetFeaturesToFetch() { return 100; }
 };
 
-
 /************************************************************************/
 /*                        OGRAmigoCloudTableLayer                          */
 /************************************************************************/
@@ -155,43 +156,43 @@ class OGRAmigoCloudTableLayer : public OGRAmigoCloudLayer
 
     void                BuildWhere();
 
-    virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
+    virtual CPLString    GetSRS_SQL(const char* pszGeomCol) override;
 
     public:
          OGRAmigoCloudTableLayer(OGRAmigoCloudDataSource* poDS, const char* pszName);
-        ~OGRAmigoCloudTableLayer();
+        virtual ~OGRAmigoCloudTableLayer();
 
-        virtual const char        *GetName() { return osTableName.c_str(); }
+        virtual const char        *GetName() override { return osTableName.c_str(); }
                 const char        *GetDatasetId() { return osDatasetId.c_str(); }
-        virtual OGRFeatureDefn    *GetLayerDefnInternal(json_object* poObjIn);
-        virtual json_object       *FetchNewFeatures(GIntBig iNext);
+        virtual OGRFeatureDefn    *GetLayerDefnInternal(json_object* poObjIn) override;
+        virtual json_object       *FetchNewFeatures(GIntBig iNext) override;
 
-        virtual GIntBig             GetFeatureCount( int bForce = TRUE );
-        virtual OGRFeature         *GetFeature( GIntBig nFeatureId );
+        virtual GIntBig             GetFeatureCount( int bForce = TRUE ) override;
+        virtual OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
 
-        virtual int                 TestCapability( const char * );
+        virtual int                 TestCapability( const char * ) override;
 
         virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                         int bApproxOK = TRUE );
+                                         int bApproxOK = TRUE ) override;
 
-        virtual OGRFeature  *GetNextRawFeature();
+        virtual OGRFeature  *GetNextRawFeature() override;
 
-        virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-        virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-        virtual OGRErr      DeleteFeature( GIntBig nFID );
+        virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+        virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+        virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-        virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
-        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
-        virtual OGRErr      SetAttributeFilter( const char * );
+        virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override { SetSpatialFilter(0, poGeom); }
+        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override;
+        virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) { return GetExtent(0, psExtent, bForce); }
-        virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce );
+        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override { return GetExtent(0, psExtent, bForce); }
+        virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce ) override;
 
         void                SetDeferredCreation(OGRwkbGeometryType eGType,
                                    OGRSpatialReference *poSRS,
                                    int bGeomNullable);
 
-        CPLString           GetAmigoCloudType(OGRFieldDefn& oField);
+        static CPLString           GetAmigoCloudType(OGRFieldDefn& oField);
 
         OGRErr              RunDeferredCreationIfNecessary();
         int                 GetDeferredCreation() const { return bDeferredCreation; }
@@ -209,15 +210,15 @@ class OGRAmigoCloudResultLayer : public OGRAmigoCloudLayer
 {
         OGRFeature          *poFirstFeature;
 
-        virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
+        virtual CPLString    GetSRS_SQL(const char* pszGeomCol) override;
 
     public:
         OGRAmigoCloudResultLayer( OGRAmigoCloudDataSource* poDS,
                                                const char * pszRawStatement );
         virtual             ~OGRAmigoCloudResultLayer();
 
-        virtual OGRFeatureDefn *GetLayerDefnInternal(json_object* poObjIn);
-        virtual OGRFeature  *GetNextRawFeature();
+        virtual OGRFeatureDefn *GetLayerDefnInternal(json_object* poObjIn) override;
+        virtual OGRFeature  *GetNextRawFeature() override;
 
         int                 IsOK();
 };
@@ -233,47 +234,47 @@ class OGRAmigoCloudDataSource : public OGRDataSource
 
         OGRAmigoCloudTableLayer**  papoLayers;
         int                 nLayers;
-        int                 bReadWrite;
+        bool                bReadWrite;
 
-        int                 bUseHTTPS;
+        bool                bUseHTTPS;
 
         CPLString           osAPIKey;
 
-        int                 bMustCleanPersistent;
+        bool                bMustCleanPersistent;
 
         CPLString           osCurrentSchema;
-
+        // TODO(schwehr): Can bHasOGRMetadataFunction be a bool?
         int                 bHasOGRMetadataFunction;
 
     public:
         OGRAmigoCloudDataSource();
-        ~OGRAmigoCloudDataSource();
+        virtual ~OGRAmigoCloudDataSource();
 
         int                 Open( const char * pszFilename,
                                   char** papszOpenOptions,
                                   int bUpdate );
 
-        virtual const char* GetName() { return pszName; }
+        virtual const char* GetName() override { return pszName; }
 
-        virtual int         GetLayerCount() { return nLayers; }
-        virtual OGRLayer   *GetLayer( int );
-        virtual OGRLayer   *GetLayerByName(const char *);
+        virtual int         GetLayerCount() override { return nLayers; }
+        virtual OGRLayer   *GetLayer( int ) override;
+        virtual OGRLayer   *GetLayerByName(const char *) override;
 
-        virtual int         TestCapability( const char * );
+        virtual int         TestCapability( const char * ) override;
 
         virtual OGRLayer   *ICreateLayer( const char *pszName,
                                          OGRSpatialReference *poSpatialRef = NULL,
                                          OGRwkbGeometryType eGType = wkbUnknown,
-                                         char ** papszOptions = NULL );
-        virtual OGRErr      DeleteLayer(int);
+                                         char ** papszOptions = NULL ) override;
+        virtual OGRErr      DeleteLayer(int) override;
 
         virtual OGRLayer   *ExecuteSQL( const char *pszSQLCommand,
                                         OGRGeometry *poSpatialFilter,
-                                        const char *pszDialect );
-        virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                        const char *pszDialect ) override;
+        virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
         const char*                 GetAPIURL() const;
-        int                         IsReadWrite() const { return bReadWrite; }
+        bool                        IsReadWrite() const { return bReadWrite; }
         const char*                 GetProjetcId() { return pszProjetctId;}
         char**                      AddHTTPOptions();
         json_object*                RunPOST(const char*pszURL, const char *pszPostData, const char *pszHeaders="HEADERS=Content-Type: application/json");
@@ -281,16 +282,17 @@ class OGRAmigoCloudDataSource : public OGRDataSource
         json_object*                RunDELETE(const char*pszURL);
         json_object*                RunSQL(const char* pszUnescapedSQL);
         const CPLString&            GetCurrentSchema() { return osCurrentSchema; }
-        int                         FetchSRSId( OGRSpatialReference * poSRS );
+        static int                         FetchSRSId( OGRSpatialReference * poSRS );
 
-        int                         IsAuthenticatedConnection() { return osAPIKey.size() != 0; }
+        int                         IsAuthenticatedConnection() { return !osAPIKey.empty(); }
         int                         HasOGRMetadataFunction() { return bHasOGRMetadataFunction; }
         void                        SetOGRMetadataFunction(int bFlag) { bHasOGRMetadataFunction = bFlag; }
 
-        OGRLayer *                  ExecuteSQLInternal( const char *pszSQLCommand,
-                                                        OGRGeometry *poSpatialFilter = NULL,
-                                                        const char *pszDialect = NULL,
-                                                        int bRunDeferredActions = FALSE );
+        OGRLayer *                  ExecuteSQLInternal(
+            const char *pszSQLCommand,
+            OGRGeometry *poSpatialFilter = NULL,
+            const char *pszDialect = NULL,
+            bool bRunDeferredActions = false );
 };
 
 #endif /* ndef OGR_AMIGOCLOUD_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp
index e7293f4..cc69eb6 100644
--- a/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  AmigoCloud Translator
  * Purpose:  Implements OGRAmigoCloudDataSource class
@@ -29,9 +28,10 @@
 
 #include "ogr_amigocloud.h"
 #include "ogr_pgdump.h"
+#include "ogrgeojsonreader.h"
 #include <sstream>
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogramigoclouddatasource.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 CPLString OGRAMIGOCLOUDGetOptionValue(const char* pszFilename, const char* pszOptionName);
 
@@ -44,9 +44,9 @@ OGRAmigoCloudDataSource::OGRAmigoCloudDataSource() :
     pszProjetctId(NULL),
     papoLayers(NULL),
     nLayers(0),
-    bReadWrite(FALSE),
-    bUseHTTPS(FALSE),
-    bMustCleanPersistent(FALSE),
+    bReadWrite(false),
+    bUseHTTPS(false),
+    bMustCleanPersistent(false),
     bHasOGRMetadataFunction(-1)
 {}
 
@@ -61,7 +61,7 @@ OGRAmigoCloudDataSource::~OGRAmigoCloudDataSource()
         delete papoLayers[i];
     CPLFree( papoLayers );
 
-    if (bMustCleanPersistent)
+    if( bMustCleanPersistent )
     {
         char** papszOptions = NULL;
         papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("AMIGOCLOUD:%p", this));
@@ -80,10 +80,12 @@ OGRAmigoCloudDataSource::~OGRAmigoCloudDataSource()
 int OGRAmigoCloudDataSource::TestCapability( const char * pszCap )
 
 {
-    if( bReadWrite && EQUAL(pszCap,ODsCCreateLayer) )
+    if( bReadWrite && EQUAL(pszCap, ODsCCreateLayer) )
         return TRUE;
-    else if( bReadWrite && EQUAL(pszCap,ODsCDeleteLayer) )
+    else if( bReadWrite && EQUAL(pszCap, ODsCDeleteLayer) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return bReadWrite;
     else
         return FALSE;
 }
@@ -124,7 +126,7 @@ CPLString OGRAMIGOCLOUDGetOptionValue(const char* pszFilename,
     if (!pszOptionValue)
         return "";
 
-    CPLString osOptionValue(pszOptionValue + strlen(osOptionName));
+    CPLString osOptionValue(pszOptionValue + osOptionName.size());
     const char* pszSpace = strchr(osOptionValue.c_str(), ' ');
     if (pszSpace)
         osOptionValue.resize(pszSpace - osOptionValue.c_str());
@@ -136,12 +138,12 @@ CPLString OGRAMIGOCLOUDGetOptionValue(const char* pszFilename,
 /************************************************************************/
 
 int OGRAmigoCloudDataSource::Open( const char * pszFilename,
-                                char** papszOpenOptionsIn,
-                                int bUpdateIn )
+                                   char** papszOpenOptionsIn,
+                                   int bUpdateIn )
 
 {
 
-    bReadWrite = bUpdateIn;
+    bReadWrite = CPL_TO_BOOL(bUpdateIn);
 
     pszName = CPLStrdup( pszFilename );
     if( CSLFetchNameValue(papszOpenOptionsIn, "PROJECTID") )
@@ -185,10 +187,10 @@ int OGRAmigoCloudDataSource::Open( const char * pszFilename,
         }
         ReleaseResultSet(poSchemaLayer);
     }
-    if( osCurrentSchema.size() == 0 )
+    if( osCurrentSchema.empty() )
         return FALSE;
 
-    if (osDatasets.size() != 0)
+    if (!osDatasets.empty())
     {
         char** papszTables = CSLTokenizeString2(osDatasets, ",", 0);
         for(int i=0;papszTables && papszTables[i];i++)
@@ -214,7 +216,7 @@ const char* OGRAmigoCloudDataSource::GetAPIURL() const
     if (pszAPIURL)
         return pszAPIURL;
 
-    else if (bUseHTTPS)
+    else if( bUseHTTPS )
         return CPLSPrintf("https://www.amigocloud.com/api/v1");
     else
         return CPLSPrintf("http://www.amigocloud.com/api/v1");
@@ -227,15 +229,14 @@ const char* OGRAmigoCloudDataSource::GetAPIURL() const
 int OGRAmigoCloudDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
 {
-    const char*         pszAuthorityName;
-
     if( poSRS == NULL )
         return 0;
 
     OGRSpatialReference oSRS(*poSRS);
+    // cppcheck-suppress uselessAssignmentPtrArg
     poSRS = NULL;
 
-    pszAuthorityName = oSRS.GetAuthorityName(NULL);
+    const char* pszAuthorityName = oSRS.GetAuthorityName(NULL);
 
     if( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
     {
@@ -263,12 +264,10 @@ int OGRAmigoCloudDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
     if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
     {
-        int             nAuthorityCode;
-
         /* For the root authority name 'EPSG', the authority code
          * should always be integral
          */
-        nAuthorityCode = atoi( oSRS.GetAuthorityCode(NULL) );
+        const int nAuthorityCode = atoi( oSRS.GetAuthorityCode(NULL) );
 
         return nAuthorityCode;
     }
@@ -285,7 +284,7 @@ OGRLayer   *OGRAmigoCloudDataSource::ICreateLayer( const char *pszNameIn,
                                            OGRwkbGeometryType eGType,
                                            char ** papszOptions )
 {
-    if (!bReadWrite)
+    if( !bReadWrite )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode");
         return NULL;
@@ -298,7 +297,8 @@ OGRLayer   *OGRAmigoCloudDataSource::ICreateLayer( const char *pszNameIn,
     CPLString osName(pszNameIn);
 
     OGRAmigoCloudTableLayer* poLayer = new OGRAmigoCloudTableLayer(this, osName);
-    int bGeomNullable = CSLFetchBoolean(papszOptions, "GEOMETRY_NULLABLE", TRUE);
+    const bool bGeomNullable =
+        CPLFetchBool(papszOptions, "GEOMETRY_NULLABLE", true);
     poLayer->SetDeferredCreation(eGType, poSpatialRef, bGeomNullable);
     papoLayers = (OGRAmigoCloudTableLayer**) CPLRealloc(
                     papoLayers, (nLayers + 1) * sizeof(OGRAmigoCloudTableLayer*));
@@ -313,7 +313,7 @@ OGRLayer   *OGRAmigoCloudDataSource::ICreateLayer( const char *pszNameIn,
 
 OGRErr OGRAmigoCloudDataSource::DeleteLayer(int iLayer)
 {
-    if (!bReadWrite)
+    if( !bReadWrite )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in read-only mode");
@@ -343,7 +343,7 @@ OGRErr OGRAmigoCloudDataSource::DeleteLayer(int iLayer)
              sizeof(void *) * (nLayers - iLayer - 1) );
     nLayers--;
 
-    if (osDatasetId.size() == 0)
+    if (osDatasetId.empty())
         return OGRERR_NONE;
 
     if( !bDeferredCreation )
@@ -367,7 +367,7 @@ OGRErr OGRAmigoCloudDataSource::DeleteLayer(int iLayer)
 
 char** OGRAmigoCloudDataSource::AddHTTPOptions()
 {
-    bMustCleanPersistent = TRUE;
+    bMustCleanPersistent = true;
 
     return CSLAddString(NULL, CPLSPrintf("PERSISTENT=AMIGOCLOUD:%p", this));
 }
@@ -383,7 +383,7 @@ json_object* OGRAmigoCloudDataSource::RunPOST(const char*pszURL, const char *psz
     /* -------------------------------------------------------------------- */
     /*      Provide the API Key                                             */
     /* -------------------------------------------------------------------- */
-    if( osAPIKey.size() > 0 )
+    if( !osAPIKey.empty() )
     {
         osURL += "?token=";
         osURL += osAPIKey;
@@ -448,7 +448,7 @@ json_object* OGRAmigoCloudDataSource::RunPOST(const char*pszURL, const char *psz
     {
         if( json_object_get_type(poObj) == json_type_object )
         {
-            json_object* poError = json_object_object_get(poObj, "error");
+            json_object* poError = CPL_json_object_object_get(poObj, "error");
             if( poError != NULL && json_object_get_type(poError) == json_type_array &&
                 json_object_array_length(poError) > 0 )
             {
@@ -483,7 +483,7 @@ json_object* OGRAmigoCloudDataSource::RunDELETE(const char*pszURL)
     /* -------------------------------------------------------------------- */
     /*      Provide the API Key                                             */
     /* -------------------------------------------------------------------- */
-    if( osAPIKey.size() > 0 )
+    if( !osAPIKey.empty() )
     {
         osURL += "?token=";
         osURL += osAPIKey;
@@ -545,7 +545,7 @@ json_object* OGRAmigoCloudDataSource::RunDELETE(const char*pszURL)
     {
         if( json_object_get_type(poObj) == json_type_object )
         {
-            json_object* poError = json_object_object_get(poObj, "error");
+            json_object* poError = CPL_json_object_object_get(poObj, "error");
             if( poError != NULL && json_object_get_type(poError) == json_type_array &&
                 json_object_array_length(poError) > 0 )
             {
@@ -580,7 +580,7 @@ json_object* OGRAmigoCloudDataSource::RunGET(const char*pszURL)
     /* -------------------------------------------------------------------- */
     /*      Provide the API Key                                             */
     /* -------------------------------------------------------------------- */
-    if( osAPIKey.size() > 0 )
+    if( !osAPIKey.empty() )
     {
         osURL += "?token=";
         osURL += osAPIKey;
@@ -638,7 +638,7 @@ json_object* OGRAmigoCloudDataSource::RunGET(const char*pszURL)
     {
         if( json_object_get_type(poObj) == json_type_object )
         {
-            json_object* poError = json_object_object_get(poObj, "error");
+            json_object* poError = CPL_json_object_object_get(poObj, "error");
             if( poError != NULL && json_object_get_type(poError) == json_type_array &&
                 json_object_array_length(poError) > 0 )
             {
@@ -674,7 +674,7 @@ json_object* OGRAmigoCloudDataSource::RunSQL(const char* pszUnescapedSQL)
     /* -------------------------------------------------------------------- */
     /*      Provide the API Key                                             */
     /* -------------------------------------------------------------------- */
-    if( osAPIKey.size() > 0 )
+    if( !osAPIKey.empty() )
     {
         osSQL += "?token=";
         osSQL += osAPIKey;
@@ -753,7 +753,7 @@ json_object* OGRAmigoCloudDataSource::RunSQL(const char* pszUnescapedSQL)
     {
         if( json_object_get_type(poObj) == json_type_object )
         {
-            json_object* poError = json_object_object_get(poObj, "error");
+            json_object* poError = CPL_json_object_object_get(poObj, "error");
             if( poError != NULL && json_object_get_type(poError) == json_type_array &&
                 json_object_array_length(poError) > 0 )
             {
@@ -788,7 +788,7 @@ json_object* OGRAMIGOCLOUDGetSingleRow(json_object* poObj)
         return NULL;
     }
 
-    json_object* poRows = json_object_object_get(poObj, "data");
+    json_object* poRows = CPL_json_object_object_get(poObj, "data");
     if( poRows == NULL ||
         json_object_get_type(poRows) != json_type_array ||
         json_object_array_length(poRows) != 1 )
@@ -814,14 +814,14 @@ OGRLayer * OGRAmigoCloudDataSource::ExecuteSQL( const char *pszSQLCommand,
                                         const char *pszDialect )
 
 {
-    return ExecuteSQLInternal(pszSQLCommand, poSpatialFilter, pszDialect,
-                              TRUE);
+    return ExecuteSQLInternal(pszSQLCommand, poSpatialFilter, pszDialect, true);
 }
 
-OGRLayer * OGRAmigoCloudDataSource::ExecuteSQLInternal( const char *pszSQLCommand,
-                                                     OGRGeometry *poSpatialFilter,
-                                                     const char *,
-                                                     int bRunDeferredActions )
+OGRLayer * OGRAmigoCloudDataSource::ExecuteSQLInternal(
+    const char *pszSQLCommand,
+    OGRGeometry *poSpatialFilter,
+    const char *,
+    bool bRunDeferredActions )
 
 {
     if( bRunDeferredActions )
@@ -837,7 +837,6 @@ OGRLayer * OGRAmigoCloudDataSource::ExecuteSQLInternal( const char *pszSQLComman
     while(*pszSQLCommand == ' ')
         pszSQLCommand ++;
 
-
     if( !EQUALN(pszSQLCommand, "SELECT", strlen("SELECT")) &&
         !EQUALN(pszSQLCommand, "EXPLAIN", strlen("EXPLAIN")) &&
         !EQUALN(pszSQLCommand, "WITH", strlen("WITH")) )
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigoclouddriver.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddriver.cpp
index 1f3c22d..e8b77b4 100644
--- a/ogr/ogrsf_frmts/amigocloud/ogramigoclouddriver.cpp
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigoclouddriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  AmigoCloud Translator
  * Purpose:  Implements OGRAMIGOCLOUDDriver.
@@ -29,7 +28,7 @@
 
 #include "ogr_amigocloud.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogramigoclouddriver.cpp 35611 2016-10-04 14:58:17Z goatbar $");
 
 extern "C" void RegisterOGRAmigoCloud();
 
@@ -69,11 +68,11 @@ static GDALDataset *OGRAmigoCloudDriverOpen( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *OGRAmigoCloudDriverCreate( const char * pszName,
-                                            CPL_UNUSED int nBands,
-                                            CPL_UNUSED int nXSize,
-                                            CPL_UNUSED int nYSize,
-                                            CPL_UNUSED GDALDataType eDT,
-                                            CPL_UNUSED char **papszOptions )
+                                               CPL_UNUSED int nBands,
+                                               CPL_UNUSED int nXSize,
+                                               CPL_UNUSED int nYSize,
+                                               CPL_UNUSED GDALDataType eDT,
+                                               CPL_UNUSED char **papszOptions )
 
 {
     OGRAmigoCloudDataSource   *poDS = new OGRAmigoCloudDataSource();
@@ -135,4 +134,3 @@ void RegisterOGRAmigoCloud()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp
index b025d81..800f10f 100644
--- a/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigocloudlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  AmigoCloud Translator
  * Purpose:  Implements OGRAmigoCloudLayer class.
@@ -29,8 +28,9 @@
 
 #include "ogr_amigocloud.h"
 #include "ogr_p.h"
+#include "ogrgeojsonreader.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogramigocloudlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGRAmigoCloudLayer()                            */
@@ -96,9 +96,9 @@ OGRFeature *OGRAmigoCloudLayer::BuildFeature(json_object* poRowObj)
     {
         poFeature = new OGRFeature(poFeatureDefn);
 
-        if( osFIDColName.size() > 0 )
+        if( !osFIDColName.empty() )
         {
-            json_object* poVal = json_object_object_get(poRowObj, osFIDColName);
+            json_object* poVal = CPL_json_object_object_get(poRowObj, osFIDColName);
             if( poVal != NULL &&
                 json_object_get_type(poVal) == json_type_string )
             {
@@ -106,18 +106,19 @@ OGRFeature *OGRAmigoCloudLayer::BuildFeature(json_object* poRowObj)
                 OGRAmigoCloudFID aFID(amigo_id, iNext);
                 mFIDs[aFID.iFID] = aFID;
                 poFeature->SetFID(aFID.iFID);
-
             }
         }
 
-
         for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
         {
-            json_object* poVal = json_object_object_get(poRowObj,
+            json_object* poVal = CPL_json_object_object_get(poRowObj,
                             poFeatureDefn->GetFieldDefn(i)->GetNameRef());
 
-            if( poVal != NULL &&
-                json_object_get_type(poVal) == json_type_string )
+            if( poVal == NULL )
+            {
+                poFeature->SetFieldNull(i);
+            }
+            else if( json_object_get_type(poVal) == json_type_string )
             {
                 if( poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
                 {
@@ -133,14 +134,12 @@ OGRFeature *OGRAmigoCloudLayer::BuildFeature(json_object* poRowObj)
                     poFeature->SetField(i, json_object_get_string(poVal));
                 }
             }
-            else if( poVal != NULL &&
-                (json_object_get_type(poVal) == json_type_int ||
-                 json_object_get_type(poVal) == json_type_boolean) )
+            else if( json_object_get_type(poVal) == json_type_int ||
+                     json_object_get_type(poVal) == json_type_boolean )
             {
                 poFeature->SetField(i, (GIntBig)json_object_get_int64(poVal));
             }
-            else if( poVal != NULL &&
-                json_object_get_type(poVal) == json_type_double )
+            else if( json_object_get_type(poVal) == json_type_double )
             {
                 poFeature->SetField(i, json_object_get_double(poVal));
             }
@@ -149,7 +148,7 @@ OGRFeature *OGRAmigoCloudLayer::BuildFeature(json_object* poRowObj)
         for(int i=0;i<poFeatureDefn->GetGeomFieldCount();i++)
         {
             OGRGeomFieldDefn* poGeomFldDefn = poFeatureDefn->GetGeomFieldDefn(i);
-            json_object* poVal = json_object_object_get(poRowObj,
+            json_object* poVal = CPL_json_object_object_get(poRowObj,
                             poGeomFldDefn->GetNameRef());
             if( poVal != NULL &&
                 json_object_get_type(poVal) == json_type_string )
@@ -200,7 +199,7 @@ OGRFeature *OGRAmigoCloudLayer::GetNextRawFeature()
             return NULL;
         }
 
-        if( poFeatureDefn == NULL && osBaseSQL.size() == 0 )
+        if( poFeatureDefn == NULL && osBaseSQL.empty() )
         {
             GetLayerDefn();
         }
@@ -217,7 +216,7 @@ OGRFeature *OGRAmigoCloudLayer::GetNextRawFeature()
             GetLayerDefnInternal(poObj);
         }
 
-        json_object* poRows = json_object_object_get(poObj, "data");
+        json_object* poRows = CPL_json_object_object_get(poObj, "data");
 
         if( poRows == NULL ||
             json_object_get_type(poRows) != json_type_array ||
@@ -236,7 +235,7 @@ OGRFeature *OGRAmigoCloudLayer::GetNextRawFeature()
         iNextInFetchedObjects = 0;
     }
 
-    json_object* poRows = json_object_object_get(poCachedObj, "data");
+    json_object* poRows = CPL_json_object_object_get(poCachedObj, "data");
     json_object* poRowObj = json_object_array_get_idx(poRows, iNextInFetchedObjects);
 
     iNextInFetchedObjects ++;
@@ -258,11 +257,9 @@ OGRFeature *OGRAmigoCloudLayer::GetNextRawFeature()
 
 OGRFeature *OGRAmigoCloudLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
     while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -295,7 +292,7 @@ int OGRAmigoCloudLayer::TestCapability( const char * pszCap )
 /************************************************************************/
 
 void OGRAmigoCloudLayer::EstablishLayerDefn(const char* pszLayerName,
-                                         json_object* poObjIn)
+                                            json_object* poObjIn)
 {
     poFeatureDefn = new OGRFeatureDefn(pszLayerName);
     poFeatureDefn->Reference();
@@ -316,10 +313,8 @@ void OGRAmigoCloudLayer::EstablishLayerDefn(const char* pszLayerName,
     }
     else
         osSQL.Printf("%s LIMIT 0", osBaseSQL.c_str());
-    json_object* poObj;
-    if( poObjIn != NULL )
-        poObj = poObjIn;
-    else
+    json_object* poObj = poObjIn;
+    if( poObj == NULL )
     {
         poObj = poDS->RunSQL(osSQL);
         if( poObj == NULL )
@@ -328,7 +323,7 @@ void OGRAmigoCloudLayer::EstablishLayerDefn(const char* pszLayerName,
         }
     }
 
-    json_object* poFields = json_object_object_get(poObj, "columns");
+    json_object* poFields = CPL_json_object_object_get(poObj, "columns");
     if( poFields == NULL || json_object_get_type(poFields) != json_type_array)
     {
         if( poObjIn == NULL )
@@ -439,13 +434,13 @@ OGRSpatialReference* OGRAmigoCloudLayer::GetSRS(const char* pszGeomCol,
         return NULL;
     }
 
-    json_object* poSRID = json_object_object_get(poRowObj, "srid");
+    json_object* poSRID = CPL_json_object_object_get(poRowObj, "srid");
     if( poSRID != NULL && json_object_get_type(poSRID) == json_type_int )
     {
         *pnSRID = json_object_get_int(poSRID);
     }
 
-    json_object* poSRTEXT = json_object_object_get(poRowObj, "srtext");
+    json_object* poSRTEXT = CPL_json_object_object_get(poRowObj, "srtext");
     OGRSpatialReference* poSRS = NULL;
     if( poSRTEXT != NULL && json_object_get_type(poSRTEXT) == json_type_string )
     {
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigocloudresultlayer.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigocloudresultlayer.cpp
index 6818913..4eae0e1 100644
--- a/ogr/ogrsf_frmts/amigocloud/ogramigocloudresultlayer.cpp
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigocloudresultlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id
  *
  * Project:  AmigoCloud Translator
  * Purpose:  Implements OGRAmigoCloudResultLayer class.
@@ -29,7 +28,7 @@
 
 #include "ogr_amigocloud.h"
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: ogramigocloudresultlayer.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                          OGRAmigoCloudResultLayer()                     */
diff --git a/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp b/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp
index f2a7888..279a303 100644
--- a/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp
+++ b/ogr/ogrsf_frmts/amigocloud/ogramigocloudtablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  AmigoCloud Translator
  * Purpose:  Implements OGRAmigoCloudTableLayer class.
@@ -30,9 +29,10 @@
 #include "ogr_amigocloud.h"
 #include "ogr_p.h"
 #include "ogr_pgdump.h"
+#include "ogrgeojsonreader.h"
 #include <sstream>
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogramigocloudtablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                    OGRAMIGOCLOUDEscapeIdentifier( )                     */
@@ -44,8 +44,8 @@ CPLString OGRAMIGOCLOUDEscapeIdentifier(const char* pszStr)
 
     osStr += "\"";
 
-    char ch;
-    for(int i=0; (ch = pszStr[i]) != '\0'; i++)
+    char ch = '\0';
+    for( int i = 0; (ch = pszStr[i]) != '\0'; i++ )
     {
         if (ch == '"')
             osStr.append(1, ch);
@@ -65,8 +65,8 @@ CPLString OGRAMIGOCLOUDEscapeLiteral(const char* pszStr)
 {
     CPLString osStr;
 
-    char ch;
-    for(int i=0; (ch = pszStr[i]) != '\0'; i++)
+    char ch = '\0';
+    for( int i=0; (ch = pszStr[i]) != '\0'; i++ )
     {
         if (ch == '\'')
             osStr.append(1, ch);
@@ -144,14 +144,14 @@ OGRFeatureDefn * OGRAmigoCloudTableLayer::GetLayerDefnInternal(CPL_UNUSED json_o
         osBaseSQL = "";
     }
 
-    if( osFIDColName.size() > 0 )
+    if( !osFIDColName.empty() )
     {
         CPLString sql;
         sql.Printf("SELECT %s FROM %s", OGRAMIGOCLOUDEscapeIdentifier(osFIDColName).c_str(), OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str());
         json_object* poObj = poDS->RunSQL(sql);
         if( poObj != NULL && json_object_get_type(poObj) == json_type_object)
         {
-            json_object* poRows = json_object_object_get(poObj, "data");
+            json_object* poRows = CPL_json_object_object_get(poObj, "data");
 
             if(poRows!=NULL && json_object_get_type(poRows) == json_type_array)
             {
@@ -183,14 +183,14 @@ OGRFeatureDefn * OGRAmigoCloudTableLayer::GetLayerDefnInternal(CPL_UNUSED json_o
         }
     }
 
-    if( osFIDColName.size() > 0 )
+    if( !osFIDColName.empty() )
     {
         osBaseSQL = "SELECT ";
         osBaseSQL += OGRAMIGOCLOUDEscapeIdentifier(osFIDColName);
     }
     for(int i=0; i<poFeatureDefn->GetGeomFieldCount(); i++)
     {
-        if( osBaseSQL.size() == 0 )
+        if( osBaseSQL.empty() )
             osBaseSQL = "SELECT ";
         else
             osBaseSQL += ", ";
@@ -198,13 +198,13 @@ OGRFeatureDefn * OGRAmigoCloudTableLayer::GetLayerDefnInternal(CPL_UNUSED json_o
     }
     for(int i=0; i<poFeatureDefn->GetFieldCount(); i++)
     {
-        if( osBaseSQL.size() == 0 )
+        if( osBaseSQL.empty() )
             osBaseSQL = "SELECT ";
         else
             osBaseSQL += ", ";
         osBaseSQL += OGRAMIGOCLOUDEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
     }
-    if( osBaseSQL.size() == 0 )
+    if( osBaseSQL.empty() )
         osBaseSQL = "SELECT *";
     osBaseSQL += " FROM ";
     osBaseSQL += OGRAMIGOCLOUDEscapeIdentifier(osTableName);
@@ -220,15 +220,15 @@ OGRFeatureDefn * OGRAmigoCloudTableLayer::GetLayerDefnInternal(CPL_UNUSED json_o
 
 json_object* OGRAmigoCloudTableLayer::FetchNewFeatures(GIntBig iNextIn)
 {
-    if( osFIDColName.size() > 0 )
+    if( !osFIDColName.empty() )
     {
         CPLString osSQL;
 
-        if(osWHERE.size() > 0)
+        if(!osWHERE.empty())
         {
             osSQL.Printf("%s WHERE %s ",
                          osSELECTWithoutWHERE.c_str(),
-                         (osWHERE.size() > 0) ? CPLSPrintf("%s", osWHERE.c_str()) : "");
+                         (!osWHERE.empty()) ? CPLSPrintf("%s", osWHERE.c_str()) : "");
         } else
         {
             osSQL.Printf("%s", osSELECTWithoutWHERE.c_str());
@@ -319,7 +319,7 @@ void OGRAmigoCloudTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * po
 void OGRAmigoCloudTableLayer::FlushDeferredInsert()
 
 {
-    if(vsDeferredInsertChangesets.size()==0)
+    if(vsDeferredInsertChangesets.empty())
         return;
 
     std::stringstream url;
@@ -378,7 +378,7 @@ OGRErr OGRAmigoCloudTableLayer::CreateField( OGRFieldDefn *poFieldIn,
         osSQL.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
                     OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str(),
                     OGRAMIGOCLOUDEscapeIdentifier(oField.GetNameRef()).c_str(),
-                    OGRPGCommonLayerGetType(oField, FALSE, TRUE).c_str() );
+                    OGRPGCommonLayerGetType(oField, false, true).c_str() );
         if( !oField.IsNullable() )
             osSQL += " NOT NULL";
         if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
@@ -405,8 +405,6 @@ OGRErr OGRAmigoCloudTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 OGRErr OGRAmigoCloudTableLayer::ICreateFeature( OGRFeature *poFeature )
 
 {
-    int i;
-
     if( bDeferredCreation )
     {
         if( RunDeferredCreationIfNecessary() != OGRERR_NONE )
@@ -422,7 +420,6 @@ OGRErr OGRAmigoCloudTableLayer::ICreateFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-
     std::stringstream record;
 
     record << "{\"new\":{";
@@ -430,7 +427,7 @@ OGRErr OGRAmigoCloudTableLayer::ICreateFeature( OGRFeature *poFeature )
     int counter=0;
 
     // Add geometry field
-    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+    for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
     {
         if( poFeature->GetGeomFieldRef(i) == NULL )
             continue;
@@ -446,7 +443,7 @@ OGRErr OGRAmigoCloudTableLayer::ICreateFeature( OGRFeature *poFeature )
         int nSRID = poGeomFieldDefn->nSRID;
         if( nSRID == 0 )
             nSRID = 4326;
-        char* pszEWKB;
+        char* pszEWKB = NULL;
         if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon &&
             wkbFlatten(GetGeomType()) == wkbMultiPolygon )
         {
@@ -466,7 +463,7 @@ OGRErr OGRAmigoCloudTableLayer::ICreateFeature( OGRFeature *poFeature )
     std::string amigo_id_value;
 
     // Add non-geometry field
-    for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         std::string name = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
         std::string value = poFeature->GetFieldAsString(i);
@@ -476,13 +473,15 @@ OGRErr OGRAmigoCloudTableLayer::ICreateFeature( OGRFeature *poFeature )
             amigo_id_value = value;
             continue;
         }
+        if( !poFeature->IsFieldSet(i) )
+            continue;
 
         if(counter > 0)
             record << ",";
 
         record << OGRAMIGOCLOUDEscapeIdentifier(name.c_str()) << ":";
 
-        if(!value.empty())
+        if( !poFeature->IsFieldNull(i) )
         {
             OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
             if( eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime )
@@ -521,7 +520,6 @@ OGRErr OGRAmigoCloudTableLayer::ICreateFeature( OGRFeature *poFeature )
 OGRErr OGRAmigoCloudTableLayer::ISetFeature( OGRFeature *poFeature )
 
 {
-    int i;
     OGRErr eRet = OGRERR_FAILURE;
 
     if( bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
@@ -544,7 +542,6 @@ OGRErr OGRAmigoCloudTableLayer::ISetFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-
     std::map<GIntBig, OGRAmigoCloudFID>::iterator it = mFIDs.find( poFeature->GetFID() );
     if(it!=mFIDs.end())
     {
@@ -552,18 +549,21 @@ OGRErr OGRAmigoCloudTableLayer::ISetFeature( OGRFeature *poFeature )
 
         CPLString osSQL;
         osSQL.Printf("UPDATE %s SET ", OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str());
-        int bMustComma = FALSE;
-        for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+        bool bMustComma = false;
+        for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
         {
-            if(bMustComma)
+            if( !poFeature->IsFieldSet(i) )
+                continue;
+
+            if( bMustComma )
                 osSQL += ", ";
             else
-                bMustComma = TRUE;
+                bMustComma = true;
 
             osSQL += OGRAMIGOCLOUDEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
             osSQL += " = ";
 
-            if(!poFeature->IsFieldSet(i))
+            if(poFeature->IsFieldNull(i))
             {
                 osSQL += "NULL";
             }
@@ -586,12 +586,12 @@ OGRErr OGRAmigoCloudTableLayer::ISetFeature( OGRFeature *poFeature )
             }
         }
 
-        for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+        for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
         {
-            if(bMustComma)
+            if( bMustComma )
                 osSQL += ", ";
             else
-                bMustComma = TRUE;
+                bMustComma = true;
 
             osSQL += OGRAMIGOCLOUDEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
             osSQL += " = ";
@@ -616,22 +616,22 @@ OGRErr OGRAmigoCloudTableLayer::ISetFeature( OGRFeature *poFeature )
             }
         }
 
+        if( !bMustComma ) // nothing to do
+            return OGRERR_NONE;
 
         osSQL += CPLSPrintf(" WHERE %s = '%s'",
                             OGRAMIGOCLOUDEscapeIdentifier(osFIDColName).c_str(),
                             aFID.osAmigoId.c_str());
 
-
         std::stringstream changeset;
         changeset << "{\"query\": \"" << json_encode(osSQL) << "\"}";
         std::stringstream url;
         url << std::string(poDS->GetAPIURL()) << "/users/0/projects/" + std::string(poDS->GetProjetcId()) + "/sql";
         json_object *poObj = poDS->RunPOST(url.str().c_str(), changeset.str().c_str());
 
-
         if(poObj != NULL)
         {
-            json_object *poTotalRows = json_object_object_get(poObj, "total_rows");
+            json_object *poTotalRows = CPL_json_object_object_get(poObj, "total_rows");
             if(poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int)
             {
                 int nTotalRows = json_object_get_int(poTotalRows);
@@ -670,7 +670,7 @@ OGRErr OGRAmigoCloudTableLayer::DeleteFeature( GIntBig nFID )
         return OGRERR_FAILURE;
     }
 
-    if( osFIDColName.size() == 0 )
+    if( osFIDColName.empty() )
         return OGRERR_FAILURE;
 
     std::map<GIntBig, OGRAmigoCloudFID>::iterator it = mFIDs.find(nFID);
@@ -739,7 +739,7 @@ void OGRAmigoCloudTableLayer::BuildWhere()
 
         char szBox3D_1[128];
         char szBox3D_2[128];
-        char* pszComma;
+        char* pszComma = NULL;
 
         CPLsnprintf(szBox3D_1, sizeof(szBox3D_1), "%.18g %.18g", sEnvelope.MinX, sEnvelope.MinY);
         while((pszComma = strchr(szBox3D_1, ',')) != NULL)
@@ -752,17 +752,17 @@ void OGRAmigoCloudTableLayer::BuildWhere()
                        szBox3D_1, szBox3D_2 );
     }
 
-    if( strlen(osQuery) > 0 )
+    if( !osQuery.empty() )
     {
-        if( osWHERE.size() > 0 )
+        if( !osWHERE.empty() )
             osWHERE += " AND ";
         osWHERE += osQuery;
     }
 
-    if( osFIDColName.size() == 0 )
+    if( osFIDColName.empty() )
     {
         osBaseSQL = osSELECTWithoutWHERE;
-        if( osWHERE.size() > 0 )
+        if( !osWHERE.empty() )
         {
             osBaseSQL += " WHERE ";
             osBaseSQL += osWHERE;
@@ -783,7 +783,7 @@ OGRFeature* OGRAmigoCloudTableLayer::GetFeature( GIntBig nFeatureId )
 
     GetLayerDefn();
 
-    if( osFIDColName.size() == 0 )
+    if( osFIDColName.empty() )
         return OGRAmigoCloudLayer::GetFeature(nFeatureId);
 
     CPLString osSQL = osSELECTWithoutWHERE;
@@ -822,7 +822,7 @@ GIntBig OGRAmigoCloudTableLayer::GetFeatureCount(int bForce)
 
     CPLString osSQL(CPLSPrintf("SELECT COUNT(*) FROM %s",
                                OGRAMIGOCLOUDEscapeIdentifier(osTableName).c_str()));
-    if( osWHERE.size() > 0 )
+    if( !osWHERE.empty() )
     {
         osSQL += " WHERE ";
         osSQL += osWHERE;
@@ -837,7 +837,7 @@ GIntBig OGRAmigoCloudTableLayer::GetFeatureCount(int bForce)
         return OGRAmigoCloudLayer::GetFeatureCount(bForce);
     }
 
-    json_object* poCount = json_object_object_get(poRowObj, "count");
+    json_object* poCount = CPL_json_object_object_get(poRowObj, "count");
     if( poCount == NULL || json_object_get_type(poCount) != json_type_int )
     {
         json_object_put(poObj);
@@ -889,7 +889,7 @@ OGRErr OGRAmigoCloudTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent
     json_object* poRowObj = OGRAMIGOCLOUDGetSingleRow(poObj);
     if( poRowObj != NULL )
     {
-        json_object* poExtent = json_object_object_get(poRowObj, "st_extent");
+        json_object* poExtent = CPL_json_object_object_get(poRowObj, "st_extent");
         if( poExtent != NULL && json_object_get_type(poExtent) == json_type_string )
         {
             const char* pszBox = json_object_get_string(poExtent);
@@ -967,7 +967,7 @@ int OGRAmigoCloudTableLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap, OLCRandomRead) )
     {
         GetLayerDefn();
-        return osFIDColName.size() != 0;
+        return !osFIDColName.empty();
     }
 
     if(
@@ -1081,7 +1081,7 @@ bool OGRAmigoCloudTableLayer::IsDatasetExists()
         int type = json_object_get_type(result);
         if(type == json_type_object)
         {
-            json_object *poId = json_object_object_get(result, "id");
+            json_object *poId = CPL_json_object_object_get(result, "id");
             if(poId != NULL)
             {
                 json_object_put(result);
@@ -1092,7 +1092,7 @@ bool OGRAmigoCloudTableLayer::IsDatasetExists()
     }
 
     // Sleep 3 sec
-	CPLSleep(3);
+    CPLSleep(3);
 
     return false;
 }
@@ -1173,7 +1173,7 @@ OGRErr OGRAmigoCloudTableLayer::RunDeferredCreationIfNecessary()
     {
         if(json_object_get_type(result) == json_type_object)
         {
-            json_object *poId = json_object_object_get(result, "id");
+            json_object *poId = CPL_json_object_object_get(result, "id");
             if(poId!=NULL)
             {
                 osTableName = CPLString("dataset_") + json_object_to_json_string(poId);
diff --git a/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h b/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
index 535dd09..d833cb6 100644
--- a/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
+++ b/ogr/ogrsf_frmts/arcgen/ogr_arcgen.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_arcgen.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogr_arcgen.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Definition of classes for OGR .arcgen driver.
@@ -41,7 +41,7 @@ class OGRARCGENLayer : public OGRLayer
     OGRFeatureDefn*    poFeatureDefn;
 
     VSILFILE*          fp;
-    int                bEOF;
+    bool               bEOF;
 
     int                nNextFID;
 
@@ -50,15 +50,14 @@ class OGRARCGENLayer : public OGRLayer
   public:
                         OGRARCGENLayer(const char* pszFilename,
                                     VSILFILE* fp, OGRwkbGeometryType eType);
-                        ~OGRARCGENLayer();
+                        virtual ~OGRARCGENLayer();
 
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -74,16 +73,16 @@ class OGRARCGENDataSource : public OGRDataSource
 
   public:
                         OGRARCGENDataSource();
-                        ~OGRARCGENDataSource();
+               virtual ~OGRARCGENDataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_ARCGEN_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
index cbb010d..1f11732 100644
--- a/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgendatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ograrcgendatasource.cpp 32119 2015-12-11 05:47:58Z goatbar $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Implements OGRARCGENDataSource class
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ograrcgendatasource.cpp 32119 2015-12-11 05:47:58Z goatbar $");
+CPL_CVSID("$Id: ograrcgendatasource.cpp 35273 2016-09-01 15:39:56Z goatbar $");
 
 /************************************************************************/
 /*                          OGRARCGENDataSource()                          */
@@ -154,9 +153,9 @@ int OGRARCGENDataSource::Open( const char * pszFilename )
         eType = wkbUnknown;
         CPLString osFirstX, osFirstY;
         CPLString osLastX, osLastY;
-        int bIs3D = FALSE;
-        const char* pszLine;
-        while((pszLine = CPLReadLine2L(fp,256,NULL)) != NULL)
+        bool bIs3D = false;
+        const char* pszLine = NULL;
+        while( (pszLine = CPLReadLine2L(fp,256,NULL)) != NULL )
         {
             nLineNumber ++;
             if (nLineNumber == 2)
@@ -166,7 +165,7 @@ int OGRARCGENDataSource::Open( const char * pszFilename )
                 if (nTokens == 2 || nTokens == 3)
                 {
                     if (nTokens == 3)
-                        bIs3D = TRUE;
+                        bIs3D = true;
                     osFirstX = papszTokens[0];
                     osFirstY = papszTokens[1];
                 }
@@ -180,9 +179,9 @@ int OGRARCGENDataSource::Open( const char * pszFilename )
                 {
                     if (osFirstX.compare(osLastX) == 0 &&
                         osFirstY.compare(osLastY) == 0)
-                        eType = (bIs3D) ? wkbPolygon25D : wkbPolygon;
+                        eType = bIs3D ? wkbPolygon25D : wkbPolygon;
                     else
-                        eType = (bIs3D) ? wkbLineString25D : wkbLineString;
+                        eType = bIs3D ? wkbLineString25D : wkbLineString;
                     break;
                 }
 
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
index 0d980f9..25e488e 100644
--- a/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgendriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ograrcgendriver.cpp 32119 2015-12-11 05:47:58Z goatbar $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Implements OGRARCGENDriver.
@@ -30,11 +29,10 @@
 #include "ogr_arcgen.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ograrcgendriver.cpp 32119 2015-12-11 05:47:58Z goatbar $");
+CPL_CVSID("$Id: ograrcgendriver.cpp 35903 2016-10-24 12:09:43Z goatbar $");
 
 extern "C" void RegisterOGRARCGEN();
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -53,7 +51,7 @@ static GDALDataset *OGRARCGENDriverOpen( GDALOpenInfo* poOpenInfo )
     bool bFoundEOL = false;
     char* szFirstLine
         = CPLStrdup(reinterpret_cast<char *>( poOpenInfo->pabyHeader ) );
-    for(int i=0;szFirstLine[i] != '\0';i++)
+    for( int i = 0; szFirstLine[i] != '\0'; i++ )
     {
         if (szFirstLine[i] == '\n' || szFirstLine[i] == '\r')
         {
@@ -126,4 +124,3 @@ void RegisterOGRARCGEN()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp b/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
index ea3c79a..30575ef 100644
--- a/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
+++ b/ogr/ogrsf_frmts/arcgen/ograrcgenlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ograrcgenlayer.cpp 32330 2015-12-20 14:24:33Z rouault $
  *
  * Project:  Arc/Info Generate Translator
  * Purpose:  Implements OGRARCGENLayer class.
@@ -33,7 +32,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ograrcgenlayer.cpp 32330 2015-12-20 14:24:33Z rouault $");
+CPL_CVSID("$Id: ograrcgenlayer.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                            OGRARCGENLayer()                             */
@@ -43,7 +42,7 @@ OGRARCGENLayer::OGRARCGENLayer( const char* pszFilename,
                                 VSILFILE* fpIn, OGRwkbGeometryType eType ) :
     poFeatureDefn(NULL),
     fp(fpIn),
-    bEOF(FALSE),
+    bEOF(false),
     nNextFID(0)
 {
     poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
@@ -67,7 +66,6 @@ OGRARCGENLayer::~OGRARCGENLayer()
     VSIFCloseL( fp );
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -76,11 +74,10 @@ void OGRARCGENLayer::ResetReading()
 
 {
     nNextFID = 0;
-    bEOF = FALSE;
+    bEOF = false;
     VSIFSeekL( fp, 0, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -123,7 +120,7 @@ OGRFeature *OGRARCGENLayer::GetNextRawFeature()
             const char* pszLine = CPLReadLine2L(fp,256,NULL);
             if (pszLine == NULL || EQUAL(pszLine, "END"))
             {
-                bEOF = TRUE;
+                bEOF = true;
                 return NULL;
             }
             char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
@@ -162,7 +159,7 @@ OGRFeature *OGRARCGENLayer::GetNextRawFeature()
 
         if (EQUAL(pszLine, "END"))
         {
-            if (osID.size() == 0)
+            if (osID.empty())
                 break;
 
             OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
@@ -181,7 +178,7 @@ OGRFeature *OGRARCGENLayer::GetNextRawFeature()
 
         char** papszTokens = CSLTokenizeString2( pszLine, " ,", 0 );
         int nTokens = CSLCount(papszTokens);
-        if (osID.size() == 0)
+        if (osID.empty())
         {
             if (nTokens >= 1)
                 osID = papszTokens[0];
@@ -213,7 +210,7 @@ OGRFeature *OGRARCGENLayer::GetNextRawFeature()
         CSLDestroy(papszTokens);
     }
 
-    bEOF = TRUE;
+    bEOF = true;
     delete poLS;
     return NULL;
 }
diff --git a/ogr/ogrsf_frmts/arcobjects/GNUmakefile b/ogr/ogrsf_frmts/arcobjects/GNUmakefile
index 83f9633..630c4f4 100644
--- a/ogr/ogrsf_frmts/arcobjects/GNUmakefile
+++ b/ogr/ogrsf_frmts/arcobjects/GNUmakefile
@@ -1,16 +1,16 @@
-
-
-include ../../../GDALmake.opt
-
-OBJ	=	aodriver.o aoatasource.o aolayer.o
-
-CPPFLAGS	:=	 $(AO_INC) $(CPPFLAGS)
-
-default:	$(O_OBJ:.o=.$(OBJ_EXT))
-
-clean:
-	rm -f *.o $(O_OBJ)
-
-$(O_OBJ):	ogr_ao.h
-
-install-obj:    $(O_OBJ:.o=.$(OBJ_EXT)) 
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	aodriver.o aoatasource.o aolayer.o
+
+CPPFLAGS	:=	 $(AO_INC) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_ao.h
+
+install-obj:    $(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/ogr/ogrsf_frmts/arcobjects/aodatasource.cpp b/ogr/ogrsf_frmts/arcobjects/aodatasource.cpp
index 7e2c58d..743ca14 100644
--- a/ogr/ogrsf_frmts/arcobjects/aodatasource.cpp
+++ b/ogr/ogrsf_frmts/arcobjects/aodatasource.cpp
@@ -1,220 +1,217 @@
-/******************************************************************************
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements ArcObjects OGR Datasource.
- * Author:   Ragi Yaser Burhum, ragi at burhum.com
- *
- ******************************************************************************
- * Copyright (c) 2009, Ragi Yaser Burhum
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_ao.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "gdal.h"
-#include "aoutils.h"
-
-
-/************************************************************************/
-/*                          AODataSource()                           */
-/************************************************************************/
-
-AODataSource::AODataSource():
-OGRDataSource(),
-m_pszName(0)
-{
-}
-
-/************************************************************************/
-/*                          ~AODataSource()                          */
-/************************************************************************/
-
-AODataSource::~AODataSource()
-{   
-    CPLFree( m_pszName );
-
-    size_t count = m_layers.size();
-    for(size_t i = 0; i < count; ++i )
-        delete m_layers[i];
-}
-
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-int AODataSource::Open(IWorkspace* pWorkspace, const char * pszNewName, int bUpdate )
-{
-    CPLAssert( m_nLayers == 0 );
-
-    if (bUpdate)
-    {
-      // Start Editing?
-    }
-
-    m_pszName = CPLStrdup( pszNewName );
-    
-    m_ipWorkspace = pWorkspace;
-
-    HRESULT hr;
-
-    // Anything will be fetched
-    IEnumDatasetPtr ipEnumDataset;
-
-    if (FAILED(hr = m_ipWorkspace->get_Datasets(esriDTAny, &ipEnumDataset)))
-    {
-      return AOErr(hr, "Failed Opening Workspace Layers");
-    }
-
-
-    return LoadLayers(ipEnumDataset);
-}
-
-/************************************************************************/
-/*                          LoadLayers()                                */
-/************************************************************************/
-
-bool AODataSource::LoadLayers(IEnumDataset* pEnumDataset)
-{
-  HRESULT hr;
-
-  pEnumDataset->Reset();
-
-  IDatasetPtr ipDataset;
-
-  bool errEncountered = false;
-
-  while ((S_OK == pEnumDataset->Next(&ipDataset)) && !(ipDataset == NULL))
-  {
-    IFeatureDatasetPtr ipFD = ipDataset;
-    if (!(ipFD == NULL))
-    {
-      //We are dealing with a FeatureDataset, need to get
-      IEnumDatasetPtr ipEnumDatasetSubset;
-      if (FAILED(hr = ipFD->get_Subsets(&ipEnumDatasetSubset)))
-      {
-        AOErr(hr, "Failed getting dataset subsets");
-        errEncountered = true;
-        continue; //skipping
-      }
-
-      if (LoadLayers(ipEnumDatasetSubset) == false)
-        errEncountered = true;
-
-      continue;
-    }
-
-    IFeatureClassPtr ipFC = ipDataset;
-
-    if (ipFC == NULL)
-      continue; //skip
-
-    AOLayer* pLayer = new AOLayer;
-    
-    ITablePtr ipTable = ipFC;
-
-    if (!pLayer->Initialize(ipTable))
-    {
-      errEncountered = true;
-      continue;
-    }
-
-    m_layers.push_back(pLayer);
-
-  }
-
-  if (errEncountered && m_layers.size() == 0)
-    return false; //all of the ones we tried had errors
-  else
-    return true; //at least one worked
-}
-
-
-/************************************************************************/
-/*                            DeleteLayer()                             */
-/************************************************************************/
-
-OGRErr AODataSource::DeleteLayer( int iLayer )
-{
-  if( iLayer < 0 || iLayer >= static_cast<int>(m_layers.size()) )
-    return OGRERR_FAILURE;
-
-  // Fetch ArObject Table before deleting OGR layer object
-
-  ITablePtr ipTable;
-  m_layers[iLayer]->GetTable(&ipTable);
-
-  std::string name = m_layers[iLayer]->GetLayerDefn()->GetName();
-
-  // delete OGR layer
-  delete m_layers[iLayer];
-
-  m_layers.erase(m_layers.begin() + iLayer);
-
-  IDatasetPtr ipDataset = ipTable;
-
-  HRESULT hr;
-  
-  if (FAILED(hr = ipDataset->Delete()))
-  {
-    CPLError( CE_Warning, CPLE_AppDefined, "%s was not deleted however it has been closed", name.c_str());
-    AOErr(hr, "Failed deleting dataset");
-   
-    return OGRERR_FAILURE;
-  }
-  else
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int AODataSource::TestCapability( const char * pszCap )
-{
-  /*
-    if( EQUAL(pszCap,ODsCCreateLayer) && bDSUpdate )
-        return TRUE;
-    else if( EQUAL(pszCap,ODsCDeleteLayer) && bDSUpdate )
-        return TRUE;
-    else
-        return FALSE;
-  */
-
-  if(EQUAL(pszCap,ODsCDeleteLayer))
-    return TRUE;
-  else
-    return FALSE;
-}
-//
-/************************************************************************/
-/*                              GetLayer()                              */
-/************************************************************************/
-
-OGRLayer *AODataSource::GetLayer( int iLayer )
-{ 
-  int count = static_cast<int>(m_layers.size());
-
-  if( iLayer < 0 || iLayer >= count )
-    return NULL;
-  else
-    return m_layers[iLayer];
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements ArcObjects OGR Datasource.
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Ragi Yaser Burhum
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_ao.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal.h"
+#include "aoutils.h"
+
+CPL_CVSID("$Id: aodatasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+/************************************************************************/
+/*                          AODataSource()                           */
+/************************************************************************/
+
+AODataSource::AODataSource():
+OGRDataSource(),
+m_pszName(0)
+{
+}
+
+/************************************************************************/
+/*                          ~AODataSource()                          */
+/************************************************************************/
+
+AODataSource::~AODataSource()
+{
+    CPLFree( m_pszName );
+
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+        delete m_layers[i];
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int AODataSource::Open(IWorkspace* pWorkspace, const char * pszNewName, int bUpdate )
+{
+    CPLAssert( m_nLayers == 0 );
+
+    if (bUpdate)
+    {
+      // Start Editing?
+    }
+
+    m_pszName = CPLStrdup( pszNewName );
+
+    m_ipWorkspace = pWorkspace;
+
+    HRESULT hr;
+
+    // Anything will be fetched
+    IEnumDatasetPtr ipEnumDataset;
+
+    if (FAILED(hr = m_ipWorkspace->get_Datasets(esriDTAny, &ipEnumDataset)))
+    {
+      return AOErr(hr, "Failed Opening Workspace Layers");
+    }
+
+    return LoadLayers(ipEnumDataset);
+}
+
+/************************************************************************/
+/*                          LoadLayers()                                */
+/************************************************************************/
+
+bool AODataSource::LoadLayers(IEnumDataset* pEnumDataset)
+{
+  HRESULT hr;
+
+  pEnumDataset->Reset();
+
+  IDatasetPtr ipDataset;
+
+  bool errEncountered = false;
+
+  while ((S_OK == pEnumDataset->Next(&ipDataset)) && !(ipDataset == NULL))
+  {
+    IFeatureDatasetPtr ipFD = ipDataset;
+    if (!(ipFD == NULL))
+    {
+      //We are dealing with a FeatureDataset, need to get
+      IEnumDatasetPtr ipEnumDatasetSubset;
+      if (FAILED(hr = ipFD->get_Subsets(&ipEnumDatasetSubset)))
+      {
+        AOErr(hr, "Failed getting dataset subsets");
+        errEncountered = true;
+        continue; //skipping
+      }
+
+      if (LoadLayers(ipEnumDatasetSubset) == false)
+        errEncountered = true;
+
+      continue;
+    }
+
+    IFeatureClassPtr ipFC = ipDataset;
+
+    if (ipFC == NULL)
+      continue; //skip
+
+    AOLayer* pLayer = new AOLayer;
+
+    ITablePtr ipTable = ipFC;
+
+    if (!pLayer->Initialize(ipTable))
+    {
+      errEncountered = true;
+      continue;
+    }
+
+    m_layers.push_back(pLayer);
+  }
+
+  if (errEncountered && m_layers.empty())
+    return false; //all of the ones we tried had errors
+  else
+    return true; //at least one worked
+}
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+OGRErr AODataSource::DeleteLayer( int iLayer )
+{
+  if( iLayer < 0 || iLayer >= static_cast<int>(m_layers.size()) )
+    return OGRERR_FAILURE;
+
+  // Fetch ArObject Table before deleting OGR layer object
+
+  ITablePtr ipTable;
+  m_layers[iLayer]->GetTable(&ipTable);
+
+  std::string name = m_layers[iLayer]->GetLayerDefn()->GetName();
+
+  // delete OGR layer
+  delete m_layers[iLayer];
+
+  m_layers.erase(m_layers.begin() + iLayer);
+
+  IDatasetPtr ipDataset = ipTable;
+
+  HRESULT hr;
+
+  if (FAILED(hr = ipDataset->Delete()))
+  {
+    CPLError( CE_Warning, CPLE_AppDefined, "%s was not deleted however it has been closed", name.c_str());
+    AOErr(hr, "Failed deleting dataset");
+
+    return OGRERR_FAILURE;
+  }
+  else
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int AODataSource::TestCapability( const char * pszCap )
+{
+  /*
+    if( EQUAL(pszCap,ODsCCreateLayer) && bDSUpdate )
+        return TRUE;
+    else if( EQUAL(pszCap,ODsCDeleteLayer) && bDSUpdate )
+        return TRUE;
+    else
+        return FALSE;
+  */
+
+  if(EQUAL(pszCap,ODsCDeleteLayer))
+    return TRUE;
+  else
+    return FALSE;
+}
+//
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *AODataSource::GetLayer( int iLayer )
+{
+  int count = static_cast<int>(m_layers.size());
+
+  if( iLayer < 0 || iLayer >= count )
+    return NULL;
+  else
+    return m_layers[iLayer];
+}
diff --git a/ogr/ogrsf_frmts/arcobjects/aodriver.cpp b/ogr/ogrsf_frmts/arcobjects/aodriver.cpp
index 34f1337..bde2097 100644
--- a/ogr/ogrsf_frmts/arcobjects/aodriver.cpp
+++ b/ogr/ogrsf_frmts/arcobjects/aodriver.cpp
@@ -1,226 +1,219 @@
-/******************************************************************************
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements ArcObjects OGR driver.
- * Author:   Ragi Yaser Burhum, ragi at burhum.com
- *
- ******************************************************************************
- * Copyright (c) 2009, Ragi Yaser Burhum
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_ao.h"
-#include "cpl_conv.h"
-#include "aoutils.h"
-
-
-/************************************************************************/
-/*                            AODriver()                            */
-/************************************************************************/
-AODriver::AODriver():
-OGRSFDriver(), m_licensedCheckedOut(false), m_productCode(-1), m_initialized(false)
-{
-}
-
-/************************************************************************/
-/*                            ~AODriver()                            */
-/************************************************************************/
-AODriver::~AODriver()
-
-{
-  if (m_initialized)
-  {
-    if (m_licensedCheckedOut)
-      ShutdownDriver();
-
-    ::CoUninitialize();
-  }
-}
-
-bool AODriver::Init()
-{
-  if (m_initialized)
-    return true;
-
-  ::CoInitialize(NULL);
-  m_initialized = true; //need to mark to un-init COM system on destruction
-
-
-  m_licensedCheckedOut = InitializeDriver();
-  if (!m_licensedCheckedOut)
-  {
-    CPLError( CE_Failure, CPLE_AppDefined, "ArcGIS License checkout failed.");
-
-    return false;
-  }
-  else
-  {
-    m_productCode = GetInitedProductCode();
-  }
-
-  return true;
-}
-
-
-/************************************************************************/
-/*                              GetName()                               */
-/************************************************************************/
-
-const char *AODriver::GetName()
-
-{
-  return "ArcObjects";
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-OGRDataSource *AODriver::Open( const char* pszFilename,
-                              int bUpdate )
-
-{
-  // First check if we have to do any work.
-  // In order to avoid all the COM overhead, we are going to check
-  // if we have an AO prefix
-
-  if( !STARTS_WITH_CI(pszFilename, "AO:") )
-    return NULL;
-
-  //OK, it is our turn, let's pay the price
-
-  if (!Init())
-  {
-    return NULL;
-  }
-
-  const char* pInitString = pszFilename + 3; //skip chars
-
-
-  IWorkspacePtr ipWorkspace = NULL;
-  OpenWorkspace(pInitString, &ipWorkspace);
-
-  if (ipWorkspace == NULL)
-    return NULL;
-
-  AODataSource* pDS;
-
-  pDS = new AODataSource();
-
-  if(!pDS->Open( ipWorkspace, pszFilename, bUpdate ) )
-  {
-    delete pDS;
-    return NULL;
-  }
-  else
-    return pDS;
-}
-
-/************************************************************************
-*                     CreateDataSource()                                *
-************************************************************************/
-
-OGRDataSource* AODriver::CreateDataSource( const char * pszName,
-                                           char **papszOptions)
-{
-  return NULL;
-}
-
-
-void AODriver::OpenWorkspace(std::string conn, IWorkspace** ppWorkspace)
-{
-  //If there are any others we want to support in the future, we just need to add them here
-  // http://resources.esri.com/help/9.3/ArcGISDesktop/ArcObjects/esriGeoDatabase/IWorkspaceFactory.htm
-  //
-  //We can also add GUIDS based on licensing code if necessary
-
-  const GUID* pFactories[]=
-  {
-    &CLSID_FileGDBWorkspaceFactory,
-    &CLSID_SdeWorkspaceFactory,
-    &CLSID_AccessWorkspaceFactory
-  };
-
-  CComBSTR connString(conn.c_str()); //not sure if GDAL is sending utf8 or native - check later
-
-  HRESULT hr;
-
-  // try to connect with every factory specified
-  //
-
-  for (int i = 0; i < (sizeof(pFactories)/sizeof(pFactories[0])); ++i)
-  {
-    if (pFactories[i] == NULL) // in case we have conditional factories
-      continue;
-
-    IWorkspaceFactoryPtr ipFactory(*pFactories[i]);
-
-    VARIANT_BOOL isWorkspace = VARIANT_FALSE;
-
-    if (FAILED(hr = ipFactory->IsWorkspace(connString, &isWorkspace)) || isWorkspace == VARIANT_FALSE)
-      continue; //try next factory
-
-    IWorkspacePtr ipWorkspace = NULL;
-
-    if (FAILED(hr = ipFactory->OpenFromFile(connString, 0, &ipWorkspace)) || ipWorkspace == NULL)
-      continue;
-
-    *ppWorkspace = ipWorkspace.Detach();
-
-    return;
-  }
-
-
-  *ppWorkspace = NULL;
-}
-
-/************************************************************************
-*                           TestCapability()                           *
-************************************************************************/
-
-int AODriver::TestCapability( const char * pszCap )
-
-{
-  /*
-  if (EQUAL(pszCap, ODsCCreateLayer) )
-    return FALSE;
-    */
-  if (EQUAL(pszCap, ODsCDeleteLayer) )
-    return TRUE;
-  /*
-  if (EQUAL(pszCap, ODrCCreateDataSource) )
-    return FALSE;
-  */
-
-  return FALSE;
-}
-
-/************************************************************************
-*                           RegisterOGRao()                                 *
-************************************************************************/
-
-void RegisterOGRao()
-
-{
-  if (! GDAL_CHECK_VERSION("OGR AO"))
-    return;
-  OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new AODriver );
-}
-
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements ArcObjects OGR driver.
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Ragi Yaser Burhum
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_ao.h"
+#include "cpl_conv.h"
+#include "aoutils.h"
+
+CPL_CVSID("$Id: aodriver.cpp 35903 2016-10-24 12:09:43Z goatbar $");
+
+/************************************************************************/
+/*                            AODriver()                            */
+/************************************************************************/
+AODriver::AODriver():
+OGRSFDriver(), m_licensedCheckedOut(false), m_productCode(-1), m_initialized(false)
+{
+}
+
+/************************************************************************/
+/*                            ~AODriver()                            */
+/************************************************************************/
+AODriver::~AODriver()
+
+{
+  if (m_initialized)
+  {
+    if (m_licensedCheckedOut)
+      ShutdownDriver();
+
+    ::CoUninitialize();
+  }
+}
+
+bool AODriver::Init()
+{
+  if (m_initialized)
+    return true;
+
+  ::CoInitialize(NULL);
+  m_initialized = true; //need to mark to un-init COM system on destruction
+
+  m_licensedCheckedOut = InitializeDriver();
+  if (!m_licensedCheckedOut)
+  {
+    CPLError( CE_Failure, CPLE_AppDefined, "ArcGIS License checkout failed.");
+
+    return false;
+  }
+  else
+  {
+    m_productCode = GetInitedProductCode();
+  }
+
+  return true;
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *AODriver::GetName()
+
+{
+  return "ArcObjects";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *AODriver::Open( const char* pszFilename,
+                              int bUpdate )
+
+{
+  // First check if we have to do any work.
+  // In order to avoid all the COM overhead, we are going to check
+  // if we have an AO prefix
+
+  if( !STARTS_WITH_CI(pszFilename, "AO:") )
+    return NULL;
+
+  //OK, it is our turn, let's pay the price
+
+  if (!Init())
+  {
+    return NULL;
+  }
+
+  const char* pInitString = pszFilename + 3; //skip chars
+
+  IWorkspacePtr ipWorkspace = NULL;
+  OpenWorkspace(pInitString, &ipWorkspace);
+
+  if (ipWorkspace == NULL)
+    return NULL;
+
+  AODataSource* pDS = new AODataSource();
+
+  if(!pDS->Open( ipWorkspace, pszFilename, bUpdate ) )
+  {
+    delete pDS;
+    return NULL;
+  }
+
+  return pDS;
+}
+
+/************************************************************************
+*                     CreateDataSource()                                *
+************************************************************************/
+
+OGRDataSource* AODriver::CreateDataSource( const char * pszName,
+                                           char **papszOptions)
+{
+  return NULL;
+}
+
+void AODriver::OpenWorkspace(std::string conn, IWorkspace** ppWorkspace)
+{
+  //If there are any others we want to support in the future, we just need to add them here
+  // http://resources.esri.com/help/9.3/ArcGISDesktop/ArcObjects/esriGeoDatabase/IWorkspaceFactory.htm
+  //
+  //We can also add GUIDS based on licensing code if necessary
+
+  const GUID* pFactories[]=
+  {
+    &CLSID_FileGDBWorkspaceFactory,
+    &CLSID_SdeWorkspaceFactory,
+    &CLSID_AccessWorkspaceFactory
+  };
+
+  CComBSTR connString(conn.c_str()); //not sure if GDAL is sending utf8 or native - check later
+
+  HRESULT hr;
+
+  // try to connect with every factory specified
+  //
+
+  for (int i = 0; i < (sizeof(pFactories)/sizeof(pFactories[0])); ++i)
+  {
+    if (pFactories[i] == NULL) // in case we have conditional factories
+      continue;
+
+    IWorkspaceFactoryPtr ipFactory(*pFactories[i]);
+
+    VARIANT_BOOL isWorkspace = VARIANT_FALSE;
+
+    if (FAILED(hr = ipFactory->IsWorkspace(connString, &isWorkspace)) || isWorkspace == VARIANT_FALSE)
+      continue; //try next factory
+
+    IWorkspacePtr ipWorkspace = NULL;
+
+    if (FAILED(hr = ipFactory->OpenFromFile(connString, 0, &ipWorkspace)) || ipWorkspace == NULL)
+      continue;
+
+    *ppWorkspace = ipWorkspace.Detach();
+
+    return;
+  }
+
+  *ppWorkspace = NULL;
+}
+
+/************************************************************************
+*                           TestCapability()                           *
+************************************************************************/
+
+int AODriver::TestCapability( const char * pszCap )
+
+{
+  /*
+  if (EQUAL(pszCap, ODsCCreateLayer) )
+    return FALSE;
+    */
+  if (EQUAL(pszCap, ODsCDeleteLayer) )
+    return TRUE;
+  /*
+  if (EQUAL(pszCap, ODrCCreateDataSource) )
+    return FALSE;
+  */
+
+  return FALSE;
+}
+
+/************************************************************************
+*                           RegisterOGRao()                                 *
+************************************************************************/
+
+void RegisterOGRao()
+
+{
+  if (! GDAL_CHECK_VERSION("OGR AO"))
+    return;
+  OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new AODriver );
+}
diff --git a/ogr/ogrsf_frmts/arcobjects/aolayer.cpp b/ogr/ogrsf_frmts/arcobjects/aolayer.cpp
index d953e16..a700e46 100644
--- a/ogr/ogrsf_frmts/arcobjects/aolayer.cpp
+++ b/ogr/ogrsf_frmts/arcobjects/aolayer.cpp
@@ -1,608 +1,593 @@
-/******************************************************************************
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements ArcObjects OGR layer.
- * Author:   Ragi Yaser Burhum, ragi at burhum.com
- *
- ******************************************************************************
- * Copyright (c) 2009, Ragi Yaser Burhum
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_ao.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "aoutils.h"
-#include <strstream>
-
-/************************************************************************/
-/*                              AOLayer()                               */
-/************************************************************************/
-AOLayer::AOLayer():
-OGRLayer(),m_pFeatureDefn(NULL),m_pSRS(NULL), m_ipQF(CLSID_QueryFilter),
-m_pBuffer(NULL), m_bufferSize(0), m_suppressColumnMappingError(false),m_forceMulti(false)
-{
-}
-
-/************************************************************************/
-/*                            ~AOLayer()                            */
-/************************************************************************/
-
-AOLayer::~AOLayer()
-{
-  if (m_pFeatureDefn)
-    m_pFeatureDefn->Release();
-
-  if (m_pSRS)
-    m_pSRS->Release();
-
-  if (m_pBuffer)
-    delete [] m_pBuffer;
-}
-
-/************************************************************************/
-/*                            Initialize()                            */
-/************************************************************************/
-
-bool AOLayer::Initialize(ITable* pTable)
-{
-  HRESULT hr;
-
-  m_ipTable = pTable;
-
-  CComBSTR temp;
-
-  IDatasetPtr ipDataset = m_ipTable;
-  if (FAILED(hr = ipDataset->get_Name(&temp)))
-    return false;
-
-  m_pFeatureDefn = new OGRFeatureDefn(CW2A(temp)); //Should I "new" an OGR smart pointer - sample says so, but it doesn't seem right
-                                                   //as long as we use the same compiler & settings in both the ogr build and this
-                                                   //driver, we should be OK
-  m_pFeatureDefn->Reference();
-
-  IFeatureClassPtr ipFC = m_ipTable;
-
-  VARIANT_BOOL hasOID = VARIANT_FALSE;
-  ipFC->get_HasOID(&hasOID);
-
-  if (hasOID == VARIANT_TRUE)
-  {
-    ipFC->get_OIDFieldName(&temp);
-    m_strOIDFieldName = CW2A(temp);
-  }
-
-  if (FAILED(hr = ipFC->get_ShapeFieldName(&temp)))
-    return AOErr(hr, "No shape field found!");
-
-  m_strShapeFieldName = CW2A(temp);
-
-  IFieldsPtr ipFields;
-  if (FAILED(hr = ipFC->get_Fields(&ipFields)))
-    return AOErr(hr, "Fields not found!");
-
-  long shapeIndex = -1;
-  if (FAILED(hr = ipFields->FindField(temp, &shapeIndex)))
-    return AOErr(hr, "Shape field not found!");
-
-  IFieldPtr ipShapeField;
-  if (FAILED(hr = ipFields->get_Field(shapeIndex, &ipShapeField)))
-    return false;
-    
-  // Use GeometryDef to set OGR shapetype and Spatial Reference information
-  //
-
-  IGeometryDefPtr ipGeoDef;
-  if (FAILED(hr = ipShapeField->get_GeometryDef(&ipGeoDef)))
-    return false;
-
-  OGRwkbGeometryType ogrGeoType;
-  if (!AOToOGRGeometry(ipGeoDef, &ogrGeoType))
-    return false;
-
-  m_pFeatureDefn->SetGeomType(ogrGeoType);
-
-  if (wkbFlatten(ogrGeoType) == wkbMultiLineString || wkbFlatten(ogrGeoType) == wkbMultiPoint)
-    m_forceMulti = true;
-
-  
-  // Mapping of Spatial Reference will be passive about errors
-  // (it is possible we won't be able to map some ESRI-specific projections)
-
-  esriGeometry::ISpatialReferencePtr ipSR = NULL;
-
-  if (FAILED(hr = ipGeoDef->get_SpatialReference(&ipSR)))
-  {
-    AOErr(hr, "Failed Fetching ESRI spatial reference");
-  }
-  else
-  {
-    if (!AOToOGRSpatialReference(ipSR, &m_pSRS))
-    {
-      //report error, but be passive about it
-      CPLError( CE_Warning, CPLE_AppDefined, "Failed Mapping ESRI Spatial Reference");
-    }
-  }
-
-
-  // Map fields
-  //
-  return AOToOGRFields(ipFields, m_pFeatureDefn, m_OGRFieldToESRIField);
-}
-
-
-
-/************************************************************************/
-/*                            ResetReading()                            */
-/************************************************************************/
-
-void AOLayer::ResetReading()
-{
-  HRESULT hr;
-
-  if (FAILED(hr = m_ipTable->Search(m_ipQF, VARIANT_TRUE, &m_ipCursor)))
-    AOErr(hr, "Error Executing Query");
-
-}
-
-/************************************************************************/
-/*                            GetTable()                            */
-/************************************************************************/
-
-HRESULT AOLayer::GetTable(ITable** ppTable)
-{
-  return m_ipTable.QueryInterface(IID_ITable, ppTable);
-}
-
-
-/************************************************************************/
-/*                         SetSpatialFilter()                           */
-/************************************************************************/
-
-void AOLayer::SetSpatialFilter( OGRGeometry* pOGRGeom )
-{
-  if (pOGRGeom == NULL)
-  {
-    SwitchToAttributeOnlyFilter();
-    return;
-  }
-  else
-  {
-    SwitchToSpatialFilter();
-  }
-
-  esriGeometry::IGeometryPtr ipGeometry = NULL;
-
-  if ((!OGRGeometryToAOGeometry(pOGRGeom, &ipGeometry)) || ipGeometry == NULL)
-  {
-    // Crap! we failed and there is no return error mechanism.
-    // Report Error and dismiss ogr geometry to go back to at least a working
-    // state
-    CPLError( CE_Failure, CPLE_AppDefined, "Could not convert OGR spatial filter geometry to ArcObjecs one. Dismissing spatial filter!");
-
-    SwitchToAttributeOnlyFilter();
-    return;
-  }
-
-  // Set Spatial Reference on AO geometry
-  IGeoDatasetPtr ipGeoDataset = m_ipTable;
-  esriGeometry::ISpatialReferencePtr ipSR = NULL;
-  ipGeoDataset->get_SpatialReference(&ipSR);
-  ipGeometry->putref_SpatialReference(ipSR);
-
-  ISpatialFilterPtr ipSF = m_ipQF; //QI should never fail because we called SwitchToSpatialFilter
-
-  ipSF->putref_Geometry(ipGeometry);
-  
-  ResetReading();
-}
-
-/************************************************************************/
-/*                         SetSpatialFilterRect()                       */
-/************************************************************************/
-
-void AOLayer::SetSpatialFilterRect (double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
-{
-  SwitchToSpatialFilter();
-
-  IGeoDatasetPtr ipGD = m_ipTable;
-  esriGeometry::IEnvelopePtr ipEnvelope(esriGeometry::CLSID_Envelope);
-  esriGeometry::ISpatialReferencePtr ipSR;
-
-  ipGD->get_SpatialReference(&ipSR);
-  ipEnvelope->putref_SpatialReference(ipSR);
-  ipEnvelope->PutCoords(dfMinX, dfMinY, dfMaxX, dfMaxY);
-  
-  ISpatialFilterPtr ipSF(m_ipQF);
-  ipSF->putref_Geometry(ipEnvelope);
-  ipSF->put_SpatialRel(esriSpatialRelIntersects);
-
-}
-
-
-/************************************************************************/
-/*                       SwitchToAttributeOnlyFilter()                  */
-/************************************************************************/
-
-void AOLayer::SwitchToAttributeOnlyFilter()
-{
-  ISpatialFilterPtr ipSF = m_ipQF;
-
-  if (ipSF == NULL)
-    return; //nothing to be done - it is an attribute filter
-
-  //only need to preserve whereclause since it is the only thing we consume in this driver
-  CComBSTR strWhereClause;
-  m_ipQF->get_WhereClause(&strWhereClause);
-
-  m_ipQF.CreateInstance(CLSID_QueryFilter); // will destroy old spatial filter
-  if (strWhereClause.Length() > 0)
-  {
-    m_ipQF->put_WhereClause(strWhereClause);
-  }
-}
-
-/************************************************************************/
-/*                         SwitchToSpatialFilter()                      */
-/************************************************************************/
-
-void AOLayer::SwitchToSpatialFilter()
-{
-  ISpatialFilterPtr ipSF = m_ipQF;
-
-  if (!(ipSF == NULL))
-    return; //nothing to be done it is a spatial filter already
-
-  //only need to preserve whereclause since it is the only thing we consume in this driver
-  CComBSTR strWhereClause;
-  m_ipQF->get_WhereClause(&strWhereClause);
-
-  m_ipQF.CreateInstance(CLSID_SpatialFilter); // will destroy old query filter
-  if (strWhereClause.Length() > 0)
-  {
-    m_ipQF->put_WhereClause(strWhereClause);
-  }
-
-}
-
-/************************************************************************/
-/*                         SetAttributeFilter()                         */
-/************************************************************************/
-
-OGRErr AOLayer::SetAttributeFilter( const char* pszQuery )
-{
-
-  if( pszQuery == NULL )
-  {
-    
-    CComBSTR whereClause(_T(""));
-    m_ipQF->put_WhereClause(whereClause);
-    
-  }
-  else
-  {
-    CComBSTR whereClause(pszQuery);
-    m_ipQF->put_WhereClause(whereClause);
-  }
-
-  ResetReading();
-
-  return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           OGRFeatureFromAORow()                      */
-/************************************************************************/
-
-bool AOLayer::OGRFeatureFromAORow(IRow* pRow, OGRFeature** ppFeature)
-{
-  HRESULT hr;
-
-  OGRFeature* pOutFeature = new OGRFeature(m_pFeatureDefn);
-
-  /////////////////////////////////////////////////////////
-  // Translate OID
-  //
-
-  long oid = -1;
-  if (FAILED(hr = pRow->get_OID(&oid)))
-  {
-    //this should never happen
-    delete pOutFeature;
-    return false;
-  }
-  pOutFeature->SetFID(oid);
-
-  /////////////////////////////////////////////////////////
-  // Translate Geometry
-  //
-
-  IFeaturePtr ipFeature = pRow;
-  esriGeometry::IGeometryPtr ipGeometry = NULL;
-
-  if (FAILED(hr = ipFeature->get_Shape(&ipGeometry)) || ipGeometry == NULL)
-  {
-    delete pOutFeature;
-    return AOErr(hr, "Failed retrieving shape from ArcObjects");
-  }
-
-  OGRGeometry* pOGRGeo = NULL;
-
-  if ((!AOGeometryToOGRGeometry(m_forceMulti, ipGeometry, m_pSRS, m_pBuffer, m_bufferSize, &pOGRGeo)) || pOGRGeo == NULL)
-  {
-    delete pOutFeature;
-    return AOErr(hr, "Failed to translate ArcObjects Geometry to OGR Geometry");
-  }
-
-  pOutFeature->SetGeometryDirectly(pOGRGeo);
-
-
-  //////////////////////////////////////////////////////////
-  // Map fields
-  //
-
-  CComVariant val;
-  size_t mappedFieldCount = m_OGRFieldToESRIField.size();
-
-  bool foundBadColumn = false;
-
-  for (size_t i = 0; i < mappedFieldCount; ++i)
-  {
-    long index = m_OGRFieldToESRIField[i];
-
-    if (FAILED(hr = pRow->get_Value(index, &val)))
-    {
-      // this should not happen
-      return AOErr(hr, "Failed retrieving row value");
-    }
-
-    if (val.vt == VT_NULL)
-    {
-      continue; //leave as unset
-    }
-
-    // 
-    // NOTE: This switch statement needs to be kept in sync with AOToOGRGeometry
-    //       since we are only checking for types we mapped in that utility function
-
-    switch (m_pFeatureDefn->GetFieldDefn(i)->GetType())
-    {
-
-    case OFTInteger:
-      {
-        val.ChangeType(VT_I4);
-        pOutFeature->SetField(i, val.intVal);
-      }
-      break;
-
-    case OFTReal:
-      {
-        val.ChangeType(VT_R8);
-        pOutFeature->SetField(i, val.dblVal);
-      }
-      break;
-    case OFTString:
-      {
-        val.ChangeType(VT_BSTR);
-        pOutFeature->SetField(i, CW2A(val.bstrVal));
-      }
-      break;
-
-    /* TODO: Need to get test dataset to implement these leave it as NULL for now
-    case OFTBinary:
-      {
-      // Access as SafeArray with SafeArrayAccessData perhaps?
-      }
-      break;
-    case OFTDateTime:
-      {
-      // Examine test data to figure out how to extract that
-      }
-      break;
-      */
-    default:
-      {
-        if (!m_suppressColumnMappingError)
-        {
-          foundBadColumn = true;
-          CPLError( CE_Warning, CPLE_AppDefined, "Row id: %d col:%d has unhandled col type (%d). Setting to NULL.", oid, i, m_pFeatureDefn->GetFieldDefn(i)->GetType());
-        }
-      }
-    }
-  }
-  
-  if (foundBadColumn)
-    m_suppressColumnMappingError = true;
-  
-
-  *ppFeature = pOutFeature;
-
-  return true;
-}
-
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRFeature* AOLayer::GetNextFeature()
-{
-  while (1) //want to skip errors
-  {
-    if (m_ipCursor == NULL)
-      return NULL;
-
-    HRESULT hr;
-
-    IRowPtr ipRow;
-
-    if (FAILED(hr = m_ipCursor->NextRow(&ipRow)))
-    {
-      AOErr(hr, "Failed fetching features");
-      return NULL;
-    }
-
-    if (hr == S_FALSE || ipRow == NULL)
-    {
-      // It's OK, we are done fetching
-      return NULL;
-    }
-
-    OGRFeature* pOGRFeature = NULL;
-
-    if (!OGRFeatureFromAORow(ipRow,  &pOGRFeature))
-    {
-      long oid = -1;
-      ipRow->get_OID(&oid);
-
-      std::strstream msg;
-      msg << "Failed translating ArcObjects row [" << oid << "] to OGR Feature";
-
-      AOErr(hr, msg.str());
-      
-      //return NULL;
-      continue; //skip feature
-    }
-
-    return pOGRFeature;
-  }
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *AOLayer::GetFeature( GIntBig oid )
-{
-  HRESULT hr;
-
-  IRowPtr ipRow;
-  if (FAILED(hr = m_ipTable->GetRow(oid, &ipRow)))
-  {
-    AOErr(hr, "Failed fetching row");
-    return NULL;
-  }
-
-  OGRFeature* pOGRFeature = NULL;
-
-  if (!OGRFeatureFromAORow(ipRow,  &pOGRFeature))
-  {
-    AOErr(hr, "Failed translating ArcObjects row to OGR Feature");
-    return NULL;
-  }
-
-  return pOGRFeature;
-}
-
-
-/************************************************************************/
-/*                          GetFeatureCount()                           */
-/************************************************************************/
-
-GIntBig AOLayer::GetFeatureCount( int bForce )
-{
-  HRESULT hr;
-
-  long rowCount = -1;
-
-  if (FAILED(hr = m_ipTable->RowCount(m_ipQF, &rowCount)))
-  {
-    AOErr(hr, "Failed calculating row count");
-
-    return rowCount;
-  }
-
-  return static_cast<int>(rowCount);
-}
-
-
-
-/************************************************************************/
-/*                             GetExtent()                              */
-/************************************************************************/
-
-OGRErr AOLayer::GetExtent (OGREnvelope* psExtent, int bForce)
-{
-
-  if (bForce) 
-  {
-    return OGRLayer::GetExtent( psExtent, bForce );
-  }
-
-  HRESULT hr;
-
-  IGeoDatasetPtr ipGeoDataset = m_ipTable;
-  
-  esriGeometry::IEnvelopePtr ipEnv = NULL;
-  if (FAILED(hr = ipGeoDataset->get_Extent(&ipEnv)) || ipEnv == NULL)
-  {
-    AOErr(hr, "Failed retrieving extent");
-    
-    return OGRERR_FAILURE;
-  }
-
-  double temp;
-
-  ipEnv->get_XMin(&temp);
-  psExtent->MinX = temp;
-
-  ipEnv->get_YMin(&temp);
-  psExtent->MinY = temp;
-
-  ipEnv->get_XMax(&temp);
-  psExtent->MaxX = temp;
-
-  ipEnv->get_YMax(&temp);
-  psExtent->MaxY = temp;
-
-  return OGRERR_NONE;
-}
-
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int AOLayer::TestCapability( const char* pszCap )
-{
-    if (EQUAL(pszCap,OLCRandomRead))
-        return TRUE;
-
-    else if (EQUAL(pszCap,OLCFastFeatureCount)) 
-        return TRUE;
-
-    else if (EQUAL(pszCap,OLCFastSpatialFilter))
-        return TRUE;
-
-    else if (EQUAL(pszCap,OLCFastGetExtent))
-        return TRUE;
-    
-    // Have not implemented this yet
-    else if (EQUAL(pszCap,OLCCreateField))
-        return FALSE;
-
-    // Have not implemented this yet
-    else if (EQUAL(pszCap,OLCSequentialWrite)
-          || EQUAL(pszCap,OLCRandomWrite))
-        return FALSE;
-
-    else 
-        return FALSE;
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements ArcObjects OGR layer.
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Ragi Yaser Burhum
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_ao.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "aoutils.h"
+#include <strstream>
+
+CPL_CVSID("$Id: aolayer.cpp 36332 2016-11-20 15:19:39Z rouault $");
+
+/************************************************************************/
+/*                              AOLayer()                               */
+/************************************************************************/
+AOLayer::AOLayer():
+OGRLayer(),m_pFeatureDefn(NULL),m_pSRS(NULL), m_ipQF(CLSID_QueryFilter),
+m_pBuffer(NULL), m_bufferSize(0), m_suppressColumnMappingError(false),m_forceMulti(false)
+{
+}
+
+/************************************************************************/
+/*                            ~AOLayer()                            */
+/************************************************************************/
+
+AOLayer::~AOLayer()
+{
+  if (m_pFeatureDefn)
+    m_pFeatureDefn->Release();
+
+  if (m_pSRS)
+    m_pSRS->Release();
+
+  if (m_pBuffer)
+    delete [] m_pBuffer;
+}
+
+/************************************************************************/
+/*                            Initialize()                            */
+/************************************************************************/
+
+bool AOLayer::Initialize(ITable* pTable)
+{
+  HRESULT hr;
+
+  m_ipTable = pTable;
+
+  CComBSTR temp;
+
+  IDatasetPtr ipDataset = m_ipTable;
+  if (FAILED(hr = ipDataset->get_Name(&temp)))
+    return false;
+
+  m_pFeatureDefn = new OGRFeatureDefn(CW2A(temp)); //Should I "new" an OGR smart pointer - sample says so, but it doesn't seem right
+                                                   //as long as we use the same compiler & settings in both the ogr build and this
+                                                   //driver, we should be OK
+  m_pFeatureDefn->Reference();
+
+  IFeatureClassPtr ipFC = m_ipTable;
+
+  VARIANT_BOOL hasOID = VARIANT_FALSE;
+  ipFC->get_HasOID(&hasOID);
+
+  if (hasOID == VARIANT_TRUE)
+  {
+    ipFC->get_OIDFieldName(&temp);
+    m_strOIDFieldName = CW2A(temp);
+  }
+
+  if (FAILED(hr = ipFC->get_ShapeFieldName(&temp)))
+    return AOErr(hr, "No shape field found!");
+
+  m_strShapeFieldName = CW2A(temp);
+
+  IFieldsPtr ipFields;
+  if (FAILED(hr = ipFC->get_Fields(&ipFields)))
+    return AOErr(hr, "Fields not found!");
+
+  long shapeIndex = -1;
+  if (FAILED(hr = ipFields->FindField(temp, &shapeIndex)))
+    return AOErr(hr, "Shape field not found!");
+
+  IFieldPtr ipShapeField;
+  if (FAILED(hr = ipFields->get_Field(shapeIndex, &ipShapeField)))
+    return false;
+
+  // Use GeometryDef to set OGR shapetype and Spatial Reference information
+  //
+
+  IGeometryDefPtr ipGeoDef;
+  if (FAILED(hr = ipShapeField->get_GeometryDef(&ipGeoDef)))
+    return false;
+
+  OGRwkbGeometryType ogrGeoType;
+  if (!AOToOGRGeometry(ipGeoDef, &ogrGeoType))
+    return false;
+
+  m_pFeatureDefn->SetGeomType(ogrGeoType);
+
+  if (wkbFlatten(ogrGeoType) == wkbMultiLineString || wkbFlatten(ogrGeoType) == wkbMultiPoint)
+    m_forceMulti = true;
+
+  // Mapping of Spatial Reference will be passive about errors
+  // (it is possible we won't be able to map some ESRI-specific projections)
+
+  esriGeometry::ISpatialReferencePtr ipSR = NULL;
+
+  if (FAILED(hr = ipGeoDef->get_SpatialReference(&ipSR)))
+  {
+    AOErr(hr, "Failed Fetching ESRI spatial reference");
+  }
+  else
+  {
+    if (!AOToOGRSpatialReference(ipSR, &m_pSRS))
+    {
+      //report error, but be passive about it
+      CPLError( CE_Warning, CPLE_AppDefined, "Failed Mapping ESRI Spatial Reference");
+    }
+  }
+
+  // Map fields
+  //
+  return AOToOGRFields(ipFields, m_pFeatureDefn, m_OGRFieldToESRIField);
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void AOLayer::ResetReading()
+{
+  HRESULT hr;
+
+  if (FAILED(hr = m_ipTable->Search(m_ipQF, VARIANT_TRUE, &m_ipCursor)))
+    AOErr(hr, "Error Executing Query");
+}
+
+/************************************************************************/
+/*                            GetTable()                            */
+/************************************************************************/
+
+HRESULT AOLayer::GetTable(ITable** ppTable)
+{
+  return m_ipTable.QueryInterface(IID_ITable, ppTable);
+}
+
+/************************************************************************/
+/*                         SetSpatialFilter()                           */
+/************************************************************************/
+
+void AOLayer::SetSpatialFilter( OGRGeometry* pOGRGeom )
+{
+  if (pOGRGeom == NULL)
+  {
+    SwitchToAttributeOnlyFilter();
+    return;
+  }
+  else
+  {
+    SwitchToSpatialFilter();
+  }
+
+  esriGeometry::IGeometryPtr ipGeometry = NULL;
+
+  if ((!OGRGeometryToAOGeometry(pOGRGeom, &ipGeometry)) || ipGeometry == NULL)
+  {
+    // Crap! we failed and there is no return error mechanism.
+    // Report Error and dismiss ogr geometry to go back to at least a working
+    // state
+    CPLError( CE_Failure, CPLE_AppDefined, "Could not convert OGR spatial filter geometry to ArcObjecs one. Dismissing spatial filter!");
+
+    SwitchToAttributeOnlyFilter();
+    return;
+  }
+
+  // Set Spatial Reference on AO geometry
+  IGeoDatasetPtr ipGeoDataset = m_ipTable;
+  esriGeometry::ISpatialReferencePtr ipSR = NULL;
+  ipGeoDataset->get_SpatialReference(&ipSR);
+  ipGeometry->putref_SpatialReference(ipSR);
+
+  ISpatialFilterPtr ipSF = m_ipQF; //QI should never fail because we called SwitchToSpatialFilter
+
+  ipSF->putref_Geometry(ipGeometry);
+
+  ResetReading();
+}
+
+/************************************************************************/
+/*                         SetSpatialFilterRect()                       */
+/************************************************************************/
+
+void AOLayer::SetSpatialFilterRect (double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+{
+  SwitchToSpatialFilter();
+
+  IGeoDatasetPtr ipGD = m_ipTable;
+  esriGeometry::IEnvelopePtr ipEnvelope(esriGeometry::CLSID_Envelope);
+  esriGeometry::ISpatialReferencePtr ipSR;
+
+  ipGD->get_SpatialReference(&ipSR);
+  ipEnvelope->putref_SpatialReference(ipSR);
+  ipEnvelope->PutCoords(dfMinX, dfMinY, dfMaxX, dfMaxY);
+
+  ISpatialFilterPtr ipSF(m_ipQF);
+  ipSF->putref_Geometry(ipEnvelope);
+  ipSF->put_SpatialRel(esriSpatialRelIntersects);
+}
+
+/************************************************************************/
+/*                       SwitchToAttributeOnlyFilter()                  */
+/************************************************************************/
+
+void AOLayer::SwitchToAttributeOnlyFilter()
+{
+  ISpatialFilterPtr ipSF = m_ipQF;
+
+  if (ipSF == NULL)
+    return; //nothing to be done - it is an attribute filter
+
+  //only need to preserve whereclause since it is the only thing we consume in this driver
+  CComBSTR strWhereClause;
+  m_ipQF->get_WhereClause(&strWhereClause);
+
+  m_ipQF.CreateInstance(CLSID_QueryFilter); // will destroy old spatial filter
+  if (strWhereClause.Length() > 0)
+  {
+    m_ipQF->put_WhereClause(strWhereClause);
+  }
+}
+
+/************************************************************************/
+/*                         SwitchToSpatialFilter()                      */
+/************************************************************************/
+
+void AOLayer::SwitchToSpatialFilter()
+{
+  ISpatialFilterPtr ipSF = m_ipQF;
+
+  if (!(ipSF == NULL))
+    return; //nothing to be done it is a spatial filter already
+
+  //only need to preserve whereclause since it is the only thing we consume in this driver
+  CComBSTR strWhereClause;
+  m_ipQF->get_WhereClause(&strWhereClause);
+
+  m_ipQF.CreateInstance(CLSID_SpatialFilter); // will destroy old query filter
+  if (strWhereClause.Length() > 0)
+  {
+    m_ipQF->put_WhereClause(strWhereClause);
+  }
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr AOLayer::SetAttributeFilter( const char* pszQuery )
+{
+
+  if( pszQuery == NULL )
+  {
+
+    CComBSTR whereClause(_T(""));
+    m_ipQF->put_WhereClause(whereClause);
+  }
+  else
+  {
+    CComBSTR whereClause(pszQuery);
+    m_ipQF->put_WhereClause(whereClause);
+  }
+
+  ResetReading();
+
+  return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           OGRFeatureFromAORow()                      */
+/************************************************************************/
+
+bool AOLayer::OGRFeatureFromAORow(IRow* pRow, OGRFeature** ppFeature)
+{
+  HRESULT hr;
+
+  OGRFeature* pOutFeature = new OGRFeature(m_pFeatureDefn);
+
+  /////////////////////////////////////////////////////////
+  // Translate OID
+  //
+
+  long oid = -1;
+  if (FAILED(hr = pRow->get_OID(&oid)))
+  {
+    //this should never happen
+    delete pOutFeature;
+    return false;
+  }
+  pOutFeature->SetFID(oid);
+
+  /////////////////////////////////////////////////////////
+  // Translate Geometry
+  //
+
+  IFeaturePtr ipFeature = pRow;
+  esriGeometry::IGeometryPtr ipGeometry = NULL;
+
+  if (FAILED(hr = ipFeature->get_Shape(&ipGeometry)) || ipGeometry == NULL)
+  {
+    delete pOutFeature;
+    return AOErr(hr, "Failed retrieving shape from ArcObjects");
+  }
+
+  OGRGeometry* pOGRGeo = NULL;
+
+  if ((!AOGeometryToOGRGeometry(m_forceMulti, ipGeometry, m_pSRS, m_pBuffer, m_bufferSize, &pOGRGeo)) || pOGRGeo == NULL)
+  {
+    delete pOutFeature;
+    return AOErr(hr, "Failed to translate ArcObjects Geometry to OGR Geometry");
+  }
+
+  pOutFeature->SetGeometryDirectly(pOGRGeo);
+
+  //////////////////////////////////////////////////////////
+  // Map fields
+  //
+
+  CComVariant val;
+  size_t mappedFieldCount = m_OGRFieldToESRIField.size();
+
+  bool foundBadColumn = false;
+
+  for (size_t i = 0; i < mappedFieldCount; ++i)
+  {
+    long index = m_OGRFieldToESRIField[i];
+
+    if (FAILED(hr = pRow->get_Value(index, &val)))
+    {
+      // this should not happen
+      return AOErr(hr, "Failed retrieving row value");
+    }
+
+    if (val.vt == VT_NULL)
+    {
+      continue; //leave as unset
+    }
+
+    //
+    // NOTE: This switch statement needs to be kept in sync with AOToOGRGeometry
+    //       since we are only checking for types we mapped in that utility function
+
+    switch (m_pFeatureDefn->GetFieldDefn(i)->GetType())
+    {
+
+    case OFTInteger:
+      {
+        val.ChangeType(VT_I4);
+        pOutFeature->SetField(i, val.intVal);
+      }
+      break;
+
+    case OFTReal:
+      {
+        val.ChangeType(VT_R8);
+        pOutFeature->SetField(i, val.dblVal);
+      }
+      break;
+    case OFTString:
+      {
+        val.ChangeType(VT_BSTR);
+        pOutFeature->SetField(i, CW2A(val.bstrVal));
+      }
+      break;
+
+    /* TODO: Need to get test dataset to implement these leave it as NULL for now
+    case OFTBinary:
+      {
+      // Access as SafeArray with SafeArrayAccessData perhaps?
+      }
+      break;
+    case OFTDateTime:
+      {
+      // Examine test data to figure out how to extract that
+      }
+      break;
+      */
+    default:
+      {
+        if (!m_suppressColumnMappingError)
+        {
+          foundBadColumn = true;
+          CPLError( CE_Warning, CPLE_AppDefined, "Row id: %d col:%d has unhandled col type (%d). Setting to NULL.", oid, i, m_pFeatureDefn->GetFieldDefn(i)->GetType());
+        }
+      }
+    }
+  }
+
+  if (foundBadColumn)
+    m_suppressColumnMappingError = true;
+
+  *ppFeature = pOutFeature;
+
+  return true;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature* AOLayer::GetNextFeature()
+{
+  while (1) //want to skip errors
+  {
+    if (m_ipCursor == NULL)
+      return NULL;
+
+    HRESULT hr;
+
+    IRowPtr ipRow;
+
+    if (FAILED(hr = m_ipCursor->NextRow(&ipRow)))
+    {
+      AOErr(hr, "Failed fetching features");
+      return NULL;
+    }
+
+    if (hr == S_FALSE || ipRow == NULL)
+    {
+      // It's OK, we are done fetching
+      return NULL;
+    }
+
+    OGRFeature* pOGRFeature = NULL;
+
+    if (!OGRFeatureFromAORow(ipRow,  &pOGRFeature))
+    {
+      long oid = -1;
+      ipRow->get_OID(&oid);
+
+      std::strstream msg;
+      msg << "Failed translating ArcObjects row [" << oid << "] to OGR Feature";
+
+      AOErr(hr, msg.str());
+
+      //return NULL;
+      continue; //skip feature
+    }
+
+    return pOGRFeature;
+  }
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *AOLayer::GetFeature( GIntBig oid )
+{
+  HRESULT hr;
+
+  IRowPtr ipRow;
+  if (FAILED(hr = m_ipTable->GetRow(oid, &ipRow)))
+  {
+    AOErr(hr, "Failed fetching row");
+    return NULL;
+  }
+
+  OGRFeature* pOGRFeature = NULL;
+
+  if (!OGRFeatureFromAORow(ipRow,  &pOGRFeature))
+  {
+    AOErr(hr, "Failed translating ArcObjects row to OGR Feature");
+    return NULL;
+  }
+
+  return pOGRFeature;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig AOLayer::GetFeatureCount( int bForce )
+{
+  HRESULT hr;
+
+  long rowCount = -1;
+
+  if (FAILED(hr = m_ipTable->RowCount(m_ipQF, &rowCount)))
+  {
+    AOErr(hr, "Failed calculating row count");
+
+    return rowCount;
+  }
+
+  return static_cast<int>(rowCount);
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr AOLayer::GetExtent (OGREnvelope* psExtent, int bForce)
+{
+
+  if (bForce)
+  {
+    return OGRLayer::GetExtent( psExtent, bForce );
+  }
+
+  HRESULT hr;
+
+  IGeoDatasetPtr ipGeoDataset = m_ipTable;
+
+  esriGeometry::IEnvelopePtr ipEnv = NULL;
+  if (FAILED(hr = ipGeoDataset->get_Extent(&ipEnv)) || ipEnv == NULL)
+  {
+    AOErr(hr, "Failed retrieving extent");
+
+    return OGRERR_FAILURE;
+  }
+
+  double temp;
+
+  ipEnv->get_XMin(&temp);
+  psExtent->MinX = temp;
+
+  ipEnv->get_YMin(&temp);
+  psExtent->MinY = temp;
+
+  ipEnv->get_XMax(&temp);
+  psExtent->MaxX = temp;
+
+  ipEnv->get_YMax(&temp);
+  psExtent->MaxY = temp;
+
+  return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int AOLayer::TestCapability( const char* pszCap )
+{
+    if (EQUAL(pszCap,OLCRandomRead))
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCFastFeatureCount))
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCFastSpatialFilter))
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCFastGetExtent))
+        return TRUE;
+#ifdef notdef
+    // Have not implemented this yet
+    else if (EQUAL(pszCap,OLCCreateField))
+        return FALSE;
+
+    // Have not implemented this yet
+    else if (EQUAL(pszCap,OLCSequentialWrite)
+          || EQUAL(pszCap,OLCRandomWrite))
+        return FALSE;
+#endif
+    else
+        return FALSE;
+}
diff --git a/ogr/ogrsf_frmts/arcobjects/aoutils.cpp b/ogr/ogrsf_frmts/arcobjects/aoutils.cpp
index 3e297ce..41eeed3 100644
--- a/ogr/ogrsf_frmts/arcobjects/aoutils.cpp
+++ b/ogr/ogrsf_frmts/arcobjects/aoutils.cpp
@@ -1,465 +1,462 @@
-/******************************************************************************
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Different utility functions used in ArcObjects OGR driver.
- * Author:   Ragi Yaser Burhum, ragi at burhum.com
- *
- ******************************************************************************
- * Copyright (c) 2009, Ragi Yaser Burhum
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "aoutils.h"
-
-
-bool AOErr(HRESULT hr, std::string desc)
-{
-  IErrorInfoPtr ipErrorInfo = NULL;
-  ::GetErrorInfo(NULL, &ipErrorInfo);
-
-  if (ipErrorInfo)
-  {
-    CComBSTR comErrDesc;
-    ipErrorInfo->GetDescription(&comErrDesc);
-
-    CW2A errMsg(comErrDesc);
-
-    CPLError( CE_Failure, CPLE_AppDefined, "AO Error: %s HRESULT:%d COM_ERROR:%s", desc.c_str(), hr, errMsg );
-
-    ::SetErrorInfo(NULL, NULL);
-  }
-  else
-  {
-    CPLError( CE_Failure, CPLE_AppDefined, "AO Error: %s HRESULT:%d", desc.c_str(), hr);
-  }
-
-  return false;
-}
-
-bool AOToOGRGeometry(IGeometryDef* pGeoDef, OGRwkbGeometryType* pOut)
-{
-  esriGeometry::esriGeometryType geo;
-  VARIANT_BOOL hasZ;
-
-  pGeoDef->get_GeometryType(&geo);
-  pGeoDef->get_HasZ(&hasZ);
-  
-  switch (geo)
-  {
-    case esriGeometry::esriGeometryPoint:      *pOut = hasZ == VARIANT_TRUE? wkbPoint25D      : wkbPoint;                break;
-    case esriGeometry::esriGeometryMultipoint: *pOut = hasZ == VARIANT_TRUE? wkbMultiPoint25D : wkbMultiPoint;           break;
-    case esriGeometry::esriGeometryLine:       *pOut = hasZ == VARIANT_TRUE? wkbLineString25D : wkbLineString;           break;
-    case esriGeometry::esriGeometryPolyline:   *pOut = hasZ == VARIANT_TRUE? wkbMultiLineString25D : wkbMultiLineString; break;
-    case esriGeometry::esriGeometryPolygon:    *pOut = hasZ == VARIANT_TRUE? wkbMultiPolygon25D : wkbMultiPolygon;    break;// no mapping to single polygon
-
-    default:
-      {
-        CPLError( CE_Failure, CPLE_AppDefined, "Cannot map esriGeometryType(%d) to OGRwkbGeometryType", geo);
-        return false;
-      }
-  }
-
-  return true;
-}
-
-bool AOToOGRFields(IFields* pFields, OGRFeatureDefn* pOGRFeatureDef, std::vector<long> & ogrToESRIFieldMapping)
-{
-  HRESULT hr;
-
-  long fieldCount;
-  if (FAILED(hr = pFields->get_FieldCount(&fieldCount)))
-    return false;
-
-  ogrToESRIFieldMapping.clear();
-
-  for (long i = 0; i < fieldCount; ++i)
-  {
-
-    IFieldPtr ipField;
-    if (FAILED(hr = pFields->get_Field(i, &ipField)))
-      return AOErr(hr, "Error getting field");
-
-    CComBSTR name;
-    if (FAILED(hr = ipField->get_Name(&name)))
-      return AOErr(hr, "Could not get field name");
-
-    esriFieldType fieldType;
-    if (FAILED(hr = ipField->get_Type(&fieldType)))
-      return AOErr(hr, "Error getting field type");
-
-    //skip these
-    if (fieldType == esriFieldTypeOID || fieldType == esriFieldTypeGeometry)
-      continue;
-
-    OGRFieldType ogrType;
-    if (!AOToOGRFieldType(fieldType, &ogrType))
-    {
-      // field cannot be mapped, skipping it
-      CPLError( CE_Warning, CPLE_AppDefined, "Skipping field %s", CW2A(name) );
-      continue;
-    }
-
-    OGRFieldDefn fieldTemplate( CW2A(name), ogrType);
-    pOGRFeatureDef->AddFieldDefn( &fieldTemplate );
-
-    ogrToESRIFieldMapping.push_back(i);
-  }
-
-  CPLAssert(ogrToESRIFieldMapping.size() == pOGRFeatureDef->GetFieldCount());
-
-  return true;
-}
-
-// We could make this function far more robust by doing automatic coercion of
-// types, and/or skipping fields we do not know. But, for our purposes, this
-// works fine.
-
-bool AOToOGRFieldType(esriFieldType aoType, OGRFieldType* pOut)
-{
-  /*
-  ESRI types
-    esriFieldTypeSmallInteger = 0,
-    esriFieldTypeInteger = 1,
-    esriFieldTypeSingle = 2,
-    esriFieldTypeDouble = 3,
-    esriFieldTypeString = 4,
-    esriFieldTypeDate = 5,
-    esriFieldTypeOID = 6,
-    esriFieldTypeGeometry = 7,
-    esriFieldTypeBlob = 8,
-    esriFieldTypeRaster = 9,
-    esriFieldTypeGUID = 10,
-    esriFieldTypeGlobalID = 11,
-    esriFieldTypeXML = 12
-  */
-
-  //OGR Types
-
-  //            Desc                                 Name                AO->OGR Mapped By Us?
-  /** Simple 32bit integer *///                   OFTInteger = 0,             YES 
-  /** List of 32bit integers *///                 OFTIntegerList = 1,         NO
-  /** Double Precision floating point *///        OFTReal = 2,                YES
-  /** List of doubles *///                        OFTRealList = 3,            NO
-  /** String of ASCII chars *///                  OFTString = 4,              YES
-  /** Array of strings *///                       OFTStringList = 5,          NO
-  /** deprecated *///                             OFTWideString = 6,          NO
-  /** deprecated *///                             OFTWideStringList = 7,      NO
-  /** Raw Binary data *///                        OFTBinary = 8,              YES
-  /** Date *///                                   OFTDate = 9,                NO
-  /** Time *///                                   OFTTime = 10,               NO
-  /** Date and Time *///                          OFTDateTime = 11            YES
-
-  switch (aoType)
-  {
-  case esriFieldTypeSmallInteger:
-  case esriFieldTypeInteger:
-    {
-      *pOut = OFTInteger;
-      return true;
-    }
-  case esriFieldTypeSingle:
-  case esriFieldTypeDouble:
-    {
-      *pOut = OFTReal;
-      return true;
-    }
-  case esriFieldTypeGUID:
-  case esriFieldTypeGlobalID:
-  case esriFieldTypeXML:
-  case esriFieldTypeString:
-    {
-      *pOut = OFTString;
-      return true;
-    }
-  case esriFieldTypeDate:
-    {
-      *pOut = OFTDateTime;
-      return true;
-    }
-  case esriFieldTypeBlob:
-    {
-      *pOut = OFTBinary;
-      return true;
-    }
-  default:
-    {
-      /* Intentionally fail at these
-        esriFieldTypeOID
-        esriFieldTypeGeometry
-        esriFieldTypeRaster
-      */
-      return false;
-    }
-
-  }
-}
-
-
-bool AOGeometryToOGRGeometry(bool forceMulti, esriGeometry::IGeometry* pInAOGeo, OGRSpatialReference* pOGRSR, unsigned char* & pInOutWorkingBuffer, long & inOutBufferSize, OGRGeometry** ppOutGeometry)
-{
-  HRESULT hr;
-  
-  esriGeometry::IWkbPtr ipWkb = pInAOGeo;
-
-  long reqSize = 0;
-
-  if (FAILED(hr = ipWkb->get_WkbSize(&reqSize)))
-  {
-    AOErr(hr, "Error getting Wkb buffer size");
-    return false;
-  }
-
-  if (reqSize > inOutBufferSize)
-  {
-    // resize working buffer
-    delete [] pInOutWorkingBuffer;
-    pInOutWorkingBuffer = new unsigned char[reqSize];
-    inOutBufferSize = reqSize;
-  }
-  
-  if (FAILED(hr = ipWkb->ExportToWkb(&reqSize, pInOutWorkingBuffer)))
-  {
-    AOErr(hr, "Error exporting to WKB buffer");
-    return false;
-  }
-
-  OGRGeometry* pOGRGeometry = NULL;
-  OGRErr eErr = OGRGeometryFactory::createFromWkb(pInOutWorkingBuffer, pOGRSR, &pOGRGeometry, reqSize);
-  if (eErr != OGRERR_NONE)
-  {
-    CPLError( CE_Failure, CPLE_AppDefined, "Failed attempting to import ArcGIS WKB Geometry. OGRGeometryFactory err:%d", eErr);
-    return false;
-  }
-
-  // force geometries to multi if requested
-
-
-  // If it is a polygon, force to MultiPolygon since we always produce multipolygons
-  if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbPolygon)
-  {
-    pOGRGeometry = OGRGeometryFactory::forceToMultiPolygon(pOGRGeometry);
-  }
-  else if (forceMulti)
-  {
-    if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbLineString)
-    {
-      pOGRGeometry = OGRGeometryFactory::forceToMultiLineString(pOGRGeometry);
-    }
-    else if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbPoint)
-    {
-      pOGRGeometry = OGRGeometryFactory::forceToMultiPoint(pOGRGeometry);
-    } 
-  }
-
-
-  *ppOutGeometry = pOGRGeometry;
-  
-  return true;
-}
-
-bool AOToOGRSpatialReference(esriGeometry::ISpatialReference* pSR, OGRSpatialReference** ppSR)
-{
-  HRESULT hr;
-
-  if (pSR == NULL)
-  {
-    CPLError( CE_Warning, CPLE_AppDefined, "ESRI Spatial Reference is NULL");
-    return false;
-  }
-
-  esriGeometry::IESRISpatialReferenceGEN2Ptr ipSRGen = pSR;
-
-  if (ipSRGen == NULL)
-  {
-    CPLError( CE_Warning, CPLE_AppDefined, "ESRI Spatial Reference is Unknown");
-    return false;
-  }
-
-  long bufferSize = 0;
-  if (FAILED(hr = ipSRGen->get_ESRISpatialReferenceSize(&bufferSize)) || bufferSize == 0)
-    return false; //should never happen
-
-  BSTR buffer = ::SysAllocStringLen(NULL,bufferSize);
-
-  if (FAILED(hr = ipSRGen->ExportToESRISpatialReference2(&buffer, &bufferSize)))
-  {
-    ::SysFreeString(buffer);
-
-    return AOErr(hr, "Failed to export ESRI string");
-  }
-
-  CW2A strESRIWKT(buffer);
-
-  ::SysFreeString(buffer);
-
-  if (strlen(strESRIWKT) <= 0)
-  {
-    CPLError( CE_Warning, CPLE_AppDefined, "ESRI Spatial Reference is NULL");
-    return false; 
-  }
-
-  *ppSR = new OGRSpatialReference(strESRIWKT);
-
-  OGRErr result = (*ppSR)->morphFromESRI();
-
-  if (result == OGRERR_NONE)
-  {
-    return true;
-  }
-  else
-  {
-    delete *ppSR;
-    *ppSR = NULL;
-
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "Failed morphing from ESRI Geometry: %s", strESRIWKT);
-
-    return false;
-  }
-}
-
-bool OGRGeometryToAOGeometry(OGRGeometry* pOGRGeom, esriGeometry::IGeometry** ppGeometry)
-{
-  HRESULT hr;
-
-  *ppGeometry = NULL;
-
-  GByte* pWKB = NULL;
-
-  long wkbSize = pOGRGeom->WkbSize();
-  pWKB = (GByte *) CPLMalloc(wkbSize);
-
-  if( pOGRGeom->exportToWkb( wkbNDR, pWKB ) != OGRERR_NONE )
-  {
-    CPLFree (pWKB);
-    CPLError( CE_Failure, CPLE_AppDefined, "Could not export OGR geometry to WKB");
-    return false; 
-  }
-
-  long bytesRead;
-  esriGeometry::IGeometryFactoryPtr ipGeomFact(esriGeometry::CLSID_GeometryEnvironment);
-  hr = ipGeomFact->CreateGeometryFromWkb(&bytesRead, pWKB, ppGeometry);
-
-  CPLFree (pWKB);
-
-  if (FAILED(hr))
-  {
-    return AOErr(hr, "Failed translating OGR geometry to ESRI Geometry");
-  }
-
-  return true;
-}
-
-// Attempt to checkout a license from the top down
-bool InitializeDriver(esriLicenseExtensionCode license) 
-{
-  IAoInitializePtr ipInit(CLSID_AoInitialize);
-
-  if (license == 0)
-  {
-    // Try to init as engine, then engineGeoDB, then ArcView, 
-    //    then ArcEditor, then ArcInfo 
-    if (!InitAttemptWithoutExtension(esriLicenseProductCodeEngine))
-      if (!InitAttemptWithoutExtension(esriLicenseProductCodeArcView))
-        if (!InitAttemptWithoutExtension(esriLicenseProductCodeArcEditor))
-          if (!InitAttemptWithoutExtension(esriLicenseProductCodeArcInfo))
-          {
-            // No appropriate license is available
-
-            CPLError( CE_Failure, CPLE_AppDefined, "ArcGIS License checkout failed.");
-            return false;
-          }
-
-          return true;
-  }
-
-  // Try to init as engine, then engineGeoDB, then ArcView, 
-  //    then ArcEditor, then ArcInfo 
-  if (!InitAttemptWithExtension(esriLicenseProductCodeEngine,license))
-    if (!InitAttemptWithExtension(esriLicenseProductCodeArcView, license))
-      if (!InitAttemptWithExtension(esriLicenseProductCodeArcEditor, license))
-        if (!InitAttemptWithExtension(esriLicenseProductCodeArcInfo, license))
-        {
-          // No appropriate license is available
-          CPLError( CE_Failure, CPLE_AppDefined, "ArcGIS License checkout failed.");
-          return false;
-        }
-
-        return true;
-}
-
-// Attempt to initialize without an extension
-bool InitAttemptWithoutExtension(esriLicenseProductCode product)
-{
-  IAoInitializePtr ipInit(CLSID_AoInitialize);
-
-  esriLicenseStatus status = esriLicenseFailure;
-  ipInit->Initialize(product, &status);
-  return (status == esriLicenseCheckedOut);
-}
-
-// Attempt to initialize with an extension
-bool InitAttemptWithExtension(esriLicenseProductCode product,
-                              esriLicenseExtensionCode extension)
-{
-  IAoInitializePtr ipInit(CLSID_AoInitialize);
-
-  esriLicenseStatus licenseStatus = esriLicenseFailure;
-  ipInit->IsExtensionCodeAvailable(product, extension, &licenseStatus);
-  if (licenseStatus == esriLicenseAvailable)
-  {
-    ipInit->Initialize(product, &licenseStatus);
-    if (licenseStatus == esriLicenseCheckedOut)
-      ipInit->CheckOutExtension(extension, &licenseStatus);
-  }
-  return (licenseStatus == esriLicenseCheckedOut);
-}
-
-// Shutdown the driver and check-in the license if needed.
-HRESULT ShutdownDriver(esriLicenseExtensionCode license)
-{
-  HRESULT hr;
-
-  // Scope ipInit so released before AoUninitialize call
-  {
-    IAoInitializePtr ipInit(CLSID_AoInitialize);
-    esriLicenseStatus status;
-    if (license != NULL)
-    {
-      hr = ipInit->CheckInExtension(license, &status);
-      if (FAILED(hr) || status != esriLicenseCheckedIn)
-        CPLError( CE_Failure, CPLE_AppDefined, "License checkin failed.");
-    }
-    hr = ipInit->Shutdown();
-  }
-
-  return hr;
-}
-
-int GetInitedProductCode()
-{
-  HRESULT hr;
-  IAoInitializePtr ipAO(CLSID_AoInitialize);
-  esriLicenseProductCode code;
-  if (FAILED(hr = ipAO->InitializedProduct(&code)))
-    return -1;
-
-  return static_cast<int>(code);
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Different utility functions used in ArcObjects OGR driver.
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Ragi Yaser Burhum
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "aoutils.h"
+
+CPL_CVSID("$Id: aoutils.cpp 35933 2016-10-25 16:46:26Z goatbar $");
+
+bool AOErr(HRESULT hr, std::string desc)
+{
+  IErrorInfoPtr ipErrorInfo = NULL;
+  ::GetErrorInfo(NULL, &ipErrorInfo);
+
+  if (ipErrorInfo)
+  {
+    CComBSTR comErrDesc;
+    ipErrorInfo->GetDescription(&comErrDesc);
+
+    CW2A errMsg(comErrDesc);
+
+    CPLError( CE_Failure, CPLE_AppDefined, "AO Error: %s HRESULT:%d COM_ERROR:%s", desc.c_str(), hr, errMsg );
+
+    ::SetErrorInfo(NULL, NULL);
+  }
+  else
+  {
+    CPLError( CE_Failure, CPLE_AppDefined, "AO Error: %s HRESULT:%d", desc.c_str(), hr);
+  }
+
+  return false;
+}
+
+bool AOToOGRGeometry(IGeometryDef* pGeoDef, OGRwkbGeometryType* pOut)
+{
+  esriGeometry::esriGeometryType geo;
+  VARIANT_BOOL hasZ;
+
+  pGeoDef->get_GeometryType(&geo);
+  pGeoDef->get_HasZ(&hasZ);
+
+  switch (geo)
+  {
+    case esriGeometry::esriGeometryPoint:      *pOut = hasZ == VARIANT_TRUE? wkbPoint25D      : wkbPoint;                break;
+    case esriGeometry::esriGeometryMultipoint: *pOut = hasZ == VARIANT_TRUE? wkbMultiPoint25D : wkbMultiPoint;           break;
+    case esriGeometry::esriGeometryLine:       *pOut = hasZ == VARIANT_TRUE? wkbLineString25D : wkbLineString;           break;
+    case esriGeometry::esriGeometryPolyline:   *pOut = hasZ == VARIANT_TRUE? wkbMultiLineString25D : wkbMultiLineString; break;
+    case esriGeometry::esriGeometryPolygon:    *pOut = hasZ == VARIANT_TRUE? wkbMultiPolygon25D : wkbMultiPolygon;    break;// no mapping to single polygon
+
+    default:
+      {
+        CPLError( CE_Failure, CPLE_AppDefined, "Cannot map esriGeometryType(%d) to OGRwkbGeometryType", geo);
+        return false;
+      }
+  }
+
+  return true;
+}
+
+bool AOToOGRFields(IFields* pFields, OGRFeatureDefn* pOGRFeatureDef, std::vector<long> & ogrToESRIFieldMapping)
+{
+  HRESULT hr;
+
+  long fieldCount;
+  if (FAILED(hr = pFields->get_FieldCount(&fieldCount)))
+    return false;
+
+  ogrToESRIFieldMapping.clear();
+
+  for (long i = 0; i < fieldCount; ++i)
+  {
+
+    IFieldPtr ipField;
+    if (FAILED(hr = pFields->get_Field(i, &ipField)))
+      return AOErr(hr, "Error getting field");
+
+    CComBSTR name;
+    if (FAILED(hr = ipField->get_Name(&name)))
+      return AOErr(hr, "Could not get field name");
+
+    esriFieldType fieldType;
+    if (FAILED(hr = ipField->get_Type(&fieldType)))
+      return AOErr(hr, "Error getting field type");
+
+    //skip these
+    if (fieldType == esriFieldTypeOID || fieldType == esriFieldTypeGeometry)
+      continue;
+
+    OGRFieldType ogrType;
+    if (!AOToOGRFieldType(fieldType, &ogrType))
+    {
+      // field cannot be mapped, skipping it
+      CPLError( CE_Warning, CPLE_AppDefined, "Skipping field %s", CW2A(name) );
+      continue;
+    }
+
+    OGRFieldDefn fieldTemplate( CW2A(name), ogrType);
+    pOGRFeatureDef->AddFieldDefn( &fieldTemplate );
+
+    ogrToESRIFieldMapping.push_back(i);
+  }
+
+  CPLAssert(ogrToESRIFieldMapping.size() == pOGRFeatureDef->GetFieldCount());
+
+  return true;
+}
+
+// We could make this function far more robust by doing automatic coercion of
+// types, and/or skipping fields we do not know. But, for our purposes, this
+// works fine.
+
+bool AOToOGRFieldType(esriFieldType aoType, OGRFieldType* pOut)
+{
+  /*
+  ESRI types
+    esriFieldTypeSmallInteger = 0,
+    esriFieldTypeInteger = 1,
+    esriFieldTypeSingle = 2,
+    esriFieldTypeDouble = 3,
+    esriFieldTypeString = 4,
+    esriFieldTypeDate = 5,
+    esriFieldTypeOID = 6,
+    esriFieldTypeGeometry = 7,
+    esriFieldTypeBlob = 8,
+    esriFieldTypeRaster = 9,
+    esriFieldTypeGUID = 10,
+    esriFieldTypeGlobalID = 11,
+    esriFieldTypeXML = 12
+  */
+
+  //OGR Types
+
+  //            Desc                                 Name                AO->OGR Mapped By Us?
+  /** Simple 32bit integer *///                   OFTInteger = 0,             YES
+  /** List of 32bit integers *///                 OFTIntegerList = 1,         NO
+  /** Double Precision floating point *///        OFTReal = 2,                YES
+  /** List of doubles *///                        OFTRealList = 3,            NO
+  /** String of ASCII chars *///                  OFTString = 4,              YES
+  /** Array of strings *///                       OFTStringList = 5,          NO
+  /** deprecated *///                             OFTWideString = 6,          NO
+  /** deprecated *///                             OFTWideStringList = 7,      NO
+  /** Raw Binary data *///                        OFTBinary = 8,              YES
+  /** Date *///                                   OFTDate = 9,                NO
+  /** Time *///                                   OFTTime = 10,               NO
+  /** Date and Time *///                          OFTDateTime = 11            YES
+
+  switch (aoType)
+  {
+  case esriFieldTypeSmallInteger:
+  case esriFieldTypeInteger:
+    {
+      *pOut = OFTInteger;
+      return true;
+    }
+  case esriFieldTypeSingle:
+  case esriFieldTypeDouble:
+    {
+      *pOut = OFTReal;
+      return true;
+    }
+  case esriFieldTypeGUID:
+  case esriFieldTypeGlobalID:
+  case esriFieldTypeXML:
+  case esriFieldTypeString:
+    {
+      *pOut = OFTString;
+      return true;
+    }
+  case esriFieldTypeDate:
+    {
+      *pOut = OFTDateTime;
+      return true;
+    }
+  case esriFieldTypeBlob:
+    {
+      *pOut = OFTBinary;
+      return true;
+    }
+  default:
+    {
+      /* Intentionally fail at these
+        esriFieldTypeOID
+        esriFieldTypeGeometry
+        esriFieldTypeRaster
+      */
+      return false;
+    }
+  }
+}
+
+bool AOGeometryToOGRGeometry(bool forceMulti, esriGeometry::IGeometry* pInAOGeo, OGRSpatialReference* pOGRSR, unsigned char* & pInOutWorkingBuffer, long & inOutBufferSize, OGRGeometry** ppOutGeometry)
+{
+  HRESULT hr;
+
+  esriGeometry::IWkbPtr ipWkb = pInAOGeo;
+
+  long reqSize = 0;
+
+  if (FAILED(hr = ipWkb->get_WkbSize(&reqSize)))
+  {
+    AOErr(hr, "Error getting Wkb buffer size");
+    return false;
+  }
+
+  if (reqSize > inOutBufferSize)
+  {
+    // resize working buffer
+    delete [] pInOutWorkingBuffer;
+    pInOutWorkingBuffer = new unsigned char[reqSize];
+    inOutBufferSize = reqSize;
+  }
+
+  if (FAILED(hr = ipWkb->ExportToWkb(&reqSize, pInOutWorkingBuffer)))
+  {
+    AOErr(hr, "Error exporting to WKB buffer");
+    return false;
+  }
+
+  OGRGeometry* pOGRGeometry = NULL;
+  OGRErr eErr = OGRGeometryFactory::createFromWkb(pInOutWorkingBuffer, pOGRSR, &pOGRGeometry, reqSize);
+  if (eErr != OGRERR_NONE)
+  {
+    CPLError( CE_Failure, CPLE_AppDefined, "Failed attempting to import ArcGIS WKB Geometry. OGRGeometryFactory err:%d", eErr);
+    return false;
+  }
+
+  // force geometries to multi if requested
+
+  // If it is a polygon, force to MultiPolygon since we always produce multipolygons
+  if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbPolygon)
+  {
+    pOGRGeometry = OGRGeometryFactory::forceToMultiPolygon(pOGRGeometry);
+  }
+  else if (forceMulti)
+  {
+    if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbLineString)
+    {
+      pOGRGeometry = OGRGeometryFactory::forceToMultiLineString(pOGRGeometry);
+    }
+    else if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbPoint)
+    {
+      pOGRGeometry = OGRGeometryFactory::forceToMultiPoint(pOGRGeometry);
+    }
+  }
+
+  *ppOutGeometry = pOGRGeometry;
+
+  return true;
+}
+
+bool AOToOGRSpatialReference(esriGeometry::ISpatialReference* pSR, OGRSpatialReference** ppSR)
+{
+  HRESULT hr;
+
+  if (pSR == NULL)
+  {
+    CPLError( CE_Warning, CPLE_AppDefined, "ESRI Spatial Reference is NULL");
+    return false;
+  }
+
+  esriGeometry::IESRISpatialReferenceGEN2Ptr ipSRGen = pSR;
+
+  if (ipSRGen == NULL)
+  {
+    CPLError( CE_Warning, CPLE_AppDefined, "ESRI Spatial Reference is Unknown");
+    return false;
+  }
+
+  long bufferSize = 0;
+  if (FAILED(hr = ipSRGen->get_ESRISpatialReferenceSize(&bufferSize)) || bufferSize == 0)
+    return false; //should never happen
+
+  BSTR buffer = ::SysAllocStringLen(NULL,bufferSize);
+
+  if (FAILED(hr = ipSRGen->ExportToESRISpatialReference2(&buffer, &bufferSize)))
+  {
+    ::SysFreeString(buffer);
+
+    return AOErr(hr, "Failed to export ESRI string");
+  }
+
+  CW2A strESRIWKT(buffer);
+
+  ::SysFreeString(buffer);
+
+  if (strlen(strESRIWKT) <= 0)
+  {
+    CPLError( CE_Warning, CPLE_AppDefined, "ESRI Spatial Reference is NULL");
+    return false;
+  }
+
+  *ppSR = new OGRSpatialReference(strESRIWKT);
+
+  OGRErr result = (*ppSR)->morphFromESRI();
+
+  if (result == OGRERR_NONE)
+  {
+    return true;
+  }
+  else
+  {
+    delete *ppSR;
+    *ppSR = NULL;
+
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "Failed morphing from ESRI Geometry: %s", strESRIWKT);
+
+    return false;
+  }
+}
+
+bool OGRGeometryToAOGeometry(OGRGeometry* pOGRGeom, esriGeometry::IGeometry** ppGeometry)
+{
+  HRESULT hr;
+
+  *ppGeometry = NULL;
+
+  GByte* pWKB = NULL;
+
+  long wkbSize = pOGRGeom->WkbSize();
+  pWKB = (GByte *) CPLMalloc(wkbSize);
+
+  if( pOGRGeom->exportToWkb( wkbNDR, pWKB ) != OGRERR_NONE )
+  {
+    CPLFree (pWKB);
+    CPLError( CE_Failure, CPLE_AppDefined, "Could not export OGR geometry to WKB");
+    return false;
+  }
+
+  long bytesRead;
+  esriGeometry::IGeometryFactoryPtr ipGeomFact(esriGeometry::CLSID_GeometryEnvironment);
+  hr = ipGeomFact->CreateGeometryFromWkb(&bytesRead, pWKB, ppGeometry);
+
+  CPLFree (pWKB);
+
+  if (FAILED(hr))
+  {
+    return AOErr(hr, "Failed translating OGR geometry to ESRI Geometry");
+  }
+
+  return true;
+}
+
+// Attempt to checkout a license from the top down
+bool InitializeDriver(esriLicenseExtensionCode license)
+{
+  IAoInitializePtr ipInit(CLSID_AoInitialize);
+
+  if (license == 0)
+  {
+    // Try to init as engine, then engineGeoDB, then ArcView,
+    //    then ArcEditor, then ArcInfo
+    if (!InitAttemptWithoutExtension(esriLicenseProductCodeEngine))
+      if (!InitAttemptWithoutExtension(esriLicenseProductCodeArcView))
+        if (!InitAttemptWithoutExtension(esriLicenseProductCodeArcEditor))
+          if (!InitAttemptWithoutExtension(esriLicenseProductCodeArcInfo))
+          {
+            // No appropriate license is available
+
+            CPLError( CE_Failure, CPLE_AppDefined, "ArcGIS License checkout failed.");
+            return false;
+          }
+
+          return true;
+  }
+
+  // Try to init as engine, then engineGeoDB, then ArcView,
+  //    then ArcEditor, then ArcInfo
+  if (!InitAttemptWithExtension(esriLicenseProductCodeEngine,license))
+    if (!InitAttemptWithExtension(esriLicenseProductCodeArcView, license))
+      if (!InitAttemptWithExtension(esriLicenseProductCodeArcEditor, license))
+        if (!InitAttemptWithExtension(esriLicenseProductCodeArcInfo, license))
+        {
+          // No appropriate license is available
+          CPLError( CE_Failure, CPLE_AppDefined, "ArcGIS License checkout failed.");
+          return false;
+        }
+
+        return true;
+}
+
+// Attempt to initialize without an extension
+bool InitAttemptWithoutExtension(esriLicenseProductCode product)
+{
+  IAoInitializePtr ipInit(CLSID_AoInitialize);
+
+  esriLicenseStatus status = esriLicenseFailure;
+  ipInit->Initialize(product, &status);
+  return status == esriLicenseCheckedOut;
+}
+
+// Attempt to initialize with an extension
+bool InitAttemptWithExtension(esriLicenseProductCode product,
+                              esriLicenseExtensionCode extension)
+{
+  IAoInitializePtr ipInit(CLSID_AoInitialize);
+
+  esriLicenseStatus licenseStatus = esriLicenseFailure;
+  ipInit->IsExtensionCodeAvailable(product, extension, &licenseStatus);
+  if (licenseStatus == esriLicenseAvailable)
+  {
+    ipInit->Initialize(product, &licenseStatus);
+    if (licenseStatus == esriLicenseCheckedOut)
+      ipInit->CheckOutExtension(extension, &licenseStatus);
+  }
+  return licenseStatus == esriLicenseCheckedOut;
+}
+
+// Shutdown the driver and check-in the license if needed.
+HRESULT ShutdownDriver(esriLicenseExtensionCode license)
+{
+  HRESULT hr;
+
+  // Scope ipInit so released before AoUninitialize call
+  {
+    IAoInitializePtr ipInit(CLSID_AoInitialize);
+    esriLicenseStatus status;
+    if (license != NULL)
+    {
+      hr = ipInit->CheckInExtension(license, &status);
+      if (FAILED(hr) || status != esriLicenseCheckedIn)
+        CPLError( CE_Failure, CPLE_AppDefined, "License checkin failed.");
+    }
+    hr = ipInit->Shutdown();
+  }
+
+  return hr;
+}
+
+int GetInitedProductCode()
+{
+  HRESULT hr;
+  IAoInitializePtr ipAO(CLSID_AoInitialize);
+  esriLicenseProductCode code;
+  if (FAILED(hr = ipAO->InitializedProduct(&code)))
+    return -1;
+
+  return static_cast<int>(code);
+}
diff --git a/ogr/ogrsf_frmts/arcobjects/aoutils.h b/ogr/ogrsf_frmts/arcobjects/aoutils.h
index 4171fd1..40ce7d1 100644
--- a/ogr/ogrsf_frmts/arcobjects/aoutils.h
+++ b/ogr/ogrsf_frmts/arcobjects/aoutils.h
@@ -1,39 +1,35 @@
-
-#ifndef AO_UTILS_H_INCLUDED
-#define AO_UTILS_H_INCLUDED
-
-#include "ogr_ao.h"
-#include <iostream>
-
-// ArcObjects to OGR Geometry Mapping 
-bool AOToOGRGeometry(IGeometryDef* pGeoDef, OGRwkbGeometryType* outOGRType);
-bool AOGeometryToOGRGeometry(bool forceMulti, esriGeometry::IGeometry* pInAOGeo, OGRSpatialReference* pOGRSR, unsigned char* & pInWorkingBuffer, long & inOutBufferSize, OGRGeometry** ppOutGeometry); //working buffer is an optimization to avoid reallocating mem
-bool AOToOGRSpatialReference(esriGeometry::ISpatialReference* pSR, OGRSpatialReference** ppSR);
-bool OGRGeometryToAOGeometry(OGRGeometry* pOGRGeom, esriGeometry::IGeometry** ppGeometry);
-
-
-// ArcObjects to OGR Field Mapping
-bool AOToOGRFields(IFields* pFields, OGRFeatureDefn* pOGRFeatureDef, std::vector<long> & ogrToESRIFieldMapping);
-bool AOToOGRFieldType(esriFieldType aoType, OGRFieldType* ogrType);
-
-
-// COM error to OGR
-bool AOErr(HRESULT hr, std::string desc);
-
-// Init driver and check out license
-bool InitializeDriver(esriLicenseExtensionCode license = 
-                   (esriLicenseExtensionCode)0);
-
-// Exit app and check in license
-HRESULT ShutdownDriver(esriLicenseExtensionCode license = 
-                    (esriLicenseExtensionCode)0);
-
-
-// Helper functions to initialize
-bool InitAttemptWithoutExtension(esriLicenseProductCode product);
-bool InitAttemptWithExtension(esriLicenseProductCode product,
-                              esriLicenseExtensionCode extension);
-int GetInitedProductCode();
-
-
-#endif
+
+#ifndef AO_UTILS_H_INCLUDED
+#define AO_UTILS_H_INCLUDED
+
+#include "ogr_ao.h"
+#include <iostream>
+
+// ArcObjects to OGR Geometry Mapping
+bool AOToOGRGeometry(IGeometryDef* pGeoDef, OGRwkbGeometryType* outOGRType);
+bool AOGeometryToOGRGeometry(bool forceMulti, esriGeometry::IGeometry* pInAOGeo, OGRSpatialReference* pOGRSR, unsigned char* & pInWorkingBuffer, long & inOutBufferSize, OGRGeometry** ppOutGeometry); //working buffer is an optimization to avoid reallocating mem
+bool AOToOGRSpatialReference(esriGeometry::ISpatialReference* pSR, OGRSpatialReference** ppSR);
+bool OGRGeometryToAOGeometry(OGRGeometry* pOGRGeom, esriGeometry::IGeometry** ppGeometry);
+
+// ArcObjects to OGR Field Mapping
+bool AOToOGRFields(IFields* pFields, OGRFeatureDefn* pOGRFeatureDef, std::vector<long> & ogrToESRIFieldMapping);
+bool AOToOGRFieldType(esriFieldType aoType, OGRFieldType* ogrType);
+
+// COM error to OGR
+bool AOErr(HRESULT hr, std::string desc);
+
+// Init driver and check out license
+bool InitializeDriver(esriLicenseExtensionCode license =
+                   (esriLicenseExtensionCode)0);
+
+// Exit app and check in license
+HRESULT ShutdownDriver(esriLicenseExtensionCode license =
+                    (esriLicenseExtensionCode)0);
+
+// Helper functions to initialize
+bool InitAttemptWithoutExtension(esriLicenseProductCode product);
+bool InitAttemptWithExtension(esriLicenseProductCode product,
+                              esriLicenseExtensionCode extension);
+int GetInitedProductCode();
+
+#endif
diff --git a/ogr/ogrsf_frmts/arcobjects/ogr_ao.h b/ogr/ogrsf_frmts/arcobjects/ogr_ao.h
index ebbf48e..e626c52 100644
--- a/ogr/ogrsf_frmts/arcobjects/ogr_ao.h
+++ b/ogr/ogrsf_frmts/arcobjects/ogr_ao.h
@@ -1,203 +1,195 @@
-/******************************************************************************
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Standard includes and class definitions ArcObjects OGR driver.
- * Author:   Ragi Yaser Burhum, ragi at burhum.com
- *
- ******************************************************************************
- * Copyright (c) 2009, Ragi Yaser Burhum
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef OGR_AO_H_INCLUDED
-#define OGR_AO_H_INCLUDED
-
-#include "ogrsf_frmts.h"
-
-#include <vector>
-#include "cpl_string.h"
-
-//COM ATL Includes
-#include <atlbase.h> 
-#include <atlcom.h>
-#include <atlctl.h>
-#include <atlstr.h> //CString
-
-using namespace ATL;
-
-// ArcGIS COM Includes
-#import "C:\Program Files (x86)\ArcGIS\com\esriSystem.olb" raw_interfaces_only, raw_native_types, no_namespace, named_guids, exclude("OLE_COLOR", "OLE_HANDLE", "VARTYPE"), rename("min", "esrimin"), rename("max", "esrimax")
-#import "C:\Program Files (x86)\ArcGIS\com\esriGeometry.olb" raw_interfaces_only, raw_native_types, named_guids, exclude("ISegment")
-#import "C:\Program Files (x86)\ArcGIS\com\esriGeoDatabase.olb" raw_interfaces_only, raw_native_types, no_namespace, named_guids
-#import "C:\Program Files (x86)\ArcGIS\com\esriDataSourcesGDB.olb" raw_interfaces_only, raw_native_types, no_namespace, named_guids
-
-
-
-/************************************************************************/
-/*                            AOLayer                                  */
-/************************************************************************/
-
-class AODataSource;
-
-class AOLayer : public OGRLayer
-{
-public:
-
-  AOLayer();
-  virtual ~AOLayer();
-
-  bool Initialize(ITable* pTable);
-
-  const char* GetFIDFieldName() const { return m_strOIDFieldName.c_str(); }
-  const char* GetShapeFieldName() const { return m_strShapeFieldName.c_str(); }
-
-  virtual void        ResetReading();
-  virtual OGRFeature* GetNextFeature();
-  virtual OGRFeature* GetFeature( GIntBig nFeatureId );
-
-  HRESULT GetTable(ITable** ppTable);
-
-
-  virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
-  virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
-                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-  virtual GIntBig     GetFeatureCount( int bForce );
-  virtual OGRErr      SetAttributeFilter( const char *pszQuery );
-  virtual void 	      SetSpatialFilterRect (double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
-  virtual void        SetSpatialFilter( OGRGeometry * );
-  virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
-                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
-
-/*
-  virtual OGRErr      CreateField( OGRFieldDefn *poFieldIn,
-  int bApproxOK );
-
-  virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-  virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-  virtual OGRErr      DeleteFeature( GIntBig nFID );
-*/
-   OGRFeatureDefn *    GetLayerDefn() { return m_pFeatureDefn; }
-
-   virtual OGRSpatialReference *GetSpatialRef() { return m_pSRS; }
-
-  virtual int         TestCapability( const char * );
-
-protected:
-    bool OGRFeatureFromAORow(IRow* pRow, OGRFeature** ppFeature);
-    void SwitchToAttributeOnlyFilter();
-    void SwitchToSpatialFilter();
-
-    ITablePtr m_ipTable;
-    OGRFeatureDefn* m_pFeatureDefn;
-    OGRSpatialReference* m_pSRS;
-
-    std::string m_strOIDFieldName;
-    std::string m_strShapeFieldName;
-
-    ICursorPtr m_ipCursor;
-    IQueryFilterPtr m_ipQF;
-
-    std::vector<long> m_OGRFieldToESRIField; //OGR Field Index to ESRI Field Index Mapping
-
-    //buffers are used for avoiding constant reallocation of temp memory
-    unsigned char* m_pBuffer;
-    long  m_bufferSize; //in bytes
-    bool  m_suppressColumnMappingError;
-    bool  m_forceMulti;
-};
-
-/************************************************************************/
-/*                           AODataSource                            */
-/************************************************************************/
-class AODataSource : public OGRDataSource
-{
-
-public:
-  AODataSource();
-  virtual ~AODataSource();
-
-
-  int         Open(IWorkspace* pWorkspace, const char *, int );
-  
-  const char* GetName() { return m_pszName; }
-  int         GetLayerCount() { return static_cast<int>(m_layers.size()); }
-  
-  OGRLayer*   GetLayer( int );
-
-  
-  /*
-  virtual OGRLayer* ICreateLayer( const char *,
-                                 OGRSpatialReference* = NULL,
-                                 OGRwkbGeometryType = wkbUnknown,
-                                 char** = NULL );
-
- */
-  virtual OGRErr DeleteLayer( int );
-
-  int TestCapability( const char * );
-
-  /*
-protected:
-
-  void EnumerateSpatialTables();
-  void OpenSpatialTable( const char* pszTableName );
-*/
-protected:
-  bool LoadLayers(IEnumDataset* pEnumDataset);
-
-  char* m_pszName;
-  std::vector <AOLayer*> m_layers;
-  IWorkspacePtr m_ipWorkspace;
-
-};
-
-/************************************************************************/
-/*                              AODriver                                */
-/************************************************************************/
-
-class AODriver : public OGRSFDriver
-{
-
-public:
-  AODriver();
-  virtual ~AODriver();
-
-  bool Init();
-
-  const char *GetName();
-  virtual OGRDataSource *Open( const char *, int );
-  int TestCapability( const char * );
-  virtual OGRDataSource *CreateDataSource( const char *pszName, char ** = NULL);
-
-  void OpenWorkspace(std::string, IWorkspace** ppWorkspace);
-
-private:
-  bool m_licensedCheckedOut;
-  int  m_productCode;
-  bool m_initialized;
-};
-
-CPL_C_START
-void CPL_DLL RegisterOGRao();
-CPL_C_END
-
-#endif /* ndef _OGR_PG_H_INCLUDED */
-
-
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Standard includes and class definitions ArcObjects OGR driver.
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Ragi Yaser Burhum
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_AO_H_INCLUDED
+#define OGR_AO_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+#include <vector>
+#include "cpl_string.h"
+
+//COM ATL Includes
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlctl.h>
+#include <atlstr.h> //CString
+
+using namespace ATL;
+
+// ArcGIS COM Includes
+#import "C:\Program Files (x86)\ArcGIS\com\esriSystem.olb" raw_interfaces_only, raw_native_types, no_namespace, named_guids, exclude("OLE_COLOR", "OLE_HANDLE", "VARTYPE"), rename("min", "esrimin"), rename("max", "esrimax")
+#import "C:\Program Files (x86)\ArcGIS\com\esriGeometry.olb" raw_interfaces_only, raw_native_types, named_guids, exclude("ISegment")
+#import "C:\Program Files (x86)\ArcGIS\com\esriGeoDatabase.olb" raw_interfaces_only, raw_native_types, no_namespace, named_guids
+#import "C:\Program Files (x86)\ArcGIS\com\esriDataSourcesGDB.olb" raw_interfaces_only, raw_native_types, no_namespace, named_guids
+
+/************************************************************************/
+/*                            AOLayer                                  */
+/************************************************************************/
+
+class AODataSource;
+
+class AOLayer : public OGRLayer
+{
+public:
+
+  AOLayer();
+  virtual ~AOLayer();
+
+  bool Initialize(ITable* pTable);
+
+  const char* GetFIDFieldName() const { return m_strOIDFieldName.c_str(); }
+  const char* GetShapeFieldName() const { return m_strShapeFieldName.c_str(); }
+
+  virtual void        ResetReading() override;
+  virtual OGRFeature* GetNextFeature() override;
+  virtual OGRFeature* GetFeature( GIntBig nFeatureId ) override;
+
+  HRESULT GetTable(ITable** ppTable);
+
+  virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
+  virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+  virtual GIntBig     GetFeatureCount( int bForce ) override;
+  virtual OGRErr      SetAttributeFilter( const char *pszQuery ) override;
+  virtual void        SetSpatialFilterRect (double dfMinX, double dfMinY, double dfMaxX, double dfMaxY) override;
+  virtual void        SetSpatialFilter( OGRGeometry * ) override;
+  virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
+
+/*
+  virtual OGRErr      CreateField( OGRFieldDefn *poFieldIn,
+  int bApproxOK );
+
+  virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+  virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+  virtual OGRErr      DeleteFeature( GIntBig nFID );
+*/
+   OGRFeatureDefn *    GetLayerDefn() override { return m_pFeatureDefn; }
+
+   virtual OGRSpatialReference *GetSpatialRef() override { return m_pSRS; }
+
+  virtual int         TestCapability( const char * ) override;
+
+protected:
+    bool OGRFeatureFromAORow(IRow* pRow, OGRFeature** ppFeature);
+    void SwitchToAttributeOnlyFilter();
+    void SwitchToSpatialFilter();
+
+    ITablePtr m_ipTable;
+    OGRFeatureDefn* m_pFeatureDefn;
+    OGRSpatialReference* m_pSRS;
+
+    std::string m_strOIDFieldName;
+    std::string m_strShapeFieldName;
+
+    ICursorPtr m_ipCursor;
+    IQueryFilterPtr m_ipQF;
+
+    std::vector<long> m_OGRFieldToESRIField; //OGR Field Index to ESRI Field Index Mapping
+
+    //buffers are used for avoiding constant reallocation of temp memory
+    unsigned char* m_pBuffer;
+    long  m_bufferSize; //in bytes
+    bool  m_suppressColumnMappingError;
+    bool  m_forceMulti;
+};
+
+/************************************************************************/
+/*                           AODataSource                            */
+/************************************************************************/
+class AODataSource : public OGRDataSource
+{
+
+public:
+  AODataSource();
+  virtual ~AODataSource();
+
+  int         Open(IWorkspace* pWorkspace, const char *, int );
+
+  const char* GetName() override { return m_pszName; }
+  int         GetLayerCount() override { return static_cast<int>(m_layers.size()); }
+
+  OGRLayer*   GetLayer( int ) override;
+
+  /*
+  virtual OGRLayer* ICreateLayer( const char *,
+                                 OGRSpatialReference* = NULL,
+                                 OGRwkbGeometryType = wkbUnknown,
+                                 char** = NULL );
+
+ */
+  virtual OGRErr DeleteLayer( int ) override;
+
+  int TestCapability( const char * ) override;
+
+  /*
+protected:
+
+  void EnumerateSpatialTables();
+  void OpenSpatialTable( const char* pszTableName );
+*/
+protected:
+  bool LoadLayers(IEnumDataset* pEnumDataset);
+
+  char* m_pszName;
+  std::vector <AOLayer*> m_layers;
+  IWorkspacePtr m_ipWorkspace;
+};
+
+/************************************************************************/
+/*                              AODriver                                */
+/************************************************************************/
+
+class AODriver : public OGRSFDriver
+{
+
+public:
+  AODriver();
+  virtual ~AODriver();
+
+  bool Init();
+
+  const char *GetName() override;
+  virtual OGRDataSource *Open( const char *, int ) override;
+  int TestCapability( const char * ) override;
+  virtual OGRDataSource *CreateDataSource( const char *pszName, char ** = NULL) override;
+
+  static void OpenWorkspace(std::string, IWorkspace** ppWorkspace);
+
+private:
+  bool m_licensedCheckedOut;
+  int  m_productCode;
+  bool m_initialized;
+};
+
+CPL_C_START
+void CPL_DLL RegisterOGRao();
+CPL_C_END
+
+#endif /* ndef _OGR_PG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/avc/GNUmakefile b/ogr/ogrsf_frmts/avc/GNUmakefile
index e690f78..8afd61b 100644
--- a/ogr/ogrsf_frmts/avc/GNUmakefile
+++ b/ogr/ogrsf_frmts/avc/GNUmakefile
@@ -8,7 +8,7 @@ OGR_OBJ =	ogravcbindriver.o ogravcbindatasource.o ogravcbinlayer.o \
 
 AVC_OBJ	=	avc_bin.o avc_binwr.o avc_e00gen.o avc_e00parse.o \
 		avc_e00write.o avc_e00read.o avc_mbyte.o avc_misc.o \
-		avc_rawbin.o 
+		avc_rawbin.o
 
 OBJ =	$(AVC_OBJ) $(OGR_OBJ)
 
@@ -20,4 +20,4 @@ default:	$(O_OBJ:.o=.$(OBJ_EXT))
 clean:
 	rm -f *.o $(O_OBJ)
 
-$(O_OBJ):	ogr_avc.h avc.h 
+$(O_OBJ):	ogr_avc.h avc.h
diff --git a/ogr/ogrsf_frmts/avc/HISTORY.TXT b/ogr/ogrsf_frmts/avc/HISTORY.TXT
index 0522dfc..20d1d40 100644
--- a/ogr/ogrsf_frmts/avc/HISTORY.TXT
+++ b/ogr/ogrsf_frmts/avc/HISTORY.TXT
@@ -1,6 +1,6 @@
 AVCE00 library - Revision History
 =================================
- 
+
 
 Current Version:
 ----------------
@@ -12,7 +12,7 @@ Version 2.0.1 (CVS):
 - Fixed GCC 4.1.x compile warnings related to use of char vs unsigned char
   (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2495)
 
-- Fixed VC++ WIN32 build problems in GDAL/OGR environment 
+- Fixed VC++ WIN32 build problems in GDAL/OGR environment
   (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2500)
 
 - Detect compressed E00 input files and refuse to open them instead of
@@ -35,7 +35,7 @@ Version 2.0.0 (2006-08-17):
     void             AVCE00ReadCloseE00(AVCE00ReadE00Ptr psRead);
     int              AVCE00ReadRewindE00(AVCE00ReadE00Ptr psRead);
     int              AVCE00ReadSeekE00(AVCE00ReadE00Ptr psRead,
-                                       int nOffset, int nWhence); 
+                                       int nOffset, int nWhence);
     void            *AVCE00ReadNextObjectE00(AVCE00ReadE00Ptr psRead,
                                              int bContinue);
 
@@ -44,7 +44,7 @@ Version 2.0.0 (2006-08-17):
 
 - Accept empty subclass names for TX6/TX7 sections (bug 1261)
 
-- Applied patch to remove any embedded '\0' from data line in 
+- Applied patch to remove any embedded '\0' from data line in
   AVCE00GenTableRec()
 
 - Support for reading standalone info tables (just tables, no coverage
@@ -60,15 +60,15 @@ Version 1.3.0 (2005-06-02):
   to discover filename "case" on Unix in AVCAdjustCaseSensitiveFilename.
   http://bugzilla.remotesensing.org/show_bug.cgi?id=314
 
-- Fixed leak in AVCE00ReadOpen() when trying to open something that's 
+- Fixed leak in AVCE00ReadOpen() when trying to open something that's
   not a coverage (bug513)
 
-- Added AVCBinReadObject() to randomly read an object using the index file. 
+- Added AVCBinReadObject() to randomly read an object using the index file.
   Currently only works for Arcs, info records and polygons.  NFW
 
-- Fixed up AVCBinReadObject() to work properly for PC Arc/Info style 
+- Fixed up AVCBinReadObject() to work properly for PC Arc/Info style
   coverages.  Also fixed to use upper/lower case 'X' for index based on
-  base file type. NFW  OGR Bug#493. 
+  base file type. NFW  OGR Bug#493.
 
 - avc_e00write.c: modified to use VSIMkdir().
 
@@ -95,23 +95,23 @@ Version 1.2.1 (2000-11-25):
 - Fixed E00 parsing to properly handle PAL entries with 0 arcs which happen
   to contain a single "0 0 0" entry.
 
-- Fixed E00 generation to correctly format 0-arc PAL records so that 
+- Fixed E00 generation to correctly format 0-arc PAL records so that
   they have a single "0 0 0" (filler) arc record (bug#597)
 
 - Fixed reading of type 40 fields from E00: when a type 40 field is not
-  stored in exponent format then a decimal format may be used but the 
-  decimal position is shifted to the right in the E00 value.  So we have 
-  to shift the decimal point to the left (i.e. divide by 10) as we 
+  stored in exponent format then a decimal format may be used but the
+  decimal position is shifted to the right in the E00 value.  So we have
+  to shift the decimal point to the left (i.e. divide by 10) as we
   interpret the value (bug#599).  Really odd!
 
-- Added a hack to remap type 40 fields bigger than 8 digits to double 
-  precision binary floats while generating E00 output (bug#599).  
-  In E00 format, type 40 fields bigger than 8 digits would lose some 
-  digits of precision and double precision floats can carry up to 18 
-  digits of precision. 
+- Added a hack to remap type 40 fields bigger than 8 digits to double
+  precision binary floats while generating E00 output (bug#599).
+  In E00 format, type 40 fields bigger than 8 digits would lose some
+  digits of precision and double precision floats can carry up to 18
+  digits of precision.
   This hack is enabled using "-DAVC_MAP_TYPE40_TO_DOUBLE" in OPTFLAGS.
 
-- Fixed problem with info/arc####.dat files coming from Windows that 
+- Fixed problem with info/arc####.dat files coming from Windows that
   contained '\\' in the data file path.  Remap '\\' in path to '/' on Unix.
   This problem seems to be new with Arc8 on Windows.
 
@@ -124,7 +124,7 @@ Version 1.2.0 (2000-10-17):
 
 - Added Japanese (multibyte characters) support.
 
-- Made validation on new coverage name more flexible (used to accept only 
+- Made validation on new coverage name more flexible (used to accept only
   isalnum() chars and '_')
 
 - Added a case to treat pal.adf files with nPrecision==1011 as double prec.
@@ -180,7 +180,7 @@ Version 0.6 (1999-08-26):
 - Fixed some memory leaks.
 
 - Fixed a Windows-specific bug: the arc.dir was sometimes overwritten when
-  several coverages were created by the same process... likely a buffering 
+  several coverages were created by the same process... likely a buffering
   issue.
 
 Version 0.5 (1999-06-10):
@@ -189,10 +189,10 @@ Version 0.5 (1999-06-10):
 - Overwrite existing arc.dir entries when necessary while creating INFO
   tables.
   The problem was that when same coverage name was used twice with the
-  same info directory... we ended up with 2 sets of tables with the 
+  same info directory... we ended up with 2 sets of tables with the
   same names.
   This happened if a user deleted a coverage directory using "rm".
-  In this case, IMPORT71 reuses and overwrites the old table entry with 
+  In this case, IMPORT71 reuses and overwrites the old table entry with
   the same name in the ARC.DIR... our lib now does the same.
 
 - Created NMAKE makefile.vc for Windows
@@ -207,7 +207,7 @@ Version 0.4 (1999-05-17):
 
 - Added RXP write support
 
-- Fixed problem with double precision RPL sections: the second PAL 
+- Fixed problem with double precision RPL sections: the second PAL
   termination line confused the parser.
 
 - The write library now detects the E00's precision and generate
@@ -219,7 +219,7 @@ Version 0.4 (1999-05-17):
   a new one.  Also force name to contain only alnum() and '_'.
 
 - INFO TABLES: the name of the system attributes (COVER#/COVER-ID) are
-               now changed to the new coverage name when creating a new 
+               now changed to the new coverage name when creating a new
 	       info table.
 
 - Fixed problem parsing an E00 INFO table that contains 0 records
@@ -229,7 +229,7 @@ Version 0.4 (1999-05-17):
 Version 0.3 (1999-05-10):
 -------------------------
 
-- Added support to create coverages from E00 (alpha version).  Most file 
+- Added support to create coverages from E00 (alpha version).  Most file
   types are supported, but only single precision has been tested on Linux.
   There are still a number of known problems with the write support.
 
@@ -240,15 +240,15 @@ Version 0.3 (1999-05-10):
   floats in double-precision tables.
 
 - Fixed the following problem:
-   In some cases, the "number of records" field for a table in the 
-   arc.dir does not correspond to the real number of records 
+   In some cases, the "number of records" field for a table in the
+   arc.dir does not correspond to the real number of records
    in the data file.  In this kind of situation, the number of
    records returned by Arc/Info in an E00 file will be based
    on the real data file size, and not on the value from the arc.dir.
 
 - Tested on a CPL_MSB system
 
- 
+
 Version 0.2 (1999-02-24):
 -------------------------
 
@@ -261,8 +261,8 @@ Version 0.2 (1999-02-24):
 
 - Tested with routes coverage
 
-- Added support for "par.adf": Double precision coverages have their 
-  tolerances stored in a file named "par.adf" which is different from 
+- Added support for "par.adf": Double precision coverages have their
+  tolerances stored in a file named "par.adf" which is different from
   the "tol.adf" we find in single precision coverages...
 
 - PRJ section: remove '\r' at end of lines when coverage generated on
@@ -274,12 +274,12 @@ Version 0.2 (1999-02-24):
   we should probably do it as well!
 
 - Changed AVCE00ReadOpen() so that the coverage name does not absolutely
-  have to be terminated by a "/".  Now, you can either pass the name of 
+  have to be terminated by a "/".  Now, you can either pass the name of
   the coverage directory (with or without a '/' at the end), or the path
-  to one of the files in the coverage directory. 
+  to one of the files in the coverage directory.
 
 - Added extra line after the end of PAL sections in double precision
-  coverages: 
+  coverages:
         -1         0         0         0         0         0         0
  0.00000000000000E+00 0.00000000000000E+00
   Even if I consider this second line to be a glitch, I guess I have to
@@ -294,7 +294,7 @@ Version 0.2 (1999-02-24):
 Version 0.1 (1999-01-31):
 -------------------------
 
-First version, supports the most common file types, still several 
+First version, supports the most common file types, still several
 know problems.
 
 
diff --git a/ogr/ogrsf_frmts/avc/avc.h b/ogr/ogrsf_frmts/avc/avc.h
index b67d4f4..e194f60 100644
--- a/ogr/ogrsf_frmts/avc/avc.h
+++ b/ogr/ogrsf_frmts/avc/avc.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: avc.h,v 1.25 2008/07/23 20:51:38 dmorissette Exp $
+ * $Id: avc.h 35933 2016-10-25 16:46:26Z goatbar $
  *
  * Name:     avc.h
  * Project:  Arc/Info Vector coverage (AVC) BIN<->E00 conversion library
@@ -133,7 +133,6 @@ CPL_C_START
  *--------------------------------------------------------------------*/
 #define AVC_VERSION "2.0.0 (2006-08-17)"
 
-
 /* Coverage precision
  */
 #define AVC_DEFAULT_PREC   0
@@ -163,7 +162,6 @@ typedef enum
     AVCFileTABLE
 }AVCFileType;
 
-
 /* Read or Write access flag
  */
 typedef enum
@@ -193,7 +191,6 @@ typedef enum
     AVCLittleEndian  /* CPL_LSB, Intel ordering */
 } AVCByteOrder;
 
-
 /* Macros to establish byte ordering for each coverage type
  * The rule until now: all coverage types use big endian (Motorola ordering)
  * except PC Arc/Info coverages variant 1 (AVCCoverPC).
@@ -262,7 +259,6 @@ typedef struct AVCCnt_t
     GInt32      *panLabelIds;
 }AVCCnt;
 
-
 /*---------------------------------------------------------------------
  * AVCLab: Information about a LAB (polygon Label)
  *--------------------------------------------------------------------*/
@@ -293,7 +289,7 @@ typedef struct AVCTxt_t
     GInt32      nTxtId;
     GInt32      nUserId;
     GInt32      nLevel;
-    float       f_1e2;	/* Always (float)-1e+20, even for double precision! */
+    float       f_1e2;  /* Always (float)-1e+20, even for double precision! */
     GInt32      nSymbol;
     GInt32      numVerticesLine;
     GInt32      n28;    /* Unknown value at byte 28 */
@@ -321,7 +317,6 @@ typedef struct AVCRxp_t
     GInt32      n2;
 }AVCRxp;
 
-
 /*---------------------------------------------------------------------
  * AVCTableDef: Definition of an INFO table's structure.
  *               This info is read from several files:
@@ -360,7 +355,6 @@ typedef struct AVCFieldInfo_t
 #define AVC_FT_BININT   50
 #define AVC_FT_BINFLOAT 60
 
-
 typedef struct AVCTableDef_t
 {
     /* Stuff read from the arc.dir file
@@ -381,8 +375,7 @@ typedef struct AVCTableDef_t
     /* Field information read from the arc####.nit file
      */
     AVCFieldInfo *pasFieldDef;
-
-}AVCTableDef;
+} AVCTableDef;
 
 typedef struct AVCField_t
 {
@@ -391,7 +384,7 @@ typedef struct AVCField_t
     float       fFloat;
     double      dDouble;
     GByte       *pszStr;
-}AVCField;
+} AVCField;
 
 /*---------------------------------------------------------------------
  * Stuff related to buffered reading of raw binary files
@@ -417,8 +410,7 @@ typedef struct AVCRawBinFile_t
     /* Handle on dataset's multibyte character encoding info. */
     AVCDBCSInfo *psDBCSInfo;
 
-}AVCRawBinFile;
-
+} AVCRawBinFile;
 
 /*---------------------------------------------------------------------
  * Stuff related to reading and writing binary coverage files
@@ -466,7 +458,7 @@ typedef struct AVCBinFile_t
         char         **papszPrj;
     }cur;
 
-}AVCBinFile;
+} AVCBinFile;
 
 /*---------------------------------------------------------------------
  * Stuff related to the generation of E00
@@ -542,7 +534,6 @@ typedef struct AVCE00ParseInfo_t
     int         nBufSize;
 }AVCE00ParseInfo;
 
-
 /*---------------------------------------------------------------------
  * Stuff related to the transparent binary -> E00 conversion
  *--------------------------------------------------------------------*/
@@ -616,7 +607,6 @@ typedef struct AVCE00ReadInfoE00_t
 
 } *AVCE00ReadE00Ptr;
 
-
 /* E00 generation steps... tells the AVCE00Read*() functions which
  * parts of the given E00 file are currently being processed.
  */
@@ -810,7 +800,6 @@ AVCTableDef *AVCE00ParseNextTableDefLine(AVCE00ParseInfo *psInfo,
 AVCField    *AVCE00ParseNextTableRecLine(AVCE00ParseInfo *psInfo,
                                          const char *pszLine);
 
-
 /*---------------------------------------------------------------------
  * Misc. functions shared by several parts of the lib.
  *--------------------------------------------------------------------*/
diff --git a/ogr/ogrsf_frmts/avc/avc_bin.c b/ogr/ogrsf_frmts/avc/avc_bin.c
index 0404f8d..b0fd4a1 100644
--- a/ogr/ogrsf_frmts/avc/avc_bin.c
+++ b/ogr/ogrsf_frmts/avc/avc_bin.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: avc_bin.c,v 1.30 2008/07/23 20:51:38 dmorissette Exp $
+ * $Id: avc_bin.c 36457 2016-11-23 00:18:37Z rouault $
  *
  * Name:     avc_bin.c
  * Project:  Arc/Info vector coverage (AVC)  BIN->E00 conversion library
@@ -570,6 +570,7 @@ void *AVCBinReadObject(AVCBinFile *psFile, int iObjIndex )
 {
     int	 bIndexed = FALSE;
     int  nObjectOffset, nRecordSize=0, nRecordStart = 0, nLen;
+    /* cppcheck-suppress unreadVariable */
     char szExt[4] = {0,0,0,0};
     char *pszExt = szExt;
 
@@ -1863,6 +1864,7 @@ char **AVCBinReadListTables(const char *pszInfoPath, const char *pszCoverName,
      * letters extension.
      *----------------------------------------------------------------*/
     if (pszCoverName != NULL)
+        // cppcheck-suppress bufferAccessOutOfBounds
         snprintf(szNameToFind, sizeof(szNameToFind), "%-.28s.", pszCoverName);
     nLen = (int)strlen(szNameToFind);
 
@@ -1940,6 +1942,8 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
     int            i;
     size_t         nFnameLen;
 
+    memset(&sTableDef, 0, sizeof(sTableDef));
+    sTableDef.numFields = 0;
     sTableDef.pasFieldDef = NULL;
 
     /* Alloc a buffer big enough for the longest possible filename...
@@ -1986,6 +1990,14 @@ AVCBinFile *_AVCBinReadOpenTable(const char *pszInfoPath,
         CPLFree(pszFname);
         return NULL;
     }
+    /* To please Coverity */
+    if( sTableDef.numFields < 0 || sTableDef.numFields >= 32767 )
+    {
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Invalid numFields in %s", pszTableName);
+        CPLFree(pszFname);
+        return NULL;
+    }
 
     /*-----------------------------------------------------------------
      * Establish the location of the data file... depends on the
diff --git a/ogr/ogrsf_frmts/avc/avc_binwr.c b/ogr/ogrsf_frmts/avc/avc_binwr.c
index 07125b5..7f0317f 100644
--- a/ogr/ogrsf_frmts/avc/avc_binwr.c
+++ b/ogr/ogrsf_frmts/avc/avc_binwr.c
@@ -1,4 +1,4 @@
-/* $Id: avc_binwr.c,v 1.18 2008/07/23 20:51:38 dmorissette Exp $
+/* $Id: avc_binwr.c 36381 2016-11-21 10:29:21Z rouault $
  *
  * Name:     avc_binwr.c
  * Project:  Arc/Info vector coverage (AVC)  E00->BIN conversion library
@@ -323,10 +323,14 @@ int AVCBinWriteHeader(AVCBinFile *psFile)
     int          nStatus=0;
     GBool        bHeader = TRUE;
 
+    memset(&sHeader, 0, sizeof(sHeader));
+
     /*-----------------------------------------------------------------
      * Set the appropriate header information for this file type.
      *----------------------------------------------------------------*/
-    sHeader.nPrecision = sHeader.nRecordSize = sHeader.nLength = 0;
+    sHeader.nPrecision = 0;
+    sHeader.nRecordSize = 0;
+    sHeader.nLength = 0;
     sHeader.nSignature = 9994;
     switch(psFile->eFileType)
     {
diff --git a/ogr/ogrsf_frmts/avc/avc_e00gen.c b/ogr/ogrsf_frmts/avc/avc_e00gen.c
index d5aef54..04e498d 100644
--- a/ogr/ogrsf_frmts/avc/avc_e00gen.c
+++ b/ogr/ogrsf_frmts/avc/avc_e00gen.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: avc_e00gen.c,v 1.18 2008/07/23 20:51:38 dmorissette Exp $
+ * $Id: avc_e00gen.c 36380 2016-11-21 10:21:20Z rouault $
  *
  * Name:     avc_e00gen.c
  * Project:  Arc/Info vector coverage (AVC)  BIN->E00 conversion library
@@ -869,10 +869,8 @@ const char *AVCE00GenTxt(AVCE00GenInfo *psInfo, AVCTxt *psTxt, GBool bCont)
          * (This is a little bit less efficient, but will give much easier
          *  code to read ;-)
          *------------------------------------------------------------*/
-        double  dXY[15];
+        double  dXY[15] = { 0.0 };
         int     i, nFirstValue, numValuesPerLine;
-        for(i=0; i<14; i++)
-            dXY[i] = 0.0;
 
         dXY[14] = psTxt->dHeight;
 
diff --git a/ogr/ogrsf_frmts/avc/avc_e00parse.c b/ogr/ogrsf_frmts/avc/avc_e00parse.c
index c04a5d4..1711544 100644
--- a/ogr/ogrsf_frmts/avc/avc_e00parse.c
+++ b/ogr/ogrsf_frmts/avc/avc_e00parse.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: avc_e00parse.c,v 1.19 2008/07/23 20:51:38 dmorissette Exp $
+ * $Id: avc_e00parse.c 37451 2017-02-25 15:38:43Z rouault $
  *
  * Name:     avc_e00parse.c
  * Project:  Arc/Info vector coverage (AVC)  E00->BIN conversion library
@@ -1964,7 +1964,7 @@ static AVCField   *_AVCE00ParseTableRecord(AVCE00ParseInfo *psInfo)
     AVCFieldInfo *pasDef;
     AVCTableDef *psTableDef;
     int         i, nType, nSize;
-    char        szFormat[10];
+    char        szFormat[20];
     char        *pszBuf, szTmp[30];
 
     pasFields =  psInfo->cur.pasFields;
diff --git a/ogr/ogrsf_frmts/avc/avc_e00read.c b/ogr/ogrsf_frmts/avc/avc_e00read.c
index c558cfb..a1dac87 100644
--- a/ogr/ogrsf_frmts/avc/avc_e00read.c
+++ b/ogr/ogrsf_frmts/avc/avc_e00read.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: avc_e00read.c,v 1.28 2008/07/30 19:22:18 dmorissette Exp $
+ * $Id: avc_e00read.c 34524 2016-07-03 02:47:25Z goatbar $
  *
  * Name:     avc_e00read.c
  * Project:  Arc/Info vector coverage (AVC)  BIN->E00 conversion library
diff --git a/ogr/ogrsf_frmts/avc/avc_e00write.c b/ogr/ogrsf_frmts/avc/avc_e00write.c
index 3c11c57..5475982 100644
--- a/ogr/ogrsf_frmts/avc/avc_e00write.c
+++ b/ogr/ogrsf_frmts/avc/avc_e00write.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: avc_e00write.c,v 1.21 2008/07/23 20:51:38 dmorissette Exp $
+ * $Id: avc_e00write.c 34524 2016-07-03 02:47:25Z goatbar $
  *
  * Name:     avc_e00write.c
  * Project:  Arc/Info vector coverage (AVC)  E00->BIN conversion library
diff --git a/ogr/ogrsf_frmts/avc/avc_mbyte.c b/ogr/ogrsf_frmts/avc/avc_mbyte.c
index b98049e..94a5d64 100644
--- a/ogr/ogrsf_frmts/avc/avc_mbyte.c
+++ b/ogr/ogrsf_frmts/avc/avc_mbyte.c
@@ -1,4 +1,4 @@
-/* $Id: avc_mbyte.c,v 1.4 2008/07/23 20:51:38 dmorissette Exp $
+/* $Id: avc_mbyte.c 36763 2016-12-09 22:10:55Z rouault $
  *
  * Name:     avc_mbyte.c
  * Project:  Arc/Info vector coverage (AVC)  E00->BIN conversion library
@@ -377,16 +377,16 @@ static const GByte *_AVCJapanese2ArcDBCS(AVCDBCSInfo *psDBCSInfo,
          */
         psDBCSInfo->nDBCSEncoding = _AVCDetectJapaneseEncoding(pszLine);
 
-/*
+#if 0
         if (psDBCSInfo->nDBCSEncoding == AVC_CODE_JAP_SHIFTJIS)
         {
-            printf("Found Japanese Shift-JIS encoding\n");
+            printf("Found Japanese Shift-JIS encoding\n");/*ok*/
         }
         else if (psDBCSInfo->nDBCSEncoding == AVC_CODE_JAP_EUC)
         {
-            printf("Found Japanese EUC encoding\n");
+            printf("Found Japanese EUC encoding\n");/*ok*/
         }
-*/
+#endif
     }
 
     for(iDst=0; *pszLine && iDst < nMaxOutputLen; pszLine++)
diff --git a/ogr/ogrsf_frmts/avc/avc_mbyte.h b/ogr/ogrsf_frmts/avc/avc_mbyte.h
index 432fb5f..39bf935 100644
--- a/ogr/ogrsf_frmts/avc/avc_mbyte.h
+++ b/ogr/ogrsf_frmts/avc/avc_mbyte.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: avc_mbyte.h,v 1.4 2008/07/23 20:51:38 dmorissette Exp $
+ * $Id: avc_mbyte.h 35903 2016-10-24 12:09:43Z goatbar $
  *
  * Name:     avc.h
  * Project:  Arc/Info Vector coverage (AVC) BIN<->E00 conversion library
@@ -64,7 +64,6 @@ CPL_C_START
 #define AVC_CODE_JAP_SHIFTJIS   1
 #define AVC_CODE_JAP_EUC        2
 
-
 /*---------------------------------------------------------------------
  * We use the following structure to keep track of DBCS info.
  *--------------------------------------------------------------------*/
diff --git a/ogr/ogrsf_frmts/avc/avc_misc.c b/ogr/ogrsf_frmts/avc/avc_misc.c
index d837711..228c6dd 100644
--- a/ogr/ogrsf_frmts/avc/avc_misc.c
+++ b/ogr/ogrsf_frmts/avc/avc_misc.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: avc_misc.c,v 1.9 2005/06/03 03:49:59 daniel Exp $
+ * $Id: avc_misc.c 36763 2016-12-09 22:10:55Z rouault $
  *
  * Name:     avc_misc.c
  * Project:  Arc/Info vector coverage (AVC)  BIN<->E00 conversion library
@@ -424,7 +424,7 @@ int  AVCPrintRealValue(char *pszBuf, size_t nBufLen, int nPrecision, AVCFileType
     static int numExpDigits=-1;
     int        nLen = 0;
 
-    /* WIN32 systems' printf for floating point output generates 3
+    /* WIN32 systems' printf() for floating point output generates 3
      * digits exponents (ex: 1.23E+012), but E00 files must have 2 digits
      * exponents (ex: 1.23E+12).
      * Run a test (only once per prg execution) to establish the number
diff --git a/ogr/ogrsf_frmts/avc/avc_rawbin.c b/ogr/ogrsf_frmts/avc/avc_rawbin.c
index c450f40..d82e9a1 100644
--- a/ogr/ogrsf_frmts/avc/avc_rawbin.c
+++ b/ogr/ogrsf_frmts/avc/avc_rawbin.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: avc_rawbin.c,v 1.14 2008/07/23 20:51:38 dmorissette Exp $
+ * $Id: avc_rawbin.c 34524 2016-07-03 02:47:25Z goatbar $
  *
  * Name:     avc_rawbin.c
  * Project:  Arc/Info vector coverage (AVC)  BIN->E00 conversion library
diff --git a/ogr/ogrsf_frmts/avc/ogr_avc.h b/ogr/ogrsf_frmts/avc/ogr_avc.h
index db53a28..6cf3650 100644
--- a/ogr/ogrsf_frmts/avc/ogr_avc.h
+++ b/ogr/ogrsf_frmts/avc/ogr_avc.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_avc.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_avc.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Arc/Info Coverage (E00 & Binary) Reader
  * Purpose:  Declarations for OGR wrapper classes for coverage access.
@@ -49,12 +49,12 @@ class OGRAVCLayer : public OGRLayer
     AVCFileType         eSectionType;
 
     int                 SetupFeatureDefinition( const char *pszName );
-    int                 AppendTableDefinition( AVCTableDef *psTableDef );
+    bool                AppendTableDefinition( AVCTableDef *psTableDef );
 
-    int                 MatchesSpatialFilter( void * );
+    bool                MatchesSpatialFilter( void * );
     OGRFeature          *TranslateFeature( void * );
 
-    int                 TranslateTableFields( OGRFeature *poFeature,
+    bool                TranslateTableFields( OGRFeature *poFeature,
                                               int nFieldBase,
                                               AVCTableDef *psTableDef,
                                               AVCField *pasFields );
@@ -62,13 +62,13 @@ class OGRAVCLayer : public OGRLayer
   public:
                         OGRAVCLayer( AVCFileType eSectionType,
                                      OGRAVCDataSource *poDS );
-    			~OGRAVCLayer();
+    virtual ~OGRAVCLayer();
 
-    OGRFeatureDefn *	GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -79,11 +79,11 @@ class OGRAVCDataSource : public OGRDataSource
 {
   protected:
     OGRSpatialReference *poSRS;
-    char		*pszCoverageName;
+    char                *pszCoverageName;
 
   public:
-		        OGRAVCDataSource();
-    			~OGRAVCDataSource();
+                        OGRAVCDataSource();
+    virtual ~OGRAVCDataSource();
 
     virtual OGRSpatialReference *GetSpatialRef();
 
@@ -106,32 +106,32 @@ class OGRAVCBinLayer : public OGRAVCLayer
     AVCBinFile          *hFile;
 
     OGRAVCBinLayer      *poArcLayer;
-    int                 bNeedReset;
+    bool                bNeedReset;
 
-    char		szTableName[128];
+    char                szTableName[128];
     AVCBinFile          *hTable;
     int                 nTableBaseField;
     int                 nTableAttrIndex;
 
     int                 nNextFID;
 
-    int                 FormPolygonGeometry( OGRFeature *poFeature,
+    bool                FormPolygonGeometry( OGRFeature *poFeature,
                                              AVCPal *psPAL );
 
-    int                 CheckSetupTable();
-    int                 AppendTableFields( OGRFeature *poFeature );
+    bool                CheckSetupTable();
+    bool                AppendTableFields( OGRFeature *poFeature );
 
   public:
                         OGRAVCBinLayer( OGRAVCBinDataSource *poDS,
                                         AVCE00Section *psSectionIn );
 
-    			~OGRAVCBinLayer();
+                        ~OGRAVCBinLayer();
 
-    void		ResetReading();
-    OGRFeature *	GetNextFeature();
-    OGRFeature *	GetFeature( GIntBig nFID );
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    OGRFeature *        GetFeature( GIntBig nFID ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -141,23 +141,23 @@ class OGRAVCBinLayer : public OGRAVCLayer
 class OGRAVCBinDataSource : public OGRAVCDataSource
 {
     OGRLayer            **papoLayers;
-    int			nLayers;
+    int                 nLayers;
 
-    char		*pszName;
+    char                *pszName;
 
     AVCE00ReadPtr       psAVC;
 
   public:
-    			OGRAVCBinDataSource();
-    			~OGRAVCBinDataSource();
+                        OGRAVCBinDataSource();
+                        ~OGRAVCBinDataSource();
 
-    int			Open( const char *, int bTestOpen );
+    int                 Open( const char *, int bTestOpen );
 
-    const char	        *GetName() { return pszName; }
-    int			GetLayerCount() { return nLayers; }
-    OGRLayer		*GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     AVCE00ReadPtr       GetInfo() { return psAVC; }
 };
@@ -175,7 +175,7 @@ class OGRAVCE00Layer : public OGRAVCLayer
     AVCE00ReadE00Ptr    psRead;
     OGRAVCE00Layer      *poArcLayer;
     int                 nFeatureCount;
-    int                 bNeedReset;
+    bool                bNeedReset;
     int                 nNextFID;
 
     AVCE00Section       *psTableSection;
@@ -185,20 +185,20 @@ class OGRAVCE00Layer : public OGRAVCLayer
     int                 nTableBaseField;
     int                 nTableAttrIndex;
 
-    int                 FormPolygonGeometry( OGRFeature *poFeature,
+    bool                FormPolygonGeometry( OGRFeature *poFeature,
                                              AVCPal *psPAL );
   public:
                         OGRAVCE00Layer( OGRAVCDataSource *poDS,
                                         AVCE00Section *psSectionIn );
 
-    			~OGRAVCE00Layer();
+                        ~OGRAVCE00Layer();
 
-    void		ResetReading();
-    OGRFeature *	GetNextFeature();
-    OGRFeature *GetFeature( GIntBig nFID );
-    GIntBig GetFeatureCount(int bForce);
-    int CheckSetupTable(AVCE00Section *psTblSectionIn);
-    int AppendTableFields( OGRFeature *poFeature );
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    OGRFeature *GetFeature( GIntBig nFID ) override;
+    GIntBig GetFeatureCount(int bForce) override;
+    bool CheckSetupTable(AVCE00Section *psTblSectionIn);
+    bool AppendTableFields( OGRFeature *poFeature );
 };
 
 /************************************************************************/
@@ -217,18 +217,17 @@ class OGRAVCE00DataSource : public OGRAVCDataSource
 
   public:
     OGRAVCE00DataSource();
-    ~OGRAVCE00DataSource();
+    virtual ~OGRAVCE00DataSource();
 
     int Open(const char *, int bTestOpen);
 
     AVCE00ReadE00Ptr GetInfo() { return psE00; }
-    const char *GetName() { return pszName; }
-    int GetLayerCount() { return nLayers; }
+    const char *GetName() override { return pszName; }
+    int GetLayerCount() override { return nLayers; }
 
-    OGRLayer *GetLayer( int );
-    int TestCapability( const char * );
-    virtual OGRSpatialReference *GetSpatialRef();
+    OGRLayer *GetLayer( int ) override;
+    int TestCapability( const char * ) override;
+    virtual OGRSpatialReference *GetSpatialRef() override;
 };
 
-
 #endif /* OGR_AVC_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp b/ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp
index 8aaceee..421beaa 100644
--- a/ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravcbindatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogravcbindatasource.cpp 32122 2015-12-11 16:01:28Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCBinDataSource class.
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravcbindatasource.cpp 32122 2015-12-11 16:01:28Z goatbar $");
+CPL_CVSID("$Id: ogravcbindatasource.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                        OGRAVCBinDataSource()                         */
diff --git a/ogr/ogrsf_frmts/avc/ogravcbindriver.cpp b/ogr/ogrsf_frmts/avc/ogravcbindriver.cpp
index 2ba2bc7..8049454 100644
--- a/ogr/ogrsf_frmts/avc/ogravcbindriver.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravcbindriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogravcbindriver.cpp 32122 2015-12-11 16:01:28Z goatbar $
  *
  * Project:  OGR
  * Purpose:  OGRAVCBinDriver implementation (Arc/Info Binary Coverages)
@@ -29,7 +28,7 @@
 
 #include "ogr_avc.h"
 
-CPL_CVSID("$Id: ogravcbindriver.cpp 32122 2015-12-11 16:01:28Z goatbar $");
+CPL_CVSID("$Id: ogravcbindriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
diff --git a/ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp b/ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp
index 1ae9a9a..7175d22 100644
--- a/ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravcbinlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogravcbinlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCBinLayer class.
@@ -32,7 +31,9 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravcbinlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+#include <cstdlib>
+
+CPL_CVSID("$Id: ogravcbinlayer.cpp 36472 2016-11-23 16:38:20Z rouault $");
 
 /************************************************************************/
 /*                           OGRAVCBinLayer()                           */
@@ -44,7 +45,7 @@ OGRAVCBinLayer::OGRAVCBinLayer( OGRAVCBinDataSource *poDSIn,
     m_psSection(psSectionIn),
     hFile(NULL),
     poArcLayer(NULL),
-    bNeedReset(FALSE),
+    bNeedReset(false),
     hTable(NULL),
     nTableBaseField(-1),
     nTableAttrIndex(-1),
@@ -103,7 +104,7 @@ void OGRAVCBinLayer::ResetReading()
         hFile = NULL;
     }
 
-    bNeedReset = FALSE;
+    bNeedReset = false;
     nNextFID = 1;
 
     if( hTable != NULL )
@@ -154,7 +155,7 @@ OGRFeature *OGRAVCBinLayer::GetFeature( GIntBig nFID )
     }
     else
     {
-        bNeedReset = TRUE;
+        bNeedReset = true;
         pFeature = AVCBinReadObject( hFile, (int)nFID );
     }
 
@@ -164,9 +165,7 @@ OGRFeature *OGRAVCBinLayer::GetFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
 /*      Translate the feature.                                          */
 /* -------------------------------------------------------------------- */
-    OGRFeature *poFeature;
-
-    poFeature = TranslateFeature( pFeature );
+    OGRFeature *poFeature = TranslateFeature( pFeature );
     if( poFeature == NULL )
         return NULL;
 
@@ -253,8 +252,8 @@ int OGRAVCBinLayer::TestCapability( const char * pszCap )
 /*      them into the appropriate OGR geometry on the target feature.   */
 /************************************************************************/
 
-int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
-                                         AVCPal *psPAL )
+bool OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
+                                          AVCPal *psPAL )
 
 {
 /* -------------------------------------------------------------------- */
@@ -273,7 +272,7 @@ int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
         }
 
         if( poArcLayer == NULL )
-            return FALSE;
+            return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -296,13 +295,13 @@ int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
             continue;
 
         OGRFeature *poArc
-            = poArcLayer->GetFeature( ABS(psPAL->pasArcs[iArc].nArcId) );
+            = poArcLayer->GetFeature( std::abs(psPAL->pasArcs[iArc].nArcId) );
 
         if( poArc == NULL )
-            return FALSE;
+            return false;
 
         if( poArc->GetGeometryRef() == NULL )
-            return FALSE;
+            return false;
 
         oArcs.addGeometry( poArc->GetGeometryRef() );
         OGRFeature::DestroyFeature( poArc );
@@ -327,21 +326,28 @@ int OGRAVCBinLayer::FormPolygonGeometry( OGRFeature *poFeature,
 /*      definition.                                                     */
 /************************************************************************/
 
-int OGRAVCBinLayer::CheckSetupTable()
+bool OGRAVCBinLayer::CheckSetupTable()
 
 {
     if( szTableName[0] == '\0' )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Scan for the indicated section.                                 */
 /* -------------------------------------------------------------------- */
     AVCE00ReadPtr psInfo
         = static_cast<OGRAVCBinDataSource *>( poDS )->GetInfo();
-    char szPaddedName[65];
+    const size_t BUFSIZE = 32;
+    char szPaddedName[BUFSIZE+1] = { 0 };
 
-    snprintf( szPaddedName, sizeof(szPaddedName), "%s%32s", szTableName, " " );
-    szPaddedName[32] = '\0';
+    // Fill szPaddedName with szTableName up to 32 chars and fill the remaining
+    // ones with ' '
+    strncpy( szPaddedName, szTableName, BUFSIZE );
+    if( strlen(szTableName) < BUFSIZE )
+    {
+        memset( szPaddedName + strlen(szTableName), ' ',
+                BUFSIZE - strlen(szTableName) );
+    }
 
     AVCE00Section *l_psSection = NULL;
     for( int iSection = 0; iSection < psInfo->numSections; iSection++ )
@@ -354,7 +360,7 @@ int OGRAVCBinLayer::CheckSetupTable()
     if( l_psSection == NULL )
     {
         szTableName[0] = '\0';
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -367,7 +373,7 @@ int OGRAVCBinLayer::CheckSetupTable()
     if( hTable == NULL )
     {
         szTableName[0] = '\0';
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -384,21 +390,21 @@ int OGRAVCBinLayer::CheckSetupTable()
 
     hTable = NULL;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                         AppendTableFields()                          */
 /************************************************************************/
 
-int OGRAVCBinLayer::AppendTableFields( OGRFeature *poFeature )
+bool OGRAVCBinLayer::AppendTableFields( OGRFeature *poFeature )
 
 {
     AVCE00ReadPtr psInfo
         = static_cast<OGRAVCBinDataSource *>( poDS)->GetInfo();
 
     if( szTableName[0] == '\0' )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Open the table if it is currently closed.                       */
@@ -411,7 +417,7 @@ int OGRAVCBinLayer::AppendTableFields( OGRFeature *poFeature )
     }
 
     if( hTable == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Read the info record.                                           */
@@ -422,16 +428,13 @@ int OGRAVCBinLayer::AppendTableFields( OGRFeature *poFeature )
 /*      nTableAttrIndex will already be setup to refer to the           */
 /*      PolyId field.                                                   */
 /* -------------------------------------------------------------------- */
-    int nRecordId;
-
-    if( nTableAttrIndex == -1 )
-        nRecordId = static_cast<int>( poFeature->GetFID() );
-    else
-        nRecordId = poFeature->GetFieldAsInteger( nTableAttrIndex );
+    const int nRecordId = nTableAttrIndex == -1
+        ? static_cast<int>( poFeature->GetFID() )
+        : poFeature->GetFieldAsInteger( nTableAttrIndex );
 
     void *hRecord = AVCBinReadObject( hTable, nRecordId );
     if( hRecord == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Translate it.                                                   */
diff --git a/ogr/ogrsf_frmts/avc/ogravcdatasource.cpp b/ogr/ogrsf_frmts/avc/ogravcdatasource.cpp
index 94f82aa..8de8097 100644
--- a/ogr/ogrsf_frmts/avc/ogravcdatasource.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravcdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogravcdatasource.cpp 32122 2015-12-11 16:01:28Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCDataSource class.
@@ -29,7 +28,7 @@
 
 #include "ogr_avc.h"
 
-CPL_CVSID("$Id: ogravcdatasource.cpp 32122 2015-12-11 16:01:28Z goatbar $");
+CPL_CVSID("$Id: ogravcdatasource.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                          OGRAVCDataSource()                          */
diff --git a/ogr/ogrsf_frmts/avc/ogravce00datasource.cpp b/ogr/ogrsf_frmts/avc/ogravce00datasource.cpp
index ac85bd3..9688ab8 100644
--- a/ogr/ogrsf_frmts/avc/ogravce00datasource.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravce00datasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogravce00datasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCE00DataSource class.
@@ -33,16 +32,18 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravce00datasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogravce00datasource.cpp 35903 2016-10-24 12:09:43Z goatbar $");
 
 /************************************************************************/
 /*                        OGRAVCE00DataSource()                         */
 /************************************************************************/
 
-OGRAVCE00DataSource::OGRAVCE00DataSource()
-    : nLayers(0), pszName(NULL), psE00(NULL), papoLayers(NULL)
-{
-}
+OGRAVCE00DataSource::OGRAVCE00DataSource() :
+    nLayers(0),
+    pszName(NULL),
+    psE00(NULL),
+    papoLayers(NULL)
+{}
 
 /************************************************************************/
 /*                        ~OGRAVCE00DataSource()                        */
@@ -182,7 +183,7 @@ int OGRAVCE00DataSource::CheckAddTable( AVCE00Section *psTblSection )
     int nCount = 0;
     for (int i = 0; i < nLayers; ++i)
     {
-        if (papoLayers[i]->CheckSetupTable(psTblSection))
+        if( papoLayers[i]->CheckSetupTable(psTblSection) )
             ++nCount;
     }
     return nCount;
@@ -220,7 +221,6 @@ OGRSpatialReference *OGRAVCE00DataSource::GetSpatialRef()
     if (psE00 == NULL)
         return NULL;
 
-
     for( int iSection = 0; iSection < psE00->numSections; iSection++ )
     {
         AVCE00Section *psSec = psE00->pasSections + iSection;
diff --git a/ogr/ogrsf_frmts/avc/ogravce00driver.cpp b/ogr/ogrsf_frmts/avc/ogravce00driver.cpp
index 9adccf9..e77ff6f 100644
--- a/ogr/ogrsf_frmts/avc/ogravce00driver.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravce00driver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogravcbindriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $
  *
  * Project:  OGR
  * Purpose:  OGRAVCE00Driver implementation (Arc/Info E00ary Coverages)
@@ -29,7 +28,7 @@
 
 #include "ogr_avc.h"
 
-CPL_CVSID("$Id: ogravcbindriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogravce00driver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
diff --git a/ogr/ogrsf_frmts/avc/ogravce00layer.cpp b/ogr/ogrsf_frmts/avc/ogravce00layer.cpp
index b9f0296..1fad5a6 100644
--- a/ogr/ogrsf_frmts/avc/ogravce00layer.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravce00layer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogravce00layer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCE00Layer class.
@@ -34,27 +33,29 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravce00layer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+#include <cstdlib>
+
+CPL_CVSID("$Id: ogravce00layer.cpp 35952 2016-10-26 17:31:27Z goatbar $");
 
 /************************************************************************/
 /*                           OGRAVCE00Layer()                           */
 /************************************************************************/
 
 OGRAVCE00Layer::OGRAVCE00Layer( OGRAVCDataSource *poDSIn,
-                                AVCE00Section *psSectionIn )
-        : OGRAVCLayer( psSectionIn->eType, poDSIn ),
-          psSection(psSectionIn),
-          psRead(NULL),
-          poArcLayer(NULL),
-          nFeatureCount(-1),
-          bNeedReset(0),
-          nNextFID(1),
-          psTableSection(NULL),
-          psTableRead(NULL),
-          pszTableFilename(NULL),
-          nTablePos(0),
-          nTableBaseField(0),
-          nTableAttrIndex(-1)
+                                AVCE00Section *psSectionIn ) :
+    OGRAVCLayer( psSectionIn->eType, poDSIn ),
+    psSection(psSectionIn),
+    psRead(NULL),
+    poArcLayer(NULL),
+    nFeatureCount(-1),
+    bNeedReset(false),
+    nNextFID(1),
+    psTableSection(NULL),
+    psTableRead(NULL),
+    pszTableFilename(NULL),
+    nTablePos(0),
+    nTableBaseField(0),
+    nTableAttrIndex(-1)
 {
     SetupFeatureDefinition( psSection->pszName );
     /* psRead = AVCE00ReadOpenE00(psSection->pszFilename); */
@@ -127,7 +128,7 @@ void OGRAVCE00Layer::ResetReading()
         AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0);
     }
 
-    bNeedReset = FALSE;
+    bNeedReset = false;
     nNextFID = 1;
 }
 
@@ -169,7 +170,7 @@ OGRFeature *OGRAVCE00Layer::GetFeature( GIntBig nFID )
     }
     else
     {
-        bNeedReset = TRUE;
+        bNeedReset = true;
 
         if (nNextFID > nFID)
         {
@@ -283,8 +284,8 @@ int OGRAVCE00Layer::TestCapability( const char * pszCap )
 /*      them into the appropriate OGR geometry on the target feature.   */
 /************************************************************************/
 
-int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
-                                         AVCPal *psPAL )
+bool OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
+                                          AVCPal *psPAL )
 {
 /* -------------------------------------------------------------------- */
 /*      Try to find the corresponding ARC layer if not already          */
@@ -302,7 +303,7 @@ int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
         }
 
         if( poArcLayer == NULL )
-            return FALSE;
+            return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -325,13 +326,13 @@ int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
             continue;
 
         OGRFeature *poArc
-            = poArcLayer->GetFeature( ABS(psPAL->pasArcs[iArc].nArcId) );
+            = poArcLayer->GetFeature( std::abs(psPAL->pasArcs[iArc].nArcId) );
 
         if( poArc == NULL )
-            return FALSE;
+            return false;
 
         if( poArc->GetGeometryRef() == NULL )
-            return FALSE;
+            return false;
 
         oArcs.addGeometry( poArc->GetGeometryRef() );
         OGRFeature::DestroyFeature( poArc );
@@ -355,10 +356,10 @@ int OGRAVCE00Layer::FormPolygonGeometry( OGRFeature *poFeature,
 /*      definition.                                                     */
 /************************************************************************/
 
-int OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
+bool OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
 {
     if (psTableRead)
-        return FALSE;
+        return false;
 
     const char *pszTableType = NULL;
     switch (eSectionType)
@@ -381,7 +382,7 @@ int OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
 /*      a case insensitive check.                                       */
 /* -------------------------------------------------------------------- */
     if( pszTableType == NULL )
-        return FALSE;
+        return false;
 
     int iCheckOff = 0;
     for( ;
@@ -394,7 +395,7 @@ int OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
     }
 
     if( psTblSectionIn->pszName[iCheckOff] == '\0' )
-        return FALSE;
+        return false;
 
     psTableSection = psTblSectionIn;
 
@@ -403,18 +404,18 @@ int OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
 /* -------------------------------------------------------------------- */
     psTableRead = AVCE00ReadOpenE00(psTblSectionIn->pszFilename);
     if (psTableRead == NULL)
-        return FALSE;
+        return false;
 
     /* advance to the specified line number */
     if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
     {
         AVCE00ReadCloseE00(psTableRead);
         psTableRead = NULL;
-        return FALSE;
+        return false;
     }
 
     AVCE00ReadNextObjectE00(psTableRead);
-    bNeedReset = 1;
+    bNeedReset = true;
 
     pszTableFilename = CPLStrdup(psTblSectionIn->pszFilename);
     nTableBaseField = poFeatureDefn->GetFieldCount();
@@ -440,18 +441,18 @@ int OGRAVCE00Layer::CheckSetupTable(AVCE00Section *psTblSectionIn)
 /* -------------------------------------------------------------------- */
     /* AVCE00ReadCloseE00( psTableRead ); */
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                         AppendTableFields()                          */
 /************************************************************************/
 
-int OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
+bool OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
 
 {
     if (psTableRead == NULL)
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Open the table if it is currently closed.                       */
@@ -460,14 +461,14 @@ int OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
     {
         psTableRead = AVCE00ReadOpenE00(pszTableFilename);
         if (psTableRead == NULL)
-            return FALSE;
+            return false;
 
         /* Advance to the specified line number */
         if (AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0)
         {
             AVCE00ReadCloseE00(psTableRead);
             psTableRead = NULL;
-            return FALSE;
+            return false;
         }
         nTablePos = 0;
     }
@@ -481,17 +482,14 @@ int OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
 /*      nTableAttrIndex will already be setup to refer to the           */
 /*      PolyId field.                                                   */
 /* -------------------------------------------------------------------- */
-    int nRecordId;
-
-    if( nTableAttrIndex == -1 )
-        nRecordId = static_cast<int>( poFeature->GetFID() );
-    else
-        nRecordId = poFeature->GetFieldAsInteger( nTableAttrIndex );
+    const int nRecordId = nTableAttrIndex == -1
+        ? static_cast<int>( poFeature->GetFID() )
+        : poFeature->GetFieldAsInteger( nTableAttrIndex );
 
     if (nRecordId <= nTablePos)
     {
         if( AVCE00ReadGotoSectionE00(psTableRead, psTableSection, 0) != 0 )
-            return FALSE;
+            return false;
         nTablePos = 0;
     }
 
@@ -504,7 +502,7 @@ int OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
     while (NULL != hRecord && nTablePos < nRecordId);
 
     if( hRecord == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Translate it.                                                   */
@@ -514,7 +512,6 @@ int OGRAVCE00Layer::AppendTableFields( OGRFeature *poFeature )
                                  static_cast<AVCField *>( hRecord ) );
 }
 
-
 GIntBig OGRAVCE00Layer::GetFeatureCount(int bForce)
 {
     if (m_poAttrQuery != NULL || m_poFilterGeom != NULL)
diff --git a/ogr/ogrsf_frmts/avc/ogravclayer.cpp b/ogr/ogrsf_frmts/avc/ogravclayer.cpp
index b8fa3dd..378c306 100644
--- a/ogr/ogrsf_frmts/avc/ogravclayer.cpp
+++ b/ogr/ogrsf_frmts/avc/ogravclayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogravclayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRAVCLayer class.  This is the base class for E00
@@ -34,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogravclayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogravclayer.cpp 35273 2016-09-01 15:39:56Z goatbar $");
 
 /************************************************************************/
 /*                           OGRAVCLayer()                           */
@@ -371,11 +370,11 @@ OGRFeature *OGRAVCLayer::TranslateFeature( void *pAVCFeature )
 /*                        MatchesSpatialFilter()                        */
 /************************************************************************/
 
-int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
+bool OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
 
 {
     if( m_poFilterGeom == NULL )
-        return TRUE;
+        return true;
 
     switch( eSectionType )
     {
@@ -403,10 +402,10 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
                       && psV2->y > m_sFilterEnvelope.MaxY) )
                   /* This segment is completely outside extents */;
               else
-                  return TRUE;
+                  return true;
           }
 
-          return FALSE;
+          return false;
       }
 
 /* ==================================================================== */
@@ -424,9 +423,9 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
               || psPAL->sMax.x < m_sFilterEnvelope.MinX
               || psPAL->sMin.y > m_sFilterEnvelope.MaxY
               || psPAL->sMax.y < m_sFilterEnvelope.MinY )
-              return FALSE;
+              return false;
           else
-              return TRUE;
+              return true;
       }
 
 /* ==================================================================== */
@@ -440,9 +439,9 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
               || psCNT->sCoord.x > m_sFilterEnvelope.MaxX
               || psCNT->sCoord.y < m_sFilterEnvelope.MinY
               || psCNT->sCoord.y > m_sFilterEnvelope.MaxY )
-              return FALSE;
+              return false;
           else
-              return TRUE;
+              return true;
       }
 
 /* ==================================================================== */
@@ -456,9 +455,9 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
               || psLAB->sCoord1.x > m_sFilterEnvelope.MaxX
               || psLAB->sCoord1.y < m_sFilterEnvelope.MinY
               || psLAB->sCoord1.y > m_sFilterEnvelope.MaxY )
-              return FALSE;
+              return false;
           else
-              return TRUE;
+              return true;
       }
 
 /* ==================================================================== */
@@ -470,19 +469,19 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
           AVCTxt *psTXT = static_cast<AVCTxt *>( pFeature );
 
           if( psTXT->numVerticesLine == 0 )
-              return TRUE;
+              return true;
 
           if( psTXT->pasVertices[0].x < m_sFilterEnvelope.MinX
               || psTXT->pasVertices[0].x > m_sFilterEnvelope.MaxX
               || psTXT->pasVertices[0].y < m_sFilterEnvelope.MinY
               || psTXT->pasVertices[0].y > m_sFilterEnvelope.MaxY )
-              return FALSE;
+              return false;
 
-          return TRUE;
+          return true;
       }
 
       default:
-        return TRUE;
+        return true;
     }
 }
 
@@ -493,7 +492,7 @@ int OGRAVCLayer::MatchesSpatialFilter( void *pFeature )
 /*      definition from the coverage.                                   */
 /************************************************************************/
 
-int OGRAVCLayer::AppendTableDefinition( AVCTableDef *psTableDef )
+bool OGRAVCLayer::AppendTableDefinition( AVCTableDef *psTableDef )
 
 {
     for( int iField = 0; iField < psTableDef->numFields; iField++ )
@@ -542,7 +541,7 @@ int OGRAVCLayer::AppendTableDefinition( AVCTableDef *psTableDef )
 /*                        TranslateTableFields()                        */
 /************************************************************************/
 
-int OGRAVCLayer::TranslateTableFields( OGRFeature *poFeature,
+bool OGRAVCLayer::TranslateTableFields( OGRFeature *poFeature,
                                        int nFieldBase,
                                        AVCTableDef *psTableDef,
                                        AVCField *pasFields )
@@ -596,10 +595,10 @@ int OGRAVCLayer::TranslateTableFields( OGRFeature *poFeature,
         }
         else
         {
-            CPLAssert( FALSE );
-            return FALSE;
+            CPLAssert( false );
+            return false;
         }
     }
 
-    return TRUE;
+    return true;
 }
diff --git a/ogr/ogrsf_frmts/bna/ogr_bna.h b/ogr/ogrsf_frmts/bna/ogr_bna.h
index bef50c0..5521385 100644
--- a/ogr/ogrsf_frmts/bna/ogr_bna.h
+++ b/ogr/ogrsf_frmts/bna/ogr_bna.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_bna.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_bna.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  BNA Translator
  * Purpose:  Definition of classes for OGR .bna driver.
@@ -54,13 +54,13 @@ class OGRBNALayer : public OGRLayer
     int                bWriter;
 
     int                nIDs;
-    int                eof;
-    int                failed;
+    bool               eof;
+    bool               failed;
     int                curLine;
     int                nNextFID;
     VSILFILE*          fpBNA;
     int                nFeatures;
-    int                partialIndexTable;
+    bool               partialIndexTable;
     OffsetAndLine*     offsetAndLineFeaturesTable;
 
     BNAFeatureType     bnaFeatureType;
@@ -84,18 +84,17 @@ class OGRBNALayer : public OGRLayer
                                              OffsetAndLine* offsetAndLineFeaturesTable,
                                              int partialIndexTable);
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
-    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK );
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
+    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    OGRFeature *        GetFeature( GIntBig nFID );
-
-    int                 TestCapability( const char * );
+    OGRFeature *        GetFeature( GIntBig nFID ) override;
 
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -113,10 +112,10 @@ class OGRBNADataSource : public OGRDataSource
 
     /*  Export related */
     VSILFILE                *fpOutput; /* Virtual file API */
-    int                 bUseCRLF;
+    bool                bUseCRLF;
     int                 bMultiLine;
     int                 nbOutID;
-    int                 bEllipsesAsEllipses;
+    bool                bEllipsesAsEllipses;
     int                 nbPairPerLine;
     int                 coordinatePrecision;
     char*               pszCoordinateSeparator;
@@ -126,10 +125,10 @@ class OGRBNADataSource : public OGRDataSource
                         ~OGRBNADataSource();
 
     VSILFILE                *GetOutputFP() { return fpOutput; }
-    int                 GetUseCRLF() { return bUseCRLF; }
+    bool                GetUseCRLF() { return bUseCRLF; }
     int                 GetMultiLine() { return bMultiLine; }
     int                 GetNbOutId() { return nbOutID; }
-    int                 GetEllipsesAsEllipses() { return bEllipsesAsEllipses; }
+    bool                GetEllipsesAsEllipses() { return bEllipsesAsEllipses; }
     int                 GetNbPairPerLine() { return nbPairPerLine; }
     int                 GetCoordinatePrecision() { return coordinatePrecision; }
     const char*         GetCoordinateSeparator() { return pszCoordinateSeparator; }
@@ -140,17 +139,17 @@ class OGRBNADataSource : public OGRDataSource
     int                 Create( const char *pszFilename,
                               char **papszOptions );
 
-    const char*         GetName() { return pszName; }
+    const char*         GetName() override { return pszName; }
 
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer*           GetLayer( int );
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer*           GetLayer( int ) override;
 
     OGRLayer *          ICreateLayer( const char * pszLayerName,
                                     OGRSpatialReference *poSRS,
                                     OGRwkbGeometryType eType,
-                                    char ** papszOptions );
+                                    char ** papszOptions ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_BNA_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp b/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
index 17975a3..6e29ac8 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnadatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrbnadatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  BNA Translator
  * Purpose:  Implements OGRBNADataSource class
@@ -33,6 +32,8 @@
 #include "cpl_csv.h"
 #include "ogrbnaparser.h"
 
+CPL_CVSID("$Id: ogrbnadatasource.cpp 35903 2016-10-24 12:09:43Z goatbar $");
+
 /************************************************************************/
 /*                          OGRBNADataSource()                          */
 /************************************************************************/
@@ -41,16 +42,16 @@ OGRBNADataSource::OGRBNADataSource() :
     pszName(NULL),
     papoLayers(NULL),
     nLayers(0),
-    bUpdate(FALSE),
+    bUpdate(false),
     fpOutput(NULL),
-    bUseCRLF(FALSE),
+    bUseCRLF(false),
     bMultiLine(FALSE),
     nbOutID(0),
-    bEllipsesAsEllipses(FALSE),
+    bEllipsesAsEllipses(false),
     nbPairPerLine(FALSE),
     coordinatePrecision(0),
     pszCoordinateSeparator(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                         ~OGRBNADataSource()                          */
@@ -155,12 +156,11 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
     int ok = FALSE;
 
     pszName = CPLStrdup( pszFilename );
-    bUpdate = bUpdateIn;
+    bUpdate = CPL_TO_BOOL(bUpdateIn);
 
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
     if (fp)
     {
-        BNARecord* record;
         int curLine = 0;
         static const char* const layerRadixName[]
             = { "points", "polygons", "lines", "ellipses"};
@@ -168,7 +168,7 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
             = { wkbPoint, wkbMultiPolygon, wkbLineString, wkbPolygon };
 
 #if defined(BNA_FAST_DS_OPEN)
-        record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
+        BNARecord* record = BNA_GetNextRecord(fp, &ok, &curLine, FALSE, BNA_READ_NONE);
         BNA_FreeRecord(record);
 
         if (ok)
@@ -176,8 +176,8 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
             nLayers = 4;
 
             papoLayers = static_cast<OGRBNALayer **>(
-                CPLMalloc(nLayers * sizeof(OGRBNALayer*) ) );
-            for(i=0;i<4;i++)
+                CPLMalloc(nLayers * sizeof(OGRBNALayer*)));
+            for( i = 0; i < 4; i++ )
                 papoLayers[i] = new OGRBNALayer(
                     pszFilename,
                     layerRadixName[i],
@@ -188,8 +188,9 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
         int nFeatures[4] = { 0, 0, 0, 0 };
         OffsetAndLine* offsetAndLineFeaturesTable[4] = { NULL, NULL, NULL, NULL };
         int nIDs[4] = {0, 0, 0, 0};
-        int partialIndexTable = TRUE;
+        bool partialIndexTable = true;
 
+        BNARecord* record = NULL;
         while(1)
         {
             int offset = static_cast<int>( VSIFTellL(fp) );
@@ -208,7 +209,7 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
                 ok = TRUE;
 
                 /* and we have finally build the whole index table */
-                partialIndexTable = FALSE;
+                partialIndexTable = false;
                 break;
             }
 
@@ -254,7 +255,6 @@ int OGRBNADataSource::Open( const char * pszFilename, int bUpdateIn)
     return ok;
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
@@ -264,7 +264,7 @@ int OGRBNADataSource::Create( const char *pszFilename,
 {
     if( fpOutput != NULL)
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return FALSE;
     }
 
@@ -299,29 +299,29 @@ int OGRBNADataSource::Create( const char *pszFilename,
     if( pszCRLFFormat == NULL )
     {
 #ifdef WIN32
-        bUseCRLF = TRUE;
+        bUseCRLF = true;
 #else
-        bUseCRLF = FALSE;
+        bUseCRLF = false;
 #endif
     }
     else if( EQUAL(pszCRLFFormat,"CRLF") )
-        bUseCRLF = TRUE;
+        bUseCRLF = true;
     else if( EQUAL(pszCRLFFormat,"LF") )
-        bUseCRLF = FALSE;
+        bUseCRLF = false;
     else
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "LINEFORMAT=%s not understood, use one of CRLF or LF.",
                   pszCRLFFormat );
 #ifdef WIN32
-        bUseCRLF = TRUE;
+        bUseCRLF = true;
 #else
-        bUseCRLF = FALSE;
+        bUseCRLF = false;
 #endif
     }
 
     /* Multi line or single line format ? */
-    bMultiLine = CSLFetchBoolean( papszOptions, "MULTILINE", TRUE);
+    bMultiLine = CPLFetchBool( papszOptions, "MULTILINE", true);
 
     /* Number of identifiers per record */
     const char* pszNbOutID = CSLFetchNameValue ( papszOptions, "NB_IDS");
@@ -353,7 +353,8 @@ int OGRBNADataSource::Create( const char *pszFilename,
     }
 
     /* Ellipses export as ellipses or polygons ? */
-    bEllipsesAsEllipses = CSLFetchBoolean( papszOptions, "ELLIPSES_AS_ELLIPSES", TRUE);
+    bEllipsesAsEllipses =
+        CPLFetchBool( papszOptions, "ELLIPSES_AS_ELLIPSES", true);
 
     /* Number of coordinate pairs per line */
     const char* pszNbPairPerLine = CSLFetchNameValue( papszOptions, "NB_PAIRS_PER_LINE");
diff --git a/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp b/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
index e26059a..84f2c37 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnadriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrbnadriver.cpp
  *
  * Project:  BNA Translator
  * Purpose:  Implements OGRBNADriver.
@@ -30,6 +29,8 @@
 #include "ogr_bna.h"
 #include "cpl_conv.h"
 
+CPL_CVSID("$Id: ogrbnadriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp b/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
index 05bd32b..d542320 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnalayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrbnalayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  BNA Translator
  * Purpose:  Implements OGRBNALayer class.
@@ -33,6 +32,8 @@
 #include "cpl_csv.h"
 #include "ogr_p.h"
 
+CPL_CVSID("$Id: ogrbnalayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
 /************************************************************************/
 /*                            OGRBNALayer()                             */
 /*                                                                      */
@@ -50,8 +51,8 @@ OGRBNALayer::OGRBNALayer( const char *pszFilename,
     poDS(poDSIn),
     bWriter(bWriterIn),
     nIDs(nIDsIn),
-    eof(FALSE),
-    failed(FALSE),
+    eof(false),
+    failed(false),
     curLine(0),
     nNextFID(0),
     nFeatures(0),
@@ -69,7 +70,7 @@ OGRBNALayer::OGRBNALayer( const char *pszFilename,
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( eLayerGeomType );
     SetDescription( poFeatureDefn->GetName() );
-    this->bnaFeatureType = bnaFeatureTypeIn;
+    bnaFeatureType = bnaFeatureTypeIn;
 
     if (! bWriter )
     {
@@ -134,7 +135,7 @@ void OGRBNALayer::SetFeatureIndexTable(
 {
     nFeatures = nFeaturesIn;
     offsetAndLineFeaturesTable = offsetAndLineFeaturesTableIn;
-    partialIndexTable = partialIndexTableIn;
+    partialIndexTable = CPL_TO_BOOL(partialIndexTableIn);
 }
 
 /************************************************************************/
@@ -146,24 +147,23 @@ void OGRBNALayer::ResetReading()
 {
     if( fpBNA == NULL )
         return;
-    eof = FALSE;
-    failed = FALSE;
+    eof = false;
+    failed = false;
     curLine = 0;
     nNextFID = 0;
     CPL_IGNORE_RET_VAL(VSIFSeekL( fpBNA, 0, SEEK_SET ));
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
 OGRFeature *OGRBNALayer::GetNextFeature()
 {
-    if (failed || eof || fpBNA == NULL)
+    if( failed || eof || fpBNA == NULL )
         return NULL;
 
-    while(1)
+    while( true )
     {
         int ok = FALSE;
         const int offset = static_cast<int>( VSIFTellL(fpBNA) );
@@ -180,16 +180,16 @@ OGRFeature *OGRBNALayer::GetNextFeature()
         if (ok == FALSE)
         {
             BNA_FreeRecord(record);
-            failed = TRUE;
+            failed = true;
             return NULL;
         }
         if (record == NULL)
         {
             /* end of file */
-            eof = TRUE;
+            eof = true;
 
             /* and we have finally build the whole index table */
-            partialIndexTable = FALSE;
+            partialIndexTable = false;
             return NULL;
         }
 
@@ -228,14 +228,12 @@ OGRFeature *OGRBNALayer::GetNextFeature()
     }
 }
 
-
 /************************************************************************/
 /*                      WriteFeatureAttributes()                        */
 /************************************************************************/
 
-void OGRBNALayer::WriteFeatureAttributes(VSILFILE* fp, OGRFeature *poFeature )
+void OGRBNALayer::WriteFeatureAttributes( VSILFILE* fp, OGRFeature *poFeature )
 {
-    OGRFieldDefn *poFieldDefn;
     int nbOutID = poDS->GetNbOutId();
     if (nbOutID < 0)
         nbOutID = poFeatureDefn->GetFieldCount();
@@ -243,8 +241,8 @@ void OGRBNALayer::WriteFeatureAttributes(VSILFILE* fp, OGRFeature *poFeature )
     {
         if (i < poFeatureDefn->GetFieldCount())
         {
-            poFieldDefn = poFeatureDefn->GetFieldDefn( i );
-            if( poFeature->IsFieldSet( i ) )
+            OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
+            if( poFeature->IsFieldSetAndNotNull( i ) )
             {
                 if (poFieldDefn->GetType() == OFTReal)
                 {
@@ -303,7 +301,7 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if (poDS->GetUseCRLF())
+    if( poDS->GetUseCRLF() )
     {
         eol[0] = 13;
         eol[1] = 10;
@@ -353,7 +351,7 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
             double firstX = ring->getX(0);
             double firstY = ring->getY(0);
             int nBNAPoints = ring->getNumPoints();
-            int is_ellipse = FALSE;
+            bool is_ellipse = false;
 
             /* This code tries to detect an ellipse in a polygon geometry */
             /* This will only work presumably on ellipses already read from a BNA file */
@@ -378,17 +376,17 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
                 {
                     double major_radius = fabs(firstX - center1X);
                     double minor_radius = fabs(quarterY - center1Y);
-                    is_ellipse = TRUE;
+                    is_ellipse = true;
                     for(int i=0;i<360;i++)
                     {
                         if (!(fabs(center1X + major_radius * cos(i * (M_PI / 180)) - ring->getX(i)) < 1e-5 &&
                               fabs(center1Y + minor_radius * sin(i * (M_PI / 180)) - ring->getY(i)) < 1e-5))
                         {
-                            is_ellipse = FALSE;
+                            is_ellipse = false;
                             break;
                         }
                     }
-                    if ( is_ellipse == TRUE )
+                    if( is_ellipse )
                     {
                         WriteFeatureAttributes(fp, poFeature);
                         CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "2"));
@@ -401,7 +399,7 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
                 }
             }
 
-            if ( is_ellipse == FALSE)
+            if( !is_ellipse )
             {
                 int nInteriorRings = polygon->getNumInteriorRings();
                 for(int i=0;i<nInteriorRings;i++)
@@ -448,8 +446,9 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
             OGRMultiPolygon* multipolygon = (OGRMultiPolygon*)poGeom;
             int N = multipolygon->getNumGeometries();
             int nBNAPoints = 0;
-            double firstX = 0, firstY = 0;
-            for(int i=0;i<N;i++)
+            double firstX = 0.0;
+            double firstY = 0.0;
+            for( int i = 0; i < N; i++ )
             {
                 OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i);
                 OGRLinearRing* ring = polygon->getExteriorRing();
@@ -554,8 +553,6 @@ OGRErr OGRBNALayer::ICreateFeature( OGRFeature *poFeature )
     return OGRERR_NONE;
 }
 
-
-
 /************************************************************************/
 /*                            CreateField()                             */
 /************************************************************************/
@@ -570,7 +567,6 @@ OGRErr OGRBNALayer::CreateField( OGRFieldDefn *poField, int /* bApproxOK */ )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           BuildFeatureFromBNARecord()                */
 /************************************************************************/
@@ -604,7 +600,8 @@ OGRFeature *OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long fid)
         double firstX = record->tabCoords[0][0];
         double firstY = record->tabCoords[0][1];
         int isFirstPolygon = 1;
-        double secondaryFirstX = 0, secondaryFirstY = 0;
+        double secondaryFirstX = 0.0;
+        double secondaryFirstY = 0.0;
 
         OGRLinearRing* ring = new OGRLinearRing ();
         ring->setCoordinateDimension(2);
@@ -724,7 +721,7 @@ OGRFeature *OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long fid)
         }
         else
         {
-            int isValidGeometry;
+            int isValidGeometry = FALSE;
             poFeature->SetGeometryDirectly(
                 OGRGeometryFactory::organizePolygons(
                     reinterpret_cast<OGRGeometry**>( tabPolygons ),
@@ -772,13 +769,12 @@ OGRFeature *OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long fid)
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                           FastParseUntil()                           */
 /************************************************************************/
 void OGRBNALayer::FastParseUntil ( int interestFID)
 {
-    if (partialIndexTable)
+    if( partialIndexTable )
     {
         ResetReading();
 
@@ -808,16 +804,16 @@ void OGRBNALayer::FastParseUntil ( int interestFID)
                                        BNA_READ_NONE);
             if (ok == FALSE)
             {
-                failed = TRUE;
+                failed = true;
                 return;
             }
             if (record == NULL)
             {
                 /* end of file */
-                eof = TRUE;
+                eof = true;
 
                 /* and we have finally build the whole index table */
-                partialIndexTable = FALSE;
+                partialIndexTable = false;
                 return;
             }
 
@@ -858,11 +854,11 @@ OGRFeature *  OGRBNALayer::GetFeature( GIntBig nFID )
     if (nFID >= nFeatures)
         return NULL;
 
-    int ok;
     if( VSIFSeekL( fpBNA, offsetAndLineFeaturesTable[nFID].offset, SEEK_SET ) < 0 )
         return NULL;
 
     curLine = offsetAndLineFeaturesTable[nFID].line;
+    int ok = FALSE;
     BNARecord* record
         = BNA_GetNextRecord(fpBNA, &ok, &curLine, TRUE, bnaFeatureType);
 
diff --git a/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp b/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp
index 1b269f0..874335c 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp
+++ b/ogr/ogrsf_frmts/bna/ogrbnaparser.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrbnaparser.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  BNA Parser
  * Purpose:  Parse a BNA record
@@ -32,6 +31,8 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
+CPL_CVSID("$Id: ogrbnaparser.cpp 36776 2016-12-10 11:17:47Z rouault $");
+
 void BNA_FreeRecord(BNARecord* record)
 {
   if (record)
@@ -64,17 +65,19 @@ const char* BNA_FeatureTypeToStr(BNAFeatureType featureType)
   }
 }
 
+#ifdef DEBUG_VERBOSE
 void BNA_Display(BNARecord* record)
 {
-  fprintf(stderr, "\"%s\", \"%s\", \"%s\", %s\n",
+  fprintf(stderr, "\"%s\", \"%s\", \"%s\", %s\n", /*ok*/
           record->ids[0] ? record->ids[0] : "",
           record->ids[1] ? record->ids[1] : "",
           record->ids[2] ? record->ids[2] : "",
           BNA_FeatureTypeToStr(record->featureType));
   for( int i = 0; i < record->nCoords; i++ )
-    fprintf( stderr, "%f, %f\n", record->tabCoords[i][0],
+    fprintf( stderr, "%f, %f\n", record->tabCoords[i][0], /*ok*/
              record->tabCoords[i][1] );
 }
+#endif
 
 /*
 For a description of the format, see http://www.softwright.com/faq/support/boundary_file_bna_format.html
@@ -158,17 +161,17 @@ static int BNA_GetLine(char szLineBuffer[LINE_BUFFER_SIZE+1], VSILFILE* f)
         return BNA_LINE_EOF;
     }
 
-    int bFoundEOL = FALSE;
+    bool bFoundEOL = false;
     while (*ptrCurLine)
     {
         if (*ptrCurLine == 0x0d || *ptrCurLine == 0x0a)
         {
-            bFoundEOL = TRUE;
+            bFoundEOL = true;
             break;
         }
         ptrCurLine ++;
     }
-    if (!bFoundEOL)
+    if( !bFoundEOL )
     {
         if (nRead < LINE_BUFFER_SIZE)
             return BNA_LINE_OK;
@@ -180,11 +183,11 @@ static int BNA_GetLine(char szLineBuffer[LINE_BUFFER_SIZE+1], VSILFILE* f)
     {
         if (ptrCurLine == szLineBuffer + LINE_BUFFER_SIZE - 1)
         {
-            char c;
+            char c = '\0';
             nRead = static_cast<int>(VSIFReadL(&c, 1, 1, f));
-            if (nRead == 1)
+            if( nRead == 1 )
             {
-                if (c == 0x0a)
+                if( c == 0x0a )
                 {
                     /* Do nothing */
                 }
@@ -224,7 +227,6 @@ static int BNA_GetLine(char szLineBuffer[LINE_BUFFER_SIZE+1], VSILFILE* f)
     return BNA_LINE_OK;
 }
 
-
 BNARecord* BNA_GetNextRecord(VSILFILE* f,
                              int* ok,
                              int* curLine,
@@ -254,7 +256,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
       numChar = 0;
       (*curLine)++;
 
-      int retGetLine = BNA_GetLine(szLineBuffer, f);
+      const int retGetLine = BNA_GetLine(szLineBuffer, f);
       if (retGetLine == BNA_LINE_TOO_LONG)
       {
           detailedErrorMsg = LINE_TOO_LONG;
@@ -277,7 +279,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
         numChar = static_cast<int>(ptrCurLine - ptrBeginLine);
         char c = *ptrCurLine;
         if (c == 0) c = 10;
-        if (inQuotes)
+        if( inQuotes )
         {
           if (c == 10)
           {
@@ -297,7 +299,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
           }
           else if (c == '"')
           {
-            inQuotes = FALSE;
+            inQuotes = false;
           }
           else
           {
@@ -403,7 +405,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
           }
           else if (numField == NB_MIN_BNA_IDS + nbExtraId)
           {
-            int nCoords;
+            int nCoords = 0;
             if (ptrBeginningOfNumber == NULL)
             {
               detailedErrorMsg = INTEGER_NUMBER_EXPECTED;
@@ -418,22 +420,26 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
             }
             else if (nCoords == 1)
             {
-              currentFeatureType = record->featureType = BNA_POINT;
+              currentFeatureType = BNA_POINT;
+              record->featureType = BNA_POINT;
               record->nCoords = 1;
             }
             else if (nCoords == 2)
             {
-              currentFeatureType = record->featureType = BNA_ELLIPSE;
+              currentFeatureType = BNA_ELLIPSE;
+              record->featureType = BNA_ELLIPSE;
               record->nCoords = 2;
             }
             else if (nCoords > 0)
             {
-              currentFeatureType = record->featureType = BNA_POLYGON;
+              currentFeatureType = BNA_POLYGON;
+              record->featureType = BNA_POLYGON;
               record->nCoords = nCoords;
             }
             else
             {
-              currentFeatureType = record->featureType = BNA_POLYLINE;
+              currentFeatureType = BNA_POLYLINE;
+              record->featureType = BNA_POLYLINE;
               record->nCoords = -nCoords;
             }
 
@@ -446,7 +452,8 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
               {
                 if (tmpBufferLength[i] && tmpBuffer[i][0])
                 {
-                  record->ids[i] = (char*)CPLMalloc(tmpBufferLength[i] + 1);
+                  record->ids[i] = static_cast<char *>(
+                      CPLMalloc(tmpBufferLength[i] + 1));
                   tmpBuffer[i][tmpBufferLength[i]] = 0;
                   memcpy(record->ids[i], tmpBuffer[i], tmpBufferLength[i] + 1);
                 }
@@ -511,7 +518,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
         {
           if (numField < NB_MIN_BNA_IDS)
           {
-            inQuotes = TRUE;
+            inQuotes = true;
           }
           else if ( numField >= NB_MIN_BNA_IDS
                     && currentFeatureType == BNA_UNKNOWN)
@@ -524,7 +531,7 @@ BNARecord* BNA_GetNextRecord(VSILFILE* f,
                 goto error;
               }
               nbExtraId ++;
-              inQuotes = TRUE;
+              inQuotes = true;
             }
             else
             {
diff --git a/ogr/ogrsf_frmts/bna/ogrbnaparser.h b/ogr/ogrsf_frmts/bna/ogrbnaparser.h
index 66a3097..921408e 100644
--- a/ogr/ogrsf_frmts/bna/ogrbnaparser.h
+++ b/ogr/ogrsf_frmts/bna/ogrbnaparser.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrbnaparser.h 31955 2015-12-02 06:07:22Z goatbar $
+ * $Id: ogrbnaparser.h 35903 2016-10-24 12:09:43Z goatbar $
  *
  * Project:  BNA Parser header
  * Purpose:  Definition of structures, enums and functions of BNA parser
@@ -27,7 +27,6 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
 #ifndef OGR_BNA_PARSER_INCLUDED
 #define OGR_BNA_PARSER_INCLUDED
 
diff --git a/ogr/ogrsf_frmts/cad/GNUmakefile b/ogr/ogrsf_frmts/cad/GNUmakefile
new file mode 100644
index 0000000..3871b7d
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/GNUmakefile
@@ -0,0 +1,20 @@
+
+include ../../../GDALmake.opt
+
+SUBDIRS-yes := libopencad
+
+OBJ	:= \
+	ogrcaddriver.o \
+	gdalcaddataset.o \
+	ogrcadlayer.o \
+	vsilfileio.o
+
+CPPFLAGS	:=	-I. -I.. -I../.. -Ilibopencad $(CPPFLAGS)
+
+default:	$(foreach d,$(SUBDIRS-yes),$(d)-target) $(O_OBJ:.o=.$(OBJ_EXT))
+
+clean: $(foreach d,$(SUBDIRS-yes),$(d)-clean)
+	rm -f *.o $(O_OBJ)
+	rm -f *~
+
+$(O_OBJ):	ogr_cad.h
diff --git a/ogr/ogrsf_frmts/cad/drv_cad.html b/ogr/ogrsf_frmts/cad/drv_cad.html
new file mode 100644
index 0000000..8cb763b
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/drv_cad.html
@@ -0,0 +1,49 @@
+<html>
+<head>
+    <title>AutoCAD DWG</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>AutoCAD DWG</h1>
+
+OGR DWG support is based on libopencad, so the list of supported DWG (DXF)
+versions can be seen in libopencad documentation. All drawing entities are
+separated into layers as they are in DWG file, not in 1 layer as DXF Driver does.
+<p>
+
+DWG files are considered to have no georeferencing information through OGR.
+Features will all have the following generic attributes:
+
+<ul>
+    <li> CADGeometry: CAD Type of the presented geometry.
+    <li> Thickness: Thickness of the object drawing units (if it's not supported
+        by this type, it is set to 0.0).
+    <li> Color (RGB): IntegerList contains R,G,B components of the color.
+    <li> ExtendedEntity: Where available, extended entity attributes all appended
+        to form a single text attribute.
+</ul>
+
+<h2>Supported Elements</h2>
+
+The following element types are supported:<p>
+
+<ul>
+    <li> POINT: Produces a simple point geometry feature.
+    <li> LINE: Translated as a LINESTRING. Rounded polylines (those with their
+        vertices' budge attributes set) will be tessellated. Single-vertex
+        polylines are translated to POINT.
+    <li> CIRCLE, ARC: Translated as a CIRCULARSTRING.
+    <li> 3DFACE: Translated as POLYGON.
+</ul>
+
+The driver is read-only.
+
+<h3>See also:</h2>
+<ul>
+    <li><a href="https://www.opendesign.com/files/guestdownloads/OpenDesign_Specification_for_.dwg_files.pdf">
+    ODA DWG Reference</a>
+    <li><a href="https://github.com/sandyre/libopencad">Libopencad repository</a>
+</ul>
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/cad/gdalcaddataset.cpp b/ogr/ogrsf_frmts/cad/gdalcaddataset.cpp
new file mode 100644
index 0000000..6259141
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/gdalcaddataset.cpp
@@ -0,0 +1,478 @@
+/*******************************************************************************
+ *  Project: OGR CAD Driver
+ *  Purpose: Implements driver based on libopencad
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, polimax at mail.ru
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016, NextGIS <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "cpl_conv.h"
+#include "gdal_pam.h"
+#include "gdal_proxy.h"
+#include "ogr_cad.h"
+#include "vsilfileio.h"
+
+class CADWrapperRasterBand : public GDALProxyRasterBand
+{
+  GDALRasterBand* poBaseBand;
+
+  protected:
+    virtual GDALRasterBand* RefUnderlyingRasterBand() override { return poBaseBand; }
+
+  public:
+    explicit CADWrapperRasterBand( GDALRasterBand* poBaseBandIn ) :
+                    poBaseBand( poBaseBandIn )
+    {
+        eDataType = poBaseBand->GetRasterDataType();
+        poBaseBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    }
+    virtual ~CADWrapperRasterBand() {}
+};
+
+GDALCADDataset::GDALCADDataset() :
+    poCADFile(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    poRasterDS(NULL),
+    poSpatialReference(NULL)
+{
+    adfGeoTransform[0] = 0.0;
+    adfGeoTransform[1] = 1.0;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = 0.0;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = 1.0;
+}
+
+GDALCADDataset::~GDALCADDataset()
+{
+    if( poRasterDS != NULL )
+    {
+        GDALClose( poRasterDS );
+        poRasterDS = NULL;
+    }
+
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree( papoLayers );
+
+    if( poSpatialReference)
+        poSpatialReference->Release();
+
+    if( poCADFile )
+        delete poCADFile;
+}
+
+void GDALCADDataset::FillTransform(CADImage* pImage, double dfUnits)
+{
+    CADImage::ResolutionUnit eResUnits = pImage->getResolutionUnits();
+    double dfMultiply = 1.0;
+
+    switch( eResUnits ) // 0 == none, 2 == centimeters, 5 == inches;
+    {
+        case CADImage::ResolutionUnit::CENTIMETER:
+            dfMultiply = 100.0 / dfUnits; // Meters to linear units
+            break;
+        case CADImage::ResolutionUnit::INCH:
+            dfMultiply = 0.0254 / dfUnits;
+            break;
+        case CADImage::ResolutionUnit::NONE:
+        default:
+            dfMultiply = 1.0;
+    }
+
+    CADVector oSizePt = pImage->getImageSizeInPx();
+    CADVector oInsPt = pImage->getVertInsertionPoint();
+    CADVector oSizeUnitsPt = pImage->getPixelSizeInACADUnits();
+    adfGeoTransform[0] = oInsPt.getX();
+    adfGeoTransform[3] = oInsPt.getY() + oSizePt.getY() * oSizeUnitsPt.getX() *
+    dfMultiply;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[4] = 0.0;
+
+    adfGeoTransform[1] = oSizeUnitsPt.getX() * dfMultiply;
+    adfGeoTransform[5] = -oSizeUnitsPt.getY() * dfMultiply;
+}
+
+int GDALCADDataset::Open( GDALOpenInfo* poOpenInfo, CADFileIO* pFileIO,
+                          long nSubRasterLayer, long nSubRasterFID )
+{
+    osCADFilename = pFileIO->GetFilePath();
+    SetDescription( poOpenInfo->pszFilename );
+
+    const char * papszReadOptions = CSLFetchNameValueDef(
+                             poOpenInfo->papszOpenOptions, "MODE", "READ_FAST" );
+    const char * papszReadUnsupportedGeoms = CSLFetchNameValueDef(
+        poOpenInfo->papszOpenOptions, "ADD_UNSUPPORTED_GEOMETRIES_DATA", "NO");
+
+    enum CADFile::OpenOptions openOpts = CADFile::READ_FAST;
+    bool bReadUnsupportedGeometries = false;
+    if( EQUAL( papszReadOptions, "READ_ALL" ) )
+    {
+        openOpts = CADFile::READ_ALL;
+    }
+    else if( EQUAL( papszReadOptions, "READ_FASTEST" ) )
+    {
+        openOpts = CADFile::READ_FASTEST;
+    }
+
+    if( EQUAL( papszReadUnsupportedGeoms, "YES") )
+    {
+        bReadUnsupportedGeometries = true;
+    }
+
+    poCADFile = OpenCADFile( pFileIO, openOpts, bReadUnsupportedGeometries );
+
+    if ( GetLastErrorCode() == CADErrorCodes::UNSUPPORTED_VERSION )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "libopencad %s does not support this version of CAD file.\n"
+                  "Supported formats are:\n%s", GetVersionString(), GetCADFormats() );
+        return FALSE;
+    }
+
+    if ( GetLastErrorCode() != CADErrorCodes::SUCCESS )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "libopencad %s does not support this version of CAD file.\nSupported formats: %s",
+                  GetVersionString(), GetCADFormats() );
+        return FALSE;
+    }
+
+    OGRSpatialReference *poSpatialRef = GetSpatialReference();
+    int nRasters = 1;
+
+    if( nSubRasterLayer != -1 && nSubRasterFID != -1 )
+    {
+        // Indicates that subdataset from CAD layer number nSubRasterLayer and
+        // FID nSubRasterFID is request
+        nRasters = 2;
+    }
+    else
+    {
+        // Fill metadata
+        const CADHeader& header = poCADFile->getHeader();
+        for( size_t i = 0; i < header.getSize(); ++i )
+        {
+            short nCode = header.getCode( static_cast<int>( i ) );
+            const CADVariant& oVal = header.getValue( nCode );
+            GDALDataset::SetMetadataItem( header.getValueName( nCode ),
+                                                        oVal.getString().c_str());
+        }
+
+        // Reading content of .prj file, or extracting it from CAD if not present
+        nLayers = 0;
+        // FIXME: We allocate extra memory, do we need more strict policy here?
+        papoLayers = static_cast<OGRCADLayer**>( CPLMalloc( sizeof( OGRCADLayer* ) *
+                                                  poCADFile->GetLayersCount() ) );
+
+        int nEncoding = GetCadEncoding();
+        for( size_t i = 0; i < poCADFile->GetLayersCount(); ++i )
+        {
+            CADLayer &oLayer = poCADFile->GetLayer( i );
+            if( poOpenInfo->nOpenFlags & GDAL_OF_VECTOR &&
+                oLayer.getGeometryCount() > 0 )
+            {
+                papoLayers[nLayers++] = new OGRCADLayer( oLayer, poSpatialRef,
+                                                         nEncoding);
+            }
+
+            if( poOpenInfo->nOpenFlags & GDAL_OF_RASTER )
+            {
+                for( size_t j = 0; j < oLayer.getImageCount(); ++j )
+                {
+                    nSubRasterLayer = static_cast<long>( i );
+                    nSubRasterFID = static_cast<long>( j );
+                    GDALDataset::SetMetadataItem( CPLSPrintf("SUBDATASET_%d_NAME",
+                        nRasters),
+                        CPLSPrintf("CAD:%s:%ld:%ld", osCADFilename.c_str(),
+                            nSubRasterLayer, nSubRasterFID), "SUBDATASETS" );
+                    GDALDataset::SetMetadataItem( CPLSPrintf("SUBDATASET_%d_DESC",
+                        nRasters),
+                        CPLSPrintf("%s - %ld", oLayer.getName().c_str(),
+                                    nSubRasterFID), "SUBDATASETS" );
+                    nRasters++;
+                }
+            }
+        }
+        // If nRasters == 2 we have the only one raster in CAD file
+    }
+
+    // The only one raster layer in dataset is present or subdataset is request
+    if( nRasters == 2 )
+    {
+        CADLayer &oLayer = poCADFile->GetLayer( nSubRasterLayer );
+        CADImage* pImage = oLayer.getImage( nSubRasterFID );
+        if( pImage )
+        {
+            // TODO: Add support clipping region in neatline
+            CPLString osImgFilename = pImage->getFilePath();
+            CPLString osImgPath = CPLGetPath( osImgFilename );
+            if( osImgPath.empty () )
+            {
+                osImgFilename = CPLFormFilename( CPLGetPath( osCADFilename ),
+                                                 osImgFilename, NULL );
+            }
+
+            if ( !CPLCheckForFile( const_cast<char *>( osImgFilename.c_str () ), NULL) )
+                return poOpenInfo->nOpenFlags & GDAL_OF_VECTOR;
+
+            poRasterDS = reinterpret_cast<GDALDataset *>(
+                                GDALOpen( osImgFilename, poOpenInfo->eAccess ) );
+            if( poRasterDS == NULL )
+            {
+                delete pImage;
+                return poOpenInfo->nOpenFlags & GDAL_OF_VECTOR;
+            }
+            if( poRasterDS->GetRasterCount() == 0 )
+            {
+                delete pImage;
+                GDALClose( poRasterDS );
+                return poOpenInfo->nOpenFlags & GDAL_OF_VECTOR;
+            }
+
+            if( poRasterDS->GetGeoTransform( adfGeoTransform ) != CE_None )
+            {
+                // The external world file have priority
+                double dfUnits = 1.0;
+                if( NULL != poSpatialRef )
+                    dfUnits = poSpatialRef->GetLinearUnits();
+                FillTransform( pImage, dfUnits );
+            }
+            delete pImage;
+
+            nRasterXSize = poRasterDS->GetRasterXSize();
+            nRasterYSize = poRasterDS->GetRasterYSize();
+            if( !GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) )
+            {
+                GDALClose( poRasterDS );
+                return poOpenInfo->nOpenFlags & GDAL_OF_VECTOR;
+            }
+
+            for( int iBand = 1; iBand <= poRasterDS->GetRasterCount(); iBand++ )
+                SetBand( iBand,
+                    new CADWrapperRasterBand( poRasterDS->GetRasterBand(
+                        iBand )) );
+
+            char** papszDomainList = poRasterDS->GetMetadataDomainList();
+            while( papszDomainList )
+            {
+                char** papszMetadata = GetMetadata( *papszDomainList );
+                char** papszRasterMetadata = poRasterDS->GetMetadata( *papszDomainList );
+                if( NULL == papszMetadata )
+                    SetMetadata( papszRasterMetadata, *papszDomainList );
+                else
+                {
+                    char** papszMD = CSLMerge( CSLDuplicate(papszMetadata), papszRasterMetadata );
+                    SetMetadata( papszMD, *papszDomainList );
+                    CSLDestroy( papszMD );
+                }
+                papszDomainList++;
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+OGRLayer *GDALCADDataset::GetLayer( int iLayer )
+{
+    if ( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+int GDALCADDataset::TestCapability( const char * pszCap )
+{
+    if ( EQUAL( pszCap,ODsCCreateLayer ) || EQUAL( pszCap,ODsCDeleteLayer ) )
+         return FALSE;
+    else if( EQUAL(pszCap,ODsCCurveGeometries) )
+        return TRUE;
+    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
+        return TRUE;
+    return FALSE;
+}
+
+char** GDALCADDataset::GetFileList()
+{
+    char **papszFileList = GDALDataset::GetFileList();
+
+    /* duplicated papszFileList = CSLAddString( papszFileList, osCADFilename );*/
+    const char * pszPRJFilename = GetPrjFilePath();
+    if( NULL != pszPRJFilename )
+        papszFileList = CSLAddString( papszFileList, pszPRJFilename );
+
+    for( size_t i = 0; i < poCADFile->GetLayersCount(); ++i )
+    {
+        CADLayer &oLayer = poCADFile->GetLayer( i );
+        for( size_t j = 0; j < oLayer.getImageCount(); ++j )
+        {
+            CADImage* pImage = oLayer.getImage( j );
+            if( pImage )
+            {
+                CPLString osImgFilename = pImage->getFilePath();
+                if ( CPLCheckForFile (const_cast<char *>( osImgFilename.c_str()),
+                        NULL) == TRUE)
+                    papszFileList = CSLAddString( papszFileList, osImgFilename );
+            }
+        }
+    }
+
+    if( NULL != poRasterDS )
+    {
+        papszFileList = CSLMerge( papszFileList, poRasterDS->GetFileList() );
+    }
+    return papszFileList;
+}
+
+int GDALCADDataset::GetCadEncoding() const
+{
+    if( poCADFile == NULL )
+        return 0;
+    const CADHeader & header = poCADFile->getHeader();
+    return static_cast<int>( header.getValue(
+                                        CADHeader::DWGCODEPAGE, 0 ).getDecimal() );
+}
+
+OGRSpatialReference *GDALCADDataset::GetSpatialReference()
+{
+    if( poSpatialReference )
+        return poSpatialReference;
+
+    if( poCADFile != NULL )
+    {
+        CPLString sESRISpatRef;
+        poSpatialReference = new OGRSpatialReference();
+        CADDictionary oNOD = poCADFile->GetNOD();
+        CPLString sESRISpatRefData = oNOD.getRecordByName("ESRI_PRJ");
+        if( !sESRISpatRefData.empty() )
+        {
+            sESRISpatRef = sESRISpatRefData.substr( sESRISpatRefData.find("GEO") );
+        }
+
+        if( !sESRISpatRef.empty() )
+        {
+            char** papszPRJData = NULL;
+            papszPRJData = CSLAddString( papszPRJData, sESRISpatRef );
+            if( poSpatialReference->importFromESRI( papszPRJData ) != OGRERR_NONE )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                        "Failed to parse PRJ section, ignoring." );
+                delete poSpatialReference;
+                poSpatialReference = NULL;
+            }
+
+            CSLDestroy( papszPRJData );
+        }
+        else
+        {
+            const char * pszPRJFilename = GetPrjFilePath();
+            if( pszPRJFilename && pszPRJFilename[0] ) // check if path exists
+            {
+                CPLPushErrorHandler( CPLQuietErrorHandler );
+                char **papszPRJData = CSLLoad( pszPRJFilename );
+                CPLPopErrorHandler();
+
+                if( poSpatialReference->importFromESRI( papszPRJData ) != OGRERR_NONE )
+                {
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                        "Failed to parse PRJ file, ignoring." );
+                    delete poSpatialReference;
+                    poSpatialReference = NULL;
+                }
+
+                if( papszPRJData )
+                    CSLDestroy( papszPRJData );
+            }
+        }
+    }
+
+    if( poSpatialReference )
+    {
+        char *pszProjection = NULL;
+        poSpatialReference->exportToWkt( &pszProjection );
+        soWKT = pszProjection;
+        CPLFree( pszProjection );
+    }
+    return poSpatialReference;
+}
+
+const char* GDALCADDataset::GetPrjFilePath()
+{
+    const char * pszPRJFilename = CPLResetExtension( osCADFilename, "prj" );
+    if ( CPLCheckForFile( (char*)pszPRJFilename, NULL ) == TRUE )
+        return pszPRJFilename;
+
+    pszPRJFilename = CPLResetExtension( osCADFilename, "PRJ" );
+    if ( CPLCheckForFile( (char*)pszPRJFilename, NULL ) == TRUE )
+        return pszPRJFilename;
+
+    return "";
+}
+
+const char *GDALCADDataset::GetProjectionRef(void)
+{
+    return soWKT;
+}
+
+CPLErr GDALCADDataset::GetGeoTransform( double* padfGeoTransform )
+{
+    memcpy( padfGeoTransform, adfGeoTransform, sizeof(double) * 6 );
+    return CE_None;
+}
+
+int GDALCADDataset::GetGCPCount()
+{
+    if(NULL == poRasterDS)
+        return 0;
+    return poRasterDS->GetGCPCount();
+}
+
+const char *GDALCADDataset::GetGCPProjection()
+{
+    if( NULL == poRasterDS )
+        return "";
+    return poRasterDS->GetGCPProjection();
+}
+
+const GDAL_GCP *GDALCADDataset::GetGCPs()
+{
+    if( NULL == poRasterDS )
+        return NULL;
+    return poRasterDS->GetGCPs();
+}
+
+int GDALCADDataset::CloseDependentDatasets()
+{
+    int bRet = GDALDataset::CloseDependentDatasets();
+    if ( poRasterDS != NULL )
+    {
+        GDALClose( poRasterDS );
+        poRasterDS = NULL;
+        bRet = TRUE;
+    }
+    return bRet;
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/GNUmakefile b/ogr/ogrsf_frmts/cad/libopencad/GNUmakefile
new file mode 100644
index 0000000..6005745
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/GNUmakefile
@@ -0,0 +1,31 @@
+
+include ../../../../GDALmake.opt
+
+SUBDIRS-yes :=	dwg
+
+OBJ := \
+	cadfile.o \
+	cadcolors.o \
+	cadlayer.o \
+	cadclasses.o \
+	cadfileio.o \
+	cadobjects.o \
+	cadtables.o \
+	cadfilestreamio.o \
+	cadgeometry.o \
+	cadheader.o \
+	opencad.o \
+	caddictionary.o
+
+O_OBJ := $(foreach file,$(OBJ),../../o/$(file))
+
+CPPFLAGS	:=	-I. -I.. -I../.. $(CPPFLAGS)
+
+default:	$(foreach d,$(SUBDIRS-yes),$(d)-target) $(O_OBJ:.o=.$(OBJ_EXT))
+
+../../o/%.$(OBJ_EXT):	%.cpp
+	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+clean: $(foreach d,$(SUBDIRS-yes),$(d)-clean)
+	rm -f *.o $(O_OBJ)
+	rm -f *~
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadclasses.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadclasses.cpp
new file mode 100644
index 0000000..2c5c038
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadclasses.cpp
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "cadclasses.h"
+#include "opencad.h"
+
+#include <iostream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+// CADClass
+//------------------------------------------------------------------------------
+
+CADClass::CADClass() : sCppClassName(""),
+                sApplicationName(""),
+                sDXFRecordName(""),
+                dProxyCapFlag(0),
+                dInstanceCount(0),
+                bWasZombie(false),
+                bIsEntity(false),
+                dClassNum(0),
+                dClassVersion(0)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADClasses
+//------------------------------------------------------------------------------
+
+CADClasses::CADClasses()
+{
+}
+
+void CADClasses::addClass( CADClass stClass )
+{
+    classes.push_back( stClass );
+
+    DebugMsg( "CLASS INFO\n"
+                      "  Class Number: %d\n"
+                      "  Proxy capabilities flag or Version: %d\n"
+                      "  App name: %s\n"
+                      "  C++ Class Name: %s\n"
+                      "  DXF Class name: %s\n"
+                      "  Was a zombie? %x\n"
+                      "  Is-an-entity flag: %x\n\n", stClass.dClassNum, stClass.dProxyCapFlag,
+              stClass.sApplicationName.c_str(), stClass.sCppClassName.c_str(), stClass.sDXFRecordName.c_str(),
+              stClass.bWasZombie, stClass.bIsEntity );
+}
+
+CADClass CADClasses::getClassByNum( short num ) const
+{
+    for( const CADClass &cadClass : classes )
+    {
+        if( cadClass.dClassNum == num )
+            return cadClass;
+    }
+    return CADClass();
+}
+
+void CADClasses::print() const
+{
+    cout << "============ CLASSES Section ============\n";
+
+    for( CADClass stClass : classes )
+    {
+        cout << "Class:" <<
+        "\n  Class Number: " << stClass.dClassNum <<
+        "\n  Proxy capabilities flag or Version: " << stClass.dProxyCapFlag <<
+        "\n  App name: " << stClass.sApplicationName <<
+        "\n  C++ Class Name: " << stClass.sCppClassName <<
+        "\n  DXF Class name: " << stClass.sDXFRecordName <<
+        "\n  Was a zombie: " << stClass.bWasZombie <<
+        "\n  Is-an-entity flag: " << stClass.bIsEntity << "\n\n";
+    }
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadclasses.h b/ogr/ogrsf_frmts/cad/libopencad/cadclasses.h
new file mode 100644
index 0000000..680ee87
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadclasses.h
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef CADCLASSES_H
+#define CADCLASSES_H
+
+#include "opencad.h"
+
+// std headers
+#include <string>
+#include <vector>
+
+class OCAD_EXTERN  CADClass
+{
+public:
+    CADClass();
+
+public:
+    std::string          sCppClassName;       /**< TV, C++ class name */
+    std::string          sApplicationName;    /**< TV, Application name */
+    std::string          sDXFRecordName;      /**< TV, Class DXF record name */
+    int             dProxyCapFlag;       /**< BITSHORT, Proxy capabilities flag, 90 */
+    unsigned short  dInstanceCount;      /**< BITSHORT, Instance count for a custom class, 91 */
+    bool            bWasZombie;          /**< BIT, Was-a-proxy flag, 280*/
+    bool            bIsEntity;           /**< BITSHORT, Is-an-entity flag, 281 */
+    short           dClassNum;           /**< BITSHORT, Class number */
+    short           dClassVersion;       /**< BITSHORT, Class version */
+};
+
+class OCAD_EXTERN CADClasses
+{
+public:
+    CADClasses();
+
+public:
+    void                addClass(CADClass stClass);
+    CADClass            getClassByNum(short num) const;
+    void                print() const;
+
+protected:
+    std::vector<CADClass>    classes;
+};
+
+#endif // CADCLASSES_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadcolors.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadcolors.cpp
new file mode 100644
index 0000000..c5185d1
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadcolors.cpp
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+ #include "cadcolors.h"
+
+const RGBColor CADACIColors[]
+{
+    { 0,   0,   0 },
+    { 255, 0,   0 },
+    { 255, 255, 0 },
+    { 0,   255, 0 },
+    { 0,   255, 255 },
+    { 0,   0,   255 },
+    { 255, 0,   255 },
+    { 255, 255, 255 },
+    { 65,  65,  65 },
+    { 128, 128, 128 },
+    { 255, 0,   0 },
+    { 255, 170, 170 },
+    { 189, 0,   0 },
+    { 189, 126, 126 },
+    { 129, 0,   0 },
+    { 129, 86,  86 },
+    { 104, 0,   0 },
+    { 104, 69,  69 },
+    { 79,  0,   0 },
+    { 79,  53,  53 },
+    { 255, 63,  0 },
+    { 255, 191, 170 },
+    { 189, 46,  0 },
+    { 189, 141, 126 },
+    { 129, 31,  0 },
+    { 129, 96,  86 },
+    { 104, 25,  0 },
+    { 104, 78,  69 },
+    { 79,  19,  0 },
+    { 79,  59,  53 },
+    { 255, 127, 0 },
+    { 255, 212, 170 },
+    { 189, 94,  0 },
+    { 189, 157, 126 },
+    { 129, 64,  0 },
+    { 129, 107, 86 },
+    { 104, 52,  0 },
+    { 104, 86,  69 },
+    { 79,  39,  0 },
+    { 79,  66,  53 },
+    { 255, 191, 0 },
+    { 255, 234, 170 },
+    { 189, 141, 0 },
+    { 189, 173, 126 },
+    { 129, 96,  0 },
+    { 129, 118, 86 },
+    { 104, 78,  0 },
+    { 104, 95,  69 },
+    { 79,  59,  0 },
+    { 79,  73,  53 },
+    { 255, 255, 0 },
+    { 255, 255, 170 },
+    { 189, 189, 0 },
+    { 189, 189, 126 },
+    { 129, 129, 0 },
+    { 129, 129, 86 },
+    { 104, 104, 0 },
+    { 104, 104, 69 },
+    { 79,  79,  0 },
+    { 79,  79,  53 },
+    { 191, 255, 0 },
+    { 234, 255, 170 },
+    { 141, 189, 0 },
+    { 173, 189, 126 },
+    { 96,  129, 0 },
+    { 118, 129, 86 },
+    { 78,  104, 0 },
+    { 95,  104, 69 },
+    { 59,  79,  0 },
+    { 73,  79,  53 },
+    { 127, 255, 0 },
+    { 212, 255, 170 },
+    { 94,  189, 0 },
+    { 157, 189, 126 },
+    { 64,  129, 0 },
+    { 107, 129, 86 },
+    { 52,  104, 0 },
+    { 86,  104, 69 },
+    { 39,  79,  0 },
+    { 66,  79,  53 },
+    { 63,  255, 0 },
+    { 191, 255, 170 },
+    { 46,  189, 0 },
+    { 141, 189, 126 },
+    { 31,  129, 0 },
+    { 96,  129, 86 },
+    { 25,  104, 0 },
+    { 78,  104, 69 },
+    { 19,  79,  0 },
+    { 59,  79,  53 },
+    { 0,   255, 0 },
+    { 170, 255, 170 },
+    { 0,   189, 0 },
+    { 126, 189, 126 },
+    { 0,   129, 0 },
+    { 86,  129, 86 },
+    { 0,   104, 0 },
+    { 69,  104, 69 },
+    { 0,   79,  0 },
+    { 53,  79,  53 },
+    { 0,   255, 63 },
+    { 170, 255, 191 },
+    { 0,   189, 46 },
+    { 126, 189, 141 },
+    { 0,   129, 31 },
+    { 86,  129, 96 },
+    { 0,   104, 25 },
+    { 69,  104, 78 },
+    { 0,   79,  19 },
+    { 53,  79,  59 },
+    { 0,   255, 127 },
+    { 170, 255, 212 },
+    { 0,   189, 94 },
+    { 126, 189, 157 },
+    { 0,   129, 64 },
+    { 86,  129, 107 },
+    { 0,   104, 52 },
+    { 69,  104, 86 },
+    { 0,   79,  39 },
+    { 53,  79,  66 },
+    { 0,   255, 191 },
+    { 170, 255, 234 },
+    { 0,   189, 141 },
+    { 126, 189, 173 },
+    { 0,   129, 96 },
+    { 86,  129, 118 },
+    { 0,   104, 78 },
+    { 69,  104, 95 },
+    { 0,   79,  59 },
+    { 53,  79,  73 },
+    { 0,   255, 255 },
+    { 170, 255, 255 },
+    { 0,   189, 189 },
+    { 126, 189, 189 },
+    { 0,   129, 129 },
+    { 86,  129, 129 },
+    { 0,   104, 104 },
+    { 69,  104, 104 },
+    { 0,   79,  79 },
+    { 53,  79,  79 },
+    { 0,   191, 255 },
+    { 170, 234, 255 },
+    { 0,   141, 189 },
+    { 126, 173, 189 },
+    { 0,   96,  129 },
+    { 86,  118, 129 },
+    { 0,   78,  104 },
+    { 69,  95,  104 },
+    { 0,   59,  79 },
+    { 53,  73,  79 },
+    { 0,   127, 255 },
+    { 170, 212, 255 },
+    { 0,   94,  189 },
+    { 126, 157, 189 },
+    { 0,   64,  129 },
+    { 86,  107, 129 },
+    { 0,   52,  104 },
+    { 69,  86,  104 },
+    { 0,   39,  79 },
+    { 53,  66,  79 },
+    { 0,   63,  255 },
+    { 170, 191, 255 },
+    { 0,   46,  189 },
+    { 126, 141, 189 },
+    { 0,   31,  129 },
+    { 86,  96,  129 },
+    { 0,   25,  104 },
+    { 69,  78,  104 },
+    { 0,   19,  79 },
+    { 53,  59,  79 },
+    { 0,   0,   255 },
+    { 170, 170, 255 },
+    { 0,   0,   189 },
+    { 126, 126, 189 },
+    { 0,   0,   129 },
+    { 86,  86,  129 },
+    { 0,   0,   104 },
+    { 69,  69,  104 },
+    { 0,   0,   79 },
+    { 53,  53,  79 },
+    { 63,  0,   255 },
+    { 191, 170, 255 },
+    { 46,  0,   189 },
+    { 141, 126, 189 },
+    { 31,  0,   129 },
+    { 96,  86,  129 },
+    { 25,  0,   104 },
+    { 78,  69,  104 },
+    { 19,  0,   79 },
+    { 59,  53,  79 },
+    { 127, 0,   255 },
+    { 212, 170, 255 },
+    { 94,  0,   189 },
+    { 157, 126, 189 },
+    { 64,  0,   129 },
+    { 107, 86,  129 },
+    { 52,  0,   104 },
+    { 86,  69,  104 },
+    { 39,  0,   79 },
+    { 66,  53,  79 },
+    { 191, 0,   255 },
+    { 234, 170, 255 },
+    { 141, 0,   189 },
+    { 173, 126, 189 },
+    { 96,  0,   129 },
+    { 118, 86,  129 },
+    { 78,  0,   104 },
+    { 95,  69,  104 },
+    { 59,  0,   79 },
+    { 73,  53,  79 },
+    { 255, 0,   255 },
+    { 255, 170, 255 },
+    { 189, 0,   189 },
+    { 189, 126, 189 },
+    { 129, 0,   129 },
+    { 129, 86,  129 },
+    { 104, 0,   104 },
+    { 104, 69,  104 },
+    { 79,  0,   79 },
+    { 79,  53,  79 },
+    { 255, 0,   191 },
+    { 255, 170, 234 },
+    { 189, 0,   141 },
+    { 189, 126, 173 },
+    { 129, 0,   96 },
+    { 129, 86,  118 },
+    { 104, 0,   78 },
+    { 104, 69,  95 },
+    { 79,  0,   59 },
+    { 79,  53,  73 },
+    { 255, 0,   127 },
+    { 255, 170, 212 },
+    { 189, 0,   94 },
+    { 189, 126, 157 },
+    { 129, 0,   64 },
+    { 129, 86,  107 },
+    { 104, 0,   52 },
+    { 104, 69,  86 },
+    { 79,  0,   39 },
+    { 79,  53,  66 },
+    { 255, 0,   63 },
+    { 255, 170, 191 },
+    { 189, 0,   46 },
+    { 189, 126, 141 },
+    { 129, 0,   31 },
+    { 129, 86,  96 },
+    { 104, 0,   25 },
+    { 104, 69,  78 },
+    { 79,  0,   19 },
+    { 79,  53,  59 },
+    { 51,  51,  51 },
+    { 80,  80,  80 },
+    { 105, 105, 105 },
+    { 130, 130, 130 },
+    { 190, 190, 190 },
+    { 255, 255, 255 }
+};
+
+const RGBColor getCADACIColor(short index)
+{
+    if(index < 0 || index > 255)
+        return {255, 255, 255};
+    return CADACIColors[index];
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadcolors.h b/ogr/ogrsf_frmts/cad/libopencad/cadcolors.h
new file mode 100644
index 0000000..4182aaf
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadcolors.h
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef CADCOLORS_H
+#define CADCOLORS_H
+
+typedef struct
+{
+    unsigned char R;
+    unsigned char G;
+    unsigned char B;
+} RGBColor;
+
+/**
+ * @brief Lookup table to translate ACI to RGB color.
+ */
+ const RGBColor getCADACIColor(short index);
+
+#endif // CADCOLORS_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/caddictionary.cpp b/ogr/ogrsf_frmts/cad/libopencad/caddictionary.cpp
new file mode 100644
index 0000000..3882398
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/caddictionary.cpp
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+
+#include "caddictionary.h"
+
+using namespace std;
+//
+// CADDictionaryRecord
+//
+
+CADDictionaryRecord::CADDictionaryRecord() :
+    objType(CADObject::UNUSED)
+{
+}
+
+CADObject::ObjectType CADDictionaryRecord::getType() const
+{
+    return objType;
+}
+
+//
+// CADXRecord
+//
+
+CADXRecord::CADXRecord()
+{
+    objType = CADObject::XRECORD;
+}
+
+const string CADXRecord::getRecordData() const
+{
+    return sRecordData;
+}
+
+void CADXRecord::setRecordData( const string& data )
+{
+    sRecordData = data;
+}
+
+//
+// CADDictionary
+//
+
+CADDictionary::CADDictionary()
+{
+    objType = CADObject::DICTIONARY;
+}
+
+CADDictionary::~CADDictionary()
+{
+}
+
+size_t CADDictionary::getRecordsCount()
+{
+    return astXRecords.size();
+}
+
+CADDictionaryItem CADDictionary::getRecord( size_t index )
+{
+    return astXRecords[index];
+}
+
+void CADDictionary::addRecord( CADDictionaryItem record )
+{
+    astXRecords.emplace_back( record );
+}
+
+string CADDictionary::getRecordByName(const string& name) const
+{
+    for( size_t i = 0; i < astXRecords.size(); ++i )
+    {
+        if( astXRecords[i].first.compare(name) == 0 )
+        {
+            std::shared_ptr<CADDictionaryRecord> XRecordPtr = astXRecords[i].second;
+            if(XRecordPtr == nullptr ||
+               XRecordPtr->getType() != CADObject::XRECORD)
+                continue;
+            CADXRecord * poXRecord = static_cast<CADXRecord*>(XRecordPtr.get() );
+            return poXRecord->getRecordData();
+        }
+    }
+    return "";
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/caddictionary.h b/ogr/ogrsf_frmts/cad/libopencad/caddictionary.h
new file mode 100644
index 0000000..924b54a
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/caddictionary.h
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef CADDICTIONARY_H
+#define CADDICTIONARY_H
+
+#include "cadobjects.h"
+#include <memory>
+
+/*
+ * @brief Base-class for XRecord and Dictionary.
+ */
+class CADDictionaryRecord
+{
+public:
+    CADDictionaryRecord();
+    virtual ~CADDictionaryRecord(){}
+
+    CADObject::ObjectType getType() const;
+
+protected:
+    CADObject::ObjectType objType;
+};
+
+/*
+ * @brief Class which implements XRecord
+ */
+class OCAD_EXTERN CADXRecord : public CADDictionaryRecord
+{
+public:
+    CADXRecord();
+    virtual ~CADXRecord(){}
+
+    const std::string getRecordData() const;
+    void              setRecordData( const std::string& data );
+
+private:
+    std::string sRecordData;
+};
+
+/*
+ * @brief Class which implements Dictionary
+ */
+typedef std::pair< std::string, std::shared_ptr<CADDictionaryRecord>> CADDictionaryItem;
+class OCAD_EXTERN CADDictionary : public CADDictionaryRecord
+{
+public:
+    CADDictionary();
+    virtual ~CADDictionary();
+
+    size_t getRecordsCount();
+    void   addRecord( CADDictionaryItem );
+    CADDictionaryItem getRecord( size_t index );
+    std::string getRecordByName(const std::string& name) const;
+private:
+    std::vector< CADDictionaryItem > astXRecords;
+};
+
+#endif // CADDICTIONARY_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadfile.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadfile.cpp
new file mode 100644
index 0000000..39520b7
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadfile.cpp
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "cadfile.h"
+#include "opencad_api.h"
+
+#include <iostream>
+
+CADFile::CADFile( CADFileIO * poFileIO ) :
+    pFileIO( poFileIO ),
+    bReadingUnsupportedGeometries( false )
+{
+}
+
+CADFile::~CADFile()
+{
+    if( nullptr != pFileIO )
+    {
+        pFileIO->Close();
+        delete pFileIO;
+    }
+}
+
+const CADHeader& CADFile::getHeader() const
+{
+    return oHeader;
+}
+
+const CADClasses& CADFile::getClasses() const
+{
+    return oClasses;
+}
+
+const CADTables& CADFile::getTables() const
+{
+    return oTables;
+}
+
+int CADFile::ParseFile( enum OpenOptions eOptions, bool bReadUnsupportedGeometries )
+{
+    if( nullptr == pFileIO )
+        return CADErrorCodes::FILE_OPEN_FAILED;
+
+    if( !pFileIO->IsOpened() )
+    {
+        if( !pFileIO->Open( CADFileIO::read | CADFileIO::binary ) )
+            return CADErrorCodes::FILE_OPEN_FAILED;
+    }
+
+    // Set flag which will tell CADLayer to skip/not skip unsupported geoms
+    bReadingUnsupportedGeometries = bReadUnsupportedGeometries;
+
+    int nResultCode;
+    nResultCode = ReadSectionLocators();
+    if( nResultCode != CADErrorCodes::SUCCESS )
+        return nResultCode;
+    nResultCode = ReadHeader( eOptions );
+    if( nResultCode != CADErrorCodes::SUCCESS )
+        return nResultCode;
+    nResultCode = ReadClasses( eOptions );
+    if( nResultCode != CADErrorCodes::SUCCESS )
+        return nResultCode;
+    nResultCode = CreateFileMap();
+    if( nResultCode != CADErrorCodes::SUCCESS )
+        return nResultCode;
+    nResultCode = ReadTables( eOptions );
+    if( nResultCode != CADErrorCodes::SUCCESS )
+        return nResultCode;
+
+    return CADErrorCodes::SUCCESS;
+}
+
+int CADFile::ReadTables( CADFile::OpenOptions /*eOptions*/ )
+{
+    // TODO: read other tables in ALL option mode
+
+    int nResult = oTables.ReadTable( this, CADTables::LayersTable );
+    return nResult;
+}
+
+size_t CADFile::GetLayersCount() const
+{
+    return oTables.GetLayerCount();
+}
+
+CADLayer& CADFile::GetLayer( size_t index )
+{
+    return oTables.GetLayer( index );
+}
+
+bool CADFile::isReadingUnsupportedGeometries()
+{
+    return bReadingUnsupportedGeometries;
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadfile.h b/ogr/ogrsf_frmts/cad/libopencad/cadfile.h
new file mode 100644
index 0000000..9ab62bb
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadfile.h
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef CADFILE_H
+#define CADFILE_H
+
+#include "caddictionary.h"
+#include "cadclasses.h"
+#include "cadfileio.h"
+#include "cadtables.h"
+
+/**
+ * @brief The abstract CAD file class
+ */
+class OCAD_EXTERN CADFile
+{
+    friend class CADTables;
+    friend class CADLayer;
+
+public:
+    /**
+     * @brief The CAD file open options enum
+     */
+    enum OpenOptions
+    {
+        READ_ALL, /**< read all available information */
+        READ_FAST, /**< read some methadata */
+        READ_FASTEST    /**< read only geometry and layers */
+    };
+
+public:
+    explicit                 CADFile( CADFileIO * poFileIO );
+    virtual                 ~CADFile();
+
+public:
+    const CADHeader & getHeader() const;
+    const CADClasses& getClasses() const;
+    const CADTables & getTables() const;
+
+public:
+    virtual int    ParseFile( enum OpenOptions eOptions, bool bReadUnsupportedGeometries = true );
+    virtual size_t GetLayersCount() const;
+    virtual CADLayer& GetLayer( size_t index );
+
+    /**
+     * @brief returns NamedObjectDictionary (root) of all others dictionaries
+     * @return root CADDictionary
+     */
+    virtual CADDictionary GetNOD() = 0;
+
+//    virtual size_t GetBlocksCount();
+//    virtual CADBlockObject * GetBlock( size_t index );
+
+protected:
+    /**
+     * @brief Get CAD Object from file
+     * @param dObjectHandle Object handle
+     * @param bHandlesOnly set TRUE if object data should be skipped, and only object handles should be read.
+     * @return pointer to CADObject or nullptr. User have to free returned pointer.
+     */
+    virtual CADObject * GetObject( long dObjectHandle, bool bHandlesOnly = false ) = 0;
+
+    /**
+     * @brief read geometry from CAD file
+     * @param iLayerIndex layer index (counts from 0)
+     * @param dHandle Handle of CAD object
+     * @param dBlockRefHandle Handle of BlockRef (0 if geometry is not in block reference)
+     * @return NULL if failed or pointer which mast be feed by user
+     */
+    virtual CADGeometry * GetGeometry( size_t iLayerIndex, long dHandle, long dBlockRefHandle = 0 ) = 0;
+
+    /**
+     * @brief initially read some basic values and section locator
+     * @return CADErrorCodes::SUCCESS if OK, or error code
+     */
+    virtual int ReadSectionLocators() = 0;
+
+    /**
+     * @brief Read header from CAD file
+     * @param eOptions Read options
+     * @return CADErrorCodes::SUCCESS if OK, or error code
+     */
+    virtual int ReadHeader( enum OpenOptions eOptions ) = 0;
+
+    /**
+     * @brief Read classes from CAD file
+     * @param eOptions Read options
+     * @return CADErrorCodes::SUCCESS if OK, or error code
+     */
+    virtual int ReadClasses( enum OpenOptions eOptions ) = 0;
+
+    /**
+     * @brief Create the file map for fast access to CAD objects
+     * @return CADErrorCodes::SUCCESS if OK, or error code
+     */
+    virtual int CreateFileMap() = 0;
+
+    /**
+     * @brief Read tables from CAD file
+     * @param eOptions Read options
+     * @return CADErrorCodes::SUCCESS if OK, or error code
+     */
+    virtual int ReadTables( enum OpenOptions eOptions );
+
+    /**
+     * @brief returns value of flag Read Unsupported Geometries
+     */
+    bool isReadingUnsupportedGeometries();
+
+protected:
+    CADFileIO * pFileIO;
+    CADHeader  oHeader;
+    CADClasses oClasses;
+    CADTables  oTables;
+
+protected:
+    std::map<long, long> mapObjects; // object index <-> file offset
+    bool bReadingUnsupportedGeometries;
+};
+
+#endif // CADFILE_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadfileio.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadfileio.cpp
new file mode 100644
index 0000000..d92e299
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadfileio.cpp
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ ******************************************************************************/
+#include "cadfileio.h"
+
+CADFileIO::CADFileIO( const char * pszFileName ) :
+    m_soFilePath( pszFileName),
+    m_bIsOpened (false)
+{
+}
+
+CADFileIO::~CADFileIO()
+{
+    if( IsOpened() )
+        Close();
+}
+
+bool CADFileIO::IsOpened() const
+{
+    return m_bIsOpened;
+}
+
+bool CADFileIO::Close()
+{
+    m_bIsOpened = false;
+    return true;
+}
+
+const char * CADFileIO::GetFilePath() const
+{
+    return m_soFilePath.c_str();
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadfileio.h b/ogr/ogrsf_frmts/cad/libopencad/cadfileio.h
new file mode 100644
index 0000000..250f410
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadfileio.h
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ ******************************************************************************/
+#ifndef CADFILEIO_H
+#define CADFILEIO_H
+
+#include <cstddef>
+#include <string>
+
+/**
+ * @brief The CADFileIO class provides in/out file operations as read, write,
+ * seek, etc. This is abstract class.
+ */
+class CADFileIO
+{
+public:
+    enum class SeekOrigin
+    {
+        BEG, /**< Begin of the file */
+        CUR, /**< Current position of the pointer */
+        END  /**< End of file */
+    };
+
+    enum OpenMode
+    {
+        binary      = 1L << 2,
+        read        = 1L << 3,
+        write       = 1L << 4
+    };
+
+public:
+    explicit CADFileIO( const char * pszFileName );
+    virtual                 ~CADFileIO();
+
+    virtual const char * ReadLine() = 0;
+    virtual bool     Eof() const                                = 0;
+    virtual bool     Open( int mode )                           = 0;
+    virtual bool     IsOpened() const;
+    virtual bool     Close();
+    virtual int      Seek( long int offset, SeekOrigin origin ) = 0;
+    virtual long int Tell()                                     = 0;
+    virtual size_t   Read( void * ptr, size_t size )            = 0;
+    virtual size_t   Write( void * ptr, size_t size )           = 0;
+    virtual void     Rewind()                                   = 0;
+    const char * GetFilePath() const;
+
+protected:
+    std::string m_soFilePath;
+    bool        m_bIsOpened;
+};
+
+#endif // CADFILEIO_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadfilestreamio.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadfilestreamio.cpp
new file mode 100644
index 0000000..833e99a
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadfilestreamio.cpp
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+*******************************************************************************/
+#include "cadfilestreamio.h"
+
+CADFileStreamIO::CADFileStreamIO( const char * pszFilePath ) : CADFileIO( pszFilePath )
+{
+}
+
+CADFileStreamIO::~CADFileStreamIO()
+{
+}
+
+const char * CADFileStreamIO::ReadLine()
+{
+    // TODO: getline
+    return nullptr;
+}
+
+bool CADFileStreamIO::Eof() const
+{
+    return m_oFileStream.eof();
+}
+
+bool CADFileStreamIO::Open( int mode )
+{
+    auto io_mode = std::ifstream::in; // As we use ifstream
+    if( mode & OpenMode::binary )
+        io_mode = std::ifstream::binary; // In set by default
+
+    if( mode & OpenMode::write )
+        //io_mode |= std::ifstream::out;
+        return false;
+
+    m_oFileStream.open( m_soFilePath, io_mode );
+
+    if( m_oFileStream.is_open() )
+        m_bIsOpened = true;
+
+    return m_bIsOpened;
+}
+
+bool CADFileStreamIO::Close()
+{
+    m_oFileStream.close();
+    return CADFileIO::Close();
+}
+
+int CADFileStreamIO::Seek( long offset, CADFileIO::SeekOrigin origin )
+{
+    std::ios_base::seekdir direction;
+    switch( origin )
+    {
+        case SeekOrigin::CUR:
+            direction = std::ios_base::cur;
+            break;
+        case SeekOrigin::END:
+            direction = std::ios_base::end;
+            break;
+        default:
+        case SeekOrigin::BEG:
+            direction = std::ios_base::beg;
+            break;
+    }
+
+    return m_oFileStream.seekg( offset, direction ).good() ? 0 : 1;
+}
+
+long int CADFileStreamIO::Tell()
+{
+    return m_oFileStream.tellg();
+}
+
+size_t CADFileStreamIO::Read( void * ptr, size_t size )
+{
+    return static_cast<size_t>(m_oFileStream.read( static_cast<char *>(ptr), static_cast<long>(size) ).gcount());
+}
+
+size_t CADFileStreamIO::Write( void * /*ptr*/, size_t /*size*/ )
+{
+    // unsupported
+    return 0;
+}
+
+void CADFileStreamIO::Rewind()
+{
+    m_oFileStream.seekg( 0, std::ios_base::beg );
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadfilestreamio.h b/ogr/ogrsf_frmts/cad/libopencad/cadfilestreamio.h
new file mode 100644
index 0000000..7acfb7c
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadfilestreamio.h
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ ******************************************************************************/
+#ifndef CADFILESTREAMIO_H
+#define CADFILESTREAMIO_H
+
+#include "cadfileio.h"
+
+#include <fstream>
+
+class CADFileStreamIO : public CADFileIO
+{
+public:
+    explicit             CADFileStreamIO(const char* pszFilePath);
+    virtual             ~CADFileStreamIO();
+
+    virtual const char* ReadLine() override;
+    virtual bool        Eof() const override;
+    virtual bool        Open(int mode) override;
+    virtual bool        Close() override;
+    virtual int         Seek(long int offset, SeekOrigin origin) override;
+    virtual long int    Tell() override;
+    virtual size_t      Read(void* ptr, size_t size) override;
+    virtual size_t      Write(void* ptr, size_t size) override;
+    virtual void        Rewind() override;
+protected:
+    std::ifstream       m_oFileStream;
+};
+
+#endif // CADFILESTREAMIO_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadgeometry.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadgeometry.cpp
new file mode 100644
index 0000000..f763ac6
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadgeometry.cpp
@@ -0,0 +1,1263 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "cadgeometry.h"
+
+#include <cmath>
+#include <iostream>
+
+using namespace std;
+
+//------------------------------------------------------------------------------
+// CADGeometry
+//------------------------------------------------------------------------------
+
+Matrix::Matrix()
+{
+    matrix[0] = 1.0;
+    matrix[1] = 0.0;
+    matrix[2] = 0.0;
+    matrix[3] = 0.0;
+    matrix[4] = 1.0;
+    matrix[5] = 0.0;
+    matrix[6] = 0.0;
+    matrix[7] = 0.0;
+    matrix[8] = 1.0;
+}
+
+void Matrix::translate( const CADVector& vector )
+{
+    double a00 = matrix[0];
+    double a01 = matrix[1];
+    double a02 = matrix[2];
+    double a10 = matrix[3];
+    double a11 = matrix[4];
+    double a12 = matrix[5];
+    double a20 = matrix[6];
+    double a21 = matrix[7];
+    double a22 = matrix[8];
+
+    matrix[6] = vector.getX() * a00 + vector.getY() * a10 + a20;
+    matrix[7] = vector.getX() * a01 + vector.getY() * a11 + a21;
+    matrix[8] = vector.getX() * a02 + vector.getY() * a12 + a22;
+}
+
+void Matrix::rotate( double rotation )
+{
+    const double s = sin( rotation );
+    const double c = cos( rotation );
+    double a00 = matrix[0];
+    double a01 = matrix[1];
+    double a02 = matrix[2];
+    double a10 = matrix[3];
+    double a11 = matrix[4];
+    double a12 = matrix[5];
+
+    matrix[0] = c * a00 + s * a10;
+    matrix[1] = c * a01 + s * a11;
+    matrix[2] = c * a02 + s * a12;
+
+    matrix[3] = c * a10 - s * a00;
+    matrix[4] = c * a11 - s * a01;
+    matrix[5] = c * a12 - s * a02;
+}
+
+void Matrix::scale( const CADVector& vector )
+{
+    matrix[0] *= vector.getX();
+    matrix[1] *= vector.getX();
+    matrix[2] *= vector.getX();
+    matrix[3] *= vector.getY();
+    matrix[4] *= vector.getY();
+    matrix[5] *= vector.getY();
+}
+
+CADVector Matrix::multiply( const CADVector& vector ) const
+{
+    CADVector out;
+    out.setX( vector.getX() * matrix[0] + vector.getY() * matrix[1] + vector.getZ() * matrix[2] );
+    out.setY( vector.getX() * matrix[3] + vector.getY() * matrix[4] + vector.getZ() * matrix[5] );
+    out.setZ( vector.getX() * matrix[6] + vector.getY() * matrix[7] + vector.getZ() * matrix[8] );
+    return out;
+}
+
+//------------------------------------------------------------------------------
+// CADGeometry
+//------------------------------------------------------------------------------
+
+CADGeometry::CADGeometry() :
+    geometryType( UNDEFINED ),
+    thickness( 0 )
+{
+    geometry_color.R = 0;
+    geometry_color.G = 0;
+    geometry_color.B = 0;
+}
+
+CADGeometry::~CADGeometry()
+{
+
+}
+
+CADGeometry::GeometryType CADGeometry::getType() const
+{
+    return geometryType;
+}
+
+double CADGeometry::getThickness() const
+{
+    return thickness;
+}
+
+void CADGeometry::setThickness( double thicknes )
+{
+    thickness = thicknes;
+}
+
+RGBColor CADGeometry::getColor() const
+{
+    return geometry_color;
+}
+
+void CADGeometry::setColor( RGBColor color )
+{
+    geometry_color = color;
+}
+
+vector<string> CADGeometry::getEED() const
+{
+    return asEED;
+}
+
+void CADGeometry::setEED( const vector<string>& eed )
+{
+    asEED = eed;
+}
+
+vector<CADAttrib> CADGeometry::getBlockAttributes() const
+{
+    return blockAttributes;
+}
+
+void CADGeometry::setBlockAttributes( const vector<CADAttrib>& data )
+{
+    blockAttributes = data;
+}
+
+//------------------------------------------------------------------------------
+// CADUnknown
+//------------------------------------------------------------------------------
+CADUnknown::CADUnknown()
+{
+}
+
+void CADUnknown::transform( const Matrix& /*matrix*/)
+{
+}
+
+void CADUnknown::print() const
+{
+    cout << "|---------Unhandled---------|\n\n";
+}
+
+//------------------------------------------------------------------------------
+// CADPoint3D
+//------------------------------------------------------------------------------
+
+CADPoint3D::CADPoint3D() :
+    xAxisAng( 0.0 )
+{
+    geometryType = CADGeometry::POINT;
+}
+
+CADPoint3D::CADPoint3D( const CADVector& positionIn, double thicknessIn ) :
+    position( positionIn),
+    xAxisAng( 0.0 )
+{
+    thickness = thicknessIn;
+    geometryType = CADGeometry::POINT;
+}
+
+CADVector CADPoint3D::getPosition() const
+{
+    return position;
+}
+
+void CADPoint3D::setPosition( const CADVector& value )
+{
+    position = value;
+}
+
+CADVector CADPoint3D::getExtrusion() const
+{
+    return extrusion;
+}
+
+void CADPoint3D::setExtrusion( const CADVector& value )
+{
+    extrusion = value;
+}
+
+double CADPoint3D::getXAxisAng() const
+{
+    return xAxisAng;
+}
+
+void CADPoint3D::setXAxisAng( double value )
+{
+    xAxisAng = value;
+}
+
+void CADPoint3D::print() const
+{
+    cout << "|---------Point---------|\n" <<
+        "Position: \t" << position.getX() <<
+                  "\t" << position.getY() <<
+                  "\t" << position.getZ() << "\n\n";
+}
+
+void CADPoint3D::transform( const Matrix& matrix )
+{
+    position = matrix.multiply( position );
+}
+
+//------------------------------------------------------------------------------
+// CADLine
+//------------------------------------------------------------------------------
+
+CADLine::CADLine()
+{
+    geometryType = CADGeometry::LINE;
+}
+
+CADLine::CADLine( const CADPoint3D& startIn, const CADPoint3D& endIn ) :
+    start( startIn ),
+    end( endIn )
+{
+    geometryType = CADGeometry::LINE;
+}
+
+CADPoint3D CADLine::getStart() const
+{
+    return start;
+}
+
+void CADLine::setStart( const CADPoint3D& value )
+{
+    start = value;
+}
+
+CADPoint3D CADLine::getEnd() const
+{
+    return end;
+}
+
+void CADLine::setEnd( const CADPoint3D& value )
+{
+    end = value;
+}
+
+void CADLine::print() const
+{
+    cout << "|---------Line---------|\n" <<
+        "Start Position: \t" << start.getPosition().getX() <<
+                        "\t" << start.getPosition().getY() <<
+                        "\t" << start.getPosition().getZ() << "\n" <<
+        "End Position: \t" << end.getPosition().getX() <<
+                      "\t" << end.getPosition().getY() <<
+                      "\t" << end.getPosition().getZ() << "\n\n";
+}
+
+void CADLine::transform( const Matrix& matrix )
+{
+    start.transform( matrix );
+    end.transform( matrix );
+}
+
+//------------------------------------------------------------------------------
+// CADCircle
+//------------------------------------------------------------------------------
+
+CADCircle::CADCircle() : radius( 0.0f )
+{
+    geometryType = CADGeometry::CIRCLE;
+}
+
+double CADCircle::getRadius() const
+{
+    return radius;
+}
+
+void CADCircle::setRadius( double value )
+{
+    radius = value;
+}
+
+void CADCircle::print() const
+{
+    cout << "|---------Circle---------|\n" <<
+        "Position: \t" << position.getX() <<
+                  "\t" << position.getY() <<
+                  "\t" << position.getZ() << "\n" <<
+        "Radius: " << radius << "\n\n";
+}
+
+//------------------------------------------------------------------------------
+// CADArc
+//------------------------------------------------------------------------------
+
+CADArc::CADArc() : CADCircle(),
+    startingAngle( 0.0f ),
+    endingAngle( 0.0f )
+{
+    geometryType = CADGeometry::ARC;
+}
+
+double CADArc::getStartingAngle() const
+{
+    return startingAngle;
+}
+
+void CADArc::setStartingAngle( double value )
+{
+    startingAngle = value;
+}
+
+double CADArc::getEndingAngle() const
+{
+    return endingAngle;
+}
+
+void CADArc::setEndingAngle( double value )
+{
+    endingAngle = value;
+}
+
+void CADArc::print() const
+{
+    cout << "|---------Arc---------|\n" <<
+        "Position: \t" << position.getX() <<
+                  "\t" << position.getY() <<
+                  "\t" << position.getZ() << "\n" <<
+        "Radius: \t" << radius << "\n" <<
+        "Beg & End angles: \t" << startingAngle <<
+                          "\t" << endingAngle << "\n\n";
+}
+
+//------------------------------------------------------------------------------
+// CADPolyline3D
+//------------------------------------------------------------------------------
+
+CADPolyline3D::CADPolyline3D()
+{
+    geometryType = CADGeometry::POLYLINE3D;
+}
+
+void CADPolyline3D::addVertex( const CADVector& vertex )
+{
+    vertexes.push_back( vertex );
+}
+
+size_t CADPolyline3D::getVertexCount() const
+{
+    return vertexes.size();
+}
+
+CADVector& CADPolyline3D::getVertex( size_t index )
+{
+    return vertexes[index];
+}
+
+void CADPolyline3D::print() const
+{
+    cout << "|------Polyline3D-----|\n";
+    for( size_t i = 0; i < vertexes.size(); ++i )
+    {
+        cout << "  #" << i <<
+            ". X: " << vertexes[i].getX() <<
+            ", Y: " << vertexes[i].getY() << "\n";
+    }
+    cout << "\n";
+}
+
+void CADPolyline3D::transform( const Matrix& matrix )
+{
+    for( CADVector& vertex : vertexes )
+    {
+        vertex = matrix.multiply( vertex );
+    }
+}
+
+//------------------------------------------------------------------------------
+// CADLWPolyline
+//------------------------------------------------------------------------------
+
+CADLWPolyline::CADLWPolyline() :
+    bClosed( false ),
+    constWidth( 0.0 ),
+    elevation( 0.0 )
+{
+    geometryType = CADGeometry::LWPOLYLINE;
+}
+
+void CADLWPolyline::print() const
+{
+    cout << "|------LWPolyline-----|\n";
+    for( size_t i = 0; i < vertexes.size(); ++i )
+    {
+        cout << "  #" << i <<
+            ". X: " << vertexes[i].getX() <<
+            ", Y: " << vertexes[i].getY() << "\n";
+    }
+    cout << "\n";
+}
+
+double CADLWPolyline::getConstWidth() const
+{
+    return constWidth;
+}
+
+void CADLWPolyline::setConstWidth( double value )
+{
+    constWidth = value;
+}
+
+double CADLWPolyline::getElevation() const
+{
+    return elevation;
+}
+
+void CADLWPolyline::setElevation( double value )
+{
+    elevation = value;
+}
+
+CADVector CADLWPolyline::getVectExtrusion() const
+{
+    return vectExtrusion;
+}
+
+void CADLWPolyline::setVectExtrusion( const CADVector& value )
+{
+    vectExtrusion = value;
+}
+
+vector<pair<double, double> > CADLWPolyline::getWidths() const
+{
+    return widths;
+}
+
+void CADLWPolyline::setWidths( const vector<pair<double, double> >& value )
+{
+    widths = value;
+}
+
+vector<double> CADLWPolyline::getBulges() const
+{
+    return bulges;
+}
+
+void CADLWPolyline::setBulges( const vector<double>& value )
+{
+    bulges = value;
+}
+
+bool CADLWPolyline::isClosed() const
+{
+    return bClosed;
+}
+
+void CADLWPolyline::setClosed( bool state )
+{
+    bClosed = state;
+}
+
+//------------------------------------------------------------------------------
+// CADEllipse
+//------------------------------------------------------------------------------
+
+CADEllipse::CADEllipse() : CADArc(),
+    axisRatio( 0.0f )
+{
+    geometryType = CADGeometry::ELLIPSE;
+}
+
+double CADEllipse::getAxisRatio() const
+{
+    return axisRatio;
+}
+
+void CADEllipse::setAxisRatio( double value )
+{
+    axisRatio = value;
+}
+
+CADVector CADEllipse::getSMAxis()
+{
+    return vectSMAxis;
+};
+
+void CADEllipse::setSMAxis( const CADVector& SMAxisVect )
+{
+    vectSMAxis = SMAxisVect;
+}
+
+void CADEllipse::print() const
+{
+    cout << "|---------Ellipse---------|\n" <<
+        "Position: \t" << position.getX() <<
+                  "\t" << position.getY() <<
+                  "\t" << position.getZ() << "\n" <<
+        "Beg & End angles: \t" << startingAngle <<
+                          "\t" << endingAngle << "\n\n";
+}
+
+//------------------------------------------------------------------------------
+// CADText
+//------------------------------------------------------------------------------
+
+CADText::CADText() : CADPoint3D(),
+    obliqueAngle( 0 ),
+    rotationAngle( 0 ),
+    height( 0 )
+{
+    geometryType = CADGeometry::TEXT;
+}
+
+string CADText::getTextValue() const
+{
+    return textValue;
+}
+
+void CADText::setTextValue( const string& value )
+{
+    textValue = value;
+}
+
+double CADText::getHeight() const
+{
+    return height;
+}
+
+void CADText::setHeight( double value )
+{
+    height = value;
+}
+
+double CADText::getRotationAngle() const
+{
+    return rotationAngle;
+}
+
+void CADText::setRotationAngle( double value )
+{
+    rotationAngle = value;
+}
+
+double CADText::getObliqueAngle() const
+{
+    return obliqueAngle;
+}
+
+void CADText::setObliqueAngle( double value )
+{
+    obliqueAngle = value;
+}
+
+void CADText::print() const
+{
+    cout << "|---------Text---------|\n" <<
+        "Position: \t" << position.getX() <<
+                  "\t" << position.getY() << "\n" <<
+        "Text value: \t" << textValue << "\n\n";
+}
+
+//------------------------------------------------------------------------------
+// CADRay
+//------------------------------------------------------------------------------
+
+CADRay::CADRay() : CADPoint3D()
+{
+    geometryType = CADGeometry::RAY;
+}
+
+CADVector CADRay::getVectVector() const
+{
+    return extrusion;
+}
+
+void CADRay::setVectVector( const CADVector& value )
+{
+    extrusion = value;
+}
+
+void CADRay::print() const
+{
+    cout << "|---------Ray---------|\n" <<
+        "Position: \t" << position.getX() <<
+                  "\t" << position.getY() << "\n" <<
+        "Vector: \t" << extrusion.getX() <<
+                "\t" << extrusion.getY() << "\n\n";
+}
+
+//------------------------------------------------------------------------------
+// CADHatch
+//------------------------------------------------------------------------------
+
+CADHatch::CADHatch()
+{
+    geometryType = CADGeometry::HATCH;
+}
+
+//------------------------------------------------------------------------------
+// CADSpline
+//------------------------------------------------------------------------------
+
+CADSpline::CADSpline() :
+    scenario( 0 ),
+    rational( false ),
+    closed( false ),
+    weight( false ),
+    fitTollerance( 0.0 ),
+    degree( 0 )
+{
+    geometryType = CADGeometry::SPLINE;
+}
+
+void CADSpline::print() const
+{
+
+    cout << "|---------Spline---------|\n" <<
+        "Is rational: \t" << rational << "\n" <<
+        "Is closed: \t" << closed << "\n" <<
+        "Control pts count: " << avertCtrlPoints.size() << "\n";
+    for( size_t j = 0; j < avertCtrlPoints.size(); ++j )
+    {
+        cout << "  #" << j << ".\t" << avertCtrlPoints[j].getX() <<
+                               "\t" << avertCtrlPoints[j].getY() <<
+                               "\t" << avertCtrlPoints[j].getZ() << "\t";
+        if( weight == true )
+            cout << ctrlPointsWeight[j] << "\n";
+        else
+            cout << "\n";
+    }
+
+    cout << "Fit pts count: " << averFitPoints.size() << "\n";
+    for( size_t j = 0; j < averFitPoints.size(); ++j )
+    {
+        cout << "  #" << j << ".\t" << averFitPoints[j].getX() <<
+                               "\t" << averFitPoints[j].getY() <<
+                               "\t" << averFitPoints[j].getZ() << "\n";
+    }
+    cout << "\n";
+}
+
+void CADSpline::transform( const Matrix& matrix )
+{
+    for( CADVector& pt : avertCtrlPoints )
+        pt = matrix.multiply( pt );
+    for( CADVector& pt : averFitPoints )
+        pt = matrix.multiply( pt );
+}
+
+long CADSpline::getScenario() const
+{
+    return scenario;
+}
+
+void CADSpline::setScenario( long value )
+{
+    scenario = value;
+}
+
+bool CADSpline::isRational() const
+{
+    return rational;
+}
+
+void CADSpline::setRational( bool value )
+{
+    rational = value;
+}
+
+bool CADSpline::isClosed() const
+{
+    return closed;
+}
+
+void CADSpline::setClosed( bool value )
+{
+    closed = value;
+}
+
+void CADSpline::addControlPointsWeight( double p_weight )
+{
+    ctrlPointsWeight.push_back( p_weight );
+}
+
+void CADSpline::addControlPoint( const CADVector& point )
+{
+    avertCtrlPoints.push_back( point );
+}
+
+void CADSpline::addFitPoint( const CADVector& point )
+{
+    averFitPoints.push_back( point );
+}
+
+bool CADSpline::getWeight() const
+{
+    return weight;
+}
+
+void CADSpline::setWeight( bool value )
+{
+    weight = value;
+}
+
+double CADSpline::getFitTollerance() const
+{
+    return fitTollerance;
+}
+
+void CADSpline::setFitTollerance( double value )
+{
+    fitTollerance = value;
+}
+
+long CADSpline::getDegree() const
+{
+    return degree;
+}
+
+void CADSpline::setDegree( long value )
+{
+    degree = value;
+}
+
+vector<CADVector>& CADSpline::getControlPoints()
+{
+    return avertCtrlPoints;
+}
+
+vector<CADVector>& CADSpline::getFitPoints()
+{
+    return averFitPoints;
+}
+
+vector<double>& CADSpline::getControlPointsWeights()
+{
+    return ctrlPointsWeight;
+}
+
+//------------------------------------------------------------------------------
+// CADSolid
+//------------------------------------------------------------------------------
+
+CADSolid::CADSolid() :
+    elevation( 0.0 )
+{
+    geometryType = CADGeometry::SOLID;
+}
+
+void CADSolid::print() const
+{
+    cout << "|---------Solid---------|\n";
+    for( size_t i = 0; i < avertCorners.size(); ++i )
+    {
+        cout << "  #" << i << ".\t" << avertCorners[i].getX() <<
+                               "\t" << avertCorners[i].getY() << "\n" <<
+                "Elevation: " << elevation << "\n";
+    }
+    cout << "\n";
+}
+
+void CADSolid::transform( const Matrix& matrix )
+{
+    CADPoint3D::transform( matrix );
+    for( CADVector& corner : avertCorners )
+        corner = matrix.multiply( corner );
+}
+
+double CADSolid::getElevation() const
+{
+    return elevation;
+}
+
+void CADSolid::setElevation( double value )
+{
+    elevation = value;
+}
+
+void CADSolid::addCorner( const CADVector& corner )
+{
+    avertCorners.push_back( corner );
+}
+
+vector<CADVector> CADSolid::getCorners()
+{
+    return avertCorners;
+}
+
+//------------------------------------------------------------------------------
+// CADImage
+//------------------------------------------------------------------------------
+
+CADImage::CADImage() :
+    bTransparency( false ),
+    bClipping( false ),
+    dBrightness( 0 ),
+    dContrast( 0 ),
+    resolutionUnits( NONE ),
+    clippingBoundaryType( 0 )
+{
+    geometryType = CADGeometry::IMAGE;
+}
+
+CADVector CADImage::getVertInsertionPoint() const
+{
+    return vertInsertionPoint;
+}
+
+void CADImage::setVertInsertionPoint( const CADVector& value )
+{
+    vertInsertionPoint = value;
+}
+
+CADVector CADImage::getImageSize() const
+{
+    return imageSize;
+}
+
+void CADImage::setImageSize( const CADVector& value )
+{
+    imageSize = value;
+}
+
+CADVector CADImage::getImageSizeInPx() const
+{
+    return imageSizeInPx;
+}
+
+void CADImage::setImageSizeInPx( const CADVector& value )
+{
+    imageSizeInPx = value;
+}
+
+CADVector CADImage::getPixelSizeInACADUnits() const
+{
+    return pixelSizeInACADUnits;
+}
+
+void CADImage::setPixelSizeInACADUnits( const CADVector& value )
+{
+    pixelSizeInACADUnits = value;
+}
+
+short CADImage::getClippingBoundaryType() const
+{
+    return clippingBoundaryType;
+}
+
+void CADImage::setClippingBoundaryType( short value )
+{
+    clippingBoundaryType = value;
+}
+
+enum CADImage::ResolutionUnit CADImage::getResolutionUnits() const
+{
+    return resolutionUnits;
+}
+
+void CADImage::setResolutionUnits( enum CADImage::ResolutionUnit res_unit )
+{
+    resolutionUnits = res_unit;
+}
+
+string CADImage::getFilePath() const
+{
+    return filePath;
+}
+
+void CADImage::setFilePath( const string& value )
+{
+    filePath = value;
+}
+
+void CADImage::setOptions( bool transparency, bool clip, unsigned char brightness,
+    unsigned char contrast )
+{
+    bTransparency = transparency;
+    bClipping     = clip;
+    dBrightness   = brightness;
+    dContrast     = contrast;
+}
+
+void CADImage::print() const
+{
+    cout << "|---------Image---------|\n" <<
+        "Filepath: " << filePath << "\n" <<
+        "Insertion point: " << vertInsertionPoint.getX() << "\t" <<
+                               vertInsertionPoint.getY() << "\n" <<
+        "Transparent? : " << bTransparency << "\n" <<
+        "Brightness (0-100) : " << dBrightness << "\n" <<
+        "Contrast (0-100) : " << dContrast << "\n" <<
+        "Clipping polygon:" << endl;
+    for( size_t i = 0; i < avertClippingPolygon.size(); ++i )
+    {
+        cout << "  #" << i << ". X: " << avertClippingPolygon[i].getX() <<
+                              ", Y: " << avertClippingPolygon[i].getY() << "\n";
+    }
+    cout << "\n";
+}
+
+void CADImage::transform( const Matrix& matrix )
+{
+    vertInsertionPoint = matrix.multiply( vertInsertionPoint );
+    for( CADVector& pt : avertClippingPolygon )
+        pt = matrix.multiply( pt );
+}
+
+void CADImage::addClippingPoint( const CADVector& pt )
+{
+    avertClippingPolygon.push_back( pt );
+}
+
+//------------------------------------------------------------------------------
+// CADMText
+//------------------------------------------------------------------------------
+
+CADMText::CADMText() :
+    rectWidth( 0.0 ),
+    extents( 0.0 ),
+    extentsWidth( 0.0 )
+{
+    geometryType = CADGeometry::MTEXT;
+}
+
+double CADMText::getRectWidth() const
+{
+    return rectWidth;
+}
+
+void CADMText::setRectWidth( double value )
+{
+    rectWidth = value;
+}
+
+double CADMText::getExtents() const
+{
+    return extents;
+}
+
+void CADMText::setExtents( double value )
+{
+    extents = value;
+}
+
+double CADMText::getExtentsWidth() const
+{
+    return extentsWidth;
+}
+
+void CADMText::setExtentsWidth( double value )
+{
+    extentsWidth = value;
+}
+
+void CADMText::print() const
+{
+    cout << "|---------MText---------|\n" <<
+        "Position: " << position.getX() << "\t" <<
+                        position.getY() << "\t" <<
+                        position.getZ() << "\n" <<
+        "Text: " << textValue << "\n\n";
+}
+
+//------------------------------------------------------------------------------
+// CADFace3D
+//------------------------------------------------------------------------------
+
+CADFace3D::CADFace3D() :
+    invisFlags( 0 )
+{
+    geometryType = CADGeometry::FACE3D;
+}
+
+void CADFace3D::addCorner( const CADVector& corner )
+{
+    avertCorners.push_back( corner );
+}
+
+CADVector CADFace3D::getCorner( size_t index )
+{
+    return avertCorners[index];
+}
+
+void CADFace3D::print() const
+{
+    cout << "|---------3DFace---------|\n" <<
+        "Corners: \n";
+    for( size_t i = 0; i < avertCorners.size(); ++i )
+    {
+        cout << "  #" << i << ". X: " << avertCorners[i].getX() << "\t" <<
+                                "Y: " << avertCorners[i].getY() << "\t" <<
+                                "Z: " << avertCorners[i].getZ() << "\n";
+    }
+    cout << "\n";
+}
+
+void CADFace3D::transform( const Matrix& matrix )
+{
+    for( CADVector& corner : avertCorners )
+    {
+        corner = matrix.multiply( corner );
+    }
+}
+
+short CADFace3D::getInvisFlags() const
+{
+    return invisFlags;
+}
+
+void CADFace3D::setInvisFlags( short value )
+{
+    invisFlags = value;
+}
+
+//------------------------------------------------------------------------------
+// CADPolylinePFace
+//------------------------------------------------------------------------------
+
+CADPolylinePFace::CADPolylinePFace()
+{
+    geometryType = CADGeometry::POLYLINE_PFACE;
+}
+
+void CADPolylinePFace::print() const
+{
+    cout << "|---------PolylinePface---------|\n";
+    for( size_t i = 0; i < vertexes.size(); ++i )
+    {
+        cout << "  #" << i << ".\t" << vertexes[i].getX() <<
+                               "\t" << vertexes[i].getY() <<
+                               "\t" << vertexes[i].getZ() << "\n";
+    }
+    cout << "\n";
+}
+
+void CADPolylinePFace::transform( const Matrix& matrix )
+{
+    for( CADVector& vertex : vertexes )
+        vertex = matrix.multiply( vertex );
+}
+
+void CADPolylinePFace::addVertex( const CADVector& vertex )
+{
+    vertexes.push_back( vertex );
+}
+
+//------------------------------------------------------------------------------
+// CADXLine
+//------------------------------------------------------------------------------
+
+CADXLine::CADXLine()
+{
+    geometryType = CADGeometry::XLINE;
+}
+
+void CADXLine::print() const
+{
+    cout << "|---------XLine---------|\n" <<
+        "Position: " << position.getX() << "\t" <<
+                        position.getY() << "\t" <<
+                        position.getZ() << "\n" <<
+        "Direction: " << extrusion.getX() << "\t" <<
+                         extrusion.getY() << "\t" <<
+                         extrusion.getZ() << "\n\n";
+}
+
+//------------------------------------------------------------------------------
+// CADMLine
+//------------------------------------------------------------------------------
+
+CADMLine::CADMLine() :
+    scale( 0.0 ),
+    opened( false )
+{
+    geometryType = CADGeometry::MLINE;
+}
+
+void CADMLine::print() const
+{
+    cout << "|---------MLine---------|\n" <<
+        "Base point: " << position.getX() << "\t" <<
+                          position.getY() << "\t" <<
+                          position.getZ() << "\n" <<
+        "Vertexes:\n";
+    for( size_t i = 0; i < avertVertexes.size(); ++i )
+    {
+        cout << "  #" << i << ".\t" << avertVertexes[i].getX() <<
+                               "\t" << avertVertexes[i].getY() <<
+                               "\t" << avertVertexes[i].getZ() << "\n";
+    }
+    cout << "\n";
+}
+
+void CADMLine::transform( const Matrix& matrix )
+{
+    CADPoint3D::transform( matrix );
+    for( CADVector& vertex : avertVertexes )
+    {
+        vertex = matrix.multiply( vertex );
+    }
+}
+
+double CADMLine::getScale() const
+{
+    return scale;
+}
+
+void CADMLine::setScale( double value )
+{
+    scale = value;
+}
+
+bool CADMLine::isOpened() const
+{
+    return opened;
+}
+
+void CADMLine::setOpened( bool value )
+{
+    opened = value;
+}
+
+void CADMLine::addVertex( const CADVector& vertex )
+{
+    avertVertexes.push_back( vertex );
+}
+
+//------------------------------------------------------------------------------
+// CADAttrib
+//------------------------------------------------------------------------------
+
+CADAttrib::CADAttrib() :
+    dfElevation( 0.0 ),
+    bLockPosition( false )
+{
+    geometryType = CADGeometry::ATTRIB;
+}
+
+void CADAttrib::print() const
+{
+    cout << "|---------Attribute---------|\n" <<
+        "Base point: " << position.getX() << "\t" <<
+                          position.getY() << "\t" <<
+                          position.getZ() << "\n" <<
+        "Tag: " << sTag << "\n" <<
+        "Text: " << textValue << "\n\n";
+}
+
+void CADAttrib::transform( const Matrix& matrix )
+{
+    CADText::transform( matrix );
+    vertAlignmentPoint = matrix.multiply( vertAlignmentPoint );
+}
+
+double CADAttrib::getElevation() const
+{
+    return dfElevation;
+}
+
+void CADAttrib::setElevation( double elev )
+{
+    dfElevation = elev;
+}
+
+string CADAttrib::getTag() const
+{
+    return sTag;
+}
+
+void CADAttrib::setTag( const string& tag )
+{
+    sTag = tag;
+}
+
+CADVector CADAttrib::getAlignmentPoint() const
+{
+    return vertAlignmentPoint;
+}
+
+void CADAttrib::setAlignmentPoint( const CADVector& vect )
+{
+    vertAlignmentPoint = vect;
+}
+
+bool CADAttrib::isPositionLocked() const
+{
+    return bLockPosition;
+}
+
+void CADAttrib::setPositionLocked( bool lock )
+{
+    bLockPosition = lock;
+}
+
+//------------------------------------------------------------------------------
+// CADAttdef
+//------------------------------------------------------------------------------
+
+CADAttdef::CADAttdef()
+{
+    geometryType = CADGeometry::ATTDEF;
+}
+
+void CADAttdef::print() const
+{
+    cout << "|---------Attribute defn---------|\n" <<
+        "Base point: " << position.getX() << "\t" <<
+                          position.getY() << "\t" <<
+                          position.getZ() << "\n" <<
+        "Tag: " << sTag << "\n" <<
+        "Text: " << textValue << "\n" <<
+        "Prompt: " << sPrompt << "\n\n";
+}
+
+string CADAttdef::getPrompt() const
+{
+    return sPrompt;
+}
+
+void CADAttdef::setPrompt( const string& prompt )
+{
+    sPrompt = prompt;
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadgeometry.h b/ogr/ogrsf_frmts/cad/libopencad/cadgeometry.h
new file mode 100644
index 0000000..6ec2dcc
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadgeometry.h
@@ -0,0 +1,683 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef CADGEOMETRIES_H
+#define CADGEOMETRIES_H
+
+#include "cadobjects.h"
+#include "cadcolors.h"
+
+#include <array>
+
+class CADAttdef;
+class CADAttrib;
+
+/**
+ * @brief The Matrix class
+ */
+class Matrix
+{
+public:
+              Matrix();
+    void      translate( const CADVector& vector );
+    void      rotate( double rotation );
+    void      scale( const CADVector& vector );
+    CADVector multiply( const CADVector& vector ) const;
+protected:
+    std::array<double, 9> matrix;
+};
+
+/**
+ * @brief Base CAD geometry class
+ */
+class CADGeometry
+{
+public:
+    CADGeometry();
+    virtual ~CADGeometry();
+    /**
+     * @brief The CAD geometry types enum
+     */
+    enum GeometryType
+    {
+        UNDEFINED = 0,
+        POINT,
+        CIRCLE,
+        LWPOLYLINE,
+        ELLIPSE,
+        LINE,
+        POLYLINE3D,
+        TEXT,
+        ARC,
+        SPLINE,
+        SOLID,
+        RAY,
+        HATCH, // NOT IMPLEMENTED
+        IMAGE,
+        MTEXT,
+        MLINE,
+        XLINE,
+        FACE3D,
+        POLYLINE_PFACE,
+        ATTRIB,
+        ATTDEF
+    };
+
+    enum GeometryType getType() const;
+    double            getThickness() const;
+    void              setThickness( double thicknes );
+    RGBColor          getColor() const;
+    void              setColor( RGBColor color ); // TODO: In 2004+ ACI is not the only way to set the color.
+
+    std::vector<CADAttrib> getBlockAttributes() const;
+    void              setBlockAttributes( const std::vector<CADAttrib>& value );
+
+    std::vector<std::string> getEED() const;
+    void setEED( const std::vector<std::string>& eed );
+
+    virtual void print() const                     = 0;
+    virtual void transform( const Matrix& matrix ) = 0;
+protected:
+    std::vector<CADAttrib> blockAttributes; // Attributes of block reference this geometry is attached to.
+
+    std::vector<std::string>    asEED;
+    enum GeometryType geometryType;
+    double            thickness;
+    RGBColor          geometry_color;
+};
+
+/**
+ * @brief Geometry class which represents Unhandled geometry (means that library can't read it yet)
+ */
+class CADUnknown : public CADGeometry
+{
+public:
+    CADUnknown();
+    virtual ~CADUnknown(){}
+
+    virtual void print() const override;
+    void         transform( const Matrix& matrix ) override;
+};
+
+/**
+ * @brief Geometry class which a single Point
+ */
+class CADPoint3D : public CADGeometry
+{
+public:
+    CADPoint3D();
+    CADPoint3D( const CADVector& positionIn, double thicknessIn );
+    virtual ~CADPoint3D(){}
+    CADVector getPosition() const;
+    void      setPosition( const CADVector& value );
+
+    CADVector getExtrusion() const;
+    void      setExtrusion( const CADVector& value );
+
+    double getXAxisAng() const;
+    void   setXAxisAng( double value );
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    CADVector position;
+    CADVector extrusion;
+    double    xAxisAng;
+};
+
+/**
+ * @brief Geometry class which represents a simple Line
+ */
+class CADLine : public CADGeometry
+{
+public:
+    CADLine();
+    CADLine( const CADPoint3D& startIn, const CADPoint3D& endIn );
+    virtual ~CADLine(){}
+    CADPoint3D getStart() const;
+    void       setStart( const CADPoint3D& value );
+
+    CADPoint3D getEnd() const;
+    void       setEnd( const CADPoint3D& value );
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    CADPoint3D start;
+    CADPoint3D end;
+};
+
+/**
+ * @brief Geometry class which represents Polyline 3D
+ */
+class CADPolyline3D : public CADGeometry
+{
+public:
+    CADPolyline3D();
+    virtual ~CADPolyline3D(){}
+    void   addVertex( const CADVector& vertex );
+    size_t getVertexCount() const;
+    CADVector& getVertex( size_t index );
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    std::vector<CADVector> vertexes;
+};
+
+/**
+ * @brief Geometry class which represents LWPolyline
+ */
+
+class CADLWPolyline : public CADPolyline3D
+{
+public:
+    CADLWPolyline();
+    virtual ~CADLWPolyline(){}
+
+    double getConstWidth() const;
+    void   setConstWidth( double value );
+
+    double getElevation() const;
+    void   setElevation( double value );
+
+    CADVector getVectExtrusion() const;
+    void      setVectExtrusion( const CADVector& value );
+
+    std::vector<std::pair<double, double> > getWidths() const;
+    void  setWidths( const std::vector<std::pair<double, double> >& value );
+
+    std::vector<double> getBulges() const;
+    void           setBulges( const std::vector<double>& value );
+
+    bool isClosed() const;
+    void setClosed( bool state );
+
+    virtual void print() const override;
+protected:
+    bool                          bClosed;
+    double                        constWidth;
+    double                        elevation;
+    CADVector                     vectExtrusion;
+    std::vector<double>                bulges;
+    std::vector<std::pair<double, double> > widths; // Start & end.
+};
+
+/**
+ * @brief Geometry class which represents Circle
+ */
+class CADCircle : public CADPoint3D
+{
+public:
+    CADCircle();
+    virtual ~CADCircle(){}
+
+    double getRadius() const;
+    void   setRadius( double value );
+
+    virtual void print() const override;
+protected:
+    double radius;
+};
+
+/**
+ * @brief Geometry class which represents Text
+ */
+class CADText : public CADPoint3D
+{
+public:
+    CADText();
+    virtual ~CADText(){}
+
+    std::string getTextValue() const;
+    void   setTextValue( const std::string& value );
+
+    double getHeight() const;
+    void   setHeight( double value );
+
+    double getRotationAngle() const;
+    void   setRotationAngle( double value );
+
+    double getObliqueAngle() const;
+    void   setObliqueAngle( double value );
+
+    virtual void print() const override;
+protected:
+    double obliqueAngle;
+    double rotationAngle;
+    double height;
+    std::string textValue;
+};
+
+/**
+ * @brief Geometry class which represents Arc
+ */
+class CADArc : public CADCircle
+{
+public:
+    CADArc();
+    virtual ~CADArc(){}
+
+    double getStartingAngle() const;
+    void   setStartingAngle( double value );
+
+    double getEndingAngle() const;
+    void   setEndingAngle( double value );
+
+    virtual void print() const override;
+protected:
+    double startingAngle;
+    double endingAngle;
+};
+
+/**
+ * @brief Geometry class which represents Ellipse
+ */
+class CADEllipse : public CADArc
+{
+public:
+    CADEllipse();
+    virtual ~CADEllipse(){}
+
+    double getAxisRatio() const;
+    void   setAxisRatio( double value );
+
+    CADVector getSMAxis();
+    void      setSMAxis( const CADVector& vectSMA );
+
+    virtual void print() const override;
+protected:
+    CADVector vectSMAxis;
+    double    axisRatio;
+};
+
+/**
+ * @brief Geometry class which represents Spline
+ */
+class CADSpline : public CADGeometry
+{
+public:
+    CADSpline();
+    virtual ~CADSpline(){}
+
+    long getScenario() const;
+    void setScenario( long value );
+
+    bool isRational() const;
+    void setRational( bool value );
+
+    bool isClosed() const;
+    void setClosed( bool value );
+
+    std::vector<CADVector>& getControlPoints();
+    std::vector<CADVector>& getFitPoints();
+    std::vector<double>   & getControlPointsWeights();
+
+    void addControlPointsWeight( double p_weight );
+    void addControlPoint( const CADVector& point );
+    void addFitPoint( const CADVector& point );
+
+    bool getWeight() const;
+    void setWeight( bool value );
+
+    double getFitTollerance() const;
+    void   setFitTollerance( double value );
+
+    long getDegree() const;
+    void setDegree( long value );
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    long   scenario;
+    bool   rational;
+    bool   closed;
+    bool   weight;
+    double fitTollerance;
+    long   degree;
+
+    std::vector<double>    ctrlPointsWeight;
+    std::vector<CADVector> avertCtrlPoints;
+    std::vector<CADVector> averFitPoints;
+};
+
+/**
+ * @brief Geometry class which represents Solid
+ */
+class CADSolid : public CADPoint3D
+{
+public:
+    CADSolid();
+    virtual ~CADSolid(){}
+
+    double getElevation() const;
+    void   setElevation( double value );
+    void   addCorner( const CADVector& corner );
+    std::vector<CADVector> getCorners();
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    double            elevation;
+    std::vector<CADVector> avertCorners;
+};
+
+/**
+ * @brief Geometry class which represents Ray
+ */
+class CADRay : public CADPoint3D
+{
+public:
+    CADRay();
+    virtual ~CADRay(){}
+
+    CADVector getVectVector() const;
+    void      setVectVector( const CADVector& value );
+
+    virtual void print() const override;
+};
+
+/**
+ * @brief Geometry class which represents Hatch
+ */
+class CADHatch : public CADGeometry
+{
+public:
+    CADHatch();
+    virtual ~CADHatch(){}
+};
+
+/**
+ * @brief Geometry class which represents Image (Raster Image)
+ */
+class CADImage : public CADGeometry
+{
+public:
+    /**
+     * @brief enum which describes in which units Image resolutions is present
+     */
+    enum ResolutionUnit
+    {
+        NONE = 0, CENTIMETER = 2, INCH = 5
+    };
+
+    CADImage();
+    virtual ~CADImage(){}
+
+    CADVector getVertInsertionPoint() const;
+    void      setVertInsertionPoint( const CADVector& value );
+
+    CADVector getImageSize() const;
+    void      setImageSize( const CADVector& value );
+
+    CADVector getImageSizeInPx() const;
+    void      setImageSizeInPx( const CADVector& value );
+
+    CADVector getPixelSizeInACADUnits() const;
+    void      setPixelSizeInACADUnits( const CADVector& value );
+
+    short getClippingBoundaryType() const;
+    void  setClippingBoundaryType( short value );
+
+    enum ResolutionUnit getResolutionUnits() const;
+    void                setResolutionUnits( enum ResolutionUnit value );
+
+    std::string getFilePath() const;
+    void   setFilePath( const std::string& value );
+
+    void setOptions( bool transparency, bool clip, unsigned char brightness,
+                     unsigned char contrast );
+
+    void addClippingPoint( const CADVector& pt );
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    CADVector     vertInsertionPoint;
+    //CADVector vectUDirection;
+    //CADVector vectVDirection;
+    CADVector     imageSize;
+    //bool bShow;
+    //bool bShowWhenNotAlignedWithScreen;
+    //bool bUseClippingBoundary;
+    bool          bTransparency;
+    bool          bClipping;
+    unsigned char dBrightness;
+    unsigned char dContrast;
+    //char dFade;
+
+    CADVector           imageSizeInPx;
+    std::string         filePath;
+    //bool bIsLoaded;
+    enum ResolutionUnit resolutionUnits;
+    //unsigned char       resolutionUnit; // 0 == none, 2 == centimeters, 5 == inches;
+    CADVector           pixelSizeInACADUnits;
+
+    short clippingBoundaryType; // 1 == rect, 2 == polygon
+    std::vector<CADVector> avertClippingPolygon;
+};
+
+/**
+ * @brief Geometry class which represents MText
+ */
+class CADMText : public CADText
+{
+public:
+    CADMText();
+    virtual ~CADMText(){}
+
+    double getRectWidth() const;
+    void   setRectWidth( double value );
+
+    double getExtents() const;
+    void   setExtents( double value );
+
+    double getExtentsWidth() const;
+    void   setExtentsWidth( double value );
+
+    virtual void print() const override;
+protected:
+    double rectWidth;
+    double extents;
+    double extentsWidth;
+    // TODO: do we need this here?
+    //short dDrawingDir;
+    //short dLineSpacingStyle;
+    //short dLineSpacingFactor;
+    //long dBackgroundFlags; // R2004+
+    //long dBackgroundScaleFactor;
+    //short dBackgroundColor;
+    //long dBackgroundTransparency;
+};
+
+/**
+ * @brief Geometry class which represents 3DFace
+ */
+class CADFace3D : public CADGeometry
+{
+public:
+    CADFace3D();
+    virtual ~CADFace3D(){}
+
+    void      addCorner( const CADVector& corner );
+    CADVector getCorner( size_t index );
+
+    short getInvisFlags() const;
+    void  setInvisFlags( short value );
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    std::vector<CADVector> avertCorners;
+    short             invisFlags;
+};
+
+/**
+ * @brief Geometry class which represents Polyline (PFace)
+ */
+class CADPolylinePFace : public CADGeometry
+{
+public:
+    CADPolylinePFace();
+    virtual ~CADPolylinePFace(){}
+
+    void addVertex( const CADVector& vertex );
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    std::vector<CADVector> vertexes;
+};
+
+/**
+ * @brief Geometry class which represents XLine
+ */
+class CADXLine : public CADRay
+{
+public:
+    CADXLine();
+    virtual ~CADXLine(){}
+
+    virtual void print() const override;
+};
+
+/**
+ * @brief Geometry class which represents MLine
+ */
+class CADMLine : public CADPoint3D
+{
+public:
+    CADMLine();
+    virtual ~CADMLine(){}
+
+    double getScale() const;
+    void   setScale( double value );
+
+    bool isOpened() const;
+    void setOpened( bool value );
+
+    void addVertex( const CADVector& vertex );
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    double            scale;
+    //char dJust;
+    bool              opened; // 1 == open, 0 == close
+    // TODO: do we need more properties here?
+    std::vector<CADVector> avertVertexes;
+};
+
+/**
+ * @brief Geometry class which represents Attribute
+ */
+class CADAttrib : public CADText
+{
+public:
+    CADAttrib();
+    virtual ~CADAttrib(){}
+
+    double getElevation() const;
+    void   setElevation( double );
+
+    std::string getTag() const;
+    void   setTag( const std::string& );
+
+    CADVector getAlignmentPoint() const;
+    void      setAlignmentPoint( const CADVector& );
+
+    bool isPositionLocked() const;
+    void setPositionLocked( bool );
+
+    virtual void print() const override;
+    virtual void transform( const Matrix& matrix ) override;
+protected:
+    CADVector vertAlignmentPoint;
+    double    dfElevation;
+    std::string    sTag;
+    bool      bLockPosition;
+};
+
+/**
+ * @brief Geometry class which represents Attribute definition
+ */
+class CADAttdef : public CADAttrib
+{
+public:
+    CADAttdef();
+    virtual ~CADAttdef(){}
+
+    std::string getPrompt() const;
+    void   setPrompt( const std::string& );
+
+    virtual void print() const override;
+protected:
+    std::string sPrompt;
+};
+
+//class EXTERN LineType
+//{
+//public:
+//    std::string sEntryName;
+//    std::string sDescription;
+//    double dfPatternLen;
+//    char dAlignment;
+//    char nNumDashes;
+//    struct Dash
+//    {
+//        double dfLength;
+//        short dComplexShapecode;
+//        double dfXOffset;
+//        double dfYOffset;
+//        double dfScale;
+//        double dfRotation;
+//        short dShapeflag;
+//    };
+//    std::vector < char > abyTextArea; // TODO: what is it?
+//    std::vector < CADHandle > hShapefiles; // TODO: one for each dash?
+//};
+
+//class EXTERN Block
+//{
+//public:
+//    Block(CADFile * pCADFile)
+//    {
+//        pstCADFile_m = pCADFile;
+//    }
+//
+//    std::string sBlockName;
+//
+//    CADFile * pstCADFile_m;
+//
+//    std::vector < std::pair < long long, short > > astAttachedGeometries;
+//};
+
+
+#endif // CADGEOMETRIES_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadheader.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadheader.cpp
new file mode 100644
index 0000000..8890445
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadheader.cpp
@@ -0,0 +1,525 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "cadheader.h"
+#include "opencad_api.h"
+#include "dwg/io.h"
+
+#include <cstring>
+#include <iostream>
+#include <time.h>
+
+#if (defined(__sun__) || defined(__FreeBSD__)) && __GNUC__ == 4 && __GNUC_MINOR__ == 8
+// gcc 4.8 on Solaris 11.3 or FreeBSD 11 doesn't have std::string
+#include <sstream>
+template <typename T> std::string to_string(T val)
+{
+    std::ostringstream os;
+    os << val;
+    return os.str();
+}
+#endif
+
+using namespace std;
+
+typedef struct
+{
+    short      nConstant;
+    short      nGroupCode;
+    const char * pszValueName;
+} CADHeaderConstantDetail;
+
+#define FillCADConstantDetail( x, y ) {CADHeader::x, y, "$"#x}
+
+static const CADHeaderConstantDetail CADHeaderConstantDetails[]{
+        FillCADConstantDetail( ACADMAINTVER, 70 ), FillCADConstantDetail( ACADVER, 1 ),
+        FillCADConstantDetail( ANGBASE, 50 ), FillCADConstantDetail( ANGDIR, 70 ), FillCADConstantDetail( ATTMODE, 70 ),
+        FillCADConstantDetail( AUNITS, 70 ), FillCADConstantDetail( AUPREC, 70 ), FillCADConstantDetail( CECOLOR, 62 ),
+        FillCADConstantDetail( CELTSCALE, 40 ), FillCADConstantDetail( CELTYPE, 6 ),
+        FillCADConstantDetail( CELWEIGHT, 370 ), FillCADConstantDetail( CEPSNID, 390 ),
+        FillCADConstantDetail( CEPSNTYPE, 380 ), FillCADConstantDetail( CHAMFERA, 40 ),
+        FillCADConstantDetail( CHAMFERB, 40 ), FillCADConstantDetail( CHAMFERC, 40 ),
+        FillCADConstantDetail( CHAMFERD, 40 ), FillCADConstantDetail( CLAYER, 8 ), FillCADConstantDetail( CMLJUST, 70 ),
+        FillCADConstantDetail( CMLSCALE, 40 ), FillCADConstantDetail( CMLSTYLE, 2 ),
+        FillCADConstantDetail( CSHADOW, 280 ), FillCADConstantDetail( DIMADEC, 70 ),
+        FillCADConstantDetail( DIMALT, 70 ), FillCADConstantDetail( DIMALTD, 70 ), FillCADConstantDetail( DIMALTF, 40 ),
+        FillCADConstantDetail( DIMALTRND, 40 ), FillCADConstantDetail( DIMALTTD, 70 ),
+        FillCADConstantDetail( DIMALTTZ, 70 ), FillCADConstantDetail( DIMALTU, 70 ),
+        FillCADConstantDetail( DIMALTZ, 70 ), FillCADConstantDetail( DIMAPOST, 1 ), FillCADConstantDetail( DIMASO, 70 ),
+        FillCADConstantDetail( DIMASSOC, 280 ), FillCADConstantDetail( DIMASZ, 40 ),
+        FillCADConstantDetail( DIMATFIT, 70 ), FillCADConstantDetail( DIMAUNIT, 70 ),
+        FillCADConstantDetail( DIMAZIN, 70 ), FillCADConstantDetail( DIMBLK, 1 ), FillCADConstantDetail( DIMBLK1, 1 ),
+        FillCADConstantDetail( DIMBLK2, 1 ), FillCADConstantDetail( DIMCEN, 40 ), FillCADConstantDetail( DIMCLRD, 70 ),
+        FillCADConstantDetail( DIMCLRE, 70 ), FillCADConstantDetail( DIMCLRT, 70 ), FillCADConstantDetail( DIMDEC, 70 ),
+        FillCADConstantDetail( DIMDLE, 40 ), FillCADConstantDetail( DIMDLI, 40 ), FillCADConstantDetail( DIMDSEP, 70 ),
+        FillCADConstantDetail( DIMEXE, 40 ), FillCADConstantDetail( DIMEXO, 40 ), FillCADConstantDetail( DIMFAC, 40 ),
+        FillCADConstantDetail( DIMGAP, 40 ), FillCADConstantDetail( DIMJUST, 70 ),
+        FillCADConstantDetail( DIMLDRBLK, 1 ), FillCADConstantDetail( DIMLFAC, 40 ),
+        FillCADConstantDetail( DIMLIM, 70 ), FillCADConstantDetail( DIMLUNIT, 70 ), FillCADConstantDetail( DIMLWD, 70 ),
+        FillCADConstantDetail( DIMLWE, 70 ), FillCADConstantDetail( DIMPOST, 1 ), FillCADConstantDetail( DIMRND, 40 ),
+        FillCADConstantDetail( DIMSAH, 70 ), FillCADConstantDetail( DIMSCALE, 40 ), FillCADConstantDetail( DIMSD1, 70 ),
+        FillCADConstantDetail( DIMSD2, 70 ), FillCADConstantDetail( DIMSE1, 70 ), FillCADConstantDetail( DIMSE2, 70 ),
+        FillCADConstantDetail( DIMSHO, 70 ), FillCADConstantDetail( DIMSOXD, 70 ), FillCADConstantDetail( DIMSTYLE, 2 ),
+        FillCADConstantDetail( DIMTAD, 70 ), FillCADConstantDetail( DIMTDEC, 70 ), FillCADConstantDetail( DIMTFAC, 40 ),
+        FillCADConstantDetail( DIMTIH, 70 ), FillCADConstantDetail( DIMTIX, 70 ), FillCADConstantDetail( DIMTM, 40 ),
+        FillCADConstantDetail( DIMTMOVE, 70 ), FillCADConstantDetail( DIMTOFL, 70 ),
+        FillCADConstantDetail( DIMTOH, 70 ), FillCADConstantDetail( DIMTOL, 70 ), FillCADConstantDetail( DIMTOLJ, 70 ),
+        FillCADConstantDetail( DIMTP, 40 ), FillCADConstantDetail( DIMTSZ, 40 ), FillCADConstantDetail( DIMTVP, 40 ),
+        FillCADConstantDetail( DIMTXSTY, 7 ), FillCADConstantDetail( DIMTXT, 40 ), FillCADConstantDetail( DIMTZIN, 70 ),
+        FillCADConstantDetail( DIMUPT, 70 ), FillCADConstantDetail( DIMZIN, 70 ), FillCADConstantDetail( DISPSILH, 70 ),
+        FillCADConstantDetail( DRAGVS, 349 ), FillCADConstantDetail( DWGCODEPAGE, 3 ),
+        FillCADConstantDetail( ELEVATION, 40 ), FillCADConstantDetail( ENDCAPS, 280 ),
+        FillCADConstantDetail( EXTMAX, 123 ), FillCADConstantDetail( EXTMIN, 123 ),
+        FillCADConstantDetail( EXTNAMES, 290 ), FillCADConstantDetail( FILLETRAD, 40 ),
+        FillCADConstantDetail( FILLMODE, 70 ), FillCADConstantDetail( FINGERPRINTGUID, 2 ),
+        FillCADConstantDetail( HALOGAP, 280 ), FillCADConstantDetail( HANDSEED, 5 ),
+        FillCADConstantDetail( HIDETEXT, 290 ), FillCADConstantDetail( HYPERLINKBASE, 1 ),
+        FillCADConstantDetail( INDEXCTL, 280 ), FillCADConstantDetail( INSBASE, 123 ),
+        FillCADConstantDetail( INSUNITS, 70 ), FillCADConstantDetail( INTERFERECOLOR, 62 ),
+        FillCADConstantDetail( INTERFEREOBJVS, 345 ), FillCADConstantDetail( INTERFEREVPVS, 346 ),
+        FillCADConstantDetail( INTERSECTIONCOLOR, 70 ), FillCADConstantDetail( INTERSECTIONDISPLAY, 290 ),
+        FillCADConstantDetail( JOINSTYLE, 280 ), FillCADConstantDetail( LIMCHECK, 70 ),
+        FillCADConstantDetail( LIMMAX, 1020 ), FillCADConstantDetail( LIMMIN, 1020 ),
+        FillCADConstantDetail( LTSCALE, 40 ), FillCADConstantDetail( LUNITS, 70 ), FillCADConstantDetail( LUPREC, 70 ),
+        FillCADConstantDetail( LWDISPLAY, 290 ), FillCADConstantDetail( MAXACTVP, 70 ),
+        FillCADConstantDetail( MEASUREMENT, 70 ), FillCADConstantDetail( MENU, 1 ),
+        FillCADConstantDetail( MIRRTEXT, 70 ), FillCADConstantDetail( OBSCOLOR, 70 ),
+        FillCADConstantDetail( OBSLTYPE, 280 ), FillCADConstantDetail( ORTHOMODE, 70 ),
+        FillCADConstantDetail( PDMODE, 70 ), FillCADConstantDetail( PDSIZE, 40 ),
+        FillCADConstantDetail( PELEVATION, 40 ), FillCADConstantDetail( PEXTMAX, 123 ),
+        FillCADConstantDetail( PEXTMIN, 123 ), FillCADConstantDetail( PINSBASE, 123 ),
+        FillCADConstantDetail( PLIMCHECK, 70 ), FillCADConstantDetail( PLIMMAX, 1020 ),
+        FillCADConstantDetail( PLIMMIN, 1020 ), FillCADConstantDetail( PLINEGEN, 70 ),
+        FillCADConstantDetail( PLINEWID, 40 ), FillCADConstantDetail( PROJECTNAME, 1 ),
+        FillCADConstantDetail( PROXYGRAPHICS, 70 ), FillCADConstantDetail( PSLTSCALE, 70 ),
+        FillCADConstantDetail( PSTYLEMODE, 290 ), FillCADConstantDetail( PSVPSCALE, 40 ),
+        FillCADConstantDetail( PUCSBASE, 2 ), FillCADConstantDetail( PUCSNAME, 2 ),
+        FillCADConstantDetail( PUCSORG, 123 ), FillCADConstantDetail( PUCSORGBACK, 123 ),
+        FillCADConstantDetail( PUCSORGBOTTOM, 123 ), FillCADConstantDetail( PUCSORGFRONT, 123 ),
+        FillCADConstantDetail( PUCSORGLEFT, 123 ), FillCADConstantDetail( PUCSORGRIGHT, 123 ),
+        FillCADConstantDetail( PUCSORGTOP, 123 ), FillCADConstantDetail( PUCSORTHOREF, 2 ),
+        FillCADConstantDetail( PUCSORTHOVIEW, 70 ), FillCADConstantDetail( PUCSXDIR, 123 ),
+        FillCADConstantDetail( PUCSYDIR, 123 ), FillCADConstantDetail( QTEXTMODE, 70 ),
+        FillCADConstantDetail( REGENMODE, 70 ), FillCADConstantDetail( SHADEDGE, 70 ),
+        FillCADConstantDetail( SHADEDIF, 70 ), FillCADConstantDetail( SHADOWPLANELOCATION, 40 ),
+        FillCADConstantDetail( SKETCHINC, 40 ), FillCADConstantDetail( SKPOLY, 70 ),
+        FillCADConstantDetail( SORTENTS, 280 ), FillCADConstantDetail( SPLINESEGS, 70 ),
+        FillCADConstantDetail( SPLINETYPE, 70 ), FillCADConstantDetail( SURFTAB1, 70 ),
+        FillCADConstantDetail( SURFTAB2, 70 ), FillCADConstantDetail( SURFTYPE, 70 ),
+        FillCADConstantDetail( SURFU, 70 ), FillCADConstantDetail( SURFV, 70 ), FillCADConstantDetail( TDCREATE, 40 ),
+        FillCADConstantDetail( TDINDWG, 40 ), FillCADConstantDetail( TDUCREATE, 40 ),
+        FillCADConstantDetail( TDUPDATE, 40 ), FillCADConstantDetail( TDUSRTIMER, 40 ),
+        FillCADConstantDetail( TDUUPDATE, 40 ), FillCADConstantDetail( TEXTSIZE, 40 ),
+        FillCADConstantDetail( TEXTSTYLE, 7 ), FillCADConstantDetail( THICKNESS, 40 ),
+        FillCADConstantDetail( TILEMODE, 70 ), FillCADConstantDetail( TRACEWID, 40 ),
+        FillCADConstantDetail( TREEDEPTH, 70 ), FillCADConstantDetail( UCSBASE, 2 ),
+        FillCADConstantDetail( UCSNAME, 2 ), FillCADConstantDetail( UCSORG, 123 ),
+        FillCADConstantDetail( UCSORGBACK, 123 ), FillCADConstantDetail( UCSORGBOTTOM, 123 ),
+        FillCADConstantDetail( UCSORGFRONT, 123 ), FillCADConstantDetail( UCSORGLEFT, 123 ),
+        FillCADConstantDetail( UCSORGRIGHT, 123 ), FillCADConstantDetail( UCSORGTOP, 123 ),
+        FillCADConstantDetail( UCSORTHOREF, 2 ), FillCADConstantDetail( UCSORTHOVIEW, 70 ),
+        FillCADConstantDetail( UCSXDIR, 123 ), FillCADConstantDetail( UCSYDIR, 123 ),
+        FillCADConstantDetail( UNITMODE, 70 ), FillCADConstantDetail( USERI1, 70 ), FillCADConstantDetail( USERI2, 70 ),
+        FillCADConstantDetail( USERI3, 70 ), FillCADConstantDetail( USERI4, 70 ), FillCADConstantDetail( USERI5, 70 ),
+        FillCADConstantDetail( USERR1, 40 ), FillCADConstantDetail( USERR2, 40 ), FillCADConstantDetail( USERR3, 40 ),
+        FillCADConstantDetail( USERR4, 40 ), FillCADConstantDetail( USERR5, 40 ), FillCADConstantDetail( USRTIMER, 70 ),
+        FillCADConstantDetail( VERSIONGUID, 2 ), FillCADConstantDetail( VISRETAIN, 70 ),
+        FillCADConstantDetail( WORLDVIEW, 70 ), FillCADConstantDetail( XCLIPFRAME, 290 ),
+        FillCADConstantDetail( XEDIT, 290 ), { -1, -1, nullptr }
+};
+
+//------------------------------------------------------------------------------
+// CADHandle
+//------------------------------------------------------------------------------
+
+CADHandle::CADHandle( unsigned char codeIn ) : code( codeIn )
+{
+}
+
+CADHandle::CADHandle( const CADHandle& other ) :
+    code( other.code ),
+    handleOrOffset( other.handleOrOffset )
+{
+}
+
+CADHandle& CADHandle::operator=( const CADHandle& other )
+{
+    if( this == & other )
+        return * this;
+    code           = other.code;
+    handleOrOffset = other.handleOrOffset;
+    return * this;
+}
+
+void CADHandle::addOffset( unsigned char val )
+{
+    handleOrOffset.push_back( val );
+}
+
+long CADHandle::getAsLong( const CADHandle& ref_handle ) const
+{
+    switch( code )
+    {
+        case 0x06:
+        {
+            return getAsLong(ref_handle.handleOrOffset) + 1;
+        }
+        case 0x08:
+        {
+            return getAsLong(ref_handle.handleOrOffset) - 1;
+        }
+        case 0x0A:
+        {
+            return getAsLong(ref_handle.handleOrOffset) + getAsLong(handleOrOffset);
+        }
+        case 0x0C:
+        {
+            return getAsLong(ref_handle.handleOrOffset) - getAsLong(handleOrOffset);
+        }
+    }
+
+    return getAsLong(handleOrOffset);
+}
+
+long CADHandle::getAsLong() const
+{
+    return getAsLong(handleOrOffset);
+}
+
+long CADHandle::getAsLong(const std::vector<unsigned char>& handle)
+{
+    long result = 0;
+    if( handle.empty() )
+        return result;
+    memcpy( &result, handle.data(), handle.size() );
+    SwapEndianness( result, handle.size() );
+    return result;
+}
+
+bool CADHandle::isNull() const
+{
+    return handleOrOffset.empty() ? true : false;
+}
+
+//------------------------------------------------------------------------------
+// CADVariant
+//------------------------------------------------------------------------------
+
+CADVariant::CADVariant() :
+    type        ( DataType::INVALID ),
+    decimalVal  ( 0 ),
+    xVal        ( 0 ),
+    yVal        ( 0 ),
+    zVal        ( 0 ),
+    dateTimeVal ( 0 )
+{
+}
+
+CADVariant::CADVariant( const char * val ) :
+    type        ( DataType::STRING ),
+    decimalVal  ( 0 ),
+    xVal        ( 0 ),
+    yVal        ( 0 ),
+    zVal        ( 0 ),
+    stringVal   ( string( val ) ),
+    dateTimeVal ( 0 )
+{
+}
+
+CADVariant::CADVariant( int val ) :
+    type        ( DataType::DECIMAL ),
+    decimalVal  ( val ),
+    xVal        ( 0 ),
+    yVal        ( 0 ),
+    zVal        ( 0 ),
+    stringVal   ( to_string( val ) ),
+    dateTimeVal ( 0 )
+{
+}
+
+CADVariant::CADVariant( short val ) :
+    type        ( DataType::DECIMAL ),
+    decimalVal  ( val ),
+    xVal        ( 0 ),
+    yVal        ( 0 ),
+    zVal        ( 0 ),
+    stringVal   ( to_string( val ) ),
+    dateTimeVal ( 0 )
+{
+}
+
+CADVariant::CADVariant( double val ) :
+    type        ( DataType::REAL ),
+    decimalVal  ( 0 ),
+    xVal        ( val ),
+    yVal        ( 0 ),
+    zVal        ( 0 ),
+    stringVal   ( to_string( val ) ),
+    dateTimeVal ( 0 )
+{
+}
+
+CADVariant::CADVariant( double x, double y, double z ) :
+    type        ( DataType::COORDINATES ),
+    decimalVal  ( 0 ),
+    xVal        ( x ),
+    yVal        ( y ),
+    zVal        ( z ),
+    dateTimeVal ( 0 )
+{
+    char str_buff[256];
+    snprintf( str_buff, sizeof(str_buff), "[%.15g,%.15g,%.15g]", x, y, z );
+    stringVal = str_buff;
+}
+
+CADVariant::CADVariant( const string& val ) :
+    type        ( DataType::STRING ),
+    decimalVal  ( 0 ),
+    xVal        ( 0 ),
+    yVal        ( 0 ),
+    zVal        ( 0 ),
+    stringVal   ( val ),
+    dateTimeVal ( 0 )
+{
+}
+
+CADVariant::CADVariant( time_t val ) :
+    type        ( DataType::DATETIME ),
+    decimalVal  ( 0 ),
+    xVal        ( 0 ),
+    yVal        ( 0 ),
+    zVal        ( 0 ),
+    dateTimeVal ( val )
+{
+    char str_buff[256];
+    strftime(str_buff, 255, "%Y-%m-%d %H:%M:%S", localtime(&dateTimeVal));
+    stringVal = str_buff;
+}
+
+CADVariant::CADVariant( const CADHandle& val ) :
+    type        ( DataType::HANDLE ),
+    decimalVal  ( 0 ),
+    xVal        ( 0 ),
+    yVal        ( 0 ),
+    zVal        ( 0 ),
+    stringVal   ( to_string( val.getAsLong() ) ),
+    handleVal   ( val ),
+    dateTimeVal ( 0 )
+{
+}
+
+CADVariant::CADVariant( const CADVariant& orig ) :
+    type        ( orig.type ),
+    decimalVal  ( orig.decimalVal ),
+    xVal        ( orig.xVal ),
+    yVal        ( orig.yVal ),
+    zVal        ( orig.zVal ),
+    stringVal   ( orig.stringVal ),
+    handleVal   ( orig.handleVal ),
+    dateTimeVal ( orig.dateTimeVal )
+{
+}
+
+CADVariant& CADVariant::operator=( const CADVariant& orig )
+{
+    if( this == & orig )
+        return * this;
+    type        = orig.type;
+    stringVal   = orig.stringVal;
+    decimalVal  = orig.decimalVal;
+    xVal        = orig.xVal;
+    yVal        = orig.yVal;
+    zVal        = orig.zVal;
+    handleVal   = orig.handleVal;
+    dateTimeVal = orig.dateTimeVal;
+    return * this;
+}
+
+long CADVariant::getDecimal() const
+{
+    return decimalVal;
+}
+
+double CADVariant::getReal() const
+{
+    return xVal;
+}
+
+const string& CADVariant::getString() const
+{
+    return stringVal;
+}
+
+CADVariant::DataType CADVariant::getType() const
+{
+    return type;
+}
+
+double CADVariant::getX() const
+{
+    return xVal;
+}
+
+double CADVariant::getY() const
+{
+    return yVal;
+}
+
+double CADVariant::getZ() const
+{
+    return zVal;
+}
+
+const CADHandle& CADVariant::getHandle() const
+{
+    return handleVal;
+}
+
+//------------------------------------------------------------------------------
+// CADHeader
+//------------------------------------------------------------------------------
+
+CADHeader::CADHeader()
+{
+}
+
+int CADHeader::addValue( short code, const CADVariant& val )
+{
+    if( valuesMap.find( code ) != valuesMap.end() )
+        return CADErrorCodes::VALUE_EXISTS;
+
+    valuesMap[code] = val;
+    return CADErrorCodes::SUCCESS;
+}
+
+int CADHeader::addValue( short code, const char * val )
+{
+    return addValue( code, CADVariant( val ) );
+}
+/*
+int CADHeader::addValue( short code, long val )
+{
+    return addValue( code, CADVariant( val ) );
+}
+*/
+int CADHeader::addValue( short code, int val )
+{
+    return addValue( code, CADVariant( val ) );
+}
+
+int CADHeader::addValue( short code, short val )
+{
+    return addValue( code, CADVariant( val ) );
+}
+
+int CADHeader::addValue( short code, double val )
+{
+    return addValue( code, CADVariant( val ) );
+}
+
+int CADHeader::addValue( short code, const string& val )
+{
+    return addValue( code, CADVariant( val ) );
+}
+
+int CADHeader::addValue( short code, bool val )
+{
+    return addValue( code, CADVariant( val ? 1 : 0 ) );
+}
+
+int CADHeader::addValue( short code, double x, double y, double z )
+{
+    return addValue( code, CADVariant( x, y, z ) );
+}
+
+int CADHeader::addValue( short code, long julianday, long milliseconds )
+{
+    // unix -> julian        return ( unixSecs / 86400.0 ) + 2440587.5;
+    // julian -> unix        return (julian - 2440587.5) * 86400.0
+
+    double dfSeconds = double( milliseconds ) / 1000;
+    double dfUnix = 0;
+    if(julianday != 0)
+        dfUnix = ( double( julianday ) - 2440587.5 ) * 86400.0;
+    time_t fullSeconds = static_cast<time_t>( dfUnix + dfSeconds );
+    return addValue( code, CADVariant( fullSeconds ) );
+}
+
+int CADHeader::getGroupCode( short code )
+{
+    for( CADHeaderConstantDetail detail : CADHeaderConstantDetails )
+    {
+        if( detail.nConstant == code )
+            return detail.nGroupCode;
+    }
+
+    return -1;
+}
+
+const CADVariant CADHeader::getValue( short code, const CADVariant& val ) const
+{
+    auto it = valuesMap.find( code );
+    if( it != valuesMap.end() )
+        return it->second;
+    else
+        return val;
+}
+
+const char * CADHeader::getValueName( short code )
+{
+    for( CADHeaderConstantDetail detail : CADHeaderConstantDetails )
+    {
+        if( detail.nConstant == code )
+            return detail.pszValueName;
+    }
+    return "Undefined";
+}
+
+void CADHeader::print() const
+{
+    cout << "============ HEADER Section ============\n";
+    for( auto it : valuesMap )
+    {
+        cout << getValueName( it.first ) << ": " << it.second.getString() << "\n";
+    }
+    cout << "\n";
+}
+
+size_t CADHeader::getSize() const
+{
+    return valuesMap.size();
+}
+
+short CADHeader::getCode( int index ) const
+{
+    auto it = valuesMap.begin();
+    advance( it, index );
+    return it->first;
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadheader.h b/ogr/ogrsf_frmts/cad/libopencad/cadheader.h
new file mode 100644
index 0000000..977f250
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadheader.h
@@ -0,0 +1,709 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef CADHEADER_H
+#define CADHEADER_H
+
+#include "opencad.h"
+#include <map>
+#include <string>
+#include <vector>
+#include <ctime>
+
+class OCAD_EXTERN CADHandle final
+{
+public:
+    explicit CADHandle( unsigned char codeIn = 0 );
+    CADHandle( const CADHandle& other );
+    CADHandle& operator=( const CADHandle& other );
+
+    void addOffset( unsigned char val );
+    bool isNull() const;
+    long getAsLong() const;
+    long getAsLong( const CADHandle& ref_handle ) const;
+private:
+    static long getAsLong(const std::vector<unsigned char>& handle);
+protected:
+    unsigned char              code;
+    std::vector<unsigned char> handleOrOffset;
+};
+
+class OCAD_EXTERN CADVariant final
+{
+public:
+    enum class DataType
+    {
+        INVALID = 0, DECIMAL, REAL, STRING, DATETIME, COORDINATES, HANDLE
+    };
+
+public:
+    CADVariant();
+    // cppcheck-suppress noExplicitConstructor
+    CADVariant( const char * val );
+    // cppcheck-suppress noExplicitConstructor
+    CADVariant( int val );
+    // cppcheck-suppress noExplicitConstructor
+    CADVariant( short val );
+    // cppcheck-suppress noExplicitConstructor
+    CADVariant( double val );
+    CADVariant( double x, double y, double z = 0 );
+    // cppcheck-suppress noExplicitConstructor
+    CADVariant( const CADHandle& val );
+    // cppcheck-suppress noExplicitConstructor
+    CADVariant( const std::string& val );
+    // cppcheck-suppress noExplicitConstructor
+    CADVariant( time_t val );
+public:
+    CADVariant( const CADVariant& orig );
+    CADVariant& operator=( const CADVariant& orig );
+public:
+    long                getDecimal() const;
+    double              getReal() const;
+    const std::string&  getString() const;
+    DataType            getType() const;
+    double              getX() const;
+    double              getY() const;
+    double              getZ() const;
+    const CADHandle&    getHandle() const;
+protected:
+    DataType            type;
+    long                decimalVal;
+    double              xVal;
+    double              yVal;
+    double              zVal;
+    std::string         stringVal;
+    CADHandle           handleVal;
+    time_t              dateTimeVal;
+};
+
+/**
+ * @brief The common CAD header class
+ */
+class OCAD_EXTERN CADHeader
+{
+public:
+    /**
+     * @brief The CAD нeader сonstants enum get from dxf reference:
+     *        http://help.autodesk.com/view/ACD/2016/ENU/?guid=GUID-A85E8E67-27CD-4C59-BE61-4DC9FADBE74A
+     */
+    enum CADHeaderConstants
+    {
+        OPENCADVER          = 1, /**< enum CADVersions value*/
+        ACADMAINTVER, /**< Maintenance version number (should be ignored) */
+        ACADVER, /**< The AutoCAD drawing database version number:
+                              AC1006 = R10
+                              AC1009 = R11 and R12
+                              AC1012 = R13
+                              AC1014 = R14
+                              AC1015 = AutoCAD 2000
+                              AC1018 = AutoCAD 2004
+                              AC1021 = AutoCAD 2007
+                              AC1024 = AutoCAD 2010
+                              AC1027 = AutoCAD 2013 */
+        ANGBASE, /**< Angle 0 direction */
+        ANGDIR, /**< 1 (Clockwise angles) or 0 (Counterclockwise angles) */
+        ATTMODE, /**< Attribute visibility: 0,1,2 */
+        ATTREQ, /**< todo: */
+        ATTDIA, /**< todo: */
+        AUNITS, /**< Units format for angles */
+        AUPREC, /**< Units precision for angles */
+        CECOLOR, /**< 0 = BYBLOCK; 256 = BYLAYER */
+        CELTSCALE, /**< Current entity linetype scale */
+        CELTYPE, /**< Entity linetype name, or BYBLOCK or BYLAYER */
+        CELWEIGHT, /**< Lineweight of new objects */
+        CEPSNID, /**< Plotstyle handle of new objects;
+                              if CEPSNTYPE is 3, then this value indicates the
+                              handle */
+        CEPSNTYPE, /**< Plot style type of new objects:
+                              0 = Plot style by layer,
+                              1 = Plot style by block,
+                              2 = Plot style by dictionary default,
+                              3 = Plot style by object ID/handle */
+        CHAMFERA, /**< First chamfer distance */
+        CHAMFERB, /**< Second chamfer distance */
+        CHAMFERC, /**< Chamfer length */
+        CHAMFERD, /**< Chamfer angle */
+        CLAYER, /**< Current layer name */
+        CMLJUST, /**< Current multiline justification:
+                              0 = Top;
+                              1 = Middle;
+                              2 = Bottom */
+        CMLSCALE, /**< Current multiline scale */
+        CMLSTYLE, /**< Current multiline style name */
+        CSHADOW, /**< Shadow mode for a 3D object:
+                              0 = Casts and receives shadows
+                              1 = Casts shadows
+                              2 = Receives shadows
+                              3 = Ignores shadows */
+        DIMADEC, /**< Number of precision places displayed in angular
+                              dimensions */
+        DIMALT, /**< Alternate unit dimensioning performed if nonzero */
+        DIMALTD, /**< Alternate unit decimal places */
+        DIMALTF, /**< Alternate unit scale factor */
+        DIMALTRND, /**< Determines rounding of alternate units */
+        DIMALTTD, /**< Number of decimal places for tolerance values of
+                              an alternate units dimension */
+        DIMALTTZ, /**< Controls suppression of zeros for alternate
+                              tolerance values:
+                              0 = Suppresses zero feet and precisely zero inches
+                              1 = Includes zero feet and precisely zero inches
+                              2 = Includes zero feet and suppresses zero inches
+                              3 = Includes zero inches and suppresses zero feet */
+        DIMALTU, /**< Units format for alternate units of all dimension
+                              style family members except angular:
+                              1 = Scientific
+                              2 = Decimal
+                              3 = Engineering
+                              4 = Architectural (stacked)
+                              5 = Fractional (stacked)
+                              6 = Architectural
+                              7 = Fractional */
+        DIMALTZ, /**< Controls suppression of zeros for alternate unit
+                              dimension, values:
+                              0 = Suppresses zero feet and precisely zero inches
+                              1 = Includes zero feet and precisely zero inches
+                              2 = Includes zero feet and suppresses zero inches
+                              3 = Includes zero inches and suppresses zero feet */
+        DIMAPOST, /**< Alternate dimensioning suffix */
+        DIMASO, /**< 1 = Create associative dimensioning,
+                              0 = Draw individual entities */
+        DIMASSOC, /**< Controls the associativity of dimension objects:
+                              0 = Creates exploded dimensions; there is no
+                                  association between elements of the dimension,
+                                  and the lines, arcs, arrowheads, and text of a
+                                  dimension are drawn as separate objects
+                              1 = Creates non-associative dimension objects;
+                                  the elements of the dimension are formed into
+                                  a single object, and if the definition point
+                                  on the object moves, then the dimension value
+                                  is updated
+                              2 = Creates associative dimension objects; the
+                                  elements of the dimension are formed into a
+                                  single object and one or more definition
+                                  points of the dimension are coupled with
+                                  association points on geometric objects */
+        DIMASZ, /**< Dimensioning arrow size */
+        DIMATFIT, /**< Controls dimension text and arrow placement when
+                              space is not sufficient to place both within the
+                              extension lines:
+                              0 = Places both text and arrows outside extension
+                                  lines
+                              1 = Moves arrows first, then text
+                              2 = Moves text first, then arrows
+                              3 = Moves either text or arrows, whichever fits
+                                  best AutoCAD adds a leader to moved dimension
+                                  text when DIMTMOVE is set to 1 */
+        DIMAUNIT, /**< Angle format for angular dimensions:
+                              0 = Decimal degrees
+                              1 = Degrees/minutes/seconds
+                              2 = Gradians
+                              3 = Radians
+                              4 = Surveyor's units */
+        DIMAZIN, /**< Controls suppression of zeros for angular
+                              dimensions:
+                              0 = Displays all leading and trailing zeros
+                              1 = Suppresses leading zeros in decimal dimensions
+                              2 = Suppresses trailing zeros in decimal dimensions
+                              3 = Suppresses leading and trailing zeros */
+        DIMBLK, /**< Arrow block name */
+        DIMBLK1, /**< First arrow block name */
+        DIMBLK2, /**< Second arrow block name */
+        DIMCEN, /**< Size of center mark/lines */
+        DIMCLRD, /**< Dimension line color:
+                              range is 0 = BYBLOCK; 256 = BYLAYER */
+        DIMCLRE, /**< Dimension extension line color:
+                              range is 0 = BYBLOCK; 256 = BYLAYER */
+        DIMCLRT, /**< Dimension text color:
+                              range is 0 = BYBLOCK; 256 = BYLAYER */
+        DIMDEC, /**< Number of decimal places for the tolerance values
+                              of a primary units dimension */
+        DIMDLE, /**< Dimension line extension */
+        DIMDLI, /**< Dimension line increment */
+        DIMDSEP, /**< Single-character decimal separator used when
+                              creating dimensions whose unit format is decimal */
+        DIMEXE, /**< Extension line extension */
+        DIMEXO, /**< Extension line offset */
+        DIMFAC, /**< Scale factor used to calculate the height of text
+                              for dimension fractions and tolerances. AutoCAD
+                              multiplies DIMTXT by DIMTFAC to set the fractional
+                              or tolerance text height */
+        DIMGAP, /**< Dimension line gap */
+        DIMJUST, /**< Horizontal dimension text position:
+                              0 = Above dimension line and center-justified
+                                  between extension lines
+                              1 = Above dimension line and next to first
+                                  extension line
+                              2 = Above dimension line and next to second
+                                  extension line
+                              3 = Above and center-justified to first extension
+                                  line
+                              4 = Above and center-justified to second
+                                  extension line */
+        DIMLDRBLK, /**< Arrow block name for leaders */
+        DIMLFAC, /**< Linear measurements scale factor */
+        DIMLIM, /**< Dimension limits generated if nonzero */
+        DIMLUNIT, /**< Sets units for all dimension types except Angular:
+                              1 = Scientific
+                              2 = Decimal
+                              3 = Engineering
+                              4 = Architectural
+                              5 = Fractional
+                              6 = Windows desktop */
+        DIMLWD, /**< Dimension line lineweight:
+                              -3 = Standard
+                              -2 = ByLayer
+                              -1 = ByBlock
+                              0-211 = an integer representing 100th of mm */
+        DIMLWE, /**< Extension line lineweight:
+                              -3 = Standard
+                              -2 = ByLayer
+                              -1 = ByBlock
+                              0-211 = an integer representing 100th of mm */
+        DIMPOST, /**< General dimensioning suffix */
+        DIMRND, /**< Rounding value for dimension distances */
+        DIMSAH, /**< Use separate arrow blocks if nonzero */
+        DIMSCALE, /**< Overall dimensioning scale factor */
+        DIMSD1, /**< Suppression of first extension line:
+                              0 = Not suppressed
+                              1 = Suppressed */
+        DIMSD2, /**< Suppression of second extension line:
+                              0 = Not suppressed
+                              1 = Suppressed */
+        DIMSE1, /**< First extension line suppressed if nonzero */
+        DIMSE2, /**< Second extension line suppressed if nonzero */
+        DIMSHO, /**< 1 = Recompute dimensions while dragging
+                              0 = Drag original image */
+        DIMSOXD, /**< Suppress outside-extensions dimension lines if
+                              nonzero */
+        DIMSTYLE, /**< Dimension style name */
+        DIMTAD, /**< Text above dimension line if nonzero */
+        DIMTDEC, /**< Number of decimal places to display the tolerance
+                              values */
+        DIMTFAC, /**< Dimension tolerance display scale factor */
+        DIMTIH, /**< Text inside horizontal if nonzero */
+        DIMTIX, /**< Force text inside extensions if nonzero */
+        DIMTM, /**< Minus tolerance */
+        DIMTMOVE, /**< Dimension text movement rules:
+                              0 = Moves the dimension line with dimension text
+                              1 = Adds a leader when dimension text is moved
+                              2 = Allows text to be moved freely without a leader */
+        DIMTOFL, /**< If text is outside extensions, force line
+                              extensions between extensions if nonzero */
+        DIMTOH, /**< Text outside horizontal if nonzero */
+        DIMTOL, /**< Dimension tolerances generated if nonzero */
+        DIMTOLJ, /**< Vertical justification for tolerance values:
+                              0 = Top
+                              1 = Middle
+                              2 = Bottom */
+        DIMTP, /**< Plus tolerance */
+        DIMTSZ, /**< Dimensioning tick size:
+                              0 = No ticks */
+        DIMTVP, /**< Text vertical position */
+        DIMTXSTY, /**< Dimension text style */
+        DIMTXT, /**< Dimensioning text height */
+        DIMTZIN, /**< Controls suppression of zeros for tolerance values:
+                              0 = Suppresses zero feet and precisely zero inches
+                              1 = Includes zero feet and precisely zero inches
+                              2 = Includes zero feet and suppresses zero inches
+                              3 = Includes zero inches and suppresses zero feet */
+        DIMUPT, /**< Cursor functionality for user-positioned text:
+                              0 = Controls only the dimension line location
+                              1 = Controls the text position as well as the
+                                  dimension line location */
+        DIMZIN, /**< Controls suppression of zeros for primary unit
+                              values:
+                              0 = Suppresses zero feet and precisely zero inches
+                              1 = Includes zero feet and precisely zero inches
+                              2 = Includes zero feet and suppresses zero inches
+                              3 = Includes zero inches and suppresses zero feet */
+        DISPSILH, /**< Controls the display of silhouette curves of body
+                              objects in Wireframe mode:
+                              0 = Off
+                              1 = On */
+        DRAGVS, /**< Hard-pointer ID to visual style while creating 3D
+                              solid primitives. The default value is NULL */
+        DWGCODEPAGE, /**< Drawing code page; set to the system code page
+                              when a new drawing is created, but not otherwise
+                              maintained by AutoCAD */
+        ELEVATION, /**< Current elevation set by ELEV command */
+        ENDCAPS, /**< Lineweight endcaps setting for new objects:
+                              0 = none
+                              1 = round
+                              2 = angle
+                              3 = square */
+        EXTMAX, /**< X, Y, and Z drawing extents upper-right corner
+                              (in WCS) */
+        EXTMIN, /**< X, Y, and Z drawing extents lower-left corner
+                              (in WCS) */
+        EXTNAMES, /**< Controls symbol table naming:
+                              0 = Release 14 compatibility. Limits names to 31
+                                  characters in length. Names can include the
+                                  letters A to Z, the numerals 0 to 9, and the
+                                  special characters dollar sign ($), underscore
+                                  (_), and hyphen (-).
+                              1 = AutoCAD 2000. Names can be up to 255 characters
+                                  in length, and can include the letters A to Z,
+                                  the numerals 0 to 9, spaces, and any special
+                                  characters not used for other purposes by
+                                  Microsoft Windows and AutoCAD */
+        FILLETRAD, /**< Fillet radius */
+        FILLMODE, /**< Fill mode on if nonzero */
+        FINGERPRINTGUID, /**< Set at creation time, uniquely identifies a
+                              particular drawing */
+        HALOGAP, /**< Specifies a gap to be displayed where an object is
+                              hidden by another object; the value is specified
+                              as a percent of one unit and is independent of the
+                              zoom level. A haloed line is shortened at the
+                              point where it is hidden when HIDE or the Hidden
+                              option of SHADEMODE is used */
+        HANDSEED, /**< Next available handle */
+        HIDETEXT, /**< Specifies HIDETEXT system variable:
+                              0 = HIDE ignores text objects when producing the
+                                  hidden view
+                              1 = HIDE does not ignore text objects */
+        HYPERLINKBASE, /**< Path for all relative hyperlinks in the drawing.
+                              If null, the drawing path is used */
+        INDEXCTL, /**< Controls whether layer and spatial indexes are
+                              created and saved in drawing files:
+                              0 = No indexes are created
+                              1 = Layer index is created
+                              2 = Spatial index is created
+                              3 = Layer and spatial indexes are created */
+        INSBASE, /**< Insertion base set by BASE command (in WCS) */
+        INSUNITS, /**< Default drawing units for AutoCAD DesignCenter
+                              blocks:
+                              0 = Unitless
+                              1 = Inches
+                              2 = Feet
+                              3 = Miles
+                              4 = Millimeters
+                              5 = Centimeters
+                              6 = Meters
+                              7 = Kilometers
+                              8 = Microinches
+                              9 = Mils
+                             10 = Yards
+                             11 = Angstroms
+                             12 = Nanometers
+                             13 = Microns
+                             14 = Decimeters
+                             15 = Decameters
+                             16 = Hectometers
+                             17 = Gigameters
+                             18 = Astronomical units
+                             19 = Light years
+                             20 = Parsecs */
+        INTERFERECOLOR, /**< Represents the ACI color index of the
+                              "interference objects" created during the
+                              interfere command. Default value is 1 */
+        INTERFEREOBJVS, /**< Hard-pointer ID to the visual style for
+                              interference objects. Default visual style is
+                              Conceptual */
+        INTERFEREVPVS, /**< Hard-pointer ID to the visual style for the
+                              viewport during interference checking. Default
+                              visual style is 3d Wireframe. */
+        INTERSECTIONCOLOR, /**< Specifies the entity color of intersection
+                                 polylines:
+                                 Values 1-255 designate an AutoCAD color index (ACI)
+                                 0 = Color BYBLOCK
+                               256 = Color BYLAYER
+                               257 = Color BYENTITY */
+        INTERSECTIONDISPLAY, /**< Specifies the display of intersection polylines:
+                                 0 = Turns off the display of intersection
+                                     polylines
+                                 1 = Turns on the display of intersection
+                                     polylines */
+        JOINSTYLE, /**< Lineweight joint setting for new objects:
+                              0 = none
+                              1 = round
+                              2 = angle
+                              3 = flat */
+        LIMCHECK, /**< Nonzero if limits checking is on */
+        LIMMAX, /**< XY drawing limits upper-right corner (in WCS) */
+        LIMMIN, /**< XY drawing limits lower-left corner (in WCS) */
+        LTSCALE, /**< Global linetype scale */
+        LUNITS, /**< Units format for coordinates and distances */
+        LUPREC, /**< Units precision for coordinates and distances */
+        LWDISPLAY, /**< Controls the display of lineweights on the Model
+                              or Layout tab:
+                              0 = Lineweight is not displayed
+                              1 = Lineweight is displayed */
+        MAXACTVP, /**< Sets maximum number of viewports to be regenerated */
+        MEASUREMENT, /**< Sets drawing units:
+                              0 = English
+                              1 = Metric */
+        MENU, /**< Name of menu file */
+        MIRRTEXT, /**< Mirror text if nonzero */
+        OBSCOLOR, /**< Specifies the color of obscured lines. An obscured
+                              line is a hidden line made visible by changing its
+                              color and linetype and is visible only when the
+                              HIDE or SHADEMODE command is used. The OBSCUREDCOLOR
+                              setting is visible only if the OBSCUREDLTYPE is
+                              turned ON by setting it to a value other than 0.
+                              0 and 256 = Entity color
+                              1-255 = An AutoCAD color index (ACI) */
+        OBSLTYPE, /**< Specifies the linetype of obscured lines. Obscured
+                              linetypes are independent of zoom level, unlike
+                              regular AutoCAD linetypes. Value 0 turns off
+                              display of obscured lines and is the default.
+                              Linetype values are defined as follows:
+                              0 = Off
+                              1 = Solid
+                              2 = Dashed
+                              3 = Dotted
+                              4 = Short Dash
+                              5 = Medium Dash
+                              6 = Long Dash
+                              7 = Double Short Dash
+                              8 = Double Medium Dash
+                              9 = Double Long Dash
+                             10 = Medium Long Dash
+                             11 = Sparse Dot */
+        ORTHOMODE, /**< Ortho mode on if nonzero */
+        PDMODE, /**< Point display mode */
+        PDSIZE, /**< Point display size */
+        PELEVATION, /**< Current paper space elevation */
+        PEXTMAX, /**< Maximum X, Y, and Z extents for paper space */
+        PEXTMIN, /**< Minimum X, Y, and Z extents for paper space */
+        PINSBASE, /**< Paper space insertion base point */
+        PLIMCHECK, /**< Limits checking in paper space when nonzero */
+        PLIMMAX, /**< Maximum X and Y limits in paper space */
+        PLIMMIN, /**< Minimum X and Y limits in paper space */
+        PLINEGEN, /**< Governs the generation of linetype patterns around
+                              the vertices of a 2D polyline:
+                              1 = Linetype is generated in a continuous pattern
+                                  around vertices of the polyline
+                              0 = Each segment of the polyline starts and ends
+                                  with a dash */
+        PLINEWID, /**< Default polyline width */
+        PROJECTNAME, /**< Assigns a project name to the current drawing.
+                              Used when an external reference or image is not
+                              found on its original path. The project name
+                              points to a section in the registry that can
+                              contain one or more search paths for each project
+                              name defined. Project names and their search
+                              directories are created from the Files tab of the
+                              Options dialog box */
+        PROXYGRAPHICS, /**< Controls the saving of proxy object images */
+        PSLTSCALE, /**< Controls paper space linetype scaling:
+                              1 = No special linetype scaling
+                              0 = Viewport scaling governs linetype scaling */
+        PSTYLEMODE, /**< Indicates whether the current drawing is in a
+                              Color-Dependent or Named Plot Style mode:
+                              0 = Uses named plot style tables in the current
+                                  drawing
+                              1 = Uses color-dependent plot style tables in the
+                                  current drawing */
+        PSVPSCALE, /**< View scale factor for new viewports:
+                              0 = Scaled to fit
+                             >0 = Scale factor (a positive real value) */
+        PUCSBASE, /**< Name of the UCS that defines the origin and
+                              orientation of orthographic UCS settings (paper
+                              space only) */
+        PUCSNAME, /**< Current paper space UCS name */
+        PUCSORG, /**< Current paper space UCS origin */
+        PUCSORGBACK, /**< Point which becomes the new UCS origin after
+                              changing paper space UCS to BACK when PUCSBASE is
+                              set to WORLD */
+        PUCSORGBOTTOM, /**< Point which becomes the new UCS origin after
+                              changing paper space UCS to BOTTOM when PUCSBASE
+                              is set to WORLD */
+        PUCSORGFRONT, /**< Point which becomes the new UCS origin after
+                              changing paper space UCS to FRONT when PUCSBASE is
+                              set to WORLD */
+        PUCSORGLEFT, /**< Point which becomes the new UCS origin after
+                              changing paper space UCS to LEFT when PUCSBASE is
+                              set to WORLD */
+        PUCSORGRIGHT, /**< Point which becomes the new UCS origin after
+                              changing paper space UCS to RIGHT when PUCSBASE is
+                              set to WORLD */
+        PUCSORGTOP, /**< Point which becomes the new UCS origin after
+                              changing paper space UCS to TOP when PUCSBASE is
+                              set to WORLD */
+        PUCSORTHOREF, /**< If paper space UCS is orthographic (PUCSORTHOVIEW
+                              not equal to 0), this is the name of the UCS that
+                              the orthographic UCS is relative to. If blank, UCS
+                              is relative to WORLD */
+        PUCSORTHOVIEW, /**< Orthographic view type of paper space UCS:
+                              0 = UCS is not orthographic
+                              1 = Top
+                              2 = Bottom
+                              3 = Front
+                              4 = Back
+                              5 = Left
+                              6 = Right */
+        PUCSXDIR, /**< Current paper space UCS X axis */
+        PUCSYDIR, /**< Current paper space UCS Y axis */
+        QTEXTMODE, /**< Quick Text mode on if nonzero */
+        REGENMODE, /**< REGENAUTO mode on if nonzero */
+        SHADEDGE, /**< 0 = Faces shaded, edges not highlighted
+                              1 = Faces shaded, edges highlighted in black
+                              2 = Faces not filled, edges in entity color
+                              3 = Faces in entity color, edges in black */
+        SHADEDIF, /**< Percent ambient/diffuse light range 1-100
+                              default 70 */
+        SHADOWPLANELOCATION, /**< Location of the ground shadow plane. This is a
+                                  Z axis ordinate. */
+        SKETCHINC, /**< Sketch record increment */
+        SKPOLY, /**< 0 = Sketch lines
+                              1 = Sketch polylines */
+        SORTENTS, /**< Controls the object sorting methods; accessible
+                              from the Options dialog box User Preferences tab.
+                              SORTENTS uses the following bitcodes:
+                              0 = Disables SORTENTS
+                              1 = Sorts for object selection
+                              2 = Sorts for object snap
+                              4 = Sorts for redraws
+                              8 = Sorts for MSLIDE command slide creation
+                             16 = Sorts for REGEN commands
+                             32 = Sorts for plotting
+                             64 = Sorts for PostScript output */
+        SPLINESEGS, /**< Number of line segments per spline patch */
+        SPLINETYPE, /**< Spline curve type for PEDIT Spline */
+        SURFTAB1, /**< Number of mesh tabulations in first direction */
+        SURFTAB2, /**< Number of mesh tabulations in second direction */
+        SURFTYPE, /**< Surface type for PEDIT Smooth */
+        SURFU, /**< Surface density (for PEDIT Smooth) in M direction */
+        SURFV, /**< Surface density (for PEDIT Smooth) in N direction */
+        TDCREATE, /**< Local date/time of drawing creation (see “Special
+                              Handling of Date/Time Variables”) */
+        TDINDWG, /**< Cumulative editing time for this drawing */
+        TDUCREATE, /**< Universal date/time the drawing was created */
+        TDUPDATE, /**< Local date/time of last drawing update */
+        TDUSRTIMER, /**< User-elapsed timer */
+        TDUUPDATE, /**< Universal date/time of the last update/save */
+        TEXTSIZE, /**< Default text height */
+        TEXTSTYLE, /**< Current text style name */
+        THICKNESS, /**< Current thickness set by ELEV command */
+        TILEMODE, /**< 1 for previous release compatibility mode
+                              0 otherwise */
+        TRACEWID, /**< Default trace width */
+        TREEDEPTH, /**< Specifies the maximum depth of the spatial index */
+        UCSBASE, /**< Name of the UCS that defines the origin and
+                              orientation of orthographic UCS settings */
+        UCSNAME, /**< Name of current UCS */
+        UCSORG, /**< Origin of current UCS (in WCS) */
+        UCSORGBACK, /**< Point which becomes the new UCS origin after
+                              changing model space UCS to BACK when UCSBASE is
+                              set to WORLD */
+        UCSORGBOTTOM, /**< Point which becomes the new UCS origin after
+                              changing model space UCS to BOTTOM when UCSBASE is
+                              set to WORLD */
+        UCSORGFRONT, /**< Point which becomes the new UCS origin after
+                              changing model space UCS to FRONT when UCSBASE is
+                              set to WORLD */
+        UCSORGLEFT, /**< Point which becomes the new UCS origin after
+                              changing model space UCS to LEFT when UCSBASE is
+                              set to WORLD */
+        UCSORGRIGHT, /**< Point which becomes the new UCS origin after
+                              changing model space UCS to RIGHT when UCSBASE is
+                              set to WORLD */
+        UCSORGTOP, /**< Point which becomes the new UCS origin after
+                              changing model space UCS to TOP when UCSBASE is
+                              set to WORLD */
+        UCSORTHOREF, /**< If model space UCS is orthographic (UCSORTHOVIEW
+                              not equal to 0), this is the name of the UCS that
+                              the orthographic UCS is relative to. If blank, UCS
+                              is relative to WORLD */
+        UCSORTHOVIEW, /**< Orthographic view type of model space UCS:
+                              0 = UCS is not orthographic
+                              1 = Top
+                              2 = Bottom
+                              3 = Front
+                              4 = Back
+                              5 = Left
+                              6 = Right */
+        UCSXDIR, /**< Direction of the current UCS X axis (in WCS) */
+        UCSYDIR, /**< Direction of the current UCS Y axis (in WCS) */
+        UNITMODE, /**< Low bit set = Display fractions, feet-and-inches,
+                              and surveyor's angles in input format */
+        USERI1, /**< Five integer variables intended for use by
+                              third-party developers */
+        USERI2, USERI3, USERI4, USERI5, USERR1, /**< Five real variables intended for use by
+                              third-party developers */
+        USERR2, USERR3, USERR4, USERR5, USRTIMER, /**< 0 = Timer off
+                              1 = Timer on */
+        VERSIONGUID, /**< Uniquely identifies a particular version of a
+                              drawing. Updated when the drawing is modified */
+        VISRETAIN, /**< 0 = Don't retain xref-dependent visibility settings
+                              1 = Retain xref-dependent visibility settings */
+        WORLDVIEW, /**< 1 = Set UCS to WCS during DVIEW/VPOINT
+                              0 = Don't change UCS */
+        XCLIPFRAME, /**< Controls the visibility of xref clipping
+                              boundaries:
+                              0 = Clipping boundary is not visible
+                              1 = Clipping boundary is visible */
+        XEDIT, /**< Controls whether the current drawing can be edited
+                              in-place when being referenced by another drawing.
+                              0 = Can't use in-place reference editing
+                              1 = Can use in-place reference editing */
+        SPLFRAME, /** ? */
+        WORDLVIEW, /** ? */
+        PELLIPSE, /** ? */
+        ISOLINES, /** ? */
+        TEXTQLTY, /** ? */
+        FACETRES, /** ? */
+        DIMFRAC, /** ? */
+        OLESTARTUP, /** ? */
+        STYLESHEET, /** ? */
+        TSTACKALIGN, /**< default = 1 (not present in DXF) */
+        TSTACKSIZE, /**< default = 70 (not present in DXF) */
+        MAX_HEADER_CONSTANT = 1000 /**< max + num for user constants */
+
+    };
+public:
+                     CADHeader();
+    /**
+     * @brief Add new value to the CAD file header
+     * @param code The code from constants enum
+     * @param val Value to add
+     * @return SUCCESS or some value from CADErrorCodes
+     */
+    int              addValue( short code, const CADVariant& val );
+    int              addValue( short code, const char * val );
+    //int              addValue( short code, long val );
+    int              addValue( short code, int val );
+    int              addValue( short code, short val );
+    int              addValue( short code, double val );
+    int              addValue( short code, const std::string& val );
+    int              addValue( short code, bool val );
+    int              addValue( short code, double x, double y, double z = 0 );
+    int              addValue( short code, long julianday, long milliseconds );
+    static int              getGroupCode( short code );
+    const CADVariant getValue( short code, const CADVariant& val = CADVariant() ) const;
+    static const char * getValueName( short code );
+    void   print() const;
+    size_t getSize() const;
+    short  getCode( int index ) const;
+protected:
+    std::map<short, CADVariant> valuesMap;
+};
+
+#endif // CADHEADER_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadlayer.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadlayer.cpp
new file mode 100644
index 0000000..f5a74c0
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadlayer.cpp
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "cadlayer.h"
+#include "cadfile.h"
+
+#include <cassert>
+#include <iostream>
+#include <algorithm>
+
+CADLayer::CADLayer( CADFile * file ) :
+    frozen( false ),
+    on( true ),
+    frozenByDefault( false ),
+    locked( false ),
+    plotting( false ),
+    lineWeight( 1 ),
+    color( 0 ),
+    layerId( 0 ),
+    layer_handle( 0 ),
+    pCADFile( file )
+{
+}
+
+std::string CADLayer::getName() const
+{
+    return layerName;
+}
+
+void CADLayer::setName( const std::string& value )
+{
+    layerName = value;
+}
+
+bool CADLayer::getFrozen() const
+{
+    return frozen;
+}
+
+void CADLayer::setFrozen( bool value )
+{
+    frozen = value;
+}
+
+bool CADLayer::getOn() const
+{
+    return on;
+}
+
+void CADLayer::setOn( bool value )
+{
+    on = value;
+}
+
+bool CADLayer::getFrozenByDefault() const
+{
+    return frozenByDefault;
+}
+
+void CADLayer::setFrozenByDefault( bool value )
+{
+    frozenByDefault = value;
+}
+
+bool CADLayer::getLocked() const
+{
+    return locked;
+}
+
+void CADLayer::setLocked( bool value )
+{
+    locked = value;
+}
+
+bool CADLayer::getPlotting() const
+{
+    return plotting;
+}
+
+void CADLayer::setPlotting( bool value )
+{
+    plotting = value;
+}
+
+short CADLayer::getLineWeight() const
+{
+    return lineWeight;
+}
+
+void CADLayer::setLineWeight( short value )
+{
+    lineWeight = value;
+}
+
+short CADLayer::getColor() const
+{
+    return color;
+}
+
+void CADLayer::setColor( short value )
+{
+    color = value;
+}
+
+size_t CADLayer::getId() const
+{
+    return layerId;
+}
+
+void CADLayer::setId( const size_t& value )
+{
+    layerId = value;
+}
+
+long CADLayer::getHandle() const
+{
+    return layer_handle;
+}
+
+void CADLayer::setHandle( long value )
+{
+    layer_handle = value;
+}
+
+void CADLayer::addHandle( long handle, CADObject::ObjectType type, long cadinserthandle )
+{
+#ifdef _DEBUG
+    std::cout << "addHandle: " << handle << " type: " << type << "\n";
+#endif //_DEBUG
+    if( type == CADObject::ATTRIB || type == CADObject::ATTDEF )
+    {
+        std::unique_ptr<CADAttdef> attdef( static_cast< CADAttdef *>(
+                         pCADFile->GetGeometry( this->getId() - 1, handle ) ) );
+        attributesNames.insert( attdef->getTag() );
+    }
+
+    if( type == CADObject::INSERT )
+    {
+        // TODO: transform insert to block of objects (do we need to transform
+        // coordinates according to insert point)?
+        std::unique_ptr<CADObject> insert( pCADFile->GetObject( handle, false ) );
+        CADInsertObject * pInsert = static_cast<CADInsertObject *>(insert.get());
+        if( nullptr != pInsert )
+        {
+            std::unique_ptr<CADObject> blockHeader( pCADFile->GetObject(
+                                    pInsert->hBlockHeader.getAsLong(), false ) );
+            CADBlockHeaderObject * pBlockHeader =
+                          static_cast<CADBlockHeaderObject *>(blockHeader.get());
+            if( nullptr != pBlockHeader )
+            {
+#ifdef _DEBUG
+                if( pBlockHeader->bBlkisXRef )
+                {
+                    assert( 0 );
+                }
+#endif //_DEBUG
+                auto dCurrentEntHandle = pBlockHeader->hEntities[0].getAsLong();
+                auto dLastEntHandle    = pBlockHeader->hEntities.back().getAsLong(); // FIXME: in 2000+ entities probably has no links to each other.
+
+                if( dCurrentEntHandle == dLastEntHandle ) // Blocks can be empty (contain no objects)
+                    return;
+
+                while( true )
+                {
+                    std::unique_ptr<CADEntityObject> entity(
+                        static_cast< CADEntityObject * >( pCADFile->GetObject(
+                                                    dCurrentEntHandle, true ) ) );
+
+                    if( dCurrentEntHandle == dLastEntHandle )
+                    {
+                        if( entity != nullptr )
+                        {
+                            addHandle( dCurrentEntHandle, entity->getType(), handle );
+                            Matrix mat;
+                            mat.translate( pInsert->vertInsertionPoint );
+                            mat.scale( pInsert->vertScales );
+                            mat.rotate( pInsert->dfRotation );
+                            transformations[dCurrentEntHandle] = mat;
+                            break;
+                        }
+                        else
+                        {
+                            assert( 0 );
+                        }
+                    }
+
+                    if( entity != nullptr )
+                    {
+                        addHandle( dCurrentEntHandle, entity->getType(), handle );
+                        Matrix mat;
+                        mat.translate( pInsert->vertInsertionPoint );
+                        mat.scale( pInsert->vertScales );
+                        mat.rotate( pInsert->dfRotation );
+                        transformations[dCurrentEntHandle] = mat;
+
+                        if( entity->stCed.bNoLinks )
+                            ++dCurrentEntHandle;
+                        else
+                            dCurrentEntHandle =
+                                entity->stChed.hNextEntity.getAsLong(
+                                    entity->stCed.hObjectHandle );
+                    }
+                    else
+                    {
+                        assert ( 0 );
+                    }
+                }
+            }
+        }
+        return;
+    }
+
+    if( isCommonEntityType( type ) )
+    {
+        if( type == CADObject::IMAGE )
+            imageHandles.push_back( handle );
+        else
+        {
+            if( pCADFile->isReadingUnsupportedGeometries() == false )
+            {
+                if( isSupportedGeometryType( type ) )
+                {
+                    if( geometryTypes.empty() ) geometryTypes.push_back( type );
+
+                    if( find( geometryTypes.begin(), geometryTypes.end(), type ) ==
+                        geometryTypes.end() )
+                    {
+                        geometryTypes.push_back( type );
+                    }
+                    geometryHandles.push_back( std::make_pair( handle, cadinserthandle ) );
+                }
+            }
+            else
+            {
+                if( geometryTypes.empty() ) geometryTypes.push_back( type );
+
+                if( find( geometryTypes.begin(), geometryTypes.end(), type ) ==
+                    geometryTypes.end() )
+                {
+                    geometryTypes.push_back( type );
+                }
+                geometryHandles.push_back( std::make_pair( handle, cadinserthandle ) );
+            }
+        }
+    }
+}
+
+size_t CADLayer::getGeometryCount() const
+{
+    return geometryHandles.size();
+}
+
+CADGeometry * CADLayer::getGeometry( size_t index )
+{
+    auto handleBlockRefPair = geometryHandles[index];
+    CADGeometry * pGeom = pCADFile->GetGeometry( this->getId() - 1,
+                        handleBlockRefPair.first, handleBlockRefPair.second );
+    if( nullptr == pGeom )
+        return nullptr;
+    auto iter = transformations.find( handleBlockRefPair.first );
+    if( iter != transformations.end() )
+    {
+        // transform geometry if nHandle is in transformations
+        pGeom->transform( iter->second );
+    }
+    return pGeom;
+}
+
+size_t CADLayer::getImageCount() const
+{
+    return imageHandles.size();
+}
+
+CADImage * CADLayer::getImage( size_t index )
+{
+    return static_cast<CADImage *>(pCADFile->GetGeometry( this->getId() - 1,
+                                                            imageHandles[index] ));
+}
+
+bool CADLayer::addAttribute( const CADObject * pObject )
+{
+    if( nullptr == pObject )
+        return true;
+
+    auto attrib = static_cast<const CADAttribObject *>(pObject);
+    for( auto i = geometryAttributes.begin(); i != geometryAttributes.end(); ++i )
+    {
+        if( i->first == attrib->stChed.hOwner.getAsLong() )
+        {
+            i->second.insert( make_pair( attrib->sTag, layer_handle ) );
+            return true;
+        }
+    }
+
+    return false;
+}
+
+std::vector<CADObject::ObjectType> CADLayer::getGeometryTypes()
+{
+    return geometryTypes;
+}
+
+std::unordered_set<std::string> CADLayer::getAttributesTags()
+{
+    return attributesNames;
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadlayer.h b/ogr/ogrsf_frmts/cad/libopencad/cadlayer.h
new file mode 100644
index 0000000..8cdf713
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadlayer.h
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef CADLAYER_H
+#define CADLAYER_H
+
+#include "cadgeometry.h"
+
+#include <memory>
+#include <unordered_set>
+
+class CADFile;
+
+class OCAD_EXTERN CADLayer
+{
+public:
+    explicit       CADLayer( CADFile * file );
+    std::string getName() const;
+    void   setName( const std::string& value );
+
+    bool getFrozen() const;
+    void setFrozen( bool value );
+
+    bool getOn() const;
+    void setOn( bool value );
+
+    bool getFrozenByDefault() const;
+    void setFrozenByDefault( bool value );
+
+    bool getLocked() const;
+    void setLocked( bool value );
+
+    bool getPlotting() const;
+    void setPlotting( bool value );
+
+    short getLineWeight() const;
+    void  setLineWeight( short value );
+
+    short getColor() const;
+    void  setColor( short value );
+
+    size_t getId() const;
+    void   setId( const size_t& value );
+
+    long getHandle() const;
+    void setHandle( long value );
+
+    std::unordered_set<std::string> getAttributesTags();
+
+    // cadinserthandle is 0 by default because if entity isn't a part of custom block - its a part of ModelSpace block.
+    void addHandle( long handle, enum CADObject::ObjectType type, long cadinserthandle = 0 );
+
+    size_t getGeometryCount() const;
+    CADGeometry * getGeometry( size_t index );
+    size_t getImageCount() const;
+    CADImage * getImage( size_t index );
+
+    /**
+     * @brief returns a vector of presented geometries types
+     */
+    std::vector<CADObject::ObjectType> getGeometryTypes();
+
+protected:
+    bool addAttribute( const CADObject * pObject );
+protected:
+    std::string layerName;
+    bool   frozen;
+    bool   on;
+    bool   frozenByDefault;
+    bool   locked;
+    bool   plotting;
+    short  lineWeight;
+    short  color;
+    size_t layerId;
+    long   layer_handle;
+
+    std::vector<CADObject::ObjectType>  geometryTypes; // FIXME: replace with hashset would be perfect
+    std::unordered_set<std::string>     attributesNames;
+    std::vector<std::pair<long, long> > geometryHandles; // second param is CADInsert handle, 0 if its not a geometry in block ref.
+    std::vector<long>                   imageHandles;
+    std::vector<std::pair<long, std::map<std::string, long> > > geometryAttributes;
+    std::map<long, Matrix>              transformations;
+
+    CADFile * pCADFile;
+};
+
+#endif // CADLAYER_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadobjects.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadobjects.cpp
new file mode 100644
index 0000000..a53587e
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadobjects.cpp
@@ -0,0 +1,918 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+
+#include "cadobjects.h"
+
+#include <math.h>
+#include <algorithm>
+
+//------------------------------------------------------------------------------
+// CADVector
+//------------------------------------------------------------------------------
+#define EPSILON std::numeric_limits<double>::epsilon() * 16
+
+CADVector::CADVector( double x, double y ) :
+    X( x ),
+    Y( y ),
+    Z( 0.0 ),
+    bHasZ( false )
+{
+
+}
+
+CADVector::CADVector( double x, double y, double z ) :
+    X( x ),
+    Y( y ),
+    Z( z ),
+    bHasZ( true )
+{
+
+}
+
+CADVector::CADVector( const CADVector& other )
+{
+    X     = other.X;
+    Y     = other.Y;
+    Z     = other.Z;
+    bHasZ = other.bHasZ;
+}
+
+bool CADVector::operator==( const CADVector& second )
+{
+    return ( fcmp( this->X, second.X ) && fcmp( this->Y, second.Y ) &&
+                                                    fcmp( this->Z, second.Z ) );
+}
+
+CADVector& CADVector::operator=( const CADVector& second )
+{
+    if( &second != this )
+    {
+        X     = second.X;
+        Y     = second.Y;
+        Z     = second.Z;
+        bHasZ = second.bHasZ;
+    }
+    return * this;
+}
+
+bool CADVector::fcmp( double x, double y )
+{
+    return fabs( x - y ) < EPSILON ? true : false;
+}
+
+bool CADVector::getBHasZ() const
+{
+    return bHasZ;
+}
+
+void CADVector::setBHasZ( bool value )
+{
+    bHasZ = value;
+}
+
+double CADVector::getZ() const
+{
+    return Z;
+}
+
+void CADVector::setZ( double value )
+{
+    if( !bHasZ )
+        bHasZ = true;
+    Z         = value;
+}
+
+double CADVector::getY() const
+{
+    return Y;
+}
+
+void CADVector::setY( double value )
+{
+    Y = value;
+}
+
+double CADVector::getX() const
+{
+    return X;
+}
+
+void CADVector::setX( double value )
+{
+    X = value;
+}
+
+CADVector::CADVector() : X( .0 ), Y( .0 ), Z( .0 ), bHasZ( true )
+{
+
+}
+
+//------------------------------------------------------------------------------
+// CADText
+//------------------------------------------------------------------------------
+
+CADTextObject::CADTextObject() :
+    CADEntityObject(TEXT),
+    DataFlags(0),
+    dfElevation(0.0),
+    dfThickness(0.0),
+    dfObliqueAng(0.0),
+    dfRotationAng(0.0),
+    dfHeight(0.0),
+    dfWidthFactor(0.0),
+    dGeneration(0),
+    dHorizAlign(0),
+    dVertAlign(0)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADAttribObject
+//------------------------------------------------------------------------------
+
+CADAttribObject::CADAttribObject(ObjectType typeIn) :
+    CADEntityObject(typeIn),
+    DataFlags( 0 ),
+    dfElevation(0.0),
+    dfThickness(0.0),
+    dfObliqueAng(0.0),
+    dfRotationAng(0.0),
+    dfHeight(0.0),
+    dfWidthFactor(0.0),
+    dGeneration(0),
+    dHorizAlign(0),
+    dVertAlign(0),
+    dVersion(0),
+    nFieldLength(0),
+    nFlags(0),
+    bLockPosition(false)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADAttdef
+//------------------------------------------------------------------------------
+
+CADAttdefObject::CADAttdefObject() :
+    CADAttribObject(ATTDEF)
+{
+}
+
+
+//------------------------------------------------------------------------------
+// CADBlockObject
+//------------------------------------------------------------------------------
+
+CADBlockObject::CADBlockObject() :
+    CADEntityObject(BLOCK)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADEndblkObject
+//------------------------------------------------------------------------------
+
+CADEndblkObject::CADEndblkObject() :
+    CADEntityObject(ENDBLK)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADSeqendObject
+//------------------------------------------------------------------------------
+
+CADSeqendObject::CADSeqendObject() :
+    CADEntityObject(SEQEND)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADInsertObject
+//------------------------------------------------------------------------------
+
+CADInsertObject::CADInsertObject(ObjectType typeIn) :
+    CADEntityObject(typeIn),
+    dfRotation( 0.0 ),
+    bHasAttribs( false ),
+    nObjectsOwned( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADMInsertObject
+//------------------------------------------------------------------------------
+
+CADMInsertObject::CADMInsertObject() :
+    CADEntityObject(MINSERT1), // TODO: it has 2 type codes?
+    dfRotation( 0.0 ),
+    bHasAttribs( false ),
+    nObjectsOwned( 0 ),
+    nNumCols( 0 ),
+    nNumRows( 0 ),
+    nColSpacing( 0 ),
+    nRowSpacing( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADVertex2DObject
+//------------------------------------------------------------------------------
+
+CADVertex2DObject::CADVertex2DObject() :
+    CADEntityObject(VERTEX2D),
+    dfStartWidth( 0.0 ),
+    dfEndWidth( 0.0 ),
+    dfBulge( 0.0 ),
+    nVertexID( 0 ),
+    dfTangentDir( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADVertex3DObject
+//------------------------------------------------------------------------------
+
+CADVertex3DObject::CADVertex3DObject() :
+    CADEntityObject(VERTEX3D)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADVertexMeshObject
+//------------------------------------------------------------------------------
+
+CADVertexMeshObject::CADVertexMeshObject() :
+    CADEntityObject(VERTEX_MESH)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADVertexPFaceObject
+//------------------------------------------------------------------------------
+
+CADVertexPFaceObject::CADVertexPFaceObject() :
+    CADEntityObject(VERTEX_PFACE)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADVertexPFaceFaceObject
+//------------------------------------------------------------------------------
+
+CADVertexPFaceFaceObject::CADVertexPFaceFaceObject() :
+    CADEntityObject(VERTEX_PFACE_FACE),
+    iVertexIndex1( 0 ),
+    iVertexIndex2( 0 ),
+    iVertexIndex3( 0 ),
+    iVertexIndex4( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADPolyline2DObject
+//------------------------------------------------------------------------------
+
+CADPolyline2DObject::CADPolyline2DObject() :
+    CADEntityObject(POLYLINE2D),
+    dFlags( 0 ),
+    dCurveNSmoothSurfType( 0 ),
+    dfStartWidth( 0.0 ),
+    dfEndWidth( 0.0 ),
+    dfThickness( 0.0 ),
+    dfElevation( 0.0 ),
+    nObjectsOwned( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADPolyline3DObject
+//------------------------------------------------------------------------------
+
+CADPolyline3DObject::CADPolyline3DObject() :
+    CADEntityObject(POLYLINE3D),
+    SplinedFlags( 0 ),
+    ClosedFlags( 0 ),
+    nObjectsOwned( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADArcObject
+//------------------------------------------------------------------------------
+
+CADArcObject::CADArcObject() :
+    CADEntityObject(ARC),
+    dfRadius( 0.0 ),
+    dfThickness( 0.0 ),
+    dfStartAngle( 0.0 ),
+    dfEndAngle( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADCircleObject
+//------------------------------------------------------------------------------
+
+CADCircleObject::CADCircleObject() :
+    CADEntityObject(CIRCLE),
+    dfRadius( 0.0 ),
+    dfThickness( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADLineObject
+//------------------------------------------------------------------------------
+
+CADLineObject::CADLineObject() :
+    CADEntityObject(LINE),
+    dfThickness( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADBlockControlObject
+//------------------------------------------------------------------------------
+
+CADBlockControlObject::CADBlockControlObject() :
+    CADObject(BLOCK_CONTROL_OBJ),
+    nObjectSizeInBits( 0 ),
+    nNumReactors( 0 ),
+    bNoXDictionaryPresent( false ),
+    nNumEntries( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADBlockHeaderObject
+//------------------------------------------------------------------------------
+
+CADBlockHeaderObject::CADBlockHeaderObject() :
+    CADObject(BLOCK_HEADER),
+    nObjectSizeInBits( 0 ),
+    nNumReactors( 0 ),
+    bNoXDictionaryPresent( false ),
+    b64Flag( false ),
+    dXRefIndex( 0 ),
+    bXDep( false ),
+    bAnonymous( false ),
+    bHasAtts( false ),
+    bBlkisXRef( false ),
+    bXRefOverlaid( false ),
+    bLoadedBit( false ),
+    nOwnedObjectsCount( 0 ),
+    nSizeOfPreviewData( 0 ),
+    nInsertUnits( 0 ),
+    bExplodable( false ),
+    dBlockScaling( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADLayerControlObject
+//------------------------------------------------------------------------------
+
+CADLayerControlObject::CADLayerControlObject() :
+    CADObject(LAYER_CONTROL_OBJ),
+    nObjectSizeInBits( 0 ),
+    nNumReactors( 0 ),
+    bNoXDictionaryPresent( false ),
+    nNumEntries( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADLayerObject
+//------------------------------------------------------------------------------
+
+CADLayerObject::CADLayerObject() :
+    CADObject(LAYER),
+    nObjectSizeInBits( 0 ),
+    nNumReactors( 0 ),
+    bNoXDictionaryPresent( false ),
+    b64Flag( 0 ),
+    dXRefIndex( 0 ),
+    bXDep( 0 ),
+    bFrozen( false ),
+    bOn( false ),
+    bFrozenInNewVPORT( false ),
+    bLocked( false ),
+    bPlottingFlag( false ),
+    dLineWeight( 0 ),
+    dCMColor( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADLineTypeControlObject
+//------------------------------------------------------------------------------
+
+CADLineTypeControlObject::CADLineTypeControlObject() :
+    CADObject(LTYPE_CONTROL_OBJ),
+    nObjectSizeInBits( 0 ),
+    nNumReactors( 0 ),
+    bNoXDictionaryPresent( false ),
+    nNumEntries( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADLineTypeObject
+//------------------------------------------------------------------------------
+
+CADLineTypeObject::CADLineTypeObject() :
+    CADObject(LTYPE1),
+    nObjectSizeInBits( 0 ),
+    nNumReactors( 0 ),
+    bNoXDictionaryPresent( false ),
+    b64Flag( false ),
+    dXRefIndex( 0 ),
+    bXDep( false ),
+    dfPatternLen( 0.0 ),
+    dAlignment( 0 ),
+    nNumDashes( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADPointObject
+//------------------------------------------------------------------------------
+
+CADPointObject::CADPointObject() :
+    CADEntityObject(POINT),
+    dfThickness( 0.0 ),
+    dfXAxisAng( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADSolidObject
+//------------------------------------------------------------------------------
+
+CADSolidObject::CADSolidObject() :
+    CADEntityObject(SOLID),
+    dfThickness( 0.0 ),
+    dfElevation( 0.0 )
+{
+    avertCorners.reserve( 4 );
+}
+
+//------------------------------------------------------------------------------
+// CADEllipseObject
+//------------------------------------------------------------------------------
+
+CADEllipseObject::CADEllipseObject() :
+    CADEntityObject(ELLIPSE),
+    dfAxisRatio( 0.0 ),
+    dfBegAngle( 0.0 ),
+    dfEndAngle( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADRayObject
+//------------------------------------------------------------------------------
+
+CADRayObject::CADRayObject() :
+    CADEntityObject(RAY)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADXLineObject
+//------------------------------------------------------------------------------
+
+CADXLineObject::CADXLineObject() :
+    CADEntityObject(XLINE)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADDictionaryObject
+//------------------------------------------------------------------------------
+
+CADDictionaryObject::CADDictionaryObject() :
+    CADObject(DICTIONARY),
+    nObjectSizeInBits( 0 ),
+    nNumReactors( 0 ),
+    bNoXDictionaryPresent( false ),
+    nNumItems( 0 ),
+    dCloningFlag( 0 ),
+    dHardOwnerFlag( 0 )
+
+{
+}
+
+//------------------------------------------------------------------------------
+// CADLWPolylineObject
+//------------------------------------------------------------------------------
+
+CADLWPolylineObject::CADLWPolylineObject() :
+    CADEntityObject(LWPOLYLINE),
+    bClosed( false ),
+    dfConstWidth( 0.0 ),
+    dfElevation( 0.0 ),
+    dfThickness( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADSplineObject
+//------------------------------------------------------------------------------
+
+CADSplineObject::CADSplineObject() :
+    CADEntityObject( SPLINE ),
+    dScenario( 0 ),
+    dSplineFlags( 0 ),
+    dKnotParameter( 0 ),
+    dDegree( 0 ),
+    dfFitTol( 0.0 ),
+    nNumFitPts( 0 ),
+    bRational( false ),
+    bClosed( false ),
+    bPeriodic( false ),
+    dfKnotTol( 0.0 ),
+    dfCtrlTol( 0.0 ),
+    nNumKnots( 0 ),
+    nNumCtrlPts( 0 ),
+    bWeight( false )
+{
+}
+
+//------------------------------------------------------------------------------
+
+const std::vector<char> CADCommonEntityObjectTypes{
+    CADObject::POINT, CADObject::ARC, CADObject::TEXT, CADObject::ELLIPSE,
+    CADObject::CIRCLE, CADObject::LINE, CADObject::LWPOLYLINE,
+    CADObject::POLYLINE3D, CADObject::MLINE, CADObject::SPLINE, CADObject::SOLID,
+    CADObject::MTEXT, CADObject::IMAGE, CADObject::XLINE, CADObject::RAY,
+    CADObject::MLINE, CADObject::FACE3D, CADObject::POLYLINE_PFACE,
+    CADObject::ATTRIB, CADObject::ATTDEF, CADObject::POLYLINE2D, CADObject::HATCH,
+    CADObject::INSERT, CADObject::VERTEX3D, CADObject::VERTEX2D,
+    CADObject::VERTEX_MESH, CADObject::VERTEX_PFACE, CADObject::VERTEX_PFACE_FACE,
+    CADObject::TOLERANCE, CADObject::SOLID3D, CADObject::WIPEOUT, CADObject::TRACE
+};
+
+const std::vector<char> CADSupportedGeometryTypes{
+    CADObject::POINT, CADObject::ARC, CADObject::TEXT, CADObject::ELLIPSE,
+    CADObject::CIRCLE, CADObject::LINE, CADObject::LWPOLYLINE,
+    CADObject::POLYLINE3D, CADObject::MLINE, CADObject::ATTRIB, CADObject::ATTDEF,
+    CADObject::RAY, CADObject::SPLINE, CADObject::SOLID, CADObject::IMAGE,
+    CADObject::MTEXT, CADObject::POLYLINE_PFACE, CADObject::XLINE,
+    CADObject::FACE3D
+};
+
+bool isCommonEntityType( short nType )
+{
+    return std::find( CADCommonEntityObjectTypes.begin(),
+                      CADCommonEntityObjectTypes.end(),
+                      nType ) != CADCommonEntityObjectTypes.end();
+}
+
+bool isSupportedGeometryType( short nType )
+{
+    return std::find( CADSupportedGeometryTypes.begin(),
+                      CADSupportedGeometryTypes.end(),
+                      nType ) !=  CADSupportedGeometryTypes.end();
+}
+
+const std::map<char, std::string> CADObjectNames{
+    { CADObject::UNUSED,               "UNUSED" },
+    { CADObject::TEXT,                 "TEXT" },
+    { CADObject::ATTRIB,               "ATTRIB" },
+    { CADObject::ATTDEF,               "ATTDEF" },
+    { CADObject::BLOCK,                "BLOCK" },
+    { CADObject::ENDBLK,               "ENDBLK" },
+    { CADObject::SEQEND,               "SEQEND" },
+    { CADObject::INSERT,               "INSERT" },
+    { CADObject::MINSERT1,             "MINSERT" },
+    { CADObject::MINSERT2,             "MINSERT" },
+    { CADObject::VERTEX2D,             "VERTEX 2D" },
+    { CADObject::VERTEX3D,             "VERTEX 3D" },
+    { CADObject::VERTEX_MESH,          "VERTEX MESH" },
+    { CADObject::VERTEX_PFACE,         "VERTEX PFACE" },
+    { CADObject::VERTEX_PFACE_FACE,    "VERTEX PFACE FACE" },
+    { CADObject::POLYLINE2D,           "POLYLINE 2D" },
+    { CADObject::POLYLINE3D,           "POLYLINE 3D" },
+    { CADObject::ARC,                  "ARC" },
+    { CADObject::CIRCLE,               "CIRCLE" },
+    { CADObject::LINE,                 "LINE" },
+    { CADObject::DIMENSION_ORDINATE,   "DIMENSION ORDINATE" },
+    { CADObject::DIMENSION_LINEAR,     "DIMENSION LINEAR" },
+    { CADObject::DIMENSION_ALIGNED,    "DIMENSION ALIGNED" },
+    { CADObject::DIMENSION_ANG_3PT,    "DIMENSION ANG 3PT" },
+    { CADObject::DIMENSION_ANG_2LN,    "DIMENSION AND 2LN" },
+    { CADObject::DIMENSION_RADIUS,     "DIMENSION RADIUS" },
+    { CADObject::DIMENSION_DIAMETER,   "DIMENSION DIAMETER" },
+    { CADObject::POINT,                "POINT" },
+    { CADObject::FACE3D,               "3DFACE" },
+    { CADObject::POLYLINE_PFACE,       "POLYLINE PFACE" },
+    { CADObject::POLYLINE_MESH,        "POLYLINE MESH" },
+    { CADObject::SOLID,                "SOLID" },
+    { CADObject::TRACE,                "TRACE" },
+    { CADObject::SHAPE,                "SHAPE" },
+    { CADObject::VIEWPORT,             "VIEWPORT" },
+    { CADObject::ELLIPSE,              "ELLIPSE" },
+    { CADObject::SPLINE,               "SPLINE" },
+    { CADObject::REGION,               "REGION" },
+    { CADObject::SOLID3D,              "3DSOLID" },
+    { CADObject::BODY,                 "BODY" },
+    { CADObject::RAY,                  "RAY" },
+    { CADObject::XLINE,                "XLINE" },
+    { CADObject::DICTIONARY,           "DICTIONARY" },
+    { CADObject::OLEFRAME,             "OLEFRAME" },
+    { CADObject::MTEXT,                "MTEXT" },
+    { CADObject::LEADER,               "LEADER" },
+    { CADObject::TOLERANCE,            "TOLERANCE" },
+    { CADObject::MLINE,                "MLINE" },
+    { CADObject::BLOCK_CONTROL_OBJ,    "BLOCK CONTROL OBJ" },
+    { CADObject::BLOCK_HEADER,         "BLOCK HEADER" },
+    { CADObject::LAYER_CONTROL_OBJ,    "LAYER CONTROL OBJ" },
+    { CADObject::LAYER,                "LAYER" },
+    { CADObject::STYLE_CONTROL_OBJ,    "STYLE CONTROL OBJ" },
+    { CADObject::STYLE1,               "STYLE1" },
+    { CADObject::STYLE2,               "STYLE2" },
+    { CADObject::STYLE3,               "STYLE3" },
+    { CADObject::LTYPE_CONTROL_OBJ,    "LTYPE CONTROL OBJ" },
+    { CADObject::LTYPE1,               "LTYPE1" },
+    { CADObject::LTYPE2,               "LTYPE2" },
+    { CADObject::LTYPE3,               "LTYPE3" },
+    { CADObject::VIEW_CONTROL_OBJ,     "VIEW CONTROL OBJ" },
+    { CADObject::VIEW,                 "VIEW" },
+    { CADObject::UCS_CONTROL_OBJ,      "UCS CONTROL OBJ" },
+    { CADObject::UCS,                  "UCS" },
+    { CADObject::VPORT_CONTROL_OBJ,    "VPORT CONTROL OBJ" },
+    { CADObject::VPORT,                "VPORT" },
+    { CADObject::APPID_CONTROL_OBJ,    "APPID CONTROL OBJ" },
+    { CADObject::APPID,                "APPID" },
+    { CADObject::DIMSTYLE_CONTROL_OBJ, "DIMSTYLE CONTROL OBJ" },
+    { CADObject::DIMSTYLE,             "DIMSTYLE" },
+    { CADObject::VP_ENT_HDR_CTRL_OBJ,  "VP ENT HDR CTRL OBJ" },
+    { CADObject::VP_ENT_HDR,           "VP ENT HDR" },
+    { CADObject::GROUP,                "GROUP" },
+    { CADObject::MLINESTYLE,           "MLINESTYLE" },
+    { CADObject::OLE2FRAME,            "OLE2FRAME" },
+    { CADObject::DUMMY,                "DUMMY" },
+    { CADObject::LONG_TRANSACTION,     "LONG TRANSACTION" },
+    { CADObject::LWPOLYLINE,           "LWPOLYLINE" },
+    { CADObject::HATCH,                "HATCH" },
+    { CADObject::XRECORD,              "XRECORD" },
+    { CADObject::ACDBPLACEHOLDER,      "ACDBPLACEHOLDER" },
+    { CADObject::VBA_PROJECT,          "VBA PROJECT" },
+    { CADObject::LAYOUT,               "LAYOUT" }
+};
+
+std::string getNameByType( CADObject::ObjectType eType )
+{
+    auto it = CADObjectNames.find( eType );
+    if( it == CADObjectNames.end() )
+        return "";
+
+    return it->second;
+}
+//------------------------------------------------------------------------------
+// CADObject
+//------------------------------------------------------------------------------
+
+CADObject::ObjectType CADObject::getType() const
+{
+    return type;
+}
+
+long CADObject::getSize() const
+{
+    return size;
+}
+
+void CADObject::setSize( long value )
+{
+    size = value;
+}
+
+short CADObject::getCRC() const
+{
+    return CRC;
+}
+
+void CADObject::setCRC( unsigned short value )
+{
+    CRC = value;
+}
+
+//------------------------------------------------------------------------------
+// CADDimensionOrdinateObject
+//------------------------------------------------------------------------------
+
+CADDimensionOrdinateObject::CADDimensionOrdinateObject() :
+    CADDimensionObject(DIMENSION_ORDINATE),
+    Flags2( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADDimensionLinearObject
+//------------------------------------------------------------------------------
+
+CADDimensionLinearObject::CADDimensionLinearObject() :
+    CADDimensionObject(DIMENSION_LINEAR),
+    dfExtLnRot( 0.0 ),
+    dfDimRot( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADDimensionAlignedObject
+//------------------------------------------------------------------------------
+
+CADDimensionAlignedObject::CADDimensionAlignedObject() :
+    CADDimensionObject(DIMENSION_ALIGNED),
+    dfExtLnRot( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADDimensionAngular3PtObject
+//------------------------------------------------------------------------------
+
+CADDimensionAngular3PtObject::CADDimensionAngular3PtObject(ObjectType typeIn) :
+    CADDimensionObject(typeIn)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADDimensionAngular2LnObject
+//------------------------------------------------------------------------------
+
+CADDimensionAngular2LnObject::CADDimensionAngular2LnObject() :
+    CADDimensionAngular3PtObject(DIMENSION_ANG_2LN)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADDimensionRadiusObject
+//------------------------------------------------------------------------------
+
+CADDimensionRadiusObject::CADDimensionRadiusObject(ObjectType typeIn) :
+    CADDimensionObject(typeIn),
+    dfLeaderLen( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADDimensionDiameterObject
+//------------------------------------------------------------------------------
+
+CADDimensionDiameterObject::CADDimensionDiameterObject() :
+    CADDimensionRadiusObject(DIMENSION_DIAMETER)
+{
+}
+
+//------------------------------------------------------------------------------
+// CADImageObject
+//------------------------------------------------------------------------------
+
+CADImageObject::CADImageObject() :
+    CADEntityObject(IMAGE),
+    dClassVersion( 0 ),
+    dfSizeX( 0.0 ),
+    dfSizeY( 0.0 ),
+    dDisplayProps( 0 ),
+    bClipping( false ),
+    dBrightness( 0 ),
+    dContrast( 0 ),
+    dFade( 0 ),
+    bClipMode( false ),
+    dClipBoundaryType( 0 ),
+    nNumberVertexesInClipPolygon( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADImageDefObject
+//------------------------------------------------------------------------------
+
+CADImageDefObject::CADImageDefObject() :
+    CADImageDefReactorObject(IMAGEDEF),
+    dfXImageSizeInPx( 0.0 ),
+    dfYImageSizeInPx( 0.0 ),
+    bIsLoaded( false ),
+    dResUnits( 0 ),
+    dfXPixelSize( 0.0 ),
+    dfYPixelSize( 0.0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADImageDefReactorObject
+//------------------------------------------------------------------------------
+
+CADImageDefReactorObject::CADImageDefReactorObject(ObjectType typeIn) :
+    CADObject(typeIn),
+    nObjectSizeInBits( 0 ),
+    nNumReactors( 0 ),
+    bNoXDictionaryPresent( false ),
+    dClassVersion( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADMTextObject
+//------------------------------------------------------------------------------
+
+CADMTextObject::CADMTextObject() :
+    CADEntityObject(MTEXT),
+    dfRectWidth( 0.0 ),
+    dfTextHeight( 0.0 ),
+    dAttachment( 0 ),
+    dDrawingDir( 0 ),
+    dfExtents( 0.0 ),
+    dfExtentsWidth( 0.0 ),
+    dLineSpacingStyle( 0 ),
+    dLineSpacingFactor( 0 ),
+    bUnknownBit( false),
+    dBackgroundFlags( 0 ),
+    dBackgroundScaleFactor( 0 ),
+    dBackgroundColor( 0 ),
+    dBackgroundTransparency( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADMLineObject
+//------------------------------------------------------------------------------
+
+CADMLineObject::CADMLineObject() :
+    CADEntityObject(MLINE),
+    dfScale( 0.0 ),
+    dJust( 0 ),
+    dOpenClosed( 0 ),
+    nLinesInStyle( 0 ),
+    nNumVertexes( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CAD3DFaceObject
+//------------------------------------------------------------------------------
+
+CAD3DFaceObject::CAD3DFaceObject() :
+    CADEntityObject(FACE3D),
+    bHasNoFlagInd( false ),
+    bZZero( false ),
+    dInvisFlags( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADPolylinePFaceObject
+//------------------------------------------------------------------------------
+
+CADPolylinePFaceObject::CADPolylinePFaceObject() :
+    CADEntityObject(POLYLINE_PFACE),
+    nNumVertexes( 0 ),
+    nNumFaces( 0 ),
+    nObjectsOwned( 0 )
+{
+}
+
+//------------------------------------------------------------------------------
+// CADXRecordObject
+//------------------------------------------------------------------------------
+
+CADXRecordObject::CADXRecordObject() :
+    CADObject(XRECORD),
+    nObjectSizeInBits( 0 ),
+    nNumReactors( 0 ),
+    bNoXDictionaryPresent( false ),
+    nNumDataBytes( 0 ),
+    dCloningFlag( 0 )
+{
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadobjects.h b/ogr/ogrsf_frmts/cad/libopencad/cadobjects.h
new file mode 100644
index 0000000..0af770d
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadobjects.h
@@ -0,0 +1,1349 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+
+#ifndef CADOBJECTS_H
+#define CADOBJECTS_H
+
+#include "cadheader.h"
+
+/*
+ * @brief Class which basically implements implements 3D vertex
+ */
+class CADVector
+{
+public:
+    CADVector();
+    CADVector( double dx, double dy );
+    CADVector( double dx, double dy, double dz );
+    CADVector( const CADVector& other );
+    bool      operator==( const CADVector& second );
+    CADVector& operator=( const CADVector& second );
+    double getX() const;
+    void   setX( double value );
+
+    double getY() const;
+    void   setY( double value );
+
+    double getZ() const;
+    void   setZ( double value );
+
+    bool getBHasZ() const;
+    void setBHasZ( bool value );
+
+protected:
+    inline static bool fcmp( double x, double y );
+protected:
+    double X;
+    double Y;
+    double Z;
+    bool   bHasZ;
+};
+
+typedef struct _Eed
+{
+    short                 dLength = 0;
+    CADHandle             hApplication;
+    std::vector<unsigned char> acData;
+} CADEed;
+
+typedef std::vector<CADHandle> CADHandleArray;
+typedef std::vector<CADEed>    CADEedArray;
+
+/**
+ * @brief The base CAD object class
+ */
+class CADObject
+{
+public:
+    enum ObjectType
+    {
+        UNUSED               = 0x0,  // 0
+        TEXT                 = 0x1,  // 1
+        ATTRIB               = 0x2,  // 2
+        ATTDEF               = 0x3,  // 3
+        BLOCK                = 0x4,  // 4
+        ENDBLK               = 0x5,  // 5
+        SEQEND               = 0x6,  // 6
+        INSERT               = 0x7,  // 7
+        MINSERT1             = 0x8,  // 8
+        MINSERT2             = 0x9,  // 9
+        VERTEX2D             = 0x0A, // 10
+        VERTEX3D             = 0x0B, // 11
+        VERTEX_MESH          = 0x0C, // 12
+        VERTEX_PFACE         = 0x0D, // 13
+        VERTEX_PFACE_FACE    = 0x0E, // 14
+        POLYLINE2D           = 0x0F, // 15
+        POLYLINE3D           = 0x10, // 16
+        ARC                  = 0x11, // 17
+        CIRCLE               = 0x12, // 18
+        LINE                 = 0x13, // 19
+        DIMENSION_ORDINATE   = 0x14, // 20
+        DIMENSION_LINEAR     = 0x15, // 21
+        DIMENSION_ALIGNED    = 0x16, // 22
+        DIMENSION_ANG_3PT    = 0x17, // 23
+        DIMENSION_ANG_2LN    = 0x18, // 24
+        DIMENSION_RADIUS     = 0x19, // 25
+        DIMENSION_DIAMETER   = 0x1A, // 26
+        POINT                = 0x1B, // 27
+        FACE3D               = 0x1C, // 28
+        POLYLINE_PFACE       = 0x1D, // 29
+        POLYLINE_MESH        = 0x1E, // 30
+        SOLID                = 0x1F, // 31
+        TRACE                = 0x20, // 32
+        SHAPE                = 0x21, // 33
+        VIEWPORT             = 0x22, // 34
+        ELLIPSE              = 0x23, // 35
+        SPLINE               = 0x24, // 36
+        REGION               = 0x25, // 37
+        SOLID3D              = 0x26, // 38
+        BODY                 = 0x27, // 39
+        RAY                  = 0x28, // 40
+        XLINE                = 0x29, // 41
+        DICTIONARY           = 0x2A, // 42
+        OLEFRAME             = 0x2B, // 43
+        MTEXT                = 0x2C, // 44
+        LEADER               = 0x2D, // 45
+        TOLERANCE            = 0x2E, // 46
+        MLINE                = 0x2F, // 47
+        BLOCK_CONTROL_OBJ    = 0x30, // 48
+        BLOCK_HEADER         = 0x31, // 49
+        LAYER_CONTROL_OBJ    = 0x32, // 50
+        LAYER                = 0x33, // 51
+        STYLE_CONTROL_OBJ    = 0x34, // 52
+        STYLE1               = 0x35, // 53
+        STYLE2               = 0x36, // 54
+        STYLE3               = 0x37, // 55
+        LTYPE_CONTROL_OBJ    = 0x38, // 56
+        LTYPE1               = 0x39, // 57
+        LTYPE2               = 0x3A, // 58
+        LTYPE3               = 0x3B, // 59
+        VIEW_CONTROL_OBJ     = 0x3C, // 60
+        VIEW                 = 0x3D, // 61
+        UCS_CONTROL_OBJ      = 0x3E, // 62
+        UCS                  = 0x3F, // 63
+        VPORT_CONTROL_OBJ    = 0x40, // 64
+        VPORT                = 0x41, // 65
+        APPID_CONTROL_OBJ    = 0x42, // 66
+        APPID                = 0x43, // 67
+        DIMSTYLE_CONTROL_OBJ = 0x44, // 68
+        DIMSTYLE             = 0x45, // 69
+        VP_ENT_HDR_CTRL_OBJ  = 0x46, // 70
+        VP_ENT_HDR           = 0x47, // 71
+        GROUP                = 0x48, // 72
+        MLINESTYLE           = 0x49, // 73
+        OLE2FRAME            = 0x4A, // 74
+        DUMMY                = 0x4B, // 75
+        LONG_TRANSACTION     = 0x4C, // 76
+        LWPOLYLINE           = 0x4D, // 77
+        HATCH                = 0x4E, // 78
+        XRECORD              = 0x4F, // 79
+        ACDBPLACEHOLDER      = 0x50, // 80
+        VBA_PROJECT          = 0x51, // 81
+        LAYOUT               = 0x52, // 82
+        // Codes below aren't fixed, libopencad uses it for reading, in writing it will be different!
+        CELLSTYLEMAP         = 0x53, // 83
+        DBCOLOR              = 0x54, // 84
+        DICTIONARYVAR        = 0x55, // 85
+        DICTIONARYWDFLT      = 0x56, // 86
+        FIELD                = 0x57, // 87
+        GROUP_UNFIXED        = 0x58, // 88
+        HATCH_UNFIXED        = 0x59, // 89
+        IDBUFFER             = 0x5A, // 90
+        IMAGE                = 0x5B, // 91
+        IMAGEDEF             = 0x5C, // 92
+        IMAGEDEFREACTOR      = 0x5D, // 93
+        LAYER_INDEX          = 0x5E, // 94
+        LAYOUT_UNFIXED       = 0x5F, // 95
+        LWPOLYLINE_UNFIXED   = 0x60, // 96
+        MATERIAL             = 0x61, // 97
+        MLEADER              = 0x62, // 98
+        MLEADERSTYLE         = 0x63, // 99
+        OLE2FRAME_UNFIXED    = 0x64, // 100
+        PLACEHOLDER          = 0x65, // 101
+        PLOTSETTINGS         = 0x66, // 102
+        RASTERVARIABLES      = 0x67, // 103
+        SCALE                = 0x68, // 104
+        SORTENTSTABLE        = 0x69, // 105
+        SPATIAL_FILTER       = 0x6A, // 106
+        SPATIAL_INDEX        = 0x6B, // 107
+        TABLEGEOMETRY        = 0x6C, // 108
+        TABLESTYLES          = 0x6D, // 109
+        VBA_PROJECT_UNFIXED  = 0x6E, // 110
+        VISUALSTYLE          = 0x6F, // 111
+        WIPEOUTVARIABLE      = 0x70, // 112
+        XRECORD_UNFIXED      = 0x71, // 113
+        WIPEOUT              = 0x72  // 114
+    };
+
+    virtual ~CADObject(){}
+
+    ObjectType getType() const;
+    long       getSize() const;
+
+    void setSize( long value );
+
+    short getCRC() const;
+    void  setCRC(unsigned short value );
+
+protected:
+    long       size;
+    ObjectType type;
+    unsigned short CRC;
+
+        explicit CADObject(ObjectType typeIn) : size(0), type(typeIn), CRC(0) {}
+};
+
+std::string getNameByType( CADObject::ObjectType eType );
+bool   isCommonEntityType( short nType );
+bool   isSupportedGeometryType( short nType );
+
+/**
+ * @brief The CADCommonED struct
+ */
+struct CADCommonED
+{
+    long        nObjectSizeInBits;
+    CADHandle   hObjectHandle;
+    CADEedArray aEED;
+
+    bool         bGraphicsPresented;
+    std::vector<char> abyGraphicsData;
+
+    unsigned char bbEntMode;
+    long          nNumReactors;
+
+    bool bNoXDictionaryHandlePresent;
+    bool bBinaryDataPresent;
+
+    bool bIsByLayerLT; // R13-14 only
+
+    bool  bNoLinks;
+    short nCMColor;
+
+    double        dfLTypeScale;
+    unsigned char bbLTypeFlags;
+    unsigned char bbPlotStyleFlags;
+    char          bbMaterialFlags;
+    char          nShadowFlags;
+
+    short         nInvisibility;
+    unsigned char nLineWeight;
+
+    CADCommonED() :
+        nObjectSizeInBits(0),
+        bGraphicsPresented(false),
+        bbEntMode(0),
+        nNumReactors(0),
+        bNoXDictionaryHandlePresent(false),
+        bBinaryDataPresent(false),
+        bIsByLayerLT(false),
+        bNoLinks(false),
+        nCMColor(0),
+        dfLTypeScale(0.0),
+        bbLTypeFlags(0),
+        bbPlotStyleFlags(0),
+        bbMaterialFlags(0),
+        nShadowFlags(0),
+        nInvisibility(0),
+        nLineWeight(0)
+    {
+    }
+};
+
+/**
+ * @brief The CADCommonEHD struct
+ */
+struct CADCommonEHD
+{
+    CADHandle      hOwner; // depends on entmode.
+    CADHandleArray hReactors;
+    CADHandle      hXDictionary;
+    CADHandle      hLayer;
+    CADHandle      hLType;
+
+    CADHandle hPrevEntity;
+    CADHandle hNextEntity;
+
+    CADHandle hColorBookHandle;
+
+    CADHandle hMaterial;
+    CADHandle hPlotStyle;
+
+    CADHandle hFullVisualStyle;
+    CADHandle hFaceVisualStyle;
+    CADHandle hEdgeVisualStyle;
+};
+
+/*
+ * @brief The abstract class, which contains data common to all entities
+ */
+class CADEntityObject : public CADObject
+{
+public:
+    explicit CADEntityObject(ObjectType typeIn): CADObject(typeIn) {}
+
+    virtual ~CADEntityObject(){}
+    struct CADCommonED  stCed;
+    struct CADCommonEHD stChed;
+};
+
+/**
+ * @brief The CAD Text Object class
+ */
+class CADTextObject : public CADEntityObject
+{
+public:
+    CADTextObject();
+    virtual ~CADTextObject(){}
+    unsigned char DataFlags;
+    double        dfElevation;
+    CADVector     vertInsetionPoint;
+    CADVector     vertAlignmentPoint;
+    CADVector     vectExtrusion;
+    double        dfThickness;
+    double        dfObliqueAng;
+    double        dfRotationAng;
+    double        dfHeight;
+    double        dfWidthFactor;
+    std::string   sTextValue;
+    short         dGeneration;
+    short         dHorizAlign;
+    short         dVertAlign;
+
+    CADHandle hStyle;
+};
+
+/**
+ * @brief The CAD Attribute Object class
+ */
+class CADAttribObject : public CADEntityObject
+{
+public:
+    explicit CADAttribObject( ObjectType typeIn = ATTRIB );
+    virtual ~CADAttribObject(){}
+    unsigned char DataFlags;
+    double        dfElevation;
+    CADVector     vertInsetionPoint;
+    CADVector     vertAlignmentPoint;
+    CADVector     vectExtrusion;
+    double        dfThickness;
+    double        dfObliqueAng;
+    double        dfRotationAng;
+    double        dfHeight;
+    double        dfWidthFactor;
+    std::string   sTextValue;
+    short         dGeneration;
+    short         dHorizAlign;
+    short         dVertAlign;
+    char          dVersion; // R2010+
+    std::string   sTag;
+    short         nFieldLength;
+    unsigned char nFlags;
+    bool          bLockPosition;
+
+    CADHandle hStyle;
+};
+
+/**
+ * @brief The CAD Attribute definition Object class
+ */
+class CADAttdefObject : public CADAttribObject
+{
+public:
+    CADAttdefObject();
+    virtual ~CADAttdefObject(){}
+    std::string sPrompt;
+};
+
+/**
+ * @brief The CAD Block Object class
+ */
+class CADBlockObject : public CADEntityObject
+{
+public:
+    CADBlockObject();
+    virtual ~CADBlockObject(){}
+    std::string sBlockName;
+};
+
+/**
+ * @brief The CAD End block Object class
+ */
+//TODO: do we need this class? Maybe CADEntityObject enouth?
+class CADEndblkObject : public CADEntityObject
+{
+public:
+    CADEndblkObject();
+    virtual ~CADEndblkObject(){}
+    // it actually has nothing more thatn CED and CEHD.
+};
+
+/**
+ * @brief The CADSeqendObject class
+ */
+//TODO: do we need this class? Maybe CADEntityObject enouth?
+class CADSeqendObject : public CADEntityObject
+{
+public:
+    CADSeqendObject();
+    virtual ~CADSeqendObject(){}
+    // it actually has nothing more thatn CED and CEHD.
+};
+
+/**
+ * @brief The CADInsertObject class
+ */
+class CADInsertObject : public CADEntityObject
+{
+public:
+    explicit CADInsertObject( ObjectType typeIn = INSERT );
+    virtual ~CADInsertObject(){}
+    CADVector vertInsertionPoint;
+    CADVector vertScales;
+    double    dfRotation;
+    CADVector vectExtrusion;
+    bool      bHasAttribs;
+    long      nObjectsOwned;
+
+    CADHandle      hBlockHeader;
+    CADHandleArray hAttribs;
+    CADHandle      hSeqend; // if bHasAttribs == true
+};
+
+/**
+ * @brief The CADMInsertObject class
+ */
+class CADMInsertObject : public CADEntityObject
+{
+public:
+    CADMInsertObject();
+    virtual ~CADMInsertObject(){}
+    CADVector vertInsertionPoint;
+    CADVector vertScales;
+    double    dfRotation;
+    CADVector vectExtrusion;
+    bool      bHasAttribs;
+    long      nObjectsOwned;
+
+    short nNumCols;
+    short nNumRows;
+    short nColSpacing;
+    short nRowSpacing;
+
+    CADHandle      hBlockHeader;
+    CADHandleArray hAtrribs;
+    CADHandle      hSeqend; // if bHasAttribs == true
+};
+
+/**
+ * @brief The CADVertex2DObject class
+ */
+class CADVertex2DObject : public CADEntityObject
+{
+public:
+    CADVertex2DObject();
+    virtual ~CADVertex2DObject(){}
+    CADVector vertPosition; // Z must be taken from 2d polyline elevation.
+    double    dfStartWidth;
+    double    dfEndWidth;
+    double    dfBulge;
+    long      nVertexID;
+    double    dfTangentDir;
+
+/* NOTES: Neither elevation nor thickness are present in the 2D VERTEX data.
+ * Both should be taken from the 2D POLYLINE entity (15)
+ */
+};
+
+/**
+ * @brief The CADVertex3DObject class
+ */
+// TODO: do we need so many identical classes. Maybe CADVector(enum ObjectType eType)
+// for all cases?
+class CADVertex3DObject : public CADEntityObject
+{
+public:
+    CADVertex3DObject();
+    virtual ~CADVertex3DObject(){}
+    CADVector vertPosition;
+};
+
+/**
+ * @brief The CADVertexMesh class
+ */
+class CADVertexMeshObject : public CADEntityObject
+{
+public:
+    CADVertexMeshObject();
+    virtual ~CADVertexMeshObject(){}
+    CADVector vertPosition;
+};
+
+/**
+ * @brief The CADVertexPFaceObject class
+ */
+class CADVertexPFaceObject : public CADEntityObject
+{
+public:
+    CADVertexPFaceObject();
+    virtual ~CADVertexPFaceObject(){}
+    CADVector vertPosition;
+};
+
+/**
+ * @brief The CADVertexPFaceFaceObject class
+ */
+class CADVertexPFaceFaceObject : public CADEntityObject
+{
+public:
+    CADVertexPFaceFaceObject();
+    virtual ~CADVertexPFaceFaceObject(){}
+    // TODO: check DXF ref to get info what does it mean.
+    short iVertexIndex1;
+    short iVertexIndex2;
+    short iVertexIndex3;
+    short iVertexIndex4;
+};
+
+/**
+ * @brief The CADPolyline2DObject class
+ */
+class CADPolyline2DObject : public CADEntityObject
+{
+public:
+    CADPolyline2DObject();
+    virtual ~CADPolyline2DObject(){}
+    short     dFlags;
+    short     dCurveNSmoothSurfType;
+    double    dfStartWidth;
+    double    dfEndWidth;
+    double    dfThickness;
+    double    dfElevation;
+    CADVector vectExtrusion;
+
+    long nObjectsOwned;
+
+    CADHandleArray hVertexes; // content really depends on DWG version.
+
+    CADHandle hSeqend;
+};
+
+/**
+ * @brief The CADPolyline3DObject class
+ */
+class CADPolyline3DObject : public CADEntityObject
+{
+public:
+    CADPolyline3DObject();
+    virtual ~CADPolyline3DObject(){}
+    unsigned char SplinedFlags;
+    unsigned char ClosedFlags;
+
+    long nObjectsOwned;
+
+    CADHandleArray hVertexes; // content really depends on DWG version.
+
+    CADHandle hSeqend;
+};
+
+/**
+ * @brief The CADArc class
+ */
+class CADArcObject : public CADEntityObject
+{
+public:
+    CADArcObject();
+    virtual ~CADArcObject(){}
+    CADVector vertPosition;
+    double    dfRadius;
+    double    dfThickness;
+    CADVector vectExtrusion;
+    double    dfStartAngle;
+    double    dfEndAngle;
+};
+
+/**
+ * @brief The CADCircleObject class
+ */
+class CADCircleObject : public CADEntityObject
+{
+public:
+    CADCircleObject();
+    virtual ~CADCircleObject(){}
+    CADVector vertPosition;
+    double    dfRadius;
+    double    dfThickness;
+    CADVector vectExtrusion;
+};
+
+/**
+ * @brief The CADLineObject class
+ */
+class CADLineObject : public CADEntityObject
+{
+public:
+    CADLineObject();
+    virtual ~CADLineObject(){}
+    CADVector vertStart;
+    CADVector vertEnd;
+    double    dfThickness;
+    CADVector vectExtrusion;
+};
+
+/**
+ * @brief The CADBlockControlObject class
+ */
+class CADBlockControlObject : public CADObject
+{
+public:
+    CADBlockControlObject();
+    virtual ~CADBlockControlObject(){}
+    long           nObjectSizeInBits;
+    CADHandle      hObjectHandle;
+    CADEedArray    aEED;
+    long           nNumReactors;
+    bool           bNoXDictionaryPresent;
+    long           nNumEntries; // doesn't count MODELSPACE and PAPERSPACE
+    CADHandle      hNull;
+    CADHandle      hXDictionary;
+    CADHandleArray hBlocks; // ends with modelspace and paperspace handles.
+};
+
+/**
+ * @brief The CADBlockHeaderObject class
+ */
+class CADBlockHeaderObject : public CADObject
+{
+public:
+    CADBlockHeaderObject();
+    virtual ~CADBlockHeaderObject(){}
+    long                  nObjectSizeInBits;
+    CADHandle             hObjectHandle;
+    CADEedArray           aEED;
+    long                  nNumReactors;
+    bool                  bNoXDictionaryPresent;
+    std::string           sEntryName;
+    bool                  b64Flag;
+    short                 dXRefIndex;
+    bool                  bXDep;
+    bool                  bAnonymous;
+    bool                  bHasAtts;
+    bool                  bBlkisXRef;
+    bool                  bXRefOverlaid;
+    bool                  bLoadedBit;
+    long                  nOwnedObjectsCount;
+    CADVector             vertBasePoint;
+    std::string           sXRefPName;
+    std::vector<unsigned char> adInsertCount; // TODO: ???
+    std::string           sBlockDescription;
+    long                  nSizeOfPreviewData;
+    std::vector<unsigned char> abyBinaryPreviewData;
+    short                 nInsertUnits;
+    bool                  bExplodable;
+    char                  dBlockScaling;
+    CADHandle             hBlockControl;
+    std::vector<CADHandle> hReactors;
+    CADHandle             hXDictionary;
+    CADHandle             hNull;
+    CADHandle             hBlockEntity;
+    CADHandleArray        hEntities;
+    CADHandle             hEndBlk;
+    CADHandleArray        hInsertHandles;
+    CADHandle             hLayout;
+};
+
+/**
+ * @brief The CADLayerControlObject class
+ */
+class CADLayerControlObject : public CADObject
+{
+public:
+    CADLayerControlObject();
+    virtual ~CADLayerControlObject(){}
+
+    long           nObjectSizeInBits;
+    CADHandle      hObjectHandle;
+    CADEedArray    aEED;
+    long           nNumReactors;
+    bool           bNoXDictionaryPresent;
+    long           nNumEntries; // counts layer "0"
+    CADHandle      hNull;
+    CADHandle      hXDictionary;
+    CADHandleArray hLayers;
+};
+
+/**
+ * @brief The CADLayerObject class
+ */
+class CADLayerObject : public CADObject
+{
+public:
+    CADLayerObject();
+    virtual ~CADLayerObject(){}
+
+    long        nObjectSizeInBits;
+    CADHandle   hObjectHandle;
+    CADEedArray aEED;
+    long        nNumReactors;
+    bool        bNoXDictionaryPresent;
+    std::string sLayerName;
+    bool        b64Flag;
+    short       dXRefIndex;
+    bool        bXDep;
+    bool        bFrozen;
+    bool        bOn;
+    bool        bFrozenInNewVPORT;
+    bool        bLocked;
+    bool        bPlottingFlag;
+    short       dLineWeight;
+    short       dCMColor;
+
+    CADHandle      hLayerControl;
+    CADHandleArray hReactors;
+    CADHandle      hXDictionary;
+    CADHandle      hExternalRefBlockHandle;
+    CADHandle      hPlotStyle;
+    CADHandle      hMaterial;
+    CADHandle      hLType;
+    CADHandle      hUnknownHandle;
+};
+
+/**
+ * @brief The CADLineTypeControlObject class
+ */
+class CADLineTypeControlObject : public CADObject
+{
+public:
+    CADLineTypeControlObject();
+    virtual ~CADLineTypeControlObject(){}
+
+    long           nObjectSizeInBits;
+    CADHandle      hObjectHandle;
+    CADEedArray    aEED;
+    long           nNumReactors;
+    bool           bNoXDictionaryPresent;
+    long           nNumEntries; // doesn't count BYBLOCK / BYLAYER.
+    CADHandle      hNull;
+    CADHandle      hXDictionary;
+    CADHandleArray hLTypes;
+};
+
+typedef struct _dash
+{
+    double dfLength;
+    short  dComplexShapecode;
+    double dfXOffset;
+    double dfYOffset;
+    double dfScale;
+    double dfRotation;
+    short  dShapeflag;
+} CADDash;
+
+/**
+ * @brief The CADLineTypeObject class
+ */
+class CADLineTypeObject : public CADObject
+{
+public:
+    CADLineTypeObject();
+    virtual ~CADLineTypeObject(){}
+
+    long                  nObjectSizeInBits;
+    CADHandle             hObjectHandle;
+    CADEedArray           aEED;
+    long                  nNumReactors;
+    bool                  bNoXDictionaryPresent;
+    std::string           sEntryName;
+    bool                  b64Flag;
+    short                 dXRefIndex;
+    bool                  bXDep;
+    std::string           sDescription;
+    double                dfPatternLen;
+    unsigned char         dAlignment;
+    unsigned char         nNumDashes;
+    std::vector<CADDash>  astDashes;
+    std::vector<unsigned char> abyTextArea; // TODO: what is it?
+    CADHandle             hLTControl;
+    CADHandleArray        hReactors;
+    CADHandle             hXDictionary;
+    CADHandle             hXRefBlock;
+    CADHandleArray        hShapefiles; // TODO: one for each dash?
+};
+
+/**
+ * @brief The CADPointObject class
+ */
+class CADPointObject : public CADEntityObject
+{
+public:
+    CADPointObject();
+    virtual ~CADPointObject(){}
+
+    CADVector vertPosition;
+    double    dfThickness;
+    CADVector vectExtrusion;
+    double    dfXAxisAng;
+};
+
+/**
+ * @brief The CADSolidObject class
+ */
+class CADSolidObject : public CADEntityObject
+{
+public:
+    CADSolidObject();
+    virtual ~CADSolidObject(){}
+
+    double            dfThickness;
+    double            dfElevation;
+    std::vector<CADVector> avertCorners;
+    CADVector         vectExtrusion;
+};
+
+/**
+ * @brief The CADEllipseObject class
+ */
+class CADEllipseObject : public CADEntityObject
+{
+public:
+    CADEllipseObject();
+    virtual ~CADEllipseObject(){}
+
+    CADVector vertPosition;
+    CADVector vectSMAxis;
+    CADVector vectExtrusion;
+    double    dfAxisRatio;
+    double    dfBegAngle;
+    double    dfEndAngle;
+};
+
+/**
+ * @brief The CADRayObject class
+ */
+class CADRayObject : public CADEntityObject
+{
+public:
+    CADRayObject();
+    virtual ~CADRayObject(){}
+
+    CADVector vertPosition;
+    CADVector vectVector;
+};
+
+/**
+ * @brief The CADXLineObject class
+ */
+class CADXLineObject : public CADEntityObject
+{
+public:
+    CADXLineObject();
+    virtual ~CADXLineObject(){}
+
+    CADVector vertPosition;
+    CADVector vectVector;
+};
+
+/**
+ * @brief The CADDictionaryObject class
+ */
+class CADDictionaryObject : public CADObject
+{
+public:
+    CADDictionaryObject();
+    virtual ~CADDictionaryObject(){}
+
+    long          nObjectSizeInBits;
+    CADHandle     hObjectHandle;
+    CADEedArray   aEED;
+    long          nNumReactors;
+    bool          bNoXDictionaryPresent;
+    long          nNumItems;
+    short         dCloningFlag;
+    unsigned char dHardOwnerFlag;
+
+    std::vector<std::string> sItemNames;
+
+    CADHandle      hParentHandle;
+    CADHandleArray hReactors;
+    CADHandle      hXDictionary;
+    CADHandleArray hItemHandles;
+};
+
+/**
+ * @brief The CADLWPolylineObject class
+ */
+class CADLWPolylineObject : public CADEntityObject
+{
+public:
+    CADLWPolylineObject();
+    virtual ~CADLWPolylineObject(){}
+
+    bool                         bClosed;
+    double                       dfConstWidth;
+    double                       dfElevation;
+    double                       dfThickness;
+    CADVector                    vectExtrusion;
+    std::vector<CADVector>            avertVertexes;
+    std::vector<double>               adfBulges;
+    std::vector<short>                adVertexesID;
+    std::vector<std::pair<double, double>> astWidths; // start, end.
+};
+
+/**
+ * @brief The CADSplineObject class
+ */
+class CADSplineObject : public CADEntityObject
+{
+public:
+    CADSplineObject();
+    virtual ~CADSplineObject(){}
+
+    long dScenario;
+    long dSplineFlags; // 2013+
+    long dKnotParameter; // 2013+
+
+    long      dDegree;
+    double    dfFitTol;
+    CADVector vectBegTangDir;
+    CADVector vectEndTangDir;
+    long      nNumFitPts;
+
+    bool   bRational;
+    bool   bClosed;
+    bool   bPeriodic;
+    double dfKnotTol;
+    double dfCtrlTol;
+    long   nNumKnots;
+    long   nNumCtrlPts;
+    bool   bWeight;
+
+    std::vector<double>    adfKnots;
+    std::vector<double>    adfCtrlPointsWeight;
+    std::vector<CADVector> avertCtrlPoints;
+    std::vector<CADVector> averFitPoints;
+};
+
+/**
+ * @brief Common Dimensional Data structure
+ */
+struct CADCommonDimensionData
+{
+    char          dVersion;
+    CADVector     vectExtrusion;
+    CADVector     vertTextMidPt;
+    double        dfElevation;
+    unsigned char dFlags;
+    std::string   sUserText;
+    double        dfTextRotation;
+    double        dfHorizDir;
+    double        dfInsXScale;
+    double        dfInsYScale;
+    double        dfInsZScale;
+    double        dfInsRotation;
+
+    short  dAttachmentPoint;
+    short  dLineSpacingStyle;
+    double dfLineSpacingFactor;
+    double dfActualMeasurement;
+
+    bool bUnknown;
+    bool bFlipArrow1;
+    bool bFlipArrow2;
+
+    CADVector vert12Pt;
+
+    CADCommonDimensionData() :
+        dVersion(0),
+        dfElevation(0.0),
+        dFlags(0),
+        dfTextRotation(0.0),
+        dfHorizDir(0.0),
+        dfInsXScale(0.0),
+        dfInsYScale(0.0),
+        dfInsZScale(0.0),
+        dfInsRotation(0.0),
+        dAttachmentPoint(0),
+        dLineSpacingStyle(0),
+        dfLineSpacingFactor(0.0),
+        dfActualMeasurement(0.0),
+        bUnknown(false),
+        bFlipArrow1(false),
+        bFlipArrow2(false)
+    {
+    }
+};
+
+/**
+ * @brief The CADDimensionObject class
+ */
+class CADDimensionObject : public CADEntityObject
+{
+public:
+    explicit CADDimensionObject( ObjectType typeIn ) : CADEntityObject(typeIn) {}
+    virtual ~CADDimensionObject(){}
+    CADCommonDimensionData cdd;
+    CADVector              vert10pt;
+    CADHandle              hDimstyle;
+    CADHandle              hAnonymousBlock;
+};
+
+/**
+ * @brief The CADDimensionOrdinateObject class
+ */
+class CADDimensionOrdinateObject : public CADDimensionObject
+{
+public:
+    CADDimensionOrdinateObject();
+    virtual ~CADDimensionOrdinateObject(){}
+    CADVector     vert13pt, vert14pt;
+    unsigned char Flags2;
+};
+
+/**
+ * @brief The CADDimensionLinearObject class
+ */
+class CADDimensionLinearObject : public CADDimensionObject
+{
+public:
+    CADDimensionLinearObject();
+    virtual ~CADDimensionLinearObject(){}
+    CADVector vert13pt, vert14pt;
+
+    double dfExtLnRot;
+    double dfDimRot;
+};
+
+/**
+ * @brief The CADDimensionAlignedObject class
+ */
+class CADDimensionAlignedObject : public CADDimensionObject
+{
+public:
+    CADDimensionAlignedObject();
+    virtual ~CADDimensionAlignedObject(){}
+    CADVector vert13pt, vert14pt;
+
+    double dfExtLnRot;
+};
+
+/**
+ * @brief The CADDimensionAngular3PtObject class
+ */
+class CADDimensionAngular3PtObject : public CADDimensionObject
+{
+public:
+    explicit CADDimensionAngular3PtObject(ObjectType typeIn = DIMENSION_ANG_3PT);
+    virtual ~CADDimensionAngular3PtObject(){}
+    CADVector vert13pt, vert14pt;
+    CADVector vert15pt;
+};
+
+/**
+ * @brief The CADDimensionAngular2LnObject class
+ */
+class CADDimensionAngular2LnObject : public CADDimensionAngular3PtObject
+{
+public:
+    CADDimensionAngular2LnObject();
+    virtual ~CADDimensionAngular2LnObject(){}
+
+    CADVector vert16pt;
+};
+
+/**
+ * @brief The CADDimensionRadiusObject class
+ */
+class CADDimensionRadiusObject : public CADDimensionObject
+{
+public:
+    explicit CADDimensionRadiusObject(ObjectType typeIn = DIMENSION_RADIUS);
+    virtual ~CADDimensionRadiusObject(){}
+
+    CADVector vert15pt;
+    double    dfLeaderLen;
+};
+
+/**
+ * @brief The CADDimensionDiameterObject class
+ */
+class CADDimensionDiameterObject : public CADDimensionRadiusObject
+{
+public:
+    CADDimensionDiameterObject();
+    virtual ~CADDimensionDiameterObject(){}
+};
+
+/**
+ * @brief The CADImageObject class
+ */
+class CADImageObject : public CADEntityObject
+{
+public:
+    CADImageObject();
+    virtual ~CADImageObject(){}
+
+    long      dClassVersion;
+    CADVector vertInsertion;
+    CADVector vectUDirection;
+    CADVector vectVDirection;
+    double    dfSizeX;
+    double    dfSizeY;
+    /*  display properties (bit coded), 1==show image,
+        2==show image when not aligned with screen, 4==use
+        clipping boundary, 8==transparency on */
+    short     dDisplayProps;
+
+    bool          bClipping;
+    unsigned char dBrightness;
+    unsigned char dContrast;
+    unsigned char dFade;
+    bool          bClipMode; // R2010+
+
+    short dClipBoundaryType;
+
+    long              nNumberVertexesInClipPolygon;
+    std::vector<CADVector> avertClippingPolygonVertexes;
+
+    CADHandle hImageDef;
+    CADHandle hImageDefReactor;
+};
+
+/**
+ * @brief The CADImageDefReactorObject class
+ */
+class CADImageDefReactorObject : public CADObject
+{
+public:
+    explicit CADImageDefReactorObject(ObjectType typeIn = IMAGEDEFREACTOR);
+    virtual ~CADImageDefReactorObject(){}
+
+    long              nObjectSizeInBits;
+    CADHandle         hObjectHandle;
+    std::vector<CADEed>    aEED;
+    long              nNumReactors;
+    bool              bNoXDictionaryPresent;
+    long              dClassVersion;
+    CADHandle         hParentHandle;
+    std::vector<CADHandle> hReactors;
+    CADHandle         hXDictionary;
+};
+
+/**
+ * @brief The CADImageDefObject class
+ */
+class CADImageDefObject : public CADImageDefReactorObject
+{
+public:
+    CADImageDefObject();
+    virtual ~CADImageDefObject(){}
+
+    double        dfXImageSizeInPx;
+    double        dfYImageSizeInPx;
+    std::string   sFilePath;
+    bool          bIsLoaded;
+    unsigned char dResUnits; // 0 == none, 2 == centimeters, 5 == inches
+    double        dfXPixelSize; // size of 1 pixel in autocad units
+    double        dfYPixelSize;
+};
+
+/**
+ * @brief The CADMTextObject class
+ */
+class CADMTextObject : public CADEntityObject
+{
+public:
+    CADMTextObject();
+    virtual ~CADMTextObject(){}
+
+    CADVector vertInsertionPoint;
+    CADVector vectExtrusion;
+    CADVector vectXAxisDir;
+    double    dfRectWidth;
+    double    dfTextHeight;
+    short     dAttachment; // TODO: meaning unknown
+    short     dDrawingDir;
+    double    dfExtents; // TODO: meaning unknown
+    double    dfExtentsWidth; // TODO: meaning unknown
+    std::string sTextValue;
+    short     dLineSpacingStyle;
+    double    dLineSpacingFactor;
+    bool      bUnknownBit;
+    long      dBackgroundFlags;
+    long      dBackgroundScaleFactor;
+    short     dBackgroundColor;
+    long      dBackgroundTransparency;
+    CADHandle hStyle;
+};
+
+/**
+ * @brief Linestyle data structure
+ */
+typedef struct _linestyle
+{
+    short          nNumSegParms;
+    std::vector<double> adfSegparms;
+    short          nAreaFillParms;
+    std::vector<double> adfAreaFillParameters;
+} CADLineStyle;
+
+/**
+ * @brief MLine vertex data structure
+ */
+typedef struct _mlinevertex
+{
+    CADVector            vertPosition;
+    CADVector            vectDirection;
+    CADVector            vectMIterDirection;
+    std::vector<CADLineStyle> astLStyles;
+} CADMLineVertex;
+
+/**
+ * @brief The CADMLineObject class
+ */
+class CADMLineObject : public CADEntityObject
+{
+public:
+    CADMLineObject();
+    virtual ~CADMLineObject(){}
+
+    double        dfScale;
+    unsigned char dJust;
+    CADVector     vertBasePoint;
+    CADVector     vectExtrusion;
+    short         dOpenClosed; // 1 open, 3 closed
+    unsigned char nLinesInStyle;
+    short         nNumVertexes;
+
+    std::vector<CADMLineVertex> avertVertexes;
+
+    CADHandle hMLineStyle;
+};
+
+/**
+ * @brief The CAD3DFaceObject class
+ */
+class CAD3DFaceObject : public CADEntityObject
+{
+public:
+    CAD3DFaceObject();
+    virtual ~CAD3DFaceObject(){}
+
+    bool              bHasNoFlagInd; // 2000+
+    bool              bZZero;
+    std::vector<CADVector> avertCorners;
+    short             dInvisFlags;
+};
+
+/**
+ * @brief The CADPolylinePFaceObject class
+ */
+class CADPolylinePFaceObject : public CADEntityObject
+{
+public:
+    CADPolylinePFaceObject();
+    virtual ~CADPolylinePFaceObject(){}
+
+    short             nNumVertexes;
+    short             nNumFaces;
+    long              nObjectsOwned;
+    std::vector<CADHandle> hVertexes; // content really depends on DWG version.
+    CADHandle         hSeqend;
+};
+
+#ifdef TODO
+/**
+ * @brief The CADHatchObject class TODO: not completed
+ */
+class CADHatchObject : public CADEntityObject
+{
+public:
+    typedef struct
+    {
+        double dfUnknowndouble;
+        short  dUnknownshort;
+        long   dRGBColor;
+        char   dIgnoredColorByte;
+    } _gradient_color;
+
+    CADHatchObject();
+    virtual ~CADHatchObject(){}
+
+    long                    dIsGradientFill; // 2004+
+    long                    dReserved;
+    double                  dfGradientAngle;
+    double                  dfGradientShift;
+    long                    dSingleColorGrad;
+    double                  dfGradientTint;
+    long                    nGradientColors;
+    std::vector<_gradient_color> astGradientColors;
+
+    std::string sGradientName;
+
+    double    dfZCoord; // always X = Y = 0.0
+    CADVector vectExtrusion;
+    std::string    sHatchName;
+    bool      bSolidFill;
+    bool      bAssociative;
+    long      nNumPaths;
+
+    typedef struct
+    {
+        char      dPathTypeStatus;
+        CADVector vectPt0;
+        CADVector vectPt1;
+    } _path_segment;
+};
+#endif
+
+/**
+ * @brief The CADXRecordObject class
+ */
+class CADXRecordObject : public CADObject
+{
+public:
+    CADXRecordObject();
+    virtual ~CADXRecordObject(){}
+    long                                nObjectSizeInBits;
+    CADHandle                           hObjectHandle;
+    CADEedArray                         aEED;
+    long                                nNumReactors;
+    bool                                bNoXDictionaryPresent;
+    long                                nNumDataBytes;
+    std::vector<char>                   abyDataBytes;
+    short                               dCloningFlag;
+    std::vector<std::pair<short, std::vector<char> > > astXRecordData;
+    CADHandle                           hParentHandle;
+    std::vector<CADHandle>              hReactors;
+    CADHandle                           hXDictionary;
+    std::vector<CADHandle>              hObjIdHandles;
+};
+
+#endif //CADOBJECTS_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadtables.cpp b/ogr/ogrsf_frmts/cad/libopencad/cadtables.cpp
new file mode 100644
index 0000000..4a36e5e
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadtables.cpp
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "cadtables.h"
+#include "opencad_api.h"
+
+#include <memory>
+#include <cassert>
+#include <iostream>
+
+using namespace std;
+
+CADTables::CADTables()
+{
+}
+
+void CADTables::AddTable( TableType eType, const CADHandle& hHandle )
+{
+    mapTables[eType] = hHandle;
+}
+
+int CADTables::ReadTable( CADFile * const pCADFile, CADTables::TableType eType )
+{
+    auto iterAskedTable = mapTables.find( eType );
+    if( iterAskedTable == mapTables.end() )
+        return CADErrorCodes::TABLE_READ_FAILED;
+
+    // TODO: read different tables
+    switch( eType )
+    {
+        case LayersTable:
+            return ReadLayersTable( pCADFile, iterAskedTable->second.getAsLong() );
+        default:
+            std::cerr << "Unsupported table.";
+            break;
+    }
+
+    return CADErrorCodes::SUCCESS;
+}
+
+size_t CADTables::GetLayerCount() const
+{
+    return aLayers.size();
+}
+
+CADLayer& CADTables::GetLayer( size_t iIndex )
+{
+    return aLayers[iIndex];
+}
+
+CADHandle CADTables::GetTableHandle( enum TableType eType )
+{
+    // FIXME: need to add try/catch to prevent crashes on not found elem.
+    return mapTables[eType];
+}
+
+int CADTables::ReadLayersTable( CADFile * const pCADFile, long dLayerControlHandle )
+{
+    // Reading Layer Control obj, and aLayers.
+    unique_ptr<CADLayerControlObject> spLayerControl(
+            static_cast<CADLayerControlObject *>(pCADFile->GetObject( dLayerControlHandle )) );
+    if( spLayerControl == nullptr )
+        return CADErrorCodes::TABLE_READ_FAILED;
+
+    for( size_t i = 0; i < spLayerControl->hLayers.size(); ++i )
+    {
+        if( !spLayerControl->hLayers[i].isNull() )
+        {
+            CADLayer oCADLayer( pCADFile );
+
+            // Init CADLayer from CADLayerObject properties
+            unique_ptr<CADLayerObject> oCADLayerObj(
+                    static_cast<CADLayerObject *>(pCADFile->GetObject( spLayerControl->hLayers[i].getAsLong() )) );
+
+            oCADLayer.setName( oCADLayerObj->sLayerName );
+            oCADLayer.setFrozen( oCADLayerObj->bFrozen );
+            oCADLayer.setOn( oCADLayerObj->bOn );
+            oCADLayer.setFrozenByDefault( oCADLayerObj->bFrozenInNewVPORT );
+            oCADLayer.setLocked( oCADLayerObj->bLocked );
+            oCADLayer.setLineWeight( oCADLayerObj->dLineWeight );
+            oCADLayer.setColor( oCADLayerObj->dCMColor );
+            oCADLayer.setId( aLayers.size() + 1 );
+            oCADLayer.setHandle( oCADLayerObj->hObjectHandle.getAsLong() );
+
+            aLayers.push_back( oCADLayer );
+        }
+    }
+
+    auto iterBlockMS = mapTables.find( BlockRecordModelSpace );
+    if( iterBlockMS == mapTables.end() )
+        return CADErrorCodes::TABLE_READ_FAILED;
+
+    unique_ptr<CADBlockHeaderObject> spModelSpace(
+            static_cast<CADBlockHeaderObject *>(pCADFile->GetObject( iterBlockMS->second.getAsLong() )) );
+
+    auto dCurrentEntHandle = spModelSpace->hEntities[0].getAsLong();
+    auto dLastEntHandle    = spModelSpace->hEntities[1].getAsLong();
+    while( dCurrentEntHandle != 0 )
+    {
+        unique_ptr<CADEntityObject> spEntityObj( static_cast<CADEntityObject *>(
+                                                         pCADFile->GetObject( dCurrentEntHandle, true )) );
+
+        if( spEntityObj == nullptr )
+        {
+            DebugMsg( "Entity object is null\n" );
+            break;
+        }
+        else if ( dCurrentEntHandle == dLastEntHandle )
+        {
+            FillLayer( spEntityObj.get() );
+            break;
+        }
+
+        FillLayer( spEntityObj.get() );
+
+        if( spEntityObj->stCed.bNoLinks )
+        {
+            ++dCurrentEntHandle;
+        }
+        else
+        {
+            dCurrentEntHandle = spEntityObj->stChed.hNextEntity.getAsLong( spEntityObj->stCed.hObjectHandle );
+        }
+    }
+
+    DebugMsg( "Readed aLayers using LayerControl object count: %d\n",
+              static_cast<int>(aLayers.size()) );
+
+    return CADErrorCodes::SUCCESS;
+}
+
+void CADTables::FillLayer( const CADEntityObject * pEntityObject )
+{
+    for( CADLayer& oLayer : aLayers )
+    {
+        if( pEntityObject->stChed.hLayer.getAsLong( pEntityObject->stCed.hObjectHandle ) == oLayer.getHandle() )
+        {
+            DebugMsg( "Object with type: %s is attached to layer named: %s\n",
+                      getNameByType( pEntityObject->getType() ).c_str(), oLayer.getName().c_str() );
+
+            oLayer.addHandle( pEntityObject->stCed.hObjectHandle.getAsLong(), pEntityObject->getType() );
+            break;
+        }
+    }
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/cadtables.h b/ogr/ogrsf_frmts/cad/libopencad/cadtables.h
new file mode 100644
index 0000000..2230ed7
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/cadtables.h
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef CADTABLES_H
+#define CADTABLES_H
+
+#include "cadheader.h"
+#include "cadlayer.h"
+
+class CADFile;
+
+/**
+ * @brief The CAD tables class. Store tables
+ */
+class OCAD_EXTERN CADTables
+{
+public:
+    /**
+     * @brief The CAD table types enum
+     */
+    enum TableType
+    {
+        CurrentViewportTable,
+        BlocksTable,
+        LayersTable,
+        StyleTable,
+        LineTypesTable,
+        ViewTable,
+        UCSTable,
+        ViewportTable,
+        APPIDTable,
+        EntityTable,
+        ACADGroupDict,
+        ACADMLineStyleDict,
+        NamedObjectsDict,
+        LayoutsDict,
+        PlotSettingsDict,
+        PlotStylesDict,
+        BlockRecordPaperSpace,
+        BlockRecordModelSpace
+    };
+public:
+    CADTables();
+
+    void      AddTable( enum TableType eType, const CADHandle& hHandle );
+    CADHandle GetTableHandle( enum TableType eType );
+    int       ReadTable( CADFile * const pCADFile, enum TableType eType );
+    size_t    GetLayerCount() const;
+    CADLayer& GetLayer( size_t iIndex );
+
+protected:
+    int  ReadLayersTable( CADFile * const pCADFile, long dLayerControlHandle );
+    void FillLayer( const CADEntityObject * pEntityObject );
+protected:
+    std::map<enum TableType, CADHandle> mapTables;
+    std::vector<CADLayer>               aLayers;
+};
+
+#endif // CADTABLES_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/dwg/GNUmakefile b/ogr/ogrsf_frmts/cad/libopencad/dwg/GNUmakefile
new file mode 100644
index 0000000..c09fb81
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/dwg/GNUmakefile
@@ -0,0 +1,19 @@
+
+include ../../../../../GDALmake.opt
+
+OBJ := \
+	io.o \
+    r2000.o
+
+O_OBJ =	$(foreach file,$(OBJ),../../../o/$(file))
+
+CPPFLAGS	:=	-I. -I.. -I../.. -I../../.. $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+../../../o/%.$(OBJ_EXT):	%.cpp
+	$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+clean:
+	rm -f *.o $(O_OBJ)
+	rm -f *~
diff --git a/ogr/ogrsf_frmts/cad/libopencad/dwg/io.cpp b/ogr/ogrsf_frmts/cad/libopencad/dwg/io.cpp
new file mode 100644
index 0000000..c8d0c46
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/dwg/io.cpp
@@ -0,0 +1,899 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "io.h"
+
+#include <iostream>
+#include <cstring>
+
+const size_t DWGConstants::SentinelLength = 16;
+const char * DWGConstants::HeaderVariablesStart
+            = "\xCF\x7B\x1F\x23\xFD\xDE\x38\xA9\x5F\x7C\x68\xB8\x4E\x6D\x33\x5F";
+const char * DWGConstants::HeaderVariablesEnd
+            = "\x30\x84\xE0\xDC\x02\x21\xC7\x56\xA0\x83\x97\x47\xB1\x92\xCC\xA0";
+
+const char * DWGConstants::DSClassesStart
+                        = "\x8D\xA1\xC4\xB8\xC4\xA9\xF8\xC5\xC0\xDC\xF4\x5F\xE7\xCF\xB6\x8A";
+const char * DWGConstants::DSClassesEnd
+                        = "\x72\x5E\x3B\x47\x3B\x56\x07\x3A\x3F\x23\x0B\xA0\x18\x30\x49\x75";
+
+const int DWGCRC8Table[256] = {
+    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1,
+    0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40,
+    0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1,
+    0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1,
+    0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40,
+    0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1,
+    0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0,
+    0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,
+    0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0,
+    0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1,
+    0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140,
+    0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0,
+    0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0,
+    0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341,
+    0x4100, 0x81C1, 0x8081, 0x4040
+};
+
+unsigned short CalculateCRC8( unsigned short initialVal, const char * ptr, int num )
+{
+    unsigned char al;
+    while( num-- > 0 )
+    {
+        al = static_cast<unsigned char>( ( * ptr ) ^ ( static_cast<char> ( initialVal & 0xFF ) ) );
+        initialVal = ( initialVal >> 8 ) & 0xFF;
+        initialVal = static_cast<unsigned short>( initialVal ^ DWGCRC8Table[al & 0xFF] );
+        ptr++;
+    }
+
+    return initialVal;
+}
+
+unsigned char Read2B( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char result           = 0;
+    size_t        nByteOffset      = nBitOffsetFromStart / 8;
+    size_t        nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * p2BByte = pabyInput + nByteOffset;
+    unsigned char a2BBytes[2];
+    memcpy( a2BBytes, p2BByte, 2 );
+
+    switch( nBitOffsetInByte )
+    {
+        case 7:
+            result  = ( a2BBytes[0] & binary( 00000001 ) ) << 1;
+            result |= ( a2BBytes[1] & binary( 10000000 ) ) >> 7;
+            break;
+        default:
+            result = ( a2BBytes[0] >> ( 6 - nBitOffsetInByte ) );
+            break;
+    }
+
+    result &= binary( 00000011 );
+    nBitOffsetFromStart += 2;
+
+    return result;
+}
+
+unsigned char Read3B( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char result           = 0;
+    size_t        nByteOffset      = nBitOffsetFromStart / 8;
+    size_t        nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * p3BByte = pabyInput + nByteOffset;
+    unsigned char a3BBytes[2];
+    memcpy( a3BBytes, p3BByte, 2 );
+
+    switch( nBitOffsetInByte )
+    {
+        case 6:
+            result  = ( a3BBytes[0] & binary( 00000011 ) ) << 1;
+            result |= ( a3BBytes[1] & binary( 10000000 ) ) >> 7;
+            break;
+
+        case 7:
+            result  = ( a3BBytes[0] & binary( 00000001 ) ) << 2;
+            result |= ( a3BBytes[1] & binary( 11000000 ) ) >> 6;
+            break;
+
+        default:
+            result = ( a3BBytes[0] >> ( 5 - nBitOffsetInByte ) );
+            break;
+    }
+
+    result &= binary( 00000111 );
+    nBitOffsetFromStart += 3;
+
+    return result;
+}
+
+unsigned char Read4B( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char result           = 0;
+    size_t        nByteOffset      = nBitOffsetFromStart / 8;
+    size_t        nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * p4BByte = pabyInput + nByteOffset;
+    unsigned char a4BBytes[2];
+    memcpy( a4BBytes, p4BByte, 2 );
+
+    switch( nBitOffsetInByte )
+    {
+        case 5:
+            result  = ( a4BBytes[0] & binary( 00000111 ) ) << 1;
+            result |= ( a4BBytes[1] & binary( 10000000 ) ) >> 7;
+            break;
+        case 6:
+            result  = ( a4BBytes[0] & binary( 00000011 ) ) << 2;
+            result |= ( a4BBytes[1] & binary( 11000000 ) ) >> 6;
+            break;
+
+        case 7:
+            result  = ( a4BBytes[0] & binary( 00000001 ) ) << 3;
+            result |= ( a4BBytes[1] & binary( 11100000 ) ) >> 5;
+            break;
+
+        default:
+            result = ( a4BBytes[0] >> ( 4 - nBitOffsetInByte ) );
+            break;
+    }
+
+    result &= binary( 00001111 );
+    nBitOffsetFromStart += 4;
+
+    return result;
+}
+
+short ReadRAWSHORT( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    size_t nByteOffset      = nBitOffsetFromStart / 8;
+    size_t nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * pShortFirstByte = pabyInput + nByteOffset;
+    unsigned char aShortBytes[3];
+    memcpy( aShortBytes, pShortFirstByte, 3 );
+
+    switch( nBitOffsetInByte )
+    {
+        case 0:
+            break;
+
+        default:
+            aShortBytes[0] <<= nBitOffsetInByte;
+            aShortBytes[0] |= ( aShortBytes[1] >> ( 8 - nBitOffsetInByte ) );
+            aShortBytes[1] <<= nBitOffsetInByte;
+            aShortBytes[1] |= ( aShortBytes[2] >> ( 8 - nBitOffsetInByte ) );
+            break;
+    }
+
+    void  * ptr    = aShortBytes;
+    short * result = static_cast<short *>(ptr);
+
+    nBitOffsetFromStart += 16;
+
+    return * result;
+}
+
+double ReadRAWDOUBLE( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    size_t nByteOffset      = nBitOffsetFromStart / 8;
+    size_t nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * pDoubleFirstByte = pabyInput + nByteOffset;
+
+    unsigned char aDoubleBytes[9];
+    memcpy( aDoubleBytes, pDoubleFirstByte, 9 );
+
+    switch( nBitOffsetInByte )
+    {
+        case 0:
+            break;
+
+        default:
+            aDoubleBytes[0] <<= nBitOffsetInByte;
+            aDoubleBytes[0] |= ( aDoubleBytes[1] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[1] <<= nBitOffsetInByte;
+            aDoubleBytes[1] |= ( aDoubleBytes[2] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[2] <<= nBitOffsetInByte;
+            aDoubleBytes[2] |= ( aDoubleBytes[3] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[3] <<= nBitOffsetInByte;
+            aDoubleBytes[3] |= ( aDoubleBytes[4] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[4] <<= nBitOffsetInByte;
+            aDoubleBytes[4] |= ( aDoubleBytes[5] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[5] <<= nBitOffsetInByte;
+            aDoubleBytes[5] |= ( aDoubleBytes[6] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[6] <<= nBitOffsetInByte;
+            aDoubleBytes[6] |= ( aDoubleBytes[7] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[7] <<= nBitOffsetInByte;
+            aDoubleBytes[7] |= ( aDoubleBytes[8] >> ( 8 - nBitOffsetInByte ) );
+            break;
+    }
+
+    void   * ptr    = aDoubleBytes;
+    double * result = static_cast<double *>(ptr);
+
+    nBitOffsetFromStart += 64;
+
+    return * result;
+}
+
+int ReadRAWLONG( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    size_t nByteOffset      = nBitOffsetFromStart / 8;
+    size_t nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * pLongFirstByte = pabyInput + nByteOffset;
+
+    unsigned char aLongBytes[5];
+    memcpy( aLongBytes, pLongFirstByte, 5 );
+
+    switch( nBitOffsetInByte )
+    {
+        case 0:
+            break;
+
+        default:
+            aLongBytes[0] <<= nBitOffsetInByte;
+            aLongBytes[0] |= ( aLongBytes[1] >> ( 8 - nBitOffsetInByte ) );
+            aLongBytes[1] <<= nBitOffsetInByte;
+            aLongBytes[1] |= ( aLongBytes[2] >> ( 8 - nBitOffsetInByte ) );
+            aLongBytes[2] <<= nBitOffsetInByte;
+            aLongBytes[2] |= ( aLongBytes[3] >> ( 8 - nBitOffsetInByte ) );
+            aLongBytes[3] <<= nBitOffsetInByte;
+            aLongBytes[3] |= ( aLongBytes[4] >> ( 8 - nBitOffsetInByte ) );
+            break;
+    }
+
+    void * ptr    = aLongBytes;
+    int  * result = static_cast<int *>(ptr);
+
+    nBitOffsetFromStart += 32;
+
+    return * result;
+}
+
+bool ReadBIT( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    size_t nByteOffset      = nBitOffsetFromStart / 8;
+    size_t nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * pBoolByte = pabyInput + nByteOffset;
+
+    unsigned char resultVal = ( pBoolByte[0] >> ( 7 - nBitOffsetInByte ) ) & binary( 00000001 );
+    ++nBitOffsetFromStart;
+
+    return resultVal == 0 ? false : true;
+}
+
+short ReadBITSHORT( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char BITCODE = Read2B( pabyInput, nBitOffsetFromStart );
+
+    size_t nByteOffset      = nBitOffsetFromStart / 8;
+    size_t nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * pShortFirstByte = pabyInput + nByteOffset;
+    unsigned char aShortBytes[4]; // maximum bytes a single short can take.
+    memcpy( aShortBytes, pShortFirstByte, 4 );
+
+    switch( BITCODE )
+    {
+        case BITSHORT_NORMAL:
+        {
+            aShortBytes[0] = ( aShortBytes[0] << nBitOffsetInByte );
+            aShortBytes[0] |= ( aShortBytes[1] >> ( 8 - nBitOffsetInByte ) );
+            aShortBytes[1] = ( aShortBytes[1] << nBitOffsetInByte );
+            aShortBytes[1] |= ( aShortBytes[2] >> ( 8 - nBitOffsetInByte ) );
+
+            nBitOffsetFromStart += 16;
+
+            void  * ptr    = aShortBytes;
+            short * result = static_cast < short * > ( ptr );
+
+            return * result;
+        }
+
+        case BITSHORT_UNSIGNED_CHAR:
+        {
+            aShortBytes[0] = ( aShortBytes[0] << nBitOffsetInByte );
+            aShortBytes[0] |= ( aShortBytes[1] >> ( 8 - nBitOffsetInByte ) );
+
+            nBitOffsetFromStart += 8;
+
+            return static_cast<unsigned char>(aShortBytes[0]);
+        }
+
+        case BITSHORT_ZERO_VALUE:
+        {
+            nBitOffsetFromStart += 0;
+            return 0;
+        }
+
+        case BITSHORT_256:
+        {
+            nBitOffsetFromStart += 0;
+            return 256;
+        }
+    }
+
+    return -1;
+}
+
+unsigned char ReadCHAR( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char result           = 0;
+    size_t        nByteOffset      = nBitOffsetFromStart / 8;
+    size_t        nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * pCharFirstByte = pabyInput + nByteOffset;
+    unsigned char aCharBytes[2]; // maximum bytes a single char can take.
+    memcpy( aCharBytes, pCharFirstByte, 2 );
+
+    result = ( aCharBytes[0] << nBitOffsetInByte );
+    result |= ( aCharBytes[1] >> ( 8 - nBitOffsetInByte ) );
+
+    nBitOffsetFromStart += 8;
+
+    return result;
+}
+
+std::string ReadTV( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    // TODO: due to CLion issues with copying text from output window, all
+    //       string readed are now not zero-terminated. Will fix soon.
+    short stringLength = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    std::string result;
+
+    for( short i = 0; i < stringLength; ++i )
+    {
+        result += static_cast<char>(ReadCHAR( pabyInput, nBitOffsetFromStart ));
+    }
+
+    return result;
+}
+
+long ReadUMCHAR( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    // TODO: bit offset is calculated, but function has nothing to do with it.
+    long result = 0;
+    /*bool   negative = false;*/
+    size_t nByteOffset = nBitOffsetFromStart / 8;
+    /*size_t nBitOffsetInByte = nBitOffsetFromStart % 8;*/
+
+    const char * pMCharFirstByte = pabyInput + nByteOffset;
+    unsigned char aMCharBytes[8]; // 8 bytes is maximum.
+    memcpy( aMCharBytes, pMCharFirstByte, 8 );
+
+    size_t MCharBytesCount = 0;
+    for( size_t i = 0; i < 8; ++i )
+    {
+        aMCharBytes[i] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+        ++MCharBytesCount;
+        if ( !( aMCharBytes[i] & binary( 10000000 ) ) )
+        {
+            break;
+        }
+    }
+
+    SwapEndianness( aMCharBytes, MCharBytesCount ); // LSB to MSB
+
+    for( size_t i = 0; i < MCharBytesCount; ++i )
+    {
+        aMCharBytes[i] &= binary( 01111111 );
+    }
+
+    // TODO: this code doesn't cover case when char.bytescount > 3, but its
+    //       possible on large files.
+    // I just can't write an algorithm that does this.
+    switch( MCharBytesCount )
+    {
+        case 1:
+            break;
+        case 2:
+        {
+            char tmp = aMCharBytes[0] & binary( 00000001 );
+            aMCharBytes[0] = aMCharBytes[0] >> 1;
+            aMCharBytes[1] |= ( tmp << 7 );
+            break;
+        }
+        case 3:
+        {
+            unsigned char tmp1 = aMCharBytes[0] & binary( 00000011 );
+            unsigned char tmp2 = aMCharBytes[1] & binary( 00000001 );
+            aMCharBytes[0] = aMCharBytes[0] >> 2;
+            aMCharBytes[1] = aMCharBytes[1] >> 1;
+            aMCharBytes[1] |= ( tmp1 << 6 );
+            aMCharBytes[2] |= ( tmp2 << 7 );
+            break;
+        }
+        case 4:
+        {
+            unsigned char tmp1 = aMCharBytes[0] & binary( 00000111 );
+            unsigned char tmp2 = aMCharBytes[1] & binary( 00000011 );
+            unsigned char tmp3 = aMCharBytes[2] & binary( 00000001 );
+            aMCharBytes[0] = aMCharBytes[0] >> 3;
+            aMCharBytes[1] = aMCharBytes[1] >> 2;
+            aMCharBytes[2] = aMCharBytes[2] >> 1;
+            aMCharBytes[1] |= ( tmp1 << 5 );
+            aMCharBytes[2] |= ( tmp2 << 6 );
+            aMCharBytes[3] |= ( tmp3 << 7 );
+            break;
+        }
+    }
+
+    SwapEndianness( aMCharBytes, MCharBytesCount ); // MSB to LSB
+
+    memcpy( &result, aMCharBytes, MCharBytesCount );
+
+    return result;
+}
+
+long ReadMCHAR( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    long   result      = 0;
+    bool   negative    = false;
+    size_t nByteOffset = nBitOffsetFromStart / 8;
+
+    // TODO: bit offset is calculated, but function has nothing to do with it.
+    /*size_t nBitOffsetInByte = nBitOffsetFromStart % 8;*/
+
+    const char * pMCharFirstByte = pabyInput + nByteOffset;
+    unsigned char aMCharBytes[8]; // 8 bytes is maximum.
+    memcpy( aMCharBytes, pMCharFirstByte, 8 );
+
+    size_t MCharBytesCount = 0;
+    for( size_t i = 0; i < 8; ++i )
+    {
+        aMCharBytes[i] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+        ++MCharBytesCount;
+        if ( !( aMCharBytes[i] & binary( 10000000 ) ) )
+        {
+            break;
+        }
+    }
+
+    SwapEndianness( aMCharBytes, MCharBytesCount ); // LSB to MSB
+
+    if ( ( aMCharBytes[0] & binary( 01000000 ) ) == binary( 01000000 ) )
+    {
+        aMCharBytes[0] &= binary( 10111111 );
+        negative = true;
+    }
+
+    for( size_t i = 0; i < MCharBytesCount; ++i )
+    {
+        aMCharBytes[i] &= binary( 01111111 );
+    }
+
+    // TODO: this code doesn't cover case when char.bytescount > 3, but its
+    //       possible on large files.
+    // I just can't write an algorithm that does this.
+    switch( MCharBytesCount )
+    {
+        case 1:
+            break;
+        case 2:
+        {
+            char tmp = aMCharBytes[0] & binary( 00000001 );
+            aMCharBytes[0] = aMCharBytes[0] >> 1;
+            aMCharBytes[1] |= ( tmp << 7 );
+            break;
+        }
+        case 3:
+        {
+            unsigned char tmp1 = aMCharBytes[0] & binary( 00000011 );
+            unsigned char tmp2 = aMCharBytes[1] & binary( 00000001 );
+            aMCharBytes[0] = aMCharBytes[0] >> 2;
+            aMCharBytes[1] = aMCharBytes[1] >> 1;
+            aMCharBytes[1] |= ( tmp1 << 6 );
+            aMCharBytes[2] |= ( tmp2 << 7 );
+            break;
+        }
+        case 4:
+        {
+            unsigned char tmp1 = aMCharBytes[0] & binary( 00000111 );
+            unsigned char tmp2 = aMCharBytes[1] & binary( 00000011 );
+            unsigned char tmp3 = aMCharBytes[2] & binary( 00000001 );
+            aMCharBytes[0] = aMCharBytes[0] >> 3;
+            aMCharBytes[1] = aMCharBytes[1] >> 2;
+            aMCharBytes[2] = aMCharBytes[2] >> 1;
+            aMCharBytes[1] |= ( tmp1 << 5 );
+            aMCharBytes[2] |= ( tmp2 << 6 );
+            aMCharBytes[3] |= ( tmp3 << 7 );
+            break;
+        }
+    }
+
+    SwapEndianness( aMCharBytes, MCharBytesCount ); // MSB to LSB
+
+    memcpy( &result, aMCharBytes, MCharBytesCount );
+
+    if( negative )
+        result *= -1;
+
+    return result;
+}
+
+unsigned int ReadMSHORT( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned int  result = 0;
+    /*size_t nByteOffset      = nBitOffsetFromStart / 8;
+    size_t nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * pMShortFirstByte = pabyInput + nByteOffset;*/
+    unsigned char aMShortBytes[8]; // 8 bytes is maximum.
+
+    // TODO: this function doesnot support MSHORTS longer than 4 bytes. ODA says
+    //       its impossible, but not sure.
+    size_t MShortBytesCount = 2;
+    aMShortBytes[0] = ReadCHAR ( pabyInput, nBitOffsetFromStart );
+    aMShortBytes[1] = ReadCHAR ( pabyInput, nBitOffsetFromStart );
+    if ( aMShortBytes[1] & binary( 10000000 ) )
+    {
+        aMShortBytes[2] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+        aMShortBytes[3] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+        MShortBytesCount = 4;
+    }
+
+    SwapEndianness( aMShortBytes, MShortBytesCount );
+
+    if( MShortBytesCount == 2 )
+    {
+        aMShortBytes[0] &= binary( 01111111 ); // drop high order flag bit.
+    }
+    else if ( MShortBytesCount == 4 )
+    {
+        aMShortBytes[0] &= binary( 01111111 );
+        aMShortBytes[2] &= binary( 01111111 );
+
+        aMShortBytes[2] |= ( aMShortBytes[1] << 7 );
+        aMShortBytes[1] = ( aMShortBytes[1] >> 1 );
+        aMShortBytes[1] |= ( aMShortBytes[0] << 7 );
+        aMShortBytes[0] = ( aMShortBytes[0] >> 1 );
+    }
+    SwapEndianness( aMShortBytes, MShortBytesCount ); // MSB to LSB
+    memcpy( & result, aMShortBytes, MShortBytesCount );
+    return result;
+}
+
+double ReadBITDOUBLE( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char BITCODE = Read2B( pabyInput, nBitOffsetFromStart );
+
+    size_t nByteOffset      = nBitOffsetFromStart / 8;
+    size_t nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * pDoubleFirstByte = pabyInput + nByteOffset;
+    unsigned char aDoubleBytes[9]; // maximum bytes a single double can take.
+    memcpy( aDoubleBytes, pDoubleFirstByte, 9 );
+
+    switch( BITCODE )
+    {
+        case BITDOUBLE_NORMAL:
+        {
+            aDoubleBytes[0] <<= nBitOffsetInByte;
+            aDoubleBytes[0] |= ( aDoubleBytes[1] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[1] <<= nBitOffsetInByte;
+            aDoubleBytes[1] |= ( aDoubleBytes[2] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[2] <<= nBitOffsetInByte;
+            aDoubleBytes[2] |= ( aDoubleBytes[3] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[3] <<= nBitOffsetInByte;
+            aDoubleBytes[3] |= ( aDoubleBytes[4] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[4] <<= nBitOffsetInByte;
+            aDoubleBytes[4] |= ( aDoubleBytes[5] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[5] <<= nBitOffsetInByte;
+            aDoubleBytes[5] |= ( aDoubleBytes[6] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[6] <<= nBitOffsetInByte;
+            aDoubleBytes[6] |= ( aDoubleBytes[7] >> ( 8 - nBitOffsetInByte ) );
+            aDoubleBytes[7] <<= nBitOffsetInByte;
+            aDoubleBytes[7] |= ( aDoubleBytes[8] >> ( 8 - nBitOffsetInByte ) );
+
+            nBitOffsetFromStart += 64;
+
+            void   * ptr    = aDoubleBytes;
+            double * result = static_cast< double *> ( ptr );
+
+            return * result;
+        }
+
+        case BITDOUBLE_ONE_VALUE:
+        {
+            nBitOffsetFromStart += 0;
+
+            return 1.0f;
+        }
+
+        case BITDOUBLE_ZERO_VALUE:
+        {
+            nBitOffsetFromStart += 0;
+
+            return 0.0f;
+        }
+
+        case BITDOUBLE_NOT_USED:
+        {
+            nBitOffsetFromStart += 0;
+
+            return 0.0f;
+        }
+    }
+
+    return 0.0f;
+}
+
+double ReadBITDOUBLEWD( const char * pabyInput, size_t& nBitOffsetFromStart, double defaultvalue )
+{
+    unsigned char aDefaultValueBytes[8];
+    memcpy( aDefaultValueBytes, & defaultvalue, 8 );
+
+    unsigned char BITCODE = Read2B( pabyInput, nBitOffsetFromStart );
+
+    switch( BITCODE )
+    {
+        case BITDOUBLEWD_DEFAULT_VALUE:
+        {
+            return defaultvalue;
+        }
+
+        case BITDOUBLEWD_4BYTES_PATCHED:
+        {
+            aDefaultValueBytes[0] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[1] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[2] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[3] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+            void   * ptr    = aDefaultValueBytes;
+            double * result = static_cast< double *> ( ptr );
+
+            return * result;
+        }
+
+        case BITDOUBLEWD_6BYTES_PATCHED:
+        {
+            aDefaultValueBytes[4] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[5] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[0] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[1] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[2] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[3] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+            void   * ptr    = aDefaultValueBytes;
+            double * result = static_cast< double *> ( ptr );
+
+            return * result;
+        }
+
+        case BITDOUBLEWD_FULL_RD:
+        {
+            aDefaultValueBytes[0] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[1] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[2] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[3] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[4] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[5] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[6] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+            aDefaultValueBytes[7] = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+            void   * ptr    = aDefaultValueBytes;
+            double * result = static_cast< double *> ( ptr );
+
+            return * result;
+        }
+    }
+
+    return 0.0f;
+}
+
+CADHandle ReadHANDLE( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADHandle result( Read4B( pabyInput, nBitOffsetFromStart ) );
+    unsigned char counter = Read4B( pabyInput, nBitOffsetFromStart );
+    for( unsigned char i = 0; i < counter; ++i )
+    {
+        result.addOffset( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+    }
+
+    return result;
+}
+
+void SkipHANDLE( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    Read4B( pabyInput, nBitOffsetFromStart );
+    unsigned char counter = static_cast<unsigned char>(Read4B( pabyInput, nBitOffsetFromStart ));
+    nBitOffsetFromStart += counter * 8;
+}
+
+CADHandle ReadHANDLE8BLENGTH( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADHandle result;
+
+    unsigned char counter = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    for( unsigned char i = 0; i < counter; ++i )
+    {
+        result.addOffset( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+    }
+
+    return result;
+}
+
+int ReadBITLONG( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char BITCODE = Read2B( pabyInput, nBitOffsetFromStart );
+
+    size_t nByteOffset      = nBitOffsetFromStart / 8;
+    size_t nBitOffsetInByte = nBitOffsetFromStart % 8;
+
+    const char * pLongFirstByte = pabyInput + nByteOffset;
+    unsigned char aLongBytes[5]; // maximum bytes a single short can take.
+    memcpy( aLongBytes, pLongFirstByte, 5 );
+
+    switch( BITCODE )
+    {
+        case BITLONG_NORMAL:
+        {
+            aLongBytes[0] <<= nBitOffsetInByte;
+            aLongBytes[0] |= ( aLongBytes[1] >> ( 8 - nBitOffsetInByte ) );
+            aLongBytes[1] <<= nBitOffsetInByte;
+            aLongBytes[1] |= ( aLongBytes[2] >> ( 8 - nBitOffsetInByte ) );
+            aLongBytes[2] <<= nBitOffsetInByte;
+            aLongBytes[2] |= ( aLongBytes[3] >> ( 8 - nBitOffsetInByte ) );
+            aLongBytes[3] <<= nBitOffsetInByte;
+            aLongBytes[3] |= ( aLongBytes[4] >> ( 8 - nBitOffsetInByte ) );
+
+            nBitOffsetFromStart += 32;
+
+            void * ptr    = aLongBytes;
+            int  * result = static_cast < int * > ( ptr );
+
+            return * result;
+        }
+
+        case BITLONG_UNSIGNED_CHAR:
+        {
+            aLongBytes[0] <<= nBitOffsetInByte;
+            aLongBytes[0] |= ( aLongBytes[1] >> ( 8 - nBitOffsetInByte ) );
+
+            nBitOffsetFromStart += 8;
+
+            return aLongBytes[0];
+        }
+
+        case BITLONG_ZERO_VALUE:
+        {
+            nBitOffsetFromStart += 0;
+            return 0;
+        }
+
+        case BITLONG_NOT_USED:
+        {
+            std::cerr <<
+            "THAT SHOULD NEVER HAPPENED! BUG. (in file, or reader, or both.) ReadBITLONG(), case BITLONG_NOT_USED" <<
+            std::endl;
+            nBitOffsetFromStart += 0;
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+void SkipBITDOUBLE( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char BITCODE = Read2B( pabyInput, nBitOffsetFromStart );
+
+    switch( BITCODE )
+    {
+        case BITDOUBLE_NORMAL:
+            nBitOffsetFromStart += 64;
+            break;
+        case BITDOUBLE_ONE_VALUE:
+            nBitOffsetFromStart += 0;
+            break;
+        case BITDOUBLE_ZERO_VALUE:
+        case BITDOUBLE_NOT_USED:
+            break;
+    }
+}
+
+void SkipTV( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    short stringLength = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    nBitOffsetFromStart += size_t( stringLength * 8 );
+}
+
+void SkipBITLONG( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char BITCODE = Read2B( pabyInput, nBitOffsetFromStart );
+    switch( BITCODE )
+    {
+        case BITLONG_NORMAL:
+            nBitOffsetFromStart += 32;
+            break;
+
+        case BITLONG_UNSIGNED_CHAR:
+            nBitOffsetFromStart += 8;
+            break;
+
+        case BITLONG_ZERO_VALUE:
+        case BITLONG_NOT_USED:
+            break;
+    }
+}
+
+void SkipBITSHORT( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    unsigned char BITCODE = Read2B( pabyInput, nBitOffsetFromStart );
+    switch( BITCODE )
+    {
+        case BITSHORT_NORMAL:
+            nBitOffsetFromStart += 16;
+            break;
+
+        case BITSHORT_UNSIGNED_CHAR:
+            nBitOffsetFromStart += 8;
+            break;
+
+        case BITSHORT_ZERO_VALUE:
+        case BITSHORT_256:
+            break;
+    }
+}
+
+void SkipBIT( const char * /*pabyInput*/, size_t& nBitOffsetFromStart )
+{
+    ++nBitOffsetFromStart;
+}
+
+CADVector ReadVector( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    double x, y, z;
+    x = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    y = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    z = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    return CADVector( x, y, z );
+}
+
+CADVector ReadRAWVector( const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    double x, y;
+    x = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    y = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    return CADVector( x, y );
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/dwg/io.h b/ogr/ogrsf_frmts/cad/libopencad/dwg/io.h
new file mode 100644
index 0000000..c5517ec
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/dwg/io.h
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef DWG_IO_H
+#define DWG_IO_H
+
+#include "cadheader.h"
+#include "cadobjects.h"
+
+#include <string>
+#include <algorithm>
+
+/* DATA TYPES CONSTANTS */
+
+#define BITSHORT_NORMAL         0x0
+#define BITSHORT_UNSIGNED_CHAR  0x1
+#define BITSHORT_ZERO_VALUE     0x2
+#define BITSHORT_256            0x3
+
+#define BITLONG_NORMAL          0x0
+#define BITLONG_UNSIGNED_CHAR   0x1
+#define BITLONG_ZERO_VALUE      0x2
+#define BITLONG_NOT_USED        0x3
+
+#define BITDOUBLE_NORMAL        0x0
+#define BITDOUBLE_ONE_VALUE     0x1
+#define BITDOUBLE_ZERO_VALUE    0x2
+#define BITDOUBLE_NOT_USED      0x3
+
+#define BITDOUBLEWD_DEFAULT_VALUE  0x0
+#define BITDOUBLEWD_4BYTES_PATCHED 0x1
+#define BITDOUBLEWD_6BYTES_PATCHED 0x2
+#define BITDOUBLEWD_FULL_RD        0x3
+
+namespace DWGConstants {
+extern const size_t SentinelLength;
+extern const char * HeaderVariablesStart;
+extern const char * HeaderVariablesEnd;
+extern const char * DSClassesStart;
+extern const char * DSClassesEnd;
+
+/* UNUSED
+static const char * DWGDSPreviewStart
+            = "\x1F\x25\x6D\x07\xD4\x36\x28\x28\x9D\x57\xCA\x3F\x9D\x44\x10\x2B";
+static const char * DWGDSPreviewEnd
+            = "\xE0\xDA\x92\xF8\x2B\xc9\xD7\xD7\x62\xA8\x35\xC0\x62\xBB\xEF\xD4";
+
+static const char * DWGSecondFileHeaderStart
+            = "\xD4\x7B\x21\xCE\x28\x93\x9F\xBF\x53\x24\x40\x09\x12\x3C\xAA\x01";
+static const char * DWGSecondFileHeaderEnd
+            = "\x2B\x84\xDE\x31\xD7\x6C\x60\x40\xAC\xDB\xBF\xF6\xED\xC3\x55\xFE";
+*/
+}
+
+// TODO: probably it would be better to have no dependencies on <algorithm>.
+template<typename T, typename S>
+inline void SwapEndianness( T&& object, S&& size )
+{
+    std::reverse( ( char * ) &object, ( char * ) &object + size );
+}
+
+/*
+ * Method taken from here: http://stackoverflow.com/a/2611850
+ * Purpose: no C++14 dependencies in library
+ */
+template< unsigned long N >
+struct bin
+{
+    enum
+    {
+        value = ( N % 8 ) + ( bin< N / 8 >::value << 1 )
+    };
+};
+
+template<>
+struct bin< 0 >
+{
+    enum
+    {
+        value = 0
+    };
+};
+#define binary( n ) bin<0##n>::value
+
+extern const int DWGCRC8Table[256];
+
+unsigned short CalculateCRC8( unsigned short initialVal, const char * ptr, int num );
+
+long          ReadRAWLONGLONG( const char * pabyInput, size_t& nBitOffsetFromStart );
+int           ReadRAWLONG( const char * pabyInput, size_t& nBitOffsetFromStart );
+short         ReadRAWSHORT( const char * pabyInput, size_t& nBitOffsetFromStart );
+double        ReadRAWDOUBLE( const char * pabyInput, size_t& nBitOffsetFromStart );
+unsigned char Read2B( const char * pabyInput, size_t& nBitOffsetFromStart );
+unsigned char Read3B( const char * pabyInput, size_t& nBitOffsetFromStart );
+unsigned char Read4B( const char * pabyInput, size_t& nBitOffsetFromStart );
+CADHandle     ReadHANDLE( const char * pabyInput, size_t& nBitOffsetFromStart );
+CADHandle     ReadHANDLE8BLENGTH( const char * pabyInput, size_t& nBitOffsetFromStart );
+void          SkipHANDLE( const char * pabyInput, size_t& nBitOffsetFromStart );
+bool          ReadBIT( const char * pabyInput, size_t& nBitOffsetFromStart );
+void          SkipBIT( const char * pabyInput, size_t& nBitOffsetFromStart );
+unsigned char ReadCHAR( const char * pabyInput, size_t& nBitOffsetFromStart );
+short         ReadBITSHORT( const char * pabyInput, size_t& nBitOffsetFromStart );
+int           ReadBITLONG( const char * pabyInput, size_t& nBitOffsetFromStart );
+double        ReadBITDOUBLE( const char * pabyInput, size_t& nBitOffsetFromStart );
+void          SkipBITDOUBLE( const char * pabyInput, size_t& nBitOffsetFromStart );
+double        ReadBITDOUBLEWD( const char * pabyInput, size_t& nBitOffsetFromStart, double defaultvalue );
+long          ReadMCHAR( const char * pabyInput, size_t& nBitOffsetFromStart );
+long          ReadUMCHAR( const char * pabyInput, size_t& nBitOffsetFromStart );
+unsigned int  ReadMSHORT( const char * pabyInput, size_t& nBitOffsetFromStart );
+std::string   ReadTV( const char * pabyInput, size_t& nBitOffsetFromStart );
+void          SkipTV( const char * pabyInput, size_t& nBitOffsetFromStart );
+void          SkipBITLONG( const char * pabyInput, size_t& nBitOffsetFromStart );
+void          SkipBITSHORT( const char * pabyInput, size_t& nBitOffsetFromStart );
+
+CADVector ReadVector( const char * pabyInput, size_t& nBitOffsetFromStart );
+CADVector ReadRAWVector( const char * pabyInput, size_t& nBitOffsetFromStart );
+
+#endif // DWG_IO_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/dwg/makefile.vc b/ogr/ogrsf_frmts/cad/libopencad/dwg/makefile.vc
new file mode 100644
index 0000000..5f09b7d
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/dwg/makefile.vc
@@ -0,0 +1,18 @@
+#
+# Makefile building opencad library
+# 
+
+OBJ = \
+	r2000.obj \
+	io.obj 
+
+GDAL_ROOT	=	..\..\..\..\..
+EXTRAFLAGS =	-I. -I.. -I..\.. -I..\..\.. -I..\..\..\.. -DOCAD_EXTERN=""
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+
+clean:
+	-del *.lib
+	-del *.obj *.pdb
\ No newline at end of file
diff --git a/ogr/ogrsf_frmts/cad/libopencad/dwg/r2000.cpp b/ogr/ogrsf_frmts/cad/libopencad/dwg/r2000.cpp
new file mode 100644
index 0000000..58b759a
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/dwg/r2000.cpp
@@ -0,0 +1,3653 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "cadgeometry.h"
+#include "cadobjects.h"
+#include "io.h"
+#include "opencad_api.h"
+#include "r2000.h"
+
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <memory>
+#include <string>
+
+#if (defined(__sun__) || defined(__FreeBSD__)) && __GNUC__ == 4 && __GNUC_MINOR__ == 8
+// gcc 4.8 on Solaris 11.3 or FreeBSD 11 doesn't have std::string
+#include <sstream>
+template <typename T> std::string to_string(T val)
+{
+    std::ostringstream os;
+    os << val;
+    return os.str();
+}
+#endif
+
+#ifdef __APPLE__
+    #include <MacTypes.h>
+#endif
+
+#define UNKNOWN1 CADHeader::MAX_HEADER_CONSTANT + 1
+#define UNKNOWN2 CADHeader::MAX_HEADER_CONSTANT + 2
+#define UNKNOWN3 CADHeader::MAX_HEADER_CONSTANT + 3
+#define UNKNOWN4 CADHeader::MAX_HEADER_CONSTANT + 4
+#define UNKNOWN5 CADHeader::MAX_HEADER_CONSTANT + 5
+#define UNKNOWN6 CADHeader::MAX_HEADER_CONSTANT + 6
+#define UNKNOWN7 CADHeader::MAX_HEADER_CONSTANT + 7
+#define UNKNOWN8 CADHeader::MAX_HEADER_CONSTANT + 8
+#define UNKNOWN9 CADHeader::MAX_HEADER_CONSTANT + 9
+#define UNKNOWN10 CADHeader::MAX_HEADER_CONSTANT + 10
+#define UNKNOWN11 CADHeader::MAX_HEADER_CONSTANT + 11
+#define UNKNOWN12 CADHeader::MAX_HEADER_CONSTANT + 12
+#define UNKNOWN13 CADHeader::MAX_HEADER_CONSTANT + 13
+#define UNKNOWN14 CADHeader::MAX_HEADER_CONSTANT + 14
+#define UNKNOWN15 CADHeader::MAX_HEADER_CONSTANT + 15
+
+using namespace std;
+
+int DWGFileR2000::ReadHeader( OpenOptions eOptions )
+{
+    char buffer[255];
+    char * pabyBuf;
+    size_t dHeaderVarsSectionLength = 0;
+    const size_t dSizeOfSectionSize = 4;
+
+    pFileIO->Seek( sectionLocatorRecords[0].dSeeker, CADFileIO::SeekOrigin::BEG );
+    pFileIO->Read( buffer, DWGConstants::SentinelLength );
+    if( memcmp( buffer, DWGConstants::HeaderVariablesStart,
+                        DWGConstants::SentinelLength ) )
+    {
+        DebugMsg( "File is corrupted (wrong pointer to HEADER_VARS section,"
+                          "or HEADERVARS starting sentinel corrupted.)" );
+
+        return CADErrorCodes::HEADER_SECTION_READ_FAILED;
+    }
+
+    pFileIO->Read( &dHeaderVarsSectionLength, dSizeOfSectionSize );
+        DebugMsg( "Header variables section length: %d\n",
+                  static_cast<int>(dHeaderVarsSectionLength) );
+
+    pabyBuf = new char[dHeaderVarsSectionLength + dSizeOfSectionSize + 10]; // Add extra 10 bytes
+    memcpy (pabyBuf, &dHeaderVarsSectionLength, dSizeOfSectionSize);
+    memset (pabyBuf + dSizeOfSectionSize, 0, dHeaderVarsSectionLength + 10);
+    pFileIO->Read( pabyBuf + dSizeOfSectionSize, dHeaderVarsSectionLength + 2 );
+    size_t nBitOffsetFromStart = dSizeOfSectionSize * 8;
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        oHeader.addValue( UNKNOWN1, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN2, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN3, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN4, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN5, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN6, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN7, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN8, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN9, ReadBITLONG( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN10, ReadBITLONG( pabyBuf, nBitOffsetFromStart ) );
+    } else
+    {
+        SkipBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+        SkipBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+        SkipBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+        SkipBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+        SkipTV( pabyBuf, nBitOffsetFromStart );
+        SkipTV( pabyBuf, nBitOffsetFromStart );
+        SkipTV( pabyBuf, nBitOffsetFromStart );
+        SkipTV( pabyBuf, nBitOffsetFromStart );
+        SkipBITLONG( pabyBuf, nBitOffsetFromStart );
+        SkipBITLONG( pabyBuf, nBitOffsetFromStart );
+    }
+
+    CADHandle stCurrentViewportTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::CurrentViewportTable, stCurrentViewportTable );
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        oHeader.addValue( CADHeader::DIMASO, ReadBIT( pabyBuf, nBitOffsetFromStart ) );     // 1
+        oHeader.addValue( CADHeader::DIMSHO, ReadBIT( pabyBuf, nBitOffsetFromStart ) );     // 2
+        oHeader.addValue( CADHeader::PLINEGEN, ReadBIT( pabyBuf, nBitOffsetFromStart ) );   // 3
+        oHeader.addValue( CADHeader::ORTHOMODE, ReadBIT( pabyBuf, nBitOffsetFromStart ) );  // 4
+        oHeader.addValue( CADHeader::REGENMODE, ReadBIT( pabyBuf, nBitOffsetFromStart ) );  // 5
+        oHeader.addValue( CADHeader::FILLMODE, ReadBIT( pabyBuf, nBitOffsetFromStart ) );   // 6
+        oHeader.addValue( CADHeader::QTEXTMODE, ReadBIT( pabyBuf, nBitOffsetFromStart ) );  // 7
+        oHeader.addValue( CADHeader::PSLTSCALE, ReadBIT( pabyBuf, nBitOffsetFromStart ) );  // 8
+        oHeader.addValue( CADHeader::LIMCHECK, ReadBIT( pabyBuf, nBitOffsetFromStart ) );   // 9
+        oHeader.addValue( CADHeader::USRTIMER, ReadBIT( pabyBuf, nBitOffsetFromStart ) );   // 10
+        oHeader.addValue( CADHeader::SKPOLY, ReadBIT( pabyBuf, nBitOffsetFromStart ) );     // 11
+        oHeader.addValue( CADHeader::ANGDIR, ReadBIT( pabyBuf, nBitOffsetFromStart ) );     // 12
+        oHeader.addValue( CADHeader::SPLFRAME, ReadBIT( pabyBuf, nBitOffsetFromStart ) );   // 13
+        oHeader.addValue( CADHeader::MIRRTEXT, ReadBIT( pabyBuf, nBitOffsetFromStart ) );   // 14
+        oHeader.addValue( CADHeader::WORDLVIEW, ReadBIT( pabyBuf, nBitOffsetFromStart ) );  // 15
+        oHeader.addValue( CADHeader::TILEMODE, ReadBIT( pabyBuf, nBitOffsetFromStart ) );   // 16
+        oHeader.addValue( CADHeader::PLIMCHECK, ReadBIT( pabyBuf, nBitOffsetFromStart ) );  // 17
+        oHeader.addValue( CADHeader::VISRETAIN, ReadBIT( pabyBuf, nBitOffsetFromStart ) );  // 18
+        oHeader.addValue( CADHeader::DISPSILH, ReadBIT( pabyBuf, nBitOffsetFromStart ) );   // 19
+        oHeader.addValue( CADHeader::PELLIPSE, ReadBIT( pabyBuf, nBitOffsetFromStart ) );   // 20
+    } else
+    {
+        nBitOffsetFromStart += 20;
+    }
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        oHeader.addValue( CADHeader::PROXYGRAPHICS, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) ); // 1
+        oHeader.addValue( CADHeader::TREEDEPTH, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );     // 2
+        oHeader.addValue( CADHeader::LUNITS, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );        // 3
+        oHeader.addValue( CADHeader::LUPREC, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );        // 4
+        oHeader.addValue( CADHeader::AUNITS, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );        // 5
+        oHeader.addValue( CADHeader::AUPREC, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );        // 6
+    } else
+    {
+        for( char i = 0; i < 6; ++i )
+            SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+    }
+
+    oHeader.addValue( CADHeader::ATTMODE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::PDMODE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        oHeader.addValue( CADHeader::USERI1, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );    // 1
+        oHeader.addValue( CADHeader::USERI2, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );    // 2
+        oHeader.addValue( CADHeader::USERI3, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );    // 3
+        oHeader.addValue( CADHeader::USERI4, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );    // 4
+        oHeader.addValue( CADHeader::USERI5, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );    // 5
+        oHeader.addValue( CADHeader::SPLINESEGS, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );// 6
+        oHeader.addValue( CADHeader::SURFU, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );     // 7
+        oHeader.addValue( CADHeader::SURFV, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );     // 8
+        oHeader.addValue( CADHeader::SURFTYPE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 9
+        oHeader.addValue( CADHeader::SURFTAB1, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 10
+        oHeader.addValue( CADHeader::SURFTAB2, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 11
+        oHeader.addValue( CADHeader::SPLINETYPE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );// 12
+        oHeader.addValue( CADHeader::SHADEDGE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 13
+        oHeader.addValue( CADHeader::SHADEDIF, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 14
+        oHeader.addValue( CADHeader::UNITMODE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 15
+        oHeader.addValue( CADHeader::MAXACTVP, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 16
+        oHeader.addValue( CADHeader::ISOLINES, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 17
+        oHeader.addValue( CADHeader::CMLJUST, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 18
+        oHeader.addValue( CADHeader::TEXTQLTY, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 19
+    } else
+    {
+        for( char i = 0; i < 19; ++i )
+            SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+    }
+
+    oHeader.addValue( CADHeader::LTSCALE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::TEXTSIZE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::TRACEWID, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::SKETCHINC, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::FILLETRAD, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::THICKNESS, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::ANGBASE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::PDSIZE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::PLINEWID, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        oHeader.addValue( CADHeader::USERR1, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 1
+        oHeader.addValue( CADHeader::USERR2, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 2
+        oHeader.addValue( CADHeader::USERR3, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 3
+        oHeader.addValue( CADHeader::USERR4, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 4
+        oHeader.addValue( CADHeader::USERR5, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 5
+        oHeader.addValue( CADHeader::CHAMFERA, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) ); // 6
+        oHeader.addValue( CADHeader::CHAMFERB, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) ); // 7
+        oHeader.addValue( CADHeader::CHAMFERC, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) ); // 8
+        oHeader.addValue( CADHeader::CHAMFERD, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) ); // 9
+        oHeader.addValue( CADHeader::FACETRES, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) ); // 10
+        oHeader.addValue( CADHeader::CMLSCALE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) ); // 11
+        oHeader.addValue( CADHeader::CELTSCALE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );// 12
+
+        oHeader.addValue( CADHeader::MENU, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+    } else
+    {
+        for( char i = 0; i < 12; ++i )
+            SkipBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+        SkipTV( pabyBuf, nBitOffsetFromStart );
+    }
+
+    long juliandate, millisec;
+    juliandate = ReadBITLONG( pabyBuf, nBitOffsetFromStart );
+    millisec   = ReadBITLONG( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::TDCREATE, juliandate, millisec );
+    juliandate = ReadBITLONG( pabyBuf, nBitOffsetFromStart );
+    millisec   = ReadBITLONG( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::TDUPDATE, juliandate, millisec );
+    juliandate = ReadBITLONG( pabyBuf, nBitOffsetFromStart );
+    millisec   = ReadBITLONG( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::TDINDWG, juliandate, millisec );
+    juliandate = ReadBITLONG( pabyBuf, nBitOffsetFromStart );
+    millisec   = ReadBITLONG( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::TDUSRTIMER, juliandate, millisec );
+
+    oHeader.addValue( CADHeader::CECOLOR, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+
+    oHeader.addValue( CADHeader::HANDSEED, ReadHANDLE8BLENGTH( pabyBuf, nBitOffsetFromStart ) ); // TODO: Check this case.
+
+    oHeader.addValue( CADHeader::CLAYER, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::TEXTSTYLE, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::CELTYPE, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::DIMSTYLE, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::CMLSTYLE, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+
+    oHeader.addValue( CADHeader::PSVPSCALE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    double dX, dY, dZ;
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PINSBASE, dX, dY, dZ );
+
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PEXTMIN, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PEXTMAX, dX, dY, dZ );
+    dX = ReadRAWDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadRAWDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PLIMMIN, dX, dY );
+    dX = ReadRAWDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadRAWDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PLIMMAX, dX, dY );
+
+    oHeader.addValue( CADHeader::PELEVATION, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PUCSORG, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PUCSXDIR, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PUCSYDIR, dX, dY, dZ );
+
+    oHeader.addValue( CADHeader::PUCSNAME, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::PUCSORTHOREF, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+
+    oHeader.addValue( CADHeader::PUCSORTHOVIEW, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::PUCSBASE, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PUCSORGTOP, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PUCSORGBOTTOM, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PUCSORGLEFT, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PUCSORGRIGHT, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PUCSORGFRONT, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::PUCSORGBACK, dX, dY, dZ );
+
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::INSBASE, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::EXTMIN, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::EXTMAX, dX, dY, dZ );
+    dX = ReadRAWDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadRAWDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::LIMMIN, dX, dY );
+    dX = ReadRAWDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadRAWDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::LIMMAX, dX, dY );
+
+    oHeader.addValue( CADHeader::ELEVATION, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::UCSORG, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::UCSXDIR, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::UCSYDIR, dX, dY, dZ );
+
+    oHeader.addValue( CADHeader::UCSNAME, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::UCSORTHOREF, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+
+    oHeader.addValue( CADHeader::UCSORTHOVIEW, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+
+    oHeader.addValue( CADHeader::UCSBASE, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::UCSORGTOP, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::UCSORGBOTTOM, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::UCSORGLEFT, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::UCSORGRIGHT, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::UCSORGFRONT, dX, dY, dZ );
+    dX = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dY = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    dZ = ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::UCSORGBACK, dX, dY, dZ );
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        oHeader.addValue( CADHeader::DIMPOST, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMAPOST, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMSCALE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) ); // 1
+        oHeader.addValue( CADHeader::DIMASZ, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 2
+        oHeader.addValue( CADHeader::DIMEXO, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 3
+        oHeader.addValue( CADHeader::DIMDLI, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 4
+        oHeader.addValue( CADHeader::DIMEXE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 5
+        oHeader.addValue( CADHeader::DIMRND, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 6
+        oHeader.addValue( CADHeader::DIMDLE, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 7
+        oHeader.addValue( CADHeader::DIMTP, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );    // 8
+        oHeader.addValue( CADHeader::DIMTM, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );    // 9
+
+        oHeader.addValue( CADHeader::DIMTOL, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMLIM, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMTIH, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMTOH, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMSE1, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMSE2, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMTAD, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMZIN, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMAZIN, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMTXT, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 1
+        oHeader.addValue( CADHeader::DIMCEN, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 2
+        oHeader.addValue( CADHeader::DIMTSZ, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 3
+        oHeader.addValue( CADHeader::DIMALTF, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );  // 4
+        oHeader.addValue( CADHeader::DIMLFAC, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );  // 5
+        oHeader.addValue( CADHeader::DIMTVP, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 6
+        oHeader.addValue( CADHeader::DIMTFAC, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );  // 7
+        oHeader.addValue( CADHeader::DIMGAP, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );   // 8
+        oHeader.addValue( CADHeader::DIMALTRND, ReadBITDOUBLE( pabyBuf, nBitOffsetFromStart ) );// 9
+
+        oHeader.addValue( CADHeader::DIMALT, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMALTD, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMTOFL, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMSAH, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMTIX, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMSOXD, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMCLRD, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 1
+        oHeader.addValue( CADHeader::DIMCLRE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 2
+        oHeader.addValue( CADHeader::DIMCLRT, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 3
+        oHeader.addValue( CADHeader::DIMADEC, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 4
+        oHeader.addValue( CADHeader::DIMDEC, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );    // 5
+        oHeader.addValue( CADHeader::DIMTDEC, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 6
+        oHeader.addValue( CADHeader::DIMALTU, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 7
+        oHeader.addValue( CADHeader::DIMALTTD, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 8
+        oHeader.addValue( CADHeader::DIMAUNIT, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 9
+        oHeader.addValue( CADHeader::DIMFRAC, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 10
+        oHeader.addValue( CADHeader::DIMLUNIT, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 11
+        oHeader.addValue( CADHeader::DIMDSEP, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 12
+        oHeader.addValue( CADHeader::DIMTMOVE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );  // 13
+        oHeader.addValue( CADHeader::DIMJUST, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );   // 14
+
+        oHeader.addValue( CADHeader::DIMSD1, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMSD2, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMTOLJ, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMTZIN, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMALTZ, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMALTTZ, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMUPT, ReadBIT( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMATFIT, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMTXSTY, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMLDRBLK, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMBLK, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMBLK1, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMBLK2, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+
+        oHeader.addValue( CADHeader::DIMLWD, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::DIMLWE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+    } else
+    {
+        SkipTV( pabyBuf, nBitOffsetFromStart );
+        SkipTV( pabyBuf, nBitOffsetFromStart );
+
+        for( char i = 0; i < 9; ++i )
+            SkipBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+
+        nBitOffsetFromStart += 6;
+
+        for( char i = 0; i < 3; ++i )
+            SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+
+        for( char i = 0; i < 9; ++i )
+            SkipBITDOUBLE( pabyBuf, nBitOffsetFromStart );
+
+        nBitOffsetFromStart++;
+
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+
+        nBitOffsetFromStart += 4;
+
+        for( char i = 0; i < 14; ++i )
+            SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+
+        nBitOffsetFromStart += 2;
+
+        for( char i = 0; i < 4; ++i )
+            SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+
+        nBitOffsetFromStart++;
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+
+        for( char i = 0; i < 5; ++i )
+            SkipHANDLE( pabyBuf, nBitOffsetFromStart );
+
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+    }
+
+    CADHandle stBlocksTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::BlocksTable, stBlocksTable );
+
+    CADHandle stLayersTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::LayersTable, stLayersTable );
+
+    CADHandle stStyleTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::StyleTable, stStyleTable );
+
+    CADHandle stLineTypesTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::LineTypesTable, stLineTypesTable );
+
+    CADHandle stViewTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::ViewTable, stViewTable );
+
+    CADHandle stUCSTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::UCSTable, stUCSTable );
+
+    CADHandle stViewportTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::ViewportTable, stViewportTable );
+
+    CADHandle stAPPIDTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::APPIDTable, stAPPIDTable );
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        oHeader.addValue( CADHeader::DIMSTYLE, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+    } else
+    {
+        SkipHANDLE( pabyBuf, nBitOffsetFromStart );
+    }
+
+    CADHandle stEntityTable = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::EntityTable, stEntityTable );
+
+    CADHandle stACADGroupDict = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::ACADGroupDict, stACADGroupDict );
+
+    CADHandle stACADMLineStyleDict = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::ACADMLineStyleDict, stACADMLineStyleDict );
+
+    CADHandle stNamedObjectsDict = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::NamedObjectsDict, stNamedObjectsDict );
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        oHeader.addValue( CADHeader::TSTACKALIGN, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( CADHeader::TSTACKSIZE, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+    } else
+    {
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+    }
+
+    oHeader.addValue( CADHeader::HYPERLINKBASE, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::STYLESHEET, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+
+    CADHandle stLayoutsDict = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::LayoutsDict, stLayoutsDict );
+
+    CADHandle stPlotSettingsDict = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::PlotSettingsDict, stPlotSettingsDict );
+
+    CADHandle stPlotStylesDict = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::PlotStylesDict, stPlotStylesDict );
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        int Flags = ReadBITLONG( pabyBuf, nBitOffsetFromStart );
+        oHeader.addValue( CADHeader::CELWEIGHT, Flags & 0x001F );
+        oHeader.addValue( CADHeader::ENDCAPS, ( Flags & 0x0060 ) != 0 );
+        oHeader.addValue( CADHeader::JOINSTYLE, (Flags & 0x0180) != 0);
+        oHeader.addValue( CADHeader::LWDISPLAY, ( Flags & 0x0200 ) == 0);
+        oHeader.addValue( CADHeader::XEDIT, ( Flags & 0x0400 ) == 0);
+        oHeader.addValue( CADHeader::EXTNAMES, ( Flags & 0x0800 ) != 0 );
+        oHeader.addValue( CADHeader::PSTYLEMODE, ( Flags & 0x2000 ) != 0 );
+        oHeader.addValue( CADHeader::OLESTARTUP, ( Flags & 0x4000 ) != 0);
+    }
+    else
+    {
+        SkipBITLONG( pabyBuf, nBitOffsetFromStart );
+    }
+
+    oHeader.addValue( CADHeader::INSUNITS, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+    short nCEPSNTYPE = ReadBITSHORT( pabyBuf, nBitOffsetFromStart );
+    oHeader.addValue( CADHeader::CEPSNTYPE, nCEPSNTYPE );
+
+    if( nCEPSNTYPE == 3 )
+        oHeader.addValue( CADHeader::CEPSNID, ReadHANDLE( pabyBuf, nBitOffsetFromStart ) );
+
+    oHeader.addValue( CADHeader::FINGERPRINTGUID, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+    oHeader.addValue( CADHeader::VERSIONGUID, ReadTV( pabyBuf, nBitOffsetFromStart ) );
+
+    CADHandle stBlockRecordPaperSpace = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::BlockRecordPaperSpace, stBlockRecordPaperSpace );
+    // TODO: is this part of the header?
+    CADHandle stBlockRecordModelSpace = ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+    oTables.AddTable( CADTables::BlockRecordModelSpace, stBlockRecordModelSpace );
+
+    if( eOptions == OpenOptions::READ_ALL )
+    {
+        // Is this part of the header?
+
+        /*CADHandle LTYPE_BYLAYER = */ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+        /*CADHandle LTYPE_BYBLOCK = */ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+        /*CADHandle LTYPE_CONTINUOUS = */ReadHANDLE( pabyBuf, nBitOffsetFromStart );
+
+        oHeader.addValue( UNKNOWN11, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN12, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN13, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+        oHeader.addValue( UNKNOWN14, ReadBITSHORT( pabyBuf, nBitOffsetFromStart ) );
+    } else
+    {
+        SkipHANDLE( pabyBuf, nBitOffsetFromStart );
+        SkipHANDLE( pabyBuf, nBitOffsetFromStart );
+        SkipHANDLE( pabyBuf, nBitOffsetFromStart );
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+        SkipBITSHORT( pabyBuf, nBitOffsetFromStart );
+    }
+
+    int returnCode = CADErrorCodes::SUCCESS;
+    unsigned short dSectionCRC = validateEntityCRC( pabyBuf,
+        static_cast<unsigned int>(dHeaderVarsSectionLength + dSizeOfSectionSize),
+        nBitOffsetFromStart, "HEADERVARS" );
+
+    if(dSectionCRC == 0)
+    {
+        delete[] pabyBuf;
+        std::cerr << "File is corrupted (HEADERVARS section CRC doesn't match.)\n";
+        return CADErrorCodes::HEADER_SECTION_READ_FAILED;
+    }
+
+    pFileIO->Read( pabyBuf, DWGConstants::SentinelLength );
+    if( memcmp( pabyBuf, DWGConstants::HeaderVariablesEnd,
+                         DWGConstants::SentinelLength ) )
+    {
+        std::cerr << "File is corrupted (HEADERVARS section ending sentinel "
+                          "doesn't match.)\n";
+        returnCode = CADErrorCodes::HEADER_SECTION_READ_FAILED;
+    }
+
+    delete[] pabyBuf;
+    return returnCode;
+}
+
+int DWGFileR2000::ReadClasses( enum OpenOptions eOptions )
+{
+    if( eOptions == OpenOptions::READ_ALL || eOptions == OpenOptions::READ_FAST )
+    {
+        char   buffer[255];
+        size_t dSectionSize = 0;
+        const size_t dSizeOfSectionSize = 4;
+
+        pFileIO->Seek( sectionLocatorRecords[1].dSeeker, CADFileIO::SeekOrigin::BEG );
+
+        pFileIO->Read( buffer, DWGConstants::SentinelLength );
+        if( memcmp( buffer, DWGConstants::DSClassesStart,
+                            DWGConstants::SentinelLength ) )
+        {
+            std::cerr << "File is corrupted (wrong pointer to CLASSES section,"
+                    "or CLASSES starting sentinel corrupted.)\n";
+
+            return CADErrorCodes::CLASSES_SECTION_READ_FAILED;
+        }
+
+        pFileIO->Read( &dSectionSize, dSizeOfSectionSize );
+        DebugMsg( "Classes section length: %d\n",
+                  static_cast<int>(dSectionSize) );
+
+        char * pabySectionContent = new char[dSectionSize + dSizeOfSectionSize + 10]; // Add extra 10 bytes
+        memcpy (pabySectionContent, &dSectionSize, dSizeOfSectionSize);
+        memset (pabySectionContent + dSizeOfSectionSize, 0, dSectionSize + 10);
+        pFileIO->Read( pabySectionContent + dSizeOfSectionSize, dSectionSize + 2 );
+        size_t dBitOffsetFromStart = dSizeOfSectionSize * 8;
+        size_t dSectionBitSize = (dSectionSize + dSizeOfSectionSize) * 8;
+        while( dBitOffsetFromStart < dSectionBitSize - 8)
+        {
+            CADClass stClass;
+            stClass.dClassNum        = ReadBITSHORT( pabySectionContent,
+                                                     dBitOffsetFromStart );
+            stClass.dProxyCapFlag    = ReadBITSHORT( pabySectionContent,
+                                                     dBitOffsetFromStart );
+            stClass.sApplicationName = ReadTV( pabySectionContent,
+                                               dBitOffsetFromStart );
+            stClass.sCppClassName    = ReadTV( pabySectionContent,
+                                               dBitOffsetFromStart );
+            stClass.sDXFRecordName   = ReadTV( pabySectionContent,
+                                               dBitOffsetFromStart );
+            stClass.bWasZombie       = ReadBIT( pabySectionContent,
+                                                dBitOffsetFromStart );
+            stClass.bIsEntity        = ReadBITSHORT( pabySectionContent,
+                                                     dBitOffsetFromStart ) == 0x1F2;
+
+            oClasses.addClass( stClass );
+        }
+
+        dBitOffsetFromStart = dSectionBitSize;
+        unsigned short dSectionCRC = validateEntityCRC( pabySectionContent,
+                    static_cast<unsigned int>(dSectionSize + dSizeOfSectionSize),
+                    dBitOffsetFromStart, "CLASSES" );
+        delete[] pabySectionContent;
+
+        if(dSectionCRC == 0)
+        {
+            std::cerr << "File is corrupted (CLASSES section CRC doesn't match.)\n";
+            return CADErrorCodes::CLASSES_SECTION_READ_FAILED;
+        }
+
+        pFileIO->Read( buffer, DWGConstants::SentinelLength );
+        if( memcmp( buffer, DWGConstants::DSClassesEnd,
+                            DWGConstants::SentinelLength ) )
+        {
+            std::cerr << "File is corrupted (CLASSES section ending sentinel "
+                    "doesn't match.)\n";
+            return CADErrorCodes::CLASSES_SECTION_READ_FAILED;
+        }
+    }
+    return CADErrorCodes::SUCCESS;
+}
+
+int DWGFileR2000::CreateFileMap()
+{
+    // Seems like ODA specification is completely awful. CRC is included in section size.
+    // section size
+    size_t nSection = 0;
+
+    typedef pair<long, long> ObjHandleOffset;
+    ObjHandleOffset          previousObjHandleOffset;
+    ObjHandleOffset          tmpOffset;
+
+    mapObjects.clear();
+
+    // seek to the beginning of the objects map
+    pFileIO->Seek( sectionLocatorRecords[2].dSeeker, CADFileIO::SeekOrigin::BEG );
+
+    while( true )
+    {
+        unsigned short dSectionSize = 0;
+
+        // read section size
+        const size_t dSizeOfSectionSize = 2;
+        pFileIO->Read( &dSectionSize, dSizeOfSectionSize );
+        unsigned short dSectionSizeOriginal = dSectionSize;
+        SwapEndianness( dSectionSize, sizeof( dSectionSize ) );
+
+        DebugMsg( "Object map section #%d size: %d\n",
+                  static_cast<int>(++nSection), dSectionSize );
+
+        if( dSectionSize == dSizeOfSectionSize )
+            break; // last section is empty.
+
+        char * pabySectionContent  = new char[dSectionSize + dSizeOfSectionSize + 10]; // Add extra 10 bytes
+        memcpy(pabySectionContent, &dSectionSizeOriginal, dSizeOfSectionSize);
+        memset (pabySectionContent + dSizeOfSectionSize, 0, dSectionSize + 10);
+        size_t nRecordsInSection   = 0;
+
+        // read section datsa
+        pFileIO->Read( pabySectionContent + dSizeOfSectionSize, dSectionSize );
+        unsigned int dSectionBitSize = dSectionSize * 8;
+        size_t nBitOffsetFromStart = dSizeOfSectionSize * 8; // Skip section size from start
+
+        while( nBitOffsetFromStart < dSectionBitSize )
+        {
+            tmpOffset.first  = ReadUMCHAR( pabySectionContent, nBitOffsetFromStart ); // 8 + 8*8
+            tmpOffset.second = ReadMCHAR( pabySectionContent, nBitOffsetFromStart ); // 8 + 8*8
+
+            if( 0 == nRecordsInSection )
+            {
+                previousObjHandleOffset = tmpOffset;
+            }
+            else
+            {
+                previousObjHandleOffset.first += tmpOffset.first;
+                previousObjHandleOffset.second += tmpOffset.second;
+            }
+#ifdef _DEBUG
+            assert( mapObjects.find( previousObjHandleOffset.first ) ==
+                                                                mapObjects.end() );
+#endif //_DEBUG
+            mapObjects.insert( previousObjHandleOffset );
+            ++nRecordsInSection;
+        }
+
+        unsigned short dSectionCRC = validateEntityCRC( pabySectionContent,
+                    static_cast<unsigned int>(dSectionSize),
+                    nBitOffsetFromStart, "OBJECTMAP", true );
+        delete[] pabySectionContent;
+
+        if(dSectionCRC == 0)
+        {
+            std::cerr << "File is corrupted (OBJECTMAP section CRC doesn't match.)\n";
+            return CADErrorCodes::OBJECTS_SECTION_READ_FAILED;
+        }
+    }
+
+    return CADErrorCodes::SUCCESS;
+}
+
+CADObject * DWGFileR2000::GetObject( long dHandle, bool bHandlesOnly )
+{
+    char   pabyObjectSize[8];
+    size_t nBitOffsetFromStart = 0;
+    pFileIO->Seek( mapObjects[dHandle], CADFileIO::SeekOrigin::BEG );
+    pFileIO->Read( pabyObjectSize, 8 );
+    unsigned int dObjectSize = ReadMSHORT( pabyObjectSize, nBitOffsetFromStart );
+
+    // FIXME: Limit object size to 64kB
+    if( dObjectSize > 65536 )
+        return nullptr;
+
+    // And read whole data chunk into memory for future parsing.
+    // + nBitOffsetFromStart/8 + 2 is because dObjectSize doesn't cover CRC and itself.
+    dObjectSize += static_cast<unsigned int>(nBitOffsetFromStart / 8 + 2);
+    unique_ptr<char[]> sectionContentPtr( new char[dObjectSize + 64] ); // 64 is extra buffer size
+    char * pabySectionContent = sectionContentPtr.get();
+    pFileIO->Seek( mapObjects[dHandle], CADFileIO::SeekOrigin::BEG );
+    pFileIO->Read( pabySectionContent, static_cast<size_t>(dObjectSize) );
+
+    nBitOffsetFromStart = 0;
+    /* Unused dObjectSize = */ ReadMSHORT( pabySectionContent, nBitOffsetFromStart );
+    short dObjectType = ReadBITSHORT( pabySectionContent, nBitOffsetFromStart );
+    if( dObjectType >= 500 )
+    {
+        CADClass cadClass = oClasses.getClassByNum( dObjectType );
+        // FIXME: replace strcmp() with C++ analog
+        if( !strcmp( cadClass.sCppClassName.c_str(), "AcDbRasterImage" ) )
+        {
+            dObjectType = CADObject::IMAGE;
+        }
+        else if( !strcmp( cadClass.sCppClassName.c_str(), "AcDbRasterImageDef" ) )
+        {
+            dObjectType = CADObject::IMAGEDEF;
+        }
+        else if( !strcmp( cadClass.sCppClassName.c_str(), "AcDbRasterImageDefReactor" ) )
+        {
+            dObjectType = CADObject::IMAGEDEFREACTOR;
+        }
+        else if( !strcmp( cadClass.sCppClassName.c_str(), "AcDbWipeout" ) )
+        {
+            dObjectType = CADObject::WIPEOUT;
+        }
+    }
+
+    // Entities handling
+    if( isCommonEntityType( dObjectType ) )
+    {
+        struct CADCommonED stCommonEntityData; // common for all entities
+
+        stCommonEntityData.nObjectSizeInBits = ReadRAWLONG( pabySectionContent, nBitOffsetFromStart );
+        stCommonEntityData.hObjectHandle     = ReadHANDLE( pabySectionContent, nBitOffsetFromStart );
+
+        short  dEEDSize;
+        CADEed dwgEed;
+        while( ( dEEDSize = ReadBITSHORT( pabySectionContent, nBitOffsetFromStart ) ) != 0 )
+        {
+            dwgEed.dLength      = dEEDSize;
+            dwgEed.hApplication = ReadHANDLE( pabySectionContent, nBitOffsetFromStart );
+
+            for( short i = 0; i < dEEDSize; ++i )
+            {
+                dwgEed.acData.push_back( ReadCHAR( pabySectionContent, nBitOffsetFromStart ) );
+            }
+
+            stCommonEntityData.aEED.push_back( dwgEed );
+        }
+
+        stCommonEntityData.bGraphicsPresented = ReadBIT( pabySectionContent, nBitOffsetFromStart );
+        if( stCommonEntityData.bGraphicsPresented )
+        {
+            size_t nGraphicsDataSize = static_cast<size_t>(ReadRAWLONG( pabySectionContent, nBitOffsetFromStart ));
+            // skip read graphics data
+            nBitOffsetFromStart += nGraphicsDataSize * 8;
+        }
+        stCommonEntityData.bbEntMode        = Read2B( pabySectionContent, nBitOffsetFromStart );
+        stCommonEntityData.nNumReactors     = ReadBITLONG( pabySectionContent, nBitOffsetFromStart );
+        stCommonEntityData.bNoLinks         = ReadBIT( pabySectionContent, nBitOffsetFromStart );
+        stCommonEntityData.nCMColor         = ReadBITSHORT( pabySectionContent, nBitOffsetFromStart );
+        stCommonEntityData.dfLTypeScale     = ReadBITDOUBLE( pabySectionContent, nBitOffsetFromStart );
+        stCommonEntityData.bbLTypeFlags     = Read2B( pabySectionContent, nBitOffsetFromStart );
+        stCommonEntityData.bbPlotStyleFlags = Read2B( pabySectionContent, nBitOffsetFromStart );
+        stCommonEntityData.nInvisibility    = ReadBITSHORT( pabySectionContent, nBitOffsetFromStart );
+        stCommonEntityData.nLineWeight      = ReadCHAR( pabySectionContent, nBitOffsetFromStart );
+
+        // Skip entitity-specific data, we don't need it if bHandlesOnly == true
+        if( bHandlesOnly == true )
+        {
+            return getEntity( dObjectType, dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+        }
+
+        switch( dObjectType )
+        {
+            case CADObject::BLOCK:
+                return getBlock( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::ELLIPSE:
+                return getEllipse( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::MLINE:
+                return getMLine( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::SOLID:
+                return getSolid( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::POINT:
+                return getPoint( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::POLYLINE3D:
+                return getPolyLine3D( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::RAY:
+                return getRay( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::XLINE:
+                return getXLine( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::LINE:
+                return getLine( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::TEXT:
+                return getText( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::VERTEX3D:
+                return getVertex3D( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::CIRCLE:
+                return getCircle( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::ENDBLK:
+                return getEndBlock( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::POLYLINE2D:
+                return getPolyline2D( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::ATTRIB:
+                return getAttributes( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::ATTDEF:
+                return getAttributesDefn( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::LWPOLYLINE:
+                return getLWPolyLine( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::ARC:
+                return getArc( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::SPLINE:
+                return getSpline( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::POLYLINE_PFACE:
+                return getPolylinePFace( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::IMAGE:
+                return getImage( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::FACE3D:
+                return get3DFace( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::VERTEX_MESH:
+                return getVertexMesh( dObjectSize, stCommonEntityData, pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::VERTEX_PFACE:
+                return getVertexPFace( dObjectSize, stCommonEntityData,
+                                       pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::MTEXT:
+                return getMText( dObjectSize, stCommonEntityData,
+                                 pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::DIMENSION_RADIUS:
+            case CADObject::DIMENSION_DIAMETER:
+            case CADObject::DIMENSION_ALIGNED:
+            case CADObject::DIMENSION_ANG_3PT:
+            case CADObject::DIMENSION_ANG_2LN:
+            case CADObject::DIMENSION_ORDINATE:
+            case CADObject::DIMENSION_LINEAR:
+                return getDimension( dObjectType, dObjectSize, stCommonEntityData,
+                                     pabySectionContent, nBitOffsetFromStart );
+
+            case CADObject::INSERT:
+                return getInsert( dObjectType, dObjectSize, stCommonEntityData,
+                                  pabySectionContent,  nBitOffsetFromStart );
+
+            default:
+                return getEntity( dObjectType, dObjectSize, stCommonEntityData,
+                                  pabySectionContent, nBitOffsetFromStart );
+        }
+    }
+    else
+    {
+        switch( dObjectType )
+        {
+            case CADObject::DICTIONARY:
+                return getDictionary( dObjectSize, pabySectionContent,
+                                      nBitOffsetFromStart );
+
+            case CADObject::LAYER:
+                return getLayerObject( dObjectSize, pabySectionContent,
+                                       nBitOffsetFromStart );
+
+            case CADObject::LAYER_CONTROL_OBJ:
+                return getLayerControl( dObjectSize, pabySectionContent,
+                                        nBitOffsetFromStart );
+
+            case CADObject::BLOCK_CONTROL_OBJ:
+                return getBlockControl( dObjectSize, pabySectionContent,
+                                        nBitOffsetFromStart );
+
+            case CADObject::BLOCK_HEADER:
+                return getBlockHeader( dObjectSize, pabySectionContent,
+                                       nBitOffsetFromStart );
+
+            case CADObject::LTYPE_CONTROL_OBJ:
+                return getLineTypeControl( dObjectSize, pabySectionContent,
+                                           nBitOffsetFromStart );
+
+            case CADObject::LTYPE1:
+                return getLineType1( dObjectSize, pabySectionContent,
+                                     nBitOffsetFromStart );
+
+            case CADObject::IMAGEDEF:
+                return getImageDef( dObjectSize, pabySectionContent,
+                                    nBitOffsetFromStart );
+
+            case CADObject::IMAGEDEFREACTOR:
+                return getImageDefReactor( dObjectSize, pabySectionContent,
+                                           nBitOffsetFromStart );
+
+            case CADObject::XRECORD:
+                return getXRecord( dObjectSize, pabySectionContent,
+                                   nBitOffsetFromStart );
+        }
+    }
+
+    return nullptr;
+}
+
+CADGeometry * DWGFileR2000::GetGeometry( size_t iLayerIndex, long dHandle, long dBlockRefHandle )
+{
+    CADGeometry * poGeometry = nullptr;
+    unique_ptr<CADEntityObject> readedObject( static_cast<CADEntityObject *>(GetObject( dHandle )) );
+
+    if( nullptr == readedObject )
+        return nullptr;
+
+    switch( readedObject->getType() )
+    {
+        case CADObject::ARC:
+        {
+            CADArc       * arc    = new CADArc();
+            CADArcObject * cadArc = static_cast<CADArcObject *>(
+                    readedObject.get());
+
+            arc->setPosition( cadArc->vertPosition );
+            arc->setExtrusion( cadArc->vectExtrusion );
+            arc->setRadius( cadArc->dfRadius );
+            arc->setThickness( cadArc->dfThickness );
+            arc->setStartingAngle( cadArc->dfStartAngle );
+            arc->setEndingAngle( cadArc->dfEndAngle );
+
+            poGeometry = arc;
+            break;
+        }
+
+        case CADObject::POINT:
+        {
+            CADPoint3D     * point    = new CADPoint3D();
+            CADPointObject * cadPoint = static_cast<CADPointObject *>(
+                    readedObject.get());
+
+            point->setPosition( cadPoint->vertPosition );
+            point->setExtrusion( cadPoint->vectExtrusion );
+            point->setXAxisAng( cadPoint->dfXAxisAng );
+            point->setThickness( cadPoint->dfThickness );
+
+            poGeometry = point;
+            break;
+        }
+
+        case CADObject::POLYLINE3D:
+        {
+            CADPolyline3D       * polyline               = new CADPolyline3D();
+            CADPolyline3DObject * cadPolyline3D          = static_cast<CADPolyline3DObject *>(
+                    readedObject.get());
+
+            // TODO: code can be much simplified if CADHandle will be used.
+            // to do so, == and ++ operators should be implemented.
+            unique_ptr<CADVertex3DObject> vertex;
+            long                          currentVertexH = cadPolyline3D->hVertexes[0].getAsLong();
+            while( currentVertexH != 0 )
+            {
+                vertex.reset( static_cast<CADVertex3DObject *>(
+                                      GetObject( currentVertexH )) );
+
+                if( vertex == nullptr )
+                    break;
+
+                currentVertexH = vertex->stCed.hObjectHandle.getAsLong();
+                polyline->addVertex( vertex->vertPosition );
+                if( vertex->stCed.bNoLinks == true )
+                {
+                    ++currentVertexH;
+                } else
+                {
+                    currentVertexH = vertex->stChed.hNextEntity.getAsLong( vertex->stCed.hObjectHandle );
+                }
+
+                // Last vertex is reached. read it and break reading.
+                if( currentVertexH == cadPolyline3D->hVertexes[1].getAsLong() )
+                {
+                    vertex.reset( static_cast<CADVertex3DObject *>(
+                                          GetObject( currentVertexH )) );
+                    polyline->addVertex( vertex->vertPosition );
+                    break;
+                }
+            }
+
+            poGeometry = polyline;
+            break;
+        }
+
+        case CADObject::LWPOLYLINE:
+        {
+            CADLWPolyline       * lwPolyline    = new CADLWPolyline();
+            CADLWPolylineObject * cadlwPolyline = static_cast<CADLWPolylineObject *>(
+                    readedObject.get());
+
+            lwPolyline->setBulges( cadlwPolyline->adfBulges );
+            lwPolyline->setClosed( cadlwPolyline->bClosed );
+            lwPolyline->setConstWidth( cadlwPolyline->dfConstWidth );
+            lwPolyline->setElevation( cadlwPolyline->dfElevation );
+            for( const CADVector& vertex : cadlwPolyline->avertVertexes )
+                lwPolyline->addVertex( vertex );
+            lwPolyline->setVectExtrusion( cadlwPolyline->vectExtrusion );
+            lwPolyline->setWidths( cadlwPolyline->astWidths );
+
+            poGeometry = lwPolyline;
+            break;
+        }
+
+        case CADObject::CIRCLE:
+        {
+            CADCircle       * circle    = new CADCircle();
+            CADCircleObject * cadCircle = static_cast<CADCircleObject *>(
+                    readedObject.get());
+
+            circle->setPosition( cadCircle->vertPosition );
+            circle->setExtrusion( cadCircle->vectExtrusion );
+            circle->setRadius( cadCircle->dfRadius );
+            circle->setThickness( cadCircle->dfThickness );
+
+            poGeometry = circle;
+            break;
+        }
+
+        case CADObject::ATTRIB:
+        {
+            CADAttrib       * attrib    = new CADAttrib();
+            CADAttribObject * cadAttrib = static_cast<CADAttribObject *>(
+                    readedObject.get() );
+
+            attrib->setPosition( cadAttrib->vertInsetionPoint );
+            attrib->setExtrusion( cadAttrib->vectExtrusion );
+            attrib->setRotationAngle( cadAttrib->dfRotationAng );
+            attrib->setAlignmentPoint( cadAttrib->vertAlignmentPoint );
+            attrib->setElevation( cadAttrib->dfElevation );
+            attrib->setHeight( cadAttrib->dfHeight );
+            attrib->setObliqueAngle( cadAttrib->dfObliqueAng );
+            attrib->setPositionLocked( cadAttrib->bLockPosition );
+            attrib->setTag( cadAttrib->sTag );
+            attrib->setTextValue( cadAttrib->sTextValue );
+            attrib->setThickness( cadAttrib->dfThickness );
+
+            poGeometry = attrib;
+            break;
+        }
+
+        case CADObject::ATTDEF:
+        {
+            CADAttdef * attdef = new CADAttdef();
+            CADAttdefObject * cadAttrib = static_cast<CADAttdefObject*>(
+                    readedObject.get() );
+
+            attdef->setPosition( cadAttrib->vertInsetionPoint );
+            attdef->setExtrusion( cadAttrib->vectExtrusion );
+            attdef->setRotationAngle( cadAttrib->dfRotationAng );
+            attdef->setAlignmentPoint( cadAttrib->vertAlignmentPoint );
+            attdef->setElevation( cadAttrib->dfElevation );
+            attdef->setHeight( cadAttrib->dfHeight );
+            attdef->setObliqueAngle( cadAttrib->dfObliqueAng );
+            attdef->setPositionLocked( cadAttrib->bLockPosition );
+            attdef->setTag( cadAttrib->sTag );
+            attdef->setTextValue( cadAttrib->sTextValue );
+            attdef->setThickness( cadAttrib->dfThickness );
+            attdef->setPrompt( cadAttrib->sPrompt );
+
+            poGeometry = attdef;
+            break;
+        }
+
+        case CADObject::ELLIPSE:
+        {
+            CADEllipse       * ellipse    = new CADEllipse();
+            CADEllipseObject * cadEllipse = static_cast<CADEllipseObject *>(
+                    readedObject.get());
+
+            ellipse->setPosition( cadEllipse->vertPosition );
+            ellipse->setSMAxis( cadEllipse->vectSMAxis );
+            ellipse->setAxisRatio( cadEllipse->dfAxisRatio );
+            ellipse->setEndingAngle( cadEllipse->dfEndAngle );
+            ellipse->setStartingAngle( cadEllipse->dfBegAngle );
+
+            poGeometry = ellipse;
+            break;
+        }
+
+        case CADObject::LINE:
+        {
+            CADLineObject * cadLine = static_cast<CADLineObject *>(
+                    readedObject.get());
+
+            CADPoint3D ptBeg( cadLine->vertStart, cadLine->dfThickness );
+            CADPoint3D ptEnd( cadLine->vertEnd, cadLine->dfThickness );
+
+            CADLine * line = new CADLine( ptBeg, ptEnd );
+
+            poGeometry = line;
+            break;
+        }
+
+        case CADObject::RAY:
+        {
+            CADRay       * ray    = new CADRay();
+            CADRayObject * cadRay = static_cast<CADRayObject *>(
+                    readedObject.get());
+
+            ray->setVectVector( cadRay->vectVector );
+            ray->setPosition( cadRay->vertPosition );
+
+            poGeometry = ray;
+            break;
+        }
+
+        case CADObject::SPLINE:
+        {
+            CADSpline       * spline    = new CADSpline();
+            CADSplineObject * cadSpline = static_cast<CADSplineObject *>(
+                    readedObject.get());
+
+            spline->setScenario( cadSpline->dScenario );
+            spline->setDegree( cadSpline->dDegree );
+            if( spline->getScenario() == 2 )
+            {
+                spline->setFitTollerance( cadSpline->dfFitTol );
+            } else if( spline->getScenario() == 1 )
+            {
+                spline->setRational( cadSpline->bRational );
+                spline->setClosed( cadSpline->bClosed );
+                spline->setWeight( cadSpline->bWeight );
+            }
+            for( double weight : cadSpline->adfCtrlPointsWeight )
+                spline->addControlPointsWeight( weight );
+
+            for( const CADVector& pt : cadSpline->averFitPoints )
+                spline->addFitPoint( pt );
+
+            for( const CADVector& pt : cadSpline->avertCtrlPoints )
+                spline->addControlPoint( pt );
+
+            poGeometry = spline;
+            break;
+        }
+
+        case CADObject::TEXT:
+        {
+            CADText       * text    = new CADText();
+            CADTextObject * cadText = static_cast<CADTextObject *>(
+                    readedObject.get());
+
+            text->setPosition( cadText->vertInsetionPoint );
+            text->setTextValue( cadText->sTextValue );
+            text->setRotationAngle( cadText->dfRotationAng );
+            text->setObliqueAngle( cadText->dfObliqueAng );
+            text->setThickness( cadText->dfThickness );
+            text->setHeight( cadText->dfElevation );
+
+            poGeometry = text;
+            break;
+        }
+
+        case CADObject::SOLID:
+        {
+            CADSolid       * solid    = new CADSolid();
+            CADSolidObject * cadSolid = static_cast<CADSolidObject *>(
+                    readedObject.get());
+
+            solid->setElevation( cadSolid->dfElevation );
+            solid->setThickness( cadSolid->dfThickness );
+            for( const CADVector& corner : cadSolid->avertCorners )
+                solid->addCorner( corner );
+            solid->setExtrusion( cadSolid->vectExtrusion );
+
+            poGeometry = solid;
+            break;
+        }
+
+        case CADObject::IMAGE:
+        {
+            CADImage       * image    = new CADImage();
+            CADImageObject * cadImage = static_cast<CADImageObject *>(
+                    readedObject.get());
+
+            unique_ptr<CADImageDefObject> cadImageDef(
+                static_cast<CADImageDefObject *>( GetObject(
+                    cadImage->hImageDef.getAsLong() ) ) );
+
+
+            image->setClippingBoundaryType( cadImage->dClipBoundaryType );
+            image->setFilePath( cadImageDef->sFilePath );
+            image->setVertInsertionPoint( cadImage->vertInsertion );
+            CADVector imageSize( cadImage->dfSizeX, cadImage->dfSizeY );
+            image->setImageSize( imageSize );
+            CADVector imageSizeInPx( cadImageDef->dfXImageSizeInPx, cadImageDef->dfYImageSizeInPx );
+            image->setImageSizeInPx( imageSizeInPx );
+            CADVector pixelSizeInACADUnits( cadImageDef->dfXPixelSize, cadImageDef->dfYPixelSize );
+            image->setPixelSizeInACADUnits( pixelSizeInACADUnits );
+            image->setResolutionUnits(
+                static_cast<CADImage::ResolutionUnit>( cadImageDef->dResUnits ) );
+            bool bTransparency = (cadImage->dDisplayProps & 0x08) != 0;
+            image->setOptions( bTransparency,
+                               cadImage->bClipping,
+                               cadImage->dBrightness,
+                               cadImage->dContrast );
+            for( const CADVector& clipPt : cadImage->avertClippingPolygonVertexes )
+            {
+                image->addClippingPoint( clipPt );
+            }
+
+            poGeometry = image;
+            break;
+        }
+
+        case CADObject::MLINE:
+        {
+            CADMLine       * mline    = new CADMLine();
+            CADMLineObject * cadmLine = static_cast<CADMLineObject *>(
+                    readedObject.get());
+
+            mline->setScale( cadmLine->dfScale );
+            mline->setOpened( cadmLine->dOpenClosed == 1 ? true : false );
+            for( const CADMLineVertex& vertex : cadmLine->avertVertexes )
+                mline->addVertex( vertex.vertPosition );
+
+            poGeometry = mline;
+            break;
+        }
+
+        case CADObject::MTEXT:
+        {
+            CADMText       * mtext    = new CADMText();
+            CADMTextObject * cadmText = static_cast<CADMTextObject *>(
+                    readedObject.get());
+
+            mtext->setTextValue( cadmText->sTextValue );
+            mtext->setXAxisAng( cadmText->vectXAxisDir.getX() ); //TODO: is this needed?
+
+            mtext->setPosition( cadmText->vertInsertionPoint );
+            mtext->setExtrusion( cadmText->vectExtrusion );
+
+            mtext->setHeight( cadmText->dfTextHeight );
+            mtext->setRectWidth( cadmText->dfRectWidth );
+            mtext->setExtents( cadmText->dfExtents );
+            mtext->setExtentsWidth( cadmText->dfExtentsWidth );
+
+            poGeometry = mtext;
+            break;
+        }
+
+        case CADObject::POLYLINE_PFACE:
+        {
+            CADPolylinePFace       * polyline                  = new CADPolylinePFace();
+            CADPolylinePFaceObject * cadpolyPface              = static_cast<CADPolylinePFaceObject *>(
+                    readedObject.get());
+
+            // TODO: code can be much simplified if CADHandle will be used.
+            // to do so, == and ++ operators should be implemented.
+            unique_ptr<CADVertexPFaceObject> vertex;
+            auto                             dCurrentEntHandle = cadpolyPface->hVertexes[0].getAsLong();
+            auto                             dLastEntHandle    = cadpolyPface->hVertexes[1].getAsLong();
+            while( true )
+            {
+                vertex.reset( static_cast<CADVertexPFaceObject *>(
+                                      GetObject( dCurrentEntHandle )) );
+                /* TODO: this check is excessive, but if something goes wrong way -
+             * some part of geometries will be parsed. */
+                if( vertex == nullptr )
+                    continue;
+
+                polyline->addVertex( vertex->vertPosition );
+
+                /* FIXME: somehow one more vertex which isnot presented is read.
+             * so, checking the number of added vertexes */
+                /*TODO: is this needed - check on real data
+            if ( polyline->hVertexes.size() == cadpolyPface->nNumVertexes )
+            {
+                delete( vertex );
+                break;
+            }*/
+
+                if( vertex->stCed.bNoLinks )
+                    ++dCurrentEntHandle;
+                else
+                    dCurrentEntHandle = vertex->stChed.hNextEntity.getAsLong( vertex->stCed.hObjectHandle );
+
+                if( dCurrentEntHandle == dLastEntHandle )
+                {
+                    vertex.reset( static_cast<CADVertexPFaceObject *>(
+                                          GetObject( dCurrentEntHandle )) );
+                    polyline->addVertex( vertex->vertPosition );
+                    break;
+                }
+            }
+
+            poGeometry = polyline;
+            break;
+        }
+
+        case CADObject::XLINE:
+        {
+            CADXLine       * xline    = new CADXLine();
+            CADXLineObject * cadxLine = static_cast<CADXLineObject *>(
+                    readedObject.get());
+
+            xline->setVectVector( cadxLine->vectVector );
+            xline->setPosition( cadxLine->vertPosition );
+
+            poGeometry = xline;
+            break;
+        }
+
+        case CADObject::FACE3D:
+        {
+            CADFace3D       * face      = new CADFace3D();
+            CAD3DFaceObject * cad3DFace = static_cast<CAD3DFaceObject *>(
+                    readedObject.get());
+
+            for( const CADVector& corner : cad3DFace->avertCorners )
+                face->addCorner( corner );
+            face->setInvisFlags( cad3DFace->dInvisFlags );
+
+            poGeometry = face;
+            break;
+        }
+
+        case CADObject::POLYLINE_MESH:
+        case CADObject::VERTEX_MESH:
+        case CADObject::VERTEX_PFACE_FACE:
+        default:
+            std::cerr << "Asked geometry has unsupported type." << endl;
+            poGeometry = new CADUnknown();
+            break;
+    }
+
+    if( poGeometry == nullptr )
+        return nullptr;
+
+    // Applying color
+    if( readedObject->stCed.nCMColor == 256 ) // BYLAYER CASE
+    {
+        CADLayer& oCurrentLayer = this->GetLayer( iLayerIndex );
+        poGeometry->setColor( getCADACIColor( oCurrentLayer.getColor() ) );
+    }
+    else if( readedObject->stCed.nCMColor <= 255 &&
+             readedObject->stCed.nCMColor >= 0 ) // Excessive check until BYBLOCK case will not be implemented
+    {
+        poGeometry->setColor( getCADACIColor( readedObject->stCed.nCMColor ) );
+    }
+
+    // Applying EED
+    // Casting object's EED to a vector of strings
+    vector<string> asEED;
+    for( auto citer = readedObject->stCed.aEED.cbegin();
+         citer != readedObject->stCed.aEED.cend(); ++citer )
+    {
+        string sEED = "";
+        // Detect the type of EED entity
+        switch( citer->acData[0] )
+        {
+            case 0: // string
+            {
+                unsigned char nStrSize = citer->acData[1];
+                // +2 = skip CodePage, no idea how to use it anyway
+                for( size_t   i        = 0; i < nStrSize; ++i )
+                {
+                    sEED += citer->acData[i + 4];
+                }
+                break;
+            }
+            case 1: // invalid
+            {
+                DebugMsg( "Error: EED obj type is 1, error in R2000::getGeometry()" );
+                break;
+            }
+            case 2: // { or }
+            {
+                sEED += citer->acData[1] == 0 ? '{' : '}';
+                break;
+            }
+            case 3: // layer table ref
+            {
+                // FIXME: get CADHandle and return getAsLong() result.
+                sEED += "Layer table ref (handle):";
+                for( size_t i = 0; i < 8; ++i )
+                {
+                    sEED += citer->acData[i + 1];
+                }
+                break;
+            }
+            case 4: // binary chunk
+            {
+                unsigned char nChunkSize = citer->acData[1];
+                sEED += "Binary chunk (chars):";
+                for( size_t i = 0; i < nChunkSize; ++i )
+                {
+                    sEED += citer->acData[i + 2];
+                }
+                break;
+            }
+            case 5: // entity handle ref
+            {
+                // FIXME: get CADHandle and return getAsLong() result.
+                sEED += "Entity handle ref (handle):";
+                for( size_t i = 0; i < 8; ++i )
+                {
+                    sEED += citer->acData[i + 1];
+                }
+                break;
+            }
+            case 10:
+            case 11:
+            case 12:
+            case 13:
+            {
+                sEED += "Point: {";
+                double dfX = 0, dfY = 0, dfZ = 0;
+                memcpy( & dfX, citer->acData.data() + 1, 8 );
+                memcpy( & dfY, citer->acData.data() + 9, 8 );
+                memcpy( & dfZ, citer->acData.data() + 17, 8 );
+                sEED += to_string( dfX );
+                sEED += ';';
+                sEED += to_string( dfY );
+                sEED += ';';
+                sEED += to_string( dfZ );
+                sEED += '}';
+                break;
+            }
+            case 40:
+            case 41:
+            case 42:
+            {
+                sEED += "Double:";
+                double dfVal = 0;
+                memcpy( & dfVal, citer->acData.data() + 1, 8 );
+                sEED += to_string( dfVal );
+                break;
+            }
+            case 70:
+            {
+                sEED += "Short:";
+                short dVal = 0;
+                memcpy( & dVal, citer->acData.data() + 1, 2 );
+                sEED += to_string( dVal );
+                break;
+            }
+            case 71:
+            {
+                sEED += "Long Int:";
+                long dVal = 0;
+                memcpy( & dVal, citer->acData.data() + 1, 4 );
+                sEED += to_string( dVal );
+                break;
+            }
+            default:
+            {
+                DebugMsg( "Error in parsing geometry EED: undefined typecode: %d",
+                          static_cast<int>(citer->acData[0]) );
+            }
+        }
+        asEED.emplace_back( sEED );
+    }
+
+    // Getting block reference attributes.
+    if( dBlockRefHandle != 0 )
+    {
+        vector<CADAttrib>           blockRefAttributes;
+        unique_ptr<CADInsertObject> spoBlockRef( static_cast<CADInsertObject *>( GetObject( dBlockRefHandle ) ) );
+
+        if( !spoBlockRef->hAttribs.empty() )
+        {
+            long dCurrentEntHandle = spoBlockRef->hAttribs[0].getAsLong();
+            long dLastEntHandle    = spoBlockRef->hAttribs[0].getAsLong();
+
+            while( spoBlockRef->bHasAttribs )
+            {
+                // FIXME: memory leak, somewhere in CAD* destructor is a bug
+                CADEntityObject * attDefObj = static_cast<CADEntityObject *>(
+                        GetObject( dCurrentEntHandle, true ) );
+
+                if( dCurrentEntHandle == dLastEntHandle )
+                {
+                    if( attDefObj == nullptr )
+                        break;
+
+                    CADAttrib * attrib = static_cast<CADAttrib *>(
+                            GetGeometry( iLayerIndex, dCurrentEntHandle ) );
+
+                    if( attrib )
+                    {
+                        blockRefAttributes.push_back( CADAttrib( * attrib ) );
+                        delete attrib;
+                    }
+                    delete attDefObj;
+                    break;
+                }
+
+                if( attDefObj != nullptr )
+                {
+                    if( attDefObj->stCed.bNoLinks )
+                        ++dCurrentEntHandle;
+                    else
+                        dCurrentEntHandle = attDefObj->stChed.hNextEntity.getAsLong( attDefObj->stCed.hObjectHandle );
+
+                    CADAttrib * attrib = static_cast<CADAttrib *>(
+                            GetGeometry( iLayerIndex, dCurrentEntHandle ) );
+
+                    if( attrib )
+                    {
+                        blockRefAttributes.push_back( CADAttrib( * attrib ) );
+                        delete attrib;
+                    }
+                    delete attDefObj;
+                } else
+                {
+                    assert ( 0 );
+                }
+            }
+            poGeometry->setBlockAttributes( blockRefAttributes );
+        }
+    }
+
+    poGeometry->setEED( asEED );
+    return poGeometry;
+}
+
+CADBlockObject * DWGFileR2000::getBlock(unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                         const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADBlockObject * pBlock = new CADBlockObject();
+
+    pBlock->setSize( dObjectSize );
+    pBlock->stCed = stCommonEntityData;
+
+    pBlock->sBlockName = ReadTV( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( pBlock, pabyInput, nBitOffsetFromStart );
+
+    pBlock->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "BLOCK" ) );
+
+    return pBlock;
+}
+
+CADEllipseObject * DWGFileR2000::getEllipse(unsigned int dObjectSize,
+                                            const CADCommonED& stCommonEntityData,
+                                            const char * pabyInput,
+                                            size_t& nBitOffsetFromStart )
+{
+    CADEllipseObject * ellipse = new CADEllipseObject();
+
+    ellipse->setSize( dObjectSize );
+    ellipse->stCed = stCommonEntityData;
+
+    CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );
+
+    ellipse->vertPosition = vertPosition;
+
+    CADVector vectSMAxis = ReadVector( pabyInput, nBitOffsetFromStart );
+
+    ellipse->vectSMAxis = vectSMAxis;
+
+    CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+
+    ellipse->vectExtrusion = vectExtrusion;
+
+    ellipse->dfAxisRatio = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    ellipse->dfBegAngle  = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    ellipse->dfEndAngle  = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( ellipse, pabyInput, nBitOffsetFromStart );
+
+    ellipse->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                        nBitOffsetFromStart, "ELLIPSE" ) );
+
+    return ellipse;
+}
+
+CADSolidObject * DWGFileR2000::getSolid(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                         size_t& nBitOffsetFromStart )
+{
+    CADSolidObject * solid = new CADSolidObject();
+
+    solid->setSize( dObjectSize );
+    solid->stCed = stCommonEntityData;
+
+    solid->dfThickness = ReadBIT( pabyInput, nBitOffsetFromStart ) ? 0.0f : ReadBITDOUBLE( pabyInput,
+                                                                                           nBitOffsetFromStart );
+
+    solid->dfElevation = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    CADVector   oCorner;
+    for( size_t i      = 0; i < 4; ++i )
+    {
+        oCorner.setX( ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart ) );
+        oCorner.setY( ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart ) );
+        solid->avertCorners.push_back( oCorner );
+    }
+
+    if( ReadBIT( pabyInput, nBitOffsetFromStart ) )
+    {
+        solid->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
+    } else
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        solid->vectExtrusion = vectExtrusion;
+    }
+
+
+    fillCommonEntityHandleData( solid, pabyInput, nBitOffsetFromStart );
+
+    solid->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                      nBitOffsetFromStart, "SOLID" ) );
+
+    return solid;
+}
+
+CADPointObject * DWGFileR2000::getPoint(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                         size_t& nBitOffsetFromStart )
+{
+    CADPointObject * point = new CADPointObject();
+
+    point->setSize( dObjectSize );
+    point->stCed = stCommonEntityData;
+
+    CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );
+
+    point->vertPosition = vertPosition;
+
+    point->dfThickness = ReadBIT( pabyInput, nBitOffsetFromStart ) ? 0.0f : ReadBITDOUBLE( pabyInput,
+                                                                                           nBitOffsetFromStart );
+
+    if( ReadBIT( pabyInput, nBitOffsetFromStart ) )
+    {
+        point->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
+    } else
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        point->vectExtrusion = vectExtrusion;
+    }
+
+    point->dfXAxisAng = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( point, pabyInput, nBitOffsetFromStart );
+
+    point->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                      nBitOffsetFromStart, "POINT" ) );
+
+    return point;
+}
+
+CADPolyline3DObject * DWGFileR2000::getPolyLine3D(unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                                   const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADPolyline3DObject * polyline = new CADPolyline3DObject();
+
+    polyline->setSize( dObjectSize );
+    polyline->stCed = stCommonEntityData;
+
+    polyline->SplinedFlags = ReadCHAR( pabyInput, nBitOffsetFromStart );
+    polyline->ClosedFlags  = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( polyline, pabyInput, nBitOffsetFromStart );
+
+    polyline->hVertexes.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) ); // 1st vertex
+    polyline->hVertexes.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) ); // last vertex
+
+    polyline->hSeqend = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    nBitOffsetFromStart = (dObjectSize - 2) * 8;
+    polyline->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                         nBitOffsetFromStart, "POLYLINE" ) );
+
+    return polyline;
+}
+
+CADRayObject * DWGFileR2000::getRay(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                     size_t& nBitOffsetFromStart )
+{
+    CADRayObject * ray = new CADRayObject();
+
+    ray->setSize( dObjectSize );
+    ray->stCed = stCommonEntityData;
+
+    CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );
+
+    ray->vertPosition = vertPosition;
+
+    CADVector vectVector = ReadVector( pabyInput, nBitOffsetFromStart );
+    ray->vectVector = vectVector;
+
+    fillCommonEntityHandleData( ray, pabyInput, nBitOffsetFromStart );
+
+    ray->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                    nBitOffsetFromStart, "RAY" ) );
+
+    return ray;
+}
+
+CADXLineObject * DWGFileR2000::getXLine(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                         size_t& nBitOffsetFromStart )
+{
+    CADXLineObject * xline = new CADXLineObject();
+
+    xline->setSize( dObjectSize );
+    xline->stCed = stCommonEntityData;
+
+    CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );
+
+    xline->vertPosition = vertPosition;
+
+    CADVector vectVector = ReadVector( pabyInput, nBitOffsetFromStart );
+    xline->vectVector = vectVector;
+
+    fillCommonEntityHandleData( xline, pabyInput, nBitOffsetFromStart );
+
+    xline->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                      nBitOffsetFromStart, "XLINE" ) );
+
+    return xline;
+}
+
+CADLineObject * DWGFileR2000::getLine(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                       size_t& nBitOffsetFromStart )
+{
+    CADLineObject * line = new CADLineObject();
+
+    line->setSize( dObjectSize );
+    line->stCed = stCommonEntityData;
+
+    bool bZsAreZeros = ReadBIT( pabyInput, nBitOffsetFromStart );
+
+    CADVector vertStart, vertEnd;
+    vertStart.setX( ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart ) );
+    vertEnd.setX( ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, vertStart.getX() ) );
+    vertStart.setY( ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart ) );
+    vertEnd.setY( ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, vertStart.getY() ) );
+
+    if( !bZsAreZeros )
+    {
+        vertStart.setZ( ReadBITDOUBLE( pabyInput, nBitOffsetFromStart ) );
+        vertEnd.setZ( ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, vertStart.getZ() ) );
+    }
+
+    line->vertStart = vertStart;
+    line->vertEnd   = vertEnd;
+
+    line->dfThickness = ReadBIT( pabyInput, nBitOffsetFromStart ) ? 0.0f : ReadBITDOUBLE( pabyInput,
+                                                                                          nBitOffsetFromStart );
+
+    if( ReadBIT( pabyInput, nBitOffsetFromStart ) )
+    {
+        line->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
+    } else
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        line->vectExtrusion = vectExtrusion;
+    }
+
+    fillCommonEntityHandleData( line, pabyInput, nBitOffsetFromStart );
+
+    nBitOffsetFromStart = (dObjectSize - 2) * 8;
+    line->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                     nBitOffsetFromStart, "LINE" ) );
+    return line;
+}
+
+CADTextObject * DWGFileR2000::getText(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                       size_t& nBitOffsetFromStart )
+{
+    CADTextObject * text = new CADTextObject();
+
+    text->setSize( dObjectSize );
+    text->stCed = stCommonEntityData;
+
+    text->DataFlags = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    if( !( text->DataFlags & 0x01 ) )
+        text->dfElevation = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    CADVector vertInsetionPoint = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+
+    text->vertInsetionPoint = vertInsetionPoint;
+
+    if( !( text->DataFlags & 0x02 ) )
+    {
+        double x, y;
+        x = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, vertInsetionPoint.getX() );
+        y = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, vertInsetionPoint.getY() );
+        CADVector vertAlignmentPoint( x, y );
+        text->vertAlignmentPoint = vertAlignmentPoint;
+    }
+
+    if( ReadBIT( pabyInput, nBitOffsetFromStart ) )
+    {
+        text->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
+    } else
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        text->vectExtrusion = vectExtrusion;
+    }
+
+    text->dfThickness = ReadBIT( pabyInput, nBitOffsetFromStart ) ? 0.0f : ReadBITDOUBLE( pabyInput,
+                                                                                          nBitOffsetFromStart );
+
+    if( !( text->DataFlags & 0x04 ) )
+        text->dfObliqueAng  = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    if( !( text->DataFlags & 0x08 ) )
+        text->dfRotationAng = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    text->dfHeight = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    if( !( text->DataFlags & 0x10 ) )
+        text->dfWidthFactor = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    text->sTextValue = ReadTV( pabyInput, nBitOffsetFromStart );
+
+    if( !( text->DataFlags & 0x20 ) )
+        text->dGeneration = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    if( !( text->DataFlags & 0x40 ) )
+        text->dHorizAlign = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    if( !( text->DataFlags & 0x80 ) )
+        text->dVertAlign  = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( text, pabyInput, nBitOffsetFromStart );
+
+    text->hStyle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    text->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                     nBitOffsetFromStart, "TEXT" ) );
+
+    return text;
+}
+
+CADVertex3DObject * DWGFileR2000::getVertex3D(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                               size_t& nBitOffsetFromStart )
+{
+    CADVertex3DObject * vertex = new CADVertex3DObject();
+
+    vertex->setSize( dObjectSize );
+    vertex->stCed = stCommonEntityData;
+
+    /*unsigned char Flags = */ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );;
+    vertex->vertPosition = vertPosition;
+
+    fillCommonEntityHandleData( vertex, pabyInput, nBitOffsetFromStart );
+
+    nBitOffsetFromStart = (dObjectSize - 2) * 8;
+    vertex->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "VERTEX" ) );
+    return vertex;
+}
+
+CADCircleObject * DWGFileR2000::getCircle(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                           size_t& nBitOffsetFromStart )
+{
+    CADCircleObject * circle = new CADCircleObject();
+
+    circle->setSize( dObjectSize );
+    circle->stCed = stCommonEntityData;
+
+    CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );
+    circle->vertPosition = vertPosition;
+    circle->dfRadius     = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    circle->dfThickness  = ReadBIT( pabyInput, nBitOffsetFromStart ) ? 0.0f : ReadBITDOUBLE( pabyInput,
+                                                                                             nBitOffsetFromStart );
+
+    if( ReadBIT( pabyInput, nBitOffsetFromStart ) )
+    {
+        circle->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
+    } else
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        circle->vectExtrusion = vectExtrusion;
+    }
+
+    fillCommonEntityHandleData( circle, pabyInput, nBitOffsetFromStart );
+
+    nBitOffsetFromStart = (dObjectSize - 2) * 8;
+    circle->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "CIRCLE" ) );
+    return circle;
+}
+
+CADEndblkObject * DWGFileR2000::getEndBlock(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                             size_t& nBitOffsetFromStart )
+{
+    CADEndblkObject * endblk = new CADEndblkObject();
+
+    endblk->setSize( dObjectSize );
+    endblk->stCed = stCommonEntityData;
+
+    fillCommonEntityHandleData( endblk, pabyInput, nBitOffsetFromStart );
+
+    endblk->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "ENDBLK" ) );
+    return endblk;
+}
+
+CADPolyline2DObject * DWGFileR2000::getPolyline2D(unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                                   const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADPolyline2DObject * polyline = new CADPolyline2DObject();
+
+    polyline->setSize( dObjectSize );
+    polyline->stCed = stCommonEntityData;
+
+    polyline->dFlags                = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    polyline->dCurveNSmoothSurfType = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    polyline->dfStartWidth = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    polyline->dfEndWidth   = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    polyline->dfThickness = ReadBIT( pabyInput, nBitOffsetFromStart ) ? 0.0f : ReadBITDOUBLE( pabyInput,
+                                                                                              nBitOffsetFromStart );
+
+    polyline->dfElevation = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    if( ReadBIT( pabyInput, nBitOffsetFromStart ) )
+    {
+        polyline->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
+    }
+    else
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        polyline->vectExtrusion = vectExtrusion;
+    }
+
+    fillCommonEntityHandleData( polyline, pabyInput, nBitOffsetFromStart );
+
+    polyline->hVertexes.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) ); // 1st vertex
+    polyline->hVertexes.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) ); // last vertex
+
+    polyline->hSeqend = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    polyline->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                         nBitOffsetFromStart, "POLYLINE" ) );
+    return polyline;
+}
+
+CADAttribObject * DWGFileR2000::getAttributes(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                               size_t& nBitOffsetFromStart )
+{
+    CADAttribObject * attrib = new CADAttribObject();
+
+    attrib->setSize( dObjectSize );
+    attrib->stCed     = stCommonEntityData;
+    attrib->DataFlags = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    if( !( attrib->DataFlags & 0x01 ) )
+        attrib->dfElevation = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    double x, y;
+
+    CADVector vertInsetionPoint = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+    attrib->vertInsetionPoint = vertInsetionPoint;
+
+    if( !( attrib->DataFlags & 0x02 ) )
+    {
+        x = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, vertInsetionPoint.getX() );
+        y = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, vertInsetionPoint.getY() );
+        CADVector vertAlignmentPoint( x, y );
+        attrib->vertAlignmentPoint = vertAlignmentPoint;
+    }
+
+    if( ReadBIT( pabyInput, nBitOffsetFromStart ) )
+    {
+        attrib->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
+    } else
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        attrib->vectExtrusion = vectExtrusion;
+    }
+
+    attrib->dfThickness = ReadBIT( pabyInput, nBitOffsetFromStart ) ? 0.0f : ReadBITDOUBLE( pabyInput,
+                                                                                            nBitOffsetFromStart );
+
+    if( !( attrib->DataFlags & 0x04 ) )
+        attrib->dfObliqueAng  = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    if( !( attrib->DataFlags & 0x08 ) )
+        attrib->dfRotationAng = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    attrib->dfHeight          = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    if( !( attrib->DataFlags & 0x10 ) )
+        attrib->dfWidthFactor = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    attrib->sTextValue        = ReadTV( pabyInput, nBitOffsetFromStart );
+    if( !( attrib->DataFlags & 0x20 ) )
+        attrib->dGeneration   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    if( !( attrib->DataFlags & 0x40 ) )
+        attrib->dHorizAlign   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    if( !( attrib->DataFlags & 0x80 ) )
+        attrib->dVertAlign    = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    attrib->sTag         = ReadTV( pabyInput, nBitOffsetFromStart );
+    attrib->nFieldLength = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    attrib->nFlags       = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( attrib, pabyInput, nBitOffsetFromStart );
+
+    attrib->hStyle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    attrib->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "ATTRIB" ) );
+    return attrib;
+}
+
+CADAttdefObject * DWGFileR2000::getAttributesDefn(unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                                   const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADAttdefObject * attdef = new CADAttdefObject();
+
+    attdef->setSize( dObjectSize );
+    attdef->stCed     = stCommonEntityData;
+    attdef->DataFlags = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    if( ( attdef->DataFlags & 0x01 ) == 0 )
+        attdef->dfElevation = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    CADVector vertInsetionPoint = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+    attdef->vertInsetionPoint = vertInsetionPoint;
+
+    if( ( attdef->DataFlags & 0x02 ) == 0 )
+    {
+        double x = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart,
+            vertInsetionPoint.getX() );
+        double y = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart,
+            vertInsetionPoint.getY() );
+        CADVector vertAlignmentPoint( x, y );
+        attdef->vertAlignmentPoint = vertAlignmentPoint;
+    }
+
+    if( ReadBIT( pabyInput, nBitOffsetFromStart ) )
+    {
+        attdef->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
+    }
+    else
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        attdef->vectExtrusion = vectExtrusion;
+    }
+
+    attdef->dfThickness = ReadBIT( pabyInput, nBitOffsetFromStart ) ? 0.0f :
+                          ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    if( ( attdef->DataFlags & 0x04 ) == 0 )
+        attdef->dfObliqueAng  = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    if( ( attdef->DataFlags & 0x08 ) == 0 )
+        attdef->dfRotationAng = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    attdef->dfHeight          = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    if( ( attdef->DataFlags & 0x10 ) == 0 )
+        attdef->dfWidthFactor = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    attdef->sTextValue        = ReadTV( pabyInput, nBitOffsetFromStart );
+    if( ( attdef->DataFlags & 0x20 ) == 0 )
+        attdef->dGeneration   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    if( ( attdef->DataFlags & 0x40 ) == 0 )
+        attdef->dHorizAlign   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    if( ( attdef->DataFlags & 0x80 ) == 0 )
+        attdef->dVertAlign    = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    attdef->sTag         = ReadTV( pabyInput, nBitOffsetFromStart );
+    attdef->nFieldLength = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    attdef->nFlags       = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    attdef->sPrompt = ReadTV( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( attdef, pabyInput, nBitOffsetFromStart );
+
+    attdef->hStyle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    attdef->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "ATTRDEF" ) );
+    return attdef;
+}
+
+CADLWPolylineObject * DWGFileR2000::getLWPolyLine(unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                                   const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADLWPolylineObject * polyline = new CADLWPolylineObject();
+    polyline->setSize( dObjectSize );
+    polyline->stCed = stCommonEntityData;
+
+    double x             = 0.0, y = 0.0;
+    int    vertixesCount = 0, nBulges = 0, nNumWidths = 0;
+    short  dataFlag      = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    if( dataFlag & 4 )
+        polyline->dfConstWidth = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    if( dataFlag & 8 )
+        polyline->dfElevation  = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    if( dataFlag & 2 )
+        polyline->dfThickness  = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    if( dataFlag & 1 )
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        polyline->vectExtrusion = vectExtrusion;
+    }
+
+    vertixesCount = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    polyline->avertVertexes.reserve( static_cast<size_t>(vertixesCount) );
+
+    if( dataFlag & 16 )
+    {
+        nBulges = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+        polyline->adfBulges.reserve( static_cast<size_t>(nBulges) );
+    }
+
+    // TODO: tell ODA that R2000 contains nNumWidths flag
+    if( dataFlag & 32 )
+    {
+        nNumWidths = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+        polyline->astWidths.reserve( static_cast<size_t>(nNumWidths) );
+    }
+
+    if( dataFlag & 512 )
+    {
+        polyline->bClosed = true;
+    } else
+        polyline->bClosed = false;
+
+    // First of all, read first vertex.
+    CADVector vertex = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+    polyline->avertVertexes.push_back( vertex );
+
+    // All the others are not raw doubles; bitdoubles with default instead,
+    // where default is previous point coords.
+    size_t   prev;
+    for( int i       = 1; i < vertixesCount; ++i )
+    {
+        prev = size_t( i - 1 );
+        x    = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart,
+                                polyline->avertVertexes[prev].getX() );
+        y    = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart,
+                                polyline->avertVertexes[prev].getY() );
+        vertex.setX( x );
+        vertex.setY( y );
+        polyline->avertVertexes.push_back( vertex );
+    }
+
+    for( int i = 0; i < nBulges; ++i )
+    {
+        double dfBulgeValue = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+        polyline->adfBulges.push_back( dfBulgeValue );
+    }
+
+    for( int i = 0; i < nNumWidths; ++i )
+    {
+        double dfStartWidth = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+        double dfEndWidth   = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+        polyline->astWidths.push_back( make_pair( dfStartWidth, dfEndWidth ) );
+    }
+
+    fillCommonEntityHandleData( polyline, pabyInput, nBitOffsetFromStart );
+
+    polyline->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                         nBitOffsetFromStart, "WPOLYLINE" ) );
+    return polyline;
+}
+
+CADArcObject * DWGFileR2000::getArc(unsigned int dObjectSize,
+                                    const CADCommonED& stCommonEntityData,
+                                    const char * pabyInput,
+                                    size_t& nBitOffsetFromStart )
+{
+    CADArcObject * arc = new CADArcObject();
+
+    arc->setSize( dObjectSize );
+    arc->stCed = stCommonEntityData;
+
+    CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );
+    arc->vertPosition = vertPosition;
+    arc->dfRadius     = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    arc->dfThickness  = ReadBIT( pabyInput, nBitOffsetFromStart ) ? 0.0f : ReadBITDOUBLE( pabyInput,
+                                                                                          nBitOffsetFromStart );
+
+    if( ReadBIT( pabyInput, nBitOffsetFromStart ) )
+    {
+        arc->vectExtrusion = CADVector( 0.0f, 0.0f, 1.0f );
+    } else
+    {
+        CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+        arc->vectExtrusion = vectExtrusion;
+    }
+
+    arc->dfStartAngle = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    arc->dfEndAngle   = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( arc, pabyInput, nBitOffsetFromStart );
+
+    arc->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                    nBitOffsetFromStart, "ARC" ) );
+    return arc;
+}
+
+CADSplineObject * DWGFileR2000::getSpline(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                           size_t& nBitOffsetFromStart )
+{
+    CADSplineObject * spline = new CADSplineObject();
+    spline->setSize( dObjectSize );
+    spline->stCed     = stCommonEntityData;
+    spline->dScenario = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    spline->dDegree   = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+
+    if( spline->dScenario == 2 )
+    {
+        spline->dfFitTol = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+        CADVector vectBegTangDir = ReadVector( pabyInput, nBitOffsetFromStart );
+        spline->vectBegTangDir = vectBegTangDir;
+        CADVector vectEndTangDir = ReadVector( pabyInput, nBitOffsetFromStart );
+        spline->vectEndTangDir = vectEndTangDir;
+
+        spline->nNumFitPts = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+        spline->averFitPoints.reserve( static_cast<size_t>(spline->nNumFitPts) );
+    } else if( spline->dScenario == 1 )
+    {
+        spline->bRational = ReadBIT( pabyInput, nBitOffsetFromStart );
+        spline->bClosed   = ReadBIT( pabyInput, nBitOffsetFromStart );
+        spline->bPeriodic = ReadBIT( pabyInput, nBitOffsetFromStart );
+        spline->dfKnotTol = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+        spline->dfCtrlTol = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+        spline->nNumKnots = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+        spline->adfKnots.reserve( static_cast<size_t>(spline->nNumKnots) );
+
+        spline->nNumCtrlPts = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+        spline->avertCtrlPoints.reserve( static_cast<size_t>(spline->nNumCtrlPts) );
+        if( spline->bWeight )
+            spline->adfCtrlPointsWeight.reserve( static_cast<size_t>(spline->nNumCtrlPts) );
+
+        spline->bWeight = ReadBIT( pabyInput, nBitOffsetFromStart );
+    }
+#ifdef _DEBUG
+    else
+    {
+        DebugMsg( "Spline scenario != {1,2} readed: error." );
+    }
+#endif
+    for( long i = 0; i < spline->nNumKnots; ++i )
+        spline->adfKnots.push_back( ReadBITDOUBLE( pabyInput, nBitOffsetFromStart ) );
+    for( long i = 0; i < spline->nNumCtrlPts; ++i )
+    {
+        CADVector vertex = ReadVector( pabyInput, nBitOffsetFromStart );
+        spline->avertCtrlPoints.push_back( vertex );
+        if( spline->bWeight )
+            spline->adfCtrlPointsWeight.push_back( ReadBITDOUBLE( pabyInput, nBitOffsetFromStart ) );
+    }
+    for( long i = 0; i < spline->nNumFitPts; ++i )
+    {
+        CADVector vertex = ReadVector( pabyInput, nBitOffsetFromStart );
+        spline->averFitPoints.push_back( vertex );
+    }
+
+    fillCommonEntityHandleData( spline, pabyInput, nBitOffsetFromStart );
+
+    spline->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "SPLINE" ) );
+    return spline;
+}
+
+CADEntityObject * DWGFileR2000::getEntity(int dObjectType, unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                           const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADEntityObject * entity = new CADEntityObject(
+                    static_cast<CADObject::ObjectType>(dObjectType) );
+
+    entity->setSize( dObjectSize );
+    entity->stCed = stCommonEntityData;
+
+    nBitOffsetFromStart = static_cast<size_t>(
+            entity->stCed.nObjectSizeInBits + 16);
+
+    fillCommonEntityHandleData( entity, pabyInput, nBitOffsetFromStart );
+
+    nBitOffsetFromStart = (dObjectSize - 2) * 8;
+    entity->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "ENTITY" ) );
+    return entity;
+}
+
+CADInsertObject * DWGFileR2000::getInsert(int dObjectType, unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                           const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADInsertObject * insert = new CADInsertObject(
+                            static_cast<CADObject::ObjectType>(dObjectType) );
+    insert->setSize( dObjectSize );
+    insert->stCed = stCommonEntityData;
+
+    insert->vertInsertionPoint = ReadVector( pabyInput, nBitOffsetFromStart );
+    unsigned char dataFlags = Read2B( pabyInput, nBitOffsetFromStart );
+    double        val41     = 1.0;
+    double        val42     = 1.0;
+    double        val43     = 1.0;
+    if( dataFlags == 0 )
+    {
+        val41 = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+        val42 = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, val41 );
+        val43 = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, val41 );
+    } else if( dataFlags == 1 )
+    {
+        val41 = 1.0;
+        val42 = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, val41 );
+        val43 = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, val41 );
+    } else if( dataFlags == 2 )
+    {
+        val41 = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+        val42 = val41;
+        val43 = val41;
+    }
+    insert->vertScales    = CADVector( val41, val42, val43 );
+    insert->dfRotation    = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    insert->vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+    insert->bHasAttribs   = ReadBIT( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( insert, pabyInput, nBitOffsetFromStart );
+
+    insert->hBlockHeader = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    if( insert->bHasAttribs )
+    {
+        insert->hAttribs.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+        insert->hAttribs.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+        insert->hSeqend = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    }
+
+    insert->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "INSERT" ) );
+
+    return insert;
+}
+
+CADDictionaryObject * DWGFileR2000::getDictionary(unsigned int dObjectSize, const char * pabyInput,
+                                                   size_t& nBitOffsetFromStart )
+{
+    /*
+     * FIXME: ODA has a lot of mistypes in spec. for this objects,
+     * it doesn't work for now (error begins in handles stream).
+     * Nonetheless, dictionary->sItemNames is 100% array,
+     * not a single obj as pointer by their docs.
+     */
+    CADDictionaryObject * dictionary = new CADDictionaryObject();
+
+    dictionary->setSize( dObjectSize );
+    dictionary->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    dictionary->hObjectHandle     = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    short  dEEDSize = 0;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        dictionary->aEED.push_back( dwgEed );
+    }
+
+    dictionary->nNumReactors   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    dictionary->nNumItems      = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    dictionary->dCloningFlag   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    dictionary->dHardOwnerFlag = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < dictionary->nNumItems; ++i )
+        dictionary->sItemNames.push_back( ReadTV( pabyInput, nBitOffsetFromStart ) );
+
+    dictionary->hParentHandle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < dictionary->nNumReactors; ++i )
+        dictionary->hReactors.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+    dictionary->hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    for( long i = 0; i < dictionary->nNumItems; ++i )
+        dictionary->hItemHandles.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+
+    nBitOffsetFromStart = (dObjectSize - 2) * 8;
+    dictionary->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                           nBitOffsetFromStart, "DICT" ) );
+
+    return dictionary;
+}
+
+CADLayerObject * DWGFileR2000::getLayerObject(unsigned int dObjectSize, const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADLayerObject * layer = new CADLayerObject();
+
+    layer->setSize( dObjectSize );
+    layer->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    layer->hObjectHandle     = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    short  dEEDSize = 0;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        layer->aEED.push_back( dwgEed );
+    }
+
+    layer->nNumReactors = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    layer->sLayerName   = ReadTV( pabyInput, nBitOffsetFromStart );
+    layer->b64Flag      = ReadBIT( pabyInput, nBitOffsetFromStart ) != 0;
+    layer->dXRefIndex   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    layer->bXDep        = ReadBIT( pabyInput, nBitOffsetFromStart ) != 0;
+
+    short dFlags = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    layer->bFrozen           = (dFlags & 0x01) != 0;
+    layer->bOn               = (dFlags & 0x02) != 0;
+    layer->bFrozenInNewVPORT = (dFlags & 0x04) != 0;
+    layer->bLocked           = (dFlags & 0x08) != 0;
+    layer->bPlottingFlag     = (dFlags & 0x10) != 0;
+    layer->dLineWeight       = dFlags & 0x03E0;
+    layer->dCMColor          = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    layer->hLayerControl     = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    for( long i = 0; i < layer->nNumReactors; ++i )
+        layer->hReactors.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+    layer->hXDictionary            = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    layer->hExternalRefBlockHandle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    layer->hPlotStyle              = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    layer->hLType                  = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    /*
+     * FIXME: ODA says that this handle should be null hard pointer. It is not.
+     * Also, after reading it dObjectSize is != actual readed structure's size.
+     * Not used anyway, so no point to read it for now.
+     * It also means that CRC cannot be computed correctly.
+     */
+// layer->hUnknownHandle = ReadHANDLE (pabySectionContent, nBitOffsetFromStart);
+
+    layer->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                      nBitOffsetFromStart, "LAYER" ) );
+    return layer;
+}
+
+CADLayerControlObject * DWGFileR2000::getLayerControl(unsigned int dObjectSize, const char * pabyInput,
+                                                       size_t& nBitOffsetFromStart )
+{
+    CADLayerControlObject * layerControl = new CADLayerControlObject();
+
+    layerControl->setSize( dObjectSize );
+    layerControl->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    layerControl->hObjectHandle     = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    short  dEEDSize = 0;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        layerControl->aEED.push_back( dwgEed );
+    }
+
+    layerControl->nNumReactors = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    layerControl->nNumEntries  = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    layerControl->hNull        = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    layerControl->hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    for( long i = 0; i < layerControl->nNumEntries; ++i )
+        layerControl->hLayers.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+
+    layerControl->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                             nBitOffsetFromStart, "LAYERCONTROL" ) );
+    return layerControl;
+}
+
+CADBlockControlObject * DWGFileR2000::getBlockControl(unsigned int dObjectSize, const char * pabyInput,
+                                                       size_t& nBitOffsetFromStart )
+{
+    CADBlockControlObject * blockControl = new CADBlockControlObject();
+
+    blockControl->setSize( dObjectSize );
+    blockControl->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    blockControl->hObjectHandle     = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    short  dEEDSize = 0;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        blockControl->aEED.push_back( dwgEed );
+    }
+
+    blockControl->nNumReactors = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    blockControl->nNumEntries  = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+
+    blockControl->hNull        = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    blockControl->hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < blockControl->nNumEntries + 2; ++i )
+    {
+        blockControl->hBlocks.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+    }
+
+    blockControl->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                             nBitOffsetFromStart, "BLOCKCONTROL" ) );
+    return blockControl;
+}
+
+CADBlockHeaderObject * DWGFileR2000::getBlockHeader(unsigned int dObjectSize, const char * pabyInput,
+                                                     size_t& nBitOffsetFromStart )
+{
+    CADBlockHeaderObject * blockHeader = new CADBlockHeaderObject();
+
+    blockHeader->setSize( dObjectSize );
+    blockHeader->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    blockHeader->hObjectHandle     = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    short  dEEDSize;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        blockHeader->aEED.push_back( dwgEed );
+    }
+
+    blockHeader->nNumReactors  = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    blockHeader->sEntryName    = ReadTV( pabyInput, nBitOffsetFromStart );
+    blockHeader->b64Flag       = ReadBIT( pabyInput, nBitOffsetFromStart );
+    blockHeader->dXRefIndex    = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    blockHeader->bXDep         = ReadBIT( pabyInput, nBitOffsetFromStart );
+    blockHeader->bAnonymous    = ReadBIT( pabyInput, nBitOffsetFromStart );
+    blockHeader->bHasAtts      = ReadBIT( pabyInput, nBitOffsetFromStart );
+    blockHeader->bBlkisXRef    = ReadBIT( pabyInput, nBitOffsetFromStart );
+    blockHeader->bXRefOverlaid = ReadBIT( pabyInput, nBitOffsetFromStart );
+    blockHeader->bLoadedBit    = ReadBIT( pabyInput, nBitOffsetFromStart );
+
+    CADVector vertBasePoint = ReadVector( pabyInput, nBitOffsetFromStart );
+    blockHeader->vertBasePoint = vertBasePoint;
+    blockHeader->sXRefPName    = ReadTV( pabyInput, nBitOffsetFromStart );
+    unsigned char Tmp;
+    do
+    {
+        Tmp = ReadCHAR( pabyInput, nBitOffsetFromStart );
+        blockHeader->adInsertCount.push_back( Tmp );
+    } while( Tmp != 0 );
+
+    blockHeader->sBlockDescription  = ReadTV( pabyInput, nBitOffsetFromStart );
+    blockHeader->nSizeOfPreviewData = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    for( long i = 0; i < blockHeader->nSizeOfPreviewData; ++i )
+        blockHeader->abyBinaryPreviewData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+
+    blockHeader->hBlockControl = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    for( long i = 0; i < blockHeader->nNumReactors; ++i )
+        blockHeader->hReactors.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+    blockHeader->hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    blockHeader->hNull        = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    blockHeader->hBlockEntity = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    if( !blockHeader->bBlkisXRef && !blockHeader->bXRefOverlaid )
+    {
+        blockHeader->hEntities.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) ); // first
+        blockHeader->hEntities.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) ); // last
+    }
+
+    blockHeader->hEndBlk = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    for( size_t i = 0; i < blockHeader->adInsertCount.size() - 1; ++i )
+        blockHeader->hInsertHandles.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+    blockHeader->hLayout = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    nBitOffsetFromStart = (dObjectSize - 2) * 8;
+    blockHeader->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                            nBitOffsetFromStart, "BLOCKHEADER" ) );
+    return blockHeader;
+}
+
+CADLineTypeControlObject * DWGFileR2000::getLineTypeControl(unsigned int dObjectSize, const char * pabyInput,
+                                                             size_t& nBitOffsetFromStart )
+{
+    CADLineTypeControlObject * ltypeControl = new CADLineTypeControlObject();
+    ltypeControl->setSize( dObjectSize );
+    ltypeControl->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    ltypeControl->hObjectHandle     = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    short  dEEDSize = 0;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        ltypeControl->aEED.push_back( dwgEed );
+    }
+
+    ltypeControl->nNumReactors = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    ltypeControl->nNumEntries  = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+
+    ltypeControl->hNull        = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    ltypeControl->hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    // hLTypes ends with BYLAYER and BYBLOCK
+    for( long i = 0; i < ltypeControl->nNumEntries + 2; ++i )
+        ltypeControl->hLTypes.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+
+    ltypeControl->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                             nBitOffsetFromStart, "LINETYPECTRL" ) );
+    return ltypeControl;
+}
+
+CADLineTypeObject * DWGFileR2000::getLineType1(unsigned int dObjectSize, const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADLineTypeObject * ltype = new CADLineTypeObject();
+
+    ltype->setSize( dObjectSize );
+    ltype->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    ltype->hObjectHandle     = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    short  dEEDSize = 0;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        ltype->aEED.push_back( dwgEed );
+    }
+
+    ltype->nNumReactors = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    ltype->sEntryName   = ReadTV( pabyInput, nBitOffsetFromStart );
+    ltype->b64Flag      = ReadBIT( pabyInput, nBitOffsetFromStart );
+    ltype->dXRefIndex   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    ltype->bXDep        = ReadBIT( pabyInput, nBitOffsetFromStart );
+    ltype->sDescription = ReadTV( pabyInput, nBitOffsetFromStart );
+    ltype->dfPatternLen = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    ltype->dAlignment   = ReadCHAR( pabyInput, nBitOffsetFromStart );
+    ltype->nNumDashes   = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    CADDash     dash;
+    for( size_t i       = 0; i < ltype->nNumDashes; ++i )
+    {
+        dash.dfLength          = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+        dash.dComplexShapecode = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+        dash.dfXOffset         = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+        dash.dfYOffset         = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+        dash.dfScale           = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+        dash.dfRotation        = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+        dash.dShapeflag        = ReadBITSHORT( pabyInput, nBitOffsetFromStart ); // TODO: what to do with it?
+
+        ltype->astDashes.push_back( dash );
+    }
+
+    for( short i = 0; i < 256; ++i )
+        ltype->abyTextArea.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+
+    ltype->hLTControl = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < ltype->nNumReactors; ++i )
+        ltype->hReactors.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+
+    ltype->hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    ltype->hXRefBlock   = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    // TODO: shapefile for dash/shape (1 each). Does it mean that we have nNumDashes * 2 handles, or what?
+
+    ltype->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                      nBitOffsetFromStart, "LINETYPE" ) );
+    return ltype;
+}
+
+CADMLineObject * DWGFileR2000::getMLine(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                         size_t& nBitOffsetFromStart )
+{
+    CADMLineObject * mline = new CADMLineObject();
+
+    mline->setSize( dObjectSize );
+    mline->stCed = stCommonEntityData;
+
+    mline->dfScale = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    mline->dJust   = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    CADVector vertBasePoint = ReadVector( pabyInput, nBitOffsetFromStart );
+    mline->vertBasePoint = vertBasePoint;
+
+    CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+    mline->vectExtrusion = vectExtrusion;
+    mline->dOpenClosed   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    mline->nLinesInStyle = ReadCHAR( pabyInput, nBitOffsetFromStart );
+    mline->nNumVertexes  = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    CADMLineVertex stVertex;
+    CADLineStyle   stLStyle;
+    for( long      i     = 0; i < mline->nNumVertexes; ++i )
+    {
+        CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );
+        stVertex.vertPosition = vertPosition;
+
+        CADVector vectDirection = ReadVector( pabyInput, nBitOffsetFromStart );
+        stVertex.vectDirection = vectDirection;
+
+        CADVector vectMIterDirection = ReadVector( pabyInput, nBitOffsetFromStart );
+        stVertex.vectMIterDirection = vectMIterDirection;
+        for( size_t j = 0; j < mline->nLinesInStyle; ++j )
+        {
+            stLStyle.nNumSegParms = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+            for( short k = 0; k < stLStyle.nNumSegParms; ++k )
+                stLStyle.adfSegparms.push_back( ReadBITDOUBLE( pabyInput, nBitOffsetFromStart ) );
+            stLStyle.nAreaFillParms = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+            for( short k = 0; k < stLStyle.nAreaFillParms; ++k )
+                stLStyle.adfAreaFillParameters.push_back( ReadBITDOUBLE( pabyInput, nBitOffsetFromStart ) );
+
+            stVertex.astLStyles.push_back( stLStyle );
+        }
+        mline->avertVertexes.push_back( stVertex );
+    }
+
+    if( mline->stCed.bbEntMode == 0 )
+        mline->stChed.hOwner = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < mline->stCed.nNumReactors; ++i )
+        mline->stChed.hReactors.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+
+    mline->stChed.hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    if( !mline->stCed.bNoLinks )
+    {
+        mline->stChed.hPrevEntity = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+        mline->stChed.hNextEntity = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    }
+
+    mline->stChed.hLayer = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    if( mline->stCed.bbLTypeFlags == 0x03 )
+        mline->stChed.hLType = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    if( mline->stCed.bbPlotStyleFlags == 0x03 )
+        mline->stChed.hPlotStyle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    mline->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                      nBitOffsetFromStart, "MLINE" ) );
+    return mline;
+}
+
+CADPolylinePFaceObject * DWGFileR2000::getPolylinePFace(unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                                         const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADPolylinePFaceObject * polyline = new CADPolylinePFaceObject();
+
+    polyline->setSize( dObjectSize );
+    polyline->stCed = stCommonEntityData;
+
+    polyline->nNumVertexes = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    polyline->nNumFaces    = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( polyline, pabyInput, nBitOffsetFromStart );
+
+    polyline->hVertexes.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) ); // 1st vertex
+    polyline->hVertexes.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) ); // last vertex
+
+    polyline->hSeqend = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    polyline->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                         nBitOffsetFromStart, "POLYLINEPFACE" ) );
+    return polyline;
+}
+
+CADImageObject * DWGFileR2000::getImage(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                         size_t& nBitOffsetFromStart )
+{
+    CADImageObject * image = new CADImageObject();
+
+    image->setSize( dObjectSize );
+    image->stCed = stCommonEntityData;
+
+    image->dClassVersion = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+
+    CADVector vertInsertion = ReadVector( pabyInput, nBitOffsetFromStart );
+    image->vertInsertion = vertInsertion;
+
+    CADVector vectUDirection = ReadVector( pabyInput, nBitOffsetFromStart );
+    image->vectUDirection = vectUDirection;
+
+    CADVector vectVDirection = ReadVector( pabyInput, nBitOffsetFromStart );
+    image->vectVDirection = vectVDirection;
+
+    image->dfSizeX       = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    image->dfSizeY       = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    image->dDisplayProps = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    image->bClipping         = ReadBIT( pabyInput, nBitOffsetFromStart );
+    image->dBrightness       = ReadCHAR( pabyInput, nBitOffsetFromStart );
+    image->dContrast         = ReadCHAR( pabyInput, nBitOffsetFromStart );
+    image->dFade             = ReadCHAR( pabyInput, nBitOffsetFromStart );
+    image->dClipBoundaryType = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    if( image->dClipBoundaryType == 1 )
+    {
+        CADVector vertPoint1 = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+        image->avertClippingPolygonVertexes.push_back( vertPoint1 );
+
+        CADVector vertPoint2 = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+        image->avertClippingPolygonVertexes.push_back( vertPoint2 );
+    } else
+    {
+        image->nNumberVertexesInClipPolygon = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+
+        for( long i = 0; i < image->nNumberVertexesInClipPolygon; ++i )
+        {
+            CADVector vertPoint = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+            image->avertClippingPolygonVertexes.push_back( vertPoint );
+        }
+    }
+
+    fillCommonEntityHandleData( image, pabyInput, nBitOffsetFromStart );
+
+    image->hImageDef        = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    image->hImageDefReactor = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    image->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                      nBitOffsetFromStart, "IMAGE" ) );
+
+    return image;
+}
+
+CAD3DFaceObject * DWGFileR2000::get3DFace(unsigned int dObjectSize, const CADCommonED& stCommonEntityData, const char * pabyInput,
+                                           size_t& nBitOffsetFromStart )
+{
+    CAD3DFaceObject * face = new CAD3DFaceObject();
+
+    face->setSize( dObjectSize );
+    face->stCed = stCommonEntityData;
+
+    face->bHasNoFlagInd = ReadBIT( pabyInput, nBitOffsetFromStart );
+    face->bZZero        = ReadBIT( pabyInput, nBitOffsetFromStart );
+
+    double x, y, z;
+
+    CADVector vertex = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+    if( !face->bZZero )
+    {
+        z = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+        vertex.setZ( z );
+    }
+    face->avertCorners.push_back( vertex );
+    for( size_t i = 1; i < 4; ++i )
+    {
+        x = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, face->avertCorners[i - 1].getX() );
+        y = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, face->avertCorners[i - 1].getY() );
+        z = ReadBITDOUBLEWD( pabyInput, nBitOffsetFromStart, face->avertCorners[i - 1].getZ() );
+
+        CADVector corner( x, y, z );
+        face->avertCorners.push_back( corner );
+    }
+
+    if( !face->bHasNoFlagInd )
+        face->dInvisFlags = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( face, pabyInput, nBitOffsetFromStart );
+
+    face->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                     nBitOffsetFromStart, "3DFACE" ) );
+    return face;
+}
+
+CADVertexMeshObject * DWGFileR2000::getVertexMesh(unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                                   const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADVertexMeshObject * vertex = new CADVertexMeshObject();
+
+    vertex->setSize( dObjectSize );
+    vertex->stCed = stCommonEntityData;
+
+    /*unsigned char Flags = */ReadCHAR( pabyInput, nBitOffsetFromStart );
+    CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );
+    vertex->vertPosition = vertPosition;
+
+    fillCommonEntityHandleData( vertex, pabyInput, nBitOffsetFromStart );
+
+    vertex->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "VERTEXMESH" ) );
+    return vertex;
+}
+
+CADVertexPFaceObject * DWGFileR2000::getVertexPFace(unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                                     const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADVertexPFaceObject * vertex = new CADVertexPFaceObject();
+
+    vertex->setSize( dObjectSize );
+    vertex->stCed = stCommonEntityData;
+
+    /*unsigned char Flags = */ReadCHAR( pabyInput, nBitOffsetFromStart );
+    CADVector vertPosition = ReadVector( pabyInput, nBitOffsetFromStart );
+    vertex->vertPosition = vertPosition;
+
+    fillCommonEntityHandleData( vertex, pabyInput, nBitOffsetFromStart );
+
+    vertex->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                       nBitOffsetFromStart, "VERTEXPFACE" ) );
+    return vertex;
+}
+
+CADMTextObject * DWGFileR2000::getMText(unsigned int dObjectSize,
+                                        const CADCommonED& stCommonEntityData,
+                                        const char * pabyInput,
+                                        size_t& nBitOffsetFromStart )
+{
+    CADMTextObject * text = new CADMTextObject();
+
+    text->setSize( dObjectSize );
+    text->stCed = stCommonEntityData;
+
+    CADVector vertInsertionPoint = ReadVector( pabyInput, nBitOffsetFromStart );
+    text->vertInsertionPoint = vertInsertionPoint;
+
+    CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+    text->vectExtrusion = vectExtrusion;
+
+    CADVector vectXAxisDir = ReadVector( pabyInput, nBitOffsetFromStart );
+    text->vectXAxisDir = vectXAxisDir;
+
+    text->dfRectWidth        = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    text->dfTextHeight       = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    text->dAttachment        = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    text->dDrawingDir        = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    text->dfExtents          = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    text->dfExtentsWidth     = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    text->sTextValue         = ReadTV( pabyInput, nBitOffsetFromStart );
+    text->dLineSpacingStyle  = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    text->dLineSpacingFactor = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    text->bUnknownBit        = ReadBIT( pabyInput, nBitOffsetFromStart );
+
+    fillCommonEntityHandleData( text, pabyInput, nBitOffsetFromStart );
+
+    text->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                     nBitOffsetFromStart, "MTEXT" ) );
+    return text;
+}
+
+CADDimensionObject * DWGFileR2000::getDimension(short dObjectType, unsigned int dObjectSize, const CADCommonED& stCommonEntityData,
+                                                 const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADCommonDimensionData stCDD;
+
+    CADVector vectExtrusion = ReadVector( pabyInput, nBitOffsetFromStart );
+    stCDD.vectExtrusion = vectExtrusion;
+
+    CADVector vertTextMidPt = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+    stCDD.vertTextMidPt = vertTextMidPt;
+
+    stCDD.dfElevation = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    stCDD.dFlags      = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    stCDD.sUserText      = ReadTV( pabyInput, nBitOffsetFromStart );
+    stCDD.dfTextRotation = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    stCDD.dfHorizDir     = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    stCDD.dfInsXScale   = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    stCDD.dfInsYScale   = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    stCDD.dfInsZScale   = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    stCDD.dfInsRotation = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    stCDD.dAttachmentPoint    = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    stCDD.dLineSpacingStyle   = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+    stCDD.dfLineSpacingFactor = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+    stCDD.dfActualMeasurement = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    CADVector vert12Pt = ReadRAWVector( pabyInput, nBitOffsetFromStart );
+    stCDD.vert12Pt = vert12Pt;
+
+    switch( dObjectType )
+    {
+        case CADObject::DIMENSION_ORDINATE:
+        {
+            CADDimensionOrdinateObject * dimension = new CADDimensionOrdinateObject();
+
+            dimension->setSize( dObjectSize );
+            dimension->stCed = stCommonEntityData;
+            dimension->cdd   = stCDD;
+
+            CADVector vert10pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert10pt = vert10pt;
+
+            CADVector vert13pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert13pt = vert13pt;
+
+            CADVector vert14pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert14pt = vert14pt;
+
+            dimension->Flags2 = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+            fillCommonEntityHandleData( dimension, pabyInput, nBitOffsetFromStart );
+
+            dimension->hDimstyle       = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+            dimension->hAnonymousBlock = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+            dimension->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                                  nBitOffsetFromStart, "DIM" ) );
+            return dimension;
+        }
+
+        case CADObject::DIMENSION_LINEAR:
+        {
+            CADDimensionLinearObject * dimension = new CADDimensionLinearObject();
+
+            dimension->setSize( dObjectSize );
+            dimension->stCed = stCommonEntityData;
+            dimension->cdd   = stCDD;
+
+            CADVector vert13pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert13pt = vert13pt;
+
+            CADVector vert14pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert14pt = vert14pt;
+
+            CADVector vert10pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert10pt = vert10pt;
+
+            dimension->dfExtLnRot = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+            dimension->dfDimRot   = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+            fillCommonEntityHandleData( dimension, pabyInput, nBitOffsetFromStart );
+
+            dimension->hDimstyle       = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+            dimension->hAnonymousBlock = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+            dimension->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                                  nBitOffsetFromStart, "DIM" ) );
+            return dimension;
+        }
+
+        case CADObject::DIMENSION_ALIGNED:
+        {
+            CADDimensionAlignedObject * dimension = new CADDimensionAlignedObject();
+
+            dimension->setSize( dObjectSize );
+            dimension->stCed = stCommonEntityData;
+            dimension->cdd   = stCDD;
+
+            CADVector vert13pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert13pt = vert13pt;
+
+            CADVector vert14pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert14pt = vert14pt;
+
+            CADVector vert10pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert10pt = vert10pt;
+
+            dimension->dfExtLnRot = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+            fillCommonEntityHandleData( dimension, pabyInput, nBitOffsetFromStart );
+
+            dimension->hDimstyle       = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+            dimension->hAnonymousBlock = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+            dimension->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                                  nBitOffsetFromStart, "DIM" ) );
+            return dimension;
+        }
+
+        case CADObject::DIMENSION_ANG_3PT:
+        {
+            CADDimensionAngular3PtObject * dimension = new CADDimensionAngular3PtObject();
+
+            dimension->setSize( dObjectSize );
+            dimension->stCed = stCommonEntityData;
+            dimension->cdd   = stCDD;
+
+            CADVector vert10pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert10pt = vert10pt;
+
+            CADVector vert13pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert13pt = vert13pt;
+
+            CADVector vert14pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert14pt = vert14pt;
+
+            CADVector vert15pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert15pt = vert15pt;
+
+            fillCommonEntityHandleData( dimension, pabyInput, nBitOffsetFromStart );
+
+            dimension->hDimstyle       = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+            dimension->hAnonymousBlock = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+            dimension->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                                  nBitOffsetFromStart, "DIM" ) );
+            return dimension;
+        }
+
+        case CADObject::DIMENSION_ANG_2LN:
+        {
+            CADDimensionAngular2LnObject * dimension = new CADDimensionAngular2LnObject();
+
+            dimension->setSize( dObjectSize );
+            dimension->stCed = stCommonEntityData;
+            dimension->cdd   = stCDD;
+
+            CADVector vert16pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert16pt = vert16pt;
+
+            CADVector vert13pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert13pt = vert13pt;
+
+            CADVector vert14pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert14pt = vert14pt;
+
+            CADVector vert15pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert15pt = vert15pt;
+
+            CADVector vert10pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert10pt = vert10pt;
+
+            fillCommonEntityHandleData( dimension, pabyInput, nBitOffsetFromStart );
+
+            dimension->hDimstyle       = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+            dimension->hAnonymousBlock = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+            dimension->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                                  nBitOffsetFromStart, "DIM" ) );
+            return dimension;
+        }
+
+        case CADObject::DIMENSION_RADIUS:
+        {
+            CADDimensionRadiusObject * dimension = new CADDimensionRadiusObject();
+
+            dimension->setSize( dObjectSize );
+            dimension->stCed = stCommonEntityData;
+            dimension->cdd   = stCDD;
+
+            CADVector vert10pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert10pt = vert10pt;
+
+            CADVector vert15pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert15pt = vert15pt;
+
+            dimension->dfLeaderLen = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+            fillCommonEntityHandleData( dimension, pabyInput, nBitOffsetFromStart );
+
+            dimension->hDimstyle       = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+            dimension->hAnonymousBlock = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+            dimension->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                                  nBitOffsetFromStart, "DIM" ) );
+            return dimension;
+        }
+
+        case CADObject::DIMENSION_DIAMETER:
+        {
+            CADDimensionDiameterObject * dimension = new CADDimensionDiameterObject();
+
+            dimension->setSize( dObjectSize );
+            dimension->stCed = stCommonEntityData;
+            dimension->cdd   = stCDD;
+
+            CADVector vert15pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert15pt = vert15pt;
+
+            CADVector vert10pt = ReadVector( pabyInput, nBitOffsetFromStart );
+            dimension->vert10pt = vert10pt;
+
+            dimension->dfLeaderLen = ReadBITDOUBLE( pabyInput, nBitOffsetFromStart );
+
+            fillCommonEntityHandleData( dimension, pabyInput, nBitOffsetFromStart );
+
+            dimension->hDimstyle       = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+            dimension->hAnonymousBlock = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+            dimension->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                                  nBitOffsetFromStart, "DIM" ) );
+            return dimension;
+        }
+    }
+    return nullptr;
+}
+
+CADImageDefObject * DWGFileR2000::getImageDef(unsigned int dObjectSize,
+                                              const char * pabyInput,
+                                              size_t& nBitOffsetFromStart )
+{
+    CADImageDefObject * imagedef = new CADImageDefObject();
+
+    imagedef->setSize( dObjectSize );
+    imagedef->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    imagedef->hObjectHandle     = ReadHANDLE8BLENGTH( pabyInput, nBitOffsetFromStart );
+
+    short  dEEDSize = 0;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        imagedef->aEED.push_back( dwgEed );
+    }
+
+    imagedef->nNumReactors  = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    imagedef->dClassVersion = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+
+    imagedef->dfXImageSizeInPx = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    imagedef->dfYImageSizeInPx = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    imagedef->sFilePath = ReadTV( pabyInput, nBitOffsetFromStart );
+    imagedef->bIsLoaded = ReadBIT( pabyInput, nBitOffsetFromStart );
+
+    imagedef->dResUnits = ReadCHAR( pabyInput, nBitOffsetFromStart );
+
+    imagedef->dfXPixelSize = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    imagedef->dfYPixelSize = ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+
+    imagedef->hParentHandle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < imagedef->nNumReactors; ++i )
+        imagedef->hReactors.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+
+    imagedef->hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    imagedef->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                         nBitOffsetFromStart, "IMAGEDEF" ) );
+
+    return imagedef;
+}
+
+CADImageDefReactorObject * DWGFileR2000::getImageDefReactor(unsigned int dObjectSize, const char * pabyInput,
+                                                             size_t& nBitOffsetFromStart )
+{
+    CADImageDefReactorObject * imagedefreactor = new CADImageDefReactorObject();
+
+    imagedefreactor->setSize( dObjectSize );
+    imagedefreactor->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    imagedefreactor->hObjectHandle     = ReadHANDLE8BLENGTH( pabyInput, nBitOffsetFromStart );
+
+    short  dEEDSize = 0;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        imagedefreactor->aEED.push_back( dwgEed );
+    }
+
+    imagedefreactor->nNumReactors  = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    imagedefreactor->dClassVersion = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+
+    imagedefreactor->hParentHandle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < imagedefreactor->nNumReactors; ++i )
+        imagedefreactor->hReactors.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+
+    imagedefreactor->hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    imagedefreactor->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                                nBitOffsetFromStart, "IMAGEDEFREFACTOR" ) );
+
+    return imagedefreactor;
+}
+
+CADXRecordObject * DWGFileR2000::getXRecord(unsigned int dObjectSize, const char * pabyInput, size_t& nBitOffsetFromStart )
+{
+    CADXRecordObject * xrecord = new CADXRecordObject();
+
+    xrecord->setSize( dObjectSize );
+    xrecord->nObjectSizeInBits = ReadRAWLONG( pabyInput, nBitOffsetFromStart );
+    xrecord->hObjectHandle     = ReadHANDLE8BLENGTH( pabyInput, nBitOffsetFromStart );
+
+    short  dEEDSize = 0;
+    CADEed dwgEed;
+    while( ( dEEDSize = ReadBITSHORT( pabyInput, nBitOffsetFromStart ) ) != 0 )
+    {
+        dwgEed.dLength      = dEEDSize;
+        dwgEed.hApplication = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+        for( short i = 0; i < dEEDSize; ++i )
+        {
+            dwgEed.acData.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+        }
+
+        xrecord->aEED.push_back( dwgEed );
+    }
+
+    xrecord->nNumReactors  = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+    xrecord->nNumDataBytes = ReadBITLONG( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < xrecord->nNumDataBytes; ++i )
+    {
+        xrecord->abyDataBytes.push_back( ReadCHAR( pabyInput, nBitOffsetFromStart ) );
+    }
+
+    xrecord->dCloningFlag = ReadBITSHORT( pabyInput, nBitOffsetFromStart );
+
+    short dIndicatorNumber = ReadRAWSHORT( pabyInput, nBitOffsetFromStart );
+    if( dIndicatorNumber == 1 )
+    {
+        unsigned char nStringSize = ReadCHAR( pabyInput, nBitOffsetFromStart );
+        /* char dCodePage   =  */ ReadCHAR( pabyInput, nBitOffsetFromStart );
+        for( unsigned char i = 0; i < nStringSize; ++i )
+        {
+            ReadCHAR( pabyInput, nBitOffsetFromStart );
+        }
+    }
+    else if( dIndicatorNumber == 70 )
+    {
+        ReadRAWSHORT( pabyInput, nBitOffsetFromStart );
+    }
+    else if( dIndicatorNumber == 10 )
+    {
+        ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+        ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+        ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    }
+    else if( dIndicatorNumber == 40 )
+    {
+        ReadRAWDOUBLE( pabyInput, nBitOffsetFromStart );
+    }
+
+    xrecord->hParentHandle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < xrecord->nNumReactors; ++i )
+        xrecord->hReactors.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+
+    xrecord->hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    size_t dObjectSizeBit = (dObjectSize + 4) * 8;
+    while( nBitOffsetFromStart < dObjectSizeBit )
+    {
+        xrecord->hObjIdHandles.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+    }
+
+    nBitOffsetFromStart = (dObjectSize - 2) * 8;
+    xrecord->setCRC( validateEntityCRC( pabyInput, dObjectSize - 2,
+                                        nBitOffsetFromStart, "XRECORD" ) );
+
+    return xrecord;
+}
+
+void DWGFileR2000::fillCommonEntityHandleData( CADEntityObject * pEnt, const char * pabyInput,
+                                               size_t& nBitOffsetFromStart )
+{
+    if( pEnt->stCed.bbEntMode == 0 )
+        pEnt->stChed.hOwner = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    for( long i = 0; i < pEnt->stCed.nNumReactors; ++i )
+        pEnt->stChed.hReactors.push_back( ReadHANDLE( pabyInput, nBitOffsetFromStart ) );
+
+    pEnt->stChed.hXDictionary = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    if( !pEnt->stCed.bNoLinks )
+    {
+        pEnt->stChed.hPrevEntity = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+        pEnt->stChed.hNextEntity = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+    }
+
+    pEnt->stChed.hLayer = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    if( pEnt->stCed.bbLTypeFlags == 0x03 )
+        pEnt->stChed.hLType = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+
+    if( pEnt->stCed.bbPlotStyleFlags == 0x03 )
+        pEnt->stChed.hPlotStyle = ReadHANDLE( pabyInput, nBitOffsetFromStart );
+}
+
+DWGFileR2000::DWGFileR2000( CADFileIO * poFileIO ) :
+    CADFile( poFileIO ),
+    imageSeeker(0)
+{
+    oHeader.addValue( CADHeader::OPENCADVER, CADVersions::DWG_R2000 );
+}
+
+DWGFileR2000::~DWGFileR2000()
+{
+}
+
+int DWGFileR2000::ReadSectionLocators()
+{
+    char  abyBuf[255];
+    int   dImageSeeker, SLRecordsCount;
+    short dCodePage;
+
+    pFileIO->Rewind();
+    memset( abyBuf, 0, DWG_VERSION_STR_SIZE + 1 );
+    pFileIO->Read( abyBuf, DWG_VERSION_STR_SIZE );
+    oHeader.addValue( CADHeader::ACADVER, abyBuf );
+    memset( abyBuf, 0, 8 );
+    pFileIO->Read( abyBuf, 7 );
+    oHeader.addValue( CADHeader::ACADMAINTVER, abyBuf );
+    // TODO: code can be much simplified if CADHandle will be used.
+    pFileIO->Read( & dImageSeeker, 4 );
+    // to do so, == and ++ operators should be implemented.
+    DebugMsg( "Image seeker readed: %d\n", dImageSeeker );
+    imageSeeker = dImageSeeker;
+
+    pFileIO->Seek( 2, CADFileIO::SeekOrigin::CUR ); // 19
+    pFileIO->Read( & dCodePage, 2 );
+    oHeader.addValue( CADHeader::DWGCODEPAGE, dCodePage );
+
+    DebugMsg( "DWG Code page: %d\n", dCodePage );
+
+    pFileIO->Read( & SLRecordsCount, 4 ); // 21
+    // Last vertex is reached. read it and break reading.
+    DebugMsg( "Section locator records count: %d\n", SLRecordsCount );
+
+    for( size_t i = 0; i < static_cast<size_t>(SLRecordsCount); ++i )
+    {
+        SectionLocatorRecord readedRecord;
+        pFileIO->Read( & readedRecord.byRecordNumber, 1 );
+        pFileIO->Read( & readedRecord.dSeeker, 4 );
+        pFileIO->Read( & readedRecord.dSize, 4 );
+
+        sectionLocatorRecords.push_back( readedRecord );
+        DebugMsg( "  Record #%d : %d %d\n", sectionLocatorRecords[i].byRecordNumber, sectionLocatorRecords[i].dSeeker,
+                  sectionLocatorRecords[i].dSize );
+    }
+
+    return CADErrorCodes::SUCCESS;
+}
+
+CADDictionary DWGFileR2000::GetNOD()
+{
+    CADDictionary stNOD;
+
+    unique_ptr<CADDictionaryObject> spoNamedDictObj(
+            static_cast<CADDictionaryObject*>( GetObject( oTables.GetTableHandle(
+                CADTables::NamedObjectsDict ).getAsLong() ) ) );
+    if( spoNamedDictObj == nullptr )
+        return stNOD;
+
+    for( size_t i = 0; i < spoNamedDictObj->sItemNames.size(); ++i )
+    {
+        unique_ptr<CADObject> spoDictRecord (
+                    GetObject( spoNamedDictObj->hItemHandles[i].getAsLong() ) );
+
+        if( spoDictRecord == nullptr )
+            continue; // skip unreaded objects
+
+        if( spoDictRecord->getType() == CADObject::DICTIONARY )
+        {
+            // TODO: add implementation of DICTIONARY reading
+        }
+        else if( spoDictRecord->getType() == CADObject::XRECORD )
+        {
+            CADXRecord * cadxRecord = new CADXRecord();
+            CADXRecordObject * cadxRecordObject =
+                static_cast<CADXRecordObject*>(spoDictRecord.get());
+
+            string xRecordData( cadxRecordObject->abyDataBytes.begin(),
+                                cadxRecordObject->abyDataBytes.end() );
+            cadxRecord->setRecordData( xRecordData );
+
+            shared_ptr<CADDictionaryRecord> cadxRecordPtr(static_cast<CADDictionaryRecord*>(cadxRecord));
+
+            stNOD.addRecord( make_pair( spoNamedDictObj->sItemNames[i], cadxRecordPtr ) );
+        }
+    }
+
+    return stNOD;
+}
+
+unsigned short DWGFileR2000::validateEntityCRC(const char * pabyInput,
+        unsigned int dObjectSize, size_t & nBitOffsetFromStart,
+        const char * entityName, bool bSwapEndianness )
+{
+    const unsigned short CRC = static_cast<unsigned short>(ReadRAWSHORT(
+                                            pabyInput, nBitOffsetFromStart ));
+    if(bSwapEndianness)
+        SwapEndianness (CRC, sizeof (CRC));
+
+    const unsigned short initial = 0xC0C1;
+    const unsigned short calculated = CalculateCRC8( initial, pabyInput,
+                                                     static_cast<int>(dObjectSize) );
+    if( CRC != calculated )
+    {
+        DebugMsg( "Invalid CRC for %s object\nCRC read:0x%X calculated:0x%X\n",
+                                                  entityName, CRC, calculated );
+        return 0; // If CRC equal 0 - this is error
+    }
+    return CRC;
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/dwg/r2000.h b/ogr/ogrsf_frmts/cad/libopencad/dwg/r2000.h
new file mode 100644
index 0000000..39d6925
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/dwg/r2000.h
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef DWG_R2000_H_H
+#define DWG_R2000_H_H
+
+#include "cadfile.h"
+
+struct SectionLocatorRecord
+{
+    char byRecordNumber = 0;
+    int  dSeeker        = 0;
+    int  dSize          = 0;
+};
+
+struct DWG2000Ced
+{
+    long        dLength;
+    short       dType;
+    int         dObjSizeInBits;
+    CADHandle   hHandle;
+    CADEedArray eEED;
+    bool        bGraphicPresentFlag;
+
+    char dEntMode;
+    int  dNumReactors;
+
+    bool   bNoLinks;
+    short  dCMColorIndex;
+    double dfLtypeScale;
+
+    char ltype_flags;
+    char plotstyle_flags;
+
+    short dInvisibility;
+    char  cLineWeight;
+};
+
+struct DWG2000Cehd
+{
+    CADHandle hOwner;
+    CADHandle hReactors;
+    CADHandle hxdibobjhandle;
+    CADHandle hprev_entity, hnext_entity;
+    CADHandle hlayer;
+    CADHandle hltype;
+    CADHandle hplotstyle;
+};
+
+class DWGFileR2000 : public CADFile
+{
+public:
+    explicit             DWGFileR2000( CADFileIO * poFileIO );
+    virtual             ~DWGFileR2000();
+
+protected:
+    virtual int ReadSectionLocators() override;
+    virtual int ReadHeader( enum OpenOptions eOptions ) override;
+    virtual int ReadClasses( enum OpenOptions eOptions ) override;
+    virtual int CreateFileMap() override;
+
+    CADObject   * GetObject( long dHandle, bool bHandlesOnly = false ) override;
+    CADGeometry * GetGeometry( size_t iLayerIndex, long dHandle,
+                               long dBlockRefHandle = 0 ) override;
+
+    CADDictionary GetNOD() override;
+protected:
+    CADBlockObject * getBlock( unsigned int dObjectSize,
+                               const CADCommonED& stCommonEntityData,
+                               const char * pabyInput,
+                               size_t& nBitOffsetFromStart );
+    CADEllipseObject * getEllipse( unsigned int dObjectSize,
+                                   const CADCommonED& stCommonEntityData,
+                                   const char * pabyInput,
+                                   size_t& nBitOffsetFromStart );
+    CADSolidObject * getSolid( unsigned int dObjectSize,
+                               const CADCommonED& stCommonEntityData,
+                               const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADPointObject * getPoint( unsigned int dObjectSize,
+                               const CADCommonED& stCommonEntityData,
+                               const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADPolyline3DObject * getPolyLine3D( unsigned int dObjectSize,
+                                         const CADCommonED& stCommonEntityData,
+                                         const char * pabyInput,
+                                         size_t& nBitOffsetFromStart );
+    CADRayObject * getRay( unsigned int dObjectSize,
+                           const CADCommonED& stCommonEntityData,
+                           const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADXLineObject * getXLine( unsigned int dObjectSize,
+                               const CADCommonED& stCommonEntityData,
+                               const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADLineObject * getLine( unsigned int dObjectSize,
+                             const CADCommonED& stCommonEntityData,
+                             const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADTextObject * getText( unsigned int dObjectSize,
+                             const CADCommonED& stCommonEntityData,
+                             const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADVertex3DObject * getVertex3D( unsigned int dObjectSize,
+                                     const CADCommonED& stCommonEntityData,
+                                     const char * pabyInput,
+                                     size_t& nBitOffsetFromStart );
+    CADCircleObject * getCircle( unsigned int dObjectSize,
+                                 const CADCommonED& stCommonEntityData,
+                                 const char * pabyInput,
+                                 size_t& nBitOffsetFromStart );
+    CADEndblkObject * getEndBlock( unsigned int dObjectSize,
+                                   const CADCommonED& stCommonEntityData,
+                                   const char * pabyInput,
+                                   size_t& nBitOffsetFromStart );
+    CADPolyline2DObject * getPolyline2D( unsigned int dObjectSize,
+                                         const CADCommonED& stCommonEntityData,
+                                         const char * pabyInput,
+                                         size_t& nBitOffsetFromStart );
+    CADAttribObject * getAttributes( unsigned int dObjectSize,
+                                     const CADCommonED& stCommonEntityData,
+                                     const char * pabyInput,
+                                     size_t& nBitOffsetFromStart );
+    CADAttdefObject * getAttributesDefn( unsigned int dObjectSize,
+                                         const CADCommonED& stCommonEntityData,
+                                         const char * pabyInput,
+                                         size_t& nBitOffsetFromStart );
+    CADLWPolylineObject * getLWPolyLine( unsigned int dObjectSize,
+                                         const CADCommonED& stCommonEntityData,
+                                         const char * pabyInput,
+                                         size_t& nBitOffsetFromStart );
+    CADArcObject * getArc( unsigned int dObjectSize,
+                           const CADCommonED& stCommonEntityData,
+                           const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADSplineObject * getSpline( unsigned int dObjectSize,
+                                 const CADCommonED& stCommonEntityData,
+                                 const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADEntityObject * getEntity( int dObjectType, unsigned int dObjectSize,
+                                 const CADCommonED& stCommonEntityData,
+                                 const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADInsertObject * getInsert( int dObjectType, unsigned int dObjectSize,
+                                 const CADCommonED& stCommonEntityData,
+                                 const char * pabyInput, size_t& nBitOffsetFromStart );
+    CADDictionaryObject * getDictionary( unsigned int dObjectSize,
+                                         const char * pabyInput,
+                                         size_t& nBitOffsetFromStart );
+    CADXRecordObject * getXRecord( unsigned int dObjectSize,
+                                   const char * pabyInput,
+                                   size_t& nBitOffsetFromStart );
+    CADLayerObject * getLayerObject( unsigned int dObjectSize,
+                                     const char * pabyInput,
+                                     size_t& nBitOffsetFromStart );
+    CADLayerControlObject * getLayerControl( unsigned int dObjectSize,
+                                             const char * pabyInput,
+                                             size_t& nBitOffsetFromStart );
+    CADBlockControlObject * getBlockControl( unsigned int dObjectSize,
+                                             const char * pabyInput,
+                                             size_t& nBitOffsetFromStart );
+    CADBlockHeaderObject * getBlockHeader( unsigned int dObjectSize,
+                                           const char * pabyInput,
+                                           size_t& nBitOffsetFromStart );
+    CADLineTypeControlObject * getLineTypeControl( unsigned int dObjectSize,
+                                                   const char * pabyInput,
+                                                   size_t& nBitOffsetFromStart );
+    CADLineTypeObject * getLineType1( unsigned int dObjectSize,
+                                      const char * pabyInput,
+                                      size_t& nBitOffsetFromStart );
+    CADMLineObject * getMLine( unsigned int dObjectSize,
+                               const CADCommonED& stCommonEntityData,
+                               const char * pabyInput,
+                               size_t& nBitOffsetFromStart );
+    CADPolylinePFaceObject * getPolylinePFace( unsigned int dObjectSize,
+                                               const CADCommonED& stCommonEntityData,
+                                               const char * pabyInput,
+                                               size_t& nBitOffsetFromStart );
+    CADImageObject * getImage( unsigned int dObjectSize,
+                               const CADCommonED& stCommonEntityData,
+                               const char * pabyInput,
+                               size_t& nBitOffsetFromStart );
+    CAD3DFaceObject * get3DFace( unsigned int dObjectSize,
+                                 const CADCommonED& stCommonEntityData,
+                                 const char * pabyInput,
+                                 size_t& nBitOffsetFromStart );
+    CADVertexMeshObject * getVertexMesh( unsigned int dObjectSize,
+                                         const CADCommonED& stCommonEntityData,
+                                         const char * pabyInput,
+                                         size_t& nBitOffsetFromStart );
+    CADVertexPFaceObject * getVertexPFace( unsigned int dObjectSize,
+                                           const CADCommonED& stCommonEntityData,
+                                           const char * pabyInput,
+                                           size_t& nBitOffsetFromStart );
+    CADDimensionObject * getDimension( short dObjectType, unsigned int dObjectSize,
+                                       const CADCommonED& stCommonEntityData,
+                                       const char * pabyInput,
+                                       size_t& nBitOffsetFromStart );
+    CADMTextObject * getMText( unsigned int dObjectSize,
+                               const CADCommonED& stCommonEntityData,
+                               const char * pabyInput,
+                               size_t& nBitOffsetFromStart );
+    CADImageDefObject * getImageDef( unsigned int dObjectSize,
+                                     const char * pabyInput,
+                                     size_t& nBitOffsetFromStart );
+    CADImageDefReactorObject * getImageDefReactor( unsigned int dObjectSize,
+                                                   const char * pabyInput,
+                                                   size_t& nBitOffsetFromStart );
+    void fillCommonEntityHandleData( CADEntityObject * pEnt, const char * pabyInput,
+                                                         size_t& nBitOffsetFromStart );
+    unsigned short validateEntityCRC(const char * pabyInput,
+        unsigned int dObjectSize, size_t & nBitOffsetFromStart,
+        const char * entityName = "ENTITY", bool bSwapEndianness = false );
+protected:
+    int                               imageSeeker;
+    std::vector<SectionLocatorRecord> sectionLocatorRecords;
+};
+
+#endif // DWG_R2000_H_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/makefile.vc b/ogr/ogrsf_frmts/cad/libopencad/makefile.vc
new file mode 100644
index 0000000..64d7a04
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/makefile.vc
@@ -0,0 +1,34 @@
+#
+# Makefile building opencad library
+#
+
+OBJ = \
+	cadclasses.obj \
+	caddictionary.obj \
+	cadcolors.obj \
+	cadfile.obj \
+	cadfileio.obj \
+	cadfilestreamio.obj \
+	cadgeometry.obj \
+	cadheader.obj \
+	cadlayer.obj \
+	cadobjects.obj \
+	cadtables.obj \
+	opencad.obj
+
+GDAL_ROOT	=	..\..\..\..
+EXTRAFLAGS =	-I. -I.. -I..\.. -I..\..\.. -Idwg $(SOFTWARNFLAGS) -DOCAD_EXTERN=""
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	cd dwg
+	$(MAKE) /f makefile.vc
+	cd ..
+
+clean:
+	cd dwg
+	$(MAKE) /f makefile.vc clean
+	cd ..
+	-del *.lib
+	-del *.obj *.pdb
diff --git a/ogr/ogrsf_frmts/cad/libopencad/opencad.cpp b/ogr/ogrsf_frmts/cad/libopencad/opencad.cpp
new file mode 100644
index 0000000..e4a21b8
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/opencad.cpp
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ *  Project: libopencad_api.cpp
+ *  Purpose: libOpenCAD OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "opencad_api.h"
+#include "cadfilestreamio.h"
+#include "dwg/r2000.h"
+
+#include <cctype>
+#include <cstdarg>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+static int gLastError = CADErrorCodes::SUCCESS;
+
+/**
+ * @brief Check CAD file
+ * @param pCADFileIO CAD file reader pointer owned by function
+ * @return returns and int, 0 if CAD file has unsupported format
+ */
+static int CheckCADFile(CADFileIO * pCADFileIO)
+{
+    if( pCADFileIO == nullptr )
+        return 0;
+
+    const char * pszFilePath = pCADFileIO->GetFilePath();
+    size_t nPathLen = strlen( pszFilePath );
+
+    if( toupper( pszFilePath[nPathLen - 3] ) == 'D' &&
+        toupper( pszFilePath[nPathLen - 2] ) == 'X' &&
+        toupper( pszFilePath[nPathLen - 1] ) == 'F' )
+    {
+        //TODO: "AutoCAD Binary DXF"
+        std::cerr << "DXF ASCII and binary is not supported yet.";
+        return 0;
+    }
+    if( ! ( toupper( pszFilePath[nPathLen - 3] ) == 'D' &&
+            toupper( pszFilePath[nPathLen - 2] ) == 'W' &&
+            toupper( pszFilePath[nPathLen - 1] ) == 'G' ) )
+    {
+        return 0;
+    }
+
+    if( !pCADFileIO->IsOpened() )
+        pCADFileIO->Open( CADFileIO::OpenMode::read | CADFileIO::OpenMode::binary );
+    if( !pCADFileIO->IsOpened() )
+        return 0;
+
+    char pabyDWGVersion[DWG_VERSION_STR_SIZE + 1] = { 0 };
+    pCADFileIO->Rewind ();
+    pCADFileIO->Read( pabyDWGVersion, DWG_VERSION_STR_SIZE );
+    return atoi( pabyDWGVersion + 2 );
+}
+
+/**
+ * @brief Open CAD file
+ * @param pCADFileIO CAD file reader pointer ownd by function
+ * @param eOptions Open options
+ * @param bReadUnsupportedGeometries Unsupported geoms will be returned as CADUnknown
+ * @return CADFile pointer or NULL if failed. The pointer have to be freed by user
+ */
+CADFile * OpenCADFile( CADFileIO * pCADFileIO, enum CADFile::OpenOptions eOptions, bool bReadUnsupportedGeometries )
+{
+    int nCADFileVersion = CheckCADFile( pCADFileIO );
+    CADFile * poCAD = nullptr;
+
+    switch( nCADFileVersion )
+    {
+        case CADVersions::DWG_R2000:
+            poCAD = new DWGFileR2000( pCADFileIO );
+            break;
+        default:
+            gLastError = CADErrorCodes::UNSUPPORTED_VERSION;
+            delete pCADFileIO;
+            return nullptr;
+    }
+
+    gLastError = poCAD->ParseFile( eOptions, bReadUnsupportedGeometries );
+    if( gLastError != CADErrorCodes::SUCCESS )
+    {
+        delete poCAD;
+        return nullptr;
+    }
+
+    return poCAD;
+}
+
+
+/**
+ * @brief Get library version number as major * 10000 + minor * 100 + rev
+ * @return library version number
+ */
+int GetVersion()
+{
+    return OCAD_VERSION_NUM;
+}
+
+/**
+ * @brief Get library version string
+ * @return library version string
+ */
+const char * GetVersionString()
+{
+    return OCAD_VERSION;
+}
+
+/**
+ * @brief Get last error code
+ * @return last error code
+ */
+int GetLastErrorCode()
+{
+    return gLastError;
+}
+
+/**
+ * @brief GetDefaultFileIO return default file in/out class.
+ * @param pszFileName CAD file path
+ * @return CADFileIO pointer or null if error. The pointer have to be freed by
+ * user
+ */
+CADFileIO* GetDefaultFileIO( const char * pszFileName )
+{
+    return new CADFileStreamIO( pszFileName );
+}
+
+/**
+ * @brief IdentifyCADFile
+ * @param pCADFileIO pointer to file in/out class
+ * @return positive number for dwg version, negative for dxf version, 0 if error
+ * occurred
+ */
+int IdentifyCADFile( CADFileIO * pCADFileIO, bool bOwn )
+{
+    int result = CheckCADFile(pCADFileIO);
+    if(bOwn)
+    {
+        delete pCADFileIO;
+    }
+    return result;
+}
+
+/**
+ * @brief List supported CAD Formats
+ * @return String describes supported CAD formats
+ */
+const char * GetCADFormats()
+{
+    return "DWG R2000 [ACAD1015]\n";
+}
+
+/**
+ * @brief Open CAD file
+ * @param pszFileName Path to CAD file
+ * @param eOptions Open options
+ * @return CADFile pointer or NULL if failed. The pointer have to be freed by user.
+ */
+CADFile * OpenCADFile( const char * pszFileName, enum CADFile::OpenOptions eOptions, bool bReadUnsupportedGeometries )
+{
+    return OpenCADFile( GetDefaultFileIO( pszFileName ), eOptions, bReadUnsupportedGeometries );
+}
+
+#ifdef _DEBUG
+void DebugMsg( const char* format, ... )
+#else
+void DebugMsg( const char*, ... )
+#endif
+{
+#ifdef _DEBUG
+    va_list argptr;
+    va_start( argptr, format );
+    vfprintf( stdout, format, argptr );
+    va_end( argptr );
+#endif //_DEBUG
+}
diff --git a/ogr/ogrsf_frmts/cad/libopencad/opencad.h b/ogr/ogrsf_frmts/cad/libopencad/opencad.h
new file mode 100644
index 0000000..519f4c8
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/opencad.h
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef OPENCAD_H
+#define OPENCAD_H
+
+#define OCAD_VERSION    "0.3.2"
+#define OCAD_VERSION_MAJOR 0
+#define OCAD_VERSION_MINOR 3
+#define OCAD_VERSION_REV   2
+
+#ifndef OCAD_COMPUTE_VERSION
+#define OCAD_COMPUTE_VERSION(maj,min,rev) ((maj)*10000+(min)*100+rev) // maj - any, min < 99, rev < 99
+#endif
+
+#define OCAD_VERSION_NUM OCAD_COMPUTE_VERSION(OCAD_VERSION_MAJOR,OCAD_VERSION_MINOR,OCAD_VERSION_REV)
+
+/*  check if the current version is at least major.minor.revision */
+#define CHECK_VERSION(major,minor,rev) \
+    (OCAD_VERSION_MAJOR > (major) || \
+    (OCAD_VERSION_MAJOR == (major) && OCAD_VERSION_MINOR > (minor)) || \
+    (OCAD_VERSION_MAJOR == (major) && OCAD_VERSION_MINOR == (minor) && OCAD_VERSION_REV >= (release)))
+
+#define DWG_VERSION_STR_SIZE  6
+
+#ifndef OCAD_EXTERN
+#ifdef OCAD_STATIC
+  #define OCAD_EXTERN extern
+#else
+#   if defined (_MSC_VER)
+#    ifdef OCAD_EXPORTS
+#      ifdef __GNUC__
+#        define OCAD_EXTERN extern __attribute__((dllexport))
+#      else
+#        define OCAD_EXTERN extern __declspec(dllexport)
+#      endif
+#    else
+#      ifdef __GNUC__
+#        define OCAD_EXTERN extern __attribute__((dllimport))
+#      else
+#        define OCAD_EXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#   else
+#     if __GNUC__ >= 4
+#       define OCAD_EXTERN __attribute__((visibility("default")))
+#     else
+#       define OCAD_EXTERN                extern
+#     endif
+#   endif
+#endif
+#endif
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+# define OCAD_PRINT_FUNC_FORMAT( format_idx, arg_idx ) __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#else
+#  define OCAD_PRINT_FUNC_FORMAT( format_idx, arg_idx )
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER < 1900)
+#  define snprintf _snprintf
+#endif
+
+void DebugMsg(const char *, ...) OCAD_PRINT_FUNC_FORMAT (1,2);
+
+#endif // OPENCAD_H
diff --git a/ogr/ogrsf_frmts/cad/libopencad/opencad_api.h b/ogr/ogrsf_frmts/cad/libopencad/opencad_api.h
new file mode 100644
index 0000000..416dcfc
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/libopencad/opencad_api.h
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef OPENCAD_API_H
+#define OPENCAD_API_H
+
+#include "cadfile.h"
+
+enum CADVersions
+{
+    DWG_R13   = 1012,
+    DWG_R14   = 1014,
+    DWG_R2000 = 1015,
+    DWG_R2004 = 1018,
+    DWG_R2007 = 1021,
+    DWG_R2010 = 1024,
+    DWG_R2013 = 1027,
+    DXF_UNDEF = -1000,
+    DXF_R13   = -DWG_R13,
+    DXF_R14   = -DWG_R14,
+    DXF_R2000 = -DWG_R2000,
+    DXF_R2004 = -DWG_R2004,
+    DXF_R2007 = -DWG_R2007,
+    DXF_R2010 = -DWG_R2010,
+    DXF_R2013 = -DWG_R2013
+};
+
+enum CADErrorCodes
+{
+    SUCCESS = 0,                /**< operation successfully executed */
+    FILE_OPEN_FAILED,           /**< failed to open CAD file */
+    UNSUPPORTED_VERSION,        /**< unsupported CAD file version */
+    FILE_PARSE_FAILED,          /**< failed to parse file */
+    SECTION_LOCATOR_READ_FAILED,/**< failed to read section locator */
+    HEADER_SECTION_READ_FAILED, /**< failed to read header section */
+    CLASSES_SECTION_READ_FAILED,/**< failed to read classes section */
+    TABLES_SECTION_READ_FAILED, /**< failed to read tables section */
+    BLOCKS_SECTION_READ_FAILED, /**< failed to read blocks section */
+    ENTITIES_SECTION_READ_FAILED,/**< failed to read entities section */
+    OBJECTS_SECTION_READ_FAILED, /**< failed to read objects section */
+    THUMBNAILIMAGE_SECTION_READ_FAILED, /**< failed to read thumbnailimage section */
+    TABLE_READ_FAILED,          /**< failed to read table*/
+    VALUE_EXISTS                /**< the value already exist in the header */
+};
+
+OCAD_EXTERN int GetVersion();
+OCAD_EXTERN const char * GetVersionString();
+OCAD_EXTERN CADFile    * OpenCADFile( CADFileIO * pCADFileIO, enum CADFile::OpenOptions eOptions,
+                                      bool bReadUnsupportedGeometries = false );
+OCAD_EXTERN CADFile    * OpenCADFile( const char * pszFileName, enum CADFile::OpenOptions eOptions,
+                                      bool bReadUnsupportedGeometries = false );
+OCAD_EXTERN int GetLastErrorCode();
+OCAD_EXTERN CADFileIO * GetDefaultFileIO( const char * pszFileName );
+OCAD_EXTERN int IdentifyCADFile( CADFileIO * pCADFileIO, bool bOwn = true );
+OCAD_EXTERN const char * GetCADFormats();
+
+#endif // OPENCAD_API_H
diff --git a/ogr/ogrsf_frmts/cad/makefile.vc b/ogr/ogrsf_frmts/cad/makefile.vc
new file mode 100644
index 0000000..b9bf4d1
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/makefile.vc
@@ -0,0 +1,21 @@
+
+OBJ	=	ogrcaddriver.obj gdalcaddataset.obj ogrcadlayer.obj vsilfileio.obj
+
+EXTRAFLAGS =	-I.. -I..\.. -Ilibopencad $(SOFTWARNFLAGS) -DOCAD_EXTERN=""
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+default:	$(OBJ)
+	cd libopencad
+	$(MAKE) /f makefile.vc
+	cd ..
+
+clean:
+	cd libopencad
+	$(MAKE) /f makefile.vc clean
+	cd ..
+	-del *.lib
+	-del *.obj *.pdb
+
diff --git a/ogr/ogrsf_frmts/cad/ogr_cad.h b/ogr/ogrsf_frmts/cad/ogr_cad.h
new file mode 100644
index 0000000..1b809e5
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/ogr_cad.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ *  Project: OGR CAD Driver
+ *  Purpose: Implements driver based on libopencad
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, polimax at mail.ru
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016, NextGIS
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#ifndef OGR_CAD_H_INCLUDED
+#define OGR_CAD_H_INCLUDED
+
+// gdal headers
+#include "ogrsf_frmts.h"
+
+// libopencad headers
+#include "cadgeometry.h"
+#include "opencad_api.h"
+
+#include <set>
+
+class OGRCADLayer : public OGRLayer
+{
+    OGRFeatureDefn  *poFeatureDefn;
+    OGRSpatialReference * poSpatialRef;
+    GIntBig         nNextFID;
+    CADLayer        &poCADLayer;
+    int             nDWGEncoding;
+
+public:
+    OGRCADLayer( CADLayer &poCADLayer, OGRSpatialReference *poSR, int nEncoding );
+    ~OGRCADLayer();
+
+    void            ResetReading() override;
+    OGRFeature      *GetNextFeature() override;
+    OGRFeature      *GetFeature( GIntBig nFID ) override;
+    GIntBig         GetFeatureCount( int /* bForce */ ) override;
+    OGRSpatialReference *GetSpatialRef() override { return poSpatialRef; }
+    OGRFeatureDefn  *GetLayerDefn() override { return poFeatureDefn; }
+    std::set< CPLString > asFeaturesAttributes;
+    int             TestCapability( const char * ) override { return( FALSE ); }
+};
+
+class GDALCADDataset : public GDALDataset
+{
+    CPLString      osCADFilename;
+    CADFile       *poCADFile;
+    // vector
+    OGRCADLayer  **papoLayers;
+    int            nLayers;
+    // raster
+    CPLString      soWKT;
+    double         adfGeoTransform[6];
+    GDALDataset   *poRasterDS;
+    OGRSpatialReference *poSpatialReference;
+
+public:
+    GDALCADDataset();
+    virtual ~GDALCADDataset();
+
+    int            Open( GDALOpenInfo* poOpenInfo, CADFileIO* pFileIO,
+                            long nSubRasterLayer = -1, long nSubRasterFID = -1 );
+    int            GetLayerCount() override { return nLayers; }
+    OGRLayer      *GetLayer( int ) override;
+    int            TestCapability( const char * ) override;
+    virtual char **GetFileList() override;
+    virtual const char  *GetProjectionRef(void) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
+    virtual int CloseDependentDatasets() override;
+
+protected:
+    OGRSpatialReference *GetSpatialReference();
+    const char* GetPrjFilePath();
+    void FillTransform(CADImage* pImage, double dfUnits);
+    int GetCadEncoding() const;
+private:
+    CPL_DISALLOW_COPY_ASSIGN(GDALCADDataset);
+};
+
+CPLString CADRecode( const CPLString& sString, int CADEncoding );
+
+#endif
diff --git a/ogr/ogrsf_frmts/cad/ogrcaddriver.cpp b/ogr/ogrsf_frmts/cad/ogrcaddriver.cpp
new file mode 100644
index 0000000..65d3c83
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/ogrcaddriver.cpp
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ *  Project: OGR CAD Driver
+ *  Purpose: Implements driver based on libopencad
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, polimax at mail.ru
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016, NextGIS
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "ogr_cad.h"
+#include "vsilfileio.h"
+
+/************************************************************************/
+/*                           OGRCADDriverIdentify()                     */
+/************************************************************************/
+
+static int OGRCADDriverIdentify( GDALOpenInfo *poOpenInfo )
+{
+    if ( poOpenInfo->nHeaderBytes < 6 )
+        return FALSE;
+
+    if ( poOpenInfo->pabyHeader[0] != 'A' ||
+        poOpenInfo->pabyHeader[1] != 'C' )
+        return FALSE;
+
+    return IdentifyCADFile ( new VSILFileIO( poOpenInfo->pszFilename ), true ) == 0 ?
+        FALSE : TRUE;
+}
+
+/************************************************************************/
+/*                           OGRCADDriverOpen()                         */
+/************************************************************************/
+
+static GDALDataset *OGRCADDriverOpen( GDALOpenInfo* poOpenInfo )
+{
+    long nSubRasterLayer = -1;
+    long nSubRasterFID = -1;
+
+    CADFileIO* pFileIO;
+    if ( STARTS_WITH_CI(poOpenInfo->pszFilename, "CAD:") )
+    {
+        char** papszTokens = CSLTokenizeString2( poOpenInfo->pszFilename, ":", 0 );
+        int nTokens = CSLCount( papszTokens );
+        if( nTokens < 4 )
+        {
+            CSLDestroy(papszTokens);
+            return NULL;
+        }
+
+        CPLString osFilename;
+        for( int i = 1; i < nTokens - 2; ++i )
+        {
+            if( osFilename.empty() )
+                osFilename += ":";
+            osFilename += papszTokens[i];
+        }
+
+        pFileIO = new VSILFileIO( osFilename );
+        nSubRasterLayer = atol( papszTokens[nTokens - 2] );
+        nSubRasterFID = atol( papszTokens[nTokens - 1] );
+
+        CSLDestroy( papszTokens );
+    }
+    else
+    {
+        pFileIO = new VSILFileIO( poOpenInfo->pszFilename );
+    }
+
+    if ( IdentifyCADFile( pFileIO, false ) == FALSE )
+    {
+        delete pFileIO;
+        return NULL;
+    }
+
+
+/* -------------------------------------------------------------------- */
+/*      Confirm the requested access is supported.                      */
+/* -------------------------------------------------------------------- */
+    if( poOpenInfo->eAccess == GA_Update )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "The CAD driver does not support update access to existing"
+                  " datasets.\n" );
+        delete pFileIO;
+        return NULL;
+    }
+
+    GDALCADDataset *poDS = new GDALCADDataset();
+    if( !poDS->Open( poOpenInfo, pFileIO, nSubRasterLayer, nSubRasterFID ) )
+    {
+        delete poDS;
+        return NULL;
+    }
+    else
+        return poDS;
+}
+
+/************************************************************************/
+/*                           RegisterGDALCAD()                          */
+/************************************************************************/
+
+void RegisterOGRCAD()
+{
+    GDALDriver  *poDriver;
+
+    if ( GDALGetDriverByName( "CAD" ) == NULL )
+    {
+        poDriver = new GDALDriver();
+        poDriver->SetDescription( "CAD" );
+        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+        poDriver->SetMetadataItem( GDAL_DMD_SUBDATASETS, "YES" );
+        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "AutoCAD Driver" );
+        poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dwg" );
+        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_cad.html" );
+
+        poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList>"
+"  <Option name='MODE' type='string' description='Open mode. READ_ALL - read all data (slow), READ_FAST - read main data (fast), READ_FASTEST - read less data' default='READ_FAST'/>"
+"  <Option name='ADD_UNSUPPORTED_GEOMETRIES_DATA' type='string' description='Add unsupported geometries data (color, attributes) to the layer (YES/NO). They will have no geometrical representation.' default='NO'/>"
+"</OpenOptionList>");
+
+
+        poDriver->pfnOpen = OGRCADDriverOpen;
+        poDriver->pfnIdentify = OGRCADDriverIdentify;
+        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+        GetGDALDriverManager()->RegisterDriver( poDriver );
+    }
+}
+
+CPLString CADRecode( const CPLString& sString, int CADEncoding )
+{
+    const char* pszSource[] = {
+        /* 0 UNDEFINED */ "",
+        /* 1 ASCII */ "US-ASCII",
+        /* 2 8859_1 */ "ISO-8859-1",
+        /* 3 8859_2 */ "ISO-8859-2",
+        /* 4 UNDEFINED */ "",
+        /* 5 8859_4 */ "ISO-8859-4",
+        /* 6 8859_5 */ "ISO-8859-5",
+        /* 7 8859_6 */ "ISO-8859-6",
+        /* 8 8859_7 */ "ISO-8859-7",
+        /* 9 8859_8 */ "ISO-8859-8",
+        /* 10 8859_9 */ "ISO-8859-9",
+        /* 11 DOS437 */ "CP437",
+        /* 12 DOS850 */ "CP850",
+        /* 13 DOS852 */ "CP852",
+        /* 14 DOS855 */ "CP855",
+        /* 15 DOS857 */ "CP857",
+        /* 16 DOS860 */ "CP860",
+        /* 17 DOS861 */ "CP861",
+        /* 18 DOS863 */ "CP863",
+        /* 19 DOS864 */ "CP864",
+        /* 20 DOS865 */ "CP865",
+        /* 21 DOS869 */ "CP869",
+        /* 22 DOS932 */ "CP932",
+        /* 23 MACINTOSH */ "MACINTOSH",
+        /* 24 BIG5 */ "BIG5",
+        /* 25 KSC5601 */ "CP949",
+        /* 26 JOHAB */ "JOHAB",
+        /* 27 DOS866 */ "CP866",
+        /* 28 ANSI_1250 */ "CP1250",
+        /* 29 ANSI_1251 */ "CP1251",
+        /* 30 ANSI_1252 */ "CP1252",
+        /* 31 GB2312 */ "GB2312",
+        /* 32 ANSI_1253 */ "CP1253",
+        /* 33 ANSI_1254 */ "CP1254",
+        /* 34 ANSI_1255 */ "CP1255",
+        /* 35 ANSI_1256 */ "CP1256",
+        /* 36 ANSI_1257 */ "CP1257",
+        /* 37 ANSI_874 */ "CP874",
+        /* 38 ANSI_932 */ "CP932",
+        /* 39 ANSI_936 */ "CP936",
+        /* 40 ANSI_949 */ "CP949",
+        /* 41 ANSI_950 */ "CP950",
+        /* 42 ANSI_1361 */ "CP1361",
+        /* 43 ANSI_1200 */ "UTF-16",
+        /* 44 ANSI_1258 */ "CP1258"
+    };
+
+    if( CADEncoding > 0 &&
+        CADEncoding < static_cast<int>(sizeof(pszSource) / sizeof(pszSource[0])) &&
+        CADEncoding != 4 )
+    {
+        char* pszRecoded = CPLRecode( sString, pszSource[CADEncoding], CPL_ENC_UTF8 );
+        CPLString soRecoded(pszRecoded);
+        CPLFree(pszRecoded);
+        return soRecoded;
+    }
+    CPLError( CE_Failure, CPLE_NotSupported,
+            "CADRecode() function does not support provided CADEncoding." );
+    return CPLString("");
+}
diff --git a/ogr/ogrsf_frmts/cad/ogrcadlayer.cpp b/ogr/ogrsf_frmts/cad/ogrcadlayer.cpp
new file mode 100644
index 0000000..b7de25c
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/ogrcadlayer.cpp
@@ -0,0 +1,761 @@
+/*******************************************************************************
+ *  Project: OGR CAD Driver
+ *  Purpose: Implements driver based on libopencad
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, polimax at mail.ru
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016, NextGIS <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ *******************************************************************************/
+#include "cpl_conv.h"
+#include "ogr_cad.h"
+
+#include <iomanip>
+#include <sstream>
+
+#define FIELD_NAME_GEOMTYPE "cadgeom_type"
+#define FIELD_NAME_THICKNESS "thickness"
+#define FIELD_NAME_COLOR "color"
+#define FIELD_NAME_EXT_DATA "extentity_data"
+#define FIELD_NAME_TEXT "text"
+
+static const double DEG2RAD = M_PI / 180.0;
+// UNUSED static const double RAD2DEG = 1.0 / DEG2RAD;
+
+OGRCADLayer::OGRCADLayer( CADLayer &poCADLayer_, OGRSpatialReference *poSR,
+                          int nEncoding) :
+                          poSpatialRef( poSR ),
+                          poCADLayer( poCADLayer_ ),
+                          nDWGEncoding( nEncoding)
+{
+    nNextFID = 0;
+
+    if( poSpatialRef )
+        poSpatialRef->Reference();
+    poFeatureDefn = new OGRFeatureDefn( CADRecode( poCADLayer_.getName(), nDWGEncoding ) );
+
+    // Setting up layer geometry type
+    OGRwkbGeometryType eGeomType;
+    char dLineStringPresented = 0;
+    char dCircularStringPresented = 0;
+    char dPointPresented = 0;
+    char dPolygonPresented = 0;
+    std::vector<CADObject::ObjectType> aePresentedGeometryTypes =
+                                                    poCADLayer.getGeometryTypes();
+    for( size_t i = 0; i < aePresentedGeometryTypes.size(); ++i )
+    {
+        switch( aePresentedGeometryTypes[i] )
+        {
+        case CADObject::ATTDEF:
+        case CADObject::TEXT:
+        case CADObject::MTEXT:
+        case CADObject::POINT:
+            dPointPresented = 1;
+            break;
+        case CADObject::CIRCLE:
+            dCircularStringPresented = 1;
+            break;
+        case CADObject::SPLINE:
+        case CADObject::ELLIPSE:
+        case CADObject::ARC:
+        case CADObject::POLYLINE3D:
+        case CADObject::POLYLINE2D:
+        case CADObject::LWPOLYLINE:
+        case CADObject::LINE:
+            dLineStringPresented = 1;
+            break;
+        case CADObject::FACE3D:
+        case CADObject::SOLID:
+            dPolygonPresented = 1;
+            break;
+        default:
+            break;
+        }
+    }
+
+    if( ( dLineStringPresented +
+          dCircularStringPresented +
+          dPointPresented +
+          dPolygonPresented ) > 1 )
+    {
+        eGeomType = wkbGeometryCollection;
+    }
+    else
+    {
+        if( dLineStringPresented )
+        {
+            eGeomType = wkbLineString;
+        }
+        else if( dCircularStringPresented )
+        {
+            eGeomType = wkbCircularString;
+        }
+        else if( dPointPresented )
+        {
+            eGeomType = wkbPoint;
+        }
+        else if( dPolygonPresented )
+        {
+            eGeomType = wkbPolygon;
+        }
+        else
+        {
+            eGeomType = wkbUnknown;
+        }
+    }
+    poFeatureDefn->SetGeomType( eGeomType );
+
+    OGRFieldDefn  oClassField( FIELD_NAME_GEOMTYPE, OFTString );
+    poFeatureDefn->AddFieldDefn( &oClassField );
+
+    OGRFieldDefn  oLinetypeField( FIELD_NAME_THICKNESS, OFTReal );
+    poFeatureDefn->AddFieldDefn( &oLinetypeField );
+
+    OGRFieldDefn  oColorField( FIELD_NAME_COLOR, OFTString );
+    poFeatureDefn->AddFieldDefn( &oColorField );
+
+    OGRFieldDefn  oExtendedField( FIELD_NAME_EXT_DATA, OFTString );
+    poFeatureDefn->AddFieldDefn( &oExtendedField );
+
+    OGRFieldDefn  oTextField( FIELD_NAME_TEXT, OFTString );
+    poFeatureDefn->AddFieldDefn( &oTextField );
+
+    auto oAttrTags = poCADLayer.getAttributesTags();
+    for( const std::string & osTag : oAttrTags )
+    {
+        auto ret = asFeaturesAttributes.insert( osTag );
+        if( ret.second == true)
+        {
+            OGRFieldDefn oAttrField( osTag.c_str(), OFTString );
+            poFeatureDefn->AddFieldDefn( &oAttrField );
+        }
+    }
+
+    // Applying spatial ref info
+    if (poFeatureDefn->GetGeomFieldCount() != 0)
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSpatialRef );
+
+    SetDescription( poFeatureDefn->GetName() );
+    poFeatureDefn->Reference();
+}
+
+GIntBig OGRCADLayer::GetFeatureCount( int bForce )
+{
+    if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
+        return OGRLayer::GetFeatureCount( bForce );
+
+    return poCADLayer.getGeometryCount();
+}
+
+OGRCADLayer::~OGRCADLayer()
+{
+    if( poSpatialRef )
+        poSpatialRef->Release();
+    poFeatureDefn->Release();
+}
+
+void OGRCADLayer::ResetReading()
+{
+    nNextFID = 0;
+}
+
+OGRFeature *OGRCADLayer::GetNextFeature()
+{
+    OGRFeature *poFeature = GetFeature( nNextFID );
+    ++nNextFID;
+
+    if( poFeature == NULL )
+        return NULL;
+
+    if( ( m_poFilterGeom == NULL ||  FilterGeometry( poFeature->GetGeometryRef() ) )
+        && ( m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature ) ) )
+    {
+        return poFeature;
+    }
+
+    return NULL;
+}
+
+OGRFeature *OGRCADLayer::GetFeature( GIntBig nFID )
+{
+    if( poCADLayer.getGeometryCount() <= static_cast<size_t>(nFID)
+        || nFID < 0 )
+    {
+        return NULL;
+    }
+
+    OGRFeature  *poFeature = NULL;
+    CADGeometry *poCADGeometry = poCADLayer.getGeometry( nFID );
+
+    if( NULL == poCADGeometry || GetLastErrorCode() != CADErrorCodes::SUCCESS )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                 "Failed to get geometry with ID = " CPL_FRMT_GIB " from layer \"%s\". Libopencad errorcode: %d",
+                 nFID, poCADLayer.getName().c_str(), GetLastErrorCode() );
+        return NULL;
+    }
+
+    poFeature = new OGRFeature( poFeatureDefn );
+    poFeature->SetFID( nFID );
+    poFeature->SetField( FIELD_NAME_THICKNESS, poCADGeometry->getThickness() );
+
+    if( !poCADGeometry->getEED().empty() )
+    {
+        std::vector<std::string> asGeometryEED = poCADGeometry->getEED();
+        std::string sEEDAsOneString = "";
+        for ( std::vector<std::string>::const_iterator
+              iter = asGeometryEED.cbegin();
+              iter != asGeometryEED.cend(); ++iter )
+        {
+            sEEDAsOneString += *iter;
+            sEEDAsOneString += ' ';
+        }
+
+        poFeature->SetField( FIELD_NAME_EXT_DATA, sEEDAsOneString.c_str() );
+    }
+
+    RGBColor stRGB = poCADGeometry->getColor();
+    CPLString sHexColor;
+    sHexColor.Printf("#%02X%02X%02X%02X", stRGB.R, stRGB.G, stRGB.B, 255);
+    poFeature->SetField( FIELD_NAME_COLOR, sHexColor );
+
+    CPLString sStyle;
+    sStyle.Printf("PEN(c:%s,w:5px)", sHexColor.c_str());
+    poFeature->SetStyleString( sStyle );
+
+    std::vector< CADAttrib > oBlockAttrs = poCADGeometry->getBlockAttributes();
+    for( const CADAttrib& oAttrib : oBlockAttrs )
+    {
+        CPLString osTag = oAttrib.getTag();
+        auto featureAttrIt = asFeaturesAttributes.find( osTag );
+        if( featureAttrIt != asFeaturesAttributes.end())
+        {
+            poFeature->SetField(*featureAttrIt, oAttrib.getTextValue().c_str());
+        }
+    }
+
+    switch( poCADGeometry->getType() )
+    {
+        case CADGeometry::POINT:
+        {
+            CADPoint3D * const poCADPoint = ( CADPoint3D* ) poCADGeometry;
+            CADVector stPositionVector = poCADPoint->getPosition();
+
+            poFeature->SetGeometryDirectly( new OGRPoint( stPositionVector.getX(),
+                                                          stPositionVector.getY(),
+                                                          stPositionVector.getZ() ) );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADPoint" );
+            break;
+        }
+
+        case CADGeometry::LINE:
+        {
+            CADLine * const poCADLine = ( CADLine* ) poCADGeometry;
+            OGRLineString *poLS = new OGRLineString();
+            poLS->addPoint( poCADLine->getStart().getPosition().getX(),
+                           poCADLine->getStart().getPosition().getY(),
+                           poCADLine->getStart().getPosition().getZ() );
+            poLS->addPoint( poCADLine->getEnd().getPosition().getX(),
+                           poCADLine->getEnd().getPosition().getY(),
+                           poCADLine->getEnd().getPosition().getZ() );
+
+            poFeature->SetGeometryDirectly( poLS );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADLine" );
+            break;
+        }
+
+        case CADGeometry::SOLID:
+        {
+            CADSolid * const poCADSolid = ( CADSolid* ) poCADGeometry;
+            OGRPolygon * poPoly = new OGRPolygon();
+            OGRLinearRing * poLR = new OGRLinearRing();
+
+            std::vector<CADVector> astSolidCorners = poCADSolid->getCorners();
+            for( size_t i = 0; i < astSolidCorners.size(); ++i )
+            {
+                poLR->addPoint( astSolidCorners[i].getX(),
+                                astSolidCorners[i].getY(),
+                                astSolidCorners[i].getZ());
+            }
+            poPoly->addRingDirectly( poLR );
+            poPoly->closeRings();
+            poFeature->SetGeometryDirectly( poPoly );
+
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADSolid" );
+            break;
+        }
+
+        case CADGeometry::CIRCLE:
+        {
+            CADCircle * poCADCircle = static_cast<CADCircle*>(poCADGeometry);
+            OGRCircularString * poCircle = new OGRCircularString();
+
+            CADVector stCircleCenter = poCADCircle->getPosition();
+            OGRPoint  oCirclePoint1;
+            oCirclePoint1.setX( stCircleCenter.getX() + poCADCircle->getRadius() );
+            oCirclePoint1.setY( stCircleCenter.getY() + poCADCircle->getRadius() );
+            oCirclePoint1.setZ( stCircleCenter.getZ() );
+            poCircle->addPoint( &oCirclePoint1 );
+
+            OGRPoint  oCirclePoint2;
+            oCirclePoint2.setX( stCircleCenter.getX() - poCADCircle->getRadius() );
+            oCirclePoint2.setY( stCircleCenter.getY() - poCADCircle->getRadius() );
+            oCirclePoint2.setZ( stCircleCenter.getZ() );
+            poCircle->addPoint( &oCirclePoint2 );
+
+            // Close the circle
+            poCircle->addPoint( &oCirclePoint1 );
+
+            /*NOTE: The alternative way:
+                    OGRGeometry *poCircle = OGRGeometryFactory::approximateArcAngles(
+                    poCADCircle->getPosition().getX(),
+                    poCADCircle->getPosition().getY(),
+                    poCADCircle->getPosition().getZ(),
+                    poCADCircle->getRadius(), poCADCircle->getRadius(), 0.0,
+                    0.0, 360.0,
+                    0.0 );
+            */
+            poFeature->SetGeometryDirectly( poCircle );
+
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADCircle" );
+            break;
+        }
+
+        case CADGeometry::ARC:
+        {
+            CADArc * poCADArc = static_cast<CADArc*>(poCADGeometry);
+            OGRCircularString * poCircle = new OGRCircularString();
+
+            // Need at least 3 points in arc
+            double dfStartAngle = poCADArc->getStartingAngle() * DEG2RAD;
+            double dfEndAngle = poCADArc->getEndingAngle() * DEG2RAD;
+            double dfMidAngle = (dfEndAngle + dfStartAngle) / 2;
+            CADVector stCircleCenter = poCADArc->getPosition();
+
+            OGRPoint  oCirclePoint;
+            oCirclePoint.setX( stCircleCenter.getX() + poCADArc->getRadius() *
+                                                            cos( dfStartAngle ) );
+            oCirclePoint.setY( stCircleCenter.getY() + poCADArc->getRadius() *
+                                                            sin( dfStartAngle ) );
+            oCirclePoint.setZ( stCircleCenter.getZ() );
+            poCircle->addPoint( &oCirclePoint );
+
+            oCirclePoint.setX( stCircleCenter.getX() + poCADArc->getRadius() *
+                                                            cos( dfMidAngle ) );
+            oCirclePoint.setY( stCircleCenter.getY() + poCADArc->getRadius() *
+                                                            sin( dfMidAngle ) );
+            oCirclePoint.setZ( stCircleCenter.getZ() );
+            poCircle->addPoint( &oCirclePoint );
+
+            oCirclePoint.setX( stCircleCenter.getX() + poCADArc->getRadius() *
+                                                            cos( dfEndAngle ) );
+            oCirclePoint.setY( stCircleCenter.getY() + poCADArc->getRadius() *
+                                                            sin( dfEndAngle ) );
+            oCirclePoint.setZ( stCircleCenter.getZ() );
+            poCircle->addPoint( &oCirclePoint );
+
+            /*NOTE: alternative way:
+                OGRGeometry * poArc = OGRGeometryFactory::approximateArcAngles(
+                poCADArc->getPosition().getX(),
+                poCADArc->getPosition().getY(),
+                poCADArc->getPosition().getZ(),
+                poCADArc->getRadius(), poCADArc->getRadius(), 0.0,
+                dfStartAngle,
+                dfStartAngle > dfEndAngle ?
+                    ( dfEndAngle + 360.0f ) :
+                    dfEndAngle,
+                0.0 );
+            */
+
+            poFeature->SetGeometryDirectly( poCircle );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADArc" );
+
+            break;
+        }
+
+        case CADGeometry::FACE3D:
+        {
+            CADFace3D * const poCADFace = ( CADFace3D* ) poCADGeometry;
+            OGRPolygon * poPoly = new OGRPolygon();
+            OGRLinearRing * poLR = new OGRLinearRing();
+
+            for ( size_t i = 0; i < 3; ++i )
+            {
+                poLR->addPoint(
+                    poCADFace->getCorner( i ).getX(),
+                    poCADFace->getCorner( i ).getY(),
+                    poCADFace->getCorner( i ).getZ()
+                );
+            }
+            if ( !(poCADFace->getCorner( 2 ) == poCADFace->getCorner( 3 )) )
+            {
+                poLR->addPoint(
+                    poCADFace->getCorner( 3 ).getX(),
+                    poCADFace->getCorner( 3 ).getY(),
+                    poCADFace->getCorner( 3 ).getZ()
+                );
+            }
+            poPoly->addRingDirectly( poLR );
+            poPoly->closeRings();
+            poFeature->SetGeometryDirectly( poPoly );
+
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADFace3D" );
+            break;
+        }
+
+        case CADGeometry::LWPOLYLINE:
+        {
+            CADLWPolyline * const poCADLWPolyline = ( CADLWPolyline* ) poCADGeometry;
+
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADLWPolyline" );
+
+            /*
+             * Excessive check, like in DXF driver.
+             * I tried to make a single-point polyline, but couldnt make it.
+             * Probably this check should be removed.
+             */
+            if( poCADLWPolyline->getVertexCount() == 1 )
+            {
+                poFeature->SetGeometryDirectly(
+                            new OGRPoint( poCADLWPolyline->getVertex(0).getX(),
+                                          poCADLWPolyline->getVertex(0).getY(),
+                                          poCADLWPolyline->getVertex(0).getZ() )
+                );
+
+                break;
+            }
+
+            /*
+             * If polyline has no arcs, handle it in easy way.
+             */
+            OGRLineString * poLS = new OGRLineString();
+
+            if( poCADLWPolyline->getBulges().empty() )
+            {
+                for( size_t i = 0; i < poCADLWPolyline->getVertexCount(); ++i )
+                {
+                    CADVector stVertex = poCADLWPolyline->getVertex( i );
+                    poLS->addPoint( stVertex.getX(),
+                                    stVertex.getY(),
+                                    stVertex.getZ()
+                    );
+                }
+
+                poFeature->SetGeometryDirectly( poLS );
+                break;
+            }
+
+            /*
+             * Last case - if polyline has mixed arcs and lines.
+             */
+            bool   bLineStringStarted = false;
+            size_t iCurrentVertex = 0,
+                   iLastVertex = poCADLWPolyline->getVertexCount() - 1;
+            std::vector< double > adfBulges = poCADLWPolyline->getBulges();
+
+            while( iCurrentVertex != iLastVertex )
+            {
+                CADVector stCurrentVertex = poCADLWPolyline->getVertex( iCurrentVertex );
+                CADVector stNextVertex = poCADLWPolyline->getVertex( iCurrentVertex + 1 );
+
+                double dfLength = sqrt( pow( stNextVertex.getX() - stCurrentVertex.getX(), 2 )
+                                      + pow( stNextVertex.getY() - stCurrentVertex.getY(), 2 ) );
+
+                /*
+                 * Handling straight polyline segment.
+                 */
+                if( ( dfLength == 0 ) || ( adfBulges[iCurrentVertex] == 0 ) )
+                {
+                    if( !bLineStringStarted )
+                    {
+                        poLS->addPoint( stCurrentVertex.getX(),
+                                        stCurrentVertex.getY(),
+                                        stCurrentVertex.getZ()
+                        );
+                        bLineStringStarted = true;
+                    }
+
+                    poLS->addPoint( stNextVertex.getX(),
+                                    stNextVertex.getY(),
+                                    stNextVertex.getZ()
+                    );
+                }
+                else
+                {
+                    double dfSegmentBulge = adfBulges[iCurrentVertex];
+                    double dfH = ( dfSegmentBulge * dfLength ) / 2;
+                    double dfRadius = ( dfH / 2 ) + ( dfLength * dfLength / ( 8 * dfH ) );
+                    double dfOgrArcRotation = 0, dfOgrArcRadius = fabs( dfRadius );
+
+                    /*
+                     * Set arc's direction and keep bulge positive.
+                     */
+                    bool   bClockwise = ( dfSegmentBulge < 0 );
+                    if( bClockwise )
+                        dfSegmentBulge *= -1;
+
+                    /*
+                     * Get arc's center point.
+                     */
+                    double dfSaggita = fabs( dfSegmentBulge * ( dfLength / 2.0 ) );
+                    double dfApo = bClockwise ? -( dfOgrArcRadius - dfSaggita ) :
+                                                -( dfSaggita - dfOgrArcRadius );
+
+                    CADVector stVertex;
+                    stVertex.setX( stCurrentVertex.getX() - stNextVertex.getX() );
+                    stVertex.setY( stCurrentVertex.getY() - stNextVertex.getY() );
+                    stVertex.setZ( stCurrentVertex.getZ() );
+
+                    CADVector stMidPoint;
+                    stMidPoint.setX( stNextVertex.getX() + 0.5 * stVertex.getX() );
+                    stMidPoint.setY( stNextVertex.getY() + 0.5 * stVertex.getY() );
+                    stMidPoint.setZ( stVertex.getZ() );
+
+                    CADVector stPperp;
+                    stPperp.setX( stVertex.getY() );
+                    stPperp.setY( -stVertex.getX() );
+                    double dfStPperpLength = sqrt( stPperp.getX() * stPperp.getX() +
+                                                   stPperp.getY() * stPperp.getY() );
+                    // TODO: Check that length isnot 0
+                    stPperp.setX( stPperp.getX() / dfStPperpLength );
+                    stPperp.setY( stPperp.getY() / dfStPperpLength );
+
+                    CADVector stOgrArcCenter;
+                    stOgrArcCenter.setX( stMidPoint.getX() + ( stPperp.getX() * dfApo ) );
+                    stOgrArcCenter.setY( stMidPoint.getY() + ( stPperp.getY() * dfApo ) );
+
+                    /*
+                     * Get the line's general vertical direction ( -1 = down, +1 = up ).
+                     */
+                    double dfLineDir = stNextVertex.getY() >
+                                            stCurrentVertex.getY() ? 1.0f : -1.0f;
+
+                    /*
+                     * Get arc's starting angle.
+                     */
+                    double dfA = atan2( ( stOgrArcCenter.getY() - stCurrentVertex.getY() ),
+                                        ( stOgrArcCenter.getX() - stCurrentVertex.getX() ) ) * DEG2RAD;
+                    if( bClockwise && ( dfLineDir == 1.0 ) )
+                        dfA += ( dfLineDir * 180.0 );
+
+                    double dfOgrArcStartAngle = dfA > 0.0 ? -( dfA - 180.0 ) :
+                                                            -( dfA + 180.0 );
+
+                    /*
+                     * Get arc's ending angle.
+                     */
+                    dfA = atan2( ( stOgrArcCenter.getY() - stNextVertex.getY() ),
+                                 ( stOgrArcCenter.getX() - stNextVertex.getX() ) ) * DEG2RAD;
+                    if( bClockwise && ( dfLineDir == 1.0 ) )
+                        dfA += ( dfLineDir * 180.0 );
+
+                    double dfOgrArcEndAngle = dfA > 0.0 ? -( dfA - 180.0 ) :
+                                                          -( dfA + 180.0 );
+
+                    if( !bClockwise && ( dfOgrArcStartAngle < dfOgrArcEndAngle) )
+                        dfOgrArcEndAngle = -180.0 + ( dfLineDir * dfA );
+
+                    if( bClockwise && ( dfOgrArcStartAngle > dfOgrArcEndAngle ) )
+                        dfOgrArcEndAngle += 360.0;
+
+                    /*
+                     * Flip arc's rotation if necessary.
+                     */
+                    if( bClockwise && ( dfLineDir == 1.0 ) )
+                        dfOgrArcRotation = dfLineDir * 180.0;
+
+                    /*
+                     * Tesselate the arc segment and append to the linestring.
+                     */
+                    OGRLineString * poArcpoLS =
+                        ( OGRLineString * ) OGRGeometryFactory::approximateArcAngles(
+                            stOgrArcCenter.getX(), stOgrArcCenter.getY(), stOgrArcCenter.getZ(),
+                            dfOgrArcRadius, dfOgrArcRadius, dfOgrArcRotation,
+                            dfOgrArcStartAngle,dfOgrArcEndAngle,
+                            0.0 );
+
+                    poLS->addSubLineString( poArcpoLS );
+
+                    delete( poArcpoLS );
+                }
+
+                ++iCurrentVertex;
+            }
+
+            if( poCADLWPolyline->isClosed() )
+            {
+                poLS->addPoint( poCADLWPolyline->getVertex(0).getX(),
+                                poCADLWPolyline->getVertex(0).getY(),
+                                poCADLWPolyline->getVertex(0).getZ()
+                );
+            }
+
+            poFeature->SetGeometryDirectly( poLS );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADLWPolyline" );
+            break;
+        }
+
+        // TODO: Unsupported smooth lines
+        case CADGeometry::POLYLINE3D:
+        {
+            CADPolyline3D * const poCADPolyline3D = ( CADPolyline3D* ) poCADGeometry;
+            OGRLineString * poLS = new OGRLineString();
+
+            for( size_t i = 0; i < poCADPolyline3D->getVertexCount(); ++i )
+            {
+                CADVector stVertex = poCADPolyline3D->getVertex( i );
+
+                poLS->addPoint( stVertex.getX(),
+                                stVertex.getY(),
+                                stVertex.getZ() );
+            }
+
+            poFeature->SetGeometryDirectly( poLS );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADPolyline3D" );
+            break;
+        }
+
+        case CADGeometry::TEXT:
+        {
+            CADText * const poCADText = ( CADText * ) poCADGeometry;
+            OGRPoint * poPoint = new OGRPoint( poCADText->getPosition().getX(),
+                                               poCADText->getPosition().getY(),
+                                               poCADText->getPosition().getZ() );
+            CPLString sTextValue = CADRecode( poCADText->getTextValue(), nDWGEncoding );
+
+            poFeature->SetField( FIELD_NAME_TEXT, sTextValue );
+            poFeature->SetGeometryDirectly( poPoint );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADText" );
+
+            sStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",c:%s)", sTextValue.c_str(),
+                                                              sHexColor.c_str());
+            poFeature->SetStyleString( sStyle );
+            break;
+        }
+
+        case CADGeometry::MTEXT:
+        {
+            CADMText * const poCADMText = ( CADMText * ) poCADGeometry;
+            OGRPoint * poPoint = new OGRPoint( poCADMText->getPosition().getX(),
+                                               poCADMText->getPosition().getY(),
+                                               poCADMText->getPosition().getZ() );
+            CPLString sTextValue = CADRecode( poCADMText->getTextValue(), nDWGEncoding );
+
+            poFeature->SetField( FIELD_NAME_TEXT, sTextValue );
+            poFeature->SetGeometryDirectly( poPoint );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADMText" );
+
+            sStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",c:%s)", sTextValue.c_str(),
+                                                              sHexColor.c_str());
+            poFeature->SetStyleString( sStyle );
+            break;
+        }
+
+        case CADGeometry::SPLINE:
+        {
+            CADSpline * const poCADSpline = ( CADSpline * ) poCADGeometry;
+            OGRLineString * poLS = new OGRLineString();
+
+            // TODO: Interpolate spline as points or curves
+            for( size_t i = 0; i < poCADSpline->getControlPoints().size(); ++i )
+            {
+                poLS->addPoint( poCADSpline->getControlPoints()[i].getX(),
+                                poCADSpline->getControlPoints()[i].getY(),
+                                poCADSpline->getControlPoints()[i].getZ() );
+            }
+
+            poFeature->SetGeometryDirectly( poLS );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADSpline" );
+            break;
+        }
+
+        case CADGeometry::ELLIPSE:
+        {
+            CADEllipse * poCADEllipse = static_cast<CADEllipse*>(poCADGeometry);
+
+            // FIXME: Start/end angles should be swapped to work exactly as DXF driver.
+            // is it correct?
+            double dfStartAngle = -1 * poCADEllipse->getEndingAngle() * DEG2RAD;
+            double dfEndAngle = -1 * poCADEllipse->getStartingAngle() * DEG2RAD;
+            double dfAxisRatio = poCADEllipse->getAxisRatio();
+
+            if( dfStartAngle > dfEndAngle )
+                dfEndAngle += 360.0;
+
+            CADVector vectPosition = poCADEllipse->getPosition();
+            CADVector vectSMAxis = poCADEllipse->getSMAxis();
+            double dfPrimaryRadius, dfSecondaryRadius;
+            double dfRotation;
+            dfPrimaryRadius = sqrt( vectSMAxis.getX() * vectSMAxis.getX()
+                                    + vectSMAxis.getY() * vectSMAxis.getY()
+                                    + vectSMAxis.getZ() * vectSMAxis.getZ() );
+
+            dfSecondaryRadius = dfAxisRatio * dfPrimaryRadius;
+
+            dfRotation = -1 * atan2( vectSMAxis.getY(), vectSMAxis.getX() ) * DEG2RAD;
+
+            OGRGeometry *poEllipse =
+                OGRGeometryFactory::approximateArcAngles(
+                    vectPosition.getX(), vectPosition.getY(), vectPosition.getZ(),
+                    dfPrimaryRadius, dfSecondaryRadius, dfRotation,
+                    dfStartAngle, dfEndAngle, 0.0 );
+
+            poFeature->SetGeometryDirectly( poEllipse );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADEllipse" );
+            break;
+        }
+
+        case CADGeometry::ATTDEF:
+        {
+            CADAttdef * const poCADAttdef = ( CADAttdef* ) poCADGeometry;
+            OGRPoint * poPoint = new OGRPoint( poCADAttdef->getPosition().getX(),
+                                               poCADAttdef->getPosition().getY(),
+                                               poCADAttdef->getPosition().getZ() );
+            CPLString sTextValue = CADRecode( poCADAttdef->getTag(), nDWGEncoding );
+
+            poFeature->SetField( FIELD_NAME_TEXT, sTextValue );
+            poFeature->SetGeometryDirectly( poPoint );
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADAttdef" );
+
+            sStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",c:%s)", sTextValue.c_str(),
+                                                              sHexColor.c_str());
+            poFeature->SetStyleString( sStyle );
+            break;
+        }
+
+        default:
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                     "Unhandled feature. Skipping it." );
+
+            poFeature->SetField( FIELD_NAME_GEOMTYPE, "CADUnknown" );
+            delete poCADGeometry;
+            return poFeature;
+        }
+    }
+
+    delete poCADGeometry;
+    poFeature->GetGeometryRef()->assignSpatialReference( poSpatialRef );
+    return poFeature;
+}
diff --git a/ogr/ogrsf_frmts/cad/vsilfileio.cpp b/ogr/ogrsf_frmts/cad/vsilfileio.cpp
new file mode 100644
index 0000000..3a8f5ef
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/vsilfileio.cpp
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+*******************************************************************************/
+#include "vsilfileio.h"
+
+VSILFileIO::VSILFileIO(const char* pszFilePath) :
+    CADFileIO(pszFilePath),
+    m_oFileStream(nullptr)
+{
+
+}
+
+VSILFileIO::~VSILFileIO()
+{
+    if( m_oFileStream )
+        Close();
+}
+
+const char* VSILFileIO::ReadLine()
+{
+    // TODO: getline
+    return nullptr;
+}
+
+bool VSILFileIO::Eof() const
+{
+    return VSIFEofL( m_oFileStream ) == 0 ? false : true;
+}
+
+bool VSILFileIO::Open(int mode)
+{
+    // NOTE: now support only read mode
+    if( mode & OpenMode::write )
+        return false;
+
+    std::string sOpenMode = "r";
+    if( mode & OpenMode::binary )
+        sOpenMode = "rb";
+
+    m_oFileStream = VSIFOpenL( m_soFilePath.c_str(), sOpenMode.c_str() );
+
+    if( m_oFileStream != NULL )
+        m_bIsOpened = true;
+
+    return m_bIsOpened;
+}
+
+bool VSILFileIO::Close()
+{
+    bool bRet = VSIFCloseL( m_oFileStream ) == 0 ? true : false;
+    m_oFileStream = nullptr;
+    return bRet;
+}
+
+int VSILFileIO::Seek(long offset, CADFileIO::SeekOrigin origin)
+{
+    int nWhence = 0;
+    switch( origin )
+    {
+    case SeekOrigin::CUR:
+        nWhence = SEEK_CUR;
+        break;
+    case SeekOrigin::END:
+        nWhence = SEEK_END;
+        break;
+    case SeekOrigin::BEG:
+        nWhence = SEEK_SET;
+        break;
+    }
+
+    return VSIFSeekL( m_oFileStream, offset, nWhence) == 0 ? 0 : 1;
+}
+
+long int VSILFileIO::Tell()
+{
+    return VSIFTellL( m_oFileStream );
+}
+
+size_t VSILFileIO::Read(void* ptr, size_t size)
+{
+    return VSIFReadL( static_cast<char*>(ptr),
+                     1,
+                     size,
+                     m_oFileStream );
+}
+
+size_t VSILFileIO::Write(void* /*ptr*/, size_t /*size*/)
+{
+    // unsupported
+    return 0;
+}
+
+void VSILFileIO::Rewind()
+{
+    VSIRewindL ( m_oFileStream );
+}
diff --git a/ogr/ogrsf_frmts/cad/vsilfileio.h b/ogr/ogrsf_frmts/cad/vsilfileio.h
new file mode 100644
index 0000000..5af9461
--- /dev/null
+++ b/ogr/ogrsf_frmts/cad/vsilfileio.h
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ *  Project: libopencad
+ *  Purpose: OpenSource CAD formats support library
+ *  Author: Alexandr Borzykh, mush3d at gmail.com
+ *  Author: Dmitry Baryshnikov, bishop.dev at gmail.com
+ *  Language: C++
+ *******************************************************************************
+ *  The MIT License (MIT)
+ *
+ *  Copyright (c) 2016 Alexandr Borzykh
+ *  Copyright (c) 2016 NextGIS, <info at nextgis.com>
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a copy
+ *  of this software and associated documentation files (the "Software"), to deal
+ *  in the Software without restriction, including without limitation the rights
+ *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ *  copies of the Software, and to permit persons to whom the Software is
+ *  furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice shall be included in all
+ *  copies or substantial portions of the Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ *  SOFTWARE.
+ ******************************************************************************/
+#ifndef VSILFILEIO_H
+#define VSILFILEIO_H
+
+#include "cadfileio.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+class VSILFileIO : public CADFileIO
+{
+public:
+    explicit VSILFileIO(const char* pszFilePath);
+    virtual ~VSILFileIO();
+    virtual const char* ReadLine() override;
+    virtual bool Eof() const override;
+    virtual bool Open(int mode) override;
+    virtual bool Close() override;
+    virtual int Seek(long int offset, SeekOrigin origin) override;
+    virtual long int Tell() override;
+    virtual size_t Read(void* ptr, size_t size) override;
+    virtual size_t Write(void* ptr, size_t size) override;
+    virtual void Rewind() override;
+protected:
+    VSILFILE *m_oFileStream;
+};
+
+#endif // VSILFILEIO_H
diff --git a/ogr/ogrsf_frmts/carto/GNUmakefile b/ogr/ogrsf_frmts/carto/GNUmakefile
index 66d5ec7..c9d695d 100644
--- a/ogr/ogrsf_frmts/carto/GNUmakefile
+++ b/ogr/ogrsf_frmts/carto/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrcartodriver.o ogrcartodatasource.o ogrcartolayer.o ogrcartotablelayer.o ogrcartoresultlayer.o
 
-CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. -I../pgdump $(CPPFLAGS)
+CPPFLAGS	:=	-I../geojson $(JSON_INCLUDE) -I.. -I../.. -I../pgdump $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/carto/drv_cartodb.html b/ogr/ogrsf_frmts/carto/drv_cartodb.html
new file mode 100644
index 0000000..a8def50
--- /dev/null
+++ b/ogr/ogrsf_frmts/carto/drv_cartodb.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta charset="UTF-8" />
+<meta http-equiv="Refresh" content="0; url=http://www.gdal.org/drv_carto.html" />
+<title>Redirection</title>
+<meta name="robots" content="noindex" />
+</head>
+
+<body>
+<p><a href="drv_carto.html">Redirection to drv_carto.html</a></p>
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/carto/makefile.vc b/ogr/ogrsf_frmts/carto/makefile.vc
index 0553aa2..ca2c58c 100644
--- a/ogr/ogrsf_frmts/carto/makefile.vc
+++ b/ogr/ogrsf_frmts/carto/makefile.vc
@@ -1,7 +1,7 @@
 
 OBJ	=	ogrcartodriver.obj ogrcartodatasource.obj ogrcartolayer.obj ogrcartotablelayer.obj ogrcartoresultlayer.obj
 
-EXTRAFLAGS =	-I.. -I..\.. -I..\geojson\libjson -I..\pgdump 
+EXTRAFLAGS =	-I.. -I..\.. -I..\geojson -I..\geojson\libjson -I..\pgdump 
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/carto/ogr_carto.h b/ogr/ogrsf_frmts/carto/ogr_carto.h
index 6704d96..95f5a56 100644
--- a/ogr/ogrsf_frmts/carto/ogr_carto.h
+++ b/ogr/ogrsf_frmts/carto/ogr_carto.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_carto.h 34979 2016-08-08 09:30:34Z rouault $
+ * $Id: ogr_carto.h 36687 2016-12-04 22:28:14Z rouault $
  *
  * Project:  CARTO Translator
  * Purpose:  Definition of classes for OGR Carto driver.
@@ -34,7 +34,9 @@
 #include "cpl_http.h"
 
 #include <vector>
-#include <json.h>
+
+#include "ogr_json_header.h"
+
 
 json_object* OGRCARTOGetSingleRow(json_object* poObj);
 CPLString OGRCARTOEscapeIdentifier(const char* pszStr);
@@ -69,7 +71,7 @@ protected:
     CPLString            osBaseSQL;
     CPLString            osFIDColName;
 
-    int                  bEOF;
+    bool                 bEOF;
     int                  nFetchedObjects;
     int                  iNextInFetchedObjects;
     GIntBig              iNext;
@@ -84,21 +86,21 @@ protected:
     virtual CPLString    GetSRS_SQL(const char* pszGeomCol) = 0;
 
   public:
-                         OGRCARTOLayer(OGRCARTODataSource* poDS);
-                        ~OGRCARTOLayer();
+    explicit OGRCARTOLayer(OGRCARTODataSource* poDS);
+    virtual ~OGRCARTOLayer();
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
     virtual OGRFeatureDefn *    GetLayerDefnInternal(json_object* poObjIn) = 0;
     virtual json_object*        FetchNewFeatures(GIntBig iNext);
 
-    virtual const char*         GetFIDColumn() { return osFIDColName.c_str(); }
+    virtual const char*         GetFIDColumn() override { return osFIDColName.c_str(); }
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
-    int                         GetFeaturesToFetch() {
+    static int                         GetFeaturesToFetch() {
         return atoi(CPLGetConfigOption("CARTO_PAGE_SIZE",
                         CPLGetConfigOption("CARTODB_PAGE_SIZE", "500"))); }
 };
@@ -121,61 +123,63 @@ class OGRCARTOTableLayer : public OGRCARTOLayer
     CPLString           osWHERE;
     CPLString           osSELECTWithoutWHERE;
 
-    int                 bLaunderColumnNames;
+    bool                bLaunderColumnNames;
 
-    int                 bInDeferredInsert;
+    bool                bInDeferredInsert;
     InsertState         eDeferredInsertState;
     CPLString           osDeferredInsertSQL;
     GIntBig             nNextFID;
 
-    int                 bDeferredCreation;
-    int                 bCartodbfy;
+    bool                bDeferredCreation;
+    bool                bCartodbfy;
     int                 nMaxChunkSize;
 
     void                BuildWhere();
 
-    virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
+    virtual CPLString    GetSRS_SQL(const char* pszGeomCol) override;
 
   public:
                          OGRCARTOTableLayer(OGRCARTODataSource* poDS, const char* pszName);
-                        ~OGRCARTOTableLayer();
+    virtual ~OGRCARTOTableLayer();
 
-    virtual const char*         GetName() { return osName.c_str(); }
-    virtual OGRFeatureDefn *    GetLayerDefnInternal(json_object* poObjIn);
-    virtual json_object*        FetchNewFeatures(GIntBig iNext);
+    virtual const char*         GetName() override { return osName.c_str(); }
+    virtual OGRFeatureDefn *    GetLayerDefnInternal(json_object* poObjIn) override;
+    virtual json_object*        FetchNewFeatures(GIntBig iNext) override;
 
-    virtual GIntBig             GetFeatureCount( int bForce = TRUE );
-    virtual OGRFeature         *GetFeature( GIntBig nFeatureId );
+    virtual GIntBig             GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
-    virtual OGRErr		DeleteField( int iField );
+    virtual OGRErr      DeleteField( int iField ) override;
 
-    virtual OGRFeature  *GetNextRawFeature();
+    virtual OGRFeature  *GetNextRawFeature() override;
 
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override;
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) { return GetExtent(0, psExtent, bForce); }
-    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce ) override;
 
-    void                SetLaunderFlag( int bFlag )
-                                { bLaunderColumnNames = bFlag; }
+    void                SetLaunderFlag( bool bFlag )
+        { bLaunderColumnNames = bFlag; }
     void                SetDeferredCreation( OGRwkbGeometryType eGType,
-                                            OGRSpatialReference* poSRS,
-                                            int bGeomNullable,
-                                            int bCartodbfy);
+                                             OGRSpatialReference* poSRS,
+                                             bool bGeomNullable,
+                                             bool bCartodbfy);
     OGRErr              RunDeferredCreationIfNecessary();
-    int                 GetDeferredCreation() const { return bDeferredCreation; }
-    void                CancelDeferredCreation() { bDeferredCreation = FALSE; bCartodbfy = FALSE; }
+    bool                GetDeferredCreation() const
+        { return bDeferredCreation; }
+    void                CancelDeferredCreation()
+        { bDeferredCreation = false; bCartodbfy = false; }
 
     OGRErr              FlushDeferredInsert(bool bReset = true);
     void                RunDeferredCartofy();
@@ -189,17 +193,17 @@ class OGRCARTOResultLayer : public OGRCARTOLayer
 {
     OGRFeature          *poFirstFeature;
 
-    virtual CPLString    GetSRS_SQL(const char* pszGeomCol);
+    virtual CPLString    GetSRS_SQL(const char* pszGeomCol) override;
 
   public:
                         OGRCARTOResultLayer( OGRCARTODataSource* poDS,
                                                const char * pszRawStatement );
     virtual             ~OGRCARTOResultLayer();
 
-    virtual OGRFeatureDefn *GetLayerDefnInternal(json_object* poObjIn);
-    virtual OGRFeature  *GetNextRawFeature();
+    virtual OGRFeatureDefn *GetLayerDefnInternal(json_object* poObjIn) override;
+    virtual OGRFeature  *GetNextRawFeature() override;
 
-    int                 IsOK();
+    bool                IsOK();
 };
 
 /************************************************************************/
@@ -214,14 +218,14 @@ class OGRCARTODataSource : public OGRDataSource
     OGRCARTOTableLayer**  papoLayers;
     int                 nLayers;
 
-    int                 bReadWrite;
-    int                 bBatchInsert;
+    bool                bReadWrite;
+    bool                bBatchInsert;
 
-    int                 bUseHTTPS;
+    bool                bUseHTTPS;
 
     CPLString           osAPIKey;
 
-    int                 bMustCleanPersistent;
+    bool                bMustCleanPersistent;
 
     CPLString           osCurrentSchema;
 
@@ -232,47 +236,48 @@ class OGRCARTODataSource : public OGRDataSource
 
   public:
                         OGRCARTODataSource();
-                        ~OGRCARTODataSource();
+    virtual ~OGRCARTODataSource();
 
     int                 Open( const char * pszFilename,
                               char** papszOpenOptions,
                               int bUpdate );
 
-    virtual const char* GetName() { return pszName; }
+    virtual const char* GetName() override { return pszName; }
 
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer*   GetLayer( int );
-    virtual OGRLayer    *GetLayerByName(const char *);
+    virtual int         GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*   GetLayer( int ) override;
+    virtual OGRLayer    *GetLayerByName(const char *) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
-                                     char ** papszOptions = NULL );
-    virtual OGRErr      DeleteLayer(int);
+                                     char ** papszOptions = NULL ) override;
+    virtual OGRErr      DeleteLayer(int) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     const char*                 GetAPIURL() const;
-    int                         IsReadWrite() const { return bReadWrite; }
-    int                         DoBatchInsert() const { return bBatchInsert; }
+    bool                        IsReadWrite() const { return bReadWrite; }
+    bool                        DoBatchInsert() const { return bBatchInsert; }
     char**                      AddHTTPOptions();
     json_object*                RunSQL(const char* pszUnescapedSQL);
     const CPLString&            GetCurrentSchema() { return osCurrentSchema; }
-    int                         FetchSRSId( OGRSpatialReference * poSRS );
+    static int                         FetchSRSId( OGRSpatialReference * poSRS );
 
-    int                         IsAuthenticatedConnection() { return osAPIKey.size() != 0; }
+    int                         IsAuthenticatedConnection() { return !osAPIKey.empty(); }
     int                         HasOGRMetadataFunction() { return bHasOGRMetadataFunction; }
     void                        SetOGRMetadataFunction(int bFlag) { bHasOGRMetadataFunction = bFlag; }
 
-    OGRLayer *                  ExecuteSQLInternal( const char *pszSQLCommand,
-                                                    OGRGeometry *poSpatialFilter = NULL,
-                                                    const char *pszDialect = NULL,
-                                                    int bRunDeferredActions = FALSE );
+    OGRLayer *                  ExecuteSQLInternal(
+        const char *pszSQLCommand,
+        OGRGeometry *poSpatialFilter = NULL,
+        const char *pszDialect = NULL,
+        bool bRunDeferredActions = false );
 
     int                         GetPostGISMajor() const { return nPostGISMajor; }
     int                         GetPostGISMinor() const { return nPostGISMinor; }
diff --git a/ogr/ogrsf_frmts/carto/ogrcartodatasource.cpp b/ogr/ogrsf_frmts/carto/ogrcartodatasource.cpp
index db6f030..b5045a9 100644
--- a/ogr/ogrsf_frmts/carto/ogrcartodatasource.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartodatasource.cpp
@@ -28,8 +28,9 @@
 
 #include "ogr_carto.h"
 #include "ogr_pgdump.h"
+#include "ogrgeojsonreader.h"
 
-CPL_CVSID("$Id: ogrcartodatasource.cpp 34979 2016-08-08 09:30:34Z rouault $");
+CPL_CVSID("$Id: ogrcartodatasource.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 /************************************************************************/
 /*                        OGRCARTODataSource()                        */
@@ -40,10 +41,10 @@ OGRCARTODataSource::OGRCARTODataSource() :
     pszAccount(NULL),
     papoLayers(NULL),
     nLayers(0),
-    bReadWrite(FALSE),
-    bBatchInsert(TRUE),
-    bUseHTTPS(FALSE),
-    bMustCleanPersistent(FALSE),
+    bReadWrite(false),
+    bBatchInsert(true),
+    bUseHTTPS(false),
+    bMustCleanPersistent(false),
     bHasOGRMetadataFunction(-1),
     nPostGISMajor(2),
     nPostGISMinor(0)
@@ -60,7 +61,7 @@ OGRCARTODataSource::~OGRCARTODataSource()
         delete papoLayers[i];
     CPLFree( papoLayers );
 
-    if (bMustCleanPersistent)
+    if( bMustCleanPersistent )
     {
         char** papszOptions = NULL;
         papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("CARTO:%p", this));
@@ -83,6 +84,8 @@ int OGRCARTODataSource::TestCapability( const char * pszCap )
         return TRUE;
     else if( bReadWrite && EQUAL(pszCap,ODsCDeleteLayer) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return bReadWrite;
     else
         return FALSE;
 }
@@ -123,7 +126,7 @@ static CPLString OGRCARTOGetOptionValue(const char* pszFilename,
     if (!pszOptionValue)
         return "";
 
-    CPLString osOptionValue(pszOptionValue + strlen(osOptionName));
+    CPLString osOptionValue(pszOptionValue + osOptionName.size());
     const char* pszSpace = strchr(osOptionValue.c_str(), ' ');
     if (pszSpace)
         osOptionValue.resize(pszSpace - osOptionValue.c_str());
@@ -139,8 +142,9 @@ int OGRCARTODataSource::Open( const char * pszFilename,
                                 int bUpdateIn )
 
 {
-    bReadWrite = bUpdateIn;
-    bBatchInsert = CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn, "BATCH_INSERT", "YES"));
+    bReadWrite = CPL_TO_BOOL(bUpdateIn);
+    bBatchInsert = CPLTestBool(
+        CSLFetchNameValueDef(papszOpenOptionsIn, "BATCH_INSERT", "YES"));
 
     pszName = CPLStrdup( pszFilename );
     if( CSLFetchNameValue(papszOpenOptionsIn, "ACCOUNT") )
@@ -161,21 +165,23 @@ int OGRCARTODataSource::Open( const char * pszFilename,
         }
     }
 
-    osAPIKey = CSLFetchNameValueDef(papszOpenOptionsIn, "API_KEY",
-                            CPLGetConfigOption("CARTO_API_KEY", 
-                                CPLGetConfigOption("CARTODB_API_KEY", "")));
+    osAPIKey = CSLFetchNameValueDef(
+        papszOpenOptionsIn, "API_KEY",
+        CPLGetConfigOption("CARTO_API_KEY",
+                           CPLGetConfigOption("CARTODB_API_KEY", "")));
 
     CPLString osTables = OGRCARTOGetOptionValue(pszFilename, "tables");
 
-    /*if( osTables.size() == 0 && osAPIKey.size() == 0 )
+    /*if( osTables.empty() && osAPIKey.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "When not specifying tables option, CARTO_API_KEY must be defined");
         return FALSE;
     }*/
 
-    bUseHTTPS = CPLTestBool(CPLGetConfigOption("CARTO_HTTPS",
-                                CPLGetConfigOption("CARTODB_HTTPS", "YES")));
+    bUseHTTPS = CPLTestBool(
+        CPLGetConfigOption("CARTO_HTTPS",
+                           CPLGetConfigOption("CARTODB_HTTPS", "YES")));
 
     OGRLayer* poSchemaLayer = ExecuteSQLInternal("SELECT current_schema()");
     if( poSchemaLayer )
@@ -191,7 +197,7 @@ int OGRCARTODataSource::Open( const char * pszFilename,
         }
         ReleaseResultSet(poSchemaLayer);
     }
-    if( osCurrentSchema.size() == 0 )
+    if( osCurrentSchema.empty() )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -220,7 +226,7 @@ int OGRCARTODataSource::Open( const char * pszFilename,
         }
     }
 
-    if( osAPIKey.size() && bUpdateIn )
+    if( !osAPIKey.empty() && bUpdateIn )
     {
         ExecuteSQLInternal(
                 "DROP FUNCTION IF EXISTS ogr_table_metadata(TEXT,TEXT); "
@@ -253,7 +259,7 @@ int OGRCARTODataSource::Open( const char * pszFilename,
                 "$$ LANGUAGE SQL");
     }
 
-    if (osTables.size() != 0)
+    if (!osTables.empty())
     {
         char** papszTables = CSLTokenizeString2(osTables, ",", 0);
         for(int i=0;papszTables && papszTables[i];i++)
@@ -327,7 +333,7 @@ const char* OGRCARTODataSource::GetAPIURL() const
                                 CPLGetConfigOption("CARTODB_API_URL", NULL));
     if (pszAPIURL)
         return pszAPIURL;
-    else if (bUseHTTPS)
+    else if( bUseHTTPS )
         return CPLSPrintf("https://%s.carto.com/api/v2/sql", pszAccount);
     else
         return CPLSPrintf("http://%s.carto.com/api/v2/sql", pszAccount);
@@ -346,6 +352,7 @@ int OGRCARTODataSource::FetchSRSId( OGRSpatialReference * poSRS )
         return 0;
 
     OGRSpatialReference oSRS(*poSRS);
+    // cppcheck-suppress uselessAssignmentPtrArg
     poSRS = NULL;
 
     pszAuthorityName = oSRS.GetAuthorityName(NULL);
@@ -376,12 +383,10 @@ int OGRCARTODataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
     if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
     {
-        int             nAuthorityCode;
-
         /* For the root authority name 'EPSG', the authority code
          * should always be integral
          */
-        nAuthorityCode = atoi( oSRS.GetAuthorityCode(NULL) );
+        const int nAuthorityCode = atoi( oSRS.GetAuthorityCode(NULL) );
 
         return nAuthorityCode;
     }
@@ -398,7 +403,7 @@ OGRLayer   *OGRCARTODataSource::ICreateLayer( const char *pszNameIn,
                                            OGRwkbGeometryType eGType,
                                            char ** papszOptions )
 {
-    if (!bReadWrite)
+    if( !bReadWrite )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode");
         return NULL;
@@ -408,9 +413,7 @@ OGRLayer   *OGRCARTODataSource::ICreateLayer( const char *pszNameIn,
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
-    int iLayer;
-
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszNameIn,papoLayers[iLayer]->GetName()) )
         {
@@ -432,20 +435,20 @@ OGRLayer   *OGRCARTODataSource::ICreateLayer( const char *pszNameIn,
     }
 
     CPLString osName(pszNameIn);
-    if( CPLFetchBool(const_cast<const char**>(papszOptions), "LAUNDER", true) )
+    if( CPLFetchBool(papszOptions, "LAUNDER", true) )
     {
         char* pszTmp = OGRPGCommonLaunderName(pszNameIn);
         osName = pszTmp;
         CPLFree(pszTmp);
     }
 
-
     OGRCARTOTableLayer* poLayer = new OGRCARTOTableLayer(this, osName);
-    const bool bGeomNullable = CPLFetchBool(const_cast<const char**>(papszOptions), "GEOMETRY_NULLABLE", true);
+    const bool bGeomNullable =
+        CPLFetchBool(papszOptions, "GEOMETRY_NULLABLE", true);
     int nSRID = (poSpatialRef && eGType != wkbNone) ? FetchSRSId( poSpatialRef ) : 0;
-    bool bCartoify = CPLFetchBool(const_cast<const char**>(papszOptions), "CARTODBFY",
-                                    CPLFetchBool(const_cast<const char**>(papszOptions), "CARTODBIFY",
-                                                 true));
+    bool bCartoify = CPLFetchBool(papszOptions, "CARTODBFY",
+                                  CPLFetchBool(papszOptions, "CARTODBIFY",
+                                               true));
     if( bCartoify )
     {
         if( nSRID != 4326 )
@@ -460,8 +463,9 @@ OGRLayer   *OGRCARTODataSource::ICreateLayer( const char *pszNameIn,
         }
     }
 
-    poLayer->SetLaunderFlag( CPLFetchBool(const_cast<const char**>(papszOptions), "LAUNDER", true) );
-    poLayer->SetDeferredCreation(eGType, poSpatialRef, bGeomNullable, bCartoify);
+    poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", true) );
+    poLayer->SetDeferredCreation(eGType, poSpatialRef,
+                                 bGeomNullable, bCartoify);
     papoLayers = (OGRCARTOTableLayer**) CPLRealloc(
                     papoLayers, (nLayers + 1) * sizeof(OGRCARTOTableLayer*));
     papoLayers[nLayers ++] = poLayer;
@@ -475,7 +479,7 @@ OGRLayer   *OGRCARTODataSource::ICreateLayer( const char *pszNameIn,
 
 OGRErr OGRCARTODataSource::DeleteLayer(int iLayer)
 {
-    if (!bReadWrite)
+    if( !bReadWrite )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in read-only mode");
@@ -505,7 +509,7 @@ OGRErr OGRCARTODataSource::DeleteLayer(int iLayer)
              sizeof(void *) * (nLayers - iLayer - 1) );
     nLayers--;
 
-    if (osLayerName.size() == 0)
+    if (osLayerName.empty())
         return OGRERR_NONE;
 
     if( !bDeferredCreation )
@@ -529,7 +533,7 @@ OGRErr OGRCARTODataSource::DeleteLayer(int iLayer)
 
 char** OGRCARTODataSource::AddHTTPOptions()
 {
-    bMustCleanPersistent = TRUE;
+    bMustCleanPersistent = true;
 
     return CSLAddString(NULL, CPLSPrintf("PERSISTENT=CARTO:%p", this));
 }
@@ -554,7 +558,7 @@ json_object* OGRCARTODataSource::RunSQL(const char* pszUnescapedSQL)
 /* -------------------------------------------------------------------- */
 /*      Provide the API Key                                             */
 /* -------------------------------------------------------------------- */
-    if( osAPIKey.size() )
+    if( !osAPIKey.empty() )
     {
         osSQL += "&api_key=";
         osSQL += osAPIKey;
@@ -626,7 +630,7 @@ json_object* OGRCARTODataSource::RunSQL(const char* pszUnescapedSQL)
     {
         if( json_object_get_type(poObj) == json_type_object )
         {
-            json_object* poError = json_object_object_get(poObj, "error");
+            json_object* poError = CPL_json_object_object_get(poObj, "error");
             if( poError != NULL && json_object_get_type(poError) == json_type_array &&
                 json_object_array_length(poError) > 0 )
             {
@@ -661,7 +665,7 @@ json_object* OGRCARTOGetSingleRow(json_object* poObj)
         return NULL;
     }
 
-    json_object* poRows = json_object_object_get(poObj, "rows");
+    json_object* poRows = CPL_json_object_object_get(poObj, "rows");
     if( poRows == NULL ||
         json_object_get_type(poRows) != json_type_array ||
         json_object_array_length(poRows) != 1 )
@@ -688,13 +692,13 @@ OGRLayer * OGRCARTODataSource::ExecuteSQL( const char *pszSQLCommand,
 
 {
     return ExecuteSQLInternal(pszSQLCommand, poSpatialFilter, pszDialect,
-                              TRUE);
+                              true);
 }
 
 OGRLayer * OGRCARTODataSource::ExecuteSQLInternal( const char *pszSQLCommand,
-                                                     OGRGeometry *poSpatialFilter,
-                                                     const char *pszDialect,
-                                                     int bRunDeferredActions )
+                                                   OGRGeometry *poSpatialFilter,
+                                                   const char *pszDialect,
+                                                   bool bRunDeferredActions )
 
 {
     if( bRunDeferredActions )
diff --git a/ogr/ogrsf_frmts/carto/ogrcartodriver.cpp b/ogr/ogrsf_frmts/carto/ogrcartodriver.cpp
index 21b3df3..f2573d8 100644
--- a/ogr/ogrsf_frmts/carto/ogrcartodriver.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartodriver.cpp
@@ -30,7 +30,7 @@
 
 // g++ -g -Wall -fPIC -shared -o ogr_CARTO.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/carto ogr/ogrsf_frmts/carto/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson/libjson
 
-CPL_CVSID("$Id: ogrcartodriver.cpp 35040 2016-08-10 14:02:46Z rouault $");
+CPL_CVSID("$Id: ogrcartodriver.cpp 34976 2016-08-08 08:33:30Z rouault $");
 
 extern "C" void RegisterOGRCarto();
 
@@ -140,9 +140,3 @@ void RegisterOGRCarto()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
-// Just kept for C ABI stability
-void RegisterOGRCartoDB()
-{
-    RegisterOGRCarto();
-}
diff --git a/ogr/ogrsf_frmts/carto/ogrcartolayer.cpp b/ogr/ogrsf_frmts/carto/ogrcartolayer.cpp
index 242c376..a212024 100644
--- a/ogr/ogrsf_frmts/carto/ogrcartolayer.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartolayer.cpp
@@ -28,8 +28,9 @@
 
 #include "ogr_carto.h"
 #include "ogr_p.h"
+#include "ogrgeojsonreader.h"
 
-CPL_CVSID("$Id: ogrcartolayer.cpp 34979 2016-08-08 09:30:34Z rouault $");
+CPL_CVSID("$Id: ogrcartolayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGRCARTOLayer()                            */
@@ -67,7 +68,7 @@ void OGRCARTOLayer::ResetReading()
     if( poCachedObj != NULL )
         json_object_put(poCachedObj);
     poCachedObj = NULL;
-    bEOF = FALSE;
+    bEOF = false;
     nFetchedObjects = -1;
     iNextInFetchedObjects = 0;
     iNext = 0;
@@ -95,9 +96,9 @@ OGRFeature *OGRCARTOLayer::BuildFeature(json_object* poRowObj)
         //CPLDebug("Carto", "Row: %s", json_object_to_json_string(poRowObj));
         poFeature = new OGRFeature(poFeatureDefn);
 
-        if( osFIDColName.size() )
+        if( !osFIDColName.empty() )
         {
-            json_object* poVal = json_object_object_get(poRowObj, osFIDColName);
+            json_object* poVal = CPL_json_object_object_get(poRowObj, osFIDColName);
             if( poVal != NULL &&
                 json_object_get_type(poVal) == json_type_int )
             {
@@ -111,10 +112,13 @@ OGRFeature *OGRCARTOLayer::BuildFeature(json_object* poRowObj)
 
         for(int i=0;i<poFeatureDefn->GetFieldCount();i++)
         {
-            json_object* poVal = json_object_object_get(poRowObj,
+            json_object* poVal = CPL_json_object_object_get(poRowObj,
                             poFeatureDefn->GetFieldDefn(i)->GetNameRef());
-            if( poVal != NULL &&
-                json_object_get_type(poVal) == json_type_string )
+            if( poVal == NULL )
+            {
+                poFeature->SetFieldNull(i);
+            }
+            else if( json_object_get_type(poVal) == json_type_string )
             {
                 if( poFeatureDefn->GetFieldDefn(i)->GetType() == OFTDateTime )
                 {
@@ -130,14 +134,12 @@ OGRFeature *OGRCARTOLayer::BuildFeature(json_object* poRowObj)
                     poFeature->SetField(i, json_object_get_string(poVal));
                 }
             }
-            else if( poVal != NULL &&
-                (json_object_get_type(poVal) == json_type_int ||
-                 json_object_get_type(poVal) == json_type_boolean) )
+            else if( json_object_get_type(poVal) == json_type_int ||
+                     json_object_get_type(poVal) == json_type_boolean )
             {
                 poFeature->SetField(i, (GIntBig)json_object_get_int64(poVal));
             }
-            else if( poVal != NULL &&
-                json_object_get_type(poVal) == json_type_double )
+            else if( json_object_get_type(poVal) == json_type_double )
             {
                 poFeature->SetField(i, json_object_get_double(poVal));
             }
@@ -146,13 +148,13 @@ OGRFeature *OGRCARTOLayer::BuildFeature(json_object* poRowObj)
         for(int i=0;i<poFeatureDefn->GetGeomFieldCount();i++)
         {
             OGRGeomFieldDefn* poGeomFldDefn = poFeatureDefn->GetGeomFieldDefn(i);
-            json_object* poVal = json_object_object_get(poRowObj,
+            json_object* poVal = CPL_json_object_object_get(poRowObj,
                             poGeomFldDefn->GetNameRef());
             if( poVal != NULL &&
                 json_object_get_type(poVal) == json_type_string )
             {
                 OGRGeometry* poGeom = OGRGeometryFromHexEWKB(
-                                        json_object_get_string(poVal), NULL, FALSE);
+                    json_object_get_string(poVal), NULL, FALSE);
                 if( poGeom != NULL )
                     poGeom->assignSpatialReference(poGeomFldDefn->GetSpatialRef());
                 poFeature->SetGeomFieldDirectly(i, poGeom);
@@ -193,11 +195,11 @@ OGRFeature *OGRCARTOLayer::GetNextRawFeature()
     {
         if( nFetchedObjects > 0 && nFetchedObjects < GetFeaturesToFetch() )
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
 
-        if( poFeatureDefn == NULL && osBaseSQL.size() == 0 )
+        if( poFeatureDefn == NULL && osBaseSQL.empty() )
         {
             GetLayerDefn();
         }
@@ -205,7 +207,7 @@ OGRFeature *OGRCARTOLayer::GetNextRawFeature()
         json_object* poObj = FetchNewFeatures(iNext);
         if( poObj == NULL )
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
 
@@ -214,13 +216,13 @@ OGRFeature *OGRCARTOLayer::GetNextRawFeature()
             GetLayerDefnInternal(poObj);
         }
 
-        json_object* poRows = json_object_object_get(poObj, "rows");
+        json_object* poRows = CPL_json_object_object_get(poObj, "rows");
         if( poRows == NULL ||
             json_object_get_type(poRows) != json_type_array ||
             json_object_array_length(poRows) == 0 )
         {
             json_object_put(poObj);
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
 
@@ -232,7 +234,7 @@ OGRFeature *OGRCARTOLayer::GetNextRawFeature()
         iNextInFetchedObjects = 0;
     }
 
-    json_object* poRows = json_object_object_get(poCachedObj, "rows");
+    json_object* poRows = CPL_json_object_object_get(poCachedObj, "rows");
     json_object* poRowObj = json_object_array_get_idx(poRows, iNextInFetchedObjects);
 
     iNextInFetchedObjects ++;
@@ -319,7 +321,7 @@ void OGRCARTOLayer::EstablishLayerDefn(const char* pszLayerName,
         }
     }
 
-    json_object* poFields = json_object_object_get(poObj, "fields");
+    json_object* poFields = CPL_json_object_object_get(poObj, "fields");
     if( poFields == NULL || json_object_get_type(poFields) != json_type_object)
     {
         if( poObjIn == NULL )
@@ -336,7 +338,7 @@ void OGRCARTOLayer::EstablishLayerDefn(const char* pszLayerName,
         const char* pszColName = it.key;
         if( it.val != NULL && json_object_get_type(it.val) == json_type_object)
         {
-            json_object* poType = json_object_object_get(it.val, "type");
+            json_object* poType = CPL_json_object_object_get(it.val, "type");
             if( poType != NULL && json_object_get_type(poType) == json_type_string )
             {
                 const char* pszType = json_object_get_string(poType);
@@ -431,13 +433,13 @@ OGRSpatialReference* OGRCARTOLayer::GetSRS(const char* pszGeomCol,
         return NULL;
     }
 
-    json_object* poSRID = json_object_object_get(poRowObj, "srid");
+    json_object* poSRID = CPL_json_object_object_get(poRowObj, "srid");
     if( poSRID != NULL && json_object_get_type(poSRID) == json_type_int )
     {
         *pnSRID = json_object_get_int(poSRID);
     }
 
-    json_object* poSRTEXT = json_object_object_get(poRowObj, "srtext");
+    json_object* poSRTEXT = CPL_json_object_object_get(poRowObj, "srtext");
     OGRSpatialReference* l_poSRS = NULL;
     if( poSRTEXT != NULL && json_object_get_type(poSRTEXT) == json_type_string )
     {
diff --git a/ogr/ogrsf_frmts/carto/ogrcartoresultlayer.cpp b/ogr/ogrsf_frmts/carto/ogrcartoresultlayer.cpp
index 1e7814d..b52d30a 100644
--- a/ogr/ogrsf_frmts/carto/ogrcartoresultlayer.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartoresultlayer.cpp
@@ -28,7 +28,7 @@
 
 #include "ogr_carto.h"
 
-CPL_CVSID("$Id: ogrcartoresultlayer.cpp 34979 2016-08-08 09:30:34Z rouault $");
+CPL_CVSID("$Id: ogrcartoresultlayer.cpp 35298 2016-09-02 23:00:49Z goatbar $");
 
 /************************************************************************/
 /*                          OGRCARTOResultLayer()                     */
@@ -87,7 +87,7 @@ OGRFeature  *OGRCARTOResultLayer::GetNextRawFeature()
 /*                                IsOK()                                */
 /************************************************************************/
 
-int  OGRCARTOResultLayer::IsOK()
+bool OGRCARTOResultLayer::IsOK()
 {
     CPLErrorReset();
     poFirstFeature = GetNextFeature();
diff --git a/ogr/ogrsf_frmts/carto/ogrcartotablelayer.cpp b/ogr/ogrsf_frmts/carto/ogrcartotablelayer.cpp
index d3e7a89..07836da 100644
--- a/ogr/ogrsf_frmts/carto/ogrcartotablelayer.cpp
+++ b/ogr/ogrsf_frmts/carto/ogrcartotablelayer.cpp
@@ -29,8 +29,9 @@
 #include "ogr_carto.h"
 #include "ogr_p.h"
 #include "ogr_pgdump.h"
+#include "ogrgeojsonreader.h"
 
-CPL_CVSID("$Id: ogrcartotablelayer.cpp 34979 2016-08-08 09:30:34Z rouault $");
+CPL_CVSID("$Id: ogrcartotablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                    OGRCARTOEscapeIdentifier( )                     */
@@ -42,7 +43,7 @@ CPLString OGRCARTOEscapeIdentifier(const char* pszStr)
 
     osStr += "\"";
 
-    char ch;
+    char ch = '\0';
     for(int i=0; (ch = pszStr[i]) != '\0'; i++)
     {
         if (ch == '"')
@@ -63,7 +64,7 @@ CPLString OGRCARTOEscapeLiteral(const char* pszStr)
 {
     CPLString osStr;
 
-    char ch;
+    char ch = '\0';
     for(int i=0; (ch = pszStr[i]) != '\0'; i++)
     {
         if (ch == '\'')
@@ -79,19 +80,18 @@ CPLString OGRCARTOEscapeLiteral(const char* pszStr)
 /************************************************************************/
 
 OGRCARTOTableLayer::OGRCARTOTableLayer(OGRCARTODataSource* poDSIn,
-                                           const char* pszName) :
-                                           OGRCARTOLayer(poDSIn)
-
+                                       const char* pszName) :
+    OGRCARTOLayer(poDSIn),
+    osName( pszName )
 {
-    osName = pszName;
     SetDescription( osName );
-    bLaunderColumnNames = TRUE;
+    bLaunderColumnNames = true;
     bInDeferredInsert = poDS->DoBatchInsert();
     eDeferredInsertState = INSERT_UNINIT;
     nNextFID = -1;
-    bDeferredCreation = FALSE;
-    bCartodbfy = FALSE;
-    nMaxChunkSize = atoi(CPLGetConfigOption("CARTO_MAX_CHUNK_SIZE", 
+    bDeferredCreation = false;
+    bCartodbfy = false;
+    nMaxChunkSize = atoi(CPLGetConfigOption("CARTO_MAX_CHUNK_SIZE",
             CPLGetConfigOption("CARTODB_MAX_CHUNK_SIZE", "15"))) * 1024 * 1024;
 }
 
@@ -152,7 +152,7 @@ OGRFeatureDefn * OGRCARTOTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object
                           OGRCARTOEscapeLiteral(osName).c_str() );
     }
 
-    if( osCommand.size() )
+    if( !osCommand.empty() )
     {
         if( !poDS->IsAuthenticatedConnection() && poDS->HasOGRMetadataFunction() < 0 )
             CPLPushErrorHandler(CPLQuietErrorHandler);
@@ -196,7 +196,7 @@ OGRFeatureDefn * OGRCARTOTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object
                 int bNotNull = poFeat->GetFieldAsInteger("attnotnull");
                 int bIsPrimary = poFeat->GetFieldAsInteger("indisprimary");
                 int iDefaultExpr = poLyr->GetLayerDefn()->GetFieldIndex("defaultexpr");
-                const char* pszDefault = (iDefaultExpr >= 0 && poFeat->IsFieldSet(iDefaultExpr)) ?
+                const char* pszDefault = (iDefaultExpr >= 0 && poFeat->IsFieldSetAndNotNull(iDefaultExpr)) ?
                             poFeat->GetFieldAsString(iDefaultExpr) : NULL;
 
                 if( bIsPrimary &&
@@ -221,7 +221,7 @@ OGRFeatureDefn * OGRCARTOTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object
                         int nDim = poFeat->GetFieldAsInteger("dim");
                         int nSRID = poFeat->GetFieldAsInteger("srid");
                         const char* pszGeomType = poFeat->GetFieldAsString("geomtyp");
-                        const char* pszSRText = (poFeat->IsFieldSet(
+                        const char* pszSRText = (poFeat->IsFieldSetAndNotNull(
                             poLyr->GetLayerDefn()->GetFieldIndex("srtext"))) ?
                                     poFeat->GetFieldAsString("srtext") : NULL;
                         OGRwkbGeometryType eType = OGRFromOGCGeomType(pszGeomType);
@@ -276,14 +276,14 @@ OGRFeatureDefn * OGRCARTOTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object
         osBaseSQL = "";
     }
 
-    if( osFIDColName.size() > 0 )
+    if( !osFIDColName.empty() )
     {
         osBaseSQL = "SELECT ";
         osBaseSQL += OGRCARTOEscapeIdentifier(osFIDColName);
     }
     for(int i=0; i<poFeatureDefn->GetGeomFieldCount(); i++)
     {
-        if( osBaseSQL.size() == 0 )
+        if( osBaseSQL.empty() )
             osBaseSQL = "SELECT ";
         else
             osBaseSQL += ", ";
@@ -291,13 +291,13 @@ OGRFeatureDefn * OGRCARTOTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object
     }
     for(int i=0; i<poFeatureDefn->GetFieldCount(); i++)
     {
-        if( osBaseSQL.size() == 0 )
+        if( osBaseSQL.empty() )
             osBaseSQL = "SELECT ";
         else
             osBaseSQL += ", ";
         osBaseSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
     }
-    if( osBaseSQL.size() == 0 )
+    if( osBaseSQL.empty() )
         osBaseSQL = "SELECT *";
     osBaseSQL += " FROM ";
     osBaseSQL += OGRCARTOEscapeIdentifier(osName);
@@ -313,7 +313,7 @@ OGRFeatureDefn * OGRCARTOTableLayer::GetLayerDefnInternal(CPL_UNUSED json_object
 
 json_object* OGRCARTOTableLayer::FetchNewFeatures(GIntBig iNextIn)
 {
-    if( osFIDColName.size() > 0 )
+    if( !osFIDColName.empty() )
     {
         CPLString osSQL;
         osSQL.Printf("%s WHERE %s%s >= " CPL_FRMT_GIB " ORDER BY %s ASC LIMIT %d",
@@ -398,13 +398,12 @@ void OGRCARTOTableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomI
 /*                         RunDeferredCartofy()                         */
 /************************************************************************/
 
-
 void OGRCARTOTableLayer::RunDeferredCartofy()
 
 {
     if( bCartodbfy )
     {
-        bCartodbfy = FALSE;
+        bCartodbfy = false;
 
         CPLString osSQL;
         if( poDS->GetCurrentSchema() == "public" )
@@ -429,7 +428,7 @@ OGRErr OGRCARTOTableLayer::FlushDeferredInsert(bool bReset)
 
 {
     OGRErr eErr = OGRERR_NONE;
-    if( bInDeferredInsert && osDeferredInsertSQL.size() > 0 )
+    if( bInDeferredInsert && !osDeferredInsertSQL.empty() )
     {
         osDeferredInsertSQL = "BEGIN;" + osDeferredInsertSQL;
         if( eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
@@ -446,7 +445,7 @@ OGRErr OGRCARTOTableLayer::FlushDeferredInsert(bool bReset)
         }
         else
         {
-            bInDeferredInsert = FALSE;
+            bInDeferredInsert = false;
             eErr = OGRERR_FAILURE;
         }
     }
@@ -454,7 +453,7 @@ OGRErr OGRCARTOTableLayer::FlushDeferredInsert(bool bReset)
     osDeferredInsertSQL = "";
     if( bReset )
     {
-        bInDeferredInsert = FALSE;
+        bInDeferredInsert = false;
         nNextFID = -1;
     }
     return eErr;
@@ -500,7 +499,7 @@ OGRErr OGRCARTOTableLayer::CreateField( OGRFieldDefn *poFieldIn,
         osSQL.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
                     OGRCARTOEscapeIdentifier(osName).c_str(),
                     OGRCARTOEscapeIdentifier(oField.GetNameRef()).c_str(),
-                    OGRPGCommonLayerGetType(oField, FALSE, TRUE).c_str() );
+                    OGRPGCommonLayerGetType(oField, false, true).c_str() );
         if( !oField.IsNullable() )
             osSQL += " NOT NULL";
         if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
@@ -571,8 +570,6 @@ OGRErr OGRCARTOTableLayer::DeleteField( int iField )
 OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
 
 {
-    int i;
-
     if( bDeferredCreation )
     {
         if( RunDeferredCreationIfNecessary() != OGRERR_NONE )
@@ -580,8 +577,8 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
     GetLayerDefn();
-    int bHasUserFieldMatchingFID = FALSE;
-    if( osFIDColName.size() )
+    bool bHasUserFieldMatchingFID = false;
+    if( !osFIDColName.empty() )
         bHasUserFieldMatchingFID = poFeatureDefn->GetFieldIndex(osFIDColName) >= 0;
 
     if (!poDS->IsReadWrite())
@@ -593,8 +590,8 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     CPLString osSQL;
 
-    int bHasJustGotNextFID = FALSE;
-    if( !bHasUserFieldMatchingFID && bInDeferredInsert && nNextFID < 0 && osFIDColName.size() )
+    bool bHasJustGotNextFID = false;
+    if( !bHasUserFieldMatchingFID && bInDeferredInsert && nNextFID < 0 && !osFIDColName.empty() )
     {
         osSQL.Printf("SELECT nextval('%s') AS nextid",
                      OGRCARTOEscapeLiteral(CPLSPrintf("%s_%s_seq", osName.c_str(), osFIDColName.c_str())).c_str());
@@ -603,11 +600,11 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
         json_object* poRowObj = OGRCARTOGetSingleRow(poObj);
         if( poRowObj != NULL )
         {
-            json_object* poID = json_object_object_get(poRowObj, "nextid");
+            json_object* poID = CPL_json_object_object_get(poRowObj, "nextid");
             if( poID != NULL && json_object_get_type(poID) == json_type_int )
             {
                 nNextFID = json_object_get_int64(poID);
-                bHasJustGotNextFID = TRUE;
+                bHasJustGotNextFID = true;
             }
         }
 
@@ -618,7 +615,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
     // Check if we can go on with multiple insertion mode
     if( eDeferredInsertState == INSERT_MULTIPLE_FEATURE )
     {
-        if( !bHasUserFieldMatchingFID && osFIDColName.size() &&
+        if( !bHasUserFieldMatchingFID && !osFIDColName.empty() &&
             (poFeature->GetFID() != OGRNullFID || (nNextFID >= 0 && bHasJustGotNextFID)) )
         {
             if( FlushDeferredInsert(false) != OGRERR_NONE )
@@ -634,7 +631,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
         {
             eDeferredInsertState = INSERT_SINGLE_FEATURE;
         }
-        else if( !bHasUserFieldMatchingFID && osFIDColName.size() &&
+        else if( !bHasUserFieldMatchingFID && !osFIDColName.empty() &&
             (poFeature->GetFID() != OGRNullFID || (nNextFID >= 0 && bHasJustGotNextFID)) )
         {
             eDeferredInsertState = INSERT_SINGLE_FEATURE;
@@ -643,7 +640,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
         else
         {
             eDeferredInsertState = INSERT_MULTIPLE_FEATURE;
-            for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+            for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
             {
                 if( poFeatureDefn->GetFieldDefn(i)->GetDefault() != NULL )
                     eDeferredInsertState = INSERT_SINGLE_FEATURE;
@@ -651,11 +648,11 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
     }
 
-    int bMustComma = FALSE;
+    bool bMustComma = false;
     if( bWriteInsertInto )
     {
         osSQL.Printf("INSERT INTO %s ", OGRCARTOEscapeIdentifier(osName).c_str());
-        for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+        for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
         {
             if( eDeferredInsertState != INSERT_MULTIPLE_FEATURE &&
                 !poFeature->IsFieldSet(i) )
@@ -666,13 +663,13 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
             else
             {
                 osSQL += "(";
-                bMustComma = TRUE;
+                bMustComma = true;
             }
 
             osSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
         }
 
-        for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+        for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
         {
             if( eDeferredInsertState != INSERT_MULTIPLE_FEATURE &&
                 poFeature->GetGeomFieldRef(i) == NULL )
@@ -683,21 +680,21 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
             else
             {
                 osSQL += "(";
-                bMustComma = TRUE;
+                bMustComma = true;
             }
 
             osSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
         }
 
         if( !bHasUserFieldMatchingFID &&
-            osFIDColName.size() && (poFeature->GetFID() != OGRNullFID || (nNextFID >= 0 && bHasJustGotNextFID)) )
+            !osFIDColName.empty() && (poFeature->GetFID() != OGRNullFID || (nNextFID >= 0 && bHasJustGotNextFID)) )
         {
             if( bMustComma )
                 osSQL += ", ";
             else
             {
                 osSQL += "(";
-                bMustComma = TRUE;
+                bMustComma = true;
             }
 
             osSQL += OGRCARTOEscapeIdentifier(osFIDColName);
@@ -716,8 +713,8 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
         else
             osSQL += ") VALUES (";
 
-        bMustComma = FALSE;
-        for(i = 0; i < poFeatureDefn->GetFieldCount(); i++)
+        bMustComma = false;
+        for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++)
         {
             if( !poFeature->IsFieldSet(i) )
             {
@@ -726,7 +723,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
                     if( bMustComma )
                         osSQL += ", ";
                     else
-                        bMustComma = TRUE;
+                        bMustComma = true;
                     osSQL += "NULL";
                 }
                 continue;
@@ -735,10 +732,14 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
             if( bMustComma )
                 osSQL += ", ";
             else
-                bMustComma = TRUE;
+                bMustComma = true;
 
             OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
-            if( eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime )
+            if( poFeature->IsFieldNull(i) )
+            {
+                osSQL += "NULL";
+            }
+            else if( eType == OFTString || eType == OFTDateTime || eType == OFTDate || eType == OFTTime )
             {
                 osSQL += "'";
                 osSQL += OGRCARTOEscapeLiteral(poFeature->GetFieldAsString(i));
@@ -753,7 +754,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
                 osSQL += poFeature->GetFieldAsString(i);
         }
 
-        for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+        for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
         {
             OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
             if( poGeom == NULL )
@@ -763,7 +764,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
                     if( bMustComma )
                         osSQL += ", ";
                     else
-                        bMustComma = TRUE;
+                        bMustComma = true;
                     osSQL += "NULL";
                 }
                 continue;
@@ -772,7 +773,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
             if( bMustComma )
                 osSQL += ", ";
             else
-                bMustComma = TRUE;
+                bMustComma = true;
 
             OGRCartoGeomFieldDefn* poGeomFieldDefn =
                 (OGRCartoGeomFieldDefn *)poFeatureDefn->GetGeomFieldDefn(i);
@@ -802,24 +803,23 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
 
         if( !bHasUserFieldMatchingFID )
         {
-            if( osFIDColName.size() && nNextFID >= 0 )
+            if( !osFIDColName.empty() && nNextFID >= 0 )
             {
                 if( bHasJustGotNextFID )
                 {
                     if( bMustComma )
                         osSQL += ", ";
-                    else
-                        bMustComma = TRUE;
-
+                    // No need to set bMustComma to true in else case.
+                    // Not in a loop.
                     osSQL += CPLSPrintf(CPL_FRMT_GIB, nNextFID);
                 }
             }
-            else if( osFIDColName.size() && poFeature->GetFID() != OGRNullFID )
+            else if( !osFIDColName.empty() && poFeature->GetFID() != OGRNullFID )
             {
                 if( bMustComma )
                     osSQL += ", ";
-                else
-                    bMustComma = TRUE;
+                // No need to set bMustComma to true in else case
+                // Not in a loop.
 
                 osSQL += CPLSPrintf(CPL_FRMT_GIB, poFeature->GetFID());
             }
@@ -827,9 +827,8 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
 
         osSQL += ")";
     }
-    CPL_IGNORE_RET_VAL(bMustComma);
 
-    if( !bHasUserFieldMatchingFID && osFIDColName.size() && nNextFID >= 0 )
+    if( !bHasUserFieldMatchingFID && !osFIDColName.empty() && nNextFID >= 0 )
     {
         poFeature->SetFID(nNextFID);
         nNextFID ++;
@@ -838,8 +837,10 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
     if( bInDeferredInsert )
     {
         OGRErr eRet = OGRERR_NONE;
-        if( eDeferredInsertState == INSERT_SINGLE_FEATURE && /* in multiple mode, this would require rebuilding the osSQL buffer. Annoying... */
-            osDeferredInsertSQL.size() != 0 &&
+        // In multiple mode, this would require rebuilding the osSQL
+        // buffer. Annoying.
+        if( eDeferredInsertState == INSERT_SINGLE_FEATURE &&
+            !osDeferredInsertSQL.empty() &&
             (int)osDeferredInsertSQL.size() + (int)osSQL.size() > nMaxChunkSize )
         {
             eRet = FlushDeferredInsert(false);
@@ -860,7 +861,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
         return eRet;
     }
 
-    if( osFIDColName.size() )
+    if( !osFIDColName.empty() )
     {
         osSQL += " RETURNING ";
         osSQL += OGRCARTOEscapeIdentifier(osFIDColName);
@@ -874,7 +875,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
             return OGRERR_FAILURE;
         }
 
-        json_object* poID = json_object_object_get(poRowObj, osFIDColName);
+        json_object* poID = CPL_json_object_object_get(poRowObj, osFIDColName);
         if( poID != NULL && json_object_get_type(poID) == json_type_int )
         {
             poFeature->SetFID(json_object_get_int64(poID));
@@ -891,7 +892,7 @@ OGRErr OGRCARTOTableLayer::ICreateFeature( OGRFeature *poFeature )
         json_object* poObj = poDS->RunSQL(osSQL);
         if( poObj != NULL )
         {
-            json_object* poTotalRows = json_object_object_get(poObj, "total_rows");
+            json_object* poTotalRows = CPL_json_object_object_get(poObj, "total_rows");
             if( poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int )
             {
                 int nTotalRows = json_object_get_int(poTotalRows);
@@ -937,18 +938,21 @@ OGRErr OGRCARTOTableLayer::ISetFeature( OGRFeature *poFeature )
 
     CPLString osSQL;
     osSQL.Printf("UPDATE %s SET ", OGRCARTOEscapeIdentifier(osName).c_str());
-    int bMustComma = FALSE;
+    bool bMustComma = false;
     for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
+        if( !poFeature->IsFieldSet(i) )
+            continue;
+
         if( bMustComma )
             osSQL += ", ";
         else
-            bMustComma = TRUE;
+            bMustComma = true;
 
         osSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
         osSQL += " = ";
 
-        if( !poFeature->IsFieldSet(i) )
+        if( poFeature->IsFieldNull(i) )
         {
             osSQL += "NULL";
         }
@@ -976,7 +980,7 @@ OGRErr OGRCARTOTableLayer::ISetFeature( OGRFeature *poFeature )
         if( bMustComma )
             osSQL += ", ";
         else
-            bMustComma = TRUE;
+            bMustComma = true;
 
         osSQL += OGRCARTOEscapeIdentifier(poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
         osSQL += " = ";
@@ -1003,6 +1007,9 @@ OGRErr OGRCARTOTableLayer::ISetFeature( OGRFeature *poFeature )
         }
     }
 
+    if( !bMustComma ) // nothing to do
+        return OGRERR_NONE;
+
     osSQL += CPLSPrintf(" WHERE %s = " CPL_FRMT_GIB,
                     OGRCARTOEscapeIdentifier(osFIDColName).c_str(),
                     poFeature->GetFID());
@@ -1011,7 +1018,7 @@ OGRErr OGRCARTOTableLayer::ISetFeature( OGRFeature *poFeature )
     json_object* poObj = poDS->RunSQL(osSQL);
     if( poObj != NULL )
     {
-        json_object* poTotalRows = json_object_object_get(poObj, "total_rows");
+        json_object* poTotalRows = CPL_json_object_object_get(poObj, "total_rows");
         if( poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int )
         {
             int nTotalRows = json_object_get_int(poTotalRows);
@@ -1050,7 +1057,7 @@ OGRErr OGRCARTOTableLayer::DeleteFeature( GIntBig nFID )
         return OGRERR_FAILURE;
     }
 
-    if( osFIDColName.size() == 0 )
+    if( osFIDColName.empty() )
         return OGRERR_FAILURE;
 
     CPLString osSQL;
@@ -1063,7 +1070,7 @@ OGRErr OGRCARTOTableLayer::DeleteFeature( GIntBig nFID )
     json_object* poObj = poDS->RunSQL(osSQL);
     if( poObj != NULL )
     {
-        json_object* poTotalRows = json_object_object_get(poObj, "total_rows");
+        json_object* poTotalRows = CPL_json_object_object_get(poObj, "total_rows");
         if( poTotalRows != NULL && json_object_get_type(poTotalRows) == json_type_int )
         {
             int nTotalRows = json_object_get_int(poTotalRows);
@@ -1134,17 +1141,17 @@ void OGRCARTOTableLayer::BuildWhere()
                        szBox3D_1, szBox3D_2 );
     }
 
-    if( strlen(osQuery) > 0 )
+    if( !osQuery.empty() )
     {
-        if( osWHERE.size() > 0 )
+        if( !osWHERE.empty() )
             osWHERE += " AND ";
         osWHERE += osQuery;
     }
 
-    if( osFIDColName.size() == 0 )
+    if( osFIDColName.empty() )
     {
         osBaseSQL = osSELECTWithoutWHERE;
-        if( osWHERE.size() )
+        if( !osWHERE.empty() )
         {
             osBaseSQL += " WHERE ";
             osBaseSQL += osWHERE;
@@ -1166,7 +1173,7 @@ OGRFeature* OGRCARTOTableLayer::GetFeature( GIntBig nFeatureId )
 
     GetLayerDefn();
 
-    if( osFIDColName.size() == 0 )
+    if( osFIDColName.empty() )
         return OGRCARTOLayer::GetFeature(nFeatureId);
 
     CPLString osSQL = osSELECTWithoutWHERE;
@@ -1206,7 +1213,7 @@ GIntBig OGRCARTOTableLayer::GetFeatureCount(int bForce)
 
     CPLString osSQL(CPLSPrintf("SELECT COUNT(*) FROM %s",
                                OGRCARTOEscapeIdentifier(osName).c_str()));
-    if( osWHERE.size() )
+    if( !osWHERE.empty() )
     {
         osSQL += " WHERE ";
         osSQL += osWHERE;
@@ -1221,7 +1228,7 @@ GIntBig OGRCARTOTableLayer::GetFeatureCount(int bForce)
         return OGRCARTOLayer::GetFeatureCount(bForce);
     }
 
-    json_object* poCount = json_object_object_get(poRowObj, "count");
+    json_object* poCount = CPL_json_object_object_get(poRowObj, "count");
     if( poCount == NULL || json_object_get_type(poCount) != json_type_int )
     {
         json_object_put(poObj);
@@ -1274,7 +1281,7 @@ OGRErr OGRCARTOTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int
     json_object* poRowObj = OGRCARTOGetSingleRow(poObj);
     if( poRowObj != NULL )
     {
-        json_object* poExtent = json_object_object_get(poRowObj, "st_extent");
+        json_object* poExtent = CPL_json_object_object_get(poRowObj, "st_extent");
         if( poExtent != NULL && json_object_get_type(poExtent) == json_type_string )
         {
             const char* pszBox = json_object_get_string(poExtent);
@@ -1352,7 +1359,7 @@ int OGRCARTOTableLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap, OLCRandomRead) )
     {
         GetLayerDefn();
-        return osFIDColName.size() != 0;
+        return !osFIDColName.empty();
     }
 
     if( EQUAL(pszCap,OLCSequentialWrite)
@@ -1371,15 +1378,15 @@ int OGRCARTOTableLayer::TestCapability( const char * pszCap )
 /*                        SetDeferredCreation()                          */
 /************************************************************************/
 
-void OGRCARTOTableLayer::SetDeferredCreation (OGRwkbGeometryType eGType,
-                                               OGRSpatialReference* poSRSIn,
-                                               int bGeomNullable,
-                                               int bCartodbfyIn)
+void OGRCARTOTableLayer::SetDeferredCreation( OGRwkbGeometryType eGType,
+                                              OGRSpatialReference* poSRSIn,
+                                              bool bGeomNullable,
+                                              bool bCartodbfyIn )
 {
-    bDeferredCreation = TRUE;
+    bDeferredCreation = true;
     nNextFID = 1;
     CPLAssert(poFeatureDefn == NULL);
-    this->bCartodbfy = bCartodbfyIn;
+    bCartodbfy = bCartodbfyIn;
     poFeatureDefn = new OGRFeatureDefn(osName);
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType(wkbNone);
@@ -1414,7 +1421,7 @@ OGRErr OGRCARTOTableLayer::RunDeferredCreationIfNecessary()
 {
     if( !bDeferredCreation )
         return OGRERR_NONE;
-    bDeferredCreation = FALSE;
+    bDeferredCreation = false;
 
     CPLString osSQL;
     osSQL.Printf("CREATE TABLE %s ( %s SERIAL,",
@@ -1447,7 +1454,7 @@ OGRErr OGRCARTOTableLayer::RunDeferredCreationIfNecessary()
         {
             osSQL += OGRCARTOEscapeIdentifier(poFieldDefn->GetNameRef());
             osSQL += " ";
-            osSQL += OGRPGCommonLayerGetType(*poFieldDefn, FALSE, TRUE);
+            osSQL += OGRPGCommonLayerGetType(*poFieldDefn, false, true);
             if( !poFieldDefn->IsNullable() )
                 osSQL += " NOT NULL";
             if( poFieldDefn->GetDefault() != NULL && !poFieldDefn->IsDefaultDriverSpecific() )
diff --git a/ogr/ogrsf_frmts/cloudant/ogr_cloudant.h b/ogr/ogrsf_frmts/cloudant/ogr_cloudant.h
index 93a468c..92bd274 100644
--- a/ogr/ogrsf_frmts/cloudant/ogr_cloudant.h
+++ b/ogr/ogrsf_frmts/cloudant/ogr_cloudant.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: ogr_cloudant.h 37371 2017-02-13 11:41:59Z rouault $
  *
  * Project:  Cloudant Translator
  * Purpose:  Definition of classes for OGR Cloudant driver.
@@ -46,24 +46,24 @@ class OGRCloudantDataSource;
 
 class OGRCloudantTableLayer : public OGRCouchDBTableLayer
 {
-    int                       bHasStandardSpatial;
+    int                       bHasStandardSpatial;  // -1, TRUE, FALSE
     const char*               pszSpatialView;
     char*                     pszSpatialDDoc;
 
     protected:
-            virtual int               GetFeaturesToFetch() {
+            virtual int               GetFeaturesToFetch() override {
                return atoi(CPLGetConfigOption("CLOUDANT_PAGE_SIZE", "200"));
             }
 
-            virtual int               RunSpatialFilterQueryIfNecessary();
+            virtual bool              RunSpatialFilterQueryIfNecessary() override;
             virtual void              GetSpatialView();
-            virtual void              WriteMetadata();
-            virtual void              LoadMetadata();
+            virtual void              WriteMetadata() override;
+            virtual void              LoadMetadata() override;
 
     public:
-            OGRCloudantTableLayer(OGRCloudantDataSource* poDS,
-                                 const char* pszName);
-            ~OGRCloudantTableLayer();
+            OGRCloudantTableLayer( OGRCloudantDataSource* poDS,
+                                   const char* pszName );
+            virtual ~OGRCloudantTableLayer();
 };
 
 /************************************************************************/
@@ -76,29 +76,12 @@ class OGRCloudantDataSource : public OGRCouchDBDataSource
             OGRLayer*    OpenDatabase(const char* pszLayerName = NULL);
   public:
                         OGRCloudantDataSource();
-                        ~OGRCloudantDataSource();
+    virtual ~OGRCloudantDataSource();
     virtual int Open( const char * pszFilename, int bUpdateIn);
     virtual OGRLayer   *ICreateLayer( const char *pszName,
              OGRSpatialReference *poSpatialRef = NULL,
              OGRwkbGeometryType eGType = wkbUnknown,
-             char ** papszOptions = NULL );
-};
-
-/************************************************************************/
-/*                           OGRCloudantDriver                          */
-/************************************************************************/
-
-class OGRCloudantDriver : public OGRCouchDBDriver
-{
-  public:
-                ~OGRCloudantDriver();
-
-    virtual const char*         GetName();
-    virtual OGRDataSource*      Open( const char *, int );
-    virtual OGRDataSource*      CreateDataSource( const char * pszName,
-                                                  char **papszOptions );
-    virtual int                 TestCapability( const char * );
-
+             char ** papszOptions = NULL ) override;
 };
 
 #endif /* ndef OGR_CLOUDANT_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp b/ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp
index a7b1d1b..847f979 100644
--- a/ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp
+++ b/ogr/ogrsf_frmts/cloudant/ogrcloudantdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  Cloudant Translator
  * Purpose:  Definition of classes for OGR Cloudant driver.
@@ -33,7 +32,7 @@
 #include "ogrgeojsonwriter.h"
 #include "swq.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogrcloudantdatasource.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /************************************************************************/
 /*                        OGRCloudantDataSource()                       */
@@ -91,7 +90,7 @@ OGRLayer* OGRCloudantDataSource::OpenDatabase(const char* pszLayerName)
         return NULL;
 
     if ( !json_object_is_type(poAnswerObj, json_type_object) ||
-            json_object_object_get(poAnswerObj, "db_name") == NULL )
+            CPL_json_object_object_get(poAnswerObj, "db_name") == NULL )
     {
         IsError(poAnswerObj, "Database opening failed");
 
@@ -101,9 +100,9 @@ OGRLayer* OGRCloudantDataSource::OpenDatabase(const char* pszLayerName)
 
     OGRCloudantTableLayer* poLayer = new OGRCloudantTableLayer(this, osTableName);
 
-    if ( json_object_object_get(poAnswerObj, "update_seq") != NULL )
+    if ( CPL_json_object_object_get(poAnswerObj, "update_seq") != NULL )
     {
-        int nUpdateSeq = json_object_get_int(json_object_object_get(poAnswerObj, "update_seq"));
+        int nUpdateSeq = json_object_get_int(CPL_json_object_object_get(poAnswerObj, "update_seq"));
         poLayer->SetUpdateSeq(nUpdateSeq);
     }
 
@@ -115,7 +114,6 @@ OGRLayer* OGRCloudantDataSource::OpenDatabase(const char* pszLayerName)
     return poLayer;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -123,22 +121,21 @@ OGRLayer* OGRCloudantDataSource::OpenDatabase(const char* pszLayerName)
 int OGRCloudantDataSource::Open( const char * pszFilename, int bUpdateIn)
 
 {
-    int bHTTP = FALSE;
-    if (STARTS_WITH(pszFilename, "http://") ||
-        STARTS_WITH(pszFilename, "https://"))
-        bHTTP = TRUE;
-    else if (!STARTS_WITH_CI(pszFilename, "cloudant:"))
+    const bool bHTTP =
+        STARTS_WITH(pszFilename, "http://") ||
+        STARTS_WITH(pszFilename, "https://");
+    if( !bHTTP && !STARTS_WITH_CI(pszFilename, "cloudant:") )
         return FALSE;
 
-    bReadWrite = bUpdateIn;
+    bReadWrite = CPL_TO_BOOL(bUpdateIn);
 
     pszName = CPLStrdup( pszFilename );
 
-    if (bHTTP)
+    if( bHTTP )
         osURL = pszFilename;
     else
         osURL = pszFilename + 9;
-    if (osURL.size() > 0 && osURL[osURL.size() - 1] == '/')
+    if (!osURL.empty() && osURL.back() == '/')
         osURL.resize(osURL.size() - 1);
 
     const char* pszUserPwd = CPLGetConfigOption("CLOUDANT_USERPWD", NULL);
@@ -162,7 +159,6 @@ int OGRCloudantDataSource::Open( const char * pszFilename, int bUpdateIn)
         return OpenDatabase() != NULL;
     }
 
-
     pszKnowProvider = strstr(osURL, "localhost");
     if (pszKnowProvider != NULL &&
         strstr(pszKnowProvider + strlen("localhost"), pszSlash ) != NULL)
@@ -177,8 +173,8 @@ int OGRCloudantDataSource::Open( const char * pszFilename, int bUpdateIn)
     {
         if ( json_object_is_type(poAnswerObj, json_type_object) )
         {
-            json_object* poError = json_object_object_get(poAnswerObj, "error");
-            json_object* poReason = json_object_object_get(poAnswerObj, "reason");
+            json_object* poError = CPL_json_object_object_get(poAnswerObj, "error");
+            json_object* poReason = CPL_json_object_object_get(poAnswerObj, "reason");
 
             const char* pszError = json_object_get_string(poError);
             const char* pszReason = json_object_get_string(poReason);
@@ -225,7 +221,6 @@ int OGRCloudantDataSource::Open( const char * pszFilename, int bUpdateIn)
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                          ICreateLayer()                              */
 /************************************************************************/
@@ -249,9 +244,7 @@ OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *l_pszName,
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
-    int iLayer;
-
-    for( iLayer = 0; iLayer < GetLayerCount(); iLayer++ )
+    for( int iLayer = 0; iLayer < GetLayerCount(); iLayer++ )
     {
         if( EQUAL(osLayerName, papoLayers[iLayer]->GetName()) )
         {
@@ -288,7 +281,7 @@ OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *l_pszName,
     if (poAnswerObj == NULL)
         return NULL;
 
-    if (!IsOK(poAnswerObj, "Layer creation failed"))
+    if( !IsOK(poAnswerObj, "Layer creation failed") )
     {
         json_object_put(poAnswerObj);
         return NULL;
@@ -359,20 +352,22 @@ OGRLayer   *OGRCloudantDataSource::ICreateLayer( const char *l_pszName,
 
         poAnswerObj = PUT(osURI, json_object_to_json_string(poDoc));
 
-        if (IsOK(poAnswerObj, "Cloudant spatial index creation failed"))
-            nUpdateSeq ++;
+        if( IsOK(poAnswerObj, "Cloudant spatial index creation failed") )
+            nUpdateSeq++;
 
         json_object_put(poDoc);
         json_object_put(poAnswerObj);
     }
 
-    int bGeoJSONDocument = CPLTestBool(CSLFetchNameValueDef(papszOptions, "GEOJSON", "TRUE"));
+    const bool bGeoJSONDocument =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions, "GEOJSON", "TRUE"));
     int nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
 
     OGRCloudantTableLayer* poLayer = new OGRCloudantTableLayer(this, osLayerName);
     if (nCoordPrecision != -1)
         poLayer->SetCoordinatePrecision(nCoordPrecision);
-    poLayer->SetInfoAfterCreation(eGType, poSpatialRef, nUpdateSeq, bGeoJSONDocument);
+    poLayer->SetInfoAfterCreation(eGType, poSpatialRef,
+                                  nUpdateSeq, bGeoJSONDocument);
     papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
     papoLayers[nLayers ++] = poLayer;
     return poLayer;
diff --git a/ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp b/ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp
index 37f9610..cee9fa7 100644
--- a/ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp
+++ b/ogr/ogrsf_frmts/cloudant/ogrcloudantdriver.cpp
@@ -1,8 +1,7 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  CouchDB Translator
- * Purpose:  Implements OGRCouchDBDriver.
+ * Purpose:  Implements OGRCloudantDriver.
  * Author:   Even Rouault, even dot rouault at mines dash paris dot org
  *
  ******************************************************************************
@@ -29,42 +28,37 @@
 
 #include "ogr_cloudant.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogrcloudantdriver.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 extern "C" void RegisterOGRCloudant();
 
 /************************************************************************/
-/*                         ~OGRCloudantDriver()                          */
+/*                   OGRCloudantDriverIdentify()                        */
 /************************************************************************/
 
-OGRCloudantDriver::~OGRCloudantDriver()
+static int OGRCloudantDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
-}
-
-/************************************************************************/
-/*                              GetName()                               */
-/************************************************************************/
+    if (STARTS_WITH_CI(poOpenInfo->pszFilename, "Cloudant:"))
+        return 1;
+    else
+        return 0;
 
-const char *OGRCloudantDriver::GetName()
-
-{
-    return "Cloudant";
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                  OGRCloudantDriverOpen()                             */
 /************************************************************************/
 
-OGRDataSource *OGRCloudantDriver::Open( const char * pszFilename, int bUpdate )
+static GDALDataset* OGRCloudantDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    if (!STARTS_WITH_CI(pszFilename, "cloudant:"))
+    if( OGRCloudantDriverIdentify(poOpenInfo) == 0 )
         return NULL;
 
     OGRCloudantDataSource   *poDS = new OGRCloudantDataSource();
 
-    if( !poDS->Open( pszFilename, bUpdate ) )
+    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update ) )
     {
         delete poDS;
         poDS = NULL;
@@ -73,13 +67,16 @@ OGRDataSource *OGRCloudantDriver::Open( const char * pszFilename, int bUpdate )
     return poDS;
 }
 
-
 /************************************************************************/
 /*                          CreateDataSource()                          */
 /************************************************************************/
 
-OGRDataSource *OGRCloudantDriver::CreateDataSource( const char * pszName,
-                                                   CPL_UNUSED char **papszOptions )
+static GDALDataset* OGRCloudantDriverCreate( const char * pszName,
+                                            int /* nXSize */,
+                                            int /* nYSize */,
+                                            int /* nBands */,
+                                            GDALDataType /* eDT */,
+                                            char ** /* papszOptions */ )
 {
     OGRCloudantDataSource   *poDS = new OGRCloudantDataSource();
 
@@ -93,26 +90,40 @@ OGRDataSource *OGRCloudantDriver::CreateDataSource( const char * pszName,
 }
 
 /************************************************************************/
-/*                           TestCapability()                           */
+/*                         RegisterOGRCloudant()                        */
 /************************************************************************/
 
-int OGRCloudantDriver::TestCapability( const char * pszCap )
+void RegisterOGRCloudant()
 
 {
-    if (EQUAL(pszCap, ODrCCreateDataSource))
-        return TRUE;
+    if( GDALGetDriverByName( "Cloudant" ) != NULL )
+      return;
 
-    return FALSE;
-}
-
-/************************************************************************/
-/*                         RegisterOGRCloudant()                         */
-/************************************************************************/
+    GDALDriver  *poDriver = new GDALDriver();
 
-void RegisterOGRCloudant()
-
-{
-    OGRSFDriver* poDriver = new OGRCloudantDriver;
+    poDriver->SetDescription( "Cloudant" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Cloudant / CouchDB" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_cloudant.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "Cloudant:" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>");
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    "<LayerCreationOptionList>"
+    "  <Option name='UPDATE_PERMISSIONS' type='string' description='Update permissions for the new layer.'/>"
+    "  <Option name='GEOJSON ' type='boolean' description='Whether to write documents as GeoJSON documents.' default='YES'/>"
+    "  <Option name='COORDINATE_PRECISION' type='int' description='Maximum number of figures after decimal separator to write in coordinates.' default='15'/>"
+    "</LayerCreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time IntegerList Integer64List RealList "
+                               "StringList Binary" );
+
+    poDriver->pfnIdentify = OGRCloudantDriverIdentify;
+    poDriver->pfnOpen = OGRCloudantDriverOpen;
+    poDriver->pfnCreate = OGRCloudantDriverCreate;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp b/ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp
index 97a0b54..6a8295c 100644
--- a/ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp
+++ b/ogr/ogrsf_frmts/cloudant/ogrcloudanttablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  Cloudant Translator
  * Purpose:  Definition of classes for OGR Cloudant driver.
@@ -35,7 +34,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogrcloudanttablelayer.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 /************************************************************************/
 /*                       OGRCloudantTableLayer()                         */
@@ -59,7 +58,7 @@ OGRCloudantTableLayer::~OGRCloudantTableLayer()
     if( bMustWriteMetadata )
     {
         WriteMetadata();
-        bMustWriteMetadata = FALSE;
+        bMustWriteMetadata = false;
     }
 
     if (pszSpatialDDoc)
@@ -70,12 +69,12 @@ OGRCloudantTableLayer::~OGRCloudantTableLayer()
 /*                   RunSpatialFilterQueryIfNecessary()                 */
 /************************************************************************/
 
-int OGRCloudantTableLayer::RunSpatialFilterQueryIfNecessary()
+bool OGRCloudantTableLayer::RunSpatialFilterQueryIfNecessary()
 {
-    if (!bMustRunSpatialFilter)
-        return TRUE;
+    if( !bMustRunSpatialFilter )
+        return true;
 
-    bMustRunSpatialFilter = FALSE;
+    bMustRunSpatialFilter = false;
 
     CPLAssert(nOffset == 0);
 
@@ -101,24 +100,24 @@ int OGRCloudantTableLayer::RunSpatialFilterQueryIfNecessary()
     {
         CPLDebug("Cloudant",
                     "Cloudant geo not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
-        return FALSE;
+        bServerSideSpatialFilteringWorks = false;
+        return false;
     }
 
     if ( !json_object_is_type(poAnswerObj, json_type_object) )
     {
         CPLDebug("Cloudant",
                     "Cloudant geo not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
+        bServerSideSpatialFilteringWorks = false;
         CPLError(CE_Failure, CPLE_AppDefined,
                     "FetchNextRowsSpatialFilter() failed");
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
     /* Catch error for a non cloudant geo database */
-    json_object* poError = json_object_object_get(poAnswerObj, "error");
-    json_object* poReason = json_object_object_get(poAnswerObj, "reason");
+    json_object* poError = CPL_json_object_object_get(poAnswerObj, "error");
+    json_object* poReason = CPL_json_object_object_get(poAnswerObj, "reason");
 
     const char* pszError = json_object_get_string(poError);
     const char* pszReason = json_object_get_string(poReason);
@@ -128,31 +127,31 @@ int OGRCloudantTableLayer::RunSpatialFilterQueryIfNecessary()
     {
         CPLDebug("Cloudant",
                     "Cloudant geo not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
+        bServerSideSpatialFilteringWorks = false;
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
     if (poDS->IsError(poAnswerObj, "FetchNextRowsSpatialFilter() failed"))
     {
         CPLDebug("Cloudant",
                     "Cloudant geo not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
+        bServerSideSpatialFilteringWorks = false;
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
-    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    json_object* poRows = CPL_json_object_object_get(poAnswerObj, "rows");
     if (poRows == NULL ||
         !json_object_is_type(poRows, json_type_array))
     {
         CPLDebug("Cloudant",
                     "Cloudant geo not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
+        bServerSideSpatialFilteringWorks = false;
         CPLError(CE_Failure, CPLE_AppDefined,
                     "FetchNextRowsSpatialFilter() failed");
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
     int nRows = json_object_array_length(poRows);
@@ -165,10 +164,10 @@ int OGRCloudantTableLayer::RunSpatialFilterQueryIfNecessary()
             CPLError(CE_Failure, CPLE_AppDefined,
                         "FetchNextRowsSpatialFilter() failed");
             json_object_put(poAnswerObj);
-            return FALSE;
+            return false;
         }
 
-        json_object* poId = json_object_object_get(poRow, "id");
+        json_object* poId = CPL_json_object_object_get(poRow, "id");
         const char* pszId = json_object_get_string(poId);
         if (pszId != NULL)
         {
@@ -180,10 +179,9 @@ int OGRCloudantTableLayer::RunSpatialFilterQueryIfNecessary()
 
     json_object_put(poAnswerObj);
 
-    return TRUE;
+    return true;
 }
 
-
 /************************************************************************/
 /*                          GetSpatialView()                          */
 /************************************************************************/
@@ -192,8 +190,6 @@ void OGRCloudantTableLayer::GetSpatialView()
 {
     if (pszSpatialView == NULL)
     {
-        char **papszTokens;
-
         if (bHasStandardSpatial < 0 || bHasStandardSpatial == FALSE)
         {
             pszSpatialView = CPLGetConfigOption("CLOUDANT_SPATIAL_FILTER" , NULL);
@@ -211,14 +207,14 @@ void OGRCloudantTableLayer::GetSpatialView()
             json_object* poAnswerObj = poDS->GET(osURI);
             bHasStandardSpatial = (poAnswerObj != NULL &&
                 json_object_is_type(poAnswerObj, json_type_object) &&
-                json_object_object_get(poAnswerObj, "st_indexes") != NULL);
+                CPL_json_object_object_get(poAnswerObj, "st_indexes") != NULL);
             json_object_put(poAnswerObj);
         }
 
         if (bHasStandardSpatial)
             pszSpatialView = "_design/SpatialView/_geo/spatial";
 
-        papszTokens =
+        char **papszTokens =
             CSLTokenizeString2( pszSpatialView, "/", 0);
 
         if ((papszTokens[0] == NULL) || (papszTokens[1] == NULL))
@@ -229,7 +225,7 @@ void OGRCloudantTableLayer::GetSpatialView()
         }
 
         const size_t nLen = strlen(papszTokens[0]) + strlen(papszTokens[1]) + 2;
-        pszSpatialDDoc = (char*) CPLCalloc(nLen, 1);
+        pszSpatialDDoc = static_cast<char *>(CPLCalloc(nLen, 1));
 
         snprintf(pszSpatialDDoc, nLen, "%s/%s", papszTokens[0], papszTokens[1]);
 
@@ -256,7 +252,6 @@ void OGRCloudantTableLayer::WriteMetadata()
     osURI += "/";
     osURI += pszSpatialDDoc;
 
-
    json_object* poDDocObj = poDS->GET(osURI);
     if (poDDocObj == NULL)
         return;
@@ -268,7 +263,7 @@ void OGRCloudantTableLayer::WriteMetadata()
         return;
     }
 
-    json_object* poError = json_object_object_get(poDDocObj, "error");
+    json_object* poError = CPL_json_object_object_get(poDDocObj, "error");
     const char* pszError = json_object_get_string(poError);
     if (pszError && strcmp(pszError, "not_found") == 0)
     {
@@ -282,7 +277,6 @@ void OGRCloudantTableLayer::WriteMetadata()
         return;
     }
 
-
     if (poSRS)
     {
         // epsg codes are supported in Cloudant
@@ -311,7 +305,6 @@ void OGRCloudantTableLayer::WriteMetadata()
             {
                 json_object_object_add(poDDocObj, "srsid",
                                    json_object_new_string(pszUrn));
-
             }
         }
     }
@@ -385,10 +378,10 @@ static int OGRCloudantIsNumericObject(json_object* poObj)
 
 void OGRCloudantTableLayer::LoadMetadata()
 {
-    if (bHasLoadedMetadata)
+    if( bHasLoadedMetadata )
         return;
 
-    bHasLoadedMetadata = TRUE;
+    bHasLoadedMetadata = true;
 
     if (pszSpatialDDoc == NULL)
         GetSpatialView();
@@ -411,12 +404,12 @@ void OGRCloudantTableLayer::LoadMetadata()
         return;
     }
 
-    json_object* poRev = json_object_object_get(poAnswerObj, "_rev");
+    json_object* poRev = CPL_json_object_object_get(poAnswerObj, "_rev");
     const char* pszRev = json_object_get_string(poRev);
     if (pszRev)
         osMetadataRev = pszRev;
 
-    json_object* poError = json_object_object_get(poAnswerObj, "error");
+    json_object* poError = CPL_json_object_object_get(poAnswerObj, "error");
     const char* pszError = json_object_get_string(poError);
     if (pszError && strcmp(pszError, "not_found") == 0)
     {
@@ -430,7 +423,7 @@ void OGRCloudantTableLayer::LoadMetadata()
         return;
     }
 
-    json_object* poJsonSRS = json_object_object_get(poAnswerObj, "srsid");
+    json_object* poJsonSRS = CPL_json_object_object_get(poAnswerObj, "srsid");
     const char* pszSRS = json_object_get_string(poJsonSRS);
     if (pszSRS != NULL)
     {
@@ -442,7 +435,7 @@ void OGRCloudantTableLayer::LoadMetadata()
         }
     }
 
-    json_object* poGeomType = json_object_object_get(poAnswerObj, "geomtype");
+    json_object* poGeomType = CPL_json_object_object_get(poAnswerObj, "geomtype");
     const char* pszGeomType = json_object_get_string(poGeomType);
 
      if (pszGeomType)
@@ -450,20 +443,20 @@ void OGRCloudantTableLayer::LoadMetadata()
         if (EQUAL(pszGeomType, "NONE"))
         {
             eGeomType = wkbNone;
-            bExtentValid = TRUE;
+            bExtentValid = true;
         }
         else
         {
             eGeomType = OGRFromOGCGeomType(pszGeomType);
 
-            json_object* poIs25D = json_object_object_get(poAnswerObj, "is_25D");
+            json_object* poIs25D = CPL_json_object_object_get(poAnswerObj, "is_25D");
             if (poIs25D && json_object_get_boolean(poIs25D))
                 eGeomType = wkbSetZ(eGeomType);
 
-            json_object* poExtent = json_object_object_get(poAnswerObj, "extent");
+            json_object* poExtent = CPL_json_object_object_get(poAnswerObj, "extent");
             if (poExtent && json_object_get_type(poExtent) == json_type_object)
             {
-                json_object* poBbox = json_object_object_get(poExtent, "bbox");
+                json_object* poBbox = CPL_json_object_object_get(poExtent, "bbox");
                 if (poBbox &&
                     json_object_get_type(poBbox) == json_type_array &&
                     json_object_array_length(poBbox) == 4 &&
@@ -476,17 +469,18 @@ void OGRCloudantTableLayer::LoadMetadata()
                     dfMinY = json_object_get_double(json_object_array_get_idx(poBbox, 1));
                     dfMaxX = json_object_get_double(json_object_array_get_idx(poBbox, 2));
                     dfMaxY = json_object_get_double(json_object_array_get_idx(poBbox, 3));
-                    bExtentValid = bExtentSet = TRUE;
+                    bExtentValid = true;
+                    bExtentSet = true;
                 }
             }
         }
     }
 
-    json_object* poGeoJSON = json_object_object_get(poAnswerObj, "geojson_documents");
+    json_object* poGeoJSON = CPL_json_object_object_get(poAnswerObj, "geojson_documents");
     if (poGeoJSON && json_object_is_type(poGeoJSON, json_type_boolean))
-        bGeoJSONDocument = json_object_get_boolean(poGeoJSON);
+        bGeoJSONDocument = CPL_TO_BOOL(json_object_get_boolean(poGeoJSON));
 
-    json_object* poFields = json_object_object_get(poAnswerObj, "fields");
+    json_object* poFields = CPL_json_object_object_get(poAnswerObj, "fields");
     if (poFields && json_object_is_type(poFields, json_type_array))
     {
         poFeatureDefn = new OGRFeatureDefn( osName );
@@ -508,11 +502,11 @@ void OGRCloudantTableLayer::LoadMetadata()
             json_object* poField = json_object_array_get_idx(poFields, i);
             if (poField && json_object_is_type(poField, json_type_object))
             {
-                json_object* poName = json_object_object_get(poField, "name");
+                json_object* poName = CPL_json_object_object_get(poField, "name");
                 const char* pszName = json_object_get_string(poName);
                 if (pszName)
                 {
-                    json_object* poType = json_object_object_get(poField, "type");
+                    json_object* poType = CPL_json_object_object_get(poField, "type");
                     const char* pszType = json_object_get_string(poType);
                     OGRFieldType eType = OFTString;
                     if (pszType)
diff --git a/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h b/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
index 9ab4f2b..dd6c074 100644
--- a/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
+++ b/ogr/ogrsf_frmts/couchdb/ogr_couchdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_couchdb.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_couchdb.h 37371 2017-02-13 11:41:59Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Definition of classes for OGR CouchDB / GeoCouch driver.
@@ -32,7 +32,8 @@
 
 #include "ogrsf_frmts.h"
 #include "cpl_http.h"
-#include <json.h>
+
+#include "ogr_json_header.h"
 
 #include <vector>
 #include <map>
@@ -62,43 +63,43 @@ protected:
 
     int                         nNextInSeq;
     int                         nOffset;
-    int                         bEOF;
+    bool                        bEOF;
 
     json_object*                poFeatures;
     std::vector<json_object*>   aoFeatures;
 
     OGRFeature*                 GetNextRawFeature();
     OGRFeature*                 TranslateFeature( json_object* poObj );
-    void                        ParseFieldValue(OGRFeature* poFeature,
+    static void                        ParseFieldValue(OGRFeature* poFeature,
                                                 const char* pszKey,
                                                 json_object* poValue);
 
-    int                         FetchNextRowsAnalyseDocs(json_object* poAnswerObj);
-   virtual int                  FetchNextRows() = 0;
+    bool                        FetchNextRowsAnalyseDocs( json_object* poAnswerObj );
+    virtual bool                FetchNextRows() = 0;
 
-   int                          bGeoJSONDocument;
+    bool                        bGeoJSONDocument;
 
-   void                         BuildFeatureDefnFromDoc(json_object* poDoc);
-   int                          BuildFeatureDefnFromRows(json_object* poAnswerObj);
+    void                        BuildFeatureDefnFromDoc(json_object* poDoc);
+    bool                        BuildFeatureDefnFromRows( json_object* poAnswerObj );
 
-   virtual int                  GetFeaturesToFetch() { return atoi(CPLGetConfigOption("COUCHDB_PAGE_SIZE", "500")); }
+    virtual int                 GetFeaturesToFetch() { return atoi(CPLGetConfigOption("COUCHDB_PAGE_SIZE", "500")); }
 
   public:
-                         OGRCouchDBLayer(OGRCouchDBDataSource* poDS);
-                        ~OGRCouchDBLayer();
+    explicit OGRCouchDBLayer(OGRCouchDBDataSource* poDS);
+    virtual ~OGRCouchDBLayer();
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     virtual CouchDBLayerType    GetLayerType() = 0;
 
-    virtual OGRErr              SetNextByIndex( GIntBig nIndex );
+    virtual OGRErr              SetNextByIndex( GIntBig nIndex ) override;
 
-    virtual OGRSpatialReference * GetSpatialRef();
+    virtual OGRSpatialReference * GetSpatialRef() override;
 };
 
 /************************************************************************/
@@ -108,27 +109,27 @@ protected:
 class OGRCouchDBTableLayer : public OGRCouchDBLayer
 {
     int                       nNextFIDForCreate;
-    int                       bInTransaction;
+    bool                      bInTransaction;
     std::vector<json_object*> aoTransactionFeatures;
 
-    virtual int               FetchNextRows();
+    virtual bool              FetchNextRows() override;
 
     int                       bHasOGRSpatial;
-    int                       bHasGeocouchUtilsMinimalSpatialView;
-    int                       bServerSideAttributeFilteringWorks;
-    int                       FetchNextRowsSpatialFilter();
+    bool                      bHasGeocouchUtilsMinimalSpatialView;
+    bool                      bServerSideAttributeFilteringWorks;
+    bool                      FetchNextRowsSpatialFilter();
 
-    int                       bHasInstalledAttributeFilter;
+    bool                      bHasInstalledAttributeFilter;
     CPLString                 osURIAttributeFilter;
     std::map<CPLString, int>  oMapFilterFields;
-    CPLString                 BuildAttrQueryURI(int& bOutHasStrictComparisons);
-    int                       FetchNextRowsAttributeFilter();
+    CPLString                 BuildAttrQueryURI(bool& bOutHasStrictComparisons);
+    bool                      FetchNextRowsAttributeFilter();
 
     int                       GetTotalFeatureCount();
     int                       GetMaximumId();
 
     int                       nUpdateSeq;
-    int                       bAlwaysValid;
+    bool                      bAlwaysValid;
     int                       FetchUpdateSeq();
 
     int                       nCoordPrecision;
@@ -140,15 +141,15 @@ class OGRCouchDBTableLayer : public OGRCouchDBLayer
 
     CPLString                 osName;
     CPLString                 osEscapedName;
-    int                       bMustWriteMetadata;
-    int                       bMustRunSpatialFilter;
+    bool                      bMustWriteMetadata;
+    bool                      bMustRunSpatialFilter;
     std::vector<CPLString>    aosIdsToFetch;
-    int                       bServerSideSpatialFilteringWorks;
-    int                       bHasLoadedMetadata;
+    bool                      bServerSideSpatialFilteringWorks;
+    bool                      bHasLoadedMetadata;
     CPLString                 osMetadataRev;
-    int                       bExtentValid;
+    bool                      bExtentValid;
 
-    int                       bExtentSet;
+    bool                      bExtentSet;
     double                    dfMinX;
     double                    dfMinY;
     double                    dfMaxX;
@@ -158,55 +159,56 @@ class OGRCouchDBTableLayer : public OGRCouchDBLayer
 
     virtual void              WriteMetadata();
     virtual void              LoadMetadata();
-    virtual int               RunSpatialFilterQueryIfNecessary();
+    virtual bool              RunSpatialFilterQueryIfNecessary();
 
     public:
             OGRCouchDBTableLayer(OGRCouchDBDataSource* poDS,
                                  const char* pszName);
-            ~OGRCouchDBTableLayer();
+    virtual ~OGRCouchDBTableLayer();
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
 
-    virtual const char *        GetName() { return osName.c_str(); }
+    virtual const char *        GetName() override { return osName.c_str(); }
 
-    virtual GIntBig             GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr              GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual GIntBig             GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr              GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    virtual OGRFeature *        GetFeature( GIntBig nFID );
+    virtual OGRFeature *        GetFeature( GIntBig nFID ) override;
 
-    virtual void                SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void                SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
-    virtual OGRErr              SetAttributeFilter( const char * );
+    virtual OGRErr              SetAttributeFilter( const char * ) override;
 
     virtual OGRErr              CreateField( OGRFieldDefn *poField,
-                                            int bApproxOK = TRUE );
-    virtual OGRErr              ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr              ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr              DeleteFeature( GIntBig nFID );
+                                             int bApproxOK = TRUE ) override;
+    virtual OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr              ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr              DeleteFeature( GIntBig nFID ) override;
 
-    virtual OGRErr              StartTransaction();
-    virtual OGRErr              CommitTransaction();
-    virtual OGRErr              RollbackTransaction();
+    virtual OGRErr              StartTransaction() override;
+    virtual OGRErr              CommitTransaction() override;
+    virtual OGRErr              RollbackTransaction() override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
-    void                        SetInfoAfterCreation(OGRwkbGeometryType eGType,
-                                             OGRSpatialReference* poSRSIn,
-                                             int nUpdateSeqIn,
-                                             int bGeoJSONDocumentIn);
+    void                        SetInfoAfterCreation( OGRwkbGeometryType eGType,
+                                                      OGRSpatialReference* poSRSIn,
+                                                      int nUpdateSeqIn,
+                                                      bool bGeoJSONDocumentIn );
 
     void                        SetUpdateSeq(int nUpdateSeqIn) { nUpdateSeq = nUpdateSeqIn; };
 
     int                       HasFilterOnFieldOrCreateIfNecessary(const char* pszFieldName);
 
-    void                        SetCoordinatePrecision(int nCoordPrecisionIn) { this->nCoordPrecision = nCoordPrecisionIn; }
+    void                        SetCoordinatePrecision( int nCoordPrecisionIn )
+        { nCoordPrecision = nCoordPrecisionIn; }
 
-    virtual CouchDBLayerType    GetLayerType() { return COUCHDB_TABLE_LAYER; }
+    virtual CouchDBLayerType    GetLayerType() override { return COUCHDB_TABLE_LAYER; }
 
     OGRErr            DeleteFeature( const char* pszId );
 };
@@ -217,19 +219,19 @@ class OGRCouchDBTableLayer : public OGRCouchDBLayer
 
 class OGRCouchDBRowsLayer : public OGRCouchDBLayer
 {
-    int                       bAllInOne;
+    bool                      bAllInOne;
 
-    virtual int               FetchNextRows();
+    virtual bool              FetchNextRows() override;
 
     public:
-            OGRCouchDBRowsLayer(OGRCouchDBDataSource* poDS);
-            ~OGRCouchDBRowsLayer();
+            explicit OGRCouchDBRowsLayer( OGRCouchDBDataSource* poDS );
+            virtual ~OGRCouchDBRowsLayer();
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 
-    int                         BuildFeatureDefn();
+    bool                        BuildFeatureDefn();
 
-    virtual CouchDBLayerType    GetLayerType() { return COUCHDB_TABLE_LAYER; }
+    virtual CouchDBLayerType    GetLayerType() override { return COUCHDB_TABLE_LAYER; }
 };
 
 /************************************************************************/
@@ -244,9 +246,9 @@ class OGRCouchDBDataSource : public OGRDataSource
     OGRLayer**          papoLayers;
     int                 nLayers;
 
-    int                 bReadWrite;
+    bool                bReadWrite;
 
-    int                 bMustCleanPersistent;
+    bool                bMustCleanPersistent;
 
     CPLString           osURL;
     CPLString           osUserPwd;
@@ -263,31 +265,31 @@ class OGRCouchDBDataSource : public OGRDataSource
 
   public:
                         OGRCouchDBDataSource();
-                        ~OGRCouchDBDataSource();
+                        virtual ~OGRCouchDBDataSource();
 
     int                 Open( const char * pszFilename,
                               int bUpdate );
 
-    virtual const char* GetName() { return pszName; }
+    virtual const char* GetName() override { return pszName; }
 
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer*   GetLayer( int );
-    virtual OGRLayer    *GetLayerByName(const char *);
+    virtual int         GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*   GetLayer( int ) override;
+    virtual OGRLayer    *GetLayerByName(const char *) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
-                                     char ** papszOptions = NULL );
-    virtual OGRErr      DeleteLayer(int);
+                                     char ** papszOptions = NULL ) override;
+    virtual OGRErr      DeleteLayer(int) override;
 
     virtual OGRLayer*  ExecuteSQL( const char *pszSQLCommand,
                                    OGRGeometry *poSpatialFilter,
-                                   const char *pszDialect );
-    virtual void       ReleaseResultSet( OGRLayer * poLayer );
+                                   const char *pszDialect ) override;
+    virtual void       ReleaseResultSet( OGRLayer * poLayer ) override;
 
-    int                         IsReadWrite() const { return bReadWrite; }
+    bool                IsReadWrite() const { return bReadWrite; }
 
     char*                 GetETag(const char* pszURI);
     json_object*                GET(const char* pszURI);
@@ -297,26 +299,10 @@ class OGRCouchDBDataSource : public OGRDataSource
 
     const CPLString&            GetURL() const { return osURL; }
 
-    static int                  IsError(json_object* poAnswerObj,
+    static bool                 IsError(json_object* poAnswerObj,
                                         const char* pszErrorMsg);
-    static int                  IsOK   (json_object* poAnswerObj,
+    static bool                 IsOK   (json_object* poAnswerObj,
                                         const char* pszErrorMsg);
 };
 
-/************************************************************************/
-/*                           OGRCouchDBDriver                           */
-/************************************************************************/
-
-class OGRCouchDBDriver : public OGRSFDriver
-{
-  public:
-                ~OGRCouchDBDriver();
-
-    virtual const char*         GetName();
-    virtual OGRDataSource*      Open( const char *, int );
-    virtual OGRDataSource*      CreateDataSource( const char * pszName,
-                                                  char **papszOptions );
-    virtual int                 TestCapability( const char * );
-};
-
 #endif /* ndef OGR_COUCHDB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
index a7c19e8..b05092d 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcouchdbdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBDataSource class
@@ -28,26 +27,22 @@
  ****************************************************************************/
 
 #include "ogr_couchdb.h"
+#include "ogrgeojsonreader.h"
 #include "swq.h"
 
-CPL_CVSID("$Id: ogrcouchdbdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrcouchdbdatasource.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /************************************************************************/
 /*                        OGRCouchDBDataSource()                        */
 /************************************************************************/
 
-OGRCouchDBDataSource::OGRCouchDBDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-
-    bReadWrite = FALSE;
-
-    bMustCleanPersistent = FALSE;
-}
+OGRCouchDBDataSource::OGRCouchDBDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bReadWrite(false),
+    bMustCleanPersistent(false)
+{}
 
 /************************************************************************/
 /*                       ~OGRCouchDBDataSource()                        */
@@ -60,7 +55,7 @@ OGRCouchDBDataSource::~OGRCouchDBDataSource()
         delete papoLayers[i];
     CPLFree( papoLayers );
 
-    if (bMustCleanPersistent)
+    if( bMustCleanPersistent )
     {
         char** papszOptions = NULL;
         papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("CouchDB:%p", this));
@@ -78,10 +73,12 @@ OGRCouchDBDataSource::~OGRCouchDBDataSource()
 int OGRCouchDBDataSource::TestCapability( const char * pszCap )
 
 {
-    if( bReadWrite && EQUAL(pszCap,ODsCCreateLayer) )
+    if( bReadWrite && EQUAL(pszCap, ODsCCreateLayer) )
         return TRUE;
-    else if( bReadWrite && EQUAL(pszCap,ODsCDeleteLayer) )
+    else if( bReadWrite && EQUAL(pszCap, ODsCDeleteLayer) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return bReadWrite;
     else
         return FALSE;
 }
@@ -156,7 +153,7 @@ OGRLayer* OGRCouchDBDataSource::OpenDatabase(const char* pszLayerName)
         return NULL;
 
     if ( !json_object_is_type(poAnswerObj, json_type_object) ||
-            json_object_object_get(poAnswerObj, "db_name") == NULL )
+            CPL_json_object_object_get(poAnswerObj, "db_name") == NULL )
     {
         IsError(poAnswerObj, "Database opening failed");
 
@@ -166,9 +163,9 @@ OGRLayer* OGRCouchDBDataSource::OpenDatabase(const char* pszLayerName)
 
     OGRCouchDBTableLayer* poLayer = new OGRCouchDBTableLayer(this, osTableName);
 
-    if ( json_object_object_get(poAnswerObj, "update_seq") != NULL )
+    if ( CPL_json_object_object_get(poAnswerObj, "update_seq") != NULL )
     {
-        int nUpdateSeq = json_object_get_int(json_object_object_get(poAnswerObj, "update_seq"));
+        int nUpdateSeq = json_object_get_int(CPL_json_object_object_get(poAnswerObj, "update_seq"));
         poLayer->SetUpdateSeq(nUpdateSeq);
     }
 
@@ -206,29 +203,28 @@ OGRLayer* OGRCouchDBDataSource::OpenView()
 int OGRCouchDBDataSource::Open( const char * pszFilename, int bUpdateIn)
 
 {
-    int bHTTP = FALSE;
-    if (STARTS_WITH(pszFilename, "http://") ||
-        STARTS_WITH(pszFilename, "https://"))
-        bHTTP = TRUE;
-    else if (!STARTS_WITH_CI(pszFilename, "CouchDB:"))
+    bool bHTTP =
+        STARTS_WITH(pszFilename, "http://") ||
+        STARTS_WITH(pszFilename, "https://");
+
+    if( !bHTTP && !STARTS_WITH_CI(pszFilename, "CouchDB:"))
         return FALSE;
 
-    bReadWrite = bUpdateIn;
+    bReadWrite = CPL_TO_BOOL(bUpdateIn);
 
     pszName = CPLStrdup( pszFilename );
 
-    if (bHTTP)
+    if( bHTTP )
         osURL = pszFilename;
     else
         osURL = pszFilename + 8;
-    if (osURL.size() > 0 && osURL[osURL.size() - 1] == '/')
+    if (!osURL.empty() && osURL.back() == '/')
         osURL.resize(osURL.size() - 1);
 
     const char* pszUserPwd = CPLGetConfigOption("COUCHDB_USERPWD", NULL);
     if (pszUserPwd)
         osUserPwd = pszUserPwd;
 
-
     if ((strstr(osURL, "/_design/") && strstr(osURL, "/_view/")) ||
         strstr(osURL, "/_all_docs"))
     {
@@ -264,8 +260,8 @@ int OGRCouchDBDataSource::Open( const char * pszFilename, int bUpdateIn)
     {
         if ( json_object_is_type(poAnswerObj, json_type_object) )
         {
-            json_object* poError = json_object_object_get(poAnswerObj, "error");
-            json_object* poReason = json_object_object_get(poAnswerObj, "reason");
+            json_object* poError = CPL_json_object_object_get(poAnswerObj, "error");
+            json_object* poReason = CPL_json_object_object_get(poAnswerObj, "reason");
 
             const char* pszError = json_object_get_string(poError);
             const char* pszReason = json_object_get_string(poReason);
@@ -311,7 +307,6 @@ int OGRCouchDBDataSource::Open( const char * pszFilename, int bUpdateIn)
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                          ICreateLayer()                              */
 /************************************************************************/
@@ -321,7 +316,7 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszNameIn,
                                            OGRwkbGeometryType eGType,
                                            char ** papszOptions )
 {
-    if (!bReadWrite)
+    if( !bReadWrite )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in read-only mode");
         return NULL;
@@ -331,9 +326,7 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszNameIn,
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
-    int iLayer;
-
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszNameIn,papoLayers[iLayer]->GetName()) )
         {
@@ -370,7 +363,7 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszNameIn,
     if (poAnswerObj == NULL)
         return NULL;
 
-    if (!IsOK(poAnswerObj, "Layer creation failed"))
+    if( !IsOK(poAnswerObj, "Layer creation failed") )
     {
         json_object_put(poAnswerObj);
         return NULL;
@@ -392,13 +385,12 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszNameIn,
 
         poAnswerObj = PUT(osURI, osContent);
 
-        if (IsOK(poAnswerObj, "Spatial index creation failed"))
+        if( IsOK(poAnswerObj, "Spatial index creation failed") )
             nUpdateSeq ++;
 
         json_object_put(poAnswerObj);
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Create validation function                                      */
 /* -------------------------------------------------------------------- */
@@ -423,7 +415,7 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszNameIn,
         osValidation += "\"}";
     }
 
-    if (osValidation.size())
+    if (!osValidation.empty() )
     {
         osURI = "/";
         osURI += osEscapedName;
@@ -431,19 +423,21 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszNameIn,
 
         poAnswerObj = PUT(osURI, osValidation);
 
-        if (IsOK(poAnswerObj, "Validation function creation failed"))
+        if( IsOK(poAnswerObj, "Validation function creation failed") )
             nUpdateSeq ++;
 
         json_object_put(poAnswerObj);
     }
 
-    int bGeoJSONDocument = CPLTestBool(CSLFetchNameValueDef(papszOptions, "GEOJSON", "TRUE"));
+    const bool bGeoJSONDocument =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions, "GEOJSON", "TRUE"));
     int nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
 
     OGRCouchDBTableLayer* poLayer = new OGRCouchDBTableLayer(this, pszNameIn);
     if (nCoordPrecision != -1)
         poLayer->SetCoordinatePrecision(nCoordPrecision);
-    poLayer->SetInfoAfterCreation(eGType, poSpatialRef, nUpdateSeq, bGeoJSONDocument);
+    poLayer->SetInfoAfterCreation(eGType, poSpatialRef,
+                                  nUpdateSeq, bGeoJSONDocument);
     papoLayers = (OGRLayer**) CPLRealloc(papoLayers, (nLayers + 1) * sizeof(OGRLayer*));
     papoLayers[nLayers ++] = poLayer;
     return poLayer;
@@ -456,12 +450,11 @@ OGRLayer   *OGRCouchDBDataSource::ICreateLayer( const char *pszNameIn,
 void OGRCouchDBDataSource::DeleteLayer( const char *pszLayerName )
 
 {
-    int iLayer;
-
 /* -------------------------------------------------------------------- */
 /*      Try to find layer.                                              */
 /* -------------------------------------------------------------------- */
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    int iLayer = 0;  // Used after for.
+    for( ; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetName()) )
             break;
@@ -484,7 +477,7 @@ void OGRCouchDBDataSource::DeleteLayer( const char *pszLayerName )
 
 OGRErr OGRCouchDBDataSource::DeleteLayer(int iLayer)
 {
-    if (!bReadWrite)
+    if( !bReadWrite )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in read-only mode");
@@ -528,7 +521,7 @@ OGRErr OGRCouchDBDataSource::DeleteLayer(int iLayer)
     if (poAnswerObj == NULL)
         return OGRERR_FAILURE;
 
-    if (!IsOK(poAnswerObj, "Layer deletion failed"))
+    if( !IsOK(poAnswerObj, "Layer deletion failed") )
     {
         json_object_put(poAnswerObj);
         return OGRERR_FAILURE;
@@ -639,7 +632,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
             return NULL;
         OGRCouchDBTableLayer* poTableLayer = (OGRCouchDBTableLayer*)poLayer;
 
-        while(*pszIter && *pszIter == ' ')
+        while( *pszIter == ' ' )
             pszIter ++;
         if (!STARTS_WITH_CI(pszIter, "WHERE "))
         {
@@ -676,7 +669,6 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQL( const char *pszSQLCommand,
             return NULL;
         }
 
-
         return NULL;
     }
 
@@ -703,7 +695,7 @@ class PointerAutoFree
 {
         void * m_p;
     public:
-        PointerAutoFree(void* p) { m_p = p; }
+        explicit PointerAutoFree(void* p) { m_p = p; }
         ~PointerAutoFree() { CPLFree(m_p); }
 };
 
@@ -712,9 +704,13 @@ class OGRCouchDBOneLineLayer : public OGRLayer
     public:
         OGRFeature* poFeature;
         OGRFeatureDefn* poFeatureDefn;
-        int bEnd;
+        bool bEnd;
 
-        OGRCouchDBOneLineLayer() { poFeature = NULL; poFeatureDefn = NULL; bEnd = FALSE; }
+        OGRCouchDBOneLineLayer() :
+            poFeature(NULL),
+            poFeatureDefn(NULL),
+            bEnd(false)
+        {}
         ~OGRCouchDBOneLineLayer()
         {
             delete poFeature;
@@ -722,15 +718,15 @@ class OGRCouchDBOneLineLayer : public OGRLayer
                 poFeatureDefn->Release();
         }
 
-        virtual void        ResetReading() { bEnd = FALSE;}
-        virtual OGRFeature *GetNextFeature()
+        virtual void        ResetReading() override { bEnd = false;}
+        virtual OGRFeature *GetNextFeature() override
         {
-            if (bEnd) return NULL;
-            bEnd = TRUE;
+            if( bEnd ) return NULL;
+            bEnd = true;
             return poFeature->Clone();
         }
-        virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
-        virtual int         TestCapability( const char * ) { return FALSE; }
+        virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
+        virtual int         TestCapability( const char * ) override { return FALSE; }
 };
 
 OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
@@ -771,21 +767,21 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
     sFieldList.table_defs = sSelectInfo.table_defs;
 
     sFieldList.count = 0;
-    sFieldList.names = (char **) CPLMalloc( sizeof(char *) * nFieldCount );
-    sFieldList.types = (swq_field_type *)
-        CPLMalloc( sizeof(swq_field_type) * nFieldCount );
-    sFieldList.table_ids = (int *)
-        CPLMalloc( sizeof(int) * nFieldCount );
-    sFieldList.ids = (int *)
-        CPLMalloc( sizeof(int) * nFieldCount );
+    sFieldList.names = static_cast<char **>(
+        CPLMalloc( sizeof(char *) * nFieldCount ));
+    sFieldList.types = static_cast<swq_field_type *>(
+        CPLMalloc( sizeof(swq_field_type) * nFieldCount ));
+    sFieldList.table_ids = static_cast<int *>(
+        CPLMalloc( sizeof(int) * nFieldCount ));
+    sFieldList.ids = static_cast<int *>(
+        CPLMalloc( sizeof(int) * nFieldCount ));
 
     PointerAutoFree oHolderNames(sFieldList.names);
     PointerAutoFree oHolderTypes(sFieldList.types);
     PointerAutoFree oHolderTableIds(sFieldList.table_ids);
     PointerAutoFree oHolderIds(sFieldList.ids);
 
-    int iField;
-    for( iField = 0;
+    for( int iField = 0;
          iField < poSrcLayer->GetLayerDefn()->GetFieldCount();
          iField++ )
     {
@@ -806,7 +802,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
     }
 
     CPLString osLastFieldName;
-    for( iField = 0; iField < sSelectInfo.result_columns; iField++ )
+    for( int iField = 0; iField < sSelectInfo.result_columns; iField++ )
     {
         swq_col_def *psColDef = sSelectInfo.column_defs + iField;
         if (psColDef->field_name == NULL)
@@ -814,7 +810,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
 
         if (strcmp(psColDef->field_name, "*") != 0)
         {
-            if (osLastFieldName.size() == 0)
+            if (osLastFieldName.empty())
                 osLastFieldName = psColDef->field_name;
             else if (strcmp(osLastFieldName, psColDef->field_name) != 0)
                 return NULL;
@@ -834,7 +830,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
             return NULL;
     }
 
-    if (osLastFieldName.size() == 0)
+    if (osLastFieldName.empty())
         return NULL;
 
     /* Normalize field name */
@@ -858,7 +854,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
         return NULL;
     }
 
-    for( iField = 0; iField < sSelectInfo.result_columns; iField++ )
+    for( int iField = 0; iField < sSelectInfo.result_columns; iField++ )
     {
         swq_col_def *psColDef = sSelectInfo.column_defs + iField;
         if (psColDef->field_index == -1)
@@ -875,8 +871,9 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
         }
     }
 
-    int bFoundFilter = poSrcLayer->HasFilterOnFieldOrCreateIfNecessary(osLastFieldName);
-    if (!bFoundFilter)
+    const bool bFoundFilter = CPL_TO_BOOL(
+        poSrcLayer->HasFilterOnFieldOrCreateIfNecessary(osLastFieldName));
+    if( !bFoundFilter )
         return NULL;
 
     CPLString osURI = "/";
@@ -889,7 +886,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
     json_object* poRows = NULL;
     if (!(poAnswerObj != NULL &&
           json_object_is_type(poAnswerObj, json_type_object) &&
-          (poRows = json_object_object_get(poAnswerObj, "rows")) != NULL &&
+          (poRows = CPL_json_object_object_get(poAnswerObj, "rows")) != NULL &&
           json_object_is_type(poRows, json_type_array)))
     {
         json_object_put(poAnswerObj);
@@ -910,17 +907,17 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
         return NULL;
     }
 
-    json_object* poValue = json_object_object_get(poRow, "value");
+    json_object* poValue = CPL_json_object_object_get(poRow, "value");
     if (!(poValue != NULL && json_object_is_type(poValue, json_type_object)))
     {
         json_object_put(poAnswerObj);
         return NULL;
     }
 
-    json_object* poSum = json_object_object_get(poValue, "sum");
-    json_object* poCount = json_object_object_get(poValue, "count");
-    json_object* poMin = json_object_object_get(poValue, "min");
-    json_object* poMax = json_object_object_get(poValue, "max");
+    json_object* poSum = CPL_json_object_object_get(poValue, "sum");
+    json_object* poCount = CPL_json_object_object_get(poValue, "count");
+    json_object* poMin = CPL_json_object_object_get(poValue, "min");
+    json_object* poMax = CPL_json_object_object_get(poValue, "max");
     if (poSum != NULL && (json_object_is_type(poSum, json_type_int) ||
                             json_object_is_type(poSum, json_type_double)) &&
         poCount != NULL && (json_object_is_type(poCount, json_type_int) ||
@@ -942,7 +939,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
         OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(poSrcLayer->GetName());
         poFeatureDefn->Reference();
 
-        for( iField = 0; iField < sSelectInfo.result_columns; iField++ )
+        for( int iField = 0; iField < sSelectInfo.result_columns; iField++ )
         {
             swq_col_def *psColDef = sSelectInfo.column_defs + iField;
             OGRFieldDefn oFDefn( "", OFTInteger );
@@ -972,7 +969,7 @@ OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand )
 
         OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
-        for( iField = 0; iField < sSelectInfo.result_columns; iField++ )
+        for( int iField = 0; iField < sSelectInfo.result_columns; iField++ )
         {
             swq_col_def *psColDef = sSelectInfo.column_defs + iField;
             switch(psColDef->col_func)
@@ -1026,19 +1023,18 @@ void OGRCouchDBDataSource::ReleaseResultSet( OGRLayer * poLayer )
 
 char* OGRCouchDBDataSource::GetETag(const char* pszURI)
 {
-
     // make a head request and only return the etag response header
     char* pszEtag = NULL;
     char **papszTokens;
     char** papszOptions = NULL;
 
-    bMustCleanPersistent = TRUE;
+    bMustCleanPersistent = true;
 
     papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=CouchDB:%p", this));
     papszOptions = CSLAddString(papszOptions, "HEADERS=Content-Type: application/json");
     papszOptions = CSLAddString(papszOptions, "NO_BODY=1");
 
-    if (osUserPwd.size())
+    if (!osUserPwd.empty() )
     {
         CPLString osUserPwdOption("USERPWD=");
         osUserPwdOption += osUserPwd;
@@ -1079,7 +1075,7 @@ json_object* OGRCouchDBDataSource::REQUEST(const char* pszVerb,
                                            const char* pszURI,
                                            const char* pszData)
 {
-    bMustCleanPersistent = TRUE;
+    bMustCleanPersistent = true;
 
     char** papszOptions = NULL;
     papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=CouchDB:%p", this));
@@ -1095,7 +1091,7 @@ json_object* OGRCouchDBDataSource::REQUEST(const char* pszVerb,
 
     papszOptions = CSLAddString(papszOptions, "HEADERS=Content-Type: application/json");
 
-    if (osUserPwd.size())
+    if (!osUserPwd.empty() )
     {
         CPLString osUserPwdOption("USERPWD=");
         osUserPwdOption += osUserPwd;
@@ -1188,17 +1184,17 @@ json_object* OGRCouchDBDataSource::DELETE(const char* pszURI)
 /*                            IsError()                                 */
 /************************************************************************/
 
-int OGRCouchDBDataSource::IsError(json_object* poAnswerObj,
+bool OGRCouchDBDataSource::IsError(json_object* poAnswerObj,
                                   const char* pszErrorMsg)
 {
     if ( poAnswerObj == NULL ||
         !json_object_is_type(poAnswerObj, json_type_object) )
     {
-        return FALSE;
+        return false;
     }
 
-    json_object* poError = json_object_object_get(poAnswerObj, "error");
-    json_object* poReason = json_object_object_get(poAnswerObj, "reason");
+    json_object* poError = CPL_json_object_object_get(poAnswerObj, "error");
+    json_object* poReason = CPL_json_object_object_get(poAnswerObj, "reason");
 
     const char* pszError = json_object_get_string(poError);
     const char* pszReason = json_object_get_string(poReason);
@@ -1210,18 +1206,18 @@ int OGRCouchDBDataSource::IsError(json_object* poAnswerObj,
                  pszError,
                  pszReason ? pszReason : "");
 
-        return TRUE;
+        return true;
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                              IsOK()                                  */
 /************************************************************************/
 
-int OGRCouchDBDataSource::IsOK(json_object* poAnswerObj,
-                               const char* pszErrorMsg)
+bool OGRCouchDBDataSource::IsOK(json_object* poAnswerObj,
+                                const char* pszErrorMsg)
 {
     if ( poAnswerObj == NULL ||
         !json_object_is_type(poAnswerObj, json_type_object) )
@@ -1229,15 +1225,15 @@ int OGRCouchDBDataSource::IsOK(json_object* poAnswerObj,
         CPLError(CE_Failure, CPLE_AppDefined, "%s",
                  pszErrorMsg);
 
-        return FALSE;
+        return false;
     }
 
-    json_object* poOK = json_object_object_get(poAnswerObj, "ok");
+    json_object* poOK = CPL_json_object_object_get(poAnswerObj, "ok");
     if ( !poOK )
     {
         IsError(poAnswerObj, pszErrorMsg);
 
-        return FALSE;
+        return false;
     }
 
     const char* pszOK = json_object_get_string(poOK);
@@ -1245,8 +1241,8 @@ int OGRCouchDBDataSource::IsOK(json_object* poAnswerObj,
     {
         CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrorMsg);
 
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
index 61327d6..607d373 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcouchdbdriver.cpp 31122 2015-10-25 09:28:57Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBDriver.
@@ -31,47 +30,42 @@
 
 // g++ -g -Wall -fPIC -shared -o ogr_CouchDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/couchdb ogr/ogrsf_frmts/couchdb/*.c* -L. -lgdal -Iogr/ogrsf_frmts/geojson/jsonc
 
-CPL_CVSID("$Id: ogrcouchdbdriver.cpp 31122 2015-10-25 09:28:57Z rouault $");
+CPL_CVSID("$Id: ogrcouchdbdriver.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 extern "C" void RegisterOGRCouchDB();
 
 /************************************************************************/
-/*                         ~OGRCouchDBDriver()                          */
+/*                   OGRCouchDBDriverIdentify()                         */
 /************************************************************************/
 
-OGRCouchDBDriver::~OGRCouchDBDriver()
+static int OGRCouchDBDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
-}
-
-/************************************************************************/
-/*                              GetName()                               */
-/************************************************************************/
-
-const char *OGRCouchDBDriver::GetName()
+    if (STARTS_WITH(poOpenInfo->pszFilename, "http://") ||
+        STARTS_WITH(poOpenInfo->pszFilename, "https://"))
+    {
+        return -1;
+    }
+    else if (STARTS_WITH_CI(poOpenInfo->pszFilename, "CouchDB:"))
+        return 1;
+    else
+        return 0;
 
-{
-    return "CouchDB";
 }
 
 /************************************************************************/
-/*                                Open()                                */
+/*                  OGRCouchDBDriverOpen()                              */
 /************************************************************************/
 
-OGRDataSource *OGRCouchDBDriver::Open( const char * pszFilename, int bUpdate )
+static GDALDataset* OGRCouchDBDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    if (STARTS_WITH(pszFilename, "http://") ||
-        STARTS_WITH(pszFilename, "https://"))
-    {
-        /* ok */
-    }
-    else if (!STARTS_WITH_CI(pszFilename, "CouchDB:"))
+    if( OGRCouchDBDriverIdentify(poOpenInfo) == 0 )
         return NULL;
 
     OGRCouchDBDataSource   *poDS = new OGRCouchDBDataSource();
 
-    if( !poDS->Open( pszFilename, bUpdate ) )
+    if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update ) )
     {
         delete poDS;
         poDS = NULL;
@@ -80,13 +74,16 @@ OGRDataSource *OGRCouchDBDriver::Open( const char * pszFilename, int bUpdate )
     return poDS;
 }
 
-
 /************************************************************************/
 /*                          CreateDataSource()                          */
 /************************************************************************/
 
-OGRDataSource *OGRCouchDBDriver::CreateDataSource( const char * pszName,
-                                                   CPL_UNUSED char **papszOptions )
+static GDALDataset* OGRCouchDBDriverCreate( const char * pszName,
+                                            int /* nXSize */,
+                                            int /* nYSize */,
+                                            int /* nBands */,
+                                            GDALDataType /* eDT */,
+                                            char ** /* papszOptions */ )
 {
     OGRCouchDBDataSource   *poDS = new OGRCouchDBDataSource();
 
@@ -100,26 +97,40 @@ OGRDataSource *OGRCouchDBDriver::CreateDataSource( const char * pszName,
 }
 
 /************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRCouchDBDriver::TestCapability( const char * pszCap )
-
-{
-    if (EQUAL(pszCap, ODrCCreateDataSource))
-        return TRUE;
-
-    return FALSE;
-}
-
-/************************************************************************/
 /*                         RegisterOGRCouchDB()                         */
 /************************************************************************/
 
 void RegisterOGRCouchDB()
 
 {
-    OGRSFDriver* poDriver = new OGRCouchDBDriver;
+    if( GDALGetDriverByName( "CouchDB" ) != NULL )
+      return;
+
+    GDALDriver  *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "CouchDB" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "CouchDB / GeoCouch" );
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_couchdb.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "CouchDB:" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>");
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    "<LayerCreationOptionList>"
+    "  <Option name='UPDATE_PERMISSIONS' type='string' description='Update permissions for the new layer.'/>"
+    "  <Option name='GEOJSON ' type='boolean' description='Whether to write documents as GeoJSON documents.' default='YES'/>"
+    "  <Option name='COORDINATE_PRECISION' type='int' description='Maximum number of figures after decimal separator to write in coordinates.' default='15'/>"
+    "</LayerCreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time IntegerList Integer64List RealList "
+                               "StringList Binary" );
+
+    poDriver->pfnIdentify = OGRCouchDBDriverIdentify;
+    poDriver->pfnOpen = OGRCouchDBDriverOpen;
+    poDriver->pfnCreate = OGRCouchDBDriverCreate;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
index 500a01f..c7d6be8 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdblayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcouchdblayer.cpp 32247 2015-12-19 07:05:52Z goatbar $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBLayer class.
@@ -31,7 +30,7 @@
 #include "ogrgeojsonreader.h"
 #include "ogrgeojsonutils.h"
 
-CPL_CVSID("$Id: ogrcouchdblayer.cpp 32247 2015-12-19 07:05:52Z goatbar $");
+CPL_CVSID("$Id: ogrcouchdblayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                            OGRCouchDBLayer()                             */
@@ -43,9 +42,9 @@ OGRCouchDBLayer::OGRCouchDBLayer(OGRCouchDBDataSource* poDSIn) :
     poSRS(NULL),
     nNextInSeq(0),
     nOffset(0),
-    bEOF(FALSE),
+    bEOF(false),
     poFeatures(NULL),
-    bGeoJSONDocument(TRUE)
+    bGeoJSONDocument(true)
 {}
 
 /************************************************************************/
@@ -73,7 +72,7 @@ void OGRCouchDBLayer::ResetReading()
 {
     nNextInSeq = 0;
     nOffset = 0;
-    bEOF = FALSE;
+    bEOF = false;
 }
 
 /************************************************************************/
@@ -101,11 +100,11 @@ OGRFeature *OGRCouchDBLayer::GetNextFeature()
         if (nNextInSeq < nOffset ||
             nNextInSeq >= nOffset + static_cast<int>(aoFeatures.size()))
         {
-            if (bEOF)
+            if( bEOF )
                 return NULL;
 
             nOffset += static_cast<int>(aoFeatures.size());
-            if (!FetchNextRows())
+            if( !FetchNextRows() )
                 return NULL;
         }
 
@@ -152,7 +151,7 @@ OGRErr OGRCouchDBLayer::SetNextByIndex( GIntBig nIndex )
 {
     if (nIndex < 0 || nIndex >= INT_MAX )
         return OGRERR_FAILURE;
-    bEOF = FALSE;
+    bEOF = false;
     nNextInSeq = (int)nIndex;
     return OGRERR_NONE;
 }
@@ -180,7 +179,7 @@ OGRFeature* OGRCouchDBLayer::TranslateFeature( json_object* poObj )
     OGRFeature* poFeature = NULL;
     poFeature = new OGRFeature( GetLayerDefn() );
 
-    json_object* poId = json_object_object_get(poObj, "_id");
+    json_object* poId = CPL_json_object_object_get(poObj, "_id");
     const char* pszId = json_object_get_string(poId);
     if (pszId)
     {
@@ -192,7 +191,7 @@ OGRFeature* OGRCouchDBLayer::TranslateFeature( json_object* poObj )
             poFeature->SetFID(nFID);
     }
 
-    json_object* poRev = json_object_object_get(poObj, "_rev");
+    json_object* poRev = CPL_json_object_object_get(poObj, "_rev");
     const char* pszRev = json_object_get_string(poRev);
     if (pszRev)
         poFeature->SetField(COUCHDB_REV_FIELD, pszRev);
@@ -207,7 +206,7 @@ OGRFeature* OGRCouchDBLayer::TranslateFeature( json_object* poObj )
     it.entry = NULL;
     if( bGeoJSONDocument )
     {
-        json_object* poObjProps = json_object_object_get( poObj, "properties" );
+        json_object* poObjProps = CPL_json_object_object_get( poObj, "properties" );
         if ( NULL != poObjProps &&
              json_object_get_type(poObjProps ) == json_type_object )
         {
@@ -234,7 +233,7 @@ OGRFeature* OGRCouchDBLayer::TranslateFeature( json_object* poObj )
 /*      Translate geometry sub-object of GeoJSON Feature.               */
 /* -------------------------------------------------------------------- */
 
-    json_object* poObjGeom = json_object_object_get( poObj, "geometry" );
+    json_object* poObjGeom = CPL_json_object_object_get( poObj, "geometry" );
     if (poObjGeom != NULL)
     {
         OGRGeometry* poGeometry = OGRGeoJSONReadGeometry( poObjGeom );
@@ -265,7 +264,11 @@ void OGRCouchDBLayer::ParseFieldValue(OGRFeature* poFeature,
                     "Ignoring its value",
                     pszKey);
     }
-    else if (poValue != NULL)
+    else if (poValue == NULL)
+    {
+        poFeature->SetFieldNull( nField );
+    }
+    else
     {
         OGRFieldDefn* poFieldDefn = poFeature->GetFieldDefnRef(nField);
         CPLAssert(poFieldDefn != NULL);
@@ -284,8 +287,9 @@ void OGRCouchDBLayer::ParseFieldValue(OGRFeature* poFeature,
             if ( json_object_get_type(poValue) == json_type_array )
             {
                 int nLength = json_object_array_length(poValue);
-                int* panVal = (int*)CPLMalloc(sizeof(int) * nLength);
-                for(int i=0;i<nLength;i++)
+                int* panVal = static_cast<int *>(
+                    CPLMalloc(sizeof(int) * nLength));
+                for( int i = 0; i < nLength; i++ )
                 {
                     json_object* poRow = json_object_array_get_idx(poValue, i);
                     panVal[i] = json_object_get_int(poRow);
@@ -298,9 +302,10 @@ void OGRCouchDBLayer::ParseFieldValue(OGRFeature* poFeature,
         {
             if ( json_object_get_type(poValue) == json_type_array )
             {
-                int nLength = json_object_array_length(poValue);
-                double* padfVal = (double*)CPLMalloc(sizeof(double) * nLength);
-                for(int i=0;i<nLength;i++)
+                const int nLength = json_object_array_length(poValue);
+                double* padfVal = static_cast<double *>(
+                    CPLMalloc(sizeof(double) * nLength));
+                for( int i = 0; i < nLength; i++ )
                 {
                     json_object* poRow = json_object_array_get_idx(poValue, i);
                     padfVal[i] = json_object_get_double(poRow);
@@ -314,9 +319,10 @@ void OGRCouchDBLayer::ParseFieldValue(OGRFeature* poFeature,
             if ( json_object_get_type(poValue) == json_type_array )
             {
                 int nLength = json_object_array_length(poValue);
-                char** papszVal = (char**)CPLMalloc(sizeof(char*) * (nLength+1));
-                int i;
-                for(i=0;i<nLength;i++)
+                char** papszVal = static_cast<char **>(
+                    CPLMalloc(sizeof(char*) * (nLength+1)));
+                int i = 0;  // Used after for.
+                for( ; i < nLength; i++ )
                 {
                     json_object* poRow = json_object_array_get_idx(poValue, i);
                     const char* pszVal = json_object_get_string(poRow);
@@ -336,7 +342,6 @@ void OGRCouchDBLayer::ParseFieldValue(OGRFeature* poFeature,
     }
 }
 
-
 /************************************************************************/
 /*                      BuildFeatureDefnFromDoc()                       */
 /************************************************************************/
@@ -346,7 +351,7 @@ void OGRCouchDBLayer::BuildFeatureDefnFromDoc(json_object* poDoc)
 /* -------------------------------------------------------------------- */
 /*      Read collection of properties.                                  */
 /* -------------------------------------------------------------------- */
-    json_object* poObjProps = json_object_object_get( poDoc,
+    json_object* poObjProps = CPL_json_object_object_get( poDoc,
                                                         "properties" );
     json_object_iter it;
     it.key = NULL;
@@ -367,7 +372,7 @@ void OGRCouchDBLayer::BuildFeatureDefnFromDoc(json_object* poDoc)
     }
     else
     {
-        bGeoJSONDocument = FALSE;
+        bGeoJSONDocument = false;
 
         json_object_object_foreachC( poDoc, it )
         {
@@ -384,38 +389,37 @@ void OGRCouchDBLayer::BuildFeatureDefnFromDoc(json_object* poDoc)
         }
     }
 
-    if( json_object_object_get( poDoc, "geometry" ) == NULL )
+    if( CPL_json_object_object_get( poDoc, "geometry" ) == NULL )
     {
         poFeatureDefn->SetGeomType(wkbNone);
     }
 }
 
-
 /************************************************************************/
 /*                      BuildFeatureDefnFromRows()                      */
 /************************************************************************/
 
-int OGRCouchDBLayer::BuildFeatureDefnFromRows(json_object* poAnswerObj)
+bool OGRCouchDBLayer::BuildFeatureDefnFromRows( json_object* poAnswerObj )
 {
     if ( !json_object_is_type(poAnswerObj, json_type_object) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                     "Layer definition creation failed");
-        return FALSE;
+        return false;
     }
 
     if (poDS->IsError(poAnswerObj, "Layer definition creation failed"))
     {
-        return FALSE;
+        return false;
     }
 
-    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    json_object* poRows = CPL_json_object_object_get(poAnswerObj, "rows");
     if (poRows == NULL ||
         !json_object_is_type(poRows, json_type_array))
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                     "Layer definition creation failed");
-        return FALSE;
+        return false;
     }
 
     int nRows = json_object_array_length(poRows);
@@ -427,7 +431,7 @@ int OGRCouchDBLayer::BuildFeatureDefnFromRows(json_object* poAnswerObj)
         if (poTmpRow != NULL &&
             json_object_is_type(poTmpRow, json_type_object))
         {
-            json_object* poId = json_object_object_get(poTmpRow, "id");
+            json_object* poId = CPL_json_object_object_get(poTmpRow, "id");
             const char* pszId = json_object_get_string(poId);
             if (pszId != NULL && pszId[0] != '_')
             {
@@ -439,56 +443,56 @@ int OGRCouchDBLayer::BuildFeatureDefnFromRows(json_object* poAnswerObj)
 
     if ( poRow == NULL )
     {
-        return FALSE;
+        return false;
     }
 
-    json_object* poDoc = json_object_object_get(poRow, "doc");
+    json_object* poDoc = CPL_json_object_object_get(poRow, "doc");
     if ( poDoc == NULL )
-        poDoc = json_object_object_get(poRow, "value");
+        poDoc = CPL_json_object_object_get(poRow, "value");
     if ( poDoc == NULL ||
             !json_object_is_type(poDoc, json_type_object) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                     "Layer definition creation failed");
-        return FALSE;
+        return false;
     }
 
     BuildFeatureDefnFromDoc(poDoc);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                   FetchNextRowsAnalyseDocs()                         */
 /************************************************************************/
 
-int OGRCouchDBLayer::FetchNextRowsAnalyseDocs(json_object* poAnswerObj)
+bool OGRCouchDBLayer::FetchNextRowsAnalyseDocs( json_object* poAnswerObj )
 {
     if (poAnswerObj == NULL)
-        return FALSE;
+        return false;
 
     if ( !json_object_is_type(poAnswerObj, json_type_object) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "FetchNextRowsAnalyseDocs() failed");
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
     if (poDS->IsError(poAnswerObj, "FetchNextRowsAnalyseDocs() failed"))
     {
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
-    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    json_object* poRows = CPL_json_object_object_get(poAnswerObj, "rows");
     if (poRows == NULL ||
         !json_object_is_type(poRows, json_type_array))
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "FetchNextRowsAnalyseDocs() failed");
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
     int nRows = json_object_array_length(poRows);
@@ -501,22 +505,22 @@ int OGRCouchDBLayer::FetchNextRowsAnalyseDocs(json_object* poAnswerObj)
             CPLError(CE_Failure, CPLE_AppDefined,
                      "FetchNextRowsAnalyseDocs() failed");
             json_object_put(poAnswerObj);
-            return FALSE;
+            return false;
         }
 
-        json_object* poDoc = json_object_object_get(poRow, "doc");
+        json_object* poDoc = CPL_json_object_object_get(poRow, "doc");
         if ( poDoc == NULL )
-            poDoc = json_object_object_get(poRow, "value");
+            poDoc = CPL_json_object_object_get(poRow, "value");
         if ( poDoc == NULL ||
              !json_object_is_type(poDoc, json_type_object) )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "FetchNextRowsAnalyseDocs() failed");
             json_object_put(poAnswerObj);
-            return FALSE;
+            return false;
         }
 
-        json_object* poId = json_object_object_get(poDoc, "_id");
+        json_object* poId = CPL_json_object_object_get(poDoc, "_id");
         const char* pszId = json_object_get_string(poId);
         if (pszId != NULL && !STARTS_WITH(pszId, "_design/"))
         {
@@ -528,11 +532,11 @@ int OGRCouchDBLayer::FetchNextRowsAnalyseDocs(json_object* poAnswerObj)
 
     poFeatures = poAnswerObj;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
-/*              	     GetSpatialRef()                            */
+/*                           GetSpatialRef()                            */
 /************************************************************************/
 
 OGRSpatialReference* OGRCouchDBLayer::GetSpatialRef()
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
index 01b6357..c6e7295 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbrowslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcouchdbrowslayer.cpp 32370 2015-12-20 19:40:13Z rouault $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBRowsLayer class.
@@ -29,7 +28,7 @@
 
 #include "ogr_couchdb.h"
 
-CPL_CVSID("$Id: ogrcouchdbrowslayer.cpp 32370 2015-12-20 19:40:13Z rouault $");
+CPL_CVSID("$Id: ogrcouchdbrowslayer.cpp 35298 2016-09-02 23:00:49Z goatbar $");
 
 /************************************************************************/
 /*                         OGRCouchDBRowsLayer()                        */
@@ -37,7 +36,7 @@ CPL_CVSID("$Id: ogrcouchdbrowslayer.cpp 32370 2015-12-20 19:40:13Z rouault $");
 
 OGRCouchDBRowsLayer::OGRCouchDBRowsLayer(OGRCouchDBDataSource* poDSIn) :
     OGRCouchDBLayer(poDSIn),
-    bAllInOne(FALSE)
+    bAllInOne(false)
 {
     poFeatureDefn = new OGRFeatureDefn( "rows" );
     poFeatureDefn->Reference();
@@ -66,7 +65,7 @@ void OGRCouchDBRowsLayer::ResetReading()
 {
     OGRCouchDBLayer::ResetReading();
 
-    if (!bAllInOne)
+    if( !bAllInOne )
     {
         json_object_put(poFeatures);
         poFeatures = NULL;
@@ -78,16 +77,16 @@ void OGRCouchDBRowsLayer::ResetReading()
 /*                           FetchNextRows()                            */
 /************************************************************************/
 
-int OGRCouchDBRowsLayer::FetchNextRows()
+bool OGRCouchDBRowsLayer::FetchNextRows()
 {
-    if (bAllInOne)
-        return FALSE;
+    if( bAllInOne )
+        return false;
 
     json_object_put(poFeatures);
     poFeatures = NULL;
     aoFeatures.resize(0);
 
-    int bHasEsperluet = (strstr(poDS->GetURL(), "?") != NULL);
+    bool bHasEsperluet = strstr(poDS->GetURL(), "?") != NULL;
 
     CPLString osURI;
     if (strstr(poDS->GetURL(), "limit=") == NULL &&
@@ -95,7 +94,7 @@ int OGRCouchDBRowsLayer::FetchNextRows()
     {
         if (!bHasEsperluet)
         {
-            bHasEsperluet = TRUE;
+            bHasEsperluet = true;
             osURI += "?";
         }
 
@@ -104,9 +103,9 @@ int OGRCouchDBRowsLayer::FetchNextRows()
     }
     if (strstr(poDS->GetURL(), "reduce=") == NULL)
     {
-        if (!bHasEsperluet)
+        if( !bHasEsperluet )
         {
-            /*bHasEsperluet = TRUE;*/
+            // bHasEsperluet = true;
             osURI += "?";
         }
 
@@ -120,18 +119,18 @@ int OGRCouchDBRowsLayer::FetchNextRows()
 /*                         BuildFeatureDefn()                           */
 /************************************************************************/
 
-int OGRCouchDBRowsLayer::BuildFeatureDefn()
+bool OGRCouchDBRowsLayer::BuildFeatureDefn()
 {
-    int bRet = FetchNextRows();
+    bool bRet = FetchNextRows();
     if (!bRet)
-        return FALSE;
+        return false;
 
     bRet = BuildFeatureDefnFromRows(poFeatures);
     if (!bRet)
-        return FALSE;
+        return false;
 
-    if ( bEOF )
-        bAllInOne = TRUE;
+    if( bEOF )
+        bAllInOne = true;
 
-    return TRUE;
+    return true;
 }
diff --git a/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp b/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
index d3814e0..2ed08f1 100644
--- a/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
+++ b/ogr/ogrsf_frmts/couchdb/ogrcouchdbtablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcouchdbtablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CouchDB Translator
  * Purpose:  Implements OGRCouchDBTableLayer class.
@@ -34,7 +33,7 @@
 
 #include <algorithm>
 
-CPL_CVSID("$Id: ogrcouchdbtablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrcouchdbtablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                       OGRCouchDBTableLayer()                         */
@@ -44,20 +43,20 @@ OGRCouchDBTableLayer::OGRCouchDBTableLayer( OGRCouchDBDataSource* poDSIn,
                                             const char* pszName) :
     OGRCouchDBLayer(poDSIn),
     nNextFIDForCreate(-1),
-    bInTransaction(FALSE),
+    bInTransaction(false),
     bHasOGRSpatial(-1),
-    bHasGeocouchUtilsMinimalSpatialView(FALSE),
-    bServerSideAttributeFilteringWorks(TRUE),
-    bHasInstalledAttributeFilter(FALSE),
+    bHasGeocouchUtilsMinimalSpatialView(false),
+    bServerSideAttributeFilteringWorks(true),
+    bHasInstalledAttributeFilter(false),
     nUpdateSeq(-1),
-    bAlwaysValid(FALSE),
+    bAlwaysValid(false),
     osName(pszName),
-    bMustWriteMetadata(FALSE),
-    bMustRunSpatialFilter(FALSE),
-    bServerSideSpatialFilteringWorks(TRUE),
-    bHasLoadedMetadata(FALSE),
-    bExtentValid(FALSE),
-    bExtentSet(FALSE),
+    bMustWriteMetadata(false),
+    bMustRunSpatialFilter(false),
+    bServerSideSpatialFilteringWorks(true),
+    bHasLoadedMetadata(false),
+    bExtentValid(false),
+    bExtentSet(false),
     dfMinX(0),
     dfMinY(0),
     dfMaxX(0),
@@ -141,19 +140,19 @@ int OGRCouchDBTableLayer::TestCapability( const char * pszCap )
 /*                   RunSpatialFilterQueryIfNecessary()                 */
 /************************************************************************/
 
-int OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
+bool OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
 {
-    if (!bMustRunSpatialFilter)
-        return TRUE;
+    if( !bMustRunSpatialFilter )
+        return true;
 
-    bMustRunSpatialFilter = FALSE;
+    bMustRunSpatialFilter = false;
 
     CPLAssert(nOffset == 0);
 
     aosIdsToFetch.resize(0);
 
     const char* pszSpatialFilter = NULL;
-    if (bHasOGRSpatial < 0 || bHasOGRSpatial == FALSE)
+    if( bHasOGRSpatial < 0 || bHasOGRSpatial == FALSE )
     {
         pszSpatialFilter = CPLGetConfigOption("COUCHDB_SPATIAL_FILTER" , NULL);
         if (pszSpatialFilter)
@@ -169,7 +168,7 @@ int OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
         json_object* poAnswerObj = poDS->GET(osURI);
         bHasOGRSpatial = (poAnswerObj != NULL &&
             json_object_is_type(poAnswerObj, json_type_object) &&
-            json_object_object_get(poAnswerObj, "spatial") != NULL);
+            CPL_json_object_object_get(poAnswerObj, "spatial") != NULL);
         json_object_put(poAnswerObj);
 
         if (!bHasOGRSpatial)
@@ -179,21 +178,25 @@ int OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
             osURI += osEscapedName;
             osURI += "/_design/geo";
 
-            json_object* poSpatialObj;
+            json_object* poSpatialObj = NULL;
             poAnswerObj = poDS->GET(osURI);
-            bHasGeocouchUtilsMinimalSpatialView = (poAnswerObj != NULL &&
+            bHasGeocouchUtilsMinimalSpatialView =
+                poAnswerObj != NULL &&
                 json_object_is_type(poAnswerObj, json_type_object) &&
-                (poSpatialObj = json_object_object_get(poAnswerObj, "spatial")) != NULL &&
+                (poSpatialObj = CPL_json_object_object_get(poAnswerObj,
+                                                       "spatial")) != NULL &&
                 json_object_is_type(poSpatialObj, json_type_object) &&
-                json_object_object_get(poSpatialObj, "minimal") != NULL);
+                CPL_json_object_object_get(poSpatialObj, "minimal") != NULL;
+
             json_object_put(poAnswerObj);
 
-            if (!bHasGeocouchUtilsMinimalSpatialView)
+            if( !bHasGeocouchUtilsMinimalSpatialView )
             {
-                CPLDebug("CouchDB",
-                            "Geocouch not working --> client-side spatial filtering");
-                bServerSideSpatialFilteringWorks = FALSE;
-                return FALSE;
+                CPLDebug(
+                    "CouchDB",
+                    "Geocouch not working --> client-side spatial filtering");
+                bServerSideSpatialFilteringWorks = false;
+                return false;
             }
         }
     }
@@ -203,7 +206,7 @@ int OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
 
     if (bHasOGRSpatial)
         pszSpatialFilter = "_design/ogr_spatial/_spatial/spatial";
-    else if (bHasGeocouchUtilsMinimalSpatialView)
+    else if( bHasGeocouchUtilsMinimalSpatialView )
         pszSpatialFilter = "_design/geo/_spatial/minimal";
 
     CPLString osURI("/");
@@ -220,24 +223,24 @@ int OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
     {
         CPLDebug("CouchDB",
                     "Geocouch not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
-        return FALSE;
+        bServerSideSpatialFilteringWorks = false;
+        return false;
     }
 
     if ( !json_object_is_type(poAnswerObj, json_type_object) )
     {
         CPLDebug("CouchDB",
                     "Geocouch not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
+        bServerSideSpatialFilteringWorks = false;
         CPLError(CE_Failure, CPLE_AppDefined,
                     "FetchNextRowsSpatialFilter() failed");
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
     /* Catch error for a non geocouch database */
-    json_object* poError = json_object_object_get(poAnswerObj, "error");
-    json_object* poReason = json_object_object_get(poAnswerObj, "reason");
+    json_object* poError = CPL_json_object_object_get(poAnswerObj, "error");
+    json_object* poReason = CPL_json_object_object_get(poAnswerObj, "reason");
 
     const char* pszError = json_object_get_string(poError);
     const char* pszReason = json_object_get_string(poReason);
@@ -247,31 +250,31 @@ int OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
     {
         CPLDebug("CouchDB",
                     "Geocouch not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
+        bServerSideSpatialFilteringWorks = false;
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
     if (poDS->IsError(poAnswerObj, "FetchNextRowsSpatialFilter() failed"))
     {
         CPLDebug("CouchDB",
                     "Geocouch not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
+        bServerSideSpatialFilteringWorks = false;
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
-    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    json_object* poRows = CPL_json_object_object_get(poAnswerObj, "rows");
     if (poRows == NULL ||
         !json_object_is_type(poRows, json_type_array))
     {
         CPLDebug("CouchDB",
                     "Geocouch not working --> client-side spatial filtering");
-        bServerSideSpatialFilteringWorks = FALSE;
+        bServerSideSpatialFilteringWorks = false;
         CPLError(CE_Failure, CPLE_AppDefined,
                     "FetchNextRowsSpatialFilter() failed");
         json_object_put(poAnswerObj);
-        return FALSE;
+        return false;
     }
 
     int nRows = json_object_array_length(poRows);
@@ -282,12 +285,12 @@ int OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
             !json_object_is_type(poRow, json_type_object) )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                        "FetchNextRowsSpatialFilter() failed");
+                     "FetchNextRowsSpatialFilter() failed");
             json_object_put(poAnswerObj);
-            return FALSE;
+            return false;
         }
 
-        json_object* poId = json_object_object_get(poRow, "id");
+        json_object* poId = CPL_json_object_object_get(poRow, "id");
         const char* pszId = json_object_get_string(poId);
         if (pszId != NULL)
         {
@@ -299,20 +302,21 @@ int OGRCouchDBTableLayer::RunSpatialFilterQueryIfNecessary()
 
     json_object_put(poAnswerObj);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                   FetchNextRowsSpatialFilter()                       */
 /************************************************************************/
 
-int OGRCouchDBTableLayer::FetchNextRowsSpatialFilter()
+bool OGRCouchDBTableLayer::FetchNextRowsSpatialFilter()
 {
-    if (!RunSpatialFilterQueryIfNecessary())
-        return FALSE;
+    if( !RunSpatialFilterQueryIfNecessary() )
+        return false;
 
     CPLString osContent("{\"keys\":[");
-    int nLimit = MIN(nOffset + GetFeaturesToFetch(), (int)aosIdsToFetch.size());
+    const int nLimit =
+        std::min(nOffset + GetFeaturesToFetch(), (int)aosIdsToFetch.size());
     for(int i=nOffset;i<nLimit;i++)
     {
         if (i > nOffset)
@@ -334,6 +338,7 @@ int OGRCouchDBTableLayer::FetchNextRowsSpatialFilter()
 /*                HasFilterOnFieldOrCreateIfNecessary()                 */
 /************************************************************************/
 
+// TODO(schwehr): What is the return type supposed to be?  Can it be a bool?
 int OGRCouchDBTableLayer::HasFilterOnFieldOrCreateIfNecessary(const char* pszFieldName)
 {
     std::map<CPLString, int>::iterator oIter = oMapFilterFields.find(pszFieldName);
@@ -345,18 +350,18 @@ int OGRCouchDBTableLayer::HasFilterOnFieldOrCreateIfNecessary(const char* pszFie
     osURI += "/_design/ogr_filter_";
     osURI += pszFieldName;
 
-    int bFoundFilter = FALSE;
+    bool bFoundFilter = false;
 
     json_object* poAnswerObj = poDS->GET(osURI);
     if (poAnswerObj &&
         json_object_is_type(poAnswerObj, json_type_object) &&
-        json_object_object_get(poAnswerObj, "views") != NULL)
+        CPL_json_object_object_get(poAnswerObj, "views") != NULL)
     {
-        bFoundFilter = TRUE;
+        bFoundFilter = true;
     }
     json_object_put(poAnswerObj);
 
-    if (!bFoundFilter)
+    if( !bFoundFilter )
     {
         json_object* poDoc = json_object_new_object();
         json_object* poViews = json_object_new_object();
@@ -370,7 +375,7 @@ int OGRCouchDBTableLayer::HasFilterOnFieldOrCreateIfNecessary(const char* pszFie
         int bIsNumeric = poFieldDefn->GetType() == OFTInteger ||
                          poFieldDefn->GetType() == OFTReal;
 
-        if (bGeoJSONDocument)
+        if( bGeoJSONDocument )
         {
             osMap = "function(doc) { if (doc.properties && doc.properties.";
             osMap += pszFieldName;
@@ -431,11 +436,11 @@ int OGRCouchDBTableLayer::HasFilterOnFieldOrCreateIfNecessary(const char* pszFie
 
         json_object_put(poDoc);
 
-        if (poDS->IsOK(poAnswerObj, "Filter creation failed"))
+        if( poDS->IsOK(poAnswerObj, "Filter creation failed") )
         {
-            bFoundFilter = TRUE;
-            if (!bAlwaysValid)
-                bMustWriteMetadata = TRUE;
+            bFoundFilter = true;
+            if( !bAlwaysValid )
+                bMustWriteMetadata = true;
             nUpdateSeq++;
         }
 
@@ -452,17 +457,17 @@ int OGRCouchDBTableLayer::HasFilterOnFieldOrCreateIfNecessary(const char* pszFie
 /************************************************************************/
 
 static const char* OGRCouchDBGetOpStr(int nOperation,
-                                      int& bOutHasStrictComparisons)
+                                      bool &bOutHasStrictComparisons)
 {
-    bOutHasStrictComparisons = FALSE;
+    bOutHasStrictComparisons = false;
 
-    switch(nOperation)
+    switch( nOperation )
     {
         case SWQ_EQ: return "=";
         case SWQ_GE: return ">=";
         case SWQ_LE: return "<=";
-        case SWQ_GT: bOutHasStrictComparisons = TRUE; return ">";
-        case SWQ_LT: bOutHasStrictComparisons = TRUE; return "<";
+        case SWQ_GT: bOutHasStrictComparisons = true; return ">";
+        case SWQ_LT: bOutHasStrictComparisons = true; return "<";
         default:     return "unknown op";
     }
 }
@@ -530,13 +535,13 @@ static const char* OGRCouchDBGetKeyName(int nOperation)
 /*                         BuildAttrQueryURI()                          */
 /************************************************************************/
 
-CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
+CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(bool &bOutHasStrictComparisons)
 {
     CPLString osURI = "";
 
-    bOutHasStrictComparisons = FALSE;
+    bOutHasStrictComparisons = false;
 
-    int bCanHandleFilter = FALSE;
+    bool bCanHandleFilter = false;
 
     swq_expr_node * pNode = (swq_expr_node *) m_poAttrQuery->GetSWQExpr();
     if (pNode->eNodeType == SNT_OPERATION &&
@@ -556,7 +561,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
         if (pNode->nOperation == SWQ_EQ &&
             nIndex == COUCHDB_ID_FIELD && eType == SWQ_STRING)
         {
-            bCanHandleFilter = TRUE;
+            bCanHandleFilter = true;
 
             osURI = "/";
             osURI += osEscapedName;
@@ -566,10 +571,11 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             (eType == SWQ_STRING || eType == SWQ_INTEGER ||
              eType == SWQ_INTEGER64 || eType == SWQ_FLOAT))
         {
-            int bFoundFilter = HasFilterOnFieldOrCreateIfNecessary(pszFieldName);
-            if (bFoundFilter)
+            const bool bFoundFilter = CPL_TO_BOOL(
+                HasFilterOnFieldOrCreateIfNecessary(pszFieldName));
+            if( bFoundFilter )
             {
-                bCanHandleFilter = TRUE;
+                bCanHandleFilter = true;
 
                 osURI = "/";
                 osURI += osEscapedName;
@@ -579,9 +585,10 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             }
         }
 
-        if (bCanHandleFilter)
+        if( bCanHandleFilter )
         {
-            const char* pszOp = OGRCouchDBGetOpStr(pNode->nOperation, bOutHasStrictComparisons);
+            const char* pszOp =
+                OGRCouchDBGetOpStr(pNode->nOperation, bOutHasStrictComparisons);
             CPLString osVal = OGRCouchDBGetValue(eType, pNode->papoSubExpr[1]);
             CPLDebug("CouchDB", "Evaluating %s %s %s", pszFieldName, pszOp, osVal.c_str());
 
@@ -619,7 +626,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
         if (nIndex0 == nIndex1 && eType0 == eType1 &&
             nIndex0 == COUCHDB_ID_FIELD && eType0 == SWQ_STRING)
         {
-            bCanHandleFilter = TRUE;
+            bCanHandleFilter = true;
 
             osURI = "/";
             osURI += osEscapedName;
@@ -630,10 +637,11 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             (eType0 == SWQ_STRING || eType0 == SWQ_INTEGER ||
              eType0 == SWQ_INTEGER64 || eType0 == SWQ_FLOAT))
         {
-            int bFoundFilter = HasFilterOnFieldOrCreateIfNecessary(pszFieldName);
-            if (bFoundFilter)
+            const bool bFoundFilter = CPL_TO_BOOL(
+                HasFilterOnFieldOrCreateIfNecessary(pszFieldName));
+            if( bFoundFilter )
             {
-                bCanHandleFilter = TRUE;
+                bCanHandleFilter = true;
 
                 osURI = "/";
                 osURI += osEscapedName;
@@ -643,7 +651,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             }
         }
 
-        if (bCanHandleFilter)
+        if( bCanHandleFilter )
         {
             swq_field_type eType = eType0;
             CPLString osVal0 = OGRCouchDBGetValue(eType, pNode->papoSubExpr[0]->papoSubExpr[1]);
@@ -652,8 +660,10 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             int nOperation0 = pNode->papoSubExpr[0]->nOperation;
             int nOperation1 = pNode->papoSubExpr[1]->nOperation;
 
-            const char* pszOp0 = OGRCouchDBGetOpStr(nOperation0, bOutHasStrictComparisons);
-            const char* pszOp1 = OGRCouchDBGetOpStr(nOperation1, bOutHasStrictComparisons);
+            const char* pszOp0 =
+                OGRCouchDBGetOpStr(nOperation0, bOutHasStrictComparisons);
+            const char* pszOp1 =
+                OGRCouchDBGetOpStr(nOperation1, bOutHasStrictComparisons);
 
             CPLDebug("CouchDB", "Evaluating %s %s %s AND %s %s %s",
                             pszFieldName, pszOp0, osVal0.c_str(),
@@ -681,7 +691,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
 
         if (nIndex == COUCHDB_ID_FIELD && eType == SWQ_STRING)
         {
-            bCanHandleFilter = TRUE;
+            bCanHandleFilter = true;
 
             osURI = "/";
             osURI += osEscapedName;
@@ -691,10 +701,11 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             (eType == SWQ_STRING || eType == SWQ_INTEGER ||
              eType == SWQ_INTEGER64 || eType == SWQ_FLOAT))
         {
-            int bFoundFilter = HasFilterOnFieldOrCreateIfNecessary(pszFieldName);
-            if (bFoundFilter)
+            const bool bFoundFilter = CPL_TO_BOOL(
+                HasFilterOnFieldOrCreateIfNecessary(pszFieldName));
+            if( bFoundFilter )
             {
-                bCanHandleFilter = TRUE;
+                bCanHandleFilter = true;
 
                 osURI = "/";
                 osURI += osEscapedName;
@@ -704,7 +715,7 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
             }
         }
 
-        if (bCanHandleFilter)
+        if( bCanHandleFilter )
         {
             CPLString osVal0 = OGRCouchDBGetValue(eType, pNode->papoSubExpr[1]);
             CPLString osVal1 = OGRCouchDBGetValue(eType, pNode->papoSubExpr[2]);
@@ -729,23 +740,23 @@ CPLString OGRCouchDBTableLayer::BuildAttrQueryURI(int& bOutHasStrictComparisons)
 /*                   FetchNextRowsAttributeFilter()                     */
 /************************************************************************/
 
-int OGRCouchDBTableLayer::FetchNextRowsAttributeFilter()
+bool OGRCouchDBTableLayer::FetchNextRowsAttributeFilter()
 {
-    if (bHasInstalledAttributeFilter)
+    if( bHasInstalledAttributeFilter )
     {
-        bHasInstalledAttributeFilter = FALSE;
+        bHasInstalledAttributeFilter = false;
 
         CPLAssert(nOffset == 0);
 
-        int bOutHasStrictComparisons = FALSE;
+        bool bOutHasStrictComparisons = false;
         osURIAttributeFilter = BuildAttrQueryURI(bOutHasStrictComparisons);
 
-        if (osURIAttributeFilter.size() == 0)
+        if (osURIAttributeFilter.empty())
         {
             CPLDebug("CouchDB",
                      "Turning to client-side attribute filtering");
-            bServerSideAttributeFilteringWorks = FALSE;
-            return FALSE;
+            bServerSideAttributeFilteringWorks = false;
+            return false;
         }
     }
 
@@ -762,7 +773,7 @@ int OGRCouchDBTableLayer::FetchNextRowsAttributeFilter()
 /*                           FetchNextRows()                            */
 /************************************************************************/
 
-int OGRCouchDBTableLayer::FetchNextRows()
+bool OGRCouchDBTableLayer::FetchNextRows()
 {
     json_object_put(poFeatures);
     poFeatures = NULL;
@@ -770,15 +781,15 @@ int OGRCouchDBTableLayer::FetchNextRows()
 
     if( m_poFilterGeom != NULL && bServerSideSpatialFilteringWorks )
     {
-        int bRet = FetchNextRowsSpatialFilter();
-        if (bRet || bServerSideSpatialFilteringWorks)
+        const bool bRet = FetchNextRowsSpatialFilter();
+        if( bRet || bServerSideSpatialFilteringWorks )
             return bRet;
     }
 
     if( m_poAttrQuery != NULL && bServerSideAttributeFilteringWorks )
     {
-        int bRet = FetchNextRowsAttributeFilter();
-        if (bRet || bServerSideAttributeFilteringWorks)
+        const bool bRet = FetchNextRowsAttributeFilter();
+        if( bRet || bServerSideAttributeFilteringWorks )
             return bRet;
     }
 
@@ -790,7 +801,6 @@ int OGRCouchDBTableLayer::FetchNextRows()
     return FetchNextRowsAnalyseDocs(poAnswerObj);
 }
 
-
 /************************************************************************/
 /*                            GetFeature()                              */
 /************************************************************************/
@@ -893,17 +903,17 @@ GIntBig OGRCouchDBTableLayer::GetFeatureCount(int bForce)
 
     if (m_poFilterGeom == NULL && m_poAttrQuery != NULL)
     {
-        int bOutHasStrictComparisons = FALSE;
+        bool bOutHasStrictComparisons = false;
         CPLString osURI = BuildAttrQueryURI(bOutHasStrictComparisons);
-        if (!bOutHasStrictComparisons && osURI.size() != 0 &&
-            strstr(osURI, "/_all_docs?") == NULL)
+        if( !bOutHasStrictComparisons && !osURI.empty() &&
+            strstr(osURI, "/_all_docs?") == NULL )
         {
             osURI += "&reduce=true";
             json_object* poAnswerObj = poDS->GET(osURI);
             json_object* poRows = NULL;
             if (poAnswerObj != NULL &&
                 json_object_is_type(poAnswerObj, json_type_object) &&
-                (poRows = json_object_object_get(poAnswerObj, "rows")) != NULL &&
+                (poRows = CPL_json_object_object_get(poAnswerObj, "rows")) != NULL &&
                 json_object_is_type(poRows, json_type_array))
             {
                 int nLength = json_object_array_length(poRows);
@@ -918,7 +928,7 @@ GIntBig OGRCouchDBTableLayer::GetFeatureCount(int bForce)
                     if (poRow && json_object_is_type(poRow, json_type_object))
                     {
                         /* for string fields */
-                        json_object* poValue = json_object_object_get(poRow, "value");
+                        json_object* poValue = CPL_json_object_object_get(poRow, "value");
                         if (poValue != NULL && json_object_is_type(poValue, json_type_int))
                         {
                             int nVal = json_object_get_int(poValue);
@@ -928,7 +938,7 @@ GIntBig OGRCouchDBTableLayer::GetFeatureCount(int bForce)
                         else if (poValue != NULL && json_object_is_type(poValue, json_type_object))
                         {
                             /* for numeric fields */
-                            json_object* poCount = json_object_object_get(poValue, "count");
+                            json_object* poCount = CPL_json_object_object_get(poValue, "count");
                             if (poCount != NULL && json_object_is_type(poCount, json_type_int))
                             {
                                 int nVal = json_object_get_int(poCount);
@@ -951,7 +961,7 @@ GIntBig OGRCouchDBTableLayer::GetFeatureCount(int bForce)
         /* geometry of a feature does not necessary mean the intersection of the */
         /* geometry itself */
         RunSpatialFilterQueryIfNecessary();
-        if (bServerSideSpatialFilteringWorks)
+        if( bServerSideSpatialFilteringWorks )
         {
             return (int)aosIdsToFetch.size();
         }
@@ -984,7 +994,7 @@ int OGRCouchDBTableLayer::GetTotalFeatureCount()
         return nTotalRows;
     }
 
-    json_object* poTotalRows = json_object_object_get(poAnswerObj,
+    json_object* poTotalRows = CPL_json_object_object_get(poAnswerObj,
                                                         "total_rows");
     if (poTotalRows != NULL &&
         json_object_is_type(poTotalRows, json_type_int))
@@ -992,7 +1002,7 @@ int OGRCouchDBTableLayer::GetTotalFeatureCount()
         nTotalRows = json_object_get_int(poTotalRows);
     }
 
-    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    json_object* poRows = CPL_json_object_object_get(poAnswerObj, "rows");
     if (poRows == NULL ||
         !json_object_is_type(poRows, json_type_array))
     {
@@ -1009,7 +1019,7 @@ int OGRCouchDBTableLayer::GetTotalFeatureCount()
         if ( poRow != NULL &&
              json_object_is_type(poRow, json_type_object) )
         {
-            json_object* poId = json_object_object_get(poRow, "id");
+            json_object* poId = CPL_json_object_object_get(poRow, "id");
             const char* pszId = json_object_get_string(poId);
             if ( pszId && strcmp(pszId, "_design/ogr_spatial") == 0)
             {
@@ -1020,7 +1030,7 @@ int OGRCouchDBTableLayer::GetTotalFeatureCount()
 
     if (!bHasOGRSpatial)
     {
-        bServerSideSpatialFilteringWorks = FALSE;
+        bServerSideSpatialFilteringWorks = false;
     }
 
     if (nTotalRows >= nSpecialRows)
@@ -1039,7 +1049,7 @@ OGRErr OGRCouchDBTableLayer::CreateField( OGRFieldDefn *poField,
                                           CPL_UNUSED int bApproxOK )
 {
 
-    if (!poDS->IsReadWrite())
+    if( !poDS->IsReadWrite() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in read-only mode");
@@ -1050,7 +1060,7 @@ OGRErr OGRCouchDBTableLayer::CreateField( OGRFieldDefn *poField,
 
     poFeatureDefn->AddFieldDefn(poField);
 
-    bMustWriteMetadata = TRUE;
+    bMustWriteMetadata = true;
 
     return OGRERR_NONE;
 }
@@ -1061,7 +1071,7 @@ OGRErr OGRCouchDBTableLayer::CreateField( OGRFieldDefn *poField,
 
 static json_object* OGRCouchDBWriteFeature( OGRFeature* poFeature,
                                             OGRwkbGeometryType eGeomType,
-                                            int bGeoJSONDocument,
+                                            bool bGeoJSONDocument,
                                             int nCoordPrecision )
 {
     CPLAssert( NULL != poFeature );
@@ -1069,7 +1079,7 @@ static json_object* OGRCouchDBWriteFeature( OGRFeature* poFeature,
     json_object* poObj = json_object_new_object();
     CPLAssert( NULL != poObj );
 
-    if (poFeature->IsFieldSet(COUCHDB_ID_FIELD))
+    if (poFeature->IsFieldSetAndNotNull(COUCHDB_ID_FIELD))
     {
         const char* pszId = poFeature->GetFieldAsString(COUCHDB_ID_FIELD);
         json_object_object_add( poObj, "_id",
@@ -1090,14 +1100,14 @@ static json_object* OGRCouchDBWriteFeature( OGRFeature* poFeature,
                                 json_object_new_string(CPLSPrintf("%09ld", (long)poFeature->GetFID())) );
     }
 
-    if (poFeature->IsFieldSet(COUCHDB_REV_FIELD))
+    if (poFeature->IsFieldSetAndNotNull(COUCHDB_REV_FIELD))
     {
         const char* pszRev = poFeature->GetFieldAsString(COUCHDB_REV_FIELD);
         json_object_object_add( poObj, "_rev",
                                 json_object_new_string(pszRev) );
     }
 
-    if (bGeoJSONDocument)
+    if( bGeoJSONDocument )
     {
         json_object_object_add( poObj, "type",
                                 json_object_new_string("Feature") );
@@ -1108,14 +1118,14 @@ static json_object* OGRCouchDBWriteFeature( OGRFeature* poFeature,
 /* -------------------------------------------------------------------- */
     json_object* poObjProps = NULL;
 
-    poObjProps = OGRGeoJSONWriteAttributes( poFeature, -1 );
+    poObjProps = OGRGeoJSONWriteAttributes( poFeature );
     if (poObjProps)
     {
         json_object_object_del(poObjProps, "_id");
         json_object_object_del(poObjProps, "_rev");
     }
 
-    if (bGeoJSONDocument)
+    if( bGeoJSONDocument )
     {
         json_object_object_add( poObj, "properties", poObjProps );
     }
@@ -1192,7 +1202,7 @@ int OGRCouchDBTableLayer::GetMaximumId()
         return -1;
     }
 
-    json_object* poRows = json_object_object_get(poAnswerObj, "rows");
+    json_object* poRows = CPL_json_object_object_get(poAnswerObj, "rows");
     if (poRows == NULL ||
         !json_object_is_type(poRows, json_type_array))
     {
@@ -1218,7 +1228,7 @@ int OGRCouchDBTableLayer::GetMaximumId()
         return -1;
     }
 
-    json_object* poId = json_object_object_get(poRow, "id");
+    json_object* poId = CPL_json_object_object_get(poRow, "id");
     const char* pszId = json_object_get_string(poId);
     if (pszId != NULL)
     {
@@ -1240,7 +1250,7 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
 {
     GetLayerDefn();
 
-    if (!poDS->IsReadWrite())
+    if( !poDS->IsReadWrite() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in read-only mode");
@@ -1249,11 +1259,14 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     if (poFeature->IsFieldSet(COUCHDB_REV_FIELD))
     {
-        static int bOnce = FALSE;
-        if (!bOnce)
+        static bool bOnce = false;
+        if( !bOnce )
         {
-            bOnce = TRUE;
-            CPLDebug("CouchDB", "CreateFeature() should be called with an unset _rev field. Ignoring it");
+            bOnce = true;
+            CPLDebug(
+                "CouchDB",
+                "CreateFeature() should be called with an unset _rev field. "
+                "Ignoring it");
         }
         poFeature->UnsetField(COUCHDB_REV_FIELD);
     }
@@ -1268,17 +1281,17 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
     OGRGeometry* poGeom = poFeature->GetGeometryRef();
-    if (bExtentValid && poGeom != NULL && !poGeom->IsEmpty())
+    if( bExtentValid && poGeom != NULL && !poGeom->IsEmpty() )
     {
         OGREnvelope sEnvelope;
         poGeom->getEnvelope(&sEnvelope);
-        if (!bExtentSet)
+        if( !bExtentSet )
         {
             dfMinX = sEnvelope.MinX;
             dfMinY = sEnvelope.MinY;
             dfMaxX = sEnvelope.MaxX;
             dfMaxY = sEnvelope.MaxY;
-            bExtentSet = TRUE;
+            bExtentSet = true;
         }
         if (sEnvelope.MinX < dfMinX)
             dfMinX = sEnvelope.MinX;
@@ -1290,13 +1303,14 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
             dfMaxY = sEnvelope.MaxY;
     }
 
-    if (bExtentValid && eGeomType != wkbNone)
-        bMustWriteMetadata = TRUE;
+    if( bExtentValid && eGeomType != wkbNone )
+        bMustWriteMetadata = true;
 
     int nFID = nNextFIDForCreate ++;
     CPLString osFID;
-    if (!poFeature->IsFieldSet(COUCHDB_ID_FIELD) ||
-        !CPLTestBool(CPLGetConfigOption("COUCHDB_PRESERVE_ID_ON_INSERT", "FALSE")))
+    if( !poFeature->IsFieldSetAndNotNull(COUCHDB_ID_FIELD) ||
+        !CPLTestBool(CPLGetConfigOption("COUCHDB_PRESERVE_ID_ON_INSERT",
+                                        "FALSE")) )
     {
         if (poFeature->GetFID() != OGRNullFID)
         {
@@ -1317,7 +1331,7 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
                                                 bGeoJSONDocument,
                                                 nCoordPrecision);
 
-    if (bInTransaction)
+    if( bInTransaction )
     {
         aoTransactionFeatures.push_back(poObj);
 
@@ -1335,14 +1349,14 @@ OGRErr OGRCouchDBTableLayer::ICreateFeature( OGRFeature *poFeature )
     if (poAnswerObj == NULL)
         return OGRERR_FAILURE;
 
-    if (!poDS->IsOK(poAnswerObj, "Feature creation failed"))
+    if( !poDS->IsOK(poAnswerObj, "Feature creation failed") )
     {
         json_object_put(poAnswerObj);
         return OGRERR_FAILURE;
     }
 
-    json_object* poId = json_object_object_get(poAnswerObj, "id");
-    json_object* poRev = json_object_object_get(poAnswerObj, "rev");
+    json_object* poId = CPL_json_object_object_get(poAnswerObj, "id");
+    json_object* poRev = CPL_json_object_object_get(poAnswerObj, "rev");
 
     const char* pszId = json_object_get_string(poId);
     const char* pszRev = json_object_get_string(poRev);
@@ -1378,14 +1392,14 @@ OGRErr      OGRCouchDBTableLayer::ISetFeature( OGRFeature *poFeature )
 {
     GetLayerDefn();
 
-    if (!poDS->IsReadWrite())
+    if( !poDS->IsReadWrite() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in read-only mode");
         return OGRERR_FAILURE;
     }
 
-    if (!poFeature->IsFieldSet(COUCHDB_ID_FIELD))
+    if (!poFeature->IsFieldSetAndNotNull(COUCHDB_ID_FIELD))
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "SetFeature() requires non null _id field");
@@ -1407,22 +1421,22 @@ OGRErr      OGRCouchDBTableLayer::ISetFeature( OGRFeature *poFeature )
     if (poAnswerObj == NULL)
         return OGRERR_FAILURE;
 
-    if (!poDS->IsOK(poAnswerObj, "Feature update failed"))
+    if( !poDS->IsOK(poAnswerObj, "Feature update failed") )
     {
         json_object_put(poAnswerObj);
         return OGRERR_FAILURE;
     }
 
-    json_object* poRev = json_object_object_get(poAnswerObj, "rev");
+    json_object* poRev = CPL_json_object_object_get(poAnswerObj, "rev");
     const char* pszRev = json_object_get_string(poRev);
     poFeature->SetField(COUCHDB_REV_FIELD, pszRev);
 
     json_object_put(poAnswerObj);
 
-    if (bExtentValid && eGeomType != wkbNone)
+    if( bExtentValid && eGeomType != wkbNone )
     {
-        bExtentValid = FALSE;
-        bMustWriteMetadata = TRUE;
+        bExtentValid = false;
+        bMustWriteMetadata = true;
     }
     nUpdateSeq ++;
 
@@ -1437,7 +1451,7 @@ OGRErr OGRCouchDBTableLayer::DeleteFeature( GIntBig nFID )
 {
     GetLayerDefn();
 
-    if (!poDS->IsReadWrite())
+    if( !poDS->IsReadWrite() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in read-only mode");
@@ -1459,7 +1473,7 @@ OGRErr OGRCouchDBTableLayer::DeleteFeature( const char* pszId )
 {
     GetLayerDefn();
 
-    if (!poDS->IsReadWrite())
+    if( !poDS->IsReadWrite() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in read-only mode");
@@ -1479,8 +1493,8 @@ OGRErr OGRCouchDBTableLayer::DeleteFeature( const char* pszId )
 
 OGRErr OGRCouchDBTableLayer::DeleteFeature( OGRFeature* poFeature )
 {
-    if (!poFeature->IsFieldSet(COUCHDB_ID_FIELD) ||
-        !poFeature->IsFieldSet(COUCHDB_REV_FIELD))
+    if (!poFeature->IsFieldSetAndNotNull(COUCHDB_ID_FIELD) ||
+        !poFeature->IsFieldSetAndNotNull(COUCHDB_REV_FIELD))
     {
         delete poFeature;
         return OGRERR_FAILURE;
@@ -1494,11 +1508,11 @@ OGRErr OGRCouchDBTableLayer::DeleteFeature( OGRFeature* poFeature )
     osURI += "/";
     osURI += CPLSPrintf("%s?rev=%s", pszId, pszRev);
 
-    if (bExtentValid && eGeomType != wkbNone)
-        bMustWriteMetadata = TRUE;
+    if( bExtentValid && eGeomType != wkbNone )
+        bMustWriteMetadata = true;
 
     OGRGeometry* poGeom = poFeature->GetGeometryRef();
-    if (bExtentValid && bExtentSet && poGeom != NULL && !poGeom->IsEmpty())
+    if( bExtentValid && bExtentSet && poGeom != NULL && !poGeom->IsEmpty() )
     {
         OGREnvelope sEnvelope;
         poGeom->getEnvelope(&sEnvelope);
@@ -1507,7 +1521,7 @@ OGRErr OGRCouchDBTableLayer::DeleteFeature( OGRFeature* poFeature )
             dfMaxX == sEnvelope.MaxX ||
             dfMaxY == sEnvelope.MaxY)
         {
-            bExtentValid = FALSE;
+            bExtentValid = false;
         }
     }
 
@@ -1518,7 +1532,7 @@ OGRErr OGRCouchDBTableLayer::DeleteFeature( OGRFeature* poFeature )
     if (poAnswerObj == NULL)
         return OGRERR_FAILURE;
 
-    if (!poDS->IsOK(poAnswerObj, "Feature deletion failed"))
+    if( !poDS->IsOK(poAnswerObj, "Feature deletion failed") )
     {
         json_object_put(poAnswerObj);
         return OGRERR_FAILURE;
@@ -1539,20 +1553,20 @@ OGRErr OGRCouchDBTableLayer::StartTransaction()
 {
     GetLayerDefn();
 
-    if (bInTransaction)
+    if( bInTransaction )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Already in transaction");
         return OGRERR_FAILURE;
     }
 
-    if (!poDS->IsReadWrite())
+    if( !poDS->IsReadWrite() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in read-only mode");
         return OGRERR_FAILURE;
     }
 
-    bInTransaction = TRUE;
+    bInTransaction = true;
 
     return OGRERR_NONE;
 }
@@ -1565,15 +1579,15 @@ OGRErr OGRCouchDBTableLayer::CommitTransaction()
 {
     GetLayerDefn();
 
-    if (!bInTransaction)
+    if( !bInTransaction )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
         return OGRERR_FAILURE;
     }
 
-    bInTransaction = FALSE;
+    bInTransaction = false;
 
-    if (aoTransactionFeatures.size() == 0)
+    if (aoTransactionFeatures.empty())
         return OGRERR_NONE;
 
     CPLString osPost("{ \"docs\": [");
@@ -1618,10 +1632,10 @@ OGRErr OGRCouchDBTableLayer::CommitTransaction()
         if ( poRow != NULL &&
              json_object_is_type(poRow, json_type_object) )
         {
-            json_object* poId = json_object_object_get(poRow, "id");
-            json_object* poRev = json_object_object_get(poRow, "rev");
-            json_object* poError = json_object_object_get(poRow, "error");
-            json_object* poReason = json_object_object_get(poRow, "reason");
+            json_object* poId = CPL_json_object_object_get(poRow, "id");
+            json_object* poRev = CPL_json_object_object_get(poRow, "rev");
+            json_object* poError = CPL_json_object_object_get(poRow, "error");
+            json_object* poReason = CPL_json_object_object_get(poRow, "reason");
 
             const char* pszId = json_object_get_string(poId);
 
@@ -1660,12 +1674,12 @@ OGRErr OGRCouchDBTableLayer::RollbackTransaction()
 {
     GetLayerDefn();
 
-    if (!bInTransaction)
+    if( !bInTransaction )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Should be in transaction");
         return OGRERR_FAILURE;
     }
-    bInTransaction = FALSE;
+    bInTransaction = false;
     for(int i=0;i<(int)aoTransactionFeatures.size();i++)
     {
         json_object_put(aoTransactionFeatures[i]);
@@ -1683,19 +1697,18 @@ OGRErr OGRCouchDBTableLayer::SetAttributeFilter( const char *pszQuery )
 {
     GetLayerDefn();
 
-    bServerSideAttributeFilteringWorks = TRUE;
+    bServerSideAttributeFilteringWorks = true;
 
     OGRErr eErr = OGRCouchDBLayer::SetAttributeFilter(pszQuery);
 
     if (eErr == OGRERR_NONE)
     {
-        bHasInstalledAttributeFilter = TRUE;
+        bHasInstalledAttributeFilter = true;
     }
 
     return eErr;
 }
 
-
 /************************************************************************/
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
@@ -1707,7 +1720,7 @@ void OGRCouchDBTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 
     if( InstallFilter( poGeomIn ) )
     {
-        bMustRunSpatialFilter = TRUE;
+        bMustRunSpatialFilter = true;
 
         ResetReading();
     }
@@ -1720,13 +1733,13 @@ void OGRCouchDBTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 void OGRCouchDBTableLayer::SetInfoAfterCreation(OGRwkbGeometryType eGType,
                                                 OGRSpatialReference* poSRSIn,
                                                 int nUpdateSeqIn,
-                                                int bGeoJSONDocumentIn)
+                                                bool bGeoJSONDocumentIn)
 {
     eGeomType = eGType;
     nNextFIDForCreate = 0;
-    bMustWriteMetadata = TRUE;
-    bExtentValid = TRUE;
-    bHasLoadedMetadata = TRUE;
+    bMustWriteMetadata = true;
+    bExtentValid = true;
+    bHasLoadedMetadata = true;
     nUpdateSeq = nUpdateSeqIn;
     bGeoJSONDocument = bGeoJSONDocumentIn;
 
@@ -1752,10 +1765,10 @@ static int OGRCouchDBIsNumericObject(json_object* poObj)
 
 void OGRCouchDBTableLayer::LoadMetadata()
 {
-    if (bHasLoadedMetadata)
+    if( bHasLoadedMetadata )
         return;
 
-    bHasLoadedMetadata = TRUE;
+    bHasLoadedMetadata = true;
 
     CPLString osURI("/");
     osURI += osEscapedName;
@@ -1771,12 +1784,12 @@ void OGRCouchDBTableLayer::LoadMetadata()
         return;
     }
 
-    json_object* poRev = json_object_object_get(poAnswerObj, "_rev");
+    json_object* poRev = CPL_json_object_object_get(poAnswerObj, "_rev");
     const char* pszRev = json_object_get_string(poRev);
     if (pszRev)
         osMetadataRev = pszRev;
 
-    json_object* poError = json_object_object_get(poAnswerObj, "error");
+    json_object* poError = CPL_json_object_object_get(poAnswerObj, "error");
     const char* pszError = json_object_get_string(poError);
     if (pszError && strcmp(pszError, "not_found") == 0)
     {
@@ -1790,7 +1803,7 @@ void OGRCouchDBTableLayer::LoadMetadata()
         return;
     }
 
-    json_object* poJsonSRS = json_object_object_get(poAnswerObj, "srs");
+    json_object* poJsonSRS = CPL_json_object_object_get(poAnswerObj, "srs");
     const char* pszSRS = json_object_get_string(poJsonSRS);
     if (pszSRS != NULL)
     {
@@ -1802,7 +1815,7 @@ void OGRCouchDBTableLayer::LoadMetadata()
         }
     }
 
-    json_object* poGeomType = json_object_object_get(poAnswerObj, "geomtype");
+    json_object* poGeomType = CPL_json_object_object_get(poAnswerObj, "geomtype");
     const char* pszGeomType = json_object_get_string(poGeomType);
 
     if (pszGeomType)
@@ -1810,27 +1823,27 @@ void OGRCouchDBTableLayer::LoadMetadata()
         if (EQUAL(pszGeomType, "NONE"))
         {
             eGeomType = wkbNone;
-            bExtentValid = TRUE;
+            bExtentValid = true;
         }
         else
         {
             eGeomType = OGRFromOGCGeomType(pszGeomType);
 
-            json_object* poIs25D = json_object_object_get(poAnswerObj, "is_25D");
+            json_object* poIs25D = CPL_json_object_object_get(poAnswerObj, "is_25D");
             if (poIs25D && json_object_get_boolean(poIs25D))
                 eGeomType = wkbSetZ(eGeomType);
 
-            json_object* poExtent = json_object_object_get(poAnswerObj, "extent");
+            json_object* poExtent = CPL_json_object_object_get(poAnswerObj, "extent");
             if (poExtent && json_object_get_type(poExtent) == json_type_object)
             {
                 json_object* poUpdateSeq =
-                    json_object_object_get(poExtent, "validity_update_seq");
+                    CPL_json_object_object_get(poExtent, "validity_update_seq");
                 if (poUpdateSeq && json_object_get_type(poUpdateSeq) == json_type_int)
                 {
                     int nValidityUpdateSeq = json_object_get_int(poUpdateSeq);
                     if (nValidityUpdateSeq <= 0)
                     {
-                        bAlwaysValid = TRUE;
+                        bAlwaysValid = true;
                     }
                     else
                     {
@@ -1848,7 +1861,7 @@ void OGRCouchDBTableLayer::LoadMetadata()
                 else
                     poUpdateSeq = NULL;
 
-                json_object* poBbox = json_object_object_get(poExtent, "bbox");
+                json_object* poBbox = CPL_json_object_object_get(poExtent, "bbox");
                 if (poUpdateSeq && poBbox &&
                     json_object_get_type(poBbox) == json_type_array &&
                     json_object_array_length(poBbox) == 4 &&
@@ -1861,17 +1874,19 @@ void OGRCouchDBTableLayer::LoadMetadata()
                     dfMinY = json_object_get_double(json_object_array_get_idx(poBbox, 1));
                     dfMaxX = json_object_get_double(json_object_array_get_idx(poBbox, 2));
                     dfMaxY = json_object_get_double(json_object_array_get_idx(poBbox, 3));
-                    bExtentValid = bExtentSet = TRUE;
+                    bExtentValid = true;
+                    bExtentSet = true;
                 }
             }
         }
     }
 
-    json_object* poGeoJSON = json_object_object_get(poAnswerObj, "geojson_documents");
+    json_object* poGeoJSON =
+        CPL_json_object_object_get(poAnswerObj, "geojson_documents");
     if (poGeoJSON && json_object_is_type(poGeoJSON, json_type_boolean))
-        bGeoJSONDocument = json_object_get_boolean(poGeoJSON);
+        bGeoJSONDocument = CPL_TO_BOOL(json_object_get_boolean(poGeoJSON));
 
-    json_object* poFields = json_object_object_get(poAnswerObj, "fields");
+    json_object* poFields = CPL_json_object_object_get(poAnswerObj, "fields");
     if (poFields && json_object_is_type(poFields, json_type_array))
     {
         poFeatureDefn = new OGRFeatureDefn( osName );
@@ -1893,11 +1908,11 @@ void OGRCouchDBTableLayer::LoadMetadata()
             json_object* poField = json_object_array_get_idx(poFields, i);
             if (poField && json_object_is_type(poField, json_type_object))
             {
-                json_object* poName = json_object_object_get(poField, "name");
+                json_object* poName = CPL_json_object_object_get(poField, "name");
                 const char* pszName = json_object_get_string(poName);
                 if (pszName)
                 {
-                    json_object* poType = json_object_object_get(poField, "type");
+                    json_object* poType = CPL_json_object_object_get(poField, "type");
                     const char* pszType = json_object_get_string(poType);
                     OGRFieldType eType = OFTString;
                     if (pszType)
@@ -1943,7 +1958,7 @@ void OGRCouchDBTableLayer::WriteMetadata()
 
     json_object* poDoc = json_object_new_object();
 
-    if (osMetadataRev.size() > 0)
+    if (!osMetadataRev.empty())
     {
         json_object_object_add(poDoc, "_rev",
                                json_object_new_string(osMetadataRev));
@@ -1971,13 +1986,14 @@ void OGRCouchDBTableLayer::WriteMetadata()
                                json_object_new_boolean(TRUE));
         }
 
-        if (bExtentValid && bExtentSet && nUpdateSeq >= 0)
+        if( bExtentValid && bExtentSet && nUpdateSeq >= 0 )
         {
             json_object* poExtent = json_object_new_object();
             json_object_object_add(poDoc, "extent", poExtent);
 
-            json_object_object_add(poExtent, "validity_update_seq",
-                                   json_object_new_int((bAlwaysValid) ? -1 : nUpdateSeq + 1));
+            json_object_object_add(
+                poExtent, "validity_update_seq",
+                json_object_new_int(bAlwaysValid ? -1 : nUpdateSeq + 1));
 
             json_object* poBbox = json_object_new_array();
             json_object_object_add(poExtent, "bbox", poBbox);
@@ -1999,7 +2015,6 @@ void OGRCouchDBTableLayer::WriteMetadata()
     json_object* poFields = json_object_new_array();
     json_object_object_add(poDoc, "fields", poFields);
 
-
     for(int i=COUCHDB_FIRST_FIELD;i<poFeatureDefn->GetFieldCount();i++)
     {
         json_object* poField = json_object_new_object();
@@ -2029,11 +2044,11 @@ void OGRCouchDBTableLayer::WriteMetadata()
 
     json_object_put(poDoc);
 
-    if (poDS->IsOK(poAnswerObj, "Metadata creation failed"))
+    if( poDS->IsOK(poAnswerObj, "Metadata creation failed") )
     {
         nUpdateSeq++;
 
-        json_object* poRev = json_object_object_get(poAnswerObj, "_rev");
+        json_object* poRev = CPL_json_object_object_get(poAnswerObj, "_rev");
         const char* pszRev = json_object_get_string(poRev);
         if (pszRev)
             osMetadataRev = pszRev;
@@ -2050,7 +2065,7 @@ OGRErr OGRCouchDBTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 {
     LoadMetadata();
 
-    if (!bExtentValid)
+    if( !bExtentValid )
         return OGRCouchDBLayer::GetExtent(psExtent, bForce);
 
     psExtent->MinX = 0.0;
@@ -2058,7 +2073,7 @@ OGRErr OGRCouchDBTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     psExtent->MinY = 0.0;
     psExtent->MaxY = 0.0;
 
-    if (!bExtentSet)
+    if( !bExtentSet )
         return OGRERR_FAILURE;
 
     psExtent->MinX = dfMinX;
@@ -2085,9 +2100,9 @@ int OGRCouchDBTableLayer::FetchUpdateSeq()
     json_object* poAnswerObj = poDS->GET(osURI);
     if (poAnswerObj != NULL &&
         json_object_is_type(poAnswerObj, json_type_object) &&
-        json_object_object_get(poAnswerObj, "update_seq") != NULL)
+        CPL_json_object_object_get(poAnswerObj, "update_seq") != NULL)
     {
-        nUpdateSeq = json_object_get_int(json_object_object_get(poAnswerObj,
+        nUpdateSeq = json_object_get_int(CPL_json_object_object_get(poAnswerObj,
                                                                 "update_seq"));
     }
     else
diff --git a/ogr/ogrsf_frmts/csv/drv_csv.html b/ogr/ogrsf_frmts/csv/drv_csv.html
index 804ebb9..360de23 100644
--- a/ogr/ogrsf_frmts/csv/drv_csv.html
+++ b/ogr/ogrsf_frmts/csv/drv_csv.html
@@ -45,6 +45,11 @@ accordingly with the <a href="http://giswiki.hsr.ch/GeoCSV">GeoCSV specification
 the "CoordX" or "Point(X)" type can be used to specify a column with longitude/easting values,
 "CoordY" or "Point(Y)" for latitude/northing values and "WKT" for geometries encoded in WKT </p>
 
+<p>Starting with GDAL 2.2, the "JSonStringList", "JSonIntegerList", "JSonInteger64List"
+and "JSonRealList" types can be used in .csvt to map to the corresponding OGR StringList,
+IntegerList, Integer64List and RealList types. The field values are then encoded as
+JSon arrays, with proper CSV escaping.</p>
+
 <p>Starting with GDAL 2.0, automatic field type guessing can also be done if
 specifying the open options described in the below "Open options" section.</p>
 
diff --git a/ogr/ogrsf_frmts/csv/ogr_csv.h b/ogr/ogrsf_frmts/csv/ogr_csv.h
index f542e93..8c2850a 100644
--- a/ogr/ogrsf_frmts/csv/ogr_csv.h
+++ b/ogr/ogrsf_frmts/csv/ogr_csv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_csv.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_csv.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  CSV Translator
  * Purpose:  Definition of classes for OGR .csv driver.
@@ -46,9 +46,9 @@ typedef enum
 class OGRCSVDataSource;
 
 char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
-                             int bDontHonourStrings = FALSE,
-                             int bKeepLeadingAndClosingQuotes = FALSE,
-                             int bMergeDelimiter = FALSE);
+                             bool bDontHonourStrings = false,
+                             bool bKeepLeadingAndClosingQuotes = false,
+                             bool bMergeDelimiter = false );
 
 typedef enum
 {
@@ -71,30 +71,30 @@ class OGRCSVLayer : public OGRLayer
 
     int                 nNextFID;
 
-    int                 bHasFieldNames;
+    bool                bHasFieldNames;
 
     OGRFeature *        GetNextUnfilteredFeature();
 
-    int                 bNew;
-    int                 bInWriteMode;
-    int                 bUseCRLF;
-    int                 bNeedRewindBeforeRead;
+    bool                bNew;
+    bool                bInWriteMode;
+    bool                bUseCRLF;
+    bool                bNeedRewindBeforeRead;
     OGRCSVGeometryFormat eGeometryFormat;
 
     char*               pszFilename;
-    int                 bCreateCSVT;
-    int                 bWriteBOM;
+    bool                bCreateCSVT;
+    bool                bWriteBOM;
     char                chDelimiter;
 
     int                 nCSVFieldCount;
     int*                panGeomFieldIndex;
-    int                 bFirstFeatureAppendedDuringSession;
-    int                 bHiddenWKTColumn;
+    bool                bFirstFeatureAppendedDuringSession;
+    bool                bHiddenWKTColumn;
 
     /*http://www.faa.gov/airports/airport_safety/airportdata_5010/menu/index.cfm specific */
     int                 iNfdcLongitudeS;
     int                 iNfdcLatitudeS;
-    int                 bDontHonourStrings;
+    bool                bDontHonourStrings;
 
     int                 iLongitudeField;
     int                 iLatitudeField;
@@ -103,37 +103,38 @@ class OGRCSVLayer : public OGRLayer
     CPLString           osYField;
     CPLString           osZField;
 
-    int                 bIsEurostatTSV;
+    bool                bIsEurostatTSV;
     int                 nEurostatDims;
 
     GIntBig             nTotalFeatures;
 
     char              **AutodetectFieldTypes(char** papszOpenOptions, int nFieldCount);
 
-    int                 bWarningBadTypeOrWidth;
-    int                 bKeepSourceColumns;
-    int                 bKeepGeomColumns;
+    bool                bWarningBadTypeOrWidth;
+    bool                bKeepSourceColumns;
+    bool                bKeepGeomColumns;
 
-    int                 bMergeDelimiter;
+    bool                bMergeDelimiter;
 
-    int                 bEmptyStringNull;
+    bool                bEmptyStringNull;
 
     char              **GetNextLineTokens();
 
-    static int          Matches(const char* pszFieldName, char** papszPossibleNames);
+    static bool         Matches( const char* pszFieldName,
+                                 char** papszPossibleNames );
 
   public:
     OGRCSVLayer( const char *pszName, VSILFILE *fp, const char *pszFilename,
                  int bNew, int bInWriteMode, char chDelimiter );
-   ~OGRCSVLayer();
+    virtual ~OGRCSVLayer();
 
     const char*         GetFilename() const { return pszFilename; }
     char                GetDelimiter() const { return chDelimiter; }
-    int                 GetCRLF() const { return bUseCRLF; }
-    int                 GetCreateCSVT() const { return bCreateCSVT; }
-    int                 GetWriteBOM() const { return bWriteBOM; }
+    bool                GetCRLF() const { return bUseCRLF; }
+    bool                GetCreateCSVT() const { return bCreateCSVT; }
+    bool                GetWriteBOM() const { return bWriteBOM; }
     OGRCSVGeometryFormat GetGeometryFormat() const { return eGeometryFormat; }
-    int                 HasHiddenWKTColumn() const { return bHiddenWKTColumn; }
+    bool                HasHiddenWKTColumn() const { return bHiddenWKTColumn; }
     GIntBig             GetTotalFeatureCount() const { return nTotalFeatures; }
     const CPLString&    GetXField() const { return osXField; }
     const CPLString&    GetYField() const { return osYField; }
@@ -143,33 +144,34 @@ class OGRCSVLayer : public OGRLayer
                                           const char* pszGeonamesGeomFieldPrefix = NULL,
                                           char** papszOpenOptions = NULL );
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
-    virtual OGRFeature* GetFeature( GIntBig nFID );
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    virtual OGRFeature* GetFeature( GIntBig nFID ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
     static OGRCSVCreateFieldAction PreCreateField( OGRFeatureDefn* poFeatureDefn,
-                                    OGRFieldDefn *poNewField, int bApproxOK );
+                                                   OGRFieldDefn *poNewField,
+                                                   int bApproxOK );
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
-                                         int bApproxOK = TRUE );
+                                         int bApproxOK = TRUE ) override;
 
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
 
-    void                SetCRLF(int);
+    void                SetCRLF( bool bNewValue );
     void                SetWriteGeometry(OGRwkbGeometryType eGType,
                                          OGRCSVGeometryFormat eGeometryFormat,
                                          const char* pszGeomCol = NULL);
-    void                SetCreateCSVT(int bCreateCSVT);
-    void                SetWriteBOM(int bWriteBOM);
+    void                SetCreateCSVT( bool bCreateCSVT );
+    void                SetWriteBOM( bool bWriteBOM );
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      SyncToDisk();
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr      SyncToDisk() override;
 
     OGRErr              WriteHeader();
 };
@@ -185,42 +187,42 @@ class OGRCSVDataSource : public OGRDataSource
     OGRLayer          **papoLayers;
     int                 nLayers;
 
-    int                 bUpdate;
+    bool                bUpdate;
 
     CPLString           osDefaultCSVName;
 
-    int                 bEnableGeometryFields;
+    bool                bEnableGeometryFields;
 
   public:
                         OGRCSVDataSource();
-                        ~OGRCSVDataSource();
+                        virtual ~OGRCSVDataSource();
 
     int                 Open( const char * pszFilename,
                               int bUpdate, int bForceAccept,
                               char** papszOpenOptions = NULL );
-    int                 OpenTable( const char * pszFilename,
+    bool                OpenTable( const char * pszFilename,
                                    char** papszOpenOptions,
                                    const char* pszNfdcRunwaysGeomField = NULL,
-                                   const char* pszGeonamesGeomFieldPrefix = NULL);
+                                   const char* pszGeonamesGeomFieldPrefix = NULL );
 
-    const char          *GetName() { return pszName; }
+    const char          *GetName() override { return pszName; }
 
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
-                                     char ** papszOptions = NULL );
+                                     char ** papszOptions = NULL ) override;
 
-    virtual OGRErr      DeleteLayer(int);
+    virtual OGRErr      DeleteLayer(int) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     void                CreateForSingleFile( const char* pszDirname,
                                              const char *pszFilename );
 
-    void                EnableGeometryFields() { bEnableGeometryFields = TRUE; }
+    void                EnableGeometryFields() { bEnableGeometryFields = true; }
 
     static CPLString    GetRealExtension(CPLString osFilename);
 };
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
index 3764717..582a1b0 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcsvdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDataSource class
@@ -28,16 +27,27 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_csv.h"
+
+#include <cerrno>
+#include <cstring>
+#include <string>
+
+#include "cpl_csv.h"
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
-#include "cpl_csv.h"
+#include "cpl_vsi.h"
 #include "cpl_vsi_virtual.h"
-
-#include "ogr_csv.h"
-
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
 #include "ogreditablelayer.h"
+#include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrcsvdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrcsvdatasource.cpp 37367 2017-02-13 05:32:41Z goatbar $");
 
 /************************************************************************/
 /*                     OGRCSVEditableLayerSynchronizer                  */
@@ -53,10 +63,10 @@ class OGRCSVEditableLayerSynchronizer: public IOGREditableLayerSynchronizer
                                                             char** papszOpenOptions) :
                                                 m_poCSVLayer(poCSVLayer),
                                                 m_papszOpenOptions(CSLDuplicate(papszOpenOptions)) {}
-                           ~OGRCSVEditableLayerSynchronizer();
+                   virtual ~OGRCSVEditableLayerSynchronizer();
 
             virtual OGRErr EditableSyncToDisk(OGRLayer* poEditableLayer,
-                                              OGRLayer** ppoDecoratedLayer);
+                                              OGRLayer** ppoDecoratedLayer) override;
 };
 
 /************************************************************************/
@@ -79,7 +89,7 @@ OGRErr OGRCSVEditableLayerSynchronizer::EditableSyncToDisk(OGRLayer* poEditableL
 
     CPLString osLayerName(m_poCSVLayer->GetName());
     CPLString osFilename(m_poCSVLayer->GetFilename());
-    const bool bCreateCSVT = m_poCSVLayer->GetCreateCSVT() != FALSE;
+    const bool bCreateCSVT = m_poCSVLayer->GetCreateCSVT();
     CPLString osCSVTFilename(CPLResetExtension(osFilename, "csvt"));
     VSIStatBufL sStatBuf;
     const bool bHasCSVT = VSIStatL(osCSVTFilename, &sStatBuf) == 0;
@@ -93,7 +103,7 @@ OGRErr OGRCSVEditableLayerSynchronizer::EditableSyncToDisk(OGRLayer* poEditableL
     const char chDelimiter = m_poCSVLayer->GetDelimiter();
     OGRCSVLayer* poCSVTmpLayer = new OGRCSVLayer( osLayerName, NULL,
                                                   osTmpFilename,
-                                                  TRUE, TRUE, chDelimiter );
+                                                  true, true, chDelimiter );
     poCSVTmpLayer->BuildFeatureDefn(NULL, NULL, m_papszOpenOptions);
     poCSVTmpLayer->SetCRLF( m_poCSVLayer->GetCRLF() );
     poCSVTmpLayer->SetCreateCSVT( bCreateCSVT || bHasCSVT );
@@ -108,7 +118,7 @@ OGRErr OGRCSVEditableLayerSynchronizer::EditableSyncToDisk(OGRLayer* poEditableL
                   i < poEditableFDefn->GetFieldCount(); i++ )
     {
         OGRFieldDefn oFieldDefn(poEditableFDefn->GetFieldDefn(i));
-        int iGeomFieldIdx;
+        int iGeomFieldIdx = 0;
         if( (EQUAL(oFieldDefn.GetNameRef(), "WKT") &&
              (iGeomFieldIdx = poEditableFDefn->GetGeomFieldIndex("")) >= 0) ||
             (iGeomFieldIdx = poEditableFDefn->GetGeomFieldIndex(oFieldDefn.GetNameRef())) >= 0 )
@@ -123,10 +133,10 @@ OGRErr OGRCSVEditableLayerSynchronizer::EditableSyncToDisk(OGRLayer* poEditableL
         }
     }
 
-    const bool bHasXY = ( m_poCSVLayer->GetXField().size() != 0 &&
-                          m_poCSVLayer->GetYField().size() != 0 );
-    const bool bHasZ = ( m_poCSVLayer->GetZField().size() != 0 );
-    if( bHasXY && !CSLFetchBoolean(m_papszOpenOptions, "KEEP_GEOM_COLUMNS", TRUE) )
+    const bool bHasXY = ( !m_poCSVLayer->GetXField().empty() &&
+                          !m_poCSVLayer->GetYField().empty() );
+    const bool bHasZ = ( !m_poCSVLayer->GetZField().empty() );
+    if( bHasXY && !CPLFetchBool(m_papszOpenOptions, "KEEP_GEOM_COLUMNS", true) )
     {
         if( poCSVTmpLayer->GetLayerDefn()->GetFieldIndex(m_poCSVLayer->GetXField()) < 0 )
         {
@@ -170,7 +180,7 @@ OGRErr OGRCSVEditableLayerSynchronizer::EditableSyncToDisk(OGRLayer* poEditableL
         }
     }
 
-    OGRFeature* poFeature;
+    OGRFeature* poFeature = NULL;
     poEditableLayer->ResetReading();
     while( eErr == OGRERR_NONE &&
            (poFeature = poEditableLayer->GetNextFeature()) != NULL )
@@ -220,7 +230,8 @@ OGRErr OGRCSVEditableLayerSynchronizer::EditableSyncToDisk(OGRLayer* poEditableL
             (bHasCSVT && VSIRename( osTmpCSVTFilename, osCSVTFilename ) != 0) )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename files");
-            *ppoDecoratedLayer = m_poCSVLayer = NULL;
+            *ppoDecoratedLayer = NULL;
+            m_poCSVLayer = NULL;
             return OGRERR_FAILURE;
         }
         VSIUnlink( osTmpOriFilename );
@@ -233,14 +244,15 @@ OGRErr OGRCSVEditableLayerSynchronizer::EditableSyncToDisk(OGRLayer* poEditableL
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen updated %s",
                  osFilename.c_str());
-        *ppoDecoratedLayer = m_poCSVLayer = NULL;
+        *ppoDecoratedLayer = NULL;
+        m_poCSVLayer = NULL;
         return OGRERR_FAILURE;
     }
 
     m_poCSVLayer = new OGRCSVLayer( osLayerName, fp,
                                     osFilename,
-                                    FALSE, /* new */
-                                    TRUE, /* update */
+                                    false, /* new */
+                                    true, /* update */
                                     chDelimiter );
     m_poCSVLayer->BuildFeatureDefn(NULL, NULL, m_papszOpenOptions);
     *ppoDecoratedLayer = m_poCSVLayer;
@@ -259,8 +271,8 @@ class OGRCSVEditableLayer: public OGREditableLayer
                             char** papszOpenOptions);
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
+                                     int bApproxOK = TRUE ) override;
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
 };
 
 /************************************************************************/
@@ -269,10 +281,10 @@ class OGRCSVEditableLayer: public OGREditableLayer
 
 OGRCSVEditableLayer::OGRCSVEditableLayer(OGRCSVLayer* poCSVLayer,
                                          char** papszOpenOptions) :
-        OGREditableLayer(poCSVLayer, true,
-                         new OGRCSVEditableLayerSynchronizer(
-                                         poCSVLayer, papszOpenOptions),
-                         true)
+    OGREditableLayer(poCSVLayer, true,
+                     new OGRCSVEditableLayerSynchronizer(
+                         poCSVLayer, papszOpenOptions),
+                     true)
 {
     SetSupportsCreateGeomField(true);
     SetSupportsCurveGeometries(true);
@@ -282,7 +294,8 @@ OGRCSVEditableLayer::OGRCSVEditableLayer(OGRCSVLayer* poCSVLayer,
 /*                            CreateField()                             */
 /************************************************************************/
 
-OGRErr OGRCSVEditableLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
+OGRErr OGRCSVEditableLayer::CreateField( OGRFieldDefn *poNewField,
+                                         int bApproxOK )
 
 {
     OGRCSVCreateFieldAction eAction = OGRCSVLayer::PreCreateField(
@@ -319,8 +332,8 @@ OGRCSVDataSource::OGRCSVDataSource() :
     pszName(NULL),
     papoLayers(NULL),
     nLayers(0),
-    bUpdate(FALSE),
-    bEnableGeometryFields(FALSE)
+    bUpdate(false),
+    bEnableGeometryFields(false)
 {}
 
 /************************************************************************/
@@ -357,6 +370,8 @@ int OGRCSVDataSource::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return bUpdate;
     else
         return FALSE;
 }
@@ -383,11 +398,11 @@ CPLString OGRCSVDataSource::GetRealExtension(CPLString osFilename)
     CPLString osExt = CPLGetExtension(osFilename);
     if( STARTS_WITH(osFilename, "/vsigzip/") && EQUAL(osExt, "gz") )
     {
-        if( strlen(osFilename) > 7
-            && EQUAL(osFilename + strlen(osFilename) - 7, ".csv.gz") )
+        if( osFilename.size() > 7
+            && EQUAL(osFilename + osFilename.size() - 7, ".csv.gz") )
             osExt = "csv";
-        else if( strlen(osFilename) > 7
-                 && EQUAL(osFilename + strlen(osFilename) - 7, ".tsv.gz") )
+        else if( osFilename.size() > 7
+                 && EQUAL(osFilename + osFilename.size() - 7, ".tsv.gz") )
             osExt = "tsv";
     }
     return osExt;
@@ -402,13 +417,13 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
 
 {
     pszName = CPLStrdup( pszFilename );
-    bUpdate = bUpdateIn;
+    bUpdate = CPL_TO_BOOL(bUpdateIn);
 
-    if (bUpdateIn && bForceOpen && EQUAL(pszFilename, "/vsistdout/"))
+    if( bUpdate && bForceOpen && EQUAL(pszFilename, "/vsistdout/") )
         return TRUE;
 
     /* For writable /vsizip/, do nothing more */
-    if (bUpdateIn && bForceOpen && STARTS_WITH(pszFilename, "/vsizip/"))
+    if( bUpdate && bForceOpen && STARTS_WITH(pszFilename, "/vsizip/") )
         return TRUE;
 
     CPLString osFilename(pszFilename);
@@ -431,7 +446,7 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
         EQUAL(osBaseFilename, "NfdcRemarks.xls") ||
         EQUAL(osBaseFilename, "NfdcSchedules.xls"))
     {
-        if (bUpdateIn)
+        if( bUpdate )
             return FALSE;
         bIgnoreExtension = true;
     }
@@ -446,13 +461,13 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
               STARTS_WITH_CI(osBaseFilename, "NationalFedCodes_") ||
               STARTS_WITH_CI(osBaseFilename, "AllStates_") ||
               STARTS_WITH_CI(osBaseFilename, "AllStatesFedCodes_") ||
-              ( strlen(osBaseFilename) > 2 &&
+              ( osBaseFilename.size() > 2 &&
                 STARTS_WITH_CI(osBaseFilename+2, "_Features_")) ||
-              ( strlen(osBaseFilename) > 2 &&
+              ( osBaseFilename.size() > 2 &&
                 STARTS_WITH_CI(osBaseFilename+2, "_FedCodes_"))) &&
              (EQUAL(osExt, "txt") || EQUAL(osExt, "zip")) )
     {
-        if (bUpdateIn)
+        if( bUpdate )
             return FALSE;
         bIgnoreExtension = true;
         bUSGeonamesFile = true;
@@ -466,7 +481,7 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
     else if (EQUAL(osBaseFilename, "allCountries.txt") ||
              EQUAL(osBaseFilename, "allCountries.zip"))
     {
-        if (bUpdateIn)
+        if( bUpdate )
             return FALSE;
         bIgnoreExtension = true;
         /* bGeonamesOrgFile = true; */
@@ -511,7 +526,7 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
             if (STARTS_WITH_CI(osBaseFilename, "NationalFedCodes_") ||
                 STARTS_WITH_CI(osBaseFilename, "AllStatesFedCodes_") ||
                 STARTS_WITH_CI(osBaseFilename, "ANTARCTICA_") ||
-                ( strlen(osBaseFilename) > 2 &&
+                ( osBaseFilename.size() > 2 &&
                   STARTS_WITH_CI(osBaseFilename+2, "_FedCodes_")))
             {
                 OpenTable( osFilename, papszOpenOptionsIn, NULL, "PRIMARY");
@@ -597,8 +612,8 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
                   STARTS_WITH_CI(papszNames[i]+2, "_Features_") &&
                   EQUAL(CPLGetExtension(papszNames[i]), "txt") )
         {
-            int bRet
-                = OpenTable( oSubFilename, papszOpenOptionsIn, NULL, "PRIM");
+            bool bRet =
+                OpenTable( oSubFilename, papszOpenOptionsIn, NULL, "PRIM");
             bRet |=
                 OpenTable( oSubFilename, papszOpenOptionsIn, NULL, "SOURCE");
             if ( !bRet )
@@ -641,10 +656,10 @@ int OGRCSVDataSource::Open( const char * pszFilename, int bUpdateIn,
 /*                              OpenTable()                             */
 /************************************************************************/
 
-int OGRCSVDataSource::OpenTable( const char * pszFilename,
-                                 char** papszOpenOptionsIn,
-                                 const char* pszNfdcRunwaysGeomField,
-                                 const char* pszGeonamesGeomFieldPrefix)
+bool OGRCSVDataSource::OpenTable( const char * pszFilename,
+                                  char** papszOpenOptionsIn,
+                                  const char* pszNfdcRunwaysGeomField,
+                                  const char* pszGeonamesGeomFieldPrefix)
 
 {
 /* -------------------------------------------------------------------- */
@@ -661,7 +676,7 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
         CPLError( CE_Warning, CPLE_OpenFailed,
                   "Failed to open %s, %s.",
                   pszFilename, VSIStrerror( errno ) );
-        return FALSE;
+        return false;
     }
 
     if( !bUpdate && strstr(pszFilename, "/vsigzip/") == NULL &&
@@ -696,7 +711,7 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
     if (pszLine == NULL)
     {
         VSIFCloseL( fp );
-        return FALSE;
+        return false;
     }
     char chDelimiter = CSVDetectSeperator(pszLine);
     if( chDelimiter != '\t' && strchr(pszLine, '\t') != NULL )
@@ -709,10 +724,11 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
         }
         else
         {
-            for( int bDontHonourStrings = 0;
-                 bDontHonourStrings <= 1;
-                 bDontHonourStrings++ )
+            for( int nDontHonourStrings = 0;
+                 nDontHonourStrings <= 1;
+                 nDontHonourStrings++ )
             {
+                const bool bDontHonourStrings = CPL_TO_BOOL(nDontHonourStrings);
                 // Read the first 2 lines to see if they have the same number
                 // of fields, if using tabulation.
                 VSIRewindL( fp );
@@ -763,13 +779,13 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
         strchr(pszLine, '|') != NULL)
         chDelimiter = '|';
 
-    char **papszFields = OGRCSVReadParseLineL( fp, chDelimiter, FALSE );
+    char **papszFields = OGRCSVReadParseLineL( fp, chDelimiter, false );
 
     if( CSLCount(papszFields) < 2 )
     {
         VSIFCloseL( fp );
         CSLDestroy( papszFields );
-        return FALSE;
+        return false;
     }
 
     VSIRewindL( fp );
@@ -796,8 +812,9 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
     if (EQUAL(pszFilename, "/vsistdin/"))
         osLayerName = "layer";
 
-    OGRCSVLayer* poCSVLayer = new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate,
-                                            chDelimiter  );
+    OGRCSVLayer* poCSVLayer =
+        new OGRCSVLayer( osLayerName, fp, pszFilename, FALSE, bUpdate,
+                         chDelimiter  );
     poCSVLayer->BuildFeatureDefn( pszNfdcRunwaysGeomField,
                                              pszGeonamesGeomFieldPrefix,
                                              papszOpenOptionsIn );
@@ -808,7 +825,7 @@ int OGRCSVDataSource::OpenTable( const char * pszFilename,
     }
     papoLayers[nLayers-1] = poLayer;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -824,7 +841,7 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Verify we are in update mode.                                   */
 /* -------------------------------------------------------------------- */
-    if (!bUpdate)
+    if( !bUpdate )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
                   "Data source %s opened read-only.\n"
@@ -909,7 +926,7 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
 
     OGRCSVLayer* poCSVLayer = new OGRCSVLayer( pszLayerName, NULL, osFilename,
-                                             TRUE, TRUE, chDelimiter );
+                                               true, true, chDelimiter );
 
     poCSVLayer->BuildFeatureDefn();
 
@@ -917,29 +934,28 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
 /*      Was a particular CRLF order requested?                          */
 /* -------------------------------------------------------------------- */
     const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
-    int bUseCRLF;
+    bool bUseCRLF = false;
 
     if( pszCRLFFormat == NULL )
     {
 #ifdef WIN32
-        bUseCRLF = TRUE;
-#else
-        bUseCRLF = FALSE;
+        bUseCRLF = true;
 #endif
     }
-    else if( EQUAL(pszCRLFFormat,"CRLF") )
-        bUseCRLF = TRUE;
-    else if( EQUAL(pszCRLFFormat,"LF") )
-        bUseCRLF = FALSE;
+    else if( EQUAL(pszCRLFFormat, "CRLF") )
+    {
+        bUseCRLF = true;
+    }
+    else if( EQUAL(pszCRLFFormat, "LF") )
+    {
+    }
     else
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "LINEFORMAT=%s not understood, use one of CRLF or LF.",
                   pszCRLFFormat );
 #ifdef WIN32
-        bUseCRLF = TRUE;
-#else
-        bUseCRLF = FALSE;
+        bUseCRLF = true;
 #endif
     }
 
@@ -996,7 +1012,7 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
     const char *pszCreateCSVT = CSLFetchNameValue( papszOptions, "CREATE_CSVT");
     if (pszCreateCSVT && CPLTestBool(pszCreateCSVT))
     {
-        poCSVLayer->SetCreateCSVT(TRUE);
+        poCSVLayer->SetCreateCSVT(true);
 
 /* -------------------------------------------------------------------- */
 /*      Create .prj file                                                */
@@ -1025,7 +1041,7 @@ OGRCSVDataSource::ICreateLayer( const char *pszLayerName,
 /* -------------------------------------------------------------------- */
 
     const char *pszWriteBOM = CSLFetchNameValue( papszOptions, "WRITE_BOM");
-    if (pszWriteBOM)
+    if( pszWriteBOM )
         poCSVLayer->SetWriteBOM(CPLTestBool(pszWriteBOM));
 
     nLayers++;
@@ -1103,6 +1119,6 @@ void OGRCSVDataSource::CreateForSingleFile( const char* pszDirname,
                                             const char *pszFilename )
 {
     pszName = CPLStrdup( pszDirname );
-    bUpdate = TRUE;
+    bUpdate = true;
     osDefaultCSVName = CPLGetFilename(pszFilename);
 }
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
index 84f88de..da8dfae 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcsvdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVDriver.
@@ -28,12 +27,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_csv.h"
+
+#include <cerrno>
+#include <cstring>
+#include <map>
+#include <string>
+#include <utility>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
-#include <map>
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "gdal_priv.h"
 
-CPL_CVSID("$Id: ogrcsvdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrcsvdriver.cpp 37367 2017-02-13 05:32:41Z goatbar $");
 
 static CPLMutex* hMutex = NULL;
 static std::map<CPLString, GDALDataset*> *poMap = NULL;
@@ -70,9 +81,9 @@ static int OGRCSVDriverIdentify( GDALOpenInfo* poOpenInfo )
               STARTS_WITH_CI(osBaseFilename, "NationalFedCodes_") ||
               STARTS_WITH_CI(osBaseFilename, "AllStates_") ||
               STARTS_WITH_CI(osBaseFilename, "AllStatesFedCodes_") ||
-              (strlen(osBaseFilename) > 2
+              (osBaseFilename.size() > 2
                && STARTS_WITH_CI(osBaseFilename+2, "_Features_")) ||
-              (strlen(osBaseFilename) > 2
+              (osBaseFilename.size()
                && STARTS_WITH_CI(osBaseFilename+2, "_FedCodes_"))) &&
              (EQUAL(osExt, "txt") || EQUAL(osExt, "zip")) )
         {
@@ -134,7 +145,7 @@ void OGRCSVDriverRemoveFromMap(const char* pszName, GDALDataset* poDS)
 static GDALDataset *OGRCSVDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    if( OGRCSVDriverIdentify(poOpenInfo) == FALSE )
+    if( !OGRCSVDriverIdentify(poOpenInfo) )
         return NULL;
 
     if( poMap != NULL )
@@ -267,7 +278,6 @@ static CPLErr OGRCSVDriverDelete( const char *pszFilename )
     return CE_Failure;
 }
 
-
 /************************************************************************/
 /*                           OGRCSVDriverUnload()                       */
 /************************************************************************/
@@ -371,7 +381,7 @@ void RegisterOGRCSV()
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
                                "Integer Integer64 Real String Date DateTime "
-                               "Time" );
+                               "Time IntegerList Integer64List RealList StringList" );
 
     poDriver->pfnOpen = OGRCSVDriverOpen;
     poDriver->pfnIdentify = OGRCSVDriverIdentify;
diff --git a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
index 11221bb..80f92f2 100644
--- a/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
+++ b/ogr/ogrsf_frmts/csv/ogrcsvlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcsvlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  CSV Translator
  * Purpose:  Implements OGRCSVLayer class.
@@ -28,14 +27,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_csv.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+#include <string>
+#include <vector>
+
 #include "cpl_conv.h"
-#include "cpl_string.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
 #include "ogr_p.h"
+#include "ogr_spatialref.h"
+#include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrcsvlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
-
+CPL_CVSID("$Id: ogrcsvlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                            CSVSplitLine()                            */
@@ -47,8 +68,8 @@ CPL_CVSID("$Id: ogrcsvlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 /************************************************************************/
 
 static char **CSVSplitLine( const char *pszString, char chDelimiter,
-                            int bKeepLeadingAndClosingQuotes,
-                            int bMergeDelimiter )
+                            bool bKeepLeadingAndClosingQuotes,
+                            bool bMergeDelimiter )
 
 {
     char **papszRetList = NULL;
@@ -116,7 +137,7 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter,
     }
 
     if( papszRetList == NULL )
-        papszRetList = (char **) CPLCalloc(sizeof(char *),1);
+        papszRetList = static_cast<char **>(CPLCalloc(sizeof(char *), 1));
 
     CPLFree( pszToken );
 
@@ -131,14 +152,14 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter,
 /************************************************************************/
 
 char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
-                             int bDontHonourStrings,
-                             int bKeepLeadingAndClosingQuotes,
-                             int bMergeDelimiter )
+                             bool bDontHonourStrings,
+                             bool bKeepLeadingAndClosingQuotes,
+                             bool bMergeDelimiter )
 
 {
     const char *pszLine = CPLReadLineL( fp );
     if( pszLine == NULL )
-        return( NULL );
+        return NULL;
 
     /* Skip BOM */
     const GByte* pabyData = reinterpret_cast<const GByte *>( pszLine );
@@ -146,7 +167,7 @@ char **OGRCSVReadParseLineL( VSILFILE * fp, char chDelimiter,
         pszLine += 3;
 
     // Special fix to read NdfcFacilities.xls with un-balanced double quotes.
-    if (chDelimiter == '\t' && bDontHonourStrings)
+    if( chDelimiter == '\t' && bDontHonourStrings )
     {
         return CSLTokenizeStringComplex(pszLine, "\t", FALSE, TRUE);
     }
@@ -223,34 +244,34 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
     poFeatureDefn(NULL),
     fpCSV(fp),
     nNextFID(1),
-    bHasFieldNames(FALSE),
-    bNew(bNewIn),
-    bInWriteMode(bInWriteModeIn),
-    bUseCRLF(FALSE),
-    bNeedRewindBeforeRead(FALSE),
+    bHasFieldNames(false),
+    bNew(CPL_TO_BOOL(bNewIn)),
+    bInWriteMode(CPL_TO_BOOL(bInWriteModeIn)),
+    bUseCRLF(false),
+    bNeedRewindBeforeRead(false),
     eGeometryFormat(OGR_CSV_GEOM_NONE),
     pszFilename(CPLStrdup(pszFilenameIn)),
-    bCreateCSVT(FALSE),
-    bWriteBOM(FALSE),
+    bCreateCSVT(false),
+    bWriteBOM(false),
     chDelimiter(chDelimiterIn),
     nCSVFieldCount(0),
     panGeomFieldIndex(NULL),
-    bFirstFeatureAppendedDuringSession(TRUE),
-    bHiddenWKTColumn(FALSE),
+    bFirstFeatureAppendedDuringSession(true),
+    bHiddenWKTColumn(false),
     iNfdcLongitudeS(-1),
     iNfdcLatitudeS(-1),
-    bDontHonourStrings(FALSE),
+    bDontHonourStrings(false),
     iLongitudeField(-1),
     iLatitudeField(-1),
     iZField(-1),
-    bIsEurostatTSV(FALSE),
+    bIsEurostatTSV(false),
     nEurostatDims(0),
-    nTotalFeatures( bNewIn ? 0 : -1 ),
-    bWarningBadTypeOrWidth(FALSE),
-    bKeepSourceColumns(FALSE),
-    bKeepGeomColumns(TRUE),
-    bMergeDelimiter(FALSE),
-    bEmptyStringNull(FALSE)
+    nTotalFeatures(bNewIn ? 0 : -1),
+    bWarningBadTypeOrWidth(false),
+    bKeepSourceColumns(false),
+    bKeepGeomColumns(true),
+    bMergeDelimiter(false),
+    bEmptyStringNull(false)
 {
     poFeatureDefn = new OGRFeatureDefn( pszLayerNameIn );
     SetDescription( poFeatureDefn->GetName() );
@@ -262,10 +283,10 @@ OGRCSVLayer::OGRCSVLayer( const char *pszLayerNameIn,
 /*                             Matches()                                */
 /************************************************************************/
 
-int OGRCSVLayer::Matches(const char* pszFieldName, char** papszPossibleNames)
+bool OGRCSVLayer::Matches( const char* pszFieldName, char** papszPossibleNames )
 {
     if( papszPossibleNames == NULL )
-        return FALSE;
+        return false;
     for(char** papszIter = papszPossibleNames; *papszIter; papszIter++)
     {
         const char* pszPattern = *papszIter;
@@ -273,7 +294,7 @@ int OGRCSVLayer::Matches(const char* pszFieldName, char** papszPossibleNames)
         if( pszStar == NULL )
         {
             if( EQUAL(pszFieldName, pszPattern) )
-                return TRUE;
+                return true;
         }
         else
         {
@@ -287,7 +308,7 @@ int OGRCSVLayer::Matches(const char* pszFieldName, char** papszPossibleNames)
                     oPattern.resize(oPattern.size()-1);
                     if( CPLString(pszFieldName).ifind(oPattern)
                         != std::string::npos )
-                        return TRUE;
+                        return true;
                 }
                 else
                 {
@@ -296,7 +317,7 @@ int OGRCSVLayer::Matches(const char* pszFieldName, char** papszPossibleNames)
                         EQUAL( pszFieldName + strlen(pszFieldName)
                                - (strlen(pszPattern)-1), pszPattern+1) )
                     {
-                        return TRUE;
+                        return true;
                     }
                 }
             }
@@ -304,11 +325,11 @@ int OGRCSVLayer::Matches(const char* pszFieldName, char** papszPossibleNames)
             {
                 // pattern*
                 if( EQUALN(pszFieldName, pszPattern, strlen(pszPattern)-1) )
-                    return TRUE;
+                    return true;
             }
         }
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -319,11 +340,9 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
                                     const char* pszGeonamesGeomFieldPrefix,
                                     char** papszOpenOptions )
 {
-
-    bMergeDelimiter
-        = CSLFetchBoolean(papszOpenOptions, "MERGE_SEPARATOR", FALSE);
-    bEmptyStringNull
-        = CSLFetchBoolean(papszOpenOptions, "EMPTY_STRING_AS_NULL", FALSE);
+    bMergeDelimiter = CPLFetchBool(papszOpenOptions, "MERGE_SEPARATOR", false);
+    bEmptyStringNull =
+        CPLFetchBool(papszOpenOptions, "EMPTY_STRING_AS_NULL", false);
 
 /* -------------------------------------------------------------------- */
 /*      If this is not a new file, read ahead to establish if it is     */
@@ -332,13 +351,13 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
     if( !bNew && bInWriteMode )
     {
         int nBytesRead = 0;
-        char chNewByte;
+        char chNewByte = '\0';
 
         while( nBytesRead < 10000 && VSIFReadL( &chNewByte, 1, 1, fpCSV ) == 1 )
         {
             if( chNewByte == 13 )
             {
-                bUseCRLF = TRUE;
+                bUseCRLF = true;
                 break;
             }
             nBytesRead ++;
@@ -380,43 +399,48 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
             const char* pszCSVHeaders
                 = CSLFetchNameValueDef(papszOpenOptions, "HEADERS", "AUTO");
 
-            if (EQUAL(pszCSVHeaders, "YES"))
-                bHasFieldNames = TRUE;
-            else if (EQUAL(pszCSVHeaders, "NO"))
-                bHasFieldNames = FALSE;
-            else {
-                // detect via checking for the presence of numeric values.
-                bHasFieldNames = TRUE;
+            if( EQUAL(pszCSVHeaders, "YES") )
+            {
+                bHasFieldNames = true;
+            }
+            else if( EQUAL(pszCSVHeaders, "NO") )
+            {
+                bHasFieldNames = false;
+            }
+            else
+            {
+                // Detect via checking for the presence of numeric values.
+                bHasFieldNames = true;
                 for( int iField = 0;
                      iField < nFieldCount && bHasFieldNames;
                      iField++ )
                 {
-                    const CPLValueType eType
-                        = CPLGetValueType(papszTokens[iField]);
+                    const CPLValueType eType =
+                        CPLGetValueType(papszTokens[iField]);
                     if ( (eType == CPL_VALUE_INTEGER ||
-                          eType == CPL_VALUE_REAL) ) {
+                          eType == CPL_VALUE_REAL) )
+                    {
                         // We have a numeric field, therefore do not consider
                         // the first line as field names.
-                        bHasFieldNames = FALSE;
+                        bHasFieldNames = false;
                     }
                 }
 
-                const CPLString osExt
-                    = OGRCSVDataSource::GetRealExtension(pszFilename);
+                const CPLString osExt =
+                    OGRCSVDataSource::GetRealExtension(pszFilename);
 
                 /* Eurostat .tsv files */
                 if( EQUAL(osExt, "tsv") && nFieldCount > 1 &&
                     strchr(papszTokens[0], ',') != NULL
                     && strchr(papszTokens[0], '\\') != NULL )
                 {
-                    bHasFieldNames = TRUE;
-                    bIsEurostatTSV = TRUE;
+                    bHasFieldNames = true;
+                    bIsEurostatTSV = true;
                 }
             }
 
             /* tokenize without quotes to get the actual values */
             CSLDestroy( papszTokens );
-            // papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, FALSE );
             int l_nFlags = CSLT_HONOURSTRINGS;
             if( !bMergeDelimiter )
                 l_nFlags |= CSLT_ALLOWEMPTYTOKENS;
@@ -425,7 +449,9 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
         }
     }
     else
-        bHasFieldNames = FALSE;
+    {
+        bHasFieldNames = false;
+    }
 
     if( !bNew )
         ResetReading();
@@ -491,11 +517,10 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
 
             nFieldCount = 0;
 
-            bDontHonourStrings = TRUE;
+            bDontHonourStrings = true;
         }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Search a csvt file for types                                    */
 /* -------------------------------------------------------------------- */
@@ -509,7 +534,7 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
         CPLFree(fname);
         if (fpCSVT!=NULL) {
             VSIRewindL(fpCSVT);
-            papszFieldTypes = OGRCSVReadParseLineL(fpCSVT, ',', FALSE,FALSE);
+            papszFieldTypes = OGRCSVReadParseLineL(fpCSVT, ',', false, false);
             VSIFCloseL(fpCSVT);
         }
     }
@@ -577,7 +602,8 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
             /* in the header line */
             if( iField == 1 && nFieldCount == 2 && papszTokens[1][0] == '\0' )
             {
-                nCSVFieldCount = nFieldCount = 1;
+                nCSVFieldCount = 1;
+                nFieldCount = 1;
                 break;
             }
             pszFieldName = szFieldNameBuffer;
@@ -684,6 +710,14 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
                     oField.SetType(OFTTime);
                 else if (EQUAL(papszFieldTypes[iField], "DateTime"))
                     oField.SetType(OFTDateTime);
+                else if (EQUAL(papszFieldTypes[iField], "JSonStringList"))
+                    oField.SetType(OFTStringList);
+                else if (EQUAL(papszFieldTypes[iField], "JSonIntegerList"))
+                    oField.SetType(OFTIntegerList);
+                else if (EQUAL(papszFieldTypes[iField], "JSonInteger64List"))
+                    oField.SetType(OFTInteger64List);
+                else if (EQUAL(papszFieldTypes[iField], "JSonRealList"))
+                    oField.SetType(OFTRealList);
                 else
                     CPLError( CE_Warning, CPLE_NotSupported,
                               "Unknown type : %s", papszFieldTypes[iField]);
@@ -737,6 +771,26 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
                 oGeomFieldDefn.SetType(wkbMultiLineString);
             else if( strstr(pszFieldName, "_MULTIPOLYGON") )
                 oGeomFieldDefn.SetType(wkbMultiPolygon);
+             else if( strstr(pszFieldName, "_CIRCULARSTRING") )
+                oGeomFieldDefn.SetType(wkbCircularString);
+            else if( strstr(pszFieldName, "_COMPOUNDCURVE") )
+                oGeomFieldDefn.SetType(wkbCompoundCurve);
+            else if( strstr(pszFieldName, "_CURVEPOLYGON") )
+                oGeomFieldDefn.SetType(wkbCurvePolygon);
+            else if( strstr(pszFieldName, "_CURVE") )
+                oGeomFieldDefn.SetType(wkbCurve);
+            else if( strstr(pszFieldName, "_SURFACE") )
+                oGeomFieldDefn.SetType(wkbSurface);
+            else if( strstr(pszFieldName, "_MULTICURVE") )
+                oGeomFieldDefn.SetType(wkbMultiCurve);
+            else if( strstr(pszFieldName, "_MULTISURFACE") )
+                oGeomFieldDefn.SetType(wkbMultiSurface);
+            else if( strstr(pszFieldName, "_POLYHEDRALSURFACE") )
+                oGeomFieldDefn.SetType(wkbPolyhedralSurface);
+            else if( strstr(pszFieldName, "_TIN") )
+                oGeomFieldDefn.SetType(wkbTIN);
+            else if( strstr(pszFieldName, "_TRIANGLE") )
+                oGeomFieldDefn.SetType(wkbTriangle);
 
             poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
             if( !bKeepGeomColumns )
@@ -830,13 +884,15 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
 
     if ( iNfdcLatitudeS != -1 && iNfdcLongitudeS != -1 )
     {
-        bDontHonourStrings = TRUE;
+        bDontHonourStrings = true;
         if( poFeatureDefn->GetGeomFieldCount() == 0 )
             poFeatureDefn->SetGeomType( wkbPoint );
         else
         {
-            iNfdcLatitudeS = iNfdcLongitudeS = -1;
-            iLatitudeField = iLongitudeField = -1;
+            iNfdcLatitudeS = -1;
+            iNfdcLongitudeS = -1;
+            iLatitudeField = -1;
+            iLongitudeField = -1;
         }
     }
     else if ( iLatitudeField != -1 && iLongitudeField != -1 )
@@ -845,8 +901,10 @@ void OGRCSVLayer::BuildFeatureDefn( const char* pszNfdcGeomField,
             poFeatureDefn->SetGeomType( (iZField >= 0) ? wkbPoint25D : wkbPoint );
         else
         {
-            iNfdcLatitudeS = iNfdcLongitudeS = -1;
-            iLatitudeField = iLongitudeField = -1;
+            iNfdcLatitudeS = -1;
+            iNfdcLongitudeS = -1;
+            iLatitudeField = -1;
+            iLongitudeField = -1;
         }
     }
 
@@ -966,26 +1024,34 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
             nBytes = INT_MAX;
     }
     else if( nBytes < 0 || (vsi_l_offset)nBytes < VSIFTellL(fpCSV) )
+    {
         nBytes = 1000000;
+    }
 
-    const char* pszAutodetectWidth
-        = CSLFetchNameValueDef(papszOpenOptions, "AUTODETECT_WIDTH", "NO");
-    int bAutodetectWidth = FALSE;
-    int bAutodetectWidthForIntOrReal = FALSE;
+    const char* pszAutodetectWidth =
+        CSLFetchNameValueDef(papszOpenOptions, "AUTODETECT_WIDTH", "NO");
+    bool bAutodetectWidth = false;
+    bool bAutodetectWidthForIntOrReal = false;
     if( EQUAL(pszAutodetectWidth, "YES") )
-        bAutodetectWidth = bAutodetectWidthForIntOrReal = TRUE;
+    {
+        bAutodetectWidth = true;
+        bAutodetectWidthForIntOrReal = true;
+    }
     else if( EQUAL(pszAutodetectWidth, "STRING_ONLY") )
-        bAutodetectWidth = TRUE;
+    {
+        bAutodetectWidth = true;
+    }
 
-    int bQuotedFieldAsString = CPLTestBool(
+    const bool bQuotedFieldAsString = CPLTestBool(
         CSLFetchNameValueDef( papszOpenOptions, "QUOTED_FIELDS_AS_STRING",
                               "NO" ) );
 
-    char* pszData = (char*) VSI_MALLOC_VERBOSE( nBytes );
+    char* pszData = static_cast<char *>( VSI_MALLOC_VERBOSE( nBytes ));
     if( pszData != NULL && (vsi_l_offset)nBytes > VSIFTellL(fpCSV) )
     {
-        int nRequested = nBytes - 1 - (int)VSIFTellL(fpCSV);
-        int nRead = static_cast<int>(VSIFReadL(pszData, 1, nRequested, fpCSV));
+        const int nRequested = nBytes - 1 - (int)VSIFTellL(fpCSV);
+        const int nRead =
+            static_cast<int>(VSIFReadL(pszData, 1, nRequested, fpCSV));
         pszData[nRead] = 0;
 
         CPLString osTmpMemFile(CPLSPrintf("/vsimem/tmp%p", this));
@@ -1009,7 +1075,7 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
         while( !VSIFEofL(fpMem) )
         {
             char** papszTokens = OGRCSVReadParseLineL( fpMem, chDelimiter,
-                                                       FALSE,
+                                                       false,
                                                        bQuotedFieldAsString,
                                                        bMergeDelimiter );
             /* Can happen if we just reach EOF while trying to read new bytes */
@@ -1024,8 +1090,8 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
                 break;
             }
 
-            for( int iField = 0; papszTokens[iField] != NULL &&
-                             iField < nFieldCount; iField++ )
+            for( int iField = 0; iField < nFieldCount &&
+                                 papszTokens[iField] != NULL; iField++ )
             {
                 if( papszTokens[iField][0] == 0 )
                     continue;
@@ -1085,14 +1151,17 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
                 {
                     OGRField sWrkField;
                     CPLPushErrorHandler(CPLQuietErrorHandler);
-                    int bSuccess = OGRParseDate( papszTokens[iField], &sWrkField, 0 );
+                    const bool bSuccess = CPL_TO_BOOL(
+                        OGRParseDate( papszTokens[iField], &sWrkField, 0 ));
                     CPLPopErrorHandler();
                     CPLErrorReset();
                     if( bSuccess )
                     {
-                        int bHasDate = strchr( papszTokens[iField], '/' ) != NULL ||
-                                       strchr( papszTokens[iField], '-' ) != NULL;
-                        int bHasTime = strchr( papszTokens[iField], ':' ) != NULL;
+                        const bool bHasDate =
+                            strchr( papszTokens[iField], '/' ) != NULL ||
+                            strchr( papszTokens[iField], '-' ) != NULL;
+                        const bool bHasTime =
+                            strchr( papszTokens[iField], ':' ) != NULL;
                         if( bHasDate && bHasTime )
                             eOGRFieldType = OFTDateTime;
                         else if( bHasDate )
@@ -1208,6 +1277,14 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
                 osFieldType = "Date";
             else if( aeFieldType[iField] == OFTTime  )
                 osFieldType = "Time";
+            else if( aeFieldType[iField] == OFTStringList  )
+                osFieldType = "JSonStringList";
+            else if( aeFieldType[iField] == OFTIntegerList  )
+                osFieldType = "JSonIntegerList";
+            else if( aeFieldType[iField] == OFTInteger64List  )
+                osFieldType = "JSonInteger64List";
+            else if( aeFieldType[iField] == OFTRealList  )
+                osFieldType = "JSonRealList";
             else if( abFieldBoolean[iField] )
                 osFieldType = "Integer(Boolean)";
             else
@@ -1223,9 +1300,9 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
                 {
                     osFieldType += CPLSPrintf(" (%d)", anFieldWidth[iField]);
                 }
-                else if ( anFieldWidth[iField] > 0 &&
-                        bAutodetectWidthForIntOrReal &&
-                        aeFieldType[iField] == OFTReal )
+                else if( anFieldWidth[iField] > 0 &&
+                         bAutodetectWidthForIntOrReal &&
+                         aeFieldType[iField] == OFTReal )
                 {
                     osFieldType += CPLSPrintf(" (%d.%d)", anFieldWidth[iField],
                                             anFieldPrecision[iField]);
@@ -1237,7 +1314,6 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
 
         VSIFCloseL(fpMem);
         VSIUnlink(osTmpMemFile);
-
     }
     VSIFree(pszData);
 
@@ -1246,7 +1322,6 @@ char** OGRCSVLayer::AutodetectFieldTypes(char** papszOpenOptions, int nFieldCoun
     return papszFieldTypes;
 }
 
-
 /************************************************************************/
 /*                            ~OGRCSVLayer()                            */
 /************************************************************************/
@@ -1285,9 +1360,10 @@ void OGRCSVLayer::ResetReading()
         VSIRewindL( fpCSV );
 
     if( bHasFieldNames )
-        CSLDestroy( OGRCSVReadParseLineL( fpCSV, chDelimiter, bDontHonourStrings ) );
+        CSLDestroy(
+            OGRCSVReadParseLineL( fpCSV, chDelimiter, bDontHonourStrings ) );
 
-    bNeedRewindBeforeRead = FALSE;
+    bNeedRewindBeforeRead = false;
 
     nNextFID = 1;
 }
@@ -1301,12 +1377,13 @@ char** OGRCSVLayer::GetNextLineTokens()
 /* -------------------------------------------------------------------- */
 /*      Read the CSV record.                                            */
 /* -------------------------------------------------------------------- */
-    char **papszTokens;
+    char **papszTokens = NULL;
 
     while( true )
     {
-        papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter, bDontHonourStrings,
-                                            FALSE, bMergeDelimiter );
+        papszTokens = OGRCSVReadParseLineL( fpCSV, chDelimiter,
+                                            bDontHonourStrings,
+                                            false, bMergeDelimiter );
         if( papszTokens == NULL )
             return NULL;
 
@@ -1359,35 +1436,34 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
 /* -------------------------------------------------------------------- */
 /*      Create the OGR feature.                                         */
 /* -------------------------------------------------------------------- */
-    OGRFeature *poFeature;
-
-    poFeature = new OGRFeature( poFeatureDefn );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
 /* -------------------------------------------------------------------- */
 /*      Set attributes for any indicated attribute records.             */
 /* -------------------------------------------------------------------- */
-    int         iAttr;
-    int         iOGRField = 0;
-    int         nAttrCount = MIN(CSLCount(papszTokens), nCSVFieldCount + (bHiddenWKTColumn ? 1 : 0) );
+    int iOGRField = 0;
+    const int nAttrCount =
+        std::min( CSLCount(papszTokens),
+                  nCSVFieldCount + (bHiddenWKTColumn ? 1 : 0) );
     CPLValueType eType;
 
-    for( iAttr = 0; !bIsEurostatTSV && iAttr < nAttrCount; iAttr++)
+    for( int iAttr = 0; !bIsEurostatTSV && iAttr < nAttrCount; iAttr++ )
     {
         if( (iAttr == iLongitudeField || iAttr == iLatitudeField || iAttr == iZField ) &&
             !bKeepGeomColumns )
         {
             continue;
         }
-        int iGeom;
+        int iGeom = 0;
         if( bHiddenWKTColumn )
         {
-            if(iAttr == 0)
-                iGeom = 0;
-            else
+            if(iAttr != 0)
                 iGeom = panGeomFieldIndex[iAttr - 1];
         }
         else
+        {
             iGeom = panGeomFieldIndex[iAttr];
+        }
         if( iGeom >= 0 )
         {
             if ( papszTokens[iAttr][0] != '\0'&&
@@ -1444,7 +1520,7 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
                 }
                 else if( !bWarningBadTypeOrWidth )
                 {
-                    bWarningBadTypeOrWidth = TRUE;
+                    bWarningBadTypeOrWidth = true;
                     CPLError(CE_Warning, CPLE_AppDefined,
                                 "Invalid value type found in record %d for field %s. "
                                 "This warning will no longer be emitted",
@@ -1468,24 +1544,28 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
                 {
                     poFeature->SetField( iOGRField, papszTokens[iAttr] );
                     if( !bWarningBadTypeOrWidth &&
-                        (eFieldType == OFTInteger || eFieldType == OFTInteger64) && eType == CPL_VALUE_REAL )
+                        (eFieldType == OFTInteger ||
+                         eFieldType == OFTInteger64) &&
+                        eType == CPL_VALUE_REAL )
                     {
-                        bWarningBadTypeOrWidth = TRUE;
+                        bWarningBadTypeOrWidth = true;
                         CPLError(CE_Warning, CPLE_AppDefined,
                                  "Invalid value type found in record %d for field %s. "
                                  "This warning will no longer be emitted",
                                  nNextFID, poFieldDefn->GetNameRef());
                     }
-                    else if( !bWarningBadTypeOrWidth && poFieldDefn->GetWidth() > 0 &&
+                    else if( !bWarningBadTypeOrWidth &&
+                             poFieldDefn->GetWidth() > 0 &&
                              (int)strlen(papszTokens[iAttr]) > poFieldDefn->GetWidth() )
                     {
-                        bWarningBadTypeOrWidth = TRUE;
+                        bWarningBadTypeOrWidth = true;
                         CPLError(CE_Warning, CPLE_AppDefined,
                                  "Value with a width greater than field width found in record %d for field %s. "
                                  "This warning will no longer be emitted",
                                  nNextFID, poFieldDefn->GetNameRef());
                     }
-                    else if( !bWarningBadTypeOrWidth && eType == CPL_VALUE_REAL &&
+                    else if( !bWarningBadTypeOrWidth &&
+                             eType == CPL_VALUE_REAL &&
                              poFieldDefn->GetWidth() > 0)
                     {
                         const char* pszDot = strchr(papszTokens[iAttr], '.');
@@ -1494,7 +1574,7 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
                             nPrecision = static_cast<int>(strlen(pszDot + 1));
                         if( nPrecision > poFieldDefn->GetPrecision() )
                         {
-                             bWarningBadTypeOrWidth = TRUE;
+                             bWarningBadTypeOrWidth = true;
                             CPLError(CE_Warning, CPLE_AppDefined,
                                      "Value with a precision greater than field precision found in record %d for field %s. "
                                      "This warning will no longer be emitted",
@@ -1506,11 +1586,12 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
                 {
                     if( !bWarningBadTypeOrWidth )
                     {
-                        bWarningBadTypeOrWidth = TRUE;
-                        CPLError(CE_Warning, CPLE_AppDefined,
-                                    "Invalid value type found in record %d for field %s. "
-                                    "This warning will no longer be emitted",
-                                    nNextFID, poFieldDefn->GetNameRef());
+                        bWarningBadTypeOrWidth = true;
+                        CPLError(
+                            CE_Warning, CPLE_AppDefined,
+                            "Invalid value type found in record %d for field "
+                            "%s. This warning will no longer be emitted.",
+                            nNextFID, poFieldDefn->GetNameRef());
                     }
                 }
             }
@@ -1520,9 +1601,10 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
             if (papszTokens[iAttr][0] != '\0' && !poFieldDefn->IsIgnored())
             {
                 poFeature->SetField( iOGRField, papszTokens[iAttr] );
-                if( !bWarningBadTypeOrWidth && !poFeature->IsFieldSet(iOGRField) )
+                if( !bWarningBadTypeOrWidth &&
+                    !poFeature->IsFieldSetAndNotNull(iOGRField) )
                 {
-                    bWarningBadTypeOrWidth = TRUE;
+                    bWarningBadTypeOrWidth = true;
                     CPLError(CE_Warning, CPLE_AppDefined,
                              "Invalid value type found in record %d for field %s. "
                              "This warning will no longer be emitted",
@@ -1530,20 +1612,24 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
                 }
             }
         }
-        else
+        else if( !poFieldDefn->IsIgnored() )
         {
-            if( !poFieldDefn->IsIgnored() &&
-                (!bEmptyStringNull || papszTokens[iAttr][0] != '\0') )
+            if( bEmptyStringNull && papszTokens[iAttr][0] == '\0' )
+            {
+                poFeature->SetFieldNull( iOGRField );
+            }
+            else
             {
                 poFeature->SetField( iOGRField, papszTokens[iAttr] );
                 if( !bWarningBadTypeOrWidth && poFieldDefn->GetWidth() > 0 &&
                     (int)strlen(papszTokens[iAttr]) > poFieldDefn->GetWidth() )
                 {
-                    bWarningBadTypeOrWidth = TRUE;
+                    bWarningBadTypeOrWidth = true;
                     CPLError(CE_Warning, CPLE_AppDefined,
-                                "Value with a width greater than field width found in record %d for field %s. "
-                                "This warning will no longer be emitted",
-                                nNextFID, poFieldDefn->GetNameRef());
+                             "Value with a width greater than field width "
+                             "found in record %d for field %s. "
+                             "This warning will no longer be emitted",
+                             nNextFID, poFieldDefn->GetNameRef());
                 }
             }
         }
@@ -1565,7 +1651,7 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
 /*      Eurostat TSV files.                                             */
 /* -------------------------------------------------------------------- */
 
-    for( iAttr = 0; bIsEurostatTSV && iAttr < nAttrCount; iAttr++)
+    for( int iAttr = 0; bIsEurostatTSV && iAttr < nAttrCount; iAttr++ )
     {
         if( iAttr == 0 )
         {
@@ -1663,7 +1749,6 @@ OGRFeature * OGRCSVLayer::GetNextUnfilteredFeature()
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -1726,7 +1811,8 @@ int OGRCSVLayer::TestCapability( const char * pszCap )
 /************************************************************************/
 
 OGRCSVCreateFieldAction OGRCSVLayer::PreCreateField( OGRFeatureDefn* poFeatureDefn,
-                                    OGRFieldDefn *poNewField, int bApproxOK )
+                                                     OGRFieldDefn *poNewField,
+                                                     int bApproxOK )
 {
 
 /* -------------------------------------------------------------------- */
@@ -1747,8 +1833,7 @@ OGRCSVCreateFieldAction OGRCSVLayer::PreCreateField( OGRFeatureDefn* poFeatureDe
     }
 
 /* -------------------------------------------------------------------- */
-/*      Is this a legal field type for CSV?  For now we only allow      */
-/*      simple integer, real and string fields.                         */
+/*      Is this a legal field type for CSV?                             */
 /* -------------------------------------------------------------------- */
     switch( poNewField->GetType() )
     {
@@ -1756,6 +1841,13 @@ OGRCSVCreateFieldAction OGRCSVLayer::PreCreateField( OGRFeatureDefn* poFeatureDe
       case OFTInteger64:
       case OFTReal:
       case OFTString:
+      case OFTIntegerList:
+      case OFTInteger64List:
+      case OFTRealList:
+      case OFTStringList:
+      case OFTTime:
+      case OFTDate:
+      case OFTDateTime:
         // these types are OK.
         break;
 
@@ -1816,7 +1908,6 @@ OGRErr OGRCSVLayer::CreateField( OGRFieldDefn *poNewField, int bApproxOK )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                          CreateGeomField()                           */
 /************************************************************************/
@@ -1888,14 +1979,14 @@ OGRErr OGRCSVLayer::WriteHeader()
 /*      Write field names if we haven't written them yet.               */
 /*      Write .csvt file if needed                                      */
 /* -------------------------------------------------------------------- */
-    bNew = FALSE;
-    bHasFieldNames = TRUE;
+    bNew = false;
+    bHasFieldNames = true;
     bool bOK = true;
 
-    for(int iFile=0;iFile<((bCreateCSVT) ? 2 : 1);iFile++)
+    for( int iFile = 0; iFile < (bCreateCSVT ? 2 : 1); iFile++ )
     {
         VSILFILE* fpCSVT = NULL;
-        if (bCreateCSVT && iFile == 0)
+        if( bCreateCSVT && iFile == 0 )
         {
             char* pszDirName = CPLStrdup(CPLGetDirname(pszFilename));
             char* pszBaseName = CPLStrdup(CPLGetBasename(pszFilename));
@@ -1920,7 +2011,7 @@ OGRErr OGRCSVLayer::WriteHeader()
             }
         }
 
-        if (bWriteBOM && fpCSV)
+        if( bWriteBOM && fpCSV )
         {
             bOK &= VSIFWriteL("\xEF\xBB\xBF", 1, 3, fpCSV) > 0;
         }
@@ -1964,23 +2055,21 @@ OGRErr OGRCSVLayer::WriteHeader()
 
         for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
         {
-            char *pszEscaped;
-
             if( iField > 0 || bHiddenWKTColumn )
             {
                 if (fpCSV) bOK &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
                 if (fpCSVT) bOK &= VSIFPrintfL( fpCSVT, "%s", ",") > 0;
             }
 
-            pszEscaped =
+            char *pszEscaped =
                 CPLEscapeString( poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
                                  -1, CPLES_CSV );
 
-            if (fpCSV)
+            if( fpCSV )
             {
-                int bAddDoubleQuote = FALSE;
+                bool bAddDoubleQuote = false;
                 if( chDelimiter == ' ' && pszEscaped[0] != '"' && strchr(pszEscaped, ' ') != NULL )
-                    bAddDoubleQuote = TRUE;
+                    bAddDoubleQuote = true;
                 if( bAddDoubleQuote )
                     bOK &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
                 bOK &= VSIFPrintfL( fpCSV, "%s", pszEscaped ) >= 0;
@@ -2029,6 +2118,10 @@ OGRErr OGRCSVLayer::WriteHeader()
                   case OFTDate:     bOK &= VSIFPrintfL( fpCSVT, "%s", "Date") > 0; break;
                   case OFTTime:     bOK &= VSIFPrintfL( fpCSVT, "%s", "Time") > 0; break;
                   case OFTDateTime: bOK &= VSIFPrintfL( fpCSVT, "%s", "DateTime") > 0; break;
+                  case OFTStringList:     bOK &= VSIFPrintfL( fpCSVT, "%s", "JSonStringList") > 0; break;
+                  case OFTIntegerList:     bOK &= VSIFPrintfL( fpCSVT, "%s", "JSonIntegerList") > 0; break;
+                  case OFTInteger64List:     bOK &= VSIFPrintfL( fpCSVT, "%s", "JSonInteger64List") > 0; break;
+                  case OFTRealList:     bOK &= VSIFPrintfL( fpCSVT, "%s", "JSonRealList") > 0; break;
                   default:          bOK &= VSIFPrintfL( fpCSVT, "%s", "String") > 0; break;
                 }
 
@@ -2073,8 +2166,6 @@ OGRErr OGRCSVLayer::WriteHeader()
 OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
 
 {
-    int iField;
-
     if( !bInWriteMode )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -2085,9 +2176,9 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
     /* If we need rewind, it means that we have just written a feature before */
     /* so there's no point seeking to the end of the file, as we're already */
     /* at the end */
-    int bNeedSeekEnd = !bNeedRewindBeforeRead;
+    bool bNeedSeekEnd = !bNeedRewindBeforeRead;
 
-    bNeedRewindBeforeRead = TRUE;
+    bNeedRewindBeforeRead = true;
 
 /* -------------------------------------------------------------------- */
 /*      Write field names if we haven't written them yet.               */
@@ -2098,7 +2189,7 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
         OGRErr eErr = WriteHeader();
         if (eErr != OGRERR_NONE)
             return eErr;
-        bNeedSeekEnd = FALSE;
+        bNeedSeekEnd = false;
     }
 
     if (fpCSV == NULL)
@@ -2108,18 +2199,18 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
 /* -------------------------------------------------------------------- */
 /*      Make sure we are at the end of the file.                        */
 /* -------------------------------------------------------------------- */
-    if (bNeedSeekEnd)
+    if( bNeedSeekEnd )
     {
-        if (bFirstFeatureAppendedDuringSession)
+        if( bFirstFeatureAppendedDuringSession )
         {
             /* Add a newline character to the end of the file if necessary */
-            bFirstFeatureAppendedDuringSession = FALSE;
+            bFirstFeatureAppendedDuringSession = false;
             bRet &= VSIFSeekL( fpCSV, 0, SEEK_END ) >= 0;
             bRet &= VSIFSeekL( fpCSV, VSIFTellL(fpCSV) - 1, SEEK_SET) >= 0;
-            char chLast;
+            char chLast = '\0';
             bRet &= VSIFReadL( &chLast, 1, 1, fpCSV ) > 0;
             bRet &= VSIFSeekL( fpCSV, 0, SEEK_END ) >= 0;
-            if (chLast != '\n')
+            if( chLast != '\n' )
             {
                 if( bUseCRLF )
                     bRet &= VSIFPutcL( 13, fpCSV ) != EOF;
@@ -2172,7 +2263,7 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
 /* -------------------------------------------------------------------- */
 /*      Special case to deal with hidden "WKT" geometry column          */
 /* -------------------------------------------------------------------- */
-    int bNonEmptyLine = FALSE;
+    bool bNonEmptyLine = false;
 
     if( bHiddenWKTColumn )
     {
@@ -2180,7 +2271,7 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
         OGRGeometry     *poGeom = poNewFeature->GetGeomFieldRef(0);
         if (poGeom && poGeom->exportToWkt(&pszWKT, wkbVariantIso) == OGRERR_NONE)
         {
-            bNonEmptyLine = TRUE;
+            bNonEmptyLine = true;
             bRet &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
             bRet &= VSIFWriteL( pszWKT, strlen(pszWKT), 1, fpCSV ) > 0;
             bRet &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
@@ -2191,10 +2282,9 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
 /* -------------------------------------------------------------------- */
 /*      Write out all the field values.                                 */
 /* -------------------------------------------------------------------- */
-
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
-        char *pszEscaped;
+        char *pszEscaped = NULL;
 
         if( iField > 0 || bHiddenWKTColumn )
             bRet &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
@@ -2207,7 +2297,8 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
             if (poGeom && poGeom->exportToWkt(&pszEscaped, wkbVariantIso) == OGRERR_NONE)
             {
                 int nLenWKT = (int)strlen(pszEscaped);
-                char* pszNew = (char*) CPLMalloc(1 + nLenWKT + 1 + 1);
+                char* pszNew = static_cast<char *>(
+                    CPLMalloc(1 + nLenWKT + 1 + 1));
                 pszNew[0] = '"';
                 memcpy(pszNew + 1, pszEscaped, nLenWKT);
                 pszNew[1 + nLenWKT] = '"';
@@ -2216,30 +2307,50 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
                 pszEscaped = pszNew;
             }
             else
+            {
                 pszEscaped = CPLStrdup("");
+            }
         }
-        else if (poFeatureDefn->GetFieldDefn(iField)->GetType() == OFTReal)
+        else
         {
-            if( poFeatureDefn->GetFieldDefn(iField)->GetSubType() == OFSTFloat32 &&
-                poNewFeature->IsFieldSet(iField) )
+            const OGRFieldType eType(poFeatureDefn->GetFieldDefn(iField)->GetType());
+            if ( eType == OFTReal)
+            {
+                if( poFeatureDefn->GetFieldDefn(iField)->GetSubType() == OFSTFloat32 &&
+                    poNewFeature->IsFieldSetAndNotNull(iField) )
+                {
+                    pszEscaped = CPLStrdup(CPLSPrintf("%.8g", poNewFeature->GetFieldAsDouble(iField)));
+                }
+                else
+                    pszEscaped = CPLStrdup(poNewFeature->GetFieldAsString(iField));
+            }
+            else if( eType == OFTStringList || eType == OFTIntegerList ||
+                     eType == OFTInteger64List || eType == OFTRealList )
             {
-                pszEscaped = CPLStrdup(CPLSPrintf("%.8g", poNewFeature->GetFieldAsDouble(iField)));
+                char* pszJSon = poNewFeature->GetFieldAsSerializedJSon(iField);
+                if( pszJSon )
+                {
+                    pszEscaped = CPLEscapeString( pszJSon, -1, CPLES_CSV );
+                }
+                else
+                {
+                    pszEscaped = CPLStrdup("");
+                }
+                CPLFree( pszJSon );
             }
             else
-                pszEscaped = CPLStrdup(poNewFeature->GetFieldAsString(iField));
-        }
-        else
-        {
-            pszEscaped =
-                CPLEscapeString( poNewFeature->GetFieldAsString(iField),
-                                -1, CPLES_CSV );
+            {
+                pszEscaped =
+                    CPLEscapeString( poNewFeature->GetFieldAsString(iField),
+                                    -1, CPLES_CSV );
+            }
         }
 
         int nLen = (int)strlen(pszEscaped);
-        bNonEmptyLine |= (nLen != 0);
-        int bAddDoubleQuote = FALSE;
+        bNonEmptyLine |= nLen != 0;
+        bool bAddDoubleQuote = false;
         if( chDelimiter == ' ' && pszEscaped[0] != '"' && strchr(pszEscaped, ' ') != NULL )
-            bAddDoubleQuote = TRUE;
+            bAddDoubleQuote = true;
         if( bAddDoubleQuote )
             bRet &= VSIFWriteL( "\"", 1, 1, fpCSV ) > 0;
         if( nLen )
@@ -2250,7 +2361,8 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
     }
 
     if( (poFeatureDefn->GetFieldCount() == 1 ||
-         (poFeatureDefn->GetFieldCount() == 0 && bHiddenWKTColumn)) && !bNonEmptyLine )
+         (poFeatureDefn->GetFieldCount() == 0 && bHiddenWKTColumn)) &&
+        !bNonEmptyLine )
         bRet &= VSIFPrintfL( fpCSV, "%c", chDelimiter ) > 0;
 
     if( bUseCRLF )
@@ -2267,7 +2379,7 @@ OGRErr OGRCSVLayer::ICreateFeature( OGRFeature *poNewFeature )
 /*                              SetCRLF()                               */
 /************************************************************************/
 
-void OGRCSVLayer::SetCRLF( int bNewValue )
+void OGRCSVLayer::SetCRLF( bool bNewValue )
 
 {
     bUseCRLF = bNewValue;
@@ -2281,11 +2393,11 @@ void OGRCSVLayer::SetWriteGeometry(OGRwkbGeometryType eGType,
                                    OGRCSVGeometryFormat eGeometryFormatIn,
                                    const char* pszGeomCol)
 {
-    this->eGeometryFormat = eGeometryFormatIn;
-    if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT && eGType != wkbNone )
+    eGeometryFormat = eGeometryFormatIn;
+    if( eGeometryFormat == OGR_CSV_GEOM_AS_WKT && eGType != wkbNone )
     {
         OGRGeomFieldDefn oGFld(pszGeomCol, eGType);
-        bHiddenWKTColumn = TRUE;
+        bHiddenWKTColumn = true;
         /* We don't use CreateGeomField() since we don't want to generate */
         /* a geometry field in first position, as it confuses applications */
         /* (such as MapServer <= 6.4) that assume that the first regular field */
@@ -2300,18 +2412,18 @@ void OGRCSVLayer::SetWriteGeometry(OGRwkbGeometryType eGType,
 /*                          SetCreateCSVT()                             */
 /************************************************************************/
 
-void OGRCSVLayer::SetCreateCSVT(int bCreateCSVTIn)
+void OGRCSVLayer::SetCreateCSVT( bool bCreateCSVTIn )
 {
-    this->bCreateCSVT = bCreateCSVTIn;
+    bCreateCSVT = bCreateCSVTIn;
 }
 
 /************************************************************************/
 /*                          SetWriteBOM()                               */
 /************************************************************************/
 
-void OGRCSVLayer::SetWriteBOM(int bWriteBOMIn)
+void OGRCSVLayer::SetWriteBOM( bool bWriteBOMIn )
 {
-    this->bWriteBOM = bWriteBOMIn;
+    bWriteBOM = bWriteBOMIn;
 }
 
 /************************************************************************/
@@ -2343,10 +2455,11 @@ GIntBig OGRCSVLayer::GetFeatureCount( int bForce )
         char szBuffer[4096+1];
 
         nTotalFeatures = 0;
-        int bLastWasNewLine = FALSE;
+        bool bLastWasNewLine = false;
         while( true )
         {
-            int nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 4096, fpCSV));
+            const int nRead =
+                static_cast<int>(VSIFReadL(szBuffer, 1, 4096, fpCSV));
             szBuffer[nRead] = 0;
             if( nTotalFeatures == 0 && szBuffer[0] != 13 && szBuffer[0] != 10 )
                 nTotalFeatures = 1;
@@ -2354,12 +2467,12 @@ GIntBig OGRCSVLayer::GetFeatureCount( int bForce )
             {
                 if( szBuffer[i] == 13 || szBuffer[i] == 10 )
                 {
-                    bLastWasNewLine = TRUE;
+                    bLastWasNewLine = true;
                 }
                 else if( bLastWasNewLine )
                 {
-                    nTotalFeatures ++;
-                    bLastWasNewLine = FALSE;
+                    nTotalFeatures++;
+                    bLastWasNewLine = false;
                 }
             }
 
diff --git a/ogr/ogrsf_frmts/csw/ogrcswdataset.cpp b/ogr/ogrsf_frmts/csw/ogrcswdataset.cpp
index a4ffc38..c8a95ee 100644
--- a/ogr/ogrsf_frmts/csw/ogrcswdataset.cpp
+++ b/ogr/ogrsf_frmts/csw/ogrcswdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrcswdataset.cpp 32983 2016-01-14 18:32:10Z goatbar $
  *
  * Project:  CSW Translator
  * Purpose:  Implements OGRCSWDriver.
@@ -34,7 +33,7 @@
 #include "ogr_p.h"
 #include "gmlutils.h"
 
-CPL_CVSID("$Id: ogrcswdataset.cpp 32983 2016-01-14 18:32:10Z goatbar $");
+CPL_CVSID("$Id: ogrcswdataset.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 extern "C" void RegisterOGRCSW();
 
@@ -56,28 +55,29 @@ class OGRCSWLayer : public OGRLayer
     int                 nFeatureRead;
     int                 nFeaturesInCurrentPage;
 
-    CPLString           osQuery, osCSWWhere;
+    CPLString           osQuery;
+    CPLString           osCSWWhere;
 
     GDALDataset*        FetchGetRecords();
     GIntBig             GetFeatureCountWithHits();
     void                BuildQuery();
 
   public:
-                        OGRCSWLayer(OGRCSWDataSource* poDS);
-                        ~OGRCSWLayer();
+               explicit OGRCSWLayer( OGRCSWDataSource* poDS );
+               virtual ~OGRCSWLayer();
 
-    virtual void                ResetReading();
-    virtual OGRFeature*         GetNextFeature();
-    virtual GIntBig             GetFeatureCount(int bForce = FALSE);
+    virtual void                ResetReading() override;
+    virtual OGRFeature*         GetNextFeature() override;
+    virtual GIntBig             GetFeatureCount( int bForce = FALSE ) override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int                 TestCapability( const char * ) { return FALSE; }
+    virtual int                 TestCapability( const char * ) override { return FALSE; }
 
-    virtual void                SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void                SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
-    virtual OGRErr              SetAttributeFilter( const char * );
+    virtual OGRErr              SetAttributeFilter( const char * ) override;
 };
 
 /************************************************************************/
@@ -94,23 +94,23 @@ class OGRCSWDataSource : public OGRDataSource
     int                 nMaxRecords;
 
     OGRCSWLayer*        poLayer;
-    int                 bFullExtentRecordsAsNonSpatial;
+    bool                bFullExtentRecordsAsNonSpatial;
 
     CPLHTTPResult*      SendGetCapabilities();
 
   public:
                         OGRCSWDataSource();
-                        ~OGRCSWDataSource();
+               virtual ~OGRCSWDataSource();
 
     int                 Open( const char * pszFilename,
                               char** papszOpenOptions );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return poLayer != NULL; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return poLayer != NULL; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * ) { return FALSE; }
+    virtual int                 TestCapability( const char * ) override { return FALSE; }
 
     CPLHTTPResult*              HTTPFetch( const char* pszURL, const char* pszPost );
 
@@ -118,7 +118,7 @@ class OGRCSWDataSource : public OGRDataSource
     const CPLString&            GetVersion() { return osVersion; }
     const CPLString&            GetElementSetName() { return osElementSetName; }
     const CPLString&            GetOutputSchema() { return osOutputSchema; }
-    int                         FullExtentRecordsAsNonSpatial() { return bFullExtentRecordsAsNonSpatial; }
+    bool                        FullExtentRecordsAsNonSpatial() { return bFullExtentRecordsAsNonSpatial; }
     int                         GetMaxRecords() { return nMaxRecords; }
 };
 
@@ -126,7 +126,7 @@ class OGRCSWDataSource : public OGRDataSource
 /*                           OGRCSWLayer()                              */
 /************************************************************************/
 
-OGRCSWLayer::OGRCSWLayer(OGRCSWDataSource* poDSIn) :
+OGRCSWLayer::OGRCSWLayer( OGRCSWDataSource* poDSIn ) :
     poDS(poDSIn),
     poFeatureDefn(new OGRFeatureDefn("records")),
     poBaseDS(NULL),
@@ -209,7 +209,7 @@ OGRCSWLayer::OGRCSWLayer(OGRCSWDataSource* poDSIn) :
         OGRFieldDefn oField("anytext", OFTString);
         poFeatureDefn->AddFieldDefn(&oField);
     }
-    if( poDS->GetOutputSchema().size() )
+    if( !poDS->GetOutputSchema().empty() )
     {
         OGRFieldDefn oField("raw_xml", OFTString);
         poFeatureDefn->AddFieldDefn(&oField);
@@ -284,7 +284,7 @@ OGRFeature* OGRCSWLayer::GetNextFeature()
             /* http://www.paikkatietohakemisto.fi/geonetwork/srv/en/csw returns URI ... */
             if( iSrcField < 0 && strcmp(pszFieldname, "references") == 0 )
                 iSrcField = poSrcFeature->GetFieldIndex("URI");
-            if( iSrcField >= 0 && poSrcFeature->IsFieldSet(iSrcField) )
+            if( iSrcField >= 0 && poSrcFeature->IsFieldSetAndNotNull(iSrcField) )
             {
                 OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
                 OGRFieldType eSrcType = poSrcFeature->GetFieldDefnRef(iSrcField)->GetType();
@@ -356,7 +356,7 @@ OGRFeature* OGRCSWLayer::GetNextFeature()
         poNewFeature->SetFID(nFeatureRead);
         delete poSrcFeature;
 
-        if( osCSWWhere.size() == 0 &&
+        if( osCSWWhere.empty() &&
             m_poAttrQuery != NULL &&
             !m_poAttrQuery->Evaluate( poNewFeature ) )
         {
@@ -441,7 +441,7 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
     CPLHTTPResult* psResult = NULL;
 
     CPLString osOutputSchema = poDS->GetOutputSchema();
-    if( osOutputSchema.size() )
+    if( !osOutputSchema.empty() )
         osOutputSchema = " outputSchema=\"" + osOutputSchema + "\"";
 
     CPLString osPost = CPLSPrintf(
@@ -500,7 +500,7 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
     osTmpFileName = osTmpDirName + "/file.gml";
 
     VSILFILE *fp = VSIFileFromMemBuffer( osTmpFileName, pabyData,
-                                    nDataLen, TRUE);
+                                         nDataLen, TRUE);
     VSIFCloseL(fp);
     psResult->pabyData = NULL;
 
@@ -508,7 +508,7 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
 
     GDALDataset* l_poBaseDS = NULL;
 
-    if( poDS->GetOutputSchema().size() )
+    if( !poDS->GetOutputSchema().empty() )
     {
         GDALDriver* poDrv = (GDALDriver*)GDALGetDriverByName("Memory");
         if( poDrv == NULL )
@@ -590,12 +590,13 @@ GDALDataset* OGRCSWLayer::FetchGetRecords()
                     CPLFree(psBBox->pszValue);
                     psBBox->pszValue = CPLStrdup("gml:Envelope");
                     CPLString osSRS = CPLGetXMLValue(psBBox, "crs", "");
-                    OGRGeometry* poGeom = GML2OGRGeometry_XMLNode( psBBox,
-                                                          FALSE,
-                                                          0, 0, false, true,
-                                                          false );
+                    OGRGeometry* poGeom =
+                        GML2OGRGeometry_XMLNode( psBBox,
+                                                 FALSE,
+                                                 0, 0, false, true,
+                                                 false );
                     bool bLatLongOrder = true;
-                    if( osSRS.size() )
+                    if( !osSRS.empty() )
                         bLatLongOrder = GML_IsSRSLatLongOrder(osSRS);
                     if( bLatLongOrder && CPLTestBool(
                             CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES")) )
@@ -774,7 +775,7 @@ OGRErr OGRCSWLayer::SetAttributeFilter( const char * pszFilter )
     else
         osCSWWhere = "";
 
-    if (m_poAttrQuery != NULL && osCSWWhere.size() == 0)
+    if (m_poAttrQuery != NULL && osCSWWhere.empty())
     {
         CPLDebug("CSW", "Using client-side only mode for filter \"%s\"", pszFilter);
         OGRErr eErr = OGRLayer::SetAttributeFilter(pszFilter);
@@ -794,11 +795,11 @@ OGRErr OGRCSWLayer::SetAttributeFilter( const char * pszFilter )
 
 void OGRCSWLayer::BuildQuery()
 {
-    if( m_poFilterGeom != NULL || osCSWWhere.size() != 0 )
+    if( m_poFilterGeom != NULL || !osCSWWhere.empty() )
     {
         osQuery = "<csw:Constraint version=\"1.1.0\">";
         osQuery += "<ogc:Filter>";
-        if( m_poFilterGeom != NULL && osCSWWhere.size() != 0 )
+        if( m_poFilterGeom != NULL && !osCSWWhere.empty() )
             osQuery += "<ogc:And>";
         if( m_poFilterGeom != NULL )
         {
@@ -822,7 +823,7 @@ void OGRCSWLayer::BuildQuery()
             osQuery += "</ogc:BBOX>";
         }
         osQuery += osCSWWhere;
-        if( m_poFilterGeom != NULL && osCSWWhere.size() != 0 )
+        if( m_poFilterGeom != NULL && !osCSWWhere.empty() )
             osQuery += "</ogc:And>";
         osQuery += "</ogc:Filter>";
         osQuery += "</csw:Constraint>";
@@ -839,7 +840,7 @@ OGRCSWDataSource::OGRCSWDataSource() :
     pszName(NULL),
     nMaxRecords(500),
     poLayer(NULL),
-    bFullExtentRecordsAsNonSpatial(FALSE)
+    bFullExtentRecordsAsNonSpatial(false)
 {}
 
 /************************************************************************/
@@ -863,11 +864,9 @@ CPLHTTPResult* OGRCSWDataSource::SendGetCapabilities()
     osURL = CPLURLAddKVP(osURL, "SERVICE", "CSW");
     osURL = CPLURLAddKVP(osURL, "REQUEST", "GetCapabilities");
 
-    CPLHTTPResult* psResult;
-
     CPLDebug("CSW", "%s", osURL.c_str());
 
-    psResult = HTTPFetch( osURL, NULL);
+    CPLHTTPResult* psResult = HTTPFetch( osURL, NULL);
     if (psResult == NULL)
     {
         return NULL;
@@ -911,9 +910,9 @@ int OGRCSWDataSource::Open( const char * pszFilename,
     osBaseURL = pszBaseURL;
     osElementSetName = CSLFetchNameValueDef(papszOpenOptionsIn, "ELEMENTSETNAME",
                                             "full");
-    bFullExtentRecordsAsNonSpatial = CSLFetchBoolean(papszOpenOptionsIn,
-                                                     "FULL_EXTENT_RECORDS_AS_NON_SPATIAL",
-                                                     FALSE);
+    bFullExtentRecordsAsNonSpatial =
+        CPLFetchBool(papszOpenOptionsIn,
+                     "FULL_EXTENT_RECORDS_AS_NON_SPATIAL", false);
     osOutputSchema = CSLFetchNameValueDef(papszOpenOptionsIn, "OUTPUT_SCHEMA", "");
     if( EQUAL(osOutputSchema, "gmd") )
         osOutputSchema = "http://www.isotc211.org/2005/gmd";
@@ -1078,4 +1077,3 @@ void RegisterOGRCSW()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/db2/GNUmakefile b/ogr/ogrsf_frmts/db2/GNUmakefile
index 6a8ddaa..25a568f 100644
--- a/ogr/ogrsf_frmts/db2/GNUmakefile
+++ b/ogr/ogrsf_frmts/db2/GNUmakefile
@@ -1,10 +1,10 @@
-include ../../../GDALmake.opt
-
-OBJ	=	ogrdb2cli.o gdaldb2rasterband.o ogrdb2datasourcemd.o ogrdb2driver.o ogrdb2datasource.o ogrdb2layer.o ogrdb2tablelayer.o ogrdb2selectlayer.o
-
-CPPFLAGS	:=	 -I.. -I../.. -I../../../frmts/mem $(CPPFLAGS)
-
-default:	$(O_OBJ:.o=.$(OBJ_EXT))
-
-clean:
-	rm -f *.o $(O_OBJ)
+include ../../../GDALmake.opt
+
+OBJ	=	ogrdb2cli.o gdaldb2rasterband.o ogrdb2datasourcemd.o ogrdb2driver.o ogrdb2datasource.o ogrdb2layer.o ogrdb2tablelayer.o ogrdb2selectlayer.o
+
+CPPFLAGS	:=	 -I.. -I../.. -I../../../frmts/mem $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
diff --git a/ogr/ogrsf_frmts/db2/drv_db2_raster.html b/ogr/ogrsf_frmts/db2/drv_db2_raster.html
index 6d93f0f..9955527 100644
--- a/ogr/ogrsf_frmts/db2/drv_db2_raster.html
+++ b/ogr/ogrsf_frmts/db2/drv_db2_raster.html
@@ -47,7 +47,7 @@ The GeoPackage standard uses a SQLite database file as a generic container, and
 run by a user with create authority on the database it is working with.</p>
 
 <p>The driver can also handle DB2 vectors. See
-<a href="drv_DB2.html">DB2 vector</a> documentation page</p>
+<a href="drv_db2.html">DB2 vector</a> documentation page</p>
 
 <p>Various kind of input datasets can be converted to DB2 raster :
 <ul>
@@ -380,7 +380,7 @@ Open a specific raster table in a DB2
 <h3>See Also</h3>
 
 <ul>
-<li> <a href="drv_DB2.html">DB2 vector</a> documentation page</li>
+<li> <a href="drv_db2.html">DB2 vector</a> documentation page</li>
 <li> <a href="frmt_various.html#PNG">PNG driver</a> documentation page</li>
 <li> <a href="frmt_jpeg.html">JPEG driver</a> documentation page</li>
 <li> <a href="frmt_webp.html">WEBP driver</a> documentation page</li>
diff --git a/ogr/ogrsf_frmts/db2/gdaldb2rasterband.cpp b/ogr/ogrsf_frmts/db2/gdaldb2rasterband.cpp
index b9af75c..73ddd41 100644
--- a/ogr/ogrsf_frmts/db2/gdaldb2rasterband.cpp
+++ b/ogr/ogrsf_frmts/db2/gdaldb2rasterband.cpp
@@ -31,6 +31,9 @@
 #include "ogr_db2.h"
 #include "memdataset.h"
 #include "gdal_alg_priv.h"
+
+CPL_CVSID("$Id: gdaldb2rasterband.cpp 37534 2017-03-01 16:50:58Z rouault $");
+
 static char* GByteArrayToHexString( const GByte* pabyData, int nLen);
 //#define DEBUG_VERBOSE
 
@@ -38,12 +41,12 @@ static char* GByteArrayToHexString( const GByte* pabyData, int nLen);
 /*                      GDALDB2RasterBand()                      */
 /************************************************************************/
 
-GDALDB2RasterBand::GDALDB2RasterBand(OGRDB2DataSource* poDS,
-                                     int nBand,
+GDALDB2RasterBand::GDALDB2RasterBand(OGRDB2DataSource* poDSIn,
+                                     int nBandIn,
                                      int nTileWidth, int nTileHeight)
 {
-    this->poDS = poDS;
-    this->nBand = nBand;
+    this->poDS = poDSIn;
+    this->nBand = nBandIn;
     eDataType = GDT_Byte;
     nBlockXSize = nTileWidth;
     nBlockYSize = nTileHeight;
@@ -138,6 +141,17 @@ GDALColorTable* GDALDB2RasterBand::GetColorTable()
                                   4,
                                   0);
 
+            if (nRetCode != SQL_SUCCESS)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Failed fetching tile_data; error: %s",
+                         oSession->GetLastError());
+                CPLDebug("OGRDB2DataSource::ReadTile",
+                         "Failed fetching tile_data; error: %s",
+                         oSession->GetLastError());
+                return NULL;
+            }
+
 // Allocate a buffer to read the tile BLOB into based on the
 // length(tile_data) value
             GByte* pabyBlob = (GByte*) VSIMalloc(nDataLen);
@@ -188,7 +202,6 @@ GDALColorTable* GDALDB2RasterBand::GetColorTable()
     }
 
     return poGDS->m_poCT;
-
 }
 
 /************************************************************************/
@@ -560,7 +573,7 @@ GByte* OGRDB2DataSource::ReadTile(int nRow, int nCol, GByte* pabyData,
                        "WHERE zoom_level = %d AND tile_row = %d "
                        "AND tile_column = %d%s",
                        m_osRasterTable.c_str(), m_nZoomLevel, nRow, nCol,
-                       m_osWHERE.size() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
+                       !m_osWHERE.empty() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
 
 #ifdef DEBUG_SQL
     CPLDebug("OGRDB2DataSource::ReadTile2",
@@ -602,6 +615,17 @@ GByte* OGRDB2DataSource::ReadTile(int nRow, int nCol, GByte* pabyData,
                               4,
                               0);
 
+        if (nRetCode != SQL_SUCCESS)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Failed fetching tile_data; error: %s",
+                     GetSession()->GetLastError());
+            CPLDebug("OGRDB2DataSource::ReadTile",
+                     "Failed fetching tile_data; error: %s",
+                     GetSession()->GetLastError());
+            return NULL;
+        }
+
 // Allocate a buffer to read the tile BLOB into based on the
 // length(tile_data) value
         GByte* pabyBlob = (GByte*) VSIMalloc(nDataLen);
@@ -643,6 +667,7 @@ GByte* OGRDB2DataSource::ReadTile(int nRow, int nCol, GByte* pabyData,
     {
         oStatement.Clear();
 
+#ifdef LATER
         if( m_hTempDB && (m_nShiftXPixelsMod || m_nShiftYPixelsMod) )
         {
             oStatement.Appendf(
@@ -725,6 +750,7 @@ GByte* OGRDB2DataSource::ReadTile(int nRow, int nCol, GByte* pabyData,
             }
         }
         else
+#endif
         {
             memset(pabyData, 0, nBands * nBlockSize );
         }
@@ -789,7 +815,6 @@ CPLErr GDALDB2RasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
         poGDS->m_asCachedTilesDesc[3].nCol = nColMin + 1;
         poGDS->m_asCachedTilesDesc[1].nIdxWithinTileData = -1;
         poGDS->m_asCachedTilesDesc[3].nIdxWithinTileData = -1;
-
     }
 
     for(int nRow = nRowMin; nRow <= nRowMax; nRow ++)
@@ -872,7 +897,6 @@ CPLErr GDALDB2RasterBand::IReadBlock(int nBlockXOff, int nBlockYOff,
 
                 if( poBlock )
                     poBlock->DropLock();
-
             }
         }
     }
@@ -1130,11 +1154,11 @@ CPLErr OGRDB2DataSource::WriteTileInternal()
     }
     else
     {
-        CPLAssert(0);
+        CPLAssert(false);
     }
 
-    GDALDriver* poDriver = (GDALDriver*) GDALGetDriverByName(pszDriverName);
-    if( poDriver != NULL)
+    GDALDriver* l_poDriver = (GDALDriver*) GDALGetDriverByName(pszDriverName);
+    if( l_poDriver != NULL)
     {
         GDALDataset* poMEMDS = MEMDataset::Create("", nBlockXSize, nBlockYSize,
                                0, GDT_Byte, NULL);
@@ -1349,7 +1373,7 @@ CPLErr OGRDB2DataSource::WriteTileInternal()
         VSIStatBufL sStat;
         CPLAssert(VSIStatL(osMemFileName, &sStat) != 0);
 #endif
-        GDALDataset* poOutDS = poDriver->CreateCopy(osMemFileName, poMEMDS,
+        GDALDataset* poOutDS = l_poDriver->CreateCopy(osMemFileName, poMEMDS,
                                FALSE, papszDriverOptions, NULL, NULL);
         CSLDestroy( papszDriverOptions );
         if( poOutDS )
@@ -1473,7 +1497,7 @@ CPLErr OGRDB2DataSource::FlushRemainingShiftedTiles()
     int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, strlen(pszSQL), &hStmt, NULL);
     if ( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
                   pszSQL, sqlite3_errmsg( m_hTempDB ) );
         return CE_Failure;
     }
@@ -1518,12 +1542,12 @@ CPLErr OGRDB2DataSource::FlushRemainingShiftedTiles()
                 char* pszNewSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
                                                   "WHERE zoom_level = %d AND tile_row = %d AND tile_column = %d%s",
                                                   m_osRasterTable.c_str(), m_nZoomLevel, nRow, nCol,
-                                                  m_osWHERE.size() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
+                                                  !m_osWHERE.empty() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
 #ifdef DEBUG_VERBOSE
                 CPLDebug("GPKG", "%s", pszNewSQL);
 #endif
                 sqlite3_stmt* hNewStmt = NULL;
-                rc = sqlite3_prepare(GetDB(), pszNewSQL, -1, &hNewStmt, NULL);
+                rc = sqlite3_prepare_v2(GetDB(), pszNewSQL, -1, &hNewStmt, NULL);
                 if ( rc == SQLITE_OK )
                 {
                     rc = sqlite3_step( hNewStmt );
@@ -1637,9 +1661,9 @@ CPLErr OGRDB2DataSource::FlushRemainingShiftedTiles()
 /*                         WriteShiftedTile()                           */
 /************************************************************************/
 
-CPLErr OGRDB2DataSource::WriteShiftedTile(int nRow, int nCol, int nBand,
-        int nDstXOffset, int nDstYOffset,
-        int nDstXSize, int nDstYSize)
+CPLErr OGRDB2DataSource::WriteShiftedTile(int /*nRow*/, int /*nCol*/, int /*nBand*/,
+        int /*nDstXOffset*/, int /*nDstYOffset*/,
+        int /*nDstXSize*/, int /*nDstYSize*/)
 {
 #ifdef LATER
     CPLAssert( m_nShiftXPixelsMod || m_nShiftYPixelsMod );
@@ -1725,7 +1749,7 @@ CPLErr OGRDB2DataSource::WriteShiftedTile(int nRow, int nCol, int nBand,
     int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, strlen(pszSQL), &hStmt, NULL);
     if ( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
                   pszSQL, sqlite3_errmsg( m_hTempDB ) );
         return CE_Failure;
     }
@@ -1812,7 +1836,7 @@ CPLErr OGRDB2DataSource::WriteShiftedTile(int nRow, int nCol, int nBand,
                 rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, strlen(pszSQL), &hStmt, NULL);
                 if ( rc != SQLITE_OK )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+                    CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
                               pszSQL, sqlite3_errmsg( m_hTempDB ) );
                     return CE_Failure;
                 }
@@ -2034,9 +2058,12 @@ CPLErr GDALDB2RasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
                 if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
                     poGDS->m_asCachedTilesDesc[0].abBandDirty[iBand - 1] = TRUE;
 
-                int nDstXOffset = 0, nDstXSize = nBlockXSize,
-                    nDstYOffset = 0, nDstYSize = nBlockYSize;
-                int nSrcXOffset = 0, nSrcYOffset = 0;
+                int nDstXOffset = 0;
+                int nDstXSize = nBlockXSize;
+                int nDstYOffset = 0;
+                int nDstYSize = nBlockYSize;
+                int nSrcXOffset = 0;
+                int nSrcYOffset = 0;
                 // Composite block data into tile data
                 if( poGDS->m_nShiftXPixelsMod == 0 && poGDS->m_nShiftYPixelsMod == 0 )
                 {
@@ -2139,8 +2166,9 @@ GDALRasterBand* GDALDB2RasterBand::GetOverview(int nIdx)
 static char* GByteArrayToHexString( const GByte* pabyData, int nLen)
 {
     char* pszTextBuf;
+    const size_t nBufLen = nLen*2+3;
 
-    pszTextBuf = (char *) CPLMalloc(nLen*2+3);
+    pszTextBuf = (char *) CPLMalloc(nBufLen);
 
     int  iSrc, iDst=0;
 
@@ -2148,12 +2176,12 @@ static char* GByteArrayToHexString( const GByte* pabyData, int nLen)
     {
         if( iSrc == 0 )
         {
-            sprintf( pszTextBuf+iDst, "0x%02x", pabyData[iSrc] );
+            snprintf( pszTextBuf+iDst, nBufLen - iDst, "0x%02x", pabyData[iSrc] );
             iDst += 4;
         }
         else
         {
-            sprintf( pszTextBuf+iDst, "%02x", pabyData[iSrc] );
+            snprintf( pszTextBuf+iDst, nBufLen - iDst, "%02x", pabyData[iSrc] );
             iDst += 2;
         }
     }
diff --git a/ogr/ogrsf_frmts/db2/ogr_db2.h b/ogr/ogrsf_frmts/db2/ogr_db2.h
index 52e37fc..afb7cee 100644
--- a/ogr/ogrsf_frmts/db2/ogr_db2.h
+++ b/ogr/ogrsf_frmts/db2/ogr_db2.h
@@ -84,7 +84,6 @@ class OGRDB2DataSource;
 #define DB2_DEBUG_EXIT(ogrdb2fn)
 #endif
 
-
 #define DB2ODBC_PREFIX "DB2ODBC:"
 
 #define UNKNOWN_SRID   -2
@@ -128,8 +127,7 @@ typedef enum
 #else
 #  define CPL_SQLULEN SQLUINTEGER
 #  define CPL_SQLLEN  SQLINTEGER
-#endif	/* ifdef SQLULEN */
-
+#endif  /* ifdef SQLULEN */
 
 /**
  * A class representing an ODBC database session.
@@ -156,7 +154,7 @@ protected:
 
 public:
     OGRDB2Session( );
-    ~OGRDB2Session();
+    virtual ~OGRDB2Session();
 // From CPLODBCSession
     int         EstablishSession( const char *pszDSN,
                                   const char *pszUserid,
@@ -217,13 +215,11 @@ protected:
     char         **m_papszColValues;
     CPL_SQLLEN       *m_panColValueLengths;
 
-
-
     char          *m_pszStatement;
     size_t         m_nStatementMax;
     size_t         m_nStatementLen;
 public:
-    OGRDB2Statement( OGRDB2Session * );
+    explicit OGRDB2Statement( OGRDB2Session * );
     OGRDB2Statement( );
     ~OGRDB2Statement();
     int             DB2Execute(const char *pszCallingFunction);
@@ -298,9 +294,6 @@ public:
 void OGRDB2AppendEscaped( OGRDB2Statement* poStatement,
                           const char* pszStrValue);
 
-
-
-
 /************************************************************************/
 /*                             OGRDB2Layer                              */
 /************************************************************************/
@@ -342,26 +335,26 @@ public:
     OGRDB2Layer();
     virtual             ~OGRDB2Layer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
     virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRFeatureDefn *GetLayerDefn() {
+    virtual OGRFeatureDefn *GetLayerDefn() override {
         return poFeatureDefn;
     }
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual OGRErr     StartTransaction();
-    virtual OGRErr     CommitTransaction();
-    virtual OGRErr     RollbackTransaction();
+    virtual OGRErr     StartTransaction() override;
+    virtual OGRErr     CommitTransaction() override;
+    virtual OGRErr     RollbackTransaction() override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
     char*               GByteArrayToHexString( const GByte* pabyData,
             int nLen);
 
@@ -387,15 +380,15 @@ class OGRDB2TableLayer : public OGRDB2Layer
     int                 bPreservePrecision;
     int                 bNeedSpatialIndex;
 
-    int                 nUploadGeometryFormat;
+    //int                 nUploadGeometryFormat;
     char                *m_pszQuery;
 
     void                ClearStatement();
     OGRDB2Statement* BuildStatement(const char* pszColumns);
-    void                FreeBindBuffer(int nBindNum, void **bind_buffer);
+    static void                FreeBindBuffer(int nBindNum, void **bind_buffer);
     CPLString BuildFields();
 
-    virtual OGRDB2Statement *  GetStatement();
+    virtual OGRDB2Statement *  GetStatement() override;
 
     char               *pszTableName;
     char               *m_pszLayerName;
@@ -404,30 +397,30 @@ class OGRDB2TableLayer : public OGRDB2Layer
     OGRwkbGeometryType eGeomType;
 
 // From GPKG
-    char*                       m_pszTableName;
+    //char*                       m_pszTableName;
     int                         m_iSrs;
-    OGREnvelope*                m_poExtent;
+    //OGREnvelope*                m_poExtent;
     CPLString                   m_soColumns;
     CPLString                   m_soFilter;
     CPLString                   osQuery;
-    OGRBoolean                  m_bExtentChanged;
+    //OGRBoolean                  m_bExtentChanged;
 
-    int                         m_bInsertStatementWithFID;
+    //int                         m_bInsertStatementWithFID;
 
-    int                         bDeferredSpatialIndexCreation;
-    int                         m_bHasSpatialIndex;
-    int                         bDropRTreeTable;
-    int                         m_anHasGeometryExtension[wkbMultiSurface+1];
-    int                         m_bPreservePrecision;
-    int                         m_bTruncateFields;
-    int                         m_bDeferredCreation;
-    int                         m_iFIDAsRegularColumnIndex;
+    //int                         bDeferredSpatialIndexCreation;
+    //int                         m_bHasSpatialIndex;
+    //int                         bDropRTreeTable;
+    //int                         m_anHasGeometryExtension[wkbMultiSurface+1];
+    //int                         m_bPreservePrecision;
+    //int                         m_bTruncateFields;
+    //int                         m_bDeferredCreation;
+    //int                         m_iFIDAsRegularColumnIndex;
 
     CPLString                   m_osIdentifierLCO;
     CPLString                   m_osDescriptionLCO;
-    int                         m_bHasReadMetadataFromStorage;
+    //int                         m_bHasReadMetadataFromStorage;
     OGRErr              RegisterGeometryColumn();
-    void                BuildWhere(void);
+    void                BuildWhere();
 //    OGRErr              SyncToDisk();
 
     OGRErr              BindFieldValue(OGRDB2Statement *poStatement,
@@ -435,8 +428,8 @@ class OGRDB2TableLayer : public OGRDB2Layer
                                        int nBindNum, void **papBindBuffer);
 
 public:
-    OGRDB2TableLayer( OGRDB2DataSource * );
-    ~OGRDB2TableLayer();
+    explicit OGRDB2TableLayer( OGRDB2DataSource * );
+    virtual ~OGRDB2TableLayer();
 
     CPLErr              Initialize( const char *pszSchema,
                                     const char *pszTableName,
@@ -445,22 +438,22 @@ public:
                                     int nSRId,
                                     const char *pszSRText,
                                     OGRwkbGeometryType eType);
-    OGRErr              isFieldTypeSupported( OGRFieldType nFieldType );
+    static OGRErr              isFieldTypeSupported( OGRFieldType nFieldType );
     OGRErr              CreateSpatialIndex();
     void                DropSpatialIndex();
 
-    virtual void        ResetReading();
-    virtual GIntBig         GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig         GetFeatureCount( int ) override;
 
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual const char* GetName();
+    virtual const char* GetName() override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
     virtual OGRErr      PrepareFeature( OGRFeature *poFeature, char cType );
 
     const char*         GetTableName() {
@@ -474,11 +467,11 @@ public:
     }
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     void                SetLaunderFlag( int bFlag )
     {
@@ -494,7 +487,7 @@ public:
     }
 
     int                 FetchSRSId();
-    void                CreateSpatialIndexIfNecessary();
+    //void                CreateSpatialIndexIfNecessary();
 
     int                 DropSpatialIndex(int bCalledFromSQLFunction = FALSE);
     /*
@@ -530,6 +523,7 @@ public:
                 const char* pszIdentifier,
                 const char* pszDescription );
     */
+    // cppcheck-suppress functionStatic
     OGRErr              RunDeferredCreationIfNecessary();
     /************************************************************************/
     /* GPKG methods */
@@ -543,7 +537,6 @@ private:
     void                CheckUnknownExtensions();
     int                 CreateGeometryExtensionIfNecessary(
                                 OGRwkbGeometryType eGType);
-
 };
 
 /************************************************************************/
@@ -557,21 +550,23 @@ class OGRDB2SelectLayer : public OGRDB2Layer
     void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual OGRDB2Statement *  GetStatement();
+    virtual OGRDB2Statement *  GetStatement() override;
 
 public:
     OGRDB2SelectLayer( OGRDB2DataSource *,
                        OGRDB2Statement * );
-    ~OGRDB2SelectLayer();
+    virtual ~OGRDB2SelectLayer();
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+     virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
+            { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -668,7 +663,7 @@ class OGRDB2DataSource : public GDALPamDataset
 
     CPLString           m_osWHERE;
 
-    int                 m_hTempDB;  //LATER - flag that partial_tiles exists
+    //int                 m_hTempDB;  //LATER - flag that partial_tiles exists
     CPLString           m_osTempDBFilename;
 
     int                 m_bInFlushCache;
@@ -734,7 +729,9 @@ class OGRDB2DataSource : public GDALPamDataset
     CPLErr                  WriteTile();
 
     CPLErr                  WriteTileInternal();
+    // cppcheck-suppress functionStatic
     CPLErr                  FlushRemainingShiftedTiles();
+    // cppcheck-suppress functionStatic
     CPLErr                  WriteShiftedTile(int nRow, int nCol, int iBand,
             int nDstXOffset, int nDstYOffset,
             int nDstXSize, int nDstYSize);
@@ -754,32 +751,29 @@ class OGRDB2DataSource : public GDALPamDataset
 
 public:
     OGRDB2DataSource();
-    ~OGRDB2DataSource();
+    virtual ~OGRDB2DataSource();
 //***************** For raster support
 
-    virtual char **     GetMetadata( const char *pszDomain = NULL );
+    virtual char **     GetMetadata( const char *pszDomain = NULL ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
-    virtual char **     GetMetadataDomainList();
+                                         const char * pszDomain = "" ) override;
+    virtual char **     GetMetadataDomainList() override;
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                          const char * pszValue,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
     CPLErr              FlushCacheWithErrCode();
 
+    virtual const char* GetProjectionRef() override;
+    virtual CPLErr      SetProjection( const char* pszProjection ) override;
 
-    virtual const char* GetProjectionRef();
-    virtual CPLErr      SetProjection( const char* pszProjection );
-
-    virtual CPLErr      GetGeoTransform( double* padfGeoTransform );
-    virtual CPLErr      SetGeoTransform( double* padfGeoTransform );
-
-
+    virtual CPLErr      GetGeoTransform( double* padfGeoTransform ) override;
+    virtual CPLErr      SetGeoTransform( double* padfGeoTransform ) override;
 
     virtual CPLErr      IBuildOverviews( const char *, int, int *,
                                          int, int *,
-                                         GDALProgressFunc, void * );
+                                         GDALProgressFunc, void * ) override;
 
     OGRErr              CreateGDALAspatialExtension();
     void                SetMetadataDirty() {
@@ -787,9 +781,11 @@ public:
     }
     /*
     */
+    // cppcheck-suppress functionStatic
     OGRErr              CreateExtensionsTableIfNecessary();
+    // cppcheck-suppress functionStatic
     int                 HasExtensionsTable();
-    virtual void        FlushCache();
+    virtual void        FlushCache() override;
     static GDALDataset* CreateCopy( const char *pszFilename,
                                     GDALDataset *poSrcDS,
                                     int bStrict,
@@ -803,7 +799,7 @@ public:
         return m_pszCatalog;
     }
 
-    int                 ParseValue(char** pszValue, char* pszSource,
+    static int                 ParseValue(char** pszValue, char* pszSource,
                                    const char* pszKey,
                                    int nStart, int nNext, int nTerm,
                                    int bRemove);
@@ -826,37 +822,39 @@ public:
     const char          *GetName() {
         return m_pszName;
     }
-    int                 GetLayerCount();
-    OGRLayer            *GetLayer( int );
-    OGRLayer            *GetLayerByName( const char* pszLayerName );
+    int                 GetLayerCount() override;
+    OGRLayer            *GetLayer( int ) override;
+    OGRLayer            *GetLayerByName( const char* pszLayerName ) override;
 
     int                 UseGeometryColumns() {
         return bUseGeometryColumns;
     }
 
-    virtual int         DeleteLayer( int iLayer );
+    virtual int         DeleteLayer( int iLayer ) override;
     virtual OGRLayer    *ICreateLayer( const char *,
                                        OGRSpatialReference * = NULL,
                                        OGRwkbGeometryType = wkbUnknown,
-                                       char ** = NULL );
+                                       char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    // cppcheck-suppress functionStatic
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     char                *LaunderName( const char *pszSrcName );
     char                *ToUpper( const char *pszSrcName );
+    // cppcheck-suppress functionStatic
     OGRErr              InitializeMetadataTables();
 
     OGRSpatialReference* FetchSRS( int nId );
     int                 FetchSRSId( OGRSpatialReference * poSRS );
 
-    OGRErr              StartTransaction(CPL_UNUSED int bForce);
-    OGRErr              CommitTransaction();
-    OGRErr              RollbackTransaction();
+    OGRErr              StartTransaction(CPL_UNUSED int bForce) override;
+    OGRErr              CommitTransaction() override;
+    OGRErr              RollbackTransaction() override;
     OGRErr              SoftStartTransaction();
     OGRErr              SoftCommitTransaction();
     OGRErr              SoftRollbackTransaction();
@@ -866,8 +864,6 @@ public:
     }
     int                 InitializeSession( const char * pszNewName,
                                            int bTestOpen );
-
-
 };
 
 /************************************************************************/
@@ -893,19 +889,19 @@ public:
                       int nTileWidth, int nTileHeight);
 
     virtual CPLErr          IReadBlock(int nBlockXOff, int nBlockYOff,
-                                       void* pData);
+                                       void* pData) override;
     virtual CPLErr          IWriteBlock(int nBlockXOff, int nBlockYOff,
-                                        void* pData);
-    virtual CPLErr          FlushCache();
+                                        void* pData) override;
+    virtual CPLErr          FlushCache() override;
 
-    virtual GDALColorTable* GetColorTable();
-    virtual CPLErr          SetColorTable(GDALColorTable* poCT);
+    virtual GDALColorTable* GetColorTable() override;
+    virtual CPLErr          SetColorTable(GDALColorTable* poCT) override;
 
-    virtual GDALColorInterp GetColorInterpretation();
-    virtual CPLErr          SetColorInterpretation( GDALColorInterp );
+    virtual GDALColorInterp GetColorInterpretation() override;
+    virtual CPLErr          SetColorInterpretation( GDALColorInterp ) override;
 
-    virtual int             GetOverviewCount();
-    virtual GDALRasterBand* GetOverview(int nIdx);
+    virtual int             GetOverviewCount() override;
+    virtual GDALRasterBand* GetOverview(int nIdx) override;
     char*           GByteArrayToHexString( const GByte* pabyData, int nLen);
 };
 #endif /* ndef OGR_DB2_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2cli.cpp b/ogr/ogrsf_frmts/db2/ogrdb2cli.cpp
index c5dd92c..9421c9c 100644
--- a/ogr/ogrsf_frmts/db2/ogrdb2cli.cpp
+++ b/ogr/ogrsf_frmts/db2/ogrdb2cli.cpp
@@ -33,6 +33,8 @@
 #include "cpl_string.h"
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: ogrdb2cli.cpp 36355 2016-11-20 22:54:34Z rouault $");
+
 #ifndef SQLColumns_TABLE_CAT
 #define SQLColumns_TABLE_CAT 1
 #define SQLColumns_TABLE_SCHEM 2
@@ -84,7 +86,6 @@ OGRDB2Session::~OGRDB2Session()
     CloseSession();
 }
 
-
 /************************************************************************/
 /*                       RollbackTransaction()                          */
 /************************************************************************/
@@ -351,8 +352,6 @@ const char *OGRDB2Session::GetLastError()
     return m_szLastError;
 }
 
-
-
 /************************************************************************/
 /* ==================================================================== */
 /*                           OGRDB2Statement                           */
@@ -367,6 +366,7 @@ OGRDB2Statement::OGRDB2Statement( OGRDB2Session *poSession )
 
 {
     DB2_DEBUG_ENTER("OGRDB2Statement::OGRDB2Statement");
+    m_nLastRetCode = 0;
     m_bPrepared = FALSE;
 
     m_poSession = poSession;
@@ -485,8 +485,9 @@ int OGRDB2Statement::DB2Execute(const char *pszCallingFunction)
     if (m_bPrepared)
     {
         m_nLastRetCode = SQLExecute(m_hStmt);
-
-    } else {
+    }
+    else
+    {
         m_nLastRetCode = SQLExecDirect( m_hStmt, (SQLCHAR *) m_pszStatement, SQL_NTS );
     }
 
@@ -499,7 +500,6 @@ int OGRDB2Statement::DB2Execute(const char *pszCallingFunction)
     return CollectResultsInfo();
 }
 
-
 /************************************************************************/
 /*                             ExecuteSQL()                             */
 /************************************************************************/
@@ -858,7 +858,6 @@ int OGRDB2Statement::Fetch( int nOrientation, int nOffset )
                           m_poSession->GetLastError() );
             }
 
-
             return FALSE;
         }
     }
@@ -936,7 +935,6 @@ int OGRDB2Statement::Fetch( int nOrientation, int nOffset )
                     while ((cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0)
                         && (szWrkData[cbDataLen - 2] == 0))
                         cbDataLen -= 2; // trimming the extra terminators
-
             }
 
             m_papszColValues[iCol] = (char *) CPLMalloc(cbDataLen+2);
@@ -1189,7 +1187,7 @@ void OGRDB2Statement::Append( const char *pszText )
         }
         else
         {
-            m_pszStatement = (char *) VSIRealloc(m_pszStatement, m_nStatementMax);
+            m_pszStatement = (char *) CPLRealloc(m_pszStatement, m_nStatementMax);
         }
     }
 
@@ -1377,7 +1375,6 @@ void OGRDB2Statement::Clear()
         CPLFree( m_panColValueLengths );
         m_panColValueLengths = NULL;
     }
-
 }
 
 /************************************************************************/
@@ -1845,5 +1842,3 @@ SQLSMALLINT OGRDB2Statement::GetTypeMapping( SQLSMALLINT nTypeCode )
             return SQL_C_CHAR;
     }
 }
-
-
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2datasource.cpp b/ogr/ogrsf_frmts/db2/ogrdb2datasource.cpp
index e9b1aa9..9f7adb4 100644
--- a/ogr/ogrsf_frmts/db2/ogrdb2datasource.cpp
+++ b/ogr/ogrsf_frmts/db2/ogrdb2datasource.cpp
@@ -28,6 +28,9 @@
  ****************************************************************************/
 
 #include "ogr_db2.h"
+
+CPL_CVSID("$Id: ogrdb2datasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 static GPKGTileFormat GetTileFormat(const char* pszTF );
 
 /* layer status */
@@ -36,7 +39,6 @@ static GPKGTileFormat GetTileFormat(const char* pszTF );
 #define DB2LAYERSTATUS_CREATED  2
 #define DB2LAYERSTATUS_DISABLED 3
 
-
 /************************************************************************/
 /*                             Tiling schemes                           */
 /************************************************************************/
@@ -185,7 +187,7 @@ OGRDB2DataSource::OGRDB2DataSource()
     m_pabyHugeColorArray = NULL;
     m_poCT = NULL;
     m_bInWriteTile = FALSE;
-    m_hTempDB = NULL;
+    //m_hTempDB = NULL;
     m_bInFlushCache = FALSE;
     m_nTileInsertionCount = 0;
     m_osTilingScheme = "CUSTOM";
@@ -212,7 +214,7 @@ OGRDB2DataSource::~OGRDB2DataSource()
 
     if (!m_bIsVector)
     {
-        if( m_poParentDS == NULL && m_osRasterTable.size() &&
+        if( m_poParentDS == NULL && !m_osRasterTable.empty() &&
                 !m_bGeoTransformValid )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -235,7 +237,6 @@ OGRDB2DataSource::~OGRDB2DataSource()
         if( m_papoSRS[i] != NULL )
             CPLDebug("OGRDB2DataSource::~OGRDB2DataSource","m_papoSRS[%d] is not null", i);
 //LATER            m_papoSRS[i]->Release(); //fails for some reason
-
     }
     CPLFree( m_panSRID );
     CPLFree( m_papoSRS );
@@ -272,6 +273,8 @@ int OGRDB2DataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) || EQUAL(pszCap,ODsCDeleteLayer) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -342,7 +345,6 @@ OGRLayer *OGRDB2DataSource::GetLayerByName( const char* pszLayerName )
     return poLayer;
 }
 
-
 /************************************************************************/
 /*                    DeleteLayer(OGRDB2TableLayer * poLayer)           */
 /************************************************************************/
@@ -396,7 +398,6 @@ int OGRDB2DataSource::DeleteLayer( OGRDB2TableLayer * poLayer )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                            DeleteLayer(int iLayer)                   */
 /************************************************************************/
@@ -408,7 +409,6 @@ int OGRDB2DataSource::DeleteLayer( int iLayer )
         return OGRERR_FAILURE;
 
     return DeleteLayer(m_papoLayers[iLayer]);
-
 }
 
 /************************************************************************/
@@ -450,7 +450,6 @@ OGRLayer * OGRDB2DataSource::ICreateLayer( const char * pszLayerName,
 
         /* For now, always convert layer name to uppercase table name*/
         pszTableName = ToUpper( pszDotPos + 1 );
-
     }
     else
     {
@@ -465,7 +464,6 @@ OGRLayer * OGRDB2DataSource::ICreateLayer( const char * pszLayerName,
         pszSchemaName = CPLStrdup(CSLFetchNameValue(papszOptions, "SCHEMA"));
     }
 
-
     /* -------------------------------------------------------------------- */
     /*      Do we already have this layer?  If so, should we blow it        */
     /*      away?                                                           */
@@ -516,7 +514,6 @@ OGRLayer * OGRDB2DataSource::ICreateLayer( const char * pszLayerName,
     if (!pszGeomColumn)
         pszGeomColumn = "OGR_geometry";
 
-
     /* -------------------------------------------------------------------- */
     /*      Try to get the SRS Id of this spatial reference system,         */
     /*      adding to the srs table if needed.                              */
@@ -574,13 +571,11 @@ OGRLayer * OGRDB2DataSource::ICreateLayer( const char * pszLayerName,
     /* -------------------------------------------------------------------- */
     /*      Create the layer object.                                        */
     /* -------------------------------------------------------------------- */
-    OGRDB2TableLayer   *poLayer;
+    OGRDB2TableLayer *poLayer = new OGRDB2TableLayer( this );
 
-    poLayer = new OGRDB2TableLayer( this );
-
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
-    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",
-                               TRUE));
+    poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", true) );
+    poLayer->SetPrecisionFlag(
+        CPLFetchBool(papszOptions, "PRECISION", true));
 
     char *pszWKT = NULL;
     if( poSRS && poSRS->exportToWkt( &pszWKT ) != OGRERR_NONE )
@@ -612,7 +607,6 @@ OGRLayer * OGRDB2DataSource::ICreateLayer( const char * pszLayerName,
 
     m_papoLayers[m_nLayers++] = poLayer;
 
-
     return poLayer;
 }
 
@@ -651,7 +645,6 @@ int OGRDB2DataSource::OpenTable( const char *pszSchemaName,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                       GetLayerCount()                                */
 /************************************************************************/
@@ -744,10 +737,10 @@ int OGRDB2DataSource::Create( const char * pszFilename,
         }
     }
 
-    int bFileExists = FALSE;
+    //int bFileExists = FALSE;
     if( VSIStatL( pszFilename, &sStatBuf ) == 0 )
     {
-        bFileExists = TRUE;
+        //bFileExists = TRUE;
         if( nBandsIn == 0 ||
                 !CPLTestBool(CSLFetchNameValueDef(papszOptions, "APPEND_SUBDATASET", "NO")) )
         {
@@ -813,7 +806,7 @@ int OGRDB2DataSource::Create( const char * pszFilename,
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Error creating layer: %s", GetSession()->GetLastError() );
             CPLDebug("OGR_DB2DataSource::Create", "create failed");
-            return NULL;
+            return FALSE;
         }
 
         // Remove entries from raster catalog tables - will cascade
@@ -854,7 +847,7 @@ int OGRDB2DataSource::Create( const char * pszFilename,
         CPLDebug("OGR_DB2DataSource::Create","setting metadata PIXEL");
         GDALPamDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
         GDALPamDataset::SetMetadataItem("IDENTIFIER", m_osIdentifier);
-        if( m_osDescription.size() )
+        if( !m_osDescription.empty() )
             GDALPamDataset::SetMetadataItem("DESCRIPTION", m_osDescription);
 
         const char* pszTF = CSLFetchNameValue(papszOptions, "TILE_FORMAT");
@@ -910,13 +903,8 @@ int OGRDB2DataSource::Create( const char * pszFilename,
     }
     CPLDebug("OGR_DB2DataSource::Create","exiting");
     return TRUE;
-
-
 }
 
-
-
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -962,7 +950,7 @@ int OGRDB2DataSource::Open( GDALOpenInfo* poOpenInfo )
         if( CSLFetchNameValue( poOpenInfo->papszOpenOptions, "TABLE") ) {
             osSubdatasetTableName = CSLFetchNameValue( poOpenInfo->papszOpenOptions, "TABLE");
         }
-        if( osSubdatasetTableName.size() )
+        if( !osSubdatasetTableName.empty() )
         {
             oStatement.Appendf(" AND c.table_name='%s'", osSubdatasetTableName.c_str());
             SetPhysicalFilename( osFilename.c_str() ); //LATER
@@ -1082,8 +1070,6 @@ int OGRDB2DataSource::InitializeSession( const char * pszNewName,
 
     m_pszName = CPLStrdup(pszNewName);
 
-
-
     // if the table parameter was specified, pull out the table names
     if( pszTableSpec != NULL )
     {
@@ -1092,7 +1078,6 @@ int OGRDB2DataSource::InitializeSession( const char * pszNewName,
 
         papszTableList = CSLTokenizeString2( pszTableSpec, ",", 0 );
 
-
         for( i = 0; i < CSLCount(papszTableList); i++ )
         {
             char      **papszQualifiedParts;
@@ -1282,7 +1267,6 @@ int OGRDB2DataSource::Open( const char * pszNewName,
         }
     }
 
-
     /* Determine the available tables if not specified. */
     if (m_papszTableNames == NULL)
     {
@@ -1374,7 +1358,7 @@ int OGRDB2DataSource::Open( const char * pszNewName,
                             && oStatement2.Fetch() )
                     {
                         if ( oStatement2.GetColData( 0 ) )
-                            pszSRText = CPLStrdup(oStatement2.GetColData( 0 ));;
+                            pszSRText = CPLStrdup(oStatement2.GetColData( 0 ));
                     }
                 }
                 if (nSRId < 0) { // something went wrong - didn't find srid - use default
@@ -1459,7 +1443,6 @@ OGRLayer * OGRDB2DataSource::ExecuteSQL( const char *pszSQLCommand,
     CPLDebug( "OGRDB2DataSource::ExecuteSQL", "ExecuteSQL(%s) called.",
               pszSQLCommand );
 
-
     /* Execute the command natively */
     OGRDB2Statement *poStatement = new OGRDB2Statement( &m_oSession );
     poStatement->Append( pszSQLCommand );
@@ -1561,10 +1544,8 @@ OGRErr OGRDB2DataSource::InitializeMetadataTables()
               "Dynamically creating DB2 spatial metadata tables is "
               "not supported" );
     return OGRERR_FAILURE;
-
 }
 
-
 /************************************************************************/
 /*                              FetchSRS()                              */
 /*                                                                      */
@@ -1667,6 +1648,7 @@ int OGRDB2DataSource::FetchSRSId( OGRSpatialReference * poSRS)
         return 0;
 
     OGRSpatialReference oSRS(*poSRS);
+    // cppcheck-suppress uselessAssignmentPtrArg
     poSRS = NULL;
 
     pszAuthorityName = oSRS.GetAuthorityName(NULL);
@@ -2004,7 +1986,6 @@ int OGRDB2DataSource::OpenRaster( const char* pszTableName,
         pszContentsMinY = osContentsMinY.c_str();
         pszContentsMaxX = osContentsMaxX.c_str();
         pszContentsMaxY = osContentsMaxY.c_str();
-
     }
 
     if(! InitRaster ( NULL, pszTableName, dfMinX, dfMinY, dfMaxX, dfMaxY,
@@ -2076,7 +2057,6 @@ int OGRDB2DataSource::OpenRaster( const char* pszTableName,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                         InitRaster()                                 */
 /************************************************************************/
@@ -2102,7 +2082,6 @@ int OGRDB2DataSource::InitRaster ( OGRDB2DataSource* poParentDS,
     if (nIdxInResult > 0) {
         CPLDebug("OGRDB2DataSource::InitRaster1",
                  "Serious problem as we don't support nIdxInResult");
-
     }
     int nZoomLevel = atoi(oStatement->GetColData( 0));
     double dfPixelXSize = CPLAtof(oStatement->GetColData( 1));
@@ -2217,7 +2196,6 @@ int OGRDB2DataSource::InitRaster ( OGRDB2DataSource* poParentDS,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                         GetTileFormat()                              */
 /************************************************************************/
@@ -2265,12 +2243,11 @@ int OGRDB2DataSource::RegisterWebPExtension()
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                    CheckUnknownExtensions()                          */
 /************************************************************************/
 
-void OGRDB2DataSource::CheckUnknownExtensions(int bCheckRasterTable)
+void OGRDB2DataSource::CheckUnknownExtensions(int /*bCheckRasterTable*/)
 {
     if( !HasExtensionsTable() )
         return;
@@ -2366,7 +2343,6 @@ void OGRDB2DataSource::ParseCompressionOptions(char** papszOptions)
         m_bDither = CPLTestBool(pszDither);
 }
 
-
 /************************************************************************/
 /*                      ComputeTileAndPixelShifts()                     */
 /************************************************************************/
@@ -2384,10 +2360,8 @@ void OGRDB2DataSource::ComputeTileAndPixelShifts()
     int nShiftYPixels = (int)floor(0.5 + (m_adfGeoTransform[3] - m_dfTMSMaxY) /  m_adfGeoTransform[5]);
     m_nShiftYTiles = (int)floor(1.0 * nShiftYPixels / nTileHeight);
     m_nShiftYPixelsMod = ((nShiftYPixels % nTileHeight) + nTileHeight) % nTileHeight;
-
 }
 
-
 /************************************************************************/
 /*                  CreateExtensionsTableIfNecessary()                  */
 /************************************************************************/
@@ -2419,7 +2393,6 @@ OGRErr OGRDB2DataSource::CreateExtensionsTableIfNecessary()
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                         HasExtensionsTable()                         */
 /************************************************************************/
@@ -2448,7 +2421,6 @@ void OGRDB2DataSource::FlushCache()
     DB2_DEBUG_ENTER("OGRDB2DataSource::FlushCache");
     FlushCacheWithErrCode();
     DB2_DEBUG_EXIT("OGRDB2DataSource::FlushCache");
-
 }
 
 CPLErr OGRDB2DataSource::FlushCacheWithErrCode()
@@ -2499,10 +2471,8 @@ CPLErr OGRDB2DataSource::FlushCacheWithErrCode()
     CPLDebug("OGRDB2DataSource::FlushCacheWithErrCode","exiting; eErr: %d", eErr);
 
     return eErr;
-
 }
 
-
 /************************************************************************/
 /*                         SoftStartTransaction()                       */
 /************************************************************************/
@@ -2513,8 +2483,6 @@ int OGRDB2DataSource::SoftStartTransaction()
     return m_oSession.BeginTransaction();
 }
 
-
-
 /************************************************************************/
 /*                         SoftCommitTransaction()                      */
 /************************************************************************/
@@ -2525,8 +2493,6 @@ int OGRDB2DataSource::SoftCommitTransaction()
     return m_oSession.CommitTransaction();
 }
 
-
-
 /************************************************************************/
 /*                         SoftRollbackTransaction()                    */
 /************************************************************************/
@@ -2537,8 +2503,6 @@ int OGRDB2DataSource::SoftRollbackTransaction()
     return m_oSession.RollbackTransaction();
 }
 
-
-
 /************************************************************************/
 /*                            CreateCopy()                              */
 /************************************************************************/
@@ -2559,7 +2523,7 @@ static const WarpResamplingAlg asResamplingAlg[] =
     { "AVERAGE", GRA_Average },
 };
 
-void DumpStringList(char **papszStrList)
+static void DumpStringList(char **papszStrList)
 {
     if (papszStrList == NULL)
         return ;
@@ -2572,8 +2536,6 @@ void DumpStringList(char **papszStrList)
     return ;
 }
 
-
-
 GDALDataset* OGRDB2DataSource::CreateCopy( const char *pszFilename,
         GDALDataset *poSrcDS,
         int bStrict,
@@ -2868,7 +2830,6 @@ GDALDataset* OGRDB2DataSource::CreateCopy( const char *pszFilename,
     return poDS;
 }
 
-
 /************************************************************************/
 /*                         GetProjectionRef()                           */
 /************************************************************************/
@@ -2910,7 +2871,6 @@ CPLErr OGRDB2DataSource::SetProjection( const char* pszProjection )
         if( oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE )
             return CE_Failure;
         nSRID = FetchSRSId( &oSRS );
-        nSRID = FetchSRSId( &oSRS );
     }
 
     for(size_t iScheme = 0;
@@ -2946,12 +2906,12 @@ CPLErr OGRDB2DataSource::SetProjection( const char* pszProjection )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Set projection failed in gpkg.contents "
-                     "for table %s; ",
+                     "for table %s: %s",
                      m_osRasterTable.c_str(),
                      GetSession()->GetLastError());
             CPLDebug("OGRDB2DataSource::SetProjection",
                      "Set projection failed in gpkg.contents "
-                     "for table %s; ",
+                     "for table %s: %s",
                      m_osRasterTable.c_str(),
                      GetSession()->GetLastError());
             return CE_Failure;
@@ -2965,12 +2925,12 @@ CPLErr OGRDB2DataSource::SetProjection( const char* pszProjection )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Set projection in gpkg.tile_matrix_set failed "
-                     "for table %s; ",
+                     "for table %s: %s",
                      m_osRasterTable.c_str(),
                      GetSession()->GetLastError());
             CPLDebug("OGRDB2DataSource::SetProjection",
                      "Set projection in gpkg.tile_matrix_set failed "
-                     "for table %s; ",
+                     "for table %s: %s",
                      m_osRasterTable.c_str(),
                      GetSession()->GetLastError());
             return CE_Failure;
@@ -3228,8 +3188,6 @@ CPLErr OGRDB2DataSource::FinalizeRasterRegistration()
     return CE_None;
 }
 
-
-
 /************************************************************************/
 /*                          IBuildOverviews()                           */
 /************************************************************************/
@@ -3420,12 +3378,12 @@ CPLErr OGRDB2DataSource::IBuildOverviews(
                         SoftRollbackTransaction();
                         CPLError(CE_Failure, CPLE_AppDefined,
                                  "updating tile_matrix failed "
-                                 "for table %s; ",
+                                 "for table %s: %s ",
                                  m_osRasterTable.c_str(),
                                  GetSession()->GetLastError());
                         CPLDebug("OGRDB2DataSource::IBuildOverviews",
                                  "updating tile_matrix failed "
-                                 "for table %s; ",
+                                 "for table %s: %s ",
                                  m_osRasterTable.c_str(),
                                  GetSession()->GetLastError());
                         return CE_Failure;
@@ -3446,12 +3404,12 @@ CPLErr OGRDB2DataSource::IBuildOverviews(
                         SoftRollbackTransaction();
                         CPLError(CE_Failure, CPLE_AppDefined,
                                  "update failed "
-                                 "for table %s; ",
+                                 "for table %s: %s ",
                                  m_osRasterTable.c_str(),
                                  GetSession()->GetLastError());
                         CPLDebug("OGRDB2DataSource::IBuildOverviews",
                                  "update failed "
-                                 "for table %s; ",
+                                 "for table %s: %s ",
                                  m_osRasterTable.c_str(),
                                  GetSession()->GetLastError());
                         return CE_Failure;
@@ -3484,12 +3442,12 @@ CPLErr OGRDB2DataSource::IBuildOverviews(
                     SoftRollbackTransaction();
                     CPLError(CE_Failure, CPLE_AppDefined,
                              "insert into tile_matrix failed "
-                             "for table %s; ",
+                             "for table %s: %s ",
                              m_osRasterTable.c_str(),
                              GetSession()->GetLastError());
                     CPLDebug("OGRDB2DataSource::IBuildOverviews",
                              "insert into tile_matrix failed "
-                             "for table %s; ",
+                             "for table %s: %s ",
                              m_osRasterTable.c_str(),
                              GetSession()->GetLastError());
                     return CE_Failure;
@@ -3571,7 +3529,6 @@ CPLErr OGRDB2DataSource::IBuildOverviews(
     return eErr;
 }
 
-
 /************************************************************************/
 /*                       RegisterZoomOtherExtension()                   */
 /************************************************************************/
@@ -3617,6 +3574,3 @@ OGRErr OGRDB2DataSource::CreateGDALAspatialExtension()
 #endif
     return OGRERR_NONE;
 }
-
-
-
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2datasourcemd.cpp b/ogr/ogrsf_frmts/db2/ogrdb2datasourcemd.cpp
index bdafbda..e395179 100644
--- a/ogr/ogrsf_frmts/db2/ogrdb2datasourcemd.cpp
+++ b/ogr/ogrsf_frmts/db2/ogrdb2datasourcemd.cpp
@@ -30,6 +30,8 @@
 
 #include "ogr_db2.h"
 
+CPL_CVSID("$Id: ogrdb2datasourcemd.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 /************************************************************************/
 /*                            FlushMetadata()                           */
 /************************************************************************/
@@ -46,7 +48,7 @@ CPLErr OGRDB2DataSource::FlushMetadata()
     CPLDebug("OGRDB2DataSource::FlushMetadata","Write Metadata");
     m_bMetadataDirty = FALSE;
 
-    if( m_osRasterTable.size() )
+    if( !m_osRasterTable.empty() )
     {
         const char* pszIdentifier = GetMetadataItem("IDENTIFIER");
         const char* pszDescription = GetMetadataItem("DESCRIPTION");
@@ -63,12 +65,11 @@ CPLErr OGRDB2DataSource::FlushMetadata()
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Set identifier failed in gpkg.contents"
-                         "for table %s; ",
+                         "for table %s: %s",
                          m_osRasterTable.c_str(),
                          GetSession()->GetLastError());
                 return CE_Failure;
             }
-
         }
         if( !m_bDescriptionAsCO && pszDescription != NULL &&
                 pszDescription != m_osDescription )
@@ -83,7 +84,7 @@ CPLErr OGRDB2DataSource::FlushMetadata()
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Set description failed in gpkg.contents"
-                         "for table %s; ",
+                         "for table %s: %s",
                          m_osRasterTable.c_str(),
                          GetSession()->GetLastError());
                 return CE_Failure;
@@ -127,7 +128,7 @@ CPLErr OGRDB2DataSource::FlushMetadata()
 
     WriteMetadata(psXMLNode, m_osRasterTable.c_str() );
 
-    if( m_osRasterTable.size() )
+    if( !m_osRasterTable.empty() )
     {
         char** papszGeopackageMD = GetMetadata("GEOPACKAGE");
 
@@ -161,12 +162,12 @@ CPLErr OGRDB2DataSource::FlushMetadata()
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Set identifier failed in gpkg.contents"
-                         "for table %s; ",
+                         "for table %s: %s",
                          m_osRasterTable.c_str(),
                          GetSession()->GetLastError());
                 CPLDebug("OGRDB2DataSource::FlushMetadata",
                          "Set identifier failed in gpkg.contents"
-                         "for table %s; ",
+                         "for table %s: %s",
                          m_osRasterTable.c_str(),
                          GetSession()->GetLastError());
                 return CE_Failure;
@@ -183,12 +184,12 @@ CPLErr OGRDB2DataSource::FlushMetadata()
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Set description failed in gpkg.contents"
-                         "for table %s; ",
+                         "for table %s: %s",
                          m_osRasterTable.c_str(),
                          GetSession()->GetLastError());
                 CPLDebug("OGRDB2DataSource::FlushMetadata",
                          "Set description failed in gpkg.contents"
-                         "for table %s; ",
+                         "for table %s: %s",
                          m_osRasterTable.c_str(),
                          GetSession()->GetLastError());
                 return CE_Failure;
@@ -231,7 +232,6 @@ CPLErr OGRDB2DataSource::FlushMetadata()
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                            WriteMetadata()                           */
 /************************************************************************/
@@ -239,8 +239,6 @@ CPLErr OGRDB2DataSource::FlushMetadata()
 void OGRDB2DataSource::WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed by the method */
                                      const char* pszTableName)
 {
-
-
     int bIsEmpty = (psXMLNode == NULL);
     char *pszXML = NULL;
     if( !bIsEmpty )
@@ -251,6 +249,7 @@ void OGRDB2DataSource::WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed
         pszXML = CPLSerializeXMLTree(psMasterXMLNode);
         CPLDestroyXMLNode(psMasterXMLNode);
     }
+    // cppcheck-suppress uselessAssignmentPtrArg
     psXMLNode = NULL;
     CPLDebug("OGRDB2DataSource::WriteMetadata",
              "pszTableName: %s; bIsEmpty: %d", pszTableName, bIsEmpty);
@@ -367,9 +366,9 @@ void OGRDB2DataSource::WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed
             else
             {
                 oStatement.Appendf("INSERT INTO gpkg.metadata_reference "
-                                   "(reference_scope, table_name, md_file_id) "
-                                   "VALUES ('table', '%s', %d)",
-                                   pszTableName, nNewId);
+                                   "(reference_scope, md_file_id) "
+                                   "VALUES ('geopackage', %d)",
+                                   nNewId);
             }
         }
         else
@@ -392,7 +391,6 @@ void OGRDB2DataSource::WriteMetadata(CPLXMLNode* psXMLNode, /* will be destroyed
     return;
 }
 
-
 /************************************************************************/
 /*                        CreateMetadataTables()                        */
 /************************************************************************/
@@ -546,8 +544,6 @@ int OGRDB2DataSource::CreateMetadataTables()
         return FALSE;
 #endif
 
-
-
     /* From C.11. gpkg_metadata_reference Table 36. gpkg_metadata_reference Table Definition SQL */
     oStatement.Clear();
     oStatement.Appendf("CREATE TABLE gpkg.metadata_reference ( "
@@ -713,7 +709,6 @@ int OGRDB2DataSource::HasMetadataTables()
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                      GetMetadataDomainList()                         */
 /************************************************************************/
@@ -722,7 +717,7 @@ char **OGRDB2DataSource::GetMetadataDomainList()
 {
     CPLDebug("OGRDB2DataSource::GetMetadataDomainList","Entering");
     GetMetadata();
-    if( m_osRasterTable.size() != 0 )
+    if( !m_osRasterTable.empty() )
         GetMetadata("GEOPACKAGE");
     return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
                                    TRUE,
@@ -737,7 +732,7 @@ const char* OGRDB2DataSource::CheckMetadataDomain( const char* pszDomain )
 {
     DB2_DEBUG_ENTER("OGRDB2DataSource::CheckMetadataDomain");
     if( pszDomain != NULL && EQUAL(pszDomain, "GEOPACKAGE") &&
-            m_osRasterTable.size() == 0 )
+            m_osRasterTable.empty() )
     {
         CPLError(CE_Warning, CPLE_IllegalArg,
                  "Using GEOPACKAGE for a non-raster geopackage is not supported. "
@@ -747,7 +742,6 @@ const char* OGRDB2DataSource::CheckMetadataDomain( const char* pszDomain )
     return pszDomain;
 }
 
-
 /************************************************************************/
 /*                            GetMetadata()                             */
 /************************************************************************/
@@ -769,7 +763,7 @@ char **OGRDB2DataSource::GetMetadata( const char *pszDomain )
         return GDALPamDataset::GetMetadata( pszDomain );
 
     OGRDB2Statement oStatement( GetSession() );
-    if( m_osRasterTable.size() )
+    if( !m_osRasterTable.empty() )
     {
 
         oStatement.Appendf(
@@ -818,7 +812,7 @@ char **OGRDB2DataSource::GetMetadata( const char *pszDomain )
             {
                 GDALMultiDomainMetadata oLocalMDMD;
                 oLocalMDMD.XMLInit(psXMLNode, FALSE);
-                if( m_osRasterTable.size() && bIsGPKGScope )
+                if( !m_osRasterTable.empty() && bIsGPKGScope )
                 {
                     oMDMD.SetMetadata( oLocalMDMD.GetMetadata(), "GEOPACKAGE" );
                 }
@@ -861,7 +855,7 @@ char **OGRDB2DataSource::GetMetadata( const char *pszDomain )
                 pszMimeType != NULL && EQUAL(pszMimeType, "text/xml") )
             continue;
 
-        if( m_osRasterTable.size() && bIsGPKGScope )
+        if( !m_osRasterTable.empty() && bIsGPKGScope )
         {
             oMDMD.SetMetadataItem( CPLSPrintf("GPKG_METADATA_ITEM_%d", nNonGDALMDIGeopackage),
                                    pszMetadata,
@@ -886,10 +880,8 @@ char **OGRDB2DataSource::GetMetadata( const char *pszDomain )
 #endif
 
     return GDALPamDataset::GetMetadata(pszDomain);
-
 }
 
-
 /************************************************************************/
 /*                          GetMetadataItem()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2driver.cpp b/ogr/ogrsf_frmts/db2/ogrdb2driver.cpp
index 8b78f92..a658d9f 100644
--- a/ogr/ogrsf_frmts/db2/ogrdb2driver.cpp
+++ b/ogr/ogrsf_frmts/db2/ogrdb2driver.cpp
@@ -29,6 +29,8 @@
 #include "ogr_db2.h"
 #include "cpl_conv.h"
 
+CPL_CVSID("$Id: ogrdb2driver.cpp 35910 2016-10-24 14:08:24Z goatbar $");
+
 /************************************************************************/
 /*                       OGRDB2DriverIdentify()                  */
 /************************************************************************/
@@ -104,7 +106,6 @@ static CPLErr OGRDB2DriverDelete( const char *pszFilename )
         return CE_Failure;
 }
 
-
 /************************************************************************/
 /*                           RegisterOGRDB2()                  */
 /************************************************************************/
@@ -132,7 +133,6 @@ void RegisterOGRDB2()
 "  <Option name='ZLEVEL' type='int' min='1' max='9' description='DEFLATE compression level for PNG tiles' default='6'/>" \
 "  <Option name='DITHER' type='boolean' description='Whether to apply Floyd-Steinberg dithering (for TILE_FORMAT=PNG8)' default='NO'/>"
 
-
     poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList>"
                                "  <Option name='TABLE' type='string' description='Name of tile user-table'/>"
                                "  <Option name='ZOOM_LEVEL' type='integer' description='Zoom level of full resolution. If not specified, maximum non-empty zoom level'/>"
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2geometryvalidator.cpp b/ogr/ogrsf_frmts/db2/ogrdb2geometryvalidator.cpp
index 4e827cb..88434a2 100644
--- a/ogr/ogrsf_frmts/db2/ogrdb2geometryvalidator.cpp
+++ b/ogr/ogrsf_frmts/db2/ogrdb2geometryvalidator.cpp
@@ -31,6 +31,8 @@
 #include "cpl_conv.h"
 #include "ogr_db2.h"
 
+CPL_CVSID("$Id: ogrdb2geometryvalidator.cpp 35675 2016-10-10 04:57:58Z goatbar $");
+
 /************************************************************************/
 /*                   OGRDB2GeometryValidator()                        */
 /************************************************************************/
@@ -276,7 +278,7 @@ int OGRDB2GeometryValidator::ValidateMultiLineString(
         poValidGeometry = poGeometries;
     }
 
-    return (poValidGeometry == NULL);
+    return poValidGeometry == NULL;
 }
 
 /************************************************************************/
@@ -332,7 +334,7 @@ int OGRDB2GeometryValidator::ValidatePolygon(OGRPolygon* poGeom)
         poValidGeometry = poGeometries;
     }
 
-    return (poValidGeometry == NULL);
+    return poValidGeometry == NULL;
 }
 
 /************************************************************************/
@@ -437,7 +439,7 @@ int OGRDB2GeometryValidator::ValidateGeometryCollection(
         poValidGeometry = poGeometries;
     }
 
-    return (poValidGeometry == NULL);
+    return poValidGeometry == NULL;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2layer.cpp b/ogr/ogrsf_frmts/db2/ogrdb2layer.cpp
index 6aa8f84..2ddca3d 100644
--- a/ogr/ogrsf_frmts/db2/ogrdb2layer.cpp
+++ b/ogr/ogrsf_frmts/db2/ogrdb2layer.cpp
@@ -29,6 +29,8 @@
 
 #include "ogr_db2.h"
 
+CPL_CVSID("$Id: ogrdb2layer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
 /************************************************************************/
 /*                        OGRDB2Layer()                        */
 /************************************************************************/
@@ -36,13 +38,17 @@
 OGRDB2Layer::OGRDB2Layer()
 
 {
+    m_poDS = NULL;
+    poFeatureDefn = NULL;
     poDS = NULL;
     pszGeomColumn = NULL;
     pszFIDColumn = NULL;
     bIsIdentityFid = FALSE;
     cGenerated = ' ';
+    nLayerStatus = 0;
     panFieldOrdinals = NULL;
     m_poStmt = NULL;
+    m_poPrepStmt = NULL;
     iNextShapeId = 0;
     poSRS = NULL;
     nSRSId = -1; // we haven't even queried the database for it yet.
@@ -57,7 +63,8 @@ OGRDB2Layer::~OGRDB2Layer()
 {
     CPLDebug("OGRDB2Layer::~OGRDB2Layer","entering");
     CPLDebug("OGRDB2Layer::~OGRDB2Layer",
-             "m_nFeaturesRead: %d; poFeatureDefn: %p", m_nFeaturesRead,poFeatureDefn);
+             "m_nFeaturesRead: " CPL_FRMT_GIB "; poFeatureDefn: %p",
+             m_nFeaturesRead,poFeatureDefn);
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "OGR_DB2Layer",
@@ -217,7 +224,6 @@ CPLErr OGRDB2Layer::BuildFeatureDefn( const char *pszLayerName,
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -303,7 +309,7 @@ OGRFeature *OGRDB2Layer::GetNextRawFeature()
         const char *pszValue = m_poStmt->GetColData( iSrcField );
 
         if( pszValue == NULL )
-            /* no value */;
+            poFeature->SetFieldNull( iField );
         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
             poFeature->SetField( iField,
                                  m_poStmt->GetColDataLength(iSrcField),
@@ -473,8 +479,9 @@ const char *OGRDB2Layer::GetGeometryColumn()
 char* OGRDB2Layer::GByteArrayToHexString( const GByte* pabyData, int nLen)
 {
     char* pszTextBuf;
+    const size_t nBufLen = nLen*2+3;
 
-    pszTextBuf = (char *) CPLMalloc(nLen*2+3);
+    pszTextBuf = (char *) CPLMalloc(nBufLen);
 
     int  iSrc, iDst=0;
 
@@ -482,12 +489,12 @@ char* OGRDB2Layer::GByteArrayToHexString( const GByte* pabyData, int nLen)
     {
         if( iSrc == 0 )
         {
-            sprintf( pszTextBuf+iDst, "0x%02x", pabyData[iSrc] );
+            snprintf( pszTextBuf+iDst, nBufLen - iDst, "0x%02x", pabyData[iSrc] );
             iDst += 4;
         }
         else
         {
-            sprintf( pszTextBuf+iDst, "%02x", pabyData[iSrc] );
+            snprintf( pszTextBuf+iDst, nBufLen - iDst, "%02x", pabyData[iSrc] );
             iDst += 2;
         }
     }
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2selectlayer.cpp b/ogr/ogrsf_frmts/db2/ogrdb2selectlayer.cpp
index 594a0b0..0db795b 100644
--- a/ogr/ogrsf_frmts/db2/ogrdb2selectlayer.cpp
+++ b/ogr/ogrsf_frmts/db2/ogrdb2selectlayer.cpp
@@ -31,6 +31,8 @@
 #include "cpl_conv.h"
 #include "ogr_db2.h"
 
+CPL_CVSID("$Id: ogrdb2selectlayer.cpp 36342 2016-11-20 18:25:31Z rouault $");
+
 /************************************************************************/
 /*                     OGRDB2SelectLayer()                     */
 /************************************************************************/
@@ -77,7 +79,7 @@ OGRDB2SelectLayer::OGRDB2SelectLayer( OGRDB2DataSource *poDSIn,
     if (nNameLength > 0)
     {
         char szLayerName[512];
-        sprintf(szLayerName, "%s.%s",szSchemaName, szTableName);
+        snprintf(szLayerName, sizeof(szLayerName), "%s.%s",szSchemaName, szTableName);
         poBaseLayer = (OGRDB2Layer *) poDS->GetLayerByName((const char*)
                       szLayerName);
         if (poBaseLayer != NULL)
diff --git a/ogr/ogrsf_frmts/db2/ogrdb2tablelayer.cpp b/ogr/ogrsf_frmts/db2/ogrdb2tablelayer.cpp
index d1241c4..47fa2b5 100644
--- a/ogr/ogrsf_frmts/db2/ogrdb2tablelayer.cpp
+++ b/ogr/ogrsf_frmts/db2/ogrdb2tablelayer.cpp
@@ -29,6 +29,8 @@
 #include "cpl_conv.h"
 #include "ogr_db2.h"
 
+CPL_CVSID("$Id: ogrdb2tablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
 /************************************************************************/
 /*                         OGRDB2AppendEscaped( )                     */
 /************************************************************************/
@@ -72,7 +74,8 @@ void OGRDB2AppendEscaped( OGRDB2Statement* poStatement,
 /*                          OGRDB2TableLayer()                 */
 /************************************************************************/
 
-OGRDB2TableLayer::OGRDB2TableLayer( OGRDB2DataSource *poDSIn )
+OGRDB2TableLayer::OGRDB2TableLayer( OGRDB2DataSource *poDSIn ) :
+    eGeomType( wkbNone )
 
 {
     poDS = poDSIn;
@@ -93,7 +96,11 @@ OGRDB2TableLayer::OGRDB2TableLayer( OGRDB2DataSource *poDSIn )
     m_pszLayerName = NULL;
     pszSchemaName = NULL;
     pszFIDColumn = NULL;
-    eGeomType = wkbNone;
+
+    bLaunderColumnNames = false;
+    bPreservePrecision = false;
+    bNeedSpatialIndex = false;
+    m_iSrs = 0;
 }
 
 /************************************************************************/
@@ -294,7 +301,6 @@ CPLErr OGRDB2TableLayer::Initialize( const char *pszSchema,
               "nSRId: '%d', eType: '%d', srText: '%s'",
               nSRId, eType, pszSRText);
 
-
     /* -------------------------------------------------------------------- */
     /*      Parse out schema name if present in layer.  We assume a         */
     /*      schema is provided if there is a dot in the name, and that      */
@@ -418,7 +424,6 @@ OGRErr OGRDB2TableLayer::CreateSpatialIndex()
 
     OGRDB2Statement oStatement( poDS->GetSession() );
 
-
     OGREnvelope oExt;
     if (GetExtent(&oExt, TRUE) != OGRERR_NONE)
     {
@@ -574,7 +579,6 @@ OGRDB2Statement *OGRDB2TableLayer::GetStatement()
     return m_poStmt;
 }
 
-
 /************************************************************************/
 /*                           BuildStatement()                           */
 /************************************************************************/
@@ -648,7 +652,7 @@ OGRFeature *OGRDB2TableLayer::GetFeature( GIntBig nFeatureId )
 
     m_poStmt = new OGRDB2Statement( poDS->GetSession() );
     CPLString osFields = BuildFields();
-    m_poStmt->Appendf( "select %s from %s where %s = %ld", osFields.c_str(),
+    m_poStmt->Appendf( "select %s from %s where %s = " CPL_FRMT_GIB, osFields.c_str(),
                        poFeatureDefn->GetName(), pszFIDColumn, nFeatureId );
 
     if( !m_poStmt->DB2Execute("OGR_DB2TableLayer::GetFeature") )
@@ -684,7 +688,6 @@ OGRErr OGRDB2TableLayer::SetAttributeFilter( const char *pszQuery )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -699,7 +702,7 @@ int OGRDB2TableLayer::TestCapability( const char * pszCap )
             return TRUE;
 
         else if( EQUAL(pszCap,OLCRandomWrite) )
-            return (pszFIDColumn != NULL);
+            return pszFIDColumn != NULL;
     }
 
     if( EQUAL(pszCap,OLCTransactions) )
@@ -709,7 +712,7 @@ int OGRDB2TableLayer::TestCapability( const char * pszCap )
         return TRUE;
 
     if( EQUAL(pszCap,OLCRandomRead) )
-        return (pszFIDColumn != NULL);
+        return pszFIDColumn != NULL;
     else if( EQUAL(pszCap,OLCFastFeatureCount) )
         return TRUE;
     else
@@ -743,7 +746,6 @@ GIntBig OGRDB2TableLayer::GetFeatureCount( int bForce )
     return nRet;
 }
 
-
 /************************************************************************/
 /*                            CreateField()                             */
 /************************************************************************/
@@ -778,14 +780,14 @@ OGRErr OGRDB2TableLayer::CreateField( OGRFieldDefn *poFieldIn,
     if( oField.GetType() == OFTInteger )
     {
         if( oField.GetWidth() > 0 && bPreservePrecision )
-            sprintf( szFieldType, "numeric(%d,0)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "numeric(%d,0)", oField.GetWidth() );
         else
             strcpy( szFieldType, "int" );
     }
     else if( oField.GetType() == OFTInteger64 )
     {
         if( oField.GetWidth() > 0 && bPreservePrecision )
-            sprintf( szFieldType, "numeric(%d,0)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "numeric(%d,0)", oField.GetWidth() );
         else
             strcpy( szFieldType, "bigint" );
     }
@@ -793,7 +795,7 @@ OGRErr OGRDB2TableLayer::CreateField( OGRFieldDefn *poFieldIn,
     {
         if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
                 && bPreservePrecision )
-            sprintf( szFieldType, "numeric(%d,%d)",
+            snprintf( szFieldType, sizeof(szFieldType), "numeric(%d,%d)",
                      oField.GetWidth(), oField.GetPrecision() );
         else
             strcpy( szFieldType, "float" );
@@ -803,7 +805,7 @@ OGRErr OGRDB2TableLayer::CreateField( OGRFieldDefn *poFieldIn,
         if( oField.GetWidth() == 0 || !bPreservePrecision )
             strcpy( szFieldType, "varchar(MAX)" );
         else
-            sprintf( szFieldType, "varchar(%d)", oField.GetWidth() );
+            snprintf( szFieldType, sizeof(szFieldType), "varchar(%d)", oField.GetWidth() );
     }
     else if( oField.GetType() == OFTDate )
     {
@@ -900,7 +902,6 @@ OGRErr OGRDB2TableLayer::ISetFeature( OGRFeature *poFeature )
                   "Unable to update features in tables without\n"
                   "a recognised FID column.");
         return eErr;
-
     }
 
     ClearStatement();
@@ -911,7 +912,6 @@ OGRErr OGRDB2TableLayer::ISetFeature( OGRFeature *poFeature )
     if (PrepareFeature(poFeature, 'U'))
         return OGRERR_FAILURE;
 
-
     int nFieldCount = poFeatureDefn->GetFieldCount();
     int nBindNum = 0;
     void** papBindBuffer = (void**)CPLMalloc(sizeof(void*) * nFieldCount);
@@ -962,7 +962,6 @@ OGRErr OGRDB2TableLayer::ISetFeature( OGRFeature *poFeature )
         nBindNum++;
     }
 
-
     /* -------------------------------------------------------------------- */
     /*      Execute the update.                                             */
     /* -------------------------------------------------------------------- */
@@ -1026,11 +1025,6 @@ OGRErr OGRDB2TableLayer::DeleteFeature( GIntBig nFID )
     return OGRERR_NONE;
 }
 
-
-
-
-
-
 /************************************************************************/
 /*                          isFieldTypeSupported()                      */
 /************************************************************************/
@@ -1114,7 +1108,7 @@ OGRErr OGRDB2TableLayer::PrepareFeature( OGRFeature *poFeature, char cType )
     for( int i = 0; i < nFieldCount; i++ )
     {
 
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
             continue;
 
         if (bNeedComma)
@@ -1190,8 +1184,9 @@ OGRErr OGRDB2TableLayer::ICreateFeature( OGRFeature *poFeature )
             {
                 papBindBuffer[nBindNum] = pszWKT;
                 nBindNum++;
-
-            } else {
+            }
+            else
+            {
                 CPLDebug("OGRDB2TableLayer::ICreateFeature",
                          "Bind parameter failed");
                 FreeBindBuffer(nBindNum, papBindBuffer);
@@ -1215,8 +1210,9 @@ OGRErr OGRDB2TableLayer::ICreateFeature( OGRFeature *poFeature )
         {
             papBindBuffer[nBindNum] = NULL;
             nBindNum++;
-
-        } else {
+        }
+        else
+        {
             CPLDebug("OGRDB2TableLayer::ICreateFeature",
                      "Bind parameter failed");
             FreeBindBuffer(nBindNum, papBindBuffer);
@@ -1227,7 +1223,7 @@ OGRErr OGRDB2TableLayer::ICreateFeature( OGRFeature *poFeature )
     for( int i = 0; i < nFieldCount; i++ )
     {
 
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
             continue;
 
 //        int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
@@ -1274,7 +1270,6 @@ OGRErr OGRDB2TableLayer::ICreateFeature( OGRFeature *poFeature )
             if ( oStatement2.GetColData( 0 ) )
             {
                 poFeature->SetFID( atoi(oStatement2.GetColData( 0 ) ));
-
             }
         }
         CPLDebug("OGR_DB2TableLayer::ICreateFeature","Old FID: " CPL_FRMT_GIB
@@ -1305,7 +1300,7 @@ void OGRDB2TableLayer::FreeBindBuffer(int nBindNum, void **papBindBuffer)
 /* non-empty field value                                                */
 /************************************************************************/
 
-OGRErr OGRDB2TableLayer::BindFieldValue(OGRDB2Statement *poStatement,
+OGRErr OGRDB2TableLayer::BindFieldValue(OGRDB2Statement * /*poStatement*/,
                                         OGRFeature* poFeature, int i,
                                         int nBindNum, void **papBindBuffer)
 {
@@ -1356,7 +1351,6 @@ OGRErr OGRDB2TableLayer::BindFieldValue(OGRDB2Statement *poStatement,
         nParameterType = SQL_BIGINT;
     }
 
-
     if (pValuePointer) {
         if (!m_poPrepStmt->DB2BindParameterIn(
                     "OGRDB2TableLayer::BindFieldValue",
@@ -1374,7 +1368,7 @@ OGRErr OGRDB2TableLayer::BindFieldValue(OGRDB2Statement *poStatement,
     return OGRERR_NONE;
 }
 
-
+#ifdef notdef
 /************************************************************************/
 /*                     CreateSpatialIndexIfNecessary()                  */
 /************************************************************************/
@@ -1386,8 +1380,7 @@ void OGRDB2TableLayer::CreateSpatialIndexIfNecessary()
         CreateSpatialIndex();
     }
 }
-
-
+#endif
 
 /************************************************************************/
 /*                      RunDeferredCreationIfNecessary()                */
@@ -1483,7 +1476,6 @@ OGRErr OGRDB2TableLayer::RunDeferredCreationIfNecessary()
 
     osCommand += ")";
 
-
     OGRErr err = SQLCommand(m_poDS->GetDB(), osCommand.c_str());
     if ( OGRERR_NONE != err )
         return OGRERR_FAILURE;
diff --git a/ogr/ogrsf_frmts/dgn/Doxyfile b/ogr/ogrsf_frmts/dgn/Doxyfile
index b80aca4..4254829 100644
--- a/ogr/ogrsf_frmts/dgn/Doxyfile
+++ b/ogr/ogrsf_frmts/dgn/Doxyfile
@@ -10,19 +10,19 @@
 #---------------------------------------------------------------------------
 
 # The PROJECT_NAME tag is a single word (or a sequence of word surrounded
-# by quotes) that should identify the project. 
+# by quotes) that should identify the project.
 
 PROJECT_NAME         =	dgnlib
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or 
+# This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER       =	
+PROJECT_NUMBER       =
 
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
 # where doxygen was started. If left blank the current directory will be used.
 
 OUTPUT_DIRECTORY     =
@@ -39,14 +39,14 @@ HTML_OUTPUT          =
 
 LATEX_OUTPUT          =
 
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard header.
 
 #HTML_HEADER          = html/gdal_header.html
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
 # standard footer.
 
 #HTML_FOOTER          = html/gdal_footer.html
@@ -98,7 +98,7 @@ GENERATE_HTML        = YES
 GENERATE_RTF         = NO
 
 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in 
+# include brief member descriptions after the members that are listed in
 # the file and class documentation (similar to JavaDoc).
 # Set to NO to disable this.
 
@@ -114,23 +114,23 @@ FULL_PATH_NAMES = NO
 # configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag is used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
 INPUT = dgnlib.h dgnopen.cpp dgnread.cpp dgnstroke.cpp dgnhelp.cpp dgnwrite.cpp
 
 
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
 # blank all files are included.
 
 FILE_PATTERNS    =	*.h *.cpp *.c *.dox
 
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
 # the \include command).
 
 EXAMPLE_PATH     = .
@@ -142,16 +142,16 @@ EXAMPLE_PATH     = .
 RECURSIVE        = NO
 
 # The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program 
+# invoke to filter for each input file. Doxygen will invoke the filter program
 # by executing (via popen()) the command <filter> <input-file>, where <filter>
 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an
 # input file. Doxygen will then use the output that the filter program writes
 # to standard output.
 
-INPUT_FILTER     = 
+INPUT_FILTER     =
 
 #---------------------------------------------------------------------------
-# Configuration options related to the preprocessor 
+# Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
 # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
@@ -161,7 +161,7 @@ INPUT_FILTER     =
 ENABLE_PREPROCESSING = YES
 
 # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional 
+# names in the source code. If set to NO (the default) only conditional
 # compilation will be performed.
 
 MACRO_EXPANSION = NO
@@ -192,10 +192,10 @@ PREDEFINED =
 EXPAND_ONLY_PREDEF = NO
 
 #---------------------------------------------------------------------------
-# Configuration options related to external references 
+# Configuration options related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES tag can be used to specify one or more tagfiles. 
+# The TAGFILES tag can be used to specify one or more tagfiles.
 
 TAGFILES         =
 
@@ -216,10 +216,10 @@ ALLEXTERNALS     = NO
 PERL_PATH        = /usr/bin/perl
 
 #---------------------------------------------------------------------------
-# Configuration options related to the search engine 
+# Configuration options related to the search engine
 #---------------------------------------------------------------------------
 
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# The SEARCHENGINE tag specifies whether or not a search engine should be
 # used. If set to NO the values of all tags below this one will be ignored.
 
 SEARCHENGINE     = NO
@@ -231,13 +231,13 @@ SEARCHENGINE     = NO
 CGI_NAME         = search.cgi
 
 # The CGI_URL tag should be the absolute URL to the directory where the
-# cgi binaries are located. See the documentation of your http daemon for 
+# cgi binaries are located. See the documentation of your http daemon for
 # details.
 
 CGI_URL          =
 
 # The DOC_URL tag should be the absolute URL to the directory where the
-# documentation is located. If left blank the absolute path to the 
+# documentation is located. If left blank the absolute path to the
 # documentation, with file:// prepended to it, will be used.
 
 DOC_URL          =
@@ -253,7 +253,7 @@ DOC_ABSPATH      =
 
 BIN_ABSPATH      = /usr/local/bin/
 
-# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to
 # documentation generated for other projects. This allows doxysearch to search
 # the documentation for these projects as well.
 
diff --git a/ogr/ogrsf_frmts/dgn/GNUmakefile b/ogr/ogrsf_frmts/dgn/GNUmakefile
index 732799b..f4d41e2 100644
--- a/ogr/ogrsf_frmts/dgn/GNUmakefile
+++ b/ogr/ogrsf_frmts/dgn/GNUmakefile
@@ -15,7 +15,7 @@ DIST_DIR =	dgnlib-$(DIST_REV)
 DIST_FILE = 	dgnlib-$(DIST_REV).zip
 DIST_FILES =	dgnread.cpp dgnopen.cpp dgnlib.h dgnlibp.h dgnfloat.cpp \
 		dgnstroke.cpp dgnwrite.cpp dgnhelp.cpp \
-		dgnwritetest.c dgndump.c \
+		dgnwritetest.cpp dgndump.cpp \
 		\
 		dist/Makefile dist/Makefile.vc dist/cpl_config.h \
 		dist/README \
diff --git a/ogr/ogrsf_frmts/dgn/dgndump.c b/ogr/ogrsf_frmts/dgn/dgndump.c
deleted file mode 100644
index 571a045..0000000
--- a/ogr/ogrsf_frmts/dgn/dgndump.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/******************************************************************************
- * $Id: dgndump.c 33713 2016-03-12 17:41:57Z goatbar $
- *
- * Project:  Microstation DGN Access Library
- * Purpose:  Temporary low level DGN dumper application.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2000, Avenza Systems Inc, http://www.avenza.com/
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "dgnlibp.h"
-
-CPL_CVSID("$Id: dgndump.c 33713 2016-03-12 17:41:57Z goatbar $");
-
-static void DGNDumpRawElement( DGNHandle hDGN, DGNElemCore *psCore,
-                               FILE *fpOut );
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage()
-
-{
-    printf( "Usage: dgndump [-e xmin ymin xmax ymax] [-s] [-r n] filename.dgn\n" );
-    printf( "\n" );
-    printf( "  -e xmin ymin xmax ymax: only get elements within extents.\n" );
-    printf( "  -s: produce summary report of element types and levels.\n");
-    printf( "  -r n: report raw binary contents of elements of type n.\n");
-
-    exit( 1 );
-}
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-int main( int argc, char ** argv )
-
-{
-    DGNHandle   hDGN;
-    DGNElemCore *psElement;
-    const char  *pszFilename = NULL;
-    int         bSummary = FALSE, iArg, bRaw = FALSE, bReportExtents = FALSE;
-    char        achRaw[128];
-    double      dfSFXMin=0.0, dfSFXMax=0.0, dfSFYMin=0.0, dfSFYMax=0.0;
-
-    memset( achRaw, 0, 128 );
-
-    for( iArg = 1; iArg < argc; iArg++ )
-    {
-        if( strcmp(argv[iArg],"-s") == 0 )
-        {
-            bSummary = TRUE;
-        }
-        else if( strcmp(argv[iArg],"-e") == 0 && iArg < argc-4 )
-        {
-            dfSFXMin = CPLAtof(argv[iArg+1]);
-            dfSFYMin = CPLAtof(argv[iArg+2]);
-            dfSFXMax = CPLAtof(argv[iArg+3]);
-            dfSFYMax = CPLAtof(argv[iArg+4]);
-            iArg += 4;
-        }
-        else if( strcmp(argv[iArg],"-r") == 0 && iArg < argc-1 )
-        {
-            achRaw[MAX(0,MIN(127,atoi(argv[iArg+1])))] = 1;
-            bRaw = TRUE;
-            iArg++;
-        }
-        else if( strcmp(argv[iArg],"-extents") == 0 )
-        {
-            bReportExtents = TRUE;
-        }
-        else if( argv[iArg][0] == '-' || pszFilename != NULL )
-            Usage();
-        else
-            pszFilename = argv[iArg];
-    }
-
-    if( pszFilename == NULL )
-        Usage();
-
-    hDGN = DGNOpen( pszFilename, FALSE );
-    if( hDGN == NULL )
-        exit( 1 );
-
-    if( bRaw )
-        DGNSetOptions( hDGN, DGNO_CAPTURE_RAW_DATA );
-
-    DGNSetSpatialFilter( hDGN, dfSFXMin, dfSFYMin, dfSFXMax, dfSFYMax );
-
-    if( !bSummary )
-    {
-        while( (psElement=DGNReadElement(hDGN)) != NULL )
-        {
-            DGNDumpElement( hDGN, psElement, stdout );
-
-            CPLAssert( psElement->type >= 0 && psElement->type < 128 );
-
-            if( achRaw[psElement->type] != 0 )
-                DGNDumpRawElement( hDGN, psElement, stdout );
-
-            if( bReportExtents )
-            {
-                DGNPoint sMin, sMax;
-                if( DGNGetElementExtents( hDGN, psElement, &sMin, &sMax ) )
-                    printf( "  Extents: (%.6f,%.6f,%.6f)\n"
-                            "        to (%.6f,%.6f,%.6f)\n",
-                            sMin.x, sMin.y, sMin.z,
-                            sMax.x, sMax.y, sMax.z );
-            }
-
-            DGNFreeElement( hDGN, psElement );
-        }
-    }
-    else
-    {
-        const DGNElementInfo    *pasEI;
-        int                     nCount, i, nLevel, nType;
-        int                     anLevelTypeCount[128*64];
-        int                     anLevelCount[64];
-        int                     anTypeCount[128];
-        double                  adfExtents[6];
-
-        DGNGetExtents( hDGN, adfExtents );
-        printf( "X Range: %.2f to %.2f\n",
-                adfExtents[0], adfExtents[3] );
-        printf( "Y Range: %.2f to %.2f\n",
-                adfExtents[1], adfExtents[4] );
-        printf( "Z Range: %.2f to %.2f\n",
-                adfExtents[2], adfExtents[5] );
-
-        pasEI = DGNGetElementIndex( hDGN, &nCount );
-
-        printf( "Total Elements: %d\n", nCount );
-
-        memset( anLevelTypeCount, 0, 128*64*sizeof(int) );
-        memset( anLevelCount, 0, 64*sizeof(int) );
-        memset( anTypeCount, 0, 128*sizeof(int) );
-
-        for( i = 0; i < nCount; i++ )
-        {
-            anLevelTypeCount[pasEI[i].level * 128 + pasEI[i].type]++;
-            anLevelCount[pasEI[i].level]++;
-            anTypeCount[pasEI[i].type]++;
-        }
-
-        printf( "\n" );
-        printf( "Per Type Report\n" );
-        printf( "===============\n" );
-
-        for( nType = 0; nType < 128; nType++ )
-        {
-            if( anTypeCount[nType] != 0 )
-            {
-                printf( "Type %s: %d\n",
-                        DGNTypeToName( nType ),
-                        anTypeCount[nType] );
-            }
-        }
-
-        printf( "\n" );
-        printf( "Per Level Report\n" );
-        printf( "================\n" );
-
-        for( nLevel = 0; nLevel < 64; nLevel++ )
-        {
-            if( anLevelCount[nLevel] == 0 )
-                continue;
-
-            printf( "Level %d, %d elements:\n",
-                    nLevel,
-                    anLevelCount[nLevel] );
-
-            for( nType = 0; nType < 128; nType++ )
-            {
-                if( anLevelTypeCount[nLevel * 128 + nType] != 0 )
-                {
-                    printf( "  Type %s: %d\n",
-                            DGNTypeToName( nType ),
-                            anLevelTypeCount[nLevel*128 + nType] );
-                }
-            }
-
-            printf( "\n" );
-        }
-    }
-
-    DGNClose( hDGN );
-
-    return 0;
-}
-
-/************************************************************************/
-/*                         DGNDumpRawElement()                          */
-/************************************************************************/
-
-static void DGNDumpRawElement( DGNHandle hDGN, DGNElemCore *psCore,
-                               FILE *fpOut )
-
-{
-    int         i, iChar = 0;
-    char        szLine[80];
-
-    fprintf( fpOut, "  Raw Data (%d bytes):\n", psCore->raw_bytes );
-    for( i = 0; i < psCore->raw_bytes; i++ )
-    {
-        char    szHex[3];
-
-        if( (i % 16) == 0 )
-        {
-            sprintf( szLine, "%6d: %71s", i, " " );
-            iChar = 0;
-        }
-
-        sprintf( szHex, "%02x", psCore->raw_data[i] );
-        strncpy( szLine+8+iChar*2, szHex, 2 );
-
-        if( psCore->raw_data[i] < 32 || psCore->raw_data[i] > 127 )
-            szLine[42+iChar] = '.';
-        else
-            szLine[42+iChar] = psCore->raw_data[i];
-
-        if( i == psCore->raw_bytes - 1 || (i+1) % 16 == 0 )
-        {
-            fprintf( fpOut, "%s\n", szLine );
-        }
-
-        iChar++;
-    }
-}
diff --git a/ogr/ogrsf_frmts/dgn/dgndump.cpp b/ogr/ogrsf_frmts/dgn/dgndump.cpp
new file mode 100644
index 0000000..0a159f5
--- /dev/null
+++ b/ogr/ogrsf_frmts/dgn/dgndump.cpp
@@ -0,0 +1,253 @@
+/******************************************************************************
+ * $Id: dgndump.cpp 36016 2016-10-29 04:12:00Z goatbar $
+ *
+ * Project:  Microstation DGN Access Library
+ * Purpose:  Temporary low level DGN dumper application.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2000, Avenza Systems Inc, http://www.avenza.com/
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "dgnlibp.h"
+
+#include <algorithm>
+
+CPL_CVSID("$Id: dgndump.cpp 36016 2016-10-29 04:12:00Z goatbar $");
+
+static void DGNDumpRawElement( DGNHandle hDGN, DGNElemCore *psCore,
+                               FILE *fpOut );
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage()
+
+{
+    printf( "Usage: dgndump [-e xmin ymin xmax ymax] [-s] [-r n] "
+            "filename.dgn\n" );
+    printf( "\n" );
+    printf( "  -e xmin ymin xmax ymax: only get elements within extents.\n" );
+    printf( "  -s: produce summary report of element types and levels.\n");
+    printf( "  -r n: report raw binary contents of elements of type n.\n");
+
+    exit( 1 );
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main( int argc, char ** argv )
+
+{
+    char achRaw[128] = {};
+    bool bRaw = false;
+    bool bReportExtents = false;
+    bool bSummary = false;
+    double dfSFXMin = 0.0;
+    double dfSFXMax = 0.0;
+    double dfSFYMin = 0.0;
+    double dfSFYMax = 0.0;
+    const char *pszFilename = NULL;
+
+    for( int iArg = 1; iArg < argc; iArg++ )
+    {
+        if( strcmp(argv[iArg],"-s") == 0 )
+        {
+            bSummary = true;
+        }
+        else if( strcmp(argv[iArg],"-e") == 0 && iArg < argc-4 )
+        {
+            dfSFXMin = CPLAtof(argv[iArg+1]);
+            dfSFYMin = CPLAtof(argv[iArg+2]);
+            dfSFXMax = CPLAtof(argv[iArg+3]);
+            dfSFYMax = CPLAtof(argv[iArg+4]);
+            iArg += 4;
+        }
+        else if( strcmp(argv[iArg],"-r") == 0 && iArg < argc-1 )
+        {
+            achRaw[std::max(0, std::min(127, atoi(argv[iArg+1])))] = 1;
+            bRaw = true;
+            iArg++;
+        }
+        else if( strcmp(argv[iArg],"-extents") == 0 )
+        {
+            bReportExtents = true;
+        }
+        else if( argv[iArg][0] == '-' || pszFilename != NULL )
+            Usage();
+        else
+            pszFilename = argv[iArg];
+    }
+
+    if( pszFilename == NULL )
+        Usage();
+
+    DGNHandle hDGN = DGNOpen( pszFilename, FALSE );
+    if( hDGN == NULL )
+        exit( 1 );
+
+    if( bRaw )
+        DGNSetOptions( hDGN, DGNO_CAPTURE_RAW_DATA );
+
+    DGNSetSpatialFilter( hDGN, dfSFXMin, dfSFYMin, dfSFXMax, dfSFYMax );
+
+    if( !bSummary )
+    {
+        DGNElemCore *psElement = NULL;
+        while( (psElement=DGNReadElement(hDGN)) != NULL )
+        {
+            DGNDumpElement( hDGN, psElement, stdout );
+
+            CPLAssert( psElement->type >= 0 && psElement->type < 128 );
+
+            if( achRaw[psElement->type] != 0 )
+                DGNDumpRawElement( hDGN, psElement, stdout );
+
+            if( bReportExtents )
+            {
+                DGNPoint sMin = { 0.0, 0.0, 0.0 };
+                DGNPoint sMax = { 0.0, 0.0, 0.0 };
+                if( DGNGetElementExtents( hDGN, psElement, &sMin, &sMax ) )
+                    printf( "  Extents: (%.6f,%.6f,%.6f)\n"
+                            "        to (%.6f,%.6f,%.6f)\n",
+                            sMin.x, sMin.y, sMin.z,
+                            sMax.x, sMax.y, sMax.z );
+            }
+
+            DGNFreeElement( hDGN, psElement );
+        }
+    }
+    else
+    {
+        double adfExtents[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+
+        DGNGetExtents( hDGN, adfExtents );
+        printf( "X Range: %.2f to %.2f\n",
+                adfExtents[0], adfExtents[3] );
+        printf( "Y Range: %.2f to %.2f\n",
+                adfExtents[1], adfExtents[4] );
+        printf( "Z Range: %.2f to %.2f\n",
+                adfExtents[2], adfExtents[5] );
+
+        int nCount = 0;
+        const DGNElementInfo *pasEI = DGNGetElementIndex( hDGN, &nCount );
+
+        printf( "Total Elements: %d\n", nCount );
+
+        int anLevelTypeCount[128*64] = {};
+        int anLevelCount[64] = {};
+        int anTypeCount[128] = {};
+
+        for( int i = 0; i < nCount; i++ )
+        {
+            anLevelTypeCount[pasEI[i].level * 128 + pasEI[i].type]++;
+            anLevelCount[pasEI[i].level]++;
+            anTypeCount[pasEI[i].type]++;
+        }
+
+        printf( "\n" );
+        printf( "Per Type Report\n" );
+        printf( "===============\n" );
+
+        for( int nType = 0; nType < 128; nType++ )
+        {
+            if( anTypeCount[nType] != 0 )
+            {
+                printf( "Type %s: %d\n",
+                        DGNTypeToName( nType ),
+                        anTypeCount[nType] );
+            }
+        }
+
+        printf( "\n" );
+        printf( "Per Level Report\n" );
+        printf( "================\n" );
+
+        for( int nLevel = 0; nLevel < 64; nLevel++ )
+        {
+            if( anLevelCount[nLevel] == 0 )
+                continue;
+
+            printf( "Level %d, %d elements:\n",
+                    nLevel,
+                    anLevelCount[nLevel] );
+
+            for( int nType = 0; nType < 128; nType++ )
+            {
+                if( anLevelTypeCount[nLevel * 128 + nType] != 0 )
+                {
+                    printf( "  Type %s: %d\n",
+                            DGNTypeToName( nType ),
+                            anLevelTypeCount[nLevel*128 + nType] );
+                }
+            }
+
+            printf( "\n" );
+        }
+    }
+
+    DGNClose( hDGN );
+
+    return 0;
+}
+
+/************************************************************************/
+/*                         DGNDumpRawElement()                          */
+/************************************************************************/
+
+static void DGNDumpRawElement( DGNHandle /* hDGN */, DGNElemCore *psCore,
+                               FILE *fpOut )
+
+{
+    int iChar = 0;
+    const size_t knLineSize = 80;
+    char szLine[knLineSize] = {};
+
+    fprintf( fpOut, "  Raw Data (%d bytes):\n", psCore->raw_bytes );
+    for( int i = 0; i < psCore->raw_bytes; i++ )
+    {
+        if( (i % 16) == 0 )
+        {
+            snprintf( szLine, knLineSize, "%6d: %71s", i, " " );
+            iChar = 0;
+        }
+
+        const size_t knHexSize = 3;
+        char szHex[knHexSize] = { '\0', '\0', '\0' };
+        snprintf( szHex, knHexSize, "%02x", psCore->raw_data[i] );
+        strncpy( szLine+8+iChar*2, szHex, 2 );
+
+        if( psCore->raw_data[i] < 32 || psCore->raw_data[i] > 127 )
+            szLine[42+iChar] = '.';
+        else
+            szLine[42+iChar] = psCore->raw_data[i];
+
+        if( i == psCore->raw_bytes - 1 || (i+1) % 16 == 0 )
+        {
+            fprintf( fpOut, "%s\n", szLine );
+        }
+
+        iChar++;
+    }
+}
diff --git a/ogr/ogrsf_frmts/dgn/dgnfloat.cpp b/ogr/ogrsf_frmts/dgn/dgnfloat.cpp
index 287aa54..5dc040c 100644
--- a/ogr/ogrsf_frmts/dgn/dgnfloat.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnfloat.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dgnfloat.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Functions for translating DGN floats into IEEE floats.
@@ -29,7 +28,7 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnfloat.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: dgnfloat.cpp 35910 2016-10-24 14:08:24Z goatbar $");
 
 typedef struct dbl {
     GUInt32 hi;
@@ -47,15 +46,13 @@ void    DGN2IEEEDouble(void * dbl)
     GUInt32     sign;
     GUInt32     exponent;
     GUInt32     rndbits;
-    unsigned char       *src;
-    unsigned char       *dest;
 
 /* -------------------------------------------------------------------- */
 /*      Arrange the VAX double so that it may be accessed by a          */
 /*      double64_t structure, (two GUInt32s).                           */
 /* -------------------------------------------------------------------- */
-    src =  (unsigned char *) dbl;
-    dest = (unsigned char *) &dt;
+    unsigned char *src =  (unsigned char *) dbl;
+    unsigned char *dest = (unsigned char *) &dt;
 #ifdef CPL_LSB
     dest[2] = src[0];
     dest[3] = src[1];
@@ -108,8 +105,6 @@ void    DGN2IEEEDouble(void * dbl)
     dt.hi = dt.hi & 0x000fffff;
     dt.hi = dt.hi | (exponent << 20) | sign;
 
-
-
 #ifdef CPL_LSB
 /* -------------------------------------------------------------------- */
 /*      Change the number to a byte swapped format                      */
@@ -131,10 +126,9 @@ void    DGN2IEEEDouble(void * dbl)
 void    IEEE2DGNDouble(void * dbl)
 
 {
-    double64_t  dt;
-    GInt32      exponent;
-    GInt32      sign;
-    GByte       *src,*dest;
+    double64_t dt;
+    GByte  *src = NULL;
+    GByte *dest = NULL;
 
 #ifdef CPL_LSB
     src  = (GByte *) dbl;
@@ -152,8 +146,8 @@ void    IEEE2DGNDouble(void * dbl)
     memcpy( &dt, dbl, 8 );
 #endif
 
-    sign         = dt.hi & 0x80000000;
-    exponent = dt.hi >> 20;
+    GInt32 sign = dt.hi & 0x80000000;
+    GInt32 exponent = dt.hi >> 20;
     exponent = exponent & 0x000007ff;
 
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/dgn/dgnhelp.cpp b/ogr/ogrsf_frmts/dgn/dgnhelp.cpp
index ff3bb56..3ca4d48 100644
--- a/ogr/ogrsf_frmts/dgn/dgnhelp.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnhelp.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dgnhelp.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Application visible helper functions for parsing DGN information.
@@ -29,7 +28,7 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnhelp.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: dgnhelp.cpp 37343 2017-02-11 19:40:13Z rouault $");
 
 static const unsigned char abyDefaultPCT[256][3] =
 {
@@ -291,7 +290,6 @@ static const unsigned char abyDefaultPCT[256][3] =
   {28,0,100}
 };
 
-
 /************************************************************************/
 /*                           DGNLookupColor()                           */
 /************************************************************************/
@@ -318,11 +316,11 @@ int DGNLookupColor( DGNHandle hDGN, int color_index,
                     int * red, int * green, int * blue )
 
 {
-    DGNInfo     *psDGN = (DGNInfo *) hDGN;
-
     if( color_index < 0 || color_index > 255  )
         return FALSE;
 
+    DGNInfo *psDGN = (DGNInfo *) hDGN;
+
     if( !psDGN->got_color_table )
     {
         *red = abyDefaultPCT[color_index][0];
@@ -361,15 +359,13 @@ int DGNLookupColor( DGNHandle hDGN, int color_index,
 int DGNGetShapeFillInfo( DGNHandle hDGN, DGNElemCore *psElem, int *pnColor )
 
 {
-    int iLink;
-
-    for( iLink = 0; true; iLink++ )
+    for( int iLink = 0; true; iLink++ )
     {
-        int nLinkType, nLinkSize;
-        unsigned char *pabyData;
-
-        pabyData = DGNGetLinkage( hDGN, psElem, iLink, &nLinkType,
-                                  NULL, NULL, &nLinkSize );
+        int nLinkType = 0;
+        int nLinkSize = 0;
+        unsigned char *pabyData =
+            DGNGetLinkage( hDGN, psElem, iLink, &nLinkType,
+                           NULL, NULL, &nLinkSize );
         if( pabyData == NULL )
             return FALSE;
 
@@ -401,15 +397,13 @@ int DGNGetShapeFillInfo( DGNHandle hDGN, DGNElemCore *psElem, int *pnColor )
 int DGNGetAssocID( DGNHandle hDGN, DGNElemCore *psElem )
 
 {
-    int iLink;
-
-    for( iLink = 0; true; iLink++ )
+    for( int iLink = 0; true; iLink++ )
     {
-        int nLinkType, nLinkSize;
-        unsigned char *pabyData;
-
-        pabyData = DGNGetLinkage( hDGN, psElem, iLink, &nLinkType,
-                                  NULL, NULL, &nLinkSize );
+        int nLinkType = 0;
+        int nLinkSize = 0;
+        unsigned char *pabyData =
+            DGNGetLinkage( hDGN, psElem, iLink, &nLinkType,
+                           NULL, NULL, &nLinkSize );
         if( pabyData == NULL )
             return -1;
 
@@ -431,14 +425,12 @@ int DGNGetAssocID( DGNHandle hDGN, DGNElemCore *psElem )
 
 void DGNRad50ToAscii(unsigned short sRad50, char *str )
 {
-    unsigned short sValue;
     char           ch = '\0';
-    unsigned short saQuots[3] = {1600,40,1};
-    int i;
+    unsigned short saQuots[3] = { 1600, 40,1 };
 
-    for ( i=0; i<3; i++)
+    for( int i = 0; i < 3; i++ )
     {
-        sValue = sRad50;
+        unsigned short sValue = sRad50;
         sValue /= saQuots[i];
         /* Map 0..39 to ASCII */
         if (sValue==0)
@@ -471,18 +463,17 @@ void DGNAsciiToRad50( const char *str, unsigned short *pRad50 )
 
 {
     unsigned short rad50 = 0;
-    int  i;
 
-    for( i = 0; i < 3; i++ )
+    for( int i = 0; i < 3; i++ )
     {
-        unsigned short value;
-
         if( i >= (int) strlen(str) )
         {
             rad50 = rad50 * 40;
             continue;
         }
 
+        unsigned short value = 0;
+
         if( str[i] == '$' )
             value = 27;
         else if( str[i] == '.' )
@@ -504,7 +495,6 @@ void DGNAsciiToRad50( const char *str, unsigned short *pRad50 )
     *pRad50 = rad50;
 }
 
-
 /************************************************************************/
 /*                        DGNGetLineStyleName()                         */
 /*                                                                      */
@@ -592,8 +582,6 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
 
     if( psElement->properties != 0 )
     {
-        int     nClass;
-
         fprintf( fp, "  properties=%d", psElement->properties );
         if( psElement->properties & DGNPF_HOLE )
             fprintf( fp, ",HOLE" );
@@ -612,7 +600,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
         if( psElement->properties & DGNPF_LOCKED )
             fprintf( fp, ",LOCKED" );
 
-        nClass = psElement->properties & DGNPF_CLASS;
+        int nClass = psElement->properties & DGNPF_CLASS;
         if( nClass == DGNC_PATTERN_COMPONENT )
             fprintf( fp, ",PATTERN_COMPONENT" );
         else if( nClass == DGNC_CONSTRUCTION_ELEMENT )
@@ -634,9 +622,8 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       case DGNST_MULTIPOINT:
       {
           DGNElemMultiPoint     *psLine = (DGNElemMultiPoint *) psElement;
-          int                   i;
 
-          for( i=0; i < psLine->num_vertices; i++ )
+          for( int i = 0; i < psLine->num_vertices; i++ )
               fprintf( fp, "  (%.6f,%.6f,%.6f)\n",
                        psLine->vertices[i].x,
                        psLine->vertices[i].y,
@@ -762,12 +749,12 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
                    psNode->length_mult,
                    psNode->height_mult );
           fprintf( fp,
-		   "  max_length=%d, used=%d,",
-		   psNode->max_length,
-		   psNode->max_used );
+                   "  max_length=%d, used=%d,",
+                   psNode->max_length,
+                   psNode->max_used );
           fprintf( fp,
-		   "  node_number=%d\n",
-		   psNode->node_number );
+                   "  node_number=%d\n",
+                   psNode->node_number );
       }
       break;
 
@@ -791,12 +778,11 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       case DGNST_COLORTABLE:
       {
           DGNElemColorTable *psCT = (DGNElemColorTable *) psElement;
-          int                   i;
 
           fprintf( fp, "  screen_flag: %d\n", psCT->screen_flag );
-          for( i = 0; i < 256; i++ )
+          for( int i = 0; i < 256; i++ )
           {
-              fprintf( fp, "  %3d: (%3d,%3d,%3d)\n",
+              fprintf( fp, "  %3d: (%3u,%3u,%3u)\n",
                        i,
                        psCT->color_info[i][0],
                        psCT->color_info[i][1],
@@ -808,7 +794,6 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       case DGNST_TCB:
       {
           DGNElemTCB *psTCB = (DGNElemTCB *) psElement;
-          int iView;
 
           fprintf( fp, "  dimension = %d\n", psTCB->dimension );
           fprintf( fp, "  uor_per_subunit = %ld, subunits = `%s'\n",
@@ -820,7 +805,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
                    psTCB->origin_y,
                    psTCB->origin_z );
 
-          for( iView = 0; iView < 8; iView++ )
+          for( int iView = 0; iView < 8; iView++ )
           {
               DGNViewInfo *psView = psTCB->views + iView;
 
@@ -858,12 +843,11 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
       case DGNST_TAG_SET:
       {
           DGNElemTagSet *psTagSet = (DGNElemTagSet*) psElement;
-          int            iTag;
 
           fprintf( fp, "  tagSetName=%s, tagSet=%d, tagCount=%d, flags=%d\n",
                    psTagSet->tagSetName, psTagSet->tagSet,
                    psTagSet->tagCount, psTagSet->flags );
-          for( iTag = 0; iTag < psTagSet->tagCount; iTag++ )
+          for( int iTag = 0; iTag < psTagSet->tagCount; iTag++ )
           {
               DGNTagDef *psTagDef = psTagSet->tagList + iTag;
 
@@ -924,7 +908,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
           DGNElemBSplineSurfaceHeader *psSpline =
             (DGNElemBSplineSurfaceHeader *) psElement;
 
-          fprintf( fp, "  desc_words=%ld, curve type=%d\n",
+          fprintf( fp, "  desc_words=%ld, curve type=%u\n",
                    psSpline->desc_words, psSpline->curve_type);
 
           fprintf( fp, "  U: properties=%02x",
@@ -944,7 +928,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
             }
           }
           fprintf(fp, "\n");
-          fprintf( fp, "     order=%d\n  %d poles, %d knots, %d rule lines\n",
+          fprintf( fp, "     order=%u\n  %d poles, %d knots, %d rule lines\n",
                    psSpline->u_order, psSpline->num_poles_u,
                    psSpline->num_knots_u, psSpline->rule_lines_u);
 
@@ -959,7 +943,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
             }
           }
           fprintf(fp, "\n");
-          fprintf( fp, "     order=%d\n  %d poles, %d knots, %d rule lines\n",
+          fprintf( fp, "     order=%u\n  %d poles, %d knots, %d rule lines\n",
                    psSpline->v_order, psSpline->num_poles_v,
                    psSpline->num_knots_v, psSpline->rule_lines_v);
       }
@@ -971,7 +955,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
             (DGNElemBSplineCurveHeader *) psElement;
 
           fprintf( fp,
-                   "  desc_words=%ld, curve type=%d\n"
+                   "  desc_words=%ld, curve type=%u\n"
                    "  properties=%02x",
                    psSpline->desc_words, psSpline->curve_type,
                    psSpline->properties);
@@ -990,7 +974,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
             }
           }
           fprintf(fp, "\n");
-          fprintf( fp, "  order=%d\n  %d poles, %d knots\n",
+          fprintf( fp, "  order=%u\n  %d poles, %d knots\n",
                    psSpline->order, psSpline->num_poles, psSpline->num_knots);
       }
       break;
@@ -1026,18 +1010,17 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
 
     if( psElement->attr_bytes > 0 )
     {
-        int iLink;
-
         fprintf( fp, "Attributes (%d bytes):\n", psElement->attr_bytes );
 
-        for( iLink = 0; true; iLink++ )
-
+        for( int iLink = 0; true; iLink++ )
         {
-            int nLinkType, nEntityNum=0, nMSLink=0, nLinkSize, i;
-            unsigned char *pabyData;
-
-            pabyData = DGNGetLinkage( hDGN, psElement, iLink, &nLinkType,
-                                      &nEntityNum, &nMSLink, &nLinkSize );
+            int nLinkType = 0;
+            int nEntityNum = 0;
+            int nMSLink = 0;
+            int nLinkSize = 0;
+            unsigned char *pabyData =
+                DGNGetLinkage( hDGN, psElement, iLink, &nLinkType,
+                               &nEntityNum, &nMSLink, &nLinkSize );
             if( pabyData == NULL )
                 break;
 
@@ -1058,15 +1041,13 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
             }
             fprintf( fp, "\n  0x" );
 
-            for( i = 0; i < nLinkSize; i++ )
+            for( int i = 0; i < nLinkSize; i++ )
                 fprintf( fp, "%02x", pabyData[i] );
             fprintf( fp, "\n" );
-
         }
     }
 }
 
-
 /************************************************************************/
 /*                           DGNTypeToName()                            */
 /************************************************************************/
@@ -1085,7 +1066,7 @@ void DGNDumpElement( DGNHandle hDGN, DGNElemCore *psElement, FILE *fp )
 const char *DGNTypeToName( int nType )
 
 {
-    static char szNumericResult[16];
+    static char szNumericResult[16] = {};
 
     switch( nType )
     {
@@ -1264,22 +1245,23 @@ unsigned char *DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement,
                               int *pnEntityNum, int *pnMSLink, int *pnLength )
 
 {
-    int nAttrOffset;
-    int iLinkage, nLinkSize;
+    int nLinkSize = 0;
 
-    for( iLinkage=0, nAttrOffset=0;
+    for( int iLinkage=0, nAttrOffset=0;
          (nLinkSize = DGNGetAttrLinkSize( hDGN, psElement, nAttrOffset)) != 0;
          iLinkage++, nAttrOffset += nLinkSize )
     {
         if( iLinkage == iIndex )
         {
-            int  nLinkageType=0, nEntityNum=0, nMSLink = 0;
             if( nLinkSize <= 4 )
             {
                 CPLError(CE_Failure, CPLE_AssertionFailed, "nLinkSize <= 4");
                 return NULL;
             }
 
+            int nLinkageType = 0;
+            int nEntityNum = 0;
+            int nMSLink = 0;
             if( psElement->attr_data[nAttrOffset+0] == 0x00
                 && (psElement->attr_data[nAttrOffset+1] == 0x00
                     || psElement->attr_data[nAttrOffset+1] == 0x80) )
@@ -1301,10 +1283,9 @@ unsigned char *DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement,
                 nEntityNum = psElement->attr_data[nAttrOffset+6]
                     + psElement->attr_data[nAttrOffset+7] * 256;
                 nMSLink = psElement->attr_data[nAttrOffset+8]
-                    + psElement->attr_data[nAttrOffset+9] * 256
-                    + psElement->attr_data[nAttrOffset+10] * 65536
-                    + psElement->attr_data[nAttrOffset+11] * 65536 * 256;
-
+                    | (psElement->attr_data[nAttrOffset+9] << 8)
+                    | (psElement->attr_data[nAttrOffset+10] << 16)
+                    | (psElement->attr_data[nAttrOffset+11] << 24);
             }
 
             if( pnLinkageType != NULL )
@@ -1332,7 +1313,7 @@ unsigned char *DGNGetLinkage( DGNHandle hDGN, DGNElemCore *psElement,
 void DGNRotationToQuaternion( double dfRotation, int *panQuaternion )
 
 {
-    double dfRadianRot = (dfRotation / 180.0)  * M_PI;
+    const double dfRadianRot = (dfRotation / 180.0)  * M_PI;
 
     panQuaternion[0] = (int) (cos(-dfRadianRot/2.0) * 2147483647);
     panQuaternion[1] = 0;
@@ -1351,22 +1332,22 @@ void DGNRotationToQuaternion( double dfRotation, int *panQuaternion )
 
 void DGNQuaternionToMatrix( int *quat, float *mat )
 {
-  double q[4];
-
-  q[0] = 1.0 * quat[1] / (1<<31);
-  q[1] = 1.0 * quat[2] / (1<<31);
-  q[2] = 1.0 * quat[3] / (1<<31);
-  q[3] = 1.0 * quat[0] / (1<<31);
-
-  mat[0*3+0] = (float) (q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]);
-  mat[0*3+1] = (float) (2 * (q[2]*q[3] + q[0]*q[1]));
-  mat[0*3+2] = (float) (2 * (q[0]*q[2] - q[1]*q[3]));
-  mat[1*3+0] = (float) (2 * (q[0]*q[1] - q[2]*q[3]));
-  mat[1*3+1] = (float) (-q[0]*q[0] + q[1]*q[1] - q[2]*q[2] + q[3]*q[3]);
-  mat[1*3+2] = (float) (2 * (q[0]*q[3] + q[1]*q[2]));
-  mat[2*3+0] = (float) (2 * (q[0]*q[2] + q[1]*q[3]));
-  mat[2*3+1] = (float) (2 * (q[1]*q[2] - q[0]*q[3]));
-  mat[2*3+2] = (float) (-q[0]*q[0] - q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
+    const double q[4] = {
+        1.0 * quat[1] / (1<<31),
+        1.0 * quat[2] / (1<<31),
+        1.0 * quat[3] / (1<<31),
+        1.0 * quat[0] / (1<<31)
+    };
+
+    mat[0*3+0] = (float) (q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3]);
+    mat[0*3+1] = (float) (2 * (q[2]*q[3] + q[0]*q[1]));
+    mat[0*3+2] = (float) (2 * (q[0]*q[2] - q[1]*q[3]));
+    mat[1*3+0] = (float) (2 * (q[0]*q[1] - q[2]*q[3]));
+    mat[1*3+1] = (float) (-q[0]*q[0] + q[1]*q[1] - q[2]*q[2] + q[3]*q[3]);
+    mat[1*3+2] = (float) (2 * (q[0]*q[3] + q[1]*q[2]));
+    mat[2*3+0] = (float) (2 * (q[0]*q[2] + q[1]*q[3]));
+    mat[2*3+1] = (float) (2 * (q[1]*q[2] - q[0]*q[3]));
+    mat[2*3+2] = (float) (-q[0]*q[0] - q[1]*q[1] + q[2]*q[2] + q[3]*q[3]);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dgn/dgnlib.h b/ogr/ogrsf_frmts/dgn/dgnlib.h
index 41f1c72..724eb2e 100644
--- a/ogr/ogrsf_frmts/dgn/dgnlib.h
+++ b/ogr/ogrsf_frmts/dgn/dgnlib.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnlib.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: dgnlib.h 35910 2016-10-24 14:08:24Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Definitions of public structures and API of DGN Library.
@@ -405,7 +405,6 @@ typedef struct {
 
 } DGNElemCone;
 
-
 /**
  * Text Node Header.
  *
@@ -419,23 +418,22 @@ typedef struct {
 typedef struct {
   DGNElemCore core;   /* must be at first position ! */
 
-  int       totlength; 	 	/*!<  Total length of the node
-				      (bytes = totlength * 2 + 38) */
-  int       numelems;    	/*!<  Number of text strings */
-  int       node_number; 	/*!<  text node number */
-  short     max_length;  	/*!<  maximum length allowed, characters */
-  short     max_used;    	/*!<  maximum length used */
-  short	    font_id;     	/*!<  text font used */
-  short     justification; 	/*!<  justification type, see DGNJ_ */
-  long      line_spacing; 	/*!<  spacing between text strings */
-  double    length_mult; 	/*!<  length multiplier */
-  double    height_mult; 	/*!<  height multiplier */
-  double    rotation;    	/*!<  rotation angle (2d)*/
-  DGNPoint  origin;       	/*!<  Snap origin (as defined by user) */
+  int       totlength;          /*!<  Total length of the node
+                                      (bytes = totlength * 2 + 38) */
+  int       numelems;           /*!<  Number of text strings */
+  int       node_number;        /*!<  text node number */
+  short     max_length;         /*!<  maximum length allowed, characters */
+  short     max_used;           /*!<  maximum length used */
+  short     font_id;            /*!<  text font used */
+  short     justification;      /*!<  justification type, see DGNJ_ */
+  long      line_spacing;       /*!<  spacing between text strings */
+  double    length_mult;        /*!<  length multiplier */
+  double    height_mult;        /*!<  height multiplier */
+  double    rotation;           /*!<  rotation angle (2d)*/
+  DGNPoint  origin;             /*!<  Snap origin (as defined by user) */
 
 } DGNElemTextNode;
 
-
 /**
  * B-Spline Surface Header element
  *
@@ -518,7 +516,6 @@ typedef struct {
                              header. */
 } DGNElemKnotWeight;
 
-
 /* -------------------------------------------------------------------- */
 /*      Structure types                                                 */
 /* -------------------------------------------------------------------- */
@@ -577,7 +574,6 @@ typedef struct {
 /** DGNElemCore style: Element uses DGNElemSharedCellDefn structure */
 #define DGNST_SHARED_CELL_DEFN         18
 
-
 /* -------------------------------------------------------------------- */
 /*      Element types                                                   */
 /* -------------------------------------------------------------------- */
@@ -645,7 +641,6 @@ typedef struct {
 #define DGNSOT_VOLUME_OF_REVOLUTION     1
 #define DGNSOT_BOUNDED_VOLUME           2
 
-
 /* -------------------------------------------------------------------- */
 /*      Class                                                           */
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/dgn/dgnlibp.h b/ogr/ogrsf_frmts/dgn/dgnlibp.h
index c4f77cb..e53c570 100644
--- a/ogr/ogrsf_frmts/dgn/dgnlibp.h
+++ b/ogr/ogrsf_frmts/dgn/dgnlibp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dgnlibp.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: dgnlibp.h 35374 2016-09-09 13:32:13Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Internal (privatE) datastructures, and prototypes for DGN Access
@@ -40,7 +40,7 @@ typedef struct {
     int         nElemBytes;
     GByte       abyElem[131076];
 
-    int         got_tcb;
+    bool        got_tcb;
     int         dimension;
     int         options;
     double      scale;
@@ -48,7 +48,7 @@ typedef struct {
     double      origin_y;
     double      origin_z;
 
-    int         index_built;
+    bool        index_built;
     int         element_count;
     int         max_element_count;
     DGNElementInfo *element_index;
@@ -56,7 +56,7 @@ typedef struct {
     int         got_color_table;
     GByte       color_table[256][3];
 
-    int         got_bounds;
+    bool        got_bounds;
     GUInt32     min_x;
     GUInt32     min_y;
     GUInt32     min_z;
@@ -64,11 +64,11 @@ typedef struct {
     GUInt32     max_y;
     GUInt32     max_z;
 
-    int         has_spatial_filter;
-    int         sf_converted_to_uor;
+    bool        has_spatial_filter;
+    bool        sf_converted_to_uor;
 
-    int         select_complex_group;
-    int         in_complex_group;
+    bool        select_complex_group;
+    bool        in_complex_group;
 
     GUInt32     sf_min_x;
     GUInt32     sf_min_y;
diff --git a/ogr/ogrsf_frmts/dgn/dgnopen.cpp b/ogr/ogrsf_frmts/dgn/dgnopen.cpp
index 85c842b..160d375 100644
--- a/ogr/ogrsf_frmts/dgn/dgnopen.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnopen.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dgnopen.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  DGN Access Library file open code.
@@ -29,7 +28,7 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnopen.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: dgnopen.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 /************************************************************************/
 /*                            DGNTestOpen()                             */
@@ -96,16 +95,10 @@ int DGNTestOpen( GByte *pabyHeader, int nByteCount )
 DGNHandle DGNOpen( const char * pszFilename, int bUpdate )
 
 {
-
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    FILE *fp;
-
-    if( bUpdate )
-        fp = VSIFOpen( pszFilename, "rb+" );
-    else
-        fp = VSIFOpen( pszFilename, "rb" );
+    FILE *fp = VSIFOpen( pszFilename, bUpdate ? "rb+" : "rb");
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -118,7 +111,8 @@ DGNHandle DGNOpen( const char * pszFilename, int bUpdate )
 /*      Verify the format ... add later.                                */
 /* -------------------------------------------------------------------- */
     GByte abyHeader[512];
-    const int nHeaderBytes = static_cast<int>(VSIFRead( abyHeader, 1, sizeof(abyHeader), fp ));
+    const int nHeaderBytes =
+        static_cast<int>(VSIFRead( abyHeader, 1, sizeof(abyHeader), fp ));
     if( !DGNTestOpen( abyHeader, nHeaderBytes ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -133,31 +127,31 @@ DGNHandle DGNOpen( const char * pszFilename, int bUpdate )
 /* -------------------------------------------------------------------- */
 /*      Create the info structure.                                      */
 /* -------------------------------------------------------------------- */
-    DGNInfo *psDGN = (DGNInfo *) CPLCalloc(sizeof(DGNInfo),1);
+    DGNInfo *psDGN = static_cast<DGNInfo *>(CPLCalloc(sizeof(DGNInfo), 1));
     psDGN->fp = fp;
     psDGN->next_element_id = 0;
 
-    psDGN->got_tcb = FALSE;
+    psDGN->got_tcb = false;
     psDGN->scale = 1.0;
     psDGN->origin_x = 0.0;
     psDGN->origin_y = 0.0;
     psDGN->origin_z = 0.0;
 
-    psDGN->index_built = FALSE;
+    psDGN->index_built = false;
     psDGN->element_count = 0;
     psDGN->element_index = NULL;
 
-    psDGN->got_bounds = FALSE;
+    psDGN->got_bounds = false;
 
     if( abyHeader[0] == 0xC8 )
         psDGN->dimension = 3;
     else
         psDGN->dimension = 2;
 
-    psDGN->has_spatial_filter = FALSE;
-    psDGN->sf_converted_to_uor = FALSE;
-    psDGN->select_complex_group = FALSE;
-    psDGN->in_complex_group = FALSE;
+    psDGN->has_spatial_filter = false;
+    psDGN->sf_converted_to_uor = false;
+    psDGN->select_complex_group = false;
+    psDGN->in_complex_group = false;
 
     return (DGNHandle) psDGN;
 }
@@ -222,17 +216,17 @@ void DGNSetSpatialFilter( DGNHandle hDGN,
                           double dfXMax, double dfYMax )
 
 {
-    DGNInfo     *psDGN = (DGNInfo *) hDGN;
+    DGNInfo *psDGN = (DGNInfo *) hDGN;
 
     if( dfXMin == 0.0 && dfXMax == 0.0
         && dfYMin == 0.0 && dfYMax == 0.0 )
     {
-        psDGN->has_spatial_filter = FALSE;
+        psDGN->has_spatial_filter = false;
         return;
     }
 
-    psDGN->has_spatial_filter = TRUE;
-    psDGN->sf_converted_to_uor = FALSE;
+    psDGN->has_spatial_filter = true;
+    psDGN->sf_converted_to_uor = false;
 
     psDGN->sf_min_x_geo = dfXMin;
     psDGN->sf_min_y_geo = dfYMin;
@@ -240,7 +234,6 @@ void DGNSetSpatialFilter( DGNHandle hDGN,
     psDGN->sf_max_y_geo = dfYMax;
 
     DGNSpatialFilterToUOR( psDGN );
-
 }
 
 /************************************************************************/
@@ -250,20 +243,22 @@ void DGNSetSpatialFilter( DGNHandle hDGN,
 void DGNSpatialFilterToUOR( DGNInfo *psDGN )
 
 {
-    DGNPoint    sMin, sMax;
-
     if( psDGN->sf_converted_to_uor
         || !psDGN->has_spatial_filter
         || !psDGN->got_tcb )
         return;
 
-    sMin.x = psDGN->sf_min_x_geo;
-    sMin.y = psDGN->sf_min_y_geo;
-    sMin.z = 0;
+    DGNPoint sMin = {
+        psDGN->sf_min_x_geo,
+        psDGN->sf_min_y_geo,
+        0
+    };
 
-    sMax.x = psDGN->sf_max_x_geo;
-    sMax.y = psDGN->sf_max_y_geo;
-    sMax.z = 0;
+    DGNPoint sMax = {
+        psDGN->sf_max_x_geo,
+        psDGN->sf_max_y_geo,
+        0
+    };
 
     DGNInverseTransformPoint( psDGN, &sMin );
     DGNInverseTransformPoint( psDGN, &sMax );
@@ -273,7 +268,7 @@ void DGNSpatialFilterToUOR( DGNInfo *psDGN )
     psDGN->sf_max_x = (GUInt32) (sMax.x + 2147483648.0);
     psDGN->sf_max_y = (GUInt32) (sMax.y + 2147483648.0);
 
-    psDGN->sf_converted_to_uor = TRUE;
+    psDGN->sf_converted_to_uor = true;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dgn/dgnread.cpp b/ogr/ogrsf_frmts/dgn/dgnread.cpp
index 8a9609f..0ee414c 100644
--- a/ogr/ogrsf_frmts/dgn/dgnread.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnread.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dgnread.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  DGN Access Library element reading code.
@@ -29,7 +28,9 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnread.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: dgnread.cpp 37472 2017-02-26 02:47:45Z goatbar $");
 
 static DGNElemCore *DGNParseTCB( DGNInfo * );
 static DGNElemCore *DGNParseColorTable( DGNInfo * );
@@ -37,6 +38,15 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * );
 
 
 /************************************************************************/
+/*                             DGN_INT16()                              */
+/************************************************************************/
+
+static short int DGN_INT16(const GByte *p)
+{
+    return static_cast<short>(p[0] | (p[1] << 8));
+}
+
+/************************************************************************/
 /*                           DGNGotoElement()                           */
 /************************************************************************/
 
@@ -69,7 +79,7 @@ int DGNGotoElement( DGNHandle hDGN, int element_id )
         return FALSE;
 
     psDGN->next_element_id = element_id;
-    psDGN->in_complex_group = FALSE;
+    psDGN->in_complex_group = false;
 
     return TRUE;
 }
@@ -85,8 +95,6 @@ int DGNLoadRawElement( DGNInfo *psDGN, int *pnType, int *pnLevel )
 /*      Read the first four bytes to get the level, type, and word      */
 /*      count.                                                          */
 /* -------------------------------------------------------------------- */
-    int         nType, nWords, nLevel;
-
     if( VSIFRead( psDGN->abyElem, 1, 4, psDGN->fp ) != 4 )
         return FALSE;
 
@@ -94,9 +102,9 @@ int DGNLoadRawElement( DGNInfo *psDGN, int *pnType, int *pnLevel )
     if( psDGN->abyElem[0] == 0xff && psDGN->abyElem[1] == 0xff )
         return FALSE;
 
-    nWords = psDGN->abyElem[2] + psDGN->abyElem[3]*256;
-    nType = psDGN->abyElem[1] & 0x7f;
-    nLevel = psDGN->abyElem[0] & 0x3f;
+    int nWords = psDGN->abyElem[2] + psDGN->abyElem[3]*256;
+    int nType = psDGN->abyElem[1] & 0x7f;
+    int nLevel = psDGN->abyElem[0] & 0x3f;
 
 /* -------------------------------------------------------------------- */
 /*      Read the rest of the element data into the working buffer.      */
@@ -124,18 +132,17 @@ int DGNLoadRawElement( DGNInfo *psDGN, int *pnType, int *pnLevel )
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                          DGNGetRawExtents()                          */
 /*                                                                      */
-/*      Returns FALSE if the element type does not have recognizable    */
-/*      element extents, other TRUE and the extents will be updated.    */
+/*      Returns false if the element type does not have recognizable    */
+/*      element extents, other true and the extents will be updated.    */
 /*                                                                      */
 /*      It is assumed the raw element data has been loaded into the     */
 /*      working area by DGNLoadRawElement().                            */
 /************************************************************************/
 
-static int
+static bool
 DGNGetRawExtents( DGNInfo *psDGN, int nType, unsigned char *pabyRawData,
                   GUInt32 *pnXMin, GUInt32 *pnYMin, GUInt32 *pnZMin,
                   GUInt32 *pnXMax, GUInt32 *pnYMax, GUInt32 *pnZMax )
@@ -171,14 +178,13 @@ DGNGetRawExtents( DGNInfo *psDGN, int nType, unsigned char *pabyRawData,
         *pnYMax = DGN_INT32( pabyRawData + 20 );
         if( pnZMax != NULL )
             *pnZMax = DGN_INT32( pabyRawData + 24 );
-        return TRUE;
+        return true;
 
       default:
-        return FALSE;
+        return false;
     }
 }
 
-
 /************************************************************************/
 /*                        DGNGetElementExtents()                        */
 /************************************************************************/
@@ -212,9 +218,11 @@ int DGNGetElementExtents( DGNHandle hDGN, DGNElemCore *psElement,
                           DGNPoint *psMin, DGNPoint *psMax )
 
 {
-    DGNInfo     *psDGN = (DGNInfo *) hDGN;
-    GUInt32 anMin[3], anMax[3];
-    int bResult;
+    DGNInfo *psDGN = (DGNInfo *) hDGN;
+    bool bResult = false;
+
+    GUInt32 anMin[3] = { 0, 0, 0 };
+    GUInt32 anMax[3] = { 0, 0, 0 };
 
 /* -------------------------------------------------------------------- */
 /*      Get the extents if we have raw data in the element, or          */
@@ -233,8 +241,8 @@ int DGNGetElementExtents( DGNHandle hDGN, DGNElemCore *psElement,
     else
     {
         CPLError(CE_Warning, CPLE_AppDefined,
-                 "DGNGetElementExtents() fails because the requested element\n"
-                 " does not have raw data available." );
+                 "DGNGetElementExtents() fails because the requested element "
+                 "does not have raw data available." );
         return FALSE;
     }
 
@@ -278,10 +286,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
     {
       case DGNT_CELL_HEADER:
       {
-          DGNElemCellHeader *psCell;
-
-          psCell = (DGNElemCellHeader *)
-              CPLCalloc(sizeof(DGNElemCellHeader),1);
+          DGNElemCellHeader *psCell = static_cast<DGNElemCellHeader *>(
+              CPLCalloc(sizeof(DGNElemCellHeader), 1));
           psElement = (DGNElemCore *) psCell;
           psElement->stype = DGNST_CELL_HEADER;
           DGNParseCore( psDGN, psElement );
@@ -319,13 +325,12 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
               psCell->origin.y = DGN_INT32( psDGN->abyElem + 88 );
 
               {
-              double a, b, c, d, a2, c2;
-              a = DGN_INT32( psDGN->abyElem + 68 );
-              b = DGN_INT32( psDGN->abyElem + 72 );
-              c = DGN_INT32( psDGN->abyElem + 76 );
-              d = DGN_INT32( psDGN->abyElem + 80 );
-              a2 = a * a;
-              c2 = c * c;
+              const double a = DGN_INT32( psDGN->abyElem + 68 );
+              const double b = DGN_INT32( psDGN->abyElem + 72 );
+              const double c = DGN_INT32( psDGN->abyElem + 76 );
+              const double d = DGN_INT32( psDGN->abyElem + 80 );
+              const double a2 = a * a;
+              const double c2 = c * c;
 
               psCell->xscale = sqrt(a2 + c2) / 214748;
               psCell->yscale = sqrt(b*b + d*d) / 214748;
@@ -381,11 +386,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
       case DGNT_CELL_LIBRARY:
       {
-          DGNElemCellLibrary *psCell;
-          int                 iWord;
-
-          psCell = (DGNElemCellLibrary *)
-              CPLCalloc(sizeof(DGNElemCellLibrary),1);
+          DGNElemCellLibrary *psCell = static_cast<DGNElemCellLibrary *>(
+              CPLCalloc(sizeof(DGNElemCellLibrary), 1));
           psElement = (DGNElemCore *) psCell;
           psElement->stype = DGNST_CELL_LIBRARY;
           DGNParseCore( psDGN, psElement );
@@ -410,7 +412,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
           memset( psCell->description, 0, sizeof(psCell->description) );
 
-          for( iWord = 0; iWord < 9; iWord++ )
+          for( int iWord = 0; iWord < 9; iWord++ )
           {
               int iOffset = 52 + iWord * 2;
 
@@ -423,14 +425,28 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
       case DGNT_LINE:
       {
-          DGNElemMultiPoint *psLine;
-
-          psLine = (DGNElemMultiPoint *)
-              CPLCalloc(sizeof(DGNElemMultiPoint),1);
+          DGNElemMultiPoint *psLine = static_cast<DGNElemMultiPoint *>(
+              CPLCalloc(sizeof(DGNElemMultiPoint), 1));
           psElement = (DGNElemCore *) psLine;
           psElement->stype = DGNST_MULTIPOINT;
           DGNParseCore( psDGN, psElement );
 
+          int deltaLength = 0, deltaStart = 0;
+          if (psLine->core.properties & DGNPF_ATTRIBUTES)
+          {
+            for (int iAttr = 0; iAttr<psLine->core.attr_bytes - 3; iAttr++)
+            {
+                if (psLine->core.attr_data[iAttr] == 0xA9 &&
+                    psLine->core.attr_data[iAttr + 1] == 0x51)
+                {
+                    deltaLength = (psLine->core.attr_data[iAttr + 2] +
+                                   psLine->core.attr_data[iAttr + 3] * 256) * 2;
+                    deltaStart = iAttr + 6;
+                    break;
+                }
+            }
+          }
+
           psLine->num_vertices = 2;
           if( psDGN->dimension == 2 )
           {
@@ -448,6 +464,18 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
               psLine->vertices[1].y = DGN_INT32( psDGN->abyElem + 52 );
               psLine->vertices[1].z = DGN_INT32( psDGN->abyElem + 56 );
           }
+
+          if (deltaStart && deltaLength)
+          {
+              for (int i=0; i<2; i++)
+              {
+                 int dx = DGN_INT16(psLine->core.attr_data + deltaStart + i * 4);
+                 int dy = DGN_INT16(psLine->core.attr_data + deltaStart + i * 4 + 2);
+                 psLine->vertices[i].x += dx / 32767.0;
+                 psLine->vertices[i].y += dy / 32767.0;
+              }
+          }
+
           DGNTransformPoint( psDGN, psLine->vertices + 0 );
           DGNTransformPoint( psDGN, psLine->vertices + 1 );
       }
@@ -458,18 +486,17 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       case DGNT_CURVE:
       case DGNT_BSPLINE_POLE:
       {
-          DGNElemMultiPoint *psLine;
-          int                i, count;
-          int                pntsize = psDGN->dimension * 4;
+          int pntsize = psDGN->dimension * 4;
 
-          count = psDGN->abyElem[36] + psDGN->abyElem[37]*256;
+          int count = psDGN->abyElem[36] + psDGN->abyElem[37]*256;
           if( count < 2 )
           {
               CPLError(CE_Failure, CPLE_AssertionFailed, "count < 2");
               return NULL;
           }
-          psLine = (DGNElemMultiPoint *)
-              CPLCalloc(sizeof(DGNElemMultiPoint)+(count-2)*sizeof(DGNPoint),1);
+          DGNElemMultiPoint *psLine = static_cast<DGNElemMultiPoint *>(
+              CPLCalloc(sizeof(DGNElemMultiPoint)+(count-2)*sizeof(DGNPoint),
+                        1));
           psElement = (DGNElemCore *) psLine;
           psElement->stype = DGNST_MULTIPOINT;
           DGNParseCore( psDGN, psElement );
@@ -490,8 +517,23 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
                         count );
               count = new_count;
           }
+          int deltaLength=0,deltaStart=0;
+          if (psLine->core.properties & DGNPF_ATTRIBUTES)
+          {
+              for (int iAttr=0; iAttr<psLine->core.attr_bytes-3; iAttr++)
+              {
+                    if (psLine->core.attr_data[iAttr] == 0xA9 &&
+                        psLine->core.attr_data[iAttr+1] == 0x51)
+                    {
+                        deltaLength = (psLine->core.attr_data[iAttr + 2] +
+                            psLine->core.attr_data[iAttr + 3] * 256) * 2;
+                        deltaStart = iAttr + 6;
+                        break;
+                    }
+              }
+          }
           psLine->num_vertices = count;
-          for( i = 0; i < psLine->num_vertices; i++ )
+          for( int i = 0; i < psLine->num_vertices; i++ )
           {
               psLine->vertices[i].x =
                   DGN_INT32( psDGN->abyElem + 38 + i*pntsize );
@@ -500,7 +542,13 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
               if( psDGN->dimension == 3 )
                   psLine->vertices[i].z =
                       DGN_INT32( psDGN->abyElem + 46 + i*pntsize );
-
+              if (deltaStart && deltaLength)
+              {
+                int dx = DGN_INT16(psLine->core.attr_data + deltaStart + i * 4);
+                int dy = DGN_INT16(psLine->core.attr_data + deltaStart + i * 4 + 2);
+                psLine->vertices[i].x += dx / 32767.0;
+                psLine->vertices[i].y += dy / 32767.0;
+              }
               DGNTransformPoint( psDGN, psLine->vertices + i );
           }
       }
@@ -508,9 +556,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
       case DGNT_TEXT_NODE:
       {
-          DGNElemTextNode *psNode;
-
-          psNode = (DGNElemTextNode *) CPLCalloc(sizeof(DGNElemTextNode),1);
+          DGNElemTextNode *psNode = static_cast<DGNElemTextNode *>(
+              CPLCalloc(sizeof(DGNElemTextNode), 1));
           psElement = (DGNElemCore *) psNode;
           psElement->stype = DGNST_TEXT_NODE;
           DGNParseCore( psDGN, psElement );
@@ -518,33 +565,32 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           psNode->totlength = psDGN->abyElem[36] + psDGN->abyElem[37] * 256;
           psNode->numelems  = psDGN->abyElem[38] + psDGN->abyElem[39] * 256;
 
-          psNode->node_number 	= psDGN->abyElem[40] + psDGN->abyElem[41] * 256;
-          psNode->max_length 	= psDGN->abyElem[42];
-          psNode->max_used 	= psDGN->abyElem[43];
-          psNode->font_id	= psDGN->abyElem[44];
-          psNode->justification	= psDGN->abyElem[45];
+          psNode->node_number   = psDGN->abyElem[40] + psDGN->abyElem[41] * 256;
+          psNode->max_length    = psDGN->abyElem[42];
+          psNode->max_used      = psDGN->abyElem[43];
+          psNode->font_id       = psDGN->abyElem[44];
+          psNode->justification = psDGN->abyElem[45];
           psNode->length_mult = (DGN_INT32( psDGN->abyElem + 50 ))
               * psDGN->scale * 6.0 / 1000.0;
           psNode->height_mult = (DGN_INT32( psDGN->abyElem + 54 ))
               * psDGN->scale * 6.0 / 1000.0;
 
           if( psDGN->dimension == 2 )
-	    {
-	      psNode->rotation = DGN_INT32( psDGN->abyElem + 58 ) / 360000.0;
-
-	      psNode->origin.x = DGN_INT32( psDGN->abyElem + 62 );
-	      psNode->origin.y = DGN_INT32( psDGN->abyElem + 66 );
-	    }
-	  else
-	    {
+          {
+              psNode->rotation = DGN_INT32( psDGN->abyElem + 58 ) / 360000.0;
+
+              psNode->origin.x = DGN_INT32( psDGN->abyElem + 62 );
+              psNode->origin.y = DGN_INT32( psDGN->abyElem + 66 );
+          }
+          else
+          {
               /* leave quaternion for later */
 
               psNode->origin.x = DGN_INT32( psDGN->abyElem + 74 );
               psNode->origin.y = DGN_INT32( psDGN->abyElem + 78 );
               psNode->origin.z = DGN_INT32( psDGN->abyElem + 82 );
-	    }
+          }
           DGNTransformPoint( psDGN, &(psNode->origin) );
-
       }
       break;
 
@@ -555,7 +601,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
         }
         else
         {
-            psElement = (DGNElemCore *) CPLCalloc(sizeof(DGNElemCore),1);
+            psElement = static_cast<DGNElemCore *>(
+                CPLCalloc(sizeof(DGNElemCore), 1));
             psElement->stype = DGNST_CORE;
             DGNParseCore( psDGN, psElement );
         }
@@ -563,9 +610,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
       case DGNT_ELLIPSE:
       {
-          DGNElemArc *psEllipse;
-
-          psEllipse = (DGNElemArc *) CPLCalloc(sizeof(DGNElemArc),1);
+          DGNElemArc *psEllipse =
+              static_cast<DGNElemArc *>(CPLCalloc(sizeof(DGNElemArc), 1));
           psElement = (DGNElemCore *) psEllipse;
           psElement->stype = DGNST_ARC;
           DGNParseCore( psDGN, psElement );
@@ -617,10 +663,10 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
       case DGNT_ARC:
       {
-          DGNElemArc *psEllipse;
-          GInt32     nSweepVal;
+          GInt32 nSweepVal = 0;
 
-          psEllipse = (DGNElemArc *) CPLCalloc(sizeof(DGNElemArc),1);
+          DGNElemArc *psEllipse =
+              static_cast<DGNElemArc *>(CPLCalloc(sizeof(DGNElemArc), 1));
           psElement = (DGNElemCore *) psEllipse;
           psElement->stype = DGNST_ARC;
           DGNParseCore( psDGN, psElement );
@@ -685,15 +731,16 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
       case DGNT_TEXT:
       {
-          DGNElemText *psText;
-          int         num_chars, text_off;
+          int num_chars = 0;
+          int text_off = 0;
 
           if( psDGN->dimension == 2 )
               num_chars = psDGN->abyElem[58];
           else
               num_chars = psDGN->abyElem[74];
 
-          psText = (DGNElemText *) CPLCalloc(sizeof(DGNElemText)+num_chars,1);
+          DGNElemText *psText = static_cast<DGNElemText *>(
+              CPLCalloc(sizeof(DGNElemText)+num_chars, 1));
           psElement = (DGNElemCore *) psText;
           psElement->stype = DGNST_TEXT;
           DGNParseCore( psDGN, psElement );
@@ -731,10 +778,11 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
               && *(psDGN->abyElem + text_off + 1) == 0xFD)
           {
               int n=0;
-              for (int i=0;i<num_chars/2-1;i++) {
-                  unsigned short w;
-                  memcpy(&w,psDGN->abyElem + text_off + 2 + i*2 ,2);
-                  w = CPL_LSBWORD16(w);
+              for( int i = 0; i < num_chars/2 - 1; i++ )
+              {
+                  unsigned short w = 0;
+                  memcpy(&w, psDGN->abyElem + text_off + 2 + i*2, 2);
+                  CPL_LSBPTR16(&w);
                   if (w<256) { // if alpa-numeric code area : Normal character
                       *(psText->string + n) = (char) (w & 0xFF);
                       n++; // skip 1 byte;
@@ -762,10 +810,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       case DGNT_COMPLEX_CHAIN_HEADER:
       case DGNT_COMPLEX_SHAPE_HEADER:
       {
-          DGNElemComplexHeader *psHdr;
-
-          psHdr = (DGNElemComplexHeader *)
-              CPLCalloc(sizeof(DGNElemComplexHeader),1);
+          DGNElemComplexHeader *psHdr = static_cast<DGNElemComplexHeader *>(
+              CPLCalloc(sizeof(DGNElemComplexHeader), 1));
           psElement = (DGNElemCore *) psHdr;
           psElement->stype = DGNST_COMPLEX_HEADER;
           DGNParseCore( psDGN, psElement );
@@ -777,17 +823,15 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
       case DGNT_TAG_VALUE:
       {
-          DGNElemTagValue *psTag;
-
-          psTag = (DGNElemTagValue *)
-              CPLCalloc(sizeof(DGNElemTagValue),1);
+          DGNElemTagValue *psTag = static_cast<DGNElemTagValue *>(
+              CPLCalloc(sizeof(DGNElemTagValue), 1));
           psElement = (DGNElemCore *) psTag;
           psElement->stype = DGNST_TAG_VALUE;
           DGNParseCore( psDGN, psElement );
 
           psTag->tagType = psDGN->abyElem[74] + psDGN->abyElem[75] * 256;
           memcpy( &(psTag->tagSet), psDGN->abyElem + 68, 4 );
-          psTag->tagSet = CPL_LSBWORD32(psTag->tagSet);
+          CPL_LSBPTR32( &(psTag->tagSet) );
           psTag->tagIndex = psDGN->abyElem[72] + psDGN->abyElem[73] * 256;
           psTag->tagLength = psDGN->abyElem[150] + psDGN->abyElem[151] * 256;
 
@@ -800,8 +844,7 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           {
               memcpy( &(psTag->tagValue.integer),
                       psDGN->abyElem + 154, 4 );
-              psTag->tagValue.integer =
-                  CPL_LSBWORD32( psTag->tagValue.integer );
+              CPL_LSBPTR32( &(psTag->tagValue.integer) );
           }
           else if( psTag->tagType == 4 )
           {
@@ -816,10 +859,13 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
         if( nLevel == 24 )
         {
             psElement = DGNParseTagSet( psDGN );
+            if( psElement == NULL )
+                return NULL;
         }
         else
         {
-            psElement = (DGNElemCore *) CPLCalloc(sizeof(DGNElemCore),1);
+            psElement = static_cast<DGNElemCore *>(
+                CPLCalloc(sizeof(DGNElemCore), 1));
             psElement->stype = DGNST_CORE;
             DGNParseCore( psDGN, psElement );
         }
@@ -827,15 +873,14 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 
       case DGNT_CONE:
         {
-          DGNElemCone *psCone;
-
           if( psDGN->dimension != 3 )
           {
               CPLError(CE_Failure, CPLE_AssertionFailed, "psDGN->dimension != 3");
               return NULL;
           }
 
-          psCone = (DGNElemCone *) CPLCalloc(sizeof(DGNElemCone),1);
+          DGNElemCone *psCone =
+              static_cast<DGNElemCone *>(CPLCalloc(sizeof(DGNElemCone), 1));
           psElement = (DGNElemCore *) psCone;
           psElement->stype = DGNST_CONE;
           DGNParseCore( psDGN, psElement );
@@ -874,10 +919,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       case DGNT_3DSURFACE_HEADER:
       case DGNT_3DSOLID_HEADER:
         {
-          DGNElemComplexHeader *psShape;
-
-          psShape =
-            (DGNElemComplexHeader *) CPLCalloc(sizeof(DGNElemComplexHeader),1);
+          DGNElemComplexHeader *psShape = static_cast<DGNElemComplexHeader *>(
+              CPLCalloc(sizeof(DGNElemComplexHeader), 1));
           psElement = (DGNElemCore *) psShape;
           psElement->stype = DGNST_COMPLEX_HEADER;
           DGNParseCore( psDGN, psElement );
@@ -891,10 +934,9 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
         break;
       case DGNT_BSPLINE_SURFACE_HEADER:
         {
-          DGNElemBSplineSurfaceHeader *psSpline;
-
-          psSpline = (DGNElemBSplineSurfaceHeader *)
-            CPLCalloc(sizeof(DGNElemBSplineSurfaceHeader), 1);
+          DGNElemBSplineSurfaceHeader *psSpline =
+              static_cast<DGNElemBSplineSurfaceHeader *>(
+                  CPLCalloc(sizeof(DGNElemBSplineSurfaceHeader), 1));
           psElement = (DGNElemCore *) psSpline;
           psElement->stype = DGNST_BSPLINE_SURFACE_HEADER;
           DGNParseCore( psDGN, psElement );
@@ -922,10 +964,9 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       break;
       case DGNT_BSPLINE_CURVE_HEADER:
         {
-          DGNElemBSplineCurveHeader *psSpline;
-
-          psSpline = (DGNElemBSplineCurveHeader *)
-            CPLCalloc(sizeof(DGNElemBSplineCurveHeader), 1);
+          DGNElemBSplineCurveHeader *psSpline =
+              static_cast<DGNElemBSplineCurveHeader *>(
+                  CPLCalloc(sizeof(DGNElemBSplineCurveHeader), 1));
           psElement = (DGNElemCore *) psSpline;
           psElement->stype = DGNST_BSPLINE_CURVE_HEADER;
           DGNParseCore( psDGN, psElement );
@@ -944,7 +985,6 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       break;
       case DGNT_BSPLINE_SURFACE_BOUNDARY:
         {
-          DGNElemBSplineSurfaceBoundary *psBounds;
           short numverts = psDGN->abyElem[38] + psDGN->abyElem[39]*256;
           if( numverts <= 0 )
           {
@@ -952,13 +992,29 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
               return NULL;
           }
 
-          psBounds = (DGNElemBSplineSurfaceBoundary *)
-            CPLCalloc(sizeof(DGNElemBSplineSurfaceBoundary)+
-                      (numverts-1)*sizeof(DGNPoint), 1);
+          DGNElemBSplineSurfaceBoundary *psBounds =
+              static_cast<DGNElemBSplineSurfaceBoundary *>(
+                  CPLCalloc(sizeof(DGNElemBSplineSurfaceBoundary) +
+                            (numverts-1)*sizeof(DGNPoint), 1));
           psElement = (DGNElemCore *) psBounds;
           psElement->stype = DGNST_BSPLINE_SURFACE_BOUNDARY;
           DGNParseCore( psDGN, psElement );
 
+          int deltaLength=0,deltaStart=0;
+          if (psBounds->core.properties & DGNPF_ATTRIBUTES)
+          {
+              for (int iAttr=0; iAttr<psBounds->core.attr_bytes-3; iAttr++)
+              {
+                    if (psBounds->core.attr_data[iAttr] == 0xA9 &&
+                        psBounds->core.attr_data[iAttr+1] == 0x51)
+                    {
+                        deltaLength = (psBounds->core.attr_data[iAttr + 2] +
+                            psBounds->core.attr_data[iAttr + 3] * 256) * 2;
+                        deltaStart = iAttr + 6;
+                        break;
+                    }
+              }
+          }
           // Read B-Spline surface boundary
           psBounds->number = psDGN->abyElem[36] + psDGN->abyElem[37]*256;
           psBounds->numverts = numverts;
@@ -967,21 +1023,28 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
             psBounds->vertices[i].x = DGN_INT32( psDGN->abyElem + 40 + i*8 );
             psBounds->vertices[i].y = DGN_INT32( psDGN->abyElem + 44 + i*8 );
             psBounds->vertices[i].z = 0;
+            if (deltaStart && deltaLength)
+            {
+                int dx = DGN_INT16(psBounds->core.attr_data + deltaStart + i * 4);
+                int dy = DGN_INT16(psBounds->core.attr_data + deltaStart + i * 4 + 2);
+                psBounds->vertices[i].x += dx / 32767.0;
+                psBounds->vertices[i].y += dy / 32767.0;
+            }
           }
         }
       break;
       case DGNT_BSPLINE_KNOT:
       case DGNT_BSPLINE_WEIGHT_FACTOR:
         {
-          DGNElemKnotWeight *psArray;
           // FIXME: Is it OK to assume that the # of elements corresponds
           // directly to the element size? kintel 20051215.
           int attr_bytes = psDGN->nElemBytes -
             (psDGN->abyElem[30] + psDGN->abyElem[31]*256)*2 - 32;
           int numelems = (psDGN->nElemBytes - 36 - attr_bytes)/4;
 
-          psArray = (DGNElemKnotWeight *)
-            CPLCalloc(sizeof(DGNElemKnotWeight) + (numelems-1)*sizeof(float), 1);
+          DGNElemKnotWeight *psArray = static_cast<DGNElemKnotWeight *>(
+              CPLCalloc(sizeof(DGNElemKnotWeight) + (numelems-1)*sizeof(float),
+                        1));
 
           psElement = (DGNElemCore *) psArray;
           psElement->stype = DGNST_KNOT_WEIGHT;
@@ -990,16 +1053,15 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
           // Read array
           for (int i=0;i<numelems;i++) {
             psArray->array[i] =
-              1.0f * DGN_INT32(psDGN->abyElem + 36 + i*4) / ((1UL << 31) - 1);
+              static_cast<float>(1.0 * DGN_INT32(psDGN->abyElem + 36 + i*4) / ((1UL << 31) - 1));
           }
         }
       break;
       case DGNT_SHARED_CELL_DEFN:
       {
-          DGNElemSharedCellDefn *psShared;
-
-          psShared = (DGNElemSharedCellDefn *)
-              CPLCalloc(sizeof(DGNElemSharedCellDefn),1);
+          DGNElemSharedCellDefn *psShared =
+              static_cast<DGNElemSharedCellDefn *>(
+                  CPLCalloc(sizeof(DGNElemSharedCellDefn), 1));
           psElement = (DGNElemCore *) psShared;
           psElement->stype = DGNST_SHARED_CELL_DEFN;
           DGNParseCore( psDGN, psElement );
@@ -1009,7 +1071,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
       break;
       default:
       {
-          psElement = (DGNElemCore *) CPLCalloc(sizeof(DGNElemCore),1);
+          psElement = static_cast<DGNElemCore *>(
+              CPLCalloc(sizeof(DGNElemCore), 1));
           psElement->stype = DGNST_CORE;
           DGNParseCore( psDGN, psElement );
       }
@@ -1025,7 +1088,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
         || (psDGN->options & DGNO_CAPTURE_RAW_DATA) )
     {
         psElement->raw_bytes = psDGN->nElemBytes;
-        psElement->raw_data = (unsigned char *)CPLMalloc(psElement->raw_bytes);
+        psElement->raw_data = static_cast<unsigned char *>(
+            CPLMalloc(psElement->raw_bytes));
 
         memcpy( psElement->raw_data, psDGN->abyElem, psElement->raw_bytes );
     }
@@ -1035,7 +1099,8 @@ static DGNElemCore *DGNProcessElement( DGNInfo *psDGN, int nType, int nLevel )
 /* -------------------------------------------------------------------- */
     psElement->element_id = psDGN->next_element_id - 1;
 
-    psElement->offset = static_cast<int>(VSIFTell( psDGN->fp )) - psDGN->nElemBytes;
+    psElement->offset =
+        static_cast<int>(VSIFTell( psDGN->fp )) - psDGN->nElemBytes;
     psElement->size = psDGN->nElemBytes;
 
     return psElement;
@@ -1066,9 +1131,9 @@ DGNElemCore *DGNReadElement( DGNHandle hDGN )
 
 {
     DGNInfo     *psDGN = (DGNInfo *) hDGN;
-    DGNElemCore *psElement = NULL;
-    int         nType, nLevel;
-    int         bInsideFilter;
+    int nType = 0;
+    int nLevel = 0;
+    bool bInsideFilter = false;
 
 /* -------------------------------------------------------------------- */
 /*      Load the element data into the current buffer.  If a spatial    */
@@ -1076,31 +1141,35 @@ DGNElemCore *DGNReadElement( DGNHandle hDGN )
 /*      spatial constraints.                                            */
 /* -------------------------------------------------------------------- */
     do {
-        bInsideFilter = TRUE;
+        bInsideFilter = true;
 
         if( !DGNLoadRawElement( psDGN, &nType, &nLevel ) )
             return NULL;
 
         if( psDGN->has_spatial_filter )
         {
-            GUInt32     nXMin, nXMax, nYMin, nYMax;
-
             if( !psDGN->sf_converted_to_uor )
                 DGNSpatialFilterToUOR( psDGN );
 
+            GUInt32 nXMin = 0;
+            GUInt32 nXMax = 0;
+            GUInt32 nYMin = 0;
+            GUInt32 nYMax = 0;
             if( !DGNGetRawExtents( psDGN, nType, NULL,
                                    &nXMin, &nYMin, NULL,
                                    &nXMax, &nYMax, NULL ) )
             {
                 /* If we don't have spatial characteristics for the element
                    we will pass it through. */
-                bInsideFilter = TRUE;
+                bInsideFilter = true;
             }
             else if( nXMin > psDGN->sf_max_x
                      || nYMin > psDGN->sf_max_y
                      || nXMax < psDGN->sf_min_x
                      || nYMax < psDGN->sf_min_y )
-                bInsideFilter = FALSE;
+            {
+                bInsideFilter = false;
+            }
 
             /*
             ** We want to select complex elements based on the extents of
@@ -1109,7 +1178,7 @@ DGNElemCore *DGNReadElement( DGNHandle hDGN )
             if( nType == DGNT_COMPLEX_CHAIN_HEADER
                 || nType == DGNT_COMPLEX_SHAPE_HEADER )
             {
-                psDGN->in_complex_group = TRUE;
+                psDGN->in_complex_group = true;
                 psDGN->select_complex_group = bInsideFilter;
             }
             else if( psDGN->abyElem[0] & 0x80 /* complex flag set */ )
@@ -1118,14 +1187,16 @@ DGNElemCore *DGNReadElement( DGNHandle hDGN )
                     bInsideFilter = psDGN->select_complex_group;
             }
             else
-                psDGN->in_complex_group = FALSE;
+            {
+                psDGN->in_complex_group = false;
+            }
         }
     } while( !bInsideFilter );
 
 /* -------------------------------------------------------------------- */
 /*      Convert into an element structure.                              */
 /* -------------------------------------------------------------------- */
-    psElement = DGNProcessElement( psDGN, nType, nLevel );
+    DGNElemCore *psElement = DGNProcessElement( psDGN, nType, nLevel );
 
     return psElement;
 }
@@ -1170,7 +1241,6 @@ int DGNElemTypeHasDispHdr( int nElemType )
     }
 }
 
-
 /************************************************************************/
 /*                            DGNParseCore()                            */
 /************************************************************************/
@@ -1204,15 +1274,13 @@ int DGNParseCore( DGNInfo *psDGN, DGNElemCore *psElement )
 
     if( psElement->properties & DGNPF_ATTRIBUTES )
     {
-        int   nAttIndex;
-
-        nAttIndex = psData[30] + psData[31] * 256;
+        const int nAttIndex = psData[30] + psData[31] * 256;
 
         psElement->attr_bytes = psDGN->nElemBytes - nAttIndex*2 - 32;
         if( psElement->attr_bytes > 0 )
         {
-            psElement->attr_data = (unsigned char *)
-                CPLMalloc(psElement->attr_bytes);
+            psElement->attr_data = static_cast<unsigned char *>(
+                CPLMalloc(psElement->attr_bytes));
             memcpy( psElement->attr_data, psData + nAttIndex * 2 + 32,
                     psElement->attr_bytes );
         }
@@ -1237,12 +1305,9 @@ int DGNParseCore( DGNInfo *psDGN, DGNElemCore *psElement )
 static DGNElemCore *DGNParseColorTable( DGNInfo * psDGN )
 
 {
-    DGNElemCore *psElement;
-    DGNElemColorTable  *psColorTable;
-
-    psColorTable = (DGNElemColorTable *)
-        CPLCalloc(sizeof(DGNElemColorTable),1);
-    psElement = (DGNElemCore *) psColorTable;
+    DGNElemColorTable *psColorTable = static_cast<DGNElemColorTable *>(
+        CPLCalloc(sizeof(DGNElemColorTable), 1));
+    DGNElemCore *psElement = (DGNElemCore *) psColorTable;
     psElement->stype = DGNST_COLORTABLE;
 
     DGNParseCore( psDGN, psElement );
@@ -1271,13 +1336,9 @@ static DGNElemCore *DGNParseColorTable( DGNInfo * psDGN )
 static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
 
 {
-    DGNElemCore *psElement;
-    DGNElemTagSet *psTagSet;
-    size_t      nDataOffset;
-    int         iTag;
-
-    psTagSet = (DGNElemTagSet *) CPLCalloc(sizeof(DGNElemTagSet),1);
-    psElement = (DGNElemCore *) psTagSet;
+    DGNElemTagSet *psTagSet =
+        static_cast<DGNElemTagSet *>(CPLCalloc(sizeof(DGNElemTagSet), 1));
+    DGNElemCore *psElement = (DGNElemCore *) psTagSet;
     psElement->stype = DGNST_TAG_SET;
 
     DGNParseCore( psDGN, psElement );
@@ -1307,12 +1368,12 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
 /* -------------------------------------------------------------------- */
 /*      Parse each of the tag definitions.                              */
 /* -------------------------------------------------------------------- */
-    psTagSet->tagList = (DGNTagDef *)
-        CPLCalloc(sizeof(DGNTagDef), psTagSet->tagCount);
+    psTagSet->tagList = static_cast<DGNTagDef *>(
+        CPLCalloc(sizeof(DGNTagDef), psTagSet->tagCount));
 
-    nDataOffset = 48 + strlen(psTagSet->tagSetName) + 1 + 1;
+    size_t nDataOffset = 48 + strlen(psTagSet->tagSetName) + 1 + 1;
 
-    for( iTag = 0; iTag < psTagSet->tagCount; iTag++ )
+    for( int iTag = 0; iTag < psTagSet->tagCount; iTag++ )
     {
         DGNTagDef *tagDef = psTagSet->tagList + iTag;
 
@@ -1337,7 +1398,6 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
         tagDef->prompt = CPLStrdup( (char *) psDGN->abyElem + nDataOffset );
         nDataOffset += strlen(tagDef->prompt)+1;
 
-
         /* Get type */
         tagDef->type = psDGN->abyElem[nDataOffset]
             + psDGN->abyElem[nDataOffset+1] * 256;
@@ -1357,8 +1417,7 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
         {
             memcpy( &(tagDef->defaultValue.integer),
                     psDGN->abyElem + nDataOffset, 4 );
-            tagDef->defaultValue.integer =
-                CPL_LSBWORD32( tagDef->defaultValue.integer );
+            CPL_LSBPTR32( &(tagDef->defaultValue.integer) );
             nDataOffset += 4;
         }
         else if( tagDef->type == 4 )
@@ -1381,12 +1440,9 @@ static DGNElemCore *DGNParseTagSet( DGNInfo * psDGN )
 static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
 
 {
-    DGNElemTCB *psTCB;
-    DGNElemCore *psElement;
-    int iView;
-
-    psTCB = (DGNElemTCB *) CPLCalloc(sizeof(DGNElemTCB),1);
-    psElement = (DGNElemCore *) psTCB;
+    DGNElemTCB *psTCB = static_cast<DGNElemTCB *>(
+        CPLCalloc(sizeof(DGNElemTCB), 1));
+    DGNElemCore *psElement = (DGNElemCore *) psTCB;
     psElement->stype = DGNST_TCB;
     DGNParseCore( psDGN, psElement );
 
@@ -1431,7 +1487,7 @@ static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
 
     if( !psDGN->got_tcb )
     {
-        psDGN->got_tcb = TRUE;
+        psDGN->got_tcb = true;
         psDGN->dimension = psTCB->dimension;
         psDGN->origin_x = psTCB->origin_x;
         psDGN->origin_y = psTCB->origin_y;
@@ -1444,11 +1500,10 @@ static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
     }
 
     /* Collect views */
-    for( iView = 0; iView < 8; iView++ )
+    for( int iView = 0; iView < 8; iView++ )
     {
         unsigned char *pabyRawView = psDGN->abyElem + 46 + iView*118;
         DGNViewInfo *psView = psTCB->views + iView;
-        int i;
 
         psView->flags = pabyRawView[0] + pabyRawView[1] * 256;
         memcpy( psView->levels, pabyRawView + 2, 8 );
@@ -1468,7 +1523,7 @@ static DGNElemCore *DGNParseTCB( DGNInfo * psDGN )
         psView->delta.z *= psDGN->scale;
 
         memcpy( psView->transmatrx, pabyRawView + 34, sizeof(double) * 9 );
-        for( i = 0; i < 9; i++ )
+        for( int i = 0; i < 9; i++ )
             DGN2IEEEDouble( psView->transmatrx + i );
 
         memcpy( &(psView->conversion), pabyRawView + 106, sizeof(double) );
@@ -1504,12 +1559,10 @@ void DGNFreeElement( CPL_UNUSED DGNHandle hDGN, DGNElemCore *psElement )
 
     if( psElement->stype == DGNST_TAG_SET )
     {
-        int             iTag;
-
         DGNElemTagSet *psTagSet = (DGNElemTagSet *) psElement;
         CPLFree( psTagSet->tagSetName );
 
-        for( iTag = 0; iTag < psTagSet->tagCount; iTag++ )
+        for( int iTag = 0; iTag < psTagSet->tagCount; iTag++ )
         {
             CPLFree( psTagSet->tagList[iTag].name );
             CPLFree( psTagSet->tagList[iTag].prompt );
@@ -1545,12 +1598,12 @@ void DGNFreeElement( CPL_UNUSED DGNHandle hDGN, DGNElemCore *psElement )
 void DGNRewind( DGNHandle hDGN )
 
 {
-    DGNInfo     *psDGN = (DGNInfo *) hDGN;
+    DGNInfo *psDGN = (DGNInfo *) hDGN;
 
     VSIRewind( psDGN->fp );
 
     psDGN->next_element_id = 0;
-    psDGN->in_complex_group = FALSE;
+    psDGN->in_complex_group = false;
 }
 
 /************************************************************************/
@@ -1576,9 +1629,9 @@ void DGNInverseTransformPoint( DGNInfo *psDGN, DGNPoint *psPoint )
     psPoint->y = (psPoint->y + psDGN->origin_y) / psDGN->scale;
     psPoint->z = (psPoint->z + psDGN->origin_z) / psDGN->scale;
 
-    psPoint->x = MAX(-2147483647,MIN(2147483647,psPoint->x));
-    psPoint->y = MAX(-2147483647,MIN(2147483647,psPoint->y));
-    psPoint->z = MAX(-2147483647,MIN(2147483647,psPoint->z));
+    psPoint->x = std::max(-2147483647.0, std::min(2147483647.0, psPoint->x));
+    psPoint->y = std::max(-2147483647.0, std::min(2147483647.0, psPoint->y));
+    psPoint->z = std::max(-2147483647.0, std::min(2147483647.0, psPoint->z));
 }
 
 /************************************************************************/
@@ -1589,21 +1642,19 @@ void DGNInverseTransformPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
                                     unsigned char *pabyTarget )
 
 {
-    double     adfCT[3];
-    int        i;
-
-    adfCT[0] = (psPoint->x + psDGN->origin_x) / psDGN->scale;
-    adfCT[1] = (psPoint->y + psDGN->origin_y) / psDGN->scale;
-    adfCT[2] = (psPoint->z + psDGN->origin_z) / psDGN->scale;
-
-    const int nIter = MIN(3, psDGN->dimension);
-    for( i = 0; i < nIter; i++ )
+    double adfCT[3] = {
+        (psPoint->x + psDGN->origin_x) / psDGN->scale,
+        (psPoint->y + psDGN->origin_y) / psDGN->scale,
+        (psPoint->z + psDGN->origin_z) / psDGN->scale
+    };
+
+    const int nIter = std::min(3, psDGN->dimension);
+    for( int i = 0; i < nIter; i++ )
     {
-        GInt32 nCTI;
+        GInt32 nCTI = static_cast<GInt32>(
+            std::max(-2147483647.0, std::min(2147483647.0, adfCT[i])));
         unsigned char *pabyCTI = (unsigned char *) &nCTI;
 
-        nCTI = (GInt32) MAX(-2147483647,MIN(2147483647,adfCT[i]));
-
 #ifdef WORDS_BIGENDIAN
         pabyTarget[i*4+0] = pabyCTI[1];
         pabyTarget[i*4+1] = pabyCTI[0];
@@ -1720,17 +1771,18 @@ const DGNElementInfo *DGNGetElementIndex( DGNHandle hDGN, int *pnElementCount )
 int DGNGetExtents( DGNHandle hDGN, double * padfExtents )
 
 {
-    DGNInfo     *psDGN = (DGNInfo *) hDGN;
-    DGNPoint    sMin, sMax;
+    DGNInfo *psDGN = (DGNInfo *) hDGN;
 
     DGNBuildIndex( psDGN );
 
     if( !psDGN->got_bounds )
         return FALSE;
 
-    sMin.x = psDGN->min_x - 2147483648.0;
-    sMin.y = psDGN->min_y - 2147483648.0;
-    sMin.z = psDGN->min_z - 2147483648.0;
+    DGNPoint sMin = {
+        psDGN->min_x - 2147483648.0,
+        psDGN->min_y - 2147483648.0,
+        psDGN->min_z - 2147483648.0
+    };
 
     DGNTransformPoint( psDGN, &sMin );
 
@@ -1738,9 +1790,11 @@ int DGNGetExtents( DGNHandle hDGN, double * padfExtents )
     padfExtents[1] = sMin.y;
     padfExtents[2] = sMin.z;
 
-    sMax.x = psDGN->max_x - 2147483648.0;
-    sMax.y = psDGN->max_y - 2147483648.0;
-    sMax.z = psDGN->max_z - 2147483648.0;
+    DGNPoint sMax = {
+        psDGN->max_x - 2147483648.0,
+        psDGN->max_y - 2147483648.0,
+        psDGN->max_z - 2147483648.0
+    };
 
     DGNTransformPoint( psDGN, &sMax );
 
@@ -1758,24 +1812,22 @@ int DGNGetExtents( DGNHandle hDGN, double * padfExtents )
 void DGNBuildIndex( DGNInfo *psDGN )
 
 {
-    int nMaxElements, nType, nLevel;
-    long nLastOffset;
-    GUInt32 anRegion[6];
-
     if( psDGN->index_built )
         return;
 
-    psDGN->index_built = TRUE;
+    int nType = 0;
+    int nLevel = 0;
+    GUInt32 anRegion[6] = {};
+
+    psDGN->index_built = true;
 
     DGNRewind( psDGN );
 
-    nMaxElements = 0;
+    int nMaxElements = 0;
 
-    nLastOffset = VSIFTell( psDGN->fp );
+    long nLastOffset = VSIFTell( psDGN->fp );
     while( DGNLoadRawElement( psDGN, &nType, &nLevel ) )
     {
-        DGNElementInfo  *psEI;
-
         if( psDGN->element_count == nMaxElements )
         {
             nMaxElements = (int) (nMaxElements * 1.5) + 500;
@@ -1785,7 +1837,7 @@ void DGNBuildIndex( DGNInfo *psDGN )
                             nMaxElements * sizeof(DGNElementInfo) );
         }
 
-        psEI = psDGN->element_index + psDGN->element_count;
+        DGNElementInfo *psEI = psDGN->element_index + psDGN->element_count;
         psEI->level = (unsigned char) nLevel;
         psEI->type = (unsigned char) nType;
         psEI->flags = 0;
@@ -1848,7 +1900,7 @@ void DGNBuildIndex( DGNInfo *psDGN )
                                  anRegion+3, anRegion+4, anRegion+5 ) )
         {
 #ifdef notdef
-            printf( "panRegion[%d]=%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n",
+            printf( "panRegion[%d]=%.1f,%.1f,%.1f,%.1f,%.1f,%.1f\n",/*ok*/
                     psDGN->element_count,
                     anRegion[0] - 2147483648.0,
                     anRegion[1] - 2147483648.0,
@@ -1859,12 +1911,12 @@ void DGNBuildIndex( DGNInfo *psDGN )
 #endif
             if( psDGN->got_bounds )
             {
-                psDGN->min_x = MIN(psDGN->min_x, anRegion[0]);
-                psDGN->min_y = MIN(psDGN->min_y, anRegion[1]);
-                psDGN->min_z = MIN(psDGN->min_z, anRegion[2]);
-                psDGN->max_x = MAX(psDGN->max_x, anRegion[3]);
-                psDGN->max_y = MAX(psDGN->max_y, anRegion[4]);
-                psDGN->max_z = MAX(psDGN->max_z, anRegion[5]);
+                psDGN->min_x = std::min(psDGN->min_x, anRegion[0]);
+                psDGN->min_y = std::min(psDGN->min_y, anRegion[1]);
+                psDGN->min_z = std::min(psDGN->min_z, anRegion[2]);
+                psDGN->max_x = std::max(psDGN->max_x, anRegion[3]);
+                psDGN->max_y = std::max(psDGN->max_y, anRegion[4]);
+                psDGN->max_z = std::max(psDGN->max_z, anRegion[5]);
             }
             else
             {
@@ -1874,7 +1926,7 @@ void DGNBuildIndex( DGNInfo *psDGN )
                 psDGN->max_x = anRegion[3];
                 psDGN->max_y = anRegion[4];
                 psDGN->max_z = anRegion[5];
-                psDGN->got_bounds = TRUE;
+                psDGN->got_bounds = true;
             }
         }
 
diff --git a/ogr/ogrsf_frmts/dgn/dgnstroke.cpp b/ogr/ogrsf_frmts/dgn/dgnstroke.cpp
index a76af07..2d6ddf8 100644
--- a/ogr/ogrsf_frmts/dgn/dgnstroke.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnstroke.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dgnstroke.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  Code to stroke Arcs/Ellipses into polylines.
@@ -28,11 +27,11 @@
  ****************************************************************************/
 
 #include "dgnlibp.h"
-#include <math.h>
+#include <cmath>
 
-CPL_CVSID("$Id: dgnstroke.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: dgnstroke.cpp 36889 2016-12-15 20:20:24Z goatbar $");
 
-#define DEG_TO_RAD (M_PI/180.0)
+static const double DEG_TO_RAD = M_PI / 180.0;
 
 /************************************************************************/
 /*                         ComputePointOnArc()                          */
@@ -44,10 +43,10 @@ static void ComputePointOnArc2D( double dfPrimary, double dfSecondary,
 
 {
     // dfAxisRotation and dfAngle are supposed to be in Radians
-    double      dfCosRotation = cos(dfAxisRotation);
-    double      dfSinRotation = sin(dfAxisRotation);
-    double      dfEllipseX = dfPrimary * cos(dfAngle);
-    double      dfEllipseY = dfSecondary * sin(dfAngle);
+    const double dfCosRotation = cos(dfAxisRotation);
+    const double dfSinRotation = sin(dfAxisRotation);
+    const double dfEllipseX = dfPrimary * cos(dfAngle);
+    const double dfEllipseY = dfSecondary * sin(dfAngle);
 
     *pdfX = dfEllipseX * dfCosRotation - dfEllipseY * dfSinRotation;
     *pdfY = dfEllipseX * dfSinRotation + dfEllipseY * dfCosRotation;
@@ -76,9 +75,6 @@ int DGNStrokeArc( CPL_UNUSED DGNHandle hFile,
                   DGNElemArc *psArc,
                   int nPoints, DGNPoint * pasPoints )
 {
-    double      dfAngleStep, dfAngle;
-    int         i;
-
     if( nPoints < 2 )
         return FALSE;
 
@@ -89,10 +85,10 @@ int DGNStrokeArc( CPL_UNUSED DGNHandle hFile,
         return FALSE;
     }
 
-    dfAngleStep = psArc->sweepang / (nPoints - 1);
-    for( i = 0; i < nPoints; i++ )
+    const double dfAngleStep = psArc->sweepang / (nPoints - 1);
+    for( int i = 0; i < nPoints; i++ )
     {
-        dfAngle = (psArc->startang + dfAngleStep * i) * DEG_TO_RAD;
+        const double dfAngle = (psArc->startang + dfAngleStep * i) * DEG_TO_RAD;
 
         ComputePointOnArc2D( psArc->primary_axis,
                              psArc->secondary_axis,
@@ -131,12 +127,7 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
                     DGNElemMultiPoint *psCurve,
                     int nPoints, DGNPoint * pasPoints )
 {
-    int         k, nDGNPoints, iOutPoint;
-    double      *padfMx, *padfMy, *padfD, dfTotalD = 0, dfStepSize, dfD;
-    double      *padfTx, *padfTy;
-    DGNPoint    *pasDGNPoints = psCurve->vertices;
-
-    nDGNPoints = psCurve->num_vertices;
+    const int nDGNPoints = psCurve->num_vertices;
 
     if( nDGNPoints < 6 )
         return FALSE;
@@ -147,13 +138,22 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
 /* -------------------------------------------------------------------- */
 /*      Compute the Compute the slopes/distances of the segments.       */
 /* -------------------------------------------------------------------- */
-    padfMx = (double *) CPLMalloc(sizeof(double) * nDGNPoints);
-    padfMy = (double *) CPLMalloc(sizeof(double) * nDGNPoints);
-    padfD  = (double *) CPLMalloc(sizeof(double) * nDGNPoints);
-    padfTx = (double *) CPLMalloc(sizeof(double) * nDGNPoints);
-    padfTy = (double *) CPLMalloc(sizeof(double) * nDGNPoints);
-
-    for( k = 0; k < nDGNPoints-1; k++ )
+    double *padfMx = static_cast<double *>(
+        CPLMalloc(sizeof(double) * nDGNPoints));
+    double *padfMy = static_cast<double *>(
+        CPLMalloc(sizeof(double) * nDGNPoints));
+    double *padfD  = static_cast<double *>(
+        CPLMalloc(sizeof(double) * nDGNPoints));
+    double *padfTx = static_cast<double *>(
+        CPLMalloc(sizeof(double) * nDGNPoints));
+    double *padfTy = static_cast<double *>(
+        CPLMalloc(sizeof(double) * nDGNPoints));
+
+    double dfTotalD = 0.0;
+
+    DGNPoint *pasDGNPoints = psCurve->vertices;
+
+    for( int k = 0; k < nDGNPoints-1; k++ )
     {
         /* coverity[overrun-local] */
         padfD[k] = sqrt( (pasDGNPoints[k+1].x-pasDGNPoints[k].x)
@@ -179,7 +179,7 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
 /* -------------------------------------------------------------------- */
 /*      Compute the Tx, and Ty coefficients for each segment.           */
 /* -------------------------------------------------------------------- */
-    for( k = 2; k < nDGNPoints - 2; k++ )
+    for( int k = 2; k < nDGNPoints - 2; k++ )
     {
         if( fabs(padfMx[k+1] - padfMx[k]) == 0.0
             && fabs(padfMx[k-1] - padfMx[k-2]) == 0.0 )
@@ -190,7 +190,8 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
         {
             padfTx[k] = (padfMx[k-1] * fabs( padfMx[k+1] - padfMx[k])
                     + padfMx[k] * fabs( padfMx[k-1] - padfMx[k-2] ))
-           / (ABS(padfMx[k+1] - padfMx[k]) + ABS(padfMx[k-1] - padfMx[k-2]));
+           / (std::abs(padfMx[k+1] - padfMx[k]) +
+              std::abs(padfMx[k-1] - padfMx[k-2]));
         }
 
         if( fabs(padfMy[k+1] - padfMy[k]) == 0.0
@@ -202,7 +203,8 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
         {
             padfTy[k] = (padfMy[k-1] * fabs( padfMy[k+1] - padfMy[k])
                     + padfMy[k] * fabs( padfMy[k-1] - padfMy[k-2] ))
-            / (ABS(padfMy[k+1] - padfMy[k]) + ABS(padfMy[k-1] - padfMy[k-2]));
+            / (std::abs(padfMy[k+1] - padfMy[k]) +
+               std::abs(padfMy[k-1] - padfMy[k-2]));
         }
     }
 
@@ -211,35 +213,33 @@ int DGNStrokeCurve( CPL_UNUSED DGNHandle hFile,
 /*      roughly equidistant steps in D, but assume we also want to      */
 /*      include every node along the way.                               */
 /* -------------------------------------------------------------------- */
-    dfStepSize = dfTotalD / (nPoints - (nDGNPoints - 4) - 1);
+    double dfStepSize = dfTotalD / (nPoints - (nDGNPoints - 4) - 1);
 
 /* ==================================================================== */
 /*      Process each of the segments.                                   */
 /* ==================================================================== */
-    dfD = dfStepSize;
-    iOutPoint = 0;
+    double dfD = dfStepSize;
+    int iOutPoint = 0;
 
-    for( k = 2; k < nDGNPoints - 3; k++ )
+    for( int k = 2; k < nDGNPoints - 3; k++ )
     {
-        double  dfAx, dfAy, dfBx, dfBy, dfCx, dfCy;
-
 /* -------------------------------------------------------------------- */
 /*      Compute the "x" coefficients for this segment.                  */
 /* -------------------------------------------------------------------- */
-        dfCx = padfTx[k];
-        dfBx = (3.0 * (pasDGNPoints[k+1].x - pasDGNPoints[k].x) / padfD[k]
+        const double dfCx = padfTx[k];
+        const double dfBx = (3.0 * (pasDGNPoints[k+1].x - pasDGNPoints[k].x) / padfD[k]
                 - 2.0 * padfTx[k] - padfTx[k+1]) / padfD[k];
-        dfAx = (padfTx[k] + padfTx[k+1]
+        const double dfAx = (padfTx[k] + padfTx[k+1]
                 - 2 * (pasDGNPoints[k+1].x - pasDGNPoints[k].x) / padfD[k])
             / (padfD[k] * padfD[k]);
 
 /* -------------------------------------------------------------------- */
 /*      Compute the Y coefficients for this segment.                    */
 /* -------------------------------------------------------------------- */
-        dfCy = padfTy[k];
-        dfBy = (3.0 * (pasDGNPoints[k+1].y - pasDGNPoints[k].y) / padfD[k]
+        const double dfCy = padfTy[k];
+        const double dfBy = (3.0 * (pasDGNPoints[k+1].y - pasDGNPoints[k].y) / padfD[k]
                 - 2.0 * padfTy[k] - padfTy[k+1]) / padfD[k];
-        dfAy = (padfTy[k] + padfTy[k+1]
+        const double dfAy = (padfTy[k] + padfTy[k+1]
                 - 2 * (pasDGNPoints[k+1].y - pasDGNPoints[k].y) / padfD[k])
             / (padfD[k] * padfD[k]);
 
@@ -307,23 +307,24 @@ int main( int argc, char ** argv )
 {
     if( argc != 5 )
     {
-        printf( "Usage: stroke primary_axis secondary_axis axis_rotation angle\n" );
+        printf(  // ok
+            "Usage: stroke primary_axis secondary_axis axis_rotation angle\n");
         exit( 1 );
     }
 
-    double      dfX, dfY, dfPrimary, dfSecondary, dfAxisRotation, dfAngle;
-
-    dfPrimary = CPLAtof(argv[1]);
-    dfSecondary = CPLAtof(argv[2]);
-    dfAxisRotation = CPLAtof(argv[3]) / 180 * M_PI;
-    dfAngle = CPLAtof(argv[4]) / 180 * M_PI;
+    const double dfPrimary = CPLAtof(argv[1]);
+    const double dfSecondary = CPLAtof(argv[2]);
+    const double dfAxisRotation = CPLAtof(argv[3]) / 180 * M_PI;
+    const double dfAngle = CPLAtof(argv[4]) / 180 * M_PI;
 
+    double dfX = 0.0;
+    double dfY = 0.0;
     ComputePointOnArc2D( dfPrimary, dfSecondary, dfAxisRotation, dfAngle,
                          &dfX, &dfY );
 
-    printf( "X=%.2f, Y=%.2f\n", dfX, dfY );
+    printf( "X=%.2f, Y=%.2f\n", dfX, dfY );  // ok
 
-    exit( 0 );
+    return 0;
 }
 
 #endif
diff --git a/ogr/ogrsf_frmts/dgn/dgnwrite.cpp b/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
index ee853f4..ca9ef4d 100644
--- a/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
+++ b/ogr/ogrsf_frmts/dgn/dgnwrite.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: dgnwrite.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Microstation DGN Access Library
  * Purpose:  DGN Access functions related to writing DGN elements.
@@ -30,7 +29,11 @@
 
 #include "dgnlibp.h"
 
-CPL_CVSID("$Id: dgnwrite.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+#include <cmath>
+
+#include <algorithm>
+
+CPL_CVSID("$Id: dgnwrite.cpp 36016 2016-10-29 04:12:00Z goatbar $");
 
 static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
                            unsigned char *pabyTarget );
@@ -144,7 +147,7 @@ int DGNResizeElement( DGNHandle hDGN, DGNElemCore *psElement, int nNewSize )
 /* -------------------------------------------------------------------- */
 /*      Update the size information within the raw buffer.              */
 /* -------------------------------------------------------------------- */
-    int nWords = (nNewSize / 2) - 2;
+    const int nWords = (nNewSize / 2) - 2;
 
     psElement->raw_data[2] = (unsigned char) (nWords % 256);
     psElement->raw_data[3] = (unsigned char) (nWords / 256);
@@ -201,7 +204,7 @@ int DGNWriteElement( DGNHandle hDGN, DGNElemCore *psElement )
         if( !DGNGotoElement( hDGN, psDGN->element_count-1 ) )
             return FALSE;
 
-        int nJunk;
+        int nJunk = 0;
         if( !DGNLoadRawElement( psDGN, &nJunk, &nJunk ) )
             return FALSE;
 
@@ -256,10 +259,7 @@ int DGNWriteElement( DGNHandle hDGN, DGNElemCore *psElement )
 /* -------------------------------------------------------------------- */
     if( psDGN->next_element_id == psDGN->element_count )
     {
-        unsigned char abyEOF[2];
-
-        abyEOF[0] = 0xff;
-        abyEOF[1] = 0xff;
+        const unsigned char abyEOF[2] = { 0xff, 0xff };
 
         VSIFWrite( abyEOF, 2, 1, psDGN->fp );
         VSIFSeek( psDGN->fp, -2, SEEK_CUR );
@@ -314,27 +314,23 @@ DGNHandle
                  const char *pszMasterUnits, const char *pszSubUnits )
 
 {
-    DGNInfo *psSeed, *psDGN;
-    FILE    *fpNew;
-    DGNElemCore *psSrcTCB;
-
 /* -------------------------------------------------------------------- */
 /*      Open seed file, and read TCB element.                           */
 /* -------------------------------------------------------------------- */
-    psSeed = (DGNInfo *) DGNOpen( pszSeedFile, FALSE );
+    DGNInfo *psSeed = (DGNInfo *) DGNOpen( pszSeedFile, FALSE );
     if( psSeed == NULL )
         return NULL;
 
     DGNSetOptions( psSeed, DGNO_CAPTURE_RAW_DATA );
 
-    psSrcTCB = DGNReadElement( psSeed );
+    DGNElemCore *psSrcTCB = DGNReadElement( psSeed );
 
     CPLAssert( psSrcTCB->raw_bytes >= 1536 );
 
 /* -------------------------------------------------------------------- */
 /*      Open output file.                                               */
 /* -------------------------------------------------------------------- */
-    fpNew = VSIFOpen( pszNewFilename, "wb" );
+    FILE *fpNew = VSIFOpen( pszNewFilename, "wb" );
     if( fpNew == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -345,7 +341,7 @@ DGNHandle
 /* -------------------------------------------------------------------- */
 /*      Modify TCB appropriately for the output file.                   */
 /* -------------------------------------------------------------------- */
-    GByte *pabyRawTCB = (GByte *) CPLMalloc(psSrcTCB->raw_bytes);
+    GByte *pabyRawTCB = static_cast<GByte *>(CPLMalloc(psSrcTCB->raw_bytes));
 
     memcpy( pabyRawTCB, psSrcTCB->raw_data, psSrcTCB->raw_bytes );
 
@@ -381,13 +377,10 @@ DGNHandle
 /* -------------------------------------------------------------------- */
 /*      Write TCB and EOF to new file.                                  */
 /* -------------------------------------------------------------------- */
-    unsigned char abyEOF[2];
-
     VSIFWrite( pabyRawTCB, psSrcTCB->raw_bytes, 1, fpNew );
     CPLFree( pabyRawTCB );
 
-    abyEOF[0] = 0xff;
-    abyEOF[1] = 0xff;
+    unsigned char abyEOF[2] = { 0xff,  0xff };
 
     VSIFWrite( abyEOF, 2, 1, fpNew );
 
@@ -398,12 +391,13 @@ DGNHandle
 /* -------------------------------------------------------------------- */
     VSIFClose( fpNew );
 
-    psDGN = (DGNInfo *) DGNOpen( pszNewFilename, TRUE );
+    DGNInfo *psDGN = (DGNInfo *) DGNOpen( pszNewFilename, TRUE );
 
 /* -------------------------------------------------------------------- */
 /*      Now copy over elements according to options in effect.          */
 /* -------------------------------------------------------------------- */
-    DGNElemCore *psSrcElement, *psDstElement;
+    DGNElemCore *psSrcElement = NULL;
+    DGNElemCore *psDstElement = NULL;
 
     while( (psSrcElement = DGNReadElement( psSeed )) != NULL )
     {
@@ -461,107 +455,93 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
 /* -------------------------------------------------------------------- */
     if( psSrcElement->stype == DGNST_CORE )
     {
-        psClone = (DGNElemCore *) CPLMalloc(sizeof(DGNElemCore));
+        psClone = static_cast<DGNElemCore *>(CPLMalloc(sizeof(DGNElemCore)));
         memcpy( psClone, psSrcElement, sizeof(DGNElemCore) );
     }
     else if( psSrcElement->stype == DGNST_MULTIPOINT )
     {
-        DGNElemMultiPoint *psMP, *psSrcMP;
-        size_t             nSize;
-
-        psSrcMP = (DGNElemMultiPoint *) psSrcElement;
+        DGNElemMultiPoint *psSrcMP = (DGNElemMultiPoint *) psSrcElement;
 
-        nSize = sizeof(DGNElemMultiPoint)
+        const size_t nSize = sizeof(DGNElemMultiPoint)
             + sizeof(DGNPoint) * (psSrcMP->num_vertices-2);
 
-        psMP = (DGNElemMultiPoint *) CPLMalloc( nSize );
+        DGNElemMultiPoint *psMP =
+            static_cast<DGNElemMultiPoint *>(CPLMalloc( nSize ));
         memcpy( psMP, psSrcElement, nSize );
 
         psClone = (DGNElemCore *) psMP;
     }
     else if( psSrcElement->stype == DGNST_ARC )
     {
-        DGNElemArc *psArc;
-
-        psArc = (DGNElemArc *) CPLMalloc(sizeof(DGNElemArc));
+        DGNElemArc *psArc =
+            static_cast<DGNElemArc *>(CPLMalloc(sizeof(DGNElemArc)));
         memcpy( psArc, psSrcElement, sizeof(DGNElemArc) );
 
         psClone = (DGNElemCore *) psArc;
     }
     else if( psSrcElement->stype == DGNST_TEXT )
     {
-        DGNElemText       *psText, *psSrcText;
-        size_t             nSize;
+        DGNElemText *psSrcText = (DGNElemText *) psSrcElement;
+        const size_t nSize = sizeof(DGNElemText) + strlen(psSrcText->string);
 
-        psSrcText = (DGNElemText *) psSrcElement;
-        nSize = sizeof(DGNElemText) + strlen(psSrcText->string);
-
-        psText = (DGNElemText *) CPLMalloc( nSize );
+        DGNElemText *psText =
+          static_cast<DGNElemText *>(CPLMalloc( nSize ));
         memcpy( psText, psSrcElement, nSize );
 
         psClone = (DGNElemCore *) psText;
     }
     else if( psSrcElement->stype == DGNST_TEXT_NODE )
     {
-        DGNElemTextNode *psNode;
-
-        psNode = (DGNElemTextNode *)
-            CPLMalloc(sizeof(DGNElemTextNode));
+        DGNElemTextNode *psNode = static_cast<DGNElemTextNode *>(
+            CPLMalloc(sizeof(DGNElemTextNode)));
         memcpy( psNode, psSrcElement, sizeof(DGNElemTextNode) );
 
         psClone = (DGNElemCore *) psNode;
     }
     else if( psSrcElement->stype == DGNST_COMPLEX_HEADER )
     {
-        DGNElemComplexHeader *psCH;
-
-        psCH = (DGNElemComplexHeader *)
-            CPLMalloc(sizeof(DGNElemComplexHeader));
+        DGNElemComplexHeader *psCH = static_cast<DGNElemComplexHeader *>(
+            CPLMalloc(sizeof(DGNElemComplexHeader)));
         memcpy( psCH, psSrcElement, sizeof(DGNElemComplexHeader) );
 
         psClone = (DGNElemCore *) psCH;
     }
     else if( psSrcElement->stype == DGNST_COLORTABLE )
     {
-        DGNElemColorTable *psCT;
-
-        psCT = (DGNElemColorTable *) CPLMalloc(sizeof(DGNElemColorTable));
+        DGNElemColorTable *psCT = static_cast<DGNElemColorTable *>(
+            CPLMalloc(sizeof(DGNElemColorTable)));
         memcpy( psCT, psSrcElement, sizeof(DGNElemColorTable) );
 
         psClone = (DGNElemCore *) psCT;
     }
     else if( psSrcElement->stype == DGNST_TCB )
     {
-        DGNElemTCB *psTCB;
-
-        psTCB = (DGNElemTCB *) CPLMalloc(sizeof(DGNElemTCB));
+        DGNElemTCB *psTCB =
+            static_cast<DGNElemTCB *>(CPLMalloc(sizeof(DGNElemTCB)));
         memcpy( psTCB, psSrcElement, sizeof(DGNElemTCB) );
 
         psClone = (DGNElemCore *) psTCB;
     }
     else if( psSrcElement->stype == DGNST_CELL_HEADER )
     {
-        DGNElemCellHeader *psCH;
-
-        psCH = (DGNElemCellHeader *) CPLMalloc(sizeof(DGNElemCellHeader));
+        DGNElemCellHeader *psCH = static_cast<DGNElemCellHeader *>(
+            CPLMalloc(sizeof(DGNElemCellHeader)));
         memcpy( psCH, psSrcElement, sizeof(DGNElemCellHeader) );
 
         psClone = (DGNElemCore *) psCH;
     }
     else if( psSrcElement->stype == DGNST_CELL_LIBRARY )
     {
-        DGNElemCellLibrary *psCL;
-
-        psCL = (DGNElemCellLibrary *) CPLMalloc(sizeof(DGNElemCellLibrary));
+        DGNElemCellLibrary *psCL = static_cast<DGNElemCellLibrary *>(
+            CPLMalloc(sizeof(DGNElemCellLibrary)));
         memcpy( psCL, psSrcElement, sizeof(DGNElemCellLibrary) );
 
         psClone = (DGNElemCore *) psCL;
     }
     else if( psSrcElement->stype == DGNST_TAG_VALUE )
     {
-        DGNElemTagValue *psTV;
-
-        psTV = (DGNElemTagValue *) CPLMalloc(sizeof(DGNElemTagValue));
+        DGNElemTagValue *psTV = static_cast<DGNElemTagValue *>(
+            CPLMalloc(sizeof(DGNElemTagValue)));
         memcpy( psTV, psSrcElement, sizeof(DGNElemTagValue) );
 
         if( psTV->tagType == 1 )
@@ -571,21 +551,18 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     }
     else if( psSrcElement->stype == DGNST_TAG_SET )
     {
-        DGNElemTagSet *psTS;
-        int iTag;
-        DGNTagDef *pasTagList;
-
-        psTS = (DGNElemTagSet *) CPLMalloc(sizeof(DGNElemTagSet));
+        DGNElemTagSet *psTS = static_cast<DGNElemTagSet *>(
+            CPLMalloc(sizeof(DGNElemTagSet)));
         memcpy( psTS, psSrcElement, sizeof(DGNElemTagSet) );
 
         psTS->tagSetName = CPLStrdup( psTS->tagSetName );
 
-        pasTagList = (DGNTagDef *)
-            CPLMalloc( sizeof(DGNTagDef) * psTS->tagCount );
+        DGNTagDef *pasTagList = static_cast<DGNTagDef *>(
+            CPLMalloc( sizeof(DGNTagDef) * psTS->tagCount ));
         memcpy( pasTagList, psTS->tagList,
                 sizeof(DGNTagDef) * psTS->tagCount );
 
-        for( iTag = 0; iTag < psTS->tagCount; iTag++ )
+        for( int iTag = 0; iTag < psTS->tagCount; iTag++ )
         {
             pasTagList[iTag].name = CPLStrdup( pasTagList[iTag].name );
             pasTagList[iTag].prompt = CPLStrdup( pasTagList[iTag].prompt );
@@ -599,79 +576,74 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
     }
     else if( psSrcElement->stype == DGNST_CONE )
     {
-        DGNElemCone *psCone;
-
-        psCone = (DGNElemCone *) CPLMalloc(sizeof(DGNElemCone));
+        DGNElemCone *psCone = static_cast<DGNElemCone *>(
+            CPLMalloc(sizeof(DGNElemCone)));
         memcpy( psCone, psSrcElement, sizeof(DGNElemCone) );
 
         psClone = (DGNElemCore *) psCone;
     }
     else if( psSrcElement->stype == DGNST_BSPLINE_SURFACE_HEADER )
     {
-        DGNElemBSplineSurfaceHeader *psSurface;
-
-        psSurface = (DGNElemBSplineSurfaceHeader *)
-          CPLMalloc(sizeof(DGNElemBSplineSurfaceHeader));
+        DGNElemBSplineSurfaceHeader *psSurface =
+            static_cast<DGNElemBSplineSurfaceHeader *>(
+                CPLMalloc(sizeof(DGNElemBSplineSurfaceHeader)));
         memcpy( psSurface, psSrcElement, sizeof(DGNElemBSplineSurfaceHeader) );
 
         psClone = (DGNElemCore *) psSurface;
     }
     else if( psSrcElement->stype == DGNST_BSPLINE_CURVE_HEADER )
     {
-        DGNElemBSplineCurveHeader *psCurve;
-
-        psCurve = (DGNElemBSplineCurveHeader *)
-          CPLMalloc(sizeof(DGNElemBSplineCurveHeader));
+        DGNElemBSplineCurveHeader *psCurve =
+            static_cast<DGNElemBSplineCurveHeader *>(
+                CPLMalloc(sizeof(DGNElemBSplineCurveHeader)));
         memcpy( psCurve, psSrcElement, sizeof(DGNElemBSplineCurveHeader) );
 
         psClone = (DGNElemCore *) psCurve;
     }
     else if( psSrcElement->stype == DGNST_BSPLINE_SURFACE_BOUNDARY )
     {
-        DGNElemBSplineSurfaceBoundary *psBSB, *psSrcBSB;
-        size_t             nSize;
-
-        psSrcBSB = (DGNElemBSplineSurfaceBoundary *) psSrcElement;
+        DGNElemBSplineSurfaceBoundary *psSrcBSB =
+            (DGNElemBSplineSurfaceBoundary *) psSrcElement;
 
-        nSize = sizeof(DGNElemBSplineSurfaceBoundary)
+        const size_t nSize = sizeof(DGNElemBSplineSurfaceBoundary)
             + sizeof(DGNPoint) * (psSrcBSB->numverts-1);
 
-        psBSB = (DGNElemBSplineSurfaceBoundary *) CPLMalloc( nSize );
+        DGNElemBSplineSurfaceBoundary *psBSB =
+            static_cast<DGNElemBSplineSurfaceBoundary *>(
+                CPLMalloc( nSize ));
         memcpy( psBSB, psSrcElement, nSize );
 
         psClone = (DGNElemCore *) psBSB;
     }
     else if( psSrcElement->stype == DGNST_KNOT_WEIGHT )
     {
-        DGNElemKnotWeight *psArray /* , *psSrcArray*/;
-        size_t             nSize;
-        int                numelems;
-
         // FIXME: Is it OK to assume that the # of elements corresponds
         // directly to the element size? kintel 20051218.
-        numelems = (psSrcElement->size - 36 - psSrcElement->attr_bytes)/4;
+        const int numelems =
+            (psSrcElement->size - 36 - psSrcElement->attr_bytes)/4;
 
-        /* psSrcArray = (DGNElemKnotWeight *) psSrcElement; */
+        /* DGNElemKnotWeight *psSrcArray = (DGNElemKnotWeight *) psSrcElement; */
 
-        nSize = sizeof(DGNElemKnotWeight) + sizeof(long) * (numelems-1);
+        const size_t nSize =
+            sizeof(DGNElemKnotWeight) + sizeof(long) * (numelems-1);
 
-        psArray = (DGNElemKnotWeight *) CPLMalloc( nSize );
+        DGNElemKnotWeight *psArray = static_cast<DGNElemKnotWeight *>(
+            CPLMalloc( nSize ));
         memcpy( psArray, psSrcElement, nSize );
 
         psClone = (DGNElemCore *) psArray;
     }
     else if( psSrcElement->stype == DGNST_SHARED_CELL_DEFN )
     {
-        DGNElemSharedCellDefn *psCH;
-
-        psCH = (DGNElemSharedCellDefn *)CPLMalloc(sizeof(DGNElemSharedCellDefn));
+        DGNElemSharedCellDefn *psCH = static_cast<DGNElemSharedCellDefn *>(
+            CPLMalloc(sizeof(DGNElemSharedCellDefn)));
         memcpy( psCH, psSrcElement, sizeof(DGNElemSharedCellDefn) );
 
         psClone = (DGNElemCore *) psCH;
     }
     else
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return NULL;
     }
 
@@ -680,14 +652,16 @@ DGNElemCore *DGNCloneElement( CPL_UNUSED DGNHandle hDGNSrc,
 /* -------------------------------------------------------------------- */
     if( psClone->raw_bytes != 0 )
     {
-        psClone->raw_data = (unsigned char *) CPLMalloc(psClone->raw_bytes);
+        psClone->raw_data = static_cast<unsigned char *>(
+            CPLMalloc(psClone->raw_bytes));
         memcpy( psClone->raw_data, psSrcElement->raw_data,
                 psClone->raw_bytes );
     }
 
     if( psClone->attr_bytes != 0 )
     {
-        psClone->attr_data = (unsigned char *) CPLMalloc(psClone->attr_bytes);
+        psClone->attr_data = static_cast<unsigned char *>(
+            CPLMalloc(psClone->attr_bytes));
         memcpy( psClone->attr_data, psSrcElement->attr_data,
                 psClone->attr_bytes );
     }
@@ -757,17 +731,16 @@ int DGNUpdateElemCore( DGNHandle hDGN, DGNElemCore *psElement,
  * @return TRUE on success, or FALSE on failure.
  */
 
-
 int DGNUpdateElemCoreExtended( CPL_UNUSED DGNHandle hDGN,
                                DGNElemCore *psElement )
 {
     GByte *rd = psElement->raw_data;
-    int   nWords = (psElement->raw_bytes / 2) - 2;
+    const int nWords = (psElement->raw_bytes / 2) - 2;
 
     if( psElement->raw_data == NULL
         || psElement->raw_bytes < 36 )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return FALSE;
     }
 
@@ -791,7 +764,7 @@ int DGNUpdateElemCoreExtended( CPL_UNUSED DGNHandle hDGN,
 /* -------------------------------------------------------------------- */
     if( psElement->raw_data[30] == 0 && psElement->raw_data[31] == 0 )
     {
-        int     nAttIndex = (psElement->raw_bytes - 32) / 2;
+        const int nAttIndex = (psElement->raw_bytes - 32) / 2;
 
         psElement->raw_data[30] = (GByte) (nAttIndex % 256);
         psElement->raw_data[31] = (GByte) (nAttIndex / 256);
@@ -878,10 +851,7 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
                                       int nPointCount, DGNPoint *pasVertices )
 
 {
-    DGNElemMultiPoint *psMP;
-    DGNElemCore *psCore;
     DGNInfo *psDGN = (DGNInfo *) hDGN;
-    DGNPoint sMin, sMax;
 
     CPLAssert( nType == DGNT_LINE
                || nType == DGNT_LINE_STRING
@@ -906,10 +876,10 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psMP = (DGNElemMultiPoint *)
+    DGNElemMultiPoint *psMP = static_cast<DGNElemMultiPoint *>(
         CPLCalloc( sizeof(DGNElemMultiPoint)
-                   + sizeof(DGNPoint) * (nPointCount-2), 1 );
-    psCore = &(psMP->core);
+                   + sizeof(DGNPoint) * (nPointCount-2), 1 ));
+    DGNElemCore *psCore = &(psMP->core);
 
     DGNInitializeElemCore( hDGN, psCore );
     psCore->stype = DGNST_MULTIPOINT;
@@ -931,7 +901,8 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
 
         psCore->raw_bytes = 36 + psDGN->dimension* 4 * nPointCount;
 
-        psCore->raw_data = (unsigned char*) CPLCalloc(psCore->raw_bytes,1);
+        psCore->raw_data = static_cast<unsigned char *>(
+            CPLCalloc(psCore->raw_bytes, 1));
 
         DGNInverseTransformPointToInt( psDGN, pasVertices + 0,
                                        psCore->raw_data + 36 );
@@ -944,7 +915,8 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
         CPLAssert( nPointCount >= 2 );
 
         psCore->raw_bytes = 38 + psDGN->dimension * 4 * nPointCount;
-        psCore->raw_data = (unsigned char*) CPLCalloc(psCore->raw_bytes,1);
+        psCore->raw_data = static_cast<unsigned char *>(
+            CPLCalloc(psCore->raw_bytes, 1));
 
         psCore->raw_data[36] = (unsigned char) (nPointCount % 256);
         psCore->raw_data[37] = (unsigned char) (nPointCount/256);
@@ -960,15 +932,16 @@ DGNElemCore *DGNCreateMultiPointElem( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
     DGNUpdateElemCoreExtended( hDGN, psCore );
 
-    sMin = sMax = pasVertices[0];
+    DGNPoint sMin = pasVertices[0];
+    DGNPoint sMax = pasVertices[0];
     for( int i = 1; i < nPointCount; i++ )
     {
-        sMin.x = MIN(pasVertices[i].x,sMin.x);
-        sMin.y = MIN(pasVertices[i].y,sMin.y);
-        sMin.z = MIN(pasVertices[i].z,sMin.z);
-        sMax.x = MAX(pasVertices[i].x,sMax.x);
-        sMax.y = MAX(pasVertices[i].y,sMax.y);
-        sMax.z = MAX(pasVertices[i].z,sMax.z);
+        sMin.x = std::min(pasVertices[i].x, sMin.x);
+        sMin.y = std::min(pasVertices[i].y, sMin.y);
+        sMin.z = std::min(pasVertices[i].z, sMin.z);
+        sMax.x = std::max(pasVertices[i].x, sMax.x);
+        sMax.y = std::max(pasVertices[i].y, sMax.y);
+        sMax.z = std::max(pasVertices[i].z, sMax.z);
     }
 
     DGNWriteBounds( psDGN, psCore, &sMin, &sMax );
@@ -1031,21 +1004,17 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
                   double dfRotation, int *panQuaternion )
 
 {
-    DGNElemArc *psArc;
-    DGNElemCore *psCore;
-    DGNInfo *psDGN = (DGNInfo *) hDGN;
-    DGNPoint sMin, sMax, sOrigin;
-    GInt32 nAngle;
-
     CPLAssert( nType == DGNT_ARC || nType == DGNT_ELLIPSE );
 
+    DGNInfo *psDGN = (DGNInfo *) hDGN;
     DGNLoadTCB( hDGN );
 
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psArc = (DGNElemArc *) CPLCalloc( sizeof(DGNElemArc), 1 );
-    psCore = &(psArc->core);
+    DGNElemArc *psArc = static_cast<DGNElemArc *>(
+        CPLCalloc(sizeof(DGNElemArc), 1));
+    DGNElemCore *psCore = &(psArc->core);
 
     DGNInitializeElemCore( hDGN, psCore );
     psCore->stype = DGNST_ARC;
@@ -1054,9 +1023,7 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
 /*      Set arc specific information in the structure.                  */
 /* -------------------------------------------------------------------- */
-    sOrigin.x = dfOriginX;
-    sOrigin.y = dfOriginY;
-    sOrigin.z = dfOriginZ;
+    DGNPoint sOrigin = { dfOriginX, dfOriginY, dfOriginZ };
 
     psArc->origin = sOrigin;
     psArc->primary_axis = dfPrimaryAxis;
@@ -1078,6 +1045,8 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
 /*      Setup Raw data for the arc section.                             */
 /* -------------------------------------------------------------------- */
+    GInt32 nAngle = 0;
+
     if( nType == DGNT_ARC )
     {
         double dfScaledAxis;
@@ -1086,7 +1055,8 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
             psCore->raw_bytes = 100;
         else
             psCore->raw_bytes = 80;
-        psCore->raw_data = (unsigned char*) CPLCalloc(psCore->raw_bytes,1);
+        psCore->raw_data = static_cast<unsigned char *>(
+            CPLCalloc(psCore->raw_bytes, 1));
 
         /* start angle */
         nAngle = (int) (dfStartAngle * 360000.0);
@@ -1095,7 +1065,7 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
         /* sweep angle */
         if( dfSweepAngle < 0.0 )
         {
-            nAngle = (int) (ABS(dfSweepAngle) * 360000.0);
+            nAngle = static_cast<int>(std::abs(dfSweepAngle) * 360000.0);
             nAngle |= 0x80000000;
         }
         else if( dfSweepAngle > 364.9999 )
@@ -1211,12 +1181,16 @@ DGNCreateArcElem( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
     DGNUpdateElemCoreExtended( hDGN, psCore );
 
-    sMin.x = dfOriginX - MAX(dfPrimaryAxis,dfSecondaryAxis);
-    sMin.y = dfOriginY - MAX(dfPrimaryAxis,dfSecondaryAxis);
-    sMin.z = dfOriginZ - MAX(dfPrimaryAxis,dfSecondaryAxis);
-    sMax.x = dfOriginX + MAX(dfPrimaryAxis,dfSecondaryAxis);
-    sMax.y = dfOriginY + MAX(dfPrimaryAxis,dfSecondaryAxis);
-    sMax.z = dfOriginZ + MAX(dfPrimaryAxis,dfSecondaryAxis);
+    DGNPoint sMin = {
+        dfOriginX - std::max(dfPrimaryAxis, dfSecondaryAxis),
+        dfOriginY - std::max(dfPrimaryAxis, dfSecondaryAxis),
+        dfOriginZ - std::max(dfPrimaryAxis, dfSecondaryAxis)
+    };
+    DGNPoint sMax = {
+        dfOriginX + std::max(dfPrimaryAxis, dfSecondaryAxis),
+        dfOriginY + std::max(dfPrimaryAxis, dfSecondaryAxis),
+        dfOriginZ + std::max(dfPrimaryAxis, dfSecondaryAxis)
+    };
 
     DGNWriteBounds( psDGN, psCore, &sMin, &sMax );
 
@@ -1258,19 +1232,15 @@ DGNCreateConeElem( DGNHandle hDGN,
                    double dfCenter_2Z, double dfRadius_2,
                    int *panQuaternion )
 {
-    DGNElemCone *psCone;
-    DGNElemCore *psCore;
     DGNInfo *psDGN = (DGNInfo *) hDGN;
-    DGNPoint sMin, sMax, sCenter_1, sCenter_2;
-    double dfScaledRadius;
 
     DGNLoadTCB( hDGN );
 
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psCone = (DGNElemCone *) CPLCalloc( sizeof(DGNElemCone), 1 );
-    psCore = &(psCone->core);
+    DGNElemCone *psCone = (DGNElemCone *) CPLCalloc( sizeof(DGNElemCone), 1 );
+    DGNElemCore *psCore = &(psCone->core);
 
     DGNInitializeElemCore( hDGN, psCore );
     psCore->stype = DGNST_CONE;
@@ -1279,12 +1249,8 @@ DGNCreateConeElem( DGNHandle hDGN,
 /* -------------------------------------------------------------------- */
 /*      Set cone specific information in the structure.                 */
 /* -------------------------------------------------------------------- */
-    sCenter_1.x = dfCenter_1X;
-    sCenter_1.y = dfCenter_1Y;
-    sCenter_1.z = dfCenter_1Z;
-    sCenter_2.x = dfCenter_2X;
-    sCenter_2.y = dfCenter_2Y;
-    sCenter_2.z = dfCenter_2Z;
+    DGNPoint sCenter_1 = { dfCenter_1X, dfCenter_1Y, dfCenter_1Z };
+    DGNPoint sCenter_2 = { dfCenter_2X, dfCenter_2Y, dfCenter_2Z };
     psCone->center_1 = sCenter_1;
     psCone->center_2 = sCenter_2;
     psCone->radius_1 = dfRadius_1;
@@ -1295,7 +1261,8 @@ DGNCreateConeElem( DGNHandle hDGN,
     {
         memcpy( psCone->quat, panQuaternion, sizeof(int)*4 );
     }
-    else {
+    else
+    {
       psCone->quat[0] = 1 << 31;
       psCone->quat[1] = 0;
       psCone->quat[2] = 0;
@@ -1328,7 +1295,7 @@ DGNCreateConeElem( DGNHandle hDGN,
     IEEE2DGNDouble( psCore->raw_data + 70 );
 
     /* radius_1 */
-    dfScaledRadius = psCone->radius_1 / psDGN->scale;
+    double dfScaledRadius = psCone->radius_1 / psDGN->scale;
     memcpy( psCore->raw_data + 78, &dfScaledRadius, 8 );
     IEEE2DGNDouble( psCore->raw_data + 78 );
 
@@ -1365,6 +1332,8 @@ DGNCreateConeElem( DGNHandle hDGN,
 //     sMax.y = psCone->center_2.y+largestRadius;
 //     sMax.z = psCone->center_2.z;
 
+    DGNPoint sMin = { 0.0, 0.0, 0.0 };
+    DGNPoint sMax = { 0.0, 0.0, 0.0 };
     DGNWriteBounds( psDGN, psCore, &sMin, &sMax );
 
     return (DGNElemCore*) psCone;
@@ -1406,21 +1375,16 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
                    double dfOriginX, double dfOriginY, double dfOriginZ )
 
 {
-    DGNElemText *psText;
-    DGNElemCore *psCore;
     DGNInfo *psDGN = (DGNInfo *) hDGN;
-    DGNPoint sMin, sMax, sLowLeft, sLowRight, sUpLeft, sUpRight;
-    GInt32 nIntValue, nBase;
-    double length, height, diagonal;
 
     DGNLoadTCB( hDGN );
 
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psText = (DGNElemText *)
+    DGNElemText *psText = (DGNElemText *)
         CPLCalloc( sizeof(DGNElemText)+strlen(pszText), 1 );
-    psCore = &(psText->core);
+    DGNElemCore *psCore = &(psText->core);
 
     DGNInitializeElemCore( hDGN, psCore );
     psCore->stype = DGNST_TEXT;
@@ -1453,12 +1417,15 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
     psCore->raw_data[36] = (unsigned char) nFontId;
     psCore->raw_data[37] = (unsigned char) nJustification;
 
-    nIntValue = (int) (dfLengthMult * 1000.0 / (psDGN->scale * 6.0) + 0.5);
+    GInt32 nIntValue =
+        static_cast<int>(dfLengthMult * 1000.0 / (psDGN->scale * 6.0) + 0.5);
     DGN_WRITE_INT32( nIntValue, psCore->raw_data + 38 );
 
     nIntValue = (int) (dfHeightMult * 1000.0 / (psDGN->scale * 6.0) + 0.5);
     DGN_WRITE_INT32( nIntValue, psCore->raw_data + 42 );
 
+    GInt32 nBase = 0;
+
     if( psDGN->dimension == 2 )
     {
         nIntValue = (int) (dfRotation * 360000.0);
@@ -1500,31 +1467,43 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
     DGNUpdateElemCoreExtended( hDGN, psCore );
 
     //calculate bounds if rotation is 0
-    sMin.x = dfOriginX;
-    sMin.y = dfOriginY;
-    sMin.z = 0.0;
-    sMax.x = dfOriginX + dfLengthMult * strlen(pszText);
-    sMax.y = dfOriginY + dfHeightMult;
-    sMax.z = 0.0;
+    DGNPoint sMin = { dfOriginX, dfOriginY, 0.0 };
+    DGNPoint sMax = {
+        dfOriginX + dfLengthMult * strlen(pszText),
+        dfOriginY + dfHeightMult,
+        0.0
+    };
 
     //calculate rotated bounding box coordinates
-    length = sMax.x-sMin.x;
-    height = sMax.y-sMin.y;
-    diagonal=sqrt(length*length+height*height);
-    sLowLeft.x=sMin.x;
-    sLowLeft.y=sMin.y;
-    sLowRight.x=sMin.x+cos(psText->rotation*M_PI/180.0)*length;
-    sLowRight.y=sMin.y+sin(psText->rotation*M_PI/180.0)*length;
-    sUpRight.x=sMin.x+cos((psText->rotation*M_PI/180.0)+atan(height/length))*diagonal;
-    sUpRight.y=sMin.y+sin((psText->rotation*M_PI/180.0)+atan(height/length))*diagonal;
-    sUpLeft.x=sMin.x+cos((psText->rotation+90.0)*M_PI/180.0)*height;
-    sUpLeft.y=sMin.y+sin((psText->rotation+90.0)*M_PI/180.0)*height;
+    const double length = sMax.x-sMin.x;
+    const double height = sMax.y-sMin.y;
+    const double diagonal=sqrt(length*length+height*height);
+    const DGNPoint sLowLeft = { sMin.x, sMin.y, 0.0 };
+    const DGNPoint sLowRight = {
+       sMin.x+cos(psText->rotation*M_PI/180.0)*length,
+       sMin.y+sin(psText->rotation*M_PI/180.0)*length,
+       0.0
+    };
+    const DGNPoint sUpRight = {
+        sMin.x+cos((psText->rotation*M_PI/180.0)+atan(height/length))*diagonal,
+        sMin.y+sin((psText->rotation*M_PI/180.0)+atan(height/length))*diagonal,
+        0.0
+    };
+    const DGNPoint sUpLeft = {
+        sMin.x+cos((psText->rotation+90.0)*M_PI/180.0)*height,
+        sMin.y+sin((psText->rotation+90.0)*M_PI/180.0)*height,
+        0.0
+    };
 
     //calculate new values for bounding box
-    sMin.x=MIN(sLowLeft.x,MIN(sLowRight.x,MIN(sUpLeft.x,sUpRight.x)));
-    sMin.y=MIN(sLowLeft.y,MIN(sLowRight.y,MIN(sUpLeft.y,sUpRight.y)));
-    sMax.x=MAX(sLowLeft.x,MAX(sLowRight.x,MAX(sUpLeft.x,sUpRight.x)));
-    sMax.y=MAX(sLowLeft.y,MAX(sLowRight.y,MAX(sUpLeft.y,sUpRight.y)));
+    sMin.x = std::min(sLowLeft.x,
+                      std::min(sLowRight.x, std::min(sUpLeft.x, sUpRight.x)));
+    sMin.y = std::min(sLowLeft.y,
+                      std::min(sLowRight.y, std::min(sUpLeft.y, sUpRight.y)));
+    sMax.x = std::max(sLowLeft.x,
+                      std::max(sLowRight.x, std::max(sUpLeft.x, sUpRight.x)));
+    sMax.y = std::max(sLowLeft.y,
+                      std::max(sLowRight.y, std::max(sUpLeft.y, sUpRight.y)));
     sMin.x = dfOriginX - dfLengthMult * strlen(pszText);
     sMin.y = dfOriginY - dfHeightMult;
     sMin.z = 0.0;
@@ -1563,20 +1542,17 @@ DGNCreateTextElem( DGNHandle hDGN, const char *pszText,
  * @return the new element (DGNElemColorTable) or NULL on failure.
  */
 
-
 DGNElemCore *
 DGNCreateColorTableElem( DGNHandle hDGN, int nScreenFlag,
                          GByte abyColorInfo[256][3] )
 
 {
-    DGNElemColorTable *psCT;
-    DGNElemCore *psCore;
-
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psCT = (DGNElemColorTable *) CPLCalloc( sizeof(DGNElemColorTable), 1 );
-    psCore = &(psCT->core);
+    DGNElemColorTable *psCT = (DGNElemColorTable *)
+        CPLCalloc( sizeof(DGNElemColorTable), 1 );
+    DGNElemCore *psCore = &(psCT->core);
 
     DGNInitializeElemCore( hDGN, psCore );
     psCore->stype = DGNST_COLORTABLE;
@@ -1638,8 +1614,6 @@ DGNElemCore *
 DGNCreateComplexHeaderElem( DGNHandle hDGN, int nType,
                             int nTotLength, int nNumElems )
 {
-    DGNElemComplexHeader *psCH;
-    DGNElemCore *psCore;
     unsigned char abyRawZeroLinkage[8] = {0,0,0,0,0,0,0,0};
 
     CPLAssert( nType == DGNT_COMPLEX_CHAIN_HEADER
@@ -1650,9 +1624,9 @@ DGNCreateComplexHeaderElem( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psCH = (DGNElemComplexHeader *)
+    DGNElemComplexHeader *psCH = (DGNElemComplexHeader *)
         CPLCalloc( sizeof(DGNElemComplexHeader), 1 );
-    psCore = &(psCH->core);
+    DGNElemCore *psCore = &(psCH->core);
 
     DGNInitializeElemCore( hDGN, psCore );
     psCore->complex = TRUE;
@@ -1722,11 +1696,6 @@ DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
                                  int nNumElems, DGNElemCore **papsElems )
 
 {
-    int         nTotalLength = 5;
-    int         i, nLevel;
-    DGNElemCore *psCH;
-    DGNPoint    sMin = {0.0,0.0,0.0}, sMax = {0.0,0.0,0.0};
-
     DGNLoadTCB( hDGN );
 
     if( nNumElems < 1 || papsElems == NULL )
@@ -1739,12 +1708,13 @@ DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
 /* -------------------------------------------------------------------- */
 /*      Collect the total size, and bounds.                             */
 /* -------------------------------------------------------------------- */
-    nLevel = papsElems[0]->level;
+    int nTotalLength = 5;
+    const int nLevel = papsElems[0]->level;
+    DGNPoint sMin = { 0.0, 0.0, 0.0 };
+    DGNPoint sMax = { 0.0, 0.0, 0.0 };
 
-    for( i = 0; i < nNumElems; i++ )
+    for( int i = 0; i < nNumElems; i++ )
     {
-        DGNPoint sThisMin, sThisMax;
-
         nTotalLength += papsElems[i]->raw_bytes / 2;
 
         papsElems[i]->complex = TRUE;
@@ -1756,6 +1726,9 @@ DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
                       "Not all level values matching in a complex set group!");
         }
 
+        DGNPoint sThisMin = { 0.0, 0.0, 0.0 };
+        DGNPoint sThisMax = { 0.0, 0.0, 0.0 };
+
         DGNGetElementExtents( hDGN, papsElems[i], &sThisMin, &sThisMax );
         if( i == 0 )
         {
@@ -1764,19 +1737,20 @@ DGNCreateComplexHeaderFromGroup( DGNHandle hDGN, int nType,
         }
         else
         {
-            sMin.x = MIN(sMin.x,sThisMin.x);
-            sMin.y = MIN(sMin.y,sThisMin.y);
-            sMin.z = MIN(sMin.z,sThisMin.z);
-            sMax.x = MAX(sMax.x,sThisMax.x);
-            sMax.y = MAX(sMax.y,sThisMax.y);
-            sMax.z = MAX(sMax.z,sThisMax.z);
+            sMin.x = std::min(sMin.x, sThisMin.x);
+            sMin.y = std::min(sMin.y, sThisMin.y);
+            sMin.z = std::min(sMin.z, sThisMin.z);
+            sMax.x = std::max(sMax.x, sThisMax.x);
+            sMax.y = std::max(sMax.y, sThisMax.y);
+            sMax.z = std::max(sMax.z, sThisMax.z);
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create the corresponding complex header.                        */
 /* -------------------------------------------------------------------- */
-    psCH = DGNCreateComplexHeaderElem( hDGN, nType, nTotalLength, nNumElems );
+    DGNElemCore *psCH =
+        DGNCreateComplexHeaderElem( hDGN, nType, nTotalLength, nNumElems );
     DGNUpdateElemCore( hDGN, psCH, papsElems[0]->level, psCH->graphic_group,
                        psCH->color, psCH->weight, psCH->style );
 
@@ -1899,11 +1873,6 @@ DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
                                DGNElemCore **papsElems )
 
 {
-    int         nTotalLength = 6;
-    int         i, nLevel;
-    DGNElemCore *psCH;
-    DGNPoint    sMin = {0.0,0.0,0.0}, sMax = {0.0,0.0,0.0};
-
     DGNLoadTCB( hDGN );
 
     if( nNumElems < 1 || papsElems == NULL )
@@ -1916,12 +1885,13 @@ DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
 /* -------------------------------------------------------------------- */
 /*      Collect the total size, and bounds.                             */
 /* -------------------------------------------------------------------- */
-    nLevel = papsElems[0]->level;
+    const int nLevel = papsElems[0]->level;
+    int nTotalLength = 6;
+    DGNPoint sMin = { 0.0, 0.0, 0.0 };
+    DGNPoint sMax = { 0.0, 0.0, 0.0 };
 
-    for( i = 0; i < nNumElems; i++ )
+    for( int i = 0; i < nNumElems; i++ )
     {
-        DGNPoint sThisMin, sThisMax;
-
         nTotalLength += papsElems[i]->raw_bytes / 2;
 
         papsElems[i]->complex = TRUE;
@@ -1933,6 +1903,8 @@ DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
                       "Not all level values matching in a complex set group!");
         }
 
+        DGNPoint sThisMin = { 0.0, 0.0, 0.0 };
+        DGNPoint sThisMax = { 0.0, 0.0, 0.0 };
         DGNGetElementExtents( hDGN, papsElems[i], &sThisMin, &sThisMax );
         if( i == 0 )
         {
@@ -1941,20 +1913,21 @@ DGNCreateSolidHeaderFromGroup( DGNHandle hDGN, int nType, int nSurfType,
         }
         else
         {
-            sMin.x = MIN(sMin.x,sThisMin.x);
-            sMin.y = MIN(sMin.y,sThisMin.y);
-            sMin.z = MIN(sMin.z,sThisMin.z);
-            sMax.x = MAX(sMax.x,sThisMax.x);
-            sMax.y = MAX(sMax.y,sThisMax.y);
-            sMax.z = MAX(sMax.z,sThisMax.z);
+            sMin.x = std::min(sMin.x,sThisMin.x);
+            sMin.y = std::min(sMin.y,sThisMin.y);
+            sMin.z = std::min(sMin.z,sThisMin.z);
+            sMax.x = std::max(sMax.x,sThisMax.x);
+            sMax.y = std::max(sMax.y,sThisMax.y);
+            sMax.z = std::max(sMax.z,sThisMax.z);
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create the corresponding solid header.                          */
 /* -------------------------------------------------------------------- */
-    psCH = DGNCreateSolidHeaderElem( hDGN, nType, nSurfType, nBoundElems,
-                                     nTotalLength, nNumElems );
+    DGNElemCore *psCH =
+        DGNCreateSolidHeaderElem( hDGN, nType, nSurfType, nBoundElems,
+                                  nTotalLength, nNumElems );
     DGNUpdateElemCore( hDGN, psCH, papsElems[0]->level, psCH->graphic_group,
                        psCH->color, psCH->weight, psCH->style );
 
@@ -2006,8 +1979,6 @@ DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
  */
 
 {
-    DGNElemCellHeader *psCH;
-    DGNElemCore *psCore;
     DGNInfo *psInfo = (DGNInfo *) hDGN;
 
     DGNLoadTCB( hDGN );
@@ -2015,8 +1986,9 @@ DGNCreateCellHeaderElem( DGNHandle hDGN, int nTotLength, const char *pszName,
 /* -------------------------------------------------------------------- */
 /*      Allocate element.                                               */
 /* -------------------------------------------------------------------- */
-    psCH = (DGNElemCellHeader *) CPLCalloc( sizeof(DGNElemCellHeader), 1 );
-    psCore = &(psCH->core);
+    DGNElemCellHeader *psCH = (DGNElemCellHeader *)
+        CPLCalloc( sizeof(DGNElemCellHeader), 1 );
+    DGNElemCore *psCore = &(psCH->core);
 
     DGNInitializeElemCore( hDGN, psCore );
     psCore->stype = DGNST_CELL_HEADER;
@@ -2137,21 +2109,19 @@ static void DGNPointToInt( DGNInfo *psDGN, DGNPoint *psPoint,
                            unsigned char *pabyTarget )
 
 {
-    double     adfCT[3];
-    int        i;
-
-    adfCT[0] = psPoint->x;
-    adfCT[1] = psPoint->y;
-    adfCT[2] = psPoint->z;
-
-    const int nIter = MIN(3, psDGN->dimension);
-    for( i = 0; i < nIter; i++ )
+    double adfCT[3] = {
+        psPoint->x,
+        psPoint->y,
+        psPoint->z
+    };
+
+    const int nIter = std::min(3, psDGN->dimension);
+    for( int i = 0; i < nIter; i++ )
     {
-        GInt32 nCTI;
+        GInt32 nCTI = static_cast<GInt32>(
+            std::max(-2147483647.0, std::min(2147483647.0,adfCT[i])));
         unsigned char *pabyCTI = (unsigned char *) &nCTI;
 
-        nCTI = (GInt32) MAX(-2147483647,MIN(2147483647,adfCT[i]));
-
 #ifdef WORDS_BIGENDIAN
         pabyTarget[i*4+0] = pabyCTI[1];
         pabyTarget[i*4+1] = pabyCTI[0];
@@ -2210,11 +2180,6 @@ DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
                               double dfRotation )
 
 {
-    int         nTotalLength;
-    int         i /* , nLevel */;
-    DGNElemCore *psCH;
-    DGNPoint    sMin={0.0,0.0,0.0}, sMax={0.0,0.0,0.0};
-    unsigned char abyLevelsOccurring[8] = {0,0,0,0,0,0,0,0};
     DGNInfo *psInfo = (DGNInfo *) hDGN;
 
     DGNLoadTCB( hDGN );
@@ -2226,21 +2191,17 @@ DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
         return NULL;
     }
 
-    if( psInfo->dimension == 2 )
-        nTotalLength = 27;
-    else
-        nTotalLength = 43;
-
 /* -------------------------------------------------------------------- */
 /*      Collect the total size, and bounds.                             */
 /* -------------------------------------------------------------------- */
-    /* nLevel = papsElems[0]->level; */
+    int nTotalLength = psInfo->dimension == 2 ? 27 : 43;
+    // nLevel = papsElems[0]->level;x
+    DGNPoint sMin = { 0.0, 0.0, 0.0 };
+    DGNPoint sMax = { 0.0, 0.0, 0.0 };
+    unsigned char abyLevelsOccurring[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
-    for( i = 0; i < nNumElems; i++ )
+    for( int i = 0; i < nNumElems; i++ )
     {
-        DGNPoint sThisMin, sThisMax;
-        int  nLevel;
-
         nTotalLength += papsElems[i]->raw_bytes / 2;
 
         /* mark as complex */
@@ -2248,10 +2209,12 @@ DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
         papsElems[i]->raw_data[0] |= 0x80;
 
         /* establish level */
-        nLevel = papsElems[i]->level;
-        nLevel = MAX(1,MIN(nLevel,64));
+        int nLevel = papsElems[i]->level;
+        nLevel = std::max(1,std::min(nLevel,64));
         abyLevelsOccurring[(nLevel-1) >> 3] |= (0x1 << ((nLevel-1)&0x7));
 
+        DGNPoint sThisMin = { 0.0, 0.0, 0.0 };
+        DGNPoint sThisMax = { 0.0, 0.0, 0.0 };
         DGNGetElementExtents( hDGN, papsElems[i], &sThisMin, &sThisMax );
         if( i == 0 )
         {
@@ -2260,12 +2223,12 @@ DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
         }
         else
         {
-            sMin.x = MIN(sMin.x,sThisMin.x);
-            sMin.y = MIN(sMin.y,sThisMin.y);
-            sMin.z = MIN(sMin.z,sThisMin.z);
-            sMax.x = MAX(sMax.x,sThisMax.x);
-            sMax.y = MAX(sMax.y,sThisMax.y);
-            sMax.z = MAX(sMax.z,sThisMax.z);
+            sMin.x = std::min(sMin.x,sThisMin.x);
+            sMin.y = std::min(sMin.y,sThisMin.y);
+            sMin.z = std::min(sMin.z,sThisMin.z);
+            sMax.x = std::max(sMax.x,sThisMax.x);
+            sMax.y = std::max(sMax.y,sThisMax.y);
+            sMax.z = std::max(sMax.z,sThisMax.z);
         }
     }
 
@@ -2298,14 +2261,14 @@ DGNCreateCellHeaderFromGroup( DGNHandle hDGN, const char *pszName,
     if( panLevels == NULL )
         panLevels = (short *) abyLevelsOccurring + 0;
 
-    psCH = DGNCreateCellHeaderElem( hDGN, nTotalLength, pszName,
-                                    nClass, panLevels,
-                                    &sMin, &sMax, psOrigin,
-                                    dfXScale, dfYScale, dfRotation );
+    DGNElemCore *psCH =
+        DGNCreateCellHeaderElem( hDGN, nTotalLength, pszName,
+                                 nClass, panLevels,
+                                 &sMin, &sMax, psOrigin,
+                                 dfXScale, dfYScale, dfRotation );
     DGNWriteBounds( (DGNInfo *) hDGN, psCH, &sMin, &sMax );
 
     return psCH;
-
 }
 
 /************************************************************************/
@@ -2335,8 +2298,8 @@ int DGNAddMSLink( DGNHandle hDGN, DGNElemCore *psElement,
                   int nLinkageType, int nEntityNum, int nMSLink )
 
 {
-    unsigned char abyLinkage[32];
-    int           nLinkageSize;
+    unsigned char abyLinkage[32] = {};
+    int nLinkageSize = 0;
 
     if( nLinkageType == DGNLT_DMRS )
     {
@@ -2405,8 +2368,6 @@ int DGNAddRawAttrLink( DGNHandle hDGN, DGNElemCore *psElement,
                        int nLinkSize, unsigned char *pabyRawLinkData )
 
 {
-    int   iLinkage;
-
     if( nLinkSize % 2 == 1 )
         nLinkSize++;
 
@@ -2468,14 +2429,15 @@ int DGNAddRawAttrLink( DGNHandle hDGN, DGNElemCore *psElement,
 /* -------------------------------------------------------------------- */
 /*      Figure out what the linkage index is.                           */
 /* -------------------------------------------------------------------- */
-    for( iLinkage = 0; ; iLinkage++ )
+    int iLinkage = 0;  // Used after for.
+    for( ; ; iLinkage++ )
     {
         if( DGNGetLinkage( hDGN, psElement, iLinkage, NULL, NULL, NULL, NULL )
             == NULL )
             break;
     }
 
-    return iLinkage-1;
+    return iLinkage - 1;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dgn/dgnwritetest.c b/ogr/ogrsf_frmts/dgn/dgnwritetest.c
deleted file mode 100644
index 25c808d..0000000
--- a/ogr/ogrsf_frmts/dgn/dgnwritetest.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/******************************************************************************
- * $Id: dgnwritetest.c 33713 2016-03-12 17:41:57Z goatbar $
- *
- * Project:  Microstation DGN Access Library
- * Purpose:  Test program for use of write api.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "dgnlib.h"
-
-CPL_CVSID("$Id: dgnwritetest.c 33713 2016-03-12 17:41:57Z goatbar $");
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-int main( int argc, char ** argv )
-
-{
-    DGNHandle hNewDGN;
-    DGNElemCore *psMembers[2];
-    DGNPoint   asPoints[10];
-    DGNElemCore *psLine;
-
-/* -------------------------------------------------------------------- */
-/*      Create new DGN file.                                            */
-/* -------------------------------------------------------------------- */
-    hNewDGN = DGNCreate( "out.dgn", "seed.dgn",
-                         DGNCF_USE_SEED_UNITS
-                         | DGNCF_USE_SEED_ORIGIN,
-                         0.0, 0.0, 0.0, 0, 0, "", "" );
-
-    if( hNewDGN == NULL )
-    {
-        printf( "DGNCreate failed.\n" );
-        exit( 10 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Write one line segment to it.                                   */
-/* -------------------------------------------------------------------- */
-    memset( &asPoints, 0, sizeof(asPoints) );
-
-    asPoints[0].x = 0;
-    asPoints[0].y = 0;
-    asPoints[0].z = 100;
-    asPoints[1].x = 10000;
-    asPoints[1].y = 4000;
-    asPoints[1].z = 110;
-
-    psLine = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE, 2, asPoints );
-    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
-    DGNWriteElement( hNewDGN, psLine );
-    DGNFreeElement( hNewDGN, psLine );
-
-/* -------------------------------------------------------------------- */
-/*      Write a line string.                                            */
-/* -------------------------------------------------------------------- */
-    asPoints[0].x = 0;
-    asPoints[0].y = 1000;
-    asPoints[1].x = 6000;
-    asPoints[1].y = 5000;
-    asPoints[2].x = 12000;
-    asPoints[2].y = 6000;
-
-    psLine = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3, asPoints );
-    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
-    DGNWriteElement( hNewDGN, psLine );
-    DGNFreeElement( hNewDGN, psLine );
-
-/* -------------------------------------------------------------------- */
-/*      Write an Arc.                                                   */
-/* -------------------------------------------------------------------- */
-    psLine = DGNCreateArcElem( hNewDGN, DGNT_ARC,
-                               2000.0, 3000.0, 500.0, 2000.0, 1000.0,
-                               0.0, 270.0, 0.0, NULL );
-
-    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
-    DGNWriteElement( hNewDGN, psLine );
-    DGNFreeElement( hNewDGN, psLine );
-
-/* -------------------------------------------------------------------- */
-/*      Write an Ellipse with fill info.                                */
-/* -------------------------------------------------------------------- */
-    psLine = DGNCreateArcElem( hNewDGN, DGNT_ELLIPSE,
-                               200.0, 30.0, 5.0, 10.0, 10.0,
-                               0.0, 360.0, 0.0, NULL );
-
-    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
-    DGNWriteElement( hNewDGN, psLine );
-    DGNFreeElement( hNewDGN, psLine );
-
-/* -------------------------------------------------------------------- */
-/*      Write some text.                                                */
-/* -------------------------------------------------------------------- */
-    psLine = DGNCreateTextElem( hNewDGN, "This is a test string",
-                                0, DGNJ_CENTER_TOP, 200.0, 200.0, 0.0, NULL,
-                                2000.0, 3000.0, 0.0 );
-
-    DGNAddMSLink( hNewDGN, psLine, DGNLT_XBASE, 7, 101 );
-    DGNAddMSLink( hNewDGN, psLine, DGNLT_DMRS, 7, 101 );
-    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
-    DGNWriteElement( hNewDGN, psLine );
-    DGNFreeElement( hNewDGN, psLine );
-
-    psLine = DGNCreateTextElem( hNewDGN, "------- 30 degrees",
-                                0, DGNJ_CENTER_TOP, 200.0, 200.0, 30.0, NULL,
-                                2000.0, 3000.0, 0.0 );
-
-    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
-    DGNWriteElement( hNewDGN, psLine );
-    DGNFreeElement( hNewDGN, psLine );
-
-    psLine = DGNCreateTextElem( hNewDGN, "------- 90 degrees",
-                                0, DGNJ_CENTER_TOP, 200.0, 200.0, 90.0, NULL,
-                                2000.0, 3000.0, 0.0 );
-
-    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
-    DGNWriteElement( hNewDGN, psLine );
-    DGNFreeElement( hNewDGN, psLine );
-
-/* -------------------------------------------------------------------- */
-/*      Write a complex shape consisting of two line strings.           */
-/* -------------------------------------------------------------------- */
-    asPoints[0].x = 8000;
-    asPoints[0].y = 8000;
-    asPoints[1].x = 6000;
-    asPoints[1].y = 8000;
-    asPoints[2].x = 6000;
-    asPoints[2].y = 6000;
-
-    psMembers[0] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
-                                            asPoints );
-    DGNUpdateElemCore( hNewDGN, psMembers[0], 9, 0, 3, 1, 0 );
-
-    asPoints[0].x = 6000;
-    asPoints[0].y = 6000;
-    asPoints[1].x = 8000;
-    asPoints[1].y = 6000;
-    asPoints[2].x = 8000;
-    asPoints[2].y = 8000;
-
-    psMembers[1] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
-                                            asPoints );
-    DGNUpdateElemCore( hNewDGN, psMembers[1], 9, 0, 3, 1, 0 );
-
-    psLine = DGNCreateComplexHeaderFromGroup( hNewDGN,
-                                              DGNT_COMPLEX_SHAPE_HEADER,
-                                              2, psMembers );
-
-    DGNUpdateElemCore( hNewDGN, psLine, 9, 0, 3, 1, 0 );
-    DGNAddShapeFillInfo( hNewDGN, psLine, 7 );
-
-    DGNWriteElement( hNewDGN, psLine );
-    DGNWriteElement( hNewDGN, psMembers[0] );
-    DGNWriteElement( hNewDGN, psMembers[1] );
-
-    DGNFreeElement( hNewDGN, psLine );
-    DGNFreeElement( hNewDGN, psMembers[0] );
-    DGNFreeElement( hNewDGN, psMembers[1] );
-
-/* -------------------------------------------------------------------- */
-/*      Write a cell with two lines.                                    */
-/* -------------------------------------------------------------------- */
-    asPoints[0].x = 7000;
-    asPoints[0].y = 7000;
-    asPoints[1].x = 5000;
-    asPoints[1].y = 7000;
-    asPoints[2].x = 5000;
-    asPoints[2].y = 5000;
-
-    psMembers[0] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
-                                            asPoints );
-    DGNUpdateElemCore( hNewDGN, psMembers[0], 10, 0, 3, 1, 0 );
-
-    asPoints[0].x = 5000;
-    asPoints[0].y = 5000;
-    asPoints[1].x = 8000;
-    asPoints[1].y = 5000;
-    asPoints[2].x = 7000;
-    asPoints[2].y = 7000;
-
-    psMembers[1] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
-                                            asPoints );
-    DGNUpdateElemCore( hNewDGN, psMembers[1], 9, 0, 3, 1, 0 );
-
-    asPoints[0].x = 5000;
-    asPoints[0].y = 5000;
-
-    psLine = DGNCreateCellHeaderFromGroup( hNewDGN, "BE70", 1, NULL,
-                                           2, psMembers, asPoints + 0,
-                                           1.0, 1.0, 0.0 );
-
-    DGNWriteElement( hNewDGN, psLine );
-    DGNWriteElement( hNewDGN, psMembers[0] );
-    DGNWriteElement( hNewDGN, psMembers[1] );
-
-    DGNFreeElement( hNewDGN, psLine );
-    DGNFreeElement( hNewDGN, psMembers[0] );
-    DGNFreeElement( hNewDGN, psMembers[1] );
-
-/* -------------------------------------------------------------------- */
-/*      Close it.                                                       */
-/* -------------------------------------------------------------------- */
-    DGNClose( hNewDGN );
-
-    return 0;
-}
diff --git a/ogr/ogrsf_frmts/dgn/dgnwritetest.cpp b/ogr/ogrsf_frmts/dgn/dgnwritetest.cpp
new file mode 100644
index 0000000..9540503
--- /dev/null
+++ b/ogr/ogrsf_frmts/dgn/dgnwritetest.cpp
@@ -0,0 +1,225 @@
+/******************************************************************************
+ * $Id: dgnwritetest.cpp 36763 2016-12-09 22:10:55Z rouault $
+ *
+ * Project:  Microstation DGN Access Library
+ * Purpose:  Test program for use of write api.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Frank Warmerdam <warmerdam at pobox.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "dgnlib.h"
+
+CPL_CVSID("$Id: dgnwritetest.cpp 36763 2016-12-09 22:10:55Z rouault $");
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+int main( int /* argc */, char ** /* argv */ )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Create new DGN file.                                            */
+/* -------------------------------------------------------------------- */
+    DGNHandle hNewDGN = DGNCreate( "out.dgn", "seed.dgn",
+                                   DGNCF_USE_SEED_UNITS
+                                   | DGNCF_USE_SEED_ORIGIN,
+                                   0.0, 0.0, 0.0, 0, 0, "", "" );
+
+    if( hNewDGN == NULL )
+    {
+        printf( "DGNCreate failed.\n" );/*ok*/
+        exit( 10 );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write one line segment to it.                                   */
+/* -------------------------------------------------------------------- */
+    DGNPoint asPoints[10] = {};
+
+    asPoints[0].x = 0;
+    asPoints[0].y = 0;
+    asPoints[0].z = 100;
+    asPoints[1].x = 10000;
+    asPoints[1].y = 4000;
+    asPoints[1].z = 110;
+
+    DGNElemCore *psLine =
+        DGNCreateMultiPointElem( hNewDGN, DGNT_LINE, 2, asPoints );
+    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
+    DGNWriteElement( hNewDGN, psLine );
+    DGNFreeElement( hNewDGN, psLine );
+
+/* -------------------------------------------------------------------- */
+/*      Write a line string.                                            */
+/* -------------------------------------------------------------------- */
+    asPoints[0].x = 0;
+    asPoints[0].y = 1000;
+    asPoints[1].x = 6000;
+    asPoints[1].y = 5000;
+    asPoints[2].x = 12000;
+    asPoints[2].y = 6000;
+
+    psLine = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3, asPoints );
+    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
+    DGNWriteElement( hNewDGN, psLine );
+    DGNFreeElement( hNewDGN, psLine );
+
+/* -------------------------------------------------------------------- */
+/*      Write an Arc.                                                   */
+/* -------------------------------------------------------------------- */
+    psLine = DGNCreateArcElem( hNewDGN, DGNT_ARC,
+                               2000.0, 3000.0, 500.0, 2000.0, 1000.0,
+                               0.0, 270.0, 0.0, NULL );
+
+    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
+    DGNWriteElement( hNewDGN, psLine );
+    DGNFreeElement( hNewDGN, psLine );
+
+/* -------------------------------------------------------------------- */
+/*      Write an Ellipse with fill info.                                */
+/* -------------------------------------------------------------------- */
+    psLine = DGNCreateArcElem( hNewDGN, DGNT_ELLIPSE,
+                               200.0, 30.0, 5.0, 10.0, 10.0,
+                               0.0, 360.0, 0.0, NULL );
+
+    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
+    DGNWriteElement( hNewDGN, psLine );
+    DGNFreeElement( hNewDGN, psLine );
+
+/* -------------------------------------------------------------------- */
+/*      Write some text.                                                */
+/* -------------------------------------------------------------------- */
+    psLine = DGNCreateTextElem( hNewDGN, "This is a test string",
+                                0, DGNJ_CENTER_TOP, 200.0, 200.0, 0.0, NULL,
+                                2000.0, 3000.0, 0.0 );
+
+    DGNAddMSLink( hNewDGN, psLine, DGNLT_XBASE, 7, 101 );
+    DGNAddMSLink( hNewDGN, psLine, DGNLT_DMRS, 7, 101 );
+    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
+    DGNWriteElement( hNewDGN, psLine );
+    DGNFreeElement( hNewDGN, psLine );
+
+    psLine = DGNCreateTextElem( hNewDGN, "------- 30 degrees",
+                                0, DGNJ_CENTER_TOP, 200.0, 200.0, 30.0, NULL,
+                                2000.0, 3000.0, 0.0 );
+
+    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
+    DGNWriteElement( hNewDGN, psLine );
+    DGNFreeElement( hNewDGN, psLine );
+
+    psLine = DGNCreateTextElem( hNewDGN, "------- 90 degrees",
+                                0, DGNJ_CENTER_TOP, 200.0, 200.0, 90.0, NULL,
+                                2000.0, 3000.0, 0.0 );
+
+    DGNUpdateElemCore( hNewDGN, psLine, 15, 0, 3, 1, 0 );
+    DGNWriteElement( hNewDGN, psLine );
+    DGNFreeElement( hNewDGN, psLine );
+
+/* -------------------------------------------------------------------- */
+/*      Write a complex shape consisting of two line strings.           */
+/* -------------------------------------------------------------------- */
+    asPoints[0].x = 8000;
+    asPoints[0].y = 8000;
+    asPoints[1].x = 6000;
+    asPoints[1].y = 8000;
+    asPoints[2].x = 6000;
+    asPoints[2].y = 6000;
+
+    DGNElemCore *psMembers[2] = {
+        DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3, asPoints ),
+        DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3, asPoints )
+    };
+    DGNUpdateElemCore( hNewDGN, psMembers[0], 9, 0, 3, 1, 0 );
+
+    asPoints[0].x = 6000;
+    asPoints[0].y = 6000;
+    asPoints[1].x = 8000;
+    asPoints[1].y = 6000;
+    asPoints[2].x = 8000;
+    asPoints[2].y = 8000;
+
+    DGNUpdateElemCore( hNewDGN, psMembers[1], 9, 0, 3, 1, 0 );
+
+    psLine = DGNCreateComplexHeaderFromGroup( hNewDGN,
+                                              DGNT_COMPLEX_SHAPE_HEADER,
+                                              2, psMembers );
+
+    DGNUpdateElemCore( hNewDGN, psLine, 9, 0, 3, 1, 0 );
+    DGNAddShapeFillInfo( hNewDGN, psLine, 7 );
+
+    DGNWriteElement( hNewDGN, psLine );
+    DGNWriteElement( hNewDGN, psMembers[0] );
+    DGNWriteElement( hNewDGN, psMembers[1] );
+
+    DGNFreeElement( hNewDGN, psLine );
+    DGNFreeElement( hNewDGN, psMembers[0] );
+    DGNFreeElement( hNewDGN, psMembers[1] );
+
+/* -------------------------------------------------------------------- */
+/*      Write a cell with two lines.                                    */
+/* -------------------------------------------------------------------- */
+    asPoints[0].x = 7000;
+    asPoints[0].y = 7000;
+    asPoints[1].x = 5000;
+    asPoints[1].y = 7000;
+    asPoints[2].x = 5000;
+    asPoints[2].y = 5000;
+
+    psMembers[0] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
+                                            asPoints );
+    DGNUpdateElemCore( hNewDGN, psMembers[0], 10, 0, 3, 1, 0 );
+
+    asPoints[0].x = 5000;
+    asPoints[0].y = 5000;
+    asPoints[1].x = 8000;
+    asPoints[1].y = 5000;
+    asPoints[2].x = 7000;
+    asPoints[2].y = 7000;
+
+    psMembers[1] = DGNCreateMultiPointElem( hNewDGN, DGNT_LINE_STRING, 3,
+                                            asPoints );
+    DGNUpdateElemCore( hNewDGN, psMembers[1], 9, 0, 3, 1, 0 );
+
+    asPoints[0].x = 5000;
+    asPoints[0].y = 5000;
+
+    psLine = DGNCreateCellHeaderFromGroup( hNewDGN, "BE70", 1, NULL,
+                                           2, psMembers, asPoints + 0,
+                                           1.0, 1.0, 0.0 );
+
+    DGNWriteElement( hNewDGN, psLine );
+    DGNWriteElement( hNewDGN, psMembers[0] );
+    DGNWriteElement( hNewDGN, psMembers[1] );
+
+    DGNFreeElement( hNewDGN, psLine );
+    DGNFreeElement( hNewDGN, psMembers[0] );
+    DGNFreeElement( hNewDGN, psMembers[1] );
+
+/* -------------------------------------------------------------------- */
+/*      Close it.                                                       */
+/* -------------------------------------------------------------------- */
+    DGNClose( hNewDGN );
+
+    return 0;
+}
diff --git a/ogr/ogrsf_frmts/dgn/dist/README b/ogr/ogrsf_frmts/dgn/dist/README
index f6ae5f4..92e1724 100644
--- a/ogr/ogrsf_frmts/dgn/dist/README
+++ b/ogr/ogrsf_frmts/dgn/dist/README
@@ -12,7 +12,7 @@ Building
 --------
 
 This is a preliminary source distribution, and I have not gone to any
-pains to make it easy to configure and build.  To build please do the 
+pains to make it easy to configure and build.  To build please do the
 following:
 
 == Unix:
@@ -21,16 +21,16 @@ following:
 that matters is to #define WORDS_BIGENDIAN on big endian platforms.  The
 rest can likely be ignored.<p>
 
-2. Build the programs. 
+2. Build the programs.
 
-  % make 
+  % make
 
 == Windows:
 
 1. Ensure you have Microsoft Visual C++ 6.x or later installed.
 
 2. Ensure the commandline VC++ environment is setup properly.  You may need
-   to run the VCVARS32.BAT script from within the VC++ tree. 
+   to run the VCVARS32.BAT script from within the VC++ tree.
 
 3. Compile the code, and build statically linked executables for the sample
    programs and DLL using the following command.
@@ -59,19 +59,19 @@ Release 1.11
    - Fixed incorrect reading and writing of surftype field.
    - Added boundelms field to DGNElemComplexHeader
    - Added DGNCreateSolidHeaderElem() and DGNCreateSolidHeaderElemFromGroup()
-   - Changed DGNCreateComplexHeaderElem() and 
+   - Changed DGNCreateComplexHeaderElem() and
      DGNCreateComplexHeaderElemFromGroup() to only support complex chains/shapes
    - Fixed bug creating solids/surfaces: totlength was 1 word too short.
    - Renamed bogus define DGNSUT_SOLID to DGNSUT_SURFACE_OF_PROJECTION
 
  o Added support for cloning Cone elements
 
- o Fixes for uor handling in DGNCreate(). 
+ o Fixes for uor handling in DGNCreate().
 
- o Treat the most recently read color table as the global color table, 
+ o Treat the most recently read color table as the global color table,
    instead of just the first one encountered.
 
- o Added Text Node implementation from Ilya Beylin. 
+ o Added Text Node implementation from Ilya Beylin.
 
 
 Release 1.10
@@ -83,14 +83,14 @@ Release 1.10
  o Check if a negative amount of attribute information is being read in
    DGNParseCore(), and if so just issue a warning, and skip attempt.
 
- o Fixed DGNCreateCellHeaderFromGroup() to not pre-transform the bounds.  
+ o Fixed DGNCreateCellHeaderFromGroup() to not pre-transform the bounds.
 
  o Fixed missing handling of min/max Z in DGNCreateMultiPointElem(). (Marius)
 
  o Added surface type to DGNCreateComplexHeaderElem().  (Marius)
 
  o DGNRad50ToAscii() reimplemented to correct a few problems.  New version
-   provided by Armin Berg (iez.com). 
+   provided by Armin Berg (iez.com).
 
  o Fixes to complex header and cell header creation to set the total group
    size properly, and to set up complex header pad attributes properly.  Now
@@ -101,7 +101,7 @@ Release 1.9
 -----------
 
  o Added DGNLoadTCB(), and fixed problem when writing new elements to an
-   existing file without having already read the TCB. 
+   existing file without having already read the TCB.
 
  o Fixed serious bug in setting the index "offset" location.  Critical for
    writing applications.
@@ -110,8 +110,8 @@ Release 1.9
 Release 1.8
 -----------
 
- o Added support for reading 3D cone (23), 3D surface (18) and 3D solid (19) 
-   elements based on contributions from Marius Kintel. 
+ o Added support for reading 3D cone (23), 3D surface (18) and 3D solid (19)
+   elements based on contributions from Marius Kintel.
 
  o Main site moved to http://dgnlib.maptools.org/
 
@@ -120,9 +120,9 @@ Release 1.7
 -----------
 
  o Improved calculation of bounding box in DGLCreateTextElem() based on code
-   from Matt Kelder. 
+   from Matt Kelder.
 
- o Added preliminary 3D write support. 
+ o Added preliminary 3D write support.
 
  o Modified DGNCreateTextElem() arguments, and deprecated DGNCreateArcElem2D()
    in favour of DGNCreateArcElem().
@@ -135,27 +135,27 @@ Release 1.6
 
  o Bug fix in DGNGetLinkage() for DMRS recognition from Henk Jan Priester.
 
- o Added DGNCreateCellHeaderFromGroup() and DGNCreateCellHeaderElem() 
+ o Added DGNCreateCellHeaderFromGroup() and DGNCreateCellHeaderElem()
    functions in the write API.
 
- o Added a Microsoft VC++ makefile (Makefile.vc). 
+ o Added a Microsoft VC++ makefile (Makefile.vc).
 
 
 Release 1.5
 -----------
 
- o Added 2D write support!  
+ o Added 2D write support!
 
  o Fixed collection of background color in color table (color 255) as per
-   bug report by Henk Jan Priester (Justcroft Technical Systems). 
+   bug report by Henk Jan Priester (Justcroft Technical Systems).
 
- o Added support for association ids (DGNLT_ASSOC_ID, DGNGetAssocID()). 
+ o Added support for association ids (DGNLT_ASSOC_ID, DGNGetAssocID()).
 
  o Fixed problem with updating the DGNInfo.color_table field when a color
-   table is read. 
+   table is read.
 
  o Fixed problem with spatial queries either including all of a complex
-   element (and it's members) or none. 
+   element (and it's members) or none.
 
  o Added support for reading the eight view descriptions in the TCB element.
 
@@ -168,28 +168,28 @@ Release 1.5
 Release 1.4
 -----------
 
- o Added "fast" spatial searching via the DGNSetSpatialFilter() function. 
-   This basically just reads the extents information at beginning of 
-   geometric features to see if they should be returned. 
+ o Added "fast" spatial searching via the DGNSetSpatialFilter() function.
+   This basically just reads the extents information at beginning of
+   geometric features to see if they should be returned.
 
  o Actually extract the global origin from the TCB, and use it when
    transforming points.  Only a few files (i.e. Brazos County roads.rds) use
    a non-zero origin.
 
  o Added experimental multi byte text support from Ason Kang
-   (hiska at netian.com). 
+   (hiska at netian.com).
 
  o Add experimental support for 3D files.  Some 3D elements not supported.
    3D quaternion for ellipse and arc elements not utilized.
 
  o Added preliminary support for reading cell header structures based
-   on input from Mike Cane. 
+   on input from Mike Cane.
 
- o Moved a bunch of stuff into dgnread.cpp. 
+ o Moved a bunch of stuff into dgnread.cpp.
 
- o Build default colortable into dgnhelp.cpp for use of DGNLookupColor(). 
+ o Build default colortable into dgnhelp.cpp for use of DGNLookupColor().
 
- o Added DGNGetShapeFillInfo(). 
+ o Added DGNGetShapeFillInfo().
 
  o DGNGetShapeFillInfo() now tries to handle multi-part attribute linkages.
 
@@ -198,12 +198,12 @@ Release 1.3
 -----------
 
  o Added raw_data/raw_bytes members of DGNElemCore, and DGNSetOptions()
-   to allow control of when raw element image is retained. 
+   to allow control of when raw element image is retained.
 
- o Added -r flag to dgndump to dump raw contents of desired elements. 
+ o Added -r flag to dgndump to dump raw contents of desired elements.
 
- o Add CPL_CVSID() to simplify tracking of versions. 
+ o Add CPL_CVSID() to simplify tracking of versions.
 
- o Fixed bug with freeing element index in DGNClose(). 
+ o Fixed bug with freeing element index in DGNClose().
 
 
diff --git a/ogr/ogrsf_frmts/dgn/drv_dgn.html b/ogr/ogrsf_frmts/dgn/drv_dgn.html
index c706d24..b03f3ac 100644
--- a/ogr/ogrsf_frmts/dgn/drv_dgn.html
+++ b/ogr/ogrsf_frmts/dgn/drv_dgn.html
@@ -8,7 +8,9 @@
 <h1>Microstation DGN</h1>
 
 Microstation DGN files from Microstation versions predating version 8.0
-are supported for reading.  The entire file is represented as one layer
+are supported for reading (a <a href="drv_dgnv8.html">DGNv8 driver</a>,
+using Teigha libraries, is available to read and write DGN v8 files).
+The entire file is represented as one layer
 (named "elements").<p>
 
 DGN files are considered to have no georeferencing information through OGR.
@@ -141,6 +143,7 @@ default the origin from the seed file is used.<p>
 <ul>
 <li> <a href="http://dgnlib.maptools.org/">Dgnlib Page</a>
 <li> <a href="http://gdal.org/ogr_feature_style.html">OGR Feature Style Specification</a>
+<li> <a href="drv_dgnv8.html">DGNv8 driver</a> (using Teigha libraries)
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/dgn/ogr_dgn.h b/ogr/ogrsf_frmts/dgn/ogr_dgn.h
index ba78405..2ac9584 100644
--- a/ogr/ogrsf_frmts/dgn/ogr_dgn.h
+++ b/ogr/ogrsf_frmts/dgn/ogr_dgn.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_dgn.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_dgn.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  OGR Driver for DGN Reader.
@@ -65,27 +65,26 @@ class OGRDGNLayer : public OGRLayer
   public:
                         OGRDGNLayer( const char * pszName, DGNHandle hDGN,
                                      int bUpdate );
-                        ~OGRDGNLayer();
+                        virtual ~OGRDGNLayer();
 
-    void                SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    void                SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
-    OGRFeature *        GetFeature( GIntBig nFeatureId );
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    OGRFeature *        GetFeature( GIntBig nFeatureId ) override;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
-
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
+    int                 TestCapability( const char * ) override;
 
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
 };
 
 /************************************************************************/
@@ -107,18 +106,18 @@ class OGRDGNDataSource : public OGRDataSource
                         ~OGRDGNDataSource();
 
     int                 Open( const char *, int bTestOpen, int bUpdate );
-    int                 PreCreate( const char *, char ** );
+    bool                PreCreate( const char *, char ** );
 
     OGRLayer           *ICreateLayer( const char *,
                                      OGRSpatialReference * = NULL,
                                      OGRwkbGeometryType = wkbUnknown,
-                                     char ** = NULL );
+                                     char ** = NULL ) override;
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_DGN_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp b/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp
index 7a29c5c..0f8f965 100644
--- a/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp
+++ b/ogr/ogrsf_frmts/dgn/ogrdgndatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdgndatasource.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDataSource class.
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdgndatasource.cpp 33105 2016-01-23 15:27:32Z rouault $");
+CPL_CVSID("$Id: ogrdgndatasource.cpp 35910 2016-10-24 14:08:24Z goatbar $");
 
 /************************************************************************/
 /*                         OGRDGNDataSource()                           */
@@ -154,7 +153,6 @@ OGRLayer *OGRDGNDataSource::GetLayer( int iLayer )
     return papoLayers[iLayer];
 }
 
-
 /************************************************************************/
 /*                             PreCreate()                              */
 /*                                                                      */
@@ -163,14 +161,14 @@ OGRLayer *OGRDGNDataSource::GetLayer( int iLayer )
 /*      yet.  It will be created by theICreateLayer() call.             */
 /************************************************************************/
 
-int OGRDGNDataSource::PreCreate( const char *pszFilename,
-                                 char **papszOptionsIn )
+bool OGRDGNDataSource::PreCreate( const char *pszFilename,
+                                  char **papszOptionsIn )
 
 {
-    this->papszOptions = CSLDuplicate( papszOptionsIn );
+    papszOptions = CSLDuplicate( papszOptionsIn );
     pszName = CPLStrdup( pszFilename );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -225,8 +223,7 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
     papszOptions = CSLInsertStrings( papszOptions, 0, papszExtraOptions );
 
     const bool b3DRequested
-        = CPL_TO_BOOL(CSLFetchBoolean( papszOptions, "3D",
-                           wkbHasZ(eGeomType) ));
+        = CPLFetchBool( papszOptions, "3D", wkbHasZ(eGeomType) );
 
     const char *pszSeed = CSLFetchNameValue( papszOptions, "SEED" );
     int nCreationFlags = 0;
@@ -244,9 +241,9 @@ OGRLayer *OGRDGNDataSource::ICreateLayer( const char *pszLayerName,
         return NULL;
     }
 
-    if( CSLFetchBoolean( papszOptions, "COPY_WHOLE_SEED_FILE", TRUE ) )
+    if( CPLFetchBool( papszOptions, "COPY_WHOLE_SEED_FILE", true ) )
         nCreationFlags |= DGNCF_COPY_WHOLE_SEED_FILE;
-    if( CSLFetchBoolean( papszOptions, "COPY_SEED_FILE_COLOR_TABLE", TRUE ) )
+    if( CPLFetchBool( papszOptions, "COPY_SEED_FILE_COLOR_TABLE", true ) )
         nCreationFlags |= DGNCF_COPY_SEED_FILE_COLOR_TABLE;
 
     const char *pszValue
diff --git a/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp b/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp
index d8cc84c..11a9087 100644
--- a/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp
+++ b/ogr/ogrsf_frmts/dgn/ogrdgndriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdgndriver.cpp 32154 2015-12-13 05:34:45Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRDGNDriver class.
@@ -30,7 +29,7 @@
 #include "ogr_dgn.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdgndriver.cpp 32154 2015-12-13 05:34:45Z goatbar $");
+CPL_CVSID("$Id: ogrdgndriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
diff --git a/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp b/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp
index 7734220..7fe0a3a 100644
--- a/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp
+++ b/ogr/ogrsf_frmts/dgn/ogrdgnlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdgnlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRDGNLayer class.
@@ -31,9 +30,12 @@
 #include "cpl_conv.h"
 #include "ogr_featurestyle.h"
 #include "ogr_api.h"
+
+#include <algorithm>
+#include <cmath>
 #include <list>
 
-CPL_CVSID("$Id: ogrdgnlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdgnlayer.cpp 36020 2016-10-29 08:53:27Z rouault $");
 
 /************************************************************************/
 /*                           OGRDGNLayer()                              */
@@ -45,8 +47,6 @@ OGRDGNLayer::OGRDGNLayer( const char * pszName, DGNHandle hDGNIn,
     iNextShapeId(0),
     hDGN(hDGNIn),
     bUpdate(bUpdateIn)
-    // Unused:
-    // bHaveSimpleQuery(FALSE)
 {
 
 /* -------------------------------------------------------------------- */
@@ -333,7 +333,6 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
     int iLink = 0;
     int nLinkCount = 0;
 
-
     pabyData = DGNGetLinkage( hDGN, psElement, iLink, NULL,
                               anEntityNum + iLink, anMSLink + iLink, NULL );
     while( pabyData && nLinkCount < MAX_LINK )
@@ -402,11 +401,11 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
 /* -------------------------------------------------------------------- */
 /*      Lookup color.                                                   */
 /* -------------------------------------------------------------------- */
-    int gv_red;
-    int gv_green;
-    int gv_blue;
+    int gv_red = 0;
+    int gv_green = 0;
+    int gv_blue = 0;
 
-    char szFSColor[128];
+    char szFSColor[128] = {};
     szFSColor[0] = '\0';
     if( DGNLookupColor( hDGN, psElement->color,
                         &gv_red, &gv_green, &gv_blue ) )
@@ -529,15 +528,16 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
 
       case DGNST_ARC:
       {
-          OGRLineString *poLine = new OGRLineString();
           DGNElemArc    *psArc = (DGNElemArc *) psElement;
-          DGNPoint      asPoints[90];
-          // TODO: std::abs abd std::max
-          int nPoints = static_cast<int>(MAX(1,ABS(psArc->sweepang) / 5) + 1);
+          int nPoints = static_cast<int>(
+              std::max(1.0, std::abs(psArc->sweepang) / 5.0) + 1.0);
           if( nPoints > 90 )
               nPoints = 90;
+
+          DGNPoint asPoints[90] = {};
           DGNStrokeArc( hDGN, psArc, nPoints, asPoints );
 
+          OGRLineString *poLine = new OGRLineString();
           poLine->setNumPoints( nPoints );
           for( int i = 0; i < nPoints; i++ )
           {
@@ -576,11 +576,11 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
 
           // Add the size info in ground units.
           // TODO: std::abs
-          if( ABS(psText->height_mult) >= 6.0 )
+          if( std::abs(psText->height_mult) >= 6.0 )
               CPLsnprintf( pszOgrFS+strlen(pszOgrFS),
                            nOgrFSLen-strlen(pszOgrFS), ",s:%dg",
                            static_cast<int>( psText->height_mult ) );
-          else if( ABS(psText->height_mult) > 0.1 )
+          else if( std::abs(psText->height_mult) > 0.1 )
               CPLsnprintf( pszOgrFS+strlen(pszOgrFS),
                           nOgrFSLen-strlen(pszOgrFS), ",s:%.3fg",
                            psText->height_mult );
@@ -655,9 +655,7 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
           for( int iChild = 0; iChild < psHdr->numelems; iChild++ )
           {
               OGRFeature *poChildFeature = NULL;
-              DGNElemCore *psChildElement;
-
-              psChildElement = DGNReadElement( hDGN );
+              DGNElemCore *psChildElement = DGNReadElement( hDGN );
               // should verify complex bit set, not another header.
 
               if( psChildElement != NULL )
@@ -669,9 +667,7 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
               if( poChildFeature != NULL
                   && poChildFeature->GetGeometryRef() != NULL )
               {
-                  OGRGeometry *poGeom;
-
-                  poGeom = poChildFeature->GetGeometryRef();
+                  OGRGeometry *poGeom = poChildFeature->GetGeometryRef();
                   if( wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
                       oChildren.addGeometry( poGeom );
               }
@@ -681,7 +677,7 @@ OGRFeature *OGRDGNLayer::ElementToFeature( DGNElemCore *psElement )
           }
 
           // Try to assemble into polygon geometry.
-          OGRGeometry *poGeom = NULL;;
+          OGRGeometry *poGeom = NULL;
 
           if( psElement->type == DGNT_COMPLEX_SHAPE_HEADER )
               poGeom = reinterpret_cast<OGRPolygon *>(
@@ -797,8 +793,8 @@ GIntBig OGRDGNLayer::GetFeatureCount( int bForce )
 /* -------------------------------------------------------------------- */
 /*      Otherwise scan the index.                                       */
 /* -------------------------------------------------------------------- */
-    int nElementCount;
-    const DGNElementInfo *pasIndex = DGNGetElementIndex(hDGN,&nElementCount);
+    int nElementCount = 0;
+    const DGNElementInfo *pasIndex = DGNGetElementIndex(hDGN, &nElementCount);
 
     int nFeatureCount = 0;
     bool bInComplexShape = false;
@@ -816,13 +812,13 @@ GIntBig OGRDGNLayer::GetFeatureCount( int bForce )
             if( !(pasIndex[i].flags & DGNEIF_COMPLEX) || !bInComplexShape )
             {
                 nFeatureCount++;
-                bInComplexShape = FALSE;
+                bInComplexShape = false;
             }
             break;
 
           case DGNST_COMPLEX_HEADER:
             nFeatureCount++;
-            bInComplexShape = TRUE;
+            bInComplexShape = true;
             break;
 
           default:
@@ -871,15 +867,14 @@ DGNElemCore **OGRDGNLayer::LineStringToElementGroup( OGRLineString *poLS,
                                                      int nGroupType )
 
 {
-    int nTotalPoints = poLS->getNumPoints();
-    int iNextPoint = 0;
+    const int nTotalPoints = poLS->getNumPoints();
     int iGeom = 0;
     DGNElemCore **papsGroup = static_cast<DGNElemCore **>(
         CPLCalloc( sizeof(void*), (nTotalPoints/(MAX_ELEM_POINTS-1))+3 ) );
 
-    for( iNextPoint = 0; iNextPoint < nTotalPoints;  )
+    for( int iNextPoint = 0; iNextPoint < nTotalPoints;  )
     {
-        DGNPoint asPoints[MAX_ELEM_POINTS];
+        DGNPoint asPoints[MAX_ELEM_POINTS] = {};
         int nThisCount = 0;
 
         // we need to repeat end points of elements.
@@ -1064,7 +1059,7 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
             && (pszStyle == NULL || strstr(pszStyle,"LABEL") == NULL) )
         {
             // Treat a non text point as a degenerate line.
-            DGNPoint asPoints[2];
+            DGNPoint asPoints[2] = {};
             asPoints[0].x = poPoint->getX();
             asPoints[0].y = poPoint->getY();
             asPoints[0].z = poPoint->getZ();
@@ -1128,10 +1123,7 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
             // papsGroup[0] = DGNCreateComplexHeaderFromGroup(
             //     hDGN, DGNT_COMPLEX_SHAPE_HEADER, dgnElements.size(),
             //     papsGroup+1 );
-            DGNPoint asPoints[1];
-            asPoints[0].x = 0;
-            asPoints[0].y = 0;
-            asPoints[0].z = 0;
+            DGNPoint asPoints[1] = {};
             papsGroup[0] = DGNCreateCellHeaderFromGroup(
                 hDGN, "", 1, NULL,
                 static_cast<int>(dgnElements.size()), papsGroup + 1,
@@ -1177,11 +1169,11 @@ OGRErr OGRDGNLayer::CreateFeatureWithGeom( OGRFeature *poFeature,
     int nMSLink = poFeature->GetFieldAsInteger( "MSLink" );
 
     // TODO: Use std::max and std::min.
-    nLevel = MAX(0,MIN(63,nLevel));
-    nColor = MAX(0,MIN(255,nColor));
-    nWeight = MAX(0,MIN(31,nWeight));
-    nStyle = MAX(0,MIN(7,nStyle));
-    nMSLink = MAX(0,nMSLink);
+    nLevel = std::max(0, std::min(63, nLevel));
+    nColor = std::max(0, std::min(255, nColor));
+    nWeight = std::max(0, std::min(31, nWeight));
+    nStyle = std::max(0, std::min(7, nStyle));
+    nMSLink = std::max(0, nMSLink);
 
     DGNUpdateElemCore( hDGN, papsGroup[0], nLevel, nGraphicGroup, nColor,
                        nWeight, nStyle );
diff --git a/ogr/ogrsf_frmts/dods/GNUmakefile b/ogr/ogrsf_frmts/dods/GNUmakefile
index 4aedbca..3fb0ad3 100644
--- a/ogr/ogrsf_frmts/dods/GNUmakefile
+++ b/ogr/ogrsf_frmts/dods/GNUmakefile
@@ -13,6 +13,6 @@ clean:
 	rm -f *.o $(O_OBJ)
 
 
-dodstest:	dodstest.cpp	
+dodstest:	dodstest.cpp
 	g++ -g -I$(DODS_INC) dodstest.cpp -o dodstest -L/u/pkg/DODS/lib -ldap++ -lpthread -lrx  -L/u/pkg/dods/DODS/lib -lcurl -lssl -lcrypto -L/u/pkg/dods/DODS/lib -lxml2 -L/u/pkg/dods/DODS/lib -ldl -lz
 
diff --git a/ogr/ogrsf_frmts/dods/libdap_headers.h b/ogr/ogrsf_frmts/dods/libdap_headers.h
new file mode 100644
index 0000000..a22be99
--- /dev/null
+++ b/ogr/ogrsf_frmts/dods/libdap_headers.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes libdap headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef LIBDAP_HEADERS_H
+#define LIBDAP_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#define DEFAULT_BASETYPE_FACTORY
+
+// #define DODS_DEBUG 1
+#include <debug.h>
+
+#include <BaseType.h>  // DODS
+#include <Byte.h>
+#include <Int16.h>
+#include <UInt16.h>
+#include <Int32.h>
+#include <UInt32.h>
+#include <Float32.h>
+#include <Float64.h>
+#include <Str.h>
+#include <Url.h>
+#include <Array.h>
+#include <Structure.h>
+#include <Sequence.h>
+#include <Grid.h>
+
+#ifdef LIBDAP_310
+/* AISConnect.h/AISConnect class was renamed to Connect.h/Connect in libdap 3.10 */
+#include <Connect.h>
+#define AISConnect Connect
+#else
+#include <AISConnect.h>
+#endif
+
+#include <DDS.h>
+#include <DAS.h>
+#include <BaseTypeFactory.h>
+#include <Error.h>
+#include <escaping.h>
+
+#endif
diff --git a/ogr/ogrsf_frmts/dods/ogr_dods.h b/ogr/ogrsf_frmts/dods/ogr_dods.h
index 627a90c..ef867b9 100644
--- a/ogr/ogrsf_frmts/dods/ogr_dods.h
+++ b/ogr/ogrsf_frmts/dods/ogr_dods.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_dods.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_dods.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/DODS driver.
@@ -41,39 +41,7 @@
 #include <algorithm>
 #include <exception>
 
-#define DEFAULT_BASETYPE_FACTORY
-
-// #define DODS_DEBUG 1
-#include <debug.h>
-
-#include <BaseType.h>		// DODS
-#include <Byte.h>
-#include <Int16.h>
-#include <UInt16.h>
-#include <Int32.h>
-#include <UInt32.h>
-#include <Float32.h>
-#include <Float64.h>
-#include <Str.h>
-#include <Url.h>
-#include <Array.h>
-#include <Structure.h>
-#include <Sequence.h>
-#include <Grid.h>
-
-#ifdef LIBDAP_310
-/* AISConnect.h/AISConnect class was renamed to Connect.h/Connect in libdap 3.10 */
-#include <Connect.h>
-#define AISConnect Connect
-#else
-#include <AISConnect.h>
-#endif
-
-#include <DDS.h>
-#include <DAS.h>
-#include <BaseTypeFactory.h>
-#include <Error.h>
-#include <escaping.h>
+#include "libdap_headers.h"
 
 using namespace libdap;
 
@@ -85,20 +53,20 @@ public:
     OGRDODSFieldDefn();
     ~OGRDODSFieldDefn();
 
-    int Initialize( AttrTable *,
-                    BaseType *poTarget = NULL, BaseType *poSuperSeq = NULL );
-    int Initialize( const char *, const char * = "das",
-                    BaseType *poTarget = NULL, BaseType *poSuperSeq = NULL );
+    bool Initialize( AttrTable *,
+                     BaseType *poTarget = NULL, BaseType *poSuperSeq = NULL );
+    bool Initialize( const char *, const char * = "das",
+                     BaseType *poTarget = NULL, BaseType *poSuperSeq = NULL );
 
-    int  bValid;
+    bool bValid;
     char *pszFieldName;
     char *pszFieldScope;
     int  iFieldIndex;
     char *pszFieldValue;
     char *pszPathToSequence;
 
-    int  bRelativeToSuperSequence;
-    int  bRelativeToSequence;
+    bool bRelativeToSuperSequence;
+    bool bRelativeToSequence;
 };
 
 /************************************************************************/
@@ -126,8 +94,8 @@ class OGRDODSLayer : public OGRLayer
 
     OGRDODSFieldDefn  **papoFields;
 
-    virtual int         ProvideDataDDS();
-    int                 bDataLoaded;
+    virtual bool        ProvideDataDDS();
+    bool                bDataLoaded;
 
     AISConnect         *poConnection;
     DataDDS            *poDataDDS;
@@ -136,7 +104,7 @@ class OGRDODSLayer : public OGRLayer
 
     AttrTable          *poOGRLayerInfo;
 
-    int                 bKnowExtent;
+    bool                bKnowExtent;
     OGREnvelope         sExtent;
 
   public:
@@ -145,18 +113,18 @@ class OGRDODSLayer : public OGRLayer
                                       AttrTable *poAttrInfo );
     virtual             ~OGRDODSLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
 
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
@@ -185,15 +153,15 @@ private:
     BaseType           *GetFieldValue( OGRDODSFieldDefn *, int,
                                        Sequence * );
 
-    double              BaseTypeToDouble( BaseType * );
+    static double              BaseTypeToDouble( BaseType * );
 
-    int                 BuildFields( BaseType *, const char *,
+    bool                BuildFields( BaseType *, const char *,
                                      const char * );
 
     Sequence           *FindSuperSequence( BaseType * );
 
 protected:
-    virtual int         ProvideDataDDS();
+    virtual bool        ProvideDataDDS() override;
 
 public:
                         OGRDODSSequenceLayer( OGRDODSDataSource *poDS,
@@ -201,9 +169,9 @@ public:
                                               AttrTable *poAttrInfo );
     virtual             ~OGRDODSSequenceLayer();
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual GIntBig     GetFeatureCount( int );
+    virtual GIntBig     GetFeatureCount( int ) override;
 };
 
 /************************************************************************/
@@ -274,14 +242,12 @@ class OGRDODSGridLayer : public OGRDODSLayer
     OGRDODSDim         *paoDimensions;
     int                 nMaxRawIndex;
 
-    void               *pRawData;
-
-    int                 ArrayEntryToField( Array *poArray, void *pRawData,
+    static bool                ArrayEntryToField( Array *poArray, void *pRawData,
                                            int iArrayIndex,
-                                           OGRFeature *poFeature, int iField);
+                                           OGRFeature *poFeature, int iField );
 
 protected:
-    virtual int         ProvideDataDDS();
+    virtual bool        ProvideDataDDS() override;
 
 public:
                         OGRDODSGridLayer( OGRDODSDataSource *poDS,
@@ -289,10 +255,9 @@ public:
                                          AttrTable *poAttrInfo );
     virtual             ~OGRDODSGridLayer();
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-
-    virtual GIntBig     GetFeatureCount( int );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
+    virtual GIntBig     GetFeatureCount( int ) override;
 };
 
 /************************************************************************/
@@ -326,11 +291,11 @@ class OGRDODSDataSource : public OGRDataSource
 
     int                 Open( const char * );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -341,15 +306,15 @@ class OGRDODSDriver : public OGRSFDriver
 {
   public:
                 ~OGRDODSDriver();
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
-    int                 TestCapability( const char * );
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
+    int                 TestCapability( const char * ) override;
 };
 
 string OGRDODSGetVarPath( BaseType * );
 int  OGRDODSGetVarIndex( Sequence *poParent, string oVarName );
 
-int  OGRDODSIsFloatInvalid( const float * );
-int  OGRDODSIsDoubleInvalid( const double * );
+bool OGRDODSIsFloatInvalid( const float * );
+bool OGRDODSIsDoubleInvalid( const double * );
 
 #endif /* ndef OGR_DODS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp b/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp
index ad9f773..38b004a 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodsdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdodsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSDataSource class.
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdodsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdodsdatasource.cpp 36182 2016-11-09 12:10:20Z rouault $");
 /************************************************************************/
 /*                         OGRDODSDataSource()                          */
 /************************************************************************/
@@ -85,9 +84,7 @@ int OGRDODSDataSource::Open( const char * pszNewName )
 /*      expression.                                                     */
 /* -------------------------------------------------------------------- */
     char *pszWrkURL = CPLStrdup( pszNewName + 5 );
-    char *pszFound;
-
-    pszFound = strstr(pszWrkURL,"&");
+    char *pszFound = strstr(pszWrkURL, "&");
     if( pszFound )
     {
         oConstraints = pszFound;
@@ -102,7 +99,7 @@ int OGRDODSDataSource::Open( const char * pszNewName )
     }
 
     // Trim common requests.
-    int nLen = strlen(pszWrkURL);
+    int nLen = static_cast<int>(strlen(pszWrkURL));
     if( strcmp(pszWrkURL+nLen-4,".das") == 0 )
         pszWrkURL[nLen-4] = '\0';
     else if( strcmp(pszWrkURL+nLen-4,".dds") == 0 )
@@ -125,15 +122,16 @@ int OGRDODSDataSource::Open( const char * pszNewName )
     if( CPLGetConfigOption( "DODS_CONF", NULL ) != NULL
         && getenv("DODS_CONF") == NULL )
     {
-        static char szDODS_CONF[1000];
+        const int knBufSize = 1000;
+        static char szDODS_CONF[knBufSize];
 
-        sprintf( szDODS_CONF, "DODS_CONF=%.980s",
-                 CPLGetConfigOption( "DODS_CONF", "" ) );
+        snprintf( szDODS_CONF, knBufSize, "DODS_CONF=%.980s",
+                  CPLGetConfigOption( "DODS_CONF", "" ) );
         putenv( szDODS_CONF );
     }
 
 /* -------------------------------------------------------------------- */
-/*      If we have a overridding AIS file location, apply it now.       */
+/*      If we have a overriding AIS file location, apply it now.       */
 /* -------------------------------------------------------------------- */
     if( CPLGetConfigOption( "DODS_AIS_FILE", NULL ) != NULL )
     {
@@ -276,10 +274,7 @@ void OGRDODSDataSource::AddLayer( OGRDODSLayer *poLayer )
 int OGRDODSDataSource::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,ODsCCreateLayer) )
-        return TRUE;
-    else
-        return FALSE;
+    return EQUAL(pszCap,ODsCCreateLayer);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp b/ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp
index 34cc260..8b76eb1 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodsdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdodsdriver.cpp 31120 2015-10-24 19:55:09Z rouault $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSDriver class.
@@ -30,7 +29,7 @@
 #include "ogr_dods.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdodsdriver.cpp 31120 2015-10-24 19:55:09Z rouault $");
+CPL_CVSID("$Id: ogrdodsdriver.cpp 36179 2016-11-09 10:19:21Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRDODSDriver()                            */
@@ -56,15 +55,13 @@ const char *OGRDODSDriver::GetName()
 /************************************************************************/
 
 OGRDataSource *OGRDODSDriver::Open( const char * pszFilename,
-                                     int bUpdate )
+                                     int /*bUpdate*/ )
 
 {
-    OGRDODSDataSource     *poDS;
-
     if( !STARTS_WITH_CI(pszFilename, "DODS:http:") )
         return NULL;
 
-    poDS = new OGRDODSDataSource();
+    OGRDODSDataSource *poDS = new OGRDODSDataSource();
 
     if( !poDS->Open( pszFilename ) )
     {
@@ -79,7 +76,7 @@ OGRDataSource *OGRDODSDriver::Open( const char * pszFilename,
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRDODSDriver::TestCapability( const char * pszCap )
+int OGRDODSDriver::TestCapability( const char * /*pszCap*/ )
 
 {
     return FALSE;
@@ -96,4 +93,3 @@ void RegisterOGRDODS()
         return;
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new OGRDODSDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp b/ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp
index a72f1da..3d7dc64 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodsfielddefn.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdodsfielddefn.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSFieldDefn class.  This is a small class used
@@ -31,21 +30,21 @@
 #include "ogr_dods.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdodsfielddefn.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdodsfielddefn.cpp 36182 2016-11-09 12:10:20Z rouault $");
 
 /************************************************************************/
 /*                          OGRDODSFieldDefn()                          */
 /************************************************************************/
 
 OGRDODSFieldDefn::OGRDODSFieldDefn() :
-    bValid(FALSE),
+    bValid(false),
     pszFieldName(NULL),
     pszFieldScope(NULL),
     iFieldIndex(-1),
     pszFieldValue(NULL),
     pszPathToSequence(NULL),
-    bRelativeToSuperSequence(FALSE),
-    bRelativeToSequence(FALSE)
+    bRelativeToSuperSequence(false),
+    bRelativeToSequence(false)
 {}
 
 /************************************************************************/
@@ -70,16 +69,16 @@ OGRDODSFieldDefn::~OGRDODSFieldDefn()
 /*      entry.                                                          */
 /************************************************************************/
 
-int OGRDODSFieldDefn::Initialize( AttrTable *poEntry,
-                                  BaseType *poTarget,
-                                  BaseType *poSuperSeq )
+bool OGRDODSFieldDefn::Initialize( AttrTable *poEntry,
+                                   BaseType *poTarget,
+                                   BaseType *poSuperSeq )
 
 {
-    const char *pszFieldScope = poEntry->get_attr("scope").c_str();
-    if( pszFieldScope == NULL )
-        pszFieldScope = "dds";
+    const char *l_pszFieldScope = poEntry->get_attr("scope").c_str();
+    if( l_pszFieldScope == NULL )
+        l_pszFieldScope = "dds";
 
-    return Initialize( poEntry->get_attr("name").c_str(), pszFieldScope,
+    return Initialize( poEntry->get_attr("name").c_str(), l_pszFieldScope,
                        poTarget, poSuperSeq );
 }
 
@@ -87,10 +86,10 @@ int OGRDODSFieldDefn::Initialize( AttrTable *poEntry,
 /*                             Initialize()                             */
 /************************************************************************/
 
-int OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn,
-                                  const char *pszFieldScopeIn,
-                                  BaseType *poTarget,
-                                  BaseType *poSuperSeq )
+bool OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn,
+                                   const char *pszFieldScopeIn,
+                                   BaseType *poTarget,
+                                   BaseType *poSuperSeq )
 
 {
     pszFieldScope = CPLStrdup( pszFieldScopeIn );
@@ -99,7 +98,7 @@ int OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn,
     if( poTarget != NULL && EQUAL(pszFieldScope,"dds") )
     {
         string oTargPath = OGRDODSGetVarPath( poTarget );
-        int    nTargPathLen = strlen(oTargPath.c_str());
+        int    nTargPathLen = static_cast<int>(strlen(oTargPath.c_str()));
 
         if( EQUALN(oTargPath.c_str(),pszFieldNameIn,nTargPathLen)
             && pszFieldNameIn[nTargPathLen] == '.' )
@@ -107,14 +106,14 @@ int OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn,
             CPLFree( pszFieldName );
             pszFieldName = CPLStrdup( pszFieldNameIn + nTargPathLen + 1 );
 
-            bRelativeToSequence = TRUE;
+            bRelativeToSequence = true;
             iFieldIndex = OGRDODSGetVarIndex(
                 dynamic_cast<Sequence *>( poTarget ), pszFieldName );
         }
         else if( poSuperSeq != NULL  )
         {
-            string oTargPath = OGRDODSGetVarPath( poSuperSeq );
-            int    nTargPathLen = strlen(oTargPath.c_str());
+            oTargPath = OGRDODSGetVarPath( poSuperSeq );
+            nTargPathLen = static_cast<int>(strlen(oTargPath.c_str()));
 
             if( EQUALN(oTargPath.c_str(),pszFieldNameIn,nTargPathLen)
                 && pszFieldNameIn[nTargPathLen] == '.' )
@@ -122,16 +121,16 @@ int OGRDODSFieldDefn::Initialize( const char *pszFieldNameIn,
                 CPLFree( pszFieldName );
                 pszFieldName = CPLStrdup( pszFieldNameIn + nTargPathLen + 1 );
 
-                bRelativeToSuperSequence = TRUE;
+                bRelativeToSuperSequence = true;
                 iFieldIndex = OGRDODSGetVarIndex(
                     dynamic_cast<Sequence *>( poSuperSeq ), pszFieldName );
             }
         }
     }
 
-    bValid = TRUE;
+    bValid = true;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp b/ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp
index 7c9c6ab..858d7bf 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodsgrid.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdodsgrid.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSGridLayer class, which implements the
@@ -32,7 +31,7 @@
 #include "ogr_dods.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdodsgrid.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdodsgrid.cpp 36663 2016-12-03 21:34:45Z rouault $");
 
 /************************************************************************/
 /*                          OGRDODSGridLayer()                          */
@@ -48,10 +47,8 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
     paoArrayRefs(NULL),
     nDimCount(0),
     paoDimensions(NULL),
-    nMaxRawIndex(0),
-    pRawData(NULL)
+    nMaxRawIndex(0)
 {
-
 /* -------------------------------------------------------------------- */
 /*      What is the layer name?                                         */
 /* -------------------------------------------------------------------- */
@@ -85,7 +82,7 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
     }
     else
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return;
     }
 
@@ -316,7 +313,6 @@ OGRDODSGridLayer::OGRDODSGridLayer( OGRDODSDataSource *poDSIn,
             oZField.iFieldIndex =
                 poFeatureDefn->GetFieldIndex( oZField.pszFieldName );
         }
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -369,67 +365,67 @@ OGRDODSGridLayer::~OGRDODSGridLayer()
 /*                         ArrayEntryToField()                          */
 /************************************************************************/
 
-int OGRDODSGridLayer::ArrayEntryToField( Array *poArray, void *pRawData,
-                                         int iArrayIndex,
-                                         OGRFeature *poFeature, int iField)
+bool OGRDODSGridLayer::ArrayEntryToField( Array *poArray, void *pRawDataIn,
+                                          int iArrayIndex,
+                                          OGRFeature *poFeature, int iField )
 
 {
     switch( poArray->var()->type() )
     {
       case dods_byte_c:
       {
-          GByte *pabyRawData = (GByte *) pRawData;
+          GByte *pabyRawData = (GByte *) pRawDataIn;
           poFeature->SetField( iField, pabyRawData[iArrayIndex] );
       }
       break;
 
       case dods_int16_c:
       {
-          GInt16 *panRawData = (GInt16 *) pRawData;
+          GInt16 *panRawData = (GInt16 *) pRawDataIn;
           poFeature->SetField( iField, panRawData[iArrayIndex] );
       }
       break;
 
       case dods_uint16_c:
       {
-          GUInt16 *panRawData = (GUInt16 *) pRawData;
+          GUInt16 *panRawData = (GUInt16 *) pRawDataIn;
           poFeature->SetField( iField, panRawData[iArrayIndex] );
       }
       break;
 
       case dods_int32_c:
       {
-          GInt32 *panRawData = (GInt32 *) pRawData;
+          GInt32 *panRawData = (GInt32 *) pRawDataIn;
           poFeature->SetField( iField, panRawData[iArrayIndex] );
       }
       break;
 
       case dods_uint32_c:
       {
-          GUInt32 *panRawData = (GUInt32 *) pRawData;
+          GUInt32 *panRawData = (GUInt32 *) pRawDataIn;
           poFeature->SetField( iField, (int) panRawData[iArrayIndex] );
       }
       break;
 
       case dods_float32_c:
       {
-          float * pafRawData = (float *) pRawData;
+          float * pafRawData = (float *) pRawDataIn;
           poFeature->SetField( iField, pafRawData[iArrayIndex] );
       }
       break;
 
       case dods_float64_c:
       {
-          double * padfRawData = (double *) pRawData;
+          double * padfRawData = (double *) pRawDataIn;
           poFeature->SetField( iField, padfRawData[iArrayIndex] );
       }
       break;
 
       default:
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -451,9 +447,7 @@ OGRFeature *OGRDODSGridLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
 /*      Create the feature being read.                                  */
 /* -------------------------------------------------------------------- */
-    OGRFeature *poFeature;
-
-    poFeature = new OGRFeature( poFeatureDefn );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     poFeature->SetFID( nFeatureId );
     m_nFeaturesRead++;
 
@@ -461,7 +455,7 @@ OGRFeature *OGRDODSGridLayer::GetFeature( GIntBig nFeatureId )
 /*      Establish the values for the various dimension indices.         */
 /* -------------------------------------------------------------------- */
     int iDim;
-    int nRemainder = nFeatureId;
+    int nRemainder = static_cast<int>(nFeatureId);
 
     for( iDim = nDimCount-1; iDim >= 0; iDim-- )
     {
@@ -499,7 +493,8 @@ OGRFeature *OGRDODSGridLayer::GetFeature( GIntBig nFeatureId )
     {
         OGRDODSArrayRef *poRef = paoArrayRefs + iArray;
 
-        ArrayEntryToField( poRef->poArray, poRef->pRawData, nFeatureId,
+        ArrayEntryToField( poRef->poArray, poRef->pRawData,
+                           static_cast<int>(nFeatureId),
                            poFeature, poRef->iFieldIndex );
     }
 
@@ -526,19 +521,18 @@ OGRFeature *OGRDODSGridLayer::GetFeature( GIntBig nFeatureId )
 /*                           ProvideDataDDS()                           */
 /************************************************************************/
 
-int OGRDODSGridLayer::ProvideDataDDS()
+bool OGRDODSGridLayer::ProvideDataDDS()
 
 {
     if( bDataLoaded )
         return poTargetVar != NULL;
 
-    int bResult = OGRDODSLayer::ProvideDataDDS();
+    const bool  bResult = OGRDODSLayer::ProvideDataDDS();
 
     if( !bResult )
         return bResult;
 
-    int iArray;
-    for( iArray=0; iArray < nArrayRefCount; iArray++ )
+    for( int iArray=0; iArray < nArrayRefCount; iArray++ )
     {
         OGRDODSArrayRef *poRef = paoArrayRefs + iArray;
         BaseType *poTarget = poDataDDS->var( poRef->pszName );
@@ -558,8 +552,8 @@ int OGRDODSGridLayer::ProvideDataDDS()
         }
         else
         {
-            CPLAssert( FALSE );
-            return FALSE;
+            CPLAssert( false );
+            return false;
         }
 
         if( iArray == 0 )
@@ -573,14 +567,16 @@ int OGRDODSGridLayer::ProvideDataDDS()
     // Setup pointers to each of the map objects.
     if( poTargetGrid != NULL )
     {
-        int iMap;
+        int iMap = 0;
         Grid::Map_iter iterMap;
 
-        for( iterMap = poTargetGrid->map_begin(), iMap = 0;
+        for( iterMap = poTargetGrid->map_begin();
              iterMap != poTargetGrid->map_end();
              iterMap++, iMap++ )
         {
             paoDimensions[iMap].poMap = dynamic_cast<Array *>(*iterMap);
+            if( paoDimensions[iMap].poMap == NULL )
+                return false;
             paoDimensions[iMap].pRawData =
                 CPLMalloc( paoDimensions[iMap].poMap->width() );
             paoDimensions[iMap].poMap->buf2val( &(paoDimensions[iMap].pRawData) );
diff --git a/ogr/ogrsf_frmts/dods/ogrdodslayer.cpp b/ogr/ogrsf_frmts/dods/ogrdodslayer.cpp
index 7352b2d..a5a5a16 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodslayer.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdodslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSLayer class.
@@ -30,7 +29,7 @@
 #include "ogr_dods.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdodslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdodslayer.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 /************************************************************************/
 /*                            OGRDODSLayer()                            */
@@ -47,12 +46,12 @@ OGRDODSLayer::OGRDODSLayer( OGRDODSDataSource *poDSIn,
     pszFIDColumn (NULL),
     pszTarget(CPLStrdup( pszTargetIn )),
     papoFields(NULL),
-    bDataLoaded(FALSE),
+    bDataLoaded(false),
     poConnection(NULL),
     poDataDDS(new DataDDS( poDSIn->poBTF )),
     poTargetVar(NULL),
     poOGRLayerInfo(poOGRLayerInfoIn),
-    bKnowExtent(FALSE)
+    bKnowExtent(false)
 {
 /* ==================================================================== */
 /*      Harvest some metadata if available.                             */
@@ -84,13 +83,12 @@ OGRDODSLayer::OGRDODSLayer( OGRDODSDataSource *poDSIn,
         AttrTable *poLayerExt=poOGRLayerInfo->find_container("layer_extents");
         if( poLayerExt != NULL )
         {
-            bKnowExtent = TRUE;
+            bKnowExtent = true;
             sExtent.MinX = CPLAtof(poLayerExt->get_attr("x_min").c_str());
             sExtent.MaxX = CPLAtof(poLayerExt->get_attr("x_max").c_str());
             sExtent.MinY = CPLAtof(poLayerExt->get_attr("y_min").c_str());
             sExtent.MaxY = CPLAtof(poLayerExt->get_attr("y_max").c_str());
         }
-
     }
 
 /* ==================================================================== */
@@ -159,9 +157,7 @@ void OGRDODSLayer::ResetReading()
 OGRFeature *OGRDODSLayer::GetNextFeature()
 
 {
-    OGRFeature *poFeature;
-
-    for( poFeature = GetFeature( iNextShapeId++ );
+    for( OGRFeature *poFeature = GetFeature( iNextShapeId++ );
          poFeature != NULL;
          poFeature = GetFeature( iNextShapeId++ ) )
     {
@@ -180,7 +176,7 @@ OGRFeature *OGRDODSLayer::GetNextFeature()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRDODSLayer::TestCapability( const char * pszCap )
+int OGRDODSLayer::TestCapability( const char * /* pszCap */ )
 
 {
     return FALSE;
@@ -200,13 +196,13 @@ OGRSpatialReference *OGRDODSLayer::GetSpatialRef()
 /*                           ProvideDataDDS()                           */
 /************************************************************************/
 
-int OGRDODSLayer::ProvideDataDDS()
+bool OGRDODSLayer::ProvideDataDDS()
 
 {
     if( bDataLoaded )
         return poTargetVar != NULL;
 
-    bDataLoaded = TRUE;
+    bDataLoaded = true;
     try
     {
         poConnection = new AISConnect( poDS->oBaseURL );
@@ -223,7 +219,7 @@ int OGRDODSLayer::ProvideDataDDS()
         CPLError( CE_Failure, CPLE_AppDefined,
                   "DataDDS request failed:\n%s",
                   e.get_error_message().c_str() );
-        return FALSE;
+        return false;
     }
 
     poTargetVar = poDataDDS->var( pszTarget );
@@ -238,21 +234,19 @@ int OGRDODSLayer::ProvideDataDDS()
 OGRErr OGRDODSLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 
 {
-    OGRErr eErr;
-
     if( bKnowExtent )
     {
-        *psExtent = this->sExtent;
+        *psExtent = sExtent;
         return OGRERR_NONE;
     }
 
     if( !bForce )
         return OGRERR_FAILURE;
 
-    eErr = OGRLayer::GetExtent( &sExtent, bForce );
+    const OGRErr eErr = OGRLayer::GetExtent( &sExtent, bForce );
     if( eErr == OGRERR_NONE )
     {
-        bKnowExtent = TRUE;
+        bKnowExtent = true;
         *psExtent = sExtent;
     }
 
diff --git a/ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp b/ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp
index 5fa4983..ed12419 100644
--- a/ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp
+++ b/ogr/ogrsf_frmts/dods/ogrdodssequencelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdodssequencelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OGR/DODS Interface
  * Purpose:  Implements OGRDODSSequenceLayer class, which implements the
@@ -32,7 +31,7 @@
 #include "ogr_dods.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdodssequencelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdodssequencelayer.cpp 36663 2016-12-03 21:34:45Z rouault $");
 
 /************************************************************************/
 /*                        OGRDODSSequenceLayer()                        */
@@ -153,16 +152,14 @@ OGRDODSSequenceLayer::~OGRDODSSequenceLayer()
 
 /************************************************************************/
 /*                         FindSuperSequence()                          */
-/*									*/
+/*                                                                      */
 /*      Are we a subsequence of a sequence?                             */
 /************************************************************************/
 
 Sequence *OGRDODSSequenceLayer::FindSuperSequence( BaseType *poChild )
 
 {
-    BaseType *poParent;
-
-    for( poParent = poChild->get_parent();
+    for( BaseType *poParent = poChild->get_parent();
          poParent != NULL;
          poParent = poParent->get_parent() )
     {
@@ -182,9 +179,9 @@ Sequence *OGRDODSSequenceLayer::FindSuperSequence( BaseType *poChild )
 /*      the passed variable and it's children (if it has them).         */
 /************************************************************************/
 
-int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
-                                       const char *pszPathToVar,
-                                       const char *pszPathToSequence )
+bool OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
+                                        const char *pszPathToVar,
+                                        const char *pszPathToSequence )
 
 {
     OGRFieldDefn oField( "", OFTInteger );
@@ -237,22 +234,22 @@ int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
 
           // We don't support a 3rd level of sequence nesting.
           if( pszPathToSequence != NULL )
-              return FALSE;
+              return false;
 
           // We don't explore down into the target sequence if we
           // are recursing from a supersequence.
-          if( poFieldVar == this->poTargetVar )
-              return FALSE;
+          if( poFieldVar == poTargetVar )
+              return false;
 
           for( v_i = seq->var_begin(); v_i != seq->var_end(); v_i++ )
           {
               BuildFields( *v_i, oField.GetNameRef(), oField.GetNameRef() );
           }
       }
-      return FALSE;
+      return false;
 
       default:
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -270,12 +267,11 @@ int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
         OGRDODSGetVarPath(poFieldVar).c_str(), "dds",
         poTargetVar, poSuperSeq );
 
-
     if( pszPathToSequence )
         papoFields[poFeatureDefn->GetFieldCount()-1]->pszPathToSequence
             = CPLStrdup( pszPathToSequence );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -399,7 +395,7 @@ double OGRDODSSequenceLayer::BaseTypeToDouble( BaseType *poBT )
       break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         break;
     }
 
@@ -414,9 +410,7 @@ double OGRDODSSequenceLayer::GetFieldValueAsDouble( OGRDODSFieldDefn *poFDefn,
                                                     int nFeatureId )
 
 {
-    BaseType *poBT;
-
-    poBT = GetFieldValue( poFDefn, nFeatureId, NULL );
+    BaseType *poBT = GetFieldValue( poFDefn, nFeatureId, NULL );
     if( poBT == NULL )
         return 0.0;
 
@@ -449,21 +443,22 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
         return NULL;
 
     if( poSuperSeq == NULL )
-        iSubSeq = nFeatureId;
+        iSubSeq = static_cast<int>(nFeatureId);
     else
     {
-        int nSeqOffset = 0, iSuperSeq;
+        int nSeqOffset = 0;
 
-        // for now we just scan through till find find out what
+        // For now we just scan through till find find out what
         // super sequence this in.  In the long term we need a better (cached)
         // approach that doesn't involve this quadratic cost.
-        for( iSuperSeq = 0;
+        int iSuperSeq = 0;  // Used after for.
+        for( ;
              iSuperSeq < nSuperSeqCount;
              iSuperSeq++ )
         {
             if( nSeqOffset + panSubSeqSize[iSuperSeq] > nFeatureId )
             {
-                iSubSeq = nFeatureId - nSeqOffset;
+                iSubSeq = static_cast<int>(nFeatureId) - nSeqOffset;
                 break;
             }
             nSeqOffset += panSubSeqSize[iSuperSeq];
@@ -484,9 +479,7 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
 /*      Create the feature being read.                                  */
 /* -------------------------------------------------------------------- */
-    OGRFeature *poFeature;
-
-    poFeature = new OGRFeature( poFeatureDefn );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     poFeature->SetFID( nFeatureId );
     m_nFeaturesRead++;
 
@@ -589,7 +582,6 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRDODSFieldDefn *poFD = papoFields[iField];
-        const char *pszPathFromSubSeq;
 
         if( poFD->pszPathToSequence == NULL )
             continue;
@@ -597,6 +589,8 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
         CPLAssert( strlen(poFD->pszPathToSequence)
                    < strlen(poFD->pszFieldName)-1 );
 
+        const char *pszPathFromSubSeq = NULL;
+
         if( strstr(poFD->pszFieldName,poFD->pszPathToSequence) != NULL )
             pszPathFromSubSeq =
                 strstr(poFD->pszFieldName,poFD->pszPathToSequence)
@@ -609,13 +603,12 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
         BaseType *poFieldVar = seq->var_value( iSubSeq,
                                                poFD->pszPathToSequence );
-        Sequence *poSubSeq;
         int nSubSeqCount;
 
         if( poFieldVar == NULL )
             continue;
 
-        poSubSeq = dynamic_cast<Sequence *>( poFieldVar );
+        Sequence *poSubSeq = dynamic_cast<Sequence *>( poFieldVar );
         if( poSubSeq == NULL )
             continue;
 
@@ -783,14 +776,17 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
         else if( poFeature->GetFieldDefnRef(iXField)->GetType() == OFTRealList
             && poFeature->GetFieldDefnRef(iYField)->GetType() == OFTRealList )
         {
-            const double *padfX, *padfY, *padfZ = NULL;
             int nPointCount, i;
             OGRLineString *poLS = new OGRLineString();
 
-            padfX = poFeature->GetFieldAsDoubleList( iXField, &nPointCount );
-            padfY = poFeature->GetFieldAsDoubleList( iYField, &nPointCount );
-            if( iZField != -1 )
-                padfZ = poFeature->GetFieldAsDoubleList(iZField,&nPointCount);
+            const double *padfX =
+                poFeature->GetFieldAsDoubleList(iXField, &nPointCount);
+            const double *padfY =
+                poFeature->GetFieldAsDoubleList(iYField, &nPointCount);
+            const double *padfZ =
+                iZField != -1
+                ? poFeature->GetFieldAsDoubleList(iZField, &nPointCount)
+                : NULL;
 
             poLS->setPoints( nPointCount, (double *) padfX, (double *) padfY,
                              (double *) padfZ );
@@ -801,22 +797,22 @@ OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
                 double dfX = poLS->getX(i);
                 double dfY = poLS->getY(i);
                 double dfZ = poLS->getZ(i);
-                int bReset = FALSE;
+                bool bReset = false;
 
                 if( OGRDODSIsDoubleInvalid( &dfX ) )
                 {
                     dfX = 0.0;
-                    bReset = TRUE;
+                    bReset = true;
                 }
                 if( OGRDODSIsDoubleInvalid( &dfY ) )
                 {
                     dfY = 0.0;
-                    bReset = TRUE;
+                    bReset = true;
                 }
                 if( OGRDODSIsDoubleInvalid( &dfZ ) )
                 {
                     dfZ = 0.0;
-                    bReset = TRUE;
+                    bReset = true;
                 }
 
                 if( bReset )
@@ -861,7 +857,7 @@ GIntBig OGRDODSSequenceLayer::GetFeatureCount( int bForce )
 /*                           ProvideDataDDS()                           */
 /************************************************************************/
 
-int OGRDODSSequenceLayer::ProvideDataDDS()
+bool OGRDODSSequenceLayer::ProvideDataDDS()
 
 {
     if( bDataLoaded )
@@ -884,7 +880,12 @@ int OGRDODSSequenceLayer::ProvideDataDDS()
 /*      count of elements.                                              */
 /* -------------------------------------------------------------------- */
     if( poSuperSeq == NULL )
-        nRecordCount = dynamic_cast<Sequence *>(poTargetVar)->number_of_rows();
+    {
+        Sequence* poSeq = dynamic_cast<Sequence *>(poTargetVar);
+        if( poSeq == NULL )
+            return false;
+        nRecordCount = poSeq->number_of_rows();
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Otherwise we have to count up all the target sequence           */
@@ -976,8 +977,8 @@ The value V represented by the word may be determined as follows:
 /*      or -Inf.                                                        */
 /************************************************************************/
 
-
-int OGRDODSIsFloatInvalid( const float * pfValToCheck )
+#if 0  // Unused.
+bool OGRDODSIsFloatInvalid( const float * pfValToCheck )
 
 {
     const unsigned char *pabyValToCheck = (unsigned char *) pfValToCheck;
@@ -985,17 +986,18 @@ int OGRDODSIsFloatInvalid( const float * pfValToCheck )
 #if CPL_IS_LSB == 0
     if( (pabyValToCheck[0] & 0x7f) == 0x7f
         && (pabyValToCheck[1] & 0x80) == 0x80 )
-        return TRUE;
+        return true;
     else
-        return FALSE;
+        return false;
 #else
     if( (pabyValToCheck[3] & 0x7f) == 0x7f
         && (pabyValToCheck[2] & 0x80) == 0x80 )
-        return TRUE;
+        return true;
     else
-        return FALSE;
+        return false;
 #endif
 }
+#endif
 
 /************************************************************************/
 /*                       OGRDODSIsDoubleInvalid()                       */
@@ -1004,8 +1006,7 @@ int OGRDODSIsFloatInvalid( const float * pfValToCheck )
 /*      or -Inf.                                                        */
 /************************************************************************/
 
-
-int OGRDODSIsDoubleInvalid( const double * pdfValToCheck )
+bool OGRDODSIsDoubleInvalid( const double * pdfValToCheck )
 
 {
     const unsigned char *pabyValToCheck = (unsigned char *) pdfValToCheck;
@@ -1013,14 +1014,14 @@ int OGRDODSIsDoubleInvalid( const double * pdfValToCheck )
 #if CPL_IS_LSB == 0
     if( (pabyValToCheck[0] & 0x7f) == 0x7f
         && (pabyValToCheck[1] & 0xf0) == 0xf0 )
-        return TRUE;
+        return true;
     else
-        return FALSE;
+        return false;
 #else
     if( (pabyValToCheck[7] & 0x7f) == 0x7f
         && (pabyValToCheck[6] & 0xf0) == 0xf0 )
-        return TRUE;
+        return true;
     else
-        return FALSE;
+        return false;
 #endif
 }
diff --git a/ogr/ogrsf_frmts/dwg/GNUmakefile b/ogr/ogrsf_frmts/dwg/GNUmakefile
index 273a01f..8f8f706 100644
--- a/ogr/ogrsf_frmts/dwg/GNUmakefile
+++ b/ogr/ogrsf_frmts/dwg/GNUmakefile
@@ -1,53 +1,27 @@
-TD_ROOT = /home/warmerda/pkg/td_4.2
-TDLIB_ROOT = $(TD_ROOT)/lib/lnxX64_4.2pic
-TDXXFLAGS = \
-	-I$(TD_ROOT)/TD/Include \
-	-I$(TD_ROOT)/TD/Extensions/ExServices \
-	-I$(TD_ROOT)/TD/Examples/Common
-
-TD_LIBS =	$(TDLIB_ROOT)/libModelerGeometry.a \
-	$(TDLIB_ROOT)/libTD_BrepRenderer.a \
-	$(TDLIB_ROOT)/libTD_Br.a \
-        $(TDLIB_ROOT)/libTD_AcisBuilder.a \
-        $(TDLIB_ROOT)/libTD_DynBlocks.a \
-        $(TDLIB_ROOT)/libTD_Db.a \
-        $(TDLIB_ROOT)/libTD_DbRoot.a \
-        $(TDLIB_ROOT)/libTD_Gs.a \
-        $(TDLIB_ROOT)/libTD_SpatialIndex.a \
-        $(TDLIB_ROOT)/libTD_Ave.a \
-        $(TDLIB_ROOT)/libTD_Root.a \
-        $(TDLIB_ROOT)/libTD_Gi.a \
-        $(TDLIB_ROOT)/libTD_Ge.a \
-        $(TDLIB_ROOT)/libTD_FT.a \
-        $(TDLIB_ROOT)/libTD_Alloc.a \
-        $(TDLIB_ROOT)/libRxRasterServices.a \
-        $(TDLIB_ROOT)/libJpeg.a \
-        $(TDLIB_ROOT)/libRecomputeDimBlock.a \
-        $(TDLIB_ROOT)/libExFieldEvaluator.a \
-        $(TDLIB_ROOT)/libOdBagFiler.a \
-        $(TDLIB_ROOT)/libRasterProcessor.a \
-	$(TDLIB_ROOT)/libTD_ExamplesCommon.a
 
+TDXXFLAGS = \
+	-I$(TEIGHA_DIR)/Core/Include \
+	-I$(TEIGHA_DIR)/Core/Extensions/ExServices \
+	-I$(TEIGHA_DIR)/Core/Examples/Common \
+	-I$(TEIGHA_DIR)/Dgn/include \
+	-I$(TEIGHA_DIR)/Dgn/Extensions/ExServices
 
 include ../../../GDALmake.opt
 
 OBJ	=	ogrdwgdriver.o ogrdwgdatasource.o ogrdwglayer.o \
 		ogrdwg_dimension.o ogrdwg_hatch.o ogrdwgblockslayer.o \
-		ogrdwg_blockmap.o
+		ogrdwg_blockmap.o \
+		ogrdgnv8driver.o ogrdgnv8datasource.o ogrdgnv8layer.o \
+		ogrteigha.o
 
 CPPFLAGS	:=	 -I../dxf $(TDXXFLAGS) $(CPPFLAGS)
 
-PLUGIN_SO	=	ogr_DWG.so
-
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
 clean:
-	rm -f *.o $(O_OBJ) $(PLUGIN_SO)
-
-$(O_OBJ) $(OBJ):	ogr_dwg.h 
+	rm -f *.o $(O_OBJ) createdgnv8testfile$(EXE)
 
-plugin: $(PLUGIN_SO)
+$(O_OBJ) $(OBJ):	ogr_dwg.h ogr_dgnv8.h
 
-$(PLUGIN_SO):	$(OBJ) 
-	gcc -shared $(LNK_FLAGS) $(OBJ) $(CONFIG_LIBS_INS) $(EXTRA_LIBS) $(TD_LIBS) \
-		-o $(PLUGIN_SO)
+createdgnv8testfile$(EXE):	createdgnv8testfile.$(OBJ_EXT)
+	$(LD) $(LDFLAGS) createdgnv8testfile.$(OBJ_EXT) $(CONFIG_LIBS) -o createdgnv8testfile$(EXE)
diff --git a/ogr/ogrsf_frmts/dwg/createdgnv8testfile.cpp b/ogr/ogrsf_frmts/dwg/createdgnv8testfile.cpp
new file mode 100644
index 0000000..f8369dc
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/createdgnv8testfile.cpp
@@ -0,0 +1,826 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Generate a test .dgn file
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "createdgnv8testfile_headers.h"
+
+const double DEG_TO_RAD = 3.141592653589793 / 180.0;
+
+/************************************************************************/
+/*                         OGRDGNV8Services                             */
+/*                                                                      */
+/*      Services implementation for OGR.  Eventually we should          */
+/*      override the OdExDgnSystemServices IO to use VSI*L.             */
+/************************************************************************/
+
+class OGRDGNV8Services : public OdExDgnSystemServices,
+                         public OdExDgnHostAppServices
+{
+protected:
+  ODRX_USING_HEAP_OPERATORS(OdExDgnSystemServices);
+};
+
+static OdStaticRxObject<OGRDGNV8Services> oServices;
+
+int main()
+{
+    odrxInitialize(&oServices);
+    oServices.disableProgressMeterOutput( true );
+    ::odrxDynamicLinker()->loadModule(L"TG_Db", false);
+
+    OdDgDatabasePtr pDb = oServices.createDatabase();
+
+    OdDgModelPtr pModel = pDb->getActiveModelId().openObject(OdDg::kForWrite);
+    pModel->setWorkingUnit( OdDgModel::kWuMasterUnit );
+    pModel->setName( "my_model" );
+    pModel->setDescription( "my_description" );
+
+    // Add font
+    OdDgFontTablePtr pFontTable = pModel->database()->getFontTable(OdDg::kForWrite);
+    {
+        OdDgFontTableRecordPtr pFont = OdDgFontTableRecord::createObject();
+        pFont->setName("Arial");
+        pFont->setType(kFontTypeTrueType);
+
+        pFontTable->add(pFont);
+    }
+
+    // Read as point by OGR
+    {
+        OdDgLine3dPtr line = OdDgLine3d::createObject();
+        pModel->addElement(line);
+        OdGePoint3d point;  
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        line->setStartPoint(point);
+        line->setEndPoint(point);
+
+        line->setLevelEntryId(1);
+        line->setGraphicsGroupEntryId(2);
+        line->setColorIndex(3);
+        line->setLineStyleEntryId(4);
+        line->setLineWeight(5);
+    }
+    
+    // Read as point by OGR
+    {
+        OdDgLine2dPtr line = OdDgLine2d::createObject();
+        pModel->addElement(line);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        line->setStartPoint(point);
+        line->setEndPoint(point);
+    }
+
+    {
+        OdDgLine3dPtr line = OdDgLine3d::createObject();
+        pModel->addElement(line);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        line->setStartPoint(point);
+        point.x = 3;
+        point.y = 4;
+        point.z = 5;
+        line->setEndPoint(point);
+    }
+
+    {
+        OdDgLine2dPtr line = OdDgLine2d::createObject();
+        pModel->addElement(line);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        line->setStartPoint(point);
+        point.x = 2;
+        point.y = 3;
+        line->setEndPoint(point);
+    }
+
+    {
+        OdDgText2dPtr text = OdDgText2d::createObject();
+        pModel->addElement(text);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        text->setOrigin(point);
+        text->setText(L"myT\u00e9.xt");
+        text->setRotation(-45 * DEG_TO_RAD);
+        text->setHeightMultiplier( 1.0 );
+        text->setLengthMultiplier( 1.0 );
+        OdUInt32 nIdx = OdDgColorTable::getColorIndexByRGB(
+            text->database(), ODRGB( 255, 200, 150 ) );
+        text->setColorIndex(nIdx);
+
+        OdDgElementId idFont = pFontTable->getAt( "Arial" );
+        if( !idFont.isNull() )
+        {
+            OdDgFontTableRecordPtr pFont = idFont.openObject(OdDg::kForRead);
+            OdUInt32 uFontEntryId = pFont->getNumber();
+            text->setFontEntryId(uFontEntryId);
+        }
+    }
+
+    {
+        OdDgText3dPtr text = OdDgText3d::createObject();
+        pModel->addElement(text);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        text->setOrigin(point);
+        text->setText("x");
+        text->setHeightMultiplier( 1.0 );
+        text->setLengthMultiplier( 1.0 );
+    }
+
+    {
+        OdDgTextNode2dPtr textNode = OdDgTextNode2d::createObject();
+        pModel->addElement(textNode);
+
+        OdDgText2dPtr text = OdDgText2d::createObject();
+        textNode->add(text);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        text->setOrigin(point);
+        text->setText("z");
+        text->setHeightMultiplier( 1.0 );
+        text->setLengthMultiplier( 1.0 );
+    }
+
+    {
+        OdDgTextNode3dPtr textNode = OdDgTextNode3d::createObject();
+        pModel->addElement(textNode);
+
+        OdDgText3dPtr text = OdDgText3d::createObject();
+        textNode->add(text);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        text->setOrigin(point);
+        text->setText("z");
+        text->setHeightMultiplier( 1.0 );
+        text->setLengthMultiplier( 1.0 );
+    }
+
+    {
+        OdDgLineString3dPtr line = OdDgLineString3d::createObject();
+        pModel->addElement(line);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        line->addVertex(point);
+        point.x = 3;
+        point.y = 4;
+        point.z = 5;
+        line->addVertex(point);
+        point.x = 6;
+        point.y = 7;
+        point.z = 8;
+        line->addVertex(point);
+    }
+
+    {
+        OdDgLineString2dPtr line = OdDgLineString2d::createObject();
+        pModel->addElement(line);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        line->addVertex(point);
+        point.x = 3;
+        point.y = 4;
+        line->addVertex(point);
+        point.x = 6;
+        point.y = 7;
+        line->addVertex(point);
+    }
+
+    {
+        OdDgPointString2dPtr line = OdDgPointString2d::createObject();
+        pModel->addElement(line);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        line->addVertex(point, OdGeMatrix2d::rotation(0));
+        point.x = 3;
+        point.y = 4;
+        line->addVertex(point, OdGeMatrix2d::rotation(0));
+    }
+
+    {
+        OdDgPointString3dPtr line = OdDgPointString3d::createObject();
+        pModel->addElement(line);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        line->addVertex(point, OdGeQuaternion( 1., 0., 0., 0. ));
+        point.x = 3;
+        point.y = 4;
+        line->addVertex(point, OdGeQuaternion( 1., 0., 0., 0. ));
+    }
+
+    {
+        OdDgMultilinePtr multiline = OdDgMultiline::createObject();
+        pModel->addElement(multiline);
+        OdDgMultilinePoint multilinePoint;
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        multilinePoint.setPoint(point);
+        multiline->addPoint( multilinePoint );
+    }
+
+    // True ellipse
+    {
+        OdDgEllipse2dPtr ellipse = OdDgEllipse2d::createObject();
+        pModel->addElement(ellipse);
+        ellipse->setPrimaryAxis(1);
+        ellipse->setSecondaryAxis(2);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        ellipse->setOrigin(point);
+    }
+
+    // Circle
+    {
+        OdDgEllipse2dPtr ellipse = OdDgEllipse2d::createObject();
+        pModel->addElement(ellipse);
+        ellipse->setPrimaryAxis(1);
+        ellipse->setSecondaryAxis(1);
+        ellipse->setRotationAngle(45 * DEG_TO_RAD);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        ellipse->setOrigin(point);
+    }
+
+    // Circle
+    {
+        OdDgEllipse3dPtr ellipse = OdDgEllipse3d::createObject();
+        pModel->addElement(ellipse);
+        ellipse->setPrimaryAxis(1);
+        ellipse->setSecondaryAxis(1);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        ellipse->setOrigin(point);
+    }
+
+    // True arc
+    {
+        OdDgArc2dPtr arc = OdDgArc2d::createObject();
+        pModel->addElement(arc);
+        arc->setPrimaryAxis(1);
+        arc->setSecondaryAxis(2);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        arc->setOrigin(point);
+        arc->setStartAngle(10 * DEG_TO_RAD);
+        arc->setSweepAngle(180 * DEG_TO_RAD);
+    }
+
+    // Circle arc
+    {
+        OdDgArc2dPtr arc = OdDgArc2d::createObject();
+        pModel->addElement(arc);
+        arc->setPrimaryAxis(1);
+        arc->setSecondaryAxis(1);
+        arc->setRotationAngle(45 * DEG_TO_RAD);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        arc->setOrigin(point);
+        arc->setStartAngle(10 * DEG_TO_RAD);
+        arc->setSweepAngle(180 * DEG_TO_RAD);
+    }
+
+    // Circle arc
+    {
+        OdDgArc3dPtr arc = OdDgArc3d::createObject();
+        pModel->addElement(arc);
+        arc->setPrimaryAxis(1);
+        arc->setSecondaryAxis(1);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        arc->setOrigin(point);
+        arc->setStartAngle(10 * DEG_TO_RAD);
+        arc->setSweepAngle(180 * DEG_TO_RAD);
+    }
+
+    {
+        OdDgCurve2dPtr curve = OdDgCurve2d::createObject();
+        pModel->addElement(curve);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 0;
+        curve->addVertex(point);
+        point.x = 0;
+        point.y = 1;
+        curve->addVertex(point);
+        point.x = 1;
+        point.y = 1;
+        curve->addVertex(point);
+        point.x = 1;
+        point.y = 0;
+        curve->addVertex(point);
+
+        point.x = 0;
+        point.y = 0;
+        curve->addVertex(point);
+        point.x = 0;
+        point.y = 1;
+        curve->addVertex(point);
+        point.x = 1;
+        point.y = 1;
+        curve->addVertex(point);
+        point.x = 1;
+        point.y = 0;
+        curve->addVertex(point);
+    }
+
+    {
+        OdDgCurve3dPtr curve = OdDgCurve3d::createObject();
+        pModel->addElement(curve);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 0;
+        point.z = 1;
+        curve->addVertex(point);
+        point.x = 0;
+        point.y = 1;
+        curve->addVertex(point);
+        point.x = 1;
+        point.y = 1;
+        curve->addVertex(point);
+        point.x = 1;
+        point.y = 0;
+        curve->addVertex(point);
+
+        point.x = 0;
+        point.y = 0;
+        curve->addVertex(point);
+        point.x = 0;
+        point.y = 1;
+        curve->addVertex(point);
+        point.x = 1;
+        point.y = 1;
+        curve->addVertex(point);
+        point.x = 1;
+        point.y = 0;
+        curve->addVertex(point);
+    }
+
+    {
+        OdDgBSplineCurve3dPtr curve = OdDgBSplineCurve3d::createObject();
+        pModel->addElement( curve );
+
+        OdGePoint3dArray arrCtrlPts;
+        OdGePoint3d center;
+        double major = 1.0;
+        double minor = 0.5;
+        arrCtrlPts.push_back( center + OdGeVector3d( -1. * major,  1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -1. * major,  2. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -2. * major,  2. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -2. * major,  1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -1. * major,  1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  1. * major,  1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  2. * major,  1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  2. * major,  2. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  1. * major,  2. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  1. * major,  1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  1. * major, -1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  1. * major, -2. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  2. * major, -2. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  2. * major, -1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d(  1. * major, -1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -1. * major, -1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -2. * major, -1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -2. * major, -2. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -1. * major, -2. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -1. * major, -1. * minor, 0. ) );
+        arrCtrlPts.push_back( center + OdGeVector3d( -1. * major,  1. * minor, 0. ) );
+
+        OdGeKnotVector vrKnots;
+        OdGeDoubleArray arrWeights;
+
+        curve->setNurbsData( 4, false, true, arrCtrlPts, vrKnots, arrWeights );
+    }
+
+    {
+        OdDgBSplineCurve2dPtr curve = OdDgBSplineCurve2d::createObject();
+        pModel->addElement( curve );
+
+        OdGePoint2dArray arrCtrlPts;
+        OdGePoint2d center;
+        double major = 1.0;
+        double minor = 0.5;
+        arrCtrlPts.push_back( center + OdGeVector2d( -1. * major,  1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -1. * major,  2. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -2. * major,  2. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -2. * major,  1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -1. * major,  1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  1. * major,  1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  2. * major,  1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  2. * major,  2. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  1. * major,  2. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  1. * major,  1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  1. * major, -1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  1. * major, -2. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  2. * major, -2. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  2. * major, -1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d(  1. * major, -1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -1. * major, -1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -2. * major, -1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -2. * major, -2. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -1. * major, -2. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -1. * major, -1. * minor ) );
+        arrCtrlPts.push_back( center + OdGeVector2d( -1. * major,  1. * minor ) );
+
+        OdGeKnotVector vrKnots;
+        OdGeDoubleArray arrWeights;
+
+        curve->setNurbsData( 4, false, true, arrCtrlPts, vrKnots, arrWeights );
+    }
+
+    // ComplexString
+    {
+        OdDgComplexStringPtr complex = OdDgComplexString::createObject();
+        pModel->addElement(complex);
+
+        OdDgLine2dPtr line = OdDgLine2d::createObject();
+        complex->add(line);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        line->setStartPoint(point);
+        point.x = 2;
+        point.y = 3;
+        line->setEndPoint(point);
+
+        line = OdDgLine2d::createObject();
+        complex->add(line);
+        point.x = 2;
+        point.y = 3;
+        line->setStartPoint(point);
+        point.x = 4;
+        point.y = 5;
+        line->setEndPoint(point);
+    }
+
+    // ComplexString
+    {
+        OdDgComplexStringPtr complex = OdDgComplexString::createObject();
+        pModel->addElement(complex);
+
+        OdDgLine3dPtr line = OdDgLine3d::createObject();
+        complex->add(line);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        line->setStartPoint(point);
+        point.x = 2;
+        point.y = 3;
+        line->setEndPoint(point);
+
+        line = OdDgLine3d::createObject();
+        complex->add(line);
+        point.x = 2;
+        point.y = 3;
+        line->setStartPoint(point);
+        point.x = 4;
+        point.y = 5;
+        line->setEndPoint(point);
+    }
+
+    // ComplexString
+    {
+        OdDgComplexStringPtr complex = OdDgComplexString::createObject();
+        pModel->addElement(complex);
+
+        OdDgLine2dPtr line = OdDgLine2d::createObject();
+        complex->add(line);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 1;
+        line->setStartPoint(point);
+        point.x = 2;
+        point.y = 1;
+        line->setEndPoint(point);
+
+        OdDgArc2dPtr arc = OdDgArc2d::createObject();
+        complex->add(arc);
+        arc->setPrimaryAxis(1);
+        arc->setSecondaryAxis(1);
+        point.x = 3;
+        point.y = 1;
+        arc->setOrigin(point);
+        arc->setStartAngle(180 * DEG_TO_RAD);
+        arc->setSweepAngle(180 * DEG_TO_RAD);
+    }
+
+    // Polygon 2D
+    {
+        OdDgShape2dPtr shape = OdDgShape2d::createObject();
+        pModel->addElement(shape);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 0;
+        shape->addVertex(point);
+        point.x = 0;
+        point.y = 1;
+        shape->addVertex(point);
+        point.x = 1;
+        point.y = 1;
+        shape->addVertex(point);
+        point.x = 0;
+        point.y = 0;
+        shape->addVertex(point);
+
+        OdDgFillColorLinkagePtr fillColor =
+                OdDgFillColorLinkage::createObject();
+        OdUInt32 nIdx = OdDgColorTable::getColorIndexByRGB(
+            shape->database(), ODRGB( 200, 255, 150 ) );
+        fillColor->setColorIndex( nIdx );
+        shape->addLinkage( fillColor->getPrimaryId(),
+                           fillColor.get() );
+    }
+
+    // Polygon 3D
+    {
+        OdDgShape3dPtr shape = OdDgShape3d::createObject();
+        pModel->addElement(shape);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 0;
+        point.z = 1;
+        shape->addVertex(point);
+        point.x = 0;
+        point.y = 1;
+        shape->addVertex(point);
+        point.x = 1;
+        point.y = 1;
+        shape->addVertex(point);
+        point.x = 0;
+        point.y = 0;
+        shape->addVertex(point);
+    }
+
+    // Polygon 2D with hole
+    {
+        OdDgCellHeader2dPtr pCell = OdDgCellHeader2d::createObject(); 
+        pModel->addElement(pCell);
+
+        OdDgShape2dPtr shape = OdDgShape2d::createObject();
+        pCell->add(shape);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 0;
+        shape->addVertex(point);
+        point.x = 0;
+        point.y = 1;
+        shape->addVertex(point);
+        point.x = 1;
+        point.y = 1;
+        shape->addVertex(point);
+        point.x = 0;
+        point.y = 0;
+        shape->addVertex(point);
+
+        shape = OdDgShape2d::createObject();
+        shape->setHbitFlag(true);
+        pCell->add(shape);
+        point.x = 0.1;
+        point.y = 0.1;
+        shape->addVertex(point);
+        point.x = 0.1;
+        point.y = 0.9;
+        shape->addVertex(point);
+        point.x = 0.9;
+        point.y = 0.9;
+        shape->addVertex(point);
+        point.x = 0.1;
+        point.y = 0.1;
+        shape->addVertex(point);
+    }
+
+    // Polygon 3D with hole
+    {
+        OdDgCellHeader3dPtr pCell = OdDgCellHeader3d::createObject(); 
+        pModel->addElement(pCell);
+
+        OdDgShape3dPtr shape = OdDgShape3d::createObject();
+        pCell->add(shape);
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 0;
+        point.z = 1;
+        shape->addVertex(point);
+        point.x = 0;
+        point.y = 1;
+        shape->addVertex(point);
+        point.x = 1;
+        point.y = 1;
+        shape->addVertex(point);
+        point.x = 0;
+        point.y = 0;
+        shape->addVertex(point);
+
+        shape = OdDgShape3d::createObject();
+        shape->setHbitFlag(true);
+        pCell->add(shape);
+        point.x = 0.1;
+        point.y = 0.1;
+        shape->addVertex(point);
+        point.x = 0.1;
+        point.y = 0.9;
+        shape->addVertex(point);
+        point.x = 0.9;
+        point.y = 0.9;
+        shape->addVertex(point);
+        point.x = 0.1;
+        point.y = 0.1;
+        shape->addVertex(point);
+    }
+
+    // ComplexShape
+    {
+        OdDgComplexShapePtr complex = OdDgComplexShape::createObject();
+        pModel->addElement(complex);
+
+        OdDgLine2dPtr line = OdDgLine2d::createObject();
+        complex->add(line);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 0;
+        line->setStartPoint(point);
+        point.x = 0;
+        point.y = 1;
+        line->setEndPoint(point);
+
+        line = OdDgLine2d::createObject();
+        complex->add(line);
+        point.x = 1;
+        point.y = 1;
+        line->setStartPoint(point);
+        point.x = 1;
+        point.y = 0;
+        line->setEndPoint(point);
+
+        line = OdDgLine2d::createObject();
+        complex->add(line);
+        point.x = 1;
+        point.y = 0;
+        line->setStartPoint(point);
+        point.x = 0;
+        point.y = 0;
+        line->setEndPoint(point);
+    }
+
+    // ComplexShape
+    {
+        OdDgComplexShapePtr complex = OdDgComplexShape::createObject();
+        pModel->addElement(complex);
+
+        OdDgLine2dPtr line = OdDgLine2d::createObject();
+        complex->add(line);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 0;
+        line->setStartPoint(point);
+        point.x = 0;
+        point.y = 1;
+        line->setEndPoint(point);
+
+        OdDgArc2dPtr arc = OdDgArc2d::createObject();
+        complex->add(arc);
+        arc->setPrimaryAxis(0.5);
+        arc->setSecondaryAxis(0.5);
+        point.x = 0.5;
+        point.y = 1;
+        arc->setOrigin(point);
+        arc->setStartAngle(180 * DEG_TO_RAD);
+        arc->setSweepAngle(-180 * DEG_TO_RAD);
+
+        line = OdDgLine2d::createObject();
+        complex->add(line);
+        point.x = 1;
+        point.y = 1;
+        line->setStartPoint(point);
+        point.x = 0;
+        point.y = 0;
+        line->setEndPoint(point);
+    }
+
+    // ComplexShape (out of order rings, we handle that, not sure this is legal though)
+    {
+        OdDgComplexShapePtr complex = OdDgComplexShape::createObject();
+        pModel->addElement(complex);
+
+        OdDgLine2dPtr line = OdDgLine2d::createObject();
+        complex->add(line);
+        OdGePoint2d point;
+        point.x = 0;
+        point.y = 0;
+        line->setStartPoint(point);
+        point.x = 0;
+        point.y = 1;
+        line->setEndPoint(point);
+
+        line = OdDgLine2d::createObject();
+        complex->add(line);
+        point.x = 1;
+        point.y = 0;
+        line->setStartPoint(point);
+        point.x = 0;
+        point.y = 0;
+        line->setEndPoint(point);
+
+        line = OdDgLine2d::createObject();
+        complex->add(line);
+        point.x = 1;
+        point.y = 1;
+        line->setStartPoint(point);
+        point.x = 1;
+        point.y = 0;
+        line->setEndPoint(point);
+    }
+
+    //create a definition and reference
+    {
+        OdDgSharedCellDefinitionPtr definition;
+        OdDgSharedCellDefinitionTablePtr table = pDb->getSharedCellDefinitionTable(OdDg::kForWrite);
+
+        definition = OdDgSharedCellDefinition::createObject();
+        definition->setName( "Named definition" );
+        table->add( definition );
+
+        OdDgEllipse3dPtr ellipse;
+        ellipse = OdDgEllipse3d::createObject();
+        ellipse->setPrimaryAxis( 1. );
+        ellipse->setSecondaryAxis( 1. );
+        definition->add( ellipse );
+
+        OdDgSharedCellReferencePtr reference;
+  
+        reference = OdDgSharedCellReference::createObject();
+        reference->setDefinitionName( "Named definition" );
+        OdGePoint3d point;
+        point.x = 0;
+        point.y = 1;
+        point.z = 2;
+        reference->setOrigin( point );
+        pModel->addElement( reference );
+    }
+
+    // Unhandled element.
+    {
+        OdDgTagElementPtr tag = OdDgTagElement::createObject();
+        pModel->addElement( tag );
+    }
+
+    pModel->fitToView();
+    pDb->writeFile( "test_dgnv8.dgn" );
+    pDb = NULL;
+
+    ::odrxUninitialize();
+
+    return 0;
+}
diff --git a/ogr/ogrsf_frmts/dwg/createdgnv8testfile_headers.h b/ogr/ogrsf_frmts/dwg/createdgnv8testfile_headers.h
new file mode 100644
index 0000000..2ef09cb
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/createdgnv8testfile_headers.h
@@ -0,0 +1,76 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Generate a test .dgn file
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#define HAVE_GCC_SYSTEM_HEADER
+#endif
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#include "OdaCommon.h"
+
+#include "StaticRxObject.h"
+#include "RxInit.h"
+#include "RxDynamicModule.h"
+#include "DynamicLinker.h"
+#include "DgDatabase.h"
+#include "RxDynamicModule.h"
+
+#include "DgGraphicsElement.h"
+#include "DgComplexCurve.h"
+
+#include "ExDgnServices.h"
+#include "ExDgnHostAppServices.h"
+
+#include "Ge/GeKnotVector.h"
+
+#include "DgArc.h"
+#include "DgAttributeLinkage.h"
+#include "DgBSplineCurve.h"
+#include "DgCellHeader.h"
+#include "DgColorTable.h"
+#include "DgComplexCurve.h"
+#include "DgComplexShape.h"
+#include "DgComplexString.h"
+#include "DgCurve.h"
+#include "DgCurveElement2d.h"
+#include "DgCurveElement3d.h"
+#include "DgElementIterator.h"
+#include "DgEllipse.h"
+#include "DgFontTableRecord.h"
+#include "DgLine.h"
+#include "DgLineString.h"
+#include "DgMultiline.h"
+#include "DgPointString.h"
+#include "DgShape.h"
+#include "DgSharedCellReference.h"
+#include "DgText.h"
+#include "DgTextNode.h"
+#include "DgTagElement.h"
diff --git a/ogr/ogrsf_frmts/dwg/dgnv8_headers.h b/ogr/ogrsf_frmts/dwg/dgnv8_headers.h
new file mode 100644
index 0000000..28e2161
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/dgnv8_headers.h
@@ -0,0 +1,79 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  OGR Driver for DGNv8
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef DGNV8_HEADERS_H
+#define DGNV8_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#include "OdaCommon.h"
+
+#include "StaticRxObject.h"
+#include "RxInit.h"
+#include "RxDynamicModule.h"
+#include "DynamicLinker.h"
+#include "DgDatabase.h"
+#include "RxDynamicModule.h"
+
+#include "DgGraphicsElement.h"
+#include "DgComplexCurve.h"
+
+#include "ExDgnServices.h"
+#include "ExDgnHostAppServices.h"
+
+#include "DgSummaryInfo.h"
+#include "Gs/GsBaseInclude.h"
+
+#include "DgArc.h"
+#include "DgAttributeLinkage.h"
+#include "DgBSplineCurve.h"
+#include "DgCellHeader.h"
+#include "DgColorTable.h"
+#include "DgComplexCurve.h"
+#include "DgComplexShape.h"
+#include "DgComplexString.h"
+#include "DgCurve.h"
+#include "DgCurveElement2d.h"
+#include "DgCurveElement3d.h"
+#include "DgElementIterator.h"
+#include "DgEllipse.h"
+#include "DgFontTableRecord.h"
+#include "DgLine.h"
+#include "DgLineString.h"
+#include "DgMultiline.h"
+#include "DgPointString.h"
+#include "DgShape.h"
+#include "DgSharedCellReference.h"
+#include "DgText.h"
+#include "DgTextNode.h"
+
+#endif // DGNV8_HEADERS_H
diff --git a/ogr/ogrsf_frmts/dwg/drv_dgnv8.html b/ogr/ogrsf_frmts/dwg/drv_dgnv8.html
new file mode 100644
index 0000000..206aa99
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/drv_dgnv8.html
@@ -0,0 +1,179 @@
+<html>
+<head>
+<title>Microstation DGN v8</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>Microstation DGN v8</h1>
+
+Available since GDAL 2.2<p>
+
+Microstation DGN files from Microstation version 8.0
+are supported for reading and writing. Each model of the file is
+represented by a OGR layer.<p>
+
+This driver requires to be built against the (non open source)
+Open Design Alliance Teiga library.<p>
+
+DGN files are considered to have no georeferencing information through OGR.
+Features will all have the following generic attributes:
+
+<ul>
+<li> Type: The integer type code as listed below in supported elements.
+<li> Level: The DGN level number.
+<li> GraphicGroup: The graphic group number.
+<li> ColorIndex: The color index from the dgn palette.
+<li> Weight: The drawing weight (thickness) for the element.
+<li> Style: The style value for the element.
+</ul>
+
+<h2>Supported Elements</h2>
+
+The following element types are supported in reading:<p>
+
+<ul>
+<li> Cell Header (2): used for polygons with holes
+<li> Line (3): Line (2 points) geometry.
+<li> Line String (4): Multi segment line geometry.
+<li> Shape (6): Polygon geometry.
+<li> TextNode (7): Container of Text elements.
+<li> Curve (11): Approximated as a line geometry.
+<li> ComplexString (12): Treated as line string or compound curve.
+<li> ComplexShape (14): Treated as polygon or curve polygon.
+<li> Ellipse (15): Approximated as a line geometry or a circular string.
+<li> Arc (16): Approximated as a line geometry or a circular string.
+<li> Text (17): Treated as a point geometry.
+<li> B-Spline (21): Treated as a line geometry.
+<li> PointString (22): Treatead as multi point.
+<li> Shared cell reference (35): Treated as point.
+</ul>
+
+Generally speaking any concept of complex objects, and cells as associated
+components is lost.  Each component of a complex object or cell is treated
+as a independent feature.<p>
+
+<h2>Styling Information</h2>
+
+Some drawing information about features can be extracted from the ColorIndex,
+Weight and Style generic attributes; however, for all features an OGR
+style string has been prepared with the values encoded in ready-to-use form
+for applications supporting OGR style strings.<p>
+
+The various kinds of linear geometries will carry style information indicating
+the color, thickness and line style (i.e. dotted, solid, etc).<p>
+
+Polygons (Shape elements) will carry styling information for the edge as well
+as a fill color if provided.  Fill patterns are not supported.<p>
+
+Text elements will contain the text, angle, color and size information
+(expressed in ground units) in the style string.<p>
+
+<h2>Metadata</h2>
+
+The various metadata items that can be set in the DGN header with the dataset
+creation options (see below) can be retrieved in the "DGN" metadata domain.
+
+<h2>Creation Issues</h2>
+
+DGN files may be written with OGR with  limitations:<P>
+
+<ul>
+<li> Output features have the usual fixed DGN attributes.  Attempts to create
+any other fields will fail.<p>
+
+<li> Translation from OGR feature style strings back into DGN representation information
+is limited to a few properties of LABEL (text, font name, size, angle, color), PEN (color)
+and BRUSH (fill color) tools. <p>
+
+<li> POINT geometries that are not text (Text is NULL, and the feature
+style string is not a LABEL) will be translated as a degenerate (0 length)
+line element. <p>
+
+<li> Geometries which fall outside the "design plane" of the seed file will
+be discarded, or corrupted in unpredictable ways.<p>
+
+</ul>
+
+The dataset creation supports the following options:<p>
+
+<ul>
+
+<li> <b>SEED=</b><i>filename</i>: Specify the seed file to use.<p>
+
+<li> <b>COPY_SEED_FILE_COLOR_TABLE=</b><i>YES/NO</i>: Indicates whether the
+color table should be copied from the seed file.
+Only taken into account if SEED is specified.
+By default this is NO. <p>
+
+<li> <b>COPY_SEED_FILE_MODEL=</b><i>YES/NO</i>: Indicates whether the
+existing models (without their graphic contents) should be copied from the seed file.
+This holds as well for the view groups and named views to which they are linked to.
+Only taken into account if SEED is specified.
+By default this is YES. <p>
+
+<li> <b>COPY_SEED_FILE_MODEL_CONTROL_ELEMENTS=</b><i>YES/NO</i>: Indicates whether the
+existing control elements of models should be copied from the seed file.
+Only taken into account if COPY_SEED_FILE_MODEL=YES.
+By default this is YES. <p>
+
+<li> <b>APPLICATION=</b><i>string</i>: Set Application field in header. If not specified,
+derived from seed file when set. Otherwise mentions the version of GDAL and the Teigha
+library used.<p>
+
+<li> <b>TITLE=</b><i>string</i>: Set Title field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>SUBJECT=</b><i>string</i>: Set Subject field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>AUTHOR=</b><i>string</i>: Set Author field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>KEYWORDS=</b><i>string</i>: Set Keywords field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>TEMPLATE=</b><i>string</i>: Set Template field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>COMMENTS=</b><i>string</i>: Set Comments field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>LAST_SAVED_BY=</b><i>string</i>: Set LastSavedBy field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>REVISION_NUMBER=</b><i>string</i>: Set RevisionNumber field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>CATEGORY=</b><i>string</i>: Set Category field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>MANAGER=</b><i>string</i>: Set Manager field in header. If not specified,
+from the seed file.<p>
+
+<li> <b>COMPANY=</b><i>string</i>: Set Company field in header. If not specified,
+from the seed file.<p>
+
+</ul>
+
+The layer creation supports the following options:<p>
+
+<ul>
+
+<li> <b>DESCRIPTION=</b><i>string</i>: Description associated with the layer.
+If not specified, from the seed file.<p>
+
+<li> <b>DIM=</b><i>2/3</i>: Dimension (ie 2D vs 3D) of the layer. By default, 3,
+unless the model is reused from the seed file.<p>
+
+</ul>
+
+<hr>
+
+<ul>
+<li> <a href="drv_dgn.html">DGN (v7) driver</a>
+<li> <a href="http://gdal.org/ogr_feature_style.html">OGR Feature Style Specification</a>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/dwg/dwg_headers.h b/ogr/ogrsf_frmts/dwg/dwg_headers.h
new file mode 100644
index 0000000..dc05d47
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/dwg_headers.h
@@ -0,0 +1,90 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes Teigha headers
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2011,  Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef TEIGHA_HEADERS_H
+#define TEIGHA_HEADERS_H
+
+#include "cpl_port.h"
+
+#ifdef HAVE_GCC_SYSTEM_HEADER
+#pragma GCC system_header
+#endif
+
+#include "OdaCommon.h"
+#include "diagnostics.h"
+#include "DbDatabase.h"
+#include "DbEntity.h"
+#include "DbDimAssoc.h"
+#include "DbObjectIterator.h"
+#include "DbBlockTable.h"
+#include "DbBlockTableRecord.h"
+#include "DbSymbolTable.h"
+
+#include "DbLayerTable.h"
+#include "DbLayerTableRecord.h"
+#include "DbLinetypeTable.h"
+#include "DbLinetypeTableRecord.h"
+
+#include "DbPolyline.h"
+#include "Db2dPolyline.h"
+#include "Db3dPolyline.h"
+#include "Db3dPolylineVertex.h"
+#include "DbLine.h"
+#include "DbPoint.h"
+#include "DbEllipse.h"
+#include "DbArc.h"
+#include "DbMText.h"
+#include "DbText.h"
+#include "DbCircle.h"
+#include "DbSpline.h"
+#include "DbBlockReference.h"
+#include "DbAttribute.h"
+#include "DbFiler.h"
+#include "Ge/GeScale3d.h"
+
+#include "DbDimension.h"
+#include "DbRotatedDimension.h"
+#include "DbAlignedDimension.h"
+
+#include "DbHatch.h"
+#include "Ge/GePoint2dArray.h"
+#include "Ge/GeCurve2d.h"
+#include "Ge/GeCircArc2d.h"
+#include "Ge/GeEllipArc2d.h"
+
+
+#include "OdCharMapper.h"
+#include "RxObjectImpl.h"
+
+#include "ExSystemServices.h"
+#include "ExHostAppServices.h"
+#include "OdFileBuf.h"
+#include "RxDynamicModule.h"
+#include "FdField.h"
+
+#endif // TEIGHA_HEADERS_H
diff --git a/ogr/ogrsf_frmts/dwg/makefile.vc b/ogr/ogrsf_frmts/dwg/makefile.vc
index b1fba61..7c7c354 100644
--- a/ogr/ogrsf_frmts/dwg/makefile.vc
+++ b/ogr/ogrsf_frmts/dwg/makefile.vc
@@ -6,43 +6,20 @@ OBJ =	\
     ogrdwgblockslayer.obj \
     ogrdwg_blockmap.obj \
     ogrdwg_dimension.obj \
-    ogrdwg_hatch.obj 
+    ogrdwg_hatch.obj \
+    ogrdgnv8driver.obj \
+    ogrdgnv8datasource.obj \
+    ogrdgnv8layer.obj \
+    ogrteigha.obj
 
-DXF_OBJ = ..\dxf\intronurbs.obj ..\dxf\ogrdxf_polyline_smooth.obj 
+DXF_OBJ = ..\dxf\intronurbs.obj ..\dxf\ogrdxf_polyline_smooth.obj  ..\dxf\ogr_autocad_services.obj
 
-PLUGIN_DLL = ogr_DWG.dll
+PLUGIN_DLL = ogr_DWG_DGNV8.dll
 
 GDAL_ROOT	=	..\..\..
 
-TD_LIBS =  \
-	$(TD_LIBDIR)/TD_ExamplesCommon.lib \
-	$(TD_LIBDIR)/TD_Key.lib \
-	$(TD_LIBDIR)/ModelerGeometry.lib \
-	$(TD_LIBDIR)/TD_BrepRenderer.lib \
-	$(TD_LIBDIR)/TD_Br.lib \
-	$(TD_LIBDIR)/TD_AcisBuilder.lib \
-	$(TD_LIBDIR)/TD_DynBlocks.lib \
-	$(TD_LIBDIR)/TD_Db.lib \
-	$(TD_LIBDIR)/TD_DbRoot.lib \
-	$(TD_LIBDIR)/TD_Gs.lib \
-	$(TD_LIBDIR)/TD_SpatialIndex.lib \
-	$(TD_LIBDIR)/TD_Ave.lib \
-	$(TD_LIBDIR)/TD_Root.lib \
-	$(TD_LIBDIR)/TD_Gi.lib \
-	$(TD_LIBDIR)/TD_Ge.lib \
-	$(TD_LIBDIR)/TD_FT.lib \
-	$(TD_LIBDIR)/TD_Alloc.lib \
-	$(TD_LIBDIR)/RxRasterServices.lib \
-	$(TD_LIBDIR)/Jpeg.lib \
-	$(TD_LIBDIR)/RecomputeDimBlock.lib \
-	$(TD_LIBDIR)/ExFieldEvaluator.lib \
-	$(TD_LIBDIR)/OdBagFiler.lib \
-	$(TD_LIBDIR)/RasterProcessor.lib \
-	advapi32.lib
-
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-
 EXTRAFLAGS = -I.. -I..\.. $(TD_FLAGS) $(TD_INCLUDE) -I..\dxf
 
 default:	$(OBJ)
@@ -63,3 +40,8 @@ $(PLUGIN_DLL):	$(OBJ)
 plugin-install:
 	-mkdir $(PLUGINDIR)
 	$(INSTALL) $(PLUGIN_DLL) $(PLUGINDIR)
+
+createdgnv8testfile.exe: createdgnv8testfile.obj
+	cl /Zi createdgnv8testfile.obj $(TD_LIBS)
+
+
diff --git a/ogr/ogrsf_frmts/dwg/ogr_dgnv8.h b/ogr/ogrsf_frmts/dwg/ogr_dgnv8.h
new file mode 100644
index 0000000..ae9acf5
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogr_dgnv8.h
@@ -0,0 +1,171 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  OGR Driver for DGNv8
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_DGNV8_H_INCLUDED
+#define OGR_DGNV8_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "dgnv8_headers.h"
+
+/************************************************************************/
+/*                         OGRDGNV8Services                             */
+/*                                                                      */
+/*      Services implementation for OGR.  Eventually we should          */
+/*      override the OdExDgnSystemServices IO to use VSI*L.             */
+/************************************************************************/
+
+class OGRDGNV8Services : public OdExDgnSystemServices,
+                         public OdExDgnHostAppServices
+{
+protected:
+  ODRX_USING_HEAP_OPERATORS(OdExDgnSystemServices);
+};
+
+/************************************************************************/
+/*                           OGRDGNV8Layer                              */
+/************************************************************************/
+
+class OGRDGNV8DataSource;
+typedef std::pair<OGRFeature*, bool> tPairFeatureHoleFlag;
+
+class OGRDGNV8Layer : public OGRLayer
+{
+    friend class OGRDGNV8DataSource;
+
+    OGRDGNV8DataSource         *m_poDS;
+    OGRFeatureDefn             *m_poFeatureDefn;
+    OdDgModelPtr                m_pModel;
+    OdDgElementIteratorPtr      m_pIterator;
+    std::vector<tPairFeatureHoleFlag>    m_aoPendingFeatures;
+    size_t                      m_nIdxInPendingFeatures;
+    std::set<CPLString>         m_aoSetIgnoredFeatureClasses;
+
+    void                                 CleanPendingFeatures();
+    std::vector<tPairFeatureHoleFlag>    CollectSubElements( OdDgElementIteratorPtr iterator,
+                                                    int level );
+    std::vector<tPairFeatureHoleFlag>    ProcessElement(OdDgGraphicsElementPtr element,
+                                               int level = 0);
+    OGRFeature*                 GetNextUnfilteredFeature();
+
+    void                        AddToComplexCurve( OGRFeature* poFeature,
+                                                   OGRCircularString* poCS,
+                                                   OdDgComplexCurvePtr complexCurve );    
+    void                        AddToComplexCurve( OGRFeature* poFeature,
+                                                   OGRCompoundCurve* poCC,
+                                                   OdDgComplexCurvePtr complexCurve );
+    OdDgGraphicsElementPtr      CreateShape( OGRFeature* poFeature,
+                                             OGRCurve* poCurve,
+                                             bool bIsHole = false );
+    OdDgGraphicsElementPtr      CreateGraphicsElement( OGRFeature *poFeature,
+                                                       OGRGeometry *poGeom );
+    OdDgGraphicsElementPtr      TranslateLabel(
+                                    OGRFeature *poFeature, OGRPoint *poPoint );
+    void                        AttachFillLinkage( OGRFeature* poFeature,
+                                                   OdDgGraphicsElementPtr element);
+    void                        AttachCommonAttributes( OGRFeature *poFeature,
+                                                        OdDgGraphicsElementPtr element );
+    int                         GetColorFromString(const char* pszColor);
+    OdDgGraphicsElementPtr      GetFeatureInternal(GIntBig nFID, OdDg::OpenMode openMode);
+
+  public:
+                        OGRDGNV8Layer( OGRDGNV8DataSource* poDS,
+                                       OdDgModelPtr pModel );
+                        virtual ~OGRDGNV8Layer();
+
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    OGRFeature *        GetFeature(GIntBig nFID) override;
+    OGRErr              GetExtent( OGREnvelope *psExtent, int bForce ) override;
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent,
+                                   int bForce ) override
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+
+    OGRFeatureDefn *    GetLayerDefn() override { return m_poFeatureDefn; }
+
+    int                 TestCapability( const char * ) override;
+
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
+    OGRErr              DeleteFeature(GIntBig nFID) override;
+};
+
+
+/************************************************************************/
+/*                         OGRDGNV8DataSource                           */
+/************************************************************************/
+
+class OGRDGNV8DataSource : public GDALDataset
+{
+    OGRDGNV8Services   *m_poServices;
+    OGRDGNV8Layer     **m_papoLayers;
+    int                 m_nLayers;
+    char              **m_papszOptions;
+    OdDgDatabasePtr     m_poDb;
+    bool                m_bUpdate;
+    bool                m_bModified;
+    CPLStringList       m_osDGNMD;
+
+    void                InitWithSeed();
+
+  public:
+                        explicit OGRDGNV8DataSource(OGRDGNV8Services* poServices);
+                        ~OGRDGNV8DataSource();
+
+    int                 Open( const char *, bool bUpdate );
+    bool                PreCreate( const char *, char ** );
+
+    OGRLayer           *ICreateLayer( const char *,
+                                     OGRSpatialReference * = NULL,
+                                     OGRwkbGeometryType = wkbUnknown,
+                                     char ** = NULL ) override;
+
+    int                 GetLayerCount() override { return m_nLayers; }
+    OGRLayer            *GetLayer( int ) override;
+
+    int                 TestCapability( const char * ) override;
+    virtual void        FlushCache() override;
+
+    virtual char **     GetMetadataDomainList() override;
+    virtual char**      GetMetadata(const char* pszDomain = "") override;
+    virtual const char* GetMetadataItem(const char* pszName,
+                                        const char* pszDomain = "") override;
+
+    OdDgDatabasePtr     GetDb() const { return m_poDb; }
+
+    bool                GetUpdate() const { return m_bUpdate; }
+    void                SetModified() { m_bModified = true; }
+
+    static OdString     FromUTF8(const CPLString& str);
+    static CPLString    ToUTF8(const OdString& str);
+};
+
+#endif /* ndef OGR_DGNV8_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dwg/ogr_dwg.h b/ogr/ogrsf_frmts/dwg/ogr_dwg.h
index 4dd3305..7a6d19f 100644
--- a/ogr/ogrsf_frmts/dwg/ogr_dwg.h
+++ b/ogr/ogrsf_frmts/dwg/ogr_dwg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_dxf.h 22008 2011-03-22 19:45:20Z warmerdam $
+ * $Id: ogr_dwg.h 37969 2017-04-12 07:56:18Z rouault $
  *
  * Project:  DWG Translator
  * Purpose:  Definition of classes for OGR .dwg driver.
@@ -38,25 +38,7 @@
 #include <queue>
 
 #include "ogr_autocad_services.h"
-
-#include "OdaCommon.h"
-#include "diagnostics.h"
-#include "DbDatabase.h"
-#include "DbEntity.h"
-#include "DbDimAssoc.h"
-#include "DbObjectIterator.h"
-#include "DbBlockTable.h"
-#include "DbBlockTableRecord.h"
-#include "DbSymbolTable.h"
-
-#include "OdCharMapper.h"
-#include "RxObjectImpl.h"
-
-#include "ExSystemServices.h"
-#include "ExHostAppServices.h"
-#include "OdFileBuf.h"
-#include "RxDynamicModule.h"
-#include "FdField.h"
+#include "dwg_headers.h"
 
 class OGRDWGDataSource;
 class OGRDWGServices;
@@ -93,15 +75,15 @@ class OGRDWGBlocksLayer : public OGRLayer
     std::map<CPLString,DWGBlockDefinition>::iterator oIt;
 
   public:
-    OGRDWGBlocksLayer( OGRDWGDataSource *poDS );
+    explicit OGRDWGBlocksLayer( OGRDWGDataSource *poDS );
     ~OGRDWGBlocksLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     OGRFeature *        GetNextUnfilteredFeature();
 };
@@ -147,19 +129,19 @@ class OGRDWGLayer : public OGRLayer
 
     CPLString           TextUnescape( OdString oString);
 
-    OdDbBlockTableRecordPtr poBlock;
+    OdDbBlockTableRecordPtr m_poBlock;
     OdDbObjectIteratorPtr   poEntIter;
 
   public:
-    OGRDWGLayer( OGRDWGDataSource *poDS );
+    explicit OGRDWGLayer( OGRDWGDataSource *poDS );
     ~OGRDWGLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     OGRFeature *        GetNextUnfilteredFeature();
 
@@ -176,7 +158,7 @@ class OGRDWGDataSource : public OGRDataSource
 {
     VSILFILE           *fp;
 
-    CPLString           osName;
+    CPLString           m_osName;
     std::vector<OGRLayer*> apoLayers;
 
     int                 iEntitiesSectionOffset;
@@ -206,12 +188,12 @@ class OGRDWGDataSource : public OGRDataSource
     int                 Open( OGRDWGServices *poServices,
                               const char * pszFilename, int bHeaderOnly=FALSE );
 
-    const char          *GetName() { return osName; }
+    const char          *GetName() override { return m_osName; }
 
-    int                 GetLayerCount() { return apoLayers.size(); }
-    OGRLayer            *GetLayer( int );
+    int                 GetLayerCount() override { return static_cast<int>(apoLayers.size()); }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     // The following is only used by OGRDWGLayer
 
@@ -257,23 +239,17 @@ protected:
 
 class OGRDWGDriver : public OGRSFDriver
 {
-    int     bInitialized;
-    void    Initialize();
-
-    OdStaticRxObject<OGRDWGServices> oServices;
-
-    static void ErrorHandler( OdResult oRes );
+    OGRDWGServices *poServices;
 
   public:
     OGRDWGDriver();
     ~OGRDWGDriver();
 
-    OGRDWGServices *GetServices() { return &oServices; }
+    OGRDWGServices *GetServices() { return poServices; }
 
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
-    int         TestCapability( const char * );
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
+    int         TestCapability( const char * ) override;
 };
 
-
 #endif /* ndef OGR_DWG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/dwg/ogrdgnv8datasource.cpp b/ogr/ogrsf_frmts/dwg/ogrdgnv8datasource.cpp
new file mode 100644
index 0000000..7769c6e
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdgnv8datasource.cpp
@@ -0,0 +1,626 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  OGR Driver for DGNv8
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_dgnv8.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogrdgnv8datasource.cpp 37987 2017-04-14 07:42:50Z rouault $");
+
+/************************************************************************/
+/*                        OGRDGNV8DataSource()                          */
+/************************************************************************/
+
+OGRDGNV8DataSource::OGRDGNV8DataSource(OGRDGNV8Services* poServices) :
+    m_poServices(poServices),
+    m_papoLayers(NULL),
+    m_nLayers(0),
+    m_papszOptions(NULL),
+    m_poDb(static_cast<const OdRxObject*>(NULL)),
+    m_bUpdate(false),
+    m_bModified(false)
+{}
+
+/************************************************************************/
+/*                       ~OGRDGNV8DataSource()                          */
+/************************************************************************/
+
+OGRDGNV8DataSource::~OGRDGNV8DataSource()
+
+{
+    FlushCache();
+
+    for( int i = 0; i < m_nLayers; i++ )
+        delete m_papoLayers[i];
+
+    CPLFree( m_papoLayers );
+    CSLDestroy( m_papszOptions );
+}
+
+
+/************************************************************************/
+/*                              FlushCache()                            */
+/************************************************************************/
+
+void OGRDGNV8DataSource::FlushCache()
+{
+    if( m_poDb.isNull() || !m_bModified )
+        return;
+    m_bModified = false;
+
+    for( int i = 0; i < m_nLayers; i++ )
+    {
+       m_papoLayers[i]->m_pModel->fitToView();
+    }
+
+    OdString oFilename( FromUTF8(GetDescription()) );
+    try
+    {
+        m_poDb->writeFile( oFilename );
+    }
+    catch (const OdError& e)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Teigha DGN error occurred: %s",
+                 ToUTF8(e.description()).c_str());
+    }
+    catch (const std::exception &exc)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "std::exception occurred: %s", exc.what());
+    }
+    catch (...)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unknown exception occurred");
+    }
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRDGNV8DataSource::Open( const char * pszFilename, bool bUpdate )
+
+{
+    SetDescription(pszFilename);
+    
+    OdString oFilename( FromUTF8(pszFilename) );
+    try
+    {
+        m_poDb = m_poServices->readFile( oFilename );
+    }
+    catch (const OdError& e)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Teigha DGN error occurred: %s",
+                 ToUTF8(e.description()).c_str());
+        return FALSE;
+    }
+    catch (const std::exception &exc)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "std::exception occurred: %s", exc.what());
+        return FALSE;
+    }
+    catch (...)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unknown exception occurred");
+        return FALSE;
+    }
+
+    OdDgModelTablePtr pModelTable = m_poDb->getModelTable();
+    if (pModelTable.isNull())
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "No model table found");
+        return FALSE;
+    }
+
+    // Loop over models
+    OdDgElementIteratorPtr pIter = pModelTable->createIterator();
+    for ( ; !pIter.isNull() && !pIter->done(); pIter->step() )
+    {
+        OdDgModelPtr pModel = OdDgModel::cast(
+                pIter->item().openObject( 
+                    bUpdate ? OdDg::kForWrite : OdDg::kForRead ) );
+        if ( !pModel.isNull() )
+        {
+            OGRDGNV8Layer* poLayer = new OGRDGNV8Layer(this, pModel);
+            m_papoLayers = static_cast<OGRDGNV8Layer**>(
+                    CPLRealloc(m_papoLayers,
+                               sizeof(OGRDGNV8Layer*) * (m_nLayers + 1)));
+            m_papoLayers[ m_nLayers++ ] = poLayer;
+        }
+    }
+
+    m_bUpdate = bUpdate;
+
+    return m_bUpdate || m_nLayers > 0;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDGNV8DataSource::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,ODsCCreateLayer) )
+        return m_bUpdate;
+    else if( EQUAL(pszCap,ODsCCurveGeometries) )
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRDGNV8DataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= m_nLayers )
+        return NULL;
+
+    return m_papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                         EraseSubElements()                           */
+/************************************************************************/
+
+template<class T> static void EraseSubElements(T container)
+{
+    if( !container.isNull() )
+    {
+        OdDgElementIteratorPtr pIter = container->createIterator();
+        for(; !pIter.isNull() && !pIter->done(); pIter->step() )
+        {
+            OdDgElementPtr pElement =
+                pIter->item().openObject(OdDg::kForWrite);
+            if( !pElement.isNull() )
+            {
+                pElement->erase(true);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                          InitWithSeed()                              */
+/************************************************************************/
+
+void OGRDGNV8DataSource::InitWithSeed()
+{
+#if 0
+    EraseSubElements(m_poDb->getLevelTable(OdDg::kForWrite));
+#endif
+
+    if( !CPLTestBool(CSLFetchNameValueDef(
+            m_papszOptions, "COPY_SEED_FILE_COLOR_TABLE", "NO")) )
+    {
+        OdDgColorTablePtr colorTable = m_poDb->getColorTable(OdDg::kForWrite);
+        if( !colorTable.isNull() )
+        {
+            const ODCOLORREF* defColors = OdDgColorTable::defaultPalette();
+            OdArray<ODCOLORREF> palette;
+            palette.insert(palette.begin(), defColors, defColors + 256);
+            colorTable->setPalette(palette);
+        }
+    }
+    
+    OdDgModelTablePtr pModelTable = m_poDb->getModelTable();
+
+    if( CPLTestBool(CSLFetchNameValueDef(
+            m_papszOptions, "COPY_SEED_FILE_MODEL", "YES")) )
+    {
+        if( !pModelTable.isNull() )
+        {
+            OdDgElementIteratorPtr pIter = pModelTable->createIterator();
+            for(; !pIter.isNull() && !pIter->done(); pIter->step() )
+            {
+                OdDgModelPtr pModel = OdDgModel::cast(
+                    pIter->item().openObject( OdDg::kForWrite ) );
+                if( !pModel.isNull() )
+                {
+                    OdDgElementIteratorPtr pIter2 =
+                        pModel->createGraphicsElementsIterator();
+                    for(; !pIter2.isNull() && !pIter2->done(); pIter2->step() )
+                    {
+                        OdDgElementPtr pElement =
+                            pIter2->item().openObject(OdDg::kForWrite);
+                        if( !pElement.isNull() )
+                        {
+                            pElement->erase(true);
+                        }
+                    }
+
+                    if( !CPLTestBool(CSLFetchNameValueDef(
+                            m_papszOptions,
+                            "COPY_SEED_FILE_MODEL_CONTROL_ELEMENTS", "YES")) )
+                    {
+                        pIter2 =
+                            pModel->createControlElementsIterator();
+                        for(; !pIter2.isNull() && !pIter2->done();
+                            pIter2->step() )
+                        {
+                            OdDgElementPtr pElement =
+                                pIter2->item().openObject(OdDg::kForWrite);
+                            if( !pElement.isNull() )
+                            {
+                                pElement->erase(true);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        // Erase existing models
+        EraseSubElements(pModelTable);
+
+        // Recreate a new model and bind it as default
+        OdDgModelPtr model = OdDgModel::createObject();
+        pModelTable->add( model );
+        
+        m_poDb->setActiveModelId( model->elementId() );
+        m_poDb->setDefaultModelId( model->elementId() );
+
+        // Erase existing views
+        EraseSubElements(m_poDb->getNamedViewTable());
+        OdDgViewGroupTablePtr pViewGroupTable = m_poDb->getViewGroupTable();
+        EraseSubElements(pViewGroupTable);
+
+        // Recreate a new view group and bind it as default
+        model->createViewGroup();
+
+        OdDgElementIteratorPtr pIter = pViewGroupTable->createIterator();
+        m_poDb->setActiveViewGroupId(pIter->item());
+    }
+
+#if 0
+    CPLString osTmpFile(CPLString(GetDescription()) + ".tmp");
+    OdString odTmpFile( FromUTF8( osTmpFile ) );
+    m_poDb->writeFile( odTmpFile );
+    m_poDb = m_poServices->readFile( odTmpFile );
+    VSIUnlink(osTmpFile);
+#endif
+}
+
+/************************************************************************/
+/*                            FillMD()                                  */
+/************************************************************************/
+
+static void FillMD( CPLStringList& osDGNMD, const char* pszKey, OdString str )
+{
+    CPLString osVal( OGRDGNV8DataSource::ToUTF8(str) );
+    if( !osVal.empty() )
+        osDGNMD.SetNameValue(pszKey, osVal);
+}
+
+/************************************************************************/
+/*                      GetMetadataDomainList()                         */
+/************************************************************************/
+
+char **OGRDGNV8DataSource::GetMetadataDomainList()
+{
+    return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
+                                   TRUE,
+                                   "DGN", NULL);
+}
+
+/************************************************************************/
+/*                          GetMetadata()                              */
+/************************************************************************/
+
+char** OGRDGNV8DataSource::GetMetadata(const char* pszDomain)
+{
+    if( pszDomain != NULL && EQUAL(pszDomain, "DGN") )
+    {
+        m_osDGNMD.Clear();
+        OdDgSummaryInformationPtr summary = oddgGetSummaryInformation(m_poDb);
+        FillMD( m_osDGNMD, "APPLICATION", summary->getApplicationName() );
+        FillMD( m_osDGNMD, "TITLE", summary->getTitle() );
+        FillMD( m_osDGNMD, "SUBJECT", summary->getSubject() );
+        FillMD( m_osDGNMD, "AUTHOR", summary->getAuthor() );
+        FillMD( m_osDGNMD, "KEYWORDS", summary->getKeywords() );
+        FillMD( m_osDGNMD, "TEMPLATE", summary->getTemplate() );
+        FillMD( m_osDGNMD, "COMMENTS", summary->getComments() );
+        FillMD( m_osDGNMD, "LAST_SAVED_BY", summary->getLastSavedBy() );
+        FillMD( m_osDGNMD, "REVISION_NUMBER", summary->getRevisionNumber() );
+        OdDgDocumentSummaryInformationPtr docSummaryInfo =
+                                oddgGetDocumentSummaryInformation(m_poDb);
+        FillMD( m_osDGNMD, "CATEGORY", docSummaryInfo->getCategory() );
+        FillMD( m_osDGNMD, "MANAGER", docSummaryInfo->getManager() );
+        FillMD( m_osDGNMD, "COMPANY", docSummaryInfo->getCompany() );
+        return m_osDGNMD.List();
+    }
+    return GDALDataset::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                        GetMetadataItem()                             */
+/************************************************************************/
+
+const char* OGRDGNV8DataSource::GetMetadataItem(const char* pszName,
+                                                const char* pszDomain)
+{
+    return CSLFetchNameValue( GetMetadata(pszDomain), pszName );
+}
+
+/************************************************************************/
+/*                             PreCreate()                              */
+/*                                                                      */
+/*      Called by OGRDGNV8DriverCreate() method to setup a stub         */
+/*      OGRDataSource object without the associated file created        */
+/*      yet.                                                            */
+/************************************************************************/
+
+bool OGRDGNV8DataSource::PreCreate( const char *pszFilename,
+                                    char **papszOptionsIn )
+
+{
+    m_bUpdate = true;
+    m_bModified = true;
+    m_papszOptions = CSLDuplicate( papszOptionsIn );
+    SetDescription( pszFilename );
+    
+    VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
+    if( fp == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Cannot write %s", pszFilename);
+        return false;
+    }
+    VSIFCloseL(fp);
+    
+    const char* pszSeed = CSLFetchNameValue(m_papszOptions, "SEED");
+    
+    try
+    {
+        if( pszSeed )
+            m_poDb = m_poServices->readFile( FromUTF8(pszSeed) );
+        else
+            m_poDb = m_poServices->createDatabase();
+        
+        if( pszSeed )
+        {
+            InitWithSeed();
+        }
+    }
+    catch (const OdError& e)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Teigha DGN error occurred: %s",
+                 ToUTF8(e.description()).c_str());
+        return false;
+    }
+    catch (const std::exception &exc)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "std::exception occurred: %s", exc.what());
+        return false;
+    }
+    catch (...)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unknown exception occurred");
+        return false;
+    }
+
+    OdDgSummaryInformationPtr summary = oddgGetSummaryInformation(m_poDb);
+    CPLString osDefaultAppName("GDAL ");
+    osDefaultAppName += GDALVersionInfo("RELEASE_NAME");
+    osDefaultAppName += " with " + ToUTF8(summary->getApplicationName());
+    const char* pszAppName = CSLFetchNameValue(m_papszOptions,
+                                                  "APPLICATION");
+    if( pszSeed == NULL && pszAppName == NULL )
+        pszAppName = osDefaultAppName;
+    if( pszAppName )
+        summary->setApplicationName(FromUTF8(pszAppName));
+
+    const char* pszTitle = CSLFetchNameValue(m_papszOptions, "TITLE");
+    if( pszTitle )
+        summary->setTitle(FromUTF8(pszTitle));
+
+    const char* pszSubject = CSLFetchNameValue(m_papszOptions, "SUBJECT");
+    if( pszSubject )
+        summary->setSubject(FromUTF8(pszSubject));
+
+    const char* pszAuthor = CSLFetchNameValue(m_papszOptions, "AUTHOR");
+    if( pszAuthor )
+        summary->setAuthor(FromUTF8(pszAuthor));
+
+    const char* pszKeywords = CSLFetchNameValue(m_papszOptions, "KEYWORDS");
+    if( pszKeywords )
+        summary->setKeywords(FromUTF8(pszKeywords));
+
+    const char* pszTemplate = CSLFetchNameValue(m_papszOptions, "TEMPLATE");
+    if( pszTemplate )
+        summary->setTemplate(FromUTF8(pszTemplate));
+
+    const char* pszComments = CSLFetchNameValue(m_papszOptions, "COMMENTS");
+    if( pszComments )
+        summary->setComments(FromUTF8(pszComments));
+
+    const char* pszLastSavedBy = CSLFetchNameValue(m_papszOptions,
+                                                   "LAST_SAVED_BY");
+    if( pszLastSavedBy )
+        summary->setLastSavedBy(FromUTF8(pszLastSavedBy));
+
+    const char* pszRevisionNumber = CSLFetchNameValue(m_papszOptions,
+                                                      "REVISION_NUMBER");
+    if( pszRevisionNumber )
+        summary->setRevisionNumber(FromUTF8(pszRevisionNumber));
+
+    OdDgDocumentSummaryInformationPtr docSummaryInfo =
+        oddgGetDocumentSummaryInformation(m_poDb);
+
+    const char* pszCategory = CSLFetchNameValue(m_papszOptions, "CATEGORY");
+    if( pszCategory )
+        docSummaryInfo->setCategory(FromUTF8(pszCategory));
+
+    const char* pszManager = CSLFetchNameValue(m_papszOptions, "MANAGER");
+    if( pszManager )
+        docSummaryInfo->setManager(FromUTF8(pszManager));
+
+    const char* pszCompany = CSLFetchNameValue(m_papszOptions, "COMPANY");
+    if( pszCompany )
+        docSummaryInfo->setCompany(FromUTF8(pszCompany));
+
+    return true;
+}
+
+/************************************************************************/
+/*                             ToUTF8()                                 */
+/************************************************************************/
+
+CPLString OGRDGNV8DataSource::ToUTF8(const OdString& str)
+{
+    CPL_STATIC_ASSERT( sizeof(OdChar) == sizeof(wchar_t) );
+    char* pszUTF8 = CPLRecodeFromWChar(
+        reinterpret_cast<const wchar_t*>(str.c_str()),
+        "WCHAR_T",
+        CPL_ENC_UTF8);
+    CPLString osRet(pszUTF8);
+    CPLFree(pszUTF8);
+    return osRet;    
+}
+
+/************************************************************************/
+/*                            FromUTF8()                                */
+/************************************************************************/
+
+OdString OGRDGNV8DataSource::FromUTF8(const CPLString& str)
+{
+    CPL_STATIC_ASSERT( sizeof(OdChar) == sizeof(wchar_t) );
+    OdChar* pwszWide = reinterpret_cast<OdChar*>(CPLRecodeToWChar(
+        str.c_str(),
+        CPL_ENC_UTF8,
+        "WCHAR_T"));
+    OdString osRet(pwszWide);
+    CPLFree(pwszWide);
+    return osRet;    
+}
+
+/************************************************************************/
+/*                           ICreateLayer()                             */
+/************************************************************************/
+
+OGRLayer *OGRDGNV8DataSource::ICreateLayer( const char *pszLayerName,
+                                            OGRSpatialReference * /*poSRS*/,
+                                            OGRwkbGeometryType /*eGeomType*/,
+                                            char **papszOptions )
+
+{
+    if( !m_bUpdate )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "CreateLayer() only supported on update mode." );
+        return NULL;
+    }
+
+    OdDgModelPtr model;
+    try
+    {
+        OdDgModelTablePtr pModelTable = m_poDb->getModelTable(OdDg::kForWrite);
+        // First try to find a model that matches the layer name (case of a seed
+        // file)
+        OdDgElementIteratorPtr pIter = pModelTable->createIterator();
+        for ( ; !pIter->done(); pIter->step() )
+        {
+            OdDgModelPtr pModel = OdDgModel::cast(
+                    pIter->item().openObject( OdDg::kForWrite ) );
+            if ( !pModel.isNull() )
+            {
+                if( ToUTF8(pModel->getName()) == CPLString(pszLayerName) )
+                {
+                    model = pModel;
+                    break;
+                }
+            }
+        }
+        // If we don't find a match, but there's at least one model, pick
+        // the default one
+        if( model.isNull() && m_nLayers == 0 )
+            model = m_poDb->getActiveModelId().openObject( OdDg::kForWrite );
+        if( model.isNull() )
+        {
+            model = OdDgModel::createObject();
+            pModelTable->add( model );
+        }
+        
+        const char* pszDim = CSLFetchNameValue(papszOptions, "DIM");
+        if( pszDim != NULL )
+        {
+            model->setModelIs3dFlag( EQUAL(pszDim, "3") );
+        }
+
+        model->setWorkingUnit( OdDgModel::kWuMasterUnit );
+            
+        model->setName( FromUTF8(pszLayerName) );
+        
+        const char* pszDescription = CSLFetchNameValue(papszOptions,
+                                                       "DESCRIPTION");
+        if( pszDescription )
+            model->setDescription( FromUTF8(pszDescription) );
+    }
+    catch (const OdError& e)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Teigha DGN error occurred: %s",
+                 ToUTF8(e.description()).c_str());
+        return NULL;
+    }
+    catch (const std::exception &exc)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "std::exception occurred: %s", exc.what());
+        return NULL;
+    }
+    catch (...)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unknown exception occurred");
+        return NULL;
+    }
+    
+    m_bModified = true;
+
+    OGRDGNV8Layer* poLayer = new OGRDGNV8Layer(this, model);
+    m_papoLayers = static_cast<OGRDGNV8Layer**>(
+                    CPLRealloc(m_papoLayers,
+                               sizeof(OGRDGNV8Layer*) * (m_nLayers + 1)));
+    m_papoLayers[ m_nLayers++ ] = poLayer;
+    return poLayer;
+}
diff --git a/ogr/ogrsf_frmts/dwg/ogrdgnv8driver.cpp b/ogr/ogrsf_frmts/dwg/ogrdgnv8driver.cpp
new file mode 100644
index 0000000..6c2ef5a
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdgnv8driver.cpp
@@ -0,0 +1,205 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  OGR Driver for DGNv8
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_dgnv8.h"
+#include "cpl_conv.h"
+#include "ogrteigha.h"
+
+CPL_CVSID("$Id: ogrdgnv8driver.cpp 37968 2017-04-12 07:16:55Z rouault $");
+
+/************************************************************************/
+/*                         OGRDGNV8DriverUnload()                       */
+/************************************************************************/
+
+static void OGRDGNV8DriverUnload( GDALDriver* )
+{
+    CPLDebug("DGNv8", "Driver cleanup");
+    OGRTEIGHADeinitialize();
+}
+
+/************************************************************************/
+/*                         OGRDGNV8DriverIdentify()                     */
+/************************************************************************/
+
+static int OGRDGNV8DriverIdentify( GDALOpenInfo* poOpenInfo )
+
+{
+    VSIStatBuf sStat;
+    if(  poOpenInfo->fpL != NULL &&
+         poOpenInfo->nHeaderBytes >= 512 )
+    {
+        // Is it a DGN v7 cell library?
+        if( poOpenInfo->pabyHeader[0] == 0x08
+            && poOpenInfo->pabyHeader[1] == 0x05
+            && poOpenInfo->pabyHeader[2] == 0x17
+            && poOpenInfo->pabyHeader[3] == 0x00 )
+        {
+            return GDALGetDriverByName("DGN") == NULL &&
+                   VSIStat(poOpenInfo->pszFilename, &sStat) == 0;
+        }
+
+        // Is it a DGN v7 regular 2D or 3D file?
+        if( (poOpenInfo->pabyHeader[0] == 0x08 ||
+             poOpenInfo->pabyHeader[0] == 0xC8)
+            && poOpenInfo->pabyHeader[1] == 0x09
+            && poOpenInfo->pabyHeader[2] == 0xFE
+            && poOpenInfo->pabyHeader[3] == 0x02 )
+        {
+            return GDALGetDriverByName("DGN") == NULL &&
+                   VSIStat(poOpenInfo->pszFilename, &sStat) == 0;
+        }
+    }
+
+    return poOpenInfo->fpL != NULL &&
+           poOpenInfo->nHeaderBytes >= 512 &&
+           EQUAL( CPLGetExtension(poOpenInfo->pszFilename), "DGN" ) &&
+           memcmp(poOpenInfo->pabyHeader,
+                  "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1", 8) == 0 &&
+           VSIStat(poOpenInfo->pszFilename, &sStat) == 0;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+static GDALDataset *OGRDGNV8DriverOpen( GDALOpenInfo* poOpenInfo )
+
+{
+    if( !OGRDGNV8DriverIdentify(poOpenInfo))
+        return NULL;
+
+    if( !OGRTEIGHAInitialize() )
+        return NULL;
+
+    OGRDGNV8DataSource *poDS = new OGRDGNV8DataSource(OGRDGNV8GetServices());
+    if( !poDS->Open( poOpenInfo->pszFilename,
+                     poOpenInfo->eAccess == GA_Update) )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                              Create()                                */
+/************************************************************************/
+
+static GDALDataset *OGRDGNV8DriverCreate( const char * pszName,
+                                        int /* nBands */,
+                                        int /* nXSize */,
+                                        int /* nYSize */,
+                                        GDALDataType /* eDT */,
+                                        char **papszOptions )
+{
+    if( !OGRTEIGHAInitialize() )
+        return NULL;
+
+    OGRDGNV8DataSource *poDS = new OGRDGNV8DataSource(OGRDGNV8GetServices());
+    if( !poDS->PreCreate( pszName, papszOptions ) )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                         RegisterOGRDGNV8()                           */
+/************************************************************************/
+
+void RegisterOGRDGNV8()
+
+{
+    if( GDALGetDriverByName( "DGNV8" ) != NULL )
+        return;
+
+    GDALDriver  *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "DGNV8" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Microstation DGNv8" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dgn" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_dgnv8.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>"
+"  <Option name='SEED' type='string' "
+    "description='Filename of seed file to use'/>"
+"  <Option name='COPY_SEED_FILE_COLOR_TABLE' type='boolean' "
+    "description='whether the color table should be copied from the "
+    "seed file.' default='NO'/>"
+"  <Option name='COPY_SEED_FILE_MODEL' type='boolean' "
+    "description='whether the existing models (without their graphic "
+    "contents) should be copied from the seed file.' default='YES'/>"
+"  <Option name='COPY_SEED_FILE_MODEL_CONTROL_ELEMENTS' type='boolean' "
+    "description='whether the existing control elements of models should be "
+    "copied from the seed file.' default='YES'/>"
+"  <Option name='APPLICATION' type='string' "
+    "description='Set Application field in header'/>"
+"  <Option name='TITLE' type='string' "
+    "description='Set Title field in header'/>"
+"  <Option name='SUBJECT' type='string' "
+    "description='Set Subject field in header'/>"
+"  <Option name='AUTHOR' type='string' "
+    "description='Set Author field in header'/>"
+"  <Option name='KEYWORDS' type='string' "
+    "description='Set Keywords field in header'/>"
+"  <Option name='TEMPLATE' type='string' "
+    "description='Set Template field in header'/>"
+"  <Option name='COMMENTS' type='string' "
+    "description='Set Comments field in header'/>"
+"  <Option name='LAST_SAVED_BY' type='string' "
+    "description='Set LastSavedBy field in header'/>"
+"  <Option name='REVISION_NUMBER' type='string' "
+    "description='Set RevisionNumber field in header'/>"
+"  <Option name='CATEGORY' type='string' "
+    "description='Set Category field in header'/>"
+"  <Option name='MANAGER' type='string' "
+    "description='Set Manager field in header'/>"
+"  <Option name='COMPANY' type='string' "
+    "description='Set Company field in header'/>"
+"</CreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+"<LayerCreationOptionList>"
+"  <Option name='DESCRIPTION' type='string' "
+    "description='Description of the layer/model'/>"
+"  <Option name='DIM' type='int' "
+    "description='Dimension (2 or 3) of the layer/model'/>"
+"</LayerCreationOptionList>" );
+
+    poDriver->pfnOpen = OGRDGNV8DriverOpen;
+    poDriver->pfnIdentify = OGRDGNV8DriverIdentify;
+    poDriver->pfnCreate = OGRDGNV8DriverCreate;
+    poDriver->pfnUnloadDriver = OGRDGNV8DriverUnload;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/dwg/ogrdgnv8layer.cpp b/ogr/ogrsf_frmts/dwg/ogrdgnv8layer.cpp
new file mode 100644
index 0000000..97fa10b
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrdgnv8layer.cpp
@@ -0,0 +1,2281 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  OGR Driver for DGNv8
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_dgnv8.h"
+#include "cpl_conv.h"
+#include "ogr_featurestyle.h"
+#include "ogr_api.h"
+
+#include <math.h>
+#include <algorithm>
+
+/* -------------------------------------------------------------------- */
+/*      Line Styles                                                     */
+/* -------------------------------------------------------------------- */
+#define DGNS_SOLID              0
+#define DGNS_DOTTED             1
+#define DGNS_MEDIUM_DASH        2
+#define DGNS_LONG_DASH          3
+#define DGNS_DOT_DASH           4
+#define DGNS_SHORT_DASH         5
+#define DGNS_DASH_DOUBLE_DOT    6
+#define DGNS_LONG_DASH_SHORT_DASH 7
+
+static const double DEG_TO_RAD = M_PI / 180.0;
+static const double RAD_TO_DEG = 180.0 / M_PI;
+static const double CONTIGUITY_TOLERANCE = 1e10; // Arbitrary high value
+
+CPL_CVSID("$Id: ogrdgnv8layer.cpp 37987 2017-04-14 07:42:50Z rouault $");
+
+static CPLString ToUTF8(const OdString& str)
+{
+    return OGRDGNV8DataSource::ToUTF8(str);
+}
+
+/************************************************************************/
+/*                       EscapeDoubleQuote()                            */
+/************************************************************************/
+
+static CPLString EscapeDoubleQuote(const char* pszStr)
+{
+    if( strchr( pszStr, '"') != NULL )
+    {
+        CPLString osEscaped;
+
+        for( size_t iC = 0; pszStr[iC] != '\0'; iC++ )
+        {
+            if( pszStr[iC] == '"' )
+                osEscaped += "\\\"";
+            else
+                osEscaped += pszStr[iC];
+        }
+        return osEscaped;
+    }
+    else
+    {
+        return pszStr;
+    }
+}
+
+/************************************************************************/
+/*                          OGRDGNV8Layer()                             */
+/************************************************************************/
+
+OGRDGNV8Layer::OGRDGNV8Layer( OGRDGNV8DataSource* poDS,
+                              OdDgModelPtr pModel ) :
+    m_poDS(poDS),
+    m_poFeatureDefn(NULL),
+    m_pModel(pModel),
+    m_pIterator(static_cast<OdDgElementIterator*>(NULL)),
+    m_nIdxInPendingFeatures(0)
+{
+    const char* pszName;
+    if( pModel->getName().isEmpty() )
+        pszName = CPLSPrintf("Model #%d", pModel->getEntryId());
+    else
+        pszName = CPLSPrintf("%s", ToUTF8(pModel->getName()).c_str());
+    CPLDebug("DGNV8", "%s is %dd", pszName,
+             pModel->getModelIs3dFlag() ? 3 : 2);
+
+/* -------------------------------------------------------------------- */
+/*      Create the feature definition.                                  */
+/* -------------------------------------------------------------------- */
+    m_poFeatureDefn = new OGRFeatureDefn( pszName );
+    SetDescription( m_poFeatureDefn->GetName() );
+    m_poFeatureDefn->Reference();
+
+    OGRFieldDefn oField( "", OFTInteger );
+
+/* -------------------------------------------------------------------- */
+/*      Element type                                                    */
+/* -------------------------------------------------------------------- */
+    oField.SetName( "Type" );
+    oField.SetType( OFTInteger );
+    oField.SetWidth( 2 );
+    oField.SetPrecision( 0 );
+    m_poFeatureDefn->AddFieldDefn( &oField );
+
+/* -------------------------------------------------------------------- */
+/*      Level number.                                                   */
+/* -------------------------------------------------------------------- */
+    oField.SetName( "Level" );
+    oField.SetType( OFTInteger );
+    oField.SetWidth( 2 );
+    oField.SetPrecision( 0 );
+    m_poFeatureDefn->AddFieldDefn( &oField );
+
+/* -------------------------------------------------------------------- */
+/*      graphic group                                                   */
+/* -------------------------------------------------------------------- */
+    oField.SetName( "GraphicGroup" );
+    oField.SetType( OFTInteger );
+    oField.SetWidth( 4 );
+    oField.SetPrecision( 0 );
+    m_poFeatureDefn->AddFieldDefn( &oField );
+
+/* -------------------------------------------------------------------- */
+/*      ColorIndex                                                      */
+/* -------------------------------------------------------------------- */
+    oField.SetName( "ColorIndex" );
+    oField.SetType( OFTInteger );
+    oField.SetWidth( 3 );
+    oField.SetPrecision( 0 );
+    m_poFeatureDefn->AddFieldDefn( &oField );
+
+/* -------------------------------------------------------------------- */
+/*      Weight                                                          */
+/* -------------------------------------------------------------------- */
+    oField.SetName( "Weight" );
+    oField.SetType( OFTInteger );
+    oField.SetWidth( 2 );
+    oField.SetPrecision( 0 );
+    m_poFeatureDefn->AddFieldDefn( &oField );
+
+/* -------------------------------------------------------------------- */
+/*      Style                                                           */
+/* -------------------------------------------------------------------- */
+    oField.SetName( "Style" );
+    oField.SetType( OFTInteger );
+    oField.SetWidth( 1 );
+    oField.SetPrecision( 0 );
+    m_poFeatureDefn->AddFieldDefn( &oField );
+
+/* -------------------------------------------------------------------- */
+/*      Text                                                            */
+/* -------------------------------------------------------------------- */
+    oField.SetName( "Text" );
+    oField.SetType( OFTString );
+    oField.SetWidth( 0 );
+    oField.SetPrecision( 0 );
+    m_poFeatureDefn->AddFieldDefn( &oField );
+    
+    ResetReading();
+}
+
+/************************************************************************/
+/*                          ~OGRDGNV8Layer()                            */
+/************************************************************************/
+
+OGRDGNV8Layer::~OGRDGNV8Layer()
+
+{
+    CleanPendingFeatures();
+    m_poFeatureDefn->Release();
+}
+/************************************************************************/
+/*                       CleanPendingFeatures()                         */
+/************************************************************************/
+
+void OGRDGNV8Layer::CleanPendingFeatures()
+
+{
+    for( size_t i = m_nIdxInPendingFeatures;
+                i < m_aoPendingFeatures.size(); i++ )
+    {
+        delete m_aoPendingFeatures[i].first;
+    }
+    m_aoPendingFeatures.clear();
+    m_nIdxInPendingFeatures = 0;
+}
+    
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRDGNV8Layer::ResetReading()
+
+{
+    if( m_pModel.get() )
+    {
+        m_pIterator = m_pModel->createGraphicsElementsIterator();
+    }
+    CleanPendingFeatures();
+}
+
+/************************************************************************/
+/*                         CollectSubElements()                         */
+/************************************************************************/
+
+std::vector<tPairFeatureHoleFlag> OGRDGNV8Layer::CollectSubElements(
+                            OdDgElementIteratorPtr iterator, int level )
+{
+    std::vector<tPairFeatureHoleFlag> oVector;
+#ifdef DEBUG_VERBOSE
+    CPLString osIndent;
+    for(int i=0;i<level;i++)
+        osIndent += "  ";
+    int counter = 0;
+#endif
+    for( ; !iterator->done(); iterator->step())
+    {
+#ifdef DEBUG_VERBOSE
+        fprintf(stdout, "%sSub element %d:\n", osIndent.c_str(), counter );
+        counter ++;
+#endif
+        OdRxObjectPtr object = iterator->item().openObject( OdDg::kForRead );
+        OdDgGraphicsElementPtr element = OdDgGraphicsElement::cast( object );
+        if (element.isNull())
+            continue;
+
+        std::vector<tPairFeatureHoleFlag>  oSubVector =
+            ProcessElement(element, level + 1);
+        oVector.insert(oVector.end(), oSubVector.begin(), oSubVector.end());
+    }
+    return oVector;
+}
+
+/************************************************************************/
+/*                        GetAnchorPosition()                           */
+/************************************************************************/
+
+static int GetAnchorPosition( OdDg::TextJustification value )
+{
+    switch( value )
+    {
+        case OdDg::kLeftTop           : return 7;
+        case OdDg::kLeftCenter        : return 4;
+        case OdDg::kLeftBottom        : return 10;
+        case OdDg::kLeftMarginTop     : return 7;
+        case OdDg::kLeftMarginCenter  : return 4;
+        case OdDg::kLeftMarginBottom  : return 10;
+        case OdDg::kCenterTop         : return 8;
+        case OdDg::kCenterCenter      : return 5;
+        case OdDg::kCenterBottom      : return 11;
+        case OdDg::kRightMarginTop    : return 9;
+        case OdDg::kRightMarginCenter : return 6;
+        case OdDg::kRightMarginBottom : return 12;
+        case OdDg::kRightTop          : return 9;
+        case OdDg::kRightCenter       : return 6;
+        case OdDg::kRightBottom       : return 12;
+        case OdDg::kLeftDescender     : return 1;
+        case OdDg::kCenterDescender   : return 2;
+        case OdDg::kRightDescender    : return 3;
+        default                       : return 0;
+    }
+}
+
+/************************************************************************/
+/*                        GetAnchorPosition()                           */
+/************************************************************************/
+
+static OdDg::TextJustification GetAnchorPositionFromOGR( int value )
+{
+    switch( value )
+    {
+        case 1:  return OdDg::kLeftDescender;
+        case 2:  return OdDg::kCenterDescender;
+        case 3:  return OdDg::kRightDescender;
+        case 4:  return OdDg::kLeftCenter;
+        case 5:  return OdDg::kCenterCenter;
+        case 6:  return OdDg::kRightCenter;
+        case 7:  return OdDg::kLeftTop;
+        case 8:  return OdDg::kCenterTop;
+        case 9:  return OdDg::kRightTop;
+        case 10: return OdDg::kLeftBottom;
+        case 11: return OdDg::kCenterBottom;
+        case 12: return OdDg::kRightBottom;
+        default: return OdDg::kLeftTop;
+    }
+}
+
+/************************************************************************/
+/*                           AlmostEqual()                              */
+/************************************************************************/
+
+static bool AlmostEqual(double dfA, double dfB)
+{
+    if( fabs(dfB) > 1e-7 )
+        return fabs((dfA - dfB) / dfB) < 1e-6;
+    else
+        return fabs(dfA) <= 1e-7;
+}
+
+/************************************************************************/
+/*                         ProcessTextTraits                           */
+/************************************************************************/
+
+template<class TextPtr> struct ProcessTextTraits
+{
+};
+
+template<> struct ProcessTextTraits<OdDgText2dPtr>
+{
+    static double getRotation(OdDgText2dPtr text)
+    {
+        return text->getRotation();
+    }
+
+    static void setGeom(OGRFeature* poFeature, OdDgText2dPtr text)
+    {
+        OdGePoint2d point = text->getOrigin();
+        poFeature->SetGeometryDirectly(
+                new OGRPoint(point.x, point.y) );
+    }
+};
+
+template<> struct ProcessTextTraits<OdDgText3dPtr>
+{
+    static double getRotation(OdDgText3dPtr /*text*/)
+    {
+        return 0.0;
+    }
+
+    static void setGeom(OGRFeature* poFeature, OdDgText3dPtr text)
+    {
+        OdGePoint3d point = text->getOrigin();
+        poFeature->SetGeometryDirectly(
+                new OGRPoint(point.x, point.y, point.z) );
+    }
+};
+
+/************************************************************************/
+/*                           ProcessText()                              */
+/************************************************************************/
+
+template<class TextPtr >
+static void ProcessText(OGRFeature* poFeature,
+                        const CPLString& osColor,
+                        TextPtr text)
+{
+        const OdString oText = text->getText();
+        poFeature->SetField( "Text", ToUTF8(oText).c_str());
+
+        CPLString osStyle;
+        osStyle.Printf("LABEL(t:\"%s\"",
+                        EscapeDoubleQuote(ToUTF8(oText)).c_str());
+        osStyle += osColor;
+        osStyle += CPLSPrintf(",s:%fg", text->getHeightMultiplier());
+
+        // Gets Font name
+        OdDgFontTablePtr pFontTable = text->database()->getFontTable();
+        OdDgFontTableRecordPtr pFont =
+            pFontTable->getFont(text->getFontEntryId());
+        if (!pFont.isNull())
+        {
+            osStyle += CPLSPrintf(",f:\"%s\"",
+                EscapeDoubleQuote(ToUTF8(pFont->getName())).c_str() );
+        }
+        else
+        {
+            osStyle += CPLSPrintf(",f:MstnFont%u",
+                text->getFontEntryId() );
+        }
+
+        const int nAnchor = GetAnchorPosition(text->getJustification());
+        if( nAnchor > 0 )
+            osStyle += CPLSPrintf(",p:%d", nAnchor);
+        
+        // Add the angle, if not horizontal
+        const double dfRotation =
+                        ProcessTextTraits<TextPtr>::getRotation(text);
+        if( dfRotation != 0.0 )
+          osStyle += CPLSPrintf(",a:%d",
+                   static_cast<int>(floor(dfRotation * RAD_TO_DEG +0.5)) );
+
+        osStyle += ")";
+        poFeature->SetStyleString(osStyle);
+        ProcessTextTraits<TextPtr>::setGeom( poFeature, text );
+}
+
+/************************************************************************/
+/*                            ConsiderBrush()                           */
+/************************************************************************/
+
+static CPLString ConsiderBrush(OdDgGraphicsElementPtr element,
+                                       const CPLString& osStyle)
+{
+    CPLString osNewStyle(osStyle);
+    OdRxObjectPtrArray linkages;
+    element->getLinkages(OdDgAttributeLinkage::kFillStyle, linkages);
+    if( linkages.length() >= 1 )
+    {
+        OdDgFillColorLinkagePtr fillColor =
+            OdDgFillColorLinkage::cast( linkages[0] );
+        if( !fillColor.isNull() )
+        {
+            const OdUInt32 uFillColorIdx = fillColor->getColorIndex();
+            if( OdDgColorTable::isCorrectIndex(
+                                    element->database(), uFillColorIdx  ) )
+            {
+                ODCOLORREF color = OdDgColorTable::lookupRGB(
+                    element->database(), uFillColorIdx  );
+                const char* pszBrush = CPLSPrintf(
+                    "BRUSH(fc:#%02x%02x%02x,id:\"ogr-brush-0\")",
+                    ODGETRED(color),
+                    ODGETGREEN(color),
+                    ODGETBLUE(color));
+                const OdUInt32 uColorIndex = element->getColorIndex();
+                if( uFillColorIdx != uColorIndex )
+                {
+                    osNewStyle = CPLString(pszBrush) + ";" + osNewStyle;
+                }
+                else
+                {
+                    osNewStyle = pszBrush;
+                }
+            }
+        }
+    }
+    return osNewStyle;
+}
+
+/************************************************************************/
+/*                         ProcessCurveTraits                           */
+/************************************************************************/
+
+template<class CurveElementPtr> struct ProcessCurveTraits
+{
+};
+
+template<> struct ProcessCurveTraits<OdDgCurveElement2dPtr>
+{
+    typedef OdDgCurve2d         CurveType;
+    typedef OdDgArc2d           ArcType;
+    typedef OdDgBSplineCurve2d  BSplineType;
+    typedef OdDgEllipse2d       EllipseType;
+    typedef OdGePoint2d         PointType;
+
+    static void setPoint( OGRSimpleCurve* poSC, int i, OdGePoint2d point)
+    {
+        poSC->setPoint(i, point.x, point.y);
+    }
+};
+
+template<> struct ProcessCurveTraits<OdDgCurveElement3dPtr>
+{
+    typedef OdDgCurve3d         CurveType;
+    typedef OdDgArc3d           ArcType;
+    typedef OdDgBSplineCurve3d  BSplineType;
+    typedef OdDgEllipse3d       EllipseType;
+    typedef OdGePoint3d         PointType;
+
+    static void setPoint( OGRSimpleCurve* poSC, int i, OdGePoint3d point)
+    {
+        poSC->setPoint(i, point.x, point.y, point.z);
+    }
+};
+
+/************************************************************************/
+/*                            ProcessCurve()                            */
+/************************************************************************/
+
+template<class CurveElementPtr>
+static void ProcessCurve(OGRFeature* poFeature, const CPLString& osPen,
+                         CurveElementPtr curveElement)
+{
+    typedef typename ProcessCurveTraits<CurveElementPtr>::CurveType CurveType;
+    typedef typename ProcessCurveTraits<CurveElementPtr>::ArcType ArcType;
+    typedef typename ProcessCurveTraits<CurveElementPtr>::BSplineType
+                                                                 BSplineType;
+    typedef typename ProcessCurveTraits<CurveElementPtr>::EllipseType
+                                                                 EllipseType;
+    typedef typename ProcessCurveTraits<CurveElementPtr>::PointType PointType;
+
+    OdSmartPtr<CurveType> curve = CurveType::cast( curveElement );
+    OdSmartPtr<ArcType> arc = ArcType::cast( curveElement );
+    OdSmartPtr<BSplineType> bspline = BSplineType::cast( curveElement );
+    OdSmartPtr<EllipseType> ellipse = EllipseType::cast( curveElement );
+
+    bool bIsCircular = false;
+    if( !ellipse.isNull() )
+    {
+        bIsCircular = AlmostEqual(ellipse->getPrimaryAxis(),
+                                  ellipse->getSecondaryAxis());
+    }
+    else if( !arc.isNull() )
+    {
+        bIsCircular = AlmostEqual(arc->getPrimaryAxis(),
+                                  arc->getSecondaryAxis());
+    }
+
+    double dfStartParam, dfEndParam;
+    OdResult eRes = curveElement->getStartParam(dfStartParam);
+    CPLAssert(eRes == eOk );
+    eRes = curveElement->getEndParam(dfEndParam);
+    CPLAssert(eRes == eOk );
+    
+    CPLString osStyle(osPen);
+    bool bIsFilled = false;
+    if( !ellipse.isNull() )
+    {
+        osStyle = ConsiderBrush(curveElement, osPen);
+        bIsFilled = osStyle.find("BRUSH") == 0;
+    }
+
+    OGRSimpleCurve* poSC;
+    int nPoints;
+    if( !bspline.isNull() )
+    {
+        // 10 is somewhat arbitrary
+        nPoints = 10 * bspline->numControlPoints();
+        poSC = new OGRLineString();
+    }
+    else if( !curve.isNull() )
+    {
+        // 5 is what is used in DGN driver
+        nPoints = 5 * curve->getVerticesCount();
+        poSC = new OGRLineString();
+    }
+    else if( bIsCircular )
+    {
+        poSC = new OGRCircularString();
+        if( !ellipse.isNull() )
+        {
+            nPoints = 5;
+        }
+        else
+        {
+            nPoints = 3;
+        }
+    }
+    else
+    {
+        if( bIsFilled )
+            poSC = new OGRLinearRing();
+        else
+            poSC = new OGRLineString();
+        const double dfArcStepSize =
+            CPLAtofM(CPLGetConfigOption("OGR_ARC_STEPSIZE", "4"));
+        if( !ellipse.isNull() )
+        {
+            nPoints = std::max(2,
+                static_cast<int>(360 / dfArcStepSize));
+        }
+        else
+        {
+            nPoints = std::max(2,
+                static_cast<int>(arc->getSweepAngle() *
+                                 RAD_TO_DEG / dfArcStepSize) );
+        }
+    }
+
+    poSC->setNumPoints(nPoints);
+    for( int i = 0; i < nPoints; i++ )
+    {
+        PointType point;
+        double dfParam = dfStartParam + i *
+                (dfEndParam - dfStartParam) / (nPoints - 1);
+        eRes = curveElement->getPointAtParam(dfParam, point);
+        CPLAssert(eRes == eOk );
+        ProcessCurveTraits<CurveElementPtr>::setPoint(poSC, i, point);
+    }
+
+    if( bIsFilled )
+    {
+        if( bIsCircular )
+        {
+            OGRCurvePolygon* poCP = new OGRCurvePolygon();
+            poCP->addRingDirectly(poSC);
+            poFeature->SetGeometryDirectly( poCP );
+        }
+        else
+        {
+            OGRPolygon* poPoly = new OGRPolygon();
+            poPoly->addRingDirectly(poSC);
+            poFeature->SetGeometryDirectly( poPoly );
+        }
+    }
+    else
+    {
+        poFeature->SetGeometryDirectly( poSC );
+    }
+    poFeature->SetStyleString(osStyle);
+}
+
+/************************************************************************/
+/*                           IsContiguous()                             */
+/************************************************************************/
+
+static
+bool IsContiguous( const std::vector<tPairFeatureHoleFlag>& oVectorSubElts,
+                   bool& bHasCurves,
+                   bool& bIsClosed )
+{
+    bHasCurves = false;
+    bIsClosed = false;
+    OGRPoint oFirstPoint, oLastPoint;
+    bool bLastPointValid = false;
+    bool bIsContiguous = true;
+    for( size_t i = 0; i < oVectorSubElts.size(); i++ )
+    {
+        OGRGeometry* poGeom = oVectorSubElts[i].first->GetGeometryRef();
+        if( poGeom != NULL )
+        {
+            OGRwkbGeometryType eType =
+                                wkbFlatten(poGeom->getGeometryType());
+            if( eType == wkbCircularString )
+            {
+                bHasCurves = true;
+            }
+            if( bIsContiguous &&
+                (eType == wkbCircularString ||
+                 eType == wkbLineString) )
+            {
+                OGRCurve* poCurve = static_cast<OGRCurve*>(poGeom);
+                if( poCurve->getNumPoints() >= 2 )
+                {
+                    OGRPoint oStartPoint;
+                    poCurve->StartPoint( &oStartPoint );
+                   
+                    if( bLastPointValid )
+                    {
+                        if( !AlmostEqual(oStartPoint.getX(),
+                                         oLastPoint.getX()) ||
+                            !AlmostEqual(oStartPoint.getY(),
+                                         oLastPoint.getY()) ||
+                            !AlmostEqual(oStartPoint.getZ(),
+                                         oLastPoint.getZ()) )
+                        {
+                             bIsContiguous = false;
+                             break;
+                        }
+                    }
+                    else
+                    {
+                        oFirstPoint = oStartPoint;
+                    }
+                    bLastPointValid = true;
+                    poCurve->EndPoint( &oLastPoint );
+                }
+                else
+                {
+                    bIsContiguous = false;
+                    break;
+                }
+            }
+            else
+            {
+                bIsContiguous = false;
+                break;
+            }
+        }
+    }
+    if( bIsContiguous )
+    {
+        bIsClosed = bLastPointValid &&
+                AlmostEqual(oFirstPoint.getX(), oLastPoint.getX()) &&
+                AlmostEqual(oFirstPoint.getY(), oLastPoint.getY()) &&
+                AlmostEqual(oFirstPoint.getZ(), oLastPoint.getZ());
+    }
+    return bIsContiguous;
+}
+
+/************************************************************************/
+/*                           ProcessElement()                           */
+/************************************************************************/
+
+std::vector<tPairFeatureHoleFlag> OGRDGNV8Layer::ProcessElement(
+                                            OdDgGraphicsElementPtr element,
+                                            int level)
+{
+    std::vector<tPairFeatureHoleFlag> oVector;
+#ifdef DEBUG_VERBOSE
+    CPLString osIndent;
+    for(int i=0;i<level;i++)
+        osIndent += "  ";
+#endif
+
+    bool bHoleFlag = false;
+    OGRFeature  *poFeature = new OGRFeature( m_poFeatureDefn );
+
+    OdRxClass *poClass = element->isA();
+    const OdString osName = poClass->name();
+    const char *pszEntityClassName = static_cast<const char*>(osName);
+    poFeature->SetFID(
+        static_cast<GIntBig>(
+            static_cast<OdUInt64>(element->elementId().getHandle()) ) );
+#ifdef DEBUG_VERBOSE
+    fprintf(stdout, "%s%s\n", osIndent.c_str(), pszEntityClassName);
+    fprintf(stdout, "%sID = %s\n", 
+            osIndent.c_str(),
+            static_cast<const char*>(element->elementId().getHandle().ascii()) );
+    fprintf(stdout, "%sType = %d\n",
+            osIndent.c_str(), element->getElementType() );
+#endif
+
+    poFeature->SetField("Type", element->getElementType() );
+    const int nLevel = static_cast<int>(element->getLevelEntryId());
+    poFeature->SetField("Level", nLevel );
+    poFeature->SetField("GraphicGroup", 
+                        static_cast<int>(element->getGraphicsGroupEntryId()) );
+    const OdUInt32 uColorIndex = element->getColorIndex();
+    CPLString osColor;
+    if( uColorIndex != OdDg::kColorByLevel &&
+        uColorIndex != OdDg::kColorByCell )
+    {
+        poFeature->SetField("ColorIndex",
+                            static_cast<int>(uColorIndex));
+
+        const ODCOLORREF color = element->getColor();
+        osColor = CPLSPrintf(",c:#%02x%02x%02x",
+                              ODGETRED(color),
+                              ODGETGREEN(color),
+                              ODGETBLUE(color));
+    }
+    const OdInt32 nLineStyle = element->getLineStyleEntryId();
+    if( nLineStyle != OdDg::kLineStyleByLevel &&
+        nLineStyle != OdDg::kLineStyleByCell )
+    {
+        poFeature->SetField("Style", nLineStyle);
+    }
+
+    const OdUInt32 uLineWeight = element->getLineWeight();
+    int nLineWeight = 0;
+    if( uLineWeight != OdDg::kLineWeightByLevel && 
+        uLineWeight != OdDg::kLineWeightByCell )
+    {
+        nLineWeight = static_cast<int>(uLineWeight);
+        poFeature->SetField("Weight", nLineWeight);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Generate corresponding PEN style.                               */
+/* -------------------------------------------------------------------- */
+    CPLString osPen;
+
+    if( nLineStyle == DGNS_SOLID )
+        osPen = "PEN(id:\"ogr-pen-0\"";
+    else if( nLineStyle == DGNS_DOTTED )
+        osPen = "PEN(id:\"ogr-pen-5\"";
+    else if( nLineStyle == DGNS_MEDIUM_DASH )
+        osPen = "PEN(id:\"ogr-pen-2\"";
+    else if( nLineStyle == DGNS_LONG_DASH )
+        osPen = "PEN(id:\"ogr-pen-4\"";
+    else if( nLineStyle == DGNS_DOT_DASH )
+        osPen = "PEN(id:\"ogr-pen-6\"";
+    else if( nLineStyle == DGNS_SHORT_DASH )
+        osPen = "PEN(id:\"ogr-pen-3\"";
+    else if( nLineStyle == DGNS_DASH_DOUBLE_DOT )
+        osPen = "PEN(id:\"ogr-pen-7\"";
+    else if( nLineStyle == DGNS_LONG_DASH_SHORT_DASH )
+        osPen = "PEN(p:\"10px 5px 4px 5px\"";
+    else
+        osPen = "PEN(id:\"ogr-pen-0\"";
+
+    osPen += osColor;
+
+    if( nLineWeight > 1 )
+        osPen += CPLSPrintf(",w:%dpx", nLineWeight );
+
+    osPen += ")";
+
+    if( EQUAL(pszEntityClassName, "OdDgCellHeader2d") ||
+        EQUAL(pszEntityClassName, "OdDgCellHeader3d") )
+    {
+        bool bDestroyFeature = true;
+        OdDgElementIteratorPtr iterator;
+        if( EQUAL(pszEntityClassName, "OdDgCellHeader2d") )
+        {
+            OdDgCellHeader2dPtr elementCell = OdDgCellHeader2d::cast( element );
+            CPLAssert( !elementCell.isNull() );
+            iterator = elementCell->createIterator();
+        }
+        else
+        {
+            OdDgCellHeader3dPtr elementCell = OdDgCellHeader3d::cast( element );
+            CPLAssert( !elementCell.isNull() );
+            iterator = elementCell->createIterator();
+        }
+        if( !iterator.isNull() )
+        {
+            oVector = CollectSubElements(iterator, level + 1 );
+            int nCountMain = 0;
+            bool bHasHole = false;
+            bool bHasCurve = false;
+            OGRGeometry* poExterior = NULL;
+            for( size_t i = 0; i < oVector.size(); i++ )
+            {
+                OGRFeature* poFeat = oVector[i].first;
+                CPLAssert( poFeat );
+                OGRGeometry* poGeom = poFeat->GetGeometryRef();
+                if( poGeom == NULL )
+                {
+                    nCountMain = 0;
+                    break;
+                }
+                const OGRwkbGeometryType eType =
+                    wkbFlatten(poGeom->getGeometryType());
+                if( (eType == wkbPolygon || eType == wkbCurvePolygon) &&
+                    static_cast<OGRCurvePolygon*>(poGeom)->
+                                                getNumInteriorRings() == 0 )
+                {
+                    if( eType == wkbCurvePolygon )
+                        bHasCurve = true;
+                    if( oVector[i].second )
+                        bHasHole = true;
+                    else
+                    {
+                        poExterior = poGeom;
+                        nCountMain ++;
+                    }
+                }
+                else
+                {
+                    nCountMain = 0;
+                    break;
+                }
+            }
+            if( nCountMain == 1 && bHasHole )
+            {
+                bDestroyFeature = false;
+                OGRCurvePolygon* poCP;
+                if( bHasCurve )
+                    poCP = new OGRCurvePolygon();
+                else
+                    poCP = new OGRPolygon();
+                poCP->addRing(
+                    static_cast<OGRCurvePolygon*>(poExterior)->getExteriorRingCurve() );
+                for( size_t i = 0; i < oVector.size(); i++ )
+                {
+                    OGRFeature* poFeat = oVector[i].first;
+                    OGRGeometry* poGeom = poFeat->GetGeometryRef();
+                    if( poGeom != poExterior )
+                    {
+                        poCP->addRing(
+                            static_cast<OGRCurvePolygon*>(poGeom)->getExteriorRingCurve() );
+                    }
+                    delete poFeat;
+                }
+                oVector.clear();
+                poFeature->SetGeometryDirectly(poCP);
+                poFeature->SetStyleString( ConsiderBrush(element, osPen) );
+            }                
+        }
+        if( bDestroyFeature )
+        {
+            delete poFeature;
+            poFeature = NULL;
+        }
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgText2d") )
+    {
+        OdDgText2dPtr text = OdDgText2d::cast( element );
+        CPLAssert( !text.isNull() );
+        ProcessText(poFeature, osColor, text);
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgText3d") )
+    {
+        OdDgText3dPtr text = OdDgText3d::cast( element );
+        CPLAssert( !text.isNull() );
+        ProcessText(poFeature, osColor, text);
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgTextNode2d") ||
+             EQUAL(pszEntityClassName, "OdDgTextNode3d") )
+    {
+        OdDgElementIteratorPtr iterator;
+        if( EQUAL(pszEntityClassName, "OdDgTextNode2d") )
+        {
+            OdDgTextNode2dPtr textNode = OdDgTextNode2d::cast( element );
+            CPLAssert( !textNode.isNull() );
+            iterator = textNode->createIterator();
+        }
+        else
+        {
+            OdDgTextNode3dPtr textNode = OdDgTextNode3d::cast( element );
+            CPLAssert( !textNode.isNull() );
+            iterator = textNode->createIterator();
+        }
+        if( !iterator.isNull() )
+        {
+            oVector = CollectSubElements(iterator, level + 1 );
+        }
+        delete poFeature;
+        poFeature = NULL;
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgLine2d") )
+    {
+        OdDgLine2dPtr line = OdDgLine2d::cast( element );
+        CPLAssert( !line.isNull() );
+        OdGePoint2d pointStart = line->getStartPoint( );
+        OdGePoint2d pointEnd = line->getEndPoint( );
+        if( pointStart == pointEnd )
+        {
+             poFeature->SetGeometryDirectly(
+                new OGRPoint(pointStart.x, pointStart.y) );
+        }
+        else
+        {
+            OGRLineString* poLS = new OGRLineString();
+            poLS->setNumPoints(2);
+            poLS->setPoint(0, pointStart.x, pointStart.y);
+            poLS->setPoint(1, pointEnd.x, pointEnd.y);
+            poFeature->SetGeometryDirectly( poLS );
+            poFeature->SetStyleString(osPen);
+        }
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgLine3d") )
+    {
+        OdDgLine3dPtr line = OdDgLine3d::cast( element );
+        CPLAssert( !line.isNull() );
+        OdGePoint3d pointStart = line->getStartPoint( );
+        OdGePoint3d pointEnd = line->getEndPoint( );
+        if( pointStart == pointEnd )
+        {
+             poFeature->SetGeometryDirectly(
+                new OGRPoint(pointStart.x, pointStart.y, pointStart.z) );
+        }
+        else
+        {
+            OGRLineString* poLS = new OGRLineString();
+            poLS->setNumPoints(2);
+            poLS->setPoint(0, pointStart.x, pointStart.y, pointStart.z);
+            poLS->setPoint(1, pointEnd.x, pointEnd.y, pointEnd.z);
+            poFeature->SetGeometryDirectly( poLS );
+            poFeature->SetStyleString(osPen);
+        }
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgLineString2d") )
+    {
+        OdDgLineString2dPtr line = OdDgLineString2d::cast( element );
+        CPLAssert( !line.isNull() );
+        const int nPoints = line->getVerticesCount();
+
+        OGRLineString* poLS = new OGRLineString();
+        poLS->setNumPoints(nPoints);
+        for( int i = 0; i < nPoints; i++ )
+        {
+            OdGePoint2d point = line->getVertexAt( i );
+            poLS->setPoint(i, point.x, point.y);
+        }
+        poFeature->SetGeometryDirectly( poLS );
+        poFeature->SetStyleString(osPen);
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgLineString3d") )
+    {
+        OdDgLineString3dPtr line = OdDgLineString3d::cast( element );
+        CPLAssert( !line.isNull() );
+        const int nPoints = line->getVerticesCount();
+
+        OGRLineString* poLS = new OGRLineString();
+        poLS->setNumPoints(nPoints);
+        for( int i = 0; i < nPoints; i++ )
+        {
+            OdGePoint3d point = line->getVertexAt( i );
+            poLS->setPoint(i, point.x, point.y, point.z);
+        }
+        poFeature->SetGeometryDirectly( poLS );
+        poFeature->SetStyleString(osPen);
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgPointString2d") )
+    {
+        OdDgPointString2dPtr string = OdDgPointString2d::cast( element );
+        CPLAssert( !string.isNull() );
+        const int nPoints = string->getVerticesCount();
+        
+        // Not sure this is the right way to model this
+        // We lose the rotation per vertex.
+        OGRMultiPoint* poMP = new OGRMultiPoint();
+        for( int i = 0; i < nPoints; i++ )
+        {
+            OdGePoint2d point = string->getVertexAt( i );
+            poMP->addGeometryDirectly(new OGRPoint(point.x, point.y));
+        }
+        poFeature->SetGeometryDirectly( poMP );
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgPointString3d") )
+    {
+        OdDgPointString3dPtr string = OdDgPointString3d::cast( element );
+        CPLAssert( !string.isNull() );
+        const int nPoints = string->getVerticesCount();
+
+        // Not sure this is the right way to model this
+        // We lose the rotation per vertex.
+        OGRMultiPoint* poMP = new OGRMultiPoint();
+        for( int i = 0; i < nPoints; i++ )
+        {
+            OdGePoint3d point = string->getVertexAt( i );
+            poMP->addGeometryDirectly(new OGRPoint(point.x, point.y, point.z));
+        }
+        poFeature->SetGeometryDirectly( poMP );
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgMultiline") )
+    {
+        // This is a poor approximation since a multiline is a central line
+        // with parallel lines.
+        OdDgMultilinePtr line = OdDgMultiline::cast( element );
+        CPLAssert( !line.isNull() );
+        const int nPoints = static_cast<int>(line->getPointsCount());
+
+        OGRLineString* poLS = new OGRLineString();
+        poLS->setNumPoints(nPoints);
+        for( int i = 0; i < nPoints; i++ )
+        {
+            OdDgMultilinePoint point;
+            OdGePoint3d point3d;
+            line->getPoint( i, point );
+            point.getPoint( point3d );
+            poLS->setPoint(i, point3d.x, point3d.y, point3d.z);
+        }
+        poFeature->SetGeometryDirectly( poLS );
+        poFeature->SetStyleString(osPen);
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgArc2d") ||
+             EQUAL(pszEntityClassName, "OdDgCurve2d") ||
+             EQUAL(pszEntityClassName, "OdDgBSplineCurve2d") ||
+             EQUAL(pszEntityClassName, "OdDgEllipse2d") )
+    {
+        OdDgCurveElement2dPtr curveElement =
+                            OdDgCurveElement2d::cast( element );
+        CPLAssert( !curveElement.isNull() );
+
+        ProcessCurve(poFeature, osPen, curveElement);
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgArc3d") ||
+             EQUAL(pszEntityClassName, "OdDgCurve3d") ||
+             EQUAL(pszEntityClassName, "OdDgBSplineCurve3d") ||
+             EQUAL(pszEntityClassName, "OdDgEllipse3d") )
+    {
+        OdDgCurveElement3dPtr curveElement =
+                            OdDgCurveElement3d::cast( element );
+        CPLAssert( !curveElement.isNull() );
+
+        ProcessCurve(poFeature, osPen, curveElement);
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgShape2d") )
+    {
+        OdDgShape2dPtr shape = OdDgShape2d::cast( element );
+        CPLAssert( !shape.isNull() );
+        bHoleFlag = shape->getHoleFlag();
+        const int nPoints = shape->getVerticesCount();
+       
+        OGRLinearRing* poLS = new OGRLinearRing();
+        poLS->setNumPoints(nPoints);
+        for( int i = 0; i < nPoints; i++ )
+        {
+            OdGePoint2d point = shape->getVertexAt( i );
+            poLS->setPoint(i, point.x, point.y);
+        }
+        OGRPolygon* poPoly = new OGRPolygon();
+        poPoly->addRingDirectly(poLS);
+        poFeature->SetGeometryDirectly( poPoly );
+        poFeature->SetStyleString(ConsiderBrush(element, osPen));
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgShape3d") )
+    {
+        OdDgShape3dPtr shape = OdDgShape3d::cast( element );
+        CPLAssert( !shape.isNull() );
+        bHoleFlag = shape->getHoleFlag();
+        const int nPoints = shape->getVerticesCount();
+       
+        OGRLinearRing* poLS = new OGRLinearRing();
+        poLS->setNumPoints(nPoints);
+        for( int i = 0; i < nPoints; i++ )
+        {
+            OdGePoint3d point = shape->getVertexAt( i );
+            poLS->setPoint(i, point.x, point.y, point.z);
+        }
+        OGRPolygon* poPoly = new OGRPolygon();
+        poPoly->addRingDirectly(poLS);
+        poFeature->SetGeometryDirectly( poPoly );
+        poFeature->SetStyleString(ConsiderBrush(element, osPen));
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgComplexString") )
+    {
+        OdDgComplexStringPtr complex = OdDgComplexString::cast( element );
+        CPLAssert( !complex.isNull() );
+
+        OdDgElementIteratorPtr iterator = complex->createIterator();
+        if( !iterator.isNull() )
+        {
+            std::vector<tPairFeatureHoleFlag> oVectorSubElts =
+                                CollectSubElements(iterator, level + 1 );
+
+            // First pass to determine if we have non-linear pieces.
+            bool bHasCurves = false;
+            bool bIsClosed = false;
+            bool bIsContiguous = IsContiguous(oVectorSubElts, bHasCurves, bIsClosed );
+
+            if( bIsContiguous && bHasCurves )
+            {
+                OGRCompoundCurve* poCC = new OGRCompoundCurve();
+
+                // Second pass to aggregate the geometries.
+                for( size_t i = 0; i < oVectorSubElts.size(); i++ )
+                {
+                    OGRGeometry* poGeom =
+                            oVectorSubElts[i].first->GetGeometryRef();
+                    if( poGeom != NULL )
+                    {
+                        OGRwkbGeometryType eType =
+                                        wkbFlatten(poGeom->getGeometryType());
+                        if( eType == wkbCircularString || eType == wkbLineString )
+                        {
+                            poCC->addCurve( static_cast<OGRCurve*>(poGeom),
+                                            CONTIGUITY_TOLERANCE );
+                        }
+                    }
+                    delete oVectorSubElts[i].first;
+                }
+
+                poFeature->SetGeometryDirectly( poCC );
+            }
+            else
+            {
+                OGRMultiCurve* poMC;
+                if( bHasCurves )
+                    poMC = new OGRMultiCurve();
+                else
+                    poMC = new OGRMultiLineString();
+
+                // Second pass to aggregate the geometries.
+                for( size_t i = 0; i < oVectorSubElts.size(); i++ )
+                {
+                    OGRGeometry* poGeom =
+                                    oVectorSubElts[i].first->GetGeometryRef();
+                    if( poGeom != NULL )
+                    {
+                        OGRwkbGeometryType eType =
+                                        wkbFlatten(poGeom->getGeometryType());
+                        if( eType == wkbCircularString || eType == wkbLineString )
+                        {
+                            poMC->addGeometry( poGeom );
+                        }
+                    }
+                    delete oVectorSubElts[i].first;
+                }
+
+                poFeature->SetGeometryDirectly( poMC );
+            }
+            poFeature->SetStyleString( osPen );
+        }
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgComplexShape") )
+    {
+        OdDgComplexCurvePtr complex = OdDgComplexCurve::cast( element );
+        CPLAssert( !complex.isNull() );
+
+        OdDgComplexShapePtr complexShape = OdDgComplexShape::cast( element );
+        CPLAssert( !complexShape.isNull() );
+        bHoleFlag = complexShape->getHoleFlag();
+
+        OdDgElementIteratorPtr iterator = complex->createIterator();
+        if( !iterator.isNull() )
+        {
+            std::vector<tPairFeatureHoleFlag> oVectorSubElts =
+                                CollectSubElements(iterator, level + 1 );
+
+            // First pass to determine if we have non-linear pieces.
+            bool bHasCurves = false;
+            bool bIsClosed = false;
+            bool bIsContiguous = IsContiguous(oVectorSubElts, bHasCurves, bIsClosed );
+
+            if( bIsContiguous && bIsClosed )
+            {
+                OGRCurvePolygon* poCP;
+                OGRCompoundCurve* poCC = NULL;
+                OGRLinearRing* poLR = NULL;
+
+                if( bHasCurves )
+                {
+                    poCP = new OGRCurvePolygon();
+                    poCC = new OGRCompoundCurve();
+                }
+                else
+                {
+                    poCP = new OGRPolygon();
+                    poLR = new OGRLinearRing();
+                }
+
+                // Second pass to aggregate the geometries.
+                for( size_t i = 0; i < oVectorSubElts.size(); i++ )
+                {
+                    OGRGeometry* poGeom =
+                            oVectorSubElts[i].first->GetGeometryRef();
+                    if( poGeom != NULL )
+                    {
+                        OGRwkbGeometryType eType =
+                                    wkbFlatten(poGeom->getGeometryType());
+                        if( poCC != NULL )
+                        {
+                            poCC->addCurve( static_cast<OGRCurve*>(poGeom),
+                                            CONTIGUITY_TOLERANCE );
+                        }
+                        else if( eType == wkbLineString )
+                        {
+                            poLR->addSubLineString(
+                                static_cast<OGRLineString*>(poGeom),
+                                poLR->getNumPoints() == 0 ? 0 : 1 );
+                        }
+                    }
+                    delete oVectorSubElts[i].first;
+                }
+
+                poCP->addRingDirectly( ( bHasCurves ) ?
+                    static_cast<OGRCurve*>(poCC) :
+                    static_cast<OGRCurve*>(poLR) );
+
+                poFeature->SetGeometryDirectly( poCP );
+            }
+            else
+            {
+                OGRGeometryCollection oGC;
+                for( size_t i = 0; i < oVectorSubElts.size(); i++ )
+                {
+                    OGRGeometry* poGeom =
+                                    oVectorSubElts[i].first->StealGeometry();
+                    if( poGeom != NULL )
+                    {
+                        OGRwkbGeometryType eType =
+                                        wkbFlatten(poGeom->getGeometryType());
+                        if( eType == wkbCircularString )
+                        {
+                            oGC.addGeometryDirectly(
+                                OGRGeometryFactory::forceToLineString(poGeom) );
+                        }
+                        else if( eType == wkbLineString )
+                        {
+                            oGC.addGeometryDirectly( poGeom );
+                        }
+                        else
+                        {
+                            delete poGeom;
+                        }
+                    }
+                    delete oVectorSubElts[i].first;
+                }
+
+                // Try to assemble into polygon geometry.
+                OGRGeometry* poGeom = reinterpret_cast<OGRGeometry *>(
+                    OGRBuildPolygonFromEdges(
+                      reinterpret_cast<OGRGeometryH>( &oGC ),
+                      TRUE, TRUE, CONTIGUITY_TOLERANCE, NULL ) );
+                poGeom->setCoordinateDimension( oGC.getCoordinateDimension() );
+                poFeature->SetGeometryDirectly( poGeom );
+
+            }
+            poFeature->SetStyleString( ConsiderBrush( element, osPen) );
+        }
+    }
+    else if( EQUAL(pszEntityClassName, "OdDgSharedCellReference") )
+    {
+        OdDgSharedCellReferencePtr ref =
+                            OdDgSharedCellReference::cast( element );
+        CPLAssert( !ref.isNull() );
+        OdGePoint3d point = ref->getOrigin();
+        poFeature->SetField( "Text",
+                    ToUTF8(ref->getDefinitionName()).c_str() );
+        poFeature->SetGeometryDirectly(
+                new OGRPoint(point.x, point.y, point.z) );
+    }
+    else
+    {
+        if( m_aoSetIgnoredFeatureClasses.find(pszEntityClassName) ==
+                                        m_aoSetIgnoredFeatureClasses.end() )
+        {
+            m_aoSetIgnoredFeatureClasses.insert(pszEntityClassName);
+            CPLDebug("DGNV8", "Unhandled class %s for, at least, "
+                     "feature " CPL_FRMT_GIB,
+                     pszEntityClassName, poFeature->GetFID());
+        }
+    }
+
+    if( poFeature != NULL )
+        oVector.push_back( tPairFeatureHoleFlag(poFeature, bHoleFlag) );
+
+    return oVector;
+}
+
+/************************************************************************/
+/*                    GetNextUnfilteredFeature()                        */
+/************************************************************************/
+
+OGRFeature *OGRDGNV8Layer::GetNextUnfilteredFeature()
+
+{
+    while( true )
+    {
+        if( m_nIdxInPendingFeatures < m_aoPendingFeatures.size() )
+        {
+            OGRFeature* poFeature =
+                m_aoPendingFeatures[m_nIdxInPendingFeatures].first;
+            m_aoPendingFeatures[m_nIdxInPendingFeatures].first = NULL;
+            m_nIdxInPendingFeatures ++;
+            return poFeature;
+        }
+
+        if( m_pIterator.isNull() )
+            return NULL;
+
+        while( true )
+        {
+            if( m_pIterator->done() )
+                return NULL;
+            OdRxObjectPtr object = m_pIterator->item().openObject();
+            m_pIterator->step();
+            OdDgGraphicsElementPtr element =
+                            OdDgGraphicsElement::cast( object );
+            if (element.isNull())
+                continue;
+            
+            m_aoPendingFeatures = ProcessElement(element);
+            m_nIdxInPendingFeatures = 0;
+
+            break;
+        }
+    }
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRDGNV8Layer::GetNextFeature()
+
+{
+    while( true )
+    {
+        OGRFeature* poFeature = GetNextUnfilteredFeature();
+        if( poFeature == NULL )
+            break;
+        if( poFeature->GetGeometryRef() == NULL )
+        {
+            delete poFeature;
+            continue;
+        }
+
+        if( (m_poAttrQuery == NULL
+             || m_poAttrQuery->Evaluate( poFeature ))
+            && FilterGeometry( poFeature->GetGeometryRef() ) )
+            return poFeature;
+
+        delete poFeature;
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                        GetFeatureInternal()                          */
+/************************************************************************/
+
+OdDgGraphicsElementPtr OGRDGNV8Layer::GetFeatureInternal(GIntBig nFID,
+                                                  OdDg::OpenMode openMode)
+{
+    if( nFID < 0 )
+        return OdDgGraphicsElementPtr();
+    const OdDbHandle handle( static_cast<OdUInt64>(nFID) );
+    const OdDgElementId id = m_pModel->database()->getElementId(handle);
+    OdRxObjectPtr object = id.openObject(openMode);
+    OdDgGraphicsElementPtr element = OdDgGraphicsElement::cast( object );
+    if (element.isNull() || element->ownerId() != m_pModel->elementId() )
+        return OdDgGraphicsElementPtr();
+    return element;
+}
+
+/************************************************************************/
+/*                            GetFeature()                              */
+/************************************************************************/
+
+OGRFeature *OGRDGNV8Layer::GetFeature(GIntBig nFID)
+{
+    OdDgGraphicsElementPtr element = GetFeatureInternal(nFID, OdDg::kForRead);
+    if( element.isNull() )
+        return NULL;
+    std::vector<tPairFeatureHoleFlag> oVector = ProcessElement(element);
+    // Only return a feature if and only if we have a single element
+    if( oVector.empty() )
+        return NULL;
+    if( oVector.size() > 1 )
+    {
+        for( size_t i = 0; i < oVector.size(); i++ )
+            delete oVector[i].first;
+        return NULL;
+    }
+    return oVector[0].first;
+}
+
+/************************************************************************/
+/*                          DeleteFeature()                             */
+/************************************************************************/
+
+OGRErr OGRDGNV8Layer::DeleteFeature(GIntBig nFID)
+{
+    if( !m_poDS->GetUpdate() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to delete feature on read-only DGN file." );
+        return OGRERR_FAILURE;
+    }
+
+    OdDgGraphicsElementPtr element = GetFeatureInternal(nFID,
+                                                        OdDg::kForWrite);
+    if( element.isNull() )
+        return OGRERR_FAILURE;
+    try
+    {
+        element->erase(true);
+    }
+    catch (const OdError& e)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Teigha DGN error occurred: %s",
+                 ToUTF8(e.description()).c_str());
+        return OGRERR_FAILURE;
+    }
+    catch (const std::exception &exc)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "std::exception occurred: %s", exc.what());
+        return OGRERR_FAILURE;
+    }
+    catch (...)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unknown exception occurred");
+        return OGRERR_FAILURE;
+    }
+    m_poDS->SetModified();
+    return OGRERR_NONE;
+}
+
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr OGRDGNV8Layer::GetExtent( OGREnvelope *psExtent, int bForce )
+{
+    OdDgModel::StorageUnitDescription description;
+    m_pModel->getStorageUnit( description );
+    OdDgElementIteratorPtr iterator =
+                        m_pModel->createGraphicsElementsIterator();
+    bool bValid = false;
+    while( true )
+    {
+        if( iterator.isNull() || iterator->done() )
+            break;
+        OdRxObjectPtr object = iterator->item().openObject();
+        iterator->step();
+        OdDgGraphicsElementPtr element = OdDgGraphicsElement::cast( object );
+        if (element.isNull())
+            continue;
+        OdDgGraphicsElementPEPtr pElementPE =
+            OdDgGraphicsElementPEPtr(OdRxObjectPtr(element));
+        if( pElementPE.isNull() )
+            continue;
+        OdGeExtents3d savedExtent;
+        if( pElementPE->getRange( element, savedExtent ) == eOk )
+        {
+            OdGePoint3d min = savedExtent.minPoint();
+            OdGePoint3d max = savedExtent.maxPoint();
+            if( !bValid )
+            {
+                psExtent->MinX = min.x / description.m_uorPerStorageUnit;
+                psExtent->MinY = min.y / description.m_uorPerStorageUnit;
+                psExtent->MaxX = max.x / description.m_uorPerStorageUnit;
+                psExtent->MaxY = max.y / description.m_uorPerStorageUnit;
+                bValid = true;
+            }
+            else
+            {
+                psExtent->MinX = std::min(psExtent->MinX,
+                    min.x / description.m_uorPerStorageUnit);
+                psExtent->MinY = std::min(psExtent->MinY,
+                    min.y / description.m_uorPerStorageUnit);
+                psExtent->MaxX = std::max(psExtent->MaxX,
+                    max.x / description.m_uorPerStorageUnit);
+                psExtent->MaxY = std::max(psExtent->MaxY,
+                    max.y / description.m_uorPerStorageUnit);
+            }
+        }
+    }
+    if( bValid )
+        return OGRERR_NONE;
+    return OGRLayer::GetExtent(psExtent, bForce);
+}
+
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRDGNV8Layer::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,OLCRandomRead) )
+        return TRUE;
+    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+        return TRUE;
+    else if( EQUAL(pszCap,OLCSequentialWrite) ||
+             EQUAL(pszCap,OLCDeleteFeature) )
+        return m_poDS->GetUpdate();
+    else if( EQUAL(pszCap,OLCCurveGeometries) )
+        return TRUE;
+
+    return FALSE;
+}
+
+
+/************************************************************************/
+/*                           ICreateFeature()                            */
+/*                                                                      */
+/*      Create a new feature and write to file.                         */
+/************************************************************************/
+
+OGRErr OGRDGNV8Layer::ICreateFeature( OGRFeature *poFeature )
+
+{
+    if( !m_poDS->GetUpdate() )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Attempt to create feature on read-only DGN file." );
+        return OGRERR_FAILURE;
+    }
+
+    if( poFeature->GetGeometryRef() == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Features with empty, geometry collection geometries not "
+                  "supported in DGN format." );
+        return OGRERR_FAILURE;
+    }
+
+    try
+    {
+        OdDgGraphicsElementPtr element = CreateGraphicsElement(
+                                poFeature, poFeature->GetGeometryRef() );
+        if( element.isNull() )
+            return OGRERR_FAILURE;
+        m_pModel->addElement(element);
+        poFeature->SetFID(
+            static_cast<GIntBig>(
+                static_cast<OdUInt64>(element->elementId().getHandle()) ) );
+    }
+    catch (const OdError& e)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Teigha DGN error occurred: %s",
+                 ToUTF8(e.description()).c_str());
+        return OGRERR_FAILURE;
+    }
+    catch (const std::exception &exc)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "std::exception occurred: %s", exc.what());
+        return OGRERR_FAILURE;
+    }
+    catch (...)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unknown exception occurred");
+        return OGRERR_FAILURE;
+    }
+
+    m_poDS->SetModified();
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                              GetTool()                               */
+/************************************************************************/
+
+static OGRStyleTool* GetTool( OGRFeature* poFeature, OGRSTClassId eClassId )
+{
+
+    OGRStyleMgr oMgr;
+    oMgr.InitFromFeature( poFeature );
+    for( int i=0; i<oMgr.GetPartCount(); i++)
+    {
+        OGRStyleTool* poTool = oMgr.GetPart( i );
+        if( poTool == NULL || poTool->GetType() != eClassId)
+        {
+            delete poTool;
+        }
+        else
+        {
+            return poTool;
+        }
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                           TranslateLabel()                           */
+/************************************************************************/
+
+OdDgGraphicsElementPtr OGRDGNV8Layer::TranslateLabel(
+                                    OGRFeature *poFeature, OGRPoint *poPoint )
+
+{
+    const char *pszText = poFeature->GetFieldAsString( "Text" );
+
+    OGRStyleLabel *poLabel = static_cast<OGRStyleLabel*>(
+                                            GetTool(poFeature, OGRSTCLabel));
+
+    OdDgText2dPtr text = OdDgText2d::createObject();
+    OdGePoint2d point;
+    point.x = poPoint->getX();
+    point.y = poPoint->getY();
+    text->setOrigin(point);
+
+    double dfHeightMultiplier = 1.0;
+    if( poLabel != NULL )
+    {
+        GBool bDefault;
+
+        if( poLabel->TextString(bDefault) != NULL && !bDefault )
+            pszText = poLabel->TextString(bDefault);
+
+        const double dfRotation = poLabel->Angle(bDefault);
+        text->setRotation(dfRotation * DEG_TO_RAD);
+
+        poLabel->SetUnit(OGRSTUMM);
+        double dfVal = poLabel->Size( bDefault );
+        if( !bDefault  )
+            dfHeightMultiplier = dfVal/1000.0;
+
+        /* get font id */
+        const char *pszFontName = poLabel->FontName( bDefault );
+        if( !bDefault && pszFontName != NULL )
+        {
+            OdDgFontTablePtr pFontTable =
+                m_pModel->database()->getFontTable(OdDg::kForRead);
+            OdDgElementId idFont = pFontTable->getAt( 
+                            OGRDGNV8DataSource::FromUTF8(pszFontName) );
+            if( !idFont.isNull() )
+            {
+                OdDgFontTableRecordPtr pFont =
+                    idFont.openObject(OdDg::kForRead);
+                OdUInt32 uFontEntryId = pFont->getNumber();
+                text->setFontEntryId(uFontEntryId);
+            }
+        }
+
+        int nAnchor = poLabel->Anchor(bDefault);
+        if( !bDefault )
+            text->setJustification( GetAnchorPositionFromOGR( nAnchor ) );
+    }
+
+    text->setHeightMultiplier( dfHeightMultiplier );
+    text->setLengthMultiplier( text->getHeightMultiplier() ); // FIXME ??
+    text->setText( OGRDGNV8DataSource::FromUTF8(pszText) );
+
+    if( poLabel )
+        delete poLabel;
+    return text;
+}
+
+/************************************************************************/
+/*                       GetColorFromString()                           */
+/************************************************************************/
+
+int OGRDGNV8Layer::GetColorFromString(const char* pszColor)
+{
+    unsigned int nRed = 0;
+    unsigned int nGreen = 0;
+    unsigned int nBlue = 0;
+    const int nCount =
+        sscanf(pszColor, "#%2x%2x%2x", &nRed, &nGreen, &nBlue);
+    if( nCount == 3 )
+    {
+        OdUInt32 nIdx = OdDgColorTable::getColorIndexByRGB(
+            m_poDS->GetDb(), ODRGB( nRed, nGreen ,nBlue ) );
+        return static_cast<int>(nIdx);
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+/************************************************************************/
+/*                       AttachFillLinkage()                            */
+/************************************************************************/
+
+void OGRDGNV8Layer::AttachFillLinkage( OGRFeature* poFeature,
+                                       OdDgGraphicsElementPtr element )
+{
+    const char* pszStyle = poFeature->GetStyleString();
+    if( pszStyle != NULL && strstr(pszStyle, "BRUSH") != NULL )
+    {
+        OGRStyleBrush* poBrush = static_cast<OGRStyleBrush*>(
+                                            GetTool(poFeature, OGRSTCBrush));
+        if( poBrush != NULL )
+        {
+            GBool bDefault;
+            const char* pszColor = poBrush->ForeColor(bDefault);
+            if( pszColor && !bDefault )
+            {
+                const int nIdx = GetColorFromString(pszColor);
+                if( nIdx >= 0 )
+                {
+                    OdDgFillColorLinkagePtr fillColor =
+                            OdDgFillColorLinkage::createObject();
+                    fillColor->setColorIndex( nIdx );
+                    element->addLinkage( fillColor->getPrimaryId(),
+                                         fillColor.get() );
+                }
+            }
+                
+            delete poBrush;
+        }
+    }
+}
+
+/************************************************************************/
+/*                       AttachCommonAttributes()                       */
+/************************************************************************/
+
+void OGRDGNV8Layer::AttachCommonAttributes( OGRFeature *poFeature,
+                                            OdDgGraphicsElementPtr element )
+{
+    const int nLevel = poFeature->GetFieldAsInteger( "Level" );
+    const int nGraphicGroup = poFeature->GetFieldAsInteger( "GraphicGroup" );
+    const int nWeight = poFeature->GetFieldAsInteger( "Weight" );
+    const int nStyle = poFeature->GetFieldAsInteger( "Style" );
+    
+    element->setLevelEntryId(nLevel);
+    element->setGraphicsGroupEntryId(nGraphicGroup);
+    
+    const int nColorIndexField = poFeature->GetFieldIndex("ColorIndex");
+    if( poFeature->IsFieldSetAndNotNull(nColorIndexField) )
+    {
+        const int nColor = poFeature->GetFieldAsInteger(nColorIndexField);
+        element->setColorIndex(nColor);
+    }
+    else
+    {
+        const char* pszStyle = poFeature->GetStyleString();
+        if( pszStyle != NULL && strstr(pszStyle, "PEN") != NULL )
+        {
+            OGRStylePen* poPen = static_cast<OGRStylePen*>(
+                                            GetTool(poFeature, OGRSTCPen));
+            if( poPen != NULL )
+            {
+                GBool bDefault;
+                const char* pszColor = poPen->Color(bDefault);
+                if( pszColor && !bDefault )
+                {
+                    const int nIdx = GetColorFromString(pszColor);
+                    if( nIdx >= 0 )
+                    {
+                        element->setColorIndex(nIdx);
+                    }
+                }
+                delete poPen;
+            }
+        }
+        else if( pszStyle != NULL && strstr(pszStyle, "LABEL") != NULL )
+        {
+            OGRStyleLabel *poLabel = static_cast<OGRStyleLabel*>(
+                                            GetTool(poFeature, OGRSTCLabel));
+            if( poLabel != NULL )
+            {
+                GBool bDefault;
+                const char* pszColor = poLabel->ForeColor(bDefault);
+                if( pszColor && !bDefault )
+                {
+                    const int nIdx = GetColorFromString(pszColor);
+                    if( nIdx >= 0 )
+                    {
+                        element->setColorIndex(nIdx);
+                    }
+                }
+
+                delete poLabel;
+            }
+        }
+    }
+
+    element->setLineStyleEntryId(nStyle);
+    element->setLineWeight(nWeight);
+}
+
+/************************************************************************/
+/*                          AddToComplexCurve()                         */
+/************************************************************************/
+
+void OGRDGNV8Layer::AddToComplexCurve( OGRFeature* poFeature,
+                                       OGRCircularString* poCS,
+                                       OdDgComplexCurvePtr complexCurve )
+{
+    for( int i = 0; i + 2 < poCS->getNumPoints(); i+= 2 )
+    {
+        double R, cx, cy;
+        double alpha0, alpha1, alpha2;
+        if( OGRGeometryFactory::GetCurveParmeters(
+                poCS->getX(i),
+                poCS->getY(i),
+                poCS->getX(i+1),
+                poCS->getY(i+1),
+                poCS->getX(i+2),
+                poCS->getY(i+2),
+                R, cx, cy, alpha0, alpha1, alpha2) )
+        {
+            OdDgArc2dPtr arc = OdDgArc2d::createObject();
+            arc->setPrimaryAxis(R);
+            arc->setSecondaryAxis(R);
+            OdGePoint2d point;
+            point.x = cx;
+            point.y = cy;
+            arc->setOrigin(point);
+            arc->setStartAngle(alpha0); // already in radians
+            arc->setSweepAngle(alpha2 - alpha0);
+            AttachCommonAttributes(poFeature, arc);
+            complexCurve->add(arc);
+        }
+    }
+}
+
+/************************************************************************/
+/*                         AddToComplexCurve()                          */
+/************************************************************************/
+
+void OGRDGNV8Layer::AddToComplexCurve( OGRFeature* poFeature,
+                                       OGRCompoundCurve* poCC,
+                                       OdDgComplexCurvePtr complexCurve )
+{
+    for( int iCurve = 0; iCurve < poCC->getNumCurves(); ++iCurve )
+    {
+        OGRCurve* poCurve = poCC->getCurve(iCurve);
+        OGRwkbGeometryType eType = wkbFlatten(poCurve->getGeometryType());
+        if( eType == wkbLineString || OGR_GT_HasZ(eType) )
+        {
+            complexCurve->add( CreateGraphicsElement(poFeature, poCurve) );
+        }
+        else if( eType == wkbCircularString )
+        {
+            OGRCircularString* poCS = static_cast<OGRCircularString*>(poCurve);
+            AddToComplexCurve(poFeature, poCS, complexCurve);
+        }
+        else
+        {
+            CPLAssert(false);
+        }
+    }
+}
+
+/************************************************************************/
+/*                        CreateShapeFromLS()                           */
+/************************************************************************/
+
+static
+OdDgGraphicsElementPtr CreateShapeFromLS( OGRLineString* poLS,
+                                          bool bHbit = false )
+{
+    if( OGR_GT_HasZ(poLS->getGeometryType()) )
+    {
+        OdDgShape3dPtr shape = OdDgShape3d::createObject();
+        for( int i = 0; i < poLS->getNumPoints(); i++ )
+        {
+            OGRPoint ogrPoint;
+            OdGePoint3d point;
+            poLS->getPoint(i, &ogrPoint);
+            point.x = ogrPoint.getX();
+            point.y = ogrPoint.getY();
+            point.z = ogrPoint.getZ();
+            shape->addVertex(point);
+        }
+        shape->setHbitFlag(bHbit);
+        return shape;
+    }
+    else
+    {
+        OdDgShape2dPtr shape = OdDgShape2d::createObject();
+        for( int i = 0; i < poLS->getNumPoints(); i++ )
+        {
+            OGRPoint ogrPoint;
+            OdGePoint2d point;
+            poLS->getPoint(i, &ogrPoint);
+            point.x = ogrPoint.getX();
+            point.y = ogrPoint.getY();
+            shape->addVertex(point);
+        }
+        shape->setHbitFlag(bHbit);
+        return shape;
+    }
+}
+
+/************************************************************************/
+/*                           CreateShape()                              */
+/************************************************************************/
+
+OdDgGraphicsElementPtr OGRDGNV8Layer::CreateShape( OGRFeature* poFeature,
+                                                   OGRCurve* poCurve,
+                                                   bool bIsHole )
+{
+    OdDgGraphicsElementPtr element;
+    OGRwkbGeometryType eType = wkbFlatten(poCurve->getGeometryType());
+    if( eType == wkbLineString )
+    {
+        OGRLineString* poLS = static_cast<OGRLineString*>(poCurve);
+        element = CreateShapeFromLS(poLS, bIsHole);
+    }
+    else if( eType == wkbCircularString )
+    {
+        OdDgComplexShapePtr complexShape = OdDgComplexShape::createObject();
+        complexShape->setHbitFlag(bIsHole);
+        OGRCircularString* poCS = static_cast<OGRCircularString*>(poCurve);
+        AddToComplexCurve(poFeature, poCS, complexShape);
+        element = complexShape;
+    }
+    else if( eType == wkbCompoundCurve )
+    {
+        OdDgComplexShapePtr complexShape = OdDgComplexShape::createObject();
+        complexShape->setHbitFlag(bIsHole);
+        OGRCompoundCurve* poCC = static_cast<OGRCompoundCurve*>(poCurve);
+        AddToComplexCurve( poFeature, poCC, complexShape );
+        element = complexShape;
+    }
+    
+    if( !bIsHole )
+        AttachFillLinkage( poFeature, element );
+
+    return element;
+}
+
+/************************************************************************/
+/*                           IsFullCircle()                             */
+/************************************************************************/
+
+static bool IsFullCircle( OGRCircularString* poCS,
+                          double& cx, double& cy,
+                          double& R )
+{
+    if( poCS->getNumPoints() == 3 && poCS->get_IsClosed() )
+    {
+        const double x0 = poCS->getX(0);
+        const double y0 = poCS->getY(0);
+        const double x1 = poCS->getX(1);
+        const double y1 = poCS->getY(1);
+        cx = (x0 + x1) / 2;
+        cy = (y0 + y1) / 2;
+        R = sqrt((x1 - cx) * (x1 - cx) + (y1 - cy) * (y1 - cy));
+        return true;
+    }
+    // Full circle defined by 2 arcs?
+    else if( poCS->getNumPoints() == 5 && poCS->get_IsClosed() )
+    {
+        double R_1 = 0.0;
+        double cx_1 = 0.0;
+        double cy_1 = 0.0;
+        double alpha0_1 = 0.0;
+        double alpha1_1 = 0.0;
+        double alpha2_1 = 0.0;
+        double R_2 = 0.0;
+        double cx_2 = 0.0;
+        double cy_2 = 0.0;
+        double alpha0_2 = 0.0;
+        double alpha1_2 = 0.0;
+        double alpha2_2 = 0.0;
+        if( OGRGeometryFactory::GetCurveParmeters(
+                poCS->getX(0), poCS->getY(0),
+                poCS->getX(1), poCS->getY(1),
+                poCS->getX(2), poCS->getY(2),
+                R_1, cx_1, cy_1, alpha0_1, alpha1_1, alpha2_1) &&
+            OGRGeometryFactory::GetCurveParmeters(
+                poCS->getX(2), poCS->getY(2),
+                poCS->getX(3), poCS->getY(3),
+                poCS->getX(4), poCS->getY(4),
+                R_2, cx_2, cy_2, alpha0_2, alpha1_2, alpha2_2) &&
+            AlmostEqual(R_1,R_2) &&
+            AlmostEqual(cx_1,cx_2) &&
+            AlmostEqual(cy_1,cy_2) &&
+            (alpha2_1 - alpha0_1) * (alpha2_2 - alpha0_2) > 0 )
+        {
+            cx = cx_1;
+            cy = cy_1;
+            R = R_1;
+            return true;
+        }
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                       CreateGraphicsElement()                        */
+/*                                                                      */
+/*      Create an element or element group from a given geometry and    */
+/*      the given feature.  This method recurses to handle              */
+/*      collections as essentially independent features.                */
+/************************************************************************/
+
+OdDgGraphicsElementPtr OGRDGNV8Layer::CreateGraphicsElement(
+                                             OGRFeature *poFeature,
+                                             OGRGeometry *poGeom)
+
+{
+    const OGRwkbGeometryType eType = poGeom->getGeometryType();
+    const OGRwkbGeometryType eFType = wkbFlatten(eType);
+
+    const int nType = poFeature->GetFieldAsInteger( "Type" );
+
+    OdDgGraphicsElementPtr element;
+
+    if( eFType == wkbPoint )
+    {
+        OGRPoint *poPoint = static_cast<OGRPoint *>( poGeom );
+        const char *pszText = poFeature->GetFieldAsString("Text");
+        const char *pszStyle = poFeature->GetStyleString();
+
+        if( (pszText == NULL || pszText[0] == 0)
+            && (pszStyle == NULL || strstr(pszStyle,"LABEL") == NULL) )
+        {
+            if( OGR_GT_HasZ(eType) )
+            {
+                OdDgLine3dPtr line = OdDgLine3d::createObject();
+                element = line;
+                OdGePoint3d point;
+                point.x = poPoint->getX();
+                point.y = poPoint->getY();
+                point.z = poPoint->getZ();
+                line->setStartPoint(point);
+                line->setEndPoint(point);
+            }
+            else
+            {
+                OdDgLine2dPtr line = OdDgLine2d::createObject();
+                element = line;
+                OdGePoint2d point;
+                point.x = poPoint->getX();
+                point.y = poPoint->getY();
+                line->setStartPoint(point);
+                line->setEndPoint(point);
+            }
+        }
+        else
+        {
+            element = TranslateLabel( poFeature, poPoint );
+        }
+    }
+    else if( eFType == wkbLineString )
+    {
+        OGRLineString* poLS = static_cast<OGRLineString *>( poGeom );
+        if( poLS->getNumPoints() == 2 &&
+            (nType == 0 || nType == OdDgElement::kTypeLine) )
+        {
+            if( OGR_GT_HasZ(eType) )
+            {
+                OdDgLine3dPtr line = OdDgLine3d::createObject();
+                element = line;
+                OGRPoint ogrPoint;
+                OdGePoint3d point;
+                poLS->getPoint(0, &ogrPoint);
+                point.x = ogrPoint.getX();
+                point.y = ogrPoint.getY();
+                point.z = ogrPoint.getZ();
+                line->setStartPoint(point);
+                poLS->getPoint(1, &ogrPoint);
+                point.x = ogrPoint.getX();
+                point.y = ogrPoint.getY();
+                point.z = ogrPoint.getZ();
+                line->setEndPoint(point);
+            }
+            else
+            {
+                OdDgLine2dPtr line = OdDgLine2d::createObject();
+                element = line;
+                OGRPoint ogrPoint;
+                OdGePoint2d point;
+                poLS->getPoint(0, &ogrPoint);
+                point.x = ogrPoint.getX();
+                point.y = ogrPoint.getY();
+                line->setStartPoint(point);
+                poLS->getPoint(1, &ogrPoint);
+                point.x = ogrPoint.getX();
+                point.y = ogrPoint.getY();
+                line->setEndPoint(point);
+            }
+        }
+        else
+        {
+            if( OGR_GT_HasZ(eType) )
+            {
+                OdDgLineString3dPtr line = OdDgLineString3d::createObject();
+                element = line;
+                for( int i = 0; i < poLS->getNumPoints(); i++ )
+                {
+                    OGRPoint ogrPoint;
+                    OdGePoint3d point;
+                    poLS->getPoint(i, &ogrPoint);
+                    point.x = ogrPoint.getX();
+                    point.y = ogrPoint.getY();
+                    point.z = ogrPoint.getZ();
+                    line->addVertex(point);
+                }
+            }
+            else
+            {
+                OdDgLineString2dPtr line = OdDgLineString2d::createObject();
+                element = line;
+                for( int i = 0; i < poLS->getNumPoints(); i++ )
+                {
+                    OGRPoint ogrPoint;
+                    OdGePoint2d point;
+                    poLS->getPoint(i, &ogrPoint);
+                    point.x = ogrPoint.getX();
+                    point.y = ogrPoint.getY();
+                    line->addVertex(point);
+                }
+            }
+        }
+    }
+    else if( eFType == wkbCircularString )
+    {
+        OGRCircularString* poCS = static_cast<OGRCircularString*>(poGeom);
+        double R, cx, cy;
+        if( IsFullCircle(poCS, cx, cy, R) && !OGR_GT_HasZ(eType) )
+        {
+            OdDgEllipse2dPtr ellipse = OdDgEllipse2d::createObject();
+            element = ellipse;
+            ellipse->setPrimaryAxis(R);
+            ellipse->setSecondaryAxis(R);
+            OdGePoint2d point;
+            point.x = cx;
+            point.y = cy;
+            ellipse->setOrigin(point);
+        }
+        else if( poCS->getNumPoints() == 3 && !OGR_GT_HasZ(eType) )
+        {
+            double alpha0, alpha1, alpha2;
+            if( OGRGeometryFactory::GetCurveParmeters(
+                    poCS->getX(0),
+                    poCS->getY(0),
+                    poCS->getX(1),
+                    poCS->getY(1),
+                    poCS->getX(2),
+                    poCS->getY(2),
+                    R, cx, cy, alpha0, alpha1, alpha2) )
+            {
+                OdDgArc2dPtr arc = OdDgArc2d::createObject();
+                element = arc;
+                arc->setPrimaryAxis(R);
+                arc->setSecondaryAxis(R);
+                OdGePoint2d point;
+                point.x = cx;
+                point.y = cy;
+                arc->setOrigin(point);
+                arc->setStartAngle(alpha0); // already in radians
+                arc->setSweepAngle(alpha2 - alpha0);
+            }
+        }
+        else if( !OGR_GT_HasZ(eType) )
+        {
+            OdDgComplexCurvePtr complexCurve =
+                            OdDgComplexString::createObject();
+            element = complexCurve;
+            AddToComplexCurve(poFeature, poCS, complexCurve);
+        }
+
+        if( element.isNull() )
+        {
+            OGRGeometry* poLS =
+                OGRGeometryFactory::forceToLineString( poGeom->clone() );
+            element = CreateGraphicsElement(poFeature, poLS);
+            delete poLS;
+            return element;
+        }
+    }
+    else if( eFType == wkbCompoundCurve )
+    {
+        OGRCompoundCurve* poCC = static_cast<OGRCompoundCurve*>(poGeom);
+        OdDgComplexCurvePtr complexCurve = OdDgComplexString::createObject();
+        element = complexCurve;
+        AddToComplexCurve( poFeature, poCC, complexCurve );
+    }
+    else if( eFType == wkbCurvePolygon || eFType == wkbPolygon )
+    {
+        OGRCurvePolygon* poPoly = static_cast<OGRCurvePolygon*>(poGeom);
+        if( poPoly->getNumInteriorRings() == 0 &&
+            poPoly->getExteriorRingCurve() == NULL )
+        {
+            if( OGR_GT_HasZ(eType) )
+            {
+                element = OdDgShape3d::createObject();
+            }
+            else
+            {
+                element = OdDgShape2d::createObject();
+            }
+        }
+        else if( poPoly->getNumInteriorRings() == 0 )
+        {
+            element = CreateShape(poFeature, poPoly->getExteriorRingCurve());
+        }
+        else
+        {
+            if( OGR_GT_HasZ(eType) )
+            {
+                OdDgCellHeader3dPtr pCell = OdDgCellHeader3d::createObject(); 
+                element = pCell;
+                for( int iRing = -1;
+                         iRing < poPoly->getNumInteriorRings(); iRing++ )
+                {
+                    OGRCurve* poCurve = (iRing < 0 ) ?
+                            poPoly->getExteriorRingCurve() :
+                           poPoly->getInteriorRingCurve(iRing);
+                                                         
+                    OdDgGraphicsElementPtr shape = CreateShape(
+                        poFeature, poCurve, iRing >= 0);
+                    AttachCommonAttributes(poFeature, shape);
+                    pCell->add(shape);
+                }
+            }
+            else
+            {
+                OdDgCellHeader2dPtr pCell = OdDgCellHeader2d::createObject(); 
+                element = pCell;
+                for( int iRing = -1;
+                         iRing < poPoly->getNumInteriorRings(); iRing++ )
+                {
+                    OGRCurve* poCurve = (iRing < 0 ) ?
+                            poPoly->getExteriorRingCurve() :
+                           poPoly->getInteriorRingCurve(iRing);
+
+                    OdDgGraphicsElementPtr shape = CreateShape(
+                        poFeature, poCurve, iRing >= 0);
+                    AttachCommonAttributes(poFeature, shape);
+                    pCell->add(shape);
+                }
+            }
+            AttachFillLinkage( poFeature, element );
+        }
+    }
+    else if( OGR_GT_IsSubClassOf( eFType, wkbGeometryCollection ) )
+    {
+        OGRGeometryCollection* poGC =
+                static_cast<OGRGeometryCollection*>(poGeom);
+        OdDgCellHeader2dPtr pCell = OdDgCellHeader2d::createObject(); 
+        element = pCell;
+        for( int i = 0; i < poGC->getNumGeometries(); ++i )
+        {
+            pCell->add(CreateGraphicsElement( poFeature,
+                                              poGC->getGeometryRef(i) ));
+        }
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Unsupported geometry type (%s) for DGN.",
+                  OGRGeometryTypeToName( eType ) );
+    }
+
+    if( !element.isNull() )
+        AttachCommonAttributes(poFeature, element);
+
+    return element;
+}
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp
index 3b7cf2c..7f00b7a 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_blockmap.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdwg_blockmap.cpp 22011 2011-03-22 20:13:38Z warmerdam $
  *
  * Project:  DWG Translator
  * Purpose:  Implements BlockMap reading and management portion of
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrdwg_blockmap.cpp 22011 2011-03-22 20:13:38Z warmerdam $");
+CPL_CVSID("$Id: ogrdwg_blockmap.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                          ReadBlockSection()                          */
@@ -71,7 +70,7 @@ void OGRDWGDataSource::ReadBlocksSection()
         // We aggregate the geometries of the features into a multi-geometry,
         // but throw away other stuff attached to the features.
 
-        OGRFeature *poFeature;
+        OGRFeature *poFeature = NULL;
         OGRGeometryCollection *poColl = new OGRGeometryCollection();
         std::vector<OGRFeature*> apoFeatures;
 
@@ -95,7 +94,7 @@ void OGRDWGDataSource::ReadBlocksSection()
         else
             oBlockMap[osBlockName].poGeometry = SimplifyBlockGeometry(poColl);
 
-        if( apoFeatures.size() > 0 )
+        if( !apoFeatures.empty() )
             oBlockMap[osBlockName].apoFeatures = apoFeatures;
     }
 
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp
index b5194ee..7d82b91 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_dimension.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $
  *
  * Project:  DWG Translator
  * Purpose:  Implements translation support for DIMENSION elements as a part
@@ -31,11 +30,7 @@
 #include "ogr_dwg.h"
 #include "cpl_conv.h"
 
-#include "DbDimension.h"
-#include "DbRotatedDimension.h"
-#include "DbAlignedDimension.h"
-
-CPL_CVSID("$Id: ogrdxf_dimension.cpp 19643 2010-05-08 21:56:18Z rouault $");
+CPL_CVSID("$Id: ogrdwg_dimension.cpp 37946 2017-04-10 14:37:01Z rouault $");
 
 /************************************************************************/
 /*                         TranslateDIMENSION()                         */
@@ -174,9 +169,7 @@ the approach is as above in all these cases.
 /* -------------------------------------------------------------------- */
 /*      Compute the text angle.                                         */
 /* -------------------------------------------------------------------- */
-    double dfAngle = 0.0;
-
-    dfAngle = atan2(dfVec2Y,dfVec2X) * 180.0 / M_PI;
+    double dfAngle = atan2(dfVec2Y,dfVec2X) * 180.0 / M_PI;
 
 /* -------------------------------------------------------------------- */
 /*      Rescale the direction vectors so we can use them in             */
@@ -292,7 +285,7 @@ the approach is as above in all these cases.
 /*      feature for the next feature read.                              */
 /* -------------------------------------------------------------------- */
 
-    // a single space suppresses labelling.
+    // a single space suppresses labeling.
     if( osText == " " )
         return poFeature;
 
@@ -301,7 +294,7 @@ the approach is as above in all these cases.
     poLabelFeature->SetGeometryDirectly( new OGRPoint( oTextPos.x, oTextPos.y ) );
 
     // Do we need to compute the dimension value?
-    if( osText.size() == 0 )
+    if( osText.empty() )
     {
         FormatDimension( osText, POINT_DIST( oArrow1.x, oArrow1.y,
                                              dfArrowX2, dfArrowY2 ) );
@@ -309,7 +302,7 @@ the approach is as above in all these cases.
 
     CPLString osStyle;
     char szBuffer[64];
-    char* pszComma;
+    char* pszComma = NULL;
 
     osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",p:5",osText.c_str());
 
@@ -369,7 +362,7 @@ void OGRDWGLayer::FormatDimension( CPLString &osText, double dfValue )
     // to spend the effort.  See QCAD's rs_dimlinear.cpp and related files
     // for example.
 
-    sprintf(szFormat, "%%.%df", nPrecision );
+    snprintf(szFormat, sizeof(szFormat), "%%.%df", nPrecision );
     CPLsnprintf(szBuffer, sizeof(szBuffer), szFormat, dfValue);
     char* pszComma = strchr(szBuffer, ',');
     if (pszComma)
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp b/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
index cf346f8..81f3f38 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwg_hatch.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdwg_hatch.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DWG Translator
  * Purpose:  Implements translation support for HATCH elements as part
@@ -32,17 +31,9 @@
 #include "cpl_conv.h"
 #include "ogr_api.h"
 
-#include "DbHatch.h"
-
 #include "ogrdxf_polyline_smooth.h"
 
-#include "Ge/GePoint2dArray.h"
-#include "Ge/GeCurve2d.h"
-#include "Ge/GeCircArc2d.h"
-#include "Ge/GeEllipArc2d.h"
-
-CPL_CVSID("$Id: ogrdwg_hatch.cpp 33713 2016-03-12 17:41:57Z goatbar $");
-
+CPL_CVSID("$Id: ogrdwg_hatch.cpp 37946 2017-04-10 14:37:01Z rouault $");
 
 static OGRErr DWGCollectBoundaryLoop( OdDbHatchPtr poHatch, int iLoop,
                                       OGRGeometryCollection *poGC );
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp
index 288f0b3..d65df75 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgblockslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdwglayer.cpp 19643 2010-05-08 21:56:18Z rouault $
  *
  * Project:  DWG Translator
  * Purpose:  Implements OGRDWGBlocksLayer class.
@@ -30,7 +29,7 @@
 #include "ogr_dwg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdwglayer.cpp 19643 2010-05-08 21:56:18Z rouault $");
+CPL_CVSID("$Id: ogrdwgblockslayer.cpp 37969 2017-04-12 07:56:18Z rouault $");
 
 /************************************************************************/
 /*                         OGRDWGBlocksLayer()                          */
@@ -38,7 +37,7 @@ CPL_CVSID("$Id: ogrdwglayer.cpp 19643 2010-05-08 21:56:18Z rouault $");
 
 OGRDWGBlocksLayer::OGRDWGBlocksLayer( OGRDWGDataSource *poDSIn ) :
     poDS(poDSIn),
-    poFeatureDefn(new OGRFeatureDefn( "blocks" )),
+    poFeatureDefn(new OGRFeatureDefn( "blocks" ))
 {
     ResetReading();
 
@@ -96,14 +95,15 @@ OGRFeature *OGRDWGBlocksLayer::GetNextUnfilteredFeature()
 /*      Are we done reading the current blocks features?                */
 /* -------------------------------------------------------------------- */
     DWGBlockDefinition *psBlock = &(oIt->second);
-    unsigned int nSubFeatureCount = psBlock->apoFeatures.size();
+    unsigned int nSubFeatureCount = static_cast<unsigned int>(
+        psBlock->apoFeatures.size());
 
     if( psBlock->poGeometry != NULL )
         nSubFeatureCount++;
 
     if( iNextSubFeature >= nSubFeatureCount )
     {
-        oIt++;
+        ++oIt;
 
         iNextSubFeature = 0;
 
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp
index dd2abae..95bf925 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxfdatasource.cpp 22009 2011-03-22 20:01:34Z warmerdam $
  *
  * Project:  DWG Translator
  * Purpose:  Implements OGRDWGDataSource class
@@ -31,23 +30,20 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-#include "DbSymbolTable.h"
-#include "DbLayerTable.h"
-#include "DbLayerTableRecord.h"
-#include "DbLinetypeTable.h"
-#include "DbLinetypeTableRecord.h"
-
-CPL_CVSID("$Id: ogrdxfdatasource.cpp 22009 2011-03-22 20:01:34Z warmerdam $");
+CPL_CVSID("$Id: ogrdwgdatasource.cpp 37968 2017-04-12 07:16:55Z rouault $");
 
 /************************************************************************/
 /*                          OGRDWGDataSource()                          */
 /************************************************************************/
 
 OGRDWGDataSource::OGRDWGDataSource() :
-  fp(NULL)
+  fp(NULL),
+  iEntitiesSectionOffset(0),
+  bInlineBlocks(FALSE),
+  poServices(NULL),
+  poDb(static_cast<const OdRxObject*>(NULL))
 
 {
-    poDb = NULL;
 }
 
 /************************************************************************/
@@ -60,7 +56,7 @@ OGRDWGDataSource::~OGRDWGDataSource()
 /* -------------------------------------------------------------------- */
 /*      Destroy layers.                                                 */
 /* -------------------------------------------------------------------- */
-    while( apoLayers.size() > 0 )
+    while( !apoLayers.empty() )
     {
         delete apoLayers.back();
         apoLayers.pop_back();
@@ -71,7 +67,7 @@ OGRDWGDataSource::~OGRDWGDataSource()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRDWGDataSource::TestCapability( const char * pszCap )
+int OGRDWGDataSource::TestCapability( const char * /*pszCap*/ )
 
 {
     return FALSE;
@@ -81,7 +77,6 @@ int OGRDWGDataSource::TestCapability( const char * pszCap )
 /*                              GetLayer()                              */
 /************************************************************************/
 
-
 OGRLayer *OGRDWGDataSource::GetLayer( int iLayer )
 
 {
@@ -95,18 +90,15 @@ OGRLayer *OGRDWGDataSource::GetLayer( int iLayer )
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRDWGDataSource::Open( OGRDWGServices *poServices,
-                            const char * pszFilename, int bHeaderOnly )
+int OGRDWGDataSource::Open( OGRDWGServices *poServicesIn,
+                            const char * pszFilename, int /*bHeaderOnly*/ )
 
 {
-    if( !EQUAL(CPLGetExtension(pszFilename),"dwg") )
-        return FALSE;
-
-    this->poServices = poServices;
+    poServices = poServicesIn;
 
     osEncoding = CPL_ENC_ISO8859_1;
 
-    osName = pszFilename;
+    m_osName = pszFilename;
 
     bInlineBlocks = CPLTestBool(
         CPLGetConfigOption( "DWG_INLINE_BLOCKS", "TRUE" ) );
@@ -180,9 +172,9 @@ void OGRDWGDataSource::ReadLayerDefinitions()
 
         oLayerProperties["Exists"] = "1";
 
-        OdDbLinetypeTableRecordPtr poLT = poLD->linetypeObjectId().safeOpenObject();
+        OdDbLinetypeTableRecordPtr poLinetypeTableRecord = poLD->linetypeObjectId().safeOpenObject();
         oLayerProperties["Linetype"] =
-            ACTextUnescape(poLT->getName(),GetEncoding());
+            ACTextUnescape(poLinetypeTableRecord->getName(),GetEncoding());
 
         osValue.Printf( "%d", poLD->colorIndex() );
         oLayerProperties["Color"] = osValue;
@@ -364,7 +356,7 @@ void OGRDWGDataSource::AddStandardFields( OGRFeatureDefn *poFeatureDefn )
 
     if( !bInlineBlocks )
     {
-        OGRFieldDefn  oTextField( "BlockName", OFTString );
-        poFeatureDefn->AddFieldDefn( &oTextField );
+        OGRFieldDefn  oBlockNameField( "BlockName", OFTString );
+        poFeatureDefn->AddFieldDefn( &oBlockNameField );
     }
 }
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp b/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
index 7bcbdc2..3ac44ac 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwgdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxfdriver.cpp 18535 2010-01-12 01:40:32Z warmerdam $
  *
  * Project:  DWG Translator
  * Purpose:  Implements OGRDWGDriver.
@@ -29,74 +28,27 @@
 
 #include "ogr_dwg.h"
 #include "cpl_conv.h"
+#include "ogrteigha.h"
 
-CPL_CVSID("$Id: ogrdxfdriver.cpp 18535 2010-01-12 01:40:32Z warmerdam $");
-
-CPL_C_START
-void CPL_DLL RegisterOGRDWG();
-CPL_C_END
+CPL_CVSID("$Id: ogrdwgdriver.cpp 37968 2017-04-12 07:16:55Z rouault $");
 
 /************************************************************************/
 /*                            OGRDWGDriver()                            */
 /************************************************************************/
 
-OGRDWGDriver::OGRDWGDriver()
+OGRDWGDriver::OGRDWGDriver() : poServices(NULL)
 
 {
-    bInitialized = FALSE;
 }
 
 /************************************************************************/
-/*                          ~OGRDWGDriver()                          */
+/*                          ~OGRDWGDriver()                             */
 /************************************************************************/
 
 OGRDWGDriver::~OGRDWGDriver()
 
 {
-    if( bInitialized && !CPLTestBool(
-            CPLGetConfigOption("IN_GDAL_GLOBAL_DESTRUCTOR", "NO")) )
-    {
-        bInitialized = FALSE;
-        odUninitialize();
-    }
-}
-
-/************************************************************************/
-/*                             Initialize()                             */
-/************************************************************************/
-
-void OGRDWGDriver::Initialize()
-
-{
-    if( bInitialized )
-        return;
-
-    bInitialized = TRUE;
-
-    OdGeContext::gErrorFunc = ErrorHandler;
-
-    odInitialize(&oServices);
-    oServices.disableOutput( true );
-
-    /********************************************************************/
-    /* Find the data file and and initialize the character mapper       */
-    /********************************************************************/
-    OdString iniFile = oServices.findFile(OD_T("adinit.dat"));
-    if (!iniFile.isEmpty())
-      OdCharMapper::initialize(iniFile);
-
-}
-
-/************************************************************************/
-/*                            ErrorHandler()                            */
-/************************************************************************/
-
-void OGRDWGDriver::ErrorHandler( OdResult oResult )
-
-{
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "GeError:%s",
-              (const char *) OdError(oResult).description().c_str() );
+    OGRTEIGHADeinitialize();
 }
 
 /************************************************************************/
@@ -113,14 +65,18 @@ const char *OGRDWGDriver::GetName()
 /*                                Open()                                */
 /************************************************************************/
 
-OGRDataSource *OGRDWGDriver::Open( const char * pszFilename, int bUpdate )
+OGRDataSource *OGRDWGDriver::Open( const char * pszFilename, int /*bUpdate*/ )
 
 {
-    Initialize();
+    if( !EQUAL(CPLGetExtension(pszFilename),"dwg") )
+        return NULL;
+
+    if( !OGRTEIGHAInitialize() )
+        return NULL;
 
     OGRDWGDataSource   *poDS = new OGRDWGDataSource();
 
-    if( !poDS->Open( &oServices, pszFilename ) )
+    if( !poDS->Open( OGRDWGGetServices(), pszFilename ) )
     {
         delete poDS;
         poDS = NULL;
@@ -133,7 +89,7 @@ OGRDataSource *OGRDWGDriver::Open( const char * pszFilename, int bUpdate )
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRDWGDriver::TestCapability( const char * pszCap )
+int OGRDWGDriver::TestCapability( const char * /*pszCap*/ )
 
 {
     return FALSE;
diff --git a/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp b/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
index 8ca42b1..ede39de 100644
--- a/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
+++ b/ogr/ogrsf_frmts/dwg/ogrdwglayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdwglayer.cpp 22008 2011-03-22 19:45:20Z warmerdam $
  *
  * Project:  DWG Translator
  * Purpose:  Implements OGRDWGLayer class.
@@ -32,33 +31,16 @@
 
 #include "ogrdxf_polyline_smooth.h"
 
-#include "DbPolyline.h"
-#include "Db2dPolyline.h"
-#include "Db3dPolyline.h"
-#include "Db3dPolylineVertex.h"
-#include "DbLine.h"
-#include "DbPoint.h"
-#include "DbEllipse.h"
-#include "DbArc.h"
-#include "DbMText.h"
-#include "DbText.h"
-#include "DbCircle.h"
-#include "DbSpline.h"
-#include "DbBlockReference.h"
-#include "DbAttribute.h"
-#include "DbFiler.h"
-#include "Ge/GeScale3d.h"
-
-CPL_CVSID("$Id: ogrdwglayer.cpp 22008 2011-03-22 19:45:20Z warmerdam $");
+CPL_CVSID("$Id: ogrdwglayer.cpp 37946 2017-04-10 14:37:01Z rouault $");
 
 /************************************************************************/
 /*                            OGRDWGLayer()                             */
 /************************************************************************/
 
-OGRDWGLayer::OGRDWGLayer( OGRDWGDataSource *poDS )
+OGRDWGLayer::OGRDWGLayer( OGRDWGDataSource *poDSIn )
 
 {
-    this->poDS = poDS;
+    this->poDS = poDSIn;
 
     iNextFID = 0;
 
@@ -86,12 +68,12 @@ OGRDWGLayer::OGRDWGLayer( OGRDWGDataSource *poDS )
 
     for (pBlkIter->start(); ! pBlkIter->done(); pBlkIter->step())
     {
-        poBlock = pBlkIter->getRecordId().safeOpenObject();
+        m_poBlock = pBlkIter->getRecordId().safeOpenObject();
 
-        if( EQUAL(poBlock->getName(),"*Model_Space") )
+        if( EQUAL(m_poBlock->getName(),"*Model_Space") )
             break;
         else
-            poBlock = NULL;
+            m_poBlock = NULL;
     }
 
     ResetReading();
@@ -137,12 +119,11 @@ CPLString OGRDWGLayer::TextUnescape( OdString oString )
 void OGRDWGLayer::SetBlockTable( OdDbBlockTableRecordPtr poNewBlock )
 
 {
-    poBlock = poNewBlock;
+    m_poBlock = poNewBlock;
 
     ResetReading();
 }
 
-
 /************************************************************************/
 /*                        ClearPendingFeatures()                        */
 /************************************************************************/
@@ -167,8 +148,8 @@ void OGRDWGLayer::ResetReading()
     iNextFID = 0;
     ClearPendingFeatures();
 
-    if( !poBlock.isNull() )
-        poEntIter = poBlock->newIterator();
+    if( !m_poBlock.isNull() )
+        poEntIter = m_poBlock->newIterator();
 }
 
 /************************************************************************/
@@ -192,7 +173,6 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
     OdDbHandle oHandle = poEntity->getDbHandle();
     poFeature->SetField( "EntityHandle", (const char *) oHandle.ascii() );
 
-
     if( poEntity->colorIndex() != 256 )
     {
         osValue.Printf( "%d", poEntity->colorIndex() );
@@ -207,7 +187,7 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
 
     while( poClass != NULL )
     {
-        if( osSubClasses.size() > 0 )
+        if( !osSubClasses.empty() )
             osSubClasses = ":" + osSubClasses;
 
         osSubClasses = ((const char *) poClass->name()) + osSubClasses;
@@ -292,14 +272,13 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
             break;
         }
 
-        if( osFullXData.size() > 0 )
+        if( !osFullXData.empty() )
             osFullXData += " ";
         osFullXData += (const char *) osXDataItem;
     }
 
     poFeature->SetField( "ExtendedEntity", osFullXData );
 
-
 #ifdef notdef
       // OCS vector.
       case 210:
@@ -314,7 +293,6 @@ void OGRDWGLayer::TranslateGenericProperties( OGRFeature *poFeature,
         oStyleProperties["230_N.dZ"] = pszValue;
         break;
 
-
       default:
         break;
     }
@@ -437,7 +415,7 @@ OGRFeature *OGRDWGLayer::TranslateMTEXT( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
     CPLString osText = TextUnescape( poMTE->contents() );
 
-    if( osText != "" && osText[osText.size()-1] == '\n' )
+    if( !osText.empty() && osText.back() == '\n' )
         osText.resize( osText.size() - 1 );
 
     poFeature->SetField( "Text", osText );
@@ -487,7 +465,7 @@ OGRFeature *OGRDWGLayer::TranslateMTEXT( OdDbEntityPtr poEntity )
 
     CPLString osStyle;
     char szBuffer[64];
-    char* pszComma;
+    char* pszComma = NULL;
 
     osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
 
@@ -560,7 +538,7 @@ OGRFeature *OGRDWGLayer::TranslateTEXT( OdDbEntityPtr poEntity )
 /* -------------------------------------------------------------------- */
     CPLString osText = TextUnescape( poText->textString() );
 
-    if( osText != "" && osText[osText.size()-1] == '\n' )
+    if( !osText.empty() && osText.back() == '\n' )
         osText.resize( osText.size() - 1 );
 
     poFeature->SetField( "Text", osText );
@@ -619,7 +597,7 @@ OGRFeature *OGRDWGLayer::TranslateTEXT( OdDbEntityPtr poEntity )
 
     CPLString osStyle;
     char szBuffer[64];
-    char* pszComma;
+    char* pszComma = NULL;
 
     osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
 
@@ -961,19 +939,16 @@ OGRFeature *OGRDWGLayer::TranslateARC( OdDbEntityPtr poEntity )
 {
     OdDbArcPtr poAE = OdDbArc::cast( poEntity );
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfRadius = 0.0;
-    double dfStartAngle = 0.0, dfEndAngle = 360.0;
-    OdGePoint3d oCenter;
 
     TranslateGenericProperties( poFeature, poEntity );
 
 /* -------------------------------------------------------------------- */
 /*      Collect parameters.                                             */
 /* -------------------------------------------------------------------- */
-    dfEndAngle = -1 * poAE->startAngle() * 180 / M_PI;
-    dfStartAngle = -1 * poAE->endAngle() * 180 / M_PI;
-    dfRadius = poAE->radius();
-    oCenter = poAE->center();
+    double dfEndAngle = -1 * poAE->startAngle() * 180 / M_PI;
+    double dfStartAngle = -1 * poAE->endAngle() * 180 / M_PI;
+    double dfRadius = poAE->radius();
+    OdGePoint3d oCenter = poAE->center();
 
 /* -------------------------------------------------------------------- */
 /*      Create geometry                                                 */
@@ -1087,7 +1062,6 @@ OGRFeature *OGRDWGLayer::TranslateSPLINE( OdDbEntityPtr poEntity )
 /*                      GeometryInsertTransformer                       */
 /************************************************************************/
 
-
 class GeometryInsertTransformer : public OGRCoordinateTransformation
 {
 public:
@@ -1104,15 +1078,15 @@ public:
     double dfZScale;
     double dfAngle;
 
-    OGRSpatialReference *GetSourceCS() { return NULL; }
-    OGRSpatialReference *GetTargetCS() { return NULL; }
+    OGRSpatialReference *GetSourceCS() override { return NULL; }
+    OGRSpatialReference *GetTargetCS() override { return NULL; }
     int Transform( int nCount,
-                   double *x, double *y, double *z )
+                   double *x, double *y, double *z ) override
         { return TransformEx( nCount, x, y, z, NULL ); }
 
     int TransformEx( int nCount,
                      double *x, double *y, double *z = NULL,
-                     int *pabSuccess = NULL )
+                     int *pabSuccess = NULL ) override
         {
             int i;
             for( i = 0; i < nCount; i++ )
@@ -1121,7 +1095,8 @@ public:
 
                 x[i] *= dfXScale;
                 y[i] *= dfYScale;
-                z[i] *= dfZScale;
+                if( z )
+                    z[i] *= dfZScale;
 
                 dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
                 dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
@@ -1131,7 +1106,8 @@ public:
 
                 x[i] += dfXOffset;
                 y[i] += dfYOffset;
-                z[i] += dfZOffset;
+                if( z )
+                    z[i] += dfZOffset;
 
                 if( pabSuccess )
                     pabSuccess[i] = TRUE;
@@ -1390,7 +1366,6 @@ OGRFeature *OGRDWGLayer::GetNextUnfilteredFeature()
                 poFeature = apoPendingFeatures.front();
                 apoPendingFeatures.pop();
             }
-
         }
         else
         {
diff --git a/ogr/ogrsf_frmts/dwg/ogrteigha.cpp b/ogr/ogrsf_frmts/dwg/ogrteigha.cpp
new file mode 100644
index 0000000..b7b62b4
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrteigha.cpp
@@ -0,0 +1,147 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Common services for DGNv8/DWG drivers
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_multiproc.h"
+
+#include "ogr_dgnv8.h"
+#include "ogr_dwg.h"
+#include "ogrteigha.h"
+
+extern "C" void CPL_DLL RegisterOGRDWG_DGNV8();
+
+extern "C" int CPL_DLL GDALIsInGlobalDestructor();
+
+static CPLMutex* hMutex = NULL;
+static bool bInitialized = false;
+static bool bInitSuccess = false;
+static OdStaticRxObject<OGRDWGServices> oDWGServices;
+static OdStaticRxObject<OGRDGNV8Services> oDGNServices;
+
+/************************************************************************/
+/*                        OGRTEIGHAErrorHandler()                       */
+/************************************************************************/
+
+static void OGRTEIGHAErrorHandler( OdResult oResult )
+
+{
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "GeError:%ls",
+              OdError(oResult).description().c_str() );
+}
+
+/************************************************************************/
+/*                        OGRTEIGHAInitialize()                         */
+/************************************************************************/
+
+bool OGRTEIGHAInitialize()
+{
+    CPLMutexHolderD(&hMutex);
+    if( bInitialized )
+        return bInitSuccess;
+
+    bInitialized = true;
+
+    OdGeContext::gErrorFunc = OGRTEIGHAErrorHandler;
+
+    try
+    {
+        odInitialize(&oDWGServices);
+        oDWGServices.disableOutput( true );
+
+        /********************************************************************/
+        /* Find the data file and and initialize the character mapper       */
+        /********************************************************************/
+        OdString iniFile = oDWGServices.findFile(OD_T("adinit.dat"));
+        if (!iniFile.isEmpty())
+            OdCharMapper::initialize(iniFile);
+
+        odrxInitialize(&oDGNServices);
+        oDGNServices.disableProgressMeterOutput( true );
+
+        ::odrxDynamicLinker()->loadModule(L"TG_Db", false);
+
+        bInitSuccess = true;
+    }
+    catch ( ... )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "An exception occurred in OGRTEIGHAInitialize()");
+    }
+    return bInitSuccess;
+}
+
+/************************************************************************/
+/*                        OGRDWGGetServices()                           */
+/************************************************************************/
+
+OGRDWGServices* OGRDWGGetServices()
+{
+    return &oDWGServices;
+}
+
+/************************************************************************/
+/*                        OGRDGNV8GetServices()                         */
+/************************************************************************/
+
+OGRDGNV8Services* OGRDGNV8GetServices()
+{
+    return &oDGNServices;
+}
+
+/************************************************************************/
+/*                       OGRTEIGHADeinitialize()                        */
+/************************************************************************/
+
+void OGRTEIGHADeinitialize()
+{
+    if( GDALIsInGlobalDestructor()   )
+        return;
+    if( bInitSuccess )
+    {
+        odUninitialize();
+        odrxUninitialize();
+    }
+    bInitialized = false;
+    bInitSuccess = false;
+    if( hMutex != NULL )
+        CPLDestroyMutex(hMutex);
+    hMutex = NULL;
+}
+
+/************************************************************************/
+/*                       RegisterOGRDWG_DGNV8()                         */
+/*                                                                      */
+/* Entry point for the plugin                                           */
+/************************************************************************/
+
+void RegisterOGRDWG_DGNV8()
+
+{
+    RegisterOGRDWG();
+    RegisterOGRDGNV8();
+}
diff --git a/ogr/ogrsf_frmts/dwg/ogrteigha.h b/ogr/ogrsf_frmts/dwg/ogrteigha.h
new file mode 100644
index 0000000..5d8da6a
--- /dev/null
+++ b/ogr/ogrsf_frmts/dwg/ogrteigha.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Common services for DGNv8/DWG drivers
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_TEIGHA_H
+#define OGR_TEIGHA_H
+
+class OGRDWGServices;
+class OGRDGNV8Services;
+
+bool OGRTEIGHAInitialize();
+void OGRTEIGHADeinitialize();
+OGRDWGServices* OGRDWGGetServices();
+OGRDGNV8Services* OGRDGNV8GetServices();
+
+#endif // OGR_TEIGHA_H
diff --git a/ogr/ogrsf_frmts/dxf/intronurbs.cpp b/ogr/ogrsf_frmts/dxf/intronurbs.cpp
index 350e17d..4a56a72 100644
--- a/ogr/ogrsf_frmts/dxf/intronurbs.cpp
+++ b/ogr/ogrsf_frmts/dxf/intronurbs.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  DXF Translator
  * Purpose:  Low level spline interpolation.
@@ -13,7 +12,6 @@ available at:
 
   http://www.nar-associates.com/nurbs/
 
-
 Copyright (c) 2009, David F. Rogers
 All rights reserved.
 
@@ -46,9 +44,42 @@ POSSIBILITY OF SUCH DAMAGE.
 #include <vector>
 #include "cpl_port.h" // in case of -DDEBUG_BOOL
 
+CPL_CVSID("$Id: intronurbs.cpp 37987 2017-04-14 07:42:50Z rouault $");
+
 /* used by ogrdxflayer.cpp */
-void rbspline2(int npts,int k,int p1,double b[],double h[],
-        bool xflag, double x[], double p[]);
+void rbspline2( int npts,int k,int p1,double b[],double h[],
+                bool bCalculateKnots, double x[], double p[] );
+
+/* used by DWG driver */
+void rbspline(int npts,int k,int p1,double b[],double h[], double p[]);
+void rbsplinu(int npts,int k,int p1,double b[],double h[], double p[]);
+
+/************************************************************************/
+/*                               knotu()                                */
+/************************************************************************/
+
+/*  Subroutine to generate a B-spline uniform (periodic) knot vector.
+
+    c            = order of the basis function
+    n            = the number of defining polygon vertices
+    nplus2       = index of x() for the first occurrence of the maximum knot vector value
+    nplusc       = maximum value of the knot vector -- $n + c$
+    x[]          = array containing the knot vector
+*/
+
+static void knotu(int n,int c,double x[])
+
+{
+  int nplusc, /* nplus2, */i;
+
+    nplusc = n + c;
+    /* nplus2 = n + 2; */
+
+    x[1] = 0;
+    for (i = 2; i <= nplusc; i++){
+        x[i] = i-1;
+    }
+}
 
 /************************************************************************/
 /*                                knot()                                */
@@ -65,16 +96,15 @@ void rbspline2(int npts,int k,int p1,double b[],double h[],
     x()          = array containing the knot vector
 */
 
-static void knot(int n,int c,double x[])
+static void knot( int n, int c, double x[] )
 
 {
-    int nplusc,nplus2,i;
-
-    nplusc = n + c;
-    nplus2 = n + 2;
+    const int nplusc = n + c;
+    const int nplus2 = n + 2;
 
     x[1] = 0.0;
-    for (i = 2; i <= nplusc; i++){
+    for( int i = 2; i <= nplusc; i++ )
+    {
         if ( (i > c) && (i < nplus2) )
             x[i] = x[i-1] + 1.0;
         else
@@ -88,19 +118,19 @@ static void knot(int n,int c,double x[])
 
 /*  Subroutine to generate rational B-spline basis functions--open knot vector
 
-	C code for An Introduction to NURBS
-	by David F. Rogers. Copyright (C) 2000 David F. Rogers,
-	All rights reserved.
+        C code for An Introduction to NURBS
+        by David F. Rogers. Copyright (C) 2000 David F. Rogers,
+        All rights reserved.
 
-	Name: rbais
-	Language: C
-	Subroutines called: none
-	Book reference: Chapter 4, Sec. 4. , p 296
+        Name: rbais
+        Language: C
+        Subroutines called: none
+        Book reference: Chapter 4, Sec. 4. , p 296
 
-	c        = order of the B-spline basis function
+    c        = order of the B-spline basis function
     d        = first term of the basis function recursion relation
     e        = second term of the basis function recursion relation
-	h[]	     = array containing the homogeneous weights
+    h[]      = array containing the homogeneous weights
     npts     = number of defining polygon vertices
     nplusc   = constant -- npts + c -- maximum number of knot values
     r[]      = array containing the rationalbasis functions
@@ -110,64 +140,153 @@ static void knot(int n,int c,double x[])
     x[]      = knot vector
 */
 
-static void rbasis(int c,double t,int npts, double x[], double h[], double r[])
+static void rbasis( int c, double t, int npts,
+                    double x[], double h[], double r[] )
 
 {
-    int nplusc;
-    int i,k;
-    double d,e;
-    double sum;
-    std::vector<double> temp;
-
-    nplusc = npts + c;
+    const int nplusc = npts + c;
 
+    std::vector<double> temp;
     temp.resize( nplusc+1 );
 
-/* calculate the first order nonrational basis functions n[i]	*/
+    /* calculate the first order nonrational basis functions n[i] */
 
-    for (i = 1; i<= nplusc-1; i++){
-    	if (( t >= x[i]) && (t < x[i+1]))
+    for( int i = 1; i<= nplusc-1; i++ )
+    {
+        if (( t >= x[i]) && (t < x[i+1]))
             temp[i] = 1.0;
         else
             temp[i] = 0.0;
     }
 
-/* calculate the higher order nonrational basis functions */
+    /* calculate the higher order nonrational basis functions */
 
-    for (k = 2; k <= c; k++){
-    	for (i = 1; i <= nplusc-k; i++){
+    for( int k = 2; k <= c; k++ )
+    {
+        for ( int i = 1; i <= nplusc-k; i++ )
+        {
+            double d = 0.0;
+            double e = 0.0;
             if (temp[i] != 0)    /* if the lower order basis function is zero skip the calculation */
                 d = ((t-x[i])*temp[i])/(x[i+k-1]-x[i]);
-            else
-                d = 0;
+            // else
+            //    d = 0.0 ;
 
-    	    if (temp[i+1] != 0)     /* if the lower order basis function is zero skip the calculation */
+            if (temp[i+1] != 0)     /* if the lower order basis function is zero skip the calculation */
                 e = ((x[i+k]-t)*temp[i+1])/(x[i+k]-x[i+1]);
-            else
-                e = 0;
+            // else
+            //     e = 0.0;
 
-    	    temp[i] = d + e;
+            temp[i] = d + e;
         }
     }
 
-    if (t == (double)x[nplusc]){		/*    pick up last point	*/
+    if (t == (double)x[nplusc]){  /* pick up last point */
         temp[npts] = 1;
     }
 
 /* calculate sum for denominator of rational basis functions */
 
-    sum = 0.;
-    for (i = 1; i <= npts; i++){
+    double sum = 0.0;
+    for( int i = 1; i <= npts; i++ )
+    {
         sum = sum + temp[i]*h[i];
     }
 
 /* form rational basis functions and put in r vector */
 
-    for (i = 1; i <= npts; i++){
-    	if (sum != 0){
-            r[i] = (temp[i]*h[i])/(sum);}
+    for( int i = 1; i <= npts; i++ )
+    {
+        if (sum != 0)
+        {
+            r[i] = (temp[i]*h[i])/(sum);
+        }
         else
+        {
             r[i] = 0;
+        }
+    }
+}
+
+/************************************************************************/
+/*                             rbspline2()                              */
+/************************************************************************/
+
+/*  Subroutine to generate a rational B-spline curve.
+
+    C code for An Introduction to NURBS
+    by David F. Rogers. Copyright (C) 2000 David F. Rogers,
+    All rights reserved.
+
+    Name: rbspline.c
+    Language: C
+    Subroutines called: knot.c, rbasis.c, fmtmul.c
+    Book reference: Chapter 4, Alg. p. 297
+
+    b[]         = array containing the defining polygon vertices
+                  b[1] contains the x-component of the vertex
+                  b[2] contains the y-component of the vertex
+                  b[3] contains the z-component of the vertex
+    h[]         = array containing the homogeneous weighting factors
+    k           = order of the B-spline basis function
+    nbasis      = array containing the basis functions for a single value of t
+    nplusc      = number of knot values
+    npts        = number of defining polygon vertices
+    p[,]        = array containing the curve points
+                  p[1] contains the x-component of the point
+                  p[2] contains the y-component of the point
+                  p[3] contains the z-component of the point
+    p1          = number of points to be calculated on the curve
+    t           = parameter value 0 <= t <= npts - k + 1
+    bCalculateKnots  = when set to true, x will be filled with the knot() routine,
+                  otherwise its content will be used.
+    knots[]     = array containing the knot vector (must be npts + k + 1 large)
+*/
+
+void rbspline2( int npts,int k,int p1,double b[],double h[],
+                bool bCalculateKnots, double knots[], double p[] )
+
+{
+    const int nplusc = npts + k;
+
+    std::vector<double> nbasis;
+    nbasis.resize( npts+1 );
+
+/* generate the uniform open knot vector */
+
+    if( bCalculateKnots == true )
+        knot(npts, k, knots);
+
+    int icount = 0;
+
+/*    calculate the points on the rational B-spline curve */
+
+    double t = 0.0;
+    const double step = ((double)knots[nplusc])/((double)(p1-1));
+
+    for( int i1 = 1; i1<= p1; i1++ )
+    {
+        if( (double)knots[nplusc] - t < 5e-6 )
+        {
+            t = (double)knots[nplusc];
+        }
+
+        /* generate the basis function for this value of t */
+        rbasis(k, t, npts, knots, h, &(nbasis[0]));
+        for( int j = 1; j <= 3; j++ )
+        {      /* generate a point on the curve */
+            int jcount = j;
+            p[icount+j] = 0.;
+
+            for( int i = 1; i <= npts; i++ )
+            { /* Do local matrix multiplication */
+                const double temp = nbasis[i]*b[jcount];
+                p[icount + j] = p[icount + j] + temp;
+                jcount = jcount + 3;
+            }
+        }
+        icount = icount + 3;
+        t = t + step;
     }
 }
 
@@ -177,20 +296,20 @@ static void rbasis(int c,double t,int npts, double x[], double h[], double r[])
 
 /*  Subroutine to generate a rational B-spline curve using an uniform open knot vector
 
-	C code for An Introduction to NURBS
-	by David F. Rogers. Copyright (C) 2000 David F. Rogers,
-	All rights reserved.
+    C code for An Introduction to NURBS
+    by David F. Rogers. Copyright (C) 2000 David F. Rogers,
+    All rights reserved.
 
-	Name: rbspline.c
-	Language: C
-	Subroutines called: knot.c, rbasis.c, fmtmul.c
-	Book reference: Chapter 4, Alg. p. 297
+    Name: rbspline.c
+    Language: C
+    Subroutines called: knot.c, rbasis.c, fmtmul.c
+    Book reference: Chapter 4, Alg. p. 297
 
     b[]         = array containing the defining polygon vertices
                   b[1] contains the x-component of the vertex
                   b[2] contains the y-component of the vertex
                   b[3] contains the z-component of the vertex
-	h[]			= array containing the homogeneous weighting factors
+    h[]         = array containing the homogeneous weighting factors 
     k           = order of the B-spline basis function
     nbasis      = array containing the basis functions for a single value of t
     nplusc      = number of knot values
@@ -204,8 +323,47 @@ static void rbasis(int c,double t,int npts, double x[], double h[], double r[])
     x[]         = array containing the knot vector
 */
 
-void rbspline2(int npts,int k,int p1,double b[],double h[],
-        bool xflag, double x[], double p[])
+void rbspline(int npts,int k,int p1,double b[],double h[], double p[])
+
+{
+    std::vector<double> x (npts + k + 1, 0.0);
+    rbspline2( npts,k,p1,b,h,true,&x[0],p );
+}
+
+/************************************************************************/
+/*                              rbsplinu()                              */
+/************************************************************************/
+
+/*  Subroutine to generate a rational B-spline curve using an uniform periodic knot vector
+
+    C code for An Introduction to NURBS
+    by David F. Rogers. Copyright (C) 2000 David F. Rogers,
+    All rights reserved.
+
+    Name: rbsplinu.c
+    Language: C
+    Subroutines called: knotu.c, rbasis.c, fmtmul.c
+    Book reference: Chapter 4, Alg. p. 298
+
+    b[]         = array containing the defining polygon vertices
+                  b[1] contains the x-component of the vertex
+                  b[2] contains the y-component of the vertex
+                  b[3] contains the z-component of the vertex
+    h[]         = array containing the homogeneous weighting factors 
+    k           = order of the B-spline basis function
+    nbasis      = array containing the basis functions for a single value of t
+    nplusc      = number of knot values
+    npts        = number of defining polygon vertices
+    p[,]        = array containing the curve points
+                  p[1] contains the x-component of the point
+                  p[2] contains the y-component of the point
+                  p[3] contains the z-component of the point
+    p1          = number of points to be calculated on the curve
+    t           = parameter value 0 <= t <= npts - k + 1
+    x[]         = array containing the knot vector
+*/
+
+void rbsplinu(int npts,int k,int p1,double b[],double h[], double p[])
 
 {
     int i,j,icount,jcount;
@@ -216,31 +374,42 @@ void rbspline2(int npts,int k,int p1,double b[],double h[],
     double t;
     double temp;
     std::vector<double> nbasis;
+    std::vector<double> x;
 
     nplusc = npts + k;
 
-    nbasis.resize( npts+1 );
+    x.resize( nplusc+1);
+    nbasis.resize(npts+1);
 
-/* generate the uniform open knot vector */
+/*  zero and redimension the knot vector and the basis array */
 
-    if( xflag == true )
-        knot(npts,k,x);
+    for(i = 0; i <= npts; i++){
+        nbasis[i] = 0.;
+    }
+
+    for(i = 0; i <= nplusc; i++){
+        x[i] = 0;
+    }
+
+/* generate the uniform periodic knot vector */
+
+    knotu(npts,k,&(x[0]));
 
     icount = 0;
 
 /*    calculate the points on the rational B-spline curve */
 
-    t = 0;
-    step = ((double)x[nplusc])/((double)(p1-1));
+    t = k-1;
+    step = ((double)((npts)-(k-1)))/((double)(p1-1));
 
     for (i1 = 1; i1<= p1; i1++){
 
-        if ((double)x[nplusc] - t < 5e-6){
-            t = (double)x[nplusc];
+        if (x[nplusc] - t < 5e-6){
+            t = x[nplusc];
         }
 
-        /* generate the basis function for this value of t */
-        rbasis(k,t,npts,x,h,&(nbasis[0]));
+        rbasis(k,t,npts,&(x[0]),h,&(nbasis[0]));      /* generate the basis function for this value of t */
+
         for (j = 1; j <= 3; j++){      /* generate a point on the curve */
             jcount = j;
             p[icount+j] = 0.;
@@ -251,7 +420,7 @@ void rbspline2(int npts,int k,int p1,double b[],double h[],
                 jcount = jcount + 3;
             }
         }
-    	icount = icount + 3;
+        icount = icount + 3;
         t = t + step;
     }
 }
diff --git a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
index fe8949e..0f0d294 100644
--- a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  DXF and DWG Translators
  * Purpose:  Implements various generic services shared between autocad related
@@ -31,7 +30,7 @@
 #include "ogr_autocad_services.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdwglayer.cpp 22008 2011-03-22 19:45:20Z warmerdam $");
+CPL_CVSID("$Id: ogr_autocad_services.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /************************************************************************/
 /*                           ACTextUnescape()                           */
@@ -77,7 +76,7 @@ CPLString ACTextUnescape( const char *pszRawInput, const char *pszEncoding )
                  && pszInput[2] == '+' )
         {
             CPLString osHex;
-            int iChar;
+            unsigned int iChar = 0;
 
             osHex.assign( pszInput+3, 4 );
             sscanf( osHex.c_str(), "%x", &iChar );
@@ -459,7 +458,7 @@ void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature )
     }
     else
     {
-        CPLAssert( osOldStyle[osOldStyle.size()-1] == ')' );
+        CPLAssert( osOldStyle.back() == ')' );
         osPreAngle.assign( osOldStyle, 0, osOldStyle.size() - 1 );
         osPostAngle = ")";
     }
@@ -497,7 +496,7 @@ void ACAdjustText( double dfAngle, double dfScale, OGRFeature *poFeature )
     }
     else
     {
-        CPLAssert( osOldStyle[osOldStyle.size()-1] == ')' );
+        CPLAssert( osOldStyle.back() == ')' );
         osPreScale.assign( osOldStyle, 0, osOldStyle.size() - 1 );
         osPostScale = ")";
     }
diff --git a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h
index 3da6690..3073fbe 100644
--- a/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h
+++ b/ogr/ogrsf_frmts/dxf/ogr_autocad_services.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: ogr_autocad_services.h 34524 2016-07-03 02:47:25Z goatbar $
  *
  * Project:  DXF and DWG Translators
  * Purpose:  Declarations for shared AutoCAD format services.
diff --git a/ogr/ogrsf_frmts/dxf/ogr_dxf.h b/ogr/ogrsf_frmts/dxf/ogr_dxf.h
index e4ddd4f..630ddbf 100644
--- a/ogr/ogrsf_frmts/dxf/ogr_dxf.h
+++ b/ogr/ogrsf_frmts/dxf/ogr_dxf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_dxf.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_dxf.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Definition of classes for OGR .dxf driver.
@@ -73,15 +73,15 @@ class OGRDXFBlocksLayer : public OGRLayer
     std::map<CPLString,DXFBlockDefinition>::iterator oIt;
 
   public:
-    OGRDXFBlocksLayer( OGRDXFDataSource *poDS );
+    explicit OGRDXFBlocksLayer( OGRDXFDataSource *poDS );
     ~OGRDXFBlocksLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     OGRFeature *        GetNextUnfilteredFeature();
 };
@@ -131,15 +131,15 @@ class OGRDXFLayer : public OGRLayer
     CPLString           TextUnescape( const char * );
 
   public:
-    OGRDXFLayer( OGRDXFDataSource *poDS );
+    explicit OGRDXFLayer( OGRDXFDataSource *poDS );
     ~OGRDXFLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     OGRFeature *        GetNextUnfilteredFeature();
 };
@@ -182,7 +182,6 @@ public:
     void                ResetReadPointer( int iNewOffset );
 };
 
-
 /************************************************************************/
 /*                           OGRDXFDataSource                           */
 /************************************************************************/
@@ -207,7 +206,7 @@ class OGRDXFDataSource : public OGRDataSource
 
     std::map<CPLString,CPLString> oLineTypeTable;
 
-    int                 bInlineBlocks;
+    bool                bInlineBlocks;
 
     OGRDXFReader        oReader;
 
@@ -217,16 +216,16 @@ class OGRDXFDataSource : public OGRDataSource
 
     int                 Open( const char * pszFilename, int bHeaderOnly=FALSE );
 
-    const char          *GetName() { return osName; }
+    const char          *GetName() override { return osName; }
 
-    int                 GetLayerCount() { return static_cast<int>(apoLayers.size()); }
-    OGRLayer            *GetLayer( int );
+    int                 GetLayerCount() override { return static_cast<int>(apoLayers.size()); }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     // The following is only used by OGRDXFLayer
 
-    int                 InlineBlocks() { return bInlineBlocks; }
+    bool                InlineBlocks() { return bInlineBlocks; }
     void                AddStandardFields( OGRFeatureDefn *poDef );
 
     // Implemented in ogrdxf_blockmap.cpp
@@ -287,8 +286,8 @@ class OGRDXFWriterLayer : public OGRLayer
     OGRErr              WriteINSERT( OGRFeature* );
 
     static CPLString    TextEscape( const char * );
-    int                 ColorStringToDXFColor( const char * );
-    CPLString           PrepareLineTypeDefinition( OGRFeature*, OGRStyleTool* );
+    static int          ColorStringToDXFColor( const char * );
+    static CPLString    PrepareLineTypeDefinition( OGRFeature*, OGRStyleTool* );
 
     std::map<CPLString,CPLString> oNewLineTypes;
     int                 nNextAutoID;
@@ -298,15 +297,15 @@ class OGRDXFWriterLayer : public OGRLayer
     OGRDXFWriterLayer( OGRDXFWriterDS *poDS, VSILFILE *fp );
     ~OGRDXFWriterLayer();
 
-    void                ResetReading() {}
-    OGRFeature         *GetNextFeature() { return NULL; }
+    void                ResetReading() override {}
+    OGRFeature         *GetNextFeature() override { return NULL; }
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
+    int                 TestCapability( const char * ) override;
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
     OGRErr              CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
     void                ResetFP( VSILFILE * );
 
@@ -322,18 +321,18 @@ class OGRDXFBlocksWriterLayer : public OGRLayer
     OGRFeatureDefn     *poFeatureDefn;
 
   public:
-    OGRDXFBlocksWriterLayer( OGRDXFWriterDS *poDS );
+    explicit OGRDXFBlocksWriterLayer( OGRDXFWriterDS *poDS );
     ~OGRDXFBlocksWriterLayer();
 
-    void                ResetReading() {}
-    OGRFeature         *GetNextFeature() { return NULL; }
+    void                ResetReading() override {}
+    OGRFeature         *GetNextFeature() override { return NULL; }
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
+    int                 TestCapability( const char * ) override;
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
     OGRErr              CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
     std::vector<OGRFeature*> apoBlocks;
     OGRFeature          *FindBlock( const char * );
@@ -371,13 +370,13 @@ class OGRDXFWriterDS : public OGRDataSource
     void                ScanForEntities( const char *pszFilename,
                                          const char *pszTarget );
 
-    int                 WriteNewLineTypeRecords( VSILFILE *fp );
-    int                 WriteNewBlockRecords( VSILFILE * );
-    int                 WriteNewBlockDefinitions( VSILFILE * );
-    int                 WriteNewLayerDefinitions( VSILFILE * );
-    int                 TransferUpdateHeader( VSILFILE * );
-    int                 TransferUpdateTrailer( VSILFILE * );
-    int                 FixupHANDSEED( VSILFILE * );
+    bool                WriteNewLineTypeRecords( VSILFILE *fp );
+    bool                WriteNewBlockRecords( VSILFILE * );
+    bool                WriteNewBlockDefinitions( VSILFILE * );
+    bool                WriteNewLayerDefinitions( VSILFILE * );
+    bool                TransferUpdateHeader( VSILFILE * );
+    bool                TransferUpdateTrailer( VSILFILE * );
+    bool                FixupHANDSEED( VSILFILE * );
 
     OGREnvelope         oGlobalEnvelope;
 
@@ -388,19 +387,19 @@ class OGRDXFWriterDS : public OGRDataSource
     int                 Open( const char * pszFilename,
                               char **papszOptions );
 
-    const char          *GetName() { return osName; }
+    const char          *GetName() override { return osName; }
 
-    int                 GetLayerCount();
-    OGRLayer            *GetLayer( int );
+    int                 GetLayerCount() override;
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     OGRLayer           *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
-                                     char ** papszOptions = NULL );
+                                     char ** papszOptions = NULL ) override;
 
-    int                 CheckEntityID( const char *pszEntityID );
+    bool                CheckEntityID( const char *pszEntityID );
     long                WriteEntityID( VSILFILE * fp,
                                        long nPreferredFID = OGRNullFID );
 
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
index b4355f6..a726e9e 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_blockmap.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxf_blockmap.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements BlockMap reading and management portion of
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrdxf_blockmap.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdxf_blockmap.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                          ReadBlockSection()                          */
@@ -42,14 +41,15 @@ CPL_CVSID("$Id: ogrdxf_blockmap.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 bool OGRDXFDataSource::ReadBlocksSection()
 
 {
-    char szLineBuf[257];
-    int  nCode;
-    OGRDXFLayer *poReaderLayer = (OGRDXFLayer *) GetLayerByName( "Entities" );
-    int bMergeBlockGeometries = CPLTestBool(
+    OGRDXFLayer *poReaderLayer = static_cast<OGRDXFLayer *>(
+        GetLayerByName( "Entities" ));
+    const bool bMergeBlockGeometries = CPLTestBool(
         CPLGetConfigOption( "DXF_MERGE_BLOCK_GEOMETRIES", "TRUE" ) );
 
     iEntitiesSectionOffset = oReader.iSrcBufferFileOffset + oReader.iSrcBufferOffset;
 
+    char szLineBuf[257];
+    int nCode = 0;
     while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1
            && !EQUAL(szLineBuf,"ENDSEC") )
     {
@@ -84,7 +84,7 @@ bool OGRDXFDataSource::ReadBlocksSection()
         // we aggregate the geometries of the features into a multi-geometry,
         // but throw away other stuff attached to the features.
 
-        OGRFeature *poFeature;
+        OGRFeature *poFeature = NULL;
         OGRGeometryCollection *poColl = new OGRGeometryCollection();
         std::vector<OGRFeature*> apoFeatures;
 
@@ -108,7 +108,7 @@ bool OGRDXFDataSource::ReadBlocksSection()
         else
             oBlockMap[osBlockName].poGeometry = SimplifyBlockGeometry(poColl);
 
-        if( apoFeatures.size() > 0 )
+        if( !apoFeatures.empty() )
             oBlockMap[osBlockName].apoFeatures = apoFeatures;
     }
     if( nCode < 0 )
@@ -137,17 +137,59 @@ OGRGeometry *OGRDXFDataSource::SimplifyBlockGeometry(
     if( poCollection->getNumGeometries() == 1 )
     {
         OGRGeometry *poReturn = poCollection->getGeometryRef(0);
-        poCollection->removeGeometry(0,FALSE);
+        poCollection->removeGeometry(0, FALSE);
         delete poCollection;
         return poReturn;
     }
 
 /* -------------------------------------------------------------------- */
-/*      Eventually we likely ought to have logic to convert to          */
-/*      polygon, multipolygon, multilinestring or multipoint but        */
-/*      I'll put that off till it would be meaningful.                  */
+/*      Convert to polygon, multipolygon, multilinestring or multipoint */
 /* -------------------------------------------------------------------- */
 
+    OGRwkbGeometryType eType =
+                wkbFlatten(poCollection->getGeometryRef(0)->getGeometryType());
+    int i;
+    for(i=1;i<poCollection->getNumGeometries();i++)
+    {
+        if (wkbFlatten(poCollection->getGeometryRef(i)->getGeometryType())
+            != eType)
+        {
+            eType = wkbUnknown;
+            break;
+        }
+    }
+    if (eType == wkbPoint || eType == wkbLineString)
+    {
+        OGRGeometryCollection* poNewColl;
+        if (eType == wkbPoint)
+            poNewColl = new OGRMultiPoint();
+        else
+            poNewColl = new OGRMultiLineString();
+        while(poCollection->getNumGeometries() > 0)
+        {
+            OGRGeometry *poGeom = poCollection->getGeometryRef(0);
+            poCollection->removeGeometry(0,FALSE);
+            poNewColl->addGeometryDirectly(poGeom);
+        }
+        delete poCollection;
+        return poNewColl;
+    }
+    else if (eType == wkbPolygon)
+    {
+        std::vector<OGRGeometry*> aosPolygons;
+        while(poCollection->getNumGeometries() > 0)
+        {
+            OGRGeometry *poGeom = poCollection->getGeometryRef(0);
+            poCollection->removeGeometry(0,FALSE);
+            aosPolygons.push_back(poGeom);
+        }
+        delete poCollection;
+        int bIsValidGeometry;
+        return OGRGeometryFactory::organizePolygons(
+            &aosPolygons[0], (int)aosPolygons.size(),
+            &bIsValidGeometry, NULL);
+    }
+
     return poCollection;
 }
 
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp
index 7ccca55..0f09fc9 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_dimension.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxf_dimension.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements translation support for DIMENSION elements as a part
@@ -32,7 +31,7 @@
 #include "ogr_dxf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdxf_dimension.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdxf_dimension.cpp 37040 2016-12-30 15:31:43Z rouault $");
 
 /************************************************************************/
 /*                         TranslateDIMENSION()                         */
@@ -42,12 +41,21 @@ OGRFeature *OGRDXFLayer::TranslateDIMENSION()
 
 {
     char szLineBuf[257];
-    int nCode /*, nDimType = 0 */;
+    int nCode = 0;
+    // int  nDimType = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfArrowX1 = 0.0, dfArrowY1 = 0.0 /*, dfArrowZ1 = 0.0 */;
-    double dfTargetX1 = 0.0, dfTargetY1 = 0.0 /* , dfTargetZ1 = 0.0 */;
-    double dfTargetX2 = 0.0, dfTargetY2 = 0.0 /* , dfTargetZ2 = 0.0 */;
-    double dfTextX = 0.0, dfTextY = 0.0 /* , dfTextZ = 0.0 */;
+    double dfArrowX1 = 0.0;
+    double dfArrowY1 = 0.0;
+    // double dfArrowZ1 = 0.0;
+    double dfTargetX1 = 0.0;
+    double dfTargetY1 = 0.0;
+    // double dfTargetZ1 = 0.0;
+    double dfTargetX2 = 0.0;
+    double dfTargetY2 = 0.0;
+    // double dfTargetZ2 = 0.0;
+    double dfTextX = 0.0;
+    double dfTextY = 0.0;
+    // double dfTextZ = 0.0;
     double dfAngle = 0.0;
     double dfHeight = CPLAtof(poDS->GetVariable("$DIMTXT", "2.5"));
 
@@ -135,7 +143,6 @@ OGRFeature *OGRDXFLayer::TranslateDIMENSION()
         |
         X (14,24) (Target1)
 
-
 Given:
   Locations Arrow1, Target1, and Target2 we need to compute Arrow2.
 
@@ -152,32 +159,30 @@ the approach is as above in all these cases.
 
 *************************************************************************/
 
-    ;
-
 /* -------------------------------------------------------------------- */
 /*      Step 1, compute direction vector between Target1 and Arrow1.    */
 /* -------------------------------------------------------------------- */
-    double dfVec1X, dfVec1Y;
-
-    dfVec1X = (dfArrowX1 - dfTargetX1);
-    dfVec1Y = (dfArrowY1 - dfTargetY1);
+    double dfVec1X = dfArrowX1 - dfTargetX1;
+    double dfVec1Y = dfArrowY1 - dfTargetY1;
 
 /* -------------------------------------------------------------------- */
 /*      Step 2, compute the direction vector from Arrow1 to Arrow2      */
 /*      as a perpendicular to Vec1.                                     */
 /* -------------------------------------------------------------------- */
-    double dfVec2X, dfVec2Y;
-
-    dfVec2X = dfVec1Y;
-    dfVec2Y = -dfVec1X;
+    double dfVec2X = dfVec1Y;
+    double dfVec2Y = -dfVec1X;
 
 /* -------------------------------------------------------------------- */
 /*      Step 3, compute intersection of line from target2 along         */
 /*      direction vector 1, with the line through Arrow1 and            */
 /*      direction vector 2.                                             */
 /* -------------------------------------------------------------------- */
-    double dfL1M, dfL1B, dfL2M, dfL2B;
-    double dfArrowX2, dfArrowY2;
+    double dfL1M = 0.0;
+    double dfL1B = 0.0;
+    double dfL2M = 0.0;
+    double dfL2B = 0.0;
+    double dfArrowX2 = 0.0;
+    double dfArrowY2 = 0.0;
 
     // special case if vec1 is vertical.
     if( dfVec1X == 0.0 )
@@ -224,17 +229,16 @@ the approach is as above in all these cases.
 #define VECTOR_LEN(x,y) sqrt( (x)*(x) + (y)*(y) )
 #define POINT_DIST(x1,y1,x2,y2)  VECTOR_LEN((x2-x1),(y2-y1))
 
-    double dfBaselineLength = POINT_DIST(dfArrowX1,dfArrowY1,
-                                         dfArrowX2,dfArrowY2);
-    double dfTargetLength = dfBaselineLength * 0.03;
-    double dfScaleFactor;
+    const double dfBaselineLength = POINT_DIST(dfArrowX1, dfArrowY1,
+                                               dfArrowX2, dfArrowY2);
+    const double dfTargetLength = dfBaselineLength * 0.03;
 
     // recompute vector 2 to ensure the direction is regular
     dfVec2X = (dfArrowX2 - dfArrowX1);
     dfVec2Y = (dfArrowY2 - dfArrowY1);
 
     // vector 1
-    dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec1X,dfVec1Y);
+    double dfScaleFactor = dfTargetLength / VECTOR_LEN(dfVec1X, dfVec1Y);
     dfVec1X *= dfScaleFactor;
     dfVec1Y *= dfScaleFactor;
 
@@ -250,22 +254,22 @@ the approach is as above in all these cases.
     OGRMultiLineString *poMLS = new OGRMultiLineString();
     OGRLineString oLine;
 
-    // main arrow line between Arrow1 and Arrow2
+    // Main arrow line between Arrow1 and Arrow2.
     oLine.setPoint( 0, dfArrowX1, dfArrowY1 );
     oLine.setPoint( 1, dfArrowX2, dfArrowY2 );
     poMLS->addGeometry( &oLine );
 
-    // dimension line from Target1 to Arrow1 with a small extension.
+    // Dimension line from Target1 to Arrow1 with a small extension.
     oLine.setPoint( 0, dfTargetX1, dfTargetY1 );
     oLine.setPoint( 1, dfArrowX1 + dfVec1X, dfArrowY1 + dfVec1Y );
     poMLS->addGeometry( &oLine );
 
-    // dimension line from Target2 to Arrow2 with a small extension.
+    // Dimension line from Target2 to Arrow2 with a small extension.
     oLine.setPoint( 0, dfTargetX2, dfTargetY2 );
     oLine.setPoint( 1, dfArrowX2 + dfVec1X, dfArrowY2 + dfVec1Y );
     poMLS->addGeometry( &oLine );
 
-    // add arrow1 arrow head.
+    // Add arrow1 arrow head.
 
     oLine.setPoint( 0, dfArrowX1, dfArrowY1 );
     oLine.setPoint( 1,
@@ -279,7 +283,7 @@ the approach is as above in all these cases.
                     dfArrowY1 + dfVec2Y*3 - dfVec1Y );
     poMLS->addGeometry( &oLine );
 
-    // add arrow2 arrow head.
+    // Add arrow2 arrow head.
 
     oLine.setPoint( 0, dfArrowX2, dfArrowY2 );
     oLine.setPoint( 1,
@@ -303,7 +307,7 @@ the approach is as above in all these cases.
 /*      feature for the next feature read.                              */
 /* -------------------------------------------------------------------- */
 
-    // a single space suppresses labelling.
+    // a single space suppresses labeling.
     if( osText == " " )
         return poFeature;
 
@@ -312,7 +316,7 @@ the approach is as above in all these cases.
     poLabelFeature->SetGeometryDirectly( new OGRPoint( dfTextX, dfTextY ) );
 
     // Do we need to compute the dimension value?
-    if( osText.size() == 0 )
+    if( osText.empty() )
     {
         FormatDimension( osText, POINT_DIST( dfArrowX1, dfArrowY1,
                                              dfArrowX2, dfArrowY2 ) );
@@ -321,7 +325,7 @@ the approach is as above in all these cases.
     CPLString osStyle;
     char szBuffer[64];
 
-    osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",p:5",osText.c_str());
+    osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\",p:5", osText.c_str());
 
     if( dfAngle != 0.0 )
     {
@@ -335,7 +339,7 @@ the approach is as above in all these cases.
         osStyle += CPLString().Printf(",s:%sg", szBuffer);
     }
 
-    // add color!
+    // Add color!
 
     osStyle += ")";
 
@@ -356,15 +360,17 @@ the approach is as above in all these cases.
 void OGRDXFLayer::FormatDimension( CPLString &osText, double dfValue )
 
 {
-    int nPrecision = atoi(poDS->GetVariable("$LUPREC","4"));
-    char szFormat[32];
-    char szBuffer[64];
+    const int nPrecision = atoi(poDS->GetVariable("$LUPREC","4"));
 
-    // we could do a significantly more precise formatting if we want
+    // We could do a significantly more precise formatting if we want
     // to spend the effort.  See QCAD's rs_dimlinear.cpp and related files
     // for example.
 
+    char szFormat[32];
     snprintf(szFormat, sizeof(szFormat), "%%.%df", nPrecision );
+
+    char szBuffer[64];
     CPLsnprintf(szBuffer, sizeof(szBuffer), szFormat, dfValue);
+
     osText = szBuffer;
 }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
index c493228..1aeacf3 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_hatch.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxf_hatch.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements translation support for HATCH elements as part
@@ -35,7 +34,7 @@
 
 #include "ogrdxf_polyline_smooth.h"
 
-CPL_CVSID("$Id: ogrdxf_hatch.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdxf_hatch.cpp 35626 2016-10-06 14:02:20Z rouault $");
 
 /************************************************************************/
 /*                           TranslateHATCH()                           */
@@ -49,7 +48,7 @@ OGRFeature *OGRDXFLayer::TranslateHATCH()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     CPLString osHatchPattern;
@@ -72,9 +71,10 @@ OGRFeature *OGRDXFLayer::TranslateHATCH()
           case 91:
           {
               int nBoundaryPathCount = atoi(szLineBuf);
-              int iBoundary;
 
-              for( iBoundary = 0; iBoundary < nBoundaryPathCount; iBoundary++ )
+              for( int iBoundary = 0;
+                   iBoundary < nBoundaryPathCount;
+                   iBoundary++ )
               {
                   if (CollectBoundaryPath( &oGC ) != OGRERR_NONE)
                       break;
@@ -163,20 +163,19 @@ OGRFeature *OGRDXFLayer::TranslateHATCH()
 OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 
 {
-    int  nCode;
     char szLineBuf[257];
 
 /* -------------------------------------------------------------------- */
 /*      Read the boundary path type.                                    */
 /* -------------------------------------------------------------------- */
-    nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf));
+    int nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf));
     if( nCode != 92 )
     {
         DXF_LAYER_READER_ERROR();
         return OGRERR_FAILURE;
     }
 
-    int  nBoundaryPathType = atoi(szLineBuf);
+    const int nBoundaryPathType = atoi(szLineBuf);
 
 /* ==================================================================== */
 /*      Handle polyline loops.                                          */
@@ -198,22 +197,20 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
         return OGRERR_FAILURE;
     }
 
-    int nEdgeCount = atoi(szLineBuf);
+    const int nEdgeCount = atoi(szLineBuf);
 
 /* -------------------------------------------------------------------- */
 /*      Loop reading edges.                                             */
 /* -------------------------------------------------------------------- */
-    int iEdge;
-
-    for( iEdge = 0; iEdge < nEdgeCount; iEdge++ )
+    for( int iEdge = 0; iEdge < nEdgeCount; iEdge++ )
     {
 /* -------------------------------------------------------------------- */
 /*      Read the edge type.                                             */
 /* -------------------------------------------------------------------- */
-#define ET_LINE         1
-#define ET_CIRCULAR_ARC 2
-#define ET_ELLIPTIC_ARC 3
-#define ET_SPLINE       4
+        const int ET_LINE = 1;
+        const int ET_CIRCULAR_ARC = 2;
+        const int ET_ELLIPTIC_ARC = 3;
+        // const int ET_SPLINE = 4;
 
         nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf));
         if( nCode != 72 )
@@ -229,26 +226,29 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 /* -------------------------------------------------------------------- */
         if( nEdgeType == ET_LINE )
         {
-            double dfStartX;
-            double dfStartY;
-            double dfEndX;
-            double dfEndY;
+            double dfStartX = 0.0;
 
             if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 10 )
                 dfStartX = CPLAtof(szLineBuf);
             else
                 break;
 
+            double dfStartY = 0.0;
+
             if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 20 )
                 dfStartY = CPLAtof(szLineBuf);
             else
                 break;
 
+            double dfEndX = 0.0;
+
             if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 11 )
                 dfEndX = CPLAtof(szLineBuf);
             else
                 break;
 
+            double dfEndY = 0.0;
+
             if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 21 )
                 dfEndY = CPLAtof(szLineBuf);
             else
@@ -266,40 +266,45 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 /* -------------------------------------------------------------------- */
         else if( nEdgeType == ET_CIRCULAR_ARC )
         {
-            double dfCenterX;
-            double dfCenterY;
-            double dfRadius;
-            double dfStartAngle;
-            double dfEndAngle;
-            int    bCounterClockwise = FALSE;
+            double dfCenterX = 0.0;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 10 )
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 10 )
                 dfCenterX = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 20 )
+            double dfCenterY = 0.0;
+
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 20 )
                 dfCenterY = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 40 )
+            double dfRadius = 0.0;
+
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 40 )
                 dfRadius = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 50 )
+            double dfStartAngle = 0.0;
+
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 50 )
                 dfStartAngle = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 51 )
+            double dfEndAngle = 0.0;
+
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 51 )
                 dfEndAngle = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 73 )
-                bCounterClockwise = atoi(szLineBuf);
+            bool bCounterClockwise = false;
+
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 73 )
+                bCounterClockwise = atoi(szLineBuf) != 0;
             else if (nCode >= 0)
                 poDS->UnreadValue();
             else
@@ -328,53 +333,59 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 /* -------------------------------------------------------------------- */
         else if( nEdgeType == ET_ELLIPTIC_ARC )
         {
-            double dfCenterX;
-            double dfCenterY;
-            double dfMajorRadius, dfMinorRadius;
-            double dfMajorX, dfMajorY;
-            double dfStartAngle;
-            double dfEndAngle;
-            double dfRotation;
-            double dfRatio;
-            int    bCounterClockwise = FALSE;
+            double dfCenterX = 0.0;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 10 )
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 10 )
                 dfCenterX = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 20 )
+            double dfCenterY = 0.0;
+
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 20 )
                 dfCenterY = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 11 )
+            double dfMajorX = 0.0;
+
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 11 )
                 dfMajorX = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 21 )
+            double dfMajorY = 0.0;
+
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 21 )
                 dfMajorY = CPLAtof(szLineBuf);
             else
                 break;
 
-            if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 40 )
+            double dfRatio = 0.0;
+
+            if( (nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) == 40 )
                 dfRatio = CPLAtof(szLineBuf) / 100.0;
             else
                 break;
 
+            double dfStartAngle = 0.0;
+
             if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 50 )
                 dfStartAngle = CPLAtof(szLineBuf);
             else
                 break;
 
+            double dfEndAngle = 0.0;
+
             if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 51 )
                 dfEndAngle = CPLAtof(szLineBuf);
             else
                 break;
 
+            bool bCounterClockwise = false;
+
             if( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) == 73 )
-                bCounterClockwise = atoi(szLineBuf);
+                bCounterClockwise = atoi(szLineBuf) != 0;
             else if (nCode >= 0)
                 poDS->UnreadValue();
             else
@@ -388,10 +399,12 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
                 dfEndAngle *= -1;
             }
 
-            dfMajorRadius = sqrt( dfMajorX * dfMajorX + dfMajorY * dfMajorY );
-            dfMinorRadius = dfMajorRadius * dfRatio;
+            const double dfMajorRadius =
+                sqrt( dfMajorX * dfMajorX + dfMajorY * dfMajorY );
+            const double dfMinorRadius = dfMajorRadius * dfRatio;
 
-            dfRotation = -1 * atan2( dfMajorY, dfMajorX ) * 180 / M_PI;
+            const double dfRotation =
+                -1 * atan2( dfMajorY, dfMajorX ) * 180 / M_PI;
 
             OGRGeometry *poArc = OGRGeometryFactory::approximateArcAngles(
                 dfCenterX, dfCenterY, 0.0,
@@ -447,15 +460,17 @@ OGRErr OGRDXFLayer::CollectBoundaryPath( OGRGeometryCollection *poGC )
 OGRErr OGRDXFLayer::CollectPolylinePath( OGRGeometryCollection *poGC )
 
 {
-    int  nCode;
+    int nCode = 0;
     char szLineBuf[257];
     DXFSmoothPolyline oSmoothPolyline;
     double dfBulge = 0.0;
-    double dfX = 0.0, dfY = 0.0;
-    int bHaveX = FALSE, bHaveY = FALSE;
-    int bIsClosed = FALSE;
+    double dfX = 0.0;
+    double dfY = 0.0;
+    bool bHaveX = false;
+    bool bHaveY = false;
+    bool bIsClosed = false;
     int nVertexCount = -1;
-    int bHaveBulges = FALSE;
+    bool bHaveBulges = false;
 
 /* -------------------------------------------------------------------- */
 /*      Read the boundary path type.                                    */
@@ -472,11 +487,11 @@ OGRErr OGRDXFLayer::CollectPolylinePath( OGRGeometryCollection *poGC )
             break;
 
           case 72:
-            bHaveBulges = atoi(szLineBuf);
+            bHaveBulges = CPL_TO_BOOL(atoi(szLineBuf));
             break;
 
           case 73:
-            bIsClosed = atoi(szLineBuf);
+            bIsClosed = CPL_TO_BOOL(atoi(szLineBuf));
             break;
 
           case 10:
@@ -484,10 +499,10 @@ OGRErr OGRDXFLayer::CollectPolylinePath( OGRGeometryCollection *poGC )
             {
                 oSmoothPolyline.AddPoint(dfX, dfY, 0.0, dfBulge);
                 dfBulge = 0.0;
-                bHaveY = FALSE;
+                bHaveY = false;
             }
             dfX = CPLAtof(szLineBuf);
-            bHaveX = TRUE;
+            bHaveX = true;
             break;
 
           case 20:
@@ -495,15 +510,16 @@ OGRErr OGRDXFLayer::CollectPolylinePath( OGRGeometryCollection *poGC )
             {
                 oSmoothPolyline.AddPoint( dfX, dfY, 0.0, dfBulge );
                 dfBulge = 0.0;
-                bHaveX = bHaveY = FALSE;
+                bHaveX = false;
             }
             dfY = CPLAtof(szLineBuf);
-            bHaveY = TRUE;
+            bHaveY = true;
             if( bHaveX && bHaveY && !bHaveBulges )
             {
                 oSmoothPolyline.AddPoint( dfX, dfY, 0.0, dfBulge );
                 dfBulge = 0.0;
-                bHaveX = bHaveY = FALSE;
+                bHaveX = false;
+                bHaveY = false;
             }
             break;
 
@@ -513,7 +529,8 @@ OGRErr OGRDXFLayer::CollectPolylinePath( OGRGeometryCollection *poGC )
             {
                 oSmoothPolyline.AddPoint( dfX, dfY, 0.0, dfBulge );
                 dfBulge = 0.0;
-                bHaveX = bHaveY = FALSE;
+                bHaveX = false;
+                bHaveY = false;
             }
             break;
 
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
index 01c58be..dda3ace 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.cpp
@@ -32,18 +32,18 @@
 #include "math.h"
 #include "ogrdxf_polyline_smooth.h"
 
+CPL_CVSID("$Id: ogrdxf_polyline_smooth.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /************************************************************************/
 /*                Local helper functions                                */
 /************************************************************************/
 
-static double GetRadius(double bulge, double length)
+static double GetRadius( double bulge, double length )
 {
     const double h = (bulge * length) / 2;
     return (h / 2) + (length * length / (8 * h));
 }
 
-
 static double GetLength
 (
     const DXFSmoothPolylineVertex& start,
@@ -53,7 +53,6 @@ static double GetLength
     return sqrt(pow(end.x - start.x, 2) + pow(end.y - start.y, 2));
 }
 
-
 static double GetAngle
 (
     const DXFSmoothPolylineVertex& start,
@@ -63,7 +62,6 @@ static double GetAngle
     return atan2((start.y - end.y), (start.x - end.x)) * 180.0 / M_PI;
 }
 
-
 static double GetOGRangle(double angle)
 {
     return angle > 0.0
@@ -71,7 +69,6 @@ static double GetOGRangle(double angle)
             : -(angle + 180.0);
 }
 
-
 // TODO: Spelling Tesselate -> Tessellate
 /************************************************************************/
 /*                DXFSmoothPolyline::Tesselate()                        */
@@ -81,7 +78,6 @@ OGRGeometry* DXFSmoothPolyline::Tesselate() const
 {
     assert(!m_vertices.empty());
 
-
 /* -------------------------------------------------------------------- */
 /*      If polyline is one vertex, convert it to a point                */
 /* -------------------------------------------------------------------- */
@@ -94,7 +90,6 @@ OGRGeometry* DXFSmoothPolyline::Tesselate() const
         return poPt;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Otherwise, presume a line string                                */
 /* -------------------------------------------------------------------- */
@@ -106,35 +101,34 @@ OGRGeometry* DXFSmoothPolyline::Tesselate() const
     std::vector<DXFSmoothPolylineVertex>::const_iterator oIter = m_vertices.begin();
     std::vector<DXFSmoothPolylineVertex>::const_iterator oEndIter = m_vertices.end();
 
-    oEndIter--;
+    --oEndIter;
 
     DXFSmoothPolylineVertex begin = *oIter;
 
     double dfZ = 0.0;
-    const bool bConstantZ = this->HasConstantZ(dfZ);
+    const bool bConstantZ = HasConstantZ(dfZ);
 
     while(oIter != oEndIter)
     {
-        oIter++;
+        ++oIter;
         DXFSmoothPolylineVertex end = *oIter;
 
         const double len = GetLength(begin,end);
 
         if((len == 0) || (begin.bulge == 0))
         {
-            this->EmitLine(begin, end, poLS, bConstantZ, dfZ);
+            EmitLine(begin, end, poLS, bConstantZ, dfZ);
         }
         else
         {
             const double radius = GetRadius(begin.bulge,len);
-            this->EmitArc(begin, end, radius, len, begin.bulge, poLS, dfZ);
+            EmitArc(begin, end, radius, len, begin.bulge, poLS, dfZ);
         }
 
         // Move to next vertex
         begin = end;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Flatten to 2D if necessary                                      */
 /* -------------------------------------------------------------------- */
@@ -142,7 +136,6 @@ OGRGeometry* DXFSmoothPolyline::Tesselate() const
     if(bConstantZ && dfZ == 0.0 && m_dim == 2)
         poLS->flattenTo2D();
 
-
 /* -------------------------------------------------------------------- */
 /*      If polyline is closed, convert linestring to a linear ring      */
 /*                                                                      */
@@ -169,25 +162,21 @@ OGRGeometry* DXFSmoothPolyline::Tesselate() const
     return poLS;
 }
 
-
 /************************************************************************/
 /*                DXFSmoothPolyline::EmitArc()                        */
 /************************************************************************/
 
-void DXFSmoothPolyline::EmitArc
-(
+void DXFSmoothPolyline::EmitArc(
     const DXFSmoothPolylineVertex& start,
     const DXFSmoothPolylineVertex& end,
     double radius, double len, double bulge,
     OGRLineString* poLS,
-    double dfZ
-) const
+    double dfZ )
 {
     assert(poLS);
 
-    double  ogrArcRotation = 0.0,
-            ogrArcRadius = fabs(radius);
-
+    double ogrArcRotation = 0.0;
+    const double ogrArcRadius = fabs(radius);
 
 /* -------------------------------------------------------------------- */
 /*      Set arc's direction and keep bulge positive                     */
@@ -195,10 +184,9 @@ void DXFSmoothPolyline::EmitArc
 
     const bool bClockwise = (bulge < 0);
 
-    if(bClockwise)
+    if( bClockwise )
         bulge *= -1;
 
-
 /* -------------------------------------------------------------------- */
 /*      Get arc's center point                                          */
 /* -------------------------------------------------------------------- */
@@ -229,14 +217,12 @@ void DXFSmoothPolyline::EmitArc
     ogrArcCenter.x = midpoint.x + (pperp.x * apo);
     ogrArcCenter.y = midpoint.y + (pperp.y * apo);
 
-
 /* -------------------------------------------------------------------- */
 /*      Get the line's general vertical direction (-1 = down, +1 = up)  */
 /* -------------------------------------------------------------------- */
 
     const double linedir = end.y > start.y ? 1.0 : -1.0;
 
-
 /* -------------------------------------------------------------------- */
 /*      Get arc's starting angle.                                       */
 /* -------------------------------------------------------------------- */
@@ -248,7 +234,6 @@ void DXFSmoothPolyline::EmitArc
 
     double ogrArcStartAngle = GetOGRangle(a);
 
-
 /* -------------------------------------------------------------------- */
 /*      Get arc's ending angle.                                         */
 /* -------------------------------------------------------------------- */
@@ -273,7 +258,6 @@ void DXFSmoothPolyline::EmitArc
     if(bClockwise && (linedir == 1.0))
         ogrArcRotation = linedir * 180.0;
 
-
 /* -------------------------------------------------------------------- */
 /*      Tessellate the arc segment and append to the linestring.        */
 /* -------------------------------------------------------------------- */
@@ -290,20 +274,16 @@ void DXFSmoothPolyline::EmitArc
     delete poArcpoLS;
 }
 
-
-
 /************************************************************************/
 /*                DXFSmoothPolyline::EmitLine()                         */
 /************************************************************************/
 
-void DXFSmoothPolyline::EmitLine
-(
+void DXFSmoothPolyline::EmitLine(
     const DXFSmoothPolylineVertex& start,
     const DXFSmoothPolylineVertex& end,
     OGRLineString* poLS,
     bool bConstantZ,
-    double dfZ
-) const
+    double dfZ ) const
 {
     assert(poLS);
 
@@ -318,7 +298,6 @@ void DXFSmoothPolyline::EmitLine
         bConstantZ ? dfZ : end.z);
 }
 
-
 /************************************************************************/
 /*                DXFSmoothPolyline::Close()                            */
 /************************************************************************/
@@ -330,7 +309,7 @@ void DXFSmoothPolyline::Close()
     if(m_vertices.size() >= 2)
     {
         const bool bVisuallyClosed =
-            (m_vertices[m_vertices.size() - 1].shares_2D_pos(m_vertices[0]));
+            (m_vertices.back().shares_2D_pos(m_vertices[0]));
 
         if(!bVisuallyClosed)
         {
@@ -340,12 +319,11 @@ void DXFSmoothPolyline::Close()
     }
 }
 
-
 /************************************************************************/
 /*                DXFSmoothPolyline::HasConstantZ()                     */
 /************************************************************************/
 
-bool DXFSmoothPolyline::HasConstantZ(double& dfZ) const
+bool DXFSmoothPolyline::HasConstantZ( double& dfZ ) const
 {
     // Treat the polyline as having constant Z if all Z members
     // are equal or if any bulge attribute exists. In the latter case,
@@ -355,9 +333,9 @@ bool DXFSmoothPolyline::HasConstantZ(double& dfZ) const
 
     const double d = m_vertices[0].z;
 
-    for(size_t i = 1; i < m_vertices.size(); i++)
+    for( size_t i = 1; i < m_vertices.size(); i++ )
     {
-        if(m_vertices[i].bulge != 0.0)
+        if( m_vertices[i].bulge != 0.0 )
         {
             dfZ = 0.0;
             return true;
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h
index 09a2c21..435574c 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h
+++ b/ogr/ogrsf_frmts/dxf/ogrdxf_polyline_smooth.h
@@ -28,7 +28,6 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
 #ifndef OGRDXF_SMOOTH_POLYLINE_H_INCLUDED
 #define OGRDXF_SMOOTH_POLYLINE_H_INCLUDED
 
@@ -37,26 +36,26 @@
 #include <vector>
 #include "assert.h"
 
-
 class DXFSmoothPolylineVertex
 {
 public:
-    double  x, y, z, bulge;
-
+    double x;
+    double y;
+    double z;
+    double bulge;
 
     DXFSmoothPolylineVertex()
         {
             x = y = z = bulge = 0.0;
         }
 
-
-    DXFSmoothPolylineVertex(double dfX, double dfY, double dfZ, double dfBulge)
+    DXFSmoothPolylineVertex( double dfX, double dfY, double dfZ,
+                             double dfBulge )
         {
-            this->set(dfX, dfY, dfZ, dfBulge);
+            set(dfX, dfY, dfZ, dfBulge);
         }
 
-
-    void set(double dfX, double dfY, double dfZ, double dfBulge)
+    void set( double dfX, double dfY, double dfZ, double dfBulge )
         {
             x = dfX;
             y = dfY;
@@ -64,38 +63,32 @@ public:
             bulge = dfBulge;
         }
 
-
     void scale(double s)
         {
             x *= s;
             y *= s;
         }
 
-
     double length() const
         {
             return (sqrt(x*x + y*y));
         }
 
-
     void normalize()
         {
-            const double len = this->length();
+            const double len = length();
             assert(len != 0.0);
 
             x /= len;
             y /= len;
         }
 
-
     bool shares_2D_pos(const DXFSmoothPolylineVertex& v) const
         {
             return (x == v.x && y == v.y);
         }
-
 };
 
-
 class DXFSmoothPolyline
 {
     // A DXF polyline that includes vertex bulge information.
@@ -104,11 +97,10 @@ class DXFSmoothPolyline
     // change in the future.
 
 private:
-
-    std::vector<DXFSmoothPolylineVertex>    m_vertices;
-    mutable bool                            m_blinestringstarted;
-    bool                                    m_bClosed;
-    int										m_dim;
+    std::vector<DXFSmoothPolylineVertex> m_vertices;
+    mutable bool                         m_blinestringstarted;
+    bool                                 m_bClosed;
+    int                                  m_dim;
 
 public:
     DXFSmoothPolyline() : m_blinestringstarted(false), m_bClosed(false),
@@ -116,9 +108,9 @@ public:
 
     OGRGeometry* Tesselate() const;  // TODO: Spelling.
 
-    size_t size() { return m_vertices.size(); }
+    size_t size() const { return m_vertices.size(); }
 
-    void SetSize(int n) { m_vertices.reserve(n); }
+    void SetSize( int n ) { m_vertices.reserve(n); }
 
     void AddPoint(double dfX, double dfY, double dfZ, double dfBulge)
         {
@@ -131,14 +123,12 @@ public:
 
     bool HasConstantZ(double&) const;
 
-    void setCoordinateDimension(int n) { m_dim = n; }
-
-
+    void setCoordinateDimension( int n ) { m_dim = n; }
 
 private:
-    void EmitArc(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&,
+    static void EmitArc(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&,
                  double radius, double len, double saggita,
-                 OGRLineString*, double dfZ = 0.0) const;
+                 OGRLineString*, double dfZ = 0.0);
 
     void EmitLine(const DXFSmoothPolylineVertex&, const DXFSmoothPolylineVertex&,
                   OGRLineString*, bool bConstantZ, double dfZ) const;
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp
index b08b2a5..fd7c3c3 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfblockslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxflayer.cpp 19643 2010-05-08 21:56:18Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFBlocksLayer class.
@@ -30,7 +29,7 @@
 #include "ogr_dxf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdxflayer.cpp 19643 2010-05-08 21:56:18Z rouault $");
+CPL_CVSID("$Id: ogrdxfblockslayer.cpp 36418 2016-11-21 22:58:41Z rouault $");
 
 /************************************************************************/
 /*                         OGRDXFBlocksLayer()                          */
@@ -103,7 +102,7 @@ OGRFeature *OGRDXFBlocksLayer::GetNextUnfilteredFeature()
 
     if( iNextSubFeature >= nSubFeatureCount )
     {
-        oIt++;
+        ++oIt;
 
         iNextSubFeature = 0;
 
@@ -179,8 +178,5 @@ OGRFeature *OGRDXFBlocksLayer::GetNextFeature()
 int OGRDXFBlocksLayer::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,OLCStringsAsUTF8) )
-        return TRUE;
-    else
-        return FALSE;
+    return EQUAL(pszCap, OLCStringsAsUTF8);
 }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp
index 8277a92..8598248 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfblockswriterlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxfwriterlayer.cpp 20670 2010-09-22 00:21:17Z warmerdam $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFBlocksWriterLayer used for capturing block
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_featurestyle.h"
 
-CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 20670 2010-09-22 00:21:17Z warmerdam $");
+CPL_CVSID("$Id: ogrdxfblockswriterlayer.cpp 35645 2016-10-08 00:48:42Z goatbar $");
 
 /************************************************************************/
 /*                      OGRDXFBlocksWriterLayer()                       */
@@ -88,10 +87,7 @@ OGRDXFBlocksWriterLayer::~OGRDXFBlocksWriterLayer()
 int OGRDXFBlocksWriterLayer::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,OLCSequentialWrite) )
-        return TRUE;
-    else
-        return FALSE;
+    return EQUAL(pszCap,OLCSequentialWrite);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
index 95d5684..604e172 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxfdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFDataSource class
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrdxfdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdxfdatasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                          OGRDXFDataSource()                          */
@@ -41,8 +40,8 @@ CPL_CVSID("$Id: ogrdxfdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 OGRDXFDataSource::OGRDXFDataSource() :
     fp(NULL),
     iEntitiesSectionOffset(0),
-    bInlineBlocks(FALSE)
-{ }
+    bInlineBlocks(false)
+{}
 
 /************************************************************************/
 /*                         ~OGRDXFDataSource()                          */
@@ -54,7 +53,7 @@ OGRDXFDataSource::~OGRDXFDataSource()
 /* -------------------------------------------------------------------- */
 /*      Destroy layers.                                                 */
 /* -------------------------------------------------------------------- */
-    while( apoLayers.size() > 0 )
+    while( !apoLayers.empty() )
     {
         delete apoLayers.back();
         apoLayers.pop_back();
@@ -83,7 +82,6 @@ int OGRDXFDataSource::TestCapability( CPL_UNUSED const char * pszCap )
 /*                              GetLayer()                              */
 /************************************************************************/
 
-
 OGRLayer *OGRDXFDataSource::GetLayer( int iLayer )
 
 {
@@ -124,8 +122,7 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
 /*      Confirm we have a header section.                               */
 /* -------------------------------------------------------------------- */
     char szLineBuf[257];
-    int  nCode;
-    int  bEntitiesOnly = FALSE;
+    bool bEntitiesOnly = false;
 
     if( ReadValue( szLineBuf ) != 0 || !EQUAL(szLineBuf,"SECTION") )
         return FALSE;
@@ -135,13 +132,12 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
         return FALSE;
 
     if( EQUAL(szLineBuf,"ENTITIES") )
-        bEntitiesOnly = TRUE;
+        bEntitiesOnly = true;
 
     /* Some files might have no header but begin directly with a TABLES section */
     else if( EQUAL(szLineBuf,"TABLES") )
     {
-        if( CPLGetConfigOption( "DXF_ENCODING", NULL ) != NULL )
-            osEncoding = CPLGetConfigOption( "DXF_ENCODING", NULL );
+        osEncoding = CPLGetConfigOption( "DXF_ENCODING", osEncoding );
 
         if( !ReadTablesSection() )
             return FALSE;
@@ -189,7 +185,8 @@ int OGRDXFDataSource::Open( const char * pszFilename, int bHeaderOnly )
 
         if( EQUAL(szLineBuf,"CLASSES") )
         {
-            while( (nCode = ReadValue( szLineBuf,sizeof(szLineBuf) )) > -1
+            // int nCode = 0;
+            while( (/* nCode = */ ReadValue( szLineBuf,sizeof(szLineBuf) )) > -1
                    && !EQUAL(szLineBuf,"ENDSEC") )
             {
                 //printf("C:%d/%s\n", nCode, szLineBuf );
@@ -311,7 +308,7 @@ bool OGRDXFDataSource::ReadTablesSection()
 
 {
     char szLineBuf[257];
-    int  nCode;
+    int nCode = 0;
 
     while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1
            && !EQUAL(szLineBuf,"ENDSEC") )
@@ -366,8 +363,8 @@ bool OGRDXFDataSource::ReadLayerDefinition()
 
 {
     char szLineBuf[257];
-    int  nCode;
-    std::map<CPLString,CPLString> oLayerProperties;
+    int nCode = 0;
+    std::map<CPLString,CPLString>  oLayerProperties;
     CPLString osLayerName = "";
 
     oLayerProperties["Hidden"] = "0";
@@ -414,7 +411,7 @@ bool OGRDXFDataSource::ReadLayerDefinition()
         return false;
     }
 
-    if( oLayerProperties.size() > 0 )
+    if( !oLayerProperties.empty() )
         oLayerTable[osLayerName] = oLayerProperties;
 
     if( nCode == 0 )
@@ -448,7 +445,7 @@ bool OGRDXFDataSource::ReadLineTypeDefinition()
 
 {
     char szLineBuf[257];
-    int  nCode;
+    int nCode = 0;
     CPLString osLineTypeName;
     CPLString osLineTypeDef;
 
@@ -513,7 +510,7 @@ bool OGRDXFDataSource::ReadHeaderSection()
 
 {
     char szLineBuf[257];
-    int  nCode;
+    int nCode = 0;
 
     while( (nCode = ReadValue( szLineBuf, sizeof(szLineBuf) )) > -1
            && !EQUAL(szLineBuf,"ENDSEC") )
@@ -600,8 +597,9 @@ bool OGRDXFDataSource::ReadHeaderSection()
         osEncoding = CPL_ENC_ISO8859_1;
     }
 
-    if( CPLGetConfigOption( "DXF_ENCODING", NULL ) != NULL )
-        osEncoding = CPLGetConfigOption( "DXF_ENCODING", NULL );
+    const char *pszEncoding = CPLGetConfigOption( "DXF_ENCODING", NULL );
+    if( pszEncoding != NULL )
+        osEncoding = pszEncoding;
 
     if( osEncoding != CPL_ENC_ISO8859_1 )
         CPLDebug( "DXF", "Treating DXF as encoding '%s', $DWGCODEPAGE='%s'",
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp
index 3320299..093b9e3 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxfdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFDriver.
@@ -30,7 +29,7 @@
 #include "ogr_dxf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrdxfdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrdxfdriver.cpp 35645 2016-10-08 00:48:42Z goatbar $");
 
 /************************************************************************/
 /*                       OGRDXFDriverIdentify()                         */
@@ -44,32 +43,32 @@ static int OGRDXFDriverIdentify( GDALOpenInfo* poOpenInfo )
     if( EQUAL(CPLGetExtension(poOpenInfo->pszFilename),"dxf") )
         return TRUE;
     const char* pszIter = (const char*)poOpenInfo->pabyHeader;
-    int bFoundZero = FALSE;
-    int i = 0;
-    for(i=0; pszIter[i]; i++)
+    bool bFoundZero = false;
+    int i = 0;  // Used after for.
+    for( ; pszIter[i]; i++ )
     {
         if( pszIter[i] == '0' )
         {
-            int j=i-1;
-            for(; j>=0; j--)
+            int j = i-1;  // Used after for.
+            for( ; j >= 0; j-- )
             {
                 if( pszIter[j] != ' ' )
                     break;
             }
             if( j < 0 || pszIter[j] == '\n'|| pszIter[j] == '\r' )
             {
-                bFoundZero = TRUE;
+                bFoundZero = true;
                 break;
             }
         }
     }
     if( !bFoundZero )
         return FALSE;
-    i ++;
+    i++;
     while( pszIter[i] == ' ' )
-        i ++;
+        i++;
     while( pszIter[i] == '\n' || pszIter[i] == '\r' )
-        i ++;
+        i++;
     if( !STARTS_WITH_CI(pszIter + i, "SECTION") )
         return FALSE;
     i += static_cast<int>(strlen("SECTION"));
@@ -86,7 +85,7 @@ static GDALDataset *OGRDXFDriverOpen( GDALOpenInfo* poOpenInfo )
     if( !OGRDXFDriverIdentify(poOpenInfo) )
         return NULL;
 
-    OGRDXFDataSource   *poDS = new OGRDXFDataSource();
+    OGRDXFDataSource *poDS = new OGRDXFDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename ) )
     {
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
index 5ddfbc2..a542fec 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxflayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxflayer.cpp 33981 2016-04-16 18:31:19Z rouault $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFLayer class.
@@ -33,7 +32,9 @@
 #include "ogrdxf_polyline_smooth.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrdxflayer.cpp 33981 2016-04-16 18:31:19Z rouault $");
+#include <cmath>
+
+CPL_CVSID("$Id: ogrdxflayer.cpp 37837 2017-03-23 22:13:09Z rouault $");
 
 /************************************************************************/
 /*                            OGRDXFLayer()                             */
@@ -125,7 +126,7 @@ void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
       case 100:
       {
           CPLString osSubClass = poFeature->GetFieldAsString("SubClasses");
-          if( osSubClass.size() > 0 )
+          if( !osSubClass.empty() )
               osSubClass += ":";
           osSubClass += pszValue;
           poFeature->SetField( "SubClasses", osSubClass.c_str() );
@@ -161,7 +162,7 @@ void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
       {
           CPLString osAggregate = poFeature->GetFieldAsString("ExtendedEntity");
 
-          if( osAggregate.size() > 0 )
+          if( !osAggregate.empty() )
               osAggregate += " ";
           osAggregate += pszValue;
 
@@ -182,7 +183,6 @@ void OGRDXFLayer::TranslateGenericProperty( OGRFeature *poFeature,
         oStyleProperties["230_N.dZ"] = pszValue;
         break;
 
-
       default:
         break;
     }
@@ -290,22 +290,24 @@ private:
     double dfDeterminant;
     double aadfInverse[4][4];
 
-    double Det2x2( double a, double b, double c, double d )
+    static double Det2x2( double a, double b, double c, double d )
     {
-        return (a*d - b*c);
+        return a*d - b*c;
     }
 
 public:
-    OCSTransformer( double adfNIn[3], bool bInverse = false ) {
+    OCSTransformer( double adfNIn[3], bool bInverse = false ) :
+        aadfInverse()
+    {
         static const double dSmall = 1.0 / 64.0;
-        static const double adfWZ[3] = {0, 0, 1};
-        static const double adfWY[3] = {0, 1, 0};
+        static const double adfWZ[3] = { 0.0, 0.0, 1.0 };
+        static const double adfWY[3] = { 0.0, 1.0, 0.0 };
 
         dfDeterminant = 0.0;
         Scale2Unit( adfNIn );
-        memcpy( this->adfN, adfNIn, sizeof(double)*3 );
+        memcpy( adfN, adfNIn, sizeof(double)*3 );
 
-    if ((ABS(adfN[0]) < dSmall) && (ABS(adfN[1]) < dSmall))
+    if ((std::abs(adfN[0]) < dSmall) && (std::abs(adfN[1]) < dSmall))
             CrossProduct(adfWY, adfN, adfAX);
     else
             CrossProduct(adfWZ, adfN, adfAX);
@@ -315,19 +317,25 @@ public:
     Scale2Unit( adfAY );
 
     if( bInverse == true ) {
-        double a[4] = { 0.0, adfAX[0], adfAY[0], adfN[0] };
-        double b[4] = { 0.0, adfAX[1], adfAY[1], adfN[1] };
-        double c[4] = { 0.0, adfAX[2], adfAY[2], adfN[2] };
+        const double a[4] = { 0.0, adfAX[0], adfAY[0], adfN[0] };
+        const double b[4] = { 0.0, adfAX[1], adfAY[1], adfN[1] };
+        const double c[4] = { 0.0, adfAX[2], adfAY[2], adfN[2] };
 
         dfDeterminant = a[1]*b[2]*c[3] - a[1]*b[3]*c[2]
                       + a[2]*b[3]*c[1] - a[2]*b[1]*c[3]
                       + a[3]*b[1]*c[2] - a[3]*b[2]*c[1];
 
         if( dfDeterminant != 0.0 ) {
-            double k = 1 / dfDeterminant;
-            double a11 = adfAX[0], a12 = adfAY[0], a13 = adfN[0];
-            double a21 = adfAX[1], a22 = adfAY[1], a23 = adfN[1];
-            double a31 = adfAX[2], a32 = adfAY[2], a33 = adfN[2];
+            const double k = 1.0 / dfDeterminant;
+            const double a11 = adfAX[0];
+            const double a12 = adfAY[0];
+            const double a13 = adfN[0];
+            const double a21 = adfAX[1];
+            const double a22 = adfAY[1];
+            const double a23 = adfN[1];
+            const double a31 = adfAX[2];
+            const double a32 = adfAY[2];
+            const double a33 = adfN[2];
 
             aadfInverse[1][1] = k * Det2x2( a22,a23,a32,a33 );
             aadfInverse[1][2] = k * Det2x2( a13,a12,a33,a32 );
@@ -344,35 +352,36 @@ public:
     }
     }
 
-    void CrossProduct(const double *a, const double *b, double *vResult) {
+    static void CrossProduct(const double *a, const double *b, double *vResult) {
         vResult[0] = a[1] * b[2] - a[2] * b[1];
         vResult[1] = a[2] * b[0] - a[0] * b[2];
         vResult[2] = a[0] * b[1] - a[1] * b[0];
     }
 
-    void Scale2Unit(double* adfV) {
-    double dfLen=sqrt(adfV[0]*adfV[0] + adfV[1]*adfV[1] + adfV[2]*adfV[2]);
-    if (dfLen != 0)
-    {
-            adfV[0] /= dfLen;
-            adfV[1] /= dfLen;
-            adfV[2] /= dfLen;
-    }
+    static void Scale2Unit(double* adfV) {
+        double dfLen=sqrt(adfV[0]*adfV[0] + adfV[1]*adfV[1] + adfV[2]*adfV[2]);
+        if (dfLen != 0)
+        {
+                adfV[0] /= dfLen;
+                adfV[1] /= dfLen;
+                adfV[2] /= dfLen;
+        }
     }
-    OGRSpatialReference *GetSourceCS() { return NULL; }
-    OGRSpatialReference *GetTargetCS() { return NULL; }
+    OGRSpatialReference *GetSourceCS() override { return NULL; }
+    OGRSpatialReference *GetTargetCS() override { return NULL; }
     int Transform( int nCount,
-                   double *x, double *y, double *z )
+                   double *x, double *y, double *z ) override
         { return TransformEx( nCount, x, y, z, NULL ); }
 
     int TransformEx( int nCount,
                      double *adfX, double *adfY, double *adfZ,
-                     int *pabSuccess = NULL )
+                     int *pabSuccess = NULL ) override
         {
-            int i;
-            for( i = 0; i < nCount; i++ )
+            for( int i = 0; i < nCount; i++ )
             {
-                double x = adfX[i], y = adfY[i], z = adfZ[i];
+                const double x = adfX[i];
+                const double y = adfY[i];
+                const double z = adfZ[i];
 
                 adfX[i] = x * adfAX[0] + y * adfAY[0] + z * adfN[0];
                 adfY[i] = x * adfAX[1] + y * adfAY[1] + z * adfN[1];
@@ -392,7 +401,9 @@ public:
 
         for( int i = 0; i < nCount; i++ )
         {
-            double x = adfX[i], y = adfY[i], z = adfZ[i];
+            const double x = adfX[i];
+            const double y = adfY[i];
+            const double z = adfZ[i];
 
             adfX[i] = x * aadfInverse[1][1] + y * aadfInverse[1][2]
                     + z * aadfInverse[1][3];
@@ -455,15 +466,19 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
+    double dfX = 0.0;
+    double dfY = 0.0;
+    double dfZ = 0.0;
     double dfAngle = 0.0;
     double dfHeight = 0.0;
-    double dfXDirection = 0.0, dfYDirection = 0.0;
-    int bHaveZ = FALSE;
+    double dfXDirection = 0.0;
+    double dfYDirection = 0.0;
+    bool bHaveZ = false;
     int nAttachmentPoint = -1;
     CPLString osText;
+    CPLString osStyleName = "Arial";
 
     while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
     {
@@ -479,7 +494,7 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
 
           case 30:
             dfZ = CPLAtof(szLineBuf);
-            bHaveZ = TRUE;
+            bHaveZ = true;
             break;
 
           case 40:
@@ -510,6 +525,10 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
             dfAngle = CPLAtof(szLineBuf);
             break;
 
+          case 7:
+            osStyleName = TextUnescape(szLineBuf);
+            break;
+
           default:
             TranslateGenericProperty( poFeature, nCode, szLineBuf );
             break;
@@ -525,7 +544,7 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
     if( nCode == 0 )
         poDS->UnreadValue();
 
-    OGRPoint* poGeom;
+    OGRPoint* poGeom = NULL;
     if( bHaveZ )
         poGeom = new OGRPoint( dfX, dfY, dfZ );
     else
@@ -536,12 +555,11 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
 /* -------------------------------------------------------------------- */
 /*      Apply text after stripping off any extra terminating newline.   */
 /* -------------------------------------------------------------------- */
-    if( osText != "" && osText[osText.size()-1] == '\n' )
+    if( !osText.empty() && osText.back() == '\n' )
         osText.resize( osText.size() - 1 );
 
     poFeature->SetField( "Text", osText );
 
-
 /* -------------------------------------------------------------------- */
 /*      We need to escape double quotes with backslashes before they    */
 /*      can be inserted in the style string.                            */
@@ -549,9 +567,8 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
     if( strchr( osText, '"') != NULL )
     {
         CPLString osEscaped;
-        size_t iC;
 
-        for( iC = 0; iC < osText.size(); iC++ )
+        for( size_t iC = 0; iC < osText.size(); iC++ )
         {
             if( osText[iC] == '"' )
                 osEscaped += "\\\"";
@@ -584,7 +601,7 @@ OGRFeature *OGRDXFLayer::TranslateMTEXT()
     CPLString osStyle;
     char szBuffer[64];
 
-    osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
+    osStyle.Printf("LABEL(f:\"%s\",t:\"%s\"", osStyleName.c_str(), osText.c_str());
 
     if( dfAngle != 0.0 )
     {
@@ -632,15 +649,19 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
+    double dfX = 0.0;
+    double dfY = 0.0;
+    double dfZ = 0.0;
     double dfAngle = 0.0;
     double dfHeight = 0.0;
     CPLString osText;
-    int bHaveZ = FALSE;
+    CPLString osStyleName = "Arial";
+    bool bHaveZ = false;
     int nAnchorPosition = 1;
-    int nHorizontalAlignment = 0, nVerticalAlignment = 0;
+    int nHorizontalAlignment = 0;
+    int nVerticalAlignment = 0;
 
     while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
     {
@@ -656,7 +677,7 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
 
           case 30:
             dfZ = CPLAtof(szLineBuf);
-            bHaveZ = TRUE;
+            bHaveZ = true;
             break;
 
           case 40:
@@ -680,6 +701,10 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
             nVerticalAlignment = atoi(szLineBuf);
             break;
 
+          case 7:
+            osStyleName = TextUnescape(szLineBuf);
+            break;
+          
           default:
             TranslateGenericProperty( poFeature, nCode, szLineBuf );
             break;
@@ -695,7 +720,7 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
     if( nCode == 0 )
         poDS->UnreadValue();
 
-    OGRPoint* poGeom;
+    OGRPoint* poGeom = NULL;
     if( bHaveZ )
         poGeom = new OGRPoint( dfX, dfY, dfZ );
     else
@@ -745,9 +770,8 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
     if( strchr( osText, '"') != NULL )
     {
         CPLString osEscaped;
-        size_t iC;
 
-        for( iC = 0; iC < osText.size(); iC++ )
+        for( size_t iC = 0; iC < osText.size(); iC++ )
         {
             if( osText[iC] == '"' )
                 osEscaped += "\\\"";
@@ -790,8 +814,8 @@ OGRFeature *OGRDXFLayer::TranslateTEXT()
     CPLString osStyle;
     char szBuffer[64];
 
-    osStyle.Printf("LABEL(f:\"Arial\",t:\"%s\"",osText.c_str());
-
+    osStyle.Printf("LABEL(f:\"%s\",t:\"%s\"", osStyleName.c_str(), osText.c_str());
+    
     osStyle += CPLString().Printf(",p:%d", nAnchorPosition);
 
     if( dfAngle != 0.0 )
@@ -832,10 +856,12 @@ OGRFeature *OGRDXFLayer::TranslatePOINT()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
-    int bHaveZ = FALSE;
+    double dfX = 0.0;
+    double dfY = 0.0;
+    double dfZ = 0.0;
+    bool bHaveZ = false;
 
     while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 )
     {
@@ -851,7 +877,7 @@ OGRFeature *OGRDXFLayer::TranslatePOINT()
 
           case 30:
             dfZ = CPLAtof(szLineBuf);
-            bHaveZ = TRUE;
+            bHaveZ = true;
             break;
 
           default:
@@ -869,7 +895,7 @@ OGRFeature *OGRDXFLayer::TranslatePOINT()
     if( nCode == 0 )
         poDS->UnreadValue();
 
-    OGRPoint* poGeom;
+    OGRPoint* poGeom = NULL;
     if( bHaveZ )
         poGeom = new OGRPoint( dfX, dfY, dfZ );
     else
@@ -891,11 +917,15 @@ OGRFeature *OGRDXFLayer::TranslateLINE()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0;
-    double dfX2 = 0.0, dfY2 = 0.0, dfZ2 = 0.0;
-    int bHaveZ = FALSE;
+    double dfX1 = 0.0;
+    double dfY1 = 0.0;
+    double dfZ1 = 0.0;
+    double dfX2 = 0.0;
+    double dfY2 = 0.0;
+    double dfZ2 = 0.0;
+    bool bHaveZ = false;
 
 /* -------------------------------------------------------------------- */
 /*      Process values.                                                 */
@@ -922,12 +952,12 @@ OGRFeature *OGRDXFLayer::TranslateLINE()
 
           case 30:
             dfZ1 = CPLAtof(szLineBuf);
-            bHaveZ = TRUE;
+            bHaveZ = true;
             break;
 
           case 31:
             dfZ2 = CPLAtof(szLineBuf);
-            bHaveZ = TRUE;
+            bHaveZ = true;
             break;
 
           default:
@@ -977,21 +1007,21 @@ OGRFeature *OGRDXFLayer::TranslateLWPOLYLINE()
     // If there are no bulges, then we are a straight-line polyline.
     // Single-vertex polylines become points.
     // Group code 30 (vertex Z) is not part of this entity.
+    char szLineBuf[257];
+    int nCode = 0;
+    int nPolylineFlag = 0;
 
-    char                szLineBuf[257];
-    int                 nCode;
-    int                 nPolylineFlag = 0;
-
-
-    OGRFeature          *poFeature = new OGRFeature( poFeatureDefn );
-    double              dfX = 0.0, dfY = 0.0, dfZ = 0.0;
-    int                 bHaveX = FALSE;
-    int                 bHaveY = FALSE;
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+    double dfX = 0.0;
+    double dfY = 0.0;
+    double dfZ = 0.0;
+    bool bHaveX = false;
+    bool bHaveY = false;
 
-    int                 nNumVertices = 1;   // use 1 based index
-    int                 npolyarcVertexCount = 1;
-    double              dfBulge = 0.0;
-    DXFSmoothPolyline   smoothPolyline;
+    int nNumVertices = 1;   // use 1 based index
+    int npolyarcVertexCount = 1;
+    double dfBulge = 0.0;
+    DXFSmoothPolyline smoothPolyline;
 
     smoothPolyline.setCoordinateDimension(2);
 
@@ -1030,10 +1060,10 @@ OGRFeature *OGRDXFLayer::TranslateLWPOLYLINE()
                 smoothPolyline.AddPoint(dfX, dfY, dfZ, dfBulge);
                 npolyarcVertexCount++;
                 dfBulge = 0.0;
-                bHaveY = FALSE;
+                bHaveY = false;
             }
             dfX = CPLAtof(szLineBuf);
-            bHaveX = TRUE;
+            bHaveX = true;
             break;
 
           case 20:
@@ -1042,17 +1072,16 @@ OGRFeature *OGRDXFLayer::TranslateLWPOLYLINE()
                 smoothPolyline.AddPoint( dfX, dfY, dfZ, dfBulge );
                 npolyarcVertexCount++;
                 dfBulge = 0.0;
-                bHaveX = FALSE;
+                bHaveX = false;
             }
             dfY = CPLAtof(szLineBuf);
-            bHaveY = TRUE;
+            bHaveY = true;
             break;
 
           case 42:
             dfBulge = CPLAtof(szLineBuf);
             break;
 
-
           default:
             TranslateGenericProperty( poFeature, nCode, szLineBuf );
             break;
@@ -1071,7 +1100,6 @@ OGRFeature *OGRDXFLayer::TranslateLWPOLYLINE()
     if( bHaveX && bHaveY )
         smoothPolyline.AddPoint(dfX, dfY, dfZ, dfBulge);
 
-
     if(smoothPolyline.IsEmpty())
     {
         delete poFeature;
@@ -1093,7 +1121,6 @@ OGRFeature *OGRDXFLayer::TranslateLWPOLYLINE()
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                         TranslatePOLYLINE()                          */
 /*                                                                      */
@@ -1104,7 +1131,7 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     int nPolylineFlag = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
@@ -1131,9 +1158,9 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
         return NULL;
     }
 
-    if( (nPolylineFlag & (16 ^ 64)) != 0 )
+    if( (nPolylineFlag & 16) != 0 )
     {
-        CPLDebug( "DXF", "Polygon/polyface mesh not supported." );
+        CPLDebug( "DXF", "Polygon mesh not supported." );
         delete poFeature;
         return NULL;
     }
@@ -1141,10 +1168,19 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
 /* -------------------------------------------------------------------- */
 /*      Collect VERTEXes as a smooth polyline.                          */
 /* -------------------------------------------------------------------- */
-    double              dfX = 0.0, dfY = 0.0, dfZ = 0.0;
-    double              dfBulge = 0.0;
+    double dfX = 0.0;
+    double dfY = 0.0;
+    double dfZ = 0.0;
+    double dfBulge = 0.0;
+    int nVertexFlag = 0;
     DXFSmoothPolyline   smoothPolyline;
-    int                 nVertexFlag = 0;
+    int                 vertexIndex71 = 0;
+    int                 vertexIndex72 = 0;
+    int                 vertexIndex73 = 0;
+    int                 vertexIndex74 = 0;
+    OGRPoint **papoPoints = NULL;
+    int nPoints = 0;
+    OGRPolyhedralSurface *poPS = new OGRPolyhedralSurface();
 
     smoothPolyline.setCoordinateDimension(2);
 
@@ -1158,6 +1194,12 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
             {
                 DXF_LAYER_READER_ERROR();
                 delete poFeature;
+                delete poPS;
+                // delete the list of points
+                for (int i = 0; i < nPoints; i++)
+                    delete papoPoints[i];
+                CPLFree(papoPoints);
+
                 return NULL;
             }
 
@@ -1190,33 +1232,136 @@ OGRFeature *OGRDXFLayer::TranslatePOLYLINE()
                 nVertexFlag = atoi(szLineBuf);
                 break;
 
+              case 71:
+                vertexIndex71 = atoi(szLineBuf);
+                break;
+
+              case 72:
+                vertexIndex72 = atoi(szLineBuf);
+                break;
+
+              case 73:
+                vertexIndex73 = atoi(szLineBuf);
+                break;
+
+              case 74:
+                vertexIndex74 = atoi(szLineBuf);
+                break;
+
               default:
                 break;
             }
         }
+
+        if (((nVertexFlag & 64) != 0) && ((nVertexFlag & 128) != 0))
+        {
+            // add the point to the list of points
+            OGRPoint *poPoint = new OGRPoint(dfX, dfY, dfZ);
+            OGRPoint** papoNewPoints = (OGRPoint **) VSI_REALLOC_VERBOSE( papoPoints,
+                                                     sizeof(void*) * (nPoints+1) );
+
+            papoPoints = papoNewPoints;
+            papoPoints[nPoints] = poPoint;
+            nPoints++;
+        }
+
+        // Note - If any index out of vertexIndex71, vertexIndex72, vertexIndex73 or vertexIndex74
+        // is negative, it means that the line starting from that vertex is invisible
+
+        if (nVertexFlag == 128 && papoPoints != NULL)
+        {
+            // create a polygon and add it to the Polyhedral Surface
+            OGRLinearRing *poLR = new OGRLinearRing();
+            int iPoint = 0;
+            int startPoint = -1;
+            poLR->set3D(TRUE);
+            if (vertexIndex71 > 0 && vertexIndex71 <= nPoints)
+            {
+                if (startPoint == -1)
+                    startPoint = vertexIndex71-1;
+                poLR->setPoint(iPoint,papoPoints[vertexIndex71-1]);
+                iPoint++;
+                vertexIndex71 = 0;
+            }
+            if (vertexIndex72 > 0 && vertexIndex72 <= nPoints)
+            {
+                if (startPoint == -1)
+                    startPoint = vertexIndex72-1;
+                poLR->setPoint(iPoint,papoPoints[vertexIndex72-1]);
+                iPoint++;
+                vertexIndex72 = 0;
+            }
+            if (vertexIndex73 > 0 && vertexIndex73 <= nPoints)
+            {
+                if (startPoint == -1)
+                    startPoint = vertexIndex73-1;
+                poLR->setPoint(iPoint,papoPoints[vertexIndex73-1]);
+                iPoint++;
+                vertexIndex73 = 0;
+            }
+            if (vertexIndex74 > 0 && vertexIndex74 <= nPoints)
+            {
+                if (startPoint == -1)
+                    startPoint = vertexIndex74-1;
+                poLR->setPoint(iPoint,papoPoints[vertexIndex74-1]);
+                iPoint++;
+                vertexIndex74 = 0;
+            }
+
+            // complete the ring
+            poLR->setPoint(iPoint,papoPoints[startPoint]);
+
+            OGRPolygon *poPolygon = new OGRPolygon();
+            poPolygon->addRing((OGRCurve *)poLR);
+
+            poPS->addGeometryDirectly(poPolygon);
+
+            // delete the ring to prevent leakage
+            delete poLR;
+        }
+
         if( nCode < 0 )
         {
             DXF_LAYER_READER_ERROR();
             delete poFeature;
+            delete poPS;
+            // delete the list of points
+            for (int i = 0; i < nPoints; i++)
+                delete papoPoints[i];
+            CPLFree(papoPoints);
             return NULL;
         }
 
-
         // Ignore Spline frame control points ( see #4683 )
         if ((nVertexFlag & 16) == 0)
             smoothPolyline.AddPoint( dfX, dfY, dfZ, dfBulge );
         dfBulge = 0.0;
     }
 
+    // delete the list of points
+    for (int i = 0; i < nPoints; i++)
+        delete papoPoints[i];
+    CPLFree(papoPoints);
+
     if(smoothPolyline.IsEmpty())
     {
         delete poFeature;
+        delete poPS;
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Close polyline if necessary.                                    */
-/* -------------------------------------------------------------------- */
+    if (poPS->getNumGeometries() > 0)
+    {
+        poFeature->SetGeometryDirectly((OGRGeometry *)poPS);
+        return poFeature;
+    }
+
+    else
+        delete poPS;
+
+    /* -------------------------------------------------------------------- */
+    /*      Close polyline if necessary.                                    */
+    /* -------------------------------------------------------------------- */
     if(nPolylineFlag & 0x01)
         smoothPolyline.Close();
 
@@ -1239,10 +1384,13 @@ OGRFeature *OGRDXFLayer::TranslateCIRCLE()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0, dfRadius = 0.0;
-    int bHaveZ = FALSE;
+    double dfX1 = 0.0;
+    double dfY1 = 0.0;
+    double dfZ1 = 0.0;
+    double dfRadius = 0.0;
+    bool bHaveZ = false;
 
 /* -------------------------------------------------------------------- */
 /*      Process values.                                                 */
@@ -1261,7 +1409,7 @@ OGRFeature *OGRDXFLayer::TranslateCIRCLE()
 
           case 30:
             dfZ1 = CPLAtof(szLineBuf);
-            bHaveZ = TRUE;
+            bHaveZ = true;
             break;
 
           case 40:
@@ -1310,13 +1458,18 @@ OGRFeature *OGRDXFLayer::TranslateELLIPSE()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0, dfRatio = 0.0;
-    double dfStartAngle = 0.0, dfEndAngle = 360.0;
-    double dfAxisX=0.0, dfAxisY=0.0, dfAxisZ=0.0;
-    int bHaveZ = FALSE;
-    double adfN[3];
+    double dfX1 = 0.0;
+    double dfY1 = 0.0;
+    double dfZ1 = 0.0;
+    double dfRatio = 0.0;
+    double dfStartAngle = 0.0;
+    double dfEndAngle = 360.0;
+    double dfAxisX = 0.0;
+    double dfAxisY = 0.0;
+    double dfAxisZ=0.0;
+    bool bHaveZ = false;
     bool bApplyOCSTransform = false;
 
 /* -------------------------------------------------------------------- */
@@ -1336,7 +1489,7 @@ OGRFeature *OGRDXFLayer::TranslateELLIPSE()
 
           case 30:
             dfZ1 = CPLAtof(szLineBuf);
-            bHaveZ = TRUE;
+            bHaveZ = true;
             break;
 
           case 11:
@@ -1387,21 +1540,26 @@ OGRFeature *OGRDXFLayer::TranslateELLIPSE()
         && oStyleProperties.count("220_N.dY") != 0
         && oStyleProperties.count("230_N.dZ") != 0 )
     {
-        adfN[0] = CPLAtof(oStyleProperties["210_N.dX"]);
-        adfN[1] = CPLAtof(oStyleProperties["220_N.dY"]);
-        adfN[2] = CPLAtof(oStyleProperties["230_N.dZ"]);
+        double adfN[3] = {
+            CPLAtof(oStyleProperties["210_N.dX"]),
+            CPLAtof(oStyleProperties["220_N.dY"]),
+            CPLAtof(oStyleProperties["230_N.dZ"])
+        };
 
         if( (adfN[0] == 0.0 && adfN[1] == 0.0 && adfN[2] == 1.0) == false )
         {
-            double *x, *y, *z;
             OCSTransformer oTransformer( adfN, true );
 
             bApplyOCSTransform = true;
 
-            x = &dfX1; y = &dfY1, z = &dfZ1;
+            double *x = &dfX1;
+            double *y = &dfY1;
+            double *z = &dfZ1;
             oTransformer.InverseTransform( 1, x, y, z );
 
-            x = &dfAxisX; y = &dfAxisY, z = &dfAxisZ;
+            x = &dfAxisX;
+            y = &dfAxisY;
+            z = &dfAxisZ;
             oTransformer.InverseTransform( 1, x, y, z );
         }
     }
@@ -1410,16 +1568,13 @@ OGRFeature *OGRDXFLayer::TranslateELLIPSE()
 /*      Compute primary and secondary axis lengths, and the angle of    */
 /*      rotation for the ellipse.                                       */
 /* -------------------------------------------------------------------- */
-    double dfPrimaryRadius, dfSecondaryRadius;
-    double dfRotation;
-
-    dfPrimaryRadius = sqrt( dfAxisX * dfAxisX
+    double dfPrimaryRadius = sqrt( dfAxisX * dfAxisX
                             + dfAxisY * dfAxisY
                             + dfAxisZ * dfAxisZ );
 
-    dfSecondaryRadius = dfRatio * dfPrimaryRadius;
+    double dfSecondaryRadius = dfRatio * dfPrimaryRadius;
 
-    dfRotation = -1 * atan2( dfAxisY, dfAxisX ) * 180 / M_PI;
+    double dfRotation = -1 * atan2( dfAxisY, dfAxisX ) * 180 / M_PI;
 
 /* -------------------------------------------------------------------- */
 /*      Create geometry                                                 */
@@ -1455,11 +1610,15 @@ OGRFeature *OGRDXFLayer::TranslateARC()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0, dfRadius = 0.0;
-    double dfStartAngle = 0.0, dfEndAngle = 360.0;
-    int bHaveZ = FALSE;
+    double dfX1 = 0.0;
+    double dfY1 = 0.0;
+    double dfZ1 = 0.0;
+    double dfRadius = 0.0;
+    double dfStartAngle = 0.0;
+    double dfEndAngle = 360.0;
+    bool bHaveZ = false;
 
 /* -------------------------------------------------------------------- */
 /*      Process values.                                                 */
@@ -1478,7 +1637,7 @@ OGRFeature *OGRDXFLayer::TranslateARC()
 
           case 30:
             dfZ1 = CPLAtof(szLineBuf);
-            bHaveZ = TRUE;
+            bHaveZ = true;
             break;
 
           case 40:
@@ -1537,15 +1696,20 @@ OGRFeature *OGRDXFLayer::TranslateARC()
 /************************************************************************/
 
 void rbspline2(int npts,int k,int p1,double b[],double h[],
-        bool xflag, double x[], double p[]);
+        bool bCalculateKnots, double knots[], double p[]);
 
 OGRFeature *OGRDXFLayer::TranslateSPLINE()
 
 {
     char szLineBuf[257];
-    int nCode, nDegree = -1, nOrder = -1, i;
-    int nControlPoints = -1, nKnots = -1;
-    bool bResult = false, bCalculateKnots = false;
+    int nCode;
+    int nDegree = -1;
+    int nOrder = -1;
+    int i;
+    int nControlPoints = -1;
+    int nKnots = -1;
+    bool bResult = false;
+    bool bCalculateKnots = false;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     std::vector<double> adfControlPoints;
     std::vector<double> adfKnots;
@@ -1714,12 +1878,20 @@ OGRFeature *OGRDXFLayer::Translate3DFACE()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-    double dfX1 = 0.0, dfY1 = 0.0, dfZ1 = 0.0;
-    double dfX2 = 0.0, dfY2 = 0.0, dfZ2 = 0.0;
-    double dfX3 = 0.0, dfY3 = 0.0, dfZ3 = 0.0;
-    double dfX4 = 0.0, dfY4 = 0.0, dfZ4 = 0.0;
+    double dfX1 = 0.0;
+    double dfY1 = 0.0;
+    double dfZ1 = 0.0;
+    double dfX2 = 0.0;
+    double dfY2 = 0.0;
+    double dfZ2 = 0.0;
+    double dfX3 = 0.0;
+    double dfY3 = 0.0;
+    double dfZ3 = 0.0;
+    double dfX4 = 0.0;
+    double dfY4 = 0.0;
+    double dfZ4 = 0.0;
 
 /* -------------------------------------------------------------------- */
 /*      Process values.                                                 */
@@ -1864,12 +2036,16 @@ OGRFeature *OGRDXFLayer::TranslateSOLID()
 {
     CPLDebug("SOLID", "translating solid");
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
-    double dfX1 = 0.0, dfY1 = 0.0;
-    double dfX2 = 0.0, dfY2 = 0.0;
-    double dfX3 = 0.0, dfY3 = 0.0;
-    double dfX4 = 0.0, dfY4 = 0.0;
+    double dfX1 = 0.0;
+    double dfY1 = 0.0;
+    double dfX2 = 0.0;
+    double dfY2 = 0.0;
+    double dfX3 = 0.0;
+    double dfY3 = 0.0;
+    double dfX4 = 0.0;
+    double dfY4 = 0.0;
 
     while ((nCode = poDS->ReadValue(szLineBuf, sizeof(szLineBuf))) > 0) {
         switch (nCode) {
@@ -1999,34 +2175,33 @@ public:
     double dfZScale;
     double dfAngle;
 
-    OGRSpatialReference *GetSourceCS() { return NULL; }
-    OGRSpatialReference *GetTargetCS() { return NULL; }
+    OGRSpatialReference *GetSourceCS() override { return NULL; }
+    OGRSpatialReference *GetTargetCS() override { return NULL; }
     int Transform( int nCount,
-                   double *x, double *y, double *z )
+                   double *x, double *y, double *z ) override
         { return TransformEx( nCount, x, y, z, NULL ); }
 
     int TransformEx( int nCount,
                      double *x, double *y, double *z = NULL,
-                     int *pabSuccess = NULL )
+                     int *pabSuccess = NULL ) override
         {
-            int i;
-            for( i = 0; i < nCount; i++ )
+            for( int i = 0; i < nCount; i++ )
             {
-                double dfXNew, dfYNew;
-
                 x[i] *= dfXScale;
                 y[i] *= dfYScale;
-                z[i] *= dfZScale;
+                if( z )
+                    z[i] *= dfZScale;
 
-                dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
-                dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
+                const double dfXNew = x[i] * cos(dfAngle) - y[i] * sin(dfAngle);
+                const double dfYNew = x[i] * sin(dfAngle) + y[i] * cos(dfAngle);
 
                 x[i] = dfXNew;
                 y[i] = dfYNew;
 
                 x[i] += dfXOffset;
                 y[i] += dfYOffset;
-                z[i] += dfZOffset;
+                if( z )
+                    z[i] += dfZOffset;
 
                 if( pabSuccess )
                     pabSuccess[i] = TRUE;
@@ -2043,7 +2218,7 @@ OGRFeature *OGRDXFLayer::TranslateINSERT()
 
 {
     char szLineBuf[257];
-    int nCode;
+    int nCode = 0;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     GeometryInsertTransformer oTransformer;
     CPLString osBlockName;
@@ -2157,9 +2332,9 @@ OGRFeature *OGRDXFLayer::TranslateINSERT()
 /*      Note that while we transform the geometry of the features we    */
 /*      don't adjust subtle things like text angle.                     */
 /* -------------------------------------------------------------------- */
-    unsigned int iSubFeat;
-
-    for( iSubFeat = 0; iSubFeat < poBlock->apoFeatures.size(); iSubFeat++ )
+    for( unsigned int iSubFeat = 0;
+         iSubFeat < poBlock->apoFeatures.size();
+         iSubFeat++ )
     {
         OGRFeature *poSubFeature = poBlock->apoFeatures[iSubFeat]->Clone();
         CPLString osCompEntityId;
@@ -2223,11 +2398,11 @@ OGRFeature *OGRDXFLayer::GetNextUnfilteredFeature()
 /*      Read the entity type.                                           */
 /* -------------------------------------------------------------------- */
     char szLineBuf[257];
-    int nCode;
 
     while( poFeature == NULL )
     {
         // read ahead to an entity.
+        int nCode = 0;
         while( (nCode = poDS->ReadValue(szLineBuf,sizeof(szLineBuf))) > 0 ) {}
         if( nCode < 0 )
         {
@@ -2368,8 +2543,5 @@ OGRFeature *OGRDXFLayer::GetNextFeature()
 int OGRDXFLayer::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,OLCStringsAsUTF8) )
-        return TRUE;
-    else
-        return FALSE;
+    return EQUAL(pszCap, OLCStringsAsUTF8);
 }
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp
index 9cec993..ef69cf4 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxf_diskio.cpp 20278 2010-08-14 15:11:01Z warmerdam $
  *
  * Project:  DXF Translator
  * Purpose:  Implements low level DXF reading with caching and parsing of
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrdxf_diskio.cpp 20278 2010-08-14 15:11:01Z warmerdam $");
+CPL_CVSID("$Id: ogrdxfreader.cpp 36347 2016-11-20 20:43:39Z rouault $");
 
 /************************************************************************/
 /*                            OGRDXFReader()                            */
@@ -44,6 +43,9 @@ OGRDXFReader::OGRDXFReader() :
     iSrcBufferOffset(0),
     nSrcBufferBytes(0),
     iSrcBufferFileOffset(0),
+#if HAVE_CXX11
+    achSrcBuffer{},
+#endif
     nLastValueSize(0),
     nLineNumber(0)
 {}
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp
index adca3cf..981c2e9 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfwriterds.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxfwriterds.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFWriterDS - the OGRDataSource class used for
@@ -32,24 +31,23 @@
 #include "ogr_dxf.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "cpl_vsi_error.h"
 
-CPL_CVSID("$Id: ogrdxfwriterds.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrdxfwriterds.cpp 37091 2017-01-10 17:25:57Z rouault $");
 
 /************************************************************************/
 /*                          OGRDXFWriterDS()                          */
 /************************************************************************/
 
-OGRDXFWriterDS::OGRDXFWriterDS()
-
-{
-    fp = NULL;
-    fpTemp = NULL;
-    poLayer = NULL;
-    poBlocksLayer = NULL;
-    papszLayersToCreate = NULL;
-    nNextFID = 80;
-    nHANDSEEDOffset = 0;
-}
+OGRDXFWriterDS::OGRDXFWriterDS() :
+    nNextFID(80),
+    poLayer(NULL),
+    poBlocksLayer(NULL),
+    fp(NULL),
+    fpTemp(NULL),
+    papszLayersToCreate(NULL),
+    nHANDSEEDOffset(0)
+{}
 
 /************************************************************************/
 /*                         ~OGRDXFWriterDS()                          */
@@ -73,11 +71,10 @@ OGRDXFWriterDS::~OGRDXFWriterDS()
 /* -------------------------------------------------------------------- */
 /*      Copy in the temporary file contents.                            */
 /* -------------------------------------------------------------------- */
-            const char *pszLine;
-
             VSIFCloseL(fpTemp);
             fpTemp = VSIFOpenL( osTempFilename, "r" );
 
+            const char *pszLine = NULL;
             while( (pszLine = CPLReadLineL(fpTemp)) != NULL )
             {
                 VSIFWriteL( pszLine, 1, strlen(pszLine), fp );
@@ -138,7 +135,6 @@ int OGRDXFWriterDS::TestCapability( const char * pszCap )
 /*                              GetLayer()                              */
 /************************************************************************/
 
-
 OGRLayer *OGRDXFWriterDS::GetLayer( int iLayer )
 
 {
@@ -227,13 +223,13 @@ int OGRDXFWriterDS::Open( const char * pszFilename, char **papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszFilename, "w+" );
+    fp = VSIFOpenExL( pszFilename, "w+", true );
 
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to open '%s' for writing.",
-                  pszFilename );
+                  "Failed to open '%s' for writing: %s",
+                  pszFilename, VSIGetLastErrorMsg() );
         return FALSE;
     }
 
@@ -287,7 +283,7 @@ OGRLayer *OGRDXFWriterDS::ICreateLayer( const char *pszName,
 /*                             WriteValue()                             */
 /************************************************************************/
 
-static int WriteValue( VSILFILE *fp, int nCode, const char *pszLine )
+static bool WriteValue( VSILFILE *fp, int nCode, const char *pszLine )
 
 {
     char szLinePair[300];
@@ -298,17 +294,17 @@ static int WriteValue( VSILFILE *fp, int nCode, const char *pszLine )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Attempt to write line to DXF file failed, disk full?." );
-        return FALSE;
+        return false;
     }
-    else
-        return TRUE;
+
+    return true;
 }
 
 /************************************************************************/
 /*                             WriteValue()                             */
 /************************************************************************/
 
-static int WriteValue( VSILFILE *fp, int nCode, double dfValue )
+static bool WriteValue( VSILFILE *fp, int nCode, double dfValue )
 
 {
     char szLinePair[64];
@@ -319,16 +315,16 @@ static int WriteValue( VSILFILE *fp, int nCode, double dfValue )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Attempt to write line to DXF file failed, disk full?." );
-        return FALSE;
+        return false;
     }
-    else
-        return TRUE;
+
+    return true;
 }
 /************************************************************************/
 /*                        TransferUpdateHeader()                        */
 /************************************************************************/
 
-int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
+bool OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
 
 {
     oHeaderDS.ResetReadPointer( 0 );
@@ -337,8 +333,10 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
 /*      Copy header, inserting in new objects as needed.                */
 /* -------------------------------------------------------------------- */
     char szLineBuf[257];
-    int nCode;
-    CPLString osSection, osTable, osEntity;
+    int nCode = 0;
+    CPLString osSection;
+    CPLString osTable;
+    CPLString osEntity;
 
     while( (nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1
            && osSection != "ENTITIES" )
@@ -350,7 +348,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
             if( osTable == "LAYER" )
             {
                 if( !WriteNewLayerDefinitions( fp ) )
-                    return FALSE;
+                    return false;
             }
 
             // If at the end of the BLOCK_RECORD TABLE consider inserting
@@ -358,7 +356,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
             if( osTable == "BLOCK_RECORD" && poBlocksLayer )
             {
                 if( !WriteNewBlockRecords( fp ) )
-                    return FALSE;
+                    return false;
             }
 
             // If at the end of the LTYPE TABLE consider inserting
@@ -366,7 +364,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
             if( osTable == "LTYPE" )
             {
                 if( !WriteNewLineTypeRecords( fp ) )
-                    return FALSE;
+                    return false;
             }
 
             osTable = "";
@@ -378,7 +376,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
             && poBlocksLayer != NULL )
         {
             if( !WriteNewBlockDefinitions( fp ) )
-                return FALSE;
+                return false;
         }
 
         // We need to keep track of where $HANDSEED is so that we can
@@ -386,7 +384,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
         if( nCode == 9 && EQUAL(szLineBuf,"$HANDSEED") )
         {
             if( !WriteValue( fpOut, nCode, szLineBuf ) )
-                return FALSE;
+                return false;
 
             nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
 
@@ -404,19 +402,19 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
         if( nCode == 9 && EQUAL(szLineBuf,"$EXTMIN") )
         {
             if( !WriteValue( fpOut, nCode, szLineBuf ) )
-                return FALSE;
+                return false;
 
             nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
             if (nCode == 10)
             {
                 if( !WriteValue( fpOut, nCode, oGlobalEnvelope.MinX ) )
-                    return FALSE;
+                    return false;
 
                 nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
                 if (nCode == 20)
                 {
                     if( !WriteValue( fpOut, nCode, oGlobalEnvelope.MinY ) )
-                        return FALSE;
+                        return false;
 
                     continue;
                 }
@@ -427,19 +425,19 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
         if( nCode == 9 && EQUAL(szLineBuf,"$EXTMAX") )
         {
             if( !WriteValue( fpOut, nCode, szLineBuf ) )
-                return FALSE;
+                return false;
 
             nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
             if (nCode == 10)
             {
                 if( !WriteValue( fpOut, nCode, oGlobalEnvelope.MaxX ) )
-                    return FALSE;
+                    return false;
 
                 nCode = oHeaderDS.ReadValue( szLineBuf, sizeof(szLineBuf) );
                 if (nCode == 20)
                 {
                     if( !WriteValue( fpOut, nCode, oGlobalEnvelope.MaxY ) )
-                        return FALSE;
+                        return false;
 
                     continue;
                 }
@@ -448,7 +446,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
 
         // Copy over the source line.
         if( !WriteValue( fpOut, nCode, szLineBuf ) )
-            return FALSE;
+            return false;
 
         // Track what entity we are in - that is the last "code 0" object.
         if( nCode == 0  )
@@ -462,7 +460,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
                 break;
 
             if( !WriteValue( fpOut, nCode, szLineBuf ) )
-                return FALSE;
+                return false;
 
             osSection = szLineBuf;
         }
@@ -472,7 +470,7 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
         {
             nCode = oHeaderDS.ReadValue( szLineBuf );
             if( !WriteValue( fpOut, nCode, szLineBuf ) )
-                return FALSE;
+                return false;
 
             osTable = szLineBuf;
         }
@@ -481,14 +479,14 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
         // the layer contents while copying so we can duplicate
         // it for any new layer definitions.
         if( nCode == 0 && EQUAL(szLineBuf,"LAYER")
-            && osTable == "LAYER" && aosDefaultLayerText.size() == 0 )
+            && osTable == "LAYER" && aosDefaultLayerText.empty() )
         {
             do {
                 anDefaultLayerCode.push_back( nCode );
                 aosDefaultLayerText.push_back( szLineBuf );
 
                 if( nCode != 0 && !WriteValue( fpOut, nCode, szLineBuf ) )
-                    return FALSE;
+                    return false;
 
                 nCode = oHeaderDS.ReadValue( szLineBuf );
 
@@ -504,33 +502,31 @@ int OGRDXFWriterDS::TransferUpdateHeader( VSILFILE *fpOut )
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                       TransferUpdateTrailer()                        */
 /************************************************************************/
 
-int OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
+bool OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
 {
-    OGRDXFReader oReader;
-    VSILFILE *l_fp;
-
 /* -------------------------------------------------------------------- */
 /*      Open the file and setup a reader.                               */
 /* -------------------------------------------------------------------- */
-    l_fp = VSIFOpenL( osTrailerFile, "r" );
+    VSILFILE *l_fp = VSIFOpenL( osTrailerFile, "r" );
 
     if( l_fp == NULL )
-        return FALSE;
+        return false;
 
+    OGRDXFReader oReader;
     oReader.Initialize( l_fp );
 
 /* -------------------------------------------------------------------- */
 /*      Scan ahead to find the OBJECTS section.                         */
 /* -------------------------------------------------------------------- */
     char szLineBuf[257];
-    int  nCode;
+    int nCode = 0;
 
     while( (nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 )
     {
@@ -547,7 +543,7 @@ int OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Failed to find OBJECTS section in trailer file '%s'.",
                   osTrailerFile.c_str() );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -566,13 +562,13 @@ int OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
         if( !WriteValue( fpOut, nCode, szLineBuf ) )
         {
             VSIFCloseL( fp );
-            return FALSE;
+            return false;
         }
     }
 
     VSIFCloseL( l_fp );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -582,18 +578,18 @@ int OGRDXFWriterDS::TransferUpdateTrailer( VSILFILE *fpOut )
 /*      variable.                                                       */
 /************************************************************************/
 
-int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fpIn )
+bool OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fpIn )
 
 {
 /* -------------------------------------------------------------------- */
 /*      What is a good next handle seed?  Scan existing values.         */
 /* -------------------------------------------------------------------- */
-    unsigned int   nHighestHandle = 0;
+    unsigned int nHighestHandle = 0;
     std::set<CPLString>::iterator it;
 
-    for( it = aosUsedEntities.begin(); it != aosUsedEntities.end(); it++ )
+    for( it = aosUsedEntities.begin(); it != aosUsedEntities.end(); ++it )
     {
-        unsigned int nHandle;
+        unsigned int nHandle = 0;
         if( sscanf( (*it).c_str(), "%x", &nHandle ) == 1 )
         {
             if( nHandle > nHighestHandle )
@@ -604,15 +600,14 @@ int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fpIn )
 /* -------------------------------------------------------------------- */
 /*      Read the existing handseed value, replace it, and write back.   */
 /* -------------------------------------------------------------------- */
-    char szWorkBuf[30];
-    int  i = 0;
-
     if( nHANDSEEDOffset == 0 )
-        return FALSE;
+        return false;
 
+    char szWorkBuf[30];
     VSIFSeekL( fpIn, nHANDSEEDOffset, SEEK_SET );
     VSIFReadL( szWorkBuf, 1, sizeof(szWorkBuf), fpIn );
 
+    int i = 0;
     while( szWorkBuf[i] != '\n' )
         i++;
 
@@ -628,26 +623,26 @@ int OGRDXFWriterDS::FixupHANDSEED( VSILFILE *fpIn )
     VSIFSeekL( fpIn, nHANDSEEDOffset, SEEK_SET );
     VSIFWriteL( szWorkBuf, 1, sizeof(szWorkBuf), fp );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                      WriteNewLayerDefinitions()                      */
 /************************************************************************/
 
-int  OGRDXFWriterDS::WriteNewLayerDefinitions( VSILFILE * fpOut )
+bool OGRDXFWriterDS::WriteNewLayerDefinitions( VSILFILE * fpOut )
 
 {
-    int iLayer, nNewLayers = CSLCount(papszLayersToCreate);
+    const int nNewLayers = CSLCount(papszLayersToCreate);
 
-    for( iLayer = 0; iLayer < nNewLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < nNewLayers; iLayer++ )
     {
         for( unsigned i = 0; i < aosDefaultLayerText.size(); i++ )
         {
             if( anDefaultLayerCode[i] == 2 )
             {
                 if( !WriteValue( fpOut, 2, papszLayersToCreate[iLayer] ) )
-                    return FALSE;
+                    return false;
             }
             else if( anDefaultLayerCode[i] == 5 )
             {
@@ -658,30 +653,30 @@ int  OGRDXFWriterDS::WriteNewLayerDefinitions( VSILFILE * fpOut )
                 if( !WriteValue( fpOut,
                                  anDefaultLayerCode[i],
                                  aosDefaultLayerText[i] ) )
-                    return FALSE;
+                    return false;
             }
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                      WriteNewLineTypeRecords()                       */
 /************************************************************************/
 
-int OGRDXFWriterDS::WriteNewLineTypeRecords( VSILFILE *fpIn )
+bool OGRDXFWriterDS::WriteNewLineTypeRecords( VSILFILE *fpIn )
 
 {
     if( poLayer == NULL )
-        return TRUE;
+        return true;
 
     std::map<CPLString,CPLString>::iterator oIt;
     std::map<CPLString,CPLString>& oNewLineTypes =
         poLayer->GetNewLineTypeMap();
 
     for( oIt = oNewLineTypes.begin();
-         oIt != oNewLineTypes.end(); oIt++ )
+         oIt != oNewLineTypes.end(); ++oIt )
     {
         WriteValue( fpIn, 0, "LTYPE" );
         WriteEntityID( fpIn );
@@ -697,14 +692,14 @@ int OGRDXFWriterDS::WriteNewLineTypeRecords( VSILFILE *fpIn )
                   (*oIt).first.c_str() );
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                        WriteNewBlockRecords()                        */
 /************************************************************************/
 
-int OGRDXFWriterDS::WriteNewBlockRecords( VSILFILE * fpIn )
+bool OGRDXFWriterDS::WriteNewBlockRecords( VSILFILE * fpIn )
 
 {
     std::set<CPLString> aosAlreadyHandled;
@@ -741,17 +736,17 @@ int OGRDXFWriterDS::WriteNewBlockRecords( VSILFILE * fpIn )
         WriteValue( fpIn, 100, "AcDbBlockTableRecord" );
         WriteValue( fpIn, 2, poThisBlockFeat->GetFieldAsString("BlockName") );
         if( !WriteValue( fpIn, 340, "0" ) )
-            return FALSE;
+            return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                      WriteNewBlockDefinitions()                      */
 /************************************************************************/
 
-int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fpIn )
+bool OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fpIn )
 
 {
     poLayer->ResetFP( fpIn );
@@ -800,7 +795,7 @@ int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fpIn )
 /*      Write out the feature entities.                                 */
 /* -------------------------------------------------------------------- */
         if( poLayer->CreateFeature( poThisBlockFeat ) != OGRERR_NONE )
-            return FALSE;
+            return false;
 
 /* -------------------------------------------------------------------- */
 /*      Write out following features if they are the same block.        */
@@ -813,7 +808,7 @@ int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fpIn )
 
             if( poLayer->CreateFeature( poBlocksLayer->apoBlocks[iBlock] )
                 != OGRERR_NONE )
-                return FALSE;
+                return false;
         }
 
 /* -------------------------------------------------------------------- */
@@ -829,7 +824,7 @@ int OGRDXFWriterDS::WriteNewBlockDefinitions( VSILFILE * fpIn )
         WriteValue( fpIn, 100, "AcDbBlockEnd" );
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -844,24 +839,22 @@ void OGRDXFWriterDS::ScanForEntities( const char *pszFilename,
                                       const char *pszTarget )
 
 {
-    OGRDXFReader oReader;
-    VSILFILE *l_fp;
-
 /* -------------------------------------------------------------------- */
 /*      Open the file and setup a reader.                               */
 /* -------------------------------------------------------------------- */
-    l_fp = VSIFOpenL( pszFilename, "r" );
+    VSILFILE *l_fp = VSIFOpenL( pszFilename, "r" );
 
     if( l_fp == NULL )
         return;
 
+    OGRDXFReader oReader;
     oReader.Initialize( l_fp );
 
 /* -------------------------------------------------------------------- */
 /*      Add every code "5" line to our entities list.                   */
 /* -------------------------------------------------------------------- */
     char szLineBuf[257];
-    int  nCode;
+    int nCode = 0;
     const char *pszPortion = "HEADER";
 
     while( (nCode = oReader.ReadValue( szLineBuf, sizeof(szLineBuf) )) != -1 )
@@ -896,16 +889,13 @@ void OGRDXFWriterDS::ScanForEntities( const char *pszFilename,
 /*      Does the mentioned entity already exist?                        */
 /************************************************************************/
 
-int OGRDXFWriterDS::CheckEntityID( const char *pszEntityID )
+bool OGRDXFWriterDS::CheckEntityID( const char *pszEntityID )
 
 {
     std::set<CPLString>::iterator it;
 
     it = aosUsedEntities.find( pszEntityID );
-    if( it != aosUsedEntities.end() )
-        return TRUE;
-    else
-        return FALSE;
+    return it != aosUsedEntities.end();
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp b/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
index aa6de22..272bb2a 100644
--- a/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
+++ b/ogr/ogrsf_frmts/dxf/ogrdxfwriterlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdxfwriterlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  DXF Translator
  * Purpose:  Implements OGRDXFWriterLayer - the OGRLayer class used for
@@ -34,18 +33,19 @@
 #include "cpl_string.h"
 #include "ogr_featurestyle.h"
 
-CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+#include <cstdlib>
+
+CPL_CVSID("$Id: ogrdxfwriterlayer.cpp 36883 2016-12-15 13:31:12Z rouault $");
 
 /************************************************************************/
 /*                         OGRDXFWriterLayer()                          */
 /************************************************************************/
 
-OGRDXFWriterLayer::OGRDXFWriterLayer( OGRDXFWriterDS *poDSIn, VSILFILE *fpIn )
-
+OGRDXFWriterLayer::OGRDXFWriterLayer( OGRDXFWriterDS *poDSIn, VSILFILE *fpIn ) :
+    fp(fpIn),
+    poFeatureDefn(NULL),  // TODO(schwehr): Can I move the new here?
+    poDS(poDSIn)
 {
-    this->fp = fpIn;
-    this->poDS = poDSIn;
-
     nNextAutoID = 1;
     bWriteHatch = CPLTestBool(CPLGetConfigOption("DXF_WRITE_HATCH", "YES"));
 
@@ -221,16 +221,31 @@ OGRErr OGRDXFWriterLayer::WriteCore( OGRFeature *poFeature )
     }
     else
     {
+        CPLString osSanitizedLayer(pszLayer);
+        // Replaced restricted characters with underscore
+        // See http://docs.autodesk.com/ACD/2010/ENU/AutoCAD%202010%20User%20Documentation/index.html?url=WS1a9193826455f5ffa23ce210c4a30acaf-7345.htm,topicNumber=d0e41665
+        const char achForbiddenChars[] = {
+          '<', '>', '/', '\\', '"', ':', ';', '?', '*', '|', '=', '\'' };
+        for( size_t i = 0; i < CPL_ARRAYSIZE(achForbiddenChars); ++i )
+        {
+            osSanitizedLayer.replaceAll( achForbiddenChars[i], '_' );
+        }
+
+        // also remove newline characters (#15067)
+        osSanitizedLayer.replaceAll( "\r\n", "_" );
+        osSanitizedLayer.replaceAll( '\r', '_' );
+        osSanitizedLayer.replaceAll( '\n', '_' );
+
         const char *pszExists =
-            poDS->oHeaderDS.LookupLayerProperty( pszLayer, "Exists" );
+            poDS->oHeaderDS.LookupLayerProperty( osSanitizedLayer, "Exists" );
         if( (pszExists == NULL || strlen(pszExists) == 0)
-            && CSLFindString( poDS->papszLayersToCreate, pszLayer ) == -1 )
+            && CSLFindString( poDS->papszLayersToCreate, osSanitizedLayer ) == -1 )
         {
             poDS->papszLayersToCreate =
-                CSLAddString( poDS->papszLayersToCreate, pszLayer );
+                CSLAddString( poDS->papszLayersToCreate, osSanitizedLayer );
         }
 
-        WriteValue( 8, pszLayer );
+        WriteValue( 8, osSanitizedLayer );
     }
 
     return OGRERR_NONE;
@@ -262,7 +277,7 @@ OGRErr OGRDXFWriterLayer::WriteINSERT( OGRFeature *poFeature )
     if( poTool && poTool->GetType() == OGRSTCSymbol )
     {
         OGRStyleSymbol *poSymbol = (OGRStyleSymbol *) poTool;
-        GBool  bDefault;
+        GBool bDefault;
 
         if( poSymbol->Color(bDefault) != NULL && !bDefault )
             WriteValue( 62, ColorStringToDXFColor( poSymbol->Color(bDefault) ) );
@@ -287,7 +302,7 @@ OGRErr OGRDXFWriterLayer::WriteINSERT( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Write scaling.                                                  */
 /* -------------------------------------------------------------------- */
-    int nScaleCount;
+    int nScaleCount = 0;
     const double *padfScale =
         poFeature->GetFieldAsDoubleList( "BlockScale", &nScaleCount );
 
@@ -301,7 +316,7 @@ OGRErr OGRDXFWriterLayer::WriteINSERT( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Write rotation.                                                 */
 /* -------------------------------------------------------------------- */
-    double dfAngle = poFeature->GetFieldAsDouble( "BlockAngle" );
+    const double dfAngle = poFeature->GetFieldAsDouble( "BlockAngle" );
 
     if( dfAngle != 0.0 )
     {
@@ -374,10 +389,7 @@ CPLString OGRDXFWriterLayer::TextEscape( const char *pszInput )
     wchar_t *panInput = CPLRecodeToWChar( pszInput,
                                           CPL_ENC_UTF8,
                                           CPL_ENC_UCS2 );
-    int i;
-
-
-    for( i = 0; panInput[i] != 0; i++ )
+    for( int i = 0; panInput[i] != 0; i++ )
     {
         if( panInput[i] == '\n' )
             osResult += "\\P";
@@ -444,7 +456,7 @@ OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Angle                                                           */
 /* -------------------------------------------------------------------- */
-        double dfAngle = poLabel->Angle(bDefault);
+        const double dfAngle = poLabel->Angle(bDefault);
 
         // The DXF2000 reference says this is in radians, but in files
         // I see it seems to be in degrees. Perhaps this is version dependent?
@@ -456,7 +468,7 @@ OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature )
 /*      doubt the default translation mechanism will be much good.      */
 /* -------------------------------------------------------------------- */
         poTool->SetUnit( OGRSTUGround );
-        double dfHeight = poLabel->Size(bDefault);
+        const double dfHeight = poLabel->Size(bDefault);
 
         if( !bDefault )
             WriteValue( 40, dfHeight );
@@ -464,7 +476,7 @@ OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Anchor / Attachment Point                                       */
 /* -------------------------------------------------------------------- */
-        int nAnchor = poLabel->Anchor(bDefault);
+        const int nAnchor = poLabel->Anchor(bDefault);
 
         if( !bDefault )
         {
@@ -505,7 +517,6 @@ OGRErr OGRDXFWriterLayer::WriteTEXT( OGRFeature *poFeature )
     }
 
     return OGRERR_NONE;
-
 }
 
 /************************************************************************/
@@ -515,15 +526,13 @@ CPLString
 OGRDXFWriterLayer::PrepareLineTypeDefinition( CPL_UNUSED OGRFeature *poFeature,
                                               OGRStyleTool *poTool )
 {
-    CPLString osDef;
     OGRStylePen *poPen = (OGRStylePen *) poTool;
     GBool  bDefault;
-    const char *pszPattern;
 
 /* -------------------------------------------------------------------- */
 /*      Fetch pattern.                                                  */
 /* -------------------------------------------------------------------- */
-    pszPattern = poPen->Pattern( bDefault );
+    const char *pszPattern = poPen->Pattern( bDefault );
     if( bDefault || strlen(pszPattern) == 0 )
         return "";
 
@@ -531,18 +540,18 @@ OGRDXFWriterLayer::PrepareLineTypeDefinition( CPL_UNUSED OGRFeature *poFeature,
 /*      Split into pen up / pen down bits.                              */
 /* -------------------------------------------------------------------- */
     char **papszTokens = CSLTokenizeString(pszPattern);
-    int i;
     double dfTotalLength = 0;
+    CPLString osDef;
 
-    for( i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
+    for( int i = 0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
     {
         const char *pszToken = papszTokens[i];
-        const char *pszUnit;
         CPLString osAmount;
         CPLString osDXFEntry;
 
         // Split amount and unit.
-        for( pszUnit = pszToken;
+        const char *pszUnit = pszToken;  // Used after for.
+        for( ;
              strchr( "0123456789.", *pszUnit) != NULL;
              pszUnit++ ) {}
 
@@ -601,10 +610,9 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
         || wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString )
     {
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
-        int iGeom;
         OGRErr eErr = OGRERR_NONE;
 
-        for( iGeom = 0;
+        for( int iGeom = 0;
              eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries();
              iGeom++ )
         {
@@ -617,14 +625,14 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
 /* -------------------------------------------------------------------- */
 /*      Polygons are written with on entity per ring.                   */
 /* -------------------------------------------------------------------- */
-    if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon )
+    if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon
+        || wkbFlatten(poGeom->getGeometryType()) == wkbTriangle)
     {
         OGRPolygon *poPoly = (OGRPolygon *) poGeom;
-        int iGeom;
         OGRErr eErr;
 
         eErr = WritePOLYLINE( poFeature, poPoly->getExteriorRing() );
-        for( iGeom = 0;
+        for( int iGeom = 0;
              eErr == OGRERR_NONE && iGeom < poPoly->getNumInteriorRings();
              iGeom++ )
         {
@@ -702,14 +710,14 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
     if( poTool && poTool->GetType() == OGRSTCPen )
     {
         OGRStylePen *poPen = (OGRStylePen *) poTool;
-        GBool  bDefault;
+        GBool bDefault;
 
         if( poPen->Color(bDefault) != NULL && !bDefault )
             WriteValue( 62, ColorStringToDXFColor( poPen->Color(bDefault) ) );
 
         // we want to fetch the width in ground units.
         poPen->SetUnit( OGRSTUGround, 1.0 );
-        double dfWidth = poPen->Width(bDefault);
+        const double dfWidth = poPen->Width(bDefault);
 
         if( !bDefault )
             WriteValue( 370, (int) floor(dfWidth * 100 + 0.5) );
@@ -720,7 +728,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
 /* -------------------------------------------------------------------- */
     CPLString osLineType = poFeature->GetFieldAsString( "Linetype" );
 
-    if( osLineType.size() > 0
+    if( !osLineType.empty()
         && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL
             || oNewLineTypes.count(osLineType) > 0 ) )
     {
@@ -739,7 +747,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
 
             for( it = oNewLineTypes.begin();
                  it != oNewLineTypes.end();
-                 it++ )
+                 ++it )
             {
                 if( (*it).second == osDefinition )
                 {
@@ -778,9 +786,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
             return OGRERR_FAILURE;
     }
 
-    int iVert;
-
-    for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
+    for( int iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
     {
         if( bHasDifferentZ )
         {
@@ -827,9 +833,7 @@ OGRErr OGRDXFWriterLayer::WritePOLYLINE( OGRFeature *poFeature,
         WriteValue( 70, 0 );
     WriteValue( 66, "1" );
 
-    int iVert;
-
-    for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
+    for( int iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
     {
         WriteValue( 0, "VERTEX" );
         WriteValue( 8, "0" );
@@ -874,10 +878,9 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
     if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
     {
         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
-        int iGeom;
         OGRErr eErr = OGRERR_NONE;
 
-        for( iGeom = 0;
+        for( int iGeom = 0;
              eErr == OGRERR_NONE && iGeom < poGC->getNumGeometries();
              iGeom++ )
         {
@@ -890,8 +893,11 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
 /* -------------------------------------------------------------------- */
 /*      Do we now have a geometry we can work with?                     */
 /* -------------------------------------------------------------------- */
-    if( wkbFlatten(poGeom->getGeometryType()) != wkbPolygon )
+    if( wkbFlatten(poGeom->getGeometryType()) != wkbPolygon &&
+        wkbFlatten(poGeom->getGeometryType()) != wkbTriangle )
+    {
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Write as a hatch.                                               */
@@ -960,7 +966,7 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
 /* -------------------------------------------------------------------- */
     CPLString osLineType = poFeature->GetFieldAsString( "Linetype" );
 
-    if( osLineType.size() > 0
+    if( !osLineType.empty()
         && (poDS->oHeaderDS.LookupLineType( osLineType ) != NULL
             || oNewLineTypes.count(osLineType) > 0 ) )
     {
@@ -1018,12 +1024,9 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
 
     for( int iRing = -1; iRing < poPoly->getNumInteriorRings(); iRing++ )
     {
-        OGRLinearRing *poLR;
-
-        if( iRing == -1 )
-            poLR = poPoly->getExteriorRing();
-        else
-            poLR = poPoly->getInteriorRing( iRing );
+        OGRLinearRing *poLR = iRing == -1
+            ? poPoly->getExteriorRing()
+            : poPoly->getInteriorRing( iRing );
 
         WriteValue( 92, 2 ); // Polyline
         WriteValue( 72, 0 ); // has bulge
@@ -1059,9 +1062,7 @@ OGRErr OGRDXFWriterLayer::WriteHATCH( OGRFeature *poFeature,
         WriteValue( 70, 0 );
     WriteValue( 66, "1" );
 
-    int iVert;
-
-    for( iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
+    for( int iVert = 0; iVert < poLS->getNumPoints(); iVert++ )
     {
         WriteValue( 0, "VERTEX" );
         WriteValue( 8, "0" );
@@ -1137,7 +1138,8 @@ OGRErr OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature )
         return WritePOLYLINE( poFeature );
 
     else if( eGType == wkbPolygon
-             || eGType == wkbMultiPolygon )
+             || eGType == wkbTriangle
+             || eGType == wkbMultiPolygon)
     {
         if( bWriteHatch )
             return WriteHATCH( poFeature );
@@ -1150,9 +1152,7 @@ OGRErr OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature )
     {
         OGRGeometryCollection *poGC = (OGRGeometryCollection *)
             poFeature->StealGeometry();
-        int iGeom;
-
-        for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
+        for( int iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
         {
             poFeature->SetGeometry( poGC->getGeometryRef(iGeom) );
 
@@ -1160,7 +1160,6 @@ OGRErr OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature )
 
             if( eErr != OGRERR_NONE )
                 return eErr;
-
         }
 
         poFeature->SetGeometryDirectly( poGC );
@@ -1188,10 +1187,13 @@ int OGRDXFWriterLayer::ColorStringToDXFColor( const char *pszRGB )
     if( pszRGB == NULL )
         return -1;
 
-    int nRed, nGreen, nBlue, nTransparency = 255;
+    unsigned int nRed = 0;
+    unsigned int nGreen = 0;
+    unsigned int nBlue = 0;
+    unsigned int nTransparency = 255;
 
-    int nCount  = sscanf(pszRGB,"#%2x%2x%2x%2x",&nRed,&nGreen,&nBlue,
-                         &nTransparency);
+    const int nCount =
+        sscanf(pszRGB, "#%2x%2x%2x%2x", &nRed, &nGreen, &nBlue, &nTransparency);
 
     if (nCount < 3 )
         return -1;
@@ -1200,15 +1202,15 @@ int OGRDXFWriterLayer::ColorStringToDXFColor( const char *pszRGB )
 /*      Find near color in DXF palette.                                 */
 /* -------------------------------------------------------------------- */
     const unsigned char *pabyDXFColors = ACGetColorTable();
-    int i;
     int nMinDist = 768;
     int nBestColor = -1;
 
-    for( i = 1; i < 256; i++ )
+    for( int i = 1; i < 256; i++ )
     {
-        int nDist = ABS(nRed - pabyDXFColors[i*3+0])
-            + ABS(nGreen - pabyDXFColors[i*3+1])
-            + ABS(nBlue  - pabyDXFColors[i*3+2]);
+        const int nDist =
+            std::abs(static_cast<int>(nRed) - pabyDXFColors[i*3+0])
+            + std::abs(static_cast<int>(nGreen) - pabyDXFColors[i*3+1])
+            + std::abs(static_cast<int>(nBlue)  - pabyDXFColors[i*3+2]);
 
         if( nDist < nMinDist )
         {
diff --git a/ogr/ogrsf_frmts/edigeo/drv_edigeo.html b/ogr/ogrsf_frmts/edigeo/drv_edigeo.html
index 715306a..918a4e3 100644
--- a/ogr/ogrsf_frmts/edigeo/drv_edigeo.html
+++ b/ogr/ogrsf_frmts/edigeo/drv_edigeo.html
@@ -56,7 +56,7 @@ according to the value of xxx=OBJ_OBJ_LNK_LAYER. This can be disabled by setting
 <ul>
 <li> <a href="http://georezo.net/wiki/main/donnees/edigeo">Introduction to the EDIGEO standard</a> (in French)
 <li> <a href="http://georezo.net/wiki/_media/main/geomatique/norme_edigeo.zip">EDIGEO standard - AFNOR NF Z 52000</a> (in French)
-<li> <a href="http://www.craig.fr/contenu/resources/dossiers/pci/pdf/EDIGeO_PCI.pdf">Standard d'échange des objets du PCI selon la norme EDIGEO</a> (in French)
+<li> <a href="https://www.craig.fr/sites/default/files/contenu/60-2010-le-pci-en-auvergne/docs/edigeopci.pdf">Standard d'échange des objets du PCI selon la norme EDIGEO</a> (in French)
 <li> <a href="http://www.cadastre.gouv.fr">Homepage of the French Digital Cadastral Plan</a> (in French)
 <li> <a href="http://docs.codehaus.org/pages/viewpage.action?pageId=77692976">Geotools EDIGEO module description</a> (in English)
 <li> <a href="http://svn.geotools.org/trunk/modules/unsupported/edigeo/src/test/resources/org/geotools/data/edigeo/test-data/">Sample of EDIGEO data</a>
diff --git a/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h b/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
index 86614e2..74546de 100644
--- a/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
+++ b/ogr/ogrsf_frmts/edigeo/ogr_edigeo.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_edigeo.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogr_edigeo.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Definition of classes for OGR .edigeo driver.
@@ -61,20 +61,19 @@ class OGREDIGEOLayer : public OGRLayer
                         OGREDIGEOLayer(OGREDIGEODataSource* poDS,
                                        const char* pszName, OGRwkbGeometryType eType,
                                        OGRSpatialReference* poSRS);
-                        ~OGREDIGEOLayer();
+                        virtual ~OGREDIGEOLayer();
 
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
+    virtual OGRFeature *        GetFeature(GIntBig nFID) override;
+    virtual GIntBig             GetFeatureCount( int bForce ) override;
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
-    virtual OGRFeature *        GetFeature(GIntBig nFID);
-    virtual GIntBig             GetFeatureCount( int bForce );
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual int                 TestCapability( const char * ) override;
 
-    virtual int                 TestCapability( const char * );
-
-    virtual OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr              GetExtent(OGREnvelope *psExtent, int bForce) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     void                        AddFeature(OGRFeature* poFeature);
@@ -151,7 +150,7 @@ class OGREDIGEODataSource : public OGRDataSource
     VSILFILE*           OpenFile(const char *pszType,
                                  const CPLString& osExt);
 
-    // TODO: Tranlate comments to English.
+    // TODO: Translate comments to English.
     CPLString osLON; /* Nom du lot */
     CPLString osGNN; /* Nom du sous-ensemble de données générales */
     CPLString osGON; /* Nom du sous-ensemble de la référence de coordonnées */
@@ -228,19 +227,18 @@ class OGREDIGEODataSource : public OGRDataSource
 
   public:
                         OGREDIGEODataSource();
-                        ~OGREDIGEODataSource();
+                        virtual ~OGREDIGEODataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount();
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override;
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     int                         HasUTF8ContentOnly() { return bHasUTF8ContentOnly; }
 };
 
-
 #endif /* ndef OGR_EDIGEO_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
index 723b451..4792fdc 100644
--- a/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeodatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogredigeodatasource.cpp 32983 2016-01-14 18:32:10Z goatbar $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Implements OGREDIGEODataSource class
@@ -31,39 +30,44 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogredigeodatasource.cpp 32983 2016-01-14 18:32:10Z goatbar $");
+CPL_CVSID("$Id: ogredigeodatasource.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /************************************************************************/
 /*                        OGREDIGEODataSource()                         */
 /************************************************************************/
 
-OGREDIGEODataSource::OGREDIGEODataSource()
-
+OGREDIGEODataSource::OGREDIGEODataSource() :
+    pszName(NULL),
+    fpTHF(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    poSRS(NULL),
+    bExtentValid(FALSE),
+    dfMinX(0),
+    dfMinY(0),
+    dfMaxX(0),
+    dfMaxY(0),
+    bRecodeToUTF8(
+        CPLTestBool(CPLGetConfigOption("OGR_EDIGEO_RECODE_TO_UTF8", "YES"))),
+    bHasUTF8ContentOnly(TRUE),
+    iATR(-1),
+    iDI3(-1),
+    iDI4(-1),
+    iHEI(-1),
+    iFON(-1),
+    iATR_VAL(-1),
+    iANGLE(-1),
+    iSIZE(-1),
+    iOBJ_LNK(-1),
+    iOBJ_LNK_LAYER(-1),
+    dfSizeFactor(CPLAtof(
+        CPLGetConfigOption("OGR_EDIGEO_FONT_SIZE_FACTOR", "2"))),
+    bIncludeFontFamily(CPLTestBool(
+        CPLGetConfigOption("OGR_EDIGEO_INCLUDE_FONT_FAMILY", "YES"))),
+    bHasReadEDIGEO(FALSE)
 {
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-    poSRS = NULL;
-
-    bExtentValid = FALSE;
-    dfMinX = dfMinY = dfMaxX = dfMaxY = 0;
-
-    fpTHF = NULL;
-    bHasReadEDIGEO = FALSE;
-
-    bIncludeFontFamily = CPLTestBool(CPLGetConfigOption(
-                                 "OGR_EDIGEO_INCLUDE_FONT_FAMILY", "YES"));
-
-    iATR = iDI3 = iDI4 = iHEI = iFON = -1;
-    iATR_VAL = iANGLE = iSIZE = iOBJ_LNK = iOBJ_LNK_LAYER = -1;
-    dfSizeFactor = CPLAtof(CPLGetConfigOption("OGR_EDIGEO_FONT_SIZE_FACTOR", "2"));
     if (dfSizeFactor <= 0 || dfSizeFactor >= 100)
         dfSizeFactor = 2;
-
-    bRecodeToUTF8 = CPLTestBool(CPLGetConfigOption(
-                                        "OGR_EDIGEO_RECODE_TO_UTF8", "YES"));
-    bHasUTF8ContentOnly = TRUE;
 }
 
 /************************************************************************/
@@ -125,7 +129,7 @@ int OGREDIGEODataSource::GetLayerCount()
 
 int OGREDIGEODataSource::ReadTHF(VSILFILE* fp)
 {
-    const char* pszLine;
+    const char* pszLine = NULL;
     while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL)
     {
         if (strlen(pszLine) < 8 || pszLine[7] != ':')
@@ -135,7 +139,7 @@ int OGREDIGEODataSource::ReadTHF(VSILFILE* fp)
 
         if (STARTS_WITH(pszLine, "LONSA"))
         {
-            if (osLON.size() != 0)
+            if (!osLON.empty())
             {
                 CPLDebug("EDIGEO", "We only handle one lot per THF file");
                 break;
@@ -155,22 +159,22 @@ int OGREDIGEODataSource::ReadTHF(VSILFILE* fp)
         else if (STARTS_WITH(pszLine, "GDNSA"))
             aosGDN.push_back(pszLine + 8);
     }
-    if (osLON.size() == 0)
+    if (osLON.empty())
     {
         CPLDebug("EDIGEO", "LON field missing");
         return 0;
     }
-    if (osGON.size() == 0)
+    if (osGON.empty())
     {
         CPLDebug("EDIGEO", "GON field missing");
         return 0;
     }
-    if (osDIN.size() == 0)
+    if (osDIN.empty())
     {
         CPLDebug("EDIGEO", "DIN field missing");
         return 0;
     }
-    if (osSCN.size() == 0)
+    if (osSCN.empty())
     {
         CPLDebug("EDIGEO", "SCN field missing");
         return FALSE;
@@ -188,7 +192,6 @@ int OGREDIGEODataSource::ReadTHF(VSILFILE* fp)
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                             OpenFile()                               */
 /************************************************************************/
@@ -226,8 +229,8 @@ int OGREDIGEODataSource::ReadGEO()
     if (fp == NULL)
         return FALSE;
 
-    const char* pszLine;
-    while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL)
+    const char* pszLine = NULL;
+    while( (pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL )
     {
         if (strlen(pszLine) < 8 || pszLine[7] != ':')
             continue;
@@ -242,7 +245,7 @@ int OGREDIGEODataSource::ReadGEO()
 
     VSIFCloseL(fp);
 
-    if (osREL.size() == 0)
+    if (osREL.empty())
     {
         CPLDebug("EDIGEO", "REL field missing");
         return FALSE;
@@ -285,9 +288,10 @@ int OGREDIGEODataSource::ReadGEN()
     if (fp == NULL)
         return FALSE;
 
-    const char* pszLine;
-    CPLString osCM1, osCM2;
-    while((pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL)
+    const char* pszLine = NULL;
+    CPLString osCM1;
+    CPLString osCM2;
+    while( (pszLine = CPLReadLine2L(fp, 81, NULL)) != NULL )
     {
         if (strlen(pszLine) < 8 || pszLine[7] != ':')
             continue;
@@ -304,7 +308,7 @@ int OGREDIGEODataSource::ReadGEN()
 
     VSIFCloseL(fp);
 
-    if (osCM1.size() == 0 || osCM2.size() == 0)
+    if (osCM1.empty() || osCM2.empty())
         return FALSE;
 
     char** papszTokens1 = CSLTokenizeString2(osCM1.c_str(), ";", 0);
@@ -333,8 +337,11 @@ int OGREDIGEODataSource::ReadDIC()
     if (fp == NULL)
         return FALSE;
 
-    const char* pszLine;
-    CPLString osRTY, osRID, osLAB, osTYP;
+    const char* pszLine = NULL;
+    CPLString osRTY;
+    CPLString osRID;
+    CPLString osLAB;
+    CPLString osTYP;
     while( true )
     {
         pszLine = CPLReadLine2L(fp, 81, NULL);
@@ -378,7 +385,6 @@ int OGREDIGEODataSource::ReadDIC()
 
     VSIFCloseL(fp);
 
-
     return TRUE;
 }
 
@@ -392,7 +398,7 @@ int OGREDIGEODataSource::ReadSCD()
     if (fp == NULL)
         return FALSE;
 
-    const char* pszLine;
+    const char* pszLine = NULL;
     CPLString osRTY, osRID, osNameRID, osKND;
     strListType aosAttrRID;
     int nWidth = 0;
@@ -487,7 +493,6 @@ int OGREDIGEODataSource::ReadSCD()
 
     VSIFCloseL(fp);
 
-
     return TRUE;
 }
 
@@ -501,9 +506,11 @@ int OGREDIGEODataSource::ReadQAL()
     if (fp == NULL)
         return FALSE;
 
-    const char* pszLine;
-    CPLString osRTY, osRID;
-    int nODA = 0, nUDA = 0;
+    const char* pszLine = NULL;
+    CPLString osRTY;
+    CPLString osRID;
+    int nODA = 0;
+    int nUDA = 0;
     while( true )
     {
         pszLine = CPLReadLine2L(fp, 81, NULL);
@@ -584,7 +591,6 @@ int OGREDIGEODataSource::CreateLayerFromObjectDesc(const OGREDIGEOObjectDescript
         }
     }
 
-
     if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") == 0)
     {
         OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
@@ -610,7 +616,7 @@ int OGREDIGEODataSource::CreateLayerFromObjectDesc(const OGREDIGEOObjectDescript
         poLayer->AddFieldDefn("OGR_FONT_SIZE", OFTReal, "");
         iSIZE = poFDefn->GetFieldIndex("OGR_FONT_SIZE");
     }
-    else if (mapQAL.size() != 0)
+    else if (!mapQAL.empty())
     {
         poLayer->AddFieldDefn("CREAT_DATE", OFTInteger, "");
         poLayer->AddFieldDefn("UPDATE_DATE", OFTInteger, "");
@@ -636,7 +642,7 @@ int OGREDIGEODataSource::ReadVEC(const char* pszVECName)
     if (fp == NULL)
         return FALSE;
 
-    const char* pszLine;
+    const char* pszLine = NULL;
     CPLString osRTY, osRID;
     xyPairListType aXY;
     CPLString osLnkStartType, osLnkStartName, osLnkEndType, osLnkEndName;
@@ -777,7 +783,7 @@ skip_read_next_line:
             char** papszTokens = CSLTokenizeString2(pszLine + 8, ";", 0);
             if (CSLCount(papszTokens) == 4)
             {
-                if (osLnkStartType.size() == 0)
+                if (osLnkStartType.empty())
                 {
                     osLnkStartType = papszTokens[2];
                     osLnkStartName = papszTokens[3];
@@ -849,7 +855,7 @@ skip_read_next_line:
             {
                 bHasUTF8ContentOnly = CPLIsUTF8(osAttVal.c_str(), -1);
             }
-            if (osAttId.size() != 0)
+            if (!osAttId.empty())
                 aosAttIdVal.push_back( strstrType (osAttId, osAttVal) );
             osAttId = "";
             bIso8859_1 = FALSE;
@@ -863,7 +869,7 @@ skip_read_next_line:
                 if (strcmp(papszTokens[2], "ATT") == 0)
                 {
                     CPLString osAttVal = papszTokens[3];
-                    if (osAttId.size() != 0)
+                    if (!osAttId.empty())
                         aosAttIdVal.push_back( strstrType (osAttId, osAttVal) );
                     osAttId = "";
                 }
@@ -925,7 +931,7 @@ OGRFeature* OGREDIGEODataSource::CreateFeature(const CPLString& osFEA)
         }
 
         if (strcmp(poLayer->GetName(), "ID_S_OBJ_Z_1_2_2") != 0 &&
-            mapQAL.size() != 0 && fea.osQUP_RID.size() != 0)
+            !mapQAL.empty() && !fea.osQUP_RID.empty())
         {
             const std::map<CPLString, intintType>::iterator itQAL =
                                                         mapQAL.find(fea.osQUP_RID);
@@ -1140,8 +1146,6 @@ int OGREDIGEODataSource::BuildLineStrings()
 int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA,
                                       const CPLString& osPFE)
 {
-    int i;
-
     const std::map< CPLString, strListType >::iterator itPFE_PAR =
                                                     mapPFE_PAR.find(osPFE);
     if (itPFE_PAR == mapPFE_PAR.end())
@@ -1156,18 +1160,18 @@ int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA,
 /*      Resolve arc ids to arc coordinate lists.                        */
 /* -------------------------------------------------------------------- */
     std::vector< const xyPairListType *> aoPARPtrList;
-    for(i=0;i<(int)aosPARList.size();i++)
+    for( int i = 0; i < (int)aosPARList.size(); i++ )
     {
         const std::map< CPLString, xyPairListType >::iterator itPAR =
                                             mapPAR.find(aosPARList[i]);
-        if (itPAR != mapPAR.end())
+        if( itPAR != mapPAR.end() )
             aoPARPtrList.push_back(&(itPAR->second));
         else
             CPLDebug("EDIGEO",
                      "ERROR: Cannot find ARC %s", aosPARList[i].c_str());
     }
 
-    if (aoPARPtrList.size() == 0)
+    if (aoPARPtrList.empty())
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -1175,45 +1179,45 @@ int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA,
 /* -------------------------------------------------------------------- */
     std::vector<xyPairListType> aoXYList;
 
-    int j;
-    for(j=0;j<(int)aoPARPtrList.size();j++)
+    for( int j = 0; j < (int)aoPARPtrList.size(); j++ )
     {
         if (aoPARPtrList[j] == NULL)
             continue;
         const xyPairListType& sFirstRing = *(aoPARPtrList[j]);
-        const xyPairType* psNext = &(sFirstRing[sFirstRing.size()-1]);
+        const xyPairType* psNext = &(sFirstRing.back());
 
         xyPairListType aoXY;
-        for(i=0;i<(int)sFirstRing.size();i++)
+        for( int i = 0; i < (int)sFirstRing.size(); i++ )
             aoXY.push_back(sFirstRing[i]);
         aoPARPtrList[j] = NULL;
 
         int nIter = 1;
-        while(aoXY[aoXY.size()-1] != aoXY[0] && nIter < (int)aoPARPtrList.size())
+        while(aoXY.back() != aoXY[0] && nIter < (int)aoPARPtrList.size())
         {
-            int bFound = FALSE;
-            int bReverseSecond = FALSE;
-            for(i=0;i<(int)aoPARPtrList.size();i++)
+            bool bFound = false;
+            bool bReverseSecond = false;
+            int i = 0;  // Used after for.
+            for( ; i < (int)aoPARPtrList.size(); i++ )
             {
                 if (aoPARPtrList[i] != NULL)
                 {
                     const xyPairListType& sSecondRing = *(aoPARPtrList[i]);
                     if (*psNext == sSecondRing[0])
                     {
-                        bFound = TRUE;
-                        bReverseSecond = FALSE;
+                        bFound = true;
+                        bReverseSecond = false;
                         break;
                     }
-                    else if (*psNext == sSecondRing[sSecondRing.size()-1])
+                    else if (*psNext == sSecondRing.back())
                     {
-                        bFound = TRUE;
-                        bReverseSecond = TRUE;
+                        bFound = true;
+                        bReverseSecond = true;
                         break;
                     }
                 }
             }
 
-            if (!bFound)
+            if( !bFound )
             {
                 CPLDebug("EDIGEO", "Cannot find ring for FEA %s / PFE %s",
                         osFEA.c_str(), osPFE.c_str());
@@ -1223,11 +1227,11 @@ int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA,
             {
                 const xyPairListType& secondRing = *(aoPARPtrList[i]);
                 aoPARPtrList[i] = NULL;
-                if (!bReverseSecond)
+                if( !bReverseSecond )
                 {
                     for(i=1;i<(int)secondRing.size();i++)
                         aoXY.push_back(secondRing[i]);
-                    psNext = &secondRing[secondRing.size()-1];
+                    psNext = &secondRing.back();
                 }
                 else
                 {
@@ -1247,15 +1251,15 @@ int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA,
 /*      Create feature.                                                 */
 /* -------------------------------------------------------------------- */
     OGRFeature* poFeature = CreateFeature(osFEA);
-    if (poFeature)
+    if( poFeature )
     {
         std::vector<OGRGeometry*> aosPolygons;
-        for(j=0;j<(int)aoXYList.size();j++)
+        for( int j = 0; j < (int)aoXYList.size(); j++ )
         {
             const xyPairListType& aoXY = aoXYList[j];
             OGRLinearRing* poLS = new OGRLinearRing();
             poLS->setNumPoints((int)aoXY.size());
-            for(i=0;i<(int)aoXY.size();i++)
+            for( int i = 0; i < (int)aoXY.size(); i++ )
                 poLS->setPoint(i, aoXY[i].first, aoXY[i].second);
             poLS->closeRings();
             OGRPolygon* poPolygon = new OGRPolygon();
@@ -1263,7 +1267,7 @@ int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA,
             aosPolygons.push_back(poPolygon);
         }
 
-        int bIsValidGeometry;
+        int bIsValidGeometry = FALSE;
         OGRGeometry* poGeom = OGRGeometryFactory::organizePolygons(
             &aosPolygons[0], (int)aosPolygons.size(),
             &bIsValidGeometry, NULL);
@@ -1284,8 +1288,7 @@ int OGREDIGEODataSource::BuildPolygon(const CPLString& osFEA,
 
 int OGREDIGEODataSource::BuildPolygons()
 {
-    int iter;
-    for(iter=0;iter<(int)listFEA_PFE.size();iter++)
+    for( int iter = 0; iter < (int)listFEA_PFE.size(); iter++ )
     {
         const CPLString& osFEA = listFEA_PFE[iter].first;
         const CPLString& osPFE = listFEA_PFE[iter].second;
@@ -1353,20 +1356,20 @@ int OGREDIGEODataSource::Open( const char * pszFilename )
     if (fpTHF == NULL)
         return FALSE;
 
-    const char* pszLine;
+    const char* pszLine = NULL;
     int i = 0;
-    int bIsEDIGEO = FALSE;
-    while(i < 100 && (pszLine = CPLReadLine2L(fpTHF, 81, NULL)) != NULL)
+    bool bIsEDIGEO = false;
+    while( i < 100 && (pszLine = CPLReadLine2L(fpTHF, 81, NULL)) != NULL )
     {
         if (strcmp(pszLine, "RTYSA03:GTS") == 0)
         {
-            bIsEDIGEO = TRUE;
+            bIsEDIGEO = true;
             break;
         }
         i++;
     }
 
-    if (!bIsEDIGEO)
+    if( !bIsEDIGEO )
     {
         VSIFCloseL(fpTHF);
         fpTHF = NULL;
@@ -1409,7 +1412,7 @@ void OGREDIGEODataSource::ReadEDIGEO()
 /* -------------------------------------------------------------------- */
 /*      Read .GEN file                                                  */
 /* -------------------------------------------------------------------- */
-    if (osGNN.size() != 0)
+    if (!osGNN.empty())
         ReadGEN();
 
 /* -------------------------------------------------------------------- */
@@ -1427,14 +1430,13 @@ void OGREDIGEODataSource::ReadEDIGEO()
 /* -------------------------------------------------------------------- */
 /*      Read .QAL file                                                  */
 /* -------------------------------------------------------------------- */
-    if (osQAN.size() != 0)
+    if (!osQAN.empty())
         ReadQAL();
 
 /* -------------------------------------------------------------------- */
 /*      Create layers from SCD definitions                              */
 /* -------------------------------------------------------------------- */
-    int i;
-    for(i=0;i<(int)aoObjList.size();i++)
+    for( int i = 0; i < (int)aoObjList.size(); i++ )
     {
         CreateLayerFromObjectDesc(aoObjList[i]);
     }
@@ -1442,7 +1444,7 @@ void OGREDIGEODataSource::ReadEDIGEO()
 /* -------------------------------------------------------------------- */
 /*      Read .VEC files and create features                             */
 /* -------------------------------------------------------------------- */
-    for(i=0;i<(int)aosGDN.size();i++)
+    for( int i = 0; i < (int)aosGDN.size(); i++ )
     {
         ReadVEC(aosGDN[i]);
 
@@ -1468,7 +1470,7 @@ void OGREDIGEODataSource::ReadEDIGEO()
 /* -------------------------------------------------------------------- */
 /*      Delete empty layers                                             */
 /* -------------------------------------------------------------------- */
-    for(i=0;i<nLayers;/*nothing*/)
+    for( int i = 0; i <nLayers; /*nothing*/ )
     {
         if (papoLayers[i]->GetFeatureCount(TRUE) == 0)
         {
@@ -1510,9 +1512,9 @@ void OGREDIGEODataSource::CreateLabelLayers()
 
     std::map<CPLString, OGREDIGEOLayer*> mapLayerNameToLayer;
 
-    OGRFeature* poFeature;
+    OGRFeature* poFeature = NULL;
     OGRFeatureDefn* poFeatureDefn = poLayer->GetLayerDefn();
-    while((poFeature = poLayer->GetNextFeature()) != NULL)
+    while( (poFeature = poLayer->GetNextFeature()) != NULL )
     {
         const char* pszBelongingLayerName =
             poFeature->GetFieldAsString(iOBJ_LNK_LAYER);
@@ -1521,7 +1523,7 @@ void OGREDIGEODataSource::CreateLabelLayers()
             CPLString osBelongingLayerName = pszBelongingLayerName;
             std::map<CPLString, OGREDIGEOLayer*>::iterator it =
                         mapLayerNameToLayer.find(osBelongingLayerName);
-            OGREDIGEOLayer* poLabelLayer;
+            OGREDIGEOLayer* poLabelLayer = NULL;
 
             if (it == mapLayerNameToLayer.end())
             {
@@ -1529,9 +1531,8 @@ void OGREDIGEODataSource::CreateLabelLayers()
                 CPLString osLayerLabelName = osBelongingLayerName + "_LABEL";
                 poLabelLayer = new OGREDIGEOLayer(this, osLayerLabelName.c_str(),
                                              wkbPoint, poSRS);
-                int i;
                 OGRFeatureDefn* poLabelFeatureDefn = poLabelLayer->GetLayerDefn();
-                for(i=0;i<poFeatureDefn->GetFieldCount();i++)
+                for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
                     poLabelFeatureDefn->AddFieldDefn(poFeatureDefn->GetFieldDefn(i));
                 mapLayerNameToLayer[osBelongingLayerName] = poLabelLayer;
 
@@ -1541,7 +1542,9 @@ void OGREDIGEODataSource::CreateLabelLayers()
                 nLayers ++;
             }
             else
+            {
                 poLabelLayer = mapLayerNameToLayer[osBelongingLayerName];
+            }
 
             OGRFeature* poNewFeature = new OGRFeature(poLabelLayer->GetLayerDefn());
             poNewFeature->SetFrom(poFeature);
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
index 4fe0aac..c0203ce 100644
--- a/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeodriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogredigeodriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Implements OGREDIGEODriver.
@@ -30,7 +29,7 @@
 #include "ogr_edigeo.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogredigeodriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogredigeodriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 extern "C" void RegisterOGREDIGEO();
 
@@ -95,4 +94,3 @@ void RegisterOGREDIGEO()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp b/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
index 758a8b1..9a9c17b 100644
--- a/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
+++ b/ogr/ogrsf_frmts/edigeo/ogredigeolayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogredigeolayer.cpp 32011 2015-12-06 10:19:18Z rouault $
  *
  * Project:  EDIGEO Translator
  * Purpose:  Implements OGREDIGEOLayer class.
@@ -33,7 +32,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogredigeolayer.cpp 32011 2015-12-06 10:19:18Z rouault $");
+CPL_CVSID("$Id: ogredigeolayer.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                          OGREDIGEOLayer()                            */
@@ -41,17 +40,15 @@ CPL_CVSID("$Id: ogredigeolayer.cpp 32011 2015-12-06 10:19:18Z rouault $");
 
 OGREDIGEOLayer::OGREDIGEOLayer( OGREDIGEODataSource* poDSIn,
                                 const char* pszName, OGRwkbGeometryType eType,
-                                OGRSpatialReference* poSRSIn )
-
+                                OGRSpatialReference* poSRSIn ) :
+    poDS(poDSIn),
+    poFeatureDefn(new OGRFeatureDefn( pszName )),
+    poSRS(poSRSIn),
+    nNextFID(0)
 {
-    this->poDS = poDSIn;
-    nNextFID = 0;
-
-    this->poSRS = poSRSIn;
-    if (poSRS)
+    if( poSRS )
         poSRS->Reference();
 
-    poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( eType );
     if( poFeatureDefn->GetGeomFieldCount() != 0 )
@@ -75,7 +72,6 @@ OGREDIGEOLayer::~OGREDIGEOLayer()
         poSRS->Release();
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -86,18 +82,16 @@ void OGREDIGEOLayer::ResetReading()
     nNextFID = 0;
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
 OGRFeature *OGREDIGEOLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
 
     while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -108,8 +102,8 @@ OGRFeature *OGREDIGEOLayer::GetNextFeature()
         {
             return poFeature;
         }
-        else
-            delete poFeature;
+
+        delete poFeature;
     }
 }
 
@@ -222,7 +216,7 @@ void OGREDIGEOLayer::AddFieldDefn(const CPLString& osName,
                                   OGRFieldType eType,
                                   const CPLString& osRID)
 {
-    if (osRID.size() != 0)
+    if (!osRID.empty())
         mapAttributeToIndex[osRID] = poFeatureDefn->GetFieldCount();
 
     OGRFieldDefn oFieldDefn(osName, eType);
diff --git a/ogr/ogrsf_frmts/elastic/GNUmakefile b/ogr/ogrsf_frmts/elastic/GNUmakefile
index fe0d840..3c2bc40 100644
--- a/ogr/ogrsf_frmts/elastic/GNUmakefile
+++ b/ogr/ogrsf_frmts/elastic/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrelasticdriver.o ogrelasticdatasource.o ogrelasticlayer.o
 
-CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../..  $(CPPFLAGS)
+CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. -I../geojson $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/elastic/drv_elasticsearch.html b/ogr/ogrsf_frmts/elastic/drv_elasticsearch.html
index 22de086..73f6916 100644
--- a/ogr/ogrsf_frmts/elastic/drv_elasticsearch.html
+++ b/ogr/ogrsf_frmts/elastic/drv_elasticsearch.html
@@ -7,9 +7,13 @@
 
 <h1>ElasticSearch:  Geographically Encoded Objects for ElasticSearch</h1>
 
-(Driver available in GDAL 1.10 or later)</br>
+(Driver available in GDAL 1.10 or later)<br/>
+
+Driver is read-write starting with GDAL 2.1 (was write only in GDAL 2.0 or earlier)<br/>
+
+As of GDAL 2.1, ElasticSearch 1.X and, partially, 2.X versions are supported
+(5.0 known not to work). GDAL 2.2 adds supports for ElasticSearch 2.X and 5.X<br/>
 
-Driver is read-write starting with GDAL 2.1 (was write only in GDAL 2.0 or earlier)
 <p>
 
 <a href="http://elasticsearch.org/">ElasticSearch</a> is an Enterprise-level
@@ -69,7 +73,7 @@ Note that this will properly work only if only one single layer is created.
 Starting with GDAL 2.1, the <b>WRITE_MAPPING</b> layer creation option should rather be used.<br>
 <li> <b>ES_META</b>=/path/to/mapfile.txt. Tells the driver to the user-defined
 field mappings. Starting with GDAL 2.1, the <b>MAPPING</b> layer creation option should rather be used.<br>
-<li> <b>ES_BULK</b>=10000. Identifies the maximum size in bytes of the buffer
+<li> <b>ES_BULK</b>=5000000. Identifies the maximum size in bytes of the buffer
 to store documents to be inserted at a time. Lower record counts help with
 memory consumption within ElasticSearch but take longer to insert.
 Starting with GDAL 2.1, the <b>BULK_SIZE</b> layer creation option should rather be used.<br>
@@ -94,14 +98,17 @@ by ElasticSearch and will be approximated to their linear equivalents).
 
 The driver will forward any spatial filter set with SetSpatialFilter() to the server.<p>
 
-However, in the current state, SQL attribute filters set with SetAttributeFilter()
-are evaluated only on client-side. To enable server-side filtering, the string
-passed to SetAttributeFilter() must be a JSon object in the
-<a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-filters.html">ElasticSearch filter syntax</a>.
-e.g. <pre>{ "filter": { "term": { "EAS_ID": 169 } } }</pre>
+Starting with GDAL 2.2, SQL attribute filters set with SetAttributeFilter() are
+converted to <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-filters.html">
+ElasticSearch filter syntax</a>.
+They will be combined with the potentially defined spatial filter.<p>
+
+It is also possible to directly use a ElasticSearch filter by setting the string
+passed to SetAttributeFilter() as a JSon serialized object, e.g.
+<pre>{ "post_filter": { "term": { "properties.EAS_ID": 169 } } }</pre>
 <p>
 
-Note: if defining an Elastic Search JSon filter, the spatial filter specified
+Note: if defining directly an Elastic Search JSon filter, the spatial filter specified
 through SetSpatialFilter() will be ignored, and must thus be included in the JSon
 filter if needed.<p>
 
@@ -138,7 +145,10 @@ stable at all.<p>
 
 <h2>ExecuteSQL() interface</h2>
 
-If specifying "ES" as the dialect of ExecuteSQL(), a JSon string with a
+Starting with GDAL 2.2, SQL requests, involving a single layer, with WHERE and
+ORDER BY statements will be translated as ElasticSearch queries.<p>
+
+Otherwise, if specifying "ES" as the dialect of ExecuteSQL(), a JSon string with a
 serialized <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-filters.html">Elastic Search filter</a>
 can be passed. The search will be done on all indices and types, unless the
 filter itself restricts the search. The returned layer will be a union of the
@@ -146,7 +156,8 @@ types returned by the FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN first documents. I
 will also contain the _index and _type special fields to indicate the provenance
 of the features.<p>
 
-The following filter can be used to restrict the search to the "poly" index and its "FeatureCollection" type mapping:
+The following filter can be used to restrict the search to the "poly" index and
+its "FeatureCollection" type mapping (ElasticSearch 1.X and 2.X)
 <pre>
 { "filter": {
     "indices" : {
@@ -155,7 +166,7 @@ The following filter can be used to restrict the search to the "poly" index and
         "filter": {
            "and" : [
              { "type": { "value": "FeatureCollection" } },
-             { "term" : { "EAS_ID" : 158.0 } }
+             { "term" : { "properties.EAS_ID" : 158.0 } }
            ]
         }
       }
@@ -163,9 +174,26 @@ The following filter can be used to restrict the search to the "poly" index and
 }
 </pre>
 
-Aggregations are not supported.<p>
+For ElasticSearch 5.X (works also with 2.X) :
+<pre>
+{ "post_filter": {
+    "indices" : {
+        "no_match_query": "none",
+        "index": "poly",
+        "query": {
+          "bool": {
+            "must" : [
+              { "type": { "value": "FeatureCollection" } },
+              { "term" : { "properties.EAS_ID" : 158.0 } }
+            ]
+          }
+        }
+      }
+    }
+}
+</pre>
 
-Standard SQL requests will be executed on client-side.<p>
+Aggregations are not supported.<p>
 
 <h2>Getting metadata</h2>
 
@@ -203,8 +231,15 @@ mapping, or mapping as serialized JSon.</li>
 <li><b>WRITE_MAPPING</b>=filename. Creates a mapping file that can be modified
 by the user prior to insert in to the index. No feature will be written.
 This option is exclusive with MAPPING.</li>
-<li><b>OVERWRITE</b>=YES/NO. Whether to overwrite an existing collection with
+<li><b>OVERWRITE</b>=YES/NO. Whether to overwrite an existing type mapping with
 the layer name to be created. Defaults to NO.</li>
+<li><b>OVERWRITE_INDEX</b>=YES/NO. (GDAL >= 2.2) Whether to overwrite the whole index to which
+the layer belongs to. Defaults to NO. This option is stronger than OVERWRITE.
+OVERWRITE will only proceed if the type mapping corresponding to the layer
+is the single type mapping of the index. In case there are several type mappings,
+the whole index need to be destroyed (it is unsafe to destroy a mapping and the
+documents that use it, since they might be used by other mappings. This was
+possible in ElasticSearch 1.X, but no longer in later versions).</li>
 <li><b>GEOMETRY_NAME</b>=name. Name of geometry column. Defaults to 'geometry'.</li>
 <li><b>GEOM_MAPPING_TYPE</b>=AUTO/GEO_POINT/GEO_SHAPE. Mapping type for geometry fields. Defaults to AUTO.
 GEO_POINT uses the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-geo-point-type.html">geo_point</a>
@@ -229,12 +264,19 @@ This option is without effect if MAPPING is specified.</li>
 Those fields will have their <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-core-types.html">"index" property</a> of the field mapping set to "not_analyzed"
 (the default in ElasticSearch is "analyzed"). A same field should not be
 specified both in NOT_ANALYZED_FIELDS and NOT_INDEXED_FIELDS.
+Starting with GDAL 2.2, the {ALL} value can be used to designate all fields.
 This option is without effect if MAPPING is specified.</li>
 <li><b>NOT_INDEXED_FIELDS</b>=List of comma separated field names that should not be indexed.
 Those fields will have their <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-core-types.html">"index" property</a> of the field mapping set to "no"
 (the default in ElasticSearch is "analyzed"). A same field should not be
 specified both in NOT_ANALYZED_FIELDS and NOT_INDEXED_FIELDS.
 This option is without effect if MAPPING is specified.</li>
+<li><b>FIELDS_WITH_RAW_VALUE</b>=(GDAL > 2.2) List of comma separated field
+names (of type string) that should be created with an additional raw/not_analyzed
+sub-field, or {ALL} to designate all string analyzed fields.
+This is needed for sorting on those columns, and can improve performance when
+filtering with SQL operators.
+This option is without effect if MAPPING is specified.</li>
 <li><b>BULK_INSERT</b>=YES/NO. Whether to use bulk insert for feature creation. Defaults to YES.</li>
 <li><b>BULK_SIZE</b>=value. Size in bytes of the buffer for bulk upload. Defaults to 1000000 (1 million).</li>
 <li><b>FID</b>=string. Field name, with integer values, to use as FID. Can be set to empty to disable the writing of the FID value. Defaults to 'ogc_fid'</li>
@@ -256,13 +298,13 @@ ogrinfo ES:http://example.com:9200
 
 <b>Filtering on a Elastic Search field:</b><br>
 <pre>
-ogrinfo -ro ES: my_type -where '{ "filter": { "term": { "EAS_ID": 168 } } }'
+ogrinfo -ro ES: my_type -where '{ "post_filter": { "term": { "properties.EAS_ID": 168 } } }'
 </pre>
 
 <b>Using "match" query on Windows:</b><br>
 On Windows the query must be between double quotes and double quotes inside the query must be escaped.
 <pre>
-C:\GDAL_on_Windows>ogrinfo ES: my_type -where "{\"query\": { \"match\": { \"NAME\": \"Helsinki\" } } }"
+C:\GDAL_on_Windows>ogrinfo ES: my_type -where "{\"query\": { \"match\": { \"properties.NAME\": \"Helsinki\" } } }"
 </pre>
 <b>Load an ElasticSearch index with a shapefile:</b> </br>
 <pre>
@@ -294,14 +336,15 @@ ogr2ogr -progress -lco MAPPING=/path/to/file/map.txt -f "ElasticSearch" http://l
 </pre>
 
 <b>Bulk Uploading (for larger datasets):</b> </br>
-Bulk loading helps when uploading a lot of data. The integer value is the number of bytes that are collection before being inserted.
+Bulk loading helps when uploading a lot of data. The integer value is the number of bytes that are collected before being inserted.
+<a href="https://www.elastic.co/guide/en/elasticsearch/guide/current/bulk.html#_how_big_is_too_big">Bulk size considerations</a>
 </br>
 <pre>
-ogr2ogr -progress --config ES_BULK 10000 -f "ElasticSearch" http://localhost:9200 PG:"host=localhost user=postgres dbname=my_db password=password" "my_table" -nln thetable
+ogr2ogr -progress --config ES_BULK 5000000 -f "ElasticSearch" http://localhost:9200 PG:"host=localhost user=postgres dbname=my_db password=password" "my_table" -nln thetable
 </pre>
 or (GDAL >= 2.1):
 <pre>
-ogr2ogr -progress -lco BULK_SIZE=10000 -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
+ogr2ogr -progress -lco BULK_SIZE=5000000 -f "ElasticSearch" http://localhost:9200 my_shapefile.shp
 </pre>
 
 <b>Overwrite the current Index:</b> </br>
diff --git a/ogr/ogrsf_frmts/elastic/ogr_elastic.h b/ogr/ogrsf_frmts/elastic/ogr_elastic.h
index 0df6779..71831ce 100644
--- a/ogr/ogrsf_frmts/elastic/ogr_elastic.h
+++ b/ogr/ogrsf_frmts/elastic/ogr_elastic.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_elastic.h 32177 2015-12-14 07:25:30Z goatbar $
+ * $Id: ogr_elastic.h 37472 2017-02-26 02:47:45Z goatbar $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -34,7 +34,8 @@
 #include "ogr_p.h"
 #include "cpl_hash_set.h"
 #include <vector>
-#include <json.h>
+
+#include "ogr_json_header.h"
 
 typedef enum
 {
@@ -45,6 +46,21 @@ typedef enum
 
 class OGRElasticDataSource;
 
+
+class OGRESSortDesc
+{
+    public:
+        CPLString osColumn;
+        bool      bAsc;
+
+        OGRESSortDesc( const CPLString& osColumnIn, bool bAscIn ) :
+            osColumn(osColumnIn),
+            bAsc(bAscIn) {}
+        OGRESSortDesc(const OGRESSortDesc& other) :
+            osColumn(other.osColumn),
+            bAsc(other.bAsc) {}
+};
+
 /************************************************************************/
 /*                          OGRElasticLayer                             */
 /************************************************************************/
@@ -56,17 +72,19 @@ class OGRElasticLayer : public OGRLayer {
     CPLString                            m_osMappingName;
 
     OGRFeatureDefn                      *m_poFeatureDefn;
-    int                                  m_bFeatureDefnFinalized;
+    bool                                 m_bFeatureDefnFinalized;
 
-    int                                  m_bManualMapping;
-    int                                  m_bSerializeMapping;
+    bool                                 m_bManualMapping;
+    bool                                 m_bSerializeMapping;
     CPLString                            m_osWriteMapFilename;
     bool                                 m_bStoreFields;
     char                               **m_papszStoredFields;
     char                               **m_papszNotAnalyzedFields;
     char                               **m_papszNotIndexedFields;
+    char                               **m_papszFieldsWithRawValue;
 
     CPLString                            m_osESSearch;
+    std::vector<OGRESSortDesc>           m_aoSortColumns;
 
     CPLString                            m_osBulkContent;
     int                                  m_nBulkUpload;
@@ -88,17 +106,19 @@ class OGRElasticLayer : public OGRLayer {
     GIntBig                               m_nNextFID;
     int                                   m_iCurFeatureInPage;
     std::vector<OGRFeature*>              m_apoCachedFeatures;
-    int                                   m_bEOF;
+    bool                                  m_bEOF;
 
     json_object*                          m_poSpatialFilter;
     CPLString                             m_osJSONFilter;
+    bool                                  m_bFilterMustBeClientSideEvaluated;
+    json_object*                          m_poJSONFilter;
 
-    int                                   m_bIgnoreSourceID;
-    int                                   m_bDotAsNestedField;
+    bool                                  m_bIgnoreSourceID;
+    bool                                  m_bDotAsNestedField;
 
-    int                                   m_bAddPretty;
+    bool                                  m_bAddPretty;
 
-    int                                   PushIndex();
+    bool                                  PushIndex();
     CPLString                             BuildMap();
 
     OGRErr                                WriteMapIfNecessary();
@@ -129,6 +149,12 @@ class OGRElasticLayer : public OGRLayer {
                                             const std::vector<CPLString>& aosPath,
                                             int bIsGeoPoint );
 
+    CPLString                             BuildQuery(bool bCountOnly);
+    json_object*                          GetValue( int nFieldIdx,
+                                                    swq_expr_node* poValNode );
+    json_object*                          TranslateSQLToFilter(swq_expr_node* poNode);
+    json_object*                          BuildSort();
+
 public:
                         OGRElasticLayer( const char* pszLayerName,
                                          const char* pszIndexName,
@@ -136,34 +162,34 @@ public:
                                          OGRElasticDataSource* poDS,
                                          char** papszOptions,
                                          const char* pszESSearch = NULL);
-                        ~OGRElasticLayer();
+                        virtual ~OGRElasticLayer();
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRErr      ICreateFeature(OGRFeature *poFeature);
-    virtual OGRErr      ISetFeature(OGRFeature *poFeature);
-    virtual OGRErr      CreateField(OGRFieldDefn *poField, int bApproxOK);
-    virtual OGRErr      CreateGeomField(OGRGeomFieldDefn *poField, int bApproxOK);
+    virtual OGRErr      ICreateFeature(OGRFeature *poFeature) override;
+    virtual OGRErr      ISetFeature(OGRFeature *poFeature) override;
+    virtual OGRErr      CreateField(OGRFieldDefn *poField, int bApproxOK) override;
+    virtual OGRErr      CreateGeomField(OGRGeomFieldDefn *poField, int bApproxOK) override;
 
-    virtual const char* GetName() { return m_poFeatureDefn->GetName(); }
-    virtual OGRFeatureDefn *GetLayerDefn();
-    virtual const char *GetFIDColumn();
+    virtual const char* GetName() override { return m_poFeatureDefn->GetName(); }
+    virtual OGRFeatureDefn *GetLayerDefn() override;
+    virtual const char *GetFIDColumn() override;
 
-    virtual int         TestCapability(const char *);
+    virtual int         TestCapability(const char *) override;
 
-    virtual GIntBig     GetFeatureCount(int bForce);
+    virtual GIntBig     GetFeatureCount(int bForce) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
-    virtual OGRErr      SetAttributeFilter(const char* pszFilter);
+    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override;
+    virtual OGRErr      SetAttributeFilter(const char* pszFilter) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) { return GetExtent(0, psExtent, bForce); }
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 
-    void                FinalizeFeatureDefn(int bReadFeatures = TRUE);
+    void                FinalizeFeatureDefn(bool bReadFeatures = true);
     void                InitFeatureDefnFromMapping(json_object* poSchema,
                                     const char* pszPrefix,
                                     const std::vector<CPLString>& aosPath);
@@ -171,11 +197,15 @@ public:
     const CPLString&    GetIndexName() const { return m_osIndexName; }
     const CPLString&    GetMappingName() const { return m_osMappingName; }
 
-    void                SetIgnoreSourceID(int bFlag) { m_bIgnoreSourceID = bFlag; }
-    void                SetManualMapping() { m_bManualMapping = TRUE; }
-    void                SetDotAsNestedField(int bFlag) { m_bDotAsNestedField = bFlag; }
+    void                SetIgnoreSourceID( bool bFlag ) { m_bIgnoreSourceID = bFlag; }
+    void                SetManualMapping() { m_bManualMapping = true; }
+    void                SetDotAsNestedField( bool bFlag ) { m_bDotAsNestedField = bFlag; }
     void                SetFID(const CPLString& m_osFIDIn) { m_osFID = m_osFIDIn; }
     void                SetNextFID(GIntBig nNextFID) { m_nNextFID = nNextFID; }
+
+    OGRElasticLayer*    Clone() const;
+    void                SetOrderBy( const std::vector<OGRESSortDesc>& v )
+                                                        { m_aoSortColumns = v; }
 };
 
 /************************************************************************/
@@ -189,19 +219,24 @@ class OGRElasticDataSource : public GDALDataset {
 
     OGRElasticLayer   **m_papoLayers;
     int                 m_nLayers;
+    std::map<OGRLayer*, OGRLayer*> m_oMapResultSet;
+
+    bool                CheckVersion();
+    int                 GetLayerIndex( const char* pszName );
 
 public:
                             OGRElasticDataSource();
-                            ~OGRElasticDataSource();
+                            virtual ~OGRElasticDataSource();
 
-    int                 m_bOverwrite;
+    bool                m_bOverwrite;
     int                 m_nBulkUpload;
     char               *m_pszWriteMap;
     char               *m_pszMapping;
     int                 m_nBatchSize;
     int                 m_nFeatureCountToEstablishFeatureDefn;
-    int                 m_bJSonField;
-    int                 m_bFlattenNestedAttributes;
+    bool                m_bJSonField;
+    bool                m_bFlattenNestedAttributes;
+    int                 m_nMajorVersion;
 
     int Open(GDALOpenInfo* poOpenInfo);
 
@@ -212,28 +247,27 @@ public:
 
     virtual const char *GetName() { return m_pszName; }
 
-    virtual int         GetLayerCount() { return m_nLayers; }
-    virtual OGRLayer   *GetLayer(int);
+    virtual int         GetLayerCount() override { return m_nLayers; }
+    virtual OGRLayer   *GetLayer(int) override;
 
     virtual OGRLayer   *ICreateLayer(const char * pszLayerName,
                                     OGRSpatialReference *poSRS,
                                     OGRwkbGeometryType eType,
-                                    char ** papszOptions);
-    virtual OGRErr      DeleteLayer( int iLayer );
+                                    char ** papszOptions) override;
+    virtual OGRErr      DeleteLayer( int iLayer ) override;
 
     virtual OGRLayer   *ExecuteSQL( const char *pszSQLCommand,
                                             OGRGeometry *poSpatialFilter,
-                                            const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                            const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
-    virtual int         TestCapability(const char *);
+    virtual int         TestCapability(const char *) override;
 
-    int                 UploadFile(const CPLString &url, const CPLString &data);
-    void                Delete(const CPLString &url);
+    static bool         UploadFile(const CPLString &url, const CPLString &data);
+    static void         Delete(const CPLString &url);
 
     json_object*        RunRequest(const char* pszURL, const char* pszPostContent = NULL);
     const CPLString&    GetFID() const { return m_osFID; }
 };
 
-
 #endif /* ndef _OGR_Elastic_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp b/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp
index 934201e..1ce1741 100644
--- a/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp
+++ b/ogr/ogrsf_frmts/elastic/ogrelasticdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrelasticdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -28,34 +27,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-// What was this supposed to do?
-// #pragma warning( disable : 4251 )
-
 #include "ogr_elastic.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_csv.h"
 #include "cpl_http.h"
+#include "ogrgeojsonreader.h"
+#include "swq.h"
 
-CPL_CVSID("$Id: ogrelasticdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrelasticdatasource.cpp 37072 2017-01-09 12:54:57Z rouault $");
 
 /************************************************************************/
 /*                        OGRElasticDataSource()                        */
 /************************************************************************/
 
-OGRElasticDataSource::OGRElasticDataSource() {
-    m_papoLayers = NULL;
-    m_nLayers = 0;
-    m_pszName = NULL;
-    m_pszMapping = NULL;
-    m_pszWriteMap = NULL;
-    m_bOverwrite = FALSE;
-    m_nBulkUpload = 0;
-    m_nBatchSize = 100;
-    m_nFeatureCountToEstablishFeatureDefn = 100;
-    m_bJSonField = FALSE;
-    m_bFlattenNestedAttributes = TRUE;
-
+OGRElasticDataSource::OGRElasticDataSource() :
+    m_pszName(NULL),
+    m_papoLayers(NULL),
+    m_nLayers(0),
+    m_bOverwrite(false),
+    m_nBulkUpload(0),
+    m_pszWriteMap(NULL),
+    m_pszMapping(NULL),
+    m_nBatchSize(100),
+    m_nFeatureCountToEstablishFeatureDefn(100),
+    m_bJSonField(false),
+    m_bFlattenNestedAttributes(true),
+    m_nMajorVersion(0)
+{
     const char* pszWriteMapIn = CPLGetConfigOption("ES_WRITEMAP", NULL);
     if (pszWriteMapIn != NULL) {
         m_pszWriteMap = CPLStrdup(pszWriteMapIn);
@@ -79,13 +78,16 @@ OGRElasticDataSource::~OGRElasticDataSource() {
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRElasticDataSource::TestCapability(const char * pszCap) {
+int OGRElasticDataSource::TestCapability(const char * pszCap)
+{
     if (EQUAL(pszCap, ODsCCreateLayer) ||
         EQUAL(pszCap, ODsCDeleteLayer) ||
         EQUAL(pszCap, ODsCCreateGeomFieldAfterCreateLayer) )
-        return TRUE;
-    else
-        return FALSE;
+    {
+        return GetAccess() == GA_Update;
+    }
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -123,6 +125,36 @@ OGRErr OGRElasticDataSource::DeleteLayer( int iLayer )
     CPLString osIndex = m_papoLayers[iLayer]->GetIndexName();
     CPLString osMapping = m_papoLayers[iLayer]->GetMappingName();
 
+    bool bSeveralMappings = false;
+    json_object* poIndexResponse = RunRequest(CPLSPrintf("%s/%s",
+                                       GetURL(), osIndex.c_str()), NULL);
+    if( poIndexResponse )
+    {
+        json_object* poIndex = CPL_json_object_object_get(poIndexResponse,
+                                                          osMapping);
+        if( poIndex != NULL )
+        {
+            json_object* poMappings = CPL_json_object_object_get(poIndex,
+                                                                 "mappings");
+            if( poMappings != NULL )
+            {
+                bSeveralMappings = json_object_object_length(poMappings) > 1;
+            }
+        }
+        json_object_put(poIndexResponse);
+    }
+    // Deletion of one mapping in an index was supported in ES 1.X, but
+    // considered unsafe and removed in later versions
+    if( bSeveralMappings )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                "%s/%s already exists, but other mappings also exist in "
+                "this index. "
+                "You have to delete the whole index.",
+                osIndex.c_str(), osMapping.c_str());
+        return OGRERR_FAILURE;
+    }
+
     CPLDebug( "ES", "DeleteLayer(%s)", osLayerName.c_str() );
 
     delete m_papoLayers[iLayer];
@@ -130,8 +162,7 @@ OGRErr OGRElasticDataSource::DeleteLayer( int iLayer )
             (m_nLayers - 1 - iLayer) * sizeof(OGRLayer*));
     m_nLayers --;
 
-    Delete(CPLSPrintf("%s/%s/_mapping/%s",
-                      GetURL(), osIndex.c_str(), osMapping.c_str()));
+    Delete(CPLSPrintf("%s/%s",  GetURL(), osIndex.c_str()));
 
     return OGRERR_NONE;
 }
@@ -172,48 +203,68 @@ OGRLayer * OGRElasticDataSource::ICreateLayer(const char * pszLayerName,
     CPLErrorNum nLastErrorNo = CPLGetLastErrorNo();
     CPLString osLastErrorMsg = CPLGetLastErrorMsg();
 
-    // Check if the index exists
-    int bIndexExists = FALSE;
-    CPLPushErrorHandler(CPLQuietErrorHandler);
-    CPLHTTPResult* psResult = CPLHTTPFetch(CPLSPrintf("%s/%s",
-                                           GetURL(), osLaunderedName.c_str()), NULL);
-    CPLPopErrorHandler();
-    if (psResult) {
-        bIndexExists = (psResult->pszErrBuf == NULL);
-        CPLHTTPDestroyResult(psResult);
-    }
-
-    const char* m_pszMappingName = CSLFetchNameValueDef(papszOptions,
+    const char* pszMappingName = CSLFetchNameValueDef(papszOptions,
                                         "MAPPING_NAME", "FeatureCollection");
 
-    int bMappingExists = FALSE;
-    if( bIndexExists )
-    {
-        CPLPushErrorHandler(CPLQuietErrorHandler);
-        psResult = CPLHTTPFetch(CPLSPrintf("%s/%s/_mapping/%s",
-                        GetURL(), osLaunderedName.c_str(), m_pszMappingName), NULL);
-        CPLPopErrorHandler();
-        bMappingExists = psResult != NULL && psResult->pabyData != NULL &&
-                         !STARTS_WITH_CI((const char*)psResult->pabyData, "{}");
-        CPLHTTPDestroyResult(psResult);
-    }
+    // Check if the index and mapping exists
+    bool bIndexExists = false;
+    bool bMappingExists = false;
+    bool bSeveralMappings = false;
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    json_object* poIndexResponse = RunRequest(CPLSPrintf("%s/%s",
+                                       GetURL(), osLaunderedName.c_str()), NULL);
+    CPLPopErrorHandler();
 
     // Restore error state
     CPLErrorSetState( eLastErrorType, nLastErrorNo, osLastErrorMsg );
 
-    if( m_bOverwrite || CSLFetchBoolean(papszOptions, "OVERWRITE", FALSE) )
+    if( poIndexResponse )
     {
-        if( bMappingExists )
+        bIndexExists = true;
+        json_object* poIndex = CPL_json_object_object_get(poIndexResponse,
+                                                          osLaunderedName);
+        if( poIndex != NULL )
         {
-            Delete(CPLSPrintf("%s/%s/_mapping/%s",
-                              GetURL(), osLaunderedName.c_str(), m_pszMappingName));
+            json_object* poMappings = CPL_json_object_object_get(poIndex,
+                                                                 "mappings");
+            if( poMappings != NULL )
+            {
+                bMappingExists = CPL_json_object_object_get(
+                                    poMappings, pszMappingName) != NULL;
+                bSeveralMappings = json_object_object_length(poMappings) > 1;
+            }
         }
+        json_object_put(poIndexResponse);
     }
-    else if( bMappingExists )
+
+    if( bMappingExists )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "%s/%s already exists",
-                 osLaunderedName.c_str(), m_pszMappingName);
-        return NULL;
+        if( CPLFetchBool(papszOptions, "OVERWRITE_INDEX", false)  )
+        {
+            Delete(CPLSPrintf("%s/%s", GetURL(), osLaunderedName.c_str()));
+        }
+        else if( m_bOverwrite || CPLFetchBool(papszOptions, "OVERWRITE", false) )
+        {
+            // Deletion of one mapping in an index was supported in ES 1.X, but
+            // considered unsafe and removed in later versions
+            if( bSeveralMappings )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "%s/%s already exists, but other mappings also exist "
+                        "in this index. "
+                        "You have to delete the whole index. You can do that "
+                        "with OVERWRITE_INDEX=YES",
+                        osLaunderedName.c_str(), pszMappingName);
+                return NULL;
+            }
+            Delete(CPLSPrintf("%s/%s", GetURL(), osLaunderedName.c_str()));
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "%s/%s already exists",
+                    osLaunderedName.c_str(), pszMappingName);
+            return NULL;
+        }
     }
 
     // Create the index
@@ -245,7 +296,7 @@ OGRLayer * OGRElasticDataSource::ICreateLayer(const char * pszLayerName,
         }
 
         if( !UploadFile(CPLSPrintf("%s/%s/%s/_mapping",
-                            GetURL(), osLaunderedName.c_str(), m_pszMappingName),
+                            GetURL(), osLaunderedName.c_str(), pszMappingName),
                         pszLayerMapping) )
         {
             return NULL;
@@ -254,13 +305,13 @@ OGRLayer * OGRElasticDataSource::ICreateLayer(const char * pszLayerName,
 
     OGRElasticLayer* poLayer = new OGRElasticLayer(osLaunderedName.c_str(),
                                                    osLaunderedName.c_str(),
-                                                   m_pszMappingName,
+                                                   pszMappingName,
                                                    this, papszOptions);
     m_nLayers++;
     m_papoLayers = (OGRElasticLayer **) CPLRealloc(m_papoLayers, m_nLayers * sizeof (OGRElasticLayer*));
     m_papoLayers[m_nLayers - 1] = poLayer;
 
-    poLayer->FinalizeFeatureDefn(FALSE);
+    poLayer->FinalizeFeatureDefn(false);
 
     if( eGType != wkbNone )
     {
@@ -272,8 +323,10 @@ OGRLayer * OGRElasticDataSource::ICreateLayer(const char * pszLayerName,
     if( pszLayerMapping )
         poLayer->SetManualMapping();
 
-    poLayer->SetIgnoreSourceID(CSLFetchBoolean(papszOptions, "IGNORE_SOURCE_ID", FALSE));
-    poLayer->SetDotAsNestedField(CSLFetchBoolean(papszOptions, "DOT_AS_NESTED_FIELD", TRUE));
+    poLayer->SetIgnoreSourceID(
+        CPLFetchBool(papszOptions, "IGNORE_SOURCE_ID", false));
+    poLayer->SetDotAsNestedField(
+        CPLFetchBool(papszOptions, "DOT_AS_NESTED_FIELD", true));
     poLayer->SetFID(CSLFetchNameValueDef(papszOptions, "FID", "ogc_fid"));
     poLayer->SetNextFID(0);
 
@@ -351,6 +404,42 @@ json_object* OGRElasticDataSource::RunRequest(const char* pszURL, const char* ps
 }
 
 /************************************************************************/
+/*                           CheckVersion()                             */
+/************************************************************************/
+
+bool OGRElasticDataSource::CheckVersion()
+{
+    json_object* poMainInfo = RunRequest(m_osURL);
+    if( poMainInfo == NULL )
+        return false;
+    bool bVersionFound = false;
+    json_object* poVersion = CPL_json_object_object_get(poMainInfo, "version");
+    if( poVersion != NULL )
+    {
+        json_object* poNumber = CPL_json_object_object_get(poVersion, "number");
+        if( poNumber != NULL &&
+            json_object_get_type(poNumber) == json_type_string )
+        {
+            bVersionFound = true;
+            const char* pszVersion = json_object_get_string(poNumber);
+            CPLDebug("ES", "Server version: %s", pszVersion);
+            m_nMajorVersion = atoi(pszVersion);
+        }
+    }
+    json_object_put(poMainInfo);
+    if( !bVersionFound )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Server version not found");
+        return false;
+    }
+    if( m_nMajorVersion != 1 && m_nMajorVersion != 2 && m_nMajorVersion != 5 )
+    {
+        CPLDebug("ES", "Server version untested with current driver");
+    }
+    return true;
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
@@ -359,7 +448,7 @@ int OGRElasticDataSource::Open(GDALOpenInfo* poOpenInfo)
     eAccess = poOpenInfo->eAccess;
     m_pszName = CPLStrdup(poOpenInfo->pszFilename);
     m_osURL = (STARTS_WITH_CI(m_pszName, "ES:")) ? m_pszName + 3 : m_pszName;
-    if( m_osURL.size() == 0 )
+    if( m_osURL.empty() )
     {
         const char* pszHost =
             CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "HOST", "localhost");
@@ -371,11 +460,15 @@ int OGRElasticDataSource::Open(GDALOpenInfo* poOpenInfo)
     m_nBatchSize = atoi(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "BATCH_SIZE", "100"));
     m_nFeatureCountToEstablishFeatureDefn = atoi(CSLFetchNameValueDef(
         poOpenInfo->papszOpenOptions, "FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN", "100"));
-    m_bJSonField = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "JSON_FIELD", FALSE);
-    m_bFlattenNestedAttributes = CSLFetchBoolean(
-            poOpenInfo->papszOpenOptions, "FLATTEN_NESTED_ATTRIBUTES", TRUE);
+    m_bJSonField =
+        CPLFetchBool(poOpenInfo->papszOpenOptions, "JSON_FIELD", false);
+    m_bFlattenNestedAttributes = CPLFetchBool(
+            poOpenInfo->papszOpenOptions, "FLATTEN_NESTED_ATTRIBUTES", true);
     m_osFID = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "FID", "ogc_fid");
 
+    if( !CheckVersion() )
+        return FALSE;
+
     CPLHTTPResult* psResult = CPLHTTPFetch((m_osURL + "/_cat/indices?h=i").c_str(), NULL);
     if( psResult == NULL || psResult->pszErrBuf != NULL )
     {
@@ -410,13 +503,13 @@ int OGRElasticDataSource::Open(GDALOpenInfo* poOpenInfo)
 
         const char* pszIndexName = pszCur;
 
-        json_object* poRes = RunRequest((m_osURL + CPLString("/") + pszIndexName + CPLString("?pretty")).c_str());
+        json_object* poRes = RunRequest((m_osURL + CPLString("/") + pszIndexName + CPLString("/_mapping?pretty")).c_str());
         if( poRes )
         {
-            json_object* poLayerObj = json_object_object_get(poRes, pszIndexName);
+            json_object* poLayerObj = CPL_json_object_object_get(poRes, pszIndexName);
             json_object* poMappings = NULL;
             if( poLayerObj && json_object_get_type(poLayerObj) == json_type_object )
-                poMappings = json_object_object_get(poLayerObj, "mappings");
+                poMappings = CPL_json_object_object_get(poLayerObj, "mappings");
             if( poMappings && json_object_get_type(poMappings) == json_type_object )
             {
                 json_object_iter it;
@@ -433,7 +526,7 @@ int OGRElasticDataSource::Open(GDALOpenInfo* poOpenInfo)
                 {
                     OGRElasticLayer* poLayer = new OGRElasticLayer(
                         pszCur, pszCur, aosMappings[0], this, poOpenInfo->papszOpenOptions);
-                    poLayer->InitFeatureDefnFromMapping(json_object_object_get(poMappings, aosMappings[0]),
+                    poLayer->InitFeatureDefnFromMapping(CPL_json_object_object_get(poMappings, aosMappings[0]),
                                                         "", std::vector<CPLString>());
 
                     m_nLayers++;
@@ -446,7 +539,7 @@ int OGRElasticDataSource::Open(GDALOpenInfo* poOpenInfo)
                     {
                         OGRElasticLayer* poLayer = new OGRElasticLayer(
                             (pszCur + CPLString("_") + aosMappings[i]).c_str(), pszCur, aosMappings[i], this, poOpenInfo->papszOpenOptions);
-                        poLayer->InitFeatureDefnFromMapping(json_object_object_get(poMappings, aosMappings[i]),
+                        poLayer->InitFeatureDefnFromMapping(CPL_json_object_object_get(poMappings, aosMappings[i]),
                                                             "", std::vector<CPLString>());
 
                         m_nLayers++;
@@ -467,7 +560,6 @@ int OGRElasticDataSource::Open(GDALOpenInfo* poOpenInfo)
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                             Delete()                                 */
 /************************************************************************/
@@ -486,24 +578,30 @@ void OGRElasticDataSource::Delete(const CPLString &url) {
 /*                            UploadFile()                              */
 /************************************************************************/
 
-int OGRElasticDataSource::UploadFile(const CPLString &url, const CPLString &data) {
-    int bRet = TRUE;
+bool OGRElasticDataSource::UploadFile( const CPLString &url,
+                                       const CPLString &data )
+{
+    bool bRet = true;
     char** papszOptions = NULL;
-    papszOptions = CSLAddNameValue(papszOptions, "POSTFIELDS", data.c_str());
+    if( data.empty() )
+        papszOptions = CSLAddNameValue(papszOptions, "CUSTOMREQUEST", "PUT");
+    else
+        papszOptions = CSLAddNameValue(papszOptions, "POSTFIELDS", data.c_str());
     papszOptions = CSLAddNameValue(papszOptions, "HEADERS",
             "Content-Type: application/x-javascript; charset=UTF-8");
 
     CPLHTTPResult* psResult = CPLHTTPFetch(url, papszOptions);
     CSLDestroy(papszOptions);
-    if (psResult) {
+    if( psResult )
+    {
         if( psResult->pszErrBuf != NULL ||
             (psResult->pabyData && STARTS_WITH((const char*) psResult->pabyData, "{\"error\":")) ||
             (psResult->pabyData && strstr((const char*) psResult->pabyData, "\"errors\":true,") != NULL) )
         {
-            bRet = FALSE;
+            bRet = false;
             CPLError(CE_Failure, CPLE_AppDefined, "%s",
-                        psResult->pabyData ? (const char*) psResult->pabyData :
-                        psResult->pszErrBuf);
+                     psResult->pabyData ? (const char*) psResult->pabyData :
+                     psResult->pszErrBuf);
         }
         CPLHTTPDestroyResult(psResult);
     }
@@ -518,14 +616,14 @@ int OGRElasticDataSource::Create(const char *pszFilename,
                                  CPL_UNUSED char **papszOptions)
 {
     eAccess = GA_Update;
-    this->m_pszName = CPLStrdup(pszFilename);
+    m_pszName = CPLStrdup(pszFilename);
     m_osURL = (STARTS_WITH_CI(pszFilename, "ES:")) ? pszFilename + 3 : pszFilename;
-    if( m_osURL.size() == 0 )
+    if( m_osURL.empty() )
         m_osURL = "localhost:9200";
 
     const char* pszMetaFile = CPLGetConfigOption("ES_META", NULL);
-    this->m_bOverwrite = CPLTestBool(CPLGetConfigOption("ES_OVERWRITE", "0"));
-    this->m_nBulkUpload = (int) CPLAtof(CPLGetConfigOption("ES_BULK", "0"));
+    m_bOverwrite = CPLTestBool(CPLGetConfigOption("ES_OVERWRITE", "0"));
+    m_nBulkUpload = (int) CPLAtof(CPLGetConfigOption("ES_BULK", "0"));
 
     // Read in the meta file from disk
     if (pszMetaFile != NULL)
@@ -537,24 +635,32 @@ int OGRElasticDataSource::Create(const char *pszFilename,
             CPL_IGNORE_RET_VAL(VSIIngestFile( fp, pszMetaFile, &pabyRet, NULL, -1));
             if( pabyRet )
             {
-                this->m_pszMapping = (char*)pabyRet;
+                m_pszMapping = (char*)pabyRet;
             }
             VSIFCloseL(fp);
         }
     }
 
-    // Do a status check to ensure that the server is valid
-    CPLHTTPResult* psResult = CPLHTTPFetch(CPLSPrintf("%s/_stats", m_osURL.c_str()), NULL);
-    int bOK = (psResult != NULL && psResult->pszErrBuf == NULL);
-    if (!bOK)
-    {
-        CPLError(CE_Failure, CPLE_NoWriteAccess,
-                "Could not connect to server");
-    }
+    return CheckVersion();
+}
 
-    CPLHTTPDestroyResult(psResult);
+/************************************************************************/
+/*                           GetLayerIndex()                            */
+/************************************************************************/
 
-    return bOK;
+int OGRElasticDataSource::GetLayerIndex( const char* pszName )
+{
+    for( int i=0; i < m_nLayers; ++i )
+    {
+        if( strcmp( m_papoLayers[i]->GetName(), pszName ) == 0 )
+            return i;
+    }
+    for( int i=0; i < m_nLayers; ++i )
+    {
+        if( EQUAL( m_papoLayers[i]->GetName(), pszName ) )
+            return i;
+    }
+    return -1;
 }
 
 /************************************************************************/
@@ -600,17 +706,107 @@ OGRLayer* OGRElasticDataSource::ExecuteSQL( const char *pszSQLCommand,
                                    this, papszOpenOptions,
                                    pszSQLCommand);
     }
-    else
+
+
+/* -------------------------------------------------------------------- */
+/*      Deal with "SELECT xxxx ORDER BY" statement                      */
+/* -------------------------------------------------------------------- */
+    if (STARTS_WITH_CI(pszSQLCommand, "SELECT"))
     {
-        return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
+        swq_select* psSelectInfo = new swq_select();
+        if( psSelectInfo->preparse( pszSQLCommand, TRUE ) != CE_None )
+        {
+            delete psSelectInfo;
+            return NULL;
+        }
+
+        int iLayer = 0;
+        if( psSelectInfo->table_count == 1 &&
+            psSelectInfo->table_defs[0].data_source == NULL &&
+            (iLayer =
+                GetLayerIndex( psSelectInfo->table_defs[0].table_name )) >= 0 &&
+            psSelectInfo->join_count == 0 &&
+            psSelectInfo->order_specs > 0 &&
+            psSelectInfo->poOtherSelect == NULL )
+        {
+            OGRElasticLayer* poSrcLayer = m_papoLayers[iLayer];
+            std::vector<OGRESSortDesc> aoSortColumns;
+            int i = 0;  // Used after for.
+            for( ; i < psSelectInfo->order_specs; i++ )
+            {
+                int nFieldIndex = poSrcLayer->GetLayerDefn()->GetFieldIndex(
+                                        psSelectInfo->order_defs[i].field_name);
+                if (nFieldIndex < 0)
+                    break;
+
+                /* Make sure to have the right case */
+                const char* pszFieldName = poSrcLayer->GetLayerDefn()->
+                    GetFieldDefn(nFieldIndex)->GetNameRef();
+
+                OGRESSortDesc oSortDesc(pszFieldName,
+                    CPL_TO_BOOL(psSelectInfo->order_defs[i].ascending_flag));
+                aoSortColumns.push_back(oSortDesc);
+            }
+
+            if( i == psSelectInfo->order_specs )
+            {
+                OGRElasticLayer* poDupLayer = poSrcLayer->Clone();
+
+                poDupLayer->SetOrderBy(aoSortColumns);
+                int nBackup = psSelectInfo->order_specs;
+                psSelectInfo->order_specs = 0;
+                char* pszSQLWithoutOrderBy = psSelectInfo->Unparse();
+                CPLDebug("ES", "SQL without ORDER BY: %s", pszSQLWithoutOrderBy);
+                psSelectInfo->order_specs = nBackup;
+                delete psSelectInfo;
+                psSelectInfo = NULL;
+
+                /* Just set poDupLayer in the papoLayers for the time of the */
+                /* base ExecuteSQL(), so that the OGRGenSQLResultsLayer */
+                /* references  that temporary layer */
+                m_papoLayers[iLayer] = poDupLayer;
+
+                OGRLayer* poResLayer = GDALDataset::ExecuteSQL(
+                    pszSQLWithoutOrderBy, poSpatialFilter, pszDialect );
+                m_papoLayers[iLayer] = poSrcLayer;
+
+                CPLFree(pszSQLWithoutOrderBy);
+
+                if (poResLayer != NULL)
+                    m_oMapResultSet[poResLayer] = poDupLayer;
+                else
+                    delete poDupLayer;
+                return poResLayer;
+            }
+        }
+        delete psSelectInfo;
     }
+
+    return GDALDataset::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
 }
 
 /************************************************************************/
 /*                          ReleaseResultSet()                          */
 /************************************************************************/
 
-void OGRElasticDataSource::ReleaseResultSet( OGRLayer * poLayer )
+void OGRElasticDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
 {
-    delete poLayer;
+    if (poResultsSet == NULL)
+        return;
+
+    std::map<OGRLayer*, OGRLayer*>::iterator oIter =
+                                        m_oMapResultSet.find(poResultsSet);
+    if (oIter != m_oMapResultSet.end())
+    {
+        /* Destroy first the result layer, because it still references */
+        /* the poDupLayer (oIter->second) */
+        delete poResultsSet;
+
+        delete oIter->second;
+        m_oMapResultSet.erase(oIter);
+    }
+    else
+    {
+        delete poResultsSet;
+    }
 }
diff --git a/ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp b/ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp
index 61af233..4e51c1c 100644
--- a/ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp
+++ b/ogr/ogrsf_frmts/elastic/ogrelasticdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrelasticdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -30,7 +29,7 @@
 #include "ogr_elastic.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrelasticdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrelasticdriver.cpp 37072 2017-01-09 12:54:57Z rouault $");
 
 /************************************************************************/
 /*                   OGRElasticSearchDriverIdentify()                   */
@@ -108,7 +107,8 @@ void RegisterOGRElastic() {
     "  <Option name='MAPPING_NAME' type='string' description='Name of the mapping type within the index.' default='FeatureCollection'/>"
     "  <Option name='MAPPING' type='string' description='Filename from which to read a user-defined mapping, or mapping as serialized JSon.'/>"
     "  <Option name='WRITE_MAPPING' type='string' description='Filename where to write the OGR generated mapping.'/>"
-    "  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing collection with the layer name to be created' default='NO'/>"
+    "  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing type mapping with the layer name to be created' default='NO'/>"
+    "  <Option name='OVERWRITE_INDEX' type='boolean' description='Whether to overwrite the whole index to which the layer belongs to' default='NO'/>"
     "  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column.' default='geometry'/>"
     "  <Option name='GEOM_MAPPING_TYPE' type='string-select' description='Mapping type for geometry fields' default='AUTO'>"
     "    <Value>AUTO</Value>"
@@ -118,8 +118,9 @@ void RegisterOGRElastic() {
     "  <Option name='GEOM_PRECISION' type='string' description='Desired geometry precision. Number followed by unit. For example 1m'/>"
     "  <Option name='STORE_FIELDS' type='boolean' description='Whether fields should be stored in the index' default='NO'/>"
     "  <Option name='STORED_FIELDS' type='string' description='List of comma separated field names that should be stored in the index'/>"
-    "  <Option name='NOT_ANALYZED_FIELDS' type='string' description='List of comma separated field names that should not be analyzed during indexing'/>"
+    "  <Option name='NOT_ANALYZED_FIELDS' type='string' description='List of comma separated field names that should not be analyzed during indexing, or {ALL}'/>"
     "  <Option name='NOT_INDEXED_FIELDS' type='string' description='List of comma separated field names that should not be indexed'/>"
+    "  <Option name='FIELDS_WITH_RAW_VALUE' type='string' description='List of comma separated field names (of type string) that should have an additional raw/not_analyzed field, or {ALL}'/>"
     "  <Option name='BULK_INSERT' type='boolean' description='Whether to use bulk insert for feature creation' default='YES'/>"
     "  <Option name='BULK_SIZE' type='integer' description='Size in bytes of the buffer for bulk upload' default='1000000'/>"
     "  <Option name='DOT_AS_NESTED_FIELD' type='boolean' description='Whether to consider dot character in field name as sub-document' default='YES'/>"
diff --git a/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp b/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp
index acfd6f5..a6a4345 100644
--- a/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp
+++ b/ogr/ogrsf_frmts/elastic/ogrelasticlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrelasticlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  ElasticSearch Translator
  * Purpose:
@@ -7,7 +6,7 @@
  *
  ******************************************************************************
  * Copyright (c) 2011, Adam Estrada
- * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2012-2016, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,34 +33,59 @@
 #include "cpl_http.h"
 #include "ogr_api.h"
 #include "ogr_p.h"
+#include "swq.h"
 #include "../geojson/ogrgeojsonwriter.h"
 #include "../geojson/ogrgeojsonreader.h"
 #include "../geojson/ogrgeojsonutils.h"
 #include "../xplane/ogr_xplane_geo_utils.h"
+
+#include <cstdlib>
 #include <set>
 
-CPL_CVSID("$Id: ogrelasticlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrelasticlayer.cpp 37472 2017-02-26 02:47:45Z goatbar $");
 
 /************************************************************************/
 /*                           OGRElasticLayer()                          */
 /************************************************************************/
 
-OGRElasticLayer::OGRElasticLayer(const char* pszLayerName,
-                                 const char* pszIndexName,
-                                 const char* pszMappingName,
-                                 OGRElasticDataSource* poDS,
-                                 char** papszOptions,
-                                 const char* pszESSearch)
+OGRElasticLayer::OGRElasticLayer( const char* pszLayerName,
+                                  const char* pszIndexName,
+                                  const char* pszMappingName,
+                                  OGRElasticDataSource* poDS,
+                                  char** papszOptions,
+                                  const char* pszESSearch ) :
+
+    m_poDS(poDS),
+    m_osIndexName(pszIndexName ? pszIndexName : ""),
+    m_osMappingName(pszMappingName ? pszMappingName : ""),
+    m_poFeatureDefn(new OGRFeatureDefn(pszLayerName)),
+    m_bFeatureDefnFinalized(false),
+    m_bManualMapping(false),
+    m_bSerializeMapping(false),
+    m_osWriteMapFilename(
+        CSLFetchNameValueDef(papszOptions, "WRITE_MAPPING",
+                             poDS->m_pszWriteMap ? poDS->m_pszWriteMap : "")),
+    m_bStoreFields(CPLFetchBool(papszOptions, "STORE_FIELDS", false)),
+    m_papszStoredFields(NULL),
+    m_papszNotAnalyzedFields(NULL),
+    m_papszNotIndexedFields(NULL),
+    m_papszFieldsWithRawValue(NULL),
+    m_osESSearch(pszESSearch ? pszESSearch : ""),
+    m_nBulkUpload(poDS->m_nBulkUpload),
+    m_eGeomTypeMapping(ES_GEOMTYPE_AUTO),
+    m_osPrecision(CSLFetchNameValueDef(papszOptions, "GEOM_PRECISION", "")),
+    m_iCurID(0),
+    m_nNextFID(-1),
+    m_iCurFeatureInPage(0),
+    m_bEOF(false),
+    m_poSpatialFilter(NULL),
+    m_bFilterMustBeClientSideEvaluated(false),
+    m_poJSONFilter(NULL),
+    m_bIgnoreSourceID(false),
+    m_bDotAsNestedField(true),
+    // Undocumented. Only useful for developers.
+    m_bAddPretty(CPLTestBool(CPLGetConfigOption("ES_ADD_PRETTY", "FALSE")))
 {
-    m_poDS = poDS;
-
-    m_osIndexName = pszIndexName ? pszIndexName : "";
-    m_osMappingName = pszMappingName ? pszMappingName : "";
-    m_osESSearch = pszESSearch ? pszESSearch : "";
-    m_osWriteMapFilename = CSLFetchNameValueDef(papszOptions, "WRITE_MAPPING",
-                                      m_poDS->m_pszWriteMap ? m_poDS->m_pszWriteMap : "");
-
-    m_eGeomTypeMapping = ES_GEOMTYPE_AUTO;
     const char* pszESGeomType = CSLFetchNameValue(papszOptions, "GEOM_MAPPING_TYPE");
     if( pszESGeomType != NULL )
     {
@@ -70,66 +94,78 @@ OGRElasticLayer::OGRElasticLayer(const char* pszLayerName,
         else if( EQUAL(pszESGeomType, "GEO_SHAPE") )
             m_eGeomTypeMapping = ES_GEOMTYPE_GEO_SHAPE;
     }
-    m_nBulkUpload = m_poDS->m_nBulkUpload;
-    if( CSLFetchBoolean(papszOptions, "BULK_INSERT", TRUE) )
+    if( CPLFetchBool(papszOptions, "BULK_INSERT", true) )
     {
         m_nBulkUpload = atoi(CSLFetchNameValueDef(papszOptions, "BULK_SIZE", "1000000"));
     }
 
-    m_osPrecision = CSLFetchNameValueDef(papszOptions, "GEOM_PRECISION", "");
-    m_bStoreFields = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "STORE_FIELDS", false));
-
     const char* pszStoredFields = CSLFetchNameValue(papszOptions, "STORED_FIELDS");
     if( pszStoredFields )
         m_papszStoredFields = CSLTokenizeString2(pszStoredFields, ",", 0);
-    else
-        m_papszStoredFields = NULL;
 
     const char* pszNotAnalyzedFields = CSLFetchNameValue(papszOptions, "NOT_ANALYZED_FIELDS");
     if( pszNotAnalyzedFields )
         m_papszNotAnalyzedFields = CSLTokenizeString2(pszNotAnalyzedFields, ",", 0);
-    else
-        m_papszNotAnalyzedFields = NULL;
 
     const char* pszNotIndexedFields = CSLFetchNameValue(papszOptions, "NOT_INDEXED_FIELDS");
     if( pszNotIndexedFields )
         m_papszNotIndexedFields = CSLTokenizeString2(pszNotIndexedFields, ",", 0);
-    else
-        m_papszNotIndexedFields = NULL;
 
-    m_poFeatureDefn = new OGRFeatureDefn(pszLayerName);
+    const char* pszFieldsWithRawValue = CSLFetchNameValue(papszOptions,
+                                                    "FIELDS_WITH_RAW_VALUE");
+    if( pszFieldsWithRawValue )
+        m_papszFieldsWithRawValue = CSLTokenizeString2(
+                                            pszFieldsWithRawValue, ",", 0);
+
     SetDescription( m_poFeatureDefn->GetName() );
     m_poFeatureDefn->Reference();
     m_poFeatureDefn->SetGeomType(wkbNone);
 
     AddFieldDefn("_id", OFTString, std::vector<CPLString>());
 
-    if( m_osESSearch.size() )
+    if( !m_osESSearch.empty() )
     {
         AddFieldDefn("_index", OFTString, std::vector<CPLString>());
         AddFieldDefn("_type", OFTString, std::vector<CPLString>());
     }
 
-    m_bFeatureDefnFinalized = FALSE;
-    m_bSerializeMapping = FALSE;
-    m_bManualMapping = FALSE;
-    m_bDotAsNestedField = TRUE;
-
-    m_iCurID = 0;
-    m_nNextFID = -1;
-    m_iCurFeatureInPage = 0;
-    m_bEOF = FALSE;
-    m_poSpatialFilter = NULL;
-    m_bIgnoreSourceID = FALSE;
-
-    // Undocumented. Only useful for developers
-    m_bAddPretty = CPLTestBool(CPLGetConfigOption("ES_ADD_PRETTY", "FALSE"));
-
     ResetReading();
     return;
 }
 
 /************************************************************************/
+/*                              Clone()                                 */
+/************************************************************************/
+
+OGRElasticLayer* OGRElasticLayer::Clone() const
+{
+    OGRElasticLayer* poNew = new OGRElasticLayer(m_poFeatureDefn->GetName(),
+                                                 m_osIndexName,
+                                                 m_osMappingName,
+                                                 m_poDS,
+                                                 NULL);
+    poNew->m_poFeatureDefn->Release();
+    poNew->m_poFeatureDefn =
+        const_cast<OGRElasticLayer*>(this)->GetLayerDefn()->Clone();
+    poNew->m_poFeatureDefn->Reference();
+    poNew->m_bFeatureDefnFinalized = true;
+    poNew->m_osBulkContent = m_osBulkContent;
+    poNew->m_nBulkUpload = m_nBulkUpload;
+    poNew->m_osFID = m_osFID;
+    poNew->m_aaosFieldPaths = m_aaosFieldPaths;
+    poNew->m_aosMapToFieldIndex = m_aosMapToFieldIndex;
+    poNew->m_aaosGeomFieldPaths = m_aaosGeomFieldPaths;
+    poNew->m_aosMapToGeomFieldIndex = m_aosMapToGeomFieldIndex;
+    poNew->m_abIsGeoPoint = m_abIsGeoPoint;
+    poNew->m_eGeomTypeMapping = m_eGeomTypeMapping;
+    poNew->m_osPrecision = m_osPrecision;
+    poNew->m_papszNotAnalyzedFields = CSLDuplicate(m_papszNotAnalyzedFields);
+    poNew->m_papszNotIndexedFields = CSLDuplicate(m_papszNotIndexedFields);
+    poNew->m_papszFieldsWithRawValue = CSLDuplicate(m_papszFieldsWithRawValue);
+    return poNew;
+}
+
+/************************************************************************/
 /*                         ~OGRElasticLayer()                           */
 /************************************************************************/
 
@@ -139,6 +175,7 @@ OGRElasticLayer::~OGRElasticLayer() {
     ResetReading();
 
     json_object_put(m_poSpatialFilter);
+    json_object_put(m_poJSONFilter);
 
     for(int i=0;i<(int)m_apoCT.size();i++)
         delete m_apoCT[i];
@@ -148,6 +185,7 @@ OGRElasticLayer::~OGRElasticLayer() {
     CSLDestroy(m_papszStoredFields);
     CSLDestroy(m_papszNotAnalyzedFields);
     CSLDestroy(m_papszNotIndexedFields);
+    CSLDestroy(m_papszFieldsWithRawValue);
 }
 
 /************************************************************************/
@@ -164,7 +202,7 @@ void OGRElasticLayer::AddFieldDefn( const char* pszName,
     if( eSubType == OFSTBoolean )
         oFieldDefn.SetWidth(1);
     m_aaosFieldPaths.push_back(aosPath);
-    if( aosPath.size() )
+    if( !aosPath.empty() )
         m_aosMapToFieldIndex[ BuildPathFromArray(aosPath) ] = m_poFeatureDefn->GetFieldCount();
     m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
 }
@@ -201,7 +239,7 @@ void OGRElasticLayer::InitFeatureDefnFromMapping(json_object* poSchema,
                                                  const char* pszPrefix,
                                                  const std::vector<CPLString>& aosPath)
 {
-    json_object* poTopProperties = json_object_object_get(poSchema, "properties");
+    json_object* poTopProperties = CPL_json_object_object_get(poSchema, "properties");
     if( poTopProperties == NULL || json_object_get_type(poTopProperties) != json_type_object )
         return;
     json_object_iter it;
@@ -210,7 +248,7 @@ void OGRElasticLayer::InitFeatureDefnFromMapping(json_object* poSchema,
     it.entry = NULL;
     json_object_object_foreachC( poTopProperties, it )
     {
-        json_object* poProperties = json_object_object_get(it.val, "properties");
+        json_object* poProperties = CPL_json_object_object_get(it.val, "properties");
         if( poProperties && json_object_get_type(poProperties) == json_type_object )
         {
             json_object* poType = json_ex_get_object_by_path(poProperties, "coordinates.type");
@@ -237,7 +275,7 @@ void OGRElasticLayer::InitFeatureDefnFromMapping(json_object* poSchema,
                 continue;
             }
 
-            if( aosPath.size() == 0 && m_osMappingName == "FeatureCollection" && strcmp(it.key, "properties") == 0 )
+            if( aosPath.empty() && m_osMappingName == "FeatureCollection" && strcmp(it.key, "properties") == 0 )
             {
                 std::vector<CPLString> aosNewPaths = aosPath;
                 aosNewPaths.push_back(it.key);
@@ -265,7 +303,7 @@ void OGRElasticLayer::InitFeatureDefnFromMapping(json_object* poSchema,
             }
         }
 
-        if( aosPath.size() == 0 && EQUAL(it.key, m_poDS->GetFID()) )
+        if( aosPath.empty() && EQUAL(it.key, m_poDS->GetFID()) )
         {
             m_osFID = it.key;
         }
@@ -275,21 +313,21 @@ void OGRElasticLayer::InitFeatureDefnFromMapping(json_object* poSchema,
         }
     }
 
-    if( aosPath.size() == 0 )
+    if( aosPath.empty() )
     {
-        json_object* poMeta = json_object_object_get(poSchema, "_meta");
+        json_object* poMeta = CPL_json_object_object_get(poSchema, "_meta");
         if( poMeta && json_object_get_type(poMeta) == json_type_object )
         {
-            json_object* poFID = json_object_object_get(poMeta, "fid");
+            json_object* poFID = CPL_json_object_object_get(poMeta, "fid");
             if( poFID && json_object_get_type(poFID) == json_type_string )
                 m_osFID = json_object_get_string(poFID);
 
-            json_object* poGeomFields = json_object_object_get(poMeta, "geomfields");
+            json_object* poGeomFields = CPL_json_object_object_get(poMeta, "geomfields");
             if( poGeomFields && json_object_get_type(poGeomFields) == json_type_object )
             {
                 for( int i=0; i< m_poFeatureDefn->GetGeomFieldCount(); i++ )
                 {
-                    json_object* poObj = json_object_object_get(poGeomFields,
+                    json_object* poObj = CPL_json_object_object_get(poGeomFields,
                             m_poFeatureDefn->GetGeomFieldDefn(i)->GetNameRef());
                     if( poObj && json_object_get_type(poObj) == json_type_string )
                     {
@@ -300,12 +338,12 @@ void OGRElasticLayer::InitFeatureDefnFromMapping(json_object* poSchema,
                 }
             }
 
-            json_object* poFields = json_object_object_get(poMeta, "fields");
+            json_object* poFields = CPL_json_object_object_get(poMeta, "fields");
             if( poFields && json_object_get_type(poFields) == json_type_object )
             {
                 for( int i=0; i< m_poFeatureDefn->GetFieldCount(); i++ )
                 {
-                    json_object* poObj = json_object_object_get(poFields,
+                    json_object* poObj = CPL_json_object_object_get(poFields,
                             m_poFeatureDefn->GetFieldDefn(i)->GetNameRef());
                     if( poObj && json_object_get_type(poObj) == json_type_string )
                     {
@@ -335,7 +373,7 @@ void OGRElasticLayer::CreateFieldFromSchema(const char* pszName,
                                             json_object* poObj)
 {
     const char* pszType = "";
-    json_object* poType = json_object_object_get(poObj, "type");
+    json_object* poType = CPL_json_object_object_get(poObj, "type");
     if( poType && json_object_get_type(poType) == json_type_string )
     {
         pszType = json_object_get_string(poType);
@@ -359,7 +397,7 @@ void OGRElasticLayer::CreateFieldFromSchema(const char* pszName,
                          EQUAL(pszType, "geo_point") ? wkbPoint : wkbUnknown,
                          aosPath, EQUAL(pszType, "geo_point"));
     }
-    else if( !( aosPath.size() == 0 && m_osMappingName == "FeatureCollection" ) )
+    else if( !( aosPath.empty() && m_osMappingName == "FeatureCollection" ) )
     {
         if( m_poFeatureDefn->GetFieldIndex(osFieldName) >= 0 )
             return;
@@ -382,7 +420,7 @@ void OGRElasticLayer::CreateFieldFromSchema(const char* pszName,
         else if( EQUAL(pszType, "date") )
         {
             eType = OFTDateTime;
-            json_object* poFormat = json_object_object_get(poObj, "format");
+            json_object* poFormat = CPL_json_object_object_get(poObj, "format");
             if( poFormat && json_object_get_type(poFormat) == json_type_string )
             {
                 const char* pszFormat = json_object_get_string(poFormat);
@@ -394,9 +432,64 @@ void OGRElasticLayer::CreateFieldFromSchema(const char* pszName,
         }
         else if( EQUAL(pszType, "binary") )
             eType = OFTBinary;
+        else if( EQUAL(pszType, "string") ) // ES < 5.0
+        {
+            json_object* poIndex =  CPL_json_object_object_get(poObj, "index");
+            if( poIndex && json_object_get_type(poIndex) == json_type_string )
+            {
+                const char* pszIndex = json_object_get_string(poIndex);
+                if( EQUAL(pszIndex, "not_analyzed") )
+                {
+                    m_papszNotAnalyzedFields = CSLAddString(
+                        m_papszNotAnalyzedFields, osFieldName);
+                }
+            }
+        }
+        else if( EQUAL(pszType, "keyword") ) // ES >= 5.0
+        {
+            m_papszNotAnalyzedFields = CSLAddString(
+                        m_papszNotAnalyzedFields, osFieldName);
+        }
 
         aosPath.push_back( pszName );
         AddFieldDefn(osFieldName, eType, aosPath, eSubType);
+
+        json_object* poFields = CPL_json_object_object_get(poObj, "fields");
+        if( poFields && json_object_get_type(poFields) == json_type_object )
+        {
+            json_object* poRaw = CPL_json_object_object_get(poFields, "raw");
+            if( poRaw && json_object_get_type(poRaw) == json_type_object )
+            {
+                json_object* poRawType = CPL_json_object_object_get(poRaw,
+                                                                    "type");
+                if( poRawType && json_object_get_type(poRawType) ==
+                                                            json_type_string )
+                {
+                    const char* pszRawType = json_object_get_string(poRawType);
+                    if( EQUAL(pszRawType, "keyword") ) // ES >= 5.0
+                    {
+                        m_papszFieldsWithRawValue = CSLAddString(
+                            m_papszFieldsWithRawValue, osFieldName);
+                    }
+                    else if( EQUAL(pszRawType, "string") ) // ES < 5.0
+                    {
+                        json_object* poRawIndex = CPL_json_object_object_get(
+                            poRaw, "index");
+                        if( poRawIndex && json_object_get_type(poRawIndex) ==
+                                                            json_type_string )
+                        {
+                            const char* pszRawIndex =
+                                json_object_get_string(poRawIndex);
+                            if( EQUAL(pszRawIndex, "not_analyzed") )
+                            {
+                                m_papszFieldsWithRawValue = CSLAddString(
+                                    m_papszFieldsWithRawValue, osFieldName);
+                            }
+                        }
+                    }
+                }
+            }
+        }
     }
 }
 
@@ -404,15 +497,15 @@ void OGRElasticLayer::CreateFieldFromSchema(const char* pszName,
 /*                        FinalizeFeatureDefn()                         */
 /************************************************************************/
 
-void OGRElasticLayer::FinalizeFeatureDefn(int bReadFeatures)
+void OGRElasticLayer::FinalizeFeatureDefn(bool bReadFeatures)
 {
     if( m_bFeatureDefnFinalized )
         return;
 
-    m_bFeatureDefnFinalized = TRUE;
+    m_bFeatureDefnFinalized = true;
 
     int nFeatureCountToEstablishFeatureDefn = m_poDS->m_nFeatureCountToEstablishFeatureDefn;
-    if( m_osESSearch.size() && nFeatureCountToEstablishFeatureDefn <= 0 )
+    if( !m_osESSearch.empty() && nFeatureCountToEstablishFeatureDefn <= 0 )
         nFeatureCountToEstablishFeatureDefn = 1;
     std::set< std::pair<CPLString, CPLString> > oVisited;
 
@@ -420,16 +513,16 @@ void OGRElasticLayer::FinalizeFeatureDefn(int bReadFeatures)
     {
         //CPLDebug("ES", "Try to get %d features to establish feature definition",
         //         FeatureCountToEstablishFeatureDefn);
-        int bFirst = TRUE;
+        bool bFirst = true;
         int nAlreadyQueried = 0;
         while( true )
         {
-            json_object* poResponse;
-            CPLString osRequest, osPostData;
+            CPLString osRequest;
+            CPLString osPostData;
             if( bFirst )
             {
-                bFirst = FALSE;
-                if(  m_osESSearch.size() )
+                bFirst = false;
+                if(  !m_osESSearch.empty() )
                 {
                     osRequest = CPLSPrintf("%s/_search?scroll=1m&size=%d",
                            m_poDS->GetURL(), m_poDS->m_nBatchSize);
@@ -442,20 +535,20 @@ void OGRElasticLayer::FinalizeFeatureDefn(int bReadFeatures)
             }
             else
             {
-                if( m_osScrollID.size() == 0 )
+                if( m_osScrollID.empty() )
                     break;
-                osRequest = CPLSPrintf("%s/_search/scroll?scroll=1m&size=%d&scroll_id=%s",
-                               m_poDS->GetURL(), m_poDS->m_nBatchSize, m_osScrollID.c_str());
+                osRequest = CPLSPrintf("%s/_search/scroll?scroll=1m&scroll_id=%s",
+                               m_poDS->GetURL(), m_osScrollID.c_str());
             }
 
             if( m_bAddPretty )
                 osRequest += "&pretty";
-            poResponse = m_poDS->RunRequest(osRequest, osPostData);
+            json_object* poResponse = m_poDS->RunRequest(osRequest, osPostData);
             if( poResponse == NULL )
             {
                 break;
             }
-            json_object* poScrollID = json_object_object_get(poResponse, "_scroll_id");
+            json_object* poScrollID = CPL_json_object_object_get(poResponse, "_scroll_id");
             if( poScrollID )
             {
                 const char* pszScrollID = json_object_get_string(poScrollID);
@@ -483,18 +576,18 @@ void OGRElasticLayer::FinalizeFeatureDefn(int bReadFeatures)
                 {
                     continue;
                 }
-                json_object* poSource = json_object_object_get(poHit, "_source");
+                json_object* poSource = CPL_json_object_object_get(poHit, "_source");
                 if( poSource == NULL || json_object_get_type(poSource) != json_type_object )
                 {
                     continue;
                 }
 
-                if( m_osESSearch.size() )
+                if( !m_osESSearch.empty() )
                 {
-                    json_object* poIndex = json_object_object_get(poHit, "_index");
+                    json_object* poIndex = CPL_json_object_object_get(poHit, "_index");
                     if( poIndex == NULL || json_object_get_type(poIndex) != json_type_string )
                         break;
-                    json_object* poType = json_object_object_get(poHit, "_type");
+                    json_object* poType = CPL_json_object_object_get(poHit, "_type");
                     if( poType == NULL || json_object_get_type(poType) != json_type_string )
                         break;
                     CPLString osIndex(json_object_get_string(poIndex));
@@ -508,13 +601,13 @@ void OGRElasticLayer::FinalizeFeatureDefn(int bReadFeatures)
                             (m_poDS->GetURL() + CPLString("/") + osIndex + CPLString("/_mapping/") + m_osMappingName + CPLString("?pretty")).c_str());
                         if( poMappingRes )
                         {
-                            json_object* poLayerObj = json_object_object_get(poMappingRes, osIndex);
+                            json_object* poLayerObj = CPL_json_object_object_get(poMappingRes, osIndex);
                             json_object* poMappings = NULL;
                             if( poLayerObj && json_object_get_type(poLayerObj) == json_type_object )
-                                poMappings = json_object_object_get(poLayerObj, "mappings");
+                                poMappings = CPL_json_object_object_get(poLayerObj, "mappings");
                             if( poMappings && json_object_get_type(poMappings) == json_type_object )
                             {
-                                json_object* poMapping = json_object_object_get(poMappings, m_osMappingName);
+                                json_object* poMapping = CPL_json_object_object_get(poMappings, m_osMappingName);
                                 if( poMapping)
                                 {
                                     InitFeatureDefnFromMapping(poMapping, "", std::vector<CPLString>());
@@ -531,7 +624,7 @@ void OGRElasticLayer::FinalizeFeatureDefn(int bReadFeatures)
                 it.entry = NULL;
                 json_object_object_foreachC( poSource, it )
                 {
-                    if( m_osFID.size() )
+                    if( !m_osFID.empty() )
                     {
                         if( EQUAL(it.key, m_osFID) )
                             continue;
@@ -636,11 +729,11 @@ void OGRElasticLayer::AddOrUpdateField(const char* pszAttrName,
 
     if( eJSONType == json_type_object )
     {
-        json_object* poType = json_object_object_get(poObj, "type");
+        json_object* poType = CPL_json_object_object_get(poObj, "type");
         OGRwkbGeometryType eGeomType;
         if( poType && json_object_get_type(poType) == json_type_string &&
             (eGeomType = GetOGRGeomTypeFromES(json_object_get_string(poType))) != wkbUnknown &&
-            json_object_object_get(poObj, (eGeomType == wkbGeometryCollection) ? "geometries" : "coordinates") )
+            CPL_json_object_object_get(poObj, (eGeomType == wkbGeometryCollection) ? "geometries" : "coordinates") )
         {
             int nIndex = m_poFeatureDefn->GetGeomFieldIndex(pszAttrName);
             if( nIndex < 0 )
@@ -700,8 +793,12 @@ void OGRElasticLayer::AddOrUpdateField(const char* pszAttrName,
         (poFDefn != NULL &&
          (poFDefn->GetType() == OFTDate || poFDefn->GetType() == OFTDateTime || poFDefn->GetType() == OFTTime) ) )
     {
-        int nYear, nMonth, nDay, nHour, nMinute;
-        float fSecond;
+        int nYear = 0;
+        int nMonth = 0;
+        int nDay = 0;
+        int nHour = 0;
+        int nMinute = 0;
+        float fSecond = 0.0f;
         if( sscanf(json_object_get_string(poObj),
                    "%04d/%02d/%02d %02d:%02d",
                    &nYear, &nMonth, &nDay, &nHour, &nMinute) == 5 ||
@@ -754,7 +851,6 @@ OGRErr OGRElasticLayer::SyncToDisk()
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                            GetLayerDefn()                            */
 /************************************************************************/
@@ -782,7 +878,7 @@ const char* OGRElasticLayer::GetFIDColumn()
 
 void OGRElasticLayer::ResetReading()
 {
-    if( m_osScrollID.size() )
+    if( !m_osScrollID.empty() )
     {
         char** papszOptions = CSLAddNameValue(NULL, "CUSTOMREQUEST", "DELETE");
         CPLHTTPResult* psResult = CPLHTTPFetch((m_poDS->GetURL() + CPLString("/_search/scroll?scroll_id=") + m_osScrollID).c_str(), papszOptions);
@@ -796,7 +892,7 @@ void OGRElasticLayer::ResetReading()
     m_apoCachedFeatures.resize(0);
     m_iCurID = 0;
     m_iCurFeatureInPage = 0;
-    m_bEOF = FALSE;
+    m_bEOF = false;
 }
 
 /************************************************************************/
@@ -810,9 +906,7 @@ OGRFeature *OGRElasticLayer::GetNextFeature()
 
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -827,6 +921,71 @@ OGRFeature *OGRElasticLayer::GetNextFeature()
 }
 
 /************************************************************************/
+/*                           BuildSort()                                */
+/************************************************************************/
+
+json_object* OGRElasticLayer::BuildSort()
+{
+    json_object* poRet = json_object_new_array();
+    for( size_t i=0; i<m_aoSortColumns.size(); ++i)
+    {
+        const int nIdx =
+            m_poFeatureDefn->GetFieldIndex(m_aoSortColumns[i].osColumn);
+        CPLString osFieldName( nIdx == 0 ? "_uid" :
+                            BuildPathFromArray(m_aaosFieldPaths[ nIdx ]));
+        if( CSLFindString(m_papszFieldsWithRawValue,
+                          m_aoSortColumns[i].osColumn) >= 0 )
+        {
+            osFieldName += ".raw";
+        }
+        json_object* poSortCol = json_object_new_object();
+        json_object* poSortProp = json_object_new_object();
+        json_object_array_add(poRet, poSortCol);
+        json_object_object_add(poSortProp, "order",
+            json_object_new_string(m_aoSortColumns[i].bAsc ? "asc" : "desc"));
+        json_object_object_add(poSortCol, osFieldName, poSortProp);
+    }
+    return poRet;
+}
+
+/************************************************************************/
+/*                           BuildQuery()                               */
+/************************************************************************/
+
+CPLString OGRElasticLayer::BuildQuery(bool bCountOnly)
+{
+    CPLString osRet = "{ ";
+    if( bCountOnly && m_poDS->m_nMajorVersion < 5 )
+    {
+        osRet += "\"size\": 0, ";
+    }
+    if( m_poSpatialFilter && m_poJSONFilter)
+    {
+        osRet += CPLSPrintf(
+            "\"query\": { \"constant_score\" : { \"filter\": "
+            "{ \"bool\" : { \"must\" : [%s, %s] } } } }",
+            json_object_to_json_string( m_poSpatialFilter ),
+            json_object_to_json_string( m_poJSONFilter ));
+    }
+    else
+    {
+        osRet += CPLSPrintf(
+            "\"query\": { \"constant_score\" : { \"filter\": %s } }",
+            json_object_to_json_string( m_poSpatialFilter ?
+                            m_poSpatialFilter : m_poJSONFilter ));
+    }
+    if( !bCountOnly && !m_aoSortColumns.empty() )
+    {
+        json_object* poSort = BuildSort();
+        osRet += CPLSPrintf(", \"sort\" : %s",
+                            json_object_to_json_string(poSort));
+        json_object_put(poSort);
+    }
+    osRet += " }";
+    return osRet;
+}
+
+/************************************************************************/
 /*                         GetNextRawFeature()                          */
 /************************************************************************/
 
@@ -851,22 +1010,31 @@ OGRFeature *OGRElasticLayer::GetNextRawFeature()
     m_iCurFeatureInPage = 0;
 
     CPLString osRequest, osPostData;
-    if( m_osScrollID.size() == 0 )
+    if( m_osScrollID.empty() )
     {
-        if( m_osESSearch.size() )
+        if( !m_osESSearch.empty() )
         {
-           osRequest = CPLSPrintf("%s/_search?scroll=1m&size=%d",
+            osRequest = CPLSPrintf("%s/_search?scroll=1m&size=%d",
                            m_poDS->GetURL(), m_poDS->m_nBatchSize);
             osPostData = m_osESSearch;
         }
-        else if( m_poSpatialFilter && m_osJSONFilter.size() == 0 )
+        else if( (m_poSpatialFilter && m_osJSONFilter.empty()) || m_poJSONFilter )
         {
-            CPLString osFilter = CPLSPrintf("{ \"query\": { \"filtered\" : { \"query\" : { \"match_all\" : {} }, \"filter\": %s } } }",
-                                            json_object_to_json_string( m_poSpatialFilter ));
+            osPostData = BuildQuery(false);
             osRequest = CPLSPrintf("%s/%s/%s/_search?scroll=1m&size=%d",
-                           m_poDS->GetURL(), m_osIndexName.c_str(),
-                           m_osMappingName.c_str(), m_poDS->m_nBatchSize);
-            osPostData = osFilter;
+                        m_poDS->GetURL(), m_osIndexName.c_str(),
+                        m_osMappingName.c_str(), m_poDS->m_nBatchSize);
+        }
+        else if( !m_aoSortColumns.empty() && m_osJSONFilter.empty() )
+        {
+            osRequest = CPLSPrintf("%s/%s/%s/_search?scroll=1m&size=%d",
+                        m_poDS->GetURL(), m_osIndexName.c_str(),
+                        m_osMappingName.c_str(), m_poDS->m_nBatchSize);
+            json_object* poSort = BuildSort();
+            osPostData = CPLSPrintf(
+                "{ \"sort\": %s }",
+                json_object_to_json_string(poSort));
+            json_object_put(poSort);
         }
         else
         {
@@ -880,8 +1048,8 @@ OGRFeature *OGRElasticLayer::GetNextRawFeature()
     else
     {
         osRequest =
-            CPLSPrintf("%s/_search/scroll?scroll=1m&size=%d&scroll_id=%s",
-                       m_poDS->GetURL(), m_poDS->m_nBatchSize, m_osScrollID.c_str());
+            CPLSPrintf("%s/_search/scroll?scroll=1m&scroll_id=%s",
+                       m_poDS->GetURL(), m_osScrollID.c_str());
     }
 
     if( m_bAddPretty )
@@ -889,10 +1057,10 @@ OGRFeature *OGRElasticLayer::GetNextRawFeature()
     poResponse = m_poDS->RunRequest(osRequest, osPostData);
     if( poResponse == NULL )
     {
-        m_bEOF = TRUE;
+        m_bEOF = true;
         return NULL;
     }
-    json_object* poScrollID = json_object_object_get(poResponse, "_scroll_id");
+    json_object* poScrollID = CPL_json_object_object_get(poResponse, "_scroll_id");
     if( poScrollID )
     {
         const char* pszScrollID = json_object_get_string(poScrollID);
@@ -900,17 +1068,17 @@ OGRFeature *OGRElasticLayer::GetNextRawFeature()
             m_osScrollID = pszScrollID;
     }
 
-    json_object* poHits = json_object_object_get(poResponse, "hits");
+    json_object* poHits = CPL_json_object_object_get(poResponse, "hits");
     if( poHits == NULL || json_object_get_type(poHits) != json_type_object )
     {
-        m_bEOF = TRUE;
+        m_bEOF = true;
         json_object_put(poResponse);
         return NULL;
     }
-    poHits = json_object_object_get(poHits, "hits");
+    poHits = CPL_json_object_object_get(poHits, "hits");
     if( poHits == NULL || json_object_get_type(poHits) != json_type_array )
     {
-        m_bEOF = TRUE;
+        m_bEOF = true;
         json_object_put(poResponse);
         return NULL;
     }
@@ -918,7 +1086,7 @@ OGRFeature *OGRElasticLayer::GetNextRawFeature()
     if( nHits == 0 )
     {
         m_osScrollID = "";
-        m_bEOF = TRUE;
+        m_bEOF = true;
         json_object_put(poResponse);
         return NULL;
     }
@@ -929,14 +1097,14 @@ OGRFeature *OGRElasticLayer::GetNextRawFeature()
         {
             continue;
         }
-        json_object* poSource = json_object_object_get(poHit, "_source");
+        json_object* poSource = CPL_json_object_object_get(poHit, "_source");
         if( poSource == NULL || json_object_get_type(poSource) != json_type_object )
         {
             continue;
         }
 
         const char* pszId = NULL;
-        json_object* poId = json_object_object_get(poHit, "_id");
+        json_object* poId = CPL_json_object_object_get(poHit, "_id");
         if( poId != NULL && json_object_get_type(poId) == json_type_string )
             pszId = json_object_get_string(poId);
 
@@ -944,13 +1112,13 @@ OGRFeature *OGRElasticLayer::GetNextRawFeature()
         if( pszId )
             poFeature->SetField("_id", pszId);
 
-        if( m_osESSearch.size() )
+        if( !m_osESSearch.empty() )
         {
-            json_object* poIndex = json_object_object_get(poHit, "_index");
+            json_object* poIndex = CPL_json_object_object_get(poHit, "_index");
             if( poIndex != NULL && json_object_get_type(poIndex) == json_type_string )
                 poFeature->SetField("_index", json_object_get_string(poIndex));
 
-            json_object* poType = json_object_object_get(poHit, "_type");
+            json_object* poType = CPL_json_object_object_get(poHit, "_type");
             if( poType != NULL && json_object_get_type(poType) == json_type_string )
                 poFeature->SetField("_type", json_object_get_string(poType));
         }
@@ -965,7 +1133,7 @@ OGRFeature *OGRElasticLayer::GetNextRawFeature()
     }
 
     json_object_put(poResponse);
-    if( m_apoCachedFeatures.size() )
+    if( !m_apoCachedFeatures.empty() )
     {
         OGRFeature* poRet = m_apoCachedFeatures[ 0 ];
         m_apoCachedFeatures[ 0 ] = NULL;
@@ -984,15 +1152,24 @@ OGRFeature *OGRElasticLayer::GetNextRawFeature()
 
 static const char BASE32[] = "0123456789bcdefghjkmnpqrstuvwxyz";
 
-static void decode_geohash_bbox(const char *geohash, double lat[2], double lon[2])
+static void decode_geohash_bbox( const char *geohash, double lat[2],
+                                 double lon[2] )
 {
-    int i, j, hashlen;
-    char c, cd, mask, is_even=1;
+    int i;
+    int j;
+    int hashlen;
+    char c;
+    char cd;
+    char mask;
+    char is_even = 1;
     static const char bits[] = {16,8,4,2,1};
-    lat[0] = -90.0; lat[1] = 90.0;
-    lon[0] = -180.0; lon[1] = 180.0;
+    lat[0] = -90.0;
+    lat[1] = 90.0;
+    lon[0] = -180.0;
+    lon[1] = 180.0;
     hashlen = static_cast<int>(strlen(geohash));
-    for (i=0; i<hashlen; i++) {
+    for( i = 0; i<hashlen; i++ )
+    {
         c = static_cast<char>(tolower(geohash[i]));
         cd = static_cast<char>(strchr(BASE32, c)-BASE32);
         for (j=0; j<5; j++) {
@@ -1021,8 +1198,8 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
     CPLString osCurPath;
     json_object_object_foreachC( poSource, it )
     {
-        if( osPath.size() == 0 &&
-            m_osFID.size() && EQUAL(m_osFID, it.key) )
+        if( osPath.empty() &&
+            !m_osFID.empty() && EQUAL(m_osFID, it.key) )
         {
             json_type eJSONType = json_object_get_type(it.val);
             if( eJSONType == json_type_int )
@@ -1032,7 +1209,7 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
             }
         }
 
-        if( osPath.size() )
+        if( !osPath.empty() )
             osCurPath = osPath + "." + it.key;
         else
             osCurPath = it.key;
@@ -1041,6 +1218,9 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
         {
             switch( json_object_get_type(it.val) )
             {
+                case json_type_null:
+                    poFeature->SetFieldNull( oIter->second );
+                    break;
                 case json_type_boolean:
                     poFeature->SetField( oIter->second, json_object_get_boolean(it.val));
                     break;
@@ -1138,8 +1318,8 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
                 }
                 else if( eJSONType == json_type_object )
                 {
-                    json_object* poX = json_object_object_get(it.val, "lon");
-                    json_object* poY = json_object_object_get(it.val, "lat");
+                    json_object* poX = CPL_json_object_object_get(it.val, "lon");
+                    json_object* poY = CPL_json_object_object_get(it.val, "lat");
                     if( poX != NULL && poY != NULL )
                     {
                         poGeom = new OGRPoint( json_object_get_double(poX),
@@ -1157,7 +1337,8 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
                     }
                     else
                     {
-                        double lat[2], lon[2];
+                        double lat[2] = { 0.0, 0.0 };
+                        double lon[2] = { 0.0, 0.0 };
                         decode_geohash_bbox(pszLatLon, lat, lon);
                         poGeom = new OGRPoint( (lon[0] + lon[1]) / 2,
                                                (lat[0] + lat[1]) / 2 );
@@ -1168,9 +1349,9 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
             }
             else if( json_object_get_type(it.val) == json_type_object )
             {
-                json_object* poType = json_object_object_get(it.val, "type");
-                json_object* poRadius = json_object_object_get(it.val, "radius");
-                json_object* poCoordinates = json_object_object_get(it.val, "coordinates");
+                json_object* poType = CPL_json_object_object_get(it.val, "type");
+                json_object* poRadius = CPL_json_object_object_get(it.val, "radius");
+                json_object* poCoordinates = CPL_json_object_object_get(it.val, "coordinates");
                 if( poType && poRadius && poCoordinates &&
                     json_object_get_type(poType) == json_type_string &&
                     EQUAL( json_object_get_string(poType), "circle" ) &&
@@ -1181,9 +1362,9 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
                     json_object_array_length(poCoordinates) == 2 )
                 {
                     const char* pszRadius = json_object_get_string(poRadius);
-                    double dfX = json_object_get_double(json_object_array_get_idx(poCoordinates, 0));
-                    double dfY = json_object_get_double(json_object_array_get_idx(poCoordinates, 1));
-                    int nRadiusLength = (int)strlen(pszRadius);
+                    const double dfX = json_object_get_double(json_object_array_get_idx(poCoordinates, 0));
+                    const double dfY = json_object_get_double(json_object_array_get_idx(poCoordinates, 1));
+                    const int nRadiusLength = (int)strlen(pszRadius);
                     double dfRadius = CPLAtof(pszRadius);
                     double dfUnit = 0.0;
                     if( nRadiusLength >= 1 && pszRadius[nRadiusLength-1] == 'm' )
@@ -1210,8 +1391,10 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
                         OGRLinearRing* poRing = new OGRLinearRing();
                         for(double dfStep = 0; dfStep <= 360; dfStep += 4 )
                         {
-                            double dfLat, dfLon;
-                            OGRXPlane_ExtendPosition( dfY, dfX, dfRadius, dfStep, &dfLat, &dfLon);
+                            double dfLat = 0.0;
+                            double dfLon = 0.0;
+                            OGRXPlane_ExtendPosition(dfY, dfX, dfRadius,
+                                                      dfStep, &dfLat, &dfLon);
                             poRing->addPoint(dfLon, dfLat);
                         }
                         OGRPolygon* poPoly = new OGRPolygon();
@@ -1233,10 +1416,10 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
                         json_object_get_type(poCorner2) == json_type_array &&
                         json_object_array_length(poCorner2) == 2 )
                     {
-                        double dfX1 = json_object_get_double(json_object_array_get_idx(poCorner1, 0));
-                        double dfY1 = json_object_get_double(json_object_array_get_idx(poCorner1, 1));
-                        double dfX2 = json_object_get_double(json_object_array_get_idx(poCorner2, 0));
-                        double dfY2 = json_object_get_double(json_object_array_get_idx(poCorner2, 1));
+                        const double dfX1 = json_object_get_double(json_object_array_get_idx(poCorner1, 0));
+                        const double dfY1 = json_object_get_double(json_object_array_get_idx(poCorner1, 1));
+                        const double dfX2 = json_object_get_double(json_object_array_get_idx(poCorner2, 0));
+                        const double dfY2 = json_object_get_double(json_object_array_get_idx(poCorner2, 1));
                         OGRLinearRing* poRing = new OGRLinearRing();
                         poRing->addPoint(dfX1, dfY1);
                         poRing->addPoint(dfX2, dfY1);
@@ -1262,14 +1445,15 @@ void OGRElasticLayer::BuildFeature(OGRFeature* poFeature, json_object* poSource,
         }
         else if( json_object_get_type(it.val) == json_type_object &&
                  (m_poDS->m_bFlattenNestedAttributes ||
-                  (osPath.size() == 0 && m_osMappingName == "FeatureCollection" && strcmp(it.key, "properties") == 0)) )
+                  (osPath.empty() && m_osMappingName == "FeatureCollection" && strcmp(it.key, "properties") == 0)) )
         {
             BuildFeature(poFeature, it.val, osCurPath);
         }
         else if( json_object_get_type(it.val) == json_type_object &&
                  !m_poDS->m_bFlattenNestedAttributes )
         {
-            if( ( oIter = m_aosMapToGeomFieldIndex.find(osCurPath + ".coordinates") ) != m_aosMapToGeomFieldIndex.end() )
+            if( m_aosMapToGeomFieldIndex.find(osCurPath + ".coordinates")
+                                            != m_aosMapToGeomFieldIndex.end() )
             {
                 BuildFeature(poFeature, it.val, osCurPath);
             }
@@ -1330,7 +1514,6 @@ static json_object* GetContainerForMapping( json_object* poContainer,
     return poContainer;
 }
 
-
 /************************************************************************/
 /*                             BuildMap()                               */
 /************************************************************************/
@@ -1363,7 +1546,7 @@ CPLString OGRElasticLayer::BuildMap() {
         json_object* poContainer = GetContainerForMapping(poMappingProperties,
                                                           m_aaosFieldPaths[i],
                                                           oMap);
-        const char* pszLastComponent = m_aaosFieldPaths[i][(int)m_aaosFieldPaths[i].size()-1];
+        const char* pszLastComponent = m_aaosFieldPaths[i].back();
 
         const char* pszType = "string";
         const char* pszFormat = NULL;
@@ -1403,37 +1586,80 @@ CPLString OGRElasticLayer::BuildMap() {
                 break;
         }
 
+        bool bAnalyzed = EQUAL(pszType, "string");
         json_object* poPropertyMap = json_object_new_object();
+        if( m_poDS->m_nMajorVersion >= 5 && EQUAL(pszType, "string") )
+        {
+            if( CSLFindString(m_papszNotAnalyzedFields,
+                              poFieldDefn->GetNameRef()) >= 0 ||
+                (CSLCount(m_papszNotAnalyzedFields) == 1 &&
+                 EQUAL(m_papszNotAnalyzedFields[0], "{ALL}")) )
+            {
+                bAnalyzed = false;
+                pszType = "keyword";
+            }
+            else
+                pszType = "text";
+        }
         json_object_object_add(poPropertyMap, "type", json_object_new_string(pszType));
         if( pszFormat )
             json_object_object_add(poPropertyMap, "format", json_object_new_string(pszFormat));
         if( m_bStoreFields || CSLFindString(m_papszStoredFields, poFieldDefn->GetNameRef()) >= 0 )
             json_object_object_add(poPropertyMap, "store", json_object_new_string("yes"));
-        if( CSLFindString(m_papszNotAnalyzedFields, poFieldDefn->GetNameRef()) >= 0 )
+        if( m_poDS->m_nMajorVersion < 5 &&
+            (CSLFindString(m_papszNotAnalyzedFields,
+                          poFieldDefn->GetNameRef()) >= 0  ||
+                (CSLCount(m_papszNotAnalyzedFields) == 1 &&
+                 EQUAL(m_papszNotAnalyzedFields[0], "{ALL}"))) )
+        {
+            bAnalyzed = false;
             json_object_object_add(poPropertyMap, "index", json_object_new_string("not_analyzed"));
+        }
         else if( CSLFindString(m_papszNotIndexedFields, poFieldDefn->GetNameRef()) >= 0 )
             json_object_object_add(poPropertyMap, "index", json_object_new_string("no"));
 
-        json_object_object_add(poContainer, pszLastComponent, poPropertyMap);
+        if( bAnalyzed && (CSLFindString(m_papszFieldsWithRawValue,
+                          poFieldDefn->GetNameRef()) >= 0  ||
+                (CSLCount(m_papszFieldsWithRawValue) == 1 &&
+                 EQUAL(m_papszFieldsWithRawValue[0], "{ALL}"))) )
+        {
+            json_object* poFields = json_object_new_object();
+            json_object* poRaw = json_object_new_object();
+            json_object_object_add(poFields, "raw", poRaw);
+            if( m_poDS->m_nMajorVersion >= 5 )
+            {
+                json_object_object_add(poRaw, "type",
+                                       json_object_new_string("keyword"));
+            }
+            else
+            {
+                json_object_object_add(poRaw, "type",
+                                       json_object_new_string("string"));
+                json_object_object_add(poRaw, "index",
+                                       json_object_new_string("not_analyzed"));
+            }
+            json_object_object_add(poPropertyMap, "fields", poFields);
+        }
 
+        json_object_object_add(poContainer, pszLastComponent, poPropertyMap);
     }
 
     for(int i=0;i<m_poFeatureDefn->GetGeomFieldCount();i++)
     {
         std::vector<CPLString> aosPath = m_aaosGeomFieldPaths[i];
-        int bAddGeoJSONType = FALSE;
+        bool bAddGeoJSONType = false;
         if( m_abIsGeoPoint[i] &&
             aosPath.size() >= 2 &&
-            aosPath[(int)aosPath.size()-1] == "coordinates" )
+            aosPath.back() == "coordinates" )
         {
-            bAddGeoJSONType = TRUE;
+            bAddGeoJSONType = true;
             aosPath.resize( (int)aosPath.size() - 1 );
         }
 
         json_object* poContainer = GetContainerForMapping(poMappingProperties,
                                                         aosPath,
                                                         oMap);
-        const char* pszLastComponent = aosPath[(int)aosPath.size()-1];
+        const char* pszLastComponent = aosPath.back();
 
         if( m_abIsGeoPoint[i] )
         {
@@ -1448,7 +1674,7 @@ CPLString OGRElasticLayer::BuildMap() {
             {
                 json_object_object_add(poContainer, pszLastComponent, geo_point);
             }
-            if( m_osPrecision.size() )
+            if( !m_osPrecision.empty() )
             {
                 json_object* field_data = json_object_new_object();
                 json_object_object_add(geo_point, "fielddata", field_data);
@@ -1463,7 +1689,7 @@ CPLString OGRElasticLayer::BuildMap() {
                                 pszLastComponent,
                                 geometry);
             json_object_object_add(geometry, "type", json_object_new_string("geo_shape"));
-            if( m_osPrecision.size() )
+            if( !m_osPrecision.empty() )
                 json_object_object_add(geometry, "precision", json_object_new_string(m_osPrecision.c_str()));
         }
     }
@@ -1471,7 +1697,7 @@ CPLString OGRElasticLayer::BuildMap() {
     json_object* poMeta = NULL;
     json_object* poGeomFields = NULL;
     json_object* poFields = NULL;
-    if( m_osFID.size() )
+    if( !m_osFID.empty() )
     {
         poMeta = json_object_new_object();
         json_object_object_add(poMeta, "fid",
@@ -1690,7 +1916,6 @@ static void BuildGeoJSONGeometry(json_object* geometry, OGRGeometry* poGeom)
         default:
             break;
     }
-
 }
 
 /************************************************************************/
@@ -1704,9 +1929,10 @@ OGRErr OGRElasticLayer::WriteMapIfNecessary()
 
     // Check to see if the user has elected to only write out the mapping file
     // This method will only write out one layer from the vector file in cases where there are multiple layers
-    if (m_osWriteMapFilename.size()) {
-        if (m_bSerializeMapping) {
-            m_bSerializeMapping = FALSE;
+    if (!m_osWriteMapFilename.empty() ) {
+        if( m_bSerializeMapping )
+        {
+            m_bSerializeMapping = false;
             CPLString map = BuildMap();
 
             // Write the map to a file
@@ -1720,8 +1946,9 @@ OGRErr OGRElasticLayer::WriteMapIfNecessary()
     }
 
     // Check to see if we have any fields to upload to this index
-    if (m_osWriteMapFilename.size() == 0 && m_bSerializeMapping ) {
-        m_bSerializeMapping = FALSE;
+    if( m_osWriteMapFilename.empty() && m_bSerializeMapping )
+    {
+        m_bSerializeMapping = false;
         if( !m_poDS->UploadFile(CPLSPrintf("%s/%s/%s/_mapping", m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()), BuildMap()) )
         {
             return OGRERR_FAILURE;
@@ -1759,7 +1986,6 @@ static json_object* GetContainerForFeature( json_object* poContainer,
     return poContainer;
 }
 
-
 /************************************************************************/
 /*                        BuildJSonFromFeature()                        */
 /************************************************************************/
@@ -1769,7 +1995,7 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
 
     CPLString fields;
     int nJSonFieldIndex = m_poFeatureDefn->GetFieldIndex("_json");
-    if( nJSonFieldIndex >= 0 && poFeature->IsFieldSet(nJSonFieldIndex) )
+    if( nJSonFieldIndex >= 0 && poFeature->IsFieldSetAndNotNull(nJSonFieldIndex) )
     {
         fields = poFeature->GetFieldAsString(nJSonFieldIndex);
     }
@@ -1777,7 +2003,7 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
     {
         json_object *fieldObject = json_object_new_object();
 
-        if( poFeature->GetFID() >= 0 && m_osFID.size() )
+        if( poFeature->GetFID() >= 0 && !m_osFID.empty() )
         {
             json_object_object_add(fieldObject,
                                    m_osFID.c_str(),
@@ -1799,10 +2025,10 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
                 else if( env.MinX < -180 || env.MinY < -90 ||
                          env.MaxX > 180 || env.MaxY > 90 )
                 {
-                    static int bHasWarned = FALSE;
+                    static bool bHasWarned = false;
                     if( !bHasWarned )
                     {
-                        bHasWarned = TRUE;
+                        bHasWarned = true;
                         CPLError(CE_Warning, CPLE_AppDefined,
                                  "At least one geometry has a bounding box outside "
                                  "of [-180,180] longitude range and/or [-90,90] latitude range. Undefined behaviour");
@@ -1810,17 +2036,17 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
                 }
 
                 std::vector<CPLString> aosPath = m_aaosGeomFieldPaths[i];
-                int bAddGeoJSONType = FALSE;
+                bool bAddGeoJSONType = false;
                 if( m_abIsGeoPoint[i] &&
                     aosPath.size() >= 2 &&
-                    aosPath[(int)aosPath.size()-1] == "coordinates" )
+                    aosPath.back() == "coordinates" )
                 {
-                    bAddGeoJSONType = TRUE;
+                    bAddGeoJSONType = true;
                     aosPath.resize( (int)aosPath.size() - 1 );
                 }
 
                 json_object* poContainer = GetContainerForFeature(fieldObject, aosPath, oMap);
-                const char* pszLastComponent = aosPath[(int)aosPath.size()-1];
+                const char* pszLastComponent = aosPath.back();
 
                 if( m_abIsGeoPoint[i] )
                 {
@@ -1873,7 +2099,14 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
             }
 
             json_object* poContainer = GetContainerForFeature(fieldObject, m_aaosFieldPaths[i], oMap);
-            const char* pszLastComponent = m_aaosFieldPaths[i][(int)m_aaosFieldPaths[i].size()-1];
+            const char* pszLastComponent = m_aaosFieldPaths[i].back();
+
+            if( poFeature->IsFieldNull(i) )
+            {
+                json_object_object_add(poContainer,
+                                       pszLastComponent, NULL);
+                continue;
+            }
 
             switch (m_poFeatureDefn->GetFieldDefn(i)->GetType()) {
                 case OFTInteger:
@@ -1898,10 +2131,10 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
                     break;
                 case OFTIntegerList:
                 {
-                    int nCount;
+                    int nCount = 0;
                     const int* panValues = poFeature->GetFieldAsIntegerList(i, &nCount);
                     json_object* poArray = json_object_new_array();
-                    for(int j=0;j<nCount;j++)
+                    for( int j = 0; j < nCount; j++ )
                         json_object_array_add(poArray, json_object_new_int(panValues[j]));
                     json_object_object_add(poContainer,
                             pszLastComponent, poArray);
@@ -1909,7 +2142,7 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
                 }
                 case OFTInteger64List:
                 {
-                    int nCount;
+                    int nCount = 0;
                     const GIntBig* panValues = poFeature->GetFieldAsInteger64List(i, &nCount);
                     json_object* poArray = json_object_new_array();
                     for(int j=0;j<nCount;j++)
@@ -1920,7 +2153,7 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
                 }
                 case OFTRealList:
                 {
-                    int nCount;
+                    int nCount = 0;
                     const double* padfValues = poFeature->GetFieldAsDoubleList(i, &nCount);
                     json_object* poArray = json_object_new_array();
                     for(int j=0;j<nCount;j++)
@@ -1941,7 +2174,7 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
                 }
                 case OFTBinary:
                 {
-                    int nCount;
+                    int nCount = 0;
                     GByte* pabyVal = poFeature->GetFieldAsBinary(i, &nCount);
                     char* pszVal = CPLBase64Encode(nCount, pabyVal);
                     json_object_object_add(poContainer,
@@ -1952,8 +2185,13 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
                 }
                 case OFTDateTime:
                 {
-                    int nYear, nMonth, nDay, nHour, nMin, nTZ;
-                    float fSec;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMin = 0;
+                    int nTZ = 0;
+                    float fSec = 0.0f;
                     poFeature->GetFieldAsDateTime(i, &nYear, &nMonth, &nDay,
                                                   &nHour, &nMin, &fSec, &nTZ);
                     if( nTZ == 0 )
@@ -1966,9 +2204,9 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
                     }
                     else
                     {
-                        int TZOffset = ABS(nTZ - 100) * 15;
-                        int TZHour = TZOffset / 60;
-                        int TZMinute = TZOffset - TZHour * 60;
+                        const int TZOffset = std::abs(nTZ - 100) * 15;
+                        const int TZHour = TZOffset / 60;
+                        const int TZMinute = TZOffset - TZHour * 60;
                         json_object_object_add(poContainer,
                                 pszLastComponent,
                                 json_object_new_string(
@@ -2002,12 +2240,18 @@ CPLString OGRElasticLayer::BuildJSonFromFeature(OGRFeature *poFeature)
 
 OGRErr OGRElasticLayer::ICreateFeature(OGRFeature *poFeature)
 {
+    if( m_poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
     FinalizeFeatureDefn();
 
     if( WriteMapIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
 
-    if (m_osWriteMapFilename.size())
+    if (!m_osWriteMapFilename.empty() )
         return OGRERR_NONE;
 
     if( poFeature->GetFID() < 0 )
@@ -2020,7 +2264,7 @@ OGRErr OGRElasticLayer::ICreateFeature(OGRFeature *poFeature)
     CPLString osFields(BuildJSonFromFeature(poFeature));
 
     const char* pszId = NULL;
-    if( poFeature->IsFieldSet(0) && !m_bIgnoreSourceID )
+    if( poFeature->IsFieldSetAndNotNull(0) && !m_bIgnoreSourceID )
         pszId = poFeature->GetFieldAsString(0);
 
     // Check to see if we're using bulk uploading
@@ -2037,8 +2281,10 @@ OGRErr OGRElasticLayer::ICreateFeature(OGRFeature *poFeature)
                 return OGRERR_FAILURE;
             }
         }
-
-    } else { // Fall back to using single item upload for every feature
+    }
+    else
+    {
+        // Fall back to using single item upload for every feature.
         CPLString osURL(CPLSPrintf("%s/%s/%s/", m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()));
         if( pszId )
             osURL += pszId;
@@ -2049,13 +2295,12 @@ OGRErr OGRElasticLayer::ICreateFeature(OGRFeature *poFeature)
         }
         if( pszId == NULL )
         {
-            json_object* poId = json_object_object_get(poRes, "_id");
+            json_object* poId = CPL_json_object_object_get(poRes, "_id");
             if( poId != NULL && json_object_get_type(poId) == json_type_string )
             {
                 pszId = json_object_get_string(poId);
                 poFeature->SetField(0, pszId);
             }
-
         }
         json_object_put(poRes);
     }
@@ -2069,14 +2314,20 @@ OGRErr OGRElasticLayer::ICreateFeature(OGRFeature *poFeature)
 
 OGRErr OGRElasticLayer::ISetFeature(OGRFeature *poFeature)
 {
+    if( m_poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
     FinalizeFeatureDefn();
 
-    if( !poFeature->IsFieldSet(0) )
+    if( !poFeature->IsFieldSetAndNotNull(0) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "_id field not set");
         return OGRERR_FAILURE;
     }
-    if( poFeature->GetFID() < 0 && m_osFID.size() )
+    if( poFeature->GetFID() < 0 && !m_osFID.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid FID");
         return OGRERR_FAILURE;
@@ -2107,12 +2358,16 @@ OGRErr OGRElasticLayer::ISetFeature(OGRFeature *poFeature)
 /*                             PushIndex()                              */
 /************************************************************************/
 
-int OGRElasticLayer::PushIndex() {
-    if (m_osBulkContent.empty()) {
-        return TRUE;
+bool OGRElasticLayer::PushIndex()
+{
+    if( m_osBulkContent.empty() )
+    {
+        return true;
     }
 
-    int bRet = m_poDS->UploadFile(CPLSPrintf("%s/_bulk", m_poDS->GetURL()), m_osBulkContent);
+    const bool bRet =
+      m_poDS->UploadFile(CPLSPrintf("%s/_bulk", m_poDS->GetURL()),
+                         m_osBulkContent);
     m_osBulkContent.clear();
 
     return bRet;
@@ -2123,8 +2378,14 @@ int OGRElasticLayer::PushIndex() {
 /************************************************************************/
 
 OGRErr OGRElasticLayer::CreateField(OGRFieldDefn *poFieldDefn,
-                                    CPL_UNUSED int bApproxOK)
+                                    int /*bApproxOK*/)
 {
+    if( m_poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
     FinalizeFeatureDefn();
     ResetReading();
 
@@ -2159,7 +2420,7 @@ OGRErr OGRElasticLayer::CreateField(OGRFieldDefn *poFieldDefn,
                   aosPath,
                   poFieldDefn->GetSubType() );
 
-    m_bSerializeMapping = TRUE;
+    m_bSerializeMapping = true;
 
     return OGRERR_NONE;
 }
@@ -2168,9 +2429,16 @@ OGRErr OGRElasticLayer::CreateField(OGRFieldDefn *poFieldDefn,
 /*                           CreateGeomField()                          */
 /************************************************************************/
 
-OGRErr OGRElasticLayer::CreateGeomField( OGRGeomFieldDefn *poFieldIn, CPL_UNUSED int bApproxOK )
+OGRErr OGRElasticLayer::CreateGeomField( OGRGeomFieldDefn *poFieldIn,
+                                         int /*bApproxOK*/ )
 
 {
+    if( m_poDS->GetAccess() != GA_Update )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Dataset opened in read-only mode");
+        return OGRERR_FAILURE;
+    }
+
     FinalizeFeatureDefn();
     ResetReading();
 
@@ -2250,7 +2518,7 @@ OGRErr OGRElasticLayer::CreateGeomField( OGRGeomFieldDefn *poFieldIn, CPL_UNUSED
 
     m_apoCT.push_back(poCT);
 
-    m_bSerializeMapping = TRUE;
+    m_bSerializeMapping = true;
 
     return OGRERR_NONE;
 }
@@ -2267,12 +2535,11 @@ int OGRElasticLayer::TestCapability(const char * pszCap) {
         return TRUE;
 
     else if (EQUAL(pszCap, OLCSequentialWrite) ||
-             EQUAL(pszCap, OLCRandomWrite)
-    )
-        return TRUE;
+             EQUAL(pszCap, OLCRandomWrite) )
+        return m_poDS->GetAccess() == GA_Update;
     else if (EQUAL(pszCap, OLCCreateField) ||
              EQUAL(pszCap, OLCCreateGeomField) )
-        return TRUE;
+        return m_poDS->GetAccess() == GA_Update;
     else
         return FALSE;
 }
@@ -2281,36 +2548,57 @@ int OGRElasticLayer::TestCapability(const char * pszCap) {
 /*                          GetFeatureCount()                           */
 /************************************************************************/
 
-GIntBig OGRElasticLayer::GetFeatureCount(int bForce)
+GIntBig OGRElasticLayer::GetFeatureCount( int bForce )
 {
-    if( m_poAttrQuery != NULL )
+    if( m_bFilterMustBeClientSideEvaluated )
         return OGRLayer::GetFeatureCount(bForce);
 
-    json_object* poResponse;
-    if( m_osESSearch.size() )
+    json_object* poResponse = NULL;
+    if( !m_osESSearch.empty() )
     {
+        if( m_osESSearch[0] != '{' )
+            return OGRLayer::GetFeatureCount(bForce);
         poResponse = m_poDS->RunRequest(
-            CPLSPrintf("%s/_search?search_type=count&pretty", m_poDS->GetURL()),
-            m_osESSearch.c_str());
+            CPLSPrintf("%s/_search?pretty", m_poDS->GetURL()),
+            ("{ \"size\": 0, " + m_osESSearch.substr(1)).c_str());
     }
-    else if( m_poSpatialFilter )
+    else if( (m_poSpatialFilter && m_osJSONFilter.empty()) || m_poJSONFilter )
+    {
+        CPLString osFilter = BuildQuery(true);
+        if( m_poDS->m_nMajorVersion >= 5 )
+        {
+            poResponse = m_poDS->RunRequest(
+                CPLSPrintf("%s/%s/%s/_count?pretty", m_poDS->GetURL(),
+                           m_osIndexName.c_str(), m_osMappingName.c_str()),
+                osFilter.c_str());
+        }
+        else
+        {
+            poResponse = m_poDS->RunRequest(
+                CPLSPrintf("%s/%s/%s/_search?pretty", m_poDS->GetURL(),
+                           m_osIndexName.c_str(), m_osMappingName.c_str()),
+                osFilter.c_str());
+        }
+    }
+    else if( !m_osJSONFilter.empty() )
     {
-        CPLString osFilter = CPLSPrintf("{ \"query\": { \"filtered\" : { \"query\" : { \"match_all\" : {} }, \"filter\": %s } } }",
-                                        json_object_to_json_string( m_poSpatialFilter ));
         poResponse = m_poDS->RunRequest(
-            CPLSPrintf("%s/%s/%s/_search?search_type=count&pretty", m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()),
-            osFilter.c_str());
+            CPLSPrintf("%s/%s/%s/_search?&pretty", m_poDS->GetURL(),
+                       m_osIndexName.c_str(), m_osMappingName.c_str()),
+            ("{ \"size\": 0, " + m_osJSONFilter.substr(1)).c_str());
     }
     else
     {
         poResponse = m_poDS->RunRequest(
-            CPLSPrintf("%s/%s/%s/_search?search_type=count&pretty", m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()),
-            m_osJSONFilter.c_str());
+            CPLSPrintf("%s/%s/%s/_count?pretty", m_poDS->GetURL(),
+                       m_osIndexName.c_str(), m_osMappingName.c_str()));
     }
 
     json_object* poCount = json_ex_get_object_by_path(poResponse, "hits.count");
     if( poCount == NULL )
         poCount = json_ex_get_object_by_path(poResponse, "hits.total");
+    if( poCount == NULL )
+        poCount = json_ex_get_object_by_path(poResponse, "count");
     if( poCount == NULL || json_object_get_type(poCount) != json_type_int )
     {
         json_object_put(poResponse);
@@ -2323,17 +2611,542 @@ GIntBig OGRElasticLayer::GetFeatureCount(int bForce)
 }
 
 /************************************************************************/
+/*                            GetValue()                                */
+/************************************************************************/
+
+json_object* OGRElasticLayer::GetValue( int nFieldIdx,
+                                        swq_expr_node* poValNode )
+{
+    json_object* poVal = NULL;
+    if (poValNode->field_type == SWQ_FLOAT)
+        poVal = json_object_new_double(poValNode->float_value);
+    else if (poValNode->field_type == SWQ_INTEGER ||
+             poValNode->field_type == SWQ_INTEGER64)
+        poVal = json_object_new_int64(poValNode->int_value);
+    else if (poValNode->field_type == SWQ_STRING)
+        poVal = json_object_new_string(poValNode->string_value);
+    else if (poValNode->field_type == SWQ_TIMESTAMP)
+    {
+        int nYear = 0;
+        int nMonth = 0;
+        int nDay = 0;
+        int nHour = 0;
+        int nMinute = 0;
+        float fSecond = 0;
+        if( sscanf(poValNode->string_value,"%04d/%02d/%02d %02d:%02d:%f",
+                    &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) >= 3 ||
+            sscanf(poValNode->string_value,"%04d-%02d-%02dT%02d:%02d:%f",
+                    &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond) >= 3 )
+        {
+            OGRFieldType eType(m_poFeatureDefn->GetFieldDefn(
+                    nFieldIdx)->GetType());
+            if( eType == OFTDateTime )
+                poVal = json_object_new_string(
+                    CPLSPrintf("%04d/%02d/%02d %02d:%02d:%02.03f",
+                        nYear, nMonth, nDay, nHour, nMinute, fSecond));
+            else if( eType == OFTDate)
+                poVal = json_object_new_string(
+                    CPLSPrintf("%04d/%02d/%02d",
+                        nYear, nMonth, nDay));
+            else
+                poVal = json_object_new_string(
+                    CPLSPrintf("%02d:%02d:%02.03f",
+                        nHour, nMinute, fSecond));
+        }
+        else
+        {
+            return NULL;
+        }
+    }
+    else
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unhandled type: %d",
+                 poValNode->field_type);
+    }
+    return poVal;
+}
+
+/************************************************************************/
+/*                        TranslateSQLToFilter()                        */
+/************************************************************************/
+
+json_object* OGRElasticLayer::TranslateSQLToFilter(swq_expr_node* poNode)
+{
+    if( poNode->eNodeType == SNT_OPERATION )
+    {
+        if( poNode->nOperation == SWQ_AND && poNode->nSubExprCount == 2 )
+        {
+            // For AND, we can deal with a failure in one of the branch
+            // since client-side will do that extra filtering
+            json_object* poFilter1 = TranslateSQLToFilter(poNode->papoSubExpr[0]);
+            json_object* poFilter2 = TranslateSQLToFilter(poNode->papoSubExpr[1]);
+            if( poFilter1 && poFilter2 )
+            {
+                json_object* poRet = json_object_new_object();
+                json_object* poBool = json_object_new_object();
+                json_object_object_add(poRet, "bool", poBool);
+                json_object* poMust = json_object_new_array();
+                json_object_object_add(poBool, "must", poMust);
+                json_object_array_add(poMust, poFilter1);
+                json_object_array_add(poMust, poFilter2);
+                return poRet;
+            }
+            else if( poFilter1 )
+                return poFilter1;
+            else
+                return poFilter2;
+        }
+        else if( poNode->nOperation == SWQ_OR && poNode->nSubExprCount == 2 )
+        {
+            json_object* poFilter1 = TranslateSQLToFilter(poNode->papoSubExpr[0]);
+            json_object* poFilter2 = TranslateSQLToFilter(poNode->papoSubExpr[1]);
+            if( poFilter1 && poFilter2 )
+            {
+                json_object* poRet = json_object_new_object();
+                json_object* poBool = json_object_new_object();
+                json_object_object_add(poRet, "bool", poBool);
+                json_object* poShould = json_object_new_array();
+                json_object_object_add(poBool, "should", poShould);
+                json_object_array_add(poShould, poFilter1);
+                json_object_array_add(poShould, poFilter2);
+                return poRet;
+            }
+            else
+            {
+                json_object_put(poFilter1);
+                json_object_put(poFilter2);
+                return NULL;
+            }
+        }
+        else if( poNode->nOperation == SWQ_NOT && poNode->nSubExprCount == 1 )
+        {
+            if( poNode->papoSubExpr[0]->eNodeType == SNT_OPERATION &&
+                poNode->papoSubExpr[0]->nOperation == SWQ_ISNULL &&
+                poNode->papoSubExpr[0]->nSubExprCount == 1 &&
+                poNode->papoSubExpr[0]->papoSubExpr[0]->eNodeType ==
+                                                            SNT_COLUMN &&
+                poNode->papoSubExpr[0]->papoSubExpr[0]->field_index != 0 &&
+                poNode->papoSubExpr[0]->papoSubExpr[0]->field_index <
+                                        m_poFeatureDefn->GetFieldCount() )
+            {
+                json_object* poRet = json_object_new_object();
+                json_object* poExists = json_object_new_object();
+                CPLString osFieldName(BuildPathFromArray(
+                    m_aaosFieldPaths[
+                        poNode->papoSubExpr[0]->papoSubExpr[0]->field_index]));
+                json_object_object_add(poExists, "field",
+                                       json_object_new_string(osFieldName));
+                json_object_object_add(poRet, "exists", poExists);
+                return poRet;
+            }
+            else
+            {
+                json_object* poFilter = TranslateSQLToFilter(
+                                                    poNode->papoSubExpr[0]);
+                if( poFilter )
+                {
+                    json_object* poRet = json_object_new_object();
+                    json_object* poBool = json_object_new_object();
+                    json_object_object_add(poRet, "bool", poBool);
+                    json_object_object_add(poBool, "must_not", poFilter);
+                    return poRet;
+                }
+                else
+                {
+                    return NULL;
+                }
+            }
+        }
+        else if( poNode->nOperation == SWQ_ISNULL &&
+                 poNode->nSubExprCount == 1 &&
+                 poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+                 poNode->papoSubExpr[0]->field_index != 0 &&
+                 poNode->papoSubExpr[0]->field_index <
+                                        m_poFeatureDefn->GetFieldCount() )
+        {
+            json_object* poRet = json_object_new_object();
+            json_object* poExists = json_object_new_object();
+            CPLString osFieldName(BuildPathFromArray(
+                m_aaosFieldPaths[ poNode->papoSubExpr[0]->field_index]));
+            json_object_object_add(poExists, "field",
+                                    json_object_new_string(osFieldName));
+            json_object* poBool = json_object_new_object();
+            json_object_object_add(poRet, "bool", poBool);
+            json_object* poMustNot = json_object_new_object();
+            json_object_object_add(poMustNot, "exists", poExists);
+            json_object_object_add(poBool, "must_not", poMustNot);
+            return poRet;
+        }
+        else if( poNode->nOperation == SWQ_NE )
+        {
+            poNode->nOperation = SWQ_EQ;
+            json_object* poFilter = TranslateSQLToFilter(poNode);
+            poNode->nOperation = SWQ_NE;
+            if( poFilter )
+            {
+                json_object* poRet = json_object_new_object();
+                json_object* poBool = json_object_new_object();
+                json_object_object_add(poRet, "bool", poBool);
+                json_object_object_add(poBool, "must_not", poFilter);
+                return poRet;
+            }
+            else
+            {
+                return NULL;
+            }
+        }
+        else if( poNode->nOperation == SWQ_EQ && poNode->nSubExprCount == 2 &&
+                 poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+                 poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+                 poNode->papoSubExpr[0]->field_index <
+                                        m_poFeatureDefn->GetFieldCount() )
+        {
+            json_object* poVal = GetValue(poNode->papoSubExpr[0]->field_index,
+                                          poNode->papoSubExpr[1]);
+            if( poVal == NULL )
+            {
+                return NULL;
+            }
+            json_object* poRet = json_object_new_object();
+            if( poNode->papoSubExpr[0]->field_index == 0 )
+            {
+                json_object* poIds = json_object_new_object();
+                json_object* poValues = json_object_new_array();
+                json_object_object_add(poIds, "values", poValues);
+                json_object_array_add(poValues, poVal);
+                json_object_object_add(poRet, "ids", poIds);
+            }
+            else
+            {
+                json_object* poTerm = json_object_new_object();
+                CPLString osPath(BuildPathFromArray(
+                        m_aaosFieldPaths[ poNode->papoSubExpr[0]->field_index]));
+                bool bNotAnalyzed = true;
+                if( poNode->papoSubExpr[1]->field_type == SWQ_STRING )
+                {
+                    const char* pszFieldName =
+                        m_poFeatureDefn->GetFieldDefn(
+                            poNode->papoSubExpr[0]->field_index)->GetNameRef();
+                    bNotAnalyzed = CSLFindString(m_papszNotAnalyzedFields,
+                                                 pszFieldName) >= 0;
+                    if( !bNotAnalyzed )
+                    {
+                        if( CSLFindString(m_papszFieldsWithRawValue,
+                                          pszFieldName) >= 0 )
+                        {
+                            osPath += ".raw";
+                            bNotAnalyzed = true;
+                        }
+                        else if( !m_bFilterMustBeClientSideEvaluated )
+                        {
+                            m_bFilterMustBeClientSideEvaluated = true;
+                            CPLDebug("ES",
+                            "Part or full filter will have to be evaluated on "
+                            "client side (equality test on a analyzed "
+                            "field).");
+                        }
+                    }
+                }
+                json_object_object_add(poRet,
+                                    bNotAnalyzed ? "term" : "match", poTerm);
+                json_object_object_add(poTerm, osPath, poVal);
+
+                if( !bNotAnalyzed && m_poDS->m_nMajorVersion < 2 )
+                {
+                    json_object* poNewRet = json_object_new_object();
+                    json_object_object_add(poNewRet, "query", poRet);
+                    poRet = poNewRet;
+                }
+            }
+            return poRet;
+        }
+        else if( (poNode->nOperation == SWQ_LT ||
+                  poNode->nOperation == SWQ_LE ||
+                  poNode->nOperation == SWQ_GT ||
+                  poNode->nOperation == SWQ_GE) && poNode->nSubExprCount == 2 &&
+                  poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+                  poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+                  poNode->papoSubExpr[0]->field_index != 0 &&
+                  poNode->papoSubExpr[0]->field_index <
+                                            m_poFeatureDefn->GetFieldCount() )
+        {
+            json_object* poVal = GetValue(poNode->papoSubExpr[0]->field_index,
+                                          poNode->papoSubExpr[1]);
+            if( poVal == NULL )
+            {
+                return NULL;
+            }
+            json_object* poRet = json_object_new_object();
+            json_object* poRange = json_object_new_object();
+            json_object_object_add(poRet, "range", poRange);
+            json_object* poFieldConstraint = json_object_new_object();
+            CPLString osFieldName(BuildPathFromArray(
+                    m_aaosFieldPaths[ poNode->papoSubExpr[0]->field_index]));
+            json_object_object_add(poRange, osFieldName, poFieldConstraint);
+            const char* pszOp = (poNode->nOperation == SWQ_LT) ? "lt" :
+                                (poNode->nOperation == SWQ_LE) ? "lte" :
+                                (poNode->nOperation == SWQ_GT) ? "gt" :
+                                /*(poNode->nOperation == SWQ_GE) ?*/ "gte";
+            json_object_object_add(poFieldConstraint, pszOp, poVal);
+            return poRet;
+        }
+        else if( poNode->nOperation == SWQ_BETWEEN &&
+                 poNode->nSubExprCount == 3 &&
+                 poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+                 poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+                 poNode->papoSubExpr[2]->eNodeType == SNT_CONSTANT &&
+                 poNode->papoSubExpr[0]->field_index != 0 &&
+                 poNode->papoSubExpr[0]->field_index <
+                                            m_poFeatureDefn->GetFieldCount() )
+        {
+            json_object* poVal1 = GetValue(poNode->papoSubExpr[0]->field_index,
+                                          poNode->papoSubExpr[1]);
+            if( poVal1 == NULL )
+            {
+                return NULL;
+            }
+            json_object* poVal2 = GetValue(poNode->papoSubExpr[0]->field_index,
+                                          poNode->papoSubExpr[2]);
+            if( poVal2 == NULL )
+            {
+                json_object_put(poVal1);
+                return NULL;
+            }
+
+            json_object* poRet = json_object_new_object();
+            json_object* poRange = json_object_new_object();
+            json_object_object_add(poRet, "range", poRange);
+            json_object* poFieldConstraint = json_object_new_object();
+            CPLString osFieldName(BuildPathFromArray(
+                    m_aaosFieldPaths[ poNode->papoSubExpr[0]->field_index]));
+            json_object_object_add(poRange, osFieldName, poFieldConstraint);
+            json_object_object_add(poFieldConstraint, "gte", poVal1);
+            json_object_object_add(poFieldConstraint, "lte", poVal2);
+            return poRet;
+        }
+        else if( poNode->nOperation == SWQ_IN &&
+                 poNode->nSubExprCount > 1 &&
+                 poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+                 poNode->papoSubExpr[0]->field_index <
+                                            m_poFeatureDefn->GetFieldCount() )
+        {
+            bool bAllConstant = true;
+            for( int i=1; i< poNode->nSubExprCount; i++ )
+            {
+                if( poNode->papoSubExpr[i]->eNodeType != SNT_CONSTANT )
+                {
+                    bAllConstant = false;
+                    break;
+                }
+            }
+            if( bAllConstant )
+            {
+                json_object* poRet = json_object_new_object();
+                if( poNode->papoSubExpr[0]->field_index == 0 )
+                {
+                    json_object* poIds = json_object_new_object();
+                    json_object* poValues = json_object_new_array();
+                    json_object_object_add(poIds, "values", poValues);
+                    json_object_object_add(poRet, "ids", poIds);
+                        for( int i=1; i< poNode->nSubExprCount; i++ )
+                    {
+                        json_object* poVal = GetValue(
+                                            poNode->papoSubExpr[0]->field_index,
+                                            poNode->papoSubExpr[i]);
+                        if( poVal == NULL )
+                        {
+                            json_object_put(poRet);
+                            return NULL;
+                        }
+                        json_object_array_add(poValues, poVal);
+                    }
+                }
+                else
+                {
+                    bool bNotAnalyzed = true;
+                    CPLString osPath(BuildPathFromArray(
+                        m_aaosFieldPaths[ poNode->papoSubExpr[0]->field_index]));
+                    if( poNode->papoSubExpr[1]->field_type == SWQ_STRING )
+                    {
+                        const char* pszFieldName =
+                            m_poFeatureDefn->GetFieldDefn(
+                                poNode->papoSubExpr[0]->field_index)->
+                                                                GetNameRef();
+                        bNotAnalyzed = CSLFindString(m_papszNotAnalyzedFields,
+                                                     pszFieldName) >= 0;
+                        if( !bNotAnalyzed &&
+                            CSLFindString(m_papszFieldsWithRawValue,
+                                                            pszFieldName) >= 0 )
+                        {
+                            osPath += ".raw";
+                            bNotAnalyzed = true;
+                        }
+
+                        if( !bNotAnalyzed &&
+                            !m_bFilterMustBeClientSideEvaluated )
+                        {
+                            m_bFilterMustBeClientSideEvaluated = true;
+                            CPLDebug("ES",
+                                    "Part or full filter will have to be "
+                                    "evaluated on client side (IN test on a "
+                                    "analyzed field).");
+                        }
+                    }
+
+                    if( bNotAnalyzed )
+                    {
+                        json_object* poTerms = json_object_new_object();
+                        json_object_object_add(poRet, "terms", poTerms);
+                        json_object* poTermsValues = json_object_new_array();
+                        json_object_object_add(poTerms, osPath,
+                                               poTermsValues);
+                        for( int i=1; i< poNode->nSubExprCount; i++ )
+                        {
+                            json_object* poVal = GetValue(
+                                        poNode->papoSubExpr[0]->field_index,
+                                        poNode->papoSubExpr[i]);
+                            if( poVal == NULL )
+                            {
+                                json_object_put(poRet);
+                                return NULL;
+                            }
+                            json_object_array_add(poTermsValues, poVal);
+                        }
+                    }
+                    else
+                    {
+                        json_object* poBool = json_object_new_object();
+                        json_object_object_add(poRet, "bool", poBool);
+                        json_object* poShould = json_object_new_array();
+                        json_object_object_add(poBool, "should", poShould);
+                        for( int i=1; i< poNode->nSubExprCount; i++ )
+                        {
+                            json_object* poVal = GetValue(
+                                        poNode->papoSubExpr[0]->field_index,
+                                        poNode->papoSubExpr[i]);
+                            if( poVal == NULL )
+                            {
+                                json_object_put(poRet);
+                                return NULL;
+                            }
+                            json_object* poShouldElt = json_object_new_object();
+                            json_object* poMatch = json_object_new_object();
+                            json_object_object_add(poShouldElt, "match",
+                                                   poMatch);
+                            json_object_object_add(poMatch, osPath, poVal);
+
+                            if( m_poDS->m_nMajorVersion < 2 )
+                            {
+                                json_object* poNewShouldElt =
+                                                    json_object_new_object();
+                                json_object_object_add(poNewShouldElt,
+                                                       "query", poShouldElt);
+                                poShouldElt = poNewShouldElt;
+                            }
+                            json_object_array_add(poShould, poShouldElt);
+                        }
+                    }
+                }
+                return poRet;
+            }
+        }
+        else if( poNode->nOperation == SWQ_LIKE &&
+                 poNode->nSubExprCount >= 2 &&
+                 poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+                 poNode->papoSubExpr[0]->field_index != 0 &&
+                 poNode->papoSubExpr[0]->field_index <
+                                            m_poFeatureDefn->GetFieldCount() )
+        {
+            char chEscape = '\0';
+            if( poNode->nSubExprCount == 3 )
+                chEscape = poNode->papoSubExpr[2]->string_value[0];
+            const char* pszPattern = poNode->papoSubExpr[1]->string_value;
+            const char* pszFieldName = m_poFeatureDefn->GetFieldDefn(
+                    poNode->papoSubExpr[0]->field_index)->GetNameRef();
+            bool bNotAnalyzed = CSLFindString(m_papszNotAnalyzedFields,
+                                              pszFieldName) >= 0;
+            CPLString osPath(BuildPathFromArray(
+                    m_aaosFieldPaths[ poNode->papoSubExpr[0]->field_index]));
+            if( !bNotAnalyzed && CSLFindString(m_papszFieldsWithRawValue,
+                                                        pszFieldName) >= 0 )
+            {
+                osPath += ".raw";
+                bNotAnalyzed = true;
+            }
+
+            if( strchr(pszPattern, '*') || strchr(pszPattern, '?') )
+            {
+                CPLDebug("ES", "Cannot handle * or ? in LIKE pattern");
+            }
+            else if( !bNotAnalyzed )
+            {
+                if( !m_bFilterMustBeClientSideEvaluated )
+                {
+                    m_bFilterMustBeClientSideEvaluated = true;
+                    CPLDebug("ES",
+                            "Part or full filter will have to be evaluated on "
+                            "client side (wildcard test on a analyzed field).");
+                }
+            }
+            else
+            {
+                CPLString osUnescaped;
+                for( int i=0; pszPattern[i] != '\0'; ++i )
+                {
+                    if( chEscape == pszPattern[i] )
+                    {
+                        if( pszPattern[i+1] == '\0' )
+                            break;
+                        osUnescaped += pszPattern[i+1];
+                        i ++;
+                    }
+                    else if( pszPattern[i] == '%' )
+                    {
+                        osUnescaped += '*';
+                    }
+                    else if( pszPattern[i] == '_' )
+                    {
+                        osUnescaped += '?';
+                    }
+                    else
+                    {
+                        osUnescaped += pszPattern[i];
+                    }
+                }
+                json_object* poRet = json_object_new_object();
+                json_object* poWildcard = json_object_new_object();
+                json_object_object_add(poRet, "wildcard", poWildcard);
+                json_object_object_add(poWildcard, osPath,
+                    json_object_new_string(osUnescaped));
+                return poRet;
+            }
+        }
+    }
+
+    if( !m_bFilterMustBeClientSideEvaluated )
+    {
+        m_bFilterMustBeClientSideEvaluated = true;
+        CPLDebug("ES",
+                 "Part or full filter will have to be evaluated on "
+                 "client side.");
+    }
+    return NULL;
+}
+
+/************************************************************************/
 /*                          SetAttributeFilter()                        */
 /************************************************************************/
 
 OGRErr OGRElasticLayer::SetAttributeFilter(const char* pszFilter)
 {
+    m_bFilterMustBeClientSideEvaluated = false;
     if( pszFilter != NULL && pszFilter[0] == '{' )
     {
-        if( m_osESSearch.size() )
+        if( !m_osESSearch.empty() )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Setting an ElasticSearch filter on a resulting layer is not supported");
+                "Setting an ElasticSearch filter on a resulting layer "
+                "is not supported");
             return OGRERR_FAILURE;
         }
         OGRLayer::SetAttributeFilter(NULL);
@@ -2342,8 +3155,17 @@ OGRErr OGRElasticLayer::SetAttributeFilter(const char* pszFilter)
     }
     else
     {
-        m_osJSONFilter = "";
-        return OGRLayer::SetAttributeFilter(pszFilter);
+        m_osJSONFilter.clear();
+        json_object_put(m_poJSONFilter);
+        m_poJSONFilter = NULL;
+        OGRErr eErr = OGRLayer::SetAttributeFilter(pszFilter);
+        if( eErr == OGRERR_NONE && m_poAttrQuery != NULL )
+        {
+            swq_expr_node* poNode = reinterpret_cast<swq_expr_node*>(
+                                                m_poAttrQuery->GetSWQExpr());
+            m_poJSONFilter = TranslateSQLToFilter(poNode);
+        }
+        return eErr;
     }
 }
 
@@ -2376,7 +3198,7 @@ void OGRElasticLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
     if( poGeomIn == NULL )
         return;
 
-    if( m_osESSearch.size() )
+    if( !m_osESSearch.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                     "Setting a spatial filter on a resulting layer is not supported");
@@ -2426,13 +3248,13 @@ void OGRElasticLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
 
         json_object* top_left = json_object_new_object();
         json_object_object_add(field, "top_left", top_left);
-        json_object_object_add(top_left, "lat", json_object_new_double(sEnvelope.MaxY));
-        json_object_object_add(top_left, "lon", json_object_new_double(sEnvelope.MinX));
+        json_object_object_add(top_left, "lat", json_object_new_double_with_precision(sEnvelope.MaxY, 6));
+        json_object_object_add(top_left, "lon", json_object_new_double_with_precision(sEnvelope.MinX, 6));
 
         json_object* bottom_right = json_object_new_object();
         json_object_object_add(field, "bottom_right", bottom_right);
-        json_object_object_add(bottom_right, "lat", json_object_new_double(sEnvelope.MinY));
-        json_object_object_add(bottom_right, "lon", json_object_new_double(sEnvelope.MaxX));
+        json_object_object_add(bottom_right, "lat", json_object_new_double_with_precision(sEnvelope.MinY, 6));
+        json_object_object_add(bottom_right, "lon", json_object_new_double_with_precision(sEnvelope.MaxX, 6));
     }
     else
     {
@@ -2453,13 +3275,13 @@ void OGRElasticLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
         json_object_object_add(shape, "coordinates", coordinates);
 
         json_object* top_left = json_object_new_array();
-        json_object_array_add(top_left, json_object_new_double(sEnvelope.MinX));
-        json_object_array_add(top_left, json_object_new_double(sEnvelope.MaxY));
+        json_object_array_add(top_left, json_object_new_double_with_precision(sEnvelope.MinX, 6));
+        json_object_array_add(top_left, json_object_new_double_with_precision(sEnvelope.MaxY, 6));
         json_object_array_add(coordinates, top_left);
 
         json_object* bottom_right = json_object_new_array();
-        json_object_array_add(bottom_right, json_object_new_double(sEnvelope.MaxX));
-        json_object_array_add(bottom_right, json_object_new_double(sEnvelope.MinY));
+        json_object_array_add(bottom_right, json_object_new_double_with_precision(sEnvelope.MaxX, 6));
+        json_object_array_add(bottom_right, json_object_new_double_with_precision(sEnvelope.MinY, 6));
         json_object_array_add(coordinates, bottom_right);
     }
 }
@@ -2485,12 +3307,12 @@ OGRErr OGRElasticLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bFo
     if( !m_abIsGeoPoint[iGeomField] )
         return OGRLayer::GetExtentInternal(iGeomField, psExtent, bForce);
 
-    json_object* poResponse;
-    CPLString osFilter = CPLSPrintf("{ \"aggs\" : { \"bbox\" : { \"geo_bounds\" : { \"field\" : \"%s\" } } } }",
+    CPLString osFilter = CPLSPrintf("{ \"size\": 0, \"aggs\" : { \"bbox\" : { \"geo_bounds\" : { \"field\" : \"%s\" } } } }",
                                     BuildPathFromArray(m_aaosGeomFieldPaths[iGeomField]).c_str() );
-    poResponse = m_poDS->RunRequest(
-        CPLSPrintf("%s/%s/%s/_search?search_type=count&pretty",
-                    m_poDS->GetURL(), m_osIndexName.c_str(), m_osMappingName.c_str()),
+    json_object* poResponse = m_poDS->RunRequest(
+        CPLSPrintf("%s/%s/%s/_search?pretty",
+                   m_poDS->GetURL(), m_osIndexName.c_str(),
+                   m_osMappingName.c_str()),
         osFilter.c_str());
 
     json_object* poBounds = json_ex_get_object_by_path(poResponse, "aggregations.bbox.bounds");
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
index ebba8ba..76f2892 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDatasource.cpp
@@ -1,760 +1,757 @@
-/******************************************************************************
- * $Id: FGdbDatasource.cpp 33563 2016-02-26 14:57:06Z rouault $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements FileGDB OGR Datasource.
- * Author:   Ragi Yaser Burhum, ragi at burhum.com
- *           Paul Ramsey, pramsey at cleverelephant.ca
- *
- ******************************************************************************
- * Copyright (c) 2010, Ragi Yaser Burhum
- * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
- * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_fgdb.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "gdal.h"
-#include "FGdbUtils.h"
-#include "cpl_multiproc.h"
-
-CPL_CVSID("$Id: FGdbDatasource.cpp 33563 2016-02-26 14:57:06Z rouault $");
-
-using std::vector;
-using std::wstring;
-
-/************************************************************************/
-/*                          FGdbDataSource()                           */
-/************************************************************************/
-
-FGdbDataSource::FGdbDataSource(FGdbDriver* poDriverIn, 
-                               FGdbDatabaseConnection* pConnection):
-OGRDataSource(),
-m_poDriver(poDriverIn), m_pConnection(pConnection), m_pGeodatabase(NULL), m_bUpdate(false),
-m_poOpenFileGDBDrv(NULL)
-{
-    bPerLayerCopyingForTransaction = -1;
-}
-
-/************************************************************************/
-/*                          ~FGdbDataSource()                          */
-/************************************************************************/
-
-FGdbDataSource::~FGdbDataSource()
-{
-    CPLMutexHolderOptionalLockD(m_poDriver ? m_poDriver->GetMutex() : NULL);
-    
-    if( m_pConnection && m_pConnection->IsLocked() )
-        CommitTransaction();
-
-    //Close();
-    size_t count = m_layers.size();
-    for(size_t i = 0; i < count; ++i )
-    {
-        m_layers[i]->CloseGDBObjects();
-    }
-
-    FixIndexes();
-
-    if( m_poDriver )
-        m_poDriver->Release( m_osPublicName );
-
-    //size_t count = m_layers.size();
-    for(size_t i = 0; i < count; ++i )
-    {
-        delete m_layers[i];
-    }
-}
-
-/************************************************************************/
-/*                             FixIndexes()                             */
-/************************************************************************/
-
-int FGdbDataSource::FixIndexes()
-{
-    int bRet = TRUE;
-    if( m_pConnection && m_pConnection->IsFIDHackInProgress() )
-    {
-        m_pConnection->CloseGeodatabase();
-
-        char* apszDrivers[2];
-        apszDrivers[0] = (char*) "OpenFileGDB";
-        apszDrivers[1] = NULL;
-        const char* pszSystemCatalog = CPLFormFilename(m_osFSName, "a00000001.gdbtable", NULL);
-        GDALDataset* poOpenFileGDBDS = (GDALDataset*)
-            GDALOpenEx(pszSystemCatalog, GDAL_OF_VECTOR,
-                       apszDrivers, NULL, NULL);
-        if( poOpenFileGDBDS == NULL || poOpenFileGDBDS->GetLayer(0) == NULL )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Cannot open %s with OpenFileGDB driver. "
-                     "Should not happen. Some layers will be corrupted",
-                     pszSystemCatalog);
-            bRet = FALSE;
-        }
-        else
-        {
-            OGRLayer* poLayer = poOpenFileGDBDS->GetLayer(0);
-            size_t count = m_layers.size();
-            for(size_t i = 0; i < count; ++i )
-            {
-                if( m_layers[i]->m_oMapOGRFIDToFGDBFID.size() == 0)
-                    continue;
-                CPLString osFilter = "name = '";
-                osFilter += m_layers[i]->GetName();
-                osFilter += "'";
-                poLayer->SetAttributeFilter(osFilter);
-                poLayer->ResetReading();
-                OGRFeature* poF = poLayer->GetNextFeature();
-                if( poF == NULL )
-                {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Cannot find filename for layer %s",
-                             m_layers[i]->GetName());
-                    bRet = FALSE;
-                }
-                else
-                {
-                    if( !m_layers[i]->EditIndexesForFIDHack(CPLFormFilename(m_osFSName,
-                                        CPLSPrintf("a%08x", (int)poF->GetFID()), NULL)) )
-                    {
-                        bRet = FALSE;
-                    }
-                }
-                delete poF;
-            }
-        }
-        GDALClose(poOpenFileGDBDS);
-
-        m_pConnection->SetFIDHackInProgress(FALSE);
-    }
-    return bRet;
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-int FGdbDataSource::Open(const char * pszNewName, int bUpdate,
-                         const char* pszPublicName )
-{
-    m_osFSName = pszNewName;
-    m_osPublicName = (pszPublicName) ? pszPublicName : pszNewName;
-    m_pGeodatabase = m_pConnection->GetGDB();
-    m_bUpdate = CPL_TO_BOOL(bUpdate);
-    m_poOpenFileGDBDrv = (GDALDriver*) GDALGetDriverByName("OpenFileGDB");
-
-    std::vector<std::wstring> typesRequested;
-
-	// We're only interested in Tables, Feature Datasets and Feature Classes
-	typesRequested.push_back(L"Feature Class");
-	typesRequested.push_back(L"Table");
-	typesRequested.push_back(L"Feature Dataset");
-	
-    bool rv = LoadLayers(L"\\");
-
-    return rv;
-}
-
-/************************************************************************/
-/*                               Close()                                */
-/************************************************************************/
-
-int FGdbDataSource::Close(int bCloseGeodatabase)
-{
-    size_t count = m_layers.size();
-    for(size_t i = 0; i < count; ++i )
-    {
-        m_layers[i]->CloseGDBObjects();
-    }
-
-    int bRet = FixIndexes();
-    if( m_pConnection && bCloseGeodatabase )
-        m_pConnection->CloseGeodatabase();
-    m_pGeodatabase = NULL;
-    return bRet;
-}
-
-/************************************************************************/
-/*                               ReOpen()                               */
-/************************************************************************/
-
-int FGdbDataSource::ReOpen()
-{
-    CPLAssert(m_pGeodatabase == NULL);
-
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE1") ||
-        !m_pConnection->OpenGeodatabase(m_osFSName) )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s",
-                 m_osFSName.c_str());
-        return FALSE;
-    }
-
-    FGdbDataSource* pDS = new FGdbDataSource(m_poDriver, m_pConnection);
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE2") ||
-        !pDS->Open(m_osPublicName, TRUE, m_osFSName) )
-    {
-        pDS->m_poDriver = NULL;
-        delete pDS;
-        CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s",
-                 m_osFSName.c_str());
-        return FALSE;
-    }
-    
-    int bRet = TRUE;
-    size_t count = m_layers.size();
-    for(size_t i = 0; i < count; ++i )
-    {
-        FGdbLayer* pNewLayer = (FGdbLayer*)pDS->GetLayerByName(m_layers[i]->GetName());
-        if( pNewLayer &&
-            !EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE3") )
-        {
-            m_layers[i]->m_pTable = pNewLayer->m_pTable;
-            pNewLayer->m_pTable = NULL;
-            m_layers[i]->m_pEnumRows = pNewLayer->m_pEnumRows;
-            pNewLayer->m_pEnumRows = NULL;
-        }
-        else
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s",
-                     m_layers[i]->GetName());
-            bRet = FALSE;
-        }
-        m_layers[i]->m_oMapOGRFIDToFGDBFID.clear();
-        m_layers[i]->m_oMapFGDBFIDToOGRFID.clear();
-    }
-    
-    m_pGeodatabase = pDS->m_pGeodatabase;
-    pDS->m_pGeodatabase = NULL;
-
-    pDS->m_poDriver = NULL;
-    pDS->m_pConnection = NULL;
-    delete pDS;
-    
-    return bRet;
-}
-
-/************************************************************************/
-/*                          OpenFGDBTables()                            */
-/************************************************************************/
-
-bool FGdbDataSource::OpenFGDBTables(const std::wstring &type,
-                                    const std::vector<std::wstring> &layers)
-{
-    fgdbError hr;
-    for ( unsigned int i = 0; i < layers.size(); i++ )
-    {
-        Table* pTable = new Table;
-        //CPLDebug("FGDB", "Opening %s", WStringToString(layers[i]).c_str());
-        if (FAILED(hr = m_pGeodatabase->OpenTable(layers[i], *pTable)))
-        {
-            delete pTable;
-            
-            std::wstring fgdb_error_desc_w;
-            fgdbError er;
-            er = FileGDBAPI::ErrorInfo::GetErrorDescription(hr, fgdb_error_desc_w);
-            const char* pszLikelyReason = "Might be due to unsupported spatial reference system. Using OpenFileGDB driver or FileGDB SDK >= 1.4 should solve it";
-            if ( er == S_OK )
-            {
-                std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
-                if( fgdb_error_desc == "FileGDB compression is not installed." )
-                {
-                    pszLikelyReason = "Using FileGDB SDK 1.4 or later should solve this issue.";
-                }
-            }
-
-            GDBErr(hr, "Error opening " + WStringToString(layers[i]),
-                   CE_Warning,
-                   (". Skipping it. " + CPLString(pszLikelyReason)).c_str());
-            continue;
-        }
-        FGdbLayer* pLayer = new FGdbLayer();
-        if (!pLayer->Initialize(this, pTable, layers[i], type))
-        {
-            delete pLayer;
-            return GDBErr(hr, "Error initializing OGRLayer for " + WStringToString(layers[i]));
-        }
-
-        m_layers.push_back(pLayer);
-    }
-    return true;
-}
-
-/************************************************************************/
-/*                            LoadLayers()                             */
-/************************************************************************/
-
-bool FGdbDataSource::LoadLayers(const std::wstring &root) 
-{
-    std::vector<wstring> tables;
-    std::vector<wstring> featureclasses;
-    std::vector<wstring> featuredatasets;
-    fgdbError hr;
-
-    /* Find all the Tables in the root */
-    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Table", tables)) )
-    {
-        return GDBErr(hr, "Error reading Tables in " + WStringToString(root));
-    }
-    /* Open the tables we found */
-    if ( tables.size() > 0 && ! OpenFGDBTables(L"Table", tables) )
-        return false;
-
-    /* Find all the Feature Classes in the root */
-    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Class", featureclasses)) )
-    {
-        return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(root));
-    }
-    /* Open the tables we found */
-    if ( featureclasses.size() > 0 && ! OpenFGDBTables(L"Feature Class", featureclasses) )
-        return false;
-
-    /* Find all the Feature Datasets in the root */
-    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Dataset", featuredatasets)) )
-    {
-        return GDBErr(hr, "Error reading Feature Datasets in " + WStringToString(root));
-    }
-    /* Look for Feature Classes inside the Feature Dataset */
-    for ( unsigned int i = 0; i < featuredatasets.size(); i++ )
-    {
-        if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(featuredatasets[i], L"Feature Class", featureclasses)) )
-        {
-            return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(featuredatasets[i]));
-        }
-        if ( featureclasses.size() > 0 && ! OpenFGDBTables(L"Feature Class", featureclasses) )
-            return false;
-    }
-    return true;
-}
-
-
-#if 0
-/************************************************************************/
-/*                            LoadLayersOld()                              */
-/************************************************************************/
-
-/* Old recursive LoadLayers. Removed in favor of simple one that only
-   looks at FeatureClasses and Tables. */
-
-// Flattens out hierarchical GDB structure.
-bool FGdbDataSource::LoadLayersOld(const std::vector<wstring> & datasetTypes,
-                                const wstring & parent)
-{
-    long hr = S_OK;
-
-    // I didn't find an API to give me the type of the dataset based on name - I am *not*
-    // parsing XML for something like this - in the meantime I can use this hack to see
-    // if the dataset had any children whatsoever - if so, then I won't attempt to open it
-    // otherwise, do attempt to do that
-
-    bool childrenFound = false;
-    bool errorsEncountered = false;
-
-    for (size_t dsTypeIndex = 0; dsTypeIndex < datasetTypes.size(); dsTypeIndex++)
-    {
-        std::vector<wstring> childDatasets;
-        m_pGeodatabase->GetChildDatasets( parent, datasetTypes[dsTypeIndex], childDatasets);
-
-        if (childDatasets.size() > 0)
-        {
-            //it is a container of other datasets
-
-            for (size_t childDatasetIndex = 0;
-                 childDatasetIndex < childDatasets.size();
-                 childDatasetIndex++)
-            {
-                childrenFound = true;
-
-                // do something with it
-                // For now, we just ignore dataset containers and only open the children
-                // std::wcout << datasetTypes[dsTypeIndex] << L" " << childDatasets[childDatasetIndex] << std::endl;
-
-                if (!LoadLayersOld(datasetTypes, childDatasets[childDatasetIndex]))
-                    errorsEncountered = true;
-            }
-        }
-    }
-
-    //it is a full fledged dataset itself without children - open it (except the root)
-
-    if ((!childrenFound) && parent != L"\\")
-    {
-        // wcout << "Opening " << parent << "...";
-        Table* pTable = new Table;
-        if (FAILED(hr = m_pGeodatabase->OpenTable(parent,*pTable)))
-        {
-            delete pTable;
-            return GDBErr(hr, "Error opening " + WStringToString(parent));
-        }
-
-        FGdbLayer* pLayer = new FGdbLayer;
-
-        //pLayer has ownership of the table pointer as soon Initialize is called
-        if (!pLayer->Initialize(this, pTable, parent))
-        {
-            delete pLayer;
-
-            return GDBErr(hr, "Error initializing OGRLayer for " +
-                          WStringToString(parent));
-        }
-
-        m_layers.push_back(pLayer);
-    }
-
-    return !errorsEncountered;
-}
-#endif
-
-
-/************************************************************************/
-/*                            DeleteLayer()                             */
-/************************************************************************/
-
-OGRErr FGdbDataSource::DeleteLayer( int iLayer )
-{
-    if( !m_bUpdate || m_pGeodatabase == NULL )
-        return OGRERR_FAILURE;
-
-    if( iLayer < 0 || iLayer >= static_cast<int>(m_layers.size()) )
-        return OGRERR_FAILURE;
-    
-    FGdbLayer* poBaseLayer = m_layers[iLayer];
-
-    // Fetch FGDBAPI Table before deleting OGR layer object
-
-    //Table* pTable = poBaseLayer->GetTable();
-
-    std::string name = poBaseLayer->GetLayerDefn()->GetName();
-    std::wstring strPath = poBaseLayer->GetTablePath();
-    std::wstring strType = poBaseLayer->GetType();
-
-    // delete OGR layer
-    delete m_layers[iLayer];
-
-    //pTable = NULL; // OGR Layer had ownership of FGDB Table
-
-    m_layers.erase(m_layers.begin() + iLayer);
-
-    long hr;
-  
-    if (FAILED(hr = m_pGeodatabase->Delete(strPath, strType)))
-    {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                 "%s was not deleted however it has been closed", name.c_str());
-        GDBErr(hr, "Failed deleting dataset");
-        return OGRERR_FAILURE;
-    }
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int FGdbDataSource::TestCapability( const char * pszCap )
-{
-    if( EQUAL(pszCap,ODsCCreateLayer) )
-        return m_bUpdate;
-
-    else if( EQUAL(pszCap,ODsCDeleteLayer) )
-        return m_bUpdate;
-    else if EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer)
-        return TRUE;
-    return FALSE;
-}
-
-
-/************************************************************************/
-/*                              GetLayer()                              */
-/************************************************************************/
-
-OGRLayer *FGdbDataSource::GetLayer( int iLayer )
-{ 
-    int count = static_cast<int>(m_layers.size());
-
-    if( iLayer < 0 || iLayer >= count )
-        return NULL;
-    else
-        return m_layers[iLayer];
-}
-
-/************************************************************************/
-/*                             ICreateLayer()                           */
-/*                                                                      */
-/* See FGdbLayer::Create for creation options                           */
-/************************************************************************/
-
-OGRLayer *
-FGdbDataSource::ICreateLayer( const char * pszLayerName,
-                              OGRSpatialReference *poSRS,
-                              OGRwkbGeometryType eType,
-                              char ** papszOptions )
-{
-    if( !m_bUpdate || m_pGeodatabase == NULL )
-        return NULL;
-
-    FGdbLayer* pLayer = new FGdbLayer();
-    if (!pLayer->Create(this, pszLayerName, poSRS, eType, papszOptions))
-    {
-        delete pLayer;
-        return NULL;
-    }
-
-    m_layers.push_back(pLayer);
-
-    return pLayer;  
-}
-
-
-/************************************************************************/
-/*                   OGRFGdbSingleFeatureLayer                          */
-/************************************************************************/
-
-class OGRFGdbSingleFeatureLayer : public OGRLayer
-{
-  private:
-    char               *pszVal;
-    OGRFeatureDefn     *poFeatureDefn;
-    int                 iNextShapeId;
-
-  public:
-                        OGRFGdbSingleFeatureLayer( const char* pszLayerName,
-                                                   const char *pszVal );
-                        ~OGRFGdbSingleFeatureLayer();
-
-    virtual void        ResetReading() { iNextShapeId = 0; }
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
-    virtual int         TestCapability( const char * ) { return FALSE; }
-};
-
-/************************************************************************/
-/*                    OGRFGdbSingleFeatureLayer()                       */
-/************************************************************************/
-
-OGRFGdbSingleFeatureLayer::OGRFGdbSingleFeatureLayer(const char* pszLayerName,
-                                                     const char *pszValIn )
-{
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
-    SetDescription( poFeatureDefn->GetName() );
-    poFeatureDefn->Reference();
-    OGRFieldDefn oField( "FIELD_1", OFTString );
-    poFeatureDefn->AddFieldDefn( &oField );
-
-    iNextShapeId = 0;
-    this->pszVal = pszValIn ? CPLStrdup(pszValIn) : NULL;
-}
-
-/************************************************************************/
-/*                   ~OGRFGdbSingleFeatureLayer()                       */
-/************************************************************************/
-
-OGRFGdbSingleFeatureLayer::~OGRFGdbSingleFeatureLayer()
-{
-    if( poFeatureDefn != NULL )
-        poFeatureDefn->Release();
-    CPLFree(pszVal);
-}
-
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRFeature * OGRFGdbSingleFeatureLayer::GetNextFeature()
-{
-    if (iNextShapeId != 0)
-        return NULL;
-
-    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
-    if (pszVal)
-        poFeature->SetField(0, pszVal);
-    poFeature->SetFID(iNextShapeId ++);
-    return poFeature;
-}
-
-/************************************************************************/
-/*                              ExecuteSQL()                            */
-/************************************************************************/
-
-OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
-                                       OGRGeometry *poSpatialFilter,
-                                       const char *pszDialect )
-
-{
-    if( m_pConnection && m_pConnection->IsFIDHackInProgress() )
-    {
-        if( Close() )
-            ReOpen();
-    }
-    if( m_pGeodatabase == NULL )
-         return NULL;
-
-    size_t count = m_layers.size();
-    for(size_t i = 0; i < count; ++i )
-    {
-        m_layers[i]->EndBulkLoad();
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Use generic implementation for recognized dialects              */
-/* -------------------------------------------------------------------- */
-    if( IsGenericSQLDialect(pszDialect) )
-        return OGRDataSource::ExecuteSQL( pszSQLCommand,
-                                          poSpatialFilter,
-                                          pszDialect );
-
-/* -------------------------------------------------------------------- */
-/*      Special case GetLayerDefinition                                 */
-/* -------------------------------------------------------------------- */
-    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerDefinition "))
-    {
-        FGdbLayer* poLayer = (FGdbLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerDefinition "));
-        if (poLayer)
-        {
-            char* pszVal = NULL;
-            poLayer->GetLayerXML(&pszVal);
-            OGRLayer* poRet = new OGRFGdbSingleFeatureLayer( "LayerDefinition", pszVal );
-            CPLFree(pszVal);
-            return poRet;
-        }
-        else
-            return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Special case GetLayerMetadata                                   */
-/* -------------------------------------------------------------------- */
-    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerMetadata "))
-    {
-        FGdbLayer* poLayer = (FGdbLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerMetadata "));
-        if (poLayer)
-        {
-            char* pszVal = NULL;
-            poLayer->GetLayerMetadataXML(&pszVal);
-            OGRLayer* poRet = new OGRFGdbSingleFeatureLayer( "LayerMetadata", pszVal );
-            CPLFree(pszVal);
-            return poRet;
-        }
-        else
-            return NULL;
-    }
-
-    /* TODO: remove that workaround when the SDK has finally a decent */
-    /* SQL support ! */
-    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") && pszDialect == NULL )
-    {
-        CPLDebug("FGDB", "Support for SELECT is known to be partially "
-                         "non-compliant with FileGDB SDK API v1.2.\n"
-                         "So for now, we use default OGR SQL engine. "
-                         "Explicitly specify -dialect FileGDB\n"
-                         "to use the SQL engine from the FileGDB SDK API");
-        OGRLayer* poLayer = OGRDataSource::ExecuteSQL( pszSQLCommand,
-                                        poSpatialFilter,
-                                        pszDialect );
-        if( poLayer )
-            m_oSetSelectLayers.insert(poLayer);
-        return poLayer;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Run the SQL                                                     */
-/* -------------------------------------------------------------------- */
-    EnumRows* pEnumRows = new EnumRows;
-    long hr;
-    try
-    {
-        hr = m_pGeodatabase->ExecuteSQL(
-                                StringToWString(pszSQLCommand), true, *pEnumRows);
-    }
-    catch(...)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Exception occurred at executing '%s'. Application may "
-                  "become unstable", pszSQLCommand );
-        delete pEnumRows;
-        return NULL;
-    }
-
-    if (FAILED(hr))
-    {
-        GDBErr(hr, CPLSPrintf("Failed at executing '%s'", pszSQLCommand));
-        delete pEnumRows;
-        return NULL;
-    }
-
-    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
-    {
-        OGRLayer* poLayer = new FGdbResultLayer(this, pszSQLCommand, pEnumRows);
-        m_oSetSelectLayers.insert(poLayer);
-        return poLayer;
-    }
-    else
-    {
-        delete pEnumRows;
-        return NULL;
-    }
-}
-
-/************************************************************************/
-/*                           ReleaseResultSet()                         */
-/************************************************************************/
-
-void FGdbDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
-{
-    if( poResultsSet )
-        m_oSetSelectLayers.erase(poResultsSet);
-    delete poResultsSet;
-}
-
-/************************************************************************/
-/*                      HasPerLayerCopyingForTransaction()              */
-/************************************************************************/
-
-int FGdbDataSource::HasPerLayerCopyingForTransaction()
-{
-    if( bPerLayerCopyingForTransaction >= 0 )
-        return bPerLayerCopyingForTransaction;
-#ifdef WIN32
-    bPerLayerCopyingForTransaction = FALSE;
-#else
-    bPerLayerCopyingForTransaction =
-        m_poOpenFileGDBDrv != NULL &&
-        CPLTestBool(CPLGetConfigOption("FGDB_PER_LAYER_COPYING_TRANSACTION", "TRUE"));
-#endif
-    return bPerLayerCopyingForTransaction;
-}
-
-/************************************************************************/
-/*                        SetSymlinkFlagOnAllLayers()                    */
-/************************************************************************/
-
-void FGdbDataSource::SetSymlinkFlagOnAllLayers()
-{
-    size_t count = m_layers.size();
-    for(size_t i = 0; i < count; ++i )
-    {
-        m_layers[i]->SetSymlinkFlag();
-    }
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements FileGDB OGR Datasource.
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *           Paul Ramsey, pramsey at cleverelephant.ca
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Ragi Yaser Burhum
+ * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_fgdb.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal.h"
+#include "FGdbUtils.h"
+#include "cpl_multiproc.h"
+
+CPL_CVSID("$Id: FGdbDatasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+using std::vector;
+using std::wstring;
+
+/************************************************************************/
+/*                          FGdbDataSource()                           */
+/************************************************************************/
+
+FGdbDataSource::FGdbDataSource(FGdbDriver* poDriverIn,
+                               FGdbDatabaseConnection* pConnection):
+OGRDataSource(),
+m_poDriver(poDriverIn), m_pConnection(pConnection), m_pGeodatabase(NULL), m_bUpdate(false),
+m_poOpenFileGDBDrv(NULL)
+{
+    bPerLayerCopyingForTransaction = -1;
+}
+
+/************************************************************************/
+/*                          ~FGdbDataSource()                          */
+/************************************************************************/
+
+FGdbDataSource::~FGdbDataSource()
+{
+    CPLMutexHolderOptionalLockD(m_poDriver ? m_poDriver->GetMutex() : NULL);
+
+    if( m_pConnection && m_pConnection->IsLocked() )
+        CommitTransaction();
+
+    //Close();
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        m_layers[i]->CloseGDBObjects();
+    }
+
+    FixIndexes();
+
+    if( m_poDriver )
+        m_poDriver->Release( m_osPublicName );
+
+    //size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        delete m_layers[i];
+    }
+}
+
+/************************************************************************/
+/*                             FixIndexes()                             */
+/************************************************************************/
+
+int FGdbDataSource::FixIndexes()
+{
+    int bRet = TRUE;
+    if( m_pConnection && m_pConnection->IsFIDHackInProgress() )
+    {
+        m_pConnection->CloseGeodatabase();
+
+        char* apszDrivers[2];
+        apszDrivers[0] = (char*) "OpenFileGDB";
+        apszDrivers[1] = NULL;
+        const char* pszSystemCatalog = CPLFormFilename(m_osFSName, "a00000001.gdbtable", NULL);
+        GDALDataset* poOpenFileGDBDS = (GDALDataset*)
+            GDALOpenEx(pszSystemCatalog, GDAL_OF_VECTOR,
+                       apszDrivers, NULL, NULL);
+        if( poOpenFileGDBDS == NULL || poOpenFileGDBDS->GetLayer(0) == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot open %s with OpenFileGDB driver. "
+                     "Should not happen. Some layers will be corrupted",
+                     pszSystemCatalog);
+            bRet = FALSE;
+        }
+        else
+        {
+            OGRLayer* poLayer = poOpenFileGDBDS->GetLayer(0);
+            size_t count = m_layers.size();
+            for(size_t i = 0; i < count; ++i )
+            {
+                if( m_layers[i]->m_oMapOGRFIDToFGDBFID.empty())
+                    continue;
+                CPLString osFilter = "name = '";
+                osFilter += m_layers[i]->GetName();
+                osFilter += "'";
+                poLayer->SetAttributeFilter(osFilter);
+                poLayer->ResetReading();
+                OGRFeature* poF = poLayer->GetNextFeature();
+                if( poF == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot find filename for layer %s",
+                             m_layers[i]->GetName());
+                    bRet = FALSE;
+                }
+                else
+                {
+                    if( !m_layers[i]->EditIndexesForFIDHack(CPLFormFilename(m_osFSName,
+                                        CPLSPrintf("a%08x", (int)poF->GetFID()), NULL)) )
+                    {
+                        bRet = FALSE;
+                    }
+                }
+                delete poF;
+            }
+        }
+        GDALClose(poOpenFileGDBDS);
+
+        m_pConnection->SetFIDHackInProgress(FALSE);
+    }
+    return bRet;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int FGdbDataSource::Open(const char * pszNewName, int bUpdate,
+                         const char* pszPublicName )
+{
+    m_osFSName = pszNewName;
+    m_osPublicName = (pszPublicName) ? pszPublicName : pszNewName;
+    m_pGeodatabase = m_pConnection->GetGDB();
+    m_bUpdate = CPL_TO_BOOL(bUpdate);
+    m_poOpenFileGDBDrv = (GDALDriver*) GDALGetDriverByName("OpenFileGDB");
+
+    std::vector<std::wstring> typesRequested;
+
+    // We're only interested in Tables, Feature Datasets and Feature Classes
+    typesRequested.push_back(L"Feature Class");
+    typesRequested.push_back(L"Table");
+    typesRequested.push_back(L"Feature Dataset");
+
+    bool rv = LoadLayers(L"\\");
+
+    return rv;
+}
+
+/************************************************************************/
+/*                               Close()                                */
+/************************************************************************/
+
+int FGdbDataSource::Close(int bCloseGeodatabase)
+{
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        m_layers[i]->CloseGDBObjects();
+    }
+
+    int bRet = FixIndexes();
+    if( m_pConnection && bCloseGeodatabase )
+        m_pConnection->CloseGeodatabase();
+    m_pGeodatabase = NULL;
+    return bRet;
+}
+
+/************************************************************************/
+/*                               ReOpen()                               */
+/************************************************************************/
+
+int FGdbDataSource::ReOpen()
+{
+    CPLAssert(m_pGeodatabase == NULL);
+
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE1") ||
+        !m_pConnection->OpenGeodatabase(m_osFSName) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s",
+                 m_osFSName.c_str());
+        return FALSE;
+    }
+
+    FGdbDataSource* pDS = new FGdbDataSource(m_poDriver, m_pConnection);
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE2") ||
+        !pDS->Open(m_osPublicName, TRUE, m_osFSName) )
+    {
+        pDS->m_poDriver = NULL;
+        delete pDS;
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s",
+                 m_osFSName.c_str());
+        return FALSE;
+    }
+
+    int bRet = TRUE;
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        FGdbLayer* pNewLayer = (FGdbLayer*)pDS->GetLayerByName(m_layers[i]->GetName());
+        if( pNewLayer &&
+            !EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE3") )
+        {
+            m_layers[i]->m_pTable = pNewLayer->m_pTable;
+            pNewLayer->m_pTable = NULL;
+            m_layers[i]->m_pEnumRows = pNewLayer->m_pEnumRows;
+            pNewLayer->m_pEnumRows = NULL;
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s",
+                     m_layers[i]->GetName());
+            bRet = FALSE;
+        }
+        m_layers[i]->m_oMapOGRFIDToFGDBFID.clear();
+        m_layers[i]->m_oMapFGDBFIDToOGRFID.clear();
+    }
+
+    m_pGeodatabase = pDS->m_pGeodatabase;
+    pDS->m_pGeodatabase = NULL;
+
+    pDS->m_poDriver = NULL;
+    pDS->m_pConnection = NULL;
+    delete pDS;
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                          OpenFGDBTables()                            */
+/************************************************************************/
+
+bool FGdbDataSource::OpenFGDBTables(const std::wstring &type,
+                                    const std::vector<std::wstring> &layers)
+{
+    fgdbError hr;
+    for ( unsigned int i = 0; i < layers.size(); i++ )
+    {
+        Table* pTable = new Table;
+        //CPLDebug("FGDB", "Opening %s", WStringToString(layers[i]).c_str());
+        if (FAILED(hr = m_pGeodatabase->OpenTable(layers[i], *pTable)))
+        {
+            delete pTable;
+
+            std::wstring fgdb_error_desc_w;
+            fgdbError er;
+            er = FileGDBAPI::ErrorInfo::GetErrorDescription(hr, fgdb_error_desc_w);
+            const char* pszLikelyReason = "Might be due to unsupported spatial reference system. Using OpenFileGDB driver or FileGDB SDK >= 1.4 should solve it";
+            if ( er == S_OK )
+            {
+                std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
+                if( fgdb_error_desc == "FileGDB compression is not installed." )
+                {
+                    pszLikelyReason = "Using FileGDB SDK 1.4 or later should solve this issue.";
+                }
+            }
+
+            GDBErr(hr, "Error opening " + WStringToString(layers[i]),
+                   CE_Warning,
+                   (". Skipping it. " + CPLString(pszLikelyReason)).c_str());
+            continue;
+        }
+        FGdbLayer* pLayer = new FGdbLayer();
+        if (!pLayer->Initialize(this, pTable, layers[i], type))
+        {
+            delete pLayer;
+            return GDBErr(hr, "Error initializing OGRLayer for " + WStringToString(layers[i]));
+        }
+
+        m_layers.push_back(pLayer);
+    }
+    return true;
+}
+
+/************************************************************************/
+/*                            LoadLayers()                             */
+/************************************************************************/
+
+bool FGdbDataSource::LoadLayers(const std::wstring &root)
+{
+    std::vector<wstring> tables;
+    std::vector<wstring> featureclasses;
+    std::vector<wstring> featuredatasets;
+    fgdbError hr;
+
+    /* Find all the Tables in the root */
+    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Table", tables)) )
+    {
+        return GDBErr(hr, "Error reading Tables in " + WStringToString(root));
+    }
+    /* Open the tables we found */
+    if ( !tables.empty() && ! OpenFGDBTables(L"Table", tables) )
+        return false;
+
+    /* Find all the Feature Classes in the root */
+    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Class", featureclasses)) )
+    {
+        return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(root));
+    }
+    /* Open the tables we found */
+    if ( !featureclasses.empty() && ! OpenFGDBTables(L"Feature Class", featureclasses) )
+        return false;
+
+    /* Find all the Feature Datasets in the root */
+    if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(root, L"Feature Dataset", featuredatasets)) )
+    {
+        return GDBErr(hr, "Error reading Feature Datasets in " + WStringToString(root));
+    }
+    /* Look for Feature Classes inside the Feature Dataset */
+    for ( unsigned int i = 0; i < featuredatasets.size(); i++ )
+    {
+        if ( FAILED(hr = m_pGeodatabase->GetChildDatasets(featuredatasets[i], L"Feature Class", featureclasses)) )
+        {
+            return GDBErr(hr, "Error reading Feature Classes in " + WStringToString(featuredatasets[i]));
+        }
+        if ( !featureclasses.empty() && ! OpenFGDBTables(L"Feature Class", featureclasses) )
+            return false;
+    }
+    return true;
+}
+
+#if 0
+/************************************************************************/
+/*                            LoadLayersOld()                              */
+/************************************************************************/
+
+/* Old recursive LoadLayers. Removed in favor of simple one that only
+   looks at FeatureClasses and Tables. */
+
+// Flattens out hierarchical GDB structure.
+bool FGdbDataSource::LoadLayersOld(const std::vector<wstring> & datasetTypes,
+                                const wstring & parent)
+{
+    long hr = S_OK;
+
+    // I didn't find an API to give me the type of the dataset based on name - I am *not*
+    // parsing XML for something like this - in the meantime I can use this hack to see
+    // if the dataset had any children whatsoever - if so, then I won't attempt to open it
+    // otherwise, do attempt to do that
+
+    bool childrenFound = false;
+    bool errorsEncountered = false;
+
+    for (size_t dsTypeIndex = 0; dsTypeIndex < datasetTypes.size(); dsTypeIndex++)
+    {
+        std::vector<wstring> childDatasets;
+        m_pGeodatabase->GetChildDatasets( parent, datasetTypes[dsTypeIndex], childDatasets);
+
+        if (!childDatasets.empty())
+        {
+            //it is a container of other datasets
+
+            for (size_t childDatasetIndex = 0;
+                 childDatasetIndex < childDatasets.size();
+                 childDatasetIndex++)
+            {
+                childrenFound = true;
+
+                // do something with it
+                // For now, we just ignore dataset containers and only open the children
+                // std::wcout << datasetTypes[dsTypeIndex] << L" " << childDatasets[childDatasetIndex] << std::endl;
+
+                if (!LoadLayersOld(datasetTypes, childDatasets[childDatasetIndex]))
+                    errorsEncountered = true;
+            }
+        }
+    }
+
+    //it is a full fledged dataset itself without children - open it (except the root)
+
+    if ((!childrenFound) && parent != L"\\")
+    {
+        // wcout << "Opening " << parent << "...";
+        Table* pTable = new Table;
+        if (FAILED(hr = m_pGeodatabase->OpenTable(parent,*pTable)))
+        {
+            delete pTable;
+            return GDBErr(hr, "Error opening " + WStringToString(parent));
+        }
+
+        FGdbLayer* pLayer = new FGdbLayer;
+
+        //pLayer has ownership of the table pointer as soon Initialize is called
+        if (!pLayer->Initialize(this, pTable, parent))
+        {
+            delete pLayer;
+
+            return GDBErr(hr, "Error initializing OGRLayer for " +
+                          WStringToString(parent));
+        }
+
+        m_layers.push_back(pLayer);
+    }
+
+    return !errorsEncountered;
+}
+#endif
+
+/************************************************************************/
+/*                            DeleteLayer()                             */
+/************************************************************************/
+
+OGRErr FGdbDataSource::DeleteLayer( int iLayer )
+{
+    if( !m_bUpdate || m_pGeodatabase == NULL )
+        return OGRERR_FAILURE;
+
+    if( iLayer < 0 || iLayer >= static_cast<int>(m_layers.size()) )
+        return OGRERR_FAILURE;
+
+    FGdbLayer* poBaseLayer = m_layers[iLayer];
+
+    // Fetch FGDBAPI Table before deleting OGR layer object
+
+    //Table* pTable = poBaseLayer->GetTable();
+
+    std::string name = poBaseLayer->GetLayerDefn()->GetName();
+    std::wstring strPath = poBaseLayer->GetTablePath();
+    std::wstring strType = poBaseLayer->GetType();
+
+    // delete OGR layer
+    delete m_layers[iLayer];
+
+    //pTable = NULL; // OGR Layer had ownership of FGDB Table
+
+    m_layers.erase(m_layers.begin() + iLayer);
+
+    long hr;
+
+    if (FAILED(hr = m_pGeodatabase->Delete(strPath, strType)))
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                 "%s was not deleted however it has been closed", name.c_str());
+        GDBErr(hr, "Failed deleting dataset");
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int FGdbDataSource::TestCapability( const char * pszCap )
+{
+    if( EQUAL(pszCap,ODsCCreateLayer) )
+        return m_bUpdate;
+
+    else if( EQUAL(pszCap,ODsCDeleteLayer) )
+        return m_bUpdate;
+    else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
+        return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return m_bUpdate;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *FGdbDataSource::GetLayer( int iLayer )
+{
+    int count = static_cast<int>(m_layers.size());
+
+    if( iLayer < 0 || iLayer >= count )
+        return NULL;
+    else
+        return m_layers[iLayer];
+}
+
+/************************************************************************/
+/*                             ICreateLayer()                           */
+/*                                                                      */
+/* See FGdbLayer::Create for creation options                           */
+/************************************************************************/
+
+OGRLayer *
+FGdbDataSource::ICreateLayer( const char * pszLayerName,
+                              OGRSpatialReference *poSRS,
+                              OGRwkbGeometryType eType,
+                              char ** papszOptions )
+{
+    if( !m_bUpdate || m_pGeodatabase == NULL )
+        return NULL;
+
+    FGdbLayer* pLayer = new FGdbLayer();
+    if (!pLayer->Create(this, pszLayerName, poSRS, eType, papszOptions))
+    {
+        delete pLayer;
+        return NULL;
+    }
+
+    m_layers.push_back(pLayer);
+
+    return pLayer;
+}
+
+/************************************************************************/
+/*                   OGRFGdbSingleFeatureLayer                          */
+/************************************************************************/
+
+class OGRFGdbSingleFeatureLayer : public OGRLayer
+{
+  private:
+    char               *pszVal;
+    OGRFeatureDefn     *poFeatureDefn;
+    int                 iNextShapeId;
+
+  public:
+                        OGRFGdbSingleFeatureLayer( const char* pszLayerName,
+                                                   const char *pszVal );
+               virtual ~OGRFGdbSingleFeatureLayer();
+
+    virtual void        ResetReading() override { iNextShapeId = 0; }
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
+    virtual int         TestCapability( const char * ) override { return FALSE; }
+};
+
+/************************************************************************/
+/*                    OGRFGdbSingleFeatureLayer()                       */
+/************************************************************************/
+
+OGRFGdbSingleFeatureLayer::OGRFGdbSingleFeatureLayer(const char* pszLayerName,
+                                                     const char *pszValIn )
+{
+    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    SetDescription( poFeatureDefn->GetName() );
+    poFeatureDefn->Reference();
+    OGRFieldDefn oField( "FIELD_1", OFTString );
+    poFeatureDefn->AddFieldDefn( &oField );
+
+    iNextShapeId = 0;
+    pszVal = pszValIn ? CPLStrdup(pszValIn) : NULL;
+}
+
+/************************************************************************/
+/*                   ~OGRFGdbSingleFeatureLayer()                       */
+/************************************************************************/
+
+OGRFGdbSingleFeatureLayer::~OGRFGdbSingleFeatureLayer()
+{
+    if( poFeatureDefn != NULL )
+        poFeatureDefn->Release();
+    CPLFree(pszVal);
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature * OGRFGdbSingleFeatureLayer::GetNextFeature()
+{
+    if (iNextShapeId != 0)
+        return NULL;
+
+    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+    if (pszVal)
+        poFeature->SetField(0, pszVal);
+    poFeature->SetFID(iNextShapeId ++);
+    return poFeature;
+}
+
+/************************************************************************/
+/*                              ExecuteSQL()                            */
+/************************************************************************/
+
+OGRLayer * FGdbDataSource::ExecuteSQL( const char *pszSQLCommand,
+                                       OGRGeometry *poSpatialFilter,
+                                       const char *pszDialect )
+
+{
+    if( m_pConnection && m_pConnection->IsFIDHackInProgress() )
+    {
+        if( Close() )
+            ReOpen();
+    }
+    if( m_pGeodatabase == NULL )
+         return NULL;
+
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        m_layers[i]->EndBulkLoad();
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Use generic implementation for recognized dialects              */
+/* -------------------------------------------------------------------- */
+    if( IsGenericSQLDialect(pszDialect) )
+        return OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                          poSpatialFilter,
+                                          pszDialect );
+
+/* -------------------------------------------------------------------- */
+/*      Special case GetLayerDefinition                                 */
+/* -------------------------------------------------------------------- */
+    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerDefinition "))
+    {
+        FGdbLayer* poLayer = (FGdbLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerDefinition "));
+        if (poLayer)
+        {
+            char* pszVal = NULL;
+            poLayer->GetLayerXML(&pszVal);
+            OGRLayer* poRet = new OGRFGdbSingleFeatureLayer( "LayerDefinition", pszVal );
+            CPLFree(pszVal);
+            return poRet;
+        }
+        else
+            return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case GetLayerMetadata                                   */
+/* -------------------------------------------------------------------- */
+    if (STARTS_WITH_CI(pszSQLCommand, "GetLayerMetadata "))
+    {
+        FGdbLayer* poLayer = (FGdbLayer*) GetLayerByName(pszSQLCommand + strlen("GetLayerMetadata "));
+        if (poLayer)
+        {
+            char* pszVal = NULL;
+            poLayer->GetLayerMetadataXML(&pszVal);
+            OGRLayer* poRet = new OGRFGdbSingleFeatureLayer( "LayerMetadata", pszVal );
+            CPLFree(pszVal);
+            return poRet;
+        }
+        else
+            return NULL;
+    }
+
+    /* TODO: remove that workaround when the SDK has finally a decent */
+    /* SQL support ! */
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") && pszDialect == NULL )
+    {
+        CPLDebug("FGDB", "Support for SELECT is known to be partially "
+                         "non-compliant with FileGDB SDK API v1.2.\n"
+                         "So for now, we use default OGR SQL engine. "
+                         "Explicitly specify -dialect FileGDB\n"
+                         "to use the SQL engine from the FileGDB SDK API");
+        OGRLayer* poLayer = OGRDataSource::ExecuteSQL( pszSQLCommand,
+                                        poSpatialFilter,
+                                        pszDialect );
+        if( poLayer )
+            m_oSetSelectLayers.insert(poLayer);
+        return poLayer;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Run the SQL                                                     */
+/* -------------------------------------------------------------------- */
+    EnumRows* pEnumRows = new EnumRows;
+    long hr;
+    try
+    {
+        hr = m_pGeodatabase->ExecuteSQL(
+                                StringToWString(pszSQLCommand), true, *pEnumRows);
+    }
+    catch(...)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Exception occurred at executing '%s'. Application may "
+                  "become unstable", pszSQLCommand );
+        delete pEnumRows;
+        return NULL;
+    }
+
+    if (FAILED(hr))
+    {
+        GDBErr(hr, CPLSPrintf("Failed at executing '%s'", pszSQLCommand));
+        delete pEnumRows;
+        return NULL;
+    }
+
+    if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
+    {
+        OGRLayer* poLayer = new FGdbResultLayer(this, pszSQLCommand, pEnumRows);
+        m_oSetSelectLayers.insert(poLayer);
+        return poLayer;
+    }
+    else
+    {
+        delete pEnumRows;
+        return NULL;
+    }
+}
+
+/************************************************************************/
+/*                           ReleaseResultSet()                         */
+/************************************************************************/
+
+void FGdbDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
+{
+    if( poResultsSet )
+        m_oSetSelectLayers.erase(poResultsSet);
+    delete poResultsSet;
+}
+
+/************************************************************************/
+/*                      HasPerLayerCopyingForTransaction()              */
+/************************************************************************/
+
+int FGdbDataSource::HasPerLayerCopyingForTransaction()
+{
+    if( bPerLayerCopyingForTransaction >= 0 )
+        return bPerLayerCopyingForTransaction;
+#ifdef WIN32
+    bPerLayerCopyingForTransaction = FALSE;
+#else
+    bPerLayerCopyingForTransaction =
+        m_poOpenFileGDBDrv != NULL &&
+        CPLTestBool(CPLGetConfigOption("FGDB_PER_LAYER_COPYING_TRANSACTION", "TRUE"));
+#endif
+    return bPerLayerCopyingForTransaction;
+}
+
+/************************************************************************/
+/*                        SetSymlinkFlagOnAllLayers()                    */
+/************************************************************************/
+
+void FGdbDataSource::SetSymlinkFlagOnAllLayers()
+{
+    size_t count = m_layers.size();
+    for(size_t i = 0; i < count; ++i )
+    {
+        m_layers[i]->SetSymlinkFlag();
+    }
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
index b0cb957..0c08752 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbDriver.cpp
@@ -1,844 +1,856 @@
-/******************************************************************************
- * $Id: FGdbDriver.cpp 32833 2016-01-08 11:43:51Z rouault $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements FileGDB OGR driver.
- * Author:   Ragi Yaser Burhum, ragi at burhum.com
- *           Paul Ramsey, pramsey at cleverelephant.ca
- *
- ******************************************************************************
- * Copyright (c) 2010, Ragi Yaser Burhum
- * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
- * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_fgdb.h"
-#include "cpl_conv.h"
-#include "FGdbUtils.h"
-#include "cpl_multiproc.h"
-#include "ogrmutexeddatasource.h"
-
-CPL_CVSID("$Id: FGdbDriver.cpp 32833 2016-01-08 11:43:51Z rouault $");
-
-extern "C" void RegisterOGRFileGDB();
-
-/************************************************************************/
-/*                            FGdbDriver()                              */
-/************************************************************************/
-FGdbDriver::FGdbDriver(): OGRSFDriver(), hMutex(NULL)
-{
-}
-
-/************************************************************************/
-/*                            ~FGdbDriver()                             */
-/************************************************************************/
-FGdbDriver::~FGdbDriver()
-
-{
-    if( oMapConnections.size() != 0 )
-        CPLDebug("FileGDB", "Remaining %d connections. Bug?",
-                 (int)oMapConnections.size());
-    if( hMutex != NULL )
-        CPLDestroyMutex(hMutex);
-    hMutex = NULL;
-}
-
-
-/************************************************************************/
-/*                              GetName()                               */
-/************************************************************************/
-
-const char *FGdbDriver::GetName()
-
-{
-    return "FileGDB";
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
-
-{
-    // First check if we have to do any work.
-    size_t nLen = strlen(pszFilename);
-    if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) ||
-          (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) )
-        return NULL;
-
-    long hr;
-
-    /* Check that the filename is really a directory, to avoid confusion with */
-    /* Garmin MapSource - gdb format which can be a problem when the FileGDB */
-    /* driver is loaded as a plugin, and loaded before the GPSBabel driver */
-    /* (http://trac.osgeo.org/osgeo4w/ticket/245) */
-    VSIStatBuf stat;
-    if( CPLStat( pszFilename, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) )
-    {
-        return NULL;
-    }
-
-    CPLMutexHolderD(&hMutex);
-
-    FGdbDatabaseConnection* pConnection = oMapConnections[pszFilename];
-    if( pConnection != NULL )
-    {
-        if( pConnection->IsFIDHackInProgress() )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Cannot open geodatabase at the moment since it is in 'FID hack mode'");
-            return NULL;
-        }
-
-        pConnection->m_nRefCount ++;
-        CPLDebug("FileGDB", "ref_count of %s = %d now", pszFilename,
-                 pConnection->m_nRefCount);
-    }
-    else
-    {
-        Geodatabase* pGeoDatabase = new Geodatabase;
-        hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase);
-
-        if (FAILED(hr))
-        {
-            delete pGeoDatabase;
-            
-            if( OGRGetDriverByName("OpenFileGDB") != NULL && bUpdate == FALSE )
-            {
-                std::wstring fgdb_error_desc_w;
-                std::string fgdb_error_desc("Unknown error");
-                fgdbError er;
-                er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w);
-                if ( er == S_OK )
-                {
-                    fgdb_error_desc = WStringToString(fgdb_error_desc_w);
-                }
-                CPLDebug("FileGDB", "Cannot open %s with FileGDB driver: %s. Failing silently so OpenFileGDB can be tried",
-                         pszFilename,
-                         fgdb_error_desc.c_str());
-            }
-            else
-            {
-                GDBErr(hr, "Failed to open Geodatabase");
-            }
-            oMapConnections.erase(pszFilename);
-            return NULL;
-        }
-
-        CPLDebug("FileGDB", "Really opening %s", pszFilename);
-        pConnection = new FGdbDatabaseConnection(pszFilename, pGeoDatabase);
-        oMapConnections[pszFilename] = pConnection;
-    }
-
-    FGdbDataSource* pDS;
-
-    pDS = new FGdbDataSource(this, pConnection);
-
-    if(!pDS->Open( pszFilename, bUpdate, NULL ) )
-    {
-        delete pDS;
-        return NULL;
-    }
-    else
-    {
-        OGRMutexedDataSource* poMutexedDS =
-                new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
-        if( bUpdate )
-            return OGRCreateEmulatedTransactionDataSourceWrapper(poMutexedDS, this, TRUE, FALSE);
-        else
-            return poMutexedDS;
-    }
-}
-
-/***********************************************************************/
-/*                     CreateDataSource()                              */
-/***********************************************************************/
-
-OGRDataSource* FGdbDriver::CreateDataSource( const char * conn,
-                                           char **papszOptions)
-{
-    long hr;
-    Geodatabase *pGeodatabase;
-    std::wstring wconn = StringToWString(conn);
-    int bUpdate = TRUE; // If we're creating, we must be writing.
-    VSIStatBuf stat;
-
-    CPLMutexHolderD(&hMutex);
-
-    /* We don't support options yet, so warn if they send us some */
-    if ( papszOptions )
-    {
-        /* TODO: warning, ignoring options */
-    }
-
-    /* Only accept names of form "filename.gdb" and */
-    /* also .gdb.zip to be able to return FGDB with MapServer OGR output (#4199) */
-    const char* pszExt = CPLGetExtension(conn);
-    if ( !(EQUAL(pszExt,"gdb") || EQUAL(pszExt, "zip")) )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "FGDB data source name must use 'gdb' extension.\n" );
-        return NULL;
-    }
-
-    /* Don't try to create on top of something already there */
-    if( CPLStat( conn, &stat ) == 0 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s already exists.\n", conn );
-        return NULL;
-    }
-
-    /* Try to create the geodatabase */
-    pGeodatabase = new Geodatabase; // Create on heap so we can store it in the Datasource
-    hr = CreateGeodatabase(wconn, *pGeodatabase);
-
-    /* Handle creation errors */
-    if ( S_OK != hr )
-    {
-        const char *errstr = "Error creating geodatabase (%s).\n";
-        if ( hr == -2147220653 )
-            errstr = "File already exists (%s).\n";
-        delete pGeodatabase;
-        CPLError( CE_Failure, CPLE_AppDefined, errstr, conn );
-        return NULL;
-    }
-
-    FGdbDatabaseConnection* pConnection = new FGdbDatabaseConnection(conn, pGeodatabase);
-    oMapConnections[conn] = pConnection;
-
-    /* Ready to embed the Geodatabase in an OGR Datasource */
-    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
-    if ( ! pDS->Open(conn, bUpdate, NULL) )
-    {
-        delete pDS;
-        return NULL;
-    }
-    else
-        return OGRCreateEmulatedTransactionDataSourceWrapper(
-            new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE), this,
-            TRUE, FALSE);
-}
-
-/************************************************************************/
-/*                           StartTransaction()                         */
-/************************************************************************/
-
-OGRErr FGdbDriver::StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS)
-{
-    CPLMutexHolderOptionalLockD(hMutex);
-
-    bOutHasReopenedDS = FALSE;
-
-    OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut;
-    FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource();
-    if( !poDS->GetUpdate() )
-        return OGRERR_FAILURE;
-    FGdbDatabaseConnection* pConnection = poDS->GetConnection();
-    if( pConnection->GetRefCount() != 1 )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot start transaction as database is opened in another connection");
-        return OGRERR_FAILURE;
-    }
-    if( pConnection->IsLocked() )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Transaction is already in progress");
-        return OGRERR_FAILURE;
-    }
-
-    bOutHasReopenedDS = TRUE;
-
-    CPLString osName(poMutexedDS->GetName());
-    CPLString osNameOri(osName);
-    if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' )
-        osName.resize(osName.size()-1);
-
-#ifndef WIN32
-    int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
-#endif
-
-    pConnection->m_nRefCount ++;
-    delete poDSInOut;
-    poDSInOut = NULL;
-    poMutexedDS = NULL;
-    poDS = NULL;
-
-    pConnection->CloseGeodatabase();
-
-    CPLString osEditedName(osName);
-    osEditedName += ".ogredited";
-
-    CPLPushErrorHandler(CPLQuietErrorHandler);
-    CPL_IGNORE_RET_VAL(CPLUnlinkTree(osEditedName));
-    CPLPopErrorHandler();
-
-    OGRErr eErr = OGRERR_NONE;
-    
-    CPLString osDatabaseToReopen;
-#ifndef WIN32
-    if( bPerLayerCopyingForTransaction )
-    {
-        int bError = FALSE;
-        
-        if( VSIMkdir( osEditedName, 0755 ) != 0 )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, 
-                      "Cannot create directory '%s'.",
-                      osEditedName.c_str() );
-            bError = TRUE;
-        }
-
-        // Only copy a0000000X.Y files with X >= 1 && X <= 8, gdb and timestamps
-        // and symlink others
-        char** papszFiles = VSIReadDir(osName);
-        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
-        {
-            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
-                continue;
-            if( ((*papszIter)[0] == 'a' && atoi((*papszIter)+1) >= 1 &&
-                 atoi((*papszIter)+1) <= 8) || EQUAL(*papszIter, "gdb") ||
-                 EQUAL(*papszIter, "timestamps") )
-            {
-                if( CPLCopyFile(CPLFormFilename(osEditedName, *papszIter, NULL),
-                                CPLFormFilename(osName, *papszIter, NULL)) != 0 )
-                {
-                    bError = TRUE;
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Cannot copy %s", *papszIter);
-                }
-            }
-            else
-            {
-                CPLString osSourceFile;
-                if( CPLIsFilenameRelative(osName) )
-                    osSourceFile = CPLFormFilename(CPLSPrintf("../%s", CPLGetFilename(osName.c_str())), *papszIter, NULL);
-                else
-                    osSourceFile = osName;
-                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
-                    CPLSymlink( osSourceFile,
-                                CPLFormFilename(osEditedName.c_str(), *papszIter, NULL),
-                                NULL ) != 0 )
-                {
-                    bError = TRUE;
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Cannot symlink %s", *papszIter);
-                }
-            }
-        }
-        CSLDestroy(papszFiles);
-
-        if( bError )
-        {
-            eErr = OGRERR_FAILURE;
-            osDatabaseToReopen = osName;
-        }
-        else
-            osDatabaseToReopen = osEditedName;
-    }
-    else
-#endif
-    {
-        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
-            CPLCopyTree( osEditedName, osName ) != 0 )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                    "Cannot backup geodatabase");
-            eErr = OGRERR_FAILURE;
-            osDatabaseToReopen = osName;
-        }
-        else
-            osDatabaseToReopen = osEditedName;
-    }
-
-    pConnection->m_pGeodatabase = new Geodatabase;
-    long hr = ::OpenGeodatabase(StringToWString(osDatabaseToReopen), *(pConnection->m_pGeodatabase));
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || FAILED(hr))
-    {
-        delete pConnection->m_pGeodatabase;
-        pConnection->m_pGeodatabase = NULL;
-        Release(osName);
-        GDBErr(hr, CPLSPrintf("Failed to open %s. Dataset should be closed",
-                              osDatabaseToReopen.c_str()));
-
-        return OGRERR_FAILURE;
-    }
-
-    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
-    pDS->Open(osDatabaseToReopen, TRUE, osNameOri);
-
-#ifndef WIN32
-    if( eErr == OGRERR_NONE && bPerLayerCopyingForTransaction )
-    {
-        pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
-        pDS->SetSymlinkFlagOnAllLayers();
-    }
-#endif
-
-    poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
-
-    if( eErr == OGRERR_NONE )
-        pConnection->SetLocked(TRUE);
-    return eErr;
-}
-
-/************************************************************************/
-/*                           CommitTransaction()                        */
-/************************************************************************/
-
-OGRErr FGdbDriver::CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS)
-{
-    CPLMutexHolderOptionalLockD(hMutex);
-
-    bOutHasReopenedDS = FALSE;
-
-
-    OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut;
-    FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource();
-    FGdbDatabaseConnection* pConnection = poDS->GetConnection();
-    if( !pConnection->IsLocked() )
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "No transaction in progress");
-        return OGRERR_FAILURE;
-    }
-
-    bOutHasReopenedDS = TRUE;
-
-    CPLString osName(poMutexedDS->GetName());
-    CPLString osNameOri(osName);
-    if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' )
-        osName.resize(osName.size()-1);
-
-#ifndef WIN32
-    int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
-#endif
-
-    pConnection->m_nRefCount ++;
-    delete poDSInOut;
-    poDSInOut = NULL;
-    poMutexedDS = NULL;
-    poDS = NULL;
-
-    pConnection->CloseGeodatabase();
-
-    CPLString osEditedName(osName);
-    osEditedName += ".ogredited";
-    
-#ifndef WIN32
-    if( bPerLayerCopyingForTransaction )
-    {
-        int bError = FALSE;
-        char** papszFiles;
-        std::vector<CPLString> aosTmpFilesToClean;
-        
-        // Check for files present in original copy that are not in edited copy
-        // That is to say deleted layers
-        papszFiles = VSIReadDir(osName);
-        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
-        {
-            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
-                continue;
-            VSIStatBufL sStat;
-            if( (*papszIter)[0] == 'a' &&
-                VSIStatL( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 )
-            {
-                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
-                    VSIRename( CPLFormFilename(osName, *papszIter, NULL),
-                               CPLFormFilename(osName, *papszIter, "tmp") ) != 0 )
-                {
-                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s",
-                             CPLFormFilename(osName, *papszIter, NULL),
-                             CPLFormFilename(osName, *papszIter, "tmp"));
-                    bError = TRUE;
-                }
-                else
-                    aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp"));
-            }
-        }
-        CSLDestroy(papszFiles);
-
-        // Move modified files from edited directory to main directory
-        papszFiles = VSIReadDir(osEditedName);
-        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
-        {
-            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
-                continue;
-            struct stat sStat;
-            if( lstat( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 )
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "Cannot stat %s",
-                         CPLFormFilename(osEditedName, *papszIter, NULL));
-                bError = TRUE;
-            }
-            else if( !S_ISLNK(sStat.st_mode) )
-            {
-                // If there was such a file in original directory, first rename it
-                // as a temporary file
-                if( lstat( CPLFormFilename(osName, *papszIter, NULL), &sStat ) == 0 )
-                {
-                    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || 
-                        VSIRename( CPLFormFilename(osName, *papszIter, NULL),
-                                   CPLFormFilename(osName, *papszIter, "tmp") ) != 0 )
-                    {
-                        CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s",
-                                 CPLFormFilename(osName, *papszIter, NULL),
-                                 CPLFormFilename(osName, *papszIter, "tmp"));
-                        bError = TRUE;
-                    }
-                    else
-                        aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp"));
-                }
-                if( !bError )
-                {
-                    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || 
-                        CPLMoveFile( CPLFormFilename(osName, *papszIter, NULL),
-                                     CPLFormFilename(osEditedName, *papszIter, NULL) ) != 0 )
-                    {
-                        CPLError(CE_Failure, CPLE_AppDefined, "Cannot move %s to %s",
-                                 CPLFormFilename(osEditedName, *papszIter, NULL),
-                                 CPLFormFilename(osName, *papszIter, NULL));
-                        bError = TRUE;
-                    }
-                    else
-                        CPLDebug("FileGDB", "Move %s to %s",
-                                 CPLFormFilename(osEditedName, *papszIter, NULL),
-                                 CPLFormFilename(osName, *papszIter, NULL));
-                }
-            }
-        }
-        CSLDestroy(papszFiles);
-
-        if( !bError )
-        {
-            for(size_t i=0;i<aosTmpFilesToClean.size();i++)
-            {
-                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE4") || 
-                    VSIUnlink(aosTmpFilesToClean[i]) != 0 )
-                {
-                    CPLError(CE_Warning, CPLE_AppDefined,
-                             "Cannot remove %s. Manual cleanup required", aosTmpFilesToClean[i].c_str());
-                }
-            }
-        }
-
-        if( bError )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "An error occurred while moving files from %s back to %s. "
-                     "Manual cleaning must be done and dataset should be closed",
-                     osEditedName.c_str(),
-                     osName.c_str());
-            pConnection->SetLocked(FALSE);
-            Release(osName);
-            return OGRERR_FAILURE;
-        }
-        else if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE5") || 
-                 CPLUnlinkTree(osEditedName) != 0 )
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                    "Cannot remove %s. Manual cleanup required", osEditedName.c_str());
-        }
-    }
-    else
-#endif
-    {
-        CPLString osTmpName(osName);
-        osTmpName += ".ogrtmp";
-        
-        /* Install the backup copy as the main database in 3 steps : */
-        /* first rename the main directory  in .tmp */
-        /* then rename the edited copy under regular name */
-        /* and finally dispose the .tmp directory */
-        /* That way there's no risk definitely losing data */
-        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
-            VSIRename(osName, osTmpName) != 0 )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                    "Cannot rename %s to %s. Edited database during transaction is in %s"
-                    "Dataset should be closed",
-                    osName.c_str(), osTmpName.c_str(), osEditedName.c_str());
-            pConnection->SetLocked(FALSE);
-            Release(osName);
-            return OGRERR_FAILURE;
-        }
-        
-        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || 
-            VSIRename(osEditedName, osName) != 0 )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                    "Cannot rename %s to %s. The original geodatabase is in '%s'. "
-                    "Dataset should be closed",
-                    osEditedName.c_str(), osName.c_str(), osTmpName.c_str());
-            pConnection->SetLocked(FALSE);
-            Release(osName);
-            return OGRERR_FAILURE;
-        }
-
-        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || 
-            CPLUnlinkTree(osTmpName) != 0 )
-        {
-            CPLError(CE_Warning, CPLE_AppDefined,
-                    "Cannot remove %s. Manual cleanup required", osTmpName.c_str());
-        }
-    }
-
-    pConnection->m_pGeodatabase = new Geodatabase;
-    long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase));
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE_REOPEN") || FAILED(hr))
-    {
-        delete pConnection->m_pGeodatabase;
-        pConnection->m_pGeodatabase = NULL;
-        pConnection->SetLocked(FALSE);
-        Release(osName);
-        GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed");
-        return OGRERR_FAILURE;
-    }
-
-    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
-    pDS->Open(osNameOri, TRUE, NULL);
-    //pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
-    poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
-
-    pConnection->SetLocked(FALSE);
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           RollbackTransaction()                      */
-/************************************************************************/
-
-OGRErr FGdbDriver::RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS)
-{
-    CPLMutexHolderOptionalLockD(hMutex);
-
-    bOutHasReopenedDS = FALSE;
-
-    OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut;
-    FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource();
-    FGdbDatabaseConnection* pConnection = poDS->GetConnection();
-    if( !pConnection->IsLocked() )
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "No transaction in progress");
-        return OGRERR_FAILURE;
-    }
-
-    bOutHasReopenedDS = TRUE;
-
-    CPLString osName(poMutexedDS->GetName());
-    CPLString osNameOri(osName);
-    if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' )
-        osName.resize(osName.size()-1);
-
-    //int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
-
-    pConnection->m_nRefCount ++;
-    delete poDSInOut;
-    poDSInOut = NULL;
-    poMutexedDS = NULL;
-    poDS = NULL;
-
-    pConnection->CloseGeodatabase();
-
-    CPLString osEditedName(osName);
-    osEditedName += ".ogredited";
-
-    OGRErr eErr = OGRERR_NONE;
-    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || 
-        CPLUnlinkTree(osEditedName) != 0 )
-    {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                 "Cannot remove %s. Manual cleanup required", osEditedName.c_str());
-        eErr = OGRERR_FAILURE;
-    }
-
-    pConnection->m_pGeodatabase = new Geodatabase;
-    long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase));
-    if (EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") ||
-        FAILED(hr))
-    {
-        delete pConnection->m_pGeodatabase;
-        pConnection->m_pGeodatabase = NULL;
-        pConnection->SetLocked(FALSE);
-        Release(osName);
-        GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed");
-        return OGRERR_FAILURE;
-    }
-
-    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
-    pDS->Open(osNameOri, TRUE, NULL);
-    //pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
-    poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
-
-    pConnection->SetLocked(FALSE);
-
-    return eErr;
-}
-
-/***********************************************************************/
-/*                            Release()                                */
-/***********************************************************************/
-
-void FGdbDriver::Release(const char* pszName)
-{
-    CPLMutexHolderOptionalLockD(hMutex);
-
-    FGdbDatabaseConnection* pConnection = oMapConnections[pszName];
-    if( pConnection != NULL )
-    {
-        pConnection->m_nRefCount --;
-        CPLDebug("FileGDB", "ref_count of %s = %d now", pszName,
-                 pConnection->m_nRefCount);
-        if( pConnection->m_nRefCount == 0 )
-        {
-            pConnection->CloseGeodatabase();
-            delete pConnection;
-            oMapConnections.erase(pszName);
-        }
-    }
-}
-
-/***********************************************************************/
-/*                         CloseGeodatabase()                          */
-/***********************************************************************/
-
-void FGdbDatabaseConnection::CloseGeodatabase()
-{
-    if( m_pGeodatabase != NULL )
-    {
-        CPLDebug("FileGDB", "Really closing %s now", m_osName.c_str());
-        ::CloseGeodatabase(*m_pGeodatabase);
-        delete m_pGeodatabase;
-        m_pGeodatabase = NULL;
-    }
-}
-
-/***********************************************************************/
-/*                         OpenGeodatabase()                           */
-/***********************************************************************/
-
-int FGdbDatabaseConnection::OpenGeodatabase(const char* pszFSName)
-{
-    m_pGeodatabase = new Geodatabase;
-    long hr = ::OpenGeodatabase(StringToWString(CPLString(pszFSName)), *m_pGeodatabase);
-    if (FAILED(hr))
-    {
-        delete m_pGeodatabase;
-        m_pGeodatabase = NULL;
-        return FALSE;
-    }
-    return TRUE;
-}
-
-/***********************************************************************/
-/*                         TestCapability()                            */
-/***********************************************************************/
-
-int FGdbDriver::TestCapability( const char * pszCap )
-{
-    if (EQUAL(pszCap, ODrCCreateDataSource) )
-        return TRUE;
-
-    else if (EQUAL(pszCap, ODrCDeleteDataSource) )
-        return TRUE;
-
-    return FALSE;
-}
-/************************************************************************/
-/*                          DeleteDataSource()                          */
-/************************************************************************/
-
-OGRErr FGdbDriver::DeleteDataSource( const char *pszDataSource )
-{
-    CPLMutexHolderD(&hMutex);
-
-    std::wstring wstr = StringToWString(pszDataSource);
-
-    long hr;
-
-    if (S_OK != (hr = ::DeleteGeodatabase(wstr)))
-    {
-        GDBErr(hr, "Failed to delete Geodatabase");
-        return OGRERR_FAILURE;
-    }
-
-    return OGRERR_NONE;
-}
-
-/***********************************************************************/
-/*                       RegisterOGRFileGDB()                          */
-/***********************************************************************/
-
-void RegisterOGRFileGDB()
-
-{
-    if (! GDAL_CHECK_VERSION("OGR FGDB"))
-        return;
-
-    OGRSFDriver* poDriver = new FGdbDriver;
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                "ESRI FileGDB" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gdb" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_filegdb.html" );
-
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-                               "<CreationOptionList/>" );
-
-    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
-"<LayerCreationOptionList>"
-"  <Option name='FEATURE_DATASET' type='string' description='FeatureDataset folder into to put the new layer'/>"
-"  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column' default='SHAPE'/>"
-"  <Option name='GEOMETRY_NULLABLE' type='boolean' description='Whether the values of the geometry column can be NULL' default='YES'/>"
-"  <Option name='FID' type='string' description='Name of OID column' default='OBJECTID' deprecated_alias='OID_NAME'/>"
-"  <Option name='XYTOLERANCE' type='float' description='Snapping tolerance, used for advanced ArcGIS features like network and topology rules, on 2D coordinates, in the units of the CRS'/>"
-"  <Option name='ZTOLERANCE' type='float' description='Snapping tolerance, used for advanced ArcGIS features like network and topology rules, on Z coordinates, in the units of the CRS'/>"
-"  <Option name='XORIGIN' type='float' description='X origin of the coordinate precision grid'/>"
-"  <Option name='YORIGIN' type='float' description='Y origin of the coordinate precision grid'/>"
-"  <Option name='ZORIGIN' type='float' description='Z origin of the coordinate precision grid'/>"
-"  <Option name='XYSCALE' type='float' description='X,Y scale of the coordinate precision grid'/>"
-"  <Option name='ZSCALE' type='float' description='Z scale of the coordinate precision grid'/>"
-"  <Option name='XML_DEFINITION' type='string' description='XML definition to create the new table. The root node of such a XML definition must be a <esri:DataElement> element conformant to FileGDBAPI.xsd'/>"
-"  <Option name='CREATE_MULTIPATCH' type='boolean' description='Whether to write geometries of layers of type MultiPolygon as MultiPatch' default='NO'/>"
-"  <Option name='COLUMN_TYPES' type='string' description='A list of strings of format field_name=fgdb_filed_type (separated by comma) to force the FileGDB column type of fields to be created'/>"
-"  <Option name='CONFIGURATION_KEYWORD' type='string-select' description='Customize how data is stored. By default text in UTF-8 and data up to 1TB'>"
-"    <Value>DEFAULTS</Value>"
-"    <Value>TEXT_UTF16</Value>"
-"    <Value>MAX_FILE_SIZE_4GB</Value>"
-"    <Value>MAX_FILE_SIZE_256TB</Value>"
-"    <Value>GEOMETRY_OUTOFLINE</Value>"
-"    <Value>BLOB_OUTOFLINE</Value>"
-"    <Value>GEOMETRY_AND_BLOB_OUTOFLINE</Value>"
-"  </Option>"
-"</LayerCreationOptionList>");
-
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
-                               "Integer Real String Date DateTime Binary" );
-    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
-    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
-
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
-}
-
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements FileGDB OGR driver.
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *           Paul Ramsey, pramsey at cleverelephant.ca
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Ragi Yaser Burhum
+ * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_fgdb.h"
+#include "cpl_conv.h"
+#include "FGdbUtils.h"
+#include "cpl_multiproc.h"
+#include "ogrmutexeddatasource.h"
+
+CPL_CVSID("$Id: FGdbDriver.cpp 36981 2016-12-20 19:46:41Z rouault $");
+
+extern "C" void RegisterOGRFileGDB();
+
+/************************************************************************/
+/*                            FGdbDriver()                              */
+/************************************************************************/
+FGdbDriver::FGdbDriver(): OGRSFDriver(), hMutex(NULL)
+{
+}
+
+/************************************************************************/
+/*                            ~FGdbDriver()                             */
+/************************************************************************/
+FGdbDriver::~FGdbDriver()
+
+{
+    if( !oMapConnections.empty() )
+        CPLDebug("FileGDB", "Remaining %d connections. Bug?",
+                 (int)oMapConnections.size());
+    if( hMutex != NULL )
+        CPLDestroyMutex(hMutex);
+    hMutex = NULL;
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *FGdbDriver::GetName()
+
+{
+    return "FileGDB";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
+
+{
+    // First check if we have to do any work.
+    size_t nLen = strlen(pszFilename);
+    if( nLen == 1 && pszFilename[0] == '.' )
+    {
+        char* pszCurrentDir = CPLGetCurrentDir();
+        if( pszCurrentDir )
+        {
+            size_t nLen2 = strlen(pszCurrentDir);
+            bool bOK = (nLen2 >= 4 && EQUAL(pszCurrentDir + nLen2 - 4, ".gdb"));
+            CPLFree(pszCurrentDir);
+            if( !bOK )
+                return NULL;
+        }
+        else
+        {
+            return NULL;
+        }
+    }
+    else if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) ||
+               (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) )
+        return NULL;
+
+    long hr;
+
+    /* Check that the filename is really a directory, to avoid confusion with */
+    /* Garmin MapSource - gdb format which can be a problem when the FileGDB */
+    /* driver is loaded as a plugin, and loaded before the GPSBabel driver */
+    /* (http://trac.osgeo.org/osgeo4w/ticket/245) */
+    VSIStatBuf stat;
+    if( CPLStat( pszFilename, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) )
+    {
+        return NULL;
+    }
+
+    CPLMutexHolderD(&hMutex);
+
+    FGdbDatabaseConnection* pConnection = oMapConnections[pszFilename];
+    if( pConnection != NULL )
+    {
+        if( pConnection->IsFIDHackInProgress() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot open geodatabase at the moment since it is in 'FID hack mode'");
+            return NULL;
+        }
+
+        pConnection->m_nRefCount ++;
+        CPLDebug("FileGDB", "ref_count of %s = %d now", pszFilename,
+                 pConnection->m_nRefCount);
+    }
+    else
+    {
+        Geodatabase* pGeoDatabase = new Geodatabase;
+        hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase);
+
+        if (FAILED(hr))
+        {
+            delete pGeoDatabase;
+
+            if( OGRGetDriverByName("OpenFileGDB") != NULL && bUpdate == FALSE )
+            {
+                std::wstring fgdb_error_desc_w;
+                std::string fgdb_error_desc("Unknown error");
+                fgdbError er;
+                er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w);
+                if ( er == S_OK )
+                {
+                    fgdb_error_desc = WStringToString(fgdb_error_desc_w);
+                }
+                CPLDebug("FileGDB", "Cannot open %s with FileGDB driver: %s. Failing silently so OpenFileGDB can be tried",
+                         pszFilename,
+                         fgdb_error_desc.c_str());
+            }
+            else
+            {
+                GDBErr(hr, "Failed to open Geodatabase");
+            }
+            oMapConnections.erase(pszFilename);
+            return NULL;
+        }
+
+        CPLDebug("FileGDB", "Really opening %s", pszFilename);
+        pConnection = new FGdbDatabaseConnection(pszFilename, pGeoDatabase);
+        oMapConnections[pszFilename] = pConnection;
+    }
+
+    FGdbDataSource* pDS;
+
+    pDS = new FGdbDataSource(this, pConnection);
+
+    if(!pDS->Open( pszFilename, bUpdate, NULL ) )
+    {
+        delete pDS;
+        return NULL;
+    }
+    else
+    {
+        OGRMutexedDataSource* poMutexedDS =
+                new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
+        if( bUpdate )
+            return OGRCreateEmulatedTransactionDataSourceWrapper(poMutexedDS, this, TRUE, FALSE);
+        else
+            return poMutexedDS;
+    }
+}
+
+/***********************************************************************/
+/*                     CreateDataSource()                              */
+/***********************************************************************/
+
+OGRDataSource* FGdbDriver::CreateDataSource( const char * conn,
+                                           char **papszOptions)
+{
+    long hr;
+    Geodatabase *pGeodatabase;
+    std::wstring wconn = StringToWString(conn);
+    int bUpdate = TRUE; // If we're creating, we must be writing.
+    VSIStatBuf stat;
+
+    CPLMutexHolderD(&hMutex);
+
+    /* We don't support options yet, so warn if they send us some */
+    if ( papszOptions )
+    {
+        /* TODO: warning, ignoring options */
+    }
+
+    /* Only accept names of form "filename.gdb" and */
+    /* also .gdb.zip to be able to return FGDB with MapServer OGR output (#4199) */
+    const char* pszExt = CPLGetExtension(conn);
+    if ( !(EQUAL(pszExt,"gdb") || EQUAL(pszExt, "zip")) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "FGDB data source name must use 'gdb' extension.\n" );
+        return NULL;
+    }
+
+    /* Don't try to create on top of something already there */
+    if( CPLStat( conn, &stat ) == 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "%s already exists.\n", conn );
+        return NULL;
+    }
+
+    /* Try to create the geodatabase */
+    pGeodatabase = new Geodatabase; // Create on heap so we can store it in the Datasource
+    hr = CreateGeodatabase(wconn, *pGeodatabase);
+
+    /* Handle creation errors */
+    if ( S_OK != hr )
+    {
+        const char *errstr = "Error creating geodatabase (%s).\n";
+        if ( hr == -2147220653 )
+            errstr = "File already exists (%s).\n";
+        delete pGeodatabase;
+        CPLError( CE_Failure, CPLE_AppDefined, errstr, conn );
+        return NULL;
+    }
+
+    FGdbDatabaseConnection* pConnection = new FGdbDatabaseConnection(conn, pGeodatabase);
+    oMapConnections[conn] = pConnection;
+
+    /* Ready to embed the Geodatabase in an OGR Datasource */
+    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
+    if ( ! pDS->Open(conn, bUpdate, NULL) )
+    {
+        delete pDS;
+        return NULL;
+    }
+    else
+        return OGRCreateEmulatedTransactionDataSourceWrapper(
+            new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE), this,
+            TRUE, FALSE);
+}
+
+/************************************************************************/
+/*                           StartTransaction()                         */
+/************************************************************************/
+
+OGRErr FGdbDriver::StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS)
+{
+    CPLMutexHolderOptionalLockD(hMutex);
+
+    bOutHasReopenedDS = FALSE;
+
+    OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut;
+    FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource();
+    if( !poDS->GetUpdate() )
+        return OGRERR_FAILURE;
+    FGdbDatabaseConnection* pConnection = poDS->GetConnection();
+    if( pConnection->GetRefCount() != 1 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot start transaction as database is opened in another connection");
+        return OGRERR_FAILURE;
+    }
+    if( pConnection->IsLocked() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Transaction is already in progress");
+        return OGRERR_FAILURE;
+    }
+
+    bOutHasReopenedDS = TRUE;
+
+    CPLString osName(poMutexedDS->GetName());
+    CPLString osNameOri(osName);
+    if( osName.back()== '/' || osName.back()== '\\' )
+        osName.resize(osName.size()-1);
+
+#ifndef WIN32
+    int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
+#endif
+
+    pConnection->m_nRefCount ++;
+    delete poDSInOut;
+    poDSInOut = NULL;
+    poMutexedDS = NULL;
+    poDS = NULL;
+
+    pConnection->CloseGeodatabase();
+
+    CPLString osEditedName(osName);
+    osEditedName += ".ogredited";
+
+    CPLPushErrorHandler(CPLQuietErrorHandler);
+    CPL_IGNORE_RET_VAL(CPLUnlinkTree(osEditedName));
+    CPLPopErrorHandler();
+
+    OGRErr eErr = OGRERR_NONE;
+
+    CPLString osDatabaseToReopen;
+#ifndef WIN32
+    if( bPerLayerCopyingForTransaction )
+    {
+        int bError = FALSE;
+
+        if( VSIMkdir( osEditedName, 0755 ) != 0 )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Cannot create directory '%s'.",
+                      osEditedName.c_str() );
+            bError = TRUE;
+        }
+
+        // Only copy a0000000X.Y files with X >= 1 && X <= 8, gdb and timestamps
+        // and symlink others
+        char** papszFiles = VSIReadDir(osName);
+        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
+        {
+            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
+                continue;
+            if( ((*papszIter)[0] == 'a' && atoi((*papszIter)+1) >= 1 &&
+                 atoi((*papszIter)+1) <= 8) || EQUAL(*papszIter, "gdb") ||
+                 EQUAL(*papszIter, "timestamps") )
+            {
+                if( CPLCopyFile(CPLFormFilename(osEditedName, *papszIter, NULL),
+                                CPLFormFilename(osName, *papszIter, NULL)) != 0 )
+                {
+                    bError = TRUE;
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot copy %s", *papszIter);
+                }
+            }
+            else
+            {
+                CPLString osSourceFile;
+                if( CPLIsFilenameRelative(osName) )
+                    osSourceFile = CPLFormFilename(CPLSPrintf("../%s", CPLGetFilename(osName.c_str())), *papszIter, NULL);
+                else
+                    osSourceFile = osName;
+                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
+                    CPLSymlink( osSourceFile,
+                                CPLFormFilename(osEditedName.c_str(), *papszIter, NULL),
+                                NULL ) != 0 )
+                {
+                    bError = TRUE;
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot symlink %s", *papszIter);
+                }
+            }
+        }
+        CSLDestroy(papszFiles);
+
+        if( bError )
+        {
+            eErr = OGRERR_FAILURE;
+            osDatabaseToReopen = osName;
+        }
+        else
+            osDatabaseToReopen = osEditedName;
+    }
+    else
+#endif
+    {
+        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
+            CPLCopyTree( osEditedName, osName ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot backup geodatabase");
+            eErr = OGRERR_FAILURE;
+            osDatabaseToReopen = osName;
+        }
+        else
+            osDatabaseToReopen = osEditedName;
+    }
+
+    pConnection->m_pGeodatabase = new Geodatabase;
+    long hr = ::OpenGeodatabase(StringToWString(osDatabaseToReopen), *(pConnection->m_pGeodatabase));
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || FAILED(hr))
+    {
+        delete pConnection->m_pGeodatabase;
+        pConnection->m_pGeodatabase = NULL;
+        Release(osName);
+        GDBErr(hr, CPLSPrintf("Failed to open %s. Dataset should be closed",
+                              osDatabaseToReopen.c_str()));
+
+        return OGRERR_FAILURE;
+    }
+
+    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
+    pDS->Open(osDatabaseToReopen, TRUE, osNameOri);
+
+#ifndef WIN32
+    if( eErr == OGRERR_NONE && bPerLayerCopyingForTransaction )
+    {
+        pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
+        pDS->SetSymlinkFlagOnAllLayers();
+    }
+#endif
+
+    poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
+
+    if( eErr == OGRERR_NONE )
+        pConnection->SetLocked(TRUE);
+    return eErr;
+}
+
+/************************************************************************/
+/*                           CommitTransaction()                        */
+/************************************************************************/
+
+OGRErr FGdbDriver::CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS)
+{
+    CPLMutexHolderOptionalLockD(hMutex);
+
+    bOutHasReopenedDS = FALSE;
+
+    OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut;
+    FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource();
+    FGdbDatabaseConnection* pConnection = poDS->GetConnection();
+    if( !pConnection->IsLocked() )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "No transaction in progress");
+        return OGRERR_FAILURE;
+    }
+
+    bOutHasReopenedDS = TRUE;
+
+    CPLString osName(poMutexedDS->GetName());
+    CPLString osNameOri(osName);
+    if( osName.back()== '/' || osName.back()== '\\' )
+        osName.resize(osName.size()-1);
+
+#ifndef WIN32
+    int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
+#endif
+
+    pConnection->m_nRefCount ++;
+    delete poDSInOut;
+    poDSInOut = NULL;
+    poMutexedDS = NULL;
+    poDS = NULL;
+
+    pConnection->CloseGeodatabase();
+
+    CPLString osEditedName(osName);
+    osEditedName += ".ogredited";
+
+#ifndef WIN32
+    if( bPerLayerCopyingForTransaction )
+    {
+        int bError = FALSE;
+        char** papszFiles;
+        std::vector<CPLString> aosTmpFilesToClean;
+
+        // Check for files present in original copy that are not in edited copy
+        // That is to say deleted layers
+        papszFiles = VSIReadDir(osName);
+        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
+        {
+            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
+                continue;
+            VSIStatBufL sStat;
+            if( (*papszIter)[0] == 'a' &&
+                VSIStatL( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 )
+            {
+                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
+                    VSIRename( CPLFormFilename(osName, *papszIter, NULL),
+                               CPLFormFilename(osName, *papszIter, "tmp") ) != 0 )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s",
+                             CPLFormFilename(osName, *papszIter, NULL),
+                             CPLFormFilename(osName, *papszIter, "tmp"));
+                    bError = TRUE;
+                }
+                else
+                    aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp"));
+            }
+        }
+        CSLDestroy(papszFiles);
+
+        // Move modified files from edited directory to main directory
+        papszFiles = VSIReadDir(osEditedName);
+        for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter)
+        {
+            if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
+                continue;
+            struct stat sStat;
+            if( lstat( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Cannot stat %s",
+                         CPLFormFilename(osEditedName, *papszIter, NULL));
+                bError = TRUE;
+            }
+            else if( !S_ISLNK(sStat.st_mode) )
+            {
+                // If there was such a file in original directory, first rename it
+                // as a temporary file
+                if( lstat( CPLFormFilename(osName, *papszIter, NULL), &sStat ) == 0 )
+                {
+                    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") ||
+                        VSIRename( CPLFormFilename(osName, *papszIter, NULL),
+                                   CPLFormFilename(osName, *papszIter, "tmp") ) != 0 )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s",
+                                 CPLFormFilename(osName, *papszIter, NULL),
+                                 CPLFormFilename(osName, *papszIter, "tmp"));
+                        bError = TRUE;
+                    }
+                    else
+                        aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp"));
+                }
+                if( !bError )
+                {
+                    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") ||
+                        CPLMoveFile( CPLFormFilename(osName, *papszIter, NULL),
+                                     CPLFormFilename(osEditedName, *papszIter, NULL) ) != 0 )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined, "Cannot move %s to %s",
+                                 CPLFormFilename(osEditedName, *papszIter, NULL),
+                                 CPLFormFilename(osName, *papszIter, NULL));
+                        bError = TRUE;
+                    }
+                    else
+                        CPLDebug("FileGDB", "Move %s to %s",
+                                 CPLFormFilename(osEditedName, *papszIter, NULL),
+                                 CPLFormFilename(osName, *papszIter, NULL));
+                }
+            }
+        }
+        CSLDestroy(papszFiles);
+
+        if( !bError )
+        {
+            for(size_t i=0;i<aosTmpFilesToClean.size();i++)
+            {
+                if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE4") ||
+                    VSIUnlink(aosTmpFilesToClean[i]) != 0 )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Cannot remove %s. Manual cleanup required", aosTmpFilesToClean[i].c_str());
+                }
+            }
+        }
+
+        if( bError )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "An error occurred while moving files from %s back to %s. "
+                     "Manual cleaning must be done and dataset should be closed",
+                     osEditedName.c_str(),
+                     osName.c_str());
+            pConnection->SetLocked(FALSE);
+            Release(osName);
+            return OGRERR_FAILURE;
+        }
+        else if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE5") ||
+                 CPLUnlinkTree(osEditedName) != 0 )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "Cannot remove %s. Manual cleanup required", osEditedName.c_str());
+        }
+    }
+    else
+#endif
+    {
+        CPLString osTmpName(osName);
+        osTmpName += ".ogrtmp";
+
+        /* Install the backup copy as the main database in 3 steps : */
+        /* first rename the main directory  in .tmp */
+        /* then rename the edited copy under regular name */
+        /* and finally dispose the .tmp directory */
+        /* That way there's no risk definitely losing data */
+        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
+            VSIRename(osName, osTmpName) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot rename %s to %s. Edited database during transaction is in %s"
+                    "Dataset should be closed",
+                    osName.c_str(), osTmpName.c_str(), osEditedName.c_str());
+            pConnection->SetLocked(FALSE);
+            Release(osName);
+            return OGRERR_FAILURE;
+        }
+
+        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") ||
+            VSIRename(osEditedName, osName) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot rename %s to %s. The original geodatabase is in '%s'. "
+                    "Dataset should be closed",
+                    osEditedName.c_str(), osName.c_str(), osTmpName.c_str());
+            pConnection->SetLocked(FALSE);
+            Release(osName);
+            return OGRERR_FAILURE;
+        }
+
+        if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") ||
+            CPLUnlinkTree(osTmpName) != 0 )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "Cannot remove %s. Manual cleanup required", osTmpName.c_str());
+        }
+    }
+
+    pConnection->m_pGeodatabase = new Geodatabase;
+    long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase));
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE_REOPEN") || FAILED(hr))
+    {
+        delete pConnection->m_pGeodatabase;
+        pConnection->m_pGeodatabase = NULL;
+        pConnection->SetLocked(FALSE);
+        Release(osName);
+        GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed");
+        return OGRERR_FAILURE;
+    }
+
+    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
+    pDS->Open(osNameOri, TRUE, NULL);
+    //pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
+    poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
+
+    pConnection->SetLocked(FALSE);
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           RollbackTransaction()                      */
+/************************************************************************/
+
+OGRErr FGdbDriver::RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS)
+{
+    CPLMutexHolderOptionalLockD(hMutex);
+
+    bOutHasReopenedDS = FALSE;
+
+    OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut;
+    FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource();
+    FGdbDatabaseConnection* pConnection = poDS->GetConnection();
+    if( !pConnection->IsLocked() )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "No transaction in progress");
+        return OGRERR_FAILURE;
+    }
+
+    bOutHasReopenedDS = TRUE;
+
+    CPLString osName(poMutexedDS->GetName());
+    CPLString osNameOri(osName);
+    if( osName.back()== '/' || osName.back()== '\\' )
+        osName.resize(osName.size()-1);
+
+    //int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction();
+
+    pConnection->m_nRefCount ++;
+    delete poDSInOut;
+    poDSInOut = NULL;
+    poMutexedDS = NULL;
+    poDS = NULL;
+
+    pConnection->CloseGeodatabase();
+
+    CPLString osEditedName(osName);
+    osEditedName += ".ogredited";
+
+    OGRErr eErr = OGRERR_NONE;
+    if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") ||
+        CPLUnlinkTree(osEditedName) != 0 )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Cannot remove %s. Manual cleanup required", osEditedName.c_str());
+        eErr = OGRERR_FAILURE;
+    }
+
+    pConnection->m_pGeodatabase = new Geodatabase;
+    long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase));
+    if (EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") ||
+        FAILED(hr))
+    {
+        delete pConnection->m_pGeodatabase;
+        pConnection->m_pGeodatabase = NULL;
+        pConnection->SetLocked(FALSE);
+        Release(osName);
+        GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed");
+        return OGRERR_FAILURE;
+    }
+
+    FGdbDataSource* pDS = new FGdbDataSource(this, pConnection);
+    pDS->Open(osNameOri, TRUE, NULL);
+    //pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction);
+    poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE);
+
+    pConnection->SetLocked(FALSE);
+
+    return eErr;
+}
+
+/***********************************************************************/
+/*                            Release()                                */
+/***********************************************************************/
+
+void FGdbDriver::Release(const char* pszName)
+{
+    CPLMutexHolderOptionalLockD(hMutex);
+
+    FGdbDatabaseConnection* pConnection = oMapConnections[pszName];
+    if( pConnection != NULL )
+    {
+        pConnection->m_nRefCount --;
+        CPLDebug("FileGDB", "ref_count of %s = %d now", pszName,
+                 pConnection->m_nRefCount);
+        if( pConnection->m_nRefCount == 0 )
+        {
+            pConnection->CloseGeodatabase();
+            delete pConnection;
+            oMapConnections.erase(pszName);
+        }
+    }
+}
+
+/***********************************************************************/
+/*                         CloseGeodatabase()                          */
+/***********************************************************************/
+
+void FGdbDatabaseConnection::CloseGeodatabase()
+{
+    if( m_pGeodatabase != NULL )
+    {
+        CPLDebug("FileGDB", "Really closing %s now", m_osName.c_str());
+        ::CloseGeodatabase(*m_pGeodatabase);
+        delete m_pGeodatabase;
+        m_pGeodatabase = NULL;
+    }
+}
+
+/***********************************************************************/
+/*                         OpenGeodatabase()                           */
+/***********************************************************************/
+
+int FGdbDatabaseConnection::OpenGeodatabase(const char* pszFSName)
+{
+    m_pGeodatabase = new Geodatabase;
+    long hr = ::OpenGeodatabase(StringToWString(CPLString(pszFSName)), *m_pGeodatabase);
+    if (FAILED(hr))
+    {
+        delete m_pGeodatabase;
+        m_pGeodatabase = NULL;
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/***********************************************************************/
+/*                         TestCapability()                            */
+/***********************************************************************/
+
+int FGdbDriver::TestCapability( const char * pszCap )
+{
+    if (EQUAL(pszCap, ODrCCreateDataSource) )
+        return TRUE;
+
+    else if (EQUAL(pszCap, ODrCDeleteDataSource) )
+        return TRUE;
+
+    return FALSE;
+}
+/************************************************************************/
+/*                          DeleteDataSource()                          */
+/************************************************************************/
+
+OGRErr FGdbDriver::DeleteDataSource( const char *pszDataSource )
+{
+    CPLMutexHolderD(&hMutex);
+
+    std::wstring wstr = StringToWString(pszDataSource);
+
+    long hr = 0;
+
+    if( S_OK != (hr = ::DeleteGeodatabase(wstr)) )
+    {
+        GDBErr(hr, "Failed to delete Geodatabase");
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/***********************************************************************/
+/*                       RegisterOGRFileGDB()                          */
+/***********************************************************************/
+
+void RegisterOGRFileGDB()
+
+{
+    if (! GDAL_CHECK_VERSION("OGR FGDB"))
+        return;
+
+    OGRSFDriver* poDriver = new FGdbDriver;
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                                "ESRI FileGDB" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gdb" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_filegdb.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>" );
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+"<LayerCreationOptionList>"
+"  <Option name='FEATURE_DATASET' type='string' description='FeatureDataset folder into to put the new layer'/>"
+"  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column' default='SHAPE'/>"
+"  <Option name='GEOMETRY_NULLABLE' type='boolean' description='Whether the values of the geometry column can be NULL' default='YES'/>"
+"  <Option name='FID' type='string' description='Name of OID column' default='OBJECTID' deprecated_alias='OID_NAME'/>"
+"  <Option name='XYTOLERANCE' type='float' description='Snapping tolerance, used for advanced ArcGIS features like network and topology rules, on 2D coordinates, in the units of the CRS'/>"
+"  <Option name='ZTOLERANCE' type='float' description='Snapping tolerance, used for advanced ArcGIS features like network and topology rules, on Z coordinates, in the units of the CRS'/>"
+"  <Option name='XORIGIN' type='float' description='X origin of the coordinate precision grid'/>"
+"  <Option name='YORIGIN' type='float' description='Y origin of the coordinate precision grid'/>"
+"  <Option name='ZORIGIN' type='float' description='Z origin of the coordinate precision grid'/>"
+"  <Option name='XYSCALE' type='float' description='X,Y scale of the coordinate precision grid'/>"
+"  <Option name='ZSCALE' type='float' description='Z scale of the coordinate precision grid'/>"
+"  <Option name='XML_DEFINITION' type='string' description='XML definition to create the new table. The root node of such a XML definition must be a <esri:DataElement> element conformant to FileGDBAPI.xsd'/>"
+"  <Option name='CREATE_MULTIPATCH' type='boolean' description='Whether to write geometries of layers of type MultiPolygon as MultiPatch' default='NO'/>"
+"  <Option name='COLUMN_TYPES' type='string' description='A list of strings of format field_name=fgdb_filed_type (separated by comma) to force the FileGDB column type of fields to be created'/>"
+"  <Option name='CONFIGURATION_KEYWORD' type='string-select' description='Customize how data is stored. By default text in UTF-8 and data up to 1TB'>"
+"    <Value>DEFAULTS</Value>"
+"    <Value>TEXT_UTF16</Value>"
+"    <Value>MAX_FILE_SIZE_4GB</Value>"
+"    <Value>MAX_FILE_SIZE_256TB</Value>"
+"    <Value>GEOMETRY_OUTOFLINE</Value>"
+"    <Value>BLOB_OUTOFLINE</Value>"
+"    <Value>GEOMETRY_AND_BLOB_OUTOFLINE</Value>"
+"  </Option>"
+"</LayerCreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Real String Date DateTime Binary" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
index 0d359e5..13f3ae3 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbLayer.cpp
@@ -1,3826 +1,3828 @@
-/******************************************************************************
-* $Id: FGdbLayer.cpp 35794 2016-10-17 19:29:48Z rouault $
-*
-* Project:  OpenGIS Simple Features Reference Implementation
-* Purpose:  Implements FileGDB OGR layer.
-* Author:   Ragi Yaser Burhum, ragi at burhum.com
-*           Paul Ramsey, pramsey at cleverelephant.ca
-*
-******************************************************************************
-* Copyright (c) 2010, Ragi Yaser Burhum
-* Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
- * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-* DEALINGS IN THE SOFTWARE.
-****************************************************************************/
-
-#include "ogr_fgdb.h"
-#include "ogrpgeogeometry.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "FGdbUtils.h"
-#include "cpl_minixml.h" // the only way right now to extract schema information
-
-CPL_CVSID("$Id: FGdbLayer.cpp 35794 2016-10-17 19:29:48Z rouault $");
-
-using std::string;
-using std::wstring;
-
-/************************************************************************/
-/*                           FGdbBaseLayer()                            */
-/************************************************************************/
-FGdbBaseLayer::FGdbBaseLayer() :
-    m_pFeatureDefn(NULL), m_pSRS(NULL), m_pEnumRows(NULL),
-    m_suppressColumnMappingError(false), m_forceMulti(false)
-{
-}
-
-/************************************************************************/
-/*                          ~FGdbBaseLayer()                            */
-/************************************************************************/
-FGdbBaseLayer::~FGdbBaseLayer()
-{
-    if (m_pFeatureDefn)
-    {
-        m_pFeatureDefn->Release();
-        m_pFeatureDefn = NULL;
-    }
-
-    CloseGDBObjects();
-
-    if (m_pSRS)
-    {
-        m_pSRS->Release();
-        m_pSRS = NULL;
-    }
-}
-
-/************************************************************************/
-/*                          CloseGDBObjects()                           */
-/************************************************************************/
-
-void FGdbBaseLayer::CloseGDBObjects()
-{
-    if (m_pEnumRows)
-    {
-        delete m_pEnumRows;
-        m_pEnumRows = NULL;
-    }
-}
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRFeature* FGdbBaseLayer::GetNextFeature()
-{
-    while (1) //want to skip errors
-    {
-        if (m_pEnumRows == NULL)
-            return NULL;
-
-        long hr;
-
-        Row row;
-
-        if (FAILED(hr = m_pEnumRows->Next(row)))
-        {
-            GDBErr(hr, "Failed fetching features");
-            return NULL;
-        }
-
-        if (hr != S_OK)
-        {
-        // It's OK, we are done fetching - failure is caught by FAILED macro
-            return NULL;
-        }
-
-        OGRFeature* pOGRFeature = NULL;
-
-        if (!OGRFeatureFromGdbRow(&row,  &pOGRFeature))
-        {
-            int32 oid = -1;
-            row.GetOID(oid);
-
-            GDBErr(hr, CPLSPrintf("Failed translating FGDB row [%d] to OGR Feature", oid));
-
-            //return NULL;
-            continue; //skip feature
-        }
-
-        return pOGRFeature;
-    }
-}
-
-/************************************************************************/
-/*                              FGdbLayer()                             */
-/************************************************************************/
-FGdbLayer::FGdbLayer():
-    m_pDS(NULL), m_pTable(NULL), m_wstrSubfields(L"*"), m_pOGRFilterGeometry(NULL), 
-    m_bFilterDirty(true), 
-    m_bLaunderReservedKeywords(true)
-{
-    m_bBulkLoadAllowed = -1; /* uninitialized */
-    m_bBulkLoadInProgress = FALSE;
-    m_pEnumRows = new EnumRows;
-
-#ifdef EXTENT_WORKAROUND
-    m_bLayerEnvelopeValid = false;
-    m_bLayerJustCreated = false;
-#endif
-    m_papszOptions = NULL;
-    m_bCreateMultipatch = FALSE;
-    m_nResyncThreshold = atoi(CPLGetConfigOption("FGDB_RESYNC_THRESHOLD", "1000000"));
-    m_bSymlinkFlag = FALSE;
-}
-
-/************************************************************************/
-/*                            ~FGdbLayer()                              */
-/************************************************************************/
-
-FGdbLayer::~FGdbLayer()
-{
-    CloseGDBObjects();
-
-    if (m_pOGRFilterGeometry)
-    {
-        OGRGeometryFactory::destroyGeometry(m_pOGRFilterGeometry);
-        m_pOGRFilterGeometry = NULL;
-    }
-    
-    for(size_t i = 0; i < m_apoByteArrays.size(); i++ )
-        delete m_apoByteArrays[i];
-    m_apoByteArrays.resize(0);
-
-    CSLDestroy(m_papszOptions);
-    m_papszOptions = NULL;
-    
-}
-
-/************************************************************************/
-/*                        CloseGDBObjects()                             */
-/************************************************************************/
-
-void FGdbLayer::CloseGDBObjects()
-{
-    EndBulkLoad();
-
-#ifdef EXTENT_WORKAROUND
-    WorkAroundExtentProblem();
-#endif
-
-    if (m_pTable)
-    {
-        delete m_pTable;
-        m_pTable = NULL;
-    }
-
-    FGdbBaseLayer::CloseGDBObjects();
-}
-
-/************************************************************************/
-/*                     EditIndexesForFIDHack()                          */
-/************************************************************************/
-
-int FGdbLayer::EditIndexesForFIDHack(const char* pszRadixTablename)
-{
-    // Fix FIDs in .gdbtablx, .spx and .atx's
-
-    CPLString osGDBTablX = CPLResetExtension(pszRadixTablename, "gdbtablx");
-    CPLString osNewGDBTablX = CPLResetExtension(pszRadixTablename, "gdbtablx.new");
-
-    if( !EditGDBTablX(osGDBTablX, osNewGDBTablX) )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Error occurred when editing %s", osNewGDBTablX.c_str());
-        VSIUnlink(osNewGDBTablX);
-        return FALSE;
-    }
-
-    CPLString osDirectory(CPLGetPath(pszRadixTablename));;
-    char** papszFiles = VSIReadDir(osDirectory);
-    CPLString osBasename(CPLGetBasename(pszRadixTablename));
-    int bRet = TRUE;
-    for(char** papszIter = papszFiles; papszIter && *papszIter; papszIter++)
-    {
-        if( strncmp(*papszIter, osBasename.c_str(), osBasename.size()) == 0 &&
-            (EQUAL(CPLGetExtension(*papszIter), "atx") ||
-             EQUAL(CPLGetExtension(*papszIter), "spx")) )
-        {
-            CPLString osIndex(CPLFormFilename(osDirectory, *papszIter, NULL));
-            if( !EditATXOrSPX(osIndex) )
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Error occurred when editing %s", osIndex.c_str());
-                bRet = FALSE;
-            }
-        }
-    }
-    CSLDestroy(papszFiles);
-
-    CPLString osGDBTablXTmp(CPLSPrintf("%s.tmp", osGDBTablX.c_str()));
-    int bRet2 = (VSIRename(osGDBTablX,osGDBTablXTmp) == 0 &&
-                 VSIRename(osNewGDBTablX, osGDBTablX) == 0);
-    VSIUnlink(osGDBTablXTmp);
-    if( !bRet2 )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot rename %s to %s", osNewGDBTablX.c_str(), osGDBTablX.c_str());
-        bRet = FALSE;
-    }
-
-    return bRet;
-}
-
-/************************************************************************/
-/*                           EditATXOrSPX()                             */
-/************************************************************************/
-
-/* See https://github.com/rouault/dump_gdbtable/wiki/FGDB-Spec */
-int FGdbLayer::EditATXOrSPX( const CPLString& osIndex )
-{
-    VSILFILE* fp = VSIFOpenL(osIndex, "rb+");
-    if (fp == NULL )
-    {
-        CPLError(CE_Failure, CPLE_FileIO, "Cannot open %s", osIndex.c_str());
-        return FALSE;
-    }
-    VSIFSeekL(fp, 0, SEEK_END);
-    vsi_l_offset nPos = VSIFTellL(fp);
-    int bRet = FALSE;
-    int bInvalidateIndex = FALSE;
-    if( nPos > 22 )
-    {
-        VSIFSeekL(fp, nPos - 22, SEEK_SET);
-        GByte nSizeIndexedValue;
-        if( VSIFReadL(&nSizeIndexedValue, 1, 1, fp) == 1 &&
-            nSizeIndexedValue > 0 )
-        {
-            GByte abyIndexedValue[255];
-            VSIFSeekL(fp, nPos - 22 + 6, SEEK_SET);
-            int nDepth;
-            if( VSIFReadL(&nDepth, 1, 4, fp) == 4 )
-            {
-                nDepth = CPL_LSBWORD32(nDepth);
-
-                int bIndexedValueIsValid = FALSE;
-                int nFirstIndexAtThisValue = -1;
-                std::vector<int> anPagesAtThisValue;
-                int bSortThisValue = FALSE;
-                int nLastPageVisited = 0;
-                bRet = EditATXOrSPX(fp,
-                                    1,
-                                    nLastPageVisited,
-                                    nDepth,
-                                    nSizeIndexedValue,
-                                    abyIndexedValue,
-                                    bIndexedValueIsValid,
-                                    nFirstIndexAtThisValue,
-                                    anPagesAtThisValue,
-                                    bSortThisValue,
-                                    bInvalidateIndex);
-            }
-        }
-    }
-    VSIFCloseL(fp);
-    if( bInvalidateIndex )
-    {
-        //CPLDebug("FGDB", "Invalidate %s", osIndex.c_str());
-        CPLError(CE_Warning, CPLE_AppDefined, "Invalidate %s", osIndex.c_str());
-        VSIUnlink(osIndex);
-    }
-    return bRet;
-}
-
-static int FGdbLayerSortATX(const void* _pa, const void* _pb)
-{
-    int a = CPL_LSBWORD32(*(int*)_pa);
-    int b = CPL_LSBWORD32(*(int*)_pb);
-    if( a < b )
-        return -1;
-    else if( a > b )
-        return 1;
-    CPLAssert(FALSE);
-    return 0;
-}
-
-int FGdbLayer::EditATXOrSPX(VSILFILE* fp,
-                            int nThisPage,
-                            int& nLastPageVisited,
-                            int nDepth,
-                            int nSizeIndexedValue,
-                            GByte* pabyLastIndexedValue,
-                            int& bIndexedValueIsValid,
-                            int& nFirstIndexAtThisValue,
-                            std::vector<int>& anPagesAtThisValue,
-                            int& bSortThisValue,
-                            int& bInvalidateIndex)
-{
-    GByte abyBuffer[4096];
-    
-    VSIFSeekL(fp, (nThisPage - 1) * 4096, SEEK_SET);
-
-    if( nDepth == 1 )
-    {
-        if( nThisPage == nLastPageVisited )
-            return TRUE;
-
-        /* This page directly references features */
-        int bRewritePage = FALSE;
-        if( VSIFReadL(abyBuffer, 1, 4096, fp) != 4096 )
-            return FALSE;
-        int nNextPageID;
-        memcpy(&nNextPageID, abyBuffer, 4);
-        int nFeatures;
-        memcpy(&nFeatures, abyBuffer + 4, 4);
-        nFeatures = CPL_LSBWORD32(nFeatures);
-        
-        //if( nLastPageVisited == 0 )
-        //    printf("nFeatures = %d\n", nFeatures);
-        
-        const int nMaxPerPages = (4096 - 12) / (4 + nSizeIndexedValue);
-        const int nOffsetFirstValInPage = 12 + nMaxPerPages * 4;
-        if( nFeatures > nMaxPerPages )
-            return FALSE;
-        for(int i=0; i < nFeatures; i++)
-        {
-            int bNewVal = ( !bIndexedValueIsValid ||
-                            memcmp(pabyLastIndexedValue,
-                                   abyBuffer + nOffsetFirstValInPage + i * nSizeIndexedValue,
-                                   nSizeIndexedValue) != 0 );
-
-            int nFID;
-            memcpy(&nFID, abyBuffer + 12 + 4 * i, 4);
-            nFID = CPL_LSBWORD32(nFID);
-            int nOGRFID = m_oMapFGDBFIDToOGRFID[nFID];
-            if( nOGRFID )
-            {
-                nFID = nOGRFID;
-                nOGRFID = CPL_LSBWORD32(nOGRFID);
-                memcpy(abyBuffer + 12 + 4 * i, &nOGRFID, 4);
-                bRewritePage = TRUE;
-                
-                if( bIndexedValueIsValid && i == nFeatures - 1 && nNextPageID == 0 )
-                    bSortThisValue = TRUE;
-            }
-             
-            // We must make sure that features with same indexed values are
-            // sorted by increasing FID, even when that spans over several
-            // pages           
-            if( bSortThisValue && (bNewVal || (i == nFeatures - 1 && nNextPageID == 0)) )
-            {
-                if( anPagesAtThisValue[0] == nThisPage )
-                {
-                    CPLAssert(anPagesAtThisValue.size() == 1);
-                    int nFeaturesToSortThisPage = i - nFirstIndexAtThisValue;
-                    if( !bNewVal && i == nFeatures - 1 && nNextPageID == 0 )
-                        nFeaturesToSortThisPage ++;
-                    CPLAssert(nFeaturesToSortThisPage > 0);
-                    
-                    bRewritePage = TRUE;
-                    qsort(abyBuffer + 12 + 4 * nFirstIndexAtThisValue,
-                          nFeaturesToSortThisPage, 4, FGdbLayerSortATX);
-                }
-                else
-                {
-                    std::vector<int> anValues;
-                    int nFeaturesToSort = 0;
-                    anValues.resize(anPagesAtThisValue.size() * nMaxPerPages);
-                    
-                    int nFeaturesToSortLastPage = i;
-                    if( !bNewVal && i == nFeatures - 1 && nNextPageID == 0 )
-                        nFeaturesToSortLastPage ++;
-                    
-                    for(size_t j=0;j<anPagesAtThisValue.size();j++)
-                    {
-                        int nFeaturesPrevPage;
-                        VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 4, SEEK_SET);
-                        VSIFReadL(&nFeaturesPrevPage, 1, 4, fp);
-                        nFeaturesPrevPage = CPL_LSBWORD32(nFeaturesPrevPage);
-                        if( j == 0 )
-                        {
-                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12 + 4 * nFirstIndexAtThisValue, SEEK_SET);
-                            VSIFReadL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage - nFirstIndexAtThisValue, fp);
-                            nFeaturesToSort += nFeaturesPrevPage - nFirstIndexAtThisValue;
-                        }
-                        else if( j == anPagesAtThisValue.size() - 1 && anPagesAtThisValue[j] == nThisPage )
-                        {
-                            bRewritePage = TRUE;
-                            memcpy(&anValues[nFeaturesToSort], abyBuffer + 12, nFeaturesToSortLastPage * 4);
-                            nFeaturesToSort += nFeaturesToSortLastPage;
-                        }
-                        else
-                        {
-                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12, SEEK_SET);
-                            VSIFReadL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage, fp);
-                            nFeaturesToSort += nFeaturesPrevPage;
-                        }
-                    }
-
-                    qsort(&anValues[0], nFeaturesToSort, 4, FGdbLayerSortATX);
-                    
-                    nFeaturesToSort = 0;
-                    for(size_t j=0;j<anPagesAtThisValue.size();j++)
-                    {
-                        int nFeaturesPrevPage;
-                        VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 4, SEEK_SET);
-                        VSIFReadL(&nFeaturesPrevPage, 1, 4, fp);
-                        nFeaturesPrevPage = CPL_LSBWORD32(nFeaturesPrevPage);
-                        if( j == 0 )
-                        {
-                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12 + 4 * nFirstIndexAtThisValue, SEEK_SET);
-                            VSIFWriteL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage - nFirstIndexAtThisValue, fp);
-                            nFeaturesToSort += nFeaturesPrevPage - nFirstIndexAtThisValue;
-                        }
-                        else if( j == anPagesAtThisValue.size() - 1 && anPagesAtThisValue[j] == nThisPage )
-                        {
-                            memcpy(abyBuffer + 12, &anValues[nFeaturesToSort], nFeaturesToSortLastPage * 4);
-                            nFeaturesToSort += nFeaturesToSortLastPage;
-                        }
-                        else
-                        {
-                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12, SEEK_SET);
-                            VSIFWriteL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage, fp);
-                            nFeaturesToSort += nFeaturesPrevPage;
-                        }
-                    }
-                }
-            }
-            
-            if( bNewVal )
-            {
-                nFirstIndexAtThisValue = i;
-                anPagesAtThisValue.clear();
-                anPagesAtThisValue.push_back(nThisPage);
-                
-                memcpy(pabyLastIndexedValue,
-                       abyBuffer + nOffsetFirstValInPage + i * nSizeIndexedValue,
-                       nSizeIndexedValue);
-                bSortThisValue = FALSE;
-            }
-            else if( i == 0 )
-            {
-                if( anPagesAtThisValue.size() > 100000 )
-                {
-                    bInvalidateIndex = TRUE;
-                    return FALSE;
-                }
-                else
-                {
-                    anPagesAtThisValue.push_back(nThisPage);
-                }
-            }
-
-            if( nOGRFID )
-                bSortThisValue = TRUE;
-
-            bIndexedValueIsValid = TRUE;
-        }
-        
-        if( bRewritePage )
-        {
-            VSIFSeekL(fp, (nThisPage - 1) * 4096, SEEK_SET);
-            if( VSIFWriteL(abyBuffer, 1, 4096, fp) != 4096 )
-                return FALSE;
-        }
-        
-        nLastPageVisited = nThisPage;
-
-        return TRUE;
-    }
-    else
-    {
-        /* This page references other pages */
-        if( VSIFReadL(abyBuffer, 1, 4096, fp) != 4096 )
-            return FALSE;
-        int nSubPages;
-        memcpy(&nSubPages, abyBuffer + 4, 4);
-        nSubPages = CPL_LSBWORD32(nSubPages);
-        nSubPages ++;
-        if( nSubPages > (4096 - 8) / 4 )
-            return FALSE;
-        for(int i=0; i < nSubPages; i++)
-        {
-            int nSubPageID;
-            memcpy(&nSubPageID, abyBuffer + 8 + 4 * i, 4);
-            nSubPageID = CPL_LSBWORD32(nSubPageID);
-            if( nSubPageID < 1 )
-                return FALSE;
-            if( !EditATXOrSPX(fp,
-                              nSubPageID,
-                              nLastPageVisited,
-                              nDepth - 1,
-                              nSizeIndexedValue,
-                              pabyLastIndexedValue,
-                              bIndexedValueIsValid,
-                              nFirstIndexAtThisValue,
-                              anPagesAtThisValue,
-                              bSortThisValue,
-                              bInvalidateIndex) )
-            {
-                return FALSE;
-            }
-        }
-        
-        return TRUE;
-    }
-}
-
-/************************************************************************/
-/*                              GetInt32()                              */
-/************************************************************************/
-
-static GInt32 GetInt32(const GByte* pBaseAddr, int iOffset)
-{
-    GInt32 nVal;
-    memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
-    CPL_LSBPTR32(&nVal);
-    return nVal;
-}
-
-/************************************************************************/
-/*                     UpdateNextOGRFIDAndFGDBFID()                     */
-/************************************************************************/
-
-static CPL_INLINE void UpdateNextOGRFIDAndFGDBFID(int i,
-                                       std::map<int,int>& oMapOGRFIDToFGDBFID,
-                                       std::map<int,int>::iterator& oIterO2F,
-                                       int& nNextOGRFID,
-                                       std::map<int,int>& oMapFGDBFIDToOGRFID,
-                                       std::map<int,int>::iterator& oIterF2O,
-                                       int& nNextFGDBFID)
-{
-    while( nNextOGRFID > 0 && i > nNextOGRFID )
-    {
-        ++ oIterO2F;
-        if( oIterO2F == oMapOGRFIDToFGDBFID.end() )
-            nNextOGRFID = -1;
-        else
-            nNextOGRFID = oIterO2F->first;
-    }
-
-    while( nNextFGDBFID > 0 && i > nNextFGDBFID )
-    {
-        ++ oIterF2O;
-        if( oIterF2O == oMapFGDBFIDToOGRFID.end() )
-            nNextFGDBFID = -1;
-        else
-            nNextFGDBFID = oIterF2O->first;
-    }
-}
-
-/************************************************************************/
-/*                          EditGDBTablX()                              */
-/************************************************************************/
-
-#define TEST_BIT(ar, bit)                       (ar[(bit) / 8] & (1 << ((bit) % 8)))
-#define SET_BIT(ar,bit)                         ar[(bit)/8] |= (1 << ((bit) % 8))
-#define BIT_ARRAY_SIZE_IN_BYTES(bitsize)        (((bitsize)+7)/8)
-
-/* See https://github.com/rouault/dump_gdbtable/wiki/FGDB-Spec */
-int  FGdbLayer::EditGDBTablX( const CPLString& osGDBTablX,
-                              const CPLString& osNewGDBTablX )
-{
-    VSILFILE* fp = VSIFOpenL(osGDBTablX, "rb");
-    if (fp == NULL )
-    {
-        CPLError(CE_Failure, CPLE_FileIO, "Cannot open %s", osGDBTablX.c_str());
-        return FALSE;
-    }
-    VSILFILE* fpNew = VSIFOpenL(osNewGDBTablX, "wb");
-    if (fpNew == NULL )
-    {
-        CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s", osNewGDBTablX.c_str());
-        VSIFCloseL(fp);
-        return FALSE;
-    }
-    GByte abyBuffer[16];
-    VSIFReadL(abyBuffer, 1, 16, fp);
-    int n1024Blocks = GetInt32(abyBuffer, 1);
-    int nInMaxFID = GetInt32(abyBuffer, 2);
-#ifdef DEBUG
-    const int nInMaxFIDOri = nInMaxFID;
-#endif
-    int nRecordSize = GetInt32(abyBuffer, 3);
-    CPLAssert(nRecordSize >= 4 && nRecordSize <= 6);
-
-    std::map<int,int>::iterator oIterO2F = m_oMapOGRFIDToFGDBFID.begin();
-    int nMaxOGRFID = 0;
-    for(; oIterO2F != m_oMapOGRFIDToFGDBFID.end(); ++oIterO2F )
-        nMaxOGRFID = oIterO2F->first;
-    //printf("nInMaxFID = %d\n", nInMaxFID);
-    //printf("nMaxOGRFID = %d\n", nMaxOGRFID);
-    int nOutMaxFID = MAX(nInMaxFID, nMaxOGRFID);
-
-    // Optimization: If the feature ids at the end of the file all map to a OGR fid
-    // then they don't need to be included in the final file
-    for(int i=nInMaxFID; i>nMaxOGRFID; i--)
-    {
-        if( m_oMapFGDBFIDToOGRFID.find(i) != m_oMapFGDBFIDToOGRFID.end() )
-        {
-            nOutMaxFID --;
-            nInMaxFID --;
-        }
-        else
-            break;
-    }
-    
-    //printf("nInMaxFID = %d\n", nInMaxFID);
-    //printf("nOutMaxFID = %d\n", nOutMaxFID);
-
-    int n1024BlocksOut = (int)(((GIntBig)nOutMaxFID + 1023) / 1024);
-    int nTmp;
-
-    nTmp = CPL_LSBWORD32(n1024BlocksOut);
-    memcpy(abyBuffer + 4, &nTmp, 4);
-
-    nTmp = CPL_LSBWORD32(nOutMaxFID);
-    memcpy(abyBuffer + 8, &nTmp, 4);
-    VSIFWriteL(abyBuffer, 1, 16, fpNew);
-
-    VSIFSeekL(fp, 1024 * n1024Blocks * nRecordSize, SEEK_CUR);
-    VSIFReadL(abyBuffer, 1, 16, fp);
-    int nBitmapInt32Words = GetInt32(abyBuffer, 0);
-    int n1024BlocksTotal = GetInt32(abyBuffer, 1);
-    CPLAssert(n1024BlocksTotal == (int)(((GIntBig)nInMaxFIDOri + 1023 ) / 1024) );
-    GByte* pabyBlockMap = NULL;
-    if( nBitmapInt32Words != 0 )
-    {
-        int nSizeInBytes = BIT_ARRAY_SIZE_IN_BYTES(n1024BlocksTotal);
-        pabyBlockMap = (GByte*) CPLMalloc( nSizeInBytes );
-        VSIFReadL( pabyBlockMap, nSizeInBytes, 1, fp );
-    }
-    int nSizeInBytesOut = BIT_ARRAY_SIZE_IN_BYTES(n1024BlocksOut);
-    /* Round to the next multiple of 128 bytes (32 int4 words) */
-    nSizeInBytesOut = ((nSizeInBytesOut + 127) / 128) * 128;
-    GByte* pabyBlockMapOut = (GByte*) VSI_CALLOC_VERBOSE( 1, nSizeInBytesOut );
-    GByte* pabyPage = (GByte*)VSI_MALLOC_VERBOSE( 1024 * nRecordSize );
-    if( pabyBlockMapOut == NULL || pabyPage == NULL )
-    {
-        VSIFree(pabyBlockMapOut);
-        VSIFree(pabyPage);
-        VSIFCloseL(fp);
-        return FALSE;
-    }
-    GByte abyEmptyOffset[6];
-    memset(abyEmptyOffset, 0, 6);
-    int nNonEmptyPages = 0;
-    int nOffsetInPage = 0, nLastWrittenOffset = 0;
-    int bDisableSparsePages = CPLTestBool(CPLGetConfigOption("FILEGDB_DISABLE_SPARSE_PAGES", "NO"));
-    
-    oIterO2F = m_oMapOGRFIDToFGDBFID.begin();
-    int nNextOGRFID = oIterO2F->first;
-    std::map<int,int>::iterator oIterF2O = m_oMapFGDBFIDToOGRFID.begin();
-    int nNextFGDBFID = oIterF2O->first;
-    
-    int nCountBlocksBeforeIBlockIdx = 0;
-    int nCountBlocksBeforeIBlockValue = 0;
-    
-    int bRet = TRUE;
-    for(int i=1; i<=nOutMaxFID;i++, nOffsetInPage += nRecordSize)
-    {
-        if( nOffsetInPage == 1024 * nRecordSize )
-        {
-            if( nLastWrittenOffset > 0 || bDisableSparsePages )
-            {
-                SET_BIT(pabyBlockMapOut, (i - 2) / 1024);
-                nNonEmptyPages ++;
-                if( nLastWrittenOffset < nOffsetInPage )
-                    memset(pabyPage + nLastWrittenOffset, 0, nOffsetInPage - nLastWrittenOffset);
-                if( VSIFWriteL(pabyPage, 1024 * nRecordSize, 1, fpNew) != 1 )
-                {
-                    bRet = FALSE;
-                    goto end;
-                }
-            }
-            nOffsetInPage = 0;
-            nLastWrittenOffset = 0;
-
-            // A few optimizations :
-            if( !bDisableSparsePages && i > nInMaxFID && nNextOGRFID > 0 && i < nNextOGRFID - 1024 )
-            {
-                // If we created a OGR FID far away from the latest FGDB FID
-                // then skip to it
-                i = ((nNextOGRFID-1) / 1024) * 1024 + 1;
-            }
-            else if( !bDisableSparsePages && pabyBlockMap != NULL && i <= nInMaxFID &&
-                     TEST_BIT(pabyBlockMap, (i-1)/1024) == 0 )
-            {
-                // Skip empty pages
-                UpdateNextOGRFIDAndFGDBFID(i,
-                                  m_oMapOGRFIDToFGDBFID, oIterO2F, nNextOGRFID,
-                                  m_oMapFGDBFIDToOGRFID, oIterF2O, nNextFGDBFID);
-                if( (nNextOGRFID < 0 || i < nNextOGRFID - 1024) &&
-                    (nNextFGDBFID < 0 || i < nNextFGDBFID - 1024) )
-                {
-                    if( i > INT_MAX - 1024 )
-                        break;
-                    i += 1023;
-                    nOffsetInPage += 1023 * nRecordSize;
-                    continue;
-                }
-            }
-        }
-
-       UpdateNextOGRFIDAndFGDBFID(i,
-                                  m_oMapOGRFIDToFGDBFID, oIterO2F, nNextOGRFID,
-                                  m_oMapFGDBFIDToOGRFID, oIterF2O, nNextFGDBFID);
-
-        int nSrcFID;
-        if( i == nNextOGRFID )
-        {
-            // This FID matches a user defined OGR FID, then find the
-            // corresponding FGDB record
-            nSrcFID = oIterO2F->second;
-            //printf("(1) i = %d, nSrcFID = %d\n", i, nSrcFID);
-        }
-        else if( i == nNextFGDBFID || i > nInMaxFID )
-        {
-            // This record is a temporary one (will be moved to a user-define FID)
-            // or we are out of the validity zone of input records
-            //printf("(2) i = %d, nNextFGDBFID = %d, nInMaxFID = %d\n", i, nNextFGDBFID, nInMaxFID);
-            continue;
-        }
-        else
-        {
-            // Regular record, not overloaded by user defined FID
-            nSrcFID = i;
-            //printf("(3) i = %d, nSrcFID = %d\n", i, nSrcFID);
-        }
-
-        if( pabyBlockMap != NULL )
-        {
-            int iBlock = (nSrcFID-1) / 1024;
-
-            // Check if the block is not empty
-            if( TEST_BIT(pabyBlockMap, iBlock) )
-            {
-                int nCountBlocksBefore;
-                if( iBlock >= nCountBlocksBeforeIBlockIdx )
-                {
-                    nCountBlocksBefore = nCountBlocksBeforeIBlockValue;
-                    for(int j=nCountBlocksBeforeIBlockIdx;j<iBlock;j++)
-                        nCountBlocksBefore += TEST_BIT(pabyBlockMap, j) != 0;
-                }
-                else
-                {
-                    nCountBlocksBefore = 0;
-                    for(int j=0;j<iBlock;j++)
-                        nCountBlocksBefore += TEST_BIT(pabyBlockMap, j) != 0;
-                }
-                nCountBlocksBeforeIBlockIdx = iBlock;
-                nCountBlocksBeforeIBlockValue = nCountBlocksBefore;
-                int iCorrectedRow = nCountBlocksBefore * 1024 + ((nSrcFID-1) % 1024);
-                VSIFSeekL(fp, 16 + nRecordSize * iCorrectedRow, SEEK_SET);
-                VSIFReadL(abyBuffer, 1, nRecordSize, fp);
-                if( memcmp( abyBuffer, abyEmptyOffset, nRecordSize) != 0 )
-                {
-                    if( nLastWrittenOffset < nOffsetInPage )
-                        memset(pabyPage + nLastWrittenOffset, 0, nOffsetInPage - nLastWrittenOffset);
-                    memcpy(pabyPage + nOffsetInPage, abyBuffer, nRecordSize);
-                    nLastWrittenOffset = nOffsetInPage + nRecordSize;
-                }
-            }
-        }
-        else
-        {
-            VSIFSeekL(fp, 16 + nRecordSize * (nSrcFID-1), SEEK_SET);
-            VSIFReadL(abyBuffer, 1, nRecordSize, fp);
-            if( memcmp( abyBuffer, abyEmptyOffset, nRecordSize) != 0 )
-            {
-                if( nLastWrittenOffset < nOffsetInPage )
-                    memset(pabyPage + nLastWrittenOffset, 0, nOffsetInPage - nLastWrittenOffset);
-                memcpy(pabyPage + nOffsetInPage, abyBuffer, nRecordSize);
-                nLastWrittenOffset = nOffsetInPage + nRecordSize;
-            }
-        }
-    }
-    //printf("nLastWrittenOffset = %d\n", nLastWrittenOffset);
-    if( nLastWrittenOffset > 0 || bDisableSparsePages )
-    {
-        SET_BIT(pabyBlockMapOut, (nOutMaxFID - 1) / 1024);
-        nNonEmptyPages ++;
-        if( nLastWrittenOffset < 1024 * nRecordSize )
-            memset(pabyPage + nLastWrittenOffset, 0, 1024 * nRecordSize - nLastWrittenOffset);
-        if( VSIFWriteL(pabyPage, 1024 * nRecordSize, 1, fpNew) != 1 )
-        {
-            bRet = FALSE;
-            goto end;
-        }
-    }
-
-    memset(abyBuffer, 0, 16);
-
-    /* Number of total blocks, including omitted ones */
-    nTmp = CPL_LSBWORD32(n1024BlocksOut);
-    memcpy(abyBuffer + 4, &nTmp, 4);
-
-    nTmp = CPL_LSBWORD32(nNonEmptyPages);
-    memcpy(abyBuffer + 8, &nTmp, 4);
-
-    if( nNonEmptyPages < n1024BlocksOut )
-    {
-        /* Number of int4 words for the bitmap (rounded to the next multiple of 32) */
-        nTmp = CPL_LSBWORD32(nSizeInBytesOut / 4);
-        memcpy(abyBuffer + 0, &nTmp, 4);
-
-        /* Number of int4 words in the bitmap where there's at least a non-zero bit */
-        /* Seems to be unused */
-        nTmp = CPL_LSBWORD32(((nOutMaxFID - 1) / 1024 + 31) / 32);
-        memcpy(abyBuffer + 12, &nTmp, 4);
-    }
-
-    if( VSIFWriteL(abyBuffer, 1, 16, fpNew) != 16 )
-    {
-        bRet = FALSE;
-        goto end;
-    }
-
-    if( nNonEmptyPages < n1024BlocksOut )
-    {
-        VSIFWriteL(pabyBlockMapOut, 1, nSizeInBytesOut, fpNew);
-
-        VSIFSeekL(fpNew, 4, SEEK_SET);
-        nTmp = CPL_LSBWORD32(nNonEmptyPages);
-        VSIFWriteL(&nTmp, 1, 4, fpNew);
-    }
-
-end:
-    CPLFree(pabyBlockMap);
-    CPLFree(pabyBlockMapOut);
-    CPLFree(pabyPage);
-    VSIFCloseL(fpNew);
-    VSIFCloseL(fp);
-
-    return bRet;
-}
-
-#ifdef EXTENT_WORKAROUND
-
-/************************************************************************/
-/*                     UpdateRowWithGeometry()                          */
-/************************************************************************/
-
-bool FGdbLayer::UpdateRowWithGeometry(Row& row, OGRGeometry* poGeom)
-{
-    ShapeBuffer shape;
-    long hr;
-
-    /* Write geometry to a buffer */
-    GByte *pabyShape = NULL;
-    int nShapeSize = 0;
-    if ( OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize ) != OGRERR_NONE )
-    {
-        CPLFree(pabyShape);
-        return false;
-    }
-
-    /* Copy it into a ShapeBuffer */
-    if ( nShapeSize > 0 )
-    {
-        shape.Allocate(nShapeSize);
-        memcpy(shape.shapeBuffer, pabyShape, nShapeSize);
-        shape.inUseLength = nShapeSize;
-    }
-
-    /* Free the shape buffer */
-    CPLFree(pabyShape);
-
-    /* Write ShapeBuffer into the Row */
-    hr = row.SetGeometry(shape);
-    if (FAILED(hr))
-    {
-        return false;
-    }
-
-    /* Update row */
-    hr = m_pTable->Update(row);
-    if (FAILED(hr))
-    {
-        return false;
-    }
-
-    return true;
-}
-
-/************************************************************************/
-/*                    WorkAroundExtentProblem()                         */
-/*                                                                      */
-/* Work-around problem with FileGDB API 1.1 on Linux 64bit. See #4455   */
-/************************************************************************/
-
-void FGdbLayer::WorkAroundExtentProblem()
-{
-    if (!m_bLayerJustCreated || !m_bLayerEnvelopeValid)
-        return;
-    m_bLayerJustCreated = FALSE;
-
-    OGREnvelope sEnvelope;
-    if (GetExtent(&sEnvelope, TRUE) != OGRERR_NONE)
-        return;
-
-    /* The characteristic of the bug is that the reported extent */
-    /* is the real extent truncated incorrectly to integer values */
-    /* We work around that by temporary updating one feature with a geometry */
-    /* whose coordinates are integer values but ceil'ed and floor'ed */
-    /* such that they include the real layer extent. */
-    if (((double)(int)sEnvelope.MinX == sEnvelope.MinX &&
-         (double)(int)sEnvelope.MinY == sEnvelope.MinY &&
-         (double)(int)sEnvelope.MaxX == sEnvelope.MaxX &&
-         (double)(int)sEnvelope.MaxY == sEnvelope.MaxY) &&
-        (fabs(sEnvelope.MinX - sLayerEnvelope.MinX) > 1e-5 ||
-         fabs(sEnvelope.MinY - sLayerEnvelope.MinY) > 1e-5 ||
-         fabs(sEnvelope.MaxX - sLayerEnvelope.MaxX) > 1e-5 ||
-         fabs(sEnvelope.MaxY - sLayerEnvelope.MaxY) > 1e-5))
-    {
-        long           hr;
-        Row            row;
-        EnumRows       enumRows;
-
-        if (FAILED(hr = m_pTable->Search(StringToWString("*"), StringToWString(""), true, enumRows)))
-            return;
-
-        if (FAILED(hr = enumRows.Next(row)))
-            return;
-
-        if (hr != S_OK)
-            return;
-
-        /* Backup original shape buffer */
-        ShapeBuffer originalGdbGeometry;
-        if (FAILED(hr = row.GetGeometry(originalGdbGeometry)))
-            return;
-
-        OGRGeometry* pOGRGeo = NULL;
-        if ((!GDBGeometryToOGRGeometry(m_forceMulti, &originalGdbGeometry, m_pSRS, &pOGRGeo)) || pOGRGeo == NULL)
-        {
-            delete pOGRGeo;
-            return;
-        }
-
-        OGRwkbGeometryType eType = wkbFlatten(pOGRGeo->getGeometryType());
-
-        delete pOGRGeo;
-        pOGRGeo = NULL;
-
-        OGRPoint oP1(floor(sLayerEnvelope.MinX), floor(sLayerEnvelope.MinY));
-        OGRPoint oP2(ceil(sLayerEnvelope.MaxX), ceil(sLayerEnvelope.MaxY));
-
-        OGRLinearRing oLR;
-        oLR.addPoint(&oP1);
-        oLR.addPoint(&oP2);
-        oLR.addPoint(&oP1);
-
-        if ( eType == wkbPoint )
-        {
-            UpdateRowWithGeometry(row, &oP1);
-            UpdateRowWithGeometry(row, &oP2);
-        }
-        else if ( eType == wkbLineString )
-        {
-            UpdateRowWithGeometry(row, &oLR);
-        }
-        else if ( eType == wkbPolygon )
-        {
-            OGRPolygon oPoly;
-            oPoly.addRing(&oLR);
-
-            UpdateRowWithGeometry(row, &oPoly);
-        }
-        else if ( eType == wkbMultiPoint )
-        {
-            OGRMultiPoint oColl;
-            oColl.addGeometry(&oP1);
-            oColl.addGeometry(&oP2);
-
-            UpdateRowWithGeometry(row, &oColl);
-        }
-        else if ( eType == wkbMultiLineString )
-        {
-            OGRMultiLineString oColl;
-            oColl.addGeometry(&oLR);
-
-            UpdateRowWithGeometry(row, &oColl);
-        }
-        else if ( eType == wkbMultiPolygon )
-        {
-            OGRMultiPolygon oColl;
-            OGRPolygon oPoly;
-            oPoly.addRing(&oLR);
-            oColl.addGeometry(&oPoly);
-
-            UpdateRowWithGeometry(row, &oColl);
-        }
-        else
-            return;
-
-        /* Restore original ShapeBuffer */
-        hr = row.SetGeometry(originalGdbGeometry);
-        if (FAILED(hr))
-            return;
-
-        /* Update Row */
-        hr = m_pTable->Update(row);
-        if (FAILED(hr))
-            return;
-
-        CPLDebug("FGDB", "Workaround extent problem with Linux 64bit FGDB SDK 1.1");
-    }
-}
-#endif // EXTENT_WORKAROUND
-
-/************************************************************************/
-/*                            ICreateFeature()                           */
-/* Create an FGDB Row and populate it from an OGRFeature.               */
-/*                                                                      */
-/************************************************************************/
-
-OGRErr FGdbLayer::ICreateFeature( OGRFeature *poFeature )
-{
-    Row fgdb_row;
-    fgdbError hr;
-
-    if( !m_pDS->GetUpdate() || m_pTable == NULL )
-        return OGRERR_FAILURE;
-
-    GIntBig nFID = poFeature->GetFID();
-    if( nFID < -1 || nFID == 0 || !CPL_INT64_FITS_ON_INT32(nFID) )
-    {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Only 32 bit positive integers FID supported by FileGDB");
-        return OGRERR_FAILURE;
-    }
-
-    if( nFID > 0 )
-    {
-        if( m_pDS->GetOpenFileGDBDrv() == NULL )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Cannot call CreateFeature() with a set FID when OpenFileGDB driver not available");
-            return OGRERR_FAILURE;
-        }
-        
-        if( m_pDS->HasSelectLayers() )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Cannot call CreateFeature() with a set FID when a layer resulting from ExecuteSQL() is still opened");
-            return OGRERR_FAILURE;
-        }
-        
-        if( m_pDS->GetConnection()->GetRefCount() > 1 )
-            {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Cannot call CreateFeature() with a set FID when a dataset is opened more than once");
-            return OGRERR_FAILURE;
-        }
-        
-        if( m_oMapOGRFIDToFGDBFID.find((int)poFeature->GetFID()) != m_oMapOGRFIDToFGDBFID.end() )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "A feature with same FID already exists");
-            return OGRERR_FAILURE;
-        }
-        
-        if( m_oMapFGDBFIDToOGRFID.find((int)poFeature->GetFID()) == m_oMapFGDBFIDToOGRFID.end() )
-        {
-            EnumRows       enumRows;
-            Row            row;
-            if (GetRow(enumRows, row, (int)poFeature->GetFID()) == OGRERR_NONE)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "A feature with same FID already exists");
-                return OGRERR_FAILURE;
-            }
-        }
-
-        if( (int)m_oMapOGRFIDToFGDBFID.size() == m_nResyncThreshold )
-            ResyncIDs();
-    }
-
-    if( m_bSymlinkFlag && !CreateRealCopy() )
-        return OGRERR_FAILURE;
-
-    if (m_bBulkLoadAllowed < 0)
-        m_bBulkLoadAllowed = CPLTestBool(CPLGetConfigOption("FGDB_BULK_LOAD", "NO"));
-
-    if (m_bBulkLoadAllowed && !m_bBulkLoadInProgress)
-        StartBulkLoad();
-
-    hr = m_pTable->CreateRowObject(fgdb_row);
-
-    /* Check the status of the Row create */
-    if (FAILED(hr))
-    {
-        GDBErr(hr, "Failed at creating Row in CreateFeature.");
-        return OGRERR_FAILURE;
-    }
-
-    /* As we have issues with fixed values for dates, or CURRENT_xxxx isn't */
-    /* handled anyway, let's fill ourselves all unset fields with their default */
-    poFeature->FillUnsetWithDefault(FALSE, NULL);
-
-    /* Populate the row with the feature content */
-    if (PopulateRowWithFeature(fgdb_row, poFeature) != OGRERR_NONE)
-        return OGRERR_FAILURE;
-
-    /* Cannot write to FID field - it is managed by GDB*/
-    //std::wstring wfield_name = StringToWString(m_strOIDFieldName);
-    //hr = fgdb_row.SetInteger(wfield_name, poFeature->GetFID());
-
-    /* Write the row to the table */
-    hr = m_pTable->Insert(fgdb_row);
-    if (FAILED(hr))
-    {
-        GDBErr(hr, "Failed at writing Row to Table in CreateFeature.");
-        return OGRERR_FAILURE;
-    }
-
-    int32 oid = -1;
-    if (!FAILED(hr = fgdb_row.GetOID(oid)))
-    {
-        if( poFeature->GetFID() < 0 )
-        {
-            // Avoid colliding with a user set FID
-            while( m_oMapOGRFIDToFGDBFID.find(oid) != m_oMapOGRFIDToFGDBFID.end() )
-            {
-                EndBulkLoad();
-
-                CPLDebug("FGDB", "Collision with user set FID %d", oid);
-                if (FAILED(hr = m_pTable->Delete(fgdb_row)))
-                {
-                    GDBErr(hr, "Failed deleting row ");
-                    return OGRERR_FAILURE;
-                }
-                hr = m_pTable->Insert(fgdb_row);
-                if (FAILED(hr))
-                {
-                    GDBErr(hr, "Failed at writing Row to Table in CreateFeature.");
-                    return OGRERR_FAILURE;
-                }
-                if (FAILED(hr = fgdb_row.GetOID(oid)))
-                {
-                    return OGRERR_FAILURE;
-                }
-            }
-            poFeature->SetFID(oid);
-        }
-        else if( (int)poFeature->GetFID() != oid )
-        {
-            m_pDS->GetConnection()->SetFIDHackInProgress(TRUE);
-            m_oMapOGRFIDToFGDBFID[(int)poFeature->GetFID()] = oid;
-            m_oMapFGDBFIDToOGRFID[oid] = (int)poFeature->GetFID();
-        }
-    }
-
-#ifdef EXTENT_WORKAROUND
-    /* For WorkAroundExtentProblem() needs */
-    OGRGeometry* poGeom = poFeature->GetGeometryRef();
-    if ( m_bLayerJustCreated && poGeom != NULL && !poGeom->IsEmpty() )
-    {
-        OGREnvelope sFeatureGeomEnvelope;
-        poGeom->getEnvelope(&sFeatureGeomEnvelope);
-        if (!m_bLayerEnvelopeValid)
-        {
-            memcpy(&sLayerEnvelope, &sFeatureGeomEnvelope, sizeof(sLayerEnvelope));
-            m_bLayerEnvelopeValid = true;
-        }
-        else
-        {
-            sLayerEnvelope.Merge(sFeatureGeomEnvelope);
-        }
-    }
-#endif
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                    PopulateRowWithFeature()                          */
-/*                                                                      */
-/************************************************************************/
-
-OGRErr FGdbLayer::PopulateRowWithFeature( Row& fgdb_row, OGRFeature *poFeature )
-{
-    ShapeBuffer shape;
-    fgdbError hr;
-
-    OGRFeatureDefn* poFeatureDefn = m_pFeatureDefn;
-    int nFieldCount = poFeatureDefn->GetFieldCount();
-
-    /* Copy the OGR visible fields (everything except geometry and FID) */
-    int nCountBinaryField = 0;
-    for( int i = 0; i < nFieldCount; i++ )
-    {
-        std::string field_name = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
-        std::wstring wfield_name = StringToWString(field_name);
-        const std::string & strFieldType = m_vOGRFieldToESRIFieldType[i];
-
-        /* Set empty fields to NULL */
-        if( !poFeature->IsFieldSet( i ) )
-        {
-            if( strFieldType == "esriFieldTypeGlobalID" )
-                continue;
-
-            if (FAILED(hr = fgdb_row.SetNull(wfield_name)))
-            {
-                GDBErr(hr, "Failed setting field to NULL.");
-                return OGRERR_FAILURE;
-            }
-            continue;
-        }
-
-        /* Set the information using the appropriate FGDB function */
-        int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
-
-        if ( nOGRFieldType == OFTInteger )
-        {
-            int fldvalue = poFeature->GetFieldAsInteger(i);
-            if( strFieldType == "esriFieldTypeInteger" )
-                hr = fgdb_row.SetInteger(wfield_name, fldvalue);
-            else
-            {
-                if( fldvalue < -32768 || fldvalue > 32767 )
-                {
-                    static int bHasWarned = FALSE;
-                    if( !bHasWarned )
-                    {
-                        bHasWarned = TRUE;
-                        CPLError(CE_Warning, CPLE_NotSupported,
-                                 "Value %d for field %s does not fit into a short and will be clamped. "
-                                 "This warning will not be emitted any more",
-                                 fldvalue, field_name.c_str());
-                    }
-                    if( fldvalue < -32768 )
-                        fldvalue = -32768;
-                    else
-                        fldvalue = 32767;
-                }
-                hr = fgdb_row.SetShort(wfield_name, (short) fldvalue);
-            }
-        }
-        else if ( nOGRFieldType == OFTReal || nOGRFieldType == OFTInteger64 )
-        {
-            /* Doubles (we don't handle FGDB Floats) */
-            double fldvalue = poFeature->GetFieldAsDouble(i);
-            if( strFieldType == "esriFieldTypeDouble" )
-                hr = fgdb_row.SetDouble(wfield_name, fldvalue);
-            else
-                hr = fgdb_row.SetFloat(wfield_name, (float) fldvalue);
-        }
-        else if ( nOGRFieldType == OFTString )
-        {
-            /* Strings we convert to wstring */
-            std::string fldvalue = poFeature->GetFieldAsString(i);
-            if( strFieldType == "esriFieldTypeString" )
-            {
-                std::wstring wfldvalue = StringToWString(fldvalue);
-                hr = fgdb_row.SetString(wfield_name, wfldvalue);
-            }
-            // Apparently, esriFieldTypeGlobalID can not be set, but is
-            // initialized by the FileGDB SDK itself.
-            else if( strFieldType == "esriFieldTypeGUID" /*||
-                     strFieldType == "esriFieldTypeGlobalID" */ )
-            {
-                Guid guid;
-                std::wstring wfldvalue = StringToWString(fldvalue);
-                if( FAILED(hr = guid.FromString(wfldvalue)) )
-                {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                        "Cannot parse GUID value %s for field %s.",
-                        fldvalue.c_str(), field_name.c_str() );
-                }
-                else
-                {
-                    hr = fgdb_row.SetGUID(wfield_name, guid);
-                }
-            }
-            else if( strFieldType == "esriFieldTypeXML"  )
-            {
-                hr = fgdb_row.SetXML(wfield_name, fldvalue);
-            }
-            else
-                hr = 0;
-        }
-        else if ( nOGRFieldType == OFTDateTime || nOGRFieldType == OFTDate )
-        {
-            /* Dates we need to coerce a little */
-            struct tm val;
-            poFeature->GetFieldAsDateTime(i, &(val.tm_year), &(val.tm_mon), &(val.tm_mday),
-                                          &(val.tm_hour), &(val.tm_min), &(val.tm_sec), NULL);
-            val.tm_year -= 1900;
-            val.tm_mon = val.tm_mon - 1; /* OGR months go 1-12, FGDB go 0-11 */
-            hr = fgdb_row.SetDate(wfield_name, val);
-        }
-        else if ( nOGRFieldType == OFTBinary )
-        {
-            /* Binary data */
-            int bytesize;
-            GByte *bytes = poFeature->GetFieldAsBinary(i, &bytesize);
-            if ( bytesize )
-            {
-                /* This is annoying but SetBinary() doesn't keep the binary */
-                /* content. The ByteArray object must still be alive at */
-                /* the time Insert() is called */
-                m_apoByteArrays[nCountBinaryField]->Allocate(bytesize);
-                memcpy(m_apoByteArrays[nCountBinaryField]->byteArray, bytes, bytesize);
-                m_apoByteArrays[nCountBinaryField]->inUseLength = bytesize;
-                hr = fgdb_row.SetBinary(wfield_name, *(m_apoByteArrays[nCountBinaryField]));
-            }
-            else
-            {
-                hr = fgdb_row.SetNull(wfield_name);
-            }
-            nCountBinaryField ++;
-        }
-        else
-        {
-            /* We can't handle this type */
-            CPLError( CE_Failure, CPLE_AppDefined,
-                "FGDB driver does not support OGR type." );
-            return OGRERR_FAILURE;
-        }
-        
-        if (FAILED(hr))
-        {
-            CPLError(CE_Warning, CPLE_AppDefined, "Cannot set value for field %s",
-                     field_name.c_str());
-        }
-    }
-
-    if ( m_pFeatureDefn->GetGeomType() != wkbNone )
-    {
-        /* Done with attribute fields, now do geometry */
-        OGRGeometry *poGeom = poFeature->GetGeometryRef();
-
-        if (poGeom == NULL || poGeom->IsEmpty())
-        {
-            /* EMPTY geometries should be treated as NULL, see #4832 */
-            hr = fgdb_row.SetNull(StringToWString(m_strShapeFieldName));
-            if (FAILED(hr))
-            {
-                GDBErr(hr, "Failed at writing EMPTY Geometry to Row in CreateFeature.");
-                return OGRERR_FAILURE;
-            }
-        }
-        else
-        {
-            /* Write geometry to a buffer */
-            GByte *pabyShape = NULL;
-            int nShapeSize = 0;
-            OGRErr err;
-
-            if( m_bCreateMultipatch && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
-            {
-                err = OGRWriteMultiPatchToShapeBin( poGeom, &pabyShape, &nShapeSize );
-            }
-            else
-            {
-                err = OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize );
-            }
-            if ( err != OGRERR_NONE )
-            {
-                CPLFree(pabyShape);
-                return err;
-            }
-
-            /* Copy it into a ShapeBuffer */
-            if ( nShapeSize > 0 )
-            {
-                shape.Allocate(nShapeSize);
-                memcpy(shape.shapeBuffer, pabyShape, nShapeSize);
-                shape.inUseLength = nShapeSize;
-            }
-
-            /* Free the shape buffer */
-            CPLFree(pabyShape);
-
-            /* Write ShapeBuffer into the Row */
-            hr = fgdb_row.SetGeometry(shape);
-            if (FAILED(hr))
-            {
-                GDBErr(hr, "Failed at writing Geometry to Row in CreateFeature.");
-                return OGRERR_FAILURE;
-            }
-        }
-    }
-
-    return OGRERR_NONE;
-
-}
-
-/************************************************************************/
-/*                             GetRow()                                 */
-/************************************************************************/
-
-OGRErr FGdbLayer::GetRow( EnumRows& enumRows, Row& row, GIntBig nFID )
-{
-    long           hr;
-    CPLString      osQuery;
-    
-    /* Querying a 64bit FID causes a runtime exception in FileGDB... */
-    if( !CPL_INT64_FITS_ON_INT32(nFID) )
-    {
-        return OGRERR_FAILURE;
-    }
-
-    osQuery.Printf("%s = " CPL_FRMT_GIB, m_strOIDFieldName.c_str(), nFID);
-
-    if (FAILED(hr = m_pTable->Search(m_wstrSubfields, StringToWString(osQuery.c_str()), true, enumRows)))
-    {
-        GDBErr(hr, "Failed fetching row ");
-        return OGRERR_FAILURE;
-    }
-
-    if (FAILED(hr = enumRows.Next(row)))
-    {
-        GDBErr(hr, "Failed fetching row ");
-        return OGRERR_FAILURE;
-    }
-
-    if (hr != S_OK)
-        return OGRERR_NON_EXISTING_FEATURE; //none found - but no failure
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           DeleteFeature()                            */
-/************************************************************************/
-
-OGRErr FGdbLayer::DeleteFeature( GIntBig nFID )
-
-{
-    long           hr;
-    EnumRows       enumRows;
-    Row            row;
-
-    if( !m_pDS->GetUpdate() || m_pTable == NULL )
-        return OGRERR_FAILURE;
-    if( !CPL_INT64_FITS_ON_INT32(nFID) )
-        return OGRERR_NON_EXISTING_FEATURE;
-
-    if( m_bSymlinkFlag && !CreateRealCopy() )
-        return OGRERR_FAILURE;
-
-    int nFID32 = (int)nFID;
-    std::map<int,int>::iterator oIter = m_oMapOGRFIDToFGDBFID.find(nFID32);
-    if( oIter != m_oMapOGRFIDToFGDBFID.end() )
-    {
-        nFID32 = oIter->second;
-        m_oMapFGDBFIDToOGRFID.erase(nFID32);
-        m_oMapOGRFIDToFGDBFID.erase(oIter);
-    }
-    else if( m_oMapFGDBFIDToOGRFID.find(nFID32) != m_oMapFGDBFIDToOGRFID.end() )
-        return OGRERR_NON_EXISTING_FEATURE;
-
-    EndBulkLoad();
-
-    OGRErr eErr = GetRow(enumRows, row, nFID32);
-    if( eErr != OGRERR_NONE)
-        return eErr;
-
-    if (FAILED(hr = m_pTable->Delete(row)))
-    {
-        GDBErr(hr, "Failed deleting row ");
-        return OGRERR_FAILURE;
-    }
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                            ISetFeature()                              */
-/************************************************************************/
-
-OGRErr FGdbLayer::ISetFeature( OGRFeature* poFeature )
-
-{
-    long           hr;
-    EnumRows       enumRows;
-    Row            row;
-
-    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
-        return OGRERR_FAILURE;
-
-    GIntBig nFID64 = poFeature->GetFID();
-    if( nFID64 == OGRNullFID )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "SetFeature() with unset FID fails." );
-        return OGRERR_FAILURE;
-    }
-    if( !CPL_INT64_FITS_ON_INT32(nFID64) )
-        return OGRERR_NON_EXISTING_FEATURE;
-
-    EndBulkLoad();
-
-    if( m_bSymlinkFlag && !CreateRealCopy() )
-        return OGRERR_FAILURE;
-
-    int nFID = (int)nFID64;
-    std::map<int,int>::iterator oIter = m_oMapOGRFIDToFGDBFID.find(nFID);
-    if( oIter != m_oMapOGRFIDToFGDBFID.end() )
-        nFID = oIter->second;
-    else if( m_oMapFGDBFIDToOGRFID.find((int)poFeature->GetFID()) != m_oMapFGDBFIDToOGRFID.end() )
-        return OGRERR_NON_EXISTING_FEATURE;
-
-    OGRErr eErr = GetRow(enumRows, row, nFID);
-    if( eErr != OGRERR_NONE)
-        return eErr;
-
-    /* Populate the row with the feature content */
-    if (PopulateRowWithFeature(row, poFeature) != OGRERR_NONE)
-        return OGRERR_FAILURE;
-
-    if (FAILED(hr = m_pTable->Update(row)))
-    {
-        GDBErr(hr, "Failed updating row ");
-        return OGRERR_FAILURE;
-    }
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                          CreateFieldDefn()                           */
-/************************************************************************/
-
-char* FGdbLayer::CreateFieldDefn(OGRFieldDefn& oField,
-                                 int bApproxOK,
-                                 std::string& fieldname_clean,
-                                 std::string& gdbFieldType)
-{
-    std::string fieldname = oField.GetNameRef();
-    std::string fidname = std::string(GetFIDColumn());
-    std::string nullable = (oField.IsNullable()) ? "true" : "false";
-
-    /* Try to map the OGR type to an ESRI type */
-    OGRFieldType fldtype = oField.GetType();
-    if ( ! OGRToGDBFieldType(fldtype, oField.GetSubType(), &gdbFieldType) )
-    {
-        GDBErr(-1, "Failed converting field type.");
-        return NULL;
-    }
-    
-    if( oField.GetType() == OFTInteger64 && !bApproxOK )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Integer64 not supported in FileGDB");
-        return NULL;
-    }
-
-    const char* pszColumnTypes = CSLFetchNameValue(m_papszOptions, "COLUMN_TYPES");
-    if( pszColumnTypes != NULL )
-    {
-        char** papszTokens = CSLTokenizeString2(pszColumnTypes, ",", 0);
-        const char* pszFieldType = CSLFetchNameValue(papszTokens, fieldname.c_str());
-        if( pszFieldType != NULL )
-        {
-            OGRFieldType fldtypeCheck;
-            OGRFieldSubType eSubType;
-            if( GDBToOGRFieldType(pszFieldType, &fldtypeCheck, &eSubType) )
-            {
-                if( fldtypeCheck != fldtype )
-                {
-                    CPLError(CE_Warning, CPLE_AppDefined, "Ignoring COLUMN_TYPES=%s=%s : %s not consistent with OGR data type",
-                         fieldname.c_str(), pszFieldType, pszFieldType);
-                }
-                else
-                    gdbFieldType = pszFieldType;
-            }
-            else
-                CPLError(CE_Warning, CPLE_AppDefined, "Ignoring COLUMN_TYPES=%s=%s : %s not recognized",
-                         fieldname.c_str(), pszFieldType, pszFieldType);
-        }
-        CSLDestroy(papszTokens);
-    }
-
-    if (fieldname_clean.size() != 0)
-    {
-        oField.SetName(fieldname_clean.c_str());
-    }
-    else
-    {
-        /* Clean field names */
-        fieldname_clean = FGDBLaunderName(fieldname);
-
-        if (m_bLaunderReservedKeywords)
-            fieldname_clean = FGDBEscapeReservedKeywords(fieldname_clean);
-
-        /* Truncate to 64 characters */
-        if (fieldname_clean.size() > 64)
-            fieldname_clean.resize(64);
-
-        std::string temp_fieldname = fieldname_clean;
-
-        /* Ensures uniqueness of field name */
-        int numRenames = 1;
-        while ((m_pFeatureDefn->GetFieldIndex(temp_fieldname.c_str()) >= 0) && (numRenames < 10))
-        {
-            temp_fieldname = CPLSPrintf("%s_%d", fieldname_clean.substr(0, 62).c_str(), numRenames);
-            numRenames ++;
-        }
-        while ((m_pFeatureDefn->GetFieldIndex(temp_fieldname.c_str()) >= 0) && (numRenames < 100))
-        {
-            temp_fieldname = CPLSPrintf("%s_%d", fieldname_clean.substr(0, 61).c_str(), numRenames);
-            numRenames ++;
-        }
-
-        if (temp_fieldname != fieldname)
-        {
-            if( !bApproxOK || (m_pFeatureDefn->GetFieldIndex(temp_fieldname.c_str()) >= 0) )
-            {
-                CPLError( CE_Failure, CPLE_NotSupported,
-                    "Failed to add field named '%s'",
-                    fieldname.c_str() );
-                return NULL;
-            }
-            CPLError(CE_Warning, CPLE_NotSupported,
-                "Normalized/laundered field name: '%s' to '%s'",
-                fieldname.c_str(), temp_fieldname.c_str());
-
-            fieldname_clean = temp_fieldname;
-            oField.SetName(fieldname_clean.c_str());
-        }
-    }
-
-    /* Then the Field definition */
-    CPLXMLNode *defn_xml = CPLCreateXMLNode(NULL, CXT_Element, "esri:Field");
-
-    /* Add the XML attributes to the Field node */
-    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
-    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xs", "http://www.w3.org/2001/XMLSchema");
-    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:esri", "http://www.esri.com/schemas/ArcGIS/10.1");
-    FGDB_CPLAddXMLAttribute(defn_xml, "xsi:type", "esri:Field");
-
-    /* Basic field information */
-    CPLCreateXMLElementAndValue(defn_xml, "Name", fieldname_clean.c_str());
-    CPLCreateXMLElementAndValue(defn_xml, "Type", gdbFieldType.c_str());
-    CPLCreateXMLElementAndValue(defn_xml, "IsNullable", nullable.c_str());
-
-    /* Get the Width and Precision if we know them */
-    int width = oField.GetWidth();
-    int precision = oField.GetPrecision();
-    if ( width <= 0 )
-        GDBFieldTypeToWidthPrecision(gdbFieldType, &width, &precision);
-
-    /* Write out the Width and Precision */
-    char buf[100];
-    snprintf(buf, 100, "%d", width);
-    CPLCreateXMLElementAndValue(defn_xml,"Length", buf);
-    snprintf(buf, 100, "%d", precision);
-    CPLCreateXMLElementAndValue(defn_xml,"Precision", buf);
-
-    /* We know nothing about Scale, so zero it out */
-    CPLCreateXMLElementAndValue(defn_xml,"Scale", "0");
-
-    /*  Attempt to preserve the original fieldname */
-    if (fieldname != fieldname_clean)
-    {
-        CPLCreateXMLElementAndValue(defn_xml, "AliasName", fieldname.c_str());
-    }
-
-    if( oField.GetDefault() != NULL )
-    {
-        const char* pszDefault = oField.GetDefault();
-        /*int nYear, nMonth, nDay, nHour, nMinute;
-        float fSecond;*/
-        if( oField.GetType() == OFTString )
-        {
-            CPLString osVal = pszDefault;
-            if( osVal[0] == '\'' && osVal[osVal.size()-1] == '\'' )
-            {
-                osVal = osVal.substr(1);
-                osVal.resize(osVal.size()-1);
-                char* pszTmp = CPLUnescapeString(osVal, NULL, CPLES_SQL);
-                osVal = pszTmp;
-                CPLFree(pszTmp);
-            }
-            CPLXMLNode* psDefaultValue =
-                CPLCreateXMLElementAndValue(defn_xml, "DefaultValue", osVal);
-            FGDB_CPLAddXMLAttribute(psDefaultValue, "xsi:type", "xs:string");
-        }
-        else if( oField.GetType() == OFTInteger &&
-                 !EQUAL(gdbFieldType.c_str(), "esriFieldTypeSmallInteger") &&
-                 CPLGetValueType(pszDefault) == CPL_VALUE_INTEGER )
-        {
-            CPLXMLNode* psDefaultValue =
-                CPLCreateXMLElementAndValue(defn_xml, "DefaultValue", pszDefault);
-            FGDB_CPLAddXMLAttribute(psDefaultValue, "xsi:type", "xs:int");
-        }
-        else if( oField.GetType() == OFTReal &&
-                 !EQUAL(gdbFieldType.c_str(), "esriFieldTypeSingle") &&
-                 CPLGetValueType(pszDefault) != CPL_VALUE_STRING )
-        {
-            CPLXMLNode* psDefaultValue =
-                CPLCreateXMLElementAndValue(defn_xml, "DefaultValue", pszDefault);
-            FGDB_CPLAddXMLAttribute(psDefaultValue, "xsi:type", "xs:double");
-        }
-        /*else if( oField.GetType() == OFTDateTime &&
-                 sscanf(pszDefault, "'%d/%d/%d %d:%d:%f'", &nYear, &nMonth, &nDay,
-                        &nHour, &nMinute, &fSecond) == 6 )
-        {
-            CPLXMLNode* psDefaultValue =
-                CPLCreateXMLElementAndValue(defn_xml, "DefaultValue",
-                    CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
-                               nYear, nMonth, nDay, nHour, nMinute, (int)(fSecond + 0.5)));
-            FGDB_CPLAddXMLAttribute(psDefaultValue, "xsi:type", "xs:dateTime");
-        }*/
-    }
-    /* <DefaultValue xsi:type="xs:string">afternoon</DefaultValue> */
-
-    /* Convert our XML tree into a string for FGDB */
-    char *defn_str = CPLSerializeXMLTree(defn_xml);
-    CPLDebug("FGDB", "CreateField() generated XML for FGDB\n%s", defn_str);
-
-    /* Free the XML */
-    CPLDestroyXMLNode(defn_xml);
-
-    return defn_str;
-}
-
-/************************************************************************/
-/*                            CreateField()                             */
-/*  Build up an FGDB XML field definition and use it to create a Field  */
-/*  Update the OGRFeatureDefn to reflect the new field.                 */
-/*                                                                      */
-/************************************************************************/
-
-OGRErr FGdbLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
-{
-    OGRFieldDefn oField(poField);
-    std::string fieldname_clean;
-    std::string gdbFieldType;
-
-    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
-        return OGRERR_FAILURE;
-
-    char* defn_str = CreateFieldDefn(oField, bApproxOK,
-                                     fieldname_clean, gdbFieldType);
-    if (defn_str == NULL)
-        return OGRERR_FAILURE;
-
-    /* Add the FGDB Field to the FGDB Table. */
-    fgdbError hr = m_pTable->AddField(defn_str);
-
-    CPLFree(defn_str);
-
-    /* Check the status of the Field add */
-    if (FAILED(hr))
-    {
-        GDBErr(hr, "Failed at creating Field for " + std::string(oField.GetNameRef()));
-        return OGRERR_FAILURE;
-    }
-
-    /* Now add the OGRFieldDefn to the OGRFeatureDefn */
-    m_pFeatureDefn->AddFieldDefn(&oField);
-
-    m_vOGRFieldToESRIField.push_back(StringToWString(fieldname_clean));
-    m_vOGRFieldToESRIFieldType.push_back( gdbFieldType );
-    
-    if( oField.GetType() == OFTBinary )
-        m_apoByteArrays.push_back(new ByteArray());
-
-    /* All done and happy */
-    return OGRERR_NONE;
-
-}
-
-/************************************************************************/
-/*                             DeleteField()                            */
-/************************************************************************/
-
-OGRErr FGdbLayer::DeleteField( int iFieldToDelete )
-{
-
-    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
-        return OGRERR_FAILURE;
-
-    if (iFieldToDelete < 0 || iFieldToDelete >= m_pFeatureDefn->GetFieldCount())
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Invalid field index");
-        return OGRERR_FAILURE;
-    }
-
-    ResetReading();
-
-    const char* pszFieldName = m_pFeatureDefn->GetFieldDefn(iFieldToDelete)->GetNameRef();
-
-    fgdbError hr;
-    if (FAILED(hr = m_pTable->DeleteField(StringToWString(pszFieldName))))
-    {
-        GDBErr(hr, "Failed deleting field " + std::string(pszFieldName));
-        return OGRERR_FAILURE;
-    }
-
-    m_vOGRFieldToESRIField.erase (m_vOGRFieldToESRIField.begin() + iFieldToDelete);
-    m_vOGRFieldToESRIFieldType.erase( m_vOGRFieldToESRIFieldType.begin() + iFieldToDelete );
-
-
-    return m_pFeatureDefn->DeleteFieldDefn( iFieldToDelete );
-}
-
-#ifdef AlterFieldDefn_implemented_but_not_working
-
-/************************************************************************/
-/*                           AlterFieldDefn()                           */
-/************************************************************************/
-
-OGRErr FGdbLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags )
-{
-
-    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
-        return OGRERR_FAILURE;
-
-    if (iFieldToAlter < 0 || iFieldToAlter >= m_pFeatureDefn->GetFieldCount())
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Invalid field index");
-        return OGRERR_FAILURE;
-    }
-
-    OGRFieldDefn* poFieldDefn = m_pFeatureDefn->GetFieldDefn(iFieldToAlter);
-    OGRFieldDefn oField(poFieldDefn);
-
-    if (nFlags & ALTER_TYPE_FLAG)
-    {
-        oField.SetSubType(OFSTNone);
-        oField.SetType(poNewFieldDefn->GetType());
-        oField.SetSubType(poNewFieldDefn->GetSubType());
-    }
-    if (nFlags & ALTER_NAME_FLAG)
-    {
-        if (strcmp(poNewFieldDefn->GetNameRef(), oField.GetNameRef()) != 0)
-        {
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "Altering field name is not supported" );
-            return OGRERR_FAILURE;
-        }
-        oField.SetName(poNewFieldDefn->GetNameRef());
-    }
-    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
-    {
-        oField.SetWidth(poNewFieldDefn->GetWidth());
-        oField.SetPrecision(poNewFieldDefn->GetPrecision());
-    }
-
-    std::string fieldname_clean = WStringToString(m_vOGRFieldToESRIField[iFieldToAlter]);
-    std::string gdbFieldType;
-
-    char* defn_str = CreateFieldDefn(oField, TRUE,
-                                     fieldname_clean, gdbFieldType);
-    if (defn_str == NULL)
-        return OGRERR_FAILURE;
-
-    ResetReading();
-
-    /* Add the FGDB Field to the FGDB Table. */
-    fgdbError hr = m_pTable->AlterField(defn_str);
-
-    CPLFree(defn_str);
-
-    /* Check the status of the AlterField */
-    if (FAILED(hr))
-    {
-        GDBErr(hr, "Failed at altering field " + std::string(oField.GetNameRef()));
-        return OGRERR_FAILURE;
-    }
-
-    m_vOGRFieldToESRIFieldType[iFieldToAlter] = gdbFieldType;
-
-    poFieldDefn->SetSubType(OFSTNone);
-    poFieldDefn->SetType(oField.GetType());
-    poFieldDefn->SetType(oField.GetSubType());
-    poFieldDefn->SetWidth(oField.GetWidth());
-    poFieldDefn->SetPrecision(oField.GetPrecision());
-
-    return OGRERR_NONE;
-}
-#endif // AlterFieldDefn_implemented_but_not_working
-
-/************************************************************************/
-/*                      XMLSpatialReference()                           */
-/*  Build up an XML representation of an OGRSpatialReference.           */
-/*  Used in layer creation.                                             */
-/*                                                                      */
-/************************************************************************/
-
-static CPLXMLNode* XMLSpatialReference(OGRSpatialReference* poSRS, char** papszOptions)
-{
-    /* We always need a SpatialReference */
-    CPLXMLNode *srs_xml = CPLCreateXMLNode(NULL, CXT_Element, "SpatialReference");
-
-    /* Extract the WKID before morphing */
-    int nSRID = 0;
-    if ( poSRS && poSRS->GetAuthorityCode(NULL) )
-    {
-        nSRID = atoi(poSRS->GetAuthorityCode(NULL));
-    }
-
-    /* NULL poSRS => UnknownCoordinateSystem */
-    if ( ! poSRS )
-    {
-        FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:UnknownCoordinateSystem");
-    }
-    else
-    {
-        /* Set the SpatialReference type attribute correctly for GEOGCS/PROJCS */
-        if ( poSRS->IsProjected() )
-            FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:ProjectedCoordinateSystem");
-        else
-            FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:GeographicCoordinateSystem");
-
-        /* Add the WKT to the XML */
-        SpatialReferenceInfo oESRI_SRS;
-
-        /* Do we have a known SRID ? If so, directly query the ESRI SRS DB */
-        if( nSRID && SpatialReferences::FindSpatialReferenceBySRID(nSRID, oESRI_SRS) )
-        {
-            CPLDebug("FGDB",
-                     "Layer SRS has a SRID (%d). Using WKT from ESRI SRS DBFound perfect match. ",
-                     nSRID);
-            CPLCreateXMLElementAndValue(srs_xml,"WKT", WStringToString(oESRI_SRS.srtext).c_str());
-        }
-        else
-        {
-            /* Make a clone so we can morph it without morphing the original */
-            OGRSpatialReference* poSRSClone = poSRS->Clone();
-
-            /* Flip the WKT to ESRI form, return UnknownCoordinateSystem if we can't */
-            if ( poSRSClone->morphToESRI() != OGRERR_NONE )
-            {
-                delete poSRSClone;
-                FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:UnknownCoordinateSystem");
-                return srs_xml;
-            }
-
-            char *wkt = NULL;
-            poSRSClone->exportToWkt(&wkt);
-            if (wkt)
-            {
-                EnumSpatialReferenceInfo oEnumESRI_SRS;
-                std::vector<int> oaiCandidateSRS;
-                nSRID = 0;
-
-                /* Enumerate SRS from ESRI DB and find a match */
-                while( true )
-                {
-                    if ( poSRS->IsProjected() )
-                    {
-                        if( !oEnumESRI_SRS.NextProjectedSpatialReference(oESRI_SRS) )
-                            break;
-                    }
-                    else
-                    {
-                        if( !oEnumESRI_SRS.NextGeographicSpatialReference(oESRI_SRS) )
-                            break;
-                    }
-
-                    std::string osESRI_WKT = WStringToString(oESRI_SRS.srtext);
-                    const char* pszESRI_WKT = osESRI_WKT.c_str();
-                    if( strcmp(pszESRI_WKT, wkt) == 0 )
-                    {
-                        /* Exact match found (not sure this case happens) */
-                        nSRID = oESRI_SRS.auth_srid;
-                        break;
-                    }
-                    OGRSpatialReference oSRS_FromESRI;
-                    if( oSRS_FromESRI.SetFromUserInput(pszESRI_WKT) == OGRERR_NONE &&
-                        poSRSClone->IsSame(&oSRS_FromESRI) )
-                    {
-                        /* Potential match found */
-                        oaiCandidateSRS.push_back(oESRI_SRS.auth_srid);
-                    }
-                }
-
-                if( nSRID != 0 )
-                {
-                    CPLDebug("FGDB",
-                             "Found perfect match in ESRI SRS DB "
-                             "for layer SRS. SRID is %d", nSRID);
-                }
-                else if( oaiCandidateSRS.size() == 0 )
-                {
-                     CPLDebug("FGDB",
-                              "Did not found a match in ESRI SRS DB for layer SRS. "
-                              "Using morphed SRS WKT. Failure is to be expected");
-                }
-                else if( oaiCandidateSRS.size() == 1 )
-                {
-                    nSRID = oaiCandidateSRS[0];
-                    if( SpatialReferences::FindSpatialReferenceBySRID(
-                                                            nSRID, oESRI_SRS) )
-                    {
-                        CPLDebug("FGDB",
-                                 "Found a single match in ESRI SRS DB "
-                                 "for layer SRS. SRID is %d",
-                                 nSRID);
-                        nSRID = oESRI_SRS.auth_srid;
-                        OGRFree(wkt);
-                        wkt = CPLStrdup(WStringToString(oESRI_SRS.srtext).c_str());
-                    }
-                }
-                else
-                {
-                    /* Not sure this case can happen */
-
-                    CPLString osCandidateSRS;
-                    for(int i=0; i<(int)oaiCandidateSRS.size() && i < 10; i++)
-                    {
-                        if( osCandidateSRS.size() )
-                            osCandidateSRS += ", ";
-                        osCandidateSRS += CPLSPrintf("%d", oaiCandidateSRS[i]);
-                    }
-                    if(oaiCandidateSRS.size() > 10)
-                        osCandidateSRS += "...";
-
-                    CPLDebug("FGDB",
-                             "As several candidates (%s) have been found in "
-                             "ESRI SRS DB for layer SRS, none has been selected. "
-                             "Using morphed SRS WKT. Failure is to be expected",
-                             osCandidateSRS.c_str());
-                }
-
-                CPLCreateXMLElementAndValue(srs_xml,"WKT", wkt);
-                OGRFree(wkt);
-            }
-
-            /* Dispose of our close */
-            delete poSRSClone;
-        }
-    }
-    
-    /* Handle Origin/Scale/Tolerance */
-    const char* grid[7] = {
-      "XOrigin", "YOrigin", "XYScale",
-      "ZOrigin", "ZScale",
-      "XYTolerance", "ZTolerance" };
-    const char* gridvalues[7];
-
-    /* 
-    Need different default parameters for geographic and projected coordinate systems.
-    Try and use ArcGIS 10 default values.
-    */
-    // default tolerance is 1mm in the units of the coordinate system
-    double ztol = 0.001 * (poSRS ? poSRS->GetTargetLinearUnits("VERT_CS") : 1.0);
-    // default scale is 10x the tolerance
-    long zscale = (long)(1 / ztol * 10);
-
-    char s_xyscale[50], s_xytol[50], s_zscale[50], s_ztol[50];
-    CPLsnprintf(s_ztol, 50, "%f", ztol);
-    snprintf(s_zscale, 50, "%ld", zscale);
-    
-    if ( poSRS == NULL || poSRS->IsProjected() )
-    {
-        // default tolerance is 1mm in the units of the coordinate system
-        double xytol = 0.001 * (poSRS ? poSRS->GetTargetLinearUnits("PROJCS") : 1.0);
-        // default scale is 10x the tolerance
-        long xyscale = (long)(1 / xytol * 10);
-
-        CPLsnprintf(s_xytol, 50, "%f", xytol);
-        snprintf(s_xyscale, 50, "%ld", xyscale);
-
-        // Ideally we would use the same X/Y origins as ArcGIS, but we need the algorithm they use.
-        gridvalues[0] = "-2147483647";
-        gridvalues[1] = "-2147483647";
-        gridvalues[2] = s_xyscale;
-        gridvalues[3] = "-100000";
-        gridvalues[4] = s_zscale;
-        gridvalues[5] = s_xytol;
-        gridvalues[6] = s_ztol;
-    }
-    else
-    {
-        gridvalues[0] = "-400";
-        gridvalues[1] = "-400";
-        gridvalues[2] = "1000000000";
-        gridvalues[3] = "-100000";
-        gridvalues[4] = s_zscale;
-        gridvalues[5] = "0.000000008983153";
-        gridvalues[6] = s_ztol;
-    }
-
-    /* Convert any layer creation options available, use defaults otherwise */
-    for( int i = 0; i < 7; i++ )
-    {
-        if ( CSLFetchNameValue( papszOptions, grid[i] ) != NULL )
-            gridvalues[i] = CSLFetchNameValue( papszOptions, grid[i] );
-
-        CPLCreateXMLElementAndValue(srs_xml, grid[i], gridvalues[i]);
-    }
-
-    /* FGDB is always High Precision */
-    CPLCreateXMLElementAndValue(srs_xml, "HighPrecision", "true");     
-
-    /* Add the WKID to the XML */
-    if ( nSRID ) 
-    {
-        CPLCreateXMLElementAndValue(srs_xml, "WKID", CPLSPrintf("%d", nSRID));
-    }
-
-    return srs_xml;
-}
-
-/************************************************************************/
-/*                    CreateFeatureDataset()                            */
-/************************************************************************/
-
-bool FGdbLayer::CreateFeatureDataset(FGdbDataSource* pParentDataSource, 
-                                     std::string feature_dataset_name,
-                                     OGRSpatialReference* poSRS,
-                                     char** papszOptions )
-{
-    /* XML node */
-    CPLXMLNode *xml_xml = CPLCreateXMLNode(NULL, CXT_Element, "?xml");
-    FGDB_CPLAddXMLAttribute(xml_xml, "version", "1.0");
-    FGDB_CPLAddXMLAttribute(xml_xml, "encoding", "UTF-8");
-
-    /* First build up a bare-bones feature definition */
-    CPLXMLNode *defn_xml = CPLCreateXMLNode(NULL, CXT_Element, "esri:DataElement");
-    CPLAddXMLSibling(xml_xml, defn_xml);
-
-    /* Add the attributes to the DataElement */
-    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
-    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xs", "http://www.w3.org/2001/XMLSchema");
-    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:esri", "http://www.esri.com/schemas/ArcGIS/10.1");
-
-    /* Need to set this to esri:DEFeatureDataset or esri:DETable */
-    FGDB_CPLAddXMLAttribute(defn_xml, "xsi:type", "esri:DEFeatureDataset");
-
-    /* Add in more children */
-    std::string catalog_page = "\\" + feature_dataset_name;
-    CPLCreateXMLElementAndValue(defn_xml,"CatalogPath", catalog_page.c_str());
-    CPLCreateXMLElementAndValue(defn_xml,"Name", feature_dataset_name.c_str());
-    CPLCreateXMLElementAndValue(defn_xml,"ChildrenExpanded", "false");
-    CPLCreateXMLElementAndValue(defn_xml,"DatasetType", "esriDTFeatureDataset");
-    CPLCreateXMLElementAndValue(defn_xml,"Versioned", "false");
-    CPLCreateXMLElementAndValue(defn_xml,"CanVersion", "false");
-
-    /* Add in empty extent */
-    CPLXMLNode *extent_xml = CPLCreateXMLNode(NULL, CXT_Element, "Extent");
-    FGDB_CPLAddXMLAttribute(extent_xml, "xsi:nil", "true");
-    CPLAddXMLChild(defn_xml, extent_xml);
-
-    /* Add the SRS */
-    if( true ) // TODO: conditional on existence of SRS
-    {
-        CPLXMLNode *srs_xml = XMLSpatialReference(poSRS, papszOptions);
-        if ( srs_xml )
-            CPLAddXMLChild(defn_xml, srs_xml);
-    }
-
-    /* Convert our XML tree into a string for FGDB */
-    char *defn_str = CPLSerializeXMLTree(xml_xml);
-    CPLDestroyXMLNode(xml_xml);
-
-    /* TODO, tie this to debugging levels */
-    CPLDebug("FGDB", "%s", defn_str);
-
-    /* Create the FeatureDataset. */
-    Geodatabase *gdb = pParentDataSource->GetGDB();
-    fgdbError hr = gdb->CreateFeatureDataset(defn_str);
-
-    /* Free the XML */
-    CPLFree(defn_str);
-
-    /* Check table create status */
-    if (FAILED(hr))
-    {
-        return GDBErr(hr, "Failed at creating FeatureDataset " + feature_dataset_name);
-    }
-
-    return true;
-}
-
-/************************************************************************/
-/*                            Create()                                  */
-/* Build up an FGDB XML layer definition and use it to create a Table   */
-/* or Feature Class to work from.                                       */
-/*                                                                      */
-/* Layer creation options:                                              */
-/*   FEATURE_DATASET, nest layer inside a FeatureDataset folder         */
-/*   GEOMETRY_NAME, user-selected name for the geometry column          */
-/*   FID/OID_NAME, user-selected name for the FID column                */
-/*   XORIGIN, YORIGIN, ZORIGIN, origin of the snapping grid             */
-/*   XYSCALE, ZSCALE, inverse resolution of the snapping grid           */
-/*   XYTOLERANCE, ZTOLERANCE, snapping tolerance for topology/networks  */
-/*                                                                      */
-/************************************************************************/
-
-bool FGdbLayer::Create(FGdbDataSource* pParentDataSource, 
-                       const char* pszLayerNameIn, 
-                       OGRSpatialReference* poSRS, 
-                       OGRwkbGeometryType eType, 
-                       char** papszOptions)
-{
-    std::string parent_path = "";
-    std::wstring wtable_path, wparent_path;
-    std::string geometry_name = FGDB_GEOMETRY_NAME;
-    std::string fid_name = FGDB_OID_NAME;
-    std::string esri_type;
-    bool has_z = false;
-    bool has_m = false;
-
-#ifdef EXTENT_WORKAROUND
-    m_bLayerJustCreated = true;
-#endif
-
-    /* Launder the Layer name */
-    std::string layerName = pszLayerNameIn;
-
-    layerName = FGDBLaunderName(pszLayerNameIn);
-    layerName = FGDBEscapeReservedKeywords(layerName);
-    layerName = FGDBEscapeUnsupportedPrefixes(layerName);
-
-    if (layerName.size() > 160)
-        layerName.resize(160);
-
-    /* Ensures uniqueness of layer name */
-    int numRenames = 1;
-    while ((pParentDataSource->GetLayerByName(layerName.c_str()) != NULL) && (numRenames < 10))
-    {
-        layerName = CPLSPrintf("%s_%d", layerName.substr(0, 158).c_str(), numRenames);
-        numRenames ++;
-    }
-    while ((pParentDataSource->GetLayerByName(layerName.c_str()) != NULL) && (numRenames < 100))
-    {
-        layerName = CPLSPrintf("%s_%d", layerName.substr(0, 157).c_str(), numRenames);
-        numRenames ++;
-    }
-
-    if (layerName != pszLayerNameIn)
-    {
-        CPLError(CE_Warning, CPLE_NotSupported,
-                "Normalized/laundered layer name: '%s' to '%s'",
-                pszLayerNameIn, layerName.c_str());
-    }
-
-    std::string table_path = "\\" + std::string(layerName);
-
-    /* Handle the FEATURE_DATASET case */
-    if (  CSLFetchNameValue( papszOptions, "FEATURE_DATASET") != NULL )
-    {
-        std::string feature_dataset = CSLFetchNameValue( papszOptions, "FEATURE_DATASET");
-
-        /* Check if FEATURE_DATASET exists. Otherwise create it */
-        std::vector<wstring> featuredatasets;
-        Geodatabase *gdb = pParentDataSource->GetGDB();
-        int bFeatureDataSetExists = FALSE;
-        fgdbError hr;
-        if ( !FAILED(hr = gdb->GetChildDatasets(L"\\", L"Feature Dataset", featuredatasets)) )
-        {
-            std::wstring feature_dataset_with_slash = L"\\" + StringToWString(feature_dataset);
-            for ( unsigned int i = 0; i < featuredatasets.size(); i++ )
-            {
-                if (featuredatasets[i] == feature_dataset_with_slash)
-                    bFeatureDataSetExists = TRUE;
-            }
-        }
-
-        if (!bFeatureDataSetExists)
-        {
-            bool rv = CreateFeatureDataset(pParentDataSource, feature_dataset, poSRS, papszOptions);
-            if ( ! rv )
-                return rv;
-        }
-
-        table_path = "\\" + feature_dataset + table_path;
-        parent_path = "\\" + feature_dataset;
-    }
-
-    /* Convert table_path into wstring */
-    wtable_path = StringToWString(table_path);
-    wparent_path = StringToWString(parent_path);
-
-    /* Over-ride the geometry name if necessary */
-    if ( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
-        geometry_name = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
-
-    /* Over-ride the OID name if necessary */
-    if ( CSLFetchNameValue( papszOptions, "FID") != NULL )
-        fid_name = CSLFetchNameValue( papszOptions, "FID");
-    else if ( CSLFetchNameValue( papszOptions, "OID_NAME") != NULL )
-        fid_name = CSLFetchNameValue( papszOptions, "OID_NAME");
-
-    /* Figure out our geometry type */
-    if ( eType != wkbNone )
-    {
-        if ( wkbFlatten(eType) == wkbUnknown )
-        {
-            return GDBErr(-1, "FGDB layers cannot be created with a wkbUnknown layer geometry type.");
-        }
-        if ( ! OGRGeometryToGDB(eType, &esri_type, &has_z, &has_m) )
-            return GDBErr(-1, "Unable to map OGR type to ESRI type");
-
-        if( wkbFlatten(eType) == wkbMultiPolygon &&
-            CPLTestBool(CSLFetchNameValueDef(papszOptions, "CREATE_MULTIPATCH", "NO")) )
-        {
-            esri_type = "esriGeometryMultiPatch";
-            has_z = true;
-        }
-    }
-
-    m_bLaunderReservedKeywords = CSLFetchBoolean( papszOptions, "LAUNDER_RESERVED_KEYWORDS", TRUE) == TRUE;
-
-    /* XML node */
-    CPLXMLNode *xml_xml = CPLCreateXMLNode(NULL, CXT_Element, "?xml");
-    FGDB_CPLAddXMLAttribute(xml_xml, "version", "1.0");
-    FGDB_CPLAddXMLAttribute(xml_xml, "encoding", "UTF-8");
-
-    /* First build up a bare-bones feature definition */
-    CPLXMLNode *defn_xml = CPLCreateXMLNode(NULL, CXT_Element, "esri:DataElement");
-    CPLAddXMLSibling(xml_xml, defn_xml);
-
-    /* Add the attributes to the DataElement */
-    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
-    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xs", "http://www.w3.org/2001/XMLSchema");
-    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:esri", "http://www.esri.com/schemas/ArcGIS/10.1");
-
-    /* Need to set this to esri:DEFeatureDataset or esri:DETable */
-    FGDB_CPLAddXMLAttribute(defn_xml, "xsi:type", (eType == wkbNone ? "esri:DETable" : "esri:DEFeatureClass"));
-
-    /* Add in more children */
-    CPLCreateXMLElementAndValue(defn_xml,"CatalogPath",table_path.c_str());
-    CPLCreateXMLElementAndValue(defn_xml,"Name", layerName.c_str());
-    CPLCreateXMLElementAndValue(defn_xml,"ChildrenExpanded", "false");
-
-    /* WKB type of none implies this is a 'Table' otherwise it's a 'Feature Class' */
-    std::string datasettype = (eType == wkbNone ? "esriDTTable" : "esriDTFeatureClass");
-    CPLCreateXMLElementAndValue(defn_xml,"DatasetType", datasettype.c_str() );
-    CPLCreateXMLElementAndValue(defn_xml,"Versioned", "false");
-    CPLCreateXMLElementAndValue(defn_xml,"CanVersion", "false");
-
-    if ( CSLFetchNameValue( papszOptions, "CONFIGURATION_KEYWORD") != NULL )
-        CPLCreateXMLElementAndValue(defn_xml,"ConfigurationKeyword",
-                                    CSLFetchNameValue( papszOptions, "CONFIGURATION_KEYWORD"));
-
-    /* We might need to make OID optional later, but OGR likes to have a FID */
-    CPLCreateXMLElementAndValue(defn_xml,"HasOID", "true");
-    CPLCreateXMLElementAndValue(defn_xml,"OIDFieldName", fid_name.c_str());
-
-    /* Add in empty Fields */
-    CPLXMLNode *fields_xml = CPLCreateXMLNode(defn_xml, CXT_Element, "Fields");
-    FGDB_CPLAddXMLAttribute(fields_xml, "xsi:type", "esri:Fields");
-    CPLXMLNode *fieldarray_xml = CPLCreateXMLNode(fields_xml, CXT_Element, "FieldArray");
-    FGDB_CPLAddXMLAttribute(fieldarray_xml, "xsi:type", "esri:ArrayOfField");
-
-    /* Feature Classes have an implicit geometry column, so we'll add it at creation time */
-    CPLXMLNode *srs_xml = NULL;
-    if ( eType != wkbNone )
-    {
-        CPLXMLNode *shape_xml = CPLCreateXMLNode(fieldarray_xml, CXT_Element, "Field");
-        FGDB_CPLAddXMLAttribute(shape_xml, "xsi:type", "esri:Field");
-        CPLCreateXMLElementAndValue(shape_xml, "Name", geometry_name.c_str());
-        CPLCreateXMLElementAndValue(shape_xml, "Type", "esriFieldTypeGeometry");
-        if( CSLFetchBoolean( papszOptions, "GEOMETRY_NULLABLE", TRUE) )
-            CPLCreateXMLElementAndValue(shape_xml, "IsNullable", "true");
-        else
-            CPLCreateXMLElementAndValue(shape_xml, "IsNullable", "false");
-        CPLCreateXMLElementAndValue(shape_xml, "Length", "0");
-        CPLCreateXMLElementAndValue(shape_xml, "Precision", "0");
-        CPLCreateXMLElementAndValue(shape_xml, "Scale", "0");
-        CPLCreateXMLElementAndValue(shape_xml, "Required", "true");
-        CPLXMLNode *geom_xml = CPLCreateXMLNode(shape_xml, CXT_Element, "GeometryDef");
-        FGDB_CPLAddXMLAttribute(geom_xml, "xsi:type", "esri:GeometryDef");
-        CPLCreateXMLElementAndValue(geom_xml, "AvgNumPoints", "0");
-        CPLCreateXMLElementAndValue(geom_xml, "GeometryType", esri_type.c_str());
-        CPLCreateXMLElementAndValue(geom_xml,"HasM", (has_m ? "true" : "false"));
-        CPLCreateXMLElementAndValue(geom_xml,"HasZ", (has_z ? "true" : "false"));
-
-        /* Add the SRS if we have one */
-        srs_xml = XMLSpatialReference(poSRS, papszOptions);
-        if ( srs_xml )
-            CPLAddXMLChild(geom_xml, srs_xml);
-    }
-
-    /* All (?) Tables and Feature Classes will have an ObjectID */
-    CPLXMLNode *oid_xml = CPLCreateXMLNode(fieldarray_xml, CXT_Element, "Field");
-    FGDB_CPLAddXMLAttribute(oid_xml, "xsi:type", "esri:Field");
-    CPLCreateXMLElementAndValue(oid_xml, "Name", fid_name.c_str());
-    CPLCreateXMLElementAndValue(oid_xml, "Type", "esriFieldTypeOID");
-    CPLCreateXMLElementAndValue(oid_xml, "IsNullable", "false");
-    CPLCreateXMLElementAndValue(oid_xml, "Length", "12");
-    CPLCreateXMLElementAndValue(oid_xml, "Precision", "0");
-    CPLCreateXMLElementAndValue(oid_xml, "Scale", "0");
-    CPLCreateXMLElementAndValue(oid_xml, "Required", "true");
-
-    /* Add in empty Indexes */
-    CPLXMLNode *indexes_xml = CPLCreateXMLNode(defn_xml, CXT_Element, "Indexes");
-    FGDB_CPLAddXMLAttribute(indexes_xml, "xsi:type", "esri:Indexes");
-    CPLXMLNode *indexarray_xml = CPLCreateXMLNode(indexes_xml, CXT_Element, "IndexArray");
-    FGDB_CPLAddXMLAttribute(indexarray_xml, "xsi:type", "esri:ArrayOfIndex");
-
-    /* CLSID http://forums.arcgis.com/threads/34536?p=118484#post118484 */
-    if ( eType == wkbNone )
-    {
-        CPLCreateXMLElementAndValue(defn_xml, "CLSID", "{7A566981-C114-11D2-8A28-006097AFF44E}");
-        CPLCreateXMLElementAndValue(defn_xml, "EXTCLSID", "");
-    }
-    else
-    {
-        CPLCreateXMLElementAndValue(defn_xml, "CLSID", "{52353152-891A-11D0-BEC6-00805F7C4268}");
-        CPLCreateXMLElementAndValue(defn_xml, "EXTCLSID", "");
-    }
-
-    /* Set the alias for the Feature Class */
-    if (pszLayerNameIn != layerName)
-    {
-        CPLCreateXMLElementAndValue(defn_xml, "AliasName", pszLayerNameIn);
-    }
-
-    /* Map from OGR WKB type to ESRI type */
-    if ( eType != wkbNone )
-    {
-        /* Declare our feature type */
-        CPLCreateXMLElementAndValue(defn_xml,"FeatureType", "esriFTSimple");
-        CPLCreateXMLElementAndValue(defn_xml,"ShapeType", esri_type.c_str());
-        CPLCreateXMLElementAndValue(defn_xml,"ShapeFieldName", geometry_name.c_str());
-
-        /* Dimensionality */
-        CPLCreateXMLElementAndValue(defn_xml,"HasM", (has_m ? "true" : "false"));
-        CPLCreateXMLElementAndValue(defn_xml,"HasZ", (has_z ? "true" : "false"));
-
-        /* TODO: Handle spatial indexes (layer creation option?) */
-        CPLCreateXMLElementAndValue(defn_xml,"HasSpatialIndex", "false");
-
-        /* These field are required for Arcmap to display aliases correctly */
-        CPLCreateXMLNode(defn_xml, CXT_Element, "AreaFieldName");
-        CPLCreateXMLNode(defn_xml, CXT_Element, "LengthFieldName");
-
-        /* We can't know the extent at this point <Extent xsi:nil='true'/> */
-        CPLXMLNode *extn_xml = CPLCreateXMLNode(defn_xml, CXT_Element, "Extent");
-        FGDB_CPLAddXMLAttribute(extn_xml, "xsi:nil", "true");
-    }
-
-    /* Feature Class with known SRS gets an SRS entry */
-    if( eType != wkbNone && srs_xml != NULL)
-    {
-        CPLAddXMLChild(defn_xml, CPLCloneXMLTree(srs_xml));
-    }
-
-    /* Convert our XML tree into a string for FGDB */
-    char *defn_str;
-    
-    if( CSLFetchNameValue( papszOptions, "XML_DEFINITION") != NULL )
-        defn_str = CPLStrdup(CSLFetchNameValue( papszOptions, "XML_DEFINITION"));
-    else
-        defn_str = CPLSerializeXMLTree(xml_xml);
-    CPLDestroyXMLNode(xml_xml);
-
-    /* TODO, tie this to debugging levels */
-    CPLDebug("FGDB", "%s", defn_str);
-    //std::cout << defn_str << std::endl;
-
-    /* Create the table. */
-    Table *table = new Table;
-    Geodatabase *gdb = pParentDataSource->GetGDB();
-    fgdbError hr = gdb->CreateTable(defn_str, wparent_path, *table);
-    
-    /* Free the XML */
-    CPLFree(defn_str);
-
-    /* Check table create status */
-    if (FAILED(hr))
-    {
-        delete table;
-        return GDBErr(hr, "Failed at creating table for " + table_path);
-    }
-
-    m_papszOptions = CSLDuplicate(papszOptions);
-    m_bCreateMultipatch = CPLTestBool(CSLFetchNameValueDef(m_papszOptions, "CREATE_MULTIPATCH", "NO"));
-    
-    // Default to YES here assuming ogr2ogr scenario
-    m_bBulkLoadAllowed = CPLTestBool(CPLGetConfigOption("FGDB_BULK_LOAD", "YES"));
-
-    /* Store the new FGDB Table pointer and set up the OGRFeatureDefn */
-    return FGdbLayer::Initialize(pParentDataSource, table, wtable_path, L"Table");
-}
-
-/*************************************************************************/
-/*                            Initialize()                               */
-/* Has ownership of the table as soon as it is called.                   */
-/************************************************************************/
-
-bool FGdbLayer::Initialize(FGdbDataSource* pParentDataSource, Table* pTable,
-                           std::wstring wstrTablePath, std::wstring wstrType)
-{
-    long hr;
-
-    m_pDS = pParentDataSource; // we never assume ownership of the parent - so our destructor should not delete
-
-    m_pTable = pTable;
-
-    m_wstrTablePath = wstrTablePath;
-    m_wstrType = wstrType;
-
-    wstring wstrQueryName;
-    if (FAILED(hr = pParentDataSource->GetGDB()->GetQueryName(wstrTablePath, wstrQueryName)))
-        return GDBErr(hr, "Failed at getting underlying table name for " +
-                      WStringToString(wstrTablePath));
-
-    m_strName = WStringToString(wstrQueryName);
-
-    m_pFeatureDefn = new OGRFeatureDefn(m_strName.c_str()); //TODO: Should I "new" an OGR smart pointer - sample says so, but it doesn't seem right
-    SetDescription( m_pFeatureDefn->GetName() );
-    //as long as we use the same compiler & settings in both the ogr build and this
-    //driver, we should be OK
-    m_pFeatureDefn->Reference();
-
-    string tableDef;
-    if (FAILED(hr = m_pTable->GetDefinition(tableDef)))
-        return GDBErr(hr, "Failed at getting table definition for " +
-                      WStringToString(wstrTablePath));
-
-    //xxx  printf("Table definition = %s", tableDef.c_str() );
-
-    bool abort = false;
-
-    // extract schema information from table
-    CPLXMLNode *psRoot = CPLParseXMLString( tableDef.c_str() );
-
-    if (psRoot == NULL)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, "%s",
-                  ("Failed parsing GDB Table Schema XML for " + m_strName).c_str());
-        return false;
-    }
-
-    CPLXMLNode *pDataElementNode = psRoot->psNext; // Move to next field which should be DataElement
-
-    if( pDataElementNode != NULL
-        && pDataElementNode->psChild != NULL
-        && pDataElementNode->eType == CXT_Element
-        && EQUAL(pDataElementNode->pszValue,"esri:DataElement") )
-    {
-        CPLXMLNode *psNode;
-
-        for( psNode = pDataElementNode->psChild;
-        psNode != NULL;
-        psNode = psNode->psNext )
-        {
-            if( psNode->eType == CXT_Element && psNode->psChild != NULL )
-            {
-                if (EQUAL(psNode->pszValue,"OIDFieldName") )
-                {
-                    char* pszUnescaped = CPLUnescapeString(
-                    psNode->psChild->pszValue, NULL, CPLES_XML);
-                    m_strOIDFieldName = pszUnescaped;
-                    CPLFree(pszUnescaped);
-                }
-                else if (EQUAL(psNode->pszValue,"ShapeFieldName") )
-                {
-                    char* pszUnescaped = CPLUnescapeString(
-                    psNode->psChild->pszValue, NULL, CPLES_XML);
-                    m_strShapeFieldName = pszUnescaped;
-                    CPLFree(pszUnescaped);
-                }
-                else if (EQUAL(psNode->pszValue,"Fields") )
-                {
-                    if (!GDBToOGRFields(psNode))
-                    {
-                        abort = true;
-                        break;
-                    }
-                }
-            }
-        }
-
-        if (m_strShapeFieldName.size() == 0)
-            m_pFeatureDefn->SetGeomType(wkbNone);
-    }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, "%s",
-                ("Failed parsing GDB Table Schema XML (DataElement) for " + m_strName).c_str());
-        return false;
-    }
-    CPLDestroyXMLNode( psRoot );
-
-    if( m_pFeatureDefn->GetGeomFieldCount() != 0 )
-    {
-        m_pFeatureDefn->GetGeomFieldDefn(0)->SetName(m_strShapeFieldName.c_str());
-        m_pFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_pSRS);
-    }
-
-    if (abort)
-        return false;
-
-    return true; //AOToOGRFields(ipFields, m_pFeatureDefn, m_vOGRFieldToESRIField);
-}
-
-/************************************************************************/
-/*                          ParseGeometryDef()                          */
-/************************************************************************/
-
-bool FGdbLayer::ParseGeometryDef(CPLXMLNode* psRoot)
-{
-    CPLXMLNode *psGeometryDefItem;
-
-    string geometryType;
-    bool hasZ = false, hasM = false;
-    string wkt, wkid, latestwkid;
-
-    for (psGeometryDefItem = psRoot->psChild;
-        psGeometryDefItem != NULL;
-        psGeometryDefItem = psGeometryDefItem->psNext )
-    {
-        //loop through all "GeometryDef" elements
-        //
-
-        if (psGeometryDefItem->eType == CXT_Element &&
-            psGeometryDefItem->psChild != NULL)
-        {
-            if (EQUAL(psGeometryDefItem->pszValue,"GeometryType"))
-            {
-                char* pszUnescaped = CPLUnescapeString(
-                    psGeometryDefItem->psChild->pszValue, NULL, CPLES_XML);
-
-                geometryType = pszUnescaped;
-
-                CPLFree(pszUnescaped);
-            }
-            else if (EQUAL(psGeometryDefItem->pszValue,"SpatialReference"))
-            {
-                ParseSpatialReference(psGeometryDefItem, &wkt, &wkid, &latestwkid); // we don't check for success because it
-                                                                // may not be there
-            }
-            else if (EQUAL(psGeometryDefItem->pszValue,"HasM"))
-            {
-                char* pszUnescaped = CPLUnescapeString(psGeometryDefItem->psChild->pszValue, NULL, CPLES_XML);
-
-                if (!strcmp(pszUnescaped, "true"))
-                    hasM = true;
-
-                CPLFree(pszUnescaped);
-            }
-            else if (EQUAL(psGeometryDefItem->pszValue,"HasZ"))
-            {
-                char* pszUnescaped = CPLUnescapeString(
-                    psGeometryDefItem->psChild->pszValue, NULL, CPLES_XML);
-
-                if (!strcmp(pszUnescaped, "true"))
-                hasZ = true;
-
-                CPLFree(pszUnescaped);
-            }
-        }
-
-    }
-
-    OGRwkbGeometryType ogrGeoType;
-    if (!GDBToOGRGeometry(geometryType, hasZ, hasM, &ogrGeoType))
-        return false;
-
-    m_pFeatureDefn->SetGeomType(ogrGeoType);
-
-    if (wkbFlatten(ogrGeoType) == wkbMultiLineString ||
-        wkbFlatten(ogrGeoType) == wkbMultiPoint)
-        m_forceMulti = true;
-
-    if (latestwkid.length() > 0 || wkid.length() > 0)
-    {
-        int bSuccess = FALSE;
-        m_pSRS = new OGRSpatialReference();
-        CPLPushErrorHandler(CPLQuietErrorHandler);
-        if( latestwkid.length() > 0 )
-        {
-            if( m_pSRS->importFromEPSG(atoi(latestwkid.c_str())) == OGRERR_NONE )
-            {
-                bSuccess = TRUE;
-            }
-            else
-            {
-                CPLDebug("FGDB", "Cannot import SRID %s", latestwkid.c_str());
-            }
-        }
-        if( !bSuccess && wkid.length() > 0 )
-        {
-            if( m_pSRS->importFromEPSG(atoi(wkid.c_str())) == OGRERR_NONE )
-            {
-                bSuccess = TRUE;
-            }
-            else
-            {
-                CPLDebug("FGDB", "Cannot import SRID %s", wkid.c_str());
-            }
-        }
-        CPLPopErrorHandler();
-        CPLErrorReset();
-        if( !bSuccess )
-        {
-            delete m_pSRS;
-            m_pSRS = NULL;
-        }
-        else
-            return true;
-    }
-
-    if (wkt.length() > 0)
-    {
-        if (!GDBToOGRSpatialReference(wkt, &m_pSRS))
-        {
-            //report error, but be passive about it
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Failed Mapping ESRI Spatial Reference");
-        }
-    }
-    else
-    {
-        //report error, but be passive about it
-        CPLError( CE_Warning, CPLE_AppDefined, "Empty Spatial Reference");
-    }
-
-    return true;
-}
-
-/************************************************************************/
-/*                        ParseSpatialReference()                       */
-/************************************************************************/
-
-bool FGdbLayer::ParseSpatialReference(CPLXMLNode* psSpatialRefNode,
-                                      string* pOutWkt, string* pOutWKID,
-                                      string* pOutLatestWKID)
-{
-    *pOutWkt = "";
-    *pOutWKID = "";
-    *pOutLatestWKID = "";
-
-    CPLXMLNode* psSRItemNode;
-
-    /* Loop through all the SRS elements we want to store */
-    for( psSRItemNode = psSpatialRefNode->psChild;
-         psSRItemNode != NULL;
-         psSRItemNode = psSRItemNode->psNext )
-    {
-        /* The WKID maps (mostly) to an EPSG code */
-        if( psSRItemNode->eType == CXT_Element &&
-            psSRItemNode->psChild != NULL &&
-            EQUAL(psSRItemNode->pszValue,"WKID") )
-        {
-            char* pszUnescaped = CPLUnescapeString(psSRItemNode->psChild->pszValue, NULL, CPLES_XML);
-            *pOutWKID = pszUnescaped;
-            CPLFree(pszUnescaped);
-
-            // Needed with FileGDB v1.4 with layers with empty SRS
-            if( *pOutWKID == "0" )
-                *pOutWKID = "";
-        }
-        /* The concept of LatestWKID is explained in http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r3000000n1000000 */
-        else if( psSRItemNode->eType == CXT_Element &&
-            psSRItemNode->psChild != NULL &&
-            EQUAL(psSRItemNode->pszValue,"LatestWKID") )
-        {
-            char* pszUnescaped = CPLUnescapeString(psSRItemNode->psChild->pszValue, NULL, CPLES_XML);
-            *pOutLatestWKID = pszUnescaped;
-            CPLFree(pszUnescaped);
-        }
-        /* The WKT well-known text can be converted by OGR */
-        else if( psSRItemNode->eType == CXT_Element &&
-                psSRItemNode->psChild != NULL &&
-                EQUAL(psSRItemNode->pszValue,"WKT") )
-        {
-            char* pszUnescaped = CPLUnescapeString(psSRItemNode->psChild->pszValue, NULL, CPLES_XML);
-            *pOutWkt = pszUnescaped;
-            CPLFree(pszUnescaped);
-        }
-
-    }
-    return (*pOutWkt != "" || *pOutWKID != "");
-}
-
-/************************************************************************/
-/*                          GDBToOGRFields()                           */
-/************************************************************************/
-
-bool FGdbLayer::GDBToOGRFields(CPLXMLNode* psRoot)
-{
-    m_vOGRFieldToESRIField.clear();
-
-    if (psRoot->psChild == NULL || psRoot->psChild->psNext == NULL)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, "Unrecognized GDB XML Schema");
-
-        return false;
-    }
-
-    psRoot = psRoot->psChild->psNext; //change root to "FieldArray"
-
-    //CPLAssert(ogrToESRIFieldMapping.size() == pOGRFeatureDef->GetFieldCount());
-
-    CPLXMLNode* psFieldNode;
-    int bShouldQueryOpenFileGDB = FALSE;
-
-    for( psFieldNode = psRoot->psChild;
-        psFieldNode != NULL;
-        psFieldNode = psFieldNode->psNext )
-    {
-        //loop through all "Field" elements
-        //
-
-        if( psFieldNode->eType == CXT_Element && psFieldNode->psChild != NULL &&
-            EQUAL(psFieldNode->pszValue,"Field"))
-        {
-
-            CPLXMLNode* psFieldItemNode;
-            std::string fieldName;
-            std::string fieldType;
-            int nLength = 0;
-            //int nPrecision = 0;
-            int bNullable = TRUE;
-            std::string osDefault;
-
-            // loop through all items in Field element
-            //
-
-            for( psFieldItemNode = psFieldNode->psChild;
-                psFieldItemNode != NULL;
-                psFieldItemNode = psFieldItemNode->psNext )
-            {
-                if (psFieldItemNode->eType == CXT_Element)
-                {
-                    if (EQUAL(psFieldItemNode->pszValue,"Name"))
-                    {
-                        char* pszUnescaped = CPLUnescapeString(
-                            psFieldItemNode->psChild->pszValue, NULL, CPLES_XML);
-                        fieldName = pszUnescaped;
-                        CPLFree(pszUnescaped);
-                    }
-                    else if (EQUAL(psFieldItemNode->pszValue,"Type") )
-                    {
-                        char* pszUnescaped = CPLUnescapeString(
-                            psFieldItemNode->psChild->pszValue, NULL, CPLES_XML);
-                        fieldType = pszUnescaped;
-                        CPLFree(pszUnescaped);
-                    }
-                    else if (EQUAL(psFieldItemNode->pszValue,"GeometryDef") )
-                    {
-                        if (!ParseGeometryDef(psFieldItemNode))
-                            return false; // if we failed parsing the GeometryDef, we are done!
-                    }
-                    else if (EQUAL(psFieldItemNode->pszValue,"Length") )
-                    {
-                        nLength = atoi(psFieldItemNode->psChild->pszValue);
-                    }
-                    else if (EQUAL(psFieldItemNode->pszValue,"Precision") )
-                    {
-                        //nPrecision = atoi(psFieldItemNode->psChild->pszValue);
-                    }
-                    else if (EQUAL(psFieldItemNode->pszValue,"IsNullable") )
-                    {
-                        bNullable = EQUAL(psFieldItemNode->psChild->pszValue, "true");
-                    }
-                    else if (EQUAL(psFieldItemNode->pszValue,"DefaultValue"))
-                    {
-                        osDefault = CPLGetXMLValue(psFieldItemNode, NULL, "");
-                    }
-                }
-            }
-
-
-            ///////////////////////////////////////////////////////////////////
-            // At this point we have parsed everything about the current field
-
-
-            if (fieldType == "esriFieldTypeGeometry")
-            {
-                m_strShapeFieldName = fieldName;
-                m_pFeatureDefn->GetGeomFieldDefn(0)->SetNullable(bNullable);
-
-                continue; // finish here for special field - don't add as OGR fielddef
-            }
-            else if (fieldType == "esriFieldTypeOID")
-            {
-                //m_strOIDFieldName = fieldName; // already set by this point
-
-                continue; // finish here for special field - don't add as OGR fielddef
-            }
-
-            OGRFieldType ogrType;
-            OGRFieldSubType eSubType;
-            //CPLDebug("FGDB", "name = %s, type = %s", fieldName.c_str(), fieldType.c_str() );
-            if (!GDBToOGRFieldType(fieldType, &ogrType, &eSubType))
-            {
-                // field cannot be mapped, skipping further processing
-                CPLError( CE_Warning, CPLE_AppDefined, "Skipping field: [%s] type: [%s] ",
-                fieldName.c_str(), fieldType.c_str() );
-                continue;
-            }
-
-
-            //TODO: Optimization - modify m_wstrSubFields so it only fetches fields that are mapped
-
-            OGRFieldDefn fieldTemplate( fieldName.c_str(), ogrType);
-            fieldTemplate.SetSubType(eSubType);
-            /* On creation (GDBFieldTypeToWidthPrecision) if string width is 0, we pick up */
-            /* 65535 by default to mean unlimited string length, but we don't want */
-            /* to advertize such a big number */
-            if( ogrType == OFTString && nLength < 65535 )
-                fieldTemplate.SetWidth(nLength);
-            //fieldTemplate.SetPrecision(nPrecision);
-            fieldTemplate.SetNullable(bNullable);
-            if( osDefault.size() )
-            {
-                if( ogrType == OFTString )
-                {
-                    char* pszTmp = CPLEscapeString(osDefault.c_str(), -1, CPLES_SQL);
-                    osDefault = "'";
-                    osDefault += pszTmp;
-                    CPLFree(pszTmp);
-                    osDefault += "'";
-                    fieldTemplate.SetDefault(osDefault.c_str());
-                }
-                else if( ogrType == OFTInteger ||
-                         ogrType == OFTReal )
-                {
-#ifdef unreliable
-                    /* Disabling this as GDBs and the FileGDB SDK aren't reliable for numeric values */
-                    /* It often occurs that the XML definition in a00000004.gdbtable doesn't */
-                    /* match the default values (in binary) found in the field definition */
-                    /* section of the .gdbtable of the layers themselves */
-                    /* The Table::GetDefinition() API of FileGDB doesn't seem to use the */
-                    /* XML definition, but rather the values found in the field definition */
-                    /* section of the .gdbtable of the layers themselves */
-                    /* It seems that the XML definition in a00000004.gdbtable is authoritative */
-                    /* in ArcGIS, so we're screwed... */
-
-                    fieldTemplate.SetDefault(osDefault.c_str());
-#endif
-                    bShouldQueryOpenFileGDB = TRUE;
-                }
-                else if( ogrType == OFTDateTime )
-                {
-                    int nYear, nMonth, nDay, nHour, nMinute;
-                    float fSecond;
-                    if( sscanf(osDefault.c_str(), "%d-%d-%dT%d:%d:%fZ", &nYear, &nMonth, &nDay,
-                        &nHour, &nMinute, &fSecond) == 6 ||
-                        sscanf(osDefault.c_str(), "'%d-%d-%d %d:%d:%fZ'", &nYear, &nMonth, &nDay,
-                             &nHour, &nMinute, &fSecond) == 6 )
-                    {
-                        fieldTemplate.SetDefault(CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%02d'",
-                               nYear, nMonth, nDay, nHour, nMinute, (int)(fSecond + 0.5)));
-                    }
-                }
-            }
-
-            m_pFeatureDefn->AddFieldDefn( &fieldTemplate );
-
-            m_vOGRFieldToESRIField.push_back(StringToWString(fieldName));
-            m_vOGRFieldToESRIFieldType.push_back( fieldType );
-            if( ogrType == OFTBinary )
-                m_apoByteArrays.push_back(new ByteArray());
-
-        }
-    }
-
-    /* Using OpenFileGDB to get reliable default values for integer/real fields */
-    if( bShouldQueryOpenFileGDB )
-    {
-        const char* apszDrivers[] = { "OpenFileGDB", NULL };
-        GDALDataset* poDS = (GDALDataset*) GDALOpenEx(m_pDS->GetFSName(),
-                            GDAL_OF_VECTOR, (char**)apszDrivers, NULL, NULL);
-        if( poDS != NULL )
-        {
-            OGRLayer* poLyr = poDS->GetLayerByName(GetName());
-            if( poLyr )
-            {
-                for(int i=0;i<poLyr->GetLayerDefn()->GetFieldCount();i++)
-                {
-                    OGRFieldDefn* poSrcDefn = poLyr->GetLayerDefn()->GetFieldDefn(i);
-                    if( (poSrcDefn->GetType() == OFTInteger || poSrcDefn->GetType() == OFTReal) &&
-                        poSrcDefn->GetDefault() != NULL )
-                    {
-                        int nIdxDst = m_pFeatureDefn->GetFieldIndex(poSrcDefn->GetNameRef());
-                        if( nIdxDst >= 0 )
-                            m_pFeatureDefn->GetFieldDefn(nIdxDst)->SetDefault(poSrcDefn->GetDefault());
-                    }
-                }
-            }
-            GDALClose( poDS );
-        }
-    }
-
-    return true;
-}
-
-
-/************************************************************************/
-/*                            ResetReading()                            */
-/************************************************************************/
-
-void FGdbLayer::ResetReading()
-{
-    long hr;
-    
-    if( m_pTable == NULL )
-        return;
-
-    EndBulkLoad();
-
-    if (m_pOGRFilterGeometry && !m_pOGRFilterGeometry->IsEmpty())
-    {
-        // Search spatial
-        // As of beta1, FileGDB only supports bbox searched, if we have GEOS installed,
-        // we can do the rest ourselves.
-
-        OGREnvelope ogrEnv;
-
-        m_pOGRFilterGeometry->getEnvelope(&ogrEnv);
-
-        //spatial query
-        FileGDBAPI::Envelope env(ogrEnv.MinX, ogrEnv.MaxX, ogrEnv.MinY, ogrEnv.MaxY);
-
-        if FAILED(hr = m_pTable->Search(m_wstrSubfields, m_wstrWhereClause, env, true, *m_pEnumRows))
-        GDBErr(hr, "Failed Searching");
-
-        m_bFilterDirty = false;
-
-        return;
-    }
-
-    // Search non-spatial
-
-    if FAILED(hr = m_pTable->Search(m_wstrSubfields, m_wstrWhereClause, true, *m_pEnumRows))
-        GDBErr(hr, "Failed Searching");
-
-    m_bFilterDirty = false;
-  
-}
-
-/************************************************************************/
-/*                         SetSpatialFilter()                           */
-/************************************************************************/
-
-void FGdbLayer::SetSpatialFilter( OGRGeometry* pOGRGeom )
-{
-    if( !InstallFilter(pOGRGeom) )
-        return;
-
-    if (m_pOGRFilterGeometry)
-    {
-        OGRGeometryFactory::destroyGeometry(m_pOGRFilterGeometry);
-        m_pOGRFilterGeometry = NULL;
-    }
-
-    if (pOGRGeom == NULL || pOGRGeom->IsEmpty())
-    {
-        m_bFilterDirty = true;
-
-        return;
-    }
-
-    m_pOGRFilterGeometry = pOGRGeom->clone();
-
-    m_pOGRFilterGeometry->transformTo(m_pSRS);
-
-    m_bFilterDirty = true;
-}
-
-/************************************************************************/
-/*                             ResyncIDs()                              */
-/************************************************************************/
-
-void  FGdbLayer::ResyncIDs()
-{
-    if( m_oMapOGRFIDToFGDBFID.size() == 0 )
-        return;
-    if( m_pDS->Close() )
-        m_pDS->ReOpen();
-}
-
-/************************************************************************/
-/*                         SetAttributeFilter()                         */
-/************************************************************************/
-
-OGRErr FGdbLayer::SetAttributeFilter( const char* pszQuery )
-{
-    if( pszQuery != NULL && CPLString(pszQuery).ifind(GetFIDColumn()) != std::string::npos )
-        ResyncIDs();
-
-    m_wstrWhereClause = StringToWString( (pszQuery != NULL) ? pszQuery : "" );
-
-    m_bFilterDirty = true;
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           OGRFeatureFromGdbRow()                      */
-/************************************************************************/
-
-bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
-{
-    long hr;
-
-    OGRFeature* pOutFeature = new OGRFeature(m_pFeatureDefn);
-
-    /////////////////////////////////////////////////////////
-    // Translate OID
-    //
-
-    int32 oid = -1;
-    if (FAILED(hr = pRow->GetOID(oid)))
-    {
-        //this should never happen
-        delete pOutFeature;
-        return false;
-    }
-    pOutFeature->SetFID(oid);
-
-
-    /////////////////////////////////////////////////////////
-    // Translate Geometry
-    //
-
-    ShapeBuffer gdbGeometry;
-    // Row::GetGeometry() will fail with -2147467259 for NULL geometries
-    // Row::GetGeometry() will fail with -2147219885 for tables without a geometry field
-    if (!m_pFeatureDefn->IsGeometryIgnored() &&
-        !FAILED(hr = pRow->GetGeometry(gdbGeometry)))
-    {
-        OGRGeometry* pOGRGeo = NULL;
-
-        if ((!GDBGeometryToOGRGeometry(m_forceMulti, &gdbGeometry, m_pSRS, &pOGRGeo)))
-        {
-            delete pOutFeature;
-            return GDBErr(hr, "Failed to translate FileGDB Geometry to OGR Geometry for row " + string(CPLSPrintf("%d", (int)oid)));
-        }
-
-        pOutFeature->SetGeometryDirectly(pOGRGeo);
-    }
-
-
-    //////////////////////////////////////////////////////////
-    // Map fields
-    //
-
-
-    int mappedFieldCount = static_cast<int>(m_vOGRFieldToESRIField.size());
-
-    bool foundBadColumn = false;
-
-    for (int i = 0; i < mappedFieldCount; ++i)
-    {
-        OGRFieldDefn* poFieldDefn = m_pFeatureDefn->GetFieldDefn(i);
-        // The IsNull() and GetXXX() API are very slow when there are a 
-        // big number of fields, for example with Tiger database.
-        if (poFieldDefn->IsIgnored() )
-            continue;
-
-        const wstring & wstrFieldName = m_vOGRFieldToESRIField[i];
-        const std::string & strFieldType = m_vOGRFieldToESRIFieldType[i];
-
-        bool isNull = false;
-
-        if (FAILED(hr = pRow->IsNull(wstrFieldName, isNull)))
-        {
-            GDBErr(hr, "Failed to determine NULL status from column " +
-                   WStringToString(wstrFieldName));
-            foundBadColumn = true;
-            continue;
-        }
-
-        if (isNull)
-        {
-            continue; //leave as unset
-        }
-
-        //
-        // NOTE: This switch statement needs to be kept in sync with GDBToOGRFieldType utility function
-        //       since we are only checking for types we mapped in that utility function
-
-        switch (poFieldDefn->GetType())
-        {
-
-            case OFTInteger:
-            {
-                int32 val;
-
-                if (FAILED(hr = pRow->GetInteger(wstrFieldName, val)))
-                {
-                    int16 shortval;
-                    if (FAILED(hr = pRow->GetShort(wstrFieldName, shortval)))
-                    {
-                        GDBErr(hr, "Failed to determine integer value for column " +
-                               WStringToString(wstrFieldName));
-                        foundBadColumn = true;
-                        continue;
-                    }
-                    val = shortval;
-                }
-
-                pOutFeature->SetField(i, (int)val);
-            }
-            break;
-
-            case OFTReal:
-            {
-                if (strFieldType == "esriFieldTypeSingle")
-                {
-                    float val;
-
-                    if (FAILED(hr = pRow->GetFloat(wstrFieldName, val)))
-                    {
-                        GDBErr(hr, "Failed to determine float value for column " +
-                               WStringToString(wstrFieldName));
-                        foundBadColumn = true;
-                        continue;
-                    }
-
-                    pOutFeature->SetField(i, val);
-                }
-                else
-                {
-                    double val;
-
-                    if (FAILED(hr = pRow->GetDouble(wstrFieldName, val)))
-                    {
-                        GDBErr(hr, "Failed to determine real value for column " +
-                               WStringToString(wstrFieldName));
-                        foundBadColumn = true;
-                        continue;
-                    }
-
-                    pOutFeature->SetField(i, val);
-                }
-            }
-            break;
-            case OFTString:
-            {
-                wstring val;
-                std::string strValue;
-
-                if( strFieldType == "esriFieldTypeGlobalID" )
-                {
-                    Guid guid;
-                    if( FAILED(hr = pRow->GetGlobalID(guid)) ||
-                        FAILED(hr = guid.ToString(val)) )
-                    {
-                        GDBErr(hr, "Failed to determine string value for column " +
-                            WStringToString(wstrFieldName));
-                        foundBadColumn = true;
-                        continue;
-                    }
-                    strValue = WStringToString(val);
-                }
-                else if( strFieldType == "esriFieldTypeGUID" )
-                {
-                    Guid guid;
-                    if( FAILED(hr = pRow->GetGUID(wstrFieldName, guid)) ||
-                        FAILED(hr = guid.ToString(val)) )
-                    {
-                        GDBErr(hr, "Failed to determine string value for column " +
-                            WStringToString(wstrFieldName));
-                        foundBadColumn = true;
-                        continue;
-                    }
-                    strValue = WStringToString(val);
-                }
-                else if( strFieldType == "esriFieldTypeXML" )
-                {
-                    if (FAILED(hr = pRow->GetXML(wstrFieldName, strValue)))
-                    {
-                        GDBErr(hr, "Failed to determine XML value for column " +
-                            WStringToString(wstrFieldName));
-                        foundBadColumn = true;
-                        continue;
-                    }
-                }
-                else
-                {
-                    if (FAILED(hr = pRow->GetString(wstrFieldName, val)))
-                    {
-                        GDBErr(hr, "Failed to determine string value for column " +
-                            WStringToString(wstrFieldName));
-                        foundBadColumn = true;
-                        continue;
-                    }
-                    strValue = WStringToString(val);
-                }
-
-                pOutFeature->SetField(i, strValue.c_str());
-            }
-            break;
-
-            case OFTBinary:
-            {
-                ByteArray binaryBuf;
-
-                if (FAILED(hr = pRow->GetBinary(wstrFieldName, binaryBuf)))
-                    {
-                    GDBErr(hr, "Failed to determine binary value for column " + WStringToString(wstrFieldName));
-                    foundBadColumn = true;
-                    continue;
-                }
-
-                pOutFeature->SetField(i, (int)binaryBuf.inUseLength, (GByte*)binaryBuf.byteArray);
-            }
-            break;
-
-            case OFTDateTime:
-            {
-                struct tm val;
-
-                if (FAILED(hr = pRow->GetDate(wstrFieldName, val)))
-                {
-                    GDBErr(hr, "Failed to determine date value for column " +
-                           WStringToString(wstrFieldName));
-                    foundBadColumn = true;
-                    continue;
-                }
-
-                pOutFeature->SetField(i, val.tm_year + 1900, val.tm_mon + 1,
-                                      val.tm_mday, val.tm_hour, val.tm_min, (float)val.tm_sec);
-            // Examine test data to figure out how to extract that
-            }
-            break;
-
-            default:
-            {
-                if (!m_suppressColumnMappingError)
-                {
-                    foundBadColumn = true;
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                            "Row id: %d col:%d has unhandled col type (%d). Setting to NULL.",
-                            (int)oid, (int)i, m_pFeatureDefn->GetFieldDefn(i)->GetType());
-                }
-            }
-        }
-    }
-
-    if (foundBadColumn)
-        m_suppressColumnMappingError = true;
-
-
-    *ppFeature = pOutFeature;
-
-    return true;
-}
-
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRFeature* FGdbLayer::GetNextFeature()
-{
-    if (m_bFilterDirty)
-        ResetReading();
-
-    EndBulkLoad();
-
-    OGRFeature* poFeature = FGdbBaseLayer::GetNextFeature();
-    if( poFeature )
-    {
-        std::map<int,int>::iterator oIter = m_oMapFGDBFIDToOGRFID.find((int)poFeature->GetFID());
-        if( oIter != m_oMapFGDBFIDToOGRFID.end() )
-        {
-            poFeature->SetFID(oIter->second);
-        }
-    }
-    return poFeature;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *FGdbLayer::GetFeature( GIntBig oid )
-{
-    // do query to fetch individual row
-    EnumRows       enumRows;
-    Row            row;
-    if( !CPL_INT64_FITS_ON_INT32(oid) || m_pTable == NULL )
-        return NULL;
-
-    EndBulkLoad();
-
-    int nFID32 = (int)oid;
-    std::map<int,int>::iterator oIter = m_oMapOGRFIDToFGDBFID.find(nFID32);
-    if( oIter != m_oMapOGRFIDToFGDBFID.end() )
-        nFID32 = oIter->second;
-    else if( m_oMapFGDBFIDToOGRFID.find(nFID32) != m_oMapFGDBFIDToOGRFID.end() )
-        return NULL;
-
-    if (GetRow(enumRows, row, nFID32) != OGRERR_NONE)
-        return NULL;
-
-    OGRFeature* pOGRFeature = NULL;
-
-    if (!OGRFeatureFromGdbRow(&row,  &pOGRFeature))
-    {
-        return NULL;
-    }
-    if( pOGRFeature )
-    {
-        pOGRFeature->SetFID(oid);
-    }
-
-    return pOGRFeature;
-}
-
-
-/************************************************************************/
-/*                          GetFeatureCount()                           */
-/************************************************************************/
-
-GIntBig FGdbLayer::GetFeatureCount( CPL_UNUSED int bForce )
-{
-    int32          rowCount = 0;
-    
-    if( m_pTable == NULL )
-        return 0;
-
-    EndBulkLoad();
-
-    if (m_pOGRFilterGeometry != NULL || m_wstrWhereClause.size() != 0)
-    {
-        ResetReading();
-        if (m_pEnumRows == NULL)
-            return 0;
-
-        int nFeatures = 0;
-        while( true )
-        {
-            long hr;
-
-            Row row;
-
-            if (FAILED(hr = m_pEnumRows->Next(row)))
-            {
-                GDBErr(hr, "Failed fetching features");
-                return 0;
-            }
-
-            if (hr != S_OK)
-            {
-                break;
-            }
-            nFeatures ++;
-        }
-        ResetReading();
-        return nFeatures;
-    }
-
-    long hr;
-    if (FAILED(hr = m_pTable->GetRowCount(rowCount)))
-    {
-        GDBErr(hr, "Failed counting rows");
-        return 0;
-    }
-
-    return static_cast<int>(rowCount);
-}
-
-/************************************************************************/
-/*                         GetMetadataItem()                            */
-/************************************************************************/
-
-const char* FGdbLayer::GetMetadataItem(const char* pszName, const char* pszDomain)
-{
-    if( pszDomain != NULL && EQUAL(pszDomain, "MAP_OGR_FID_TO_FGDB_FID") )
-    {
-        if( m_oMapOGRFIDToFGDBFID.find(atoi(pszName)) != m_oMapOGRFIDToFGDBFID.end() )
-            return CPLSPrintf("%d", m_oMapOGRFIDToFGDBFID[atoi(pszName)]);
-    }
-    else if( pszDomain != NULL && EQUAL(pszDomain, "MAP_FGDB_FID_TO_OGR_FID") )
-    {
-        if( m_oMapFGDBFIDToOGRFID.find(atoi(pszName)) != m_oMapFGDBFIDToOGRFID.end() )
-            return CPLSPrintf("%d", m_oMapFGDBFIDToOGRFID[atoi(pszName)]);
-    }
-    return OGRLayer::GetMetadataItem(pszName, pszDomain);
-}
-
-/************************************************************************/
-/*                             GetExtent()                              */
-/************************************************************************/
-
-OGRErr FGdbLayer::GetExtent (OGREnvelope* psExtent, int bForce)
-{
-    if( m_pTable == NULL )
-        return OGRERR_FAILURE;
-
-    if (m_pOGRFilterGeometry != NULL || m_wstrWhereClause.size() != 0 ||
-        m_strShapeFieldName.size() == 0)
-    {
-        int* pabSaveFieldIgnored = new int[m_pFeatureDefn->GetFieldCount()];
-        for(int i=0;i<m_pFeatureDefn->GetFieldCount();i++)
-        {
-            pabSaveFieldIgnored[i] = m_pFeatureDefn->GetFieldDefn(i)->IsIgnored();
-            m_pFeatureDefn->GetFieldDefn(i)->SetIgnored(TRUE);
-        }
-        OGRErr eErr = OGRLayer::GetExtent(psExtent, bForce);
-        for(int i=0;i<m_pFeatureDefn->GetFieldCount();i++)
-        {
-            m_pFeatureDefn->GetFieldDefn(i)->SetIgnored(pabSaveFieldIgnored[i]);
-        }
-        delete[] pabSaveFieldIgnored;
-        return eErr;
-    }
-
-    long hr;
-    Envelope envelope;
-    if (FAILED(hr = m_pTable->GetExtent(envelope)))
-    {
-        GDBErr(hr, "Failed fetching extent");
-        return OGRERR_FAILURE;
-    }
-
-    psExtent->MinX = envelope.xMin;
-    psExtent->MinY = envelope.yMin;
-    psExtent->MaxX = envelope.xMax;
-    psExtent->MaxY = envelope.yMax;
-
-    if (CPLIsNan(psExtent->MinX) ||
-        CPLIsNan(psExtent->MinY) ||
-        CPLIsNan(psExtent->MaxX) ||
-        CPLIsNan(psExtent->MaxY))
-        return OGRERR_FAILURE;
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                          StartBulkLoad()                             */
-/************************************************************************/
-
-void FGdbLayer::StartBulkLoad ()
-{
-    if ( ! m_pTable )
-        return;
-
-    if ( m_bBulkLoadInProgress )
-        return;
-
-    m_bBulkLoadInProgress = TRUE;
-    m_pTable->LoadOnlyMode(true);
-    m_pTable->SetWriteLock();
-}
-
-/************************************************************************/
-/*                           EndBulkLoad()                              */
-/************************************************************************/
-
-void FGdbLayer::EndBulkLoad ()
-{
-    if ( ! m_pTable )
-        return;
-
-    if ( ! m_bBulkLoadInProgress )
-        return;
-
-    m_bBulkLoadInProgress = FALSE;
-    m_bBulkLoadAllowed = -1; /* so that the configuration option is read the first time we CreateFeature() again */
-    m_pTable->LoadOnlyMode(false);
-    m_pTable->FreeWriteLock();
-}
-
-/* OGRErr FGdbLayer::StartTransaction ()
-{
-    if ( ! m_pTable ) 
-        return OGRERR_FAILURE;
-        
-    m_pTable->LoadOnlyMode(true);
-    m_pTable->SetWriteLock();
-    return OGRERR_NONE;
-    
-} */
-
-
-/* OGRErr FGdbLayer::CommitTransaction ()
-{
-    if ( ! m_pTable ) 
-        return OGRERR_FAILURE;
-    
-    m_pTable->LoadOnlyMode(false);
-    m_pTable->FreeWriteLock();
-    return OGRERR_NONE;
-} */
-
-/* OGRErr FGdbLayer::RollbackTransaction ()
-{
-    if ( ! m_pTable ) 
-        return OGRERR_FAILURE;
-    
-    m_pTable->LoadOnlyMode(false);
-    m_pTable->FreeWriteLock();
-    return OGRERR_NONE;
-} */
-
-
-/************************************************************************/
-/*                           GetLayerXML()                              */
-/* Return XML definition of the Layer as provided by FGDB. Caller must  */
-/* free result.                                                         */
-/* Not currently used by the driver, but can be used by external code   */
-/* for specific purposes.                                               */
-/************************************************************************/
-
-OGRErr FGdbLayer::GetLayerXML (char **ppXml)
-{
-    long hr;
-    std::string xml;
-
-    if( m_pTable == NULL )
-        return OGRERR_FAILURE;
-    
-    if ( FAILED(hr = m_pTable->GetDefinition(xml)) )
-    {
-        GDBErr(hr, "Failed fetching XML table definition");
-        return OGRERR_FAILURE;
-    }
-
-    *ppXml = CPLStrdup(xml.c_str());
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           GetLayerMetadataXML()                      */
-/* Return XML metadata for the Layer as provided by FGDB. Caller must  */
-/* free result.                                                         */
-/* Not currently used by the driver, but can be used by external code   */
-/* for specific purposes.                                               */
-/************************************************************************/
-
-OGRErr FGdbLayer::GetLayerMetadataXML (char **ppXml)
-{
-    long hr;
-    std::string xml;
-    
-    if( m_pTable == NULL )
-        return OGRERR_FAILURE;
-
-    if ( FAILED(hr = m_pTable->GetDocumentation(xml)) )
-    {
-        GDBErr(hr, "Failed fetching XML table metadata");
-        return OGRERR_FAILURE;
-    }
-
-    *ppXml = CPLStrdup(xml.c_str());
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int FGdbLayer::TestCapability( const char* pszCap )
-{
-
-    if (EQUAL(pszCap,OLCRandomRead))
-        return TRUE;
-
-    else if (EQUAL(pszCap,OLCFastFeatureCount)) 
-        return m_pOGRFilterGeometry == NULL && m_wstrWhereClause.size() == 0;
-
-    else if (EQUAL(pszCap,OLCFastSpatialFilter))
-        return TRUE;
-
-    else if (EQUAL(pszCap,OLCFastGetExtent))
-        return m_pOGRFilterGeometry == NULL && m_wstrWhereClause.size() == 0;
-
-    else if (EQUAL(pszCap,OLCCreateField)) /* CreateField() */
-        return m_pDS->GetUpdate();
-
-    else if (EQUAL(pszCap,OLCSequentialWrite)) /* ICreateFeature() */
-        return m_pDS->GetUpdate();
-
-    else if (EQUAL(pszCap,OLCStringsAsUTF8)) /* Native UTF16, converted to UTF8 */
-        return TRUE;
-
-    else if (EQUAL(pszCap,OLCReorderFields)) /* TBD ReorderFields() */
-        return m_pDS->GetUpdate();
-
-    else if (EQUAL(pszCap,OLCDeleteFeature)) /* DeleteFeature() */
-        return m_pDS->GetUpdate();
-
-    else if (EQUAL(pszCap,OLCRandomWrite)) /* ISetFeature() */
-        return m_pDS->GetUpdate();
-
-    else if (EQUAL(pszCap,OLCDeleteField)) /* DeleteField() */
-        return m_pDS->GetUpdate();
-
-#ifdef AlterFieldDefn_implemented_but_not_working
-    else if (EQUAL(pszCap,OLCAlterFieldDefn)) /* AlterFieldDefn() */
-        return m_pDS->GetUpdate();
-#endif
-
-    else if (EQUAL(pszCap,OLCFastSetNextByIndex)) /* TBD FastSetNextByIndex() */
-        return FALSE;
-
-    else if (EQUAL(pszCap,OLCTransactions)) /* TBD Start/End Transactions() */
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCIgnoreFields) )
-        return TRUE;
-
-    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
-        return TRUE;
-
-    else 
-        return FALSE;
-}
-
-/************************************************************************/
-/*                           CreateRealCopy()                           */
-/************************************************************************/
-
-int FGdbLayer::CreateRealCopy()
-{
-    CPLAssert( m_bSymlinkFlag );
-
-    // Find the FID of the layer in the system catalog
-    char* apszDrivers[2];
-    apszDrivers[0] = (char*) "OpenFileGDB";
-    apszDrivers[1] = NULL;
-    const char* pszSystemCatalog
-        = CPLFormFilename(m_pDS->GetFSName(), "a00000001.gdbtable", NULL);
-    GDALDataset* poOpenFileGDBDS = (GDALDataset*)
-        GDALOpenEx(pszSystemCatalog, GDAL_OF_VECTOR,
-                    apszDrivers, NULL, NULL);
-    if( poOpenFileGDBDS == NULL || poOpenFileGDBDS->GetLayer(0) == NULL )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Cannot open %s with OpenFileGDB driver. Should not happen.",
-                  pszSystemCatalog);
-        GDALClose(poOpenFileGDBDS);
-        return FALSE;
-    }
-
-    OGRLayer* poLayer = poOpenFileGDBDS->GetLayer(0);
-    CPLString osFilter = "name = '";
-    osFilter += GetName();
-    osFilter += "'";
-    poLayer->SetAttributeFilter(osFilter);
-    poLayer->ResetReading();
-    OGRFeature* poF = poLayer->GetNextFeature();
-    if( poF == NULL )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Cannot find filename for layer %s",
-                  GetName());
-        GDALClose(poOpenFileGDBDS);
-        return FALSE;
-    }
-    int nLayerFID = (int)poF->GetFID();
-    delete poF;
-    GDALClose(poOpenFileGDBDS);
-
-    if( !m_pDS->Close(TRUE) )
-        return FALSE;
-
-    // Create real copies (in .tmp files now) instead of symlinks
-    char** papszFiles = VSIReadDir(m_pDS->GetFSName());
-    CPLString osBasename(CPLSPrintf("a%08x", nLayerFID));
-    int bError = FALSE;
-    std::vector<CPLString> aoFiles;
-    for(char** papszIter = papszFiles; !bError && papszIter && *papszIter; papszIter++)
-    {
-        if( strncmp(*papszIter, osBasename.c_str(), osBasename.size()) == 0 )
-        {
-            if(CPLCopyFile( CPLFormFilename(m_pDS->GetFSName(), *papszIter, "tmp"),
-                            CPLFormFilename(m_pDS->GetFSName(), *papszIter, NULL) ) != 0 )
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                             "Cannot copy %s", *papszIter);
-                bError = TRUE;
-            }
-            else
-                aoFiles.push_back(*papszIter);
-        }
-    }
-    CSLDestroy(papszFiles);
-    
-    // Rename the .tmp into normal filenames
-    for(size_t i=0; !bError && i<aoFiles.size(); i++ )
-    {
-        if( VSIUnlink( CPLFormFilename(m_pDS->GetFSName(), aoFiles[i], NULL) ) != 0 ||
-            VSIRename( CPLFormFilename(m_pDS->GetFSName(), aoFiles[i], "tmp"),
-                       CPLFormFilename(m_pDS->GetFSName(), aoFiles[i], NULL) ) != 0 )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s.tmp", aoFiles[i].c_str());
-            bError = TRUE;
-        }
-    }
-
-    int bRet = !bError && m_pDS->ReOpen();
-    if( bRet )
-        m_bSymlinkFlag = FALSE;
-    return bRet;
-}
+/******************************************************************************
+*
+* Project:  OpenGIS Simple Features Reference Implementation
+* Purpose:  Implements FileGDB OGR layer.
+* Author:   Ragi Yaser Burhum, ragi at burhum.com
+*           Paul Ramsey, pramsey at cleverelephant.ca
+*
+******************************************************************************
+* Copyright (c) 2010, Ragi Yaser Burhum
+* Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+****************************************************************************/
+
+#include "ogr_fgdb.h"
+#include "ogrpgeogeometry.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "FGdbUtils.h"
+#include "cpl_minixml.h" // the only way right now to extract schema information
+
+CPL_CVSID("$Id: FGdbLayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
+using std::string;
+using std::wstring;
+
+/************************************************************************/
+/*                           FGdbBaseLayer()                            */
+/************************************************************************/
+FGdbBaseLayer::FGdbBaseLayer() :
+    m_pFeatureDefn(NULL), m_pSRS(NULL), m_pEnumRows(NULL),
+    m_suppressColumnMappingError(false), m_forceMulti(false)
+{
+}
+
+/************************************************************************/
+/*                          ~FGdbBaseLayer()                            */
+/************************************************************************/
+FGdbBaseLayer::~FGdbBaseLayer()
+{
+    if (m_pFeatureDefn)
+    {
+        m_pFeatureDefn->Release();
+        m_pFeatureDefn = NULL;
+    }
+
+    CloseGDBObjects();
+
+    if (m_pSRS)
+    {
+        m_pSRS->Release();
+        m_pSRS = NULL;
+    }
+}
+
+/************************************************************************/
+/*                          CloseGDBObjects()                           */
+/************************************************************************/
+
+void FGdbBaseLayer::CloseGDBObjects()
+{
+    if (m_pEnumRows)
+    {
+        delete m_pEnumRows;
+        m_pEnumRows = NULL;
+    }
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature* FGdbBaseLayer::GetNextFeature()
+{
+    while (1) //want to skip errors
+    {
+        if (m_pEnumRows == NULL)
+            return NULL;
+
+        long hr;
+
+        Row row;
+
+        if (FAILED(hr = m_pEnumRows->Next(row)))
+        {
+            GDBErr(hr, "Failed fetching features");
+            return NULL;
+        }
+
+        if (hr != S_OK)
+        {
+        // It's OK, we are done fetching - failure is caught by FAILED macro
+            return NULL;
+        }
+
+        OGRFeature* pOGRFeature = NULL;
+
+        if (!OGRFeatureFromGdbRow(&row,  &pOGRFeature))
+        {
+            int32 oid = -1;
+            row.GetOID(oid);
+
+            GDBErr(hr, CPLSPrintf("Failed translating FGDB row [%d] to OGR Feature", oid));
+
+            //return NULL;
+            continue; //skip feature
+        }
+
+        return pOGRFeature;
+    }
+}
+
+/************************************************************************/
+/*                              FGdbLayer()                             */
+/************************************************************************/
+FGdbLayer::FGdbLayer():
+    m_pDS(NULL), m_pTable(NULL), m_wstrSubfields(L"*"), m_pOGRFilterGeometry(NULL),
+    m_bFilterDirty(true),
+    m_bLaunderReservedKeywords(true)
+{
+    m_bBulkLoadAllowed = -1; /* uninitialized */
+    m_bBulkLoadInProgress = FALSE;
+    m_pEnumRows = new EnumRows;
+
+#ifdef EXTENT_WORKAROUND
+    m_bLayerEnvelopeValid = false;
+    m_bLayerJustCreated = false;
+#endif
+    m_papszOptions = NULL;
+    m_bCreateMultipatch = FALSE;
+    m_nResyncThreshold = atoi(CPLGetConfigOption("FGDB_RESYNC_THRESHOLD", "1000000"));
+    m_bSymlinkFlag = FALSE;
+}
+
+/************************************************************************/
+/*                            ~FGdbLayer()                              */
+/************************************************************************/
+
+FGdbLayer::~FGdbLayer()
+{
+    CloseGDBObjects();
+
+    if (m_pOGRFilterGeometry)
+    {
+        OGRGeometryFactory::destroyGeometry(m_pOGRFilterGeometry);
+        m_pOGRFilterGeometry = NULL;
+    }
+
+    for(size_t i = 0; i < m_apoByteArrays.size(); i++ )
+        delete m_apoByteArrays[i];
+    m_apoByteArrays.resize(0);
+
+    CSLDestroy(m_papszOptions);
+    m_papszOptions = NULL;
+}
+
+/************************************************************************/
+/*                        CloseGDBObjects()                             */
+/************************************************************************/
+
+void FGdbLayer::CloseGDBObjects()
+{
+    EndBulkLoad();
+
+#ifdef EXTENT_WORKAROUND
+    WorkAroundExtentProblem();
+#endif
+
+    if (m_pTable)
+    {
+        delete m_pTable;
+        m_pTable = NULL;
+    }
+
+    FGdbBaseLayer::CloseGDBObjects();
+}
+
+/************************************************************************/
+/*                     EditIndexesForFIDHack()                          */
+/************************************************************************/
+
+int FGdbLayer::EditIndexesForFIDHack(const char* pszRadixTablename)
+{
+    // Fix FIDs in .gdbtablx, .spx and .atx's
+
+    CPLString osGDBTablX = CPLResetExtension(pszRadixTablename, "gdbtablx");
+    CPLString osNewGDBTablX = CPLResetExtension(pszRadixTablename, "gdbtablx.new");
+
+    if( !EditGDBTablX(osGDBTablX, osNewGDBTablX) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Error occurred when editing %s", osNewGDBTablX.c_str());
+        VSIUnlink(osNewGDBTablX);
+        return FALSE;
+    }
+
+    CPLString osDirectory(CPLGetPath(pszRadixTablename));
+    char** papszFiles = VSIReadDir(osDirectory);
+    CPLString osBasename(CPLGetBasename(pszRadixTablename));
+    int bRet = TRUE;
+    for(char** papszIter = papszFiles; papszIter && *papszIter; papszIter++)
+    {
+        if( strncmp(*papszIter, osBasename.c_str(), osBasename.size()) == 0 &&
+            (EQUAL(CPLGetExtension(*papszIter), "atx") ||
+             EQUAL(CPLGetExtension(*papszIter), "spx")) )
+        {
+            CPLString osIndex(CPLFormFilename(osDirectory, *papszIter, NULL));
+            if( !EditATXOrSPX(osIndex) )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Error occurred when editing %s", osIndex.c_str());
+                bRet = FALSE;
+            }
+        }
+    }
+    CSLDestroy(papszFiles);
+
+    CPLString osGDBTablXTmp(CPLSPrintf("%s.tmp", osGDBTablX.c_str()));
+    int bRet2 = (VSIRename(osGDBTablX,osGDBTablXTmp) == 0 &&
+                 VSIRename(osNewGDBTablX, osGDBTablX) == 0);
+    VSIUnlink(osGDBTablXTmp);
+    if( !bRet2 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot rename %s to %s", osNewGDBTablX.c_str(), osGDBTablX.c_str());
+        bRet = FALSE;
+    }
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                           EditATXOrSPX()                             */
+/************************************************************************/
+
+/* See https://github.com/rouault/dump_gdbtable/wiki/FGDB-Spec */
+int FGdbLayer::EditATXOrSPX( const CPLString& osIndex )
+{
+    VSILFILE* fp = VSIFOpenL(osIndex, "rb+");
+    if (fp == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot open %s", osIndex.c_str());
+        return FALSE;
+    }
+    VSIFSeekL(fp, 0, SEEK_END);
+    vsi_l_offset nPos = VSIFTellL(fp);
+    int bRet = FALSE;
+    int bInvalidateIndex = FALSE;
+    if( nPos > 22 )
+    {
+        VSIFSeekL(fp, nPos - 22, SEEK_SET);
+        GByte nSizeIndexedValue;
+        if( VSIFReadL(&nSizeIndexedValue, 1, 1, fp) == 1 &&
+            nSizeIndexedValue > 0 )
+        {
+            GByte abyIndexedValue[255];
+            VSIFSeekL(fp, nPos - 22 + 6, SEEK_SET);
+            int nDepth;
+            if( VSIFReadL(&nDepth, 1, 4, fp) == 4 )
+            {
+                CPL_LSBPTR32(&nDepth);
+
+                int bIndexedValueIsValid = FALSE;
+                int nFirstIndexAtThisValue = -1;
+                std::vector<int> anPagesAtThisValue;
+                int bSortThisValue = FALSE;
+                int nLastPageVisited = 0;
+                bRet = EditATXOrSPX(fp,
+                                    1,
+                                    nLastPageVisited,
+                                    nDepth,
+                                    nSizeIndexedValue,
+                                    abyIndexedValue,
+                                    bIndexedValueIsValid,
+                                    nFirstIndexAtThisValue,
+                                    anPagesAtThisValue,
+                                    bSortThisValue,
+                                    bInvalidateIndex);
+            }
+        }
+    }
+    VSIFCloseL(fp);
+    if( bInvalidateIndex )
+    {
+        //CPLDebug("FGDB", "Invalidate %s", osIndex.c_str());
+        CPLError(CE_Warning, CPLE_AppDefined, "Invalidate %s", osIndex.c_str());
+        VSIUnlink(osIndex);
+    }
+    return bRet;
+}
+
+static int FGdbLayerSortATX(const void* _pa, const void* _pb)
+{
+    int a = CPL_LSBWORD32(*(int*)_pa);
+    int b = CPL_LSBWORD32(*(int*)_pb);
+    if( a < b )
+        return -1;
+    else if( a > b )
+        return 1;
+    CPLAssert(false);
+    return 0;
+}
+
+int FGdbLayer::EditATXOrSPX(VSILFILE* fp,
+                            int nThisPage,
+                            int& nLastPageVisited,
+                            int nDepth,
+                            int nSizeIndexedValue,
+                            GByte* pabyLastIndexedValue,
+                            int& bIndexedValueIsValid,
+                            int& nFirstIndexAtThisValue,
+                            std::vector<int>& anPagesAtThisValue,
+                            int& bSortThisValue,
+                            int& bInvalidateIndex)
+{
+    GByte abyBuffer[4096];
+
+    VSIFSeekL(fp, (nThisPage - 1) * 4096, SEEK_SET);
+
+    if( nDepth == 1 )
+    {
+        if( nThisPage == nLastPageVisited )
+            return TRUE;
+
+        /* This page directly references features */
+        int bRewritePage = FALSE;
+        if( VSIFReadL(abyBuffer, 1, 4096, fp) != 4096 )
+            return FALSE;
+        int nNextPageID;
+        memcpy(&nNextPageID, abyBuffer, 4);
+        int nFeatures;
+        memcpy(&nFeatures, abyBuffer + 4, 4);
+        CPL_LSBPTR32(&nFeatures);
+
+        //if( nLastPageVisited == 0 )
+        //    printf("nFeatures = %d\n", nFeatures);
+
+        const int nMaxPerPages = (4096 - 12) / (4 + nSizeIndexedValue);
+        const int nOffsetFirstValInPage = 12 + nMaxPerPages * 4;
+        if( nFeatures > nMaxPerPages )
+            return FALSE;
+        for(int i=0; i < nFeatures; i++)
+        {
+            int bNewVal = ( !bIndexedValueIsValid ||
+                            memcmp(pabyLastIndexedValue,
+                                   abyBuffer + nOffsetFirstValInPage + i * nSizeIndexedValue,
+                                   nSizeIndexedValue) != 0 );
+
+            int nFID;
+            memcpy(&nFID, abyBuffer + 12 + 4 * i, 4);
+            CPL_LSBPTR32(&nFID);
+            int nOGRFID = m_oMapFGDBFIDToOGRFID[nFID];
+            if( nOGRFID )
+            {
+                nFID = nOGRFID;
+                CPL_LSBPTR32(&nOGRFID);
+                memcpy(abyBuffer + 12 + 4 * i, &nOGRFID, 4);
+                bRewritePage = TRUE;
+
+                if( bIndexedValueIsValid && i == nFeatures - 1 && nNextPageID == 0 )
+                    bSortThisValue = TRUE;
+            }
+
+            // We must make sure that features with same indexed values are
+            // sorted by increasing FID, even when that spans over several
+            // pages
+            if( bSortThisValue && (bNewVal || (i == nFeatures - 1 && nNextPageID == 0)) )
+            {
+                if( anPagesAtThisValue[0] == nThisPage )
+                {
+                    CPLAssert(anPagesAtThisValue.size() == 1);
+                    int nFeaturesToSortThisPage = i - nFirstIndexAtThisValue;
+                    if( !bNewVal && i == nFeatures - 1 && nNextPageID == 0 )
+                        nFeaturesToSortThisPage ++;
+                    CPLAssert(nFeaturesToSortThisPage > 0);
+
+                    bRewritePage = TRUE;
+                    qsort(abyBuffer + 12 + 4 * nFirstIndexAtThisValue,
+                          nFeaturesToSortThisPage, 4, FGdbLayerSortATX);
+                }
+                else
+                {
+                    std::vector<int> anValues;
+                    int nFeaturesToSort = 0;
+                    anValues.resize(anPagesAtThisValue.size() * nMaxPerPages);
+
+                    int nFeaturesToSortLastPage = i;
+                    if( !bNewVal && i == nFeatures - 1 && nNextPageID == 0 )
+                        nFeaturesToSortLastPage ++;
+
+                    for(size_t j=0;j<anPagesAtThisValue.size();j++)
+                    {
+                        int nFeaturesPrevPage;
+                        VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 4, SEEK_SET);
+                        VSIFReadL(&nFeaturesPrevPage, 1, 4, fp);
+                        CPL_LSBPTR32(&nFeaturesPrevPage);
+                        if( j == 0 )
+                        {
+                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12 + 4 * nFirstIndexAtThisValue, SEEK_SET);
+                            VSIFReadL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage - nFirstIndexAtThisValue, fp);
+                            nFeaturesToSort += nFeaturesPrevPage - nFirstIndexAtThisValue;
+                        }
+                        else if( j == anPagesAtThisValue.size() - 1 && anPagesAtThisValue[j] == nThisPage )
+                        {
+                            bRewritePage = TRUE;
+                            memcpy(&anValues[nFeaturesToSort], abyBuffer + 12, nFeaturesToSortLastPage * 4);
+                            nFeaturesToSort += nFeaturesToSortLastPage;
+                        }
+                        else
+                        {
+                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12, SEEK_SET);
+                            VSIFReadL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage, fp);
+                            nFeaturesToSort += nFeaturesPrevPage;
+                        }
+                    }
+
+                    qsort(&anValues[0], nFeaturesToSort, 4, FGdbLayerSortATX);
+
+                    nFeaturesToSort = 0;
+                    for(size_t j=0;j<anPagesAtThisValue.size();j++)
+                    {
+                        int nFeaturesPrevPage;
+                        VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 4, SEEK_SET);
+                        VSIFReadL(&nFeaturesPrevPage, 1, 4, fp);
+                        CPL_LSBPTR32(&nFeaturesPrevPage);
+                        if( j == 0 )
+                        {
+                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12 + 4 * nFirstIndexAtThisValue, SEEK_SET);
+                            VSIFWriteL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage - nFirstIndexAtThisValue, fp);
+                            nFeaturesToSort += nFeaturesPrevPage - nFirstIndexAtThisValue;
+                        }
+                        else if( j == anPagesAtThisValue.size() - 1 && anPagesAtThisValue[j] == nThisPage )
+                        {
+                            memcpy(abyBuffer + 12, &anValues[nFeaturesToSort], nFeaturesToSortLastPage * 4);
+                            nFeaturesToSort += nFeaturesToSortLastPage;
+                        }
+                        else
+                        {
+                            VSIFSeekL(fp, (anPagesAtThisValue[j]-1) * 4096 + 12, SEEK_SET);
+                            VSIFWriteL(&anValues[nFeaturesToSort], 4, nFeaturesPrevPage, fp);
+                            nFeaturesToSort += nFeaturesPrevPage;
+                        }
+                    }
+                }
+            }
+
+            if( bNewVal )
+            {
+                nFirstIndexAtThisValue = i;
+                anPagesAtThisValue.clear();
+                anPagesAtThisValue.push_back(nThisPage);
+
+                memcpy(pabyLastIndexedValue,
+                       abyBuffer + nOffsetFirstValInPage + i * nSizeIndexedValue,
+                       nSizeIndexedValue);
+                bSortThisValue = FALSE;
+            }
+            else if( i == 0 )
+            {
+                if( anPagesAtThisValue.size() > 100000 )
+                {
+                    bInvalidateIndex = TRUE;
+                    return FALSE;
+                }
+                else
+                {
+                    anPagesAtThisValue.push_back(nThisPage);
+                }
+            }
+
+            if( nOGRFID )
+                bSortThisValue = TRUE;
+
+            bIndexedValueIsValid = TRUE;
+        }
+
+        if( bRewritePage )
+        {
+            VSIFSeekL(fp, (nThisPage - 1) * 4096, SEEK_SET);
+            if( VSIFWriteL(abyBuffer, 1, 4096, fp) != 4096 )
+                return FALSE;
+        }
+
+        nLastPageVisited = nThisPage;
+
+        return TRUE;
+    }
+    else
+    {
+        /* This page references other pages */
+        if( VSIFReadL(abyBuffer, 1, 4096, fp) != 4096 )
+            return FALSE;
+        int nSubPages;
+        memcpy(&nSubPages, abyBuffer + 4, 4);
+        CPL_LSBPTR32(&nSubPages);
+        nSubPages ++;
+        if( nSubPages > (4096 - 8) / 4 )
+            return FALSE;
+        for(int i=0; i < nSubPages; i++)
+        {
+            int nSubPageID;
+            memcpy(&nSubPageID, abyBuffer + 8 + 4 * i, 4);
+            CPL_LSBPTR32(&nSubPageID);
+            if( nSubPageID < 1 )
+                return FALSE;
+            if( !EditATXOrSPX(fp,
+                              nSubPageID,
+                              nLastPageVisited,
+                              nDepth - 1,
+                              nSizeIndexedValue,
+                              pabyLastIndexedValue,
+                              bIndexedValueIsValid,
+                              nFirstIndexAtThisValue,
+                              anPagesAtThisValue,
+                              bSortThisValue,
+                              bInvalidateIndex) )
+            {
+                return FALSE;
+            }
+        }
+
+        return TRUE;
+    }
+}
+
+/************************************************************************/
+/*                              GetInt32()                              */
+/************************************************************************/
+
+static GInt32 GetInt32(const GByte* pBaseAddr, int iOffset)
+{
+    GInt32 nVal;
+    memcpy(&nVal, pBaseAddr + sizeof(nVal) * iOffset, sizeof(nVal));
+    CPL_LSBPTR32(&nVal);
+    return nVal;
+}
+
+/************************************************************************/
+/*                     UpdateNextOGRFIDAndFGDBFID()                     */
+/************************************************************************/
+
+static CPL_INLINE void UpdateNextOGRFIDAndFGDBFID(int i,
+                                       std::map<int,int>& oMapOGRFIDToFGDBFID,
+                                       std::map<int,int>::iterator& oIterO2F,
+                                       int& nNextOGRFID,
+                                       std::map<int,int>& oMapFGDBFIDToOGRFID,
+                                       std::map<int,int>::iterator& oIterF2O,
+                                       int& nNextFGDBFID)
+{
+    while( nNextOGRFID > 0 && i > nNextOGRFID )
+    {
+        ++ oIterO2F;
+        if( oIterO2F == oMapOGRFIDToFGDBFID.end() )
+            nNextOGRFID = -1;
+        else
+            nNextOGRFID = oIterO2F->first;
+    }
+
+    while( nNextFGDBFID > 0 && i > nNextFGDBFID )
+    {
+        ++ oIterF2O;
+        if( oIterF2O == oMapFGDBFIDToOGRFID.end() )
+            nNextFGDBFID = -1;
+        else
+            nNextFGDBFID = oIterF2O->first;
+    }
+}
+
+/************************************************************************/
+/*                          EditGDBTablX()                              */
+/************************************************************************/
+
+#define TEST_BIT(ar, bit)                       (ar[(bit) / 8] & (1 << ((bit) % 8)))
+#define SET_BIT(ar,bit)                         ar[(bit)/8] |= (1 << ((bit) % 8))
+#define BIT_ARRAY_SIZE_IN_BYTES(bitsize)        (((bitsize)+7)/8)
+
+/* See https://github.com/rouault/dump_gdbtable/wiki/FGDB-Spec */
+int  FGdbLayer::EditGDBTablX( const CPLString& osGDBTablX,
+                              const CPLString& osNewGDBTablX )
+{
+    VSILFILE* fp = VSIFOpenL(osGDBTablX, "rb");
+    if (fp == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot open %s", osGDBTablX.c_str());
+        return FALSE;
+    }
+    VSILFILE* fpNew = VSIFOpenL(osNewGDBTablX, "wb");
+    if (fpNew == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s", osNewGDBTablX.c_str());
+        VSIFCloseL(fp);
+        return FALSE;
+    }
+    GByte abyBuffer[16];
+    VSIFReadL(abyBuffer, 1, 16, fp);
+    int n1024Blocks = GetInt32(abyBuffer, 1);
+    int nInMaxFID = GetInt32(abyBuffer, 2);
+#ifdef DEBUG
+    const int nInMaxFIDOri = nInMaxFID;
+#endif
+    int nRecordSize = GetInt32(abyBuffer, 3);
+    CPLAssert(nRecordSize >= 4 && nRecordSize <= 6);
+
+    std::map<int,int>::iterator oIterO2F = m_oMapOGRFIDToFGDBFID.begin();
+    int nMaxOGRFID = 0;
+    for(; oIterO2F != m_oMapOGRFIDToFGDBFID.end(); ++oIterO2F )
+        nMaxOGRFID = oIterO2F->first;
+    //printf("nInMaxFID = %d\n", nInMaxFID);
+    //printf("nMaxOGRFID = %d\n", nMaxOGRFID);
+    int nOutMaxFID = MAX(nInMaxFID, nMaxOGRFID);
+
+    // Optimization: If the feature ids at the end of the file all map to a OGR fid
+    // then they don't need to be included in the final file
+    for(int i=nInMaxFID; i>nMaxOGRFID; i--)
+    {
+        if( m_oMapFGDBFIDToOGRFID.find(i) != m_oMapFGDBFIDToOGRFID.end() )
+        {
+            nOutMaxFID --;
+            nInMaxFID --;
+        }
+        else
+            break;
+    }
+
+    //printf("nInMaxFID = %d\n", nInMaxFID);
+    //printf("nOutMaxFID = %d\n", nOutMaxFID);
+
+    int n1024BlocksOut = (int)(((GIntBig)nOutMaxFID + 1023) / 1024);
+    int nTmp;
+
+    nTmp = CPL_LSBWORD32(n1024BlocksOut);
+    memcpy(abyBuffer + 4, &nTmp, 4);
+
+    nTmp = CPL_LSBWORD32(nOutMaxFID);
+    memcpy(abyBuffer + 8, &nTmp, 4);
+    VSIFWriteL(abyBuffer, 1, 16, fpNew);
+
+    VSIFSeekL(fp, 1024 * n1024Blocks * nRecordSize, SEEK_CUR);
+    VSIFReadL(abyBuffer, 1, 16, fp);
+    int nBitmapInt32Words = GetInt32(abyBuffer, 0);
+    int n1024BlocksTotal = GetInt32(abyBuffer, 1);
+    CPLAssert(n1024BlocksTotal == (int)(((GIntBig)nInMaxFIDOri + 1023 ) / 1024) );
+    GByte* pabyBlockMap = NULL;
+    if( nBitmapInt32Words != 0 )
+    {
+        int nSizeInBytes = BIT_ARRAY_SIZE_IN_BYTES(n1024BlocksTotal);
+        pabyBlockMap = (GByte*) CPLMalloc( nSizeInBytes );
+        VSIFReadL( pabyBlockMap, nSizeInBytes, 1, fp );
+    }
+    int nSizeInBytesOut = BIT_ARRAY_SIZE_IN_BYTES(n1024BlocksOut);
+    /* Round to the next multiple of 128 bytes (32 int4 words) */
+    nSizeInBytesOut = ((nSizeInBytesOut + 127) / 128) * 128;
+    GByte* pabyBlockMapOut = (GByte*) VSI_CALLOC_VERBOSE( 1, nSizeInBytesOut );
+    GByte* pabyPage = (GByte*)VSI_MALLOC_VERBOSE( 1024 * nRecordSize );
+    if( pabyBlockMapOut == NULL || pabyPage == NULL )
+    {
+        VSIFree(pabyBlockMapOut);
+        VSIFree(pabyPage);
+        VSIFCloseL(fp);
+        return FALSE;
+    }
+    GByte abyEmptyOffset[6];
+    memset(abyEmptyOffset, 0, 6);
+    int nNonEmptyPages = 0;
+    int nOffsetInPage = 0, nLastWrittenOffset = 0;
+    int bDisableSparsePages = CPLTestBool(CPLGetConfigOption("FILEGDB_DISABLE_SPARSE_PAGES", "NO"));
+
+    oIterO2F = m_oMapOGRFIDToFGDBFID.begin();
+    int nNextOGRFID = oIterO2F->first;
+    std::map<int,int>::iterator oIterF2O = m_oMapFGDBFIDToOGRFID.begin();
+    int nNextFGDBFID = oIterF2O->first;
+
+    int nCountBlocksBeforeIBlockIdx = 0;
+    int nCountBlocksBeforeIBlockValue = 0;
+
+    int bRet = TRUE;
+    for(int i=1; i<=nOutMaxFID;i++, nOffsetInPage += nRecordSize)
+    {
+        if( nOffsetInPage == 1024 * nRecordSize )
+        {
+            if( nLastWrittenOffset > 0 || bDisableSparsePages )
+            {
+                SET_BIT(pabyBlockMapOut, (i - 2) / 1024);
+                nNonEmptyPages ++;
+                if( nLastWrittenOffset < nOffsetInPage )
+                    memset(pabyPage + nLastWrittenOffset, 0, nOffsetInPage - nLastWrittenOffset);
+                if( VSIFWriteL(pabyPage, 1024 * nRecordSize, 1, fpNew) != 1 )
+                {
+                    bRet = FALSE;
+                    goto end;
+                }
+            }
+            nOffsetInPage = 0;
+            nLastWrittenOffset = 0;
+
+            // A few optimizations :
+            if( !bDisableSparsePages && i > nInMaxFID && nNextOGRFID > 0 && i < nNextOGRFID - 1024 )
+            {
+                // If we created a OGR FID far away from the latest FGDB FID
+                // then skip to it
+                i = ((nNextOGRFID-1) / 1024) * 1024 + 1;
+            }
+            else if( !bDisableSparsePages && pabyBlockMap != NULL && i <= nInMaxFID &&
+                     TEST_BIT(pabyBlockMap, (i-1)/1024) == 0 )
+            {
+                // Skip empty pages
+                UpdateNextOGRFIDAndFGDBFID(i,
+                                  m_oMapOGRFIDToFGDBFID, oIterO2F, nNextOGRFID,
+                                  m_oMapFGDBFIDToOGRFID, oIterF2O, nNextFGDBFID);
+                if( (nNextOGRFID < 0 || i < nNextOGRFID - 1024) &&
+                    (nNextFGDBFID < 0 || i < nNextFGDBFID - 1024) )
+                {
+                    if( i > INT_MAX - 1024 )
+                        break;
+                    i += 1023;
+                    nOffsetInPage += 1023 * nRecordSize;
+                    continue;
+                }
+            }
+        }
+
+       UpdateNextOGRFIDAndFGDBFID(i,
+                                  m_oMapOGRFIDToFGDBFID, oIterO2F, nNextOGRFID,
+                                  m_oMapFGDBFIDToOGRFID, oIterF2O, nNextFGDBFID);
+
+        int nSrcFID;
+        if( i == nNextOGRFID )
+        {
+            // This FID matches a user defined OGR FID, then find the
+            // corresponding FGDB record
+            nSrcFID = oIterO2F->second;
+            //printf("(1) i = %d, nSrcFID = %d\n", i, nSrcFID);
+        }
+        else if( i == nNextFGDBFID || i > nInMaxFID )
+        {
+            // This record is a temporary one (will be moved to a user-define FID)
+            // or we are out of the validity zone of input records
+            //printf("(2) i = %d, nNextFGDBFID = %d, nInMaxFID = %d\n", i, nNextFGDBFID, nInMaxFID);
+            continue;
+        }
+        else
+        {
+            // Regular record, not overloaded by user defined FID
+            nSrcFID = i;
+            //printf("(3) i = %d, nSrcFID = %d\n", i, nSrcFID);
+        }
+
+        if( pabyBlockMap != NULL )
+        {
+            int iBlock = (nSrcFID-1) / 1024;
+
+            // Check if the block is not empty
+            if( TEST_BIT(pabyBlockMap, iBlock) )
+            {
+                int nCountBlocksBefore;
+                if( iBlock >= nCountBlocksBeforeIBlockIdx )
+                {
+                    nCountBlocksBefore = nCountBlocksBeforeIBlockValue;
+                    for(int j=nCountBlocksBeforeIBlockIdx;j<iBlock;j++)
+                        nCountBlocksBefore += TEST_BIT(pabyBlockMap, j) != 0;
+                }
+                else
+                {
+                    nCountBlocksBefore = 0;
+                    for(int j=0;j<iBlock;j++)
+                        nCountBlocksBefore += TEST_BIT(pabyBlockMap, j) != 0;
+                }
+                nCountBlocksBeforeIBlockIdx = iBlock;
+                nCountBlocksBeforeIBlockValue = nCountBlocksBefore;
+                int iCorrectedRow = nCountBlocksBefore * 1024 + ((nSrcFID-1) % 1024);
+                VSIFSeekL(fp, 16 + nRecordSize * iCorrectedRow, SEEK_SET);
+                VSIFReadL(abyBuffer, 1, nRecordSize, fp);
+                if( memcmp( abyBuffer, abyEmptyOffset, nRecordSize) != 0 )
+                {
+                    if( nLastWrittenOffset < nOffsetInPage )
+                        memset(pabyPage + nLastWrittenOffset, 0, nOffsetInPage - nLastWrittenOffset);
+                    memcpy(pabyPage + nOffsetInPage, abyBuffer, nRecordSize);
+                    nLastWrittenOffset = nOffsetInPage + nRecordSize;
+                }
+            }
+        }
+        else
+        {
+            VSIFSeekL(fp, 16 + nRecordSize * (nSrcFID-1), SEEK_SET);
+            VSIFReadL(abyBuffer, 1, nRecordSize, fp);
+            if( memcmp( abyBuffer, abyEmptyOffset, nRecordSize) != 0 )
+            {
+                if( nLastWrittenOffset < nOffsetInPage )
+                    memset(pabyPage + nLastWrittenOffset, 0, nOffsetInPage - nLastWrittenOffset);
+                memcpy(pabyPage + nOffsetInPage, abyBuffer, nRecordSize);
+                nLastWrittenOffset = nOffsetInPage + nRecordSize;
+            }
+        }
+    }
+    //printf("nLastWrittenOffset = %d\n", nLastWrittenOffset);
+    if( nLastWrittenOffset > 0 || bDisableSparsePages )
+    {
+        SET_BIT(pabyBlockMapOut, (nOutMaxFID - 1) / 1024);
+        nNonEmptyPages ++;
+        if( nLastWrittenOffset < 1024 * nRecordSize )
+            memset(pabyPage + nLastWrittenOffset, 0, 1024 * nRecordSize - nLastWrittenOffset);
+        if( VSIFWriteL(pabyPage, 1024 * nRecordSize, 1, fpNew) != 1 )
+        {
+            bRet = FALSE;
+            goto end;
+        }
+    }
+
+    memset(abyBuffer, 0, 16);
+
+    /* Number of total blocks, including omitted ones */
+    nTmp = CPL_LSBWORD32(n1024BlocksOut);
+    memcpy(abyBuffer + 4, &nTmp, 4);
+
+    nTmp = CPL_LSBWORD32(nNonEmptyPages);
+    memcpy(abyBuffer + 8, &nTmp, 4);
+
+    if( nNonEmptyPages < n1024BlocksOut )
+    {
+        /* Number of int4 words for the bitmap (rounded to the next multiple of 32) */
+        nTmp = CPL_LSBWORD32(nSizeInBytesOut / 4);
+        memcpy(abyBuffer + 0, &nTmp, 4);
+
+        /* Number of int4 words in the bitmap where there's at least a non-zero bit */
+        /* Seems to be unused */
+        nTmp = CPL_LSBWORD32(((nOutMaxFID - 1) / 1024 + 31) / 32);
+        memcpy(abyBuffer + 12, &nTmp, 4);
+    }
+
+    if( VSIFWriteL(abyBuffer, 1, 16, fpNew) != 16 )
+    {
+        bRet = FALSE;
+        goto end;
+    }
+
+    if( nNonEmptyPages < n1024BlocksOut )
+    {
+        VSIFWriteL(pabyBlockMapOut, 1, nSizeInBytesOut, fpNew);
+
+        VSIFSeekL(fpNew, 4, SEEK_SET);
+        nTmp = CPL_LSBWORD32(nNonEmptyPages);
+        VSIFWriteL(&nTmp, 1, 4, fpNew);
+    }
+
+end:
+    CPLFree(pabyBlockMap);
+    CPLFree(pabyBlockMapOut);
+    CPLFree(pabyPage);
+    VSIFCloseL(fpNew);
+    VSIFCloseL(fp);
+
+    return bRet;
+}
+
+#ifdef EXTENT_WORKAROUND
+
+/************************************************************************/
+/*                     UpdateRowWithGeometry()                          */
+/************************************************************************/
+
+bool FGdbLayer::UpdateRowWithGeometry(Row& row, OGRGeometry* poGeom)
+{
+    ShapeBuffer shape;
+    long hr;
+
+    /* Write geometry to a buffer */
+    GByte *pabyShape = NULL;
+    int nShapeSize = 0;
+    if ( OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize ) != OGRERR_NONE )
+    {
+        CPLFree(pabyShape);
+        return false;
+    }
+
+    /* Copy it into a ShapeBuffer */
+    if ( nShapeSize > 0 )
+    {
+        shape.Allocate(nShapeSize);
+        memcpy(shape.shapeBuffer, pabyShape, nShapeSize);
+        shape.inUseLength = nShapeSize;
+    }
+
+    /* Free the shape buffer */
+    CPLFree(pabyShape);
+
+    /* Write ShapeBuffer into the Row */
+    hr = row.SetGeometry(shape);
+    if (FAILED(hr))
+    {
+        return false;
+    }
+
+    /* Update row */
+    hr = m_pTable->Update(row);
+    if (FAILED(hr))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                    WorkAroundExtentProblem()                         */
+/*                                                                      */
+/* Work-around problem with FileGDB API 1.1 on Linux 64bit. See #4455   */
+/************************************************************************/
+
+void FGdbLayer::WorkAroundExtentProblem()
+{
+    if (!m_bLayerJustCreated || !m_bLayerEnvelopeValid)
+        return;
+    m_bLayerJustCreated = FALSE;
+
+    OGREnvelope sEnvelope;
+    if (GetExtent(&sEnvelope, TRUE) != OGRERR_NONE)
+        return;
+
+    /* The characteristic of the bug is that the reported extent */
+    /* is the real extent truncated incorrectly to integer values */
+    /* We work around that by temporary updating one feature with a geometry */
+    /* whose coordinates are integer values but ceil'ed and floor'ed */
+    /* such that they include the real layer extent. */
+    if (((double)(int)sEnvelope.MinX == sEnvelope.MinX &&
+         (double)(int)sEnvelope.MinY == sEnvelope.MinY &&
+         (double)(int)sEnvelope.MaxX == sEnvelope.MaxX &&
+         (double)(int)sEnvelope.MaxY == sEnvelope.MaxY) &&
+        (fabs(sEnvelope.MinX - sLayerEnvelope.MinX) > 1e-5 ||
+         fabs(sEnvelope.MinY - sLayerEnvelope.MinY) > 1e-5 ||
+         fabs(sEnvelope.MaxX - sLayerEnvelope.MaxX) > 1e-5 ||
+         fabs(sEnvelope.MaxY - sLayerEnvelope.MaxY) > 1e-5))
+    {
+        long           hr;
+        Row            row;
+        EnumRows       enumRows;
+
+        if (FAILED(hr = m_pTable->Search(StringToWString("*"), StringToWString(""), true, enumRows)))
+            return;
+
+        if (FAILED(hr = enumRows.Next(row)))
+            return;
+
+        if (hr != S_OK)
+            return;
+
+        /* Backup original shape buffer */
+        ShapeBuffer originalGdbGeometry;
+        if (FAILED(hr = row.GetGeometry(originalGdbGeometry)))
+            return;
+
+        OGRGeometry* pOGRGeo = NULL;
+        if ((!GDBGeometryToOGRGeometry(m_forceMulti, &originalGdbGeometry, m_pSRS, &pOGRGeo)) || pOGRGeo == NULL)
+        {
+            delete pOGRGeo;
+            return;
+        }
+
+        OGRwkbGeometryType eType = wkbFlatten(pOGRGeo->getGeometryType());
+
+        delete pOGRGeo;
+        pOGRGeo = NULL;
+
+        OGRPoint oP1(floor(sLayerEnvelope.MinX), floor(sLayerEnvelope.MinY));
+        OGRPoint oP2(ceil(sLayerEnvelope.MaxX), ceil(sLayerEnvelope.MaxY));
+
+        OGRLinearRing oLR;
+        oLR.addPoint(&oP1);
+        oLR.addPoint(&oP2);
+        oLR.addPoint(&oP1);
+
+        if ( eType == wkbPoint )
+        {
+            UpdateRowWithGeometry(row, &oP1);
+            UpdateRowWithGeometry(row, &oP2);
+        }
+        else if ( eType == wkbLineString )
+        {
+            UpdateRowWithGeometry(row, &oLR);
+        }
+        else if ( eType == wkbPolygon )
+        {
+            OGRPolygon oPoly;
+            oPoly.addRing(&oLR);
+
+            UpdateRowWithGeometry(row, &oPoly);
+        }
+        else if ( eType == wkbMultiPoint )
+        {
+            OGRMultiPoint oColl;
+            oColl.addGeometry(&oP1);
+            oColl.addGeometry(&oP2);
+
+            UpdateRowWithGeometry(row, &oColl);
+        }
+        else if ( eType == wkbMultiLineString )
+        {
+            OGRMultiLineString oColl;
+            oColl.addGeometry(&oLR);
+
+            UpdateRowWithGeometry(row, &oColl);
+        }
+        else if ( eType == wkbMultiPolygon )
+        {
+            OGRMultiPolygon oColl;
+            OGRPolygon oPoly;
+            oPoly.addRing(&oLR);
+            oColl.addGeometry(&oPoly);
+
+            UpdateRowWithGeometry(row, &oColl);
+        }
+        else
+            return;
+
+        /* Restore original ShapeBuffer */
+        hr = row.SetGeometry(originalGdbGeometry);
+        if (FAILED(hr))
+            return;
+
+        /* Update Row */
+        hr = m_pTable->Update(row);
+        if (FAILED(hr))
+            return;
+
+        CPLDebug("FGDB", "Workaround extent problem with Linux 64bit FGDB SDK 1.1");
+    }
+}
+#endif // EXTENT_WORKAROUND
+
+/************************************************************************/
+/*                            ICreateFeature()                           */
+/* Create an FGDB Row and populate it from an OGRFeature.               */
+/*                                                                      */
+/************************************************************************/
+
+OGRErr FGdbLayer::ICreateFeature( OGRFeature *poFeature )
+{
+    Row fgdb_row;
+    fgdbError hr;
+
+    if( !m_pDS->GetUpdate() || m_pTable == NULL )
+        return OGRERR_FAILURE;
+
+    GIntBig nFID = poFeature->GetFID();
+    if( nFID < -1 || nFID == 0 || !CPL_INT64_FITS_ON_INT32(nFID) )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Only 32 bit positive integers FID supported by FileGDB");
+        return OGRERR_FAILURE;
+    }
+
+    if( nFID > 0 )
+    {
+        if( m_pDS->GetOpenFileGDBDrv() == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot call CreateFeature() with a set FID when OpenFileGDB driver not available");
+            return OGRERR_FAILURE;
+        }
+
+        if( m_pDS->HasSelectLayers() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot call CreateFeature() with a set FID when a layer resulting from ExecuteSQL() is still opened");
+            return OGRERR_FAILURE;
+        }
+
+        if( m_pDS->GetConnection()->GetRefCount() > 1 )
+            {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot call CreateFeature() with a set FID when a dataset is opened more than once");
+            return OGRERR_FAILURE;
+        }
+
+        if( m_oMapOGRFIDToFGDBFID.find((int)poFeature->GetFID()) != m_oMapOGRFIDToFGDBFID.end() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "A feature with same FID already exists");
+            return OGRERR_FAILURE;
+        }
+
+        if( m_oMapFGDBFIDToOGRFID.find((int)poFeature->GetFID()) == m_oMapFGDBFIDToOGRFID.end() )
+        {
+            EnumRows       enumRows;
+            Row            row;
+            if (GetRow(enumRows, row, (int)poFeature->GetFID()) == OGRERR_NONE)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "A feature with same FID already exists");
+                return OGRERR_FAILURE;
+            }
+        }
+
+        if( (int)m_oMapOGRFIDToFGDBFID.size() == m_nResyncThreshold )
+            ResyncIDs();
+    }
+
+    if( m_bSymlinkFlag && !CreateRealCopy() )
+        return OGRERR_FAILURE;
+
+    if (m_bBulkLoadAllowed < 0)
+        m_bBulkLoadAllowed = CPLTestBool(CPLGetConfigOption("FGDB_BULK_LOAD", "NO"));
+
+    if (m_bBulkLoadAllowed && !m_bBulkLoadInProgress)
+        StartBulkLoad();
+
+    hr = m_pTable->CreateRowObject(fgdb_row);
+
+    /* Check the status of the Row create */
+    if (FAILED(hr))
+    {
+        GDBErr(hr, "Failed at creating Row in CreateFeature.");
+        return OGRERR_FAILURE;
+    }
+
+    /* As we have issues with fixed values for dates, or CURRENT_xxxx isn't */
+    /* handled anyway, let's fill ourselves all unset fields with their default */
+    poFeature->FillUnsetWithDefault(FALSE, NULL);
+
+    /* Populate the row with the feature content */
+    if (PopulateRowWithFeature(fgdb_row, poFeature) != OGRERR_NONE)
+        return OGRERR_FAILURE;
+
+    /* Cannot write to FID field - it is managed by GDB*/
+    //std::wstring wfield_name = StringToWString(m_strOIDFieldName);
+    //hr = fgdb_row.SetInteger(wfield_name, poFeature->GetFID());
+
+    /* Write the row to the table */
+    hr = m_pTable->Insert(fgdb_row);
+    if (FAILED(hr))
+    {
+        GDBErr(hr, "Failed at writing Row to Table in CreateFeature.");
+        return OGRERR_FAILURE;
+    }
+
+    int32 oid = -1;
+    if (!FAILED(hr = fgdb_row.GetOID(oid)))
+    {
+        if( poFeature->GetFID() < 0 )
+        {
+            // Avoid colliding with a user set FID
+            while( m_oMapOGRFIDToFGDBFID.find(oid) != m_oMapOGRFIDToFGDBFID.end() )
+            {
+                EndBulkLoad();
+
+                CPLDebug("FGDB", "Collision with user set FID %d", oid);
+                if (FAILED(hr = m_pTable->Delete(fgdb_row)))
+                {
+                    GDBErr(hr, "Failed deleting row ");
+                    return OGRERR_FAILURE;
+                }
+                hr = m_pTable->Insert(fgdb_row);
+                if (FAILED(hr))
+                {
+                    GDBErr(hr, "Failed at writing Row to Table in CreateFeature.");
+                    return OGRERR_FAILURE;
+                }
+                if (FAILED(hr = fgdb_row.GetOID(oid)))
+                {
+                    return OGRERR_FAILURE;
+                }
+            }
+            poFeature->SetFID(oid);
+        }
+        else if( (int)poFeature->GetFID() != oid )
+        {
+            m_pDS->GetConnection()->SetFIDHackInProgress(TRUE);
+            m_oMapOGRFIDToFGDBFID[(int)poFeature->GetFID()] = oid;
+            m_oMapFGDBFIDToOGRFID[oid] = (int)poFeature->GetFID();
+        }
+    }
+
+#ifdef EXTENT_WORKAROUND
+    /* For WorkAroundExtentProblem() needs */
+    OGRGeometry* poGeom = poFeature->GetGeometryRef();
+    if ( m_bLayerJustCreated && poGeom != NULL && !poGeom->IsEmpty() )
+    {
+        OGREnvelope sFeatureGeomEnvelope;
+        poGeom->getEnvelope(&sFeatureGeomEnvelope);
+        if (!m_bLayerEnvelopeValid)
+        {
+            memcpy(&sLayerEnvelope, &sFeatureGeomEnvelope, sizeof(sLayerEnvelope));
+            m_bLayerEnvelopeValid = true;
+        }
+        else
+        {
+            sLayerEnvelope.Merge(sFeatureGeomEnvelope);
+        }
+    }
+#endif
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                    PopulateRowWithFeature()                          */
+/*                                                                      */
+/************************************************************************/
+
+OGRErr FGdbLayer::PopulateRowWithFeature( Row& fgdb_row, OGRFeature *poFeature )
+{
+    ShapeBuffer shape;
+    fgdbError hr;
+
+    OGRFeatureDefn* poFeatureDefn = m_pFeatureDefn;
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+
+    /* Copy the OGR visible fields (everything except geometry and FID) */
+    int nCountBinaryField = 0;
+    for( int i = 0; i < nFieldCount; i++ )
+    {
+        std::string field_name = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+        std::wstring wfield_name = StringToWString(field_name);
+        const std::string & strFieldType = m_vOGRFieldToESRIFieldType[i];
+
+        /* Set empty fields to NULL */
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
+        {
+            if( strFieldType == "esriFieldTypeGlobalID" )
+                continue;
+
+            if (FAILED(hr = fgdb_row.SetNull(wfield_name)))
+            {
+                GDBErr(hr, "Failed setting field to NULL.");
+                return OGRERR_FAILURE;
+            }
+            continue;
+        }
+
+        /* Set the information using the appropriate FGDB function */
+        int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
+
+        if ( nOGRFieldType == OFTInteger )
+        {
+            int fldvalue = poFeature->GetFieldAsInteger(i);
+            if( strFieldType == "esriFieldTypeInteger" )
+                hr = fgdb_row.SetInteger(wfield_name, fldvalue);
+            else
+            {
+                if( fldvalue < -32768 || fldvalue > 32767 )
+                {
+                    static int bHasWarned = FALSE;
+                    if( !bHasWarned )
+                    {
+                        bHasWarned = TRUE;
+                        CPLError(CE_Warning, CPLE_NotSupported,
+                                 "Value %d for field %s does not fit into a short and will be clamped. "
+                                 "This warning will not be emitted any more",
+                                 fldvalue, field_name.c_str());
+                    }
+                    if( fldvalue < -32768 )
+                        fldvalue = -32768;
+                    else
+                        fldvalue = 32767;
+                }
+                hr = fgdb_row.SetShort(wfield_name, (short) fldvalue);
+            }
+        }
+        else if ( nOGRFieldType == OFTReal || nOGRFieldType == OFTInteger64 )
+        {
+            /* Doubles (we don't handle FGDB Floats) */
+            double fldvalue = poFeature->GetFieldAsDouble(i);
+            if( strFieldType == "esriFieldTypeDouble" )
+                hr = fgdb_row.SetDouble(wfield_name, fldvalue);
+            else
+                hr = fgdb_row.SetFloat(wfield_name, (float) fldvalue);
+        }
+        else if ( nOGRFieldType == OFTString )
+        {
+            /* Strings we convert to wstring */
+            std::string fldvalue = poFeature->GetFieldAsString(i);
+            if( strFieldType == "esriFieldTypeString" )
+            {
+                std::wstring wfldvalue = StringToWString(fldvalue);
+                hr = fgdb_row.SetString(wfield_name, wfldvalue);
+            }
+            // Apparently, esriFieldTypeGlobalID can not be set, but is
+            // initialized by the FileGDB SDK itself.
+            else if( strFieldType == "esriFieldTypeGUID" /*||
+                     strFieldType == "esriFieldTypeGlobalID" */ )
+            {
+                Guid guid;
+                std::wstring wfldvalue = StringToWString(fldvalue);
+                if( FAILED(hr = guid.FromString(wfldvalue)) )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                        "Cannot parse GUID value %s for field %s.",
+                        fldvalue.c_str(), field_name.c_str() );
+                }
+                else
+                {
+                    hr = fgdb_row.SetGUID(wfield_name, guid);
+                }
+            }
+            else if( strFieldType == "esriFieldTypeXML"  )
+            {
+                hr = fgdb_row.SetXML(wfield_name, fldvalue);
+            }
+            else
+                hr = 0;
+        }
+        else if ( nOGRFieldType == OFTDateTime || nOGRFieldType == OFTDate )
+        {
+            /* Dates we need to coerce a little */
+            struct tm val;
+            poFeature->GetFieldAsDateTime(i, &(val.tm_year), &(val.tm_mon), &(val.tm_mday),
+                                          &(val.tm_hour), &(val.tm_min), &(val.tm_sec), NULL);
+            val.tm_year -= 1900;
+            val.tm_mon = val.tm_mon - 1; /* OGR months go 1-12, FGDB go 0-11 */
+            hr = fgdb_row.SetDate(wfield_name, val);
+        }
+        else if ( nOGRFieldType == OFTBinary )
+        {
+            /* Binary data */
+            int bytesize;
+            GByte *bytes = poFeature->GetFieldAsBinary(i, &bytesize);
+            if ( bytesize )
+            {
+                /* This is annoying but SetBinary() doesn't keep the binary */
+                /* content. The ByteArray object must still be alive at */
+                /* the time Insert() is called */
+                m_apoByteArrays[nCountBinaryField]->Allocate(bytesize);
+                memcpy(m_apoByteArrays[nCountBinaryField]->byteArray, bytes, bytesize);
+                m_apoByteArrays[nCountBinaryField]->inUseLength = bytesize;
+                hr = fgdb_row.SetBinary(wfield_name, *(m_apoByteArrays[nCountBinaryField]));
+            }
+            else
+            {
+                hr = fgdb_row.SetNull(wfield_name);
+            }
+            nCountBinaryField ++;
+        }
+        else
+        {
+            /* We can't handle this type */
+            CPLError( CE_Failure, CPLE_AppDefined,
+                "FGDB driver does not support OGR type." );
+            return OGRERR_FAILURE;
+        }
+
+        if (FAILED(hr))
+        {
+            CPLError(CE_Warning, CPLE_AppDefined, "Cannot set value for field %s",
+                     field_name.c_str());
+        }
+    }
+
+    if ( m_pFeatureDefn->GetGeomType() != wkbNone )
+    {
+        /* Done with attribute fields, now do geometry */
+        OGRGeometry *poGeom = poFeature->GetGeometryRef();
+
+        if (poGeom == NULL || poGeom->IsEmpty())
+        {
+            /* EMPTY geometries should be treated as NULL, see #4832 */
+            hr = fgdb_row.SetNull(StringToWString(m_strShapeFieldName));
+            if (FAILED(hr))
+            {
+                GDBErr(hr, "Failed at writing EMPTY Geometry to Row in CreateFeature.");
+                return OGRERR_FAILURE;
+            }
+        }
+        else
+        {
+            /* Write geometry to a buffer */
+            GByte *pabyShape = NULL;
+            int nShapeSize = 0;
+            OGRErr err;
+
+            const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
+            if( m_bCreateMultipatch && (eType == wkbMultiPolygon ||
+                                        eType == wkbMultiSurface ||
+                                        eType == wkbTIN ||
+                                        eType == wkbPolyhedralSurface ||
+                                        eType == wkbGeometryCollection) )
+            {
+                err = OGRWriteMultiPatchToShapeBin( poGeom, &pabyShape, &nShapeSize );
+                if( err == OGRERR_UNSUPPORTED_OPERATION )
+                    err = OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize );
+            }
+            else
+            {
+                err = OGRWriteToShapeBin( poGeom, &pabyShape, &nShapeSize );
+            }
+            if ( err != OGRERR_NONE )
+            {
+                CPLFree(pabyShape);
+                return err;
+            }
+
+            /* Copy it into a ShapeBuffer */
+            if ( nShapeSize > 0 )
+            {
+                shape.Allocate(nShapeSize);
+                memcpy(shape.shapeBuffer, pabyShape, nShapeSize);
+                shape.inUseLength = nShapeSize;
+            }
+
+            /* Free the shape buffer */
+            CPLFree(pabyShape);
+
+            /* Write ShapeBuffer into the Row */
+            hr = fgdb_row.SetGeometry(shape);
+            if (FAILED(hr))
+            {
+                GDBErr(hr, "Failed at writing Geometry to Row in CreateFeature.");
+                return OGRERR_FAILURE;
+            }
+        }
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                             GetRow()                                 */
+/************************************************************************/
+
+OGRErr FGdbLayer::GetRow( EnumRows& enumRows, Row& row, GIntBig nFID )
+{
+    long           hr;
+    CPLString      osQuery;
+
+    /* Querying a 64bit FID causes a runtime exception in FileGDB... */
+    if( !CPL_INT64_FITS_ON_INT32(nFID) )
+    {
+        return OGRERR_FAILURE;
+    }
+
+    osQuery.Printf("%s = " CPL_FRMT_GIB, m_strOIDFieldName.c_str(), nFID);
+
+    if (FAILED(hr = m_pTable->Search(m_wstrSubfields, StringToWString(osQuery.c_str()), true, enumRows)))
+    {
+        GDBErr(hr, "Failed fetching row ");
+        return OGRERR_FAILURE;
+    }
+
+    if (FAILED(hr = enumRows.Next(row)))
+    {
+        GDBErr(hr, "Failed fetching row ");
+        return OGRERR_FAILURE;
+    }
+
+    if (hr != S_OK)
+        return OGRERR_NON_EXISTING_FEATURE; //none found - but no failure
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           DeleteFeature()                            */
+/************************************************************************/
+
+OGRErr FGdbLayer::DeleteFeature( GIntBig nFID )
+
+{
+    long           hr;
+    EnumRows       enumRows;
+    Row            row;
+
+    if( !m_pDS->GetUpdate() || m_pTable == NULL )
+        return OGRERR_FAILURE;
+    if( !CPL_INT64_FITS_ON_INT32(nFID) )
+        return OGRERR_NON_EXISTING_FEATURE;
+
+    if( m_bSymlinkFlag && !CreateRealCopy() )
+        return OGRERR_FAILURE;
+
+    int nFID32 = (int)nFID;
+    std::map<int,int>::iterator oIter = m_oMapOGRFIDToFGDBFID.find(nFID32);
+    if( oIter != m_oMapOGRFIDToFGDBFID.end() )
+    {
+        nFID32 = oIter->second;
+        m_oMapFGDBFIDToOGRFID.erase(nFID32);
+        m_oMapOGRFIDToFGDBFID.erase(oIter);
+    }
+    else if( m_oMapFGDBFIDToOGRFID.find(nFID32) != m_oMapFGDBFIDToOGRFID.end() )
+        return OGRERR_NON_EXISTING_FEATURE;
+
+    EndBulkLoad();
+
+    OGRErr eErr = GetRow(enumRows, row, nFID32);
+    if( eErr != OGRERR_NONE)
+        return eErr;
+
+    if (FAILED(hr = m_pTable->Delete(row)))
+    {
+        GDBErr(hr, "Failed deleting row ");
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                            ISetFeature()                              */
+/************************************************************************/
+
+OGRErr FGdbLayer::ISetFeature( OGRFeature* poFeature )
+
+{
+    long           hr;
+    EnumRows       enumRows;
+    Row            row;
+
+    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
+        return OGRERR_FAILURE;
+
+    GIntBig nFID64 = poFeature->GetFID();
+    if( nFID64 == OGRNullFID )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "SetFeature() with unset FID fails." );
+        return OGRERR_FAILURE;
+    }
+    if( !CPL_INT64_FITS_ON_INT32(nFID64) )
+        return OGRERR_NON_EXISTING_FEATURE;
+
+    EndBulkLoad();
+
+    if( m_bSymlinkFlag && !CreateRealCopy() )
+        return OGRERR_FAILURE;
+
+    int nFID = (int)nFID64;
+    std::map<int,int>::iterator oIter = m_oMapOGRFIDToFGDBFID.find(nFID);
+    if( oIter != m_oMapOGRFIDToFGDBFID.end() )
+        nFID = oIter->second;
+    else if( m_oMapFGDBFIDToOGRFID.find((int)poFeature->GetFID()) != m_oMapFGDBFIDToOGRFID.end() )
+        return OGRERR_NON_EXISTING_FEATURE;
+
+    OGRErr eErr = GetRow(enumRows, row, nFID);
+    if( eErr != OGRERR_NONE)
+        return eErr;
+
+    /* Populate the row with the feature content */
+    if (PopulateRowWithFeature(row, poFeature) != OGRERR_NONE)
+        return OGRERR_FAILURE;
+
+    if (FAILED(hr = m_pTable->Update(row)))
+    {
+        GDBErr(hr, "Failed updating row ");
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          CreateFieldDefn()                           */
+/************************************************************************/
+
+char* FGdbLayer::CreateFieldDefn(OGRFieldDefn& oField,
+                                 int bApproxOK,
+                                 std::string& fieldname_clean,
+                                 std::string& gdbFieldType)
+{
+    std::string fieldname = oField.GetNameRef();
+    //std::string fidname = std::string(GetFIDColumn());
+    std::string nullable = (oField.IsNullable()) ? "true" : "false";
+
+    /* Try to map the OGR type to an ESRI type */
+    OGRFieldType fldtype = oField.GetType();
+    if ( ! OGRToGDBFieldType(fldtype, oField.GetSubType(), &gdbFieldType) )
+    {
+        GDBErr(-1, "Failed converting field type.");
+        return NULL;
+    }
+
+    if( oField.GetType() == OFTInteger64 && !bApproxOK )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Integer64 not supported in FileGDB");
+        return NULL;
+    }
+
+    const char* pszColumnTypes = CSLFetchNameValue(m_papszOptions, "COLUMN_TYPES");
+    if( pszColumnTypes != NULL )
+    {
+        char** papszTokens = CSLTokenizeString2(pszColumnTypes, ",", 0);
+        const char* pszFieldType = CSLFetchNameValue(papszTokens, fieldname.c_str());
+        if( pszFieldType != NULL )
+        {
+            OGRFieldType fldtypeCheck;
+            OGRFieldSubType eSubType;
+            if( GDBToOGRFieldType(pszFieldType, &fldtypeCheck, &eSubType) )
+            {
+                if( fldtypeCheck != fldtype )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined, "Ignoring COLUMN_TYPES=%s=%s : %s not consistent with OGR data type",
+                         fieldname.c_str(), pszFieldType, pszFieldType);
+                }
+                else
+                    gdbFieldType = pszFieldType;
+            }
+            else
+                CPLError(CE_Warning, CPLE_AppDefined, "Ignoring COLUMN_TYPES=%s=%s : %s not recognized",
+                         fieldname.c_str(), pszFieldType, pszFieldType);
+        }
+        CSLDestroy(papszTokens);
+    }
+
+    if (!fieldname_clean.empty())
+    {
+        oField.SetName(fieldname_clean.c_str());
+    }
+    else
+    {
+        /* Clean field names */
+        fieldname_clean = FGDBLaunderName(fieldname);
+
+        if (m_bLaunderReservedKeywords)
+            fieldname_clean = FGDBEscapeReservedKeywords(fieldname_clean);
+
+        /* Truncate to 64 characters */
+        if (fieldname_clean.size() > 64)
+            fieldname_clean.resize(64);
+
+        std::string temp_fieldname = fieldname_clean;
+
+        /* Ensures uniqueness of field name */
+        int numRenames = 1;
+        while ((m_pFeatureDefn->GetFieldIndex(temp_fieldname.c_str()) >= 0) && (numRenames < 10))
+        {
+            temp_fieldname = CPLSPrintf("%s_%d", fieldname_clean.substr(0, 62).c_str(), numRenames);
+            numRenames ++;
+        }
+        while ((m_pFeatureDefn->GetFieldIndex(temp_fieldname.c_str()) >= 0) && (numRenames < 100))
+        {
+            temp_fieldname = CPLSPrintf("%s_%d", fieldname_clean.substr(0, 61).c_str(), numRenames);
+            numRenames ++;
+        }
+
+        if (temp_fieldname != fieldname)
+        {
+            if( !bApproxOK || (m_pFeatureDefn->GetFieldIndex(temp_fieldname.c_str()) >= 0) )
+            {
+                CPLError( CE_Failure, CPLE_NotSupported,
+                    "Failed to add field named '%s'",
+                    fieldname.c_str() );
+                return NULL;
+            }
+            CPLError(CE_Warning, CPLE_NotSupported,
+                "Normalized/laundered field name: '%s' to '%s'",
+                fieldname.c_str(), temp_fieldname.c_str());
+
+            fieldname_clean = temp_fieldname;
+            oField.SetName(fieldname_clean.c_str());
+        }
+    }
+
+    /* Then the Field definition */
+    CPLXMLNode *defn_xml = CPLCreateXMLNode(NULL, CXT_Element, "esri:Field");
+
+    /* Add the XML attributes to the Field node */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xs", "http://www.w3.org/2001/XMLSchema");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:esri", "http://www.esri.com/schemas/ArcGIS/10.1");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xsi:type", "esri:Field");
+
+    /* Basic field information */
+    CPLCreateXMLElementAndValue(defn_xml, "Name", fieldname_clean.c_str());
+    CPLCreateXMLElementAndValue(defn_xml, "Type", gdbFieldType.c_str());
+    CPLCreateXMLElementAndValue(defn_xml, "IsNullable", nullable.c_str());
+
+    /* Get the Width and Precision if we know them */
+    int width = oField.GetWidth();
+    int precision = oField.GetPrecision();
+    if ( width <= 0 )
+        GDBFieldTypeToWidthPrecision(gdbFieldType, &width, &precision);
+
+    /* Write out the Width and Precision */
+    char buf[100];
+    snprintf(buf, 100, "%d", width);
+    CPLCreateXMLElementAndValue(defn_xml,"Length", buf);
+    snprintf(buf, 100, "%d", precision);
+    CPLCreateXMLElementAndValue(defn_xml,"Precision", buf);
+
+    /* We know nothing about Scale, so zero it out */
+    CPLCreateXMLElementAndValue(defn_xml,"Scale", "0");
+
+    /*  Attempt to preserve the original fieldname */
+    if (fieldname != fieldname_clean)
+    {
+        CPLCreateXMLElementAndValue(defn_xml, "AliasName", fieldname.c_str());
+    }
+
+    if( oField.GetDefault() != NULL )
+    {
+        const char* pszDefault = oField.GetDefault();
+        /*int nYear, nMonth, nDay, nHour, nMinute;
+        float fSecond;*/
+        if( oField.GetType() == OFTString )
+        {
+            CPLString osVal = pszDefault;
+            if( osVal[0] == '\'' && osVal.back() == '\'' )
+            {
+                osVal = osVal.substr(1);
+                osVal.resize(osVal.size()-1);
+                char* pszTmp = CPLUnescapeString(osVal, NULL, CPLES_SQL);
+                osVal = pszTmp;
+                CPLFree(pszTmp);
+            }
+            CPLXMLNode* psDefaultValue =
+                CPLCreateXMLElementAndValue(defn_xml, "DefaultValue", osVal);
+            FGDB_CPLAddXMLAttribute(psDefaultValue, "xsi:type", "xs:string");
+        }
+        else if( oField.GetType() == OFTInteger &&
+                 !EQUAL(gdbFieldType.c_str(), "esriFieldTypeSmallInteger") &&
+                 CPLGetValueType(pszDefault) == CPL_VALUE_INTEGER )
+        {
+            CPLXMLNode* psDefaultValue =
+                CPLCreateXMLElementAndValue(defn_xml, "DefaultValue", pszDefault);
+            FGDB_CPLAddXMLAttribute(psDefaultValue, "xsi:type", "xs:int");
+        }
+        else if( oField.GetType() == OFTReal &&
+                 !EQUAL(gdbFieldType.c_str(), "esriFieldTypeSingle") &&
+                 CPLGetValueType(pszDefault) != CPL_VALUE_STRING )
+        {
+            CPLXMLNode* psDefaultValue =
+                CPLCreateXMLElementAndValue(defn_xml, "DefaultValue", pszDefault);
+            FGDB_CPLAddXMLAttribute(psDefaultValue, "xsi:type", "xs:double");
+        }
+        /*else if( oField.GetType() == OFTDateTime &&
+                 sscanf(pszDefault, "'%d/%d/%d %d:%d:%f'", &nYear, &nMonth, &nDay,
+                        &nHour, &nMinute, &fSecond) == 6 )
+        {
+            CPLXMLNode* psDefaultValue =
+                CPLCreateXMLElementAndValue(defn_xml, "DefaultValue",
+                    CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d",
+                               nYear, nMonth, nDay, nHour, nMinute, (int)(fSecond + 0.5)));
+            FGDB_CPLAddXMLAttribute(psDefaultValue, "xsi:type", "xs:dateTime");
+        }*/
+    }
+    /* <DefaultValue xsi:type="xs:string">afternoon</DefaultValue> */
+
+    /* Convert our XML tree into a string for FGDB */
+    char *defn_str = CPLSerializeXMLTree(defn_xml);
+    CPLDebug("FGDB", "CreateField() generated XML for FGDB\n%s", defn_str);
+
+    /* Free the XML */
+    CPLDestroyXMLNode(defn_xml);
+
+    return defn_str;
+}
+
+/************************************************************************/
+/*                            CreateField()                             */
+/*  Build up an FGDB XML field definition and use it to create a Field  */
+/*  Update the OGRFeatureDefn to reflect the new field.                 */
+/*                                                                      */
+/************************************************************************/
+
+OGRErr FGdbLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
+{
+    OGRFieldDefn oField(poField);
+    std::string fieldname_clean;
+    std::string gdbFieldType;
+
+    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
+        return OGRERR_FAILURE;
+
+    char* defn_str = CreateFieldDefn(oField, bApproxOK,
+                                     fieldname_clean, gdbFieldType);
+    if (defn_str == NULL)
+        return OGRERR_FAILURE;
+
+    /* Add the FGDB Field to the FGDB Table. */
+    fgdbError hr = m_pTable->AddField(defn_str);
+
+    CPLFree(defn_str);
+
+    /* Check the status of the Field add */
+    if (FAILED(hr))
+    {
+        GDBErr(hr, "Failed at creating Field for " + std::string(oField.GetNameRef()));
+        return OGRERR_FAILURE;
+    }
+
+    /* Now add the OGRFieldDefn to the OGRFeatureDefn */
+    m_pFeatureDefn->AddFieldDefn(&oField);
+
+    m_vOGRFieldToESRIField.push_back(StringToWString(fieldname_clean));
+    m_vOGRFieldToESRIFieldType.push_back( gdbFieldType );
+
+    if( oField.GetType() == OFTBinary )
+        m_apoByteArrays.push_back(new ByteArray());
+
+    /* All done and happy */
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                             DeleteField()                            */
+/************************************************************************/
+
+OGRErr FGdbLayer::DeleteField( int iFieldToDelete )
+{
+
+    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
+        return OGRERR_FAILURE;
+
+    if (iFieldToDelete < 0 || iFieldToDelete >= m_pFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+    ResetReading();
+
+    const char* pszFieldName = m_pFeatureDefn->GetFieldDefn(iFieldToDelete)->GetNameRef();
+
+    fgdbError hr;
+    if (FAILED(hr = m_pTable->DeleteField(StringToWString(pszFieldName))))
+    {
+        GDBErr(hr, "Failed deleting field " + std::string(pszFieldName));
+        return OGRERR_FAILURE;
+    }
+
+    m_vOGRFieldToESRIField.erase (m_vOGRFieldToESRIField.begin() + iFieldToDelete);
+    m_vOGRFieldToESRIFieldType.erase( m_vOGRFieldToESRIFieldType.begin() + iFieldToDelete );
+
+    return m_pFeatureDefn->DeleteFieldDefn( iFieldToDelete );
+}
+
+#ifdef AlterFieldDefn_implemented_but_not_working
+
+/************************************************************************/
+/*                           AlterFieldDefn()                           */
+/************************************************************************/
+
+OGRErr FGdbLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags )
+{
+
+    if( !m_pDS->GetUpdate()|| m_pTable == NULL )
+        return OGRERR_FAILURE;
+
+    if (iFieldToAlter < 0 || iFieldToAlter >= m_pFeatureDefn->GetFieldCount())
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Invalid field index");
+        return OGRERR_FAILURE;
+    }
+
+    OGRFieldDefn* poFieldDefn = m_pFeatureDefn->GetFieldDefn(iFieldToAlter);
+    OGRFieldDefn oField(poFieldDefn);
+
+    if (nFlags & ALTER_TYPE_FLAG)
+    {
+        oField.SetSubType(OFSTNone);
+        oField.SetType(poNewFieldDefn->GetType());
+        oField.SetSubType(poNewFieldDefn->GetSubType());
+    }
+    if (nFlags & ALTER_NAME_FLAG)
+    {
+        if (strcmp(poNewFieldDefn->GetNameRef(), oField.GetNameRef()) != 0)
+        {
+            CPLError( CE_Failure, CPLE_NotSupported,
+                      "Altering field name is not supported" );
+            return OGRERR_FAILURE;
+        }
+        oField.SetName(poNewFieldDefn->GetNameRef());
+    }
+    if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
+    {
+        oField.SetWidth(poNewFieldDefn->GetWidth());
+        oField.SetPrecision(poNewFieldDefn->GetPrecision());
+    }
+
+    std::string fieldname_clean = WStringToString(m_vOGRFieldToESRIField[iFieldToAlter]);
+    std::string gdbFieldType;
+
+    char* defn_str = CreateFieldDefn(oField, TRUE,
+                                     fieldname_clean, gdbFieldType);
+    if (defn_str == NULL)
+        return OGRERR_FAILURE;
+
+    ResetReading();
+
+    /* Add the FGDB Field to the FGDB Table. */
+    fgdbError hr = m_pTable->AlterField(defn_str);
+
+    CPLFree(defn_str);
+
+    /* Check the status of the AlterField */
+    if (FAILED(hr))
+    {
+        GDBErr(hr, "Failed at altering field " + std::string(oField.GetNameRef()));
+        return OGRERR_FAILURE;
+    }
+
+    m_vOGRFieldToESRIFieldType[iFieldToAlter] = gdbFieldType;
+
+    poFieldDefn->SetSubType(OFSTNone);
+    poFieldDefn->SetType(oField.GetType());
+    poFieldDefn->SetType(oField.GetSubType());
+    poFieldDefn->SetWidth(oField.GetWidth());
+    poFieldDefn->SetPrecision(oField.GetPrecision());
+
+    return OGRERR_NONE;
+}
+#endif // AlterFieldDefn_implemented_but_not_working
+
+/************************************************************************/
+/*                      XMLSpatialReference()                           */
+/*  Build up an XML representation of an OGRSpatialReference.           */
+/*  Used in layer creation.                                             */
+/*                                                                      */
+/************************************************************************/
+
+static CPLXMLNode* XMLSpatialReference(OGRSpatialReference* poSRS, char** papszOptions)
+{
+    /* We always need a SpatialReference */
+    CPLXMLNode *srs_xml = CPLCreateXMLNode(NULL, CXT_Element, "SpatialReference");
+
+    /* Extract the WKID before morphing */
+    int nSRID = 0;
+    if ( poSRS && poSRS->GetAuthorityCode(NULL) )
+    {
+        nSRID = atoi(poSRS->GetAuthorityCode(NULL));
+    }
+
+    /* NULL poSRS => UnknownCoordinateSystem */
+    if ( ! poSRS )
+    {
+        FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:UnknownCoordinateSystem");
+    }
+    else
+    {
+        /* Set the SpatialReference type attribute correctly for GEOGCS/PROJCS */
+        if ( poSRS->IsProjected() )
+            FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:ProjectedCoordinateSystem");
+        else
+            FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:GeographicCoordinateSystem");
+
+        /* Add the WKT to the XML */
+        SpatialReferenceInfo oESRI_SRS;
+
+        /* Do we have a known SRID ? If so, directly query the ESRI SRS DB */
+        if( nSRID && SpatialReferences::FindSpatialReferenceBySRID(nSRID, oESRI_SRS) )
+        {
+            CPLDebug("FGDB",
+                     "Layer SRS has a SRID (%d). Using WKT from ESRI SRS DBFound perfect match. ",
+                     nSRID);
+            CPLCreateXMLElementAndValue(srs_xml,"WKT", WStringToString(oESRI_SRS.srtext).c_str());
+        }
+        else
+        {
+            /* Make a clone so we can morph it without morphing the original */
+            OGRSpatialReference* poSRSClone = poSRS->Clone();
+
+            /* Flip the WKT to ESRI form, return UnknownCoordinateSystem if we can't */
+            if ( poSRSClone->morphToESRI() != OGRERR_NONE )
+            {
+                delete poSRSClone;
+                FGDB_CPLAddXMLAttribute(srs_xml, "xsi:type", "esri:UnknownCoordinateSystem");
+                return srs_xml;
+            }
+
+            char *wkt = NULL;
+            poSRSClone->exportToWkt(&wkt);
+            if (wkt)
+            {
+                EnumSpatialReferenceInfo oEnumESRI_SRS;
+                std::vector<int> oaiCandidateSRS;
+                nSRID = 0;
+
+                /* Enumerate SRS from ESRI DB and find a match */
+                while( true )
+                {
+                    if ( poSRS->IsProjected() )
+                    {
+                        if( !oEnumESRI_SRS.NextProjectedSpatialReference(oESRI_SRS) )
+                            break;
+                    }
+                    else
+                    {
+                        if( !oEnumESRI_SRS.NextGeographicSpatialReference(oESRI_SRS) )
+                            break;
+                    }
+
+                    std::string osESRI_WKT = WStringToString(oESRI_SRS.srtext);
+                    const char* pszESRI_WKT = osESRI_WKT.c_str();
+                    if( strcmp(pszESRI_WKT, wkt) == 0 )
+                    {
+                        /* Exact match found (not sure this case happens) */
+                        nSRID = oESRI_SRS.auth_srid;
+                        break;
+                    }
+                    OGRSpatialReference oSRS_FromESRI;
+                    if( oSRS_FromESRI.SetFromUserInput(pszESRI_WKT) == OGRERR_NONE &&
+                        poSRSClone->IsSame(&oSRS_FromESRI) )
+                    {
+                        /* Potential match found */
+                        oaiCandidateSRS.push_back(oESRI_SRS.auth_srid);
+                    }
+                }
+
+                if( nSRID != 0 )
+                {
+                    CPLDebug("FGDB",
+                             "Found perfect match in ESRI SRS DB "
+                             "for layer SRS. SRID is %d", nSRID);
+                }
+                else if( oaiCandidateSRS.empty() )
+                {
+                     CPLDebug("FGDB",
+                              "Did not found a match in ESRI SRS DB for layer SRS. "
+                              "Using morphed SRS WKT. Failure is to be expected");
+                }
+                else if( oaiCandidateSRS.size() == 1 )
+                {
+                    nSRID = oaiCandidateSRS[0];
+                    if( SpatialReferences::FindSpatialReferenceBySRID(
+                                                            nSRID, oESRI_SRS) )
+                    {
+                        CPLDebug("FGDB",
+                                 "Found a single match in ESRI SRS DB "
+                                 "for layer SRS. SRID is %d",
+                                 nSRID);
+                        nSRID = oESRI_SRS.auth_srid;
+                        CPLFree(wkt);
+                        wkt = CPLStrdup(WStringToString(oESRI_SRS.srtext).c_str());
+                    }
+                }
+                else
+                {
+                    /* Not sure this case can happen */
+
+                    CPLString osCandidateSRS;
+                    for(int i=0; i<(int)oaiCandidateSRS.size() && i < 10; i++)
+                    {
+                        if( !osCandidateSRS.empty() )
+                            osCandidateSRS += ", ";
+                        osCandidateSRS += CPLSPrintf("%d", oaiCandidateSRS[i]);
+                    }
+                    if(oaiCandidateSRS.size() > 10)
+                        osCandidateSRS += "...";
+
+                    CPLDebug("FGDB",
+                             "As several candidates (%s) have been found in "
+                             "ESRI SRS DB for layer SRS, none has been selected. "
+                             "Using morphed SRS WKT. Failure is to be expected",
+                             osCandidateSRS.c_str());
+                }
+
+                CPLCreateXMLElementAndValue(srs_xml,"WKT", wkt);
+                CPLFree(wkt);
+            }
+
+            /* Dispose of our close */
+            delete poSRSClone;
+        }
+    }
+
+    /* Handle Origin/Scale/Tolerance */
+    const char* grid[7] = {
+      "XOrigin", "YOrigin", "XYScale",
+      "ZOrigin", "ZScale",
+      "XYTolerance", "ZTolerance" };
+    const char* gridvalues[7];
+
+    /*
+    Need different default parameters for geographic and projected coordinate systems.
+    Try and use ArcGIS 10 default values.
+    */
+    // default tolerance is 1mm in the units of the coordinate system
+    double ztol = 0.001 * (poSRS ? poSRS->GetTargetLinearUnits("VERT_CS") : 1.0);
+    // default scale is 10x the tolerance
+    long zscale = (long)(1 / ztol * 10);
+
+    char s_xyscale[50], s_xytol[50], s_zscale[50], s_ztol[50];
+    CPLsnprintf(s_ztol, 50, "%f", ztol);
+    snprintf(s_zscale, 50, "%ld", zscale);
+
+    if ( poSRS == NULL || poSRS->IsProjected() )
+    {
+        // default tolerance is 1mm in the units of the coordinate system
+        double xytol = 0.001 * (poSRS ? poSRS->GetTargetLinearUnits("PROJCS") : 1.0);
+        // default scale is 10x the tolerance
+        long xyscale = (long)(1 / xytol * 10);
+
+        CPLsnprintf(s_xytol, 50, "%f", xytol);
+        snprintf(s_xyscale, 50, "%ld", xyscale);
+
+        // Ideally we would use the same X/Y origins as ArcGIS, but we need the algorithm they use.
+        gridvalues[0] = "-2147483647";
+        gridvalues[1] = "-2147483647";
+        gridvalues[2] = s_xyscale;
+        gridvalues[3] = "-100000";
+        gridvalues[4] = s_zscale;
+        gridvalues[5] = s_xytol;
+        gridvalues[6] = s_ztol;
+    }
+    else
+    {
+        gridvalues[0] = "-400";
+        gridvalues[1] = "-400";
+        gridvalues[2] = "1000000000";
+        gridvalues[3] = "-100000";
+        gridvalues[4] = s_zscale;
+        gridvalues[5] = "0.000000008983153";
+        gridvalues[6] = s_ztol;
+    }
+
+    /* Convert any layer creation options available, use defaults otherwise */
+    for( int i = 0; i < 7; i++ )
+    {
+        if ( CSLFetchNameValue( papszOptions, grid[i] ) != NULL )
+            gridvalues[i] = CSLFetchNameValue( papszOptions, grid[i] );
+
+        CPLCreateXMLElementAndValue(srs_xml, grid[i], gridvalues[i]);
+    }
+
+    /* FGDB is always High Precision */
+    CPLCreateXMLElementAndValue(srs_xml, "HighPrecision", "true");
+
+    /* Add the WKID to the XML */
+    if ( nSRID )
+    {
+        CPLCreateXMLElementAndValue(srs_xml, "WKID", CPLSPrintf("%d", nSRID));
+    }
+
+    return srs_xml;
+}
+
+/************************************************************************/
+/*                    CreateFeatureDataset()                            */
+/************************************************************************/
+
+bool FGdbLayer::CreateFeatureDataset(FGdbDataSource* pParentDataSource,
+                                     const std::string& feature_dataset_name,
+                                     OGRSpatialReference* poSRS,
+                                     char** papszOptions )
+{
+    /* XML node */
+    CPLXMLNode *xml_xml = CPLCreateXMLNode(NULL, CXT_Element, "?xml");
+    FGDB_CPLAddXMLAttribute(xml_xml, "version", "1.0");
+    FGDB_CPLAddXMLAttribute(xml_xml, "encoding", "UTF-8");
+
+    /* First build up a bare-bones feature definition */
+    CPLXMLNode *defn_xml = CPLCreateXMLNode(NULL, CXT_Element, "esri:DataElement");
+    CPLAddXMLSibling(xml_xml, defn_xml);
+
+    /* Add the attributes to the DataElement */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xs", "http://www.w3.org/2001/XMLSchema");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:esri", "http://www.esri.com/schemas/ArcGIS/10.1");
+
+    /* Need to set this to esri:DEFeatureDataset or esri:DETable */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xsi:type", "esri:DEFeatureDataset");
+
+    /* Add in more children */
+    std::string catalog_page = "\\" + feature_dataset_name;
+    CPLCreateXMLElementAndValue(defn_xml,"CatalogPath", catalog_page.c_str());
+    CPLCreateXMLElementAndValue(defn_xml,"Name", feature_dataset_name.c_str());
+    CPLCreateXMLElementAndValue(defn_xml,"ChildrenExpanded", "false");
+    CPLCreateXMLElementAndValue(defn_xml,"DatasetType", "esriDTFeatureDataset");
+    CPLCreateXMLElementAndValue(defn_xml,"Versioned", "false");
+    CPLCreateXMLElementAndValue(defn_xml,"CanVersion", "false");
+
+    /* Add in empty extent */
+    CPLXMLNode *extent_xml = CPLCreateXMLNode(NULL, CXT_Element, "Extent");
+    FGDB_CPLAddXMLAttribute(extent_xml, "xsi:nil", "true");
+    CPLAddXMLChild(defn_xml, extent_xml);
+
+    /* Add the SRS */
+    if( true ) // TODO: conditional on existence of SRS
+    {
+        CPLXMLNode *srs_xml = XMLSpatialReference(poSRS, papszOptions);
+        if ( srs_xml )
+            CPLAddXMLChild(defn_xml, srs_xml);
+    }
+
+    /* Convert our XML tree into a string for FGDB */
+    char *defn_str = CPLSerializeXMLTree(xml_xml);
+    CPLDestroyXMLNode(xml_xml);
+
+    /* TODO, tie this to debugging levels */
+    CPLDebug("FGDB", "%s", defn_str);
+
+    /* Create the FeatureDataset. */
+    Geodatabase *gdb = pParentDataSource->GetGDB();
+    fgdbError hr = gdb->CreateFeatureDataset(defn_str);
+
+    /* Free the XML */
+    CPLFree(defn_str);
+
+    /* Check table create status */
+    if (FAILED(hr))
+    {
+        return GDBErr(hr, "Failed at creating FeatureDataset " + feature_dataset_name);
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                            Create()                                  */
+/* Build up an FGDB XML layer definition and use it to create a Table   */
+/* or Feature Class to work from.                                       */
+/*                                                                      */
+/* Layer creation options:                                              */
+/*   FEATURE_DATASET, nest layer inside a FeatureDataset folder         */
+/*   GEOMETRY_NAME, user-selected name for the geometry column          */
+/*   FID/OID_NAME, user-selected name for the FID column                */
+/*   XORIGIN, YORIGIN, ZORIGIN, origin of the snapping grid             */
+/*   XYSCALE, ZSCALE, inverse resolution of the snapping grid           */
+/*   XYTOLERANCE, ZTOLERANCE, snapping tolerance for topology/networks  */
+/*                                                                      */
+/************************************************************************/
+
+bool FGdbLayer::Create(FGdbDataSource* pParentDataSource,
+                       const char* pszLayerNameIn,
+                       OGRSpatialReference* poSRS,
+                       OGRwkbGeometryType eType,
+                       char** papszOptions)
+{
+    std::string parent_path = "";
+    std::wstring wtable_path, wparent_path;
+    std::string geometry_name = FGDB_GEOMETRY_NAME;
+    std::string fid_name = FGDB_OID_NAME;
+    std::string esri_type;
+    bool has_z = false;
+    bool has_m = false;
+
+#ifdef EXTENT_WORKAROUND
+    m_bLayerJustCreated = true;
+#endif
+
+    /* Launder the Layer name */
+    std::string layerName;
+
+    layerName = FGDBLaunderName(pszLayerNameIn);
+    layerName = FGDBEscapeReservedKeywords(layerName);
+    layerName = FGDBEscapeUnsupportedPrefixes(layerName);
+
+    if (layerName.size() > 160)
+        layerName.resize(160);
+
+    /* Ensures uniqueness of layer name */
+    int numRenames = 1;
+    while ((pParentDataSource->GetLayerByName(layerName.c_str()) != NULL) && (numRenames < 10))
+    {
+        layerName = CPLSPrintf("%s_%d", layerName.substr(0, 158).c_str(), numRenames);
+        numRenames ++;
+    }
+    while ((pParentDataSource->GetLayerByName(layerName.c_str()) != NULL) && (numRenames < 100))
+    {
+        layerName = CPLSPrintf("%s_%d", layerName.substr(0, 157).c_str(), numRenames);
+        numRenames ++;
+    }
+
+    if (layerName != pszLayerNameIn)
+    {
+        CPLError(CE_Warning, CPLE_NotSupported,
+                "Normalized/laundered layer name: '%s' to '%s'",
+                pszLayerNameIn, layerName.c_str());
+    }
+
+    std::string table_path = "\\" + std::string(layerName);
+
+    /* Handle the FEATURE_DATASET case */
+    if (  CSLFetchNameValue( papszOptions, "FEATURE_DATASET") != NULL )
+    {
+        std::string feature_dataset = CSLFetchNameValue( papszOptions, "FEATURE_DATASET");
+
+        /* Check if FEATURE_DATASET exists. Otherwise create it */
+        std::vector<wstring> featuredatasets;
+        Geodatabase *gdb = pParentDataSource->GetGDB();
+        int bFeatureDataSetExists = FALSE;
+        fgdbError hr;
+        if ( !FAILED(hr = gdb->GetChildDatasets(L"\\", L"Feature Dataset", featuredatasets)) )
+        {
+            std::wstring feature_dataset_with_slash = L"\\" + StringToWString(feature_dataset);
+            for ( unsigned int i = 0; i < featuredatasets.size(); i++ )
+            {
+                if (featuredatasets[i] == feature_dataset_with_slash)
+                    bFeatureDataSetExists = TRUE;
+            }
+        }
+
+        if (!bFeatureDataSetExists)
+        {
+            bool rv = CreateFeatureDataset(pParentDataSource, feature_dataset, poSRS, papszOptions);
+            if ( ! rv )
+                return rv;
+        }
+
+        table_path = "\\" + feature_dataset + table_path;
+        parent_path = "\\" + feature_dataset;
+    }
+
+    /* Convert table_path into wstring */
+    wtable_path = StringToWString(table_path);
+    wparent_path = StringToWString(parent_path);
+
+    /* Over-ride the geometry name if necessary */
+    if ( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
+        geometry_name = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
+
+    /* Over-ride the OID name if necessary */
+    if ( CSLFetchNameValue( papszOptions, "FID") != NULL )
+        fid_name = CSLFetchNameValue( papszOptions, "FID");
+    else if ( CSLFetchNameValue( papszOptions, "OID_NAME") != NULL )
+        fid_name = CSLFetchNameValue( papszOptions, "OID_NAME");
+
+    m_bCreateMultipatch = CPLTestBool(CSLFetchNameValueDef(
+                                    papszOptions, "CREATE_MULTIPATCH", "NO"));
+
+    /* Figure out our geometry type */
+    if ( eType != wkbNone )
+    {
+        if ( wkbFlatten(eType) == wkbUnknown )
+        {
+            return GDBErr(-1, "FGDB layers cannot be created with a wkbUnknown layer geometry type.");
+        }
+        if ( ! OGRGeometryToGDB(eType, &esri_type, &has_z, &has_m) )
+            return GDBErr(-1, "Unable to map OGR type to ESRI type");
+
+        if( wkbFlatten(eType) == wkbMultiPolygon && m_bCreateMultipatch )
+        {
+            esri_type = "esriGeometryMultiPatch";
+            has_z = true;
+        }
+        // For TIN and PolyhedralSurface, default to create a multipatch,
+        // unless the user explicitly disabled it
+        else if( (wkbFlatten(eType) == wkbTIN ||
+                  wkbFlatten(eType) == wkbPolyhedralSurface ) &&
+                 CPLTestBool(CSLFetchNameValueDef(papszOptions,
+                                                  "CREATE_MULTIPATCH", "YES")) )
+        {
+            m_bCreateMultipatch = true;
+            esri_type = "esriGeometryMultiPatch";
+            has_z = true;
+        }
+    }
+
+    m_bLaunderReservedKeywords =
+        CPLFetchBool( papszOptions, "LAUNDER_RESERVED_KEYWORDS", true);
+
+    /* XML node */
+    CPLXMLNode *xml_xml = CPLCreateXMLNode(NULL, CXT_Element, "?xml");
+    FGDB_CPLAddXMLAttribute(xml_xml, "version", "1.0");
+    FGDB_CPLAddXMLAttribute(xml_xml, "encoding", "UTF-8");
+
+    /* First build up a bare-bones feature definition */
+    CPLXMLNode *defn_xml = CPLCreateXMLNode(NULL, CXT_Element, "esri:DataElement");
+    CPLAddXMLSibling(xml_xml, defn_xml);
+
+    /* Add the attributes to the DataElement */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:xs", "http://www.w3.org/2001/XMLSchema");
+    FGDB_CPLAddXMLAttribute(defn_xml, "xmlns:esri", "http://www.esri.com/schemas/ArcGIS/10.1");
+
+    /* Need to set this to esri:DEFeatureDataset or esri:DETable */
+    FGDB_CPLAddXMLAttribute(defn_xml, "xsi:type", (eType == wkbNone ? "esri:DETable" : "esri:DEFeatureClass"));
+
+    /* Add in more children */
+    CPLCreateXMLElementAndValue(defn_xml,"CatalogPath",table_path.c_str());
+    CPLCreateXMLElementAndValue(defn_xml,"Name", layerName.c_str());
+    CPLCreateXMLElementAndValue(defn_xml,"ChildrenExpanded", "false");
+
+    /* WKB type of none implies this is a 'Table' otherwise it's a 'Feature Class' */
+    std::string datasettype = (eType == wkbNone ? "esriDTTable" : "esriDTFeatureClass");
+    CPLCreateXMLElementAndValue(defn_xml,"DatasetType", datasettype.c_str() );
+    CPLCreateXMLElementAndValue(defn_xml,"Versioned", "false");
+    CPLCreateXMLElementAndValue(defn_xml,"CanVersion", "false");
+
+    if ( CSLFetchNameValue( papszOptions, "CONFIGURATION_KEYWORD") != NULL )
+        CPLCreateXMLElementAndValue(defn_xml,"ConfigurationKeyword",
+                                    CSLFetchNameValue( papszOptions, "CONFIGURATION_KEYWORD"));
+
+    /* We might need to make OID optional later, but OGR likes to have a FID */
+    CPLCreateXMLElementAndValue(defn_xml,"HasOID", "true");
+    CPLCreateXMLElementAndValue(defn_xml,"OIDFieldName", fid_name.c_str());
+
+    /* Add in empty Fields */
+    CPLXMLNode *fields_xml = CPLCreateXMLNode(defn_xml, CXT_Element, "Fields");
+    FGDB_CPLAddXMLAttribute(fields_xml, "xsi:type", "esri:Fields");
+    CPLXMLNode *fieldarray_xml = CPLCreateXMLNode(fields_xml, CXT_Element, "FieldArray");
+    FGDB_CPLAddXMLAttribute(fieldarray_xml, "xsi:type", "esri:ArrayOfField");
+
+    /* Feature Classes have an implicit geometry column, so we'll add it at creation time */
+    CPLXMLNode *srs_xml = NULL;
+    if ( eType != wkbNone )
+    {
+        CPLXMLNode *shape_xml = CPLCreateXMLNode(fieldarray_xml, CXT_Element, "Field");
+        FGDB_CPLAddXMLAttribute(shape_xml, "xsi:type", "esri:Field");
+        CPLCreateXMLElementAndValue(shape_xml, "Name", geometry_name.c_str());
+        CPLCreateXMLElementAndValue(shape_xml, "Type", "esriFieldTypeGeometry");
+        if( CPLFetchBool( papszOptions, "GEOMETRY_NULLABLE", true) )
+            CPLCreateXMLElementAndValue(shape_xml, "IsNullable", "true");
+        else
+            CPLCreateXMLElementAndValue(shape_xml, "IsNullable", "false");
+        CPLCreateXMLElementAndValue(shape_xml, "Length", "0");
+        CPLCreateXMLElementAndValue(shape_xml, "Precision", "0");
+        CPLCreateXMLElementAndValue(shape_xml, "Scale", "0");
+        CPLCreateXMLElementAndValue(shape_xml, "Required", "true");
+        CPLXMLNode *geom_xml = CPLCreateXMLNode(shape_xml, CXT_Element, "GeometryDef");
+        FGDB_CPLAddXMLAttribute(geom_xml, "xsi:type", "esri:GeometryDef");
+        CPLCreateXMLElementAndValue(geom_xml, "AvgNumPoints", "0");
+        CPLCreateXMLElementAndValue(geom_xml, "GeometryType", esri_type.c_str());
+        CPLCreateXMLElementAndValue(geom_xml,"HasM", (has_m ? "true" : "false"));
+        CPLCreateXMLElementAndValue(geom_xml,"HasZ", (has_z ? "true" : "false"));
+
+        /* Add the SRS if we have one */
+        srs_xml = XMLSpatialReference(poSRS, papszOptions);
+        if ( srs_xml )
+            CPLAddXMLChild(geom_xml, srs_xml);
+    }
+
+    /* All (?) Tables and Feature Classes will have an ObjectID */
+    CPLXMLNode *oid_xml = CPLCreateXMLNode(fieldarray_xml, CXT_Element, "Field");
+    FGDB_CPLAddXMLAttribute(oid_xml, "xsi:type", "esri:Field");
+    CPLCreateXMLElementAndValue(oid_xml, "Name", fid_name.c_str());
+    CPLCreateXMLElementAndValue(oid_xml, "Type", "esriFieldTypeOID");
+    CPLCreateXMLElementAndValue(oid_xml, "IsNullable", "false");
+    CPLCreateXMLElementAndValue(oid_xml, "Length", "12");
+    CPLCreateXMLElementAndValue(oid_xml, "Precision", "0");
+    CPLCreateXMLElementAndValue(oid_xml, "Scale", "0");
+    CPLCreateXMLElementAndValue(oid_xml, "Required", "true");
+
+    /* Add in empty Indexes */
+    CPLXMLNode *indexes_xml = CPLCreateXMLNode(defn_xml, CXT_Element, "Indexes");
+    FGDB_CPLAddXMLAttribute(indexes_xml, "xsi:type", "esri:Indexes");
+    CPLXMLNode *indexarray_xml = CPLCreateXMLNode(indexes_xml, CXT_Element, "IndexArray");
+    FGDB_CPLAddXMLAttribute(indexarray_xml, "xsi:type", "esri:ArrayOfIndex");
+
+    /* CLSID http://forums.arcgis.com/threads/34536?p=118484#post118484 */
+    if ( eType == wkbNone )
+    {
+        CPLCreateXMLElementAndValue(defn_xml, "CLSID", "{7A566981-C114-11D2-8A28-006097AFF44E}");
+        CPLCreateXMLElementAndValue(defn_xml, "EXTCLSID", "");
+    }
+    else
+    {
+        CPLCreateXMLElementAndValue(defn_xml, "CLSID", "{52353152-891A-11D0-BEC6-00805F7C4268}");
+        CPLCreateXMLElementAndValue(defn_xml, "EXTCLSID", "");
+    }
+
+    /* Set the alias for the Feature Class */
+    if (pszLayerNameIn != layerName)
+    {
+        CPLCreateXMLElementAndValue(defn_xml, "AliasName", pszLayerNameIn);
+    }
+
+    /* Map from OGR WKB type to ESRI type */
+    if ( eType != wkbNone )
+    {
+        /* Declare our feature type */
+        CPLCreateXMLElementAndValue(defn_xml,"FeatureType", "esriFTSimple");
+        CPLCreateXMLElementAndValue(defn_xml,"ShapeType", esri_type.c_str());
+        CPLCreateXMLElementAndValue(defn_xml,"ShapeFieldName", geometry_name.c_str());
+
+        /* Dimensionality */
+        CPLCreateXMLElementAndValue(defn_xml,"HasM", (has_m ? "true" : "false"));
+        CPLCreateXMLElementAndValue(defn_xml,"HasZ", (has_z ? "true" : "false"));
+
+        /* TODO: Handle spatial indexes (layer creation option?) */
+        CPLCreateXMLElementAndValue(defn_xml,"HasSpatialIndex", "false");
+
+        /* These field are required for Arcmap to display aliases correctly */
+        CPLCreateXMLNode(defn_xml, CXT_Element, "AreaFieldName");
+        CPLCreateXMLNode(defn_xml, CXT_Element, "LengthFieldName");
+
+        /* We can't know the extent at this point <Extent xsi:nil='true'/> */
+        CPLXMLNode *extn_xml = CPLCreateXMLNode(defn_xml, CXT_Element, "Extent");
+        FGDB_CPLAddXMLAttribute(extn_xml, "xsi:nil", "true");
+    }
+
+    /* Feature Class with known SRS gets an SRS entry */
+    if( eType != wkbNone && srs_xml != NULL)
+    {
+        CPLAddXMLChild(defn_xml, CPLCloneXMLTree(srs_xml));
+    }
+
+    /* Convert our XML tree into a string for FGDB */
+    char *defn_str;
+
+    if( CSLFetchNameValue( papszOptions, "XML_DEFINITION") != NULL )
+        defn_str = CPLStrdup(CSLFetchNameValue( papszOptions, "XML_DEFINITION"));
+    else
+        defn_str = CPLSerializeXMLTree(xml_xml);
+    CPLDestroyXMLNode(xml_xml);
+
+    /* TODO, tie this to debugging levels */
+    CPLDebug("FGDB", "%s", defn_str);
+    //std::cout << defn_str << std::endl;
+
+    /* Create the table. */
+    Table *table = new Table;
+    Geodatabase *gdb = pParentDataSource->GetGDB();
+    fgdbError hr = gdb->CreateTable(defn_str, wparent_path, *table);
+
+    /* Free the XML */
+    CPLFree(defn_str);
+
+    /* Check table create status */
+    if (FAILED(hr))
+    {
+        delete table;
+        return GDBErr(hr, "Failed at creating table for " + table_path);
+    }
+
+    m_papszOptions = CSLDuplicate(papszOptions);
+
+    // Default to YES here assuming ogr2ogr scenario
+    m_bBulkLoadAllowed = CPLTestBool(CPLGetConfigOption("FGDB_BULK_LOAD", "YES"));
+
+    /* Store the new FGDB Table pointer and set up the OGRFeatureDefn */
+    return FGdbLayer::Initialize(pParentDataSource, table, wtable_path, L"Table");
+}
+
+/*************************************************************************/
+/*                            Initialize()                               */
+/* Has ownership of the table as soon as it is called.                   */
+/************************************************************************/
+
+bool FGdbLayer::Initialize(FGdbDataSource* pParentDataSource, Table* pTable,
+                           const std::wstring& wstrTablePath,
+                           const std::wstring& wstrType)
+{
+    long hr;
+
+    m_pDS = pParentDataSource; // we never assume ownership of the parent - so our destructor should not delete
+
+    m_pTable = pTable;
+
+    m_wstrTablePath = wstrTablePath;
+    m_wstrType = wstrType;
+
+    wstring wstrQueryName;
+    if (FAILED(hr = pParentDataSource->GetGDB()->GetQueryName(wstrTablePath, wstrQueryName)))
+        return GDBErr(hr, "Failed at getting underlying table name for " +
+                      WStringToString(wstrTablePath));
+
+    m_strName = WStringToString(wstrQueryName);
+
+    m_pFeatureDefn = new OGRFeatureDefn(m_strName.c_str()); //TODO: Should I "new" an OGR smart pointer - sample says so, but it doesn't seem right
+    SetDescription( m_pFeatureDefn->GetName() );
+    //as long as we use the same compiler & settings in both the ogr build and this
+    //driver, we should be OK
+    m_pFeatureDefn->Reference();
+
+    string tableDef;
+    if (FAILED(hr = m_pTable->GetDefinition(tableDef)))
+        return GDBErr(hr, "Failed at getting table definition for " +
+                      WStringToString(wstrTablePath));
+
+    //xxx  printf("Table definition = %s", tableDef.c_str() );
+
+    bool abort = false;
+
+    // extract schema information from table
+    CPLXMLNode *psRoot = CPLParseXMLString( tableDef.c_str() );
+
+    if (psRoot == NULL)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "%s",
+                  ("Failed parsing GDB Table Schema XML for " + m_strName).c_str());
+        return false;
+    }
+
+    CPLXMLNode *pDataElementNode = psRoot->psNext; // Move to next field which should be DataElement
+
+    if( pDataElementNode != NULL
+        && pDataElementNode->psChild != NULL
+        && pDataElementNode->eType == CXT_Element
+        && EQUAL(pDataElementNode->pszValue,"esri:DataElement") )
+    {
+        CPLXMLNode *psNode;
+
+        for( psNode = pDataElementNode->psChild;
+        psNode != NULL;
+        psNode = psNode->psNext )
+        {
+            if( psNode->eType == CXT_Element && psNode->psChild != NULL )
+            {
+                if (EQUAL(psNode->pszValue,"OIDFieldName") )
+                {
+                    char* pszUnescaped = CPLUnescapeString(
+                    psNode->psChild->pszValue, NULL, CPLES_XML);
+                    m_strOIDFieldName = pszUnescaped;
+                    CPLFree(pszUnescaped);
+                }
+                else if (EQUAL(psNode->pszValue,"ShapeFieldName") )
+                {
+                    char* pszUnescaped = CPLUnescapeString(
+                    psNode->psChild->pszValue, NULL, CPLES_XML);
+                    m_strShapeFieldName = pszUnescaped;
+                    CPLFree(pszUnescaped);
+                }
+                else if (EQUAL(psNode->pszValue,"Fields") )
+                {
+                    if (!GDBToOGRFields(psNode))
+                    {
+                        abort = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (m_strShapeFieldName.empty())
+            m_pFeatureDefn->SetGeomType(wkbNone);
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "%s",
+                ("Failed parsing GDB Table Schema XML (DataElement) for " + m_strName).c_str());
+        return false;
+    }
+    CPLDestroyXMLNode( psRoot );
+
+    if( m_pFeatureDefn->GetGeomFieldCount() != 0 )
+    {
+        m_pFeatureDefn->GetGeomFieldDefn(0)->SetName(m_strShapeFieldName.c_str());
+        m_pFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_pSRS);
+    }
+
+    if (abort)
+        return false;
+
+    return true; //AOToOGRFields(ipFields, m_pFeatureDefn, m_vOGRFieldToESRIField);
+}
+
+/************************************************************************/
+/*                          ParseGeometryDef()                          */
+/************************************************************************/
+
+bool FGdbLayer::ParseGeometryDef(CPLXMLNode* psRoot)
+{
+    CPLXMLNode *psGeometryDefItem;
+
+    string geometryType;
+    bool hasZ = false, hasM = false;
+    string wkt, wkid, latestwkid;
+
+    for (psGeometryDefItem = psRoot->psChild;
+        psGeometryDefItem != NULL;
+        psGeometryDefItem = psGeometryDefItem->psNext )
+    {
+        //loop through all "GeometryDef" elements
+        //
+
+        if (psGeometryDefItem->eType == CXT_Element &&
+            psGeometryDefItem->psChild != NULL)
+        {
+            if (EQUAL(psGeometryDefItem->pszValue,"GeometryType"))
+            {
+                char* pszUnescaped = CPLUnescapeString(
+                    psGeometryDefItem->psChild->pszValue, NULL, CPLES_XML);
+
+                geometryType = pszUnescaped;
+
+                CPLFree(pszUnescaped);
+            }
+            else if (EQUAL(psGeometryDefItem->pszValue,"SpatialReference"))
+            {
+                ParseSpatialReference(psGeometryDefItem, &wkt, &wkid, &latestwkid); // we don't check for success because it
+                                                                // may not be there
+            }
+            else if (EQUAL(psGeometryDefItem->pszValue,"HasM"))
+            {
+                char* pszUnescaped = CPLUnescapeString(psGeometryDefItem->psChild->pszValue, NULL, CPLES_XML);
+
+                if (!strcmp(pszUnescaped, "true"))
+                    hasM = true;
+
+                CPLFree(pszUnescaped);
+            }
+            else if (EQUAL(psGeometryDefItem->pszValue,"HasZ"))
+            {
+                char* pszUnescaped = CPLUnescapeString(
+                    psGeometryDefItem->psChild->pszValue, NULL, CPLES_XML);
+
+                if (!strcmp(pszUnescaped, "true"))
+                hasZ = true;
+
+                CPLFree(pszUnescaped);
+            }
+        }
+    }
+
+    OGRwkbGeometryType ogrGeoType;
+    if (!GDBToOGRGeometry(geometryType, hasZ, hasM, &ogrGeoType))
+        return false;
+
+    m_pFeatureDefn->SetGeomType(ogrGeoType);
+
+    if (wkbFlatten(ogrGeoType) == wkbMultiLineString ||
+        wkbFlatten(ogrGeoType) == wkbMultiPoint)
+        m_forceMulti = true;
+
+    if (latestwkid.length() > 0 || wkid.length() > 0)
+    {
+        int bSuccess = FALSE;
+        m_pSRS = new OGRSpatialReference();
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        if( latestwkid.length() > 0 )
+        {
+            if( m_pSRS->importFromEPSG(atoi(latestwkid.c_str())) == OGRERR_NONE )
+            {
+                bSuccess = TRUE;
+            }
+            else
+            {
+                CPLDebug("FGDB", "Cannot import SRID %s", latestwkid.c_str());
+            }
+        }
+        if( !bSuccess && wkid.length() > 0 )
+        {
+            if( m_pSRS->importFromEPSG(atoi(wkid.c_str())) == OGRERR_NONE )
+            {
+                bSuccess = TRUE;
+            }
+            else
+            {
+                CPLDebug("FGDB", "Cannot import SRID %s", wkid.c_str());
+            }
+        }
+        CPLPopErrorHandler();
+        CPLErrorReset();
+        if( !bSuccess )
+        {
+            delete m_pSRS;
+            m_pSRS = NULL;
+        }
+        else
+            return true;
+    }
+
+    if (wkt.length() > 0)
+    {
+        if (!GDBToOGRSpatialReference(wkt, &m_pSRS))
+        {
+            //report error, but be passive about it
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Failed Mapping ESRI Spatial Reference");
+        }
+    }
+    else
+    {
+        //report error, but be passive about it
+        CPLError( CE_Warning, CPLE_AppDefined, "Empty Spatial Reference");
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                        ParseSpatialReference()                       */
+/************************************************************************/
+
+bool FGdbLayer::ParseSpatialReference(CPLXMLNode* psSpatialRefNode,
+                                      string* pOutWkt, string* pOutWKID,
+                                      string* pOutLatestWKID)
+{
+    *pOutWkt = "";
+    *pOutWKID = "";
+    *pOutLatestWKID = "";
+
+    CPLXMLNode* psSRItemNode;
+
+    /* Loop through all the SRS elements we want to store */
+    for( psSRItemNode = psSpatialRefNode->psChild;
+         psSRItemNode != NULL;
+         psSRItemNode = psSRItemNode->psNext )
+    {
+        /* The WKID maps (mostly) to an EPSG code */
+        if( psSRItemNode->eType == CXT_Element &&
+            psSRItemNode->psChild != NULL &&
+            EQUAL(psSRItemNode->pszValue,"WKID") )
+        {
+            char* pszUnescaped = CPLUnescapeString(psSRItemNode->psChild->pszValue, NULL, CPLES_XML);
+            *pOutWKID = pszUnescaped;
+            CPLFree(pszUnescaped);
+
+            // Needed with FileGDB v1.4 with layers with empty SRS
+            if( *pOutWKID == "0" )
+                *pOutWKID = "";
+        }
+        /* The concept of LatestWKID is explained in http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r3000000n1000000 */
+        else if( psSRItemNode->eType == CXT_Element &&
+            psSRItemNode->psChild != NULL &&
+            EQUAL(psSRItemNode->pszValue,"LatestWKID") )
+        {
+            char* pszUnescaped = CPLUnescapeString(psSRItemNode->psChild->pszValue, NULL, CPLES_XML);
+            *pOutLatestWKID = pszUnescaped;
+            CPLFree(pszUnescaped);
+        }
+        /* The WKT well-known text can be converted by OGR */
+        else if( psSRItemNode->eType == CXT_Element &&
+                psSRItemNode->psChild != NULL &&
+                EQUAL(psSRItemNode->pszValue,"WKT") )
+        {
+            char* pszUnescaped = CPLUnescapeString(psSRItemNode->psChild->pszValue, NULL, CPLES_XML);
+            *pOutWkt = pszUnescaped;
+            CPLFree(pszUnescaped);
+        }
+    }
+    return *pOutWkt != "" || *pOutWKID != "";
+}
+
+/************************************************************************/
+/*                          GDBToOGRFields()                           */
+/************************************************************************/
+
+bool FGdbLayer::GDBToOGRFields(CPLXMLNode* psRoot)
+{
+    m_vOGRFieldToESRIField.clear();
+
+    if (psRoot->psChild == NULL || psRoot->psChild->psNext == NULL)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Unrecognized GDB XML Schema");
+
+        return false;
+    }
+
+    psRoot = psRoot->psChild->psNext; //change root to "FieldArray"
+
+    //CPLAssert(ogrToESRIFieldMapping.size() == pOGRFeatureDef->GetFieldCount());
+
+    CPLXMLNode* psFieldNode;
+    int bShouldQueryOpenFileGDB = FALSE;
+
+    for( psFieldNode = psRoot->psChild;
+        psFieldNode != NULL;
+        psFieldNode = psFieldNode->psNext )
+    {
+        //loop through all "Field" elements
+        //
+
+        if( psFieldNode->eType == CXT_Element && psFieldNode->psChild != NULL &&
+            EQUAL(psFieldNode->pszValue,"Field"))
+        {
+
+            CPLXMLNode* psFieldItemNode;
+            std::string fieldName;
+            std::string fieldType;
+            int nLength = 0;
+            //int nPrecision = 0;
+            int bNullable = TRUE;
+            std::string osDefault;
+
+            // loop through all items in Field element
+            //
+
+            for( psFieldItemNode = psFieldNode->psChild;
+                psFieldItemNode != NULL;
+                psFieldItemNode = psFieldItemNode->psNext )
+            {
+                if (psFieldItemNode->eType == CXT_Element)
+                {
+                    if (EQUAL(psFieldItemNode->pszValue,"Name"))
+                    {
+                        char* pszUnescaped = CPLUnescapeString(
+                            psFieldItemNode->psChild->pszValue, NULL, CPLES_XML);
+                        fieldName = pszUnescaped;
+                        CPLFree(pszUnescaped);
+                    }
+                    else if (EQUAL(psFieldItemNode->pszValue,"Type") )
+                    {
+                        char* pszUnescaped = CPLUnescapeString(
+                            psFieldItemNode->psChild->pszValue, NULL, CPLES_XML);
+                        fieldType = pszUnescaped;
+                        CPLFree(pszUnescaped);
+                    }
+                    else if (EQUAL(psFieldItemNode->pszValue,"GeometryDef") )
+                    {
+                        if (!ParseGeometryDef(psFieldItemNode))
+                            return false; // if we failed parsing the GeometryDef, we are done!
+                    }
+                    else if (EQUAL(psFieldItemNode->pszValue,"Length") )
+                    {
+                        nLength = atoi(psFieldItemNode->psChild->pszValue);
+                    }
+                    else if (EQUAL(psFieldItemNode->pszValue,"Precision") )
+                    {
+                        //nPrecision = atoi(psFieldItemNode->psChild->pszValue);
+                    }
+                    else if (EQUAL(psFieldItemNode->pszValue,"IsNullable") )
+                    {
+                        bNullable = EQUAL(psFieldItemNode->psChild->pszValue, "true");
+                    }
+                    else if (EQUAL(psFieldItemNode->pszValue,"DefaultValue"))
+                    {
+                        osDefault = CPLGetXMLValue(psFieldItemNode, NULL, "");
+                    }
+                }
+            }
+
+            ///////////////////////////////////////////////////////////////////
+            // At this point we have parsed everything about the current field
+
+            if (fieldType == "esriFieldTypeGeometry")
+            {
+                m_strShapeFieldName = fieldName;
+                m_pFeatureDefn->GetGeomFieldDefn(0)->SetNullable(bNullable);
+
+                continue; // finish here for special field - don't add as OGR fielddef
+            }
+            else if (fieldType == "esriFieldTypeOID")
+            {
+                //m_strOIDFieldName = fieldName; // already set by this point
+
+                continue; // finish here for special field - don't add as OGR fielddef
+            }
+
+            OGRFieldType ogrType;
+            OGRFieldSubType eSubType;
+            //CPLDebug("FGDB", "name = %s, type = %s", fieldName.c_str(), fieldType.c_str() );
+            if (!GDBToOGRFieldType(fieldType, &ogrType, &eSubType))
+            {
+                // field cannot be mapped, skipping further processing
+                CPLError( CE_Warning, CPLE_AppDefined, "Skipping field: [%s] type: [%s] ",
+                fieldName.c_str(), fieldType.c_str() );
+                continue;
+            }
+
+            //TODO: Optimization - modify m_wstrSubFields so it only fetches fields that are mapped
+
+            OGRFieldDefn fieldTemplate( fieldName.c_str(), ogrType);
+            fieldTemplate.SetSubType(eSubType);
+            /* On creation (GDBFieldTypeToWidthPrecision) if string width is 0, we pick up */
+            /* 65535 by default to mean unlimited string length, but we don't want */
+            /* to advertize such a big number */
+            if( ogrType == OFTString && nLength < 65535 )
+                fieldTemplate.SetWidth(nLength);
+            //fieldTemplate.SetPrecision(nPrecision);
+            fieldTemplate.SetNullable(bNullable);
+            if( !osDefault.empty() )
+            {
+                if( ogrType == OFTString )
+                {
+                    char* pszTmp = CPLEscapeString(osDefault.c_str(), -1, CPLES_SQL);
+                    osDefault = "'";
+                    osDefault += pszTmp;
+                    CPLFree(pszTmp);
+                    osDefault += "'";
+                    fieldTemplate.SetDefault(osDefault.c_str());
+                }
+                else if( ogrType == OFTInteger ||
+                         ogrType == OFTReal )
+                {
+#ifdef unreliable
+                    /* Disabling this as GDBs and the FileGDB SDK aren't reliable for numeric values */
+                    /* It often occurs that the XML definition in a00000004.gdbtable doesn't */
+                    /* match the default values (in binary) found in the field definition */
+                    /* section of the .gdbtable of the layers themselves */
+                    /* The Table::GetDefinition() API of FileGDB doesn't seem to use the */
+                    /* XML definition, but rather the values found in the field definition */
+                    /* section of the .gdbtable of the layers themselves */
+                    /* It seems that the XML definition in a00000004.gdbtable is authoritative */
+                    /* in ArcGIS, so we're screwed... */
+
+                    fieldTemplate.SetDefault(osDefault.c_str());
+#endif
+                    bShouldQueryOpenFileGDB = TRUE;
+                }
+                else if( ogrType == OFTDateTime )
+                {
+                    int nYear, nMonth, nDay, nHour, nMinute;
+                    float fSecond;
+                    if( sscanf(osDefault.c_str(), "%d-%d-%dT%d:%d:%fZ", &nYear, &nMonth, &nDay,
+                        &nHour, &nMinute, &fSecond) == 6 ||
+                        sscanf(osDefault.c_str(), "'%d-%d-%d %d:%d:%fZ'", &nYear, &nMonth, &nDay,
+                             &nHour, &nMinute, &fSecond) == 6 )
+                    {
+                        fieldTemplate.SetDefault(CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%02d'",
+                               nYear, nMonth, nDay, nHour, nMinute, (int)(fSecond + 0.5)));
+                    }
+                }
+            }
+
+            m_pFeatureDefn->AddFieldDefn( &fieldTemplate );
+
+            m_vOGRFieldToESRIField.push_back(StringToWString(fieldName));
+            m_vOGRFieldToESRIFieldType.push_back( fieldType );
+            if( ogrType == OFTBinary )
+                m_apoByteArrays.push_back(new ByteArray());
+        }
+    }
+
+    /* Using OpenFileGDB to get reliable default values for integer/real fields */
+    if( bShouldQueryOpenFileGDB )
+    {
+        const char* apszDrivers[] = { "OpenFileGDB", NULL };
+        GDALDataset* poDS = (GDALDataset*) GDALOpenEx(m_pDS->GetFSName(),
+                            GDAL_OF_VECTOR, (char**)apszDrivers, NULL, NULL);
+        if( poDS != NULL )
+        {
+            OGRLayer* poLyr = poDS->GetLayerByName(GetName());
+            if( poLyr )
+            {
+                for(int i=0;i<poLyr->GetLayerDefn()->GetFieldCount();i++)
+                {
+                    OGRFieldDefn* poSrcDefn = poLyr->GetLayerDefn()->GetFieldDefn(i);
+                    if( (poSrcDefn->GetType() == OFTInteger || poSrcDefn->GetType() == OFTReal) &&
+                        poSrcDefn->GetDefault() != NULL )
+                    {
+                        int nIdxDst = m_pFeatureDefn->GetFieldIndex(poSrcDefn->GetNameRef());
+                        if( nIdxDst >= 0 )
+                            m_pFeatureDefn->GetFieldDefn(nIdxDst)->SetDefault(poSrcDefn->GetDefault());
+                    }
+                }
+            }
+            GDALClose( poDS );
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void FGdbLayer::ResetReading()
+{
+    long hr;
+
+    if( m_pTable == NULL )
+        return;
+
+    EndBulkLoad();
+
+    if (m_pOGRFilterGeometry && !m_pOGRFilterGeometry->IsEmpty())
+    {
+        // Search spatial
+        // As of beta1, FileGDB only supports bbox searched, if we have GEOS installed,
+        // we can do the rest ourselves.
+
+        OGREnvelope ogrEnv;
+
+        m_pOGRFilterGeometry->getEnvelope(&ogrEnv);
+
+        //spatial query
+        FileGDBAPI::Envelope env(ogrEnv.MinX, ogrEnv.MaxX, ogrEnv.MinY, ogrEnv.MaxY);
+
+        if( FAILED(hr = m_pTable->Search(m_wstrSubfields, m_wstrWhereClause, env, true, *m_pEnumRows)) )
+            GDBErr(hr, "Failed Searching");
+
+        m_bFilterDirty = false;
+
+        return;
+    }
+
+    // Search non-spatial
+
+    if( FAILED(hr = m_pTable->Search(m_wstrSubfields, m_wstrWhereClause, true, *m_pEnumRows)) )
+        GDBErr(hr, "Failed Searching");
+
+    m_bFilterDirty = false;
+}
+
+/************************************************************************/
+/*                         SetSpatialFilter()                           */
+/************************************************************************/
+
+void FGdbLayer::SetSpatialFilter( OGRGeometry* pOGRGeom )
+{
+    if( !InstallFilter(pOGRGeom) )
+        return;
+
+    if (m_pOGRFilterGeometry)
+    {
+        OGRGeometryFactory::destroyGeometry(m_pOGRFilterGeometry);
+        m_pOGRFilterGeometry = NULL;
+    }
+
+    if (pOGRGeom == NULL || pOGRGeom->IsEmpty())
+    {
+        m_bFilterDirty = true;
+
+        return;
+    }
+
+    m_pOGRFilterGeometry = pOGRGeom->clone();
+
+    m_pOGRFilterGeometry->transformTo(m_pSRS);
+
+    m_bFilterDirty = true;
+}
+
+/************************************************************************/
+/*                             ResyncIDs()                              */
+/************************************************************************/
+
+void  FGdbLayer::ResyncIDs()
+{
+    if( m_oMapOGRFIDToFGDBFID.empty() )
+        return;
+    if( m_pDS->Close() )
+        m_pDS->ReOpen();
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr FGdbLayer::SetAttributeFilter( const char* pszQuery )
+{
+    if( pszQuery != NULL && CPLString(pszQuery).ifind(GetFIDColumn()) != std::string::npos )
+        ResyncIDs();
+
+    m_wstrWhereClause = StringToWString( (pszQuery != NULL) ? pszQuery : "" );
+
+    m_bFilterDirty = true;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           OGRFeatureFromGdbRow()                      */
+/************************************************************************/
+
+bool FGdbBaseLayer::OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature)
+{
+    long hr;
+
+    OGRFeature* pOutFeature = new OGRFeature(m_pFeatureDefn);
+
+    /////////////////////////////////////////////////////////
+    // Translate OID
+    //
+
+    int32 oid = -1;
+    if (FAILED(hr = pRow->GetOID(oid)))
+    {
+        //this should never happen
+        delete pOutFeature;
+        return false;
+    }
+    pOutFeature->SetFID(oid);
+
+    /////////////////////////////////////////////////////////
+    // Translate Geometry
+    //
+
+    ShapeBuffer gdbGeometry;
+    // Row::GetGeometry() will fail with -2147467259 for NULL geometries
+    // Row::GetGeometry() will fail with -2147219885 for tables without a geometry field
+    if (!m_pFeatureDefn->IsGeometryIgnored() &&
+        !FAILED(hr = pRow->GetGeometry(gdbGeometry)))
+    {
+        OGRGeometry* pOGRGeo = NULL;
+
+        if ((!GDBGeometryToOGRGeometry(m_forceMulti, &gdbGeometry, m_pSRS, &pOGRGeo)))
+        {
+            delete pOutFeature;
+            return GDBErr(hr, "Failed to translate FileGDB Geometry to OGR Geometry for row " + string(CPLSPrintf("%d", (int)oid)));
+        }
+
+        pOutFeature->SetGeometryDirectly(pOGRGeo);
+    }
+
+    //////////////////////////////////////////////////////////
+    // Map fields
+    //
+
+    int mappedFieldCount = static_cast<int>(m_vOGRFieldToESRIField.size());
+
+    bool foundBadColumn = false;
+
+    for (int i = 0; i < mappedFieldCount; ++i)
+    {
+        OGRFieldDefn* poFieldDefn = m_pFeatureDefn->GetFieldDefn(i);
+        // The IsNull() and GetXXX() API are very slow when there are a
+        // big number of fields, for example with Tiger database.
+        if (poFieldDefn->IsIgnored() )
+            continue;
+
+        const wstring & wstrFieldName = m_vOGRFieldToESRIField[i];
+        const std::string & strFieldType = m_vOGRFieldToESRIFieldType[i];
+
+        bool isNull = false;
+
+        if (FAILED(hr = pRow->IsNull(wstrFieldName, isNull)))
+        {
+            GDBErr(hr, "Failed to determine NULL status from column " +
+                   WStringToString(wstrFieldName));
+            foundBadColumn = true;
+            continue;
+        }
+
+        if (isNull)
+        {
+            pOutFeature->SetFieldNull(i);
+            continue;
+        }
+
+        //
+        // NOTE: This switch statement needs to be kept in sync with GDBToOGRFieldType utility function
+        //       since we are only checking for types we mapped in that utility function
+
+        switch (poFieldDefn->GetType())
+        {
+
+            case OFTInteger:
+            {
+                int32 val;
+
+                if (FAILED(hr = pRow->GetInteger(wstrFieldName, val)))
+                {
+                    int16 shortval;
+                    if (FAILED(hr = pRow->GetShort(wstrFieldName, shortval)))
+                    {
+                        GDBErr(hr, "Failed to determine integer value for column " +
+                               WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+                    val = shortval;
+                }
+
+                pOutFeature->SetField(i, (int)val);
+            }
+            break;
+
+            case OFTReal:
+            {
+                if (strFieldType == "esriFieldTypeSingle")
+                {
+                    float val;
+
+                    if (FAILED(hr = pRow->GetFloat(wstrFieldName, val)))
+                    {
+                        GDBErr(hr, "Failed to determine float value for column " +
+                               WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+
+                    pOutFeature->SetField(i, val);
+                }
+                else
+                {
+                    double val;
+
+                    if (FAILED(hr = pRow->GetDouble(wstrFieldName, val)))
+                    {
+                        GDBErr(hr, "Failed to determine real value for column " +
+                               WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+
+                    pOutFeature->SetField(i, val);
+                }
+            }
+            break;
+            case OFTString:
+            {
+                wstring val;
+                std::string strValue;
+
+                if( strFieldType == "esriFieldTypeGlobalID" )
+                {
+                    Guid guid;
+                    if( FAILED(hr = pRow->GetGlobalID(guid)) ||
+                        FAILED(hr = guid.ToString(val)) )
+                    {
+                        GDBErr(hr, "Failed to determine string value for column " +
+                            WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+                    strValue = WStringToString(val);
+                }
+                else if( strFieldType == "esriFieldTypeGUID" )
+                {
+                    Guid guid;
+                    if( FAILED(hr = pRow->GetGUID(wstrFieldName, guid)) ||
+                        FAILED(hr = guid.ToString(val)) )
+                    {
+                        GDBErr(hr, "Failed to determine string value for column " +
+                            WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+                    strValue = WStringToString(val);
+                }
+                else if( strFieldType == "esriFieldTypeXML" )
+                {
+                    if (FAILED(hr = pRow->GetXML(wstrFieldName, strValue)))
+                    {
+                        GDBErr(hr, "Failed to determine XML value for column " +
+                            WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+                }
+                else
+                {
+                    if (FAILED(hr = pRow->GetString(wstrFieldName, val)))
+                    {
+                        GDBErr(hr, "Failed to determine string value for column " +
+                            WStringToString(wstrFieldName));
+                        foundBadColumn = true;
+                        continue;
+                    }
+                    strValue = WStringToString(val);
+                }
+
+                pOutFeature->SetField(i, strValue.c_str());
+            }
+            break;
+
+            case OFTBinary:
+            {
+                ByteArray binaryBuf;
+
+                if (FAILED(hr = pRow->GetBinary(wstrFieldName, binaryBuf)))
+                    {
+                    GDBErr(hr, "Failed to determine binary value for column " + WStringToString(wstrFieldName));
+                    foundBadColumn = true;
+                    continue;
+                }
+
+                pOutFeature->SetField(i, (int)binaryBuf.inUseLength, (GByte*)binaryBuf.byteArray);
+            }
+            break;
+
+            case OFTDateTime:
+            {
+                struct tm val;
+
+                if (FAILED(hr = pRow->GetDate(wstrFieldName, val)))
+                {
+                    GDBErr(hr, "Failed to determine date value for column " +
+                           WStringToString(wstrFieldName));
+                    foundBadColumn = true;
+                    continue;
+                }
+
+                pOutFeature->SetField(i, val.tm_year + 1900, val.tm_mon + 1,
+                                      val.tm_mday, val.tm_hour, val.tm_min, (float)val.tm_sec);
+            // Examine test data to figure out how to extract that
+            }
+            break;
+
+            default:
+            {
+                if (!m_suppressColumnMappingError)
+                {
+                    foundBadColumn = true;
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                            "Row id: %d col:%d has unhandled col type (%d). Setting to NULL.",
+                            (int)oid, (int)i, m_pFeatureDefn->GetFieldDefn(i)->GetType());
+                }
+            }
+        }
+    }
+
+    if (foundBadColumn)
+        m_suppressColumnMappingError = true;
+
+    *ppFeature = pOutFeature;
+
+    return true;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature* FGdbLayer::GetNextFeature()
+{
+    if (m_bFilterDirty)
+        ResetReading();
+
+    EndBulkLoad();
+
+    OGRFeature* poFeature = FGdbBaseLayer::GetNextFeature();
+    if( poFeature )
+    {
+        std::map<int,int>::iterator oIter = m_oMapFGDBFIDToOGRFID.find((int)poFeature->GetFID());
+        if( oIter != m_oMapFGDBFIDToOGRFID.end() )
+        {
+            poFeature->SetFID(oIter->second);
+        }
+    }
+    return poFeature;
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *FGdbLayer::GetFeature( GIntBig oid )
+{
+    // do query to fetch individual row
+    EnumRows       enumRows;
+    Row            row;
+    if( !CPL_INT64_FITS_ON_INT32(oid) || m_pTable == NULL )
+        return NULL;
+
+    EndBulkLoad();
+
+    int nFID32 = (int)oid;
+    std::map<int,int>::iterator oIter = m_oMapOGRFIDToFGDBFID.find(nFID32);
+    if( oIter != m_oMapOGRFIDToFGDBFID.end() )
+        nFID32 = oIter->second;
+    else if( m_oMapFGDBFIDToOGRFID.find(nFID32) != m_oMapFGDBFIDToOGRFID.end() )
+        return NULL;
+
+    if (GetRow(enumRows, row, nFID32) != OGRERR_NONE)
+        return NULL;
+
+    OGRFeature* pOGRFeature = NULL;
+
+    if (!OGRFeatureFromGdbRow(&row,  &pOGRFeature))
+    {
+        return NULL;
+    }
+    if( pOGRFeature )
+    {
+        pOGRFeature->SetFID(oid);
+    }
+
+    return pOGRFeature;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig FGdbLayer::GetFeatureCount( CPL_UNUSED int bForce )
+{
+    int32          rowCount = 0;
+
+    if( m_pTable == NULL )
+        return 0;
+
+    EndBulkLoad();
+
+    if (m_pOGRFilterGeometry != NULL || !m_wstrWhereClause.empty())
+    {
+        ResetReading();
+        if (m_pEnumRows == NULL)
+            return 0;
+
+        int nFeatures = 0;
+        while( true )
+        {
+            long hr;
+
+            Row row;
+
+            if (FAILED(hr = m_pEnumRows->Next(row)))
+            {
+                GDBErr(hr, "Failed fetching features");
+                return 0;
+            }
+
+            if (hr != S_OK)
+            {
+                break;
+            }
+            nFeatures ++;
+        }
+        ResetReading();
+        return nFeatures;
+    }
+
+    long hr;
+    if (FAILED(hr = m_pTable->GetRowCount(rowCount)))
+    {
+        GDBErr(hr, "Failed counting rows");
+        return 0;
+    }
+
+    return static_cast<int>(rowCount);
+}
+
+/************************************************************************/
+/*                         GetMetadataItem()                            */
+/************************************************************************/
+
+const char* FGdbLayer::GetMetadataItem(const char* pszName, const char* pszDomain)
+{
+    if( pszDomain != NULL && EQUAL(pszDomain, "MAP_OGR_FID_TO_FGDB_FID") )
+    {
+        if( m_oMapOGRFIDToFGDBFID.find(atoi(pszName)) != m_oMapOGRFIDToFGDBFID.end() )
+            return CPLSPrintf("%d", m_oMapOGRFIDToFGDBFID[atoi(pszName)]);
+    }
+    else if( pszDomain != NULL && EQUAL(pszDomain, "MAP_FGDB_FID_TO_OGR_FID") )
+    {
+        if( m_oMapFGDBFIDToOGRFID.find(atoi(pszName)) != m_oMapFGDBFIDToOGRFID.end() )
+            return CPLSPrintf("%d", m_oMapFGDBFIDToOGRFID[atoi(pszName)]);
+    }
+    return OGRLayer::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/************************************************************************/
+
+OGRErr FGdbLayer::GetExtent (OGREnvelope* psExtent, int bForce)
+{
+    if( m_pTable == NULL )
+        return OGRERR_FAILURE;
+
+    if (m_pOGRFilterGeometry != NULL || !m_wstrWhereClause.empty() ||
+        m_strShapeFieldName.empty())
+    {
+        const int nFieldCount = m_pFeatureDefn->GetFieldCount();
+        int* pabSaveFieldIgnored = new int[nFieldCount];
+        for(int i=0;i<nFieldCount;i++)
+        {
+            // cppcheck-suppress uninitdata
+            pabSaveFieldIgnored[i] = m_pFeatureDefn->GetFieldDefn(i)->IsIgnored();
+            m_pFeatureDefn->GetFieldDefn(i)->SetIgnored(TRUE);
+        }
+        OGRErr eErr = OGRLayer::GetExtent(psExtent, bForce);
+        for(int i=0;i<nFieldCount;i++)
+        {
+            m_pFeatureDefn->GetFieldDefn(i)->SetIgnored(pabSaveFieldIgnored[i]);
+        }
+        delete[] pabSaveFieldIgnored;
+        return eErr;
+    }
+
+    long hr;
+    Envelope envelope;
+    if (FAILED(hr = m_pTable->GetExtent(envelope)))
+    {
+        GDBErr(hr, "Failed fetching extent");
+        return OGRERR_FAILURE;
+    }
+
+    psExtent->MinX = envelope.xMin;
+    psExtent->MinY = envelope.yMin;
+    psExtent->MaxX = envelope.xMax;
+    psExtent->MaxY = envelope.yMax;
+
+    if (CPLIsNan(psExtent->MinX) ||
+        CPLIsNan(psExtent->MinY) ||
+        CPLIsNan(psExtent->MaxX) ||
+        CPLIsNan(psExtent->MaxY))
+        return OGRERR_FAILURE;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          StartBulkLoad()                             */
+/************************************************************************/
+
+void FGdbLayer::StartBulkLoad ()
+{
+    if ( ! m_pTable )
+        return;
+
+    if ( m_bBulkLoadInProgress )
+        return;
+
+    m_bBulkLoadInProgress = TRUE;
+    m_pTable->LoadOnlyMode(true);
+    m_pTable->SetWriteLock();
+}
+
+/************************************************************************/
+/*                           EndBulkLoad()                              */
+/************************************************************************/
+
+void FGdbLayer::EndBulkLoad ()
+{
+    if ( ! m_pTable )
+        return;
+
+    if ( ! m_bBulkLoadInProgress )
+        return;
+
+    m_bBulkLoadInProgress = FALSE;
+    m_bBulkLoadAllowed = -1; /* so that the configuration option is read the first time we CreateFeature() again */
+    m_pTable->LoadOnlyMode(false);
+    m_pTable->FreeWriteLock();
+}
+
+/* OGRErr FGdbLayer::StartTransaction ()
+{
+    if ( ! m_pTable )
+        return OGRERR_FAILURE;
+
+    m_pTable->LoadOnlyMode(true);
+    m_pTable->SetWriteLock();
+    return OGRERR_NONE;
+} */
+
+/* OGRErr FGdbLayer::CommitTransaction ()
+{
+    if ( ! m_pTable )
+        return OGRERR_FAILURE;
+
+    m_pTable->LoadOnlyMode(false);
+    m_pTable->FreeWriteLock();
+    return OGRERR_NONE;
+} */
+
+/* OGRErr FGdbLayer::RollbackTransaction ()
+{
+    if ( ! m_pTable )
+        return OGRERR_FAILURE;
+
+    m_pTable->LoadOnlyMode(false);
+    m_pTable->FreeWriteLock();
+    return OGRERR_NONE;
+} */
+
+/************************************************************************/
+/*                           GetLayerXML()                              */
+/* Return XML definition of the Layer as provided by FGDB. Caller must  */
+/* free result.                                                         */
+/* Not currently used by the driver, but can be used by external code   */
+/* for specific purposes.                                               */
+/************************************************************************/
+
+OGRErr FGdbLayer::GetLayerXML (char **ppXml)
+{
+    long hr;
+    std::string xml;
+
+    if( m_pTable == NULL )
+        return OGRERR_FAILURE;
+
+    if ( FAILED(hr = m_pTable->GetDefinition(xml)) )
+    {
+        GDBErr(hr, "Failed fetching XML table definition");
+        return OGRERR_FAILURE;
+    }
+
+    *ppXml = CPLStrdup(xml.c_str());
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           GetLayerMetadataXML()                      */
+/* Return XML metadata for the Layer as provided by FGDB. Caller must  */
+/* free result.                                                         */
+/* Not currently used by the driver, but can be used by external code   */
+/* for specific purposes.                                               */
+/************************************************************************/
+
+OGRErr FGdbLayer::GetLayerMetadataXML (char **ppXml)
+{
+    long hr;
+    std::string xml;
+
+    if( m_pTable == NULL )
+        return OGRERR_FAILURE;
+
+    if ( FAILED(hr = m_pTable->GetDocumentation(xml)) )
+    {
+        GDBErr(hr, "Failed fetching XML table metadata");
+        return OGRERR_FAILURE;
+    }
+
+    *ppXml = CPLStrdup(xml.c_str());
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int FGdbLayer::TestCapability( const char* pszCap )
+{
+
+    if (EQUAL(pszCap,OLCRandomRead))
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCFastFeatureCount))
+        return m_pOGRFilterGeometry == NULL && m_wstrWhereClause.empty();
+
+    else if (EQUAL(pszCap,OLCFastSpatialFilter))
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCFastGetExtent))
+        return m_pOGRFilterGeometry == NULL && m_wstrWhereClause.empty();
+
+    else if (EQUAL(pszCap,OLCCreateField)) /* CreateField() */
+        return m_pDS->GetUpdate();
+
+    else if (EQUAL(pszCap,OLCSequentialWrite)) /* ICreateFeature() */
+        return m_pDS->GetUpdate();
+
+    else if (EQUAL(pszCap,OLCStringsAsUTF8)) /* Native UTF16, converted to UTF8 */
+        return TRUE;
+
+    else if (EQUAL(pszCap,OLCReorderFields)) /* TBD ReorderFields() */
+        return m_pDS->GetUpdate();
+
+    else if (EQUAL(pszCap,OLCDeleteFeature)) /* DeleteFeature() */
+        return m_pDS->GetUpdate();
+
+    else if (EQUAL(pszCap,OLCRandomWrite)) /* ISetFeature() */
+        return m_pDS->GetUpdate();
+
+    else if (EQUAL(pszCap,OLCDeleteField)) /* DeleteField() */
+        return m_pDS->GetUpdate();
+
+#ifdef AlterFieldDefn_implemented_but_not_working
+    else if (EQUAL(pszCap,OLCAlterFieldDefn)) /* AlterFieldDefn() */
+        return m_pDS->GetUpdate();
+#endif
+
+    else if (EQUAL(pszCap,OLCFastSetNextByIndex)) /* TBD FastSetNextByIndex() */
+        return FALSE;
+
+    else if (EQUAL(pszCap,OLCTransactions)) /* TBD Start/End Transactions() */
+        return FALSE;
+
+    else if( EQUAL(pszCap,OLCIgnoreFields) )
+        return TRUE;
+
+    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
+        return TRUE;
+
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                           CreateRealCopy()                           */
+/************************************************************************/
+
+int FGdbLayer::CreateRealCopy()
+{
+    CPLAssert( m_bSymlinkFlag );
+
+    // Find the FID of the layer in the system catalog
+    char* apszDrivers[2] = { NULL };
+    apszDrivers[0] = (char*) "OpenFileGDB";
+    apszDrivers[1] = NULL;
+    const char* pszSystemCatalog
+        = CPLFormFilename(m_pDS->GetFSName(), "a00000001.gdbtable", NULL);
+    GDALDataset* poOpenFileGDBDS = (GDALDataset*)
+        GDALOpenEx(pszSystemCatalog, GDAL_OF_VECTOR,
+                    apszDrivers, NULL, NULL);
+    if( poOpenFileGDBDS == NULL || poOpenFileGDBDS->GetLayer(0) == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Cannot open %s with OpenFileGDB driver. Should not happen.",
+                  pszSystemCatalog);
+        GDALClose(poOpenFileGDBDS);
+        return FALSE;
+    }
+
+    OGRLayer* poLayer = poOpenFileGDBDS->GetLayer(0);
+    CPLString osFilter = "name = '";
+    osFilter += GetName();
+    osFilter += "'";
+    poLayer->SetAttributeFilter(osFilter);
+    poLayer->ResetReading();
+    OGRFeature* poF = poLayer->GetNextFeature();
+    if( poF == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Cannot find filename for layer %s",
+                  GetName());
+        GDALClose(poOpenFileGDBDS);
+        return FALSE;
+    }
+    int nLayerFID = (int)poF->GetFID();
+    delete poF;
+    GDALClose(poOpenFileGDBDS);
+
+    if( !m_pDS->Close(TRUE) )
+        return FALSE;
+
+    // Create real copies (in .tmp files now) instead of symlinks
+    char** papszFiles = VSIReadDir(m_pDS->GetFSName());
+    CPLString osBasename(CPLSPrintf("a%08x", nLayerFID));
+    int bError = FALSE;
+    std::vector<CPLString> aoFiles;
+    for(char** papszIter = papszFiles; !bError && papszIter && *papszIter; papszIter++)
+    {
+        if( strncmp(*papszIter, osBasename.c_str(), osBasename.size()) == 0 )
+        {
+            if(CPLCopyFile( CPLFormFilename(m_pDS->GetFSName(), *papszIter, "tmp"),
+                            CPLFormFilename(m_pDS->GetFSName(), *papszIter, NULL) ) != 0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot copy %s", *papszIter);
+                bError = TRUE;
+            }
+            else
+                aoFiles.push_back(*papszIter);
+        }
+    }
+    CSLDestroy(papszFiles);
+
+    // Rename the .tmp into normal filenames
+    for(size_t i=0; !bError && i<aoFiles.size(); i++ )
+    {
+        if( VSIUnlink( CPLFormFilename(m_pDS->GetFSName(), aoFiles[i], NULL) ) != 0 ||
+            VSIRename( CPLFormFilename(m_pDS->GetFSName(), aoFiles[i], "tmp"),
+                       CPLFormFilename(m_pDS->GetFSName(), aoFiles[i], NULL) ) != 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s.tmp", aoFiles[i].c_str());
+            bError = TRUE;
+        }
+    }
+
+    int bRet = !bError && m_pDS->ReOpen();
+    if( bRet )
+        m_bSymlinkFlag = FALSE;
+    return bRet;
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp b/ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp
index cd26dcb..837ea26 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbResultLayer.cpp
@@ -1,164 +1,166 @@
-/******************************************************************************
-*
-* Project:  OpenGIS Simple Features Reference Implementation
-* Purpose:  Implements FileGDB OGR result layer.
-* Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
-*
-******************************************************************************
- * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-* DEALINGS IN THE SOFTWARE.
-****************************************************************************/
-
-#include "ogr_fgdb.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "FGdbUtils.h"
-
-using std::string;
-using std::wstring;
-
-/************************************************************************/
-/*                         FGdbResultLayer()                            */
-/************************************************************************/
-FGdbResultLayer::FGdbResultLayer(FGdbDataSource* pParentDataSource,
-                                 const char* pszSQL,
-                                 EnumRows* pEnumRows)
-{
-    m_pFeatureDefn = new OGRFeatureDefn("result");
-    SetDescription( m_pFeatureDefn->GetName() );
-    m_pFeatureDefn->Reference();
-    m_pEnumRows = pEnumRows;
-    m_pDS = pParentDataSource;
-    osSQL = pszSQL;
-
-    m_suppressColumnMappingError = false;
-
-    FieldInfo fieldInfo;
-    m_pEnumRows->GetFieldInformation(fieldInfo);
-
-    int fieldCount;
-    fieldInfo.GetFieldCount(fieldCount);
-    for (int i = 0; i < fieldCount; i++)
-    {
-        FieldType fieldType;
-        string    strFieldType;
-        wstring   fieldName;
-        fieldInfo.GetFieldType(i, fieldType);
-        fieldInfo.GetFieldName(i, fieldName);
-
-        OGRFieldType eType = OFTString;
-        int bSkip = FALSE;
-
-        switch(fieldType)
-        {
-            case fieldTypeSmallInteger:
-            case fieldTypeInteger:
-                eType = OFTInteger;
-                break;
-
-            case fieldTypeSingle:
-                eType = OFTReal;
-                strFieldType = "esriFieldTypeSingle";
-                break;
-
-            case fieldTypeDouble:
-                eType = OFTReal;
-                break;
-
-            case fieldTypeString:
-                eType = OFTString;
-                break;
-
-            case fieldTypeDate:
-                eType = OFTDateTime;
-                break;
-
-            case fieldTypeOID:
-                bSkip = TRUE;
-                break;
-
-            case fieldTypeGeometry:
-                bSkip = TRUE;
-                break;
-
-            case fieldTypeBlob:
-                eType = OFTBinary;
-                break;
-
-            case fieldTypeRaster:
-                bSkip = TRUE;
-                break;
-
-            case fieldTypeGUID:
-                break;
-
-            case fieldTypeGlobalID:
-                break;
-
-            case fieldTypeXML:
-                break;
-
-            default:
-                CPLAssert(FALSE);
-                break;
-        }
-
-        if (!bSkip)
-        {
-            OGRFieldDefn oFieldDefn(WStringToString(fieldName).c_str(), eType);
-            m_pFeatureDefn->AddFieldDefn(&oFieldDefn);
-
-            m_vOGRFieldToESRIField.push_back(fieldName);
-            m_vOGRFieldToESRIFieldType.push_back( strFieldType );
-        }
-    }
-}
-
-/************************************************************************/
-/*                         ~FGdbResultLayer()                           */
-/************************************************************************/
-
-FGdbResultLayer::~FGdbResultLayer()
-{
-}
-
-/************************************************************************/
-/*                            ResetReading()                            */
-/************************************************************************/
-
-void FGdbResultLayer::ResetReading()
-{
-    m_pEnumRows->Close();
-    long hr;
-    if (FAILED(hr = m_pDS->GetGDB()->ExecuteSQL(
-                                    StringToWString(osSQL), true, *m_pEnumRows)))
-    {
-        GDBErr(hr, CPLSPrintf("Failed at executing '%s'", osSQL.c_str()));
-    }
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int FGdbResultLayer::TestCapability( const char * )
-{
-    return FALSE;
-}
+/******************************************************************************
+*
+* Project:  OpenGIS Simple Features Reference Implementation
+* Purpose:  Implements FileGDB OGR result layer.
+* Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+*
+******************************************************************************
+ * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+****************************************************************************/
+
+#include "ogr_fgdb.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "FGdbUtils.h"
+
+CPL_CVSID("$Id: FGdbResultLayer.cpp 35219 2016-08-27 22:39:24Z goatbar $");
+
+using std::string;
+using std::wstring;
+
+/************************************************************************/
+/*                         FGdbResultLayer()                            */
+/************************************************************************/
+FGdbResultLayer::FGdbResultLayer(FGdbDataSource* pParentDataSource,
+                                 const char* pszSQL,
+                                 EnumRows* pEnumRows)
+{
+    m_pFeatureDefn = new OGRFeatureDefn("result");
+    SetDescription( m_pFeatureDefn->GetName() );
+    m_pFeatureDefn->Reference();
+    m_pEnumRows = pEnumRows;
+    m_pDS = pParentDataSource;
+    osSQL = pszSQL;
+
+    m_suppressColumnMappingError = false;
+
+    FieldInfo fieldInfo;
+    m_pEnumRows->GetFieldInformation(fieldInfo);
+
+    int fieldCount;
+    fieldInfo.GetFieldCount(fieldCount);
+    for (int i = 0; i < fieldCount; i++)
+    {
+        FieldType fieldType;
+        string    strFieldType;
+        wstring   fieldName;
+        fieldInfo.GetFieldType(i, fieldType);
+        fieldInfo.GetFieldName(i, fieldName);
+
+        OGRFieldType eType = OFTString;
+        int bSkip = FALSE;
+
+        switch(fieldType)
+        {
+            case fieldTypeSmallInteger:
+            case fieldTypeInteger:
+                eType = OFTInteger;
+                break;
+
+            case fieldTypeSingle:
+                eType = OFTReal;
+                strFieldType = "esriFieldTypeSingle";
+                break;
+
+            case fieldTypeDouble:
+                eType = OFTReal;
+                break;
+
+            case fieldTypeString:
+                eType = OFTString;
+                break;
+
+            case fieldTypeDate:
+                eType = OFTDateTime;
+                break;
+
+            case fieldTypeOID:
+                bSkip = TRUE;
+                break;
+
+            case fieldTypeGeometry:
+                bSkip = TRUE;
+                break;
+
+            case fieldTypeBlob:
+                eType = OFTBinary;
+                break;
+
+            case fieldTypeRaster:
+                bSkip = TRUE;
+                break;
+
+            case fieldTypeGUID:
+                break;
+
+            case fieldTypeGlobalID:
+                break;
+
+            case fieldTypeXML:
+                break;
+
+            default:
+                CPLAssert(false);
+                break;
+        }
+
+        if (!bSkip)
+        {
+            OGRFieldDefn oFieldDefn(WStringToString(fieldName).c_str(), eType);
+            m_pFeatureDefn->AddFieldDefn(&oFieldDefn);
+
+            m_vOGRFieldToESRIField.push_back(fieldName);
+            m_vOGRFieldToESRIFieldType.push_back( strFieldType );
+        }
+    }
+}
+
+/************************************************************************/
+/*                         ~FGdbResultLayer()                           */
+/************************************************************************/
+
+FGdbResultLayer::~FGdbResultLayer()
+{
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void FGdbResultLayer::ResetReading()
+{
+    m_pEnumRows->Close();
+    long hr;
+    if (FAILED(hr = m_pDS->GetGDB()->ExecuteSQL(
+                                    StringToWString(osSQL), true, *m_pEnumRows)))
+    {
+        GDBErr(hr, CPLSPrintf("Failed at executing '%s'", osSQL.c_str()));
+    }
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int FGdbResultLayer::TestCapability( const char * )
+{
+    return FALSE;
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp b/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
index c2028bc..7c196b5 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
+++ b/ogr/ogrsf_frmts/filegdb/FGdbUtils.cpp
@@ -1,594 +1,613 @@
-/******************************************************************************
-* $Id: FGdbUtils.cpp 33563 2016-02-26 14:57:06Z rouault $
-*
-* Project:  OpenGIS Simple Features Reference Implementation
-* Purpose:  Different utility functions used in FileGDB OGR driver.
-* Author:   Ragi Yaser Burhum, ragi at burhum.com
-*           Paul Ramsey, pramsey at cleverelephant.ca
-*
-******************************************************************************
-* Copyright (c) 2010, Ragi Yaser Burhum
-* Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
- * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-* DEALINGS IN THE SOFTWARE.
-****************************************************************************/
-
-#include "FGdbUtils.h"
-#include <algorithm>
-
-#include "ogr_api.h"
-#include "ogrpgeogeometry.h"
-
-CPL_CVSID("$Id: FGdbUtils.cpp 33563 2016-02-26 14:57:06Z rouault $");
-
-using std::string;
-
-/*************************************************************************/
-/*                          StringToWString()                            */
-/*************************************************************************/
-
-std::wstring StringToWString(const std::string& utf8string)
-{
-    wchar_t* pszUTF16 = CPLRecodeToWChar( utf8string.c_str(), CPL_ENC_UTF8, CPL_ENC_UCS2);
-    std::wstring utf16string = pszUTF16;
-    CPLFree(pszUTF16);
-    return utf16string;
-}
-
-/*************************************************************************/
-/*                          WStringToString()                            */
-/*************************************************************************/
-
-std::string WStringToString(const std::wstring& utf16string)
-{
-    char* pszUTF8 = CPLRecodeFromWChar( utf16string.c_str(), CPL_ENC_UCS2, CPL_ENC_UTF8 );
-    std::string utf8string = pszUTF8;
-    CPLFree(pszUTF8);
-    return utf8string; 
-}
-
-/*************************************************************************/
-/*                                GDBErr()                               */
-/*************************************************************************/
-
-bool GDBErr(long int hr, std::string desc, CPLErr errType, const char* pszAddMsg)
-{
-    std::wstring fgdb_error_desc_w;
-    fgdbError er;
-    er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w);
-    if ( er == S_OK )
-    {
-        std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
-        CPLError( errType, CPLE_AppDefined,
-                  "%s (%s)%s", desc.c_str(), fgdb_error_desc.c_str(), pszAddMsg);
-    }
-    else
-    {
-        CPLError( errType, CPLE_AppDefined,
-                  "Error (%ld): %s%s", hr, desc.c_str(), pszAddMsg);
-    }
-    // FIXME? EvenR: not sure if ClearErrors() is really necessary, but as it, it causes crashes in case of
-    // repeated errors
-    //FileGDBAPI::ErrorInfo::ClearErrors();
-
-    return false;
-}
-
-/*************************************************************************/
-/*                            GDBDebug()                                 */
-/*************************************************************************/
-
-bool GDBDebug(long int hr, std::string desc)
-{
-    std::wstring fgdb_error_desc_w;
-    fgdbError er;
-    er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w);
-    if ( er == S_OK )
-    {
-        std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
-        CPLDebug("FGDB", "%s (%s)", desc.c_str(), fgdb_error_desc.c_str());
-    }
-    else
-    {
-        CPLDebug("FGDB", "%s", desc.c_str());
-    }
-    // FIXME? EvenR: not sure if ClearErrors() is really necessary, but as it, it causes crashes in case of
-    // repeated errors
-    //FileGDBAPI::ErrorInfo::ClearErrors();
-
-    return false;
-}
-
-/*************************************************************************/
-/*                            GDBToOGRGeometry()                         */
-/*************************************************************************/
-
-bool GDBToOGRGeometry(string geoType, bool hasZ, bool hasM, OGRwkbGeometryType* pOut)
-{
-    if (geoType == "esriGeometryPoint")
-    {
-        *pOut = wkbPoint;
-    }
-    else if (geoType == "esriGeometryMultipoint")
-    {
-        *pOut = wkbMultiPoint;
-    }
-    else if (geoType == "esriGeometryLine")
-    {
-        *pOut = wkbLineString;
-    }
-    else if (geoType == "esriGeometryPolyline")
-    {
-        *pOut = wkbMultiLineString;
-    }
-    else if (geoType == "esriGeometryPolygon" ||
-            geoType == "esriGeometryMultiPatch")
-    {
-        *pOut = wkbMultiPolygon; // no mapping to single polygon
-    }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                "Cannot map esriGeometryType(%s) to OGRwkbGeometryType", geoType.c_str());
-        return false;
-    }
-    if( hasZ )
-        *pOut = wkbSetZ(*pOut);
-    if( hasM )
-        *pOut = wkbSetM(*pOut);
-
-    return true;
-}
-
-/*************************************************************************/
-/*                            OGRGeometryToGDB()                         */
-/*************************************************************************/
-
-bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ, bool *hasM)
-{
-    *hasZ = wkbHasZ(ogrType);
-    *hasM = wkbHasM(ogrType);
-    switch (wkbFlatten(ogrType))
-    {
-        case wkbPoint:
-        {
-            *gdbType = "esriGeometryPoint";
-            break;
-        }
-
-        case wkbMultiPoint:
-        {
-            *gdbType = "esriGeometryMultipoint";
-            break;
-        }
-
-        case wkbLineString:
-        case wkbMultiLineString:
-        {
-            *gdbType = "esriGeometryPolyline";
-            break;
-        }
-
-        case wkbPolygon:
-        case wkbMultiPolygon:
-        {
-            *gdbType = "esriGeometryPolygon";
-            break;
-        }
-        
-        default:
-        {
-            CPLError( CE_Failure, CPLE_AppDefined, "Cannot map OGRwkbGeometryType (%s) to ESRI type",
-                      OGRGeometryTypeToName(ogrType));
-            return false;
-        }
-    }
-    return true;
-}
-
-/*************************************************************************/
-/*                            GDBToOGRFieldType()                        */
-/*************************************************************************/
-
-// We could make this function far more robust by doing automatic coercion of
-// types, and/or skipping fields we do not know. But, for our purposes. this
-// works fine.
-bool GDBToOGRFieldType(std::string gdbType, OGRFieldType* pOut, OGRFieldSubType* pSubType)
-{
-    /*
-    ESRI types
-    esriFieldTypeSmallInteger = 0,
-    esriFieldTypeInteger = 1,
-    esriFieldTypeSingle = 2,
-    esriFieldTypeDouble = 3,
-    esriFieldTypeString = 4,
-    esriFieldTypeDate = 5,
-    esriFieldTypeOID = 6,
-    esriFieldTypeGeometry = 7,
-    esriFieldTypeBlob = 8,
-    esriFieldTypeRaster = 9,
-    esriFieldTypeGUID = 10,
-    esriFieldTypeGlobalID = 11,
-    esriFieldTypeXML = 12
-    */
-
-    //OGR Types
-
-    //            Desc                                 Name                GDB->OGR Mapped By Us?
-    /** Simple 32bit integer *///                   OFTInteger = 0,             YES
-    /** List of 32bit integers *///                 OFTIntegerList = 1,         NO
-    /** Double Precision floating point *///        OFTReal = 2,                YES
-    /** List of doubles *///                        OFTRealList = 3,            NO
-    /** String of ASCII chars *///                  OFTString = 4,              YES
-    /** Array of strings *///                       OFTStringList = 5,          NO
-    /** deprecated *///                             OFTWideString = 6,          NO
-    /** deprecated *///                             OFTWideStringList = 7,      NO
-    /** Raw Binary data *///                        OFTBinary = 8,              YES
-    /** Date *///                                   OFTDate = 9,                NO
-    /** Time *///                                   OFTTime = 10,               NO
-    /** Date and Time *///                          OFTDateTime = 11            YES
-
-    *pSubType = OFSTNone;
-    if (gdbType == "esriFieldTypeSmallInteger" )
-    {
-        *pSubType = OFSTInt16;
-        *pOut = OFTInteger;
-        return true;
-    }
-    else if (gdbType == "esriFieldTypeInteger")
-    {
-        *pOut = OFTInteger;
-        return true;
-    }
-    else if (gdbType == "esriFieldTypeSingle" )
-    {
-        *pSubType = OFSTFloat32;
-        *pOut = OFTReal;
-        return true;
-    }
-    else if (gdbType == "esriFieldTypeDouble")
-    {
-        *pOut = OFTReal;
-        return true;
-    }
-    else if (gdbType == "esriFieldTypeGUID" ||
-        gdbType == "esriFieldTypeGlobalID" ||
-        gdbType == "esriFieldTypeXML" ||
-        gdbType == "esriFieldTypeString")
-    {
-        *pOut = OFTString;
-        return true;
-    }
-    else if (gdbType == "esriFieldTypeDate")
-    {
-        *pOut = OFTDateTime;
-        return true;
-    }
-    else if (gdbType == "esriFieldTypeBlob")
-    {
-        *pOut = OFTBinary;
-        return true;
-    }
-    else
-    {
-        /* Intentionally fail at these
-        esriFieldTypeOID
-        esriFieldTypeGeometry
-        esriFieldTypeRaster
-        */
-        CPLError( CE_Warning, CPLE_AppDefined, "%s", ("Cannot map field " + gdbType).c_str());
-
-        return false;
-    }
-}
-
-/*************************************************************************/
-/*                            OGRToGDBFieldType()                        */
-/*************************************************************************/
-
-bool OGRToGDBFieldType(OGRFieldType ogrType, OGRFieldSubType eSubType, std::string* gdbType)
-{
-    switch(ogrType)
-    {
-        case OFTInteger:
-        {
-            if( eSubType == OFSTInt16 )
-                *gdbType = "esriFieldTypeSmallInteger";
-            else
-                *gdbType = "esriFieldTypeInteger";
-            break;
-        }
-        case OFTReal:
-        case OFTInteger64:
-        {
-             if( eSubType == OFSTFloat32 )
-                *gdbType = "esriFieldTypeSingle";
-            else
-                *gdbType = "esriFieldTypeDouble";
-            break;
-        }
-        case OFTString:
-        {
-            *gdbType = "esriFieldTypeString";
-            break;
-        }
-        case OFTBinary:
-        {
-            *gdbType = "esriFieldTypeBlob";
-            break;
-        }
-        case OFTDate:
-        case OFTDateTime:
-        {
-            *gdbType = "esriFieldTypeDate";
-            break;
-        }
-        default:
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Cannot map OGR field type (%s)",
-                      OGR_GetFieldTypeName(ogrType) );
-            return false;
-        }
-    }
-
-    return true;
-}
-
-/*************************************************************************/
-/*                       GDBFieldTypeToWidthPrecision()                  */
-/*************************************************************************/
-
-bool GDBFieldTypeToWidthPrecision(std::string &gdbType, int *width, int *precision)
-{
-    *precision = 0;
-
-    /* Width (Length in FileGDB terms) based on FileGDB_API/samples/XMLsamples/OneOfEachFieldType.xml */
-    /* Length is in bytes per doc of FileGDB_API/xmlResources/FileGDBAPI.xsd */
-    if(gdbType == "esriFieldTypeSmallInteger" )
-    {
-        *width = 2;
-    }
-    else if(gdbType == "esriFieldTypeInteger" )
-    {
-        *width = 4;
-    }
-    else if(gdbType == "esriFieldTypeSingle" )
-    {
-        *width = 4;
-        *precision = 5; // FIXME ?
-    }
-    else if(gdbType == "esriFieldTypeDouble" )
-    {
-        *width = 8;
-        *precision = 15; // FIXME ?
-    }
-    else if(gdbType == "esriFieldTypeString" ||
-            gdbType == "esriFieldTypeXML")
-    {
-        *width = atoi(CPLGetConfigOption("FGDB_STRING_WIDTH", "65536"));
-    }
-    else if(gdbType == "esriFieldTypeDate" )
-    {
-        *width = 8;
-    }
-    else if(gdbType == "esriFieldTypeOID" )
-    {
-        *width = 4;
-    }
-    else if(gdbType == "esriFieldTypeGUID" )
-    {
-        *width = 16;
-    }
-    else if(gdbType == "esriFieldTypeBlob" )
-    {
-        *width = 0;
-    }
-    else if(gdbType == "esriFieldTypeGlobalID" )
-    {
-        *width = 38;
-    }
-    else
-    {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Cannot map ESRI field type (%s)", gdbType.c_str());
-        return false;
-    }
-
-    return true;
-}
-
-/*************************************************************************/
-/*                       GDBFieldTypeToWidthPrecision()                  */
-/*************************************************************************/
-
-bool GDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeometry,
-                              OGRSpatialReference* pOGRSR, OGRGeometry** ppOutGeometry)
-{
-
-    OGRGeometry* pOGRGeometry = NULL;
-
-    OGRErr eErr = OGRCreateFromShapeBin( pGdbGeometry->shapeBuffer,
-                                &pOGRGeometry,
-                                static_cast<int>(pGdbGeometry->inUseLength));
-
-    //OGRErr eErr = OGRGeometryFactory::createFromWkb(pGdbGeometry->shapeBuffer, pOGRSR, &pOGRGeometry, pGdbGeometry->inUseLength );
-
-    if (eErr != OGRERR_NONE)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, "Failed attempting to import GDB WKB Geometry. OGRGeometryFactory err:%d", eErr);
-        return false;
-    }
-
-    if( pOGRGeometry != NULL )
-    {
-        // force geometries to multi if requested
-
-        // If it is a polygon, force to MultiPolygon since we always produce multipolygons
-        if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbPolygon)
-        {
-            pOGRGeometry = OGRGeometryFactory::forceToMultiPolygon(pOGRGeometry);
-        }
-        else if (forceMulti)
-        {
-            if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbLineString)
-            {
-                pOGRGeometry = OGRGeometryFactory::forceToMultiLineString(pOGRGeometry);
-            }
-            else if (wkbFlatten(pOGRGeometry->getGeometryType()) == wkbPoint)
-            {
-                pOGRGeometry = OGRGeometryFactory::forceToMultiPoint(pOGRGeometry);
-            }
-        }
-
-        if (pOGRGeometry)
-            pOGRGeometry->assignSpatialReference( pOGRSR );
-    }
-
-
-    *ppOutGeometry = pOGRGeometry;
-
-    return true;
-}
-
-/*************************************************************************/
-/*                         GDBToOGRSpatialReference()                    */
-/*************************************************************************/
-
-bool GDBToOGRSpatialReference(const string & wkt, OGRSpatialReference** ppSR)
-{
-    if (wkt.size() <= 0)
-    {
-        CPLError( CE_Warning, CPLE_AppDefined, "ESRI Spatial Reference is NULL");
-        return false;
-    }
-
-    *ppSR = new OGRSpatialReference(wkt.c_str());
-
-    OGRErr result = (*ppSR)->morphFromESRI();
-
-    if (result == OGRERR_NONE)
-    {
-        return true;
-    }
-    else
-    {
-        delete *ppSR;
-        *ppSR = NULL;
-
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Failed morphing from ESRI Geometry: %s", wkt.c_str());
-
-        return false;
-    }
-}
-
-/*************************************************************************/
-/*                           FGDB_CPLAddXMLAttribute()                   */
-/*************************************************************************/
-
-/* Utility method for attributing nodes */
-void FGDB_CPLAddXMLAttribute(CPLXMLNode* node, const char* attrname, const char* attrvalue)
-{
-    if ( !node ) return;
-    CPLCreateXMLNode( CPLCreateXMLNode( node, CXT_Attribute, attrname ), CXT_Text, attrvalue );
-}
-
-/*************************************************************************/
-/*                          FGDBLaunderName()                            */
-/*************************************************************************/
-
-std::string FGDBLaunderName(const std::string name)
-{
-    std::string newName = name;
-
-    if ( newName[0]>='0' && newName[0]<='9' )
-    {
-        newName = "_" + newName;
-    }
-
-    for(size_t i=0; i < newName.size(); i++)
-    {
-        if ( !( newName[i] == '_' ||
-              ( newName[i]>='0' && newName[i]<='9') ||
-              ( newName[i]>='a' && newName[i]<='z') || 
-              ( newName[i]>='A' && newName[i]<='Z') ))
-        {
-            newName[i] = '_';
-        }
-    }
-
-    return newName;
-}
-
-/*************************************************************************/
-/*                     FGDBEscapeUnsupportedPrefixes()                   */
-/*************************************************************************/
-
-std::string FGDBEscapeUnsupportedPrefixes(const std::string className)
-{
-    std::string newName = className;
-    // From ESRI docs
-    // Feature classes starting with these strings are unsupported.
-    static const char* const UNSUPPORTED_PREFIXES[] = {"sde_", "gdb_", "delta_", NULL};
-
-    for (int i = 0; UNSUPPORTED_PREFIXES[i] != NULL; i++)
-    {
-        if (newName.find(UNSUPPORTED_PREFIXES[i]) == 0)
-        {
-            newName = "_" + newName;
-            break;
-        }
-    }
-
-    return newName;
-}
-
-/*************************************************************************/
-/*                        FGDBEscapeReservedKeywords()                   */
-/*************************************************************************/
-
-std::string FGDBEscapeReservedKeywords(const std::string name)
-{
-    std::string newName = name;
-    std::string upperName = name;
-    std::transform(upperName.begin(), upperName.end(), upperName.begin(), ::toupper);
-
-    // From ESRI docs
-    static const char* const RESERVED_WORDS[] = {FGDB_OID_NAME, "ADD", "ALTER", "AND", "AS", "ASC", "BETWEEN",
-                                    "BY", "COLUMN", "CREATE", "DATE", "DELETE", "DESC",
-                                    "DROP", "EXISTS", "FOR", "FROM", "IN", "INSERT", "INTO",
-                                    "IS", "LIKE", "NOT", "NULL", "OR", "ORDER", "SELECT",
-                                    "SET", "TABLE", "UPDATE", "VALUES", "WHERE", NULL};
-
-    // Append an underscore to any FGDB reserved words used as field names
-    // This is the same behaviour ArcCatalog follows.
-    for (int i = 0; RESERVED_WORDS[i] != NULL; i++)
-    {
-        const char* w = RESERVED_WORDS[i];
-        if (upperName == w)
-        {
-            newName += '_';
-            break;
-        }
-    }
-
-    return newName;
-}
+/******************************************************************************
+*
+* Project:  OpenGIS Simple Features Reference Implementation
+* Purpose:  Different utility functions used in FileGDB OGR driver.
+* Author:   Ragi Yaser Burhum, ragi at burhum.com
+*           Paul Ramsey, pramsey at cleverelephant.ca
+*
+******************************************************************************
+* Copyright (c) 2010, Ragi Yaser Burhum
+* Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+****************************************************************************/
+
+#include "FGdbUtils.h"
+#include <algorithm>
+
+#include "ogr_api.h"
+#include "ogrpgeogeometry.h"
+
+CPL_CVSID("$Id: FGdbUtils.cpp 36883 2016-12-15 13:31:12Z rouault $");
+
+using std::string;
+
+/*************************************************************************/
+/*                          StringToWString()                            */
+/*************************************************************************/
+
+std::wstring StringToWString(const std::string& utf8string)
+{
+    wchar_t* pszUTF16 = CPLRecodeToWChar( utf8string.c_str(), CPL_ENC_UTF8, CPL_ENC_UCS2);
+    std::wstring utf16string = pszUTF16;
+    CPLFree(pszUTF16);
+    return utf16string;
+}
+
+/*************************************************************************/
+/*                          WStringToString()                            */
+/*************************************************************************/
+
+std::string WStringToString(const std::wstring& utf16string)
+{
+    char* pszUTF8 = CPLRecodeFromWChar( utf16string.c_str(), CPL_ENC_UCS2, CPL_ENC_UTF8 );
+    std::string utf8string = pszUTF8;
+    CPLFree(pszUTF8);
+    return utf8string;
+}
+
+/*************************************************************************/
+/*                                GDBErr()                               */
+/*************************************************************************/
+
+bool GDBErr(long int hr, std::string desc, CPLErr errType, const char* pszAddMsg)
+{
+    std::wstring fgdb_error_desc_w;
+    fgdbError er;
+    er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w);
+    if ( er == S_OK )
+    {
+        std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
+        CPLError( errType, CPLE_AppDefined,
+                  "%s (%s)%s", desc.c_str(), fgdb_error_desc.c_str(), pszAddMsg);
+    }
+    else
+    {
+        CPLError( errType, CPLE_AppDefined,
+                  "Error (%ld): %s%s", hr, desc.c_str(), pszAddMsg);
+    }
+    // FIXME? EvenR: not sure if ClearErrors() is really necessary, but as it, it causes crashes in case of
+    // repeated errors
+    //FileGDBAPI::ErrorInfo::ClearErrors();
+
+    return false;
+}
+
+/*************************************************************************/
+/*                            GDBDebug()                                 */
+/*************************************************************************/
+
+bool GDBDebug(long int hr, std::string desc)
+{
+    std::wstring fgdb_error_desc_w;
+    fgdbError er;
+    er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w);
+    if ( er == S_OK )
+    {
+        std::string fgdb_error_desc = WStringToString(fgdb_error_desc_w);
+        CPLDebug("FGDB", "%s (%s)", desc.c_str(), fgdb_error_desc.c_str());
+    }
+    else
+    {
+        CPLDebug("FGDB", "%s", desc.c_str());
+    }
+    // FIXME? EvenR: not sure if ClearErrors() is really necessary, but as it, it causes crashes in case of
+    // repeated errors
+    //FileGDBAPI::ErrorInfo::ClearErrors();
+
+    return false;
+}
+
+/*************************************************************************/
+/*                            GDBToOGRGeometry()                         */
+/*************************************************************************/
+
+bool GDBToOGRGeometry(string geoType, bool hasZ, bool hasM, OGRwkbGeometryType* pOut)
+{
+    if (geoType == "esriGeometryPoint")
+    {
+        *pOut = wkbPoint;
+    }
+    else if (geoType == "esriGeometryMultipoint")
+    {
+        *pOut = wkbMultiPoint;
+    }
+    else if (geoType == "esriGeometryLine")
+    {
+        *pOut = wkbLineString;
+    }
+    else if (geoType == "esriGeometryPolyline")
+    {
+        *pOut = wkbMultiLineString;
+    }
+    else if (geoType == "esriGeometryPolygon" ||
+            geoType == "esriGeometryMultiPatch")
+    {
+        *pOut = wkbMultiPolygon; // no mapping to single polygon
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                "Cannot map esriGeometryType(%s) to OGRwkbGeometryType", geoType.c_str());
+        return false;
+    }
+    if( hasZ )
+        *pOut = wkbSetZ(*pOut);
+    if( hasM )
+        *pOut = wkbSetM(*pOut);
+
+    return true;
+}
+
+/*************************************************************************/
+/*                            OGRGeometryToGDB()                         */
+/*************************************************************************/
+
+bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ, bool *hasM)
+{
+    *hasZ = wkbHasZ(ogrType);
+    *hasM = wkbHasM(ogrType);
+    switch (wkbFlatten(ogrType))
+    {
+        case wkbPoint:
+        {
+            *gdbType = "esriGeometryPoint";
+            break;
+        }
+
+        case wkbMultiPoint:
+        {
+            *gdbType = "esriGeometryMultipoint";
+            break;
+        }
+
+        case wkbLineString:
+        case wkbMultiLineString:
+        {
+            *gdbType = "esriGeometryPolyline";
+            break;
+        }
+
+        case wkbPolygon:
+        case wkbMultiPolygon:
+        {
+            *gdbType = "esriGeometryPolygon";
+            break;
+        }
+
+        case wkbTIN:
+        case wkbPolyhedralSurface:
+        {
+            *gdbType = "esriGeometryMultiPatch";
+            break;
+        }
+
+        default:
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Cannot map OGRwkbGeometryType (%s) to ESRI type",
+                      OGRGeometryTypeToName(ogrType));
+            return false;
+        }
+    }
+    return true;
+}
+
+/*************************************************************************/
+/*                            GDBToOGRFieldType()                        */
+/*************************************************************************/
+
+// We could make this function far more robust by doing automatic coercion of
+// types, and/or skipping fields we do not know. But, for our purposes. this
+// works fine.
+bool GDBToOGRFieldType(const std::string& gdbType, OGRFieldType* pOut, OGRFieldSubType* pSubType)
+{
+    /*
+    ESRI types
+    esriFieldTypeSmallInteger = 0,
+    esriFieldTypeInteger = 1,
+    esriFieldTypeSingle = 2,
+    esriFieldTypeDouble = 3,
+    esriFieldTypeString = 4,
+    esriFieldTypeDate = 5,
+    esriFieldTypeOID = 6,
+    esriFieldTypeGeometry = 7,
+    esriFieldTypeBlob = 8,
+    esriFieldTypeRaster = 9,
+    esriFieldTypeGUID = 10,
+    esriFieldTypeGlobalID = 11,
+    esriFieldTypeXML = 12
+    */
+
+    //OGR Types
+
+    //            Desc                                 Name                GDB->OGR Mapped By Us?
+    /** Simple 32bit integer *///                   OFTInteger = 0,             YES
+    /** List of 32bit integers *///                 OFTIntegerList = 1,         NO
+    /** Double Precision floating point *///        OFTReal = 2,                YES
+    /** List of doubles *///                        OFTRealList = 3,            NO
+    /** String of ASCII chars *///                  OFTString = 4,              YES
+    /** Array of strings *///                       OFTStringList = 5,          NO
+    /** deprecated *///                             OFTWideString = 6,          NO
+    /** deprecated *///                             OFTWideStringList = 7,      NO
+    /** Raw Binary data *///                        OFTBinary = 8,              YES
+    /** Date *///                                   OFTDate = 9,                NO
+    /** Time *///                                   OFTTime = 10,               NO
+    /** Date and Time *///                          OFTDateTime = 11            YES
+
+    *pSubType = OFSTNone;
+    if (gdbType == "esriFieldTypeSmallInteger" )
+    {
+        *pSubType = OFSTInt16;
+        *pOut = OFTInteger;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeInteger")
+    {
+        *pOut = OFTInteger;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeSingle" )
+    {
+        *pSubType = OFSTFloat32;
+        *pOut = OFTReal;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeDouble")
+    {
+        *pOut = OFTReal;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeGUID" ||
+        gdbType == "esriFieldTypeGlobalID" ||
+        gdbType == "esriFieldTypeXML" ||
+        gdbType == "esriFieldTypeString")
+    {
+        *pOut = OFTString;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeDate")
+    {
+        *pOut = OFTDateTime;
+        return true;
+    }
+    else if (gdbType == "esriFieldTypeBlob")
+    {
+        *pOut = OFTBinary;
+        return true;
+    }
+    else
+    {
+        /* Intentionally fail at these
+        esriFieldTypeOID
+        esriFieldTypeGeometry
+        esriFieldTypeRaster
+        */
+        CPLError( CE_Warning, CPLE_AppDefined, "%s", ("Cannot map field " + gdbType).c_str());
+
+        return false;
+    }
+}
+
+/*************************************************************************/
+/*                            OGRToGDBFieldType()                        */
+/*************************************************************************/
+
+bool OGRToGDBFieldType(OGRFieldType ogrType, OGRFieldSubType eSubType, std::string* gdbType)
+{
+    switch(ogrType)
+    {
+        case OFTInteger:
+        {
+            if( eSubType == OFSTInt16 )
+                *gdbType = "esriFieldTypeSmallInteger";
+            else
+                *gdbType = "esriFieldTypeInteger";
+            break;
+        }
+        case OFTReal:
+        case OFTInteger64:
+        {
+             if( eSubType == OFSTFloat32 )
+                *gdbType = "esriFieldTypeSingle";
+            else
+                *gdbType = "esriFieldTypeDouble";
+            break;
+        }
+        case OFTString:
+        {
+            *gdbType = "esriFieldTypeString";
+            break;
+        }
+        case OFTBinary:
+        {
+            *gdbType = "esriFieldTypeBlob";
+            break;
+        }
+        case OFTDate:
+        case OFTDateTime:
+        {
+            *gdbType = "esriFieldTypeDate";
+            break;
+        }
+        default:
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Cannot map OGR field type (%s)",
+                      OGR_GetFieldTypeName(ogrType) );
+            return false;
+        }
+    }
+
+    return true;
+}
+
+/*************************************************************************/
+/*                       GDBFieldTypeToWidthPrecision()                  */
+/*************************************************************************/
+
+bool GDBFieldTypeToWidthPrecision(std::string &gdbType, int *width, int *precision)
+{
+    *precision = 0;
+
+    /* Width (Length in FileGDB terms) based on FileGDB_API/samples/XMLsamples/OneOfEachFieldType.xml */
+    /* Length is in bytes per doc of FileGDB_API/xmlResources/FileGDBAPI.xsd */
+    if(gdbType == "esriFieldTypeSmallInteger" )
+    {
+        *width = 2;
+    }
+    else if(gdbType == "esriFieldTypeInteger" )
+    {
+        *width = 4;
+    }
+    else if(gdbType == "esriFieldTypeSingle" )
+    {
+        *width = 4;
+        *precision = 5; // FIXME ?
+    }
+    else if(gdbType == "esriFieldTypeDouble" )
+    {
+        *width = 8;
+        *precision = 15; // FIXME ?
+    }
+    else if(gdbType == "esriFieldTypeString" ||
+            gdbType == "esriFieldTypeXML")
+    {
+        *width = atoi(CPLGetConfigOption("FGDB_STRING_WIDTH", "65536"));
+    }
+    else if(gdbType == "esriFieldTypeDate" )
+    {
+        *width = 8;
+    }
+    else if(gdbType == "esriFieldTypeOID" )
+    {
+        *width = 4;
+    }
+    else if(gdbType == "esriFieldTypeGUID" )
+    {
+        *width = 16;
+    }
+    else if(gdbType == "esriFieldTypeBlob" )
+    {
+        *width = 0;
+    }
+    else if(gdbType == "esriFieldTypeGlobalID" )
+    {
+        *width = 38;
+    }
+    else
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Cannot map ESRI field type (%s)", gdbType.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+/*************************************************************************/
+/*                       GDBFieldTypeToWidthPrecision()                  */
+/*************************************************************************/
+
+bool GDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeometry,
+                              OGRSpatialReference* pOGRSR, OGRGeometry** ppOutGeometry)
+{
+
+    OGRGeometry* pOGRGeometry = NULL;
+
+    OGRErr eErr = OGRCreateFromShapeBin( pGdbGeometry->shapeBuffer,
+                                &pOGRGeometry,
+                                static_cast<int>(pGdbGeometry->inUseLength));
+
+    //OGRErr eErr = OGRGeometryFactory::createFromWkb(pGdbGeometry->shapeBuffer, pOGRSR, &pOGRGeometry, pGdbGeometry->inUseLength );
+
+    if (eErr != OGRERR_NONE)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Failed attempting to import GDB WKB Geometry. OGRGeometryFactory err:%d", eErr);
+        return false;
+    }
+
+    if( pOGRGeometry != NULL )
+    {
+        // force geometries to multi if requested
+
+        // If it is a polygon, force to MultiPolygon since we always produce multipolygons
+        OGRwkbGeometryType eFlattenType = wkbFlatten(pOGRGeometry->getGeometryType());
+        if (eFlattenType == wkbPolygon)
+        {
+            pOGRGeometry = OGRGeometryFactory::forceToMultiPolygon(pOGRGeometry);
+        }
+        else if (eFlattenType == wkbCurvePolygon)
+        {
+            OGRMultiSurface* poMS = new OGRMultiSurface();
+            poMS->addGeometryDirectly( pOGRGeometry );
+            pOGRGeometry = poMS;
+        }
+        else if (forceMulti)
+        {
+            if (eFlattenType == wkbLineString)
+            {
+                pOGRGeometry = OGRGeometryFactory::forceToMultiLineString(pOGRGeometry);
+            }
+            else if (eFlattenType == wkbCompoundCurve)
+            {
+                OGRMultiCurve* poMC = new OGRMultiCurve();
+                poMC->addGeometryDirectly( pOGRGeometry );
+                pOGRGeometry = poMC;
+            }
+            else if (eFlattenType == wkbPoint)
+            {
+                pOGRGeometry = OGRGeometryFactory::forceToMultiPoint(pOGRGeometry);
+            }
+        }
+
+        if (pOGRGeometry)
+            pOGRGeometry->assignSpatialReference( pOGRSR );
+    }
+
+    *ppOutGeometry = pOGRGeometry;
+
+    return true;
+}
+
+/*************************************************************************/
+/*                         GDBToOGRSpatialReference()                    */
+/*************************************************************************/
+
+bool GDBToOGRSpatialReference(const string & wkt, OGRSpatialReference** ppSR)
+{
+    if (wkt.size() <= 0)
+    {
+        CPLError( CE_Warning, CPLE_AppDefined, "ESRI Spatial Reference is NULL");
+        return false;
+    }
+
+    *ppSR = new OGRSpatialReference(wkt.c_str());
+
+    OGRErr result = (*ppSR)->morphFromESRI();
+
+    if (result == OGRERR_NONE)
+    {
+        return true;
+    }
+    else
+    {
+        delete *ppSR;
+        *ppSR = NULL;
+
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Failed morphing from ESRI Geometry: %s", wkt.c_str());
+
+        return false;
+    }
+}
+
+/*************************************************************************/
+/*                           FGDB_CPLAddXMLAttribute()                   */
+/*************************************************************************/
+
+/* Utility method for attributing nodes */
+void FGDB_CPLAddXMLAttribute(CPLXMLNode* node, const char* attrname, const char* attrvalue)
+{
+    if ( !node ) return;
+    CPLCreateXMLNode( CPLCreateXMLNode( node, CXT_Attribute, attrname ), CXT_Text, attrvalue );
+}
+
+/*************************************************************************/
+/*                          FGDBLaunderName()                            */
+/*************************************************************************/
+
+std::string FGDBLaunderName(const std::string& name)
+{
+    std::string newName = name;
+
+    if ( newName[0]>='0' && newName[0]<='9' )
+    {
+        newName = "_" + newName;
+    }
+
+    for(size_t i=0; i < newName.size(); i++)
+    {
+        if ( !( newName[i] == '_' ||
+              ( newName[i]>='0' && newName[i]<='9') ||
+              ( newName[i]>='a' && newName[i]<='z') ||
+              ( newName[i]>='A' && newName[i]<='Z') ))
+        {
+            newName[i] = '_';
+        }
+    }
+
+    return newName;
+}
+
+/*************************************************************************/
+/*                     FGDBEscapeUnsupportedPrefixes()                   */
+/*************************************************************************/
+
+std::string FGDBEscapeUnsupportedPrefixes(const std::string& className)
+{
+    std::string newName = className;
+    // From ESRI docs
+    // Feature classes starting with these strings are unsupported.
+    static const char* const UNSUPPORTED_PREFIXES[] = {"sde_", "gdb_", "delta_", NULL};
+
+    for (int i = 0; UNSUPPORTED_PREFIXES[i] != NULL; i++)
+    {
+        // cppcheck-suppress stlIfStrFind
+        if (newName.find(UNSUPPORTED_PREFIXES[i]) == 0)
+        {
+            newName = "_" + newName;
+            break;
+        }
+    }
+
+    return newName;
+}
+
+/*************************************************************************/
+/*                        FGDBEscapeReservedKeywords()                   */
+/*************************************************************************/
+
+std::string FGDBEscapeReservedKeywords(const std::string& name)
+{
+    std::string newName = name;
+    std::string upperName = name;
+    std::transform(upperName.begin(), upperName.end(), upperName.begin(), ::toupper);
+
+    // From ESRI docs
+    static const char* const RESERVED_WORDS[] = {FGDB_OID_NAME, "ADD", "ALTER", "AND", "AS", "ASC", "BETWEEN",
+                                    "BY", "COLUMN", "CREATE", "DATE", "DELETE", "DESC",
+                                    "DROP", "EXISTS", "FOR", "FROM", "IN", "INSERT", "INTO",
+                                    "IS", "LIKE", "NOT", "NULL", "OR", "ORDER", "SELECT",
+                                    "SET", "TABLE", "UPDATE", "VALUES", "WHERE", NULL};
+
+    // Append an underscore to any FGDB reserved words used as field names
+    // This is the same behaviour ArcCatalog follows.
+    for (int i = 0; RESERVED_WORDS[i] != NULL; i++)
+    {
+        const char* w = RESERVED_WORDS[i];
+        if (upperName == w)
+        {
+            newName += '_';
+            break;
+        }
+    }
+
+    return newName;
+}
diff --git a/ogr/ogrsf_frmts/filegdb/FGdbUtils.h b/ogr/ogrsf_frmts/filegdb/FGdbUtils.h
index e46e6c9..3700b6e 100644
--- a/ogr/ogrsf_frmts/filegdb/FGdbUtils.h
+++ b/ogr/ogrsf_frmts/filegdb/FGdbUtils.h
@@ -1,89 +1,87 @@
-/******************************************************************************
- * $Id: FGdbUtils.h 33563 2016-02-26 14:57:06Z rouault $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Various FileGDB OGR Datasource utility functions
- * Author:   Ragi Yaser Burhum, ragi at burhum.com
- *
- ******************************************************************************
- * Copyright (c) 2010, Ragi Yaser Burhum
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-
-#ifndef FGDB_UTILS_H_INCLUDED
-#define FGDB_UTILS_H_INCLUDED
-
-#include "ogr_fgdb.h"
-#include <iostream>
-#include <string>
-#include "cpl_minixml.h"
-
-std::wstring StringToWString(const std::string& s);
-std::string WStringToString(const std::wstring& s);
-
-//
-// GDB API to OGR Geometry Mapping
-//
-
-// Type mapping
-bool GDBToOGRGeometry(std::string geoType, bool hasZ, bool hasM, OGRwkbGeometryType* pOut);
-bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ, bool *hasM);
-
-
-bool GDBToOGRSpatialReference(const std::string & wkt, OGRSpatialReference** ppSR);
-
-// Feature mapping 
-bool GDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeometry, 
-                              OGRSpatialReference* pOGRSR, OGRGeometry** ppOutGeometry);
-
-//temporary version - until we can parse the full binary format
-bool GhettoGDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeometry, 
-                                    OGRSpatialReference* pOGRSR, OGRGeometry** ppOutGeometry);
-//
-// GDB API to OGR Field Mapping
-//
-bool GDBToOGRFieldType(std::string gdbType, OGRFieldType* ogrType, OGRFieldSubType* pSubType);
-bool OGRToGDBFieldType(OGRFieldType ogrType, OGRFieldSubType eSubType, std::string* gdbType);
-
-//
-// GDB Field Width defaults
-//
-bool GDBFieldTypeToWidthPrecision(std::string &gdbType, int *width, int *precision);
-
-//
-// GDBAPI error to OGR
-//
-bool GDBErr(long hr, std::string desc, CPLErr errType = CE_Failure, const char* pszAddMsg = "");
-bool GDBDebug(long hr, std::string desc);
-
-//
-// Utility for adding attributes to CPL nodes
-//
-void FGDB_CPLAddXMLAttribute(CPLXMLNode* node, const char* attrname, const char* attrvalue);
-
-//
-// Utility for escaping reserved words and cleaning field names
-//
-std::string FGDBLaunderName(const std::string name);
-std::string FGDBEscapeUnsupportedPrefixes(const std::string className);
-std::string FGDBEscapeReservedKeywords(const std::string name);
-
-#endif
+/******************************************************************************
+ * $Id: FGdbUtils.h 36415 2016-11-21 22:40:20Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Various FileGDB OGR Datasource utility functions
+ * Author:   Ragi Yaser Burhum, ragi at burhum.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Ragi Yaser Burhum
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef FGDB_UTILS_H_INCLUDED
+#define FGDB_UTILS_H_INCLUDED
+
+#include "ogr_fgdb.h"
+#include <iostream>
+#include <string>
+#include "cpl_minixml.h"
+
+std::wstring StringToWString(const std::string& s);
+std::string WStringToString(const std::wstring& s);
+
+//
+// GDB API to OGR Geometry Mapping
+//
+
+// Type mapping
+bool GDBToOGRGeometry(std::string geoType, bool hasZ, bool hasM, OGRwkbGeometryType* pOut);
+bool OGRGeometryToGDB(OGRwkbGeometryType ogrType, std::string *gdbType, bool *hasZ, bool *hasM);
+
+bool GDBToOGRSpatialReference(const std::string & wkt, OGRSpatialReference** ppSR);
+
+// Feature mapping
+bool GDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeometry,
+                              OGRSpatialReference* pOGRSR, OGRGeometry** ppOutGeometry);
+
+//temporary version - until we can parse the full binary format
+bool GhettoGDBGeometryToOGRGeometry(bool forceMulti, FileGDBAPI::ShapeBuffer* pGdbGeometry,
+                                    OGRSpatialReference* pOGRSR, OGRGeometry** ppOutGeometry);
+//
+// GDB API to OGR Field Mapping
+//
+bool GDBToOGRFieldType(const std::string& gdbType, OGRFieldType* ogrType, OGRFieldSubType* pSubType);
+bool OGRToGDBFieldType(OGRFieldType ogrType, OGRFieldSubType eSubType, std::string* gdbType);
+
+//
+// GDB Field Width defaults
+//
+bool GDBFieldTypeToWidthPrecision(std::string &gdbType, int *width, int *precision);
+
+//
+// GDBAPI error to OGR
+//
+bool GDBErr(long hr, std::string desc, CPLErr errType = CE_Failure, const char* pszAddMsg = "");
+bool GDBDebug(long hr, std::string desc);
+
+//
+// Utility for adding attributes to CPL nodes
+//
+void FGDB_CPLAddXMLAttribute(CPLXMLNode* node, const char* attrname, const char* attrvalue);
+
+//
+// Utility for escaping reserved words and cleaning field names
+//
+std::string FGDBLaunderName(const std::string& name);
+std::string FGDBEscapeUnsupportedPrefixes(const std::string& className);
+std::string FGDBEscapeReservedKeywords(const std::string& name);
+
+#endif
diff --git a/ogr/ogrsf_frmts/filegdb/GNUmakefile b/ogr/ogrsf_frmts/filegdb/GNUmakefile
index fc5ea9a..bfc1804 100644
--- a/ogr/ogrsf_frmts/filegdb/GNUmakefile
+++ b/ogr/ogrsf_frmts/filegdb/GNUmakefile
@@ -2,7 +2,7 @@
 
 include ../../../GDALmake.opt
 
-OBJ	=	FGdbDatasource.o FGdbDriver.o FGdbLayer.o FGdbUtils.o FGdbResultLayer.o 
+OBJ	=	FGdbDatasource.o FGdbDriver.o FGdbLayer.o FGdbUtils.o FGdbResultLayer.o
 
 CPPFLAGS	:=	-I../generic  $(FGDB_INC) $(CPPFLAGS)
 
diff --git a/ogr/ogrsf_frmts/filegdb/drv_filegdb.html b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
index dab35bd..d522fd9 100644
--- a/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
+++ b/ogr/ogrsf_frmts/filegdb/drv_filegdb.html
@@ -7,7 +7,9 @@
 
 <h1>ESRI File Geodatabase (FileGDB)</h1>
 
-<p>The FileGDB driver provides read and write access to File Geodatabases (.gdb directories) created by ArcGIS 10 and above.</p>
+<p>The FileGDB driver provides read and write access to File Geodatabases
+(.gdb directories) created by ArcGIS 10 and above.  The dataset name must be
+the directory/folder name, and it must end with the .gdb extension.</p>
 
 <p>Note : starting with OGR 1.11, the <a href="drv_openfilegdb.html">OpenFileGDB driver</a> driver exists as an alternative built-in
 i.e. not depending on a third-party library) read-only driver.</p>
@@ -21,6 +23,8 @@ i.e. not depending on a third-party library) read-only driver.</p>
 	</ul>
 </p>
 
+<p>Curve in geometries are supported on reading with GDAL >= 2.2.</p>
+
 <h2>Bulk feature loading (OGR >= 1.9.2)</h2>
 
 The FGDB_BULK_LOAD configuration option can be set to YES to speed-up feature insertion (or sometimes solve problems
@@ -117,11 +121,9 @@ remapping technique to enable the user to create features at the FID of their ch
             This might be the case if messages "FGDB: Error opening XXXXXXX. Skipping it (Invalid function arguments.)"
             when running "ogrinfo --debug on the.gdb" (reported as warning in GDAL 2.0).
             Using the OpenFileGDB driver will generally solve that issue.</li>
-	<li>Blob fields have not been implemented.</li>
 	<li>FGDB coordinate snapping will cause geometries to be altered during writing. Use the origin and scale layer creation options to control the snapping behavior.</li>
 	<li>Driver can't read data  in SDC format (Smart Data Compression) because operation is not supported by the ESRI SDK.</li>
         <li>Reading data compressed in CDF format (Compressed Data Format) requires ESRI SDK 1.4 or later.</li>
-        <li>Curve in geometries are not currently supported.</li>
 </ul>
 
 <h2>Links</h2>
diff --git a/ogr/ogrsf_frmts/filegdb/filegdbsdk_headers.h b/ogr/ogrsf_frmts/filegdb/filegdbsdk_headers.h
index e253638..e374c3c 100644
--- a/ogr/ogrsf_frmts/filegdb/filegdbsdk_headers.h
+++ b/ogr/ogrsf_frmts/filegdb/filegdbsdk_headers.h
@@ -35,6 +35,11 @@
 #pragma GCC system_header
 #endif
 
+// In C++11 mode, GCC no longer defines linux, as expected by the SDK
+#if defined(__linux__) && !defined(linux)
+#define linux
+#endif
+
 /* FGDB API headers */
 #include "FileGDBAPI.h"
 
diff --git a/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
index edd6923..a445121 100644
--- a/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
+++ b/ogr/ogrsf_frmts/filegdb/ogr_fgdb.h
@@ -1,409 +1,401 @@
-/******************************************************************************
-* $Id: ogr_fgdb.h 33138 2016-01-24 11:18:11Z rouault $
-*
-* Project:  OpenGIS Simple Features Reference Implementation
-* Purpose:  Standard includes and class definitions ArcObjects OGR driver.
-* Author:   Ragi Yaser Burhum, ragi at burhum.com
-*
-******************************************************************************
-* Copyright (c) 2009, Ragi Yaser Burhum
- * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-* DEALINGS IN THE SOFTWARE.
-****************************************************************************/
-
-#ifndef OGR_FGDB_H_INCLUDED
-#define OGR_FGDB_H_INCLUDED
-
-#ifdef DEBUG_BOOL
-#define DO_NOT_USE_DEBUG_BOOL
-#endif
-
-#include <vector>
-#include <set>
-#include "ogrsf_frmts.h"
-#include "ogremulatedtransaction.h"
-
-/* GDAL string utilities */
-#include "cpl_string.h"
-
-/* GDAL XML handler */
-#include "cpl_minixml.h"
-
-/* FGDB API headers through our own inclusion file */
-#include "filegdbsdk_headers.h"
-
-/* Workaround needed for Linux, at least for FileGDB API 1.1 (#4455) */
-#if defined(__linux__)
-#define EXTENT_WORKAROUND
-#endif
-
-/************************************************************************
-* Default layer creation options
-*/
-
-#define FGDB_FEATURE_DATASET "";
-#define FGDB_GEOMETRY_NAME "SHAPE"
-#define FGDB_OID_NAME "OBJECTID"
-
-
-/* The ESRI FGDB API namespace */
-using namespace FileGDBAPI;
-
-class FGdbDriver;
-
-/************************************************************************/
-/*                           FGdbBaseLayer                              */
-/************************************************************************/
-
-class FGdbBaseLayer : public OGRLayer
-{
-protected:
-
-  FGdbBaseLayer();
-  virtual ~FGdbBaseLayer();
-
-  OGRFeatureDefn* m_pFeatureDefn;
-  OGRSpatialReference* m_pSRS;
-
-  EnumRows*    m_pEnumRows;
-
-  std::vector<std::wstring> m_vOGRFieldToESRIField; //OGR Field Index to ESRI Field Name Mapping
-  std::vector<std::string> m_vOGRFieldToESRIFieldType; //OGR Field Index to ESRI Field Type Mapping
-
-  bool  m_suppressColumnMappingError;
-  bool  m_forceMulti;
-
-  bool OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature);
-  
-  virtual void       CloseGDBObjects();
-
-public:
-          virtual OGRFeature* GetNextFeature();
-};
-
-/************************************************************************/
-/*                            FGdbLayer                                 */
-/************************************************************************/
-
-class FGdbDataSource;
-
-class FGdbLayer : public FGdbBaseLayer
-{
-  friend class FGdbDataSource;
-
-  int                 m_bBulkLoadAllowed;
-  int                 m_bBulkLoadInProgress;
-
-  virtual void        CloseGDBObjects();
-  int                 EditIndexesForFIDHack(const char* pszRadixTablename);
-  int                 EditGDBTablX(const CPLString& osGDBTablX,
-                                   const CPLString& osNewGDBTablX);
-  int                 EditATXOrSPX(const CPLString& osIndex);
-  int                 EditATXOrSPX( VSILFILE* fp,
-                                    int nThisPage,
-                                    int& nLastPageVisited,
-                                    int nDepth,
-                                    int nSizeIndexedValue,
-                                    GByte* pabyLastIndexedValue,
-                                    int& bIndexedValueIsValid,
-                                    int& nFirstIndexAtThisValue,
-                                    std::vector<int>& anPagesAtThisValue,
-                                    int& bSortThisValue,
-                                    int& bInvalidateIndex );
-
-  void                StartBulkLoad();
-  void                EndBulkLoad();
-
-#ifdef EXTENT_WORKAROUND
-  bool                m_bLayerJustCreated;
-  OGREnvelope         sLayerEnvelope;
-  bool                m_bLayerEnvelopeValid;
-  void                WorkAroundExtentProblem();
-  bool                UpdateRowWithGeometry(Row& row, OGRGeometry* poGeom);
-#endif
-
-  std::vector<ByteArray*> m_apoByteArrays;
-  OGRErr              PopulateRowWithFeature( Row& row, OGRFeature *poFeature );
-  OGRErr              GetRow( EnumRows& enumRows, Row& row, GIntBig nFID );
-
-  char              **m_papszOptions;
-  
-  int                 m_bCreateMultipatch;
-
-  std::map<int,int>   m_oMapOGRFIDToFGDBFID;
-  std::map<int,int>   m_oMapFGDBFIDToOGRFID;
-  int                 m_nResyncThreshold;
-  void                ResyncIDs();
-  
-  int                 m_bSymlinkFlag;
-  int                 CreateRealCopy();
-
-  char*               CreateFieldDefn(OGRFieldDefn& oField,
-                                      int bApproxOK,
-                                      std::string& fieldname_clean,
-                                      std::string& gdbFieldType);
-
-public:
-
-  FGdbLayer();
-  virtual ~FGdbLayer();
-
-  // Internal used by FGDB driver */
-  bool Initialize(FGdbDataSource* pParentDataSource, Table* pTable, std::wstring wstrTablePath, std::wstring wstrType);
-  bool Create(FGdbDataSource* pParentDataSource, const char * pszLayerName, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions);
-  bool CreateFeatureDataset(FGdbDataSource* pParentDataSource, std::string feature_dataset_name, OGRSpatialReference* poSRS, char** papszOptions );
-
-  // virtual const char *GetName();
-  virtual const char* GetFIDColumn() { return m_strOIDFieldName.c_str(); }
-
-  virtual void        ResetReading();
-  virtual OGRFeature* GetNextFeature();
-  virtual OGRFeature* GetFeature( GIntBig nFeatureId );
-
-  Table* GetTable() { return m_pTable; }
-
-  std::wstring GetTablePath() const { return m_wstrTablePath; }
-  std::wstring GetType() const { return m_wstrType; }
-
-  virtual OGRErr      CreateField( OGRFieldDefn *poField, int bApproxOK );
-  virtual OGRErr      DeleteField( int iFieldToDelete );
-#ifdef AlterFieldDefn_implemented_but_not_working
-  virtual OGRErr      AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags );
-#endif
-
-  virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-  virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-  virtual OGRErr      DeleteFeature( GIntBig nFID );
-
-  virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
-  virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
-                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-
-  virtual GIntBig     GetFeatureCount( int bForce );
-  virtual OGRErr      SetAttributeFilter( const char *pszQuery );
-
-  virtual void        SetSpatialFilter( OGRGeometry * );
-  virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
-                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
-
-//  virtual OGRErr        StartTransaction( );
-//  virtual OGRErr        CommitTransaction( );
-//  virtual OGRErr        RollbackTransaction( );
-
-  OGRFeatureDefn *    GetLayerDefn() { return m_pFeatureDefn; }
-
-  virtual int         TestCapability( const char * );
-
-  // Access the XML directly. The 2 following methods are not currently used by the driver, but
-  // can be used by external code for specific purposes.
-  OGRErr              GetLayerXML ( char **poXml );
-  OGRErr              GetLayerMetadataXML ( char **poXmlMeta );
-  
-  void                SetSymlinkFlag() { m_bSymlinkFlag = TRUE; }
-  
-  virtual const char* GetMetadataItem(const char* pszName, const char* pszDomain);
-  
-protected:
-
-  bool GDBToOGRFields(CPLXMLNode* psFields);  
-  bool ParseGeometryDef(CPLXMLNode* psGeometryDef);
-  bool ParseSpatialReference(CPLXMLNode* psSpatialRefNode, std::string* pOutWkt,
-                             std::string* pOutWKID, std::string* pOutLatestWKID);
-
-  FGdbDataSource* m_pDS;
-  Table* m_pTable;
-
-  std::string m_strName; //contains underlying FGDB table name (not catalog name)
-
-  std::string m_strOIDFieldName;
-  std::string m_strShapeFieldName;
-
-  std::wstring m_wstrTablePath;
-  std::wstring m_wstrType; // the type: "Table" or "Feature Class"
-
-  std::wstring m_wstrSubfields;
-  std::wstring m_wstrWhereClause;
-  OGRGeometry* m_pOGRFilterGeometry;
-
-  bool        m_bFilterDirty; //optimization to avoid multiple calls to search until necessary
-
-  bool  m_bLaunderReservedKeywords;
-
-};
-
-/************************************************************************/
-/*                         FGdbResultLayer                              */
-/************************************************************************/
-
-class FGdbResultLayer : public FGdbBaseLayer
-{
-public:
-
-  FGdbResultLayer(FGdbDataSource* pParentDataSource, const char* pszStatement, EnumRows* pEnumRows);
-  virtual ~FGdbResultLayer();
-
-  virtual void        ResetReading();
-
-  OGRFeatureDefn *    GetLayerDefn() { return m_pFeatureDefn; }
-
-  virtual int         TestCapability( const char * );
-
-protected:
-
-  FGdbDataSource* m_pDS;
-  CPLString       osSQL;
-};
-
-/************************************************************************/
-/*                           FGdbDataSource                            */
-/************************************************************************/
-
-class FGdbDatabaseConnection;
-
-class FGdbDataSource : public OGRDataSource
-{
-  CPLString             m_osFSName;
-  CPLString             m_osPublicName;
-  std::set<OGRLayer*>   m_oSetSelectLayers;
-
-  int        FixIndexes();
-  int        bPerLayerCopyingForTransaction;
-
-public:
-  FGdbDataSource(FGdbDriver* poDriver, FGdbDatabaseConnection* pConnection);
-  virtual ~FGdbDataSource();
-
-  int         Open(const char* pszFSName, int bUpdate,
-                   const char* pszPublicName);
-
-  const char* GetName() { return m_osPublicName.c_str(); }
-  const char* GetFSName() { return m_osFSName.c_str(); }
-
-  int         GetLayerCount() { return static_cast<int>(m_layers.size()); }
-
-  OGRLayer*   GetLayer( int );
-
-  virtual OGRLayer* ICreateLayer( const char *, OGRSpatialReference* = NULL, OGRwkbGeometryType = wkbUnknown, char** = NULL );
-
-  virtual OGRErr DeleteLayer( int );
-
-  virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
-                                  OGRGeometry *poSpatialFilter,
-                                  const char *pszDialect );
-  virtual void        ReleaseResultSet( OGRLayer * poResultsSet );
-
-  int TestCapability( const char * );
-
-  Geodatabase* GetGDB() { return m_pGeodatabase; }
-  bool         GetUpdate() { return m_bUpdate; }
-  FGdbDatabaseConnection* GetConnection() { return m_pConnection; }
-  
-  GDALDriver* GetOpenFileGDBDrv() { return m_poOpenFileGDBDrv; }
-  int         HasSelectLayers() { return m_oSetSelectLayers.size() != 0; }
-  
-  int         Close(int bCloseGeodatabase = FALSE);
-  int         ReOpen();
-  
-  
-  int         HasPerLayerCopyingForTransaction();
-  void        SetPerLayerCopyingForTransaction(int bFlag) { bPerLayerCopyingForTransaction = bFlag; }
-  void        SetSymlinkFlagOnAllLayers();
-
-  /*
-  protected:
-
-  void EnumerateSpatialTables();
-  void OpenSpatialTable( const char* pszTableName );
-  */
-protected:
-  bool LoadLayers(const std::wstring & parent);
-  bool OpenFGDBTables(const std::wstring &type,
-                      const std::vector<std::wstring> &layers);
-
-  FGdbDriver* m_poDriver;
-  FGdbDatabaseConnection* m_pConnection;
-  std::vector <FGdbLayer*> m_layers;
-  Geodatabase* m_pGeodatabase;
-  bool m_bUpdate;
-  GDALDriver* m_poOpenFileGDBDrv;
-};
-
-/************************************************************************/
-/*                              FGdbDriver                                */
-/************************************************************************/
-
-class FGdbDatabaseConnection
-{
-public:
-    FGdbDatabaseConnection(CPLString osName, Geodatabase* pGeodatabase) :
-        m_osName(osName), m_pGeodatabase(pGeodatabase), m_nRefCount(1), m_bLocked(FALSE),
-        m_bFIDHackInProgress(FALSE) {}
-
-    CPLString    m_osName;
-    Geodatabase* m_pGeodatabase;
-    int          m_nRefCount;
-    int          m_bLocked;
-    int          m_bFIDHackInProgress;
-    
-    Geodatabase* GetGDB() { return m_pGeodatabase; }
-    void         SetLocked(int bLockedIn) { m_bLocked = bLockedIn; }
-    int          GetRefCount() const { return m_nRefCount; }
-    int          IsLocked() const { return m_bLocked; }
-    
-    int          IsFIDHackInProgress() const { return m_bFIDHackInProgress; }
-    void         SetFIDHackInProgress(int bFlag) { m_bFIDHackInProgress = bFlag; }
-    int          OpenGeodatabase(const char* pszOverriddenName);
-    void         CloseGeodatabase();
-};
-
-class FGdbDriver : public OGRSFDriver, public IOGRTransactionBehaviour
-{
-  std::map<CPLString, FGdbDatabaseConnection*> oMapConnections;
-  CPLMutex* hMutex;
-
-public:
-  FGdbDriver();
-  virtual ~FGdbDriver();
-
-  virtual const char *GetName();
-  virtual OGRDataSource *Open( const char *, int );
-  virtual int TestCapability( const char * );
-  virtual OGRDataSource *CreateDataSource( const char *pszName, char ** = NULL);
-  virtual OGRErr DeleteDataSource( const char *pszDataSource );
-
-  /* From IOGRTransactionBehaviour */
-  virtual OGRErr StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS);
-  virtual OGRErr CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS);
-  virtual OGRErr RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS);
-
-  void Release(const char* pszName);
-  CPLMutex* GetMutex() { return hMutex; }
-
-private:
-
-};
-
-CPL_C_START
-void CPL_DLL RegisterOGRFileGDB();
-CPL_C_END
-
-#endif /* ndef _OGR_PG_H_INCLUDED */
-
-
+/******************************************************************************
+* $Id: ogr_fgdb.h 36687 2016-12-04 22:28:14Z rouault $
+*
+* Project:  OpenGIS Simple Features Reference Implementation
+* Purpose:  Standard includes and class definitions ArcObjects OGR driver.
+* Author:   Ragi Yaser Burhum, ragi at burhum.com
+*
+******************************************************************************
+* Copyright (c) 2009, Ragi Yaser Burhum
+ * Copyright (c) 2011-2014, Even Rouault <even dot rouault at mines-paris dot org>
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+****************************************************************************/
+
+#ifndef OGR_FGDB_H_INCLUDED
+#define OGR_FGDB_H_INCLUDED
+
+#ifdef DEBUG_BOOL
+#define DO_NOT_USE_DEBUG_BOOL
+#endif
+
+#include <vector>
+#include <set>
+#include "ogrsf_frmts.h"
+#include "ogremulatedtransaction.h"
+
+/* GDAL string utilities */
+#include "cpl_string.h"
+
+/* GDAL XML handler */
+#include "cpl_minixml.h"
+
+/* FGDB API headers through our own inclusion file */
+#include "filegdbsdk_headers.h"
+
+/* Workaround needed for Linux, at least for FileGDB API 1.1 (#4455) */
+#if defined(__linux__)
+#define EXTENT_WORKAROUND
+#endif
+
+/************************************************************************
+* Default layer creation options
+*/
+
+#define FGDB_FEATURE_DATASET "";
+#define FGDB_GEOMETRY_NAME "SHAPE"
+#define FGDB_OID_NAME "OBJECTID"
+
+/* The ESRI FGDB API namespace */
+using namespace FileGDBAPI;
+
+class FGdbDriver;
+
+/************************************************************************/
+/*                           FGdbBaseLayer                              */
+/************************************************************************/
+
+class FGdbBaseLayer : public OGRLayer
+{
+protected:
+
+  FGdbBaseLayer();
+  virtual ~FGdbBaseLayer();
+
+  OGRFeatureDefn* m_pFeatureDefn;
+  OGRSpatialReference* m_pSRS;
+
+  EnumRows*    m_pEnumRows;
+
+  std::vector<std::wstring> m_vOGRFieldToESRIField; //OGR Field Index to ESRI Field Name Mapping
+  std::vector<std::string> m_vOGRFieldToESRIFieldType; //OGR Field Index to ESRI Field Type Mapping
+
+  bool  m_suppressColumnMappingError;
+  bool  m_forceMulti;
+
+  bool OGRFeatureFromGdbRow(Row* pRow, OGRFeature** ppFeature);
+
+  virtual void       CloseGDBObjects();
+
+public:
+          virtual OGRFeature* GetNextFeature() override;
+};
+
+/************************************************************************/
+/*                            FGdbLayer                                 */
+/************************************************************************/
+
+class FGdbDataSource;
+
+class FGdbLayer : public FGdbBaseLayer
+{
+  friend class FGdbDataSource;
+
+  int                 m_bBulkLoadAllowed;
+  int                 m_bBulkLoadInProgress;
+
+  virtual void        CloseGDBObjects() override;
+  int                 EditIndexesForFIDHack(const char* pszRadixTablename);
+  int                 EditGDBTablX(const CPLString& osGDBTablX,
+                                   const CPLString& osNewGDBTablX);
+  int                 EditATXOrSPX(const CPLString& osIndex);
+  int                 EditATXOrSPX( VSILFILE* fp,
+                                    int nThisPage,
+                                    int& nLastPageVisited,
+                                    int nDepth,
+                                    int nSizeIndexedValue,
+                                    GByte* pabyLastIndexedValue,
+                                    int& bIndexedValueIsValid,
+                                    int& nFirstIndexAtThisValue,
+                                    std::vector<int>& anPagesAtThisValue,
+                                    int& bSortThisValue,
+                                    int& bInvalidateIndex );
+
+  void                StartBulkLoad();
+  void                EndBulkLoad();
+
+#ifdef EXTENT_WORKAROUND
+  bool                m_bLayerJustCreated;
+  OGREnvelope         sLayerEnvelope;
+  bool                m_bLayerEnvelopeValid;
+  void                WorkAroundExtentProblem();
+  bool                UpdateRowWithGeometry(Row& row, OGRGeometry* poGeom);
+#endif
+
+  std::vector<ByteArray*> m_apoByteArrays;
+  OGRErr              PopulateRowWithFeature( Row& row, OGRFeature *poFeature );
+  OGRErr              GetRow( EnumRows& enumRows, Row& row, GIntBig nFID );
+
+  char              **m_papszOptions;
+
+  int                 m_bCreateMultipatch;
+
+  std::map<int,int>   m_oMapOGRFIDToFGDBFID;
+  std::map<int,int>   m_oMapFGDBFIDToOGRFID;
+  int                 m_nResyncThreshold;
+  void                ResyncIDs();
+
+  int                 m_bSymlinkFlag;
+  int                 CreateRealCopy();
+
+  char*               CreateFieldDefn(OGRFieldDefn& oField,
+                                      int bApproxOK,
+                                      std::string& fieldname_clean,
+                                      std::string& gdbFieldType);
+
+public:
+
+  FGdbLayer();
+  virtual ~FGdbLayer();
+
+  // Internal used by FGDB driver */
+  bool Initialize(FGdbDataSource* pParentDataSource, Table* pTable, const std::wstring& wstrTablePath, const std::wstring& wstrType);
+  bool Create(FGdbDataSource* pParentDataSource, const char * pszLayerName, OGRSpatialReference *poSRS, OGRwkbGeometryType eType, char ** papszOptions);
+  static bool CreateFeatureDataset(FGdbDataSource* pParentDataSource, const std::string& feature_dataset_name, OGRSpatialReference* poSRS, char** papszOptions );
+
+  // virtual const char *GetName();
+  virtual const char* GetFIDColumn() override { return m_strOIDFieldName.c_str(); }
+
+  virtual void        ResetReading() override;
+  virtual OGRFeature* GetNextFeature() override;
+  virtual OGRFeature* GetFeature( GIntBig nFeatureId ) override;
+
+  Table* GetTable() { return m_pTable; }
+
+  std::wstring GetTablePath() const { return m_wstrTablePath; }
+  std::wstring GetType() const { return m_wstrType; }
+
+  virtual OGRErr      CreateField( OGRFieldDefn *poField, int bApproxOK ) override;
+  virtual OGRErr      DeleteField( int iFieldToDelete ) override;
+#ifdef AlterFieldDefn_implemented_but_not_working
+  virtual OGRErr      AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlags );
+#endif
+
+  virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+  virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+  virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
+
+  virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
+  virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+
+  virtual GIntBig     GetFeatureCount( int bForce ) override;
+  virtual OGRErr      SetAttributeFilter( const char *pszQuery ) override;
+
+  virtual void        SetSpatialFilter( OGRGeometry * ) override;
+  virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
+
+//  virtual OGRErr        StartTransaction( );
+//  virtual OGRErr        CommitTransaction( );
+//  virtual OGRErr        RollbackTransaction( );
+
+  OGRFeatureDefn *    GetLayerDefn() override { return m_pFeatureDefn; }
+
+  virtual int         TestCapability( const char * ) override;
+
+  // Access the XML directly. The 2 following methods are not currently used by the driver, but
+  // can be used by external code for specific purposes.
+  OGRErr              GetLayerXML ( char **poXml );
+  OGRErr              GetLayerMetadataXML ( char **poXmlMeta );
+
+  void                SetSymlinkFlag() { m_bSymlinkFlag = TRUE; }
+
+  virtual const char* GetMetadataItem(const char* pszName, const char* pszDomain) override;
+
+protected:
+
+  bool GDBToOGRFields(CPLXMLNode* psFields);
+  bool ParseGeometryDef(CPLXMLNode* psGeometryDef);
+  bool ParseSpatialReference(CPLXMLNode* psSpatialRefNode, std::string* pOutWkt,
+                             std::string* pOutWKID, std::string* pOutLatestWKID);
+
+  FGdbDataSource* m_pDS;
+  Table* m_pTable;
+
+  std::string m_strName; //contains underlying FGDB table name (not catalog name)
+
+  std::string m_strOIDFieldName;
+  std::string m_strShapeFieldName;
+
+  std::wstring m_wstrTablePath;
+  std::wstring m_wstrType; // the type: "Table" or "Feature Class"
+
+  std::wstring m_wstrSubfields;
+  std::wstring m_wstrWhereClause;
+  OGRGeometry* m_pOGRFilterGeometry;
+
+  bool        m_bFilterDirty; //optimization to avoid multiple calls to search until necessary
+
+  bool  m_bLaunderReservedKeywords;
+};
+
+/************************************************************************/
+/*                         FGdbResultLayer                              */
+/************************************************************************/
+
+class FGdbResultLayer : public FGdbBaseLayer
+{
+public:
+
+  FGdbResultLayer(FGdbDataSource* pParentDataSource, const char* pszStatement, EnumRows* pEnumRows);
+  virtual ~FGdbResultLayer();
+
+  virtual void        ResetReading() override;
+
+  OGRFeatureDefn *    GetLayerDefn() override { return m_pFeatureDefn; }
+
+  virtual int         TestCapability( const char * ) override;
+
+protected:
+
+  FGdbDataSource* m_pDS;
+  CPLString       osSQL;
+};
+
+/************************************************************************/
+/*                           FGdbDataSource                            */
+/************************************************************************/
+
+class FGdbDatabaseConnection;
+
+class FGdbDataSource : public OGRDataSource
+{
+  CPLString             m_osFSName;
+  CPLString             m_osPublicName;
+  std::set<OGRLayer*>   m_oSetSelectLayers;
+
+  int        FixIndexes();
+  int        bPerLayerCopyingForTransaction;
+
+public:
+  FGdbDataSource(FGdbDriver* poDriver, FGdbDatabaseConnection* pConnection);
+  virtual ~FGdbDataSource();
+
+  int         Open(const char* pszFSName, int bUpdate,
+                   const char* pszPublicName);
+
+  const char* GetName() override { return m_osPublicName.c_str(); }
+  const char* GetFSName() { return m_osFSName.c_str(); }
+
+  int         GetLayerCount() override { return static_cast<int>(m_layers.size()); }
+
+  OGRLayer*   GetLayer( int ) override;
+
+  virtual OGRLayer* ICreateLayer( const char *, OGRSpatialReference* = NULL, OGRwkbGeometryType = wkbUnknown, char** = NULL ) override;
+
+  virtual OGRErr DeleteLayer( int ) override;
+
+  virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
+                                  OGRGeometry *poSpatialFilter,
+                                  const char *pszDialect ) override;
+  virtual void        ReleaseResultSet( OGRLayer * poResultsSet ) override;
+
+  int TestCapability( const char * ) override;
+
+  Geodatabase* GetGDB() { return m_pGeodatabase; }
+  bool         GetUpdate() { return m_bUpdate; }
+  FGdbDatabaseConnection* GetConnection() { return m_pConnection; }
+
+  GDALDriver* GetOpenFileGDBDrv() { return m_poOpenFileGDBDrv; }
+  int         HasSelectLayers() { return !m_oSetSelectLayers.empty(); }
+
+  int         Close(int bCloseGeodatabase = FALSE);
+  int         ReOpen();
+
+  int         HasPerLayerCopyingForTransaction();
+  void        SetPerLayerCopyingForTransaction(int bFlag) { bPerLayerCopyingForTransaction = bFlag; }
+  void        SetSymlinkFlagOnAllLayers();
+
+  /*
+  protected:
+
+  void EnumerateSpatialTables();
+  void OpenSpatialTable( const char* pszTableName );
+  */
+protected:
+  bool LoadLayers(const std::wstring & parent);
+  bool OpenFGDBTables(const std::wstring &type,
+                      const std::vector<std::wstring> &layers);
+
+  FGdbDriver* m_poDriver;
+  FGdbDatabaseConnection* m_pConnection;
+  std::vector <FGdbLayer*> m_layers;
+  Geodatabase* m_pGeodatabase;
+  bool m_bUpdate;
+  GDALDriver* m_poOpenFileGDBDrv;
+};
+
+/************************************************************************/
+/*                              FGdbDriver                                */
+/************************************************************************/
+
+class FGdbDatabaseConnection
+{
+public:
+    FGdbDatabaseConnection(CPLString osName, Geodatabase* pGeodatabase) :
+        m_osName(osName), m_pGeodatabase(pGeodatabase), m_nRefCount(1), m_bLocked(FALSE),
+        m_bFIDHackInProgress(FALSE) {}
+
+    CPLString    m_osName;
+    Geodatabase* m_pGeodatabase;
+    int          m_nRefCount;
+    int          m_bLocked;
+    int          m_bFIDHackInProgress;
+
+    Geodatabase* GetGDB() { return m_pGeodatabase; }
+    void         SetLocked(int bLockedIn) { m_bLocked = bLockedIn; }
+    int          GetRefCount() const { return m_nRefCount; }
+    int          IsLocked() const { return m_bLocked; }
+
+    int          IsFIDHackInProgress() const { return m_bFIDHackInProgress; }
+    void         SetFIDHackInProgress(int bFlag) { m_bFIDHackInProgress = bFlag; }
+    int          OpenGeodatabase(const char* pszOverriddenName);
+    void         CloseGeodatabase();
+};
+
+class FGdbDriver : public OGRSFDriver, public IOGRTransactionBehaviour
+{
+  std::map<CPLString, FGdbDatabaseConnection*> oMapConnections;
+  CPLMutex* hMutex;
+
+public:
+  FGdbDriver();
+  virtual ~FGdbDriver();
+
+  virtual const char *GetName() override;
+  virtual OGRDataSource *Open( const char *, int ) override;
+  virtual int TestCapability( const char * ) override;
+  virtual OGRDataSource *CreateDataSource( const char *pszName, char ** = NULL) override;
+  virtual OGRErr DeleteDataSource( const char *pszDataSource ) override;
+
+  /* From IOGRTransactionBehaviour */
+  virtual OGRErr StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS) override;
+  virtual OGRErr CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS) override;
+  virtual OGRErr RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS) override;
+
+  void Release(const char* pszName);
+  CPLMutex* GetMutex() { return hMutex; }
+};
+
+CPL_C_START
+void CPL_DLL RegisterOGRFileGDB();
+CPL_C_END
+
+#endif /* ndef _OGR_PG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/fme/fme2ogr.h b/ogr/ogrsf_frmts/fme/fme2ogr.h
index a172e36..ab669a1 100644
--- a/ogr/ogrsf_frmts/fme/fme2ogr.h
+++ b/ogr/ogrsf_frmts/fme/fme2ogr.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: fme2ogr.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: fme2ogr.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Declarations for translating IFMEFeatures to OGRFeatures.
@@ -61,17 +61,17 @@ class OGRFMELayer : public OGRLayer
     IFMEFeature         *poFMEFeature;
 
   public:
-                        OGRFMELayer( OGRFMEDataSource * );
+    explicit            OGRFMELayer( OGRFMEDataSource * );
     virtual             ~OGRFMELayer();
 
     virtual int         Initialize( IFMEFeature *,
                                     OGRSpatialReference * );
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    OGRSpatialReference *GetSpatialRef();
+    OGRSpatialReference *GetSpatialRef() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 };
 
 /************************************************************************/
@@ -93,16 +93,16 @@ class OGRFMELayerCached : public OGRFMELayer
     int                 bQueryActive;
 
   public:
-                       OGRFMELayerCached( OGRFMEDataSource * );
+    explicit            OGRFMELayerCached( OGRFMEDataSource * );
     virtual            ~OGRFMELayerCached();
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual GIntBig     GetFeatureCount( int bForce );
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual GIntBig     GetFeatureCount( int bForce ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     int                 AssignIndex( const char *pszBase, const OGREnvelope*,
                                      OGRSpatialReference *poSRS );
@@ -134,13 +134,13 @@ class OGRFMELayerDB : public OGRFMELayer
                                       IFMEStringArray *poUserDirectives );
     virtual            ~OGRFMELayerDB();
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual GIntBig     GetFeatureCount( int bForce );
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual GIntBig     GetFeatureCount( int bForce ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     void                AssignIndex( const char *pszBase );
 };
@@ -190,18 +190,18 @@ class OGRFMEDataSource : public OGRDataSource
     IFMESession *       AcquireSession();
     void                ReleaseSession();
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     OGRGeometry        *ProcessGeometry( OGRFMELayer *, IFMEFeature *,
                                          OGRwkbGeometryType );
     OGRFeature         *ProcessFeature( OGRFMELayer *, IFMEFeature * );
-    void                ResetReading();
+    void                ResetReading() override;
 
     int                 Open( const char * );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
     IFMESession         *GetFMESession() { return poSession; }
     IFMEUniversalReader *GetFMEReader() { return poReader; }
@@ -224,10 +224,10 @@ class OGRFMEDriver : public OGRSFDriver
   public:
                 ~OGRFMEDriver();
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 };
 
 /************************************************************************/
@@ -242,7 +242,7 @@ class OGRFMECacheIndex
     void        *hLock;
 
   public:
-                OGRFMECacheIndex( const char *pszPath );
+    explicit     OGRFMECacheIndex( const char *pszPath );
                 ~OGRFMECacheIndex();
 
     const char *GetPath() { return pszPath; }
@@ -257,10 +257,10 @@ class OGRFMECacheIndex
     int         Lock();
     int         Unlock();
 
-    void        Touch( CPLXMLNode * );
+    static void        Touch( CPLXMLNode * );
     void        Add( CPLXMLNode * );
-    void        Reference( CPLXMLNode * );
-    void        Dereference( CPLXMLNode * );
+    static void        Reference( CPLXMLNode * );
+    static void        Dereference( CPLXMLNode * );
 
     int         ExpireOldCaches( IFMESession * );
 };
@@ -285,7 +285,6 @@ class OGRFMECacheIndex
 #  define FMECACHE_MAX_RETENTION    3600
 #endif
 
-
 CPL_C_START
 void RegisterOGRFME();
 CPL_C_END
diff --git a/ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp b/ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp
index 56e4f4d..c689509 100644
--- a/ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp
+++ b/ogr/ogrsf_frmts/fme/fme2ogr_utils.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: fme2ogr_utils.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Various FME related support functions.
@@ -31,6 +30,8 @@
 #include "cpl_conv.h"
 #include <stdarg.h>
 
+CPL_CVSID("$Id: fme2ogr_utils.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+
 /************************************************************************/
 /*                            CPLFMEError()                             */
 /*                                                                      */
diff --git a/ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp b/ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp
index 938a0c5..ac025e0 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmecacheindex.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfmecacheindex.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implement the OGRFMECacheIndex class, a mechanism to manage a
@@ -35,7 +34,7 @@
 #include "cpl_string.h"
 #include <time.h>
 
-CPL_CVSID("$Id: ogrfmecacheindex.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrfmecacheindex.cpp 36332 2016-11-20 15:19:39Z rouault $");
 
 /************************************************************************/
 /*                          OGRFMECacheIndex()                          */
@@ -322,13 +321,18 @@ void OGRFMECacheIndex::Dereference( CPLXMLNode *psDSNode )
 void OGRFMECacheIndex::Add( CPLXMLNode *psDSNode )
 
 {
-    CPLAssert( psTree != NULL );
+    if( psTree == NULL )
+    {
+        CPLAssert( false );
+        return;
+    }
+
+    if( psDSNode == NULL || !EQUAL(psDSNode->pszValue,"DataSource") )
+        return;
 
     psDSNode->psNext = psTree->psChild;
     psTree->psChild = psDSNode;
 
-    if( psDSNode == NULL || !EQUAL(psDSNode->pszValue,"DataSource") )
-        return;
 
 /* -------------------------------------------------------------------- */
 /*      Prepare the creation time value to use.                         */
diff --git a/ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp b/ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp
index 3d972bd..71b94df 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmedatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfmedatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementations of the OGRFMEDataSource class.
@@ -39,7 +38,7 @@
 
 const char* kPROVIDERNAME = "FME_OLEDB";
 
-CPL_CVSID("$Id: ogrfmedatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrfmedatasource.cpp 36347 2016-11-20 20:43:39Z rouault $");
 
 #ifdef WIN32
 #define FMEDLL_NAME "fme.dll"
@@ -174,6 +173,8 @@ OGRFMEDataSource::OGRFMEDataSource()
     poUserDirectives = NULL;
 
     bUseCaching = FALSE;
+    poFMEString = NULL;
+    bCoordSysOverride = FALSE;
 }
 
 /************************************************************************/
@@ -600,7 +601,6 @@ int OGRFMEDataSource::Open( const char * pszCompositeName )
 
             psMatchDS = CPLCloneXMLTree( psMatchDS );
             oCacheIndex.Unlock();
-
         }
         else
         {
@@ -1515,7 +1515,6 @@ IFMESession *OGRFMEDataSource::AcquireSession()
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Something has gone wonky with createStringArray() on the IFMESession.\n"
                       "Is it possible you built with gcc 3.2 on Linux?  This seems problematic." );
-
         }
         else
         {
diff --git a/ogr/ogrsf_frmts/fme/ogrfmedriver.cpp b/ogr/ogrsf_frmts/fme/ogrfmedriver.cpp
index e84668f..4e73989 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmedriver.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmedriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfmedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementations of the OGRFMEDriver class.
@@ -30,7 +29,7 @@
 #include "fme2ogr.h"
 #include "cpl_error.h"
 
-CPL_CVSID("$Id: ogrfmedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrfmedriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
diff --git a/ogr/ogrsf_frmts/fme/ogrfmelayer.cpp b/ogr/ogrsf_frmts/fme/ogrfmelayer.cpp
index 8d77d8b..c6cdaf5 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmelayer.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfmelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementation of the OGRFMELayer base class.  The class
@@ -33,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrfmelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrfmelayer.cpp 36763 2016-12-09 22:10:55Z rouault $");
 
 /************************************************************************/
 /*                            OGRFMELayer()                             */
@@ -252,7 +251,8 @@ int OGRFMELayer::Initialize( IFMEFeature * poSchemaFeature,
         }
         else
         {
-            printf( "Not able to translate field type: %s\n",
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Not able to translate field type: %s",
                     poAttrValue->data() );
             CSLDestroy( papszTokens );
             continue;
diff --git a/ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp b/ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp
index a67cbad..d977bd0 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmelayercached.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfmelayercached.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementation of the OGRFMELayerCached class.  This is the
@@ -33,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrfmelayercached.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrfmelayercached.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                         OGRFMELayerCached()                          */
diff --git a/ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp b/ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp
index a8d3cd8..10423a8 100644
--- a/ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp
+++ b/ogr/ogrsf_frmts/fme/ogrfmelayerdb.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrfmelayerdb.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  FMEObjects Translator
  * Purpose:  Implementation of the OGRFMELayerDB class.  This is the
@@ -34,7 +33,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrfmelayerdb.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrfmelayerdb.cpp 36451 2016-11-22 22:31:47Z rouault $");
 
 /************************************************************************/
 /*                           OGRFMELayerDB()                            */
@@ -120,8 +119,8 @@ OGRFeature *OGRFMELayerDB::GetNextFeature()
     {
         if( !CreateReader() )
         {
-            return NULL;
             poDS->ReleaseSession();
+            return NULL;
         }
     }
 
diff --git a/ogr/ogrsf_frmts/generic/GNUmakefile b/ogr/ogrsf_frmts/generic/GNUmakefile
index a226112..23b5af9 100644
--- a/ogr/ogrsf_frmts/generic/GNUmakefile
+++ b/ogr/ogrsf_frmts/generic/GNUmakefile
@@ -125,6 +125,10 @@ ifeq ($(HAVE_XERCES),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DILI_ENABLED
 endif
 
+ifeq ($(HAVE_XERCES),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DGMLAS_ENABLED
+endif
+
 ifeq ($(HAVE_NAS),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DNAS_ENABLED
 endif
@@ -133,8 +137,8 @@ ifeq ($(HAVE_LIBKML),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DLIBKML_ENABLED
 endif
 
-ifeq ($(HAVE_DWGDIRECT),yes)
-CXXFLAGS :=	$(CXXFLAGS) -DDWGDIRECT_ENABLED
+ifeq ($(HAVE_TEIGHA),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DDWG_ENABLED -DDGNV8_ENABLED
 endif
 
 ifeq ($(HAVE_IDB),yes)
@@ -218,6 +222,10 @@ ifeq ($(HAVE_MONGODB),yes)
 CXXFLAGS :=	$(CXXFLAGS) -DMONGODB_ENABLED
 endif
 
+ifeq ($(HAVE_CAD),yes)
+CXXFLAGS :=	$(CXXFLAGS) -DCAD_ENABLED
+endif
+
 CPPFLAGS	:=	-I.. -I../..  $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/ogr/ogrsf_frmts/generic/makefile.vc b/ogr/ogrsf_frmts/generic/makefile.vc
index 86beef8..bfbbeef 100644
--- a/ogr/ogrsf_frmts/generic/makefile.vc
+++ b/ogr/ogrsf_frmts/generic/makefile.vc
@@ -20,7 +20,8 @@ EXTRAFLAGS =	-I.. -I..\.. $(OGDIDEF) $(FMEDEF) $(OCIDEF) $(PGDEF) \
 		$(SDEDEF) $(BASEFORMATS) $(IDBDEF) $(NASDEF) $(DODSDEF) \
 		$(LIBKMLDEF) $(WFSDEF) $(SOSIDEF) $(GFTDEF) \
 		$(COUCHDBDEF) $(CLOUDANTDEF) $(FGDBDEF) $(XLSDEF) $(ODSDEF) $(XLSXDEF) $(INGRESDEF) \
-		$(ELASTICDEF) $(OSMDEF) $(VFKDEF) $(CARTODEF) $(AMIGOCLOUDDEF) $(PLSCENESDEF) $(CSWDEF) $(MONGODBDEF)
+		$(ELASTICDEF) $(OSMDEF) $(VFKDEF) $(CARTODEF) $(AMIGOCLOUDDEF) $(PLSCENESDEF) $(CSWDEF) $(MONGODBDEF) \
+		$(GMLASDEF) $(CADDEF)
 
 !IFDEF OGDIDIR
 OGDIDEF	=	-DOGDI_ENABLED
@@ -64,9 +65,13 @@ FMEDEF = -DFME_ENABLED
 ILIDEF = -DILI_ENABLED
 !ENDIF
 
-!IFDEF DWGDIRECT
-!IF "$(DWG_PLUGIN)" != "YES"
-ILIDEF = -DDWGDIRECT_ENABLED
+!IFDEF XERCES_INCLUDE
+GMLASDEF = -DGMLAS_ENABLED
+!ENDIF
+
+!IFDEF TD_LIBDIR
+!IF "$(TD_PLUGIN)" != "YES"
+DWGDEF = -DDWG_ENABLED -DDGNV8_ENABLED
 !ENDIF
 !ENDIF
 
@@ -162,6 +167,10 @@ MONGODBDEF = -DMONGODB_ENABLED
 !ENDIF
 !ENDIF
 
+!IF $(MSVC_VER) >= 1800
+CADDEF = -DCAD_ENABLED
+!ENDIF
+
 !ELSE
 
 EXTRAFLAGS =	-I.. -I..\..
diff --git a/ogr/ogrsf_frmts/generic/ogr_attrind.cpp b/ogr/ogrsf_frmts/generic/ogr_attrind.cpp
index b8e9c24..8674584 100644
--- a/ogr/ogrsf_frmts/generic/ogr_attrind.cpp
+++ b/ogr/ogrsf_frmts/generic/ogr_attrind.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_attrind.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRLayerAttrIndex and OGRAttrIndex base classes.
@@ -30,7 +29,9 @@
 #include "ogr_attrind.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogr_attrind.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogr_attrind.cpp 35172 2016-08-21 20:33:08Z goatbar $");
+
+//! @cond Doxygen_Suppress
 
 /************************************************************************/
 /* ==================================================================== */
@@ -42,12 +43,10 @@ CPL_CVSID("$Id: ogr_attrind.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 /*                         OGRLayerAttrIndex()                          */
 /************************************************************************/
 
-OGRLayerAttrIndex::OGRLayerAttrIndex()
-
-{
-    poLayer = NULL;
-    pszIndexPath = NULL;
-}
+OGRLayerAttrIndex::OGRLayerAttrIndex() :
+    poLayer(NULL),
+    pszIndexPath(NULL)
+{}
 
 /************************************************************************/
 /*                         ~OGRLayerAttrIndex()                         */
@@ -70,15 +69,12 @@ OGRLayerAttrIndex::~OGRLayerAttrIndex()
 /*                            OGRAttrIndex()                            */
 /************************************************************************/
 
-OGRAttrIndex::OGRAttrIndex()
-
-{
-}
+OGRAttrIndex::OGRAttrIndex() {}
 
 /************************************************************************/
 /*                           ~OGRAttrIndex()                            */
 /************************************************************************/
 
-OGRAttrIndex::~OGRAttrIndex()
-{
-}
+OGRAttrIndex::~OGRAttrIndex() {}
+
+//! @endcond
diff --git a/ogr/ogrsf_frmts/generic/ogr_gensql.cpp b/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
index 0fc9f14..afbde65 100644
--- a/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
+++ b/ogr/ogrsf_frmts/generic/ogr_gensql.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_gensql.cpp 34092 2016-04-25 09:09:46Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGenSQLResultsLayer.
@@ -34,15 +33,17 @@
 #include "cpl_string.h"
 #include "ogr_api.h"
 #include "cpl_time.h"
+#include <algorithm>
 #include <vector>
 
-CPL_CVSID("$Id: ogr_gensql.cpp 34092 2016-04-25 09:09:46Z rouault $");
+//! @cond Doxygen_Suppress
 
+CPL_CVSID("$Id: ogr_gensql.cpp 37581 2017-03-03 16:23:40Z rouault $");
 
 class OGRGenSQLGeomFieldDefn: public OGRGeomFieldDefn
 {
     public:
-        OGRGenSQLGeomFieldDefn(OGRGeomFieldDefn* poGeomFieldDefn) :
+        explicit OGRGenSQLGeomFieldDefn(OGRGeomFieldDefn* poGeomFieldDefn) :
             OGRGeomFieldDefn(poGeomFieldDefn->GetNameRef(),
                              poGeomFieldDefn->GetType()), bForceGeomType(FALSE)
         {
@@ -89,16 +90,25 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDSIn,
                                               OGRGeometry *poSpatFilter,
                                               const char *pszWHEREIn,
                                               const char *pszDialect ) :
-    poSrcLayer(NULL), pszWHERE(NULL), papoTableLayers(NULL), poDefn(NULL),
-    panGeomFieldToSrcGeomField(NULL), nIndexSize(0),
-    panFIDIndex(NULL), bOrderByValid(FALSE), nNextIndexFID(0),
-    poSummaryFeature(NULL), iFIDFieldIndex(), nExtraDSCount(0), papoExtraDS(NULL)
+    poSrcDS(poSrcDSIn),
+    poSrcLayer(NULL),
+    pSelectInfo(pSelectInfoIn),
+    pszWHERE(NULL),
+    papoTableLayers(NULL),
+    poDefn(NULL),
+    panGeomFieldToSrcGeomField(NULL),
+    nIndexSize(0),
+    panFIDIndex(NULL),
+    bOrderByValid(FALSE),
+    nNextIndexFID(0),
+    poSummaryFeature(NULL),
+    iFIDFieldIndex(),
+    nExtraDSCount(0),
+    papoExtraDS(NULL),
+    nIteratedFeatures(-1)
 {
     swq_select *psSelectInfo = (swq_select *) pSelectInfoIn;
 
-    poSrcDS = poSrcDSIn;
-    pSelectInfo = pSelectInfoIn;
-
 /* -------------------------------------------------------------------- */
 /*      Identify all the layers involved in the SELECT.                 */
 /* -------------------------------------------------------------------- */
@@ -178,7 +188,8 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDSIn,
     iFIDFieldIndex = poSrcDefn->GetFieldCount();
 
     /* + 1 since we can add an implicit geometry field */
-    panGeomFieldToSrcGeomField = (int*) CPLMalloc(sizeof(int) * (1 + psSelectInfo->result_columns));
+    panGeomFieldToSrcGeomField = static_cast<int *>(
+        CPLMalloc(sizeof(int) * (1 + psSelectInfo->result_columns)));
 
     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     {
@@ -220,7 +231,7 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDSIn,
         if( strlen(psColDef->field_name) == 0 && !bIsGeometry )
         {
             CPLFree( psColDef->field_name );
-            psColDef->field_name = (char *) CPLMalloc(40);
+            psColDef->field_name = static_cast<char *>(CPLMalloc(40));
             snprintf( psColDef->field_name, 40, "FIELD_%d", poDefn->GetFieldCount()+1 );
         }
 
@@ -372,7 +383,7 @@ OGRGenSQLResultsLayer::OGRGenSQLResultsLayer( GDALDataset *poSrcDSIn,
             break;
 
           default:
-            CPLAssert( FALSE );
+            CPLAssert( false );
             oFDefn.SetType( OFTString );
             break;
         }
@@ -547,11 +558,10 @@ void OGRGenSQLResultsLayer::ClearFilters()
 /*      Clear any attribute filter installed on the joined layers.      */
 /* -------------------------------------------------------------------- */
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
-    int iJoin;
 
     if( psSelectInfo != NULL )
     {
-        for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
+        for( int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
         {
             swq_join_def *psJoinInfo = psSelectInfo->join_defs + iJoin;
             OGRLayer *poJoinLayer =
@@ -624,7 +634,8 @@ void OGRGenSQLResultsLayer::ResetReading()
         ApplyFiltersToSource();
     }
 
-    nNextIndexFID = 0;
+    nNextIndexFID = psSelectInfo->offset;
+    nIteratedFeatures = -1;
 }
 
 /************************************************************************/
@@ -637,20 +648,25 @@ void OGRGenSQLResultsLayer::ResetReading()
 OGRErr OGRGenSQLResultsLayer::SetNextByIndex( GIntBig nIndex )
 
 {
+    if( nIndex < 0 )
+        return OGRERR_FAILURE;
+
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
 
+    nIteratedFeatures = 0;
+
     CreateOrderByIndex();
 
     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST
         || panFIDIndex != NULL )
     {
-        nNextIndexFID = nIndex;
+        nNextIndexFID = nIndex + psSelectInfo->offset;
         return OGRERR_NONE;
     }
     else
     {
-        return poSrcLayer->SetNextByIndex( nIndex );
+        return poSrcLayer->SetNextByIndex( nIndex + psSelectInfo->offset );
     }
 }
 
@@ -701,24 +717,32 @@ GIntBig OGRGenSQLResultsLayer::GetFeatureCount( int bForce )
 
     CreateOrderByIndex();
 
+    GIntBig nRet = 0;
     if( psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
     {
         if( !PrepareSummary() )
             return 0;
 
-        swq_summary *psSummary = psSelectInfo->column_summary + 0;
-
-        if( psSummary == NULL )
+        if( psSelectInfo->column_summary.empty() )
             return 0;
 
-        return psSummary->count;
+        nRet = psSelectInfo->column_summary[0].count;
     }
     else if( psSelectInfo->query_mode != SWQM_RECORDSET )
         return 1;
     else if( m_poAttrQuery == NULL && !MustEvaluateSpatialFilterOnGenSQL() )
-        return poSrcLayer->GetFeatureCount( bForce );
+    {
+        nRet = poSrcLayer->GetFeatureCount( bForce );
+    }
     else
-        return OGRLayer::GetFeatureCount( bForce );
+    {
+        nRet = OGRLayer::GetFeatureCount( bForce );
+    }
+
+    nRet = std::max(static_cast<GIntBig>(0), nRet - psSelectInfo->offset);
+    if( psSelectInfo->limit >= 0 )
+        nRet = std::min(nRet, psSelectInfo->limit);
+    return nRet;
 }
 
 /************************************************************************/
@@ -880,13 +904,12 @@ int OGRGenSQLResultsLayer::PrepareSummary()
 /*      Otherwise, process all source feature through the summary       */
 /*      building facilities of SWQ.                                     */
 /* -------------------------------------------------------------------- */
-    const char *pszError;
-    OGRFeature *poSrcFeature;
-    int iField;
+    const char *pszError = NULL;
+    OGRFeature *poSrcFeature = NULL;
 
     while( (poSrcFeature = poSrcLayer->GetNextFeature()) != NULL )
     {
-        for( iField = 0; iField < psSelectInfo->result_columns; iField++ )
+        for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
         {
             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
 
@@ -905,7 +928,7 @@ int OGRGenSQLResultsLayer::PrepareSummary()
                     else
                         pszError = NULL;
                 }
-                else if (poSrcFeature->IsFieldSet(psColDef->field_index))
+                else if (poSrcFeature->IsFieldSetAndNotNull(psColDef->field_index))
                     pszError = swq_select_summarize( psSelectInfo, iField, poSrcFeature->GetFieldAsString(
                                                 psColDef->field_index ) );
                 else
@@ -914,7 +937,7 @@ int OGRGenSQLResultsLayer::PrepareSummary()
             else
             {
                 const char* pszVal = NULL;
-                if (poSrcFeature->IsFieldSet(psColDef->field_index))
+                if (poSrcFeature->IsFieldSetAndNotNull(psColDef->field_index))
                     pszVal = poSrcFeature->GetFieldAsString(
                                                 psColDef->field_index );
                 pszError = swq_select_summarize( psSelectInfo, iField, pszVal );
@@ -938,16 +961,6 @@ int OGRGenSQLResultsLayer::PrepareSummary()
 
     poSrcLayer->GetLayerDefn()->SetGeometryIgnored(bSaveIsGeomIgnored);
 
-    pszError = swq_select_finish_summarize( psSelectInfo );
-    if( pszError != NULL )
-    {
-        delete poSummaryFeature;
-        poSummaryFeature = NULL;
-
-        CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError );
-        return FALSE;
-    }
-
 /* -------------------------------------------------------------------- */
 /*      If we have run out of features on the source layer, clear       */
 /*      away the filters we have installed till a next run through      */
@@ -962,15 +975,15 @@ int OGRGenSQLResultsLayer::PrepareSummary()
 /* -------------------------------------------------------------------- */
     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD )
     {
-        for( iField = 0; iField < psSelectInfo->result_columns; iField++ )
+        for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
         {
             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
-            if (psSelectInfo->column_summary != NULL)
+            if( !psSelectInfo->column_summary.empty() )
             {
-                swq_summary *psSummary = psSelectInfo->column_summary + iField;
+                swq_summary& oSummary = psSelectInfo->column_summary[iField];
                 if( psColDef->col_func == SWQCF_COUNT )
                 {
-                    if( CPL_INT64_FITS_ON_INT32(psSummary->count) )
+                    if( CPL_INT64_FITS_ON_INT32(oSummary.count) )
                     {
                         delete poSummaryFeature;
                         poSummaryFeature = NULL;
@@ -986,21 +999,21 @@ int OGRGenSQLResultsLayer::PrepareSummary()
             poSummaryFeature->SetFID( 0 );
         }
 
-        for( iField = 0; iField < psSelectInfo->result_columns; iField++ )
+        for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
         {
             swq_col_def *psColDef = psSelectInfo->column_defs + iField;
-            if (psSelectInfo->column_summary != NULL)
+            if (!psSelectInfo->column_summary.empty() )
             {
-                swq_summary *psSummary = psSelectInfo->column_summary + iField;
+                swq_summary& oSummary = psSelectInfo->column_summary[iField];
 
-                if( psColDef->col_func == SWQCF_AVG && psSummary->count > 0 )
+                if( psColDef->col_func == SWQCF_AVG && oSummary.count > 0 )
                 {
                     if( psColDef->field_type == SWQ_DATE ||
                         psColDef->field_type == SWQ_TIME ||
                         psColDef->field_type == SWQ_TIMESTAMP)
                     {
                         struct tm brokendowntime;
-                        double dfAvg = psSummary->sum / psSummary->count;
+                        double dfAvg = oSummary.sum / oSummary.count;
                         CPLUnixTimeToYMDHMS((GIntBig)dfAvg, &brokendowntime);
                         poSummaryFeature->SetField( iField,
                                                     brokendowntime.tm_year + 1900,
@@ -1013,30 +1026,30 @@ int OGRGenSQLResultsLayer::PrepareSummary()
                     }
                     else
                         poSummaryFeature->SetField( iField,
-                                                    psSummary->sum / psSummary->count );
+                                                    oSummary.sum / oSummary.count );
                 }
-                else if( psColDef->col_func == SWQCF_MIN && psSummary->count > 0 )
+                else if( psColDef->col_func == SWQCF_MIN && oSummary.count > 0 )
                 {
                     if( psColDef->field_type == SWQ_DATE ||
                         psColDef->field_type == SWQ_TIME ||
                         psColDef->field_type == SWQ_TIMESTAMP)
-                        poSummaryFeature->SetField( iField, psSummary->szMin );
+                        poSummaryFeature->SetField( iField, oSummary.osMin.c_str() );
                     else
-                        poSummaryFeature->SetField( iField, psSummary->min );
+                        poSummaryFeature->SetField( iField, oSummary.min );
                 }
-                else if( psColDef->col_func == SWQCF_MAX && psSummary->count > 0 )
+                else if( psColDef->col_func == SWQCF_MAX && oSummary.count > 0 )
                 {
                     if( psColDef->field_type == SWQ_DATE ||
                         psColDef->field_type == SWQ_TIME ||
                         psColDef->field_type == SWQ_TIMESTAMP)
-                        poSummaryFeature->SetField( iField, psSummary->szMax );
+                        poSummaryFeature->SetField( iField, oSummary.osMax.c_str() );
                     else
-                        poSummaryFeature->SetField( iField, psSummary->max );
+                        poSummaryFeature->SetField( iField, oSummary.max );
                 }
                 else if( psColDef->col_func == SWQCF_COUNT )
-                    poSummaryFeature->SetField( iField, psSummary->count );
-                else if( psColDef->col_func == SWQCF_SUM && psSummary->count > 0 )
-                    poSummaryFeature->SetField( iField, psSummary->sum );
+                    poSummaryFeature->SetField( iField, oSummary.count );
+                else if( psColDef->col_func == SWQCF_SUM && oSummary.count > 0 )
+                    poSummaryFeature->SetField( iField, oSummary.sum );
             }
             else if ( psColDef->col_func == SWQCF_COUNT )
                 poSummaryFeature->SetField( iField, 0 );
@@ -1056,7 +1069,6 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
 {
     std::vector<OGRFeature*> *papoFeatures =
         (std::vector<OGRFeature*> *) pFeatureList;
-    OGRFeature *poFeature;
     swq_expr_node *poRetNode = NULL;
 
     CPLAssert( op->eNodeType == SNT_COLUMN );
@@ -1072,7 +1084,7 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
         return NULL;
     }
 
-    poFeature = (*papoFeatures)[op->table_index];
+    OGRFeature *poFeature = (*papoFeatures)[op->table_index];
 
 /* -------------------------------------------------------------------- */
 /*      Fetch the value.                                                */
@@ -1082,7 +1094,7 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
       case SWQ_INTEGER:
       case SWQ_BOOLEAN:
         if( poFeature == NULL
-            || !poFeature->IsFieldSet(op->field_index) )
+            || !poFeature->IsFieldSetAndNotNull(op->field_index) )
         {
             poRetNode = new swq_expr_node(0);
             poRetNode->is_null = TRUE;
@@ -1094,7 +1106,7 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
 
       case SWQ_INTEGER64:
         if( poFeature == NULL
-            || !poFeature->IsFieldSet(op->field_index) )
+            || !poFeature->IsFieldSetAndNotNull(op->field_index) )
         {
             poRetNode = new swq_expr_node((GIntBig)0);
             poRetNode->is_null = TRUE;
@@ -1106,7 +1118,7 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
 
       case SWQ_FLOAT:
         if( poFeature == NULL
-            || !poFeature->IsFieldSet(op->field_index) )
+            || !poFeature->IsFieldSetAndNotNull(op->field_index) )
         {
             poRetNode = new swq_expr_node( 0.0 );
             poRetNode->is_null = TRUE;
@@ -1132,7 +1144,7 @@ static swq_expr_node *OGRMultiFeatureFetcher( swq_expr_node *op,
 
       default:
         if( poFeature == NULL
-            || !poFeature->IsFieldSet(op->field_index) )
+            || !poFeature->IsFieldSetAndNotNull(op->field_index) )
         {
             poRetNode = new swq_expr_node("");
             poRetNode->is_null = TRUE;
@@ -1169,7 +1181,7 @@ static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
         if( poExpr->table_index == 0 )
         {
             // if source key is null, we can't do join.
-            if( !poSrcFeat->IsFieldSet( poExpr->field_index ) )
+            if( !poSrcFeat->IsFieldSetAndNotNull( poExpr->field_index ) )
             {
                 return "";
             }
@@ -1206,7 +1218,7 @@ static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
             break;
 
             default:
-                CPLAssert( FALSE );
+                CPLAssert( false );
                 return "";
             }
         }
@@ -1218,7 +1230,7 @@ static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
             return CPLSPrintf("\"%s\"", poSecondaryFieldDefn->GetNameRef());
         }
 
-        CPLAssert(FALSE);
+        CPLAssert(false);
         return "";
     }
 
@@ -1232,7 +1244,7 @@ static CPLString GetFilterForJoin(swq_expr_node* poExpr, OGRFeature* poSrcFeat,
         {
             CPLString osSubExpr = GetFilterForJoin(poExpr->papoSubExpr[i], poSrcFeat,
                                                    poJoinLayer, secondary_table);
-            if( osSubExpr.size() == 0 )
+            if( osSubExpr.empty() )
             {
                 for( --i; i >=0; i-- )
                     CPLFree( apszSubExpr[i] );
@@ -1263,7 +1275,6 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
 
 {
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
-    OGRFeature *poDstFeat;
     std::vector<OGRFeature*> apoFeatures;
 
     if( poSrcFeat == NULL )
@@ -1276,9 +1287,7 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
 /* -------------------------------------------------------------------- */
 /*      Fetch the corresponding features from any jointed tables.       */
 /* -------------------------------------------------------------------- */
-    int iJoin;
-
-    for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
+    for( int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
     {
         CPLString osFilter;
 
@@ -1296,7 +1305,7 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
         //CPLDebug("OGR", "Filter = %s\n", osFilter.c_str());
 
         // if source key is null, we can't do join.
-        if( osFilter.size() == 0 )
+        if( osFilter.empty() )
         {
             apoFeatures.push_back( NULL );
             continue;
@@ -1314,7 +1323,7 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
 /* -------------------------------------------------------------------- */
 /*      Create destination feature.                                     */
 /* -------------------------------------------------------------------- */
-    poDstFeat = new OGRFeature( poDefn );
+    OGRFeature *poDstFeat = new OGRFeature( poDefn );
 
     poDstFeat->SetFID( poSrcFeat->GetFID() );
 
@@ -1330,8 +1339,6 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
     for( int iField = 0; iField < psSelectInfo->result_columns; iField++ )
     {
         swq_col_def *psColDef = psSelectInfo->column_defs + iField;
-        swq_expr_node *poResult;
-
         if( psColDef->field_index != -1 )
         {
             if( psColDef->field_type == SWQ_GEOMETRY ||
@@ -1342,8 +1349,9 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
             continue;
         }
 
-        poResult = psColDef->expr->Evaluate( OGRMultiFeatureFetcher,
-                                             (void *) &apoFeatures );
+        swq_expr_node *poResult =
+            psColDef->expr->Evaluate( OGRMultiFeatureFetcher,
+                                      (void *) &apoFeatures );
 
         if( poResult == NULL )
         {
@@ -1448,9 +1456,10 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
             poDstFeat->SetGeomField( iGeomField ++,
                                      poSrcFeat->GetGeomFieldRef(iSrcGeomField) );
         }
-        else if( psColDef->field_index >= iFIDFieldIndex &&
-                 psColDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
+        else if( psColDef->field_index >= iFIDFieldIndex )
         {
+            CPLAssert( psColDef->field_index <
+                                    iFIDFieldIndex + SPECIAL_FIELD_COUNT );
             switch (SpecialFieldTypes[psColDef->field_index - iFIDFieldIndex])
             {
               case SWQ_INTEGER:
@@ -1489,7 +1498,7 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
                 break;
 
               case SWQ_GEOMETRY:
-                  CPLAssert(0);
+                  CPLAssert(false);
                   break;
 
               default:
@@ -1503,7 +1512,7 @@ OGRFeature *OGRGenSQLResultsLayer::TranslateFeature( OGRFeature *poSrcFeat )
 /* -------------------------------------------------------------------- */
 /*      Copy values from any joined tables.                             */
 /* -------------------------------------------------------------------- */
-    for( iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
+    for( int iJoin = 0; iJoin < psSelectInfo->join_count; iJoin++ )
     {
         CPLString osFilter;
 
@@ -1546,14 +1555,29 @@ OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
 {
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
 
+    if( psSelectInfo->limit >= 0 &&
+        (nIteratedFeatures < 0 ? 0 : nIteratedFeatures) >= psSelectInfo->limit )
+        return NULL;
+
     CreateOrderByIndex();
+    if( panFIDIndex == NULL &&
+        nIteratedFeatures < 0 && psSelectInfo->offset > 0 &&
+        psSelectInfo->query_mode == SWQM_RECORDSET )
+    {
+        poSrcLayer->SetNextByIndex(psSelectInfo->offset);
+    }
+    if( nIteratedFeatures < 0 )
+        nIteratedFeatures = 0;
 
 /* -------------------------------------------------------------------- */
 /*      Handle summary sets.                                            */
 /* -------------------------------------------------------------------- */
     if( psSelectInfo->query_mode == SWQM_SUMMARY_RECORD
         || psSelectInfo->query_mode == SWQM_DISTINCT_LIST )
+    {
+        nIteratedFeatures ++;
         return GetFeature( nNextIndexFID++ );
+    }
 
     int bEvaluateSpatialFilter = MustEvaluateSpatialFilterOnGenSQL();
 
@@ -1562,10 +1586,10 @@ OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
     while( true )
     {
-        OGRFeature *poFeature;
+        OGRFeature *poFeature = NULL;
 
         if( panFIDIndex != NULL )
-            poFeature =  GetFeature( nNextIndexFID++ );
+            poFeature = GetFeature( nNextIndexFID++ );
         else
         {
             OGRFeature *poSrcFeat = poSrcLayer->GetNextFeature();
@@ -1584,7 +1608,10 @@ OGRFeature *OGRGenSQLResultsLayer::GetNextFeature()
             || m_poAttrQuery->Evaluate( poFeature )) &&
             (!bEvaluateSpatialFilter ||
              FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) )) )
+        {
+            nIteratedFeatures ++;
             return poFeature;
+        }
 
         delete poFeature;
     }
@@ -1622,18 +1649,61 @@ OGRFeature *OGRGenSQLResultsLayer::GetFeature( GIntBig nFID )
         if( !PrepareSummary() )
             return NULL;
 
-        swq_summary *psSummary = psSelectInfo->column_summary + 0;
-
-        if( psSummary == NULL )
-            return NULL;
-
-        if( nFID < 0 || nFID >= psSummary->count )
+        if( psSelectInfo->column_summary.empty() )
             return NULL;
 
-        if( psSummary->distinct_list[nFID] != NULL )
-            poSummaryFeature->SetField( 0, psSummary->distinct_list[nFID] );
+        swq_summary& oSummary = psSelectInfo->column_summary[0];
+        if( psSelectInfo->order_specs == 0 )
+        {
+            if( nFID < 0 || nFID >= static_cast<GIntBig>(
+                                    oSummary.oVectorDistinctValues.size()) )
+            {
+                return NULL;
+            }
+            const size_t nIdx = static_cast<size_t>(nFID);
+            if( oSummary.oVectorDistinctValues[nIdx] != SZ_OGR_NULL )
+            {
+                poSummaryFeature->SetField( 0,
+                            oSummary. oVectorDistinctValues[nIdx].c_str() );
+            }
+            else
+                poSummaryFeature->SetFieldNull( 0 );
+        }
         else
-            poSummaryFeature->UnsetField( 0 );
+        {
+            if( m_oDistinctList.empty() )
+            {
+                std::set<CPLString, swq_summary::Comparator>::const_iterator
+                    oIter = oSummary.oSetDistinctValues.begin();
+                std::set<CPLString, swq_summary::Comparator>::const_iterator
+                    oEnd = oSummary.oSetDistinctValues.end();
+                try
+                {
+                    m_oDistinctList.reserve(
+                                        oSummary.oSetDistinctValues.size() );
+                    for( ; oIter != oEnd; ++oIter )
+                    {
+                        m_oDistinctList.push_back( *oIter );
+                    }
+                }
+                catch( std::bad_alloc& )
+                {
+                    return NULL;
+                }
+                oSummary.oSetDistinctValues.clear();
+            }
+
+            if( nFID < 0 ||
+                nFID >= static_cast<GIntBig>(m_oDistinctList.size()) )
+                return NULL;
+
+            const size_t nIdx = static_cast<size_t>(nFID);
+            if( m_oDistinctList[nIdx] != SZ_OGR_NULL )
+                poSummaryFeature->SetField( 0, m_oDistinctList[nIdx].c_str() );
+            else
+                poSummaryFeature->SetFieldNull( 0 );
+        }
+
         poSummaryFeature->SetFID( nFID );
 
         return poSummaryFeature->Clone();
@@ -1645,7 +1715,7 @@ OGRFeature *OGRGenSQLResultsLayer::GetFeature( GIntBig nFID )
 /* -------------------------------------------------------------------- */
     if( panFIDIndex != NULL )
     {
-        if( nFID < 0 || nFID >= nIndexSize )
+        if( nFID < 0 || nFID >= static_cast<GIntBig>(nIndexSize) )
             return NULL;
         else
             nFID = panFIDIndex[nFID];
@@ -1655,12 +1725,11 @@ OGRFeature *OGRGenSQLResultsLayer::GetFeature( GIntBig nFID )
 /*      Handle request for random record.                               */
 /* -------------------------------------------------------------------- */
     OGRFeature *poSrcFeature = poSrcLayer->GetFeature( nFID );
-    OGRFeature *poResult;
 
     if( poSrcFeature == NULL )
         return NULL;
 
-    poResult = TranslateFeature( poSrcFeature );
+    OGRFeature *poResult = TranslateFeature( poSrcFeature );
     poResult->SetFID( nFID );
 
     delete poSrcFeature;
@@ -1706,6 +1775,129 @@ OGRFeatureDefn *OGRGenSQLResultsLayer::GetLayerDefn()
 }
 
 /************************************************************************/
+/*                         FreeIndexFields()                            */
+/************************************************************************/
+
+void OGRGenSQLResultsLayer::FreeIndexFields(OGRField *pasIndexFields,
+                                            size_t l_nIndexSize,
+                                            bool bFreeArray)
+{
+    swq_select *psSelectInfo = (swq_select *) pSelectInfo;
+    const int nOrderItems = psSelectInfo->order_specs;
+
+/* -------------------------------------------------------------------- */
+/*      Free the key field values.                                      */
+/* -------------------------------------------------------------------- */
+    for( int iKey = 0; iKey < nOrderItems; iKey++ )
+    {
+        swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
+
+        if ( psKeyDef->field_index >= iFIDFieldIndex )
+        {
+            CPLAssert( psKeyDef->field_index <
+                                    iFIDFieldIndex + SPECIAL_FIELD_COUNT );
+            /* warning: only special fields of type string should be deallocated */
+            if (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex] == SWQ_STRING)
+            {
+                for( size_t i = 0; i < l_nIndexSize; i++ )
+                {
+                    OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
+                    CPLFree( psField->String );
+                }
+            }
+            continue;
+        }
+
+        OGRFieldDefn *poFDefn =
+            poSrcLayer->GetLayerDefn()->GetFieldDefn( psKeyDef->field_index );
+
+        if( poFDefn->GetType() == OFTString )
+        {
+            for( size_t i = 0; i < l_nIndexSize; i++ )
+            {
+                OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
+
+                if( !OGR_RawField_IsUnset(psField) &&
+                    !OGR_RawField_IsNull(psField) )
+                    CPLFree( psField->String );
+            }
+        }
+    }
+
+    if( bFreeArray )
+        VSIFree(pasIndexFields);
+}
+
+/************************************************************************/
+/*                         ReadIndexFields()                            */
+/************************************************************************/
+
+void OGRGenSQLResultsLayer::ReadIndexFields( OGRFeature* poSrcFeat,
+                                             int nOrderItems,
+                                             OGRField *pasIndexFields )
+{
+    swq_select *psSelectInfo = (swq_select *) pSelectInfo;
+    for( int iKey = 0; iKey < nOrderItems; iKey++ )
+    {
+        const swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
+        OGRField *psDstField = pasIndexFields + iKey;
+
+        if ( psKeyDef->field_index >= iFIDFieldIndex)
+        {
+            CPLAssert( psKeyDef->field_index <
+                                iFIDFieldIndex + SPECIAL_FIELD_COUNT );
+
+            switch (SpecialFieldTypes[
+                            psKeyDef->field_index - iFIDFieldIndex])
+            {
+                case SWQ_INTEGER:
+                case SWQ_INTEGER64:
+                // Yes, store Integer as Integer64.
+                // This is consistent with the test in Compare()
+                psDstField->Integer64 =
+                    poSrcFeat->GetFieldAsInteger64(
+                        psKeyDef->field_index);
+                break;
+
+                case SWQ_FLOAT:
+                psDstField->Real =
+                    poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
+                break;
+
+                default:
+                psDstField->String = CPLStrdup(
+                    poSrcFeat->GetFieldAsString(
+                        psKeyDef->field_index) );
+                break;
+            }
+
+            continue;
+        }
+
+        OGRFieldDefn *poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
+            psKeyDef->field_index );
+
+        OGRField *psSrcField =
+            poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
+
+        if( poFDefn->GetType() == OFTInteger
+            || poFDefn->GetType() == OFTInteger64
+            || poFDefn->GetType() == OFTReal
+            || poFDefn->GetType() == OFTDate
+            || poFDefn->GetType() == OFTTime
+            || poFDefn->GetType() == OFTDateTime)
+            memcpy( psDstField, psSrcField, sizeof(OGRField) );
+        else if( poFDefn->GetType() == OFTString )
+        {
+            if( poSrcFeat->IsFieldSetAndNotNull( psKeyDef->field_index ) )
+                psDstField->String = CPLStrdup( psSrcField->String );
+            else
+                memcpy( psDstField, psSrcField, sizeof(OGRField) );
+        }
+    }
+}
+
+/************************************************************************/
 /*                         CreateOrderByIndex()                         */
 /*                                                                      */
 /*      This method is responsible for creating an index providing      */
@@ -1726,10 +1918,7 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
 
 {
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
-    OGRField *pasIndexFields;
-    GIntBig      i;
-    int nOrderItems = psSelectInfo->order_specs;
-    GIntBig *panFIDList;
+    const int nOrderItems = psSelectInfo->order_specs;
 
     if( ! (psSelectInfo->order_specs > 0
            && psSelectInfo->query_mode == SWQM_RECORDSET
@@ -1744,118 +1933,125 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
     ResetReading();
 
 /* -------------------------------------------------------------------- */
+/*      Optimize (memory-wise) ORDER BY ... LIMIT 1 [OFFSET 0] case.    */
+/* -------------------------------------------------------------------- */
+    if( psSelectInfo->offset == 0 && psSelectInfo->limit == 1 )
+    {
+        OGRFeature* poSrcFeat = poSrcLayer->GetNextFeature();
+        if( poSrcFeat == NULL )
+        {
+            panFIDIndex = NULL;
+            nIndexSize = 0;
+            return;
+        }
+
+        OGRField *pasCurrentFields = static_cast<OGRField *>(
+                                    CPLCalloc(sizeof(OGRField), nOrderItems));
+        OGRField *pasBestFields = static_cast<OGRField *>(
+                                    CPLCalloc(sizeof(OGRField), nOrderItems));
+        GIntBig nBestFID = poSrcFeat->GetFID();
+        ReadIndexFields( poSrcFeat, nOrderItems, pasBestFields);
+        delete poSrcFeat;
+        while( (poSrcFeat = poSrcLayer->GetNextFeature()) != NULL )
+        {
+            ReadIndexFields( poSrcFeat, nOrderItems, pasCurrentFields);
+            if( Compare( pasCurrentFields, pasBestFields ) < 0 )
+            {
+                nBestFID = poSrcFeat->GetFID();
+                FreeIndexFields( pasBestFields, 1, false);
+                memcpy( pasBestFields, pasCurrentFields,
+                        sizeof(OGRField) * nOrderItems );
+            }
+            else
+            {
+                FreeIndexFields( pasCurrentFields, 1, false);
+            }
+            memset( pasCurrentFields, 0, sizeof(OGRField) * nOrderItems );
+            delete poSrcFeat;
+        }
+        VSIFree( pasCurrentFields );
+        FreeIndexFields( pasBestFields, 1 );
+        panFIDIndex = static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig)));
+        panFIDIndex[0] = nBestFID;
+        nIndexSize = 1;
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
 /*      Allocate set of key values, and the output index.               */
 /* -------------------------------------------------------------------- */
     size_t nFeaturesAlloc = 100;
 
     panFIDIndex = NULL;
-    pasIndexFields = (OGRField *)
-        CPLCalloc(sizeof(OGRField), nOrderItems * nFeaturesAlloc);
-    panFIDList = (GIntBig *) CPLMalloc(sizeof(GIntBig) * nFeaturesAlloc);
+    OGRField *pasIndexFields = static_cast<OGRField *>(
+        CPLCalloc(sizeof(OGRField), nOrderItems * nFeaturesAlloc));
+    GIntBig *panFIDList = static_cast<GIntBig *>(
+        CPLMalloc(sizeof(GIntBig) * nFeaturesAlloc));
 
 /* -------------------------------------------------------------------- */
 /*      Read in all the key values.                                     */
 /* -------------------------------------------------------------------- */
-    OGRFeature *poSrcFeat;
+    OGRFeature *poSrcFeat = NULL;
     nIndexSize = 0;
 
     while( (poSrcFeat = poSrcLayer->GetNextFeature()) != NULL )
     {
-        int iKey;
-
-        if ((size_t)nIndexSize == nFeaturesAlloc)
-        {
-            GIntBig nNewFeaturesAlloc = (nFeaturesAlloc * 4) / 3;
-            if( (GIntBig)(size_t)(sizeof(OGRField) * nOrderItems * nNewFeaturesAlloc) !=
-                    (GIntBig)sizeof(OGRField) * nOrderItems * nNewFeaturesAlloc )
+        if (nIndexSize == nFeaturesAlloc)
+        {
+            GUIntBig nNewFeaturesAlloc = static_cast<GUIntBig>(nFeaturesAlloc)
+                                                        + nFeaturesAlloc / 3;
+            if( static_cast<size_t>(nNewFeaturesAlloc) != nNewFeaturesAlloc ||
+                static_cast<size_t>(sizeof(OGRField) * nOrderItems *
+                                    nNewFeaturesAlloc) !=
+                static_cast<GUIntBig>(sizeof(OGRField)) * nOrderItems *
+                nNewFeaturesAlloc )
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate pasIndexFields");
-                VSIFree(pasIndexFields);
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot allocate pasIndexFields");
+                FreeIndexFields( pasIndexFields, nIndexSize );
                 VSIFree(panFIDList);
                 nIndexSize = 0;
+                delete poSrcFeat;
                 return;
             }
             OGRField* pasNewIndexFields = (OGRField *)
                 VSI_REALLOC_VERBOSE(pasIndexFields,
-                           sizeof(OGRField) * nOrderItems * (size_t)nNewFeaturesAlloc);
+                           sizeof(OGRField) * nOrderItems *
+                           static_cast<size_t>(nNewFeaturesAlloc));
             if (pasNewIndexFields == NULL)
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate pasIndexFields");
-                VSIFree(pasIndexFields);
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Cannot allocate pasIndexFields");
+                FreeIndexFields( pasIndexFields, nIndexSize );
                 VSIFree(panFIDList);
                 nIndexSize = 0;
+                delete poSrcFeat;
                 return;
             }
             pasIndexFields = pasNewIndexFields;
 
             GIntBig* panNewFIDList = (GIntBig *)
-                VSI_REALLOC_VERBOSE(panFIDList, sizeof(GIntBig) *  (size_t)nNewFeaturesAlloc);
+                VSI_REALLOC_VERBOSE(panFIDList, sizeof(GIntBig) *
+                                    static_cast<size_t>(nNewFeaturesAlloc));
             if (panNewFIDList == NULL)
             {
-                VSIFree(pasIndexFields);
+                FreeIndexFields( pasIndexFields, nIndexSize );
                 VSIFree(panFIDList);
                 nIndexSize = 0;
+                delete poSrcFeat;
                 return;
             }
             panFIDList = panNewFIDList;
 
             memset(pasIndexFields + nFeaturesAlloc, 0,
-                   sizeof(OGRField) * nOrderItems * (size_t)(nNewFeaturesAlloc - nFeaturesAlloc));
+                   sizeof(OGRField) * nOrderItems *
+                   static_cast<size_t>(nNewFeaturesAlloc - nFeaturesAlloc));
 
-            nFeaturesAlloc = (size_t)nNewFeaturesAlloc;
+            nFeaturesAlloc = static_cast<size_t>(nNewFeaturesAlloc);
         }
 
-        for( iKey = 0; iKey < nOrderItems; iKey++ )
-        {
-            swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
-            OGRFieldDefn *poFDefn;
-            OGRField *psSrcField, *psDstField;
-
-            psDstField = pasIndexFields + nIndexSize * nOrderItems + iKey;
-
-            if ( psKeyDef->field_index >= iFIDFieldIndex)
-            {
-                if ( psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
-                {
-                    switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
-                    {
-                      case SWQ_INTEGER:
-                      case SWQ_INTEGER64:
-                        psDstField->Integer64 = poSrcFeat->GetFieldAsInteger64(psKeyDef->field_index);
-                        break;
-
-                      case SWQ_FLOAT:
-                        psDstField->Real = poSrcFeat->GetFieldAsDouble(psKeyDef->field_index);
-                        break;
-
-                      default:
-                        psDstField->String = CPLStrdup( poSrcFeat->GetFieldAsString(psKeyDef->field_index) );
-                        break;
-                    }
-                }
-                continue;
-            }
-
-            poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
-                psKeyDef->field_index );
-
-            psSrcField = poSrcFeat->GetRawFieldRef( psKeyDef->field_index );
-
-            if( poFDefn->GetType() == OFTInteger
-                || poFDefn->GetType() == OFTInteger64
-                || poFDefn->GetType() == OFTReal
-                || poFDefn->GetType() == OFTDate
-                || poFDefn->GetType() == OFTTime
-                || poFDefn->GetType() == OFTDateTime)
-                memcpy( psDstField, psSrcField, sizeof(OGRField) );
-            else if( poFDefn->GetType() == OFTString )
-            {
-                if( poSrcFeat->IsFieldSet( psKeyDef->field_index ) )
-                    psDstField->String = CPLStrdup( psSrcField->String );
-                else
-                    memcpy( psDstField, psSrcField, sizeof(OGRField) );
-            }
-        }
+        ReadIndexFields( poSrcFeat, nOrderItems,
+                         pasIndexFields + nIndexSize * nOrderItems );
 
         panFIDList[nIndexSize] = poSrcFeat->GetFID();
         delete poSrcFeat;
@@ -1868,23 +2064,26 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
 /* -------------------------------------------------------------------- */
 /*      Initialize panFIDIndex                                          */
 /* -------------------------------------------------------------------- */
-    panFIDIndex = (GIntBig *) VSI_MALLOC_VERBOSE(sizeof(GIntBig) * (size_t)nIndexSize);
+    panFIDIndex = (GIntBig *) VSI_MALLOC_VERBOSE(sizeof(GIntBig) * nIndexSize);
     if( panFIDIndex == NULL )
     {
-        VSIFree(pasIndexFields);
+        FreeIndexFields( pasIndexFields, nIndexSize );
         VSIFree(panFIDList);
         nIndexSize = 0;
         return;
     }
-    for( i = 0; i < nIndexSize; i++ )
-        panFIDIndex[i] = i;
+    for( size_t i = 0; i < nIndexSize; i++ )
+        panFIDIndex[i] = static_cast<GIntBig>(i);
 
 /* -------------------------------------------------------------------- */
 /*      Quick sort the records.                                         */
 /* -------------------------------------------------------------------- */
-    if( !SortIndexSection( pasIndexFields, 0, nIndexSize ) )
+
+    GIntBig *panMerged = (GIntBig *)
+        VSI_MALLOC_VERBOSE( sizeof(GIntBig) * nIndexSize );
+    if( panMerged == NULL )
     {
-        VSIFree(pasIndexFields);
+        FreeIndexFields( pasIndexFields, nIndexSize );
         VSIFree(panFIDList);
         nIndexSize = 0;
         VSIFree(panFIDIndex);
@@ -1892,59 +2091,22 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
         return;
     }
 
+    SortIndexSection( pasIndexFields, panMerged, 0, nIndexSize );
+    VSIFree( panMerged );
+
 /* -------------------------------------------------------------------- */
 /*      Rework the FID map to map to real FIDs.                         */
 /* -------------------------------------------------------------------- */
-    int bAlreadySorted = TRUE;
-    for( i = 0; i < nIndexSize; i++ )
+    bool bAlreadySorted = true;
+    for( size_t i = 0; i < nIndexSize; i++ )
     {
-        if (panFIDIndex[i] != i)
-            bAlreadySorted = FALSE;
+        if (panFIDIndex[i] != static_cast<GIntBig>(i))
+            bAlreadySorted = false;
         panFIDIndex[i] = panFIDList[panFIDIndex[i]];
     }
 
     CPLFree( panFIDList );
-
-/* -------------------------------------------------------------------- */
-/*      Free the key field values.                                      */
-/* -------------------------------------------------------------------- */
-    for( int iKey = 0; iKey < nOrderItems; iKey++ )
-    {
-        swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
-        OGRFieldDefn *poFDefn;
-
-        if ( psKeyDef->field_index >= iFIDFieldIndex &&
-            psKeyDef->field_index < iFIDFieldIndex + SPECIAL_FIELD_COUNT )
-        {
-            /* warning: only special fields of type string should be deallocated */
-            if (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex] == SWQ_STRING)
-            {
-                for( i = 0; i < nIndexSize; i++ )
-                {
-                    OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
-                    CPLFree( psField->String );
-                }
-            }
-            continue;
-        }
-
-        poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
-            psKeyDef->field_index );
-
-        if( poFDefn->GetType() == OFTString )
-        {
-            for( i = 0; i < nIndexSize; i++ )
-            {
-                OGRField *psField = pasIndexFields + iKey + i * nOrderItems;
-
-                if( psField->Set.nMarker1 != OGRUnsetMarker
-                    || psField->Set.nMarker2 != OGRUnsetMarker )
-                    CPLFree( psField->String );
-            }
-        }
-    }
-
-    CPLFree( pasIndexFields );
+    FreeIndexFields( pasIndexFields, nIndexSize );
 
     /* If it is already sorted, then free than panFIDIndex array */
     /* so that GetNextFeature() can call a sequential GetNextFeature() */
@@ -1968,73 +2130,78 @@ void OGRGenSQLResultsLayer::CreateOrderByIndex()
 /*      Sort the records in a section of the index.                     */
 /************************************************************************/
 
-int OGRGenSQLResultsLayer::SortIndexSection( OGRField *pasIndexFields,
-                                              GIntBig nStart, GIntBig nEntries )
+void OGRGenSQLResultsLayer::SortIndexSection( const OGRField *pasIndexFields,
+                                              GIntBig *panMerged,
+                                              size_t nStart, size_t nEntries )
 
 {
     if( nEntries < 2 )
-        return TRUE;
+        return;
 
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
-    int      nOrderItems = psSelectInfo->order_specs;
+    const int   nOrderItems = psSelectInfo->order_specs;
 
-    GIntBig nFirstGroup = nEntries / 2;
-    GIntBig nFirstStart = nStart;
-    GIntBig nSecondGroup = nEntries - nFirstGroup;
-    GIntBig nSecondStart = nStart + nFirstGroup;
-    GIntBig iMerge = 0;
-    GIntBig *panMerged;
+    size_t nFirstGroup = nEntries / 2;
+    size_t nFirstStart = nStart;
+    size_t nSecondGroup = nEntries - nFirstGroup;
+    size_t nSecondStart = nStart + nFirstGroup;
 
-    if( !SortIndexSection( pasIndexFields, nFirstStart, nFirstGroup ) ||
-        !SortIndexSection( pasIndexFields, nSecondStart, nSecondGroup ) )
-        return FALSE;
-
-    panMerged = (GIntBig *) VSI_MALLOC_VERBOSE( sizeof(GIntBig) * (size_t)nEntries );
-    if( panMerged == NULL )
-    {
-        return FALSE;
-    }
+    SortIndexSection( pasIndexFields, panMerged, nFirstStart,
+                      nFirstGroup );
+    SortIndexSection( pasIndexFields, panMerged, nSecondStart,
+                      nSecondGroup );
 
-    while( iMerge < nEntries )
+    for( size_t iMerge = 0; iMerge < nEntries; ++iMerge )
     {
-        int  nResult;
+        int  nResult = 0;
 
         if( nFirstGroup == 0 )
-            nResult = -1;
-        else if( nSecondGroup == 0 )
             nResult = 1;
+        else if( nSecondGroup == 0 )
+            nResult = -1;
         else
             nResult = Compare( pasIndexFields
                                + panFIDIndex[nFirstStart] * nOrderItems,
                                pasIndexFields
                                + panFIDIndex[nSecondStart] * nOrderItems );
 
-        if( nResult < 0 )
+        if( nResult > 0 )
         {
-            panMerged[iMerge++] = panFIDIndex[nSecondStart++];
+            panMerged[iMerge] = panFIDIndex[nSecondStart];
+            nSecondStart++;
             nSecondGroup--;
         }
         else
         {
-            panMerged[iMerge++] = panFIDIndex[nFirstStart++];
+            panMerged[iMerge] = panFIDIndex[nFirstStart];
+            nFirstStart++;
             nFirstGroup--;
         }
     }
 
     /* Copy the merge list back into the main index */
+    memcpy( panFIDIndex + nStart, panMerged, sizeof(GIntBig) * nEntries );
+}
 
-    memcpy( panFIDIndex + nStart, panMerged, sizeof(GIntBig) * (size_t)nEntries );
-    CPLFree( panMerged );
+/************************************************************************/
+/*                           ComparePrimitive()                         */
+/************************************************************************/
 
-    return TRUE;
+template<class T> static inline int ComparePrimitive(const T& a, const T& b)
+{
+    if( a < b )
+        return -1;
+    if( a > b )
+        return 1;
+    return 0;
 }
 
 /************************************************************************/
 /*                              Compare()                               */
 /************************************************************************/
 
-int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
-                                    OGRField *pasSecondTuple )
+int OGRGenSQLResultsLayer::Compare( const OGRField *pasFirstTuple,
+                                    const OGRField *pasSecondTuple )
 
 {
     swq_select *psSelectInfo = (swq_select *) pSelectInfo;
@@ -2043,49 +2210,44 @@ int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
     for( iKey = 0; nResult == 0 && iKey < psSelectInfo->order_specs; iKey++ )
     {
         swq_order_def *psKeyDef = psSelectInfo->order_defs + iKey;
-        OGRFieldDefn *poFDefn;
+        OGRFieldDefn *poFDefn = NULL;
 
-        if( psKeyDef->field_index >= iFIDFieldIndex + SPECIAL_FIELD_COUNT )
-        {
-            CPLAssert( FALSE );
-            return 0;
-        }
-        else if( psKeyDef->field_index >= iFIDFieldIndex )
+        if( psKeyDef->field_index >= iFIDFieldIndex )
             poFDefn = NULL;
         else
             poFDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn(
                 psKeyDef->field_index );
 
-        if( pasFirstTuple[iKey].Set.nMarker1 == OGRUnsetMarker
-             && pasFirstTuple[iKey].Set.nMarker2 == OGRUnsetMarker )
+        if( OGR_RawField_IsUnset(&pasFirstTuple[iKey]) ||
+            OGR_RawField_IsNull(&pasFirstTuple[iKey]) )
         {
-            if( pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker
-                && pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker )
+            if( OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
+                OGR_RawField_IsNull(&pasSecondTuple[iKey]) )
                 nResult = 0;
             else
                 nResult = -1;
         }
-        else if ( pasSecondTuple[iKey].Set.nMarker1 == OGRUnsetMarker
-                && pasSecondTuple[iKey].Set.nMarker2 == OGRUnsetMarker )
+        else if ( OGR_RawField_IsUnset(&pasSecondTuple[iKey]) ||
+                  OGR_RawField_IsNull(&pasSecondTuple[iKey]) )
         {
             nResult = 1;
         }
         else if ( poFDefn == NULL )
         {
+            CPLAssert( psKeyDef->field_index <
+                                    iFIDFieldIndex + SPECIAL_FIELD_COUNT );
             switch (SpecialFieldTypes[psKeyDef->field_index - iFIDFieldIndex])
             {
               case SWQ_INTEGER:
+                  // Yes, read Integer in Integer64.
+                  // This is consistent with what is done ReadIndexFields()
               case SWQ_INTEGER64:
-                if( pasFirstTuple[iKey].Integer64 < pasSecondTuple[iKey].Integer64 )
-                    nResult = -1;
-                else if( pasFirstTuple[iKey].Integer64 > pasSecondTuple[iKey].Integer64 )
-                    nResult = 1;
+                nResult = ComparePrimitive( pasFirstTuple[iKey].Integer64,
+                                            pasSecondTuple[iKey].Integer64 );
                 break;
               case SWQ_FLOAT:
-                if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
-                    nResult = -1;
-                else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
-                    nResult = 1;
+                nResult = ComparePrimitive( pasFirstTuple[iKey].Real,
+                                            pasSecondTuple[iKey].Real );
                 break;
               case SWQ_STRING:
                 nResult = strcmp(pasFirstTuple[iKey].String,
@@ -2093,35 +2255,29 @@ int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
                 break;
 
               default:
-                CPLAssert( FALSE );
+                CPLAssert( false );
                 nResult = 0;
             }
         }
         else if( poFDefn->GetType() == OFTInteger )
         {
-            if( pasFirstTuple[iKey].Integer < pasSecondTuple[iKey].Integer )
-                nResult = -1;
-            else if( pasFirstTuple[iKey].Integer
-                     > pasSecondTuple[iKey].Integer )
-                nResult = 1;
+            nResult = ComparePrimitive( pasFirstTuple[iKey].Integer,
+                                        pasSecondTuple[iKey].Integer );
         }
         else if( poFDefn->GetType() == OFTInteger64 )
         {
-            if( pasFirstTuple[iKey].Integer64 < pasSecondTuple[iKey].Integer64 )
-                nResult = -1;
-            else if( pasFirstTuple[iKey].Integer64
-                     > pasSecondTuple[iKey].Integer64 )
-                nResult = 1;
+            nResult = ComparePrimitive( pasFirstTuple[iKey].Integer64,
+                                        pasSecondTuple[iKey].Integer64 );
         }
         else if( poFDefn->GetType() == OFTString )
+        {
             nResult = strcmp(pasFirstTuple[iKey].String,
                              pasSecondTuple[iKey].String);
+        }
         else if( poFDefn->GetType() == OFTReal )
         {
-            if( pasFirstTuple[iKey].Real < pasSecondTuple[iKey].Real )
-                nResult = -1;
-            else if( pasFirstTuple[iKey].Real > pasSecondTuple[iKey].Real )
-                nResult = 1;
+            nResult = ComparePrimitive( pasFirstTuple[iKey].Real,
+                                        pasSecondTuple[iKey].Real );
         }
         else if( poFDefn->GetType() == OFTDate ||
                  poFDefn->GetType() == OFTTime ||
@@ -2131,14 +2287,13 @@ int OGRGenSQLResultsLayer::Compare( OGRField *pasFirstTuple,
                                      &pasSecondTuple[iKey]);
         }
 
-        if( psKeyDef->ascending_flag )
+        if( !(psKeyDef->ascending_flag) )
             nResult *= -1;
     }
 
     return nResult;
 }
 
-
 /************************************************************************/
 /*                         AddFieldDefnToSet()                          */
 /************************************************************************/
@@ -2221,9 +2376,10 @@ void OGRGenSQLResultsLayer::FindAndSetIgnoredFields()
     {
         OGRLayer* poLayer = papoTableLayers[iTable];
         OGRFeatureDefn *poSrcFDefn = poLayer->GetLayerDefn();
-        int iSrcField;
         char** papszIgnoredFields = NULL;
-        for(iSrcField=0;iSrcField<poSrcFDefn->GetFieldCount();iSrcField++)
+        for( int iSrcField = 0;
+             iSrcField<poSrcFDefn->GetFieldCount();
+             iSrcField++ )
         {
             OGRFieldDefn* poFDefn = poSrcFDefn->GetFieldDefn(iSrcField);
             if (CPLHashSetLookup(hSet,poFDefn) == NULL)
@@ -2275,3 +2431,5 @@ void OGRGenSQLResultsLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGe
     else
         OGRLayer::SetSpatialFilter(iGeomField, poGeom);
 }
+
+//! @endcond
diff --git a/ogr/ogrsf_frmts/generic/ogr_gensql.h b/ogr/ogrsf_frmts/generic/ogr_gensql.h
index 07773e3..3fff15e 100644
--- a/ogr/ogrsf_frmts/generic/ogr_gensql.h
+++ b/ogr/ogrsf_frmts/generic/ogr_gensql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gensql.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_gensql.h 37576 2017-03-03 14:29:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to generic implementation of ExecuteSQL().
@@ -34,6 +34,11 @@
 #include "ogrsf_frmts.h"
 #include "swq.h"
 #include "cpl_hash_set.h"
+#include "cpl_string.h"
+
+#include <vector>
+
+/*! @cond Doxygen_Suppress */
 
 #define GEOM_FIELD_INDEX_TO_ALL_FIELD_INDEX(poFDefn, iGeom) \
     ((poFDefn)->GetFieldCount() + SPECIAL_FIELD_COUNT + (iGeom))
@@ -64,7 +69,7 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
 
     int        *panGeomFieldToSrcGeomField;
 
-    GIntBig     nIndexSize;
+    size_t      nIndexSize;
     GIntBig    *panFIDIndex;
     int         bOrderByValid;
 
@@ -76,13 +81,23 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
     int         nExtraDSCount;
     GDALDataset **papoExtraDS;
 
+    GIntBig     nIteratedFeatures;
+    std::vector<CPLString> m_oDistinctList;
+
     int         PrepareSummary();
 
     OGRFeature *TranslateFeature( OGRFeature * );
     void        CreateOrderByIndex();
-    int         SortIndexSection( OGRField *pasIndexFields,
-                                  GIntBig nStart, GIntBig nEntries );
-    int         Compare( OGRField *pasFirst, OGRField *pasSecond );
+    void        ReadIndexFields( OGRFeature* poSrcFeat,
+                                 int nOrderItems,
+                                 OGRField *pasIndexFields );
+    void        SortIndexSection( const OGRField *pasIndexFields,
+                                  GIntBig *panMerged,
+                                  size_t nStart, size_t nEntries );
+    void        FreeIndexFields(OGRField *pasIndexFields,
+                                size_t l_nIndexSize,
+                                bool bFreeArray = true);
+    int         Compare( const OGRField *pasFirst, const OGRField *pasSecond );
 
     void        ClearFilters();
     void        ApplyFiltersToSource();
@@ -105,24 +120,26 @@ class CPL_DLL OGRGenSQLResultsLayer : public OGRLayer
                                        const char *pszDialect );
     virtual     ~OGRGenSQLResultsLayer();
 
-    virtual OGRGeometry *GetSpatialFilter();
+    virtual OGRGeometry *GetSpatialFilter() override;
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
-    virtual OGRFeature *GetFeature( GIntBig nFID );
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
+    virtual OGRFeature *GetFeature( GIntBig nFID ) override;
 
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) { return GetExtent(0, psExtent, bForce); }
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry * poGeom ) { SetSpatialFilter(0, poGeom); }
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual void        SetSpatialFilter( OGRGeometry * poGeom ) override { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 };
 
+/*! @endcond */
+
 #endif /* ndef OGR_GENSQL_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp b/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp
index f60c411..58100a4 100644
--- a/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp
+++ b/ogr/ogrsf_frmts/generic/ogr_miattrind.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_miattrind.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements interface to MapInfo .ID files used as attribute
@@ -33,7 +32,7 @@
 #include "mitab/mitab_priv.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: ogr_miattrind.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogr_miattrind.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                            OGRMIAttrIndex                            */
@@ -58,14 +57,14 @@ public:
                ~OGRMIAttrIndex();
 
     GByte      *BuildKey( OGRField *psKey );
-    GIntBig     GetFirstMatch( OGRField *psKey );
-    GIntBig    *GetAllMatches( OGRField *psKey );
-    GIntBig    *GetAllMatches( OGRField *psKey, GIntBig* panFIDList, int* nFIDCount, int* nLength );
+    GIntBig     GetFirstMatch( OGRField *psKey ) override;
+    GIntBig    *GetAllMatches( OGRField *psKey ) override;
+    GIntBig    *GetAllMatches( OGRField *psKey, GIntBig* panFIDList, int* nFIDCount, int* nLength ) override;
 
-    OGRErr      AddEntry( OGRField *psKey, GIntBig nFID );
-    OGRErr      RemoveEntry( OGRField *psKey, GIntBig nFID );
+    OGRErr      AddEntry( OGRField *psKey, GIntBig nFID ) override;
+    OGRErr      RemoveEntry( OGRField *psKey, GIntBig nFID ) override;
 
-    OGRErr      Clear();
+    OGRErr      Clear() override;
 };
 
 /************************************************************************/
@@ -95,15 +94,15 @@ public:
     virtual     ~OGRMILayerAttrIndex();
 
     /* base class virtual methods */
-    OGRErr      Initialize( const char *pszIndexPath, OGRLayer * );
-    OGRErr      CreateIndex( int iField );
-    OGRErr      DropIndex( int iField );
-    OGRErr      IndexAllFeatures( int iField = -1 );
+    OGRErr      Initialize( const char *pszIndexPath, OGRLayer * ) override;
+    OGRErr      CreateIndex( int iField ) override;
+    OGRErr      DropIndex( int iField ) override;
+    OGRErr      IndexAllFeatures( int iField = -1 ) override;
 
-    OGRErr      AddToIndex( OGRFeature *poFeature, int iField = -1 );
-    OGRErr      RemoveFromIndex( OGRFeature *poFeature );
+    OGRErr      AddToIndex( OGRFeature *poFeature, int iField = -1 ) override;
+    OGRErr      RemoveFromIndex( OGRFeature *poFeature ) override;
 
-    OGRAttrIndex *GetFieldIndex( int iField );
+    OGRAttrIndex *GetFieldIndex( int iField ) override;
 
     /* custom to OGRMILayerAttrIndex */
     OGRErr      SaveConfigToXML();
@@ -118,17 +117,15 @@ public:
 /*                        OGRMILayerAttrIndex()                         */
 /************************************************************************/
 
-OGRMILayerAttrIndex::OGRMILayerAttrIndex()
-
-{
-    poINDFile = NULL;
-    nIndexCount = 0;
-    papoIndexList = NULL;
-    bUnlinkINDFile = FALSE;
-    bINDAsReadOnly = TRUE;
-    pszMIINDFilename = NULL;
-    pszMetadataFilename = NULL;
-}
+OGRMILayerAttrIndex::OGRMILayerAttrIndex() :
+    poINDFile(NULL),
+    nIndexCount(0),
+    papoIndexList(NULL),
+    pszMetadataFilename(NULL),
+    pszMIINDFilename(NULL),
+    bINDAsReadOnly(TRUE),
+    bUnlinkINDFile(FALSE)
+{}
 
 /************************************************************************/
 /*                        ~OGRMILayerAttrIndex()                        */
@@ -239,20 +236,16 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML)
 /* -------------------------------------------------------------------- */
 /*      Process each attrindex.                                         */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psAttrIndex;
-
-    for( psAttrIndex = psRoot->psChild;
+    for( CPLXMLNode *psAttrIndex = psRoot->psChild;
          psAttrIndex != NULL;
          psAttrIndex = psAttrIndex->psNext )
     {
-        int iField, iIndexIndex;
-
         if( psAttrIndex->eType != CXT_Element
             || !EQUAL(psAttrIndex->pszValue,"OGRMIAttrIndex") )
             continue;
 
-        iField = atoi(CPLGetXMLValue(psAttrIndex,"FieldIndex","-1"));
-        iIndexIndex = atoi(CPLGetXMLValue(psAttrIndex,"IndexIndex","-1"));
+        int iField = atoi(CPLGetXMLValue(psAttrIndex,"FieldIndex","-1"));
+        int iIndexIndex = atoi(CPLGetXMLValue(psAttrIndex,"IndexIndex","-1"));
 
         if( iField == -1 || iIndexIndex == -1 )
         {
@@ -276,16 +269,12 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML(const char* pszRawXML)
 
 OGRErr OGRMILayerAttrIndex::LoadConfigFromXML()
 {
-    VSILFILE *fp;
-    vsi_l_offset  nXMLSize;
-    char *pszRawXML;
-
     CPLAssert( poINDFile == NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Read the XML file.                                              */
 /* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszMetadataFilename, "rb" );
+    VSILFILE *fp = VSIFOpenL( pszMetadataFilename, "rb" );
     if( fp == NULL )
         return OGRERR_FAILURE;
 
@@ -294,7 +283,7 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML()
         VSIFCloseL(fp);
         return OGRERR_FAILURE;
     }
-    nXMLSize = VSIFTellL( fp );
+    const vsi_l_offset nXMLSize = VSIFTellL( fp );
     if( nXMLSize > 10 * 1024 * 1024 ||
         VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
     {
@@ -302,7 +291,7 @@ OGRErr OGRMILayerAttrIndex::LoadConfigFromXML()
         return OGRERR_FAILURE;
     }
 
-    pszRawXML = (char *) CPLMalloc((size_t)nXMLSize+1);
+    char *pszRawXML = (char *) CPLMalloc((size_t)nXMLSize+1);
     pszRawXML[nXMLSize] = '\0';
     if( VSIFReadL( pszRawXML, (size_t)nXMLSize, 1, fp ) != 1 )
     {
@@ -331,9 +320,8 @@ OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
 /* -------------------------------------------------------------------- */
 /*      Create the XML tree corresponding to this layer.                */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psRoot;
-
-    psRoot = CPLCreateXMLNode( NULL, CXT_Element, "OGRMILayerAttrIndex" );
+    CPLXMLNode *psRoot =
+        CPLCreateXMLNode( NULL, CXT_Element, "OGRMILayerAttrIndex" );
 
     CPLCreateXMLElementAndValue( psRoot, "MIIDFilename",
                                  CPLGetFilename( pszMIINDFilename ) );
@@ -341,9 +329,8 @@ OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
     for( int i = 0; i < nIndexCount; i++ )
     {
         OGRMIAttrIndex *poAI = papoIndexList[i];
-        CPLXMLNode *psIndex;
-
-        psIndex = CPLCreateXMLNode( psRoot, CXT_Element, "OGRMIAttrIndex" );
+        CPLXMLNode *psIndex =
+            CPLCreateXMLNode( psRoot, CXT_Element, "OGRMIAttrIndex" );
 
         CPLCreateXMLElementAndValue( psIndex, "FieldIndex",
                                      CPLSPrintf( "%d", poAI->iField ) );
@@ -351,7 +338,6 @@ OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
         CPLCreateXMLElementAndValue( psIndex, "FieldName",
                                      poLayer->GetLayerDefn()->GetFieldDefn(poAI->iField)->GetNameRef() );
 
-
         CPLCreateXMLElementAndValue( psIndex, "IndexIndex",
                                      CPLSPrintf( "%d", poAI->iIndex ) );
     }
@@ -360,11 +346,10 @@ OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
 /*      Save it.                                                        */
 /* -------------------------------------------------------------------- */
     char *pszRawXML = CPLSerializeXMLTree( psRoot );
-    FILE *fp;
 
     CPLDestroyXMLNode( psRoot );
 
-    fp = VSIFOpen( pszMetadataFilename, "wb" );
+    FILE *fp = VSIFOpen( pszMetadataFilename, "wb" );
     if( fp == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -389,13 +374,12 @@ OGRErr OGRMILayerAttrIndex::SaveConfigToXML()
 OGRErr OGRMILayerAttrIndex::IndexAllFeatures( int iField )
 
 {
-    OGRFeature *poFeature;
-
     poLayer->ResetReading();
 
+    OGRFeature *poFeature = NULL;
     while( (poFeature = poLayer->GetNextFeature()) != NULL )
     {
-        OGRErr eErr = AddToIndex( poFeature, iField );
+        const OGRErr eErr = AddToIndex( poFeature, iField );
 
         delete poFeature;
 
@@ -514,9 +498,7 @@ OGRErr OGRMILayerAttrIndex::CreateIndex( int iField )
 /* -------------------------------------------------------------------- */
 /*      Create the index.                                               */
 /* -------------------------------------------------------------------- */
-    int iINDIndex;
-
-    iINDIndex = poINDFile->CreateIndex( eTABFT, nFieldWidth );
+    const int iINDIndex = poINDFile->CreateIndex( eTABFT, nFieldWidth );
 
     // CreateIndex() reports it's own errors.
     if( iINDIndex < 0 )
@@ -553,7 +535,6 @@ OGRErr OGRMILayerAttrIndex::DropIndex( int iField )
     {
         if( papoIndexList[i]->iField == iField )
             break;
-
     }
 
     if( i == nIndexCount )
@@ -648,7 +629,7 @@ OGRErr OGRMILayerAttrIndex::AddToIndex( OGRFeature *poFeature,
         if( iTargetField != -1 && iTargetField != iField )
             continue;
 
-        if( !poFeature->IsFieldSet( iField ) )
+        if( !poFeature->IsFieldSetAndNotNull( iField ) )
             continue;
 
         eErr =
@@ -692,16 +673,13 @@ OGRLayerAttrIndex *OGRCreateDefaultLayerIndex()
 /************************************************************************/
 
 OGRMIAttrIndex::OGRMIAttrIndex( OGRMILayerAttrIndex *poLayerIndex,
-                                int iIndexIn, int iFieldIn )
-
-{
-    iIndex = iIndexIn;
-    iField = iFieldIn;
-    poLIndex = poLayerIndex;
-    poINDFile = poLayerIndex->poINDFile;
-
-    poFldDefn = poLayerIndex->GetLayer()->GetLayerDefn()->GetFieldDefn(iField);
-}
+                                int iIndexIn, int iFieldIn ) :
+    iIndex(iIndexIn),
+    poINDFile(poLayerIndex->poINDFile),
+    poLIndex(poLayerIndex),
+    poFldDefn(poLayerIndex->GetLayer()->GetLayerDefn()->GetFieldDefn(iFieldIn)),
+    iField(iFieldIn)
+{}
 
 /************************************************************************/
 /*                          ~OGRMIAttrIndex()                           */
@@ -752,10 +730,11 @@ OGRErr OGRMIAttrIndex::RemoveEntry( OGRField * /*psKey*/, GIntBig /*nFID*/ )
 GByte *OGRMIAttrIndex::BuildKey( OGRField *psKey )
 
 {
+    GByte* ret = NULL;
     switch( poFldDefn->GetType() )
     {
       case OFTInteger:
-        return poINDFile->BuildKey( iIndex, psKey->Integer );
+        ret = poINDFile->BuildKey( iIndex, psKey->Integer );
         break;
 
       case OFTInteger64:
@@ -765,23 +744,23 @@ GByte *OGRMIAttrIndex::BuildKey( OGRField *psKey )
             CPLError(CE_Warning, CPLE_NotSupported,
                      "64bit integer value passed to OGRMIAttrIndex::BuildKey()");
         }
-        return poINDFile->BuildKey( iIndex, (int)psKey->Integer64 );
+        ret = poINDFile->BuildKey( iIndex, (int)psKey->Integer64 );
         break;
       }
 
       case OFTReal:
-        return poINDFile->BuildKey( iIndex, psKey->Real );
+        ret = poINDFile->BuildKey( iIndex, psKey->Real );
         break;
 
       case OFTString:
-        return poINDFile->BuildKey( iIndex, psKey->String );
+        ret = poINDFile->BuildKey( iIndex, psKey->String );
         break;
 
       default:
-        CPLAssert( FALSE );
-
-        return NULL;
+        CPLAssert( false );
+        break;
     }
+    return ret;
 }
 
 /************************************************************************/
@@ -792,9 +771,7 @@ GIntBig OGRMIAttrIndex::GetFirstMatch( OGRField *psKey )
 
 {
     GByte *pabyKey = BuildKey( psKey );
-    GIntBig nFID;
-
-    nFID = poINDFile->FindFirst( iIndex, pabyKey );
+    const GIntBig nFID = poINDFile->FindFirst( iIndex, pabyKey );
     if( nFID < 1 )
         return OGRNullFID;
     else
@@ -808,7 +785,6 @@ GIntBig OGRMIAttrIndex::GetFirstMatch( OGRField *psKey )
 GIntBig *OGRMIAttrIndex::GetAllMatches( OGRField *psKey, GIntBig* panFIDList, int* nFIDCount, int* nLength )
 {
     GByte *pabyKey = BuildKey( psKey );
-    GIntBig nFID;
 
     if (panFIDList == NULL)
     {
@@ -817,7 +793,7 @@ GIntBig *OGRMIAttrIndex::GetAllMatches( OGRField *psKey, GIntBig* panFIDList, in
         *nLength = 2;
     }
 
-    nFID = poINDFile->FindFirst( iIndex, pabyKey );
+    GIntBig nFID = poINDFile->FindFirst( iIndex, pabyKey );
     while( nFID > 0 )
     {
         if( *nFIDCount >= *nLength-1 )
diff --git a/ogr/ogrsf_frmts/generic/ogrdatasource.cpp b/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
index 3dfd661..301010c 100644
--- a/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the GDALDataset class.
@@ -32,26 +31,25 @@
 #include "ogr_api.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrdatasource.cpp 35172 2016-08-21 20:33:08Z goatbar $");
 
 /************************************************************************/
 /*                           ~OGRDataSource()                           */
 /************************************************************************/
 
-OGRDataSource::OGRDataSource()
-
-{
-}
+OGRDataSource::OGRDataSource() {}
 
 /************************************************************************/
 /*                         DestroyDataSource()                          */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 void OGRDataSource::DestroyDataSource( OGRDataSource *poDS )
 
 {
     delete poDS;
 }
+//! @endcond
 
 /************************************************************************/
 /*                           OGR_DS_Destroy()                           */
diff --git a/ogr/ogrsf_frmts/generic/ogreditablelayer.cpp b/ogr/ogrsf_frmts/generic/ogreditablelayer.cpp
index d0bad9e..fdfe1c1 100644
--- a/ogr/ogrsf_frmts/generic/ogreditablelayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogreditablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogreditablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGREditableLayer class
@@ -30,41 +29,45 @@
 #include "ogreditablelayer.h"
 #include "../mem/ogr_mem.h"
 
-CPL_CVSID("$Id: ogreditablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogreditablelayer.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+//! @cond Doxygen_Suppress
 
 /************************************************************************/
 /*                  ~IOGREditableLayerSynchronizer()                    */
 /************************************************************************/
 
-IOGREditableLayerSynchronizer::~IOGREditableLayerSynchronizer()
-{
-}
+IOGREditableLayerSynchronizer::~IOGREditableLayerSynchronizer() {}
 
 /************************************************************************/
 /*                          OGREditableLayer()                          */
 /************************************************************************/
 
-OGREditableLayer::OGREditableLayer(OGRLayer* poDecoratedLayer,
-                                   bool bTakeOwnershipDecoratedLayer,
-                                   IOGREditableLayerSynchronizer* poSynchronizer,
-                                   bool bTakeOwnershipSynchronizer):
+OGREditableLayer::OGREditableLayer(
+    OGRLayer* poDecoratedLayer,
+    bool bTakeOwnershipDecoratedLayer,
+    IOGREditableLayerSynchronizer* poSynchronizer,
+    bool bTakeOwnershipSynchronizer) :
     OGRLayerDecorator(poDecoratedLayer,
                       bTakeOwnershipDecoratedLayer),
     m_poSynchronizer(poSynchronizer),
     m_bTakeOwnershipSynchronizer(bTakeOwnershipSynchronizer),
+    m_poEditableFeatureDefn(poDecoratedLayer->GetLayerDefn()->Clone()),
     m_nNextFID(0),
+    m_poMemLayer(new OGRMemLayer( "", NULL, wkbNone )),
     m_bStructureModified(false),
     m_bSupportsCreateGeomField(false),
     m_bSupportsCurveGeometries(false)
 {
-    m_poEditableFeatureDefn = poDecoratedLayer->GetLayerDefn()->Clone();
     m_poEditableFeatureDefn->Reference();
 
-    m_poMemLayer = new OGRMemLayer( "", NULL, wkbNone );
-    for(int i=0;i<m_poEditableFeatureDefn->GetFieldCount();i++)
+    for( int i = 0; i < m_poEditableFeatureDefn->GetFieldCount(); i++ )
         m_poMemLayer->CreateField(m_poEditableFeatureDefn->GetFieldDefn(i));
-    for(int i=0;i<m_poEditableFeatureDefn->GetGeomFieldCount();i++)
-        m_poMemLayer->CreateGeomField(m_poEditableFeatureDefn->GetGeomFieldDefn(i));
+
+    for( int i = 0; i < m_poEditableFeatureDefn->GetGeomFieldCount(); i++ )
+        m_poMemLayer->
+            CreateGeomField(m_poEditableFeatureDefn->GetGeomFieldDefn(i));
+
     m_oIter = m_oSetCreated.begin();
 }
 
@@ -119,14 +122,14 @@ void OGREditableLayer::DetectNextFID()
         return;
     m_nNextFID = 0;
     m_poDecoratedLayer->ResetReading();
-    OGRFeature* poFeat;
+    OGRFeature* poFeat = NULL;
     while( (poFeat = m_poDecoratedLayer->GetNextFeature()) != NULL )
     {
         if( poFeat->GetFID() > m_nNextFID )
             m_nNextFID = poFeat->GetFID();
         delete poFeat;
     }
-    m_nNextFID ++;
+    m_nNextFID++;
 }
 
 /************************************************************************/
@@ -278,9 +281,9 @@ OGRFeature *OGREditableLayer::GetNextFeature()
 OGRErr      OGREditableLayer::SetNextByIndex( GIntBig nIndex )
 {
     if( m_poDecoratedLayer != NULL &&
-        m_oSetCreated.size() == 0 &&
-        m_oSetDeleted.size() == 0 &&
-        m_oSetEdited.size() == 0 )
+        m_oSetCreated.empty() &&
+        m_oSetDeleted.empty() &&
+        m_oSetEdited.empty() )
     {
         return m_poDecoratedLayer->SetNextByIndex(nIndex);
     }
@@ -296,7 +299,7 @@ OGRFeature *OGREditableLayer::GetFeature( GIntBig nFID )
 {
     if( !m_poDecoratedLayer ) return NULL;
 
-    OGRFeature* poSrcFeature;
+    OGRFeature* poSrcFeature = NULL;
     bool bHideDeletedFields = true;
     if( m_oSetCreated.find(nFID) != m_oSetCreated.end() ||
         m_oSetEdited.find(nFID) != m_oSetEdited.end() )
@@ -399,11 +402,13 @@ OGRErr      OGREditableLayer::DeleteFeature( GIntBig nFID )
     {
         eErr = OGRERR_NON_EXISTING_FEATURE;
     }
+    // cppcheck-suppress redundantIfRemove
     else if( m_oSetCreated.find(nFID) != m_oSetCreated.end() )
     {
         m_oSetCreated.erase(nFID);
         eErr = m_poMemLayer->DeleteFeature(nFID);
     }
+    // cppcheck-suppress redundantIfRemove
     else if( m_oSetEdited.find(nFID) != m_oSetEdited.end() )
     {
         m_oSetEdited.erase(nFID);
@@ -514,8 +519,8 @@ void        OGREditableLayer::SetSpatialFilter( int iGeomField, OGRGeometry * po
 /*                         SetSpatialFilterRect()                       */
 /************************************************************************/
 
-void        OGREditableLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
-                                                    double dfMaxX, double dfMaxY )
+void OGREditableLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
+                                             double dfMaxX, double dfMaxY )
 {
    return OGRLayer::SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
 }
@@ -524,23 +529,25 @@ void        OGREditableLayer::SetSpatialFilterRect( double dfMinX, double dfMinY
 /*                         SetSpatialFilterRect()                       */
 /************************************************************************/
 
-void        OGREditableLayer::SetSpatialFilterRect(
-                                  int iGeomField, double dfMinX, double dfMinY,
-                                  double dfMaxX, double dfMaxY )
+void OGREditableLayer::SetSpatialFilterRect(
+    int iGeomField, double dfMinX, double dfMinY,
+    double dfMaxX, double dfMaxY )
 {
-    return OGRLayer::SetSpatialFilterRect(iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
+    return
+      OGRLayer::SetSpatialFilterRect(iGeomField,
+                                     dfMinX, dfMinY, dfMaxX, dfMaxY);
 }
 
 /************************************************************************/
 /*                          GetFeatureCount()                           */
 /************************************************************************/
 
-GIntBig         OGREditableLayer::GetFeatureCount( int bForce )
+GIntBig OGREditableLayer::GetFeatureCount( int bForce )
 {
     if( !m_poDecoratedLayer ) return 0;
     if( m_poAttrQuery == NULL && m_poFilterGeom == NULL &&
-        m_oSetDeleted.size() == 0 &&
-        m_oSetEdited.size() == 0 )
+        m_oSetDeleted.empty() &&
+        m_oSetEdited.empty() )
     {
         GIntBig nFC = m_poDecoratedLayer->GetFeatureCount(bForce);
         if( nFC >= 0 )
@@ -570,8 +577,8 @@ OGRErr      OGREditableLayer::GetExtent(int iGeomField, OGREnvelope *psExtent,
 {
     if( !m_poDecoratedLayer ) return OGRERR_FAILURE;
     int iSrcGeomFieldIdx = GetSrcGeomFieldIndex(iGeomField);
-    if( iSrcGeomFieldIdx >= 0 && m_oSetEdited.size() == 0 &&
-        m_oSetDeleted.size() == 0 )
+    if( iSrcGeomFieldIdx >= 0 && m_oSetEdited.empty() &&
+        m_oSetDeleted.empty() )
     {
         OGRErr eErr = m_poDecoratedLayer->GetExtent(iSrcGeomFieldIdx, psExtent,
                                                     bForce);
@@ -760,8 +767,8 @@ OGRErr      OGREditableLayer::SyncToDisk()
     OGRErr eErr = m_poDecoratedLayer->SyncToDisk();
     if( eErr == OGRERR_NONE )
     {
-        if( m_oSetCreated.size() == 0 && m_oSetEdited.size() == 0 &&
-            m_oSetDeleted.size() == 0 && !m_bStructureModified )
+        if( m_oSetCreated.empty() && m_oSetEdited.empty() &&
+            m_oSetDeleted.empty() && !m_bStructureModified )
         {
             return OGRERR_NONE;
         }
@@ -814,3 +821,5 @@ const char *OGREditableLayer::GetGeometryColumn()
 {
     return OGRLayer::GetGeometryColumn();
 }
+
+//! @endcond
diff --git a/ogr/ogrsf_frmts/generic/ogreditablelayer.h b/ogr/ogrsf_frmts/generic/ogreditablelayer.h
index e3b092f..bb9f77d 100644
--- a/ogr/ogrsf_frmts/generic/ogreditablelayer.h
+++ b/ogr/ogrsf_frmts/generic/ogreditablelayer.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogreditablelayer.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogreditablelayer.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGREditableLayer class
@@ -30,6 +30,7 @@
 #ifndef OGREDITABLELAYER_H_INCLUDED
 #define OGREDITABLELAYER_H_INCLUDED
 
+//! @cond Doxygen_Suppress
 #include "ogrlayerdecorator.h"
 #include <set>
 
@@ -79,51 +80,52 @@ class CPL_DLL OGREditableLayer : public OGRLayerDecorator
     void                SetSupportsCreateGeomField(bool SupportsCreateGeomField);
     void                SetSupportsCurveGeometries(bool bSupportsCurveGeometries);
 
-    virtual OGRGeometry *GetSpatialFilter();
-    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual OGRGeometry *GetSpatialFilter() override;
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
     virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+                                              double dfMaxX, double dfMaxY ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
     virtual void        SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY );
+                                              double dfMaxX, double dfMaxY ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
-    virtual OGRFeature *GetFeature( GIntBig nFID );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
+    virtual OGRFeature *GetFeature( GIntBig nFID ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    virtual OGRwkbGeometryType GetGeomType();
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual OGRwkbGeometryType GetGeomType() override;
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+                                     int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
 
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
-                                         int bApproxOK = TRUE );
+                                         int bApproxOK = TRUE ) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction() override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetGeometryColumn() override;
 };
+//! @endcond
 
 #endif // OGREDITABLELAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
index 7833cae..b0c0112 100644
--- a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
+++ b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implement OGRDataSourceWithTransaction class
@@ -32,7 +31,7 @@
 #include <map>
 #include <set>
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogremulatedtransaction.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 class OGRDataSourceWithTransaction;
 
@@ -48,28 +47,26 @@ class OGRLayerWithTransaction: public OGRLayerDecorator
 
         OGRLayerWithTransaction(OGRDataSourceWithTransaction* poDS,
                                 OGRLayer* poBaseLayer);
-       ~OGRLayerWithTransaction();
+    virtual ~OGRLayerWithTransaction();
 
-    virtual const char *GetName() { return GetDescription(); }
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual const char *GetName() override { return GetDescription(); }
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+                                     int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
 
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeature *GetFeature( GIntBig nFID );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+                                     int bApproxOK = TRUE ) override;
 
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeature *GetFeature( GIntBig nFID ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
 };
 
-
 class OGRDataSourceWithTransaction : public OGRDataSource
 {
   protected:
@@ -97,47 +94,47 @@ class OGRDataSourceWithTransaction : public OGRDataSource
 
     int                 IsInTransaction() const { return m_bInTransaction; }
 
-    virtual const char  *GetName();
+    virtual const char  *GetName() override;
 
-    virtual int         GetLayerCount() ;
-    virtual OGRLayer    *GetLayer(int);
-    virtual OGRLayer    *GetLayerByName(const char *);
-    virtual OGRErr      DeleteLayer(int);
+    virtual int         GetLayerCount() override ;
+    virtual OGRLayer    *GetLayer(int) override;
+    virtual OGRLayer    *GetLayerByName(const char *) override;
+    virtual OGRErr      DeleteLayer(int) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
-                                     char ** papszOptions = NULL );
+                                     char ** papszOptions = NULL ) override;
     virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer,
                                    const char *pszNewName,
-                                   char **papszOptions = NULL );
+                                   char **papszOptions = NULL ) override;
 
-    virtual OGRStyleTable *GetStyleTable();
-    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
+    virtual OGRStyleTable *GetStyleTable() override;
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable ) override;
 
-    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
+    virtual void        SetStyleTable(OGRStyleTable *poStyleTable) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszStatement,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poResultsSet );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poResultsSet ) override;
 
-    virtual void        FlushCache();
+    virtual void        FlushCache() override;
 
-    virtual OGRErr      StartTransaction(int bForce=FALSE);
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction(int bForce=FALSE) override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                          const char * pszValue,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
 };
 
 /************************************************************************/
@@ -164,23 +161,21 @@ OGRDataSource* OGRCreateEmulatedTransactionDataSourceWrapper(
                                             bTakeOwnershipTransactionBehaviour);
 }
 
-
 /************************************************************************/
 /*                      OGRDataSourceWithTransaction                    */
 /************************************************************************/
 
 OGRDataSourceWithTransaction::OGRDataSourceWithTransaction(
-                                OGRDataSource* poBaseDataSource,
-                                IOGRTransactionBehaviour* poTransactionBehaviour,
-                                int bTakeOwnershipDataSource,
-                                int bTakeOwnershipTransactionBehaviour) :
-            m_poBaseDataSource(poBaseDataSource),
-            m_poTransactionBehaviour(poTransactionBehaviour),
-            m_bHasOwnershipDataSource(bTakeOwnershipDataSource),
-            m_bHasOwnershipTransactionBehaviour(bTakeOwnershipTransactionBehaviour),
-            m_bInTransaction(FALSE)
-{
-}
+    OGRDataSource* poBaseDataSource,
+    IOGRTransactionBehaviour* poTransactionBehaviour,
+    int bTakeOwnershipDataSource,
+    int bTakeOwnershipTransactionBehaviour) :
+    m_poBaseDataSource(poBaseDataSource),
+    m_poTransactionBehaviour(poTransactionBehaviour),
+    m_bHasOwnershipDataSource(bTakeOwnershipDataSource),
+    m_bHasOwnershipTransactionBehaviour(bTakeOwnershipTransactionBehaviour),
+    m_bInTransaction(FALSE)
+{}
 
 OGRDataSourceWithTransaction::~OGRDataSourceWithTransaction()
 {
@@ -194,7 +189,6 @@ OGRDataSourceWithTransaction::~OGRDataSourceWithTransaction()
         delete m_poTransactionBehaviour;
 }
 
-
 OGRLayer* OGRDataSourceWithTransaction::WrapLayer(OGRLayer* poLayer)
 {
     if( poLayer )
@@ -246,7 +240,6 @@ OGRLayer    *OGRDataSourceWithTransaction::GetLayer(int iIndex)
 {
     if( !m_poBaseDataSource ) return NULL;
     return WrapLayer(m_poBaseDataSource->GetLayer(iIndex));
-
 }
 
 OGRLayer    *OGRDataSourceWithTransaction::GetLayerByName(const char *pszName)
@@ -263,7 +256,7 @@ OGRErr      OGRDataSourceWithTransaction::DeleteLayer(int iIndex)
     if( poLayer )
         osName = poLayer->GetName();
     OGRErr eErr = m_poBaseDataSource->DeleteLayer(iIndex);
-    if( eErr == OGRERR_NONE && osName.size())
+    if( eErr == OGRERR_NONE && !osName.empty() )
     {
         std::map<CPLString, OGRLayerWithTransaction*>::iterator oIter = m_oMapLayers.find(osName);
         if(oIter != m_oMapLayers.end())
@@ -355,7 +348,7 @@ OGRErr OGRDataSourceWithTransaction::StartTransaction(int bForce)
                  "Transactions only supported in forced mode");
         return OGRERR_UNSUPPORTED_OPERATION;
     }
-    if( m_oSetExecuteSQLLayers.size() != 0 )
+    if( !m_oSetExecuteSQLLayers.empty() )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Cannot start transaction while a layer returned by "
@@ -387,7 +380,7 @@ OGRErr OGRDataSourceWithTransaction::CommitTransaction()
                  "No transaction in progress");
         return OGRERR_FAILURE;
     }
-    if( m_oSetExecuteSQLLayers.size() != 0 )
+    if( !m_oSetExecuteSQLLayers.empty() )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Cannot interrupt transaction while a layer returned by "
@@ -412,7 +405,7 @@ OGRErr OGRDataSourceWithTransaction::RollbackTransaction()
                  "No transaction in progress");
         return OGRERR_FAILURE;
     }
-    if( m_oSetExecuteSQLLayers.size() != 0 )
+    if( !m_oSetExecuteSQLLayers.empty() )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Cannot interrupt transaction while a layer returned by "
@@ -456,18 +449,16 @@ CPLErr      OGRDataSourceWithTransaction::SetMetadataItem( const char * pszName,
     return m_poBaseDataSource->SetMetadataItem(pszName, pszValue, pszDomain);
 }
 
-
 /************************************************************************/
 /*                       OGRLayerWithTransaction                        */
 /************************************************************************/
 
 OGRLayerWithTransaction::OGRLayerWithTransaction(
-                    OGRDataSourceWithTransaction* poDS, OGRLayer* poBaseLayer):
+    OGRDataSourceWithTransaction* poDS, OGRLayer* poBaseLayer) :
     OGRLayerDecorator(poBaseLayer, FALSE),
     m_poDS(poDS),
     m_poFeatureDefn(NULL)
-{
-}
+{}
 
 OGRLayerWithTransaction::~OGRLayerWithTransaction()
 {
diff --git a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
index 71ff366..155784a 100644
--- a/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
+++ b/ogr/ogrsf_frmts/generic/ogremulatedtransaction.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: ogremulatedtransaction.h 35910 2016-10-24 14:08:24Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRDataSourceWithTransaction class
@@ -91,7 +91,6 @@ class CPL_DLL IOGRTransactionBehaviour
                                           int& bOutHasReopenedDS) = 0;
 };
 
-
 /** Returns a new datasource object that adds transactional behaviour to an existing datasource.
  *
  * The provided poTransactionBehaviour object should implement driver-specific
diff --git a/ogr/ogrsf_frmts/generic/ogrlayer.cpp b/ogr/ogrsf_frmts/generic/ogrlayer.cpp
index 74b7fbd..9d892bb 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrlayer.cpp 33754 2016-03-20 17:03:43Z ajolma $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRSFLayer class.
@@ -35,28 +34,24 @@
 #include "swq.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrlayer.cpp 33754 2016-03-20 17:03:43Z ajolma $");
+CPL_CVSID("$Id: ogrlayer.cpp 36950 2016-12-18 22:14:23Z rouault $");
 
 /************************************************************************/
 /*                              OGRLayer()                              */
 /************************************************************************/
 
-OGRLayer::OGRLayer()
-
-{
-    m_poStyleTable = NULL;
-    m_poAttrQuery = NULL;
-    m_pszAttrQueryString = NULL;
-    m_poAttrIndex = NULL;
-    m_nRefCount = 0;
-
-    m_nFeaturesRead = 0;
-
-    m_poFilterGeom = NULL;
-    m_bFilterIsEnvelope = FALSE;
-    m_pPreparedFilterGeom = NULL;
-    m_iGeomFieldFilter = 0;
-}
+OGRLayer::OGRLayer() :
+    m_bFilterIsEnvelope(FALSE),
+    m_poFilterGeom(NULL),
+    m_pPreparedFilterGeom(NULL),
+    m_iGeomFieldFilter(0),
+    m_poStyleTable(NULL),
+    m_poAttrQuery(NULL),
+    m_pszAttrQueryString(NULL),
+    m_poAttrIndex(NULL),
+    m_nRefCount(0),
+    m_nFeaturesRead(0)
+{}
 
 /************************************************************************/
 /*                             ~OGRLayer()                              */
@@ -65,7 +60,7 @@ OGRLayer::OGRLayer()
 OGRLayer::~OGRLayer()
 
 {
-    if ( m_poStyleTable )
+    if( m_poStyleTable )
     {
         delete m_poStyleTable;
         m_poStyleTable = NULL;
@@ -171,13 +166,13 @@ int OGR_L_GetRefCount( OGRLayerH hLayer )
 GIntBig OGRLayer::GetFeatureCount( int bForce )
 
 {
-    OGRFeature     *poFeature;
-    GIntBig         nFeatureCount = 0;
-
     if( !bForce )
         return -1;
 
     ResetReading();
+
+    GIntBig nFeatureCount = 0;
+    OGRFeature *poFeature = NULL;
     while( (poFeature = GetNextFeature()) != NULL )
     {
         nFeatureCount++;
@@ -224,10 +219,10 @@ OGRErr OGRLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce )
         return GetExtentInternal(iGeomField, psExtent, bForce);
 }
 
+//! @cond Doxygen_Suppress
 OGRErr OGRLayer::GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bForce )
 
 {
-    OGRFeature  *poFeature;
     OGREnvelope oEnv;
     GBool       bExtentSet = FALSE;
 
@@ -263,6 +258,7 @@ OGRErr OGRLayer::GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bF
 /*      the features to collect geometries and build extents.           */
 /* -------------------------------------------------------------------- */
     ResetReading();
+    OGRFeature *poFeature = NULL;
     while( (poFeature = GetNextFeature()) != NULL )
     {
         OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
@@ -295,8 +291,9 @@ OGRErr OGRLayer::GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bF
     }
     ResetReading();
 
-    return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
+    return bExtentSet ? OGRERR_NONE : OGRERR_FAILURE;
 }
+//! @endcond
 
 /************************************************************************/
 /*                          OGR_L_GetExtent()                           */
@@ -411,6 +408,7 @@ static int ContainGeomSpecialField(swq_expr_node* expr,
 /*                AttributeFilterEvaluationNeedsGeometry()              */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 int OGRLayer::AttributeFilterEvaluationNeedsGeometry()
 {
     if( !m_poAttrQuery )
@@ -421,6 +419,7 @@ int OGRLayer::AttributeFilterEvaluationNeedsGeometry()
 
     return ContainGeomSpecialField(expr, nLayerFieldCount);
 }
+//! @endcond
 
 /************************************************************************/
 /*                      OGR_L_SetAttributeFilter()                      */
@@ -446,8 +445,6 @@ OGRErr OGR_L_SetAttributeFilter( OGRLayerH hLayer, const char *pszQuery )
 OGRFeature *OGRLayer::GetFeature( GIntBig nFID )
 
 {
-    OGRFeature *poFeature;
-
     /* Save old attribute and spatial filters */
     char* pszOldFilter = m_pszAttrQueryString ? CPLStrdup(m_pszAttrQueryString) : NULL;
     OGRGeometry* poOldFilterGeom = ( m_poFilterGeom != NULL ) ? m_poFilterGeom->clone() : NULL;
@@ -457,6 +454,8 @@ OGRFeature *OGRLayer::GetFeature( GIntBig nFID )
     SetSpatialFilter(0, NULL);
 
     ResetReading();
+
+    OGRFeature *poFeature = NULL;
     while( (poFeature = GetNextFeature()) != NULL )
     {
         if( poFeature->GetFID() == nFID )
@@ -498,12 +497,12 @@ OGRFeatureH OGR_L_GetFeature( OGRLayerH hLayer, GIntBig nFeatureId )
 OGRErr OGRLayer::SetNextByIndex( GIntBig nIndex )
 
 {
-    OGRFeature *poFeature;
-
     if( nIndex < 0 )
         return OGRERR_FAILURE;
 
     ResetReading();
+
+    OGRFeature *poFeature = NULL;
     while( nIndex-- > 0 )
     {
         poFeature = GetNextFeature();
@@ -783,27 +782,28 @@ OGRErr OGRLayer::ReorderField( int iOldFieldPos, int iNewFieldPos )
         return OGRERR_NONE;
 
     int* panMap = (int*) CPLMalloc(sizeof(int) * nFieldCount);
-    int i;
     if (iOldFieldPos < iNewFieldPos)
     {
         /* "0","1","2","3","4" (1,3) -> "0","2","3","1","4" */
-        for(i=0;i<iOldFieldPos;i++)
+        int i = 0;  // Used after for.
+        for( ; i < iOldFieldPos; i++ )
             panMap[i] = i;
-        for(;i<iNewFieldPos;i++)
+        for( ; i < iNewFieldPos; i++ )
             panMap[i] = i + 1;
         panMap[iNewFieldPos] = iOldFieldPos;
-        for(i=iNewFieldPos+1;i<nFieldCount;i++)
+        for( i = iNewFieldPos + 1; i < nFieldCount; i++ )
             panMap[i] = i;
     }
     else
     {
         /* "0","1","2","3","4" (3,1) -> "0","3","1","2","4" */
-        for(i=0;i<iNewFieldPos;i++)
+        for( int i = 0; i < iNewFieldPos; i++ )
             panMap[i] = i;
         panMap[iNewFieldPos] = iOldFieldPos;
-        for(i=iNewFieldPos+1;i<=iOldFieldPos;i++)
+        int i = iNewFieldPos+1;  // Used after for.
+        for( ; i <= iOldFieldPos; i++ )
             panMap[i] = i - 1;
-        for(;i<nFieldCount;i++)
+        for( ; i < nFieldCount; i++ )
             panMap[i] = i;
     }
 
@@ -1111,7 +1111,6 @@ void OGRLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
         ResetReading();
 }
 
-
 void OGRLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
 
 {
@@ -1180,7 +1179,6 @@ void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
     SetSpatialFilterRect( 0, dfMinX, dfMinY, dfMaxX, dfMaxY );
 }
 
-
 void OGRLayer::SetSpatialFilterRect( int iGeomField,
                                      double dfMinX, double dfMinY,
                                      double dfMaxX, double dfMaxY )
@@ -1260,6 +1258,7 @@ void OGR_L_SetSpatialFilterRectEx( OGRLayerH hLayer,
 /*      way from the current one.                                       */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 int OGRLayer::InstallFilter( OGRGeometry * poFilter )
 
 {
@@ -1335,6 +1334,7 @@ int OGRLayer::InstallFilter( OGRGeometry * poFilter )
 
     return TRUE;
 }
+//! @endcond
 
 /************************************************************************/
 /*                           FilterGeometry()                           */
@@ -1344,6 +1344,7 @@ int OGRLayer::InstallFilter( OGRGeometry * poFilter )
 /*      envelope.                                                       */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 int OGRLayer::FilterGeometry( OGRGeometry *poGeometry )
 
 {
@@ -1373,7 +1374,6 @@ int OGRLayer::FilterGeometry( OGRGeometry *poGeometry )
         || m_sFilterEnvelope.MaxY < sGeomEnv.MinY )
         return FALSE;
 
-
 /* -------------------------------------------------------------------- */
 /*      If the filter geometry is its own envelope and if the           */
 /*      envelope of the geometry is inside the filter geometry,         */
@@ -1455,6 +1455,7 @@ int OGRLayer::FilterGeometry( OGRGeometry *poGeometry )
             return TRUE;
     }
 }
+//! @endcond
 
 /************************************************************************/
 /*                         OGR_L_ResetReading()                         */
@@ -1481,6 +1482,7 @@ void OGR_L_ResetReading( OGRLayerH hLayer )
 /*      datasources can do it too if that is more appropriate.          */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 OGRErr OGRLayer::InitializeIndexSupport( const char *pszFilename )
 
 {
@@ -1500,6 +1502,7 @@ OGRErr OGRLayer::InitializeIndexSupport( const char *pszFilename )
 
     return eErr;
 }
+//! @endcond
 
 /************************************************************************/
 /*                             SyncToDisk()                             */
@@ -1558,11 +1561,13 @@ OGRErr OGR_L_DeleteFeature( OGRLayerH hLayer, GIntBig nFID )
 /*                          GetFeaturesRead()                           */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 GIntBig OGRLayer::GetFeaturesRead()
 
 {
     return m_nFeaturesRead;
 }
+//! @endcond
 
 /************************************************************************/
 /*                       OGR_L_GetFeaturesRead()                        */
@@ -1890,7 +1895,9 @@ OGRErr set_result_schema(OGRLayer *pLayerResult,
             mapInput[iField] = poDefnResult->GetFieldIndex(osName);
         }
         if (!mapMethod) return ret;
+        // cppcheck-suppress nullPointer
         for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
+            // cppcheck-suppress nullPointer
             CPLString osName(poDefnMethod->GetFieldDefn(iField)->GetNameRef());
             if( pszMethodPrefix != NULL )
                 osName = pszMethodPrefix + osName;
@@ -2006,6 +2013,10 @@ static OGRGeometry* promote_to_multi(OGRGeometry* poGeom)
  *     containment of features of method layer within the features of
  *     this layer. This will speed up the method significantly in some
  *     cases. Requires that the prepared geometries are in effect.
+ * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
+ *     result features with lower dimension geometry that would
+ *     otherwise be added to the result layer. The default is to add
+ *     but only if the result layer has an unknown geometry type.
  * </ul>
  *
  * This method is the same as the C function OGR_L_Intersection().
@@ -2054,6 +2065,7 @@ OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
     int bUsePreparedGeometries = CPLTestBool(CSLFetchNameValueDef(papszOptions, "USE_PREPARED_GEOMETRIES", "YES"));
     if (bUsePreparedGeometries) bUsePreparedGeometries = OGRHasPreparedGeometrySupport();
     int bPretestContainment = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PRETEST_CONTAINMENT", "NO"));
+    int bKeepLowerDimGeom = CPLTestBool(CSLFetchNameValueDef(papszOptions, "KEEP_LOWER_DIMENSION_GEOMETRIES", "YES"));
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
@@ -2071,6 +2083,13 @@ OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
     if (ret != OGRERR_NONE) goto done;
     poDefnResult = pLayerResult->GetLayerDefn();
     bEnvelopeSet = pLayerMethod->GetExtent(&sEnvelopeMethod, 1) == OGRERR_NONE;
+    if (bKeepLowerDimGeom) {
+        // require that the result layer is of geom type unknown
+        if (pLayerResult->GetGeomType() != wkbUnknown) {
+            CPLDebug("OGR", "Resetting KEEP_LOWER_DIMENSION_GEOMETRIES to NO since the result layer does not allow it.");
+            bKeepLowerDimGeom = FALSE;
+        }
+    }
 
     ResetReading();
     while (OGRFeature *x = GetNextFeature()) {
@@ -2173,6 +2192,7 @@ OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
                 CPLErrorReset();
                 z_geom = x_geom->Intersection(y_geom);
                 if (CPLGetLastErrorType() != CE_None || z_geom == NULL) {
+                    delete z_geom;
                     delete y;
                     if (!bSkipFailures) {
                         ret = OGRERR_FAILURE;
@@ -2186,9 +2206,9 @@ OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
                     }
                 }
                 if (z_geom->IsEmpty() ||
-                    (x_geom->getDimension() == 2 &&
-                     y_geom->getDimension() == 2 &&
-                     z_geom->getDimension() < 2))
+                    (!bKeepLowerDimGeom &&
+                     (x_geom->getDimension() == y_geom->getDimension() &&
+                      z_geom->getDimension() < x_geom->getDimension())))
                 {
                     delete z_geom;
                     delete y;
@@ -2274,6 +2294,10 @@ done:
  *     containment of features of method layer within the features of
  *     this layer. This will speed up the method significantly in some
  *     cases. Requires that the prepared geometries are in effect.
+ * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
+ *     result features with lower dimension geometry that would
+ *     otherwise be added to the result layer. The default is to add
+ *     but only if the result layer has an unknown geometry type.
  * </ul>
  *
  * This function is the same as the C++ method OGRLayer::Intersection().
@@ -2324,13 +2348,13 @@ OGRErr OGR_L_Intersection( OGRLayerH pLayerInput,
  * \brief Union of two layers.
  *
  * The result layer contains features whose geometries represent areas
- * that are in either in the input layer or in the method layer. The
- * features in the result layer have attributes from both input and
- * method layers. For features which represent areas that are only in
- * the input or in the method layer the respective attributes have
- * undefined values. The schema of the result layer can be set by the
- * user or, if it is empty, is initialized to contain all fields in
- * the input and method layers.
+ * that are either in the input layer, in the method layer, or in
+ * both. The features in the result layer have attributes from both
+ * input and method layers. For features which represent areas that
+ * are only in the input or in the method layer the respective
+ * attributes have undefined values. The schema of the result layer
+ * can be set by the user or, if it is empty, is initialized to
+ * contain all fields in the input and method layers.
  *
  * \note If the schema of the result is set by user and contains
  * fields that have the same name as a field in input and in method
@@ -2356,6 +2380,10 @@ OGRErr OGR_L_Intersection( OGRLayerH pLayerInput,
  * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
  *     geometries to pretest intersection of features of method layer
  *     with features of this layer.
+ * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
+ *     result features with lower dimension geometry that would
+ *     otherwise be added to the result layer. The default is to add
+ *     but only if the result layer has an unknown geometry type.
  * </ul>
  *
  * This method is the same as the C function OGR_L_Union().
@@ -2402,6 +2430,7 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
     int bPromoteToMulti = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
     int bUsePreparedGeometries = CPLTestBool(CSLFetchNameValueDef(papszOptions, "USE_PREPARED_GEOMETRIES", "YES"));
     if (bUsePreparedGeometries) bUsePreparedGeometries = OGRHasPreparedGeometrySupport();
+    int bKeepLowerDimGeom = CPLTestBool(CSLFetchNameValueDef(papszOptions, "KEEP_LOWER_DIMENSION_GEOMETRIES", "YES"));
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
@@ -2420,6 +2449,13 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
     if (ret != OGRERR_NONE) goto done;
     poDefnResult = pLayerResult->GetLayerDefn();
+    if (bKeepLowerDimGeom) {
+        // require that the result layer is of geom type unknown
+        if (pLayerResult->GetGeomType() != wkbUnknown) {
+            CPLDebug("OGR", "Resetting KEEP_LOWER_DIMENSION_GEOMETRIES to NO since the result layer does not allow it.");
+            bKeepLowerDimGeom = FALSE;
+        }
+    }
 
     // add features based on input layer
     ResetReading();
@@ -2494,6 +2530,7 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
             CPLErrorReset();
             OGRGeometry *poIntersection = x_geom->Intersection(y_geom);
             if (CPLGetLastErrorType() != CE_None || poIntersection == NULL) {
+                delete poIntersection;
                 delete y;
                 if (!bSkipFailures) {
                     ret = OGRERR_FAILURE;
@@ -2507,9 +2544,9 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
                 }
             }
             if( poIntersection->IsEmpty() ||
-                (x_geom->getDimension() == 2 &&
-                y_geom->getDimension() == 2 &&
-                poIntersection->getDimension() < 2) )
+                (!bKeepLowerDimGeom &&
+                 (x_geom->getDimension() == y_geom->getDimension() &&
+                  poIntersection->getDimension() < x_geom->getDimension())) )
             {
                 delete poIntersection;
                 delete y;
@@ -2527,6 +2564,7 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
                     CPLErrorReset();
                     OGRGeometry *x_geom_diff_new = x_geom_diff->Difference(y_geom);
                     if (CPLGetLastErrorType() != CE_None || x_geom_diff_new == NULL) {
+                        delete x_geom_diff_new;
                         if (!bSkipFailures) {
                             ret = OGRERR_FAILURE;
                             delete y;
@@ -2631,11 +2669,12 @@ OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
         while (OGRFeature *y = GetNextFeature()) {
             OGRGeometry *y_geom = y->GetGeometryRef();
             if (!y_geom) {delete y; continue;}
-            
+
             if (x_geom_diff) {
                 CPLErrorReset();
                 OGRGeometry *x_geom_diff_new = x_geom_diff->Difference(y_geom);
                 if (CPLGetLastErrorType() != CE_None || x_geom_diff_new == NULL) {
+                    delete x_geom_diff_new;
                     if (!bSkipFailures) {
                         ret = OGRERR_FAILURE;
                         delete x;
@@ -2703,13 +2742,13 @@ done:
  * \brief Union of two layers.
  *
  * The result layer contains features whose geometries represent areas
- * that are in either in the input layer or in the method layer. The
- * features in the result layer have attributes from both input and
- * method layers. For features which represent areas that are only in
- * the input or in the method layer the respective attributes have
- * undefined values. The schema of the result layer can be set by the
- * user or, if it is empty, is initialized to contain all fields in
- * the input and method layers.
+ * that are in either in the input layer, in the method layer, or in
+ * both. The features in the result layer have attributes from both
+ * input and method layers. For features which represent areas that
+ * are only in the input or in the method layer the respective
+ * attributes have undefined values. The schema of the result layer
+ * can be set by the user or, if it is empty, is initialized to
+ * contain all fields in the input and method layers.
  *
  * \note If the schema of the result is set by user and contains
  * fields that have the same name as a field in input and in method
@@ -2735,6 +2774,10 @@ done:
  * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
  *     geometries to pretest intersection of features of method layer
  *     with features of this layer.
+ * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
+ *     result features with lower dimension geometry that would
+ *     otherwise be added to the result layer. The default is to add
+ *     but only if the result layer has an unknown geometry type.
  * </ul>
  *
  * This function is the same as the C++ method OGRLayer::Union().
@@ -2921,6 +2964,7 @@ OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
                 CPLErrorReset();
                 OGRGeometry *geom_new = geom->Difference(y_geom);
                 if (CPLGetLastErrorType() != CE_None || geom_new == NULL) {
+                    delete geom_new;
                     if (!bSkipFailures) {
                         ret = OGRERR_FAILURE;
                         delete geom;
@@ -3010,6 +3054,7 @@ OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
                 CPLErrorReset();
                 OGRGeometry *geom_new = geom->Difference(y_geom);
                 if (CPLGetLastErrorType() != CE_None || geom_new == NULL) {
+                    delete geom_new;
                     if (!bSkipFailures) {
                         ret = OGRERR_FAILURE;
                         delete geom;
@@ -3186,6 +3231,10 @@ OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput,
  * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
  *     geometries to pretest intersection of features of method layer
  *     with features of this layer.
+ * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
+ *     result features with lower dimension geometry that would
+ *     otherwise be added to the result layer. The default is to add
+ *     but only if the result layer has an unknown geometry type.
  * </ul>
  *
  * This method is the same as the C function OGR_L_Identity().
@@ -3231,11 +3280,19 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
     int bPromoteToMulti = CPLTestBool(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
     int bUsePreparedGeometries = CPLTestBool(CSLFetchNameValueDef(papszOptions, "USE_PREPARED_GEOMETRIES", "YES"));
     if (bUsePreparedGeometries) bUsePreparedGeometries = OGRHasPreparedGeometrySupport();
+    int bKeepLowerDimGeom = CPLTestBool(CSLFetchNameValueDef(papszOptions, "KEEP_LOWER_DIMENSION_GEOMETRIES", "YES"));
 
     // check for GEOS
     if (!OGRGeometryFactory::haveGEOS()) {
         return OGRERR_UNSUPPORTED_OPERATION;
     }
+    if (bKeepLowerDimGeom) {
+        // require that the result layer is of geom type unknown
+        if (pLayerResult->GetGeomType() != wkbUnknown) {
+            CPLDebug("OGR", "Resetting KEEP_LOWER_DIMENSION_GEOMETRIES to NO since the result layer does not allow it.");
+            bKeepLowerDimGeom = FALSE;
+        }
+    }
 
     // get resources
     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
@@ -3321,6 +3378,7 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
             CPLErrorReset();
             OGRGeometry* poIntersection = x_geom->Intersection(y_geom);
             if (CPLGetLastErrorType() != CE_None || poIntersection == NULL) {
+                delete poIntersection;
                 delete y;
                 if (!bSkipFailures) {
                     ret = OGRERR_FAILURE;
@@ -3334,9 +3392,9 @@ OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
                 }
             }
             else if( poIntersection->IsEmpty() ||
-                (x_geom->getDimension() == 2 &&
-                y_geom->getDimension() == 2 &&
-                poIntersection->getDimension() < 2) )
+                     (!bKeepLowerDimGeom &&
+                      (x_geom->getDimension() == y_geom->getDimension() &&
+                       poIntersection->getDimension() < x_geom->getDimension())) )
             {
                 delete poIntersection;
                 delete y;
@@ -3465,6 +3523,10 @@ done:
  * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
  *     geometries to pretest intersection of features of method layer
  *     with features of this layer.
+ * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
+ *     result features with lower dimension geometry that would
+ *     otherwise be added to the result layer. The default is to add
+ *     but only if the result layer has an unknown geometry type.
  * </ul>
  *
  * This function is the same as the C++ method OGRLayer::Identity().
@@ -3648,6 +3710,7 @@ OGRErr OGRLayer::Update( OGRLayer *pLayerMethod,
                 CPLErrorReset();
                 OGRGeometry *x_geom_diff_new = x_geom_diff->Difference(y_geom);
                 if (CPLGetLastErrorType() != CE_None || x_geom_diff_new == NULL) {
+                    delete x_geom_diff_new;
                     if (!bSkipFailures) {
                         ret = OGRERR_FAILURE;
                         delete y;
@@ -3951,6 +4014,7 @@ OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
                 CPLErrorReset();
                 OGRGeometry *geom_new = geom->Union(y_geom);
                 if (CPLGetLastErrorType() != CE_None || geom_new == NULL) {
+                    delete geom_new;
                     if (!bSkipFailures) {
                         ret = OGRERR_FAILURE;
                         delete y;
@@ -3974,6 +4038,7 @@ OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
             CPLErrorReset();
             OGRGeometry* poIntersection = x_geom->Intersection(geom);
             if (CPLGetLastErrorType() != CE_None || poIntersection == NULL) {
+                delete poIntersection;
                 if (!bSkipFailures) {
                     ret = OGRERR_FAILURE;
                     delete geom;
@@ -4222,6 +4287,7 @@ OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
             CPLErrorReset();
             OGRGeometry *geom_new = geom->Difference(y_geom);
             if (CPLGetLastErrorType() != CE_None || geom_new == NULL) {
+                delete geom_new;
                 if (!bSkipFailures) {
                     ret = OGRERR_FAILURE;
                     delete x;
@@ -4235,7 +4301,10 @@ OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
                 delete geom;
                 geom = geom_new;
                 if (geom->IsEmpty())
+                {
+                    delete y;
                     break;
+                }
             }
             delete y;
         }
@@ -4259,6 +4328,10 @@ OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
                 }
             }
         }
+        else
+        {
+            delete geom;
+        }
         delete x;
     }
     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp
index 298124a..55bfa71 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrlayerdecorator.cpp 32467 2015-12-26 10:54:09Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRLayerDecorator class
@@ -27,14 +26,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrlayerdecorator.h"
 
-CPL_CVSID("$Id: ogrlayerdecorator.cpp 32467 2015-12-26 10:54:09Z rouault $");
+CPL_CVSID("$Id: ogrlayerdecorator.cpp 35910 2016-10-24 14:08:24Z goatbar $");
 
-OGRLayerDecorator::OGRLayerDecorator(OGRLayer* poDecoratedLayer,
-                                     int bTakeOwnership) :
-                                        m_poDecoratedLayer(poDecoratedLayer),
-                                        m_bHasOwnership(bTakeOwnership)
+OGRLayerDecorator::OGRLayerDecorator( OGRLayer* poDecoratedLayer,
+                                      int bTakeOwnership ) :
+    m_poDecoratedLayer(poDecoratedLayer),
+    m_bHasOwnership(bTakeOwnership)
 {
     CPLAssert(poDecoratedLayer != NULL);
     SetDescription( poDecoratedLayer->GetDescription() );
@@ -46,7 +47,6 @@ OGRLayerDecorator::~OGRLayerDecorator()
         delete m_poDecoratedLayer;
 }
 
-
 OGRGeometry *OGRLayerDecorator::GetSpatialFilter()
 {
     if( !m_poDecoratedLayer ) return NULL;
@@ -294,3 +294,5 @@ CPLErr      OGRLayerDecorator::SetMetadataItem( const char * pszName,
     if( !m_poDecoratedLayer ) return CE_Failure;
     return m_poDecoratedLayer->SetMetadataItem(pszName, pszValue, pszDomain);
 }
+
+#endif /* #ifndef DOXYGEN_SKIP */
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h
index 34abc10..533bdc8 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h
+++ b/ogr/ogrsf_frmts/generic/ogrlayerdecorator.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlayerdecorator.h 32467 2015-12-26 10:54:09Z rouault $
+ * $Id: ogrlayerdecorator.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLayerDecorator class
@@ -30,6 +30,8 @@
 #ifndef OGRLAYERDECORATOR_H_INCLUDED
 #define OGRLAYERDECORATOR_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrsf_frmts.h"
 
 class CPL_DLL OGRLayerDecorator : public OGRLayer
@@ -44,71 +46,73 @@ class CPL_DLL OGRLayerDecorator : public OGRLayer
                                          int bTakeOwnership);
     virtual           ~OGRLayerDecorator();
 
-    virtual OGRGeometry *GetSpatialFilter();
-    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual OGRGeometry *GetSpatialFilter() override;
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
     virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+                                              double dfMaxX, double dfMaxY ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
     virtual void        SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY );
+                                              double dfMaxX, double dfMaxY ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
-    virtual OGRFeature *GetFeature( GIntBig nFID );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
+    virtual OGRFeature *GetFeature( GIntBig nFID ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    virtual const char *GetName();
-    virtual OGRwkbGeometryType GetGeomType();
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual const char *GetName() override;
+    virtual OGRwkbGeometryType GetGeomType() override;
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+                                     int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
 
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
-                                         int bApproxOK = TRUE );
+                                         int bApproxOK = TRUE ) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 
-    virtual OGRStyleTable *GetStyleTable();
-    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
+    virtual OGRStyleTable *GetStyleTable() override;
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable ) override;
 
-    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
+    virtual void        SetStyleTable(OGRStyleTable *poStyleTable) override;
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction() override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 
-    virtual OGRErr      SetIgnoredFields( const char **papszFields );
+    virtual OGRErr      SetIgnoredFields( const char **papszFields ) override;
 
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                          const char * pszValue,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
 
     OGRLayer* GetBaseLayer()    { return m_poDecoratedLayer; }
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif // OGRLAYERDECORATOR_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp b/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp
index 1418ad5..1665c2e 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrlayerpool.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrlayerpool.cpp 31925 2015-12-01 15:02:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLayerPool and OGRProxiedLayer class
@@ -27,20 +26,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrlayerpool.h"
 
-CPL_CVSID("$Id: ogrlayerpool.cpp 31925 2015-12-01 15:02:41Z rouault $");
+CPL_CVSID("$Id: ogrlayerpool.cpp 35910 2016-10-24 14:08:24Z goatbar $");
 
 /************************************************************************/
 /*                      OGRAbstractProxiedLayer()                       */
 /************************************************************************/
 
-OGRAbstractProxiedLayer::OGRAbstractProxiedLayer(OGRLayerPool* poPoolIn) :
+OGRAbstractProxiedLayer::OGRAbstractProxiedLayer( OGRLayerPool* poPoolIn ) :
     poPrevLayer(NULL),
-    poNextLayer(NULL)
+    poNextLayer(NULL),
+    poPool(poPoolIn)
 {
     CPLAssert(poPoolIn != NULL);
-    poPool = poPoolIn;
 }
 
 /************************************************************************/
@@ -53,8 +54,6 @@ OGRAbstractProxiedLayer::~OGRAbstractProxiedLayer()
     poPool->UnchainLayer(this);
 }
 
-
-
 /************************************************************************/
 /*                            OGRLayerPool()                            */
 /************************************************************************/
@@ -62,10 +61,9 @@ OGRAbstractProxiedLayer::~OGRAbstractProxiedLayer()
 OGRLayerPool::OGRLayerPool(int nMaxSimultaneouslyOpenedIn) :
     poMRULayer(NULL),
     poLRULayer(NULL),
-    nMRUListSize(0)
-{
-    nMaxSimultaneouslyOpened = nMaxSimultaneouslyOpenedIn;
-}
+    nMRUListSize(0),
+    nMaxSimultaneouslyOpened(nMaxSimultaneouslyOpenedIn)
+{}
 
 /************************************************************************/
 /*                           ~OGRLayerPool()                            */
@@ -148,25 +146,23 @@ void OGRLayerPool::UnchainLayer(OGRAbstractProxiedLayer* poLayer)
     poLayer->poNextLayer = NULL;
 }
 
-
-
 /************************************************************************/
 /*                          OGRProxiedLayer()                           */
 /************************************************************************/
 
-OGRProxiedLayer::OGRProxiedLayer(OGRLayerPool* poPoolIn,
-                                 OpenLayerFunc pfnOpenLayerIn,
-                                 FreeUserDataFunc pfnFreeUserDataIn,
-                                 void* pUserDataIn) : OGRAbstractProxiedLayer(poPoolIn)
+OGRProxiedLayer::OGRProxiedLayer( OGRLayerPool* poPoolIn,
+                                  OpenLayerFunc pfnOpenLayerIn,
+                                  FreeUserDataFunc pfnFreeUserDataIn,
+                                  void* pUserDataIn ) :
+    OGRAbstractProxiedLayer(poPoolIn),
+    pfnOpenLayer(pfnOpenLayerIn),
+    pfnFreeUserData(pfnFreeUserDataIn),
+    pUserData(pUserDataIn),
+    poUnderlyingLayer(NULL),
+    poFeatureDefn(NULL),
+    poSRS(NULL)
 {
     CPLAssert(pfnOpenLayerIn != NULL);
-
-    pfnOpenLayer = pfnOpenLayerIn;
-    pfnFreeUserData = pfnFreeUserDataIn;
-    pUserData = pUserDataIn;
-    poUnderlyingLayer = NULL;
-    poFeatureDefn = NULL;
-    poSRS = NULL;
 }
 
 /************************************************************************/
@@ -582,3 +578,5 @@ OGRErr      OGRProxiedLayer::SetIgnoredFields( const char **papszFields )
     if( poUnderlyingLayer == NULL && !OpenUnderlyingLayer() ) return OGRERR_FAILURE;
     return poUnderlyingLayer->SetIgnoredFields(papszFields);
 }
+
+#endif /* #ifndef DOXYGEN_SKIP */
diff --git a/ogr/ogrsf_frmts/generic/ogrlayerpool.h b/ogr/ogrsf_frmts/generic/ogrlayerpool.h
index c2472a0..1bc2063 100644
--- a/ogr/ogrsf_frmts/generic/ogrlayerpool.h
+++ b/ogr/ogrsf_frmts/generic/ogrlayerpool.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrlayerpool.h 32177 2015-12-14 07:25:30Z goatbar $
+ * $Id: ogrlayerpool.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLayerPool and OGRProxiedLayer class
@@ -30,6 +30,8 @@
 #ifndef OGRLAYERPOOL_H_INCLUDED
 #define OGRLAYERPOOL_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrsf_frmts.h"
 
 typedef OGRLayer* (*OpenLayerFunc)(void* user_data);
@@ -54,7 +56,7 @@ class OGRAbstractProxiedLayer : public OGRLayer
         virtual void    CloseUnderlyingLayer() = 0;
 
     public:
-                        OGRAbstractProxiedLayer(OGRLayerPool* poPool);
+        explicit        OGRAbstractProxiedLayer(OGRLayerPool* poPool);
         virtual        ~OGRAbstractProxiedLayer();
 };
 
@@ -71,7 +73,7 @@ class OGRLayerPool
         int                     nMaxSimultaneouslyOpened;
 
     public:
-                                OGRLayerPool(int nMaxSimultaneouslyOpened = 100);
+        explicit                OGRLayerPool(int nMaxSimultaneouslyOpened = 100);
                                ~OGRLayerPool();
 
         void                    SetLastUsedLayer(OGRAbstractProxiedLayer* poProxiedLayer);
@@ -98,7 +100,7 @@ class OGRProxiedLayer : public OGRAbstractProxiedLayer
 
   protected:
 
-    virtual void        CloseUnderlyingLayer();
+    virtual void        CloseUnderlyingLayer() override;
 
   public:
 
@@ -110,53 +112,55 @@ class OGRProxiedLayer : public OGRAbstractProxiedLayer
 
     OGRLayer           *GetUnderlyingLayer();
 
-    virtual OGRGeometry *GetSpatialFilter();
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual OGRGeometry *GetSpatialFilter() override;
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
-    virtual OGRFeature *GetFeature( GIntBig nFID );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
+    virtual OGRFeature *GetFeature( GIntBig nFID ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    virtual const char *GetName();
-    virtual OGRwkbGeometryType GetGeomType();
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual const char *GetName() override;
+    virtual OGRwkbGeometryType GetGeomType() override;
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+                                     int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 
-    virtual OGRStyleTable *GetStyleTable();
-    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
+    virtual OGRStyleTable *GetStyleTable() override;
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable ) override;
 
-    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
+    virtual void        SetStyleTable(OGRStyleTable *poStyleTable) override;
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction() override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 
-    virtual OGRErr      SetIgnoredFields( const char **papszFields );
+    virtual OGRErr      SetIgnoredFields( const char **papszFields ) override;
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif // OGRLAYERPOOL_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp
index 80b573b..a1a168c 100644
--- a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmutexeddatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMutexedDataSource class
@@ -27,26 +26,28 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrmutexeddatasource.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrmutexeddatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrmutexeddatasource.cpp 35172 2016-08-21 20:33:08Z goatbar $");
 
-OGRMutexedDataSource::OGRMutexedDataSource(OGRDataSource* poBaseDataSource,
-                                           int bTakeOwnership,
-                                           CPLMutex* hMutexIn,
-                                           int bWrapLayersInMutexedLayer) :
-            m_poBaseDataSource(poBaseDataSource),
-            m_bHasOwnership(bTakeOwnership),
-            m_hGlobalMutex(hMutexIn),
-            m_bWrapLayersInMutexedLayer(bWrapLayersInMutexedLayer)
-{
-}
+OGRMutexedDataSource::OGRMutexedDataSource( OGRDataSource* poBaseDataSource,
+                                            int bTakeOwnership,
+                                            CPLMutex* hMutexIn,
+                                            int bWrapLayersInMutexedLayer ) :
+    m_poBaseDataSource(poBaseDataSource),
+    m_bHasOwnership(bTakeOwnership),
+    m_hGlobalMutex(hMutexIn),
+    m_bWrapLayersInMutexedLayer(bWrapLayersInMutexedLayer)
+{}
 
 OGRMutexedDataSource::~OGRMutexedDataSource()
 {
-    std::map<OGRLayer*, OGRMutexedLayer*>::iterator oIter = m_oMapLayers.begin();
-    for(; oIter != m_oMapLayers.end(); ++oIter )
+    std::map<OGRLayer*, OGRMutexedLayer*>::iterator oIter =
+        m_oMapLayers.begin();
+    for( ; oIter != m_oMapLayers.end(); ++oIter )
         delete oIter->second;
 
     if( m_bHasOwnership )
@@ -240,3 +241,5 @@ void OGRRegisterMutexedDataSource()
     delete new OGRMutexedDataSource(NULL, FALSE, NULL, FALSE);
 }
 #endif
+
+#endif /* #ifndef DOXYGEN_SKIP */
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h
index 0f2e93a..20d7a3b 100644
--- a/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h
+++ b/ogr/ogrsf_frmts/generic/ogrmutexeddatasource.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmutexeddatasource.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrmutexeddatasource.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLMutexedDataSource class
@@ -30,6 +30,8 @@
 #ifndef OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
 #define OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrsf_frmts.h"
 #include "cpl_multiproc.h"
 #include "ogrmutexedlayer.h"
@@ -67,47 +69,49 @@ class CPL_DLL OGRMutexedDataSource : public OGRDataSource
 
     OGRDataSource*      GetBaseDataSource() { return m_poBaseDataSource; }
 
-    virtual const char  *GetName();
+    virtual const char  *GetName() override;
 
-    virtual int         GetLayerCount() ;
-    virtual OGRLayer    *GetLayer(int);
-    virtual OGRLayer    *GetLayerByName(const char *);
-    virtual OGRErr      DeleteLayer(int);
+    virtual int         GetLayerCount() override ;
+    virtual OGRLayer    *GetLayer(int) override;
+    virtual OGRLayer    *GetLayerByName(const char *) override;
+    virtual OGRErr      DeleteLayer(int) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
-                                     char ** papszOptions = NULL );
+                                     char ** papszOptions = NULL ) override;
     virtual OGRLayer   *CopyLayer( OGRLayer *poSrcLayer,
                                    const char *pszNewName,
-                                   char **papszOptions = NULL );
+                                   char **papszOptions = NULL ) override;
 
-    virtual OGRStyleTable *GetStyleTable();
-    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
+    virtual OGRStyleTable *GetStyleTable() override;
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable ) override;
 
-    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
+    virtual void        SetStyleTable(OGRStyleTable *poStyleTable) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszStatement,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poResultsSet );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poResultsSet ) override;
 
-    virtual void        FlushCache();
+    virtual void        FlushCache() override;
 
-    virtual OGRErr      StartTransaction(int bForce=FALSE);
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction(int bForce=FALSE) override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                          const char * pszValue,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif // OGRMUTEXEDDATASOURCELAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp
index 88055fa..ff98c29 100644
--- a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmutexedlayer.cpp 31705 2015-11-21 22:57:18Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMutexedLayer class
@@ -27,23 +26,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrmutexedlayer.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrmutexedlayer.cpp 31705 2015-11-21 22:57:18Z rouault $");
+CPL_CVSID("$Id: ogrmutexedlayer.cpp 35910 2016-10-24 14:08:24Z goatbar $");
 
-OGRMutexedLayer::OGRMutexedLayer(OGRLayer* poDecoratedLayer,
-                                 int bTakeOwnership,
-                                 CPLMutex* hMutex) :
-        OGRLayerDecorator(poDecoratedLayer, bTakeOwnership), m_hMutex(hMutex)
+OGRMutexedLayer::OGRMutexedLayer( OGRLayer* poDecoratedLayer,
+                                  int bTakeOwnership,
+                                  CPLMutex* hMutex ) :
+    OGRLayerDecorator(poDecoratedLayer, bTakeOwnership), m_hMutex(hMutex)
 {
     SetDescription( poDecoratedLayer->GetDescription() );
 }
 
-OGRMutexedLayer::~OGRMutexedLayer()
-{
-}
-
+OGRMutexedLayer::~OGRMutexedLayer() {}
 
 OGRGeometry *OGRMutexedLayer::GetSpatialFilter()
 {
@@ -292,7 +290,9 @@ CPLErr      OGRMutexedLayer::SetMetadataItem( const char * pszName,
 void OGRRegisterMutexedLayer();
 void OGRRegisterMutexedLayer()
 {
-    CPLAssert(FALSE); // Never call this function: it will segfault
+    CPLAssert(false); // Never call this function: it will segfault
     delete new OGRMutexedLayer(NULL, FALSE, NULL);
 }
 #endif
+
+#endif /* #ifndef DOXYGEN_SKIP */
diff --git a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h
index a294100..2863299 100644
--- a/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h
+++ b/ogr/ogrsf_frmts/generic/ogrmutexedlayer.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrmutexedlayer.h 31812 2015-11-28 22:37:37Z goatbar $
+ * $Id: ogrmutexedlayer.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRLMutexedLayer class
@@ -30,6 +30,8 @@
 #ifndef OGRMUTEXEDLAYER_H_INCLUDED
 #define OGRMUTEXEDLAYER_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrlayerdecorator.h"
 #include "cpl_multiproc.h"
 
@@ -55,66 +57,68 @@ class CPL_DLL OGRMutexedLayer : public OGRLayerDecorator
     /* The destruction of the object isn't protected by the mutex */
     virtual           ~OGRMutexedLayer();
 
-    virtual OGRGeometry *GetSpatialFilter();
-    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual OGRGeometry *GetSpatialFilter() override;
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
     virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+                                              double dfMaxX, double dfMaxY ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
     virtual void        SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY );
+                                              double dfMaxX, double dfMaxY ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
-    virtual OGRFeature *GetFeature( GIntBig nFID );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
+    virtual OGRFeature *GetFeature( GIntBig nFID ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    virtual const char *GetName();
-    virtual OGRwkbGeometryType GetGeomType();
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual const char *GetName() override;
+    virtual OGRwkbGeometryType GetGeomType() override;
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+                                     int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 
-    virtual OGRStyleTable *GetStyleTable();
-    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable );
+    virtual OGRStyleTable *GetStyleTable() override;
+    virtual void        SetStyleTableDirectly( OGRStyleTable *poStyleTable ) override;
 
-    virtual void        SetStyleTable(OGRStyleTable *poStyleTable);
+    virtual void        SetStyleTable(OGRStyleTable *poStyleTable) override;
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction() override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 
-    virtual OGRErr      SetIgnoredFields( const char **papszFields );
+    virtual OGRErr      SetIgnoredFields( const char **papszFields ) override;
 
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                     const char * pszDomain = "" );
+                                     const char * pszDomain = "" ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                          const char * pszValue,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif // OGRMUTEXEDLAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
index 0e64e2a..4fecb3c 100644
--- a/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrregisterall.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrregisterall.cpp 34979 2016-08-08 09:30:34Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Function to register all known OGR drivers.
@@ -30,7 +29,7 @@
 
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrregisterall.cpp 34979 2016-08-08 09:30:34Z rouault $");
+CPL_CVSID("$Id: ogrregisterall.cpp 37968 2017-04-12 07:16:55Z rouault $");
 
 /************************************************************************/
 /*                           OGRRegisterAll()                           */
@@ -158,12 +157,18 @@ void OGRRegisterAllInternal()
 #ifdef XPLANE_ENABLED
     RegisterOGRXPlane();
 #endif
-#ifdef DWGDIRECT_ENABLED
-    RegisterOGRDXFDWG();
+#ifdef DWG_ENABLED
+    RegisterOGRDWG();
+#endif
+#ifdef DGNV8_ENABLED
+    RegisterOGRDGNV8();
 #endif
 #ifdef DXF_ENABLED
     RegisterOGRDXF();
 #endif
+#ifdef CAD_ENABLED
+    RegisterOGRCAD();
+#endif
 #ifdef GRASS_ENABLED
     RegisterOGRGRASS();
 #endif
@@ -288,6 +293,9 @@ void OGRRegisterAllInternal()
 #ifdef VDV_ENABLED
     RegisterOGRVDV();
 #endif
+#ifdef GMLAS_ENABLED
+    RegisterOGRGMLAS();
+#endif
 
 /* Put TIGER and AVCBIN at end since they need poOpenInfo->GetSiblingFiles() */
 #ifdef TIGER_ENABLED
diff --git a/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp b/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
index d8702b4..70b9506 100644
--- a/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrsfdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsfdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The generic portions of the OGRSFDriver class.
@@ -33,7 +32,9 @@
 #include "ogr_p.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrsfdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsfdriver.cpp 34999 2016-08-09 04:12:18Z goatbar $");
+
+//! @cond Doxygen_Suppress
 
 /************************************************************************/
 /*                            ~OGRSFDriver()                            */
@@ -209,9 +210,8 @@ OGRDataSourceH OGR_Dr_CopyDataSource( OGRSFDriverH hDriver,
     }
 
     GDALDataset *poSrcDS = (GDALDataset*) hSrcDS;
-    GDALDataset *poODS;
-
-    poODS = poDriver->Create( pszNewName, 0, 0, 0, GDT_Unknown, papszOptions );
+    GDALDataset *poODS =
+        poDriver->Create( pszNewName, 0, 0, 0, GDT_Unknown, papszOptions );
     if( poODS == NULL )
         return NULL;
 
@@ -231,3 +231,5 @@ OGRDataSourceH OGR_Dr_CopyDataSource( OGRSFDriverH hDriver,
 
     return (OGRDataSourceH)poODS;
 }
+
+//! @endcond
diff --git a/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp b/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
index f47d006..12d60aa 100644
--- a/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrsfdriverregistrar.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsfdriverregistrar.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSFDriverRegistrar class implementation.
@@ -32,7 +31,7 @@
 #include "ogr_api.h"
 #include "ograpispy.h"
 
-CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 35910 2016-10-24 14:08:24Z goatbar $");
 
 /************************************************************************/
 /*                         OGRSFDriverRegistrar                         */
@@ -52,16 +51,13 @@ OGRSFDriverRegistrar::OGRSFDriverRegistrar() {}
 /*                       ~OGRSFDriverRegistrar()                        */
 /************************************************************************/
 
-OGRSFDriverRegistrar::~OGRSFDriverRegistrar()
-
-{
-}
+OGRSFDriverRegistrar::~OGRSFDriverRegistrar() {}
 
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                           GetRegistrar()                             */
 /************************************************************************/
 
-
 OGRSFDriverRegistrar *OGRSFDriverRegistrar::GetRegistrar()
 {
     static      OGRSFDriverRegistrar oSingleton;
@@ -176,7 +172,6 @@ int OGRSFDriverRegistrar::GetOpenDSCount()
     return 0;
 }
 
-
 /************************************************************************/
 /*                         OGRGetOpenDSCount()                          */
 /************************************************************************/
@@ -411,3 +406,4 @@ OGRSFDriverH OGRGetDriverByName( const char *pszName )
     return (OGRSFDriverH)
         OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName( pszName );
 }
+//! @endcond
diff --git a/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp b/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
index a9d7e79..469f278 100644
--- a/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrunionlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrunionlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRUnionLayer class
@@ -27,30 +26,35 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrunionlayer.h"
 #include "ogrwarpedlayer.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrunionlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+CPL_CVSID("$Id: ogrunionlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                      OGRUnionLayerGeomFieldDefn()                    */
 /************************************************************************/
 
-OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(const char* pszNameIn,
-                                                       OGRwkbGeometryType eType) :
-        OGRGeomFieldDefn(pszNameIn, eType), bGeomTypeSet(FALSE), bSRSSet(FALSE)
-{
-}
+OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
+    const char* pszNameIn,
+    OGRwkbGeometryType eType) :
+    OGRGeomFieldDefn(pszNameIn, eType),
+    bGeomTypeSet(FALSE),
+    bSRSSet(FALSE)
+{}
 
 /************************************************************************/
 /*                      OGRUnionLayerGeomFieldDefn()                    */
 /************************************************************************/
 
 OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
-                                    OGRGeomFieldDefn* poSrc) :
+    OGRGeomFieldDefn* poSrc) :
     OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType()),
-    bGeomTypeSet(FALSE), bSRSSet(FALSE)
+    bGeomTypeSet(FALSE),
+    bSRSSet(FALSE)
 {
     SetSpatialRef(poSrc->GetSpatialRef());
 }
@@ -60,9 +64,10 @@ OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
 /************************************************************************/
 
 OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
-                                    OGRUnionLayerGeomFieldDefn* poSrc) :
+    OGRUnionLayerGeomFieldDefn* poSrc) :
     OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType()),
-    bGeomTypeSet(poSrc->bGeomTypeSet), bSRSSet(poSrc->bSRSSet)
+    bGeomTypeSet(poSrc->bGeomTypeSet),
+    bSRSSet(poSrc->bSRSSet)
 {
     SetSpatialRef(poSrc->GetSpatialRef());
     sStaticEnvelope = poSrc->sStaticEnvelope;
@@ -72,9 +77,7 @@ OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
 /*                     ~OGRUnionLayerGeomFieldDefn()                    */
 /************************************************************************/
 
-OGRUnionLayerGeomFieldDefn::~OGRUnionLayerGeomFieldDefn()
-{
-}
+OGRUnionLayerGeomFieldDefn::~OGRUnionLayerGeomFieldDefn() {}
 
 /************************************************************************/
 /*                          OGRUnionLayer()                             */
@@ -102,16 +105,13 @@ OGRUnionLayer::OGRUnionLayer( const char* pszName,
     panMap(NULL),
     papszIgnoredFields(NULL),
     bAttrFilterPassThroughValue(-1),
+    pabModifiedLayers(static_cast<int*>(CPLCalloc(sizeof(int), nSrcLayers))),
+    pabCheckIfAutoWrap(static_cast<int*>(CPLCalloc(sizeof(int), nSrcLayers))),
     poGlobalSRS(NULL)
 {
     CPLAssert(nSrcLayersIn > 0);
 
     SetDescription( pszName );
-
-    pabModifiedLayers
-        = reinterpret_cast<int*>(CPLCalloc(sizeof(int), nSrcLayers));
-    pabCheckIfAutoWrap
-        = reinterpret_cast<int*>(CPLCalloc(sizeof(int), nSrcLayers));
 }
 
 /************************************************************************/
@@ -185,7 +185,7 @@ void OGRUnionLayer::SetSourceLayerFieldName(const char* pszSourceLayerFieldName)
 {
     CPLAssert(poFeatureDefn == NULL);
 
-    CPLAssert(osSourceLayerFieldName.size() == 0);
+    CPLAssert(osSourceLayerFieldName.empty());
     if( pszSourceLayerFieldName != NULL )
         osSourceLayerFieldName = pszSourceLayerFieldName;
 }
@@ -261,7 +261,7 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
     poFeatureDefn->SetGeomType(wkbNone);
 
     int iCompareFirstIndex = 0;
-    if( osSourceLayerFieldName.size() )
+    if( !osSourceLayerFieldName.empty() )
     {
         OGRFieldDefn oField(osSourceLayerFieldName, OFTString);
         poFeatureDefn->AddFieldDefn(&oField);
@@ -270,19 +270,19 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
 
     if( eFieldStrategy == FIELD_SPECIFIED )
     {
-        int i;
-        for(i = 0; i < nFields; i++)
+        for( int i = 0; i < nFields; i++ )
             poFeatureDefn->AddFieldDefn(papoFields[i]);
-        for(i = 0; i < nGeomFields; i++)
+        for( int i = 0; i < nGeomFields; i++ )
         {
-            poFeatureDefn->AddGeomFieldDefn(new OGRUnionLayerGeomFieldDefn(papoGeomFields[i]), FALSE);
+            poFeatureDefn->AddGeomFieldDefn(
+                new OGRUnionLayerGeomFieldDefn(papoGeomFields[i]), FALSE);
             OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
                 (OGRUnionLayerGeomFieldDefn* ) poFeatureDefn->GetGeomFieldDefn(i);
 
             if( poGeomFieldDefn->bGeomTypeSet == FALSE ||
                 poGeomFieldDefn->bSRSSet == FALSE )
             {
-                for(int iLayer = 0; iLayer < nSrcLayers; iLayer++)
+                for( int iLayer = 0; iLayer < nSrcLayers; iLayer++ )
                 {
                     OGRFeatureDefn* poSrcFeatureDefn =
                                 papoSrcLayers[iLayer]->GetLayerDefn();
@@ -317,10 +317,11 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
     else if( eFieldStrategy == FIELD_FROM_FIRST_LAYER )
     {
         OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[0]->GetLayerDefn();
-        int i;
-        for(i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
+        for( int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
             poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
-        for(i = 0;  nGeomFields != - 1 && i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
+        for( int i = 0;
+             nGeomFields != - 1 && i < poSrcFeatureDefn->GetGeomFieldCount();
+             i++ )
         {
             OGRGeomFieldDefn* poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
             poFeatureDefn->AddGeomFieldDefn(
@@ -341,8 +342,7 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
                                 papoSrcLayers[iLayer]->GetLayerDefn();
 
             /* Add any field that is found in the source layers */
-            int i;
-            for(i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
+            for( int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++ )
             {
                 OGRFieldDefn* poSrcFieldDefn = poSrcFeatureDefn->GetFieldDefn(i);
                 int nIndex =
@@ -357,7 +357,10 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
                 }
             }
 
-            for(i = 0; nGeomFields != - 1 && i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
+            for( int i = 0;
+                 nGeomFields != - 1 &&
+                 i < poSrcFeatureDefn->GetGeomFieldCount();
+                 i++)
             {
                 OGRGeomFieldDefn* poSrcFieldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
                 int nIndex =
@@ -400,10 +403,9 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
     else if (eFieldStrategy == FIELD_INTERSECTION_ALL_LAYERS )
     {
         OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[0]->GetLayerDefn();
-        int i;
-        for(i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
+        for( int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++ )
             poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
-        for(i = 0; i < poSrcFeatureDefn->GetGeomFieldCount(); i++)
+        for( int i = 0; i < poSrcFeatureDefn->GetGeomFieldCount(); i++ )
         {
             OGRGeomFieldDefn* poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
             poFeatureDefn->AddGeomFieldDefn(
@@ -411,11 +413,14 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
         }
 
         /* Remove any field that is not found in the source layers */
-        for(int iLayer = 1; iLayer < nSrcLayers; iLayer++)
+        for( int iLayer = 1; iLayer < nSrcLayers; iLayer++ )
         {
             OGRFeatureDefn* l_poSrcFeatureDefn =
                                         papoSrcLayers[iLayer]->GetLayerDefn();
-            for(i = iCompareFirstIndex; i < poFeatureDefn->GetFieldCount();)
+            for( int i = iCompareFirstIndex;
+                 i < poFeatureDefn->GetFieldCount();
+                 // No increment.
+                 )
             {
                 OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
                 int nSrcIndex = l_poSrcFeatureDefn->GetFieldIndex(
@@ -430,10 +435,13 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
                         l_poSrcFeatureDefn->GetFieldDefn(nSrcIndex);
                     MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
 
-                    i ++;
+                    i++;
                 }
             }
-            for(i = 0; i < poFeatureDefn->GetGeomFieldCount();)
+            for( int i = 0;
+                 i < poFeatureDefn->GetGeomFieldCount();
+                 // No increment.
+                 )
             {
                 OGRGeomFieldDefn* poFieldDefn = poFeatureDefn->GetGeomFieldDefn(i);
                 int nSrcIndex = l_poSrcFeatureDefn->GetGeomFieldIndex(
@@ -446,7 +454,7 @@ OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
                 {
                     /* TODO: merge type, SRS, extent ? */
 
-                    i ++;
+                    i++;
                 }
             }
         }
@@ -768,7 +776,7 @@ OGRFeature *OGRUnionLayer::GetFeature( GIntBig nFeatureId )
 
 OGRErr OGRUnionLayer::ICreateFeature( OGRFeature* poFeature )
 {
-    if( osSourceLayerFieldName.size() == 0 )
+    if( osSourceLayerFieldName.empty() )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "CreateFeature() not supported when SourceLayerFieldName is not set");
@@ -782,7 +790,7 @@ OGRErr OGRUnionLayer::ICreateFeature( OGRFeature* poFeature )
         return OGRERR_FAILURE;
     }
 
-    if( !poFeature->IsFieldSet(0) )
+    if( !poFeature->IsFieldSetAndNotNull(0) )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "CreateFeature() not supported when '%s' field is not set",
@@ -827,7 +835,7 @@ OGRErr OGRUnionLayer::ISetFeature( OGRFeature* poFeature )
         return OGRERR_FAILURE;
     }
 
-    if( osSourceLayerFieldName.size() == 0 )
+    if( osSourceLayerFieldName.empty() )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "SetFeature() not supported when SourceLayerFieldName is not set");
@@ -841,7 +849,7 @@ OGRErr OGRUnionLayer::ISetFeature( OGRFeature* poFeature )
         return OGRERR_FAILURE;
     }
 
-    if( !poFeature->IsFieldSet(0) )
+    if( !poFeature->IsFieldSetAndNotNull(0) )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "SetFeature() not supported when '%s' field is not set",
@@ -1090,7 +1098,7 @@ int  OGRUnionLayer::TestCapability( const char * pszCap )
 
     if( EQUAL(pszCap, OLCRandomWrite ) )
     {
-        if( !bPreserveSrcFID || osSourceLayerFieldName.size() == 0)
+        if( !bPreserveSrcFID || osSourceLayerFieldName.empty())
             return FALSE;
 
         for(int i = 0; i < nSrcLayers; i++)
@@ -1103,7 +1111,7 @@ int  OGRUnionLayer::TestCapability( const char * pszCap )
 
     if( EQUAL(pszCap, OLCSequentialWrite ) )
     {
-        if( osSourceLayerFieldName.size() == 0)
+        if( osSourceLayerFieldName.empty())
             return FALSE;
 
         for(int i = 0; i < nSrcLayers; i++)
@@ -1213,7 +1221,6 @@ void OGRUnionLayer::SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
     }
 }
 
-
 /************************************************************************/
 /*                        TranslateFromSrcLayer()                       */
 /************************************************************************/
@@ -1226,7 +1233,7 @@ OGRFeature* OGRUnionLayer::TranslateFromSrcLayer(OGRFeature* poSrcFeature)
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
     poFeature->SetFrom(poSrcFeature, panMap, TRUE);
 
-    if( osSourceLayerFieldName.size() &&
+    if( !osSourceLayerFieldName.empty() &&
         !poFeatureDefn->GetFieldDefn(0)->IsIgnored() )
     {
         poFeature->SetField(0, papoSrcLayers[iCurLayer]->GetName());
@@ -1287,3 +1294,5 @@ OGRErr OGRUnionLayer::SyncToDisk()
 
     return OGRERR_NONE;
 }
+
+#endif /* #ifndef DOXYGEN_SKIP */
diff --git a/ogr/ogrsf_frmts/generic/ogrunionlayer.h b/ogr/ogrsf_frmts/generic/ogrunionlayer.h
index 529ad07..72ad39a 100644
--- a/ogr/ogrsf_frmts/generic/ogrunionlayer.h
+++ b/ogr/ogrsf_frmts/generic/ogrunionlayer.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrunionlayer.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogrunionlayer.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRUnionLayer class
@@ -30,6 +30,8 @@
 #ifndef OGRUNIONLAYER_H_INCLUDED
 #define OGRUNIONLAYER_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrsf_frmts.h"
 
 /************************************************************************/
@@ -45,8 +47,8 @@ class OGRUnionLayerGeomFieldDefn: public OGRGeomFieldDefn
     OGREnvelope     sStaticEnvelope;
 
             OGRUnionLayerGeomFieldDefn(const char* pszName, OGRwkbGeometryType eType);
-            OGRUnionLayerGeomFieldDefn(OGRGeomFieldDefn* poSrc);
-            OGRUnionLayerGeomFieldDefn(OGRUnionLayerGeomFieldDefn* poSrc);
+   explicit OGRUnionLayerGeomFieldDefn(OGRGeomFieldDefn* poSrc);
+   explicit OGRUnionLayerGeomFieldDefn(OGRUnionLayerGeomFieldDefn* poSrc);
            ~OGRUnionLayerGeomFieldDefn();
 };
 
@@ -117,37 +119,39 @@ class OGRUnionLayer : public OGRLayer
     void                SetSourceLayerFieldName(const char* pszSourceLayerFieldName);
     void                SetPreserveSrcFID(int bPreserveSrcFID);
     void                SetFeatureCount(int nFeatureCount);
-    virtual const char  *GetName() { return osName.c_str(); }
-    virtual OGRwkbGeometryType GetGeomType();
+    virtual const char  *GetName() override { return osName.c_str(); }
+    virtual OGRwkbGeometryType GetGeomType() override;
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRErr      ICreateFeature( OGRFeature* poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature* poFeature ) override;
 
-    virtual OGRErr      ISetFeature( OGRFeature* poFeature );
+    virtual OGRErr      ISetFeature( OGRFeature* poFeature ) override;
 
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual GIntBig     GetFeatureCount( int );
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry * poGeomIn );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+    virtual void        SetSpatialFilter( OGRGeometry * poGeomIn ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
 
-    virtual OGRErr      SetIgnoredFields( const char **papszFields );
+    virtual OGRErr      SetIgnoredFields( const char **papszFields ) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif // OGRUNIONLAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp
index c830a8d..17d4378 100644
--- a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp
+++ b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwarpedlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRWarpedLayer class
@@ -27,9 +26,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrwarpedlayer.h"
 
-CPL_CVSID("$Id: ogrwarpedlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+CPL_CVSID("$Id: ogrwarpedlayer.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 /************************************************************************/
 /*                          OGRWarpedLayer()                            */
@@ -40,24 +41,20 @@ OGRWarpedLayer::OGRWarpedLayer( OGRLayer* poDecoratedLayer,
                                 int bTakeOwnership,
                                 OGRCoordinateTransformation* poCT,
                                 OGRCoordinateTransformation* poReversedCT ) :
-                                      OGRLayerDecorator(poDecoratedLayer,
-                                                        bTakeOwnership),
-                                      m_iGeomField(iGeomField),
-                                      m_poCT(poCT),
-                                      m_poReversedCT(poReversedCT)
+    OGRLayerDecorator(poDecoratedLayer, bTakeOwnership),
+    m_poFeatureDefn(NULL),
+    m_iGeomField(iGeomField),
+    m_poCT(poCT),
+    m_poReversedCT(poReversedCT),
+    m_poSRS(m_poCT->GetTargetCS())
 {
     CPLAssert(poCT != NULL);
     SetDescription( poDecoratedLayer->GetDescription() );
 
-    m_poFeatureDefn = NULL;
-
-    if( m_poCT->GetTargetCS() != NULL )
+    if( m_poSRS != NULL )
     {
-        m_poSRS = m_poCT->GetTargetCS();
         m_poSRS->Reference();
     }
-    else
-        m_poSRS = NULL;
 }
 
 /************************************************************************/
@@ -162,7 +159,6 @@ void OGRWarpedLayer::SetSpatialFilterRect( int iGeomField, double dfMinX, double
     OGRLayer::SetSpatialFilterRect(iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
 }
 
-
 /************************************************************************/
 /*                     SrcFeatureToWarpedFeature()                      */
 /************************************************************************/
@@ -185,7 +181,6 @@ OGRFeature *OGRWarpedLayer::SrcFeatureToWarpedFeature(OGRFeature* poSrcFeature)
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                     WarpedFeatureToSrcFeature()                      */
 /************************************************************************/
@@ -295,7 +290,6 @@ OGRErr      OGRWarpedLayer::ICreateFeature( OGRFeature *poFeature )
     return eErr;
 }
 
-
 /************************************************************************/
 /*                            GetLayerDefn()                           */
 /************************************************************************/
@@ -382,11 +376,11 @@ OGRErr      OGRWarpedLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int
 /************************************************************************/
 
 static double TransformAndUpdateBBAndReturnX(
-                                   OGRCoordinateTransformation* poCT,
-                                   double dfX, double dfY,
-                                   double& dfMinX, double& dfMinY, double& dfMaxX, double& dfMaxY)
+    OGRCoordinateTransformation* poCT,
+    double dfX, double dfY,
+    double& dfMinX, double& dfMinY, double& dfMaxX, double& dfMaxY )
 {
-    int bSuccess;
+    int bSuccess = FALSE;
     poCT->TransformEx( 1, &dfX, &dfY, NULL, &bSuccess );
     if( bSuccess )
     {
@@ -396,8 +390,8 @@ static double TransformAndUpdateBBAndReturnX(
         if( dfY > dfMaxY ) dfMaxY = dfY;
         return dfX;
     }
-    else
-        return 0.0;
+
+    return 0.0;
 }
 
 /************************************************************************/
@@ -432,16 +426,16 @@ static void FindXDiscontinuity(OGRCoordinateTransformation* poCT,
 int OGRWarpedLayer::ReprojectEnvelope( OGREnvelope* psEnvelope,
                                        OGRCoordinateTransformation* poCT )
 {
-#define NSTEP   20
+    const int NSTEP = 20;
     double dfXStep = (psEnvelope->MaxX - psEnvelope->MinX) / NSTEP;
     double dfYStep = (psEnvelope->MaxY - psEnvelope->MinY) / NSTEP;
-    int i, j;
-    double *padfX, *padfY;
-    int* pabSuccess;
 
-    padfX = (double*) VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double));
-    padfY = (double*) VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double));
-    pabSuccess = (int*) VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(int));
+    double *padfX = (double*)
+        VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double));
+    double *padfY = (double*)
+        VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double));
+    int* pabSuccess = (int*)
+        VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(int));
     if( padfX == NULL || padfY == NULL || pabSuccess == NULL)
     {
         VSIFree(padfX);
@@ -450,9 +444,9 @@ int OGRWarpedLayer::ReprojectEnvelope( OGREnvelope* psEnvelope,
         return FALSE;
     }
 
-    for(j = 0; j <= NSTEP; j++)
+    for( int j = 0; j <= NSTEP; j++ )
     {
-        for(i = 0; i <= NSTEP; i++)
+        for( int i = 0; i <= NSTEP; i++ )
         {
             padfX[j * (NSTEP + 1) + i] = psEnvelope->MinX + i * dfXStep;
             padfY[j * (NSTEP + 1) + i] = psEnvelope->MinY + j * dfYStep;
@@ -464,14 +458,18 @@ int OGRWarpedLayer::ReprojectEnvelope( OGREnvelope* psEnvelope,
     if( poCT->TransformEx( (NSTEP + 1) * (NSTEP + 1), padfX, padfY, NULL,
                             pabSuccess ) )
     {
-        double dfMinX = 0.0, dfMinY = 0.0, dfMaxX = 0.0, dfMaxY = 0.0;
+        double dfMinX = 0.0;
+        double dfMinY = 0.0;
+        double dfMaxX = 0.0;
+        double dfMaxY = 0.0;
         int bSet = FALSE;
-        for(j = 0; j <= NSTEP; j++)
+        for( int j = 0; j <= NSTEP; j++ )
         {
             double dfXOld = 0.0;
             double dfDXOld = 0.0;
-            int iOld = -1, iOldOld = -1;
-            for(i = 0; i <= NSTEP; i++)
+            int iOld = -1;
+            int iOldOld = -1;
+            for( int i = 0; i <= NSTEP; i++ )
             {
                 if( pabSuccess[j * (NSTEP + 1) + i] )
                 {
@@ -480,8 +478,10 @@ int OGRWarpedLayer::ReprojectEnvelope( OGREnvelope* psEnvelope,
 
                     if( !bSet )
                     {
-                        dfMinX = dfMaxX = dfX;
-                        dfMinY = dfMaxY = dfY;
+                        dfMinX = dfX;
+                        dfMaxX = dfX;
+                        dfMinY = dfY;
+                        dfMaxY = dfY;
                         bSet = TRUE;
                     }
                     else
@@ -509,7 +509,6 @@ int OGRWarpedLayer::ReprojectEnvelope( OGREnvelope* psEnvelope,
                     dfXOld = dfX;
                     iOldOld = iOld;
                     iOld = i;
-
                 }
             }
         }
@@ -570,3 +569,5 @@ void OGRWarpedLayer::SetExtent( double dfXMin, double dfYMin,
     sStaticEnvelope.MaxX = dfXMax;
     sStaticEnvelope.MaxY = dfYMax;
 }
+
+#endif /* #ifndef DOXYGEN_SKIP */
diff --git a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h
index cade5e8..9642873 100644
--- a/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h
+++ b/ogr/ogrsf_frmts/generic/ogrwarpedlayer.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwarpedlayer.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogrwarpedlayer.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines OGRWarpedLayer class
@@ -30,6 +30,8 @@
 #ifndef OGRWARPEDLAYER_H_INCLUDED
 #define OGRWARPEDLAYER_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "ogrlayerdecorator.h"
 
 /************************************************************************/
@@ -65,27 +67,29 @@ class OGRWarpedLayer : public OGRLayerDecorator
 
     void                SetExtent(double dfXMin, double dfYMin, double dfXMax, double dfYMax);
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
     virtual void        SetSpatialFilterRect( double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
+                                              double dfMaxX, double dfMaxY ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
     virtual void        SetSpatialFilterRect( int iGeomField, double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY );
+                                              double dfMaxX, double dfMaxY ) override;
 
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeature *GetFeature( GIntBig nFID );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeature *GetFeature( GIntBig nFID ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
 
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif //  OGRWARPEDLAYER_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept.c b/ogr/ogrsf_frmts/geoconcept/geoconcept.c
index 15b1ec6..e951dea 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept.c
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: geoconcept.c
+ * $Id: geoconcept.c 36457 2016-11-23 00:18:37Z rouault $
  *
  * Name:     geoconcept.c
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -29,13 +29,14 @@
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************/
 
+#include "cpl_port.h"
 #include <math.h>
 #include "geoconcept.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_core.h"
 
-CPL_CVSID("$Id: geoconcept.c,v 1.0.0 2007-11-03 20:58:19 drichard Exp $")
+CPL_CVSID("$Id: geoconcept.c 36457 2016-11-23 00:18:37Z rouault $")
 
 #define kItemSize_GCIO      256
 #define kExtraSize_GCIO    4096
@@ -1437,7 +1438,8 @@ static GCExportFileMetadata GCIOAPI_CALL1(*) _parsePragma_GCIO (
     int v, z;
     GCSysCoord* syscoord;
     /* //$SYSCOORD {Type: int} [ ; { TimeZone: TimeZoneValue } ] */
-    v= -1, z= -1;
+    v= -1;
+    z= -1;
     if( (p= strchr(p,':')) )
     {
       p++;
@@ -1719,18 +1721,20 @@ static GCExportFileMetadata GCIOAPI_CALL1(*) _parsePragma_GCIO (
       if( EQUALN(p,kPrivate_GCIO,strlen(kPrivate_GCIO)) )
       {
         p+= strlen(kPrivate_GCIO);
-        e= p-1, *e= '@';
+        e= p-1;
+        *e= '@';
       }
       nm= CPLStrdup(e);
       CPLDebug("GEOCONCEPT", "%d e=[%s]\n", __LINE__, e);
-      if( (theField= AddSubTypeField_GCIO(hGXT,GetTypeName_GCIO(theClass),
+      theField= AddSubTypeField_GCIO(hGXT,GetTypeName_GCIO(theClass),
                                                GetSubTypeName_GCIO(theSubType),
                                                -1,
                                                nm,
                                                -1,
                                                vUnknownItemType_GCIO,
                                                NULL,
-                                               NULL))==NULL )
+                                               NULL);
+      if( theField == NULL )
       {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Geoconcept export syntax error at line %ld.\n",
@@ -1748,9 +1752,9 @@ static GCExportFileMetadata GCIOAPI_CALL1(*) _parsePragma_GCIO (
     return Meta;
   }
   /* end of definitions ... */ /* FIXME */
-  if( (p= strstr(GetGCCache_GCIO(hGXT),k3DOBJECTMONO_GCIO)) ||
-      (p= strstr(GetGCCache_GCIO(hGXT),k3DOBJECT_GCIO))     ||
-      (p= strstr(GetGCCache_GCIO(hGXT),k2DOBJECT_GCIO)) )
+  if( (strstr(GetGCCache_GCIO(hGXT),k3DOBJECTMONO_GCIO)) ||
+      (strstr(GetGCCache_GCIO(hGXT),k3DOBJECT_GCIO))     ||
+      (strstr(GetGCCache_GCIO(hGXT),k2DOBJECT_GCIO)) )
     /* next reading will be in cache ! */
     SetGCStatus_GCIO(hGXT,vMemoStatus_GCIO);
   /* unknown pragma ... */
@@ -1833,11 +1837,14 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
      * displayed to represent the ponctual entity or angle of the text entity
      * NOT IMPLEMENTED
      */
-    x= CPLAtof(pszFields[i]), i++;
-    y= CPLAtof(pszFields[i]), i++;
+    x= CPLAtof(pszFields[i]);
+    i++;
+    y= CPLAtof(pszFields[i]);
+    i++;
     if( d==v3D_GCIO||d==v3DM_GCIO )
     {
-      z= CPLAtof(pszFields[i]), i++;
+      z= CPLAtof(pszFields[i]);
+      i++;
     }
     if( buildGeom )
     {
@@ -1859,11 +1866,14 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
      * More Graphics :
      * XP<>YP[<>ZP]Nr points=k[<>X<>Y[<>Z]]k...
      */
-    x= CPLAtof(pszFields[i]), i++;
-    y= CPLAtof(pszFields[i]), i++;
+    x= CPLAtof(pszFields[i]);
+    i++;
+    y= CPLAtof(pszFields[i]);
+    i++;
     if( d==v3D_GCIO||d==v3DM_GCIO )
     {
-      z= CPLAtof(pszFields[i]), i++;
+      z= CPLAtof(pszFields[i]);
+      i++;
     }
     if( buildGeom )
     {
@@ -1883,14 +1893,18 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
     {
       i++;
     }
-    np= atoi(pszFields[i]), i++;
+    np= atoi(pszFields[i]);
+    i++;
     for( ip= 1; ip<=np; ip++ )
     {
-      x= CPLAtof(pszFields[i]), i++;
-      y= CPLAtof(pszFields[i]), i++;
+      x= CPLAtof(pszFields[i]);
+      i++;
+      y= CPLAtof(pszFields[i]);
+      i++;
       if( d==v3D_GCIO || d==v3DM_GCIO )
       {
-        z= CPLAtof(pszFields[i]), i++;
+        z= CPLAtof(pszFields[i]);
+        i++;
       }
       if( buildGeom )
       {
@@ -1944,11 +1958,14 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
         OGR_G_AssignSpatialReference(ring,GetMetaSRS_GCIO(Meta));
       }
     }
-    x= CPLAtof(pszFields[i]), i++;
-    y= CPLAtof(pszFields[i]), i++;
+    x= CPLAtof(pszFields[i]);
+    i++;
+    y= CPLAtof(pszFields[i]);
+    i++;
     if( d==v3D_GCIO||d==v3DM_GCIO )
     {
-      z= CPLAtof(pszFields[i]), i++;
+      z= CPLAtof(pszFields[i]);
+      i++;
     }
     if( buildGeom )
     {
@@ -1961,14 +1978,18 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
     {
       MergeOGREnvelope_GCIO(bbox,x,y);
     }
-    np= atoi(pszFields[i]), i++;
+    np= atoi(pszFields[i]);
+    i++;
     for( ip= 1; ip<=np; ip++ )
     {
-      x= CPLAtof(pszFields[i]), i++;
-      y= CPLAtof(pszFields[i]), i++;
+      x= CPLAtof(pszFields[i]);
+      i++;
+      y= CPLAtof(pszFields[i]);
+      i++;
       if( d==v3D_GCIO||d==v3DM_GCIO )
       {
-        z= CPLAtof(pszFields[i]), i++;
+        z= CPLAtof(pszFields[i]);
+        i++;
       }
       if( buildGeom )
       {
@@ -1995,10 +2016,11 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
         goto onError;
       }
     }
-    /* additionnal ring : either holes, or islands */
+    /* additional ring : either holes, or islands */
     if( i < nbtp-1 )
     {
-      npo= atoi(pszFields[i]), i++;
+      npo= atoi(pszFields[i]);
+      i++;
       for( ipo= 1; ipo<=npo; ipo++ )
       {
         if( buildGeom )
@@ -2013,11 +2035,14 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
             OGR_G_AssignSpatialReference(ring,GetMetaSRS_GCIO(Meta));
           }
         }
-        x= CPLAtof(pszFields[i]), i++;
-        y= CPLAtof(pszFields[i]), i++;
+        x= CPLAtof(pszFields[i]);
+        i++;
+        y= CPLAtof(pszFields[i]);
+        i++;
         if( d==v3D_GCIO||d==v3DM_GCIO )
         {
-          z= CPLAtof(pszFields[i]), i++;
+          z= CPLAtof(pszFields[i]);
+          i++;
         }
         if( buildGeom )
         {
@@ -2030,14 +2055,18 @@ static OGRGeometryH GCIOAPI_CALL _buildOGRGeometry_GCIO (
         {
           MergeOGREnvelope_GCIO(bbox,x,y);
         }
-        np= atoi(pszFields[i]), i++;
+        np= atoi(pszFields[i]);
+        i++;
         for( ip= 1; ip<=np; ip++ )
         {
-          x= CPLAtof(pszFields[i]), i++;
-          y= CPLAtof(pszFields[i]), i++;
+          x= CPLAtof(pszFields[i]);
+          i++;
+          y= CPLAtof(pszFields[i]);
+          i++;
           if( d==v3D_GCIO||d==v3DM_GCIO )
           {
-            z= CPLAtof(pszFields[i]), i++;
+            z= CPLAtof(pszFields[i]);
+            i++;
           }
           if( buildGeom )
           {
@@ -2148,7 +2177,7 @@ static OGRFeatureH GCIOAPI_CALL _buildOGRFeature_GCIO (
                                                       )
 {
   GCExportFileMetadata* Meta;
-  char **pszFields, delim[2], tdst[kItemSize_GCIO];
+  char **pszFields, delim[2] = { 0 }, tdst[kItemSize_GCIO];
   int whereClass, whereSubType, i, j, nbstf, nbf, nbtf, buildFeature;
   GCType* theClass;
   GCField* theField;
@@ -2161,7 +2190,8 @@ static OGRFeatureH GCIOAPI_CALL _buildOGRFeature_GCIO (
   fd= NULL;
   f= NULL;
   Meta= GetGCMeta_GCIO(H);
-  delim[0]= GetMetaDelimiter_GCIO(Meta), delim[1]= '\0';
+  delim[0]= GetMetaDelimiter_GCIO(Meta);
+  delim[1]= '\0';
   if( d==vUnknown3D_GCIO) d= v2D_GCIO;
   if( bbox==NULL )
   {
@@ -2291,7 +2321,8 @@ static OGRFeatureH GCIOAPI_CALL _buildOGRFeature_GCIO (
   if( nbstf==-1 )
   {
     /* figure out how many user's attributes we've got : */
-    i= 1 + nbf, nbstf= 0;
+    i= 1 + nbf;
+    nbstf= 0;
     while( (theField= GetSubTypeField_GCIO(*theSubType,i)) )
     {
       if( IsPrivateField_GCIO(theField) ) { break; };//FIXME: could count geometry private fields ...
@@ -3019,7 +3050,10 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
                                                  )
 {
   int bEOF;
-  char *k, n[kItemSize_GCIO], x[kExtraSize_GCIO], e[kExtraSize_GCIO];
+  char *k;
+  char n[kItemSize_GCIO] = {0};
+  char x[kExtraSize_GCIO] = {0};
+  char e[kExtraSize_GCIO] = {0};
   const char* normName;
   long id;
   GCTypeKind knd;
@@ -3092,7 +3126,8 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
                     GetGCCache_GCIO(hGCT));
           goto onError;
         }
-        strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
+        strncpy(n,k,kItemSize_GCIO-1);
+        n[kItemSize_GCIO-1]= '\0';
       }
       else
         if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigID_GCIO))!=NULL )
@@ -3162,7 +3197,8 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
                           GetGCCache_GCIO(hGCT));
                 goto onError;
               }
-              strncpy(x,k,kExtraSize_GCIO-1), x[kExtraSize_GCIO-1]= '\0';
+              strncpy(x,k,kExtraSize_GCIO-1);
+              x[kExtraSize_GCIO-1]= '\0';
             }
             else
               if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigList_GCIO))!=NULL )
@@ -3181,7 +3217,8 @@ static OGRErr GCIOAPI_CALL _readConfigField_GCIO (
                             GetGCCache_GCIO(hGCT));
                   goto onError;
                 }
-                strncpy(e,k,kExtraSize_GCIO-1), e[kExtraSize_GCIO-1]= '\0';
+                strncpy(e,k,kExtraSize_GCIO-1);
+                e[kExtraSize_GCIO-1]= '\0';
               }
               else
               { /* Skipping ... */
@@ -3210,7 +3247,10 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
                                                      )
 {
   int bEOF;
-  char *k, n[kItemSize_GCIO], x[kExtraSize_GCIO], e[kExtraSize_GCIO];
+  char *k;
+  char n[kItemSize_GCIO] = {0};
+  char x[kExtraSize_GCIO] = {0};
+  char e[kExtraSize_GCIO] = {0};
   long id;
   GCTypeKind knd;
   GCField* theField;
@@ -3264,7 +3304,8 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
                     GetGCCache_GCIO(hGCT));
           goto onError;
         }
-        strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
+        strncpy(n,k,kItemSize_GCIO-1);
+        n[kItemSize_GCIO-1]= '\0';
       }
       else
         if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigID_GCIO))!=NULL )
@@ -3334,7 +3375,8 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
                           GetGCCache_GCIO(hGCT));
                 goto onError;
               }
-              strncpy(x,k,kExtraSize_GCIO-1), x[kExtraSize_GCIO-1]= '\0';
+              strncpy(x,k,kExtraSize_GCIO-1);
+              x[kExtraSize_GCIO-1]= '\0';
             }
             else
               if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigList_GCIO))!=NULL )
@@ -3353,7 +3395,8 @@ static OGRErr GCIOAPI_CALL _readConfigFieldType_GCIO (
                             GetGCCache_GCIO(hGCT));
                   goto onError;
                 }
-                strncpy(e,k,kExtraSize_GCIO-1), e[kExtraSize_GCIO-1]= '\0';
+                strncpy(e,k,kExtraSize_GCIO-1);
+                e[kExtraSize_GCIO-1]= '\0';
               }
               else
               { /* Skipping ... */
@@ -3383,7 +3426,10 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
                                                         )
 {
   int bEOF;
-  char *k, n[kItemSize_GCIO], x[kExtraSize_GCIO], e[kExtraSize_GCIO];
+  char *k;
+  char n[kItemSize_GCIO] = {0};
+  char x[kExtraSize_GCIO] = {0};
+  char e[kExtraSize_GCIO] = {0};
   long id;
   GCTypeKind knd;
   GCField* theField;
@@ -3436,7 +3482,8 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
                     GetGCCache_GCIO(hGCT));
           goto onError;
         }
-        strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
+        strncpy(n,k,kItemSize_GCIO-1);
+        n[kItemSize_GCIO-1]= '\0';
       }
       else
         if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigID_GCIO))!=NULL )
@@ -3506,7 +3553,8 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
                           GetGCCache_GCIO(hGCT));
                 goto onError;
               }
-              strncpy(x,k,kExtraSize_GCIO-1), x[kExtraSize_GCIO-1]= '\0';
+              strncpy(x,k,kExtraSize_GCIO-1);
+              x[kExtraSize_GCIO-1]= '\0';
             }
             else
               if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigList_GCIO))!=NULL )
@@ -3525,7 +3573,8 @@ static OGRErr GCIOAPI_CALL _readConfigFieldSubType_GCIO (
                             GetGCCache_GCIO(hGCT));
                   goto onError;
                 }
-                strncpy(e,k,kExtraSize_GCIO-1), e[kExtraSize_GCIO-1]= '\0';
+                strncpy(e,k,kExtraSize_GCIO-1);
+                e[kExtraSize_GCIO-1]= '\0';
               }
               else
               { /* Skipping ... */
@@ -3554,7 +3603,8 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
                                                        )
 {
   int eost, res;
-  char *k, n[kItemSize_GCIO];
+  char *k;
+  char n[kItemSize_GCIO] = { 0 };
   long id;
   GCTypeKind knd;
   GCDim sys;
@@ -3596,7 +3646,8 @@ static OGRErr GCIOAPI_CALL _readConfigSubTypeType_GCIO (
                     GetGCCache_GCIO(hGCT));
           goto onError;
         }
-        strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
+        strncpy(n,k,kItemSize_GCIO-1);
+        n[kItemSize_GCIO-1]= '\0';
       }
       else
         if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigID_GCIO))!=NULL )
@@ -3730,7 +3781,8 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
                                                 )
 {
   int eot, res;
-  char *k, n[kItemSize_GCIO];
+  char *k;
+  char n[kItemSize_GCIO] = { 0 };
   long id;
   GCType *theClass;
 
@@ -3768,7 +3820,8 @@ static OGRErr GCIOAPI_CALL _readConfigType_GCIO (
                     GetGCCache_GCIO(hGCT));
           goto onError;
         }
-        strncpy(n,k,kItemSize_GCIO-1), n[kItemSize_GCIO-1]= '\0';
+        strncpy(n,k,kItemSize_GCIO-1);
+        n[kItemSize_GCIO-1]= '\0';
       }
       else
         if( (k= strstr(GetGCCache_GCIO(hGCT),kConfigID_GCIO))!=NULL )
@@ -4041,7 +4094,8 @@ onError:
               for (il= 0; il<nl; il++)
               {
                 v= CSLGetField(GetFieldList_GCIO(theField),il);
-                snprintf(l+ll,kExtraSize_GCIO-ll-1,"%s;", v), l[kExtraSize_GCIO-1]= '\0';
+                snprintf(l+ll,kExtraSize_GCIO-ll-1,"%s;", v);
+                l[kExtraSize_GCIO-1]= '\0';
                 ll+= (int)strlen(v);
               }
             }
@@ -4135,7 +4189,8 @@ onError:
                         for (il= 0; il<nl; il++)
                         {
                           v= CSLGetField(GetFieldList_GCIO(theField),il);
-                          snprintf(l+ll,kExtraSize_GCIO-ll-1,"%s;", v), l[kExtraSize_GCIO-1]= '\0';
+                          snprintf(l+ll,kExtraSize_GCIO-ll-1,"%s;", v);
+                          l[kExtraSize_GCIO-1]= '\0';
                           ll+= (int)strlen(v);
                         }
                       }
@@ -5220,7 +5275,8 @@ int GCIOAPI_CALL WriteFeatureFieldAsString_GCIO (
     quotes= "";
   }
   delim= GetMetaDelimiter_GCIO(GetGCMeta_GCIO(H));
-  if( !(theField= GetSubTypeField_GCIO(theSubType,iField)) )
+  theField= GetSubTypeField_GCIO(theSubType,iField);
+  if( !theField )
   {
     CPLError( CE_Failure, CPLE_NotSupported,
               "Attempt to write a field #%d that does not exist on feature %s.%s.\n",
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept.h b/ogr/ogrsf_frmts/geoconcept/geoconcept.h
index f26941b..b1e7bde 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept.h
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: geoconcept.h
+ * $Id: geoconcept.h$
  *
  * Name:     geoconcept.h
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -496,5 +496,4 @@ OGRFeatureH GCIOAPI_CALL ReadNextFeature_GCIO ( GCSubType* theSubType );
 }
 #endif
 
-
 #endif /* ndef GEOCONCEPT_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c
index 4ada5d0..745cc09 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.c
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: geoconcept_syscoord.c
+ * $Id: geoconcept_syscoord.c$
  *
  * Name:     geoconcept_syscoord.c
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -33,7 +33,7 @@
 #include "geoconcept_syscoord.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: geoconcept_syscoord.c,v 1.0.0 2007-12-24 15:40:28 drichard Exp $")
+CPL_CVSID("$Id: geoconcept_syscoord.c 36471 2016-11-23 16:36:44Z rouault $")
 
 /* -------------------------------------------------------------------- */
 /*      GCSRS globals                                                   */
@@ -547,15 +547,16 @@ static GCSysCoord GCSRSAPI_CALL1(*) _findSysCoord_GCSRS ( GCSysCoord* theSysCoor
 
     if( fabs(GetSysCoordCentralMeridian_GCSRS(gcsc) - GetSysCoordCentralMeridian_GCSRS(theSysCoord) ) > 1e-8 )
     {
-      switch( GetSysCoordProjID_GCSRS(gcsc) )
+      /* UTM family: central meridian is the 6* zone - 183 (in degrees) */
+      if( GetSysCoordProjID_GCSRS(gcsc) == 1 &&
+          /* generic UTM definition */
+          GetSysCoordCentralMeridian_GCSRS(gcsc)==0.0 )
       {
-        case    1 : /* UTM family: central meridian is the 6* zone - 183 (in degrees) */
-          if( GetSysCoordCentralMeridian_GCSRS(gcsc)==0.0 ) /* generic UTM definition */
-          {
-            break;
-          }
-        default   :
-          continue;
+        /* go on */
+      }
+      else
+      {
+        continue;
       }
     }
     if( fabs(GetSysCoordLatitudeOfOrigin_GCSRS(gcsc) - GetSysCoordLatitudeOfOrigin_GCSRS(theSysCoord) ) > 1e-8 ) continue;
diff --git a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h
index ec783b4..ede167c 100644
--- a/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h
+++ b/ogr/ogrsf_frmts/geoconcept/geoconcept_syscoord.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: geoconcept_syscoord.h
+ * $Id: geoconcept_syscoord.h$
  *
  * Name:     geoconcept_syscoord.h
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -185,5 +185,4 @@ OGRSpatialReferenceH GCSRSAPI_CALL SysCoord2OGRSpatialReference_GCSRS ( GCSysCoo
 }
 #endif
 
-
 #endif /* ndef GEOCONCEPT_SYSCOORD_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
index 9f27ba8..6844e5f 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeoconceptdatasource.cpp
  *
  * Name:     ogrgeoconceptdatasource.h
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -34,7 +33,7 @@
 #include "ogrgeoconceptdatasource.h"
 #include "ogrgeoconceptlayer.h"
 
-CPL_CVSID("$Id: ogrgeoconceptdatasource.cpp 00000 2007-11-03 11:49:22Z drichard $");
+CPL_CVSID("$Id: ogrgeoconceptdatasource.cpp 35008 2016-08-09 11:20:52Z goatbar $");
 
 /************************************************************************/
 /*                         OGRGeoconceptDataSource()                    */
@@ -322,7 +321,7 @@ OGRLayer *OGRGeoconceptDataSource::ICreateLayer( const char * pszLayerName,
     /*
      * pszLayerName Class.Subclass if -nln option used, otherwise file name
      */
-    const char *pszFeatureType;
+    const char *pszFeatureType = NULL;
     char pszln[512];
 
     if( !(pszFeatureType = CSLFetchNameValue(papszOptions,"FEATURETYPE")) )
@@ -338,8 +337,8 @@ OGRLayer *OGRGeoconceptDataSource::ICreateLayer( const char * pszLayerName,
         pszFeatureType= pszLayerName;
     }
 
-    char **ft;
-    if( !(ft= CSLTokenizeString2(pszFeatureType,".",0)) ||
+    char **ft = CSLTokenizeString2(pszFeatureType,".",0);
+    if( !ft ||
         CSLCount(ft)!=2 )
     {
       CSLDestroy(ft);
@@ -428,10 +427,10 @@ OGRLayer *OGRGeoconceptDataSource::ICreateLayer( const char * pszLayerName,
       }
     if( !poFile )
     {
-      GCSubType* aSubclass= NULL;
-      GCExportFileMetadata* m;
+      GCSubType* aSubclass = NULL;
+      GCExportFileMetadata* m = GetGCMeta_GCIO(_hGXT);
 
-      if( !(m= GetGCMeta_GCIO(_hGXT)) )
+      if( !m )
       {
         if( !(m= CreateHeader_GCIO()) )
         {
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.h b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.h
index 9f4ca4c..538fec8 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.h
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdatasource.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: ogrgeoconceptdatasource.h
+ * $Id: ogrgeoconceptdatasource.h$
  *
  * Name:     ogrgeoconceptdatasource.h
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -59,16 +59,16 @@ class OGRGeoconceptDataSource : public OGRDataSource
     int            Open( const char* pszName, bool bTestOpen, bool bUpdate );
     int            Create( const char* pszName, char** papszOptions );
 
-    const char*    GetName() { return _pszName; }
-    int            GetLayerCount() { return _nLayers; }
-    OGRLayer*      GetLayer( int iLayer );
+    const char*    GetName() override { return _pszName; }
+    int            GetLayerCount() override { return _nLayers; }
+    OGRLayer*      GetLayer( int iLayer ) override;
 //    OGRErr         DeleteLayer( int iLayer );
-    int            TestCapability( const char* pszCap );
+    int            TestCapability( const char* pszCap ) override;
 
     OGRLayer*      ICreateLayer( const char* pszName,
                                 OGRSpatialReference* poSpatialRef = NULL,
                                 OGRwkbGeometryType eGType = wkbUnknown,
-                                char** papszOptions = NULL );
+                                char** papszOptions = NULL ) override;
   private:
     int            LoadFile( const char * );
 };
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp
index 16c3c45..9c3d5bd 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeoconceptdriver.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeoconceptDriver class.
@@ -33,7 +32,7 @@
 #include "ogrgeoconceptdatasource.h"
 #include "ogrgeoconceptdriver.h"
 
-CPL_CVSID("$Id: ogrgeoconceptdriver.cpp 00000 2007-11-03 10:42:48Z drichard $");
+CPL_CVSID("$Id: ogrgeoconceptdriver.cpp 35910 2016-10-24 14:08:24Z goatbar $");
 
 /************************************************************************/
 /*                          ~OGRGeoconceptDriver()                      */
@@ -213,7 +212,6 @@ OGRErr OGRGeoconceptDriver::DeleteDataSource( const char *pszDataSource )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h
index c34bf49..9a97598 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptdriver.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: ogrgeoconceptdriver.h
+ * $Id: ogrgeoconceptdriver.h$
  *
  * Name:     ogrgeoconceptdriver.h
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -42,11 +42,11 @@ class OGRGeoconceptDriver : public OGRSFDriver
 public:
                    ~OGRGeoconceptDriver();
 
-    const char*    GetName( );
-    OGRDataSource* Open( const char* pszName, int bUpdate = FALSE );
-    int            TestCapability( const char* pszCap );
-    OGRDataSource* CreateDataSource( const char* pszName, char** papszOptions = NULL );
-    OGRErr         DeleteDataSource( const char* pszName );
+    const char*    GetName( ) override;
+    OGRDataSource* Open( const char* pszName, int bUpdate = FALSE ) override;
+    int            TestCapability( const char* pszCap ) override;
+    OGRDataSource* CreateDataSource( const char* pszName, char** papszOptions = NULL ) override;
+    OGRErr         DeleteDataSource( const char* pszName ) override;
 };
 
 #endif /* GEOCONCEPT_OGR_DRIVER_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp
index a68bbea..ac39ce2 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeoconceptlayer.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeoconceptLayer class.
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogrgeoconceptlayer.h"
 
-CPL_CVSID("$Id: ogrgeoconceptlayer.cpp 00000 2007-11-03 16:08:14Z drichard $");
+CPL_CVSID("$Id: ogrgeoconceptlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGRGeoconceptLayer()                         */
@@ -297,43 +296,43 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
       }
     }
 
-    int nbGeom;
-    int isSingle;
+    int nbGeom = 0;
+    bool isSingle = false;
 
     switch( eGt ) {
     case wkbPoint                 :
     case wkbPoint25D              :
-      nbGeom= 1;
-      isSingle= TRUE;
+      nbGeom = 1;
+      isSingle = true;
       break;
     case wkbMultiPoint            :
     case wkbMultiPoint25D         :
-      nbGeom= ((OGRGeometryCollection*)poGeom)->getNumGeometries();
-      isSingle= FALSE;
+      nbGeom = ((OGRGeometryCollection*)poGeom)->getNumGeometries();
+      isSingle = false;
       break;
     case wkbLineString            :
     case wkbLineString25D         :
-      nbGeom= 1;
-      isSingle= TRUE;
+      nbGeom = 1;
+      isSingle = true;
       break;
     case wkbMultiLineString       :
     case wkbMultiLineString25D    :
-      nbGeom= ((OGRGeometryCollection*)poGeom)->getNumGeometries();
-      isSingle= FALSE;
+      nbGeom = ((OGRGeometryCollection*)poGeom)->getNumGeometries();
+      isSingle = false;
       break;
     case wkbPolygon               :
     case wkbPolygon25D            :
-      nbGeom= 1;
-      isSingle= TRUE;
+      nbGeom = 1;
+      isSingle = true;
       break;
     case wkbMultiPolygon          :
     case wkbMultiPolygon25D       :
-      nbGeom= ((OGRGeometryCollection*)poGeom)->getNumGeometries();
-      isSingle= FALSE;
+      nbGeom = ((OGRGeometryCollection*)poGeom)->getNumGeometries();
+      isSingle = false;
       break;
     default                       :
-      nbGeom= 0;
-      isSingle= FALSE;
+      nbGeom = 0;
+      isSingle = false;
       break;
     }
 
@@ -385,7 +384,7 @@ OGRErr OGRGeoconceptLayer::ICreateFeature( OGRFeature* poFeature )
                   nextField = WriteFeatureFieldAsString_GCIO(
                       _gcFeature,
                       nextField,
-                      poFeature->IsFieldSet(iF)?
+                      poFeature->IsFieldSetAndNotNull(iF)?
                       poFeature->GetFieldAsString(iF) : NULL);
                   break;
                 }
@@ -509,7 +508,6 @@ OGRErr OGRGeoconceptLayer::CreateField( OGRFieldDefn *poField,
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Can't create fields on a read-only Geoconcept layer.\n");
         return OGRERR_FAILURE;
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -518,10 +516,10 @@ OGRErr OGRGeoconceptLayer::CreateField( OGRFieldDefn *poField,
 
     {
       /* check whether field exists ... */
-      GCField* theField;
       char* pszName = OGRGeoconceptLayer_GetCompatibleFieldName(poField->GetNameRef());
 
-      if( !(theField= FindFeatureField_GCIO(_gcFeature,pszName)) )
+      GCField* theField = FindFeatureField_GCIO(_gcFeature,pszName);
+      if( !theField )
       {
         if( GetFeatureCount(TRUE) > 0 )
         {
diff --git a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h
index 3971446..985bf48 100644
--- a/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h
+++ b/ogr/ogrsf_frmts/geoconcept/ogrgeoconceptlayer.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: ogrgeoconceptlayer.h
+ * $Id: ogrgeoconceptlayer.h$
  *
  * Name:     ogrgeoconceptlayer.h
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -46,7 +46,7 @@ class OGRGeoconceptLayer : public OGRLayer
 
   public:
                          OGRGeoconceptLayer();
-                        ~OGRGeoconceptLayer();
+                        virtual ~OGRGeoconceptLayer();
 
     OGRErr               Open( GCSubType* Subclass );
 
@@ -54,24 +54,24 @@ class OGRGeoconceptLayer : public OGRLayer
 //    void                 SetSpatialFilter( OGRGeometry* poGeomIn );
 //    void                 SetSpatialFilterRect( double dfMinX, double dfMinY, double dfMaxX, double dfMaxY );
 //    OGRErr               SetAttributeFilter( const char* pszQuery );
-    void                 ResetReading();
-    OGRFeature*          GetNextFeature();
+    void                 ResetReading() override;
+    OGRFeature*          GetNextFeature() override;
 //    OGRErr               SetNextByIndex( GIntBig nIndex );
 
 //    OGRFeature*          GetFeature( GIntBig nFID );
 //    OGRErr               ISetFeature( OGRFeature* poFeature );
 //    OGRErr               DeleteFeature( GIntBig nFID );
-    OGRErr               ICreateFeature( OGRFeature* poFeature );
-    OGRFeatureDefn*      GetLayerDefn( ) { return _poFeatureDefn; } // FIXME
-    OGRSpatialReference* GetSpatialRef( );
-    GIntBig              GetFeatureCount( int bForce = TRUE );
-    OGRErr               GetExtent( OGREnvelope *psExtent, int bForce = TRUE );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    OGRErr               ICreateFeature( OGRFeature* poFeature ) override;
+    OGRFeatureDefn*      GetLayerDefn( ) override { return _poFeatureDefn; } // FIXME
+    OGRSpatialReference* GetSpatialRef( ) override;
+    GIntBig              GetFeatureCount( int bForce = TRUE ) override;
+    OGRErr               GetExtent( OGREnvelope *psExtent, int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-    int                  TestCapability( const char* pszCap );
+    int                  TestCapability( const char* pszCap ) override;
 //    const char*          GetInfo( const char* pszTag );
-    OGRErr               CreateField( OGRFieldDefn* poField, int bApproxOK = TRUE );
-    OGRErr               SyncToDisk( );
+    OGRErr               CreateField( OGRFieldDefn* poField, int bApproxOK = TRUE ) override;
+    OGRErr               SyncToDisk( ) override;
 //    OGRStyleTable*       GetStyleTable( );
 //    void                 SetStyleTableDirectly( OGRStyleTable* poStyleTable );
 //    void                 SetStyleTable( OGRStyleTable* poStyleTable );
diff --git a/ogr/ogrsf_frmts/geojson/drv_geojson.html b/ogr/ogrsf_frmts/geojson/drv_geojson.html
index 309b9ec..b8959f4 100644
--- a/ogr/ogrsf_frmts/geojson/drv_geojson.html
+++ b/ogr/ogrsf_frmts/geojson/drv_geojson.html
@@ -56,6 +56,14 @@ ogrinfo -ro http://featureserver/data/.geojson OGRGeoJSON
 It's also valid to assume that OGRDataSource::GetLayerCount() for GeoJSON datasource always returns 1.
 </p>
 
+<p>Starting with GDAL 2.2, the layer name is built with the following logic:</p>
+<ol>
+<li>If a "name" member is found at the FeatureCollection level, it is used.</li>
+<li>Otherwise if the filename is regular (ie not a URL with query parameters), then
+the filename without extension and path is used as the layer name.</li>
+<li>Otherwise OGRGeoJSON is used.</li>
+</ol>
+
 <p>Accessing Web Service as a datasource (i.e. FeatureServer), each request will produce new layer.
 This behavior conforms to stateless nature of HTTP transaction and is similar to how Web browsers operate:
 single request == single page.</p>
@@ -176,11 +184,20 @@ OGRFeature(OGRGeoJSON):0
 <li><b>WRITE_BBOX</b> = YES/NO: (OGR >= 1.9.0) Set to YES to write a bbox property with the bounding box of the geometries at the feature and feature
 collection level. Defaults to NO.</li>
 <li><b>COORDINATE_PRECISION</b> = int_number: (OGR >= 1.9.0) Maximum number of figures after decimal separator to write in coordinates.
-Default to 15. "Smart" truncation will occur to remove trailing zeros.</li>
+Default to 15 for GeoJSON 2008, and 7 for RFC 7946. "Smart" truncation will occur to remove trailing zeros.</li>
 <li><b>SIGNIFICANT_FIGURES</b> = int_number: (OGR >= 2.1) Maximum number of significant figures when writing floating-point numbers.
 Default to 17. If explicitly specified, and COORDINATE_PRECISION is not, this will also apply to coordinates.</li>
 <li><b>NATIVE_DATA</b>=string. (OGR >= 2.1) Serialized JSon object that contains extra properties to store at FeatureCollection level.</li>
 <li><b>NATIVE_MEDIA_TYPE</b>=string. (OGR >= 2.1) Format of NATIVE_DATA. Must be "application/vnd.geo+json", otherwise NATIVE_DATA will be ignored.</li>
+<li><b>RFC7946</b>=YES/NO. (OGR >= 2.2) Whether to use
+<a href="https://tools.ietf.org/html/rfc7946">RFC 7946</a> standard.
+Otherwise <a href="http://geojson.org/geojson-spec.html">GeoJSON 2008</a> initial version will be used.
+Default is NO (thus GeoJSON 2008)</li>
+<li><b>WRITE_NAME</b>=YES/NO. (OGR >= 2.2) Whether to write a "name" property
+at feature collection level with layer name. Defaults to YES.</li>
+<li><b>DESCRIPTION</b>=string. (OGR >= 2.2) (Long) description to write in a
+"description" property at feature collection level. On reading, this will be
+reported in the DESCRIPTION metadata item of the layer.</li>
 </ul>
 
 <h2>VSI Virtual File System API support</h2>
@@ -230,6 +247,27 @@ change in the number of coordinates).</p>
 <p>This behaviour can be turned off by specifying the <b>-noNativeData</b> switch
 of the ogr2ogr utility.</p>
 
+<h2>RFC 7946 write support</h2>
+
+<p>By default, the driver will write GeoJSON files following GeoJSON 2008 specification.
+When specifying the RFC7946=YES creation option, the RFC 7946 standard will be
+used instead.</p>
+
+<p>The differences between the 2 versions are mentioned in <a href="https://tools.ietf.org/html/rfc7946#appendix-B">
+Appendix B of RFC 7946</a> and recalled here for what matters to the driver:</p>
+<ul>
+<li>Coordinates must be in longitude/latitude over the WGS 84 ellipsoid, hence
+if the spatial reference system specified at layer creation time is not EPSG:4326,
+on-the-fly reprojection will be done by the driver.</li>
+<li>Polygons will be written such as to follow the right-hand rule for orientation
+(counterclockwise external rings, clockwise internal rings).</li>
+<li>The values of a "bbox" array are "[west, south, east, north]", not
+"[minx, miny, maxx, maxy]"</li>
+<li>Some extension member names (see previous section about round/tripping) are
+forbidden in the FeatureCollection, Feature and Geometry objects.</li>
+<li>The default coordinate precision is 7 decimal digits after decimal separator.</li>
+</ul>
+
 <h2>Example</h2>
 
 <p>How to dump content of .geojson file:
@@ -250,6 +288,12 @@ ogr2ogr -f "ESRI Shapefile" cities.shp http://featureserver/cities/.geojson OGRG
 </pre>
 </p>
 
+<p>How to translate a ESRI Shapefile into a RFC 7946 GeoJSON file:
+<pre>
+ogr2ogr -f GeoJSON cities.json cities.shp -lco RFC7946=YES
+</pre>
+</p>
+
 <p>Read the result of a FeatureService request against a GeoServices REST server:
 <pre>
 ogrinfo -ro -al "http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydrography/Watershed173811/FeatureServer/0/query?where=objectid+%3D+objectid&outfields=*&f=json"
@@ -261,6 +305,8 @@ ogrinfo -ro -al "http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Hydr
 <p>
 <ul>
 <li><a href="http://geojson.org/">GeoJSON</a> - encoding geographic content in JSON</li>
+<li><a href="https://tools.ietf.org/html/rfc7946">RFC 7946</a> standard.</li>
+<li><a href="http://geojson.org/geojson-spec.html">GeoJSON 2008</a> specification (obsoleted by RFC 7946).</li>
 <li><a href="http://json.org/">JSON</a> - JavaScript Object Notation</li>
 <li><a href="http://oss.metaparadigm.com/json-c/">JSON-C</a> - A JSON implementation in C</li>
 <li><a href="http://lists.osgeo.org/pipermail/gdal-dev/2007-November/014746.html">[Gdal-dev] OGR GeoJSON Driver</a> - driver announcement</li>
diff --git a/ogr/ogrsf_frmts/geojson/libjson/json_object.h b/ogr/ogrsf_frmts/geojson/libjson/json_object.h
index 27ef4fa..fb38b6c 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/json_object.h
+++ b/ogr/ogrsf_frmts/geojson/libjson/json_object.h
@@ -261,6 +261,7 @@ extern void CPL_DLL json_object_object_add(struct json_object* obj, const char *
  * @param obj the json_object instance
  * @param key the object field name
  * @returns the json_object associated with the given field name
+ * @deprecated Please use json_object_object_get_ex
  */
 extern struct json_object* json_object_object_get(struct json_object* obj,
 						  const char *key);
diff --git a/ogr/ogrsf_frmts/geojson/libjson/printbuf.c b/ogr/ogrsf_frmts/geojson/libjson/printbuf.c
index fd83aab..4c0bc9d 100644
--- a/ogr/ogrsf_frmts/geojson/libjson/printbuf.c
+++ b/ogr/ogrsf_frmts/geojson/libjson/printbuf.c
@@ -118,8 +118,10 @@ int sprintbuf(struct printbuf *p, const char *msg, ...)
 
   /* user stack buffer first */
   va_start(ap, msg);
-  if((size = CPLVASPrintf(&t, msg, ap)) == -1) return -1;
+  size = CPLVASPrintf(&t, msg, ap);
   va_end(ap);
+  if( size == -1 )
+      return -1;
 
   if (strcmp(msg, "%f") == 0)
   {
diff --git a/ogr/ogrsf_frmts/geojson/ogr_geojson.h b/ogr/ogrsf_frmts/geojson/ogr_geojson.h
index 5d5c31f..2258f1e 100644
--- a/ogr/ogrsf_frmts/geojson/ogr_geojson.h
+++ b/ogr/ogrsf_frmts/geojson/ogr_geojson.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geojson.h 34331 2016-06-09 20:03:05Z rouault $
+ * $Id: ogr_geojson.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Definitions of OGR OGRGeoJSON driver types.
@@ -27,6 +27,7 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
 #ifndef OGR_GEOJSON_H_INCLUDED
 #define OGR_GEOJSON_H_INCLUDED
 
@@ -35,10 +36,9 @@
 #include "../mem/ogr_mem.h"
 
 #include <cstdio>
-#include <vector> // used by OGRGeoJSONLayer
+#include <vector>  // Used by OGRGeoJSONLayer.
 #include "ogrgeojsonutils.h"
-
-#define SPACE_FOR_BBOX  130
+#include "ogrgeojsonwriter.h"
 
 class OGRGeoJSONDataSource;
 
@@ -49,8 +49,8 @@ class OGRGeoJSONDataSource;
 class OGRGeoJSONLayer : public OGRMemLayer
 {
     friend class OGRGeoJSONDataSource;
-public:
 
+  public:
     static const char* const DefaultName;
     static const OGRwkbGeometryType DefaultGeometryType;
 
@@ -58,15 +58,15 @@ public:
                      OGRSpatialReference* poSRS,
                      OGRwkbGeometryType eGType,
                      OGRGeoJSONDataSource* poDS );
-    ~OGRGeoJSONLayer();
+    virtual ~OGRGeoJSONLayer();
 
     //
     // OGRLayer Interface
     //
-    virtual const char* GetFIDColumn();
-    virtual int         TestCapability( const char * pszCap );
+    virtual const char* GetFIDColumn() override;
+    virtual int         TestCapability( const char * pszCap ) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
     //
     // OGRGeoJSONLayer Interface
     //
@@ -74,8 +74,7 @@ public:
     void AddFeature( OGRFeature* poFeature );
     void DetectGeometryType();
 
-private:
-
+  private:
     OGRGeoJSONDataSource* poDS_;
     CPLString sFIDColumn_;
     bool bUpdated_;
@@ -88,28 +87,28 @@ private:
 
 class OGRGeoJSONWriteLayer : public OGRLayer
 {
-public:
+  public:
     OGRGeoJSONWriteLayer( const char* pszName,
                           OGRwkbGeometryType eGType,
                           char** papszOptions,
                           bool bWriteFC_BBOXIn,
+                          OGRCoordinateTransformation* poCT,
                           OGRGeoJSONDataSource* poDS );
     ~OGRGeoJSONWriteLayer();
 
     //
     // OGRLayer Interface
     //
-    OGRFeatureDefn* GetLayerDefn() { return poFeatureDefn_; }
-    OGRSpatialReference* GetSpatialRef() { return NULL; }
-
-    void ResetReading() { }
-    OGRFeature* GetNextFeature() { return NULL; }
-    OGRErr ICreateFeature( OGRFeature* poFeature );
-    OGRErr CreateField(OGRFieldDefn* poField, int bApproxOK);
-    int TestCapability( const char* pszCap );
+    OGRFeatureDefn* GetLayerDefn() override { return poFeatureDefn_; }
+    OGRSpatialReference* GetSpatialRef() override { return NULL; }
 
-private:
+    void ResetReading() override { }
+    OGRFeature* GetNextFeature() override { return NULL; }
+    OGRErr ICreateFeature( OGRFeature* poFeature ) override;
+    OGRErr CreateField( OGRFieldDefn* poField, int bApproxOK ) override;
+    int TestCapability( const char* pszCap ) override;
 
+  private:
     OGRGeoJSONDataSource* poDS_;
     OGRFeatureDefn* poFeatureDefn_;
     int nOutCounter_;
@@ -121,6 +120,10 @@ private:
 
     int nCoordPrecision_;
     int nSignificantFigures_;
+
+    bool bRFC7946_;
+    OGRCoordinateTransformation* poCT_;
+    OGRGeoJSONWriteOptions oWriteOptions_;
 };
 
 /************************************************************************/
@@ -129,24 +132,23 @@ private:
 
 class OGRGeoJSONDataSource : public OGRDataSource
 {
-public:
-
+  public:
     OGRGeoJSONDataSource();
-    ~OGRGeoJSONDataSource();
+    virtual ~OGRGeoJSONDataSource();
 
     //
     // OGRDataSource Interface
     //
     int Open( GDALOpenInfo* poOpenInfo,
                GeoJSONSourceType nSrcType );
-    const char* GetName();
-    int GetLayerCount();
-    OGRLayer* GetLayer( int nLayer );
+    const char* GetName() override;
+    int GetLayerCount() override;
+    OGRLayer* GetLayer( int nLayer ) override;
     OGRLayer* ICreateLayer( const char* pszName,
-                           OGRSpatialReference* poSRS = NULL,
-                           OGRwkbGeometryType eGType = wkbUnknown,
-                           char** papszOptions = NULL );
-    int TestCapability( const char* pszCap );
+                            OGRSpatialReference* poSRS = NULL,
+                            OGRwkbGeometryType eGType = wkbUnknown,
+                            char** papszOptions = NULL ) override;
+    int TestCapability( const char* pszCap ) override;
 
     void AddLayer( OGRGeoJSONLayer* poLayer );
 
@@ -177,9 +179,11 @@ public:
     int  HasOtherPages() const { return bOtherPages_; }
     bool IsUpdatable() const { return bUpdatable_; }
 
-    virtual void        FlushCache();
+    virtual void        FlushCache() override;
 
-private:
+    static const size_t SPACE_FOR_BBOX = 130;
+
+  private:
     //
     // Private data members
     //
@@ -212,5 +216,4 @@ private:
     void LoadLayers(char** papszOpenOptions);
 };
 
-
-#endif /* OGR_GEOJSON_H_INCLUDED */
+#endif  // OGR_GEOJSON_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
index 69cf8f2..c38b6da 100644
--- a/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogresrijsonreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogresrijsonreader.cpp 37099 2017-01-11 12:21:34Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRESRIJSONReader class (OGR ESRIJSON Driver)
@@ -30,18 +29,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogrgeojsonreader.h"
-#include "ogrgeojsonutils.h"
+
+#include <limits.h>
+#include <stddef.h>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "json.h"
+// #include "json_object.h"
+// #include "json_tokener.h"
+#include "ogr_api.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
 #include "ogr_geojson.h"
-#include <json.h> // JSON-C
-#include <ogr_api.h>
+#include "ogrgeojsonreader.h"
+#include "ogrgeojsonutils.h"
+// #include "symbol_renames.h"
+
+CPL_CVSID("$Id: ogresrijsonreader.cpp 37374 2017-02-13 11:59:01Z goatbar $");
 
 /************************************************************************/
 /*                          OGRESRIJSONReader()                         */
 /************************************************************************/
 
-OGRESRIJSONReader::OGRESRIJSONReader()
-    : poGJObject_( NULL ), poLayer_( NULL )
+OGRESRIJSONReader::OGRESRIJSONReader() :
+    poGJObject_(NULL),
+    poLayer_(NULL)
 {}
 
 /************************************************************************/
@@ -80,9 +97,8 @@ OGRErr OGRESRIJSONReader::Parse( const char* pszText )
         }
         json_tokener_free(jstok);
 
-        /* JSON tree is shared for while lifetime of the reader object
-         * and will be released in the destructor.
-         */
+        // JSON tree is shared for while lifetime of the reader object
+        // and will be released in the destructor.
         poGJObject_ = jsobj;
     }
 
@@ -104,8 +120,7 @@ void OGRESRIJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
         return;
     }
 
-    OGRSpatialReference* poSRS
-        = OGRESRIJSONReadSpatialReference( poGJObject_ );
+    OGRSpatialReference* poSRS = OGRESRIJSONReadSpatialReference( poGJObject_ );
 
     poLayer_ = new OGRGeoJSONLayer( OGRGeoJSONLayer::DefaultName, poSRS,
                                     OGRESRIJSONGetGeometryType(poGJObject_),
@@ -116,14 +131,14 @@ void OGRESRIJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
     if( !GenerateLayerDefn() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Layer schema generation failed." );
+                  "Layer schema generation failed." );
 
         delete poLayer_;
         return;
     }
 
     OGRGeoJSONLayer *poThisLayer = ReadFeatureCollection( poGJObject_ );
-    if (poThisLayer == NULL)
+    if( poThisLayer == NULL )
     {
         delete poLayer_;
         return;
@@ -149,16 +164,16 @@ bool OGRESRIJSONReader::GenerateLayerDefn()
 /* -------------------------------------------------------------------- */
 /*      Scan all features and generate layer definition.                */
 /* -------------------------------------------------------------------- */
-    json_object* poObjFeatures
-        = OGRGeoJSONFindMemberByName( poGJObject_, "fields" );
-    if( NULL != poObjFeatures
-        && json_type_array == json_object_get_type( poObjFeatures ) )
+    json_object* poObjFeatures =
+        OGRGeoJSONFindMemberByName( poGJObject_, "fields" );
+    if( NULL != poObjFeatures &&
+        json_type_array == json_object_get_type( poObjFeatures ) )
     {
         const int nFeatures = json_object_array_length( poObjFeatures );
         for( int i = 0; i < nFeatures; ++i )
         {
-            json_object* poObjFeature
-                = json_object_array_get_idx( poObjFeatures, i );
+            json_object* poObjFeature =
+                json_object_array_get_idx( poObjFeatures, i );
             if( !GenerateFeatureDefn( poObjFeature ) )
             {
                 CPLDebug( "GeoJSON", "Create feature schema failure." );
@@ -187,8 +202,8 @@ bool OGRESRIJSONReader::GenerateLayerDefn()
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                        "Invalid FeatureCollection object. "
-                        "Missing \'fields\' member." );
+                      "Invalid FeatureCollection object. "
+                      "Missing \'fields\' member." );
             bSuccess = false;
         }
     }
@@ -215,36 +230,42 @@ bool OGRESRIJSONReader::GenerateFeatureDefn( json_object* poObj )
     if( NULL != poObjName && NULL != poObjType )
     {
         OGRFieldType eFieldType = OFTString;
-        if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeOID"))
+        if( EQUAL(json_object_get_string(poObjType), "esriFieldTypeOID") )
         {
             eFieldType = OFTInteger;
             poLayer_->SetFIDColumn(json_object_get_string(poObjName));
         }
-        else if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeDouble"))
+        else if( EQUAL(json_object_get_string(poObjType),
+                       "esriFieldTypeDouble") )
         {
             eFieldType = OFTReal;
         }
-        else if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeSmallInteger") ||
-                 EQUAL(json_object_get_string(poObjType), "esriFieldTypeInteger") )
+        else if( EQUAL(json_object_get_string(poObjType),
+                       "esriFieldTypeSmallInteger") ||
+                 EQUAL(json_object_get_string(poObjType),
+                       "esriFieldTypeInteger") )
         {
             eFieldType = OFTInteger;
         }
         OGRFieldDefn fldDefn( json_object_get_string(poObjName),
-                              eFieldType);
+                              eFieldType );
 
-        json_object* poObjLength = OGRGeoJSONFindMemberByName( poObj, "length" );
-        if (poObjLength != NULL && json_object_get_type(poObjLength) == json_type_int )
+        json_object * const poObjLength =
+            OGRGeoJSONFindMemberByName( poObj, "length" );
+        if( poObjLength != NULL &&
+            json_object_get_type(poObjLength) == json_type_int )
         {
-            int nWidth = json_object_get_int(poObjLength);
-            // A dummy with of 2147483647 seems to indicate no known field with
-            // which in the OGR world is better modelled as 0 field width. (#6529)
+            const int nWidth = json_object_get_int(poObjLength);
+            // A dummy width of 2147483647 seems to indicate no known field with
+            // which in the OGR world is better modelled as 0 field width.
+            // (#6529)
             if( nWidth != INT_MAX )
                 fldDefn.SetWidth(nWidth);
         }
 
         poDefn->AddFieldDefn( &fldDefn );
 
-        bSuccess = true; // SUCCESS
+        bSuccess = true;
     }
     return bSuccess;
 }
@@ -273,13 +294,13 @@ OGRGeometry* OGRESRIJSONReader::ReadGeometry( json_object* poObj )
     OGRGeometry* poGeometry = NULL;
 
     const OGRwkbGeometryType eType = poLayer_->GetGeomType();
-    if (eType == wkbPoint)
+    if( eType == wkbPoint )
         poGeometry = OGRESRIJSONReadPoint( poObj );
-    else if (eType == wkbLineString)
+    else if( eType == wkbLineString )
         poGeometry = OGRESRIJSONReadLineString( poObj );
-    else if (eType == wkbPolygon)
+    else if( eType == wkbPolygon )
         poGeometry = OGRESRIJSONReadPolygon( poObj );
-    else if (eType == wkbMultiPoint)
+    else if( eType == wkbMultiPoint )
         poGeometry = OGRESRIJSONReadMultiPoint( poObj );
 
     return poGeometry;
@@ -294,8 +315,7 @@ OGRFeature* OGRESRIJSONReader::ReadFeature( json_object* poObj )
     CPLAssert( NULL != poObj );
     CPLAssert( NULL != poLayer_ );
 
-    OGRFeature* poFeature
-        = new OGRFeature( poLayer_->GetLayerDefn() );
+    OGRFeature* poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
 
 /* -------------------------------------------------------------------- */
 /*      Translate ESRIJSON "attributes" object to feature attributes.   */
@@ -319,40 +339,46 @@ OGRFeature* OGRESRIJSONReader::ReadFeature( json_object* poObj )
             if( nField >= 0 )
             {
                 poFieldDefn = poFeature->GetFieldDefnRef(nField);
-                if (poFieldDefn && it.val != NULL )
+                if( poFieldDefn && it.val != NULL )
                 {
-                    if ( EQUAL( it.key,  poLayer_->GetFIDColumn() ) )
+                    if( EQUAL( it.key,  poLayer_->GetFIDColumn() ) )
                         poFeature->SetFID( json_object_get_int( it.val ) );
-                    if ( poLayer_->GetLayerDefn()->GetFieldDefn(nField)->GetType() == OFTReal )
-                        poFeature->SetField( nField, CPLAtofM(json_object_get_string(it.val)) );
+                    if( poLayer_->GetLayerDefn()->
+                            GetFieldDefn(nField)->GetType() == OFTReal )
+                    {
+                        poFeature->SetField(
+                            nField, CPLAtofM(json_object_get_string(it.val)) );
+                    }
                     else
-                        poFeature->SetField( nField, json_object_get_string(it.val) );
+                    {
+                        poFeature->SetField( nField,
+                                             json_object_get_string(it.val) );
+                    }
                 }
             }
         }
     }
 
-    OGRwkbGeometryType eType = poLayer_->GetGeomType();
-    if (eType == wkbNone)
+    const OGRwkbGeometryType eType = poLayer_->GetGeomType();
+    if( eType == wkbNone )
         return poFeature;
 
 /* -------------------------------------------------------------------- */
 /*      Translate geometry sub-object of ESRIJSON Feature.               */
 /* -------------------------------------------------------------------- */
     json_object* poObjGeom = NULL;
-
     json_object* poTmp = poObj;
-
     json_object_iter it;
     it.key = NULL;
     it.val = NULL;
     it.entry = NULL;
     json_object_object_foreachC(poTmp, it)
     {
-        if( EQUAL( it.key, "geometry" ) ) {
-            if (it.val != NULL)
+        if( EQUAL( it.key, "geometry" ) )
+        {
+            if( it.val != NULL )
                 poObjGeom = it.val;
-            // we're done.  They had 'geometry':null
+            // We're done.  They had 'geometry':null.
             else
                 return poFeature;
         }
@@ -399,23 +425,19 @@ OGRESRIJSONReader::ReadFeatureCollection( json_object* poObj )
 
     if( json_type_array == json_object_get_type( poObjFeatures ) )
     {
-        /* bool bAdded = false; */
-
         const int nFeatures = json_object_array_length( poObjFeatures );
         for( int i = 0; i < nFeatures; ++i )
         {
             json_object* poObjFeature
                 = json_object_array_get_idx( poObjFeatures, i );
-            if (poObjFeature != NULL &&
-                json_object_get_type(poObjFeature) == json_type_object)
+            if( poObjFeature != NULL &&
+                json_object_get_type(poObjFeature) == json_type_object )
             {
-                OGRFeature* poFeature
-                    = OGRESRIJSONReader::ReadFeature( poObjFeature );
-                /* bAdded = */ AddFeature( poFeature );
+                OGRFeature* poFeature =
+                    OGRESRIJSONReader::ReadFeature( poObjFeature );
+                AddFeature( poFeature );
             }
-            //CPLAssert( bAdded );
         }
-        //CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
     }
 
     // We're returning class member to follow the same pattern of
@@ -433,8 +455,8 @@ OGRwkbGeometryType OGRESRIJSONGetGeometryType( json_object* poObj )
     if( NULL == poObj )
         return wkbUnknown;
 
-    json_object* poObjType
-        = OGRGeoJSONFindMemberByName( poObj, "geometryType" );
+    json_object* poObjType =
+        OGRGeoJSONFindMemberByName( poObj, "geometryType" );
     if( NULL == poObjType )
     {
         return wkbNone;
@@ -471,11 +493,12 @@ OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
     }
 
     const int iTypeX = json_object_get_type(poObjX);
-    if ( (json_type_double != iTypeX) && (json_type_int != iTypeX) )
+    if( json_type_double != iTypeX && json_type_int != iTypeX )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                "Invalid X coordinate. Type is not double or integer for \'%s\'.",
-                json_object_to_json_string(poObjX) );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Invalid X coordinate. Type is not double or integer for \'%s\'.",
+            json_object_to_json_string(poObjX) );
         return NULL;
     }
 
@@ -483,17 +506,18 @@ OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
     if( NULL == poObjY )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Invalid Point object. "
-            "Missing \'y\' member." );
+                  "Invalid Point object. "
+                  "Missing \'y\' member." );
         return NULL;
     }
 
     const int iTypeY = json_object_get_type(poObjY);
-    if ( (json_type_double != iTypeY) && (json_type_int != iTypeY) )
+    if( json_type_double != iTypeY && json_type_int != iTypeY )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
-                json_object_to_json_string(poObjY) );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
+            json_object_to_json_string(poObjY) );
         return NULL;
     }
 
@@ -505,7 +529,7 @@ OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
         return new OGRPoint(dfX, dfY);
 
     const int iTypeZ = json_object_get_type(poObjZ);
-    if ( (json_type_double != iTypeZ) && (json_type_int != iTypeZ) )
+    if( json_type_double != iTypeZ && json_type_int != iTypeZ )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid Z coordinate. Type is not double or integer "
@@ -521,151 +545,134 @@ OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
 /*                     OGRESRIJSONReaderParseZM()                  */
 /************************************************************************/
 
-static int OGRESRIJSONReaderParseZM( json_object* poObj, int *bHasZ,
-                                     int *bHasM )
+static bool OGRESRIJSONReaderParseZM( json_object* poObj, bool *bHasZ,
+                                      bool *bHasM )
 {
     CPLAssert( NULL != poObj );
-    /*
-    ** The ESRI geojson spec states that geometries other than point can
-    ** have the attributes hasZ and hasM.  A geometry that has a z value
-    ** implies the 3rd number in the tuple is z.  if hasM is true, but hasZ
-    ** is not, it is the M value, and is not supported in OGR.
-    */
-    int bZ;
+    // The ESRI geojson spec states that geometries other than point can
+    // have the attributes hasZ and hasM.  A geometry that has a z value
+    // implies the 3rd number in the tuple is z.  if hasM is true, but hasZ
+    // is not, it is the M value, and is not supported in OGR.
+    bool bZ = false;
     json_object* poObjHasZ = OGRGeoJSONFindMemberByName( poObj, "hasZ" );
-    if( poObjHasZ == NULL )
-    {
-        bZ = FALSE;
-    }
-    else
+    if( poObjHasZ != NULL )
     {
-        if( json_object_get_type( poObjHasZ ) != json_type_boolean )
-        {
-            bZ = FALSE;
-        }
-        else
+        if( json_object_get_type( poObjHasZ ) == json_type_boolean )
         {
-            bZ = json_object_get_boolean( poObjHasZ );
+            bZ = CPL_TO_BOOL(json_object_get_boolean( poObjHasZ ));
         }
     }
 
-    int bM;
+    bool bM = false;
     json_object* poObjHasM = OGRGeoJSONFindMemberByName( poObj, "hasM" );
-    if( poObjHasM == NULL )
+    if( poObjHasM != NULL )
     {
-        bM = FALSE;
-    }
-    else
-    {
-        if( json_object_get_type( poObjHasM ) != json_type_boolean )
-        {
-            bM = FALSE;
-        }
-        else
+        if( json_object_get_type( poObjHasM ) == json_type_boolean )
         {
-            bM = json_object_get_boolean( poObjHasM );
+            bM = CPL_TO_BOOL(json_object_get_boolean( poObjHasM ));
         }
     }
     if( bHasZ != NULL )
         *bHasZ = bZ;
     if( bHasM != NULL )
         *bHasM = bM;
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                     OGRESRIJSONReaderParseXYZMArray()                  */
 /************************************************************************/
 
-static int OGRESRIJSONReaderParseXYZMArray (json_object* poObjCoords,
-                                          double* pdfX, double* pdfY,
-                                          double* pdfZ, int* pnNumCoords)
+static bool OGRESRIJSONReaderParseXYZMArray( json_object* poObjCoords,
+                                             double* pdfX, double* pdfY,
+                                             double* pdfZ, int* pnNumCoords )
 {
-    if (poObjCoords == NULL)
+    if( poObjCoords == NULL )
     {
         CPLDebug( "ESRIJSON",
-                "OGRESRIJSONReaderParseXYZMArray: got null object." );
-        return FALSE;
+                  "OGRESRIJSONReaderParseXYZMArray: got null object." );
+        return false;
     }
 
     if( json_type_array != json_object_get_type( poObjCoords ))
     {
         CPLDebug( "ESRIJSON",
-                "OGRESRIJSONReaderParseXYZMArray: got non-array object." );
-        return FALSE;
+                  "OGRESRIJSONReaderParseXYZMArray: got non-array object." );
+        return false;
     }
 
     int coordDimension = json_object_array_length( poObjCoords );
-    /*
-    ** We allow 4 coordinates if M is present, but it is eventually ignored.
-    */
-    if(coordDimension < 2 || coordDimension > 4)
+
+    // Allow 4 coordinates if M is present, but it is eventually ignored.
+    if( coordDimension < 2 || coordDimension > 4 )
     {
         CPLDebug( "ESRIJSON",
                   "OGRESRIJSONReaderParseXYZMArray: got an unexpected "
                   "array object." );
-        return FALSE;
+        return false;
     }
 
-    // Read X coordinate
+    // Read X coordinate.
     json_object* poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
-    if (poObjCoord == NULL)
+    if( poObjCoord == NULL )
     {
         CPLDebug( "ESRIJSON",
                   "OGRESRIJSONReaderParseXYZMArray: got null object." );
-        return FALSE;
+        return false;
     }
 
     int iType = json_object_get_type(poObjCoord);
-    if ( (json_type_double != iType) && (json_type_int != iType) )
+    if( json_type_double != iType && json_type_int != iType )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid X coordinate. Type is not double or integer "
                   "for \'%s\'.",
                 json_object_to_json_string(poObjCoord) );
-        return FALSE;
+        return false;
     }
 
     const double dfX = json_object_get_double( poObjCoord );
 
-    // Read Y coordinate
+    // Read Y coordinate.
     poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
-    if (poObjCoord == NULL)
+    if( poObjCoord == NULL )
     {
-        CPLDebug( "ESRIJSON", "OGRESRIJSONReaderParseXYZMArray: got null object." );
-        return FALSE;
+        CPLDebug( "ESRIJSON",
+                  "OGRESRIJSONReaderParseXYZMArray: got null object." );
+        return false;
     }
 
     iType = json_object_get_type(poObjCoord);
-    if ( (json_type_double != iType) && (json_type_int != iType) )
+    if( json_type_double != iType && json_type_int != iType )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
-                json_object_to_json_string(poObjCoord) );
-        return FALSE;
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
+            json_object_to_json_string(poObjCoord) );
+        return false;
     }
 
     const double dfY = json_object_get_double( poObjCoord );
 
-    // Read Z coordinate
-    if(coordDimension > 2)
+    // Read Z coordinate.
+    if( coordDimension > 2 )
     {
         poObjCoord = json_object_array_get_idx( poObjCoords, 2 );
-        if (poObjCoord == NULL)
+        if( poObjCoord == NULL )
         {
             CPLDebug( "ESRIJSON",
                       "OGRESRIJSONReaderParseXYZMArray: got null object." );
-            return FALSE;
+            return false;
         }
 
         iType = json_object_get_type(poObjCoord);
-        if ( (json_type_double != iType) && (json_type_int != iType) )
+        if( json_type_double != iType && json_type_int != iType )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Invalid Z coordinate. Type is not double or integer "
                       "for \'%s\'.",
                     json_object_to_json_string(poObjCoord) );
-            return FALSE;
+            return false;
         }
         const double dfZ = json_object_get_double( poObjCoord );
         if( pdfZ != NULL )
@@ -684,19 +691,19 @@ static int OGRESRIJSONReaderParseXYZMArray (json_object* poObjCoords,
     if( pdfY != NULL )
         *pdfY = dfY;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                        OGRESRIJSONReadLineString()                   */
 /************************************************************************/
 
-OGRGeometry* OGRESRIJSONReadLineString( json_object* poObj)
+OGRGeometry* OGRESRIJSONReadLineString( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-    int bHasZ = FALSE;
-    int bHasM = FALSE;
+    bool bHasZ = false;
+    bool bHasM = false;
 
     if( !OGRESRIJSONReaderParseZM( poObj, &bHasZ, &bHasM ) )
     {
@@ -724,15 +731,14 @@ OGRGeometry* OGRESRIJSONReadLineString( json_object* poObj)
     OGRMultiLineString* poMLS = NULL;
     OGRGeometry* poRet = NULL;
     const int nPaths = json_object_array_length( poObjPaths );
-    for(int iPath = 0; iPath < nPaths; iPath ++)
+    for( int iPath = 0; iPath < nPaths; iPath++ )
     {
         json_object* poObjPath = json_object_array_get_idx( poObjPaths, iPath );
-        if ( poObjPath == NULL ||
-                json_type_array != json_object_get_type( poObjPath ) )
+        if( poObjPath == NULL ||
+            json_type_array != json_object_get_type( poObjPath ) )
         {
             delete poRet;
-            CPLDebug( "ESRIJSON",
-                    "LineString: got non-array object." );
+            CPLDebug( "ESRIJSON", "LineString: got non-array object." );
             return NULL;
         }
 
@@ -747,23 +753,28 @@ OGRGeometry* OGRESRIJSONReadLineString( json_object* poObj)
             poMLS->addGeometryDirectly(poLine);
         }
         else
+        {
             poRet = poLine;
+        }
         const int nPoints = json_object_array_length( poObjPath );
-        for(int i = 0; i < nPoints; i++)
+        for( int i = 0; i < nPoints; i++ )
         {
             int nNumCoords = 2;
-            json_object* poObjCoords
-                = json_object_array_get_idx( poObjPath, i );
-            double dfX, dfY, dfZ;
+            json_object* poObjCoords =
+                json_object_array_get_idx( poObjPath, i );
+            double dfX = 0.0;
+            double dfY = 0.0;
+            double dfZ = 0.0;
             if( !OGRESRIJSONReaderParseXYZMArray (
                     poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
             {
+                if( poRet != poLine )
+                    delete poRet;
                 delete poLine;
-                delete poRet;
                 return NULL;
             }
 
-            if(nNumCoords > 2 && (TRUE == bHasZ || FALSE == bHasM))
+            if( nNumCoords > 2 && (bHasZ || !bHasM) )
             {
                 poLine->addPoint( dfX, dfY, dfZ);
             }
@@ -773,6 +784,7 @@ OGRGeometry* OGRESRIJSONReadLineString( json_object* poObj)
             }
         }
     }
+
     if( poRet == NULL )
         poRet = new OGRLineString();
 
@@ -787,8 +799,8 @@ OGRGeometry* OGRESRIJSONReadPolygon( json_object* poObj)
 {
     CPLAssert( NULL != poObj );
 
-    int bHasZ = FALSE;
-    int bHasM = FALSE;
+    bool bHasZ = false;
+    bool bHasM = false;
 
     if( !OGRESRIJSONReaderParseZM( poObj, &bHasZ, &bHasM ) )
     {
@@ -815,13 +827,13 @@ OGRGeometry* OGRESRIJSONReadPolygon( json_object* poObj)
 
     const int nRings = json_object_array_length( poObjRings );
     OGRGeometry** papoGeoms = new OGRGeometry*[nRings];
-    for(int iRing = 0; iRing < nRings; iRing ++)
+    for( int iRing = 0; iRing < nRings; iRing++ )
     {
         json_object* poObjRing = json_object_array_get_idx( poObjRings, iRing );
-        if ( poObjRing == NULL ||
-                json_type_array != json_object_get_type( poObjRing ) )
+        if( poObjRing == NULL ||
+            json_type_array != json_object_get_type( poObjRing ) )
         {
-            for(int j=0;j<iRing;j++)
+            for( int j = 0; j < iRing; j++ )
                 delete papoGeoms[j];
             delete[] papoGeoms;
             CPLDebug( "ESRIJSON",
@@ -835,22 +847,24 @@ OGRGeometry* OGRESRIJSONReadPolygon( json_object* poObj)
         papoGeoms[iRing] = poPoly;
 
         const int nPoints = json_object_array_length( poObjRing );
-        for(int i = 0; i < nPoints; i++)
+        for( int i = 0; i < nPoints; i++ )
         {
             int nNumCoords = 2;
-            json_object* poObjCoords
-                = json_object_array_get_idx( poObjRing, i );
-            double dfX, dfY, dfZ;
+            json_object* poObjCoords =
+                json_object_array_get_idx( poObjRing, i );
+            double dfX = 0.0;
+            double dfY = 0.0;
+            double dfZ = 0.0;
             if( !OGRESRIJSONReaderParseXYZMArray (
                     poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
             {
-                for(int j=0;j<=iRing;j++)
+                for( int j = 0; j <= iRing; j++ )
                     delete papoGeoms[j];
                 delete[] papoGeoms;
                 return NULL;
             }
 
-            if(nNumCoords > 2 && (TRUE == bHasZ || FALSE == bHasM))
+            if( nNumCoords > 2 && (bHasZ || !bHasM) )
             {
                 poLine->addPoint( dfX, dfY, dfZ);
             }
@@ -878,8 +892,8 @@ OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
 {
     CPLAssert( NULL != poObj );
 
-    int bHasZ = FALSE;
-    int bHasM = FALSE;
+    bool bHasZ = false;
+    bool bHasM = false;
 
     if( !OGRESRIJSONReaderParseZM( poObj, &bHasZ, &bHasM ) )
     {
@@ -891,28 +905,30 @@ OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
     if( NULL == poObjPoints )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Invalid MultiPoint object. "
-            "Missing \'points\' member." );
+                  "Invalid MultiPoint object. "
+                  "Missing \'points\' member." );
         return NULL;
     }
 
     if( json_type_array != json_object_get_type( poObjPoints ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Invalid MultiPoint object. "
-            "Invalid \'points\' member." );
+                  "Invalid MultiPoint object. "
+                  "Invalid \'points\' member." );
         return NULL;
     }
 
     OGRMultiPoint* poMulti = new OGRMultiPoint();
 
     const int nPoints = json_object_array_length( poObjPoints );
-    for(int i = 0; i < nPoints; i++)
+    for( int i = 0; i < nPoints; i++ )
     {
         int nNumCoords = 2;
-        json_object* poObjCoords
-            = json_object_array_get_idx( poObjPoints, i );
-        double dfX, dfY, dfZ;
+        json_object* poObjCoords =
+            json_object_array_get_idx( poObjPoints, i );
+        double dfX = 0.0;
+        double dfY = 0.0;
+        double dfZ = 0.0;
         if( !OGRESRIJSONReaderParseXYZMArray (
                 poObjCoords, &dfX, &dfY, &dfZ, &nNumCoords) )
         {
@@ -920,7 +936,7 @@ OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
             return NULL;
         }
 
-        if(nNumCoords > 2 && (TRUE == bHasZ || FALSE == bHasM))
+        if( nNumCoords > 2 && (bHasZ || !bHasM) )
         {
             poMulti->addGeometryDirectly( new OGRPoint(dfX, dfY, dfZ) );
         }
@@ -944,20 +960,20 @@ OGRSpatialReference* OGRESRIJSONReadSpatialReference( json_object* poObj )
 /* -------------------------------------------------------------------- */
     OGRSpatialReference* poSRS = NULL;
 
-    json_object* poObjSrs
-        = OGRGeoJSONFindMemberByName( poObj, "spatialReference" );
+    json_object* poObjSrs =
+        OGRGeoJSONFindMemberByName( poObj, "spatialReference" );
     if( NULL != poObjSrs )
     {
         json_object* poObjWkid = OGRGeoJSONFindMemberByName( poObjSrs, "wkid" );
-        if (poObjWkid == NULL)
+        if( poObjWkid == NULL )
         {
-            json_object* poObjWkt
-                = OGRGeoJSONFindMemberByName( poObjSrs, "wkt" );
-            if (poObjWkt == NULL)
+            json_object* poObjWkt =
+                OGRGeoJSONFindMemberByName( poObjSrs, "wkt" );
+            if( poObjWkt == NULL )
                 return NULL;
 
-            char* pszWKT
-                = const_cast<char*>(json_object_get_string( poObjWkt ));
+            char* pszWKT =
+                const_cast<char*>(json_object_get_string( poObjWkt ));
             poSRS = new OGRSpatialReference();
             if( OGRERR_NONE != poSRS->importFromWkt( &pszWKT ) ||
                 poSRS->morphFromESRI() != OGRERR_NONE )
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
index 7ad08f9..65b2d7a 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsondatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeojsondatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONDataSource class (OGR GeoJSON Driver).
@@ -27,31 +26,58 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
+#include "cpl_port.h"
 #include "ogr_geojson.h"
-#include "ogrgeojsonutils.h"
-#include "ogrgeojsonreader.h"
-#include "gdal_utils.h"
-#include <cpl_http.h>
-#include <json.h> // JSON-C
-#include "ogrgeojsonwriter.h"
+
 #include <cstddef>
 #include <cstdlib>
-using namespace std;
+#include <cstring>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_http.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "cpl_vsi_error.h"
+#include "json.h"
+// #include "json_object.h"
+#include "gdal_utils.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
+#include "ogrgeojsonreader.h"
+#include "ogrgeojsonutils.h"
+#include "ogrgeojsonwriter.h"
+#include "ogrsf_frmts.h"
+// #include "symbol_renames.h"
+
+
+CPL_CVSID("$Id: ogrgeojsondatasource.cpp 37374 2017-02-13 11:59:01Z goatbar $");
 
 /************************************************************************/
 /*                           OGRGeoJSONDataSource()                     */
 /************************************************************************/
 
-OGRGeoJSONDataSource::OGRGeoJSONDataSource()
-    : pszName_(NULL), pszGeoData_(NULL), nGeoDataLen_(0),
-        papoLayers_(NULL), papoLayersWriter_(NULL), nLayers_(0), fpOut_(NULL),
-        flTransGeom_( OGRGeoJSONDataSource::eGeometryPreserve ),
-        flTransAttrs_( OGRGeoJSONDataSource::eAttributesPreserve ),
-        bOtherPages_(false),
-        bFpOutputIsSeekable_( false ),
-        nBBOXInsertLocation_(0),
-        bUpdatable_( false )
-{ }
+OGRGeoJSONDataSource::OGRGeoJSONDataSource() :
+    pszName_(NULL),
+    pszGeoData_(NULL),
+    nGeoDataLen_(0),
+    papoLayers_(NULL),
+    papoLayersWriter_(NULL),
+    nLayers_(0),
+    fpOut_(NULL),
+    flTransGeom_(OGRGeoJSONDataSource::eGeometryPreserve),
+    flTransAttrs_(OGRGeoJSONDataSource::eAttributesPreserve),
+    bOtherPages_(false),
+    bFpOutputIsSeekable_(false),
+    nBBOXInsertLocation_(0),
+    bUpdatable_(false)
+{}
 
 /************************************************************************/
 /*                           ~OGRGeoJSONDataSource()                    */
@@ -110,14 +136,16 @@ int OGRGeoJSONDataSource::Open( GDALOpenInfo* poOpenInfo,
         return FALSE;
     }
 
+    SetDescription( poOpenInfo->pszFilename );
     LoadLayers(poOpenInfo->papszOpenOptions);
     if( nLayers_ == 0 )
     {
         bool bEmitError = true;
         if( eGeoJSONSourceService == nSrcType )
         {
-            CPLString osTmpFilename = CPLSPrintf("/vsimem/%p/%s", this,
-                                        CPLGetFilename(poOpenInfo->pszFilename));
+            const CPLString osTmpFilename =
+                CPLSPrintf("/vsimem/%p/%s", this,
+                           CPLGetFilename(poOpenInfo->pszFilename));
             VSIFCloseL(VSIFileFromMemBuffer( osTmpFilename,
                                              (GByte*)pszGeoData_,
                                              nGeoDataLen_,
@@ -132,7 +160,7 @@ int OGRGeoJSONDataSource::Open( GDALOpenInfo* poOpenInfo,
         if( bEmitError )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                    "Failed to read GeoJSON data" );
+                      "Failed to read GeoJSON data" );
         }
         return FALSE;
     }
@@ -187,18 +215,19 @@ OGRLayer* OGRGeoJSONDataSource::GetLayer( int nLayer )
 /************************************************************************/
 
 OGRLayer* OGRGeoJSONDataSource::ICreateLayer( const char* pszNameIn,
-                                             OGRSpatialReference* poSRS,
-                                             OGRwkbGeometryType eGType,
-                                             char** papszOptions )
+                                              OGRSpatialReference* poSRS,
+                                              OGRwkbGeometryType eGType,
+                                              char** papszOptions )
 {
-    if ( NULL == fpOut_ )
+    if( NULL == fpOut_ )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "GeoJSON driver doesn't support creating a layer on a read-only datasource");
+                 "GeoJSON driver doesn't support creating a layer "
+                 "on a read-only datasource");
         return NULL;
     }
 
-    if ( nLayers_ != 0 )
+    if( nLayers_ != 0 )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "GeoJSON driver doesn't support creating more than one layer");
@@ -210,10 +239,16 @@ OGRLayer* OGRGeoJSONDataSource::ICreateLayer( const char* pszNameIn,
     bool bWriteFC_BBOX =
         CPLTestBool(CSLFetchNameValueDef(papszOptions, "WRITE_BBOX", "FALSE"));
 
+    const bool bRFC7946 = CPLTestBool(
+        CSLFetchNameValueDef(papszOptions, "RFC7946", "FALSE"));
+
     const char* pszNativeData = CSLFetchNameValue(papszOptions, "NATIVE_DATA");
-    const char* pszNativeMediaType = CSLFetchNameValue(papszOptions, "NATIVE_MEDIA_TYPE");
+    const char* pszNativeMediaType =
+        CSLFetchNameValue(papszOptions, "NATIVE_MEDIA_TYPE");
     bool bWriteCRSIfWGS84 = true;
-    if( pszNativeMediaType && EQUAL(pszNativeMediaType, "application/vnd.geo+json") )
+    bool bFoundNameInNativeData = false;
+    if( pszNativeMediaType &&
+        EQUAL(pszNativeMediaType, "application/vnd.geo+json") )
     {
         json_object *poObj = NULL;
         if( OGRJSonParse(pszNativeData, &poObj) &&
@@ -240,41 +275,118 @@ OGRLayer* OGRGeoJSONDataSource::ICreateLayer( const char* pszNameIn,
                 }
                 if( strcmp(it.key, "crs") == 0 )
                 {
-                    bWriteCRSIfWGS84 = true;
+                    if( !bRFC7946 )
+                        bWriteCRSIfWGS84 = true;
                     continue;
                 }
+                // See https://tools.ietf.org/html/rfc7946#section-7.1
+                if( bRFC7946 &&
+                    (strcmp(it.key, "coordinates") == 0 ||
+                     strcmp(it.key, "geometries") == 0 ||
+                     strcmp(it.key, "geometry") == 0 ||
+                     strcmp(it.key, "properties") == 0 ) )
+                {
+                    continue;
+                }
+
+                if( strcmp(it.key, "name") == 0 )
+                    bFoundNameInNativeData = true;
+
+                // If a native description exists, ignore it if an explicit
+                // DESCRIPTION option has been provided.
+                if( strcmp(it.key, "description") == 0 &&
+                    CSLFetchNameValue(papszOptions, "DESCRIPTION") )
+                {
+                    continue;
+                }
+
                 json_object* poKey = json_object_new_string(it.key);
-                VSIFPrintfL( fpOut_, "%s: ", json_object_to_json_string(poKey) );
+                VSIFPrintfL( fpOut_, "%s: ",
+                             json_object_to_json_string(poKey) );
                 json_object_put(poKey);
-                VSIFPrintfL( fpOut_, "%s,\n", json_object_to_json_string(it.val) );
+                VSIFPrintfL( fpOut_, "%s,\n",
+                             json_object_to_json_string(it.val) );
             }
             json_object_put(poObj);
         }
     }
 
-    if (poSRS)
+    if( !bFoundNameInNativeData &&
+        CPLFetchBool(papszOptions, "WRITE_NAME", true) &&
+        !EQUAL(pszNameIn, OGRGeoJSONLayer::DefaultName) &&
+        !EQUAL(pszNameIn, "") )
+    {
+        json_object* poName = json_object_new_string(pszNameIn);
+        VSIFPrintfL( fpOut_, "\"name\": %s,\n",
+                     json_object_to_json_string(poName) );
+        json_object_put(poName);
+    }
+
+    const char* pszDescription = CSLFetchNameValue(papszOptions, "DESCRIPTION");
+    if( pszDescription )
+    {
+        json_object* poDesc = json_object_new_string(pszDescription);
+        VSIFPrintfL( fpOut_, "\"description\": %s,\n",
+                     json_object_to_json_string(poDesc) );
+        json_object_put(poDesc);
+    }
+
+    OGRCoordinateTransformation* poCT = NULL;
+    if( bRFC7946 )
+    {
+        if( poSRS == NULL )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "No SRS set on layer. Assuming it is long/lat on WGS84 ellipsoid");
+        }
+        else
+        {
+            OGRSpatialReference oSRSWGS84;
+            oSRSWGS84.SetWellKnownGeogCS( "WGS84" );
+            if( !poSRS->IsSame(&oSRSWGS84) )
+            {
+                poCT = OGRCreateCoordinateTransformation( poSRS, &oSRSWGS84 );
+                if( poCT == NULL )
+                {
+                    CPLError(
+                        CE_Warning, CPLE_AppDefined,
+                        "Failed to create coordinate transformation between the "
+                        "input coordinate system and WGS84.  This may be because "
+                        "they are not transformable, or because projection "
+                        "services (PROJ.4 DLL/.so) could not be loaded." );
+
+                    return NULL;
+                }
+            }
+        }
+    }
+    else if( poSRS )
     {
         const char* pszAuthority = poSRS->GetAuthorityName(NULL);
         const char* pszAuthorityCode = poSRS->GetAuthorityCode(NULL);
-        if (pszAuthority != NULL && pszAuthorityCode != NULL &&
+        if( pszAuthority != NULL && pszAuthorityCode != NULL &&
             EQUAL(pszAuthority, "EPSG") &&
             (bWriteCRSIfWGS84 || !EQUAL(pszAuthorityCode, "4326")) )
         {
             json_object* poObjCRS = json_object_new_object();
             json_object_object_add(poObjCRS, "type",
-                                json_object_new_string("name"));
+                                   json_object_new_string("name"));
             json_object* poObjProperties = json_object_new_object();
             json_object_object_add(poObjCRS, "properties", poObjProperties);
 
-            if (strcmp(pszAuthorityCode, "4326") == 0)
+            if( strcmp(pszAuthorityCode, "4326") == 0 )
             {
-                json_object_object_add(poObjProperties, "name",
-                                    json_object_new_string("urn:ogc:def:crs:OGC:1.3:CRS84"));
+                json_object_object_add(
+                    poObjProperties, "name",
+                    json_object_new_string("urn:ogc:def:crs:OGC:1.3:CRS84"));
             }
             else
             {
-                json_object_object_add(poObjProperties, "name",
-                                    json_object_new_string(CPLSPrintf("urn:ogc:def:crs:EPSG::%s", pszAuthorityCode)));
+                json_object_object_add(
+                    poObjProperties, "name",
+                    json_object_new_string(
+                        CPLSPrintf("urn:ogc:def:crs:EPSG::%s",
+                                   pszAuthorityCode)));
             }
 
             const char* pszCRS = json_object_to_json_string( poObjCRS );
@@ -284,27 +396,27 @@ OGRLayer* OGRGeoJSONDataSource::ICreateLayer( const char* pszNameIn,
         }
     }
 
-    if (bFpOutputIsSeekable_ && bWriteFC_BBOX)
+    if( bFpOutputIsSeekable_ && bWriteFC_BBOX )
     {
-        nBBOXInsertLocation_ = (int) VSIFTellL( fpOut_ );
+        nBBOXInsertLocation_ = static_cast<int>(VSIFTellL( fpOut_ ));
 
-        char szSpaceForBBOX[SPACE_FOR_BBOX+1];
-        memset(szSpaceForBBOX, ' ', SPACE_FOR_BBOX);
-        szSpaceForBBOX[SPACE_FOR_BBOX] = '\0';
-        VSIFPrintfL( fpOut_, "%s\n", szSpaceForBBOX);
+        const std::string osSpaceForBBOX(SPACE_FOR_BBOX + 1, ' ');
+        VSIFPrintfL( fpOut_, "%s\n", osSpaceForBBOX.c_str());
     }
 
     VSIFPrintfL( fpOut_, "\"features\": [\n" );
 
-    OGRGeoJSONWriteLayer* poLayer
-        = new OGRGeoJSONWriteLayer( pszNameIn, eGType, papszOptions, bWriteFC_BBOX, this );
+    OGRGeoJSONWriteLayer* poLayer =
+        new OGRGeoJSONWriteLayer( pszNameIn, eGType, papszOptions,
+                                  bWriteFC_BBOX, poCT, this );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
     CPLAssert(papoLayers_ == NULL);
-    papoLayersWriter_ = (OGRGeoJSONWriteLayer **)
-        CPLRealloc( papoLayers_,  sizeof(OGRGeoJSONWriteLayer*) * (nLayers_ + 1) );
+    papoLayersWriter_ = static_cast<OGRGeoJSONWriteLayer **>(
+        CPLRealloc(papoLayers_,
+                   sizeof(OGRGeoJSONWriteLayer *) * (nLayers_ + 1)));
 
     papoLayersWriter_[nLayers_++] = poLayer;
 
@@ -320,9 +432,6 @@ int OGRGeoJSONDataSource::TestCapability( const char* pszCap )
     if( EQUAL( pszCap, ODsCCreateLayer ) )
         return fpOut_ != NULL && nLayers_ == 0;
 
-    // if( EQUAL( pszCap, ODsCDeleteLayer ) )
-    //     return FALSE;
-
     return FALSE;
 }
 
@@ -335,12 +444,13 @@ int OGRGeoJSONDataSource::Create( const char* pszName,
 {
     CPLAssert( NULL == fpOut_ );
 
-    if (strcmp(pszName, "/dev/stdout") == 0)
+    if( strcmp(pszName, "/dev/stdout") == 0 )
         pszName = "/vsistdout/";
 
-    bFpOutputIsSeekable_ =  !(strcmp(pszName,"/vsistdout/") == 0 ||
-                              STARTS_WITH(pszName, "/vsigzip/") ||
-                              STARTS_WITH(pszName, "/vsizip/"));
+    bFpOutputIsSeekable_ =
+        !(strcmp(pszName,"/vsistdout/") == 0 ||
+          STARTS_WITH(pszName, "/vsigzip/") ||
+          STARTS_WITH(pszName, "/vsizip/"));
 
 /* -------------------------------------------------------------------- */
 /*     File overwrite not supported.                                    */
@@ -356,12 +466,12 @@ int OGRGeoJSONDataSource::Create( const char* pszName,
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
-    fpOut_ = VSIFOpenL( pszName, "w" );
+    fpOut_ = VSIFOpenExL( pszName, "w", true );
     if( NULL == fpOut_)
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to create GeoJSON datasource: %s.",
-                  pszName );
+                  "Failed to create GeoJSON datasource: %s: %s",
+                  pszName, VSIGetLastErrorMsg() );
         return FALSE;
     }
 
@@ -384,7 +494,8 @@ OGRGeoJSONDataSource::SetGeometryTranslation( GeometryTranslation type )
 /*                           SetAttributesTranslation()                 */
 /************************************************************************/
 
-void OGRGeoJSONDataSource::SetAttributesTranslation( AttributesTranslation type )
+void
+OGRGeoJSONDataSource::SetAttributesTranslation( AttributesTranslation type )
 {
     flTransAttrs_ = type;
 }
@@ -431,34 +542,21 @@ int OGRGeoJSONDataSource::ReadFromFile( GDALOpenInfo* poOpenInfo )
 {
     GByte* pabyOut = NULL;
     if( poOpenInfo->fpL == NULL ||
-        !VSIIngestFile( poOpenInfo->fpL, poOpenInfo->pszFilename, &pabyOut, NULL, -1) )
+        !VSIIngestFile(poOpenInfo->fpL, poOpenInfo->pszFilename,
+                       &pabyOut, NULL, -1) )
     {
         return FALSE;
     }
 
     VSIFCloseL(poOpenInfo->fpL);
     poOpenInfo->fpL = NULL;
-    pszGeoData_ = (char*) pabyOut;
+    pszGeoData_ = reinterpret_cast<char *>(pabyOut);
 
     pszName_ = CPLStrdup( poOpenInfo->pszFilename );
 
     CPLAssert( NULL != pszGeoData_ );
 
-    if( poOpenInfo->eAccess == GA_Update )
-    {
-        VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb+");
-        if( fp == NULL )
-        {
-            CPLError(CE_Failure, CPLE_FileIO,
-                     "Update not supported because file is not writable");
-            return FALSE;
-        }
-        else
-        {
-            bUpdatable_ = true;
-        }
-        VSIFCloseL(fp);
-    }
+    bUpdatable_ = ( poOpenInfo->eAccess == GA_Update );
 
     return TRUE;
 }
@@ -483,10 +581,12 @@ int OGRGeoJSONDataSource::ReadFromService( const char* pszSource )
 /* -------------------------------------------------------------------- */
     CPLErrorReset();
 
-    char* papsOptions[] = { (char*) "HEADERS=Accept: text/plain, application/json", NULL };
+    char* papsOptions[] = {
+        const_cast<char *>("HEADERS=Accept: text/plain, application/json"),
+        NULL
+    };
 
-    CPLHTTPResult* pResult
-        = CPLHTTPFetch( pszSource, papsOptions );
+    CPLHTTPResult* pResult = CPLHTTPFetch( pszSource, papsOptions );
 
 /* -------------------------------------------------------------------- */
 /*      Try to handle CURL/HTTP errors.                                 */
@@ -510,9 +610,9 @@ int OGRGeoJSONDataSource::ReadFromService( const char* pszSource )
 /* -------------------------------------------------------------------- */
 /*      Copy returned GeoJSON data to text buffer.                      */
 /* -------------------------------------------------------------------- */
-    const char* pszData = reinterpret_cast<char*>(pResult->pabyData);
+    char* pszData = reinterpret_cast<char *>(pResult->pabyData);
 
-    if ( eGeoJSONProtocolUnknown != GeoJSONGetProtocolType( pszData ) )
+    if( eGeoJSONProtocolUnknown != GeoJSONGetProtocolType( pszData ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
             "The data that was downloaded also starts with "
@@ -522,8 +622,8 @@ int OGRGeoJSONDataSource::ReadFromService( const char* pszSource )
         return FALSE;
     }
 
-    // Directly assign CPLHTTPResult::pabyData to pszGeoData_
-    pszGeoData_ = (char*) pszData;
+    // Directly assign CPLHTTPResult::pabyData to pszGeoData_.
+    pszGeoData_ = pszData;
     nGeoDataLen_ = pResult->nDataLen;
     pResult->pabyData = NULL;
     pResult->nDataLen = 0;
@@ -553,35 +653,35 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptionsIn)
     }
 
     const char* const apszPrefix[] = { "loadGeoJSON(", "jsonp(" };
-    for(size_t iP = 0; iP < sizeof(apszPrefix) / sizeof(apszPrefix[0]); iP++ )
+    for( size_t iP = 0; iP < sizeof(apszPrefix) / sizeof(apszPrefix[0]); iP++ )
     {
         if( strncmp(pszGeoData_, apszPrefix[iP], strlen(apszPrefix[iP])) == 0 )
         {
-            size_t nDataLen = strlen(pszGeoData_);
+            const size_t nDataLen = strlen(pszGeoData_);
             memmove( pszGeoData_, pszGeoData_ + strlen(apszPrefix[iP]),
                     nDataLen - strlen(apszPrefix[iP]) );
             size_t i = nDataLen - strlen(apszPrefix[iP]);
             pszGeoData_[i] = '\0';
             while( i > 0 && pszGeoData_[i] != ')' )
             {
-                i --;
+                i--;
             }
             pszGeoData_[i] = '\0';
         }
     }
 
-
-    if ( !GeoJSONIsObject( pszGeoData_) )
+    if( !GeoJSONIsObject( pszGeoData_) )
     {
-        CPLDebug( "GeoJSON", "No valid GeoJSON data found in source '%s'", pszName_ );
+        CPLDebug( "GeoJSON",
+                  "No valid GeoJSON data found in source '%s'", pszName_ );
         return;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Is it ESRI Feature Service data ?                               */
 /* -------------------------------------------------------------------- */
-    if ( strstr(pszGeoData_, "esriGeometry") ||
-         strstr(pszGeoData_, "esriFieldType") )
+    if( strstr(pszGeoData_, "esriGeometry") ||
+        strstr(pszGeoData_, "esriFieldType") )
     {
         OGRESRIJSONReader reader;
         OGRErr err = reader.Parse( pszGeoData_ );
@@ -591,10 +691,14 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptionsIn)
             if( poObj && json_object_get_type(poObj) == json_type_object )
             {
                 json_object* poExceededTransferLimit =
-                    json_object_object_get(poObj, "exceededTransferLimit");
-                if( poExceededTransferLimit && json_object_get_type(poExceededTransferLimit) == json_type_boolean )
+                    CPL_json_object_object_get(poObj, "exceededTransferLimit");
+                if( poExceededTransferLimit &&
+                    json_object_get_type(poExceededTransferLimit) ==
+                        json_type_boolean )
+                {
                     bOtherPages_ = CPL_TO_BOOL(
                         json_object_get_boolean(poExceededTransferLimit) );
+                }
             }
             reader.ReadLayers( this );
         }
@@ -604,8 +708,8 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptionsIn)
 /* -------------------------------------------------------------------- */
 /*      Is it TopoJSON data ?                                           */
 /* -------------------------------------------------------------------- */
-    if ( strstr(pszGeoData_, "\"type\"") &&
-         strstr(pszGeoData_, "\"Topology\"")  )
+    if( strstr(pszGeoData_, "\"type\"") &&
+        strstr(pszGeoData_, "\"Topology\"") )
     {
         OGRTopoJSONReader reader;
         OGRErr err = reader.Parse( pszGeoData_ );
@@ -634,12 +738,13 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptionsIn)
     }
 
     reader.SetFlattenNestedAttributes(
-        CPL_TO_BOOL(CSLFetchBoolean(papszOpenOptionsIn, "FLATTEN_NESTED_ATTRIBUTES", FALSE)),
-        CSLFetchNameValueDef(papszOpenOptionsIn, "NESTED_ATTRIBUTE_SEPARATOR", "_")[0]);
+        CPLFetchBool(papszOpenOptionsIn, "FLATTEN_NESTED_ATTRIBUTES", false),
+        CSLFetchNameValueDef(papszOpenOptionsIn,
+                             "NESTED_ATTRIBUTE_SEPARATOR", "_")[0]);
 
-    const int bDefaultNativeData = bUpdatable_ ? TRUE : FALSE ;
+    const bool bDefaultNativeData = bUpdatable_;
     reader.SetStoreNativeData(
-        CPL_TO_BOOL(CSLFetchBoolean(papszOpenOptionsIn, "NATIVE_DATA", bDefaultNativeData)));
+        CPLFetchBool(papszOpenOptionsIn, "NATIVE_DATA", bDefaultNativeData));
 
     reader.SetArrayAsString(
         CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn, "ARRAY_AS_STRING",
@@ -648,20 +753,27 @@ void OGRGeoJSONDataSource::LoadLayers(char** papszOpenOptionsIn)
 /* -------------------------------------------------------------------- */
 /*      Parse GeoJSON and build valid OGRLayer instance.                */
 /* -------------------------------------------------------------------- */
-    OGRErr err = reader.Parse( pszGeoData_ );
+    const OGRErr err = reader.Parse( pszGeoData_ );
     if( OGRERR_NONE == err )
     {
         json_object* poObj = reader.GetJSonObject();
         if( poObj && json_object_get_type(poObj) == json_type_object )
         {
-            json_object* poProperties = json_object_object_get(poObj, "properties");
-            if( poProperties && json_object_get_type(poProperties) == json_type_object )
+            json_object* poProperties =
+                CPL_json_object_object_get(poObj, "properties");
+            if( poProperties &&
+                json_object_get_type(poProperties) == json_type_object )
             {
                 json_object* poExceededTransferLimit =
-                    json_object_object_get(poProperties, "exceededTransferLimit");
-                if( poExceededTransferLimit && json_object_get_type(poExceededTransferLimit) == json_type_boolean )
-                  bOtherPages_ = CPL_TO_BOOL(
-                      json_object_get_boolean(poExceededTransferLimit) );
+                    CPL_json_object_object_get(poProperties,
+                                               "exceededTransferLimit");
+                if( poExceededTransferLimit &&
+                    json_object_get_type(poExceededTransferLimit) ==
+                        json_type_boolean )
+                {
+                    bOtherPages_ = CPL_TO_BOOL(
+                        json_object_get_boolean(poExceededTransferLimit) );
+                }
             }
         }
 
@@ -681,12 +793,13 @@ void OGRGeoJSONDataSource::AddLayer( OGRGeoJSONLayer* poLayer )
 
     poLayer->DetectGeometryType();
 
-    /* Return layer in readable state. */
+    // Return layer in readable state.
     poLayer->ResetReading();
 
-    papoLayers_ = (OGRGeoJSONLayer**)CPLRealloc( papoLayers_, sizeof(OGRGeoJSONLayer*) * (nLayers_ + 1));
+    papoLayers_ = static_cast<OGRGeoJSONLayer**>(
+        CPLRealloc( papoLayers_, sizeof(OGRGeoJSONLayer*) * (nLayers_ + 1)));
     papoLayers_[nLayers_] = poLayer;
-    nLayers_ ++;
+    nLayers_++;
 }
 
 /************************************************************************/
@@ -698,24 +811,15 @@ void OGRGeoJSONDataSource::FlushCache()
     if( papoLayersWriter_ != NULL )
         return;
 
-    for( int i=0; i < nLayers_; i++ )
+    for( int i = 0; i < nLayers_; i++ )
     {
         if( papoLayers_[i]->HasBeenUpdated() )
         {
             papoLayers_[i]->SetUpdated(false);
 
-            CPLString osBackup(pszName_);
-            osBackup += ".bak";
-            if( VSIRename(pszName_, osBackup) < 0 )
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                         "Cannot create backup copy");
-                return;
-            }
-
             bool bOK = false;
 
-            // Disable all filters
+            // Disable all filters.
             OGRFeatureQuery *poAttrQueryBak = papoLayers_[i]->m_poAttrQuery;
             papoLayers_[i]->m_poAttrQuery = NULL;
             OGRGeometry* poFilterGeomBak = papoLayers_[i]->m_poFilterGeom;
@@ -723,7 +827,7 @@ void OGRGeoJSONDataSource::FlushCache()
 
             // If the source data only contained one single feature and
             // that's still the case, then do not use a FeatureCollection
-            // on writing
+            // on writing.
             bool bAlreadyDone = false;
             if( papoLayers_[i]->GetFeatureCount(TRUE) == 1 &&
                 papoLayers_[i]->GetMetadata("NATIVE_DATA") == NULL )
@@ -735,14 +839,16 @@ void OGRGeoJSONDataSource::FlushCache()
                     if( poFeature->GetNativeData() != NULL )
                     {
                         bAlreadyDone = true;
-                        json_object* poObj = OGRGeoJSONWriteFeature( poFeature,
-                                                                     FALSE/* bWriteBBOX */,
-                                                                     -1 /*nCoordPrecision*/,
-                                                                     -1 /* nSignificatnFigures*/);
+                        OGRGeoJSONWriteOptions oOptions;
+                        json_object* poObj =
+                            OGRGeoJSONWriteFeature(poFeature, oOptions);
                         VSILFILE* fp = VSIFOpenL(pszName_, "wb");
                         if( fp != NULL )
                         {
-                            bOK = VSIFPrintfL( fp, "%s", json_object_to_json_string( poObj ) ) > 0;
+                            bOK =
+                                VSIFPrintfL(
+                                    fp, "%s",
+                                    json_object_to_json_string(poObj) ) > 0;
                             VSIFCloseL( fp );
                         }
                         json_object_put( poObj );
@@ -751,18 +857,20 @@ void OGRGeoJSONDataSource::FlushCache()
                 }
             }
 
-            // Otherwise do layer translation
+            // Otherwise do layer translation.
             if( !bAlreadyDone )
             {
-                char** papszOptions = NULL;
-                papszOptions = CSLAddString(papszOptions, "-f");
+                char** papszOptions = CSLAddString(NULL, "-f");
                 papszOptions = CSLAddString(papszOptions, "GeoJSON");
                 GDALVectorTranslateOptions* psOptions =
                     GDALVectorTranslateOptionsNew(papszOptions, NULL);
                 CSLDestroy(papszOptions);
                 GDALDatasetH hSrcDS = this;
+                CPLString osNewFilename(pszName_);
+                osNewFilename += ".tmp";
                 GDALDatasetH hOutDS =
-                    GDALVectorTranslate(pszName_, NULL, 1, &hSrcDS, psOptions, NULL);
+                    GDALVectorTranslate(osNewFilename, NULL, 1, &hSrcDS,
+                                        psOptions, NULL);
                 GDALVectorTranslateOptionsFree(psOptions);
 
                 if( hOutDS != NULL )
@@ -771,20 +879,31 @@ void OGRGeoJSONDataSource::FlushCache()
                     GDALClose(hOutDS);
                     bOK = (CPLGetLastErrorType() == CE_None);
                 }
+                if( bOK )
+                {
+                    CPLString osBackup(pszName_);
+                    osBackup += ".bak";
+                    if( VSIRename(pszName_, osBackup) < 0 )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                "Cannot create backup copy");
+                    }
+                    else if( VSIRename(osNewFilename, pszName_) < 0 )
+                    {
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                "Cannot rename %s to %s",
+                                osNewFilename.c_str(), pszName_);
+                    }
+                    else
+                    {
+                        VSIUnlink(osBackup);
+                    }
+                }
             }
 
-            // Restore filters
+            // Restore filters.
             papoLayers_[i]->m_poAttrQuery = poAttrQueryBak;
             papoLayers_[i]->m_poFilterGeom = poFilterGeomBak;
-
-            if( bOK )
-            {
-                VSIUnlink(osBackup);
-            }
-            else
-            {
-                VSIRename(osBackup, pszName_);
-            }
         }
     }
 }
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp
index c36f113..67b1c54 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsondriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeojsondriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONDriver class (OGR GeoJSON Driver).
@@ -27,10 +26,27 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <cpl_conv.h>
-#include <cpl_http.h>
+#include "cpl_port.h"
 #include "ogr_geojson.h"
 
+#include <stdlib.h>
+#include <string.h>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_http.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+// #include "json_object.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogrgeojsonutils.h"
+#include "ogrsf_frmts.h"
+
+CPL_CVSID("$Id: ogrgeojsondriver.cpp 37374 2017-02-13 11:59:01Z goatbar $");
+
 class OGRESRIFeatureServiceDataset;
 
 /************************************************************************/
@@ -39,26 +55,26 @@ class OGRESRIFeatureServiceDataset;
 
 class OGRESRIFeatureServiceLayer: public OGRLayer
 {
-        OGRESRIFeatureServiceDataset* poDS;
-        OGRFeatureDefn* poFeatureDefn;
-        GIntBig         nFeaturesRead;
-        GIntBig         nLastFID;
-        bool            bOtherPage;
-        bool            bUseSequentialFID;
-
-    public:
-        OGRESRIFeatureServiceLayer(OGRESRIFeatureServiceDataset* poDS);
-       ~OGRESRIFeatureServiceLayer();
-
-        void ResetReading();
-        OGRFeature* GetNextFeature();
-        GIntBig GetFeatureCount( int bForce = TRUE );
-        OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-        virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent,
-                                       int bForce)
-                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-        int TestCapability( const char* pszCap );
-        OGRFeatureDefn* GetLayerDefn() { return poFeatureDefn; }
+    OGRESRIFeatureServiceDataset* poDS;
+    OGRFeatureDefn* poFeatureDefn;
+    GIntBig         nFeaturesRead;
+    GIntBig         nLastFID;
+    bool            bOtherPage;
+    bool            bUseSequentialFID;
+
+  public:
+    explicit OGRESRIFeatureServiceLayer( OGRESRIFeatureServiceDataset* poDS );
+    virtual ~OGRESRIFeatureServiceLayer();
+
+    void ResetReading() override;
+    OGRFeature* GetNextFeature() override;
+    GIntBig GetFeatureCount( int bForce = TRUE ) override;
+    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent,
+                                   int bForce) override
+            { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+    int TestCapability( const char* pszCap ) override;
+    OGRFeatureDefn* GetLayerDefn() override { return poFeatureDefn; }
 };
 
 /************************************************************************/
@@ -67,27 +83,29 @@ class OGRESRIFeatureServiceLayer: public OGRLayer
 
 class OGRESRIFeatureServiceDataset: public GDALDataset
 {
-        CPLString              osURL;
-        GIntBig                nFirstOffset, nLastOffset;
-        OGRGeoJSONDataSource* poCurrent;
-        OGRESRIFeatureServiceLayer* poLayer;
+    CPLString              osURL;
+    GIntBig                nFirstOffset;
+    GIntBig                nLastOffset;
+    OGRGeoJSONDataSource  *poCurrent;
+    OGRESRIFeatureServiceLayer *poLayer;
 
-        int                     LoadPage();
+    int                     LoadPage();
 
-    public:
-        OGRESRIFeatureServiceDataset(const CPLString &osURL,
-                                     OGRGeoJSONDataSource* poFirst);
-       ~OGRESRIFeatureServiceDataset();
+  public:
+    OGRESRIFeatureServiceDataset( const CPLString &osURL,
+                                  OGRGeoJSONDataSource* poFirst );
+    ~OGRESRIFeatureServiceDataset();
 
-        int GetLayerCount() { return 1; }
-        OGRLayer* GetLayer( int nLayer ) { return (nLayer == 0) ? poLayer : NULL; }
+    int GetLayerCount() override { return 1; }
+    OGRLayer* GetLayer( int nLayer ) override
+        { return (nLayer == 0) ? poLayer : NULL; }
 
-        OGRLayer* GetUnderlyingLayer() { return poCurrent->GetLayer(0); }
+    OGRLayer* GetUnderlyingLayer() { return poCurrent->GetLayer(0); }
 
-        int ResetReading();
-        int LoadNextPage();
+    int MyResetReading();
+    int LoadNextPage();
 
-        const CPLString&                GetURL() { return osURL; }
+    const CPLString& GetURL() { return osURL; }
 };
 
 /************************************************************************/
@@ -107,9 +125,11 @@ OGRESRIFeatureServiceLayer::OGRESRIFeatureServiceLayer(
     SetDescription(poFeatureDefn->GetName());
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType(wkbNone);
-    for(int i=0;i<poSrcFeatDefn->GetFieldCount();i++)
+
+    for( int i = 0; i < poSrcFeatDefn->GetFieldCount(); i++ )
         poFeatureDefn->AddFieldDefn(poSrcFeatDefn->GetFieldDefn(i));
-    for(int i=0;i<poSrcFeatDefn->GetGeomFieldCount();i++)
+
+    for( int i = 0; i <poSrcFeatDefn->GetGeomFieldCount(); i++ )
         poFeatureDefn->AddGeomFieldDefn(poSrcFeatDefn->GetGeomFieldDefn(i));
 }
 
@@ -128,7 +148,7 @@ OGRESRIFeatureServiceLayer::~OGRESRIFeatureServiceLayer()
 
 void OGRESRIFeatureServiceLayer::ResetReading()
 {
-    poDS->ResetReading();
+    poDS->MyResetReading();
     nFeaturesRead = 0;
     nLastFID = 0;
     bOtherPage = false;
@@ -170,10 +190,10 @@ OGRFeature* OGRESRIFeatureServiceLayer::GetNextFeature()
         nFeaturesRead ++;
         delete poSrcFeat;
 
-        if((m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
-        && (m_poAttrQuery == NULL
-            || m_poAttrQuery->Evaluate( poFeature )) )
+        if( (m_poFilterGeom == NULL
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
         {
             return poFeature;
         }
@@ -203,14 +223,18 @@ GIntBig OGRESRIFeatureServiceLayer::GetFeatureCount( int bForce )
     GIntBig nFeatureCount = -1;
     if( m_poAttrQuery == NULL && m_poFilterGeom == NULL )
     {
-        CPLString osNewURL = CPLURLAddKVP(poDS->GetURL(), "returnCountOnly", "true");
+        const CPLString osNewURL =
+            CPLURLAddKVP(poDS->GetURL(), "returnCountOnly", "true");
         CPLHTTPResult* pResult = NULL;
         CPLErrorReset();
         pResult = CPLHTTPFetch( osNewURL, NULL );
-        if( pResult != NULL && pResult->nDataLen != 0 && CPLGetLastErrorNo() == 0 &&
+        if( pResult != NULL &&
+            pResult->nDataLen != 0 &&
+            CPLGetLastErrorNo() == 0 &&
             pResult->nStatus == 0 )
         {
-            const char* pszCount = strstr((const char*)pResult->pabyData, "\"count\"");
+            const char* pszCount =
+                strstr((const char*)pResult->pabyData, "\"count\"");
             if( pszCount )
             {
                 pszCount = strchr(pszCount, ':');
@@ -232,23 +256,26 @@ GIntBig OGRESRIFeatureServiceLayer::GetFeatureCount( int bForce )
 /*                               GetExtent()                            */
 /************************************************************************/
 
-OGRErr OGRESRIFeatureServiceLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+OGRErr OGRESRIFeatureServiceLayer::GetExtent( OGREnvelope *psExtent,
+                                              int bForce )
 {
     OGRErr eErr = OGRERR_FAILURE;
-    CPLString osNewURL = CPLURLAddKVP(poDS->GetURL(), "returnExtentOnly", "true");
+    CPLString osNewURL =
+        CPLURLAddKVP(poDS->GetURL(), "returnExtentOnly", "true");
     osNewURL = CPLURLAddKVP(osNewURL, "f", "geojson");
     CPLErrorReset();
     CPLHTTPResult* pResult = CPLHTTPFetch( osNewURL, NULL );
     if( pResult != NULL && pResult->nDataLen != 0 && CPLGetLastErrorNo() == 0 &&
         pResult->nStatus == 0 )
     {
-        const char* pszBBox = strstr((const char*)pResult->pabyData, "\"bbox\"");
+        const char* pszBBox =
+            strstr((const char*)pResult->pabyData, "\"bbox\"");
         if( pszBBox )
         {
             pszBBox = strstr(pszBBox, ":[");
             if( pszBBox )
             {
-                pszBBox+=2;
+                pszBBox += 2;
                 char** papszTokens = CSLTokenizeString2(pszBBox, ",", 0);
                 if( CSLCount(papszTokens) >= 4 )
                 {
@@ -272,32 +299,40 @@ OGRErr OGRESRIFeatureServiceLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 /*                      OGRESRIFeatureServiceDataset()                  */
 /************************************************************************/
 
-OGRESRIFeatureServiceDataset::OGRESRIFeatureServiceDataset(const CPLString &osURLIn,
-                                                           OGRGeoJSONDataSource* poFirst) :
+OGRESRIFeatureServiceDataset::OGRESRIFeatureServiceDataset(
+    const CPLString &osURLIn,
+    OGRGeoJSONDataSource* poFirst) :
     poCurrent(poFirst)
 {
     poLayer = new OGRESRIFeatureServiceLayer(this);
-    this->osURL = osURLIn;
-    if( CPLURLGetValue(this->osURL, "resultRecordCount").size() == 0 )
+    osURL = osURLIn;
+    if( CPLURLGetValue(osURL, "resultRecordCount").empty() )
     {
         // We assume that if the server sets the exceededTransferLimit, the
         // and resultRecordCount is not set, the number of features returned
         // in our first request is the maximum allowed by the server
-        // So set it for following requests
-        this->osURL = CPLURLAddKVP(this->osURL, "resultRecordCount",
-                CPLSPrintf("%d", (int)poFirst->GetLayer(0)->GetFeatureCount()));
+        // So set it for following requests.
+        osURL =
+            CPLURLAddKVP(
+                this->osURL, "resultRecordCount",
+                CPLSPrintf(
+                    "%d",
+                    static_cast<int>(poFirst->GetLayer(0)->GetFeatureCount())));
     }
     else
     {
-        int nUserSetRecordCount = atoi(CPLURLGetValue(this->osURL, "resultRecordCount"));
+        const int nUserSetRecordCount =
+            atoi(CPLURLGetValue(osURL, "resultRecordCount"));
         if( nUserSetRecordCount > poFirst->GetLayer(0)->GetFeatureCount() )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
-                     "Specificied resultRecordCount=%d is greater than the maximum %d supported by the server",
-                     nUserSetRecordCount, (int)poFirst->GetLayer(0)->GetFeatureCount() );
+                     "Specificied resultRecordCount=%d is greater than "
+                     "the maximum %d supported by the server",
+                     nUserSetRecordCount,
+                     static_cast<int>(poFirst->GetLayer(0)->GetFeatureCount()));
         }
     }
-    nFirstOffset = CPLAtoGIntBig(CPLURLGetValue(this->osURL, "resultOffset"));
+    nFirstOffset = CPLAtoGIntBig(CPLURLGetValue(osURL, "resultOffset"));
     nLastOffset = nFirstOffset;
 }
 
@@ -312,10 +347,10 @@ OGRESRIFeatureServiceDataset::~OGRESRIFeatureServiceDataset()
 }
 
 /************************************************************************/
-/*                             ResetReading()                           */
+/*                           MyResetReading()                           */
 /************************************************************************/
 
-int OGRESRIFeatureServiceDataset::ResetReading()
+int OGRESRIFeatureServiceDataset::MyResetReading()
 {
     if( nLastOffset > nFirstOffset )
     {
@@ -346,9 +381,8 @@ int OGRESRIFeatureServiceDataset::LoadNextPage()
 int OGRESRIFeatureServiceDataset::LoadPage()
 {
     CPLString osNewURL = CPLURLAddKVP(osURL, "resultOffset",
-                                        CPLSPrintf(CPL_FRMT_GIB, nLastOffset));
-    OGRGeoJSONDataSource* poDS
-        = new OGRGeoJSONDataSource();
+                                      CPLSPrintf(CPL_FRMT_GIB, nLastOffset));
+    OGRGeoJSONDataSource* poDS = new OGRGeoJSONDataSource();
     GDALOpenInfo oOpenInfo(osNewURL, GA_ReadOnly);
     if( !poDS->Open( &oOpenInfo, GeoJSONGetSourceType( &oOpenInfo ) ) ||
         poDS->GetLayerCount() == 0 )
@@ -367,7 +401,7 @@ int OGRESRIFeatureServiceDataset::LoadPage()
 /************************************************************************/
 
 static int OGRGeoJSONDriverIdentifyInternal( GDALOpenInfo* poOpenInfo,
-                                     GeoJSONSourceType& nSrcType )
+                                             GeoJSONSourceType& nSrcType )
 {
 /* -------------------------------------------------------------------- */
 /*      Determine type of data source: text file (.geojson, .json),     */
@@ -402,8 +436,7 @@ static GDALDataset* OGRGeoJSONDriverOpen( GDALOpenInfo* poOpenInfo )
     if( OGRGeoJSONDriverIdentifyInternal(poOpenInfo, nSrcType) == FALSE )
         return NULL;
 
-    OGRGeoJSONDataSource* poDS
-        = new OGRGeoJSONDataSource();
+    OGRGeoJSONDataSource* poDS = new OGRGeoJSONDataSource();
 
 /* -------------------------------------------------------------------- */
 /*      Processing configuration options.                               */
@@ -417,8 +450,8 @@ static GDALDataset* OGRGeoJSONDriverOpen( GDALOpenInfo* poOpenInfo )
     const char* pszOpt = CPLGetConfigOption("GEOMETRY_AS_COLLECTION", NULL);
     if( NULL != pszOpt && STARTS_WITH_CI(pszOpt, "YES") )
     {
-            poDS->SetGeometryTranslation(
-                OGRGeoJSONDataSource::eGeometryAsCollection );
+        poDS->SetGeometryTranslation(
+            OGRGeoJSONDataSource::eGeometryAsCollection );
     }
 
     poDS->SetAttributesTranslation( OGRGeoJSONDataSource::eAttributesPreserve );
@@ -442,8 +475,8 @@ static GDALDataset* OGRGeoJSONDriverOpen( GDALOpenInfo* poOpenInfo )
     {
         const char* pszFSP = CSLFetchNameValue(poOpenInfo->papszOpenOptions,
                                                "FEATURE_SERVER_PAGING");
-        bool bHasResultOffset = CPLURLGetValue( poOpenInfo->pszFilename,
-                                                "resultOffset").size() > 0;
+        const bool bHasResultOffset =
+          !CPLURLGetValue(poOpenInfo->pszFilename, "resultOffset").empty();
         if( (!bHasResultOffset && (pszFSP == NULL || CPLTestBool(pszFSP))) ||
             (bHasResultOffset && pszFSP != NULL && CPLTestBool(pszFSP)) )
         {
@@ -460,10 +493,10 @@ static GDALDataset* OGRGeoJSONDriverOpen( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *OGRGeoJSONDriverCreate( const char * pszName,
-                                            CPL_UNUSED int nBands,
-                                            CPL_UNUSED int nXSize,
-                                            CPL_UNUSED int nYSize,
-                                            CPL_UNUSED GDALDataType eDT,
+                                            int /* nBands */,
+                                            int /* nXSize */,
+                                            int /* nYSize */,
+                                            GDALDataType /* eDT */,
                                             char **papszOptions )
 {
     OGRGeoJSONDataSource* poDS = new OGRGeoJSONDataSource();
@@ -528,10 +561,13 @@ void RegisterOGRGeoJSON()
     poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='WRITE_BBOX' type='boolean' description='whether to write a bbox property with the bounding box of the geometries at the feature and feature collection level' default='NO'/>"
-"  <Option name='COORDINATE_PRECISION' type='int' description='Number of decimal for coordinates' default='15'/>"
+"  <Option name='COORDINATE_PRECISION' type='int' description='Number of decimal for coordinates. Default is 15 for GJ2008 and 7 for RFC7946'/>"
 "  <Option name='SIGNIFICANT_FIGURES' type='int' description='Number of significant figures for floating-point values' default='17'/>"
 "  <Option name='NATIVE_DATA' type='string' description='FeatureCollection level elements.'/>"
 "  <Option name='NATIVE_MEDIA_TYPE' type='string' description='Format of NATIVE_DATA. Must be \"application/vnd.geo+json\", otherwise NATIVE_DATA will be ignored.'/>"
+"  <Option name='RFC7946' type='boolean' description='Whether to use RFC 7946 standard. Otherwise GeoJSON 2008 initial version will be used' default='NO'/>"
+"  <Option name='WRITE_NAME' type='boolean' description='Whether to write a "name" property at feature collection level with layer name' default='YES'/>"
+"  <Option name='DESCRIPTION' type='string' description='(Long) description to write in a "description" property at feature collection level'/>"
 "</LayerCreationOptionList>");
 
     poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
index 9f815de..e855943 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeojsonlayer.cpp 34334 2016-06-10 07:37:16Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONLayer class (OGR GeoJSON Driver).
@@ -27,15 +26,37 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
-#include <algorithm> // for_each, find_if
-#include <json.h> // JSON-C
+
+#include <algorithm>
+
+#if !DEBUG_JSON
+#  ifdef __clang__
+#    pragma clang diagnostic push
+#    pragma clang diagnostic ignored "-Wunknown-pragmas"
+#    pragma clang diagnostic ignored "-Wdocumentation"
+#  endif
+#endif  // !DEBUG_VERBOSE
+
+#include <json.h>
+
+#if !DEBUG_JSON
+#  ifdef __clang
+#    pragma clang diagnostic pop
+#  endif
+#endif  // !DEBUG_VERBOSE
+
 #include "ogr_geojson.h"
 
-/* Remove annoying warnings Microsoft Visual C++ */
+// Remove annoying warnings Microsoft Visual C++:
+//   'class': assignment operator could not be generated.
+//     The compiler cannot generate an assignment operator for the given
+//     class. No assignment operator was created.
 #if defined(_MSC_VER)
 #  pragma warning(disable:4512)
 #endif
 
+CPL_CVSID("$Id: ogrgeojsonlayer.cpp 35836 2016-10-20 13:57:15Z goatbar $");
+
 /************************************************************************/
 /*                       STATIC MEMBERS DEFINITION                      */
 /************************************************************************/
@@ -50,8 +71,10 @@ const OGRwkbGeometryType OGRGeoJSONLayer::DefaultGeometryType = wkbUnknown;
 OGRGeoJSONLayer::OGRGeoJSONLayer( const char* pszName,
                                   OGRSpatialReference* poSRSIn,
                                   OGRwkbGeometryType eGType,
-                                  OGRGeoJSONDataSource* poDS )
-  : OGRMemLayer( pszName, poSRSIn, eGType), poDS_(poDS), bUpdated_(false),
+                                  OGRGeoJSONDataSource* poDS ) :
+    OGRMemLayer( pszName, poSRSIn, eGType),
+    poDS_(poDS),
+    bUpdated_(false),
     bOriginalIdModified_(false)
 {
     SetAdvertizeUTF8(true);
@@ -62,9 +85,7 @@ OGRGeoJSONLayer::OGRGeoJSONLayer( const char* pszName,
 /*                          ~OGRGeoJSONLayer                            */
 /************************************************************************/
 
-OGRGeoJSONLayer::~OGRGeoJSONLayer()
-{
-}
+OGRGeoJSONLayer::~OGRGeoJSONLayer() {}
 
 /************************************************************************/
 /*                           GetFIDColumn                               */
@@ -72,7 +93,7 @@ OGRGeoJSONLayer::~OGRGeoJSONLayer()
 
 const char* OGRGeoJSONLayer::GetFIDColumn()
 {
-	return sFIDColumn_.c_str();
+    return sFIDColumn_.c_str();
 }
 
 /************************************************************************/
@@ -81,7 +102,7 @@ const char* OGRGeoJSONLayer::GetFIDColumn()
 
 void OGRGeoJSONLayer::SetFIDColumn( const char* pszFIDColumn )
 {
-	sFIDColumn_ = pszFIDColumn;
+    sFIDColumn_ = pszFIDColumn;
 }
 
 /************************************************************************/
@@ -113,37 +134,39 @@ OGRErr OGRGeoJSONLayer::SyncToDisk()
 void OGRGeoJSONLayer::AddFeature( OGRFeature* poFeature )
 {
     GIntBig nFID = poFeature->GetFID();
-    
+
     // Detect potential FID duplicates and make sure they are eventually
-    // unique
+    // unique.
     if( -1 == nFID )
     {
         nFID = GetFeatureCount(FALSE);
-        OGRFeature* poTryFeature;
+        OGRFeature* poTryFeature = NULL;
         while( (poTryFeature = GetFeature(nFID) ) != NULL )
         {
-            nFID ++;
+            nFID++;
             delete poTryFeature;
         }
     }
     else
     {
-        OGRFeature* poTryFeature;
+        OGRFeature* poTryFeature = NULL;
         if( (poTryFeature = GetFeature(nFID) ) != NULL )
         {
             if( !bOriginalIdModified_ )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "Several features with id = " CPL_FRMT_GIB " have been found. "
-                         "Altering it to be unique. This warning will not be emitted for this layer",
-                         nFID);
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Several features with id = " CPL_FRMT_GIB " have been "
+                    "found. Altering it to be unique. This warning will not "
+                    "be emitted for this layer",
+                    nFID );
                 bOriginalIdModified_ = true;
             }
             delete poTryFeature;
             nFID = GetFeatureCount(FALSE);
             while( (poTryFeature = GetFeature(nFID) ) != NULL )
             {
-                nFID ++;
+                nFID++;
                 delete poTryFeature;
             }
         }
@@ -153,7 +176,7 @@ void OGRGeoJSONLayer::AddFeature( OGRFeature* poFeature )
     if( !CPL_INT64_FITS_ON_INT32(nFID) )
         SetMetadataItem(OLMD_FID64, "YES");
 
-    SetUpdatable( true ); /* temporary toggle on updatable flag */
+    SetUpdatable( true );  // Temporary toggle on updatable flag.
     CPL_IGNORE_RET_VAL(OGRMemLayer::SetFeature(poFeature));
     SetUpdatable( poDS_->IsUpdatable() );
     SetUpdated( false );
@@ -165,13 +188,13 @@ void OGRGeoJSONLayer::AddFeature( OGRFeature* poFeature )
 
 void OGRGeoJSONLayer::DetectGeometryType()
 {
-    if (GetLayerDefn()->GetGeomType() != wkbUnknown)
+    if( GetLayerDefn()->GetGeomType() != wkbUnknown )
         return;
 
     ResetReading();
     bool bFirstGeometry = true;
     OGRwkbGeometryType eLayerGeomType = wkbUnknown;
-    OGRFeature* poFeature;
+    OGRFeature* poFeature = NULL;
     while( (poFeature = GetNextFeature()) != NULL )
     {
         OGRGeometry* poGeometry = poFeature->GetGeometryRef();
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
index 2aa1f62..6941e9d 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.cpp 34362 2016-06-17 11:45:09Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONReader class (OGR GeoJSON Driver).
@@ -27,12 +26,15 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
 #include "ogrgeojsonreader.h"
 #include "ogrgeojsonutils.h"
 #include "ogr_geojson.h"
 #include <json.h> // JSON-C
 #include <ogr_api.h>
 
+CPL_CVSID("$Id: ogrgeojsonreader.cpp 37858 2017-03-29 10:19:55Z rouault $");
+
 /************************************************************************/
 /*                           OGRGeoJSONReader                           */
 /************************************************************************/
@@ -51,7 +53,7 @@ OGRGeoJSONReader::OGRGeoJSONReader() :
     bFoundTypeFeature(false),
     bIsGeocouchSpatiallistFormat(false),
     bFoundFeatureId(false)
-{ }
+{}
 
 /************************************************************************/
 /*                          ~OGRGeoJSONReader                           */
@@ -75,7 +77,7 @@ OGRErr OGRGeoJSONReader::Parse( const char* pszText )
 {
     if( NULL != pszText )
     {
-        /* Skip UTF-8 BOM (#5630) */
+        // Skip UTF-8 BOM (#5630).
         const GByte* pabyData = (const GByte*)pszText;
         if( pabyData[0] == 0xEF && pabyData[1] == 0xBB && pabyData[2] == 0xBF )
         {
@@ -83,9 +85,8 @@ OGRErr OGRGeoJSONReader::Parse( const char* pszText )
             pszText += 3;
         }
 
-        /* JSON tree is shared for while lifetime of the reader object
-         * and will be released in the destructor.
-         */
+        // JSON tree is shared for while lifetime of the reader object
+        // and will be released in the destructor.
         if( !OGRJSonParse(pszText, &poGJObject_) )
             return OGRERR_CORRUPT_DATA;
     }
@@ -106,7 +107,7 @@ void OGRGeoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
         return;
     }
 
-    ReadLayer(poDS, OGRGeoJSONLayer::DefaultName, poGJObject_);
+    ReadLayer(poDS, NULL, poGJObject_);
 }
 
 /************************************************************************/
@@ -120,9 +121,9 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
     GeoJSONObject::Type objType = OGRGeoJSONGetType( poObj );
     if( objType == GeoJSONObject::eUnknown )
     {
-        /* Check if the object contains key:value pairs where value */
-        /* is a standard GeoJSON object. In which case, use key as the layer */
-        /* name */
+        // Check if the object contains key:value pairs where value
+        // is a standard GeoJSON object. In which case, use key as the layer
+        // name.
         if( json_type_object == json_object_get_type( poObj ) )
         {
             json_object_iter it;
@@ -137,16 +138,16 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
             }
         }
 
-        /*CPLError( CE_Failure, CPLE_AppDefined,
-            "Unrecognized GeoJSON structure." );*/
+        // CPLError(CE_Failure, CPLE_AppDefined,
+        //          "Unrecognized GeoJSON structure.");
 
         return;
     }
 
-    OGRSpatialReference* poSRS
-        = OGRGeoJSONReadSpatialReference( poObj );
-    if (poSRS == NULL ) {
-        // If there is none defined, we use 4326
+    OGRSpatialReference* poSRS = OGRGeoJSONReadSpatialReference( poObj );
+    if( poSRS == NULL )
+    {
+        // If there is none defined, we use 4326.
         poSRS = new OGRSpatialReference();
         if( OGRERR_NONE != poSRS->importFromEPSG( 4326 ) )
         {
@@ -157,21 +158,59 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
 
     CPLErrorReset();
 
-    OGRGeoJSONLayer* poLayer = new OGRGeoJSONLayer( pszName, poSRS,
-                                    OGRGeoJSONLayer::DefaultGeometryType,
-                                    poDS );
+    // Figure out layer name
+    if( pszName == NULL )
+    {
+        if( GeoJSONObject::eFeatureCollection == objType )
+        {
+            json_object* poName = CPL_json_object_object_get(poObj, "name");
+            if( poName != NULL &&
+                json_object_get_type(poName) == json_type_string )
+            {
+                pszName = json_object_get_string(poName);
+            }
+        }
+        if( pszName == NULL )
+        {
+            const char* pszDesc = poDS->GetDescription();
+            if( strchr(pszDesc, '?') == NULL &&
+                strchr(pszDesc, '{') == NULL )
+            {
+                pszName = CPLGetBasename(pszDesc);
+            }
+        }
+        if( pszName == NULL )
+            pszName = OGRGeoJSONLayer::DefaultName;
+    }
+
+    OGRGeoJSONLayer* poLayer =
+      new OGRGeoJSONLayer( pszName, poSRS,
+                           OGRGeoJSONLayer::DefaultGeometryType,
+                           poDS );
     if( poSRS != NULL )
         poSRS->Release();
 
     if( !GenerateLayerDefn(poLayer, poObj) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-            "Layer schema generation failed." );
+                  "Layer schema generation failed." );
 
         delete poLayer;
         return;
     }
 
+    if( GeoJSONObject::eFeatureCollection == objType )
+    {
+        json_object* poDescription =
+                        CPL_json_object_object_get(poObj, "description");
+        if( poDescription != NULL &&
+            json_object_get_type(poDescription) == json_type_string )
+        {
+            poLayer->SetMetadataItem("DESCRIPTION",
+                                     json_object_get_string(poDescription));
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Translate single geometry-only Feature object.                  */
 /* -------------------------------------------------------------------- */
@@ -187,8 +226,7 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
         OGRGeometry* poGeometry = ReadGeometry( poObj );
         if( !AddFeature( poLayer, poGeometry ) )
         {
-            CPLDebug( "GeoJSON",
-                      "Translation of single geometry failed." );
+            CPLDebug( "GeoJSON", "Translation of single geometry failed." );
             delete poLayer;
             return;
         }
@@ -201,8 +239,7 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
         OGRFeature* poFeature = ReadFeature( poLayer, poObj );
         if( !AddFeature( poLayer, poFeature ) )
         {
-            CPLDebug( "GeoJSON",
-                      "Translation of single feature failed." );
+            CPLDebug( "GeoJSON", "Translation of single feature failed." );
 
             delete poLayer;
             return;
@@ -226,7 +263,8 @@ void OGRGeoJSONReader::ReadLayer( OGRGeoJSONDataSource* poDS,
 /*                    OGRGeoJSONReadSpatialReference                    */
 /************************************************************************/
 
-OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
+OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj )
+{
 
 /* -------------------------------------------------------------------- */
 /*      Read spatial reference definition.                              */
@@ -236,21 +274,24 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
     json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "crs" );
     if( NULL != poObjSrs )
     {
-        json_object* poObjSrsType = OGRGeoJSONFindMemberByName( poObjSrs, "type" );
-        if (poObjSrsType == NULL)
+        json_object* poObjSrsType =
+            OGRGeoJSONFindMemberByName( poObjSrs, "type" );
+        if( poObjSrsType == NULL )
             return NULL;
 
         const char* pszSrsType = json_object_get_string( poObjSrsType );
 
-        // TODO: Add URL and URN types support
+        // TODO: Add URL and URN types support.
         if( STARTS_WITH_CI(pszSrsType, "NAME") )
         {
-            json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
-            if (poObjSrsProps == NULL)
+            json_object* poObjSrsProps =
+                OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
+            if( poObjSrsProps == NULL )
                 return NULL;
 
-            json_object* poNameURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "name" );
-            if (poNameURL == NULL)
+            json_object* poNameURL =
+                OGRGeoJSONFindMemberByName( poObjSrsProps, "name" );
+            if( poNameURL == NULL )
                 return NULL;
 
             const char* pszName = json_object_get_string( poNameURL );
@@ -265,12 +306,14 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
 
         if( STARTS_WITH_CI(pszSrsType, "EPSG") )
         {
-            json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
-            if (poObjSrsProps == NULL)
+            json_object* poObjSrsProps =
+                OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
+            if( poObjSrsProps == NULL )
                 return NULL;
 
-            json_object* poObjCode = OGRGeoJSONFindMemberByName( poObjSrsProps, "code" );
-            if (poObjCode == NULL)
+            json_object* poObjCode =
+                OGRGeoJSONFindMemberByName( poObjSrsProps, "code" );
+            if( poObjCode == NULL )
                 return NULL;
 
             int nEPSG = json_object_get_int( poObjCode );
@@ -283,18 +326,22 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
             }
         }
 
-        if( STARTS_WITH_CI(pszSrsType, "URL") || STARTS_WITH_CI(pszSrsType, "LINK")  )
+        if( STARTS_WITH_CI(pszSrsType, "URL") ||
+            STARTS_WITH_CI(pszSrsType, "LINK")  )
         {
-            json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
-            if (poObjSrsProps == NULL)
+            json_object* poObjSrsProps =
+                OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
+            if( poObjSrsProps == NULL )
                 return NULL;
 
-            json_object* poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "url" );
+            json_object* poObjURL =
+                OGRGeoJSONFindMemberByName( poObjSrsProps, "url" );
 
-            if (NULL == poObjURL) {
+            if( NULL == poObjURL )
+            {
                 poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "href" );
             }
-            if (poObjURL == NULL)
+            if( poObjURL == NULL )
                 return NULL;
 
             const char* pszURL = json_object_get_string( poObjURL );
@@ -309,16 +356,19 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
 
         if( EQUAL( pszSrsType, "OGC" ) )
         {
-            json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
-            if (poObjSrsProps == NULL)
+            json_object* poObjSrsProps =
+                OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
+            if( poObjSrsProps == NULL )
                 return NULL;
 
-            json_object* poObjURN = OGRGeoJSONFindMemberByName( poObjSrsProps, "urn" );
-            if (poObjURN == NULL)
+            json_object* poObjURN =
+                OGRGeoJSONFindMemberByName( poObjSrsProps, "urn" );
+            if( poObjURN == NULL )
                 return NULL;
 
             poSRS = new OGRSpatialReference();
-            if( OGRERR_NONE != poSRS->importFromURN( json_object_get_string(poObjURN) ) )
+            if( OGRERR_NONE !=
+                poSRS->importFromURN( json_object_get_string(poObjURN) ) )
             {
                 delete poSRS;
                 poSRS = NULL;
@@ -326,9 +376,10 @@ OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
         }
     }
 
-    /* Strip AXIS, since geojson has (easting, northing) / (longitude, latitude) order. */
-    /* According to http://www.geojson.org/geojson-spec.html#id2 : "Point coordinates are in x, y order */
-    /* (easting, northing for projected coordinates, longitude, latitude for geographic coordinates)" */
+    // Strip AXIS, since geojson has (easting, northing) / (longitude, latitude)
+    // order.  According to http://www.geojson.org/geojson-spec.html#id2 :
+    // "Point coordinates are in x, y order (easting, northing for projected
+    // coordinates, longitude, latitude for geographic coordinates)".
     if( poSRS != NULL )
     {
         OGR_SRSNode *poGEOGCS = poSRS->GetAttrNode( "GEOGCS" );
@@ -361,7 +412,8 @@ void OGRGeoJSONReader::SetSkipAttributes( bool bSkip )
 /*                         SetFlattenNestedAttributes                   */
 /************************************************************************/
 
-void OGRGeoJSONReader::SetFlattenNestedAttributes( bool bFlatten, char chSeparator )
+void OGRGeoJSONReader::SetFlattenNestedAttributes( bool bFlatten,
+                                                   char chSeparator )
 {
     bFlattenNestedAttributes_ = bFlatten;
     chNestedAttributeSeparator_ = chSeparator;
@@ -389,7 +441,8 @@ void OGRGeoJSONReader::SetArrayAsString( bool bArrayAsString )
 /*                         GenerateLayerDefn()                          */
 /************************************************************************/
 
-bool OGRGeoJSONReader::GenerateLayerDefn( OGRGeoJSONLayer* poLayer, json_object* poGJObject )
+bool OGRGeoJSONReader::GenerateLayerDefn( OGRGeoJSONLayer* poLayer,
+                                          json_object* poGJObject )
 {
     CPLAssert( NULL != poGJObject );
     CPLAssert( NULL != poLayer->GetLayerDefn() );
@@ -418,8 +471,8 @@ bool OGRGeoJSONReader::GenerateLayerDefn( OGRGeoJSONLayer* poLayer, json_object*
             const int nFeatures = json_object_array_length( poObjFeatures );
             for( int i = 0; i < nFeatures; ++i )
             {
-                json_object* poObjFeature
-                    = json_object_array_get_idx( poObjFeatures, i );
+                json_object* poObjFeature =
+                    json_object_array_get_idx( poObjFeatures, i );
                 if( !GenerateFeatureDefn( poLayer, poObjFeature ) )
                 {
                     CPLDebug( "GeoJSON", "Create feature schema failure." );
@@ -444,13 +497,15 @@ bool OGRGeoJSONReader::GenerateLayerDefn( OGRGeoJSONLayer* poLayer, json_object*
 
     if( !bFoundFeatureId )
     {
-        int idx = poLayerDefn->GetFieldIndex( "id" );
+        const int idx = poLayerDefn->GetFieldIndex( "id" );
         if( idx >= 0 )
         {
             OGRFieldDefn* poFDefn = poLayerDefn->GetFieldDefn(idx);
-            if( poFDefn->GetType() == OFTInteger || poFDefn->GetType() == OFTInteger64 )
+            if( poFDefn->GetType() == OFTInteger ||
+                poFDefn->GetType() == OFTInteger64 )
             {
-                poLayer->SetFIDColumn( poLayerDefn->GetFieldDefn(idx)->GetNameRef() );
+                poLayer->SetFIDColumn(
+                    poLayerDefn->GetFieldDefn(idx)->GetNameRef() );
             }
         }
     }
@@ -462,13 +517,14 @@ bool OGRGeoJSONReader::GenerateLayerDefn( OGRGeoJSONLayer* poLayer, json_object*
 /*                     OGRGeoJSONReaderAddNewField()                    */
 /************************************************************************/
 
-void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
-                                      const char* pszKey,
-                                      json_object* poVal,
-                                      bool bFlattenNestedAttributes,
-                                      char chNestedAttributeSeparator,
-                                      bool bArrayAsString,
-                                      std::set<int>& aoSetUndeterminedTypeFields)
+void OGRGeoJSONReaderAddOrUpdateField(
+    OGRFeatureDefn* poDefn,
+    const char* pszKey,
+    json_object* poVal,
+    bool bFlattenNestedAttributes,
+    char chNestedAttributeSeparator,
+    bool bArrayAsString,
+    std::set<int>& aoSetUndeterminedTypeFields )
 {
     if( bFlattenNestedAttributes &&
         poVal != NULL && json_object_get_type(poVal) == json_type_object )
@@ -479,21 +535,25 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
         it.entry = NULL;
         json_object_object_foreachC( poVal, it )
         {
-            char szSeparator[2];
-            szSeparator[0] = chNestedAttributeSeparator;
-            szSeparator[1] = 0;
+            char szSeparator[2] = { chNestedAttributeSeparator, '\0' };
+
             CPLString osAttrName(CPLSPrintf("%s%s%s", pszKey, szSeparator,
                                             it.key));
-            if( it.val != NULL && json_object_get_type(it.val) == json_type_object )
+            if( it.val != NULL &&
+                json_object_get_type(it.val) == json_type_object )
             {
                 OGRGeoJSONReaderAddOrUpdateField(poDefn, osAttrName, it.val,
-                                                 true, chNestedAttributeSeparator,
-                                                 bArrayAsString, aoSetUndeterminedTypeFields);
+                                                 true,
+                                                 chNestedAttributeSeparator,
+                                                 bArrayAsString,
+                                                 aoSetUndeterminedTypeFields);
             }
             else
             {
-                OGRGeoJSONReaderAddOrUpdateField(poDefn, osAttrName, it.val, false, 0,
-                                                 bArrayAsString, aoSetUndeterminedTypeFields);
+                OGRGeoJSONReaderAddOrUpdateField(poDefn, osAttrName, it.val,
+                                                 false, 0,
+                                                 bArrayAsString,
+                                                 aoSetUndeterminedTypeFields);
             }
         }
         return;
@@ -503,7 +563,8 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
     if( nIndex < 0 )
     {
         OGRFieldSubType eSubType;
-        OGRFieldType eType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
+        const OGRFieldType eType =
+            GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
         OGRFieldDefn fldDefn( pszKey, eType );
         fldDefn.SetSubType(eSubType);
         if( eSubType == OFSTBoolean )
@@ -516,14 +577,17 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
         if( poVal == NULL )
             aoSetUndeterminedTypeFields.insert( poDefn->GetFieldCount() - 1 );
     }
-    else if ( poVal ) // If there is a null value: do not update field definition
+    else if( poVal )
     {
+        // If there is a null value: do not update field definition.
         OGRFieldDefn* poFDefn = poDefn->GetFieldDefn(nIndex);
-        OGRFieldType eType = poFDefn->GetType();
-        if( aoSetUndeterminedTypeFields.find(nIndex) != aoSetUndeterminedTypeFields.end() )
+        const OGRFieldType eType = poFDefn->GetType();
+        if( aoSetUndeterminedTypeFields.find(nIndex) !=
+            aoSetUndeterminedTypeFields.end() )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
+            const OGRFieldType eNewType =
+                GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             poFDefn->SetSubType(OFSTNone);
             poFDefn->SetType(eNewType);
             if( eSubType == OFSTBoolean )
@@ -538,13 +602,16 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
         else if( eType == OFTInteger )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
+            const OGRFieldType eNewType =
+                GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             if( eNewType == OFTInteger &&
-                poFDefn->GetSubType() == OFSTBoolean && eSubType != OFSTBoolean )
+                poFDefn->GetSubType() == OFSTBoolean &&
+                eSubType != OFSTBoolean )
             {
                 poFDefn->SetSubType(OFSTNone);
             }
-            else if( eNewType == OFTInteger64 || eNewType == OFTReal || eNewType == OFTString )
+            else if( eNewType == OFTInteger64 || eNewType == OFTReal ||
+                     eNewType == OFTString )
             {
                 poFDefn->SetType(eNewType);
                 poFDefn->SetSubType(OFSTNone);
@@ -553,7 +620,8 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
         else if( eType == OFTInteger64 )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
+            const OGRFieldType eNewType =
+                GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             if( eNewType == OFTReal || eNewType == OFTString )
             {
                 poFDefn->SetType(eNewType);
@@ -563,21 +631,25 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
         else if( eType == OFTIntegerList || eType == OFTInteger64List )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
-            if( eNewType == OFTInteger64List || eNewType == OFTRealList || eNewType == OFTStringList )
+            OGRFieldType eNewType =
+                GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
+            if( eNewType == OFTInteger64List || eNewType == OFTRealList ||
+                eNewType == OFTStringList )
                 poFDefn->SetType(eNewType);
         }
         else if( eType == OFTRealList )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
+            const OGRFieldType eNewType =
+                GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             if( eNewType == OFTStringList )
                 poFDefn->SetType(eNewType);
         }
         else if( eType == OFTDate || eType == OFTTime || eType == OFTDateTime )
         {
             OGRFieldSubType eSubType;
-            OGRFieldType eNewType = GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
+            OGRFieldType eNewType =
+                GeoJSONPropertyToFieldType( poVal, eSubType, bArrayAsString );
             if( eNewType == OFTString )
                 eNewType = GeoJSONStringPropertyToFieldType( poVal );
             if( eType != eNewType )
@@ -598,7 +670,8 @@ void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
 /************************************************************************/
 /*                        GenerateFeatureDefn()                         */
 /************************************************************************/
-bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_object* poObj )
+bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer,
+                                            json_object* poObj )
 {
     OGRFeatureDefn* poDefn = poLayer->GetLayerDefn();
     CPLAssert( NULL != poDefn );
@@ -611,7 +684,7 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
     json_object* poObjId = OGRGeoJSONFindMemberByName( poObj, "id" );
     if( poObjId )
     {
-        int nIdx = poDefn->GetFieldIndex( "id" );
+        const int nIdx = poDefn->GetFieldIndex( "id" );
         if( nIdx < 0 )
         {
             if( json_object_get_type(poObjId) == json_type_int )
@@ -620,7 +693,7 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
                 // as OGRMemLayer doesn't support negative FID. And we would
                 // have an ambiguity with -1 that can mean OGRNullFID
                 // so in that case create a regular attribute and let OGR
-                // attribute sequential OGR FIDs
+                // attribute sequential OGR FIDs.
                 if( json_object_get_int64(poObjId) < 0 )
                 {
                     bFoundFeatureId = false;
@@ -633,19 +706,21 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
             if( !bFoundFeatureId )
             {
                 // If there's a top-level id of type string or negative int,
-                // and no properties.id, then declare a id field
+                // and no properties.id, then declare a id field.
                 bool bHasRegularIdProp = false;
                 if( NULL != poObjProps &&
                     json_object_get_type(poObjProps) == json_type_object )
                 {
-                    bHasRegularIdProp = (json_object_object_get(poObjProps, "id") != NULL);
+                    bHasRegularIdProp =
+                        CPL_json_object_object_get(poObjProps, "id") != NULL;
                 }
                 if( !bHasRegularIdProp )
                 {
                     OGRFieldType eType = OFTString;
                     if( json_object_get_type(poObjId) == json_type_int )
                     {
-                        if( CPL_INT64_FITS_ON_INT32( json_object_get_int64(poObjId) ) )
+                        if( CPL_INT64_FITS_ON_INT32(
+                                json_object_get_int64(poObjId) ) )
                             eType = OFTInteger;
                         else
                             eType = OFTInteger64;
@@ -674,9 +749,9 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
     if( NULL != poObjProps &&
         json_object_get_type(poObjProps) == json_type_object )
     {
-        if (bIsGeocouchSpatiallistFormat)
+        if( bIsGeocouchSpatiallistFormat )
         {
-            poObjProps = json_object_object_get(poObjProps, "properties");
+            poObjProps = CPL_json_object_object_get(poObjProps, "properties");
             if( NULL == poObjProps ||
                 json_object_get_type(poObjProps) != json_type_object )
             {
@@ -693,30 +768,41 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
             int nFldIndex = poDefn->GetFieldIndex( it.key );
             if( -1 == nFldIndex )
             {
-                /* Detect the special kind of GeoJSON output by a spatiallist of GeoCouch */
-                /* such as http://gd.iriscouch.com/cphosm/_design/geo/_rewrite/data?bbox=12.53%2C55.73%2C12.54%2C55.73 */
-                if (strcmp(it.key, "_id") == 0)
+                // Detect the special kind of GeoJSON output by a spatiallist of
+                // GeoCouch such as:
+                // http://gd.iriscouch.com/cphosm/_design/geo/_rewrite/data?bbox=12.53%2C55.73%2C12.54%2C55.73
+                if( strcmp(it.key, "_id") == 0 )
+                {
                     bFoundId = true;
-                else if (bFoundId && strcmp(it.key, "_rev") == 0)
+                }
+                else if( bFoundId && strcmp(it.key, "_rev") == 0 )
+                {
                     bFoundRev = true;
-                else if (bFoundRev && strcmp(it.key, "type") == 0 &&
-                         it.val != NULL && json_object_get_type(it.val) == json_type_string &&
-                         strcmp(json_object_get_string(it.val), "Feature") == 0)
+                }
+                else if( bFoundRev && strcmp(it.key, "type") == 0 &&
+                         it.val != NULL &&
+                         json_object_get_type(it.val) == json_type_string &&
+                         strcmp(json_object_get_string(it.val),
+                                "Feature") == 0 )
+                {
                     bFoundTypeFeature = true;
-                else if (bFoundTypeFeature && strcmp(it.key, "properties") == 0 &&
-                         it.val != NULL && json_object_get_type(it.val) == json_type_object)
+                }
+                else if( bFoundTypeFeature &&
+                         strcmp(it.key, "properties") == 0 &&
+                         it.val != NULL &&
+                         json_object_get_type(it.val) == json_type_object )
                 {
-                    if (bFlattenGeocouchSpatiallistFormat < 0)
+                    if( bFlattenGeocouchSpatiallistFormat < 0 )
                         bFlattenGeocouchSpatiallistFormat = CPLTestBool(
-                            CPLGetConfigOption("GEOJSON_FLATTEN_GEOCOUCH", "TRUE"));
-                    if (bFlattenGeocouchSpatiallistFormat)
+                            CPLGetConfigOption("GEOJSON_FLATTEN_GEOCOUCH",
+                                               "TRUE"));
+                    if( bFlattenGeocouchSpatiallistFormat )
                     {
                         poDefn->DeleteFieldDefn(poDefn->GetFieldIndex("type"));
                         bIsGeocouchSpatiallistFormat = true;
                         return GenerateFeatureDefn(poLayer, poObj);
                     }
                 }
-
             }
 
             OGRGeoJSONReaderAddOrUpdateField(poDefn, it.key, it.val,
@@ -726,7 +812,7 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
                                              aoSetUndeterminedTypeFields_);
         }
 
-        bSuccess = true; // SUCCESS
+        bSuccess = true;  // SUCCESS
     }
     else if( poObj != NULL && json_object_get_type(poObj) == json_type_object )
     {
@@ -745,16 +831,19 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
                 int nFldIndex = poDefn->GetFieldIndex( it.key );
                 if( -1 == nFldIndex )
                 {
-                    OGRFieldDefn fldDefn( it.key, OFTString );
-                    poDefn->AddFieldDefn( &fldDefn );
+                    OGRGeoJSONReaderAddOrUpdateField(poDefn, it.key, it.val,
+                                                    bFlattenNestedAttributes_,
+                                                    chNestedAttributeSeparator_,
+                                                    bArrayAsString_,
+                                                    aoSetUndeterminedTypeFields_);
                 }
             }
         }
 
         bSuccess = true; // SUCCESS
-        /*CPLError( CE_Failure, CPLE_AppDefined,
-                  "Invalid Feature object. "
-                  "Missing \'properties\' member." );*/
+        // CPLError(CE_Failure, CPLE_AppDefined,
+        //          "Invalid Feature object. "
+        //          "Missing \'properties\' member." );
     }
 
     return bSuccess;
@@ -764,12 +853,12 @@ bool OGRGeoJSONReader::GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_objec
 /*                           AddFeature                                 */
 /************************************************************************/
 
-bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRGeometry* poGeometry )
+bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer,
+                                   OGRGeometry* poGeometry )
 {
     bool bAdded = false;
 
-    // TODO: Should we check if geometry is of type of
-    //       wkbGeometryCollection ?
+    // TODO: Should we check if geometry is of type of wkbGeometryCollection?
 
     if( NULL != poGeometry )
     {
@@ -787,7 +876,8 @@ bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRGeometry* poGeom
 /*                           AddFeature                                 */
 /************************************************************************/
 
-bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRFeature* poFeature )
+bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer,
+                                   OGRFeature* poFeature )
 {
     if( poFeature == NULL )
         return false;
@@ -804,15 +894,14 @@ bool OGRGeoJSONReader::AddFeature( OGRGeoJSONLayer* poLayer, OGRFeature* poFeatu
 
 OGRGeometry* OGRGeoJSONReader::ReadGeometry( json_object* poObj )
 {
-    OGRGeometry* poGeometry
-        = OGRGeoJSONReadGeometry( poObj );
+    OGRGeometry* poGeometry = OGRGeoJSONReadGeometry( poObj );
 
 /* -------------------------------------------------------------------- */
 /*      Wrap geometry with GeometryCollection as a common denominator.  */
 /*      Sometimes a GeoJSON text may consist of objects of different    */
 /*      geometry types. Users may request wrapping all geometries with  */
 /*      OGRGeometryCollection type by using option                      */
-/*      GEOMETRY_AS_COLLECTION=NO|YES (NO is default).                 */
+/*      GEOMETRY_AS_COLLECTION=NO|YES (NO is default).                  */
 /* -------------------------------------------------------------------- */
     if( NULL != poGeometry )
     {
@@ -833,11 +922,11 @@ OGRGeometry* OGRGeoJSONReader::ReadGeometry( json_object* poObj )
 /*                OGRGeoJSONReaderSetFieldNestedAttribute()             */
 /************************************************************************/
 
-static void OGRGeoJSONReaderSetFieldNestedAttribute(OGRLayer* poLayer,
-                                                    OGRFeature* poFeature,
-                                                    const char* pszAttrPrefix,
-                                                    char chSeparator,
-                                                    json_object* poVal)
+static void OGRGeoJSONReaderSetFieldNestedAttribute( OGRLayer* poLayer,
+                                                     OGRFeature* poFeature,
+                                                     const char* pszAttrPrefix,
+                                                     char chSeparator,
+                                                     json_object* poVal )
 {
     json_object_iter it;
     it.key = NULL;
@@ -845,11 +934,9 @@ static void OGRGeoJSONReaderSetFieldNestedAttribute(OGRLayer* poLayer,
     it.entry = NULL;
     json_object_object_foreachC( poVal, it )
     {
-        char szSeparator[2];
-        szSeparator[0] = chSeparator;
-        szSeparator[1] = 0;
-        CPLString osAttrName(CPLSPrintf("%s%s%s", pszAttrPrefix, szSeparator,
-                                        it.key));
+        const char szSeparator[2] = { chSeparator, '\0' };
+        const CPLString osAttrName(
+            CPLSPrintf("%s%s%s", pszAttrPrefix, szSeparator, it.key));
         if( it.val != NULL && json_object_get_type(it.val) == json_type_object )
         {
             OGRGeoJSONReaderSetFieldNestedAttribute(poLayer, poFeature,
@@ -858,7 +945,7 @@ static void OGRGeoJSONReaderSetFieldNestedAttribute(OGRLayer* poLayer,
         }
         else
         {
-            int nField = poFeature->GetFieldIndex(osAttrName);
+            const int nField = poFeature->GetFieldIndex(osAttrName);
             OGRGeoJSONReaderSetField(poLayer, poFeature, nField,
                                      osAttrName, it.val, false, 0);
         }
@@ -869,13 +956,13 @@ static void OGRGeoJSONReaderSetFieldNestedAttribute(OGRLayer* poLayer,
 /*                   OGRGeoJSONReaderSetField()                         */
 /************************************************************************/
 
-void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
-                              OGRFeature* poFeature,
-                              int nField,
-                              const char* pszAttrPrefix,
-                              json_object* poVal,
-                              bool bFlattenNestedAttributes,
-                              char chNestedAttributeSeparator)
+void OGRGeoJSONReaderSetField( OGRLayer* poLayer,
+                               OGRFeature* poFeature,
+                               int nField,
+                               const char* pszAttrPrefix,
+                               json_object* poVal,
+                               bool bFlattenNestedAttributes,
+                               char chNestedAttributeSeparator )
 {
     if( bFlattenNestedAttributes &&
         poVal != NULL && json_object_get_type(poVal) == json_type_object )
@@ -894,13 +981,13 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
 
     if( poVal == NULL)
     {
-        /* nothing to do */
+        poFeature->SetFieldNull( nField );
     }
     else if( OFTInteger == eType )
     {
         poFeature->SetField( nField, json_object_get_int(poVal) );
 
-        /* Check if FID available and set correct value. */
+        // Check if FID available and set correct value.
         if( EQUAL( poFieldDefn->GetNameRef(), poLayer->GetFIDColumn() ) )
             poFeature->SetFID( json_object_get_int(poVal) );
     }
@@ -908,9 +995,10 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
     {
         poFeature->SetField( nField, (GIntBig)json_object_get_int64(poVal) );
 
-        /* Check if FID available and set correct value. */
+        // Check if FID available and set correct value.
         if( EQUAL( poFieldDefn->GetNameRef(), poLayer->GetFIDColumn() ) )
-            poFeature->SetFID( (GIntBig)json_object_get_int64(poVal) );
+            poFeature->SetFID(
+                static_cast<GIntBig>(json_object_get_int64(poVal)));
     }
     else if( OFTReal == eType )
     {
@@ -918,11 +1006,11 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
     }
     else if( OFTIntegerList == eType )
     {
-        if ( json_object_get_type(poVal) == json_type_array )
+        if( json_object_get_type(poVal) == json_type_array )
         {
-            int nLength = json_object_array_length(poVal);
-            int* panVal = (int*)CPLMalloc(sizeof(int) * nLength);
-            for(int i=0;i<nLength;i++)
+            const int nLength = json_object_array_length(poVal);
+            int* panVal = static_cast<int *>(CPLMalloc(sizeof(int) * nLength));
+            for( int i = 0; i < nLength; i++ )
             {
                 json_object* poRow = json_object_array_get_idx(poVal, i);
                 panVal[i] = json_object_get_int(poRow);
@@ -933,14 +1021,15 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
     }
     else if( OFTInteger64List == eType )
     {
-        if ( json_object_get_type(poVal) == json_type_array )
+        if( json_object_get_type(poVal) == json_type_array )
         {
-            int nLength = json_object_array_length(poVal);
-            GIntBig* panVal = (GIntBig*)CPLMalloc(sizeof(GIntBig) * nLength);
-            for(int i=0;i<nLength;i++)
+            const int nLength = json_object_array_length(poVal);
+            GIntBig* panVal =
+                static_cast<GIntBig *>(CPLMalloc(sizeof(GIntBig) * nLength));
+            for( int i = 0; i < nLength; i++ )
             {
                 json_object* poRow = json_object_array_get_idx(poVal, i);
-                panVal[i] = (GIntBig)json_object_get_int64(poRow);
+                panVal[i] = static_cast<GIntBig>(json_object_get_int64(poRow));
             }
             poFeature->SetField( nField, nLength, panVal );
             CPLFree(panVal);
@@ -948,11 +1037,12 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
     }
     else if( OFTRealList == eType )
     {
-        if ( json_object_get_type(poVal) == json_type_array )
+        if( json_object_get_type(poVal) == json_type_array )
         {
-            int nLength = json_object_array_length(poVal);
-            double* padfVal = (double*)CPLMalloc(sizeof(double) * nLength);
-            for(int i=0;i<nLength;i++)
+            const int nLength = json_object_array_length(poVal);
+            double* padfVal =
+                static_cast<double *>(CPLMalloc(sizeof(double) * nLength));
+            for( int i = 0; i < nLength;i++ )
             {
                 json_object* poRow = json_object_array_get_idx(poVal, i);
                 padfVal[i] = json_object_get_double(poRow);
@@ -963,16 +1053,16 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
     }
     else if( OFTStringList == eType )
     {
-        if ( json_object_get_type(poVal) == json_type_array )
+        if( json_object_get_type(poVal) == json_type_array )
         {
-            int nLength = json_object_array_length(poVal);
+            const int nLength = json_object_array_length(poVal);
             char** papszVal = (char**)CPLMalloc(sizeof(char*) * (nLength+1));
             int i = 0;
-            for( ;i<nLength;i++)
+            for( ; i < nLength; i++ )
             {
                 json_object* poRow = json_object_array_get_idx(poVal, i);
                 const char* pszVal = json_object_get_string(poRow);
-                if (pszVal == NULL)
+                if( pszVal == NULL )
                     break;
                 papszVal[i] = CPLStrdup(pszVal);
             }
@@ -991,7 +1081,8 @@ void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
 /*                           ReadFeature()                              */
 /************************************************************************/
 
-OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object* poObj )
+OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer,
+                                           json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
@@ -1009,22 +1100,24 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
 /* -------------------------------------------------------------------- */
     CPLAssert( NULL != poFeature );
 
-    json_object* poObjProps = NULL;
-    poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
+    json_object* poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
     if( !bAttributesSkip_ && NULL != poObjProps &&
         json_object_get_type(poObjProps) == json_type_object )
     {
-        if (bIsGeocouchSpatiallistFormat)
+        if( bIsGeocouchSpatiallistFormat )
         {
-            json_object* poId = json_object_object_get(poObjProps, "_id");
-            if (poId != NULL && json_object_get_type(poId) == json_type_string)
+            json_object* poId = CPL_json_object_object_get(poObjProps, "_id");
+            if( poId != NULL && json_object_get_type(poId) == json_type_string )
                 poFeature->SetField( "_id", json_object_get_string(poId) );
 
-            json_object* poRev = json_object_object_get(poObjProps, "_rev");
-            if (poRev != NULL && json_object_get_type(poRev) == json_type_string)
+            json_object* poRev = CPL_json_object_object_get(poObjProps, "_rev");
+            if( poRev != NULL &&
+                json_object_get_type(poRev) == json_type_string )
+            {
                 poFeature->SetField( "_rev", json_object_get_string(poRev) );
+            }
 
-            poObjProps = json_object_object_get(poObjProps, "properties");
+            poObjProps = CPL_json_object_object_get(poObjProps, "properties");
             if( NULL == poObjProps ||
                 json_object_get_type(poObjProps) != json_type_object )
             {
@@ -1038,8 +1131,7 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
         it.entry = NULL;
         json_object_object_foreachC( poObjProps, it )
         {
-            const int nField
-                = poFeature->GetFieldIndex(it.key);
+            const int nField = poFeature->GetFieldIndex(it.key);
             OGRGeoJSONReaderSetField(poLayer, poFeature, nField, it.key, it.val,
                                      bFlattenNestedAttributes_,
                                      chNestedAttributeSeparator_);
@@ -1054,10 +1146,13 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
         it.entry = NULL;
         json_object_object_foreachC( poObj, it )
         {
-            int nFldIndex = poFeature->GetFieldIndex(it.key);
+            const int nFldIndex = poFeature->GetFieldIndex(it.key);
             if( nFldIndex >= 0 )
             {
-                poFeature->SetField(nFldIndex, json_object_get_string(it.val) );
+                if( it.val )
+                    poFeature->SetField(nFldIndex, json_object_get_string(it.val) );
+                else
+                    poFeature->SetFieldNull(nFldIndex );
             }
         }
     }
@@ -1070,7 +1165,8 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
     json_object* poObjId = OGRGeoJSONFindMemberByName( poObj, "id" );
     if( NULL != poObjId && bFoundFeatureId )
     {
-        poFeature->SetFID( (GIntBig)json_object_get_int64( poObjId ) );
+      poFeature->SetFID(
+          static_cast<GIntBig>(json_object_get_int64( poObjId )) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1078,7 +1174,7 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
 /* -------------------------------------------------------------------- */
     else if( NULL != poObjId )
     {
-        int nIdx = poLayer->GetLayerDefn()->GetFieldIndex( "id" );
+        const int nIdx = poLayer->GetLayerDefn()->GetFieldIndex( "id" );
         if( nIdx >= 0 && !poFeature->IsFieldSet(nIdx) )
         {
             poFeature->SetField(nIdx, json_object_get_string(poObjId));
@@ -1089,19 +1185,18 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
 /*      Translate geometry sub-object of GeoJSON Feature.               */
 /* -------------------------------------------------------------------- */
     json_object* poObjGeom = NULL;
-
     json_object* poTmp = poObj;
-
     json_object_iter it;
     it.key = NULL;
     it.val = NULL;
     it.entry = NULL;
     json_object_object_foreachC(poTmp, it)
     {
-        if( EQUAL( it.key, "geometry" ) ) {
-            if (it.val != NULL)
+        if( EQUAL( it.key, "geometry" ) )
+        {
+            if( it.val != NULL )
                 poObjGeom = it.val;
-            // we're done.  They had 'geometry':null
+            // Done.  They had 'geometry':null.
             else
                 return poFeature;
         }
@@ -1124,7 +1219,9 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
         if( !bWarned )
         {
             bWarned = true;
-            CPLDebug("GeoJSON", "Non conformant Feature object. Missing \'geometry\' member." );
+            CPLDebug(
+                "GeoJSON",
+                "Non conformant Feature object. Missing \'geometry\' member.");
         }
     }
 
@@ -1136,10 +1233,10 @@ OGRFeature* OGRGeoJSONReader::ReadFeature( OGRGeoJSONLayer* poLayer, json_object
 /************************************************************************/
 
 void
-OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object* poObj )
+OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer,
+                                         json_object* poObj )
 {
-    json_object* poObjFeatures
-        = OGRGeoJSONFindMemberByName( poObj, "features" );
+    json_object* poObjFeatures = OGRGeoJSONFindMemberByName(poObj, "features");
     if( NULL == poObjFeatures )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1150,20 +1247,17 @@ OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object*
 
     if( json_type_array == json_object_get_type( poObjFeatures ) )
     {
-        /* bool bAdded = false; */
         const int nFeatures = json_object_array_length( poObjFeatures );
         for( int i = 0; i < nFeatures; ++i )
         {
             json_object* poObjFeature
                 = json_object_array_get_idx( poObjFeatures, i );
             OGRFeature* poFeature = ReadFeature( poLayer, poObjFeature );
-            /* bAdded = */ AddFeature( poLayer, poFeature );
-            //CPLAssert( bAdded );
+            AddFeature( poLayer, poFeature );
         }
-        //CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
     }
 
-    // Collect top objects except 'type' and the 'features' array
+    // Collect top objects except 'type' and the 'features' array.
     if( bStoreNativeData_ )
     {
         json_object_iter it;
@@ -1178,7 +1272,7 @@ OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object*
             {
                 continue;
             }
-            if( osNativeData.size() == 0 )
+            if( osNativeData.empty() )
                 osNativeData = "{ ";
             else
                 osNativeData += ", ";
@@ -1188,7 +1282,7 @@ OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object*
             osNativeData += ": ";
             osNativeData += json_object_to_json_string(it.val);
         }
-        if( osNativeData.size() == 0 )
+        if( osNativeData.empty() )
         {
             osNativeData = "{ ";
         }
@@ -1196,10 +1290,11 @@ OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object*
 
         osNativeData = "NATIVE_DATA=" + osNativeData;
 
-        char* apszMetadata[3];
-        apszMetadata[0] = (char*) osNativeData.c_str();
-        apszMetadata[1] = (char*) "NATIVE_MEDIA_TYPE=application/vnd.geo+json";
-        apszMetadata[2] = NULL;
+        char *apszMetadata[3] = {
+            const_cast<char *>(osNativeData.c_str()),
+            const_cast<char *>("NATIVE_MEDIA_TYPE=application/vnd.geo+json"),
+            NULL
+        };
 
         poLayer->SetMetadata( apszMetadata, "NATIVE_DATA" );
     }
@@ -1209,7 +1304,7 @@ OGRGeoJSONReader::ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object*
 /*                           OGRGeoJSONFindMemberByName                 */
 /************************************************************************/
 
-json_object* OGRGeoJSONFindMemberByName( json_object* poObj,
+lh_entry* OGRGeoJSONFindMemberEntryByName( json_object* poObj,
                                          const char* pszName )
 {
     if( NULL == pszName || NULL == poObj)
@@ -1224,20 +1319,29 @@ json_object* OGRGeoJSONFindMemberByName( json_object* poObj,
     if( NULL != json_object_get_object(poTmp) &&
         NULL != json_object_get_object(poTmp)->head )
     {
-        for( it.entry = json_object_get_object(poTmp)->head;
-             ( it.entry ?
-               ( it.key = (char*)it.entry->k,
-                 it.val = (json_object*)it.entry->v, 1) : 0);
-             it.entry = it.entry->next)
+        it.entry = json_object_get_object(poTmp)->head;
+        while( it.entry != NULL )
         {
+            it.key = (char*)it.entry->k;
+            it.val = (json_object*)it.entry->v;
             if( EQUAL( it.key, pszName ) )
-                return it.val;
+                return it.entry;
+            it.entry = it.entry->next;
         }
     }
 
     return NULL;
 }
 
+json_object* OGRGeoJSONFindMemberByName( json_object* poObj,
+                                         const char* pszName )
+{
+    lh_entry* entry = OGRGeoJSONFindMemberEntryByName( poObj, pszName );
+    if ( NULL == entry )
+        return NULL;
+    return (json_object*)entry->v;
+}
+
 /************************************************************************/
 /*                           OGRGeoJSONGetType                          */
 /************************************************************************/
@@ -1247,8 +1351,7 @@ GeoJSONObject::Type OGRGeoJSONGetType( json_object* poObj )
     if( NULL == poObj )
         return GeoJSONObject::eUnknown;
 
-    json_object* poObjType
-        = OGRGeoJSONFindMemberByName( poObj, "type" );
+    json_object* poObjType = OGRGeoJSONFindMemberByName( poObj, "type" );
     if( NULL == poObjType )
         return GeoJSONObject::eUnknown;
 
@@ -1304,16 +1407,25 @@ OGRGeometry* OGRGeoJSONReadGeometry( json_object* poObj )
                   "Unsupported geometry type detected. "
                   "Feature gets NULL geometry assigned." );
     }
-    // If we have a crs object in the current object, let's try and
-    // set it too.
-
-    json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "crs" );
-    if (poGeometry != NULL && poObjSrs != NULL) {
-        OGRSpatialReference* poSRS = OGRGeoJSONReadSpatialReference(poObj);
-        if (poSRS != NULL) {
-            poGeometry->assignSpatialReference(poSRS);
-            poSRS->Release();
+    // If we have a crs object in the current object, let's try and set it too.
+    if( poGeometry != NULL )
+    {
+        lh_entry* entry = OGRGeoJSONFindMemberEntryByName( poObj, "crs" );
+        if (entry != NULL ) {
+            json_object* poObjSrs = (json_object*)entry->v;
+            if( poObjSrs != NULL )
+            {
+                OGRSpatialReference* poSRS = OGRGeoJSONReadSpatialReference(poObj);
+                if( poSRS != NULL )
+                {
+                    poGeometry->assignSpatialReference(poSRS);
+                    poSRS->Release();
+                }
+            }
         }
+        else
+            // Assign WGS84 if no CRS defined on geometry.
+            poGeometry->assignSpatialReference(OGRSpatialReference::GetWGS84SRS());
     }
     return poGeometry;
 }
@@ -1333,76 +1445,80 @@ bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
         if( nSize < GeoJSONObject::eMinCoordinateDimension )
         {
             CPLDebug( "GeoJSON",
-                      "Invalid coord dimension. At least 2 dimensions must be present." );
+                      "Invalid coord dimension. "
+                      "At least 2 dimensions must be present." );
             return false;
         }
 
-        // Read X coordinate
+        // Read X coordinate.
         json_object* poObjCoord = json_object_array_get_idx( poObj, 0 );
-        if (poObjCoord == NULL)
+        if( poObjCoord == NULL )
         {
             CPLDebug( "GeoJSON", "Point: got null object." );
             return false;
         }
 
         int iType = json_object_get_type(poObjCoord);
-        if ( (json_type_double != iType) && (json_type_int != iType) )
+        if( json_type_double != iType && json_type_int != iType )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Invalid X coordinate. Type is not double or integer for \'%s\'.",
-                      json_object_to_json_string(poObj) );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid X coordinate. "
+                     "Type is not double or integer for \'%s\'.",
+                     json_object_to_json_string(poObj) );
             return false;
         }
 
-        if (iType == json_type_double)
+        if( iType == json_type_double )
             point.setX(json_object_get_double( poObjCoord ));
         else
             point.setX(json_object_get_int( poObjCoord ));
 
-        // Read Y coordiante
+        // Read Y coordinate.
         poObjCoord = json_object_array_get_idx( poObj, 1 );
-        if (poObjCoord == NULL)
+        if( poObjCoord == NULL )
         {
             CPLDebug( "GeoJSON", "Point: got null object." );
             return false;
         }
 
         iType = json_object_get_type(poObjCoord);
-        if ( (json_type_double != iType) && (json_type_int != iType) )
+        if( json_type_double != iType && json_type_int != iType )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
+                      "Invalid Y coordinate. "
+                      "Type is not double or integer for \'%s\'.",
                       json_object_to_json_string(poObj) );
             return false;
         }
 
-        if (iType == json_type_double)
+        if( iType == json_type_double )
             point.setY(json_object_get_double( poObjCoord ));
         else
             point.setY(json_object_get_int( poObjCoord ));
 
-        // Read Z coordinate
+        // Read Z coordinate.
         if( nSize >= GeoJSONObject::eMaxCoordinateDimension )
         {
             // Don't *expect* mixed-dimension geometries, although the
             // spec doesn't explicitly forbid this.
             poObjCoord = json_object_array_get_idx( poObj, 2 );
-            if (poObjCoord == NULL)
+            if( poObjCoord == NULL )
             {
                 CPLDebug( "GeoJSON", "Point: got null object." );
                 return false;
             }
 
             iType = json_object_get_type(poObjCoord);
-            if ( (json_type_double != iType) && (json_type_int != iType) )
+            if( json_type_double != iType && json_type_int != iType )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "Invalid Z coordinate. Type is not double or integer for \'%s\'.",
+                          "Invalid Z coordinate. "
+                          "Type is not double or integer for \'%s\'.",
                           json_object_to_json_string(poObj) );
                 return false;
             }
 
-            if (iType == json_type_double)
+            if( iType == json_type_double )
                 point.setZ(json_object_get_double( poObjCoord ));
             else
                 point.setZ(json_object_get_int( poObjCoord ));
@@ -1425,8 +1541,7 @@ OGRPoint* OGRGeoJSONReadPoint( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-    json_object* poObjCoords
-        = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
+    json_object* poObjCoords = OGRGeoJSONFindMemberByName(poObj, "coordinates");
     if( NULL == poObjCoords )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1453,8 +1568,7 @@ OGRMultiPoint* OGRGeoJSONReadMultiPoint( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-    json_object* poObjPoints
-        = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
+    json_object* poObjPoints = OGRGeoJSONFindMemberByName(poObj, "coordinates");
     if( NULL == poObjPoints )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1476,7 +1590,8 @@ OGRMultiPoint* OGRGeoJSONReadMultiPoint( json_object* poObj )
             poObjCoords = json_object_array_get_idx( poObjPoints, i );
 
             OGRPoint pt;
-            if( poObjCoords != NULL && !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
+            if( poObjCoords != NULL &&
+                !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
             {
                 delete poMultiPoint;
                 CPLDebug( "GeoJSON",
@@ -1494,7 +1609,7 @@ OGRMultiPoint* OGRGeoJSONReadMultiPoint( json_object* poObj )
 /*                           OGRGeoJSONReadLineString                   */
 /************************************************************************/
 
-OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
+OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw )
 {
     CPLAssert( NULL != poObj );
 
@@ -1527,9 +1642,9 @@ OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
 
         for( int i = 0; i < nPoints; ++i)
         {
-            json_object* poObjCoords
-                = json_object_array_get_idx( poObjPoints, i );
-            if (poObjCoords == NULL)
+            json_object* poObjCoords =
+                json_object_array_get_idx(poObjPoints, i);
+            if( poObjCoords == NULL )
             {
                 delete poLine;
                 CPLDebug( "GeoJSON",
@@ -1545,12 +1660,14 @@ OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
                           "LineString: raw point parsing failure." );
                 return NULL;
             }
-            if (pt.getCoordinateDimension() == 2) {
+            if( pt.getCoordinateDimension() == 2 )
+            {
                 poLine->setPoint( i, pt.getX(), pt.getY());
-            } else {
+            }
+            else
+            {
                 poLine->setPoint( i, pt.getX(), pt.getY(), pt.getZ() );
             }
-
         }
     }
 
@@ -1565,8 +1682,7 @@ OGRMultiLineString* OGRGeoJSONReadMultiLineString( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-    json_object* poObjLines
-        = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
+    json_object* poObjLines = OGRGeoJSONFindMemberByName(poObj, "coordinates");
     if( NULL == poObjLines )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1588,8 +1704,8 @@ OGRMultiLineString* OGRGeoJSONReadMultiLineString( json_object* poObj )
             json_object* poObjLine = NULL;
             poObjLine = json_object_array_get_idx( poObjLines, i );
 
-            OGRLineString* poLine;
-            if (poObjLine != NULL)
+            OGRLineString* poLine = NULL;
+            if( poObjLine != NULL )
                 poLine = OGRGeoJSONReadLineString( poObjLine , true );
             else
                 poLine = new OGRLineString();
@@ -1623,9 +1739,8 @@ OGRLinearRing* OGRGeoJSONReadLinearRing( json_object* poObj )
 
         for( int i = 0; i < nPoints; ++i)
         {
-            json_object* poObjCoords
-                = json_object_array_get_idx( poObj, i );
-            if (poObjCoords == NULL)
+            json_object* poObjCoords = json_object_array_get_idx( poObj, i );
+            if( poObjCoords == NULL )
             {
                 delete poRing;
                 CPLDebug( "GeoJSON",
@@ -1685,9 +1800,8 @@ OGRPolygon* OGRGeoJSONReadPolygon( json_object* poObj , bool bRaw )
         const int nRings = json_object_array_length( poObjRings );
         if( nRings > 0 )
         {
-            json_object* poObjPoints
-                = json_object_array_get_idx( poObjRings, 0 );
-            if (poObjPoints == NULL)
+            json_object* poObjPoints = json_object_array_get_idx(poObjRings, 0);
+            if( poObjPoints == NULL )
             {
                 poPolygon = new OGRPolygon();
                 poPolygon->addRingDirectly( new OGRLinearRing() );
@@ -1705,13 +1819,14 @@ OGRPolygon* OGRGeoJSONReadPolygon( json_object* poObj , bool bRaw )
             for( int i = 1; i < nRings && NULL != poPolygon; ++i )
             {
                 poObjPoints = json_object_array_get_idx( poObjRings, i );
-                if (poObjPoints == NULL)
+                if( poObjPoints == NULL )
                 {
                     poPolygon->addRingDirectly( new OGRLinearRing() );
                 }
                 else
                 {
-                    OGRLinearRing* poRing = OGRGeoJSONReadLinearRing( poObjPoints );
+                    OGRLinearRing* poRing =
+                        OGRGeoJSONReadLinearRing( poObjPoints );
                     if( NULL != poRing )
                     {
                         poPolygon->addRingDirectly( poRing );
@@ -1752,10 +1867,8 @@ OGRMultiPolygon* OGRGeoJSONReadMultiPolygon( json_object* poObj )
 
         for( int i = 0; i < nPolys; ++i)
         {
-
-            json_object* poObjPoly
-                = json_object_array_get_idx( poObjPolys, i );
-            if (poObjPoly == NULL)
+            json_object* poObjPoly = json_object_array_get_idx( poObjPolys, i );
+            if( poObjPoly == NULL )
             {
                 poMultiPoly->addGeometryDirectly( new OGRPolygon() );
             }
@@ -1772,6 +1885,7 @@ OGRMultiPolygon* OGRGeoJSONReadMultiPolygon( json_object* poObj )
 
     return poMultiPoly;
 }
+
 /************************************************************************/
 /*                           OGRGeoJSONReadGeometryCollection           */
 /************************************************************************/
@@ -1780,9 +1894,7 @@ OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
 {
     CPLAssert( NULL != poObj );
 
-
-    json_object* poObjGeoms = NULL;
-    poObjGeoms = OGRGeoJSONFindMemberByName( poObj, "geometries" );
+    json_object* poObjGeoms = OGRGeoJSONFindMemberByName( poObj, "geometries" );
     if( NULL == poObjGeoms )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1803,16 +1915,14 @@ OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
 
         for( int i = 0; i < nGeoms; ++i )
         {
-            json_object* poObjGeom
-                = json_object_array_get_idx( poObjGeoms, i );
-            if (poObjGeom == NULL)
+            json_object* poObjGeom = json_object_array_get_idx( poObjGeoms, i );
+            if( poObjGeom == NULL )
             {
                 CPLDebug( "GeoJSON", "Skipping null sub-geometry");
                 continue;
             }
 
-            OGRGeometry* poGeometry
-                = OGRGeoJSONReadGeometry( poObjGeom );
+            OGRGeometry* poGeometry = OGRGeoJSONReadGeometry( poObjGeom );
             if( NULL != poGeometry )
             {
                 poCollection->addGeometryDirectly( poGeometry );
@@ -1827,11 +1937,12 @@ OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
 /*                           OGR_G_ExportToJson                         */
 /************************************************************************/
 
+/** Create a OGR geometry from a GeoJSON geometry object */
 OGRGeometryH OGR_G_CreateGeometryFromJson( const char* pszJson )
 {
     if( NULL == pszJson )
     {
-        /* Translation failed */
+        // Translation failed.
         return NULL;
     }
 
@@ -1839,16 +1950,9 @@ OGRGeometryH OGR_G_CreateGeometryFromJson( const char* pszJson )
     if( !OGRJSonParse(pszJson, &poObj) )
         return NULL;
 
-    OGRGeometry* poGeometry
-        = OGRGeoJSONReadGeometry( poObj );
+    OGRGeometry* poGeometry = OGRGeoJSONReadGeometry( poObj );
 
-    /* Assign WGS84 if no CRS defined on geometry */
-    if( poGeometry && poGeometry->getSpatialReference() == NULL )
-    {
-        poGeometry->assignSpatialReference(OGRSpatialReference::GetWGS84SRS());
-    }
-
-    /* Release JSON tree. */
+    // Release JSON tree.
     json_object_put( poObj );
 
     return (OGRGeometryH)poGeometry;
@@ -1858,7 +1962,8 @@ OGRGeometryH OGR_G_CreateGeometryFromJson( const char* pszJson )
 /*                       json_ex_get_object_by_path()                   */
 /************************************************************************/
 
-json_object* json_ex_get_object_by_path(json_object* poObj, const char* pszPath )
+json_object* json_ex_get_object_by_path( json_object* poObj,
+                                         const char* pszPath )
 {
     if( poObj == NULL || json_object_get_type(poObj) != json_type_object ||
         pszPath == NULL || *pszPath == '\0' )
@@ -1868,7 +1973,7 @@ json_object* json_ex_get_object_by_path(json_object* poObj, const char* pszPath
     char** papszTokens = CSLTokenizeString2( pszPath, ".", 0 );
     for( int i = 0; papszTokens[i] != NULL; i++ )
     {
-        poObj = json_object_object_get(poObj, papszTokens[i]);
+        poObj = CPL_json_object_object_get(poObj, papszTokens[i]);
         if( poObj == NULL )
             break;
         if( papszTokens[i+1] != NULL )
@@ -1888,7 +1993,8 @@ json_object* json_ex_get_object_by_path(json_object* poObj, const char* pszPath
 /*                             OGRJSonParse()                           */
 /************************************************************************/
 
-bool OGRJSonParse(const char* pszText, json_object** ppoObj, bool bVerboseError)
+bool OGRJSonParse( const char* pszText, json_object** ppoObj,
+                   bool bVerboseError )
 {
     if( ppoObj == NULL )
         return false;
@@ -1898,9 +2004,9 @@ bool OGRJSonParse(const char* pszText, json_object** ppoObj, bool bVerboseError)
     {
         if( bVerboseError )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                        "GeoJSON parsing error: %s (at offset %d)",
-                        json_tokener_error_desc(jstok->err), jstok->char_offset);
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "GeoJSON parsing error: %s (at offset %d)",
+                     json_tokener_error_desc(jstok->err), jstok->char_offset);
         }
 
         json_tokener_free(jstok);
@@ -1910,3 +2016,18 @@ bool OGRJSonParse(const char* pszText, json_object** ppoObj, bool bVerboseError)
     json_tokener_free(jstok);
     return true;
 }
+
+/************************************************************************/
+/*                    CPL_json_object_object_get()                      */
+/************************************************************************/
+
+// This is the same as json_object_object_get() except it will not raise
+// deprecation warning.
+
+json_object*  CPL_json_object_object_get(struct json_object* obj,
+                                         const char *key)
+{
+    json_object* poRet = NULL;
+    json_object_object_get_ex(obj, key, &poRet);
+    return poRet;
+}
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
index f831d59..7b10742 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonreader.h 37099 2017-01-11 12:21:34Z rouault $
+ * $Id: ogrgeojsonreader.h 37858 2017-03-29 10:19:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -30,10 +30,12 @@
 #ifndef OGR_GEOJSONREADER_H_INCLUDED
 #define OGR_GEOJSONREADER_H_INCLUDED
 
-#include <ogr_core.h>
 #include "cpl_string.h"
+#include <ogr_core.h>
 #include "ogrsf_frmts.h"
-#include <json.h> // JSON-C
+
+#include "ogr_json_header.h"
+
 #include <set>
 
 /************************************************************************/
@@ -89,8 +91,7 @@ class OGRGeoJSONDataSource;
 
 class OGRGeoJSONReader
 {
-public:
-
+  public:
     OGRGeoJSONReader();
     ~OGRGeoJSONReader();
 
@@ -108,8 +109,7 @@ public:
 
     json_object* GetJSonObject() { return poGJObject_; }
 
-private:
-
+  private:
     json_object* poGJObject_;
 
     bool bGeometryPreserve_;
@@ -140,39 +140,48 @@ private:
     //
     bool GenerateLayerDefn( OGRGeoJSONLayer* poLayer, json_object* poGJObject );
     bool GenerateFeatureDefn( OGRGeoJSONLayer* poLayer, json_object* poObj );
-    bool AddFeature( OGRGeoJSONLayer* poLayer, OGRGeometry* poGeometry );
-    bool AddFeature( OGRGeoJSONLayer* poLayer, OGRFeature* poFeature );
+    static bool AddFeature( OGRGeoJSONLayer* poLayer, OGRGeometry* poGeometry );
+    static bool AddFeature( OGRGeoJSONLayer* poLayer, OGRFeature* poFeature );
 
     OGRGeometry* ReadGeometry( json_object* poObj );
     OGRFeature* ReadFeature( OGRGeoJSONLayer* poLayer, json_object* poObj );
     void ReadFeatureCollection( OGRGeoJSONLayer* poLayer, json_object* poObj );
 };
 
-void OGRGeoJSONReaderSetField(OGRLayer* poLayer,
-                              OGRFeature* poFeature,
-                              int nField,
-                              const char* pszAttrPrefix,
-                              json_object* poVal,
-                              bool bFlattenNestedAttributes,
-                              char chNestedAttributeSeparator);
-void OGRGeoJSONReaderAddOrUpdateField(OGRFeatureDefn* poDefn,
-                                      const char* pszKey,
-                                      json_object* poVal,
-                                      bool bFlattenNestedAttributes,
-                                      char chNestedAttributeSeparator,
-                                      bool bArrayAsString,
-                                      std::set<int>& aoSetUndeterminedTypeFields);
+void OGRGeoJSONReaderSetField( OGRLayer* poLayer,
+                               OGRFeature* poFeature,
+                               int nField,
+                               const char* pszAttrPrefix,
+                               json_object* poVal,
+                               bool bFlattenNestedAttributes,
+                               char chNestedAttributeSeparator );
+void OGRGeoJSONReaderAddOrUpdateField(
+    OGRFeatureDefn* poDefn,
+    const char* pszKey,
+    json_object* poVal,
+    bool bFlattenNestedAttributes,
+    char chNestedAttributeSeparator,
+    bool bArrayAsString,
+    std::set<int>& aoSetUndeterminedTypeFields );
 
 /************************************************************************/
 /*                 GeoJSON Parsing Utilities                            */
 /************************************************************************/
 
-json_object* OGRGeoJSONFindMemberByName(json_object* poObj,  const char* pszName );
+lh_entry* OGRGeoJSONFindMemberEntryByName( json_object* poObj,
+                                         const char* pszName );
+json_object* OGRGeoJSONFindMemberByName( json_object* poObj,
+                                         const char* pszName );
 GeoJSONObject::Type OGRGeoJSONGetType( json_object* poObj );
 
-json_object* json_ex_get_object_by_path(json_object* poObj, const char* pszPath );
+json_object* json_ex_get_object_by_path( json_object* poObj,
+                                         const char* pszPath );
+
+json_object CPL_DLL*  CPL_json_object_object_get( struct json_object* obj,
+                                                  const char *key );
 
-bool OGRJSonParse(const char* pszText, json_object** ppoObj, bool bVerboseError = true);
+bool OGRJSonParse( const char* pszText, json_object** ppoObj,
+                   bool bVerboseError = true );
 
 /************************************************************************/
 /*                 GeoJSON Geometry Translators                         */
@@ -190,16 +199,13 @@ OGRMultiPolygon* OGRGeoJSONReadMultiPolygon( json_object* poObj );
 OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj );
 OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj );
 
-
-
 /************************************************************************/
 /*                          OGRESRIJSONReader                           */
 /************************************************************************/
 
 class OGRESRIJSONReader
 {
-public:
-
+  public:
     OGRESRIJSONReader();
     ~OGRESRIJSONReader();
 
@@ -209,7 +215,6 @@ public:
     json_object* GetJSonObject() { return poGJObject_; }
 
 private:
-
     json_object* poGJObject_;
     OGRGeoJSONLayer* poLayer_;
 
@@ -244,16 +249,14 @@ OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj);
 
 class OGRTopoJSONReader
 {
-public:
-
+  public:
     OGRTopoJSONReader();
     ~OGRTopoJSONReader();
 
     OGRErr Parse( const char* pszText );
     void ReadLayers( OGRGeoJSONDataSource* poDS );
 
-private:
-
+  private:
     json_object* poGJObject_;
 
     //
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
index f719ee4..03b9424 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeojsonutils.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of private utilities used within OGR GeoJSON Driver.
@@ -27,23 +26,26 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
 #include "ogrgeojsonutils.h"
 #include <cpl_port.h>
 #include <cpl_conv.h>
 #include <ogr_geometry.h>
 #include <json.h> // JSON-C
 
+CPL_CVSID("$Id: ogrgeojsonutils.cpp 35836 2016-10-20 13:57:15Z goatbar $");
+
 /************************************************************************/
 /*                           GeoJSONIsObject()                          */
 /************************************************************************/
 
-int GeoJSONIsObject( const char* pszText )
+bool GeoJSONIsObject( const char* pszText )
 {
     if( NULL == pszText )
-        return FALSE;
+        return false;
 
     /* Skip UTF-8 BOM (#5630) */
-    const GByte* pabyData = (const GByte*)pszText;
+    const GByte* pabyData = reinterpret_cast<const GByte *>(pszText);
     if( pabyData[0] == 0xEF && pabyData[1] == 0xBB && pabyData[2] == 0xBF )
         pszText += 3;
 
@@ -54,7 +56,7 @@ int GeoJSONIsObject( const char* pszText )
         pszText++;
 
     const char* const apszPrefix[] = { "loadGeoJSON(", "jsonp(" };
-    for(size_t iP = 0; iP < sizeof(apszPrefix) / sizeof(apszPrefix[0]); iP++ )
+    for( size_t iP = 0; iP < sizeof(apszPrefix) / sizeof(apszPrefix[0]); iP++ )
     {
         if( strncmp(pszText, apszPrefix[iP], strlen(apszPrefix[iP])) == 0 )
         {
@@ -64,13 +66,17 @@ int GeoJSONIsObject( const char* pszText )
     }
 
     if( *pszText != '{' )
-        return FALSE;
+        return false;
 
-    return ((strstr(pszText, "\"type\"") != NULL && strstr(pszText, "\"coordinates\"") != NULL)
-        || (strstr(pszText, "\"type\"") != NULL && strstr(pszText, "\"Topology\"") != NULL)
+    return
+        (strstr(pszText, "\"type\"") != NULL &&
+         strstr(pszText, "\"coordinates\"") != NULL)
+        || (strstr(pszText, "\"type\"") != NULL &&
+            strstr(pszText, "\"Topology\"") != NULL)
         || strstr(pszText, "\"FeatureCollection\"") != NULL
         || strstr(pszText, "\"Feature\"") != NULL
-        || (strstr(pszText, "\"geometryType\"") != NULL && strstr(pszText, "\"esriGeometry") != NULL));
+        || (strstr(pszText, "\"geometryType\"") != NULL &&
+            strstr(pszText, "\"esriGeometry") != NULL);
 }
 
 /************************************************************************/
@@ -80,9 +86,9 @@ int GeoJSONIsObject( const char* pszText )
 static
 bool GeoJSONFileIsObject( GDALOpenInfo* poOpenInfo )
 {
-    // by default read first 6000 bytes
+    // By default read first 6000 bytes.
     // 6000 was chosen as enough bytes to
-    // enable all current tests to pass
+    // enable all current tests to pass.
 
     if( poOpenInfo->fpL == NULL ||
         !poOpenInfo->TryToIngest(6000) )
@@ -109,7 +115,8 @@ GeoJSONSourceType GeoJSONGetSourceType( GDALOpenInfo* poOpenInfo )
     // NOTE: Sometimes URL ends with .geojson token, for example
     //       http://example/path/2232.geojson
     //       It's important to test beginning of source first.
-    if ( eGeoJSONProtocolUnknown != GeoJSONGetProtocolType( poOpenInfo->pszFilename ) )
+    if( eGeoJSONProtocolUnknown !=
+        GeoJSONGetProtocolType( poOpenInfo->pszFilename ) )
     {
         if( (strstr(poOpenInfo->pszFilename, "SERVICE=WFS") ||
              strstr(poOpenInfo->pszFilename, "service=WFS") ||
@@ -121,9 +128,12 @@ GeoJSONSourceType GeoJSONGetSourceType( GDALOpenInfo* poOpenInfo )
     else if( EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "geojson" )
              || EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "json" )
              || EQUAL( CPLGetExtension( poOpenInfo->pszFilename ), "topojson" )
-             || ((STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/") || STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsizip/")) &&
-                 (strstr( poOpenInfo->pszFilename, ".json") || strstr( poOpenInfo->pszFilename, ".JSON") ||
-                  strstr( poOpenInfo->pszFilename, ".geojson") || strstr( poOpenInfo->pszFilename, ".GEOJSON")) ))
+             || ((STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsigzip/") ||
+                  STARTS_WITH_CI(poOpenInfo->pszFilename, "/vsizip/")) &&
+                 (strstr( poOpenInfo->pszFilename, ".json") ||
+                  strstr( poOpenInfo->pszFilename, ".JSON") ||
+                  strstr( poOpenInfo->pszFilename, ".geojson") ||
+                  strstr( poOpenInfo->pszFilename, ".GEOJSON")) ))
     {
         if( poOpenInfo->fpL != NULL )
             srcType = eGeoJSONSourceFile;
@@ -162,8 +172,8 @@ GeoJSONProtocolType GeoJSONGetProtocolType( const char* pszSource )
 /*                           GeoJSONPropertyToFieldType()               */
 /************************************************************************/
 
-#define MY_INT64_MAX ((((GIntBig)0x7FFFFFFF) << 32) | 0xFFFFFFFF)
-#define MY_INT64_MIN ((((GIntBig)0x80000000) << 32))
+static const GIntBig MY_INT64_MAX = (((GIntBig)0x7FFFFFFF) << 32) | 0xFFFFFFFF;
+static const GIntBig MY_INT64_MIN = ((GIntBig)0x80000000) << 32;
 
 OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
                                          OGRFieldSubType& eSubType,
@@ -171,7 +181,7 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
 {
     eSubType = OFSTNone;
 
-    if (poObject == NULL) { return OFTString; }
+    if( poObject == NULL ) { return OFTString; }
 
     json_type type = json_object_get_type( poObject );
 
@@ -193,9 +203,11 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
                 if( !bWarned )
                 {
                     bWarned = true;
-                    CPLError(CE_Warning, CPLE_AppDefined,
-                             "Integer values probably ranging out of 64bit integer range "
-                             "have been found. Will be clamped to INT64_MIN/INT64_MAX");
+                    CPLError(
+                        CE_Warning, CPLE_AppDefined,
+                        "Integer values probably ranging out of 64bit integer "
+                        "range have been found. Will be clamped to "
+                        "INT64_MIN/INT64_MAX");
                 }
             }
             return OFTInteger64;
@@ -211,40 +223,42 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
     {
         if( bArrayAsString )
             return OFTString;
-        int nSize = json_object_array_length(poObject);
-        if (nSize == 0)
-            return OFTStringList; /* we don't know, so let's assume it's a string list */
+        const int nSize = json_object_array_length(poObject);
+        if( nSize == 0 )
+            // We don't know, so let's assume it's a string list.
+            return OFTStringList;
         OGRFieldType eType = OFTIntegerList;
-        int bOnlyBoolean = TRUE;
-        for(int i=0;i<nSize;i++)
+        bool bOnlyBoolean = true;
+        for( int i = 0; i < nSize; i++ )
         {
             json_object* poRow = json_object_array_get_idx(poObject, i);
-            if (poRow != NULL)
+            if( poRow != NULL )
             {
                 type = json_object_get_type( poRow );
-                bOnlyBoolean &= (type == json_type_boolean);
-                if (type == json_type_string)
+                bOnlyBoolean &= type == json_type_boolean;
+                if( type == json_type_string )
                     return OFTStringList;
-                else if (type == json_type_double)
+                else if( type == json_type_double )
                     eType = OFTRealList;
-                else if (eType == OFTIntegerList &&
-                         type == json_type_int)
+                else if( eType == OFTIntegerList &&
+                         type == json_type_int )
                 {
                     GIntBig nVal = json_object_get_int64(poRow);
                     if( !CPL_INT64_FITS_ON_INT32(nVal) )
                         eType = OFTInteger64List;
                 }
-                else if (type != json_type_int &&
-                         type != json_type_boolean)
+                else if( type != json_type_int &&
+                         type != json_type_boolean )
                     return OFTString;
             }
         }
         if( bOnlyBoolean )
             eSubType = OFSTBoolean;
+
         return eType;
     }
-    else
-        return OFTString; /* null, object */
+
+    return OFTString; // null, object
 }
 
 /************************************************************************/
@@ -253,7 +267,7 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
 
 OGRFieldType GeoJSONStringPropertyToFieldType( json_object* poObject )
 {
-    if (poObject == NULL) { return OFTString; }
+    if( poObject == NULL ) { return OFTString; }
     const char* pszStr = json_object_get_string( poObject );
 
     OGRField sWrkField;
@@ -263,9 +277,10 @@ OGRFieldType GeoJSONStringPropertyToFieldType( json_object* poObject )
     CPLErrorReset();
     if( bSuccess )
     {
-        const bool bHasDate = strchr( pszStr, '/' ) != NULL ||
+        const bool bHasDate =
+            strchr( pszStr, '/' ) != NULL ||
             strchr( pszStr, '-' ) != NULL;
-        const bool  bHasTime = strchr( pszStr, ':' ) != NULL;
+        const bool bHasTime = strchr( pszStr, ':' ) != NULL;
         if( bHasDate && bHasTime )
             return OFTDateTime;
         else if( bHasDate )
@@ -299,7 +314,8 @@ const char* OGRGeoJSONGetGeometryName( OGRGeometry const* poGeometry )
         return "MultiLineString";
     else if( wkbMultiPolygon == eType || wkbMultiPolygon25D == eType )
         return "MultiPolygon";
-    else if( wkbGeometryCollection == eType || wkbGeometryCollection25D == eType )
+    else if( wkbGeometryCollection == eType ||
+             wkbGeometryCollection25D == eType )
         return "GeometryCollection";
 
     return "Unknown";
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h
index 8336bb5..a53ed33 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonutils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonutils.h 32181 2015-12-15 10:41:07Z rouault $
+ * $Id: ogrgeojsonutils.h 36477 2016-11-24 01:41:10Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private utilities within OGR OGRGeoJSON Driver.
@@ -30,7 +30,9 @@
 #define OGR_GEOJSONUTILS_H_INCLUDED
 
 #include <ogr_core.h>
-#include <json.h> // JSON-C
+
+#include "ogr_json_header.h"
+
 #include "cpl_vsi.h"
 #include "gdal_priv.h"
 
@@ -68,7 +70,7 @@ GeoJSONProtocolType GeoJSONGetProtocolType( const char* pszSource );
 /*                           GeoJSONIsObject                            */
 /************************************************************************/
 
-int GeoJSONIsObject( const char* pszText );
+bool GeoJSONIsObject( const char* pszText );
 
 /************************************************************************/
 /*                           GeoJSONPropertyToFieldType                 */
@@ -78,7 +80,6 @@ OGRFieldType GeoJSONPropertyToFieldType( json_object* poObject,
                                          OGRFieldSubType& eSubType,
                                          bool bArrayAsString = false );
 
-
 /************************************************************************/
 /*                      GeoJSONStringPropertyToFieldType                */
 /************************************************************************/
@@ -91,4 +92,4 @@ OGRFieldType GeoJSONStringPropertyToFieldType( json_object* poObject );
 
 const char* OGRGeoJSONGetGeometryName( OGRGeometry const* poGeometry );
 
-#endif /* OGR_GEOJSONUTILS_H_INCLUDED */
+#endif  // OGR_GEOJSONUTILS_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
index 9c55f40..62b8c9f 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwritelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeojsonwritelayer.cpp 35926 2016-10-25 14:37:41Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRGeoJSONWriteLayer class (OGR GeoJSON Driver).
@@ -27,10 +26,15 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
 #include "ogr_geojson.h"
 #include "ogrgeojsonwriter.h"
 
-/* Remove annoying warnings Microsoft Visual C++ */
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrgeojsonwritelayer.cpp 37472 2017-02-26 02:47:45Z goatbar $");
+
+// Remove annoying warnings Microsoft Visual C++.
 #if defined(_MSC_VER)
 #  pragma warning(disable:4512)
 #endif
@@ -43,20 +47,35 @@ OGRGeoJSONWriteLayer::OGRGeoJSONWriteLayer( const char* pszName,
                                             OGRwkbGeometryType eGType,
                                             char** papszOptions,
                                             bool bWriteFC_BBOXIn,
-                                           OGRGeoJSONDataSource* poDS )
-    : poDS_( poDS ), poFeatureDefn_(new OGRFeatureDefn( pszName ) ), nOutCounter_( 0 )
+                                            OGRCoordinateTransformation* poCT,
+                                            OGRGeoJSONDataSource* poDS ) :
+    poDS_(poDS),
+    poFeatureDefn_(new OGRFeatureDefn( pszName )),
+    nOutCounter_(0),
+    bWriteBBOX(CPLTestBool(
+        CSLFetchNameValueDef(papszOptions, "WRITE_BBOX", "FALSE"))),
+    bBBOX3D(false),
+    bWriteFC_BBOX(bWriteFC_BBOXIn),
+    nCoordPrecision_(atoi(
+        CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"))),
+    nSignificantFigures_(atoi(
+        CSLFetchNameValueDef(papszOptions, "SIGNIFICANT_FIGURES", "-1"))),
+    bRFC7946_(CPLTestBool(
+        CSLFetchNameValueDef(papszOptions, "RFC7946", "FALSE"))),
+    poCT_(poCT)
 {
-    bWriteBBOX = CPLTestBool(CSLFetchNameValueDef(
-        papszOptions, "WRITE_BBOX", "FALSE"));
-    bBBOX3D = false;
-    bWriteFC_BBOX = bWriteFC_BBOXIn;
-
     poFeatureDefn_->Reference();
     poFeatureDefn_->SetGeomType( eGType );
     SetDescription( poFeatureDefn_->GetName() );
-
-    nCoordPrecision_ = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
-    nSignificantFigures_ = atoi(CSLFetchNameValueDef(papszOptions, "SIGNIFICANT_FIGURES", "-1"));
+    if( bRFC7946_ && nCoordPrecision_ < 0 )
+        nCoordPrecision_ = 7;
+    oWriteOptions_.bWriteBBOX = bWriteBBOX;
+    oWriteOptions_.nCoordPrecision = nCoordPrecision_;
+    oWriteOptions_.nSignificantFigures = nSignificantFigures_;
+    if( bRFC7946_ )
+    {
+        oWriteOptions_.SetRFC7946Settings();
+    }
 }
 
 /************************************************************************/
@@ -72,17 +91,32 @@ OGRGeoJSONWriteLayer::~OGRGeoJSONWriteLayer()
     if( bWriteFC_BBOX && sEnvelopeLayer.IsInit() )
     {
         CPLString osBBOX = "[ ";
-        osBBOX += CPLSPrintf("%.15g, ", sEnvelopeLayer.MinX);
-        osBBOX += CPLSPrintf("%.15g, ", sEnvelopeLayer.MinY);
-        if( bBBOX3D )
-            osBBOX += CPLSPrintf("%.15g, ", sEnvelopeLayer.MinZ);
-        osBBOX += CPLSPrintf("%.15g, ", sEnvelopeLayer.MaxX);
-        osBBOX += CPLSPrintf("%.15g", sEnvelopeLayer.MaxY);
-        if( bBBOX3D )
-            osBBOX += CPLSPrintf(", %.15g", sEnvelopeLayer.MaxZ);
+        if( bRFC7946_ )
+        {
+            osBBOX += CPLSPrintf("%.*f, ", nCoordPrecision_, sEnvelopeLayer.MinX);
+            osBBOX += CPLSPrintf("%.*f, ", nCoordPrecision_, sEnvelopeLayer.MinY);
+            if( bBBOX3D )
+                osBBOX += CPLSPrintf("%.*f, ", nCoordPrecision_, sEnvelopeLayer.MinZ);
+            osBBOX += CPLSPrintf("%.*f, ", nCoordPrecision_, sEnvelopeLayer.MaxX);
+            osBBOX += CPLSPrintf("%.*f", nCoordPrecision_, sEnvelopeLayer.MaxY);
+            if( bBBOX3D )
+                osBBOX += CPLSPrintf(", %.*f", nCoordPrecision_, sEnvelopeLayer.MaxZ);
+        }
+        else
+        {
+            osBBOX += CPLSPrintf("%.15g, ", sEnvelopeLayer.MinX);
+            osBBOX += CPLSPrintf("%.15g, ", sEnvelopeLayer.MinY);
+            if( bBBOX3D )
+                osBBOX += CPLSPrintf("%.15g, ", sEnvelopeLayer.MinZ);
+            osBBOX += CPLSPrintf("%.15g, ", sEnvelopeLayer.MaxX);
+            osBBOX += CPLSPrintf("%.15g", sEnvelopeLayer.MaxY);
+            if( bBBOX3D )
+                osBBOX += CPLSPrintf(", %.15g", sEnvelopeLayer.MaxZ);
+        }
         osBBOX += " ]";
 
-        if( poDS_->GetFpOutputIsSeekable() && osBBOX.size() + 9 < SPACE_FOR_BBOX )
+        if( poDS_->GetFpOutputIsSeekable() &&
+            osBBOX.size() + 9 < OGRGeoJSONDataSource::SPACE_FOR_BBOX )
         {
             VSIFSeekL(fp, poDS_->GetBBOXInsertLocation(), SEEK_SET);
             VSIFPrintfL( fp, "\"bbox\": %s,", osBBOX.c_str() );
@@ -100,6 +134,8 @@ OGRGeoJSONWriteLayer::~OGRGeoJSONWriteLayer()
     {
         poFeatureDefn_->Release();
     }
+
+    delete poCT_;
 }
 
 /************************************************************************/
@@ -110,14 +146,45 @@ OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature )
 {
     VSILFILE* fp = poDS_->GetOutputFile();
 
-    if( NULL == poFeature )
+    OGRFeature* poFeatureToWrite;
+    if( poCT_ != NULL || bRFC7946_ )
     {
-        CPLDebug( "GeoJSON", "Feature is null" );
-        return OGRERR_INVALID_HANDLE;
+        poFeatureToWrite = new OGRFeature(poFeatureDefn_);
+        poFeatureToWrite->SetFrom( poFeature );
+        OGRGeometry* poGeometry = poFeatureToWrite->GetGeometryRef();
+        if( poGeometry )
+        {
+            const char* const apszOptions[] = { "WRAPDATELINE=YES", NULL };
+            OGRGeometry* poNewGeom =
+                OGRGeometryFactory::transformWithOptions(
+                    poGeometry, poCT_, const_cast<char**>(apszOptions));
+            if( poNewGeom == NULL )
+            {
+                delete poFeatureToWrite;
+                return OGRERR_FAILURE;
+            }
+
+            OGREnvelope sEnvelope;
+            poNewGeom->getEnvelope(&sEnvelope);
+            if( sEnvelope.MinX < -180.0 || sEnvelope.MaxX > 180.0 ||
+                sEnvelope.MinY < -90.0 || sEnvelope.MaxY > 90.0 )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Geometry extent outside of [-180.0,180.0]x[-90.0,90.0] bounds");
+                delete poFeatureToWrite;
+                return OGRERR_FAILURE;
+            }
+
+            poFeatureToWrite->SetGeometryDirectly( poNewGeom );
+        }
+    }
+    else
+    {
+        poFeatureToWrite = poFeature;
     }
 
-    json_object* poObj = OGRGeoJSONWriteFeature( poFeature, bWriteBBOX,
-                                                 nCoordPrecision_, nSignificantFigures_ );
+    json_object* poObj =
+        OGRGeoJSONWriteFeature( poFeatureToWrite, oWriteOptions_ );
     CPLAssert( NULL != poObj );
 
     if( nOutCounter_ > 0 )
@@ -131,18 +198,91 @@ OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature )
 
     ++nOutCounter_;
 
-    OGRGeometry* poGeometry = poFeature->GetGeometryRef();
-    if ( (bWriteBBOX || bWriteFC_BBOX) && poGeometry != NULL && !poGeometry->IsEmpty() )
+    OGRGeometry* poGeometry = poFeatureToWrite->GetGeometryRef();
+    if( bWriteFC_BBOX && poGeometry != NULL && !poGeometry->IsEmpty() )
     {
-        OGREnvelope3D sEnvelope;
-        poGeometry->getEnvelope(&sEnvelope);
-
+        OGREnvelope3D sEnvelope = OGRGeoJSONGetBBox( poGeometry,
+                                                     oWriteOptions_ );
         if( poGeometry->getCoordinateDimension() == 3 )
             bBBOX3D = true;
 
-        sEnvelopeLayer.Merge(sEnvelope);
+        if( !sEnvelopeLayer.IsInit() )
+        {
+            sEnvelopeLayer = sEnvelope;
+        }
+        else if( oWriteOptions_.bBBOXRFC7946 )
+        {
+            const bool bEnvelopeCrossAM = ( sEnvelope.MinX > sEnvelope.MaxX );
+            const bool bEnvelopeLayerCrossAM =
+                                ( sEnvelopeLayer.MinX > sEnvelopeLayer.MaxX );
+            if( bEnvelopeCrossAM )
+            {
+                if( bEnvelopeLayerCrossAM )
+                {
+                    sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX,
+                                                   sEnvelope.MinX);
+                    sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX,
+                                                   sEnvelope.MaxX);
+                }
+                else
+                {
+                    if( sEnvelopeLayer.MinX > 0 )
+                    {
+                        sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX,
+                                                       sEnvelope.MinX);
+                        sEnvelopeLayer.MaxX = sEnvelope.MaxX;
+                    }
+                    else if( sEnvelopeLayer.MaxX < 0 )
+                    {
+                        sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX,
+                                                       sEnvelope.MaxX);
+                        sEnvelopeLayer.MinX = sEnvelope.MinX;
+                    }
+                    else
+                    {
+                        sEnvelopeLayer.MinX = -180.0;
+                        sEnvelopeLayer.MaxX = 180.0;
+                    }
+                }
+            }
+            else if( bEnvelopeLayerCrossAM )
+            {
+                if( sEnvelope.MinX > 0 )
+                {
+                    sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX,
+                                                   sEnvelope.MinX);
+                }
+                else if( sEnvelope.MaxX < 0 )
+                {
+                    sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX,
+                                                   sEnvelope.MaxX);
+                }
+                else
+                {
+                    sEnvelopeLayer.MinX = -180.0;
+                    sEnvelopeLayer.MaxX = 180.0;
+                }
+            }
+            else
+            {
+                sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX,
+                                               sEnvelope.MinX);
+                sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX,
+                                               sEnvelope.MaxX);
+            }
+
+            sEnvelopeLayer.MinY = std::min(sEnvelopeLayer.MinY, sEnvelope.MinY);
+            sEnvelopeLayer.MaxY = std::max(sEnvelopeLayer.MaxY, sEnvelope.MaxY);
+        }
+        else
+        {
+            sEnvelopeLayer.Merge(sEnvelope);
+        }
     }
 
+    if( poFeatureToWrite != poFeature )
+        delete poFeatureToWrite;
+
     return OGRERR_NONE;
 }
 
@@ -150,10 +290,9 @@ OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature )
 /*                           CreateField()                              */
 /************************************************************************/
 
-OGRErr OGRGeoJSONWriteLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
+OGRErr OGRGeoJSONWriteLayer::CreateField( OGRFieldDefn* poField,
+                                          int /* bApproxOK */  )
 {
-    UNREFERENCED_PARAM(bApproxOK);
-
     for( int i = 0; i < poFeatureDefn_->GetFieldCount(); ++i )
     {
         OGRFieldDefn* poDefn = poFeatureDefn_->GetFieldDefn(i);
@@ -180,9 +319,9 @@ OGRErr OGRGeoJSONWriteLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
 
 int OGRGeoJSONWriteLayer::TestCapability( const char* pszCap )
 {
-    if (EQUAL(pszCap, OLCCreateField))
+    if( EQUAL(pszCap, OLCCreateField) )
         return TRUE;
-    else if (EQUAL(pszCap, OLCSequentialWrite))
+    else if( EQUAL(pszCap, OLCSequentialWrite) )
         return TRUE;
 
     return FALSE;
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
index b0a796a..2c1eddf 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeojsonwriter.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of GeoJSON writer utilities (OGR GeoJSON Driver).
@@ -27,24 +26,51 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
 #include "ogrgeojsonwriter.h"
 #include "ogrgeojsonutils.h"
 #include "ogr_geojson.h"
 #include "ogrgeojsonreader.h"
-#include <json.h> // JSON-C
+#include <json.h>  // JSON-C
 #include <json_object_private.h>
 #include <printbuf.h>
 #include <ogr_api.h>
 #include <ogr_p.h>
 
+CPL_CVSID("$Id: ogrgeojsonwriter.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
+
+/************************************************************************/
+/*                         SetRFC7946Settings()                         */
+/************************************************************************/
+
+/*! @cond Doxygen_Suppress */
+void OGRGeoJSONWriteOptions::SetRFC7946Settings()
+{
+    bBBOXRFC7946 = true;
+    if( nCoordPrecision < 0 )
+        nCoordPrecision = 7;
+    bPolygonRightHandRule = true;
+    bCanPatchCoordinatesWithNativeData = false;
+    bHonourReservedRFC7946Members = true;
+}
+/*! @endcond */
+
+/************************************************************************/
+/*                        json_object_new_coord()                       */
+/************************************************************************/
 
-static json_object* json_object_new_coord(double dfVal, int nCoordPrecision, int nSignificantFigures)
+static json_object* json_object_new_coord( double dfVal,
+                                           const OGRGeoJSONWriteOptions& oOptions )
 {
     // If coordinate precision is specified, or significant figures is not
-    // then use the '%f' formatting
-    if( nCoordPrecision >= 0 || nSignificantFigures < 0 )
-        return json_object_new_double_with_precision(dfVal, nCoordPrecision);
-    return json_object_new_double_with_significant_figures(dfVal, nSignificantFigures);
+    // then use the '%f' formatting.
+    if( oOptions.nCoordPrecision >= 0 || oOptions.nSignificantFigures < 0 )
+        return json_object_new_double_with_precision(dfVal,
+                                                     oOptions.nCoordPrecision);
+
+    return json_object_new_double_with_significant_figures(dfVal,
+                                                oOptions.nSignificantFigures);
 }
 
 /************************************************************************/
@@ -54,14 +80,33 @@ static json_object* json_object_new_coord(double dfVal, int nCoordPrecision, int
 static bool OGRGeoJSONIsPatchablePosition( json_object* poJSonCoordinates,
                                            json_object* poNativeCoordinates )
 {
-    return json_object_get_type(poJSonCoordinates) == json_type_array &&
-           json_object_get_type(poNativeCoordinates) == json_type_array &&
-           json_object_array_length(poJSonCoordinates) == 3 &&
-           json_object_array_length(poNativeCoordinates) >= 4 &&
-           json_object_get_type(
-            json_object_array_get_idx(poJSonCoordinates, 0)) != json_type_array &&
-           json_object_get_type(
-            json_object_array_get_idx(poNativeCoordinates, 0)) != json_type_array;
+    return
+        json_object_get_type(poJSonCoordinates) == json_type_array &&
+        json_object_get_type(poNativeCoordinates) == json_type_array &&
+        json_object_array_length(poJSonCoordinates) == 3 &&
+        json_object_array_length(poNativeCoordinates) >= 4 &&
+        json_object_get_type(json_object_array_get_idx(poJSonCoordinates,
+                                                       0)) != json_type_array &&
+        json_object_get_type(json_object_array_get_idx(poNativeCoordinates,
+                                                       0)) != json_type_array;
+}
+
+/************************************************************************/
+/*                    OGRGeoJSONIsCompatiblePosition()                  */
+/************************************************************************/
+
+static bool OGRGeoJSONIsCompatiblePosition( json_object* poJSonCoordinates,
+                                           json_object* poNativeCoordinates )
+{
+    return
+        json_object_get_type(poJSonCoordinates) == json_type_array &&
+        json_object_get_type(poNativeCoordinates) == json_type_array &&
+        json_object_array_length(poJSonCoordinates) ==
+            json_object_array_length(poNativeCoordinates) &&
+        json_object_get_type(json_object_array_get_idx(poJSonCoordinates,
+                                                       0)) != json_type_array &&
+        json_object_get_type(json_object_array_get_idx(poNativeCoordinates,
+                                                       0)) != json_type_array;
 }
 
 /************************************************************************/
@@ -71,8 +116,8 @@ static bool OGRGeoJSONIsPatchablePosition( json_object* poJSonCoordinates,
 static void OGRGeoJSONPatchPosition( json_object* poJSonCoordinates,
                                      json_object* poNativeCoordinates )
 {
-    int nLength = json_object_array_length(poNativeCoordinates);
-    for(int i=3; i<nLength;i++)
+    const int nLength = json_object_array_length(poNativeCoordinates);
+    for( int i = 3; i < nLength; i++ )
     {
         json_object_array_add(poJSonCoordinates,
             json_object_get(
@@ -86,13 +131,62 @@ static void OGRGeoJSONPatchPosition( json_object* poJSonCoordinates,
 
 static bool OGRGeoJSONIsPatchableArray( json_object* poJSonArray,
                                         json_object* poNativeArray,
-                                        int nDepth,
-                                        bool bLightCheck )
+                                        int nDepth )
 {
     if( nDepth == 0 )
         return OGRGeoJSONIsPatchablePosition(poJSonArray, poNativeArray);
 
-    int nLength;
+    int nLength = 0;
+    if( json_object_get_type(poJSonArray) == json_type_array &&
+        json_object_get_type(poNativeArray) == json_type_array &&
+        (nLength = json_object_array_length(poJSonArray)) ==
+                            json_object_array_length(poNativeArray) )
+    {
+        if( nLength > 0 )
+        {
+            json_object* poJSonChild =
+                json_object_array_get_idx(poJSonArray, 0);
+            json_object* poNativeChild =
+                json_object_array_get_idx(poNativeArray, 0);
+            if( !OGRGeoJSONIsPatchableArray(poJSonChild, poNativeChild,
+                                            nDepth - 1) )
+            {
+                return false;
+            }
+            // Light check as a former extensive check was done in
+            // OGRGeoJSONComputePatchableOrCompatibleArray
+        }
+        return true;
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                OGRGeoJSONComputePatchableOrCompatibleArray()         */
+/************************************************************************/
+
+/* Returns true if the objects are comparable, ie Point vs Point, LineString
+   vs LineString, but they might not be patchable or compatible */
+static bool OGRGeoJSONComputePatchableOrCompatibleArrayInternal(
+                                                    json_object* poJSonArray,
+                                                    json_object* poNativeArray,
+                                                    int nDepth,
+                                                    bool& bOutPatchable,
+                                                    bool& bOutCompatible)
+{
+    if( nDepth == 0 )
+    {
+        bOutPatchable &= OGRGeoJSONIsPatchablePosition(poJSonArray, poNativeArray);
+        bOutCompatible &= OGRGeoJSONIsCompatiblePosition(poJSonArray, poNativeArray);
+        return json_object_get_type(poJSonArray) == json_type_array &&
+               json_object_get_type(poNativeArray) == json_type_array &&
+               json_object_get_type(json_object_array_get_idx(poJSonArray,
+                                                            0)) != json_type_array &&
+               json_object_get_type(json_object_array_get_idx(poNativeArray,
+                                                            0)) != json_type_array;
+    }
+
+    int nLength = 0;
     if( json_object_get_type(poJSonArray) == json_type_array &&
         json_object_get_type(poNativeArray) == json_type_array &&
         (nLength = json_object_array_length(poJSonArray)) ==
@@ -104,17 +198,42 @@ static bool OGRGeoJSONIsPatchableArray( json_object* poJSonArray,
                 json_object_array_get_idx(poJSonArray, i);
             json_object* poNativeChild =
                 json_object_array_get_idx(poNativeArray, i);
-            if( !OGRGeoJSONIsPatchableArray(poJSonChild, poNativeChild,
-                                            nDepth - 1, bLightCheck) )
+            if( !OGRGeoJSONComputePatchableOrCompatibleArrayInternal(poJSonChild,
+                                                   poNativeChild,
+                                                   nDepth - 1,
+                                                   bOutPatchable,
+                                                   bOutCompatible) )
             {
                 return false;
             }
-            if( bLightCheck )
+            if (!bOutPatchable && !bOutCompatible)
                 break;
         }
         return true;
     }
-    return false;
+    else
+    {
+        bOutPatchable = false;
+        bOutCompatible = false;
+        return false;
+    }
+}
+
+/* Returns true if the objects are comparable, ie Point vs Point, LineString
+   vs LineString, but they might not be patchable or compatible */
+static bool OGRGeoJSONComputePatchableOrCompatibleArray( json_object* poJSonArray,
+                                                    json_object* poNativeArray,
+                                                    int nDepth,
+                                                    bool& bOutPatchable,
+                                                    bool& bOutCompatible)
+{
+    bOutPatchable = true;
+    bOutCompatible = true;
+    return OGRGeoJSONComputePatchableOrCompatibleArrayInternal(poJSonArray,
+                                                          poNativeArray,
+                                                          nDepth,
+                                                          bOutPatchable,
+                                                          bOutCompatible);
 }
 
 /************************************************************************/
@@ -130,11 +249,12 @@ static void OGRGeoJSONPatchArray( json_object* poJSonArray,
         OGRGeoJSONPatchPosition(poJSonArray, poNativeArray);
         return;
     }
-    int nLength = json_object_array_length(poJSonArray);
-    for(int i=0; i<nLength;i++)
+    const int nLength = json_object_array_length(poJSonArray);
+    for( int i = 0; i<nLength; i++ )
     {
         json_object* poJSonChild = json_object_array_get_idx(poJSonArray, i);
-        json_object* poNativeChild = json_object_array_get_idx(poNativeArray, i);
+        json_object* poNativeChild =
+            json_object_array_get_idx(poNativeArray, i);
         OGRGeoJSONPatchArray(poJSonChild, poNativeChild,nDepth-1);
     }
 }
@@ -144,7 +264,9 @@ static void OGRGeoJSONPatchArray( json_object* poJSonArray,
 /************************************************************************/
 
 static bool OGRGeoJSONIsPatchableGeometry( json_object* poJSonGeometry,
-                                           json_object* poNativeGeometry )
+                                           json_object* poNativeGeometry,
+                                           bool& bOutPatchableCoords,
+                                           bool& bOutCompatibleCoords )
 {
     if( json_object_get_type(poJSonGeometry) != json_type_object ||
         json_object_get_type(poNativeGeometry) != json_type_object )
@@ -152,6 +274,17 @@ static bool OGRGeoJSONIsPatchableGeometry( json_object* poJSonGeometry,
         return false;
     }
 
+    json_object* poType = CPL_json_object_object_get(poJSonGeometry, "type");
+    json_object* poNativeType = CPL_json_object_object_get(poNativeGeometry, "type");
+    if( poType == NULL || poNativeType == NULL ||
+        json_object_get_type(poType) != json_type_string ||
+        json_object_get_type(poNativeType) != json_type_string ||
+        strcmp(json_object_get_string(poType),
+               json_object_get_string(poNativeType)) != 0 )
+    {
+        return false;
+    }
+
     json_object_iter it;
     it.key = NULL;
     it.val = NULL;
@@ -161,18 +294,21 @@ static bool OGRGeoJSONIsPatchableGeometry( json_object* poJSonGeometry,
         if( strcmp(it.key, "coordinates") == 0 )
         {
             json_object* poJSonCoordinates =
-                    json_object_object_get(poJSonGeometry, "coordinates");
+                CPL_json_object_object_get(poJSonGeometry, "coordinates");
             json_object* poNativeCoordinates = it.val;
             // 0 = Point
             // 1 = LineString or MultiPoint
             // 2 = MultiLineString or Polygon
             // 3 = MultiPolygon
-            for(int i=0;i<=3;i++)
+            for( int i = 0; i <= 3; i++ )
             {
-                if( OGRGeoJSONIsPatchableArray(poJSonCoordinates,
-                                               poNativeCoordinates, i, false) )
+                if( OGRGeoJSONComputePatchableOrCompatibleArray(poJSonCoordinates,
+                                                       poNativeCoordinates,
+                                                       i,
+                                                       bOutPatchableCoords,
+                                                       bOutCompatibleCoords) )
                 {
-                    return true;
+                    return bOutPatchableCoords || bOutCompatibleCoords;
                 }
             }
             return false;
@@ -180,9 +316,9 @@ static bool OGRGeoJSONIsPatchableGeometry( json_object* poJSonGeometry,
         if( strcmp(it.key, "geometries") == 0 )
         {
             json_object* poJSonGeometries =
-                    json_object_object_get(poJSonGeometry, "geometries");
+                CPL_json_object_object_get(poJSonGeometry, "geometries");
             json_object* poNativeGeometries = it.val;
-            int nLength;
+            int nLength = 0;
             if( json_object_get_type(poJSonGeometries) == json_type_array &&
                 json_object_get_type(poNativeGeometries) == json_type_array &&
                 (nLength = json_object_array_length(poJSonGeometries)) ==
@@ -194,7 +330,10 @@ static bool OGRGeoJSONIsPatchableGeometry( json_object* poJSonGeometry,
                         json_object_array_get_idx(poJSonGeometries, i);
                     json_object* poNativeChild =
                         json_object_array_get_idx(poNativeGeometries, i);
-                    if( !OGRGeoJSONIsPatchableGeometry(poJSonChild, poNativeChild) )
+                    if( !OGRGeoJSONIsPatchableGeometry(poJSonChild,
+                                                       poNativeChild,
+                                                       bOutPatchableCoords,
+                                                       bOutCompatibleCoords) )
                     {
                         return false;
                     }
@@ -212,7 +351,9 @@ static bool OGRGeoJSONIsPatchableGeometry( json_object* poJSonGeometry,
 /************************************************************************/
 
 static void OGRGeoJSONPatchGeometry( json_object* poJSonGeometry,
-                                     json_object* poNativeGeometry )
+                                     json_object* poNativeGeometry,
+                                     bool bPatchableCoordinates,
+                                     const OGRGeoJSONWriteOptions& oOptions )
 {
     json_object_iter it;
     it.key = NULL;
@@ -227,13 +368,19 @@ static void OGRGeoJSONPatchGeometry( json_object* poJSonGeometry,
         }
         if( strcmp(it.key, "coordinates") == 0 )
         {
+            if( !bPatchableCoordinates &&
+                !oOptions.bCanPatchCoordinatesWithNativeData )
+            {
+                continue;
+            }
+
             json_object* poJSonCoordinates =
-                json_object_object_get(poJSonGeometry, "coordinates");
+                CPL_json_object_object_get(poJSonGeometry, "coordinates");
             json_object* poNativeCoordinates = it.val;
-            for(int i=0;i<=3;i++)
+            for( int i = 0; i <= 3; i++ )
             {
                 if( OGRGeoJSONIsPatchableArray(poJSonCoordinates,
-                                               poNativeCoordinates, i, true) )
+                                               poNativeCoordinates, i) )
                 {
                     OGRGeoJSONPatchArray(poJSonCoordinates,
                                          poNativeCoordinates, i);
@@ -246,7 +393,7 @@ static void OGRGeoJSONPatchGeometry( json_object* poJSonGeometry,
         if( strcmp(it.key, "geometries") == 0 )
         {
             json_object* poJSonGeometries =
-                json_object_object_get(poJSonGeometry, "geometries");
+                CPL_json_object_object_get(poJSonGeometry, "geometries");
             json_object* poNativeGeometries = it.val;
             int nLength = json_object_array_length(poJSonGeometries);
             for( int i=0; i < nLength; i++ )
@@ -255,26 +402,119 @@ static void OGRGeoJSONPatchGeometry( json_object* poJSonGeometry,
                     json_object_array_get_idx(poJSonGeometries, i);
                 json_object* poNativeChild =
                     json_object_array_get_idx(poNativeGeometries, i);
-                OGRGeoJSONPatchGeometry(poJSonChild, poNativeChild);
+                OGRGeoJSONPatchGeometry(poJSonChild, poNativeChild,
+                                        bPatchableCoordinates, oOptions);
             }
 
             continue;
         }
 
+        // See https://tools.ietf.org/html/rfc7946#section-7.1
+        if( oOptions.bHonourReservedRFC7946Members &&
+            (strcmp(it.key, "geometry") == 0 ||
+             strcmp(it.key, "properties") == 0 ||
+             strcmp(it.key, "features") == 0) )
+        {
+            continue;
+        }
+
         json_object_object_add( poJSonGeometry, it.key,
                                 json_object_get(it.val) );
     }
 }
 
 /************************************************************************/
+/*                           OGRGeoJSONGetBBox                          */
+/************************************************************************/
+
+OGREnvelope3D OGRGeoJSONGetBBox( OGRGeometry* poGeometry,
+                                 const OGRGeoJSONWriteOptions& oOptions )
+{
+    OGREnvelope3D sEnvelope;
+    poGeometry->getEnvelope(&sEnvelope);
+
+    if( oOptions.bBBOXRFC7946 )
+    {
+        // Heuristics to determine if the geometry was split along the
+        // date line.
+        const double EPS = 1e-7;
+        const OGRwkbGeometryType eType =
+                        wkbFlatten(poGeometry->getGeometryType());
+        if( OGR_GT_IsSubClassOf(eType, wkbGeometryCollection) &&
+            reinterpret_cast<OGRGeometryCollection*>(poGeometry)->
+                                            getNumGeometries() >= 2 &&
+            fabs(sEnvelope.MinX - (-180.0)) < EPS &&
+            fabs(sEnvelope.MaxX - 180.0) < EPS )
+        {
+            OGRGeometryCollection* poGC =
+                reinterpret_cast<OGRGeometryCollection*>(poGeometry);
+            double dfWestLimit = -180.0;
+            double dfEastLimit = 180.0;
+            bool bWestLimitIsInit = false;
+            bool bEastLimitIsInit = false;
+            for( int i=0; i < poGC->getNumGeometries(); ++i )
+            {
+                OGREnvelope sEnvelopePart;
+                poGC->getGeometryRef(i)->getEnvelope(&sEnvelopePart);
+                const bool bTouchesMinus180 =
+                            fabs(sEnvelopePart.MinX - (-180.0)) < EPS;
+                const bool bTouchesPlus180 =
+                            fabs(sEnvelopePart.MaxX - 180.0) < EPS;
+                if( bTouchesMinus180 && !bTouchesPlus180 )
+                {
+                    if( sEnvelopePart.MaxX > dfEastLimit ||
+                        !bEastLimitIsInit )
+                    {
+                        bEastLimitIsInit = true;
+                        dfEastLimit = sEnvelopePart.MaxX;
+                    }
+                }
+                else if( bTouchesPlus180 && !bTouchesMinus180 )
+                {
+                    if( sEnvelopePart.MinX < dfWestLimit ||
+                        !bWestLimitIsInit )
+                    {
+                        bWestLimitIsInit = true;
+                        dfWestLimit = sEnvelopePart.MinX;
+                    }
+                }
+                else if( !bTouchesMinus180 && !bTouchesPlus180 )
+                {
+                    if( sEnvelopePart.MinX > 0 &&
+                        (sEnvelopePart.MinX < dfWestLimit ||
+                            !bWestLimitIsInit))
+                    {
+                        bWestLimitIsInit = true;
+                        dfWestLimit = sEnvelopePart.MinX;
+                    }
+                    else if ( sEnvelopePart.MaxX < 0 &&
+                                (sEnvelopePart.MaxX > dfEastLimit ||
+                                !bEastLimitIsInit) )
+                    {
+                        bEastLimitIsInit = true;
+                        dfEastLimit = sEnvelopePart.MaxX;
+                    }
+                }
+            }
+            sEnvelope.MinX = dfWestLimit;
+            sEnvelope.MaxX = dfEastLimit;
+        }
+    }
+
+    return sEnvelope;
+}
+
+/************************************************************************/
 /*                           OGRGeoJSONWriteFeature                     */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX,
-                                     int nCoordPrecision, int nSignificantFigures )
+json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature,
+                                     const OGRGeoJSONWriteOptions& oOptions )
 {
     CPLAssert( NULL != poFeature );
 
+    bool bWriteBBOX = oOptions.bWriteBBOX;
+
     json_object* poObj = json_object_new_object();
     CPLAssert( NULL != poObj );
 
@@ -287,7 +527,10 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX,
     bool bIdAlreadyWritten = false;
     const char* pszNativeMediaType = poFeature->GetNativeMediaType();
     json_object* poNativeGeom = NULL;
-    if( pszNativeMediaType && EQUAL(pszNativeMediaType, "application/vnd.geo+json") )
+    json_object* poNativeId = NULL;
+    bool bHasProperties = true;
+    if( pszNativeMediaType &&
+        EQUAL(pszNativeMediaType, "application/vnd.geo+json") )
     {
         const char* pszNativeData = poFeature->GetNativeData();
         json_object* poNativeJSon = NULL;
@@ -299,13 +542,18 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX,
             it.val = NULL;
             it.entry = NULL;
             CPLString osNativeData;
+            bHasProperties = false;
             json_object_object_foreachC(poNativeJSon, it)
             {
-                if( strcmp(it.key, "type") == 0 ||
-                    strcmp(it.key, "properties") == 0 )
+                if( strcmp(it.key, "type") == 0 )
                 {
                     continue;
                 }
+                if( strcmp(it.key, "properties") == 0 )
+                {
+                    bHasProperties = true;
+                    continue;
+                }
                 if( strcmp(it.key, "bbox") == 0 )
                 {
                     bWriteBBOX = true;
@@ -317,7 +565,29 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX,
                     continue;
                 }
                 if( strcmp(it.key, "id") == 0 )
+                {
+                    // See https://tools.ietf.org/html/rfc7946#section-3.2
+                    if( oOptions.bHonourReservedRFC7946Members &&
+                        json_object_get_type(it.val) != json_type_string &&
+                        json_object_get_type(it.val) != json_type_int &&
+                        json_object_get_type(it.val) != json_type_double )
+                    {
+                        continue;
+                    }
+
                     bIdAlreadyWritten = true;
+                    poNativeId = it.val;
+                }
+
+                // See https://tools.ietf.org/html/rfc7946#section-7.1
+                if( oOptions.bHonourReservedRFC7946Members &&
+                    (strcmp(it.key, "coordinates") == 0 ||
+                     strcmp(it.key, "geometries") == 0 ||
+                     strcmp(it.key, "features") == 0) )
+                {
+                    continue;
+                }
+
                 json_object_object_add( poObj, it.key,
                                         json_object_get(it.val) );
             }
@@ -328,7 +598,7 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX,
 /* -------------------------------------------------------------------- */
 /*      Write FID if available                                          */
 /* -------------------------------------------------------------------- */
-    if ( poFeature->GetFID() != OGRNullFID && !bIdAlreadyWritten )
+    if( poFeature->GetFID() != OGRNullFID && !bIdAlreadyWritten )
     {
         json_object_object_add( poObj, "id",
                                 json_object_new_int64(poFeature->GetFID()) );
@@ -337,9 +607,33 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX,
 /* -------------------------------------------------------------------- */
 /*      Write feature attributes to GeoJSON "properties" object.        */
 /* -------------------------------------------------------------------- */
-    json_object* poObjProps
-        = OGRGeoJSONWriteAttributes( poFeature, nSignificantFigures );
-    json_object_object_add( poObj, "properties", poObjProps );
+    bool bWriteIdIfFoundInAttributes = true;
+    if( bIdAlreadyWritten && poNativeId != NULL )
+    {
+        int nIdx = poFeature->GetFieldIndex("id");
+        if( json_object_get_type(poNativeId) == json_type_string &&
+            nIdx >= 0 &&
+            poFeature->GetFieldDefnRef(nIdx)->GetType() == OFTString &&
+            strcmp(json_object_get_string(poNativeId), poFeature->GetFieldAsString(nIdx)) == 0 )
+        {
+            bWriteIdIfFoundInAttributes = false;
+        }
+        else if ( json_object_get_type(poNativeId) == json_type_int &&
+                  nIdx >= 0 &&
+                  (poFeature->GetFieldDefnRef(nIdx)->GetType() == OFTInteger ||
+                   poFeature->GetFieldDefnRef(nIdx)->GetType() == OFTInteger64) &&
+                  json_object_get_int64(poNativeId) == poFeature->GetFieldAsInteger64(nIdx) )
+        {
+            bWriteIdIfFoundInAttributes = false;
+        }
+    }
+
+    if( bHasProperties )
+    {
+        json_object* poObjProps
+            = OGRGeoJSONWriteAttributes( poFeature, bWriteIdIfFoundInAttributes, oOptions );
+        json_object_object_add( poObj, "properties", poObjProps );
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Write feature geometry to GeoJSON "geometry" object.            */
@@ -348,37 +642,47 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX,
     json_object* poObjGeom = NULL;
 
     OGRGeometry* poGeometry = poFeature->GetGeometryRef();
-    if ( NULL != poGeometry )
+    if( NULL != poGeometry )
     {
-        poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision, nSignificantFigures );
+        poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, oOptions );
 
-        if ( bWriteBBOX && !poGeometry->IsEmpty() )
+        if( bWriteBBOX && !poGeometry->IsEmpty() )
         {
-            OGREnvelope3D sEnvelope;
-            poGeometry->getEnvelope(&sEnvelope);
+            OGREnvelope3D sEnvelope = OGRGeoJSONGetBBox( poGeometry, oOptions );
 
             json_object* poObjBBOX = json_object_new_array();
-            json_object_array_add(poObjBBOX,
-                            json_object_new_coord(sEnvelope.MinX, nCoordPrecision, nSignificantFigures));
-            json_object_array_add(poObjBBOX,
-                            json_object_new_coord(sEnvelope.MinY, nCoordPrecision, nSignificantFigures));
-            if (poGeometry->getCoordinateDimension() == 3)
-                json_object_array_add(poObjBBOX,
-                            json_object_new_coord(sEnvelope.MinZ, nCoordPrecision, nSignificantFigures));
-            json_object_array_add(poObjBBOX,
-                            json_object_new_coord(sEnvelope.MaxX, nCoordPrecision, nSignificantFigures));
-            json_object_array_add(poObjBBOX,
-                            json_object_new_coord(sEnvelope.MaxY, nCoordPrecision, nSignificantFigures));
-            if (poGeometry->getCoordinateDimension() == 3)
-                json_object_array_add(poObjBBOX,
-                            json_object_new_coord(sEnvelope.MaxZ, nCoordPrecision, nSignificantFigures));
+            json_object_array_add(
+                poObjBBOX,
+                json_object_new_coord(sEnvelope.MinX, oOptions));
+            json_object_array_add(
+                poObjBBOX,
+                json_object_new_coord(sEnvelope.MinY, oOptions));
+            if( poGeometry->getCoordinateDimension() == 3 )
+                json_object_array_add(
+                    poObjBBOX,
+                    json_object_new_coord(sEnvelope.MinZ, oOptions));
+            json_object_array_add(
+                poObjBBOX,
+                json_object_new_coord(sEnvelope.MaxX, oOptions));
+            json_object_array_add(
+                poObjBBOX,
+                json_object_new_coord(sEnvelope.MaxY, oOptions));
+            if( poGeometry->getCoordinateDimension() == 3 )
+                json_object_array_add(
+                    poObjBBOX,
+                    json_object_new_coord(sEnvelope.MaxZ, oOptions));
 
             json_object_object_add( poObj, "bbox", poObjBBOX );
         }
 
-        if( OGRGeoJSONIsPatchableGeometry( poObjGeom, poNativeGeom ) )
+        bool bOutPatchableCoords = false;
+        bool bOutCompatibleCoords = false;
+        if( OGRGeoJSONIsPatchableGeometry( poObjGeom, poNativeGeom,
+                                           bOutPatchableCoords,
+                                           bOutCompatibleCoords ) )
         {
-            OGRGeoJSONPatchGeometry( poObjGeom, poNativeGeom );
+            OGRGeoJSONPatchGeometry( poObjGeom, poNativeGeom,
+                                     bOutPatchableCoords, oOptions );
         }
     }
 
@@ -391,10 +695,12 @@ json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX,
 }
 
 /************************************************************************/
-/*                           OGRGeoJSONWriteGeometry                    */
+/*                        OGRGeoJSONWriteAttributes                     */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature, int nSignificantFigures )
+json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature,
+                                        bool bWriteIdIfFoundInAttributes,
+                                        const OGRGeoJSONWriteOptions& oOptions )
 {
     CPLAssert( NULL != poFeature );
 
@@ -404,16 +710,27 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature, int nSignificantF
     OGRFeatureDefn* poDefn = poFeature->GetDefnRef();
     for( int nField = 0; nField < poDefn->GetFieldCount(); ++nField )
     {
+        if( !poFeature->IsFieldSet(nField) )
+        {
+            continue;
+        }
+
         OGRFieldDefn* poFieldDefn = poDefn->GetFieldDefn( nField );
         CPLAssert( NULL != poFieldDefn );
         OGRFieldType eType = poFieldDefn->GetType();
         OGRFieldSubType eSubType = poFieldDefn->GetSubType();
 
-        json_object* poObjProp;
+        if( !bWriteIdIfFoundInAttributes &&
+            strcmp(poFieldDefn->GetNameRef(), "id") == 0 )
+        {
+            continue;
+        }
 
-        if( !poFeature->IsFieldSet(nField) )
+        json_object* poObjProp = NULL;
+
+        if( poFeature->IsFieldNull(nField) )
         {
-            poObjProp = NULL;
+            // poObjProp = NULL;
         }
         else if( OFTInteger == eType )
         {
@@ -436,7 +753,8 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature, int nSignificantF
         else if( OFTReal == eType )
         {
             poObjProp = json_object_new_double_with_significant_figures(
-                poFeature->GetFieldAsDouble(nField), nSignificantFigures );
+                poFeature->GetFieldAsDouble(nField),
+                oOptions.nSignificantFigures );
         }
         else if( OFTString == eType )
         {
@@ -454,58 +772,70 @@ json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature, int nSignificantF
         else if( OFTIntegerList == eType )
         {
             int nSize = 0;
-            const int* panList = poFeature->GetFieldAsIntegerList(nField, &nSize);
+            const int* panList =
+                poFeature->GetFieldAsIntegerList(nField, &nSize);
             poObjProp = json_object_new_array();
-            for(int i=0;i<nSize;i++)
+            for( int i = 0; i < nSize; i++ )
             {
                 if( eSubType == OFSTBoolean )
-                    json_object_array_add(poObjProp,
-                            json_object_new_boolean(panList[i]));
+                    json_object_array_add(
+                        poObjProp,
+                        json_object_new_boolean(panList[i]));
                 else
-                    json_object_array_add(poObjProp,
-                            json_object_new_int(panList[i]));
+                    json_object_array_add(
+                        poObjProp,
+                        json_object_new_int(panList[i]));
             }
         }
         else if( OFTInteger64List == eType )
         {
             int nSize = 0;
-            const GIntBig* panList = poFeature->GetFieldAsInteger64List(nField, &nSize);
+            const GIntBig* panList =
+                poFeature->GetFieldAsInteger64List(nField, &nSize);
             poObjProp = json_object_new_array();
-            for(int i=0;i<nSize;i++)
+            for( int i = 0; i < nSize; i++ )
             {
                 if( eSubType == OFSTBoolean )
-                    json_object_array_add(poObjProp,
-                            json_object_new_boolean((json_bool)panList[i]));
+                    json_object_array_add(
+                        poObjProp,
+                        json_object_new_boolean(
+                            static_cast<json_bool>(panList[i])));
                 else
-                    json_object_array_add(poObjProp,
-                            json_object_new_int64(panList[i]));
+                    json_object_array_add(
+                        poObjProp,
+                        json_object_new_int64(panList[i]));
             }
         }
         else if( OFTRealList == eType )
         {
             int nSize = 0;
-            const double* padfList = poFeature->GetFieldAsDoubleList(nField, &nSize);
+            const double* padfList =
+                poFeature->GetFieldAsDoubleList(nField, &nSize);
             poObjProp = json_object_new_array();
-            for(int i=0;i<nSize;i++)
+            for( int i = 0; i < nSize; i++ )
             {
-                json_object_array_add(poObjProp,
-                            json_object_new_double_with_significant_figures(padfList[i], nSignificantFigures));
+                json_object_array_add(
+                    poObjProp,
+                    json_object_new_double_with_significant_figures(
+                        padfList[i],
+                        oOptions.nSignificantFigures));
             }
         }
         else if( OFTStringList == eType )
         {
             char** papszStringList = poFeature->GetFieldAsStringList(nField);
             poObjProp = json_object_new_array();
-            for(int i=0; papszStringList && papszStringList[i]; i++)
+            for( int i = 0; papszStringList && papszStringList[i]; i++ )
             {
-                json_object_array_add(poObjProp,
-                            json_object_new_string(papszStringList[i]));
+                json_object_array_add(
+                    poObjProp,
+                    json_object_new_string(papszStringList[i]));
             }
         }
         else
         {
             poObjProp = json_object_new_string(
-                 poFeature->GetFieldAsString(nField) );
+                poFeature->GetFieldAsString(nField) );
         }
 
         json_object_object_add( poObjProps,
@@ -524,12 +854,25 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry,
                                       int nCoordPrecision,
                                       int nSignificantFigures )
 {
-    CPLAssert( NULL != poGeometry );
+    OGRGeoJSONWriteOptions oOptions;
+    oOptions.nCoordPrecision = nCoordPrecision;
+    oOptions.nSignificantFigures = nSignificantFigures;
+    return OGRGeoJSONWriteGeometry( poGeometry, oOptions );
+}
+
+json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry,
+                                      const OGRGeoJSONWriteOptions& oOptions )
+{
+    if( poGeometry == NULL )
+    {
+        CPLAssert( false );
+        return NULL;
+    }
 
     OGRwkbGeometryType eType = poGeometry->getGeometryType();
-    /* For point empty, return a null geometry. For other empty geometry types, */
-    /* we will generate an empty coordinate array, which is propably also */
-    /* borderline. */
+    // For point empty, return a null geometry. For other empty geometry types,
+    // we will generate an empty coordinate array, which is propably also
+    // borderline.
     if( (wkbPoint == eType || wkbPoint25D == eType) && poGeometry->IsEmpty() )
     {
         return NULL;
@@ -553,31 +896,53 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry,
 
     if( wkbGeometryCollection == eType || wkbGeometryCollection25D == eType )
     {
-        poObjGeom = OGRGeoJSONWriteGeometryCollection( static_cast<OGRGeometryCollection*>(poGeometry), nCoordPrecision, nSignificantFigures );
+        poObjGeom =
+            OGRGeoJSONWriteGeometryCollection(
+                static_cast<OGRGeometryCollection*>(poGeometry), oOptions );
         json_object_object_add( poObj, "geometries", poObjGeom);
     }
     else
     {
         if( wkbPoint == eType || wkbPoint25D == eType )
-            poObjGeom = OGRGeoJSONWritePoint( static_cast<OGRPoint*>(poGeometry), nCoordPrecision, nSignificantFigures );
+            poObjGeom =
+                OGRGeoJSONWritePoint( static_cast<OGRPoint*>(poGeometry),
+                                      oOptions );
         else if( wkbLineString == eType || wkbLineString25D == eType )
-            poObjGeom = OGRGeoJSONWriteLineString( static_cast<OGRLineString*>(poGeometry), nCoordPrecision, nSignificantFigures );
+            poObjGeom =
+                OGRGeoJSONWriteLineString(
+                    static_cast<OGRLineString*>(poGeometry), oOptions );
         else if( wkbPolygon == eType || wkbPolygon25D == eType )
-            poObjGeom = OGRGeoJSONWritePolygon( static_cast<OGRPolygon*>(poGeometry), nCoordPrecision, nSignificantFigures );
+            poObjGeom =
+                OGRGeoJSONWritePolygon( static_cast<OGRPolygon*>(poGeometry),
+                                        oOptions );
         else if( wkbMultiPoint == eType || wkbMultiPoint25D == eType )
-            poObjGeom = OGRGeoJSONWriteMultiPoint( static_cast<OGRMultiPoint*>(poGeometry), nCoordPrecision, nSignificantFigures );
+            poObjGeom =
+                OGRGeoJSONWriteMultiPoint(
+                    static_cast<OGRMultiPoint*>(poGeometry), oOptions );
         else if( wkbMultiLineString == eType || wkbMultiLineString25D == eType )
-            poObjGeom = OGRGeoJSONWriteMultiLineString( static_cast<OGRMultiLineString*>(poGeometry), nCoordPrecision, nSignificantFigures );
+            poObjGeom =
+                OGRGeoJSONWriteMultiLineString(
+                    static_cast<OGRMultiLineString*>(poGeometry), oOptions );
         else if( wkbMultiPolygon == eType || wkbMultiPolygon25D == eType )
-            poObjGeom = OGRGeoJSONWriteMultiPolygon( static_cast<OGRMultiPolygon*>(poGeometry), nCoordPrecision, nSignificantFigures );
+            poObjGeom =
+                OGRGeoJSONWriteMultiPolygon(
+                    static_cast<OGRMultiPolygon*>(poGeometry), oOptions );
         else
         {
             CPLDebug( "GeoJSON",
-                "Unsupported geometry type detected. "
-                "Feature gets NULL geometry assigned." );
+                      "Unsupported geometry type detected. "
+                      "Feature gets NULL geometry assigned." );
         }
 
-        json_object_object_add( poObj, "coordinates", poObjGeom);
+        if( poObjGeom != NULL )
+        {
+            json_object_object_add( poObj, "coordinates", poObjGeom);
+        }
+        else
+        {
+            json_object_put(poObj);
+            poObj = NULL;
+        }
     }
 
     return poObj;
@@ -587,25 +952,26 @@ json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry,
 /*                           OGRGeoJSONWritePoint                       */
 /************************************************************************/
 
-json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision, int nSignificantFigures )
+json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint,
+                                   const OGRGeoJSONWriteOptions& oOptions )
 {
     CPLAssert( NULL != poPoint );
 
     json_object* poObj = NULL;
 
-    /* Generate "coordinates" object for 2D or 3D dimension. */
+    // Generate "coordinates" object for 2D or 3D dimension.
     if( 3 == poPoint->getCoordinateDimension() )
     {
         poObj = OGRGeoJSONWriteCoords( poPoint->getX(),
                                        poPoint->getY(),
                                        poPoint->getZ(),
-                                       nCoordPrecision, nSignificantFigures );
+                                       oOptions );
     }
     else if( 2 == poPoint->getCoordinateDimension() )
     {
         poObj = OGRGeoJSONWriteCoords( poPoint->getX(),
                                        poPoint->getY(),
-                                       nCoordPrecision, nSignificantFigures );
+                                       oOptions );
     }
 
     return poObj;
@@ -616,13 +982,13 @@ json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision, int n
 /************************************************************************/
 
 json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine,
-                                        int nCoordPrecision, int nSignificantFigures )
+                                        const OGRGeoJSONWriteOptions& oOptions )
 {
     CPLAssert( NULL != poLine );
 
-    /* Generate "coordinates" object for 2D or 3D dimension. */
-    json_object* poObj = NULL;
-    poObj = OGRGeoJSONWriteLineCoords( poLine, nCoordPrecision, nSignificantFigures );
+    // Generate "coordinates" object for 2D or 3D dimension.
+    json_object* poObj =
+        OGRGeoJSONWriteLineCoords( poLine, oOptions );
 
     return poObj;
 }
@@ -632,20 +998,20 @@ json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine,
 /************************************************************************/
 
 json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon,
-                                     int nCoordPrecision, int nSignificantFigures )
+                                     const OGRGeoJSONWriteOptions& oOptions )
 {
     CPLAssert( NULL != poPolygon );
 
-    /* Generate "coordinates" array object. */
+    // Generate "coordinates" array object.
     json_object* poObj = json_object_new_array();
 
-    /* Exterior ring. */
+    // Exterior ring.
     OGRLinearRing* poRing = poPolygon->getExteriorRing();
-    if (poRing == NULL)
+    if( poRing == NULL )
         return poObj;
 
-    json_object* poObjRing
-        = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision, nSignificantFigures );
+    json_object* poObjRing =
+        OGRGeoJSONWriteRingCoords( poRing, true, oOptions );
     if( poObjRing == NULL )
     {
         json_object_put(poObj);
@@ -653,15 +1019,16 @@ json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon,
     }
     json_object_array_add( poObj, poObjRing );
 
-    /* Interior rings. */
+    // Interior rings.
     const int nCount = poPolygon->getNumInteriorRings();
     for( int i = 0; i < nCount; ++i )
     {
         poRing = poPolygon->getInteriorRing( i );
-        if (poRing == NULL)
+        if( poRing == NULL )
             continue;
 
-        poObjRing = OGRGeoJSONWriteLineCoords( poRing, nCoordPrecision, nSignificantFigures );
+        poObjRing =
+            OGRGeoJSONWriteRingCoords( poRing, false, oOptions );
         if( poObjRing == NULL )
         {
             json_object_put(poObj);
@@ -679,11 +1046,11 @@ json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon,
 /************************************************************************/
 
 json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry,
-                                        int nCoordPrecision, int nSignificantFigures )
+                                        const OGRGeoJSONWriteOptions& oOptions )
 {
     CPLAssert( NULL != poGeometry );
 
-    /* Generate "coordinates" object for 2D or 3D dimension. */
+    // Generate "coordinates" object for 2D or 3D dimension.
     json_object* poObj
         = json_object_new_array();
 
@@ -693,8 +1060,8 @@ json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry,
         CPLAssert( NULL != poGeom );
         OGRPoint* poPoint = static_cast<OGRPoint*>(poGeom);
 
-        json_object* poObjPoint
-            = OGRGeoJSONWritePoint( poPoint, nCoordPrecision, nSignificantFigures );
+        json_object* poObjPoint =
+            OGRGeoJSONWritePoint(poPoint, oOptions);
         if( poObjPoint == NULL )
         {
             json_object_put(poObj);
@@ -712,11 +1079,11 @@ json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry,
 /************************************************************************/
 
 json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry,
-                                             int nCoordPrecision, int nSignificantFigures )
+                                             const OGRGeoJSONWriteOptions& oOptions )
 {
     CPLAssert( NULL != poGeometry );
 
-    /* Generate "coordinates" object for 2D or 3D dimension. */
+    // Generate "coordinates" object for 2D or 3D dimension.
     json_object* poObj = json_object_new_array();
 
     for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
@@ -725,8 +1092,8 @@ json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry,
         CPLAssert( NULL != poGeom );
         OGRLineString* poLine = static_cast<OGRLineString*>(poGeom);
 
-        json_object* poObjLine = NULL;
-        poObjLine = OGRGeoJSONWriteLineString( poLine, nCoordPrecision, nSignificantFigures );
+        json_object* poObjLine =
+            OGRGeoJSONWriteLineString( poLine, oOptions );
         if( poObjLine == NULL )
         {
             json_object_put(poObj);
@@ -744,11 +1111,11 @@ json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry,
 /************************************************************************/
 
 json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry,
-                                          int nCoordPrecision, int nSignificantFigures )
+                                          const OGRGeoJSONWriteOptions& oOptions )
 {
     CPLAssert( NULL != poGeometry );
 
-    /* Generate "coordinates" object for 2D or 3D dimension. */
+    // Generate "coordinates" object for 2D or 3D dimension.
     json_object* poObj = json_object_new_array();
 
     for( int i = 0; i < poGeometry->getNumGeometries(); ++i )
@@ -757,8 +1124,8 @@ json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry,
         CPLAssert( NULL != poGeom );
         OGRPolygon* poPoly = static_cast<OGRPolygon*>(poGeom);
 
-        json_object* poObjPoly
-            = OGRGeoJSONWritePolygon( poPoly, nCoordPrecision, nSignificantFigures );
+        json_object* poObjPoly =
+            OGRGeoJSONWritePolygon( poPoly, oOptions );
         if( poObjPoly == NULL )
         {
             json_object_put(poObj);
@@ -775,8 +1142,8 @@ json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry,
 /*                           OGRGeoJSONWriteGeometryCollection          */
 /************************************************************************/
 
-json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry,
-                                                int nCoordPrecision, int nSignificantFigures )
+json_object* OGRGeoJSONWriteGeometryCollection(
+    OGRGeometryCollection* poGeometry, const OGRGeoJSONWriteOptions& oOptions )
 {
     CPLAssert( NULL != poGeometry );
 
@@ -788,8 +1155,8 @@ json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometr
         OGRGeometry* poGeom = poGeometry->getGeometryRef( i );
         CPLAssert( NULL != poGeom );
 
-        json_object* poObjGeom
-            = OGRGeoJSONWriteGeometry( poGeom, nCoordPrecision, nSignificantFigures );
+        json_object* poObjGeom =
+            OGRGeoJSONWriteGeometry( poGeom, oOptions );
         if( poGeom == NULL )
         {
             json_object_put(poObj);
@@ -801,41 +1168,49 @@ json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometr
 
     return poObj;
 }
+
 /************************************************************************/
 /*                           OGRGeoJSONWriteCoords                      */
 /************************************************************************/
 
 json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY,
-                                    int nCoordPrecision, int nSignificantFigures )
+                                    const OGRGeoJSONWriteOptions& oOptions )
 {
     json_object* poObjCoords = NULL;
     if( CPLIsInf(fX) || CPLIsInf(fY) ||
         CPLIsNan(fX) || CPLIsNan(fY) )
     {
-        CPLError(CE_Warning, CPLE_AppDefined, "Infinite or NaN coordinate encountered");
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Infinite or NaN coordinate encountered");
         return NULL;
     }
     poObjCoords = json_object_new_array();
-    json_object_array_add( poObjCoords, json_object_new_coord( fX, nCoordPrecision, nSignificantFigures ) );
-    json_object_array_add( poObjCoords, json_object_new_coord( fY, nCoordPrecision, nSignificantFigures ) );
+    json_object_array_add( poObjCoords,
+                           json_object_new_coord( fX, oOptions ) );
+    json_object_array_add( poObjCoords,
+                           json_object_new_coord( fY, oOptions ) );
 
     return poObjCoords;
 }
 
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ,
-                                    int nCoordPrecision, int nSignificantFigures )
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY,
+                                    double const& fZ,
+                                    const OGRGeoJSONWriteOptions& oOptions )
 {
-    json_object* poObjCoords = NULL;
     if( CPLIsInf(fX) || CPLIsInf(fY) || CPLIsInf(fZ) ||
         CPLIsNan(fX) || CPLIsNan(fY) || CPLIsNan(fZ) )
     {
-        CPLError(CE_Warning, CPLE_AppDefined, "Infinite or NaN coordinate encountered");
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Infinite or NaN coordinate encountered");
         return NULL;
     }
-    poObjCoords = json_object_new_array();
-    json_object_array_add( poObjCoords, json_object_new_coord( fX, nCoordPrecision, nSignificantFigures ) );
-    json_object_array_add( poObjCoords, json_object_new_coord( fY, nCoordPrecision, nSignificantFigures ) );
-    json_object_array_add( poObjCoords, json_object_new_coord( fZ, nCoordPrecision, nSignificantFigures ) );
+    json_object* poObjCoords = json_object_new_array();
+    json_object_array_add( poObjCoords,
+                           json_object_new_coord( fX, oOptions ) );
+    json_object_array_add( poObjCoords,
+                           json_object_new_coord( fY, oOptions ) );
+    json_object_array_add( poObjCoords,
+                           json_object_new_coord( fZ, oOptions ) );
 
     return poObjCoords;
 }
@@ -845,21 +1220,62 @@ json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double c
 /************************************************************************/
 
 json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine,
-                                        int nCoordPrecision,
-                                        int nSignificantFigures )
+                                        const OGRGeoJSONWriteOptions& oOptions )
+{
+    json_object* poObjPoint = NULL;
+    json_object* poObjCoords = json_object_new_array();
+
+    const int nCount = poLine->getNumPoints();
+    for( int i = 0; i < nCount; ++i )
+    {
+        if( poLine->getCoordinateDimension() == 2 )
+            poObjPoint =
+                OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i),
+                                       oOptions );
+        else
+            poObjPoint =
+                OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i),
+                                       poLine->getZ(i),
+                                       oOptions );
+        if( poObjPoint == NULL )
+        {
+            json_object_put(poObjCoords);
+            return NULL;
+        }
+        json_object_array_add( poObjCoords, poObjPoint );
+    }
+
+    return poObjCoords;
+}
+
+/************************************************************************/
+/*                        OGRGeoJSONWriteRingCoords                     */
+/************************************************************************/
+
+json_object* OGRGeoJSONWriteRingCoords( OGRLinearRing* poLine,
+                                        bool bIsExteriorRing,
+                                        const OGRGeoJSONWriteOptions& oOptions )
 {
     json_object* poObjPoint = NULL;
     json_object* poObjCoords = json_object_new_array();
 
+    bool bInvertOrder = oOptions.bPolygonRightHandRule &&
+                        ((bIsExteriorRing && poLine->isClockwise()) ||
+                         (!bIsExteriorRing && !poLine->isClockwise()));
+
     const int nCount = poLine->getNumPoints();
     for( int i = 0; i < nCount; ++i )
     {
+        const int nIdx = (bInvertOrder) ? nCount - 1 - i: i;
         if( poLine->getCoordinateDimension() == 2 )
-            poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i),
-                                                nCoordPrecision, nSignificantFigures );
+            poObjPoint =
+                OGRGeoJSONWriteCoords( poLine->getX(nIdx), poLine->getY(nIdx),
+                                       oOptions );
         else
-            poObjPoint = OGRGeoJSONWriteCoords( poLine->getX(i), poLine->getY(i), poLine->getZ(i),
-                                                nCoordPrecision, nSignificantFigures );
+            poObjPoint =
+                OGRGeoJSONWriteCoords( poLine->getX(nIdx), poLine->getY(nIdx),
+                                       poLine->getZ(nIdx),
+                                       oOptions );
         if( poObjPoint == NULL )
         {
             json_object_put(poObjCoords);
@@ -925,26 +1341,30 @@ char* OGR_G_ExportToJsonEx( OGRGeometryH hGeometry, char** papszOptions )
 
     OGRGeometry* poGeometry = reinterpret_cast<OGRGeometry *>( hGeometry );
 
-    const int nCoordPrecision
-        = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
+    const int nCoordPrecision =
+        atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
 
-    const int nSignificantFigures
-        = atoi(CSLFetchNameValueDef(papszOptions, "SIGNIFICANT_FIGURES", "-1"));
+    const int nSignificantFigures =
+        atoi(CSLFetchNameValueDef(papszOptions, "SIGNIFICANT_FIGURES", "-1"));
 
-    json_object* poObj
-        = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision, nSignificantFigures );
+    OGRGeoJSONWriteOptions oOptions;
+    oOptions.nCoordPrecision = nCoordPrecision;
+    oOptions.nSignificantFigures = nSignificantFigures;
+
+    json_object* poObj =
+       OGRGeoJSONWriteGeometry( poGeometry, oOptions );
 
     if( NULL != poObj )
     {
         char* pszJson = CPLStrdup( json_object_to_json_string( poObj ) );
 
-        /* Release JSON tree. */
+        // Release JSON tree.
         json_object_put( poObj );
 
         return pszJson;
     }
 
-    /* Translation failed */
+    // Translation failed.
     return NULL;
 }
 
@@ -952,13 +1372,15 @@ char* OGR_G_ExportToJsonEx( OGRGeometryH hGeometry, char** papszOptions )
 /*               OGR_json_double_with_precision_to_string()             */
 /************************************************************************/
 
-static int OGR_json_double_with_precision_to_string(struct json_object *jso,
-                                                    struct printbuf *pb,
-                                                    CPL_UNUSED int level,
-                                                    CPL_UNUSED int flags)
+static int OGR_json_double_with_precision_to_string( struct json_object *jso,
+                                                     struct printbuf *pb,
+                                                     int /* level */,
+                                                     int /* flags */)
 {
-    char szBuffer[75];
-    const int nPrecision = (int) (size_t) jso->_userdata;
+    // TODO(schwehr): Explain this casting.
+    const int nPrecision =
+        static_cast<int>(reinterpret_cast<GUIntptr_t>(jso->_userdata));
+    char szBuffer[75] = {};
     OGRFormatDouble( szBuffer, sizeof(szBuffer), jso->o.c_double, '.',
                      (nPrecision < 0) ? 15 : nPrecision );
     if( szBuffer[0] == 't' /*oobig */ )
@@ -985,47 +1407,59 @@ json_object* json_object_new_double_with_precision(double dfVal,
 /*             OGR_json_double_with_significant_figures_to_string()     */
 /************************************************************************/
 
-static int OGR_json_double_with_significant_figures_to_string(struct json_object *jso,
+static int
+OGR_json_double_with_significant_figures_to_string( struct json_object *jso,
                                                     struct printbuf *pb,
-                                                    CPL_UNUSED int level,
-                                                    CPL_UNUSED int flags)
+                                                    int /* level */,
+                                                    int /* flags */)
 {
-    char szBuffer[75];
-    int nSize;
+    char szBuffer[75] = {};
+    int nSize = 0;
     if( CPLIsNan(jso->o.c_double))
         nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), "NaN");
-    else if(CPLIsInf(jso->o.c_double))
+    else if( CPLIsInf(jso->o.c_double) )
     {
-        if(jso->o.c_double > 0)
+        if( jso->o.c_double > 0 )
             nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), "Infinity");
         else
             nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), "-Infinity");
     }
     else
     {
-        char szFormatting[32];
-        const int nSignificantFigures = (int) (size_t) jso->_userdata;
-        const int nInitialSignificantFigures = nSignificantFigures >= 0 ? nSignificantFigures : 17;
-        CPLsnprintf(szFormatting, sizeof(szFormatting), "%%.%dg", nInitialSignificantFigures);
-        nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), szFormatting, jso->o.c_double);
+        char szFormatting[32] = {};
+        const int nSignificantFigures = (int) (GUIntptr_t) jso->_userdata;
+        const int nInitialSignificantFigures =
+            nSignificantFigures >= 0 ? nSignificantFigures : 17;
+        CPLsnprintf(szFormatting, sizeof(szFormatting),
+                    "%%.%dg", nInitialSignificantFigures);
+        nSize = CPLsnprintf(szBuffer, sizeof(szBuffer),
+                            szFormatting, jso->o.c_double);
         const char* pszDot = NULL;
-        if( nSize+2 < (int)sizeof(szBuffer) && (pszDot = strchr(szBuffer, '.')) == NULL )
+        if( nSize+2 < static_cast<int>(sizeof(szBuffer)) &&
+            (pszDot = strchr(szBuffer, '.')) == NULL )
         {
-            nSize += CPLsnprintf(szBuffer + nSize, sizeof(szBuffer) - nSize, ".0");
+            nSize += CPLsnprintf(szBuffer + nSize, sizeof(szBuffer) - nSize,
+                                 ".0");
         }
 
-        // Try to avoid .xxxx999999y or .xxxx000000y rounding issues by decreasing a bit precision
-        if( nInitialSignificantFigures > 10 && pszDot != NULL &&
-            (strstr(pszDot, "999999") != NULL || strstr(pszDot, "000000") != NULL) )
+        // Try to avoid .xxxx999999y or .xxxx000000y rounding issues by
+        // decreasing a bit precision.
+        if( nInitialSignificantFigures > 10 &&
+            pszDot != NULL &&
+            (strstr(pszDot, "999999") != NULL ||
+             strstr(pszDot, "000000") != NULL) )
         {
             bool bOK = false;
-            for(int i=1; i<=3; i++)
+            for( int i = 1; i <= 3; i++ )
             {
-                CPLsnprintf(szFormatting, sizeof(szFormatting), "%%.%dg", nInitialSignificantFigures- i);
-                nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), szFormatting, jso->o.c_double);
+                CPLsnprintf(szFormatting, sizeof(szFormatting),
+                            "%%.%dg", nInitialSignificantFigures- i);
+                nSize = CPLsnprintf(szBuffer, sizeof(szBuffer),
+                                    szFormatting, jso->o.c_double);
                 pszDot = strchr(szBuffer, '.');
                 if( pszDot != NULL &&
-                    strstr(pszDot, "999999") == NULL && strstr(pszDot, "000000") == NULL )
+                    strstr(pszDot, "999999") == NULL &&
+                    strstr(pszDot, "000000") == NULL )
                 {
                     bOK = true;
                     break;
@@ -1033,11 +1467,16 @@ static int OGR_json_double_with_significant_figures_to_string(struct json_object
             }
             if( !bOK )
             {
-                CPLsnprintf(szFormatting, sizeof(szFormatting), "%%.%dg", nInitialSignificantFigures);
-                nSize = CPLsnprintf(szBuffer, sizeof(szBuffer), szFormatting, jso->o.c_double);
-                if( nSize+2 < (int)sizeof(szBuffer) && (pszDot = strchr(szBuffer, '.')) == NULL )
+                CPLsnprintf(szFormatting, sizeof(szFormatting),
+                            "%%.%dg", nInitialSignificantFigures);
+                nSize = CPLsnprintf(szBuffer, sizeof(szBuffer),
+                                    szFormatting, jso->o.c_double);
+                if( nSize+2 < static_cast<int>(sizeof(szBuffer)) &&
+                    strchr(szBuffer, '.') == NULL )
                 {
-                    nSize += CPLsnprintf(szBuffer + nSize, sizeof(szBuffer) - nSize, ".0");
+                    nSize +=
+                        CPLsnprintf(szBuffer + nSize, sizeof(szBuffer) - nSize,
+                                    ".0");
                 }
             }
         }
@@ -1050,11 +1489,14 @@ static int OGR_json_double_with_significant_figures_to_string(struct json_object
 /*              json_object_new_double_with_significant_figures()       */
 /************************************************************************/
 
-json_object* json_object_new_double_with_significant_figures(double dfVal,
-                                                   int nSignificantFigures)
+json_object *
+json_object_new_double_with_significant_figures( double dfVal,
+                                                 int nSignificantFigures )
 {
     json_object* jso = json_object_new_double(dfVal);
-    json_object_set_serializer(jso, OGR_json_double_with_significant_figures_to_string,
-                               (void*)(size_t)nSignificantFigures, NULL );
+    // TODO(schwehr): Convert C cast.
+    json_object_set_serializer(
+        jso, OGR_json_double_with_significant_figures_to_string,
+        (void*)(size_t)nSignificantFigures, NULL );
     return jso;
 }
diff --git a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
index 8fa67f1..bd81c08 100644
--- a/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
+++ b/ogr/ogrsf_frmts/geojson/ogrgeojsonwriter.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeojsonwriter.h 32952 2016-01-12 12:24:52Z rouault $
+ * $Id: ogrgeojsonwriter.h 36477 2016-11-24 01:41:10Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Defines GeoJSON reader within OGR OGRGeoJSON Driver.
@@ -27,11 +27,14 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
 #ifndef OGR_GEOJSONWRITER_H_INCLUDED
 #define OGR_GEOJSONWRITER_H_INCLUDED
 
 #include <ogr_core.h>
-#include <json.h> // JSON-C
+
+#include "ogr_json_header.h"
+
 
 /************************************************************************/
 /*                         FORWARD DECLARATIONS                         */
@@ -62,20 +65,54 @@ CPL_C_END
 /*                 GeoJSON Geometry Translators                         */
 /************************************************************************/
 #ifdef __cplusplus
-json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature, int nSignificantFigures );
+class OGRCoordinateTransformation;
+
+/*! @cond Doxygen_Suppress */
+class OGRGeoJSONWriteOptions
+{
+    public:
+        bool bWriteBBOX;
+        bool bBBOXRFC7946;
+        int  nCoordPrecision;
+        int  nSignificantFigures;
+        bool bPolygonRightHandRule;
+        bool bCanPatchCoordinatesWithNativeData;
+        bool bHonourReservedRFC7946Members;
+
+        OGRGeoJSONWriteOptions():
+            bWriteBBOX(false),
+            bBBOXRFC7946(false),
+            nCoordPrecision(-1),
+            nSignificantFigures(-1),
+            bPolygonRightHandRule(false),
+            bCanPatchCoordinatesWithNativeData(true),
+            bHonourReservedRFC7946Members(false)
+        {}
+
+        void SetRFC7946Settings();
+};
+/*! @endcond */
+
+OGREnvelope3D OGRGeoJSONGetBBox( OGRGeometry* poGeometry,
+                                 const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteAttributes( OGRFeature* poFeature,
+                                        bool bWriteIdIfFoundInAttributes = true,
+                                        const OGRGeoJSONWriteOptions& oOptions = OGRGeoJSONWriteOptions() );
 json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteGeometry( OGRGeometry* poGeometry, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWritePoint( OGRPoint* poPoint, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteLineString( OGRLineString* poLine, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWritePolygon( OGRPolygon* poPolygon, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteMultiPoint( OGRMultiPoint* poGeometry, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteMultiLineString( OGRMultiLineString* poGeometry, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteMultiPolygon( OGRMultiPolygon* poGeometry, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteGeometryCollection( OGRGeometryCollection* poGeometry, const OGRGeoJSONWriteOptions& oOptions );
 
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ, int nCoordPrecision, int nSignificantFigures );
-json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, int nCoordPrecision, int nSignificantFigures );
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteCoords( double const& fX, double const& fY, double const& fZ, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteLineCoords( OGRLineString* poLine, const OGRGeoJSONWriteOptions& oOptions );
+json_object* OGRGeoJSONWriteRingCoords( OGRLinearRing* poLine, bool bIsExteriorRing, const OGRGeoJSONWriteOptions& oOptions );
 #endif
 
 #endif /* OGR_GEOJSONWRITER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp b/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp
index 47494a6..76629df 100644
--- a/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp
+++ b/ogr/ogrsf_frmts/geojson/ogrtopojsonreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrtopojsonreader.cpp 34246 2016-05-18 13:25:44Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implementation of OGRTopoJSONReader class
@@ -30,18 +29,16 @@
 #include "ogrgeojsonreader.h"
 #include "ogrgeojsonutils.h"
 #include "ogr_geojson.h"
-#include <json.h> // JSON-C
+#include <json.h>  // JSON-C
 #include <ogr_api.h>
 
+CPL_CVSID("$Id: ogrtopojsonreader.cpp 37269 2017-02-02 12:02:03Z rouault $");
+
 /************************************************************************/
 /*                          OGRTopoJSONReader()                         */
 /************************************************************************/
 
-OGRTopoJSONReader::OGRTopoJSONReader()
-    : poGJObject_( NULL )
-{
-    // Take a deep breath and get to work.
-}
+OGRTopoJSONReader::OGRTopoJSONReader() : poGJObject_( NULL ) {}
 
 /************************************************************************/
 /*                         ~OGRTopoJSONReader()                         */
@@ -71,16 +68,15 @@ OGRErr OGRTopoJSONReader::Parse( const char* pszText )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "TopoJSON parsing error: %s (at offset %d)",
-            	      json_tokener_error_desc(jstok->err), jstok->char_offset);
+                      json_tokener_error_desc(jstok->err), jstok->char_offset );
 
             json_tokener_free(jstok);
             return OGRERR_CORRUPT_DATA;
         }
         json_tokener_free(jstok);
 
-        /* JSON tree is shared for while lifetime of the reader object
-         * and will be released in the destructor.
-         */
+        // JSON tree is shared for while lifetime of the reader object
+        // and will be released in the destructor.
         poGJObject_ = jsobj;
     }
 
@@ -89,15 +85,18 @@ OGRErr OGRTopoJSONReader::Parse( const char* pszText )
 
 typedef struct
 {
-    double dfScale0, dfScale1;
-    double dfTranslate0, dfTranslate1;
+    double dfScale0;
+    double dfScale1;
+    double dfTranslate0;
+    double dfTranslate1;
+    bool bElementExists;
 } ScalingParams;
 
 /************************************************************************/
 /*                            ParsePoint()                              */
 /************************************************************************/
 
-static bool ParsePoint(json_object* poPoint, double* pdfX, double* pdfY)
+static bool ParsePoint( json_object* poPoint, double* pdfX, double* pdfY )
 {
     if( poPoint != NULL && json_type_array == json_object_get_type(poPoint) &&
         json_object_array_length(poPoint) == 2 )
@@ -124,24 +123,34 @@ static bool ParsePoint(json_object* poPoint, double* pdfX, double* pdfY)
 /************************************************************************/
 
 static void ParseArc( OGRLineString* poLS, json_object* poArcsDB, int nArcID,
-                      int bReverse, ScalingParams* psParams)
+                      bool bReverse, ScalingParams* psParams )
 {
     json_object* poArcDB = json_object_array_get_idx(poArcsDB, nArcID);
     if( poArcDB == NULL || json_type_array != json_object_get_type(poArcDB) )
         return;
     int nPoints = json_object_array_length(poArcDB);
-    double dfAccX = 0, dfAccY = 0;
+    double dfAccX = 0.0;
+    double dfAccY = 0.0;
     int nBaseIndice = poLS->getNumPoints();
-    for(int i=0; i<nPoints; i++)
+    for( int i = 0; i < nPoints; i++ )
     {
         json_object* poPoint = json_object_array_get_idx(poArcDB, i);
-        double dfX = 0.0, dfY = 0.0;
+        double dfX = 0.0;
+        double dfY = 0.0;
         if( ParsePoint( poPoint, &dfX, &dfY ) )
         {
-            dfAccX += dfX;
-            dfAccY += dfY;
-            dfX = dfAccX * psParams->dfScale0 + psParams->dfTranslate0;
-            dfY = dfAccY * psParams->dfScale1 + psParams->dfTranslate1;
+            if( psParams->bElementExists )
+            {
+                dfAccX += dfX;
+                dfAccY += dfY;
+                dfX = dfAccX * psParams->dfScale0 + psParams->dfTranslate0;
+                dfY = dfAccY * psParams->dfScale1 + psParams->dfTranslate1;
+            }
+            else
+            {
+                dfX = dfX * psParams->dfScale0 + psParams->dfTranslate0;
+                dfY = dfY * psParams->dfScale1 + psParams->dfTranslate1;
+            }
             if( i == 0 )
             {
                 if( !bReverse && poLS->getNumPoints() > 0 )
@@ -173,23 +182,23 @@ static void ParseArc( OGRLineString* poLS, json_object* poArcsDB, int nArcID,
 /*                        ParseLineString()                             */
 /************************************************************************/
 
-static void ParseLineString(OGRLineString* poLS, json_object* poRing,
-                            json_object* poArcsDB, ScalingParams* psParams)
+static void ParseLineString( OGRLineString* poLS, json_object* poRing,
+                             json_object* poArcsDB, ScalingParams* psParams )
 {
-    int nArcsDB = json_object_array_length(poArcsDB);
+    const int nArcsDB = json_object_array_length(poArcsDB);
 
-    int nArcsRing = json_object_array_length(poRing);
-    for(int j=0; j<nArcsRing; j++)
+    const int nArcsRing = json_object_array_length(poRing);
+    for( int j = 0; j < nArcsRing; j++ )
     {
         json_object* poArcId = json_object_array_get_idx(poRing, j);
         if( poArcId != NULL && json_type_int == json_object_get_type(poArcId) )
         {
             int nArcId = json_object_get_int(poArcId);
-            int bReverse = FALSE;
+            bool bReverse = false;
             if( nArcId < 0 )
             {
                 nArcId = - nArcId - 1;
-                bReverse = TRUE;
+                bReverse = true;
             }
             if( nArcId < nArcsDB )
             {
@@ -203,20 +212,30 @@ static void ParseLineString(OGRLineString* poLS, json_object* poRing,
 /*                          ParsePolygon()                              */
 /************************************************************************/
 
-static void ParsePolygon(OGRPolygon* poPoly, json_object* poArcsObj,
-                         json_object* poArcsDB, ScalingParams* psParams)
+static void ParsePolygon( OGRPolygon* poPoly, json_object* poArcsObj,
+                          json_object* poArcsDB, ScalingParams* psParams )
 {
-    int nRings = json_object_array_length(poArcsObj);
-    for(int i=0; i<nRings; i++)
+    const int nRings = json_object_array_length(poArcsObj);
+    for( int i = 0; i < nRings; i++ )
     {
         OGRLinearRing* poLR = new OGRLinearRing();
-        poPoly->addRingDirectly(poLR);
 
         json_object* poRing = json_object_array_get_idx(poArcsObj, i);
         if( poRing != NULL && json_type_array == json_object_get_type(poRing) )
         {
             ParseLineString(poLR, poRing, poArcsDB, psParams);
         }
+        poLR->closeRings();
+        if( poLR->getNumPoints() < 4 )
+        {
+            CPLDebug("TopoJSON", "Discarding polygon ring made of %d points",
+                     poLR->getNumPoints());
+            delete poLR;
+        }
+        else
+        {
+            poPoly->addRingDirectly(poLR);
+        }
     }
 }
 
@@ -224,11 +243,13 @@ static void ParsePolygon(OGRPolygon* poPoly, json_object* poArcsObj,
 /*                       ParseMultiLineString()                         */
 /************************************************************************/
 
-static void ParseMultiLineString(OGRMultiLineString* poMLS, json_object* poArcsObj,
-                                 json_object* poArcsDB, ScalingParams* psParams)
+static void ParseMultiLineString( OGRMultiLineString* poMLS,
+                                  json_object* poArcsObj,
+                                  json_object* poArcsDB,
+                                  ScalingParams* psParams )
 {
-    int nRings = json_object_array_length(poArcsObj);
-    for(int i=0; i<nRings; i++)
+    const int nRings = json_object_array_length(poArcsObj);
+    for( int i = 0; i < nRings; i++ )
     {
         OGRLineString* poLS = new OGRLineString();
         poMLS->addGeometryDirectly(poLS);
@@ -245,20 +266,30 @@ static void ParseMultiLineString(OGRMultiLineString* poMLS, json_object* poArcsO
 /*                       ParseMultiPolygon()                            */
 /************************************************************************/
 
-static void ParseMultiPolygon(OGRMultiPolygon* poMultiPoly, json_object* poArcsObj,
-                         json_object* poArcsDB, ScalingParams* psParams)
+static void ParseMultiPolygon( OGRMultiPolygon* poMultiPoly,
+                               json_object* poArcsObj,
+                               json_object* poArcsDB, ScalingParams* psParams )
 {
-    int nPolys = json_object_array_length(poArcsObj);
-    for(int i=0; i<nPolys; i++)
+    const int nPolys = json_object_array_length(poArcsObj);
+    for( int i = 0; i < nPolys; i++ )
     {
         OGRPolygon* poPoly = new OGRPolygon();
-        poMultiPoly->addGeometryDirectly(poPoly);
 
         json_object* poPolyArcs = json_object_array_get_idx(poArcsObj, i);
-        if( poPolyArcs != NULL && json_type_array == json_object_get_type(poPolyArcs) )
+        if( poPolyArcs != NULL &&
+            json_type_array == json_object_get_type(poPolyArcs) )
         {
             ParsePolygon(poPoly, poPolyArcs, poArcsDB, psParams);
         }
+
+        if( poPoly->IsEmpty() )
+        {
+            delete poPoly;
+        }
+        else
+        {
+            poMultiPoly->addGeometryDirectly(poPoly);
+        }
     }
 }
 
@@ -266,9 +297,9 @@ static void ParseMultiPolygon(OGRMultiPolygon* poMultiPoly, json_object* poArcsO
 /*                          ParseObject()                               */
 /************************************************************************/
 
-static void ParseObject(const char* pszId,
-                        json_object* poObj, OGRGeoJSONLayer* poLayer,
-                        json_object* poArcsDB, ScalingParams* psParams)
+static void ParseObject( const char* pszId,
+                         json_object* poObj, OGRGeoJSONLayer* poLayer,
+                         json_object* poArcsDB, ScalingParams* psParams )
 {
     json_object* poType = OGRGeoJSONFindMemberByName(poObj, "type");
     if( poType == NULL || json_object_get_type(poType) != json_type_string )
@@ -276,15 +307,18 @@ static void ParseObject(const char* pszId,
     const char* pszType = json_object_get_string(poType);
 
     json_object* poArcsObj = OGRGeoJSONFindMemberByName(poObj, "arcs");
-    json_object* poCoordinatesObj = OGRGeoJSONFindMemberByName(poObj, "coordinates");
+    json_object* poCoordinatesObj =
+        OGRGeoJSONFindMemberByName(poObj, "coordinates");
     if( strcmp(pszType, "Point") == 0 || strcmp(pszType, "MultiPoint") == 0 )
     {
-        if( poCoordinatesObj == NULL || json_type_array != json_object_get_type(poCoordinatesObj) )
+        if( poCoordinatesObj == NULL ||
+            json_type_array != json_object_get_type(poCoordinatesObj) )
             return;
     }
     else
     {
-        if( poArcsObj == NULL || json_type_array != json_object_get_type(poArcsObj) )
+        if( poArcsObj == NULL ||
+            json_type_array != json_object_get_type(poArcsObj) )
             return;
     }
 
@@ -304,7 +338,8 @@ static void ParseObject(const char* pszId,
         poFeature->SetField("id", pszId);
 
     json_object* poProperties = OGRGeoJSONFindMemberByName(poObj, "properties");
-    if( poProperties != NULL && json_type_object == json_object_get_type(poProperties) )
+    if( poProperties != NULL &&
+        json_type_object == json_object_get_type(poProperties) )
     {
         json_object_iter it;
         it.key = NULL;
@@ -312,16 +347,17 @@ static void ParseObject(const char* pszId,
         it.entry = NULL;
         json_object_object_foreachC( poProperties, it )
         {
-            const int nField
-                = poFeature->GetFieldIndex(it.key);
-            OGRGeoJSONReaderSetField(poLayer, poFeature, nField, it.key, it.val, false, 0);
+            const int nField = poFeature->GetFieldIndex(it.key);
+            OGRGeoJSONReaderSetField(poLayer, poFeature, nField,
+                                     it.key, it.val, false, 0);
         }
     }
 
     OGRGeometry* poGeom = NULL;
     if( strcmp(pszType, "Point") == 0 )
     {
-        double dfX = 0.0, dfY = 0.0;
+        double dfX = 0.0;
+        double dfY = 0.0;
         if( ParsePoint( poCoordinatesObj, &dfX, &dfY ) )
         {
             dfX = dfX * psParams->dfScale0 + psParams->dfTranslate0;
@@ -329,17 +365,21 @@ static void ParseObject(const char* pszId,
             poGeom = new OGRPoint(dfX, dfY);
         }
         else
+        {
             poGeom = new OGRPoint();
+        }
     }
     else if( strcmp(pszType, "MultiPoint") == 0 )
     {
         OGRMultiPoint* poMP = new OGRMultiPoint();
         poGeom = poMP;
         int nTuples = json_object_array_length(poCoordinatesObj);
-        for(int i=0; i<nTuples; i++)
+        for( int i = 0; i < nTuples; i++ )
         {
-            json_object* poPair = json_object_array_get_idx(poCoordinatesObj, i);
-            double dfX = 0.0, dfY = 0.0;
+            json_object* poPair =
+                json_object_array_get_idx(poCoordinatesObj, i);
+            double dfX = 0.0;
+            double dfY = 0.0;
             if( ParsePoint( poPair, &dfX, &dfY ) )
             {
                 dfX = dfX * psParams->dfScale0 + psParams->dfTranslate0;
@@ -379,14 +419,13 @@ static void ParseObject(const char* pszId,
     delete poFeature;
 }
 
-
 /************************************************************************/
 /*                        EstablishLayerDefn()                          */
 /************************************************************************/
 
-static void EstablishLayerDefn(OGRFeatureDefn* poDefn,
-                               json_object* poObj,
-                               std::set<int>& aoSetUndeterminedTypeFields)
+static void EstablishLayerDefn( OGRFeatureDefn* poDefn,
+                                json_object* poObj,
+                                std::set<int>& aoSetUndeterminedTypeFields )
 {
     json_object* poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
     if( NULL != poObjProps &&
@@ -396,11 +435,12 @@ static void EstablishLayerDefn(OGRFeatureDefn* poDefn,
         it.key = NULL;
         it.val = NULL;
         it.entry = NULL;
-        
+
         json_object_object_foreachC( poObjProps, it )
         {
             OGRGeoJSONReaderAddOrUpdateField(poDefn, it.key, it.val,
-                                             false, 0, false, aoSetUndeterminedTypeFields);
+                                             false, 0, false,
+                                             aoSetUndeterminedTypeFields);
         }
     }
 }
@@ -422,18 +462,21 @@ static bool ParseObjectMain( const char* pszId, json_object* poObj,
     if( poObj != NULL && json_type_object == json_object_get_type( poObj ) )
     {
         json_object* poType = OGRGeoJSONFindMemberByName(poObj, "type");
-        if( poType != NULL && json_type_string == json_object_get_type( poType ) )
+        if( poType != NULL &&
+            json_type_string == json_object_get_type( poType ) )
         {
             const char* pszType = json_object_get_string(poType);
             if( nPassNumber == 1 && strcmp(pszType, "GeometryCollection") == 0 )
             {
-                json_object* poGeometries = OGRGeoJSONFindMemberByName(poObj, "geometries");
+                json_object* poGeometries =
+                    OGRGeoJSONFindMemberByName(poObj, "geometries");
                 if( poGeometries != NULL &&
                     json_type_array == json_object_get_type( poGeometries ) )
                 {
                     if( pszId == NULL )
                     {
-                        json_object* poId = OGRGeoJSONFindMemberByName(poObj, "id");
+                        json_object* poId =
+                            OGRGeoJSONFindMemberByName(poObj, "id");
                         if( poId != NULL &&
                             (json_type_string == json_object_get_type(poId) ||
                             json_type_int == json_object_get_type(poId)) )
@@ -451,28 +494,31 @@ static bool ParseObjectMain( const char* pszId, json_object* poObj,
                         poDefn->AddFieldDefn( &fldDefn );
                     }
 
-                    int nGeometries = json_object_array_length(poGeometries);
-                    /* First pass to establish schema */
-                    for(int i=0; i<nGeometries; i++)
+                    const int nGeometries =
+                        json_object_array_length(poGeometries);
+                    // First pass to establish schema.
+                    for( int i = 0; i < nGeometries; i++ )
                     {
                         json_object* poGeom =
                             json_object_array_get_idx(poGeometries, i);
                         if( poGeom != NULL &&
                             json_type_object == json_object_get_type( poGeom ) )
                         {
-                            EstablishLayerDefn(poDefn, poGeom, aoSetUndeterminedTypeFields);
+                            EstablishLayerDefn(poDefn, poGeom,
+                                               aoSetUndeterminedTypeFields);
                         }
                     }
 
-                    /* Second pass to build objects */
-                    for(int i=0; i<nGeometries; i++)
+                    // Second pass to build objects.
+                    for( int i = 0; i < nGeometries; i++ )
                     {
                         json_object* poGeom =
                             json_object_array_get_idx(poGeometries, i);
                         if( poGeom != NULL &&
                             json_type_object == json_object_get_type( poGeom ) )
                         {
-                            ParseObject(NULL, poGeom, poLayer, poArcs, psParams);
+                            ParseObject(NULL, poGeom, poLayer,
+                                        poArcs, psParams);
                         }
                     }
 
@@ -494,11 +540,13 @@ static bool ParseObjectMain( const char* pszId, json_object* poObj,
                             "TopoJSON", NULL, wkbUnknown, poDS );
                         {
                             OGRFieldDefn fldDefn( "id", OFTString );
-                            (*ppoMainLayer)->GetLayerDefn()->AddFieldDefn( &fldDefn );
+                            (*ppoMainLayer)->
+                                GetLayerDefn()->AddFieldDefn( &fldDefn );
                         }
                     }
                     OGRFeatureDefn* poDefn = (*ppoMainLayer)->GetLayerDefn();
-                    EstablishLayerDefn(poDefn, poObj, aoSetUndeterminedTypeFields);
+                    EstablishLayerDefn(poDefn, poObj,
+                                       aoSetUndeterminedTypeFields);
                     bNeedSecondPass = true;
                 }
                 else
@@ -527,11 +575,16 @@ void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
     sParams.dfScale1 = 1.0;
     sParams.dfTranslate0 = 0.0;
     sParams.dfTranslate1 = 0.0;
-    json_object* poObjTransform = OGRGeoJSONFindMemberByName( poGJObject_, "transform" );
-    if( NULL != poObjTransform && json_type_object == json_object_get_type( poObjTransform ) )
+    sParams.bElementExists = false;
+    json_object* poObjTransform =
+        OGRGeoJSONFindMemberByName( poGJObject_, "transform" );
+    if( NULL != poObjTransform &&
+        json_type_object == json_object_get_type( poObjTransform ) )
     {
-        json_object* poObjScale = OGRGeoJSONFindMemberByName( poObjTransform, "scale" );
-        if( NULL != poObjScale && json_type_array == json_object_get_type( poObjScale ) &&
+        json_object* poObjScale =
+            OGRGeoJSONFindMemberByName( poObjTransform, "scale" );
+        if( NULL != poObjScale &&
+            json_type_array == json_object_get_type( poObjScale ) &&
             json_object_array_length( poObjScale ) == 2 )
         {
             json_object* poScale0 = json_object_array_get_idx(poObjScale, 0);
@@ -545,15 +598,20 @@ void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
             {
                 sParams.dfScale0 = json_object_get_double(poScale0);
                 sParams.dfScale1 = json_object_get_double(poScale1);
+                sParams.bElementExists = true;
             }
         }
 
-        json_object* poObjTranslate = OGRGeoJSONFindMemberByName( poObjTransform, "translate" );
-        if( NULL != poObjTranslate && json_type_array == json_object_get_type( poObjTranslate ) &&
+        json_object* poObjTranslate =
+            OGRGeoJSONFindMemberByName( poObjTransform, "translate" );
+        if( NULL != poObjTranslate &&
+            json_type_array == json_object_get_type( poObjTranslate ) &&
             json_object_array_length( poObjTranslate ) == 2 )
         {
-            json_object* poTranslate0 = json_object_array_get_idx(poObjTranslate, 0);
-            json_object* poTranslate1 = json_object_array_get_idx(poObjTranslate, 1);
+            json_object* poTranslate0 =
+                json_object_array_get_idx(poObjTranslate, 0);
+            json_object* poTranslate1 =
+                json_object_array_get_idx(poObjTranslate, 1);
             if( poTranslate0 != NULL &&
                 (json_object_get_type(poTranslate0) == json_type_double ||
                  json_object_get_type(poTranslate0) == json_type_int) &&
@@ -563,6 +621,7 @@ void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
             {
                 sParams.dfTranslate0 = json_object_get_double(poTranslate0);
                 sParams.dfTranslate1 = json_object_get_double(poTranslate1);
+                sParams.bElementExists = true;
             }
         }
     }
@@ -573,7 +632,8 @@ void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
 
     OGRGeoJSONLayer* poMainLayer = NULL;
 
-    json_object* poObjects = OGRGeoJSONFindMemberByName( poGJObject_, "objects" );
+    json_object* poObjects =
+        OGRGeoJSONFindMemberByName( poGJObject_, "objects" );
     if( poObjects == NULL )
         return;
 
@@ -609,15 +669,16 @@ void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
     {
         const int nObjects = json_object_array_length(poObjects);
         bool bNeedSecondPass = false;
-        for(int i=0; i<nObjects; i++)
+        for( int i = 0; i < nObjects; i++ )
         {
             json_object* poObj = json_object_array_get_idx(poObjects, i);
             bNeedSecondPass |= ParseObjectMain(NULL, poObj, poDS, &poMainLayer,
-                                               poArcs, &sParams, 1, aoSetUndeterminedTypeFields);
+                                               poArcs, &sParams, 1,
+                                               aoSetUndeterminedTypeFields);
         }
         if( bNeedSecondPass )
         {
-            for(int i=0; i<nObjects; i++)
+            for( int i = 0; i < nObjects; i++ )
             {
                 json_object* poObj = json_object_array_get_idx(poObjects, i);
                 ParseObjectMain(NULL, poObj, poDS, &poMainLayer, poArcs,
@@ -628,5 +689,4 @@ void OGRTopoJSONReader::ReadLayers( OGRGeoJSONDataSource* poDS )
 
     if( poMainLayer != NULL )
         poDS->AddLayer(poMainLayer);
-
 }
diff --git a/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h b/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
index a02b4dd..e6d8511 100644
--- a/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
+++ b/ogr/ogrsf_frmts/geomedia/ogr_geomedia.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geomedia.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_geomedia.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for Geomedia MDB driver.
@@ -73,18 +73,18 @@ class OGRGeomediaLayer : public OGRLayer
                         OGRGeomediaLayer();
     virtual             ~OGRGeomediaLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
     virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 };
 
 /************************************************************************/
@@ -93,30 +93,28 @@ class OGRGeomediaLayer : public OGRLayer
 
 class OGRGeomediaTableLayer : public OGRGeomediaLayer
 {
-    int                 bUpdateAccess;
-
     char                *pszQuery;
 
-    void		ClearStatement();
+    void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *  GetStatement() override;
 
   public:
-                        OGRGeomediaTableLayer( OGRGeomediaDataSource * );
-                        ~OGRGeomediaTableLayer();
+    explicit            OGRGeomediaTableLayer( OGRGeomediaDataSource * );
+                        virtual ~OGRGeomediaTableLayer();
 
     CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol,
                                     OGRSpatialReference* poSRS );
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -127,22 +125,22 @@ class OGRGeomediaSelectLayer : public OGRGeomediaLayer
 {
     char                *pszBaseStatement;
 
-    void		ClearStatement();
+    void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *GetStatement() override;
 
   public:
                         OGRGeomediaSelectLayer( OGRGeomediaDataSource *,
-                                           CPLODBCStatement * );
-                        ~OGRGeomediaSelectLayer();
+                                                CPLODBCStatement * );
+                        virtual ~OGRGeomediaSelectLayer();
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -168,24 +166,24 @@ class OGRGeomediaDataSource : public OGRDataSource
 
   public:
                         OGRGeomediaDataSource();
-                        ~OGRGeomediaDataSource();
+                        virtual ~OGRGeomediaDataSource();
 
     int                 Open( const char *, int bUpdate, int bTestOpen );
     int                 OpenTable( const char *pszTableName,
                                    const char *pszGeomCol,
                                    int bUpdate );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
-    OGRLayer            *GetLayerByName( const char* pszLayerName );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
+    OGRLayer            *GetLayerByName( const char* pszLayerName ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     // Internal use
     CPLODBCSession     *GetSession() { return &oSession; }
@@ -200,10 +198,10 @@ class OGRGeomediaDriver : public OGRODBCMDBDriver
   public:
                 ~OGRGeomediaDriver();
 
-    const char  *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char  *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
-    int          TestCapability( const char * );
+    int          TestCapability( const char * ) override;
 };
 
 #endif /* ndef _OGR_Geomedia_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
index fce1ce3..e9e72a4 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediadatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeomediadatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaDataSource class.
@@ -34,22 +33,20 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogrgeomediadatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrgeomediadatasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                       OGRGeomediaDataSource()                        */
 /************************************************************************/
 
-OGRGeomediaDataSource::OGRGeomediaDataSource()
-
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    papoLayersInvisible = NULL;
-    nLayers = 0;
-    nLayersWithInvisible = 0;
-    bDSUpdate = FALSE;
-}
+OGRGeomediaDataSource::OGRGeomediaDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    papoLayersInvisible(NULL),
+    nLayersWithInvisible(0),
+    pszName(NULL),
+    bDSUpdate(FALSE)
+{}
 
 /************************************************************************/
 /*                       ~OGRGeomediaDataSource()                       */
@@ -58,15 +55,13 @@ OGRGeomediaDataSource::OGRGeomediaDataSource()
 OGRGeomediaDataSource::~OGRGeomediaDataSource()
 
 {
-    int         i;
-
     CPLFree( pszName );
 
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
     CPLFree( papoLayers );
 
-    for( i = 0; i < nLayersWithInvisible; i++ )
+    for( int i = 0; i < nLayersWithInvisible; i++ )
         delete papoLayersInvisible[i];
     CPLFree( papoLayersInvisible );
 }
@@ -116,7 +111,7 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
 /*      get the DSN.                                                    */
 /*                                                                      */
 /* -------------------------------------------------------------------- */
-    char *pszDSN;
+    char *pszDSN = NULL;
     if( STARTS_WITH_CI(pszNewName, "GEOMEDIA:") )
         pszDSN = CPLStrdup( pszNewName + 9 );
     else
@@ -161,7 +156,7 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
 /*      GAliasTable.                                                    */
 /* -------------------------------------------------------------------- */
     CPLString osGFeaturesTable = GetTableNameFromType("INGRFeatures");
-    if (osGFeaturesTable.size() == 0)
+    if (osGFeaturesTable.empty())
         return FALSE;
 
     CPLString osGeometryProperties = GetTableNameFromType("INGRGeometryProperties");
@@ -194,7 +189,7 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
     }
 
     std::vector<OGRSpatialReference*> apoSRS;
-    if (osGeometryProperties.size() != 0 && osGCoordSystemTable.size() != 0)
+    if (!osGeometryProperties.empty() && !osGCoordSystemTable.empty())
     {
         std::vector<CPLString> aosGUID;
         {
@@ -223,8 +218,7 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
             }
         }
 
-        int i;
-        for(i=0; i<(int)aosGUID.size();i++)
+        for( size_t i = 0; i < aosGUID.size(); i++ )
         {
             apoSRS.push_back(GetGeomediaSRS(osGCoordSystemTable, aosGUID[i]));
         }
@@ -233,17 +227,14 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
 /* -------------------------------------------------------------------- */
 /*      Create a layer for each spatial table.                          */
 /* -------------------------------------------------------------------- */
-    unsigned int iTable;
 
     papoLayers = (OGRGeomediaLayer **) CPLCalloc(apapszGeomColumns.size(),
                                              sizeof(void*));
 
-    for( iTable = 0; iTable < apapszGeomColumns.size(); iTable++ )
+    for( unsigned int iTable = 0; iTable < apapszGeomColumns.size(); iTable++ )
     {
         char **papszRecord = apapszGeomColumns[iTable];
-        OGRGeomediaTableLayer  *poLayer;
-
-        poLayer = new OGRGeomediaTableLayer( this );
+        OGRGeomediaTableLayer *poLayer = new OGRGeomediaTableLayer( this );
 
         if( poLayer->Initialize( papszRecord[0], papszRecord[1], (apoSRS.size()) ? apoSRS[iTable] : NULL )
             != CE_None )
@@ -260,7 +251,6 @@ int OGRGeomediaDataSource::Open( const char * pszNewName, int bUpdate,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                     GetTableNameFromType()                           */
 /************************************************************************/
@@ -288,7 +278,6 @@ CPLString OGRGeomediaDataSource::GetTableNameFromType(const char* pszTableType)
     return "";
 }
 
-
 /************************************************************************/
 /*                          GetGeomediaSRS()                            */
 /************************************************************************/
@@ -305,7 +294,7 @@ OGRSpatialReference* OGRGeomediaDataSource::GetGeomediaSRS(const char* pszGCoord
 
     poGCoordSystemTable->ResetReading();
 
-    OGRFeature* poFeature;
+    OGRFeature* poFeature = NULL;
     while((poFeature = poGCoordSystemTable->GetNextFeature()) != NULL)
     {
         const char* pszCSGUID = poFeature->GetFieldAsString("CSGUID");
@@ -344,7 +333,6 @@ OGRLayer *OGRGeomediaDataSource::GetLayer( int iLayer )
         return papoLayers[iLayer];
 }
 
-
 /************************************************************************/
 /*                          GetLayerByName()                            */
 /************************************************************************/
@@ -366,9 +354,7 @@ OGRLayer *OGRGeomediaDataSource::GetLayerByName( const char* pszNameIn )
             return poLayer;
     }
 
-    OGRGeomediaTableLayer  *poGeomediaLayer;
-
-    poGeomediaLayer = new OGRGeomediaTableLayer( this );
+    OGRGeomediaTableLayer *poGeomediaLayer = new OGRGeomediaTableLayer( this );
 
     if( poGeomediaLayer->Initialize(pszNameIn, NULL, NULL) != CE_None )
     {
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
index a588460..38da718 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediadriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeomediadriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
@@ -31,7 +30,7 @@
 #include "ogr_geomedia.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgeomediadriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrgeomediadriver.cpp 35137 2016-08-17 17:05:45Z goatbar $");
 
 /************************************************************************/
 /*                          ~OGRODBCDriver()                            */
@@ -60,8 +59,6 @@ OGRDataSource *OGRGeomediaDriver::Open( const char * pszFilename,
                                     int bUpdate )
 
 {
-    OGRGeomediaDataSource     *poDS;
-
     if( STARTS_WITH_CI(pszFilename, "WALK:") )
         return NULL;
 
@@ -126,7 +123,7 @@ OGRDataSource *OGRGeomediaDriver::Open( const char * pszFilename,
 #endif /* ndef WIN32 */
 
     // Open data source
-    poDS = new OGRGeomediaDataSource();
+    OGRGeomediaDataSource *poDS = new OGRGeomediaDataSource();
 
     if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
     {
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
index a0ef066..aee5873 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomedialayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeomedialayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaLayer class, code shared between
@@ -34,29 +33,25 @@
 #include "cpl_string.h"
 #include "ogrgeomediageometry.h"
 
-CPL_CVSID("$Id: ogrgeomedialayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrgeomedialayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                          OGRGeomediaLayer()                          */
 /************************************************************************/
 
-OGRGeomediaLayer::OGRGeomediaLayer()
-
-{
-    poDS = NULL;
-
-    pszGeomColumn = NULL;
-    pszFIDColumn = NULL;
-
-    poStmt = NULL;
-
-    iNextShapeId = 0;
-
-    poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet.
-    poFeatureDefn = NULL;
-    panFieldOrdinals = NULL;
-}
+OGRGeomediaLayer::OGRGeomediaLayer() :
+    poFeatureDefn(NULL),
+    poStmt(NULL),
+    poSRS(NULL),
+    nSRSId(-2), // we haven't even queried the database for it yet.
+    iNextShapeId(0),
+    poDS(NULL),
+    pszGeomColumn(NULL),
+    pszFIDColumn(NULL),
+    panFieldOrdinals(NULL)
+{}
 
 /************************************************************************/
 /*                         ~OGRGeomediaLayer()                          */
@@ -119,7 +114,8 @@ CPLErr OGRGeomediaLayer::BuildFeatureDefn( const char *pszLayerName,
     {
         OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
 
-        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
+        oField.SetWidth(std::max(static_cast<short>(0),
+                                 poStmtIn->GetColSize(iCol)));
 
         if( pszGeomColumn != NULL
             && EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )
@@ -127,9 +123,9 @@ CPLErr OGRGeomediaLayer::BuildFeatureDefn( const char *pszLayerName,
 
         if( pszGeomColumn == NULL
             && EQUAL(poStmtIn->GetColName(iCol),"Geometry")
-			&& (poStmtIn->GetColType(iCol) == SQL_BINARY ||
-			    poStmtIn->GetColType(iCol) == SQL_VARBINARY ||
-				poStmtIn->GetColType(iCol) == SQL_LONGVARBINARY) )
+            && (poStmtIn->GetColType(iCol) == SQL_BINARY ||
+                poStmtIn->GetColType(iCol) == SQL_VARBINARY ||
+                poStmtIn->GetColType(iCol) == SQL_LONGVARBINARY) )
         {
             pszGeomColumn = CPLStrdup(poStmtIn->GetColName(iCol));
             continue;
@@ -183,7 +179,6 @@ CPLErr OGRGeomediaLayer::BuildFeatureDefn( const char *pszLayerName,
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -203,9 +198,7 @@ OGRFeature *OGRGeomediaLayer::GetNextFeature()
 {
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -264,7 +257,7 @@ OGRFeature *OGRGeomediaLayer::GetNextRawFeature()
         const char *pszValue = poStmt->GetColData( iSrcField );
 
         if( pszValue == NULL )
-            /* no value */;
+            poFeature->SetFieldNull( iField );
         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
             poFeature->SetField( iField,
                                  poStmt->GetColDataLength(iSrcField),
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp
index cc5a24a..b7be567 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediaselectlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeomediaselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaSelectLayer class, layer access to the results
@@ -32,15 +31,15 @@
 #include "cpl_conv.h"
 #include "ogr_geomedia.h"
 
-CPL_CVSID("$Id: ogrgeomediaselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrgeomediaselectlayer.cpp 35175 2016-08-22 03:12:11Z goatbar $");
 
 /************************************************************************/
 /*                        OGRGeomediaSelectLayer()                      */
 /************************************************************************/
 
 OGRGeomediaSelectLayer::OGRGeomediaSelectLayer( OGRGeomediaDataSource *poDSIn,
-                                        CPLODBCStatement * poStmtIn )
-
+                                                CPLODBCStatement * poStmtIn ) :
+    pszBaseStatement(CPLStrdup( poStmtIn->GetCommand() ))
 {
     poDS = poDSIn;
 
@@ -49,7 +48,6 @@ OGRGeomediaSelectLayer::OGRGeomediaSelectLayer( OGRGeomediaDataSource *poDSIn,
     poFeatureDefn = NULL;
 
     poStmt = poStmtIn;
-    pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
 
     BuildFeatureDefn( "SELECT", poStmt );
 }
diff --git a/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp b/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
index 16be49d..6194a96 100644
--- a/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
+++ b/ogr/ogrsf_frmts/geomedia/ogrgeomediatablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeomediatablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGeomediaTableLayer class, access to an existing table.
@@ -31,18 +30,16 @@
 #include "cpl_conv.h"
 #include "ogr_geomedia.h"
 
-CPL_CVSID("$Id: ogrgeomediatablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrgeomediatablelayer.cpp 35910 2016-10-24 14:08:24Z goatbar $");
 
 /************************************************************************/
 /*                          OGRGeomediaTableLayer()                     */
 /************************************************************************/
 
-OGRGeomediaTableLayer::OGRGeomediaTableLayer( OGRGeomediaDataSource *poDSIn )
-
+OGRGeomediaTableLayer::OGRGeomediaTableLayer( OGRGeomediaDataSource *poDSIn ) :
+    pszQuery(NULL)
 {
     poDS = poDSIn;
-    pszQuery = NULL;
-    bUpdateAccess = TRUE;
     iNextShapeId = 0;
     nSRSId = -1;
     poFeatureDefn = NULL;
@@ -67,7 +64,6 @@ CPLErr OGRGeomediaTableLayer::Initialize( const char *pszTableName,
                                           const char *pszGeomCol,
                                           OGRSpatialReference* poSRSIn )
 
-
 {
     CPLODBCSession *poSession = poDS->GetSession();
 
@@ -80,7 +76,7 @@ CPLErr OGRGeomediaTableLayer::Initialize( const char *pszTableName,
     CPLFree( pszFIDColumn );
     pszFIDColumn = NULL;
 
-    this->poSRS = poSRSIn;
+    poSRS = poSRSIn;
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a simple primary key?                                */
@@ -237,20 +233,19 @@ OGRFeature *OGRGeomediaTableLayer::GetFeature( GIntBig nFeatureId )
 OGRErr OGRGeomediaTableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
-    if( (pszQueryIn == NULL && this->pszQuery == NULL)
-        || (pszQueryIn != NULL && this->pszQuery != NULL
-            && EQUAL(pszQueryIn,this->pszQuery)) )
+    if( (pszQueryIn == NULL && pszQuery == NULL)
+        || (pszQueryIn != NULL && pszQuery != NULL
+            && EQUAL(pszQueryIn, pszQuery)) )
         return OGRERR_NONE;
 
-    CPLFree( this->pszQuery );
-    this->pszQuery = pszQueryIn ? CPLStrdup( pszQueryIn ) : NULL;
+    CPLFree( pszQuery );
+    pszQuery = pszQueryIn ? CPLStrdup( pszQueryIn ) : NULL;
 
     ClearStatement();
 
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/georss/ogr_georss.h b/ogr/ogrsf_frmts/georss/ogr_georss.h
index ecb0095..4b2154a 100644
--- a/ogr/ogrsf_frmts/georss/ogr_georss.h
+++ b/ogr/ogrsf_frmts/georss/ogr_georss.h
@@ -68,19 +68,20 @@ class OGRGeoRSSLayer : public OGRLayer
     int                bWriteMode;
     int                nTotalFeatureCount;
 
-    int                eof;
+    // TODO(schwehr): Remove eof?
+    bool               eof;
     int                nNextFID;
     VSILFILE*          fpGeoRSS; /* Large file API */
-    int                bHasReadSchema;
+    bool               bHasReadSchema;
 #ifdef HAVE_EXPAT
     XML_Parser         oParser;
     XML_Parser         oSchemaParser;
 #endif
     OGRGeometry*       poGlobalGeom;
-    int                bStopParsing;
-    int                bInFeature;
-    int                hasFoundLat;
-    int                hasFoundLon;
+    bool               bStopParsing;
+    bool               bInFeature;
+    bool               hasFoundLat;
+    bool               hasFoundLon;
 #ifdef HAVE_EXPAT
     double             latVal;
     double             lonVal;
@@ -91,17 +92,17 @@ class OGRGeoRSSLayer : public OGRLayer
 #ifdef HAVE_EXPAT
     int                iCurrentField;
 #endif
-    int                bInSimpleGeometry;
-    int                bInGMLGeometry;
-    int                bInGeoLat;
-    int                bInGeoLong;
+    bool               bInSimpleGeometry;
+    bool               bInGMLGeometry;
+    bool               bInGeoLat;
+    bool               bInGeoLong;
 #ifdef HAVE_EXPAT
-    int                bFoundGeom;
-    int                bSameSRS;
+    bool               bFoundGeom;
+    bool               bSameSRS;
 #endif
     OGRwkbGeometryType eGeomType;
     char*              pszGMLSRSName;
-    int                bInTagWithSubTag;
+    bool               bInTagWithSubTag;
     char*              pszTagWithSubTag;
     int                currentDepth;
     int                featureDepth;
@@ -122,7 +123,7 @@ class OGRGeoRSSLayer : public OGRLayer
 #ifdef HAVE_EXPAT
     void               AddStrToSubElementValue(const char* pszStr);
 #endif
-    int                IsStandardField(const char* pszName);
+    bool               IsStandardField( const char* pszName );
 
   public:
                         OGRGeoRSSLayer(const char *pszFilename,
@@ -132,17 +133,17 @@ class OGRGeoRSSLayer : public OGRLayer
                                     int bWriteMode = FALSE);
                         ~OGRGeoRSSLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
-    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK );
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
+    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK ) override;
 
-    OGRFeatureDefn *    GetLayerDefn();
+    OGRFeatureDefn *    GetLayerDefn() override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
-    GIntBig             GetFeatureCount( int bForce );
+    GIntBig             GetFeatureCount( int bForce ) override;
 
     void                LoadSchema();
 
@@ -183,8 +184,8 @@ class OGRGeoRSSDataSource : public OGRDataSource
 #endif
     OGRGeoRSSFormat     eFormat;
     OGRGeoRSSGeomDialect eGeomDialect;
-    int                 bUseExtensions;
-    int                 bWriteHeaderAndFooter;
+    bool                bUseExtensions;
+    bool                bWriteHeaderAndFooter;
 #ifdef HAVE_EXPAT
     XML_Parser          oCurrentParser;
     int                 nDataHandlerCounter;
@@ -200,22 +201,22 @@ class OGRGeoRSSDataSource : public OGRDataSource
     int                 Create( const char *pszFilename,
                               char **papszOptions );
 
-    const char*         GetName() { return pszName; }
+    const char*         GetName() override { return pszName; }
 
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer*           GetLayer( int );
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer*           GetLayer( int ) override;
 
     OGRLayer *          ICreateLayer( const char * pszLayerName,
                                     OGRSpatialReference *poSRS,
                                     OGRwkbGeometryType eType,
-                                    char ** papszOptions );
+                                    char ** papszOptions ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     VSILFILE *          GetOutputFP() { return fpOutput; }
     OGRGeoRSSFormat     GetFormat() { return eFormat; }
     OGRGeoRSSGeomDialect GetGeomDialect() { return eGeomDialect; }
-    int                 GetUseExtensions() { return bUseExtensions; }
+    bool                GetUseExtensions() { return bUseExtensions; }
 
 #ifdef HAVE_EXPAT
     void                startElementValidateCbk(const char *pszName, const char **ppszAttr);
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp b/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
index 695a7a6..790f5fa 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorssdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeorssdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSDataSource class
@@ -32,7 +31,7 @@
 #include "cpl_string.h"
 #include "cpl_csv.h"
 
-CPL_CVSID("$Id: ogrgeorssdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrgeorssdatasource.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 /************************************************************************/
 /*                          OGRGeoRSSDataSource()                          */
@@ -48,14 +47,14 @@ OGRGeoRSSDataSource::OGRGeoRSSDataSource() :
 #endif
     eFormat(GEORSS_RSS),
     eGeomDialect(GEORSS_SIMPLE),
-    bUseExtensions(FALSE),
-    bWriteHeaderAndFooter(TRUE)
+    bUseExtensions(false),
+    bWriteHeaderAndFooter(true)
 #ifdef HAVE_EXPAT
     ,
     oCurrentParser(NULL),
     nDataHandlerCounter(0)
 #endif
-{ }
+{}
 
 /************************************************************************/
 /*                         ~OGRGeoRSSDataSource()                          */
@@ -64,11 +63,11 @@ OGRGeoRSSDataSource::OGRGeoRSSDataSource() :
 OGRGeoRSSDataSource::~OGRGeoRSSDataSource()
 
 {
-    if ( fpOutput != NULL )
+    if( fpOutput != NULL )
     {
-        if (bWriteHeaderAndFooter)
+        if( bWriteHeaderAndFooter )
         {
-            if (eFormat == GEORSS_RSS)
+            if( eFormat == GEORSS_RSS )
             {
                 VSIFPrintfL(fpOutput, "  </channel>\n");
                 VSIFPrintfL(fpOutput, "</rss>\n");
@@ -96,10 +95,10 @@ int OGRGeoRSSDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return TRUE;
-    else if( EQUAL(pszCap,ODsCDeleteLayer) )
-        return FALSE;
-    else
-        return FALSE;
+    // else if( EQUAL(pszCap,ODsCDeleteLayer) )
+    //    return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -131,7 +130,7 @@ OGRLayer * OGRGeoRSSDataSource::ICreateLayer( const char * pszLayerName,
     {
         OGRSpatialReference oSRS;
         oSRS.SetWellKnownGeogCS("WGS84");
-        if (poSRS->IsSame(&oSRS) == FALSE)
+        if( !poSRS->IsSame(&oSRS) )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "For a non GML dialect, only WGS84 SRS is supported");
@@ -186,7 +185,6 @@ void OGRGeoRSSDataSource::startElementValidateCbk(const char *pszNameIn, const c
     }
 }
 
-
 /************************************************************************/
 /*                      dataHandlerValidateCbk()                        */
 /************************************************************************/
@@ -202,7 +200,6 @@ void OGRGeoRSSDataSource::dataHandlerValidateCbk(CPL_UNUSED const char *data,
     }
 }
 
-
 static void XMLCALL startElementValidateCbk(void *pUserData, const char *pszName, const char **ppszAttr)
 {
     OGRGeoRSSDataSource* poDS = (OGRGeoRSSDataSource*) pUserData;
@@ -248,8 +245,8 @@ int OGRGeoRSSDataSource::Open( const char * pszFilename, int bUpdateIn)
     oCurrentParser = oParser;
 
     char aBuf[BUFSIZ];
-    int nDone;
-    unsigned int nLen;
+    int nDone = 0;
+    unsigned int nLen = 0;
     int nCount = 0;
 
     /* Begin to parse the file and look for the <rss> or <feed> element */
@@ -309,7 +306,7 @@ int OGRGeoRSSDataSource::Open( const char * pszFilename, int bUpdateIn)
         papoLayers[0] = new OGRGeoRSSLayer( pszName, "georss", this, NULL, FALSE );
     }
 
-    return (validity == GEORSS_VALIDITY_VALID);
+    return validity == GEORSS_VALIDITY_VALID;
 #else
     char aBuf[256];
     VSILFILE* fp = VSIFOpenL(pszFilename, "r");
@@ -328,7 +325,6 @@ int OGRGeoRSSDataSource::Open( const char * pszFilename, int bUpdateIn)
 #endif
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
@@ -338,7 +334,7 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
 {
     if( fpOutput != NULL)
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return FALSE;
     }
 
@@ -402,10 +398,11 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
         }
     }
 
-    const char* pszWriteHeaderAndFooter = CSLFetchNameValue(papszOptions, "WRITE_HEADER_AND_FOOTER");
-    if (pszWriteHeaderAndFooter && CPLTestBool(pszWriteHeaderAndFooter) == FALSE)
+    const char* pszWriteHeaderAndFooter =
+        CSLFetchNameValue(papszOptions, "WRITE_HEADER_AND_FOOTER");
+    if( pszWriteHeaderAndFooter && !CPLTestBool(pszWriteHeaderAndFooter) )
     {
-        bWriteHeaderAndFooter = FALSE;
+        bWriteHeaderAndFooter = false;
         return TRUE;
     }
 
@@ -432,7 +429,6 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
         pszLink = CSLFetchNameValue(papszOptions, "LINK");
         if (pszLink == NULL)
             pszLink = "channel_link";
-
     }
     else if (eFormat == GEORSS_ATOM && pszHeader == NULL)
     {
@@ -453,7 +449,8 @@ int OGRGeoRSSDataSource::Create( const char *pszFilename,
             pszId = "id";
     }
 
-    const char* pszUseExtensions = CSLFetchNameValue( papszOptions, "USE_EXTENSIONS");
+    const char* pszUseExtensions =
+        CSLFetchNameValue( papszOptions, "USE_EXTENSIONS");
     bUseExtensions = pszUseExtensions && CPLTestBool(pszUseExtensions);
 
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp b/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp
index de36da8..a90fe71 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorssdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeorssdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSDriver.
@@ -30,7 +29,7 @@
 #include "ogr_georss.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgeorssdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrgeorssdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
diff --git a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
index 40a60ea..ae4bd70 100644
--- a/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
+++ b/ogr/ogrsf_frmts/georss/ogrgeorsslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeorsslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GeoRSS Translator
  * Purpose:  Implements OGRGeoRSSLayer class.
@@ -33,7 +32,7 @@
 #include "ogr_georss.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeorsslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrgeorsslayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 static const char* const apszAllowedATOMFieldNamesWithSubElements[] =
     { "author", "contributor", NULL };
@@ -86,52 +85,77 @@ OGRGeoRSSLayer::OGRGeoRSSLayer( const char* pszFilename,
                                 OGRGeoRSSDataSource* poDS_,
                                 OGRSpatialReference *poSRSIn,
                                 int bWriteMode_) :
-    poFeatureDefn(NULL), poSRS(poSRSIn), poDS(poDS_), eFormat(GEORSS_ATOM),
-    bWriteMode(bWriteMode_), nTotalFeatureCount(0), eof(FALSE), nNextFID(0),
-    fpGeoRSS(NULL), bHasReadSchema(FALSE),
+    poFeatureDefn(new OGRFeatureDefn( pszLayerName )),
+    poSRS(poSRSIn),
+    poDS(poDS_),
+    eFormat(poDS_->GetFormat()),
+    bWriteMode(bWriteMode_),
+    nTotalFeatureCount(0),
+    eof(false),
+    nNextFID(0),
+    fpGeoRSS(NULL),
+    bHasReadSchema(false),
 #ifdef HAVE_EXPAT
-    oParser(NULL), oSchemaParser(NULL),
+    oParser(NULL),
+    oSchemaParser(NULL),
 #endif
-    poGlobalGeom(NULL), bStopParsing(FALSE), bInFeature(FALSE),
-    hasFoundLat(FALSE), hasFoundLon(FALSE),
+    poGlobalGeom(NULL),
+    bStopParsing(false),
+    bInFeature(false),
+    hasFoundLat(false),
+    hasFoundLon(false),
 #ifdef HAVE_EXPAT
-    latVal(0.0), lonVal(0.0),
+    latVal(0.0),
+    lonVal(0.0),
 #endif
-    pszSubElementName(NULL), pszSubElementValue(NULL), nSubElementValueLen(0),
+    pszSubElementName(NULL),
+    pszSubElementValue(NULL),
+    nSubElementValueLen(0),
 #ifdef HAVE_EXPAT
     iCurrentField(0),
 #endif
-    bInSimpleGeometry(FALSE), bInGMLGeometry(FALSE), bInGeoLat(FALSE),
-    bInGeoLong(FALSE),
+    bInSimpleGeometry(false),
+    bInGMLGeometry(false),
+    bInGeoLat(false),
+    bInGeoLong(false),
 #ifdef HAVE_EXPAT
-    bFoundGeom(FALSE), bSameSRS(FALSE),
+    bFoundGeom(false),
+    bSameSRS(false),
 #endif
-    eGeomType(wkbUnknown), pszGMLSRSName(NULL), bInTagWithSubTag(0),
-    pszTagWithSubTag(NULL), currentDepth(0), featureDepth(0), geometryDepth(0),
+    eGeomType(wkbUnknown),
+    pszGMLSRSName(NULL),
+    bInTagWithSubTag(false),
+    pszTagWithSubTag(NULL),
+    currentDepth(0),
+    featureDepth(0),
+    geometryDepth(0),
 #ifdef HAVE_EXPAT
-    currentFieldDefn(NULL), nWithoutEventCounter(0), nDataHandlerCounter(0),
+    currentFieldDefn(NULL),
+    nWithoutEventCounter(0),
+    nDataHandlerCounter(0),
 #endif
-    setOfFoundFields(NULL), poFeature(NULL),
-    ppoFeatureTab(NULL), nFeatureTabLength(0), nFeatureTabIndex(0)
+    setOfFoundFields(NULL),
+    poFeature(NULL),
+    ppoFeatureTab(NULL),
+    nFeatureTabLength(0),
+    nFeatureTabIndex(0)
 {
-    eFormat = poDS->GetFormat();
-
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
 
-    if (poSRS)
+    if( poSRS )
     {
         poSRS->Reference();
         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
     }
 
-    if (!bWriteMode)
+    if( !bWriteMode )
     {
         fpGeoRSS = VSIFOpenL( pszFilename, "r" );
         if( fpGeoRSS == NULL )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", pszFilename);
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot open %s", pszFilename);
             return;
         }
     }
@@ -159,12 +183,12 @@ OGRGeoRSSLayer::~OGRGeoRSSLayer()
     CPLFree(pszSubElementValue);
     CPLFree(pszGMLSRSName);
     CPLFree(pszTagWithSubTag);
-    if (setOfFoundFields)
+    if( setOfFoundFields )
         CPLHashSetDestroy(setOfFoundFields);
-    if (poGlobalGeom)
+    if( poGlobalGeom )
         delete poGlobalGeom;
 
-    for(int i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+    for( int i = nFeatureTabIndex; i < nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
 
@@ -175,21 +199,18 @@ OGRGeoRSSLayer::~OGRGeoRSSLayer()
         VSIFCloseL( fpGeoRSS );
 }
 
-
 /************************************************************************/
 /*                            GetLayerDefn()                            */
 /************************************************************************/
 
 OGRFeatureDefn * OGRGeoRSSLayer::GetLayerDefn()
 {
-    if (!bHasReadSchema)
+    if( !bHasReadSchema )
         LoadSchema();
 
     return poFeatureDefn;
 }
 
-
-
 #ifdef HAVE_EXPAT
 
 static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
@@ -220,7 +241,7 @@ void OGRGeoRSSLayer::ResetReading()
     if (bWriteMode)
         return;
 
-    eof = FALSE;
+    eof = false;
     nNextFID = 0;
     if (fpGeoRSS)
     {
@@ -235,13 +256,13 @@ void OGRGeoRSSLayer::ResetReading()
         XML_SetUserData(oParser, this);
 #endif
     }
-    bInFeature = FALSE;
-    hasFoundLat = FALSE;
-    hasFoundLon = FALSE;
-    bInSimpleGeometry = FALSE;
-    bInGMLGeometry = FALSE;
-    bInGeoLat = FALSE;
-    bInGeoLong = FALSE;
+    bInFeature = false;
+    hasFoundLat = false;
+    hasFoundLon = false;
+    bInSimpleGeometry = false;
+    bInGMLGeometry = false;
+    bInGeoLat = false;
+    bInGeoLong = false;
     eGeomType = wkbUnknown;
     CPLFree(pszSubElementName);
     pszSubElementName = NULL;
@@ -268,7 +289,7 @@ void OGRGeoRSSLayer::ResetReading()
     currentDepth = 0;
     featureDepth = 0;
     geometryDepth = 0;
-    bInTagWithSubTag = FALSE;
+    bInTagWithSubTag = false;
     CPLFree(pszTagWithSubTag);
     pszTagWithSubTag = NULL;
 }
@@ -287,7 +308,7 @@ void OGRGeoRSSLayer::AddStrToSubElementValue(const char* pszStr)
     if (pszNewSubElementValue == NULL)
     {
         XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
     pszSubElementValue = pszNewSubElementValue;
@@ -316,16 +337,16 @@ static char* OGRGeoRSS_GetOGRCompatibleTagName(const char* pszName)
 /*               OGRGeoRSSLayerATOMTagHasSubElement()                   */
 /************************************************************************/
 
-static int OGRGeoRSSLayerATOMTagHasSubElement(const char* pszName)
+static bool OGRGeoRSSLayerATOMTagHasSubElement( const char* pszName )
 {
-    for( unsigned int i=0;
+    for( unsigned int i = 0;
          apszAllowedATOMFieldNamesWithSubElements[i] != NULL;
          i++ )
     {
         if (strcmp(pszName, apszAllowedATOMFieldNamesWithSubElements[i]) == 0)
-            return TRUE;
+            return true;
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -334,13 +355,13 @@ static int OGRGeoRSSLayerATOMTagHasSubElement(const char* pszName)
 
 void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
 {
-    int bSerializeTag = FALSE;
+    bool bSerializeTag = false;
     const char* pszNoNSName = pszName;
     const char* pszColon = strchr(pszNoNSName, ':');
     if( pszColon )
         pszNoNSName = pszColon + 1;
 
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     if ((eFormat == GEORSS_ATOM && currentDepth == 1 && strcmp(pszNoNSName, "entry") == 0) ||
         ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && !bInFeature &&
@@ -354,22 +375,22 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         poFeature = new OGRFeature( poFeatureDefn );
         poFeature->SetFID( nNextFID++ );
 
-        bInFeature = TRUE;
-        hasFoundLat = FALSE;
-        hasFoundLon = FALSE;
-        bInSimpleGeometry = FALSE;
-        bInGMLGeometry = FALSE;
-        bInGeoLat = FALSE;
-        bInGeoLong = FALSE;
+        bInFeature = true;
+        hasFoundLat = false;
+        hasFoundLon = false;
+        bInSimpleGeometry = false;
+        bInGMLGeometry = false;
+        bInGeoLat = false;
+        bInGeoLong = false;
         eGeomType = wkbUnknown;
         geometryDepth = 0;
-        bInTagWithSubTag = FALSE;
+        bInTagWithSubTag = false;
 
         if (setOfFoundFields)
             CPLHashSetDestroy(setOfFoundFields);
         setOfFoundFields = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
     }
-    else if (bInFeature && bInTagWithSubTag && currentDepth == 3)
+    else if( bInFeature && bInTagWithSubTag && currentDepth == 3 )
     {
         char* pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszTagWithSubTag, pszNoNSName));
 
@@ -385,8 +406,10 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
 
         CPLFree(pszFieldName);
     }
-    else if (bInFeature && eFormat == GEORSS_ATOM &&
-             currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszNoNSName))
+    else if( bInFeature &&
+             eFormat == GEORSS_ATOM &&
+             currentDepth == 2 &&
+             OGRGeoRSSLayerATOMTagHasSubElement(pszNoNSName) )
     {
         CPLFree(pszTagWithSubTag);
         pszTagWithSubTag = CPLStrdup(pszNoNSName);
@@ -400,13 +423,13 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         }
         CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszTagWithSubTag));
 
-        bInTagWithSubTag = TRUE;
+        bInTagWithSubTag = true;
     }
-    else if (bInGMLGeometry)
+    else if( bInGMLGeometry )
     {
-        bSerializeTag = TRUE;
+        bSerializeTag = true;
     }
-    else if (bInSimpleGeometry || bInGeoLat || bInGeoLong)
+    else if( bInSimpleGeometry || bInGeoLat || bInGeoLong )
     {
         /* Should not happen for a valid document. */
     }
@@ -415,14 +438,14 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         CPLFree(pszSubElementValue);
         pszSubElementValue = NULL;
         nSubElementValueLen = 0;
-        bInGeoLat = TRUE;
+        bInGeoLat = true;
     }
     else if (IS_LON_ELEMENT(pszName))
     {
         CPLFree(pszSubElementValue);
         pszSubElementValue = NULL;
         nSubElementValueLen = 0;
-        bInGeoLong = TRUE;
+        bInGeoLong = true;
     }
     else if (strcmp(pszName, "georss:point") == 0 ||
              strcmp(pszName, "georss:line") == 0 ||
@@ -439,7 +462,7 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
                       (strcmp(pszName, "georss:polygon") == 0  ||
                        strcmp(pszName, "georss:box") == 0) ? wkbPolygon :
                                                              wkbUnknown;
-        bInSimpleGeometry = TRUE;
+        bInSimpleGeometry = true;
         geometryDepth = currentDepth;
     }
     else if (strcmp(pszName, "gml:Point") == 0 ||
@@ -454,7 +477,7 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         pszSubElementValue = NULL;
         nSubElementValueLen = 0;
         AddStrToSubElementValue(CPLSPrintf("<%s>", pszName));
-        bInGMLGeometry = TRUE;
+        bInGMLGeometry = true;
         geometryDepth = currentDepth;
         CPLFree(pszGMLSRSName);
         pszGMLSRSName = NULL;
@@ -467,7 +490,7 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             }
         }
     }
-    else if (bInFeature && currentDepth == featureDepth + 1)
+    else if( bInFeature && currentDepth == featureDepth + 1 )
     {
         CPLFree(pszSubElementName);
         pszSubElementName = NULL;
@@ -518,12 +541,14 @@ void OGRGeoRSSLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         }
         CPLFree(pszCompatibleName);
     }
-    else if (bInFeature && currentDepth > featureDepth + 1 && pszSubElementName != NULL)
+    else if( bInFeature &&
+             currentDepth > featureDepth + 1 &&
+             pszSubElementName != NULL )
     {
-        bSerializeTag = TRUE;
+        bSerializeTag = true;
     }
 
-    if (bSerializeTag)
+    if( bSerializeTag )
     {
         AddStrToSubElementValue("<");
         AddStrToSubElementValue(pszName);
@@ -572,7 +597,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
 {
     OGRGeometry* poGeom = NULL;
 
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     currentDepth--;
     const char* pszNoNSName = pszName;
@@ -584,16 +609,16 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
         ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) &&
          (currentDepth == 1 || currentDepth == 2) && strcmp(pszNoNSName, "item") == 0))
     {
-        bInFeature = FALSE;
-        bInTagWithSubTag = FALSE;
+        bInFeature = false;
+        bInTagWithSubTag = false;
 
-        if (hasFoundLat && hasFoundLon)
+        if( hasFoundLat && hasFoundLon )
             poFeature->SetGeometryDirectly( new OGRPoint( lonVal, latVal ) );
         else if (poFeature->GetGeometryRef() == NULL && poGlobalGeom != NULL)
             poFeature->SetGeometry(poGlobalGeom);
 
-        hasFoundLat = FALSE;
-        hasFoundLon = FALSE;
+        hasFoundLat = false;
+        hasFoundLon = false;
 
         if (poSRS != NULL && poFeature->GetGeometryRef() != NULL)
             poFeature->GetGeometryRef()->assignSpatialReference(poSRS);
@@ -617,7 +642,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
         return;
     }
 
-    if (bInTagWithSubTag && currentDepth == 3)
+    if( bInTagWithSubTag && currentDepth == 3 )
     {
         char* pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszTagWithSubTag, pszNoNSName));
 
@@ -640,12 +665,14 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
 
         CPLFree(pszFieldName);
     }
-    else if (bInFeature && eFormat == GEORSS_ATOM &&
-             currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszNoNSName))
+    else if( bInFeature &&
+             eFormat == GEORSS_ATOM &&
+             currentDepth == 2 &&
+             OGRGeoRSSLayerATOMTagHasSubElement(pszNoNSName) )
     {
-        bInTagWithSubTag = FALSE;
+        bInTagWithSubTag = false;
     }
-    else if (bInGMLGeometry)
+    else if( bInGMLGeometry )
     {
         AddStrToSubElementValue("</");
         AddStrToSubElementValue(pszName);
@@ -661,7 +688,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
 
             if (poGeom != NULL && !poGeom->IsEmpty() )
             {
-                int bSwapCoordinates = FALSE;
+                bool bSwapCoordinates = false;
                 if (pszGMLSRSName)
                 {
                     OGRSpatialReference* poSRSFeature = new OGRSpatialReference();
@@ -670,17 +697,19 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
                     poSRSFeature->Release();
                 }
                 else
-                    bSwapCoordinates = TRUE; /* lat, lon WGS 84 */
+                {
+                    bSwapCoordinates = true; /* lat, lon WGS 84 */
+                }
 
-                if (bSwapCoordinates)
+                if( bSwapCoordinates )
                 {
                     poGeom->swapXY();
                 }
             }
-            bInGMLGeometry = FALSE;
+            bInGMLGeometry = false;
         }
     }
-    else if (bInSimpleGeometry)
+    else if( bInSimpleGeometry )
     {
         if (currentDepth > geometryDepth)
         {
@@ -698,7 +727,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
                 /* Caution : Order is latitude, longitude */
                 char** papszTokens =
                         CSLTokenizeStringComplex( pszSubElementValue,
-                                                    " ,", TRUE, FALSE );
+                                                  " ,", TRUE, FALSE );
 
                 int nTokens = CSLCount(papszTokens);
                 if ((nTokens % 2) != 0 ||
@@ -756,30 +785,30 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
 
                 CSLDestroy(papszTokens);
             }
-            bInSimpleGeometry = FALSE;
+            bInSimpleGeometry = false;
         }
     }
     else if (IS_LAT_ELEMENT(pszName))
     {
         if (pszSubElementValue)
         {
-            hasFoundLat = TRUE;
+            hasFoundLat = true;
             pszSubElementValue[nSubElementValueLen] = 0;
             latVal = CPLAtof(pszSubElementValue);
         }
-        bInGeoLat = FALSE;
+        bInGeoLat = false;
     }
     else if (IS_LON_ELEMENT(pszName))
     {
         if (pszSubElementValue)
         {
-            hasFoundLon = TRUE;
+            hasFoundLon = true;
             pszSubElementValue[nSubElementValueLen] = 0;
             lonVal = CPLAtof(pszSubElementValue);
         }
-        bInGeoLong = FALSE;
+        bInGeoLong = false;
     }
-    else if (bInFeature && currentDepth == featureDepth + 1)
+    else if( bInFeature && currentDepth == featureDepth + 1 )
     {
         if (iCurrentField != -1 && pszSubElementName &&
             poFeature && pszSubElementValue && nSubElementValueLen)
@@ -817,7 +846,9 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
         pszSubElementValue = NULL;
         nSubElementValueLen = 0;
     }
-    else if (bInFeature && currentDepth > featureDepth + 1 && pszSubElementName != NULL)
+    else if( bInFeature &&
+             currentDepth > featureDepth + 1 &&
+             pszSubElementName != NULL )
     {
         AddStrToSubElementValue("</");
         AddStrToSubElementValue(pszName);
@@ -830,7 +861,7 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
         {
             poFeature->SetGeometryDirectly(poGeom);
         }
-        else if (!bInFeature)
+        else if( !bInFeature )
         {
             if (poGlobalGeom != NULL)
                 delete poGlobalGeom;
@@ -839,12 +870,13 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
         else
             delete poGeom;
     }
-    else if (!bInFeature && hasFoundLat && hasFoundLon)
+    else if( !bInFeature && hasFoundLat && hasFoundLon )
     {
         if (poGlobalGeom != NULL)
                 delete poGlobalGeom;
         poGlobalGeom = new OGRPoint( lonVal, latVal );
-        hasFoundLat = hasFoundLon = FALSE;
+        hasFoundLat = false;
+        hasFoundLon = false;
     }
 }
 
@@ -854,18 +886,20 @@ void OGRGeoRSSLayer::endElementCbk(const char *pszName)
 
 void OGRGeoRSSLayer::dataHandlerCbk(const char *data, int nLen)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
-    if (bInGMLGeometry == TRUE || bInSimpleGeometry == TRUE ||
-        bInGeoLat == TRUE || bInGeoLong == TRUE ||
-        pszSubElementName != NULL)
+    if( bInGMLGeometry ||
+        bInSimpleGeometry ||
+        bInGeoLat ||
+        bInGeoLong  ||
+        pszSubElementName != NULL )
     {
         char* pszNewSubElementValue = (char*) VSI_REALLOC_VERBOSE(pszSubElementValue,
                                                nSubElementValueLen + nLen + 1);
         if (pszNewSubElementValue == NULL)
         {
             XML_StopParser(oSchemaParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
             return;
         }
         pszSubElementValue = pszNewSubElementValue;
@@ -891,10 +925,10 @@ OGRFeature *OGRGeoRSSLayer::GetNextFeature()
     if (fpGeoRSS == NULL)
         return NULL;
 
-    if (!bHasReadSchema)
+    if( !bHasReadSchema )
         LoadSchema();
 
-    if (bStopParsing)
+    if( bStopParsing )
         return NULL;
 
 #ifdef HAVE_EXPAT
@@ -913,7 +947,7 @@ OGRFeature *OGRGeoRSSLayer::GetNextFeature()
     nFeatureTabLength = 0;
     nFeatureTabIndex = 0;
 
-    int nDone;
+    int nDone = 0;
     do
     {
         unsigned int nLen =
@@ -927,9 +961,9 @@ OGRFeature *OGRGeoRSSLayer::GetNextFeature()
                      XML_ErrorString(XML_GetErrorCode(oParser)),
                      (int)XML_GetCurrentLineNumber(oParser),
                      (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
-    } while (!nDone && !bStopParsing && nFeatureTabLength == 0);
+    } while( !nDone && !bStopParsing && nFeatureTabLength == 0 );
 
     return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
 #else
@@ -941,14 +975,15 @@ OGRFeature *OGRGeoRSSLayer::GetNextFeature()
 /*              OGRGeoRSSLayerIsStandardFieldInternal()                 */
 /************************************************************************/
 
-static int OGRGeoRSSLayerIsStandardFieldInternal(const char* pszName,
-                                                 const char* const * papszNames)
+static bool OGRGeoRSSLayerIsStandardFieldInternal(
+    const char* pszName,
+    const char* const * papszNames )
 {
     for( unsigned int i = 0; papszNames[i] != NULL; i++)
     {
         if (strcmp(pszName, papszNames[i]) == 0)
         {
-            return TRUE;
+            return true;
         }
 
         const char* pszUnderscore = strchr(papszNames[i], '_');
@@ -961,7 +996,7 @@ static int OGRGeoRSSLayerIsStandardFieldInternal(const char* pszName,
                 while(pszName[k] >= '0' && pszName[k] <= '9')
                     k++;
                 if (pszName[k] == '\0')
-                    return TRUE;
+                    return true;
             }
         }
         else
@@ -973,28 +1008,28 @@ static int OGRGeoRSSLayerIsStandardFieldInternal(const char* pszName,
                 while(pszName[k] >= '0' && pszName[k] <= '9')
                     k++;
                 if (pszName[k] == '_' && strcmp(pszName + k, pszUnderscore) == 0)
-                    return TRUE;
+                    return true;
             }
         }
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*               OGRGeoRSSLayer::IsStandardField()                      */
 /************************************************************************/
 
-int OGRGeoRSSLayer::IsStandardField(const char* pszName)
+bool OGRGeoRSSLayer::IsStandardField( const char* pszName )
 {
-    if (eFormat == GEORSS_RSS)
+    if( eFormat == GEORSS_RSS )
     {
         return OGRGeoRSSLayerIsStandardFieldInternal(pszName,
-                apszAllowedRSSFieldNames);
+                                                     apszAllowedRSSFieldNames);
     }
     else
     {
         return OGRGeoRSSLayerIsStandardFieldInternal(pszName,
-                apszAllowedATOMFieldNames);
+                                                     apszAllowedATOMFieldNames);
     }
 }
 
@@ -1068,7 +1103,7 @@ static void OGRGeoRSSLayerWriteSimpleElement(VSILFILE* fp,
             const char* pszAttributeName = papszNames[k] + strlen(pszElementName) + 1;
             char* pszFieldName = CPLStrdup(CPLSPrintf("%s%s_%s", pszElementName, pszNumber, pszAttributeName));
             int iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-            if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
+            if (iIndex != -1 && poFeature->IsFieldSetAndNotNull( iIndex ))
             {
                 char* pszValue =
                         OGRGetXML_UTF8_EscapedString(poFeature->GetFieldAsString( iIndex ));
@@ -1081,7 +1116,7 @@ static void OGRGeoRSSLayerWriteSimpleElement(VSILFILE* fp,
 
     char* pszFieldName = CPLStrdup(CPLSPrintf("%s%s", pszElementName, pszNumber));
     int iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-    if (iIndex != -1 && poFeature->IsFieldSet( iIndex ))
+    if (iIndex != -1 && poFeature->IsFieldSetAndNotNull( iIndex ))
     {
         VSIFPrintfL(fp, ">");
 
@@ -1120,8 +1155,10 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
 
         VSIFPrintfL(fp, "    <item>\n");
 
-        if ((iFieldTitle == -1 || poFeatureIn->IsFieldSet( iFieldTitle ) == FALSE) &&
-            (iFieldDescription == -1 || poFeatureIn->IsFieldSet( iFieldDescription ) == FALSE))
+        if( (iFieldTitle == -1 ||
+             !poFeatureIn->IsFieldSetAndNotNull( iFieldTitle )) &&
+            (iFieldDescription == -1 ||
+             !poFeatureIn->IsFieldSetAndNotNull( iFieldDescription )) )
         {
             VSIFPrintfL(fp, "      <title>Feature %d</title>\n", nNextFID);
         }
@@ -1134,17 +1171,18 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
         int iFieldTitle = poFeatureDefn->GetFieldIndex( "title" );
         int iFieldUpdated = poFeatureDefn->GetFieldIndex( "updated" );
 
-        if (iFieldId == -1 || poFeatureIn->IsFieldSet( iFieldId ) == FALSE)
+        if( iFieldId == -1 || !poFeatureIn->IsFieldSetAndNotNull( iFieldId ) )
         {
             VSIFPrintfL(fp, "      <id>Feature %d</id>\n", nNextFID);
         }
 
-        if (iFieldTitle == -1 || poFeatureIn->IsFieldSet( iFieldTitle ) == FALSE)
+        if( iFieldTitle == -1 || !poFeatureIn->IsFieldSetAndNotNull( iFieldTitle ) )
         {
             VSIFPrintfL(fp, "      <title>Title for feature %d</title>\n", nNextFID);
         }
 
-        if (iFieldUpdated == -1 || poFeatureIn->IsFieldSet(iFieldUpdated ) == FALSE)
+        if( iFieldUpdated == -1 ||
+            !poFeatureIn->IsFieldSetAndNotNull(iFieldUpdated) )
         {
             VSIFPrintfL(fp, "      <updated>2009-01-01T00:00:00Z</updated>\n");
         }
@@ -1158,15 +1196,16 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
         const char* pszName = poFieldDefn->GetNameRef();
 
-        if ( ! poFeatureIn->IsFieldSet( i ) )
+        if ( ! poFeatureIn->IsFieldSetAndNotNull( i ) )
             continue;
 
-        char* pszElementName;
-        char* pszNumber;
-        char* pszAttributeName;
-        OGRGeoRSSLayerSplitComposedField(pszName, &pszElementName, &pszNumber, &pszAttributeName);
+        char* pszElementName = NULL;
+        char* pszNumber = NULL;
+        char* pszAttributeName = NULL;
+        OGRGeoRSSLayerSplitComposedField(pszName, &pszElementName, &pszNumber,
+                                         &pszAttributeName);
 
-        int bWillSkip = FALSE;
+        bool bWillSkip = false;
         /* Handle Atom entries with elements with sub-elements like */
         /* <author><name>...</name><uri>...</uri></author */
         if (eFormat == GEORSS_ATOM)
@@ -1178,7 +1217,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
                 if (strcmp(pszElementName, apszAllowedATOMFieldNamesWithSubElements[k]) == 0 &&
                     pszAttributeName != NULL)
                 {
-                    bWillSkip = TRUE;
+                    bWillSkip = true;
                     if (pbUsed[i])
                         break;
 
@@ -1187,14 +1226,15 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
                     for( int j = i; j < nFieldCount; j++ )
                     {
                         poFieldDefn = poFeatureDefn->GetFieldDefn( j );
-                        if ( ! poFeatureIn->IsFieldSet( j ) )
+                        if ( ! poFeatureIn->IsFieldSetAndNotNull( j ) )
                             continue;
 
-                        char* pszElementName2;
-                        char* pszNumber2;
-                        char* pszAttributeName2;
-                        OGRGeoRSSLayerSplitComposedField(poFieldDefn->GetNameRef(),
-                                &pszElementName2, &pszNumber2, &pszAttributeName2);
+                        char* pszElementName2 = NULL;
+                        char* pszNumber2 = NULL;
+                        char* pszAttributeName2 = NULL;
+                        OGRGeoRSSLayerSplitComposedField(
+                            poFieldDefn->GetNameRef(),
+                            &pszElementName2, &pszNumber2, &pszAttributeName2);
 
                         if (strcmp(pszElementName2, pszElementName) == 0 &&
                             strcmp(pszNumber, pszNumber2) == 0 && pszAttributeName2 != NULL)
@@ -1218,7 +1258,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
             }
         }
 
-        if (bWillSkip)
+        if( bWillSkip )
         {
             /* Do nothing */
         }
@@ -1286,16 +1326,15 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
                  (STARTS_WITH(pszName, "content") ||
                   STARTS_WITH(pszName, "summary")))
         {
-            char* pszFieldName;
-            int iIndex;
             if (strchr(pszName, '_') == NULL)
             {
                 VSIFPrintfL(fp, "      <%s", pszName);
 
                 int bIsXHTML = FALSE;
-                pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "type"));
-                iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-                if (iIndex != -1 && poFeatureIn->IsFieldSet( iIndex ))
+                char* pszFieldName =
+                    CPLStrdup(CPLSPrintf("%s_%s", pszName, "type"));
+                int iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
+                if (iIndex != -1 && poFeatureIn->IsFieldSetAndNotNull( iIndex ))
                 {
                     bIsXHTML = strcmp(poFeatureIn->GetFieldAsString( iIndex ), "xhtml") == 0;
                     char* pszValue =
@@ -1307,7 +1346,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
 
                 pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_lang"));
                 iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-                if (iIndex != -1 && poFeatureIn->IsFieldSet( iIndex ))
+                if (iIndex != -1 && poFeatureIn->IsFieldSetAndNotNull( iIndex ))
                 {
                     char* pszValue =
                             OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( iIndex ));
@@ -1318,7 +1357,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
 
                 pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_base"));
                 iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-                if (iIndex != -1 && poFeatureIn->IsFieldSet( iIndex ))
+                if (iIndex != -1 && poFeatureIn->IsFieldSetAndNotNull( iIndex ))
                 {
                     char* pszValue =
                             OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( iIndex ));
@@ -1342,15 +1381,14 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
         }
         else if (STARTS_WITH(pszName, "dc_subject"))
         {
-            char* pszFieldName;
-            int iIndex;
             if (strchr(pszName+strlen("dc_subject"), '_') == NULL)
             {
                 VSIFPrintfL(fp, "      <%s", "dc:subject");
 
-                pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_lang"));
-                iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
-                if (iIndex != -1 && poFeatureIn->IsFieldSet( iIndex ))
+                char* pszFieldName =
+                    CPLStrdup(CPLSPrintf("%s_%s", pszName, "xml_lang"));
+                int iIndex = poFeatureDefn->GetFieldIndex(pszFieldName);
+                if (iIndex != -1 && poFeatureIn->IsFieldSetAndNotNull( iIndex ))
                 {
                     char* pszValue =
                             OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( iIndex ));
@@ -1408,7 +1446,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
     if ( poGeom != NULL && !poGeom->IsEmpty() )
     {
         char* pszURN = NULL;
-        int bSwapCoordinates = FALSE;
+        bool bSwapCoordinates = false;
         if (eGeomDialect == GEORSS_GML)
         {
             if (poSRS != NULL)
@@ -1430,7 +1468,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
                     if (poSRS->IsGeographic() &&
                         (pszAxisName == NULL || STARTS_WITH_CI(pszAxisName, "Lon")))
                     {
-                        bSwapCoordinates = TRUE;
+                        bSwapCoordinates = true;
                     }
                 }
                 else
@@ -1445,7 +1483,7 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
             }
             else
             {
-                bSwapCoordinates = TRUE;
+                bSwapCoordinates = true;
             }
         }
 
@@ -1464,13 +1502,18 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
                         VSIFPrintfL(fp, " srsName=\"%s\"", pszURN);
                     if (poGeom->getCoordinateDimension() == 3)
                     {
-                        OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
-                                             poPoint->getZ(), 3);
+                        OGRMakeWktCoordinate(
+                            szCoord,
+                            bSwapCoordinates ? y : x,
+                            bSwapCoordinates ? x : y,
+                            poPoint->getZ(), 3);
                         VSIFPrintfL(fp, " srsDimension=\"3\"><gml:pos>%s", szCoord);
                     }
                     else
                     {
-                        OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
+                        OGRMakeWktCoordinate(szCoord,
+                                             bSwapCoordinates ? y : x,
+                                             bSwapCoordinates ? x : y,
                                              0, 2);
                         VSIFPrintfL(fp, "><gml:pos>%s", szCoord);
                     }
@@ -1505,7 +1548,9 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
                     {
                         double x = poLineString->getX(i);
                         double y = poLineString->getY(i);
-                        OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
+                        OGRMakeWktCoordinate(szCoord,
+                                             bSwapCoordinates ? y : x,
+                                             bSwapCoordinates ? x : y,
                                              0, 2);
                         VSIFPrintfL(fp, "%s ", szCoord);
                     }
@@ -1549,7 +1594,9 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
                     {
                         double x = poLineString->getX(i);
                         double y = poLineString->getY(i);
-                        OGRMakeWktCoordinate(szCoord, (bSwapCoordinates) ? y : x, (bSwapCoordinates) ? x : y,
+                        OGRMakeWktCoordinate(szCoord,
+                                             bSwapCoordinates ? y : x,
+                                             bSwapCoordinates ? x : y,
                                              0, 2);
                         VSIFPrintfL(fp, "%s ", szCoord);
                     }
@@ -1590,8 +1637,6 @@ OGRErr OGRGeoRSSLayer::ICreateFeature( OGRFeature *poFeatureIn )
     return OGRERR_NONE;
 }
 
-
-
 /************************************************************************/
 /*                            CreateField()                             */
 /************************************************************************/
@@ -1657,7 +1702,6 @@ static void XMLCALL dataHandlerLoadSchemaCbk(void *pUserData, const char *data,
     ((OGRGeoRSSLayer*)pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
 }
 
-
 /************************************************************************/
 /*                       LoadSchema()                         */
 /************************************************************************/
@@ -1665,10 +1709,10 @@ static void XMLCALL dataHandlerLoadSchemaCbk(void *pUserData, const char *data,
 /** This function parses the whole file to detect the fields */
 void OGRGeoRSSLayer::LoadSchema()
 {
-    if (bHasReadSchema)
+    if( bHasReadSchema )
         return;
 
-    bHasReadSchema = TRUE;
+    bHasReadSchema = true;
 
     if (fpGeoRSS == NULL)
         return;
@@ -1680,26 +1724,26 @@ void OGRGeoRSSLayer::LoadSchema()
 
     VSIFSeekL( fpGeoRSS, 0, SEEK_SET );
 
-    bInFeature = FALSE;
+    bInFeature = false;
     currentDepth = 0;
     currentFieldDefn = NULL;
     pszSubElementName = NULL;
     pszSubElementValue = NULL;
     nSubElementValueLen = 0;
-    bSameSRS = TRUE;
+    bSameSRS = true;
     CPLFree(pszGMLSRSName);
     pszGMLSRSName = NULL;
     eGeomType = wkbUnknown;
-    bFoundGeom = FALSE;
-    bInTagWithSubTag = FALSE;
+    bFoundGeom = false;
+    bInTagWithSubTag = false;
     pszTagWithSubTag = NULL;
-    bStopParsing = FALSE;
+    bStopParsing = false;
     nWithoutEventCounter = 0;
     nTotalFeatureCount = 0;
     setOfFoundFields = NULL;
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -1712,10 +1756,10 @@ void OGRGeoRSSLayer::LoadSchema()
                      XML_ErrorString(XML_GetErrorCode(oSchemaParser)),
                      (int)XML_GetCurrentLineNumber(oSchemaParser),
                      (int)XML_GetCurrentColumnNumber(oSchemaParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
         nWithoutEventCounter ++;
-    } while (!nDone && !bStopParsing && nWithoutEventCounter < 10);
+    } while( !nDone && !bStopParsing && nWithoutEventCounter < 10 );
 
     XML_ParserFree(oSchemaParser);
 
@@ -1723,11 +1767,11 @@ void OGRGeoRSSLayer::LoadSchema()
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
 
     CPLAssert(poSRS == NULL);
-    if (bSameSRS && bFoundGeom)
+    if( bSameSRS && bFoundGeom )
     {
         if (pszGMLSRSName == NULL)
         {
@@ -1757,7 +1801,6 @@ void OGRGeoRSSLayer::LoadSchema()
     VSIFSeekL( fpGeoRSS, 0, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                         OGRGeoRSSIsInt()                             */
 /************************************************************************/
@@ -1786,7 +1829,7 @@ static int OGRGeoRSSIsInt(const char* pszStr)
 
 void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char **ppszAttr)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
     const char* pszNoNSName = pszName;
@@ -1798,7 +1841,7 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
         ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) && !bInFeature &&
         (currentDepth == 1 || currentDepth == 2) && strcmp(pszNoNSName, "item") == 0))
     {
-        bInFeature = TRUE;
+        bInFeature = true;
         featureDepth = currentDepth;
 
         nTotalFeatureCount ++;
@@ -1807,7 +1850,7 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
             CPLHashSetDestroy(setOfFoundFields);
         setOfFoundFields = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
     }
-    else if (bInTagWithSubTag && currentDepth == 3)
+    else if( bInTagWithSubTag && currentDepth == 3 )
     {
         char* pszFieldName = CPLStrdup(CPLSPrintf("%s_%s", pszTagWithSubTag, pszNoNSName));
         if (poFeatureDefn->GetFieldIndex(pszFieldName) == -1)
@@ -1820,13 +1863,15 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
                 CPLError(CE_Failure, CPLE_AppDefined,
                         "Too many fields. File probably corrupted");
                 XML_StopParser(oSchemaParser, XML_FALSE);
-                bStopParsing = TRUE;
+                bStopParsing = true;
             }
         }
         CPLFree(pszFieldName);
     }
-    else if (bInFeature && eFormat == GEORSS_ATOM &&
-             currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszNoNSName))
+    else if( bInFeature &&
+             eFormat == GEORSS_ATOM &&
+             currentDepth == 2 &&
+             OGRGeoRSSLayerATOMTagHasSubElement(pszNoNSName) )
     {
         CPLFree(pszTagWithSubTag);
         pszTagWithSubTag = CPLStrdup(pszNoNSName);
@@ -1840,15 +1885,17 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
             if (pszTagWithSubTag[0] == 0)
             {
                 XML_StopParser(oSchemaParser, XML_FALSE);
-                bStopParsing = TRUE;
+                bStopParsing = true;
                 break;
             }
         }
         CPLHashSetInsert(setOfFoundFields, CPLStrdup(pszTagWithSubTag));
 
-        bInTagWithSubTag = TRUE;
+        bInTagWithSubTag = true;
     }
-    else if (bInFeature && currentDepth == featureDepth + 1 && !IS_GEO_ELEMENT(pszName))
+    else if( bInFeature &&
+             currentDepth == featureDepth + 1 &&
+             !IS_GEO_ELEMENT(pszName) )
     {
         if( pszName != pszNoNSName && STARTS_WITH(pszName, "atom:") )
             pszName = pszNoNSName;
@@ -1894,17 +1941,19 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
                 CPLError(CE_Failure, CPLE_AppDefined,
                         "Too many fields. File probably corrupted");
                 XML_StopParser(oSchemaParser, XML_FALSE);
-                bStopParsing = TRUE;
+                bStopParsing = true;
             }
         }
 
         /* Create field definitions for attributes */
-        for(int i=0; ppszAttr[i] != NULL && ppszAttr[i+1] != NULL && !bStopParsing; i+= 2)
+        for( int i=0;
+             ppszAttr[i] != NULL && ppszAttr[i+1] != NULL && !bStopParsing;
+             i+= 2 )
         {
             char* pszAttrCompatibleName =
                     OGRGeoRSS_GetOGRCompatibleTagName(CPLSPrintf("%s_%s", pszSubElementName, ppszAttr[i]));
             iField = poFeatureDefn->GetFieldIndex(pszAttrCompatibleName);
-            OGRFieldDefn* currentAttrFieldDefn;
+            OGRFieldDefn* currentAttrFieldDefn = NULL;
             if (iField >= 0)
             {
                 currentAttrFieldDefn = poFeatureDefn->GetFieldDefn(iField);
@@ -1920,7 +1969,7 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
                     CPLError(CE_Failure, CPLE_AppDefined,
                             "Too many fields. File probably corrupted");
                     XML_StopParser(oSchemaParser, XML_FALSE);
-                    bStopParsing = TRUE;
+                    bStopParsing = true;
                 }
             }
             if (currentAttrFieldDefn->GetType() == OFTInteger ||
@@ -1934,7 +1983,7 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
                 {
                     if (currentAttrFieldDefn->GetType() == OFTInteger)
                     {
-                        if (OGRGeoRSSIsInt(ppszAttr[i + 1]) == FALSE)
+                        if( !OGRGeoRSSIsInt(ppszAttr[i + 1]) )
                         {
                             currentAttrFieldDefn->SetType(OFTReal);
                         }
@@ -1957,10 +2006,10 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
              strcmp(pszName, "georss:polygon") == 0 ||
              strcmp(pszName, "georss:box") == 0)
     {
-        if (bSameSRS)
+        if( bSameSRS )
         {
-            if (pszGMLSRSName != NULL)
-                bSameSRS = FALSE;
+            if( pszGMLSRSName != NULL )
+                bSameSRS = false;
         }
     }
     else if (strcmp(pszName, "gml:Point") == 0 ||
@@ -1971,30 +2020,30 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
              strcmp(pszName, "gml:MultiPolygon") == 0 ||
              strcmp(pszName, "gml:Envelope") == 0)
     {
-        if (bSameSRS)
+        if( bSameSRS )
         {
-            int bFoundSRS = FALSE;
+            bool bFoundSRS = false;
             for(int i = 0; ppszAttr[i] != NULL; i+=2)
             {
                 if (strcmp(ppszAttr[i], "srsName") == 0)
                 {
-                    bFoundSRS = TRUE;
+                    bFoundSRS = true;
                     if (pszGMLSRSName != NULL)
                     {
                         if (strcmp(pszGMLSRSName , ppszAttr[i+1]) != 0)
-                            bSameSRS = FALSE;
+                            bSameSRS = false;
                     }
                     else
                         pszGMLSRSName = CPLStrdup(ppszAttr[i+1]);
                     break;
                 }
             }
-            if (!bFoundSRS && pszGMLSRSName != NULL)
-                bSameSRS = FALSE;
+            if( !bFoundSRS && pszGMLSRSName != NULL )
+                bSameSRS = false;
         }
     }
 
-    if (!bInFeature || currentDepth >= featureDepth + 1)
+    if( !bInFeature || currentDepth >= featureDepth + 1 )
     {
         int nDimension = 2;
         for(int i = 0; ppszAttr[i] != NULL && ppszAttr[i+1] != NULL; i+=2)
@@ -2041,10 +2090,10 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
 
         if (eFoundGeomType != wkbUnknown)
         {
-            if (!bFoundGeom)
+            if( !bFoundGeom )
             {
                 eGeomType = eFoundGeomType;
-                bFoundGeom = TRUE;
+                bFoundGeom = true;
             }
             else if (wkbFlatten(eGeomType) != eFoundGeomType)
                 eGeomType = wkbUnknown;
@@ -2063,13 +2112,13 @@ void OGRGeoRSSLayer::startElementLoadSchemaCbk(const char *pszName, const char *
 
 void OGRGeoRSSLayer::endElementLoadSchemaCbk(const char *pszName)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
 
     currentDepth--;
 
-    if (!bInFeature)
+    if( !bInFeature )
         return;
 
     const char* pszNoNSName = pszName;
@@ -2081,12 +2130,14 @@ void OGRGeoRSSLayer::endElementLoadSchemaCbk(const char *pszName)
         ((eFormat == GEORSS_RSS || eFormat == GEORSS_RSS_RDF) &&
         (currentDepth == 1 || currentDepth == 2) && strcmp(pszNoNSName, "item") == 0))
     {
-        bInFeature = FALSE;
+        bInFeature = false;
     }
-    else if (bInFeature && eFormat == GEORSS_ATOM &&
-                currentDepth == 2 && OGRGeoRSSLayerATOMTagHasSubElement(pszNoNSName))
+    else if( bInFeature &&
+             eFormat == GEORSS_ATOM &&
+             currentDepth == 2 &&
+             OGRGeoRSSLayerATOMTagHasSubElement(pszNoNSName) )
     {
-        bInTagWithSubTag = FALSE;
+        bInTagWithSubTag = false;
     }
     else if (currentDepth == featureDepth + 1 && pszSubElementName)
     {
@@ -2105,7 +2156,7 @@ void OGRGeoRSSLayer::endElementLoadSchemaCbk(const char *pszName)
                 {
                     if (currentFieldDefn->GetType() == OFTInteger)
                     {
-                        if (OGRGeoRSSIsInt(pszSubElementValue) == FALSE)
+                        if( !OGRGeoRSSIsInt(pszSubElementValue) )
                         {
                             currentFieldDefn->SetType(OFTReal);
                         }
@@ -2133,14 +2184,15 @@ void OGRGeoRSSLayer::endElementLoadSchemaCbk(const char *pszName)
 
 void OGRGeoRSSLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
-    nDataHandlerCounter ++;
+    nDataHandlerCounter++;
     if (nDataHandlerCounter >= BUFSIZ)
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "File probably corrupted (million laugh pattern)");
         XML_StopParser(oSchemaParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
@@ -2152,7 +2204,7 @@ void OGRGeoRSSLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
         if (pszNewSubElementValue == NULL)
         {
             XML_StopParser(oSchemaParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
             return;
         }
         pszSubElementValue = pszNewSubElementValue;
@@ -2163,7 +2215,7 @@ void OGRGeoRSSLayer::dataHandlerLoadSchemaCbk(const char *data, int nLen)
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Too much data inside one element. File probably corrupted");
             XML_StopParser(oSchemaParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
     }
 }
@@ -2182,7 +2234,7 @@ int OGRGeoRSSLayer::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCFastFeatureCount) )
         return !bWriteMode && bHasReadSchema &&
-                m_poFilterGeom == NULL && m_poAttrQuery == NULL;
+               m_poFilterGeom == NULL && m_poAttrQuery == NULL;
 
     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return TRUE;
@@ -2209,7 +2261,7 @@ GIntBig OGRGeoRSSLayer::GetFeatureCount( int bForce )
         return 0;
     }
 
-    if (!bHasReadSchema)
+    if( !bHasReadSchema )
         LoadSchema();
 
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
diff --git a/ogr/ogrsf_frmts/gft/drv_gft.html b/ogr/ogrsf_frmts/gft/drv_gft.html
index 25dde47..6addd06 100644
--- a/ogr/ogrsf_frmts/gft/drv_gft.html
+++ b/ogr/ogrsf_frmts/gft/drv_gft.html
@@ -18,7 +18,7 @@ The driver supports read and write operations.<p>
 
 The minimal syntax to open a GFT datasource is : <pre>GFT:</pre><p>
 
-Additionnal optional parameters can be specified after the ':' sign such as :<p>
+Additional optional parameters can be specified after the ':' sign such as :<p>
 
 <ul>
 <li> <b>tables=table_id1[,table_id2]*</b>: A list of table IDs. This is necessary when you need to access to public tables for example.
diff --git a/ogr/ogrsf_frmts/gft/ogr_gft.h b/ogr/ogrsf_frmts/gft/ogr_gft.h
index 01e6084..9ad1871 100644
--- a/ogr/ogrsf_frmts/gft/ogr_gft.h
+++ b/ogr/ogrsf_frmts/gft/ogr_gft.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gft.h 33138 2016-01-24 11:18:11Z rouault $
+ * $Id: ogr_gft.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Definition of classes for OGR Google Fusion Tables driver.
@@ -71,19 +71,19 @@ protected:
     void                SetGeomFieldName();
 
   public:
-                         OGRGFTLayer(OGRGFTDataSource* poDS);
-                        ~OGRGFTLayer();
+    explicit              OGRGFTLayer(OGRGFTDataSource* poDS);
+                         virtual ~OGRGFTLayer();
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
-    virtual OGRErr              SetNextByIndex( GIntBig nIndex );
+    virtual OGRErr              SetNextByIndex( GIntBig nIndex ) override;
 
-    const char *        GetDefaultGeometryColumnName() { return "geometry"; }
+    static const char *         GetDefaultGeometryColumnName() { return "geometry"; }
 
     static int                  ParseCSVResponse(char* pszLine,
                                                  std::vector<CPLString>& aosRes);
@@ -93,7 +93,7 @@ protected:
     int                         GetLatitudeFieldIndex() { return iLatitudeField; }
     int                         GetLongitudeFieldIndex() { return iLongitudeField; }
 
-    int                         GetFeaturesToFetch() { return atoi(CPLGetConfigOption("GFT_PAGE_SIZE", "500")); }
+    static int                  GetFeaturesToFetch() { return atoi(CPLGetConfigOption("GFT_PAGE_SIZE", "500")); }
 };
 
 /************************************************************************/
@@ -112,54 +112,54 @@ class OGRGFTTableLayer : public OGRGFTLayer
     CPLString           osWHERE;
     CPLString           osQuery;
 
-    void                BuildWhere(void);
+    void                BuildWhere();
 
     CPLString          osTransaction;
     int                bInTransaction;
     int                nFeaturesInTransaction;
 
     int                FetchDescribe();
-    virtual int                FetchNextRows();
+    virtual int        FetchNextRows() override;
 
     OGRwkbGeometryType eGTypeForCreation;
 
     std::vector<CPLString>  aosColumnInternalName;
 
     public:
-            OGRGFTTableLayer(OGRGFTDataSource* poDS,
-                             const char* pszTableName,
-                             const char* pszTableId = "",
-                             const char* pszGeomColumnName = "");
-            ~OGRGFTTableLayer();
+            OGRGFTTableLayer( OGRGFTDataSource* poDS,
+                              const char* pszTableName,
+                              const char* pszTableId = "",
+                              const char* pszGeomColumnName = "" );
+            virtual ~OGRGFTTableLayer();
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
 
-    virtual const char *        GetName() { return osTableName.c_str(); }
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
+    virtual const char *        GetName() override { return osTableName.c_str(); }
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
 
-    virtual OGRFeature *        GetFeature( GIntBig nFID );
+    virtual OGRFeature *        GetFeature( GIntBig nFID ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+                                     int bApproxOK = TRUE ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction() override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
     const CPLString&            GetTableId() const { return osTableId; }
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     void                SetGeometryType(OGRwkbGeometryType eGType);
 };
@@ -173,14 +173,14 @@ class OGRGFTResultLayer : public OGRGFTLayer
     CPLString   osSQL;
     int         bGotAllRows;
 
-    virtual int                FetchNextRows();
+    virtual int                FetchNextRows() override;
 
     public:
             OGRGFTResultLayer(OGRGFTDataSource* poDS,
                               const char* pszSQL);
-            ~OGRGFTResultLayer();
+            virtual ~OGRGFTResultLayer();
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 
     int     RunSQL();
 };
@@ -213,29 +213,29 @@ class OGRGFTDataSource : public OGRDataSource
 
   public:
                         OGRGFTDataSource();
-                        ~OGRGFTDataSource();
+                        virtual ~OGRGFTDataSource();
 
     int                 Open( const char * pszFilename,
                               int bUpdate );
 
-    virtual const char* GetName() { return pszName; }
+    virtual const char* GetName() override { return pszName; }
 
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer*   GetLayer( int );
-    virtual OGRLayer    *GetLayerByName(const char *);
+    virtual int         GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*   GetLayer( int ) override;
+    virtual OGRLayer    *GetLayerByName(const char *) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
-                                     char ** papszOptions = NULL );
-    virtual OGRErr      DeleteLayer(int);
+                                     char ** papszOptions = NULL ) override;
+    virtual OGRErr      DeleteLayer(int) override;
 
     virtual OGRLayer*  ExecuteSQL( const char *pszSQLCommand,
                                    OGRGeometry *poSpatialFilter,
-                                   const char *pszDialect );
-    virtual void       ReleaseResultSet( OGRLayer * poLayer );
+                                   const char *pszDialect ) override;
+    virtual void       ReleaseResultSet( OGRLayer * poLayer ) override;
 
     const CPLString&            GetAccessToken() const { return osAccessToken;}
     const char*                 GetAPIURL() const;
@@ -251,13 +251,13 @@ class OGRGFTDataSource : public OGRDataSource
 class OGRGFTDriver : public OGRSFDriver
 {
   public:
-                ~OGRGFTDriver();
+                virtual ~OGRGFTDriver();
 
-    virtual const char*         GetName();
-    virtual OGRDataSource*      Open( const char *, int );
+    virtual const char*         GetName() override;
+    virtual OGRDataSource*      Open( const char *, int ) override;
     virtual OGRDataSource*      CreateDataSource( const char * pszName,
-                                                  char **papszOptions );
-    virtual int                 TestCapability( const char * );
+                                                  char **papszOptions ) override;
+    virtual int                 TestCapability( const char * ) override;
 };
 
 char **OGRGFTCSVSplitLine( const char *pszString, char chDelimiter );
diff --git a/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp b/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
index 322c922..2168468 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgftdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Google Fusion Table Translator
  * Purpose:  Implements OGRGFTDataSource class
@@ -29,7 +28,7 @@
 
 #include "ogr_gft.h"
 
-CPL_CVSID("$Id: ogrgftdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrgftdatasource.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 #define GDAL_API_KEY "AIzaSyA_2h1_wXMOLHNSVeo-jf1ACME-M1XMgP0"
 #define FUSION_TABLE_SCOPE "https://www.googleapis.com/Fauth/fusiontables"
@@ -38,19 +37,14 @@ CPL_CVSID("$Id: ogrgftdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 /*                          OGRGFTDataSource()                          */
 /************************************************************************/
 
-OGRGFTDataSource::OGRGFTDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-
-    bReadWrite = FALSE;
-    bUseHTTPS = FALSE;
-
-    bMustCleanPersistent = FALSE;
-}
+OGRGFTDataSource::OGRGFTDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bReadWrite(FALSE),
+    bUseHTTPS(FALSE),
+    bMustCleanPersistent(FALSE)
+{}
 
 /************************************************************************/
 /*                         ~OGRGFTDataSource()                          */
@@ -161,7 +155,7 @@ static CPLString OGRGFTGetOptionValue(const char* pszFilename,
     if (!pszOptionValue)
         return "";
 
-    CPLString osOptionValue(pszOptionValue + strlen(osOptionName));
+    CPLString osOptionValue(pszOptionValue + osOptionName.size());
     const char* pszSpace = strchr(osOptionValue.c_str(), ' ');
     if (pszSpace)
         osOptionValue.resize(pszSpace - osOptionValue.c_str());
@@ -180,11 +174,11 @@ int OGRGFTDataSource::Open( const char * pszFilename, int bUpdateIn)
     pszName = CPLStrdup( pszFilename );
 
     osAuth = OGRGFTGetOptionValue(pszFilename, "auth");
-    if (osAuth.size() == 0)
+    if (osAuth.empty())
         osAuth = CPLGetConfigOption("GFT_AUTH", "");
 
     osRefreshToken = OGRGFTGetOptionValue(pszFilename, "refresh");
-    if (osRefreshToken.size() == 0)
+    if (osRefreshToken.empty())
         osRefreshToken = CPLGetConfigOption("GFT_REFRESH_TOKEN", "");
 
     osAPIKey = CPLGetConfigOption("GFT_APIKEY", GDAL_API_KEY);
@@ -194,26 +188,26 @@ int OGRGFTDataSource::Open( const char * pszFilename, int bUpdateIn)
     bUseHTTPS = TRUE;
 
     osAccessToken = OGRGFTGetOptionValue(pszFilename, "access");
-    if (osAccessToken.size() == 0)
+    if (osAccessToken.empty())
         osAccessToken = CPLGetConfigOption("GFT_ACCESS_TOKEN","");
-    if (osAccessToken.size() == 0 && osRefreshToken.size() > 0)
+    if (osAccessToken.empty() && !osRefreshToken.empty())
     {
         osAccessToken.Seize(GOA2GetAccessToken(osRefreshToken,
                                                FUSION_TABLE_SCOPE));
-        if (osAccessToken.size() == 0)
+        if (osAccessToken.empty())
             return FALSE;
     }
     /* coverity[copy_paste_error] */
-    if (osAccessToken.size() == 0 && osAuth.size() > 0)
+    if (osAccessToken.empty() && !osAuth.empty())
     {
         osRefreshToken.Seize(GOA2GetRefreshToken(osAuth, FUSION_TABLE_SCOPE));
-        if (osRefreshToken.size() == 0)
+        if (osRefreshToken.empty())
             return FALSE;
     }
 
-    if (osAccessToken.size() == 0)
+    if (osAccessToken.empty())
     {
-        if (osTables.size() == 0)
+        if (osTables.empty())
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                     "Unauthenticated access requires explicit tables= parameter");
@@ -221,7 +215,7 @@ int OGRGFTDataSource::Open( const char * pszFilename, int bUpdateIn)
         }
     }
 
-    if (osTables.size() != 0)
+    if (!osTables.empty())
     {
         char** papszTables = CSLTokenizeString2(osTables, ",", 0);
         for(int i=0;papszTables && papszTables[i];i++)
@@ -313,7 +307,7 @@ OGRLayer   *OGRGFTDataSource::ICreateLayer( const char *pszNameIn,
         return NULL;
     }
 
-    if (osAccessToken.size() == 0)
+    if (osAccessToken.empty())
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Operation not available in unauthenticated mode");
         return NULL;
@@ -323,9 +317,8 @@ OGRLayer   *OGRGFTDataSource::ICreateLayer( const char *pszNameIn,
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
-    int iLayer;
 
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszNameIn,papoLayers[iLayer]->GetName()) )
         {
@@ -361,12 +354,11 @@ OGRLayer   *OGRGFTDataSource::ICreateLayer( const char *pszNameIn,
 void OGRGFTDataSource::DeleteLayer( const char *pszLayerName )
 
 {
-    int iLayer;
-
 /* -------------------------------------------------------------------- */
 /*      Try to find layer.                                              */
 /* -------------------------------------------------------------------- */
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    int iLayer = 0;  // Used after for.
+    for( ; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetName()) )
             break;
@@ -396,7 +388,7 @@ OGRErr OGRGFTDataSource::DeleteLayer(int iLayer)
         return OGRERR_FAILURE;
     }
 
-    if (osAccessToken.size() == 0)
+    if (osAccessToken.empty())
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in unauthenticated mode");
@@ -454,7 +446,7 @@ char** OGRGFTDataSource::AddHTTPOptions(char** papszOptions)
 {
     bMustCleanPersistent = TRUE;
 
-    if (strlen(osAccessToken) > 0)
+    if( !osAccessToken.empty() )
       papszOptions = CSLAddString(papszOptions,
         CPLSPrintf("HEADERS=Authorization: Bearer %s",
                    osAccessToken.c_str()));
diff --git a/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp b/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
index 676795d..3138c23 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgftdriver.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTDriver.
@@ -33,7 +32,7 @@
 
 /* http://code.google.com/intl/fr/apis/fusiontables/docs/developers_reference.html */
 
-CPL_CVSID("$Id: ogrgftdriver.cpp 33105 2016-01-23 15:27:32Z rouault $");
+CPL_CVSID("$Id: ogrgftdriver.cpp 35910 2016-10-24 14:08:24Z goatbar $");
 
 extern "C" void RegisterOGRGFT();
 
@@ -77,7 +76,6 @@ OGRDataSource *OGRGFTDriver::Open( const char * pszFilename, int bUpdate )
     return poDS;
 }
 
-
 /************************************************************************/
 /*                          CreateDataSource()                          */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp b/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
index 7e930a2..7ec2ac6 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgftlayer.cpp 32370 2015-12-20 19:40:13Z rouault $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTLayer class.
@@ -30,32 +29,25 @@
 #include "ogr_gft.h"
 #include "cpl_minixml.h"
 
-CPL_CVSID("$Id: ogrgftlayer.cpp 32370 2015-12-20 19:40:13Z rouault $");
+CPL_CVSID("$Id: ogrgftlayer.cpp 36061 2016-11-01 02:26:58Z goatbar $");
 
 /************************************************************************/
 /*                            OGRGFTLayer()                             */
 /************************************************************************/
 
-OGRGFTLayer::OGRGFTLayer(OGRGFTDataSource* poDSIn)
-
-{
-    this->poDS = poDSIn;
-
-    nNextInSeq = 0;
-
-    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
-
-    poFeatureDefn = NULL;
-
-    nOffset = 0;
-    bEOF = FALSE;
-
-    iLatitudeField = iLongitudeField = -1;
-    iGeometryField = -1;
-    bHiddenGeometryField = FALSE;
-
-    bFirstTokenIsFID = FALSE;
-}
+OGRGFTLayer::OGRGFTLayer(OGRGFTDataSource* poDSIn) :
+    poDS(poDSIn),
+    poFeatureDefn(NULL),
+    poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
+    nNextInSeq(0),
+    iGeometryField(-1),
+    iLatitudeField(-1),
+    iLongitudeField(-1),
+    bHiddenGeometryField(FALSE),
+    nOffset(0),
+    bEOF(FALSE),
+    bFirstTokenIsFID(FALSE)
+{}
 
 /************************************************************************/
 /*                            ~OGRGFTLayer()                            */
@@ -99,8 +91,6 @@ OGRFeatureDefn * OGRGFTLayer::GetLayerDefn()
 
 OGRFeature *OGRGFTLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
     GetLayerDefn();
 
     while( true )
@@ -116,7 +106,7 @@ OGRFeature *OGRGFTLayer::GetNextFeature()
                 return NULL;
         }
 
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -144,18 +134,15 @@ OGRFeature *OGRGFTLayer::GetNextFeature()
 char **OGRGFTCSVSplitLine( const char *pszString, char chDelimiter )
 
 {
-    char        **papszRetList = NULL;
-    char        *pszToken;
-    int         nTokenMax, nTokenLen;
-
-    pszToken = (char *) CPLCalloc(10,1);
-    nTokenMax = 10;
+    char **papszRetList = NULL;
+    char *pszToken = (char *) CPLCalloc(10,1);
+    int nTokenMax = 10;
 
     while( pszString != NULL && *pszString != '\0' )
     {
         int     bInString = FALSE;
 
-        nTokenLen = 0;
+        int nTokenLen = 0;
 
         /* Try to find the next delimiter, marking end of token */
         for( ; *pszString != '\0'; pszString++ )
@@ -304,7 +291,7 @@ static OGRGeometry* ParseKMLGeometry(/* const */ CPLXMLNode* psXML)
     }
     else if (strcmp(pszGeomType, "MultiGeometry") == 0)
     {
-        CPLXMLNode* psIter;
+        CPLXMLNode* psIter = NULL;
         OGRwkbGeometryType eType = wkbUnknown;
         for(psIter = psXML->psChild; psIter; psIter = psIter->psNext)
         {
@@ -341,7 +328,7 @@ static OGRGeometry* ParseKMLGeometry(/* const */ CPLXMLNode* psXML)
         else if (eType == wkbPolygon)
             poColl = new OGRMultiPolygon();
         else {
-            CPLAssert(0);
+            CPLAssert(false);
         }
 
         for(psIter = psXML->psChild; psIter; psIter = psIter->psNext)
@@ -378,7 +365,6 @@ static OGRGeometry* ParseKMLGeometry(const char* pszKML)
     return poGeom;
 }
 
-
 /************************************************************************/
 /*                         BuildFeatureFromSQL()                        */
 /************************************************************************/
@@ -654,14 +640,17 @@ void OGRGFTLayer::SetGeomFieldName()
 {
     if (iGeometryField >= 0 && poFeatureDefn->GetGeomFieldCount() > 0)
     {
-        const char* pszGeomColName;
+        const char* pszGeomColName = NULL;
         if (iGeometryField == poFeatureDefn->GetFieldCount())
         {
             CPLAssert(bHiddenGeometryField);
             pszGeomColName = GetDefaultGeometryColumnName();
         }
         else
-            pszGeomColName = poFeatureDefn->GetFieldDefn(iGeometryField)->GetNameRef();
+        {
+            pszGeomColName =
+                poFeatureDefn->GetFieldDefn(iGeometryField)->GetNameRef();
+        }
         poFeatureDefn->GetGeomFieldDefn(0)->SetName(pszGeomColName);
     }
 }
diff --git a/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp b/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
index aa54a5d..88025e8 100644
--- a/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgftresultlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgftresultlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTResultLayer class.
@@ -29,20 +28,21 @@
 
 #include "ogr_gft.h"
 
-CPL_CVSID("$Id: ogrgftresultlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+CPL_CVSID("$Id: ogrgftresultlayer.cpp 36691 2016-12-04 22:45:59Z rouault $");
 
 /************************************************************************/
 /*                        OGRGFTResultLayer()                           */
 /************************************************************************/
 
-OGRGFTResultLayer::OGRGFTResultLayer(OGRGFTDataSource* poDSIn,
-                                     const char* pszSQL) : OGRGFTLayer(poDSIn)
-
+OGRGFTResultLayer::OGRGFTResultLayer( OGRGFTDataSource* poDSIn,
+                                      const char* pszSQL ) :
+    OGRGFTLayer(poDSIn),
+    osSQL( CPLString() ),
+    bGotAllRows(FALSE)
 {
+    // cppcheck-suppress useInitializationList
     osSQL = PatchSQL(pszSQL);
 
-    bGotAllRows = FALSE;
-
     poFeatureDefn = new OGRFeatureDefn( "result" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbUnknown );
@@ -198,7 +198,7 @@ int OGRGFTResultLayer::RunSQL()
             poTableDefn = poTableLayer->GetLayerDefn();
 
         if (poTableLayer != NULL &&
-            poTableLayer->GetTableId().size() &&
+            !poTableLayer->GetTableId().empty() &&
             !EQUAL(osTableId, poTableLayer->GetTableId()))
         {
             osChangedSQL = osSQL;
@@ -221,7 +221,8 @@ int OGRGFTResultLayer::RunSQL()
     }
     else
     {
-        bGotAllRows = bEOF = TRUE;
+        bGotAllRows = TRUE;
+        bEOF = TRUE;
         poFeatureDefn->SetGeomType( wkbNone );
     }
 
@@ -244,7 +245,7 @@ int OGRGFTResultLayer::RunSQL()
         STARTS_WITH_CI(osSQL.c_str(), "DESCRIBE"))
     {
         ParseCSVResponse(pszLine, aosRows);
-        if (aosRows.size() > 0)
+        if (!aosRows.empty())
         {
             char** papszTokens = OGRGFTCSVSplitLine(aosRows[0], ',');
             for(int i=0;papszTokens && papszTokens[i];i++)
@@ -282,9 +283,15 @@ int OGRGFTResultLayer::RunSQL()
         }
 
         if (bHasSetLimit)
-            bGotAllRows = bEOF = (int)aosRows.size() < GetFeaturesToFetch();
+        {
+            bEOF = (int)aosRows.size() < GetFeaturesToFetch();
+            bGotAllRows = bEOF;
+        }
         else
-            bGotAllRows = bEOF = TRUE;
+        {
+            bGotAllRows = TRUE;
+            bEOF = TRUE;
+        }
     }
 
     SetGeomFieldName();
diff --git a/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp b/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
index fc5704e..c4e08ae 100644
--- a/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
+++ b/ogr/ogrsf_frmts/gft/ogrgfttablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgfttablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  GFT Translator
  * Purpose:  Implements OGRGFTTableLayer class.
@@ -29,37 +28,38 @@
 
 #include "ogr_gft.h"
 
-CPL_CVSID("$Id: ogrgfttablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrgfttablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGRGFTTableLayer()                           */
 /************************************************************************/
 
-OGRGFTTableLayer::OGRGFTTableLayer(OGRGFTDataSource* poDSIn,
-                         const char* pszTableName,
-                         const char* pszTableId,
-                         const char* pszGeomColumnName) : OGRGFTLayer(poDSIn)
-
+OGRGFTTableLayer::OGRGFTTableLayer( OGRGFTDataSource* poDSIn,
+                                    const char* pszTableName,
+                                    const char* pszTableId,
+                                    const char* pszGeomColumnName ) :
+    OGRGFTLayer(poDSIn),
+    osTableName(pszTableName),
+    osTableId(pszTableId),
+    osGeomColumnName(pszGeomColumnName ? pszGeomColumnName : ""),
+    bHasTriedCreateTable(FALSE),
+    bInTransaction(FALSE),
+    nFeaturesInTransaction(0),
+    eGTypeForCreation(wkbUnknown)
 {
-    osTableName = pszTableName;
-    osTableId = pszTableId;
-    osGeomColumnName = pszGeomColumnName ? pszGeomColumnName : "";
-
-    bHasTriedCreateTable = FALSE;
-    bInTransaction = FALSE;
-    nFeaturesInTransaction = 0;
-
     bFirstTokenIsFID = TRUE;
-    eGTypeForCreation = wkbUnknown;
 
     SetDescription( osTableName );
 
-    if (osTableId.size() == 0)
+    if( osTableId.empty() )
     {
         poFeatureDefn = new OGRFeatureDefn( osTableName );
         poFeatureDefn->Reference();
         poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
-        poFeatureDefn->GetGeomFieldDefn(0)->SetName(GetDefaultGeometryColumnName());
+        poFeatureDefn->GetGeomFieldDefn(0)->
+            SetName(GetDefaultGeometryColumnName());
     }
 }
 
@@ -120,7 +120,7 @@ int OGRGFTTableLayer::FetchDescribe()
 
     const CPLString& osAuth = poDS->GetAccessToken();
     std::vector<CPLString> aosHeaderAndFirstDataLine;
-    if (osAuth.size())
+    if (!osAuth.empty() )
     {
         CPLString osSQL("DESCRIBE ");
         osSQL += osTableId;
@@ -155,7 +155,7 @@ int OGRGFTTableLayer::FetchDescribe()
                 else if (EQUAL(papszTokens[2], "datetime"))
                     eType = OFTDateTime;
 
-                if (EQUAL(papszTokens[2], "location") && osGeomColumnName.size() == 0)
+                if (EQUAL(papszTokens[2], "location") && osGeomColumnName.empty())
                 {
                     if (iGeometryField < 0)
                         iGeometryField = poFeatureDefn->GetFieldCount();
@@ -194,7 +194,7 @@ int OGRGFTTableLayer::FetchDescribe()
         }
 
         ParseCSVResponse(pszLine, aosHeaderAndFirstDataLine);
-        if (aosHeaderAndFirstDataLine.size() > 0)
+        if (!aosHeaderAndFirstDataLine.empty())
         {
             char** papszTokens = OGRGFTCSVSplitLine(aosHeaderAndFirstDataLine[0], ',');
             for(int i=0;papszTokens && papszTokens[i];i++)
@@ -209,7 +209,7 @@ int OGRGFTTableLayer::FetchDescribe()
         CPLHTTPDestroyResult(psResult);
     }
 
-    if (osGeomColumnName.size() > 0)
+    if (!osGeomColumnName.empty())
     {
         iGeometryField = poFeatureDefn->GetFieldIndex(osGeomColumnName);
         if (iGeometryField < 0)
@@ -238,9 +238,10 @@ int OGRGFTTableLayer::FetchDescribe()
         poFeatureDefn->GetFieldDefn(iLongitudeField)->SetType(OFTReal);
         poFeatureDefn->SetGeomType( wkbPoint );
     }
-    else if (iGeometryField < 0 && osGeomColumnName.size() == 0)
+    else if (iGeometryField < 0 && osGeomColumnName.empty())
     {
-        iLatitudeField = iLongitudeField = -1;
+        iLatitudeField = -1;
+        iLongitudeField = -1;
 
         /* In the unauthenticated case, we try to parse the first record to */
         /* auto-detect the geometry field. */
@@ -314,7 +315,7 @@ int OGRGFTTableLayer::FetchDescribe()
 
 static CPLString EscapeAndQuote(const char* pszStr)
 {
-    char ch;
+    char ch = '\0';
     CPLString osRes("'");
     while((ch = *pszStr) != 0)
     {
@@ -357,7 +358,7 @@ int OGRGFTTableLayer::FetchNextRows()
     }
     osSQL += " FROM ";
     osSQL += osTableId;
-    if (osWHERE.size())
+    if (!osWHERE.empty() )
     {
         osSQL += " ";
         osSQL += osWHERE;
@@ -388,7 +389,7 @@ int OGRGFTTableLayer::FetchNextRows()
 
     ParseCSVResponse(pszLine, aosRows);
 
-    if (aosRows.size() > 0)
+    if (!aosRows.empty())
         aosRows.erase(aosRows.begin());
 
     if (nFeaturesToFetch > 0)
@@ -467,7 +468,7 @@ OGRFeatureDefn * OGRGFTTableLayer::GetLayerDefn()
 {
     if (poFeatureDefn == NULL)
     {
-        if (osTableId.size() == 0)
+        if (osTableId.empty())
             return NULL;
         FetchDescribe();
     }
@@ -485,7 +486,7 @@ GIntBig OGRGFTTableLayer::GetFeatureCount(CPL_UNUSED int bForce)
 
     CPLString osSQL("SELECT COUNT() FROM ");
     osSQL += osTableId;
-    if (osWHERE.size())
+    if (!osWHERE.empty() )
     {
         osSQL += " ";
         osSQL += osWHERE;
@@ -539,14 +540,14 @@ OGRErr OGRGFTTableLayer::CreateField( OGRFieldDefn *poField,
         return OGRERR_FAILURE;
     }
 
-    if (osTableId.size() != 0)
+    if (!osTableId.empty())
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Cannot add field to already created table");
         return OGRERR_FAILURE;
     }
 
-    if (poDS->GetAccessToken().size() == 0)
+    if (poDS->GetAccessToken().empty())
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in unauthenticated mode");
@@ -564,7 +565,7 @@ OGRErr OGRGFTTableLayer::CreateField( OGRFieldDefn *poField,
 
 void OGRGFTTableLayer::CreateTableIfNecessary()
 {
-    if (bHasTriedCreateTable || osTableId.size() != 0)
+    if (bHasTriedCreateTable || !osTableId.empty())
         return;
 
     bHasTriedCreateTable = TRUE;
@@ -701,10 +702,10 @@ OGRErr OGRGFTTableLayer::ICreateFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if (osTableId.size() == 0)
+    if (osTableId.empty())
     {
         CreateTableIfNecessary();
-        if (osTableId.size() == 0)
+        if (osTableId.empty())
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                     "Cannot add feature to non-created table");
@@ -712,22 +713,20 @@ OGRErr OGRGFTTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
     }
 
-    if (poDS->GetAccessToken().size() == 0)
+    if (poDS->GetAccessToken().empty())
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in unauthenticated mode");
         return OGRERR_FAILURE;
     }
 
-    CPLString      osCommand;
-
-    osCommand += "INSERT INTO ";
+    CPLString osCommand = "INSERT INTO ";
     osCommand += osTableId;
     osCommand += " (";
 
-    int iField;
-    int nFieldCount = poFeatureDefn->GetFieldCount();
-    for(iField = 0; iField < nFieldCount; iField++)
+    const int nFieldCount = poFeatureDefn->GetFieldCount();
+    int iField = 0;  // Used after for
+    for( ; iField < nFieldCount; iField++ )
     {
         if (iField > 0)
             osCommand += ", ";
@@ -752,13 +751,13 @@ OGRErr OGRGFTTableLayer::ICreateFeature( OGRFeature *poFeature )
         /* If there's a geometry, let's use it in priority over the textual */
         /* content of the field. */
         if (iGeometryField != iLatitudeField && iField == iGeometryField &&
-            (iField == nFieldCount || poGeom != NULL || !poFeature->IsFieldSet( iField )))
+            (iField == nFieldCount || poGeom != NULL || !poFeature->IsFieldSetAndNotNull( iField )))
         {
             if (poGeom == NULL)
                 osCommand += "''";
             else
             {
-                char* pszKML;
+                char* pszKML = NULL;
                 if (poGeom->getSpatialReference() != NULL &&
                     !poGeom->getSpatialReference()->IsSame(poSRS))
                 {
@@ -779,7 +778,7 @@ OGRErr OGRGFTTableLayer::ICreateFeature( OGRFeature *poFeature )
             continue;
         }
 
-        if( !poFeature->IsFieldSet( iField ) )
+        if( !poFeature->IsFieldSetAndNotNull( iField ) )
         {
             osCommand += "''";
         }
@@ -887,14 +886,14 @@ OGRErr      OGRGFTTableLayer::ISetFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if (osTableId.size() == 0)
+    if (osTableId.empty())
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                 "Cannot set feature to non-created table");
         return OGRERR_FAILURE;
     }
 
-    if (poDS->GetAccessToken().size() == 0)
+    if (poDS->GetAccessToken().empty())
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in unauthenticated mode");
@@ -908,15 +907,12 @@ OGRErr      OGRGFTTableLayer::ISetFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    CPLString      osCommand;
-
-    osCommand += "UPDATE ";
+    CPLString osCommand = "UPDATE ";
     osCommand += osTableId;
     osCommand += " SET ";
 
-    int iField;
-    int nFieldCount = poFeatureDefn->GetFieldCount();
-    for(iField = 0; iField < nFieldCount + bHiddenGeometryField; iField++)
+    const int nFieldCount = poFeatureDefn->GetFieldCount();
+    for( int iField = 0; iField < nFieldCount + bHiddenGeometryField; iField++)
     {
         if (iField > 0)
             osCommand += ", ";
@@ -936,13 +932,13 @@ OGRErr      OGRGFTTableLayer::ISetFeature( OGRFeature *poFeature )
 
         OGRGeometry* poGeom = poFeature->GetGeometryRef();
         if (iGeometryField != iLatitudeField && iField == iGeometryField &&
-            (iField == nFieldCount || poGeom != NULL || !poFeature->IsFieldSet( iField )))
+            (iField == nFieldCount || poGeom != NULL || !poFeature->IsFieldSetAndNotNull( iField )))
         {
             if (poGeom == NULL)
                 osCommand += "''";
             else
             {
-                char* pszKML;
+                char* pszKML = NULL;
                 if (poGeom->getSpatialReference() != NULL &&
                     !poGeom->getSpatialReference()->IsSame(poSRS))
                 {
@@ -963,7 +959,7 @@ OGRErr      OGRGFTTableLayer::ISetFeature( OGRFeature *poFeature )
             continue;
         }
 
-        if( !poFeature->IsFieldSet( iField ) )
+        if( !poFeature->IsFieldSetAndNotNull( iField ) )
         {
             osCommand += "''";
         }
@@ -1050,14 +1046,14 @@ OGRErr OGRGFTTableLayer::DeleteFeature( GIntBig nFID )
         return OGRERR_FAILURE;
     }
 
-    if (osTableId.size() == 0)
+    if (osTableId.empty())
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                 "Cannot delete feature in non-created table");
         return OGRERR_FAILURE;
     }
 
-    if (poDS->GetAccessToken().size() == 0)
+    if (poDS->GetAccessToken().empty())
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in unauthenticated mode");
@@ -1123,10 +1119,10 @@ OGRErr OGRGFTTableLayer::StartTransaction()
         return OGRERR_FAILURE;
     }
 
-    if (osTableId.size() == 0)
+    if (osTableId.empty())
     {
         CreateTableIfNecessary();
-        if (osTableId.size() == 0)
+        if (osTableId.empty())
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                     "Cannot add feature to non-created table");
@@ -1134,7 +1130,7 @@ OGRErr OGRGFTTableLayer::StartTransaction()
         }
     }
 
-    if (poDS->GetAccessToken().size() == 0)
+    if (poDS->GetAccessToken().empty())
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Operation not available in unauthenticated mode");
@@ -1249,7 +1245,6 @@ OGRErr OGRGFTTableLayer::SetAttributeFilter( const char *pszQuery )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
@@ -1287,15 +1282,19 @@ void OGRGFTTableLayer::BuildWhere()
 
         CPLString osQuotedGeomColumn(EscapeAndQuote(GetGeometryColumn()));
 
-        osWHERE.Printf("WHERE ST_INTERSECTS(%s, RECTANGLE(LATLNG(%.12f, %.12f), LATLNG(%.12f, %.12f)))",
-                       osQuotedGeomColumn.c_str(),
-                       MAX(-90.,sEnvelope.MinY - 1e-11), MAX(-180., sEnvelope.MinX - 1e-11),
-                       MIN(90.,sEnvelope.MaxY + 1e-11), MIN(180.,sEnvelope.MaxX + 1e-11));
+        osWHERE.Printf(
+            "WHERE ST_INTERSECTS(%s, "
+            "RECTANGLE(LATLNG(%.12f, %.12f), LATLNG(%.12f, %.12f)))",
+            osQuotedGeomColumn.c_str(),
+            std::max(-90.0, sEnvelope.MinY - 1.0e-11),
+            std::max(-180.0, sEnvelope.MinX - 1.0e-11),
+            std::min(90.0, sEnvelope.MaxY + 1.0e-11),
+            std::min(180.0, sEnvelope.MaxX + 1.0e-11));
     }
 
-    if( strlen(osQuery) > 0 )
+    if( !osQuery.empty() )
     {
-        if( strlen(osWHERE) == 0 )
+        if( osWHERE.empty() )
             osWHERE = "WHERE ";
         else
             osWHERE += " AND ";
diff --git a/ogr/ogrsf_frmts/gml/GNUmakefile b/ogr/ogrsf_frmts/gml/GNUmakefile
index 33cc883..66cc1b5 100644
--- a/ogr/ogrsf_frmts/gml/GNUmakefile
+++ b/ogr/ogrsf_frmts/gml/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 CORE_OBJ =	gmlpropertydefn.o gmlfeatureclass.o gmlfeature.o gmlreader.o \
 		parsexsd.o resolvexlinks.o hugefileresolver.o gmlutils.o \
-		gmlreadstate.o gmlhandler.o trstring.o gfstemplate.o gmlregistry.o
+		gmlreadstate.o gmlhandler.o gfstemplate.o gmlregistry.o
 
 OGR_OBJ =	ogrgmldriver.o ogrgmldatasource.o ogrgmllayer.o
 
diff --git a/ogr/ogrsf_frmts/gml/drv_gml.html b/ogr/ogrsf_frmts/gml/drv_gml.html
index 294da72..b0c18c0 100644
--- a/ogr/ogrsf_frmts/gml/drv_gml.html
+++ b/ogr/ogrsf_frmts/gml/drv_gml.html
@@ -21,6 +21,8 @@ Supported GML flavors :
 </table>
 <p>
 
+Starting with GDAL 2.2, another driver, <a href="drv_gmlas.html">GMLAS</a>, for GML driven by application schemas, is also available. Both GML and GMLAS drivers have their use cases.<p>
+
 <h2>Parsers</h2>
 
 The reading part of the driver only
@@ -128,6 +130,8 @@ Since OGR 1.11, the GML driver supports reading :
 Since OGR 2.0, the GML driver supports reading responses to CSW GetRecords
 queries.<p>
 
+Since OGR 2.2, the GML driver supports reading Japanese FGD GML v4 files.<p>
+
 <h2>Geometry reading</h2>
 
 When reading a feature, the driver will by default only take into account the
@@ -448,13 +452,27 @@ will cause to advertize the SF-1 profile in the .XSD schema (such types are not
 
 <p>
 
-<li> <b>GML3_LONGSRS</b>=YES/NO. (OGR >= 1.8.0, only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. If YES, SRS with EPSG authority will
+<li> <b>GML3_LONGSRS</b>=YES/NO. (OGR >= 1.8.0, only valid when FORMAT=GML3/GML3Degree/GML3.2)
+Deprecated by SRSNAME_FORMAT in GDAL 2.2. Default to YES.
+If YES, SRS with EPSG authority will
 be written with the "urn:ogc:def:crs:EPSG::" prefix.
-In the case, if the SRS is a geographic SRS without explicit AXIS order, but that the same SRS authority code
-imported with ImportFromEPSGA() should be treated as lat/long, then the function will take care of coordinate order swapping.
-If set to NO, SRS with EPSG authority will be written with the "EPSG:" prefix, even if they are in lat/long order.<p>
-
-<li> <b>SRSDIMENSION_LOC</b>=POSLIST/GEOMETRY/GEOMETRY,POSLIST. (Only valid for FORMAT=GML3, GDAL >= 2.0) Default to POSLIST.
+In the case the SRS is a SRS without explicit AXIS order, but that the
+same SRS authority code imported with ImportFromEPSGA() should be treated as lat/long or
+northing/easting, then the function will take care of coordinate order swapping.
+If set to NO, SRS with EPSG authority will be written with the "EPSG:"
+ prefix, even if they are in lat/long order.<p>
+
+<li> <b>SRSNAME_FORMAT</b>=SHORT/OGC_URN/OGC_URL (Only valid for FORMAT=GML3/GML3Degree/GML3.2,
+GDAL >= 2.2). Defaults to OGC_URN.
+If SHORT, then srsName will be in the form AUTHORITY_NAME:AUTHORITY_CODE
+If OGC_URN, then srsName will be in the form urn:ogc:def:crs:AUTHORITY_NAME::AUTHORITY_CODE
+If OGC_URL, then srsName will be in the form http://www.opengis.net/def/crs/AUTHORITY_NAME/0/AUTHORITY_CODE
+For OGC_URN and OGC_URL, in the case the SRS is a SRS without explicit
+AXIS order,  but that the same SRS authority code imported with
+ImportFromEPSGA() should be treated as lat/long or northing/easting,
+then the function will take care of coordinate order swapping.<p>
+
+<li> <b>SRSDIMENSION_LOC</b>=POSLIST/GEOMETRY/GEOMETRY,POSLIST. (Only valid for FORMAT=GML3/GML3Degree/GML3.2, GDAL >= 2.0) Default to POSLIST.
 For 2.5D geometries, define the location where to attach the srsDimension attribute.
 There are diverging implementations. Some put in on the <gml:posList> element, other
 on the top geometry element.<p>
@@ -465,10 +483,6 @@ If set to NO, the <gml:boundedBy> element will not be written for each fea
 <li> <b>SPACE_INDENTATION</b>=YES/NO. (OGR >= 1.8.0) Default to YES. If YES, the output will be indented with spaces
 for more readability, but at the expense of file size.<p>
 
-<li> <b>SPACE_INDENTATION</b>=YES/NO. (OGR >= 1.8.0) Default to YES. If YES, the output will be indented with spaces
-for more readability, but at the expense of file size.<p>
-on the top geometry element.<p>
-
 <li> <b>GML_ID</b>=string. (Only valid for GML 3.2, GDAL >= 2.0)
 Value of feature collection gml:id. Default value is "aFeatureCollection".<p>
 
@@ -996,6 +1010,7 @@ ogr2ogr -f GML output.gml PG:'host=myserver dbname=warmerda' -sql "SELECT pop_19
 <li> <a href="http://portal.opengeospatial.org/files/?artifact_id=15201">GML 3.1.1 simple features profile - OGC(R) 06-049r1</a><p>
 <li> <a href="https://portal.opengeospatial.org/files/?artifact_id=42729">Geography Markup Language (GML) simple features profile (with Corrigendum) (GML 3.2.1) - OGC(R) 10-100r3</a><p>
 <li> <a href="http://xml.apache.org/xerces2-j/index.html">Xerces</a><p>
+<li> <a href="drv_gmlas.html">GMLAS - Geography Markup Language (GML) driven by application schemas</a><p>
 <li> <a href="drv_nas.html">NAS/ALKIS : specialized GML driver for cadastral data in Germany</a><p>
 </ul>
 
diff --git a/ogr/ogrsf_frmts/gml/gfstemplate.cpp b/ogr/ogrsf_frmts/gml/gfstemplate.cpp
index ab2942e..aa5815d 100644
--- a/ogr/ogrsf_frmts/gml/gfstemplate.cpp
+++ b/ogr/ogrsf_frmts/gml/gfstemplate.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gfstemplate.cpp 32099 2015-12-09 00:24:06Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GML GFS template management
@@ -33,10 +32,18 @@
  *
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlreaderp.h"
 #include "ogr_gml.h"
 
-CPL_CVSID("$Id: gfstemplate.cpp 32099 2015-12-09 00:24:06Z goatbar $");
+#include <cstddef>
+
+#include "cpl_conv.h"
+#include "cpl_minixml.h"
+#include "gmlreader.h"
+#include "ogr_core.h"
+
+CPL_CVSID("$Id: gfstemplate.cpp 37154 2017-01-16 00:26:43Z goatbar $");
 
 /************************************************************************/
 /*                        GFSTemplateItem                               */
@@ -44,13 +51,14 @@ CPL_CVSID("$Id: gfstemplate.cpp 32099 2015-12-09 00:24:06Z goatbar $");
 
 class GFSTemplateItem
 {
-private:
+  private:
     char            *m_pszName;
     int             n_nItemCount;
     int             n_nGeomCount;
     GFSTemplateItem *pNext;
-public:
-                    GFSTemplateItem( const char *pszName );
+
+  public:
+    explicit        GFSTemplateItem( const char *pszName );
                     ~GFSTemplateItem();
     const char      *GetName() { return m_pszName; }
     void            Update( int b_has_geom );
@@ -68,9 +76,8 @@ public:
                                 GMLReader *pReader,
                                 int *pbSequentialLayers )
 {
-/* updating the FeatureClass list */
-    int clIdx;
-    for (clIdx = 0; clIdx < pReader->GetClassCount(); clIdx++)
+    // Updating the FeatureClass list.
+    for( int clIdx = 0; clIdx < pReader->GetClassCount(); clIdx++ )
     {
         GMLFeatureClass* poClass = pReader->GetClass( clIdx );
         if (poClass != NULL)
@@ -80,13 +87,15 @@ public:
     GFSTemplateItem *pItem = pCC->GetFirst();
     while ( pItem != NULL )
     {
-    /* updating Classes */
+        // Updating Classes.
         GMLFeatureClass* poClass = pReader->GetClass( pItem->GetName() );
         if (poClass != NULL)
         {
             poClass->SetFeatureCount( pItem->GetCount() );
-            if ( pItem->GetGeomCount() != 0 && poClass->GetGeometryPropertyCount() == 0 )
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true ) );
+            if ( pItem->GetGeomCount() != 0 &&
+                 poClass->GetGeometryPropertyCount() == 0 )
+                poClass->AddGeometryProperty(
+                    new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true));
             bValid = true;
         }
         pItem = pItem->GetNext();
@@ -101,32 +110,31 @@ public:
 
 bool GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
 {
-/* rearranging the final FeatureClass list [SEQUENTIAL] */
-    int m_nSavedClassCount = GetClassCount();
-
-/* saving the previous FeatureClass list */
-    GMLFeatureClass **m_papoSavedClass = (GMLFeatureClass **)
-                    CPLMalloc( sizeof(void*) * m_nSavedClassCount );
-    int clIdx;
-    for (clIdx = 0; clIdx < GetClassCount(); clIdx++)
+    // Rearranging the final FeatureClass list [SEQUENTIAL].
+    // TODO(schwehr): Why the m_ for m_nSavedClassCount?  Not a member.
+    const int m_nSavedClassCount = GetClassCount();
+
+    // Saving the previous FeatureClass list.
+    GMLFeatureClass **m_papoSavedClass = static_cast<GMLFeatureClass **>(
+                    CPLMalloc(sizeof(void*) * m_nSavedClassCount));
+
+    for( int clIdx = 0; clIdx < GetClassCount(); clIdx++ )
     {
-    /* Transferring any previous FeatureClass */
+        // Transferring any previous FeatureClass.
         m_papoSavedClass[clIdx] = m_papoClass[clIdx];
     }
 
-/* cleaning the previous FeatureClass list */
-    SetClassListLocked( false );
-    CPLFree( m_papoClass );
+    // Cleaning the previous FeatureClass list.
+    SetClassListLocked(false);
+    CPLFree(m_papoClass);
     m_nClassCount = 0;
     m_papoClass = NULL;
 
     GFSTemplateItem *pItem = pCC->GetFirst();
     while ( pItem != NULL )
     {
-    /*
-    * re-inserting any required FeatureClassup
-    * accordingly to actual SEQUENTIAL layout
-    */
+        // Re-inserting any required FeatureClassup
+        // accordingly to actual SEQUENTIAL layout.
         GMLFeatureClass* poClass = NULL;
         for( int iClass = 0; iClass < m_nSavedClassCount; iClass++ )
         {
@@ -140,13 +148,13 @@ bool GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
         if (poClass != NULL)
         {
             if (poClass->GetFeatureCount() > 0)
-                AddClass( poClass );
+                AddClass(poClass);
         }
         pItem = pItem->GetNext();
     }
-    SetClassListLocked( true );
+    SetClassListLocked(true);
 
-/* destroying the saved List and any unused FeatureClass */
+    // Destroying the saved List and any unused FeatureClass.
     for( int iClass = 0; iClass < m_nSavedClassCount; iClass++ )
     {
         bool bUnused = true;
@@ -162,7 +170,7 @@ bool GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
         if ( bUnused )
             delete poClass;
     }
-    CPLFree( m_papoSavedClass );
+    CPLFree(m_papoSavedClass);
     return true;
 }
 
@@ -170,13 +178,12 @@ bool GMLReader::ReArrangeTemplateClasses ( GFSTemplateList *pCC )
 /*       GMLReader::PrescanForTemplate()           */
 /***************************************************/
 
-bool GMLReader::PrescanForTemplate ()
+bool GMLReader::PrescanForTemplate()
 {
-    int iCount = 0;
-    GMLFeature      *poFeature;
+    GMLFeature *poFeature = NULL;
     GFSTemplateList *pCC = new GFSTemplateList();
 
-    /* processing GML features */
+    // Processing GML features.
     while( (poFeature = NextFeature()) != NULL )
     {
         GMLFeatureClass *poClass = poFeature->GetClass();
@@ -199,26 +206,24 @@ bool GMLReader::PrescanForTemplate ()
         delete poFeature;
     }
 
-    gmlUpdateFeatureClasses( pCC, this, &m_nHasSequentialLayers );
+    gmlUpdateFeatureClasses(pCC, this, &m_nHasSequentialLayers);
     if ( m_nHasSequentialLayers == TRUE )
-        ReArrangeTemplateClasses( pCC );
-    iCount = pCC->GetClassCount();
+        ReArrangeTemplateClasses(pCC);
+    const int iCount = pCC->GetClassCount();
     delete pCC;
     CleanupParser();
     return iCount > 0;
 }
 
-
 /***************************************************/
 /*                 GFSTemplateList()               */
 /***************************************************/
 
-GFSTemplateList::GFSTemplateList( void )
-{
-    m_bSequentialLayers = true;
-    pFirst = NULL;
-    pLast = NULL;
-}
+GFSTemplateList::GFSTemplateList() :
+    m_bSequentialLayers(true),
+    pFirst(NULL),
+    pLast(NULL)
+{}
 
 /***************************************************/
 /*                 GFSTemplateList()               */
@@ -226,11 +231,10 @@ GFSTemplateList::GFSTemplateList( void )
 
 GFSTemplateList::~GFSTemplateList()
 {
-    GFSTemplateItem *pNext;
     GFSTemplateItem *pItem = pFirst;
     while ( pItem != NULL )
     {
-        pNext = pItem->GetNext();
+        GFSTemplateItem *pNext = pItem->GetNext();
         delete pItem;
         pItem = pNext;
     }
@@ -242,10 +246,9 @@ GFSTemplateList::~GFSTemplateList()
 
 GFSTemplateItem *GFSTemplateList::Insert( const char *pszName )
 {
-    GFSTemplateItem *pItem;
-    pItem = new GFSTemplateItem( pszName );
+    GFSTemplateItem *pItem = new GFSTemplateItem( pszName );
 
-    /* inserting into the linked list */
+    // Inserting into the linked list.
     if( pFirst == NULL )
         pFirst = pItem;
     if( pLast != NULL )
@@ -260,18 +263,18 @@ GFSTemplateItem *GFSTemplateList::Insert( const char *pszName )
 
 void GFSTemplateList::Update( const char *pszName, int bHasGeom )
 {
-    GFSTemplateItem *pItem;
+    GFSTemplateItem *pItem = NULL;
 
     if( pFirst == NULL )
     {
-    /* empty List: first item */
+        // Empty List: first item.
         pItem = Insert( pszName );
         pItem->Update( bHasGeom );
         return;
     }
     if( EQUAL(pszName, pLast->GetName() ) )
     {
-    /* continuing with the current Class Item */
+        // Continuing with the current Class Item.
         pLast->Update( bHasGeom );
         return;
     }
@@ -281,7 +284,7 @@ void GFSTemplateList::Update( const char *pszName, int bHasGeom )
     {
         if( EQUAL(pszName, pItem->GetName() ))
         {
-        /* Class Item previously declared: NOT SEQUENTIAL */
+            // Class Item previously declared: NOT SEQUENTIAL.
             m_bSequentialLayers = false;
             pItem->Update( bHasGeom );
             return;
@@ -289,22 +292,19 @@ void GFSTemplateList::Update( const char *pszName, int bHasGeom )
         pItem = pItem->GetNext();
     }
 
-    /* inserting a new Class Item */
+    // Inserting a new Class Item.
     pItem = Insert( pszName );
     pItem->Update( bHasGeom );
 }
 
-
 /***************************************************/
 /*          GFSTemplateList::GetClassCount()       */
 /***************************************************/
 
-int GFSTemplateList::GetClassCount( )
+int GFSTemplateList::GetClassCount()
 {
     int iCount = 0;
-    GFSTemplateItem *pItem;
-
-    pItem = pFirst;
+    GFSTemplateItem *pItem = pFirst;
     while( pItem != NULL )
     {
         iCount++;
@@ -318,13 +318,12 @@ int GFSTemplateList::GetClassCount( )
 /*                 GFSTemplateItem()               */
 /***************************************************/
 
-GFSTemplateItem::GFSTemplateItem( const char *pszName )
-{
-    m_pszName = CPLStrdup( pszName );
-    n_nItemCount = 0;
-    n_nGeomCount = 0;
-    pNext = NULL;
-}
+GFSTemplateItem::GFSTemplateItem( const char *pszName ) :
+    m_pszName(CPLStrdup( pszName )),
+    n_nItemCount(0),
+    n_nGeomCount(0),
+    pNext(NULL)
+{}
 
 /***************************************************/
 /*                ~GFSTemplateItem()               */
diff --git a/ogr/ogrsf_frmts/gml/gmlfeature.cpp b/ogr/ogrsf_frmts/gml/gmlfeature.cpp
index cac8f9b..9f7b5f6 100644
--- a/ogr/ogrsf_frmts/gml/gmlfeature.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlfeature.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: gmlfeature.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLFeature.
@@ -28,29 +27,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlreader.h"
+
+#include <cstdio>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
 #include "cpl_string.h"
 
+CPL_CVSID("$Id: gmlfeature.cpp 37155 2017-01-16 00:44:59Z goatbar $");
+
 /************************************************************************/
 /*                             GMLFeature()                             */
 /************************************************************************/
 
-GMLFeature::GMLFeature( GMLFeatureClass *poClass )
-
+GMLFeature::GMLFeature( GMLFeatureClass *poClass ) :
+    m_poClass(poClass),
+    m_pszFID(NULL),
+    m_nPropertyCount(0),
+    m_pasProperties(NULL),
+    m_nGeometryCount(0),
+    m_papsGeometry(m_apsGeometry),  // TODO(schwehr): Allowed in init list?
+    m_papszOBProperties(NULL)
 {
-    m_poClass = poClass;
-    m_pszFID = NULL;
-
-    m_nPropertyCount = 0;
-    m_pasProperties = NULL;
-
-    m_nGeometryCount = 0;
-    m_papsGeometry = m_apsGeometry;
     m_apsGeometry[0] = NULL;
     m_apsGeometry[1] = NULL;
-
-    m_papszOBProperties = NULL;
 }
 
 /************************************************************************/
@@ -60,18 +63,20 @@ GMLFeature::GMLFeature( GMLFeatureClass *poClass )
 GMLFeature::~GMLFeature()
 
 {
-    CPLFree( m_pszFID );
+    CPLFree(m_pszFID);
 
     for( int i = 0; i < m_nPropertyCount; i++ )
     {
-        int nSubProperties = m_pasProperties[i].nSubProperties;
+        const int nSubProperties = m_pasProperties[i].nSubProperties;
         if (nSubProperties == 1)
-            CPLFree( m_pasProperties[i].aszSubProperties[0] );
+        {
+            CPLFree(m_pasProperties[i].aszSubProperties[0]);
+        }
         else if (nSubProperties > 1)
         {
             for( int j = 0; j < nSubProperties; j++)
-                CPLFree( m_pasProperties[i].papszSubProperties[j] );
-            CPLFree( m_pasProperties[i].papszSubProperties );
+                CPLFree(m_pasProperties[i].papszSubProperties[j]);
+            CPLFree(m_pasProperties[i].papszSubProperties);
         }
     }
 
@@ -81,13 +86,13 @@ GMLFeature::~GMLFeature()
     }
     else if (m_nGeometryCount > 1)
     {
-        for( int i=0; i < m_nGeometryCount; i++ )
+        for( int i = 0; i < m_nGeometryCount; i++ )
             CPLDestroyXMLNode(m_papsGeometry[i]);
         CPLFree(m_papsGeometry);
     }
 
-    CPLFree( m_pasProperties );
-    CSLDestroy( m_papszOBProperties );
+    CPLFree(m_pasProperties);
+    CSLDestroy(m_papszOBProperties);
 }
 
 /************************************************************************/
@@ -97,9 +102,9 @@ GMLFeature::~GMLFeature()
 void GMLFeature::SetFID( const char *pszFID )
 
 {
-    CPLFree( m_pszFID );
+    CPLFree(m_pszFID);
     if( pszFID != NULL )
-        m_pszFID = CPLStrdup( pszFID );
+        m_pszFID = CPLStrdup(pszFID);
     else
         m_pszFID = NULL;
 }
@@ -114,35 +119,38 @@ void GMLFeature::SetPropertyDirectly( int iIndex, char *pszValue )
     CPLAssert(pszValue);
     if( iIndex >= m_nPropertyCount )
     {
-        int nClassPropertyCount = m_poClass->GetPropertyCount();
-        m_pasProperties = (GMLProperty*)
-            CPLRealloc( m_pasProperties,
-                        sizeof(GMLProperty) * nClassPropertyCount );
+        const int nClassPropertyCount = m_poClass->GetPropertyCount();
+        m_pasProperties = static_cast<GMLProperty *>(CPLRealloc(
+            m_pasProperties, sizeof(GMLProperty) * nClassPropertyCount));
         for( int i = 0; i < m_nPropertyCount; i++ )
         {
-            /* Make sure papszSubProperties point to the right address in case */
-            /* m_pasProperties has been relocated */
+            // Make sure papszSubProperties point to the right address in case
+            // m_pasProperties has been relocated.
             if (m_pasProperties[i].nSubProperties <= 1)
-                m_pasProperties[i].papszSubProperties = m_pasProperties[i].aszSubProperties;
+                m_pasProperties[i].papszSubProperties =
+                    m_pasProperties[i].aszSubProperties;
         }
         for( int i = m_nPropertyCount; i < nClassPropertyCount; i++ )
         {
             m_pasProperties[i].nSubProperties = 0;
-            m_pasProperties[i].papszSubProperties = m_pasProperties[i].aszSubProperties;
+            m_pasProperties[i].papszSubProperties =
+                m_pasProperties[i].aszSubProperties;
             m_pasProperties[i].aszSubProperties[0] = NULL;
             m_pasProperties[i].aszSubProperties[1] = NULL;
         }
         m_nPropertyCount = nClassPropertyCount;
     }
 
-    GMLProperty* psProperty = &m_pasProperties[iIndex];
-    int nSubProperties = psProperty->nSubProperties;
+    GMLProperty *psProperty = &m_pasProperties[iIndex];
+    const int nSubProperties = psProperty->nSubProperties;
     if (nSubProperties == 0)
+    {
         psProperty->aszSubProperties[0] = pszValue;
+    }
     else if (nSubProperties == 1)
     {
-        psProperty->papszSubProperties = (char**) CPLMalloc(
-                            sizeof(char*) * (nSubProperties + 2) );
+        psProperty->papszSubProperties = static_cast<char **>(
+            CPLMalloc(sizeof(char *) * (nSubProperties + 2)));
         psProperty->papszSubProperties[0] = psProperty->aszSubProperties[0];
         psProperty->aszSubProperties[0] = NULL;
         psProperty->papszSubProperties[nSubProperties] = pszValue;
@@ -150,13 +158,13 @@ void GMLFeature::SetPropertyDirectly( int iIndex, char *pszValue )
     }
     else
     {
-        psProperty->papszSubProperties = (char**) CPLRealloc(
-                            psProperty->papszSubProperties,
-                            sizeof(char*) * (nSubProperties + 2) );
+        psProperty->papszSubProperties = static_cast<char **>(
+            CPLRealloc(psProperty->papszSubProperties,
+                       sizeof(char *) * (nSubProperties + 2)));
         psProperty->papszSubProperties[nSubProperties] = pszValue;
         psProperty->papszSubProperties[nSubProperties + 1] = NULL;
     }
-    psProperty->nSubProperties ++;
+    psProperty->nSubProperties++;
 }
 
 /************************************************************************/
@@ -165,27 +173,28 @@ void GMLFeature::SetPropertyDirectly( int iIndex, char *pszValue )
 
 void GMLFeature::Dump( CPL_UNUSED FILE * fp )
 {
-    printf( "GMLFeature(%s):\n", m_poClass->GetName() );
+    printf("GMLFeature(%s):\n", m_poClass->GetName());  /*ok*/
 
     if( m_pszFID != NULL )
-        printf( "  FID = %s\n", m_pszFID );
+        printf("  FID = %s\n", m_pszFID);  /*ok*/
 
     for( int i = 0; i < m_nPropertyCount; i++ )
     {
-        const GMLProperty * psGMLProperty = GetProperty( i );
-        printf( "  %s = ", m_poClass->GetProperty( i )->GetName());
+        const GMLProperty *psGMLProperty = GetProperty(i);
+        printf("  %s = ", m_poClass->GetProperty(i)->GetName()); /*ok*/
         for ( int j = 0; j < psGMLProperty->nSubProperties; j ++)
         {
-            if (j > 0) printf(", ");
-            printf("%s", psGMLProperty->papszSubProperties[j]);
+            if (j > 0)
+                printf(", ");  /*ok*/
+            printf("%s", psGMLProperty->papszSubProperties[j]);  /*ok*/
         }
-        printf("\n");
+        printf("\n");/*ok*/
     }
 
-    for( int i=0; i < m_nGeometryCount; i++ )
+    for( int i = 0; i < m_nGeometryCount; i++ )
     {
-        char* pszXML = CPLSerializeXMLTree(m_papsGeometry[i]);
-        printf( "  %s\n", pszXML );
+        char *pszXML = CPLSerializeXMLTree(m_papsGeometry[i]);
+        printf("  %s\n", pszXML);  /*ok*/
         CPLFree(pszXML);
     }
 }
@@ -212,12 +221,13 @@ void GMLFeature::SetGeometryDirectly( int nIdx, CPLXMLNode* psGeom )
 {
     if( nIdx == 0 && m_nGeometryCount <= 1 )
     {
-        SetGeometryDirectly( psGeom );
+        SetGeometryDirectly(psGeom);
         return;
     }
     else if( nIdx > 0 && m_nGeometryCount <= 1 )
     {
-        m_papsGeometry = (CPLXMLNode **) CPLMalloc(2 * sizeof(CPLXMLNode *));
+        m_papsGeometry =
+            static_cast<CPLXMLNode **>(CPLMalloc(2 * sizeof(CPLXMLNode *)));
         m_papsGeometry[0] = m_apsGeometry[0];
         m_papsGeometry[1] = NULL;
         m_apsGeometry[0] = NULL;
@@ -225,8 +235,8 @@ void GMLFeature::SetGeometryDirectly( int nIdx, CPLXMLNode* psGeom )
 
     if( nIdx >= m_nGeometryCount )
     {
-        m_papsGeometry = (CPLXMLNode **) CPLRealloc(m_papsGeometry,
-            (nIdx + 2) * sizeof(CPLXMLNode *));
+        m_papsGeometry = static_cast<CPLXMLNode **>(
+            CPLRealloc(m_papsGeometry, (nIdx + 2) * sizeof(CPLXMLNode *)));
         for( int i = m_nGeometryCount; i <= nIdx + 1; i++ )
             m_papsGeometry[i] = NULL;
         m_nGeometryCount = nIdx + 1;
@@ -240,7 +250,7 @@ void GMLFeature::SetGeometryDirectly( int nIdx, CPLXMLNode* psGeom )
 /*                          GetGeometryRef()                            */
 /************************************************************************/
 
-const CPLXMLNode* GMLFeature::GetGeometryRef( int nIdx ) const
+const CPLXMLNode *GMLFeature::GetGeometryRef( int nIdx ) const
 {
     if( nIdx < 0 || nIdx >= m_nGeometryCount )
         return NULL;
@@ -251,7 +261,7 @@ const CPLXMLNode* GMLFeature::GetGeometryRef( int nIdx ) const
 /*                             AddGeometry()                            */
 /************************************************************************/
 
-void GMLFeature::AddGeometry( CPLXMLNode* psGeom )
+void GMLFeature::AddGeometry( CPLXMLNode *psGeom )
 
 {
     if (m_nGeometryCount == 0)
@@ -260,8 +270,8 @@ void GMLFeature::AddGeometry( CPLXMLNode* psGeom )
     }
     else if (m_nGeometryCount == 1)
     {
-        m_papsGeometry = (CPLXMLNode **) CPLMalloc(
-            (m_nGeometryCount + 2) * sizeof(CPLXMLNode *));
+        m_papsGeometry = static_cast<CPLXMLNode **>(
+            CPLMalloc((m_nGeometryCount + 2) * sizeof(CPLXMLNode *)));
         m_papsGeometry[0] = m_apsGeometry[0];
         m_apsGeometry[0] = NULL;
         m_papsGeometry[m_nGeometryCount] = psGeom;
@@ -269,12 +279,12 @@ void GMLFeature::AddGeometry( CPLXMLNode* psGeom )
     }
     else
     {
-        m_papsGeometry = (CPLXMLNode **) CPLRealloc(m_papsGeometry,
-            (m_nGeometryCount + 2) * sizeof(CPLXMLNode *));
+        m_papsGeometry = static_cast<CPLXMLNode **>(CPLRealloc(
+            m_papsGeometry, (m_nGeometryCount + 2) * sizeof(CPLXMLNode *)));
         m_papsGeometry[m_nGeometryCount] = psGeom;
         m_papsGeometry[m_nGeometryCount + 1] = NULL;
     }
-    m_nGeometryCount ++;
+    m_nGeometryCount++;
 }
 
 /************************************************************************/
@@ -285,7 +295,7 @@ void GMLFeature::AddOBProperty( const char *pszName, const char *pszValue )
 
 {
     m_papszOBProperties =
-        CSLAddNameValue( m_papszOBProperties, pszName, pszValue );
+        CSLAddNameValue(m_papszOBProperties, pszName, pszValue);
 }
 
 /************************************************************************/
@@ -295,15 +305,11 @@ void GMLFeature::AddOBProperty( const char *pszName, const char *pszValue )
 const char *GMLFeature::GetOBProperty( const char *pszName )
 
 {
-    return CSLFetchNameValue( m_papszOBProperties, pszName );
+    return CSLFetchNameValue(m_papszOBProperties, pszName);
 }
 
 /************************************************************************/
 /*                          GetOBProperties()                           */
 /************************************************************************/
 
-char **GMLFeature::GetOBProperties()
-
-{
-    return m_papszOBProperties;
-}
+char **GMLFeature::GetOBProperties() { return m_papszOBProperties; }
diff --git a/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp b/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
index b36313f..2401579 100644
--- a/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlfeatureclass.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: gmlfeatureclass.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLFeatureClass.
@@ -28,28 +27,40 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlreader.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
 #include "cpl_string.h"
 #include "ogr_core.h"
 #include "ogr_geometry.h"
-#include "cpl_string.h"
+
+CPL_CVSID("$Id: gmlfeatureclass.cpp 37445 2017-02-25 14:56:07Z goatbar $");
 
 /************************************************************************/
 /*                          GMLFeatureClass()                           */
 /************************************************************************/
 
 GMLFeatureClass::GMLFeatureClass( const char *pszName ) :
-    m_pszName(NULL),
+    m_pszName(CPLStrdup(pszName)),
     m_pszElementName(NULL),
-    n_nNameLen(0),
+    n_nNameLen(static_cast<int>(strlen(pszName))),
     n_nElementNameLen(0),
     m_nPropertyCount(0),
     m_papoProperty(NULL),
     m_nGeometryPropertyCount(0),
     m_papoGeometryProperty(NULL),
     m_bSchemaLocked(false),
-    m_nFeatureCount(-1), // unknown
+    m_nFeatureCount(-1),  // Unknown.
     m_pszExtraInfo(NULL),
     m_bHaveExtents(false),
     m_dfXMin(0.0),
@@ -58,10 +69,7 @@ GMLFeatureClass::GMLFeatureClass( const char *pszName ) :
     m_dfYMax(0.0),
     m_pszSRSName(NULL),
     m_bSRSNameConsistent(true)
-{
-    m_pszName = CPLStrdup( pszName );
-    n_nNameLen = static_cast<int>(strlen( m_pszName ));
-}
+{}
 
 /************************************************************************/
 /*                          ~GMLFeatureClass()                          */
@@ -70,16 +78,16 @@ GMLFeatureClass::GMLFeatureClass( const char *pszName ) :
 GMLFeatureClass::~GMLFeatureClass()
 
 {
-    CPLFree( m_pszName );
-    CPLFree( m_pszElementName );
+    CPLFree(m_pszName);
+    CPLFree(m_pszElementName);
 
     for( int i = 0; i < m_nPropertyCount; i++ )
         delete m_papoProperty[i];
-    CPLFree( m_papoProperty );
+    CPLFree(m_papoProperty);
 
     ClearGeometryProperties();
 
-    CPLFree( m_pszSRSName );
+    CPLFree(m_pszSRSName);
 }
 
 /************************************************************************/
@@ -89,7 +97,7 @@ GMLFeatureClass::~GMLFeatureClass()
 void GMLFeatureClass::StealProperties()
 {
     m_nPropertyCount = 0;
-    CPLFree( m_papoProperty );
+    CPLFree(m_papoProperty);
     m_papoProperty = NULL;
 }
 
@@ -100,7 +108,7 @@ void GMLFeatureClass::StealProperties()
 void GMLFeatureClass::StealGeometryProperties()
 {
     m_nGeometryPropertyCount = 0;
-    CPLFree( m_papoGeometryProperty );
+    CPLFree(m_papoGeometryProperty);
     m_papoGeometryProperty = NULL;
 }
 
@@ -108,10 +116,10 @@ void GMLFeatureClass::StealGeometryProperties()
 /*                            SetName()                                 */
 /************************************************************************/
 
-void GMLFeatureClass::SetName(const char* pszNewName)
+void GMLFeatureClass::SetName(const char *pszNewName)
 {
-    CPLFree( m_pszName );
-    m_pszName = CPLStrdup( pszNewName );
+    CPLFree(m_pszName);
+    m_pszName = CPLStrdup(pszNewName);
 }
 
 /************************************************************************/
@@ -123,8 +131,8 @@ GMLPropertyDefn *GMLFeatureClass::GetProperty( int iIndex ) const
 {
     if( iIndex < 0 || iIndex >= m_nPropertyCount )
         return NULL;
-    else
-        return m_papoProperty[iIndex];
+
+    return m_papoProperty[iIndex];
 }
 
 /************************************************************************/
@@ -135,7 +143,7 @@ int GMLFeatureClass::GetPropertyIndex( const char *pszName ) const
 
 {
     for( int i = 0; i < m_nPropertyCount; i++ )
-        if( EQUAL(pszName,m_papoProperty[i]->GetName()) )
+        if( EQUAL(pszName, m_papoProperty[i]->GetName()) )
             return i;
 
     return -1;
@@ -145,12 +153,13 @@ int GMLFeatureClass::GetPropertyIndex( const char *pszName ) const
 /*                        GetPropertyIndexBySrcElement()                */
 /************************************************************************/
 
-int GMLFeatureClass::GetPropertyIndexBySrcElement( const char *pszElement, int nLen ) const
+int GMLFeatureClass::GetPropertyIndexBySrcElement( const char *pszElement,
+                                                   int nLen ) const
 
 {
     for( int i = 0; i < m_nPropertyCount; i++ )
-        if( nLen == (int)m_papoProperty[i]->GetSrcElementLen() &&
-            memcmp(pszElement,m_papoProperty[i]->GetSrcElement(), nLen) == 0)
+        if( nLen == static_cast<int>(m_papoProperty[i]->GetSrcElementLen()) &&
+            memcmp(pszElement, m_papoProperty[i]->GetSrcElement(), nLen) == 0)
             return i;
 
     return -1;
@@ -166,41 +175,44 @@ int GMLFeatureClass::AddProperty( GMLPropertyDefn *poDefn )
     if( GetProperty(poDefn->GetName()) != NULL )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
-                 "Field with same name (%s) already exists. Skipping newer ones",
+                 "Field with same name (%s) already exists. "
+                 "Skipping newer ones",
                  poDefn->GetName());
         return -1;
     }
 
     m_nPropertyCount++;
-    m_papoProperty = (GMLPropertyDefn **)
-        CPLRealloc( m_papoProperty, sizeof(void*) * m_nPropertyCount );
+    m_papoProperty = static_cast<GMLPropertyDefn **>(
+        CPLRealloc(m_papoProperty, sizeof(void *) * m_nPropertyCount));
 
-    m_papoProperty[m_nPropertyCount-1] = poDefn;
+    m_papoProperty[m_nPropertyCount - 1] = poDefn;
 
-    return m_nPropertyCount-1;
+    return m_nPropertyCount - 1;
 }
 
 /************************************************************************/
 /*                         GetGeometryProperty(int)                      */
 /************************************************************************/
 
-GMLGeometryPropertyDefn *GMLFeatureClass::GetGeometryProperty( int iIndex ) const
+GMLGeometryPropertyDefn *
+GMLFeatureClass::GetGeometryProperty( int iIndex ) const
 {
     if( iIndex < 0 || iIndex >= m_nGeometryPropertyCount )
         return NULL;
-    else
-        return m_papoGeometryProperty[iIndex];
+
+    return m_papoGeometryProperty[iIndex];
 }
 
 /************************************************************************/
 /*                   GetGeometryPropertyIndexBySrcElement()             */
 /************************************************************************/
 
-int GMLFeatureClass::GetGeometryPropertyIndexBySrcElement( const char *pszElement ) const
+int GMLFeatureClass::GetGeometryPropertyIndexBySrcElement(
+    const char *pszElement) const
 
 {
     for( int i = 0; i < m_nGeometryPropertyCount; i++ )
-        if( strcmp(pszElement,m_papoGeometryProperty[i]->GetSrcElement()) == 0)
+        if( strcmp(pszElement, m_papoGeometryProperty[i]->GetSrcElement()) == 0)
             return i;
 
     return -1;
@@ -216,18 +228,19 @@ int GMLFeatureClass::AddGeometryProperty( GMLGeometryPropertyDefn *poDefn )
     if( GetGeometryPropertyIndexBySrcElement(poDefn->GetSrcElement()) >= 0 )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
-                 "Field with same name (%s) already exists. Skipping newer ones",
+                 "Field with same name (%s) already exists. "
+                 "Skipping newer ones",
                  poDefn->GetSrcElement());
         return -1;
     }
 
     m_nGeometryPropertyCount++;
-    m_papoGeometryProperty = (GMLGeometryPropertyDefn **)
-        CPLRealloc( m_papoGeometryProperty, sizeof(void*) * m_nGeometryPropertyCount );
+    m_papoGeometryProperty = static_cast<GMLGeometryPropertyDefn **>(CPLRealloc(
+        m_papoGeometryProperty, sizeof(void *) * m_nGeometryPropertyCount));
 
-    m_papoGeometryProperty[m_nGeometryPropertyCount-1] = poDefn;
+    m_papoGeometryProperty[m_nGeometryPropertyCount - 1] = poDefn;
 
-    return m_nGeometryPropertyCount-1;
+    return m_nGeometryPropertyCount - 1;
 }
 
 /************************************************************************/
@@ -238,7 +251,7 @@ void GMLFeatureClass::ClearGeometryProperties()
 {
     for( int i = 0; i < m_nGeometryPropertyCount; i++ )
         delete m_papoGeometryProperty[i];
-    CPLFree( m_papoGeometryProperty );
+    CPLFree(m_papoGeometryProperty);
     m_nGeometryPropertyCount = 0;
     m_papoGeometryProperty = NULL;
 }
@@ -265,8 +278,8 @@ bool GMLFeatureClass::HasFeatureProperties()
 void GMLFeatureClass::SetElementName( const char *pszElementName )
 
 {
-    CPLFree( m_pszElementName );
-    m_pszElementName = CPLStrdup( pszElementName );
+    CPLFree(m_pszElementName);
+    m_pszElementName = CPLStrdup(pszElementName);
     n_nElementNameLen = static_cast<int>(strlen(pszElementName));
 }
 
@@ -279,8 +292,8 @@ const char *GMLFeatureClass::GetElementName() const
 {
     if( m_pszElementName == NULL )
         return m_pszName;
-    else
-        return m_pszElementName;
+
+    return m_pszElementName;
 }
 
 /************************************************************************/
@@ -292,19 +305,15 @@ size_t GMLFeatureClass::GetElementNameLen() const
 {
     if( m_pszElementName == NULL )
         return n_nNameLen;
-    else
-        return n_nElementNameLen;
+
+    return n_nElementNameLen;
 }
 
 /************************************************************************/
 /*                         GetFeatureCount()                          */
 /************************************************************************/
 
-GIntBig GMLFeatureClass::GetFeatureCount()
-
-{
-    return m_nFeatureCount;
-}
+GIntBig GMLFeatureClass::GetFeatureCount() { return m_nFeatureCount; }
 
 /************************************************************************/
 /*                          SetFeatureCount()                           */
@@ -320,11 +329,7 @@ void GMLFeatureClass::SetFeatureCount( GIntBig nNewCount )
 /*                            GetExtraInfo()                            */
 /************************************************************************/
 
-const char *GMLFeatureClass::GetExtraInfo()
-
-{
-    return m_pszExtraInfo;
-}
+const char *GMLFeatureClass::GetExtraInfo() { return m_pszExtraInfo; }
 
 /************************************************************************/
 /*                            SetExtraInfo()                            */
@@ -333,11 +338,11 @@ const char *GMLFeatureClass::GetExtraInfo()
 void GMLFeatureClass::SetExtraInfo( const char *pszExtraInfo )
 
 {
-    CPLFree( m_pszExtraInfo );
+    CPLFree(m_pszExtraInfo);
     m_pszExtraInfo = NULL;
 
     if( pszExtraInfo != NULL )
-        m_pszExtraInfo = CPLStrdup( pszExtraInfo );
+        m_pszExtraInfo = CPLStrdup(pszExtraInfo);
 }
 
 /************************************************************************/
@@ -361,7 +366,7 @@ void GMLFeatureClass::SetExtents( double dfXMin, double dfXMax,
 /************************************************************************/
 
 bool GMLFeatureClass::GetExtents( double *pdfXMin, double *pdfXMax,
-                                 double *pdfYMin, double *pdfYMax )
+                                  double *pdfYMin, double *pdfYMax )
 
 {
     if( m_bHaveExtents )
@@ -384,14 +389,14 @@ void GMLFeatureClass::SetSRSName( const char* pszSRSName )
 {
     m_bSRSNameConsistent = true;
     CPLFree(m_pszSRSName);
-    m_pszSRSName = (pszSRSName) ? CPLStrdup(pszSRSName) : NULL;
+    m_pszSRSName = pszSRSName ? CPLStrdup(pszSRSName) : NULL;
 }
 
 /************************************************************************/
 /*                           MergeSRSName()                             */
 /************************************************************************/
 
-void GMLFeatureClass::MergeSRSName( const char* pszSRSName )
+void GMLFeatureClass::MergeSRSName( const char *pszSRSName )
 
 {
     if(!m_bSRSNameConsistent)
@@ -404,8 +409,8 @@ void GMLFeatureClass::MergeSRSName( const char* pszSRSName )
     }
     else
     {
-        m_bSRSNameConsistent = pszSRSName != NULL &&
-                                  strcmp(m_pszSRSName, pszSRSName) == 0;
+        m_bSRSNameConsistent =
+            pszSRSName != NULL && strcmp(m_pszSRSName, pszSRSName) == 0;
         if (!m_bSRSNameConsistent)
         {
             CPLFree(m_pszSRSName);
@@ -421,111 +426,112 @@ void GMLFeatureClass::MergeSRSName( const char* pszSRSName )
 bool GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
 
 {
-/* -------------------------------------------------------------------- */
-/*      Do some rudimentary checking that this is a well formed         */
-/*      node.                                                           */
-/* -------------------------------------------------------------------- */
-    if( psRoot == NULL
-        || psRoot->eType != CXT_Element
-        || !EQUAL(psRoot->pszValue,"GMLFeatureClass") )
+    // Do some rudimentary checking that this is a well formed node.
+    if( psRoot == NULL || psRoot->eType != CXT_Element ||
+        !EQUAL(psRoot->pszValue, "GMLFeatureClass") )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "GMLFeatureClass::InitializeFromXML() called on %s node!",
-                  psRoot->pszValue );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "GMLFeatureClass::InitializeFromXML() called on %s node!",
+                 psRoot ? psRoot->pszValue : "(null)");
         return false;
     }
 
     if( CPLGetXMLValue( psRoot, "Name", NULL ) == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "GMLFeatureClass has no <Name> element." );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "GMLFeatureClass has no <Name> element.");
         return false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Collect base info.                                              */
-/* -------------------------------------------------------------------- */
-    CPLFree( m_pszName );
-    m_pszName = CPLStrdup( CPLGetXMLValue( psRoot, "Name", NULL ) );
+    // Collect base info.
+    CPLFree(m_pszName);
+    m_pszName = CPLStrdup(CPLGetXMLValue(psRoot, "Name", NULL));
     n_nNameLen = static_cast<int>(strlen(m_pszName));
 
-    SetElementName( CPLGetXMLValue( psRoot, "ElementPath", m_pszName ) );
-
-/* -------------------------------------------------------------------- */
-/*      Collect geometry properties.                                    */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode *psThis;
+    SetElementName(CPLGetXMLValue(psRoot, "ElementPath", m_pszName));
 
+    // Collect geometry properties.
     bool bHasValidGeometryName = false;
     bool bHasValidGeometryElementPath = false;
     bool bHasFoundGeomType = false;
     bool bHasFoundGeomElements = false;
-    const char* pszGName = "";
-    const char* pszGPath = "";
+    const char *pszGName = "";
+    const char *pszGPath = "";
     int nGeomType = wkbUnknown;
 
+    CPLXMLNode *psThis = NULL;
     for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
     {
         if( psThis->eType == CXT_Element &&
             EQUAL(psThis->pszValue, "GeomPropertyDefn") )
         {
-            const char *pszName = CPLGetXMLValue( psThis, "Name", "" );
-            const char *pszElementPath = CPLGetXMLValue( psThis, "ElementPath", "" );
-            const char *pszType = CPLGetXMLValue( psThis, "Type", NULL );
-            bool bNullable = CPLTestBool(CPLGetXMLValue( psThis, "Nullable", "true") );
+            const char *pszName = CPLGetXMLValue(psThis, "Name", "");
+            const char *pszElementPath =
+                CPLGetXMLValue(psThis, "ElementPath", "");
+            const char *pszType = CPLGetXMLValue(psThis, "Type", NULL);
+            const bool bNullable =
+                CPLTestBool(CPLGetXMLValue(psThis, "Nullable", "true"));
             nGeomType = wkbUnknown;
             if( pszType != NULL && !EQUAL(pszType, "0") )
             {
                 nGeomType = atoi(pszType);
-                OGRwkbGeometryType nFlattenGeomType = wkbFlatten(nGeomType);
-                if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) )
+                const OGRwkbGeometryType nFlattenGeomType =
+                    wkbFlatten(nGeomType);
+                if( nGeomType != 0 &&
+                    !(nFlattenGeomType >= wkbPoint &&
+                      nFlattenGeomType <= wkbMultiSurface) )
                 {
                     nGeomType = wkbUnknown;
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "Unrecognized geometry type : %s",
-                              pszType);
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Unrecognized geometry type : %s",
+                             pszType);
                 }
                 else if( nGeomType == 0 )
+                {
                     nGeomType = OGRFromOGCGeomType(pszType);
+                }
             }
             bHasFoundGeomElements = true;
-            AddGeometryProperty( new GMLGeometryPropertyDefn( pszName, pszElementPath, nGeomType, -1, bNullable ) );
+            AddGeometryProperty(new GMLGeometryPropertyDefn(
+                pszName, pszElementPath, nGeomType, -1, bNullable));
             bHasValidGeometryName = false;
             bHasValidGeometryElementPath = false;
             bHasFoundGeomType = false;
         }
         else if( psThis->eType == CXT_Element &&
-            strcmp(psThis->pszValue, "GeometryName") == 0 )
+                 strcmp(psThis->pszValue, "GeometryName") == 0 )
         {
             bHasFoundGeomElements = true;
 
             if( bHasValidGeometryName )
             {
-                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, true ) );
-                /*bHasValidGeometryName = false;*/
+                AddGeometryProperty(new GMLGeometryPropertyDefn(
+                    pszGName, pszGPath, nGeomType, -1, true));
+                // bHasValidGeometryName = false;
                 bHasValidGeometryElementPath = false;
                 bHasFoundGeomType = false;
                 pszGPath = "";
                 nGeomType = wkbUnknown;
             }
-            pszGName = CPLGetXMLValue( psThis, NULL, "" );
+            pszGName = CPLGetXMLValue(psThis, NULL, "");
             bHasValidGeometryName = true;
         }
         else if( psThis->eType == CXT_Element &&
-            strcmp(psThis->pszValue, "GeometryElementPath") == 0 )
+                 strcmp(psThis->pszValue, "GeometryElementPath") == 0 )
         {
             bHasFoundGeomElements = true;
 
             if( bHasValidGeometryElementPath )
             {
-                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, true ) );
+                AddGeometryProperty(new GMLGeometryPropertyDefn(
+                    pszGName, pszGPath, nGeomType, -1, true));
                 bHasValidGeometryName = false;
-                /*bHasValidGeometryElementPath = false;*/
+                // bHasValidGeometryElementPath = false;
                 bHasFoundGeomType = false;
                 pszGName = "";
                 nGeomType = wkbUnknown;
             }
-            pszGPath = CPLGetXMLValue( psThis, NULL, "" );
+            pszGPath = CPLGetXMLValue(psThis, NULL, "");
             bHasValidGeometryElementPath = true;
         }
         else if( psThis->eType == CXT_Element &&
@@ -535,183 +541,198 @@ bool GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
 
             if( bHasFoundGeomType )
             {
-                AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, true ) );
+                AddGeometryProperty(new GMLGeometryPropertyDefn(
+                    pszGName, pszGPath, nGeomType, -1, true));
                 bHasValidGeometryName = false;
                 bHasValidGeometryElementPath = false;
-                /*bHasFoundGeomType = false;*/
+                // bHasFoundGeomType = false;
                 pszGName = "";
                 pszGPath = "";
             }
-            const char* pszGeometryType = CPLGetXMLValue( psThis, NULL, NULL );
+            const char *pszGeometryType = CPLGetXMLValue(psThis, NULL, NULL);
             nGeomType = wkbUnknown;
             if( pszGeometryType != NULL && !EQUAL(pszGeometryType, "0") )
             {
                 nGeomType = atoi(pszGeometryType);
-                OGRwkbGeometryType nFlattenGeomType = wkbFlatten(nGeomType);
+                const OGRwkbGeometryType nFlattenGeomType =
+                    wkbFlatten(nGeomType);
                 if( nGeomType == 100 || EQUAL(pszGeometryType, "NONE") )
                 {
                     bHasValidGeometryElementPath = false;
                     bHasFoundGeomType = false;
                     break;
                 }
-                else if( nGeomType != 0 && !(nFlattenGeomType >= wkbPoint && nFlattenGeomType <= wkbMultiSurface) )
+                else if( nGeomType != 0 &&
+                         !(nFlattenGeomType >= wkbPoint &&
+                           nFlattenGeomType <= wkbMultiSurface) )
                 {
                     nGeomType = wkbUnknown;
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "Unrecognized geometry type : %s",
-                              pszGeometryType);
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Unrecognized geometry type : %s",
+                             pszGeometryType);
                 }
                 else if( nGeomType == 0 )
+                {
                     nGeomType = OGRFromOGCGeomType(pszGeometryType);
+                }
             }
             bHasFoundGeomType = true;
         }
     }
 
-    /* If there was a dangling <GeometryElementPath> or <GeometryType> or */
-    /* that no explicit geometry information has been found, then add */
-    /* a geometry field */
-    if( bHasValidGeometryElementPath || bHasFoundGeomType || !bHasFoundGeomElements )
+    // If there was a dangling <GeometryElementPath> or <GeometryType> or
+    // that no explicit geometry information has been found, then add
+    // a geometry field.
+    if( bHasValidGeometryElementPath || bHasFoundGeomType ||
+        !bHasFoundGeomElements )
     {
-        AddGeometryProperty( new GMLGeometryPropertyDefn( pszGName, pszGPath, nGeomType, -1, true ) );
+        AddGeometryProperty(new GMLGeometryPropertyDefn(pszGName, pszGPath,
+                                                        nGeomType, -1, true));
     }
 
-    SetSRSName( CPLGetXMLValue( psRoot, "SRSName", NULL ) );
+    SetSRSName(CPLGetXMLValue(psRoot, "SRSName", NULL));
 
-/* -------------------------------------------------------------------- */
-/*      Collect dataset specific info.                                  */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode *psDSI = CPLGetXMLNode( psRoot, "DatasetSpecificInfo" );
+    // Collect dataset specific info.
+    CPLXMLNode *psDSI = CPLGetXMLNode(psRoot, "DatasetSpecificInfo");
     if( psDSI != NULL )
     {
-        const char *pszValue;
-
-        pszValue = CPLGetXMLValue( psDSI, "FeatureCount", NULL );
+        const char *pszValue = CPLGetXMLValue(psDSI, "FeatureCount", NULL);
         if( pszValue != NULL )
-            SetFeatureCount( CPLAtoGIntBig(pszValue) );
+            SetFeatureCount(CPLAtoGIntBig(pszValue));
 
         // Eventually we should support XML subtrees.
-        pszValue = CPLGetXMLValue( psDSI, "ExtraInfo", NULL );
+        pszValue = CPLGetXMLValue(psDSI, "ExtraInfo", NULL);
         if( pszValue != NULL )
-            SetExtraInfo( pszValue );
+            SetExtraInfo(pszValue);
 
-        if( CPLGetXMLValue( psDSI, "ExtentXMin", NULL ) != NULL
-            && CPLGetXMLValue( psDSI, "ExtentXMax", NULL ) != NULL
-            && CPLGetXMLValue( psDSI, "ExtentYMin", NULL ) != NULL
-            && CPLGetXMLValue( psDSI, "ExtentYMax", NULL ) != NULL )
+        if( CPLGetXMLValue(psDSI, "ExtentXMin", NULL) != NULL &&
+            CPLGetXMLValue(psDSI, "ExtentXMax", NULL) != NULL &&
+            CPLGetXMLValue(psDSI, "ExtentYMin", NULL) != NULL &&
+            CPLGetXMLValue(psDSI, "ExtentYMax", NULL) != NULL )
         {
-            SetExtents( CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMin", "0.0" )),
-                        CPLAtof(CPLGetXMLValue( psDSI, "ExtentXMax", "0.0" )),
-                        CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMin", "0.0" )),
-                        CPLAtof(CPLGetXMLValue( psDSI, "ExtentYMax", "0.0" )) );
+            SetExtents(CPLAtof(CPLGetXMLValue(psDSI, "ExtentXMin", "0.0")),
+                       CPLAtof(CPLGetXMLValue(psDSI, "ExtentXMax", "0.0")),
+                       CPLAtof(CPLGetXMLValue(psDSI, "ExtentYMin", "0.0")),
+                       CPLAtof(CPLGetXMLValue(psDSI, "ExtentYMax", "0.0")));
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Collect property definitions.                                   */
-/* -------------------------------------------------------------------- */
+    // Collect property definitions.
     for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
     {
         if( psThis->eType == CXT_Element &&
             EQUAL(psThis->pszValue, "PropertyDefn") )
         {
-            const char *pszName = CPLGetXMLValue( psThis, "Name", NULL );
-            const char *pszType = CPLGetXMLValue( psThis, "Type", "Untyped" );
-            const char *pszSubType = CPLGetXMLValue( psThis, "Subtype", "" );
-            const char *pszCondition = CPLGetXMLValue( psThis, "Condition", NULL );
-            bool bNullable = CPLTestBool(CPLGetXMLValue( psThis, "Nullable", "true") );
-            GMLPropertyDefn *poPDefn;
+            const char *pszName = CPLGetXMLValue(psThis, "Name", NULL);
+            const char *pszType = CPLGetXMLValue(psThis, "Type", "Untyped");
+            const char *pszSubType = CPLGetXMLValue(psThis, "Subtype", "");
+            const char *pszCondition =
+                CPLGetXMLValue(psThis, "Condition", NULL);
+            const bool bNullable =
+                CPLTestBool(CPLGetXMLValue(psThis, "Nullable", "true"));
 
             if( pszName == NULL )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "GMLFeatureClass %s has a PropertyDefn without a <Name>..",
-                          m_pszName );
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "GMLFeatureClass %s has a PropertyDefn without a <Name>.",
+                    m_pszName);
                 return false;
             }
 
-            poPDefn = new GMLPropertyDefn(
-                pszName, CPLGetXMLValue( psThis, "ElementPath", NULL ) );
+            GMLPropertyDefn *poPDefn = new GMLPropertyDefn(
+                pszName, CPLGetXMLValue(psThis, "ElementPath", NULL));
 
             poPDefn->SetNullable(bNullable);
-            if( EQUAL(pszType,"Untyped") )
-                poPDefn->SetType( GMLPT_Untyped );
-            else if( EQUAL(pszType,"String") )
+            if( EQUAL(pszType, "Untyped") )
+            {
+                poPDefn->SetType(GMLPT_Untyped);
+            }
+            else if( EQUAL(pszType, "String") )
             {
                 if( EQUAL(pszSubType, "Boolean") )
                 {
-                    poPDefn->SetType( GMLPT_Boolean );
-                    poPDefn->SetWidth( 1 );
+                    poPDefn->SetType(GMLPT_Boolean);
+                    poPDefn->SetWidth(1);
                 }
                 else
                 {
-                    poPDefn->SetType( GMLPT_String );
-                    poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
+                    poPDefn->SetType(GMLPT_String);
+                    poPDefn->SetWidth(
+                        atoi(CPLGetXMLValue(psThis, "Width", "0")));
                 }
             }
-            else if( EQUAL(pszType,"Integer") )
+            else if( EQUAL(pszType, "Integer") )
             {
                 if( EQUAL(pszSubType, "Short") )
                 {
-                    poPDefn->SetType( GMLPT_Short );
+                    poPDefn->SetType(GMLPT_Short);
                 }
                 else if( EQUAL(pszSubType, "Integer64") )
                 {
-                    poPDefn->SetType( GMLPT_Integer64 );
+                    poPDefn->SetType(GMLPT_Integer64);
                 }
                 else
                 {
-                    poPDefn->SetType( GMLPT_Integer );
+                    poPDefn->SetType(GMLPT_Integer);
                 }
-                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
+                poPDefn->SetWidth(atoi(CPLGetXMLValue(psThis, "Width", "0")));
             }
-            else if( EQUAL(pszType,"Real") )
+            else if( EQUAL(pszType, "Real") )
             {
                 if( EQUAL(pszSubType, "Float") )
                 {
-                    poPDefn->SetType( GMLPT_Float );
+                    poPDefn->SetType(GMLPT_Float);
                 }
                 else
                 {
-                    poPDefn->SetType( GMLPT_Real );
+                    poPDefn->SetType(GMLPT_Real);
                 }
-                poPDefn->SetWidth( atoi( CPLGetXMLValue( psThis, "Width", "0" ) ) );
-                poPDefn->SetPrecision( atoi( CPLGetXMLValue( psThis, "Precision", "0" ) ) );
+                poPDefn->SetWidth(atoi(CPLGetXMLValue(psThis, "Width", "0")));
+                poPDefn->SetPrecision(
+                    atoi(CPLGetXMLValue(psThis, "Precision", "0")));
             }
-            else if( EQUAL(pszType,"StringList") )
+            else if( EQUAL(pszType, "StringList") )
             {
                 if( EQUAL(pszSubType, "Boolean") )
-                    poPDefn->SetType( GMLPT_BooleanList );
+                    poPDefn->SetType(GMLPT_BooleanList);
                 else
-                    poPDefn->SetType( GMLPT_StringList );
+                    poPDefn->SetType(GMLPT_StringList);
             }
-            else if( EQUAL(pszType,"IntegerList") )
+            else if( EQUAL(pszType, "IntegerList") )
             {
                 if( EQUAL(pszSubType, "Integer64") )
-                    poPDefn->SetType( GMLPT_Integer64List );
+                    poPDefn->SetType(GMLPT_Integer64List);
                 else
-                    poPDefn->SetType( GMLPT_IntegerList );
+                    poPDefn->SetType(GMLPT_IntegerList);
+            }
+            else if( EQUAL(pszType, "RealList") )
+            {
+                poPDefn->SetType(GMLPT_RealList);
+            }
+            else if( EQUAL(pszType, "Complex") ) {
+                poPDefn->SetType(GMLPT_Complex);
+            }
+            else if( EQUAL(pszType, "FeatureProperty") )
+            {
+                poPDefn->SetType(GMLPT_FeatureProperty);
+            }
+            else if( EQUAL(pszType, "FeaturePropertyList") )
+            {
+                poPDefn->SetType(GMLPT_FeaturePropertyList );
             }
-            else if( EQUAL(pszType,"RealList") )
-                poPDefn->SetType( GMLPT_RealList );
-            else if( EQUAL(pszType,"Complex") )
-                poPDefn->SetType( GMLPT_Complex );
-            else if( EQUAL(pszType,"FeatureProperty") )
-                poPDefn->SetType( GMLPT_FeatureProperty );
-            else if( EQUAL(pszType,"FeaturePropertyList") )
-                poPDefn->SetType( GMLPT_FeaturePropertyList );
             else
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Unrecognized property type %s.",
-                          pszType );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Unrecognized property type %s.",
+                         pszType);
                 delete poPDefn;
                 return false;
             }
             if( pszCondition != NULL )
                 poPDefn->SetCondition(pszCondition);
 
-            if( AddProperty( poPDefn ) < 0 )
+            if( AddProperty(poPDefn) < 0 )
                 delete poPDefn;
         }
     }
@@ -726,99 +747,97 @@ bool GMLFeatureClass::InitializeFromXML( CPLXMLNode *psRoot )
 CPLXMLNode *GMLFeatureClass::SerializeToXML()
 
 {
-    CPLXMLNode  *psRoot;
-    int         iProperty;
+    // Set feature class and core information.
+    CPLXMLNode *psRoot = CPLCreateXMLNode(NULL, CXT_Element, "GMLFeatureClass");
 
-/* -------------------------------------------------------------------- */
-/*      Set feature class and core information.                         */
-/* -------------------------------------------------------------------- */
-    psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClass" );
-
-    CPLCreateXMLElementAndValue( psRoot, "Name", GetName() );
-    CPLCreateXMLElementAndValue( psRoot, "ElementPath", GetElementName() );
+    CPLCreateXMLElementAndValue(psRoot, "Name", GetName());
+    CPLCreateXMLElementAndValue(psRoot, "ElementPath", GetElementName());
 
     if( m_nGeometryPropertyCount > 1 )
     {
-        for(int i=0; i < m_nGeometryPropertyCount; i++)
+        for(int i = 0; i < m_nGeometryPropertyCount; i++)
         {
-            GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[i];
+            GMLGeometryPropertyDefn *poGeomFDefn = m_papoGeometryProperty[i];
 
-            CPLXMLNode *psPDefnNode;
-            psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "GeomPropertyDefn" );
+            CPLXMLNode *psPDefnNode =
+                CPLCreateXMLNode(psRoot, CXT_Element, "GeomPropertyDefn");
             if( strlen(poGeomFDefn->GetName()) > 0 )
-                CPLCreateXMLElementAndValue( psPDefnNode, "Name",
-                                             poGeomFDefn->GetName() );
-            if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 )
-                CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath",
-                                             poGeomFDefn->GetSrcElement() );
+                CPLCreateXMLElementAndValue(psPDefnNode, "Name",
+                                            poGeomFDefn->GetName());
+            if( poGeomFDefn->GetSrcElement() != NULL &&
+                strlen(poGeomFDefn->GetSrcElement()) > 0 )
+                CPLCreateXMLElementAndValue(psPDefnNode, "ElementPath",
+                                            poGeomFDefn->GetSrcElement());
 
             if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ )
             {
-                char szValue[128];
+                char szValue[128] = {};
 
-                OGRwkbGeometryType eType = (OGRwkbGeometryType)poGeomFDefn->GetType();
+                const OGRwkbGeometryType eType =
+                    static_cast<OGRwkbGeometryType>(poGeomFDefn->GetType());
 
                 CPLString osStr(OGRToOGCGeomType(eType));
-                if( wkbHasZ(eType) ) osStr += "Z";
-                CPLCreateXMLNode( psPDefnNode, CXT_Comment, osStr.c_str() );
+                if( wkbHasZ(eType) )
+                    osStr += "Z";
+                CPLCreateXMLNode(psPDefnNode, CXT_Comment, osStr.c_str());
 
-                snprintf( szValue, sizeof(szValue), "%d", eType );
-                CPLCreateXMLElementAndValue( psPDefnNode, "Type", szValue );
+                snprintf(szValue, sizeof(szValue), "%d", eType);
+                CPLCreateXMLElementAndValue(psPDefnNode, "Type", szValue);
             }
         }
     }
     else if( m_nGeometryPropertyCount == 1 )
     {
-        GMLGeometryPropertyDefn* poGeomFDefn = m_papoGeometryProperty[0];
+        GMLGeometryPropertyDefn *poGeomFDefn = m_papoGeometryProperty[0];
 
         if( strlen(poGeomFDefn->GetName()) > 0 )
-            CPLCreateXMLElementAndValue( psRoot, "GeometryName",
-                                         poGeomFDefn->GetName() );
+            CPLCreateXMLElementAndValue(psRoot, "GeometryName",
+                                        poGeomFDefn->GetName());
 
-        if( poGeomFDefn->GetSrcElement() != NULL && strlen(poGeomFDefn->GetSrcElement()) > 0 )
-            CPLCreateXMLElementAndValue( psRoot, "GeometryElementPath",
-                                         poGeomFDefn->GetSrcElement() );
+        if( poGeomFDefn->GetSrcElement() != NULL &&
+            strlen(poGeomFDefn->GetSrcElement()) > 0 )
+            CPLCreateXMLElementAndValue(psRoot, "GeometryElementPath",
+                                        poGeomFDefn->GetSrcElement());
 
         if( poGeomFDefn->GetType() != 0 /* wkbUnknown */ )
         {
-            char szValue[128];
+            char szValue[128] = {};
 
-            OGRwkbGeometryType eType = (OGRwkbGeometryType)poGeomFDefn->GetType();
+            OGRwkbGeometryType eType =
+                static_cast<OGRwkbGeometryType>(poGeomFDefn->GetType());
 
             CPLString osStr(OGRToOGCGeomType(eType));
-            if( wkbHasZ(eType) ) osStr += "Z";
-            CPLCreateXMLNode( psRoot, CXT_Comment, osStr.c_str() );
+            if( wkbHasZ(eType) )
+                osStr += "Z";
+            CPLCreateXMLNode(psRoot, CXT_Comment, osStr.c_str());
 
-            snprintf( szValue, sizeof(szValue), "%d", eType );
-            CPLCreateXMLElementAndValue( psRoot, "GeometryType", szValue );
+            snprintf(szValue, sizeof(szValue), "%d", eType);
+            CPLCreateXMLElementAndValue(psRoot, "GeometryType", szValue);
         }
     }
     else
     {
-        CPLCreateXMLElementAndValue( psRoot, "GeometryType", "100" );
+        CPLCreateXMLElementAndValue(psRoot, "GeometryType", "100");
     }
 
-    const char* pszSRSName = GetSRSName();
+    const char *pszSRSName = GetSRSName();
     if( pszSRSName )
     {
-        CPLCreateXMLElementAndValue( psRoot, "SRSName", pszSRSName );
+        CPLCreateXMLElementAndValue(psRoot, "SRSName", pszSRSName);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write out dataset specific information.                         */
-/* -------------------------------------------------------------------- */
-    CPLXMLNode *psDSI;
-
+    // Write out dataset specific information.
     if( m_bHaveExtents || m_nFeatureCount != -1 || m_pszExtraInfo != NULL )
     {
-        psDSI = CPLCreateXMLNode( psRoot, CXT_Element, "DatasetSpecificInfo" );
+        CPLXMLNode *psDSI =
+            CPLCreateXMLNode(psRoot, CXT_Element, "DatasetSpecificInfo");
 
         if( m_nFeatureCount != -1 )
         {
-            char szValue[128];
+            char szValue[128] = {};
 
-            snprintf( szValue, sizeof(szValue), CPL_FRMT_GIB, m_nFeatureCount );
-            CPLCreateXMLElementAndValue( psDSI, "FeatureCount", szValue );
+            snprintf(szValue, sizeof(szValue), CPL_FRMT_GIB, m_nFeatureCount);
+            CPLCreateXMLElementAndValue(psDSI, "FeatureCount", szValue);
         }
 
         if( m_bHaveExtents &&
@@ -827,39 +846,36 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
             fabs(m_dfYMin) < 1e100 &&
             fabs(m_dfYMax) < 1e100 )
         {
-            char szValue[128];
+            char szValue[128] = {};
 
-            CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfXMin );
-            CPLCreateXMLElementAndValue( psDSI, "ExtentXMin", szValue );
+            CPLsnprintf(szValue, sizeof(szValue), "%.5f", m_dfXMin);
+            CPLCreateXMLElementAndValue(psDSI, "ExtentXMin", szValue);
 
-            CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfXMax );
-            CPLCreateXMLElementAndValue( psDSI, "ExtentXMax", szValue );
+            CPLsnprintf(szValue, sizeof(szValue), "%.5f", m_dfXMax);
+            CPLCreateXMLElementAndValue(psDSI, "ExtentXMax", szValue);
 
-            CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfYMin );
-            CPLCreateXMLElementAndValue( psDSI, "ExtentYMin", szValue );
+            CPLsnprintf(szValue, sizeof(szValue), "%.5f", m_dfYMin);
+            CPLCreateXMLElementAndValue(psDSI, "ExtentYMin", szValue);
 
-            CPLsnprintf( szValue, sizeof(szValue), "%.5f", m_dfYMax );
-            CPLCreateXMLElementAndValue( psDSI, "ExtentYMax", szValue );
+            CPLsnprintf(szValue, sizeof(szValue), "%.5f", m_dfYMax);
+            CPLCreateXMLElementAndValue(psDSI, "ExtentYMax", szValue);
         }
 
         if( m_pszExtraInfo )
-            CPLCreateXMLElementAndValue( psDSI, "ExtraInfo", m_pszExtraInfo );
+            CPLCreateXMLElementAndValue(psDSI, "ExtraInfo", m_pszExtraInfo);
     }
 
-/* -------------------------------------------------------------------- */
-/*      emit property information.                                      */
-/* -------------------------------------------------------------------- */
-    for( iProperty = 0; iProperty < GetPropertyCount(); iProperty++ )
+    // Emit property information.
+    for( int iProperty = 0; iProperty < GetPropertyCount(); iProperty++ )
     {
-        GMLPropertyDefn *poPDefn = GetProperty( iProperty );
-        CPLXMLNode *psPDefnNode;
+        GMLPropertyDefn *poPDefn = GetProperty(iProperty);
         const char *pszTypeName = "Unknown";
 
-        psPDefnNode = CPLCreateXMLNode( psRoot, CXT_Element, "PropertyDefn" );
-        CPLCreateXMLElementAndValue( psPDefnNode, "Name",
-                                     poPDefn->GetName() );
-        CPLCreateXMLElementAndValue( psPDefnNode, "ElementPath",
-                                     poPDefn->GetSrcElement() );
+        CPLXMLNode *psPDefnNode =
+            CPLCreateXMLNode(psRoot, CXT_Element, "PropertyDefn");
+        CPLCreateXMLElementAndValue(psPDefnNode, "Name", poPDefn->GetName());
+        CPLCreateXMLElementAndValue(psPDefnNode, "ElementPath",
+                                    poPDefn->GetSrcElement());
         switch( poPDefn->GetType() )
         {
           case GMLPT_Untyped:
@@ -900,49 +916,51 @@ CPLXMLNode *GMLFeatureClass::SerializeToXML()
             pszTypeName = "StringList";
             break;
 
-          /* should not happen in practice for now because this is not */
-          /* autodetected */
+          // Should not happen in practice for now because this is not
+          // autodetected.
           case GMLPT_FeatureProperty:
             pszTypeName = "FeatureProperty";
             break;
 
-          /* should not happen in practice for now because this is not */
-          /* autodetected */
+          // Should not happen in practice for now because this is not
+          // autodetected.
           case GMLPT_FeaturePropertyList:
             pszTypeName = "FeaturePropertyList";
             break;
         }
-        CPLCreateXMLElementAndValue( psPDefnNode, "Type", pszTypeName );
+        CPLCreateXMLElementAndValue(psPDefnNode, "Type", pszTypeName);
         if( poPDefn->GetType() == GMLPT_Boolean || poPDefn->GetType() == GMLPT_BooleanList )
-            CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Boolean" );
+            CPLCreateXMLElementAndValue(psPDefnNode, "Subtype", "Boolean");
         else if( poPDefn->GetType() == GMLPT_Short )
-            CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Short" );
+            CPLCreateXMLElementAndValue(psPDefnNode, "Subtype", "Short");
         else if( poPDefn->GetType() == GMLPT_Float )
-            CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Float" );
+            CPLCreateXMLElementAndValue(psPDefnNode, "Subtype", "Float");
         else if( poPDefn->GetType() == GMLPT_Integer64 ||
                  poPDefn->GetType() == GMLPT_Integer64List )
-            CPLCreateXMLElementAndValue( psPDefnNode, "Subtype", "Integer64" );
+            CPLCreateXMLElementAndValue(psPDefnNode, "Subtype", "Integer64");
 
-        if( EQUAL(pszTypeName,"String") )
+        if( EQUAL(pszTypeName, "String") )
         {
-            char szMaxLength[48];
-            snprintf(szMaxLength, sizeof(szMaxLength), "%d", poPDefn->GetWidth());
-            CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szMaxLength );
+            char szMaxLength[48] = {};
+            snprintf(szMaxLength, sizeof(szMaxLength), "%d",
+                     poPDefn->GetWidth());
+            CPLCreateXMLElementAndValue(psPDefnNode, "Width", szMaxLength);
         }
-        if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Integer") )
+        if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName, "Integer") )
         {
-            char szLength[48];
+            char szLength[48] = {};
             snprintf(szLength, sizeof(szLength), "%d", poPDefn->GetWidth());
-            CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
+            CPLCreateXMLElementAndValue(psPDefnNode, "Width", szLength);
         }
-        if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName,"Real") )
+        if( poPDefn->GetWidth() > 0 && EQUAL(pszTypeName, "Real") )
         {
-            char szLength[48];
+            char szLength[48] = {};
             snprintf(szLength, sizeof(szLength), "%d", poPDefn->GetWidth());
-            CPLCreateXMLElementAndValue ( psPDefnNode, "Width", szLength );
-            char szPrecision[48];
-            snprintf(szPrecision, sizeof(szPrecision), "%d", poPDefn->GetPrecision());
-            CPLCreateXMLElementAndValue ( psPDefnNode, "Precision", szPrecision );
+            CPLCreateXMLElementAndValue(psPDefnNode, "Width", szLength);
+            char szPrecision[48] = {};
+            snprintf(szPrecision, sizeof(szPrecision), "%d",
+                     poPDefn->GetPrecision());
+            CPLCreateXMLElementAndValue(psPDefnNode, "Precision", szPrecision);
         }
     }
 
diff --git a/ogr/ogrsf_frmts/gml/gmlhandler.cpp b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
index 1c1cd1c..6289622 100644
--- a/ogr/ogrsf_frmts/gml/gmlhandler.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlhandler.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: gmlhandler.cpp 34706 2016-07-18 21:08:52Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLHandler class.
@@ -28,58 +27,63 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <ctype.h>
+#include "cpl_port.h"
+#include "gmlreader.h"
 #include "gmlreaderp.h"
+
+#include <climits>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+#include <string>
+#include <vector>
+
 #include "cpl_conv.h"
-#include "cpl_string.h"
+#include "cpl_error.h"
 #include "cpl_hash_set.h"
-
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#ifdef HAVE_EXPAT
+#  include "expat.h"
+#  include "expat_external.h"
+#endif
+#include "ogr_core.h"
 #ifdef HAVE_XERCES
+#  include "ogr_xerces.h"
+#endif
 
-/* Must be a multiple of 4 */
-#define MAX_TOKEN_SIZE  1000
+CPL_CVSID("$Id: gmlhandler.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
+#ifdef HAVE_XERCES
 
 /************************************************************************/
 /*                        GMLXercesHandler()                            */
 /************************************************************************/
 
-GMLXercesHandler::GMLXercesHandler( GMLReader *poReader ) : GMLHandler(poReader)
-{
-    m_nEntityCounter = 0;
-}
+GMLXercesHandler::GMLXercesHandler( GMLReader *poReader ) :
+    GMLHandler(poReader),
+    m_nEntityCounter(0)
+{}
 
 /************************************************************************/
 /*                            startElement()                            */
 /************************************************************************/
 
-void GMLXercesHandler::startElement(CPL_UNUSED const XMLCh* const uri,
-                                    const XMLCh* const localname,
-                                    CPL_UNUSED const XMLCh* const qname,
-                                    const Attributes& attrs )
+void GMLXercesHandler::startElement( const XMLCh* const /*uri*/,
+                                     const XMLCh* const localname,
+                                     const XMLCh* const /*qname*/,
+                                     const Attributes& attrs )
 {
-    char        szElementName[MAX_TOKEN_SIZE];
-
     m_nEntityCounter = 0;
 
-    /* A XMLCh character can expand to 4 bytes in UTF-8 */
-    if (4 * tr_strlen( localname ) >= MAX_TOKEN_SIZE)
-    {
-        static bool bWarnOnce = false;
-        XMLCh* tempBuffer = (XMLCh*) CPLMalloc(sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4 + 1));
-        memcpy(tempBuffer, localname, sizeof(XMLCh) * (MAX_TOKEN_SIZE / 4));
-        tempBuffer[MAX_TOKEN_SIZE / 4] = 0;
-        tr_strcpy( szElementName, tempBuffer );
-        CPLFree(tempBuffer);
-        if (!bWarnOnce)
-        {
-            bWarnOnce = true;
-            CPLError(CE_Warning, CPLE_AppDefined, "A too big element name has been truncated");
-        }
-    }
-    else
-        tr_strcpy( szElementName, localname );
+    transcode(localname, m_osElement);
 
-    if (GMLHandler::startElement(szElementName, (int)strlen(szElementName), (void*) &attrs) == OGRERR_NOT_ENOUGH_MEMORY)
+    if( GMLHandler::startElement(
+            m_osElement.c_str(),
+            static_cast<int>(m_osElement.size()),
+            const_cast<Attributes *>(&attrs)) == OGRERR_NOT_ENOUGH_MEMORY )
     {
         throw SAXNotSupportedException("Out of memory");
     }
@@ -88,9 +92,9 @@ void GMLXercesHandler::startElement(CPL_UNUSED const XMLCh* const uri,
 /************************************************************************/
 /*                             endElement()                             */
 /************************************************************************/
-void GMLXercesHandler::endElement(CPL_UNUSED const XMLCh* const uri,
-                                  CPL_UNUSED const XMLCh* const localname,
-                                  CPL_UNUSED const XMLCh* const qname )
+void GMLXercesHandler::endElement(const XMLCh* const /*uri*/,
+                                  const XMLCh* const /*localname*/,
+                                  const XMLCh* const /*qname */)
 {
     m_nEntityCounter = 0;
 
@@ -105,19 +109,12 @@ void GMLXercesHandler::endElement(CPL_UNUSED const XMLCh* const uri,
 /************************************************************************/
 
 void GMLXercesHandler::characters(const XMLCh* const chars_in,
-                                  CPL_UNUSED
-#if XERCES_VERSION_MAJOR >= 3
-                                  const XMLSize_t length
-#else
-                                  const unsigned int length
-#endif
-                                  )
+                                  const XMLSize_t length )
 
 {
-    char* utf8String = tr_strdup(chars_in);
-    int nLen = (int)strlen(utf8String);
-    OGRErr eErr = GMLHandler::dataHandler(utf8String, nLen);
-    CPLFree(utf8String);
+    transcode( chars_in, m_osCharacters, static_cast<int>(length) );
+    OGRErr eErr = GMLHandler::dataHandler(m_osCharacters.c_str(),
+                                    static_cast<int>(m_osCharacters.size()));
     if (eErr == OGRERR_NOT_ENOUGH_MEMORY)
     {
         throw SAXNotSupportedException("Out of memory");
@@ -131,26 +128,26 @@ void GMLXercesHandler::characters(const XMLCh* const chars_in,
 void GMLXercesHandler::fatalError( const SAXParseException &exception)
 
 {
-    char *pszErrorMessage;
-
-    pszErrorMessage = tr_strdup( exception.getMessage() );
+    CPLString osMsg;
+    transcode( exception.getMessage(), osMsg );
     CPLError( CE_Failure, CPLE_AppDefined,
               "XML Parsing Error: %s at line %d, column %d\n",
-              pszErrorMessage, (int)exception.getLineNumber(), (int)exception.getColumnNumber() );
-
-    CPLFree( pszErrorMessage );
+              osMsg.c_str(),
+              static_cast<int>(exception.getLineNumber()),
+              static_cast<int>(exception.getColumnNumber()) );
 }
 
 /************************************************************************/
 /*                             startEntity()                            */
 /************************************************************************/
 
-void GMLXercesHandler::startEntity (CPL_UNUSED const XMLCh *const name)
+void GMLXercesHandler::startEntity( const XMLCh *const /* name */ )
 {
     m_nEntityCounter ++;
     if (m_nEntityCounter > 1000 && !m_poReader->HasStoppedParsing())
     {
-        throw SAXNotSupportedException("File probably corrupted (million laugh pattern)");
+        throw SAXNotSupportedException(
+            "File probably corrupted (million laugh pattern)");
     }
 }
 
@@ -160,33 +157,26 @@ void GMLXercesHandler::startEntity (CPL_UNUSED const XMLCh *const name)
 
 const char* GMLXercesHandler::GetFID(void* attr)
 {
-    const Attributes* attrs = (const Attributes*) attr;
-    int nFIDIndex;
-    XMLCh   anFID[100];
-
-    tr_strcpy( anFID, "fid" );
-    nFIDIndex = attrs->getIndex( anFID );
+    const Attributes* attrs = static_cast<const Attributes*>(attr);
+    const XMLCh achFID[] = { 'f', 'i', 'd', '\0' };
+    int nFIDIndex = attrs->getIndex( achFID );
     if( nFIDIndex != -1 )
     {
-        char* pszValue = tr_strdup( attrs->getValue( nFIDIndex ) );
-        osFID.assign(pszValue);
-        CPLFree(pszValue);
-        return osFID.c_str();
+        transcode( attrs->getValue( nFIDIndex ), m_osFID );
+        return m_osFID.c_str();
     }
     else
     {
-        tr_strcpy( anFID, "gml:id" );
-        nFIDIndex = attrs->getIndex( anFID );
+        const XMLCh achGMLID[] = { 'g', 'm', 'l', ':', 'i', 'd', '\0' };
+        nFIDIndex = attrs->getIndex( achGMLID );
         if( nFIDIndex != -1 )
         {
-            char* pszValue = tr_strdup( attrs->getValue( nFIDIndex ) );
-            osFID.assign(pszValue);
-            CPLFree(pszValue);
-            return osFID.c_str();
+            transcode( attrs->getValue( nFIDIndex ), m_osFID );
+            return m_osFID.c_str();
         }
     }
 
-    osFID.resize(0);
+    m_osFID.resize(0);
     return NULL;
 }
 
@@ -196,20 +186,18 @@ const char* GMLXercesHandler::GetFID(void* attr)
 
 CPLXMLNode* GMLXercesHandler::AddAttributes(CPLXMLNode* psNode, void* attr)
 {
-    const Attributes* attrs = (const Attributes*) attr;
+    const Attributes* attrs = static_cast<const Attributes *>(attr);
 
     CPLXMLNode* psLastChild = NULL;
 
     for(unsigned int i=0; i < attrs->getLength(); i++)
     {
-        char* pszName = tr_strdup(attrs->getQName(i));
-        char* pszValue = tr_strdup(attrs->getValue(i));
+        transcode(attrs->getQName(i), m_osAttrName);
+        transcode(attrs->getValue(i), m_osAttrValue);
 
-        CPLXMLNode* psChild = CPLCreateXMLNode(NULL, CXT_Attribute, pszName);
-        CPLCreateXMLNode(psChild, CXT_Text, pszValue);
-
-        CPLFree(pszName);
-        CPLFree(pszValue);
+        CPLXMLNode* psChild =
+            CPLCreateXMLNode(NULL, CXT_Attribute, m_osAttrName.c_str());
+        CPLCreateXMLNode(psChild, CXT_Text, m_osAttrValue.c_str() );
 
         if (psLastChild == NULL)
             psNode->psChild = psChild;
@@ -225,18 +213,18 @@ CPLXMLNode* GMLXercesHandler::AddAttributes(CPLXMLNode* psNode, void* attr)
 /*                    GetAttributeValue()                               */
 /************************************************************************/
 
-char* GMLXercesHandler::GetAttributeValue(void* attr, const char* pszAttributeName)
+char* GMLXercesHandler::GetAttributeValue( void* attr,
+                                           const char* pszAttributeName )
 {
-    const Attributes* attrs = (const Attributes*) attr;
-    for(unsigned int i=0; i < attrs->getLength(); i++)
+    const Attributes* attrs = static_cast<const Attributes *>(attr);
+    for( unsigned int i=0; i < attrs->getLength(); i++ )
     {
-        char* pszString = tr_strdup(attrs->getQName(i));
-        if (strcmp(pszString, pszAttributeName) == 0)
+        transcode(attrs->getQName(i), m_osAttrName);
+        if (m_osAttrName == pszAttributeName)
         {
-            CPLFree(pszString);
-            return tr_strdup(attrs->getValue(i));
+            transcode(attrs->getValue(i), m_osAttrValue);
+            return CPLStrdup(m_osAttrValue);
         }
-        CPLFree(pszString);
     }
     return NULL;
 }
@@ -245,16 +233,20 @@ char* GMLXercesHandler::GetAttributeValue(void* attr, const char* pszAttributeNa
 /*                    GetAttributeByIdx()                               */
 /************************************************************************/
 
-char* GMLXercesHandler::GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey)
+char* GMLXercesHandler::GetAttributeByIdx( void* attr, unsigned int idx,
+                                           char** ppszKey )
 {
-    const Attributes* attrs = (const Attributes*) attr;
+    const Attributes* attrs = static_cast<const Attributes *>(attr);
     if( idx >= attrs->getLength() )
     {
         *ppszKey = NULL;
         return NULL;
     }
-    *ppszKey = tr_strdup(attrs->getQName(idx));
-    return tr_strdup(attrs->getValue(idx));
+    transcode(attrs->getQName(idx), m_osAttrName);
+    transcode(attrs->getValue(idx), m_osAttrValue);
+
+    *ppszKey = CPLStrdup( m_osAttrName );
+    return CPLStrdup( m_osAttrValue );
 }
 
 #endif
@@ -265,55 +257,56 @@ char* GMLXercesHandler::GetAttributeByIdx(void* attr, unsigned int idx, char** p
 /*                            GMLExpatHandler()                         */
 /************************************************************************/
 
-GMLExpatHandler::GMLExpatHandler( GMLReader *poReader, XML_Parser oParser ) : GMLHandler(poReader)
-
-{
-    m_oParser = oParser;
-    m_bStopParsing = false;
-    m_nDataHandlerCounter = 0;
-}
+GMLExpatHandler::GMLExpatHandler( GMLReader *poReader, XML_Parser oParser ) :
+    GMLHandler(poReader),
+    m_oParser(oParser),
+    m_bStopParsing(false),
+    m_nDataHandlerCounter(0)
+{}
 
 /************************************************************************/
 /*                           startElementCbk()                          */
 /************************************************************************/
 
-void XMLCALL GMLExpatHandler::startElementCbk(void *pUserData, const char *pszName,
-                                              const char **ppszAttr)
+void XMLCALL GMLExpatHandler::startElementCbk( void *pUserData,
+                                               const char *pszName,
+                                               const char **ppszAttr )
 
 {
-    GMLExpatHandler* pThis = ((GMLExpatHandler*)pUserData);
+    GMLExpatHandler* pThis = static_cast<GMLExpatHandler *>(pUserData);
     if (pThis->m_bStopParsing)
         return;
 
     const char* pszIter = pszName;
-    char ch;
-    while((ch = *pszIter) != '\0')
+    char ch = '\0';
+    while( (ch = *pszIter) != '\0' )
     {
-        if (ch == ':')
+        if( ch == ':' )
             pszName = pszIter + 1;
         pszIter ++;
     }
 
-    if (pThis->GMLHandler::startElement(pszName, (int)(pszIter - pszName), ppszAttr) == OGRERR_NOT_ENOUGH_MEMORY)
+    if( pThis->GMLHandler::startElement(pszName,
+                                        static_cast<int>(pszIter - pszName),
+                                        ppszAttr) == OGRERR_NOT_ENOUGH_MEMORY )
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         pThis->m_bStopParsing = true;
         XML_StopParser(pThis->m_oParser, XML_FALSE);
     }
-
 }
 
 /************************************************************************/
 /*                            endElementCbk()                           */
 /************************************************************************/
-void XMLCALL GMLExpatHandler::endElementCbk(void *pUserData,
-                                            CPL_UNUSED const char* pszName )
+void XMLCALL GMLExpatHandler::endElementCbk( void *pUserData,
+                                             const char* /* pszName */ )
 {
-    GMLExpatHandler* pThis = ((GMLExpatHandler*)pUserData);
-    if (pThis->m_bStopParsing)
+    GMLExpatHandler* pThis = static_cast<GMLExpatHandler *>(pUserData);
+    if( pThis->m_bStopParsing )
         return;
 
-    if (pThis->GMLHandler::endElement() == OGRERR_NOT_ENOUGH_MEMORY)
+    if( pThis->GMLHandler::endElement() == OGRERR_NOT_ENOUGH_MEMORY )
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         pThis->m_bStopParsing = true;
@@ -325,35 +318,36 @@ void XMLCALL GMLExpatHandler::endElementCbk(void *pUserData,
 /*                            dataHandlerCbk()                          */
 /************************************************************************/
 
-void XMLCALL GMLExpatHandler::dataHandlerCbk(void *pUserData, const char *data, int nLen)
+void XMLCALL
+GMLExpatHandler::dataHandlerCbk(void *pUserData, const char *data, int nLen)
 
 {
-    GMLExpatHandler* pThis = ((GMLExpatHandler*)pUserData);
-    if (pThis->m_bStopParsing)
+    GMLExpatHandler* pThis = static_cast<GMLExpatHandler *>(pUserData);
+    if( pThis->m_bStopParsing )
         return;
 
-    pThis->m_nDataHandlerCounter ++;
-    /* The size of the buffer that is fetched and that Expat parses is */
-    /* PARSER_BUF_SIZE bytes. If the dataHandlerCbk() callback is called */
-    /* more than PARSER_BUF_SIZE times, this means that one byte in the */
-    /* file expands to more XML text fragments, which is the sign of a */
-    /* likely abuse of <!ENTITY> */
-    /* Note: the counter is zeroed by ResetDataHandlerCounter() before each */
-    /* new XML parsing. */
-    if (pThis->m_nDataHandlerCounter >= PARSER_BUF_SIZE)
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "File probably corrupted (million laugh pattern)");
+    pThis->m_nDataHandlerCounter++;
+    // The size of the buffer that is fetched and that Expat parses is
+    // PARSER_BUF_SIZE bytes. If the dataHandlerCbk() callback is called
+    // more than PARSER_BUF_SIZE times, this means that one byte in the
+    // file expands to more XML text fragments, which is the sign of a
+    // likely abuse of <!ENTITY>
+    // Note: the counter is zeroed by ResetDataHandlerCounter() before each
+    // new XML parsing.
+    if( pThis->m_nDataHandlerCounter >= PARSER_BUF_SIZE )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "File probably corrupted (million laugh pattern)");
         pThis->m_bStopParsing = true;
         XML_StopParser(pThis->m_oParser, XML_FALSE);
         return;
     }
 
-    if (pThis->GMLHandler::dataHandler(data, nLen) == OGRERR_NOT_ENOUGH_MEMORY)
+    if( pThis->GMLHandler::dataHandler(data, nLen) == OGRERR_NOT_ENOUGH_MEMORY )
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
         pThis->m_bStopParsing = true;
         XML_StopParser(pThis->m_oParser, XML_FALSE);
-        return;
     }
 }
 
@@ -363,7 +357,7 @@ void XMLCALL GMLExpatHandler::dataHandlerCbk(void *pUserData, const char *data,
 
 const char* GMLExpatHandler::GetFID(void* attr)
 {
-    const char** papszIter = (const char** )attr;
+    const char** papszIter = (const char**)attr;
     while(*papszIter)
     {
         if (strcmp(*papszIter, "fid") == 0 ||
@@ -382,13 +376,14 @@ const char* GMLExpatHandler::GetFID(void* attr)
 
 CPLXMLNode* GMLExpatHandler::AddAttributes(CPLXMLNode* psNode, void* attr)
 {
-    const char** papszIter = (const char** )attr;
+    const char** papszIter = static_cast<const char **>(attr);
 
     CPLXMLNode* psLastChild = NULL;
 
     while(*papszIter)
     {
-        CPLXMLNode* psChild = CPLCreateXMLNode(NULL, CXT_Attribute, papszIter[0]);
+        CPLXMLNode* psChild =
+            CPLCreateXMLNode(NULL, CXT_Attribute, papszIter[0]);
         CPLCreateXMLNode(psChild, CXT_Text, papszIter[1]);
 
         if (psLastChild == NULL)
@@ -407,7 +402,8 @@ CPLXMLNode* GMLExpatHandler::AddAttributes(CPLXMLNode* psNode, void* attr)
 /*                    GetAttributeValue()                               */
 /************************************************************************/
 
-char* GMLExpatHandler::GetAttributeValue(void* attr, const char* pszAttributeName)
+char *
+GMLExpatHandler::GetAttributeValue(void* attr, const char* pszAttributeName)
 {
     const char** papszIter = (const char** )attr;
     while(*papszIter)
@@ -425,9 +421,10 @@ char* GMLExpatHandler::GetAttributeValue(void* attr, const char* pszAttributeNam
 /*                    GetAttributeByIdx()                               */
 /************************************************************************/
 
-/* CAUTION: should be called with increasing idx starting from 0 and */
-/* no attempt to read beyond end of list */
-char* GMLExpatHandler::GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey)
+// CAUTION: should be called with increasing idx starting from 0 and
+// no attempt to read beyond end of list.
+char *
+GMLExpatHandler::GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey)
 {
     const char** papszIter = (const char** )attr;
     if( papszIter[2 * idx] == NULL )
@@ -441,7 +438,6 @@ char* GMLExpatHandler::GetAttributeByIdx(void* attr, unsigned int idx, char** pp
 
 #endif
 
-
 static const char* const apszGMLGeometryElements[] =
 {
     "BoundingBox", /* ows:BoundingBox */
@@ -459,18 +455,23 @@ static const char* const apszGMLGeometryElements[] =
     "Point",
     "Polygon",
     "PolygonPatch",
+    "PolyhedralSurface",
     "SimplePolygon", /* GML 3.3 compact encoding */
     "SimpleRectangle", /* GML 3.3 compact encoding */
     "SimpleTriangle", /* GML 3.3 compact encoding */
     "SimpleMultiPoint", /* GML 3.3 compact encoding */
     "Solid",
     "Surface",
+    "Tin",
     "TopoCurve",
-    "TopoSurface"
+    "TopoSurface",
+    "Triangle",
+    "TriangulatedSurface"
 };
 
-#define GML_GEOMETRY_TYPE_COUNT  \
-    (int)(sizeof(apszGMLGeometryElements) / sizeof(apszGMLGeometryElements[0]))
+#define GML_GEOMETRY_TYPE_COUNT \
+    static_cast<int>(sizeof(apszGMLGeometryElements) / \
+                     sizeof(apszGMLGeometryElements[0]))
 
 struct _GeometryNamesStruct {
     unsigned long nHash;
@@ -496,41 +497,38 @@ static int GMLHandlerSortGeometryElements(const void *_pA, const void *_pB)
 /*                            GMLHandler()                              */
 /************************************************************************/
 
-GMLHandler::GMLHandler( GMLReader *poReader )
-
+GMLHandler::GMLHandler( GMLReader *poReader ) :
+    m_pszCurField(NULL),
+    m_nCurFieldAlloc(0),
+    m_nCurFieldLen(0),
+    m_bInCurField(false),
+    m_nAttributeIndex(-1),
+    m_nAttributeDepth(0),
+    m_pszGeometry(NULL),
+    m_nGeomAlloc(0),
+    m_nGeomLen(0),
+    m_nGeometryDepth(0),
+    m_bAlreadyFoundGeometry(false),
+    m_nGeometryPropertyIndex(0),
+    m_nDepth(0),
+    m_nDepthFeature(0),
+    m_inBoundedByDepth(0),
+    m_pszCityGMLGenericAttrName(NULL),
+    m_inCityGMLGenericAttrDepth(0),
+    m_bReportHref(false),
+    m_pszHref(NULL),
+    m_pszUom(NULL),
+    m_pszValue(NULL),
+    m_pszKieli(NULL),
+    pasGeometryNames(static_cast<GeometryNamesStruct *>(CPLMalloc(
+        GML_GEOMETRY_TYPE_COUNT * sizeof(GeometryNamesStruct)))),
+    m_nSRSDimensionIfMissing(atoi(
+        CPLGetConfigOption("GML_SRS_DIMENSION_IF_MISSING", "0") )),
+    m_poReader(poReader),
+    eAppSchemaType(APPSCHEMA_GENERIC),
+    nStackDepth(0)
 {
-    m_poReader = poReader;
-    m_bInCurField = false;
-    m_nCurFieldAlloc = 0;
-    m_nCurFieldLen = 0;
-    m_pszCurField = NULL;
-    m_nAttributeIndex = -1;
-    m_nAttributeDepth = 0;
-
-    m_pszGeometry = NULL;
-    m_nGeomAlloc = 0;
-    m_nGeomLen = 0;
-    m_nGeometryDepth = 0;
-    m_bAlreadyFoundGeometry = false;
-    m_nGeometryPropertyIndex = 0;
-
-    m_nDepthFeature = m_nDepth = 0;
-    m_inBoundedByDepth = 0;
-
-    eAppSchemaType = APPSCHEMA_GENERIC;
-
-    m_pszCityGMLGenericAttrName = NULL;
-    m_inCityGMLGenericAttrDepth = 0;
-
-    m_bReportHref = false;
-    m_pszHref = NULL;
-    m_pszUom = NULL;
-    m_pszValue = NULL;
-    m_pszKieli = NULL;
-
-    pasGeometryNames = (GeometryNamesStruct*)CPLMalloc(
-        GML_GEOMETRY_TYPE_COUNT * sizeof(GeometryNamesStruct));
-    for(int i=0; i<GML_GEOMETRY_TYPE_COUNT; i++)
+    for( int i = 0; i < GML_GEOMETRY_TYPE_COUNT; i++ )
     {
         pasGeometryNames[i].pszName = apszGMLGeometryElements[i];
         pasGeometryNames[i].nHash =
@@ -540,11 +538,7 @@ GMLHandler::GMLHandler( GMLReader *poReader )
           sizeof(GeometryNamesStruct),
           GMLHandlerSortGeometryElements);
 
-    nStackDepth = 0;
     stateStack[0] = STATE_TOP;
-
-    m_nSRSDimensionIfMissing = atoi(
-                    CPLGetConfigOption("GML_SRS_DIMENSION_IF_MISSING", "0") );
 }
 
 /************************************************************************/
@@ -567,7 +561,6 @@ GMLHandler::~GMLHandler()
     CPLFree( pasGeometryNames );
 }
 
-
 /************************************************************************/
 /*                             startElement()                           */
 /************************************************************************/
@@ -635,15 +628,18 @@ OGRErr GMLHandler::dataHandler(const char *data, int nLen)
     }
 }
 
-#define PUSH_STATE(val) do { nStackDepth ++; CPLAssert(nStackDepth < STACK_SIZE); stateStack[nStackDepth] = val; } while(0)
-#define POP_STATE()     nStackDepth --
+#define PUSH_STATE(val) do { \
+    nStackDepth++; \
+    CPLAssert(nStackDepth < STACK_SIZE); \
+    stateStack[nStackDepth] = val; } while( false )
+#define POP_STATE()     nStackDepth--
 
 /************************************************************************/
 /*                       startElementBoundedBy()                        */
 /************************************************************************/
 
 OGRErr GMLHandler::startElementBoundedBy(const char *pszName,
-                                         CPL_UNUSED int nLenName,
+                                         int /*nLenName*/,
                                          void* attr )
 {
     if ( m_nDepth == 2 && strcmp(pszName, "Envelope") == 0 )
@@ -678,7 +674,7 @@ OGRErr GMLHandler::startElementGeometry(const char *pszName, int nLenName, void*
     memcpy(psCurNode->pszValue, pszName, nLenName+1);
 
     /* Attach element as the last child of its parent */
-    NodeLastChild& sNodeLastChild = apsXMLNode[apsXMLNode.size()-1];
+    NodeLastChild& sNodeLastChild = apsXMLNode.back();
     CPLXMLNode* psLastChildParent = sNodeLastChild.psLastChild;
 
     if (psLastChildParent == NULL)
@@ -735,8 +731,8 @@ OGRErr GMLHandler::startElementGeometry(const char *pszName, int nLenName, void*
 /************************************************************************/
 
 OGRErr GMLHandler::startElementCityGMLGenericAttr(const char *pszName,
-                                                  CPL_UNUSED int nLenName,
-                                                  CPL_UNUSED void* attr )
+                                                  int /*nLenName*/,
+                                                  void* /*attr*/ )
 {
     if( strcmp(pszName, "value") == 0 )
     {
@@ -744,7 +740,8 @@ OGRErr GMLHandler::startElementCityGMLGenericAttr(const char *pszName,
         {
             CPLFree(m_pszCurField);
             m_pszCurField = NULL;
-            m_nCurFieldLen = m_nCurFieldAlloc = 0;
+            m_nCurFieldLen = 0;
+            m_nCurFieldAlloc = 0;
         }
         m_bInCurField = true;
     }
@@ -957,7 +954,9 @@ bool GMLHandler::IsConditionMatched(const char* pszCondition, void* attr)
     if( bSyntaxError )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "Invalid condition : %s. Must be of the form @attrname[!]='attrvalue' [and|or other_cond]*. 'and' and 'or' operators cannot be mixed",
+                 "Invalid condition : %s. Must be of the form "
+                 "@attrname[!]='attrvalue' [and|or other_cond]*. "
+                 "'and' and 'or' operators cannot be mixed",
                  pszCondition);
         return false;
     }
@@ -965,8 +964,9 @@ bool GMLHandler::IsConditionMatched(const char* pszCondition, void* attr)
     char* pszVal = GetAttributeValue(attr, osCondAttr);
     if( pszVal == NULL )
         pszVal = CPLStrdup("");
-    bool bCondMet = ((bOpEqual && strcmp(pszVal, osCondVal) == 0 ) ||
-                    (!bOpEqual && strcmp(pszVal, osCondVal) != 0 ));
+    const bool bCondMet =
+        (bOpEqual && strcmp(pszVal, osCondVal) == 0) ||
+        (!bOpEqual && strcmp(pszVal, osCondVal) != 0);
     CPLFree(pszVal);
     if( *pszIter == '\0' )
         return bCondMet;
@@ -1124,7 +1124,7 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
         {
             m_nGeometryDepth = m_nDepth;
 
-            CPLAssert(apsXMLNode.size() == 0);
+            CPLAssert(apsXMLNode.empty());
 
             NodeLastChild sNodeLastChild;
             sNodeLastChild.psNode = NULL;
@@ -1136,8 +1136,6 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
             return startElementGeometry(pszName, nLenName, attr);
         }
     }
-
-
     else if( nLenName == 9 && strcmp(pszName, "boundedBy") == 0 )
     {
         m_inBoundedByDepth = m_nDepth;
@@ -1207,11 +1205,23 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
                 {
                     CPLFree(m_pszCurField);
                     m_pszCurField = NULL;
-                    m_nCurFieldLen = m_nCurFieldAlloc = 0;
+                    m_nCurFieldLen = 0;
+                    m_nCurFieldAlloc = 0;
                 }
                 m_bInCurField = true;
 
-                DealWithAttributes(pszName, nLenName, attr);
+                char* pszXSINil = GetAttributeValue( attr, "xsi:nil" );
+                if( pszXSINil )
+                {
+                    if( EQUAL(pszXSINil, "true") )
+                        m_poReader->SetFeaturePropertyDirectly(pszName,
+                                        CPLStrdup(OGR_GML_NULL), -1 );
+                    CPLFree(pszXSINil);
+                }
+                else
+                {
+                    DealWithAttributes(pszName, nLenName, attr);
+                }
 
                 if (stateStack[nStackDepth] != STATE_PROPERTY)
                 {
@@ -1224,7 +1234,6 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
                 DealWithAttributes(pszName, nLenName, attr);
             }*/
         }
-
     }
     else
     {
@@ -1241,7 +1250,7 @@ OGRErr GMLHandler::startElementFeatureAttribute(const char *pszName, int nLenNam
 /************************************************************************/
 
 OGRErr GMLHandler::startElementTop(const char *pszName,
-                                   CPL_UNUSED int nLenName,
+                                   int /*nLenName*/,
                                    void* attr )
 {
     if (strcmp(pszName, "CityModel") == 0 )
@@ -1282,8 +1291,8 @@ OGRErr GMLHandler::startElementDefault(const char *pszName, int nLenName, void*
 /* -------------------------------------------------------------------- */
 /*      Is it a feature?  If so push a whole new state, and return.     */
 /* -------------------------------------------------------------------- */
-    int nClassIndex;
-    const char* pszFilteredClassName;
+    int nClassIndex = 0;
+    const char* pszFilteredClassName = NULL;
 
     if( nLenName == 9 && strcmp(pszName, "boundedBy") == 0 )
     {
@@ -1416,15 +1425,14 @@ CPLXMLNode* GMLHandler::ParseAIXMElevationPoint(CPLXMLNode *psGML)
             CPLGetXMLValue( psGML, "geoidUndulation.uom", NULL );
         if (pszGeoidUndulationUnit)
         {
-            m_poReader->SetFeaturePropertyDirectly( "geoidUndulation_uom",
-                                            CPLStrdup(pszGeoidUndulationUnit), -1 );
+            m_poReader->SetFeaturePropertyDirectly(
+                "geoidUndulation_uom",
+                CPLStrdup(pszGeoidUndulationUnit), -1 );
         }
     }
 
-    const char* pszPos =
-                    CPLGetXMLValue( psGML, "pos", NULL );
-    const char* pszCoordinates =
-                CPLGetXMLValue( psGML, "coordinates", NULL );
+    const char* pszPos = CPLGetXMLValue( psGML, "pos", NULL );
+    const char* pszCoordinates = CPLGetXMLValue( psGML, "coordinates", NULL );
     if (pszPos != NULL)
     {
         char* pszGeometry = CPLStrdup(CPLSPrintf(
@@ -1464,7 +1472,7 @@ OGRErr GMLHandler::endElementGeometry()
         psNode->eType = CXT_Text;
         psNode->pszValue = m_pszGeometry;
 
-        NodeLastChild& sNodeLastChild = apsXMLNode[apsXMLNode.size()-1];
+        NodeLastChild& sNodeLastChild = apsXMLNode.back();
         CPLXMLNode* psLastChildParent = sNodeLastChild.psLastChild;
         if (psLastChildParent == NULL)
         {
@@ -1483,7 +1491,7 @@ OGRErr GMLHandler::endElementGeometry()
 
     if( m_nDepth == m_nGeometryDepth )
     {
-        CPLXMLNode* psInterestNode = apsXMLNode[apsXMLNode.size()-1].psNode;
+        CPLXMLNode* psInterestNode = apsXMLNode.back().psNode;
 
         /*char* pszXML = CPLSerializeXMLTree(psInterestNode);
         CPLDebug("GML", "geometry = %s", pszXML);
@@ -1576,7 +1584,8 @@ OGRErr GMLHandler::endElementCityGMLGenericAttr()
                                             m_pszCurField, -1 );
         }
         m_pszCurField = NULL;
-        m_nCurFieldLen = m_nCurFieldAlloc = 0;
+        m_nCurFieldLen = 0;
+        m_nCurFieldAlloc = 0;
         m_bInCurField = false;
         CPLFree(m_pszCityGMLGenericAttrName);
         m_pszCityGMLGenericAttrName = NULL;
@@ -1638,7 +1647,8 @@ OGRErr GMLHandler::endElementAttribute()
             m_pszKieli = NULL;
         }
 
-        m_nCurFieldLen = m_nCurFieldAlloc = 0;
+        m_nCurFieldLen = 0;
+        m_nCurFieldAlloc = 0;
         m_bInCurField = false;
         m_nAttributeIndex = -1;
 
@@ -1660,8 +1670,8 @@ OGRErr GMLHandler::endElementAttribute()
 /*                    startElementFeatureProperty()                     */
 /************************************************************************/
 
-OGRErr GMLHandler::startElementFeatureProperty(CPL_UNUSED const char *pszName,
-                                               CPL_UNUSED int nLenName,
+OGRErr GMLHandler::startElementFeatureProperty(const char * /*pszName*/,
+                                               int /*nLenName*/,
                                                void* attr )
 {
     if (m_nDepth == m_nAttributeDepth + 1)
@@ -1744,48 +1754,48 @@ OGRErr GMLHandler::endElementDefault()
 OGRErr GMLHandler::dataHandlerAttribute(const char *data, int nLen)
 
 {
+    if( !m_bInCurField )
+        return OGRERR_NONE;
+
     int nIter = 0;
 
-    if( m_bInCurField )
+    // Ignore white space.
+    if (m_nCurFieldLen == 0)
     {
-        // Ignore white space
-        if (m_nCurFieldLen == 0)
+        while (nIter < nLen)
         {
-            while (nIter < nLen)
-            {
-                char ch = data[nIter];
-                if( !(ch == ' ' || ch == 10 || ch == 13 || ch == '\t') )
-                    break;
-                nIter ++;
-            }
+            const char ch = data[nIter];
+            if( !(ch == ' ' || ch == 10 || ch == 13 || ch == '\t') )
+                break;
+            nIter++;
         }
+    }
 
-        int nCharsLen = nLen - nIter;
+    const int nCharsLen = nLen - nIter;
 
-        if( nCharsLen > INT_MAX - static_cast<int>(m_nCurFieldLen) - 1 )
+    if( nCharsLen > INT_MAX - static_cast<int>(m_nCurFieldLen) - 1 )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Too much data in a single element");
+        return OGRERR_NOT_ENOUGH_MEMORY;
+    }
+    if (m_nCurFieldLen + nCharsLen + 1 > m_nCurFieldAlloc)
+    {
+        if( m_nCurFieldAlloc < INT_MAX - m_nCurFieldAlloc / 3 - nCharsLen - 1 )
+            m_nCurFieldAlloc = m_nCurFieldAlloc + m_nCurFieldAlloc / 3 + nCharsLen + 1;
+        else
+            m_nCurFieldAlloc = m_nCurFieldLen + nCharsLen + 1;
+        char *pszNewCurField = static_cast<char *>(
+            VSI_REALLOC_VERBOSE(m_pszCurField, m_nCurFieldAlloc));
+        if (pszNewCurField == NULL)
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                    "Too much data in a single element");
             return OGRERR_NOT_ENOUGH_MEMORY;
         }
-        if (m_nCurFieldLen + nCharsLen + 1 > m_nCurFieldAlloc)
-        {
-            if( m_nCurFieldAlloc < INT_MAX - m_nCurFieldAlloc / 3 - nCharsLen - 1 )
-                m_nCurFieldAlloc = m_nCurFieldAlloc + m_nCurFieldAlloc / 3 + nCharsLen + 1;
-            else
-                m_nCurFieldAlloc = m_nCurFieldLen + nCharsLen + 1;
-            char *pszNewCurField = (char *)
-                VSI_REALLOC_VERBOSE( m_pszCurField, m_nCurFieldAlloc );
-            if (pszNewCurField == NULL)
-            {
-                return OGRERR_NOT_ENOUGH_MEMORY;
-            }
-            m_pszCurField = pszNewCurField;
-        }
-        memcpy( m_pszCurField + m_nCurFieldLen, data + nIter, nCharsLen);
-        m_nCurFieldLen += nCharsLen;
-        m_pszCurField[m_nCurFieldLen] = '\0';
+        m_pszCurField = pszNewCurField;
     }
+    memcpy(m_pszCurField + m_nCurFieldLen, data + nIter, nCharsLen);
+    m_nCurFieldLen += nCharsLen;
+    m_pszCurField[m_nCurFieldLen] = '\0';
 
     return OGRERR_NONE;
 }
@@ -1807,11 +1817,11 @@ OGRErr GMLHandler::dataHandlerGeometry(const char *data, int nLen)
             char ch = data[nIter];
             if( !(ch == ' ' || ch == 10 || ch == 13 || ch == '\t') )
                 break;
-            nIter ++;
+            nIter++;
         }
     }
 
-    int nCharsLen = nLen - nIter;
+    const int nCharsLen = nLen - nIter;
     if (nCharsLen)
     {
         if( nCharsLen > INT_MAX - static_cast<int>(m_nGeomLen) - 1 )
@@ -1826,15 +1836,15 @@ OGRErr GMLHandler::dataHandlerGeometry(const char *data, int nLen)
                 m_nGeomAlloc = m_nGeomAlloc + m_nGeomAlloc / 3 + nCharsLen + 1;
             else
                 m_nGeomAlloc = m_nGeomAlloc + nCharsLen + 1;
-            char* pszNewGeometry = (char *)
-                VSI_REALLOC_VERBOSE( m_pszGeometry, m_nGeomAlloc);
+            char* pszNewGeometry = static_cast<char *>(
+                VSI_REALLOC_VERBOSE( m_pszGeometry, m_nGeomAlloc));
             if (pszNewGeometry == NULL)
             {
                 return OGRERR_NOT_ENOUGH_MEMORY;
             }
             m_pszGeometry = pszNewGeometry;
         }
-        memcpy( m_pszGeometry+m_nGeomLen, data + nIter, nCharsLen);
+        memcpy(m_pszGeometry+m_nGeomLen, data + nIter, nCharsLen);
         m_nGeomLen += nCharsLen;
         m_pszGeometry[m_nGeomLen] = '\0';
     }
@@ -1842,7 +1852,6 @@ OGRErr GMLHandler::dataHandlerGeometry(const char *data, int nLen)
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                         IsGeometryElement()                          */
 /************************************************************************/
@@ -1855,7 +1864,7 @@ bool GMLHandler::IsGeometryElement( const char *pszElement )
     unsigned long nHash = CPLHashSetHashStr(pszElement);
     do
     {
-        int nMiddle = (nFirst + nLast) / 2;
+        const int nMiddle = (nFirst + nLast) / 2;
         if (nHash == pasGeometryNames[nMiddle].nHash)
             return strcmp(pszElement, pasGeometryNames[nMiddle].pszName) == 0;
         if (nHash < pasGeometryNames[nMiddle].nHash)
diff --git a/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp b/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
index e55a480..1a97cc6 100644
--- a/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlpropertydefn.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: gmlpropertydefn.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLPropertyDefn
@@ -28,35 +27,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlreader.h"
+
+#include <cstring>
+
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
+CPL_CVSID("$Id: gmlpropertydefn.cpp 37472 2017-02-26 02:47:45Z goatbar $");
+
 /************************************************************************/
 /*                           GMLPropertyDefn                            */
 /************************************************************************/
 
 GMLPropertyDefn::GMLPropertyDefn( const char *pszName,
-                                  const char *pszSrcElement )
-
-{
-    m_pszName = CPLStrdup( pszName );
-    if( pszSrcElement != NULL )
-    {
-        m_nSrcElementLen = strlen( pszSrcElement );
-        m_pszSrcElement = CPLStrdup( pszSrcElement );
-    }
-    else
-    {
-        m_nSrcElementLen = 0;
-        m_pszSrcElement = NULL;
-    }
-    m_eType = GMLPT_Untyped;
-    m_nWidth = 0;
-    m_nPrecision = 0;
-    m_pszCondition = NULL;
-    m_bNullable = true;
-}
+                                  const char *pszSrcElement ) :
+    m_pszName(CPLStrdup(pszName)),
+    m_eType(GMLPT_Untyped),
+    m_nWidth(0),
+    m_nPrecision(0),
+    m_pszSrcElement(pszSrcElement ? CPLStrdup(pszSrcElement) : NULL),
+    m_nSrcElementLen(pszSrcElement ? strlen(pszSrcElement) : 0),
+    m_pszCondition(NULL),
+    m_bNullable(true)
+{}
 
 /************************************************************************/
 /*                          ~GMLPropertyDefn()                          */
@@ -77,11 +72,11 @@ GMLPropertyDefn::~GMLPropertyDefn()
 void GMLPropertyDefn::SetSrcElement( const char *pszSrcElement )
 
 {
-    CPLFree( m_pszSrcElement );
+    CPLFree(m_pszSrcElement);
     if( pszSrcElement != NULL )
     {
-        m_nSrcElementLen = strlen( pszSrcElement );
-        m_pszSrcElement = CPLStrdup( pszSrcElement );
+        m_nSrcElementLen = strlen(pszSrcElement);
+        m_pszSrcElement = CPLStrdup(pszSrcElement);
     }
     else
     {
@@ -96,8 +91,8 @@ void GMLPropertyDefn::SetSrcElement( const char *pszSrcElement )
 
 void GMLPropertyDefn::SetCondition( const char *pszCondition )
 {
-    CPLFree( m_pszCondition );
-    m_pszCondition = ( pszCondition != NULL ) ? CPLStrdup(pszCondition) : NULL;
+    CPLFree(m_pszCondition);
+    m_pszCondition = pszCondition != NULL ? CPLStrdup(pszCondition) : NULL;
 }
 
 /************************************************************************/
@@ -107,7 +102,7 @@ void GMLPropertyDefn::SetCondition( const char *pszCondition )
 /*      make the field type more specific, or more general.             */
 /************************************************************************/
 
-void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
+void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty *psGMLProperty,
                                             bool bSetWidth )
 
 {
@@ -116,16 +111,22 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
 /* -------------------------------------------------------------------- */
     bool bIsReal = false;
 
-    for( int j=0; j < psGMLProperty->nSubProperties; j++ )
+    for( int j = 0; j < psGMLProperty->nSubProperties; j++ )
     {
         if (j > 0)
         {
             if( m_eType == GMLPT_Integer )
+            {
                 m_eType = GMLPT_IntegerList;
+            }
             else if( m_eType == GMLPT_Integer64 )
+            {
                 m_eType = GMLPT_Integer64List;
+            }
             else if( m_eType == GMLPT_Real )
+            {
                 m_eType = GMLPT_RealList;
+            }
             else if( m_eType == GMLPT_String )
             {
                 m_eType = GMLPT_StringList;
@@ -142,16 +143,18 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
         if( *pszValue == '\0' )
             continue;
 
-        CPLValueType valueType = CPLGetValueType(pszValue);
+        const CPLValueType valueType = CPLGetValueType(pszValue);
 
-        if (valueType == CPL_VALUE_STRING
-            && m_eType != GMLPT_String
-            && m_eType != GMLPT_StringList )
+        if (valueType == CPL_VALUE_STRING &&
+            m_eType != GMLPT_String &&
+            m_eType != GMLPT_StringList )
         {
             if( (m_eType == GMLPT_Untyped || m_eType == GMLPT_Boolean) &&
                 (strcmp(pszValue, "true") == 0 ||
                  strcmp(pszValue, "false") == 0) )
+            {
                 m_eType = GMLPT_Boolean;
+            }
             else if( m_eType == GMLPT_BooleanList )
             {
                 if( !(strcmp(pszValue, "true") == 0 ||
@@ -161,22 +164,27 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
             else if( m_eType == GMLPT_IntegerList ||
                      m_eType == GMLPT_Integer64List ||
                      m_eType == GMLPT_RealList )
+            {
                 m_eType = GMLPT_StringList;
+            }
             else
+            {
                 m_eType = GMLPT_String;
+            }
         }
         else
-            bIsReal = (valueType == CPL_VALUE_REAL);
+        {
+            bIsReal = valueType == CPL_VALUE_REAL;
+        }
 
         if( m_eType == GMLPT_String )
         {
             if( bSetWidth )
             {
-                /* grow the Width to the length of the string passed in */
-                int nWidth;
-                nWidth = static_cast<int>(strlen(pszValue));
+                // Grow the Width to the length of the string passed in.
+                const int nWidth = static_cast<int>(strlen(pszValue));
                 if ( m_nWidth < nWidth )
-                    SetWidth( nWidth );
+                    SetWidth(nWidth);
             }
         }
         else if( m_eType == GMLPT_Untyped || m_eType == GMLPT_Integer ||
@@ -186,7 +194,7 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
                 m_eType = GMLPT_Real;
             else if( m_eType != GMLPT_Integer64 )
             {
-                GIntBig nVal = CPLAtoGIntBig(pszValue);
+                const GIntBig nVal = CPLAtoGIntBig(pszValue);
                 if( !CPL_INT64_FITS_ON_INT32(nVal) )
                     m_eType = GMLPT_Integer64;
                 else
@@ -198,7 +206,8 @@ void GMLPropertyDefn::AnalysePropertyValue( const GMLProperty* psGMLProperty,
         {
             m_eType = GMLPT_RealList;
         }
-        else if( m_eType == GMLPT_IntegerList && valueType == CPL_VALUE_INTEGER )
+        else if( m_eType == GMLPT_IntegerList &&
+                 valueType == CPL_VALUE_INTEGER )
         {
             GIntBig nVal = CPLAtoGIntBig(pszValue);
             if( !CPL_INT64_FITS_ON_INT32(nVal) )
@@ -215,15 +224,14 @@ GMLGeometryPropertyDefn::GMLGeometryPropertyDefn( const char *pszName,
                                                   const char *pszSrcElement,
                                                   int nType,
                                                   int nAttributeIndex,
-                                                  bool bNullable )
-{
-    m_pszName = (pszName == NULL || pszName[0] == '\0') ?
-                        CPLStrdup(pszSrcElement) : CPLStrdup(pszName);
-    m_pszSrcElement = CPLStrdup(pszSrcElement);
-    m_nGeometryType = nType;
-    m_nAttributeIndex = nAttributeIndex;
-    m_bNullable = bNullable;
-}
+                                                  bool bNullable ) :
+    m_pszName((pszName == NULL || pszName[0] == '\0') ?
+              CPLStrdup(pszSrcElement) : CPLStrdup(pszName)),
+    m_pszSrcElement(CPLStrdup(pszSrcElement)),
+    m_nGeometryType(nType),
+    m_nAttributeIndex(nAttributeIndex),
+    m_bNullable(bNullable)
+{}
 
 /************************************************************************/
 /*                       ~GMLGeometryPropertyDefn                       */
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.cpp b/ogr/ogrsf_frmts/gml/gmlreader.cpp
index fa34b47..0181067 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gmlreader.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader class.
@@ -28,29 +27,30 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlreaderp.h"
 #include "gmlreader.h"
+
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <string>
+
+#include "cpl_conv.h"
 #include "cpl_error.h"
+#include "cpl_multiproc.h"
 #include "cpl_string.h"
 #include "gmlutils.h"
-#include "cpl_conv.h"
-#include <map>
-#include "cpl_multiproc.h"
+#include "ogr_geometry.h"
 
-#define SUPPORT_GEOMETRY
-
-#ifdef SUPPORT_GEOMETRY
-#  include "ogr_geometry.h"
-#endif
+CPL_CVSID("$Id: gmlreader.cpp 37914 2017-04-06 17:38:46Z rouault $");
 
 /************************************************************************/
 /*                            ~IGMLReader()                             */
 /************************************************************************/
 
-IGMLReader::~IGMLReader()
-
-{
-}
+IGMLReader::~IGMLReader() {}
 
 /************************************************************************/
 /* ==================================================================== */
@@ -69,9 +69,9 @@ IGMLReader *CreateGMLReader(bool /*bUseExpatParserPreferably*/,
                             GMLSwapCoordinatesEnum /* eSwapCoordinates */,
                             bool /*bGetSecondaryGeometryOption*/)
 {
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "Unable to create Xerces C++ or Expat based GML reader, Xerces or Expat support\n"
-              "not configured into GDAL/OGR." );
+    CPLError(CE_Failure, CPLE_AppDefined,
+             "Unable to create Xerces C++ or Expat based GML reader, Xerces "
+             "or Expat support not configured into GDAL/OGR.");
     return NULL;
 }
 
@@ -102,8 +102,6 @@ IGMLReader *CreateGMLReader(bool bUseExpatParserPreferably,
 
 #endif
 
-OGRGMLXercesState GMLReader::m_eXercesInitState = OGRGML_XERCES_UNINITIALIZED;
-int GMLReader::m_nInstanceCount = 0;
 CPLMutex *GMLReader::hMutex = NULL;
 
 /************************************************************************/
@@ -118,81 +116,72 @@ CPL_UNUSED
                      bool bInvertAxisOrderIfLatLong,
                      bool bConsiderEPSGAsURN,
                      GMLSwapCoordinatesEnum eSwapCoordinates,
-                     bool bGetSecondaryGeometryOption)
+                     bool bGetSecondaryGeometryOption ) :
+    m_bClassListLocked(false),
+    m_nClassCount(0),
+    m_papoClass(NULL),
+    m_bLookForClassAtAnyLevel(false),
+    m_pszFilename(NULL),
+#ifndef HAVE_XERCES
+    bUseExpatReader(true),
+#else
+    bUseExpatReader(false),
+#endif
+    m_poGMLHandler(NULL),
+#ifdef HAVE_XERCES
+    m_poSAXReader(NULL),
+    m_poCompleteFeature(NULL),
+    m_GMLInputSource(NULL),
+    m_bEOF(false),
+    m_bXercesInitialized(false),
+#endif
+#ifdef HAVE_EXPAT
+    oParser(NULL),
+    ppoFeatureTab(NULL),
+    nFeatureTabLength(0),
+    nFeatureTabIndex(0),
+    nFeatureTabAlloc(0),
+    pabyBuf(NULL),
+#endif
+    fpGML(NULL),
+    m_bReadStarted(false),
+    m_poState(NULL),
+    m_poRecycledState(NULL),
+    m_bStopParsing(false),
+    // Experimental. Not publicly advertized. See commented doc in drv_gml.html
+    m_bFetchAllGeometries(
+        CPLTestBool(CPLGetConfigOption("GML_FETCH_ALL_GEOMETRIES", "NO"))),
+    m_bInvertAxisOrderIfLatLong(bInvertAxisOrderIfLatLong),
+    m_bConsiderEPSGAsURN(bConsiderEPSGAsURN),
+    m_eSwapCoordinates(eSwapCoordinates),
+    m_bGetSecondaryGeometryOption(bGetSecondaryGeometryOption),
+    m_pszGlobalSRSName(NULL),
+    m_bCanUseGlobalSRSName(false),
+    m_pszFilteredClassName(NULL),
+    m_nFilteredClassIndex(-1),
+    m_nHasSequentialLayers(-1),
+    // Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer(),
+    // and GMLReader::GMLReader().
+    m_bFaceHoleNegative(CPLTestBool(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"))),
+    m_bSetWidthFlag(true),
+    m_bReportAllAttributes(false),
+    m_bIsWFSJointLayer(false),
+    m_bEmptyAsNull(true)
 {
 #ifndef HAVE_XERCES
-    bUseExpatReader = true;
 #else
-    bUseExpatReader = false;
 #ifdef HAVE_EXPAT
-    if(bUseExpatParserPreferably)
+    if( bUseExpatParserPreferably )
         bUseExpatReader = true;
 #endif
 #endif
 
 #if defined(HAVE_EXPAT) && defined(HAVE_XERCES)
-    if (bUseExpatReader)
+    if( bUseExpatReader )
         CPLDebug("GML", "Using Expat reader");
     else
         CPLDebug("GML", "Using Xerces reader");
 #endif
-
-    m_nClassCount = 0;
-    m_papoClass = NULL;
-    m_bLookForClassAtAnyLevel = false;
-
-    m_bClassListLocked = false;
-
-    m_poGMLHandler = NULL;
-#ifdef HAVE_XERCES
-    m_poSAXReader = NULL;
-    m_poCompleteFeature = NULL;
-    m_GMLInputSource = NULL;
-    m_bEOF = false;
-#endif
-#ifdef HAVE_EXPAT
-    oParser = NULL;
-    ppoFeatureTab = NULL;
-    nFeatureTabIndex = 0;
-    nFeatureTabLength = 0;
-    nFeatureTabAlloc = 0;
-    pabyBuf = NULL;
-#endif
-    fpGML = NULL;
-    m_bReadStarted = false;
-
-    m_poState = NULL;
-    m_poRecycledState = NULL;
-
-    m_pszFilename = NULL;
-
-    m_bStopParsing = false;
-
-    /* A bit experimental. Not publicly advertized. See commented doc in drv_gml.html */
-    m_bFetchAllGeometries = CPLTestBool(CPLGetConfigOption("GML_FETCH_ALL_GEOMETRIES", "NO"));
-
-    m_bInvertAxisOrderIfLatLong = bInvertAxisOrderIfLatLong;
-    m_bConsiderEPSGAsURN = bConsiderEPSGAsURN;
-    m_eSwapCoordinates = eSwapCoordinates;
-    m_bGetSecondaryGeometryOption = bGetSecondaryGeometryOption;
-
-    m_pszGlobalSRSName = NULL;
-    m_bCanUseGlobalSRSName = false;
-
-    m_pszFilteredClassName = NULL;
-    m_nFilteredClassIndex = -1;
-
-    m_nHasSequentialLayers = -1;
-
-    /* Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer() and GMLReader::GMLReader() */
-    m_bFaceHoleNegative = CPLTestBool(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
-
-    m_bSetWidthFlag = true;
-
-    m_bReportAllAttributes = false;
-
-    m_bIsWFSJointLayer = false;
-    m_bEmptyAsNull = true;
 }
 
 /************************************************************************/
@@ -204,22 +193,15 @@ GMLReader::~GMLReader()
 {
     ClearClasses();
 
-    CPLFree( m_pszFilename );
+    CPLFree(m_pszFilename);
 
     CleanupParser();
 
     delete m_poRecycledState;
 
 #ifdef HAVE_XERCES
-    {
-    CPLMutexHolderD(&hMutex);
-    --m_nInstanceCount;
-    if( m_nInstanceCount == 0 && m_eXercesInitState == OGRGML_XERCES_INIT_SUCCESSFUL )
-    {
-        XMLPlatformUtils::Terminate();
-        m_eXercesInitState = OGRGML_XERCES_UNINITIALIZED;
-    }
-    }
+    if( m_bXercesInitialized )
+        OGRDeinitializeXerces();
 #endif
 #ifdef HAVE_EXPAT
     CPLFree(pabyBuf);
@@ -241,28 +223,21 @@ GMLReader::~GMLReader()
 void GMLReader::SetSourceFile( const char *pszFilename )
 
 {
-    CPLFree( m_pszFilename );
-    m_pszFilename = CPLStrdup( pszFilename );
+    CPLFree(m_pszFilename);
+    m_pszFilename = CPLStrdup(pszFilename);
 }
 
 /************************************************************************/
 /*                       GetSourceFileName()                           */
 /************************************************************************/
 
-const char* GMLReader::GetSourceFileName()
-
-{
-    return m_pszFilename;
-}
+const char *GMLReader::GetSourceFileName() { return m_pszFilename; }
 
 /************************************************************************/
 /*                               SetFP()                                */
 /************************************************************************/
 
-void GMLReader::SetFP( VSILFILE* fp )
-{
-    fpGML = fp;
-}
+void GMLReader::SetFP(VSILFILE *fp) { fpGML = fp; }
 
 /************************************************************************/
 /*                            SetupParser()                             */
@@ -274,7 +249,7 @@ bool GMLReader::SetupParser()
     if (fpGML == NULL)
         fpGML = VSIFOpenL(m_pszFilename, "rt");
     if (fpGML != NULL)
-        VSIFSeekL( fpGML, 0, SEEK_SET );
+        VSIFSeekL(fpGML, 0, SEEK_SET);
 
     int bRet = -1;
 #ifdef HAVE_EXPAT
@@ -288,8 +263,8 @@ bool GMLReader::SetupParser()
 #endif
     if (bRet < 0)
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "SetupParser(): should not happen");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "SetupParser(): should not happen");
         return false;
     }
 
@@ -299,7 +274,7 @@ bool GMLReader::SetupParser()
     m_bReadStarted = false;
 
     // Push an empty state.
-    PushState( m_poRecycledState ? m_poRecycledState : new GMLReadState() );
+    PushState(m_poRecycledState ? m_poRecycledState : new GMLReadState());
     m_poRecycledState = NULL;
 
     return true;
@@ -312,28 +287,11 @@ bool GMLReader::SetupParser()
 
 bool GMLReader::SetupParserXerces()
 {
+    if( !m_bXercesInitialized )
     {
-    CPLMutexHolderD(&hMutex);
-    m_nInstanceCount++;
-    if( m_eXercesInitState == OGRGML_XERCES_UNINITIALIZED )
-    {
-        try
-        {
-            XMLPlatformUtils::Initialize();
-        }
-
-        catch (const XMLException& toCatch)
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Exception initializing Xerces based GML reader.\n%s",
-                      tr_strdup(toCatch.getMessage()) );
-            m_eXercesInitState = OGRGML_XERCES_INIT_FAILED;
+        if( !OGRInitializeXerces() )
             return false;
-        }
-        m_eXercesInitState = OGRGML_XERCES_INIT_SUCCESSFUL;
-    }
-    if( m_eXercesInitState != OGRGML_XERCES_INIT_SUCCESSFUL )
-        return false;
+        m_bXercesInitialized = true;
     }
 
     // Cleanup any old parser.
@@ -341,53 +299,52 @@ bool GMLReader::SetupParserXerces()
         CleanupParser();
 
     // Create and initialize parser.
-    XMLCh* xmlUriValid = NULL;
-    XMLCh* xmlUriNS = NULL;
+    XMLCh *xmlUriValid = NULL;
+    XMLCh *xmlUriNS = NULL;
 
-    try{
+    try
+    {
         m_poSAXReader = XMLReaderFactory::createXMLReader();
 
-        GMLXercesHandler* poXercesHandler = new GMLXercesHandler( this );
+        GMLXercesHandler *poXercesHandler = new GMLXercesHandler(this);
         m_poGMLHandler = poXercesHandler;
 
-        m_poSAXReader->setContentHandler( poXercesHandler );
-        m_poSAXReader->setErrorHandler( poXercesHandler );
-        m_poSAXReader->setLexicalHandler( poXercesHandler );
-        m_poSAXReader->setEntityResolver( poXercesHandler );
-        m_poSAXReader->setDTDHandler( poXercesHandler );
+        m_poSAXReader->setContentHandler(poXercesHandler);
+        m_poSAXReader->setErrorHandler(poXercesHandler);
+        m_poSAXReader->setLexicalHandler(poXercesHandler);
+        m_poSAXReader->setEntityResolver(poXercesHandler);
+        m_poSAXReader->setDTDHandler(poXercesHandler);
 
-        xmlUriValid = XMLString::transcode("http://xml.org/sax/features/validation");
-        xmlUriNS = XMLString::transcode("http://xml.org/sax/features/namespaces");
+        xmlUriValid =
+            XMLString::transcode("http://xml.org/sax/features/validation");
+        xmlUriNS =
+            XMLString::transcode("http://xml.org/sax/features/namespaces");
 
 #if (OGR_GML_VALIDATION)
-        m_poSAXReader->setFeature( xmlUriValid, true);
-        m_poSAXReader->setFeature( xmlUriNS, true);
+        m_poSAXReader->setFeature(xmlUriValid, true);
+        m_poSAXReader->setFeature(xmlUriNS, true);
 
-        m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, true );
-        m_poSAXReader->setFeature( XMLUni::fgXercesSchema, true );
+        m_poSAXReader->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
+        m_poSAXReader->setFeature(XMLUni::fgXercesSchema, true);
 
-//    m_poSAXReader->setDoSchema(true);
-//    m_poSAXReader->setValidationSchemaFullChecking(true);
+        // m_poSAXReader->setDoSchema(true);
+        // m_poSAXReader->setValidationSchemaFullChecking(true);
 #else
-        m_poSAXReader->setFeature( XMLUni::fgSAX2CoreValidation, false);
+        m_poSAXReader->setFeature(XMLUni::fgSAX2CoreValidation, false);
 
-#if XERCES_VERSION_MAJOR >= 3
-        m_poSAXReader->setFeature( XMLUni::fgXercesSchema, false);
-#else
-        m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, false);
-#endif
+        m_poSAXReader->setFeature(XMLUni::fgXercesSchema, false);
 
 #endif
-        XMLString::release( &xmlUriValid );
-        XMLString::release( &xmlUriNS );
+        XMLString::release(&xmlUriValid);
+        XMLString::release(&xmlUriNS);
     }
     catch (...)
     {
-        XMLString::release( &xmlUriValid );
-        XMLString::release( &xmlUriNS );
+        XMLString::release(&xmlUriValid);
+        XMLString::release(&xmlUriNS);
 
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Exception initializing Xerces based GML reader.\n" );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Exception initializing Xerces based GML reader.\n");
         return false;
     }
 
@@ -410,14 +367,15 @@ bool GMLReader::SetupParserExpat()
         CleanupParser();
 
     oParser = OGRCreateExpatXMLParser();
-    m_poGMLHandler = new GMLExpatHandler( this, oParser );
+    m_poGMLHandler = new GMLExpatHandler(this, oParser);
 
-    XML_SetElementHandler(oParser, GMLExpatHandler::startElementCbk, GMLExpatHandler::endElementCbk);
+    XML_SetElementHandler(oParser, GMLExpatHandler::startElementCbk,
+                          GMLExpatHandler::endElementCbk);
     XML_SetCharacterDataHandler(oParser, GMLExpatHandler::dataHandlerCbk);
     XML_SetUserData(oParser, m_poGMLHandler);
 
     if (pabyBuf == NULL)
-        pabyBuf = (char*)VSI_MALLOC_VERBOSE(PARSER_BUF_SIZE);
+        pabyBuf = static_cast<char *>(VSI_MALLOC_VERBOSE(PARSER_BUF_SIZE));
     if (pabyBuf == NULL)
         return false;
 
@@ -460,7 +418,7 @@ void GMLReader::CleanupParser()
         XML_ParserFree(oParser);
     oParser = NULL;
 
-    for( int i=nFeatureTabIndex; i < nFeatureTabLength; i++ )
+    for( int i = nFeatureTabIndex; i < nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
     nFeatureTabIndex = 0;
@@ -478,17 +436,13 @@ void GMLReader::CleanupParser()
 
 #ifdef HAVE_XERCES
 
-GMLBinInputStream::GMLBinInputStream(VSILFILE* fpIn)
-{
-    this->fp = fpIn;
-    emptyString = 0;
-}
+GMLBinInputStream::GMLBinInputStream(VSILFILE *fpIn) :
+    fp(fpIn),
+    emptyString(0)
+{}
 
-GMLBinInputStream::~ GMLBinInputStream()
-{
-}
+GMLBinInputStream::~GMLBinInputStream() {}
 
-#if XERCES_VERSION_MAJOR >= 3
 XMLFilePos GMLBinInputStream::curPos() const
 {
     return (XMLFilePos)VSIFTellL(fp);
@@ -499,37 +453,18 @@ XMLSize_t GMLBinInputStream::readBytes(XMLByte* const toFill, const XMLSize_t ma
     return (XMLSize_t)VSIFReadL(toFill, 1, maxToRead, fp);
 }
 
-const XMLCh* GMLBinInputStream::getContentType() const
-{
-    return &emptyString;
-}
-#else
-unsigned int GMLBinInputStream::curPos() const
-{
-    return (unsigned int)VSIFTellL(fp);
-}
-
-unsigned int GMLBinInputStream::readBytes(XMLByte* const toFill, const unsigned int maxToRead)
-{
-    return (unsigned int)VSIFReadL(toFill, 1, maxToRead, fp);
-}
-#endif
+const XMLCh *GMLBinInputStream::getContentType() const { return &emptyString; }
 
-GMLInputSource::GMLInputSource(VSILFILE* fp, MemoryManager* const manager) : InputSource(manager)
-{
-    binInputStream = new GMLBinInputStream(fp);
-}
+GMLInputSource::GMLInputSource(VSILFILE *fp, MemoryManager *const manager) :
+    InputSource(manager),
+    binInputStream(new GMLBinInputStream(fp))
+{}
 
-GMLInputSource::~GMLInputSource()
-{
-}
+GMLInputSource::~GMLInputSource() {}
 
-BinInputStream* GMLInputSource::makeStream() const
-{
-    return binInputStream;
-}
+BinInputStream *GMLInputSource::makeStream() const { return binInputStream; }
 
-#endif // HAVE_XERCES
+#endif  // HAVE_XERCES
 
 /************************************************************************/
 /*                        NextFeatureXerces()                           */
@@ -569,22 +504,20 @@ GMLFeature *GMLReader::NextFeatureXerces()
 
         poReturn = m_poCompleteFeature;
         m_poCompleteFeature = NULL;
-
     }
-    catch (const XMLException& toCatch)
+    catch (const XMLException &toCatch)
     {
-        char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
-        CPLDebug( "GML",
-                  "Error during NextFeature()! Message:\n%s",
-                  pszErrorMessage );
-        CPLFree(pszErrorMessage);
+        CPLString osErrMsg;
+        transcode(toCatch.getMessage(), osErrMsg);
+        CPLDebug("GML", "Error during NextFeature()! Message:\n%s",
+                 osErrMsg.c_str());
         m_bStopParsing = true;
     }
-    catch (const SAXException& toCatch)
+    catch (const SAXException &toCatch)
     {
-        char *pszErrorMessage = tr_strdup( toCatch.getMessage() );
-        CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrorMessage);
-        CPLFree(pszErrorMessage);
+        CPLString osErrMsg;
+        transcode(toCatch.getMessage(), osErrMsg);
+        CPLError(CE_Failure, CPLE_AppDefined, "%s", osErrMsg.c_str());
         m_bStopParsing = true;
     }
 
@@ -618,21 +551,23 @@ GMLFeature *GMLReader::NextFeatureExpat()
     nFeatureTabLength = 0;
     nFeatureTabIndex = 0;
 
-    int nDone;
+    int nDone = 0;
     do
     {
-        /* Reset counter that is used to detect billion laugh attacks */
-        ((GMLExpatHandler*)m_poGMLHandler)->ResetDataHandlerCounter();
+        // Reset counter that is used to detect billion laugh attacks.
+        static_cast<GMLExpatHandler *>(m_poGMLHandler)->
+            ResetDataHandlerCounter();
 
-        unsigned int nLen =
-                (unsigned int)VSIFReadL( pabyBuf, 1, PARSER_BUF_SIZE, fpGML );
+        unsigned int nLen = static_cast<unsigned int>(
+            VSIFReadL(pabyBuf, 1, PARSER_BUF_SIZE, fpGML));
         nDone = VSIFEofL(fpGML);
 
-        /* Some files, such as APT_AIXM.xml from https://nfdc.faa.gov/webContent/56DaySub/2015-03-05/aixm5.1.zip */
-        /* end with trailing nul characters. This test is not fully bullet-proof in case */
-        /* the nul characters would occur at a buffer boundary */
+        // Some files, such as APT_AIXM.xml from
+        // https://nfdc.faa.gov/webContent/56DaySub/2015-03-05/aixm5.1.zip
+        // end with trailing nul characters. This test is not fully bullet-proof
+        // in case the nul characters would occur at a buffer boundary.
         while( nDone && nLen > 0 && pabyBuf[nLen-1] == '\0' )
-            nLen --;
+            nLen--;
 
         if (XML_Parse(oParser, pabyBuf, nLen, nDone) == XML_STATUS_ERROR)
         {
@@ -645,11 +580,11 @@ GMLFeature *GMLReader::NextFeatureExpat()
             m_bStopParsing = true;
         }
         if (!m_bStopParsing)
-            m_bStopParsing = ((GMLExpatHandler*)m_poGMLHandler)->HasStoppedParsing();
-
+            m_bStopParsing = static_cast<GMLExpatHandler*>(m_poGMLHandler)->
+                HasStoppedParsing();
     } while (!nDone && !m_bStopParsing && nFeatureTabLength == 0);
 
-    return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
+    return nFeatureTabLength ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
 }
 #endif
 
@@ -684,7 +619,7 @@ void GMLReader::PushFeature( const char *pszElement,
                              int nClassIndex )
 
 {
-    int iClass;
+    int iClass = 0;
 
     if( nClassIndex != INT_MAX )
     {
@@ -695,7 +630,7 @@ void GMLReader::PushFeature( const char *pszElement,
     /* -------------------------------------------------------------------- */
     /*      Find the class of this element.                                 */
     /* -------------------------------------------------------------------- */
-        for( iClass = 0; iClass < m_nClassCount; iClass++ )
+        for( ; iClass < m_nClassCount; iClass++ )
         {
             if( EQUAL(pszElement,m_papoClass[iClass]->GetElementName()) )
                 break;
@@ -728,9 +663,8 @@ void GMLReader::PushFeature( const char *pszElement,
 /* -------------------------------------------------------------------- */
 /*      Create and push a new read state.                               */
 /* -------------------------------------------------------------------- */
-    GMLReadState *poState;
-
-    poState = m_poRecycledState ? m_poRecycledState : new GMLReadState();
+    GMLReadState *poState =
+        m_poRecycledState ? m_poRecycledState : new GMLReadState();
     m_poRecycledState = NULL;
     poState->m_poFeature = poFeature;
     PushState( poState );
@@ -743,12 +677,13 @@ void GMLReader::PushFeature( const char *pszElement,
 /*      GML feature element?                                            */
 /************************************************************************/
 
-int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLength,
+int GMLReader::GetFeatureElementIndex( const char *pszElement,
+                                       int nElementLength,
                                        GMLAppSchemaType eAppSchemaType )
 
 {
     const char *pszLast = m_poState->GetLastComponent();
-    size_t      nLenLast = m_poState->GetLastComponentLen();
+    const size_t nLenLast = m_poState->GetLastComponentLen();
 
     if( eAppSchemaType == APPSCHEMA_MTKGML )
     {
@@ -758,16 +693,16 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
     else if( (nLenLast >= 6 && EQUAL(pszLast+nLenLast-6,"member")) ||
         (nLenLast >= 7 && EQUAL(pszLast+nLenLast-7,"members")) )
     {
-        /* Default feature name */
+        // Default feature name.
     }
     else
     {
         if (nLenLast == 4 && strcmp(pszLast, "dane") == 0)
         {
-            /* Polish TBD GML */
+            // Polish TBD GML.
         }
 
-        /* Begin of OpenLS */
+        // Begin of OpenLS.
         else if (nLenLast == 19 && nElementLength == 15 &&
                  strcmp(pszLast, "GeocodeResponseList") == 0 &&
                  strcmp(pszElement, "GeocodedAddress") == 0)
@@ -776,9 +711,9 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
         else if (nLenLast == 22 &&
                  strcmp(pszLast, "DetermineRouteResponse") == 0)
         {
-            /* We don't want the children of RouteInstructionsList */
-            /* to be a single feature. We want each RouteInstruction */
-            /* to be a feature */
+            // We don't want the children of RouteInstructionsList
+            // to be a single feature. We want each RouteInstruction
+            // to be a feature.
             if (strcmp(pszElement, "RouteInstructionsList") == 0)
                 return -1;
         }
@@ -787,15 +722,17 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
                  strcmp(pszLast, "RouteInstructionsList") == 0)
         {
         }
-        /* End of OpenLS */
+        // End of OpenLS.
 
-        else if (nLenLast > 6 && strcmp(pszLast + nLenLast - 6, "_layer") == 0 &&
-                 nElementLength > 8 && strcmp(pszElement + nElementLength - 8, "_feature") == 0)
+        else if (nLenLast > 6 &&
+                 strcmp(pszLast + nLenLast - 6, "_layer") == 0 &&
+                 nElementLength > 8 &&
+                 strcmp(pszElement + nElementLength - 8, "_feature") == 0)
         {
-            /* GML answer of MapServer WMS GetFeatureInfo request */
+            // GML answer of MapServer WMS GetFeatureInfo request.
         }
 
-        /* Begin of CSW SearchResults */
+        // Begin of CSW SearchResults.
         else if (nElementLength == (int)strlen("BriefRecord") &&
                  nLenLast == (int)strlen("SearchResults") &&
                  strcmp(pszElement, "BriefRecord") == 0 &&
@@ -830,8 +767,14 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
                         return i;
                     }
                 }
+                // Give a chance to find a feature class by element name
+                // This is for example needed for
+                // autotest/ogr/data/gml_jpfgd/BldA.xml that has a
+                // feature at a low nesting level.
+            }
+            else {
+                return -1;
             }
-            return -1;
         }
     }
 
@@ -844,7 +787,7 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
     for( int i = 0; i < m_nClassCount; i++ )
     {
         if( nElementLength == (int)m_papoClass[i]->GetElementNameLen() &&
-            memcmp(pszElement,m_papoClass[i]->GetElementName(), nElementLength) == 0 )
+            memcmp(pszElement, m_papoClass[i]->GetElementName(), nElementLength) == 0 )
             return i;
     }
 
@@ -855,7 +798,8 @@ int GMLReader::GetFeatureElementIndex( const char *pszElement, int nElementLengt
 /*                IsCityGMLGenericAttributeElement()                    */
 /************************************************************************/
 
-bool GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void* attr )
+bool GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement,
+                                                  void* attr )
 
 {
     if( strcmp(pszElement, "stringAttribute") != 0 &&
@@ -863,7 +807,7 @@ bool GMLReader::IsCityGMLGenericAttributeElement( const char *pszElement, void*
         strcmp(pszElement, "doubleAttribute") != 0 )
         return false;
 
-    char* pszVal = m_poGMLHandler->GetAttributeValue(attr, "name");
+    char *pszVal = m_poGMLHandler->GetAttributeValue(attr, "name");
     if (pszVal == NULL)
         return false;
 
@@ -974,9 +918,7 @@ void GMLReader::PopState()
         }
 #endif
 
-        GMLReadState *poParent;
-
-        poParent = m_poState->m_poParentState;
+        GMLReadState *poParent = m_poState->m_poParentState;
 
         delete m_poRecycledState;
         m_poRecycledState = m_poState;
@@ -1005,8 +947,8 @@ GMLFeatureClass *GMLReader::GetClass( int iClass ) const
 {
     if( iClass < 0 || iClass >= m_nClassCount )
         return NULL;
-    else
-        return m_papoClass[iClass];
+
+    return m_papoClass[iClass];
 }
 
 /************************************************************************/
@@ -1035,14 +977,14 @@ int GMLReader::AddClass( GMLFeatureClass *poNewClass )
     CPLAssert( GetClass( poNewClass->GetName() ) == NULL );
 
     m_nClassCount++;
-    m_papoClass = (GMLFeatureClass **)
-        CPLRealloc( m_papoClass, sizeof(void*) * m_nClassCount );
+    m_papoClass = static_cast<GMLFeatureClass **>(
+        CPLRealloc(m_papoClass, sizeof(void*) * m_nClassCount));
     m_papoClass[m_nClassCount-1] = poNewClass;
 
     if( poNewClass->HasFeatureProperties() )
         m_bLookForClassAtAnyLevel = true;
 
-    return m_nClassCount-1;
+    return m_nClassCount - 1;
 }
 
 /************************************************************************/
@@ -1054,7 +996,7 @@ void GMLReader::ClearClasses()
 {
     for( int i = 0; i < m_nClassCount; i++ )
         delete m_papoClass[i];
-    CPLFree( m_papoClass );
+    CPLFree(m_papoClass);
 
     m_nClassCount = 0;
     m_papoClass = NULL;
@@ -1077,23 +1019,23 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
 {
     GMLFeature *poFeature = GetState()->m_poFeature;
 
-    CPLAssert( poFeature  != NULL );
+    CPLAssert(poFeature != NULL);
 
 /* -------------------------------------------------------------------- */
 /*      Does this property exist in the feature class?  If not, add     */
 /*      it.                                                             */
 /* -------------------------------------------------------------------- */
     GMLFeatureClass *poClass = poFeature->GetClass();
-    int      iProperty;
+    int iProperty = 0;
 
-    int nPropertyCount = poClass->GetPropertyCount();
+    const int nPropertyCount = poClass->GetPropertyCount();
     if (iPropertyIn >= 0 && iPropertyIn < nPropertyCount)
     {
         iProperty = iPropertyIn;
     }
     else
     {
-        for( iProperty=0; iProperty < nPropertyCount; iProperty++ )
+        for( ; iProperty < nPropertyCount; iProperty++ )
         {
             if( strcmp(poClass->GetProperty( iProperty )->GetSrcElement(),
                     pszElement ) == 0 )
@@ -1104,7 +1046,8 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
         {
             if( poClass->IsSchemaLocked() )
             {
-                CPLDebug("GML","Encountered property missing from class schema : %s.",
+                CPLDebug("GML",
+                         "Encountered property missing from class schema : %s.",
                          pszElement);
                 CPLFree(pszValue);
                 return;
@@ -1114,18 +1057,19 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
 
             if( IsWFSJointLayer() )
             {
-                /* At that point the element path should be member|layer|property */
+                // At that point the element path should be
+                // member|layer|property.
 
-                /* Strip member| prefix. Should always be true normally */
+                // Strip member| prefix. Should always be true normally.
                 if( STARTS_WITH(pszElement, "member|") )
                     osFieldName = pszElement + strlen("member|");
 
-                /* Replace layer|property by layer_property */
+                // Replace layer|property by layer_property.
                 size_t iPos = osFieldName.find('|');
                 if( iPos != std::string::npos )
                     osFieldName[iPos] = '.';
 
-                /* Special case for gml:id on layer */
+                // Special case for gml:id on layer.
                 iPos = osFieldName.find("@id");
                 if( iPos != std::string::npos )
                 {
@@ -1134,7 +1078,9 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
                 }
             }
             else if( strchr(pszElement,'|') == NULL )
+            {
                 osFieldName = pszElement;
+            }
             else
             {
                 osFieldName = strrchr(pszElement,'|') + 1;
@@ -1152,14 +1098,16 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
                 osFieldName += "_";
             }
 
-            GMLPropertyDefn *poPDefn = new GMLPropertyDefn(osFieldName,pszElement);
+            GMLPropertyDefn *poPDefn =
+                new GMLPropertyDefn(osFieldName, pszElement);
 
-            if( EQUAL(CPLGetConfigOption( "GML_FIELDTYPES", ""), "ALWAYS_STRING") )
-                poPDefn->SetType( GMLPT_String );
+            if( EQUAL(CPLGetConfigOption("GML_FIELDTYPES", ""),
+                      "ALWAYS_STRING") )
+                poPDefn->SetType(GMLPT_String);
             else if( eType != GMLPT_Untyped )
                 poPDefn->SetType( eType );
 
-            if (poClass->AddProperty( poPDefn ) < 0)
+            if (poClass->AddProperty(poPDefn) < 0)
             {
                 delete poPDefn;
                 CPLFree(pszValue);
@@ -1179,7 +1127,7 @@ void GMLReader::SetFeaturePropertyDirectly( const char *pszElement,
     if( !poClass->IsSchemaLocked() )
     {
         poClass->GetProperty(iProperty)->AnalysePropertyValue(
-                             poFeature->GetProperty(iProperty), m_bSetWidthFlag );
+            poFeature->GetProperty(iProperty), m_bSetWidthFlag );
     }
 }
 
@@ -1197,111 +1145,100 @@ bool GMLReader::LoadClasses( const char *pszFile )
 /* -------------------------------------------------------------------- */
 /*      Load the raw XML file.                                          */
 /* -------------------------------------------------------------------- */
-    VSILFILE       *fp;
-    int         nLength;
-    char        *pszWholeText;
-
-    fp = VSIFOpenL( pszFile, "rb" );
+    VSILFILE *fp = VSIFOpenL(pszFile, "rb");
 
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to open file %s.", pszFile );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Failed to open file %s.", pszFile);
         return false;
     }
 
-    VSIFSeekL( fp, 0, SEEK_END );
-    nLength = (int) VSIFTellL( fp );
-    VSIFSeekL( fp, 0, SEEK_SET );
+    VSIFSeekL(fp, 0, SEEK_END);
+    int nLength = static_cast<int>(VSIFTellL(fp));
+    VSIFSeekL(fp, 0, SEEK_SET);
 
-    pszWholeText = (char *) VSIMalloc(nLength+1);
+    char *pszWholeText = static_cast<char *>(VSIMalloc(nLength + 1));
     if( pszWholeText == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Failed to allocate %d byte buffer for %s,\n"
-                  "is this really a GMLFeatureClassList file?",
-                  nLength, pszFile );
-        VSIFCloseL( fp );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Failed to allocate %d byte buffer for %s,\n"
+                 "is this really a GMLFeatureClassList file?",
+                 nLength, pszFile);
+        VSIFCloseL(fp);
         return false;
     }
 
     if( VSIFReadL( pszWholeText, nLength, 1, fp ) != 1 )
     {
-        VSIFree( pszWholeText );
-        VSIFCloseL( fp );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Read failed on %s.", pszFile );
+        VSIFree(pszWholeText);
+        VSIFCloseL(fp);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Read failed on %s.", pszFile);
         return false;
     }
     pszWholeText[nLength] = '\0';
 
-    VSIFCloseL( fp );
+    VSIFCloseL(fp);
 
-    if( strstr( pszWholeText, "<GMLFeatureClassList" ) == NULL )
+    if( strstr(pszWholeText, "<GMLFeatureClassList") == NULL )
     {
-        VSIFree( pszWholeText );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "File %s does not contain a GMLFeatureClassList tree.",
-                  pszFile );
+        VSIFree(pszWholeText);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "File %s does not contain a GMLFeatureClassList tree.",
+                 pszFile);
         return false;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Convert to XML parse tree.                                      */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psRoot;
-
-    psRoot = CPLParseXMLString( pszWholeText );
-    VSIFree( pszWholeText );
+    CPLXMLTreeCloser psRoot(CPLParseXMLString(pszWholeText));
+    VSIFree(pszWholeText);
 
     // We assume parser will report errors via CPL.
-    if( psRoot == NULL )
+    if( psRoot.get() == NULL )
         return false;
 
     if( psRoot->eType != CXT_Element
-        || !EQUAL(psRoot->pszValue,"GMLFeatureClassList") )
+        || !EQUAL(psRoot->pszValue, "GMLFeatureClassList") )
     {
-        CPLDestroyXMLNode(psRoot);
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "File %s is not a GMLFeatureClassList document.",
-                  pszFile );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "File %s is not a GMLFeatureClassList document.",
+                 pszFile);
         return false;
     }
 
-    const char* pszSequentialLayers = CPLGetXMLValue(psRoot, "SequentialLayers", NULL);
+    const char* pszSequentialLayers =
+        CPLGetXMLValue(psRoot.get(), "SequentialLayers", NULL);
     if (pszSequentialLayers)
         m_nHasSequentialLayers = CPLTestBool(pszSequentialLayers);
 
 /* -------------------------------------------------------------------- */
 /*      Extract feature classes for all definitions found.              */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psThis;
-
-    for( psThis = psRoot->psChild; psThis != NULL; psThis = psThis->psNext )
+    for( CPLXMLNode *psThis = psRoot->psChild;
+         psThis != NULL;
+         psThis = psThis->psNext )
     {
         if( psThis->eType == CXT_Element
-            && EQUAL(psThis->pszValue,"GMLFeatureClass") )
+            && EQUAL(psThis->pszValue, "GMLFeatureClass") )
         {
-            GMLFeatureClass   *poClass;
-
-            poClass = new GMLFeatureClass();
+            GMLFeatureClass *poClass = new GMLFeatureClass();
 
-            if( !poClass->InitializeFromXML( psThis ) )
+            if( !poClass->InitializeFromXML(psThis) )
             {
                 delete poClass;
-                CPLDestroyXMLNode( psRoot );
                 return false;
             }
 
-            poClass->SetSchemaLocked( true );
+            poClass->SetSchemaLocked(true);
 
-            AddClass( poClass );
+            AddClass(poClass);
         }
     }
 
-    CPLDestroyXMLNode( psRoot );
-
-    SetClassListLocked( true );
+    SetClassListLocked(true);
 
     return true;
 }
@@ -1320,14 +1257,13 @@ bool GMLReader::SaveClasses( const char *pszFile )
 /* -------------------------------------------------------------------- */
 /*      Create in memory schema tree.                                   */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psRoot;
-
-    psRoot = CPLCreateXMLNode( NULL, CXT_Element, "GMLFeatureClassList" );
+    CPLXMLNode *psRoot =
+        CPLCreateXMLNode(NULL, CXT_Element, "GMLFeatureClassList");
 
     if (m_nHasSequentialLayers != -1 && m_nClassCount > 1)
     {
-        CPLCreateXMLElementAndValue( psRoot, "SequentialLayers",
-                                     m_nHasSequentialLayers ? "true" : "false" );
+        CPLCreateXMLElementAndValue(psRoot, "SequentialLayers",
+                                    m_nHasSequentialLayers ? "true" : "false");
     }
 
     for( int iClass = 0; iClass < m_nClassCount; iClass++ )
@@ -1338,22 +1274,21 @@ bool GMLReader::SaveClasses( const char *pszFile )
 /* -------------------------------------------------------------------- */
 /*      Serialize to disk.                                              */
 /* -------------------------------------------------------------------- */
-    VSILFILE        *fp;
-    bool         bSuccess = true;
-    char        *pszWholeText = CPLSerializeXMLTree( psRoot );
+    char *pszWholeText = CPLSerializeXMLTree(psRoot);
 
-    CPLDestroyXMLNode( psRoot );
+    CPLDestroyXMLNode(psRoot);
 
-    fp = VSIFOpenL( pszFile, "wb" );
+    VSILFILE *fp = VSIFOpenL(pszFile, "wb");
 
+    bool bSuccess = true;
     if( fp == NULL )
         bSuccess = false;
-    else if( VSIFWriteL( pszWholeText, strlen(pszWholeText), 1, fp ) != 1 )
+    else if( VSIFWriteL(pszWholeText, strlen(pszWholeText), 1, fp) != 1 )
         bSuccess = false;
     else
-        VSIFCloseL( fp );
+        VSIFCloseL(fp);
 
-    CPLFree( pszWholeText );
+    CPLFree(pszWholeText);
 
     return bSuccess;
 }
@@ -1372,14 +1307,12 @@ bool GMLReader::PrescanForSchema( bool bGetExtents,
                                  bool bOnlyDetectSRS )
 
 {
-    GMLFeature  *poFeature;
-
     if( m_pszFilename == NULL )
         return false;
 
     if( !bOnlyDetectSRS )
     {
-        SetClassListLocked( false );
+        SetClassListLocked(false);
         ClearClasses();
     }
 
@@ -1396,6 +1329,7 @@ bool GMLReader::PrescanForSchema( bool bGetExtents,
 
     std::string osWork;
 
+    GMLFeature *poFeature = NULL;
     while( (poFeature = NextFeature()) != NULL )
     {
         GMLFeatureClass *poClass = poFeature->GetClass();
@@ -1406,18 +1340,18 @@ bool GMLReader::PrescanForSchema( bool bGetExtents,
         poLastClass = poClass;
 
         if( poClass->GetFeatureCount() == -1 )
-            poClass->SetFeatureCount( 1 );
+            poClass->SetFeatureCount(1);
         else
-            poClass->SetFeatureCount( poClass->GetFeatureCount() + 1 );
+            poClass->SetFeatureCount(poClass->GetFeatureCount() + 1);
 
         const CPLXMLNode* const * papsGeometry = poFeature->GetGeometryList();
         if( !bOnlyDetectSRS && papsGeometry != NULL && papsGeometry[0] != NULL )
         {
             if( poClass->GetGeometryPropertyCount() == 0 )
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true ) );
+                poClass->AddGeometryProperty(
+                    new GMLGeometryPropertyDefn("", "", wkbUnknown, -1, true));
         }
 
-#ifdef SUPPORT_GEOMETRY
         if( bGetExtents && papsGeometry != NULL )
         {
             OGRGeometry *poGeometry = GML_BuildOGRGeometryFromList(
@@ -1429,17 +1363,15 @@ bool GMLReader::PrescanForSchema( bool bGetExtents,
 
             if( poGeometry != NULL && poClass->GetGeometryPropertyCount() > 0 )
             {
-                double  dfXMin, dfXMax, dfYMin, dfYMax;
-                OGREnvelope sEnvelope;
-
-                OGRwkbGeometryType eGType = (OGRwkbGeometryType)
-                    poClass->GetGeometryProperty(0)->GetType();
+                OGRwkbGeometryType eGType = static_cast<OGRwkbGeometryType>(
+                    poClass->GetGeometryProperty(0)->GetType());
 
                 if( bAnalyzeSRSPerFeature )
                 {
-                    const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry,
-                                                                            osWork,
-                                                                            m_bConsiderEPSGAsURN);
+                    const char* pszSRSName =
+                        GML_ExtractSrsNameFromGeometry(papsGeometry,
+                                                       osWork,
+                                                       m_bConsiderEPSGAsURN);
                     if (pszSRSName != NULL)
                         m_bCanUseGlobalSRSName = false;
                     poClass->MergeSRSName(pszSRSName);
@@ -1450,19 +1382,27 @@ bool GMLReader::PrescanForSchema( bool bGetExtents,
                     eGType = wkbNone;
 
                 poClass->GetGeometryProperty(0)->SetType(
-                    (int) OGRMergeGeometryTypesEx(
-                        eGType, poGeometry->getGeometryType(), true ) );
+                    static_cast<int>(OGRMergeGeometryTypesEx(
+                        eGType, poGeometry->getGeometryType(), true)));
 
-                // merge extents.
+                // Merge extents.
                 if (!poGeometry->IsEmpty())
                 {
+                    double dfXMin = 0.0;
+                    double dfXMax = 0.0;
+                    double dfYMin = 0.0;
+                    double dfYMax = 0.0;
+
+                    OGREnvelope sEnvelope;
+
                     poGeometry->getEnvelope( &sEnvelope );
-                    if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
+                    if( poClass->GetExtents(&dfXMin, &dfXMax,
+                                            &dfYMin, &dfYMax) )
                     {
-                        dfXMin = MIN(dfXMin,sEnvelope.MinX);
-                        dfXMax = MAX(dfXMax,sEnvelope.MaxX);
-                        dfYMin = MIN(dfYMin,sEnvelope.MinY);
-                        dfYMax = MAX(dfYMax,sEnvelope.MaxY);
+                        dfXMin = std::min(dfXMin, sEnvelope.MinX);
+                        dfXMax = std::max(dfXMax, sEnvelope.MaxX);
+                        dfYMin = std::min(dfYMin, sEnvelope.MinY);
+                        dfYMax = std::max(dfYMax, sEnvelope.MaxY);
                     }
                     else
                     {
@@ -1472,12 +1412,10 @@ bool GMLReader::PrescanForSchema( bool bGetExtents,
                         dfYMax = sEnvelope.MaxY;
                     }
 
-                    poClass->SetExtents( dfXMin, dfXMax, dfYMin, dfYMax );
+                    poClass->SetExtents(dfXMin, dfXMax, dfYMin, dfYMax);
                 }
                 delete poGeometry;
-
             }
-#endif /* def SUPPORT_GEOMETRY */
         }
 
         delete poFeature;
@@ -1497,13 +1435,13 @@ bool GMLReader::PrescanForSchema( bool bGetExtents,
         if (m_bInvertAxisOrderIfLatLong && GML_IsSRSLatLongOrder(pszSRSName) &&
             oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE)
         {
-            OGR_SRSNode *poGEOGCS = oSRS.GetAttrNode( "GEOGCS" );
+            OGR_SRSNode *poGEOGCS = oSRS.GetAttrNode("GEOGCS");
             if( poGEOGCS != NULL )
-                poGEOGCS->StripNodes( "AXIS" );
+                poGEOGCS->StripNodes("AXIS");
 
-            OGR_SRSNode *poPROJCS = oSRS.GetAttrNode( "PROJCS" );
+            OGR_SRSNode *poPROJCS = oSRS.GetAttrNode("PROJCS");
             if (poPROJCS != NULL && oSRS.EPSGTreatsAsNorthingEasting())
-                poPROJCS->StripNodes( "AXIS" );
+                poPROJCS->StripNodes("AXIS");
 
             char* pszWKT = NULL;
             if (oSRS.exportToWkt(&pszWKT) == OGRERR_NONE)
@@ -1515,9 +1453,12 @@ bool GMLReader::PrescanForSchema( bool bGetExtents,
             /* order */
             if (m_bCanUseGlobalSRSName)
             {
-                double  dfXMin, dfXMax, dfYMin, dfYMax;
+                double dfXMin = 0.0;
+                double dfXMax = 0.0;
+                double dfYMin = 0.0;
+                double dfYMax = 0.0;
                 if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
-                    poClass->SetExtents( dfYMin, dfYMax, dfXMin, dfXMax );
+                    poClass->SetExtents(dfYMin, dfYMax, dfXMin, dfXMax);
             }
         }
         else if( !bAnalyzeSRSPerFeature &&
@@ -1556,7 +1497,7 @@ void GMLReader::SetGlobalSRSName( const char* pszGlobalSRSName )
 {
     if (m_pszGlobalSRSName == NULL && pszGlobalSRSName != NULL)
     {
-        const char* pszVertCS_EPSG;
+        const char* pszVertCS_EPSG = NULL;
         if( STARTS_WITH(pszGlobalSRSName, "EPSG:") &&
             (pszVertCS_EPSG = strstr(pszGlobalSRSName, ", EPSG:")) != NULL )
         {
@@ -1565,10 +1506,10 @@ void GMLReader::SetGlobalSRSName( const char* pszGlobalSRSName )
                     atoi(pszVertCS_EPSG + 7)));
         }
         else if (STARTS_WITH(pszGlobalSRSName, "EPSG:") &&
-            m_bConsiderEPSGAsURN)
+                 m_bConsiderEPSGAsURN)
         {
-            m_pszGlobalSRSName = CPLStrdup(CPLSPrintf("urn:ogc:def:crs:EPSG::%s",
-                                                      pszGlobalSRSName+5));
+            m_pszGlobalSRSName = CPLStrdup(
+                CPLSPrintf("urn:ogc:def:crs:EPSG::%s", pszGlobalSRSName + 5));
         }
         else
         {
@@ -1584,14 +1525,15 @@ void GMLReader::SetGlobalSRSName( const char* pszGlobalSRSName )
 bool GMLReader::SetFilteredClassName(const char* pszClassName)
 {
     CPLFree(m_pszFilteredClassName);
-    m_pszFilteredClassName = (pszClassName) ? CPLStrdup(pszClassName) : NULL;
+    m_pszFilteredClassName = pszClassName ? CPLStrdup(pszClassName) : NULL;
 
     m_nFilteredClassIndex = -1;
     if( m_pszFilteredClassName != NULL )
     {
         for( int i = 0; i < m_nClassCount; i++ )
         {
-            if( strcmp(m_papoClass[i]->GetElementName(), pszClassName) == 0 )
+            if( strcmp(m_papoClass[i]->GetElementName(),
+                       m_pszFilteredClassName) == 0 )
             {
                 m_nFilteredClassIndex = i;
                 break;
diff --git a/ogr/ogrsf_frmts/gml/gmlreader.h b/ogr/ogrsf_frmts/gml/gmlreader.h
index e229ff0..168a9ed 100644
--- a/ogr/ogrsf_frmts/gml/gmlreader.h
+++ b/ogr/ogrsf_frmts/gml/gmlreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreader.h 35690 2016-10-11 09:56:31Z rouault $
+ * $Id: gmlreader.h 37371 2017-02-13 11:41:59Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Public Declarations for OGR free GML Reader code.
@@ -38,6 +38,9 @@
 
 #include <vector>
 
+// Special value to map to a NULL field
+#define OGR_GML_NULL "___OGR_GML_NULL___"
+
 typedef enum {
     GMLPT_Untyped = 0,
     GMLPT_String = 1,
@@ -168,9 +171,9 @@ class CPL_DLL GMLFeatureClass
     char       *m_pszSRSName;
     bool        m_bSRSNameConsistent;
 
-public:
-            GMLFeatureClass( const char *pszName = "" );
-           ~GMLFeatureClass();
+  public:
+    explicit  GMLFeatureClass( const char *pszName = "" );
+             ~GMLFeatureClass();
 
     const char *GetElementName() const;
     size_t      GetElementNameLen() const;
@@ -240,7 +243,7 @@ class CPL_DLL GMLFeature
     char           **m_papszOBProperties;
 
 public:
-                    GMLFeature( GMLFeatureClass * );
+    explicit        GMLFeature( GMLFeatureClass * );
                    ~GMLFeature();
 
     GMLFeatureClass*GetClass() const { return m_poClass; }
@@ -271,7 +274,7 @@ public:
 /************************************************************************/
 class CPL_DLL IGMLReader
 {
-public:
+  public:
     virtual     ~IGMLReader();
 
     virtual bool IsClassListLocked() const = 0;
@@ -306,7 +309,7 @@ public:
     virtual bool PrescanForSchema( bool bGetExtents = true,
                                   bool bAnalyzeSRSPerFeature = true,
                                   bool bOnlyDetectSRS = false ) = 0;
-    virtual bool PrescanForTemplate( void ) = 0;
+    virtual bool PrescanForTemplate() = 0;
 
     virtual bool HasStoppedParsing() = 0;
 
@@ -326,5 +329,4 @@ IGMLReader *CreateGMLReader(bool bUseExpatParserPreferably,
                             GMLSwapCoordinatesEnum eSwapCoordinates,
                             bool bGetSecondaryGeometryOption);
 
-
 #endif /* GMLREADER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/gmlreaderp.h b/ogr/ogrsf_frmts/gml/gmlreaderp.h
index 2ab068f..a896658 100644
--- a/ogr/ogrsf_frmts/gml/gmlreaderp.h
+++ b/ogr/ogrsf_frmts/gml/gmlreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlreaderp.h 35690 2016-10-11 09:56:31Z rouault $
+ * $Id: gmlreaderp.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GML Reader
  * Purpose:  Private Declarations for OGR free GML Reader code.
@@ -33,10 +33,13 @@
 
 #if defined(HAVE_XERCES)
 
+// Must be first for DEBUG_BOOL case
 #include "xercesc_headers.h"
+#include "ogr_xerces.h"
 
 #endif /* HAVE_XERCES */
 
+#include "cpl_string.h"
 #include "gmlreader.h"
 #include "ogr_api.h"
 #include "cpl_vsi.h"
@@ -60,13 +63,14 @@ class GFSTemplateItem;
 
 class GFSTemplateList
 {
-private:
+  private:
     bool            m_bSequentialLayers;
     GFSTemplateItem *pFirst;
     GFSTemplateItem *pLast;
     GFSTemplateItem *Insert( const char *pszName );
-public:
-                    GFSTemplateList( void );
+
+  public:
+                    GFSTemplateList();
                     ~GFSTemplateList();
     void            Update( const char *pszName, int bHasGeom );
     GFSTemplateItem *GetFirst() { return pFirst; }
@@ -103,7 +107,6 @@ typedef struct
     CPLXMLNode* psLastChild;
 } NodeLastChild;
 
-
 typedef enum
 {
     APPSCHEMA_GENERIC,
@@ -121,7 +124,6 @@ class GMLHandler
     int        m_nAttributeIndex;
     int        m_nAttributeDepth;
 
-
     char      *m_pszGeometry;
     unsigned int m_nGeomAlloc;
     unsigned int m_nGeomLen;
@@ -187,7 +189,7 @@ protected:
     int              nStackDepth;
     HandlerState     stateStack[STACK_SIZE];
 
-    std::string      osFID;
+    CPLString           m_osFID;
     virtual const char* GetFID(void* attr) = 0;
 
     virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr) = 0;
@@ -199,14 +201,13 @@ protected:
     bool       IsGeometryElement( const char *pszElement );
 
 public:
-    GMLHandler( GMLReader *poReader );
+    explicit GMLHandler( GMLReader *poReader );
     virtual ~GMLHandler();
 
     virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName) = 0;
     virtual char*       GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey) = 0;
 };
 
-
 #if defined(HAVE_XERCES)
 
 /************************************************************************/
@@ -219,17 +220,12 @@ class GMLBinInputStream : public BinInputStream
 
 public :
 
-             GMLBinInputStream(VSILFILE* fp);
+    explicit GMLBinInputStream(VSILFILE* fp);
     virtual ~GMLBinInputStream();
 
-#if XERCES_VERSION_MAJOR >= 3
-    virtual XMLFilePos curPos() const;
-    virtual XMLSize_t readBytes(XMLByte* const toFill, const XMLSize_t maxToRead);
-    virtual const XMLCh* getContentType() const ;
-#else
-    virtual unsigned int curPos() const;
-    virtual unsigned int readBytes(XMLByte* const toFill, const unsigned int maxToRead);
-#endif
+    virtual XMLFilePos curPos() const override;
+    virtual XMLSize_t readBytes(XMLByte* const toFill, const XMLSize_t maxToRead) override;
+    virtual const XMLCh* getContentType() const override ;
 };
 
 /************************************************************************/
@@ -238,6 +234,7 @@ public :
 
 class GMLInputSource : public InputSource
 {
+    // TODO(schwehr): Rename to pBinInputStream to not look like a bool.
     GMLBinInputStream* binInputStream;
 
 public:
@@ -245,61 +242,49 @@ public:
                             MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
     virtual ~GMLInputSource();
 
-    virtual BinInputStream* makeStream() const;
+    virtual BinInputStream* makeStream() const override;
 };
 
-
-/************************************************************************/
-/*          XMLCh / char translation functions - trstring.cpp           */
-/************************************************************************/
-int tr_strcmp( const char *, const XMLCh * );
-void tr_strcpy( XMLCh *, const char * );
-void tr_strcpy( char *, const XMLCh * );
-char *tr_strdup( const XMLCh * );
-int tr_strlen( const XMLCh * );
-
 /************************************************************************/
 /*                         GMLXercesHandler                             */
 /************************************************************************/
 class GMLXercesHandler : public DefaultHandler, public GMLHandler
 {
     int        m_nEntityCounter;
+    CPLString  m_osElement;
+    CPLString  m_osCharacters;
+    CPLString  m_osAttrName;
+    CPLString  m_osAttrValue;
 
-public:
-    GMLXercesHandler( GMLReader *poReader );
+  public:
+    explicit GMLXercesHandler( GMLReader *poReader );
 
     void startElement(
         const   XMLCh* const    uri,
         const   XMLCh* const    localname,
         const   XMLCh* const    qname,
         const   Attributes& attrs
-    );
+    ) override;
     void endElement(
         const   XMLCh* const    uri,
         const   XMLCh* const    localname,
         const   XMLCh* const    qname
-    );
-#if XERCES_VERSION_MAJOR >= 3
-    void characters( const XMLCh *const chars,
-                     const XMLSize_t length );
-#else
+    ) override;
     void characters( const XMLCh *const chars,
-                     const unsigned int length );
-#endif
+                     const XMLSize_t length ) override;
 
-    void fatalError(const SAXParseException&);
+    void fatalError(const SAXParseException&) override;
 
-    void startEntity (const XMLCh *const name);
+    void startEntity (const XMLCh *const name) override;
 
-    virtual const char* GetFID(void* attr);
-    virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr);
-    virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName);
-    virtual char*       GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey);
+    virtual const char* GetFID(void* attr) override;
+    virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr) override;
+    virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName) override;
+    virtual char*       GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey) override;
 };
 
 #endif
 
-
 #if defined(HAVE_EXPAT)
 
 #include "ogr_expat.h"
@@ -320,10 +305,10 @@ public:
 
     void        ResetDataHandlerCounter() { m_nDataHandlerCounter = 0; }
 
-    virtual const char* GetFID(void* attr);
-    virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr);
-    virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName);
-    virtual char*       GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey);
+    virtual const char* GetFID(void* attr) override;
+    virtual CPLXMLNode* AddAttributes(CPLXMLNode* psNode, void* attr) override;
+    virtual char*       GetAttributeValue(void* attr, const char* pszAttributeName) override;
+    virtual char*       GetAttributeByIdx(void* attr, unsigned int idx, char** ppszKey) override;
 
     static void XMLCALL startElementCbk(void *pUserData, const char *pszName,
                                         const char **ppszAttr);
@@ -354,7 +339,6 @@ public:
         return ( m_nPathLength == 0 ) ? "" : aosPathComponents[m_nPathLength-1].c_str();
     }
 
-
     size_t GetLastComponentLen() const {
         return ( m_nPathLength == 0 ) ? 0: aosPathComponents[m_nPathLength-1].size();
     }
@@ -372,18 +356,9 @@ public:
 /*                              GMLReader                               */
 /************************************************************************/
 
-typedef enum
-{
-    OGRGML_XERCES_UNINITIALIZED,
-    OGRGML_XERCES_INIT_FAILED,
-    OGRGML_XERCES_INIT_SUCCESSFUL
-} OGRGMLXercesState;
-
 class GMLReader : public IGMLReader
 {
-private:
-    static OGRGMLXercesState    m_eXercesInitState;
-    static int    m_nInstanceCount;
+  private:
     bool          m_bClassListLocked;
 
     int         m_nClassCount;
@@ -402,6 +377,7 @@ private:
     GMLFeature   *m_poCompleteFeature;
     GMLInputSource *m_GMLInputSource;
     bool          m_bEOF;
+    bool          m_bXercesInitialized;
     bool          SetupParserXerces();
     GMLFeature   *NextFeatureXerces();
 #endif
@@ -470,41 +446,41 @@ public:
                           bool bGetSecondaryGeometryOption);
     virtual     ~GMLReader();
 
-    bool             IsClassListLocked() const { return m_bClassListLocked; }
-    void             SetClassListLocked( bool bFlag )
+    bool             IsClassListLocked() const override { return m_bClassListLocked; }
+    void             SetClassListLocked( bool bFlag ) override
         { m_bClassListLocked = bFlag; }
 
-    void             SetSourceFile( const char *pszFilename );
-    void             SetFP( VSILFILE* fp );
-    const char*      GetSourceFileName();
+    void             SetSourceFile( const char *pszFilename ) override;
+    void             SetFP( VSILFILE* fp ) override;
+    const char*      GetSourceFileName() override;
 
-    int              GetClassCount() const { return m_nClassCount; }
-    GMLFeatureClass *GetClass( int i ) const;
-    GMLFeatureClass *GetClass( const char *pszName ) const;
+    int              GetClassCount() const override { return m_nClassCount; }
+    GMLFeatureClass *GetClass( int i ) const override;
+    GMLFeatureClass *GetClass( const char *pszName ) const override;
 
-    int              AddClass( GMLFeatureClass *poClass );
-    void             ClearClasses();
+    int              AddClass( GMLFeatureClass *poClass ) override;
+    void             ClearClasses() override;
 
-    GMLFeature       *NextFeature();
+    GMLFeature       *NextFeature() override;
 
-    bool             LoadClasses( const char *pszFile = NULL );
-    bool             SaveClasses( const char *pszFile = NULL );
+    bool             LoadClasses( const char *pszFile = NULL ) override;
+    bool             SaveClasses( const char *pszFile = NULL ) override;
 
     bool             ResolveXlinks( const char *pszFile,
                                     bool* pbOutIsTempFile,
                                     char **papszSkip = NULL,
-                                    const bool bStrict = false );
+                                    const bool bStrict = false ) override;
 
     bool             HugeFileResolver( const char *pszFile,
                                        bool bSqliteIsTempFile,
-                                       int iSqliteCacheMB );
+                                       int iSqliteCacheMB ) override;
 
     bool             PrescanForSchema(bool bGetExtents = true,
                                       bool bAnalyzeSRSPerFeature = true,
-                                      bool bOnlyDetectSRS = false );
-    bool             PrescanForTemplate( void );
+                                      bool bOnlyDetectSRS = false ) override;
+    bool             PrescanForTemplate() override;
     bool             ReArrangeTemplateClasses( GFSTemplateList *pCC );
-    void             ResetReading();
+    void             ResetReading() override;
 
 // ---
 
@@ -529,20 +505,20 @@ public:
 
     void        SetWidthFlag(bool bFlag) { m_bSetWidthFlag = bFlag; }
 
-    bool        HasStoppedParsing() { return m_bStopParsing; }
+    bool        HasStoppedParsing() override { return m_bStopParsing; }
 
     bool       FetchAllGeometries() { return m_bFetchAllGeometries; }
 
-    void        SetGlobalSRSName( const char* pszGlobalSRSName ) ;
-    const char* GetGlobalSRSName() { return m_pszGlobalSRSName; }
+    void        SetGlobalSRSName( const char* pszGlobalSRSName ) override ;
+    const char* GetGlobalSRSName() override { return m_pszGlobalSRSName; }
 
-    bool        CanUseGlobalSRSName() { return m_bCanUseGlobalSRSName; }
+    bool        CanUseGlobalSRSName() override { return m_bCanUseGlobalSRSName; }
 
-    bool        SetFilteredClassName(const char* pszClassName);
-    const char* GetFilteredClassName() { return m_pszFilteredClassName; }
+    bool        SetFilteredClassName(const char* pszClassName) override;
+    const char* GetFilteredClassName() override { return m_pszFilteredClassName; }
     int         GetFilteredClassIndex() { return m_nFilteredClassIndex; }
 
-    bool        IsSequentialLayers() const { return m_nHasSequentialLayers == TRUE; }
+    bool        IsSequentialLayers() const override { return m_nHasSequentialLayers == TRUE; }
 
     void        SetReportAllAttributes(bool bFlag) { m_bReportAllAttributes = bFlag; }
     bool        ReportAllAttributes() const { return m_bReportAllAttributes; }
diff --git a/ogr/ogrsf_frmts/gml/gmlreadstate.cpp b/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
index 3ec5c79..08a3a4a 100644
--- a/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlreadstate.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: gmlreadstate.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReadState class.
@@ -28,30 +27,35 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlreaderp.h"
+
+#include <cstddef>
+#include <memory>
+#include <string>
+#include <vector>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
 
+CPL_CVSID("$Id: gmlreadstate.cpp 37182 2017-01-19 07:34:23Z goatbar $");
+
 /************************************************************************/
 /*                            GMLReadState()                            */
 /************************************************************************/
 
-GMLReadState::GMLReadState()
-
-{
-    m_poFeature = NULL;
-    m_poParentState = NULL;
-    m_nPathLength = 0;
-}
+GMLReadState::GMLReadState() :
+    m_poFeature(NULL),
+    m_poParentState(NULL),
+    m_nPathLength(0)
+{}
 
 /************************************************************************/
 /*                           ~GMLReadState()                            */
 /************************************************************************/
 
-GMLReadState::~GMLReadState()
-
-{
-}
+GMLReadState::~GMLReadState() {}
 
 /************************************************************************/
 /*                              Reset()                                 */
@@ -75,7 +79,7 @@ void GMLReadState::PushPath( const char *pszElement, int nLen )
 {
     if (m_nPathLength > 0)
         osPath.append(1, '|');
-    if (m_nPathLength < (int)aosPathComponents.size())
+    if (m_nPathLength < static_cast<int>(aosPathComponents.size()))
     {
         if (nLen >= 0)
         {
@@ -93,7 +97,7 @@ void GMLReadState::PushPath( const char *pszElement, int nLen )
         aosPathComponents.push_back(pszElement);
         osPath.append(pszElement);
     }
-    m_nPathLength ++;
+    m_nPathLength++;
 }
 
 /************************************************************************/
@@ -103,8 +107,9 @@ void GMLReadState::PushPath( const char *pszElement, int nLen )
 void GMLReadState::PopPath()
 
 {
-    CPLAssert( m_nPathLength > 0 );
+    CPLAssert(m_nPathLength > 0);
 
-    osPath.resize(osPath.size() - (aosPathComponents[m_nPathLength-1].size() + ((m_nPathLength > 1) ? 1 : 0)));
-    m_nPathLength --;
+    osPath.resize(osPath.size() - (aosPathComponents[m_nPathLength - 1].size() +
+                                   ((m_nPathLength > 1) ? 1 : 0)));
+    m_nPathLength--;
 }
diff --git a/ogr/ogrsf_frmts/gml/gmlregistry.cpp b/ogr/ogrsf_frmts/gml/gmlregistry.cpp
index aa84061..372f9a0 100644
--- a/ogr/ogrsf_frmts/gml/gmlregistry.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlregistry.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gmlregistry.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML registry
  * Purpose:  GML reader
@@ -27,32 +26,39 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlregistry.h"
 
+#include <cstring>
+
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: gmlregistry.cpp 37914 2017-04-06 17:38:46Z rouault $");
+
 /************************************************************************/
 /*                           Parse()                                    */
 /************************************************************************/
 
-int GMLRegistry::Parse()
+bool GMLRegistry::Parse()
 {
-    if( osRegistryPath.size() == 0 )
+    if( osRegistryPath.empty() )
     {
-        const char* pszFilename = CPLFindFile( "gdal", "gml_registry.xml" );
+        const char *pszFilename = CPLFindFile("gdal", "gml_registry.xml");
         if( pszFilename )
             osRegistryPath = pszFilename;
     }
-    if( osRegistryPath.size() == 0 )
-        return FALSE;
-    CPLXMLNode* psRootNode = CPLParseXMLFile(osRegistryPath);
+    if( osRegistryPath.empty() )
+        return false;
+    CPLXMLNode *psRootNode = CPLParseXMLFile(osRegistryPath);
     if( psRootNode == NULL )
-        return FALSE;
-    CPLXMLNode *psRegistryNode = CPLGetXMLNode( psRootNode, "=gml_registry" );
+        return false;
+    CPLXMLNode *psRegistryNode = CPLGetXMLNode(psRootNode, "=gml_registry");
     if( psRegistryNode == NULL )
     {
         CPLDestroyXMLNode(psRootNode);
-        return FALSE;
+        return false;
     }
-    CPLXMLNode* psIter = psRegistryNode->psChild;
+    CPLXMLNode *psIter = psRegistryNode->psChild;
     while( psIter != NULL )
     {
         if( psIter->eType == CXT_Element &&
@@ -67,26 +73,29 @@ int GMLRegistry::Parse()
         psIter = psIter->psNext;
     }
     CPLDestroyXMLNode(psRootNode);
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                           Parse()                                    */
 /************************************************************************/
 
-int GMLRegistryNamespace::Parse(const char* pszRegistryFilename, CPLXMLNode* psNode)
+bool GMLRegistryNamespace::Parse(const char *pszRegistryFilename,
+                                 CPLXMLNode *psNode)
 {
-    const char* pszPrefix = CPLGetXMLValue(psNode, "prefix", NULL);
-    const char* pszURI = CPLGetXMLValue(psNode, "uri", NULL);
-    if( pszPrefix == NULL || pszURI == NULL )
-        return FALSE;
+    const char *pszPrefix = CPLGetXMLValue(psNode, "prefix", "");
+    const char *pszURI = CPLGetXMLValue(psNode, "uri", NULL);
+    if( pszURI == NULL )
+        return false;
     osPrefix = pszPrefix;
     osURI = pszURI;
-    const char* pszUseGlobalSRSName = CPLGetXMLValue(psNode, "useGlobalSRSName", NULL);
-    if( pszUseGlobalSRSName != NULL && strcmp(pszUseGlobalSRSName, "true") == 0 )
-        bUseGlobalSRSName = TRUE;
+    const char *pszUseGlobalSRSName =
+        CPLGetXMLValue(psNode, "useGlobalSRSName", NULL);
+    if( pszUseGlobalSRSName != NULL &&
+        strcmp(pszUseGlobalSRSName, "true") == 0 )
+        bUseGlobalSRSName = true;
 
-    CPLXMLNode* psIter = psNode->psChild;
+    CPLXMLNode *psIter = psNode->psChild;
     while( psIter != NULL )
     {
         if( psIter->eType == CXT_Element &&
@@ -100,28 +109,33 @@ int GMLRegistryNamespace::Parse(const char* pszRegistryFilename, CPLXMLNode* psN
         }
         psIter = psIter->psNext;
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                           Parse()                                    */
 /************************************************************************/
 
-int GMLRegistryFeatureType::Parse(const char* pszRegistryFilename, CPLXMLNode* psNode)
+bool GMLRegistryFeatureType::Parse(const char *pszRegistryFilename,
+                                   CPLXMLNode *psNode)
 {
-    const char* pszElementName = CPLGetXMLValue(psNode, "elementName", NULL);
-    const char* pszElementValue = CPLGetXMLValue(psNode, "elementValue", NULL);
-    const char* pszSchemaLocation = CPLGetXMLValue(psNode, "schemaLocation", NULL);
-    const char* pszGFSSchemaLocation = CPLGetXMLValue(psNode, "gfsSchemaLocation", NULL);
-    if( pszElementName == NULL || (pszSchemaLocation == NULL && pszGFSSchemaLocation == NULL) )
-        return FALSE;
+    const char *pszElementName = CPLGetXMLValue(psNode, "elementName", NULL);
+    const char *pszSchemaLocation =
+        CPLGetXMLValue(psNode, "schemaLocation", NULL);
+    const char *pszGFSSchemaLocation =
+        CPLGetXMLValue(psNode, "gfsSchemaLocation", NULL);
+    if( pszElementName == NULL ||
+        (pszSchemaLocation == NULL && pszGFSSchemaLocation == NULL) )
+        return false;
+
+    const char *pszElementValue = CPLGetXMLValue(psNode, "elementValue", NULL);
     osElementName = pszElementName;
 
     if( pszSchemaLocation != NULL )
     {
         if( !STARTS_WITH(pszSchemaLocation, "http://") &&
             !STARTS_WITH(pszSchemaLocation, "https://") &&
-            CPLIsFilenameRelative(pszSchemaLocation ) )
+            CPLIsFilenameRelative(pszSchemaLocation) )
         {
             pszSchemaLocation = CPLFormFilename(
                 CPLGetPath(pszRegistryFilename), pszSchemaLocation, NULL );
@@ -132,10 +146,10 @@ int GMLRegistryFeatureType::Parse(const char* pszRegistryFilename, CPLXMLNode* p
     {
         if( !STARTS_WITH(pszGFSSchemaLocation, "http://") &&
             !STARTS_WITH(pszGFSSchemaLocation, "https://") &&
-            CPLIsFilenameRelative(pszGFSSchemaLocation ) )
+            CPLIsFilenameRelative(pszGFSSchemaLocation) )
         {
             pszGFSSchemaLocation = CPLFormFilename(
-                CPLGetPath(pszRegistryFilename), pszGFSSchemaLocation, NULL );
+                CPLGetPath(pszRegistryFilename), pszGFSSchemaLocation, NULL);
         }
         osGFSSchemaLocation = pszGFSSchemaLocation;
     }
@@ -145,5 +159,5 @@ int GMLRegistryFeatureType::Parse(const char* pszRegistryFilename, CPLXMLNode* p
         osElementValue = pszElementValue;
     }
 
-    return TRUE;
+    return true;
 }
diff --git a/ogr/ogrsf_frmts/gml/gmlregistry.h b/ogr/ogrsf_frmts/gml/gmlregistry.h
index 9c2e861..6afc691 100644
--- a/ogr/ogrsf_frmts/gml/gmlregistry.h
+++ b/ogr/ogrsf_frmts/gml/gmlregistry.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlregistry.h 33702 2016-03-11 06:20:16Z goatbar $
+ * $Id: gmlregistry.h 37244 2017-01-30 22:12:31Z goatbar $
  *
  * Project:  GML registry
  * Purpose:  GML reader
@@ -43,20 +43,20 @@ class GMLRegistryFeatureType
         CPLString                           osSchemaLocation;
         CPLString                           osGFSSchemaLocation;
 
-        int Parse(const char* pszRegistryFilename, CPLXMLNode* psNode);
+        bool Parse(const char* pszRegistryFilename, CPLXMLNode* psNode);
 };
 
 class GMLRegistryNamespace
 {
     public:
-        GMLRegistryNamespace() : bUseGlobalSRSName(FALSE) {}
+        GMLRegistryNamespace() : bUseGlobalSRSName(false) {}
 
         CPLString                           osPrefix;
         CPLString                           osURI;
-        int                                 bUseGlobalSRSName;
+        bool                                bUseGlobalSRSName;
         std::vector<GMLRegistryFeatureType> aoFeatureTypes;
 
-        int Parse(const char* pszRegistryFilename, CPLXMLNode* psNode);
+        bool Parse(const char* pszRegistryFilename, CPLXMLNode* psNode);
 };
 
 class GMLRegistry
@@ -66,8 +66,9 @@ class GMLRegistry
     public:
         std::vector<GMLRegistryNamespace> aoNamespaces;
 
-        GMLRegistry(const CPLString& osRegistryPathIn) : osRegistryPath(osRegistryPathIn) {}
-        int Parse();
+        explicit GMLRegistry(const CPLString& osRegistryPathIn) :
+                                        osRegistryPath(osRegistryPathIn) {}
+        bool Parse();
 };
 
 #endif /* GMLREGISTRY_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.cpp b/ogr/ogrsf_frmts/gml/gmlutils.cpp
index 9a2158b..524a99d 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.cpp
+++ b/ogr/ogrsf_frmts/gml/gmlutils.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gmlutils.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
@@ -27,42 +26,55 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlutils.h"
 
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <map>
+#include <string>
+#include <utility>
+
+#include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_api.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
-#include <string>
-#include <map>
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: gmlutils.cpp 37914 2017-04-06 17:38:46Z rouault $");
 
 /************************************************************************/
 /*                GML_ExtractSrsNameFromGeometry()                      */
 /************************************************************************/
 
-const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometry,
-                                     std::string& osWork,
-                                     bool bConsiderEPSGAsURN)
+const char *
+GML_ExtractSrsNameFromGeometry(const CPLXMLNode *const *papsGeometry,
+                               std::string &osWork, bool bConsiderEPSGAsURN)
 {
     if (papsGeometry[0] != NULL && papsGeometry[1] == NULL)
     {
-        const char* pszSRSName = CPLGetXMLValue((CPLXMLNode*)papsGeometry[0], "srsName", NULL);
-        if (pszSRSName)
+        const char *pszSRSName =
+            CPLGetXMLValue(const_cast<CPLXMLNode *>(papsGeometry[0]),
+                           "srsName", NULL);
+        if(pszSRSName)
         {
-            int nLen = static_cast<int>(strlen(pszSRSName));
+            const int nLen = static_cast<int>(strlen(pszSRSName));
 
-            if (STARTS_WITH(pszSRSName, "EPSG:") &&
-                bConsiderEPSGAsURN)
+            if(STARTS_WITH(pszSRSName, "EPSG:") && bConsiderEPSGAsURN)
             {
-                osWork.reserve(22 + nLen-5);
+                osWork.reserve(22 + nLen - 5);
                 osWork.assign("urn:ogc:def:crs:EPSG::", 22);
-                osWork.append(pszSRSName+5, nLen-5);
+                osWork.append(pszSRSName + 5, nLen - 5);
                 return osWork.c_str();
             }
-            else if (STARTS_WITH(pszSRSName, "http://www.opengis.net/gml/srs/epsg.xml#"))
+            else if (STARTS_WITH(pszSRSName,
+                                "http://www.opengis.net/gml/srs/epsg.xml#"))
             {
-                osWork.reserve(5 + nLen-40 );
+                osWork.reserve(5 + nLen - 40);
                 osWork.assign("EPSG:", 5);
-                osWork.append(pszSRSName+40, nLen-40);
+                osWork.append(pszSRSName + 40, nLen - 40);
                 return osWork.c_str();
             }
             else
@@ -78,32 +90,33 @@ const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometr
 /*                       GML_IsSRSLatLongOrder()                        */
 /************************************************************************/
 
-bool GML_IsSRSLatLongOrder(const char* pszSRSName)
+bool GML_IsSRSLatLongOrder(const char *pszSRSName)
 {
-    if (pszSRSName == NULL)
+    if(pszSRSName == NULL)
         return false;
 
-    if (STARTS_WITH(pszSRSName, "urn:") && strstr(pszSRSName, ":4326") != NULL)
+    if(STARTS_WITH(pszSRSName, "urn:") && strstr(pszSRSName, ":4326") != NULL)
     {
-        /* Shortcut ... */
+        // Shortcut.
         return true;
     }
     else if( !EQUALN(pszSRSName, "EPSG:", 5) )
     {
         OGRSpatialReference oSRS;
-        if (oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE)
+        if(oSRS.SetFromUserInput(pszSRSName) == OGRERR_NONE)
         {
-            if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
+            if(oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
                 return true;
         }
         return false;
     }
-    else
-    {
-        return false;
+    /* fguuid:jgd20??.bl (Japanese FGD GML v4) */
+    else if (strncmp(pszSRSName, "fguuid:jgd", 10) == 0 && strstr(pszSRSName, ".bl") != NULL) {
+        return true;
     }
-}
 
+    return false;
+}
 
 /************************************************************************/
 /*                GML_BuildOGRGeometryFromList_CreateCache()            */
@@ -116,21 +129,16 @@ public:
     bool                 bAxisInvert;
     OGRSpatialReference* poSRS;
 
-    SRSDesc() : bAxisInvert(false), poSRS(NULL)
-    {
-    }
+    SRSDesc() : bAxisInvert(false), poSRS(NULL) {}
 };
 
 class SRSCache
 {
     std::map<std::string, SRSDesc> oMap;
-    SRSDesc                        oLastDesc;
+    SRSDesc oLastDesc;
 
-public:
-
-    SRSCache()
-    {
-    }
+  public:
+    SRSCache() {}
 
     ~SRSCache()
     {
@@ -142,7 +150,7 @@ public:
         }
     }
 
-    SRSDesc& Get(const std::string& osSRSName)
+    SRSDesc &Get(const std::string &osSRSName)
     {
         if( osSRSName == oLastDesc.osSRSName )
             return oLastDesc;
@@ -157,7 +165,8 @@ public:
         oLastDesc.osSRSName = osSRSName;
         oLastDesc.bAxisInvert = GML_IsSRSLatLongOrder(osSRSName.c_str());
         oLastDesc.poSRS = new OGRSpatialReference();
-        if( oLastDesc.poSRS->SetFromUserInput(osSRSName.c_str()) != OGRERR_NONE )
+        if( oLastDesc.poSRS->SetFromUserInput(osSRSName.c_str()) !=
+            OGRERR_NONE )
         {
             delete oLastDesc.poSRS;
             oLastDesc.poSRS = NULL;
@@ -167,46 +176,47 @@ public:
     }
 };
 
-void* GML_BuildOGRGeometryFromList_CreateCache()
-{
-    return new SRSCache();
-}
+void *GML_BuildOGRGeometryFromList_CreateCache() { return new SRSCache(); }
 
 /************************************************************************/
 /*                 GML_BuildOGRGeometryFromList_DestroyCache()          */
 /************************************************************************/
 
-void GML_BuildOGRGeometryFromList_DestroyCache(void* hCacheSRS)
+void GML_BuildOGRGeometryFromList_DestroyCache(void *hCacheSRS)
 {
-    delete (SRSCache*)hCacheSRS;
+    delete static_cast<SRSCache *>(hCacheSRS);
 }
 
 /************************************************************************/
 /*                 GML_BuildOGRGeometryFromList()                       */
 /************************************************************************/
 
-OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry,
-                                          bool bTryToMakeMultipolygons,
-                                          bool bInvertAxisOrderIfLatLong,
-                                          const char* pszDefaultSRSName,
-                                          bool bConsiderEPSGAsURN,
-                                          GMLSwapCoordinatesEnum eSwapCoordinates,
-                                          int nPseudoBoolGetSecondaryGeometryOption,
-                                          void* hCacheSRS,
-                                          bool bFaceHoleNegative)
+OGRGeometry* GML_BuildOGRGeometryFromList(
+    const CPLXMLNode *const *papsGeometry,
+    bool bTryToMakeMultipolygons,
+    bool bInvertAxisOrderIfLatLong,
+    const char *pszDefaultSRSName,
+    bool bConsiderEPSGAsURN,
+    GMLSwapCoordinatesEnum eSwapCoordinates,
+    int nPseudoBoolGetSecondaryGeometryOption,
+    void *hCacheSRS,
+    bool bFaceHoleNegative)
 {
-    OGRGeometry* poGeom = NULL;
-    OGRGeometryCollection* poCollection = NULL;
-    for( int i=0; papsGeometry[i] != NULL; i++ )
+    OGRGeometry *poGeom = NULL;
+    OGRGeometryCollection *poCollection = NULL;
+    for( int i = 0; papsGeometry[i] != NULL; i++ )
     {
-        OGRGeometry* poSubGeom = GML2OGRGeometry_XMLNode( papsGeometry[i],
-                                                          nPseudoBoolGetSecondaryGeometryOption,
-                                                          0, 0, false, true,
-                                                          bFaceHoleNegative );
+        OGRGeometry* poSubGeom = GML2OGRGeometry_XMLNode(
+            papsGeometry[i],
+            nPseudoBoolGetSecondaryGeometryOption,
+            0, 0, false, true,
+            bFaceHoleNegative);
         if (poSubGeom)
         {
             if (poGeom == NULL)
+            {
                 poGeom = poSubGeom;
+            }
             else
             {
                 if (poCollection == NULL)
@@ -215,43 +225,54 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
                         wkbFlatten(poGeom->getGeometryType()) == wkbPolygon &&
                         wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
                     {
-                        OGRGeometryCollection* poGeomColl = new OGRMultiPolygon();
+                        OGRGeometryCollection *poGeomColl =
+                            new OGRMultiPolygon();
                         poGeomColl->addGeometryDirectly(poGeom);
                         poGeomColl->addGeometryDirectly(poSubGeom);
                         poGeom = poGeomColl;
                     }
-                    else if (bTryToMakeMultipolygons &&
-                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
-                                wkbFlatten(poSubGeom->getGeometryType()) == wkbPolygon)
+                    else if(bTryToMakeMultipolygons &&
+                            wkbFlatten(poGeom->getGeometryType()) ==
+                                wkbMultiPolygon &&
+                            wkbFlatten(poSubGeom->getGeometryType()) ==
+                                wkbPolygon)
                     {
-                        OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
+                        OGRGeometryCollection *poGeomColl =
+                            static_cast<OGRGeometryCollection *>(poGeom);
                         poGeomColl->addGeometryDirectly(poSubGeom);
                     }
-                    else if (bTryToMakeMultipolygons &&
-                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon &&
-                                wkbFlatten(poSubGeom->getGeometryType()) == wkbMultiPolygon)
+                    else if(bTryToMakeMultipolygons &&
+                            wkbFlatten(poGeom->getGeometryType()) ==
+                                wkbMultiPolygon &&
+                            wkbFlatten(poSubGeom->getGeometryType()) ==
+                                wkbMultiPolygon)
                     {
-                        OGRGeometryCollection* poGeomColl = (OGRGeometryCollection* )poGeom;
-                        OGRGeometryCollection* poGeomColl2 = (OGRGeometryCollection* )poSubGeom;
+                        OGRGeometryCollection *poGeomColl =
+                            static_cast<OGRGeometryCollection *>(poGeom);
+                        OGRGeometryCollection *poGeomColl2 =
+                            static_cast<OGRGeometryCollection *>(poSubGeom);
                         int nCount = poGeomColl2->getNumGeometries();
-                        for(int j=0;j<nCount;j++)
+                        for(int j = 0; j < nCount; j++)
                         {
-                            poGeomColl->addGeometry(poGeomColl2->getGeometryRef(j));
+                            poGeomColl->addGeometry(
+                                poGeomColl2->getGeometryRef(j));
                         }
                         delete poSubGeom;
                     }
-                    else if (bTryToMakeMultipolygons &&
-                                wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon)
+                    else if(bTryToMakeMultipolygons &&
+                            wkbFlatten(poGeom->getGeometryType()) ==
+                                wkbMultiPolygon)
                     {
                         delete poGeom;
                         delete poSubGeom;
-                        return GML_BuildOGRGeometryFromList(papsGeometry, false,
-                                                            bInvertAxisOrderIfLatLong,
-                                                            pszDefaultSRSName,
-                                                            bConsiderEPSGAsURN,
-                                                            eSwapCoordinates,
-                                                            nPseudoBoolGetSecondaryGeometryOption,
-                                                            hCacheSRS);
+                        return GML_BuildOGRGeometryFromList(
+                            papsGeometry, false,
+                            bInvertAxisOrderIfLatLong,
+                            pszDefaultSRSName,
+                            bConsiderEPSGAsURN,
+                            eSwapCoordinates,
+                            nPseudoBoolGetSecondaryGeometryOption,
+                            hCacheSRS);
                     }
                     else
                     {
@@ -272,16 +293,16 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
         return NULL;
 
     std::string osWork;
-    const char* pszSRSName = GML_ExtractSrsNameFromGeometry(papsGeometry, osWork,
-                                                            bConsiderEPSGAsURN);
-    const char* pszNameLookup = pszSRSName;
+    const char *pszSRSName = GML_ExtractSrsNameFromGeometry(
+        papsGeometry, osWork, bConsiderEPSGAsURN);
+    const char *pszNameLookup = pszSRSName;
     if( pszNameLookup == NULL )
         pszNameLookup = pszDefaultSRSName;
 
     if (pszNameLookup != NULL)
     {
-        SRSCache* poSRSCache = (SRSCache*)hCacheSRS;
-        SRSDesc& oSRSDesc = poSRSCache->Get(pszNameLookup);
+        SRSCache *poSRSCache = static_cast<SRSCache *>(hCacheSRS);
+        SRSDesc &oSRSDesc = poSRSCache->Get(pszNameLookup);
         poGeom->assignSpatialReference(oSRSDesc.poSRS);
         if( (eSwapCoordinates == GML_SWAP_AUTO &&
             oSRSDesc.bAxisInvert && bInvertAxisOrderIfLatLong) ||
@@ -298,56 +319,49 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
 /*                           GML_GetSRSName()                           */
 /************************************************************************/
 
-char* GML_GetSRSName(const OGRSpatialReference* poSRS, bool bLongSRS, bool *pbCoordSwap)
+char *GML_GetSRSName(const OGRSpatialReference *poSRS,
+                     OGRGMLSRSNameFormat eSRSNameFormat, bool *pbCoordSwap)
 {
     *pbCoordSwap = false;
     if (poSRS == NULL)
         return CPLStrdup("");
 
-    const char* pszAuthName = NULL;
-    const char* pszAuthCode = NULL;
-    const char* pszTarget = NULL;
-
-    if (poSRS->IsProjected())
-        pszTarget = "PROJCS";
-    else
-        pszTarget = "GEOGCS";
-
-    char szSrsName[50];
-    szSrsName[0] = 0;
-
-    pszAuthName = poSRS->GetAuthorityName( pszTarget );
-    if( NULL != pszAuthName )
+    const char *pszTarget = poSRS->IsProjected() ? "PROJCS" : "GEOGCS";
+    const char *pszAuthName = poSRS->GetAuthorityName(pszTarget);
+    const char *pszAuthCode = poSRS->GetAuthorityCode(pszTarget);
+    if( NULL != pszAuthName && NULL != pszAuthCode )
     {
-        if( EQUAL( pszAuthName, "EPSG" ) )
+        if( EQUAL( pszAuthName, "EPSG" ) &&
+            eSRSNameFormat != SRSNAME_SHORT &&
+            !(const_cast<OGRSpatialReference *>(poSRS)->EPSGTreatsAsLatLong() ||
+              const_cast<OGRSpatialReference *>(poSRS)->
+                  EPSGTreatsAsNorthingEasting()))
         {
-            pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
-            if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
+            OGRSpatialReference oSRS;
+            if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
             {
-                if (bLongSRS && !(((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong() ||
-                                  ((OGRSpatialReference*)poSRS)->EPSGTreatsAsNorthingEasting()))
-                {
-                    OGRSpatialReference oSRS;
-                    if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
-                    {
-                        if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
-                            *pbCoordSwap = true;
-                    }
-                }
-
-                if (bLongSRS)
-                {
-                    snprintf( szSrsName, sizeof(szSrsName), " srsName=\"urn:ogc:def:crs:%s::%s\"",
-                        pszAuthName, pszAuthCode );
-                }
-                else
-                {
-                    snprintf( szSrsName, sizeof(szSrsName), " srsName=\"%s:%s\"",
-                            pszAuthName, pszAuthCode );
-                }
+                if(oSRS.EPSGTreatsAsLatLong() ||
+                   oSRS.EPSGTreatsAsNorthingEasting())
+                    *pbCoordSwap = true;
             }
         }
-    }
 
-    return CPLStrdup(szSrsName);
+        if (eSRSNameFormat == SRSNAME_SHORT)
+        {
+            return CPLStrdup(
+                CPLSPrintf(" srsName=\"%s:%s\"", pszAuthName, pszAuthCode));
+        }
+        else if (eSRSNameFormat == SRSNAME_OGC_URN)
+        {
+            return CPLStrdup(CPLSPrintf(" srsName=\"urn:ogc:def:crs:%s::%s\"",
+                                        pszAuthName, pszAuthCode));
+        }
+        else if (eSRSNameFormat == SRSNAME_OGC_URL)
+        {
+            return CPLStrdup(CPLSPrintf(
+                " srsName=\"http://www.opengis.net/def/crs/%s/0/%s\"",
+                pszAuthName, pszAuthCode));
+        }
+    }
+    return CPLStrdup("");
 }
diff --git a/ogr/ogrsf_frmts/gml/gmlutils.h b/ogr/ogrsf_frmts/gml/gmlutils.h
index 3ea61a6..437cd81 100644
--- a/ogr/ogrsf_frmts/gml/gmlutils.h
+++ b/ogr/ogrsf_frmts/gml/gmlutils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gmlutils.h 35690 2016-10-11 09:56:31Z rouault $
+ * $Id: gmlutils.h 36158 2016-11-08 13:53:11Z rouault $
  *
  * Project:  GML Utils
  * Purpose:  GML reader
@@ -43,6 +43,13 @@ typedef enum
     GML_SWAP_NO,
 } GMLSwapCoordinatesEnum;
 
+typedef enum
+{
+    SRSNAME_SHORT,
+    SRSNAME_OGC_URN,
+    SRSNAME_OGC_URL
+} OGRGMLSRSNameFormat;
+
 const char* GML_ExtractSrsNameFromGeometry(const CPLXMLNode* const * papsGeometry,
                                      std::string& osWork,
                                      bool bConsiderEPSGAsURN);
@@ -62,6 +69,6 @@ OGRGeometry* GML_BuildOGRGeometryFromList(const CPLXMLNode* const * papsGeometry
                                           void* hCacheSRS,
                                           bool bFaceHoleNegative = false );
 
-char* GML_GetSRSName(const OGRSpatialReference* poSRS, bool bLongSRS, bool *pbCoordSwap);
+char* GML_GetSRSName(const OGRSpatialReference* poSRS, OGRGMLSRSNameFormat eSRSNameFormat, bool *pbCoordSwap);
 
 #endif /* _CPL_GMLREADERP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gml/hugefileresolver.cpp b/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
index 568c575..9c494c1 100644
--- a/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
+++ b/ogr/ogrsf_frmts/gml/hugefileresolver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: hugefileresolver.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader::HugeFileResolver() method.
@@ -35,34 +34,34 @@
  *
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlreader.h"
-#include "cpl_error.h"
-
 #include "gmlreaderp.h"
-#include "gmlutils.h"
+
+#include <algorithm>
+
 #include "cpl_conv.h"
-#include "ogr_p.h"
-#include "cpl_string.h"
+#include "cpl_error.h"
 #include "cpl_http.h"
+#include "cpl_string.h"
+#include "gmlutils.h"
+#include "ogr_p.h"
 
-#include <stack>
+#ifdef HAVE_SQLITE
+#include <sqlite3.h>
+#endif
 
-CPL_CVSID("$Id: hugefileresolver.cpp 33702 2016-03-11 06:20:16Z goatbar $");
+CPL_CVSID("$Id: hugefileresolver.cpp 37240 2017-01-29 21:35:59Z goatbar $");
 
 /****************************************************/
 /*      SQLite is absolutely required in order to   */
 /*      support the HUGE xlink:href resolver        */
 /****************************************************/
 
-#ifdef HAVE_SQLITE
-#include <sqlite3.h>
-#endif
-
-/* sqlite3_clear_bindings() isn't available in old versions of */
-/* sqlite3 */
+// sqlite3_clear_bindings() isn't available in old versions of sqlite3.
 #if defined(HAVE_SQLITE) && SQLITE_VERSION_NUMBER >= 3006000
 
-/* an internal helper struct supporting GML tags <Edge> */
+// Internal helper struct supporting GML tags <Edge>.
 struct huge_tag
 {
     CPLString           *gmlTagValue;
@@ -82,7 +81,7 @@ struct huge_tag
     struct huge_tag     *pNext;
 };
 
-/* an internal helper struct supporting GML tags xlink:href */
+// Internal helper struct supporting GML tags xlink:href.
 struct huge_href
 {
     CPLString           *gmlId;
@@ -94,7 +93,7 @@ struct huge_href
     struct huge_href    *pNext;
 };
 
-/* an internal helper struct supporting GML rewriting */
+// Internal struct supporting GML rewriting.
 struct huge_child
 {
     CPLXMLNode          *psChild;
@@ -102,7 +101,7 @@ struct huge_child
     struct huge_child   *pNext;
 };
 
-/* an internal helper struct supporting GML rewriting */
+// Internal struct supporting GML rewriting.
 struct huge_parent
 {
     CPLXMLNode          *psParent;
@@ -111,12 +110,22 @@ struct huge_parent
     struct huge_parent  *pNext;
 };
 
-/*
-/ an internal helper struct supporting GML
-/ resolver for Huge Files (based on SQLite)
-*/
-struct huge_helper
+// Internal class supporting GML resolver for Huge Files (based on SQLite).
+class huge_helper
 {
+  public:
+    huge_helper() :
+        hDB(NULL),
+        hNodes(NULL),
+        hEdges(NULL),
+        nodeSrs(NULL),
+        pFirst(NULL),
+        pLast(NULL),
+        pFirstHref(NULL),
+        pLastHref(NULL),
+        pFirstParent(NULL),
+        pLastParent(NULL)
+    {}
     sqlite3             *hDB;
     sqlite3_stmt        *hNodes;
     sqlite3_stmt        *hEdges;
@@ -129,90 +138,89 @@ struct huge_helper
     struct huge_parent  *pLastParent;
 };
 
-static bool gmlHugeFileSQLiteInit( struct huge_helper *helper )
+static bool gmlHugeFileSQLiteInit( huge_helper *helper )
 {
-/* attempting to create SQLite tables */
-    const char          *osCommand;
-    char                *pszErrMsg = NULL;
-    int                 rc;
-    sqlite3             *hDB = helper->hDB;
-    sqlite3_stmt        *hStmt;
-
-    /* DB table: NODES */
-    osCommand = "CREATE TABLE nodes ("
-                "     gml_id VARCHAR PRIMARY KEY, "
-                "     x DOUBLE, "
-                "     y DOUBLE, "
-                "     z DOUBLE)";
-    rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
+    // Attempting to create SQLite tables.
+    char *pszErrMsg = NULL;
+    sqlite3 *hDB = helper->hDB;
+
+    // DB table: NODES.
+    const char *osCommand =
+        "CREATE TABLE nodes ("
+        "     gml_id VARCHAR PRIMARY KEY, "
+        "     x DOUBLE, "
+        "     y DOUBLE, "
+        "     z DOUBLE)";
+    int rc = sqlite3_exec(hDB, osCommand, NULL, NULL, &pszErrMsg);
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to create table nodes: %s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to create table nodes: %s",
+                 pszErrMsg);
+        sqlite3_free(pszErrMsg);
         return false;
     }
 
-    /* DB table: GML_EDGES */
+    // DB table: GML_EDGES.
     osCommand = "CREATE TABLE gml_edges ("
                 "     gml_id VARCHAR PRIMARY KEY, "
                 "     gml_string BLOB, "
                 "     gml_resolved BLOB, "
-				"     node_from_id TEXT, "
+                "     node_from_id TEXT, "
                 "     node_from_x DOUBLE, "
                 "     node_from_y DOUBLE, "
                 "     node_from_z DOUBLE, "
-				"     node_to_id TEXT, "
+                "     node_to_id TEXT, "
                 "     node_to_x DOUBLE, "
                 "     node_to_y DOUBLE, "
                 "     node_to_z DOUBLE)";
-    rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
+    rc = sqlite3_exec(hDB, osCommand, NULL, NULL, &pszErrMsg);
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to create table gml_edges: %s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to create table gml_edges: %s",
+                 pszErrMsg);
+        sqlite3_free(pszErrMsg);
         return false;
     }
 
-    /* DB table: NODES / Insert cursor */
+    // DB table: NODES / Insert cursor.
     osCommand = "INSERT OR IGNORE INTO nodes (gml_id, x, y, z) "
                 "VALUES (?, ?, ?, ?)";
-    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hStmt, NULL );
+    sqlite3_stmt *hStmt = NULL;
+    rc = sqlite3_prepare_v2(hDB, osCommand, -1, &hStmt, NULL);
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to create INSERT stmt for: nodes" );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to create INSERT stmt for: nodes");
         return false;
     }
     helper->hNodes = hStmt;
 
-    /* DB table: GML_EDGES / Insert cursor */
+    // DB table: GML_EDGES / Insert cursor.
     osCommand = "INSERT INTO gml_edges "
                 "(gml_id, gml_string, gml_resolved, "
                 "node_from_id, node_from_x, node_from_y, "
                 "node_from_z, node_to_id, node_to_x, "
                 "node_to_y, node_to_z) "
                 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
-    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hStmt, NULL );
+    rc = sqlite3_prepare_v2(hDB, osCommand, -1, &hStmt, NULL);
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to create INSERT stmt for: gml_edges" );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to create INSERT stmt for: gml_edges");
         return false;
     }
     helper->hEdges = hStmt;
 
-    /* starting a TRANSACTION */
-    rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
+    // Starting a TRANSACTION.
+    rc = sqlite3_exec(hDB, "BEGIN", NULL, NULL, &pszErrMsg);
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to perform BEGIN TRANSACTION: %s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to perform BEGIN TRANSACTION: %s",
+                 pszErrMsg);
+        sqlite3_free(pszErrMsg);
         return false;
     }
 
@@ -220,28 +228,33 @@ static bool gmlHugeFileSQLiteInit( struct huge_helper *helper )
 }
 
 static bool gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
-                                    const char *pszFromId,
-                                    const char *pszToId )
+                                     const char *pszFromId,
+                                     const char *pszToId )
 {
-/* resolves an Edge definition */
-    CPLXMLNode      *psDirNode_1 = NULL;
-    CPLXMLNode      *psDirNode_2 = NULL;
-    CPLXMLNode      *psOldNode_1 = NULL;
-    CPLXMLNode      *psOldNode_2 = NULL;
-    CPLXMLNode      *psNewNode_1 = NULL;
-    CPLXMLNode      *psNewNode_2 = NULL;
-    int             iToBeReplaced = 0;
-    int             iReplaced = 0;
-    if( psNode->eType == CXT_Element && EQUAL( psNode->pszValue, "Edge" ) )
+    if( psNode->eType == CXT_Element && EQUAL(psNode->pszValue, "Edge") )
+    {
         ;
+    }
     else
+    {
         return false;
+    }
+
+    // Resolves an Edge definition.
+    CPLXMLNode *psDirNode_1 = NULL;
+    CPLXMLNode *psDirNode_2 = NULL;
+    CPLXMLNode *psOldNode_1 = NULL;
+    CPLXMLNode *psOldNode_2 = NULL;
+    CPLXMLNode *psNewNode_1 = NULL;
+    CPLXMLNode *psNewNode_2 = NULL;
+    int iToBeReplaced = 0;
+    int iReplaced = 0;
 
     CPLXMLNode *psChild = psNode->psChild;
     while( psChild != NULL )
     {
         if( psChild->eType == CXT_Element &&
-            EQUAL( psChild->pszValue, "directedNode" ) )
+            EQUAL(psChild->pszValue, "directedNode") )
         {
             char cOrientation = '+';
             CPLXMLNode *psOldNode = NULL;
@@ -249,10 +262,10 @@ static bool gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
             while( psAttr != NULL )
             {
                 if( psAttr->eType == CXT_Attribute &&
-                    EQUAL( psAttr->pszValue, "xlink:href" ) )
+                    EQUAL(psAttr->pszValue, "xlink:href") )
                     psOldNode = psAttr;
                 if( psAttr->eType == CXT_Attribute &&
-                    EQUAL( psAttr->pszValue, "orientation" ) )
+                    EQUAL(psAttr->pszValue, "orientation") )
                 {
                     const CPLXMLNode *psOrientation = psAttr->psChild;
                     if( psOrientation != NULL )
@@ -265,8 +278,10 @@ static bool gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
             }
             if( psOldNode != NULL )
             {
-                CPLXMLNode *psNewNode = CPLCreateXMLNode(NULL, CXT_Element, "Node");
-                CPLXMLNode *psGMLIdNode = CPLCreateXMLNode(psNewNode, CXT_Attribute, "gml:id");
+                CPLXMLNode *psNewNode =
+                    CPLCreateXMLNode(NULL, CXT_Element, "Node");
+                CPLXMLNode *psGMLIdNode =
+                    CPLCreateXMLNode(psNewNode, CXT_Attribute, "gml:id");
                 if( cOrientation == '-' )
                     CPLCreateXMLNode(psGMLIdNode, CXT_Text, pszFromId);
                 else
@@ -289,16 +304,16 @@ static bool gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
         psChild = psChild->psNext;
     }
 
-    /* rewriting the Edge GML definition */
+    // Rewriting the Edge GML definition.
     if( psDirNode_1 != NULL)
     {
         if( psOldNode_1 != NULL )
         {
-            CPLRemoveXMLChild( psDirNode_1, psOldNode_1 );
-            CPLDestroyXMLNode( psOldNode_1 );
+            CPLRemoveXMLChild(psDirNode_1, psOldNode_1);
+            CPLDestroyXMLNode(psOldNode_1);
             if( psNewNode_1 != NULL )
             {
-                CPLAddXMLChild( psDirNode_1, psNewNode_1 );
+                CPLAddXMLChild(psDirNode_1, psNewNode_1);
                 iReplaced++;
             }
         }
@@ -307,552 +322,610 @@ static bool gmlHugeResolveEdgeNodes( const CPLXMLNode *psNode,
     {
         if( psOldNode_2 != NULL )
         {
-            CPLRemoveXMLChild( psDirNode_2, psOldNode_2 );
-            CPLDestroyXMLNode( psOldNode_2 );
+            CPLRemoveXMLChild(psDirNode_2, psOldNode_2);
+            CPLDestroyXMLNode(psOldNode_2);
             if( psNewNode_2 != NULL )
             {
-                CPLAddXMLChild( psDirNode_2, psNewNode_2 );
+                CPLAddXMLChild(psDirNode_2, psNewNode_2);
                 iReplaced++;
             }
         }
     }
-    if( iToBeReplaced != iReplaced )
-        return false;
-    return true;
+
+    return iToBeReplaced == iReplaced;
 }
 
-static bool gmlHugeFileResolveEdges( struct huge_helper *helper )
+static bool gmlHugeFileResolveEdges( huge_helper *helper )
 {
-/* identifying any not yet resolved <Edge> GML string */
-    const char          *osCommand;
-    char                *pszErrMsg = NULL;
-    int rc;
-    sqlite3             *hDB = helper->hDB;
-    sqlite3_stmt        *hQueryStmt;
-    sqlite3_stmt        *hUpdateStmt;
-    int                 iCount = 0;
-    bool                bError = false;
-
-    /* query cursor */
-    osCommand = "SELECT e.gml_id, e.gml_string, e.node_from_id, "
-                "e.node_from_x, e.node_from_y, e.node_from_z, "
-                "n1.gml_id, n1.x, n1.y, n1.z, e.node_to_id, "
-                "e.node_to_x, e.node_to_y, e.node_to_z, "
-                "n2.gml_id, n2.x, n2.y, n2.z "
-                "FROM gml_edges AS e "
-                "LEFT JOIN nodes AS n1 ON (n1.gml_id = e.node_from_id) "
-                "LEFT JOIN nodes AS n2 ON (n2.gml_id = e.node_to_id)";
-    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hQueryStmt, NULL );
+    // Identifying any not yet resolved <Edge> GML string.
+    sqlite3 *hDB = helper->hDB;
+
+    // Query cursor.
+    const char *osCommand =
+        "SELECT e.gml_id, e.gml_string, e.node_from_id, "
+        "e.node_from_x, e.node_from_y, e.node_from_z, "
+        "n1.gml_id, n1.x, n1.y, n1.z, e.node_to_id, "
+        "e.node_to_x, e.node_to_y, e.node_to_z, "
+        "n2.gml_id, n2.x, n2.y, n2.z "
+        "FROM gml_edges AS e "
+        "LEFT JOIN nodes AS n1 ON (n1.gml_id = e.node_from_id) "
+        "LEFT JOIN nodes AS n2 ON (n2.gml_id = e.node_to_id)";
+    sqlite3_stmt *hQueryStmt = NULL;
+    int rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hQueryStmt, NULL );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to create QUERY stmt for Edge resolver" );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to create QUERY stmt for Edge resolver");
         return false;
     }
 
-    /* update cursor */
+    // Update cursor.
     osCommand = "UPDATE gml_edges "
                 "SET gml_resolved = ?, "
                 "gml_string = NULL "
                 "WHERE gml_id = ?";
-    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hUpdateStmt, NULL );
+    sqlite3_stmt *hUpdateStmt = NULL;
+    rc = sqlite3_prepare_v2(hDB, osCommand, -1, &hUpdateStmt, NULL);
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to create UPDATE stmt for resolved Edges" );
-        sqlite3_finalize ( hQueryStmt );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to create UPDATE stmt for resolved Edges");
+        sqlite3_finalize(hQueryStmt);
         return false;
     }
 
-    /* starting a TRANSACTION */
+    // Starting a TRANSACTION.
+    char *pszErrMsg = NULL;
     rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to perform BEGIN TRANSACTION: %s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
-        sqlite3_finalize ( hQueryStmt );
-        sqlite3_finalize ( hUpdateStmt );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to perform BEGIN TRANSACTION: %s", pszErrMsg);
+        sqlite3_free(pszErrMsg);
+        sqlite3_finalize(hQueryStmt);
+        sqlite3_finalize(hUpdateStmt);
         return false;
     }
 
-    /* looping on the QUERY result-set */
+    int iCount = 0;
+    bool bError = false;
+
+    // Looping on the QUERY result-set.
     while( true )
     {
-        const char      *pszGmlId;
-        const char      *pszGmlString = NULL;
-        int             bIsGmlStringNull;
-        const char      *pszFromId = NULL;
-        int             bIsFromIdNull;
-        double          xFrom = 0.0;
-        int             bIsXFromNull;
-        double          yFrom = 0.0;
-        int             bIsYFromNull;
-        double          zFrom = 0.0;
-        int             bIsZFromNull;
-        /* const char      *pszNodeFromId = NULL; */
-        int             bIsNodeFromIdNull;
-        double          xNodeFrom = 0.0;
-        int             bIsXNodeFromNull;
-        double          yNodeFrom = 0.0;
-        int             bIsYNodeFromNull;
-        double          zNodeFrom = 0.0;
-        int             bIsZNodeFromNull;
-        const char      *pszToId = NULL;
-        bool            bIsToIdNull;
-        double          xTo = 0.0;
-        bool            bIsXToNull;
-        double          yTo = 0.0;
-        bool            bIsYToNull;
-        double          zTo = 0.0;
-        bool            bIsZToNull;
-        /* const char      *pszNodeToId = NULL; */
-        bool            bIsNodeToIdNull;
-        double          xNodeTo = 0.0;
-        bool            bIsXNodeToNull;
-        double          yNodeTo = 0.0;
-        bool            bIsYNodeToNull;
-        double          zNodeTo = 0.0;
-        bool            bIsZNodeToNull;
-
-        rc = sqlite3_step( hQueryStmt );
+        const char *pszGmlId = NULL;
+        const char *pszGmlString = NULL;
+        bool bIsGmlStringNull = false;
+        const char *pszFromId = NULL;
+        bool bIsFromIdNull = false;
+        double xFrom = 0.0;
+        bool bIsXFromNull = false;
+        double yFrom = 0.0;
+        bool bIsYFromNull = false;
+        double zFrom = 0.0;
+        bool bIsZFromNull = false;
+        // const char *pszNodeFromId = NULL;
+        bool bIsNodeFromIdNull = false;
+        double xNodeFrom = 0.0;
+        bool bIsXNodeFromNull = false;
+        double yNodeFrom = 0.0;
+        bool bIsYNodeFromNull = false;
+        double zNodeFrom = 0.0;
+        bool bIsZNodeFromNull = false;
+        const char *pszToId = NULL;
+        bool bIsToIdNull = false;
+        double xTo = 0.0;
+        bool bIsXToNull = false;
+        double yTo = 0.0;
+        bool bIsYToNull = false;
+        double zTo = 0.0;
+        bool bIsZToNull = false;
+        // const char *pszNodeToId = NULL;
+        bool bIsNodeToIdNull = false;
+        double xNodeTo = 0.0;
+        bool bIsXNodeToNull = false;
+        double yNodeTo = 0.0;
+        bool bIsYNodeToNull = false;
+        double zNodeTo = 0.0;
+        bool bIsZNodeToNull = false;
+
+        rc = sqlite3_step(hQueryStmt);
         if( rc == SQLITE_DONE )
             break;
-        else if( rc == SQLITE_ROW )
+
+        if( rc == SQLITE_ROW )
         {
             bError = false;
-            pszGmlId = (const char *) sqlite3_column_text( hQueryStmt, 0 );
-            if( sqlite3_column_type( hQueryStmt, 1 ) == SQLITE_NULL )
+            pszGmlId = reinterpret_cast<const char *>(
+                sqlite3_column_text(hQueryStmt, 0));
+            if( sqlite3_column_type(hQueryStmt, 1) == SQLITE_NULL )
+            {
                 bIsGmlStringNull = true;
+            }
             else
             {
-                pszGmlString = (const char *) sqlite3_column_blob( hQueryStmt, 1 );
+                pszGmlString = static_cast<const char *>(
+                    sqlite3_column_blob(hQueryStmt, 1));
                 bIsGmlStringNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 2 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 2) == SQLITE_NULL )
+            {
                 bIsFromIdNull = true;
+            }
             else
             {
-                pszFromId = (const char *) sqlite3_column_text( hQueryStmt, 2 );
+                pszFromId = reinterpret_cast<const char *>(
+                    sqlite3_column_text(hQueryStmt, 2));
                 bIsFromIdNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 3 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 3) == SQLITE_NULL )
+            {
                 bIsXFromNull = true;
+            }
             else
             {
-                xFrom = sqlite3_column_double( hQueryStmt, 3 );
+                xFrom = sqlite3_column_double(hQueryStmt, 3);
                 bIsXFromNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 4 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 4) == SQLITE_NULL )
+            {
                 bIsYFromNull = true;
+            }
             else
             {
-                yFrom = sqlite3_column_double( hQueryStmt, 4 );
+                yFrom = sqlite3_column_double(hQueryStmt, 4);
                 bIsYFromNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 5 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 5) == SQLITE_NULL )
+            {
                 bIsZFromNull = true;
+            }
             else
             {
-                zFrom = sqlite3_column_double( hQueryStmt, 5 );
+                zFrom = sqlite3_column_double(hQueryStmt, 5);
                 bIsZFromNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 6 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 6) == SQLITE_NULL )
+            {
                 bIsNodeFromIdNull = true;
+            }
             else
             {
-                /* TODO: Can sqlite3_column_text be removed? */
-                /* pszNodeFromId = (const char *) */ sqlite3_column_text( hQueryStmt, 6 );
+                // TODO: Can sqlite3_column_text be removed?
+                // pszNodeFromId = (const char *)
+                sqlite3_column_text(hQueryStmt, 6);
                 bIsNodeFromIdNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 7 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 7) == SQLITE_NULL )
+            {
                 bIsXNodeFromNull = true;
+            }
             else
             {
-                xNodeFrom = sqlite3_column_double( hQueryStmt, 7 );
+                xNodeFrom = sqlite3_column_double(hQueryStmt, 7);
                 bIsXNodeFromNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 8 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 8) == SQLITE_NULL )
+            {
                 bIsYNodeFromNull = true;
+            }
             else
             {
-                yNodeFrom = sqlite3_column_double( hQueryStmt, 8 );
+                yNodeFrom = sqlite3_column_double(hQueryStmt, 8);
                 bIsYNodeFromNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 9 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 9) == SQLITE_NULL )
+            {
                 bIsZNodeFromNull = true;
+            }
             else
             {
-                zNodeFrom = sqlite3_column_double( hQueryStmt, 9 );
+                zNodeFrom = sqlite3_column_double(hQueryStmt, 9);
                 bIsZNodeFromNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 10 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 10) == SQLITE_NULL )
+            {
                 bIsToIdNull = true;
+            }
             else
             {
-                pszToId = (const char *) sqlite3_column_text( hQueryStmt, 10 );
+                pszToId = reinterpret_cast<const char *>(
+                    sqlite3_column_text(hQueryStmt, 10));
                 bIsToIdNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 11 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 11) == SQLITE_NULL )
+            {
                 bIsXToNull = true;
+            }
             else
             {
-                xTo = sqlite3_column_double( hQueryStmt, 11 );
+                xTo = sqlite3_column_double(hQueryStmt, 11);
                 bIsXToNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 12 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 12) == SQLITE_NULL )
+            {
                 bIsYToNull = true;
+            }
             else
             {
-                yTo = sqlite3_column_double( hQueryStmt, 12 );
+                yTo = sqlite3_column_double(hQueryStmt, 12);
                 bIsYToNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 13 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 13) == SQLITE_NULL )
+            {
                 bIsZToNull = true;
+            }
             else
             {
-                zTo = sqlite3_column_double( hQueryStmt, 13 );
+                zTo = sqlite3_column_double(hQueryStmt, 13);
                 bIsZToNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 14 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 14) == SQLITE_NULL )
+            {
                 bIsNodeToIdNull = true;
+            }
             else
             {
-                /* TODO: Can sqlite3_column_text be removed? */
-                /* pszNodeToId = (const char *) */ sqlite3_column_text( hQueryStmt, 14 );
+                // TODO: Can sqlite3_column_text be removed?
+                // pszNodeToId = (const char *)
+                sqlite3_column_text(hQueryStmt, 14);
                 bIsNodeToIdNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 15 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 15) == SQLITE_NULL )
+            {
                 bIsXNodeToNull = true;
+            }
             else
             {
-                xNodeTo = sqlite3_column_double( hQueryStmt, 15 );
+                xNodeTo = sqlite3_column_double(hQueryStmt, 15);
                 bIsXNodeToNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 16 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 16) == SQLITE_NULL )
+            {
                 bIsYNodeToNull = true;
+            }
             else
             {
-                yNodeTo = sqlite3_column_double( hQueryStmt, 16 );
+                yNodeTo = sqlite3_column_double(hQueryStmt, 16);
                 bIsYNodeToNull = false;
             }
-            if( sqlite3_column_type( hQueryStmt, 17 ) == SQLITE_NULL )
+            if( sqlite3_column_type(hQueryStmt, 17) == SQLITE_NULL )
+            {
                 bIsZNodeToNull = true;
+            }
             else
             {
-                zNodeTo = sqlite3_column_double( hQueryStmt, 17 );
+                zNodeTo = sqlite3_column_double(hQueryStmt, 17);
                 bIsZNodeToNull = false;
             }
 
-            /* checking for consistency */
-            if( bIsFromIdNull || bIsXFromNull  || bIsYFromNull  )
+            // Checking for consistency.
+            if( bIsFromIdNull || bIsXFromNull || bIsYFromNull )
             {
                 bError = true;
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Edge gml:id=\"%s\": invalid Node-from",
-                          pszGmlId );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Edge gml:id=\"%s\": invalid Node-from",
+                         pszGmlId);
             }
             else
             {
                 if( bIsNodeFromIdNull )
                 {
                     bError = true;
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"",
-                              pszGmlId, pszFromId );
+                    CPLError(
+                        CE_Failure, CPLE_AppDefined,
+                        "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"",
+                        pszGmlId, pszFromId);
                 }
                 else if( bIsXNodeFromNull || bIsYNodeFromNull )
                 {
                     bError = true;
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"",
-                              pszGmlId, pszFromId );
+                    CPLError(
+                        CE_Failure, CPLE_AppDefined,
+                        "Edge gml:id=\"%s\": "
+                        "unknown coords for Node gml:id=\"%s\"",
+                        pszGmlId, pszFromId);
                 }
                 else if( xFrom != xNodeFrom || yFrom != yNodeFrom )
                 {
                     bError = true;
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"",
-                              pszGmlId, pszFromId );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Edge gml:id=\"%s\": mismatching coords for Node "
+                             "gml:id=\"%s\"",
+                             pszGmlId, pszFromId);
                 }
                 else
                 {
                     if( bIsZFromNull && bIsZNodeFromNull )
-;
-                    else if( bIsZFromNull || bIsZNodeFromNull  )
+                    {
+                        ;
+                    }
+                    else if( bIsZFromNull || bIsZNodeFromNull )
                     {
                         bError = true;
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"",
-                                  pszGmlId, pszFromId );
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Edge gml:id=\"%s\": mismatching 2D/3D for "
+                                 "Node gml:id=\"%s\"",
+                                 pszGmlId, pszFromId);
                     }
                     else if( zFrom != zNodeFrom )
                     {
                         bError = true;
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"",
-                                  pszGmlId, pszFromId );
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Edge gml:id=\"%s\": mismatching Z coord for "
+                                 "Node gml:id=\"%s\"",
+                                 pszGmlId, pszFromId);
                     }
                 }
             }
             if( bIsToIdNull || bIsXToNull || bIsYToNull )
             {
                 bError = true;
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Edge gml:id=\"%s\": invalid Node-to",
-                          pszGmlId );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Edge gml:id=\"%s\": invalid Node-to",
+                         pszGmlId);
             }
             else
             {
                 if( bIsNodeToIdNull )
                 {
                     bError = true;
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"",
-                              pszGmlId, pszToId );
+                    CPLError(
+                        CE_Failure, CPLE_AppDefined,
+                        "Edge gml:id=\"%s\": undeclared Node gml:id=\"%s\"",
+                        pszGmlId, pszToId);
                 }
                 else if( bIsXNodeToNull  || bIsYNodeToNull )
                 {
                     bError = true;
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Edge gml:id=\"%s\": unknown coords for Node gml:id=\"%s\"",
-                              pszGmlId, pszToId );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Edge gml:id=\"%s\": "
+                             "unknown coords for Node gml:id=\"%s\"",
+                             pszGmlId, pszToId);
                 }
                 else if( xTo != xNodeTo || yTo != yNodeTo )
                 {
                     bError = true;
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Edge gml:id=\"%s\": mismatching coords for Node gml:id=\"%s\"",
-                              pszGmlId, pszToId );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Edge gml:id=\"%s\": mismatching coords for Node "
+                             "gml:id=\"%s\"",
+                             pszGmlId, pszToId);
                 }
                 else
                 {
                     if( bIsZToNull && bIsZNodeToNull )
-;
-                    else if(  bIsZToNull || bIsZNodeToNull )
+                    {
+                        ;
+                    }
+                    else if( bIsZToNull || bIsZNodeToNull )
                     {
                         bError = true;
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Edge gml:id=\"%s\": mismatching 2D/3D for Node gml:id=\"%s\"",
-                                  pszGmlId, pszToId );
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Edge gml:id=\"%s\": mismatching 2D/3D for "
+                                 "Node gml:id=\"%s\"",
+                                 pszGmlId, pszToId);
                     }
                     else if( zTo != zNodeTo )
                     {
                         bError = true;
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Edge gml:id=\"%s\": mismatching Z coord for Node gml:id=\"%s\"",
-                                  pszGmlId, pszToId );
+                        CPLError(CE_Failure, CPLE_AppDefined,
+                                 "Edge gml:id=\"%s\": mismatching Z coord for "
+                                 "Node gml:id=\"%s\"",
+                                 pszGmlId, pszToId);
                     }
                 }
             }
 
-            /* updating the resolved Node */
+            // Updating the resolved Node.
             if( bError == false && bIsGmlStringNull == false &&
                 bIsFromIdNull == false && bIsToIdNull == false )
             {
-                CPLXMLNode *psNode = CPLParseXMLString( pszGmlString );
+                CPLXMLNode *psNode = CPLParseXMLString(pszGmlString);
                 if( psNode != NULL )
                 {
-                    if( gmlHugeResolveEdgeNodes( psNode, pszFromId,
-                                                 pszToId ) )
+                    if( gmlHugeResolveEdgeNodes(psNode, pszFromId, pszToId) )
                     {
-                        char * gmlText = CPLSerializeXMLTree(psNode);
-                        sqlite3_reset ( hUpdateStmt );
-                        sqlite3_clear_bindings ( hUpdateStmt );
-                        sqlite3_bind_blob( hUpdateStmt, 1, gmlText,
-                                           (int)strlen(gmlText), SQLITE_STATIC );
-                        sqlite3_bind_text( hUpdateStmt, 2, pszGmlId, -1,
-                                           SQLITE_STATIC );
-                        rc = sqlite3_step( hUpdateStmt );
+                        char *gmlText = CPLSerializeXMLTree(psNode);
+                        sqlite3_reset(hUpdateStmt);
+                        sqlite3_clear_bindings(hUpdateStmt);
+                        sqlite3_bind_blob(hUpdateStmt, 1, gmlText,
+                                          static_cast<int>(strlen(gmlText)),
+                                          SQLITE_STATIC);
+                        sqlite3_bind_text(hUpdateStmt, 2, pszGmlId, -1,
+                                          SQLITE_STATIC);
+                        rc = sqlite3_step(hUpdateStmt);
                         if( rc != SQLITE_OK && rc != SQLITE_DONE )
                         {
-                            CPLError( CE_Failure, CPLE_AppDefined,
-                                      "UPDATE resolved Edge \"%s\" "
-                                      "sqlite3_step() failed:\n  %s",
-                                      pszGmlId, sqlite3_errmsg(hDB) );
+                            CPLError(CE_Failure, CPLE_AppDefined,
+                                     "UPDATE resolved Edge \"%s\" "
+                                     "sqlite3_step() failed:\n  %s",
+                                     pszGmlId, sqlite3_errmsg(hDB));
                         }
-                        CPLFree( gmlText );
+                        CPLFree(gmlText);
                         iCount++;
                         if( (iCount % 1024) == 1023 )
                         {
-                            /* committing the current TRANSACTION */
-                            rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL,
-                                               &pszErrMsg );
+                            // Committing the current TRANSACTION.
+                            rc = sqlite3_exec(hDB, "COMMIT", NULL, NULL,
+                                              &pszErrMsg);
                             if( rc != SQLITE_OK )
                             {
-                                CPLError( CE_Failure, CPLE_AppDefined,
-                                          "Unable to perform COMMIT TRANSACTION: %s",
-                                          pszErrMsg );
-                                sqlite3_free( pszErrMsg );
+                                CPLError(
+                                    CE_Failure, CPLE_AppDefined,
+                                    "Unable to perform COMMIT TRANSACTION: %s",
+                                    pszErrMsg);
+                                sqlite3_free(pszErrMsg);
                                 return false;
                             }
-                            /* restarting a new TRANSACTION */
-                            rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, &pszErrMsg );
+                            // Restarting a new TRANSACTION.
+                            rc = sqlite3_exec(hDB, "BEGIN", NULL, NULL,
+                                              &pszErrMsg);
                             if( rc != SQLITE_OK )
                             {
-                                CPLError( CE_Failure, CPLE_AppDefined,
-                                          "Unable to perform BEGIN TRANSACTION: %s",
-                                          pszErrMsg );
-                                sqlite3_free( pszErrMsg );
-                                sqlite3_finalize ( hQueryStmt );
-                                sqlite3_finalize ( hUpdateStmt );
+                                CPLError(
+                                    CE_Failure, CPLE_AppDefined,
+                                    "Unable to perform BEGIN TRANSACTION: %s",
+                                    pszErrMsg);
+                                sqlite3_free(pszErrMsg);
+                                sqlite3_finalize(hQueryStmt);
+                                sqlite3_finalize(hUpdateStmt);
                                 return false;
                             }
                         }
                     }
-                    CPLDestroyXMLNode( psNode );
+                    CPLDestroyXMLNode(psNode);
                 }
             }
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Edge resolver QUERY: sqlite3_step(%s)",
-                      sqlite3_errmsg(hDB) );
-            sqlite3_finalize ( hQueryStmt );
-            sqlite3_finalize ( hUpdateStmt );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Edge resolver QUERY: sqlite3_step(%s)",
+                     sqlite3_errmsg(hDB));
+            sqlite3_finalize(hQueryStmt);
+            sqlite3_finalize(hUpdateStmt);
             return false;
         }
     }
-    sqlite3_finalize ( hQueryStmt );
-    sqlite3_finalize ( hUpdateStmt );
+    sqlite3_finalize(hQueryStmt);
+    sqlite3_finalize(hUpdateStmt);
 
-    /* committing the current TRANSACTION */
-    rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
+    // Committing the current TRANSACTION.
+    rc = sqlite3_exec(hDB, "COMMIT", NULL, NULL, &pszErrMsg);
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to perform COMMIT TRANSACTION: %s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to perform COMMIT TRANSACTION: %s",
+                 pszErrMsg);
+        sqlite3_free(pszErrMsg);
         return false;
     }
-    if( bError )
-        return false;
-    return true;
+
+    return !bError;
 }
 
-static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
+static bool gmlHugeFileSQLiteInsert( huge_helper *helper )
 {
-/* inserting any appropriate row into the SQLite DB */
-    int rc;
-    struct huge_tag *pItem;
+    // Inserting any appropriate row into the SQLite DB.
 
-    /* looping on GML tags */
-    pItem = helper->pFirst;
+    // Looping on GML tags.
+    struct huge_tag *pItem = helper->pFirst;
     while ( pItem != NULL )
     {
         if( pItem->bHasCoords )
         {
             if( pItem->gmlNodeFrom != NULL )
             {
-                sqlite3_reset ( helper->hNodes );
-                sqlite3_clear_bindings ( helper->hNodes );
-                sqlite3_bind_text( helper->hNodes, 1,
-                                   pItem->gmlNodeFrom->c_str(), -1,
-                                   SQLITE_STATIC );
-                sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeFrom );
-                sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeFrom );
-                if( pItem->bHasZ )
-                    sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeFrom );
-                sqlite3_bind_null ( helper->hNodes, 5 );
-                rc = sqlite3_step( helper->hNodes );
+                sqlite3_reset(helper->hNodes);
+                sqlite3_clear_bindings(helper->hNodes);
+                sqlite3_bind_text(helper->hNodes, 1,
+                                  pItem->gmlNodeFrom->c_str(), -1,
+                                  SQLITE_STATIC);
+                sqlite3_bind_double(helper->hNodes, 2, pItem->xNodeFrom);
+                sqlite3_bind_double(helper->hNodes, 3, pItem->yNodeFrom);
+                if(pItem->bHasZ)
+                    sqlite3_bind_double(helper->hNodes, 4, pItem->zNodeFrom);
+                sqlite3_bind_null(helper->hNodes, 5);
+                const int rc = sqlite3_step(helper->hNodes);
                 if( rc != SQLITE_OK && rc != SQLITE_DONE )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "sqlite3_step() failed:\n  %s (gmlNodeFrom id=%s)",
-                              sqlite3_errmsg(helper->hDB), pItem->gmlNodeFrom->c_str() );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "sqlite3_step() failed:\n  %s (gmlNodeFrom id=%s)",
+                             sqlite3_errmsg(helper->hDB),
+                             pItem->gmlNodeFrom->c_str());
                     return false;
                 }
             }
             if( pItem->gmlNodeTo != NULL )
             {
-                sqlite3_reset ( helper->hNodes );
-                sqlite3_clear_bindings ( helper->hNodes );
-                sqlite3_bind_text( helper->hNodes, 1, pItem->gmlNodeTo->c_str(),
-                                   -1, SQLITE_STATIC );
-                sqlite3_bind_double ( helper->hNodes, 2, pItem->xNodeTo );
-                sqlite3_bind_double ( helper->hNodes, 3, pItem->yNodeTo );
-                if ( pItem->bHasZ )
-                    sqlite3_bind_double ( helper->hNodes, 4, pItem->zNodeTo );
-                sqlite3_bind_null ( helper->hNodes, 5 );
-                rc = sqlite3_step( helper->hNodes );
+                sqlite3_reset(helper->hNodes);
+                sqlite3_clear_bindings(helper->hNodes);
+                sqlite3_bind_text(helper->hNodes, 1, pItem->gmlNodeTo->c_str(),
+                                  -1, SQLITE_STATIC);
+                sqlite3_bind_double(helper->hNodes, 2, pItem->xNodeTo);
+                sqlite3_bind_double(helper->hNodes, 3, pItem->yNodeTo);
+                if(pItem->bHasZ)
+                    sqlite3_bind_double(helper->hNodes, 4, pItem->zNodeTo);
+                sqlite3_bind_null(helper->hNodes, 5);
+                const int rc = sqlite3_step(helper->hNodes);
                 if( rc != SQLITE_OK && rc != SQLITE_DONE )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "sqlite3_step() failed:\n  %s (gmlNodeTo id=%s)",
-                              sqlite3_errmsg(helper->hDB), pItem->gmlNodeTo->c_str() );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "sqlite3_step() failed:\n  %s (gmlNodeTo id=%s)",
+                             sqlite3_errmsg(helper->hDB),
+                             pItem->gmlNodeTo->c_str());
                     return false;
                 }
             }
         }
 
-        /* gml:id */
-        sqlite3_reset( helper->hEdges );
-        sqlite3_clear_bindings( helper->hEdges );
-        sqlite3_bind_text( helper->hEdges, 1, pItem->gmlId->c_str(), -1,
-                           SQLITE_STATIC );
+        // gml:id
+        sqlite3_reset(helper->hEdges);
+        sqlite3_clear_bindings(helper->hEdges);
+        sqlite3_bind_text(helper->hEdges, 1, pItem->gmlId->c_str(), -1,
+                          SQLITE_STATIC);
         if( pItem->bIsNodeFromHref == false && pItem->bIsNodeToHref == false )
         {
-            sqlite3_bind_null( helper->hEdges, 2 );
-            sqlite3_bind_blob( helper->hEdges, 3, pItem->gmlTagValue->c_str(),
-                               (int)strlen( pItem->gmlTagValue->c_str() ),
-                               SQLITE_STATIC );
+            sqlite3_bind_null(helper->hEdges, 2);
+            sqlite3_bind_blob(
+                helper->hEdges, 3, pItem->gmlTagValue->c_str(),
+                static_cast<int>(strlen(pItem->gmlTagValue->c_str())),
+                SQLITE_STATIC);
         }
         else
         {
-            sqlite3_bind_blob( helper->hEdges, 2, pItem->gmlTagValue->c_str(),
-                               (int)strlen( pItem->gmlTagValue->c_str() ),
-                               SQLITE_STATIC );
-            sqlite3_bind_null( helper->hEdges, 3 );
+            sqlite3_bind_blob(
+                helper->hEdges, 2, pItem->gmlTagValue->c_str(),
+                static_cast<int>(strlen(pItem->gmlTagValue->c_str())),
+                SQLITE_STATIC);
+            sqlite3_bind_null(helper->hEdges, 3);
         }
         if( pItem->gmlNodeFrom != NULL )
-            sqlite3_bind_text( helper->hEdges, 4, pItem->gmlNodeFrom->c_str(),
-                               -1, SQLITE_STATIC );
+            sqlite3_bind_text(helper->hEdges, 4, pItem->gmlNodeFrom->c_str(),
+                              -1, SQLITE_STATIC);
         else
-            sqlite3_bind_null( helper->hEdges, 4 );
+            sqlite3_bind_null(helper->hEdges, 4);
         if( pItem->bHasCoords )
         {
-            sqlite3_bind_double( helper->hEdges, 5, pItem->xNodeFrom );
-            sqlite3_bind_double( helper->hEdges, 6, pItem->yNodeFrom );
+            sqlite3_bind_double(helper->hEdges, 5, pItem->xNodeFrom);
+            sqlite3_bind_double(helper->hEdges, 6, pItem->yNodeFrom);
             if( pItem->bHasZ )
-                sqlite3_bind_double( helper->hEdges, 7, pItem->zNodeFrom );
+                sqlite3_bind_double(helper->hEdges, 7, pItem->zNodeFrom);
             else
-                sqlite3_bind_null( helper->hEdges, 7 );
+                sqlite3_bind_null(helper->hEdges, 7);
         }
         else
         {
-            sqlite3_bind_null( helper->hEdges, 5 );
-            sqlite3_bind_null( helper->hEdges, 6 );
-            sqlite3_bind_null( helper->hEdges, 7 );
+            sqlite3_bind_null(helper->hEdges, 5);
+            sqlite3_bind_null(helper->hEdges, 6);
+            sqlite3_bind_null(helper->hEdges, 7);
         }
         if( pItem->gmlNodeTo != NULL )
-            sqlite3_bind_text( helper->hEdges, 8, pItem->gmlNodeTo->c_str(),
-                               -1, SQLITE_STATIC );
+            sqlite3_bind_text(helper->hEdges, 8, pItem->gmlNodeTo->c_str(), -1,
+                              SQLITE_STATIC);
         else
-            sqlite3_bind_null( helper->hEdges, 8 );
+            sqlite3_bind_null(helper->hEdges, 8);
         if( pItem->bHasCoords )
         {
-            sqlite3_bind_double( helper->hEdges, 9, pItem->xNodeTo );
-            sqlite3_bind_double( helper->hEdges, 10, pItem->yNodeTo );
+            sqlite3_bind_double(helper->hEdges, 9, pItem->xNodeTo);
+            sqlite3_bind_double(helper->hEdges, 10, pItem->yNodeTo);
             if( pItem->bHasZ )
-                sqlite3_bind_double( helper->hEdges, 11, pItem->zNodeTo );
+                sqlite3_bind_double(helper->hEdges, 11, pItem->zNodeTo);
             else
-                sqlite3_bind_null( helper->hEdges, 11 );
+                sqlite3_bind_null(helper->hEdges, 11);
         }
         else
         {
-            sqlite3_bind_null( helper->hEdges, 9 );
-            sqlite3_bind_null( helper->hEdges, 10 );
-            sqlite3_bind_null( helper->hEdges, 11 );
+            sqlite3_bind_null(helper->hEdges, 9);
+            sqlite3_bind_null(helper->hEdges, 10);
+            sqlite3_bind_null(helper->hEdges, 11);
         }
-        rc = sqlite3_step( helper->hEdges );
+        const int rc = sqlite3_step(helper->hEdges);
         if( rc != SQLITE_OK && rc != SQLITE_DONE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "sqlite3_step() failed:\n  %s (edge gml:id=%s)",
-                      sqlite3_errmsg(helper->hDB), pItem->gmlId->c_str() );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "sqlite3_step() failed:\n  %s (edge gml:id=%s)",
+                     sqlite3_errmsg(helper->hDB), pItem->gmlId->c_str());
             return false;
         }
         pItem = pItem->pNext;
@@ -860,16 +933,15 @@ static int gmlHugeFileSQLiteInsert( struct huge_helper *helper )
     return true;
 }
 
-static void gmlHugeFileReset( struct huge_helper *helper )
+static void gmlHugeFileReset( huge_helper *helper )
 {
-/* resetting an empty helper struct */
-    struct huge_tag *pNext;
+    // Resetting an empty helper struct.
     struct huge_tag *p = helper->pFirst;
 
-    /* cleaning any previous item */
+    // Cleaning any previous item.
     while( p != NULL )
     {
-        pNext = p->pNext;
+        struct huge_tag *pNext = p->pNext;
         if( p->gmlTagValue != NULL )
             delete p->gmlTagValue;
         if( p->gmlId != NULL )
@@ -885,16 +957,15 @@ static void gmlHugeFileReset( struct huge_helper *helper )
     helper->pLast = NULL;
 }
 
-static void gmlHugeFileHrefReset( struct huge_helper *helper )
+static void gmlHugeFileHrefReset( huge_helper *helper )
 {
-/* resetting an empty helper struct */
-    struct huge_href *pNext;
+    // Resetting an empty helper struct.
     struct huge_href *p = helper->pFirstHref;
 
-    /* cleaning any previous item */
+    // Cleaning any previous item.
     while( p != NULL )
     {
-        pNext = p->pNext;
+        struct huge_href *pNext = p->pNext;
         if( p->gmlId != NULL )
             delete p->gmlId;
         if( p->gmlText != NULL )
@@ -906,42 +977,39 @@ static void gmlHugeFileHrefReset( struct huge_helper *helper )
     helper->pLastHref = NULL;
 }
 
-static int gmlHugeFileHrefCheck( struct huge_helper *helper )
+static int gmlHugeFileHrefCheck( huge_helper *helper )
 {
-/* testing for unresolved items */
-    int bError = false;
-	struct huge_href *p = helper->pFirstHref;
-	while( p != NULL )
+    // Testing for unresolved items.
+    bool bError = false;
+    struct huge_href *p = helper->pFirstHref;
+    while( p != NULL )
     {
-		if( p->gmlText == NULL)
-		{
-			bError = true;
-			CPLError( CE_Failure, CPLE_AppDefined,
-                      "Edge xlink:href\"%s\": unresolved match",
-                      p->gmlId->c_str() );
-		}
+        if( p->gmlText == NULL)
+        {
+            bError = true;
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Edge xlink:href\"%s\": unresolved match",
+                     p->gmlId->c_str());
+        }
         p = p->pNext;
     }
-	if( bError )
-		return false;
-	return true;
+
+    return !bError;
 }
 
-static void gmlHugeFileRewiterReset( struct huge_helper *helper )
+static void gmlHugeFileRewiterReset( huge_helper *helper )
 {
-/* resetting an empty helper struct */
-    struct huge_parent *pNext;
+    // Resetting an empty helper struct.
     struct huge_parent *p = helper->pFirstParent;
 
-    /* cleaning any previous item */
+    // Cleaning any previous item.
     while( p != NULL )
     {
-        pNext = p->pNext;
-        struct huge_child *pChildNext;
+        struct huge_parent *pNext = p->pNext;
         struct huge_child *pChild = p->pFirst;
         while( pChild != NULL )
         {
-            pChildNext = pChild->pNext;
+            struct huge_child *pChildNext = pChild->pNext;
             delete pChild;
             pChild = pChildNext;
         }
@@ -952,18 +1020,17 @@ static void gmlHugeFileRewiterReset( struct huge_helper *helper )
     helper->pLastParent = NULL;
 }
 
-static struct huge_tag *gmlHugeAddToHelper( struct huge_helper *helper,
+static struct huge_tag *gmlHugeAddToHelper( huge_helper *helper,
                                             CPLString *gmlId,
                                             CPLString *gmlFragment )
 {
-/* adding an item  into the linked list */
-    struct huge_tag *pItem;
+    // Adding an item into the linked list.
 
-    /* checking against duplicates */
-    pItem = helper->pFirst;
+    // Checking against duplicates.
+    struct huge_tag *pItem = helper->pFirst;
     while( pItem != NULL )
     {
-        if( EQUAL( pItem->gmlId->c_str(), gmlId->c_str() ) )
+        if( EQUAL(pItem->gmlId->c_str(), gmlId->c_str()) )
             return NULL;
         pItem = pItem->pNext;
     }
@@ -979,7 +1046,7 @@ static struct huge_tag *gmlHugeAddToHelper( struct huge_helper *helper,
     pItem->bHasZ = false;
     pItem->pNext = NULL;
 
-    /* appending the item to the linked list */
+    // Appending the item to the linked list.
     if ( helper->pFirst == NULL )
         helper->pFirst = pItem;
     if ( helper->pLast != NULL )
@@ -988,30 +1055,29 @@ static struct huge_tag *gmlHugeAddToHelper( struct huge_helper *helper,
     return pItem;
 }
 
-static void gmlHugeAddPendingToHelper( struct huge_helper *helper,
+static void gmlHugeAddPendingToHelper( huge_helper *helper,
                                        CPLString *gmlId,
                                        const CPLXMLNode *psParent,
                                        const CPLXMLNode *psNode,
                                        bool bIsDirectedEdge,
                                        char cOrientation )
 {
-/* inserting an item into the linked list */
-    struct huge_href *pItem;
+    // Inserting an item into the linked list.
 
-    /* checking against duplicates */
-    pItem = helper->pFirstHref;
+    // Checking against duplicates.
+    struct huge_href *pItem = helper->pFirstHref;
     while( pItem != NULL )
     {
-        if( EQUAL( pItem->gmlId->c_str(), gmlId->c_str() ) &&
+        if( EQUAL(pItem->gmlId->c_str(), gmlId->c_str()) &&
             pItem->psParent == psParent  &&
             pItem->psNode == psNode &&
             pItem->cOrientation == cOrientation &&
             pItem->bIsDirectedEdge == bIsDirectedEdge )
-            {
-                delete gmlId;
-                return;
-            }
-            pItem = pItem->pNext;
+        {
+            delete gmlId;
+            return;
+        }
+        pItem = pItem->pNext;
     }
 
     pItem = new struct huge_href;
@@ -1023,7 +1089,7 @@ static void gmlHugeAddPendingToHelper( struct huge_helper *helper,
     pItem->cOrientation = cOrientation;
     pItem->pNext = NULL;
 
-    /* appending the item to the linked list */
+    // Appending the item to the linked list.
     if ( helper->pFirstHref == NULL )
         helper->pFirstHref = pItem;
     if ( helper->pLastHref != NULL )
@@ -1033,13 +1099,13 @@ static void gmlHugeAddPendingToHelper( struct huge_helper *helper,
 
 static int gmlHugeFindGmlId( const CPLXMLNode *psNode, CPLString **gmlId )
 {
-/* attempting to identify a gml:id value      */
+    // Attempting to identify a gml:id value.
     *gmlId = NULL;
     const CPLXMLNode *psChild = psNode->psChild;
     while( psChild != NULL )
     {
         if( psChild->eType == CXT_Attribute &&
-            EQUAL( psChild->pszValue, "gml:id" ) )
+            EQUAL(psChild->pszValue, "gml:id") )
         {
             const CPLXMLNode *psIdValue = psChild->psChild;
             if( psIdValue != NULL )
@@ -1057,60 +1123,61 @@ static int gmlHugeFindGmlId( const CPLXMLNode *psNode, CPLString **gmlId )
 }
 
 static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
-                                   const CPLXMLNode * psNode,
+                                   const CPLXMLNode *psNode,
                                    CPL_UNUSED CPLString **nodeSrs )
 {
-/*
-/ this function attempts to set coordinates for <Node> items
-/ when required (an <Edge> is expected to be processed)
-*/
+    // This function attempts to set coordinates for <Node> items
+    // when required (an <Edge> is expected to be processed).
 
-/* attempting to fetch Node coordinates */
+    // Attempting to fetch Node coordinates.
     CPLXMLNode *psTopoCurve = CPLCreateXMLNode(NULL, CXT_Element, "TopoCurve");
-    CPLXMLNode *psDirEdge = CPLCreateXMLNode(psTopoCurve, CXT_Element, "directedEdge");
+    CPLXMLNode *psDirEdge =
+        CPLCreateXMLNode(psTopoCurve, CXT_Element, "directedEdge");
     CPLXMLNode *psEdge = CPLCloneXMLTree((CPLXMLNode *)psNode);
-    CPLAddXMLChild( psDirEdge, psEdge );
-    OGRGeometryCollection *poColl = (OGRGeometryCollection *)
-                                    GML2OGRGeometry_XMLNode( psTopoCurve, FALSE );
-    CPLDestroyXMLNode( psTopoCurve );
+    CPLAddXMLChild(psDirEdge, psEdge);
+    OGRGeometryCollection *poColl = static_cast<OGRGeometryCollection *>(
+        GML2OGRGeometry_XMLNode(psTopoCurve, FALSE));
+    CPLDestroyXMLNode(psTopoCurve);
     if( poColl != NULL )
     {
-        int iCount = poColl->getNumGeometries();
+        const int iCount = poColl->getNumGeometries();
         if( iCount == 1 )
         {
-            OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(0);
-            int type = wkbFlatten( poChild->getGeometryType());
+            OGRGeometry *poChild = (OGRGeometry *)poColl->getGeometryRef(0);
+            int type = wkbFlatten(poChild->getGeometryType());
             if( type == wkbLineString )
             {
                 OGRLineString *poLine = (OGRLineString *)poChild;
-                int iPoints =  poLine->getNumPoints();
+                const int iPoints = poLine->getNumPoints();
                 if( iPoints >= 2 )
                 {
                     pItem->bHasCoords = true;
-                    pItem->xNodeFrom = poLine->getX( 0 );
-                    pItem->yNodeFrom = poLine->getY( 0 );
-                    pItem->xNodeTo = poLine->getX( iPoints - 1 );
-                    pItem->yNodeTo = poLine->getY( iPoints - 1 );
+                    pItem->xNodeFrom = poLine->getX(0);
+                    pItem->yNodeFrom = poLine->getY(0);
+                    pItem->xNodeTo = poLine->getX(iPoints - 1);
+                    pItem->yNodeTo = poLine->getY(iPoints - 1);
                     if( poLine->getCoordinateDimension() == 3 )
                     {
-                        pItem->zNodeFrom = poLine->getZ( 0 );
-                        pItem->zNodeTo = poLine->getZ( iPoints - 1 );
+                        pItem->zNodeFrom = poLine->getZ(0);
+                        pItem->zNodeTo = poLine->getZ(iPoints - 1);
                         pItem->bHasZ = true;
                     }
                     else
+                    {
                         pItem->bHasZ = false;
+                    }
                 }
             }
         }
         delete poColl;
     }
 
-    /* searching the <directedNode> sub-tags */
+    // Searching the <directedNode> sub-tags.
     const CPLXMLNode *psChild = psNode->psChild;
     while( psChild != NULL )
     {
         if( psChild->eType == CXT_Element &&
-            EQUAL( psChild->pszValue, "directedNode" ) )
+            EQUAL(psChild->pszValue, "directedNode") )
         {
             char cOrientation = '+';
             const char *pszGmlId = NULL;
@@ -1132,7 +1199,7 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                     }
                 }
                 if( psAttr->eType == CXT_Attribute &&
-                    EQUAL( psAttr->pszValue, "orientation" ) )
+                    EQUAL(psAttr->pszValue, "orientation") )
                 {
                     const CPLXMLNode *psOrientation = psAttr->psChild;
                     if( psOrientation != NULL )
@@ -1144,13 +1211,13 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                     }
                 }
                 if( psAttr->eType == CXT_Element &&
-                    EQUAL( psAttr->pszValue, "Node" ) )
+                    EQUAL(psAttr->pszValue, "Node") )
                 {
                     const CPLXMLNode *psId = psAttr->psChild;
                     while( psId != NULL )
                     {
                         if( psId->eType == CXT_Attribute &&
-                            EQUAL( psId->pszValue, "gml:id" ) )
+                            EQUAL(psId->pszValue, "gml:id") )
                         {
                             const CPLXMLNode *psIdGml = psId->psChild;
                             if( psIdGml != NULL )
@@ -1169,22 +1236,26 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
             }
             if( pszGmlId != NULL )
             {
-                CPLString* posNode;
+                CPLString *posNode = NULL;
                 if( bIsHref )
                 {
                     if (pszGmlId[0] != '#')
                     {
                         CPLError(CE_Warning, CPLE_NotSupported,
-                                 "Only values of xlink:href element starting with '#' are supported, "
-                                 "so %s will not be properly recognized", pszGmlId);
+                                 "Only values of xlink:href element starting "
+                                 "with '#' are supported, "
+                                 "so %s will not be properly recognized",
+                                 pszGmlId);
                     }
-                    posNode = new CPLString(pszGmlId+1);
+                    posNode = new CPLString(pszGmlId + 1);
                 }
                 else
+                {
                     posNode = new CPLString(pszGmlId);
+                }
                 if( cOrientation == '-' )
                 {
-                     pItem->gmlNodeFrom = posNode;
+                    pItem->gmlNodeFrom = posNode;
                     pItem->bIsNodeFromHref = bIsHref;
                 }
                 else
@@ -1192,33 +1263,35 @@ static void gmlHugeFileNodeCoords( struct huge_tag *pItem,
                     pItem->gmlNodeTo = posNode;
                     pItem->bIsNodeToHref = bIsHref;
                 }
-                /*pszGmlId = NULL;*/
-                /*bIsHref = false; */
-                /*cOrientation = '+';*/
+                // pszGmlId = NULL;
+                // *bIsHref = false;
+                // cOrientation = '+';
             }
         }
         psChild = psChild->psNext;
     }
 }
 
-static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
+static void gmlHugeFileCheckXrefs( huge_helper *helper,
                                    const CPLXMLNode *psNode )
 {
-/* identifying <Edge> GML nodes */
+    // Identifying <Edge> GML nodes.
     if( psNode->eType == CXT_Element )
     {
         if( EQUAL(psNode->pszValue, "Edge") )
         {
             CPLString *gmlId = NULL;
-            if( gmlHugeFindGmlId( psNode, &gmlId ) )
+            if( gmlHugeFindGmlId(psNode, &gmlId) )
             {
-                char * gmlText = CPLSerializeXMLTree((CPLXMLNode *)psNode);
+                char *gmlText = CPLSerializeXMLTree(psNode);
                 CPLString *gmlValue = new CPLString(gmlText);
-                CPLFree( gmlText );
-                struct huge_tag *pItem = gmlHugeAddToHelper( helper, gmlId,
-                                                             gmlValue );
+                CPLFree(gmlText);
+                struct huge_tag *pItem =
+                    gmlHugeAddToHelper(helper, gmlId, gmlValue);
                 if( pItem != NULL )
-                    gmlHugeFileNodeCoords( pItem, psNode, &(helper->nodeSrs) );
+                {
+                    gmlHugeFileNodeCoords(pItem, psNode, &(helper->nodeSrs));
+                }
                 else
                 {
                     delete gmlId;
@@ -1228,7 +1301,7 @@ static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
         }
     }
 
-    /* recursively scanning each Child GML node */
+    // Recursively scanning each Child GML node.
     const CPLXMLNode *psChild = psNode->psChild;
     while( psChild != NULL )
     {
@@ -1237,7 +1310,7 @@ static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
             if( EQUAL(psChild->pszValue, "Edge") ||
                 EQUAL(psChild->pszValue, "directedEdge") )
             {
-                gmlHugeFileCheckXrefs( helper, psChild );
+                gmlHugeFileCheckXrefs(helper, psChild);
             }
             if( EQUAL(psChild->pszValue, "directedFace") )
             {
@@ -1255,7 +1328,7 @@ static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
                             {
                                 if( psEdge->eType == CXT_Element &&
                                     EQUAL(psEdge->pszValue, "Edge") )
-                                    gmlHugeFileCheckXrefs( helper, psEdge );
+                                    gmlHugeFileCheckXrefs(helper, psEdge);
                                 psEdge = psEdge->psNext;
                             }
                             psDirEdge = psDirEdge->psNext;
@@ -1267,7 +1340,7 @@ static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
         psChild = psChild->psNext;
     }
 
-    /* recursively scanning each GML of the same level */
+    // Recursively scanning each GML of the same level.
     const CPLXMLNode *psNext = psNode->psNext;
     while( psNext != NULL )
     {
@@ -1276,31 +1349,31 @@ static void gmlHugeFileCheckXrefs( struct huge_helper *helper,
             if( EQUAL(psNext->pszValue, "Edge") ||
                 EQUAL(psNext->pszValue, "directedEdge") )
             {
-                gmlHugeFileCheckXrefs( helper, psNext );
+                gmlHugeFileCheckXrefs(helper, psNext);
             }
         }
         psNext = psNext->psNext;
     }
 }
 
-static void gmlHugeFileCleanUp ( struct huge_helper *helper )
+static void gmlHugeFileCleanUp ( huge_helper *helper )
 {
-/* cleaning up any SQLite handle */
+    // Cleaning up any SQLite handle.
     if( helper->hNodes != NULL )
-        sqlite3_finalize ( helper->hNodes );
+        sqlite3_finalize(helper->hNodes);
     if( helper->hEdges != NULL )
-        sqlite3_finalize ( helper->hEdges );
+        sqlite3_finalize(helper->hEdges);
     if( helper->hDB != NULL )
-        sqlite3_close( helper->hDB );
+        sqlite3_close(helper->hDB);
     if( helper->nodeSrs != NULL )
         delete helper->nodeSrs;
 }
 
-static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
+static void gmlHugeFileCheckPendingHrefs( huge_helper *helper,
                                           const CPLXMLNode *psParent,
                                           const CPLXMLNode *psNode )
 {
-/* identifying any xlink:href to be replaced */
+    // Identifying any xlink:href to be replaced.
     if( psNode->eType == CXT_Element )
     {
         if( EQUAL(psNode->pszValue, "directedEdge") )
@@ -1310,7 +1383,7 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
             while( psAttr != NULL )
             {
                 if( psAttr->eType == CXT_Attribute &&
-                    EQUAL( psAttr->pszValue, "orientation" ) )
+                    EQUAL(psAttr->pszValue, "orientation") )
                 {
                     const CPLXMLNode *psOrientation = psAttr->psChild;
                     if( psOrientation != NULL )
@@ -1325,7 +1398,7 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
             while( psAttr != NULL )
             {
                 if( psAttr->eType == CXT_Attribute &&
-                    EQUAL( psAttr->pszValue, "xlink:href" ) )
+                    EQUAL(psAttr->pszValue, "xlink:href") )
                 {
                     const CPLXMLNode *pszHref = psAttr->psChild;
                     if( pszHref != NULL )
@@ -1334,13 +1407,18 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
                         {
                             if (pszHref->pszValue[0] != '#')
                             {
-                                CPLError(CE_Warning, CPLE_NotSupported,
-                                        "Only values of xlink:href element starting with '#' are supported, "
-                                        "so %s will not be properly recognized", pszHref->pszValue);
+                                CPLError(
+                                    CE_Warning, CPLE_NotSupported,
+                                    "Only values of xlink:href element "
+                                    "starting with '#' are supported, "
+                                    "so %s will not be properly recognized",
+                                    pszHref->pszValue);
                             }
-                            CPLString *gmlId = new CPLString(pszHref->pszValue+1);
-                            gmlHugeAddPendingToHelper( helper, gmlId, psParent,
-                                                       psNode, true, cOrientation );
+                            CPLString *gmlId =
+                                new CPLString(pszHref->pszValue + 1);
+                            gmlHugeAddPendingToHelper(helper, gmlId, psParent,
+                                                      psNode, true,
+                                                      cOrientation);
                         }
                     }
                 }
@@ -1349,7 +1427,7 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
         }
     }
 
-    /* recursively scanning each Child GML node */
+    // Recursively scanning each Child GML node.
     const CPLXMLNode *psChild = psNode->psChild;
     while( psChild != NULL )
     {
@@ -1359,13 +1437,13 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
                 EQUAL(psChild->pszValue, "directedFace") ||
                 EQUAL(psChild->pszValue, "Face") )
             {
-                gmlHugeFileCheckPendingHrefs( helper, psNode, psChild );
+                gmlHugeFileCheckPendingHrefs(helper, psNode, psChild);
             }
         }
         psChild = psChild->psNext;
     }
 
-    /* recursively scanning each GML of the same level */
+    // Recursively scanning each GML of the same level.
     const CPLXMLNode *psNext = psNode->psNext;
     while( psNext != NULL )
     {
@@ -1373,39 +1451,39 @@ static void gmlHugeFileCheckPendingHrefs( struct huge_helper *helper,
         {
             if( EQUAL(psNext->pszValue, "Face") )
             {
-                gmlHugeFileCheckPendingHrefs( helper, psParent, psNext );
+                gmlHugeFileCheckPendingHrefs(helper, psParent, psNext);
             }
         }
         psNext = psNext->psNext;
     }
 }
 
-static void gmlHugeSetHrefGmlText( struct huge_helper *helper,
+static void gmlHugeSetHrefGmlText( huge_helper *helper,
                                    const char *pszGmlId,
                                    const char *pszGmlText )
 {
-/* setting the GML text for the corresponding gml:id */
+    // Setting the GML text for the corresponding gml:id.
     struct huge_href *pItem = helper->pFirstHref;
     while( pItem != NULL )
     {
-        if( EQUAL( pItem->gmlId->c_str(), pszGmlId ) )
+        if( EQUAL(pItem->gmlId->c_str(), pszGmlId) )
         {
             if( pItem->gmlText != NULL)
                 delete pItem->gmlText;
-            pItem->gmlText = new CPLString( pszGmlText );
+            pItem->gmlText = new CPLString(pszGmlText);
             return;
         }
         pItem = pItem->pNext;
     }
 }
 
-static struct huge_parent *gmlHugeFindParent( struct huge_helper *helper,
+static struct huge_parent *gmlHugeFindParent( huge_helper *helper,
                                               CPLXMLNode *psParent )
 {
-    /* Inserting a GML Node (parent) to be rewritten */
+    // Inserting a GML Node (parent) to be rewritten.
     struct huge_parent *pItem = helper->pFirstParent;
 
-    /* checking if already exists */
+    // Checking if already exists.
     while( pItem != NULL )
     {
         if( pItem->psParent == psParent )
@@ -1413,7 +1491,7 @@ static struct huge_parent *gmlHugeFindParent( struct huge_helper *helper,
         pItem = pItem->pNext;
     }
 
-    /* creating a new Parent Node */
+    // Creating a new Parent Node.
     pItem = new struct huge_parent;
     pItem->psParent = psParent;
     pItem->pFirst = NULL;
@@ -1425,12 +1503,11 @@ static struct huge_parent *gmlHugeFindParent( struct huge_helper *helper,
         helper->pLastParent->pNext = pItem;
     helper->pLastParent = pItem;
 
-    /* inserting any Child node into the Parent */
+    // Inserting any Child node into the Parent.
     CPLXMLNode *psChild = psParent->psChild;
     while( psChild != NULL )
     {
-        struct huge_child *pChildItem;
-        pChildItem = new struct huge_child;
+        struct huge_child *pChildItem = new struct huge_child;
         pChildItem->psChild = psChild;
         pChildItem->pItem = NULL;
         pChildItem->pNext = NULL;
@@ -1447,38 +1524,34 @@ static struct huge_parent *gmlHugeFindParent( struct huge_helper *helper,
 static int gmlHugeSetChild( struct huge_parent *pParent,
                             struct huge_href *pItem )
 {
-    /* Setting a Child Node to be rewritten. */
+    // Setting a Child Node to be rewritten.
     struct huge_child *pChild = pParent->pFirst;
     while( pChild != NULL )
     {
-         if( pChild->psChild == pItem->psNode )
-         {
+        if( pChild->psChild == pItem->psNode )
+        {
             pChild->pItem = pItem;
             return true;
-         }
-         pChild = pChild->pNext;
+        }
+        pChild = pChild->pNext;
     }
     return false;
 }
 
-static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
+static int gmlHugeResolveEdges( CPL_UNUSED huge_helper *helper,
                                 CPL_UNUSED CPLXMLNode *psNode,
                                 sqlite3 *hDB )
 {
-/* resolving GML <Edge> xlink:href */
-    CPLString      osCommand;
-    sqlite3_stmt   *hStmtEdges;
-    int            rc;
-    bool           bIsComma = false;
-    bool           bError = false;
-    struct huge_href *pItem;
-    struct huge_parent *pParent;
-
-    /* query cursor [Edges] */
+    // Resolving GML <Edge> xlink:href.
+    CPLString osCommand;
+    bool bIsComma = false;
+    bool bError = false;
+
+    // query cursor [Edges] */
     osCommand = "SELECT gml_id, gml_resolved "
                 "FROM gml_edges "
                 "WHERE gml_id IN (";
-    pItem = helper->pFirstHref;
+    struct huge_href *pItem = helper->pFirstHref;
     while( pItem != NULL )
     {
         if( bIsComma )
@@ -1491,44 +1564,49 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
         pItem = pItem->pNext;
     }
     osCommand += ")";
-    rc = sqlite3_prepare_v2( hDB, osCommand.c_str(), -1, &hStmtEdges, NULL );
-    if( rc != SQLITE_OK )
+    sqlite3_stmt *hStmtEdges = NULL;
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to create QUERY stmt for EDGES" );
-        return false;
+        const int rc =
+            sqlite3_prepare_v2(hDB, osCommand.c_str(), -1, &hStmtEdges, NULL);
+        if( rc != SQLITE_OK )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unable to create QUERY stmt for EDGES");
+            return false;
+        }
     }
     while( true )
     {
-        rc = sqlite3_step( hStmtEdges );
+        const int rc = sqlite3_step(hStmtEdges);
         if( rc == SQLITE_DONE )
             break;
         if ( rc == SQLITE_ROW )
         {
-            const char *pszGmlId;
-            const char *pszGmlText = NULL;
-            pszGmlId = (const char *)sqlite3_column_text ( hStmtEdges, 0 );
-            if( sqlite3_column_type( hStmtEdges, 1 ) != SQLITE_NULL )
+            const char *pszGmlId = reinterpret_cast<const char *>(
+                sqlite3_column_text(hStmtEdges, 0));
+            if( sqlite3_column_type(hStmtEdges, 1) != SQLITE_NULL )
             {
-                pszGmlText = (const char *)sqlite3_column_text ( hStmtEdges, 1 );
-                gmlHugeSetHrefGmlText( helper, pszGmlId, pszGmlText );
+                const char *pszGmlText = reinterpret_cast<const char *>(
+                    sqlite3_column_text(hStmtEdges, 1));
+                gmlHugeSetHrefGmlText(helper, pszGmlId, pszGmlText);
             }
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Edge xlink:href QUERY: sqlite3_step(%s)",
-                      sqlite3_errmsg(hDB) );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Edge xlink:href QUERY: sqlite3_step(%s)",
+                     sqlite3_errmsg(hDB));
             bError = true;
             break;
         }
     }
-    sqlite3_finalize ( hStmtEdges );
+    sqlite3_finalize(hStmtEdges);
     if( bError )
         return false;
 
-    /* Identifying any GML node to be rewritten. */
+    // Identifying any GML node to be rewritten.
     pItem = helper->pFirstHref;
+    struct huge_parent *pParent = NULL;
     while( pItem != NULL )
     {
         if( pItem->gmlText == NULL || pItem->psParent == NULL ||
@@ -1537,8 +1615,9 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
             bError = true;
             break;
         }
-        pParent = gmlHugeFindParent( helper, (CPLXMLNode *)pItem->psParent );
-        if( gmlHugeSetChild( pParent, pItem ) == false )
+        pParent = gmlHugeFindParent(helper,
+                                    const_cast<CPLXMLNode *>(pItem->psParent));
+        if( gmlHugeSetChild(pParent, pItem) == false )
         {
             bError = true;
             break;
@@ -1548,46 +1627,48 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
 
     if( bError == false )
     {
-    /* rewriting GML nodes */
+        // Rewriting GML nodes.
         pParent = helper->pFirstParent;
         while( pParent != NULL )
         {
-            struct huge_child *pChild;
 
-            /* removing any Child node from the Parent */
-            pChild = pParent->pFirst;
+            // Removing any Child node from the Parent.
+            struct huge_child *pChild = pParent->pFirst;
             while( pChild != NULL )
             {
-                CPLRemoveXMLChild( pParent->psParent, pChild->psChild );
+                CPLRemoveXMLChild(pParent->psParent, pChild->psChild);
 
-                /* Destroying any Child Node to be rewritten */
+                // Destroying any Child Node to be rewritten.
                 if( pChild->pItem != NULL )
-                    CPLDestroyXMLNode( pChild->psChild );
+                    CPLDestroyXMLNode(pChild->psChild);
                 pChild = pChild->pNext;
             }
 
-            /* rewriting the Parent Node */
+            // Rewriting the Parent Node.
             pChild = pParent->pFirst;
             while( pChild != NULL )
             {
                 if( pChild->pItem == NULL )
                 {
-                    /* reinserting any untouched Child Node */
-                    CPLAddXMLChild( pParent->psParent, pChild->psChild );
+                    // Reinserting any untouched Child Node.
+                    CPLAddXMLChild(pParent->psParent, pChild->psChild);
                 }
                 else
                 {
-                    /* rewriting a Child Node */
-                    CPLXMLNode *psNewNode = CPLCreateXMLNode(NULL, CXT_Element, "directedEdge");
+                    // Rewriting a Child Node.
+                    CPLXMLNode *psNewNode =
+                        CPLCreateXMLNode(NULL, CXT_Element, "directedEdge");
                     if( pChild->pItem->cOrientation == '-' )
                     {
-                        CPLXMLNode *psOrientationNode = CPLCreateXMLNode(psNewNode, CXT_Attribute, "orientation");
+                        CPLXMLNode *psOrientationNode = CPLCreateXMLNode(
+                            psNewNode, CXT_Attribute, "orientation");
                         CPLCreateXMLNode(psOrientationNode, CXT_Text, "-");
                     }
-                    CPLXMLNode *psEdge = CPLParseXMLString(pChild->pItem->gmlText->c_str());
+                    CPLXMLNode *psEdge =
+                        CPLParseXMLString(pChild->pItem->gmlText->c_str());
                     if( psEdge != NULL )
-                        CPLAddXMLChild( psNewNode, psEdge );
-                    CPLAddXMLChild( pParent->psParent, psNewNode );
+                        CPLAddXMLChild(psNewNode, psEdge);
+                    CPLAddXMLChild(pParent->psParent, psNewNode);
                 }
                 pChild = pChild->pNext;
             }
@@ -1595,148 +1676,142 @@ static int gmlHugeResolveEdges( CPL_UNUSED struct huge_helper *helper,
         }
     }
 
-    /* resetting the Rewrite Helper to an empty state */
-    gmlHugeFileRewiterReset( helper );
-    if( bError )
-        return false;
-    return true;
+    // Resetting the Rewrite Helper to an empty state.
+    gmlHugeFileRewiterReset(helper);
+
+    return !bError;
 }
 
-static bool gmlHugeFileWriteResolved ( struct huge_helper *helper,
+static bool gmlHugeFileWriteResolved( huge_helper *helper,
                                       const char *pszOutputFilename,
                                       GMLReader *pReader,
                                       int *m_nHasSequentialLayers )
 {
-/* writing the resolved GML file */
-    VSILFILE       *fp;
-    GMLFeature     *poFeature;
-    const char     *osCommand;
-    int            rc;
-    sqlite3        *hDB = helper->hDB;
-    sqlite3_stmt   *hStmtNodes;
-    bool           bError = false;
-    int            iOutCount = 0;
-
-/* -------------------------------------------------------------------- */
-/*      Opening the resolved GML file                                   */
-/* -------------------------------------------------------------------- */
-    fp = VSIFOpenL( pszOutputFilename, "w" );
+    // Open the resolved GML file for writing.
+    VSILFILE *fp = VSIFOpenL(pszOutputFilename, "w");
     if( fp == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to open %.500s to write.", pszOutputFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed, "Failed to open %.500s to write.",
+                 pszOutputFilename);
         return false;
     }
 
-    /* query cursor [Nodes] */
-    osCommand = "SELECT gml_id, x, y, z "
-                "FROM nodes";
-    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hStmtNodes, NULL );
-    if( rc != SQLITE_OK )
+    sqlite3 *hDB = helper->hDB;
+
+    // Query cursor [Nodes].
+    const char *osCommand = "SELECT gml_id, x, y, z FROM nodes";
+    sqlite3_stmt *hStmtNodes = NULL;
+    const int rc1 = sqlite3_prepare_v2(hDB, osCommand, -1, &hStmtNodes, NULL);
+    if( rc1 != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to create QUERY stmt for NODES" );
-        VSIFCloseL( fp );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to create QUERY stmt for NODES");
+        VSIFCloseL(fp);
         return false;
     }
 
-    VSIFPrintfL ( fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" );
-    VSIFPrintfL ( fp, "<ResolvedTopoFeatureCollection  "
-                      "xmlns:gml=\"http://www.opengis.net/gml\">\n" );
-    VSIFPrintfL ( fp, "  <ResolvedTopoFeatureMembers>\n" );
-    /* exporting Nodes */
+    VSIFPrintfL(fp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+    VSIFPrintfL(fp, "<ResolvedTopoFeatureCollection  "
+                    "xmlns:gml=\"http://www.opengis.net/gml\">\n");
+    VSIFPrintfL(fp, "  <ResolvedTopoFeatureMembers>\n");
+
+    int iOutCount = 0;
+
+    // Exporting Nodes.
     GFSTemplateList *pCC = new GFSTemplateList();
     while( true )
     {
-        rc = sqlite3_step( hStmtNodes );
+        const int rc = sqlite3_step(hStmtNodes);
         if( rc == SQLITE_DONE )
             break;
+
         if ( rc == SQLITE_ROW )
         {
-            const char *pszGmlId;
-            char* pszEscaped;
-            double x;
-            double y;
-            double z = 0.0;
             bool bHasZ = false;
-            pszGmlId = (const char *)sqlite3_column_text ( hStmtNodes, 0 );
-            x = sqlite3_column_double ( hStmtNodes, 1 );
-            y = sqlite3_column_double ( hStmtNodes, 2 );
-            if ( sqlite3_column_type( hStmtNodes, 3 ) == SQLITE_FLOAT )
+            const char *pszGmlId = reinterpret_cast<const char *>(
+                sqlite3_column_text(hStmtNodes, 0));
+            const double x = sqlite3_column_double(hStmtNodes, 1);
+            const double y = sqlite3_column_double(hStmtNodes, 2);
+            double z = 0.0;
+            if ( sqlite3_column_type(hStmtNodes, 3) == SQLITE_FLOAT )
             {
-                z = sqlite3_column_double ( hStmtNodes, 3 );
+                z = sqlite3_column_double(hStmtNodes, 3);
                 bHasZ = true;
             }
 
-            /* inserting a node into the resolved GML file */
-            pCC->Update( "ResolvedNodes", true );
-            VSIFPrintfL ( fp, "    <ResolvedNodes>\n" );
-            pszEscaped = CPLEscapeString( pszGmlId, -1, CPLES_XML );
-            VSIFPrintfL ( fp, "      <NodeGmlId>%s</NodeGmlId>\n", pszEscaped );
+            // Inserting a node into the resolved GML file.
+            pCC->Update("ResolvedNodes", true);
+            VSIFPrintfL(fp, "    <ResolvedNodes>\n");
+            char *pszEscaped = CPLEscapeString(pszGmlId, -1, CPLES_XML);
+            VSIFPrintfL(fp, "      <NodeGmlId>%s</NodeGmlId>\n", pszEscaped);
             CPLFree(pszEscaped);
-            VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
-            if ( helper->nodeSrs == NULL )
-                VSIFPrintfL ( fp, "        <gml:Point srsDimension=\"%d\">",
-                              ( bHasZ ) ? 3 : 2 );
+            VSIFPrintfL(fp, "      <ResolvedGeometry> \n");
+            if( helper->nodeSrs == NULL )
+            {
+                VSIFPrintfL(fp, "        <gml:Point srsDimension=\"%d\">",
+                            bHasZ ? 3 : 2);
+            }
             else
             {
-                pszEscaped = CPLEscapeString( helper->nodeSrs->c_str(), -1, CPLES_XML );
-                VSIFPrintfL ( fp, "        <gml:Point srsDimension=\"%d\""
-                                  " srsName=\"%s\">",
-                                  ( bHasZ ) ? 3 : 2,
-                              pszEscaped );
+                pszEscaped =
+                    CPLEscapeString(helper->nodeSrs->c_str(), -1, CPLES_XML);
+                VSIFPrintfL(fp, "        <gml:Point srsDimension=\"%d\""
+                                " srsName=\"%s\">",
+                            bHasZ ? 3 : 2, pszEscaped);
                 CPLFree(pszEscaped);
             }
             if ( bHasZ )
-                VSIFPrintfL ( fp, "<gml:pos>%1.8f %1.8f %1.8f</gml:pos>"
+                VSIFPrintfL(fp, "<gml:pos>%1.8f %1.8f %1.8f</gml:pos>"
                                   "</gml:Point>\n",
-                              x, y, z );
+                            x, y, z);
             else
-                VSIFPrintfL ( fp, "<gml:pos>%1.8f %1.8f</gml:pos>"
-                                  "</gml:Point>\n",
-                              x, y );
-            VSIFPrintfL ( fp, "      </ResolvedGeometry> \n" );
-            VSIFPrintfL ( fp, "    </ResolvedNodes>\n" );
+                VSIFPrintfL(fp, "<gml:pos>%1.8f %1.8f</gml:pos>"
+                                "</gml:Point>\n",
+                            x, y);
+            VSIFPrintfL(fp, "      </ResolvedGeometry> \n");
+            VSIFPrintfL(fp, "    </ResolvedNodes>\n");
             iOutCount++;
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "ResolvedNodes QUERY: sqlite3_step(%s)",
-            sqlite3_errmsg(hDB) );
-            sqlite3_finalize ( hStmtNodes );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "ResolvedNodes QUERY: sqlite3_step(%s)",
+                     sqlite3_errmsg(hDB));
+            sqlite3_finalize(hStmtNodes);
             delete pCC;
             return false;
         }
     }
-    sqlite3_finalize ( hStmtNodes );
+    sqlite3_finalize(hStmtNodes);
+
+    // Processing GML features.
+    GMLFeature *poFeature = NULL;
+    bool bError = false;
 
-    /* processing GML features */
     while( (poFeature = pReader->NextFeature()) != NULL )
     {
         GMLFeatureClass *poClass = poFeature->GetClass();
-        const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
-        int iPropCount = poClass->GetPropertyCount();
+        const CPLXMLNode *const *papsGeomList = poFeature->GetGeometryList();
+        const int iPropCount = poClass->GetPropertyCount();
 
         bool b_has_geom = false;
-        VSIFPrintfL ( fp, "    <%s>\n", poClass->GetElementName() );
+        VSIFPrintfL(fp, "    <%s>\n", poClass->GetElementName());
 
         for( int iProp = 0; iProp < iPropCount; iProp++ )
         {
-            GMLPropertyDefn *poPropDefn = poClass->GetProperty( iProp );
+            GMLPropertyDefn *poPropDefn = poClass->GetProperty(iProp);
             const char *pszPropName = poPropDefn->GetName();
-            const GMLProperty *poProp = poFeature->GetProperty( iProp );
+            const GMLProperty *poProp = poFeature->GetProperty(iProp);
 
             if( poProp != NULL )
             {
                 for( int iSub = 0; iSub < poProp->nSubProperties; iSub++ )
                 {
-                    char *gmlText = CPLEscapeString( poProp->papszSubProperties[iSub],
-                                                    -1,
-                                                    CPLES_XML );
-                    VSIFPrintfL ( fp, "      <%s>%s</%s>\n",
-                                  pszPropName, gmlText, pszPropName );
-                    CPLFree( gmlText );
+                    char *gmlText = CPLEscapeString(
+                        poProp->papszSubProperties[iSub], -1, CPLES_XML);
+                    VSIFPrintfL(fp, "      <%s>%s</%s>\n",
+                                pszPropName, gmlText, pszPropName);
+                    CPLFree(gmlText);
                 }
             }
         }
@@ -1748,78 +1823,79 @@ static bool gmlHugeFileWriteResolved ( struct huge_helper *helper,
             while( psNode != NULL )
             {
                 char *pszResolved = NULL;
-                bool bNotToBeResolved;
+                bool bNotToBeResolved = false;
                 if( psNode->eType != CXT_Element )
+                {
                     bNotToBeResolved = true;
+                }
                 else
                 {
-                    if( EQUAL(psNode->pszValue, "TopoCurve") ||
-                        EQUAL(psNode->pszValue, "TopoSurface") )
-                        bNotToBeResolved = false;
-                    else
-                        bNotToBeResolved = true;
+                    bNotToBeResolved =
+                        !(EQUAL(psNode->pszValue, "TopoCurve") ||
+                          EQUAL(psNode->pszValue, "TopoSurface"));
                 }
                 if( bNotToBeResolved )
                 {
-                    VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
+                    VSIFPrintfL(fp, "      <ResolvedGeometry> \n");
                     pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
-                    VSIFPrintfL ( fp, "        %s\n", pszResolved );
-                    CPLFree( pszResolved );
-                    VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
+                    VSIFPrintfL(fp, "        %s\n", pszResolved);
+                    CPLFree(pszResolved);
+                    VSIFPrintfL(fp, "      </ResolvedGeometry>\n");
                     b_has_geom = true;
                 }
                 else
                 {
-                    gmlHugeFileCheckPendingHrefs( helper, psNode, psNode );
+                    gmlHugeFileCheckPendingHrefs(helper, psNode, psNode);
                     if( helper->pFirstHref == NULL )
                     {
-                        VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
-                        pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
-                        VSIFPrintfL ( fp, "        %s\n", pszResolved );
-                        CPLFree( pszResolved );
-                        VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
+                        VSIFPrintfL(fp, "      <ResolvedGeometry> \n");
+                        pszResolved = CPLSerializeXMLTree(psNode);
+                        VSIFPrintfL(fp, "        %s\n", pszResolved);
+                        CPLFree(pszResolved);
+                        VSIFPrintfL(fp, "      </ResolvedGeometry>\n");
                         b_has_geom = true;
                     }
                     else
                     {
-                        if( gmlHugeResolveEdges( helper, (CPLXMLNode *)psNode,
-                                                         hDB ) == false)
+                        if( gmlHugeResolveEdges(
+                                helper,
+                                const_cast<CPLXMLNode *>(psNode),
+                                hDB) == false)
                             bError = true;
-                        if( gmlHugeFileHrefCheck( helper ) == false )
+                        if( gmlHugeFileHrefCheck(helper) == false )
                             bError = true;
-                        VSIFPrintfL ( fp, "      <ResolvedGeometry> \n" );
-                        pszResolved = CPLSerializeXMLTree((CPLXMLNode *)psNode);
-                        VSIFPrintfL ( fp, "        %s\n", pszResolved );
-                        CPLFree( pszResolved );
-                        VSIFPrintfL ( fp, "      </ResolvedGeometry>\n" );
+                        VSIFPrintfL(fp, "      <ResolvedGeometry> \n");
+                        pszResolved = CPLSerializeXMLTree(psNode);
+                        VSIFPrintfL(fp, "        %s\n", pszResolved);
+                        CPLFree(pszResolved);
+                        VSIFPrintfL(fp, "      </ResolvedGeometry>\n");
                         b_has_geom = true;
-                        gmlHugeFileHrefReset( helper );
+                        gmlHugeFileHrefReset(helper);
                     }
                 }
                 i++;
                 psNode = papsGeomList[i];
             }
         }
-        pCC->Update( poClass->GetElementName(), b_has_geom );
+        pCC->Update(poClass->GetElementName(), b_has_geom);
 
-        VSIFPrintfL ( fp, "    </%s>\n", poClass->GetElementName() );
+        VSIFPrintfL(fp, "    </%s>\n", poClass->GetElementName());
 
         delete poFeature;
         iOutCount++;
     }
 
-    VSIFPrintfL ( fp, "  </ResolvedTopoFeatureMembers>\n" );
-    VSIFPrintfL ( fp, "</ResolvedTopoFeatureCollection>\n" );
+    VSIFPrintfL(fp, "  </ResolvedTopoFeatureMembers>\n");
+    VSIFPrintfL(fp, "</ResolvedTopoFeatureCollection>\n");
 
-    VSIFCloseL( fp );
+    VSIFCloseL(fp);
 
-    gmlUpdateFeatureClasses( pCC, pReader, m_nHasSequentialLayers );
+    gmlUpdateFeatureClasses(pCC, pReader, m_nHasSequentialLayers);
     if ( *m_nHasSequentialLayers )
-        pReader->ReArrangeTemplateClasses( pCC );
+        pReader->ReArrangeTemplateClasses(pCC);
     delete pCC;
-    if( bError || iOutCount == 0 )
-        return false;
-    return true;
+
+    return !(bError || iOutCount == 0);
 }
 
 /**************************************************************/
@@ -1831,190 +1907,181 @@ static bool gmlHugeFileWriteResolved ( struct huge_helper *helper,
 /**************************************************************/
 
 bool GMLReader::ParseXMLHugeFile( const char *pszOutputFilename,
-                                 const bool bSqliteIsTempFile,
-                                 const int iSqliteCacheMB )
+                                  const bool bSqliteIsTempFile,
+                                  const int iSqliteCacheMB )
 
 {
-    GMLFeature  *poFeature;
-    int iFeatureUID = 0;
-    int rc;
-    sqlite3 *hDB = NULL;
-    CPLString osSQLiteFilename;
-    const char *pszSQLiteFilename = NULL;
-    struct huge_helper helper;
-    char *pszErrMsg = NULL;
-
-    /* initializing the helper struct */
-    helper.hDB = NULL;
-    helper.hNodes = NULL;
-    helper.hEdges = NULL;
-    helper.nodeSrs = NULL;
-    helper.pFirst = NULL;
-    helper.pLast = NULL;
-    helper.pFirstHref = NULL;
-    helper.pLastHref = NULL;
-    helper.pFirstParent = NULL;
-    helper.pLastParent = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Creating/Opening the SQLite DB file                             */
 /* -------------------------------------------------------------------- */
-    osSQLiteFilename = CPLResetExtension( m_pszFilename, "sqlite" );
-    pszSQLiteFilename = osSQLiteFilename.c_str();
+    const CPLString osSQLiteFilename =
+        CPLResetExtension(m_pszFilename, "sqlite");
+    const char *pszSQLiteFilename = osSQLiteFilename.c_str();
 
     VSIStatBufL statBufL;
-    if ( VSIStatExL ( pszSQLiteFilename, &statBufL, VSI_STAT_EXISTS_FLAG) == 0)
+    if ( VSIStatExL(pszSQLiteFilename, &statBufL, VSI_STAT_EXISTS_FLAG) == 0)
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "sqlite3_open(%s) failed:\n\tDB-file already exists",
-                  pszSQLiteFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "sqlite3_open(%s) failed: DB-file already exists",
+                 pszSQLiteFilename);
         return false;
     }
 
-    rc = sqlite3_open( pszSQLiteFilename, &hDB );
-    if( rc != SQLITE_OK )
+    sqlite3 *hDB = NULL;
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "sqlite3_open(%s) failed: %s",
-                  pszSQLiteFilename, sqlite3_errmsg( hDB ) );
-        return false;
+        const int rc = sqlite3_open(pszSQLiteFilename, &hDB);
+        if( rc != SQLITE_OK )
+        {
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "sqlite3_open(%s) failed: %s",
+                     pszSQLiteFilename, sqlite3_errmsg(hDB));
+            return false;
+        }
     }
+
+    huge_helper helper;
     helper.hDB = hDB;
 
-/*
-* setting SQLite for max speed; this is intrinsically unsafe,
-* and the DB file could be potentially damaged (power failure ...]
-*
-* but after all this one simply is a TEMPORARY FILE !!
-* so there is no real risk condition
-*/
-    rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL,
-                       &pszErrMsg );
-    if( rc != SQLITE_OK )
+    char *pszErrMsg = NULL;
+
+    // Setting SQLite for max speed; this is intrinsically unsafe.
+    // The DB file could be potentially damaged.
+    // But, this is a temporary file, so there is no real risk.
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to set PRAGMA synchronous = OFF: %s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
+        const int rc =
+            sqlite3_exec(hDB, "PRAGMA synchronous = OFF", NULL, NULL,
+                         &pszErrMsg);
+        if( rc != SQLITE_OK )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unable to set PRAGMA synchronous = OFF: %s",
+                     pszErrMsg);
+            sqlite3_free(pszErrMsg);
+        }
     }
-    rc = sqlite3_exec( hDB, "PRAGMA journal_mode = OFF", NULL, NULL,
-                       &pszErrMsg );
-    if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to set PRAGMA journal_mode = OFF: %s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
+        const int rc =
+            sqlite3_exec(hDB, "PRAGMA journal_mode = OFF", NULL, NULL,
+                         &pszErrMsg);
+        if( rc != SQLITE_OK )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unable to set PRAGMA journal_mode = OFF: %s",
+                     pszErrMsg);
+            sqlite3_free(pszErrMsg);
+        }
     }
-    rc = sqlite3_exec( hDB, "PRAGMA locking_mode = EXCLUSIVE", NULL, NULL,
-                       &pszErrMsg );
-    if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to set PRAGMA locking_mode = EXCLUSIVE: %s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
+        const int rc =
+            sqlite3_exec(hDB, "PRAGMA locking_mode = EXCLUSIVE", NULL, NULL,
+                         &pszErrMsg);
+        if( rc != SQLITE_OK )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unable to set PRAGMA locking_mode = EXCLUSIVE: %s",
+                     pszErrMsg);
+            sqlite3_free(pszErrMsg);
+        }
     }
 
-    /* setting the SQLite cache */
+    // Setting the SQLite cache.
     if( iSqliteCacheMB > 0 )
     {
-        int cache_size = iSqliteCacheMB * 1024;
-
-        /* refusing to allocate more than 1GB */
-        if( cache_size > 1024 * 1024 )
-            cache_size = 1024 * 1024;
-        char sqlPragma[64];
-        snprintf( sqlPragma, sizeof(sqlPragma), "PRAGMA cache_size = %d", cache_size );
-        rc = sqlite3_exec( hDB, sqlPragma, NULL, NULL, &pszErrMsg );
+        // Refuse to allocate more than 1GB.
+        const int cache_size = std::min(iSqliteCacheMB * 1024, 1024 * 1024);
+
+        char sqlPragma[64] = {};
+        snprintf(sqlPragma, sizeof(sqlPragma), "PRAGMA cache_size = %d",
+                 cache_size);
+        const int rc = sqlite3_exec(hDB, sqlPragma, NULL, NULL, &pszErrMsg);
         if( rc != SQLITE_OK )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to set %s: %s", sqlPragma, pszErrMsg );
-            sqlite3_free( pszErrMsg );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unable to set %s: %s", sqlPragma, pszErrMsg);
+            sqlite3_free(pszErrMsg);
         }
     }
 
     if( !SetupParser() )
     {
-        gmlHugeFileCleanUp ( &helper );
+        gmlHugeFileCleanUp(&helper);
         return false;
     }
 
-    /* creating SQLite tables and Insert cursors */
+    // Creating SQLite tables and Insert cursors.
     if( gmlHugeFileSQLiteInit( &helper ) == false )
     {
         gmlHugeFileCleanUp ( &helper );
         return false;
     }
 
-    /* processing GML features */
+    // Processing GML features.
+    GMLFeature *poFeature = NULL;
     while( (poFeature = NextFeature()) != NULL )
     {
-        const CPLXMLNode* const * papsGeomList = poFeature->GetGeometryList();
+        const CPLXMLNode *const *papsGeomList = poFeature->GetGeometryList();
         if (papsGeomList != NULL)
         {
             int i = 0;
             const CPLXMLNode *psNode = papsGeomList[i];
-            while(psNode)
-            {
-                gmlHugeFileCheckXrefs( &helper, psNode );
-                /* inserting into the SQLite DB any appropriate row */
-                gmlHugeFileSQLiteInsert ( &helper );
-                /* resetting an empty helper struct */
-                gmlHugeFileReset ( &helper );
-                i ++;
+            while( psNode )
+            {
+                gmlHugeFileCheckXrefs(&helper, psNode);
+                // Inserting into the SQLite DB any appropriate row.
+                gmlHugeFileSQLiteInsert(&helper);
+                // Resetting an empty helper struct.
+                gmlHugeFileReset (&helper);
+                i++;
                 psNode = papsGeomList[i];
             }
         }
-        iFeatureUID++;
         delete poFeature;
     }
 
-    /* finalizing any SQLite Insert cursor */
+    // Finalizing any SQLite Insert cursor.
     if( helper.hNodes != NULL )
-        sqlite3_finalize ( helper.hNodes );
+        sqlite3_finalize(helper.hNodes);
     helper.hNodes = NULL;
     if( helper.hEdges != NULL )
-        sqlite3_finalize ( helper.hEdges );
+        sqlite3_finalize(helper.hEdges);
     helper.hEdges = NULL;
 
-    /* confirming the still pending TRANSACTION */
-    rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, &pszErrMsg );
+    // Confirming the still pending TRANSACTION.
+    const int rc = sqlite3_exec(hDB, "COMMIT", NULL, NULL, &pszErrMsg);
     if( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to perform COMMIT TRANSACTION: %s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to perform COMMIT TRANSACTION: %s",
+                 pszErrMsg);
+        sqlite3_free(pszErrMsg);
         return false;
     }
 
-/* attempting to resolve GML strings */
+    // Attempting to resolve GML strings.
     if( gmlHugeFileResolveEdges( &helper ) == false )
     {
-        gmlHugeFileCleanUp ( &helper );
+        gmlHugeFileCleanUp(&helper);
         return false;
     }
 
-    /* restarting the GML parser */
+    // Restarting the GML parser.
     if( !SetupParser() )
     {
-        gmlHugeFileCleanUp ( &helper );
+        gmlHugeFileCleanUp(&helper);
         return false;
     }
 
-    /* output: writing the revolved GML file */
-    if ( gmlHugeFileWriteResolved( &helper, pszOutputFilename, this,
-                                   &m_nHasSequentialLayers ) == false)
+    // Output: writing the revolved GML file.
+    if ( gmlHugeFileWriteResolved(&helper, pszOutputFilename, this,
+                                  &m_nHasSequentialLayers) == false)
     {
-        gmlHugeFileCleanUp ( &helper );
+        gmlHugeFileCleanUp(&helper);
         return false;
     }
 
-    gmlHugeFileCleanUp ( &helper );
+    gmlHugeFileCleanUp(&helper);
     if ( bSqliteIsTempFile )
-        VSIUnlink( pszSQLiteFilename );
+        VSIUnlink(pszSQLiteFilename);
     return true;
 }
 
@@ -2031,21 +2098,21 @@ bool GMLReader::HugeFileResolver( const char *pszFile,
     // Check if the original source file is set.
     if( m_pszFilename == NULL )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-        "GML source file needs to be set first with "
-        "GMLReader::SetSourceFile()." );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "GML source file needs to be set first with "
+                 "GMLReader::SetSourceFile().");
         return false;
     }
-    if ( ParseXMLHugeFile( pszFile, bSqliteIsTempFile, iSqliteCacheMB ) == false )
+    if ( ParseXMLHugeFile(pszFile, bSqliteIsTempFile, iSqliteCacheMB) == false )
         return false;
 
-    //set the source file to the resolved file
+    // Set the source file to the resolved file.
     CleanupParser();
     if (fpGML)
         VSIFCloseL(fpGML);
     fpGML = NULL;
-    CPLFree( m_pszFilename );
-    m_pszFilename = CPLStrdup( pszFile );
+    CPLFree(m_pszFilename);
+    m_pszFilename = CPLStrdup(pszFile);
     return true;
 }
 
@@ -2061,9 +2128,9 @@ bool GMLReader::HugeFileResolver( CPL_UNUSED const char *pszFile,
                                  CPL_UNUSED int iSqliteCacheMB )
 
 {
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "OGR was built without SQLite3 support\n"
-              "... sorry, the HUGE GML resolver is unsupported\n" );
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "OGR was built without SQLite3 support. "
+             "Sorry, the HUGE GML resolver is unsupported.");
     return false;
 }
 
@@ -2071,10 +2138,10 @@ bool GMLReader::ParseXMLHugeFile( CPL_UNUSED const char *pszOutputFilename,
                                  CPL_UNUSED const bool bSqliteIsTempFile,
                                  CPL_UNUSED const int iSqliteCacheMB )
 {
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "OGR was built without SQLite3 support\n"
-              "... sorry, the HUGE GML resolver is unsupported\n" );
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "OGR was built without SQLite3 support. "
+             "Sorry, the HUGE GML resolver is unsupported.");
     return false;
 }
 
-#endif // HAVE_SQLITE
+#endif  // HAVE_SQLITE
diff --git a/ogr/ogrsf_frmts/gml/makefile.vc b/ogr/ogrsf_frmts/gml/makefile.vc
index ee14adb..cd916a6 100644
--- a/ogr/ogrsf_frmts/gml/makefile.vc
+++ b/ogr/ogrsf_frmts/gml/makefile.vc
@@ -1,7 +1,7 @@
 
 LL_OBJ	=	gmlpropertydefn.obj gmlfeatureclass.obj gmlfeature.obj \
 		gmlreader.obj parsexsd.obj resolvexlinks.obj hugefileresolver.obj gmlutils.obj \
-		gmlreadstate.obj gmlhandler.obj trstring.obj  gfstemplate.obj gmlregistry.obj
+		gmlreadstate.obj gmlhandler.obj gfstemplate.obj gmlregistry.obj
 OGR_OBJ	=	ogrgmldriver.obj ogrgmldatasource.obj ogrgmllayer.obj
 
 OBJ	=	$(LL_OBJ) $(OGR_OBJ)
diff --git a/ogr/ogrsf_frmts/gml/ogr_gml.h b/ogr/ogrsf_frmts/gml/ogr_gml.h
index bd0aaed..ea725a5 100644
--- a/ogr/ogrsf_frmts/gml/ogr_gml.h
+++ b/ogr/ogrsf_frmts/gml/ogr_gml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gml.h 35690 2016-10-11 09:56:31Z rouault $
+ * $Id: ogr_gml.h 37265 2017-02-01 06:20:23Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Declarations for OGR wrapper classes for GML, and GML<->OGR
@@ -54,7 +54,6 @@ class OGRGMLLayer : public OGRLayer
     OGRFeatureDefn     *poFeatureDefn;
 
     GIntBig             iNextGMLId;
-    int                 nTotalGMLCount;
     bool                bInvalidFIDFound;
     char                *pszFIDPrefix;
 
@@ -76,26 +75,26 @@ class OGRGMLLayer : public OGRLayer
                                      bool bWriter,
                                      OGRGMLDataSource *poDS );
 
-                        ~OGRGMLLayer();
+                        virtual ~OGRGMLLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    GIntBig             GetFeatureCount( int bForce = TRUE );
-    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    GIntBig             GetFeatureCount( int bForce = TRUE ) override;
+    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -125,7 +124,7 @@ class OGRGMLDataSource : public OGRDataSource
     bool                bIsOutputGML3;
     bool                bIsOutputGML3Deegree; /* if TRUE, then bIsOutputGML3 is also TRUE */
     bool                bIsOutputGML32; /* if TRUE, then bIsOutputGML3 is also TRUE */
-    bool                bIsLongSRSRequired;
+    OGRGMLSRSNameFormat eSRSNameFormat;
     bool                bWriteSpaceIndentation;
 
     OGRSpatialReference* poWriteGlobalSRS;
@@ -167,21 +166,21 @@ class OGRGMLDataSource : public OGRDataSource
 
   public:
                         OGRGMLDataSource();
-                        ~OGRGMLDataSource();
+                        virtual ~OGRGMLDataSource();
 
     bool                Open( GDALOpenInfo* poOpenInfo );
     bool                Create( const char *pszFile, char **papszOptions );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
     virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+                                      char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     VSILFILE            *GetOutputFP() const { return fpOutput; }
     IGMLReader          *GetReader() const { return poReader; }
@@ -195,8 +194,8 @@ class OGRGMLDataSource : public OGRDataSource
     bool                IsGML3Output() const { return bIsOutputGML3; }
     bool                IsGML3DeegreeOutput() const { return bIsOutputGML3Deegree; }
     bool                IsGML32Output() const { return bIsOutputGML32; }
-    bool                IsLongSRSRequired() const { return bIsLongSRSRequired; }
-    int                 WriteSpaceIndentation() const { return bWriteSpaceIndentation; }
+    OGRGMLSRSNameFormat GetSRSNameFormat() const { return eSRSNameFormat; }
+    bool                WriteSpaceIndentation() const { return bWriteSpaceIndentation; }
     const char         *GetGlobalSRSName();
 
     bool                GetInvertAxisOrderIfLatLong() const { return m_bInvertAxisOrderIfLatLong; }
@@ -218,8 +217,8 @@ class OGRGMLDataSource : public OGRDataSource
 
     virtual OGRLayer *          ExecuteSQL( const char *pszSQLCommand,
                                             OGRGeometry *poSpatialFilter,
-                                            const char *pszDialect );
-    virtual void                ReleaseResultSet( OGRLayer * poResultsSet );
+                                            const char *pszDialect ) override;
+    virtual void                ReleaseResultSet( OGRLayer * poResultsSet ) override;
 
     static bool          CheckHeader(const char* pszStr);
 };
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
index 5b742e3..55545d1 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgmldatasource.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLDataSource class.
@@ -35,39 +34,41 @@
  *
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_gml.h"
-#include "parsexsd.h"
+
+#include <algorithm>
+#include <vector>
+
 #include "cpl_conv.h"
-#include "cpl_string.h"
 #include "cpl_http.h"
+#include "cpl_string.h"
+#include "cpl_vsi_error.h"
+#include "gmlreaderp.h"
+#include "gmlregistry.h"
 #include "gmlutils.h"
 #include "ogr_p.h"
-#include "gmlregistry.h"
-#include "gmlreaderp.h"
-
-#include <vector>
-
-CPL_CVSID("$Id: ogrgmldatasource.cpp 35690 2016-10-11 09:56:31Z rouault $");
+#include "parsexsd.h"
 
-static bool ExtractSRSName(const char* pszXML, char* szSRSName,
-                           size_t sizeof_szSRSName);
+CPL_CVSID("$Id: ogrgmldatasource.cpp 37914 2017-04-06 17:38:46Z rouault $");
 
 /************************************************************************/
 /*                   ReplaceSpaceByPct20IfNeeded()                      */
 /************************************************************************/
 
-static CPLString ReplaceSpaceByPct20IfNeeded(const char* pszURL)
+static CPLString ReplaceSpaceByPct20IfNeeded(const char *pszURL)
 {
-    /* Replace ' ' by '%20' */
+    // Replace ' ' by '%20'.
     CPLString osRet = pszURL;
-    const char* pszNeedle = strstr(pszURL, "; ");
+    const char *pszNeedle = strstr(pszURL, "; ");
     if (pszNeedle)
     {
-        char* pszTmp = (char*)CPLMalloc(strlen(pszURL) + 2 +1);
-        int nBeforeNeedle = (int)(pszNeedle - pszURL);
+        char *pszTmp = static_cast<char *>(CPLMalloc(strlen(pszURL) + 2 + 1));
+        const int nBeforeNeedle = static_cast<int>(pszNeedle - pszURL);
         memcpy(pszTmp, pszURL, nBeforeNeedle);
         strcpy(pszTmp + nBeforeNeedle, ";%20");
-        strcpy(pszTmp + nBeforeNeedle + strlen(";%20"), pszNeedle + strlen("; "));
+        strcpy(pszTmp + nBeforeNeedle + strlen(";%20"),
+               pszNeedle + strlen("; "));
         osRet = pszTmp;
         CPLFree(pszTmp);
     }
@@ -79,70 +80,60 @@ static CPLString ReplaceSpaceByPct20IfNeeded(const char* pszURL)
 /*                         OGRGMLDataSource()                         */
 /************************************************************************/
 
-OGRGMLDataSource::OGRGMLDataSource()
-
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-
-    poReader = NULL;
-    fpOutput = NULL;
-    bFpOutputIsNonSeekable = false;
-    bFpOutputSingleFile = false;
-    bIsOutputGML3 = false;
-    bIsOutputGML3Deegree = false;
-    bIsOutputGML32 = false;
-    bIsLongSRSRequired = false;
-    bWriteSpaceIndentation = true;
-
-    papszCreateOptions = NULL;
-    bOutIsTempFile = false;
-
-    bExposeGMLId = false;
-    bExposeFid = false;
-    nSchemaInsertLocation = -1;
-    nBoundedByLocation = -1;
-    bBBOX3D = false;
-
-    poWriteGlobalSRS = NULL;
-    bWriteGlobalSRS = false;
-    bUseGlobalSRSName = false;
-    bIsWFS = false;
-
-    eReadMode = STANDARD;
-    poStoredGMLFeature = NULL;
-    poLastReadLayer = NULL;
-
-    m_bInvertAxisOrderIfLatLong = false;
-    m_bConsiderEPSGAsURN = false;
-    m_eSwapCoordinates = GML_SWAP_AUTO;
-    m_bGetSecondaryGeometryOption = false;
-    bEmptyAsNull = true;
-}
+OGRGMLDataSource::OGRGMLDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    papszCreateOptions(NULL),
+    fpOutput(NULL),
+    bFpOutputIsNonSeekable(false),
+    bFpOutputSingleFile(false),
+    bBBOX3D(false),
+    nBoundedByLocation(-1),
+    nSchemaInsertLocation(-1),
+    bIsOutputGML3(false),
+    bIsOutputGML3Deegree(false),
+    bIsOutputGML32(false),
+    eSRSNameFormat(SRSNAME_SHORT),
+    bWriteSpaceIndentation(true),
+    poWriteGlobalSRS(NULL),
+    bWriteGlobalSRS(false),
+    poReader(NULL),
+    bOutIsTempFile(false),
+    bExposeGMLId(false),
+    bExposeFid(false),
+    bIsWFS(false),
+    bUseGlobalSRSName(false),
+    m_bInvertAxisOrderIfLatLong(false),
+    m_bConsiderEPSGAsURN(false),
+    m_eSwapCoordinates(GML_SWAP_AUTO),
+    m_bGetSecondaryGeometryOption(false),
+    eReadMode(STANDARD),
+    poStoredGMLFeature(NULL),
+    poLastReadLayer(NULL),
+    bEmptyAsNull(true)
+{}
 
 /************************************************************************/
 /*                        ~OGRGMLDataSource()                         */
 /************************************************************************/
 
 OGRGMLDataSource::~OGRGMLDataSource()
-
 {
-
     if( fpOutput != NULL )
     {
         if( nLayers == 0 )
             WriteTopElements();
 
-        const char* pszPrefix = GetAppPrefix();
+        const char *pszPrefix = GetAppPrefix();
         if( RemoveAppPrefix() )
-            PrintLine( fpOutput, "</FeatureCollection>" );
+            PrintLine(fpOutput, "</FeatureCollection>");
         else
-            PrintLine( fpOutput, "</%s:FeatureCollection>", pszPrefix );
+            PrintLine(fpOutput, "</%s:FeatureCollection>", pszPrefix);
 
         if( bFpOutputIsNonSeekable)
         {
-            VSIFCloseL( fpOutput );
+            VSIFCloseL(fpOutput);
             fpOutput = NULL;
         }
 
@@ -150,90 +141,106 @@ OGRGMLDataSource::~OGRGMLDataSource()
 
         if( !bFpOutputIsNonSeekable
             && nBoundedByLocation != -1
-            && VSIFSeekL( fpOutput, nBoundedByLocation, SEEK_SET ) == 0 )
+            && VSIFSeekL(fpOutput, nBoundedByLocation, SEEK_SET) == 0 )
         {
             if (bWriteGlobalSRS && sBoundingRect.IsInit()  && IsGML3Output())
             {
                 bool bCoordSwap = false;
-                char* pszSRSName;
-                if (poWriteGlobalSRS)
-                    pszSRSName = GML_GetSRSName(poWriteGlobalSRS, IsLongSRSRequired(), &bCoordSwap);
-                else
-                    pszSRSName = CPLStrdup("");
-                char szLowerCorner[75], szUpperCorner[75];
+                char *pszSRSName = poWriteGlobalSRS
+                    ? GML_GetSRSName(
+                        poWriteGlobalSRS, eSRSNameFormat, &bCoordSwap)
+                    : CPLStrdup("");
+                char szLowerCorner[75] = {};
+                char szUpperCorner[75] = {};
                 if (bCoordSwap)
                 {
-                    OGRMakeWktCoordinate(szLowerCorner, sBoundingRect.MinY, sBoundingRect.MinX, sBoundingRect.MinZ, (bBBOX3D) ? 3 : 2);
-                    OGRMakeWktCoordinate(szUpperCorner, sBoundingRect.MaxY, sBoundingRect.MaxX, sBoundingRect.MaxZ, (bBBOX3D) ? 3 : 2);
+                    OGRMakeWktCoordinate(
+                        szLowerCorner, sBoundingRect.MinY, sBoundingRect.MinX,
+                        sBoundingRect.MinZ, bBBOX3D ? 3 : 2);
+                    OGRMakeWktCoordinate(
+                        szUpperCorner, sBoundingRect.MaxY, sBoundingRect.MaxX,
+                        sBoundingRect.MaxZ, bBBOX3D ? 3 : 2);
                 }
                 else
                 {
-                    OGRMakeWktCoordinate(szLowerCorner, sBoundingRect.MinX, sBoundingRect.MinY, sBoundingRect.MinZ, (bBBOX3D) ? 3 : 2);
-                    OGRMakeWktCoordinate(szUpperCorner, sBoundingRect.MaxX, sBoundingRect.MaxY, sBoundingRect.MaxZ, (bBBOX3D) ? 3 : 2);
+                    OGRMakeWktCoordinate(
+                        szLowerCorner, sBoundingRect.MinX, sBoundingRect.MinY,
+                        sBoundingRect.MinZ, bBBOX3D ? 3 : 2);
+                    OGRMakeWktCoordinate(
+                        szUpperCorner, sBoundingRect.MaxX, sBoundingRect.MaxY,
+                        sBoundingRect.MaxZ, (bBBOX3D) ? 3 : 2);
                 }
                 if (bWriteSpaceIndentation)
-                    VSIFPrintfL( fpOutput, "  ");
-                PrintLine( fpOutput, "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
-                           (bBBOX3D) ? " srsDimension=\"3\"" : "", pszSRSName, szLowerCorner, szUpperCorner);
+                    VSIFPrintfL(fpOutput, "  ");
+                PrintLine(
+                    fpOutput,
+                    "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s"
+                    "</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner>"
+                    "</gml:Envelope></gml:boundedBy>",
+                    bBBOX3D ? " srsDimension=\"3\"" : "", pszSRSName,
+                    szLowerCorner, szUpperCorner);
                 CPLFree(pszSRSName);
             }
             else if (bWriteGlobalSRS && sBoundingRect.IsInit())
             {
                 if (bWriteSpaceIndentation)
-                    VSIFPrintfL( fpOutput, "  ");
-                PrintLine( fpOutput, "<gml:boundedBy>" );
+                    VSIFPrintfL(fpOutput, "  ");
+                PrintLine(fpOutput, "<gml:boundedBy>");
                 if (bWriteSpaceIndentation)
-                    VSIFPrintfL( fpOutput, "    ");
-                PrintLine( fpOutput, "<gml:Box>" );
+                    VSIFPrintfL(fpOutput, "    ");
+                PrintLine(fpOutput, "<gml:Box>");
                 if (bWriteSpaceIndentation)
-                    VSIFPrintfL( fpOutput, "      ");
-                VSIFPrintfL( fpOutput,
+                    VSIFPrintfL(fpOutput, "      ");
+                VSIFPrintfL(fpOutput,
                             "<gml:coord><gml:X>%.16g</gml:X>"
                             "<gml:Y>%.16g</gml:Y>",
-                            sBoundingRect.MinX, sBoundingRect.MinY );
+                            sBoundingRect.MinX, sBoundingRect.MinY);
                 if (bBBOX3D)
-                    VSIFPrintfL( fpOutput, "<gml:Z>%.16g</gml:Z>",
-                               sBoundingRect.MinZ );
-                PrintLine( fpOutput, "</gml:coord>");
+                    VSIFPrintfL(fpOutput, "<gml:Z>%.16g</gml:Z>",
+                                sBoundingRect.MinZ);
+                PrintLine(fpOutput, "</gml:coord>");
                 if (bWriteSpaceIndentation)
-                    VSIFPrintfL( fpOutput, "      ");
-                VSIFPrintfL( fpOutput,
+                    VSIFPrintfL(fpOutput, "      ");
+                VSIFPrintfL(fpOutput,
                             "<gml:coord><gml:X>%.16g</gml:X>"
                             "<gml:Y>%.16g</gml:Y>",
-                            sBoundingRect.MaxX, sBoundingRect.MaxY );
+                            sBoundingRect.MaxX, sBoundingRect.MaxY);
                 if (bBBOX3D)
-                    VSIFPrintfL( fpOutput, "<gml:Z>%.16g</gml:Z>",
-                               sBoundingRect.MaxZ );
-                PrintLine( fpOutput, "</gml:coord>");
+                    VSIFPrintfL(fpOutput, "<gml:Z>%.16g</gml:Z>",
+                                sBoundingRect.MaxZ);
+                PrintLine(fpOutput, "</gml:coord>");
                 if (bWriteSpaceIndentation)
-                    VSIFPrintfL( fpOutput, "    ");
-                PrintLine( fpOutput, "</gml:Box>" );
+                    VSIFPrintfL(fpOutput, "    ");
+                PrintLine(fpOutput, "</gml:Box>");
                 if (bWriteSpaceIndentation)
-                    VSIFPrintfL( fpOutput, "  ");
-                PrintLine( fpOutput, "</gml:boundedBy>" );
+                    VSIFPrintfL(fpOutput, "  ");
+                PrintLine(fpOutput, "</gml:boundedBy>");
             }
             else
             {
                 if (bWriteSpaceIndentation)
-                    VSIFPrintfL( fpOutput, "  ");
+                    VSIFPrintfL(fpOutput, "  ");
                 if (IsGML3Output())
-                    PrintLine( fpOutput, "<gml:boundedBy><gml:Null /></gml:boundedBy>" );
+                    PrintLine(fpOutput,
+                              "<gml:boundedBy><gml:Null /></gml:boundedBy>");
                 else
-                    PrintLine( fpOutput, "<gml:boundedBy><gml:null>missing</gml:null></gml:boundedBy>" );
+                    PrintLine(fpOutput,
+                              "<gml:boundedBy><gml:null>missing"
+                              "</gml:null></gml:boundedBy>");
             }
         }
 
         if (fpOutput)
-            VSIFCloseL( fpOutput );
+            VSIFCloseL(fpOutput);
     }
 
-    CSLDestroy( papszCreateOptions );
-    CPLFree( pszName );
+    CSLDestroy(papszCreateOptions);
+    CPLFree(pszName);
 
     for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
 
-    CPLFree( papoLayers );
+    CPLFree(papoLayers);
 
     if( poReader )
     {
@@ -246,7 +253,8 @@ OGRGMLDataSource::~OGRGMLDataSource()
 
     delete poStoredGMLFeature;
 
-    if (osXSDFilename.compare(CPLSPrintf("/vsimem/tmp_gml_xsd_%p.xsd", this)) == 0)
+    if (osXSDFilename.compare(
+            CPLSPrintf("/vsimem/tmp_gml_xsd_%p.xsd", this)) == 0)
         VSIUnlink(osXSDFilename);
 }
 
@@ -254,42 +262,44 @@ OGRGMLDataSource::~OGRGMLDataSource()
 /*                            CheckHeader()                             */
 /************************************************************************/
 
-bool OGRGMLDataSource::CheckHeader(const char* pszStr)
+bool OGRGMLDataSource::CheckHeader(const char *pszStr)
 {
-    if( strstr(pszStr,"opengis.net/gml") == NULL &&
-        strstr(pszStr,"<csw:GetRecordsResponse") == NULL )
+    if( strstr(pszStr, "opengis.net/gml") == NULL &&
+        strstr(pszStr, "<csw:GetRecordsResponse") == NULL )
     {
         return false;
     }
 
-    /* Ignore .xsd schemas */
-    if( strstr(pszStr, "<schema") != NULL
-        || strstr(pszStr, "<xs:schema") != NULL
-        || strstr(pszStr, "<xsd:schema") != NULL )
+    // Ignore .xsd schemas.
+    if( strstr(pszStr, "<schema") != NULL ||
+        strstr(pszStr, "<xs:schema") != NULL ||
+        strstr(pszStr, "<xsd:schema") != NULL )
     {
         return false;
     }
 
-    /* Ignore GeoRSS documents. They will be recognized by the GeoRSS driver */
-    if( strstr(pszStr, "<rss") != NULL && strstr(pszStr, "xmlns:georss") != NULL )
+    // Ignore GeoRSS documents. They will be recognized by the GeoRSS driver.
+    if( strstr(pszStr, "<rss") != NULL &&
+        strstr(pszStr, "xmlns:georss") != NULL )
     {
         return false;
     }
 
-    /* Ignore OpenJUMP .jml documents. They will be recognized by the OpenJUMP driver */
+    // Ignore OpenJUMP .jml documents.
+    // They will be recognized by the OpenJUMP driver.
     if( strstr(pszStr, "<JCSDataFile") != NULL )
     {
         return false;
     }
 
-    /* Ignore OGR WFS xml description files, or WFS Capabilities results */
+    // Ignore OGR WFS xml description files, or WFS Capabilities results.
     if( strstr(pszStr, "<OGRWFSDataSource>") != NULL ||
         strstr(pszStr, "<wfs:WFS_Capabilities") != NULL )
     {
         return false;
     }
 
-    /* Ignore WMTS capabilities results */
+    // Ignore WMTS capabilities results.
     if( strstr(pszStr, "http://www.opengis.net/wmts/1.0") != NULL )
     {
         return false;
@@ -299,22 +309,38 @@ bool OGRGMLDataSource::CheckHeader(const char* pszStr)
 }
 
 /************************************************************************/
+/*                          ExtractSRSName()                            */
+/************************************************************************/
+
+static bool ExtractSRSName(const char *pszXML, char *szSRSName,
+                           size_t sizeof_szSRSName)
+{
+    szSRSName[0] = '\0';
+
+    const char *pszSRSName = strstr(pszXML, "srsName=\"");
+    if( pszSRSName != NULL )
+    {
+        pszSRSName += 9;
+        const char *pszEndQuote = strchr(pszSRSName, '"');
+        if (pszEndQuote != NULL &&
+            static_cast<size_t>(pszEndQuote - pszSRSName) < sizeof_szSRSName)
+        {
+            memcpy(szSRSName, pszSRSName, pszEndQuote - pszSRSName);
+            szSRSName[pszEndQuote - pszSRSName] = '\0';
+            return true;
+        }
+    }
+    return false;
+}
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
-bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
+bool OGRGMLDataSource::Open( GDALOpenInfo *poOpenInfo )
 
 {
-    VSILFILE   *fp;
-    char        szHeader[4096];
-    GIntBig     nNumberOfFeatures = 0;
-    CPLString   osWithVsiGzip;
-    const char *pszSchemaLocation = NULL;
-    bool bCheckAuxFile = true;
-
-/* -------------------------------------------------------------------- */
-/*      Extract XSD filename from connection string if present.          */
-/* -------------------------------------------------------------------- */
+    // Extract XSD filename from connection string if present.
     osFilename = poOpenInfo->pszFilename;
     const char *pszXSDFilenameTmp = strstr(poOpenInfo->pszFilename, ",xsd=");
     if (pszXSDFilenameTmp != NULL)
@@ -323,16 +349,18 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         osXSDFilename = pszXSDFilenameTmp + strlen(",xsd=");
     }
     else
-        osXSDFilename = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "XSD", "");
+    {
+        osXSDFilename =
+            CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "XSD", "");
+    }
 
     const char *pszFilename = osFilename.c_str();
 
-    pszName = CPLStrdup( poOpenInfo->pszFilename );
+    pszName = CPLStrdup(poOpenInfo->pszFilename);
 
-/* -------------------------------------------------------------------- */
-/*      Open the source file.                                           */
-/* -------------------------------------------------------------------- */
-    VSILFILE* fpToClose = NULL;
+    // Open the source file.
+    VSILFILE *fpToClose = NULL;
+    VSILFILE *fp = NULL;
     if( poOpenInfo->fpL != NULL )
     {
         fp = poOpenInfo->fpL;
@@ -340,201 +368,215 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
     }
     else
     {
-        fpToClose = fp = VSIFOpenL( pszFilename, "r" );
+        fp = VSIFOpenL(pszFilename, "r");
         if( fp == NULL )
             return false;
+        fpToClose = fp;
     }
 
-    bool bExpatCompatibleEncoding = false;
-    bool bHas3D = false;
-    bool bHintConsiderEPSGAsURN = false;
-    bool bAnalyzeSRSPerFeature = true;
-
-    char szSRSName[128];
-    szSRSName[0] = '\0';
-
-/* -------------------------------------------------------------------- */
-/*      Load a header chunk and check for signs it is GML               */
-/* -------------------------------------------------------------------- */
-
-    size_t nRead = VSIFReadL( szHeader, 1, sizeof(szHeader)-1, fp );
-    if (nRead <= 0)
+    // Load a header chunk and check for signs it is GML.
+    char szHeader[4096] = {};
+    size_t nRead = VSIFReadL(szHeader, 1, sizeof(szHeader) - 1, fp);
+    if (nRead == 0)
     {
         if( fpToClose )
-            VSIFCloseL( fpToClose );
+            VSIFCloseL(fpToClose);
         return false;
     }
     szHeader[nRead] = '\0';
 
-    /* Might be a OS-Mastermap gzipped GML, so let be nice and try to open */
-    /* it transparently with /vsigzip/ */
+    CPLString osWithVsiGzip;
+
+    // Might be a OS-Mastermap gzipped GML, so let be nice and try to open
+    // it transparently with /vsigzip/.
     if ( ((GByte*)szHeader)[0] == 0x1f && ((GByte*)szHeader)[1] == 0x8b &&
             EQUAL(CPLGetExtension(pszFilename), "gz") &&
             !STARTS_WITH(pszFilename, "/vsigzip/") )
     {
         if( fpToClose )
-            VSIFCloseL( fpToClose );
+            VSIFCloseL(fpToClose);
         fpToClose = NULL;
         osWithVsiGzip = "/vsigzip/";
         osWithVsiGzip += pszFilename;
 
         pszFilename = osWithVsiGzip;
 
-        fp = fpToClose = VSIFOpenL( pszFilename, "r" );
+        fp = fpToClose = VSIFOpenL(pszFilename, "r");
         if( fp == NULL )
             return false;
 
-        nRead = VSIFReadL( szHeader, 1, sizeof(szHeader) - 1, fp );
-        if (nRead <= 0)
+        nRead = VSIFReadL(szHeader, 1, sizeof(szHeader) - 1, fp);
+        if (nRead == 0)
         {
-            VSIFCloseL( fpToClose );
+            VSIFCloseL(fpToClose);
             return false;
         }
         szHeader[nRead] = '\0';
     }
 
-/* -------------------------------------------------------------------- */
-/*      Check for a UTF-8 BOM and skip if found                         */
-/*                                                                      */
-/*      TODO: BOM is variable-length parameter and depends on encoding. */
-/*            Add BOM detection for other encodings.                    */
-/* -------------------------------------------------------------------- */
+    // Check for a UTF-8 BOM and skip if found.
+
+    // TODO: BOM is variable-length parameter and depends on encoding. */
+    // Add BOM detection for other encodings.
 
     // Used to skip to actual beginning of XML data
-    char* szPtr = szHeader;
+    char *szPtr = szHeader;
 
-    if( ( (unsigned char)szHeader[0] == 0xEF )
-        && ( (unsigned char)szHeader[1] == 0xBB )
-        && ( (unsigned char)szHeader[2] == 0xBF) )
+    if( (static_cast<unsigned char>(szHeader[0]) == 0xEF) &&
+        (static_cast<unsigned char>(szHeader[1]) == 0xBB) &&
+        (static_cast<unsigned char>(szHeader[2]) == 0xBF) )
     {
         szPtr += 3;
     }
 
-    const char* pszEncoding = strstr(szPtr, "encoding=");
+    bool bExpatCompatibleEncoding = false;
+
+    const char *pszEncoding = strstr(szPtr, "encoding=");
     if (pszEncoding)
-        bExpatCompatibleEncoding = (pszEncoding[9] == '\'' || pszEncoding[9] == '"') &&
-                                    (STARTS_WITH_CI(pszEncoding + 10, "UTF-8") ||
-                                    STARTS_WITH_CI(pszEncoding + 10, "ISO-8859-15") ||
-                                    (STARTS_WITH_CI(pszEncoding + 10, "ISO-8859-1") &&
-                                        pszEncoding[20] == pszEncoding[9])) ;
+        bExpatCompatibleEncoding =
+            (pszEncoding[9] == '\'' || pszEncoding[9] == '"') &&
+            (STARTS_WITH_CI(pszEncoding + 10, "UTF-8") ||
+             STARTS_WITH_CI(pszEncoding + 10, "ISO-8859-15") ||
+             (STARTS_WITH_CI(pszEncoding + 10, "ISO-8859-1") &&
+              pszEncoding[20] == pszEncoding[9]));
     else
-        bExpatCompatibleEncoding = true; /* utf-8 is the default */
+        bExpatCompatibleEncoding = true;  // utf-8 is the default.
 
-    bHas3D = strstr(szPtr, "srsDimension=\"3\"") != NULL || strstr(szPtr, "<gml:Z>") != NULL;
+    const bool bHas3D = strstr(szPtr, "srsDimension=\"3\"") != NULL ||
+                        strstr(szPtr, "<gml:Z>") != NULL;
 
-/* -------------------------------------------------------------------- */
-/*      Here, we expect the opening chevrons of GML tree root element   */
-/* -------------------------------------------------------------------- */
+    // Here, we expect the opening chevrons of GML tree root element.
     if( szPtr[0] != '<' || !CheckHeader(szPtr) )
     {
         if( fpToClose )
-            VSIFCloseL( fpToClose );
+            VSIFCloseL(fpToClose);
         return false;
     }
 
-    /* Now we definitely own the file descriptor */
+    // Now we definitely own the file descriptor.
     if( fp == poOpenInfo->fpL )
         poOpenInfo->fpL = NULL;
 
-    /* Small optimization: if we parse a <wfs:FeatureCollection>  and */
-    /* that numberOfFeatures is set, we can use it to set the FeatureCount */
-    /* but *ONLY* if there's just one class ! */
-    const char* pszFeatureCollection = strstr(szPtr, "wfs:FeatureCollection");
+    // Small optimization: if we parse a <wfs:FeatureCollection> and
+    // that numberOfFeatures is set, we can use it to set the FeatureCount
+    // but *ONLY* if there's just one class.
+    const char *pszFeatureCollection = strstr(szPtr, "wfs:FeatureCollection");
     if (pszFeatureCollection == NULL)
-        pszFeatureCollection = strstr(szPtr, "gml:FeatureCollection"); /* GML 3.2.1 output */
+        // GML 3.2.1 output.
+        pszFeatureCollection = strstr(szPtr, "gml:FeatureCollection");
     if (pszFeatureCollection == NULL)
     {
-        pszFeatureCollection = strstr(szPtr, "<FeatureCollection"); /* Deegree WFS 1.0.0 output */
-        if (pszFeatureCollection && strstr(szPtr, "xmlns:wfs=\"http://www.opengis.net/wfs\"") == NULL)
+        // Deegree WFS 1.0.0 output.
+        pszFeatureCollection = strstr(szPtr, "<FeatureCollection");
+        if (pszFeatureCollection &&
+            strstr(szPtr, "xmlns:wfs=\"http://www.opengis.net/wfs\"") == NULL)
             pszFeatureCollection = NULL;
     }
+
+    GIntBig nNumberOfFeatures = 0;
     if (pszFeatureCollection)
     {
         bExposeGMLId = true;
         bIsWFS = true;
-        const char* pszNumberOfFeatures = strstr(szPtr, "numberOfFeatures=");
+        const char *pszNumberOfFeatures = strstr(szPtr, "numberOfFeatures=");
         if (pszNumberOfFeatures)
         {
             pszNumberOfFeatures += 17;
             char ch = pszNumberOfFeatures[0];
-            if ((ch == '\'' || ch == '"') && strchr(pszNumberOfFeatures + 1, ch) != NULL)
+            if ((ch == '\'' || ch == '"') &&
+                strchr(pszNumberOfFeatures + 1, ch) != NULL)
             {
                 nNumberOfFeatures = CPLAtoGIntBig(pszNumberOfFeatures + 1);
             }
         }
-        else if ((pszNumberOfFeatures = strstr(szPtr, "numberReturned=")) != NULL) /* WFS 2.0.0 */
+        else if ((pszNumberOfFeatures = strstr(szPtr, "numberReturned=")) !=
+                 NULL)
         {
+            // WFS 2.0.0
             pszNumberOfFeatures += 15;
             char ch = pszNumberOfFeatures[0];
-            if ((ch == '\'' || ch == '"') && strchr(pszNumberOfFeatures + 1, ch) != NULL)
+            if ((ch == '\'' || ch == '"') &&
+                strchr(pszNumberOfFeatures + 1, ch) != NULL)
             {
-                /* 'unknown' might be a valid value in a corrected version of WFS 2.0 */
-                /* but it will also evaluate to 0, that is considered as unknown, so nothing */
-                /* particular to do */
+                // 'unknown' might be a valid value in a corrected version of
+                // WFS 2.0 but it will also evaluate to 0, that is considered as
+                // unknown, so nothing particular to do.
                 nNumberOfFeatures = CPLAtoGIntBig(pszNumberOfFeatures + 1);
             }
         }
     }
     else if (STARTS_WITH(pszFilename, "/vsimem/tempwfs_"))
     {
-        /* http://regis.intergraph.com/wfs/dcmetro/request.asp? returns a <G:FeatureCollection> */
-        /* Who knows what servers can return ? Ok, so when in the context of the WFS driver */
-        /* always expose the gml:id to avoid later crashes */
+        // http://regis.intergraph.com/wfs/dcmetro/request.asp? returns a
+        // <G:FeatureCollection> Who knows what servers can return?  When
+        // in the context of the WFS driver always expose the gml:id to avoid
+        // later crashes.
         bExposeGMLId = true;
         bIsWFS = true;
     }
     else
     {
         bExposeGMLId = strstr(szPtr, " gml:id=\"") != NULL ||
-                        strstr(szPtr, " gml:id='") != NULL;
+                       strstr(szPtr, " gml:id='") != NULL;
         bExposeFid = strstr(szPtr, " fid=\"") != NULL ||
-                        strstr(szPtr, " fid='") != NULL;
+                     strstr(szPtr, " fid='") != NULL;
     }
 
-    const char* pszExposeGMLId = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
-        "EXPOSE_GML_ID", CPLGetConfigOption("GML_EXPOSE_GML_ID", NULL));
+    const char *pszExposeGMLId =
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "EXPOSE_GML_ID",
+                             CPLGetConfigOption("GML_EXPOSE_GML_ID", NULL));
     if (pszExposeGMLId)
         bExposeGMLId = CPLTestBool(pszExposeGMLId);
 
-    const char* pszExposeFid = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
-        "EXPOSE_FID", CPLGetConfigOption("GML_EXPOSE_FID", NULL));
+    const char *pszExposeFid =
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "EXPOSE_FID",
+                             CPLGetConfigOption("GML_EXPOSE_FID", NULL));
     if (pszExposeFid)
         bExposeFid = CPLTestBool(pszExposeFid);
 
-    bHintConsiderEPSGAsURN = strstr(szPtr, "xmlns:fme=\"http://www.safe.com/gml/fme\"") != NULL;
+    const bool bHintConsiderEPSGAsURN =
+        strstr(szPtr, "xmlns:fme=\"http://www.safe.com/gml/fme\"") != NULL;
+
+    char szSRSName[128] = {};
+    bool bAnalyzeSRSPerFeature = true;
 
-    /* MTKGML */
+    // MTKGML.
     if( strstr(szPtr, "<Maastotiedot") != NULL )
     {
-        if( strstr(szPtr, "http://xml.nls.fi/XML/Namespace/Maastotietojarjestelma/SiirtotiedostonMalli/2011-02") == NULL )
-            CPLDebug("GML", "Warning: a MTKGML file was detected, but its namespace is unknown");
+        if( strstr(
+                szPtr,
+                "http://xml.nls.fi/XML/Namespace/"
+                "Maastotietojarjestelma/SiirtotiedostonMalli/2011-02") == NULL )
+            CPLDebug(
+                "GML",
+                "Warning: a MTKGML file was detected, "
+                "but its namespace is unknown");
         bAnalyzeSRSPerFeature = false;
         bUseGlobalSRSName = true;
         if( !ExtractSRSName(szPtr, szSRSName, sizeof(szSRSName)) )
             strcpy(szSRSName, "EPSG:3067");
     }
 
-    pszSchemaLocation = strstr(szPtr, "schemaLocation=");
+    const char *pszSchemaLocation = strstr(szPtr, "schemaLocation=");
     if (pszSchemaLocation)
         pszSchemaLocation += strlen("schemaLocation=");
 
+    bool bCheckAuxFile = true;
     if (STARTS_WITH(pszFilename, "/vsicurl_streaming/"))
         bCheckAuxFile = false;
     else if (STARTS_WITH(pszFilename, "/vsicurl/") &&
-             (strstr(pszFilename, "?SERVICE=") || strstr(pszFilename, "&SERVICE=")) )
+             (strstr(pszFilename, "?SERVICE=") ||
+              strstr(pszFilename, "&SERVICE=")) )
         bCheckAuxFile = false;
 
     bool bIsWFSJointLayer = bIsWFS && strstr(szPtr, "<wfs:Tuple>");
     if( bIsWFSJointLayer )
         bExposeGMLId = false;
 
-/* -------------------------------------------------------------------- */
-/*      We assume now that it is GML.  Instantiate a GMLReader on it.   */
-/* -------------------------------------------------------------------- */
-
-    const char* pszReadMode = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
-            "READ_MODE",
-            CPLGetConfigOption("GML_READ_MODE", "AUTO"));
+    // We assume now that it is GML.  Instantiate a GMLReader on it.
+    const char *pszReadMode =
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "READ_MODE",
+                             CPLGetConfigOption("GML_READ_MODE", "AUTO"));
     if( EQUAL(pszReadMode, "AUTO") )
         pszReadMode = NULL;
     if (pszReadMode == NULL || EQUAL(pszReadMode, "STANDARD"))
@@ -545,45 +587,51 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         eReadMode = INTERLEAVED_LAYERS;
     else
     {
-        CPLDebug("GML", "Unrecognized value for GML_READ_MODE configuration option.");
+        CPLDebug("GML",
+                 "Unrecognized value for GML_READ_MODE configuration option.");
     }
 
-    m_bInvertAxisOrderIfLatLong =
-        CPLTestBool(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
-            "INVERT_AXIS_ORDER_IF_LAT_LONG",
-            CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES")));
+    m_bInvertAxisOrderIfLatLong = CPLTestBool(CSLFetchNameValueDef(
+        poOpenInfo->papszOpenOptions, "INVERT_AXIS_ORDER_IF_LAT_LONG",
+        CPLGetConfigOption("GML_INVERT_AXIS_ORDER_IF_LAT_LONG", "YES")));
 
-    const char* pszConsiderEPSGAsURN =
-        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
-            "CONSIDER_EPSG_AS_URN",
-            CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", "AUTO"));
+    const char *pszConsiderEPSGAsURN = CSLFetchNameValueDef(
+        poOpenInfo->papszOpenOptions, "CONSIDER_EPSG_AS_URN",
+        CPLGetConfigOption("GML_CONSIDER_EPSG_AS_URN", "AUTO"));
     if( !EQUAL(pszConsiderEPSGAsURN, "AUTO") )
         m_bConsiderEPSGAsURN = CPLTestBool(pszConsiderEPSGAsURN);
     else if (bHintConsiderEPSGAsURN)
     {
-        /* GML produced by FME (at least CanVec GML) seem to honour EPSG axis ordering */
-        CPLDebug("GML", "FME-produced GML --> consider that GML_CONSIDER_EPSG_AS_URN is set to YES");
+        // GML produced by FME (at least CanVec GML) seem to honour EPSG axis
+        // ordering.
+        CPLDebug("GML",
+                 "FME-produced GML --> "
+                 "consider that GML_CONSIDER_EPSG_AS_URN is set to YES");
         m_bConsiderEPSGAsURN = true;
     }
     else
+    {
         m_bConsiderEPSGAsURN = false;
+    }
 
-    const char* pszSwapCoordinates =
-        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
-                             "SWAP_COORDINATES",
-            CPLGetConfigOption("GML_SWAP_COORDINATES", "AUTO"));
-    m_eSwapCoordinates = EQUAL(pszSwapCoordinates, "AUTO") ? GML_SWAP_AUTO:
-                         CPLTestBool(pszSwapCoordinates) ? GML_SWAP_YES: GML_SWAP_NO;
+    const char *pszSwapCoordinates = CSLFetchNameValueDef(
+        poOpenInfo->papszOpenOptions, "SWAP_COORDINATES",
+        CPLGetConfigOption("GML_SWAP_COORDINATES", "AUTO"));
+    m_eSwapCoordinates =
+        EQUAL(pszSwapCoordinates, "AUTO")
+            ? GML_SWAP_AUTO
+            : CPLTestBool(pszSwapCoordinates) ? GML_SWAP_YES : GML_SWAP_NO;
 
-    m_bGetSecondaryGeometryOption = CPLTestBool(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
+    m_bGetSecondaryGeometryOption =
+        CPLTestBool(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
 
-    /* EXPAT is faster than Xerces, so when it is safe to use it, use it ! */
-    /* The only interest of Xerces is for rare encodings that Expat doesn't handle */
-    /* but UTF-8 is well handled by Expat */
+    // EXPAT is faster than Xerces, so when it is safe to use it, use it!
+    // The only interest of Xerces is for rare encodings that Expat doesn't
+    // handle, but UTF-8 is well handled by Expat.
     bool bUseExpatParserPreferably = bExpatCompatibleEncoding;
 
-    /* Override default choice */
-    const char* pszGMLParser = CPLGetConfigOption("GML_PARSER", NULL);
+    // Override default choice.
+    const char *pszGMLParser = CPLGetConfigOption("GML_PARSER", NULL);
     if (pszGMLParser)
     {
         if (EQUAL(pszGMLParser, "EXPAT"))
@@ -592,111 +640,104 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
             bUseExpatParserPreferably = false;
     }
 
-    poReader = CreateGMLReader( bUseExpatParserPreferably,
-                                m_bInvertAxisOrderIfLatLong,
-                                m_bConsiderEPSGAsURN,
-                                m_eSwapCoordinates,
-                                m_bGetSecondaryGeometryOption );
+    poReader = CreateGMLReader(bUseExpatParserPreferably,
+                               m_bInvertAxisOrderIfLatLong,
+                               m_bConsiderEPSGAsURN,
+                               m_eSwapCoordinates,
+                               m_bGetSecondaryGeometryOption);
     if( poReader == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "File %s appears to be GML but the GML reader can't\n"
-                  "be instantiated, likely because Xerces or Expat support was\n"
-                  "not configured in.",
-                  pszFilename );
-        VSIFCloseL( fp );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "File %s appears to be GML but the GML reader can't\n"
+                 "be instantiated, likely because Xerces or Expat support was\n"
+                 "not configured in.",
+                 pszFilename);
+        VSIFCloseL(fp);
         return false;
     }
 
-    poReader->SetSourceFile( pszFilename );
-    ((GMLReader*)poReader)->SetIsWFSJointLayer(bIsWFSJointLayer);
-    bEmptyAsNull = CPL_TO_BOOL(CSLFetchBoolean(poOpenInfo->papszOpenOptions, "EMPTY_AS_NULL", TRUE));
-    ((GMLReader*)poReader)->SetEmptyAsNull(bEmptyAsNull);
-    ((GMLReader*)poReader)->SetReportAllAttributes(
-        CPL_TO_BOOL(CSLFetchBoolean(poOpenInfo->papszOpenOptions, "GML_ATTRIBUTES_TO_OGR_FIELDS",
-            CPLTestBool(CPLGetConfigOption("GML_ATTRIBUTES_TO_OGR_FIELDS", "NO")))));
-
-/* -------------------------------------------------------------------- */
-/*      Find <gml:description>, <gml:name> and <gml:boundedBy>          */
-/* -------------------------------------------------------------------- */
+    poReader->SetSourceFile(pszFilename);
+    static_cast<GMLReader *>(poReader)->SetIsWFSJointLayer(bIsWFSJointLayer);
+    bEmptyAsNull =
+        CPLFetchBool(poOpenInfo->papszOpenOptions, "EMPTY_AS_NULL", true);
+    static_cast<GMLReader *>(poReader)->SetEmptyAsNull(bEmptyAsNull);
+    static_cast<GMLReader *>(poReader)->SetReportAllAttributes(CPLFetchBool(
+        poOpenInfo->papszOpenOptions, "GML_ATTRIBUTES_TO_OGR_FIELDS",
+        CPLTestBool(CPLGetConfigOption("GML_ATTRIBUTES_TO_OGR_FIELDS", "NO"))));
 
+    // Find <gml:description>, <gml:name> and <gml:boundedBy>
     FindAndParseTopElements(fp);
 
     if( szSRSName[0] != '\0' )
         poReader->SetGlobalSRSName(szSRSName);
 
-/* -------------------------------------------------------------------- */
-/*      Resolve the xlinks in the source file and save it with the      */
-/*      extension ".resolved.gml". The source file will to set to that. */
-/* -------------------------------------------------------------------- */
-
+    // Resolve the xlinks in the source file and save it with the
+    // extension ".resolved.gml". The source file will to set to that.
     char *pszXlinkResolvedFilename = NULL;
     const char *pszOption = CPLGetConfigOption("GML_SAVE_RESOLVED_TO", NULL);
     bool bResolve = true;
     bool bHugeFile = false;
     if( pszOption != NULL && STARTS_WITH_CI(pszOption, "SAME") )
     {
-        // "SAME" will overwrite the existing gml file
-        pszXlinkResolvedFilename = CPLStrdup( pszFilename );
+        // "SAME" will overwrite the existing gml file.
+        pszXlinkResolvedFilename = CPLStrdup(pszFilename);
     }
     else if( pszOption != NULL &&
-             CPLStrnlen( pszOption, 5 ) >= 5 &&
-             STARTS_WITH_CI(pszOption - 4 + strlen( pszOption ), ".gml") )
+             CPLStrnlen(pszOption, 5) >= 5 &&
+             STARTS_WITH_CI(pszOption - 4 + strlen(pszOption), ".gml") )
     {
-        // Any string ending with ".gml" will try and write to it
-        pszXlinkResolvedFilename = CPLStrdup( pszOption );
+        // Any string ending with ".gml" will try and write to it.
+        pszXlinkResolvedFilename = CPLStrdup(pszOption);
     }
     else
     {
         // When no option is given or is not recognised,
         // use the same file name with the extension changed to .resolved.gml
-        pszXlinkResolvedFilename = CPLStrdup(
-                            CPLResetExtension( pszFilename, "resolved.gml" ) );
+        pszXlinkResolvedFilename =
+            CPLStrdup(CPLResetExtension(pszFilename, "resolved.gml"));
 
         // Check if the file already exists.
         VSIStatBufL sResStatBuf, sGMLStatBuf;
-        if( bCheckAuxFile && VSIStatL( pszXlinkResolvedFilename, &sResStatBuf ) == 0 )
+        if( bCheckAuxFile && VSIStatL(pszXlinkResolvedFilename, &sResStatBuf) == 0 )
         {
-            if( VSIStatL( pszFilename, &sGMLStatBuf ) == 0 &&
+            if( VSIStatL(pszFilename, &sGMLStatBuf) == 0 &&
                 sGMLStatBuf.st_mtime > sResStatBuf.st_mtime )
             {
-                CPLDebug( "GML",
-                          "Found %s but ignoring because it appears\n"
-                          "be older than the associated GML file.",
-                          pszXlinkResolvedFilename );
+                CPLDebug("GML",
+                         "Found %s but ignoring because it appears\n"
+                         "be older than the associated GML file.",
+                         pszXlinkResolvedFilename);
             }
             else
             {
-                poReader->SetSourceFile( pszXlinkResolvedFilename );
+                poReader->SetSourceFile(pszXlinkResolvedFilename);
                 bResolve = false;
             }
         }
     }
 
-    const char *pszSkipOption = CPLGetConfigOption( "GML_SKIP_RESOLVE_ELEMS",
-                                                    "ALL");
+    const char *pszSkipOption =
+        CPLGetConfigOption("GML_SKIP_RESOLVE_ELEMS", "ALL");
     char **papszSkip = NULL;
-    if( EQUAL( pszSkipOption, "ALL" ) )
+    if( EQUAL(pszSkipOption, "ALL") )
         bResolve = false;
-    else if( EQUAL( pszSkipOption, "HUGE" ) )//exactly as NONE, but intended for HUGE files
+    else if( EQUAL(pszSkipOption, "HUGE") )
+        // Exactly as NONE, but intended for HUGE files
         bHugeFile = true;
-    else if( !EQUAL( pszSkipOption, "NONE" ) )//use this to resolve everything
-        papszSkip = CSLTokenizeString2( pszSkipOption, ",",
-                                           CSLT_STRIPLEADSPACES |
-                                           CSLT_STRIPENDSPACES );
-    bool        bHaveSchema = false;
-    bool        bSchemaDone = false;
-
-/* -------------------------------------------------------------------- */
-/*      Is some GML Feature Schema (.gfs) TEMPLATE required ?           */
-/* -------------------------------------------------------------------- */
+    else if( !EQUAL(pszSkipOption, "NONE") )  // Use this to resolve everything.
+        papszSkip = CSLTokenizeString2(
+            pszSkipOption, ",", CSLT_STRIPLEADSPACES | CSLT_STRIPENDSPACES);
+    bool bHaveSchema = false;
+    bool bSchemaDone = false;
+
+    // Is some GML Feature Schema (.gfs) TEMPLATE required?
     const char *pszGFSTemplateName =
         CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "GFS_TEMPLATE",
-                CPLGetConfigOption( "GML_GFS_TEMPLATE", NULL));
+                             CPLGetConfigOption("GML_GFS_TEMPLATE", NULL));
     if( pszGFSTemplateName != NULL )
     {
-        /* attempting to load the GFS TEMPLATE */
-        bHaveSchema = poReader->LoadClasses( pszGFSTemplateName );
+        // Attempt to load the GFS TEMPLATE.
+        bHaveSchema = poReader->LoadClasses(pszGFSTemplateName);
     }
 
     if( bResolve )
@@ -705,80 +746,79 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         {
             bSchemaDone = true;
             bool bSqliteIsTempFile =
-                CPLTestBool(CPLGetConfigOption( "GML_HUGE_TEMPFILE", "YES"));
-            int iSqliteCacheMB = atoi(CPLGetConfigOption( "OGR_SQLITE_CACHE", "0"));
-            if( poReader->HugeFileResolver( pszXlinkResolvedFilename,
-                                            bSqliteIsTempFile,
-                                            iSqliteCacheMB ) == false )
+                CPLTestBool(CPLGetConfigOption("GML_HUGE_TEMPFILE", "YES"));
+            int iSqliteCacheMB =
+                atoi(CPLGetConfigOption("OGR_SQLITE_CACHE", "0"));
+            if( poReader->HugeFileResolver(pszXlinkResolvedFilename,
+                                           bSqliteIsTempFile,
+                                           iSqliteCacheMB) == false )
             {
-                // we assume an errors have been reported.
+                // Assume an error has been reported.
                 VSIFCloseL(fp);
-                CPLFree( pszXlinkResolvedFilename );
+                CPLFree(pszXlinkResolvedFilename);
                 return false;
             }
         }
         else
         {
-            poReader->ResolveXlinks( pszXlinkResolvedFilename,
-                                     &bOutIsTempFile,
-                                     papszSkip );
+            poReader->ResolveXlinks(pszXlinkResolvedFilename,
+                                    &bOutIsTempFile,
+                                    papszSkip);
         }
     }
 
-    CPLFree( pszXlinkResolvedFilename );
+    CPLFree(pszXlinkResolvedFilename);
     pszXlinkResolvedFilename = NULL;
-    CSLDestroy( papszSkip );
+    CSLDestroy(papszSkip);
     papszSkip = NULL;
 
-    /* If the source filename for the reader is still the GML filename, then */
-    /* we can directly provide the file pointer. Otherwise we close it */
+    // If the source filename for the reader is still the GML filename, then
+    // we can directly provide the file pointer. Otherwise close it.
     if (strcmp(poReader->GetSourceFileName(), pszFilename) == 0)
         poReader->SetFP(fp);
     else
         VSIFCloseL(fp);
     fp = NULL;
 
-    /* Is a prescan required ? */
+    // Is a prescan required?
     if( bHaveSchema && !bSchemaDone )
     {
-        /* We must detect which layers are actually present in the .gml */
-        /* and how many features they have */
+        // We must detect which layers are actually present in the .gml
+        // and how many features they have.
         if( !poReader->PrescanForTemplate() )
         {
-            // we assume an errors have been reported.
+            // Assume an error has been reported.
             return false;
         }
     }
 
-    CPLString osGFSFilename = CPLResetExtension( pszFilename, "gfs" );
+    CPLString osGFSFilename = CPLResetExtension(pszFilename, "gfs");
     if (STARTS_WITH(osGFSFilename, "/vsigzip/"))
         osGFSFilename = osGFSFilename.substr(strlen("/vsigzip/"));
 
-/* -------------------------------------------------------------------- */
-/*      Can we find a GML Feature Schema (.gfs) for the input file?     */
-/* -------------------------------------------------------------------- */
-    if( !bHaveSchema && osXSDFilename.size() == 0)
+    // Can we find a GML Feature Schema (.gfs) for the input file?
+    if( !bHaveSchema && osXSDFilename.empty())
     {
         VSIStatBufL sGFSStatBuf;
-        if( bCheckAuxFile && VSIStatL( osGFSFilename, &sGFSStatBuf ) == 0 )
+        if( bCheckAuxFile && VSIStatL(osGFSFilename, &sGFSStatBuf) == 0 )
         {
             VSIStatBufL sGMLStatBuf;
-            if( VSIStatL( pszFilename, &sGMLStatBuf ) == 0 &&
+            if( VSIStatL(pszFilename, &sGMLStatBuf) == 0 &&
                 sGMLStatBuf.st_mtime > sGFSStatBuf.st_mtime )
             {
-                CPLDebug( "GML",
-                          "Found %s but ignoring because it appears\n"
-                          "be older than the associated GML file.",
-                          osGFSFilename.c_str() );
+                CPLDebug("GML",
+                         "Found %s but ignoring because it appears\n"
+                         "be older than the associated GML file.",
+                         osGFSFilename.c_str());
             }
             else
             {
-                bHaveSchema = poReader->LoadClasses( osGFSFilename );
+                bHaveSchema = poReader->LoadClasses(osGFSFilename);
                 if (bHaveSchema)
                 {
-                    pszXSDFilenameTmp = CPLResetExtension( pszFilename, "xsd" );
-                    if( VSIStatExL( pszXSDFilenameTmp, &sGMLStatBuf,
-                                    VSI_STAT_EXISTS_FLAG ) == 0 )
+                    pszXSDFilenameTmp = CPLResetExtension(pszFilename, "xsd");
+                    if( VSIStatExL(pszXSDFilenameTmp, &sGMLStatBuf,
+                                   VSI_STAT_EXISTS_FLAG) == 0 )
                     {
                         CPLDebug("GML", "Using %s file, ignoring %s",
                                  osGFSFilename.c_str(), pszXSDFilenameTmp);
@@ -788,23 +828,22 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Can we find an xsd which might conform to tbe GML3 Level 0      */
-/*      profile?  We really ought to look for it based on the rules     */
-/*      schemaLocation in the GML feature collection but for now we     */
-/*      just hopes it is in the same director with the same name.       */
-/* -------------------------------------------------------------------- */
+    // Can we find an xsd which might conform to tbe GML3 Level 0
+    // profile?  We really ought to look for it based on the rules
+    // schemaLocation in the GML feature collection but for now we
+    // just hopes it is in the same director with the same name.
+
     bool bHasFoundXSD = false;
 
     if( !bHaveSchema )
     {
-        char** papszTypeNames = NULL;
+        char **papszTypeNames = NULL;
 
         VSIStatBufL sXSDStatBuf;
-        if (osXSDFilename.size() == 0)
+        if (osXSDFilename.empty())
         {
-            osXSDFilename = CPLResetExtension( pszFilename, "xsd" );
-            if( bCheckAuxFile && VSIStatExL( osXSDFilename, &sXSDStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+            osXSDFilename = CPLResetExtension(pszFilename, "xsd");
+            if( bCheckAuxFile && VSIStatExL(osXSDFilename, &sXSDStatBuf, VSI_STAT_EXISTS_FLAG) == 0 )
             {
                 bHasFoundXSD = true;
             }
@@ -813,85 +852,116 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         {
             if ( STARTS_WITH(osXSDFilename, "http://") ||
                  STARTS_WITH(osXSDFilename, "https://") ||
-                 VSIStatExL( osXSDFilename, &sXSDStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 )
+                 VSIStatExL(osXSDFilename, &sXSDStatBuf, VSI_STAT_EXISTS_FLAG) == 0 )
             {
                 bHasFoundXSD = true;
             }
         }
 
-        /* If not found, try if there is a schema in the gml_registry.xml */
-        /* that might match a declared namespace and featuretype */
+        // If not found, try if there is a schema in the gml_registry.xml
+        // that might match a declared namespace and featuretype.
         if( !bHasFoundXSD )
         {
-            GMLRegistry oRegistry(CSLFetchNameValueDef(
-                    poOpenInfo->papszOpenOptions, "REGISTRY",
-                                    CPLGetConfigOption("GML_REGISTRY", "")));
+            GMLRegistry oRegistry(
+                CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "REGISTRY",
+                                     CPLGetConfigOption("GML_REGISTRY", "")));
             if( oRegistry.Parse() )
             {
                 CPLString osHeader(szHeader);
-                for( size_t iNS = 0; iNS < oRegistry.aoNamespaces.size(); iNS ++ )
+                for( size_t iNS = 0; iNS < oRegistry.aoNamespaces.size(); iNS++ )
                 {
-                    GMLRegistryNamespace& oNamespace = oRegistry.aoNamespaces[iNS];
-                    const char* pszNSToFind =
-                                CPLSPrintf("xmlns:%s", oNamespace.osPrefix.c_str());
-                    const char* pszURIToFind =
-                                CPLSPrintf("\"%s\"", oNamespace.osURI.c_str());
-                    /* Case sensitive comparison since below test that also */
-                    /* uses the namespace prefix is case sensitive */
-                    if( osHeader.find(pszNSToFind) != std::string::npos &&
-                        strstr(szHeader, pszURIToFind) != NULL )
+                    GMLRegistryNamespace &oNamespace =
+                        oRegistry.aoNamespaces[iNS];
+                    // When namespace is omitted or fit with case sensitive match for
+                    // name space prefix, then go next to find feature match.
+                    //
+                    // Case sensitive comparison since below test that also
+                    // uses the namespace prefix is case sensitive.
+                    if( !oNamespace.osPrefix.empty() &&
+                        osHeader.find(CPLSPrintf("xmlns:%s",
+                            oNamespace.osPrefix.c_str()))
+                              == std::string::npos )
+                    {
+                        // namespace does not match with one of registry definition.
+                        // go to next entry.
+                        continue;
+                    }
+
+                    const char *pszURIToFind =
+                        CPLSPrintf("\"%s\"", oNamespace.osURI.c_str());
+                    if( strstr(szHeader, pszURIToFind) != NULL )
                     {
                         if( oNamespace.bUseGlobalSRSName )
                             bUseGlobalSRSName = true;
 
                         for( size_t iTypename = 0;
-                                    iTypename < oNamespace.aoFeatureTypes.size();
-                                    iTypename ++ )
+                             iTypename < oNamespace.aoFeatureTypes.size();
+                             iTypename++ )
                         {
-                            const char* pszElementToFind = NULL;
+                            const char *pszElementToFind = NULL;
 
-                            GMLRegistryFeatureType& oFeatureType =
-                                        oNamespace.aoFeatureTypes[iTypename];
+                            GMLRegistryFeatureType &oFeatureType =
+                                oNamespace.aoFeatureTypes[iTypename];
 
-                            if ( oFeatureType.osElementValue.size() )
-                                pszElementToFind = CPLSPrintf("%s:%s>%s",
-                                                              oNamespace.osPrefix.c_str(),
-                                                              oFeatureType.osElementName.c_str(),
-                                                              oFeatureType.osElementValue.c_str());
+                            if( !oNamespace.osPrefix.empty() )
+                            {
+                                if ( !oFeatureType.osElementValue.empty() )
+                                    pszElementToFind = CPLSPrintf(
+                                        "%s:%s>%s", oNamespace.osPrefix.c_str(),
+                                        oFeatureType.osElementName.c_str(),
+                                        oFeatureType.osElementValue.c_str());
+                                else
+                                    pszElementToFind = CPLSPrintf(
+                                        "%s:%s", oNamespace.osPrefix.c_str(),
+                                        oFeatureType.osElementName.c_str());
+                            }
                             else
-                                pszElementToFind = CPLSPrintf("%s:%s",
-                                                              oNamespace.osPrefix.c_str(),
-                                                              oFeatureType.osElementName.c_str());
-
-                            /* Case sensitive test since in a CadastralParcel feature */
-                            /* there is a property basicPropertyUnit xlink, not to be */
-                            /* confused with a top-level BasicPropertyUnit feature... */
-                            if( osHeader.find(pszElementToFind) != std::string::npos )
                             {
-                                if( oFeatureType.osSchemaLocation.size() )
+                                if ( !oFeatureType.osElementValue.empty() )
+                                    pszElementToFind = CPLSPrintf("%s>%s",
+                                                                  oFeatureType.osElementName.c_str(),
+                                                                  oFeatureType.osElementValue.c_str());
+                                else
+                                    pszElementToFind = CPLSPrintf("<%s",
+                                                                  oFeatureType.osElementName.c_str());
+                            }
+
+
+                            // Case sensitive test since in a CadastralParcel
+                            // feature there is a property basicPropertyUnit
+                            // xlink, not to be confused with a top-level
+                            // BasicPropertyUnit feature.
+                            if( osHeader.find(pszElementToFind) !=
+                                std::string::npos )
+                            {
+                                if( !oFeatureType.osSchemaLocation.empty() )
                                 {
-                                    osXSDFilename = oFeatureType.osSchemaLocation;
+                                    osXSDFilename =
+                                        oFeatureType.osSchemaLocation;
                                     if( STARTS_WITH(osXSDFilename, "http://") ||
                                         STARTS_WITH(osXSDFilename, "https://") ||
-                                        VSIStatExL( osXSDFilename, &sXSDStatBuf,
-                                                    VSI_STAT_EXISTS_FLAG ) == 0 )
+                                        VSIStatExL(osXSDFilename, &sXSDStatBuf,
+                                                   VSI_STAT_EXISTS_FLAG) == 0 )
                                     {
                                         bHasFoundXSD = true;
                                         bHaveSchema = true;
-                                        CPLDebug("GML", "Found %s for %s:%s in registry",
-                                                osXSDFilename.c_str(),
-                                                oNamespace.osPrefix.c_str(),
-                                                oFeatureType.osElementName.c_str());
+                                        CPLDebug(
+                                            "GML",
+                                            "Found %s for %s:%s in registry",
+                                            osXSDFilename.c_str(),
+                                            oNamespace.osPrefix.c_str(),
+                                            oFeatureType.osElementName.c_str());
                                     }
                                     else
                                     {
-                                        CPLDebug("GML", "Cannot open %s", osXSDFilename.c_str());
+                                        CPLDebug("GML", "Cannot open %s",
+                                                 osXSDFilename.c_str());
                                     }
                                 }
                                 else
                                 {
                                     bHaveSchema = poReader->LoadClasses(
-                                        oFeatureType.osGFSSchemaLocation );
+                                        oFeatureType.osGFSSchemaLocation);
                                     if( bHaveSchema )
                                     {
                                         CPLDebug("GML", "Found %s for %s:%s in registry",
@@ -914,50 +984,64 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
             (pszSchemaLocation[0] == '\'' || pszSchemaLocation[0] == '"') &&
              strchr(pszSchemaLocation + 1, pszSchemaLocation[0]) != NULL )
         {
-            char* pszSchemaLocationTmp1 = CPLStrdup(pszSchemaLocation + 1);
-            int nTruncLen = (int)(strchr(pszSchemaLocation + 1, pszSchemaLocation[0]) - (pszSchemaLocation + 1));
+            char *pszSchemaLocationTmp1 = CPLStrdup(pszSchemaLocation + 1);
+            int nTruncLen = static_cast<int>(
+                strchr(pszSchemaLocation + 1, pszSchemaLocation[0]) -
+                (pszSchemaLocation + 1));
             pszSchemaLocationTmp1[nTruncLen] = '\0';
-            char* pszSchemaLocationTmp2 = CPLUnescapeString(
-                pszSchemaLocationTmp1, NULL, CPLES_XML);
-            CPLString osEscaped = ReplaceSpaceByPct20IfNeeded(pszSchemaLocationTmp2);
+            char *pszSchemaLocationTmp2 =
+                CPLUnescapeString(pszSchemaLocationTmp1, NULL, CPLES_XML);
+            CPLString osEscaped =
+                ReplaceSpaceByPct20IfNeeded(pszSchemaLocationTmp2);
             CPLFree(pszSchemaLocationTmp2);
             pszSchemaLocationTmp2 = CPLStrdup(osEscaped);
             if (pszSchemaLocationTmp2)
             {
-                /* pszSchemaLocationTmp2 is of the form : */
-                /* http://namespace1 http://namespace1_schema_location http://namespace2 http://namespace1_schema_location2 */
-                /* So we try to find http://namespace1_schema_location that contains hints that it is the WFS application */
-                /* schema, i.e. if it contains typename= and request=DescribeFeatureType */
-                char** papszTokens = CSLTokenizeString2(pszSchemaLocationTmp2, " \r\n", 0);
+                // pszSchemaLocationTmp2 is of the form:
+                // http://namespace1 http://namespace1_schema_location http://namespace2 http://namespace1_schema_location2
+                // So we try to find http://namespace1_schema_location that
+                // contains hints that it is the WFS application */ schema,
+                // i.e. if it contains typename= and
+                // request=DescribeFeatureType.
+                char **papszTokens =
+                    CSLTokenizeString2(pszSchemaLocationTmp2, " \r\n", 0);
                 int nTokens = CSLCount(papszTokens);
                 if ((nTokens % 2) == 0)
                 {
-                    for(int i=0;i<nTokens;i+=2)
+                    for(int i = 0; i < nTokens; i += 2)
                     {
-                        const char* pszEscapedURL = papszTokens[i+1];
-                        char* pszLocation = CPLUnescapeString(pszEscapedURL, NULL, CPLES_URL);
+                        const char *pszEscapedURL = papszTokens[i + 1];
+                        char *pszLocation =
+                            CPLUnescapeString(pszEscapedURL, NULL, CPLES_URL);
                         CPLString osLocation = pszLocation;
                         CPLFree(pszLocation);
                         if (osLocation.ifind("typename=") != std::string::npos &&
-                            osLocation.ifind("request=DescribeFeatureType") != std::string::npos)
+                            osLocation.ifind("request=DescribeFeatureType") !=
+                                std::string::npos)
                         {
-                            CPLString osTypeName = CPLURLGetValue(osLocation, "typename");
-                            papszTypeNames = CSLTokenizeString2( osTypeName, ",", 0);
+                            CPLString osTypeName =
+                                CPLURLGetValue(osLocation, "typename");
+                            papszTypeNames =
+                                CSLTokenizeString2(osTypeName, ",", 0);
 
                             if (!bHasFoundXSD && CPLHTTPEnabled() &&
-                                CSLFetchBoolean(poOpenInfo->papszOpenOptions,
+                                CPLFetchBool(
+                                    poOpenInfo->papszOpenOptions,
                                     "DOWNLOAD_SCHEMA",
-                                    CPLTestBool(CPLGetConfigOption("GML_DOWNLOAD_WFS_SCHEMA", "YES"))) )
+                                    CPLTestBool(CPLGetConfigOption(
+                                        "GML_DOWNLOAD_WFS_SCHEMA", "YES"))))
                             {
-                                CPLHTTPResult* psResult = CPLHTTPFetch(pszEscapedURL, NULL);
+                                CPLHTTPResult *psResult =
+                                    CPLHTTPFetch(pszEscapedURL, NULL);
                                 if (psResult)
                                 {
-                                    if (psResult->nStatus == 0 && psResult->pabyData != NULL)
+                                    if (psResult->nStatus == 0 &&
+                                        psResult->pabyData != NULL)
                                     {
                                         bHasFoundXSD = true;
-                                        osXSDFilename =
-                                            CPLSPrintf("/vsimem/tmp_gml_xsd_%p.xsd", this);
-                                        VSILFILE* fpMem = VSIFileFromMemBuffer(
+                                        osXSDFilename = CPLSPrintf(
+                                            "/vsimem/tmp_gml_xsd_%p.xsd", this);
+                                        VSILFILE *fpMem = VSIFileFromMemBuffer(
                                             osXSDFilename, psResult->pabyData,
                                             psResult->nDataLen, TRUE);
                                         VSIFCloseL(fpMem);
@@ -979,22 +1063,27 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         bool bHasFeatureProperties = false;
         if( bHasFoundXSD )
         {
-            std::vector<GMLFeatureClass*> aosClasses;
+            std::vector<GMLFeatureClass *> aosClasses;
             bool bFullyUnderstood = false;
-            bHaveSchema = GMLParseXSD( osXSDFilename, aosClasses, bFullyUnderstood );
+            bHaveSchema =
+                GMLParseXSD(osXSDFilename, aosClasses, bFullyUnderstood);
 
             if( bHaveSchema && !bFullyUnderstood && bIsWFSJointLayer )
             {
-                CPLDebug("GML", "Schema found, but only partially understood. Cannot be used in a WFS join context");
-
-                std::vector<GMLFeatureClass*>::const_iterator oIter = aosClasses.begin();
-                std::vector<GMLFeatureClass*>::const_iterator oEndIter = aosClasses.end();
+                CPLDebug("GML",
+                         "Schema found, but only partially understood. "
+                         "Cannot be used in a WFS join context");
+
+                std::vector<GMLFeatureClass *>::const_iterator oIter =
+                    aosClasses.begin();
+                std::vector<GMLFeatureClass *>::const_iterator oEndIter =
+                    aosClasses.end();
                 while (oIter != oEndIter)
                 {
-                    GMLFeatureClass* poClass = *oIter;
+                    GMLFeatureClass *poClass = *oIter;
 
                     delete poClass;
-                    oIter ++;
+                    ++oIter;
                 }
                 aosClasses.resize(0);
                 bHaveSchema = false;
@@ -1003,29 +1092,31 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
             if( bHaveSchema )
             {
                 CPLDebug("GML", "Using %s", osXSDFilename.c_str());
-                std::vector<GMLFeatureClass*>::const_iterator oIter = aosClasses.begin();
-                std::vector<GMLFeatureClass*>::const_iterator oEndIter = aosClasses.end();
+                std::vector<GMLFeatureClass *>::const_iterator oIter =
+                    aosClasses.begin();
+                std::vector<GMLFeatureClass *>::const_iterator oEndIter =
+                    aosClasses.end();
                 while (oIter != oEndIter)
                 {
-                    GMLFeatureClass* poClass = *oIter;
+                    GMLFeatureClass *poClass = *oIter;
 
                     if( poClass->HasFeatureProperties() )
                     {
                         bHasFeatureProperties = true;
                         break;
                     }
-                    oIter ++;
+                    ++oIter;
                 }
 
                 oIter = aosClasses.begin();
                 while (oIter != oEndIter)
                 {
-                    GMLFeatureClass* poClass = *oIter;
-                    oIter ++;
+                    GMLFeatureClass *poClass = *oIter;
+                    ++oIter;
 
-                    /* We have no way of knowing if the geometry type is 25D */
-                    /* when examining the xsd only, so if there was a hint */
-                    /* it is, we force to 25D */
+                    // We have no way of knowing if the geometry type is 25D
+                    // when examining the xsd only, so if there was a hint
+                    // it is, we force to 25D.
                     if (bHas3D && poClass->GetGeometryPropertyCount() == 1)
                     {
                         poClass->GetGeometryProperty(0)->SetType(
@@ -1033,52 +1124,53 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                     }
 
                     bool bAddClass = true;
-                    /* If typenames are declared, only register the matching classes, in case */
-                    /* the XSD contains more layers, but not if feature classes contain */
-                    /* feature properties, in which case we will have embedded features that */
-                    /* will be reported as top-level features */
+                    // If typenames are declared, only register the matching
+                    // classes, in case the XSD contains more layers, but not if
+                    // feature classes contain feature properties, in which case
+                    // we will have embedded features that will be reported as
+                    // top-level features.
                     if( papszTypeNames != NULL && !bHasFeatureProperties )
                     {
                         bAddClass = false;
-                        char** papszIter = papszTypeNames;
+                        char **papszIter = papszTypeNames;
                         while (*papszIter && !bAddClass)
                         {
-                            const char* pszTypeName = *papszIter;
+                            const char *pszTypeName = *papszIter;
                             if (strcmp(pszTypeName, poClass->GetName()) == 0)
                                 bAddClass = true;
-                            papszIter ++;
+                            papszIter++;
                         }
 
-                        /* Retry by removing prefixes */
+                        // Retry by removing prefixes.
                         if (!bAddClass)
                         {
                             papszIter = papszTypeNames;
                             while (*papszIter && !bAddClass)
                             {
-                                const char* pszTypeName = *papszIter;
-                                const char* pszColon = strchr(pszTypeName, ':');
+                                const char *pszTypeName = *papszIter;
+                                const char *pszColon = strchr(pszTypeName, ':');
                                 if (pszColon)
                                 {
                                     pszTypeName = pszColon + 1;
-                                    if (strcmp(pszTypeName, poClass->GetName()) == 0)
+                                    if (strcmp(pszTypeName,
+                                               poClass->GetName()) == 0)
                                     {
                                         poClass->SetName(pszTypeName);
                                         bAddClass = true;
                                     }
                                 }
-                                papszIter ++;
+                                papszIter++;
                             }
                         }
-
                     }
 
                     if (bAddClass)
-                        poReader->AddClass( poClass );
+                        poReader->AddClass(poClass);
                     else
                         delete poClass;
                 }
 
-                poReader->SetClassListLocked( true );
+                poReader->SetClassListLocked(true);
             }
         }
 
@@ -1089,15 +1181,16 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
                 BuildJointClassFromXSD();
             }
 
-            /* For WFS, we can assume sequential layers */
+            // For WFS, we can assume sequential layers.
             if (poReader->GetClassCount() > 1 && pszReadMode == NULL &&
                 !bHasFeatureProperties)
             {
-                CPLDebug("GML", "WFS output. Using SEQUENTIAL_LAYERS read mode");
+                CPLDebug("GML",
+                         "WFS output. Using SEQUENTIAL_LAYERS read mode");
                 eReadMode = SEQUENTIAL_LAYERS;
             }
-            /* Sometimes the returned schema contains only <xs:include> that we don't resolve */
-            /* so ignore it */
+            // Sometimes the returned schema contains only <xs:include> that we
+            // don't resolve so ignore it.
             else if (poReader->GetClassCount() == 0)
                 bHaveSchema = false;
         }
@@ -1105,19 +1198,17 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         CSLDestroy(papszTypeNames);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Force a first pass to establish the schema.  Eventually we      */
-/*      will have mechanisms for remembering the schema and related     */
-/*      information.                                                    */
-/* -------------------------------------------------------------------- */
+    // Force a first pass to establish the schema.  Eventually we will have
+    // mechanisms for remembering the schema and related information.
     if( !bHaveSchema ||
-        CSLFetchBoolean(poOpenInfo->papszOpenOptions, "FORCE_SRS_DETECTION", FALSE) )
+        CPLFetchBool(poOpenInfo->papszOpenOptions, "FORCE_SRS_DETECTION",
+                     false) )
     {
         bool bOnlyDetectSRS = bHaveSchema;
-        if( !poReader->PrescanForSchema( true, bAnalyzeSRSPerFeature,
-                                         bOnlyDetectSRS ) )
+        if( !poReader->PrescanForSchema(true, bAnalyzeSRSPerFeature,
+                                        bOnlyDetectSRS) )
         {
-            // we assume an errors have been reported.
+            // Assume an error was reported.
             return false;
         }
         if( !bHaveSchema )
@@ -1130,7 +1221,7 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
             if( bHasFoundXSD )
             {
                 CPLDebug("GML", "Generating %s file, ignoring %s",
-                        osGFSFilename.c_str(), osXSDFilename.c_str());
+                         osGFSFilename.c_str(), osXSDFilename.c_str());
             }
         }
     }
@@ -1142,10 +1233,8 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         eReadMode = SEQUENTIAL_LAYERS;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Save the schema file if possible.  Don't make a fuss if we      */
-/*      can't ... could be read-only directory or something.            */
-/* -------------------------------------------------------------------- */
+    // Save the schema file if possible.  Don't make a fuss if we
+    // can't.  It could be read-only directory or something.
     if( !bHaveSchema && !poReader->HasStoppedParsing() &&
         !STARTS_WITH_CI(pszFilename, "/vsitar/") &&
         !STARTS_WITH_CI(pszFilename, "/vsizip/") &&
@@ -1154,28 +1243,26 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         !STARTS_WITH_CI(pszFilename, "/vsicurl/") &&
         !STARTS_WITH_CI(pszFilename, "/vsicurl_streaming/"))
     {
-        VSILFILE    *l_fp = NULL;
+        VSILFILE *l_fp = NULL;
 
         VSIStatBufL sGFSStatBuf;
-        if( VSIStatExL( osGFSFilename, &sGFSStatBuf, VSI_STAT_EXISTS_FLAG ) != 0
-            && (l_fp = VSIFOpenL( osGFSFilename, "wt" )) != NULL )
+        if( VSIStatExL(osGFSFilename, &sGFSStatBuf, VSI_STAT_EXISTS_FLAG) != 0 &&
+            (l_fp = VSIFOpenL(osGFSFilename, "wt")) != NULL )
         {
-            VSIFCloseL( l_fp );
-            poReader->SaveClasses( osGFSFilename );
+            VSIFCloseL(l_fp);
+            poReader->SaveClasses(osGFSFilename);
         }
         else
         {
             CPLDebug("GML",
                      "Not saving %s files already exists or can't be created.",
-                     osGFSFilename.c_str() );
+                     osGFSFilename.c_str());
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Translate the GMLFeatureClasses into layers.                    */
-/* -------------------------------------------------------------------- */
-    papoLayers = (OGRGMLLayer **)
-        CPLCalloc( sizeof(OGRGMLLayer *), poReader->GetClassCount());
+    // Translate the GMLFeatureClasses into layers.
+    papoLayers = static_cast<OGRGMLLayer **>(
+        CPLCalloc(sizeof(OGRGMLLayer *), poReader->GetClassCount()));
     nLayers = 0;
 
     if (poReader->GetClassCount() == 1 && nNumberOfFeatures != 0)
@@ -1188,7 +1275,9 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         }
         else if (nFeatureCount != nNumberOfFeatures)
         {
-            CPLDebug("GML", "Feature count in header, and actual feature count don't match");
+            CPLDebug("GML",
+                     "Feature count in header, "
+                     "and actual feature count don't match");
         }
     }
 
@@ -1201,8 +1290,6 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
         nLayers++;
     }
 
-
-
     return true;
 }
 
@@ -1213,36 +1300,37 @@ bool OGRGMLDataSource::Open( GDALOpenInfo* poOpenInfo )
 void OGRGMLDataSource::BuildJointClassFromXSD()
 {
     CPLString osJointClassName = "join";
-    for(int i=0;i<poReader->GetClassCount();i++)
+    for(int i = 0; i < poReader->GetClassCount(); i++)
     {
         osJointClassName += "_";
         osJointClassName += poReader->GetClass(i)->GetName();
     }
-    GMLFeatureClass* poJointClass = new GMLFeatureClass(osJointClassName);
+    GMLFeatureClass *poJointClass = new GMLFeatureClass(osJointClassName);
     poJointClass->SetElementName("Tuple");
-    for(int i=0;i<poReader->GetClassCount();i++)
+    for(int i = 0; i < poReader->GetClassCount(); i++)
     {
-        GMLFeatureClass* poClass = poReader->GetClass(i);
+        GMLFeatureClass *poClass = poReader->GetClass(i);
 
         {
-        CPLString osPropertyName;
-        osPropertyName.Printf("%s.%s", poClass->GetName(), "gml_id");
-        GMLPropertyDefn* poNewProperty = new GMLPropertyDefn( osPropertyName );
-        CPLString osSrcElement;
-            osSrcElement.Printf("member|%s at id",
-                                poClass->GetName());
-        poNewProperty->SetSrcElement(osSrcElement);
-        poNewProperty->SetType(GMLPT_String);
-        poJointClass->AddProperty(poNewProperty);
+            CPLString osPropertyName;
+            osPropertyName.Printf("%s.%s", poClass->GetName(), "gml_id");
+            GMLPropertyDefn *poNewProperty =
+                new GMLPropertyDefn(osPropertyName);
+            CPLString osSrcElement;
+            osSrcElement.Printf("member|%s at id", poClass->GetName());
+            poNewProperty->SetSrcElement(osSrcElement);
+            poNewProperty->SetType(GMLPT_String);
+            poJointClass->AddProperty(poNewProperty);
         }
 
-        int iField;
-        for( iField = 0; iField < poClass->GetPropertyCount(); iField++ )
+        for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ )
         {
-            GMLPropertyDefn *poProperty = poClass->GetProperty( iField );
+            GMLPropertyDefn *poProperty = poClass->GetProperty(iField);
             CPLString osPropertyName;
-            osPropertyName.Printf("%s.%s", poClass->GetName(), poProperty->GetName());
-            GMLPropertyDefn* poNewProperty = new GMLPropertyDefn( osPropertyName );
+            osPropertyName.Printf("%s.%s", poClass->GetName(),
+                                  poProperty->GetName());
+            GMLPropertyDefn *poNewProperty =
+                new GMLPropertyDefn(osPropertyName);
 
             poNewProperty->SetType(poProperty->GetType());
             CPLString osSrcElement;
@@ -1256,25 +1344,29 @@ void OGRGMLDataSource::BuildJointClassFromXSD()
 
             poJointClass->AddProperty(poNewProperty);
         }
-        for( iField = 0; iField < poClass->GetGeometryPropertyCount(); iField++ )
+        for( int iField = 0;
+             iField < poClass->GetGeometryPropertyCount();
+             iField++ )
         {
-            GMLGeometryPropertyDefn *poProperty = poClass->GetGeometryProperty( iField );
+            GMLGeometryPropertyDefn *poProperty =
+                poClass->GetGeometryProperty(iField);
             CPLString osPropertyName;
-            osPropertyName.Printf("%s.%s", poClass->GetName(), poProperty->GetName());
+            osPropertyName.Printf("%s.%s", poClass->GetName(),
+                                  poProperty->GetName());
             CPLString osSrcElement;
-            osSrcElement.Printf("member|%s|%s",
-                                poClass->GetName(),
+            osSrcElement.Printf("member|%s|%s", poClass->GetName(),
                                 poProperty->GetSrcElement());
-            GMLGeometryPropertyDefn* poNewProperty =
-                new GMLGeometryPropertyDefn( osPropertyName, osSrcElement,
-                        poProperty->GetType(), -1, poProperty->IsNullable() );
+            GMLGeometryPropertyDefn *poNewProperty =
+                new GMLGeometryPropertyDefn(osPropertyName, osSrcElement,
+                                            poProperty->GetType(), -1,
+                                            poProperty->IsNullable());
             poJointClass->AddGeometryProperty(poNewProperty);
         }
     }
     poJointClass->SetSchemaLocked(true);
 
     poReader->ClearClasses();
-    poReader->AddClass( poJointClass );
+    poReader->AddClass(poJointClass);
 }
 
 /************************************************************************/
@@ -1283,21 +1375,21 @@ void OGRGMLDataSource::BuildJointClassFromXSD()
 
 void OGRGMLDataSource::BuildJointClassFromScannedSchema()
 {
-    /* Make sure that all properties of a same base feature type are */
-    /* consecutive. If not, reorder */
-    std::vector< std::vector<GMLPropertyDefn*> > aapoProps;
+    // Make sure that all properties of a same base feature type are
+    // consecutive. If not, reorder.
+    std::vector<std::vector<GMLPropertyDefn*> > aapoProps;
     GMLFeatureClass *poClass = poReader->GetClass(0);
     CPLString osJointClassName = "join";
 
-    for( int iField = 0; iField < poClass->GetPropertyCount(); iField ++ )
+    for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ )
     {
-        GMLPropertyDefn* poProp = poClass->GetProperty(iField);
+        GMLPropertyDefn *poProp = poClass->GetProperty(iField);
         CPLString osPrefix(poProp->GetName());
         size_t iPos = osPrefix.find('.');
         if( iPos != std::string::npos )
             osPrefix.resize(iPos);
-        int iSubClass;
-        for( iSubClass = 0; iSubClass < (int)aapoProps.size(); iSubClass ++ )
+        int iSubClass = 0;  // Used after for.
+        for( ; iSubClass < static_cast<int>(aapoProps.size()); iSubClass++ )
         {
             CPLString osPrefixClass(aapoProps[iSubClass][0]->GetName());
             iPos = osPrefixClass.find('.');
@@ -1306,11 +1398,11 @@ void OGRGMLDataSource::BuildJointClassFromScannedSchema()
             if( osPrefix == osPrefixClass )
                 break;
         }
-        if( iSubClass == (int)aapoProps.size() )
+        if( iSubClass == static_cast<int>(aapoProps.size()) )
         {
             osJointClassName += "_";
             osJointClassName += osPrefix;
-            aapoProps.push_back( std::vector<GMLPropertyDefn*>() );
+            aapoProps.push_back(std::vector<GMLPropertyDefn*>());
         }
         aapoProps[iSubClass].push_back(poProp);
     }
@@ -1318,16 +1410,21 @@ void OGRGMLDataSource::BuildJointClassFromScannedSchema()
     poClass->SetName(osJointClassName);
 
     poClass->StealProperties();
-    std::vector< std::pair< CPLString, std::vector<GMLGeometryPropertyDefn*> > > aapoGeomProps;
-    for( int iSubClass = 0; iSubClass < (int)aapoProps.size(); iSubClass ++ )
+    std::vector< std::pair< CPLString, std::vector<GMLGeometryPropertyDefn*> > >
+        aapoGeomProps;
+    for( int iSubClass = 0; iSubClass < static_cast<int>(aapoProps.size());
+         iSubClass++ )
     {
         CPLString osPrefixClass(aapoProps[iSubClass][0]->GetName());
         size_t iPos = osPrefixClass.find('.');
         if( iPos != std::string::npos )
             osPrefixClass.resize(iPos);
-        aapoGeomProps.push_back( std::pair< CPLString, std::vector<GMLGeometryPropertyDefn*> >
-                (osPrefixClass, std::vector<GMLGeometryPropertyDefn*>()) );
-        for( int iField = 0; iField < (int)aapoProps[iSubClass].size(); iField ++ )
+        // Need to leave a space between > > for -Werror=c++0x-compat.
+        aapoGeomProps.push_back(std::pair<CPLString, std::vector<GMLGeometryPropertyDefn *> >
+                (osPrefixClass, std::vector<GMLGeometryPropertyDefn*>()));
+        for( int iField = 0;
+             iField < static_cast<int>(aapoProps[iSubClass].size());
+             iField++ )
         {
             poClass->AddProperty(aapoProps[iSubClass][iField]);
         }
@@ -1335,28 +1432,34 @@ void OGRGMLDataSource::BuildJointClassFromScannedSchema()
     aapoProps.resize(0);
 
     // Reorder geometry fields too
-    for( int iField = 0; iField < poClass->GetGeometryPropertyCount(); iField ++ )
+    for( int iField = 0;
+         iField < poClass->GetGeometryPropertyCount();
+         iField++ )
     {
-        GMLGeometryPropertyDefn* poProp = poClass->GetGeometryProperty(iField);
+        GMLGeometryPropertyDefn *poProp = poClass->GetGeometryProperty(iField);
         CPLString osPrefix(poProp->GetName());
         size_t iPos = osPrefix.find('.');
         if( iPos != std::string::npos )
             osPrefix.resize(iPos);
-        int iSubClass;
-        for( iSubClass = 0; iSubClass < (int)aapoGeomProps.size(); iSubClass ++ )
+        int iSubClass = 0;  // Used after for.
+        for( ; iSubClass < static_cast<int>(aapoGeomProps.size()); iSubClass++ )
         {
             if( osPrefix == aapoGeomProps[iSubClass].first )
                 break;
         }
-        if( iSubClass == (int)aapoGeomProps.size() )
-            aapoGeomProps.push_back( std::pair< CPLString, std::vector<GMLGeometryPropertyDefn*> >
-                    (osPrefix, std::vector<GMLGeometryPropertyDefn*>()) );
+        if( iSubClass == static_cast<int>(aapoGeomProps.size()) )
+            aapoGeomProps.push_back(
+                std::pair<CPLString, std::vector<GMLGeometryPropertyDefn*> >(
+                    osPrefix, std::vector<GMLGeometryPropertyDefn *>()));
         aapoGeomProps[iSubClass].second.push_back(poProp);
     }
     poClass->StealGeometryProperties();
-    for( int iSubClass = 0; iSubClass < (int)aapoGeomProps.size(); iSubClass ++ )
+    for( int iSubClass = 0; iSubClass < static_cast<int>(aapoGeomProps.size());
+         iSubClass++ )
     {
-        for( int iField = 0; iField < (int)aapoGeomProps[iSubClass].second.size(); iField ++ )
+        for( int iField = 0;
+             iField < static_cast<int>(aapoGeomProps[iSubClass].second.size());
+             iField++ )
         {
             poClass->AddGeometryProperty(aapoGeomProps[iSubClass].second[iField]);
         }
@@ -1370,14 +1473,9 @@ void OGRGMLDataSource::BuildJointClassFromScannedSchema()
 OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
 
 {
-    OGRGMLLayer *poLayer;
-
-/* -------------------------------------------------------------------- */
-/*      Create an empty layer.                                          */
-/* -------------------------------------------------------------------- */
-
-    const char* pszSRSName = poClass->GetSRSName();
-    OGRSpatialReference* poSRS = NULL;
+    // Create an empty layer.
+    const char *pszSRSName = poClass->GetSRSName();
+    OGRSpatialReference *poSRS = NULL;
     if (pszSRSName)
     {
         poSRS = new OGRSpatialReference();
@@ -1402,45 +1500,39 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
             if (poSRS != NULL && m_bInvertAxisOrderIfLatLong &&
                 GML_IsSRSLatLongOrder(pszSRSName))
             {
-                OGR_SRSNode *poGEOGCS = poSRS->GetAttrNode( "GEOGCS" );
+                OGR_SRSNode *poGEOGCS = poSRS->GetAttrNode("GEOGCS");
                 if( poGEOGCS != NULL )
-                    poGEOGCS->StripNodes( "AXIS" );
+                    poGEOGCS->StripNodes("AXIS");
 
-                OGR_SRSNode *poPROJCS = poSRS->GetAttrNode( "PROJCS" );
+                OGR_SRSNode *poPROJCS = poSRS->GetAttrNode("PROJCS");
                 if (poPROJCS != NULL && poSRS->EPSGTreatsAsNorthingEasting())
-                    poPROJCS->StripNodes( "AXIS" );
+                    poPROJCS->StripNodes("AXIS");
 
-                if (!poClass->HasExtents() &&
-                    sBoundingRect.IsInit())
+                if (!poClass->HasExtents() && sBoundingRect.IsInit())
                 {
-                    poClass->SetExtents(sBoundingRect.MinY,
-                                        sBoundingRect.MaxY,
-                                        sBoundingRect.MinX,
-                                        sBoundingRect.MaxX);
+                    poClass->SetExtents(sBoundingRect.MinY, sBoundingRect.MaxY,
+                                        sBoundingRect.MinX, sBoundingRect.MaxX);
                 }
             }
         }
 
-        if (!poClass->HasExtents() &&
-            sBoundingRect.IsInit())
+        if (!poClass->HasExtents() && sBoundingRect.IsInit())
         {
-            poClass->SetExtents(sBoundingRect.MinX,
-                                sBoundingRect.MaxX,
-                                sBoundingRect.MinY,
-                                sBoundingRect.MaxY);
+            poClass->SetExtents(sBoundingRect.MinX, sBoundingRect.MaxX,
+                                sBoundingRect.MinY, sBoundingRect.MaxY);
         }
     }
 
-    /* Report a COMPD_CS only if GML_REPORT_COMPD_CS is explicitly set to TRUE */
+    // Report a COMPD_CS only if GML_REPORT_COMPD_CS is explicitly set to TRUE.
     if( poSRS != NULL &&
         !CPLTestBool(CPLGetConfigOption("GML_REPORT_COMPD_CS", "FALSE")) )
     {
-        OGR_SRSNode *poCOMPD_CS = poSRS->GetAttrNode( "COMPD_CS" );
+        OGR_SRSNode *poCOMPD_CS = poSRS->GetAttrNode("COMPD_CS");
         if( poCOMPD_CS != NULL )
         {
-            OGR_SRSNode* poCandidateRoot = poCOMPD_CS->GetNode( "PROJCS" );
+            OGR_SRSNode *poCandidateRoot = poCOMPD_CS->GetNode("PROJCS");
             if( poCandidateRoot == NULL )
-                poCandidateRoot = poCOMPD_CS->GetNode( "GEOGCS" );
+                poCandidateRoot = poCOMPD_CS->GetNode("GEOGCS");
             if( poCandidateRoot != NULL )
             {
                 poSRS->SetRoot(poCandidateRoot->Clone());
@@ -1448,42 +1540,43 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
         }
     }
 
+    OGRGMLLayer *poLayer = new OGRGMLLayer(poClass->GetName(), false, this);
 
-    poLayer = new OGRGMLLayer( poClass->GetName(), false, this );
-
-/* -------------------------------------------------------------------- */
-/*      Added attributes (properties).                                  */
-/* -------------------------------------------------------------------- */
+    // Added attributes (properties).
     if (bExposeGMLId)
     {
-        OGRFieldDefn oField( "gml_id", OFTString );
+        OGRFieldDefn oField("gml_id", OFTString);
         oField.SetNullable(FALSE);
-        poLayer->GetLayerDefn()->AddFieldDefn( &oField );
+        poLayer->GetLayerDefn()->AddFieldDefn(&oField);
     }
     else if (bExposeFid)
     {
-        OGRFieldDefn oField( "fid", OFTString );
+        OGRFieldDefn oField("fid", OFTString);
         oField.SetNullable(FALSE);
-        poLayer->GetLayerDefn()->AddFieldDefn( &oField );
+        poLayer->GetLayerDefn()->AddFieldDefn(&oField);
     }
 
-    int iField;
-    for( iField = 0; iField < poClass->GetGeometryPropertyCount(); iField++ )
+    for( int iField = 0;
+         iField < poClass->GetGeometryPropertyCount();
+         iField++ )
     {
-        GMLGeometryPropertyDefn *poProperty = poClass->GetGeometryProperty( iField );
-        OGRGeomFieldDefn oField( poProperty->GetName(), (OGRwkbGeometryType)poProperty->GetType() );
-        if( poClass->GetGeometryPropertyCount() == 1 && poClass->GetFeatureCount() == 0 )
+        GMLGeometryPropertyDefn *poProperty =
+            poClass->GetGeometryProperty(iField);
+        OGRGeomFieldDefn oField(poProperty->GetName(),
+                                (OGRwkbGeometryType)poProperty->GetType());
+        if( poClass->GetGeometryPropertyCount() == 1 &&
+            poClass->GetFeatureCount() == 0 )
         {
             oField.SetType(wkbUnknown);
         }
         oField.SetSpatialRef(poSRS);
-        oField.SetNullable(poProperty->IsNullable() );
-        poLayer->GetLayerDefn()->AddGeomFieldDefn( &oField );
+        oField.SetNullable(poProperty->IsNullable());
+        poLayer->GetLayerDefn()->AddGeomFieldDefn(&oField);
     }
 
-    for( iField = 0; iField < poClass->GetPropertyCount(); iField++ )
+    for( int iField = 0; iField < poClass->GetPropertyCount(); iField++ )
     {
-        GMLPropertyDefn *poProperty = poClass->GetProperty( iField );
+        GMLPropertyDefn *poProperty = poClass->GetProperty(iField);
         OGRFieldType eFType;
 
         if( poProperty->GetType() == GMLPT_Untyped )
@@ -1513,13 +1606,13 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
         else
             eFType = OFTString;
 
-        OGRFieldDefn oField( poProperty->GetName(), eFType );
+        OGRFieldDefn oField(poProperty->GetName(), eFType);
         if ( STARTS_WITH_CI(oField.GetNameRef(), "ogr:") )
-          oField.SetName(poProperty->GetName()+4);
+          oField.SetName(poProperty->GetName() + 4);
         if( poProperty->GetWidth() > 0 )
-            oField.SetWidth( poProperty->GetWidth() );
+            oField.SetWidth(poProperty->GetWidth());
         if( poProperty->GetPrecision() > 0 )
-            oField.SetPrecision( poProperty->GetPrecision() );
+            oField.SetPrecision(poProperty->GetPrecision());
         if( poProperty->GetType() == GMLPT_Boolean ||
             poProperty->GetType() == GMLPT_BooleanList )
             oField.SetSubType(OFSTBoolean);
@@ -1530,7 +1623,7 @@ OGRGMLLayer *OGRGMLDataSource::TranslateGMLSchema( GMLFeatureClass *poClass )
         if( !bEmptyAsNull )
             oField.SetNullable(poProperty->IsNullable() );
 
-        poLayer->GetLayerDefn()->AddFieldDefn( &oField );
+        poLayer->GetLayerDefn()->AddFieldDefn(&oField);
     }
 
     if( poSRS != NULL )
@@ -1556,22 +1649,19 @@ const char *OGRGMLDataSource::GetGlobalSRSName()
 /************************************************************************/
 
 bool OGRGMLDataSource::Create( const char *pszFilename,
-                              char **papszOptions )
+                               char **papszOptions )
 
 {
     if( fpOutput != NULL || poReader != NULL )
     {
-        CPLAssert( false );
+        CPLAssert(false);
         return false;
     }
 
-    if( strcmp(pszFilename,"/dev/stdout") == 0 )
+    if( strcmp(pszFilename, "/dev/stdout") == 0 )
         pszFilename = "/vsistdout/";
 
-/* -------------------------------------------------------------------- */
-/*      Read options                                                    */
-/* -------------------------------------------------------------------- */
-
+    // Read options.
     CSLDestroy(papszCreateOptions);
     papszCreateOptions = CSLDuplicate(papszOptions);
 
@@ -1582,22 +1672,49 @@ bool OGRGMLDataSource::Create( const char *pszFilename,
     if (bIsOutputGML3Deegree || bIsOutputGML32)
         bIsOutputGML3 = true;
 
-    bIsLongSRSRequired =
-        CPLTestBool(CSLFetchNameValueDef(papszCreateOptions, "GML3_LONGSRS", "YES"));
+    eSRSNameFormat = (bIsOutputGML3) ? SRSNAME_OGC_URN : SRSNAME_SHORT;
+    if( bIsOutputGML3 )
+    {
+        const char *pszLongSRS =
+            CSLFetchNameValue(papszCreateOptions, "GML3_LONGSRS");
+        const char *pszSRSNameFormat =
+            CSLFetchNameValue(papszCreateOptions, "SRSNAME_FORMAT");
+        if( pszSRSNameFormat )
+        {
+            if( pszLongSRS )
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "Both GML3_LONGSRS and SRSNAME_FORMAT specified. "
+                         "Ignoring GML3_LONGSRS");
+            }
+            if( EQUAL(pszSRSNameFormat, "SHORT") )
+                eSRSNameFormat = SRSNAME_SHORT;
+            else if( EQUAL(pszSRSNameFormat, "OGC_URN") )
+                eSRSNameFormat = SRSNAME_OGC_URN;
+            else if( EQUAL(pszSRSNameFormat, "OGC_URL") )
+                eSRSNameFormat = SRSNAME_OGC_URL;
+            else
+            {
+                CPLError(CE_Warning, CPLE_NotSupported,
+                         "Invalid value for SRSNAME_FORMAT. "
+                         "Using SRSNAME_OGC_URN");
+            }
+        }
+        else if( pszLongSRS && !CPLTestBool(pszLongSRS) )
+            eSRSNameFormat = SRSNAME_SHORT;
+    }
 
-    bWriteSpaceIndentation =
-        CPLTestBool(CSLFetchNameValueDef(papszCreateOptions, "SPACE_INDENTATION", "YES"));
+    bWriteSpaceIndentation = CPLTestBool(
+        CSLFetchNameValueDef(papszCreateOptions, "SPACE_INDENTATION", "YES"));
 
-/* -------------------------------------------------------------------- */
-/*      Create the output file.                                         */
-/* -------------------------------------------------------------------- */
-    pszName = CPLStrdup( pszFilename );
+    // Create the output file.
+    pszName = CPLStrdup(pszFilename);
     osFilename = pszName;
 
-    if( strcmp(pszFilename,"/vsistdout/") == 0 ||
+    if( strcmp(pszFilename, "/vsistdout/") == 0 ||
         STARTS_WITH(pszFilename, "/vsigzip/") )
     {
-        fpOutput = VSIFOpenL(pszFilename, "wb");
+        fpOutput = VSIFOpenExL(pszFilename, "wb", true);
         bFpOutputIsNonSeekable = true;
         bFpOutputSingleFile = true;
     }
@@ -1609,139 +1726,134 @@ bool OGRGMLDataSource::Create( const char *pszFilename,
             pszName = CPLStrdup(CPLFormFilename(pszFilename, "out.gml", NULL));
         }
 
-        fpOutput = VSIFOpenL(pszName, "wb");
+        fpOutput = VSIFOpenExL(pszName, "wb", true);
         bFpOutputIsNonSeekable = true;
     }
     else
-        fpOutput = VSIFOpenL( pszFilename, "wb+" );
+        fpOutput = VSIFOpenExL(pszFilename, "wb+", true);
     if( fpOutput == NULL )
     {
-        CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to create GML file %s.",
-                  pszFilename );
+        CPLError(CE_Failure, CPLE_OpenFailed,
+                 "Failed to create GML file %s: %s",
+                 pszFilename, VSIGetLastErrorMsg());
         return false;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write out "standard" header.                                    */
-/* -------------------------------------------------------------------- */
-    PrintLine( fpOutput, "%s",
-                "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" );
+    // Write out "standard" header.
+    PrintLine(fpOutput, "%s",
+              "<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
 
     if (!bFpOutputIsNonSeekable)
-        nSchemaInsertLocation = (int) VSIFTellL( fpOutput );
+        nSchemaInsertLocation = static_cast<int>(VSIFTellL(fpOutput));
 
-    const char* pszPrefix = GetAppPrefix();
-    const char* pszTargetNameSpace = CSLFetchNameValueDef(papszOptions,"TARGET_NAMESPACE", "http://ogr.maptools.org/");
+    const char *pszPrefix = GetAppPrefix();
+    const char *pszTargetNameSpace = CSLFetchNameValueDef(
+        papszOptions, "TARGET_NAMESPACE", "http://ogr.maptools.org/");
 
     if( RemoveAppPrefix() )
-        PrintLine( fpOutput, "<FeatureCollection" );
+        PrintLine(fpOutput, "<FeatureCollection");
     else
-        PrintLine( fpOutput, "<%s:FeatureCollection", pszPrefix );
+        PrintLine(fpOutput, "<%s:FeatureCollection", pszPrefix);
 
     if (IsGML32Output())
     {
-        char* pszGMLId = CPLEscapeString(
-            CSLFetchNameValueDef(papszOptions, "GML_ID", "aFeatureCollection"), -1, CPLES_XML);
-        PrintLine( fpOutput, "     gml:id=\"%s\"", pszGMLId );
+        char *pszGMLId = CPLEscapeString(
+            CSLFetchNameValueDef(papszOptions, "GML_ID", "aFeatureCollection"),
+            -1, CPLES_XML);
+        PrintLine(fpOutput, "     gml:id=\"%s\"", pszGMLId);
         CPLFree(pszGMLId);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Write out schema info if provided in creation options.          */
-/* -------------------------------------------------------------------- */
-    const char *pszSchemaURI = CSLFetchNameValue(papszOptions,"XSISCHEMAURI");
-    const char *pszSchemaOpt = CSLFetchNameValue( papszOptions, "XSISCHEMA" );
+    // Write out schema info if provided in creation options.
+    const char *pszSchemaURI = CSLFetchNameValue(papszOptions, "XSISCHEMAURI");
+    const char *pszSchemaOpt = CSLFetchNameValue(papszOptions, "XSISCHEMA");
 
     if( pszSchemaURI != NULL )
     {
-        PrintLine( fpOutput,
-              "     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
-        PrintLine( fpOutput,
-              "     xsi:schemaLocation=\"%s\"",
-                    pszSchemaURI );
+        PrintLine(
+            fpOutput,
+            "     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
+        PrintLine(fpOutput, "     xsi:schemaLocation=\"%s\"", pszSchemaURI);
     }
-    else if( pszSchemaOpt == NULL || EQUAL(pszSchemaOpt,"EXTERNAL") )
+    else if( pszSchemaOpt == NULL || EQUAL(pszSchemaOpt, "EXTERNAL") )
     {
-        char *pszBasename = CPLStrdup(CPLGetBasename( pszName ));
+        char *pszBasename = CPLStrdup(CPLGetBasename(pszName));
 
-        PrintLine( fpOutput,
-              "     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
-        PrintLine( fpOutput,
-              "     xsi:schemaLocation=\"%s %s\"",
-                    pszTargetNameSpace,
-                    CPLResetExtension( pszBasename, "xsd" ) );
-        CPLFree( pszBasename );
+        PrintLine(
+            fpOutput,
+            "     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
+        PrintLine(fpOutput, "     xsi:schemaLocation=\"%s %s\"",
+                  pszTargetNameSpace, CPLResetExtension(pszBasename, "xsd"));
+        CPLFree(pszBasename);
     }
 
     if( RemoveAppPrefix() )
-        PrintLine( fpOutput,
-                "     xmlns=\"%s\"", pszTargetNameSpace );
+        PrintLine(fpOutput, "     xmlns=\"%s\"", pszTargetNameSpace);
     else
-        PrintLine( fpOutput,
-                "     xmlns:%s=\"%s\"", pszPrefix, pszTargetNameSpace );
+        PrintLine(fpOutput,
+                  "     xmlns:%s=\"%s\"", pszPrefix, pszTargetNameSpace);
 
     if (IsGML32Output())
-        PrintLine( fpOutput, "%s",
-                "     xmlns:gml=\"http://www.opengis.net/gml/3.2\">" );
+        PrintLine(fpOutput, "%s",
+                  "     xmlns:gml=\"http://www.opengis.net/gml/3.2\">");
     else
-        PrintLine( fpOutput, "%s",
-                    "     xmlns:gml=\"http://www.opengis.net/gml\">" );
+        PrintLine(fpOutput, "%s",
+                  "     xmlns:gml=\"http://www.opengis.net/gml\">");
 
     return true;
 }
 
-
 /************************************************************************/
 /*                         WriteTopElements()                           */
 /************************************************************************/
 
 void OGRGMLDataSource::WriteTopElements()
 {
-    const char* pszDescription = CSLFetchNameValueDef(papszCreateOptions,
-        "DESCRIPTION", GetMetadataItem("DESCRIPTION"));
+    const char *pszDescription = CSLFetchNameValueDef(
+        papszCreateOptions, "DESCRIPTION", GetMetadataItem("DESCRIPTION"));
     if( pszDescription != NULL )
     {
         if (bWriteSpaceIndentation)
-            VSIFPrintfL( fpOutput, "  ");
-        char* pszTmp = CPLEscapeString(pszDescription, -1, CPLES_XML);
-        PrintLine( fpOutput, "<gml:description>%s</gml:description>", pszTmp );
+            VSIFPrintfL(fpOutput, "  ");
+        char *pszTmp = CPLEscapeString(pszDescription, -1, CPLES_XML);
+        PrintLine(fpOutput, "<gml:description>%s</gml:description>", pszTmp);
         CPLFree(pszTmp);
     }
 
-    const char* l_pszName = CSLFetchNameValueDef(papszCreateOptions,
-        "NAME", GetMetadataItem("NAME"));
+    const char *l_pszName = CSLFetchNameValueDef(papszCreateOptions, "NAME",
+                                                 GetMetadataItem("NAME"));
     if( l_pszName != NULL )
     {
         if (bWriteSpaceIndentation)
-            VSIFPrintfL( fpOutput, "  ");
-        char* pszTmp = CPLEscapeString(l_pszName, -1, CPLES_XML);
-        PrintLine( fpOutput, "<gml:name>%s</gml:name>", pszTmp );
+            VSIFPrintfL(fpOutput, "  ");
+        char *pszTmp = CPLEscapeString(l_pszName, -1, CPLES_XML);
+        PrintLine(fpOutput, "<gml:name>%s</gml:name>", pszTmp);
         CPLFree(pszTmp);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Should we initialize an area to place the boundedBy element?    */
-/*      We will need to seek back to fill it in.                        */
-/* -------------------------------------------------------------------- */
+    // Should we initialize an area to place the boundedBy element?
+    // We will need to seek back to fill it in.
     nBoundedByLocation = -1;
-    if( CSLFetchBoolean( papszCreateOptions , "BOUNDEDBY", TRUE ))
+    if( CPLFetchBool(papszCreateOptions, "BOUNDEDBY", true))
     {
         if (!bFpOutputIsNonSeekable )
         {
-            nBoundedByLocation = (int) VSIFTellL( fpOutput );
+            nBoundedByLocation = static_cast<int>(VSIFTellL(fpOutput));
 
             if( nBoundedByLocation != -1 )
-                PrintLine( fpOutput, "%350s", "" );
+                PrintLine(fpOutput, "%350s", "");
         }
         else
         {
             if (bWriteSpaceIndentation)
-                VSIFPrintfL( fpOutput, "  ");
+                VSIFPrintfL(fpOutput, "  ");
             if (IsGML3Output())
-                PrintLine( fpOutput, "<gml:boundedBy><gml:Null /></gml:boundedBy>" );
+                PrintLine(fpOutput,
+                          "<gml:boundedBy><gml:Null /></gml:boundedBy>");
             else
-                PrintLine( fpOutput, "<gml:boundedBy><gml:null>missing</gml:null></gml:boundedBy>" );
+                PrintLine(
+                    fpOutput,
+                    "<gml:boundedBy><gml:null>missing</gml:null></gml:boundedBy>");
         }
     }
 }
@@ -1751,40 +1863,34 @@ void OGRGMLDataSource::WriteTopElements()
 /************************************************************************/
 
 OGRLayer *
-OGRGMLDataSource::ICreateLayer( const char * pszLayerName,
-                                OGRSpatialReference *poSRS,
-                                OGRwkbGeometryType eType,
-                                CPL_UNUSED char ** papszOptions )
+OGRGMLDataSource::ICreateLayer(const char *pszLayerName,
+                               OGRSpatialReference *poSRS,
+                               OGRwkbGeometryType eType,
+                               CPL_UNUSED char **papszOptions)
 {
-/* -------------------------------------------------------------------- */
-/*      Verify we are in update mode.                                   */
-/* -------------------------------------------------------------------- */
+    // Verify we are in update mode.
     if( fpOutput == NULL )
     {
-        CPLError( CE_Failure, CPLE_NoWriteAccess,
-                  "Data source %s opened for read access.\n"
-                  "New layer %s cannot be created.\n",
-                  pszName, pszLayerName );
+        CPLError(CE_Failure, CPLE_NoWriteAccess,
+                 "Data source %s opened for read access.\n"
+                 "New layer %s cannot be created.\n",
+                 pszName, pszLayerName);
 
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Ensure name is safe as an element name.                         */
-/* -------------------------------------------------------------------- */
-    char *pszCleanLayerName = CPLStrdup( pszLayerName );
+    // Ensure name is safe as an element name.
+    char *pszCleanLayerName = CPLStrdup(pszLayerName);
 
-    CPLCleanXMLElementName( pszCleanLayerName );
-    if( strcmp(pszCleanLayerName,pszLayerName) != 0 )
+    CPLCleanXMLElementName(pszCleanLayerName);
+    if( strcmp(pszCleanLayerName, pszLayerName) != 0 )
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Layer name '%s' adjusted to '%s' for XML validity.",
-                  pszLayerName, pszCleanLayerName );
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Layer name '%s' adjusted to '%s' for XML validity.",
+                 pszLayerName, pszCleanLayerName);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Set or check validity of global SRS.                            */
-/* -------------------------------------------------------------------- */
+    // Set or check validity of global SRS.
     if (nLayers == 0)
     {
         WriteTopElements();
@@ -1810,33 +1916,28 @@ OGRGMLDataSource::ICreateLayer( const char * pszLayerName,
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create the layer object.                                        */
-/* -------------------------------------------------------------------- */
-    OGRGMLLayer *poLayer;
-
-    poLayer = new OGRGMLLayer( pszCleanLayerName, true, this );
+    // Create the layer object.
+    OGRGMLLayer *poLayer = new OGRGMLLayer(pszCleanLayerName, true, this);
     poLayer->GetLayerDefn()->SetGeomType(eType);
     if( eType != wkbNone )
     {
-        poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->SetName("geometryProperty");
+        poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->SetName(
+            "geometryProperty");
         if( poSRS != NULL )
         {
-            /* Clone it since mapogroutput assumes that it can destroys */
-            /* the SRS it has passed to use, instead of dereferencing it. */
+            // Clone it since mapogroutput assumes that it can destroys
+            // the SRS it has passed to use, instead of dereferencing it.
             poSRS = poSRS->Clone();
             poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
             poSRS->Dereference();
         }
     }
 
-    CPLFree( pszCleanLayerName );
+    CPLFree(pszCleanLayerName);
 
-/* -------------------------------------------------------------------- */
-/*      Add layer to data source layer list.                            */
-/* -------------------------------------------------------------------- */
-    papoLayers = (OGRGMLLayer **)
-        CPLRealloc( papoLayers,  sizeof(OGRGMLLayer *) * (nLayers+1) );
+    // Add layer to data source layer list.
+    papoLayers = static_cast<OGRGMLLayer **>(
+        CPLRealloc(papoLayers, sizeof(OGRGMLLayer *) * (nLayers + 1)));
 
     papoLayers[nLayers++] = poLayer;
 
@@ -1850,12 +1951,14 @@ OGRGMLDataSource::ICreateLayer( const char * pszLayerName,
 int OGRGMLDataSource::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,ODsCCreateLayer) )
+    if( EQUAL(pszCap, ODsCCreateLayer) )
         return TRUE;
-    else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
+    else if( EQUAL(pszCap, ODsCCreateGeomFieldAfterCreateLayer) )
         return TRUE;
-    else if( EQUAL(pszCap,ODsCCurveGeometries) )
+    else if( EQUAL(pszCap, ODsCCurveGeometries) )
         return bIsOutputGML3;
+    else if( EQUAL(pszCap, ODsCRandomLayerWrite) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -1877,10 +1980,11 @@ OGRLayer *OGRGMLDataSource::GetLayer( int iLayer )
 /*                            GrowExtents()                             */
 /************************************************************************/
 
-void OGRGMLDataSource::GrowExtents( OGREnvelope3D *psGeomBounds, int nCoordDimension )
+void OGRGMLDataSource::GrowExtents( OGREnvelope3D *psGeomBounds,
+                                    int nCoordDimension )
 
 {
-    sBoundingRect.Merge( *psGeomBounds );
+    sBoundingRect.Merge(*psGeomBounds);
     if (nCoordDimension == 3)
         bBBOX3D = true;
 }
@@ -1896,64 +2000,60 @@ void OGRGMLDataSource::GrowExtents( OGREnvelope3D *psGeomBounds, int nCoordDimen
 void OGRGMLDataSource::InsertHeader()
 
 {
-    VSILFILE        *fpSchema;
-    int         nSchemaStart = 0;
+    int nSchemaStart = 0;
 
     if( bFpOutputSingleFile )
         return;
 
-/* -------------------------------------------------------------------- */
-/*      Do we want to write the schema within the GML instance doc      */
-/*      or to a separate file?  For now we only support external.       */
-/* -------------------------------------------------------------------- */
-    const char *pszSchemaURI = CSLFetchNameValue(papszCreateOptions,
-                                                 "XSISCHEMAURI");
-    const char *pszSchemaOpt = CSLFetchNameValue( papszCreateOptions,
-                                                  "XSISCHEMA" );
+    // Do we want to write the schema within the GML instance doc
+    // or to a separate file?  For now we only support external.
+    const char *pszSchemaURI =
+        CSLFetchNameValue(papszCreateOptions, "XSISCHEMAURI");
+    const char *pszSchemaOpt =
+        CSLFetchNameValue(papszCreateOptions, "XSISCHEMA");
 
     if( pszSchemaURI != NULL )
         return;
 
-    if( pszSchemaOpt == NULL || EQUAL(pszSchemaOpt,"EXTERNAL") )
+    VSILFILE *fpSchema = NULL;
+    if( pszSchemaOpt == NULL || EQUAL(pszSchemaOpt, "EXTERNAL") )
     {
-        const char *pszXSDFilename = CPLResetExtension( pszName, "xsd" );
+        const char *pszXSDFilename = CPLResetExtension(pszName, "xsd");
 
-        fpSchema = VSIFOpenL( pszXSDFilename, "wt" );
+        fpSchema = VSIFOpenL(pszXSDFilename, "wt");
         if( fpSchema == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Failed to open file %.500s for schema output.",
-                      pszXSDFilename );
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Failed to open file %.500s for schema output.",
+                     pszXSDFilename);
             return;
         }
-        PrintLine( fpSchema, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" );
+        PrintLine(fpSchema, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
     }
-    else if( EQUAL(pszSchemaOpt,"INTERNAL") )
+    else if( EQUAL(pszSchemaOpt, "INTERNAL") )
     {
         if (fpOutput == NULL)
             return;
-        nSchemaStart = (int) VSIFTellL( fpOutput );
+        nSchemaStart = static_cast<int>(VSIFTellL(fpOutput));
         fpSchema = fpOutput;
     }
     else
+    {
         return;
+    }
 
-/* ==================================================================== */
-/*      Write the schema section at the end of the file.  Once          */
-/*      complete, we will read it back in, and then move the whole      */
-/*      file "down" enough to insert the schema at the beginning.       */
-/* ==================================================================== */
+    // Write the schema section at the end of the file.  Once
+    // complete, we will read it back in, and then move the whole
+    // file "down" enough to insert the schema at the beginning.
 
-/* ==================================================================== */
-/*      Detect if there are fields of List types.                       */
-/* ==================================================================== */
-    int iLayer;
+    // Detect if there are fields of List types.
     bool bHasListFields = false;
 
-    for( iLayer = 0; !bHasListFields && iLayer < GetLayerCount(); iLayer++ )
+    for( int iLayer = 0; !bHasListFields && iLayer < GetLayerCount(); iLayer++ )
     {
         OGRFeatureDefn *poFDefn = papoLayers[iLayer]->GetLayerDefn();
-        for( int iField = 0; !bHasListFields && iField < poFDefn->GetFieldCount(); iField++ )
+        for( int iField = 0;
+             !bHasListFields && iField < poFDefn->GetFieldCount(); iField++ )
         {
             OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn(iField);
 
@@ -1964,223 +2064,213 @@ void OGRGMLDataSource::InsertHeader()
             {
                 bHasListFields = true;
             }
-        } /* next field */
-    } /* next layer */
+        }
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Emit the start of the schema section.                           */
-/* -------------------------------------------------------------------- */
-    const char* pszPrefix = GetAppPrefix();
+    // Emit the start of the schema section.
+    const char *pszPrefix = GetAppPrefix();
     if( pszPrefix[0] == '\0' )
         pszPrefix = "ogr";
-    const char* pszTargetNameSpace = CSLFetchNameValueDef(papszCreateOptions,"TARGET_NAMESPACE", "http://ogr.maptools.org/");
+    const char *pszTargetNameSpace = CSLFetchNameValueDef(
+        papszCreateOptions, "TARGET_NAMESPACE", "http://ogr.maptools.org/");
 
     if (IsGML3Output())
     {
-        PrintLine( fpSchema,
-                    "<xs:schema ");
-        PrintLine( fpSchema,
-                   "    targetNamespace=\"%s\"", pszTargetNameSpace );
-        PrintLine( fpSchema,
-                   "    xmlns:%s=\"%s\"",
-                    pszPrefix, pszTargetNameSpace );
-        PrintLine( fpSchema,
-                   "    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"");
+        PrintLine(fpSchema, "<xs:schema ");
+        PrintLine(fpSchema, "    targetNamespace=\"%s\"", pszTargetNameSpace);
+        PrintLine(fpSchema, "    xmlns:%s=\"%s\"",
+                  pszPrefix, pszTargetNameSpace);
+        PrintLine(fpSchema,
+                  "    xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"");
         if (IsGML32Output())
         {
-            PrintLine( fpSchema,
-                   "    xmlns:gml=\"http://www.opengis.net/gml/3.2\"");
-            PrintLine( fpSchema,
-                    "    xmlns:gmlsf=\"http://www.opengis.net/gmlsf/2.0\"");
+            PrintLine(fpSchema,
+                      "    xmlns:gml=\"http://www.opengis.net/gml/3.2\"");
+            PrintLine(fpSchema,
+                      "    xmlns:gmlsf=\"http://www.opengis.net/gmlsf/2.0\"");
         }
         else
         {
-            PrintLine( fpSchema,
-                    "    xmlns:gml=\"http://www.opengis.net/gml\"");
+            PrintLine(fpSchema, "    xmlns:gml=\"http://www.opengis.net/gml\"");
             if (!IsGML3DeegreeOutput())
             {
-                PrintLine( fpSchema,
-                        "    xmlns:gmlsf=\"http://www.opengis.net/gmlsf\"");
+                PrintLine(fpSchema,
+                          "    xmlns:gmlsf=\"http://www.opengis.net/gmlsf\"");
             }
         }
-        PrintLine( fpSchema,
-                   "    elementFormDefault=\"qualified\"");
-        PrintLine( fpSchema,
-                   "    version=\"1.0\">");
+        PrintLine(fpSchema, "    elementFormDefault=\"qualified\"");
+        PrintLine(fpSchema, "    version=\"1.0\">");
 
         if (IsGML32Output())
         {
-            PrintLine( fpSchema,
-                    "<xs:annotation>");
-            PrintLine( fpSchema,
-                    "  <xs:appinfo source=\"http://schemas.opengis.net/gmlsfProfile/2.0/gmlsfLevels.xsd\">");
-            PrintLine( fpSchema,
-                    "    <gmlsf:ComplianceLevel>%d</gmlsf:ComplianceLevel>", (bHasListFields) ? 1 : 0);
-            PrintLine( fpSchema,
-                    "  </xs:appinfo>");
-            PrintLine( fpSchema,
-                    "</xs:annotation>");
-
-            PrintLine( fpSchema,
-                        "<xs:import namespace=\"http://www.opengis.net/gml/3.2\" schemaLocation=\"http://schemas.opengis.net/gml/3.2.1/gml.xsd\"/>" );
-            PrintLine( fpSchema,
-                        "<xs:import namespace=\"http://www.opengis.net/gmlsf/2.0\" schemaLocation=\"http://schemas.opengis.net/gmlsfProfile/2.0/gmlsfLevels.xsd\"/>" );
+            PrintLine(fpSchema, "<xs:annotation>");
+            PrintLine(fpSchema,
+                "  <xs:appinfo source=\"http://schemas.opengis.net/gmlsfProfile/2.0/gmlsfLevels.xsd\">");
+            PrintLine(fpSchema,
+                "    <gmlsf:ComplianceLevel>%d</gmlsf:ComplianceLevel>", (bHasListFields) ? 1 : 0);
+            PrintLine(fpSchema, "  </xs:appinfo>");
+            PrintLine(fpSchema, "</xs:annotation>");
+
+            PrintLine(
+                fpSchema,
+                "<xs:import namespace=\"http://www.opengis.net/gml/3.2\" schemaLocation=\"http://schemas.opengis.net/gml/3.2.1/gml.xsd\"/>");
+            PrintLine(
+                fpSchema,
+                "<xs:import namespace=\"http://www.opengis.net/gmlsf/2.0\" schemaLocation=\"http://schemas.opengis.net/gmlsfProfile/2.0/gmlsfLevels.xsd\"/>");
         }
         else
         {
             if (!IsGML3DeegreeOutput())
             {
-                PrintLine( fpSchema,
-                        "<xs:annotation>");
-                PrintLine( fpSchema,
-                        "  <xs:appinfo source=\"http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsfLevels.xsd\">");
-                PrintLine( fpSchema,
+                PrintLine(fpSchema, "<xs:annotation>");
+                PrintLine(
+                    fpSchema,
+                    "  <xs:appinfo source=\"http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsfLevels.xsd\">");
+                PrintLine(fpSchema,
                         "    <gmlsf:ComplianceLevel>%d</gmlsf:ComplianceLevel>", (bHasListFields) ? 1 : 0);
-                PrintLine( fpSchema,
+                PrintLine(fpSchema,
                         "    <gmlsf:GMLProfileSchema>http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd</gmlsf:GMLProfileSchema>");
-                PrintLine( fpSchema,
-                        "  </xs:appinfo>");
-                PrintLine( fpSchema,
-                        "</xs:annotation>");
+                PrintLine(fpSchema, "  </xs:appinfo>");
+                PrintLine(fpSchema, "</xs:annotation>");
             }
 
-            PrintLine( fpSchema,
-                        "<xs:import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/base/gml.xsd\"/>" );
+            PrintLine(fpSchema,
+                      "<xs:import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/base/gml.xsd\"/>");
             if (!IsGML3DeegreeOutput())
             {
-                PrintLine( fpSchema,
-                            "<xs:import namespace=\"http://www.opengis.net/gmlsf\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsfLevels.xsd\"/>" );
+                PrintLine(fpSchema,
+                          "<xs:import namespace=\"http://www.opengis.net/gmlsf\" schemaLocation=\"http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsfLevels.xsd\"/>");
             }
         }
     }
     else
     {
-        PrintLine( fpSchema,
-                    "<xs:schema targetNamespace=\"%s\" xmlns:%s=\"%s\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:gml=\"http://www.opengis.net/gml\" elementFormDefault=\"qualified\" version=\"1.0\">",
-                    pszTargetNameSpace, pszPrefix, pszTargetNameSpace );
+        PrintLine(fpSchema,
+                  "<xs:schema targetNamespace=\"%s\" xmlns:%s=\"%s\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:gml=\"http://www.opengis.net/gml\" elementFormDefault=\"qualified\" version=\"1.0\">",
+                  pszTargetNameSpace, pszPrefix, pszTargetNameSpace);
 
-        PrintLine( fpSchema,
-                    "<xs:import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"http://schemas.opengis.net/gml/2.1.2/feature.xsd\"/>" );
+        PrintLine(fpSchema,
+                  "<xs:import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"http://schemas.opengis.net/gml/2.1.2/feature.xsd\"/>");
     }
 
-/* -------------------------------------------------------------------- */
-/*      Define the FeatureCollection                                    */
-/* -------------------------------------------------------------------- */
+    // Define the FeatureCollection.
     if (IsGML3Output())
     {
         if (IsGML32Output())
         {
-            PrintLine( fpSchema,
-                        "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:AbstractGML\"/>",
-                        pszPrefix );
+            // GML Simple Features profile v2.0 mentions gml:AbstractGML as
+            // substitutionGroup but using gml:AbstractFeature makes it
+            // usablable by GMLJP2 v2.
+            PrintLine(fpSchema,
+                      "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:AbstractFeature\"/>",
+                      pszPrefix);
         }
         else if (IsGML3DeegreeOutput())
         {
-            PrintLine( fpSchema,
-                        "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:_FeatureCollection\"/>",
-                        pszPrefix );
+            PrintLine(fpSchema,
+                      "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:_FeatureCollection\"/>",
+                      pszPrefix);
         }
         else
         {
-            PrintLine( fpSchema,
-                        "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:_GML\"/>",
-                        pszPrefix );
+            PrintLine(fpSchema,
+                      "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:_GML\"/>",
+                      pszPrefix);
         }
 
-        PrintLine( fpSchema, "<xs:complexType name=\"FeatureCollectionType\">");
-        PrintLine( fpSchema, "  <xs:complexContent>" );
+        PrintLine(fpSchema, "<xs:complexType name=\"FeatureCollectionType\">");
+        PrintLine(fpSchema, "  <xs:complexContent>");
         if (IsGML3DeegreeOutput())
         {
-            PrintLine( fpSchema, "    <xs:extension base=\"gml:AbstractFeatureCollectionType\">" );
-            PrintLine( fpSchema, "      <xs:sequence>" );
-            PrintLine( fpSchema, "        <xs:element name=\"featureMember\" minOccurs=\"0\" maxOccurs=\"unbounded\">" );
+            PrintLine(fpSchema, "    <xs:extension base=\"gml:AbstractFeatureCollectionType\">");
+            PrintLine(fpSchema, "      <xs:sequence>");
+            PrintLine(fpSchema, "        <xs:element name=\"featureMember\" minOccurs=\"0\" maxOccurs=\"unbounded\">");
         }
         else
         {
-            PrintLine( fpSchema, "    <xs:extension base=\"gml:AbstractFeatureType\">" );
-            PrintLine( fpSchema, "      <xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">" );
-            PrintLine( fpSchema, "        <xs:element name=\"featureMember\">" );
+            PrintLine(fpSchema, "    <xs:extension base=\"gml:AbstractFeatureType\">");
+            PrintLine(fpSchema, "      <xs:sequence minOccurs=\"0\" maxOccurs=\"unbounded\">");
+            PrintLine(fpSchema, "        <xs:element name=\"featureMember\">");
         }
-        PrintLine( fpSchema, "          <xs:complexType>" );
+        PrintLine(fpSchema, "          <xs:complexType>");
         if (IsGML32Output())
         {
-            PrintLine( fpSchema, "            <xs:complexContent>" );
-            PrintLine( fpSchema, "              <xs:extension base=\"gml:AbstractFeatureMemberType\">" );
-            PrintLine( fpSchema, "                <xs:sequence>" );
-            PrintLine( fpSchema, "                  <xs:element ref=\"gml:AbstractFeature\"/>" );
-            PrintLine( fpSchema, "                </xs:sequence>" );
-            PrintLine( fpSchema, "              </xs:extension>" );
-            PrintLine( fpSchema, "            </xs:complexContent>" );
+            PrintLine(fpSchema, "            <xs:complexContent>");
+            PrintLine(fpSchema, "              <xs:extension base=\"gml:AbstractFeatureMemberType\">");
+            PrintLine(fpSchema, "                <xs:sequence>");
+            PrintLine(fpSchema, "                  <xs:element ref=\"gml:AbstractFeature\"/>");
+            PrintLine(fpSchema, "                </xs:sequence>");
+            PrintLine(fpSchema, "              </xs:extension>");
+            PrintLine(fpSchema, "            </xs:complexContent>");
         }
         else
         {
-            PrintLine( fpSchema, "            <xs:sequence>" );
-            PrintLine( fpSchema, "              <xs:element ref=\"gml:_Feature\"/>" );
-            PrintLine( fpSchema, "            </xs:sequence>" );
+            PrintLine(fpSchema, "            <xs:sequence>");
+            PrintLine(fpSchema,
+                      "              <xs:element ref=\"gml:_Feature\"/>");
+            PrintLine(fpSchema, "            </xs:sequence>");
         }
-        PrintLine( fpSchema, "          </xs:complexType>" );
-        PrintLine( fpSchema, "        </xs:element>" );
-        PrintLine( fpSchema, "      </xs:sequence>" );
-        PrintLine( fpSchema, "    </xs:extension>" );
-        PrintLine( fpSchema, "  </xs:complexContent>" );
-        PrintLine( fpSchema, "</xs:complexType>" );
+        PrintLine(fpSchema, "          </xs:complexType>");
+        PrintLine(fpSchema, "        </xs:element>");
+        PrintLine(fpSchema, "      </xs:sequence>");
+        PrintLine(fpSchema, "    </xs:extension>");
+        PrintLine(fpSchema, "  </xs:complexContent>");
+        PrintLine(fpSchema, "</xs:complexType>");
     }
     else
     {
-        PrintLine( fpSchema,
-                    "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:_FeatureCollection\"/>",
-                    pszPrefix );
+        PrintLine(fpSchema,
+                  "<xs:element name=\"FeatureCollection\" type=\"%s:FeatureCollectionType\" substitutionGroup=\"gml:_FeatureCollection\"/>",
+                  pszPrefix);
 
-        PrintLine( fpSchema, "<xs:complexType name=\"FeatureCollectionType\">");
-        PrintLine( fpSchema, "  <xs:complexContent>" );
-        PrintLine( fpSchema, "    <xs:extension base=\"gml:AbstractFeatureCollectionType\">" );
-        PrintLine( fpSchema, "      <xs:attribute name=\"lockId\" type=\"xs:string\" use=\"optional\"/>" );
-        PrintLine( fpSchema, "      <xs:attribute name=\"scope\" type=\"xs:string\" use=\"optional\"/>" );
-        PrintLine( fpSchema, "    </xs:extension>" );
-        PrintLine( fpSchema, "  </xs:complexContent>" );
-        PrintLine( fpSchema, "</xs:complexType>" );
+        PrintLine(fpSchema, "<xs:complexType name=\"FeatureCollectionType\">");
+        PrintLine(fpSchema, "  <xs:complexContent>");
+        PrintLine(
+            fpSchema,
+            "    <xs:extension base=\"gml:AbstractFeatureCollectionType\">");
+        PrintLine(fpSchema, "      <xs:attribute name=\"lockId\" type=\"xs:string\" use=\"optional\"/>");
+        PrintLine(fpSchema, "      <xs:attribute name=\"scope\" type=\"xs:string\" use=\"optional\"/>");
+        PrintLine(fpSchema, "    </xs:extension>");
+        PrintLine(fpSchema, "  </xs:complexContent>");
+        PrintLine(fpSchema, "</xs:complexType>");
     }
 
-/* ==================================================================== */
-/*      Define the schema for each layer.                               */
-/* ==================================================================== */
-
-    for( iLayer = 0; iLayer < GetLayerCount(); iLayer++ )
+    // Define the schema for each layer.
+    for( int iLayer = 0; iLayer < GetLayerCount(); iLayer++ )
     {
         OGRFeatureDefn *poFDefn = papoLayers[iLayer]->GetLayerDefn();
 
-/* -------------------------------------------------------------------- */
-/*      Emit initial stuff for a feature type.                          */
-/* -------------------------------------------------------------------- */
-        if (IsGML32Output())
+        // Emit initial stuff for a feature type.
+        if( IsGML32Output() )
         {
             PrintLine(
                 fpSchema,
                 "<xs:element name=\"%s\" type=\"%s:%s_Type\" substitutionGroup=\"gml:AbstractFeature\"/>",
-                poFDefn->GetName(), pszPrefix, poFDefn->GetName() );
+                poFDefn->GetName(), pszPrefix, poFDefn->GetName());
         }
         else
         {
             PrintLine(
                 fpSchema,
                 "<xs:element name=\"%s\" type=\"%s:%s_Type\" substitutionGroup=\"gml:_Feature\"/>",
-                poFDefn->GetName(), pszPrefix, poFDefn->GetName() );
+                poFDefn->GetName(), pszPrefix, poFDefn->GetName());
         }
 
-        PrintLine( fpSchema, "<xs:complexType name=\"%s_Type\">", poFDefn->GetName());
-        PrintLine( fpSchema, "  <xs:complexContent>");
-        PrintLine( fpSchema, "    <xs:extension base=\"gml:AbstractFeatureType\">");
-        PrintLine( fpSchema, "      <xs:sequence>");
+        PrintLine(fpSchema, "<xs:complexType name=\"%s_Type\">",
+                  poFDefn->GetName());
+        PrintLine(fpSchema, "  <xs:complexContent>");
+        PrintLine(fpSchema,
+                  "    <xs:extension base=\"gml:AbstractFeatureType\">");
+        PrintLine(fpSchema, "      <xs:sequence>");
 
         for( int iGeomField = 0; iGeomField < poFDefn->GetGeomFieldCount(); iGeomField++ )
         {
-            OGRGeomFieldDefn *poFieldDefn = poFDefn->GetGeomFieldDefn(iGeomField);
+            OGRGeomFieldDefn *poFieldDefn =
+                poFDefn->GetGeomFieldDefn(iGeomField);
 
-    /* -------------------------------------------------------------------- */
-    /*      Define the geometry attribute.                                  */
-    /* -------------------------------------------------------------------- */
-            const char* pszGeometryTypeName = "GeometryPropertyType";
-            const char* pszComment = "";
+            // Define the geometry attribute.
+            const char *pszGeometryTypeName = "GeometryPropertyType";
+            const char *pszComment = "";
             OGRwkbGeometryType eGType = wkbFlatten(poFieldDefn->GetType());
             switch(eGType)
             {
@@ -2253,243 +2343,244 @@ void OGRGMLDataSource::InsertHeader()
             }
 
             int nMinOccurs = poFieldDefn->IsNullable() ? 0 : 1;
-            PrintLine( fpSchema,
+            PrintLine(fpSchema,
                 "        <xs:element name=\"%s\" type=\"gml:%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"1\"/>%s",
-                       poFieldDefn->GetNameRef(), pszGeometryTypeName, nMinOccurs, pszComment );
+                      poFieldDefn->GetNameRef(), pszGeometryTypeName,
+                      nMinOccurs, pszComment);
         }
 
-/* -------------------------------------------------------------------- */
-/*      Emit each of the attributes.                                    */
-/* -------------------------------------------------------------------- */
+        // Emit each of the attributes.
         for( int iField = 0; iField < poFDefn->GetFieldCount(); iField++ )
         {
             OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn(iField);
 
-            if( IsGML3Output() && strcmp(poFieldDefn->GetNameRef(), "gml_id") == 0 )
+            if( IsGML3Output() &&
+                strcmp(poFieldDefn->GetNameRef(), "gml_id") == 0 )
                 continue;
-            else if( !IsGML3Output() && strcmp(poFieldDefn->GetNameRef(), "fid") == 0 )
+            else if( !IsGML3Output() &&
+                     strcmp(poFieldDefn->GetNameRef(), "fid") == 0 )
                 continue;
 
             int nMinOccurs = poFieldDefn->IsNullable() ? 0 : 1;
             if( poFieldDefn->GetType() == OFTInteger ||
-                poFieldDefn->GetType() == OFTIntegerList  )
+                poFieldDefn->GetType() == OFTIntegerList )
             {
-                int nWidth;
-
-                if( poFieldDefn->GetWidth() > 0 )
-                    nWidth = poFieldDefn->GetWidth();
-                else
-                    nWidth = 16;
-
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">",
-                           poFieldDefn->GetNameRef(),
-                           nMinOccurs,
-                           poFieldDefn->GetType() == OFTIntegerList ? "unbounded": "1" );
-                PrintLine( fpSchema, "          <xs:simpleType>");
+                int nWidth =
+                    poFieldDefn->GetWidth() > 0 ? poFieldDefn->GetWidth() : 16;
+
+                PrintLine(fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">",
+                          poFieldDefn->GetNameRef(),
+                          nMinOccurs,
+                          poFieldDefn->GetType() == OFTIntegerList ? "unbounded": "1");
+                PrintLine(fpSchema, "          <xs:simpleType>");
                 if( poFieldDefn->GetSubType() == OFSTBoolean )
                 {
-                    PrintLine( fpSchema, "            <xs:restriction base=\"xs:boolean\">");
+                    PrintLine(
+                        fpSchema,
+                        "            <xs:restriction base=\"xs:boolean\">");
                 }
                 else if( poFieldDefn->GetSubType() == OFSTInt16 )
                 {
-                    PrintLine( fpSchema, "            <xs:restriction base=\"xs:short\">");
+                    PrintLine(fpSchema,
+                              "            <xs:restriction base=\"xs:short\">");
                 }
                 else
                 {
-                    PrintLine( fpSchema, "            <xs:restriction base=\"xs:integer\">");
-                    PrintLine( fpSchema, "              <xs:totalDigits value=\"%d\"/>", nWidth);
+                    PrintLine(
+                        fpSchema,
+                        "            <xs:restriction base=\"xs:integer\">");
+                    PrintLine(fpSchema,
+                              "              <xs:totalDigits value=\"%d\"/>",
+                              nWidth);
                 }
-                PrintLine( fpSchema, "            </xs:restriction>");
-                PrintLine( fpSchema, "          </xs:simpleType>");
-                PrintLine( fpSchema, "        </xs:element>");
+                PrintLine(fpSchema, "            </xs:restriction>");
+                PrintLine(fpSchema, "          </xs:simpleType>");
+                PrintLine(fpSchema, "        </xs:element>");
             }
             else if( poFieldDefn->GetType() == OFTInteger64 ||
-                     poFieldDefn->GetType() == OFTInteger64List  )
+                     poFieldDefn->GetType() == OFTInteger64List )
             {
-                int nWidth;
-
-                if( poFieldDefn->GetWidth() > 0 )
-                    nWidth = poFieldDefn->GetWidth();
-                else
-                    nWidth = 16;
-
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">",
-                           poFieldDefn->GetNameRef(),
-                           nMinOccurs,
-                           poFieldDefn->GetType() == OFTInteger64List ? "unbounded": "1" );
-                PrintLine( fpSchema, "          <xs:simpleType>");
+                int nWidth =
+                    poFieldDefn->GetWidth() > 0 ? poFieldDefn->GetWidth() : 16;
+
+                PrintLine(fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">",
+                          poFieldDefn->GetNameRef(),
+                          nMinOccurs,
+                          poFieldDefn->GetType() == OFTInteger64List ? "unbounded": "1");
+                PrintLine(fpSchema, "          <xs:simpleType>");
                 if( poFieldDefn->GetSubType() == OFSTBoolean )
                 {
-                    PrintLine( fpSchema, "            <xs:restriction base=\"xs:boolean\">");
+                    PrintLine(
+                        fpSchema,
+                        "            <xs:restriction base=\"xs:boolean\">");
                 }
                 else if( poFieldDefn->GetSubType() == OFSTInt16 )
                 {
-                    PrintLine( fpSchema, "            <xs:restriction base=\"xs:short\">");
+                    PrintLine(fpSchema,
+                              "            <xs:restriction base=\"xs:short\">");
                 }
                 else
                 {
-                    PrintLine( fpSchema, "            <xs:restriction base=\"xs:long\">");
-                    PrintLine( fpSchema, "              <xs:totalDigits value=\"%d\"/>", nWidth);
+                    PrintLine(fpSchema,
+                              "            <xs:restriction base=\"xs:long\">");
+                    PrintLine(fpSchema,
+                              "              <xs:totalDigits value=\"%d\"/>",
+                              nWidth);
                 }
-                PrintLine( fpSchema, "            </xs:restriction>");
-                PrintLine( fpSchema, "          </xs:simpleType>");
-                PrintLine( fpSchema, "        </xs:element>");
+                PrintLine(fpSchema, "            </xs:restriction>");
+                PrintLine(fpSchema, "          </xs:simpleType>");
+                PrintLine(fpSchema, "        </xs:element>");
             }
             else if( poFieldDefn->GetType() == OFTReal ||
-                     poFieldDefn->GetType() == OFTRealList  )
+                     poFieldDefn->GetType() == OFTRealList )
             {
                 int nWidth, nDecimals;
 
                 nWidth = poFieldDefn->GetWidth();
                 nDecimals = poFieldDefn->GetPrecision();
 
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">",
-                           poFieldDefn->GetNameRef(),
-                           nMinOccurs,
-                           poFieldDefn->GetType() == OFTRealList ? "unbounded": "1" );
-                PrintLine( fpSchema, "          <xs:simpleType>");
+                PrintLine(fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">",
+                          poFieldDefn->GetNameRef(),
+                          nMinOccurs,
+                          poFieldDefn->GetType() == OFTRealList ? "unbounded": "1");
+                PrintLine(fpSchema, "          <xs:simpleType>");
                 if( poFieldDefn->GetSubType() == OFSTFloat32 )
-                    PrintLine( fpSchema, "            <xs:restriction base=\"xs:float\">");
+                    PrintLine(fpSchema, "            <xs:restriction base=\"xs:float\">");
                 else
-                    PrintLine( fpSchema, "            <xs:restriction base=\"xs:decimal\">");
+                    PrintLine(
+                        fpSchema,
+                        "            <xs:restriction base=\"xs:decimal\">");
                 if (nWidth > 0)
                 {
-                    PrintLine( fpSchema, "              <xs:totalDigits value=\"%d\"/>", nWidth);
-                    PrintLine( fpSchema, "              <xs:fractionDigits value=\"%d\"/>", nDecimals);
+                    PrintLine(fpSchema,
+                              "              <xs:totalDigits value=\"%d\"/>",
+                              nWidth);
+                    PrintLine(fpSchema,
+                              "              <xs:fractionDigits value=\"%d\"/>",
+                              nDecimals);
                 }
-                PrintLine( fpSchema, "            </xs:restriction>");
-                PrintLine( fpSchema, "          </xs:simpleType>");
-                PrintLine( fpSchema, "        </xs:element>");
+                PrintLine(fpSchema, "            </xs:restriction>");
+                PrintLine(fpSchema, "          </xs:simpleType>");
+                PrintLine(fpSchema, "        </xs:element>");
             }
             else if( poFieldDefn->GetType() == OFTString ||
                      poFieldDefn->GetType() == OFTStringList )
             {
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">",
-                           poFieldDefn->GetNameRef(),
-                           nMinOccurs,
-                           poFieldDefn->GetType() == OFTStringList ? "unbounded": "1" );
-                PrintLine( fpSchema, "          <xs:simpleType>");
-                PrintLine( fpSchema, "            <xs:restriction base=\"xs:string\">");
+                PrintLine(fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"%s\">",
+                          poFieldDefn->GetNameRef(),
+                          nMinOccurs,
+                          poFieldDefn->GetType() == OFTStringList ? "unbounded": "1");
+                PrintLine(fpSchema, "          <xs:simpleType>");
+                PrintLine(fpSchema,
+                          "            <xs:restriction base=\"xs:string\">");
                 if( poFieldDefn->GetWidth() != 0 )
                 {
-                    PrintLine( fpSchema, "              <xs:maxLength value=\"%d\"/>", poFieldDefn->GetWidth());
+                    PrintLine(fpSchema, "              <xs:maxLength value=\"%d\"/>", poFieldDefn->GetWidth());
                 }
-                PrintLine( fpSchema, "            </xs:restriction>");
-                PrintLine( fpSchema, "          </xs:simpleType>");
-                PrintLine( fpSchema, "        </xs:element>");
+                PrintLine(fpSchema, "            </xs:restriction>");
+                PrintLine(fpSchema, "          </xs:simpleType>");
+                PrintLine(fpSchema, "        </xs:element>");
             }
             else if( poFieldDefn->GetType() == OFTDate || poFieldDefn->GetType() == OFTDateTime )
             {
-                PrintLine( fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"1\">",
+                PrintLine(fpSchema, "        <xs:element name=\"%s\" nillable=\"true\" minOccurs=\"%d\" maxOccurs=\"1\">",
                            poFieldDefn->GetNameRef(),
                            nMinOccurs );
-                PrintLine( fpSchema, "          <xs:simpleType>");
-                PrintLine( fpSchema, "            <xs:restriction base=\"xs:string\">");
-                PrintLine( fpSchema, "            </xs:restriction>");
-                PrintLine( fpSchema, "          </xs:simpleType>");
-                PrintLine( fpSchema, "        </xs:element>");
+                PrintLine(fpSchema, "          <xs:simpleType>");
+                PrintLine(fpSchema,
+                          "            <xs:restriction base=\"xs:string\">");
+                PrintLine(fpSchema, "            </xs:restriction>");
+                PrintLine(fpSchema, "          </xs:simpleType>");
+                PrintLine(fpSchema, "        </xs:element>");
             }
             else
             {
-                /* TODO */
+                // TODO.
             }
-        } /* next field */
-
-/* -------------------------------------------------------------------- */
-/*      Finish off feature type.                                        */
-/* -------------------------------------------------------------------- */
-        PrintLine( fpSchema, "      </xs:sequence>");
-        PrintLine( fpSchema, "    </xs:extension>");
-        PrintLine( fpSchema, "  </xs:complexContent>");
-        PrintLine( fpSchema, "</xs:complexType>" );
-    } /* next layer */
-
-    PrintLine( fpSchema, "</xs:schema>" );
-
-/* ==================================================================== */
-/*      Move schema to the start of the file.                           */
-/* ==================================================================== */
+        }  // Next field.
+
+        // Finish off feature type.
+        PrintLine(fpSchema, "      </xs:sequence>");
+        PrintLine(fpSchema, "    </xs:extension>");
+        PrintLine(fpSchema, "  </xs:complexContent>");
+        PrintLine(fpSchema, "</xs:complexType>");
+    }  // Next layer.
+
+    PrintLine(fpSchema, "</xs:schema>");
+
+    // Move schema to the start of the file.
     if( fpSchema == fpOutput )
     {
-/* -------------------------------------------------------------------- */
-/*      Read the schema into memory.                                    */
-/* -------------------------------------------------------------------- */
-        int nSchemaSize = (int) VSIFTellL( fpOutput ) - nSchemaStart;
-        char *pszSchema = (char *) CPLMalloc(nSchemaSize+1);
+        // Read the schema into memory.
+        int nSchemaSize = static_cast<int>(VSIFTellL(fpOutput) - nSchemaStart);
+        char *pszSchema = static_cast<char *>(CPLMalloc(nSchemaSize + 1));
 
-        VSIFSeekL( fpOutput, nSchemaStart, SEEK_SET );
+        VSIFSeekL(fpOutput, nSchemaStart, SEEK_SET);
 
-        VSIFReadL( pszSchema, 1, nSchemaSize, fpOutput );
+        VSIFReadL(pszSchema, 1, nSchemaSize, fpOutput);
         pszSchema[nSchemaSize] = '\0';
 
-/* -------------------------------------------------------------------- */
-/*      Move file data down by "schema size" bytes from after <?xml>    */
-/*      header so we have room insert the schema.  Move in pretty       */
-/*      big chunks.                                                     */
-/* -------------------------------------------------------------------- */
-        int nChunkSize = MIN(nSchemaStart-nSchemaInsertLocation,250000);
-        char *pszChunk = (char *) CPLMalloc(nChunkSize);
+        // Move file data down by "schema size" bytes from after <?xml> header
+        // so we have room insert the schema.  Move in pretty big chunks.
+        int nChunkSize = std::min(nSchemaStart - nSchemaInsertLocation, 250000);
+        char *pszChunk = static_cast<char *>(CPLMalloc(nChunkSize));
 
         for( int nEndOfUnmovedData = nSchemaStart;
              nEndOfUnmovedData > nSchemaInsertLocation; )
         {
-            int nBytesToMove =
-                MIN(nChunkSize, nEndOfUnmovedData - nSchemaInsertLocation );
+            const int nBytesToMove =
+                std::min(nChunkSize, nEndOfUnmovedData - nSchemaInsertLocation);
 
-            VSIFSeekL( fpOutput, nEndOfUnmovedData - nBytesToMove, SEEK_SET );
-            VSIFReadL( pszChunk, 1, nBytesToMove, fpOutput );
-            VSIFSeekL( fpOutput, nEndOfUnmovedData - nBytesToMove + nSchemaSize,
-                      SEEK_SET );
-            VSIFWriteL( pszChunk, 1, nBytesToMove, fpOutput );
+            VSIFSeekL(fpOutput, nEndOfUnmovedData - nBytesToMove, SEEK_SET);
+            VSIFReadL(pszChunk, 1, nBytesToMove, fpOutput);
+            VSIFSeekL(fpOutput, nEndOfUnmovedData - nBytesToMove + nSchemaSize,
+                      SEEK_SET);
+            VSIFWriteL(pszChunk, 1, nBytesToMove, fpOutput);
 
             nEndOfUnmovedData -= nBytesToMove;
         }
 
-        CPLFree( pszChunk );
+        CPLFree(pszChunk);
 
-/* -------------------------------------------------------------------- */
-/*      Write the schema in the opened slot.                            */
-/* -------------------------------------------------------------------- */
-        VSIFSeekL( fpOutput, nSchemaInsertLocation, SEEK_SET );
-        VSIFWriteL( pszSchema, 1, nSchemaSize, fpOutput );
+        // Write the schema in the opened slot.
+        VSIFSeekL(fpOutput, nSchemaInsertLocation, SEEK_SET);
+        VSIFWriteL(pszSchema, 1, nSchemaSize, fpOutput);
 
-        VSIFSeekL( fpOutput, 0, SEEK_END );
+        VSIFSeekL(fpOutput, 0, SEEK_END);
 
         nBoundedByLocation += nSchemaSize;
 
         CPLFree(pszSchema);
     }
-/* -------------------------------------------------------------------- */
-/*      Close external schema files.                                    */
-/* -------------------------------------------------------------------- */
     else
-        VSIFCloseL( fpSchema );
+    {
+        // Close external schema files.
+        VSIFCloseL(fpSchema);
+    }
 }
 
-
 /************************************************************************/
 /*                            PrintLine()                               */
 /************************************************************************/
 
-void OGRGMLDataSource::PrintLine(VSILFILE* fp, const char *fmt, ...)
+void OGRGMLDataSource::PrintLine(VSILFILE *fp, const char *fmt, ...)
 {
     CPLString osWork;
     va_list args;
 
-    va_start( args, fmt );
-    osWork.vPrintf( fmt, args );
-    va_end( args );
+    va_start(args, fmt);
+    osWork.vPrintf(fmt, args);
+    va_end(args);
 
 #ifdef WIN32
-    const char* pszEOL = "\r\n";
+    const char *pszEOL = "\r\n";
 #else
-    const char* pszEOL = "\n";
+    const char *pszEOL = "\n";
 #endif
 
     VSIFPrintfL(fp, "%s%s", osWork.c_str(), pszEOL);
 }
 
-
 /************************************************************************/
 /*                     OGRGMLSingleFeatureLayer                         */
 /************************************************************************/
@@ -2502,42 +2593,41 @@ class OGRGMLSingleFeatureLayer : public OGRLayer
     int                 iNextShapeId;
 
   public:
-                        OGRGMLSingleFeatureLayer(int nVal );
-                        ~OGRGMLSingleFeatureLayer() { poFeatureDefn->Release(); }
+    explicit            OGRGMLSingleFeatureLayer(int nVal );
+    virtual ~OGRGMLSingleFeatureLayer() { poFeatureDefn->Release(); }
 
-    virtual void        ResetReading() { iNextShapeId = 0; }
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
-    virtual int         TestCapability( const char * ) { return FALSE; }
+    virtual void        ResetReading() override { iNextShapeId = 0; }
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
+    virtual int         TestCapability( const char * ) override { return FALSE; }
 };
 
 /************************************************************************/
 /*                      OGRGMLSingleFeatureLayer()                      */
 /************************************************************************/
 
-OGRGMLSingleFeatureLayer::OGRGMLSingleFeatureLayer( int nValIn )
+OGRGMLSingleFeatureLayer::OGRGMLSingleFeatureLayer( int nValIn ) :
+    nVal(nValIn),
+    poFeatureDefn(new OGRFeatureDefn("SELECT")),
+    iNextShapeId(0)
 {
-    poFeatureDefn = new OGRFeatureDefn( "SELECT" );
     poFeatureDefn->Reference();
-    OGRFieldDefn oField( "Validates", OFTInteger );
-    poFeatureDefn->AddFieldDefn( &oField );
-
-    this->nVal = nValIn;
-    iNextShapeId = 0;
+    OGRFieldDefn oField("Validates", OFTInteger);
+    poFeatureDefn->AddFieldDefn(&oField);
 }
 
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
-OGRFeature * OGRGMLSingleFeatureLayer::GetNextFeature()
+OGRFeature *OGRGMLSingleFeatureLayer::GetNextFeature()
 {
     if (iNextShapeId != 0)
         return NULL;
 
-    OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
+    OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     poFeature->SetField(0, nVal);
-    poFeature->SetFID(iNextShapeId ++);
+    poFeature->SetFID(iNextShapeId++);
     return poFeature;
 }
 
@@ -2552,67 +2642,44 @@ OGRLayer * OGRGMLDataSource::ExecuteSQL( const char *pszSQLCommand,
     if (poReader != NULL && EQUAL(pszSQLCommand, "SELECT ValidateSchema()"))
     {
         bool bIsValid = false;
-        if (osXSDFilename.size())
+        if (!osXSDFilename.empty() )
         {
             CPLErrorReset();
-            bIsValid = CPL_TO_BOOL(CPLValidateXML(osFilename, osXSDFilename, NULL));
+            bIsValid =
+                CPL_TO_BOOL(CPLValidateXML(osFilename, osXSDFilename, NULL));
         }
         return new OGRGMLSingleFeatureLayer(bIsValid);
     }
 
-    return OGRDataSource::ExecuteSQL(pszSQLCommand, poSpatialFilter, pszDialect);
+    return OGRDataSource::ExecuteSQL(pszSQLCommand, poSpatialFilter,
+                                     pszDialect);
 }
 
 /************************************************************************/
 /*                          ReleaseResultSet()                          */
 /************************************************************************/
 
-void OGRGMLDataSource::ReleaseResultSet( OGRLayer * poResultsSet )
+void OGRGMLDataSource::ReleaseResultSet( OGRLayer *poResultsSet )
 {
     delete poResultsSet;
 }
 
 /************************************************************************/
-/*                          ExtractSRSName()                            */
-/************************************************************************/
-
-static bool ExtractSRSName(const char* pszXML, char* szSRSName,
-                           size_t sizeof_szSRSName)
-{
-    szSRSName[0] = '\0';
-
-    const char* pszSRSName = strstr(pszXML, "srsName=\"");
-    if( pszSRSName != NULL )
-    {
-        pszSRSName += 9;
-        const char* pszEndQuote = strchr(pszSRSName, '"');
-        if (pszEndQuote != NULL &&
-            (size_t)(pszEndQuote - pszSRSName) < sizeof_szSRSName)
-        {
-            memcpy(szSRSName, pszSRSName, pszEndQuote - pszSRSName);
-            szSRSName[pszEndQuote - pszSRSName] = '\0';
-            return true;
-        }
-    }
-    return false;
-}
-
-/************************************************************************/
 /*                      FindAndParseTopElements()                       */
 /************************************************************************/
 
-void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
+void OGRGMLDataSource::FindAndParseTopElements(VSILFILE *fp)
 {
-    /* Build a shortened XML file that contain only the global */
-    /* boundedBy element, so as to be able to parse it easily */
+    // Build a shortened XML file that contain only the global
+    // boundedBy element, so as to be able to parse it easily.
 
     char szStartTag[128];
-    char* pszXML = (char*)CPLMalloc(8192 + 128 + 3 + 1);
+    char *pszXML = static_cast<char *>(CPLMalloc(8192 + 128 + 3 + 1));
     VSIFSeekL(fp, 0, SEEK_SET);
-    int nRead = (int)VSIFReadL(pszXML, 1, 8192, fp);
+    int nRead = static_cast<int>(VSIFReadL(pszXML, 1, 8192, fp));
     pszXML[nRead] = 0;
 
-    const char* pszStartTag = strchr(pszXML, '<');
+    const char *pszStartTag = strchr(pszXML, '<');
     if (pszStartTag != NULL)
     {
         while (pszStartTag != NULL && pszStartTag[1] == '?')
@@ -2620,8 +2687,8 @@ void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
 
         if (pszStartTag != NULL)
         {
-            pszStartTag ++;
-            const char* pszEndTag = strchr(pszStartTag, ' ');
+            pszStartTag++;
+            const char *pszEndTag = strchr(pszStartTag, ' ');
             if (pszEndTag != NULL && pszEndTag - pszStartTag < 128 )
             {
                 memcpy(szStartTag, pszStartTag, pszEndTag - pszStartTag);
@@ -2632,42 +2699,42 @@ void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
         }
     }
 
-    const char* pszDescription = strstr(pszXML, "<gml:description>");
+    const char *pszDescription = strstr(pszXML, "<gml:description>");
     if( pszDescription )
     {
         pszDescription += strlen("<gml:description>");
-        const char* pszEndDescription = strstr(pszDescription,
-                                               "</gml:description>");
+        const char *pszEndDescription =
+            strstr(pszDescription, "</gml:description>");
         if( pszEndDescription )
         {
             CPLString osTmp(pszDescription);
-            osTmp.resize(pszEndDescription-pszDescription);
-            char* pszTmp = CPLUnescapeString(osTmp, NULL, CPLES_XML);
+            osTmp.resize(pszEndDescription - pszDescription);
+            char *pszTmp = CPLUnescapeString(osTmp, NULL, CPLES_XML);
             if( pszTmp )
                 SetMetadataItem("DESCRIPTION", pszTmp);
             CPLFree(pszTmp);
         }
     }
 
-    const char* l_pszName = strstr(pszXML, "<gml:name");
+    const char *l_pszName = strstr(pszXML, "<gml:name");
     if( l_pszName )
         l_pszName = strchr(l_pszName, '>');
     if( l_pszName )
     {
-        l_pszName ++;
-        const char* pszEndName = strstr(l_pszName, "</gml:name>");
+        l_pszName++;
+        const char *pszEndName = strstr(l_pszName, "</gml:name>");
         if( pszEndName )
         {
             CPLString osTmp(l_pszName);
-            osTmp.resize(pszEndName-l_pszName);
-            char* pszTmp = CPLUnescapeString(osTmp, NULL, CPLES_XML);
+            osTmp.resize(pszEndName - l_pszName);
+            char *pszTmp = CPLUnescapeString(osTmp, NULL, CPLES_XML);
             if( pszTmp )
                 SetMetadataItem("NAME", pszTmp);
             CPLFree(pszTmp);
         }
     }
 
-    char* pszEndBoundedBy = strstr(pszXML, "</wfs:boundedBy>");
+    char *pszEndBoundedBy = strstr(pszXML, "</wfs:boundedBy>");
     bool bWFSBoundedBy = false;
     if (pszEndBoundedBy != NULL)
         bWFSBoundedBy = true;
@@ -2675,14 +2742,11 @@ void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
         pszEndBoundedBy = strstr(pszXML, "</gml:boundedBy>");
     if (pszStartTag != NULL && pszEndBoundedBy != NULL)
     {
-        const char* pszSRSName = NULL;
-        char szSRSName[128];
-
-        szSRSName[0] = '\0';
+        char szSRSName[128] = {};
 
-        /* Find a srsName somewhere for some WFS 2.0 documents */
-        /* that have not it set at the <wfs:boundedBy> element */
-        /* e.g. http://geoserv.weichand.de:8080/geoserver/wfs?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAME=bvv:gmd_ex */
+        // Find a srsName somewhere for some WFS 2.0 documents that have not it
+        // set at the <wfs:boundedBy> element. e.g.
+        // http://geoserv.weichand.de:8080/geoserver/wfs?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAME=bvv:gmd_ex
         if( bIsWFS )
         {
             ExtractSRSName(pszXML, szSRSName, sizeof(szSRSName));
@@ -2694,32 +2758,36 @@ void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
         strcat(pszXML, ">");
 
         CPLPushErrorHandler(CPLQuietErrorHandler);
-        CPLXMLNode* psXML = CPLParseXMLString(pszXML);
+        CPLXMLNode *psXML = CPLParseXMLString(pszXML);
         CPLPopErrorHandler();
         CPLErrorReset();
         if (psXML != NULL)
         {
-            CPLXMLNode* psBoundedBy = NULL;
-            CPLXMLNode* psIter = psXML;
+            CPLXMLNode *psBoundedBy = NULL;
+            CPLXMLNode *psIter = psXML;
             while(psIter != NULL)
             {
-                psBoundedBy = CPLGetXMLNode(psIter, bWFSBoundedBy ?
-                                        "wfs:boundedBy" : "gml:boundedBy");
+                psBoundedBy = CPLGetXMLNode(
+                    psIter, bWFSBoundedBy ? "wfs:boundedBy" : "gml:boundedBy");
                 if (psBoundedBy != NULL)
                     break;
                 psIter = psIter->psNext;
             }
 
-            const char* pszLowerCorner = NULL;
-            const char* pszUpperCorner = NULL;
+            const char *pszLowerCorner = NULL;
+            const char *pszUpperCorner = NULL;
+            const char *pszSRSName = NULL;
             if (psBoundedBy != NULL)
             {
-                CPLXMLNode* psEnvelope = CPLGetXMLNode(psBoundedBy, "gml:Envelope");
+                CPLXMLNode *psEnvelope =
+                    CPLGetXMLNode(psBoundedBy, "gml:Envelope");
                 if (psEnvelope)
                 {
                     pszSRSName = CPLGetXMLValue(psEnvelope, "srsName", NULL);
-                    pszLowerCorner = CPLGetXMLValue(psEnvelope, "gml:lowerCorner", NULL);
-                    pszUpperCorner = CPLGetXMLValue(psEnvelope, "gml:upperCorner", NULL);
+                    pszLowerCorner =
+                        CPLGetXMLValue(psEnvelope, "gml:lowerCorner", NULL);
+                    pszUpperCorner =
+                        CPLGetXMLValue(psEnvelope, "gml:upperCorner", NULL);
                 }
             }
 
@@ -2730,28 +2798,32 @@ void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
                 pszSRSName = szSRSName;
             }
 
-            if (pszSRSName != NULL && pszLowerCorner != NULL && pszUpperCorner != NULL)
+            if (pszSRSName != NULL && pszLowerCorner != NULL &&
+                pszUpperCorner != NULL)
             {
-                char** papszLC = CSLTokenizeString(pszLowerCorner);
-                char** papszUC = CSLTokenizeString(pszUpperCorner);
+                char **papszLC = CSLTokenizeString(pszLowerCorner);
+                char **papszUC = CSLTokenizeString(pszUpperCorner);
                 if (CSLCount(papszLC) >= 2 && CSLCount(papszUC) >= 2)
                 {
                     CPLDebug("GML", "Global SRS = %s", pszSRSName);
 
-                    if (STARTS_WITH(pszSRSName, "http://www.opengis.net/gml/srs/epsg.xml#"))
+                    if (STARTS_WITH(pszSRSName,
+                                    "http://www.opengis.net/gml/srs/epsg.xml#"))
                     {
                         std::string osWork;
                         osWork.assign("EPSG:", 5);
-                        osWork.append(pszSRSName+40);
+                        osWork.append(pszSRSName + 40);
                         poReader->SetGlobalSRSName(osWork.c_str());
                     }
                     else
+                    {
                         poReader->SetGlobalSRSName(pszSRSName);
+                    }
 
-                    double dfMinX = CPLAtofM(papszLC[0]);
-                    double dfMinY = CPLAtofM(papszLC[1]);
-                    double dfMaxX = CPLAtofM(papszUC[0]);
-                    double dfMaxY = CPLAtofM(papszUC[1]);
+                    const double dfMinX = CPLAtofM(papszLC[0]);
+                    const double dfMinY = CPLAtofM(papszLC[1]);
+                    const double dfMaxX = CPLAtofM(papszUC[0]);
+                    const double dfMaxY = CPLAtofM(papszUC[1]);
 
                     SetExtents(dfMinX, dfMinY, dfMaxX, dfMaxY);
                 }
@@ -2770,7 +2842,8 @@ void OGRGMLDataSource::FindAndParseTopElements(VSILFILE* fp)
 /*                             SetExtents()                             */
 /************************************************************************/
 
-void OGRGMLDataSource::SetExtents(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY)
+void OGRGMLDataSource::SetExtents(double dfMinX, double dfMinY,
+                                  double dfMaxX, double dfMaxY)
 {
     sBoundingRect.MinX = dfMinX;
     sBoundingRect.MinY = dfMinY;
@@ -2782,7 +2855,7 @@ void OGRGMLDataSource::SetExtents(double dfMinX, double dfMinY, double dfMaxX, d
 /*                             GetAppPrefix()                           */
 /************************************************************************/
 
-const char* OGRGMLDataSource::GetAppPrefix()
+const char *OGRGMLDataSource::GetAppPrefix()
 {
     return CSLFetchNameValueDef(papszCreateOptions, "PREFIX", "ogr");
 }
@@ -2793,11 +2866,11 @@ const char* OGRGMLDataSource::GetAppPrefix()
 
 bool OGRGMLDataSource::RemoveAppPrefix()
 {
-    if( CPLTestBool(CSLFetchNameValueDef(
-            papszCreateOptions, "STRIP_PREFIX", "FALSE")) )
+    if( CPLTestBool(
+            CSLFetchNameValueDef(papszCreateOptions, "STRIP_PREFIX", "FALSE")))
         return true;
-    const char* pszPrefix = GetAppPrefix();
-    return( pszPrefix[0] == '\0' );
+    const char *pszPrefix = GetAppPrefix();
+    return pszPrefix[0] == '\0';
 }
 
 /************************************************************************/
@@ -2814,7 +2887,7 @@ bool OGRGMLDataSource::WriteFeatureBoundedBy()
 /*                          GetSRSDimensionLoc()                        */
 /************************************************************************/
 
-const char* OGRGMLDataSource::GetSRSDimensionLoc()
+const char *OGRGMLDataSource::GetSRSDimensionLoc()
 {
     return CSLFetchNameValue(papszCreateOptions, "SRSDIMENSION_LOC");
 }
diff --git a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
index da43d35..0bb2d55 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmldriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgmldriver.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  OGR
  * Purpose:  OGRGMLDriver implementation
@@ -32,18 +31,7 @@
 #include "cpl_multiproc.h"
 #include "gmlreaderp.h"
 
-CPL_CVSID("$Id: ogrgmldriver.cpp 35690 2016-10-11 09:56:31Z rouault $");
-
-/************************************************************************/
-/*                        OGRGMLDriverUnload()                          */
-/************************************************************************/
-
-static void OGRGMLDriverUnload(CPL_UNUSED GDALDriver* poDriver)
-{
-    if( GMLReader::hMutex != NULL )
-        CPLDestroyMutex( GMLReader::hMutex );
-    GMLReader::hMutex = NULL;
-}
+CPL_CVSID("$Id: ogrgmldriver.cpp 36158 2016-11-08 13:53:11Z rouault $");
 
 /************************************************************************/
 /*                         OGRGMLDriverIdentify()                       */
@@ -97,15 +85,13 @@ static int OGRGMLDriverIdentify( GDALOpenInfo* poOpenInfo )
 static GDALDataset *OGRGMLDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRGMLDataSource    *poDS;
-
     if( poOpenInfo->eAccess == GA_Update )
         return NULL;
 
     if( OGRGMLDriverIdentify( poOpenInfo ) == FALSE )
         return NULL;
 
-    poDS = new OGRGMLDataSource();
+    OGRGMLDataSource *poDS = new OGRGMLDataSource();
 
     if( !poDS->Open(  poOpenInfo ) )
     {
@@ -216,6 +202,11 @@ void RegisterOGRGML()
 "    <Value>GML3Deegree</Value>"
 "  </Option>"
 "  <Option name='GML3_LONGSRS' type='boolean' description='Whether to write SRS with \"urn:ogc:def:crs:EPSG::\" prefix with GML3* versions' default='YES'/>"
+"  <Option name='SRSNAME_FORMAT' type='string-select' description='Format of srsName (for GML3* versions)' default='OGC_URL'>"
+"    <Value>SHORT</Value>"
+"    <Value>OGC_URN</Value>"
+"    <Value>OGC_URL</Value>"
+"  </Option>"
 "  <Option name='WRITE_FEATURE_BOUNDED_BY' type='boolean' description='Whether to write <gml:boundedBy> element for each feature with GML3* versions' default='YES'/>"
 "  <Option name='SPACE_INDENTATION' type='boolean' description='Whether to indent the output for readability' default='YES'/>"
 "  <Option name='SRSDIMENSION_LOC' type='string-select' description='(only valid for FORMAT=GML3xx) Location where to put srsDimension attribute' default='POSLIST'>"
@@ -237,7 +228,6 @@ void RegisterOGRGML()
     poDriver->pfnOpen = OGRGMLDriverOpen;
     poDriver->pfnIdentify = OGRGMLDriverIdentify;
     poDriver->pfnCreate = OGRGMLDriverCreate;
-    poDriver->pfnUnloadDriver = OGRGMLDriverUnload;
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
index 14017f4..e0c11de 100644
--- a/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
+++ b/ogr/ogrsf_frmts/gml/ogrgmllayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgmllayer.cpp 35690 2016-10-11 09:56:31Z rouault $
  *
  * Project:  OGR
  * Purpose:  Implements OGRGMLLayer class.
@@ -36,7 +35,7 @@
 #include "ogr_p.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ogrgmllayer.cpp 35690 2016-10-11 09:56:31Z rouault $");
+CPL_CVSID("$Id: ogrgmllayer.cpp 37447 2017-02-25 15:06:33Z goatbar $");
 
 /************************************************************************/
 /*                           OGRGMLLayer()                              */
@@ -44,46 +43,30 @@ CPL_CVSID("$Id: ogrgmllayer.cpp 35690 2016-10-11 09:56:31Z rouault $");
 
 OGRGMLLayer::OGRGMLLayer( const char * pszName,
                           bool bWriterIn,
-                          OGRGMLDataSource *poDSIn )
-
+                          OGRGMLDataSource *poDSIn ) :
+    poFeatureDefn(new OGRFeatureDefn(
+        pszName + (STARTS_WITH_CI(pszName, "ogr:") ? 4 : 0))),
+    iNextGMLId(0),
+    bInvalidFIDFound(false),
+    pszFIDPrefix(NULL),
+    bWriter(bWriterIn),
+    bSameSRS(false),
+    poDS(poDSIn),
+    poFClass(!bWriter ? poDS->GetReader()->GetClass(pszName) :  NULL),
+    // Reader's should get the corresponding GMLFeatureClass and cache it.
+    hCacheSRS(GML_BuildOGRGeometryFromList_CreateCache()),
+    // Compatibility option. Not advertized, because hopefully won't be needed.
+    // Just put here in case.
+    bUseOldFIDFormat(CPLTestBool(
+        CPLGetConfigOption("GML_USE_OLD_FID_FORMAT", "FALSE"))),
+    // Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer()
+    // and GMLReader::GMLReader().
+    bFaceHoleNegative(CPLTestBool(
+        CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO")))
 {
-    iNextGMLId = 0;
-    nTotalGMLCount = -1;
-    bInvalidFIDFound = false;
-    pszFIDPrefix = NULL;
-    bFaceHoleNegative = false;
-
-    poDS = poDSIn;
-
-    if ( STARTS_WITH_CI(pszName, "ogr:") )
-      poFeatureDefn = new OGRFeatureDefn( pszName+4 );
-    else
-      poFeatureDefn = new OGRFeatureDefn( pszName );
-    SetDescription( poFeatureDefn->GetName() );
+    SetDescription(poFeatureDefn->GetName());
     poFeatureDefn->Reference();
-    poFeatureDefn->SetGeomType( wkbNone );
-
-    bWriter = bWriterIn;
-    bSameSRS = false;
-
-/* -------------------------------------------------------------------- */
-/*      Reader's should get the corresponding GMLFeatureClass and       */
-/*      cache it.                                                       */
-/* -------------------------------------------------------------------- */
-    if( !bWriter )
-        poFClass = poDS->GetReader()->GetClass( pszName );
-    else
-        poFClass = NULL;
-
-    hCacheSRS = GML_BuildOGRGeometryFromList_CreateCache();
-
-    /* Compatibility option. Not advertized, because hopefully won't be needed */
-    /* Just put here in provision... */
-    bUseOldFIDFormat = CPLTestBool(CPLGetConfigOption("GML_USE_OLD_FID_FORMAT", "FALSE"));
-
-    /* Must be in synced in OGR_G_CreateFromGML(), OGRGMLLayer::OGRGMLLayer() and GMLReader::GMLReader() */
-    bFaceHoleNegative = CPLTestBool(CPLGetConfigOption("GML_FACE_HOLE_NEGATIVE", "NO"));
-
+    poFeatureDefn->SetGeomType(wkbNone);
 }
 
 /************************************************************************/
@@ -114,8 +97,8 @@ void OGRGMLLayer::ResetReading()
     if (poDS->GetReadMode() == INTERLEAVED_LAYERS ||
         poDS->GetReadMode() == SEQUENTIAL_LAYERS)
     {
-        /* Does the last stored feature belong to our layer ? If so, no */
-        /* need to reset the reader */
+        // Does the last stored feature belong to our layer ? If so, no
+        // need to reset the reader.
         if (iNextGMLId == 0 && poDS->PeekStoredGMLFeature() != NULL &&
             poDS->PeekStoredGMLFeature()->GetClass() == poFClass)
             return;
@@ -129,8 +112,8 @@ void OGRGMLLayer::ResetReading()
     CPLDebug("GML", "ResetReading()");
     if ( poDS->GetLayerCount() > 1 && poDS->GetReadMode() == STANDARD )
     {
-        const char* pszElementName = poFClass->GetElementName();
-        const char* pszLastPipe = strrchr( pszElementName, '|' );
+        const char *pszElementName = poFClass->GetElementName();
+        const char *pszLastPipe = strrchr(pszElementName, '|');
         if ( pszLastPipe != NULL )
             pszElementName = pszLastPipe + 1;
         poDS->GetReader()->SetFilteredClassName(pszElementName);
@@ -164,12 +147,11 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /* ==================================================================== */
     while( true )
     {
-        GMLFeature  *poGMLFeature = NULL;
-        OGRGeometry *poGeom = NULL;
-
-        poGMLFeature = poDS->PeekStoredGMLFeature();
+        GMLFeature *poGMLFeature = poDS->PeekStoredGMLFeature();
         if (poGMLFeature != NULL)
+        {
             poDS->SetStoredGMLFeature(NULL);
+        }
         else
         {
             poGMLFeature = poDS->GetReader()->NextFeature();
@@ -211,7 +193,7 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /*       assigned serially thereafter                                   */
 /* -------------------------------------------------------------------- */
         GIntBig nFID = -1;
-        const char * pszGML_FID = poGMLFeature->GetFID();
+        const char *pszGML_FID = poGMLFeature->GetFID();
         if( bInvalidFIDFound )
         {
             nFID = iNextGMLId++;
@@ -224,19 +206,23 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
         else if( iNextGMLId == 0 )
         {
             int j = 0;
-            int i = static_cast<int>(strlen( pszGML_FID ))-1;
+            int i = static_cast<int>(strlen(pszGML_FID)) - 1;
             while( i >= 0 && pszGML_FID[i] >= '0'
-                          && pszGML_FID[i] <= '9' && j<20)
-                i--, j++;
-            /* i points the last character of the fid */
+                          && pszGML_FID[i] <= '9' && j < 20)
+            {
+                i--;
+                j++;
+            }
+            // i points the last character of the fid.
             if( i >= 0 && j < 20 && pszFIDPrefix == NULL)
             {
-                pszFIDPrefix = (char *) CPLMalloc(i+2);
-                pszFIDPrefix[i+1] = '\0';
-                strncpy(pszFIDPrefix, pszGML_FID, i+1);
+                pszFIDPrefix = static_cast<char *>(CPLMalloc(i + 2));
+                pszFIDPrefix[i + 1] = '\0';
+                strncpy(pszFIDPrefix, pszGML_FID, i + 1);
             }
-            /* pszFIDPrefix now contains the prefix or NULL if no prefix is found */
-            if( j < 20 && sscanf(pszGML_FID+i+1, CPL_FRMT_GIB, &nFID)==1)
+            // pszFIDPrefix now contains the prefix or NULL if no prefix is
+            // found.
+            if( j < 20 && sscanf(pszGML_FID + i + 1, CPL_FRMT_GIB, &nFID) == 1)
             {
                 if( iNextGMLId <= nFID )
                     iNextGMLId = nFID + 1;
@@ -247,21 +233,24 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                 nFID = iNextGMLId++;
             }
         }
-        else if( iNextGMLId != 0 )
+        else  // if( iNextGMLId != 0 ).
         {
-            const char* pszFIDPrefix_notnull = pszFIDPrefix;
+            const char *pszFIDPrefix_notnull = pszFIDPrefix;
             if (pszFIDPrefix_notnull == NULL) pszFIDPrefix_notnull = "";
             int nLenPrefix = static_cast<int>(strlen(pszFIDPrefix_notnull));
 
-            if(  strncmp(pszGML_FID, pszFIDPrefix_notnull, nLenPrefix) == 0 &&
-                 strlen(pszGML_FID+nLenPrefix) < 20 &&
-                 sscanf(pszGML_FID+nLenPrefix, CPL_FRMT_GIB, &nFID) == 1 )
-            { /* fid with the prefix. Using its numerical part */
+            if( strncmp(pszGML_FID, pszFIDPrefix_notnull, nLenPrefix) == 0 &&
+                strlen(pszGML_FID + nLenPrefix) < 20 &&
+                sscanf(pszGML_FID + nLenPrefix, CPL_FRMT_GIB, &nFID) == 1 )
+            {
+                // fid with the prefix. Using its numerical part.
                 if( iNextGMLId < nFID )
                     iNextGMLId = nFID + 1;
             }
             else
-            { /* fid without the aforementioned prefix or a valid numerical part */
+            {
+                // fid without the aforementioned prefix or a valid numerical
+                // part.
                 bInvalidFIDFound = true;
                 nFID = iNextGMLId++;
             }
@@ -271,45 +260,47 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /*      Does it satisfy the spatial query, if there is one?             */
 /* -------------------------------------------------------------------- */
 
-        OGRGeometry** papoGeometries = NULL;
-        const CPLXMLNode* const * papsGeometry = poGMLFeature->GetGeometryList();
+        OGRGeometry **papoGeometries = NULL;
+        const CPLXMLNode *const *papsGeometry = poGMLFeature->GetGeometryList();
+
+        OGRGeometry *poGeom = NULL;
 
         if( poFeatureDefn->GetGeomFieldCount() > 1 )
         {
-            papoGeometries = (OGRGeometry**)
-                CPLCalloc( poFeatureDefn->GetGeomFieldCount(), sizeof(OGRGeometry*) );
-            const char* pszSRSName = poDS->GetGlobalSRSName();
-            for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+            papoGeometries = static_cast<OGRGeometry **>(CPLCalloc(
+                poFeatureDefn->GetGeomFieldCount(), sizeof(OGRGeometry *)));
+            const char *pszSRSName = poDS->GetGlobalSRSName();
+            for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
             {
-                const CPLXMLNode* psGeom = poGMLFeature->GetGeometryRef(i);
+                const CPLXMLNode *psGeom = poGMLFeature->GetGeometryRef(i);
                 if( psGeom != NULL )
                 {
-                    const CPLXMLNode* myGeometryList[2];
-                    myGeometryList[0] = psGeom;
-                    myGeometryList[1] = NULL;
-                    poGeom = GML_BuildOGRGeometryFromList(myGeometryList, true,
-                                                  poDS->GetInvertAxisOrderIfLatLong(),
-                                                  pszSRSName,
-                                                  poDS->GetConsiderEPSGAsURN(),
-                                                  poDS->GetSwapCoordinates(),
-                                                  poDS->GetSecondaryGeometryOption(),
-                                                  hCacheSRS,
-                                                  bFaceHoleNegative );
-
-                    /* Do geometry type changes if needed to match layer geometry type */
+                    const CPLXMLNode *myGeometryList[2] = {psGeom, NULL};
+                    poGeom = GML_BuildOGRGeometryFromList(
+                        myGeometryList, true,
+                        poDS->GetInvertAxisOrderIfLatLong(), pszSRSName,
+                        poDS->GetConsiderEPSGAsURN(),
+                        poDS->GetSwapCoordinates(),
+                        poDS->GetSecondaryGeometryOption(), hCacheSRS,
+                        bFaceHoleNegative);
+
+                    // Do geometry type changes if needed to match layer
+                    // geometry type.
                     if (poGeom != NULL)
                     {
-                        papoGeometries[i] = OGRGeometryFactory::forceTo(poGeom,
-                                    poFeatureDefn->GetGeomFieldDefn(i)->GetType());
+                        papoGeometries[i] = OGRGeometryFactory::forceTo(
+                            poGeom,
+                            poFeatureDefn->GetGeomFieldDefn(i)->GetType());
                         poGeom = NULL;
                     }
                     else
-                    // We assume the createFromGML() function would have already
-                    // reported the error.
                     {
-                        for( i=0; i < poFeatureDefn->GetGeomFieldCount(); i++)
+                        // We assume the createFromGML() function would have
+                        // already reported the error.
+                        for(int j = 0; j < poFeatureDefn->GetGeomFieldCount();
+                            j++)
                         {
-                            delete papoGeometries[i];
+                            delete papoGeometries[j];
                         }
                         CPLFree(papoGeometries);
                         delete poGMLFeature;
@@ -324,9 +315,9 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                 papoGeometries[m_iGeomFieldFilter] &&
                 !FilterGeometry( papoGeometries[m_iGeomFieldFilter] ) )
             {
-                for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+                for( int j = 0; j < poFeatureDefn->GetGeomFieldCount(); j++ )
                 {
-                    delete papoGeometries[i];
+                    delete papoGeometries[j];
                 }
                 CPLFree(papoGeometries);
                 delete poGMLFeature;
@@ -335,30 +326,47 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
         }
         else if (papsGeometry[0] != NULL)
         {
-            const char* pszSRSName = poDS->GetGlobalSRSName();
-            poGeom = GML_BuildOGRGeometryFromList(papsGeometry, true,
-                                                  poDS->GetInvertAxisOrderIfLatLong(),
-                                                  pszSRSName,
-                                                  poDS->GetConsiderEPSGAsURN(),
-                                                  poDS->GetSwapCoordinates(),
-                                                  poDS->GetSecondaryGeometryOption(),
-                                                  hCacheSRS,
-                                                  bFaceHoleNegative );
-
-            /* Do geometry type changes if needed to match layer geometry type */
+            const char *pszSRSName = poDS->GetGlobalSRSName();
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+            poGeom = GML_BuildOGRGeometryFromList(
+                papsGeometry, true,
+                poDS->GetInvertAxisOrderIfLatLong(),
+                pszSRSName,
+                poDS->GetConsiderEPSGAsURN(),
+                poDS->GetSwapCoordinates(),
+                poDS->GetSecondaryGeometryOption(),
+                hCacheSRS,
+                bFaceHoleNegative);
+            CPLPopErrorHandler();
+
+            // Do geometry type changes if needed to match layer geometry type.
             if (poGeom != NULL)
             {
                 poGeom = OGRGeometryFactory::forceTo(poGeom, GetGeomType());
             }
             else
-            // We assume the createFromGML() function would have already
-            // reported the error.
             {
+                const CPLString osLastErrorMsg(CPLGetLastErrorMsg());
+
+                const bool bGoOn = CPLTestBool(
+                    CPLGetConfigOption("GML_SKIP_CORRUPTED_FEATURES", "NO"));
+
+                CPLError(bGoOn ? CE_Warning : CE_Failure, CPLE_AppDefined,
+                         "Geometry of feature " CPL_FRMT_GIB
+                         " %scannot be parsed: %s%s",
+                         nFID, pszGML_FID ? CPLSPrintf("%s ", pszGML_FID) : "",
+                         osLastErrorMsg.c_str(),
+                         bGoOn ? ". Skipping to next feature.":
+                         ". You may set the GML_SKIP_CORRUPTED_FEATURES "
+                         "configuration option to YES to skip to the next "
+                         "feature");
                 delete poGMLFeature;
+                if( bGoOn )
+                    continue;
                 return NULL;
             }
 
-            if( m_poFilterGeom != NULL && !FilterGeometry( poGeom ) )
+            if( m_poFilterGeom != NULL && !FilterGeometry(poGeom) )
             {
                 delete poGMLFeature;
                 delete poGeom;
@@ -369,103 +377,121 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Convert the whole feature into an OGRFeature.                   */
 /* -------------------------------------------------------------------- */
-        int iField;
         int iDstField = 0;
-        OGRFeature *poOGRFeature = new OGRFeature( poFeatureDefn );
+        OGRFeature *poOGRFeature = new OGRFeature(poFeatureDefn);
 
-        poOGRFeature->SetFID( nFID );
+        poOGRFeature->SetFID(nFID);
         if (poDS->ExposeId())
         {
             if (pszGML_FID)
-                poOGRFeature->SetField( iDstField, pszGML_FID );
-            iDstField ++;
+                poOGRFeature->SetField(iDstField, pszGML_FID);
+            iDstField++;
         }
 
-        int nPropertyCount = poFClass->GetPropertyCount();
-        for( iField = 0; iField < nPropertyCount; iField++, iDstField ++ )
+        const int nPropertyCount = poFClass->GetPropertyCount();
+        for( int iField = 0; iField < nPropertyCount; iField++, iDstField++ )
         {
-            const GMLProperty *psGMLProperty = poGMLFeature->GetProperty( iField );
+            const GMLProperty *psGMLProperty =
+                poGMLFeature->GetProperty(iField);
             if( psGMLProperty == NULL || psGMLProperty->nSubProperties == 0 )
                 continue;
 
-            switch( poFClass->GetProperty(iField)->GetType()  )
+            if( EQUAL(psGMLProperty->papszSubProperties[0], OGR_GML_NULL) )
+            {
+                poOGRFeature->SetFieldNull( iDstField );
+                continue;
+            }
+
+            switch( poFClass->GetProperty(iField)->GetType() )
             {
               case GMLPT_Real:
               {
-                  poOGRFeature->SetField( iDstField, CPLAtof(psGMLProperty->papszSubProperties[0]) );
+                  poOGRFeature->SetField(
+                      iDstField, CPLAtof(psGMLProperty->papszSubProperties[0]));
               }
               break;
 
               case GMLPT_IntegerList:
               {
-                  int nCount = psGMLProperty->nSubProperties;
-                  int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount );
+                  const int nCount = psGMLProperty->nSubProperties;
+                  int *panIntList =
+                      static_cast<int *>(CPLMalloc(sizeof(int) * nCount));
 
                   for( int i = 0; i < nCount; i++ )
-                      panIntList[i]
-                          = atoi(psGMLProperty->papszSubProperties[i]);
+                      panIntList[i] =
+                          atoi(psGMLProperty->papszSubProperties[i]);
 
-                  poOGRFeature->SetField( iDstField, nCount, panIntList );
-                  CPLFree( panIntList );
+                  poOGRFeature->SetField(iDstField, nCount, panIntList);
+                  CPLFree(panIntList);
               }
               break;
 
               case GMLPT_Integer64List:
               {
-                  int nCount = psGMLProperty->nSubProperties;
-                  GIntBig *panIntList = (GIntBig *) CPLMalloc(sizeof(GIntBig) * nCount );
+                  const int nCount = psGMLProperty->nSubProperties;
+                  GIntBig *panIntList = static_cast<GIntBig *>(
+                      CPLMalloc(sizeof(GIntBig) * nCount));
 
                   for( int i = 0; i < nCount; i++ )
-                      panIntList[i]
-                          = CPLAtoGIntBig(psGMLProperty->papszSubProperties[i]);
+                      panIntList[i] =
+                          CPLAtoGIntBig(psGMLProperty->papszSubProperties[i]);
 
-                  poOGRFeature->SetField( iDstField, nCount, panIntList );
-                  CPLFree( panIntList );
+                  poOGRFeature->SetField(iDstField, nCount, panIntList);
+                  CPLFree(panIntList);
               }
               break;
 
               case GMLPT_RealList:
               {
-                  int nCount = psGMLProperty->nSubProperties;
-                  double *padfList = (double *)CPLMalloc(sizeof(double)*nCount);
+                  const int nCount = psGMLProperty->nSubProperties;
+                  double *padfList = static_cast<double *>(
+                      CPLMalloc(sizeof(double) * nCount));
 
                   for( int i = 0; i < nCount; i++ )
-                      padfList[i]
-                          = CPLAtof(psGMLProperty->papszSubProperties[i]);
+                      padfList[i] =
+                          CPLAtof(psGMLProperty->papszSubProperties[i]);
 
-                  poOGRFeature->SetField( iDstField, nCount, padfList );
-                  CPLFree( padfList );
+                  poOGRFeature->SetField(iDstField, nCount, padfList);
+                  CPLFree(padfList);
               }
               break;
 
               case GMLPT_StringList:
               case GMLPT_FeaturePropertyList:
               {
-                  poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties );
+                  poOGRFeature->SetField(iDstField,
+                                         psGMLProperty->papszSubProperties);
               }
               break;
 
               case GMLPT_Boolean:
               {
-                  if( strcmp(psGMLProperty->papszSubProperties[0], "true") == 0 ||
+                  if( strcmp(psGMLProperty->papszSubProperties[0],
+                             "true") == 0 ||
                       strcmp(psGMLProperty->papszSubProperties[0], "1") == 0 )
                   {
-                      poOGRFeature->SetField( iDstField, 1);
+                      poOGRFeature->SetField(iDstField, 1);
                   }
-                  else if( strcmp(psGMLProperty->papszSubProperties[0], "false") == 0 ||
-                           strcmp(psGMLProperty->papszSubProperties[0], "0") == 0 )
+                  else if( strcmp(psGMLProperty->papszSubProperties[0],
+                                  "false") == 0 ||
+                           strcmp(psGMLProperty->papszSubProperties[0],
+                                  "0") == 0 )
                   {
-                      poOGRFeature->SetField( iDstField, 0);
+                      poOGRFeature->SetField(iDstField, 0);
                   }
                   else
-                      poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties[0] );
+                  {
+                      poOGRFeature->SetField(
+                          iDstField, psGMLProperty->papszSubProperties[0]);
+                  }
                   break;
               }
 
               case GMLPT_BooleanList:
               {
-                  int nCount = psGMLProperty->nSubProperties;
-                  int *panIntList = (int *) CPLMalloc(sizeof(int) * nCount );
+                  const int nCount = psGMLProperty->nSubProperties;
+                  int *panIntList =
+                      static_cast<int *>(CPLMalloc(sizeof(int) * nCount));
 
                   for( int i = 0; i < nCount; i++ )
                   {
@@ -476,42 +502,45 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
                                  "1") == 0 );
                   }
 
-                  poOGRFeature->SetField( iDstField, nCount, panIntList );
-                  CPLFree( panIntList );
+                  poOGRFeature->SetField(iDstField, nCount, panIntList);
+                  CPLFree(panIntList);
                   break;
               }
 
               default:
-                poOGRFeature->SetField( iDstField, psGMLProperty->papszSubProperties[0] );
-                break;
+                  poOGRFeature->SetField(iDstField,
+                                         psGMLProperty->papszSubProperties[0]);
+                  break;
             }
         }
 
         delete poGMLFeature;
         poGMLFeature = NULL;
 
-        /* Assign the geometry before the attribute filter because */
-        /* the attribute filter may use a special field like OGR_GEOMETRY */
+        // Assign the geometry before the attribute filter because
+        // the attribute filter may use a special field like OGR_GEOMETRY.
         if( papoGeometries != NULL )
         {
-            for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+            for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
             {
-                poOGRFeature->SetGeomFieldDirectly( i, papoGeometries[i] );
+                poOGRFeature->SetGeomFieldDirectly(i, papoGeometries[i]);
             }
             CPLFree(papoGeometries);
             papoGeometries = NULL;
         }
         else
-            poOGRFeature->SetGeometryDirectly( poGeom );
+        {
+            poOGRFeature->SetGeometryDirectly(poGeom);
+        }
 
-        /* Assign SRS */
-        for( int i=0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+        // Assign SRS.
+        for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
         {
             poGeom = poOGRFeature->GetGeomFieldRef(i);
             if( poGeom != NULL )
             {
-                OGRSpatialReference* poSRS
-                    = poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef();
+                OGRSpatialReference *poSRS =
+                    poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef();
                 if (poSRS != NULL)
                     poGeom->assignSpatialReference(poSRS);
             }
@@ -520,17 +549,13 @@ OGRFeature *OGRGMLLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Test against the attribute query.                               */
 /* -------------------------------------------------------------------- */
-        if( m_poAttrQuery != NULL
-            && !m_poAttrQuery->Evaluate( poOGRFeature ) )
+        if( m_poAttrQuery != NULL && !m_poAttrQuery->Evaluate(poOGRFeature) )
         {
             delete poOGRFeature;
             continue;
         }
 
-/* -------------------------------------------------------------------- */
-/*      Wow, we got our desired feature. Return it.                     */
-/* -------------------------------------------------------------------- */
-
+        // Got the desired feature.
         return poOGRFeature;
     }
 
@@ -548,19 +573,18 @@ GIntBig OGRGMLLayer::GetFeatureCount( int bForce )
         return 0;
 
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
-        return OGRLayer::GetFeatureCount( bForce );
-    else
+        return OGRLayer::GetFeatureCount(bForce);
+
+    // If the schema is read from a .xsd file, we haven't read
+    // the feature count, so compute it now.
+    GIntBig nFeatureCount = poFClass->GetFeatureCount();
+    if (nFeatureCount < 0)
     {
-        /* If the schema is read from a .xsd file, we haven't read */
-        /* the feature count, so compute it now */
-        GIntBig nFeatureCount = poFClass->GetFeatureCount();
-        if (nFeatureCount < 0)
-        {
-            nFeatureCount = OGRLayer::GetFeatureCount(bForce);
-            poFClass->SetFeatureCount(nFeatureCount);
-        }
-        return nFeatureCount;
+        nFeatureCount = OGRLayer::GetFeatureCount(bForce);
+        poFClass->SetFeatureCount(nFeatureCount);
     }
+
+    return nFeatureCount;
 }
 
 /************************************************************************/
@@ -570,13 +594,15 @@ GIntBig OGRGMLLayer::GetFeatureCount( int bForce )
 OGRErr OGRGMLLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 
 {
-    double dfXMin, dfXMax, dfYMin, dfYMax;
-
     if( GetGeomType() == wkbNone )
         return OGRERR_FAILURE;
 
+    double dfXMin = 0.0;
+    double dfXMax = 0.0;
+    double dfYMin = 0.0;
+    double dfYMax = 0.0;
     if( poFClass != NULL &&
-        poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ) )
+        poFClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
     {
         psExtent->MinX = dfXMin;
         psExtent->MaxX = dfXMax;
@@ -585,24 +611,24 @@ OGRErr OGRGMLLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 
         return OGRERR_NONE;
     }
-    else
-        return OGRLayer::GetExtent( psExtent, bForce );
+
+    return OGRLayer::GetExtent(psExtent, bForce);
 }
 
 /************************************************************************/
 /*                             GetExtent()                              */
 /************************************************************************/
 
-static void GMLWriteField(OGRGMLDataSource* poDS,
+static void GMLWriteField(OGRGMLDataSource *poDS,
                           VSILFILE *fp,
-                          int bWriteSpaceIndentation,
-                          const char* pszPrefix,
-                          int bRemoveAppPrefix,
-                          OGRFieldDefn* poFieldDefn,
-                          const char* pszVal )
+                          bool bWriteSpaceIndentation,
+                          const char *pszPrefix,
+                          bool bRemoveAppPrefix,
+                          OGRFieldDefn *poFieldDefn,
+                          const char *pszVal )
 
 {
-    const char* pszFieldName = poFieldDefn->GetNameRef();
+    const char *pszFieldName = poFieldDefn->GetNameRef();
 
     while( *pszVal == ' ' )
         pszVal++;
@@ -611,12 +637,9 @@ static void GMLWriteField(OGRGMLDataSource* poDS,
         VSIFPrintfL(fp, "      ");
 
     if( bRemoveAppPrefix )
-        poDS->PrintLine( fp, "<%s>%s</%s>",
-                        pszFieldName,
-                        pszVal,
-                        pszFieldName);
+        poDS->PrintLine(fp, "<%s>%s</%s>", pszFieldName, pszVal, pszFieldName);
     else
-        poDS->PrintLine( fp, "<%s:%s>%s</%s:%s>",
+        poDS->PrintLine(fp, "<%s:%s>%s</%s:%s>",
                         pszPrefix,
                         pszFieldName,
                         pszVal,
@@ -631,17 +654,19 @@ static void GMLWriteField(OGRGMLDataSource* poDS,
 OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
 
 {
-    int bIsGML3Output = poDS->IsGML3Output();
+    const bool bIsGML3Output = poDS->IsGML3Output();
     VSILFILE *fp = poDS->GetOutputFP();
-    int bWriteSpaceIndentation = poDS->WriteSpaceIndentation();
-    const char* pszPrefix = poDS->GetAppPrefix();
-    int bRemoveAppPrefix = poDS->RemoveAppPrefix();
+    const bool bWriteSpaceIndentation = poDS->WriteSpaceIndentation();
+    const char *pszPrefix = poDS->GetAppPrefix();
+    const bool bRemoveAppPrefix = poDS->RemoveAppPrefix();
 
     if( !bWriter )
         return OGRERR_FAILURE;
 
     poFeature->FillUnsetWithDefault(TRUE, NULL);
-    if( !poFeature->Validate( OGR_F_VAL_ALL & ~OGR_F_VAL_GEOM_TYPE & ~OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT, TRUE ) )
+    if( !poFeature->Validate(OGR_F_VAL_ALL & ~OGR_F_VAL_GEOM_TYPE &
+                                 ~OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT,
+                             TRUE) )
         return OGRERR_FAILURE;
 
     if (bWriteSpaceIndentation)
@@ -649,26 +674,35 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
     if (bIsGML3Output)
     {
         if( bRemoveAppPrefix )
-            poDS->PrintLine( fp, "<featureMember>" );
+            poDS->PrintLine(fp, "<featureMember>");
         else
-            poDS->PrintLine( fp, "<%s:featureMember>", pszPrefix );
+            poDS->PrintLine(fp, "<%s:featureMember>", pszPrefix);
     }
     else
-        poDS->PrintLine( fp, "<gml:featureMember>" );
+    {
+        poDS->PrintLine(fp, "<gml:featureMember>");
+    }
 
     if( iNextGMLId == 0 )
     {
         bSameSRS = true;
-        for( int iGeomField = 1; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ )
+        for( int iGeomField = 1;
+             iGeomField < poFeatureDefn->GetGeomFieldCount();
+             iGeomField++ )
         {
             OGRGeomFieldDefn *poFieldDefn0 = poFeatureDefn->GetGeomFieldDefn(0);
-            OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField);
-            OGRSpatialReference* poSRS0 = poFieldDefn0->GetSpatialRef();
-            OGRSpatialReference* poSRS = poFieldDefn->GetSpatialRef();
+            OGRGeomFieldDefn *poFieldDefn =
+                poFeatureDefn->GetGeomFieldDefn(iGeomField);
+            OGRSpatialReference *poSRS0 = poFieldDefn0->GetSpatialRef();
+            OGRSpatialReference *poSRS = poFieldDefn->GetSpatialRef();
             if( poSRS0 != NULL && poSRS == NULL )
+            {
                 bSameSRS = false;
+            }
             else if( poSRS0 == NULL && poSRS != NULL )
+            {
                 bSameSRS = false;
+            }
             else if( poSRS0 != NULL && poSRS != NULL &&
                      poSRS0 != poSRS && !poSRS0->IsSame(poSRS) )
             {
@@ -678,174 +712,259 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
     if( poFeature->GetFID() == OGRNullFID )
-        poFeature->SetFID( iNextGMLId++ );
+        poFeature->SetFID(iNextGMLId++);
 
-    int nGMLIdIndex = -1;
     if (bWriteSpaceIndentation)
         VSIFPrintfL(fp, "    ");
     VSIFPrintfL(fp, "<");
     if( !bRemoveAppPrefix )
         VSIFPrintfL(fp, "%s:", pszPrefix);
+
+    int nGMLIdIndex = -1;
     if (bIsGML3Output)
     {
         nGMLIdIndex = poFeatureDefn->GetFieldIndex("gml_id");
-        if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
-            poDS->PrintLine( fp, "%s gml:id=\"%s\">",
-                             poFeatureDefn->GetName(),
-                             poFeature->GetFieldAsString(nGMLIdIndex) );
+        if (nGMLIdIndex >= 0 && poFeature->IsFieldSetAndNotNull(nGMLIdIndex) )
+            poDS->PrintLine(fp, "%s gml:id=\"%s\">",
+                            poFeatureDefn->GetName(),
+                            poFeature->GetFieldAsString(nGMLIdIndex));
         else
-            poDS->PrintLine( fp, "%s gml:id=\"%s." CPL_FRMT_GIB "\">",
-                             poFeatureDefn->GetName(),
-                             poFeatureDefn->GetName(),
-                             poFeature->GetFID() );
+            poDS->PrintLine(fp, "%s gml:id=\"%s." CPL_FRMT_GIB "\">",
+                            poFeatureDefn->GetName(),
+                            poFeatureDefn->GetName(),
+                            poFeature->GetFID());
     }
     else
     {
         nGMLIdIndex = poFeatureDefn->GetFieldIndex("fid");
         if (bUseOldFIDFormat)
         {
-            poDS->PrintLine( fp, "%s fid=\"F" CPL_FRMT_GIB "\">",
-                             poFeatureDefn->GetName(),
-                             poFeature->GetFID() );
+            poDS->PrintLine(fp, "%s fid=\"F" CPL_FRMT_GIB "\">",
+                            poFeatureDefn->GetName(),
+                            poFeature->GetFID());
         }
-        else if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
+        else if (nGMLIdIndex >= 0 && poFeature->IsFieldSetAndNotNull( nGMLIdIndex ) )
         {
-            poDS->PrintLine( fp, "%s fid=\"%s\">",
-                             poFeatureDefn->GetName(),
-                             poFeature->GetFieldAsString(nGMLIdIndex) );
+            poDS->PrintLine(fp, "%s fid=\"%s\">",
+                            poFeatureDefn->GetName(),
+                            poFeature->GetFieldAsString(nGMLIdIndex));
         }
         else
         {
-            poDS->PrintLine( fp, "%s fid=\"%s." CPL_FRMT_GIB "\">",
-                             poFeatureDefn->GetName(),
-                             poFeatureDefn->GetName(),
-                             poFeature->GetFID() );
+            poDS->PrintLine(fp, "%s fid=\"%s." CPL_FRMT_GIB "\">",
+                            poFeatureDefn->GetName(),
+                            poFeatureDefn->GetName(),
+                            poFeature->GetFID());
         }
     }
 
-
-    for( int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ )
+    for( int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount();
+         iGeomField++ )
     {
-        OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField);
+        OGRGeomFieldDefn *poFieldDefn =
+            poFeatureDefn->GetGeomFieldDefn(iGeomField);
 
         // Write out Geometry - for now it isn't indented properly.
-        /* GML geometries don't like very much the concept of empty geometry */
-        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iGeomField);
+        // GML geometries don't like very much the concept of empty geometry.
+        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
         if( poGeom != NULL && !poGeom->IsEmpty())
         {
-            char    *pszGeometry;
             OGREnvelope3D sGeomBounds;
 
-            int nCoordDimension = poGeom->getCoordinateDimension();
+            const int nCoordDimension = poGeom->getCoordinateDimension();
 
-            poGeom->getEnvelope( &sGeomBounds );
+            poGeom->getEnvelope(&sGeomBounds);
             if( bSameSRS )
-                poDS->GrowExtents( &sGeomBounds, nCoordDimension );
+                poDS->GrowExtents(&sGeomBounds, nCoordDimension);
 
-            if (poGeom->getSpatialReference() == NULL && poFieldDefn->GetSpatialRef() != NULL)
+            if (poGeom->getSpatialReference() == NULL &&
+                poFieldDefn->GetSpatialRef() != NULL)
                 poGeom->assignSpatialReference(poFieldDefn->GetSpatialRef());
 
             if (bIsGML3Output && poDS->WriteFeatureBoundedBy())
             {
-                bool bCoordSwap;
+                bool bCoordSwap = false;
 
-                char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap);
-                char szLowerCorner[75], szUpperCorner[75];
+                char *pszSRSName =
+                    GML_GetSRSName(poGeom->getSpatialReference(),
+                                   poDS->GetSRSNameFormat(), &bCoordSwap);
+                char szLowerCorner[75] = {};
+                char szUpperCorner[75] = {};
                 if (bCoordSwap)
                 {
-                    OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, sGeomBounds.MinZ, nCoordDimension);
-                    OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, sGeomBounds.MaxZ, nCoordDimension);
+                    OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY,
+                                         sGeomBounds.MinX, sGeomBounds.MinZ,
+                                         nCoordDimension);
+                    OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY,
+                                         sGeomBounds.MaxX, sGeomBounds.MaxZ,
+                                         nCoordDimension);
                 }
                 else
                 {
-                    OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, sGeomBounds.MinZ, nCoordDimension);
-                    OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, sGeomBounds.MaxZ, nCoordDimension);
+                    OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX,
+                                         sGeomBounds.MinY, sGeomBounds.MinZ,
+                                         nCoordDimension);
+                    OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX,
+                                         sGeomBounds.MaxY, sGeomBounds.MaxZ,
+                                         nCoordDimension);
                 }
                 if (bWriteSpaceIndentation)
                     VSIFPrintfL(fp, "      ");
-                poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
-                                (nCoordDimension == 3) ? " srsDimension=\"3\"" : "",pszSRSName, szLowerCorner, szUpperCorner);
+                poDS->PrintLine(
+                    fp,
+                    "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s"
+                    "</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner>"
+                    "</gml:Envelope></gml:boundedBy>",
+                    (nCoordDimension == 3) ? " srsDimension=\"3\"" : "",
+                    pszSRSName, szLowerCorner, szUpperCorner);
                 CPLFree(pszSRSName);
             }
 
-            char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL;
-            if (bIsGML3Output && !poDS->IsLongSRSRequired())
-                papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO");
-            const char* pszSRSDimensionLoc = poDS->GetSRSDimensionLoc();
+            char **papszOptions = NULL;
+            if( bIsGML3Output )
+            {
+                papszOptions = CSLAddString(papszOptions, "FORMAT=GML3");
+                if( poDS->GetSRSNameFormat() == SRSNAME_SHORT )
+                    papszOptions =
+                        CSLAddString(papszOptions, "SRSNAME_FORMAT=SHORT");
+                else if( poDS->GetSRSNameFormat() == SRSNAME_OGC_URN )
+                    papszOptions =
+                        CSLAddString(papszOptions, "SRSNAME_FORMAT=OGC_URN");
+                else if( poDS->GetSRSNameFormat() == SRSNAME_OGC_URL )
+                    papszOptions =
+                        CSLAddString(papszOptions, "SRSNAME_FORMAT=OGC_URL");
+            }
+            const char *pszSRSDimensionLoc = poDS->GetSRSDimensionLoc();
             if( pszSRSDimensionLoc != NULL )
-                papszOptions = CSLSetNameValue(papszOptions, "SRSDIMENSION_LOC", pszSRSDimensionLoc);
+                papszOptions = CSLSetNameValue(papszOptions, "SRSDIMENSION_LOC",
+                                               pszSRSDimensionLoc);
             if (poDS->IsGML32Output())
             {
                 if( poFeatureDefn->GetGeomFieldCount() > 1 )
-                    papszOptions = CSLAddString(papszOptions,
+                    papszOptions = CSLAddString(
+                        papszOptions,
                         CPLSPrintf("GMLID=%s.%s." CPL_FRMT_GIB,
                                    poFeatureDefn->GetName(),
                                    poFieldDefn->GetNameRef(),
                                    poFeature->GetFID()));
                 else
-                    papszOptions = CSLAddString(papszOptions,
+                    papszOptions = CSLAddString(
+                        papszOptions,
                         CPLSPrintf("GMLID=%s.geom." CPL_FRMT_GIB,
-                                   poFeatureDefn->GetName(), poFeature->GetFID()));
+                                   poFeatureDefn->GetName(),
+                                   poFeature->GetFID()));
             }
-            if( !bIsGML3Output && OGR_GT_IsNonLinear(poGeom->getGeometryType()) )
+
+            char *pszGeometry = NULL;
+            if( !bIsGML3Output &&
+                OGR_GT_IsNonLinear(poGeom->getGeometryType()) )
             {
-                OGRGeometry* poGeomTmp = OGRGeometryFactory::forceTo(
-                    poGeom->clone(),OGR_GT_GetLinear(poGeom->getGeometryType()));
+                OGRGeometry *poGeomTmp = OGRGeometryFactory::forceTo(
+                    poGeom->clone(),
+                    OGR_GT_GetLinear(poGeom->getGeometryType()));
                 pszGeometry = poGeomTmp->exportToGML(papszOptions);
                 delete poGeomTmp;
             }
             else
-                pszGeometry = poGeom->exportToGML(papszOptions);
+            {
+                if( wkbFlatten(poGeom->getGeometryType()) == wkbTriangle )
+                {
+                    pszGeometry = poGeom->exportToGML(papszOptions);
+
+                    const char *pszGMLID =
+                        poDS->IsGML32Output()
+                            ? CPLSPrintf(
+                                  " gml:id=\"%s\"",
+                                  CSLFetchNameValue(papszOptions, "GMLID"))
+                            : "";
+                    char *pszNewGeom = CPLStrdup(
+                        CPLSPrintf("<gml:TriangulatedSurface%s><gml:patches>%s<"
+                                   "/gml:patches></gml:TriangulatedSurface>",
+                                   pszGMLID, pszGeometry));
+                    CPLFree(pszGeometry);
+                    pszGeometry = pszNewGeom;
+                }
+                else
+                {
+                    pszGeometry = poGeom->exportToGML(papszOptions);
+                }
+            }
             CSLDestroy(papszOptions);
-            if (bWriteSpaceIndentation)
-                VSIFPrintfL(fp, "      ");
-            if( bRemoveAppPrefix )
-                poDS->PrintLine( fp, "<%s>%s</%s>",
-                                 poFieldDefn->GetNameRef(),
-                                 pszGeometry,
-                                 poFieldDefn->GetNameRef() );
+            if( pszGeometry )
+            {
+                if (bWriteSpaceIndentation)
+                    VSIFPrintfL(fp, "      ");
+                if( bRemoveAppPrefix )
+                    poDS->PrintLine( fp, "<%s>%s</%s>",
+                                    poFieldDefn->GetNameRef(),
+                                    pszGeometry,
+                                    poFieldDefn->GetNameRef() );
+                else
+                    poDS->PrintLine( fp, "<%s:%s>%s</%s:%s>",
+                                     pszPrefix, poFieldDefn->GetNameRef(),
+                                     pszGeometry,
+                                     pszPrefix, poFieldDefn->GetNameRef() );
+            }
             else
-                poDS->PrintLine( fp, "<%s:%s>%s</%s:%s>",
-                                 pszPrefix, poFieldDefn->GetNameRef(),
-                                 pszGeometry,
-                                 pszPrefix, poFieldDefn->GetNameRef() );
-            CPLFree( pszGeometry );
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Export of geometry to GML failed");
+            }
+            CPLFree(pszGeometry);
         }
     }
 
     // Write all "set" fields.
     for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
-
+        if( iField == nGMLIdIndex )
+            continue;
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );
 
-        if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex )
+        if( poFeature->IsFieldNull( iField ) )
+        {
+            const char* pszFieldName = poFieldDefn->GetNameRef();
+
+            if (bWriteSpaceIndentation)
+                VSIFPrintfL(fp, "      ");
+
+            if( bRemoveAppPrefix )
+                poDS->PrintLine( fp, "<%s xsi:nil=\"true\"/>",
+                                pszFieldName);
+            else
+                poDS->PrintLine( fp, "<%s:%s xsi:nil=\"true\"/>",
+                                pszPrefix,
+                                pszFieldName);
+        }
+        else if( poFeature->IsFieldSet( iField ) )
         {
             OGRFieldType eType = poFieldDefn->GetType();
             if (eType == OFTStringList )
             {
-                char ** papszIter =  poFeature->GetFieldAsStringList( iField );
+                char **papszIter = poFeature->GetFieldAsStringList(iField);
                 while( papszIter != NULL && *papszIter != NULL )
                 {
-                    char *pszEscaped = OGRGetXML_UTF8_EscapedString( *papszIter );
+                    char *pszEscaped = OGRGetXML_UTF8_EscapedString(*papszIter);
                     GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                                   bRemoveAppPrefix, poFieldDefn, pszEscaped);
-                    CPLFree( pszEscaped );
+                    CPLFree(pszEscaped);
 
-                    papszIter ++;
+                    papszIter++;
                 }
             }
             else if (eType == OFTIntegerList )
             {
                 int nCount = 0;
-                const int* panVals = poFeature->GetFieldAsIntegerList( iField, &nCount );
-                if(  poFieldDefn->GetSubType() == OFSTBoolean )
+                const int *panVals =
+                    poFeature->GetFieldAsIntegerList(iField, &nCount);
+                if( poFieldDefn->GetSubType() == OFSTBoolean )
                 {
                     for(int i = 0; i < nCount; i++)
                     {
-                        /* 0 and 1 are OK, but the canonical representation is false and true */
-                        GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
-                                      bRemoveAppPrefix, poFieldDefn,
+                        // 0 and 1 are OK, but the canonical representation is
+                        // false and true.
+                        GMLWriteField(poDS, fp, bWriteSpaceIndentation,
+                                      pszPrefix, bRemoveAppPrefix, poFieldDefn,
                                       panVals[i] ? "true" : "false");
                     }
                 }
@@ -853,8 +972,8 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
                 {
                     for(int i = 0; i < nCount; i++)
                     {
-                        GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
-                                      bRemoveAppPrefix, poFieldDefn,
+                        GMLWriteField(poDS, fp, bWriteSpaceIndentation,
+                                      pszPrefix, bRemoveAppPrefix, poFieldDefn,
                                       CPLSPrintf("%d", panVals[i]));
                     }
                 }
@@ -862,14 +981,16 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
             else if (eType == OFTInteger64List )
             {
                 int nCount = 0;
-                const GIntBig* panVals = poFeature->GetFieldAsInteger64List( iField, &nCount );
-                if(  poFieldDefn->GetSubType() == OFSTBoolean )
+                const GIntBig *panVals =
+                    poFeature->GetFieldAsInteger64List(iField, &nCount);
+                if( poFieldDefn->GetSubType() == OFSTBoolean )
                 {
                     for(int i = 0; i < nCount; i++)
                     {
-                        /* 0 and 1 are OK, but the canonical representation is false and true */
-                        GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
-                                      bRemoveAppPrefix, poFieldDefn,
+                        // 0 and 1 are OK, but the canonical representation is
+                        // false and true.
+                        GMLWriteField(poDS, fp, bWriteSpaceIndentation,
+                                      pszPrefix, bRemoveAppPrefix, poFieldDefn,
                                       panVals[i] ? "true" : "false");
                     }
                 }
@@ -877,8 +998,8 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
                 {
                     for(int i = 0; i < nCount; i++)
                     {
-                        GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
-                                      bRemoveAppPrefix, poFieldDefn,
+                        GMLWriteField(poDS, fp, bWriteSpaceIndentation,
+                                      pszPrefix, bRemoveAppPrefix, poFieldDefn,
                                       CPLSPrintf(CPL_FRMT_GIB, panVals[i]));
                     }
                 }
@@ -886,11 +1007,13 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
             else if (eType == OFTRealList )
             {
                 int nCount = 0;
-                const double* padfVals = poFeature->GetFieldAsDoubleList( iField, &nCount );
+                const double *padfVals =
+                    poFeature->GetFieldAsDoubleList(iField, &nCount);
                 for(int i = 0; i < nCount; i++)
                 {
-                    char szBuffer[80];
-                    CPLsnprintf( szBuffer, sizeof(szBuffer), "%.15g", padfVals[i]);
+                    char szBuffer[80] = {};
+                    CPLsnprintf(szBuffer, sizeof(szBuffer), "%.15g",
+                                padfVals[i]);
                     GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                                   bRemoveAppPrefix, poFieldDefn, szBuffer);
                 }
@@ -898,20 +1021,22 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
             else if ((eType == OFTInteger || eType == OFTInteger64) &&
                      poFieldDefn->GetSubType() == OFSTBoolean )
             {
-                /* 0 and 1 are OK, but the canonical representation is false and true */
+                // 0 and 1 are OK, but the canonical representation is false and
+                // true.
                 GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                               bRemoveAppPrefix, poFieldDefn,
-                              (poFeature->GetFieldAsInteger(iField)) ? "true" : "false");
+                              (poFeature->GetFieldAsInteger(iField)) ? "true"
+                                                                     : "false");
             }
             else
             {
-                const char *pszRaw = poFeature->GetFieldAsString( iField );
+                const char *pszRaw = poFeature->GetFieldAsString(iField);
 
-                char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
+                char *pszEscaped = OGRGetXML_UTF8_EscapedString(pszRaw);
 
                 GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                               bRemoveAppPrefix, poFieldDefn, pszEscaped);
-                CPLFree( pszEscaped );
+                CPLFree(pszEscaped);
             }
         }
     }
@@ -919,20 +1044,22 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
     if (bWriteSpaceIndentation)
         VSIFPrintfL(fp, "    ");
     if( bRemoveAppPrefix )
-        poDS->PrintLine( fp, "</%s>", poFeatureDefn->GetName() );
+        poDS->PrintLine(fp, "</%s>", poFeatureDefn->GetName());
     else
-        poDS->PrintLine( fp, "</%s:%s>", pszPrefix, poFeatureDefn->GetName() );
+        poDS->PrintLine(fp, "</%s:%s>", pszPrefix, poFeatureDefn->GetName());
     if (bWriteSpaceIndentation)
         VSIFPrintfL(fp, "  ");
     if (bIsGML3Output)
     {
         if( bRemoveAppPrefix )
-            poDS->PrintLine( fp, "</featureMember>" );
+            poDS->PrintLine(fp, "</featureMember>");
         else
-            poDS->PrintLine( fp, "</%s:featureMember>", pszPrefix );
+            poDS->PrintLine(fp, "</%s:featureMember>", pszPrefix);
     }
     else
-        poDS->PrintLine( fp, "</gml:featureMember>" );
+    {
+        poDS->PrintLine(fp, "</gml:featureMember>");
+    }
 
     return OGRERR_NONE;
 }
@@ -944,39 +1071,42 @@ OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )
 int OGRGMLLayer::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,OLCSequentialWrite) )
+    if( EQUAL(pszCap, OLCSequentialWrite) )
         return bWriter;
 
-    else if( EQUAL(pszCap,OLCCreateField) )
+    else if( EQUAL(pszCap, OLCCreateField) )
         return bWriter && iNextGMLId == 0;
 
-    else if( EQUAL(pszCap,OLCCreateGeomField) )
+    else if( EQUAL(pszCap, OLCCreateGeomField) )
         return bWriter && iNextGMLId == 0;
 
-    else if( EQUAL(pszCap,OLCFastGetExtent) )
+    else if( EQUAL(pszCap, OLCFastGetExtent) )
     {
-        double  dfXMin, dfXMax, dfYMin, dfYMax;
-
         if( poFClass == NULL )
             return FALSE;
 
-        return poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax );
+        double dfXMin = 0.0;
+        double dfXMax = 0.0;
+        double dfYMin = 0.0;
+        double dfYMax = 0.0;
+
+        return poFClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax);
     }
 
-    else if( EQUAL(pszCap,OLCFastFeatureCount) )
+    else if( EQUAL(pszCap, OLCFastFeatureCount) )
     {
-        if( poFClass == NULL
-            || m_poFilterGeom != NULL
-            || m_poAttrQuery != NULL )
+        if( poFClass == NULL ||
+            m_poFilterGeom != NULL ||
+            m_poAttrQuery != NULL )
             return FALSE;
 
         return poFClass->GetFeatureCount() != -1;
     }
 
-    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+    else if( EQUAL(pszCap, OLCStringsAsUTF8) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCCurveGeometries) )
+    else if( EQUAL(pszCap, OLCCurveGeometries) )
         return poDS->IsGML3Output();
 
     else
@@ -996,33 +1126,32 @@ OGRErr OGRGMLLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
 /* -------------------------------------------------------------------- */
 /*      Enforce XML naming semantics on element name.                   */
 /* -------------------------------------------------------------------- */
-    OGRFieldDefn oCleanCopy( poField );
-    char *pszName = CPLStrdup( poField->GetNameRef() );
-    CPLCleanXMLElementName( pszName );
+    OGRFieldDefn oCleanCopy(poField);
+    char *pszName = CPLStrdup(poField->GetNameRef());
+    CPLCleanXMLElementName(pszName);
 
-    if( strcmp(pszName,poField->GetNameRef()) != 0 )
+    if( strcmp(pszName, poField->GetNameRef()) != 0 )
     {
         if( !bApproxOK )
         {
-            CPLFree( pszName );
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to create field with name '%s', it would not\n"
-                      "be valid as an XML element name.",
-                      poField->GetNameRef() );
+            CPLFree(pszName);
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unable to create field with name '%s', it would not\n"
+                     "be valid as an XML element name.",
+                     poField->GetNameRef());
             return OGRERR_FAILURE;
         }
 
-        oCleanCopy.SetName( pszName );
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Field name '%s' adjusted to '%s' to be a valid\n"
-                  "XML element name.",
-                  poField->GetNameRef(), pszName );
+        oCleanCopy.SetName(pszName);
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Field name '%s' adjusted to '%s' to be a valid\n"
+                 "XML element name.",
+                 poField->GetNameRef(), pszName);
     }
 
-    CPLFree( pszName );
-
+    CPLFree(pszName);
 
-    poFeatureDefn->AddFieldDefn( &oCleanCopy );
+    poFeatureDefn->AddFieldDefn(&oCleanCopy);
 
     return OGRERR_NONE;
 }
@@ -1040,33 +1169,32 @@ OGRErr OGRGMLLayer::CreateGeomField( OGRGeomFieldDefn *poField, int bApproxOK )
 /* -------------------------------------------------------------------- */
 /*      Enforce XML naming semantics on element name.                   */
 /* -------------------------------------------------------------------- */
-    OGRGeomFieldDefn oCleanCopy( poField );
-    char *pszName = CPLStrdup( poField->GetNameRef() );
-    CPLCleanXMLElementName( pszName );
+    OGRGeomFieldDefn oCleanCopy(poField);
+    char *pszName = CPLStrdup(poField->GetNameRef());
+    CPLCleanXMLElementName(pszName);
 
-    if( strcmp(pszName,poField->GetNameRef()) != 0 )
+    if( strcmp(pszName, poField->GetNameRef()) != 0 )
     {
         if( !bApproxOK )
         {
-            CPLFree( pszName );
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to create field with name '%s', it would not\n"
-                      "be valid as an XML element name.",
-                      poField->GetNameRef() );
+            CPLFree(pszName);
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unable to create field with name '%s', it would not\n"
+                     "be valid as an XML element name.",
+                     poField->GetNameRef());
             return OGRERR_FAILURE;
         }
 
-        oCleanCopy.SetName( pszName );
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Field name '%s' adjusted to '%s' to be a valid\n"
-                  "XML element name.",
-                  poField->GetNameRef(), pszName );
+        oCleanCopy.SetName(pszName);
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Field name '%s' adjusted to '%s' to be a valid\n"
+                 "XML element name.",
+                 poField->GetNameRef(), pszName);
     }
 
-    CPLFree( pszName );
-
+    CPLFree(pszName);
 
-    poFeatureDefn->AddGeomFieldDefn( &oCleanCopy );
+    poFeatureDefn->AddGeomFieldDefn(&oCleanCopy);
 
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/gml/parsexsd.cpp b/ogr/ogrsf_frmts/gml/parsexsd.cpp
index 5420437..92a5475 100644
--- a/ogr/ogrsf_frmts/gml/parsexsd.cpp
+++ b/ogr/ogrsf_frmts/gml/parsexsd.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: parsexsd.cpp 33702 2016-03-11 06:20:16Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLParseXSD()
@@ -28,13 +27,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "parsexsd.h"
-#include "cpl_error.h"
+
+#include <cstdlib>
+#include <cstring>
+#include <set>
+#include <string>
+
 #include "cpl_conv.h"
-#include "ogr_core.h"
-#include "cpl_string.h"
+#include "cpl_error.h"
 #include "cpl_http.h"
-#include <set>
+#include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
+
+CPL_CVSID("$Id: parsexsd.cpp 37446 2017-02-25 14:56:54Z goatbar $");
 
 /************************************************************************/
 /*                              StripNS()                               */
@@ -43,11 +51,10 @@
 /*      stripped off if there is one.  Returns pointer into             */
 /*      original string.                                                */
 /************************************************************************/
-static
-const char *StripNS( const char *pszFullValue )
+static const char *StripNS(const char *pszFullValue)
 
 {
-    const char *pszColon = strstr( pszFullValue, ":" );
+    const char *pszColon = strstr(pszFullValue, ":");
     if( pszColon == NULL )
         return pszFullValue;
     else
@@ -60,95 +67,88 @@ const char *StripNS( const char *pszFullValue )
 
 static
 bool GetSimpleTypeProperties(CPLXMLNode *psTypeNode,
-                            GMLPropertyType *pGMLType,
-                            int *pnWidth,
-                            int *pnPrecision)
+                             GMLPropertyType *pGMLType,
+                             int *pnWidth,
+                             int *pnPrecision)
 {
     const char *pszBase =
-            StripNS( CPLGetXMLValue( psTypeNode,
-                                        "restriction.base", "" ));
+        StripNS(CPLGetXMLValue(psTypeNode, "restriction.base", ""));
 
-    if( EQUAL(pszBase,"decimal") )
+    if( EQUAL(pszBase, "decimal") )
     {
         *pGMLType = GMLPT_Real;
         const char *pszWidth =
-            CPLGetXMLValue( psTypeNode,
-                        "restriction.totalDigits.value", "0" );
+            CPLGetXMLValue(psTypeNode, "restriction.totalDigits.value", "0");
         const char *pszPrecision =
-            CPLGetXMLValue( psTypeNode,
-                        "restriction.fractionDigits.value", "0" );
+            CPLGetXMLValue(psTypeNode, "restriction.fractionDigits.value", "0");
         *pnWidth = atoi(pszWidth);
         *pnPrecision = atoi(pszPrecision);
         return true;
     }
 
-     else if( EQUAL(pszBase,"float") )
+     else if( EQUAL(pszBase, "float") )
     {
         *pGMLType = GMLPT_Float;
         return true;
     }
 
-    else if( EQUAL(pszBase,"double") )
+    else if( EQUAL(pszBase, "double") )
     {
         *pGMLType = GMLPT_Real;
         return true;
     }
 
-    else if( EQUAL(pszBase,"integer") )
+    else if( EQUAL(pszBase, "integer") )
     {
         *pGMLType = GMLPT_Integer;
         const char *pszWidth =
-            CPLGetXMLValue( psTypeNode,
-                        "restriction.totalDigits.value", "0" );
+            CPLGetXMLValue(psTypeNode, "restriction.totalDigits.value", "0");
         *pnWidth = atoi(pszWidth);
         return true;
     }
 
-    else if( EQUAL(pszBase,"long") )
+    else if( EQUAL(pszBase, "long") )
     {
         *pGMLType = GMLPT_Integer64;
         const char *pszWidth =
-            CPLGetXMLValue( psTypeNode,
-                        "restriction.totalDigits.value", "0" );
+            CPLGetXMLValue(psTypeNode, "restriction.totalDigits.value", "0");
         *pnWidth = atoi(pszWidth);
         return true;
     }
 
-    else if( EQUAL(pszBase,"long") )
+    else if( EQUAL(pszBase, "long") )
     {
         *pGMLType = GMLPT_Integer64;
         const char *pszWidth =
-            CPLGetXMLValue( psTypeNode,
-                        "restriction.totalDigits.value", "0" );
+            CPLGetXMLValue(psTypeNode, "restriction.totalDigits.value", "0");
         *pnWidth = atoi(pszWidth);
         return true;
     }
 
-    else if( EQUAL(pszBase,"string") )
+    else if( EQUAL(pszBase, "string") )
     {
         *pGMLType = GMLPT_String;
         const char *pszWidth =
-            CPLGetXMLValue( psTypeNode,
-                        "restriction.maxLength.value", "0" );
+            CPLGetXMLValue(psTypeNode, "restriction.maxLength.value", "0");
         *pnWidth = atoi(pszWidth);
         return true;
     }
 
     /* TODO: Would be nice to have a proper date type */
-    else if( EQUAL(pszBase,"date") ||
-             EQUAL(pszBase,"dateTime") )
+    else if( EQUAL(pszBase, "date") ||
+             EQUAL(pszBase, "dateTime") )
     {
         *pGMLType = GMLPT_String;
         return true;
     }
 
-    else if( EQUAL(pszBase,"boolean") )
+    else if( EQUAL(pszBase, "boolean") )
     {
         *pGMLType = GMLPT_Boolean;
         return true;
     }
 
-    else if( EQUAL(pszBase,"short") )
+    else if( EQUAL(pszBase, "short") )
     {
         *pGMLType = GMLPT_Short;
         return true;
@@ -168,18 +168,17 @@ bool LookForSimpleType(CPLXMLNode *psSchemaNode,
                       int *pnWidth,
                       int *pnPrecision)
 {
-    CPLXMLNode *psThis;
-    for( psThis = psSchemaNode->psChild;
-         psThis != NULL; psThis = psThis->psNext )
+    CPLXMLNode *psThis = psSchemaNode->psChild;
+    for( ; psThis != NULL; psThis = psThis->psNext )
     {
-        if( psThis->eType == CXT_Element
-           && EQUAL(psThis->pszValue,"simpleType")
-           && EQUAL(CPLGetXMLValue(psThis,"name",""),pszStrippedNSType) )
+        if( psThis->eType == CXT_Element &&
+            EQUAL(psThis->pszValue, "simpleType") &&
+            EQUAL(CPLGetXMLValue(psThis, "name", ""), pszStrippedNSType) )
         {
             break;
         }
     }
-    if (psThis == NULL)
+    if( psThis == NULL )
         return false;
 
     return GetSimpleTypeProperties(psThis, pGMLType, pnWidth, pnPrecision);
@@ -192,17 +191,17 @@ bool LookForSimpleType(CPLXMLNode *psSchemaNode,
 /* Returns the child element whose name is pszExpectedValue only if */
 /* there is only one child that is an element. */
 static
-CPLXMLNode* GetSingleChildElement(CPLXMLNode* psNode, const char* pszExpectedValue)
+CPLXMLNode *GetSingleChildElement(CPLXMLNode *psNode,
+                                  const char *pszExpectedValue)
 {
-    CPLXMLNode* psChild = NULL;
-    CPLXMLNode* psIter;
-
     if( psNode == NULL )
         return NULL;
 
-    psIter = psNode->psChild;
+    CPLXMLNode *psIter = psNode->psChild;
     if( psIter == NULL )
         return NULL;
+
+    CPLXMLNode *psChild = NULL;
     while( psIter != NULL )
     {
         if( psIter->eType == CXT_Element )
@@ -223,10 +222,10 @@ CPLXMLNode* GetSingleChildElement(CPLXMLNode* psNode, const char* pszExpectedVal
 /*                      CheckMinMaxOccursCardinality()                  */
 /************************************************************************/
 
-static int CheckMinMaxOccursCardinality(CPLXMLNode* psNode)
+static int CheckMinMaxOccursCardinality(CPLXMLNode *psNode)
 {
-    const char* pszMinOccurs = CPLGetXMLValue( psNode, "minOccurs", NULL );
-    const char* pszMaxOccurs = CPLGetXMLValue( psNode, "maxOccurs", NULL );
+    const char *pszMinOccurs = CPLGetXMLValue(psNode, "minOccurs", NULL);
+    const char *pszMaxOccurs = CPLGetXMLValue(psNode, "maxOccurs", NULL);
     return (pszMinOccurs == NULL || EQUAL(pszMinOccurs, "0") ||
             EQUAL(pszMinOccurs, "1")) &&
            (pszMaxOccurs == NULL || EQUAL(pszMaxOccurs, "1"));
@@ -259,11 +258,11 @@ static GMLPropertyType GetListTypeFromSingleType(GMLPropertyType eType)
 
 typedef struct
 {
-    const char* pszName;
+    const char *pszName;
     OGRwkbGeometryType eType;
 } AssocNameType;
 
-static const AssocNameType apsPropertyTypes [] =
+static const AssocNameType apsPropertyTypes[] =
 {
     {"GeometryPropertyType", wkbUnknown},
     {"PointPropertyType", wkbPoint},
@@ -282,48 +281,47 @@ static const AssocNameType apsPropertyTypes [] =
 };
 
 /* Found in FME .xsd  (e.g. <element ref="gml:curveProperty" minOccurs="0"/>) */
-static const AssocNameType apsRefTypes [] =
+static const AssocNameType apsRefTypes[] =
 {
     {"pointProperty", wkbPoint},
-    {"curveProperty", wkbLineString}, /* should we promote to wkbCompoundCurve ? */
-    {"surfaceProperty", wkbPolygon},  /* should we promote to wkbCurvePolygon ? */
+    {"curveProperty", wkbLineString}, // Should we promote to wkbCompoundCurve?
+    {"surfaceProperty", wkbPolygon},  // Should we promote to wkbCurvePolygon?
     {"multiPointProperty", wkbMultiPoint},
     {"multiCurveProperty", wkbMultiLineString},
-    {"multiSurfaceProperty", wkbMultiPolygon}, /* should we promote to wkbMultiSurface ? */
+    // Should we promote to wkbMultiSurface?
+    {"multiSurfaceProperty", wkbMultiPolygon},
     {NULL, wkbUnknown},
 };
 
 static
-GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
-                                     const char* pszName,
+GMLFeatureClass *GMLParseFeatureType(CPLXMLNode *psSchemaNode,
+                                     const char *pszName,
                                      CPLXMLNode *psThis);
 
 static
-GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
-                                const char* pszName,
+GMLFeatureClass *GMLParseFeatureType(CPLXMLNode *psSchemaNode,
+                                const char *pszName,
                                 const char *pszType)
 {
-    CPLXMLNode *psThis;
-    for( psThis = psSchemaNode->psChild;
-         psThis != NULL; psThis = psThis->psNext )
+    CPLXMLNode *psThis = psSchemaNode->psChild;
+    for( ; psThis != NULL; psThis = psThis->psNext )
     {
-        if( psThis->eType == CXT_Element
-           && EQUAL(psThis->pszValue,"complexType")
-           && EQUAL(CPLGetXMLValue(psThis,"name",""),pszType) )
+        if( psThis->eType == CXT_Element &&
+            EQUAL(psThis->pszValue, "complexType") &&
+            EQUAL(CPLGetXMLValue(psThis, "name", ""), pszType) )
         {
             break;
         }
     }
-    if (psThis == NULL)
+    if( psThis == NULL )
         return NULL;
 
     return GMLParseFeatureType(psSchemaNode, pszName, psThis);
 }
 
-
 static
-GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
-                                     const char* pszName,
+GMLFeatureClass *GMLParseFeatureType(CPLXMLNode *psSchemaNode,
+                                     const char *pszName,
                                      CPLXMLNode *psComplexType)
 {
 
@@ -331,8 +329,7 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 /*      Grab the sequence of extensions greatgrandchild.                */
 /* -------------------------------------------------------------------- */
     CPLXMLNode *psAttrSeq =
-        CPLGetXMLNode( psComplexType,
-                        "complexContent.extension.sequence" );
+        CPLGetXMLNode(psComplexType, "complexContent.extension.sequence");
 
     if( psAttrSeq == NULL )
     {
@@ -343,53 +340,55 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 /*      We are pretty sure this going to be a valid Feature class       */
 /*      now, so create it.                                              */
 /* -------------------------------------------------------------------- */
-    GMLFeatureClass *poClass = new GMLFeatureClass( pszName );
+    GMLFeatureClass *poClass = new GMLFeatureClass(pszName);
 
 /* -------------------------------------------------------------------- */
 /*      Loop over each of the attribute elements being defined for      */
 /*      this feature class.                                             */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psAttrDef;
     int nAttributeIndex = 0;
 
     bool bGotUnrecognizedType = false;
 
-    for( psAttrDef = psAttrSeq->psChild;
-            psAttrDef != NULL;
-            psAttrDef = psAttrDef->psNext )
+    CPLXMLNode *psAttrDef = psAttrSeq->psChild;
+    for( ; psAttrDef != NULL; psAttrDef = psAttrDef->psNext )
     {
-        if( strcmp(psAttrDef->pszValue,"group") == 0 )
+        if( strcmp(psAttrDef->pszValue, "group") == 0 )
         {
             /* Too complex schema for us. Aborts parsing */
             delete poClass;
             return NULL;
         }
 
-        /* Parse stuff like :
+        /* Parse stuff like:
         <xs:choice>
             <xs:element ref="gml:polygonProperty"/>
             <xs:element ref="gml:multiPolygonProperty"/>
         </xs:choice>
         as found in https://downloadagiv.blob.core.windows.net/overstromingsgebieden-en-oeverzones/2014_01/Overstromingsgebieden_en_oeverzones_2014_01_GML.zip
         */
-        if( strcmp(psAttrDef->pszValue,"choice") == 0 )
+        if( strcmp(psAttrDef->pszValue, "choice") == 0 )
         {
-            CPLXMLNode* psChild = psAttrDef->psChild;
+            CPLXMLNode *psChild = psAttrDef->psChild;
             bool bPolygon = false;
             bool bMultiPolygon = false;
             for( ; psChild; psChild = psChild->psNext )
             {
                 if( psChild->eType != CXT_Element )
                     continue;
-                if( strcmp(psChild->pszValue,"element") == 0 )
+                if( strcmp(psChild->pszValue, "element") == 0 )
                 {
-                    const char* pszRef = CPLGetXMLValue( psChild, "ref", NULL );
+                    const char *pszRef = CPLGetXMLValue(psChild, "ref", NULL);
                     if( pszRef != NULL )
                     {
                         if( strcmp(pszRef, "gml:polygonProperty") == 0 )
+                        {
                             bPolygon = true;
+                        }
                         else if( strcmp(pszRef, "gml:multiPolygonProperty") == 0 )
+                        {
                             bMultiPolygon = true;
+                        }
                         else
                         {
                             delete poClass;
@@ -405,33 +404,35 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             }
             if( bPolygon && bMultiPolygon )
             {
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                    "", "", wkbMultiPolygon, nAttributeIndex, true ) );
+                poClass->AddGeometryProperty(new GMLGeometryPropertyDefn(
+                    "", "", wkbMultiPolygon, nAttributeIndex, true));
 
-                nAttributeIndex ++;
+                nAttributeIndex++;
             }
             continue;
         }
 
-        if( !EQUAL(psAttrDef->pszValue,"element") )
+        if( !EQUAL(psAttrDef->pszValue, "element") )
             continue;
 
-        /* MapServer WFS writes element type as an attribute of element */
-        /* not as a simpleType definition */
-        const char* pszType = CPLGetXMLValue( psAttrDef, "type", NULL );
-        const char* pszElementName = CPLGetXMLValue( psAttrDef, "name", NULL );
-        bool bNullable = EQUAL(CPLGetXMLValue( psAttrDef, "minOccurs", "1" ), "0");
-        const char* pszMaxOccurs = CPLGetXMLValue( psAttrDef, "maxOccurs", NULL );
+        // MapServer WFS writes element type as an attribute of element
+        // not as a simpleType definition.
+        const char *pszType = CPLGetXMLValue(psAttrDef, "type", NULL);
+        const char *pszElementName = CPLGetXMLValue(psAttrDef, "name", NULL);
+        bool bNullable =
+            EQUAL(CPLGetXMLValue(psAttrDef, "minOccurs", "1"), "0");
+        const char *pszMaxOccurs = CPLGetXMLValue(psAttrDef, "maxOccurs", NULL);
         if (pszType != NULL)
         {
-            const char* pszStrippedNSType = StripNS(pszType);
-            int nWidth = 0, nPrecision = 0;
+            const char *pszStrippedNSType = StripNS(pszType);
+            int nWidth = 0;
+            int nPrecision = 0;
 
             GMLPropertyType gmlType = GMLPT_Untyped;
             if (EQUAL(pszStrippedNSType, "string") ||
                 EQUAL(pszStrippedNSType, "Character"))
                 gmlType = GMLPT_String;
-            /* TODO: Would be nice to have a proper date type */
+            // TODO: Would be nice to have a proper date type.
             else if (EQUAL(pszStrippedNSType, "date") ||
                      EQUAL(pszStrippedNSType, "dateTime"))
                 gmlType = GMLPT_String;
@@ -456,41 +457,49 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             }
             else if (STARTS_WITH(pszType, "gml:"))
             {
-                const AssocNameType* psIter = apsPropertyTypes;
+                const AssocNameType *psIter = apsPropertyTypes;
                 while(psIter->pszName)
                 {
-                    if (strncmp(pszType + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
+                    if (strncmp(pszType + 4, psIter->pszName,
+                                strlen(psIter->pszName)) == 0)
                     {
                         OGRwkbGeometryType eType = psIter->eType;
 
-                        /* Look if there's a comment restricting to subclasses */
-                        if( psAttrDef->psNext != NULL && psAttrDef->psNext->eType == CXT_Comment )
+                        // Look if there's a comment restricting to subclasses.
+                        if( psAttrDef->psNext != NULL &&
+                            psAttrDef->psNext->eType == CXT_Comment )
                         {
-                            if( strstr(psAttrDef->psNext->pszValue, "restricted to Polygon") )
+                            if( strstr(psAttrDef->psNext->pszValue,
+                                       "restricted to Polygon") )
                                 eType = wkbPolygon;
-                            else if( strstr(psAttrDef->psNext->pszValue, "restricted to LineString") )
+                            else if( strstr(psAttrDef->psNext->pszValue,
+                                            "restricted to LineString") )
                                 eType = wkbLineString;
-                            else if( strstr(psAttrDef->psNext->pszValue, "restricted to MultiPolygon") )
+                            else if( strstr(psAttrDef->psNext->pszValue,
+                                            "restricted to MultiPolygon") )
                                 eType = wkbMultiPolygon;
-                            else if( strstr(psAttrDef->psNext->pszValue, "restricted to MultiLineString") )
+                            else if( strstr(psAttrDef->psNext->pszValue,
+                                            "restricted to MultiLineString") )
                                 eType = wkbMultiLineString;
                         }
 
-                        poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                            pszElementName, pszElementName, eType, nAttributeIndex, bNullable ) );
+                        poClass->AddGeometryProperty(
+                            new GMLGeometryPropertyDefn(
+                                pszElementName, pszElementName, eType,
+                                nAttributeIndex, bNullable));
 
-                        nAttributeIndex ++;
+                        nAttributeIndex++;
 
                         break;
                     }
 
-                    psIter ++;
+                    psIter++;
                 }
 
                 if (psIter->pszName == NULL)
                 {
-                    /* Can be a non geometry gml type */
-                    /* Too complex schema for us. Aborts parsing */
+                    // Can be a non geometry gml type.
+                    // Too complex schema for us. Aborts parsing.
                     delete poClass;
                     return NULL;
                 }
@@ -505,53 +514,59 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
             else if (strcmp(pszType, "G:Point_MultiPointPropertyType") == 0 ||
                      strcmp(pszType, "gmgml:Point_MultiPointPropertyType") == 0)
             {
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                    pszElementName, pszElementName, wkbMultiPoint, nAttributeIndex,
-                    bNullable ) );
+                poClass->AddGeometryProperty(new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbMultiPoint,
+                    nAttributeIndex, bNullable));
 
-                nAttributeIndex ++;
+                nAttributeIndex++;
                 continue;
             }
-            else if (strcmp(pszType, "G:LineString_MultiLineStringPropertyType") == 0 ||
-                     strcmp(pszType, "gmgml:LineString_MultiLineStringPropertyType") == 0)
+            else if (strcmp(pszType,
+                            "G:LineString_MultiLineStringPropertyType") == 0 ||
+                     strcmp(pszType,
+                            "gmgml:LineString_MultiLineStringPropertyType") == 0)
             {
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                    pszElementName, pszElementName, wkbMultiLineString, nAttributeIndex,
-                    bNullable ) );
+                poClass->AddGeometryProperty(new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbMultiLineString,
+                    nAttributeIndex, bNullable));
 
-                nAttributeIndex ++;
+                nAttributeIndex++;
                 continue;
             }
-            else if (strcmp(pszType, "G:Polygon_MultiPolygonPropertyType") == 0 ||
-                     strcmp(pszType, "gmgml:Polygon_MultiPolygonPropertyType") == 0 ||
-                     strcmp(pszType, "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType") == 0)
+            else if (strcmp(pszType,
+                            "G:Polygon_MultiPolygonPropertyType") == 0 ||
+                     strcmp(pszType,
+                            "gmgml:Polygon_MultiPolygonPropertyType") == 0 ||
+                     strcmp(pszType,
+                            "gmgml:Polygon_Surface_MultiSurface_CompositeSurfacePropertyType") == 0)
             {
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                    pszElementName, pszElementName, wkbMultiPolygon, nAttributeIndex,
-                    bNullable ) );
+                poClass->AddGeometryProperty(new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbMultiPolygon,
+                    nAttributeIndex, bNullable));
 
-                nAttributeIndex ++;
+                nAttributeIndex++;
                 continue;
             }
 
-            /* ERDAS Apollo stuff (like in http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=wfs:cntry98) */
+            // ERDAS Apollo stufflike in
+            // http://apollo.erdas.com/erdas-apollo/vector/WORLDWIDE?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=wfs:cntry98)
             else if (strcmp(pszType, "wfs:MixedPolygonPropertyType") == 0)
             {
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                    pszElementName, pszElementName, wkbMultiPolygon, nAttributeIndex,
-                    bNullable) );
+                poClass->AddGeometryProperty(new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbMultiPolygon,
+                    nAttributeIndex, bNullable));
 
-                nAttributeIndex ++;
+                nAttributeIndex++;
                 continue;
             }
 
             else
             {
                 gmlType = GMLPT_Untyped;
-                if ( ! LookForSimpleType(psSchemaNode, pszStrippedNSType,
-                                         &gmlType, &nWidth, &nPrecision) )
+                if ( !LookForSimpleType(psSchemaNode, pszStrippedNSType,
+                                        &gmlType, &nWidth, &nPrecision) )
                 {
-                    /* Too complex schema for us. Aborts parsing */
+                    // Too complex schema for us. Aborts parsing.
                     delete poClass;
                     return NULL;
                 }
@@ -559,77 +574,91 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 
             if (pszElementName == NULL)
                 pszElementName = "unnamed";
-            const char* pszPropertyName = pszElementName;
+            const char *pszPropertyName = pszElementName;
             if( gmlType == GMLPT_FeatureProperty )
             {
                 pszPropertyName = CPLSPrintf("%s_href", pszElementName);
             }
-            GMLPropertyDefn *poProp = new GMLPropertyDefn(
-                pszPropertyName, pszElementName );
+            GMLPropertyDefn *poProp =
+                new GMLPropertyDefn(pszPropertyName, pszElementName);
 
             if( pszMaxOccurs != NULL && strcmp(pszMaxOccurs, "1") != 0 )
                 gmlType = GetListTypeFromSingleType(gmlType);
 
-            poProp->SetType( gmlType );
-            poProp->SetWidth( nWidth );
-            poProp->SetPrecision( nPrecision );
-            poProp->SetNullable( bNullable );
+            poProp->SetType(gmlType);
+            poProp->SetWidth(nWidth);
+            poProp->SetPrecision(nPrecision);
+            poProp->SetNullable(bNullable);
 
             if (poClass->AddProperty( poProp ) < 0)
                 delete poProp;
             else
-                nAttributeIndex ++;
+                nAttributeIndex++;
 
             continue;
         }
 
-        // For now we skip geometries .. fixup later.
-        CPLXMLNode* psSimpleType = CPLGetXMLNode( psAttrDef, "simpleType" );
+        // For now we skip geometries.  Fixup later.
+        CPLXMLNode *psSimpleType = CPLGetXMLNode(psAttrDef, "simpleType");
         if( psSimpleType == NULL )
         {
-            const char* pszRef = CPLGetXMLValue( psAttrDef, "ref", NULL );
+            const char *pszRef = CPLGetXMLValue(psAttrDef, "ref", NULL);
 
-            /* FME .xsd */
+            // FME .xsd
             if (pszRef != NULL && STARTS_WITH(pszRef, "gml:"))
             {
-                const AssocNameType* psIter = apsRefTypes;
+                const AssocNameType *psIter = apsRefTypes;
                 while(psIter->pszName)
                 {
-                    if (strncmp(pszRef + 4, psIter->pszName, strlen(psIter->pszName)) == 0)
+                    if (strncmp(pszRef + 4, psIter->pszName,
+                                strlen(psIter->pszName)) == 0)
                     {
                         if (poClass->GetGeometryPropertyCount() > 0)
                         {
                             OGRwkbGeometryType eNewType = psIter->eType;
-                            OGRwkbGeometryType eOldType = (OGRwkbGeometryType)poClass->GetGeometryProperty(0)->GetType();
-                            if ((eNewType == wkbMultiPoint && eOldType == wkbPoint) ||
-                                (eNewType == wkbMultiLineString && eOldType == wkbLineString) ||
-                                (eNewType == wkbMultiPolygon && eOldType == wkbPolygon))
+                            OGRwkbGeometryType eOldType =
+                                (OGRwkbGeometryType)poClass
+                                    ->GetGeometryProperty(0)
+                                    ->GetType();
+
+                            if ((eNewType == wkbMultiPoint &&
+                                 eOldType == wkbPoint) ||
+                                (eNewType == wkbMultiLineString &&
+                                 eOldType == wkbLineString) ||
+                                (eNewType == wkbMultiPolygon &&
+                                 eOldType == wkbPolygon))
                             {
-                                poClass->GetGeometryProperty(0)->SetType(eNewType);
+                                poClass->GetGeometryProperty(0)->SetType(
+                                    eNewType);
                             }
                             else
                             {
-                                CPLDebug("GML", "Geometry field already found ! Ignoring the following ones");
+                                CPLDebug(
+                                    "GML",
+                                    "Geometry field already found ! "
+                                    "Ignoring the following ones");
                             }
                         }
                         else
                         {
-                            poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                                pszElementName, pszElementName, psIter->eType, nAttributeIndex, true ) );
+                            poClass->AddGeometryProperty(
+                                new GMLGeometryPropertyDefn(
+                                    pszElementName, pszElementName,
+                                    psIter->eType, nAttributeIndex, true));
 
-                            nAttributeIndex ++;
+                            nAttributeIndex++;
                         }
 
                         break;
                     }
 
-                    psIter ++;
+                    psIter++;
                 }
 
                 if (psIter->pszName == NULL)
                 {
-                    /* Can be a non geometry gml type */
-                    /* Too complex schema for us. Aborts parsing */
+                    // Can be a non geometry gml type .
+                    // Too complex schema for us. Aborts parsing.
                     delete poClass;
                     return NULL;
                 }
@@ -649,26 +678,31 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
                 </xs:complexType>
             </xs:element>
             */
-            CPLXMLNode* l_psComplexType = GetSingleChildElement( psAttrDef, "complexType" );
-            CPLXMLNode* psComplexTypeSequence = GetSingleChildElement( l_psComplexType, "sequence" );
-            CPLXMLNode* psComplexTypeSequenceElement = GetSingleChildElement( psComplexTypeSequence, "element" );
+            CPLXMLNode *l_psComplexType =
+                GetSingleChildElement(psAttrDef, "complexType");
+            CPLXMLNode *psComplexTypeSequence =
+                GetSingleChildElement(l_psComplexType, "sequence");
+            CPLXMLNode *psComplexTypeSequenceElement =
+                GetSingleChildElement(psComplexTypeSequence, "element");
 
             if( pszElementName != NULL &&
                 CheckMinMaxOccursCardinality(psAttrDef) &&
                 psComplexTypeSequenceElement != NULL &&
                 CheckMinMaxOccursCardinality(psComplexTypeSequence) &&
-                strcmp(CPLGetXMLValue( psComplexTypeSequenceElement, "ref", "" ), "gml:_Geometry") == 0 )
+                strcmp(CPLGetXMLValue(psComplexTypeSequenceElement, "ref", ""),
+                       "gml:_Geometry") == 0 )
             {
-                poClass->AddGeometryProperty( new GMLGeometryPropertyDefn(
-                    pszElementName, pszElementName, wkbUnknown, nAttributeIndex, bNullable ) );
+                poClass->AddGeometryProperty(new GMLGeometryPropertyDefn(
+                    pszElementName, pszElementName, wkbUnknown, nAttributeIndex,
+                    bNullable));
 
-                nAttributeIndex ++;
+                nAttributeIndex++;
 
                 continue;
             }
             else
             {
-                /* Too complex schema for us. Aborts parsing */
+                // Too complex schema for us. Aborts parsing.
                 delete poClass;
                 return NULL;
             }
@@ -676,39 +710,41 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 
         if (pszElementName == NULL)
             pszElementName = "unnamed";
-        GMLPropertyDefn *poProp = new GMLPropertyDefn(
-            pszElementName, pszElementName );
+        GMLPropertyDefn *poProp =
+            new GMLPropertyDefn(pszElementName, pszElementName);
 
         GMLPropertyType eType = GMLPT_Untyped;
-        int nWidth = 0, nPrecision = 0;
+        int nWidth = 0;
+        int nPrecision = 0;
         GetSimpleTypeProperties(psSimpleType, &eType, &nWidth, &nPrecision);
 
         if( pszMaxOccurs != NULL && strcmp(pszMaxOccurs, "1") != 0 )
             eType = GetListTypeFromSingleType(eType);
 
-        poProp->SetType( eType );
-        poProp->SetWidth( nWidth );
-        poProp->SetPrecision( nPrecision );
-        poProp->SetNullable( bNullable );
+        poProp->SetType(eType);
+        poProp->SetWidth(nWidth);
+        poProp->SetPrecision(nPrecision);
+        poProp->SetNullable(bNullable);
 
-        if (poClass->AddProperty( poProp ) < 0)
+        if (poClass->AddProperty(poProp) < 0)
             delete poProp;
         else
-            nAttributeIndex ++;
+            nAttributeIndex++;
     }
 
-    /* If we have found an unknown types, let's be on the side of caution and */
-    /* create a geometry field */
+    // If we have found an unknown types, let's be on the side of caution and
+    // create a geometry field.
     if( poClass->GetGeometryPropertyCount() == 0 &&
         bGotUnrecognizedType )
     {
-        poClass->AddGeometryProperty( new GMLGeometryPropertyDefn( "", "", wkbUnknown, -1, true ) );
+        poClass->AddGeometryProperty(
+            new GMLGeometryPropertyDefn("", "", wkbUnknown, -1, true));
     }
 
 /* -------------------------------------------------------------------- */
 /*      Class complete, add to reader class list.                       */
 /* -------------------------------------------------------------------- */
-    poClass->SetSchemaLocked( true );
+    poClass->SetSchemaLocked(true);
 
     return poClass;
 }
@@ -717,19 +753,18 @@ GMLFeatureClass* GMLParseFeatureType(CPLXMLNode *psSchemaNode,
 /*                         GMLParseXMLFile()                            */
 /************************************************************************/
 
-static
-CPLXMLNode* GMLParseXMLFile(const char* pszFilename)
+static CPLXMLNode *GMLParseXMLFile(const char *pszFilename)
 {
     if( STARTS_WITH(pszFilename, "http://") ||
         STARTS_WITH(pszFilename, "https://") )
     {
-        CPLXMLNode* psRet = NULL;
-        CPLHTTPResult* psResult = CPLHTTPFetch( pszFilename, NULL );
+        CPLXMLNode *psRet = NULL;
+        CPLHTTPResult *psResult = CPLHTTPFetch(pszFilename, NULL);
         if( psResult != NULL )
         {
             if( psResult->pabyData != NULL )
             {
-                psRet = CPLParseXMLString( (const char*) psResult->pabyData );
+                psRet = CPLParseXMLString((const char *)psResult->pabyData);
             }
             CPLHTTPDestroyResult(psResult);
         }
@@ -745,12 +780,11 @@ CPLXMLNode* GMLParseXMLFile(const char* pszFilename)
 /*                       CPLGetFirstChildNode()                         */
 /************************************************************************/
 
-static
-CPLXMLNode* CPLGetFirstChildNode( CPLXMLNode* psNode )
+static CPLXMLNode *CPLGetFirstChildNode(CPLXMLNode *psNode)
 {
     if( psNode == NULL )
         return NULL;
-    CPLXMLNode* psIter = psNode->psChild;
+    CPLXMLNode *psIter = psNode->psChild;
     while( psIter != NULL )
     {
         if( psIter->eType == CXT_Element )
@@ -764,10 +798,9 @@ CPLXMLNode* CPLGetFirstChildNode( CPLXMLNode* psNode )
 /*                          CPLGetLastNode()                            */
 /************************************************************************/
 
-static
-CPLXMLNode* CPLGetLastNode( CPLXMLNode* psNode )
+static CPLXMLNode *CPLGetLastNode(CPLXMLNode *psNode)
 {
-    CPLXMLNode* psIter = psNode;
+    CPLXMLNode *psIter = psNode;
     while( psIter->psNext != NULL )
         psIter = psIter->psNext;
     return psIter;
@@ -778,7 +811,7 @@ CPLXMLNode* CPLGetLastNode( CPLXMLNode* psNode )
 /************************************************************************/
 
 static
-void CPLXMLSchemaResolveInclude( const char* pszMainSchemaLocation,
+void CPLXMLSchemaResolveInclude( const char *pszMainSchemaLocation,
                                  CPLXMLNode *psSchemaNode )
 {
     std::set<CPLString> osAlreadyIncluded;
@@ -786,18 +819,17 @@ void CPLXMLSchemaResolveInclude( const char* pszMainSchemaLocation,
     bool bTryAgain;
     do
     {
-        CPLXMLNode *psThis;
         CPLXMLNode *psLast = NULL;
         bTryAgain = false;
 
-        for( psThis = psSchemaNode->psChild;
-            psThis != NULL; psThis = psThis->psNext )
+        CPLXMLNode *psThis = psSchemaNode->psChild;
+        for( ; psThis != NULL; psThis = psThis->psNext )
         {
             if( psThis->eType == CXT_Element &&
-                EQUAL(psThis->pszValue,"include") )
+                EQUAL(psThis->pszValue, "include") )
             {
-                const char* pszSchemaLocation =
-                        CPLGetXMLValue(psThis, "schemaLocation", NULL);
+                const char *pszSchemaLocation =
+                    CPLGetXMLValue(psThis, "schemaLocation", NULL);
                 if( pszSchemaLocation != NULL &&
                     osAlreadyIncluded.count( pszSchemaLocation) == 0 )
                 {
@@ -805,44 +837,45 @@ void CPLXMLSchemaResolveInclude( const char* pszMainSchemaLocation,
 
                     if( !STARTS_WITH(pszSchemaLocation, "http://") &&
                         !STARTS_WITH(pszSchemaLocation, "https://") &&
-                        CPLIsFilenameRelative(pszSchemaLocation ) )
+                        CPLIsFilenameRelative(pszSchemaLocation) )
                     {
-                        pszSchemaLocation = CPLFormFilename(
-                            CPLGetPath(pszMainSchemaLocation), pszSchemaLocation, NULL );
+                        pszSchemaLocation =
+                            CPLFormFilename(CPLGetPath(pszMainSchemaLocation),
+                                            pszSchemaLocation, NULL);
                     }
 
                     CPLXMLNode *psIncludedXSDTree =
                                 GMLParseXMLFile( pszSchemaLocation );
                     if( psIncludedXSDTree != NULL )
                     {
-                        CPLStripXMLNamespace( psIncludedXSDTree, NULL, TRUE );
+                        CPLStripXMLNamespace(psIncludedXSDTree, NULL, TRUE);
                         CPLXMLNode *psIncludedSchemaNode =
-                                CPLGetXMLNode( psIncludedXSDTree, "=schema" );
+                            CPLGetXMLNode(psIncludedXSDTree, "=schema");
                         if( psIncludedSchemaNode != NULL )
                         {
-                            /* Substitute de <include> node by its content */
-                            CPLXMLNode* psFirstChildElement =
+                            // Substitute de <include> node by its content.
+                            CPLXMLNode *psFirstChildElement =
                                 CPLGetFirstChildNode(psIncludedSchemaNode);
                             if( psFirstChildElement != NULL )
                             {
-                                CPLXMLNode* psCopy = CPLCloneXMLTree(psFirstChildElement);
+                                CPLXMLNode *psCopy =
+                                    CPLCloneXMLTree(psFirstChildElement);
                                 if( psLast != NULL )
                                     psLast->psNext = psCopy;
                                 else
                                     psSchemaNode->psChild = psCopy;
-                                CPLXMLNode* psNext = psThis->psNext;
+                                CPLXMLNode *psNext = psThis->psNext;
                                 psThis->psNext = NULL;
                                 CPLDestroyXMLNode(psThis);
                                 psThis = CPLGetLastNode(psCopy);
                                 psThis->psNext = psNext;
 
-                                /* In case the included schema also contains */
-                                /* includes */
+                                // In case the included schema also contains
+                                // includes.
                                 bTryAgain = true;
                             }
-
                         }
-                        CPLDestroyXMLNode( psIncludedXSDTree );
+                        CPLDestroyXMLNode(psIncludedXSDTree);
                     }
                 }
             }
@@ -851,11 +884,11 @@ void CPLXMLSchemaResolveInclude( const char* pszMainSchemaLocation,
         }
     } while( bTryAgain );
 
-    const char* pszSchemaOutputName =
+    const char *pszSchemaOutputName =
         CPLGetConfigOption("GML_SCHEMA_OUTPUT_NAME", NULL);
     if( pszSchemaOutputName != NULL )
     {
-        CPLSerializeXMLTreeToFile( psSchemaNode, pszSchemaOutputName );
+        CPLSerializeXMLTreeToFile(psSchemaNode, pszSchemaOutputName);
     }
 }
 
@@ -864,8 +897,8 @@ void CPLXMLSchemaResolveInclude( const char* pszMainSchemaLocation,
 /************************************************************************/
 
 bool GMLParseXSD( const char *pszFile,
-                 std::vector<GMLFeatureClass*> & aosClasses,
-                 bool& bFullyUnderstood)
+                 std::vector<GMLFeatureClass*> &aosClasses,
+                 bool &bFullyUnderstood)
 
 {
     bFullyUnderstood = false;
@@ -876,7 +909,7 @@ bool GMLParseXSD( const char *pszFile,
 /* -------------------------------------------------------------------- */
 /*      Load the raw XML file.                                          */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psXSDTree = GMLParseXMLFile( pszFile );
+    CPLXMLNode *psXSDTree = GMLParseXMLFile(pszFile);
 
     if( psXSDTree == NULL )
         return false;
@@ -889,7 +922,7 @@ bool GMLParseXSD( const char *pszFile,
 /* -------------------------------------------------------------------- */
 /*      Find <schema> root element.                                     */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psSchemaNode = CPLGetXMLNode( psXSDTree, "=schema" );
+    CPLXMLNode *psSchemaNode = CPLGetXMLNode(psXSDTree, "=schema");
     if( psSchemaNode == NULL )
     {
         CPLDestroyXMLNode( psXSDTree );
@@ -899,39 +932,38 @@ bool GMLParseXSD( const char *pszFile,
 /* ==================================================================== */
 /*      Process each include directive.                                 */
 /* ==================================================================== */
-    CPLXMLSchemaResolveInclude( pszFile, psSchemaNode );
+    CPLXMLSchemaResolveInclude(pszFile, psSchemaNode);
 
-    //CPLSerializeXMLTreeToFile(psSchemaNode, "/vsistdout/");
+    // CPLSerializeXMLTreeToFile(psSchemaNode, "/vsistdout/");
 
     bFullyUnderstood = true;
 
 /* ==================================================================== */
 /*      Process each feature class definition.                          */
 /* ==================================================================== */
-    CPLXMLNode *psThis;
-
-    for( psThis = psSchemaNode->psChild;
-         psThis != NULL; psThis = psThis->psNext )
+    CPLXMLNode *psThis = psSchemaNode->psChild;
+    for( ; psThis != NULL; psThis = psThis->psNext )
     {
 /* -------------------------------------------------------------------- */
 /*      Check for <xs:element> node.                                    */
 /* -------------------------------------------------------------------- */
         if( psThis->eType != CXT_Element
-            || !EQUAL(psThis->pszValue,"element") )
+            || !EQUAL(psThis->pszValue, "element") )
             continue;
 
 /* -------------------------------------------------------------------- */
 /*      Check the substitution group.                                   */
 /* -------------------------------------------------------------------- */
         const char *pszSubGroup =
-            StripNS(CPLGetXMLValue(psThis,"substitutionGroup",""));
+            StripNS(CPLGetXMLValue(psThis, "substitutionGroup", ""));
 
         // Old OGR produced elements for the feature collection.
         if( EQUAL(pszSubGroup, "_FeatureCollection") )
             continue;
 
+        // AbstractFeature used by GML 3.2.
         if( !EQUAL(pszSubGroup, "_Feature") &&
-            !EQUAL(pszSubGroup, "AbstractFeature") /* AbstractFeature used by GML 3.2 */ )
+            !EQUAL(pszSubGroup, "AbstractFeature") )
         {
             continue;
         }
@@ -939,9 +971,7 @@ bool GMLParseXSD( const char *pszFile,
 /* -------------------------------------------------------------------- */
 /*      Get name                                                        */
 /* -------------------------------------------------------------------- */
-        const char *pszName;
-
-        pszName = CPLGetXMLValue( psThis, "name", NULL );
+        const char *pszName = CPLGetXMLValue(psThis, "name", NULL);
         if( pszName == NULL )
         {
             continue;
@@ -950,16 +980,14 @@ bool GMLParseXSD( const char *pszFile,
 /* -------------------------------------------------------------------- */
 /*      Get type and verify relationship with name.                     */
 /* -------------------------------------------------------------------- */
-        const char *pszType;
-
-        pszType = CPLGetXMLValue( psThis, "type", NULL );
+        const char *pszType = CPLGetXMLValue(psThis, "type", NULL);
         if (pszType == NULL)
         {
-            CPLXMLNode *psComplexType = CPLGetXMLNode( psThis, "complexType" );
+            CPLXMLNode *psComplexType = CPLGetXMLNode(psThis, "complexType");
             if (psComplexType)
             {
-                GMLFeatureClass* poClass =
-                        GMLParseFeatureType(psSchemaNode, pszName, psComplexType);
+                GMLFeatureClass *poClass =
+                    GMLParseFeatureType(psSchemaNode, pszName, psComplexType);
                 if (poClass)
                     aosClasses.push_back(poClass);
                 else
@@ -967,51 +995,50 @@ bool GMLParseXSD( const char *pszFile,
             }
             continue;
         }
-        if( strstr( pszType, ":" ) != NULL )
-            pszType = strstr( pszType, ":" ) + 1;
+        if( strstr(pszType, ":") != NULL )
+            pszType = strstr(pszType, ":") + 1;
         if( EQUAL(pszType, pszName) )
         {
-            /* A few WFS servers return a type name which is the element name */
-            /* without any _Type or Type suffix */
-            /* e.g. : http://apollo.erdas.com/erdas-apollo/vector/Cherokee?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=iwfs:Air */
+            // A few WFS servers return a type name which is the element name
+            // without any _Type or Type suffix
+            // e.g.:
+            // http://apollo.erdas.com/erdas-apollo/vector/Cherokee?SERVICE=WFS&VERSION=1.0.0&REQUEST=DescribeFeatureType&TYPENAME=iwfs:Air */
+
+            // TODO(schwehr): What was supposed to go here?
         }
 
-        /* <element name="RekisteriyksikonPalstanTietoja" type="ktjkiiwfs:PalstanTietojaType" substitutionGroup="gml:_Feature" /> */
-        else if(  strlen(pszType) > 4 &&
-                  strcmp(pszType + strlen(pszType) - 4, "Type") == 0 &&
-                  strlen(pszName) > strlen(pszType) - 4 &&
-                  strncmp(pszName + strlen(pszName) - (strlen(pszType) - 4),
-                          pszType,
-                          strlen(pszType) - 4) == 0 )        {
+        // <element name="RekisteriyksikonPalstanTietoja" type="ktjkiiwfs:PalstanTietojaType" substitutionGroup="gml:_Feature" />
+        else if( strlen(pszType) > 4 &&
+                 strcmp(pszType + strlen(pszType) - 4, "Type") == 0 &&
+                 strlen(pszName) > strlen(pszType) - 4 &&
+                 strncmp(pszName + strlen(pszName) - (strlen(pszType) - 4),
+                         pszType,
+                         strlen(pszType) - 4) == 0 )        {
         }
 
-        else if( !EQUALN(pszType,pszName,strlen(pszName))
-            || !(EQUAL(pszType+strlen(pszName),"_Type") ||
-                    EQUAL(pszType+strlen(pszName),"Type")) )
+        else if( !EQUALN(pszType, pszName, strlen(pszName))
+            || !(EQUAL(pszType + strlen(pszName), "_Type") ||
+                    EQUAL(pszType + strlen(pszName), "Type")) )
         {
             continue;
         }
 
-        /* CanVec .xsd contains weird types that are not used in the related GML */
+        // CanVec .xsd contains weird types that are not used in the related
+        // GML.
         if (STARTS_WITH(pszName, "XyZz") ||
             STARTS_WITH(pszName, "XyZ1") ||
             STARTS_WITH(pszName, "XyZ2"))
             continue;
 
-        GMLFeatureClass* poClass =
-                GMLParseFeatureType(psSchemaNode, pszName, pszType);
+        GMLFeatureClass *poClass =
+            GMLParseFeatureType(psSchemaNode, pszName, pszType);
         if (poClass)
             aosClasses.push_back(poClass);
         else
             bFullyUnderstood = false;
     }
 
-    CPLDestroyXMLNode( psXSDTree );
+    CPLDestroyXMLNode(psXSDTree);
 
-    if( aosClasses.size() > 0 )
-    {
-        return true;
-    }
-    else
-        return false;
+    return !aosClasses.empty();
 }
diff --git a/ogr/ogrsf_frmts/gml/resolvexlinks.cpp b/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
index 50ee28e..eadb5a0 100644
--- a/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
+++ b/ogr/ogrsf_frmts/gml/resolvexlinks.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: resolvexlinks.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  GML Reader
  * Purpose:  Implementation of GMLReader::ResolveXlinks() method.
@@ -28,17 +27,20 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "gmlreader.h"
-#include "cpl_error.h"
+#include "gmlreaderp.h"
 
-CPL_CVSID("$Id: resolvexlinks.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+#include <cstddef>
+#include <cstring>
 
-#include "gmlreaderp.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
+#include "cpl_error.h"
 #include "cpl_http.h"
+#include "cpl_minixml.h"
+#include "cpl_string.h"
 
-#include <stack>
+CPL_CVSID("$Id: resolvexlinks.cpp 37144 2017-01-14 16:28:19Z goatbar $");
 
 /************************************************************************/
 /*                              GetID()                                 */
@@ -47,17 +49,18 @@ CPL_CVSID("$Id: resolvexlinks.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 /*      found.                                                          */
 /************************************************************************/
 
-static const char* GetID( CPLXMLNode * psNode )
+static const char *GetID( CPLXMLNode *psNode )
 
 {
     if( psNode == NULL )
         return NULL;
 
-    CPLXMLNode *psChild;
-    for( psChild = psNode->psChild; psChild != NULL; psChild = psChild->psNext )
+    for( CPLXMLNode *psChild = psNode->psChild;
+         psChild != NULL;
+         psChild = psChild->psNext )
     {
-        if( psChild->eType == CXT_Attribute
-            && EQUAL(psChild->pszValue, "gml:id") )
+        if( psChild->eType == CXT_Attribute &&
+            EQUAL(psChild->pszValue, "gml:id") )
         {
             return psChild->psChild->pszValue;
         }
@@ -80,7 +83,7 @@ static const char* GetID( CPLXMLNode * psNode )
     if( psNode1 == NULL )
         return FALSE;
 
-    return ( strcmp( GetID(psNode2), GetID(psNode1) ) > 0 );
+    return strcmp( GetID(psNode2), GetID(psNode1) ) > 0;
 }*/
 
 /************************************************************************/
@@ -95,8 +98,9 @@ static std::vector<CPLXMLNode*> BuildIDIndex( CPLXMLNode* psNode,
                                    std::vector<CPLXMLNode*> &apsNode )
 
 {
-    CPLXMLNode *psSibling;
-    for( psSibling = psNode; psSibling != NULL; psSibling = psSibling->psNext )
+    for( CPLXMLNode *psSibling = psNode;
+         psSibling != NULL;
+         psSibling = psSibling->psNext )
     {
         if( GetID( psSibling ) != NULL )
             apsNode.push_back( psSibling );
@@ -112,33 +116,34 @@ static std::vector<CPLXMLNode*> BuildIDIndex( CPLXMLNode* psNode,
 /*      it's siblings.                                                  */
 /************************************************************************/
 
-static CPLXMLNode *FindElementByID( CPLXMLNode * psRoot,
-                                    const char *pszID )
+static CPLXMLNode *FindElementByID( CPLXMLNode *psRoot, const char *pszID )
 
 {
     if( psRoot == NULL )
         return NULL;
 
-    CPLXMLNode *psSibling, *psReturn = NULL;
-
-// check for id attribute
-    for( psSibling = psRoot; psSibling != NULL; psSibling = psSibling->psNext)
+    // Check for id attribute.
+    for( CPLXMLNode *psSibling = psRoot;
+         psSibling != NULL;
+         psSibling = psSibling->psNext )
     {
         if( psSibling->eType == CXT_Element )
         {
             // check that sibling for id value
-            const char* pszIDOfSibling = GetID( psSibling );
+            const char *pszIDOfSibling = GetID(psSibling);
             if( pszIDOfSibling != NULL && EQUAL( pszIDOfSibling, pszID) )
                 return psSibling;
         }
     }
 
-// search the child elements of all the psRoot's siblings
-    for( psSibling = psRoot; psSibling != NULL; psSibling = psSibling->psNext)
+    // Search the child elements of all the psRoot's siblings.
+    for( CPLXMLNode *psSibling = psRoot;
+         psSibling != NULL;
+         psSibling = psSibling->psNext )
     {
         if( psSibling->eType == CXT_Element )
         {
-            psReturn = FindElementByID( psSibling->psChild, pszID );
+            CPLXMLNode *psReturn = FindElementByID(psSibling->psChild, pszID);
             if( psReturn != NULL )
                 return psReturn;
         }
@@ -152,7 +157,7 @@ static CPLXMLNode *FindElementByID( CPLXMLNode * psRoot,
 /*      Remove all the gml:id nodes. Doesn't check psRoot's siblings    */
 /************************************************************************/
 
-static void RemoveIDs( CPLXMLNode * psRoot )
+static void RemoveIDs( CPLXMLNode *psRoot )
 
 {
     if( psRoot == NULL )
@@ -160,16 +165,18 @@ static void RemoveIDs( CPLXMLNode * psRoot )
 
     CPLXMLNode *psChild = psRoot->psChild;
 
-// check for id attribute
-    while( psChild != NULL && !( psChild->eType == CXT_Attribute && EQUAL(psChild->pszValue, "gml:id")))
+    // Check for id attribute.
+    while( psChild != NULL &&
+           !(psChild->eType == CXT_Attribute &&
+             EQUAL(psChild->pszValue, "gml:id")) )
         psChild = psChild->psNext;
-    CPLRemoveXMLChild( psRoot, psChild );
-    CPLDestroyXMLNode( psChild );
+    CPLRemoveXMLChild(psRoot, psChild);
+    CPLDestroyXMLNode(psChild);
 
-// search the child elements of psRoot
-    for( psChild = psRoot->psChild; psChild != NULL; psChild = psChild->psNext)
+    // Search the child elements of psRoot.
+    for( psChild = psRoot->psChild; psChild != NULL; psChild = psChild->psNext )
         if( psChild->eType == CXT_Element )
-            RemoveIDs( psChild );
+            RemoveIDs(psChild);
 }
 
 /************************************************************************/
@@ -179,7 +186,7 @@ static void RemoveIDs( CPLXMLNode * psRoot )
 /*      Returns TRUE if there is a gml:id node in the descendants.      */
 /************************************************************************/
 
-static bool TrimTree( CPLXMLNode * psRoot )
+static bool TrimTree( CPLXMLNode *psRoot )
 
 {
     if( psRoot == NULL )
@@ -187,30 +194,32 @@ static bool TrimTree( CPLXMLNode * psRoot )
 
     CPLXMLNode *psChild = psRoot->psChild;
 
-// check for id attribute
-    while( psChild != NULL && !( psChild->eType == CXT_Attribute && EQUAL(psChild->pszValue, "gml:id")))
+    // Check for id attribute.
+    while( psChild != NULL &&
+           !(psChild->eType == CXT_Attribute &&
+             EQUAL(psChild->pszValue, "gml:id")) )
         psChild = psChild->psNext;
 
     if( psChild != NULL )
         return true;
 
-// search the child elements of psRoot
-    bool bReturn = false, bRemove;
+    // Search the child elements of psRoot.
+    bool bReturn = false;
     for( psChild = psRoot->psChild; psChild != NULL;)
     {
-        CPLXMLNode* psNextChild = psChild->psNext;
+        CPLXMLNode *psNextChild = psChild->psNext;
         if( psChild->eType == CXT_Element )
         {
-            bRemove = TrimTree( psChild );
+            const bool bRemove = TrimTree(psChild);
             if( bRemove )
             {
                 bReturn = bRemove;
             }
             else
             {
-                //remove this child
-                CPLRemoveXMLChild( psRoot, psChild );
-                CPLDestroyXMLNode( psChild );
+                // Remove this child.
+                CPLRemoveXMLChild(psRoot, psChild);
+                CPLDestroyXMLNode(psChild);
             }
         }
 
@@ -229,7 +238,7 @@ static bool TrimTree( CPLXMLNode * psRoot )
 /*  - If it is relative, the path from pszURL is prepended.             */
 /************************************************************************/
 
-static void CorrectURLs( CPLXMLNode * psRoot, const char *pszURL )
+static void CorrectURLs( CPLXMLNode *psRoot, const char *pszURL )
 
 {
     if( psRoot == NULL || pszURL == NULL )
@@ -239,71 +248,77 @@ static void CorrectURLs( CPLXMLNode * psRoot, const char *pszURL )
 
     CPLXMLNode *psChild = psRoot->psChild;
 
-// check for xlink:href attribute
-    while( psChild != NULL && !( ( psChild->eType == CXT_Attribute ) &&
-                                 ( EQUAL(psChild->pszValue, "xlink:href") )) )
+    // Check for xlink:href attribute.
+    while( psChild != NULL &&
+           !((psChild->eType == CXT_Attribute) &&
+             (EQUAL(psChild->pszValue, "xlink:href"))) )
         psChild = psChild->psNext;
 
     if( psChild != NULL &&
-        !( strstr( psChild->psChild->pszValue, pszURL ) == psChild->psChild->pszValue
-        && psChild->psChild->pszValue[strlen(pszURL)] == '#' ) )
+        !(strstr(psChild->psChild->pszValue, pszURL) ==
+              psChild->psChild->pszValue &&
+          psChild->psChild->pszValue[strlen(pszURL)] == '#') )
     {
-    //href has a different url
-        size_t nLen;
-        char *pszNew;
+        // href has a different url.
         if( psChild->psChild->pszValue[0] == '#' )
         {
-        //empty URL: prepend the given URL
-            nLen = CPLStrnlen( pszURL, 1024 ) +
-                   CPLStrnlen( psChild->psChild->pszValue, 1024 ) + 1;
-            pszNew = (char *)CPLMalloc( nLen * sizeof(char));
-            CPLStrlcpy( pszNew, pszURL, nLen );
-            CPLStrlcat( pszNew, psChild->psChild->pszValue, nLen );
-            CPLSetXMLValue( psRoot, "#xlink:href", pszNew );
-            CPLFree( pszNew );
+            // Empty URL: prepend the given URL.
+            const size_t nLen = CPLStrnlen(pszURL, 1024) +
+                                CPLStrnlen(psChild->psChild->pszValue, 1024) +
+                                1;
+            char *pszNew = static_cast<char *>(CPLMalloc(nLen * sizeof(char)));
+            CPLStrlcpy(pszNew, pszURL, nLen);
+            CPLStrlcat(pszNew, psChild->psChild->pszValue, nLen);
+            CPLSetXMLValue(psRoot, "#xlink:href", pszNew);
+            CPLFree(pszNew);
         }
         else
         {
-            size_t nPathLen;
-            for( nPathLen = strlen(pszURL);
-                 nPathLen > 0 && pszURL[nPathLen - 1] != '/'
-                              && pszURL[nPathLen - 1] != '\\';
-                 nPathLen--);
-
-            const char* pszDash = strchr( psChild->psChild->pszValue, '#' );
+            size_t nPathLen = strlen(pszURL);  // Used after for.
+            for( ;
+                 nPathLen > 0 &&
+                 pszURL[nPathLen - 1] != '/' &&
+                 pszURL[nPathLen - 1] != '\\';
+                 nPathLen-- )
+                {}
+
+            const char *pszDash = strchr(psChild->psChild->pszValue, '#');
             if( pszDash != NULL &&
-                strncmp( pszURL, psChild->psChild->pszValue, nPathLen ) != 0 )
+                strncmp(pszURL, psChild->psChild->pszValue, nPathLen) != 0 )
             {
-            //different path
-                int nURLLen = static_cast<int>(pszDash - psChild->psChild->pszValue);
-                char *pszURLWithoutID = (char *)CPLMalloc( (nURLLen+1) * sizeof(char));
-                strncpy( pszURLWithoutID, psChild->psChild->pszValue, nURLLen );
+                // Different path.
+                const int nURLLen =
+                    static_cast<int>(pszDash - psChild->psChild->pszValue);
+                char *pszURLWithoutID = static_cast<char *>(
+                    CPLMalloc((nURLLen + 1) * sizeof(char)));
+                strncpy(pszURLWithoutID, psChild->psChild->pszValue, nURLLen);
                 pszURLWithoutID[nURLLen] = '\0';
 
-                if( CPLIsFilenameRelative( pszURLWithoutID ) &&
-                    strstr( pszURLWithoutID, ":" ) == NULL )
+                if( CPLIsFilenameRelative(pszURLWithoutID) &&
+                    strstr(pszURLWithoutID, ":") == NULL )
                 {
-                    //relative URL: prepend the path of pszURL
-                    nLen = nPathLen +
-                           CPLStrnlen( psChild->psChild->pszValue, 1024 ) + 1;
-                    pszNew = (char *)CPLMalloc( nLen * sizeof(char));
-                    size_t i;
-                    for( i = 0; i < nPathLen; i++ )
+                    // Relative URL: prepend the path of pszURL.
+                    const size_t nLen =
+                        nPathLen +
+                        CPLStrnlen(psChild->psChild->pszValue, 1024) + 1;
+                    char *pszNew =
+                        static_cast<char *>(CPLMalloc(nLen * sizeof(char)));
+                    for( size_t i = 0; i < nPathLen; i++ )
                         pszNew[i] = pszURL[i];
                     pszNew[nPathLen] = '\0';
-                    CPLStrlcat( pszNew, psChild->psChild->pszValue, nLen );
-                    CPLSetXMLValue( psRoot, "#xlink:href", pszNew );
-                    CPLFree( pszNew );
+                    CPLStrlcat(pszNew, psChild->psChild->pszValue, nLen);
+                    CPLSetXMLValue(psRoot, "#xlink:href", pszNew);
+                    CPLFree(pszNew);
                 }
-                CPLFree( pszURLWithoutID );
+                CPLFree(pszURLWithoutID);
             }
         }
     }
 
-// search the child elements of psRoot
+    // Search the child elements of psRoot.
     for( psChild = psRoot->psChild; psChild != NULL; psChild = psChild->psNext)
         if( psChild->eType == CXT_Element )
-            CorrectURLs( psChild, pszURL );
+            CorrectURLs(psChild, pszURL);
 }
 
 /************************************************************************/
@@ -313,72 +328,71 @@ static void CorrectURLs( CPLXMLNode * psRoot, const char *pszURL )
 /*  If not present in ppapsRoot, it updates it and ppapszResourceHREF.  */
 /************************************************************************/
 
-static CPLXMLNode *FindTreeByURL( CPLXMLNode *** ppapsRoot,
-                                  char *** ppapszResourceHREF,
+static CPLXMLNode *FindTreeByURL( CPLXMLNode ***ppapsRoot,
+                                  char ***ppapszResourceHREF,
                                   const char *pszURL )
 
 {
     if( *ppapsRoot == NULL || ppapszResourceHREF == NULL )
         return NULL;
 
-//if found in ppapszResourceHREF
-    int i, nItems;
-    char *pszLocation;
-    if( ( i = CSLFindString( *ppapszResourceHREF, pszURL )) >= 0 )
+    // If found in ppapszResourceHREF.
+    const int i = CSLFindString(*ppapszResourceHREF, pszURL);
+    if( i >= 0 )
     {
-    //return corresponding psRoot
+        // Return corresponding psRoot.
         return (*ppapsRoot)[i];
     }
-    else
+
+    CPLXMLNode *psSrcTree = NULL;
+    char *pszLocation = CPLStrdup(pszURL);
+    // If it is part of filesystem.
+    if( CPLCheckForFile( pszLocation, NULL) )
     {
-        CPLXMLNode *psSrcTree = NULL, *psSibling;
-        pszLocation = CPLStrdup( pszURL );
-        //if it is part of filesystem
-        if( CPLCheckForFile( pszLocation, NULL) )
-        {//filesystem
-            psSrcTree = CPLParseXMLFile( pszURL );
-        }
-        else if( CPLHTTPEnabled() )
-        {//web resource
-            CPLErrorReset();
-            CPLHTTPResult *psResult = CPLHTTPFetch( pszURL, NULL );
-            if( psResult != NULL )
-            {
-                if( psResult->nDataLen > 0 && CPLGetLastErrorNo() == 0)
-                    psSrcTree = CPLParseXMLString( (const char*)psResult->pabyData );
-                CPLHTTPDestroyResult( psResult );
-            }
+        // Filesystem.
+        psSrcTree = CPLParseXMLFile(pszURL);
+    }
+    else if( CPLHTTPEnabled() )
+    {
+        // Web resource.
+        CPLErrorReset();
+        CPLHTTPResult *psResult = CPLHTTPFetch(pszURL, NULL);
+        if( psResult != NULL )
+        {
+            if( psResult->nDataLen > 0 && CPLGetLastErrorNo() == 0)
+                psSrcTree = CPLParseXMLString(reinterpret_cast<const char*>(psResult->pabyData));
+            CPLHTTPDestroyResult( psResult );
         }
+    }
 
-        //report error in case the resource cannot be retrieved.
-        if( psSrcTree == NULL )
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "Could not access %s", pszLocation );
+    // Report error in case the resource cannot be retrieved.
+    if( psSrcTree == NULL )
+        CPLError(CE_Failure, CPLE_NotSupported, "Could not access %s",
+                 pszLocation);
 
-        CPLFree( pszLocation );
+    CPLFree(pszLocation);
 
 /************************************************************************/
 /*      In the external GML resource we will only need elements         */
 /*      identified by a "gml:id". So trim them.                         */
 /************************************************************************/
-        psSibling = psSrcTree;
-        while( psSibling != NULL )
-        {
-            TrimTree( psSibling );
-            psSibling = psSibling->psNext;
-        }
+    CPLXMLNode *psSibling = psSrcTree;
+    while( psSibling != NULL )
+    {
+        TrimTree(psSibling);
+        psSibling = psSibling->psNext;
+    }
 
-    //update to lists
-        nItems = CSLCount(*ppapszResourceHREF);
-        *ppapszResourceHREF = CSLAddString( *ppapszResourceHREF, pszURL );
-        *ppapsRoot = (CPLXMLNode**)CPLRealloc(*ppapsRoot,
-                                            (nItems+2)*sizeof(CPLXMLNode*));
-        (*ppapsRoot)[nItems] = psSrcTree;
-        (*ppapsRoot)[nItems+1] = NULL;
+    // Update to lists.
+    int nItems = CSLCount(*ppapszResourceHREF);
+    *ppapszResourceHREF = CSLAddString(*ppapszResourceHREF, pszURL);
+    *ppapsRoot = static_cast<CPLXMLNode **>(
+        CPLRealloc(*ppapsRoot, (nItems + 2) * sizeof(CPLXMLNode *)));
+    (*ppapsRoot)[nItems] = psSrcTree;
+    (*ppapsRoot)[nItems + 1] = NULL;
 
-    //return the tree
-        return (*ppapsRoot)[nItems];
-    }
+    // Return the tree.
+    return (*ppapsRoot)[nItems];
 }
 
 /************************************************************************/
@@ -391,14 +405,15 @@ static CPLXMLNode *FindTreeByURL( CPLXMLNode *** ppapsRoot,
 /*  If everything goes fine, CE_None is returned.                       */
 /************************************************************************/
 
-static CPLErr Resolve( CPLXMLNode * psNode,
-                CPLXMLNode *** ppapsRoot,
-                char *** ppapszResourceHREF,
-                char ** papszSkip,
-                const int bStrict )
+static CPLErr Resolve( CPLXMLNode *psNode,
+                       CPLXMLNode ***ppapsRoot,
+                       char ***ppapszResourceHREF,
+                       char **papszSkip,
+                       const int bStrict,
+                       int nDepth )
 
 {
-    //for each sibling
+    // For each sibling.
     CPLXMLNode *psSibling = NULL;
     CPLXMLNode *psResource = NULL;
     CPLXMLNode *psTarget = NULL;
@@ -412,107 +427,103 @@ static CPLErr Resolve( CPLXMLNode * psNode,
         CPLXMLNode *psChild = psSibling->psChild;
         while( psChild != NULL &&
                !( psChild->eType == CXT_Attribute &&
-                  EQUAL( psChild->pszValue, "xlink:href" ) ) )
+                  EQUAL(psChild->pszValue, "xlink:href") ) )
             psChild = psChild->psNext;
 
-        //if a child has a "xlink:href" attribute
+        // If a child has a "xlink:href" attribute.
         if( psChild != NULL && psChild->psChild != NULL )
         {
-            if( CSLFindString( papszSkip, psSibling->pszValue ) >= 0 )
-            {//Skipping a specified element
+            if( CSLFindString(papszSkip, psSibling->pszValue) >= 0 )
+            {
+                // Skipping a specified element.
                 eReturn = CE_Warning;
                 continue;
             }
 
-            static int i = 0;
-            if( i-- == 0 )
-            {//a way to track progress
-                i = 256;
-                CPLDebug( "GML",
-                          "Resolving xlinks... (currently %s)",
-                          psChild->psChild->pszValue );
+            const int nDepthCheck = 256;
+            if( nDepth % nDepthCheck == 0 )
+            {
+                // A way to track progress.
+                CPLDebug("GML",
+                         "Resolving xlinks... (currently %s)",
+                         psChild->psChild->pszValue);
             }
 
-            char **papszTokens;
-            papszTokens = CSLTokenizeString2( psChild->psChild->pszValue, "#",
-                                              CSLT_ALLOWEMPTYTOKENS |
-                                              CSLT_STRIPLEADSPACES |
-                                              CSLT_STRIPENDSPACES );
-            if( CSLCount( papszTokens ) != 2 || strlen(papszTokens[1]) <= 0 )
+            char **papszTokens =
+                CSLTokenizeString2(psChild->psChild->pszValue, "#",
+                                   CSLT_ALLOWEMPTYTOKENS |
+                                   CSLT_STRIPLEADSPACES |
+                                   CSLT_STRIPENDSPACES);
+            if( CSLCount(papszTokens) != 2 || strlen(papszTokens[1]) <= 0 )
             {
-                CPLError( bStrict ? CE_Failure : CE_Warning,
-                          CPLE_NotSupported,
-                          "Error parsing the href %s.%s",
-                          psChild->psChild->pszValue,
-                          bStrict ? "" : " Skipping..." );
-                CSLDestroy( papszTokens );
+                CPLError(bStrict ? CE_Failure : CE_Warning,
+                         CPLE_NotSupported,
+                         "Error parsing the href %s.%s",
+                         psChild->psChild->pszValue,
+                         bStrict ? "" : " Skipping...");
+                CSLDestroy(papszTokens);
                 if( bStrict )
                     return CE_Failure;
                 eReturn = CE_Warning;
                 continue;
             }
 
-            //look for the resource with that URL
-            psResource = FindTreeByURL( ppapsRoot,
-                                        ppapszResourceHREF,
-                                        papszTokens[0] );
+            // Look for the resource with that URL.
+            psResource =
+                FindTreeByURL(ppapsRoot, ppapszResourceHREF, papszTokens[0]);
             if( psResource == NULL )
             {
-                CSLDestroy( papszTokens );
+                CSLDestroy(papszTokens);
                 if( bStrict )
                     return CE_Failure;
                 eReturn = CE_Warning;
                 continue;
             }
 
-            //look for the element with the ID
-            psTarget = FindElementByID( psResource, papszTokens[1] );
+            // Look for the element with the ID.
+            psTarget = FindElementByID(psResource, papszTokens[1]);
             if( psTarget != NULL )
             {
-                //remove the xlink:href attribute
-                CPLRemoveXMLChild( psSibling, psChild );
-                CPLDestroyXMLNode( psChild );
-
-                //make a copy of psTarget
-                CPLXMLNode *psCopy = CPLCreateXMLNode( NULL,
-                                                       CXT_Element,
-                                                       psTarget->pszValue );
-                psCopy->psChild = CPLCloneXMLTree( psTarget->psChild );
-                RemoveIDs( psCopy );
-                //correct empty URLs in URL#id pairs
-                if( CPLStrnlen( papszTokens[0], 1 ) > 0 )
+                // Remove the xlink:href attribute.
+                CPLRemoveXMLChild(psSibling, psChild);
+                CPLDestroyXMLNode(psChild);
+
+                // Make a copy of psTarget.
+                CPLXMLNode *psCopy =
+                    CPLCreateXMLNode(NULL, CXT_Element, psTarget->pszValue);
+                psCopy->psChild = CPLCloneXMLTree(psTarget->psChild);
+                RemoveIDs(psCopy);
+                // Correct empty URLs in URL#id pairs.
+                if( CPLStrnlen(papszTokens[0], 1) > 0 )
                 {
-                    CorrectURLs( psCopy, papszTokens[0] );
+                    CorrectURLs(psCopy, papszTokens[0]);
                 }
-                CPLAddXMLChild( psSibling, psCopy );
-                CSLDestroy( papszTokens );
+                CPLAddXMLChild(psSibling, psCopy);
+                CSLDestroy(papszTokens);
             }
             else
             {
-                //element not found
-                CSLDestroy( papszTokens );
-                CPLError( bStrict ? CE_Failure : CE_Warning,
-                          CPLE_ObjectNull,
-                          "Couldn't find the element with id %s.",
-                          psChild->psChild->pszValue );
+                // Element not found.
+                CSLDestroy(papszTokens);
+                CPLError(bStrict ? CE_Failure : CE_Warning,
+                         CPLE_ObjectNull,
+                         "Couldn't find the element with id %s.",
+                         psChild->psChild->pszValue);
                 if( bStrict )
                     return CE_Failure;
                 eReturn = CE_Warning;
             }
         }
 
-        //Recurse with the first child
-        eReturned=Resolve( psSibling->psChild,
-                           ppapsRoot,
-                           ppapszResourceHREF,
-                           papszSkip,
-                           bStrict );
+        // Recurse with the first child.
+        eReturned = Resolve(psSibling->psChild, ppapsRoot, ppapszResourceHREF,
+                            papszSkip, bStrict, nDepth + 1);
 
         if( eReturned == CE_Failure )
             return CE_Failure;
 
         if( eReturned == CE_Warning )
-                eReturn = CE_Warning;
+            eReturn = CE_Warning;
     }
     return eReturn;
 }
@@ -528,28 +539,28 @@ static CPLErr Resolve( CPLXMLNode * psNode,
 /************************************************************************/
 
 bool GMLReader::ResolveXlinks( const char *pszFile,
-                              bool* pbOutIsTempFile,
-                              char **papszSkip,
-                              const bool bStrict)
+                               bool *pbOutIsTempFile,
+                               char **papszSkip,
+                               const bool bStrict )
 
 {
     *pbOutIsTempFile = false;
 
-// Check if the original source file is set.
+    // Check if the original source file is set.
     if( m_pszFilename == NULL )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "GML source file needs to be set first with "
-                  "GMLReader::SetSourceFile()." );
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "GML source file needs to be set first with "
+                 "GMLReader::SetSourceFile().");
         return false;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Load the raw XML file into a XML Node tree.                     */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode **papsSrcTree;
-    papsSrcTree = (CPLXMLNode **)CPLCalloc( 2, sizeof(CPLXMLNode *));
-    papsSrcTree[0] = CPLParseXMLFile( m_pszFilename );
+    CPLXMLNode **papsSrcTree =
+        static_cast<CPLXMLNode **>(CPLCalloc(2, sizeof(CPLXMLNode *)));
+    papsSrcTree[0] = CPLParseXMLFile(m_pszFilename);
 
     if( papsSrcTree[0] == NULL )
     {
@@ -557,19 +568,20 @@ bool GMLReader::ResolveXlinks( const char *pszFile,
         return false;
     }
 
-    //make all the URLs absolute
+    // Make all the URLs absolute.
     CPLXMLNode *psSibling = NULL;
-    for( psSibling = papsSrcTree[0]; psSibling != NULL; psSibling = psSibling->psNext )
-        CorrectURLs( psSibling, m_pszFilename );
+    for( psSibling = papsSrcTree[0]; psSibling != NULL;
+         psSibling = psSibling->psNext )
+        CorrectURLs(psSibling, m_pszFilename);
 
-    //setup resource data structure
+    // Setup resource data structure.
     char **papszResourceHREF = NULL;
-    // "" is the href of the original source file
-    papszResourceHREF = CSLAddString( papszResourceHREF, m_pszFilename );
+    // "" is the href of the original source file.
+    papszResourceHREF = CSLAddString(papszResourceHREF, m_pszFilename);
 
-    //call resolver
-    CPLErr eReturned = CE_None;
-    eReturned = Resolve( papsSrcTree[0], &papsSrcTree, &papszResourceHREF, papszSkip, bStrict );
+    // Call resolver.
+    const CPLErr eReturned = Resolve(papsSrcTree[0], &papsSrcTree,
+                                     &papszResourceHREF, papszSkip, bStrict, 0);
 
     bool bReturn = true;
     if( eReturned != CE_Failure )
@@ -582,38 +594,38 @@ bool GMLReader::ResolveXlinks( const char *pszFile,
         {
             bTryWithTempFile = true;
         }
-        else if( !CPLSerializeXMLTreeToFile( papsSrcTree[0], pszFile ) )
+        else if( !CPLSerializeXMLTreeToFile(papsSrcTree[0], pszFile) )
         {
-            CPLError( CE_Failure, CPLE_FileIO,
-                      "Cannot serialize resolved file %s to %s.",
-                      m_pszFilename, pszFile );
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Cannot serialize resolved file %s to %s.",
+                     m_pszFilename, pszFile);
             bTryWithTempFile = true;
         }
 
         if (bTryWithTempFile)
         {
-            pszTmpName = CPLStrdup( CPLGenerateTempFilename( "ResolvedGML" ) );
-            if( !CPLSerializeXMLTreeToFile( papsSrcTree[0], pszTmpName ) )
+            pszTmpName = CPLStrdup(CPLGenerateTempFilename("ResolvedGML"));
+            if( !CPLSerializeXMLTreeToFile(papsSrcTree[0], pszTmpName) )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Cannot serialize resolved file %s to %s either.",
-                          m_pszFilename, pszTmpName );
-                CPLFree( pszTmpName );
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Cannot serialize resolved file %s to %s either.",
+                         m_pszFilename, pszTmpName);
+                CPLFree(pszTmpName);
                 bReturn = false;
             }
             else
             {
-            //set the source file to the resolved file
-                CPLFree( m_pszFilename );
+                // Set the source file to the resolved file.
+                CPLFree(m_pszFilename);
                 m_pszFilename = pszTmpName;
                 *pbOutIsTempFile = true;
             }
         }
         else
         {
-        //set the source file to the resolved file
-            CPLFree( m_pszFilename );
-            m_pszFilename = CPLStrdup( pszFile );
+            // Set the source file to the resolved file.
+            CPLFree(m_pszFilename);
+            m_pszFilename = CPLStrdup(pszFile);
         }
     }
     else
@@ -621,11 +633,11 @@ bool GMLReader::ResolveXlinks( const char *pszFile,
         bReturn = false;
     }
 
-    int nItems = CSLCount( papszResourceHREF );
-    CSLDestroy( papszResourceHREF );
-    while( nItems > 0 )
-        CPLDestroyXMLNode( papsSrcTree[--nItems] );
-    CPLFree( papsSrcTree );
+    const int nItems = CSLCount(papszResourceHREF);
+    CSLDestroy(papszResourceHREF);
+    for(int i = 0; i < nItems; i++)
+        CPLDestroyXMLNode(papsSrcTree[i]);
+    CPLFree(papsSrcTree);
 
     return bReturn;
 }
diff --git a/ogr/ogrsf_frmts/gml/trstring.cpp b/ogr/ogrsf_frmts/gml/trstring.cpp
deleted file mode 100644
index ddc8d7c..0000000
--- a/ogr/ogrsf_frmts/gml/trstring.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/******************************************************************************
- * $Id: trstring.cpp 33702 2016-03-11 06:20:16Z goatbar $
- *
- * Project:  GML Reader
- * Purpose:  Functions for translating back and forth between XMLCh and char.
- *           We assume that XMLCh is a simple numeric type that we can
- *           correspond 1:1 with char values, but that it likely is larger
- *           than a char.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2002, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifdef HAVE_XERCES
-
-#include "gmlreaderp.h"
-#include "cpl_vsi.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-
-/************************************************************************/
-/*                             tr_isascii()                             */
-/************************************************************************/
-
-static int tr_isascii( const char * pszCString )
-
-{
-    while( *pszCString != '\0' )
-    {
-        if( *((unsigned char *) pszCString) > 127 )
-            return FALSE;
-
-        pszCString++;
-    }
-
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             tr_strcmp()                              */
-/************************************************************************/
-
-int tr_strcmp( const char *pszCString, const XMLCh *panXMLString )
-
-{
-    int i = 0;
-
-/* -------------------------------------------------------------------- */
-/*      Fast (ASCII) comparison case.                                   */
-/* -------------------------------------------------------------------- */
-    if( tr_isascii( pszCString ) )
-    {
-        while( pszCString[i] != 0 && panXMLString[i] != 0
-               && pszCString[i] == panXMLString[i] ) {}
-
-        if( pszCString[i] == 0 && panXMLString[i] == 0 )
-            return 0;
-        else if( pszCString[i] < panXMLString[i] )
-            return -1;
-        else
-            return 1;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Translated UTF8 to XMLCh for comparison.                        */
-/* -------------------------------------------------------------------- */
-    XMLCh *panFirst = (XMLCh *) CPLCalloc(strlen(pszCString)+1,sizeof(XMLCh));
-
-    tr_strcpy( panFirst, pszCString );
-
-    while( panFirst[i] != 0 && panXMLString[i] != 0
-           && panFirst[i] == panXMLString[i] ) {}
-
-    if( panFirst[i] == 0 && panXMLString[i] == 0 )
-    {
-        CPLFree( panFirst );
-        return 0;
-    }
-    else if( panFirst[i] < panXMLString[i] )
-    {
-        CPLFree( panFirst );
-        return -1;
-    }
-    else
-    {
-        CPLFree( panFirst );
-        return 1;
-    }
-}
-
-/************************************************************************/
-/*                 tr_strcpy(const char*,const XMLCh*)                  */
-/************************************************************************/
-
-void tr_strcpy( XMLCh *panXMLString, const char *pszCString )
-
-{
-/* -------------------------------------------------------------------- */
-/*      Simple (ASCII) case.                                            */
-/* -------------------------------------------------------------------- */
-    if( tr_isascii( pszCString ) )
-    {
-        while( *pszCString != 0 )
-            *(panXMLString++) = *(pszCString++);
-        *panXMLString = 0;
-        return;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Otherwise we need to do a full UTC2 to UTF-8 conversion.        */
-/* -------------------------------------------------------------------- */
-    wchar_t *pwszUTF16;
-
-    pwszUTF16 = CPLRecodeToWChar( pszCString, CPL_ENC_UTF8, "WCHAR_T" );
-
-    int i = 0;
-    for( ; pwszUTF16[i] != 0; i++ )
-        panXMLString[i] = pwszUTF16[i];
-
-    panXMLString[i] = 0;
-
-    CPLFree( pwszUTF16 );
-}
-
-/************************************************************************/
-/*                 tr_strcpy(const XMLCh*,const char*)                  */
-/************************************************************************/
-
-void tr_strcpy( char *pszCString, const XMLCh *panXMLString )
-
-{
-    int bSimpleASCII = TRUE;
-    const XMLCh *panXMLStringOriginal = panXMLString;
-    char *pszCStringOriginal = pszCString;
-
-    while( *panXMLString != 0 )
-    {
-        if( *panXMLString > 127 )
-            bSimpleASCII = FALSE;
-
-        *(pszCString++) = (char) *(panXMLString++);
-    }
-    *pszCString = 0;
-
-    if( bSimpleASCII )
-        return;
-
-    panXMLString = panXMLStringOriginal;
-    pszCString = pszCStringOriginal;
-
-/* -------------------------------------------------------------------- */
-/*      The simple translation was wrong, because the source is not     */
-/*      all simple ASCII characters.  Redo using the more expensive     */
-/*      recoding API.                                                   */
-/* -------------------------------------------------------------------- */
-    wchar_t *pwszSource = (wchar_t *) CPLCalloc(sizeof(wchar_t),
-                                                tr_strlen(panXMLStringOriginal)+1 );
-    int i = 0;
-    for( ; panXMLString[i] != 0; i++ )
-        pwszSource[i] = panXMLString[i];
-    pwszSource[i] = 0;
-
-    char *pszResult = CPLRecodeFromWChar( pwszSource,
-                                          "WCHAR_T", CPL_ENC_UTF8 );
-
-    strcpy( pszCString, pszResult );
-
-    CPLFree( pwszSource );
-    CPLFree( pszResult );
-}
-
-/************************************************************************/
-/*                             tr_strlen()                              */
-/************************************************************************/
-
-int tr_strlen( const XMLCh *panXMLString )
-
-{
-    int nLength = 0;
-
-    while( *(panXMLString++) != 0 )
-        nLength++;
-
-    return nLength;
-}
-
-/************************************************************************/
-/*                             tr_strdup()                              */
-/************************************************************************/
-
-char *tr_strdup( const XMLCh *panXMLString )
-
-{
-/* -------------------------------------------------------------------- */
-/*      Compute maximum length.                                         */
-/* -------------------------------------------------------------------- */
-    int i, nMaxLen = 1;
-
-    for( i = 0; panXMLString[i] != 0; i++ )
-    {
-        if( panXMLString[i] < 128 )
-            nMaxLen++;
-        else if( panXMLString[i] < 0x7ff )
-            nMaxLen += 2;
-        else
-            nMaxLen += 4;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Do the translation.                                             */
-/* -------------------------------------------------------------------- */
-    char        *pszResult = (char *) CPLMalloc(nMaxLen);
-    tr_strcpy( pszResult, panXMLString );
-    return pszResult;
-}
-
-#endif // HAVE_XERCES
diff --git a/ogr/ogrsf_frmts/gmlas/GNUmakefile b/ogr/ogrsf_frmts/gmlas/GNUmakefile
new file mode 100644
index 0000000..7154e20
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/GNUmakefile
@@ -0,0 +1,17 @@
+
+include ../../../GDALmake.opt
+
+OBJ =	ogrgmlasdriver.o ogrgmlasdatasource.o ogrgmlaslayer.o \
+        ogrgmlasreader.o ogrgmlasschemaanalyzer.o ogrgmlasfeatureclass.o \
+        ogrgmlasxsdcache.o ogrgmlasconf.o ogrgmlasxpatchmatcher.o \
+        ogrgmlasxlinkresolver.o ogrgmlaswriter.o
+
+CPPFLAGS :=	-I../mem -I../geojson $(JSON_INCLUDE) -I.. -I../.. -I../pgdump -DHAVE_XERCES=1 \
+		 $(XERCES_INCLUDE) $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
+
+$(O_OBJ):	ogr_gmlas.h ogr_gmlas_consts.h
diff --git a/ogr/ogrsf_frmts/gmlas/drv_gmlas.html b/ogr/ogrsf_frmts/gmlas/drv_gmlas.html
new file mode 100644
index 0000000..9e2438e
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/drv_gmlas.html
@@ -0,0 +1,351 @@
+<!DOCTYPE html 
+     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>GMLAS - Geography Markup Language (GML) driven by application schemas</title>
+</head>
+
+<body>
+
+<h1>GMLAS - Geography Markup Language (GML) driven by application schemas</h1>
+
+<p>Available in GDAL >= 2.2</p>
+
+<p>This driver can read and write XML files of arbitrary structure, included those
+containing so called Complex Features, provided that they are accompanied by
+one or several XML schemas that describe the structure of their
+content. While this driver is generic to any XML schema, the main target is to
+be able to read and write documents referencing directly or indirectly to the
+GML namespace.</p>
+
+<p>The driver requires Xerces-C >= 3.1.</p>
+
+<p>The driver can deal with files of arbitrary size with a very modest RAM usage,
+due to its working in streaming mode.</p>
+
+<h2>Opening syntax</h2>
+
+<p>The connection string is GMLAS:/path/to/the.gml. Note the GMLAS: prefix.
+If this prefix it is omitted, then the GML driver is likely to be used.</p>
+
+<p>It is also possible to only used "GMLAS:" as the connection string, but
+in that case the schemas must be explicitly provided with the XSD open option.</p>
+
+
+<h2>Mapping of XML structure to OGR layers and fields</h2>
+
+<p>The driver scans the XML schemas referenced by the XML/GML to build the OGR
+layers and fields. It is strictly required that the schemas, directly or indirectly
+used, are fully valid. The content of the XML/GML file itself is marginally used,
+mostly to determine the SRS of geometry columns.</p>
+
+<p>XML elements declared at the top level of a schema will generally be exposed
+as OGR layers. Their attributes and sub-elements of simple XML types (string,
+integer, real, ...) will be exposed as OGR fields. For sub-elements of complex
+type, different cases can happen. If the cardinality of the sub-element is
+at most one and it is not referenced by other elements, then it is "flattened"
+into its enclosing element. Otherwise it will be exposed as a OGR layer, with
+either a link to its "parent" layer if the sub-element is specific to its
+parent element, or through a junction table if the sub-element is shared by
+several parents.</p>
+
+<p>By default the driver is robust to documents non strictly conforming to
+the schemas. Unexpected content in the document will be silently ignored, as
+well as content required by the schema and absent from the document.</p>
+
+<p>Consult the <a href="drv_gmlas_mapping_examples.html">GMLAS mapping examples</a>
+page for more details.</p>
+
+<h2>Metadata layers</h2>
+
+<p>Three special layers "_ogr_fields_metadata", "_ogr_layers_metadata",
+"_ogr_layer_relationships" and "_ogr_other_metadata" add extra information to
+the basic ones you can get from the OGR data model on OGR layers and fields.</p>
+
+<p>Those layers are exposed if the EXPOSE_METADATA_LAYERS open option is set
+to YES (or if enabled in the configuration). They can also be individually
+retrieved by specifying their name in calls to GetLayerByName(), or on
+as layer names with the ogrinfo and ogr2ogr utility.</p>
+
+<p>Consult the <a href="drv_gmlas_metadata_layers.html">GMLAS metadata layers</a>
+page for more details.</p>
+
+<h2>Configuration file</h2>
+
+<p>A default configuration file <a href="http://svn.osgeo.org/gdal/trunk/gdal/data/gmlasconf.xml">
+gmlasconf.xml</a> file is provided in the data directory of the GDAL installation.
+Its structure and content is documented in <a href="http://svn.osgeo.org/gdal/trunk/gdal/data/gmlasconf.xsd">
+gmlasconf.xsd</a> schema.</p>
+<p>This configuration file enables the user to modify the following settings:
+</p>
+<ul>
+<li>whether remote schemas should be downloaded. Enabled by default.</li>
+<li>whether the local cache of schemas is enabled. Enabled by default.</li>
+<li>the path of the local cache. By default, $HOME/.gdal/gmlas_xsd_cache</li>
+<li>whether validation of the document against the schemas should be enabled.
+Disabled by default.</li>
+<li>whether validation error should cause dataset opening to fail.
+Disabled by default.</li>
+<li>whether the metadata layers should be exposed by default. Disabled by default.</li>
+<li>whether a 'ogr_pkid' field should always be generated. Disabled by default.
+Turning that on can be useful on layers that have a ID attribute whose uniqueness
+is not guaranteed among various documents. Which could cause issues when appending several
+documents into a target database table.</li>
+<li>whether layers and fields that are not used in the XML document should be
+removed. Disable by default.</li>
+<li>whether OGR array data types can be used. Enabled by default.</li>
+<li>whether the XML definition of the GML geometry should be reported as a
+OGR string field. Disabled by default.</li>
+<li>whether only XML elements that derive from gml:_Feature or gml:AbstractFeature
+should be considered in the initial pass of the schema building, when at least
+one element in the schemas derive from them. Enabled by default.</li>
+<li>several rules to configure if and how xlink:href should be resolved.</li>
+<li>a definition of XPaths of elements and attributes that must be ignored, so
+as to lighten the number of OGR layers and fields.</li>
+</ul>
+
+<p>This file can be adapted and modified versions can be provided to the driver
+with the CONFIG_FILE open option. None of the elements of the configuration file
+are required. When they are absent, the default value indicated in the schema
+documentation is used.</p>
+<p>Configuration can also be provided through other open options. Note that
+some open options have identical names to settings present in the configuration
+file. When such open option is provided, then its value will override the one
+of the configuration file (either the default one, or the one provided through
+the CONFIG_FILE open option).</p>
+
+<h2>Geometry support</h2>
+
+<p>XML schemas only indicate the geometry type but do not constraint the
+spatial reference systems (SRS), so it is theoretically possible to have object
+instances of the same class having different SRS for the same geometry field.
+This is not practical to deal with, so when geometry fields are detected, an
+initial scan of the document is done to find the first geometry of each geometry
+field that has an explicit srsName set. This one will be used for the whole
+geometry field. In case other geometries of the same field would have different
+SRS, they will be reprojected.</p>
+
+<p>By default, only the OGR geometry built from the GML geometry is exposed in
+the OGR feature. It is possible to change the IncludeGeometryXML setting of the
+configuration file to true so as to expose a OGR string field with the XML
+definition of the GML geometry.</p>
+
+<h2>Performance issues with large multi-layer GML files.</h2>
+
+<p>Traditionnaly to read a OGR datasource, one iterate over layers with
+GDALDataset::GetLayer(), and for each layer one iterate over features with
+OGRLayer::GetNextFeature(). While this approach still works for the GMLAS driver,
+it may result in very poor performance on big documents or documents using
+complex schemas that are translated in many OGR layers.</p>
+
+<p>It is thus recommended to use GDALDataset::GetNextFeature() to iterate over
+features as soon as they appear in the .gml/.xml file. This may return features
+from non-sequential layers, when the features include nested elements.</p>
+
+<h2>Open options</h2>
+
+<ul>
+<li> <b>XSD</b>=filename(s): to specify an explicit XSD application schema to use
+(or a list of filenames, provided they are comma separated). "http://"
+or "https://" URLs can be used. This option is not required when the XML/GML
+document has a schemaLocation attribute with valid links in its root element.</li>
+<li> <b>CONFIG_FILE</b>=filename or inline XML definition: filename of a
+XML configuration file conforming to the <a href="http://svn.osgeo.org/gdal/trunk/gdal/data/gmlasconf.xsd">
+gmlasconf.xsd</a> schema. It is also possible to provide the XML content directly
+inlined provided that the very first characters are <Configuration.</li>
+<li> <b>EXPOSE_METADATA_LAYERS</b>=YES/NO: whether the metadata layers
+"_ogr_fields_metadata", "_ogr_layers_metadata", "_ogr_layer_relationships" and
+"ogr_other_metadata" should be reported by default. Default is NO.</li>
+<li> <b>VALIDATE</b>=YES/NO: whether the document should be validated against
+the schemas. Validation is done at dataset opening. Default is NO.</li>
+<li> <b>FAIL_IF_VALIDATION_ERROR</b>=YES/NO: Whether a validation error should
+cause dataset opening to fail. (only used if VALIDATE=YES) Default is NO.</li>
+<li> <b>REFRESH_CACHE</b>=YES/NO: Whether remote schemas and documents pointed
+by xlink:href links should be downloaded
+from the server even if already present in the local cache. If the cache is
+enabled, it will be refreshed with the newly downloaded resources. Default is NO.</li>
+<li> <b>SWAP_COORDINATES</b>=AUTO/YES/NO: Whether the order of the x/y or long/lat
+coordinates should be swapped. In AUTO mode, the driver will determine if swapping
+must be done from the srsName. If the srsName is urn:ogc:def:crs:EPSG::XXXX and
+that the order of coordinates in the EPSG database for this SRS is lat,long or
+northing,easting, then the driver will swap them to the GIS friendly order
+(long,lat or easting,northing). For other forms of SRS (such as EPSG:XXXX), GIS
+friendly order is assumed and thus no swapping is done. When SWAP_COORDINATES
+is set to YES, coordinates will be always swapped regarding the order they appear
+in the GML, and when it set to NO, they will be kept in the same order. The default
+is AUTO.</li>
+<li> <b>REMOVE_UNUSED_LAYERS</b>=YES/NO: Whether unused layers should be removed
+from the reported layers. Defaults to NO</li>
+<li> <b>REMOVE_UNUSED_FIELDS</b>=YES/NO: Whether unused fields should be removed
+from the reported layers. Defaults to NO</li>
+<li> <b>HANDLE_MULTIPLE_IMPORTS</b>=YES/NO: Whether multiple imports with the same
+namespace but different schema are allowed. Defaults to NO</li>
+<li> <b>SCHEMA_FULL_CHECKING</b>=YES/NO: Whether to be pedantic with XSD checking
+or to be forgiving e.g. if the invalid part of the schema is not referenced in the
+main document. Defaults to NO</li>
+</ul>
+
+<h2>Creation support</h2>
+
+<p>The GMLAS driver can write XML documents in a schema-driven way by converting
+a source dataset (contrary to most other drivers that have read support that
+implement the CreateLayer() and CreateFeature() interfaces). The typical
+workflow is to use the read side of the GMLAS driver to produce a SQLite/Spatialite/
+PostGIS database, potentially modify the features imported and re-export
+this database as a new XML document.</p>
+
+<p>The driver will identify in the source dataset "top-level" layers, and in
+those layers will find which features are not referenced by other top-level
+layers. As the creation of the output XML is schema-driver, the schemas need to
+be available. There are two possible ways:</p>
+<ul>
+<li>either the result of the processing of the schemas was stored as the
+4 _ogr_* metadata tables in the source dataset by using the
+EXPOSE_METADATA_LAYERS=YES open option when converting the source .xml),</li>
+<li>or the schemas can be specified at creation time with the INPUT_XSD creation
+option.</li>
+</ul>
+
+<p>By default, the driver will "wrap" the features inside a WFS 2.0
+wfs:FeatureCollection / wfs:member element.
+It is also possible to ask the driver to create instead a custom wrapping .xsd
+file that declares the ogr_gmlas:FeatureCollection / ogr_gmlas:featureMember XML
+elements.</p>
+
+<p>Note that while the file resulting from the export should be XML valid, there
+is no strong guarantee that it will validate against the additional constraints
+expressed in XML schema(s). This will depend on the content of the features
+(for example if converting from a GML file that is not conformant to the
+schemas, the output of the driver will generally be not validating)</p>
+
+<p>If the input layers have geometries stored as GML content in a _xml suffixed
+field, then the driver will compare the OGR geometry built from that XML content
+with the OGR geometry stored in the dedicated geometry field of the feature. If
+both match, then the GML content stored in the _xml suffixed field will be used,
+such as to preserve particularities of the initial GML content.
+Otherwise GML will be exported from the OGR geometry.</p>
+
+<p>To increase export performance on very large databases, creating attribute
+indexes on the fields pointed by the 'layer_pkid_name' attribute in
+'_ogr_layers_metadata' might help.</p>
+
+<h3>ogr2ogr behaviour</h3>
+
+<p>When using ogr2ogr / GDALVectorTranslate() to convert to XML/GML from a
+source database, there are restrictions to the options that can be used.
+Only the following options of ogr2ogr are supported:</p>
+
+<ul>
+<li>dataset creation options (see below)</li>
+<li>layer names</li>
+<li>spatial filter through -spat option.</li>
+<li>attribute filter through -where option</li>
+</ul>
+
+<p>The effect of spatial and attribute filtering will only apply
+on top-levels layers. Sub-features selected through joins will not be affected
+by those filters.</p>
+
+<h3>Dataset creation options</h3>
+
+<p>The supported dataset creation options are:</p>
+<ul>
+<li> <b>INPUT_XSD</b>=filename(s): to specify an explicit XSD application schema to use
+(or a list of filenames, provided they are comma separated). "http://"
+or "https://" URLs can be used. This option is not required when the source
+dataset has a _ogr_other_metadata with schemas and locations filled.</li>
+
+<li> <b>CONFIG_FILE</b>=filename or inline XML definition: filename of a
+XML configuration file conforming to the <a href="http://svn.osgeo.org/gdal/trunk/gdal/data/gmlasconf.xsd">
+gmlasconf.xsd</a> schema. It is also possible to provide the XML content directly
+inlined provided that the very first characters are <Configuration>.</li>
+
+<li> <b>LAYERS</b>=layers. Comma separated list of layers to export as top-level
+features. The special value "{SPATIAL_LAYERS}" can also be used to specify
+all layers that have geometries. When LAYERS is not specified, the driver will
+identify in the source dataset "top-level" layers, and in those layers will find
+which features are not referenced by other top-level layers.</li>
+
+<li> <b>SRSNAME_FORMAT</b>=SHORT/OGC_URN/OGC_URL (Only valid for GML 3 output)
+Defaults to OGC_URL.
+If SHORT, then srsName will be in the form AUTHORITY_NAME:AUTHORITY_CODE
+If OGC_URN, then srsName will be in the form urn:ogc:def:crs:AUTHORITY_NAME::AUTHORITY_CODE
+If OGC_URL, then srsName will be in the form http://www.opengis.net/def/crs/AUTHORITY_NAME/0/AUTHORITY_CODE
+For OGC_URN and OGC_URL, in the case the SRS is a SRS without explicit
+AXIS order,  but that the same SRS authority code imported with
+ImportFromEPSGA() should be treated as lat/long or northing/easting,
+then the function will take care of coordinate order swapping.</li>
+
+<li> <b>INDENT_SIZE</b>=[0-8]. Number of spaces for each indentation level.
+Default is 2.</li>
+
+<li> <b>COMMENT</b>=string. Comment to add at top of generated XML file as a
+XML comment.</li>
+
+<li> <b>LINEFORMAT</b>=CRLF/LF. End-of-line sequence to use. Defaults to
+CRLF on Windows and LF on other platforms.</li>
+
+<li> <b>WRAPPING</b>=WFS2_FEATURECOLLECTION/GMLAS_FEATURECOLLECTION. Whether to
+wrap features in a wfs:FeatureCollection or in a ogr_gmlas:FeatureCollection.
+Defaults to WFS2_FEATURECOLLECTION.</li>
+
+<li> <b>TIMESTAMP</b>=XML date time. User-specified XML dateTime value for
+timestamp to use in wfs:FeatureCollection attribute. If not specified, current
+date time is used. Only valid for WRAPPING=WFS2_FEATURECOLLECTION.</li>
+
+<li> <b>WFS20_SCHEMALOCATION</b>=Path or URL to wfs.xsd. Only valid for
+WRAPPING=WFS2_FEATURECOLLECTION. Default is "http://schemas.opengis.net/wfs/2.0/wfs.xsd"</li>
+
+<li> <b>GENERATE_XSD</b>=YES/NO. Whether to generate a .xsd file that has
+the structure of the wrapping ogr_gmlas:FeatureCollection / ogr_gmlas:featureMember
+elements. Only valid for WRAPPING=GMLAS_FEATURECOLLECTION. Default to YES.</li>
+
+<li> <b>OUTPUT_XSD_FILENAME</b>=string. Wrapping .xsd filename. If not specified,
+same basename as output file with .xsd extension. Note that it is possible
+to use this option even if GENERATE_XSD=NO, so that the wrapping .xsd appear
+in the schemaLocation attribute of the .xml file. Only valid for
+WRAPPING=GMLAS_FEATURECOLLECTION</li>
+
+</ul>
+
+<h2>Examples</h2>
+
+<p>
+Listing content of a data file:
+</p>
+<pre>
+ogrinfo -ro GMLAS:my.gml
+</pre>
+
+<p>
+Converting to PostGIS:
+</p>
+<pre>
+ogr2ogr -f PostgreSQL PG:'host=myserver dbname=warmerda' GMLAS:my.gml -nlt CONVERT_TO_LINEAR
+</pre>
+
+<p>
+Converting to Spatialite and back to GML
+</p>
+<pre>
+ogr2ogr -f SQLite tmp.sqlite GMLAS:in.gml -dsco SPATILIATE=YES -nlt CONVERT_TO_LINEAR -oo EXPOSE_METADATA_LAYERS=YES
+ogr2ogr -f GMLAS out.gml tmp.sqlite
+</pre>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="drv_gml.html">GML</a>: general purpose driver not requiring the presence of schemas,
+but with limited support for complex features<br/></li>
+<li> <a href="drv_nas.html">NAS/ALKIS</a>: specialized GML driver for cadastral data in Germany</li>
+</ul>
+
+<h2>Credits</h2>
+
+<p>Initial implementation has been funded by the European Union's Earth observation programme
+Copernicus, as part of the tasks delegated to the European Environment Agency.</p>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/gmlas/drv_gmlas_mapping_examples.html b/ogr/ogrsf_frmts/gmlas/drv_gmlas_mapping_examples.html
new file mode 100644
index 0000000..c5403a8
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/drv_gmlas_mapping_examples.html
@@ -0,0 +1,325 @@
+<!DOCTYPE html 
+     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>GMLAS - Mapping examples</title>
+
+<style type="text/css">
+table, th, td {
+    border: 1px solid black;
+    border-collapse: collapse;
+}
+th, td {
+    padding: 5px;
+}
+</style>
+
+</head>
+
+<body>
+
+<h1>GMLAS - Mapping examples</h1>
+
+<p>This page gives a few examples of how XML constructs are mapped to OGR layers
+and fields by the <a href="drv_gmlas.html">GMLAS</a> driver.</p>
+
+<table>
+
+<tr><th>Schema</th><th>Document</th><th>OGR layers</th><th>Comments</th></tr>
+<tr><td>
+<pre>
+<schema xmlns="http://www.w3.org/2001/XMLSchema">
+<element name="MyFeature">
+  <complexType>
+    <sequence>
+        <element name="name" type="string"/>
+    </sequence>
+    <attribute name="id" type="ID" use="required"/>
+    <attribute name="attr" type="string"/>
+  </complexType>
+</element>
+</schema>
+</pre>
+</td>
+<td>
+<pre>
+<MyFeature id="my_id" attr="attr_value">
+    <name>my_name</name>
+</MyFeature>
+</pre>
+</td>
+<td>
+<pre>
+Layer name: MyFeature
+Geometry: None
+id: String (0.0) NOT NULL
+attr: String (0.0)
+name: String (0.0) NOT NULL
+OGRFeature(MyFeature):1
+  id (String) = my_id
+  attr (String) = attr_value
+  name (String) = my_name
+</pre>
+</td>
+<td>Element with attributes and sub-elements of simple type and maximum cardinality
+of 1.</td>
+</tr>
+
+<tr><td>
+<pre>
+<schema xmlns="http://www.w3.org/2001/XMLSchema">
+<element name="MyFeature">
+  <complexType>
+    <sequence>
+        <element name="str_array" type="string"
+                 maxOccurs="2"/>
+        <element name="dt_array" type="dateTime"
+                 maxOccurs="unbounded"/>
+    </sequence>
+    <attribute name="id" type="ID" use="required"/>
+  </complexType>
+</element>
+</schema>
+</pre>
+</td>
+<td>
+<pre>
+<MyFeature id="my_id">
+    <str_array>first string</str_array>
+    <str_array>second string</str_array>
+    <dt_array>2016-09-24T15:31:00Z</dt_array>
+    <dt_array>2016-09-24T15:32:00Z</dt_array>
+</MyFeature>
+</pre>
+</td>
+<td>
+<pre>
+Layer name: MyFeature
+Geometry: None
+id: String (0.0) NOT NULL
+str_array: StringList (0.0) NOT NULL
+OGRFeature(MyFeature):1
+  id (String) = my_id
+  str_array (StringList) = 
+    (2:first string,second string)
+
+Layer name: MyFeature_dt_array
+Geometry: None
+ogr_pkid: String (0.0) NOT NULL
+parent_id: String (0.0) NOT NULL
+value: DateTime (0.0)
+OGRFeature(MyFeature_dt_array):1
+  ogr_pkid (String) = my_id_dt_array_1
+  parent_id (String) = my_id
+  value (DateTime) = 2016/09/24 15:31:00+00
+
+OGRFeature(MyFeature_dt_array):2
+  ogr_pkid (String) = my_id_dt_array_2
+  parent_id (String) = my_id
+  value (DateTime) = 2016/09/24 15:32:00+00
+</pre>
+</td>
+<td>Case of array and child layer</td>
+</tr>
+
+<tr>
+<td>
+<pre>
+<schema xmlns="http://www.w3.org/2001/XMLSchema">
+<element name="MyFeature">
+  <complexType>
+    <sequence>
+      <element name="identifier">
+        <complexType>
+          <sequence>
+            <element name="name">
+              <complexType>
+                <simpleContent>
+                  <extension base="string">
+                    <attribute name="lang"
+                               type="string"/>
+                  </extension>
+                </simpleContent>
+              </complexType>
+            </element>
+            <element name="namespace" type="string"
+                     minOccurs="0"/>
+          </sequence>
+        </complexType>
+      </element>
+    </sequence>
+    <attribute name="id" type="ID" use="required"/>
+  </complexType>
+</element>
+</schema>
+</pre>
+</td>
+<td>
+<pre>
+<MyFeature id="my_id">
+    <identifier>
+        <name lang="en">my_name</name>
+        <namespace>baz</namespace>
+    </identifier>
+</MyFeature>
+</pre>
+</td>
+<td>
+<pre>
+Layer name: MyFeature
+Geometry: None
+id: String (0.0) NOT NULL
+identifier_name_lang: String (0.0)
+identifier_name: String (0.0)
+identifier_namespace: String (0.0)
+OGRFeature(MyFeature):1
+  id (String) = my_id
+  identifier_name_lang (String) = en
+  identifier_name (String) = my_name
+  identifier_namespace (String) = baz
+</pre>
+</td>
+<td>Case of nested element, that can be folded into main layer. Use of
+an attribute on a sub-element.</td>
+</tr>
+
+<tr>
+<td>
+<pre>
+<schema xmlns:myns="http://myns"
+        targetNamespace="http://myns"
+        elementFormDefault="qualified"
+        xmlns="http://www.w3.org/2001/XMLSchema">
+
+<element name="AbstractFeature" abstract="true"/>
+
+<element name="FeatureCollection">
+  <complexType><sequence>
+      <element ref="myns:AbstractFeature" maxOccurs="unbounded"/>
+  </sequence></complexType>
+</element>
+
+<complexType name="namesType">
+  <sequence>
+    <element ref="myns:name" maxOccurs="unbounded"/>
+  </sequence>
+</complexType>
+
+<element name="MyFeature" substitutionGroup="myns:AbstractFeature">
+  <complexType><sequence>
+      <element name="names" type="myns:namesType"/>
+    </sequence>
+    <attribute name="id" type="ID" use="required"/>
+  </complexType>
+</element>
+
+<element name="MyFeature2" substitutionGroup="myns:AbstractFeature">
+  <complexType><sequence>
+      <element name="names" type="myns:namesType"/>
+    </sequence>
+    <attribute name="id" type="ID" use="required"/>
+  </complexType>
+</element>
+
+<element name="name">
+  <complexType><sequence>
+      <element name="name" type="string"/>
+      <element name="lang" type="string"/>
+  </sequence></complexType>
+</element>
+
+</schema>
+</pre>
+</td>
+<td>
+<pre>
+<FeatureCollection xmlns="http://myns">
+  <MyFeature id="my_id">
+    <names>
+        <name>
+          <name>name</name>
+          <lang>en</lang>
+        </name>
+        <name>
+          <name>nom</name>
+          <lang>fr</lang>
+        </name>
+    </names>
+  </MyFeature>
+  <MyFeature2 id="my_id2">
+    <names>
+        <name>
+          <name>nom2</name>
+          <lang>fr</lang>
+        </name>
+    </names>
+  </MyFeature2>
+</FeatureCollection>
+</pre>
+</td>
+<td>
+<pre>
+Layer name: name
+OGRFeature(name):1
+  ogr_pkid (String) = _name_1
+  name (String) = name
+  lang (String) = en
+
+OGRFeature(name):2
+  ogr_pkid (String) = _name_2
+  name (String) = nom
+  lang (String) = fr
+
+OGRFeature(name):3
+  ogr_pkid (String) = _name_3
+  name (String) = nom2
+  lang (String) = fr
+
+
+Layer name: MyFeature
+OGRFeature(MyFeature):1
+  id (String) = my_id
+
+Layer name: MyFeature2
+OGRFeature(MyFeature2):1
+  id (String) = my_id2
+
+
+Layer name: MyFeature_names_name_name
+OGRFeature(MyFeature_names_name_name):1
+  occurrence (Integer) = 1
+  parent_pkid (String) = my_id
+  child_pkid (String) = _name_1
+
+OGRFeature(MyFeature_names_name_name):2
+  occurrence (Integer) = 2
+  parent_pkid (String) = my_id
+  child_pkid (String) = _name_2
+
+
+Layer name: MyFeature2_names_name_name
+OGRFeature(MyFeature2_names_name_name):1
+  occurrence (Integer) = 1
+  parent_pkid (String) = my_id2
+  child_pkid (String) = _name_3
+
+</pre>
+</td>
+<td>Case of a common element "name" referenced by 2 layers "MyFeature" and
+"MyFeature1". The links are established through the junction layers
+"MyFeature_names_name_name" and "MyFeature2_names_name_name".
+</td>
+</tr>
+
+</table>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="drv_gmlas.html">GMLAS</a>: main documentation page for GMLAS driver.</li>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/gmlas/drv_gmlas_metadata_layers.html b/ogr/ogrsf_frmts/gmlas/drv_gmlas_metadata_layers.html
new file mode 100644
index 0000000..fc15e8c
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/drv_gmlas_metadata_layers.html
@@ -0,0 +1,171 @@
+<!DOCTYPE html 
+     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>GMLAS - Metadata layers</title>
+
+<style type="text/css">
+table, th, td {
+    border: 1px solid black;
+    border-collapse: collapse;
+}
+th, td {
+    padding: 5px;
+}
+</style>
+
+</head>
+
+<body>
+
+<h1>GMLAS - Metadata layers</h1>
+
+<p>This page details the structure of the extra metadata layers reported by
+the <a href="drv_gmlas.html">GMLAS</a> driver.</p>
+
+<h3>_ogr_fields_metadata layer</h3>
+
+<p>This layer gives metadata about OGR fields, and also "abstract" fields
+that describe the relation ship between a parent and child layer.</p>
+
+<p>Its structure is:
+<br/>
+<br/>
+</p>
+<table>
+<tr><th>Field name</th><th>Description</th></tr>
+<tr><td>layer_name</td><td>Name of the layer to which the field belongs to</td></tr>
+<tr><td>field_name</td><td>Name of the field. May be null when field_category is
+PATH_TO_CHILD_ELEMENT_NO_LINK or GROUP</td></tr>
+<tr><td>field_xpath</td><td>XPath of the element/attribute whose content is used
+for the field. The XPath is relative to the element that is the direct parent
+of this element/attribute, or a parent element in case of flattening. May be
+null for a field generated by OGR.</td></tr>
+<tr><td>field_type</td><td>the XML schema base data type (string, int, long, ID, ...).
+Extended with "geometry". May be null for a field generated by OGR</td></tr>
+<tr><td>field_is_list</td><td>Whether the XML type is a list.</td></tr>
+<tr><td>field_min_occurs</td><td>Integer value with the minimum number of occurrences
+of values. 0 or 1 typically. Or more for array types. May be
+null for a field generated by OGR</td></tr>
+<tr><td>field_max_occurs</td><td>Integer value with the maximum number of occurrences
+of values. 1 typically. Or more for array types. 2147483647 means unlimited.  May be
+null for a field generated by OGR</td></tr>
+<tr><td>field_repetition_on_sequence</td><td>Boolean value to indicate if the
+field is related to a <sequence maxOccurs=">1 or unbounded"> construct.
+Only set when field_max_occurs is not 0 or 1.</td></tr>
+<tr><td>field_default_value</td><td>Default value of the field, or null</td></tr>
+<tr><td>field_fixed_value</td><td>Fixed value of the field, or null</td></tr>
+<tr><td>field_category</td><td>Category of the field. May be REGULAR,
+PATH_TO_CHILD_ELEMENT_NO_LINK, PATH_TO_CHILD_ELEMENT_WITH_LINK,
+PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE or GROUP. May be null for a field
+generated by OGR.</td></tr>
+<tr><td>field_related_layer</td><td>Name of the child layer for
+field_category != REGULAR</td></tr>
+<tr><td>field_junction_layer</td><td>Name of the junction layer. Only
+set if field_category is equal to PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE</td></tr>
+<tr><td>field_documentation</td><td>Documentation from the schema.</td></tr>
+</table>
+
+<p>Explanation of field_category values:</p>
+<ul>
+<li>REGULAR: the field is made from the value of an element or attribute that
+is a direct child of the element that is the root of the layer considered.</li>
+<li>PATH_TO_CHILD_ELEMENT_NO_LINK: A field declared with this category
+is not instantiated as a OGR field of the layer 'layer_name'. It is merely there
+to declare the relationship between the parent and child layers. This is when
+a sub-element is of a complex type or a repeated sub-element of simple type that
+does not match one of the OGR array types.</li>
+<li>PATH_TO_CHILD_ELEMENT_WITH_LINK: the content of this field is the primary
+key of a OGR feature of another layer. The field_related_layer field contains
+the name of that linked layer.</li>
+<li>PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE: A field declared with this category
+is not instantiated as a OGR field of the layer 'layer_name'. It is merely there
+to declare the relationship between the parent and child layers. This is when
+the link between the parent and child layer is done through a junction table
+(case where the child layer is referenced by other parent layers).</li>
+<li>GROUP: A field declared with this category
+is not instantiated as a OGR field of the layer 'layer_name'. It is merely there
+to declare the relationship between the parent and child layers. This is when
+a layer uses XML schema group constructs with repeated cardinality.</li>
+</ul>
+
+<h3>_ogr_layers_metadata layer</h3>
+
+<p>This layer gives metadata about OGR layers.</p>
+
+<p>Its structure is:
+<br/>
+<br/>
+</p>
+<table border="1">
+<tr><th>Field name</th><th>Description</th></tr>
+<tr><td>layer_name</td><td>Name of the layer</td></tr>
+<tr><td>layer_xpath</td><td>XPath of the element that is used as the root
+element for the layer. May be suffixed with ";extra=XXXX" for group constructs
+or repeated sequences of repeated elements, so as to distinguish for the XPath
+of their parent element. Will be null for junction tables.</td></tr>
+<tr><td>layer_category</td><td>Category of the layer. One of TOP_LEVEL_ELEMENT,
+NESTED_ELEMENT or JUNCTION_TABLE</td></tr>
+<tr><td>layer_pkid_name</td><td>Name of the primary key field. This is the
+text attribute that uniquely identified a feature (in its layer). This is
+the XML attribute/name of type xs:ID when it exists, otherwise a "ogr_pkid"
+field is automatically created.</td></tr>
+<tr><td>layer_parent_pkid_name</td><td>Name of the field that is a foreign key
+to the parent layer of this layer. Only set for a NESTED_ELEMENT layer.</td></tr>
+<tr><td>layer_documentation</td><td>Documentation from the schema.</td></tr>
+</table>
+
+<h3>_ogr_layer_relationships layer</h3>
+
+<p>This layer gives metadata about relationship between OGR layers.</p>
+
+<p>Its structure is:
+<br/>
+<br/>
+</p>
+<table border="1">
+<tr><th>Field name</th><th>Description</th></tr>
+<tr><td>parent_layer</td><td>Name of the parent layer</td></tr>
+<tr><td>parent_pkid</td><td>Name of the primary key of the parent layer</td></tr>
+<tr><td>parent_element_name</td><td>Name of the XML element that links from the
+parent to the child. Will be null when the child layer is due to group constructs
+or repeated sequences of repeated elements of the parent.</td></tr>
+<tr><td>child_layer</td><td>Name of the child layer</td></tr>
+<tr><td>child_pkid</td><td>Name of the primary key of the child layer</td></tr>
+</table>
+
+<h3>_ogr_other_metadata layer</h3>
+
+<p>This layer contains key / value pairs with different information.</p>
+
+<p>Its structure is:
+<br/>
+<br/>
+</p>
+<table border="1">
+<tr><th>Field name</th><th>Description</th></tr>
+<tr><td>key</td><td>Name of the metadata item</td></tr>
+<tr><td>value</td><td>Value of the metadata imtem</td></tr>
+</table>
+
+<p>Possible keys are :</p>
+<ul>
+<li>document_filename: Filename of the XML/GML file read.</li>
+<li>configuration_filename: Filename of the XML configuration file used.</li>
+<li>configuration_inlined: XML content of the configuration file.</li>
+<li>namespace_uri_XX: URI of a namespace referenced by the schema(s).</li>
+<li>namespace_location_XX: Location of a schema.</li>
+<li>namespace_prefix_XX: Prefix of a namespace referenced by the schema(s).</li>
+<li>gml_version: GML version, such as 2.1.2, 3.1.1 or 3.2.1</li>
+</ul>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="drv_gmlas.html">GMLAS</a>: main documentation page for GMLAS driver.</li>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/gmlas/makefile.vc b/ogr/ogrsf_frmts/gmlas/makefile.vc
new file mode 100644
index 0000000..b8e5a5f
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/makefile.vc
@@ -0,0 +1,18 @@
+
+OBJ	=	ogrgmlasdriver.obj ogrgmlasdatasource.obj ogrgmlaslayer.obj \
+        ogrgmlasreader.obj ogrgmlasschemaanalyzer.obj ogrgmlasfeatureclass.obj \
+        ogrgmlasxsdcache.obj ogrgmlasconf.obj ogrgmlasxpatchmatcher.obj \
+        ogrgmlasxlinkresolver.obj ogrgmlaswriter.obj
+
+GDAL_ROOT	=	..\..\..
+
+!INCLUDE $(GDAL_ROOT)\nmake.opt
+
+EXTRAFLAGS =	-I.. -I..\.. -I..\mem  -I..\geojson -I..\geojson\libjson -I..\pgdump $(XERCES_INCLUDE) -DHAVE_XERCES=1 $(EXPAT_EXTRAFLAGS)
+
+default:	$(OBJ)
+
+clean:
+	-del *.lib
+	-del *.obj *.pdb
+
diff --git a/ogr/ogrsf_frmts/gmlas/ogr_gmlas.h b/ogr/ogrsf_frmts/gmlas/ogr_gmlas.h
new file mode 100644
index 0000000..907ba0f
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogr_gmlas.h
@@ -0,0 +1,1555 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_GMLAS_INCLUDED
+#define OGR_GMLAS_INCLUDED
+
+// Must be first for DEBUG_BOOL case
+#include "xercesc_headers.h"
+#include "ogr_xerces.h"
+
+#include "gdal_priv.h"
+#include "ogrsf_frmts.h"
+
+#include "ogr_gmlas_consts.h"
+
+#include <set>
+#include <map>
+#include <vector>
+
+typedef std::pair<CPLString, CPLString> PairURIFilename;
+
+typedef enum
+{
+    GMLAS_SWAP_AUTO,
+    GMLAS_SWAP_YES,
+    GMLAS_SWAP_NO,
+} GMLASSwapCoordinatesEnum;
+
+GDALDataset *OGRGMLASDriverCreateCopy(
+                          const char * pszFilename,
+                          GDALDataset *poSrcDS,
+                          int /*bStrict*/, char ** papszOptions,
+                          GDALProgressFunc pfnProgress, void * pProgressData );
+
+/************************************************************************/
+/*                          IGMLASInputSourceClosing                    */
+/************************************************************************/
+
+class IGMLASInputSourceClosing
+{
+    public:
+        virtual ~IGMLASInputSourceClosing() {}
+
+        virtual void notifyClosing(const CPLString& osFilename) = 0;
+};
+
+/************************************************************************/
+/*                         GMLASResourceCache                           */
+/************************************************************************/
+
+class GMLASResourceCache
+{
+    protected:
+                bool            m_bHasCheckedCacheDirectory;
+                CPLString       m_osCacheDirectory;
+                bool            m_bRefresh;
+                bool            m_bAllowDownload;
+                std::set<CPLString> m_aoSetRefreshedFiles;
+
+                static bool RecursivelyCreateDirectoryIfNeeded(
+                                                const CPLString& osDirname);
+                bool RecursivelyCreateDirectoryIfNeeded();
+
+                CPLString GetCachedFilename(const CPLString& osResource);
+
+    public:
+                             GMLASResourceCache();
+                    virtual ~GMLASResourceCache();
+
+                    void    SetCacheDirectory(const CPLString& osCacheDirectory);
+                    void    SetRefreshMode(bool bRefresh)
+                                            { m_bRefresh = bRefresh; }
+                    void    SetAllowDownload(bool bVal)
+                                    { m_bAllowDownload = bVal; }
+};
+
+/************************************************************************/
+/*                          GMLASXSDCache                               */
+/************************************************************************/
+
+class GMLASXSDCache: public GMLASResourceCache
+{
+    public:
+                             GMLASXSDCache();
+                    virtual ~GMLASXSDCache();
+
+                    VSILFILE* Open( const CPLString& osResource,
+                                    const CPLString& osBasePath,
+                                    CPLString& osOutFilename );
+};
+
+/************************************************************************/
+/*                     GMLASBaseEntityResolver                          */
+/************************************************************************/
+
+class GMLASBaseEntityResolver: public EntityResolver,
+                           public IGMLASInputSourceClosing
+{
+  protected:
+        std::vector<CPLString> m_aosPathStack;
+        GMLASXSDCache& m_oCache;
+        CPLString m_osGMLVersionFound;
+        std::set<CPLString> m_oSetSchemaURLs;
+
+  public:
+        GMLASBaseEntityResolver(const CPLString& osBasePath,
+                                GMLASXSDCache& oCache);
+        virtual ~GMLASBaseEntityResolver();
+
+        void SetBasePath(const CPLString& osBasePath);
+        const CPLString& GetGMLVersionFound() const
+                                        { return m_osGMLVersionFound; }
+        const std::set<CPLString>& GetSchemaURLS() const
+                                        { return m_oSetSchemaURLs; }
+
+        virtual void notifyClosing(const CPLString& osFilename ) override;
+        virtual InputSource* resolveEntity( const XMLCh* const publicId,
+                                            const XMLCh* const systemId) override;
+
+        virtual void DoExtraSchemaProcessing(const CPLString& osFilename,
+                                             VSILFILE* fp);
+};
+
+/************************************************************************/
+/*                          GMLASInputSource                            */
+/************************************************************************/
+
+class GMLASInputSource : public InputSource
+{
+    VSILFILE *m_fp;
+    bool      m_bOwnFP;
+    int       m_nCounter;
+    int      *m_pnCounter;
+    CPLString m_osFilename;
+    IGMLASInputSourceClosing* m_cbk;
+
+public:
+             GMLASInputSource(const char* pszFilename,
+                              VSILFILE* fp,
+                              bool bOwnFP,
+                              MemoryManager* const manager =
+                                            XMLPlatformUtils::fgMemoryManager);
+    virtual ~GMLASInputSource();
+
+    virtual BinInputStream* makeStream() const override;
+
+    void    SetClosingCallback( IGMLASInputSourceClosing* cbk );
+};
+
+/************************************************************************/
+/*                            GMLASErrorHandler                         */
+/************************************************************************/
+
+class GMLASErrorHandler: public ErrorHandler
+{
+    public:
+        GMLASErrorHandler () : m_bFailed (false),
+                               m_bSchemaFullChecking (false),
+                               m_bHandleMultipleImports (false)   {}
+
+        void SetSchemaFullCheckingEnabled(bool b)
+                                            { m_bSchemaFullChecking = b; }
+
+        void SetHandleMultipleImportsEnabled(bool b)
+                                            { m_bHandleMultipleImports = b; }
+
+        bool hasFailed () const { return m_bFailed; }
+
+        virtual void warning (const SAXParseException& e) override;
+        virtual void error (const SAXParseException& e) override;
+        virtual void fatalError (const SAXParseException& e) override;
+
+        virtual void resetErrors () override { m_bFailed = false; }
+
+    private:
+        bool m_bFailed;
+        bool m_bSchemaFullChecking;
+        bool m_bHandleMultipleImports;
+
+        void handle (const SAXParseException& e, CPLErr eErr);
+};
+
+/************************************************************************/
+/*                        GMLASXLinkResolutionConf                      */
+/************************************************************************/
+
+class GMLASXLinkResolutionConf
+{
+    public:
+        /* See data/gmlasconf.xsd for docomentation of the fields */
+
+        typedef enum
+        {
+            RawContent,
+            FieldsFromXPath
+        } ResolutionMode;
+
+        int m_nTimeOut;
+
+        int m_nMaxFileSize;
+
+        int m_nMaxGlobalResolutionTime;
+
+        CPLString m_osProxyServerPort;
+
+        CPLString m_osProxyUserPassword;
+
+        CPLString m_osProxyAuth;
+
+        CPLString m_osCacheDirectory;
+
+        bool m_bDefaultResolutionEnabled;
+
+        bool m_bDefaultAllowRemoteDownload;
+
+        ResolutionMode m_eDefaultResolutionMode;
+
+        int m_nDefaultResolutionDepth;
+
+        bool m_bDefaultCacheResults;
+
+        class URLSpecificResolution
+        {
+            public:
+
+                CPLString m_osURLPrefix;
+
+                std::vector< std::pair<CPLString, CPLString> > m_aosNameValueHTTPHeaders;
+
+                bool m_bAllowRemoteDownload;
+
+                ResolutionMode m_eResolutionMode;
+
+                int m_nResolutionDepth;
+
+                bool m_bCacheResults;
+
+                class XPathDerivedField
+                {
+                    public:
+
+                        CPLString m_osName;
+
+                        CPLString m_osType;
+
+                        CPLString m_osXPath;
+                };
+
+                std::vector<XPathDerivedField> m_aoFields;
+
+                URLSpecificResolution();
+        };
+
+        std::vector<URLSpecificResolution> m_aoURLSpecificRules;
+
+        GMLASXLinkResolutionConf();
+
+        bool LoadFromXML(CPLXMLNode* psRoot);
+};
+
+/************************************************************************/
+/*                          GMLASConfiguration                          */
+/************************************************************************/
+
+class GMLASConfiguration
+{
+    public:
+
+        /** Whether remote schemas are allowed to be download. */
+        bool            m_bAllowRemoteSchemaDownload;
+
+        /** Whether a ogr_pkid attribute should always be generated. */
+        bool            m_bAlwaysGenerateOGRId;
+
+        /** Whether to remove layers found to be unused in initial scan pass */
+        bool            m_bRemoveUnusedLayers;
+
+        /** Whether to remove fields found to be unused in initial scan pass */
+        bool            m_bRemoveUnusedFields;
+
+        /** Whether repeated strings, integers, reals should be in corresponding
+            OGR array types. */
+        bool            m_bUseArrays;
+
+        /** Whether OGR field null state should be used. */
+        bool            m_bUseNullState;
+
+        /** Whether geometries should be stored as XML in a OGR string field. */
+        bool            m_bIncludeGeometryXML;
+
+        /** Whether, when dealing with schemas that import the
+            GML namespace, and that at least one of them has
+            elements that derive from gml:_Feature or
+            gml:AbstractFeatureonly, only such elements should be
+            instantiated as OGR layers, during the first pass that
+            iterates over top level elements of the imported
+            schemas. */
+        bool            m_bInstantiateGMLFeaturesOnly;
+
+        /** Maximum length of layer and field identifiers*/
+        int             m_nIdentifierMaxLength;
+
+        /** Whether case insensitive comparison should be used for identifier equality testing */
+        bool            m_bCaseInsensitiveIdentifier;
+
+        /** Whether to launder identifiers like postgresql does */
+        bool            m_bPGIdentifierLaundering;
+
+        /* Maximum number of fields in an element considered for flattening. */
+        int             m_nMaximumFieldsForFlattening;
+
+        /** Whether remote XSD schemas should be locally cached. */
+        bool            m_bAllowXSDCache;
+
+        /** Cache directory for cached XSD schemas. */
+        CPLString       m_osXSDCacheDirectory;
+
+        /** Whether to enable schema full checking. */
+        bool            m_bSchemaFullChecking;
+
+        /** Whether to allow multiple imports of the same namespace. */
+        bool            m_bHandleMultipleImports;
+
+        /** Whether validation of document against schema should be done.  */
+        bool            m_bValidate;
+
+        /** Whether a validation error should prevent dataset opening.  */
+        bool            m_bFailIfValidationError;
+
+        /** Whether technical layers should be exposed.  */
+        bool            m_bExposeMetadataLayers;
+
+        /** For flatening rules, map prefix namespace to its URI */
+        std::map<CPLString, CPLString> m_oMapPrefixToURIFlatteningRules;
+
+        std::vector<CPLString> m_osForcedFlattenedXPath;
+
+        std::vector<CPLString> m_osDisabledFlattenedXPath;
+
+        enum SWEActivationMode
+        {
+            SWE_ACTIVATE_IF_NAMESPACE_FOUND,
+            SWE_ACTIVATE_TRUE,
+            SWE_ACTIVATE_FALSE
+        };
+
+        /** If and when activate SWE special processings */
+        SWEActivationMode m_eSWEActivationMode;
+
+        /** If enabling swe:DataArray parsing */
+        bool m_bSWEProcessDataArray;
+
+        /** For ignored xpaths, map prefix namespace to its URI */
+        std::map<CPLString, CPLString> m_oMapPrefixToURIIgnoredXPaths;
+
+        /** Ignored xpaths */
+        std::vector<CPLString> m_aosIgnoredXPaths;
+
+        /** For type constraints, map prefix namespace to its URI */
+        std::map<CPLString, CPLString> m_oMapPrefixToURITypeConstraints;
+
+        /** Map an XPath to a list of potential types for its children */
+        std::map<CPLString, std::vector<CPLString> > m_oMapChildrenElementsConstraints;
+
+        /* Beginning of Writer config */
+
+        /** Number of spaces for indentation */
+        int m_nIndentSize;
+
+        CPLString m_osComment;
+
+        /** End of line format: "CRLF" or "LR" */
+        CPLString m_osLineFormat;
+
+        /** "SHORT", "OGC_URN" or "OGC_URL" */
+        CPLString m_osSRSNameFormat;
+
+        /** "WFS2_FEATURECOLLECTION" or "GMLAS_FEATURECOLLECTION" */
+        CPLString m_osWrapping;
+
+        /** XML datetime or empty for current time */
+        CPLString m_osTimestamp;
+
+        /** Path or URL to OGC WFS 2.0 schema. */
+        CPLString m_osWFS20SchemaLocation;
+
+        /* End of Writer config */
+
+        /** Whether a warning should be emitted when an element or attribute is
+            found in the document parsed, but ignored because of the ignored
+            XPath defined.  */
+        std::map<CPLString, bool> m_oMapIgnoredXPathToWarn;
+
+        GMLASXLinkResolutionConf  m_oXLinkResolution;
+
+                                    GMLASConfiguration();
+                    virtual        ~GMLASConfiguration();
+
+                            bool    Load(const char* pszFilename);
+                            void    Finalize();
+
+        static CPLString GetBaseCacheDirectory();
+};
+
+/************************************************************************/
+/*                          GMLASXLinkResolver                          */
+/************************************************************************/
+
+class GMLASXLinkResolver: public GMLASResourceCache
+{
+        GMLASXLinkResolutionConf    m_oConf;
+        int                         m_nGlobalResolutionTime;
+
+        std::map<CPLString, CPLString> m_oMapURLToContent;
+        std::map<size_t, std::vector<CPLString> > m_oMapFileSizeToURLs;
+        size_t m_nMaxRAMCacheSize;
+        size_t m_nCurrentRAMCacheSize;
+
+        CPLString FetchRawContent(const CPLString& osURL,
+                                  const char* pszHeaders);
+
+        CPLString GetRawContent(const CPLString& osURL,
+                                const char* pszHeaders,
+                                bool bAllowRemoteDownload,
+                                bool bCacheResults);
+    public:
+
+                GMLASXLinkResolver();
+
+        void  SetConf( const GMLASXLinkResolutionConf& oConf );
+        const GMLASXLinkResolutionConf& GetConf() const { return m_oConf; }
+
+        bool      IsRawContentResolutionEnabled() const;
+        int       GetMatchingResolutionRule(const CPLString& osURL) const;
+        CPLString GetRawContent(const CPLString& osURL);
+        CPLString GetRawContentForRule(const CPLString& osURL, int nIdxRule);
+};
+
+/************************************************************************/
+/*                           GMLASXPathMatcher                          */
+/************************************************************************/
+
+/** Object to compares a user provided XPath against a set of test XPaths */
+class GMLASXPathMatcher
+{
+        class XPathComponent
+        {
+            public:
+                    CPLString m_osValue;
+                    bool      m_bDirectChild;
+        };
+
+        /** For reference xpaths, map prefix namespace to its URI */
+        std::map<CPLString, CPLString> m_oMapPrefixToURIReferenceXPaths;
+
+        /** Reference xpaths */
+        std::vector<CPLString> m_aosReferenceXPathsUncompiled;
+
+        /** Reference xpaths "compiled" */
+        std::vector< std::vector<XPathComponent> > m_aosReferenceXPaths;
+
+        static bool MatchesRefXPath(
+            const CPLString& osXPath,
+            const std::vector<XPathComponent>& oRefXPath);
+
+    public:
+                                GMLASXPathMatcher();
+                    virtual    ~GMLASXPathMatcher();
+
+        void    SetRefXPaths(const std::map<CPLString, CPLString>&
+                                    oMapPrefixToURIReferenceXPaths,
+                                const std::vector<CPLString>&
+                                    aosReferenceXPaths);
+
+        void    SetDocumentMapURIToPrefix(
+                    const std::map<CPLString,CPLString>& oMapURIToPrefix );
+
+        /** Return true if osXPath matches one of the XPath of
+            m_aosReferenceXPaths */
+        bool MatchesRefXPath(
+            const CPLString& osXPath,
+            CPLString& osOutMatchedXPath ) const;
+
+        const std::map<CPLString, CPLString>& GetMapPrefixToURI() const
+            { return m_oMapPrefixToURIReferenceXPaths; }
+};
+
+/************************************************************************/
+/*                            GMLASFieldType                            */
+/************************************************************************/
+
+/** Enumeration for XML primitive types */
+typedef enum
+{
+    GMLAS_FT_STRING,
+    GMLAS_FT_ID,
+    GMLAS_FT_BOOLEAN,
+    GMLAS_FT_SHORT,
+    GMLAS_FT_INT32,
+    GMLAS_FT_INT64,
+    GMLAS_FT_FLOAT,
+    GMLAS_FT_DOUBLE,
+    GMLAS_FT_DECIMAL,
+    GMLAS_FT_DATE,
+    GMLAS_FT_TIME,
+    GMLAS_FT_DATETIME,
+    GMLAS_FT_BASE64BINARY,
+    GMLAS_FT_HEXBINARY,
+    GMLAS_FT_ANYURI,
+    GMLAS_FT_ANYTYPE,
+    GMLAS_FT_ANYSIMPLETYPE,
+    GMLAS_FT_GEOMETRY, // this one isn't a XML primitive type.
+} GMLASFieldType;
+
+/************************************************************************/
+/*                              GMLASField                              */
+/************************************************************************/
+
+class GMLASField
+{
+    public:
+        typedef enum
+        {
+            /** Field that is going to be instantiated as a OGR field */
+            REGULAR,
+
+            /** Non-instanciable field. The corresponding element to the XPath
+                is stored in a child layer that will reference back to the
+                main layer. */
+            PATH_TO_CHILD_ELEMENT_NO_LINK,
+
+            /** Field that will store the PKID of a child element */
+            PATH_TO_CHILD_ELEMENT_WITH_LINK,
+
+            /** Non-instanciable field. The corresponding element to the XPath
+                is stored in a child layer. And the link between both will be
+                done through a junction table. */
+            PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE,
+
+            /** Non-instanciable field. Corresponds to a group of an element. */
+            GROUP
+        } Category;
+
+    private:
+        CPLString m_osName;         /**< Field name */
+        GMLASFieldType m_eType;     /**< Field type */
+        OGRwkbGeometryType m_eGeomType; /**< Field geometry type */
+        CPLString m_osTypeName;     /**< Original XSD type */
+        int m_nWidth;               /**< Field width */
+        bool m_bNotNullable;        /**< If the field is not nullable */
+        bool m_bArray;              /**< If the field is an array (from OGR types point of view) */
+        bool m_bList;               /**< If the field is a list (a xs:list) */
+
+        /** Category of the field. */
+        Category m_eCategory;
+
+        /** XPath of the field. */
+        CPLString m_osXPath;
+
+        /** Set of XPath that are linked to this field.
+            This is used for cases where a gml:AbstractGeometry element is
+            referenced. In which case all possible realizations of this
+            element are listed. Will be used with eType == GMLAS_FT_ANYTYPE
+            to store XML blob on parsing. */
+        std::vector<CPLString> m_aosXPath;
+
+        CPLString m_osFixedValue;       /**< Value of fixed='' attribute */
+        CPLString m_osDefaultValue;     /**< Value of default='' attribute */
+
+        /** Minimum number of occurrences. Might be -1 if unset */
+        int  m_nMinOccurs;
+
+        /** Maximum number of occurrences, or MAXOCCURS_UNLIMITED. Might be
+            -1 if unset. */
+        int  m_nMaxOccurs;
+
+        /** For a PATH_TO_CHILD_ELEMENT_NO_LINK, whether maxOccurs>1 is on the
+            sequence rather than on the element */
+        bool m_bRepetitionOnSequence;
+
+        /** In case of m_eType == GMLAS_FT_ANYTYPE whether the current element
+            must be stored in the XML blob (if false, only its children) */
+        bool m_bIncludeThisEltInBlob;
+
+        /** Only used for PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE. The XPath
+            of the abstract element (the concrete XPath is in m_osXPath).
+            e.g myns:mainElt/myns:subEltAbstract whereas the concrete XPath
+            is myns:mainElt/myns:subEltRealization */
+        CPLString m_osAbstractElementXPath;
+
+        /** Only used for PATH_TO_CHILD_ELEMENT_WITH_LINK and
+            PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE (and also for
+            PATH_TO_CHILD_ELEMENT_NO_LINK and GROUP but for metadata layers only).
+            The XPath of the child element. */
+        CPLString m_osRelatedClassXPath;
+
+        /** Only use for PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE. Name of
+            the junction layer to consult for this field. Only used by
+            writer code. */
+        CPLString m_osJunctionLayer;
+
+        /** Dirty hack to register attributes with fixed values, despite being
+            in the XPath ignored list. Needed to avoid warning when doing validation */
+        bool m_bIgnored;
+
+        /** Documentation from schema */
+        CPLString m_osDoc;
+
+        /** For elements within xs:choice */
+        bool m_bMayAppearOutOfOrder;
+
+    public:
+        GMLASField();
+
+        void SetName(const CPLString& osName) { m_osName = osName; }
+        void SetType(GMLASFieldType eType, const char* pszTypeName);
+        void SetGeomType(OGRwkbGeometryType eGeomType)
+                                   { m_eGeomType = eGeomType; }
+        void SetWidth(int nWidth) { m_nWidth = nWidth; }
+        void SetNotNullable(bool bNotNullable)
+                                    { m_bNotNullable = bNotNullable; }
+        void SetArray(bool bArray) { m_bArray = bArray; }
+        void SetList(bool bList) { m_bList = bList; }
+        void SetXPath(const CPLString& osXPath) { m_osXPath = osXPath; }
+        void AddAlternateXPath(const CPLString& osXPath)
+                                            { m_aosXPath.push_back(osXPath); }
+        void SetFixedValue(const CPLString& osFixedValue)
+                                    { m_osFixedValue = osFixedValue; }
+        void SetDefaultValue(const CPLString& osDefaultValue)
+                                    { m_osDefaultValue = osDefaultValue; }
+        void SetCategory(Category eCategory) { m_eCategory = eCategory; }
+        void SetMinOccurs(int nMinOccurs) { m_nMinOccurs = nMinOccurs; }
+        void SetMaxOccurs(int nMaxOccurs) { m_nMaxOccurs = nMaxOccurs; }
+        void SetRepetitionOnSequence(bool b) { m_bRepetitionOnSequence = b; }
+        void SetIncludeThisEltInBlob(bool b) { m_bIncludeThisEltInBlob = b; }
+        void SetAbstractElementXPath(const CPLString& osName)
+                                            { m_osAbstractElementXPath = osName; }
+
+        void SetRelatedClassXPath(const CPLString& osName)
+                                            { m_osRelatedClassXPath = osName; }
+        void SetJunctionLayer(const CPLString& osName)
+                                            { m_osJunctionLayer = osName; }
+
+        void SetIgnored() { m_bIgnored = true; }
+        void SetDocumentation(const CPLString& osDoc) { m_osDoc = osDoc; }
+        void SetMayAppearOutOfOrder(bool b) { m_bMayAppearOutOfOrder = b; }
+
+        static CPLString MakePKIDFieldXPathFromXLinkHrefXPath(
+            const CPLString& osBaseXPath)
+                            { return "{" + osBaseXPath + "}_pkid"; }
+
+        static CPLString MakeXLinkRawContentFieldXPathFromXLinkHrefXPath(
+            const CPLString& osBaseXPath)
+                            { return "{" + osBaseXPath + "}_rawcontent"; }
+
+        static CPLString MakeXLinkDerivedFieldXPathFromXLinkHrefXPath(
+            const CPLString& osBaseXPath, const CPLString& osName)
+                            { return "{" + osBaseXPath + "}_derived_" + osName; }
+
+        const CPLString& GetName() const { return m_osName; }
+        const CPLString& GetXPath() const { return m_osXPath; }
+        const std::vector<CPLString>& GetAlternateXPaths() const
+                                            { return m_aosXPath; }
+        GMLASFieldType GetType() const { return m_eType; }
+        OGRwkbGeometryType GetGeomType() const { return m_eGeomType; }
+        const CPLString& GetTypeName() const { return m_osTypeName; }
+        int GetWidth() const { return m_nWidth; }
+        bool IsNotNullable() const { return m_bNotNullable; }
+        bool IsArray() const { return m_bArray; }
+        bool IsList() const { return m_bList; }
+        const CPLString& GetFixedValue() const { return m_osFixedValue; }
+        const CPLString& GetDefaultValue() const { return m_osDefaultValue; }
+        Category GetCategory() const { return m_eCategory; }
+        int GetMinOccurs() const { return m_nMinOccurs; }
+        int GetMaxOccurs() const { return m_nMaxOccurs; }
+        bool GetRepetitionOnSequence() const { return m_bRepetitionOnSequence; }
+        bool GetIncludeThisEltInBlob() const { return m_bIncludeThisEltInBlob; }
+        const CPLString& GetAbstractElementXPath() const
+                                            { return m_osAbstractElementXPath; }
+        const CPLString& GetJunctionLayer() const
+                                                { return m_osJunctionLayer; }
+        const CPLString& GetRelatedClassXPath() const
+                                                { return m_osRelatedClassXPath; }
+        bool IsIgnored() const { return m_bIgnored; }
+        const CPLString& GetDocumentation() const { return m_osDoc; }
+        bool MayAppearOutOfOrder() const { return m_bMayAppearOutOfOrder; }
+
+        static GMLASFieldType GetTypeFromString( const CPLString& osType );
+};
+
+/************************************************************************/
+/*                            GMLASFeatureClass                         */
+/************************************************************************/
+
+class GMLASFeatureClass
+{
+        /** User facing name */
+        CPLString m_osName;
+
+        /** XPath to the main element of the feature class */
+        CPLString m_osXPath;
+
+        /** List of fields */
+        std::vector<GMLASField> m_aoFields;
+
+        /** Child nested classes */
+        std::vector<GMLASFeatureClass> m_aoNestedClasses;
+
+        /** Whether this layer corresponds to a (multiple instantiated) xs:group
+            or a repeated sequence */
+        bool m_bIsRepeatedSequence;
+
+        /** Whether this is a repeated group. Should be set together with m_bIsRepeatedSequence */
+        bool m_bIsGroup;
+
+        /** Only used for junction tables. The XPath to the parent table */
+        CPLString m_osParentXPath;
+
+        /** Only used for junction tables. The XPath to the child table */
+        CPLString m_osChildXPath;
+
+        /** Whether this corresponds to a top-level XSD element in the schema */
+        bool m_bIsTopLevelElt;
+
+        /** Documentation from schema */
+        CPLString m_osDoc;
+
+    public:
+        GMLASFeatureClass();
+
+        void SetName(const CPLString& osName);
+        void SetXPath(const CPLString& osXPath);
+        void AddField( const GMLASField& oField );
+        void PrependFields( const std::vector<GMLASField>& aoFields );
+        void AppendFields( const std::vector<GMLASField>& aoFields );
+        void AddNestedClass( const GMLASFeatureClass& oNestedClass );
+        void SetIsRepeatedSequence( bool bIsRepeatedSequence )
+                            { m_bIsRepeatedSequence = bIsRepeatedSequence; }
+        void SetIsGroup( bool bIsGroup )
+                            { m_bIsGroup = bIsGroup; }
+        void SetParentXPath(const CPLString& osXPath)
+                                                { m_osParentXPath = osXPath; }
+        void SetChildXPath(const CPLString& osXPath)
+                                                { m_osChildXPath = osXPath; }
+        void SetIsTopLevelElt(bool bIsTopLevelElt )
+                                        { m_bIsTopLevelElt = bIsTopLevelElt; }
+        void SetDocumentation(const CPLString& osDoc) { m_osDoc = osDoc; }
+
+        const CPLString& GetName() const { return m_osName; }
+        const CPLString& GetXPath() const { return m_osXPath; }
+        const std::vector<GMLASField>& GetFields() const { return m_aoFields; }
+        std::vector<GMLASField>& GetFields() { return m_aoFields; }
+        const std::vector<GMLASFeatureClass>& GetNestedClasses() const
+                                            { return m_aoNestedClasses; }
+        std::vector<GMLASFeatureClass>& GetNestedClasses()
+                                            { return m_aoNestedClasses; }
+        bool IsRepeatedSequence() const { return m_bIsRepeatedSequence; }
+        bool IsGroup() const { return m_bIsGroup; }
+        const CPLString& GetParentXPath() const { return m_osParentXPath; }
+        const CPLString& GetChildXPath() const { return m_osChildXPath; }
+        bool IsTopLevelElt() const { return m_bIsTopLevelElt; }
+        const CPLString& GetDocumentation() const { return m_osDoc; }
+};
+
+/************************************************************************/
+/*                         GMLASSchemaAnalyzer                          */
+/************************************************************************/
+
+class GMLASSchemaAnalyzer
+{
+        GMLASXPathMatcher& m_oIgnoredXPathMatcher;
+
+        GMLASXPathMatcher& m_oChildrenElementsConstraintsXPathMatcher;
+
+        GMLASXPathMatcher& m_oForcedFlattenedXPathMatcher;
+
+        GMLASXPathMatcher& m_oDisabledFlattenedXPathMatcher;
+
+        std::map<CPLString, std::vector<CPLString> > m_oMapChildrenElementsConstraints;
+
+        /** Whether repeated strings, integers, reals should be in corresponding
+            OGR array types. */
+        bool m_bUseArrays;
+
+        /** Whether OGR field null state should be used. */
+        bool            m_bUseNullState;
+
+        /** Whether, when dealing with schemas that import the
+            GML namespace, and that at least one of them has
+            elements that derive from gml:_Feature or
+            gml:AbstractFeatureonly, only such elements should be
+            instantiated as OGR layers, during the first pass that
+            iterates over top level elements of the imported
+            schemas. */
+        bool            m_bInstantiateGMLFeaturesOnly;
+
+        /** Vector of feature classes */
+        std::vector<GMLASFeatureClass> m_aoClasses;
+
+        /** Map from a namespace URI to the corresponding prefix */
+        std::map<CPLString, CPLString> m_oMapURIToPrefix;
+
+        /** Map element XPath to its XSElementDeclaration* */
+        std::map<CPLString, XSElementDeclaration*> m_oMapXPathToEltDecl;
+
+        typedef std::map<XSElementDeclaration*,
+                                std::vector<XSElementDeclaration*> >
+                                                    tMapParentEltToChildElt;
+        /** Map from a base/parent element to a vector of derived/children
+            elements that are substitutionGroup of it. The map only
+            addresses the direct derived types, and not the 2nd level or more
+            derived ones. For that recursion in the map must be used.*/
+        tMapParentEltToChildElt m_oMapParentEltToChildElt;
+
+        /** Map from a XSModelGroup* object to the name of its group definition. */
+        std::map< XSModelGroup*, XSModelGroupDefinition*> m_oMapModelGroupToMGD;
+
+        /** Map from (non namespace prefixed) element names to the number of
+            elements that share the same namespace (in different namespaces) */
+        std::map<CPLString, int> m_oMapEltNamesToInstanceCount;
+
+        /** Set of elements that match a OGR layer */
+        std::set<XSElementDeclaration*> m_oSetEltsForTopClass;
+
+        /** Set of elements that are simple enough to be inlined whenever they
+            are referenced with cardinality 1. The use case if base:identifier
+            used by Inspire schemas. */
+        std::set<XSElementDeclaration*> m_oSetSimpleEnoughElts;
+
+        /** Maximum length of layer and field identifiers*/
+        int             m_nIdentifierMaxLength;
+
+        /** Whether case insensitive comparison should be used for identifier equality testing */
+        bool            m_bCaseInsensitiveIdentifier;
+
+        /** Whether to launder identifiers like postgresql does */
+        bool            m_bPGIdentifierLaundering;
+
+        /* Maximum number of fields in an element considered for flattening. */
+        int             m_nMaximumFieldsForFlattening;
+
+        /** GML version found: 2.1.1, 3.1.1 or 3.2.1 or empty*/
+        CPLString m_osGMLVersionFound;
+
+        /** Set of schemas opened */
+        std::set<CPLString> m_oSetSchemaURLs;
+
+        static bool IsSame( const XSModelGroup* poModelGroup1,
+                                  const XSModelGroup* poModelGroup2 );
+        XSModelGroupDefinition* GetGroupDefinition( const XSModelGroup* poModelGroup );
+        void SetFieldFromAttribute(GMLASField& oField,
+                                   XSAttributeUse* poAttr,
+                                   const CPLString& osXPathPrefix,
+                                   const CPLString& osNamePrefix = CPLString());
+        void GetConcreteImplementationTypes(
+                                XSElementDeclaration* poParentElt,
+                                std::vector<XSElementDeclaration*>& apoImplEltList);
+        std::vector<XSElementDeclaration*>
+                    GetConstraintChildrenElements(const CPLString& osFullXPath);
+        bool FindElementsWithMustBeToLevel(
+                            const CPLString& osParentXPath,
+                            XSModelGroup* poModelGroup,
+                            int nRecursionCounter,
+                            std::set<XSElementDeclaration*>& oSetVisitedEltDecl,
+                            std::set<XSModelGroup*>& oSetVisitedModelGroups,
+                            std::vector<XSElementDeclaration*>& oVectorEltsForTopClass,
+                            std::set<CPLString>& aoSetXPathEltsForTopClass,
+                            XSModel* poModel,
+                            bool& bSimpleEnoughOut,
+                            int& nCountSubEltsOut);
+        void BuildMapCountOccurrencesOfSameName(
+                    XSModelGroup* poModelGroup,
+                    std::map< CPLString, int >& oMapCountOccurrencesOfSameName);
+        bool ExploreModelGroup( XSModelGroup* psMainModelGroup,
+                                XSAttributeUseList* poMainAttrList,
+                                GMLASFeatureClass& oClass,
+                                int nRecursionCounter,
+                                std::set<XSModelGroup*>& oSetVisitedModelGroups,
+                                XSModel* poModel,
+                                const std::map< CPLString, int >& oMapCountOccurrencesOfSameName);
+        void SetFieldTypeAndWidthFromDefinition( XSSimpleTypeDefinition* poST,
+                                                 GMLASField& oField );
+        CPLString GetPrefix( const CPLString& osNamespaceURI );
+        CPLString MakeXPath( const CPLString& osNamespace,
+                                          const CPLString& osName );
+        void LaunderFieldNames( GMLASFeatureClass& oClass );
+        void LaunderClassNames();
+
+        XSElementDeclaration* GetTopElementDeclarationFromXPath(
+                                                    const CPLString& osXPath,
+                                                    XSModel* poModel);
+
+        bool InstantiateClassFromEltDeclaration(XSElementDeclaration* poEltDecl,
+                                                XSModel* poModel,
+                                                bool& bError);
+        void CreateNonNestedRelationship(
+                        XSElementDeclaration* poElt,
+                        std::vector<XSElementDeclaration*>& apoSubEltList,
+                        GMLASFeatureClass& oClass,
+                        int nMaxOccurs,
+                        bool bEltNameWillNeedPrefix,
+                        bool bForceJunctionTable,
+                        bool bCaseOfConstraintChildren);
+
+        bool IsGMLNamespace(const CPLString& osURI);
+
+        bool DerivesFromGMLFeature(XSElementDeclaration* poEltDecl);
+
+        bool IsIgnoredXPath(const CPLString& osXPath);
+
+        CPLString TruncateIdentifier(const CPLString& osName);
+
+        CPLString AddSerialNumber(const CPLString& osNameIn,
+                                  int iOccurrence,
+                                  size_t nOccurrences);
+
+        void CollectClassesReferences(
+                                GMLASFeatureClass& oClass,
+                                std::vector<GMLASFeatureClass*>& aoClasses );
+
+        CPL_DISALLOW_COPY_ASSIGN(GMLASSchemaAnalyzer)
+
+    public:
+                GMLASSchemaAnalyzer(
+                    GMLASXPathMatcher& oIgnoredXPathMatcher,
+                    GMLASXPathMatcher& oChildrenElementsConstraintsXPathMatcher,
+                    const std::map<CPLString, std::vector<CPLString> >&
+                                                        oMapChildrenElementsConstraints,
+                    GMLASXPathMatcher& oForcedFlattenedXPathMatcher,
+                    GMLASXPathMatcher& oDisabledFlattenedXPathMatcher);
+
+        void SetUseArrays(bool b) { m_bUseArrays = b; }
+        void SetUseNullState(bool b) { m_bUseNullState = b; }
+        void SetInstantiateGMLFeaturesOnly(bool b)
+                                    { m_bInstantiateGMLFeaturesOnly = b; }
+        void SetIdentifierMaxLength(int nLength)
+                                    { m_nIdentifierMaxLength = nLength; }
+        void SetCaseInsensitiveIdentifier(bool b)
+                                    { m_bCaseInsensitiveIdentifier = b; }
+        void SetPGIdentifierLaundering(bool b)
+                                    { m_bPGIdentifierLaundering = b; }
+        void SetMaximumFieldsForFlattening(int n)
+                                    { m_nMaximumFieldsForFlattening = n; }
+
+        bool Analyze(GMLASXSDCache& oCache,
+                     const CPLString& osBaseDirname,
+                     std::vector<PairURIFilename>& aoXSDs,
+                     bool bSchemaFullChecking,
+                     bool bHandleMultipleImports);
+        const std::vector<GMLASFeatureClass>& GetClasses() const
+                { return m_aoClasses; }
+
+        const std::map<CPLString, CPLString>& GetMapURIToPrefix() const
+                    { return m_oMapURIToPrefix; }
+
+        const CPLString& GetGMLVersionFound() const
+                                        { return m_osGMLVersionFound; }
+        const std::set<CPLString>& GetSchemaURLS() const
+                                        { return m_oSetSchemaURLs; }
+
+        static CPLString BuildJunctionTableXPath(const CPLString& osEltXPath,
+                                                 const CPLString& osSubEltXPath)
+                    { return osEltXPath + "|" + osSubEltXPath; }
+};
+
+/************************************************************************/
+/*                           OGRGMLASDataSource                         */
+/************************************************************************/
+
+class OGRGMLASLayer;
+class GMLASReader;
+
+class OGRGMLASDataSource: public GDALDataset
+{
+        std::vector<OGRGMLASLayer*>    m_apoLayers;
+        std::map<CPLString, CPLString> m_oMapURIToPrefix;
+        CPLString                      m_osGMLFilename;
+        OGRLayer                      *m_poFieldsMetadataLayer;
+        OGRLayer                      *m_poLayersMetadataLayer;
+        OGRLayer                      *m_poRelationshipsLayer;
+        OGRLayer                      *m_poOtherMetadataLayer;
+        std::vector<OGRLayer*>         m_apoRequestedMetadataLayers;
+        VSILFILE                      *m_fpGML;
+        VSILFILE                      *m_fpGMLParser;
+        bool                           m_bLayerInitFinished;
+        bool                           m_bSchemaFullChecking;
+        bool                           m_bHandleMultipleImports;
+        bool                           m_bValidate;
+        bool                           m_bRemoveUnusedLayers;
+        bool                           m_bRemoveUnusedFields;
+        bool                           m_bFirstPassDone;
+        /** Map from a SRS name to a boolean indicating if its coordinate
+            order is inverted. */
+        std::map<CPLString, bool>      m_oMapSRSNameToInvertedAxis;
+
+        /** Map from geometry field definition to its expected SRSName */
+        std::map<OGRGeomFieldDefn*, CPLString> m_oMapGeomFieldDefnToSRSName;
+
+        std::vector<PairURIFilename>   m_aoXSDsManuallyPassed;
+
+        GMLASConfiguration             m_oConf;
+
+        /** Schema cache */
+        GMLASXSDCache                  m_oCache;
+
+        GMLASXPathMatcher              m_oIgnoredXPathMatcher;
+
+        GMLASXPathMatcher              m_oChildrenElementsConstraintsXPathMatcher;
+
+        GMLASXPathMatcher              m_oForcedFlattenedXPathMatcher;
+
+        GMLASXPathMatcher              m_oDisabledFlattenedXPathMatcher;
+
+        GMLASSwapCoordinatesEnum       m_eSwapCoordinates;
+
+        /** Base unique identifier */
+        CPLString                      m_osHash;
+
+        vsi_l_offset                   m_nFileSize;
+
+        GMLASReader*                   m_poReader;
+
+        bool                           m_bEndOfReaderLayers;
+
+        int                            m_nCurMetadataLayerIdx;
+
+        GMLASXLinkResolver             m_oXLinkResolver;
+
+        CPLString                      m_osGMLVersionFound;
+
+        bool                           m_bFoundSWE;
+
+        // Pointers are also included in m_apoLayers
+        std::vector<OGRGMLASLayer*>    m_apoSWEDataArrayLayers;
+
+        void TranslateClasses( OGRGMLASLayer* poParentLayer,
+                               const GMLASFeatureClass& oFC );
+
+        bool        RunFirstPassIfNeeded( GMLASReader* poReader,
+                                          GDALProgressFunc pfnProgress,
+                                          void* pProgressData );
+
+        void        FillOtherMetadataLayer(
+                                GDALOpenInfo* poOpenInfo,
+                                const CPLString& osConfigFile,
+                                const std::vector<PairURIFilename>& aoXSDs,
+                                const std::set<CPLString>& oSetSchemaURLs);
+
+        static std::vector<PairURIFilename> BuildXSDVector(
+                                            const CPLString& osXSDFilenames);
+    public:
+        OGRGMLASDataSource();
+        virtual ~OGRGMLASDataSource();
+
+        virtual int         GetLayerCount() override;
+        virtual OGRLayer    *GetLayer(int) override;
+        virtual OGRLayer    *GetLayerByName(const char* pszName) override;
+
+        virtual void        ResetReading() override;
+        virtual OGRFeature* GetNextFeature( OGRLayer** ppoBelongingLayer,
+                                            double* pdfProgressPct,
+                                            GDALProgressFunc pfnProgress,
+                                            void* pProgressData ) override;
+        virtual int TestCapability( const char* ) override;
+
+        bool Open(GDALOpenInfo* poOpenInfo);
+
+        std::vector<OGRGMLASLayer*>*          GetLayers()
+                                            { return &m_apoLayers; }
+        const std::map<CPLString, CPLString>& GetMapURIToPrefix() const
+                                            { return m_oMapURIToPrefix; }
+        const CPLString&                      GetGMLFilename() const
+                                            { return m_osGMLFilename; }
+        const CPLString& GetGMLVersionFound() const
+                                            { return m_osGMLVersionFound; }
+
+        OGRLayer*                             GetFieldsMetadataLayer()
+                                            { return m_poFieldsMetadataLayer; }
+        OGRLayer*                             GetLayersMetadataLayer()
+                                            { return m_poLayersMetadataLayer; }
+        OGRLayer*                             GetRelationshipsLayer()
+                                            { return m_poRelationshipsLayer; }
+        OGRGMLASLayer*          GetLayerByXPath( const CPLString& osXPath );
+
+        GMLASReader*            CreateReader( VSILFILE*& fpGML,
+                                              GDALProgressFunc pfnProgress = NULL,
+                                              void* pProgressData = NULL );
+
+        GMLASXSDCache& GetCache() { return m_oCache; }
+
+        void        PushUnusedGMLFilePointer( VSILFILE* fpGML );
+        VSILFILE   *PopUnusedGMLFilePointer();
+        bool        IsLayerInitFinished() const { return m_bLayerInitFinished; }
+        GMLASSwapCoordinatesEnum GetSwapCoordinates() const
+                                                { return m_eSwapCoordinates; }
+
+        const std::map<CPLString,bool>& GetMapIgnoredXPathToWarn() const {
+                                return m_oConf.m_oMapIgnoredXPathToWarn; }
+        const GMLASXPathMatcher& GetIgnoredXPathMatcher() const
+                                { return  m_oIgnoredXPathMatcher; }
+        const CPLString& GetHash() const { return m_osHash; }
+
+        const GMLASConfiguration& GetConf() const { return m_oConf; }
+        const std::vector<PairURIFilename>& GetXSDsManuallyPassed() const {
+                                            return m_aoXSDsManuallyPassed; }
+};
+
+/************************************************************************/
+/*                             OGRGMLASLayer                            */
+/************************************************************************/
+
+class OGRGMLASLayer: public OGRLayer
+{
+        friend class OGRGMLASDataSource;
+
+        OGRGMLASDataSource            *m_poDS;
+        GMLASFeatureClass              m_oFC;
+        bool                           m_bLayerDefnFinalized;
+        OGRFeatureDefn                *m_poFeatureDefn;
+
+        /** Map from XPath to corresponding field index in OGR layer
+            definition */
+        std::map<CPLString, int>       m_oMapFieldXPathToOGRFieldIdx;
+
+        /** Map from XPath to corresponding geometry field index in OGR layer
+            definition */
+        std::map<CPLString, int>       m_oMapFieldXPathToOGRGeomFieldIdx;
+
+        /** Map from a OGR field index to the corresponding field index in
+            m_oFC.GetFields() */
+        std::map<int, int>             m_oMapOGRFieldIdxtoFCFieldIdx;
+        std::map<int, int>             m_oMapOGRGeomFieldIdxtoFCFieldIdx;
+
+        /** Map from XPath to corresponding field index in m_oFC.GetFields() */
+        std::map<CPLString, int>       m_oMapFieldXPathToFCFieldIdx;
+
+        bool                           m_bEOF;
+        GMLASReader                   *m_poReader;
+        VSILFILE                      *m_fpGML;
+        /** OGR field index of the ID field */
+        int                            m_nIDFieldIdx;
+        /** Whether the ID field is generated, or comes from the XML content */
+        bool                           m_bIDFieldIsGenerated;
+        /** Pointer to parent layer */
+        OGRGMLASLayer                 *m_poParentLayer;
+        /** OGR field index of the field that points to the parent ID */
+        int                            m_nParentIDFieldIdx;
+
+        OGRFeature*                    GetNextRawFeature();
+
+        bool                           InitReader();
+
+        void                           SetLayerDefnFinalized(bool bVal)
+                                            { m_bLayerDefnFinalized = bVal; }
+
+    public:
+        OGRGMLASLayer(OGRGMLASDataSource* poDS,
+                      const GMLASFeatureClass& oFC,
+                      OGRGMLASLayer* poParentLayer,
+                      bool bAlwaysGenerateOGRPKId);
+        explicit OGRGMLASLayer(const char* pszLayerName);
+        virtual ~OGRGMLASLayer();
+
+        virtual const char* GetName() override { return GetDescription(); }
+        virtual OGRFeatureDefn* GetLayerDefn() override;
+        virtual void ResetReading() override;
+        virtual OGRFeature* GetNextFeature() override;
+        virtual int TestCapability( const char* ) override { return FALSE; }
+
+        void SetDataSource(OGRGMLASDataSource* poDS) { m_poDS = poDS; }
+
+        void PostInit(bool bIncludeGeometryXML);
+        void ProcessDataRecord(CPLXMLNode* psDataRecord);
+        void CreateCompoundFoldedMappings();
+
+        const GMLASFeatureClass& GetFeatureClass() const { return m_oFC; }
+        int GetOGRFieldIndexFromXPath(const CPLString& osXPath) const;
+        int GetOGRGeomFieldIndexFromXPath(const CPLString& osXPath) const;
+        int GetIDFieldIdx() const { return m_nIDFieldIdx; }
+        bool IsGeneratedIDField() const { return m_bIDFieldIsGenerated; }
+        OGRGMLASLayer* GetParent() { return m_poParentLayer; }
+        int GetParentIDFieldIdx() const { return m_nParentIDFieldIdx; }
+        int GetFCFieldIndexFromOGRFieldIdx(int iOGRFieldIdx) const;
+        int GetFCFieldIndexFromOGRGeomFieldIdx(int iOGRGeomFieldIdx) const;
+        int GetFCFieldIndexFromXPath(const CPLString& osXPath) const;
+
+        bool EvaluateFilter( OGRFeature* poFeature );
+
+        bool RemoveField( int nIdx );
+        void InsertNewField( int nInsertPos,
+                             OGRFieldDefn& oFieldDefn,
+                             const CPLString& osXPath );
+};
+
+/************************************************************************/
+/*                              GMLASReader                             */
+/************************************************************************/
+
+class GMLASReader : public DefaultHandler
+{
+        /** Schema cache */
+        GMLASXSDCache&           m_oCache;
+
+        /** Object to tell if a XPath must be ignored */
+        const GMLASXPathMatcher& m_oIgnoredXPathMatcher;
+
+        /** XLink resolver */
+        GMLASXLinkResolver&         m_oXLinkResolver;
+
+        /** Whether we should stop parsing */
+        bool              m_bParsingError;
+
+        /** Xerces reader object */
+        SAX2XMLReader    *m_poSAXReader;
+
+        /** Token for Xerces */
+        XMLPScanToken     m_oToFill;
+
+        /** File descriptor (not owned by this object) */
+        VSILFILE         *m_fp;
+
+        /** Input source */
+        GMLASInputSource *m_GMLInputSource;
+
+        /** Whether we are at the first iteration */
+        bool              m_bFirstIteration;
+
+        /** Whether we have reached end of file (or an error) */
+        bool              m_bEOF;
+
+        /** Whether GetNextFeature() has been user interrupted (progress cbk) */
+        bool              m_bInterrupted;
+
+        /** Error handler (for Xerces reader) */
+        GMLASErrorHandler m_oErrorHandler;
+
+        /** Map URI namespaces to their prefix */
+        std::map<CPLString, CPLString> m_oMapURIToPrefix;
+
+        /** List of OGR layers */
+        std::vector<OGRGMLASLayer*>* m_papoLayers;
+
+        /** Vector of features ready for consumption */
+        std::vector< std::pair<OGRFeature*, OGRGMLASLayer*> > m_aoFeaturesReady;
+
+        /** OGR field index of the current field */
+        int               m_nCurFieldIdx;
+
+        /** OGR geometry field index of the current field */
+        int               m_nCurGeomFieldIdx;
+
+        /** XML nested level of current field */
+        int               m_nCurFieldLevel;
+
+        /** Whether we should store all content of the current field as XML */
+        bool              m_bIsXMLBlob;
+        bool              m_bIsXMLBlobIncludeUpper;
+
+        /** Content of the current field */
+        CPLString         m_osTextContent;
+
+        /** For list field types, list of content */
+        CPLStringList     m_osTextContentList;
+        /** Estimated memory footprint of m_osTextContentList */
+        size_t            m_nTextContentListEstimatedSize;
+
+        /** Which layer is of interest for the reader, or NULL for all */
+        OGRGMLASLayer    *m_poLayerOfInterest;
+
+        /** Stack of length of split XPath components */
+        std::vector<size_t> m_anStackXPathLength;
+
+        /** Current absolute XPath */
+        CPLString           m_osCurXPath;
+
+        /** Current XPath, relative to top-level feature */
+        CPLString           m_osCurSubXPath;
+
+        /** Current XML nesting level */
+        int                 m_nLevel;
+
+        /** Map layer to global FID */
+        std::map<OGRLayer*, int> m_oMapGlobalCounter;
+
+        /** Parsing context */
+        struct Context
+        {
+            /** XML nesting level */
+            int             m_nLevel;
+
+            /** Current feature */
+            OGRFeature     *m_poFeature;
+
+            /** Layer of m_poFeature */
+            OGRGMLASLayer  *m_poLayer;
+
+            /** Current layer in a repeated group */
+            OGRGMLASLayer  *m_poGroupLayer;
+
+            /** Nesting level of m_poCurGroupLayer */
+            int             m_nGroupLayerLevel;
+
+            /** Index of the last processed OGR field in m_poCurGroupLayer */
+            int             m_nLastFieldIdxGroupLayer;
+
+            /** Map layer to local FID */
+            std::map<OGRLayer*, int> m_oMapCounter;
+
+            /** Current XPath, relative to (current) top-level feature */
+            CPLString       m_osCurSubXPath;
+
+            void Dump() const;
+        };
+
+        /** Current context */
+        Context              m_oCurCtxt;
+
+        /** Stack of saved contexts */
+        std::vector<Context> m_aoStackContext;
+
+        /** Context used in m_apsXMLNodeStack */
+        typedef struct
+        {
+            /** Current node */
+            CPLXMLNode* psNode;
+
+            /** Last child of psNode (for fast append operations) */
+            CPLXMLNode* psLastChild;
+        } NodeLastChild;
+
+        /** Stack of contexts to build XML tree of GML Geometry */
+        std::vector<NodeLastChild> m_apsXMLNodeStack;
+
+        /** Maximum allowed number of XML nesting level */
+        int                  m_nMaxLevel;
+
+        /** Maximum allowed size of XML content in byte */
+        size_t               m_nMaxContentSize;
+
+        /** Map from a SRS name to a boolean indicating if its coordinate
+            order is inverted. */
+        std::map<CPLString, bool>      m_oMapSRSNameToInvertedAxis;
+
+        /** Set of geometry fields with unknown SRS */
+        std::set<OGRGeomFieldDefn*>    m_oSetGeomFieldsWithUnknownSRS;
+
+        /** Map from geometry field definition to its expected SRSName.
+            This is used to know if reprojection must be done */
+        std::map<OGRGeomFieldDefn*, CPLString> m_oMapGeomFieldDefnToSRSName;
+
+        /** Whether this parsing involves schema validation */
+        bool                       m_bValidate;
+
+        /** Entity resolver used during schema validation */
+        GMLASBaseEntityResolver* m_poEntityResolver;
+
+        /** First level from which warnings about ignored XPath should be
+            silent. */
+        int                        m_nLevelSilentIgnoredXPath;
+
+        /** Whether a warning should be emitted when an element or attribute is
+            found in the document parsed, but ignored because of the ignored
+            XPath defined.  */
+        std::map<CPLString, bool> m_oMapIgnoredXPathToWarn;
+
+        /** Policy to decide when to invert coordinates */
+        GMLASSwapCoordinatesEnum       m_eSwapCoordinates;
+
+        /** Initial pass to guess SRS, etc... */
+        bool                        m_bInitialPass;
+
+        /** Whether to process swe:DataArray in a special way */
+        bool                        m_bProcessSWEDataArray;
+
+        /** Depth level of the swe:DataArray element */
+        int                         m_nSWEDataArrayLevel;
+
+        /** Base unique identifier */
+        CPLString                      m_osHash;
+
+        vsi_l_offset                   m_nFileSize;
+
+        bool                           m_bWarnUnexpected;
+
+        /** Map from layer to a map of field XPath to a set of matching
+            URL specific resolution rule index */
+        std::map<OGRGMLASLayer*, std::map<CPLString, std::set<int> > > m_oMapXLinkFields;
+
+        /** Variables that could be local but more efficient to have same
+            persistent, so as to save many memory allocations/deallocations */
+        CPLString                      m_osLocalname;
+        CPLString                      m_osNSUri;
+        CPLString                      m_osNSPrefix;
+        CPLString                      m_osXPath;
+        CPLString                      m_osLayerXPath;
+        CPLString                      m_osAttrNSUri;
+        CPLString                      m_osAttrNSPrefix;
+        CPLString                      m_osAttrLocalName;
+        CPLString                      m_osAttrXPath;
+        CPLString                      m_osAttrValue;
+        CPLString                      m_osText;
+
+        std::vector<OGRGMLASLayer*>    m_apoSWEDataArrayLayers;
+        int                            m_nSWEDataArrayLayerIdx;
+
+        void        SetField( OGRFeature* poFeature,
+                              OGRGMLASLayer* poLayer,
+                              int nAttrIdx,
+                              const CPLString& osAttrValue );
+
+        void        CreateNewFeature(const CPLString& osLocalname);
+
+        void        PushFeatureReady( OGRFeature* poFeature,
+                                      OGRGMLASLayer* poLayer );
+
+        void        PushContext( const Context& oContext );
+        void        PopContext();
+
+        void        BuildXMLBlobStartElement(const CPLString& osXPath,
+                                             const  Attributes& attrs);
+
+        OGRGMLASLayer* GetLayerByXPath( const CPLString& osXPath );
+
+        void        AttachAsLastChild(CPLXMLNode* psNode);
+
+        void        ProcessSWEDataArray(CPLXMLNode* psRoot);
+        void        ProcessGeometry(CPLXMLNode* psRoot);
+
+        void        ProcessAttributes(const Attributes& attrs);
+        void        ProcessXLinkHref( const CPLString& osAttrXPath,
+                                      const CPLString& osAttrValue );
+        void        ExploreXMLDoc( const CPLString& osAttrXPath,
+                                   const GMLASXLinkResolutionConf::URLSpecificResolution& oRule,
+                                   CPLXMLNode* psNode,
+                                   const CPLString& osParentXPath,
+                                   const GMLASXPathMatcher& oMatcher,
+                                   const std::map<CPLString, size_t>& oMapFieldXPathToIdx );
+
+        void        CreateFieldsForURLSpecificRules();
+        void        CreateFieldsForURLSpecificRule(
+                        OGRGMLASLayer* poLayer,
+                        int nFieldIdx,
+                        const CPLString& osFieldXPath,
+                        int& nInsertFieldIdx,
+                        const GMLASXLinkResolutionConf::URLSpecificResolution& oRule );
+
+        bool        FillTextContent() const { return !m_bInitialPass; }
+
+    public:
+                        GMLASReader(GMLASXSDCache& oCache,
+                                    const GMLASXPathMatcher& oIgnoredXPathMatcher,
+                                    GMLASXLinkResolver& oXLinkResolver);
+                        ~GMLASReader();
+
+        bool Init(const char* pszFilename,
+                  VSILFILE* fp,
+                  const std::map<CPLString, CPLString>& oMapURIToPrefix,
+                  std::vector<OGRGMLASLayer*>* papoLayers,
+                  bool bValidate,
+                  const std::vector<PairURIFilename>& aoXSDs,
+                  bool bSchemaFullChecking,
+                  bool bHandleMultipleImports );
+
+        void SetLayerOfInterest( OGRGMLASLayer* poLayer );
+
+        void SetMapIgnoredXPathToWarn(const std::map<CPLString,bool>& oMap)
+                    { m_oMapIgnoredXPathToWarn = oMap; }
+
+        void SetSwapCoordinates(GMLASSwapCoordinatesEnum eVal)
+                                            { m_eSwapCoordinates = eVal; }
+
+        VSILFILE* GetFP() const { return m_fp; }
+
+        const std::map<CPLString, bool>& GetMapSRSNameToInvertedAxis() const
+                                    { return m_oMapSRSNameToInvertedAxis; }
+        void SetMapSRSNameToInvertedAxis( const std::map<CPLString, bool>& oMap )
+                                    { m_oMapSRSNameToInvertedAxis = oMap; }
+
+        const std::map<OGRGeomFieldDefn*, CPLString>& GetMapGeomFieldDefnToSRSName() const
+                                    { return m_oMapGeomFieldDefnToSRSName; }
+        void SetMapGeomFieldDefnToSRSName(const std::map<OGRGeomFieldDefn*, CPLString>& oMap )
+                                    { m_oMapGeomFieldDefnToSRSName = oMap; }
+
+        void SetHash(const CPLString& osHash) { m_osHash = osHash; }
+
+        void SetFileSize(vsi_l_offset nFileSize) { m_nFileSize = nFileSize; }
+
+        OGRFeature* GetNextFeature( OGRGMLASLayer** ppoBelongingLayer = NULL,
+                                    GDALProgressFunc pfnProgress = NULL,
+                                    void* pProgressData = NULL );
+
+        virtual void startElement(
+            const   XMLCh* const    uri,
+            const   XMLCh* const    localname,
+            const   XMLCh* const    qname,
+            const   Attributes& attrs
+        ) override;
+        virtual  void endElement(
+            const   XMLCh* const    uri,
+            const   XMLCh* const    localname,
+            const   XMLCh* const    qname
+        ) override;
+
+        virtual  void characters( const XMLCh *const chars,
+                        const XMLSize_t length ) override;
+
+        bool RunFirstPass(GDALProgressFunc pfnProgress,
+                          void* pProgressData,
+                          bool bRemoveUnusedLayers,
+                          bool bRemoveUnusedFields,
+                          bool bProcessSWEDataArray,
+                          std::set<CPLString>& aoSetRemovedLayerNames);
+
+        static bool LoadXSDInParser( SAX2XMLReader* poParser,
+                                     GMLASXSDCache& oCache,
+                                     GMLASBaseEntityResolver& oXSDEntityResolver,
+                                     const CPLString& osBaseDirname,
+                                     const CPLString& osXSDFilename,
+                                     Grammar** ppoGrammar,
+                                     bool bSchemaFullChecking,
+                                     bool bHandleMultipleImports );
+
+        void SetSWEDataArrayLayers( const std::vector<OGRGMLASLayer*>& ar );
+        const std::vector<OGRGMLASLayer*>& GetSWEDataArrayLayers() const
+            { return m_apoSWEDataArrayLayers; }
+};
+
+#endif // OGR_GMLAS_INCLUDED
diff --git a/ogr/ogrsf_frmts/gmlas/ogr_gmlas_consts.h b/ogr/ogrsf_frmts/gmlas/ogr_gmlas_consts.h
new file mode 100644
index 0000000..9f1014d
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogr_gmlas_consts.h
@@ -0,0 +1,313 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_GMLAS_CONSTS_INCLUDED_REFEFINABLE
+#define OGR_GMLAS_CONSTS_INCLUDED_REFEFINABLE
+
+#ifdef CONSTANT_DEFINITION
+#define STRING_CONST(x,y)    const char* const x = y
+#define BOOL_CONST(x,y)      const bool x = y
+#define INT_CONST(x,y)       const int x = y
+#else
+#define STRING_CONST(x,y)    extern const char* const x;
+#define BOOL_CONST(x,y)      extern const bool x;
+#define INT_CONST(x,y)       extern const int x;
+#endif
+
+namespace GMLASConstants
+{
+    // Note the default values mentioned here should be kept
+    // consistent with what is documented in gmlasconf.xsd
+    BOOL_CONST(DEFAULT_RESOLUTION_ENABLED_DEFAULT, false);
+    BOOL_CONST(ALLOW_REMOTE_DOWNLOAD_DEFAULT, true);
+    BOOL_CONST(CACHE_RESULTS_DEFAULT, false);
+
+    BOOL_CONST(ALLOW_REMOTE_SCHEMA_DOWNLOAD_DEFAULT, true);
+    BOOL_CONST(ALWAYS_GENERATE_OGR_ID_DEFAULT, false);
+    BOOL_CONST(REMOVE_UNUSED_LAYERS_DEFAULT, false);
+    BOOL_CONST(REMOVE_UNUSED_FIELDS_DEFAULT, false);
+    BOOL_CONST(USE_ARRAYS_DEFAULT, true);
+    BOOL_CONST(USE_NULL_STATE_DEFAULT, false);
+    BOOL_CONST(INCLUDE_GEOMETRY_XML_DEFAULT, false);
+    BOOL_CONST(INSTANTIATE_GML_FEATURES_ONLY_DEFAULT, true);
+    BOOL_CONST(ALLOW_XSD_CACHE_DEFAULT, true);
+    BOOL_CONST(SCHEMA_FULL_CHECKING_DEFAULT, true);
+    BOOL_CONST(HANDLE_MULTIPLE_IMPORTS_DEFAULT, false);
+    BOOL_CONST(VALIDATE_DEFAULT, false);
+    BOOL_CONST(FAIL_IF_VALIDATION_ERROR_DEFAULT, false);
+    BOOL_CONST(EXPOSE_METADATA_LAYERS_DEFAULT, false);
+    BOOL_CONST(SWE_PROCESS_DATA_ARRAY_DEFAULT, true);
+    BOOL_CONST(WARN_IF_EXCLUDED_XPATH_FOUND_DEFAULT, true);
+    BOOL_CONST(CASE_INSENSITIVE_IDENTIFIER_DEFAULT, true);
+    BOOL_CONST(PG_IDENTIFIER_LAUNDERING_DEFAULT, true);
+    INT_CONST(MAXIMUM_FIELDS_FLATTENING_DEFAULT, 10);
+    INT_CONST(MIN_VALUE_OF_MAX_IDENTIFIER_LENGTH, 10);
+    INT_CONST(INDENT_SIZE_DEFAULT, 2);
+    INT_CONST(INDENT_SIZE_MIN, 0);
+    INT_CONST(INDENT_SIZE_MAX, 8);
+    INT_CONST(MAX_FILE_SIZE_DEFAULT, 1024 * 1024);
+
+
+    INT_CONST(IDX_COMPOUND_FOLDED, -2);
+
+// Pseudo index to indicate that this xpath is a part of a more detailed
+// xpath that is folded into the main type, hence we shouldn't warn about it
+// to be unexpected
+// Would for example be the case of "element_compound_simplifiable" for :
+//             <xs:element name="element_compound_simplifiable">
+//                <xs:complexType><xs:sequence>
+//                        <xs:element name="subelement" type="xs:string"/>
+//                </xs:sequence></xs:complexType>
+//            </xs:element>
+
+    INT_CONST(MAXOCCURS_UNLIMITED, -2);
+
+    STRING_CONST(szXML_URI, "http://www.w3.org/XML/1998/namespace");
+    STRING_CONST(szXS_URI, "http://www.w3.org/2001/XMLSchema");
+
+    STRING_CONST(szXSI_URI, "http://www.w3.org/2001/XMLSchema-instance");
+    STRING_CONST(szXSI_PREFIX, "xsi");
+    STRING_CONST(szNIL, "nil");
+    STRING_CONST(szAT_XSI_NIL, "@xsi:nil");
+
+    STRING_CONST(szXMLNS_URI, "http://www.w3.org/2000/xmlns/");
+    STRING_CONST(szXMLNS_PREFIX, "xmlns");
+    STRING_CONST(szSCHEMA_LOCATION, "schemaLocation");
+    STRING_CONST(szNO_NAMESPACE_SCHEMA_LOCATION,
+                                                "noNamespaceSchemaLocation");
+
+    STRING_CONST(szXLINK_URI, "http://www.w3.org/1999/xlink");
+    STRING_CONST(szXLINK_PREFIX, "xlink");
+    STRING_CONST(szTYPE, "type");
+    STRING_CONST(szHREF, "href");
+    STRING_CONST(szOWNS, "owns");
+
+    STRING_CONST(szSWE_URI, "http://www.opengis.net/swe/2.0");
+
+    STRING_CONST(szOPENGIS_URL, "http://www.opengis.net/");
+
+    STRING_CONST(szGML_URI, "http://www.opengis.net/gml");
+    STRING_CONST(szGML32_URI, "http://www.opengis.net/gml/3.2");
+    STRING_CONST(szGML_PREFIX, "gml");
+    STRING_CONST(szSRS_NAME, "srsName");
+
+    STRING_CONST(szWFS_URI, "http://www.opengis.net/wfs");
+    STRING_CONST(szWFS20_URI, "http://www.opengis.net/wfs/2.0");
+    STRING_CONST(szWFS_PREFIX, "wfs");
+    STRING_CONST(szWFS20_SCHEMALOCATION,
+                                "http://schemas.opengis.net/wfs/2.0/wfs.xsd");
+    STRING_CONST(szMEMBER, "member");
+
+    STRING_CONST(szOGRGMLAS_URI, "http://gdal.org/ogr/gmlas");
+    STRING_CONST(szOGRGMLAS_PREFIX, "ogr_gmlas");
+
+    STRING_CONST(szOGR_FIELDS_METADATA, "_ogr_fields_metadata");
+    STRING_CONST(szOGR_LAYERS_METADATA, "_ogr_layers_metadata");
+    STRING_CONST(szOGR_LAYER_RELATIONSHIPS, "_ogr_layer_relationships");
+    STRING_CONST(szOGR_OTHER_METADATA, "_ogr_other_metadata");
+
+// Fields of szOGR_FIELDS_METADATA
+    STRING_CONST(szLAYER_NAME, "layer_name");
+    STRING_CONST(szFIELD_INDEX, "field_index");
+    STRING_CONST(szFIELD_NAME, "field_name");
+    STRING_CONST(szFIELD_XPATH, "field_xpath");
+    STRING_CONST(szFIELD_TYPE, "field_type");
+    STRING_CONST(szFIELD_IS_LIST, "field_is_list");
+    STRING_CONST(szFIELD_MIN_OCCURS, "field_min_occurs");
+    STRING_CONST(szFIELD_MAX_OCCURS, "field_max_occurs");
+    STRING_CONST(szFIELD_REPETITION_ON_SEQUENCE, "field_repetition_on_sequence");
+    STRING_CONST(szFIELD_DEFAULT_VALUE, "field_default_value");
+    STRING_CONST(szFIELD_FIXED_VALUE, "field_fixed_value");
+    STRING_CONST(szFIELD_CATEGORY, "field_category");
+    STRING_CONST(szFIELD_RELATED_LAYER, "field_related_layer");
+    STRING_CONST(szFIELD_JUNCTION_LAYER, "field_junction_layer");
+    STRING_CONST(szFIELD_DOCUMENTATION, "field_documentation");
+
+// Fields of szOGR_LAYERS_METADATA
+// szLAYER_NAME
+    STRING_CONST(szLAYER_XPATH, "layer_xpath");
+    STRING_CONST(szLAYER_CATEGORY, "layer_category");
+    STRING_CONST(szLAYER_PKID_NAME, "layer_pkid_name");
+    STRING_CONST(szLAYER_PARENT_PKID_NAME, "layer_parent_pkid_name");
+    STRING_CONST(szLAYER_DOCUMENTATION, "layer_documentation");
+
+// Fields of szOGR_LAYER_RELATIONSHIPS
+    STRING_CONST(szPARENT_LAYER, "parent_layer");
+    STRING_CONST(szPARENT_PKID, "parent_pkid");
+    STRING_CONST(szPARENT_ELEMENT_NAME, "parent_element_name");
+    STRING_CONST(szCHILD_LAYER, "child_layer");
+    STRING_CONST(szCHILD_PKID, "child_pkid");
+
+// Fields of szOGR_OTHER_METADATA
+    STRING_CONST(szKEY, "key");
+    STRING_CONST(szVALUE, "value");
+
+    STRING_CONST(szCONFIGURATION_FILENAME, "configuration_filename");
+    STRING_CONST(szCONFIGURATION_INLINED, "configuration_inlined");
+    STRING_CONST(szDOCUMENT_FILENAME, "document_filename");
+
+    STRING_CONST(szNAMESPACE_URI_FMT, "namespace_uri_%d");
+    STRING_CONST(szNAMESPACE_LOCATION_FMT, "namespace_location_%d");
+    STRING_CONST(szNAMESPACE_PREFIX_FMT, "namespace_prefix_%d");
+    STRING_CONST(szGML_VERSION, "gml_version");
+    STRING_CONST(szSCHEMA_NAME_FMT, "schema_name_%d");
+
+// Fields of a junction table
+    STRING_CONST(szOCCURRENCE, "occurrence");
+// szPARENT_PKID
+// szCHILD_PKID
+
+    STRING_CONST(szOGR_PKID, "ogr_pkid");
+    STRING_CONST(szPKID_SUFFIX, "_pkid");
+    STRING_CONST(szPARENT_PREFIX, "parent_");
+    STRING_CONST(szXML_SUFFIX, "_xml");
+    STRING_CONST(szRAW_CONTENT_SUFFIX, "_rawcontent");
+    STRING_CONST(szAT_XLINK_HREF, "@xlink:href");
+    STRING_CONST(szHREF_SUFFIX, "_href");
+
+// Values of layer_category
+    STRING_CONST(szTOP_LEVEL_ELEMENT, "TOP_LEVEL_ELEMENT");
+    STRING_CONST(szNESTED_ELEMENT, "NESTED_ELEMENT");
+    STRING_CONST(szJUNCTION_TABLE, "JUNCTION_TABLE");
+
+// Values of field_category
+    STRING_CONST(szREGULAR, "REGULAR");
+    STRING_CONST(szPATH_TO_CHILD_ELEMENT_NO_LINK,
+                                    "PATH_TO_CHILD_ELEMENT_NO_LINK");
+    STRING_CONST(szPATH_TO_CHILD_ELEMENT_WITH_LINK,
+                                    "PATH_TO_CHILD_ELEMENT_WITH_LINK");
+    STRING_CONST(szPATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE,
+                                    "PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE");
+    STRING_CONST(szGROUP, "GROUP");
+
+    STRING_CONST(szGMLAS_PREFIX, "GMLAS:");
+    STRING_CONST(szDEFAULT_CONF_FILENAME, "gmlasconf.xml");
+
+// Open options
+    STRING_CONST(szCONFIG_FILE_OPTION, "CONFIG_FILE");
+    STRING_CONST(szXSD_OPTION, "XSD");
+    STRING_CONST(szREFRESH_CACHE_OPTION, "REFRESH_CACHE");
+    STRING_CONST(szEXPOSE_METADATA_LAYERS_OPTION,
+                                                "EXPOSE_METADATA_LAYERS");
+    STRING_CONST(szSWAP_COORDINATES_OPTION, "SWAP_COORDINATES");
+    STRING_CONST(szVALIDATE_OPTION, "VALIDATE");
+    STRING_CONST(szREMOVE_UNUSED_LAYERS_OPTION, "REMOVE_UNUSED_LAYERS");
+    STRING_CONST(szREMOVE_UNUSED_FIELDS_OPTION, "REMOVE_UNUSED_FIELDS");
+    STRING_CONST(szFAIL_IF_VALIDATION_ERROR_OPTION,
+                                                "FAIL_IF_VALIDATION_ERROR");
+    STRING_CONST(szKEEP_RELATIVE_PATHS_FOR_METADATA_OPTION,
+                                        "KEEP_RELATIVE_PATHS_FOR_METADATA");
+    STRING_CONST(szEXPOSE_CONFIGURATION_IN_METADATA_OPTION,
+                                        "EXPOSE_CONFIGURATION_IN_METADATA");
+    STRING_CONST(szEXPOSE_SCHEMAS_NAME_IN_METADATA_OPTION,
+                                        "EXPOSE_SCHEMAS_NAME_IN_METADATA");
+    STRING_CONST(szSCHEMA_FULL_CHECKING_OPTION, "SCHEMA_FULL_CHECKING");
+    STRING_CONST(szHANDLE_MULTIPLE_IMPORTS_OPTION,
+                                            "HANDLE_MULTIPLE_IMPORTS");
+
+// Creation options
+    STRING_CONST(szINPUT_XSD_OPTION, "INPUT_XSD");
+    STRING_CONST(szLAYERS_OPTION, "LAYERS");
+    STRING_CONST(szSRSNAME_FORMAT_OPTION, "SRSNAME_FORMAT");
+    STRING_CONST(szINDENT_SIZE_OPTION, "INDENT_SIZE");
+    STRING_CONST(szCOMMENT_OPTION, "COMMENT");
+    STRING_CONST(szLINEFORMAT_OPTION, "LINEFORMAT");
+    STRING_CONST(szWRAPPING_OPTION, "WRAPPING");
+    STRING_CONST(szTIMESTAMP_OPTION, "TIMESTAMP");
+    STRING_CONST(szWFS20_SCHEMALOCATION_OPTION, "WFS20_SCHEMALOCATION");
+    STRING_CONST(szGENERATE_XSD_OPTION, "GENERATE_XSD");
+    STRING_CONST(szOUTPUT_XSD_FILENAME_OPTION, "OUTPUT_XSD_FILENAME");
+
+// Values for SRSNAME_FORMAT option
+    STRING_CONST(szSHORT, "SHORT");
+    STRING_CONST(szOGC_URN, "OGC_URN");
+    STRING_CONST(szOGC_URL, "OGC_URL");
+    STRING_CONST(szSRSNAME_DEFAULT, "OGC_URL");
+
+// Values for LINEFORMAT option
+    STRING_CONST(szCRLF, "CRLF");
+    STRING_CONST(szLF, "LF");
+
+// Value for WRAPPING option
+    STRING_CONST(szWFS2_FEATURECOLLECTION, "WFS2_FEATURECOLLECTION");
+    STRING_CONST(szGMLAS_FEATURECOLLECTION, "GMLAS_FEATURECOLLECTION");
+
+    STRING_CONST(szFEATURE_COLLECTION, "FeatureCollection");
+    STRING_CONST(szFEATURE_MEMBER, "featureMember");
+
+// XML types
+    STRING_CONST(szXS_STRING, "string");
+    STRING_CONST(szXS_TOKEN, "token");
+    STRING_CONST(szXS_NMTOKEN, "NMTOKEN");
+    STRING_CONST(szXS_NCNAME, "NCName");
+    STRING_CONST(szXS_QNAME, "QName");
+    STRING_CONST(szXS_ID, "ID");
+    STRING_CONST(szXS_BOOLEAN, "boolean");
+    STRING_CONST(szXS_BYTE, "byte");
+    STRING_CONST(szXS_SHORT, "short");
+    STRING_CONST(szXS_INT, "int");
+    STRING_CONST(szXS_LONG, "long");
+    STRING_CONST(szXS_INTEGER, "integer");
+    STRING_CONST(szXS_NEGATIVE_INTEGER, "negativeInteger");
+    STRING_CONST(szXS_NON_NEGATIVE_INTEGER, "nonNegativeInteger");
+    STRING_CONST(szXS_NON_POSITIVE_INTEGER, "nonPositiveInteger");
+    STRING_CONST(szXS_POSITIVE_INTEGER, "positiveInteger");
+    STRING_CONST(szXS_UNSIGNED_BYTE, "unsignedByte");
+    STRING_CONST(szXS_UNSIGNED_SHORT, "unsignedShort");
+    STRING_CONST(szXS_UNSIGNED_INT, "unsignedInt");
+    STRING_CONST(szXS_UNSIGNED_LONG, "unsignedLong");
+    STRING_CONST(szXS_FLOAT, "float");
+    STRING_CONST(szXS_DOUBLE, "double");
+    STRING_CONST(szXS_DECIMAL, "decimal");
+    STRING_CONST(szXS_DATE, "date");
+    STRING_CONST(szXS_TIME, "time");
+    STRING_CONST(szXS_DATETIME, "dateTime");
+    STRING_CONST(szXS_ANY_URI, "anyURI");
+    STRING_CONST(szXS_ANY_TYPE, "anyType");
+    STRING_CONST(szXS_ANY_SIMPLE_TYPE, "anySimpleType");
+    STRING_CONST(szXS_DURATION, "duration");
+    STRING_CONST(szXS_BASE64BINARY, "base64Binary");
+    STRING_CONST(szXS_HEXBINARY, "hexBinary");
+// Extensions to XML types
+    STRING_CONST(szFAKEXS_GEOMETRY, "geometry");
+    STRING_CONST(szFAKEXS_JSON_DICT, "json_dict");
+
+    STRING_CONST(szAT_ANY_ATTR, "@*");
+    STRING_CONST(szMATCH_ALL, "/*");
+    STRING_CONST(szEXTRA_SUFFIX, ";extra=");
+};
+
+#undef STRING_CONST
+#undef INT_CONST
+#undef BOOL_CONST
+
+using namespace GMLASConstants;
+
+#endif // OGR_GMLAS_CONSTS_INCLUDED_REFEFINABLE
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlasconf.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlasconf.cpp
new file mode 100644
index 0000000..a401cc1
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlasconf.cpp
@@ -0,0 +1,674 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+
+#define CONSTANT_DEFINITION
+#undef OGR_GMLAS_CONSTS_INCLUDED_REFEFINABLE
+#include "ogr_gmlas_consts.h"
+
+#include "cpl_minixml.h"
+
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrgmlasconf.cpp 37974 2017-04-12 16:16:55Z rouault $");
+
+/************************************************************************/
+/*                          GMLASConfiguration()                        */
+/************************************************************************/
+
+GMLASConfiguration::GMLASConfiguration()
+    : m_bAllowRemoteSchemaDownload(ALLOW_REMOTE_SCHEMA_DOWNLOAD_DEFAULT)
+    , m_bAlwaysGenerateOGRId(ALWAYS_GENERATE_OGR_ID_DEFAULT)
+    , m_bRemoveUnusedLayers(REMOVE_UNUSED_LAYERS_DEFAULT)
+    , m_bRemoveUnusedFields(REMOVE_UNUSED_FIELDS_DEFAULT)
+    , m_bUseArrays(USE_ARRAYS_DEFAULT)
+    , m_bUseNullState(USE_NULL_STATE_DEFAULT)
+    , m_bIncludeGeometryXML(INCLUDE_GEOMETRY_XML_DEFAULT)
+    , m_bInstantiateGMLFeaturesOnly(INSTANTIATE_GML_FEATURES_ONLY_DEFAULT)
+    , m_nIdentifierMaxLength(0)
+    , m_bCaseInsensitiveIdentifier(CASE_INSENSITIVE_IDENTIFIER_DEFAULT)
+    , m_bPGIdentifierLaundering(PG_IDENTIFIER_LAUNDERING_DEFAULT)
+    , m_nMaximumFieldsForFlattening(MAXIMUM_FIELDS_FLATTENING_DEFAULT)
+    , m_bAllowXSDCache(ALLOW_XSD_CACHE_DEFAULT)
+    , m_bSchemaFullChecking(SCHEMA_FULL_CHECKING_DEFAULT)
+    , m_bHandleMultipleImports(HANDLE_MULTIPLE_IMPORTS_DEFAULT)
+    , m_bValidate(VALIDATE_DEFAULT)
+    , m_bFailIfValidationError(FAIL_IF_VALIDATION_ERROR_DEFAULT)
+    , m_bExposeMetadataLayers(WARN_IF_EXCLUDED_XPATH_FOUND_DEFAULT)
+    , m_eSWEActivationMode(SWE_ACTIVATE_IF_NAMESPACE_FOUND)
+    , m_bSWEProcessDataArray(SWE_PROCESS_DATA_ARRAY_DEFAULT)
+    , m_nIndentSize(INDENT_SIZE_DEFAULT)
+    , m_osSRSNameFormat(szSRSNAME_DEFAULT)
+    , m_osWrapping(szWFS2_FEATURECOLLECTION)
+    , m_osWFS20SchemaLocation(szWFS20_SCHEMALOCATION)
+{
+}
+
+/************************************************************************/
+/*                         ~GMLASConfiguration()                        */
+/************************************************************************/
+
+GMLASConfiguration::~GMLASConfiguration()
+{
+}
+
+/************************************************************************/
+/*                        GetBaseCacheDirectory()                       */
+/************************************************************************/
+
+CPLString GMLASConfiguration::GetBaseCacheDirectory()
+{
+#ifdef WIN32
+    const char* pszHome = CPLGetConfigOption("USERPROFILE", NULL);
+#else
+    const char* pszHome = CPLGetConfigOption("HOME", NULL);
+#endif
+    if( pszHome != NULL )
+    {
+        return CPLFormFilename( pszHome, ".gdal", NULL) ;
+    }
+    else
+    {
+        const char *pszDir = CPLGetConfigOption( "CPL_TMPDIR", NULL );
+
+        if( pszDir == NULL )
+            pszDir = CPLGetConfigOption( "TMPDIR", NULL );
+
+        if( pszDir == NULL )
+            pszDir = CPLGetConfigOption( "TEMP", NULL );
+
+        const char* pszUsername = CPLGetConfigOption("USERNAME", NULL);
+        if( pszUsername == NULL )
+            pszUsername = CPLGetConfigOption("USER", NULL);
+
+        if( pszDir != NULL && pszUsername != NULL )
+        {
+            return CPLFormFilename( pszDir,
+                    CPLSPrintf(".gdal_%s", pszUsername), NULL) ;
+        }
+    }
+    return CPLString();
+}
+
+/************************************************************************/
+/*                              Finalize()                              */
+/************************************************************************/
+
+void GMLASConfiguration::Finalize()
+{
+    if( m_bAllowXSDCache && m_osXSDCacheDirectory.empty() )
+    {
+        m_osXSDCacheDirectory = GetBaseCacheDirectory();
+        if( m_osXSDCacheDirectory.empty() )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                    "Could not determine a directory for GMLAS XSD cache");
+        }
+        else
+        {
+            m_osXSDCacheDirectory = CPLFormFilename( m_osXSDCacheDirectory,
+                                                  "gmlas_xsd_cache", NULL) ;
+            CPLDebug("GMLAS", "XSD cache directory: %s",
+                     m_osXSDCacheDirectory.c_str());
+        }
+    }
+}
+
+/************************************************************************/
+/*                          CPLGetXMLBoolValue()                        */
+/************************************************************************/
+
+static bool CPLGetXMLBoolValue(CPLXMLNode* psNode,
+                               const char* pszKey,
+                               bool bDefault)
+{
+    const char* pszVal = CPLGetXMLValue(psNode, pszKey, NULL);
+    if( pszVal )
+        return CPLTestBool(pszVal);
+    else
+        return bDefault;
+}
+
+/************************************************************************/
+/*                            IsValidXPath()                            */
+/************************************************************************/
+
+static bool IsValidXPath(const CPLString& osXPath )
+{
+    // Check that the XPath syntax belongs to the subset we
+    // understand
+    bool bOK = !osXPath.empty();
+    for(size_t i = 0; i < osXPath.size(); ++i )
+    {
+        const char chCur = osXPath[i];
+        if( chCur == '/' )
+        {
+            // OK
+        }
+        else if( chCur == '@' &&
+                 (i == 0 || osXPath[i-1] == '/') &&
+                 i < osXPath.size()-1 &&
+                 isalpha( static_cast<int>(osXPath[i+1]) ) )
+        {
+            // OK
+        }
+        else if( chCur == '_' ||
+                    isalpha( static_cast<int>(chCur) ) )
+        {
+            // OK
+        }
+        else if( isdigit( static_cast<int>(chCur) ) &&
+                    i > 0 &&
+                    (isalnum( static_cast<int>(osXPath[i-1]) ) ||
+                    osXPath[i-1] == '_') )
+        {
+            // OK
+        }
+        else if( chCur == ':' &&
+                 i > 0 &&
+                 (isalnum( static_cast<int>(osXPath[i-1]) ) ||
+                  osXPath[i-1] == '_') &&
+                 i < osXPath.size()-1 &&
+                 isalpha( static_cast<int>(osXPath[i+1]) ) )
+        {
+            // OK
+        }
+        else
+        {
+            bOK = false;
+            break;
+        }
+    }
+    return bOK;
+}
+
+/************************************************************************/
+/*                    GMLASConfigurationErrorHandler()                  */
+/************************************************************************/
+
+static void CPL_STDCALL GMLASConfigurationErrorHandler(CPLErr /*eErr*/,
+                                                       CPLErrorNum /*nType*/,
+                                                       const char* pszMsg)
+{
+    std::vector<CPLString>* paosErrors =
+            (std::vector<CPLString>* )CPLGetErrorHandlerUserData();
+    paosErrors->push_back(pszMsg);
+}
+
+/************************************************************************/
+/*                           ParseNamespaces()                          */
+/************************************************************************/
+
+static void ParseNamespaces(CPLXMLNode* psContainerNode,
+                            std::map<CPLString, CPLString>& oMap)
+{
+    CPLXMLNode* psNamespaces = CPLGetXMLNode(psContainerNode, "Namespaces");
+    if( psNamespaces != NULL )
+    {
+        for( CPLXMLNode* psIter = psNamespaces->psChild;
+                            psIter != NULL;
+                            psIter = psIter->psNext )
+        {
+            if( psIter->eType == CXT_Element &&
+                EQUAL(psIter->pszValue, "Namespace") )
+            {
+                CPLString osPrefix = CPLGetXMLValue(psIter, "prefix", "");
+                CPLString osURI = CPLGetXMLValue(psIter, "uri", "");
+                if( !osPrefix.empty() && !osURI.empty() )
+                {
+                    if( oMap.find(osPrefix) ==
+                        oMap.end() )
+                    {
+                        oMap[osPrefix] = osURI;
+                    }
+                    else
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                    "Prefix %s was already mapped to %s. "
+                                    "Attempt to map it to %s ignored",
+                                    osPrefix.c_str(),
+                                    oMap[osPrefix].
+                                                                    c_str(),
+                                    osURI.c_str());
+                    }
+                }
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                                 Load()                               */
+/************************************************************************/
+
+bool GMLASConfiguration::Load(const char* pszFilename)
+{
+    // Allow configuration to be inlined
+    CPLXMLNode* psRoot = STARTS_WITH(pszFilename, "<Configuration") ?
+                                CPLParseXMLString(pszFilename) :
+                                CPLParseXMLFile(pszFilename);
+    if( psRoot == NULL )
+    {
+        Finalize();
+        return false;
+    }
+    CPLXMLTreeCloser oCloser(psRoot);
+
+    // Validate the configuration file
+    if( CPLTestBool(CPLGetConfigOption("GDAL_XML_VALIDATION", "YES")) )
+    {
+        const char* pszXSD = CPLFindFile( "gdal", "gmlasconf.xsd" );
+        if( pszXSD != NULL )
+        {
+            std::vector<CPLString> aosErrors;
+            const CPLErr eErrClass = CPLGetLastErrorType();
+            const CPLErrorNum nErrNum = CPLGetLastErrorNo();
+            const CPLString osErrMsg = CPLGetLastErrorMsg();
+            CPLPushErrorHandlerEx(GMLASConfigurationErrorHandler, &aosErrors);
+            int bRet = CPLValidateXML(pszFilename, pszXSD, NULL);
+            CPLPopErrorHandler();
+            if( !bRet && !aosErrors.empty() &&
+                strstr(aosErrors[0].c_str(), "missing libxml2 support") == NULL )
+            {
+                for(size_t i = 0; i < aosErrors.size(); i++)
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "%s", aosErrors[i].c_str());
+                }
+            }
+            else
+            {
+                CPLErrorSetState(eErrClass, nErrNum, osErrMsg);
+            }
+        }
+    }
+
+    m_bAllowRemoteSchemaDownload = CPLGetXMLBoolValue(psRoot,
+                                "=Configuration.AllowRemoteSchemaDownload",
+                                ALLOW_REMOTE_SCHEMA_DOWNLOAD_DEFAULT );
+
+    m_bAllowXSDCache = CPLGetXMLBoolValue( psRoot,
+                                           "=Configuration.SchemaCache.enabled",
+                                           ALLOW_XSD_CACHE_DEFAULT );
+    if( m_bAllowXSDCache )
+    {
+        m_osXSDCacheDirectory =
+            CPLGetXMLValue(psRoot, "=Configuration.SchemaCache.Directory",
+                           "");
+    }
+
+    m_bSchemaFullChecking = CPLGetXMLBoolValue( psRoot,
+                    "=Configuration.SchemaAnalysisOptions.SchemaFullChecking",
+                    SCHEMA_FULL_CHECKING_DEFAULT);
+
+    m_bHandleMultipleImports = CPLGetXMLBoolValue( psRoot,
+                    "=Configuration.SchemaAnalysisOptions.HandleMultipleImports",
+                    HANDLE_MULTIPLE_IMPORTS_DEFAULT);
+
+    m_bValidate = CPLGetXMLBoolValue( psRoot,
+                                      "=Configuration.Validation.enabled",
+                                      VALIDATE_DEFAULT );
+
+    if( m_bValidate )
+    {
+        m_bFailIfValidationError = CPLGetXMLBoolValue(psRoot,
+                                        "=Configuration.Validation.FailIfError",
+                                        FAIL_IF_VALIDATION_ERROR_DEFAULT );
+    }
+
+    m_bExposeMetadataLayers = CPLGetXMLBoolValue( psRoot,
+                                      "=Configuration.ExposeMetadataLayers",
+                                      EXPOSE_METADATA_LAYERS_DEFAULT );
+
+    m_bAlwaysGenerateOGRId = CPLGetXMLBoolValue( psRoot,
+                                "=Configuration.LayerBuildingRules.AlwaysGenerateOGRId",
+                                ALWAYS_GENERATE_OGR_ID_DEFAULT );
+
+    m_bRemoveUnusedLayers = CPLGetXMLBoolValue( psRoot,
+                                "=Configuration.LayerBuildingRules.RemoveUnusedLayers",
+                                REMOVE_UNUSED_LAYERS_DEFAULT );
+
+    m_bRemoveUnusedFields = CPLGetXMLBoolValue( psRoot,
+                                "=Configuration.LayerBuildingRules.RemoveUnusedFields",
+                                REMOVE_UNUSED_FIELDS_DEFAULT );
+
+    m_bUseArrays = CPLGetXMLBoolValue( psRoot,
+                                "=Configuration.LayerBuildingRules.UseArrays",
+                                USE_ARRAYS_DEFAULT );
+    m_bUseNullState = CPLGetXMLBoolValue( psRoot,
+                                "=Configuration.LayerBuildingRules.UseNullState",
+                                USE_NULL_STATE_DEFAULT );
+    m_bIncludeGeometryXML = CPLGetXMLBoolValue( psRoot,
+                       "=Configuration.LayerBuildingRules.GML.IncludeGeometryXML",
+                       INCLUDE_GEOMETRY_XML_DEFAULT );
+    m_bInstantiateGMLFeaturesOnly = CPLGetXMLBoolValue( psRoot,
+                "=Configuration.LayerBuildingRules.GML.InstantiateGMLFeaturesOnly",
+                INSTANTIATE_GML_FEATURES_ONLY_DEFAULT );
+    m_nIdentifierMaxLength = atoi( CPLGetXMLValue( psRoot,
+                "=Configuration.LayerBuildingRules.IdentifierMaxLength",
+                "0" ) );
+    m_bCaseInsensitiveIdentifier = CPLGetXMLBoolValue( psRoot,
+                "=Configuration.LayerBuildingRules.CaseInsensitiveIdentifier",
+                CASE_INSENSITIVE_IDENTIFIER_DEFAULT );
+    m_bPGIdentifierLaundering = CPLGetXMLBoolValue( psRoot,
+                "=Configuration.LayerBuildingRules.PostgreSQLIdentifierLaundering",
+                PG_IDENTIFIER_LAUNDERING_DEFAULT );
+
+    CPLXMLNode* psFlatteningRules = CPLGetXMLNode(psRoot,
+                        "=Configuration.LayerBuildingRules.FlatteningRules");
+    if( psFlatteningRules )
+    {
+        m_nMaximumFieldsForFlattening = atoi( CPLGetXMLValue( psFlatteningRules,
+                "MaximumNumberOfFields",
+                CPLSPrintf("%d", MAXIMUM_FIELDS_FLATTENING_DEFAULT) ) );
+
+        ParseNamespaces(psFlatteningRules, m_oMapPrefixToURIFlatteningRules);
+
+        for( CPLXMLNode* psIter = psFlatteningRules->psChild;
+                         psIter != NULL;
+                         psIter = psIter->psNext )
+        {
+            if( psIter->eType == CXT_Element &&
+                EQUAL(psIter->pszValue, "ForceFlatteningXPath") )
+            {
+                m_osForcedFlattenedXPath.push_back(
+                    CPLGetXMLValue(psIter, "", "") );
+            }
+            else if( psIter->eType == CXT_Element &&
+                     EQUAL(psIter->pszValue, "DisableFlatteningXPath") )
+            {
+                m_osDisabledFlattenedXPath.push_back(
+                    CPLGetXMLValue(psIter, "", "") );
+            }
+        }
+    }
+
+    const char* pszSWEProcessingActivation = CPLGetXMLValue( psRoot,
+        "=Configuration.LayerBuildingRules.SWEProcessing.Activation",
+        "ifSWENamespaceFoundInTopElement" );
+    if( EQUAL(pszSWEProcessingActivation, "ifSWENamespaceFoundInTopElement") )
+        m_eSWEActivationMode = SWE_ACTIVATE_IF_NAMESPACE_FOUND;
+    else if( CPLTestBool(pszSWEProcessingActivation) )
+        m_eSWEActivationMode = SWE_ACTIVATE_TRUE;
+    else
+        m_eSWEActivationMode = SWE_ACTIVATE_FALSE;
+    m_bSWEProcessDataArray = CPLTestBool(CPLGetXMLValue( psRoot,
+        "=Configuration.LayerBuildingRules.SWEProcessing.ProcessDataArray",
+        "true" ));
+
+    CPLXMLNode* psTypingConstraints = CPLGetXMLNode(psRoot,
+                                            "=Configuration.TypingConstraints");
+    if( psTypingConstraints )
+    {
+        ParseNamespaces(psTypingConstraints, m_oMapPrefixToURITypeConstraints);
+
+        for( CPLXMLNode* psIter = psTypingConstraints->psChild;
+                         psIter != NULL;
+                         psIter = psIter->psNext )
+        {
+            if( psIter->eType == CXT_Element &&
+                EQUAL(psIter->pszValue, "ChildConstraint") )
+            {
+                const CPLString& osXPath( CPLGetXMLValue(psIter, "ContainerXPath", "") );
+                CPLXMLNode* psChildrenTypes = CPLGetXMLNode(psIter, "ChildrenElements");
+                if( IsValidXPath(osXPath) )
+                {
+                    for( CPLXMLNode* psIter2 =
+                            psChildrenTypes ? psChildrenTypes->psChild : NULL;
+                                     psIter2 != NULL;
+                                     psIter2 = psIter2->psNext )
+                    {
+                        if( psIter2->eType == CXT_Element &&
+                            EQUAL(psIter2->pszValue, "Element") )
+                        {
+                            m_oMapChildrenElementsConstraints[osXPath].push_back(
+                                CPLGetXMLValue(psIter2, "", "") );
+                        }
+                    }
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "XPath syntax %s not supported",
+                             osXPath.c_str());
+                }
+            }
+        }
+    }
+
+    CPLXMLNode* psIgnoredXPaths = CPLGetXMLNode(psRoot,
+                                            "=Configuration.IgnoredXPaths");
+    if( psIgnoredXPaths )
+    {
+        const bool bGlobalWarnIfIgnoredXPathFound = CPLGetXMLBoolValue(
+                       psIgnoredXPaths,
+                       "WarnIfIgnoredXPathFoundInDocInstance",
+                       WARN_IF_EXCLUDED_XPATH_FOUND_DEFAULT );
+
+        ParseNamespaces(psIgnoredXPaths, m_oMapPrefixToURIIgnoredXPaths);
+
+        for( CPLXMLNode* psIter = psIgnoredXPaths->psChild;
+                         psIter != NULL;
+                         psIter = psIter->psNext )
+        {
+            if( psIter->eType == CXT_Element &&
+                EQUAL(psIter->pszValue, "XPath") )
+            {
+                const CPLString& osXPath( CPLGetXMLValue(psIter, "", "") );
+                if( IsValidXPath(osXPath) )
+                {
+                    m_aosIgnoredXPaths.push_back( osXPath );
+
+                    const bool bWarnIfIgnoredXPathFound = CPLGetXMLBoolValue(
+                                psIter,
+                                "warnIfIgnoredXPathFoundInDocInstance",
+                                bGlobalWarnIfIgnoredXPathFound );
+                    m_oMapIgnoredXPathToWarn[ osXPath ] = bWarnIfIgnoredXPathFound;
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "XPath syntax %s not supported",
+                             osXPath.c_str());
+                }
+            }
+        }
+    }
+
+    CPLXMLNode* psXLinkResolutionNode = CPLGetXMLNode( psRoot,
+                                            "=Configuration.XLinkResolution");
+    if( psXLinkResolutionNode != NULL )
+        m_oXLinkResolution.LoadFromXML( psXLinkResolutionNode );
+
+    // Parse WriterConfig
+    CPLXMLNode* psWriterConfig = CPLGetXMLNode( psRoot,
+                                                "=Configuration.WriterConfig");
+    if( psWriterConfig != NULL )
+    {
+        m_nIndentSize = atoi( CPLGetXMLValue( psWriterConfig,
+                                    "IndentationSize",
+                                    CPLSPrintf("%d", INDENT_SIZE_DEFAULT ) ) );
+        m_nIndentSize = std::min( INDENT_SIZE_MAX,
+                                  std::max( INDENT_SIZE_MIN, m_nIndentSize ) );
+
+        m_osComment = CPLGetXMLValue( psWriterConfig, "Comment", "" );
+
+        m_osLineFormat = CPLGetXMLValue( psWriterConfig, "LineFormat", "" );
+
+        m_osSRSNameFormat = CPLGetXMLValue( psWriterConfig, "SRSNameFormat", "" );
+
+        m_osWrapping = CPLGetXMLValue( psWriterConfig, "Wrapping",
+                                       szWFS2_FEATURECOLLECTION );
+
+        m_osTimestamp = CPLGetXMLValue( psWriterConfig, "Timestamp", "" );
+
+        m_osWFS20SchemaLocation = CPLGetXMLValue( psWriterConfig,
+                                                  "WFS20SchemaLocation",
+                                                  szWFS20_SCHEMALOCATION );
+    }
+
+    Finalize();
+
+    return true;
+}
+
+/************************************************************************/
+/*                         GMLASXLinkResolutionConf()                   */
+/************************************************************************/
+
+GMLASXLinkResolutionConf::GMLASXLinkResolutionConf() :
+    m_nTimeOut(0),
+    m_nMaxFileSize(MAX_FILE_SIZE_DEFAULT),
+    m_nMaxGlobalResolutionTime(0),
+    m_bDefaultResolutionEnabled(DEFAULT_RESOLUTION_ENABLED_DEFAULT),
+    m_bDefaultAllowRemoteDownload(ALLOW_REMOTE_DOWNLOAD_DEFAULT),
+    m_eDefaultResolutionMode(RawContent),
+    m_nDefaultResolutionDepth(1),
+    m_bDefaultCacheResults(CACHE_RESULTS_DEFAULT)
+{
+}
+
+/************************************************************************/
+/*                               LoadFromXML()                          */
+/************************************************************************/
+
+bool GMLASXLinkResolutionConf::LoadFromXML(CPLXMLNode* psRoot)
+{
+    m_nTimeOut = atoi( CPLGetXMLValue( psRoot, "Timeout", "0" ) );
+
+    m_nMaxFileSize = atoi( CPLGetXMLValue( psRoot, "MaxFileSize",
+                                CPLSPrintf("%d", MAX_FILE_SIZE_DEFAULT)) );
+
+    m_nMaxGlobalResolutionTime = atoi(
+                CPLGetXMLValue( psRoot, "MaxGlobalResolutionTime", "0" ) );
+
+    m_osProxyServerPort = CPLGetXMLValue( psRoot, "ProxyServerPort", "" );
+    m_osProxyUserPassword = CPLGetXMLValue( psRoot, "ProxyUserPassword", "" );
+    m_osProxyAuth = CPLGetXMLValue( psRoot, "ProxyAuth", "" );
+
+    m_osCacheDirectory = CPLGetXMLValue( psRoot, "CacheDirectory", "" );
+    if( m_osCacheDirectory.empty() )
+    {
+        m_osCacheDirectory = GMLASConfiguration::GetBaseCacheDirectory();
+        if( !m_osCacheDirectory.empty() )
+        {
+            m_osCacheDirectory = CPLFormFilename( m_osCacheDirectory,
+                                                  "xlink_resolved_cache",
+                                                  NULL );
+        }
+    }
+
+    m_bDefaultResolutionEnabled = CPLGetXMLBoolValue( psRoot,
+                                        "DefaultResolution.enabled",
+                                        DEFAULT_RESOLUTION_ENABLED_DEFAULT);
+
+    m_bDefaultAllowRemoteDownload = CPLGetXMLBoolValue( psRoot,
+                                "DefaultResolution.AllowRemoteDownload",
+                                ALLOW_REMOTE_DOWNLOAD_DEFAULT);
+
+    // TODO when we support other modes
+    // m_eDefaultResolutionMode =
+
+    m_nDefaultResolutionDepth = atoi( CPLGetXMLValue( psRoot,
+                                "DefaultResolution.ResolutionDepth", "1") );
+
+    m_bDefaultCacheResults = CPLGetXMLBoolValue( psRoot,
+                                    "DefaultResolution.CacheResults",
+                                    CACHE_RESULTS_DEFAULT);
+
+    CPLXMLNode* psIterURL = psRoot->psChild;
+    for( ; psIterURL != NULL; psIterURL = psIterURL->psNext )
+    {
+        if( psIterURL->eType == CXT_Element &&
+            strcmp(psIterURL->pszValue, "URLSpecificResolution") == 0 )
+        {
+            GMLASXLinkResolutionConf::URLSpecificResolution oItem;
+            oItem.m_osURLPrefix = CPLGetXMLValue(psIterURL, "URLPrefix", "");
+
+            oItem.m_bAllowRemoteDownload = CPLGetXMLBoolValue( psIterURL,
+                                                "AllowRemoteDownload",
+                                                ALLOW_REMOTE_DOWNLOAD_DEFAULT);
+
+            const char* pszResolutionModel = CPLGetXMLValue(psIterURL,
+                                                "ResolutionMode", "RawContent");
+            if( EQUAL(pszResolutionModel, "RawContent") )
+                oItem.m_eResolutionMode = RawContent;
+            else
+                oItem.m_eResolutionMode = FieldsFromXPath;
+
+            oItem.m_nResolutionDepth = atoi( CPLGetXMLValue( psIterURL,
+                                        "ResolutionDepth", "1") );
+
+            oItem.m_bCacheResults = CPLGetXMLBoolValue( psIterURL,
+                                                        "CacheResults",
+                                                        CACHE_RESULTS_DEFAULT);
+
+            CPLXMLNode* psIter = psIterURL->psChild;
+            for( ; psIter != NULL; psIter = psIter->psNext )
+            {
+                if( psIter->eType == CXT_Element &&
+                    strcmp(psIter->pszValue, "HTTPHeader") == 0 )
+                {
+                    CPLString osName( CPLGetXMLValue(psIter, "Name", "") );
+                    CPLString osValue( CPLGetXMLValue(psIter, "Value", "") );
+                    oItem.m_aosNameValueHTTPHeaders.push_back(
+                            std::pair<CPLString, CPLString>(osName, osValue));
+                }
+                else if( psIter->eType == CXT_Element &&
+                         strcmp(psIter->pszValue, "Field") == 0 )
+                {
+                    URLSpecificResolution::XPathDerivedField oField;
+                    oField.m_osName = CPLGetXMLValue(psIter, "Name", "");
+                    oField.m_osType = CPLGetXMLValue(psIter, "Type", "");
+                    oField.m_osXPath = CPLGetXMLValue(psIter, "XPath", "");
+                    oItem.m_aoFields.push_back( oField );
+                }
+            }
+
+            m_aoURLSpecificRules.push_back( oItem );
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                          URLSpecificResolution()                     */
+/************************************************************************/
+
+GMLASXLinkResolutionConf::URLSpecificResolution::URLSpecificResolution() :
+    m_bAllowRemoteDownload(false),
+    m_eResolutionMode(RawContent),
+    m_nResolutionDepth(1),
+    m_bCacheResults(false)
+{
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlasdatasource.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlasdatasource.cpp
new file mode 100644
index 0000000..92f9fd3
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlasdatasource.cpp
@@ -0,0 +1,1409 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+
+#include "ogr_mem.h"
+#include "cpl_sha256.h"
+
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrgmlasdatasource.cpp 37974 2017-04-12 16:16:55Z rouault $");
+
+/************************************************************************/
+/*                          OGRGMLASDataSource()                        */
+/************************************************************************/
+
+OGRGMLASDataSource::OGRGMLASDataSource()
+{
+    OGRInitializeXerces();
+
+    m_fpGML = NULL;
+    m_fpGMLParser = NULL;
+    m_bLayerInitFinished = false;
+    m_bValidate = false;
+    m_bSchemaFullChecking = false;
+    m_bHandleMultipleImports = false;
+    m_bRemoveUnusedLayers = false;
+    m_bRemoveUnusedFields = false;
+    m_bFirstPassDone = false;
+    m_eSwapCoordinates = GMLAS_SWAP_AUTO;
+    m_nFileSize = 0;
+    m_poReader = NULL;
+    m_bEndOfReaderLayers = false;
+    m_nCurMetadataLayerIdx = -1;
+    m_poFieldsMetadataLayer = new OGRMemLayer
+                                    (szOGR_FIELDS_METADATA, NULL, wkbNone );
+    m_bFoundSWE = false;
+
+    {
+        OGRFieldDefn oFieldDefn(szLAYER_NAME, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_INDEX, OFTInteger);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_NAME, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_XPATH, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_TYPE, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_IS_LIST, OFTInteger);
+        oFieldDefn.SetSubType(OFSTBoolean);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_MIN_OCCURS, OFTInteger);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_MAX_OCCURS, OFTInteger);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_REPETITION_ON_SEQUENCE, OFTInteger);
+        oFieldDefn.SetSubType(OFSTBoolean);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_DEFAULT_VALUE, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_FIXED_VALUE, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_CATEGORY, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_RELATED_LAYER, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_JUNCTION_LAYER, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szFIELD_DOCUMENTATION, OFTString);
+        m_poFieldsMetadataLayer->CreateField(&oFieldDefn);
+    }
+
+    m_poLayersMetadataLayer = new OGRMemLayer
+                                    (szOGR_LAYERS_METADATA, NULL, wkbNone );
+    {
+        OGRFieldDefn oFieldDefn(szLAYER_NAME, OFTString);
+        m_poLayersMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szLAYER_XPATH, OFTString);
+        m_poLayersMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szLAYER_CATEGORY, OFTString);
+        m_poLayersMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szLAYER_PKID_NAME, OFTString);
+        m_poLayersMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szLAYER_PARENT_PKID_NAME, OFTString);
+        m_poLayersMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szLAYER_DOCUMENTATION, OFTString);
+        m_poLayersMetadataLayer->CreateField(&oFieldDefn);
+    }
+
+    m_poRelationshipsLayer = new OGRMemLayer(szOGR_LAYER_RELATIONSHIPS,
+                                             NULL, wkbNone );
+    {
+        OGRFieldDefn oFieldDefn(szPARENT_LAYER, OFTString);
+        m_poRelationshipsLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szPARENT_PKID, OFTString);
+        m_poRelationshipsLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szPARENT_ELEMENT_NAME, OFTString);
+        m_poRelationshipsLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szCHILD_LAYER, OFTString);
+        m_poRelationshipsLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szCHILD_PKID, OFTString);
+        m_poRelationshipsLayer->CreateField(&oFieldDefn);
+    }
+    m_poOtherMetadataLayer = new OGRMemLayer(szOGR_OTHER_METADATA,
+                                             NULL, wkbNone );
+    {
+        OGRFieldDefn oFieldDefn(szKEY, OFTString);
+        m_poOtherMetadataLayer->CreateField(&oFieldDefn);
+    }
+    {
+        OGRFieldDefn oFieldDefn(szVALUE, OFTString);
+        m_poOtherMetadataLayer->CreateField(&oFieldDefn);
+    }
+}
+
+/************************************************************************/
+/*                         ~OGRGMLASDataSource()                        */
+/************************************************************************/
+
+OGRGMLASDataSource::~OGRGMLASDataSource()
+{
+    for(size_t i=0;i<m_apoLayers.size();i++)
+        delete m_apoLayers[i];
+    delete m_poFieldsMetadataLayer;
+    delete m_poLayersMetadataLayer;
+    delete m_poRelationshipsLayer;
+    delete m_poOtherMetadataLayer;
+    if( m_fpGML != NULL )
+        VSIFCloseL(m_fpGML);
+    if( m_fpGMLParser != NULL )
+        VSIFCloseL(m_fpGMLParser);
+    delete m_poReader;
+
+    OGRDeinitializeXerces();
+}
+
+/************************************************************************/
+/*                            GetLayerCount()                           */
+/************************************************************************/
+
+int         OGRGMLASDataSource::GetLayerCount()
+{
+    return static_cast<int>(m_apoLayers.size() + m_apoRequestedMetadataLayers.size());
+}
+
+/************************************************************************/
+/*                                GetLayer()                            */
+/************************************************************************/
+
+OGRLayer    *OGRGMLASDataSource::GetLayer(int i)
+{
+    const int nBaseLayers = static_cast<int>(m_apoLayers.size());
+    if( i >= nBaseLayers )
+    {
+        if( i - nBaseLayers < static_cast<int>(m_apoRequestedMetadataLayers.size()) )
+            return m_apoRequestedMetadataLayers[i - nBaseLayers];
+    }
+
+    if( i < 0 || i >= nBaseLayers )
+        return NULL;
+    return m_apoLayers[i];
+}
+
+/************************************************************************/
+/*                             GetLayerByName()                         */
+/************************************************************************/
+
+OGRLayer    *OGRGMLASDataSource::GetLayerByName(const char* pszName)
+{
+    OGRLayer* poLayer = GDALDataset::GetLayerByName(pszName);
+    if( poLayer )
+        return poLayer;
+
+    OGRLayer* apoLayers[4];
+    apoLayers[0] = m_poFieldsMetadataLayer;
+    apoLayers[1] = m_poLayersMetadataLayer;
+    apoLayers[2] = m_poRelationshipsLayer;
+    apoLayers[3] = m_poOtherMetadataLayer;
+    for( size_t i=0; i < CPL_ARRAYSIZE(apoLayers); ++i)
+    {
+        if( EQUAL(pszName, apoLayers[i]->GetName()) )
+        {
+            if ( std::find(m_apoRequestedMetadataLayers.begin(),
+                        m_apoRequestedMetadataLayers.end(),
+                        apoLayers[i]) == m_apoRequestedMetadataLayers.end() )
+            {
+                m_apoRequestedMetadataLayers.push_back(apoLayers[i]);
+            }
+            return apoLayers[i];
+        }
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                           TranslateClasses()                         */
+/************************************************************************/
+
+void OGRGMLASDataSource::TranslateClasses( OGRGMLASLayer* poParentLayer,
+                                           const GMLASFeatureClass& oFC )
+{
+    const std::vector<GMLASFeatureClass>& aoClasses = oFC.GetNestedClasses();
+
+    //CPLDebug("GMLAS", "TranslateClasses(%s,%s)",
+    //         oFC.GetName().c_str(), oFC.GetXPath().c_str());
+
+    OGRGMLASLayer* poLayer = new OGRGMLASLayer(this, oFC, poParentLayer,
+                                               m_oConf.m_bAlwaysGenerateOGRId);
+    m_apoLayers.push_back(poLayer);
+
+    for( size_t i=0; i<aoClasses.size(); ++i )
+    {
+        TranslateClasses( poLayer, aoClasses[i] );
+    }
+}
+
+/************************************************************************/
+/*                         GMLASTopElementParser                        */
+/************************************************************************/
+
+class GMLASTopElementParser : public DefaultHandler
+{
+            std::vector<PairURIFilename>  m_aoFilenames;
+            int         m_nStartElementCounter;
+            bool        m_bFinish;
+            bool        m_bFoundSWE;
+
+    public:
+                        GMLASTopElementParser();
+
+                        virtual ~GMLASTopElementParser() {}
+
+        void Parse(const CPLString& osFilename, VSILFILE* fp);
+
+        const std::vector<PairURIFilename>& GetXSDs() const
+                                            { return m_aoFilenames; }
+        bool GetSWE() const { return m_bFoundSWE; }
+
+        virtual void startElement(
+            const   XMLCh* const    uri,
+            const   XMLCh* const    localname,
+            const   XMLCh* const    qname,
+            const   Attributes& attrs
+        ) override;
+};
+
+/************************************************************************/
+/*                          GMLASTopElementParser()                     */
+/************************************************************************/
+
+GMLASTopElementParser::GMLASTopElementParser()
+    : m_nStartElementCounter(0),
+        m_bFinish(false), m_bFoundSWE(false)
+{
+}
+
+/************************************************************************/
+/*                               Parse()                                */
+/************************************************************************/
+
+void GMLASTopElementParser::Parse(const CPLString& osFilename, VSILFILE* fp)
+{
+    SAX2XMLReader* poSAXReader = XMLReaderFactory::createXMLReader();
+
+    poSAXReader->setFeature (XMLUni::fgSAX2CoreNameSpaces, true);
+    poSAXReader->setFeature (XMLUni::fgSAX2CoreNameSpacePrefixes, true);
+
+    poSAXReader->setContentHandler( this );
+    poSAXReader->setLexicalHandler( this );
+    poSAXReader->setDTDHandler( this );
+
+    poSAXReader->setFeature (XMLUni::fgXercesLoadSchema, false);
+
+    GMLASErrorHandler oErrorHandler;
+    poSAXReader->setErrorHandler(&oErrorHandler);
+
+    GMLASInputSource* poIS = new GMLASInputSource(osFilename, fp, false);
+
+    try
+    {
+        XMLPScanToken     oToFill;
+        if( poSAXReader->parseFirst( *poIS, oToFill ) )
+        {
+            while( !m_bFinish &&
+                   poSAXReader->parseNext( oToFill ) )
+            {
+                // do nothing
+            }
+        }
+    }
+    catch (const XMLException& toCatch)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                 transcode( toCatch.getMessage() ).c_str() );
+    }
+    catch (const SAXException& toCatch)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                 transcode( toCatch.getMessage() ).c_str() );
+    }
+
+    delete poSAXReader;
+    delete poIS;
+}
+
+/************************************************************************/
+/*                             startElement()                           */
+/************************************************************************/
+
+void GMLASTopElementParser::startElement(
+                            const   XMLCh* const /*uri*/,
+                            const   XMLCh* const /*localname*/,
+                            const   XMLCh* const /*qname*/,
+                            const   Attributes& attrs )
+{
+    m_nStartElementCounter ++;
+
+    for(unsigned int i=0; i < attrs.getLength(); i++)
+    {
+        CPLString osAttrURIPrefix( transcode(attrs.getURI(i)) );
+        CPLString osAttrLocalname( transcode(attrs.getLocalName(i)) );
+        CPLString osAttrValue( transcode(attrs.getValue(i)) );
+
+        if( osAttrURIPrefix == szXSI_URI &&
+            osAttrLocalname == szSCHEMA_LOCATION )
+        {
+            CPLDebug("GMLAS", "%s=%s", szSCHEMA_LOCATION, osAttrValue.c_str());
+
+            char** papszTokens = CSLTokenizeString2(osAttrValue, " ", 0 );
+            int nTokens = CSLCount(papszTokens);
+            if( (nTokens % 2) == 0 )
+            {
+                for( int j = 0; j < nTokens; j+= 2 )
+                {
+                    if( !STARTS_WITH(papszTokens[j], szWFS_URI) &&
+                        !(EQUAL(papszTokens[j], szGML_URI) ||
+                          STARTS_WITH(papszTokens[j],
+                                    (CPLString(szGML_URI)+ "/").c_str())) )
+                    {
+                        CPLDebug("GMLAS", "Schema to analyze: %s -> %s",
+                                 papszTokens[j], papszTokens[j+1]);
+                        m_aoFilenames.push_back( PairURIFilename(
+                            papszTokens[j], papszTokens[j+1]) );
+                    }
+                }
+            }
+            CSLDestroy(papszTokens);
+        }
+        else if( osAttrURIPrefix == szXSI_URI &&
+                 osAttrLocalname == szNO_NAMESPACE_SCHEMA_LOCATION )
+        {
+            CPLDebug("GMLAS", "%s=%s",
+                     szNO_NAMESPACE_SCHEMA_LOCATION, osAttrValue.c_str());
+            m_aoFilenames.push_back( PairURIFilename( "", osAttrValue ) );
+        }
+        else if( osAttrURIPrefix == szXMLNS_URI &&
+                 osAttrValue == szSWE_URI )
+        {
+            CPLDebug("GMLAS", "SWE namespace found");
+            m_bFoundSWE = true;
+        }
+    }
+
+    if( m_nStartElementCounter == 1 )
+        m_bFinish = true;
+}
+
+/************************************************************************/
+/*                         FillOtherMetadataLayer()                     */
+/************************************************************************/
+
+void OGRGMLASDataSource::FillOtherMetadataLayer(
+                                GDALOpenInfo* poOpenInfo,
+                                const CPLString& osConfigFile,
+                                const std::vector<PairURIFilename>& aoXSDs,
+                                const std::set<CPLString>& oSetSchemaURLs)
+{
+    // 2 "secret" options just used for tests
+    const bool bKeepRelativePathsForMetadata =
+        CPLTestBool( CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                            szKEEP_RELATIVE_PATHS_FOR_METADATA_OPTION, "NO") );
+
+    const bool bExposeConfiguration =
+        CPLTestBool( CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                            szEXPOSE_CONFIGURATION_IN_METADATA_OPTION, "YES") );
+
+    const bool bExposeSchemaNames =
+        CPLTestBool( CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                            szEXPOSE_SCHEMAS_NAME_IN_METADATA_OPTION, "YES") );
+
+    OGRFeatureDefn* poFDefn = m_poOtherMetadataLayer->GetLayerDefn();
+
+    if( !osConfigFile.empty() && bExposeConfiguration )
+    {
+        if( STARTS_WITH(osConfigFile, "<Configuration") )
+        {
+            OGRFeature* poFeature = new OGRFeature(poFDefn);
+            poFeature->SetField( szKEY, szCONFIGURATION_INLINED );
+            poFeature->SetField( szVALUE, osConfigFile.c_str());
+            CPL_IGNORE_RET_VAL(
+                            m_poOtherMetadataLayer->CreateFeature(poFeature) );
+            delete poFeature;
+        }
+        else
+        {
+            OGRFeature* poFeature = new OGRFeature(poFDefn);
+            poFeature->SetField( szKEY, szCONFIGURATION_FILENAME );
+            char* pszCurDir = CPLGetCurrentDir();
+            if( !bKeepRelativePathsForMetadata &&
+                CPLIsFilenameRelative(osConfigFile) && pszCurDir != NULL)
+            {
+                poFeature->SetField( szVALUE,
+                                     CPLFormFilename(pszCurDir,
+                                                     osConfigFile, NULL));
+            }
+            else
+            {
+                poFeature->SetField( szVALUE, osConfigFile.c_str());
+            }
+            CPLFree(pszCurDir);
+            CPL_IGNORE_RET_VAL(
+                            m_poOtherMetadataLayer->CreateFeature(poFeature) );
+            delete poFeature;
+
+            GByte* pabyRet = NULL;
+            if( VSIIngestFile( NULL, osConfigFile, &pabyRet, NULL, -1 ) )
+            {
+                poFeature = new OGRFeature(poFDefn);
+                poFeature->SetField( szKEY, szCONFIGURATION_INLINED );
+                poFeature->SetField( szVALUE, reinterpret_cast<char*>(pabyRet));
+                CPL_IGNORE_RET_VAL(
+                            m_poOtherMetadataLayer->CreateFeature(poFeature) );
+                delete poFeature;
+            }
+            VSIFree(pabyRet);
+        }
+    }
+
+    const char* const apszMeaningfulOptionsToStoreInMD[] =
+    {
+        szSWAP_COORDINATES_OPTION,
+        szREMOVE_UNUSED_LAYERS_OPTION,
+        szREMOVE_UNUSED_FIELDS_OPTION
+    };
+    for( size_t i=0; i < CPL_ARRAYSIZE(apszMeaningfulOptionsToStoreInMD); ++i )
+    {
+        const char* pszKey = apszMeaningfulOptionsToStoreInMD[i];
+        const char* pszVal = CSLFetchNameValue(poOpenInfo->papszOpenOptions,
+                                               pszKey);
+        if( pszVal )
+        {
+            OGRFeature* poFeature = new OGRFeature(
+                                        poFDefn);
+            poFeature->SetField( szKEY, pszKey );
+            poFeature->SetField( szVALUE, pszVal );
+            CPL_IGNORE_RET_VAL(
+                            m_poOtherMetadataLayer->CreateFeature(poFeature) );
+            delete poFeature;
+        }
+    }
+
+    CPLString osAbsoluteGMLFilename;
+    if( !m_osGMLFilename.empty() )
+    {
+        OGRFeature* poFeature = new OGRFeature(poFDefn);
+        poFeature->SetField( szKEY, szDOCUMENT_FILENAME );
+        char* pszCurDir = CPLGetCurrentDir();
+        if( !bKeepRelativePathsForMetadata &&
+            CPLIsFilenameRelative(m_osGMLFilename) && pszCurDir != NULL)
+        {
+            osAbsoluteGMLFilename = CPLFormFilename(pszCurDir,
+                                                    m_osGMLFilename, NULL);
+        }
+        else
+            osAbsoluteGMLFilename = m_osGMLFilename;
+        poFeature->SetField( szVALUE, osAbsoluteGMLFilename.c_str() );
+        CPLFree(pszCurDir);
+        CPL_IGNORE_RET_VAL( m_poOtherMetadataLayer->CreateFeature(poFeature) );
+        delete poFeature;
+    }
+
+    int nNSIdx = 1;
+    std::set<CPLString> oSetVisitedURI;
+    for( int i = 0; i < static_cast<int>(aoXSDs.size()); i++ )
+    {
+        const CPLString osURI(aoXSDs[i].first);
+        const CPLString osXSDFilename(aoXSDs[i].second);
+
+        oSetVisitedURI.insert(osURI);
+
+        if( osURI == szOGRGMLAS_URI )
+            continue;
+
+        OGRFeature* poFeature = new OGRFeature(poFDefn);
+        poFeature->SetField( szKEY, CPLSPrintf(szNAMESPACE_URI_FMT, nNSIdx) );
+        poFeature->SetField( szVALUE, osURI.c_str());
+        CPL_IGNORE_RET_VAL( m_poOtherMetadataLayer->CreateFeature(poFeature) );
+        delete poFeature;
+
+        poFeature = new OGRFeature(poFDefn);
+        poFeature->SetField( szKEY,
+                             CPLSPrintf(szNAMESPACE_LOCATION_FMT, nNSIdx) );
+
+        const CPLString osAbsoluteXSDFilename(
+            (osXSDFilename.find("http://") != 0 &&
+             osXSDFilename.find("https://") != 0 &&
+             CPLIsFilenameRelative(osXSDFilename)) ?
+                CPLString(CPLFormFilename(CPLGetDirname(osAbsoluteGMLFilename),
+                                        osXSDFilename, NULL)) :
+                osXSDFilename );
+        poFeature->SetField( szVALUE, osAbsoluteXSDFilename.c_str());
+        CPL_IGNORE_RET_VAL( m_poOtherMetadataLayer->CreateFeature(poFeature) );
+        delete poFeature;
+
+        if( m_oMapURIToPrefix.find(osURI) != m_oMapURIToPrefix.end() )
+        {
+            poFeature = new OGRFeature(poFDefn);
+            poFeature->SetField( szKEY,
+                                 CPLSPrintf(szNAMESPACE_PREFIX_FMT, nNSIdx) );
+            poFeature->SetField( szVALUE, m_oMapURIToPrefix[osURI].c_str());
+            CPL_IGNORE_RET_VAL(
+                            m_poOtherMetadataLayer->CreateFeature(poFeature) );
+            delete poFeature;
+        }
+
+        nNSIdx ++;
+    }
+
+    std::map<CPLString,CPLString>::const_iterator oIter =
+                                                m_oMapURIToPrefix.begin();
+    for( ; oIter != m_oMapURIToPrefix.end(); ++oIter )
+    {
+        const CPLString& osURI( oIter->first );
+        const CPLString& osPrefix( oIter->second );
+
+        if( oSetVisitedURI.find( osURI ) == oSetVisitedURI.end() &&
+            osURI != szXML_URI &&
+            osURI != szXS_URI &&
+            osURI != szXSI_URI &&
+            osURI != szXMLNS_URI &&
+            osURI != szOGRGMLAS_URI )
+        {
+            OGRFeature* poFeature = new OGRFeature(poFDefn);
+            poFeature->SetField( szKEY,
+                                 CPLSPrintf(szNAMESPACE_URI_FMT, nNSIdx) );
+            poFeature->SetField( szVALUE, osURI.c_str());
+            CPL_IGNORE_RET_VAL(
+                            m_poOtherMetadataLayer->CreateFeature(poFeature) );
+            delete poFeature;
+
+            poFeature = new OGRFeature(poFDefn);
+            poFeature->SetField( szKEY,
+                                 CPLSPrintf(szNAMESPACE_PREFIX_FMT, nNSIdx) );
+            poFeature->SetField( szVALUE, osPrefix.c_str());
+            CPL_IGNORE_RET_VAL(
+                            m_poOtherMetadataLayer->CreateFeature(poFeature) );
+            delete poFeature;
+
+            nNSIdx ++;
+        }
+    }
+
+    if( !m_osGMLVersionFound.empty() )
+    {
+        OGRFeature* poFeature = new OGRFeature(poFDefn);
+        poFeature->SetField( szKEY, szGML_VERSION );
+        poFeature->SetField( szVALUE, m_osGMLVersionFound );
+        CPL_IGNORE_RET_VAL( m_poOtherMetadataLayer->CreateFeature(poFeature) );
+        delete poFeature;
+    }
+
+    std::set<CPLString>::const_iterator oIterSet = oSetSchemaURLs.begin();
+    int nSchemaIdx = 1;
+    for( ; bExposeSchemaNames &&
+           oIterSet != oSetSchemaURLs.end(); ++oIterSet )
+    {
+        OGRFeature* poFeature = new OGRFeature(poFDefn);
+        poFeature->SetField( szKEY, CPLSPrintf(szSCHEMA_NAME_FMT, nSchemaIdx) );
+        poFeature->SetField( szVALUE, (*oIterSet).c_str() );
+        CPL_IGNORE_RET_VAL( m_poOtherMetadataLayer->CreateFeature(poFeature) );
+        delete poFeature;
+
+        nSchemaIdx ++;
+    }
+}
+
+/************************************************************************/
+/*                         BuildXSDVector()                             */
+/************************************************************************/
+
+std::vector<PairURIFilename> OGRGMLASDataSource::BuildXSDVector(
+                                            const CPLString& osXSDFilenames)
+{
+    std::vector<PairURIFilename> aoXSDs;
+    char** papszTokens = CSLTokenizeString2(osXSDFilenames," ,",0);
+    char* pszCurDir = CPLGetCurrentDir();
+    for( int i=0; papszTokens != NULL && papszTokens[i] != NULL; i++ )
+    {
+        if( !STARTS_WITH(papszTokens[i], "http://") &&
+            !STARTS_WITH(papszTokens[i], "https://") &&
+            CPLIsFilenameRelative(papszTokens[i]) &&
+            pszCurDir != NULL )
+        {
+            aoXSDs.push_back(PairURIFilename("",
+                        CPLFormFilename(pszCurDir, papszTokens[i], NULL)));
+        }
+        else
+        {
+            aoXSDs.push_back(PairURIFilename("",papszTokens[i]));
+        }
+    }
+    CPLFree(pszCurDir);
+    CSLDestroy(papszTokens);
+    return aoXSDs;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+bool OGRGMLASDataSource::Open(GDALOpenInfo* poOpenInfo)
+{
+    CPLString osConfigFile = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                                                  szCONFIG_FILE_OPTION, "");
+    if( osConfigFile.empty() )
+    {
+        const char* pszConfigFile = CPLFindFile("gdal",
+                                                szDEFAULT_CONF_FILENAME);
+        if( pszConfigFile )
+            osConfigFile = pszConfigFile;
+    }
+    if( osConfigFile.empty() )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "No configuration file found. Using hard-coded defaults");
+        m_oConf.Finalize();
+    }
+    else
+    {
+        if( !m_oConf.Load(osConfigFile) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Loading of configuration failed");
+            return false;
+        }
+    }
+
+    m_oCache.SetCacheDirectory( m_oConf.m_osXSDCacheDirectory );
+    const bool bRefreshCache(CPLTestBool(
+                       CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                                            szREFRESH_CACHE_OPTION, "NO") ));
+    m_oCache.SetRefreshMode( bRefreshCache );
+    m_oCache.SetAllowDownload( m_oConf.m_bAllowRemoteSchemaDownload );
+
+    m_oIgnoredXPathMatcher.SetRefXPaths(
+                                    m_oConf.m_oMapPrefixToURIIgnoredXPaths,
+                                    m_oConf.m_aosIgnoredXPaths );
+
+    {
+        std::map<CPLString, std::vector<CPLString> >::const_iterator oIter =
+                            m_oConf.m_oMapChildrenElementsConstraints.begin();
+        std::vector<CPLString> oVector;
+        for( ; oIter != m_oConf.m_oMapChildrenElementsConstraints.end(); ++oIter )
+            oVector.push_back(oIter->first);
+        m_oChildrenElementsConstraintsXPathMatcher.SetRefXPaths(
+            m_oConf.m_oMapPrefixToURITypeConstraints,
+            oVector );
+    }
+
+    m_oForcedFlattenedXPathMatcher.SetRefXPaths(
+                                  m_oConf.m_oMapPrefixToURIFlatteningRules,
+                                  m_oConf.m_osForcedFlattenedXPath);
+
+    m_oDisabledFlattenedXPathMatcher.SetRefXPaths(
+                                  m_oConf.m_oMapPrefixToURIFlatteningRules,
+                                  m_oConf.m_osDisabledFlattenedXPath);
+
+    GMLASSchemaAnalyzer oAnalyzer(m_oIgnoredXPathMatcher,
+                                  m_oChildrenElementsConstraintsXPathMatcher,
+                                  m_oConf.m_oMapChildrenElementsConstraints,
+                                  m_oForcedFlattenedXPathMatcher,
+                                  m_oDisabledFlattenedXPathMatcher);
+    oAnalyzer.SetUseArrays(m_oConf.m_bUseArrays);
+    oAnalyzer.SetUseNullState(m_oConf.m_bUseNullState);
+    oAnalyzer.SetInstantiateGMLFeaturesOnly(
+                                        m_oConf.m_bInstantiateGMLFeaturesOnly);
+    oAnalyzer.SetIdentifierMaxLength(m_oConf.m_nIdentifierMaxLength);
+    oAnalyzer.SetCaseInsensitiveIdentifier(
+                                        m_oConf.m_bCaseInsensitiveIdentifier);
+    oAnalyzer.SetPGIdentifierLaundering(m_oConf.m_bPGIdentifierLaundering);
+    oAnalyzer.SetMaximumFieldsForFlattening(m_oConf.m_nMaximumFieldsForFlattening);
+
+    m_osGMLFilename = STARTS_WITH_CI(poOpenInfo->pszFilename, szGMLAS_PREFIX) ?
+        CPLExpandTilde(poOpenInfo->pszFilename + strlen(szGMLAS_PREFIX)) :
+        poOpenInfo->pszFilename;
+
+    CPLString osXSDFilenames = CSLFetchNameValueDef(
+                                poOpenInfo->papszOpenOptions, szXSD_OPTION, "");
+
+    VSILFILE* fpGML = NULL;
+    if( !m_osGMLFilename.empty() )
+    {
+        fpGML = VSIFOpenL(m_osGMLFilename, "rb");
+        if( fpGML == NULL )
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "Cannot open %s",
+                     m_osGMLFilename.c_str());
+            return false;
+        }
+    }
+    else if( osXSDFilenames.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s open option must be provided when no "
+                 "XML data file is passed",
+                 szXSD_OPTION);
+        return false;
+    }
+
+    GMLASTopElementParser topElementParser;
+    if( !m_osGMLFilename.empty() )
+    {
+        topElementParser.Parse(m_osGMLFilename, fpGML);
+        if( m_oConf.m_eSWEActivationMode ==
+                        GMLASConfiguration::SWE_ACTIVATE_IF_NAMESPACE_FOUND )
+        {
+            m_bFoundSWE = topElementParser.GetSWE();
+        }
+        else if( m_oConf.m_eSWEActivationMode ==
+                        GMLASConfiguration::SWE_ACTIVATE_TRUE )
+        {
+            m_bFoundSWE = true;
+        }
+    }
+    std::vector<PairURIFilename> aoXSDs;
+    if( osXSDFilenames.empty() )
+    {
+        aoXSDs = topElementParser.GetXSDs();
+    }
+    else
+    {
+        aoXSDs = BuildXSDVector(osXSDFilenames);
+    }
+    if( fpGML )
+    {
+        m_osHash = CSLFetchNameValueDef(
+                                    poOpenInfo->papszOpenOptions, "HASH", "");
+        if( m_osHash.empty() )
+        {
+            VSIFSeekL(fpGML, 0, SEEK_SET);
+            std::string osBuffer;
+            osBuffer.resize(8192);
+            size_t nRead = VSIFReadL(&osBuffer[0], 1, 8192, fpGML);
+            osBuffer.resize(nRead);
+            size_t nPos = osBuffer.find("timeStamp=\"");
+            if( nPos != std::string::npos )
+            {
+                size_t nPos2 = osBuffer.find('"', nPos+strlen("timeStamp=\""));
+                if( nPos2 != std::string::npos )
+                    osBuffer.replace(nPos, nPos2-nPos+1, nPos2-nPos+1, ' ');
+            }
+            CPL_SHA256Context ctxt;
+            CPL_SHA256Init(&ctxt);
+            CPL_SHA256Update(&ctxt, osBuffer.data(), osBuffer.size());
+
+            VSIStatBufL sStat;
+            if( VSIStatL(m_osGMLFilename, &sStat) == 0 )
+            {
+                m_nFileSize = sStat.st_size;
+                CPL_SHA256Update(&ctxt, &(sStat.st_size), sizeof(sStat.st_size));
+            }
+
+            GByte abyHash[CPL_SHA256_HASH_SIZE];
+            CPL_SHA256Final(&ctxt, abyHash);
+            // Half of the hash should be enough for our purpose
+            char* pszHash = CPLBinaryToHex(CPL_SHA256_HASH_SIZE / 2, abyHash);
+            m_osHash = pszHash;
+            CPLFree(pszHash);
+        }
+
+        VSIFSeekL(fpGML, 0, SEEK_SET);
+        PushUnusedGMLFilePointer(fpGML);
+    }
+
+    if( aoXSDs.empty() )
+    {
+        if( osXSDFilenames.empty() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "No schema locations found when analyzing data file: "
+                     "%s open option must be provided",
+                     szXSD_OPTION);
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "No schema locations found");
+        }
+        return false;
+    }
+
+    m_bSchemaFullChecking = CPLFetchBool(
+            poOpenInfo->papszOpenOptions,
+            szSCHEMA_FULL_CHECKING_OPTION,
+            m_oConf.m_bSchemaFullChecking );
+
+    m_bHandleMultipleImports = CPLFetchBool(
+            poOpenInfo->papszOpenOptions,
+            szHANDLE_MULTIPLE_IMPORTS_OPTION,
+            m_oConf.m_bHandleMultipleImports );
+
+    bool bRet = oAnalyzer.Analyze( m_oCache,
+                                   CPLGetDirname(m_osGMLFilename),
+                                   aoXSDs,
+                                   m_bSchemaFullChecking,
+                                   m_bHandleMultipleImports );
+    if( !bRet )
+    {
+        return false;
+    }
+
+    if( !osXSDFilenames.empty() )
+        m_aoXSDsManuallyPassed = aoXSDs;
+
+    m_oMapURIToPrefix = oAnalyzer.GetMapURIToPrefix();
+
+    m_osGMLVersionFound = oAnalyzer.GetGMLVersionFound();
+
+    const std::set<CPLString>& oSetSchemaURLs = oAnalyzer.GetSchemaURLS();
+
+    FillOtherMetadataLayer(poOpenInfo, osConfigFile, aoXSDs, oSetSchemaURLs);
+
+    if( CPLFetchBool(poOpenInfo->papszOpenOptions,
+                     szEXPOSE_METADATA_LAYERS_OPTION,
+                     m_oConf.m_bExposeMetadataLayers) )
+    {
+        m_apoRequestedMetadataLayers.push_back(m_poFieldsMetadataLayer);
+        m_apoRequestedMetadataLayers.push_back(m_poLayersMetadataLayer);
+        m_apoRequestedMetadataLayers.push_back(m_poRelationshipsLayer);
+        m_apoRequestedMetadataLayers.push_back(m_poOtherMetadataLayer);
+    }
+
+    const char* pszSwapCoordinates = CSLFetchNameValueDef(
+                                           poOpenInfo->papszOpenOptions,
+                                           szSWAP_COORDINATES_OPTION,
+                                           "AUTO");
+    if( EQUAL(pszSwapCoordinates, "AUTO") )
+    {
+        m_eSwapCoordinates = GMLAS_SWAP_AUTO;
+    }
+    else if( CPLTestBool(pszSwapCoordinates) )
+    {
+        m_eSwapCoordinates = GMLAS_SWAP_YES;
+    }
+    else
+    {
+        m_eSwapCoordinates = GMLAS_SWAP_NO;
+    }
+
+    const std::vector<GMLASFeatureClass>& aoClasses = oAnalyzer.GetClasses();
+
+    // First "standard" tables
+    for( size_t i=0; i<aoClasses.size(); ++i )
+    {
+        if( aoClasses[i].GetParentXPath().empty() )
+            TranslateClasses( NULL, aoClasses[i] );
+    }
+    // Then junction tables
+    for( size_t i=0; i<aoClasses.size(); ++i )
+    {
+        if( !aoClasses[i].GetParentXPath().empty() )
+            TranslateClasses( NULL, aoClasses[i] );
+    }
+
+    // And now do initialization since we need to have instantiated everything
+    // to be able to do cross-layer links
+    for( size_t i = 0; i < m_apoLayers.size(); i++ )
+    {
+        m_apoLayers[i]->PostInit( m_oConf.m_bIncludeGeometryXML );
+    }
+    m_bLayerInitFinished = true;
+
+    // Do optional validation
+    m_bValidate = CPLFetchBool(poOpenInfo->papszOpenOptions,
+                               szVALIDATE_OPTION,
+                               m_oConf.m_bValidate);
+
+    m_bRemoveUnusedLayers = CPLFetchBool(poOpenInfo->papszOpenOptions,
+                               szREMOVE_UNUSED_LAYERS_OPTION,
+                               m_oConf.m_bRemoveUnusedLayers);
+
+    m_bRemoveUnusedFields = CPLFetchBool(poOpenInfo->papszOpenOptions,
+                               szREMOVE_UNUSED_FIELDS_OPTION,
+                               m_oConf.m_bRemoveUnusedFields);
+
+    m_oXLinkResolver.SetConf( m_oConf.m_oXLinkResolution );
+    m_oXLinkResolver.SetRefreshMode( bRefreshCache );
+
+    if( m_bValidate || m_bRemoveUnusedLayers || m_bFoundSWE )
+    {
+        CPLErrorReset();
+        RunFirstPassIfNeeded( NULL, NULL, NULL );
+        if( CPLFetchBool( poOpenInfo->papszOpenOptions,
+                          szFAIL_IF_VALIDATION_ERROR_OPTION,
+                          m_oConf.m_bFailIfValidationError ) &&
+            CPLGetLastErrorType() != CE_None )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Validation errors encountered");
+            return false;
+        }
+    }
+    if( CPLGetLastErrorType() == CE_Failure )
+        CPLErrorReset();
+
+    return true;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGMLASDataSource::TestCapability( const char * pszCap )
+{
+    return EQUAL(pszCap, ODsCRandomLayerRead);
+}
+
+/************************************************************************/
+/*                           CreateReader()                             */
+/************************************************************************/
+
+GMLASReader* OGRGMLASDataSource::CreateReader( VSILFILE*& fpGML,
+                                               GDALProgressFunc pfnProgress,
+                                               void* pProgressData )
+{
+    if( fpGML == NULL )
+    {
+        // Try recycling an already opened and unused file pointer
+        fpGML = PopUnusedGMLFilePointer();
+        if( fpGML == NULL )
+            fpGML = VSIFOpenL(GetGMLFilename(), "rb");
+        if( fpGML == NULL )
+            return NULL;
+    }
+
+    GMLASReader* poReader = new GMLASReader( GetCache(),
+                                             GetIgnoredXPathMatcher(),
+                                             m_oXLinkResolver );
+    poReader->Init( GetGMLFilename(),
+                      fpGML,
+                      GetMapURIToPrefix(),
+                      GetLayers(),
+                      false,
+                      std::vector<PairURIFilename>(),
+                      m_bSchemaFullChecking,
+                      m_bHandleMultipleImports );
+
+    poReader->SetSwapCoordinates( GetSwapCoordinates() );
+
+    poReader->SetFileSize( m_nFileSize );
+
+    if( !RunFirstPassIfNeeded( poReader, pfnProgress, pProgressData ) )
+    {
+        delete poReader;
+        return NULL;
+    }
+
+    poReader->SetMapIgnoredXPathToWarn( GetMapIgnoredXPathToWarn());
+
+    poReader->SetHash( GetHash() );
+
+    return poReader;
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRGMLASDataSource::ResetReading()
+{
+    delete m_poReader;
+    m_poReader = NULL;
+    for(size_t i=0; i<m_apoRequestedMetadataLayers.size();++i)
+        m_apoRequestedMetadataLayers[i]->ResetReading();
+    m_bEndOfReaderLayers = false;
+    m_nCurMetadataLayerIdx = -1;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature* OGRGMLASDataSource::GetNextFeature( OGRLayer** ppoBelongingLayer,
+                                                double* pdfProgressPct,
+                                                GDALProgressFunc pfnProgress,
+                                                void* pProgressData )
+{
+    if( m_bEndOfReaderLayers )
+    {
+        if( m_nCurMetadataLayerIdx >= 0 &&
+            m_nCurMetadataLayerIdx <
+                    static_cast<int>(m_apoRequestedMetadataLayers.size()) )
+        {
+            while( true )
+            {
+                OGRLayer* poLayer =
+                    m_apoRequestedMetadataLayers[m_nCurMetadataLayerIdx];
+                OGRFeature* poFeature = poLayer->GetNextFeature();
+                if( poFeature != NULL )
+                {
+                    if( pdfProgressPct != NULL )
+                        *pdfProgressPct = 1.0;
+                    if( ppoBelongingLayer != NULL )
+                        *ppoBelongingLayer = poLayer;
+                    return poFeature;
+                }
+                if( m_nCurMetadataLayerIdx + 1
+                     < static_cast<int>(m_apoRequestedMetadataLayers.size()) )
+                {
+                    m_nCurMetadataLayerIdx ++;
+                }
+                else
+                {
+                    m_nCurMetadataLayerIdx = -1;
+                    break;
+                }
+            }
+        }
+
+        if( pdfProgressPct != NULL )
+            *pdfProgressPct = 1.0;
+        if( ppoBelongingLayer != NULL )
+            *ppoBelongingLayer = NULL;
+        return NULL;
+    }
+
+    const double dfInitialScanRatio = 0.1;
+    if( m_poReader == NULL )
+    {
+        void* pScaledProgress = GDALCreateScaledProgress( 0.0, dfInitialScanRatio,
+                                                          pfnProgress,
+                                                          pProgressData );
+
+        m_poReader = CreateReader(m_fpGMLParser,
+                                  pScaledProgress ? GDALScaledProgress : NULL,
+                                  pScaledProgress);
+
+        GDALDestroyScaledProgress(pScaledProgress);
+
+        if( m_poReader == NULL )
+        {
+            if( pdfProgressPct != NULL )
+                *pdfProgressPct = 1.0;
+            if( ppoBelongingLayer != NULL )
+                *ppoBelongingLayer = NULL;
+            m_bEndOfReaderLayers = true;
+            if( !m_apoRequestedMetadataLayers.empty() )
+            {
+                m_nCurMetadataLayerIdx = 0;
+                return GetNextFeature( ppoBelongingLayer, pdfProgressPct,
+                                    pfnProgress, pProgressData );
+            }
+            else
+            {
+                return NULL;
+            }
+        }
+    }
+
+    void* pScaledProgress = GDALCreateScaledProgress( dfInitialScanRatio, 1.0,
+                                                      pfnProgress,
+                                                      pProgressData );
+
+    while( true )
+    {
+        OGRGMLASLayer* poBelongingLayer = NULL;
+        OGRFeature* poFeature = m_poReader->GetNextFeature(
+                    &poBelongingLayer,
+                    pScaledProgress ? GDALScaledProgress : NULL,
+                    pScaledProgress);
+        if( poFeature == NULL ||
+            poBelongingLayer->EvaluateFilter(poFeature) )
+        {
+            if( ppoBelongingLayer != NULL )
+                *ppoBelongingLayer = poBelongingLayer;
+            if( pdfProgressPct != NULL )
+            {
+                const vsi_l_offset nOffset = VSIFTellL(m_fpGMLParser);
+                if( nOffset == m_nFileSize )
+                    *pdfProgressPct = 1.0;
+                else
+                    *pdfProgressPct = dfInitialScanRatio +
+                        (1.0 - dfInitialScanRatio) * nOffset / m_nFileSize;
+            }
+            GDALDestroyScaledProgress(pScaledProgress);
+            if( poFeature == NULL )
+            {
+                m_bEndOfReaderLayers = true;
+                if( !m_apoRequestedMetadataLayers.empty() )
+                {
+                    m_nCurMetadataLayerIdx = 0;
+                    return GetNextFeature( ppoBelongingLayer, pdfProgressPct,
+                                        pfnProgress, pProgressData );
+                }
+                else
+                {
+                    return NULL;
+                }
+            }
+            else
+                return poFeature;
+        }
+        delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                          GetLayerByXPath()                           */
+/************************************************************************/
+
+OGRGMLASLayer* OGRGMLASDataSource::GetLayerByXPath( const CPLString& osXPath )
+{
+    for(size_t i = 0; i < m_apoLayers.size(); i++ )
+    {
+        if( m_apoLayers[i]->GetFeatureClass().GetXPath() == osXPath )
+        {
+            return m_apoLayers[i];
+        }
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                       PushUnusedGMLFilePointer()                     */
+/************************************************************************/
+
+void OGRGMLASDataSource::PushUnusedGMLFilePointer( VSILFILE* fpGML )
+{
+    if( m_fpGML == NULL )
+        m_fpGML = fpGML;
+    else
+    {
+        VSIFCloseL(fpGML);
+    }
+}
+
+/************************************************************************/
+/*                        PopUnusedGMLFilePointer()                     */
+/************************************************************************/
+
+VSILFILE* OGRGMLASDataSource::PopUnusedGMLFilePointer()
+{
+    VSILFILE* fpGML = m_fpGML;
+    m_fpGML = NULL;
+    return fpGML;
+}
+
+/************************************************************************/
+/*                          RunFirstPassIfNeeded()                      */
+/************************************************************************/
+
+bool OGRGMLASDataSource::RunFirstPassIfNeeded( GMLASReader* poReader,
+                                               GDALProgressFunc pfnProgress,
+                                               void* pProgressData )
+{
+    if( m_bFirstPassDone )
+    {
+        if( poReader != NULL )
+        {
+            poReader->SetMapSRSNameToInvertedAxis(m_oMapSRSNameToInvertedAxis);
+            poReader->SetMapGeomFieldDefnToSRSName(m_oMapGeomFieldDefnToSRSName);
+            poReader->SetSWEDataArrayLayers(m_apoSWEDataArrayLayers);
+        }
+        return true;
+    }
+
+    m_bFirstPassDone = true;
+
+    // Determine if we have geometry fields in any layer
+    // If so, do an initial pass to determine the SRS of those geometry fields.
+    bool bHasGeomFields = false;
+    for(size_t i=0;i<m_apoLayers.size();i++)
+    {
+        m_apoLayers[i]->SetLayerDefnFinalized(true);
+        if( m_apoLayers[i]->GetLayerDefn()->GetGeomFieldCount() > 0 )
+        {
+            bHasGeomFields = true;
+            break;
+        }
+    }
+
+    const bool bHasURLSpecificRules =
+                !m_oXLinkResolver.GetConf().m_aoURLSpecificRules.empty();
+    if( bHasGeomFields || m_bValidate || m_bRemoveUnusedLayers ||
+        m_bRemoveUnusedFields || bHasURLSpecificRules || m_bFoundSWE )
+    {
+        bool bJustOpenedFiled =false;
+        VSILFILE* fp = NULL;
+        if( poReader )
+            fp = poReader->GetFP();
+        else
+        {
+            fp = VSIFOpenL(GetGMLFilename(), "rb");
+            if( fp == NULL )
+            {
+                return false;
+            }
+            bJustOpenedFiled = true;
+        }
+
+        GMLASReader* poReaderFirstPass = new GMLASReader(m_oCache,
+                                                         m_oIgnoredXPathMatcher,
+                                                         m_oXLinkResolver);
+        poReaderFirstPass->Init( GetGMLFilename(),
+                                 fp,
+                                 GetMapURIToPrefix(),
+                                 GetLayers(),
+                                 m_bValidate,
+                                 m_aoXSDsManuallyPassed,
+                                 m_bSchemaFullChecking,
+                                 m_bHandleMultipleImports );
+
+        poReaderFirstPass->SetFileSize( m_nFileSize );
+
+        poReaderFirstPass->SetMapIgnoredXPathToWarn(
+                                    m_oConf.m_oMapIgnoredXPathToWarn);
+        // No need to warn afterwards
+        m_oConf.m_oMapIgnoredXPathToWarn.clear();
+
+        std::set<CPLString> aoSetRemovedLayerNames;
+        m_bFirstPassDone = poReaderFirstPass->RunFirstPass(
+            pfnProgress,
+            pProgressData,
+            m_bRemoveUnusedLayers,
+            m_bRemoveUnusedFields,
+            m_bFoundSWE && m_oConf.m_bSWEProcessDataArray,
+            aoSetRemovedLayerNames);
+
+        const std::vector<OGRGMLASLayer*>& apoSWEDataArrayLayers =
+                                poReaderFirstPass->GetSWEDataArrayLayers();
+        m_apoSWEDataArrayLayers = apoSWEDataArrayLayers;
+        for(size_t i = 0; i < apoSWEDataArrayLayers.size(); i++ )
+        {
+            apoSWEDataArrayLayers[i]->SetDataSource(this);
+            m_apoLayers.push_back(apoSWEDataArrayLayers[i]);
+        }
+
+        // If we have removed layers, we also need to cleanup our special
+        // metadata layers
+        if( !aoSetRemovedLayerNames.empty() )
+        {
+            // Removing features while iterating works here given the layers
+            // are MEM layers
+            OGRFeature* poFeature;
+            m_poLayersMetadataLayer->ResetReading();
+            while( (poFeature = m_poLayersMetadataLayer->GetNextFeature() )
+                                                                    != NULL )
+            {
+                const char* pszLayerName =
+                                    poFeature->GetFieldAsString(szLAYER_NAME);
+                if( aoSetRemovedLayerNames.find(pszLayerName) !=
+                                                aoSetRemovedLayerNames.end() )
+                {
+                    CPL_IGNORE_RET_VAL(m_poLayersMetadataLayer->
+                                        DeleteFeature(poFeature->GetFID()));
+                }
+                delete poFeature;
+            }
+            m_poLayersMetadataLayer->ResetReading();
+
+            m_poFieldsMetadataLayer->ResetReading();
+            while( (poFeature = m_poFieldsMetadataLayer->GetNextFeature() )
+                                                                    != NULL )
+            {
+                const char* pszLayerName =
+                                    poFeature->GetFieldAsString(szLAYER_NAME);
+                const char* pszRelatedLayerName =
+                            poFeature->GetFieldAsString(szFIELD_RELATED_LAYER);
+                if( aoSetRemovedLayerNames.find(pszLayerName) !=
+                                            aoSetRemovedLayerNames.end() ||
+                    aoSetRemovedLayerNames.find(pszRelatedLayerName) !=
+                                                aoSetRemovedLayerNames.end() )
+                {
+                    CPL_IGNORE_RET_VAL(m_poFieldsMetadataLayer->
+                                        DeleteFeature(poFeature->GetFID()));
+                }
+                delete poFeature;
+            }
+            m_poFieldsMetadataLayer->ResetReading();
+
+            m_poRelationshipsLayer->ResetReading();
+            while( (poFeature = m_poRelationshipsLayer->GetNextFeature() )
+                                                                    != NULL )
+            {
+                const char* pszParentLayerName =
+                                    poFeature->GetFieldAsString(szPARENT_LAYER);
+                const char* pszChildLayerName =
+                                    poFeature->GetFieldAsString(szCHILD_LAYER);
+                if( aoSetRemovedLayerNames.find(pszParentLayerName) !=
+                                                aoSetRemovedLayerNames.end() ||
+                    aoSetRemovedLayerNames.find(pszChildLayerName) !=
+                                                aoSetRemovedLayerNames.end() )
+                {
+                    CPL_IGNORE_RET_VAL(m_poRelationshipsLayer->
+                                        DeleteFeature(poFeature->GetFID()));
+                }
+                delete poFeature;
+            }
+            m_poRelationshipsLayer->ResetReading();
+        }
+
+        // Store 2 maps to reinject them in real readers
+        m_oMapSRSNameToInvertedAxis =
+                        poReaderFirstPass->GetMapSRSNameToInvertedAxis();
+        m_oMapGeomFieldDefnToSRSName =
+                        poReaderFirstPass->GetMapGeomFieldDefnToSRSName();
+
+        delete poReaderFirstPass;
+
+        VSIFSeekL(fp, 0, SEEK_SET);
+        if( bJustOpenedFiled )
+            PushUnusedGMLFilePointer(fp);
+
+        if( poReader != NULL )
+        {
+            poReader->SetMapSRSNameToInvertedAxis(m_oMapSRSNameToInvertedAxis);
+            poReader->SetMapGeomFieldDefnToSRSName(m_oMapGeomFieldDefnToSRSName);
+            poReader->SetSWEDataArrayLayers(m_apoSWEDataArrayLayers);
+        }
+    }
+
+    return m_bFirstPassDone;
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlasdriver.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlasdriver.cpp
new file mode 100644
index 0000000..0fc0c89
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlasdriver.cpp
@@ -0,0 +1,194 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+
+// g++ -I/usr/include/json -DxDEBUG_VERBOSE -DDEBUG   -g -DDEBUG -ftrapv  -Wall -Wextra -Winit-self -Wunused-parameter -Wformat -Werror=format-security -Wno-format-nonliteral -Wlogical-op -Wshadow -Werror=vla -Wmissing-declarations -Wnon-virtual-dtor -Woverloaded-virtual -fno-operator-names ogr/ogrsf_frmts/gmlas/*.cpp -fPIC -shared -o ogr_GMLAS.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mem  -L. -lgdal   -I/home/even/spatialys/eea/inspire_gml/install-xerces-c-3.1.3/include
+
+CPL_CVSID("$Id: ogrgmlasdriver.cpp 36746 2016-12-08 14:57:59Z rouault $");
+
+/************************************************************************/
+/*                        OGRGMLASDriverIdentify()                      */
+/************************************************************************/
+
+static int OGRGMLASDriverIdentify( GDALOpenInfo* poOpenInfo )
+
+{
+    return STARTS_WITH_CI(poOpenInfo->pszFilename, szGMLAS_PREFIX);
+}
+
+/************************************************************************/
+/*                           OGRGMLASDriverOpen()                       */
+/************************************************************************/
+
+static GDALDataset *OGRGMLASDriverOpen( GDALOpenInfo* poOpenInfo )
+
+{
+    OGRGMLASDataSource    *poDS;
+
+    if( poOpenInfo->eAccess == GA_Update )
+        return NULL;
+
+    if( OGRGMLASDriverIdentify( poOpenInfo ) == FALSE )
+        return NULL;
+
+    poDS = new OGRGMLASDataSource();
+
+    if( !poDS->Open(  poOpenInfo ) )
+    {
+        delete poDS;
+        return NULL;
+    }
+    else
+        return poDS;
+}
+
+/************************************************************************/
+/*                          RegisterOGRGMLAS()                          */
+/************************************************************************/
+
+void RegisterOGRGMLAS()
+
+{
+    if( GDALGetDriverByName( "GMLAS" ) != NULL )
+        return;
+
+    GDALDriver  *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GMLAS" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Geography Markup Language (GML) "
+                               "driven by application schemas" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "gml xml" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_gmlas.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, szGMLAS_PREFIX );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"  <Option name='XSD' type='string' description='Space separated list of "
+            "filenames of XML schemas that apply to the data file'/>"
+"  <Option name='CONFIG_FILE' type='string' "
+            "description='Filename of the configuration file'/>"
+"  <Option name='EXPOSE_METADATA_LAYERS' type='boolean' "
+        "description='Whether metadata layers should be reported by default.' "
+        "default='NO'/>"
+"  <Option name='SCHEMA_FULL_CHECKING' type='boolean' description="
+        "'Whether the full schema constraint checking should be enabled.' "
+        "default='YES'/>"
+"  <Option name='HANDLE_MULTIPLE_IMPORTS' type='boolean' description='Whether "
+        "multiple imports of the same namespace can be done.' default='NO'/>"
+"  <Option name='VALIDATE' type='boolean' description='Whether validation "
+        "against the schema should be done' default='NO'/>"
+"  <Option name='FAIL_IF_VALIDATION_ERROR' type='boolean' "
+    "description='Whether a validation error should cause dataset opening "
+    "to fail' "
+    "default='NO'/>"
+"  <Option name='REFRESH_CACHE' type='boolean' "
+    "description='Whether remote schemas and resolved xlink resources should "
+    "be downloaded from the server' "
+    "default='NO'/>"
+"  <Option name='SWAP_COORDINATES' type='string-select' "
+    "description='Whether the order of geometry coordinates should be "
+    "inverted.' "
+    "default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>YES</Value>"
+"    <Value>NO</Value>"
+"  </Option>"
+"  <Option name='REMOVE_UNUSED_LAYERS' type='boolean' "
+    "description='Whether unused layers should be removed' " "default='NO'/>"
+"  <Option name='REMOVE_UNUSED_FIELDS' type='boolean' "
+    "description='Whether unused fields should be removed' " "default='NO'/>"
+"</OpenOptionList>" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+(CPLString("<CreationOptionList>") +
+"  <Option name='" + szINPUT_XSD_OPTION + "' type='string' description='"
+"Space separated list of filenames of XML schemas that apply to the data file'/>"
+"  <Option name='" + szCONFIG_FILE_OPTION + "' type='string' "
+            "description='Filename of the configuration file'/>"
+            "'Space separated list of filenames of XML schemas that apply'/>"
+"  <Option name='" +szLAYERS_OPTION + "' type='string' "
+            "description='Comma separated list of layer names to export'/>"
+"  <Option name='" + szSRSNAME_FORMAT_OPTION + "' type='string-select' "
+                    "description='Format of srsName' "
+                    "default='" + szSRSNAME_DEFAULT +"'>"
+"    <Value>" + szSHORT + "</Value>"
+"    <Value>" + szOGC_URN + "</Value>"
+"    <Value>" + szOGC_URL + "</Value>"
+"  </Option>"
+"  <Option name='" +szINDENT_SIZE_OPTION + "' type='int' min='0' max='8' "
+    "description='Number of spaces for each indentation level' default='2'/>"
+"  <Option name='" +szCOMMENT_OPTION  +"' type='string' description='"
+        "Comment to add at top of generated XML file'/>"
+"  <Option name='"+ szLINEFORMAT_OPTION + "' type='string-select' "
+                            "description='end-of-line sequence' "
+#ifdef WIN32
+                            "default='" + szCRLF + "'>"
+#else
+                            "default='" +szLF + "'>"
+#endif
+"    <Value>" +szCRLF + "</Value>"
+"    <Value>" +szLF + "</Value>"
+"  </Option>"
+"  <Option name='" + szWRAPPING_OPTION + "' type='string-select' "
+          "description='How to wrap features' "
+          "default='" +szWFS2_FEATURECOLLECTION + "'>"
+"    <Value>" + szWFS2_FEATURECOLLECTION + "</Value>"
+"    <Value>" + szGMLAS_FEATURECOLLECTION + "</Value>"
+"  </Option>"
+"  <Option name='" + szTIMESTAMP_OPTION +"' type='string' "
+    "description='User-specified XML "
+    "dateTime value for timestamp to use in wfs:FeatureCollection attribute."
+    "Only valid for " +szWRAPPING_OPTION + "=" + szWFS2_FEATURECOLLECTION +"'/>"
+"  <Option name='" + szWFS20_SCHEMALOCATION_OPTION + "' type='string' "
+    "description='Path or URL to wfs.xsd. Only valid for " +
+    szWRAPPING_OPTION + "=" + szWFS2_FEATURECOLLECTION +"'/>"
+"  <Option name='" + szGENERATE_XSD_OPTION + "' type='boolean' "
+          "description='Whether to generate a .xsd file. Only valid for "
+          + szWRAPPING_OPTION + "=" + szGMLAS_FEATURECOLLECTION +"' "
+          "default='YES'/>"
+"  <Option name='" + szOUTPUT_XSD_FILENAME_OPTION + "' type='string' "
+          "description='Wrapping .xsd filename. If not specified, same "
+          "basename as output file with .xsd extension. Only valid for "
+          + szWRAPPING_OPTION + "=" + szGMLAS_FEATURECOLLECTION +"'/>"
+"</CreationOptionList>").c_str() );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnOpen = OGRGMLASDriverOpen;
+    poDriver->pfnCreateCopy = OGRGMLASDriverCreateCopy;
+    poDriver->pfnIdentify = OGRGMLASDriverIdentify;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlasfeatureclass.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlasfeatureclass.cpp
new file mode 100644
index 0000000..a2115dd
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlasfeatureclass.cpp
@@ -0,0 +1,199 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+
+CPL_CVSID("$Id: ogrgmlasfeatureclass.cpp 37133 2017-01-12 22:00:33Z rouault $");
+
+/************************************************************************/
+/*                              GMLASField()                            */
+/************************************************************************/
+
+GMLASField::GMLASField()
+    : m_eType(GMLAS_FT_STRING)
+    , m_eGeomType(wkbNone)
+    , m_nWidth(0)
+    , m_bNotNullable(false)
+    , m_bArray(false)
+    , m_bList(false)
+    , m_eCategory(REGULAR)
+    , m_nMinOccurs(-1)
+    , m_nMaxOccurs(-1)
+    , m_bRepetitionOnSequence(false)
+    , m_bIncludeThisEltInBlob(false)
+    , m_bIgnored(false)
+    , m_bMayAppearOutOfOrder(false)
+{
+}
+
+/************************************************************************/
+/*                             GetTypeFromString()                      */
+/************************************************************************/
+
+GMLASFieldType GMLASField::GetTypeFromString( const CPLString& osType )
+{
+    if( osType == szXS_STRING ||
+        osType == szXS_TOKEN ||
+        osType == szXS_NMTOKEN ||
+        osType == szXS_NCNAME ||
+        osType == szXS_QNAME )
+    {
+        // token has special processing by XML processor: all leading/trailing
+        // white space is removed
+        return GMLAS_FT_STRING;
+    }
+    else if( osType == szXS_ID )
+        return GMLAS_FT_ID;
+    else if( osType == szXS_BOOLEAN )
+        return GMLAS_FT_BOOLEAN;
+    else if( osType == szXS_SHORT )
+        return GMLAS_FT_SHORT;
+    else if( osType == szXS_INT )
+        return GMLAS_FT_INT32;
+    else if( osType == szXS_BYTE ||
+             osType == szXS_INTEGER ||
+             osType == szXS_NEGATIVE_INTEGER ||
+             osType == szXS_NON_NEGATIVE_INTEGER ||
+             osType == szXS_NON_POSITIVE_INTEGER ||
+             osType == szXS_POSITIVE_INTEGER ||
+             osType == szXS_UNSIGNED_BYTE ||
+             osType == szXS_UNSIGNED_SHORT ||
+             osType == szXS_UNSIGNED_INT) // FIXME ?
+        return GMLAS_FT_INT32;
+    else if( osType == szXS_LONG ||
+             osType == szXS_UNSIGNED_LONG )
+        return GMLAS_FT_INT64;
+    else if( osType == szXS_FLOAT )
+        return GMLAS_FT_FLOAT;
+    else if( osType == szXS_DOUBLE )
+        return GMLAS_FT_DOUBLE;
+    else if( osType == szXS_DECIMAL )
+        return GMLAS_FT_DECIMAL;
+    else if( osType == szXS_DATE )
+        return GMLAS_FT_DATE;
+    else if( osType == szXS_TIME )
+        return GMLAS_FT_TIME;
+    else if( osType == szXS_DATETIME )
+        return GMLAS_FT_DATETIME;
+    else if( osType == szXS_ANY_URI )
+        return GMLAS_FT_ANYURI;
+    else if( osType == szXS_ANY_TYPE )
+        return GMLAS_FT_ANYTYPE;
+    else if( osType == szXS_ANY_SIMPLE_TYPE )
+        return GMLAS_FT_ANYSIMPLETYPE;
+    else if( osType == szXS_DURATION )
+        return GMLAS_FT_STRING;
+    else if( osType == szXS_BASE64BINARY )
+        return GMLAS_FT_BASE64BINARY;
+    else if( osType == szXS_HEXBINARY )
+        return GMLAS_FT_HEXBINARY;
+    else
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                    "Unhandled type: %s", osType.c_str());
+        return GMLAS_FT_STRING;
+    }
+}
+
+/************************************************************************/
+/*                               SetType()                              */
+/************************************************************************/
+
+void GMLASField::SetType(GMLASFieldType eType, const char* pszTypeName)
+{
+    m_eType = eType;
+    m_osTypeName = pszTypeName;
+}
+
+/************************************************************************/
+/*                          GMLASFeatureClass()                         */
+/************************************************************************/
+
+GMLASFeatureClass::GMLASFeatureClass()
+    : m_bIsRepeatedSequence(false)
+    , m_bIsGroup(false)
+    , m_bIsTopLevelElt(false)
+{
+}
+
+/************************************************************************/
+/*                                 SetName()                            */
+/************************************************************************/
+
+void GMLASFeatureClass::SetName(const CPLString& osName)
+{
+    m_osName = osName;
+}
+
+/************************************************************************/
+/*                                SetXPath()                            */
+/************************************************************************/
+
+void GMLASFeatureClass::SetXPath(const CPLString& osXPath)
+{
+    m_osXPath = osXPath;
+}
+
+/************************************************************************/
+/*                                AddField()                            */
+/************************************************************************/
+
+void GMLASFeatureClass::AddField( const GMLASField& oField )
+{
+    m_aoFields.push_back(oField);
+}
+
+/************************************************************************/
+/*                            PrependFields()                           */
+/************************************************************************/
+
+void GMLASFeatureClass::PrependFields( const std::vector<GMLASField>& aoFields )
+{
+    m_aoFields.insert( m_aoFields.begin(), aoFields.begin(), aoFields.end() );
+}
+
+/************************************************************************/
+/*                             AppendFields()                           */
+/************************************************************************/
+
+void GMLASFeatureClass::AppendFields( const std::vector<GMLASField>& aoFields )
+{
+    m_aoFields.insert( m_aoFields.end(), aoFields.begin(), aoFields.end() );
+}
+
+/************************************************************************/
+/*                             AddNestedClass()                         */
+/************************************************************************/
+
+void GMLASFeatureClass::AddNestedClass( const GMLASFeatureClass& oNestedClass )
+{
+    m_aoNestedClasses.push_back(oNestedClass);
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlaslayer.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlaslayer.cpp
new file mode 100644
index 0000000..311b428
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlaslayer.cpp
@@ -0,0 +1,992 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+
+CPL_CVSID("$Id: ogrgmlaslayer.cpp 37972 2017-04-12 16:13:12Z rouault $");
+
+/************************************************************************/
+/*                            OGRGMLASLayer()                           */
+/************************************************************************/
+
+OGRGMLASLayer::OGRGMLASLayer( OGRGMLASDataSource* poDS,
+                              const GMLASFeatureClass& oFC,
+                              OGRGMLASLayer* poParentLayer,
+                              bool bAlwaysGenerateOGRPKId ) :
+    m_poDS( poDS ),
+    m_oFC( oFC ),
+    m_bLayerDefnFinalized( false ),
+    m_poFeatureDefn( new OGRFeatureDefn( oFC.GetName() ) ),
+    m_bEOF( false ),
+    m_poReader( NULL ),
+    m_fpGML( NULL ),
+    m_nIDFieldIdx( -1 ),
+    m_bIDFieldIsGenerated( false ),
+    m_poParentLayer( poParentLayer ),
+    m_nParentIDFieldIdx( -1 )
+
+{
+    m_poFeatureDefn->SetGeomType(wkbNone);
+    m_poFeatureDefn->Reference();
+
+    SetDescription( m_poFeatureDefn->GetName() );
+
+    // Are we a regular table ?
+    if( m_oFC.GetParentXPath().empty() )
+    {
+        if( bAlwaysGenerateOGRPKId )
+        {
+            OGRFieldDefn oFieldDefn( szOGR_PKID, OFTString );
+            oFieldDefn.SetNullable( false );
+            m_nIDFieldIdx = m_poFeatureDefn->GetFieldCount();
+            m_bIDFieldIsGenerated = true;
+            m_poFeatureDefn->AddFieldDefn( &oFieldDefn );
+        }
+
+        // Determine if we have an xs:ID attribute/elt, and if it is compulsory,
+        // If so, place it as first field (not strictly required, but more readable)
+        // or second field (if we also add a ogr_pkid)
+        // Furthermore restrict that to attributes, because otherwise it is
+        // impractical in the reader when joining related features.
+        const std::vector<GMLASField>& oFields = m_oFC.GetFields();
+        for(int i=0; i< static_cast<int>(oFields.size()); i++ )
+        {
+            if( oFields[i].GetType() == GMLAS_FT_ID &&
+                oFields[i].IsNotNullable() &&
+                oFields[i].GetXPath().find('@') != std::string::npos)
+            {
+                OGRFieldDefn oFieldDefn( oFields[i].GetName(), OFTString );
+                oFieldDefn.SetNullable( false );
+                const int nOGRIdx = m_poFeatureDefn->GetFieldCount();
+                if( m_nIDFieldIdx < 0 )
+                    m_nIDFieldIdx = nOGRIdx;
+                m_oMapFieldXPathToOGRFieldIdx[ oFields[i].GetXPath() ] =
+                                            nOGRIdx;
+                m_oMapOGRFieldIdxtoFCFieldIdx[ nOGRIdx ] = i;
+                m_oMapFieldXPathToFCFieldIdx[ oFields[i].GetXPath() ] = i;
+                m_poFeatureDefn->AddFieldDefn( &oFieldDefn );
+                break;
+            }
+        }
+
+        // If we don't have an explicit ID, then we need
+        // to generate one, so that potentially related classes can reference it
+        // (We could perhaps try to be clever to determine if we really need it)
+        if( m_nIDFieldIdx < 0 )
+        {
+            OGRFieldDefn oFieldDefn( szOGR_PKID, OFTString );
+            oFieldDefn.SetNullable( false );
+            m_nIDFieldIdx = m_poFeatureDefn->GetFieldCount();
+            m_bIDFieldIsGenerated = true;
+            m_poFeatureDefn->AddFieldDefn( &oFieldDefn );
+        }
+    }
+
+    OGRLayer* poLayersMetadataLayer = m_poDS->GetLayersMetadataLayer();
+    OGRFeature* poLayerDescFeature =
+                        new OGRFeature(poLayersMetadataLayer->GetLayerDefn());
+    poLayerDescFeature->SetField( szLAYER_NAME, GetName() );
+    if( !m_oFC.GetParentXPath().empty() )
+    {
+        poLayerDescFeature->SetField( szLAYER_CATEGORY, szJUNCTION_TABLE );
+    }
+    else
+    {
+        poLayerDescFeature->SetField( szLAYER_XPATH, m_oFC.GetXPath() );
+
+        poLayerDescFeature->SetField( szLAYER_CATEGORY,
+                                m_oFC.IsTopLevelElt() ? szTOP_LEVEL_ELEMENT :
+                                                        szNESTED_ELEMENT );
+
+        if( m_nIDFieldIdx >= 0 )
+        {
+            poLayerDescFeature->SetField( szLAYER_PKID_NAME,
+                m_poFeatureDefn->GetFieldDefn(m_nIDFieldIdx)->GetNameRef() );
+        }
+
+        // If we are a child class, then add a field to reference the parent.
+        if( m_poParentLayer != NULL )
+        {
+            CPLString osFieldName(szPARENT_PREFIX);
+            osFieldName += m_poParentLayer->GetLayerDefn()->GetFieldDefn(
+                                    m_poParentLayer->GetIDFieldIdx())->GetNameRef();
+            poLayerDescFeature->SetField( szLAYER_PARENT_PKID_NAME,
+                                          osFieldName.c_str() );
+        }
+
+        if( !m_oFC.GetDocumentation().empty() )
+        {
+            poLayerDescFeature->SetField( szLAYER_DOCUMENTATION,
+                                          m_oFC.GetDocumentation() );
+        }
+    }
+    CPL_IGNORE_RET_VAL(
+            poLayersMetadataLayer->CreateFeature(poLayerDescFeature));
+    delete poLayerDescFeature;
+
+}
+
+/************************************************************************/
+/*                            OGRGMLASLayer()                           */
+/************************************************************************/
+
+OGRGMLASLayer::OGRGMLASLayer(const char* pszLayerName) :
+    m_poDS( NULL ),
+    m_bLayerDefnFinalized( true ),
+    m_poFeatureDefn( new OGRFeatureDefn( pszLayerName ) ),
+    m_bEOF( false ),
+    m_poReader( NULL ),
+    m_fpGML( NULL ),
+    m_nIDFieldIdx( -1 ),
+    m_bIDFieldIsGenerated( false ),
+    m_poParentLayer( NULL ),
+    m_nParentIDFieldIdx( -1 )
+
+{
+    m_poFeatureDefn->SetGeomType(wkbNone);
+    m_poFeatureDefn->Reference();
+
+    SetDescription( m_poFeatureDefn->GetName() );
+}
+
+/************************************************************************/
+/*                         ProcessDataRecord()                          */
+/************************************************************************/
+
+void OGRGMLASLayer::ProcessDataRecord(CPLXMLNode* psDataRecord)
+{
+    for( CPLXMLNode* psIter = psDataRecord->psChild;
+                        psIter != NULL; psIter = psIter->psNext )
+    {
+        if( psIter->eType == CXT_Element &&
+            strcmp(psIter->pszValue, "field") == 0 )
+        {
+            CPLString osName = CPLGetXMLValue(psIter, "name", "");
+            OGRFieldDefn oFieldDefn(osName, OFTString);
+            if( CPLGetXMLNode(psIter, "Time") )
+            {
+                oFieldDefn.SetType(OFTDateTime);
+            }
+            else if( CPLGetXMLNode(psIter, "Quantity") )
+            {
+                oFieldDefn.SetType(OFTReal);
+            }
+            m_poFeatureDefn->AddFieldDefn(&oFieldDefn);
+        }
+    }
+}
+
+/************************************************************************/
+/*                             PostInit()                               */
+/************************************************************************/
+
+void OGRGMLASLayer::PostInit( bool bIncludeGeometryXML )
+{
+    const std::vector<GMLASField>& oFields = m_oFC.GetFields();
+
+    OGRLayer* poFieldsMetadataLayer = m_poDS->GetFieldsMetadataLayer();
+    OGRLayer* poRelationshipsLayer = m_poDS->GetRelationshipsLayer();
+
+    // Is it a junction table ?
+    if( !m_oFC.GetParentXPath().empty() )
+    {
+        {
+            OGRFieldDefn oFieldDefn( szOCCURRENCE, OFTInteger );
+            oFieldDefn.SetNullable( false );
+            m_poFeatureDefn->AddFieldDefn( &oFieldDefn );
+
+            OGRFeature* poFieldDescFeature =
+                        new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
+            poFieldDescFeature->SetField( szLAYER_NAME, GetName() );
+            poFieldDescFeature->SetField( szFIELD_NAME, oFieldDefn.GetNameRef() );
+            CPL_IGNORE_RET_VAL(
+                    poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
+            delete poFieldDescFeature;
+        }
+
+        {
+            OGRFieldDefn oFieldDefn( szPARENT_PKID, OFTString );
+            oFieldDefn.SetNullable( false );
+            m_poFeatureDefn->AddFieldDefn( &oFieldDefn );
+
+            OGRFeature* poFieldDescFeature =
+                                new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
+            poFieldDescFeature->SetField( szLAYER_NAME, GetName() );
+            poFieldDescFeature->SetField( szFIELD_NAME, oFieldDefn.GetNameRef() );
+            CPL_IGNORE_RET_VAL(
+                    poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
+            delete poFieldDescFeature;
+        }
+        {
+            OGRFieldDefn oFieldDefn( szCHILD_PKID, OFTString );
+            oFieldDefn.SetNullable( false );
+            m_poFeatureDefn->AddFieldDefn( &oFieldDefn );
+
+            OGRFeature* poFieldDescFeature =
+                                new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
+            poFieldDescFeature->SetField( szLAYER_NAME, GetName() );
+            poFieldDescFeature->SetField( szFIELD_NAME, oFieldDefn.GetNameRef() );
+            CPL_IGNORE_RET_VAL(
+                    poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
+            delete poFieldDescFeature;
+        }
+
+        return;
+    }
+
+    // If we are a child class, then add a field to reference the parent.
+    if( m_poParentLayer != NULL )
+    {
+        CPLString osFieldName(szPARENT_PREFIX);
+        osFieldName += m_poParentLayer->GetLayerDefn()->GetFieldDefn(
+                                m_poParentLayer->GetIDFieldIdx())->GetNameRef();
+        OGRFieldDefn oFieldDefn( osFieldName, OFTString );
+        oFieldDefn.SetNullable( false );
+        m_nParentIDFieldIdx = m_poFeatureDefn->GetFieldCount();
+        m_poFeatureDefn->AddFieldDefn( &oFieldDefn );
+    }
+
+    int nFieldIndex = 0;
+    for(int i=0; i< static_cast<int>(oFields.size()); i++ )
+    {
+        OGRGMLASLayer* poRelatedLayer = NULL;
+        const GMLASField& oField(oFields[i]);
+
+        m_oMapFieldXPathToFCFieldIdx[ oField.GetXPath() ] = i;
+        if( oField.IsIgnored() )
+            continue;
+
+        const GMLASField::Category eCategory(oField.GetCategory());
+        if( !oField.GetRelatedClassXPath().empty() )
+        {
+            poRelatedLayer =
+                    m_poDS->GetLayerByXPath(oField.GetRelatedClassXPath());
+            if( poRelatedLayer != NULL )
+            {
+                OGRFeature* poRelationshipsFeature =
+                    new OGRFeature(poRelationshipsLayer->GetLayerDefn());
+                poRelationshipsFeature->SetField( szPARENT_LAYER, GetName() );
+                poRelationshipsFeature->SetField( szPARENT_PKID,
+                        GetLayerDefn()->GetFieldDefn(
+                                GetIDFieldIdx())->GetNameRef() );
+                if( !oField.GetName().empty() )
+                {
+                    poRelationshipsFeature->SetField( szPARENT_ELEMENT_NAME,
+                                                      oField.GetName() );
+                }
+                poRelationshipsFeature->SetField(szCHILD_LAYER,
+                                                 poRelatedLayer->GetName() );
+                if( eCategory ==
+                            GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE ||
+                    eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK )
+                {
+                    poRelationshipsFeature->SetField( szCHILD_PKID,
+                        poRelatedLayer->GetLayerDefn()->GetFieldDefn(
+                            poRelatedLayer->GetIDFieldIdx())->GetNameRef() );
+                }
+                else
+                {
+                    CPLAssert( eCategory ==
+                                    GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||
+                               eCategory == GMLASField::GROUP);
+
+                    poRelationshipsFeature->SetField( szCHILD_PKID,
+                        (CPLString(szPARENT_PREFIX) +
+                            GetLayerDefn()->GetFieldDefn(
+                                    GetIDFieldIdx())->GetNameRef()).c_str() );
+                }
+                CPL_IGNORE_RET_VAL(poRelationshipsLayer->CreateFeature(
+                                                poRelationshipsFeature));
+                delete poRelationshipsFeature;
+            }
+            else
+            {
+                CPLDebug("GMLAS", "Cannot find class matching %s",
+                        oField.GetRelatedClassXPath().c_str());
+            }
+        }
+
+        OGRFeature* poFieldDescFeature =
+                            new OGRFeature(poFieldsMetadataLayer->GetLayerDefn());
+        poFieldDescFeature->SetField( szLAYER_NAME, GetName() );
+
+        ++nFieldIndex;
+        poFieldDescFeature->SetField( szFIELD_INDEX, nFieldIndex);
+
+        if( oField.GetName().empty() )
+        {
+            CPLAssert( eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||
+                       eCategory == GMLASField::GROUP );
+        }
+        else
+        {
+            poFieldDescFeature->SetField( szFIELD_NAME,
+                                          oField.GetName().c_str() );
+        }
+        if( !oField.GetXPath().empty() )
+        {
+            poFieldDescFeature->SetField( szFIELD_XPATH,
+                                          oField.GetXPath().c_str() );
+        }
+        else if( !oField.GetAlternateXPaths().empty() )
+        {
+            CPLString osXPath;
+            const std::vector<CPLString>& aoXPaths =
+                                            oField.GetAlternateXPaths();
+            for( size_t j=0; j<aoXPaths.size(); j++ )
+            {
+                if( j != 0 ) osXPath += ",";
+                osXPath += aoXPaths[j];
+            }
+            poFieldDescFeature->SetField( szFIELD_XPATH, osXPath.c_str() );
+        }
+        if( oField.GetTypeName().empty() )
+        {
+            CPLAssert( eCategory ==
+                                GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||
+                       eCategory == GMLASField::
+                                PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE ||
+                       eCategory == GMLASField::GROUP );
+        }
+        else
+        {
+            poFieldDescFeature->SetField( szFIELD_TYPE,
+                                        oField.GetTypeName().c_str() );
+        }
+        poFieldDescFeature->SetField( szFIELD_IS_LIST,
+                                      static_cast<int>(oField.IsList()) );
+        if( oField.GetMinOccurs() != -1 )
+        {
+            poFieldDescFeature->SetField( szFIELD_MIN_OCCURS,
+                                        oField.GetMinOccurs() );
+        }
+        if( oField.GetMaxOccurs() == MAXOCCURS_UNLIMITED )
+        {
+            poFieldDescFeature->SetField( szFIELD_MAX_OCCURS, INT_MAX );
+        }
+        else if( oField.GetMaxOccurs() != -1 )
+        {
+            poFieldDescFeature->SetField( szFIELD_MAX_OCCURS,
+                                        oField.GetMaxOccurs() );
+        }
+        if( oField.GetMaxOccurs() == MAXOCCURS_UNLIMITED ||
+            oField.GetMaxOccurs() > 1 )
+        {
+            poFieldDescFeature->SetField( szFIELD_REPETITION_ON_SEQUENCE,
+                                oField.GetRepetitionOnSequence() ? 1 : 0);
+        }
+        if( !oField.GetFixedValue().empty() )
+        {
+            poFieldDescFeature->SetField( szFIELD_FIXED_VALUE,
+                                          oField.GetFixedValue() );
+        }
+        if( !oField.GetDefaultValue().empty() )
+        {
+            poFieldDescFeature->SetField( szFIELD_DEFAULT_VALUE,
+                                          oField.GetDefaultValue() );
+        }
+        switch( eCategory )
+        {
+            case GMLASField::REGULAR:
+                poFieldDescFeature->SetField(szFIELD_CATEGORY,
+                                             szREGULAR);
+                break;
+            case GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK:
+                poFieldDescFeature->SetField(szFIELD_CATEGORY,
+                                             szPATH_TO_CHILD_ELEMENT_NO_LINK);
+                break;
+            case GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK:
+                poFieldDescFeature->SetField(szFIELD_CATEGORY,
+                                             szPATH_TO_CHILD_ELEMENT_WITH_LINK);
+                break;
+            case GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE:
+                poFieldDescFeature->SetField(szFIELD_CATEGORY,
+                                szPATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE);
+                break;
+            case GMLASField::GROUP:
+                poFieldDescFeature->SetField(szFIELD_CATEGORY,
+                                             szGROUP);
+                break;
+            default:
+                CPLAssert(FALSE);
+                break;
+        }
+        if( poRelatedLayer != NULL )
+        {
+            poFieldDescFeature->SetField( szFIELD_RELATED_LAYER,
+                                          poRelatedLayer->GetName() );
+        }
+
+        if( eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE)
+        {
+            const CPLString& osAbstractElementXPath(
+                                oField.GetAbstractElementXPath());
+            const CPLString& osNestedXPath(
+                                oField.GetRelatedClassXPath());
+            CPLAssert( !osAbstractElementXPath.empty() );
+            CPLAssert( !osNestedXPath.empty() );
+
+            OGRGMLASLayer* poJunctionLayer = m_poDS->GetLayerByXPath(
+                        osAbstractElementXPath + "|" + osNestedXPath);
+            if( poJunctionLayer != NULL )
+            {
+                poFieldDescFeature->SetField( szFIELD_JUNCTION_LAYER,
+                                              poJunctionLayer->GetName() );
+            }
+        }
+
+        if( !oField.GetDocumentation().empty() )
+        {
+            poFieldDescFeature->SetField( szFIELD_DOCUMENTATION,
+                                          oField.GetDocumentation() );
+        }
+
+        CPL_IGNORE_RET_VAL(poFieldsMetadataLayer->CreateFeature(poFieldDescFeature));
+        delete poFieldDescFeature;
+
+        // Check whether the field is OGR instanciable
+        if( eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||
+            eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE ||
+            eCategory == GMLASField::GROUP )
+        {
+            continue;
+        }
+
+        OGRFieldType eType = OFTString;
+        OGRFieldSubType eSubType = OFSTNone;
+        CPLString osOGRFieldName( oField.GetName() );
+        switch( oField.GetType() )
+        {
+            case GMLAS_FT_STRING:
+                eType = OFTString;
+                break;
+            case GMLAS_FT_ID:
+            {
+                eType = OFTString;
+                if( oField.IsNotNullable() )
+                {
+                    continue;
+                }
+                break;
+            }
+            case GMLAS_FT_BOOLEAN:
+                eType = OFTInteger;
+                eSubType = OFSTBoolean;
+                break;
+            case GMLAS_FT_SHORT:
+                eType = OFTInteger;
+                eSubType = OFSTInt16;
+                break;
+            case GMLAS_FT_INT32:
+                eType = OFTInteger;
+                break;
+            case GMLAS_FT_INT64:
+                eType = OFTInteger64;
+                break;
+            case GMLAS_FT_FLOAT:
+                eType = OFTReal;
+                eSubType = OFSTFloat32;
+                break;
+            case GMLAS_FT_DOUBLE:
+                eType = OFTReal;
+                break;
+            case GMLAS_FT_DECIMAL:
+                eType = OFTReal;
+                break;
+            case GMLAS_FT_DATE:
+                eType = OFTDate;
+                break;
+            case GMLAS_FT_TIME:
+                eType = OFTTime;
+                break;
+            case GMLAS_FT_DATETIME:
+                eType = OFTDateTime;
+                break;
+            case GMLAS_FT_BASE64BINARY:
+            case GMLAS_FT_HEXBINARY:
+                eType = OFTBinary;
+                break;
+            case GMLAS_FT_ANYURI:
+                eType = OFTString;
+                break;
+            case GMLAS_FT_ANYTYPE:
+                eType = OFTString;
+                break;
+            case GMLAS_FT_ANYSIMPLETYPE:
+                eType = OFTString;
+                break;
+            case GMLAS_FT_GEOMETRY:
+            {
+                // Create a geometry field
+                OGRGeomFieldDefn oGeomFieldDefn( osOGRFieldName,
+                                                 oField.GetGeomType() );
+                m_poFeatureDefn->AddGeomFieldDefn( &oGeomFieldDefn );
+
+                const int iOGRGeomIdx =
+                                m_poFeatureDefn->GetGeomFieldCount() - 1;
+                if( !oField.GetXPath().empty() )
+                {
+                    m_oMapFieldXPathToOGRGeomFieldIdx[ oField.GetXPath() ]
+                            = iOGRGeomIdx ;
+                }
+                else
+                {
+                    const std::vector<CPLString>& aoXPaths =
+                                        oField.GetAlternateXPaths();
+                    for( size_t j=0; j<aoXPaths.size(); j++ )
+                    {
+                        m_oMapFieldXPathToOGRGeomFieldIdx[ aoXPaths[j] ]
+                                = iOGRGeomIdx ;
+                    }
+                }
+
+                m_oMapOGRGeomFieldIdxtoFCFieldIdx[ iOGRGeomIdx ] = i;
+
+                // Suffix the regular non-geometry field
+                osOGRFieldName += szXML_SUFFIX;
+                eType = OFTString;
+                break;
+            }
+            default:
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Unhandled type in enum: %d",
+                         oField.GetType() );
+                break;
+        }
+
+        if( oField.GetType() == GMLAS_FT_GEOMETRY &&
+            !bIncludeGeometryXML )
+        {
+            continue;
+        }
+
+        if( oField.IsArray() )
+        {
+            switch( eType )
+            {
+                case OFTString: eType = OFTStringList; break;
+                case OFTInteger: eType = OFTIntegerList; break;
+                case OFTInteger64: eType = OFTInteger64List; break;
+                case OFTReal: eType = OFTRealList; break;
+                default:
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Unhandled type in enum: %d", eType );
+                    break;
+            }
+        }
+        OGRFieldDefn oFieldDefn( osOGRFieldName, eType );
+        oFieldDefn.SetSubType(eSubType);
+        if( oField.IsNotNullable() )
+            oFieldDefn.SetNullable( false );
+        CPLString osDefaultOrFixed = oField.GetDefaultValue();
+        if( osDefaultOrFixed.empty() )
+            osDefaultOrFixed = oField.GetFixedValue();
+        if( !osDefaultOrFixed.empty() )
+        {
+            char* pszEscaped = CPLEscapeString(
+                                        osDefaultOrFixed, -1, CPLES_SQL );
+            oFieldDefn.SetDefault( (CPLString("'") +
+                                        pszEscaped + CPLString("'")).c_str() );
+            CPLFree(pszEscaped);
+        }
+        oFieldDefn.SetWidth( oField.GetWidth() );
+        m_poFeatureDefn->AddFieldDefn( &oFieldDefn );
+
+        const int iOGRIdx = m_poFeatureDefn->GetFieldCount() - 1;
+        if( !oField.GetXPath().empty() )
+        {
+            m_oMapFieldXPathToOGRFieldIdx[ oField.GetXPath() ] = iOGRIdx ;
+        }
+        else
+        {
+            const std::vector<CPLString>& aoXPaths = oField.GetAlternateXPaths();
+            for( size_t j=0; j<aoXPaths.size(); j++ )
+            {
+                m_oMapFieldXPathToOGRFieldIdx[ aoXPaths[j] ] = iOGRIdx ;
+            }
+        }
+
+        m_oMapOGRFieldIdxtoFCFieldIdx[iOGRIdx] = i;
+
+        // Create field to receive resolved xlink:href content, if needed
+        if( oField.GetXPath().find(szAT_XLINK_HREF) != std::string::npos &&
+            m_poDS->GetConf().m_oXLinkResolution.m_bDefaultResolutionEnabled &&
+            m_poDS->GetConf().m_oXLinkResolution.m_eDefaultResolutionMode
+                                        == GMLASXLinkResolutionConf::RawContent )
+        {
+            CPLString osRawContentFieldname(osOGRFieldName);
+            size_t nPos = osRawContentFieldname.find(szHREF_SUFFIX);
+            if( nPos != std::string::npos )
+                osRawContentFieldname.resize(nPos);
+            osRawContentFieldname += szRAW_CONTENT_SUFFIX;
+            OGRFieldDefn oFieldDefnRaw( osRawContentFieldname, OFTString );
+            m_poFeatureDefn->AddFieldDefn( &oFieldDefnRaw );
+
+            m_oMapFieldXPathToOGRFieldIdx[
+                GMLASField::MakeXLinkRawContentFieldXPathFromXLinkHrefXPath(
+                    oField.GetXPath()) ] = m_poFeatureDefn->GetFieldCount() - 1;
+        }
+    }
+
+    CreateCompoundFoldedMappings();
+}
+
+/************************************************************************/
+/*                   CreateCompoundFoldedMappings()                     */
+/************************************************************************/
+
+// In the case we have nested elements but we managed to fold into top
+// level class, then register intermediate paths so they are not reported
+// as unexpected in debug traces
+void OGRGMLASLayer::CreateCompoundFoldedMappings()
+{
+    CPLString oFCXPath(m_oFC.GetXPath());
+    if( m_oFC.IsRepeatedSequence() )
+    {
+        size_t iPosExtra = oFCXPath.find(szEXTRA_SUFFIX);
+        if (iPosExtra != std::string::npos)
+        {
+            oFCXPath.resize(iPosExtra);
+        }
+    }
+
+    const std::vector<GMLASField>& oFields = m_oFC.GetFields();
+    for(size_t i=0; i<oFields.size(); i++ )
+    {
+        std::vector<CPLString> aoXPaths = oFields[i].GetAlternateXPaths();
+        if( aoXPaths.empty() )
+            aoXPaths.push_back(oFields[i].GetXPath());
+        for( size_t j=0; j<aoXPaths.size(); j++ )
+        {
+            if( aoXPaths[j].size() > oFCXPath.size() )
+            {
+                // Split on both '/' and '@'
+                char** papszTokens = CSLTokenizeString2(
+                    aoXPaths[j].c_str() + oFCXPath.size() + 1,
+                    "/@", 0 );
+                CPLString osSubXPath = oFCXPath;
+                for(int k=0; papszTokens[k] != NULL &&
+                            papszTokens[k+1] != NULL; k++)
+                {
+                    osSubXPath += "/";
+                    osSubXPath += papszTokens[k];
+                    if( m_oMapFieldXPathToOGRFieldIdx.find( osSubXPath ) ==
+                                                m_oMapFieldXPathToOGRFieldIdx.end() )
+                    {
+                        m_oMapFieldXPathToOGRFieldIdx[ osSubXPath ] =
+                                                            IDX_COMPOUND_FOLDED;
+                    }
+                }
+                CSLDestroy(papszTokens);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                           ~OGRGMLASLayer()                           */
+/************************************************************************/
+
+OGRGMLASLayer::~OGRGMLASLayer()
+{
+    m_poFeatureDefn->Release();
+    delete m_poReader;
+    if( m_fpGML != NULL )
+        VSIFCloseL(m_fpGML);
+}
+
+/************************************************************************/
+/*                            RemoveField()                             */
+/************************************************************************/
+
+bool OGRGMLASLayer::RemoveField( int nIdx )
+{
+    if( nIdx == m_nIDFieldIdx || nIdx == m_nParentIDFieldIdx )
+        return false;
+
+    m_poFeatureDefn->DeleteFieldDefn( nIdx );
+
+    // Refresh maps
+    {
+        std::map<CPLString, int>       oMapFieldXPathToOGRFieldIdx;
+        std::map<CPLString, int>::const_iterator oIter =
+                            m_oMapFieldXPathToOGRFieldIdx.begin();
+        for( ; oIter != m_oMapFieldXPathToOGRFieldIdx.end(); ++oIter )
+        {
+            if( oIter->second < nIdx )
+                oMapFieldXPathToOGRFieldIdx[oIter->first] = oIter->second;
+            else if( oIter->second > nIdx )
+                oMapFieldXPathToOGRFieldIdx[oIter->first] = oIter->second - 1;
+        }
+        m_oMapFieldXPathToOGRFieldIdx = oMapFieldXPathToOGRFieldIdx;
+    }
+
+    {
+        std::map<int, int>             oMapOGRFieldIdxtoFCFieldIdx;
+        std::map<int, int>::const_iterator oIter =
+                            m_oMapOGRFieldIdxtoFCFieldIdx.begin();
+        for( ; oIter != m_oMapOGRFieldIdxtoFCFieldIdx.end(); ++oIter )
+        {
+            if( oIter->first < nIdx )
+                oMapOGRFieldIdxtoFCFieldIdx[oIter->first] = oIter->second;
+            else if( oIter->first > nIdx )
+                oMapOGRFieldIdxtoFCFieldIdx[oIter->first - 1] = oIter->second;
+        }
+        m_oMapOGRFieldIdxtoFCFieldIdx = oMapOGRFieldIdxtoFCFieldIdx;
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                            InsertNewField()                          */
+/************************************************************************/
+
+void OGRGMLASLayer::InsertNewField( int nInsertPos,
+                                    OGRFieldDefn& oFieldDefn,
+                                    const CPLString& osXPath )
+{
+    CPLAssert( nInsertPos >= 0 && nInsertPos <= m_poFeatureDefn->GetFieldCount() );
+    m_poFeatureDefn->AddFieldDefn( &oFieldDefn );
+    int* panMap = new int[ m_poFeatureDefn->GetFieldCount() ];
+    for( int i = 0; i < nInsertPos; ++i )
+    {
+        panMap[i] = i;
+    }
+    panMap[nInsertPos] = m_poFeatureDefn->GetFieldCount() - 1;
+    for( int i = nInsertPos + 1; i <  m_poFeatureDefn->GetFieldCount(); ++i )
+    {
+        panMap[i] = i - 1;
+    }
+    m_poFeatureDefn->ReorderFieldDefns( panMap );
+    delete[] panMap;
+
+    // Refresh maps
+    {
+        std::map<CPLString, int>       oMapFieldXPathToOGRFieldIdx;
+        std::map<CPLString, int>::const_iterator oIter =
+                            m_oMapFieldXPathToOGRFieldIdx.begin();
+        for( ; oIter != m_oMapFieldXPathToOGRFieldIdx.end(); ++oIter )
+        {
+            if( oIter->second < nInsertPos )
+                oMapFieldXPathToOGRFieldIdx[oIter->first] = oIter->second;
+            else
+                oMapFieldXPathToOGRFieldIdx[oIter->first] = oIter->second + 1;
+        }
+        m_oMapFieldXPathToOGRFieldIdx = oMapFieldXPathToOGRFieldIdx;
+        m_oMapFieldXPathToOGRFieldIdx[ osXPath ] = nInsertPos;
+    }
+
+    {
+        std::map<int, int>             oMapOGRFieldIdxtoFCFieldIdx;
+        std::map<int, int>::const_iterator oIter =
+                            m_oMapOGRFieldIdxtoFCFieldIdx.begin();
+        for( ; oIter != m_oMapOGRFieldIdxtoFCFieldIdx.end(); ++oIter )
+        {
+            if( oIter->first < nInsertPos )
+                oMapOGRFieldIdxtoFCFieldIdx[oIter->first] = oIter->second;
+            else
+                oMapOGRFieldIdxtoFCFieldIdx[oIter->first + 1] = oIter->second;
+        }
+        m_oMapOGRFieldIdxtoFCFieldIdx = oMapOGRFieldIdxtoFCFieldIdx;
+    }
+}
+
+/************************************************************************/
+/*                       GetOGRFieldIndexFromXPath()                    */
+/************************************************************************/
+
+int OGRGMLASLayer::GetOGRFieldIndexFromXPath(const CPLString& osXPath) const
+{
+    std::map<CPLString, int>::const_iterator oIter =
+        m_oMapFieldXPathToOGRFieldIdx.find(osXPath);
+    if( oIter == m_oMapFieldXPathToOGRFieldIdx.end() )
+        return -1;
+    return oIter->second;
+}
+
+/************************************************************************/
+/*                      GetOGRGeomFieldIndexFromXPath()                 */
+/************************************************************************/
+
+int OGRGMLASLayer::GetOGRGeomFieldIndexFromXPath(const CPLString& osXPath) const
+{
+    std::map<CPLString, int>::const_iterator oIter =
+        m_oMapFieldXPathToOGRGeomFieldIdx.find(osXPath);
+    if( oIter == m_oMapFieldXPathToOGRGeomFieldIdx.end() )
+        return -1;
+    return oIter->second;
+}
+
+/************************************************************************/
+/*                     GetFCFieldIndexFromOGRFieldIdx()                 */
+/************************************************************************/
+
+int OGRGMLASLayer::GetFCFieldIndexFromOGRFieldIdx(int iOGRFieldIdx) const
+{
+    std::map<int, int>::const_iterator oIter =
+        m_oMapOGRFieldIdxtoFCFieldIdx.find(iOGRFieldIdx);
+    if( oIter == m_oMapOGRFieldIdxtoFCFieldIdx.end() )
+        return -1;
+    return oIter->second;
+}
+
+/************************************************************************/
+/*                     GetFCFieldIndexFromXPath()                       */
+/************************************************************************/
+
+int OGRGMLASLayer::GetFCFieldIndexFromXPath(const CPLString& osXPath) const
+{
+    std::map<CPLString, int>::const_iterator oIter =
+        m_oMapFieldXPathToFCFieldIdx.find(osXPath);
+    if( oIter == m_oMapFieldXPathToFCFieldIdx.end() )
+        return -1;
+    return oIter->second;
+}
+
+/************************************************************************/
+/*                  GetFCFieldIndexFromOGRGeomFieldIdx()                */
+/************************************************************************/
+
+int OGRGMLASLayer::GetFCFieldIndexFromOGRGeomFieldIdx(int iOGRGeomFieldIdx) const
+{
+    std::map<int, int>::const_iterator oIter =
+        m_oMapOGRGeomFieldIdxtoFCFieldIdx.find(iOGRGeomFieldIdx);
+    if( oIter == m_oMapOGRGeomFieldIdxtoFCFieldIdx.end() )
+        return -1;
+    return oIter->second;
+}
+
+/************************************************************************/
+/*                              GetLayerDefn()                          */
+/************************************************************************/
+
+OGRFeatureDefn* OGRGMLASLayer::GetLayerDefn()
+{
+    if( !m_bLayerDefnFinalized && m_poDS->IsLayerInitFinished() )
+    {
+        // If we haven't yet determined the SRS of geometry columns, do it now
+        m_bLayerDefnFinalized = true;
+        if( m_poFeatureDefn->GetGeomFieldCount() > 0 ||
+            !m_poDS->GetConf().m_oXLinkResolution.m_aoURLSpecificRules.empty() )
+        {
+            if( m_poReader == NULL )
+                InitReader();
+        }
+    }
+    return m_poFeatureDefn;
+}
+
+/************************************************************************/
+/*                              ResetReading()                          */
+/************************************************************************/
+
+void OGRGMLASLayer::ResetReading()
+{
+    delete m_poReader;
+    m_poReader = NULL;
+    m_bEOF = false;
+}
+
+/************************************************************************/
+/*                              InitReader()                            */
+/************************************************************************/
+
+bool OGRGMLASLayer::InitReader()
+{
+    CPLAssert( m_poReader == NULL );
+
+    m_poReader = m_poDS->CreateReader( m_fpGML );
+    m_bLayerDefnFinalized = true;
+    if( m_poReader != NULL )
+    {
+        m_poReader->SetLayerOfInterest( this );
+        return true;
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                          GetNextRawFeature()                         */
+/************************************************************************/
+
+OGRFeature* OGRGMLASLayer::GetNextRawFeature()
+{
+    if( m_poReader == NULL && !InitReader() )
+        return NULL;
+
+    return m_poReader->GetNextFeature();
+}
+
+/************************************************************************/
+/*                            EvaluateFilter()                          */
+/************************************************************************/
+
+bool OGRGMLASLayer::EvaluateFilter( OGRFeature* poFeature )
+{
+    return (m_poFilterGeom == NULL
+             || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature ));
+}
+
+/************************************************************************/
+/*                            GetNextFeature()                          */
+/************************************************************************/
+
+OGRFeature* OGRGMLASLayer::GetNextFeature()
+{
+    if( m_bEOF )
+        return NULL;
+
+    while( true )
+    {
+        OGRFeature *poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
+        {
+            // Avoid keeping too many file descriptor opened
+            if( m_fpGML != NULL )
+                m_poDS->PushUnusedGMLFilePointer(m_fpGML);
+            m_fpGML = NULL;
+            delete m_poReader;
+            m_poReader = NULL;
+            m_bEOF = true;
+            return NULL;
+        }
+
+        if( EvaluateFilter(poFeature) )
+        {
+            return poFeature;
+        }
+
+        delete poFeature;
+    }
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlasreader.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlasreader.cpp
new file mode 100644
index 0000000..91b3548
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlasreader.cpp
@@ -0,0 +1,3198 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+
+#include "ogr_p.h"
+
+#include "ogr_json_header.h"
+
+CPL_CVSID("$Id: ogrgmlasreader.cpp 37972 2017-04-12 16:13:12Z rouault $");
+
+/************************************************************************/
+/*                        GMLASBinInputStream                           */
+/************************************************************************/
+
+class GMLASBinInputStream : public BinInputStream
+{
+    VSILFILE*         m_fp;
+
+public :
+
+    explicit GMLASBinInputStream(VSILFILE* fp);
+    virtual ~GMLASBinInputStream();
+
+    virtual XMLFilePos curPos() const override;
+    virtual XMLSize_t readBytes(XMLByte* const toFill, const XMLSize_t maxToRead) override;
+    virtual const XMLCh* getContentType() const override ;
+};
+
+/************************************************************************/
+/*                        GMLASBinInputStream()                         */
+/************************************************************************/
+
+GMLASBinInputStream::GMLASBinInputStream(VSILFILE* fp)
+{
+    m_fp = fp;
+    VSIFSeekL(fp, 0, SEEK_SET);
+}
+
+/************************************************************************/
+/*                       ~GMLASBinInputStream()                         */
+/************************************************************************/
+
+GMLASBinInputStream::~ GMLASBinInputStream()
+{
+}
+
+/************************************************************************/
+/*                                curPos()                              */
+/************************************************************************/
+
+XMLFilePos GMLASBinInputStream::curPos() const
+{
+    return (XMLFilePos)VSIFTellL(m_fp);
+}
+
+/************************************************************************/
+/*                               readBytes()                            */
+/************************************************************************/
+
+XMLSize_t GMLASBinInputStream::readBytes(XMLByte* const toFill,
+                                         const XMLSize_t maxToRead)
+{
+    return (XMLSize_t)VSIFReadL(toFill, 1, maxToRead, m_fp);
+}
+
+/************************************************************************/
+/*                            getContentType()                          */
+/************************************************************************/
+
+const XMLCh* GMLASBinInputStream::getContentType() const
+{
+    return NULL;
+}
+
+/************************************************************************/
+/*                          GMLASInputSource()                          */
+/************************************************************************/
+
+GMLASInputSource::GMLASInputSource(const char* pszFilename,
+                                   VSILFILE* fp,
+                                   bool bOwnFP,
+                                   MemoryManager* const manager)
+    : InputSource(manager),
+      m_osFilename( pszFilename )
+{
+    m_fp = fp;
+    m_bOwnFP = bOwnFP;
+    XMLCh* pFilename = XMLString::transcode(pszFilename);
+    setPublicId(pFilename);
+    setSystemId(pFilename);
+    XMLString::release( &pFilename );
+    m_nCounter = 0;
+    m_pnCounter = &m_nCounter;
+    m_cbk = NULL;
+}
+
+/************************************************************************/
+/*                        SetClosingCallback()                          */
+/************************************************************************/
+
+void GMLASInputSource::SetClosingCallback( IGMLASInputSourceClosing* cbk )
+{
+    m_cbk = cbk;
+}
+
+/************************************************************************/
+/*                         ~GMLASInputSource()                          */
+/************************************************************************/
+
+GMLASInputSource::~GMLASInputSource()
+{
+    if( m_cbk )
+        m_cbk->notifyClosing( m_osFilename );
+    if( m_bOwnFP && m_fp )
+        VSIFCloseL(m_fp);
+}
+
+/************************************************************************/
+/*                              makeStream()                            */
+/************************************************************************/
+
+BinInputStream* GMLASInputSource::makeStream() const
+{
+    // This is a lovely cheating around the const qualifier of this method !
+    // We cannot modify m_nCounter directly, but we can change the value
+    // pointed by m_pnCounter...
+    if( *m_pnCounter != 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "makeStream() called several times on same GMLASInputSource");
+        return NULL;
+    }
+    (*m_pnCounter) ++;
+    if( m_fp == NULL )
+        return NULL;
+    return new GMLASBinInputStream(m_fp);
+}
+
+/************************************************************************/
+/*                            warning()                                 */
+/************************************************************************/
+
+void GMLASErrorHandler::warning (const SAXParseException& e)
+{
+    handle (e, CE_Warning);
+}
+
+/************************************************************************/
+/*                             error()                                  */
+/************************************************************************/
+
+void GMLASErrorHandler::error (const SAXParseException& e)
+{
+    m_bFailed = true;
+    handle (e, CE_Failure);
+}
+
+/************************************************************************/
+/*                          fatalError()                                */
+/************************************************************************/
+
+void GMLASErrorHandler::fatalError (const SAXParseException& e)
+{
+    m_bFailed = true;
+    handle (e, CE_Failure);
+}
+
+/************************************************************************/
+/*                            handle()                                  */
+/************************************************************************/
+
+void GMLASErrorHandler::handle (const SAXParseException& e, CPLErr eErr)
+{
+    const XMLCh* resourceId (e.getPublicId());
+
+    if ( resourceId == NULL || resourceId[0] == 0 )
+        resourceId = e.getSystemId();
+
+    CPLString osErrorMsg(transcode(e.getMessage()));
+    if( m_bSchemaFullChecking &&
+        osErrorMsg.find("forbidden restriction of any particle") !=
+                                                            std::string::npos )
+    {
+        osErrorMsg += ". You may retry with the " +
+                      CPLString(szSCHEMA_FULL_CHECKING_OPTION) +
+                      "=NO open option";
+    }
+    else if( !m_bHandleMultipleImports && osErrorMsg.find("not found") !=
+                                                            std::string::npos )
+    {
+        osErrorMsg += ". You may retry with the " +
+                      CPLString(szHANDLE_MULTIPLE_IMPORTS_OPTION) +
+                      "=YES open option";
+    }
+    CPLError(eErr, CPLE_AppDefined, "%s:%d:%d %s",
+             transcode(resourceId).c_str(),
+             static_cast<int>(e.getLineNumber()),
+             static_cast<int>(e.getColumnNumber()),
+             osErrorMsg.c_str());
+}
+
+/************************************************************************/
+/*                     GMLASBaseEntityResolver()                        */
+/************************************************************************/
+
+GMLASBaseEntityResolver::GMLASBaseEntityResolver(const CPLString& osBasePath,
+                                                 GMLASXSDCache& oCache)
+    : m_oCache(oCache)
+{
+    m_aosPathStack.push_back(osBasePath);
+}
+
+/************************************************************************/
+/*                    ~GMLASBaseEntityResolver()                        */
+/************************************************************************/
+
+GMLASBaseEntityResolver::~GMLASBaseEntityResolver()
+{
+    CPLAssert( m_aosPathStack.size() == 1 );
+}
+
+/************************************************************************/
+/*                            notifyClosing()                           */
+/************************************************************************/
+
+/* Called by GMLASInputSource destructor. This is useful for use to */
+/* know where a .xsd has been finished from processing. Note that we */
+/* strongly depend on Xerces behaviour here... */
+void GMLASBaseEntityResolver::notifyClosing(const CPLString& osFilename )
+{
+    CPLDebug("GMLAS", "Closing %s", osFilename.c_str());
+
+    CPLAssert( m_aosPathStack.back() ==
+                                CPLString(CPLGetDirname(osFilename)) );
+    m_aosPathStack.pop_back();
+}
+
+/************************************************************************/
+/*                            SetBasePath()                             */
+/************************************************************************/
+
+void GMLASBaseEntityResolver::SetBasePath(const CPLString& osBasePath)
+{
+    CPLAssert( m_aosPathStack.size() == 1 );
+    m_aosPathStack[0] = osBasePath;
+}
+
+/************************************************************************/
+/*                         DoExtraSchemaProcessing()                    */
+/************************************************************************/
+
+void GMLASBaseEntityResolver::DoExtraSchemaProcessing(
+                                             const CPLString& /*osFilename*/,
+                                             VSILFILE* /*fp*/)
+{
+}
+
+/************************************************************************/
+/*                         resolveEntity()                              */
+/************************************************************************/
+
+InputSource* GMLASBaseEntityResolver::resolveEntity(
+                                                const XMLCh* const /*publicId*/,
+                                                const XMLCh* const systemId)
+{
+    // Can happen on things like <xs:import namespace="http://www.w3.org/XML/1998/namespace"/>
+    if( systemId == NULL )
+        return NULL;
+
+    CPLString osSystemId(transcode(systemId));
+
+    if( osSystemId.find("/gml/2.1.2/") != std::string::npos )
+        m_osGMLVersionFound = "2.1.2";
+    else if( osSystemId.find("/gml/3.1.1/") != std::string::npos )
+        m_osGMLVersionFound = "3.1.1";
+    else if( osSystemId.find("/gml/3.2.1/") != std::string::npos )
+        m_osGMLVersionFound = "3.2.1";
+
+    CPLString osNewPath;
+    VSILFILE* fp = m_oCache.Open(osSystemId,
+                                 m_aosPathStack.back(),
+                                 osNewPath);
+
+    if( fp != NULL )
+    {
+        if( osNewPath.find("/vsicurl_streaming/") == 0 )
+            m_oSetSchemaURLs.insert(
+                            osNewPath.substr(strlen("/vsicurl_streaming/")));
+        else
+            m_oSetSchemaURLs.insert(osNewPath);
+
+        CPLDebug("GMLAS", "Opening %s", osNewPath.c_str());
+        DoExtraSchemaProcessing( osNewPath, fp );
+    }
+
+    m_aosPathStack.push_back( CPLGetDirname(osNewPath) );
+    GMLASInputSource* poIS = new GMLASInputSource(osNewPath, fp, true);
+    poIS->SetClosingCallback(this);
+    return poIS;
+}
+
+/************************************************************************/
+/*                             Dump()                                   */
+/************************************************************************/
+
+void GMLASReader::Context::Dump() const
+{
+    CPLDebug("GMLAS", "Context");
+    CPLDebug("GMLAS", "  m_nLevel = %d", m_nLevel);
+    CPLDebug("GMLAS", "  m_poFeature = %p", m_poFeature);
+    const char* pszDebug = CPLGetConfigOption("CPL_DEBUG", "OFF");
+    if( EQUAL(pszDebug, "ON") || EQUAL(pszDebug, "GMLAS") )
+    {
+        if( m_poFeature )
+            m_poFeature->DumpReadable(stderr);
+    }
+    CPLDebug("GMLAS", "  m_poLayer = %p (%s)",
+             m_poLayer, m_poLayer ? m_poLayer->GetName() : "");
+    CPLDebug("GMLAS", "  m_poGroupLayer = %p (%s)",
+             m_poGroupLayer, m_poGroupLayer ? m_poGroupLayer->GetName() : "");
+    CPLDebug("GMLAS", "  m_nGroupLayerLevel = %d", m_nGroupLayerLevel);
+    CPLDebug("GMLAS", "  m_nLastFieldIdxGroupLayer = %d",
+             m_nLastFieldIdxGroupLayer);
+    CPLDebug("GMLAS", "  m_osCurSubXPath = %s",
+             m_osCurSubXPath.c_str());
+}
+
+/************************************************************************/
+/*                             GMLASReader()                            */
+/************************************************************************/
+
+GMLASReader::GMLASReader(GMLASXSDCache& oCache,
+                         const GMLASXPathMatcher& oIgnoredXPathMatcher,
+                         GMLASXLinkResolver& oXLinkResolver)
+    : m_oCache(oCache)
+    , m_oIgnoredXPathMatcher(oIgnoredXPathMatcher)
+    , m_oXLinkResolver(oXLinkResolver)
+{
+    m_bParsingError = false;
+    m_poSAXReader = NULL;
+    m_fp = NULL;
+    m_GMLInputSource = NULL;
+    m_bFirstIteration = true;
+    m_bEOF = false;
+    m_bInterrupted = false;
+    m_papoLayers = NULL;
+    m_nLevel = 0;
+    m_oCurCtxt.m_nLevel = 0;
+    m_oCurCtxt.m_poLayer = NULL;
+    m_oCurCtxt.m_poGroupLayer = NULL;
+    m_oCurCtxt.m_nGroupLayerLevel = -1;
+    m_oCurCtxt.m_nLastFieldIdxGroupLayer = -1;
+    m_oCurCtxt.m_poFeature = NULL;
+    m_nCurFieldIdx = -1;
+    m_nCurGeomFieldIdx = -1;
+    m_nCurFieldLevel = 0;
+    m_bIsXMLBlob = false;
+    m_bIsXMLBlobIncludeUpper = false;
+    m_nTextContentListEstimatedSize = 0;
+    m_poLayerOfInterest = NULL;
+    m_nMaxLevel = atoi(CPLGetConfigOption("GMLAS_XML_MAX_LEVEL", "100"));
+    m_nMaxContentSize = static_cast<size_t>(
+          atoi(CPLGetConfigOption("GMLAS_XML_MAX_CONTENT_SIZE", "512000000")));
+    m_bValidate = false;
+    m_poEntityResolver = NULL;
+    m_nLevelSilentIgnoredXPath = -1;
+    m_eSwapCoordinates = GMLAS_SWAP_AUTO;
+    m_bInitialPass = false;
+    m_bProcessSWEDataArray = false;
+    m_nSWEDataArrayLevel = -1;
+    m_nFileSize = 0;
+    m_bWarnUnexpected =
+        CPLTestBool(CPLGetConfigOption("GMLAS_WARN_UNEXPECTED", "FALSE"));
+    m_nSWEDataArrayLayerIdx = 0;
+}
+
+/************************************************************************/
+/*                            ~GMLASReader()                            */
+/************************************************************************/
+
+GMLASReader::~GMLASReader()
+{
+    delete m_poSAXReader;
+    delete m_GMLInputSource;
+    if( m_oCurCtxt.m_poFeature != NULL && !m_aoStackContext.empty() &&
+        m_oCurCtxt.m_poFeature != m_aoStackContext.back().m_poFeature )
+    {
+        CPLDebug("GMLAS", "Delete feature m_oCurCtxt.m_poFeature=%p",
+                 m_oCurCtxt.m_poFeature);
+        delete m_oCurCtxt.m_poFeature;
+    }
+    for( size_t i = 0; i < m_aoStackContext.size(); i++ )
+    {
+        if( i == 0 ||
+            (i > 0 && m_aoStackContext[i].m_poFeature !=
+                                        m_aoStackContext[i-1].m_poFeature) )
+        {
+            CPLDebug("GMLAS",
+                     "Delete feature m_aoStackContext[%d].m_poFeature=%p",
+                    static_cast<int>(i), m_aoStackContext[i].m_poFeature);
+            delete m_aoStackContext[i].m_poFeature;
+        }
+    }
+    for( size_t i = 0; i < m_aoFeaturesReady.size(); i++ )
+    {
+        CPLDebug("GMLAS", "Delete feature m_aoFeaturesReady[%d].first=%p",
+                 static_cast<int>(i), m_aoFeaturesReady[i].first);
+        delete m_aoFeaturesReady[i].first;
+    }
+    if( !m_apsXMLNodeStack.empty() )
+    {
+        CPLDestroyXMLNode(m_apsXMLNodeStack[0].psNode);
+    }
+    // No need to take care of m_apoSWEDataArrayLayers. Ownerships belongs to
+    // the datasource.
+    delete m_poEntityResolver;
+}
+
+/************************************************************************/
+/*                          SetLayerOfInterest()                        */
+/************************************************************************/
+
+void GMLASReader::SetLayerOfInterest( OGRGMLASLayer* poLayer )
+{
+    m_poLayerOfInterest = poLayer;
+}
+
+/************************************************************************/
+/*                        SetSWEDataArrayLayers()                       */
+/************************************************************************/
+
+void GMLASReader::SetSWEDataArrayLayers( const std::vector<OGRGMLASLayer*>& ar )
+{
+    m_apoSWEDataArrayLayers = ar;
+    m_bProcessSWEDataArray = !ar.empty();
+}
+
+/************************************************************************/
+/*                          LoadXSDInParser()                           */
+/************************************************************************/
+
+bool GMLASReader::LoadXSDInParser( SAX2XMLReader* poParser,
+                                   GMLASXSDCache& oCache,
+                                   GMLASBaseEntityResolver& oXSDEntityResolver,
+                                   const CPLString& osBaseDirname,
+                                   const CPLString& osXSDFilename,
+                                   Grammar** ppoGrammar,
+                                   bool bSchemaFullChecking,
+                                   bool bHandleMultipleImports )
+{
+    if( ppoGrammar != NULL )
+        *ppoGrammar = NULL;
+
+    const CPLString osModifXSDFilename(
+        (osXSDFilename.find("http://") != 0 &&
+        osXSDFilename.find("https://") != 0 &&
+        CPLIsFilenameRelative(osXSDFilename)) ?
+            CPLString(CPLFormFilename(osBaseDirname, osXSDFilename, NULL)) :
+            osXSDFilename );
+    CPLString osResolvedFilename;
+    VSILFILE* fpXSD = oCache.Open( osModifXSDFilename, CPLString(),
+                                   osResolvedFilename );
+    if( fpXSD == NULL )
+    {
+        return false;
+    }
+
+    poParser->setFeature (XMLUni::fgXercesSchemaFullChecking,
+                            bSchemaFullChecking);
+    poParser->setFeature( XMLUni::fgXercesHandleMultipleImports,
+                            bHandleMultipleImports );
+
+    // Install a temporary entity resolved based on the current XSD
+    CPLString osXSDDirname( CPLGetDirname(osModifXSDFilename) );
+    if( osXSDFilename.find("http://") == 0 ||
+        osXSDFilename.find("https://") == 0 )
+    {
+        osXSDDirname = CPLGetDirname(("/vsicurl_streaming/" +
+                                     osModifXSDFilename).c_str());
+    }
+    oXSDEntityResolver.SetBasePath(osXSDDirname);
+    oXSDEntityResolver.DoExtraSchemaProcessing( osResolvedFilename, fpXSD );
+
+    EntityResolver* poOldEntityResolver = poParser->getEntityResolver();
+    poParser->setEntityResolver( &oXSDEntityResolver );
+
+    // Install a temporary error handler
+    GMLASErrorHandler oErrorHandler;
+    oErrorHandler.SetSchemaFullCheckingEnabled( bSchemaFullChecking );
+    oErrorHandler.SetHandleMultipleImportsEnabled( bHandleMultipleImports );
+    ErrorHandler* poOldErrorHandler = poParser->getErrorHandler();
+    poParser->setErrorHandler( &oErrorHandler);
+
+    GMLASInputSource oSource(osResolvedFilename, fpXSD, false);
+    const bool bCacheGrammar = true;
+    Grammar* poGrammar = poParser->loadGrammar(oSource,
+                                            Grammar::SchemaGrammarType,
+                                            bCacheGrammar);
+
+    // Restore previous handlers
+    poParser->setEntityResolver( poOldEntityResolver );
+    poParser->setErrorHandler( poOldErrorHandler );
+    VSIFCloseL(fpXSD);
+
+    if( poGrammar == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "loadGrammar failed");
+        return false;
+    }
+    if( oErrorHandler.hasFailed() )
+    {
+        return false;
+    }
+
+    if( ppoGrammar != NULL )
+        *ppoGrammar = poGrammar;
+
+    return true;
+}
+
+/************************************************************************/
+/*                                  Init()                              */
+/************************************************************************/
+
+bool GMLASReader::Init(const char* pszFilename,
+                       VSILFILE* fp,
+                       const std::map<CPLString, CPLString>& oMapURIToPrefix,
+                       std::vector<OGRGMLASLayer*>* papoLayers,
+                       bool bValidate,
+                       const std::vector<PairURIFilename>& aoXSDs,
+                       bool bSchemaFullChecking,
+                       bool bHandleMultipleImports)
+{
+    m_oMapURIToPrefix = oMapURIToPrefix;
+    m_papoLayers = papoLayers;
+    m_bValidate = bValidate;
+
+    m_poSAXReader = XMLReaderFactory::createXMLReader();
+
+    // Commonly useful configuration.
+    //
+    m_poSAXReader->setFeature (XMLUni::fgSAX2CoreNameSpaces, true);
+    m_poSAXReader->setFeature (XMLUni::fgSAX2CoreNameSpacePrefixes, true);
+
+    m_poSAXReader->setContentHandler( this );
+    m_poSAXReader->setLexicalHandler( this );
+    m_poSAXReader->setDTDHandler( this );
+
+    m_oErrorHandler.SetSchemaFullCheckingEnabled( bSchemaFullChecking );
+    m_oErrorHandler.SetHandleMultipleImportsEnabled( bHandleMultipleImports );
+    m_poSAXReader->setErrorHandler(&m_oErrorHandler);
+
+    m_poSAXReader->setFeature (XMLUni::fgXercesSchemaFullChecking,
+                            bSchemaFullChecking);
+    m_poSAXReader->setFeature( XMLUni::fgXercesHandleMultipleImports,
+                            bHandleMultipleImports );
+
+    if( bValidate )
+    {
+        // Enable validation.
+        m_poSAXReader->setFeature (XMLUni::fgSAX2CoreValidation, true);
+        m_poSAXReader->setFeature (XMLUni::fgXercesSchema, true);
+
+        // We want all errors to be reported
+        m_poSAXReader->setFeature (XMLUni::fgXercesValidationErrorAsFatal, false);
+
+        CPLString osBaseDirname( CPLGetDirname(pszFilename) );
+
+        // In the case the schemas are explicitly passed, we must do special
+        // processing
+        if( !aoXSDs.empty() )
+        {
+            GMLASBaseEntityResolver oXSDEntityResolver( CPLString(), m_oCache );
+            for( size_t i = 0; i < aoXSDs.size(); i++ )
+            {
+                const CPLString osXSDFilename(aoXSDs[i].second);
+                if( !LoadXSDInParser( m_poSAXReader, m_oCache,
+                                      oXSDEntityResolver,
+                                      osBaseDirname, osXSDFilename,
+                                      NULL,
+                                      bSchemaFullChecking,
+                                      bHandleMultipleImports) )
+                {
+                    return false;
+                }
+            }
+
+            // Make sure our previously loaded schemas are used
+            m_poSAXReader->setFeature (XMLUni::fgXercesUseCachedGrammarInParse,
+                                       true);
+
+            // Don't load schemas from any other source (e.g., from XML document's
+            // xsi:schemaLocation attributes).
+            //
+            m_poSAXReader->setFeature (XMLUni::fgXercesLoadSchema, false);
+        }
+
+        // Install entity resolver based on XML file
+        m_poEntityResolver = new GMLASBaseEntityResolver(
+                                                osBaseDirname,
+                                                m_oCache );
+        m_poSAXReader->setEntityResolver( m_poEntityResolver );
+    }
+    else
+    {
+        // Don't load schemas from any other source (e.g., from XML document's
+        // xsi:schemaLocation attributes).
+        //
+        m_poSAXReader->setFeature (XMLUni::fgXercesLoadSchema, false);
+        m_poSAXReader->setEntityResolver( this );
+    }
+
+    m_fp = fp;
+    m_GMLInputSource = new GMLASInputSource(pszFilename, fp, false);
+
+    return true;
+}
+
+/************************************************************************/
+/*                             IsArrayType()                            */
+/************************************************************************/
+
+static bool IsArrayType( OGRFieldType eType )
+{
+    return eType == OFTIntegerList ||
+           eType == OFTInteger64List ||
+           eType == OFTRealList ||
+           eType == OFTStringList;
+}
+
+/************************************************************************/
+/*                                SetField()                            */
+/************************************************************************/
+
+void GMLASReader::SetField( OGRFeature* poFeature,
+                            OGRGMLASLayer* poLayer,
+                            int nAttrIdx,
+                            const CPLString& osAttrValue )
+{
+    const OGRFieldType eType(poFeature->GetFieldDefnRef(nAttrIdx)->GetType());
+    if( osAttrValue.empty() )
+    {
+        if( eType == OFTString &&
+            !poFeature->GetFieldDefnRef(nAttrIdx)->IsNullable() )
+        {
+            poFeature->SetField( nAttrIdx, "" );
+        }
+    }
+    else if( eType == OFTDateTime )
+    {
+        OGRField sField;
+        if( OGRParseXMLDateTime(
+                (m_bInitialPass) ? "1970-01-01T00:00:00" : osAttrValue.c_str(),
+                &sField ) )
+        {
+            poFeature->SetField( nAttrIdx, &sField );
+        }
+    }
+    // Transform boolean values to something that OGR understands
+    else if( eType == OFTInteger &&
+             poFeature->GetFieldDefnRef(nAttrIdx)->GetSubType() == OFSTBoolean )
+    {
+        if( osAttrValue == "true" )
+            poFeature->SetField( nAttrIdx, TRUE );
+        else
+            poFeature->SetField( nAttrIdx, FALSE );
+    }
+    else if( eType == OFTBinary )
+    {
+        const int nFCFieldIdx =
+            poLayer->GetFCFieldIndexFromOGRFieldIdx(nAttrIdx);
+        if( nFCFieldIdx >= 0 )
+        {
+            const GMLASField& oField(
+                poLayer->GetFeatureClass().GetFields()[nFCFieldIdx]);
+            if( m_bInitialPass )
+            {
+                poFeature->SetField( nAttrIdx, 1, (GByte*)("X") );
+            }
+            else if( oField.GetType() == GMLAS_FT_BASE64BINARY )
+            {
+                GByte* pabyBuffer = reinterpret_cast<GByte*>(
+                                                    CPLStrdup(osAttrValue));
+                int nBytes = CPLBase64DecodeInPlace(pabyBuffer);
+                poFeature->SetField( nAttrIdx, nBytes, pabyBuffer );
+                CPLFree(pabyBuffer);
+            }
+            else
+            {
+                int nBytes = 0;
+                GByte* pabyBuffer = CPLHexToBinary( osAttrValue, &nBytes );
+                poFeature->SetField( nAttrIdx, nBytes, pabyBuffer );
+                CPLFree(pabyBuffer);
+            }
+        }
+    }
+    else if( IsArrayType(eType) )
+    {
+        const int nFCFieldIdx =
+            poLayer->GetFCFieldIndexFromOGRFieldIdx(nAttrIdx);
+        if( nFCFieldIdx >= 0 &&
+            poLayer->GetFeatureClass().GetFields()[nFCFieldIdx].IsList() )
+        {
+            char** papszTokens = CSLTokenizeString2( osAttrValue.c_str(), " ", 0 );
+            if( eType == OFTIntegerList &&
+                poFeature->GetFieldDefnRef(nAttrIdx)->GetSubType() == OFSTBoolean )
+            {
+                for( char** papszIter = papszTokens; *papszIter != NULL; ++papszIter )
+                {
+                    if( strcmp(*papszIter, "true") == 0 )
+                    {
+                        (*papszIter)[0] = '1';
+                        (*papszIter)[1] = '\0';
+                    }
+                    else if( strcmp(*papszIter, "false") == 0 )
+                    {
+                        (*papszIter)[0] = '0';
+                        (*papszIter)[1] = '\0';
+                    }
+                }
+            }
+            poFeature->SetField( nAttrIdx, papszTokens );
+            CSLDestroy(papszTokens);
+        }
+        else
+        {
+            poFeature->SetField( nAttrIdx, osAttrValue.c_str() );
+        }
+    }
+    else
+    {
+        poFeature->SetField( nAttrIdx, osAttrValue.c_str() );
+    }
+}
+
+/************************************************************************/
+/*                          PushFeatureReady()                          */
+/************************************************************************/
+
+void GMLASReader::PushFeatureReady( OGRFeature* poFeature,
+                                    OGRGMLASLayer* poLayer )
+{
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GMLAS", "PushFeatureReady(%p / %s / %s)",
+             poFeature, poFeature->GetDefnRef()->GetName(), poLayer->GetName());
+#endif
+
+    m_aoFeaturesReady.push_back(
+        std::pair<OGRFeature*, OGRGMLASLayer*>(poFeature, poLayer) );
+}
+
+/************************************************************************/
+/*                          CreateNewFeature                            */
+/************************************************************************/
+
+void GMLASReader::CreateNewFeature(const CPLString& osLocalname)
+{
+    m_oCurCtxt.m_poFeature = new OGRFeature(
+                m_oCurCtxt.m_poLayer->GetLayerDefn() );
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GMLAS", "CreateNewFeature(element=%s / layer=%s) = %p",
+             osLocalname.c_str(), m_oCurCtxt.m_poLayer->GetName(),
+             m_oCurCtxt.m_poFeature);
+#endif
+    // Assign FID (1, ...). Only for OGR compliance, but definitely
+    // not a unique ID among datasets with the same schema
+    ++m_oMapGlobalCounter[m_oCurCtxt.m_poLayer];
+    const int nGlobalCounter =
+                    m_oMapGlobalCounter[m_oCurCtxt.m_poLayer];
+    m_oCurCtxt.m_poFeature->SetFID(nGlobalCounter);
+
+    // Find parent ID
+    CPLString osParentId;
+    if( !m_aoStackContext.empty() &&
+        m_oCurCtxt.m_poLayer->GetParentIDFieldIdx() >= 0 )
+    {
+        CPLAssert(m_aoStackContext.back().
+                            m_poLayer->GetIDFieldIdx() >= 0 );
+        osParentId = m_aoStackContext.back().m_poFeature->
+            GetFieldAsString(
+            m_aoStackContext.back().m_poLayer->GetIDFieldIdx() );
+        m_oCurCtxt.m_poFeature->SetField(
+            m_oCurCtxt.m_poLayer->GetParentIDFieldIdx(),
+            osParentId.c_str() );
+    }
+
+    // Should we generate a unique (child) ID from the parent ID ?
+    if( m_oCurCtxt.m_poLayer->IsGeneratedIDField() )
+    {
+        // Local IDs (ie related to a parent feature are fine, but when
+        // we might have cycles, that doesn't work anymore
+        /*
+        ++m_oCurCtxt.m_oMapCounter[m_oCurCtxt.m_poLayer];
+        const int nCounter =
+            m_oCurCtxt.m_oMapCounter[m_oCurCtxt.m_poLayer];*/
+        const int nCounter = nGlobalCounter;
+
+        CPLString osGeneratedID = (osParentId.empty() ? m_osHash : osParentId) +
+                                   "_" + osLocalname +
+                                   CPLSPrintf("_%d", nCounter);
+        m_oCurCtxt.m_poFeature->SetField(
+                        m_oCurCtxt.m_poLayer->GetIDFieldIdx(),
+                        osGeneratedID.c_str() );
+    }
+
+    m_nCurFieldIdx = -1;
+}
+
+/************************************************************************/
+/*                         AttachAsLastChild()                          */
+/************************************************************************/
+
+/* Attach element as the last child of its parent */
+void GMLASReader::AttachAsLastChild(CPLXMLNode* psNode)
+{
+    NodeLastChild& sNodeLastChild = m_apsXMLNodeStack.back();
+    CPLXMLNode* psLastChildParent = sNodeLastChild.psLastChild;
+
+    if (psLastChildParent == NULL)
+    {
+        CPLAssert( sNodeLastChild.psNode );
+        sNodeLastChild.psNode->psChild = psNode;
+    }
+    else
+    {
+        psLastChildParent->psNext = psNode;
+    }
+    sNodeLastChild.psLastChild = psNode;
+}
+
+/************************************************************************/
+/*                         BuildXMLBlobStartElement()                   */
+/************************************************************************/
+
+void GMLASReader::BuildXMLBlobStartElement(const CPLString& osXPath,
+                                           const  Attributes& attrs)
+{
+    if( FillTextContent() )
+    {
+        m_osTextContent += "<";
+        m_osTextContent += osXPath;
+    }
+
+    CPLXMLNode* psNode = NULL;
+    if( m_nCurGeomFieldIdx >= 0 || m_nSWEDataArrayLevel >= 0 )
+    {
+        psNode = CPLCreateXMLNode( NULL, CXT_Element, osXPath );
+        if( !m_apsXMLNodeStack.empty() )
+        {
+            AttachAsLastChild(psNode);
+        }
+    }
+
+    CPLXMLNode* psLastChild = NULL;
+    for(unsigned int i=0; i < attrs.getLength(); i++)
+    {
+        const CPLString& osAttrNSPrefix( m_osAttrNSPrefix =
+            m_oMapURIToPrefix[ transcode( attrs.getURI(i), m_osAttrNSUri ) ] );
+        const CPLString& osAttrLocalname(
+                        transcode(attrs.getLocalName(i), m_osAttrLocalName) );
+        const CPLString& osAttrValue(
+                                transcode(attrs.getValue(i), m_osAttrValue) );
+        CPLString& osAttrXPath( m_osAttrXPath );
+        if( !osAttrNSPrefix.empty() )
+        {
+            osAttrXPath.reserve(
+                        osAttrNSPrefix.size() + 1 + osAttrLocalname.size() );
+            osAttrXPath = osAttrNSPrefix;
+            osAttrXPath += ":";
+            osAttrXPath += osAttrLocalname;
+        }
+        else
+        {
+            osAttrXPath = osAttrLocalname;
+        }
+
+        if( psNode != NULL )
+        {
+            CPLXMLNode* psAttrNode = CPLCreateXMLNode( NULL, CXT_Attribute,
+                                                       osAttrXPath );
+            CPLCreateXMLNode(psAttrNode, CXT_Text, osAttrValue);
+
+            if( psLastChild == NULL )
+            {
+                psNode->psChild = psAttrNode;
+            }
+            else
+            {
+                psLastChild->psNext = psAttrNode;
+            }
+            psLastChild = psAttrNode;
+        }
+
+        if( FillTextContent() )
+        {
+            m_osTextContent += " ";
+            m_osTextContent += osAttrXPath;
+            m_osTextContent += "=\"";
+            char* pszEscaped = CPLEscapeString( osAttrValue.c_str(),
+                                        static_cast<int>(osAttrValue.size()),
+                                        CPLES_XML );
+            m_osTextContent += pszEscaped;
+            CPLFree(pszEscaped);
+            m_osTextContent += '"';
+        }
+    }
+    if( FillTextContent() )
+        m_osTextContent += ">";
+
+    if( psNode != NULL )
+    {
+        /* Push the element on the stack */
+        NodeLastChild sNewNodeLastChild;
+        sNewNodeLastChild.psNode = psNode;
+        sNewNodeLastChild.psLastChild = psLastChild;
+        m_apsXMLNodeStack.push_back(sNewNodeLastChild);
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GMLAS", "m_apsXMLNodeStack.push_back()");
+#endif
+    }
+
+    if( m_osTextContent.size() > m_nMaxContentSize )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                "Too much data in a single element");
+        m_bParsingError = true;
+    }
+}
+
+/************************************************************************/
+/*                          GetLayerByXPath()                           */
+/************************************************************************/
+
+OGRGMLASLayer* GMLASReader::GetLayerByXPath( const CPLString& osXPath )
+{
+    for(size_t i = 0; i < m_papoLayers->size(); i++ )
+    {
+        if( (*m_papoLayers)[i]->GetFeatureClass().GetXPath() == osXPath )
+        {
+            return (*m_papoLayers)[i];
+        }
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                            PushContext()                             */
+/************************************************************************/
+
+void GMLASReader::PushContext( const Context& oContext )
+{
+    m_aoStackContext.push_back( oContext );
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GMLAS", "Pushing new context:");
+    oContext.Dump();
+#endif
+}
+
+/************************************************************************/
+/*                            PopContext()                              */
+/************************************************************************/
+
+void GMLASReader::PopContext()
+{
+#ifdef DEBUG_VERBOSE
+    if( !m_aoStackContext.empty() )
+    {
+        CPLDebug("GMLAS", "Poping up context:");
+        m_aoStackContext.back().Dump();
+    }
+#endif
+    m_aoStackContext.pop_back();
+#ifdef DEBUG_VERBOSE
+    if( !m_aoStackContext.empty() )
+    {
+        CPLDebug("GMLAS", "New top of stack is:");
+        m_aoStackContext.back().Dump();
+    }
+#endif
+}
+
+/************************************************************************/
+/*                             startElement()                           */
+/************************************************************************/
+
+/* <xs:group ref="somegroup" maxOccurs="unbounded"/> are particularly hard to
+   deal with since we cannot easily know when the corresponding subfeature
+   is exactly terminated.
+
+   Let's consider:
+
+        <xs:group name="somegroup">
+            <xs:choice>
+                <xs:element name="first_elt_of_group" type="xs:string"/>
+                <xs:element name="second_elt_of_group" type="xs:string"/>
+            </xs:choice>
+        </xs:group>
+
+        <xs:group name="another_group">
+            <xs:choice>
+                <xs:element name="first_elt_of_another_group" type="xs:string"/>
+            </xs:choice>
+        </xs:group>
+
+   There are different cases :
+    *
+              <first_elt_of_group>...</first_elt_of_group>
+              <second_elt_of_group>...</first_elt_of_group>
+              <first_elt_of_group>  <!-- we are here at startElement() -->
+                ...
+              </first_elt_of_group>
+
+    *
+              <first_elt_of_group>...</first_elt_of_group>
+              <first_elt_of_group>  <!-- we are here at startElement() -->
+                ...</first_elt_of_group>
+
+    *
+              <first_elt_of_group>...</first_elt_of_group>
+              <first_elt_of_another_group>  <!-- we are here at startElement() -->
+                ...</first_elt_of_another_group>
+
+    *
+              <first_elt_of_group>...</first_elt_of_group>
+              <some_other_elt>  <!-- we are here at startElement() -->
+                ...</some_other_elt>
+
+    *
+            <first_elt>...</first_elt>
+            <second_elt><sub>...</sub></second_elt>
+            <first_elt> <-- here -->
+                ...</first_elt>
+    *
+                <first_elt_of_group>...</first_elt_of_group>
+            </end_of_enclosing_element>   <!-- we are here at endElement() -->
+*/
+void GMLASReader::startElement(
+            const   XMLCh* const    uri,
+            const   XMLCh* const    localname,
+            const   XMLCh* const
+#ifdef DEBUG_VERBOSE
+                                    qname
+#endif
+            , const   Attributes& attrs
+        )
+{
+    const CPLString& osLocalname( transcode(localname, m_osLocalname) );
+    const CPLString& osNSURI( transcode(uri, m_osNSUri) );
+    const CPLString& osNSPrefix( m_osNSPrefix = m_oMapURIToPrefix[osNSURI] );
+    if( osNSPrefix.empty() )
+        m_osXPath = osLocalname;
+    else
+    {
+        m_osXPath.reserve( osNSPrefix.size() + 1 + osLocalname.size() );
+        m_osXPath = osNSPrefix;
+        m_osXPath += ":";
+        m_osXPath += osLocalname;
+    }
+    const CPLString& osXPath( m_osXPath );
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GMLAS", "startElement(%s / %s)",
+             transcode(qname).c_str(), osXPath.c_str());
+#endif
+    m_anStackXPathLength.push_back(osXPath.size());
+    if( !m_osCurXPath.empty() )
+        m_osCurXPath += "/";
+    m_osCurXPath += osXPath;
+
+#if 0
+    CPLString osSubXPathBefore(m_osCurSubXPath);
+#endif
+    if( !m_osCurSubXPath.empty() )
+    {
+        m_osCurSubXPath += "/";
+        m_osCurSubXPath += osXPath;
+    }
+
+    if( m_bProcessSWEDataArray && m_nSWEDataArrayLevel < 0 &&
+        m_nCurGeomFieldIdx < 0 )
+    {
+        if( osNSURI == szSWE_URI &&
+            osLocalname == "DataArray" )
+        {
+            m_nSWEDataArrayLevel = m_nLevel;
+        }
+    }
+
+    // Deal with XML content
+    if( m_bIsXMLBlob || m_nSWEDataArrayLevel >= 0 )
+    {
+        BuildXMLBlobStartElement(osXPath, attrs);
+    }
+
+    if( m_bIsXMLBlob )
+    {
+        m_nLevel ++;
+        return;
+    }
+
+    if( m_nLevel == m_nMaxLevel )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Too deeply nested XML content");
+        m_bParsingError = true;
+        return;
+    }
+
+    CPLAssert(m_aoFeaturesReady.empty());
+
+    // Look which layer might match the current XPath
+    for(size_t i = 0; i < m_papoLayers->size(); i++ )
+    {
+        const CPLString* posLayerXPath =
+            &((*m_papoLayers)[i]->GetFeatureClass().GetXPath());
+        if( (*m_papoLayers)[i]->GetFeatureClass().IsRepeatedSequence() )
+        {
+            size_t iPosExtra = posLayerXPath->find(szEXTRA_SUFFIX);
+            if (iPosExtra != std::string::npos)
+            {
+                m_osLayerXPath = *posLayerXPath;
+                m_osLayerXPath.resize(iPosExtra);
+                posLayerXPath = &m_osLayerXPath;
+            }
+        }
+
+        const bool bIsGroup = (*m_papoLayers)[i]->GetFeatureClass().IsGroup();
+
+        // Are we entering or staying in a group ?
+        const bool bIsMatchingGroup =
+            (bIsGroup &&
+             (*m_papoLayers)[i]->GetOGRFieldIndexFromXPath(m_osCurSubXPath) != -1 );
+
+        const bool bIsMatchingRepeatedSequence =
+             ((*m_papoLayers)[i]->GetFeatureClass().IsRepeatedSequence()  &&
+             m_oCurCtxt.m_poLayer != NULL &&
+             m_oCurCtxt.m_poLayer != (*m_papoLayers)[i] &&
+             m_oCurCtxt.m_poLayer->GetFeatureClass().GetXPath() ==
+                    *posLayerXPath &&
+             (*m_papoLayers)[i]->GetOGRFieldIndexFromXPath(m_osCurSubXPath) >= 0);
+
+        int nTmpIdx;
+        if( // Case where we haven't yet entered the top-level element, which may
+            // be in container elements
+            (m_osCurSubXPath.empty() &&
+             *posLayerXPath == osXPath && !bIsGroup) ||
+
+            // Case where we are a sub-element of a top-level feature
+            (!m_osCurSubXPath.empty() &&
+             *posLayerXPath == m_osCurSubXPath && !bIsGroup) ||
+
+            // Case where we are a sub-element of a (repeated) group of a
+            // top-level feature
+            bIsMatchingGroup ||
+
+            // Needed to handle sequence_1_unbounded_non_simplifiable.subelement case of data/gmlas_test1.xml
+            bIsMatchingRepeatedSequence ||
+
+            // Case where we go back from a sub-element of a (repeated) group
+            // of a top-level feature to a regular sub-element of that top-level
+            // feature
+            (m_oCurCtxt.m_poGroupLayer != NULL &&
+             ((nTmpIdx = (*m_papoLayers)[i]->GetOGRFieldIndexFromXPath(m_osCurSubXPath)) >= 0 ||
+              nTmpIdx == IDX_COMPOUND_FOLDED)) )
+        {
+#ifdef DEBUG_VERBOSE
+            CPLDebug("GMLAS", "Matches layer %s (%s)",
+                     (*m_papoLayers)[i]->GetName(),
+                     (*m_papoLayers)[i]->GetFeatureClass().GetXPath().c_str());
+#endif
+
+            if( (*m_papoLayers)[i]->GetParent() != NULL &&
+                (*m_papoLayers)[i]->GetParent()->GetFeatureClass().IsRepeatedSequence() &&
+                m_oCurCtxt.m_poGroupLayer != (*m_papoLayers)[i]->GetParent() )
+            {
+                // Yuck! Simulate top-level element of a group if we directly jump
+                // into a nested class of it !
+                /* Something like
+                    <xs:group name="group">
+                        <xs:sequence>
+                            <xs:element name="optional_elt" type="xs:string" minOccurs="0"/>
+                            <xs:element name="elt">
+                                <xs:complexType>
+                                    <xs:sequence>
+                                        <xs:element name="subelt"  type="xs:dateTime" maxOccurs="unbounded"/>
+                                    </xs:sequence>
+                                </xs:complexType>
+                            </xs:element>
+                        </xs:sequence>
+                    </xs:group>
+
+                    <top_element>
+                        <elt><subelt>...</subelt></elt>
+                    </top_element>
+                */
+                m_oCurCtxt.m_poLayer = (*m_papoLayers)[i]->GetParent();
+                m_oCurCtxt.m_poGroupLayer = m_oCurCtxt.m_poLayer;
+                m_oCurCtxt.m_nLevel = m_nLevel;
+                m_oCurCtxt.m_nLastFieldIdxGroupLayer = -1;
+                CreateNewFeature( m_oCurCtxt.m_poLayer->GetName() );
+            }
+
+            bool bPushNewState = true;
+            if( bIsMatchingGroup )
+            {
+                int nFieldIdx =
+                    (*m_papoLayers)[i]->GetOGRFieldIndexFromXPath(m_osCurSubXPath);
+                bool bPushNewFeature = false;
+                if( m_oCurCtxt.m_poGroupLayer == NULL )
+                {
+                    m_oCurCtxt.m_poFeature = NULL;
+                }
+                else if( nFieldIdx < 0 )
+                {
+                    bPushNewState = false;
+                }
+                else if ( m_oCurCtxt.m_nGroupLayerLevel == m_nLevel &&
+                          m_oCurCtxt.m_poGroupLayer != (*m_papoLayers)[i] )
+                {
+#ifdef DEBUG_VERBOSE
+                    CPLDebug("GMLAS", "new feature: group case 1");
+#endif
+                    /* Case like:
+                            <first_elt_of_group>...</first_elt_of_group>
+                            <first_elt_of_another_group>  <!-- we are here at startElement() -->
+                                ...</first_elt_of_group>
+                    */
+                    bPushNewFeature = true;
+                }
+                else if( m_oCurCtxt.m_nGroupLayerLevel == m_nLevel &&
+                         m_oCurCtxt.m_poGroupLayer == (*m_papoLayers)[i] &&
+                         nFieldIdx == m_oCurCtxt.m_nLastFieldIdxGroupLayer &&
+                         !IsArrayType(m_oCurCtxt.m_poFeature->
+                                        GetFieldDefnRef(nFieldIdx)->GetType()))
+                {
+#ifdef DEBUG_VERBOSE
+                    CPLDebug("GMLAS", "new feature: group case 2");
+#endif
+                    /* Case like:
+                        <first_elt>...</first_elt>
+                        <first_elt> <-- here -->
+                    */
+                    bPushNewFeature = true;
+                }
+                else if ( m_oCurCtxt.m_nGroupLayerLevel == m_nLevel &&
+                          nFieldIdx < m_oCurCtxt.m_nLastFieldIdxGroupLayer )
+                {
+#ifdef DEBUG_VERBOSE
+                    CPLDebug("GMLAS", "new feature: group case nFieldIdx < m_oCurCtxt.m_nLastFieldIdxGroupLayer" );
+#endif
+                    /* Case like:
+                            <first_elt_of_group>...</first_elt_of_group>
+                            <second_elt_of_group>...</first_elt_of_group>
+                            <first_elt_of_group>  <!-- we are here at startElement() -->
+                                ...
+                            </first_elt_of_group>
+                    */
+                    bPushNewFeature = true;
+                }
+                else if ( m_oCurCtxt.m_nGroupLayerLevel == m_nLevel + 1 &&
+                          m_oCurCtxt.m_poGroupLayer == (*m_papoLayers)[i] )
+                {
+#ifdef DEBUG_VERBOSE
+                    CPLDebug("GMLAS", "new feature: group case 3");
+#endif
+                    /* Case like:
+                        <first_elt>...</first_elt>
+                        <second_elt><sub>...</sub></second_elt>
+                        <first_elt> <-- here -->
+                            ...</first_elt>
+                    */
+                    bPushNewFeature = true;
+                }
+                if( bPushNewFeature )
+                {
+                    CPLAssert( m_oCurCtxt.m_poFeature );
+                    CPLAssert( m_oCurCtxt.m_poGroupLayer );
+                    //CPLDebug("GMLAS", "Feature ready");
+                    PushFeatureReady(m_oCurCtxt.m_poFeature,
+                                     m_oCurCtxt.m_poGroupLayer);
+                    m_oCurCtxt.m_poFeature = NULL;
+                    m_nCurFieldIdx = -1;
+                }
+                m_oCurCtxt.m_poLayer = (*m_papoLayers)[i];
+                m_oCurCtxt.m_poGroupLayer = (*m_papoLayers)[i];
+                m_oCurCtxt.m_nGroupLayerLevel = m_nLevel;
+                if( nFieldIdx >= 0 )
+                    m_oCurCtxt.m_nLastFieldIdxGroupLayer = nFieldIdx;
+            }
+            else
+            {
+                if( m_oCurCtxt.m_nGroupLayerLevel == m_nLevel &&
+                    (*m_papoLayers)[i] == m_aoStackContext.back().m_poLayer )
+                {
+                    // This is the case where we switch from an element that was
+                    // in a group to a regular element of the same level
+
+                    // Push group feature as ready
+                    CPLAssert( m_oCurCtxt.m_poFeature );
+
+                    //CPLDebug("GMLAS", "Feature ready");
+                    PushFeatureReady(m_oCurCtxt.m_poFeature,
+                                     m_oCurCtxt.m_poGroupLayer);
+
+                    // Restore "top-level" context
+                    CPLAssert( !m_aoStackContext.empty() );
+                    m_oCurCtxt = m_aoStackContext.back();
+                    bPushNewState = false;
+                }
+                else
+                {
+                    if( m_oCurCtxt.m_poGroupLayer )
+                    {
+                        Context oContext;
+                        oContext = m_oCurCtxt;
+                        oContext.m_nLevel = -1;
+                        oContext.Dump();
+                        PushContext( oContext );
+                    }
+
+                    m_oCurCtxt.m_poFeature = NULL;
+                    m_oCurCtxt.m_poGroupLayer = NULL;
+                    m_oCurCtxt.m_nGroupLayerLevel = -1;
+                    m_oCurCtxt.m_nLastFieldIdxGroupLayer = -1;
+                    m_oCurCtxt.m_poLayer = (*m_papoLayers)[i];
+                    if( m_aoStackContext.empty() )
+                        m_osCurSubXPath = osXPath;
+                }
+            }
+
+            if( m_oCurCtxt.m_poFeature == NULL )
+            {
+                CPLAssert( bPushNewState );
+                CreateNewFeature(osLocalname);
+            }
+
+            if( bPushNewState )
+            {
+                Context oContext;
+                oContext = m_oCurCtxt;
+                oContext.m_nLevel = m_nLevel;
+                PushContext( oContext );
+                m_oCurCtxt.m_oMapCounter.clear();
+            }
+            break;
+        }
+    }
+
+    if( m_oCurCtxt.m_poLayer )
+    {
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GMLAS", "Current layer: %s", m_oCurCtxt.m_poLayer->GetName() );
+#endif
+
+
+        bool bHasProcessedAttributes = false;
+
+        // Find if we can match this element with one of our fields
+        int idx = m_oCurCtxt.m_poLayer->
+                            GetOGRFieldIndexFromXPath(m_osCurSubXPath);
+        int geom_idx = m_oCurCtxt.m_poLayer->
+                            GetOGRGeomFieldIndexFromXPath(m_osCurSubXPath);
+
+        if( idx < 0 && idx != IDX_COMPOUND_FOLDED )
+        {
+            /* Special case for a layer that matches everything, as found */
+            /* in swe:extension */
+            idx = m_oCurCtxt.m_poLayer->GetOGRFieldIndexFromXPath(
+              m_oCurCtxt.m_poLayer->GetFeatureClass().GetXPath() + szMATCH_ALL);
+        }
+
+        if( idx >= 0 || geom_idx >= 0 )
+        {
+            // Sanity check. Shouldn't normally happen !
+            if( m_oCurCtxt.m_poFeature == NULL ||
+                m_oCurCtxt.m_poLayer->GetLayerDefn() !=
+                                        m_oCurCtxt.m_poFeature->GetDefnRef() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                            "Inconsistent m_poLayer / m_poFeature state");
+                m_bParsingError = true;
+                return;
+            }
+
+            bool bPushNewFeature = false;
+            const int nFCFieldIdx = (idx >= 0) ?
+                m_oCurCtxt.m_poLayer->GetFCFieldIndexFromOGRFieldIdx(idx) :
+                m_oCurCtxt.m_poLayer->GetFCFieldIndexFromOGRGeomFieldIdx(geom_idx);
+
+            /* For cases like
+                    <xs:element name="element_compound">
+                        <xs:complexType>
+                            <xs:sequence maxOccurs="unbounded">
+                                <xs:element name="subelement1" type="xs:string"/>
+                                <xs:element name="subelement2" type="xs:string"/>
+                            </xs:sequence>
+                        </xs:complexType>
+                    </xs:element>
+
+                    <element_compound>
+                        <subelement1>a</subelement>
+                        <subelement2>b</subelement>
+                        <subelement1>c</subelement>
+                        <subelement2>d</subelement>
+                    </element_compound>
+            */
+
+            if( idx >= 0 && idx < m_nCurFieldIdx )
+            {
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GMLAS", "new feature: idx < m_nCurFieldIdx" );
+#endif
+                bPushNewFeature = true;
+            }
+
+            /* For cases like
+                    <xs:element name="element_compound">
+                        <xs:complexType>
+                            <xs:sequence maxOccurs="unbounded">
+                                <xs:element name="subelement" type="xs:dateTime"/>
+                            </xs:sequence>
+                        </xs:complexType>
+                    </xs:element>
+
+                    <element_compound>
+                        <subelement>2012-01-01T12:34:56Z</subelement>
+                        <subelement>2012-01-02T12:34:56Z</subelement>
+                    </element_compound>
+            */
+            else if( idx >= 0 && idx == m_nCurFieldIdx &&
+                     !IsArrayType(m_oCurCtxt.m_poFeature->
+                                GetFieldDefnRef(m_nCurFieldIdx)->GetType()) &&
+                     // Make sure this isn't a repeated geometry as well
+                     !( geom_idx >= 0 && nFCFieldIdx >= 0 &&
+                        m_oCurCtxt.m_poLayer->GetFeatureClass().GetFields()[
+                                        nFCFieldIdx].GetMaxOccurs() > 1 ) )
+            {
+                bPushNewFeature = true;
+            }
+
+            // Make sure we are in a repeated sequence, otherwise this is
+            // invalid XML
+            if( bPushNewFeature &&
+                !m_oCurCtxt.m_poLayer->GetFeatureClass().IsRepeatedSequence() &&
+                // Case of element within xs:choice
+                !(idx >= 0 && nFCFieldIdx >= 0 &&
+                    m_oCurCtxt.m_poLayer->GetFeatureClass().
+                        GetFields()[nFCFieldIdx].MayAppearOutOfOrder()) )
+            {
+                bPushNewFeature = false;
+                CPLError(CE_Warning, CPLE_AppDefined,
+                            "Unexpected element %s",
+                            m_osCurSubXPath.c_str());
+            }
+
+            if( bPushNewFeature )
+            {
+                //CPLDebug("GMLAS", "Feature ready");
+                PushFeatureReady(m_oCurCtxt.m_poFeature, m_oCurCtxt.m_poLayer);
+                Context oContext = m_aoStackContext.back();
+                m_aoStackContext.pop_back();
+                CreateNewFeature(osLocalname);
+                oContext.m_poFeature = m_oCurCtxt.m_poFeature;
+                m_aoStackContext.push_back( oContext );
+                m_oCurCtxt.m_oMapCounter.clear();
+            }
+
+            if( m_nCurFieldIdx != idx )
+            {
+                m_osTextContentList.Clear();
+                m_nTextContentListEstimatedSize = 0;
+            }
+            m_nCurFieldIdx = idx;
+            m_nCurGeomFieldIdx = geom_idx;
+            m_nCurFieldLevel = m_nLevel + 1;
+            m_osTextContent.clear();
+            m_bIsXMLBlob = false;
+            m_bIsXMLBlobIncludeUpper = false;
+
+#ifdef DEBUG_VERBOSE
+            if( idx >= 0 )
+            {
+                CPLDebug("GMLAS", "Matches field %s", m_oCurCtxt.m_poLayer->
+                         GetLayerDefn()->GetFieldDefn(idx)->GetNameRef() );
+            }
+            if( geom_idx >= 0 )
+            {
+                CPLDebug("GMLAS", "Matches geometry field %s", m_oCurCtxt.m_poLayer->
+                         GetLayerDefn()->GetGeomFieldDefn(geom_idx)->GetNameRef() );
+            }
+#endif
+            if( nFCFieldIdx >= 0 )
+            {
+                const GMLASField& oField(
+                    m_oCurCtxt.m_poLayer->GetFeatureClass().GetFields()[
+                                                                nFCFieldIdx]);
+                m_bIsXMLBlob = (oField.GetType() == GMLAS_FT_ANYTYPE ||
+                                m_nCurGeomFieldIdx != -1 );
+                if( m_bIsXMLBlob )
+                {
+                    CPLAssert( m_nSWEDataArrayLevel < 0 );
+                }
+                m_bIsXMLBlobIncludeUpper = m_bIsXMLBlob &&
+                                            oField.GetIncludeThisEltInBlob();
+                if( m_bIsXMLBlobIncludeUpper )
+                {
+                    BuildXMLBlobStartElement(osXPath, attrs);
+                    m_nLevel ++;
+                    return;
+                }
+
+                // Figure out if it is an element that calls for a related
+                // top-level feature (but without junction table)
+                if( oField.GetCategory() ==
+                                GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK )
+                {
+                    const CPLString& osNestedXPath(oField.GetRelatedClassXPath());
+                    CPLAssert( !osNestedXPath.empty() );
+                    OGRGMLASLayer* poSubLayer = GetLayerByXPath(osNestedXPath);
+                    if( poSubLayer && m_nCurFieldIdx >= 0 )
+                    {
+                        int nOldCurFieldIdx = m_nCurFieldIdx;
+                        OGRFeature* poOldCurFeature = m_oCurCtxt.m_poFeature;
+                        OGRGMLASLayer* poOldLayer = m_oCurCtxt.m_poLayer;
+                        m_oCurCtxt.m_poLayer = poSubLayer;
+                        CreateNewFeature(osLocalname);
+
+                        m_oCurCtxt.m_poGroupLayer = NULL;
+                        m_oCurCtxt.m_nGroupLayerLevel = -1;
+                        m_oCurCtxt.m_nLastFieldIdxGroupLayer = -1;
+
+                        // Install new context
+                        Context oContext;
+                        oContext = m_oCurCtxt;
+                        oContext.m_nLevel = m_nLevel;
+                        oContext.m_osCurSubXPath = m_osCurSubXPath;
+                        m_osCurSubXPath = osNestedXPath;
+#ifdef DEBUG_VERBOSE
+                        CPLDebug("GMLAS",
+                                 "Installing new m_osCurSubXPath from %s to %s",
+                                 oContext.m_osCurSubXPath.c_str(),
+                                 m_osCurSubXPath.c_str());
+#endif
+                        PushContext( oContext );
+                        m_oCurCtxt.m_oMapCounter.clear();
+
+                        // Process attributes now because we might need to
+                        // fetch the child id from them
+                        ProcessAttributes(attrs);
+                        bHasProcessedAttributes = true;
+
+                        CPLString osChildId(
+                            m_oCurCtxt.m_poFeature->GetFieldAsString(
+                                    m_oCurCtxt.m_poLayer->GetIDFieldIdx()));
+                        SetField( poOldCurFeature,
+                                  poOldLayer,
+                                  nOldCurFieldIdx,
+                                  osChildId );
+                    }
+                }
+            }
+        }
+
+#if 0
+        // Case where we have an abstract type and don't know its realizations
+        else if ( idx != IDX_COMPOUND_FOLDED &&
+            (idx = m_oCurCtxt.m_poLayer->GetOGRFieldIndexFromXPath(
+                                    osSubXPathBefore + "/" + "*")) >= 0 &&
+            m_oCurCtxt.m_poGroupLayer == NULL )
+        {
+            m_nCurFieldIdx = idx;
+            m_nCurFieldLevel = m_nLevel + 1;
+            m_osTextContent.clear();
+            m_bIsXMLBlob = true;
+            m_bIsXMLBlobIncludeUpper = true;
+            BuildXMLBlobStartElement(osNSPrefix, osLocalname, attrs);
+            m_nLevel ++;
+            return;
+        }
+#endif
+
+        else if( m_nLevel > m_aoStackContext.back().m_nLevel )
+        {
+            // Figure out if it is an element that calls from a related
+            // top-level feature with a junction table
+            const std::vector<GMLASField>& aoFields =
+                    m_oCurCtxt.m_poLayer->GetFeatureClass().GetFields();
+            for( size_t i = 0; i < aoFields.size(); ++i )
+            {
+                if( aoFields[i].GetCategory() ==
+                        GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE &&
+                    aoFields[i].GetXPath() == m_osCurSubXPath )
+                {
+                    const CPLString& osAbstractElementXPath(
+                                        aoFields[i].GetAbstractElementXPath());
+                    const CPLString& osNestedXPath(
+                                        aoFields[i].GetRelatedClassXPath());
+                    CPLAssert( !osAbstractElementXPath.empty() );
+                    CPLAssert( !osNestedXPath.empty() );
+
+                    OGRGMLASLayer* poJunctionLayer = GetLayerByXPath(
+                        GMLASSchemaAnalyzer::BuildJunctionTableXPath(
+                            osAbstractElementXPath, osNestedXPath));
+                    OGRGMLASLayer* poSubLayer = GetLayerByXPath(osNestedXPath);
+
+                    if( poSubLayer && poJunctionLayer )
+                    {
+                        CPLString osParentId(
+                            m_oCurCtxt.m_poFeature->GetFieldAsString(
+                                    m_oCurCtxt.m_poLayer->GetIDFieldIdx()));
+
+                        // Create child feature
+                        m_oCurCtxt.m_poLayer = poSubLayer;
+                        CreateNewFeature(osLocalname);
+
+                        ++m_oMapGlobalCounter[poJunctionLayer];
+                        const int nGlobalCounter =
+                                        m_oMapGlobalCounter[poJunctionLayer];
+
+                        ++m_oCurCtxt.m_oMapCounter[poJunctionLayer];
+                        const int nCounter =
+                            m_oCurCtxt.m_oMapCounter[poJunctionLayer];
+
+                        m_oCurCtxt.m_poGroupLayer = NULL;
+                        m_oCurCtxt.m_nGroupLayerLevel = -1;
+                        m_oCurCtxt.m_nLastFieldIdxGroupLayer = -1;
+
+                        // Install new context
+                        Context oContext;
+                        oContext = m_oCurCtxt;
+                        oContext.m_nLevel = m_nLevel;
+                        oContext.m_osCurSubXPath = m_osCurSubXPath;
+                        m_osCurSubXPath = osNestedXPath;
+#ifdef DEBUG_VERBOSE
+                        CPLDebug("GMLAS",
+                                 "Installing new m_osCurSubXPath from %s to %s",
+                                 oContext.m_osCurSubXPath.c_str(),
+                                 m_osCurSubXPath.c_str());
+#endif
+                        PushContext( oContext );
+                        m_oCurCtxt.m_oMapCounter.clear();
+
+                        // Process attributes now because we might need to
+                        // fetch the child id from them
+                        ProcessAttributes(attrs);
+                        bHasProcessedAttributes = true;
+
+                        CPLString osChildId(
+                            m_oCurCtxt.m_poFeature->GetFieldAsString(
+                                    m_oCurCtxt.m_poLayer->GetIDFieldIdx()));
+
+                        // Create junction feature
+                        OGRFeature* poJunctionFeature =
+                                new OGRFeature(poJunctionLayer->GetLayerDefn());
+                        poJunctionFeature->SetFID(nGlobalCounter);
+                        poJunctionFeature->SetField(szOCCURRENCE, nCounter);
+                        poJunctionFeature->SetField(szPARENT_PKID, osParentId);
+                        poJunctionFeature->SetField(szCHILD_PKID, osChildId);
+                        PushFeatureReady(poJunctionFeature, poJunctionLayer);
+                    }
+                    idx = IDX_COMPOUND_FOLDED;
+
+                    break;
+                }
+            }
+
+            m_nCurFieldIdx = -1;
+            m_nCurGeomFieldIdx = -1;
+            if( idx != IDX_COMPOUND_FOLDED && m_nLevelSilentIgnoredXPath < 0 &&
+
+                // Detect if we are in a situation where elements like
+                // <foo xsi:nil="true"/> have no corresponding OGR field
+                // because of the use of remove_unused_fields=true
+                !( m_oCurCtxt.m_poLayer->
+                            GetFCFieldIndexFromXPath(m_osCurSubXPath) >= 0 &&
+                    attrs.getLength() == 1 &&
+                    m_oMapURIToPrefix[ transcode( attrs.getURI(0) ) ] == szXSI_PREFIX &&
+                    transcode(attrs.getLocalName(0)) == szNIL ) )
+            {
+                CPLString osMatchedXPath;
+                if( m_oIgnoredXPathMatcher.MatchesRefXPath(
+                                        m_osCurSubXPath, osMatchedXPath) )
+                {
+                    if( m_oMapIgnoredXPathToWarn[osMatchedXPath] )
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                "Element with xpath=%s found in document but "
+                                "ignored according to configuration",
+                                m_osCurSubXPath.c_str());
+                    }
+                    else
+                    {
+                        CPLDebug("GMLAS",
+                                "Element with xpath=%s found in document but "
+                                "ignored according to configuration",
+                                m_osCurSubXPath.c_str());
+                    }
+                    m_nLevelSilentIgnoredXPath = m_nLevel;
+                }
+                else
+                {
+                    if( m_bWarnUnexpected )
+                    {
+                      CPLError(CE_Warning, CPLE_AppDefined,
+                         "Unexpected element with xpath=%s (subxpath=%s) found",
+                          m_osCurXPath.c_str(),
+                          m_osCurSubXPath.c_str());
+                    }
+                    else
+                    {
+                       CPLDebug("GMLAS",
+                         "Unexpected element with xpath=%s (subxpath=%s) found",
+                          m_osCurXPath.c_str(),
+                          m_osCurSubXPath.c_str());
+                    }
+                }
+            }
+        }
+        else
+        {
+            m_nCurFieldIdx = -1;
+            m_nCurGeomFieldIdx = -1;
+        }
+
+        if( !bHasProcessedAttributes )
+            ProcessAttributes(attrs);
+    }
+    else
+    {
+        m_nCurFieldIdx = -1;
+        m_nCurGeomFieldIdx = -1;
+    }
+
+    m_nLevel ++;
+}
+
+/************************************************************************/
+/*                          ProcessAttributes()                         */
+/************************************************************************/
+
+void GMLASReader::ProcessAttributes(const Attributes& attrs)
+{
+    // Browse through attributes and match them with one of our fields
+    const int nWildcardAttrIdx =
+        m_oCurCtxt.m_poLayer->GetOGRFieldIndexFromXPath(m_osCurSubXPath + "/" +
+                                                        szAT_ANY_ATTR);
+    json_object* poWildcard = NULL;
+
+    for(unsigned int i=0; i < attrs.getLength(); i++)
+    {
+        const CPLString& osAttrNSPrefix( m_osAttrNSPrefix =
+            m_oMapURIToPrefix[ transcode( attrs.getURI(i), m_osAttrNSUri ) ] );
+        const CPLString& osAttrLocalname(
+                        transcode(attrs.getLocalName(i), m_osAttrLocalName) );
+        const CPLString& osAttrValue(
+                                transcode(attrs.getValue(i), m_osAttrValue) );
+        CPLString& osAttrXPath( m_osAttrXPath );
+        if( !osAttrNSPrefix.empty() )
+        {
+            osAttrXPath.reserve( m_osCurSubXPath.size() + 2 +
+                        osAttrNSPrefix.size() + 1 + osAttrLocalname.size() );
+            osAttrXPath = m_osCurSubXPath;
+            osAttrXPath += "/@";
+            osAttrXPath += osAttrNSPrefix;
+            osAttrXPath += ":";
+            osAttrXPath += osAttrLocalname;
+        }
+        else
+        {
+            osAttrXPath.reserve( m_osCurSubXPath.size() + 2 +
+                                 osAttrLocalname.size() );
+            osAttrXPath = m_osCurSubXPath;
+            osAttrXPath += "/@";
+            osAttrXPath += osAttrLocalname;
+        }
+
+        const int nAttrIdx = m_oCurCtxt.m_poLayer->
+                                    GetOGRFieldIndexFromXPath(osAttrXPath);
+        int nFCIdx;
+        if( nAttrIdx >= 0 )
+        {
+            const OGRFieldType eType(
+                m_oCurCtxt.m_poFeature->GetFieldDefnRef(nAttrIdx)->GetType());
+            if( osAttrValue.empty() && eType == OFTString  )
+            {
+                m_oCurCtxt.m_poFeature->SetField( nAttrIdx, "" );
+            }
+            else
+            {
+                SetField( m_oCurCtxt.m_poFeature,
+                          m_oCurCtxt.m_poLayer,
+                          nAttrIdx, osAttrValue );
+            }
+
+            if( osAttrNSPrefix == szXLINK_PREFIX &&
+                osAttrLocalname == szHREF &&
+                !osAttrValue.empty() )
+            {
+                ProcessXLinkHref( osAttrXPath, osAttrValue );
+            }
+        }
+
+        else if( osAttrNSPrefix == szXSI_PREFIX &&
+                 osAttrLocalname == szNIL )
+        {
+            if( osAttrValue == "true" )
+            {
+                const int nMainAttrIdx = m_oCurCtxt.m_poLayer->
+                                        GetOGRFieldIndexFromXPath(m_osCurSubXPath);
+                if( nMainAttrIdx >= 0 )
+                {
+                    m_oCurCtxt.m_poFeature->SetFieldNull( nMainAttrIdx );
+                }
+                else
+                {
+                    const int nHrefAttrIdx = m_oCurCtxt.m_poLayer->
+                            GetOGRFieldIndexFromXPath(m_osCurSubXPath +
+                                        "/@" + szXLINK_PREFIX + ":" + szHREF);
+                    if( nHrefAttrIdx >= 0 )
+                    {
+                        m_oCurCtxt.m_poFeature->SetFieldNull( nHrefAttrIdx );
+                    }
+                }
+            }
+        }
+
+        else if( osAttrNSPrefix != szXMLNS_PREFIX &&
+                 osAttrLocalname != szXMLNS_PREFIX &&
+                    !(osAttrNSPrefix == szXSI_PREFIX &&
+                        osAttrLocalname == szSCHEMA_LOCATION) &&
+                    !(osAttrNSPrefix == szXSI_PREFIX &&
+                        osAttrLocalname == szNO_NAMESPACE_SCHEMA_LOCATION) &&
+                    // Do not warn about fixed attributes on geometry properties
+                    !(m_nCurGeomFieldIdx >= 0 && (
+                    (osAttrNSPrefix == szXLINK_PREFIX &&
+                     osAttrLocalname == szTYPE) ||
+                    (osAttrNSPrefix == "" && osAttrLocalname == szOWNS))) )
+        {
+            CPLString osMatchedXPath;
+            if( nWildcardAttrIdx >= 0 )
+            {
+                if( poWildcard == NULL )
+                    poWildcard = json_object_new_object();
+                CPLString osKey;
+                if( !osAttrNSPrefix.empty() )
+                    osKey = osAttrNSPrefix + ":" + osAttrLocalname;
+                else
+                    osKey = osAttrLocalname;
+                json_object_object_add(poWildcard,
+                    osKey,
+                    json_object_new_string(osAttrValue));
+            }
+            else if( m_bValidate &&
+                     (nFCIdx = m_oCurCtxt.m_poLayer->
+                        GetFCFieldIndexFromXPath(osAttrXPath)) >= 0 &&
+                     !m_oCurCtxt.m_poLayer->GetFeatureClass().
+                        GetFields()[nFCIdx].GetFixedValue().empty() )
+            {
+                // In validation mode, fixed attributes not present in the
+                // document are still reported, which cause spurious warnings
+            }
+            else if( m_oIgnoredXPathMatcher.MatchesRefXPath(
+                                        osAttrXPath, osMatchedXPath) )
+            {
+                if( m_oMapIgnoredXPathToWarn[osMatchedXPath] )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "Attribute with xpath=%s found in document but "
+                            "ignored according to configuration",
+                            osAttrXPath.c_str());
+                }
+                else
+                {
+                    CPLDebug("GMLAS",
+                            "Attribute with xpath=%s found in document but "
+                            "ignored according to configuration",
+                            osAttrXPath.c_str());
+                }
+            }
+            else
+            {
+                if( m_bWarnUnexpected )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Unexpected attribute with xpath=%s found",
+                             osAttrXPath.c_str());
+                }
+                else
+                {
+                    // Emit debug message if unexpected attribute
+                    CPLDebug("GMLAS",
+                                "Unexpected attribute with xpath=%s found",
+                            osAttrXPath.c_str());
+                }
+            }
+        }
+    }
+
+    // Store wildcard attributes
+    if( poWildcard != NULL )
+    {
+        SetField( m_oCurCtxt.m_poFeature,
+                    m_oCurCtxt.m_poLayer,
+                    nWildcardAttrIdx,
+                    json_object_get_string(poWildcard) );
+        json_object_put(poWildcard);
+    }
+
+    // Process fixed and default values, except when doing the initial scan
+    // so as to avoid the bRemoveUnusedFields logic to be confused
+    if( !m_bInitialPass )
+    {
+        const int nFieldCount = m_oCurCtxt.m_poFeature->GetFieldCount();
+        const std::vector<GMLASField>& aoFields =
+                        m_oCurCtxt.m_poLayer->GetFeatureClass().GetFields();
+        for( int i=0; i < nFieldCount; i++ )
+        {
+            const int nFCIdx =
+                    m_oCurCtxt.m_poLayer->GetFCFieldIndexFromOGRFieldIdx(i);
+            if( nFCIdx >= 0 &&
+                aoFields[nFCIdx].GetXPath().find('@') != std::string::npos )
+            {
+                // We process fixed as default. In theory, to be XSD compliant,
+                // the user shouldn't have put a different value than the fixed
+                // one, but just in case he did, then honour it instead of
+                // overwriting it.
+                CPLString osFixedDefaultValue = aoFields[nFCIdx].GetFixedValue();
+                if( osFixedDefaultValue.empty() )
+                    osFixedDefaultValue = aoFields[nFCIdx].GetDefaultValue();
+                if( !osFixedDefaultValue.empty() &&
+                    !m_oCurCtxt.m_poFeature->IsFieldSetAndNotNull(i) )
+                {
+                    SetField( m_oCurCtxt.m_poFeature,
+                                m_oCurCtxt.m_poLayer,
+                                i, osFixedDefaultValue);
+                }
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                           ProcessXLinkHref()                         */
+/************************************************************************/
+
+void GMLASReader::ProcessXLinkHref( const CPLString& osAttrXPath,
+                                    const CPLString& osAttrValue )
+{
+    // If we are a xlink:href attribute, and that the link value is
+    // a internal link, then find if we have
+    // a field that does a relation to a targetElement
+    if( osAttrValue[0] == '#' )
+    {
+        const int nAttrIdx2 =
+            m_oCurCtxt.m_poLayer->GetOGRFieldIndexFromXPath(
+                GMLASField::MakePKIDFieldXPathFromXLinkHrefXPath(
+                                                    osAttrXPath));
+        if( nAttrIdx2 >= 0 )
+        {
+            SetField( m_oCurCtxt.m_poFeature,
+                        m_oCurCtxt.m_poLayer,
+                        nAttrIdx2, osAttrValue.substr(1) );
+        }
+    }
+    else
+    {
+        const int nRuleIdx =
+                        m_oXLinkResolver.GetMatchingResolutionRule(osAttrValue);
+        if( nRuleIdx >= 0 )
+        {
+            const GMLASXLinkResolutionConf::URLSpecificResolution& oRule(
+                    m_oXLinkResolver.GetConf().m_aoURLSpecificRules[nRuleIdx] );
+            if( m_bInitialPass )
+            {
+                m_oMapXLinkFields[m_oCurCtxt.m_poLayer][osAttrXPath].insert(
+                                                            nRuleIdx );
+            }
+            else if( oRule.m_eResolutionMode ==
+                        GMLASXLinkResolutionConf::RawContent )
+            {
+                const int nAttrIdx2 =
+                  m_oCurCtxt.m_poLayer->GetOGRFieldIndexFromXPath(
+                    GMLASField::MakeXLinkRawContentFieldXPathFromXLinkHrefXPath(
+                                                                    osAttrXPath));
+                CPLAssert( nAttrIdx2 >= 0 );
+
+                const CPLString osRawContent(
+                    m_oXLinkResolver.GetRawContentForRule(osAttrValue, nRuleIdx));
+                if( !osRawContent.empty() )
+                {
+                    SetField( m_oCurCtxt.m_poFeature,
+                              m_oCurCtxt.m_poLayer,
+                              nAttrIdx2,
+                              osRawContent );
+                }
+            }
+            else if( oRule.m_eResolutionMode ==
+                        GMLASXLinkResolutionConf::FieldsFromXPath )
+            {
+                const CPLString osRawContent(
+                    m_oXLinkResolver.GetRawContentForRule(osAttrValue, nRuleIdx));
+                if( !osRawContent.empty() )
+                {
+                    CPLXMLNode* psNode = CPLParseXMLString( osRawContent );
+                    if( psNode != NULL )
+                    {
+                        std::vector<CPLString> aoXPaths;
+                        std::map<CPLString, size_t> oMapFieldXPathToIdx;
+                        for(size_t i=0; i < oRule.m_aoFields.size(); ++i )
+                        {
+                            const CPLString& osXPathRule(
+                                            oRule.m_aoFields[i].m_osXPath);
+                            aoXPaths.push_back(osXPathRule);
+                            oMapFieldXPathToIdx[osXPathRule] = i;
+                        }
+                        GMLASXPathMatcher oMatcher;
+                        oMatcher.SetRefXPaths(std::map<CPLString, CPLString>(),
+                                              aoXPaths);
+                        oMatcher.SetDocumentMapURIToPrefix(std::map<CPLString, CPLString>());
+
+                        CPLXMLNode* psIter = psNode;
+                        for( ; psIter != NULL; psIter = psIter->psNext )
+                        {
+                            if( psIter->eType == CXT_Element &&
+                                psIter->pszValue[0] != '?' )
+                            {
+                                ExploreXMLDoc( osAttrXPath,
+                                               oRule,
+                                               psIter,
+                                               CPLString(),
+                                               oMatcher,
+                                               oMapFieldXPathToIdx );
+                            }
+                        }
+                    }
+                    CPLDestroyXMLNode(psNode);
+                }
+            }
+        }
+        else if( m_oXLinkResolver.IsRawContentResolutionEnabled() )
+        {
+            const int nAttrIdx2 =
+              m_oCurCtxt.m_poLayer->GetOGRFieldIndexFromXPath(
+                GMLASField::MakeXLinkRawContentFieldXPathFromXLinkHrefXPath(
+                                                                osAttrXPath));
+            CPLAssert( nAttrIdx2 >= 0 );
+
+            const CPLString osRawContent(
+                m_oXLinkResolver.GetRawContent(osAttrValue));
+            if( !osRawContent.empty() )
+            {
+                SetField( m_oCurCtxt.m_poFeature,
+                        m_oCurCtxt.m_poLayer,
+                        nAttrIdx2,
+                        osRawContent );
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                            ExploreXMLDoc()                           */
+/************************************************************************/
+
+void GMLASReader::ExploreXMLDoc( const CPLString& osAttrXPath,
+                                 const GMLASXLinkResolutionConf::URLSpecificResolution& oRule,
+                                 CPLXMLNode* psNode,
+                                 const CPLString& osParentXPath,
+                                 const GMLASXPathMatcher& oMatcher,
+                                 const std::map<CPLString, size_t>&
+                                                        oMapFieldXPathToIdx )
+{
+    CPLString osXPath;
+    if( osParentXPath.empty() )
+        osXPath = psNode->pszValue;
+    else if( psNode->eType == CXT_Element )
+        osXPath = osParentXPath + "/" + psNode->pszValue;
+    else
+    {
+        CPLAssert( psNode->eType == CXT_Attribute );
+        osXPath = osParentXPath + "/@" + psNode->pszValue;
+    }
+
+    CPLString osMatchedXPathRule;
+    if( oMatcher.MatchesRefXPath(osXPath, osMatchedXPathRule) )
+    {
+        std::map<CPLString, size_t>::const_iterator oIter =
+                        oMapFieldXPathToIdx.find(osMatchedXPathRule);
+        CPLAssert( oIter != oMapFieldXPathToIdx.end() );
+        const size_t nFieldRuleIdx = oIter->second;
+        const CPLString osDerivedFieldXPath(
+            GMLASField::MakeXLinkDerivedFieldXPathFromXLinkHrefXPath(
+                osAttrXPath, oRule.m_aoFields[nFieldRuleIdx].m_osName) );
+        const int nAttrIdx =
+              m_oCurCtxt.m_poLayer->GetOGRFieldIndexFromXPath(osDerivedFieldXPath);
+        CPLAssert( nAttrIdx >= 0 );
+        CPLString osVal;
+        if( psNode->eType == CXT_Element &&
+            psNode->psChild != NULL &&
+            psNode->psChild->eType == CXT_Text &&
+            psNode->psChild->psNext == NULL )
+        {
+            osVal = psNode->psChild->pszValue;
+        }
+        else if( psNode->eType == CXT_Attribute )
+        {
+            osVal = psNode->psChild->pszValue;
+        }
+        else
+        {
+            char* pszContent = CPLSerializeXMLTree( psNode->psChild );
+            osVal = pszContent;
+            CPLFree(pszContent);
+        }
+        if( m_oCurCtxt.m_poFeature->IsFieldSetAndNotNull(nAttrIdx) &&
+            m_oCurCtxt.m_poFeature->GetFieldDefnRef(nAttrIdx)->GetType() == OFTString )
+        {
+            osVal = m_oCurCtxt.m_poFeature->GetFieldAsString(nAttrIdx) +
+                    CPLString(" ") + osVal;
+        }
+        SetField( m_oCurCtxt.m_poFeature, m_oCurCtxt.m_poLayer,
+                    nAttrIdx, osVal );
+    }
+
+    CPLXMLNode* psIter = psNode->psChild;
+    for( ; psIter != NULL; psIter = psIter->psNext )
+    {
+        if( psIter->eType == CXT_Element || psIter->eType == CXT_Attribute )
+        {
+            ExploreXMLDoc( osAttrXPath, oRule, psIter, osXPath, oMatcher,
+                        oMapFieldXPathToIdx );
+        }
+    }
+}
+
+/************************************************************************/
+/*                              endElement()                            */
+/************************************************************************/
+
+void GMLASReader::endElement(
+            const   XMLCh* const    uri,
+            const   XMLCh* const    localname,
+            const   XMLCh* const
+#ifdef DEBUG_VERBOSE
+                                    qname
+#endif
+        )
+{
+    m_nLevel --;
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GMLAS", "m_nLevel = %d", m_nLevel);
+#endif
+
+#ifdef DEBUG_VERBOSE
+    {
+        const CPLString& osLocalname( transcode(localname, m_osLocalname) );
+        const CPLString& osNSPrefix( m_osNSPrefix =
+                                m_oMapURIToPrefix[ transcode(uri, m_osNSUri) ] );
+        if( osNSPrefix.empty() )
+            m_osXPath = osLocalname;
+        else
+        {
+            m_osXPath.reserve( osNSPrefix.size() + 1 + osLocalname.size() );
+            m_osXPath = osNSPrefix;
+            m_osXPath += ":";
+            m_osXPath += osLocalname;
+        }
+    }
+    CPLDebug("GMLAS", "endElement(%s / %s)",
+             transcode(qname).c_str(), m_osXPath.c_str());
+#endif
+
+    if( m_nLevelSilentIgnoredXPath == m_nLevel )
+    {
+        m_nLevelSilentIgnoredXPath = -1;
+    }
+
+    // Make sure to set field only if we are at the expected nesting level
+    if( m_nCurFieldIdx >= 0 && m_nLevel == m_nCurFieldLevel - 1 )
+    {
+        const OGRFieldType eType(
+            m_nCurFieldIdx >= 0 ?
+                m_oCurCtxt.m_poFeature->GetFieldDefnRef(m_nCurFieldIdx)->GetType() :
+            OFTString );
+
+        // Assign XML content to field value
+        if( IsArrayType(eType) )
+        {
+            const int nFCFieldIdx =
+                m_oCurCtxt.m_poLayer->GetFCFieldIndexFromOGRFieldIdx(m_nCurFieldIdx);
+            if( nFCFieldIdx >= 0 &&
+                m_oCurCtxt.m_poLayer->GetFeatureClass().GetFields()[nFCFieldIdx].IsList() )
+            {
+                SetField( m_oCurCtxt.m_poFeature,
+                          m_oCurCtxt.m_poLayer,
+                          m_nCurFieldIdx, m_osTextContent );
+            }
+            else if( m_nTextContentListEstimatedSize > m_nMaxContentSize )
+            {
+                CPLError(CE_Failure, CPLE_OutOfMemory,
+                         "Too much repeated data in a single element");
+                m_bParsingError = true;
+            }
+            else
+            {
+                // Transform boolean values to something that OGR understands
+                if( eType == OFTIntegerList &&
+                    m_oCurCtxt.m_poFeature->GetFieldDefnRef(m_nCurFieldIdx)->
+                                                GetSubType() == OFSTBoolean )
+                {
+                    if( m_osTextContent == "true" )
+                        m_osTextContent = "1";
+                    else
+                        m_osTextContent = "0";
+                }
+
+                m_osTextContentList.AddString( m_osTextContent );
+                // 16 is an arbitrary number for the cost of a new entry in the
+                // string list
+                m_nTextContentListEstimatedSize += 16 + m_osTextContent.size();
+                m_oCurCtxt.m_poFeature->SetField( m_nCurFieldIdx,
+                                        m_osTextContentList.List() );
+            }
+        }
+        else
+        {
+            if( m_bIsXMLBlobIncludeUpper && FillTextContent() )
+            {
+                const CPLString& osLocalname(
+                                transcode(localname, m_osLocalname) );
+                const CPLString& osNSPrefix(
+                                m_oMapURIToPrefix[ transcode(uri, m_osNSUri) ] );
+
+                m_osTextContent += "</";
+                if( !osNSPrefix.empty() )
+                {
+                    m_osTextContent += osNSPrefix;
+                    m_osTextContent += ":";
+                }
+                m_osTextContent += osLocalname;
+                m_osTextContent += ">";
+            }
+
+            SetField( m_oCurCtxt.m_poFeature,
+                        m_oCurCtxt.m_poLayer,
+                        m_nCurFieldIdx, m_osTextContent );
+        }
+    }
+
+    // Make sure to set field only if we are at the expected nesting level
+    if( m_nCurGeomFieldIdx >= 0 && m_nLevel == m_nCurFieldLevel - 1 )
+    {
+        if( !m_apsXMLNodeStack.empty() )
+        {
+            CPLAssert( m_apsXMLNodeStack.size() == 1 );
+            CPLXMLNode* psRoot = m_apsXMLNodeStack[0].psNode;
+            ProcessGeometry(psRoot);
+            CPLDestroyXMLNode(psRoot);
+            m_apsXMLNodeStack.clear();
+        }
+    }
+
+    if( (m_nCurFieldIdx >= 0 || m_nCurGeomFieldIdx >= 0) &&
+        m_nLevel == m_nCurFieldLevel - 1 )
+    {
+        m_bIsXMLBlob = false;
+        m_bIsXMLBlobIncludeUpper = false;
+    }
+
+    if( m_bIsXMLBlob )
+    {
+        if( m_nCurGeomFieldIdx >= 0 )
+        {
+            if( m_apsXMLNodeStack.size() > 1 )
+            {
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GMLAS", "m_apsXMLNodeStack.pop_back()");
+#endif
+                m_apsXMLNodeStack.pop_back();
+            }
+        }
+
+        if( FillTextContent() )
+        {
+            const CPLString& osLocalname(
+                            transcode(localname, m_osLocalname) );
+            const CPLString& osNSPrefix(
+                            m_oMapURIToPrefix[ transcode(uri, m_osNSUri) ] );
+
+            m_osTextContent += "</";
+            if( !osNSPrefix.empty() )
+            {
+                m_osTextContent += osNSPrefix;
+                m_osTextContent += ":";
+            }
+            m_osTextContent += osLocalname;
+            m_osTextContent += ">";
+
+            if( m_osTextContent.size() > m_nMaxContentSize )
+            {
+                CPLError(CE_Failure, CPLE_OutOfMemory,
+                        "Too much data in a single element");
+                m_bParsingError = true;
+            }
+        }
+    }
+    else
+    {
+        m_osTextContent.clear();
+    }
+
+    if( m_nSWEDataArrayLevel >= 0)
+    {
+        if( m_nLevel > m_nSWEDataArrayLevel )
+        {
+            CPLAssert( m_apsXMLNodeStack.size() > 1 );
+            m_apsXMLNodeStack.pop_back();
+        }
+        else
+        {
+            CPLAssert( m_apsXMLNodeStack.size() == 1 );
+            CPLXMLNode* psRoot = m_apsXMLNodeStack[0].psNode;
+            ProcessSWEDataArray(psRoot);
+            m_nSWEDataArrayLevel = -1;
+            CPLDestroyXMLNode(psRoot);
+            m_apsXMLNodeStack.clear();
+        }
+    }
+
+    // The while and not just if is needed when a group is at the end of an
+    // element
+    while( !m_aoStackContext.empty() &&
+           m_aoStackContext.back().m_nLevel >= m_nLevel )
+    {
+        std::map<OGRLayer*, int> oMapCounter = m_aoStackContext.back().m_oMapCounter;
+        if( !m_aoStackContext.back().m_osCurSubXPath.empty() )
+        {
+#ifdef DEBUG_VERBOSE
+            CPLDebug("GMLAS", "Restoring m_osCurSubXPath from %s to %s",
+                     m_osCurSubXPath.c_str(),
+                     m_aoStackContext.back().m_osCurSubXPath.c_str());
+#endif
+            m_osCurSubXPath = m_aoStackContext.back().m_osCurSubXPath;
+        }
+
+        if( m_oCurCtxt.m_poGroupLayer == m_oCurCtxt.m_poLayer )
+        {
+            PopContext();
+            CPLAssert( !m_aoStackContext.empty() );
+            m_oCurCtxt.m_poLayer = m_aoStackContext.back().m_poLayer;
+        }
+        else
+        {
+            if( m_oCurCtxt.m_poGroupLayer )
+            {
+                /* Case like
+                        <first_elt_of_group>...</first_elt_of_group>
+                    </end_of_enclosing_element>   <!-- we are here at endElement() -->
+                */
+
+                //CPLDebug("GMLAS", "Feature ready");
+                PushFeatureReady(m_oCurCtxt.m_poFeature,
+                                 m_oCurCtxt.m_poGroupLayer);
+                //CPLDebug("GMLAS", "Feature ready");
+                PushFeatureReady(m_aoStackContext.back().m_poFeature,
+                                 m_aoStackContext.back().m_poLayer);
+            }
+            else
+            {
+                //CPLDebug("GMLAS", "Feature ready");
+                PushFeatureReady(m_oCurCtxt.m_poFeature,
+                                 m_oCurCtxt.m_poLayer);
+            }
+            PopContext();
+            if( !m_aoStackContext.empty() )
+            {
+                m_oCurCtxt = m_aoStackContext.back();
+                m_oCurCtxt.m_osCurSubXPath.clear();
+                if( m_oCurCtxt.m_nLevel < 0 )
+                {
+                    PopContext();
+                    CPLAssert( !m_aoStackContext.empty() );
+                    m_oCurCtxt.m_poLayer = m_aoStackContext.back().m_poLayer;
+                }
+            }
+            else
+            {
+                m_oCurCtxt.m_poFeature = NULL;
+                m_oCurCtxt.m_poLayer = NULL;
+                m_oCurCtxt.m_poGroupLayer = NULL;
+                m_oCurCtxt.m_nGroupLayerLevel = -1;
+                m_oCurCtxt.m_nLastFieldIdxGroupLayer = -1;
+            }
+            m_nCurFieldIdx = -1;
+        }
+        m_oCurCtxt.m_oMapCounter = oMapCounter;
+
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GMLAS", "m_oCurCtxt = ");
+        m_oCurCtxt.Dump();
+#endif
+    }
+
+    size_t nLastXPathLength = m_anStackXPathLength.back();
+    m_anStackXPathLength.pop_back();
+    if( m_anStackXPathLength.empty())
+        m_osCurXPath.clear();
+    else
+        m_osCurXPath.resize( m_osCurXPath.size() - 1 - nLastXPathLength);
+
+    if( m_osCurSubXPath.size() >= 1 + nLastXPathLength )
+        m_osCurSubXPath.resize( m_osCurSubXPath.size() - 1 - nLastXPathLength);
+    else if( m_osCurSubXPath.size() == nLastXPathLength )
+         m_osCurSubXPath.clear();
+}
+
+/************************************************************************/
+/*                         ProcessSWEDataArray()                        */
+/************************************************************************/
+
+void GMLASReader::ProcessSWEDataArray(CPLXMLNode* psRoot)
+{
+    CPLStripXMLNamespace( psRoot, "swe", true );
+    CPLXMLNode* psElementType = CPLGetXMLNode(psRoot, "elementType");
+    if( psElementType == NULL )
+        return;
+    CPLXMLNode* psDataRecord = CPLGetXMLNode(psElementType, "DataRecord");
+    if( psDataRecord == NULL )
+        return;
+    const char* pszValues = CPLGetXMLValue(psRoot, "values", NULL);
+    if( pszValues == NULL )
+        return;
+    CPLXMLNode* psTextEncoding = CPLGetXMLNode(psRoot,
+                                               "encoding.TextEncoding");
+    if( psTextEncoding == NULL )
+        return;
+    CPLString osDecimalSeparator =
+        CPLGetXMLValue(psTextEncoding, "decimalSeparator", ".");
+    CPLString osBlockSeparator =
+        CPLGetXMLValue(psTextEncoding, "blockSeparator", "");
+    CPLString osTokenSeparator =
+        CPLGetXMLValue(psTextEncoding, "tokenSeparator", "");
+    if( osBlockSeparator.empty() || osTokenSeparator.empty() )
+        return;
+
+    if( m_bInitialPass )
+    {
+        CPLString osLayerName;
+        osLayerName.Printf("DataArray_%d", m_nSWEDataArrayLayerIdx+1);
+        const char* pszElementTypeName =
+                                CPLGetXMLValue(psElementType, "name", NULL);
+        if( pszElementTypeName != NULL )
+        {
+            osLayerName += "_";
+            osLayerName += pszElementTypeName;
+        }
+        osLayerName = osLayerName.tolower();
+        OGRGMLASLayer* poLayer = new OGRGMLASLayer(osLayerName);
+        m_apoSWEDataArrayLayers.push_back(poLayer);
+        poLayer->ProcessDataRecord(psDataRecord);
+    }
+    else
+    {
+        CPLAssert( m_nSWEDataArrayLayerIdx <
+                    static_cast<int>(m_apoSWEDataArrayLayers.size()) );
+        OGRGMLASLayer* poLayer =
+                        m_apoSWEDataArrayLayers[m_nSWEDataArrayLayerIdx];
+        const int nFieldCount = poLayer->GetLayerDefn()->GetFieldCount();
+        int nFID = 1;
+        int iField = 0;
+        const size_t nLen = strlen(pszValues);
+        OGRFeature* poFeature = NULL;
+        const bool bSameSep = (osTokenSeparator == osBlockSeparator);
+        size_t nLastValid = 0;
+        while( isspace( static_cast<int>(pszValues[nLastValid]) ) )
+            nLastValid ++;
+        size_t i = nLastValid;
+        while( i < nLen )
+        {
+            if( poFeature == NULL )
+            {
+                poFeature = new OGRFeature( poLayer->GetLayerDefn() );
+                poFeature->SetFID( nFID );
+                nFID ++;
+                iField = 0;
+            }
+            if( strncmp( pszValues + i, osTokenSeparator,
+                         osTokenSeparator.size() ) == 0 )
+            {
+                if( bSameSep && iField == nFieldCount )
+                {
+                    PushFeatureReady( poFeature, poLayer );
+                    poFeature = new OGRFeature( poLayer->GetLayerDefn() );
+                    poFeature->SetFID( nFID );
+                    nFID ++;
+                    iField = 0;
+                }
+
+                if( iField < nFieldCount )
+                {
+                    std::string osValue( pszValues + nLastValid,
+                                         i - nLastValid );
+                    if( !osValue.empty() )
+                        poFeature->SetField(iField, osValue.c_str());
+                    iField ++;
+                }
+                nLastValid = i + osTokenSeparator.size();
+                while( isspace( static_cast<int>(pszValues[nLastValid]) ) )
+                    nLastValid ++;
+                i = nLastValid;
+            }
+            else if( strncmp( pszValues + i, osBlockSeparator,
+                              osBlockSeparator.size() ) == 0 )
+            {
+                if( iField < nFieldCount )
+                {
+                    std::string osValue( pszValues + nLastValid,
+                                         i - nLastValid );
+                    if( !osValue.empty() )
+                        poFeature->SetField(iField, osValue.c_str());
+                    iField ++;
+                }
+                PushFeatureReady( poFeature, poLayer );
+                poFeature = NULL;
+                nLastValid = i + osBlockSeparator.size();
+                while( isspace( static_cast<int>(pszValues[nLastValid]) ) )
+                    nLastValid ++;
+                i = nLastValid;
+            }
+            else
+            {
+                i++;
+            }
+        }
+        if( poFeature != NULL )
+        {
+            if( iField < nFieldCount )
+            {
+                std::string osValue( pszValues + nLastValid,
+                                     nLen - nLastValid );
+                if( !osValue.empty() )
+                    poFeature->SetField(iField, osValue.c_str());
+                //iField ++;
+            }
+            PushFeatureReady( poFeature, poLayer );
+        }
+    }
+    m_nSWEDataArrayLayerIdx ++;
+}
+
+/************************************************************************/
+/*                            ProcessGeometry()                         */
+/************************************************************************/
+
+void GMLASReader::ProcessGeometry(CPLXMLNode* psRoot)
+{
+    OGRGeomFieldDefn* poGeomFieldDefn =
+        m_oCurCtxt.m_poFeature->GetGeomFieldDefnRef(
+                                    m_nCurGeomFieldIdx);
+
+    if( m_bInitialPass )
+    {
+        const char* pszSRSName = CPLGetXMLValue(psRoot,
+                                                szSRS_NAME, NULL);
+        if( pszSRSName != NULL )
+        {
+            // If we are doing a first pass, store the SRS of the geometry
+            // column
+            if( !m_oSetGeomFieldsWithUnknownSRS.empty() &&
+                 m_oSetGeomFieldsWithUnknownSRS.find(poGeomFieldDefn) !=
+                        m_oSetGeomFieldsWithUnknownSRS.end() )
+            {
+                OGRSpatialReference* poSRS =
+                                new OGRSpatialReference();
+                if( poSRS->SetFromUserInput( pszSRSName ) == OGRERR_NONE )
+                {
+                    OGR_SRSNode *poGEOGCS = poSRS->GetAttrNode( "GEOGCS" );
+                    if( poGEOGCS != NULL )
+                        poGEOGCS->StripNodes( "AXIS" );
+
+                    OGR_SRSNode *poPROJCS = poSRS->GetAttrNode( "PROJCS" );
+                    if (poPROJCS != NULL &&
+                        poSRS->EPSGTreatsAsNorthingEasting())
+                    {
+                        poPROJCS->StripNodes( "AXIS" );
+                    }
+
+                    m_oMapGeomFieldDefnToSRSName[poGeomFieldDefn] = pszSRSName;
+                    poGeomFieldDefn->SetSpatialRef(poSRS);
+                }
+                poSRS->Release();
+                m_oSetGeomFieldsWithUnknownSRS.erase(poGeomFieldDefn);
+            }
+        }
+        return;
+    }
+
+#ifdef DEBUG_VERBOSE
+    {
+        char* pszXML = CPLSerializeXMLTree(psRoot);
+        CPLDebug("GML", "geometry = %s", pszXML);
+        CPLFree(pszXML);
+    }
+#endif
+
+    OGRGeometry* poGeom = reinterpret_cast<OGRGeometry*>
+                    (OGR_G_CreateFromGMLTree( psRoot ));
+    if( poGeom != NULL )
+    {
+        const char* pszSRSName = CPLGetXMLValue(psRoot,
+                                                szSRS_NAME, NULL);
+        bool bSwapXY = false;
+        if( pszSRSName != NULL )
+        {
+            // Check if the srsName indicates unusual axis order,
+            // and if so swap x and y coordinates.
+            std::map<CPLString, bool>::iterator oIter =
+                m_oMapSRSNameToInvertedAxis.find(pszSRSName);
+            if( oIter == m_oMapSRSNameToInvertedAxis.end() )
+            {
+                OGRSpatialReference oSRS;
+                oSRS.SetFromUserInput( pszSRSName );
+                bSwapXY = CPL_TO_BOOL(oSRS.EPSGTreatsAsLatLong()) ||
+                            CPL_TO_BOOL(oSRS.EPSGTreatsAsNorthingEasting());
+                m_oMapSRSNameToInvertedAxis[ pszSRSName ] = bSwapXY;
+            }
+            else
+            {
+                bSwapXY = oIter->second;
+            }
+        }
+        if( (bSwapXY && m_eSwapCoordinates == GMLAS_SWAP_AUTO) ||
+            m_eSwapCoordinates == GMLAS_SWAP_YES )
+        {
+            poGeom->swapXY();
+        }
+
+        // Do we need to do reprojection ?
+        if( pszSRSName != NULL && poGeomFieldDefn->GetSpatialRef() != NULL &&
+            m_oMapGeomFieldDefnToSRSName[poGeomFieldDefn] != pszSRSName )
+        {
+            bool bReprojectionOK = false;
+            OGRSpatialReference oSRS;
+            if( oSRS.SetFromUserInput( pszSRSName ) == OGRERR_NONE )
+            {
+                OGRCoordinateTransformation* poCT =
+                    OGRCreateCoordinateTransformation( &oSRS,
+                                            poGeomFieldDefn->GetSpatialRef() );
+                if( poCT != NULL )
+                {
+                    bReprojectionOK = (poGeom->transform( poCT ) == OGRERR_NONE);
+                    delete poCT;
+                }
+            }
+            if( !bReprojectionOK )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Reprojection fom %s to %s failed",
+                         pszSRSName,
+                         m_oMapGeomFieldDefnToSRSName[poGeomFieldDefn].c_str());
+                delete poGeom;
+                poGeom = NULL;
+            }
+#ifdef DEBUG_VERBOSE
+            else
+            {
+                CPLDebug("GMLAS", "Reprojected geometry from %s to %s",
+                         pszSRSName,
+                         m_oMapGeomFieldDefnToSRSName[poGeomFieldDefn].c_str());
+            }
+#endif
+        }
+
+        if( poGeom != NULL )
+        {
+            // Deal with possibly repeated geometries by building
+            // a geometry collection. We could also create a
+            // nested table, but that would probably be less
+            // convenient to use.
+            OGRGeometry* poPrevGeom = m_oCurCtxt.m_poFeature->
+                                    StealGeometry(m_nCurGeomFieldIdx);
+            if( poPrevGeom != NULL )
+            {
+                if( poPrevGeom->getGeometryType() ==
+                                        wkbGeometryCollection )
+                {
+                    reinterpret_cast<OGRGeometryCollection*>(
+                        poPrevGeom)->addGeometryDirectly(poGeom);
+                    poGeom = poPrevGeom;
+                }
+                else
+                {
+                    OGRGeometryCollection* poGC =
+                                    new OGRGeometryCollection();
+                    poGC->addGeometryDirectly(poPrevGeom);
+                    poGC->addGeometryDirectly(poGeom);
+                    poGeom = poGC;
+                }
+            }
+            poGeom->assignSpatialReference(
+                                poGeomFieldDefn->GetSpatialRef());
+            m_oCurCtxt.m_poFeature->SetGeomFieldDirectly(
+                m_nCurGeomFieldIdx, poGeom );
+        }
+    }
+    else
+    {
+        char* pszXML = CPLSerializeXMLTree(psRoot);
+        CPLDebug("GMLAS", "Non-recognized geometry: %s",
+                    pszXML);
+        CPLFree(pszXML);
+    }
+}
+
+/************************************************************************/
+/*                              characters()                            */
+/************************************************************************/
+
+void GMLASReader::characters( const XMLCh *const chars,
+                              const XMLSize_t length )
+{
+    bool bTextMemberUpdated = false;
+    if( ((m_bIsXMLBlob && m_nCurGeomFieldIdx >= 0 && FillTextContent()) ||
+        m_nSWEDataArrayLevel >= 0) &&
+        // Check the stack is not empty in case of space chars before the
+        // starting node
+        !m_apsXMLNodeStack.empty() )
+    {
+        bTextMemberUpdated = true;
+        const CPLString& osText( transcode(chars, m_osText,
+                                           static_cast<int>(length) ) );
+
+        // Merge content in current text node if it exists
+        NodeLastChild& sNodeLastChild = m_apsXMLNodeStack.back();
+        if( sNodeLastChild.psLastChild != NULL &&
+            sNodeLastChild.psLastChild->eType == CXT_Text )
+        {
+            CPLXMLNode* psNode = sNodeLastChild.psLastChild;
+            const size_t nOldLength = strlen(psNode->pszValue);
+            char* pszNewValue = reinterpret_cast<char*>(VSIRealloc(
+                    psNode->pszValue, nOldLength + osText.size() + 1));
+            if( pszNewValue )
+            {
+                psNode->pszValue = pszNewValue;
+                memcpy( pszNewValue + nOldLength, osText.c_str(),
+                        osText.size() + 1);
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
+                m_bParsingError = true;
+            }
+        }
+        // Otherwise create a new text node
+        else
+        {
+            CPLXMLNode* psNode = reinterpret_cast<CPLXMLNode*>
+                                        ( CPLMalloc(sizeof(CPLXMLNode)) );
+            psNode->eType = CXT_Text;
+            psNode->pszValue = reinterpret_cast<char*>
+                                        ( CPLMalloc( osText.size() + 1 ) );
+            memcpy(psNode->pszValue, osText.c_str(), osText.size() + 1);
+            psNode->psNext = NULL;
+            psNode->psChild = NULL;
+            AttachAsLastChild( psNode );
+        }
+    }
+
+    if( !FillTextContent() )
+    {
+        m_osTextContent = "1"; // dummy
+        return;
+    }
+
+    if( m_bIsXMLBlob )
+    {
+        if( m_nCurFieldIdx >= 0 )
+        {
+            const CPLString& osText( bTextMemberUpdated ? m_osText:
+                    transcode(chars, m_osText, static_cast<int>(length) ) );
+
+            char* pszEscaped = CPLEscapeString( osText.c_str(),
+                                            static_cast<int>(osText.size()),
+                                            CPLES_XML );
+            try
+            {
+                m_osTextContent += pszEscaped;
+            }
+            catch( const std::bad_alloc& )
+            {
+                CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
+                m_bParsingError = true;
+            }
+            CPLFree(pszEscaped);
+        }
+    }
+    // Make sure to set content only if we are at the expected nesting level
+    else if( m_nLevel == m_nCurFieldLevel )
+    {
+        const CPLString& osText(
+                        transcode(chars, m_osText, static_cast<int>(length) ) );
+        try
+        {
+            m_osTextContent += osText;
+        }
+        catch( const std::bad_alloc& )
+        {
+            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
+            m_bParsingError = true;
+        }
+    }
+
+    if( m_osTextContent.size() > m_nMaxContentSize )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Too much data in a single element");
+        m_bParsingError = true;
+    }
+}
+
+/************************************************************************/
+/*                            GetNextFeature()                          */
+/************************************************************************/
+
+OGRFeature* GMLASReader::GetNextFeature( OGRGMLASLayer** ppoBelongingLayer,
+                                         GDALProgressFunc pfnProgress,
+                                         void* pProgressData )
+{
+    while( !m_aoFeaturesReady.empty() )
+    {
+        OGRFeature* m_poFeatureReady = m_aoFeaturesReady[0].first;
+        OGRGMLASLayer* m_poFeatureReadyLayer = m_aoFeaturesReady[0].second;
+        m_aoFeaturesReady.erase( m_aoFeaturesReady.begin() );
+
+        if( m_poLayerOfInterest == NULL ||
+            m_poLayerOfInterest == m_poFeatureReadyLayer )
+        {
+            if( ppoBelongingLayer )
+                *ppoBelongingLayer = m_poFeatureReadyLayer;
+            return m_poFeatureReady;
+        }
+        delete m_poFeatureReady;
+    }
+
+    if( m_bEOF )
+        return NULL;
+
+    try
+    {
+        if( m_bFirstIteration )
+        {
+            m_bFirstIteration = false;
+            if( !m_poSAXReader->parseFirst( *m_GMLInputSource, m_oToFill ) )
+            {
+                m_bParsingError = true;
+                m_bEOF = true;
+                return NULL;
+            }
+        }
+
+        vsi_l_offset nLastOffset = VSIFTellL(m_fp);
+        while( m_poSAXReader->parseNext( m_oToFill ) )
+        {
+            if( pfnProgress && VSIFTellL(m_fp) - nLastOffset > 100 * 1024 )
+            {
+                nLastOffset = VSIFTellL(m_fp);
+                double dfPct = -1;
+                if( m_nFileSize )
+                    dfPct = 1.0 * nLastOffset / m_nFileSize;
+                if( !pfnProgress( dfPct, "", pProgressData ) )
+                {
+                    m_bInterrupted = true;
+                    break;
+                }
+            }
+            if( m_bParsingError )
+                break;
+
+            while( !m_aoFeaturesReady.empty() )
+            {
+                OGRFeature* m_poFeatureReady = m_aoFeaturesReady[0].first;
+                OGRGMLASLayer* m_poFeatureReadyLayer =
+                                               m_aoFeaturesReady[0].second;
+                m_aoFeaturesReady.erase( m_aoFeaturesReady.begin() );
+
+                if( m_poLayerOfInterest == NULL ||
+                    m_poLayerOfInterest == m_poFeatureReadyLayer )
+                {
+                    if( ppoBelongingLayer )
+                        *ppoBelongingLayer = m_poFeatureReadyLayer;
+
+                    if( pfnProgress )
+                    {
+                        nLastOffset = VSIFTellL(m_fp);
+                        double dfPct = -1;
+                        if( m_nFileSize )
+                            dfPct = 1.0 * nLastOffset / m_nFileSize;
+                        if( !pfnProgress( dfPct, "", pProgressData ) )
+                        {
+                            delete m_poFeatureReady;
+                            m_bInterrupted = true;
+                            m_bEOF = true;
+                            return NULL;
+                        }
+                    }
+
+                    return m_poFeatureReady;
+                }
+                delete m_poFeatureReady;
+            }
+        }
+
+        m_bEOF = true;
+    }
+    catch (const XMLException& toCatch)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                 transcode( toCatch.getMessage() ).c_str() );
+        m_bParsingError = true;
+        m_bEOF = true;
+    }
+    catch (const SAXException& toCatch)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                 transcode( toCatch.getMessage() ).c_str() );
+        m_bParsingError = true;
+        m_bEOF = true;
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                              RunFirstPass()                          */
+/************************************************************************/
+
+bool GMLASReader::RunFirstPass(GDALProgressFunc pfnProgress,
+                               void* pProgressData,
+                               bool bRemoveUnusedLayers,
+                               bool bRemoveUnusedFields,
+                               bool bProcessSWEDataArray,
+                               std::set<CPLString>& aoSetRemovedLayerNames)
+{
+    m_bInitialPass = true;
+    m_bProcessSWEDataArray = bProcessSWEDataArray;
+
+    // Store in m_oSetGeomFieldsWithUnknownSRS the geometry fields
+    std::set<OGRGMLASLayer*> oSetUnreferencedLayers;
+    std::map<OGRGMLASLayer*, std::set<int> > oMapUnusedFields;
+    for(size_t i=0; i < m_papoLayers->size(); i++ )
+    {
+        OGRGMLASLayer* poLayer = (*m_papoLayers)[i];
+        OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
+        oSetUnreferencedLayers.insert( poLayer );
+        for(int j=0; j< poFDefn->GetGeomFieldCount(); j++ )
+        {
+            m_oSetGeomFieldsWithUnknownSRS.insert(
+                                            poFDefn->GetGeomFieldDefn(j));
+        }
+        for(int j=0; j< poFDefn->GetFieldCount(); j++ )
+        {
+            oMapUnusedFields[poLayer].insert(j);
+        }
+    }
+
+    CPLDebug("GMLAS", "Start of first pass");
+
+    // Do we need to do a full scan of the file ?
+    const bool bHasURLSpecificRules =
+                !m_oXLinkResolver.GetConf().m_aoURLSpecificRules.empty();
+    const bool bDoFullPass =
+        (m_bValidate ||
+         bRemoveUnusedLayers ||
+         bRemoveUnusedFields ||
+         bHasURLSpecificRules ||
+         bProcessSWEDataArray );
+
+    // Loop on features until we have determined the SRS of all geometry
+    // columns, or potentially on the whole file for the above reasons
+    OGRGMLASLayer* poLayer;
+    OGRFeature* poFeature;
+    while( (bDoFullPass || !m_oSetGeomFieldsWithUnknownSRS.empty() ) &&
+           (poFeature = GetNextFeature(&poLayer, pfnProgress, pProgressData)) != NULL )
+    {
+        if( bRemoveUnusedLayers )
+            oSetUnreferencedLayers.erase( poLayer );
+        if( bRemoveUnusedFields )
+        {
+            std::set<int>& oSetUnusedFields = oMapUnusedFields[poLayer];
+            OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
+            int nFieldCount = poFDefn->GetFieldCount();
+            for(int j=0; j< nFieldCount; j++ )
+            {
+                if( poFeature->IsFieldSetAndNotNull(j) )
+                    oSetUnusedFields.erase(j);
+            }
+        }
+        delete poFeature;
+    }
+
+    CPLDebug("GMLAS", "End of first pass");
+
+    if( bRemoveUnusedLayers )
+    {
+        std::vector<OGRGMLASLayer*> apoNewLayers;
+        for(size_t i=0; i < m_papoLayers->size(); i++ )
+        {
+            poLayer = (*m_papoLayers)[i];
+            if( oSetUnreferencedLayers.find( poLayer ) ==
+                    oSetUnreferencedLayers.end() )
+            {
+                apoNewLayers.push_back( poLayer );
+            }
+            else
+            {
+                aoSetRemovedLayerNames.insert( poLayer->GetName() );
+                delete poLayer;
+            }
+        }
+        *m_papoLayers = apoNewLayers;
+    }
+    if( bRemoveUnusedFields )
+    {
+        for(size_t i=0; i < m_papoLayers->size(); i++ )
+        {
+            poLayer = (*m_papoLayers)[i];
+            std::set<int>& oSetUnusedFields = oMapUnusedFields[poLayer];
+            std::set<int>::iterator oIter = oSetUnusedFields.begin();
+            int nShiftIndex = 0;
+            for( ; oIter != oSetUnusedFields.end(); ++oIter )
+            {
+                if( poLayer->RemoveField( (*oIter) - nShiftIndex ) )
+                {
+                    nShiftIndex ++;
+                }
+            }
+
+            // We need to run this again since we may have delete the
+            // element that holds attributes, like in
+            // <foo xsi:nil="true" nilReason="unknown"/> where foo will be
+            // eliminated, but foo_nilReason kept.
+            poLayer->CreateCompoundFoldedMappings();
+        }
+    }
+
+    // Add fields coming from matching URL specific rules
+    if( bHasURLSpecificRules )
+    {
+        CreateFieldsForURLSpecificRules();
+    }
+
+    // Clear the set even if we didn't manage to determine all the SRS
+    m_oSetGeomFieldsWithUnknownSRS.clear();
+
+    return !m_bInterrupted;
+}
+
+/************************************************************************/
+/*                    CreateFieldsForURLSpecificRules()                 */
+/************************************************************************/
+
+void GMLASReader::CreateFieldsForURLSpecificRules()
+{
+    std::map<OGRGMLASLayer*, std::map<CPLString, std::set<int> > >::const_iterator
+        oIter = m_oMapXLinkFields.begin();
+    for( ; oIter != m_oMapXLinkFields.end(); ++oIter )
+    {
+        OGRGMLASLayer* poLayer = oIter->first;
+        const std::map<CPLString, std::set<int> >& oMap2 = oIter->second;
+        std::map<CPLString, std::set<int> >::const_iterator oIter2 =
+                                                            oMap2.begin();
+        for( ; oIter2 != oMap2.end(); ++oIter2 )
+        {
+            const CPLString& osFieldXPath(oIter2->first);
+            // Note that CreateFieldsForURLSpecificRule() running on a previous
+            // iteration will have inserted new OGR fields, so we really need
+            // to compute that index now.
+            const int nFieldIdx = poLayer->GetOGRFieldIndexFromXPath(osFieldXPath);
+            CPLAssert(nFieldIdx >= 0);
+            int nInsertFieldIdx = nFieldIdx + 1;
+            const std::set<int>& oSetRuleIndex = oIter2->second;
+            std::set<int>::const_iterator oIter3 = oSetRuleIndex.begin();
+            for( ; oIter3 != oSetRuleIndex.end(); ++ oIter3 )
+            {
+                const GMLASXLinkResolutionConf::URLSpecificResolution& oRule =
+                    m_oXLinkResolver.GetConf().m_aoURLSpecificRules[*oIter3];
+                CreateFieldsForURLSpecificRule( poLayer, nFieldIdx,
+                                                osFieldXPath,
+                                                nInsertFieldIdx,
+                                                oRule );
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                    CreateFieldsForURLSpecificRule()                  */
+/************************************************************************/
+
+void GMLASReader::CreateFieldsForURLSpecificRule(
+                OGRGMLASLayer* poLayer,
+                int nFieldIdx,
+                const CPLString& osFieldXPath,
+                int& nInsertFieldIdx,
+                const GMLASXLinkResolutionConf::URLSpecificResolution& oRule )
+{
+    if( oRule.m_eResolutionMode ==
+                        GMLASXLinkResolutionConf::RawContent )
+    {
+        const CPLString osRawContentXPath(
+            GMLASField::MakeXLinkRawContentFieldXPathFromXLinkHrefXPath(
+                                                                osFieldXPath) );
+        if( poLayer->GetOGRFieldIndexFromXPath( osRawContentXPath ) < 0 )
+        {
+            const CPLString osOGRFieldName(
+                poLayer->GetLayerDefn()->
+                        GetFieldDefn(nFieldIdx)->GetNameRef() );
+            CPLString osRawContentFieldname(osOGRFieldName);
+            size_t nPos = osRawContentFieldname.find("_href");
+            if( nPos != std::string::npos )
+                osRawContentFieldname.resize(nPos);
+            osRawContentFieldname += "_rawcontent";
+            OGRFieldDefn oFieldDefnRaw( osRawContentFieldname,
+                                        OFTString );
+            poLayer->InsertNewField( nInsertFieldIdx,
+                                        oFieldDefnRaw,
+                                        osRawContentXPath );
+            nInsertFieldIdx ++;
+        }
+    }
+    else if ( oRule.m_eResolutionMode ==
+                    GMLASXLinkResolutionConf::FieldsFromXPath )
+    {
+        for( size_t i=0; i < oRule.m_aoFields.size(); ++i )
+        {
+            const CPLString osDerivedFieldXPath(
+                GMLASField::MakeXLinkDerivedFieldXPathFromXLinkHrefXPath(
+                    osFieldXPath, oRule.m_aoFields[i].m_osName) );
+            if( poLayer->GetOGRFieldIndexFromXPath( osDerivedFieldXPath ) < 0 )
+            {
+                const CPLString osOGRFieldName(
+                    poLayer->GetLayerDefn()->
+                            GetFieldDefn(nFieldIdx)->GetNameRef() );
+                CPLString osNewFieldname(osOGRFieldName);
+                size_t nPos = osNewFieldname.find("_href");
+                if( nPos != std::string::npos )
+                    osNewFieldname.resize(nPos);
+                osNewFieldname += "_" + oRule.m_aoFields[i].m_osName;
+
+                OGRFieldType eType = OFTString;
+                const CPLString& osType(oRule.m_aoFields[i].m_osType);
+                if( osType == "integer" )
+                    eType = OFTInteger;
+                else if( osType == "long" )
+                    eType = OFTInteger64;
+                else if( osType == "double" )
+                    eType = OFTReal;
+                else if( osType == "dateTime" )
+                    eType = OFTDateTime;
+
+                OGRFieldDefn oFieldDefnRaw( osNewFieldname,
+                                            eType );
+                poLayer->InsertNewField( nInsertFieldIdx,
+                                            oFieldDefnRaw,
+                                            osDerivedFieldXPath );
+                nInsertFieldIdx ++;
+            }
+        }
+    }
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlasschemaanalyzer.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlasschemaanalyzer.cpp
new file mode 100644
index 0000000..f177c95
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlasschemaanalyzer.cpp
@@ -0,0 +1,3584 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "xercesc_headers.h"
+
+// Hack to avoid bool, possibly redefined to pedantic bool class, being later used
+static XSModel* getGrammarPool(XMLGrammarPool* pool)
+{
+    bool changed;
+    return pool->getXSModel(changed);
+}
+
+#include "ogr_gmlas.h"
+#include "ogr_pgdump.h"
+
+CPL_CVSID("$Id: ogrgmlasschemaanalyzer.cpp 37871 2017-03-31 16:39:20Z rouault $");
+
+/************************************************************************/
+/*                        IsCompatibleOfArray()                         */
+/************************************************************************/
+
+static bool IsCompatibleOfArray( GMLASFieldType eType )
+{
+    return eType == GMLAS_FT_STRING ||
+           eType == GMLAS_FT_BOOLEAN ||
+           eType == GMLAS_FT_SHORT ||
+           eType == GMLAS_FT_INT32 ||
+           eType == GMLAS_FT_INT64 ||
+           eType == GMLAS_FT_FLOAT ||
+           eType == GMLAS_FT_DOUBLE ||
+           eType == GMLAS_FT_DECIMAL ||
+           eType == GMLAS_FT_ANYURI;
+}
+
+/************************************************************************/
+/*                       GMLASPrefixMappingHander                       */
+/************************************************************************/
+
+class GMLASPrefixMappingHander: public DefaultHandler
+{
+        std::map<CPLString, CPLString>& m_oMapURIToPrefix;
+        CPLString& m_osGMLVersionFound;
+
+  public:
+        GMLASPrefixMappingHander(
+                        std::map<CPLString, CPLString>& oMapURIToPrefix,
+                        CPLString& osGMLVersionFound) :
+            m_oMapURIToPrefix( oMapURIToPrefix ),
+            m_osGMLVersionFound( osGMLVersionFound )
+        {}
+
+        virtual void startElement(
+            const   XMLCh* const    uri,
+            const   XMLCh* const    localname,
+            const   XMLCh* const    qname,
+            const   Attributes& attrs) override;
+
+        virtual void startPrefixMapping(const XMLCh* const prefix,
+                                        const XMLCh* const uri) override;
+};
+
+/************************************************************************/
+/*                           startElement()                             */
+/************************************************************************/
+
+void GMLASPrefixMappingHander::startElement(
+                                    const   XMLCh* const    uri,
+                                    const   XMLCh* const    localname,
+                                    const   XMLCh* const    /*qname*/,
+                                    const   Attributes& attrs )
+{
+    if( !m_osGMLVersionFound.empty() )
+        return;
+
+    const CPLString osURI( transcode(uri) );
+    const CPLString osLocalname( transcode(localname) );
+    if( osURI == szXS_URI && osLocalname == "schema" )
+    {
+        bool bIsGML = false;
+        CPLString osVersion;
+        for(unsigned int i=0; i < attrs.getLength(); i++)
+        {
+            CPLString osAttrLocalName(transcode(attrs.getLocalName(i)));
+            if( osAttrLocalName == "targetNamespace" )
+            {
+                bIsGML = transcode(attrs.getValue(i)) == szGML_URI;
+            }
+            else if( osAttrLocalName == "version" )
+            {
+                osVersion = transcode(attrs.getValue(i));
+            }
+        }
+        if( bIsGML && !osVersion.empty() )
+        {
+            m_osGMLVersionFound = osVersion;
+        }
+    }
+}
+
+/************************************************************************/
+/*                         startPrefixMapping()                         */
+/************************************************************************/
+
+void GMLASPrefixMappingHander::startPrefixMapping(const XMLCh* const prefix,
+                                                  const XMLCh* const uri)
+{
+    const CPLString osURI( transcode(uri) );
+    const CPLString osPrefix( transcode(prefix) );
+    if( !osPrefix.empty() )
+    {
+        std::map<CPLString, CPLString>::iterator oIter =
+                    m_oMapURIToPrefix.find( osURI );
+        if( oIter == m_oMapURIToPrefix.end() )
+        {
+            m_oMapURIToPrefix[ osURI ] = osPrefix;
+            CPLDebug("GMLAS", "Registering prefix=%s for uri=%s",
+                     osPrefix.c_str(), osURI.c_str());
+        }
+        else if( oIter->second != osPrefix )
+        {
+            CPLDebug("GMLAS",
+                     "Existing prefix=%s for uri=%s (new prefix %s not used)",
+                    oIter->second.c_str(), osURI.c_str(), osPrefix.c_str());
+        }
+    }
+}
+
+/************************************************************************/
+/*                        CollectNamespacePrefixes()                    */
+/************************************************************************/
+
+static
+void CollectNamespacePrefixes(const char* pszXSDFilename,
+                              VSILFILE* fpXSD,
+                              std::map<CPLString, CPLString>& oMapURIToPrefix,
+                              CPLString& osGMLVersionFound)
+{
+    GMLASInputSource oSource(pszXSDFilename, fpXSD, false);
+    // This is a bit silly but the startPrefixMapping() callback only gets
+    // called when using SAX2XMLReader::parse(), and not when using
+    // loadGrammar(), so we have to parse the doc twice.
+    SAX2XMLReader* poReader = XMLReaderFactory::createXMLReader ();
+
+    GMLASPrefixMappingHander contentHandler(oMapURIToPrefix, osGMLVersionFound);
+    poReader->setContentHandler(&contentHandler);
+
+    GMLASErrorHandler oErrorHandler;
+    poReader->setErrorHandler(&oErrorHandler);
+
+    poReader->parse(oSource);
+    delete poReader;
+}
+
+/************************************************************************/
+/*                       GMLASAnalyzerEntityResolver                    */
+/************************************************************************/
+
+class GMLASAnalyzerEntityResolver: public GMLASBaseEntityResolver
+{
+        std::map<CPLString, CPLString>& m_oMapURIToPrefix;
+
+  public:
+        GMLASAnalyzerEntityResolver(const CPLString& osBasePath,
+                            std::map<CPLString, CPLString>& oMapURIToPrefix,
+                            GMLASXSDCache& oCache)
+            : GMLASBaseEntityResolver(osBasePath, oCache)
+            , m_oMapURIToPrefix(oMapURIToPrefix)
+        {
+        }
+
+        virtual void DoExtraSchemaProcessing(const CPLString& osFilename,
+                                             VSILFILE* fp) override;
+};
+
+/************************************************************************/
+/*                         DoExtraSchemaProcessing()                    */
+/************************************************************************/
+
+void GMLASAnalyzerEntityResolver::DoExtraSchemaProcessing(
+                                             const CPLString& osFilename,
+                                             VSILFILE* fp)
+{
+    CollectNamespacePrefixes(osFilename, fp, m_oMapURIToPrefix,
+                             m_osGMLVersionFound);
+    VSIFSeekL(fp, 0, SEEK_SET);
+}
+
+/************************************************************************/
+/*                        GMLASSchemaAnalyzer()                         */
+/************************************************************************/
+
+GMLASSchemaAnalyzer::GMLASSchemaAnalyzer(
+                            GMLASXPathMatcher& oIgnoredXPathMatcher,
+                            GMLASXPathMatcher& oChildrenElementsConstraintsXPathMatcher,
+                            const std::map<CPLString, std::vector<CPLString> >&
+                                                        oMapChildrenElementsConstraints,
+                            GMLASXPathMatcher& oForcedFlattenedXPathMatcher,
+                            GMLASXPathMatcher& oDisabledFlattenedXPathMatcher )
+    : m_oIgnoredXPathMatcher(oIgnoredXPathMatcher)
+    , m_oChildrenElementsConstraintsXPathMatcher(oChildrenElementsConstraintsXPathMatcher)
+    , m_oForcedFlattenedXPathMatcher(oForcedFlattenedXPathMatcher)
+    , m_oDisabledFlattenedXPathMatcher(oDisabledFlattenedXPathMatcher)
+    , m_oMapChildrenElementsConstraints(oMapChildrenElementsConstraints)
+    , m_bUseArrays(true)
+    , m_bUseNullState(false)
+    , m_bInstantiateGMLFeaturesOnly(true)
+    , m_nIdentifierMaxLength(0)
+    , m_bCaseInsensitiveIdentifier(CASE_INSENSITIVE_IDENTIFIER_DEFAULT)
+    , m_bPGIdentifierLaundering(PG_IDENTIFIER_LAUNDERING_DEFAULT)
+    , m_nMaximumFieldsForFlattening(MAXIMUM_FIELDS_FLATTENING_DEFAULT)
+{
+    // A few hardcoded namespace uri->prefix mappings
+    m_oMapURIToPrefix[ szXMLNS_URI ] = szXMLNS_PREFIX;
+    m_oMapURIToPrefix[ szXSI_URI ] = szXSI_PREFIX;
+}
+
+/************************************************************************/
+/*                               GetPrefix()                            */
+/************************************************************************/
+
+CPLString GMLASSchemaAnalyzer::GetPrefix( const CPLString& osNamespaceURI )
+{
+    if( osNamespaceURI.empty() )
+        return "";
+    std::map<CPLString,CPLString>::const_iterator oIter =
+                                        m_oMapURIToPrefix.find(osNamespaceURI);
+    if( oIter != m_oMapURIToPrefix.end() )
+        return oIter->second;
+    else if( !osNamespaceURI.empty() )
+    {
+        // If the schema doesn't define a xmlns:MYPREFIX=myuri, then forge a
+        // fake prefix for conveniency
+        CPLString osPrefix;
+        if( osNamespaceURI.find(szOPENGIS_URL) == 0 )
+            osPrefix = osNamespaceURI.substr( strlen(szOPENGIS_URL) );
+        else if( osNamespaceURI.find("http://") == 0 )
+            osPrefix = osNamespaceURI.substr( strlen("http://") );
+        else
+            osPrefix = osNamespaceURI;
+        for(size_t i = 0; i < osPrefix.size(); i++ )
+        {
+            if( !isalnum(osPrefix[i]) )
+                osPrefix[i] = '_';
+        }
+        m_oMapURIToPrefix[osNamespaceURI] = osPrefix;
+        CPLDebug("GMLAS",
+                 "Cannot find prefix for ns='%s'. Forging %s",
+                 osNamespaceURI.c_str(),
+                 osPrefix.c_str());
+        return osPrefix;
+    }
+    else
+    {
+        CPLDebug("GMLAS",
+                 "Cannot find prefix for ns='%s'.",
+                 osNamespaceURI.c_str());
+        return "";
+    }
+}
+
+/************************************************************************/
+/*                               MakeXPath()                            */
+/************************************************************************/
+
+CPLString GMLASSchemaAnalyzer::MakeXPath( const CPLString& osNamespaceURI,
+                                          const CPLString& osName )
+{
+    const CPLString osPrefix(GetPrefix(osNamespaceURI));
+    if( osPrefix.empty() )
+        return osName;
+    return osPrefix + ":" + osName;
+}
+
+/************************************************************************/
+/*                         GetNSOfLastXPathComponent()                  */
+/************************************************************************/
+
+// Return the namespace (if any) of the last component of the XPath
+static CPLString GetNSOfLastXPathComponent(const CPLString& osXPath )
+{
+    size_t nPos = osXPath.rfind('@');
+    if( nPos != std::string::npos )
+        nPos ++;
+    else
+    {
+        nPos = osXPath.rfind('/');
+        if( nPos != std::string::npos )
+            nPos ++;
+        else
+            nPos = 0;
+    }
+    size_t nPosColumn = osXPath.find(':', nPos);
+    if( nPosColumn == std::string::npos )
+        return CPLString();
+    return CPLString(osXPath.substr(nPos, nPosColumn - nPos));
+}
+
+/************************************************************************/
+/*                         LaunderFieldNames()                          */
+/************************************************************************/
+
+// Make sure that field names are unique within the class
+void GMLASSchemaAnalyzer::LaunderFieldNames( GMLASFeatureClass& oClass )
+{
+    std::vector<GMLASField>& aoFields = oClass.GetFields();
+
+    // Duplicates can happen if a class has both an element and an attribute
+    // with same name, and/or attributes/elements with same name in different
+    // namespaces.
+    bool bHasDoneSomeRenaming = false;
+    do
+    {
+        bHasDoneSomeRenaming = false;
+
+        // Detect duplicated field names
+        std::map<CPLString, std::vector<int> > oSetNames;
+        for(int i=0; i< static_cast<int>(aoFields.size());i++)
+        {
+            if( aoFields[i].GetCategory() == GMLASField::REGULAR )
+            {
+                oSetNames[ aoFields[i].GetName() ].push_back(i ) ;
+            }
+        }
+
+        // Iterate over the unique names
+        std::map<CPLString, std::vector<int> >::const_iterator
+                oIter = oSetNames.begin();
+        for(; oIter != oSetNames.end(); ++oIter)
+        {
+            // Has it duplicates ?
+            const size_t nOccurrences = oIter->second.size();
+            if( nOccurrences > 1 )
+            {
+                const CPLString oClassNS =
+                        GetNSOfLastXPathComponent(oClass.GetXPath());
+                bool bHasDoneRemnamingForThatCase = false;
+
+                for(size_t i=0; i<nOccurrences;i++)
+                {
+                    GMLASField& oField = aoFields[oIter->second[i]];
+                    // CPLDebug("GMLAS", "%s", oField.GetXPath().c_str() );
+                    const CPLString oNS(
+                                GetNSOfLastXPathComponent(oField.GetXPath()));
+                    // If the field has a namespace that is not the one of its
+                    // class, then prefix its name with its namespace
+                    if( !oNS.empty() && oNS != oClassNS &&
+                        !STARTS_WITH(oField.GetName(), (oNS + "_").c_str() ) )
+                    {
+                        bHasDoneSomeRenaming = true;
+                        bHasDoneRemnamingForThatCase = true;
+                        oField.SetName( oNS + "_" + oField.GetName() );
+                        break;
+                    }
+                    // If it is an attribute without a particular namespace,
+                    // then suffix with _attr
+                    else if( oNS.empty() &&
+                             oField.GetXPath().find('@') != std::string::npos &&
+                             oField.GetName().find("_attr") == std::string::npos )
+                    {
+                        bHasDoneSomeRenaming = true;
+                        bHasDoneRemnamingForThatCase = true;
+                        oField.SetName( oField.GetName() + "_attr" );
+                        break;
+                    }
+                }
+
+                // If none of the above renaming strategies have worked, then
+                // append a counter to the duplicates.
+                if( !bHasDoneRemnamingForThatCase )
+                {
+                    for(size_t i=0; i<nOccurrences;i++)
+                    {
+                        GMLASField& oField = aoFields[oIter->second[i]];
+                        if( i > 0 )
+                        {
+                            bHasDoneSomeRenaming = true;
+                            oField.SetName( oField.GetName() +
+                                CPLSPrintf("%d", static_cast<int>(i)+1) );
+                        }
+                    }
+                }
+            }
+        }
+    }
+    // As renaming could have created new duplicates (hopefully not!), loop
+    // until no renaming has been done.
+    while( bHasDoneSomeRenaming );
+
+    // Now check if we must truncate names
+    if( m_nIdentifierMaxLength >= MIN_VALUE_OF_MAX_IDENTIFIER_LENGTH )
+    {
+        for(size_t i=0; i< aoFields.size();i++)
+        {
+            int nNameSize = static_cast<int>(aoFields[i].GetName().size());
+            if( nNameSize > m_nIdentifierMaxLength )
+            {
+                aoFields[i].SetName(TruncateIdentifier(aoFields[i].GetName()));
+            }
+        }
+    }
+
+    if( m_bPGIdentifierLaundering )
+    {
+        for(size_t i=0; i< aoFields.size();i++)
+        {
+            char* pszLaundered = OGRPGCommonLaunderName( aoFields[i].GetName(),
+                                                         "GMLAS" );
+            aoFields[i].SetName( pszLaundered );
+            CPLFree( pszLaundered );
+        }
+    }
+
+    // Detect duplicated field names
+    std::map<CPLString, std::vector<int> > oSetNames;
+    for(int i=0; i< static_cast<int>(aoFields.size());i++)
+    {
+        if( aoFields[i].GetCategory() == GMLASField::REGULAR )
+        {
+            CPLString osName( aoFields[i].GetName());
+            if( m_bCaseInsensitiveIdentifier )
+                osName.toupper();
+            oSetNames[ osName ].push_back(i ) ;
+        }
+    }
+
+    // Iterate over the unique names
+    std::map<CPLString, std::vector<int> >::const_iterator
+            oIter = oSetNames.begin();
+    for(; oIter != oSetNames.end(); ++oIter)
+    {
+        // Has it duplicates ?
+        const size_t nOccurrences = oIter->second.size();
+        if( nOccurrences > 1 )
+        {
+            for(size_t i=0; i<nOccurrences;i++)
+            {
+                GMLASField& oField = aoFields[oIter->second[i]];
+                oField.SetName( AddSerialNumber( oField.GetName(),
+                                                    static_cast<int>(i+1),
+                                                    nOccurrences) );
+            }
+        }
+    }
+
+    // Recursively process nested classes
+    std::vector<GMLASFeatureClass>& aoNestedClasses = oClass.GetNestedClasses();
+    for(size_t i=0; i<aoNestedClasses.size();i++)
+    {
+        LaunderFieldNames( aoNestedClasses[i] );
+    }
+}
+
+/************************************************************************/
+/*                       CollectClassesReferences()                     */
+/************************************************************************/
+
+void GMLASSchemaAnalyzer::CollectClassesReferences(
+                                GMLASFeatureClass& oClass,
+                                std::vector<GMLASFeatureClass*>& aoClasses )
+{
+    aoClasses.push_back(&oClass);
+    std::vector<GMLASFeatureClass>& aoNestedClasses = oClass.GetNestedClasses();
+    for(size_t i=0; i<aoNestedClasses.size();i++)
+    {
+        CollectClassesReferences( aoNestedClasses[i], aoClasses );
+    }
+}
+
+/************************************************************************/
+/*                         LaunderClassNames()                          */
+/************************************************************************/
+
+void GMLASSchemaAnalyzer::LaunderClassNames()
+{
+    std::vector<GMLASFeatureClass*> aoClasses;
+    for(size_t i=0; i< m_aoClasses.size();i++)
+    {
+        CollectClassesReferences( m_aoClasses[i], aoClasses );
+    }
+
+    if( m_nIdentifierMaxLength >= MIN_VALUE_OF_MAX_IDENTIFIER_LENGTH )
+    {
+        for(size_t i=0; i< aoClasses.size();i++)
+        {
+            int nNameSize = static_cast<int>(aoClasses[i]->GetName().size());
+            if( nNameSize > m_nIdentifierMaxLength )
+            {
+                aoClasses[i]->SetName(TruncateIdentifier(aoClasses[i]->GetName()));
+            }
+        }
+    }
+
+    if( m_bPGIdentifierLaundering )
+    {
+        for(size_t i=0; i< aoClasses.size();i++)
+        {
+            char* pszLaundered = OGRPGCommonLaunderName( aoClasses[i]->GetName(),
+                                                         "GMLAS" );
+            aoClasses[i]->SetName( pszLaundered );
+            CPLFree( pszLaundered );
+        }
+    }
+
+    // Detect duplicated names. This should normally not happen in normal
+    // conditions except if you have classes like
+    // prefix_foo, prefix:foo, other_prefix:foo
+    // or if names have been truncated in the previous step
+    std::map<CPLString, std::vector<int> > oSetNames;
+    for(int i=0; i< static_cast<int>(aoClasses.size());i++)
+    {
+        CPLString osName( aoClasses[i]->GetName() );
+        if( m_bCaseInsensitiveIdentifier )
+            osName.toupper();
+        oSetNames[ osName ].push_back(i ) ;
+    }
+
+    // Iterate over the unique names
+    std::map<CPLString, std::vector<int> >::const_iterator
+            oIter = oSetNames.begin();
+    for(; oIter != oSetNames.end(); ++oIter)
+    {
+        // Has it duplicates ?
+        const size_t nOccurrences = oIter->second.size();
+        if( nOccurrences > 1 )
+        {
+            for(size_t i=0; i<nOccurrences;i++)
+            {
+                GMLASFeatureClass* poClass = aoClasses[oIter->second[i]];
+                poClass->SetName( AddSerialNumber(poClass->GetName(),
+                                                  static_cast<int>(i+1),
+                                                  nOccurrences) );
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                        AddSerialNumber()                             */
+/************************************************************************/
+
+CPLString GMLASSchemaAnalyzer::AddSerialNumber(const CPLString& osNameIn,
+                                               int iOccurrence,
+                                               size_t nOccurrences)
+{
+    CPLString osName(osNameIn);
+    const int nDigitsSize = (nOccurrences < 10) ? 1:
+                            (nOccurrences < 100) ? 2 : 3;
+    char szDigits[4];
+    snprintf(szDigits, sizeof(szDigits), "%0*d",
+                nDigitsSize, iOccurrence);
+    if( m_nIdentifierMaxLength >= MIN_VALUE_OF_MAX_IDENTIFIER_LENGTH )
+    {
+        if( static_cast<int>(osName.size()) < m_nIdentifierMaxLength )
+        {
+            if( static_cast<int>(osName.size()) + nDigitsSize <
+                                            m_nIdentifierMaxLength )
+            {
+                osName += szDigits;
+            }
+            else
+            {
+                osName.resize(m_nIdentifierMaxLength - nDigitsSize);
+                osName += szDigits;
+            }
+        }
+        else
+        {
+            osName.resize(osName.size() - nDigitsSize);
+            osName += szDigits;
+        }
+    }
+    else
+    {
+        osName += szDigits;
+    }
+    return osName;
+}
+
+/************************************************************************/
+/*                      TruncateIdentifier()                            */
+/************************************************************************/
+
+CPLString GMLASSchemaAnalyzer::TruncateIdentifier(const CPLString& osName)
+{
+    int nExtra = static_cast<int>(osName.size()) - m_nIdentifierMaxLength;
+    CPLAssert(nExtra > 0);
+
+    // Decompose in tokens
+    char** papszTokens = CSLTokenizeString2(osName, "_",
+                                            CSLT_ALLOWEMPTYTOKENS );
+    std::vector< char > achDelimiters;
+    std::vector< CPLString > aosTokens;
+    for( int j=0; papszTokens[j] != NULL; ++j )
+    {
+        const char* pszToken = papszTokens[j];
+        bool bIsCamelCase = false;
+        // Split parts like camelCase or CamelCase into several tokens
+        if( pszToken[0] != '\0' && islower(pszToken[1]) )
+        {
+            bIsCamelCase = true;
+            bool bLastIsLower = true;
+            std::vector<CPLString> aoParts;
+            CPLString osCurrentPart;
+            osCurrentPart += pszToken[0];
+            osCurrentPart += pszToken[1];
+            for( int k=2; pszToken[k]; ++k)
+            {
+                if( isupper(pszToken[k]) )
+                {
+                    if( !bLastIsLower )
+                    {
+                        bIsCamelCase = false;
+                        break;
+                    }
+                    aoParts.push_back(osCurrentPart);
+                    osCurrentPart.clear();
+                    bLastIsLower = false;
+                }
+                else
+                {
+                    bLastIsLower = true;
+                }
+                osCurrentPart += pszToken[k];
+            }
+            if( bIsCamelCase )
+            {
+                if( !osCurrentPart.empty() )
+                    aoParts.push_back(osCurrentPart);
+                for( size_t k=0; k<aoParts.size(); ++k )
+                {
+                    achDelimiters.push_back( (j > 0 && k == 0) ? '_' : '\0' );
+                    aosTokens.push_back( aoParts[k] );
+                }
+            }
+        }
+        if( !bIsCamelCase )
+        {
+            achDelimiters.push_back( (j > 0) ? '_' : '\0' );
+            aosTokens.push_back( pszToken );
+        }
+    }
+    CSLDestroy(papszTokens);
+
+    // Truncate identifier by removing last character of longest part
+    bool bHasDoneSomething = true;
+    while( nExtra > 0 && bHasDoneSomething )
+    {
+        bHasDoneSomething = false;
+        int nMaxSize = 0;
+        size_t nIdxMaxSize = 0;
+        for( size_t j=0; j < aosTokens.size(); ++j )
+        {
+            int nTokenLen = static_cast<int>(aosTokens[j].size());
+            if( nTokenLen > nMaxSize )
+            {
+                // Avoid truncating last token unless it is excessively longer
+                // than previous ones.
+                if( j < aosTokens.size() - 1 ||
+                    nTokenLen > 2 * nMaxSize )
+                {
+                    nMaxSize = nTokenLen;
+                    nIdxMaxSize = j;
+                }
+            }
+        }
+
+        if( nMaxSize > 1 )
+        {
+            aosTokens[nIdxMaxSize].resize( nMaxSize - 1 );
+            bHasDoneSomething = true;
+            nExtra --;
+        }
+    }
+
+    // Reassemble truncated parts
+    CPLString osNewName;
+    for( size_t j=0; j < aosTokens.size(); ++j )
+    {
+        if( achDelimiters[j] )
+            osNewName += achDelimiters[j];
+        osNewName += aosTokens[j];
+    }
+
+    // If we are still longer than max allowed, truncate beginning of name
+    if( nExtra > 0 )
+    {
+        osNewName = osNewName.substr(nExtra);
+    }
+    CPLAssert( static_cast<int>(osNewName.size()) == m_nIdentifierMaxLength );
+    return osNewName;
+}
+
+/************************************************************************/
+/*                       GMLASUniquePtr()                               */
+/************************************************************************/
+
+// Poor-man std::unique_ptr
+template<class T> class GMLASUniquePtr
+{
+        T* m_p;
+
+        GMLASUniquePtr(const GMLASUniquePtr&);
+        GMLASUniquePtr& operator=(const GMLASUniquePtr&);
+
+    public:
+        explicit GMLASUniquePtr(T* p): m_p(p) {}
+       ~GMLASUniquePtr() { delete m_p; }
+
+       T* operator->() const { CPLAssert(m_p); return m_p; }
+
+       T* get () const { return m_p; }
+       T* release() { T* ret = m_p; m_p = NULL; return ret; }
+};
+
+/************************************************************************/
+/*                   GetTopElementDeclarationFromXPath()                */
+/************************************************************************/
+
+XSElementDeclaration* GMLASSchemaAnalyzer::GetTopElementDeclarationFromXPath(
+                                                    const CPLString& osXPath,
+                                                    XSModel* poModel)
+{
+    const char* pszTypename = osXPath.c_str();
+    const char* pszName = strrchr(pszTypename, ':');
+    if( pszName )
+        pszName ++;
+    XSElementDeclaration* poEltDecl = NULL;
+    if( pszName != NULL )
+    {
+        CPLString osNSPrefix = pszTypename;
+        osNSPrefix.resize( pszName - 1 - pszTypename );
+        CPLString osName = pszName;
+        CPLString osNSURI;
+
+        std::map<CPLString, CPLString>::const_iterator oIterNS =
+                                            m_oMapURIToPrefix.begin();
+        for( ; oIterNS != m_oMapURIToPrefix.end(); ++oIterNS)
+        {
+            const CPLString& osIterNSURI(oIterNS->first);
+            const CPLString& osIterNSPrefix(oIterNS->second);
+            if( osNSPrefix == osIterNSPrefix )
+            {
+                osNSURI = osIterNSURI;
+                break;
+            }
+        }
+        XMLCh* xmlNS = XMLString::transcode(osNSURI);
+        XMLCh* xmlName = XMLString::transcode(osName);
+        poEltDecl = poModel->getElementDeclaration(xmlName, xmlNS);
+        XMLString::release( &xmlNS );
+        XMLString::release( &xmlName );
+    }
+    else
+    {
+        XMLCh* xmlName = XMLString::transcode(pszTypename);
+        poEltDecl = poModel->getElementDeclaration(xmlName, NULL);
+        XMLString::release( &xmlName );
+    }
+    return poEltDecl;
+}
+
+/************************************************************************/
+/*                        IsEltCompatibleOfFC()                         */
+/************************************************************************/
+
+static XSComplexTypeDefinition* IsEltCompatibleOfFC(
+                                            XSElementDeclaration* poEltDecl)
+{
+    XSTypeDefinition* poTypeDef = poEltDecl->getTypeDefinition();
+    if( poTypeDef->getTypeCategory() == XSTypeDefinition::COMPLEX_TYPE &&
+        transcode(poEltDecl->getName()) != szFEATURE_COLLECTION )
+    {
+        XSComplexTypeDefinition* poCT =
+                    reinterpret_cast<XSComplexTypeDefinition*>(poTypeDef);
+        XSComplexTypeDefinition::CONTENT_TYPE eContentType(
+                                                poCT->getContentType());
+        if( eContentType == XSComplexTypeDefinition::CONTENTTYPE_ELEMENT ||
+            eContentType == XSComplexTypeDefinition::CONTENTTYPE_MIXED )
+        {
+            return poCT;
+        }
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                          DerivesFromGMLFeature()                     */
+/************************************************************************/
+
+bool GMLASSchemaAnalyzer::DerivesFromGMLFeature(XSElementDeclaration* poEltDecl)
+{
+    XSElementDeclaration* poIter = poEltDecl;
+    while( true )
+    {
+        XSElementDeclaration* poSubstGroup =
+            poIter->getSubstitutionGroupAffiliation();
+        if( poSubstGroup == NULL )
+            break;
+        const CPLString osSubstNS(
+                    transcode(poSubstGroup->getNamespace()) );
+        const CPLString osSubstName(
+                    transcode(poSubstGroup->getName()) );
+        if( IsGMLNamespace(osSubstNS) &&
+            osSubstName == "_FeatureCollection" )
+        {
+            return false;
+        }
+        if( IsGMLNamespace(osSubstNS) &&
+            (osSubstName == "AbstractFeature" ||
+                osSubstName == "_Feature") )
+        {
+            return true;
+        }
+        poIter = poSubstGroup;
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                               Analyze()                              */
+/************************************************************************/
+
+bool GMLASSchemaAnalyzer::Analyze(GMLASXSDCache& oCache,
+                                  const CPLString& osBaseDirname,
+                                  std::vector<PairURIFilename>& aoXSDs,
+                                  bool bSchemaFullChecking,
+                                  bool bHandleMultipleImports)
+{
+    GMLASUniquePtr<XMLGrammarPool> poGrammarPool(
+         (new XMLGrammarPoolImpl(XMLPlatformUtils::fgMemoryManager)));
+
+    std::vector<CPLString> aoNamespaces;
+    GMLASAnalyzerEntityResolver oXSDEntityResolver( CPLString(),
+                                                    m_oMapURIToPrefix,
+                                                    oCache );
+
+    aoNamespaces.push_back("");
+    for( size_t i = 0; i < aoXSDs.size(); i++ )
+    {
+        const CPLString osURI(aoXSDs[i].first);
+        const CPLString osXSDFilename(aoXSDs[i].second);
+
+        GMLASUniquePtr<SAX2XMLReader> poParser(
+                    XMLReaderFactory::createXMLReader(
+                                    XMLPlatformUtils::fgMemoryManager,
+                                    poGrammarPool.get()));
+
+        // Commonly useful configuration.
+        //
+        poParser->setFeature (XMLUni::fgSAX2CoreNameSpaces, true);
+        poParser->setFeature (XMLUni::fgSAX2CoreNameSpacePrefixes, true);
+        poParser->setFeature (XMLUni::fgSAX2CoreValidation, true);
+
+        // Enable validation.
+        //
+        poParser->setFeature (XMLUni::fgXercesSchema, true);
+
+        poParser->setFeature (XMLUni::fgXercesValidationErrorAsFatal, false);
+
+        // Use the loaded grammar during parsing.
+        //
+        poParser->setFeature (XMLUni::fgXercesUseCachedGrammarInParse, true);
+
+        // Don't load schemas from any other source (e.g., from XML document's
+        // xsi:schemaLocation attributes).
+        //
+        poParser->setFeature (XMLUni::fgXercesLoadSchema, false);
+
+        Grammar* poGrammar = NULL;
+        if( !GMLASReader::LoadXSDInParser( poParser.get(),
+                                           oCache,
+                                           oXSDEntityResolver,
+                                           osBaseDirname,
+                                           osXSDFilename,
+                                           &poGrammar,
+                                           bSchemaFullChecking,
+                                           bHandleMultipleImports ) )
+        {
+            return false;
+        }
+
+        // Some .xsd like
+        // http://www.opengis.net/gwml-main/2.1 -> https://wfspoc.brgm-rec.fr/constellation/WS/wfs/BRGM:GWML2?request=DescribeFeatureType&version=2.0.0&service=WFS&namespace=xmlns(ns1=http://www.opengis.net/gwml-main/2.1)&typenames=ns1:GW_Aquifer
+        // do not have a declared targetNamespace, so use the one of the
+        // schemaLocation if the grammar returns an empty namespace.
+        CPLString osGrammarURI( transcode(poGrammar->getTargetNamespace()) );
+        if( osGrammarURI.empty() )
+        {
+            if( !osURI.empty() )
+                osGrammarURI = osURI;
+        }
+        if( !osGrammarURI.empty() )
+        {
+            // Patch back the aoXSDs element in case we didn't know the
+            // namespace URI initially
+            if( osURI.empty() )
+                aoXSDs[i].first = osGrammarURI;
+            aoNamespaces.push_back( osGrammarURI );
+        }
+    }
+
+    m_osGMLVersionFound = oXSDEntityResolver.GetGMLVersionFound();
+    m_oSetSchemaURLs = oXSDEntityResolver.GetSchemaURLS();
+
+    m_oIgnoredXPathMatcher.SetDocumentMapURIToPrefix( m_oMapURIToPrefix );
+    m_oChildrenElementsConstraintsXPathMatcher.SetDocumentMapURIToPrefix( m_oMapURIToPrefix );
+    m_oForcedFlattenedXPathMatcher.SetDocumentMapURIToPrefix( m_oMapURIToPrefix );
+    m_oDisabledFlattenedXPathMatcher.SetDocumentMapURIToPrefix( m_oMapURIToPrefix );
+
+    XSModel* poModel = getGrammarPool(poGrammarPool.get());
+    CPLAssert(poModel); // should not be null according to doc
+
+#if 0
+    XSNamespaceItem* nsItem = poModel->getNamespaceItem(
+                                        loadedGrammar->getTargetNamespace());
+    if( nsItem == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "getNamespaceItem(%s) failed",
+                 transcode(loadedGrammar->getTargetNamespace()).c_str());
+        return false;
+    }
+#endif
+
+    bool bFoundGMLFeature = false;
+
+    // Initial pass, in all namespaces, to figure out inheritance relationships
+    // and group models that have names
+    std::map<CPLString, CPLString> oMapURIToPrefixWithEmpty(m_oMapURIToPrefix);
+    oMapURIToPrefixWithEmpty[""] = "";
+    std::map<CPLString, CPLString>::const_iterator oIterNS =
+                                                oMapURIToPrefixWithEmpty.begin();
+    for( ; oIterNS != oMapURIToPrefixWithEmpty.end(); ++oIterNS)
+    {
+        const CPLString& osNSURI(oIterNS->first);
+        if( osNSURI == szXS_URI ||
+            osNSURI == szXSI_URI ||
+            osNSURI == szXMLNS_URI ||
+            osNSURI == szXLINK_URI )
+        {
+            continue;
+        }
+
+        XMLCh* xmlNamespace = XMLString::transcode(osNSURI.c_str());
+
+        XSNamedMap<XSObject>* poMapModelGroupDefinition =
+            poModel->getComponentsByNamespace(XSConstants::MODEL_GROUP_DEFINITION,
+                                            xmlNamespace);
+
+        // Remember group models that have names
+        for(XMLSize_t i = 0; poMapModelGroupDefinition != NULL &&
+                             i <  poMapModelGroupDefinition->getLength(); i++ )
+        {
+            XSModelGroupDefinition* modelGroupDefinition =
+                reinterpret_cast<XSModelGroupDefinition*>(
+                                            poMapModelGroupDefinition->item(i));
+            m_oMapModelGroupToMGD[modelGroupDefinition->getModelGroup()]
+                            = modelGroupDefinition;
+        }
+
+        CPLDebug("GMLAS", "Discovering substitutions of %s (%s)",
+                 oIterNS->second.c_str(), osNSURI.c_str());
+
+        XSNamedMap<XSObject>* poMapElements = poModel->getComponentsByNamespace(
+                            XSConstants::ELEMENT_DECLARATION, xmlNamespace);
+
+        for(XMLSize_t i = 0; poMapElements != NULL &&
+                             i < poMapElements->getLength(); i++ )
+        {
+            XSElementDeclaration* poEltDecl =
+                reinterpret_cast<XSElementDeclaration*>(poMapElements->item(i));
+            XSElementDeclaration* poSubstGroup =
+                            poEltDecl->getSubstitutionGroupAffiliation();
+            const CPLString osEltXPath(
+                            MakeXPath(transcode(poEltDecl->getNamespace()),
+                                      transcode(poEltDecl->getName())));
+            m_oMapXPathToEltDecl[ osEltXPath ] = poEltDecl;
+            if( poSubstGroup )
+            {
+                m_oMapParentEltToChildElt[poSubstGroup].push_back(poEltDecl);
+#ifdef DEBUG_VERBOSE
+                CPLString osParentType(MakeXPath(
+                            transcode(poSubstGroup->getNamespace()),
+                            transcode(poSubstGroup->getName())));
+                CPLDebug("GMLAS", "%s is a substitution for %s",
+                        osEltXPath.c_str(),
+                        osParentType.c_str());
+#endif
+
+                // Check if this element derives from gml:_Feature/AbstractFeature
+                if( !bFoundGMLFeature &&
+                    m_bInstantiateGMLFeaturesOnly &&
+                    !IsGMLNamespace(osNSURI) &&
+                    DerivesFromGMLFeature(poEltDecl) )
+                {
+                    CPLDebug("GMLAS",
+                                "Restricting (in first pass) top level "
+                                "elements to those deriving from "
+                                "gml:_Feature/gml:AbstractFeature (due "
+                                "to %s found)",
+                                osEltXPath.c_str());
+                    bFoundGMLFeature = true;
+                }
+            }
+        }
+
+        XMLString::release(&xmlNamespace);
+    }
+
+    // Find which elements must be top levels (because referenced several
+    // times)
+    std::set<XSElementDeclaration*> oSetVisitedEltDecl;
+    std::set<XSModelGroup*> oSetVisitedModelGroups;
+    std::vector<XSElementDeclaration*> oVectorEltsForTopClass;
+
+    // For some reason, different XSElementDeclaration* can point to the
+    // same element, but we only want to instantiate a single class.
+    // This is the case for base:SpatialDataSet in
+    // inspire/geologicalunit/geologicalunit.gml test dataset.
+    std::set<CPLString> aoSetXPathEltsForTopClass;
+
+    for( int iPass = 0; iPass < 2; ++iPass )
+    {
+        for( size_t iNS = 0; iNS < aoNamespaces.size(); iNS++ )
+        {
+            XMLCh* xmlNamespace = XMLString::transcode(aoNamespaces[iNS].c_str());
+
+            XSNamedMap<XSObject>* poMapElements = poModel->getComponentsByNamespace(
+                XSConstants::ELEMENT_DECLARATION, xmlNamespace);
+
+            for(XMLSize_t i = 0; poMapElements != NULL &&
+                                i < poMapElements->getLength(); i++ )
+            {
+                XSElementDeclaration* poEltDecl =
+                    reinterpret_cast<XSElementDeclaration*>(poMapElements->item(i));
+                XSComplexTypeDefinition* poCT = IsEltCompatibleOfFC(poEltDecl);
+                if( !poEltDecl->getAbstract() && poCT != NULL  )
+                {
+                    const CPLString osXPath(MakeXPath(
+                                    transcode(poEltDecl->getNamespace()),
+                                    transcode(poEltDecl->getName())));
+                    if( !IsIgnoredXPath(osXPath ) )
+                    {
+                        if( bFoundGMLFeature &&
+                            m_bInstantiateGMLFeaturesOnly &&
+                            !DerivesFromGMLFeature(poEltDecl) )
+                        {
+                            // Do nothing
+                        }
+                        else if( iPass == 0)
+                        {
+#ifdef DEBUG_VERBOSE
+                        CPLDebug("GMLAS", "%s (%s) must be exposed as "
+                                 "top-level (is top level in imported schemas)",
+                                osXPath.c_str(),
+                                transcode(poEltDecl->getTypeDefinition()->
+                                                            getName()).c_str());
+#endif
+                            oSetVisitedEltDecl.insert( poEltDecl );
+                            if( aoSetXPathEltsForTopClass.find( osXPath ) ==
+                                aoSetXPathEltsForTopClass.end() )
+                            {
+                                m_oSetEltsForTopClass.insert( poEltDecl );
+                                oVectorEltsForTopClass.push_back( poEltDecl );
+                                aoSetXPathEltsForTopClass.insert( osXPath );
+                            }
+                        }
+                        else
+                        {
+                            bool bSimpleEnoughOut = true;
+                            int nSubCountSubEltOut = 0;
+                            FindElementsWithMustBeToLevel(
+                                    osXPath,
+                                    poCT->getParticle()->getModelGroupTerm(),
+                                    0,
+                                    oSetVisitedEltDecl,
+                                    oSetVisitedModelGroups,
+                                    oVectorEltsForTopClass,
+                                    aoSetXPathEltsForTopClass,
+                                    poModel,
+                                    bSimpleEnoughOut,
+                                    nSubCountSubEltOut );
+                        }
+                    }
+                }
+            }
+
+            XMLString::release(&xmlNamespace);
+        }
+    }
+
+    // Find ambiguous class names
+    {
+        std::set<XSElementDeclaration*>::const_iterator oIter =
+                                            m_oSetEltsForTopClass.begin();
+        for(; oIter != m_oSetEltsForTopClass.end(); ++oIter )
+        {
+            CPLString osName(transcode((*oIter)->getName()));
+            m_oMapEltNamesToInstanceCount[osName] ++;
+        }
+    }
+
+    // Instantiate all needed typenames
+    std::vector<XSElementDeclaration*>::iterator oIter =
+                                        oVectorEltsForTopClass.begin();
+    for(; oIter != oVectorEltsForTopClass.end(); ++oIter )
+    {
+        XSElementDeclaration* poEltDecl = *oIter;
+
+        const CPLString osXPath(MakeXPath(
+                            transcode(poEltDecl->getNamespace()),
+                            transcode(poEltDecl->getName())));
+
+        bool bError = false;
+        bool bResolvedType = InstantiateClassFromEltDeclaration(poEltDecl,
+                                                                poModel,
+                                                                bError);
+        if( bError )
+        {
+            return false;
+        }
+        if( !bResolvedType )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                        "Couldn't resolve %s (%s)",
+                        osXPath.c_str(),
+                        transcode(poEltDecl->getTypeDefinition()->getName()).c_str()
+                        );
+            return false;
+        }
+    }
+
+    LaunderClassNames();
+
+    return true;
+}
+
+/************************************************************************/
+/*                            GetAnnotationDoc()                        */
+/************************************************************************/
+
+static CPLString GetAnnotationDoc( const XSAnnotation* annotation )
+{
+    if( !annotation )
+        return CPLString();
+    CPLString osAnnot(transcode(annotation->getAnnotationString()));
+    CPLXMLNode* psRoot = CPLParseXMLString(osAnnot);
+    CPLStripXMLNamespace(psRoot, NULL, TRUE);
+    CPLString osDoc( CPLGetXMLValue(psRoot, "=annotation.documentation", "") );
+    CPLDestroyXMLNode(psRoot);
+    return osDoc.Trim();
+}
+
+/************************************************************************/
+/*                            GetAnnotationDoc()                        */
+/************************************************************************/
+
+static CPLString GetAnnotationDoc( const XSAnnotationList* annotationList )
+{
+    if( !annotationList )
+        return CPLString();
+    CPLString osRet;
+    for( size_t i = 0; i < annotationList->size(); ++i )
+    {
+        CPLString osDoc( GetAnnotationDoc( annotationList->elementAt(i) ) );
+        if( !osDoc.empty() )
+        {
+            if( !osRet.empty() )
+                osRet += "\n";
+            osRet += osDoc;
+        }
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                            GetAnnotationDoc()                        */
+/************************************************************************/
+
+static CPLString GetAnnotationDoc( const XSElementDeclaration* poEltDecl )
+{
+    XSTypeDefinition* poTypeDef = poEltDecl->getTypeDefinition();
+    CPLString osDoc = GetAnnotationDoc( poEltDecl->getAnnotation() );
+    XSAnnotationList* list = NULL;
+    while( poTypeDef != NULL )
+    {
+        if( poTypeDef->getTypeCategory() == XSTypeDefinition::COMPLEX_TYPE )
+        {
+            XSComplexTypeDefinition* poCT =
+                        reinterpret_cast<XSComplexTypeDefinition*>(poTypeDef);
+            list = poCT->getAnnotations();
+        }
+        else if( poTypeDef->getTypeCategory() == XSTypeDefinition::SIMPLE_TYPE )
+        {
+            XSSimpleTypeDefinition* poST =
+                        reinterpret_cast<XSSimpleTypeDefinition*>(poTypeDef);
+            list = poST->getAnnotations();
+        }
+        if( list != NULL )
+            break;
+        XSTypeDefinition* poNewTypeDef = poTypeDef->getBaseType();
+        if( poNewTypeDef == poTypeDef )
+            break;
+        poTypeDef = poNewTypeDef;
+    }
+    CPLString osDoc2 = GetAnnotationDoc( list );
+    if( !osDoc.empty() && !osDoc2.empty() )
+    {
+        osDoc += "\n";
+        osDoc += osDoc2;
+    }
+    else if( !osDoc2.empty() )
+        osDoc = osDoc2;
+    return osDoc;
+}
+
+/************************************************************************/
+/*                  InstantiateClassFromEltDeclaration()                */
+/************************************************************************/
+
+bool GMLASSchemaAnalyzer::InstantiateClassFromEltDeclaration(
+                                                XSElementDeclaration* poEltDecl,
+                                                XSModel* poModel,
+                                                bool& bError)
+{
+    bError = false;
+    XSComplexTypeDefinition* poCT = IsEltCompatibleOfFC(poEltDecl);
+    if( !poEltDecl->getAbstract() && poCT != NULL )
+    {
+        GMLASFeatureClass oClass;
+        const CPLString osEltName( transcode(poEltDecl->getName()) );
+        const CPLString osXPath( MakeXPath(
+                                transcode(poEltDecl->getNamespace()),
+                                osEltName ) );
+
+        if( IsIgnoredXPath( osXPath ) )
+        {
+#ifdef DEBUG_VERBOSE
+            CPLDebug("GMLAS", "%s is in ignored xpaths",
+                        osXPath.c_str());
+#endif
+            return false;
+        }
+
+        if( m_oMapEltNamesToInstanceCount[osEltName] > 1 )
+        {
+            CPLString osLaunderedXPath(osXPath);
+            osLaunderedXPath.replaceAll(':', '_');
+            oClass.SetName( osLaunderedXPath );
+        }
+        else
+            oClass.SetName( osEltName );
+
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GMLAS", "Instantiating element %s", osXPath.c_str());
+#endif
+        oClass.SetXPath( osXPath );
+        oClass.SetIsTopLevelElt(
+            GetTopElementDeclarationFromXPath(osXPath, poModel) != NULL );
+
+        std::set<XSModelGroup*> oSetVisitedModelGroups;
+
+        oClass.SetDocumentation( GetAnnotationDoc(poEltDecl) );
+
+        // might be NULL on swe:values for example
+        if( poCT->getParticle() != NULL )
+        {
+            std::map< CPLString, int > oMapCountOccurrencesOfSameName;
+            BuildMapCountOccurrencesOfSameName(
+                poCT->getParticle()->getModelGroupTerm(),
+                oMapCountOccurrencesOfSameName);
+            if( !ExploreModelGroup(
+                                poCT->getParticle()->getModelGroupTerm(),
+                                poCT->getAttributeUses(),
+                                oClass,
+                                0,
+                                oSetVisitedModelGroups,
+                                poModel,
+                                oMapCountOccurrencesOfSameName) )
+            {
+                bError = true;
+                return false;
+            }
+        }
+        else
+        {
+            // TODO ?
+        }
+
+        LaunderFieldNames( oClass );
+
+        m_aoClasses.push_back(oClass);
+        return true;
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                 SetFieldTypeAndWidthFromDefinition()                 */
+/************************************************************************/
+
+void GMLASSchemaAnalyzer::SetFieldTypeAndWidthFromDefinition(
+                                                 XSSimpleTypeDefinition* poST,
+                                                 GMLASField& oField )
+{
+    int nMaxLength = 0;
+    while( poST->getBaseType() != poST &&
+            poST->getBaseType()->getTypeCategory() ==
+                                        XSTypeDefinition::SIMPLE_TYPE &&
+            !XMLString::equals(poST->getNamespace(),
+                               PSVIUni::fgNamespaceXmlSchema) )
+    {
+        const XMLCh* maxLength = poST->getLexicalFacetValue(
+                                    XSSimpleTypeDefinition::FACET_LENGTH );
+        if( maxLength == NULL )
+        {
+            maxLength = poST->getLexicalFacetValue(
+                                XSSimpleTypeDefinition::FACET_MAXLENGTH );
+        }
+        if( maxLength != NULL )
+            nMaxLength = MAX(nMaxLength, atoi( transcode(maxLength) ) );
+        poST = reinterpret_cast<XSSimpleTypeDefinition*>(poST->getBaseType());
+    }
+
+    if( XMLString::equals(poST->getNamespace(), PSVIUni::fgNamespaceXmlSchema) )
+    {
+        CPLString osType( transcode(poST->getName()) );
+        oField.SetType( GMLASField::GetTypeFromString(osType), osType );
+    }
+    else
+    {
+        CPLError(CE_Warning, CPLE_AppDefined, "Base type is not a xs: one ???");
+    }
+
+    oField.SetWidth( nMaxLength );
+}
+
+/************************************************************************/
+/*                              IsSame()                                */
+/*                                                                      */
+/* The objects returned by different PSVI API are not always the same   */
+/* so do content inspection to figure out if they are equivalent.       */
+/************************************************************************/
+
+bool GMLASSchemaAnalyzer::IsSame( const XSModelGroup* poModelGroup1,
+                                  const XSModelGroup* poModelGroup2 )
+{
+    if( poModelGroup1->getCompositor() != poModelGroup2->getCompositor() )
+        return false;
+
+    const XSParticleList* poParticleList1 = poModelGroup1->getParticles();
+    const XSParticleList* poParticleList2 = poModelGroup2->getParticles();
+    if( poParticleList1->size() != poParticleList2->size() )
+        return false;
+
+    for(size_t i = 0; i < poParticleList1->size(); ++i )
+    {
+        const XSParticle* poParticle1 = poParticleList1->elementAt(i);
+        const XSParticle* poParticle2 = poParticleList2->elementAt(i);
+        if( poParticle1->getTermType() != poParticle2->getTermType() ||
+            poParticle1->getMinOccurs() != poParticle2->getMinOccurs() ||
+            poParticle1->getMaxOccurs() != poParticle2->getMaxOccurs() ||
+            poParticle1->getMaxOccursUnbounded() !=
+                                        poParticle2->getMaxOccursUnbounded() )
+        {
+            return false;
+        }
+        switch( poParticle1->getTermType() )
+        {
+            case XSParticle::TERM_EMPTY:
+                break;
+
+            case XSParticle::TERM_ELEMENT:
+            {
+                const XSElementDeclaration* poElt1 =
+                    const_cast<XSParticle*>(poParticle1)->getElementTerm();
+                const XSElementDeclaration* poElt2 =
+                    const_cast<XSParticle*>(poParticle2)->getElementTerm();
+                // Pointer comparison works here
+                if( poElt1 != poElt2 )
+                    return false;
+                break;
+            }
+
+            case XSParticle::TERM_MODELGROUP:
+            {
+                const XSModelGroup* psSubGroup1 =
+                    const_cast<XSParticle*>(poParticle1)->getModelGroupTerm();
+                const XSModelGroup* psSubGroup2 =
+                    const_cast<XSParticle*>(poParticle2)->getModelGroupTerm();
+                if( !IsSame(psSubGroup1, psSubGroup2) )
+                    return false;
+                break;
+            }
+
+            case XSParticle::TERM_WILDCARD:
+            {
+                // TODO: check that pointer comparison works
+                const XSWildcard* psWildcard1 =
+                    const_cast<XSParticle*>(poParticle1)->getWildcardTerm();
+                const XSWildcard* psWildcard2 =
+                    const_cast<XSParticle*>(poParticle2)->getWildcardTerm();
+                if( psWildcard1 != psWildcard2 )
+                    return false;
+                break;
+            }
+
+            default:
+            {
+                CPLAssert(FALSE);
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                           GetGroupName()                             */
+/*                                                                      */
+/*  The model group object returned when exploring a high level model   */
+/*  group isn't the same object as the one returned by model group      */
+/*  definitions and has no name. So we have to investigate the content  */
+/*  of model groups to figure out if they are the same.                 */
+/************************************************************************/
+
+XSModelGroupDefinition* GMLASSchemaAnalyzer::GetGroupDefinition( const XSModelGroup* poModelGroup )
+{
+    std::map< XSModelGroup*, XSModelGroupDefinition*>::const_iterator oIter =
+        m_oMapModelGroupToMGD.begin();
+    for(; oIter != m_oMapModelGroupToMGD.end(); ++oIter )
+    {
+        const XSModelGroup* psIterModelGroup = oIter->first;
+        if( IsSame(poModelGroup, psIterModelGroup) )
+        {
+            return oIter->second;
+        }
+    }
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                              IsAnyType()                             */
+/************************************************************************/
+
+static bool IsAnyType(XSComplexTypeDefinition* poType)
+{
+    if( XMLString::equals(poType->getBaseType()->getNamespace(),
+                             PSVIUni::fgNamespaceXmlSchema) &&
+        transcode( poType->getBaseType()->getName() ) == szXS_ANY_TYPE )
+    {
+        XSParticle* poParticle = poType->getParticle();
+        if( poParticle != NULL )
+        {
+            XSModelGroup* poGroupTerm = poParticle->getModelGroupTerm();
+            if( poGroupTerm != NULL )
+            {
+                XSParticleList* poParticles =  poGroupTerm->getParticles();
+                if( poParticles != NULL )
+                {
+                    return poParticles->size() == 1 &&
+                           poParticles->elementAt(0)->getTermType() ==
+                                                    XSParticle::TERM_WILDCARD;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                       SetFieldFromAttribute()                        */
+/************************************************************************/
+
+void GMLASSchemaAnalyzer::SetFieldFromAttribute(
+                                  GMLASField& oField,
+                                  XSAttributeUse* poAttr,
+                                  const CPLString& osXPathPrefix,
+                                  const CPLString& osNamePrefix)
+{
+    XSAttributeDeclaration* poAttrDecl = poAttr->getAttrDeclaration();
+    XSSimpleTypeDefinition* poAttrType = poAttrDecl->getTypeDefinition();
+
+    SetFieldTypeAndWidthFromDefinition(poAttrType, oField);
+
+    CPLString osNS(transcode(poAttrDecl->getNamespace()));
+    CPLString osName(transcode(poAttrDecl->getName()));
+
+    if( osNamePrefix.empty() )
+        oField.SetName( osName );
+    else
+        oField.SetName( osNamePrefix + "_" + osName );
+
+    oField.SetXPath( osXPathPrefix + "/@" +
+                        MakeXPath( osNS, osName) );
+    if( poAttr->getRequired() )
+    {
+        oField.SetNotNullable( true );
+    }
+    oField.SetMinOccurs( oField.IsNotNullable() ? 1 : 0 );
+    oField.SetMaxOccurs( 1 );
+    if( poAttr->getConstraintType() ==
+                            XSConstants::VALUE_CONSTRAINT_FIXED )
+    {
+        oField.SetFixedValue(
+                    transcode(poAttr->getConstraintValue()) );
+    }
+    else if( poAttr->getConstraintType() ==
+                            XSConstants::VALUE_CONSTRAINT_DEFAULT )
+    {
+        oField.SetDefaultValue(
+                    transcode(poAttr->getConstraintValue()) );
+    }
+
+    const bool bIsList =
+        ( poAttrType->getVariety() == XSSimpleTypeDefinition::VARIETY_LIST );
+    if( bIsList )
+    {
+        SetFieldTypeAndWidthFromDefinition(poAttrType->getItemType(), oField);
+        if( m_bUseArrays && IsCompatibleOfArray(oField.GetType()) )
+        {
+            oField.SetList( true );
+            oField.SetArray( true );
+        }
+        else
+        {
+            // We should probably create an auxiliary table here, but this
+            // is too corner case for now...
+            oField.SetType( GMLAS_FT_STRING, szXS_STRING );
+        }
+    }
+
+    oField.SetDocumentation( GetAnnotationDoc( poAttrDecl->getAnnotation() ) );
+}
+
+/************************************************************************/
+/*                      GetConcreteImplementationTypes()                */
+/************************************************************************/
+
+void GMLASSchemaAnalyzer::GetConcreteImplementationTypes(
+                                XSElementDeclaration* poParentElt,
+                                std::vector<XSElementDeclaration*>& apoImplEltList)
+{
+    tMapParentEltToChildElt::const_iterator oIter =
+        m_oMapParentEltToChildElt.find( poParentElt );
+    if( oIter != m_oMapParentEltToChildElt.end() )
+    {
+        for( size_t j = 0; j < oIter->second.size(); j++ )
+        {
+            XSElementDeclaration* poSubElt = oIter->second[j];
+            if( IsEltCompatibleOfFC(poSubElt) )
+            {
+                if( !poSubElt->getAbstract() )
+                {
+                    apoImplEltList.push_back(poSubElt);
+                }
+                GetConcreteImplementationTypes(poSubElt, apoImplEltList);
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                       GetConstraintChildrenElements()                */
+/************************************************************************/
+
+std::vector<XSElementDeclaration*>
+    GMLASSchemaAnalyzer::GetConstraintChildrenElements(const CPLString& osFullXPath)
+{
+
+    std::vector<XSElementDeclaration*> oVectorRes;
+    CPLString osMatched;
+    if( m_oChildrenElementsConstraintsXPathMatcher.MatchesRefXPath(
+                                                    osFullXPath, osMatched) )
+    {
+        const std::vector<CPLString>& oVector =
+                                m_oMapChildrenElementsConstraints[osMatched];
+        const std::map<CPLString, CPLString>& oMapPrefixToURI =
+                m_oChildrenElementsConstraintsXPathMatcher.GetMapPrefixToURI();
+        for( size_t j = 0; j < oVector.size(); ++j )
+        {
+            const CPLString& osSubElt(oVector[j]);
+            CPLString osSubEltPrefix;
+            CPLString osSubEltURI;
+            CPLString osSubEltType(osSubElt);
+            size_t nPos = osSubElt.find(":");
+            if( nPos != std::string::npos )
+            {
+                osSubEltPrefix = osSubElt.substr(0, nPos);
+                osSubEltType = osSubElt.substr(nPos+1);
+
+                std::map<CPLString, CPLString>::const_iterator oIter2 =
+                    oMapPrefixToURI.find(osSubEltPrefix);
+                if( oIter2 != oMapPrefixToURI.end() )
+                {
+                    osSubEltURI = oIter2->second;
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "Cannot find prefix of type constraint %s",
+                            osSubElt.c_str());
+                }
+            }
+
+            const CPLString osSubEltXPath(MakeXPath(osSubEltURI, osSubEltType));
+            std::map<CPLString, XSElementDeclaration*>::const_iterator oIter2 =
+                m_oMapXPathToEltDecl.find(osSubEltXPath);
+            if( oIter2 != m_oMapXPathToEltDecl.end() )
+            {
+                XSElementDeclaration* poSubElt = oIter2->second;
+                if( IsEltCompatibleOfFC(poSubElt) )
+                {
+                    oVectorRes.push_back(poSubElt);
+                }
+            }
+            else
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Cannot find element declaration of type constraint %s",
+                         osSubElt.c_str());
+            }
+        }
+    }
+    return oVectorRes;
+}
+
+/************************************************************************/
+/*                        GetOGRGeometryType()                          */
+/************************************************************************/
+
+static OGRwkbGeometryType GetOGRGeometryType( XSTypeDefinition* poTypeDef )
+{
+    const struct MyStruct
+    {
+        const char* pszName;
+        OGRwkbGeometryType eType;
+    } asArray[] = {
+        { "GeometryPropertyType", wkbUnknown },
+        { "PointPropertyType", wkbPoint },
+        { "PolygonPropertyType", wkbPolygon },
+        { "LineStringPropertyType", wkbLineString },
+        { "MultiPointPropertyType", wkbMultiPoint },
+        { "MultiPolygonPropertyType", wkbMultiPolygon },
+        { "MultiLineStringPropertyType", wkbMultiLineString },
+        { "MultiGeometryPropertyType", wkbGeometryCollection },
+        { "MultiCurvePropertyType", wkbMultiCurve },
+        { "MultiSurfacePropertyType", wkbMultiSurface },
+        { "MultiSolidPropertyType", wkbUnknown },
+        // GeometryArrayPropertyType ?
+        // GeometricPrimitivePropertyType ?
+        { "CurvePropertyType", wkbCurve },
+        { "SurfacePropertyType", wkbSurface },
+        // SurfaceArrayPropertyType ?
+        // AbstractRingPropertyType ?
+        // LinearRingPropertyType ?
+        { "CompositeCurvePropertyType", wkbCurve },
+        { "CompositeSurfacePropertyType", wkbSurface },
+        { "CompositeSolidPropertyType", wkbUnknown },
+        { "GeometricComplexPropertyType", wkbUnknown },
+    };
+
+    CPLString osName(transcode(poTypeDef->getName()));
+    for( size_t i = 0; i < CPL_ARRAYSIZE(asArray); ++i )
+    {
+        if( osName == asArray[i].pszName )
+            return asArray[i].eType;
+    }
+    return wkbNone;
+
+#if 0
+  <complexType name="CurveSegmentArrayPropertyType">
+  <complexType name="KnotPropertyType">
+  <complexType name="SurfacePatchArrayPropertyType">
+  <complexType name="RingPropertyType">
+  <complexType name="PolygonPatchArrayPropertyType">
+  <complexType name="TrianglePatchArrayPropertyType">
+  <complexType name="LineStringSegmentArrayPropertyType">
+  <complexType name="SolidPropertyType">
+  <complexType name="SolidArrayPropertyType">
+#endif
+}
+
+
+/************************************************************************/
+/*                 GetOGRGeometryTypeFromGMLEltName()                   */
+/************************************************************************/
+
+static OGRwkbGeometryType GetOGRGeometryTypeFromGMLEltName(
+                                                    const CPLString& osEltName )
+{
+    const struct MyStruct
+    {
+        const char* pszName;
+        OGRwkbGeometryType eType;
+    } asArray[] = {
+        { "Point", wkbPoint },
+        { "Polygon", wkbPolygon },
+        { "LineString", wkbLineString },
+        { "MultiPoint", wkbMultiPoint },
+        { "MultiPolygon", wkbMultiPolygon },
+        { "MultiLineString", wkbMultiLineString },
+        { "MultiGeometry", wkbGeometryCollection },
+        { "MultiCurve", wkbMultiCurve },
+        { "MultiSurface", wkbMultiSurface },
+        { "MultiSolid", wkbUnknown },
+        { "Curve", wkbCurve },
+        { "Surface", wkbSurface },
+        { "CompositeCurve", wkbCurve },
+        { "CompositeSurface", wkbSurface },
+        { "CompositeSolid", wkbUnknown },
+        { "GeometricComplex", wkbUnknown },
+    };
+
+    for( size_t i = 0; i < CPL_ARRAYSIZE(asArray); ++i )
+    {
+        if( osEltName == asArray[i].pszName )
+            return asArray[i].eType;
+    }
+    return wkbNone;
+}
+
+/************************************************************************/
+/*                      CreateNonNestedRelationship()                  */
+/************************************************************************/
+
+void GMLASSchemaAnalyzer::CreateNonNestedRelationship(
+                        XSElementDeclaration* poElt,
+                        std::vector<XSElementDeclaration*>& apoImplEltList,
+                        GMLASFeatureClass& oClass,
+                        int nMaxOccurs,
+                        bool bEltNameWillNeedPrefix,
+                        bool bForceJunctionTable,
+                        bool bCaseOfConstraintChildren )
+{
+    const CPLString osEltPrefix(
+                GetPrefix(transcode(poElt->getNamespace())));
+    const CPLString osEltName(transcode(poElt->getName()));
+    const CPLString osOnlyElementXPath(
+                    MakeXPath(transcode(poElt->getNamespace()),
+                              osEltName) );
+    const CPLString osElementXPath( oClass.GetXPath() + "/" +
+                                    osOnlyElementXPath );
+
+    if( !poElt->getAbstract() && !bCaseOfConstraintChildren )
+    {
+        apoImplEltList.insert(apoImplEltList.begin(), poElt);
+    }
+
+    std::set<CPLString> aoSetSubEltXPath;
+    if( nMaxOccurs == 1 && !bForceJunctionTable )
+    {
+        // If the field isn't repeated, then we can link to each
+        // potential realization types with a field
+
+        for( size_t j = 0; j < apoImplEltList.size(); j++ )
+        {
+            XSElementDeclaration* poSubElt = apoImplEltList[j];
+            const CPLString osSubEltName(transcode(poSubElt->getName()));
+            const CPLString osSubEltXPath(
+                MakeXPath(transcode(poSubElt->getNamespace()),
+                          osSubEltName) );
+
+            // For AbstractFeature_SpatialDataSet_pkid in SpatialDataSet_member
+            if( aoSetSubEltXPath.find(osSubEltXPath) !=
+                                            aoSetSubEltXPath.end() )
+            {
+                continue;
+            }
+            aoSetSubEltXPath.insert(osSubEltXPath);
+
+            const CPLString osRealFullXPath( oClass.GetXPath() + "/" +
+                    ((bCaseOfConstraintChildren) ?
+                            osOnlyElementXPath + "/" : CPLString("")) +
+                                             osSubEltXPath );
+
+            if( IsIgnoredXPath( osRealFullXPath ) )
+            {
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GMLAS", "%s is in ignored xpaths",
+                         osRealFullXPath.c_str());
+#endif
+                continue;
+            }
+
+            GMLASField oField;
+            if( apoImplEltList.size() > 1 || bCaseOfConstraintChildren )
+            {
+                if( m_oMapEltNamesToInstanceCount[osSubEltName] > 1  )
+                {
+                    CPLString osLaunderedXPath(osSubEltXPath);
+                    osLaunderedXPath.replaceAll(':', '_');
+                    oField.SetName(
+                        ((bEltNameWillNeedPrefix) ? osEltPrefix + "_" :
+                                                                CPLString()) +
+                                    transcode(poElt->getName()) + "_" +
+                                    osLaunderedXPath + "_pkid" );
+                }
+                else
+                {
+                    oField.SetName(
+                        ((bEltNameWillNeedPrefix) ? osEltPrefix + "_" :
+                                                                CPLString()) +
+                            transcode(poElt->getName()) + "_" +
+                                    osSubEltName + "_pkid" );
+                }
+            }
+            else
+            {
+                oField.SetName( transcode(poElt->getName()) + "_pkid" );
+            }
+            oField.SetXPath( osRealFullXPath );
+            oField.SetMinOccurs( 0 );
+            oField.SetMaxOccurs( nMaxOccurs );
+            oField.SetCategory( GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK );
+            oField.SetRelatedClassXPath(osSubEltXPath);
+            oField.SetType( GMLAS_FT_STRING, szXS_STRING );
+            oClass.AddField( oField );
+        }
+    }
+    else
+    {
+        // If the field is repeated, we need to use junction
+        // tables
+        for( size_t j = 0; j < apoImplEltList.size(); j++ )
+        {
+            XSElementDeclaration* poSubElt = apoImplEltList[j];
+            const CPLString osSubEltName( transcode(poSubElt->getName()) );
+            const CPLString osSubEltXPath(
+                MakeXPath(transcode(poSubElt->getNamespace()), osSubEltName) );
+
+            // For AbstractFeature_SpatialDataSet_pkid in SpatialDataSet_member
+            if( aoSetSubEltXPath.find(osSubEltXPath) !=
+                                            aoSetSubEltXPath.end() )
+            {
+                continue;
+            }
+            aoSetSubEltXPath.insert(osSubEltXPath);
+
+            // Instantiate a junction table
+            GMLASFeatureClass oJunctionTable;
+
+            if( m_oMapEltNamesToInstanceCount[osSubEltName] > 1 )
+            {
+                CPLString osLaunderedXPath(osSubEltXPath);
+                osLaunderedXPath.replaceAll(':', '_');
+                oJunctionTable.SetName( oClass.GetName() + "_" +
+                                        transcode(poElt->getName()) + "_" +
+                                        osLaunderedXPath );
+            }
+            else
+            {
+                oJunctionTable.SetName( oClass.GetName() + "_" +
+                                        transcode(poElt->getName()) + "_" +
+                                        osSubEltName );
+            }
+            // Create a fake XPath binding the parent xpath (to an abstract
+            // element) to the child element
+            oJunctionTable.SetXPath(
+                BuildJunctionTableXPath(osElementXPath, osSubEltXPath) );
+            oJunctionTable.SetParentXPath( oClass.GetXPath() );
+            oJunctionTable.SetChildXPath( osSubEltXPath );
+            m_aoClasses.push_back(oJunctionTable);
+
+            // Add an abstract field
+            GMLASField oField;
+            oField.SetName(
+                ((bEltNameWillNeedPrefix) ? osEltPrefix + "_" :
+                                                                CPLString()) +
+                osEltName + "_" + osSubEltName );
+            oField.SetXPath( oClass.GetXPath() + "/" +
+                    ((bCaseOfConstraintChildren) ?
+                            osOnlyElementXPath + "/" : CPLString("")) +
+                                                osSubEltXPath);
+            oField.SetMinOccurs( 0 );
+            oField.SetMaxOccurs( nMaxOccurs );
+            oField.SetAbstractElementXPath(osElementXPath);
+            oField.SetRelatedClassXPath(osSubEltXPath);
+            oField.SetCategory(
+                    GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE );
+            oClass.AddField( oField );
+        }
+    }
+
+#if 0
+    GMLASField oField;
+    oField.SetName( transcode(poElt->getName()) );
+    oField.SetXPath( osElementXPath );
+    oField.SetMinOccurs( poParticle->getMinOccurs() );
+    oField.SetMaxOccurs( poParticle->getMaxOccursUnbounded() ?
+        MAXOCCURS_UNLIMITED : poParticle->getMaxOccurs() );
+
+    for( size_t j = 0; j < apoImplEltList.size(); j++ )
+    {
+        XSElementDeclaration* poSubElt = apoImplEltList[j];
+        XSTypeDefinition* poSubEltType =
+                                    poSubElt->getTypeDefinition();
+        XSComplexTypeDefinition* poCT =
+            reinterpret_cast<XSComplexTypeDefinition*>(poSubEltType);
+
+        GMLASFeatureClass oNestedClass;
+        oNestedClass.SetName( oClass.GetName() + "_" +
+                    transcode(poSubElt->getName()) );
+        oNestedClass.SetXPath( oClass.GetXPath() + "/" +
+            MakeXPath(transcode(poSubElt->getNamespace()),
+                        transcode(poSubElt->getName())) );
+
+        std::set<XSModelGroup*>
+            oSetNewVisitedModelGroups(oSetVisitedModelGroups);
+        if( !ExploreModelGroup(
+                poCT->getParticle()->getModelGroupTerm(),
+                NULL,
+                oNestedClass,
+                nRecursionCounter + 1,
+                oSetNewVisitedModelGroups ) )
+        {
+            return false;
+        }
+
+        oClass.AddNestedClass( oNestedClass );
+    }
+
+    if( !apoImplEltList.empty() )
+    {
+        oField.SetAbstract(true);
+    }
+    else
+    {
+        oField.SetType( GMLAS_FT_ANYTYPE, "anyType" );
+        oField.SetXPath( oClass.GetXPath() + "/" + "*" );
+        oField.SetIncludeThisEltInBlob( true );
+    }
+    oClass.AddField( oField );
+#endif
+}
+
+/************************************************************************/
+/*                          IsIgnoredXPath()                            */
+/************************************************************************/
+
+bool GMLASSchemaAnalyzer::IsIgnoredXPath(const CPLString& osXPath)
+{
+    CPLString osIgnored;
+    return m_oIgnoredXPathMatcher.MatchesRefXPath(osXPath, osIgnored);
+}
+
+/************************************************************************/
+/*                     FindElementsWithMustBeToLevel()                  */
+/************************************************************************/
+
+bool GMLASSchemaAnalyzer::FindElementsWithMustBeToLevel(
+                            const CPLString& osParentXPath,
+                            XSModelGroup* poModelGroup,
+                            int nRecursionCounter,
+                            std::set<XSElementDeclaration*>& oSetVisitedEltDecl,
+                            std::set<XSModelGroup*>& oSetVisitedModelGroups,
+                            std::vector<XSElementDeclaration*>&
+                                                        oVectorEltsForTopClass,
+                            std::set<CPLString>& aoSetXPathEltsForTopClass,
+                            XSModel* poModel,
+                            bool& bSimpleEnoughOut,
+                            int& nCountSubEltsOut )
+{
+    const bool bAlreadyVisitedMG =
+            ( oSetVisitedModelGroups.find(poModelGroup) !=
+                                                oSetVisitedModelGroups.end() );
+
+    oSetVisitedModelGroups.insert(poModelGroup);
+
+    if( nRecursionCounter == 100 )
+    {
+        // Presumably an hostile schema
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Schema analysis failed due to too deeply nested model");
+        return false;
+    }
+
+    {
+        CPLString osIgnored;
+        if( m_oDisabledFlattenedXPathMatcher.MatchesRefXPath(
+                                            osParentXPath, osIgnored))
+        {
+            bSimpleEnoughOut = false;
+        }
+    }
+
+    XSParticleList* poParticles = poModelGroup->getParticles();
+    for(size_t i = 0; i < poParticles->size(); ++i )
+    {
+        XSParticle* poParticle = poParticles->elementAt(i);
+
+        const bool bRepeatedParticle = poParticle->getMaxOccursUnbounded() ||
+                                        poParticle->getMaxOccurs() > 1;
+
+        if( poParticle->getTermType() == XSParticle::TERM_ELEMENT )
+        {
+            XSElementDeclaration* poElt = poParticle->getElementTerm();
+            XSTypeDefinition* poTypeDef = poElt->getTypeDefinition();
+            const CPLString osEltName(transcode(poElt->getName()));
+            const CPLString osEltNS(transcode(poElt->getNamespace()));
+            const CPLString osXPath( MakeXPath(osEltNS, osEltName) );
+            const CPLString osFullXPath( osParentXPath + "/" + osXPath );
+
+#ifdef DEBUG_SUPER_VERBOSE
+            CPLDebug("GMLAS", "FindElementsWithMustBeToLevel: %s",
+                     osFullXPath.c_str());
+#endif
+
+            if( IsIgnoredXPath( osFullXPath ) )
+            {
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GMLAS", "%s is in ignored xpaths",
+                         osFullXPath.c_str());
+#endif
+                continue;
+            }
+
+            // This could be refined to detect if the repeated element might not
+            // be simplifiable as an array
+            if( bSimpleEnoughOut && bRepeatedParticle )
+            {
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GMLAS",
+                         "%s not inlinable because %s is repeated",
+                         osParentXPath.c_str(),
+                         osXPath.c_str()
+                        );
+#endif
+                bSimpleEnoughOut = false;
+            }
+
+            // We don't want to inline
+            // sub-classes with hundereds of attributes
+            nCountSubEltsOut ++;
+
+            std::vector<XSElementDeclaration*> apoImplEltList;
+            GetConcreteImplementationTypes(poElt, apoImplEltList);
+
+            std::vector<XSElementDeclaration*> apoChildrenElements =
+                GetConstraintChildrenElements(osFullXPath);
+
+            // Special case for a GML geometry property
+            if( IsGMLNamespace(transcode(poTypeDef->getNamespace())) &&
+                GetOGRGeometryType(poTypeDef) != wkbNone )
+            {
+                // Do nothing
+            }
+            else if( IsGMLNamespace(osEltNS) &&
+                     GetOGRGeometryTypeFromGMLEltName(osEltName) != wkbNone )
+            {
+                // Do nothing
+            }
+            // Any GML abstract type
+            else if( poElt->getAbstract() &&
+                     IsGMLNamespace(osEltNS) &&
+                     osEltName != "_Feature" &&
+                     osEltName != "AbstractFeature" &&
+                     osEltName != "AbstractTimeObject" )
+            {
+                // Do nothing
+            }
+            // Are there substitution groups for this element ?
+            else if( !apoImplEltList.empty() || !apoChildrenElements.empty() )
+            {
+                if( !apoChildrenElements.empty() )
+                {
+                    apoImplEltList = apoChildrenElements;
+                }
+                else if( !poElt->getAbstract() )
+                {
+                    apoImplEltList.insert(apoImplEltList.begin(), poElt);
+                }
+                for( size_t j = 0; j < apoImplEltList.size(); j++ )
+                {
+                    XSElementDeclaration* poSubElt = apoImplEltList[j];
+                    const CPLString osSubEltXPath(
+                        MakeXPath(transcode(poSubElt->getNamespace()),
+                                    transcode(poSubElt->getName())) );
+
+                    if( IsIgnoredXPath( osParentXPath + "/" + osSubEltXPath ) )
+                    {
+#ifdef DEBUG_VERBOSE
+                        CPLDebug("GMLAS", "%s is in ignored xpaths",
+                                 (osParentXPath + "/" + osSubEltXPath).c_str());
+#endif
+                        continue;
+                    }
+
+                    // Make sure we will instantiate the referenced element
+                    if( m_oSetEltsForTopClass.find( poSubElt ) ==
+                                m_oSetEltsForTopClass.end() &&
+                        aoSetXPathEltsForTopClass.find( osSubEltXPath )
+                                == aoSetXPathEltsForTopClass.end() )
+                    {
+#ifdef DEBUG_VERBOSE
+                        CPLDebug("GMLAS", "%s (%s) must be exposed as "
+                                     "top-level (%s of %s)",
+                                osSubEltXPath.c_str(),
+                                transcode(poSubElt->getTypeDefinition()->
+                                                            getName()).c_str(),
+                                apoChildrenElements.empty() ?
+                                                "derived class" : "child",
+                                osParentXPath.c_str()
+                                );
+#endif
+
+                        oSetVisitedEltDecl.insert(poSubElt);
+                        m_oSetEltsForTopClass.insert(poSubElt);
+                        oVectorEltsForTopClass.push_back(poSubElt);
+                        aoSetXPathEltsForTopClass.insert( osSubEltXPath );
+
+                        XSComplexTypeDefinition* poSubEltCT =
+                                            IsEltCompatibleOfFC(poSubElt);
+                        if( !bAlreadyVisitedMG &&
+                            poSubEltCT != NULL &&
+                            poSubEltCT->getParticle() != NULL )
+                        {
+                            bool bSubSimpleEnoughOut = true;
+                            int nSubCountSubElt = 0;
+                            if( !FindElementsWithMustBeToLevel(
+                                            osSubEltXPath,
+                                            poSubEltCT->getParticle()->
+                                                        getModelGroupTerm(),
+                                            nRecursionCounter + 1,
+                                            oSetVisitedEltDecl,
+                                            oSetVisitedModelGroups,
+                                            oVectorEltsForTopClass,
+                                            aoSetXPathEltsForTopClass,
+                                            poModel,
+                                            bSubSimpleEnoughOut,
+                                            nSubCountSubElt ) )
+                            {
+                                return false;
+                            }
+                        }
+                    }
+                }
+            }
+
+            else if( !poElt->getAbstract() &&
+                poTypeDef->getTypeCategory() == XSTypeDefinition::COMPLEX_TYPE )
+            {
+                nCountSubEltsOut --;
+
+                XSComplexTypeDefinition* poEltCT = IsEltCompatibleOfFC(poElt);
+                if( poEltCT )
+                {
+                    // Might be a bit extreme, but for now we don't inline
+                    // classes that have subclasses.
+                    if( bSimpleEnoughOut )
+                    {
+#ifdef DEBUG_VERBOSE
+                        CPLDebug("GMLAS",
+                                  "%s not inlinable because %s field is complex",
+                                  osParentXPath.c_str(),
+                                 osXPath.c_str());
+#endif
+                        bSimpleEnoughOut = false;
+                    }
+
+                    if( oSetVisitedEltDecl.find(poElt) !=
+                                    oSetVisitedEltDecl.end() )
+                    {
+                        if( m_oSetEltsForTopClass.find(poElt) ==
+                                                m_oSetEltsForTopClass.end() &&
+                            m_oSetSimpleEnoughElts.find(poElt) ==
+                                        m_oSetSimpleEnoughElts.end() &&
+                            aoSetXPathEltsForTopClass.find( osXPath )
+                                == aoSetXPathEltsForTopClass.end() )
+                        {
+#ifdef DEBUG_VERBOSE
+                            CPLDebug("GMLAS", "%s (%s) must be exposed as "
+                                     "top-level (multiple time referenced)",
+                                     osXPath.c_str(),
+                                     transcode(
+                                        poTypeDef->getNamespace()).c_str());
+#endif
+                            m_oSetEltsForTopClass.insert(poElt);
+                            oVectorEltsForTopClass.push_back(poElt);
+                            aoSetXPathEltsForTopClass.insert( osXPath );
+                        }
+                    }
+                    else
+                    {
+                        oSetVisitedEltDecl.insert(poElt);
+
+                        if( !bAlreadyVisitedMG &&
+                            poEltCT->getParticle() != NULL )
+                        {
+                            bool bSubSimpleEnoughOut = true;
+                            int nSubCountSubElt = 0;
+
+                            // Process attributes
+                            XSAttributeUseList* poAttrList =
+                                                    poEltCT->getAttributeUses();
+                            const size_t nAttrListSize = (poAttrList != NULL) ?
+                                                                poAttrList->size(): 0;
+                            for(size_t j=0; bSubSimpleEnoughOut && j< nAttrListSize; ++j )
+                            {
+                                XSAttributeUse* poAttr = poAttrList->elementAt(j);
+                                GMLASField oField;
+                                SetFieldFromAttribute(oField, poAttr, osFullXPath);
+                                if( !IsIgnoredXPath( oField.GetXPath() ) &&
+                                    oField.GetFixedValue().empty() )
+                                {
+#ifdef DEBUG_SUPER_VERBOSE
+                                    CPLDebug("GMLAS", "FindElementsWithMustBeToLevel: %s",
+                                             oField.GetXPath().c_str());
+#endif
+                                    nSubCountSubElt ++;
+                                }
+                            }
+
+                            if( !FindElementsWithMustBeToLevel(
+                                            osFullXPath,
+                                            poEltCT->getParticle()->
+                                                            getModelGroupTerm(),
+                                            nRecursionCounter + 1,
+                                            oSetVisitedEltDecl,
+                                            oSetVisitedModelGroups,
+                                            oVectorEltsForTopClass,
+                                            aoSetXPathEltsForTopClass,
+                                            poModel,
+                                            bSubSimpleEnoughOut,
+                                            nSubCountSubElt ) )
+                            {
+                                return false;
+                            }
+                            if( bSubSimpleEnoughOut )
+                            {
+#ifdef DEBUG_VERBOSE
+                                CPLDebug("GMLAS",
+                                    "%s is inlinable: %d fields",
+                                    osXPath.c_str(),
+                                    nSubCountSubElt
+                                    );
+#endif
+                                m_oSetSimpleEnoughElts.insert(poElt);
+
+                                nCountSubEltsOut += nSubCountSubElt;
+                            }
+                            else if( bSimpleEnoughOut )
+                            {
+#ifdef DEBUG_VERBOSE
+                                CPLDebug("GMLAS",
+                                    "%s not inlinable because %s is not inlinable",
+                                    osParentXPath.c_str(),
+                                    osXPath.c_str()
+                                    );
+#endif
+                                bSimpleEnoughOut = false;
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    if( transcode(poElt->getName()) != szFEATURE_COLLECTION )
+                    {
+                        poEltCT =
+                            reinterpret_cast<XSComplexTypeDefinition*>(poTypeDef);
+// Process attributes
+                        XSAttributeUseList* poAttrList =
+                                                poEltCT->getAttributeUses();
+                        const size_t nAttrListSize = (poAttrList != NULL) ?
+                                                            poAttrList->size(): 0;
+                        for(size_t j=0; bSimpleEnoughOut && j< nAttrListSize; ++j )
+                        {
+                            XSAttributeUse* poAttr = poAttrList->elementAt(j);
+                            GMLASField oField;
+                            SetFieldFromAttribute(oField, poAttr, osFullXPath);
+                            if( !IsIgnoredXPath( oField.GetXPath() ) &&
+                                oField.GetFixedValue().empty() )
+                            {
+#ifdef DEBUG_SUPER_VERBOSE
+                                CPLDebug("GMLAS", "FindElementsWithMustBeToLevel: %s",
+                                            oField.GetXPath().c_str());
+#endif
+                                nCountSubEltsOut ++;
+                            }
+                        }
+                    }
+                }
+
+                CPLString osTargetElement;
+                if( poElt->getAnnotation() != NULL )
+                {
+                    CPLString osAnnot(transcode(
+                        poElt->getAnnotation()->getAnnotationString()));
+
+#ifdef DEBUG_SUPER_VERBOSE
+                    CPLDebug("GMLAS", "Annot: %s", osAnnot.c_str());
+#endif
+                    CPLXMLNode* psRoot = CPLParseXMLString(osAnnot);
+                    CPLStripXMLNamespace(psRoot, NULL, TRUE);
+                    osTargetElement =
+                        CPLGetXMLValue(psRoot,
+                                       "=annotation.appinfo.targetElement", "");
+                    CPLDestroyXMLNode(psRoot);
+#ifdef DEBUG_VERBOSE
+                    if( !osTargetElement.empty() )
+                        CPLDebug("GMLAS", "targetElement: %s",
+                                osTargetElement.c_str());
+#endif
+                }
+
+                // If we have a element of type gml:ReferenceType that has
+                // a targetElement in its annotation.appinfo, then create
+                // a dedicated field to have cross-layer relationships.
+                if( IsGMLNamespace(transcode(poTypeDef->getNamespace())) &&
+                    transcode(poTypeDef->getName()) == "ReferenceType" &&
+                    !osTargetElement.empty() )
+                {
+                    XSElementDeclaration* poTargetElt =
+                        GetTopElementDeclarationFromXPath(osTargetElement,
+                                                            poModel);
+                    // TODO: even for non abstract we should probably
+                    // handle substitutions
+                    if( poTargetElt != NULL && !poTargetElt->getAbstract() )
+                    {
+                        const CPLString osTargetEltXPath( MakeXPath(
+                                    transcode(poTargetElt->getNamespace()),
+                                    transcode(poTargetElt->getName())) );
+
+                        if( IsIgnoredXPath( osTargetEltXPath ) )
+                        {
+#ifdef DEBUG_VERBOSE
+                            CPLDebug("GMLAS", "%s is in ignored xpaths",
+                                    osTargetEltXPath.c_str());
+#endif
+                            continue;
+                        }
+
+                        // Make sure we will instantiate the referenced
+                        //element
+                        if( m_oSetEltsForTopClass.find( poTargetElt ) ==
+                                    m_oSetEltsForTopClass.end() &&
+                            aoSetXPathEltsForTopClass.find( osTargetEltXPath )
+                                == aoSetXPathEltsForTopClass.end() )
+                        {
+#ifdef DEBUG_VERBOSE
+                            CPLDebug("GMLAS",
+                                        "%d: Adding %s as (%s) needed type",
+                                        __LINE__,
+                                    osTargetElement.c_str(),
+                                    transcode(poTargetElt->
+                                                getTypeDefinition()->
+                                                    getName()).c_str());
+#endif
+                            oSetVisitedEltDecl.insert(poTargetElt);
+                            m_oSetEltsForTopClass.insert( poTargetElt );
+                            oVectorEltsForTopClass.push_back(poTargetElt);
+                            aoSetXPathEltsForTopClass.insert( osTargetEltXPath );
+                        }
+
+                        XSComplexTypeDefinition* poTargetEltCT =
+                                    IsEltCompatibleOfFC(poTargetElt);
+                        if( !bAlreadyVisitedMG &&
+                            poTargetEltCT &&
+                            poTargetEltCT->getParticle() != NULL )
+                        {
+                            bool bSubSimpleEnoughOut = true;
+                            int nSubCountSubElt = 0;
+                            if( !FindElementsWithMustBeToLevel(
+                                            osTargetEltXPath,
+                                            poTargetEltCT->getParticle()->
+                                                            getModelGroupTerm(),
+                                            nRecursionCounter + 1,
+                                            oSetVisitedEltDecl,
+                                            oSetVisitedModelGroups,
+                                            oVectorEltsForTopClass,
+                                            aoSetXPathEltsForTopClass,
+                                            poModel,
+                                            bSubSimpleEnoughOut,
+                                            nSubCountSubElt) )
+                            {
+                                return false;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        else if( !bAlreadyVisitedMG &&
+                 poParticle->getTermType() == XSParticle::TERM_MODELGROUP )
+        {
+            // This could be refined to detect if the repeated element might not
+            // be simplifiable as an array
+            if( bSimpleEnoughOut && bRepeatedParticle )
+            {
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GMLAS",
+                        "%s not inlinable because there is a repeated particle",
+                        osParentXPath.c_str());
+#endif
+                bSimpleEnoughOut = false;
+            }
+
+            XSModelGroup* psSubModelGroup = poParticle->getModelGroupTerm();
+            if( !FindElementsWithMustBeToLevel(
+                                    osParentXPath,
+                                    psSubModelGroup,
+                                    nRecursionCounter + 1,
+                                    oSetVisitedEltDecl,
+                                    oSetVisitedModelGroups,
+                                    oVectorEltsForTopClass,
+                                    aoSetXPathEltsForTopClass,
+                                    poModel,
+                                    bSimpleEnoughOut,
+                                    nCountSubEltsOut) )
+            {
+                return false;
+            }
+        }
+        else
+        {
+            // This could be refined to detect if the repeated element might not
+            // be simplifiable as an array
+            if( bSimpleEnoughOut && bRepeatedParticle )
+            {
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GMLAS",
+                        "%s not inlinable because there is a repeated particle",
+                        osParentXPath.c_str());
+#endif
+                bSimpleEnoughOut = false;
+            }
+        }
+    }
+
+    if( bSimpleEnoughOut &&
+        nCountSubEltsOut > m_nMaximumFieldsForFlattening )
+    {
+        CPLString osIgnored;
+        if( !m_oForcedFlattenedXPathMatcher.MatchesRefXPath(
+                                                osParentXPath, osIgnored))
+        {
+#ifdef DEBUG_VERBOSE
+            CPLDebug("GMLAS",
+                        "%s not inlinable because it has more than %d fields",
+                        osParentXPath.c_str(),
+                        m_nMaximumFieldsForFlattening);
+#endif
+            bSimpleEnoughOut = false;
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                           IsGMLNamespace()                           */
+/************************************************************************/
+
+bool GMLASSchemaAnalyzer::IsGMLNamespace(const CPLString& osURI)
+{
+    if( osURI.find(szGML_URI) == 0 )
+        return true;
+    // Below is mostly for unit tests were we use xmlns:gml="http://fake_gml"
+    std::map<CPLString,CPLString>::const_iterator oIter =
+                                        m_oMapURIToPrefix.find(osURI);
+    return oIter != m_oMapURIToPrefix.end() && oIter->second == szGML_PREFIX;
+}
+
+/************************************************************************/
+/*                    BuildMapCountOccurrencesOfSameName()               */
+/************************************************************************/
+
+void GMLASSchemaAnalyzer::BuildMapCountOccurrencesOfSameName(
+                    XSModelGroup* poModelGroup,
+                    std::map< CPLString, int >& oMapCountOccurrencesOfSameName)
+{
+    XSParticleList* poParticles = poModelGroup->getParticles();
+    for(size_t i = 0; i < poParticles->size(); ++i )
+    {
+        XSParticle* poParticle = poParticles->elementAt(i);
+        if( poParticle->getTermType() == XSParticle::TERM_ELEMENT )
+        {
+            XSElementDeclaration* poElt = poParticle->getElementTerm();
+            const CPLString osEltName(transcode(poElt->getName()));
+            oMapCountOccurrencesOfSameName[ osEltName ] ++;
+        }
+        else if( poParticle->getTermType() == XSParticle::TERM_MODELGROUP )
+        {
+            XSModelGroup* psSubModelGroup = poParticle->getModelGroupTerm();
+            BuildMapCountOccurrencesOfSameName(psSubModelGroup,
+                                              oMapCountOccurrencesOfSameName);
+        }
+    }
+}
+
+/************************************************************************/
+/*                         ComposeMinOccurs()                           */
+/************************************************************************/
+
+static int ComposeMinOccurs(int nVal1, int nVal2)
+{
+    return nVal1 * nVal2;
+}
+
+/************************************************************************/
+/*                         ComposeMaxOccurs()                           */
+/************************************************************************/
+
+static int ComposeMaxOccurs(int nVal1, int nVal2)
+{
+    if( nVal1 == MAXOCCURS_UNLIMITED || nVal2 == MAXOCCURS_UNLIMITED )
+        return MAXOCCURS_UNLIMITED;
+    return nVal1 * nVal2;
+}
+
+/************************************************************************/
+/*                         ExploreModelGroup()                          */
+/************************************************************************/
+
+bool GMLASSchemaAnalyzer::ExploreModelGroup(
+                            XSModelGroup* poModelGroup,
+                            XSAttributeUseList* poMainAttrList,
+                            GMLASFeatureClass& oClass,
+                            int nRecursionCounter,
+                            std::set<XSModelGroup*>& oSetVisitedModelGroups,
+                            XSModel* poModel,
+                            const std::map< CPLString, int >& oMapCountOccurrencesOfSameName)
+{
+    if( oSetVisitedModelGroups.find(poModelGroup) !=
+                                                oSetVisitedModelGroups.end() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "%s already visited",
+                 oClass.GetXPath().c_str());
+        return false;
+    }
+    oSetVisitedModelGroups.insert(poModelGroup);
+
+    if( nRecursionCounter == 100 )
+    {
+        // Presumably an hostile schema
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Schema analysis failed due to too deeply nested model");
+        return false;
+    }
+
+    if( poMainAttrList != NULL )
+    {
+        const size_t nMainAttrListSize = poMainAttrList->size();
+        for(size_t j=0; j < nMainAttrListSize; ++j )
+        {
+            GMLASField oField;
+            XSAttributeUse* poAttr = poMainAttrList->elementAt(j);
+            SetFieldFromAttribute(oField, poAttr, oClass.GetXPath());
+
+            if( IsIgnoredXPath( oField.GetXPath() ) )
+            {
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GMLAS", "%s is in ignored xpaths",
+                        oField.GetXPath().c_str());
+#endif
+                if( !oField.GetFixedValue().empty() )
+                {
+                    oField.SetIgnored();
+                }
+                else
+                {
+                    continue;
+                }
+            }
+
+            oClass.AddField(oField);
+        }
+    }
+
+    XSParticleList* poParticles = poModelGroup->getParticles();
+
+    // Special case for GML 3.1.1 where gml:metaDataProperty should be
+    // a sequence of gml:_Metadata but for some reason they have used
+    // a sequence of any.
+    if( oClass.GetXPath() == "gml:metaDataProperty" &&
+        poModelGroup->getCompositor() ==
+                                XSModelGroup::COMPOSITOR_SEQUENCE &&
+        poParticles->size() == 1 &&
+        poParticles->elementAt(0)->
+                        getTermType() == XSParticle::TERM_WILDCARD )
+    {
+        XSElementDeclaration* poGMLMetadata =
+            GetTopElementDeclarationFromXPath("gml:_MetaData", poModel);
+        if( poGMLMetadata != NULL )
+        {
+            std::vector<XSElementDeclaration*> apoImplEltList;
+            GetConcreteImplementationTypes(poGMLMetadata, apoImplEltList);
+            CreateNonNestedRelationship(poGMLMetadata,
+                                        apoImplEltList,
+                                        oClass,
+                                        1,
+                                        false, // doesn't need prefix
+                                        true, // force junction table
+                                        false // regular case
+                                       );
+
+            return true;
+        }
+    }
+
+    const bool bIsChoice = (poModelGroup->getCompositor() ==
+                                            XSModelGroup::COMPOSITOR_CHOICE);
+    int nGroup = 0;
+
+    for(size_t i = 0; i < poParticles->size(); ++i )
+    {
+        XSParticle* poParticle = poParticles->elementAt(i);
+        const bool bRepeatedParticle = poParticle->getMaxOccursUnbounded() ||
+                                       poParticle->getMaxOccurs() > 1;
+        const int nMinOccurs = static_cast<int>(poParticle->getMinOccurs());
+        const int nMaxOccurs =
+                        poParticle->getMaxOccursUnbounded() ?
+                            MAXOCCURS_UNLIMITED :
+                            static_cast<int>(poParticle->getMaxOccurs());
+
+        if( poParticle->getTermType() == XSParticle::TERM_ELEMENT )
+        {
+            XSElementDeclaration* poElt = poParticle->getElementTerm();
+            const CPLString osEltName(transcode(poElt->getName()));
+
+            std::map< CPLString, int >::const_iterator oIter =
+                oMapCountOccurrencesOfSameName.find(osEltName);
+            const bool bEltNameWillNeedPrefix =
+                oIter != oMapCountOccurrencesOfSameName.end() &&
+                oIter->second > 1;
+            const CPLString osEltNS(transcode(poElt->getNamespace()));
+            const CPLString osPrefixedEltName(
+                (bEltNameWillNeedPrefix ? GetPrefix(osEltNS) + "_" : CPLString()) +
+                osEltName);
+            const CPLString osOnlyElementXPath(MakeXPath(osEltNS, osEltName));
+            const CPLString osElementXPath( oClass.GetXPath() + "/" +
+                                            osOnlyElementXPath );
+#ifdef DEBUG_VERBOSE
+            CPLDebug("GMLAS", "Iterating through %s", osElementXPath.c_str());
+#endif
+
+            if( IsIgnoredXPath( osElementXPath ) )
+            {
+#ifdef DEBUG_VERBOSE
+                CPLDebug("GMLAS", "%s is in ignored xpaths",
+                         osElementXPath.c_str());
+#endif
+                continue;
+            }
+
+            CPLString osTargetElement;
+            if( poElt->getAnnotation() != NULL )
+            {
+                CPLString osAnnot(transcode(
+                    poElt->getAnnotation()->getAnnotationString()));
+
+#ifdef DEBUG_SUPER_VERBOSE
+                CPLDebug("GMLAS", "Annot: %s", osAnnot.c_str());
+#endif
+                CPLXMLNode* psRoot = CPLParseXMLString(osAnnot);
+                CPLStripXMLNamespace(psRoot, NULL, TRUE);
+                osTargetElement =
+                    CPLGetXMLValue(psRoot, "=annotation.appinfo.targetElement", "");
+                CPLDestroyXMLNode(psRoot);
+#ifdef DEBUG_VERBOSE
+                if( !osTargetElement.empty() )
+                    CPLDebug("GMLAS", "targetElement: %s",
+                             osTargetElement.c_str());
+#endif
+            }
+
+            XSTypeDefinition* poTypeDef = poElt->getTypeDefinition();
+
+            std::vector<XSElementDeclaration*> apoImplEltList;
+            GetConcreteImplementationTypes(poElt, apoImplEltList);
+
+            std::vector<XSElementDeclaration*> apoChildrenElements =
+                GetConstraintChildrenElements(osElementXPath);
+
+            // Special case for a GML geometry property
+            OGRwkbGeometryType eGeomType = wkbNone;
+
+            if( !apoChildrenElements.empty() )
+            {
+                CreateNonNestedRelationship(poElt,
+                                            apoChildrenElements,
+                                            oClass,
+                                            nMaxOccurs,
+                                            bEltNameWillNeedPrefix,
+                                            false, // do not force junction table
+                                            true // special case for children elements
+                                           );
+            }
+
+            else if( IsGMLNamespace(transcode(poTypeDef->getNamespace())) &&
+                (eGeomType = GetOGRGeometryType(poTypeDef)) != wkbNone )
+            {
+                GMLASField oField;
+                oField.SetName( osPrefixedEltName );
+                oField.SetMinOccurs( nMinOccurs );
+                oField.SetMaxOccurs( nMaxOccurs );
+                oField.SetType( GMLAS_FT_GEOMETRY, szFAKEXS_GEOMETRY );
+                if( nMaxOccurs > 1 || nMaxOccurs == MAXOCCURS_UNLIMITED )
+                {
+                    // Repeated geometry property can happen in some schemas
+                    // like inspire.ec.europa.eu/schemas/ge_gp/4.0/GeophysicsCore.xsd
+                    // or http://ngwd-bdnes.cits.nrcan.gc.ca/service/gwml/schemas/2.1/gwml2-flow.xsd
+                    oField.SetGeomType( wkbUnknown );
+                    oField.SetArray( true );
+                }
+                else
+                    oField.SetGeomType( eGeomType );
+                oField.SetXPath( osElementXPath );
+                oField.SetDocumentation( GetAnnotationDoc( poElt ) );
+
+                oClass.AddField( oField );
+            }
+
+            else if( IsGMLNamespace(osEltNS) &&
+                     (eGeomType = GetOGRGeometryTypeFromGMLEltName(osEltName))
+                                                                    != wkbNone )
+            {
+                GMLASField oField;
+                oField.SetName( osPrefixedEltName );
+                oField.SetMinOccurs( nMinOccurs );
+                oField.SetMaxOccurs( nMaxOccurs );
+
+                oField.SetType( GMLAS_FT_GEOMETRY, szFAKEXS_GEOMETRY );
+                oField.SetGeomType( eGeomType );
+                oField.SetArray( nMaxOccurs > 1 ||
+                                    nMaxOccurs == MAXOCCURS_UNLIMITED );
+
+                oField.SetXPath( osElementXPath );
+                oField.SetIncludeThisEltInBlob( true );
+                oField.SetDocumentation( GetAnnotationDoc( poElt ) );
+
+                oClass.AddField( oField );
+            }
+
+            // Any GML abstract type
+            else if( poElt->getAbstract() &&
+                     IsGMLNamespace(osEltNS) &&
+                     osEltName != "_Feature" &&
+                     osEltName != "AbstractFeature" &&
+                     osEltName != "AbstractTimeObject" )
+            {
+                GMLASField oField;
+                oField.SetName( osPrefixedEltName );
+                oField.SetMinOccurs( nMinOccurs );
+                oField.SetMaxOccurs( nMaxOccurs );
+                if( osEltName == "AbstractGeometry" )
+                {
+                    oField.SetType( GMLAS_FT_GEOMETRY, szFAKEXS_GEOMETRY );
+                    oField.SetGeomType( wkbUnknown );
+                    oField.SetArray( nMaxOccurs > 1 ||
+                                     nMaxOccurs == MAXOCCURS_UNLIMITED );
+                }
+                else
+                {
+                    oField.SetType( GMLAS_FT_ANYTYPE, szXS_ANY_TYPE );
+                }
+                oField.SetIncludeThisEltInBlob( true );
+                oField.SetDocumentation( GetAnnotationDoc( poElt ) );
+
+                for( size_t j = 0; j < apoImplEltList.size(); j++ )
+                {
+                    XSElementDeclaration* poSubElt = apoImplEltList[j];
+                    oField.AddAlternateXPath( oClass.GetXPath() + "/" +
+                         MakeXPath(transcode(poSubElt->getNamespace()),
+                                   transcode(poSubElt->getName())) );
+                }
+
+                oClass.AddField( oField );
+            }
+
+            // Are there substitution groups for this element ?
+            // or is this element already identified as being a top-level one ?
+            else if( !apoImplEltList.empty() ||
+                     (m_oSetEltsForTopClass.find(poElt) !=
+                                                m_oSetEltsForTopClass.end() &&
+                      m_oSetSimpleEnoughElts.find(poElt) ==
+                                                m_oSetSimpleEnoughElts.end()) )
+            {
+                CreateNonNestedRelationship(poElt,
+                                            apoImplEltList,
+                                            oClass,
+                                            nMaxOccurs,
+                                            bEltNameWillNeedPrefix,
+                                            false, // do not force junction table
+                                            false // regular case
+                                           );
+            }
+
+            // Abstract element without realizations !
+            else if ( poElt->getAbstract() )
+            {
+                // Do nothing with it since it cannot be instantiated
+                // in a valid way.
+            }
+
+            // Simple type like string, int, etc...
+            else
+            if( poTypeDef->getTypeCategory() == XSTypeDefinition::SIMPLE_TYPE )
+            {
+                XSSimpleTypeDefinition* poST =
+                            reinterpret_cast<XSSimpleTypeDefinition*>(poTypeDef);
+                GMLASField oField;
+                SetFieldTypeAndWidthFromDefinition(poST, oField);
+                oField.SetMinOccurs( (bIsChoice) ? 0 : nMinOccurs );
+                oField.SetMaxOccurs( nMaxOccurs );
+                oField.SetDocumentation( GetAnnotationDoc( poElt ) );
+
+                bool bNeedAuxTable = false;
+                const bool bIsList =
+                    ( poST->getVariety() == XSSimpleTypeDefinition::VARIETY_LIST );
+                if( bIsList )
+                {
+                    SetFieldTypeAndWidthFromDefinition(poST->getItemType(),
+                                                       oField);
+                    if( bRepeatedParticle || !m_bUseArrays ||
+                        !IsCompatibleOfArray(oField.GetType()) )
+                    {
+                        // Really particular case. This is a workaround
+                        oField.SetType( GMLAS_FT_STRING, szXS_STRING );
+                    }
+                    else
+                    {
+                        oField.SetList( true );
+                        oField.SetArray( true );
+                    }
+                }
+
+                if( m_bUseArrays && bRepeatedParticle &&
+                    IsCompatibleOfArray(oField.GetType()) )
+                {
+                    oField.SetArray( true );
+                }
+                else if( bRepeatedParticle )
+                {
+                    bNeedAuxTable = true;
+                }
+                if( bNeedAuxTable )
+                {
+                    GMLASFeatureClass oNestedClass;
+                    oNestedClass.SetName( oClass.GetName() + "_" +
+                                          osPrefixedEltName );
+                    oNestedClass.SetXPath( osElementXPath );
+                    GMLASField oUniqueField;
+                    oUniqueField.SetName("value");
+                    oUniqueField.SetMinOccurs( 1 );
+                    oUniqueField.SetMaxOccurs( 1 );
+                    oUniqueField.SetXPath( osElementXPath );
+                    oUniqueField.SetType( oField.GetType(),
+                                          oField.GetTypeName() );
+                    oNestedClass.AddField(oUniqueField);
+                    oNestedClass.SetDocumentation( GetAnnotationDoc( poElt ) );
+
+                    oClass.AddNestedClass( oNestedClass );
+
+                    oField.SetType( GMLAS_FT_STRING, "" );
+                    oField.SetName( osPrefixedEltName );
+                    oField.SetXPath( osElementXPath );
+                    oField.SetCategory(
+                                    GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK);
+                    oField.SetRelatedClassXPath( oField.GetXPath() );
+                    oClass.AddField(oField);
+                }
+                else
+                {
+                    oField.SetName( osPrefixedEltName );
+                    oField.SetXPath( osElementXPath );
+                    if( !bIsChoice && nMinOccurs > 0 &&
+                        !poElt->getNillable() )
+                    {
+                        oField.SetNotNullable( true );
+                    }
+                    oClass.AddField(oField);
+
+                    // If the element has minOccurs=0 and is nillable, then we
+                    // need an extra field to be able to distinguish between the
+                    // case of the missing element or the element with
+                    // xsi:nil="true"
+                    if( nMinOccurs == 0 && poElt->getNillable() && !m_bUseNullState )
+                    {
+                        GMLASField oFieldNil;
+                        oFieldNil.SetName( osPrefixedEltName + "_" + szNIL );
+                        oFieldNil.SetXPath( osElementXPath + "/" +
+                                            szAT_XSI_NIL );
+                        oFieldNil.SetType( GMLAS_FT_BOOLEAN, "boolean" );
+                        oFieldNil.SetMinOccurs( 0 );
+                        oFieldNil.SetMaxOccurs( 1 );
+                        oClass.AddField(oFieldNil);
+                    }
+                }
+            }
+
+            // Complex type (element with attributes, composed element, etc...)
+            else if( poTypeDef->getTypeCategory() == XSTypeDefinition::COMPLEX_TYPE )
+            {
+                XSComplexTypeDefinition* poEltCT =
+                        reinterpret_cast<XSComplexTypeDefinition*>(poTypeDef);
+                std::vector< GMLASField > aoFields;
+                bool bNothingMoreToDo = false;
+                std::vector<GMLASFeatureClass> aoNestedClasses;
+
+                const int nMinOccursEltParticle = poEltCT->getParticle() ?
+                  static_cast<int>(poEltCT->getParticle()->getMinOccurs()) : -1;
+                const int nMaxOccursEltParticle = poEltCT->getParticle() ?
+                    (poEltCT->getParticle()->getMaxOccursUnbounded() ?
+                        MAXOCCURS_UNLIMITED :
+                        static_cast<int>(poEltCT->getParticle()->getMaxOccurs()))
+                    : -1;
+
+                const bool bEltRepeatedParticle = nMaxOccursEltParticle > 1 ||
+                                nMaxOccursEltParticle == MAXOCCURS_UNLIMITED;
+                const bool bMoveNestedClassToTop =
+                        !bRepeatedParticle && !bEltRepeatedParticle;
+
+                // Process attributes
+                XSAttributeUseList* poAttrList =
+                                        poEltCT->getAttributeUses();
+                const size_t nAttrListSize = (poAttrList != NULL) ?
+                                                    poAttrList->size(): 0;
+                for(size_t j=0; j< nAttrListSize; ++j )
+                {
+                    XSAttributeUse* poAttr = poAttrList->elementAt(j);
+                    GMLASField oField;
+                    CPLString osNamePrefix( bMoveNestedClassToTop ?
+                        osPrefixedEltName : CPLString() );
+                    SetFieldFromAttribute(oField, poAttr,
+                                          osElementXPath,
+                                          osNamePrefix);
+                    if( nMinOccurs == 0 || bIsChoice )
+                    {
+                        oField.SetMinOccurs(0);
+                        oField.SetNotNullable(false);
+                    }
+
+                    if( IsIgnoredXPath( oField.GetXPath() ) )
+                    {
+#ifdef DEBUG_VERBOSE
+                        CPLDebug("GMLAS", "%s is in ignored xpaths",
+                                 oField.GetXPath().c_str());
+#endif
+                        if( !oField.GetFixedValue().empty() )
+                        {
+                            oField.SetIgnored();
+                        }
+                        else
+                        {
+                            continue;
+                        }
+                    }
+
+                    aoFields.push_back(oField);
+                }
+
+                // Deal with anyAttributes (or any element that also imply it)
+                XSWildcard* poAttrWildcard = poEltCT->getAttributeWildcard();
+                if( poAttrWildcard != NULL )
+                {
+                    GMLASField oField;
+                    oField.SetType( GMLASField::GetTypeFromString(szXS_STRING),
+                                    szFAKEXS_JSON_DICT );
+                    if( !bMoveNestedClassToTop )
+                    {
+                        oField.SetName( "anyAttributes" );
+                    }
+                    else
+                    {
+                        oField.SetName( osPrefixedEltName + "_anyAttributes" );
+                    }
+                    oField.SetXPath(  osElementXPath + "/" + szAT_ANY_ATTR );
+                    oField.SetDocumentation( GetAnnotationDoc(
+                                            poAttrWildcard->getAnnotation() ) );
+
+                    aoFields.push_back(oField);
+                }
+
+                XSSimpleTypeDefinition* poST = poEltCT->getSimpleType();
+                if( poST != NULL )
+                {
+                    /* Case of an element, generally with attributes */
+
+                    GMLASField oField;
+                    SetFieldTypeAndWidthFromDefinition(poST, oField);
+                    if( bRepeatedParticle && nAttrListSize == 0 &&
+                        m_bUseArrays &&
+                        IsCompatibleOfArray(oField.GetType()) &&
+                        oField.GetCategory() !=
+                                GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK )
+                    {
+                        /* We have a complex type, but no attributes, and */
+                        /* compatible of arrays, so move it to top level! */
+                        oField.SetName( osPrefixedEltName );
+                        oField.SetArray( true );
+                        oField.SetMinOccurs( nMinOccurs );
+                        oField.SetMaxOccurs( nMaxOccurs );
+                    }
+                    else if( bRepeatedParticle )
+                    {
+                        oField.SetName( "value" );
+                        oField.SetMinOccurs( 1 );
+                        oField.SetMaxOccurs( 1 );
+                        oField.SetNotNullable( true );
+                    }
+                    else
+                    {
+                        if( nMinOccurs == 0 )
+                        {
+                            for(size_t j=0; j<aoFields.size();j++)
+                            {
+                                aoFields[j].SetMinOccurs( 0 );
+                                aoFields[j].SetNotNullable( false );
+                            }
+                        }
+
+                        oField.SetName( osPrefixedEltName );
+                        oField.SetMinOccurs( (bIsChoice) ? 0 : nMinOccurs );
+                        oField.SetMaxOccurs( nMaxOccurs );
+
+                        // If the element has minOccurs=0 and is nillable, then we
+                        // need an extra field to be able to distinguish between the
+                        // case of the missing element or the element with
+                        // xsi:nil="true"
+                        if( nMinOccurs == 0 && poElt->getNillable() && !m_bUseNullState )
+                        {
+                            GMLASField oFieldNil;
+                            oFieldNil.SetName( osPrefixedEltName + "_" + szNIL );
+                            oFieldNil.SetXPath( osElementXPath + "/" +
+                                                szAT_XSI_NIL );
+                            oFieldNil.SetType( GMLAS_FT_BOOLEAN, "boolean" );
+                            oFieldNil.SetMinOccurs( 0 );
+                            oFieldNil.SetMaxOccurs( 1 );
+                            aoFields.push_back(oFieldNil);
+                        }
+
+                    }
+                    oField.SetXPath( osElementXPath );
+                    oField.SetDocumentation( GetAnnotationDoc( poElt ) );
+
+                    aoFields.push_back(oField);
+                    if( oField.IsArray() )
+                    {
+                        oClass.AddField( oField );
+                        bNothingMoreToDo = true;
+                    }
+                }
+                else if( IsAnyType(poEltCT) )
+                {
+                    GMLASField oField;
+                    oField.SetType( GMLAS_FT_ANYTYPE, szXS_ANY_TYPE );
+                    if( bRepeatedParticle )
+                    {
+                        oField.SetName( "value" );
+                        oField.SetMinOccurs( 1 );
+                        oField.SetMaxOccurs( 1 );
+                        oField.SetNotNullable( true );
+                    }
+                    else
+                    {
+                        if( nMinOccurs == 0 )
+                        {
+                            for(size_t j=0; j<aoFields.size();j++)
+                            {
+                                aoFields[j].SetMinOccurs( 0 );
+                                aoFields[j].SetNotNullable( false );
+                            }
+                        }
+
+                        oField.SetName( osPrefixedEltName );
+                        oField.SetMinOccurs( nMinOccurs );
+                        oField.SetMaxOccurs( nMaxOccurs );
+                    }
+                    oField.SetXPath( osElementXPath );
+                    oField.SetDocumentation( GetAnnotationDoc( poElt ) );
+
+                    aoFields.push_back(oField);
+                }
+
+                // Is it an element that we already visited ? (cycle)
+                else if( poEltCT->getParticle() != NULL &&
+                         oSetVisitedModelGroups.find(
+                            poEltCT->getParticle()->getModelGroupTerm()) !=
+                                                oSetVisitedModelGroups.end() )
+                {
+                    CreateNonNestedRelationship(poElt,
+                                                apoImplEltList,
+                                                oClass,
+                                                bMoveNestedClassToTop ? 1 :
+                                                        MAXOCCURS_UNLIMITED,
+                                                bEltNameWillNeedPrefix,
+                                                true, // force junction table
+                                                false // regular case
+                                               );
+
+                    bNothingMoreToDo = true;
+                }
+
+                else
+                {
+                    GMLASFeatureClass oNestedClass;
+                    oNestedClass.SetName( oClass.GetName() + "_" +
+                                          osPrefixedEltName );
+                    oNestedClass.SetXPath( osElementXPath );
+                    oNestedClass.SetDocumentation( GetAnnotationDoc( poElt ) );
+
+                    // NULL can happen, for example for gml:ReferenceType
+                    // that is an empty sequence with just attributes
+                    if( poEltCT->getParticle() != NULL )
+                    {
+#ifdef DEBUG_VERBOSE
+                        CPLDebug("GMLAS", "Exploring %s",
+                                 osElementXPath.c_str());
+#endif
+                        std::set<XSModelGroup*>
+                            oSetNewVisitedModelGroups(oSetVisitedModelGroups);
+
+                        std::map< CPLString, int > oMapCountOccurrencesOfSameNameSub;
+                        BuildMapCountOccurrencesOfSameName(
+                            poEltCT->getParticle()->getModelGroupTerm(),
+                            oMapCountOccurrencesOfSameNameSub);
+
+                        if( !ExploreModelGroup(
+                                           poEltCT->getParticle()->
+                                                            getModelGroupTerm(),
+                                           NULL,
+                                           oNestedClass,
+                                           nRecursionCounter + 1,
+                                           oSetNewVisitedModelGroups,
+                                           poModel,
+                                           oMapCountOccurrencesOfSameNameSub) )
+                        {
+                            return false;
+                        }
+                    }
+
+                    // If we have a element of type gml:ReferenceType that has
+                    // a targetElement in its annotation.appinfo, then create
+                    // a dedicated field to have cross-layer relationships.
+                    if( IsGMLNamespace(transcode(poTypeDef->getNamespace())) &&
+                        transcode(poTypeDef->getName()) == "ReferenceType" &&
+                        !osTargetElement.empty() )
+                    {
+                        XSElementDeclaration* poTargetElt =
+                            GetTopElementDeclarationFromXPath(osTargetElement,
+                                                              poModel);
+                        // TODO: even for non abstract we should probably
+                        // handle substitutions
+                        if( poTargetElt != NULL && !poTargetElt->getAbstract() )
+                        {
+                            // If the element is nillable, then we
+                            // need an extra field to be able to distinguish between the
+                            // case of the missing element or the element with
+                            // xsi:nil="true"
+                            if( poElt->getNillable() && !m_bUseNullState )
+                            {
+                                GMLASField oFieldNil;
+                                oFieldNil.SetName( osPrefixedEltName + "_" + szNIL );
+                                oFieldNil.SetXPath( osElementXPath + "/" +
+                                                    szAT_XSI_NIL );
+                                oFieldNil.SetType( GMLAS_FT_BOOLEAN, "boolean" );
+                                oFieldNil.SetMinOccurs( 0 );
+                                oFieldNil.SetMaxOccurs( 1 );
+                                aoFields.push_back(oFieldNil);
+                            }
+
+                            GMLASField oField;
+                            // Fake xpath
+                            oField.SetXPath(
+                                GMLASField::MakePKIDFieldXPathFromXLinkHrefXPath(
+                                            osElementXPath + "/" + szAT_XLINK_HREF));
+                            oField.SetName( osPrefixedEltName + szPKID_SUFFIX );
+                            oField.SetMinOccurs(0);
+                            oField.SetMaxOccurs(1);
+                            oField.SetType( GMLAS_FT_STRING, szXS_STRING );
+                            oField.SetCategory(
+                                GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK );
+                            oField.SetRelatedClassXPath(osTargetElement);
+                            aoFields.push_back( oField );
+                        }
+                        else if( poTargetElt != NULL && poTargetElt->getAbstract() )
+                        {
+                            // If the element is nillable, then we
+                            // need an extra field to be able to distinguish between the
+                            // case of the missing element or the element with
+                            // xsi:nil="true"
+                            if( poElt->getNillable() && !m_bUseNullState )
+                            {
+                                GMLASField oFieldNil;
+                                oFieldNil.SetName( osPrefixedEltName + "_" + szNIL );
+                                oFieldNil.SetXPath( osElementXPath + "/" +
+                                                    szAT_XSI_NIL );
+                                oFieldNil.SetType( GMLAS_FT_BOOLEAN, "boolean" );
+                                oFieldNil.SetMinOccurs( 0 );
+                                oFieldNil.SetMaxOccurs( 1 );
+                                aoFields.push_back(oFieldNil);
+                            }
+
+                            // e.g importing http://inspire.ec.europa.eu/schemas/ad/4.0
+                            // references bu-base:AbstractConstruction, but sometimes
+                            // there are no realization available for it, so no
+                            // need to be verbose about that.
+                            std::vector<XSElementDeclaration*>
+                                                        apoImplTargetEltList;
+                            GetConcreteImplementationTypes(poTargetElt,
+                                                        apoImplTargetEltList);
+                            if( !apoImplTargetEltList.empty() )
+                            {
+                                CPLDebug("GMLAS",
+                                         "Not handled: targetElement %s of %s "
+                                         "is abstract but has substitutions",
+                                         osTargetElement.c_str(),
+                                         osElementXPath.c_str());
+                            }
+                        }
+                        else
+                        {
+                            // This shouldn't happen with consistent schemas
+                            // but as targetElement is in <annotation>, no
+                            // general-purpose XSD validator can ensure this
+                            CPLDebug("GMLAS", "%s is a targetElement of %s, "
+                                     "but cannot be found",
+                                     osTargetElement.c_str(),
+                                     osElementXPath.c_str());
+                        }
+                    }
+
+                    // Can we move the nested class(es) one level up ?
+                    if( bMoveNestedClassToTop )
+                    {
+                        // Case of an element like
+                        //   <xs:element name="foo">
+                        //      <xs:complexType>
+                        //          <xs:sequence>
+
+                        const std::vector<GMLASField>& osNestedClassFields =
+                                                    oNestedClass.GetFields();
+                        for(size_t j = 0; j < osNestedClassFields.size(); j++ )
+                        {
+                            GMLASField oField(osNestedClassFields[j]);
+                            oField.SetName( 
+                                osPrefixedEltName + "_" + oField.GetName() );
+                            if( nMinOccurs == 0 ||
+                                (poEltCT->getParticle() != NULL &&
+                                 poEltCT->getParticle()->getMinOccurs() == 0) )
+                            {
+                                oField.SetMinOccurs(0);
+                                oField.SetNotNullable(false);
+                            }
+                            aoFields.push_back( oField );
+                        }
+
+                        aoNestedClasses = oNestedClass.GetNestedClasses();
+                    }
+                    else
+                    {
+                        // Case of an element like
+                        //   <xs:element name="foo">
+                        //      <xs:complexType>
+                        //          <xs:sequence maxOccurs="unbounded">
+                        // or
+                        //   <xs:element name="foo" maxOccurs="unbounded">
+                        //      <xs:complexType>
+                        //          <xs:sequence>
+                        // or even
+                        //   <xs:element name="foo" maxOccurs="unbounded">
+                        //      <xs:complexType>
+                        //          <xs:sequence maxOccurs="unbounded">
+                        if( m_bUseArrays && nAttrListSize == 0 &&
+                            oNestedClass.GetNestedClasses().empty() &&
+                            oNestedClass.GetFields().size() == 1 &&
+                            IsCompatibleOfArray(
+                                    oNestedClass.GetFields()[0].GetType()) &&
+                            oNestedClass.GetFields()[0].GetCategory() !=
+                                GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK )
+                        {
+                            // In the case the sequence has a single element,
+                            // compatible of array type, and no attribute and
+                            // no nested classes, then add an array attribute
+                            // at the top-level
+                            GMLASField oField (oNestedClass.GetFields()[0] );
+                            oField.SetName( osPrefixedEltName + "_" +
+                                            oField.GetName() );
+                            if( oField.GetMaxOccurs() == 1 &&
+                                bEltRepeatedParticle &&
+                                poEltCT->getParticle() != NULL )
+                            {
+                                oField.SetMaxOccurs( nMaxOccursEltParticle );
+                            }
+                            oField.SetArray( true );
+                            oClass.AddField( oField );
+                        }
+                        else
+                        {
+                            if( !aoFields.empty() && bEltRepeatedParticle)
+                            {
+                                // We have attributes and the sequence is
+                                // repeated
+                                //   <xs:element name="foo" maxOccurs="unbounded">
+                                //      <xs:complexType>
+                                //          <xs:sequence maxOccurs="unbounded">
+                                //              ...
+                                //          </xs:sequence>
+                                //          <xs:attribute .../>
+                                //      </xs:complexType>
+                                //   </xs:element>
+                                // So we need to create an
+                                // intermediate class to store them
+                                GMLASFeatureClass oIntermediateNestedClass;
+                                oIntermediateNestedClass.SetName(
+                                        oClass.GetName() + "_" +
+                                        osPrefixedEltName );
+                                oIntermediateNestedClass.SetXPath( osElementXPath );
+
+                                oIntermediateNestedClass.PrependFields( aoFields );
+
+                                oNestedClass.SetName( oClass.GetName() + "_" +
+                                        osPrefixedEltName + "_sequence" );
+                                oNestedClass.SetXPath( oNestedClass.GetXPath() +
+                                        szEXTRA_SUFFIX + "sequence");
+                                oNestedClass.SetIsRepeatedSequence( true );
+
+                                GMLASField oField;
+                                oField.SetXPath( osElementXPath );
+                                oField.SetCategory(
+                                    GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK);
+                                if( nMaxOccursEltParticle != 1 )
+                                    oField.SetRepetitionOnSequence( true );
+                                oField.SetMinOccurs( nMinOccursEltParticle );
+                                oField.SetMaxOccurs( nMaxOccursEltParticle );
+                                oField.SetRelatedClassXPath( oNestedClass.GetXPath() );
+                                oIntermediateNestedClass.AddField(oField);
+
+                                oIntermediateNestedClass.AddNestedClass( oNestedClass );
+
+                                oClass.AddNestedClass( oIntermediateNestedClass );
+                            }
+                            else
+                            {
+                                oNestedClass.SetIsRepeatedSequence(
+                                                        bEltRepeatedParticle );
+                                oNestedClass.PrependFields( aoFields );
+
+                                oClass.AddNestedClass( oNestedClass );
+                            }
+
+                            GMLASField oField;
+                            oField.SetName( osPrefixedEltName );
+                            oField.SetXPath( osElementXPath );
+                            if( bRepeatedParticle )
+                            {
+                                if( poEltCT->getParticle() != NULL )
+                                {
+                                    oField.SetMinOccurs( ComposeMinOccurs(
+                                        nMinOccurs, nMinOccursEltParticle) );
+                                    oField.SetMaxOccurs( ComposeMaxOccurs(
+                                        nMaxOccurs, nMaxOccursEltParticle) );
+                                }
+                                else
+                                {
+                                    oField.SetMinOccurs( nMinOccurs );
+                                    oField.SetMaxOccurs( nMaxOccurs );
+                                }
+                            }
+                            else if( poEltCT->getParticle() != NULL )
+                            {
+                                if( nMaxOccursEltParticle != 1 )
+                                    oField.SetRepetitionOnSequence( true );
+                                oField.SetMinOccurs( nMinOccursEltParticle );
+                                oField.SetMaxOccurs( nMaxOccursEltParticle );
+                            }
+                            oField.SetCategory(
+                                    GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK);
+                            oField.SetRelatedClassXPath( oField.GetXPath() );
+                            oClass.AddField(oField);
+                        }
+
+                        bNothingMoreToDo = true;
+                    }
+                }
+
+                if( bNothingMoreToDo )
+                {
+                    // Nothing to do
+                }
+                else if( bRepeatedParticle )
+                {
+                    GMLASFeatureClass oNestedClass;
+                    oNestedClass.SetName( oClass.GetName() + "_" +
+                                          osPrefixedEltName );
+                    oNestedClass.SetXPath( osElementXPath );
+                    oNestedClass.AppendFields( aoFields );
+                    oNestedClass.SetDocumentation( GetAnnotationDoc( poElt ) );
+                    oClass.AddNestedClass( oNestedClass );
+
+                    GMLASField oField;
+                    oField.SetName( osPrefixedEltName );
+                    oField.SetXPath( osElementXPath );
+                    oField.SetMinOccurs( (bIsChoice) ? 0 : nMinOccurs );
+                    oField.SetMaxOccurs( nMaxOccurs );
+                    oField.SetCategory(
+                                    GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK);
+                    oField.SetRelatedClassXPath( oField.GetXPath() );
+                    oClass.AddField(oField);
+                }
+                else
+                {
+                    oClass.AppendFields( aoFields );
+                    for(size_t j = 0; j < aoNestedClasses.size(); j++ )
+                    {
+                        oClass.AddNestedClass( aoNestedClasses[j] );
+                    }
+                }
+            }
+        }
+        else if( poParticle->getTermType() == XSParticle::TERM_MODELGROUP )
+        {
+            XSModelGroup* psSubModelGroup = poParticle->getModelGroupTerm();
+            if( bRepeatedParticle )
+            {
+                GMLASFeatureClass oNestedClass;
+                CPLString osGroupName;
+                XSModelGroupDefinition* psGroupDefinition =
+                                            GetGroupDefinition(psSubModelGroup);
+                if( psGroupDefinition != NULL )
+                {
+                    osGroupName = transcode( psGroupDefinition->getName() );
+                    oNestedClass.SetDocumentation(
+                        GetAnnotationDoc( psGroupDefinition->getAnnotation() ) );
+                }
+                else
+                {
+                    // Is it a <xs:choice maxOccurs=">1|unbounded"
+                    if (psSubModelGroup->getCompositor() ==
+                                            XSModelGroup::COMPOSITOR_CHOICE)
+                    {
+                        std::set<XSModelGroup*>
+                            oSetNewVisitedModelGroups(oSetVisitedModelGroups);
+                        GMLASFeatureClass oTmpClass;
+                        oTmpClass.SetName( oClass.GetName() );
+                        oTmpClass.SetXPath( oClass.GetXPath() );
+                        if( !ExploreModelGroup( psSubModelGroup,
+                                                NULL,
+                                                oTmpClass,
+                                                nRecursionCounter + 1,
+                                                oSetNewVisitedModelGroups,
+                                                poModel,
+                                                oMapCountOccurrencesOfSameName ) )
+                        {
+                            return false;
+                        }
+                        bool bHasArray = false;
+                        std::vector<GMLASField>& oTmpFields =
+                                                        oTmpClass.GetFields();
+                        for( size_t j = 0; j < oTmpFields.size(); ++j )
+                        {
+                            if( oTmpFields[j].IsArray() )
+                            {
+                                bHasArray = true;
+                                break;
+                            }
+                        }
+                        if( !bHasArray )
+                        {
+                            for( size_t j = 0; j < oTmpFields.size(); ++j )
+                            {
+                                oTmpFields[j].SetMayAppearOutOfOrder( true );
+                                oClass.AddField( oTmpFields[j] );
+                            }
+                            return true;
+                        }
+                    }
+
+                    nGroup ++;
+                    osGroupName = CPLSPrintf("_group%d", nGroup);
+                }
+                oNestedClass.SetName( oClass.GetName() + "_" + osGroupName);
+                oNestedClass.SetIsGroup(true);
+                oNestedClass.SetIsRepeatedSequence(true);
+                // Caution: we will change it afterwards !
+                oNestedClass.SetXPath( oClass.GetXPath() );
+                std::set<XSModelGroup*>
+                    oSetNewVisitedModelGroups(oSetVisitedModelGroups);
+                if( !ExploreModelGroup( psSubModelGroup,
+                                        NULL,
+                                        oNestedClass,
+                                        nRecursionCounter + 1,
+                                        oSetNewVisitedModelGroups,
+                                        poModel,
+                                        oMapCountOccurrencesOfSameName) )
+                {
+                    return false;
+                }
+                // This is a nasty hack. We set a unique fake xpath *AFTER*
+                // processing the group, so that we can add a fake GROUP field
+                // pointing to the nested class
+                oNestedClass.SetXPath( oClass.GetXPath() + szEXTRA_SUFFIX + osGroupName );
+
+                if( m_bUseArrays &&
+                    oNestedClass.GetFields().size() == 1 &&
+                    IsCompatibleOfArray(oNestedClass.GetFields()[0].GetType()) )
+                {
+                    GMLASField oField(oNestedClass.GetFields()[0]);
+                    oField.SetMinOccurs( ComposeMinOccurs(oField.GetMinOccurs(), nMinOccurs) );
+                    oField.SetMaxOccurs( ComposeMaxOccurs(oField.GetMaxOccurs(), nMaxOccurs) );
+                    oField.SetArray( true );
+                    oClass.AddField( oField );
+                }
+                else
+                {
+                    oClass.AddNestedClass( oNestedClass );
+
+                    GMLASField oField;
+                    oField.SetCategory( GMLASField::GROUP );
+                    oField.SetMinOccurs( nMinOccurs );
+                    oField.SetMaxOccurs( nMaxOccurs );
+                    oField.SetRelatedClassXPath( oNestedClass.GetXPath() );
+                    oClass.AddField(oField);
+                }
+            }
+            else
+            {
+                std::set<XSModelGroup*>
+                    oSetNewVisitedModelGroups(oSetVisitedModelGroups);
+                if( !ExploreModelGroup( psSubModelGroup,
+                                        NULL,
+                                        oClass,
+                                        nRecursionCounter + 1,
+                                        oSetNewVisitedModelGroups,
+                                        poModel,
+                                        oMapCountOccurrencesOfSameName ) )
+                {
+                    return false;
+                }
+            }
+        }
+        else if( poParticle->getTermType() == XSParticle::TERM_WILDCARD )
+        {
+            /* Special case for a layer that matches everything, as found */
+            /* in swe:extension */
+            XSWildcard* poWildcard = poParticle->getWildcardTerm();
+            GMLASField oField;
+            oField.SetXPath( oClass.GetXPath() + szMATCH_ALL );
+            oField.SetName( "value" );
+            oField.SetType( GMLAS_FT_ANYTYPE, szXS_ANY_TYPE );
+            oField.SetIncludeThisEltInBlob( true );
+            oField.SetMinOccurs( nMinOccurs );
+            oField.SetMaxOccurs( 1 );
+            oField.SetDocumentation(
+                        GetAnnotationDoc( poWildcard->getAnnotation() ) );
+            oClass.AddField(oField);
+        }
+    }
+
+    return true;
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlaswriter.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlaswriter.cpp
new file mode 100644
index 0000000..a55d45a
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlaswriter.cpp
@@ -0,0 +1,3161 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+#include "ogr_p.h"
+#include "ogrgeojsonreader.h"
+#include "cpl_time.h"
+
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrgmlaswriter.cpp 37470 2017-02-26 02:23:50Z goatbar $");
+
+namespace GMLAS
+{
+
+/************************************************************************/
+/*                          GMLASWriter                                 */
+/************************************************************************/
+
+typedef std::pair<CPLString, CPLString> PairNSElement;
+
+typedef std::vector<PairNSElement> XPathComponents;
+
+typedef std::pair<CPLString, CPLString> PairLayerNameColName;
+
+class LayerDescription
+{
+    public:
+        CPLString osName;
+        CPLString osXPath;
+        CPLString osPKIDName;
+        CPLString osParentPKIDName;
+        bool      bIsSelected;
+        bool      bIsTopLevel;
+        bool      bIsJunction;
+        // map a field sequential number to a field
+        std::map< int, GMLASField > oMapIdxToField;
+        // map a field xpath to its sequential number
+        std::map< CPLString, int > oMapFieldXPathToIdx;
+        std::map< CPLString, int > oMapFieldNameToOGRIdx;
+        std::vector<PairLayerNameColName> aoReferencingLayers;
+
+        // NOTE: this doesn't scale to arbitrarily large datasets
+        std::set<GIntBig> aoSetReferencedFIDs;
+
+        LayerDescription(): bIsSelected(false),
+                            bIsTopLevel(false),
+                            bIsJunction(false) {}
+
+        int GetOGRIdxFromFieldName( const CPLString& osFieldName ) const
+        {
+            std::map< CPLString, int >::const_iterator oIter =
+                                        oMapFieldNameToOGRIdx.find(osFieldName);
+            if( oIter == oMapFieldNameToOGRIdx.end() )
+                return -1;
+            return oIter->second;
+        }
+};
+
+class GMLASWriter
+{
+        GMLASConfiguration m_oConf;
+        CPLString       m_osFilename;
+        CPLString       m_osGMLVersion;
+        CPLString       m_osSRSNameFormat;
+        CPLString       m_osEOL;
+        GDALDataset*    m_poSrcDS;
+        char**          m_papszOptions;
+        VSILFILE*       m_fpXML;
+        OGRGMLASDataSource *m_poTmpDS;
+        OGRLayer           *m_poLayersMDLayer;
+        OGRLayer           *m_poFieldsMDLayer;
+        OGRLayer           *m_poLayerRelationshipsLayer;
+        std::vector<LayerDescription> m_aoLayerDesc;
+        std::map<CPLString, int> m_oMapLayerNameToIdx;
+        std::map<CPLString, int> m_oMapXPathToIdx;
+        std::map<CPLString, OGRLayer*> m_oMapLayerNameToLayer;
+        std::map<CPLString, XPathComponents> m_oMapXPathToComponents;
+        std::map<const OGRSpatialReference*, bool> m_oMapSRSToCoordSwap;
+
+        CPLString           m_osTargetNameSpace;
+        CPLString           m_osTargetNameSpacePrefix;
+
+        CPLString           m_osIndentation;
+        int                 m_nIndentLevel;
+
+        void                IncIndent() { ++m_nIndentLevel; }
+        void                DecIndent() { --m_nIndentLevel; }
+        void                PrintIndent(VSILFILE* fp);
+
+        void                PrintLine(VSILFILE* fp, const char *fmt, ...)
+                                                CPL_PRINT_FUNC_FORMAT (3, 4);
+
+        bool                WriteXSD(
+                                const CPLString& osXSDFilenameIn,
+                                const std::vector<PairURIFilename>& aoXSDs );
+        bool                WriteXMLHeader(
+                    bool bWFS2FeatureCollection,
+                    GIntBig nTotalFeatures,
+                    bool bGenerateXSD,
+                    const CPLString& osXSDFilenameIn,
+                    const std::vector<PairURIFilename>& aoXSDs,
+                    const std::map<CPLString, CPLString>& oMapURIToPrefix );
+        bool                CollectLayers();
+        bool                CollectFields();
+        bool                CollectRelationships();
+        void                ComputeTopLevelFIDs();
+        bool                WriteLayer( bool bWFS2FeatureCollection,
+                                        const LayerDescription& oDesc,
+                                        GIntBig& nFeaturesWritten,
+                                        GIntBig nTotalTopLevelFeatures,
+                                        GDALProgressFunc pfnProgress,
+                                        void* pProgressData );
+
+        bool                WriteFeature(
+                        OGRFeature* poFeature,
+                        const LayerDescription& oLayerDesc,
+                        const std::set<CPLString>& oSetLayersInIteration,
+                        const XPathComponents& aoInitialComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        int nRecLevel);
+
+        void                WriteClosingTags(
+                                    size_t nCommonLength,
+                                    const XPathComponents& aoCurComponents,
+                                    const XPathComponents& aoNewComponents,
+                                    bool bCurIsRegularField,
+                                    bool bNewIsRegularField );
+
+        void                WriteClosingAndStartingTags(
+                        const XPathComponents& aoCurComponents,
+                        const XPathComponents& aoNewComponents,
+                        bool bCurIsRegularField );
+
+        void     PrintMultipleValuesSeparator(
+                                const GMLASField& oField,
+                                const XPathComponents& aoFieldComponents);
+
+        OGRLayer* GetFilteredLayer(OGRLayer* poSrcLayer,
+                            const CPLString& osFilter,
+                            const std::set<CPLString>& oSetLayersInIteration);
+        void      ReleaseFilteredLayer(OGRLayer* poSrcLayer,
+                                       OGRLayer* poIterLayer);
+
+        bool     WriteFieldRegular(
+                        OGRFeature* poFeature,
+                        const GMLASField& oField,
+                        const LayerDescription& oLayerDesc,
+                        /*XPathComponents& aoLayerComponents,*/
+                        XPathComponents& aoCurComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        /*const std::set<CPLString>& oSetLayersInIteration,*/
+                        bool& bAtLeastOneFieldWritten,
+                        bool& bCurIsRegularField);
+
+        bool     WriteFieldNoLink(
+                        OGRFeature* poFeature,
+                        const GMLASField& oField,
+                        const LayerDescription& oLayerDesc,
+                        XPathComponents& aoLayerComponents,
+                        XPathComponents& aoCurComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        const std::set<CPLString>& oSetLayersInIteration,
+                        int nRecLevel,
+                        bool& bAtLeastOneFieldWritten,
+                        bool& bCurIsRegularField);
+
+        bool     WriteFieldWithLink(
+                        OGRFeature* poFeature,
+                        const GMLASField& oField,
+                        const LayerDescription& oLayerDesc,
+                        XPathComponents& aoLayerComponents,
+                        XPathComponents& aoCurComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        const std::set<CPLString>& oSetLayersInIteration,
+                        int nRecLevel,
+                        bool& bAtLeastOneFieldWritten,
+                        bool& bCurIsRegularField);
+
+        bool     WriteFieldJunctionTable(
+                        OGRFeature* poFeature,
+                        const GMLASField& oField,
+                        const LayerDescription& oLayerDesc,
+                        XPathComponents& aoLayerComponents,
+                        XPathComponents& aoCurComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        const std::set<CPLString>& oSetLayersInIteration,
+                        int nRecLevel,
+                        bool& bAtLeastOneFieldWritten,
+                        bool& bCurIsRegularField);
+
+        void Close();
+
+        OGRLayer*              GetLayerByName(const CPLString& osName);
+
+        const XPathComponents& SplitXPath( const CPLString& osXPath );
+
+        bool                   GetCoordSwap( const OGRSpatialReference* poSRS );
+
+    public:
+        GMLASWriter(const char * pszFilename,
+                    GDALDataset *poSrcDS,
+                    char** papszOptions);
+        ~GMLASWriter();
+
+        bool Write(GDALProgressFunc pfnProgress,
+                   void * pProgressData);
+};
+
+/************************************************************************/
+/*                            GMLASWriter()                             */
+/************************************************************************/
+
+GMLASWriter::GMLASWriter(const char * pszFilename,
+                         GDALDataset *poSrcDS,
+                         char** papszOptions)
+    : m_osFilename(pszFilename)
+#ifdef WIN32
+    , m_osEOL("\r\n")
+#else
+    , m_osEOL("\n")
+#endif
+    , m_poSrcDS(poSrcDS)
+    , m_papszOptions(CSLDuplicate(papszOptions))
+    , m_fpXML(NULL)
+    , m_poTmpDS(NULL)
+    , m_poLayersMDLayer(NULL)
+    , m_poFieldsMDLayer(NULL)
+    , m_poLayerRelationshipsLayer(NULL)
+    , m_osTargetNameSpace(szOGRGMLAS_URI)
+    , m_osTargetNameSpacePrefix(szOGRGMLAS_PREFIX)
+    , m_osIndentation(std::string(INDENT_SIZE_DEFAULT, ' '))
+    , m_nIndentLevel(0)
+{
+
+}
+
+/************************************************************************/
+/*                           ~GMLASWriter()                             */
+/************************************************************************/
+
+GMLASWriter::~GMLASWriter()
+{
+    CSLDestroy(m_papszOptions);
+    Close();
+}
+
+/************************************************************************/
+/*                               Close()                                */
+/************************************************************************/
+
+void GMLASWriter::Close()
+{
+    if( m_fpXML != NULL )
+        VSIFCloseL( m_fpXML );
+    m_fpXML = NULL;
+    delete m_poTmpDS;
+    m_poTmpDS = NULL;
+}
+
+/************************************************************************/
+/*                              Write()                                 */
+/************************************************************************/
+
+bool GMLASWriter::Write(GDALProgressFunc pfnProgress,
+                        void * pProgressData)
+{
+    if( m_poSrcDS->GetLayerCount() == 0 &&
+        m_poSrcDS->GetLayerByName(szOGR_OTHER_METADATA) == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Source dataset has no layers");
+        return false;
+    }
+
+    // Load configuration file
+    CPLString osConfigFile = CSLFetchNameValueDef(m_papszOptions,
+                                                  szCONFIG_FILE_OPTION, "");
+    if( osConfigFile.empty() )
+    {
+        const char* pszConfigFile = CPLFindFile("gdal",
+                                                szDEFAULT_CONF_FILENAME);
+        if( pszConfigFile )
+            osConfigFile = pszConfigFile;
+    }
+    if( osConfigFile.empty() )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "No configuration file found. Using hard-coded defaults");
+        m_oConf.Finalize();
+    }
+    else
+    {
+        if( !m_oConf.Load(osConfigFile) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Loading of configuration failed");
+            return false;
+        }
+    }
+
+    CPLString osXSDFilenames = CSLFetchNameValueDef(m_papszOptions,
+                                                    szINPUT_XSD_OPTION, "");
+    std::vector<PairURIFilename> aoXSDs;
+    std::map<CPLString, CPLString> oMapURIToPrefix;
+    CPLString osGMLVersion;
+
+    if( !osXSDFilenames.empty() )
+    {
+        // Create a fake GMLAS dataset from the XSD= value
+        m_poTmpDS = new OGRGMLASDataSource();
+        GDALOpenInfo oOpenInfo(szGMLAS_PREFIX, GA_ReadOnly );
+        oOpenInfo.papszOpenOptions = CSLSetNameValue(oOpenInfo.papszOpenOptions,
+                                                     szXSD_OPTION,
+                                                     osXSDFilenames);
+        bool bRet = m_poTmpDS->Open(&oOpenInfo);
+        CSLDestroy(oOpenInfo.papszOpenOptions);
+        oOpenInfo.papszOpenOptions = NULL;
+        if( !bRet )
+        {
+            return false;
+        }
+    }
+
+    GDALDataset* poQueryDS = m_poTmpDS ? m_poTmpDS : m_poSrcDS;
+
+    // No explicit XSD creation option, then we assume that the source
+    // dataset contains all the metadata layers we need
+    OGRLayer* poOtherMetadataLayer =
+                        poQueryDS->GetLayerByName(szOGR_OTHER_METADATA);
+    if( poOtherMetadataLayer == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot establish schema since no %s creation option "
+                    "specified and no %s found in source "
+                    "dataset. One of them must be defined.",
+                    szINPUT_XSD_OPTION,
+                    szOGR_OTHER_METADATA);
+        return false;
+    }
+
+    m_poLayersMDLayer =
+        poQueryDS->GetLayerByName(szOGR_LAYERS_METADATA);
+    m_poFieldsMDLayer =
+        poQueryDS->GetLayerByName(szOGR_FIELDS_METADATA);
+    m_poLayerRelationshipsLayer =
+        poQueryDS->GetLayerByName(szOGR_LAYER_RELATIONSHIPS);
+    if( m_poLayersMDLayer == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s not found",
+                 szOGR_LAYERS_METADATA);
+        return false;
+    }
+    if( m_poFieldsMDLayer == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s not found",
+                 szOGR_FIELDS_METADATA);
+        return false;
+    }
+    if( m_poLayerRelationshipsLayer == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "%s not found",
+                 szOGR_LAYER_RELATIONSHIPS);
+        return false;
+    }
+
+    std::map<int, CPLString> oMapToUri;
+    std::map<int, CPLString> oMapToLocation;
+    std::map<int, CPLString> oMapToPrefix;
+    while( true )
+    {
+        OGRFeature* poFeature = poOtherMetadataLayer->GetNextFeature();
+        if( poFeature == NULL )
+            break;
+        const char* pszKey = poFeature->GetFieldAsString(szKEY);
+        int i = 0;
+        if( sscanf( pszKey, szNAMESPACE_URI_FMT, &i ) == 1 && i > 0 )
+        {
+            oMapToUri[i] = poFeature->GetFieldAsString(szVALUE);
+        }
+        else if( sscanf( pszKey, szNAMESPACE_LOCATION_FMT, &i ) == 1 &&
+                    i > 0 )
+        {
+            oMapToLocation[i] = poFeature->GetFieldAsString(szVALUE);
+        }
+        else if( sscanf( pszKey, szNAMESPACE_PREFIX_FMT, &i ) == 1 &&
+                    i > 0 )
+        {
+            oMapToPrefix[i] = poFeature->GetFieldAsString(szVALUE);
+        }
+        else if( EQUAL(pszKey, szGML_VERSION) )
+        {
+            osGMLVersion = poFeature->GetFieldAsString(szVALUE);
+        }
+        delete poFeature;
+    }
+    poOtherMetadataLayer->ResetReading();
+
+    for( int i = 1; i <= static_cast<int>(oMapToUri.size()); ++i )
+    {
+        if( oMapToUri.find(i) != oMapToUri.end() )
+        {
+            const CPLString& osURI( oMapToUri[i] );
+            aoXSDs.push_back( PairURIFilename( osURI,
+                                                oMapToLocation[i] ) );
+            if( oMapToPrefix.find(i) != oMapToPrefix.end() )
+            {
+                oMapURIToPrefix[ osURI ] = oMapToPrefix[i];
+            }
+        }
+    }
+
+    if( !CollectLayers() )
+        return false;
+
+    if( !CollectFields() )
+        return false;
+
+    if( !CollectRelationships() )
+        return false;
+
+    const char* pszLayers = CSLFetchNameValue(m_papszOptions, szLAYERS_OPTION);
+    if( pszLayers )
+    {
+        std::map<CPLString, int>::iterator oLayerIter =
+                                                m_oMapLayerNameToIdx.begin();
+        for(; oLayerIter != m_oMapLayerNameToIdx.end(); ++oLayerIter)
+        {
+            LayerDescription& oDesc = m_aoLayerDesc[oLayerIter->second];
+            oDesc.bIsSelected = false;
+        }
+
+        char** papszLayers = CSLTokenizeString2(pszLayers, ",", 0);
+        for( char** papszIter = papszLayers; *papszIter != NULL; ++papszIter )
+        {
+            if( EQUAL(*papszIter, "{SPATIAL_LAYERS}") )
+            {
+                oLayerIter = m_oMapLayerNameToIdx.begin();
+                for(; oLayerIter != m_oMapLayerNameToIdx.end(); ++oLayerIter)
+                {
+                    LayerDescription& oDesc = m_aoLayerDesc[oLayerIter->second];
+                    if( oDesc.bIsTopLevel )
+                    {
+                        std::map< int, GMLASField >::const_iterator
+                                    oFieldIter = oDesc.oMapIdxToField.begin();
+                        bool bIsGeometric = false;
+                        for(; oFieldIter != oDesc.oMapIdxToField.end();
+                              ++oFieldIter)
+                        {
+                            if( oFieldIter->second.GetType() ==
+                                                            GMLAS_FT_GEOMETRY )
+                            {
+                                bIsGeometric = true;
+                                break;
+                            }
+                        }
+                        oDesc.bIsSelected = bIsGeometric;
+                    }
+                }
+            }
+            else
+            {
+                oLayerIter = m_oMapLayerNameToIdx.find(*papszIter);
+                if( oLayerIter == m_oMapLayerNameToIdx.end() )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Layer %s specified in LAYERS option "
+                             "does not exist",
+                             *papszIter);
+                    CSLDestroy(papszLayers);
+                    return false;
+                }
+                else
+                {
+                    LayerDescription& oDesc = m_aoLayerDesc[oLayerIter->second];
+                    oDesc.bIsSelected = true;
+                }
+            }
+        }
+        CSLDestroy(papszLayers);
+    }
+    else
+    {
+        ComputeTopLevelFIDs();
+    }
+
+    const bool bWFS2FeatureCollection = EQUAL(
+        CSLFetchNameValueDef( m_papszOptions, szWRAPPING_OPTION,
+                              m_oConf.m_osWrapping),
+        szWFS2_FEATURECOLLECTION);
+
+    if( pfnProgress == GDALDummyProgress )
+        pfnProgress = NULL;
+    // Compute total number of top level features
+    GIntBig nTotalTopLevelFeatures = -1;
+    if( pfnProgress != NULL || bWFS2FeatureCollection )
+    {
+        nTotalTopLevelFeatures = 0;
+        std::map<CPLString, int>::const_iterator oLayerIter =
+                                                m_oMapLayerNameToIdx.begin();
+        for(; oLayerIter != m_oMapLayerNameToIdx.end(); ++oLayerIter)
+        {
+            const LayerDescription& oDesc = m_aoLayerDesc[oLayerIter->second];
+            OGRLayer* poSrcLayer = m_poSrcDS->GetLayerByName(oDesc.osName);
+            if( oDesc.bIsSelected && poSrcLayer != NULL )
+            {
+                nTotalTopLevelFeatures += poSrcLayer->GetFeatureCount(true);
+                nTotalTopLevelFeatures -=
+                        static_cast<GIntBig>(oDesc.aoSetReferencedFIDs.size());
+            }
+        }
+        CPLDebug("GMLAS", CPL_FRMT_GIB " top level features to be written",
+                 nTotalTopLevelFeatures);
+    }
+
+    // Now read options related to writing
+    int nIndentSize = std::min(INDENT_SIZE_MAX,
+        std::max(INDENT_SIZE_MIN,
+            atoi(CSLFetchNameValueDef(m_papszOptions, szINDENT_SIZE_OPTION,
+                                  CPLSPrintf("%d", m_oConf.m_nIndentSize)))));
+    m_osIndentation.assign( nIndentSize, ' ' );
+
+    if( oMapURIToPrefix.find( szGML32_URI ) != oMapURIToPrefix.end()
+        ||
+        // Used by tests
+        oMapURIToPrefix.find( "http://fake_gml32" ) != oMapURIToPrefix.end() )
+    {
+        m_osGMLVersion = "3.2.1";
+    }
+    else
+    {
+        m_osGMLVersion = osGMLVersion;
+    }
+
+    m_osSRSNameFormat = CSLFetchNameValueDef(m_papszOptions,
+                                             szSRSNAME_FORMAT_OPTION,
+                                             m_oConf.m_osSRSNameFormat);
+
+    CPLString osLineFormat = CSLFetchNameValueDef(m_papszOptions,
+                                                  szLINEFORMAT_OPTION,
+                                                  m_oConf.m_osLineFormat);
+    if( !osLineFormat.empty() )
+    {
+        if( EQUAL(osLineFormat, szCRLF) )
+            m_osEOL = "\r\n";
+        else if( EQUAL(osLineFormat, szLF) )
+            m_osEOL = "\n";
+    }
+
+    CPLString osOutXSDFilename =
+        CSLFetchNameValueDef( m_papszOptions,
+                              szOUTPUT_XSD_FILENAME_OPTION, "" );
+    const bool bGenerateXSD = !bWFS2FeatureCollection &&
+        (m_osFilename != "/vsistdout/" || !osOutXSDFilename.empty()) &&
+        CPLFetchBool( m_papszOptions, szGENERATE_XSD_OPTION, true );
+
+    // Write .xsd
+    if( bWFS2FeatureCollection )
+        VSIUnlink( CPLResetExtension( m_osFilename, "xsd" ) );
+    else if( bGenerateXSD && !WriteXSD( osOutXSDFilename, aoXSDs ) )
+        return false;
+
+    // Write .xml header
+    if( !WriteXMLHeader( bWFS2FeatureCollection,
+                         nTotalTopLevelFeatures,
+                         bGenerateXSD,
+                         osOutXSDFilename,
+                         aoXSDs, oMapURIToPrefix ) )
+        return false;
+
+    // Iterate over layers
+    std::map<CPLString, int>::const_iterator oLayerIter =
+                                                m_oMapLayerNameToIdx.begin();
+    GIntBig nFeaturesWritten = 0;
+    bool bRet = true;
+    for(; bRet && oLayerIter != m_oMapLayerNameToIdx.end(); ++oLayerIter)
+    {
+        if( m_aoLayerDesc[oLayerIter->second].bIsSelected )
+        {
+            bRet = WriteLayer( bWFS2FeatureCollection,
+                               m_aoLayerDesc[oLayerIter->second],
+                               nFeaturesWritten,
+                               nTotalTopLevelFeatures,
+                               pfnProgress, pProgressData );
+        }
+    }
+    CPLDebug("GMLAS", CPL_FRMT_GIB " top level features written",
+             nFeaturesWritten);
+
+    // Epilogue of .xml file
+    if( bWFS2FeatureCollection )
+    {
+        PrintLine( m_fpXML, "</%s:%s>",
+                   szWFS_PREFIX,
+                   szFEATURE_COLLECTION );
+    }
+    else
+    {
+        PrintLine( m_fpXML, "</%s:%s>",
+                   m_osTargetNameSpacePrefix.c_str(),
+                   szFEATURE_COLLECTION );
+    }
+
+    Close();
+    return bRet;
+}
+
+/************************************************************************/
+/*                           GetLayerByName()                           */
+/************************************************************************/
+
+// Mostly equivalent to m_poSrcDS->GetLayerByName(), except that we use
+// a map to cache instead of linear search.
+OGRLayer* GMLASWriter::GetLayerByName(const CPLString& osName)
+{
+    std::map<CPLString, OGRLayer*>::const_iterator oIter =
+                                m_oMapLayerNameToLayer.find(osName);
+    if( oIter == m_oMapLayerNameToLayer.end() )
+    {
+        OGRLayer* poLayer = m_poSrcDS->GetLayerByName(osName);
+        m_oMapLayerNameToLayer[osName] = poLayer;
+        return poLayer;
+    }
+    return oIter->second;
+}
+
+/************************************************************************/
+/*                            XMLEscape()                               */
+/************************************************************************/
+
+static CPLString XMLEscape(const CPLString& osStr)
+{
+    char* pszEscaped = CPLEscapeString( osStr, -1, CPLES_XML );
+    CPLString osRet(pszEscaped);
+    CPLFree(pszEscaped);
+    return osRet;
+}
+
+/************************************************************************/
+/*                            WriteXSD()                                */
+/************************************************************************/
+
+bool GMLASWriter::WriteXSD( const CPLString& osXSDFilenameIn,
+                            const std::vector<PairURIFilename>& aoXSDs )
+{
+    const CPLString osXSDFilename(
+        !osXSDFilenameIn.empty() ? osXSDFilenameIn :
+                CPLString(CPLResetExtension( m_osFilename, "xsd" )) );
+    VSILFILE* fpXSD = VSIFOpenL( osXSDFilename, "wb" );
+    if( fpXSD == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot create %s", osXSDFilename.c_str());
+        return false;
+    }
+
+    PrintLine( fpXSD, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" );
+    PrintLine( fpXSD,
+               "<xs:schema ");
+    PrintLine( fpXSD,
+               "    targetNamespace=\"%s\"",
+               XMLEscape(m_osTargetNameSpace).c_str() );
+    PrintLine( fpXSD,
+               "    xmlns:%s=\"%s\"",
+               m_osTargetNameSpacePrefix.c_str(),
+               XMLEscape(m_osTargetNameSpace).c_str() );
+    PrintLine( fpXSD,
+               "    xmlns:xs=\"%s\"",
+               szXS_URI);
+    PrintLine( fpXSD,
+               "    elementFormDefault=\"qualified\" version=\"1.0\" >");
+
+    // Those imports are not really needed, since the schemaLocation are
+    // already specified in the .xml file, but that helps validating the
+    // document with libxml2/xmllint since it can only accept one single main
+    // schema.
+    for( size_t i = 0; i < aoXSDs.size(); ++i )
+    {
+        if( !aoXSDs[i].second.empty() )
+        {
+            if( !aoXSDs[i].first.empty() )
+            {
+                PrintLine( fpXSD,
+                        "<xs:import namespace=\"%s\" schemaLocation=\"%s\"/>",
+                        XMLEscape(aoXSDs[i].first).c_str(),
+                        XMLEscape(aoXSDs[i].second).c_str() );
+            }
+            else
+            {
+                PrintLine( fpXSD,
+                        "<xs:import schemaLocation=\"%s\"/>",
+                        XMLEscape(aoXSDs[i].second).c_str() );
+            }
+        }
+    }
+
+    PrintLine( fpXSD,
+               "<xs:element name=\"%s\" "
+                           "type=\"%s:%sType\"/>",
+               szFEATURE_COLLECTION,
+               m_osTargetNameSpacePrefix.c_str(),
+               szFEATURE_COLLECTION);
+
+    PrintLine( fpXSD, "<xs:complexType name=\"%sType\">",
+               szFEATURE_COLLECTION );
+    PrintLine( fpXSD, "  <xs:sequence>" );
+    PrintLine( fpXSD, "    <xs:element name=\"%s\" "
+                                "minOccurs=\"0\" maxOccurs=\"unbounded\">",
+               szFEATURE_MEMBER );
+    PrintLine( fpXSD, "      <xs:complexType>" );
+    PrintLine( fpXSD, "        <xs:sequence>" );
+    PrintLine( fpXSD, "           <xs:any/>" );
+    PrintLine( fpXSD, "        </xs:sequence>" );
+    PrintLine( fpXSD, "      </xs:complexType>" );
+    PrintLine( fpXSD, "    </xs:element>" );
+    PrintLine( fpXSD, "  </xs:sequence>" );
+    PrintLine( fpXSD, "</xs:complexType>" );
+    PrintLine( fpXSD,
+            "</xs:schema>");
+
+    VSIFCloseL( fpXSD );
+
+    return true;
+}
+
+/************************************************************************/
+/*                         WriteXMLHeader()                             */
+/************************************************************************/
+
+bool GMLASWriter::WriteXMLHeader(
+                        bool bWFS2FeatureCollection,
+                        GIntBig nTotalFeatures,
+                        bool bGenerateXSD,
+                        const CPLString& osXSDFilenameIn,
+                        const std::vector<PairURIFilename>& aoXSDs,
+                        const std::map<CPLString, CPLString>& oMapURIToPrefix )
+{
+    m_fpXML = VSIFOpenL( m_osFilename, "wb" );
+    if( m_fpXML == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot create %s", m_osFilename.c_str());
+        return false;
+    }
+
+    // Delete potentially existing .gfs file
+    VSIUnlink( CPLResetExtension( m_osFilename, "gfs" ) );
+
+    std::map<CPLString, CPLString> aoWrittenPrefixes;
+    aoWrittenPrefixes[szXSI_PREFIX] = szXSI_URI;
+
+    PrintLine( m_fpXML, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" );
+    if( bWFS2FeatureCollection )
+    {
+        PrintLine( m_fpXML, "<%s:%s",
+                    szWFS_PREFIX,
+                    szFEATURE_COLLECTION );
+
+        const CPLString osTimestamp( CSLFetchNameValueDef(m_papszOptions,
+                                                    szTIMESTAMP_OPTION,
+                                                    m_oConf.m_osTimestamp) );
+        if( osTimestamp.empty() )
+        {
+            struct tm sTime;
+            CPLUnixTimeToYMDHMS(time(NULL), &sTime);
+            PrintLine( m_fpXML,
+                       "    timeStamp=\"%04d-%02d-%02dT%02d:%02d:%02dZ\"",
+                       sTime.tm_year + 1900,
+                       sTime.tm_mon + 1,
+                       sTime.tm_mday,
+                       sTime.tm_hour,
+                       sTime.tm_min,
+                       sTime.tm_sec );
+        }
+        else
+        {
+            PrintLine( m_fpXML,
+                       "    timeStamp=\"%s\"", osTimestamp.c_str() );
+        }
+        PrintLine( m_fpXML,
+                   "    numberMatched=\"unknown\"" );
+        PrintLine( m_fpXML,
+                   "    numberReturned=\"" CPL_FRMT_GIB "\"",
+                   nTotalFeatures );
+        PrintLine( m_fpXML,
+                   "    xmlns:%s=\"%s\"",
+                   szWFS_PREFIX,
+                   szWFS20_URI );
+        aoWrittenPrefixes[szWFS_PREFIX] = szWFS20_URI;
+    }
+    else
+    {
+        PrintLine( m_fpXML, "<%s:%s",
+                    m_osTargetNameSpacePrefix.c_str(),
+                    szFEATURE_COLLECTION );
+        PrintLine( m_fpXML,
+                   "    xmlns:%s=\"%s\"",
+                   m_osTargetNameSpacePrefix.c_str(),
+                   XMLEscape(m_osTargetNameSpace).c_str() );
+    }
+    PrintLine( m_fpXML,
+               "    xmlns:%s=\"%s\"",
+               szXSI_PREFIX, szXSI_URI);
+
+    CPLString osSchemaURI;
+    if( bWFS2FeatureCollection )
+    {
+        const CPLString osWFS20SchemaLocation(
+          CSLFetchNameValueDef(m_papszOptions, szWFS20_SCHEMALOCATION_OPTION,
+                               m_oConf.m_osWFS20SchemaLocation) );
+        osSchemaURI += szWFS20_URI;
+        osSchemaURI += " ";
+        osSchemaURI += osWFS20SchemaLocation;
+    }
+    else if( bGenerateXSD || !osXSDFilenameIn.empty() )
+    {
+        const CPLString osXSDFilename(
+            !osXSDFilenameIn.empty() ? osXSDFilenameIn :
+            CPLString( CPLGetFilename(
+                                CPLResetExtension( m_osFilename, "xsd" )) ) );
+        osSchemaURI += m_osTargetNameSpace;
+        osSchemaURI += " ";
+        osSchemaURI += osXSDFilename;
+    }
+
+    for( size_t i = 0; i < aoXSDs.size(); ++i )
+    {
+        const CPLString& osURI( aoXSDs[i].first );
+        const CPLString& osLocation( aoXSDs[i].second );
+
+        CPLString osPrefix;
+        if( !osURI.empty() )
+        {
+            std::map<CPLString, CPLString>::const_iterator oIter =
+                                        oMapURIToPrefix.find(osURI);
+            if( oIter != oMapURIToPrefix.end() )
+            {
+                osPrefix = oIter->second;
+            }
+        }
+        if( !osPrefix.empty() )
+        {
+            std::map<CPLString, CPLString>::const_iterator oIter =
+                                        aoWrittenPrefixes.find( osPrefix );
+            if( oIter != aoWrittenPrefixes.end() )
+            {
+                if( oIter->second != osURI )
+                {
+                    CPLDebug("GMLAS",
+                             "Namespace prefix %s already defined as URI %s "
+                             "but now redefefined as %s. Skipped",
+                             osPrefix.c_str(),
+                             oIter->second.c_str(),
+                             osURI.c_str());
+                }
+                continue;
+            }
+            aoWrittenPrefixes[osPrefix] = osURI;
+        }
+
+        if( osURI.empty() )
+        {
+            if( !osLocation.empty() )
+            {
+                PrintLine( m_fpXML,
+                           "    xsi:%s=\"%s\"",
+                           szNO_NAMESPACE_SCHEMA_LOCATION,
+                           XMLEscape(osLocation).c_str() );
+            }
+        }
+        else
+        {
+            if( osPrefix.empty() )
+            {
+                osPrefix = CPLSPrintf("ns%d", static_cast<int>(i));
+            }
+
+            PrintLine( m_fpXML,
+                       "    xmlns:%s=\"%s\"",
+                       osPrefix.c_str(),
+                       XMLEscape(osURI).c_str() );
+
+            if( !osLocation.empty() )
+            {
+                if( !osSchemaURI.empty() )
+                    osSchemaURI += " ";
+                osSchemaURI += osURI;
+                osSchemaURI += " ";
+                osSchemaURI += osLocation;
+            }
+        }
+    }
+
+    if( !osSchemaURI.empty() )
+    {
+        PrintLine( m_fpXML,
+                "    xsi:%s=\"%s\" >",
+                szSCHEMA_LOCATION,
+                XMLEscape(osSchemaURI).c_str() );
+    }
+
+    // Write optional user comment
+    CPLString osComment(CSLFetchNameValueDef(
+                                    m_papszOptions, szCOMMENT_OPTION,
+                                    m_oConf.m_osComment));
+    if( !osComment.empty() )
+    {
+        while( true )
+        {
+            const size_t nSizeBefore = osComment.size();
+            osComment.replaceAll("--", "- -");
+            if( nSizeBefore == osComment.size() )
+                break;
+        }
+        PrintLine( m_fpXML, "<!-- %s -->", osComment.c_str() );
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                          CollectLayers()                             */
+/************************************************************************/
+
+bool GMLASWriter::CollectLayers()
+{
+    OGRFeatureDefn* poFDefn = m_poLayersMDLayer->GetLayerDefn();
+    const char* const apszFields[] = { szLAYER_NAME,
+                                       szLAYER_XPATH,
+                                       szLAYER_CATEGORY,
+                                       szLAYER_PKID_NAME,
+                                       szLAYER_PARENT_PKID_NAME };
+    for( size_t i = 0; i < CPL_ARRAYSIZE(apszFields); ++i )
+    {
+        if( poFDefn->GetFieldIndex(apszFields[i]) < 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot find field %s in %s layer",
+                     apszFields[i],
+                     m_poLayersMDLayer->GetName());
+            return false;
+        }
+    }
+
+    m_poLayersMDLayer->SetAttributeFilter(NULL);
+    m_poLayersMDLayer->ResetReading();
+    while( true )
+    {
+        OGRFeature* poFeature = m_poLayersMDLayer->GetNextFeature();
+        if( poFeature == NULL )
+            break;
+        LayerDescription desc;
+        desc.osName = poFeature->GetFieldAsString(szLAYER_NAME);
+        desc.osXPath = poFeature->GetFieldAsString(szLAYER_XPATH);
+        desc.osPKIDName = poFeature->GetFieldAsString(szLAYER_PKID_NAME);
+        desc.osParentPKIDName = poFeature->GetFieldAsString(
+                                                    szLAYER_PARENT_PKID_NAME);
+        desc.bIsTopLevel = EQUAL( poFeature->GetFieldAsString(szLAYER_CATEGORY),
+                                  szTOP_LEVEL_ELEMENT );
+        desc.bIsSelected = desc.bIsTopLevel;
+        desc.bIsJunction = EQUAL( poFeature->GetFieldAsString(szLAYER_CATEGORY),
+                                  szJUNCTION_TABLE );
+        delete poFeature;
+
+        OGRLayer* poLyr = GetLayerByName(desc.osName);
+        if( poLyr )
+        {
+            if( !desc.osPKIDName.empty() )
+                desc.oMapFieldNameToOGRIdx[desc.osPKIDName] =
+                        poLyr->GetLayerDefn()->GetFieldIndex(desc.osPKIDName);
+            if( !desc.osParentPKIDName.empty() )
+                desc.oMapFieldNameToOGRIdx[desc.osParentPKIDName] =
+                    poLyr->GetLayerDefn()->GetFieldIndex(desc.osParentPKIDName);
+        }
+
+        m_aoLayerDesc.push_back(desc);
+        if( m_oMapLayerNameToIdx.find(desc.osName) !=
+                                                    m_oMapLayerNameToIdx.end() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Several layers with same %s = %s",
+                     szLAYER_NAME,
+                     desc.osName.c_str() );
+            return false;
+        }
+        if( !desc.bIsJunction &&
+            m_oMapXPathToIdx.find(desc.osXPath) != m_oMapXPathToIdx.end() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Several layers with same %s = %s",
+                     szLAYER_XPATH,
+                     desc.osXPath.c_str() );
+            return false;
+        }
+        const int nIdx = static_cast<int>(m_aoLayerDesc.size() - 1);
+        m_oMapLayerNameToIdx[ desc.osName ] = nIdx;
+        if( !desc.bIsJunction )
+            m_oMapXPathToIdx[ desc.osXPath ] = nIdx;
+    }
+    m_poLayersMDLayer->ResetReading();
+
+    return true;
+}
+
+/************************************************************************/
+/*                          CollectFields()                             */
+/************************************************************************/
+
+bool GMLASWriter::CollectFields()
+{
+    OGRFeatureDefn* poFDefn = m_poFieldsMDLayer->GetLayerDefn();
+    const char* const apszFields[] = { szLAYER_NAME,
+                                       szFIELD_INDEX,
+                                       szFIELD_NAME,
+                                       szFIELD_TYPE,
+                                       szFIELD_XPATH,
+                                       szFIELD_CATEGORY,
+                                       szFIELD_RELATED_LAYER,
+                                       szFIELD_JUNCTION_LAYER,
+                                       szFIELD_IS_LIST,
+                                       szFIELD_MIN_OCCURS,
+                                       szFIELD_MAX_OCCURS,
+                                       szFIELD_REPETITION_ON_SEQUENCE,
+                                       szFIELD_DEFAULT_VALUE };
+    for( size_t i = 0; i < CPL_ARRAYSIZE(apszFields); ++i )
+    {
+        if( poFDefn->GetFieldIndex(apszFields[i]) < 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot find field %s in %s layer",
+                     apszFields[i],
+                     m_poFieldsMDLayer->GetName());
+            return false;
+        }
+    }
+
+    m_poFieldsMDLayer->SetAttributeFilter( NULL );
+    m_poFieldsMDLayer->ResetReading();
+    while( true )
+    {
+        OGRFeature* poFeature = m_poFieldsMDLayer->GetNextFeature();
+        if( poFeature == NULL )
+            break;
+
+        GMLASField oField;
+
+        oField.SetName( poFeature->GetFieldAsString( szFIELD_NAME ) );
+
+        CPLString osLayerName( poFeature->GetFieldAsString( szLAYER_NAME ) );
+        std::map<CPLString, int>::const_iterator oIterToIdx =
+                                        m_oMapLayerNameToIdx.find(osLayerName);
+        if( oIterToIdx == m_oMapLayerNameToIdx.end() )
+        {
+            // Shouldn't happen for well behaved metadata
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Cannot find in %s layer %s, "
+                     "referenced in %s by field %s",
+                     szOGR_LAYERS_METADATA,
+                     osLayerName.c_str(),
+                     szOGR_FIELDS_METADATA,
+                     oField.GetName().c_str());
+            delete poFeature;
+            continue;
+        }
+        if( m_aoLayerDesc[oIterToIdx->second].bIsJunction )
+        {
+            delete poFeature;
+            continue;
+        }
+
+        CPLString osXPath( poFeature->GetFieldAsString( szFIELD_XPATH ) );
+        oField.SetXPath( osXPath );
+
+        CPLString osType( poFeature->GetFieldAsString( szFIELD_TYPE ) );
+        if( !osType.empty() )
+        {
+            if( osType == szFAKEXS_JSON_DICT )
+                oField.SetType( GMLAS_FT_STRING, osType );
+            else if( osType == szFAKEXS_GEOMETRY )
+            {
+                oField.SetType( GMLAS_FT_GEOMETRY, osType );
+                // Hack for geometry field that have a xpath like
+                // foo/bar/gml:Point,foo/bar/gml:LineString,...
+                size_t nPos = osXPath.find("/gml:Point,");
+                if( nPos != std::string::npos )
+                    osXPath.resize(nPos);
+                oField.SetXPath( osXPath );
+            }
+            else
+                oField.SetType( GMLASField::GetTypeFromString(osType), osType );
+        }
+
+        CPLString osCategory( poFeature->GetFieldAsString( szFIELD_CATEGORY ) );
+        if( osCategory == szREGULAR )
+        {
+            oField.SetCategory( GMLASField::REGULAR );
+        }
+        else if( osCategory == szPATH_TO_CHILD_ELEMENT_NO_LINK )
+        {
+            oField.SetCategory( GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK );
+        }
+        else if( osCategory == szPATH_TO_CHILD_ELEMENT_WITH_LINK )
+        {
+            oField.SetCategory( GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK );
+        }
+        else if( osCategory == szPATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE )
+        {
+            oField.SetCategory( GMLASField::
+                                    PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE );
+
+            CPLString osJunctionLayer( poFeature->GetFieldAsString(
+                                                    szFIELD_JUNCTION_LAYER ) );
+            if( osJunctionLayer.empty() )
+            {
+                // Shouldn't happen for well behaved metadata
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Missing value for %s for field (%s,%s)",
+                         szFIELD_JUNCTION_LAYER,
+                         osLayerName.c_str(),
+                         oField.GetName().c_str());
+                delete poFeature;
+                continue;
+            }
+            oField.SetJunctionLayer(osJunctionLayer);
+        }
+        else if( osCategory == szGROUP )
+        {
+            oField.SetCategory( GMLASField::GROUP );
+        }
+        else
+        {
+            // Shouldn't happen for well behaved metadata
+            CPLError(CE_Warning, CPLE_AppDefined,
+                        "Unknown category = %s for field (%s,%s)",
+                        osCategory.c_str(),
+                        osLayerName.c_str(),
+                        oField.GetName().c_str());
+            delete poFeature;
+            continue;
+        }
+
+        CPLString osRelatedLayer( poFeature->GetFieldAsString(
+                                                    szFIELD_RELATED_LAYER ) );
+        if( !osRelatedLayer.empty() &&
+            m_oMapLayerNameToIdx.find( osRelatedLayer ) !=
+                                                m_oMapLayerNameToIdx.end() )
+        {
+            oField.SetRelatedClassXPath(
+                m_aoLayerDesc[m_oMapLayerNameToIdx[ osRelatedLayer ]].osXPath );
+        }
+
+        oField.SetList( CPL_TO_BOOL(
+                            poFeature->GetFieldAsInteger(szFIELD_IS_LIST) ) );
+
+        oField.SetMinOccurs( poFeature->GetFieldAsInteger(szFIELD_MIN_OCCURS) );
+        oField.SetMaxOccurs( poFeature->GetFieldAsInteger(szFIELD_MAX_OCCURS) );
+        oField.SetRepetitionOnSequence( CPL_TO_BOOL(
+            poFeature->GetFieldAsInteger(szFIELD_REPETITION_ON_SEQUENCE) ) );
+        oField.SetDefaultValue( poFeature->GetFieldAsString(
+                                                szFIELD_DEFAULT_VALUE) );
+
+        const int nIdx = poFeature->GetFieldAsInteger( szFIELD_INDEX );
+        delete poFeature;
+
+        const int nLayerIdx = m_oMapLayerNameToIdx[osLayerName];
+        LayerDescription& oLayerDesc = m_aoLayerDesc[nLayerIdx];
+        if( oLayerDesc.oMapIdxToField.find(nIdx) !=
+                                            oLayerDesc.oMapIdxToField.end() )
+        {
+            // Shouldn't happen for well behaved metadata
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Field %s of %s has the same index as field %s",
+                      oField.GetName().c_str(),
+                      osLayerName.c_str(),
+                      oLayerDesc.oMapIdxToField[nIdx].GetName().c_str() );
+            return false;
+        }
+        oLayerDesc.oMapIdxToField[ nIdx ] = oField;
+
+        if( !oField.GetXPath().empty() )
+        {
+            if( oLayerDesc.oMapFieldXPathToIdx.find(oField.GetXPath()) !=
+                        oLayerDesc.oMapFieldXPathToIdx.end() )
+            {
+                // Shouldn't happen for well behaved metadata
+                CPLError( CE_Failure, CPLE_AppDefined,
+                        "Field %s of %s has the same XPath as field %s",
+                        oField.GetName().c_str(),
+                        osLayerName.c_str(),
+                        oLayerDesc.oMapIdxToField[
+                            oLayerDesc.oMapFieldXPathToIdx[oField.GetXPath()]].
+                                GetName().c_str() );
+                return false;
+            }
+            oLayerDesc.oMapFieldXPathToIdx[oField.GetXPath()] = nIdx;
+        }
+
+        OGRLayer* poLyr = GetLayerByName(osLayerName);
+        if( poLyr )
+        {
+            oLayerDesc.oMapFieldNameToOGRIdx[oField.GetName()] =
+                poLyr->GetLayerDefn()->GetFieldIndex(oField.GetName());
+            if( oField.GetType() == GMLAS_FT_GEOMETRY )
+            {
+                oLayerDesc.oMapFieldNameToOGRIdx[oField.GetName() + "_xml"] =
+                    poLyr->GetLayerDefn()->GetFieldIndex(
+                                        (oField.GetName() + "_xml").c_str());
+            }
+        }
+    }
+    m_poFieldsMDLayer->ResetReading();
+
+    return true;
+}
+
+/************************************************************************/
+/*                      CollectRelationships()                          */
+/************************************************************************/
+
+bool GMLASWriter::CollectRelationships()
+{
+    OGRFeatureDefn* poFDefn = m_poLayerRelationshipsLayer->GetLayerDefn();
+    const char* const apszFields[] = { szPARENT_LAYER,
+                                       szCHILD_LAYER,
+                                       szPARENT_ELEMENT_NAME };
+    for( size_t i = 0; i < CPL_ARRAYSIZE(apszFields); ++i )
+    {
+        if( poFDefn->GetFieldIndex(apszFields[i]) < 0 )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot find field %s in %s layer",
+                     apszFields[i],
+                     m_poLayerRelationshipsLayer->GetName());
+            return false;
+        }
+    }
+
+    m_poLayerRelationshipsLayer->SetAttributeFilter( NULL );
+    m_poLayerRelationshipsLayer->ResetReading();
+
+    while( true )
+    {
+        OGRFeature* poFeature = m_poLayerRelationshipsLayer->GetNextFeature();
+        if( poFeature == NULL )
+            break;
+
+        const CPLString osParentLayer(
+                            poFeature->GetFieldAsString( szPARENT_LAYER ) );
+        if( m_oMapLayerNameToIdx.find( osParentLayer ) ==
+                                            m_oMapLayerNameToIdx.end() )
+        {
+            // Shouldn't happen for well behaved metadata
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Cannot find in %s layer %s, referenced in %s",
+                     szOGR_LAYERS_METADATA,
+                     osParentLayer.c_str(),
+                     szOGR_LAYER_RELATIONSHIPS);
+            delete poFeature;
+            continue;
+        }
+
+        const CPLString osChildLayer(
+                                poFeature->GetFieldAsString( szCHILD_LAYER ) );
+        if( m_oMapLayerNameToIdx.find( osChildLayer ) ==
+                                            m_oMapLayerNameToIdx.end() )
+        {
+            // Shouldn't happen for well behaved metadata
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Cannot find in %s layer %s, referenced in %s",
+                     szOGR_LAYERS_METADATA,
+                     osChildLayer.c_str(),
+                     szOGR_LAYER_RELATIONSHIPS);
+            delete poFeature;
+            continue;
+        }
+
+        const int nChildLayerIdx = m_oMapLayerNameToIdx[osChildLayer];
+        if( m_aoLayerDesc[nChildLayerIdx].bIsTopLevel )
+        {
+            const CPLString osReferencingField(
+                        poFeature->GetFieldAsString( szPARENT_ELEMENT_NAME ) );
+
+            m_aoLayerDesc[nChildLayerIdx].aoReferencingLayers.push_back(
+                    PairLayerNameColName( osParentLayer, osReferencingField ) );
+        }
+
+        delete poFeature;
+    }
+    m_poLayerRelationshipsLayer->ResetReading();
+
+    return true;
+}
+
+/************************************************************************/
+/*                      ComputeTopLevelFIDs()                           */
+/*                                                                      */
+/* Find which features of top-level layers are referenced by other      */
+/* features, in which case we don't need to emit them in their layer    */
+/************************************************************************/
+
+void GMLASWriter::ComputeTopLevelFIDs()
+{
+    for( size_t i = 0; i < m_aoLayerDesc.size(); ++i )
+    {
+        LayerDescription& oDesc = m_aoLayerDesc[i];
+        OGRLayer* poLayer = GetLayerByName(oDesc.osName);
+        if( oDesc.bIsTopLevel && poLayer != NULL &&
+            !oDesc.aoReferencingLayers.empty() )
+        {
+            for( size_t j = 0; j < oDesc.aoReferencingLayers.size(); ++j )
+            {
+                CPLString osSQL;
+                CPLString osFID("FID");
+                if( poLayer->GetFIDColumn() &&
+                    !EQUAL(poLayer->GetFIDColumn(), "") )
+                {
+                    osFID = poLayer->GetFIDColumn();
+                }
+
+                // Determine if the referencing field points to a junction
+                // table
+                std::map<CPLString, int>::const_iterator oIter =
+                    m_oMapLayerNameToIdx.find(
+                                        oDesc.aoReferencingLayers[j].first);
+                if( oIter != m_oMapLayerNameToIdx.end() )
+                {
+                    const LayerDescription& oReferencingLayerDesc =
+                                                m_aoLayerDesc[oIter->second];
+                    std::map< int, GMLASField >::const_iterator oIterField =
+                        oReferencingLayerDesc.oMapIdxToField.begin();
+                    for( ;
+                        oIterField != oReferencingLayerDesc.oMapIdxToField.end();
+                        ++oIterField )
+                    {
+                        const GMLASField& oField = oIterField->second;
+                        if( oField.GetName() ==
+                                        oDesc.aoReferencingLayers[j].second )
+                        {
+                            if( oField.GetCategory() == GMLASField::
+                                    PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE )
+                            {
+                                osSQL.Printf(
+                                    "SELECT s.\"%s\" AS ogr_main_fid  "
+                                    "FROM \"%s\" s "
+                                    "JOIN \"%s\" j ON j.%s = s.\"%s\"",
+                                    osFID.c_str(),
+                                    oDesc.osName.c_str(),
+                                    oField.GetJunctionLayer().c_str(),
+                                    szCHILD_PKID,
+                                    oDesc.osPKIDName.c_str());
+                            }
+                            break;
+                        }
+                    }
+                }
+
+                // Otherwise we can use the referencing (layer_name,
+                // field_name) tuple directly.
+                if( osSQL.empty() )
+                {
+                    osSQL.Printf("SELECT s.\"%s\" AS ogr_main_fid "
+                                 "FROM \"%s\" s "
+                                 "JOIN \"%s\" m ON m.\"%s\" = s.\"%s\"",
+                                 osFID.c_str(),
+                                 oDesc.osName.c_str(),
+                                 oDesc.aoReferencingLayers[j].first.c_str(),
+                                 oDesc.aoReferencingLayers[j].second.c_str(),
+                                 oDesc.osPKIDName.c_str());
+                }
+
+                CPLDebug("GMLAS", "Executing %s", osSQL.c_str());
+                OGRLayer* poSQLLyr = m_poSrcDS->ExecuteSQL( osSQL, NULL, NULL );
+                if( poSQLLyr )
+                {
+                    while( true )
+                    {
+                        OGRFeature* poFeature = poSQLLyr->GetNextFeature();
+                        if( poFeature == NULL )
+                            break;
+
+                        const GIntBig nFID = poFeature->GetFieldAsInteger64(0);
+                        oDesc.aoSetReferencedFIDs.insert( nFID );
+
+                        delete poFeature;
+                    }
+                    m_poSrcDS->ReleaseResultSet( poSQLLyr );
+                }
+            }
+
+        }
+    }
+}
+
+/************************************************************************/
+/*                           SplitXPath()                               */
+/************************************************************************/
+
+// Decompose a XPath ns1:foo1/@ns2:foo2/... in its components
+// [ (ns1,foo1), (ns2, at foo2), ... ]
+static XPathComponents SplitXPathInternal( const CPLString& osXPath )
+{
+    char** papszTokens = CSLTokenizeString2(osXPath, "/", 0);
+    XPathComponents aoComponents;
+    for( int i = 0; papszTokens[i] != NULL; ++i )
+    {
+        const bool bAttr = (papszTokens[i][0] == '@');
+        char** papszNSElt = CSLTokenizeString2(papszTokens[i] +
+                                                    (bAttr ? 1 : 0), ":", 0);
+        if( papszNSElt[0] != NULL && papszNSElt[1] != NULL &&
+            papszNSElt[2] == NULL )
+        {
+            CPLString osVal(papszNSElt[1]);
+            size_t nPos = osVal.find(szEXTRA_SUFFIX);
+            if( nPos != std::string::npos )
+                osVal.resize(nPos);
+            aoComponents.push_back( PairNSElement( papszNSElt[0],
+                    (bAttr ? CPLString("@") : CPLString()) + osVal ) );
+        }
+        else if( papszNSElt[0] != NULL && papszNSElt[1] == NULL )
+        {
+            CPLString osVal(papszNSElt[0]);
+            size_t nPos = osVal.find(szEXTRA_SUFFIX);
+            if( nPos != std::string::npos )
+                osVal.resize(nPos);
+            aoComponents.push_back( PairNSElement( "",
+                (bAttr ? CPLString("@") : CPLString()) + osVal ) );
+        }
+        CSLDestroy(papszNSElt);
+    }
+    CSLDestroy(papszTokens);
+    return aoComponents;
+}
+
+const XPathComponents& GMLASWriter::SplitXPath( const CPLString& osXPath )
+{
+    std::map<CPLString, XPathComponents>::const_iterator oIter =
+                                    m_oMapXPathToComponents.find(osXPath);
+    if( oIter == m_oMapXPathToComponents.end() )
+    {
+        m_oMapXPathToComponents[ osXPath ] = SplitXPathInternal(osXPath);
+        oIter = m_oMapXPathToComponents.find(osXPath);
+    }
+    return oIter->second;
+}
+
+/************************************************************************/
+/*                            IsAttr()                                  */
+/************************************************************************/
+
+static bool IsAttr( const PairNSElement& pair )
+{
+    return !pair.second.empty() && pair.second[0] == '@' ;
+}
+
+/************************************************************************/
+/*                           MakeXPath()                                */
+/************************************************************************/
+
+static CPLString MakeXPath( const PairNSElement& pair )
+{
+    if( pair.first.empty() )
+    {
+        if( IsAttr(pair) )
+            return pair.second.substr(1);
+        else
+            return pair.second;
+    }
+    else if( IsAttr(pair) )
+        return pair.first + ":" + pair.second.substr(1);
+    else
+        return pair.first + ":" + pair.second;
+}
+
+/************************************************************************/
+/*                           WriteLayer()                               */
+/************************************************************************/
+
+bool GMLASWriter::WriteLayer( bool bWFS2FeatureCollection,
+                              const LayerDescription& oDesc,
+                              GIntBig& nFeaturesWritten,
+                              GIntBig nTotalTopLevelFeatures,
+                              GDALProgressFunc pfnProgress,
+                              void* pProgressData )
+{
+    OGRLayer* poSrcLayer = GetLayerByName(oDesc.osName);
+    if( poSrcLayer == NULL )
+        return true;
+
+    poSrcLayer->ResetReading();
+    IncIndent();
+    std::set<CPLString> oSetLayersInIteration;
+    oSetLayersInIteration.insert(oDesc.osName);
+    bool bRet = true;
+    while( bRet )
+    {
+        OGRFeature* poFeature = poSrcLayer->GetNextFeature();
+        if( poFeature == NULL )
+            break;
+
+        if( oDesc.aoSetReferencedFIDs.find( poFeature->GetFID() )
+                                    == oDesc.aoSetReferencedFIDs.end() )
+        {
+            PrintIndent(m_fpXML);
+            if( bWFS2FeatureCollection )
+            {
+                PrintLine(m_fpXML, "<%s:%s>", szWFS_PREFIX, szMEMBER);
+            }
+            else
+            {
+                PrintLine(m_fpXML, "<%s:%s>",
+                          m_osTargetNameSpacePrefix.c_str(), szFEATURE_MEMBER);
+            }
+
+            bRet = WriteFeature( poFeature, oDesc,
+                                 oSetLayersInIteration,
+                                 XPathComponents(),
+                                 XPathComponents(),
+                                 0 );
+
+            PrintIndent(m_fpXML);
+            if( bWFS2FeatureCollection )
+            {
+                PrintLine(m_fpXML, "</%s:%s>", szWFS_PREFIX, szMEMBER);
+            }
+            else
+            {
+                PrintLine(m_fpXML, "</%s:%s>",
+                          m_osTargetNameSpacePrefix.c_str(), szFEATURE_MEMBER);
+            }
+
+            if( bRet )
+            {
+                nFeaturesWritten ++;
+                const double dfPct = static_cast<double>(nFeaturesWritten) /
+                                                        nTotalTopLevelFeatures;
+                if( pfnProgress && !pfnProgress(dfPct, "", pProgressData) )
+                {
+                    bRet = false;
+                }
+            }
+
+        }
+        delete poFeature;
+    }
+    poSrcLayer->ResetReading();
+    DecIndent();
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                        FindCommonPrefixLength()                      */
+/************************************************************************/
+
+static
+size_t FindCommonPrefixLength( const XPathComponents& a,
+                               const XPathComponents& b )
+{
+    size_t i = 0;
+    for(; i < a.size() && i < b.size(); ++i )
+    {
+        if( a[i].first != b[i].first || a[i].second != b[i].second )
+            break;
+    }
+    return i;
+}
+
+/************************************************************************/
+/*                        WriteClosingTags()                            */
+/************************************************************************/
+
+void GMLASWriter::WriteClosingTags( size_t nCommonLength,
+                                    const XPathComponents& aoCurComponents,
+                                    const XPathComponents& aoNewComponents,
+                                    bool bCurIsRegularField,
+                                    bool bNewIsRegularField )
+{
+    if( nCommonLength < aoCurComponents.size() )
+    {
+        bool bFieldIsAnotherAttrOfCurElt = false;
+        size_t i = aoCurComponents.size() - 1;
+
+        bool bMustIndent = !bCurIsRegularField;
+
+        if( IsAttr(aoCurComponents.back()) )
+        {
+            if( nCommonLength + 1 == aoCurComponents.size() &&
+                nCommonLength + 1 == aoNewComponents.size() &&
+                IsAttr(aoNewComponents.back()) )
+            {
+                bFieldIsAnotherAttrOfCurElt = true;
+            }
+            else
+            {
+                /*
+                a/@b  cur
+                a     new
+                ==> <a b="">foo</a>
+
+                a/@b  cur
+                a/c   new
+                ==> <a b="">
+                        <c/>
+                     </a>
+
+                a/@b  cur
+                c     new
+                ==> <a b=""/>
+                    <c/>
+
+                */
+                if( (nCommonLength == 0 ||
+                     nCommonLength + 2 <= aoCurComponents.size()) &&
+                    i >= 2 )
+                {
+                    PrintLine(m_fpXML, " />");
+                    i -= 2;
+                    DecIndent();
+                    bMustIndent = true;
+                }
+                else
+                {
+                    VSIFPrintfL(m_fpXML, ">");
+                    CPLAssert( i > 0 );
+                    i --;
+                    // Print a new line except in the <elt attr="foo">bar</elt>
+                    // situation
+                    if( !(nCommonLength + 1 == aoCurComponents.size() &&
+                          nCommonLength == aoNewComponents.size() &&
+                          bNewIsRegularField) )
+                    {
+                        PrintLine(m_fpXML, "%s", "");
+                    }
+                }
+            }
+        }
+
+        if( !bFieldIsAnotherAttrOfCurElt )
+        {
+            for( ; i >= nCommonLength; --i )
+            {
+                if( bMustIndent)
+                {
+                    PrintIndent(m_fpXML);
+                }
+                bMustIndent = true;
+                PrintLine(m_fpXML, "</%s>",
+                        MakeXPath(aoCurComponents[i]).c_str());
+                DecIndent();
+                if( i == 0 )
+                    break;
+            }
+        }
+    }
+}
+
+/************************************************************************/
+/*                      WriteClosingAndStartingTags()                   */
+/************************************************************************/
+
+void GMLASWriter::WriteClosingAndStartingTags(
+                        const XPathComponents& aoCurComponents,
+                        const XPathComponents& aoNewComponents,
+                        bool bCurIsRegularField )
+{
+
+    const size_t nCommonLength =
+        FindCommonPrefixLength( aoCurComponents, aoNewComponents );
+
+    WriteClosingTags( nCommonLength, aoCurComponents,
+                      aoNewComponents, bCurIsRegularField, false );
+    for(size_t i = nCommonLength; i < aoNewComponents.size(); ++i )
+    {
+        IncIndent();
+        PrintIndent(m_fpXML);
+        PrintLine(m_fpXML, "<%s>",
+                    MakeXPath(aoNewComponents[i]).c_str());
+    }
+}
+
+/************************************************************************/
+/*                          WriteFeature()                              */
+/************************************************************************/
+
+bool GMLASWriter::WriteFeature(
+                        OGRFeature* poFeature,
+                        const LayerDescription& oLayerDesc,
+                        const std::set<CPLString>& oSetLayersInIteration,
+                        const XPathComponents& aoInitialComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        int nRecLevel)
+{
+    if( nRecLevel == 100 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "WriteFeature() called with 100 levels of recursion");
+        return false;
+    }
+
+    XPathComponents aoCurComponents(aoInitialComponents);
+    XPathComponents aoLayerComponents;
+    bool bAtLeastOneFieldWritten = false;
+    bool bCurIsRegularField = false;
+    std::map< int, GMLASField >::const_iterator oIter =
+                                            oLayerDesc.oMapIdxToField.begin();
+    for( ; oIter != oLayerDesc.oMapIdxToField.end(); ++oIter )
+    {
+        const GMLASField& oField = oIter->second;
+        const GMLASField::Category eCategory( oField.GetCategory() );
+        if( eCategory == GMLASField::REGULAR )
+        {
+            WriteFieldRegular(           poFeature, oField,
+                                         oLayerDesc,
+                                         /*aoLayerComponents, */
+                                         aoCurComponents,
+                                         aoPrefixComponents,
+                                         /*oSetLayersInIteration,*/
+                                         bAtLeastOneFieldWritten,
+                                         bCurIsRegularField);
+        }
+        else if( eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_NO_LINK ||
+                 eCategory == GMLASField::GROUP )
+        {
+            if( !WriteFieldNoLink(       poFeature, oField,
+                                         oLayerDesc,
+                                         aoLayerComponents,
+                                         aoCurComponents,
+                                         aoPrefixComponents,
+                                         oSetLayersInIteration,
+                                         nRecLevel,
+                                         bAtLeastOneFieldWritten,
+                                         bCurIsRegularField ) )
+            {
+                return false;
+            }
+        }
+        else if( eCategory == GMLASField::PATH_TO_CHILD_ELEMENT_WITH_LINK )
+        {
+            if( !WriteFieldWithLink(     poFeature, oField,
+                                         oLayerDesc,
+                                         aoLayerComponents,
+                                         aoCurComponents,
+                                         aoPrefixComponents,
+                                         oSetLayersInIteration,
+                                         nRecLevel,
+                                         bAtLeastOneFieldWritten,
+                                         bCurIsRegularField ) )
+            {
+                return false;
+            }
+        }
+        else if( eCategory ==
+                        GMLASField::PATH_TO_CHILD_ELEMENT_WITH_JUNCTION_TABLE )
+        {
+            if( !WriteFieldJunctionTable(poFeature, oField,
+                                         oLayerDesc,
+                                         aoLayerComponents,
+                                         aoCurComponents,
+                                         aoPrefixComponents,
+                                         oSetLayersInIteration,
+                                         nRecLevel,
+                                         bAtLeastOneFieldWritten,
+                                         bCurIsRegularField ) )
+            {
+                return false;
+            }
+        }
+
+    }
+
+    if( !bAtLeastOneFieldWritten && aoInitialComponents.empty() &&
+        !oLayerDesc.osXPath.empty() )
+    {
+        aoLayerComponents = SplitXPath(oLayerDesc.osXPath);
+        const CPLString osLayerElt(MakeXPath(aoLayerComponents.back()) );
+        PrintIndent(m_fpXML);
+        VSIFPrintfL(m_fpXML, "%s", m_osIndentation.c_str());
+        PrintLine(m_fpXML, "<%s />", osLayerElt.c_str());
+    }
+    else
+    {
+        const size_t nCommonLength =
+                FindCommonPrefixLength( aoCurComponents, aoInitialComponents );
+        WriteClosingTags( nCommonLength, aoCurComponents,
+                          aoInitialComponents, bCurIsRegularField, false );
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                     PrintMultipleValuesSeparator()                   */
+/************************************************************************/
+
+void GMLASWriter::PrintMultipleValuesSeparator(
+                                const GMLASField& oField,
+                                const XPathComponents& aoFieldComponents)
+{
+    if( oField.IsList() )
+    {
+        VSIFPrintfL(m_fpXML, " ");
+    }
+    else
+    {
+        PrintLine(m_fpXML, "</%s>",
+                MakeXPath(aoFieldComponents.back()).c_str());
+        PrintIndent(m_fpXML);
+        VSIFPrintfL(m_fpXML, "<%s>",
+                MakeXPath(aoFieldComponents.back()).c_str());
+    }
+}
+
+/************************************************************************/
+/*                         PrintXMLDouble()                             */
+/************************************************************************/
+
+static void PrintXMLDouble(VSILFILE* fp, double dfVal )
+{
+    if( CPLIsInf(dfVal) )
+    {
+        if( dfVal > 0 )
+            VSIFPrintfL(fp, "INF");
+        else
+            VSIFPrintfL(fp, "-INF");
+    }
+    else if( CPLIsNan(dfVal) )
+        VSIFPrintfL(fp, "NaN");
+    else
+        VSIFPrintfL(fp, "%.16g", dfVal);
+}
+
+/************************************************************************/
+/*                 AreGeomsEqualAxisOrderInsensitive()                  */
+/************************************************************************/
+
+static bool AreGeomsEqualAxisOrderInsensitive(OGRGeometry* poGeomRef,
+                                              OGRGeometry* poGeomModifiable)
+{
+    if( poGeomRef->Equals(poGeomModifiable) )
+        return true;
+    poGeomModifiable->swapXY();
+    return CPL_TO_BOOL(poGeomRef->Equals(poGeomModifiable));
+}
+
+
+/************************************************************************/
+/*                             GetCoordSwap()                           */
+/************************************************************************/
+
+bool GMLASWriter::GetCoordSwap( const OGRSpatialReference* poSRS )
+{
+    std::map<const OGRSpatialReference*, bool>::const_iterator oIter =
+                                            m_oMapSRSToCoordSwap.find(poSRS);
+    if( oIter != m_oMapSRSToCoordSwap.end() )
+        return oIter->second;
+
+    bool bCoordSwap = false;
+    const char* pszTarget = poSRS->IsProjected() ?
+                                                "PROJCS" : "GEOGCS";
+    const char* pszAuthName = poSRS->GetAuthorityName( pszTarget );
+    const char* pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
+    if( NULL != pszAuthName && NULL != pszAuthCode &&
+        EQUAL( pszAuthName, "EPSG" ) &&
+        m_osSRSNameFormat != "SHORT" &&
+        !(((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong() ||
+        ((OGRSpatialReference*)poSRS)->EPSGTreatsAsNorthingEasting()))
+    {
+        OGRSpatialReference oSRS;
+        if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
+        {
+            if (oSRS.EPSGTreatsAsLatLong() ||
+                oSRS.EPSGTreatsAsNorthingEasting())
+                bCoordSwap = true;
+        }
+    }
+    m_oMapSRSToCoordSwap[poSRS] = bCoordSwap;
+    return bCoordSwap;
+}
+
+/************************************************************************/
+/*                     WriteFieldRegular()                              */
+/************************************************************************/
+
+bool GMLASWriter::WriteFieldRegular(
+                        OGRFeature* poFeature,
+                        const GMLASField& oField,
+                        const LayerDescription& oLayerDesc,
+                        /*XPathComponents& aoLayerComponents,*/
+                        XPathComponents& aoCurComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        /*const std::set<CPLString>& oSetLayersInIteration,*/
+                        bool& bAtLeastOneFieldWritten,
+                        bool& bCurIsRegularField)
+{
+    const bool bIsGeometryField = oField.GetTypeName() == szFAKEXS_GEOMETRY;
+    const int nFieldIdx = bIsGeometryField ?
+        // Some drivers may not store the geometry field name, so for a
+        // feature with a single geometry, use it
+        ( poFeature->GetGeomFieldCount() == 1 ? 0 :
+          poFeature->GetGeomFieldIndex( oField.GetName() ) ) :
+        oLayerDesc.GetOGRIdxFromFieldName( oField.GetName() );
+    XPathComponents aoFieldComponents = SplitXPath(oField.GetXPath());
+    aoFieldComponents.insert( aoFieldComponents.begin(),
+                              aoPrefixComponents.begin(),
+                              aoPrefixComponents.end() );
+
+    // For extension/* case
+    if( !aoFieldComponents.empty() && aoFieldComponents.back().second == "*" )
+    {
+        aoFieldComponents.resize( aoFieldComponents.size() - 1 );
+    }
+
+    const size_t nCommonLength =
+        FindCommonPrefixLength( aoCurComponents, aoFieldComponents );
+
+    const bool bEmptyContent =
+        nFieldIdx < 0 ||
+          ((bIsGeometryField && !poFeature->GetGeomFieldRef(nFieldIdx)) ||
+           (!bIsGeometryField && !poFeature->IsFieldSetAndNotNull(nFieldIdx)));
+    const bool bIsNull = m_oConf.m_bUseNullState  &&
+                         (!bIsGeometryField && nFieldIdx >= 0 &&
+                           poFeature->IsFieldNull(nFieldIdx));
+    bool bMustBeEmittedEvenIfEmpty = oField.GetMinOccurs() > 0 || bIsNull;
+    if( !m_oConf.m_bUseNullState &&
+        oField.GetMinOccurs() == 0 && bEmptyContent &&
+        nCommonLength + 1 == aoCurComponents.size() &&
+        IsAttr(aoCurComponents.back()) &&
+        nCommonLength == aoFieldComponents.size() &&
+        oLayerDesc.oMapFieldXPathToIdx.find(
+            oField.GetXPath() + "/" + szAT_XSI_NIL) ==
+                                    oLayerDesc.oMapFieldXPathToIdx.end() )
+    {
+        // This is quite tricky to determine if a <foo bar="baz"/> node is
+        // valid or if we must add a xsi:nil="true" to make it valid
+        // For now assume that a string can be empty
+        if( oField.GetType() != GMLAS_FT_STRING )
+            bMustBeEmittedEvenIfEmpty = true;
+    }
+
+    if( bEmptyContent && !bMustBeEmittedEvenIfEmpty )
+        return true;
+
+    // Do not emit optional attributes at default/fixed value
+    if( !aoFieldComponents.empty() &&
+        oField.GetMinOccurs() == 0 &&
+        IsAttr( aoFieldComponents.back() ) )
+    {
+        const CPLString& osDefaultVal( !oField.GetDefaultValue().empty() ?
+                                            oField.GetDefaultValue() :
+                                            oField.GetFixedValue() );
+        if( !osDefaultVal.empty() )
+        {
+            if( oField.GetType() == GMLAS_FT_BOOLEAN )
+            {
+                const int nVal = poFeature->GetFieldAsInteger(nFieldIdx);
+                if( osDefaultVal == "false" && nVal == 0 )
+                    return true;
+                if( osDefaultVal == "true" && nVal == 1 )
+                    return true;
+            }
+            else if ( osDefaultVal == poFeature->GetFieldAsString(nFieldIdx) )
+            {
+                return true;
+            }
+        }
+    }
+
+    bAtLeastOneFieldWritten = true;
+
+    if( bEmptyContent &&
+        nCommonLength + 1 == aoCurComponents.size() &&
+        IsAttr(aoCurComponents.back()) &&
+        nCommonLength == aoFieldComponents.size() )
+    {
+        // Particular case for <a foo="bar" xsi:nil="true"/>
+        VSIFPrintfL(m_fpXML, " xsi:nil=\"true\">");
+        aoCurComponents = aoFieldComponents;
+        bCurIsRegularField = true;
+        return true;
+    }
+    else
+    {
+        // Emit closing tags
+        WriteClosingTags( nCommonLength, aoCurComponents,
+                            aoFieldComponents, bCurIsRegularField, true );
+    }
+
+    // Emit opening tags and attribute names
+    // We may do a 0 iteration in case of returning from an attribute
+    // to its element
+    bool bWriteEltContent = true;
+    for(size_t i = nCommonLength; i < aoFieldComponents.size(); ++i )
+    {
+        if( i + 1 == aoFieldComponents.size() &&
+            IsAttr(aoFieldComponents[i]) )
+        {
+            if( aoFieldComponents[i].second != szAT_ANY_ATTR )
+            {
+                VSIFPrintfL(m_fpXML, " %s=",
+                            MakeXPath(aoFieldComponents[i]).c_str());
+                bWriteEltContent = false;
+            }
+        }
+        else
+        {
+            if( i > nCommonLength ) PrintLine(m_fpXML, "%s", "");
+            IncIndent();
+            PrintIndent(m_fpXML);
+
+            if( i + 2 == aoFieldComponents.size() &&
+                    IsAttr(aoFieldComponents[i + 1]) )
+            {
+                // Are we an element that is going to have an
+                // attribute ?
+                VSIFPrintfL(m_fpXML, "<%s",
+                        MakeXPath(aoFieldComponents[i]).c_str());
+            }
+            else
+            {
+                // Are we a regular element ?
+                if( bEmptyContent )
+                {
+                    VSIFPrintfL(m_fpXML, "<%s xsi:nil=\"true\">",
+                        MakeXPath(aoFieldComponents[i]).c_str());
+                }
+                else
+                {
+                    VSIFPrintfL(m_fpXML, "<%s>",
+                        MakeXPath(aoFieldComponents[i]).c_str());
+                }
+            }
+        }
+    }
+
+    // Write content
+    if( !bWriteEltContent )
+        VSIFPrintfL(m_fpXML, "\"" );
+
+    if( !bEmptyContent && oField.GetTypeName() == szFAKEXS_JSON_DICT )
+    {
+        json_object* poObj = NULL;
+        if( OGRJSonParse( poFeature->GetFieldAsString(nFieldIdx),
+                            &poObj ) )
+        {
+            if( json_type_object == json_object_get_type( poObj ) )
+            {
+                json_object_iter it;
+                it.key = NULL;
+                it.val = NULL;
+                it.entry = NULL;
+                json_object_object_foreachC( poObj, it )
+                {
+                    if( it.val != NULL &&
+                        json_object_get_type(it.val) ==
+                                                json_type_string )
+                    {
+                        VSIFPrintfL(m_fpXML, " %s=\"%s\"",
+                                    it.key,
+                            XMLEscape(
+                                json_object_get_string(it.val)).c_str());
+                    }
+                }
+            }
+            json_object_put(poObj);
+        }
+    }
+    else if( !bEmptyContent && bIsGeometryField )
+    {
+        bool bWriteOGRGeom = true;
+        OGRGeometry* poGeom = poFeature->GetGeomFieldRef( nFieldIdx );
+
+        // In case the original GML string was saved, fetch it and compare it
+        // to the current OGR geometry. If they match (in a axis order
+        // insensitive way), then use the original GML string
+        const int nFieldXMLIdx = oLayerDesc.GetOGRIdxFromFieldName
+                                                (oField.GetName() + "_xml");
+        if( nFieldXMLIdx >= 0 &&
+            poFeature->IsFieldSetAndNotNull(nFieldXMLIdx) )
+        {
+            if( poFeature->GetFieldDefnRef(nFieldXMLIdx)->GetType() ==
+                                                                OFTStringList )
+            {
+                if( wkbFlatten(poGeom->getGeometryType()) ==
+                                                        wkbGeometryCollection )
+                {
+                    OGRGeometryCollection* poGC = new OGRGeometryCollection();
+                    char** papszValues = poFeature->
+                                        GetFieldAsStringList(nFieldXMLIdx);
+                    for( int j = 0; papszValues != NULL &&
+                                    papszValues[j] != NULL; ++j )
+                    {
+                        OGRGeometry* poPart = reinterpret_cast<OGRGeometry*>(
+                                        OGR_G_CreateFromGML(papszValues[j]));
+                        if( poPart )
+                            poGC->addGeometryDirectly(poPart);
+                    }
+                    if( AreGeomsEqualAxisOrderInsensitive(poGeom, poGC) )
+                    {
+                        for( int j = 0; papszValues != NULL &&
+                                    papszValues[j] != NULL; ++j )
+                        {
+                            if( j > 0 )
+                                PrintMultipleValuesSeparator(oField,
+                                                            aoFieldComponents);
+                            VSIFPrintfL(m_fpXML, "%s", papszValues[j]);
+                        }
+                        bWriteOGRGeom = false;
+                    }
+                    delete poGC;
+                }
+            }
+            else
+            {
+                const char* pszXML = poFeature->GetFieldAsString(nFieldXMLIdx);
+                OGRGeometry* poOrigGeom = reinterpret_cast<OGRGeometry*>(
+                                                OGR_G_CreateFromGML(pszXML));
+
+                if( poOrigGeom != NULL )
+                {
+                    if( AreGeomsEqualAxisOrderInsensitive(poGeom, poOrigGeom) )
+                    {
+                        VSIFPrintfL(m_fpXML, "%s", pszXML);
+                        bWriteOGRGeom = false;
+                    }
+                    delete poOrigGeom;
+                }
+            }
+        }
+
+        if( bWriteOGRGeom )
+        {
+            CPLString osExtraElt;
+            bool bGMLSurface311 = false;
+            bool bGMLCurve311 = false;
+            bool bGMLPoint311 = false;
+            if( m_osGMLVersion == "3.1.1" &&
+                MakeXPath(aoFieldComponents.back()) == "gml:Surface"  )
+            {
+                bGMLSurface311 = true;
+
+            }
+            else if( m_osGMLVersion == "3.1.1" &&
+                     MakeXPath(aoFieldComponents.back()) == "gml:Curve" )
+            {
+                bGMLCurve311 = true;
+            }
+            else if( m_osGMLVersion == "3.1.1" &&
+                     MakeXPath(aoFieldComponents.back()) == "gml:Point" )
+            {
+                bGMLPoint311 = true;
+            }
+
+            const double dfGMLVersion =
+                m_osGMLVersion.empty() ? 3.2 : CPLAtof(m_osGMLVersion);
+            char** papszOptions = CSLSetNameValue(NULL, "FORMAT",
+                    (dfGMLVersion >= 2.0 && dfGMLVersion < 3.0) ?  "GML2" :
+                    (dfGMLVersion >= 3.0 && dfGMLVersion < 3.2) ?  "GML3" :
+                                                                   "GML32" );
+            papszOptions = CSLSetNameValue(papszOptions, "SRSNAME_FORMAT",
+                                           m_osSRSNameFormat);
+
+            if( dfGMLVersion < 3.0 )
+            {
+                bool bSwap = false;
+                const OGRSpatialReference* poSRS =
+                                                poGeom->getSpatialReference();
+                if( poSRS != NULL && GetCoordSwap(poSRS) )
+                    bSwap = true;
+                papszOptions = CSLSetNameValue(papszOptions, "COORD_SWAP",
+                                                    bSwap ? "TRUE" : "FALSE");
+            }
+
+            if( oField.GetMaxOccurs() > 1 &&
+                wkbFlatten(poGeom->getGeometryType()) ==
+                                                        wkbGeometryCollection )
+            {
+                OGRGeometryCollection* poGC =
+                            reinterpret_cast<OGRGeometryCollection*>(poGeom);
+                for(int j=0; j<poGC->getNumGeometries(); ++j)
+                {
+                    if( dfGMLVersion >= 3.2 )
+                    {
+                        CPLString osGMLID =
+                            poFeature->GetFieldAsString(oLayerDesc.osPKIDName);
+                        osGMLID += CPLSPrintf(".geom%d.%d", nFieldIdx, j);
+                        papszOptions = CSLSetNameValue(papszOptions, "GMLID",
+                                                        osGMLID);
+                    }
+                    if( j > 0 )
+                        PrintMultipleValuesSeparator(oField,
+                                                     aoFieldComponents);
+                    char* pszGML = OGR_G_ExportToGMLEx(
+                        reinterpret_cast<OGRGeometryH>(poGC->getGeometryRef(j)),
+                        papszOptions);
+                    if( pszGML )
+                        VSIFPrintfL(m_fpXML, "%s", pszGML);
+                    CPLFree(pszGML);
+                }
+            }
+            else
+            {
+                if( dfGMLVersion >= 3.2 )
+                {
+                    CPLString osGMLID =
+                            poFeature->GetFieldAsString(oLayerDesc.osPKIDName);
+                    osGMLID += CPLSPrintf(".geom%d", nFieldIdx);
+                    papszOptions = CSLSetNameValue(papszOptions, "GMLID",
+                                                    osGMLID);
+                }
+                char* pszGML = OGR_G_ExportToGMLEx(
+                    reinterpret_cast<OGRGeometryH>(poGeom), papszOptions);
+                if( pszGML )
+                {
+                    if( bGMLSurface311 && STARTS_WITH(pszGML, "<gml:Polygon>") )
+                    {
+                        char* pszEnd = strstr(pszGML, "</gml:Polygon>");
+                        if( pszEnd )
+                        {
+                            *pszEnd = '\0';
+                            VSIFPrintfL(m_fpXML,
+                                        "<gml:patches><gml:PolygonPatch>%s"
+                                        "</gml:PolygonPatch></gml:patches>",
+                                        pszGML + strlen("<gml:Polygon>"));
+                        }
+                    }
+                    else if( bGMLCurve311 && STARTS_WITH(pszGML, "<gml:LineString>") )
+                    {
+                        char* pszEnd = strstr(pszGML, "</gml:LineString>");
+                        if( pszEnd )
+                        {
+                            *pszEnd = '\0';
+                            VSIFPrintfL(m_fpXML,
+                                        "<gml:segments><gml:LineStringSegment>%s"
+                                        "</gml:LineStringSegment></gml:segments>",
+                                        pszGML + strlen("<gml:LineString>"));
+                        }
+                    }
+                    else if( bGMLPoint311 && STARTS_WITH(pszGML, "<gml:Point>") )
+                    {
+                        char* pszEnd = strstr(pszGML, "</gml:Point>");
+                        if( pszEnd )
+                        {
+                            *pszEnd = '\0';
+                            VSIFPrintfL(m_fpXML, "%s",
+                                        pszGML + strlen("<gml:Point>"));
+                        }
+                    }
+                    else
+                    {
+                        VSIFPrintfL(m_fpXML, "%s", pszGML);
+                    }
+                }
+                CPLFree(pszGML);
+            }
+            CSLDestroy(papszOptions);
+        }
+    }
+    else if( !bEmptyContent && oField.GetTypeName() == szXS_ANY_TYPE )
+    {
+        CPLString osXML(poFeature->GetFieldAsString(nFieldIdx));
+        // Check that the content is valid XML
+        CPLString osValidatingXML( "<X>" + osXML + "</X>" );
+        CPLXMLNode* psNode = CPLParseXMLString(osValidatingXML);
+        if( psNode != NULL )
+        {
+            VSIFPrintfL(m_fpXML, "%s", osXML.c_str());
+            CPLDestroyXMLNode(psNode);
+        }
+        else
+        {
+            // Otherwise consider it as text and escape
+            VSIFPrintfL(m_fpXML, "%s", XMLEscape(osXML).c_str());
+        }
+    }
+    else if( !bEmptyContent )
+    {
+        const OGRFieldType eOGRType(
+            poFeature->GetFieldDefnRef(nFieldIdx)->GetType() );
+        switch( oField.GetType() )
+        {
+            case GMLAS_FT_BOOLEAN:
+            {
+                if( (oField.GetMaxOccurs() > 1 || oField.IsList()) &&
+                    eOGRType == OFTIntegerList )
+                {
+                    int nCount = 0;
+                    const int* panValues = poFeature->
+                                GetFieldAsIntegerList(nFieldIdx, &nCount);
+                    for( int j = 0; j < nCount; ++j )
+                    {
+                        if( j > 0 )
+                            PrintMultipleValuesSeparator(oField,
+                                                            aoFieldComponents);
+                        VSIFPrintfL(m_fpXML,
+                                    panValues[j] ? "true" : "false");
+                    }
+                }
+                else
+                {
+                    VSIFPrintfL(m_fpXML,
+                            poFeature->GetFieldAsInteger(nFieldIdx) ?
+                                                    "true" : "false" );
+                }
+                break;
+            }
+
+            case GMLAS_FT_DATETIME:
+            case GMLAS_FT_DATE:
+            case GMLAS_FT_TIME:
+            {
+                if( eOGRType == OFTDateTime ||
+                    eOGRType == OFTDate ||
+                    eOGRType == OFTTime)
+                {
+                    char* pszFormatted = OGRGetXMLDateTime(
+                                poFeature->GetRawFieldRef(nFieldIdx));
+                    char* pszT = strchr(pszFormatted, 'T');
+                    if( oField.GetType() == GMLAS_FT_TIME &&
+                        pszT != NULL )
+                    {
+                        VSIFPrintfL(m_fpXML, "%s", pszT+1);
+                    }
+                    else
+                    {
+                        if( oField.GetType() == GMLAS_FT_DATE )
+                        {
+                            if( pszT )
+                                *pszT = '\0';
+                        }
+                        VSIFPrintfL(m_fpXML, "%s", pszFormatted);
+                    }
+                    VSIFree(pszFormatted);
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "Invalid content for field %s of type %s: %s",
+                            oField.GetName().c_str(),
+                            oField.GetTypeName().c_str(),
+                            poFeature->GetFieldAsString(nFieldIdx));
+                }
+                break;
+            }
+
+            case GMLAS_FT_BASE64BINARY:
+            {
+                if( eOGRType == OFTBinary )
+                {
+                    int nCount = 0;
+                    GByte* pabyContent = poFeature->
+                                    GetFieldAsBinary(nFieldIdx, &nCount );
+                    char* pszBase64 = CPLBase64Encode(nCount, pabyContent);
+                    VSIFPrintfL(m_fpXML, "%s", pszBase64);
+                    CPLFree(pszBase64);
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "Invalid content for field %s of type %s: %s",
+                            oField.GetName().c_str(),
+                            oField.GetTypeName().c_str(),
+                            poFeature->GetFieldAsString(nFieldIdx));
+                }
+                break;
+            }
+
+            case GMLAS_FT_HEXBINARY:
+            {
+                if( eOGRType == OFTBinary )
+                {
+                    int nCount = 0;
+                    GByte* pabyContent = poFeature->
+                                    GetFieldAsBinary(nFieldIdx, &nCount );
+                    for( int i = 0; i < nCount; ++i )
+                        VSIFPrintfL(m_fpXML, "%02X", pabyContent[i]);
+                }
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                            "Invalid content for field %s of type %s: %s",
+                            oField.GetName().c_str(),
+                            oField.GetTypeName().c_str(),
+                            poFeature->GetFieldAsString(nFieldIdx));
+                }
+                break;
+            }
+
+            default:
+            {
+                if( (oField.GetMaxOccurs() > 1 || oField.IsList()) &&
+                    (eOGRType == OFTStringList ||
+                    eOGRType == OFTRealList ||
+                    eOGRType == OFTIntegerList ||
+                    eOGRType == OFTInteger64List ) )
+                {
+                    if( eOGRType == OFTStringList )
+                    {
+                        char** papszValues = poFeature->
+                                        GetFieldAsStringList(nFieldIdx);
+                        for( int j = 0; papszValues != NULL &&
+                                        papszValues[j] != NULL; ++j )
+                        {
+                            if( j > 0 )
+                                PrintMultipleValuesSeparator(oField,
+                                                            aoFieldComponents);
+                            VSIFPrintfL(m_fpXML, "%s", XMLEscape(
+                                            papszValues[j]).c_str());
+                        }
+                    }
+                    else if( eOGRType == OFTRealList )
+                    {
+                        int nCount = 0;
+                        const double* padfValues = poFeature->
+                                    GetFieldAsDoubleList(nFieldIdx, &nCount);
+                        for( int j = 0; j < nCount; ++j )
+                        {
+                            if( j > 0 )
+                                PrintMultipleValuesSeparator(oField,
+                                                            aoFieldComponents);
+                            PrintXMLDouble(m_fpXML, padfValues[j]);
+                        }
+                    }
+                    else if( eOGRType == OFTIntegerList )
+                    {
+                        int nCount = 0;
+                        const int* panValues = poFeature->
+                                GetFieldAsIntegerList(nFieldIdx, &nCount);
+                        for( int j = 0; j < nCount; ++j )
+                        {
+                            if( j > 0 )
+                                PrintMultipleValuesSeparator(oField,
+                                                            aoFieldComponents);
+                            VSIFPrintfL(m_fpXML, "%d", panValues[j]);
+                        }
+                    }
+                    else if( eOGRType == OFTInteger64List )
+                    {
+                        int nCount = 0;
+                        const GIntBig* panValues = poFeature->
+                                GetFieldAsInteger64List(nFieldIdx, &nCount);
+                        for( int j = 0; j < nCount; ++j )
+                        {
+                            if( j > 0 )
+                                PrintMultipleValuesSeparator(oField,
+                                                            aoFieldComponents);
+                            VSIFPrintfL(m_fpXML, CPL_FRMT_GIB, panValues[j]);
+                        }
+                    }
+                }
+                else if( eOGRType == OFTReal )
+                {
+                    PrintXMLDouble(m_fpXML,
+                                poFeature->GetFieldAsDouble(nFieldIdx));
+                }
+                else
+                {
+                    VSIFPrintfL(m_fpXML, "%s", XMLEscape(
+                        poFeature->GetFieldAsString(nFieldIdx)).c_str());
+                }
+                break;
+            }
+        }
+    }
+
+    if( !bWriteEltContent )
+        VSIFPrintfL(m_fpXML, "\"" );
+
+
+    aoCurComponents = aoFieldComponents;
+    bCurIsRegularField = true;
+
+    return true;
+}
+
+/************************************************************************/
+/*                     WriteFieldNoLink()                               */
+/************************************************************************/
+
+bool GMLASWriter::WriteFieldNoLink(
+                        OGRFeature* poFeature,
+                        const GMLASField& oField,
+                        const LayerDescription& oLayerDesc,
+                        XPathComponents& aoLayerComponents,
+                        XPathComponents& aoCurComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        const std::set<CPLString>& oSetLayersInIteration,
+                        int nRecLevel,
+                        bool& bAtLeastOneFieldWritten,
+                        bool& bCurIsRegularField)
+{
+    std::map<CPLString, int>::const_iterator oIter =
+        m_oMapXPathToIdx.find( oField.GetRelatedClassXPath() );
+    if( oIter == m_oMapXPathToIdx.end() )
+    {
+        // Not necessary to be more verbose in case of truncated
+        // source dataset
+        CPLDebug("GMLAS", "No child layer of %s matching xpath = %s",
+                    oLayerDesc.osName.c_str(),
+                    oField.GetRelatedClassXPath().c_str());
+        return true;
+    }
+
+    const LayerDescription& oChildLayerDesc =
+                                    m_aoLayerDesc[oIter->second];
+    OGRLayer* poRelLayer = GetLayerByName( oChildLayerDesc.osName );
+    if( poRelLayer == NULL )
+    {
+        // Not necessary to be more verbose in case of truncated
+        // source dataset
+        CPLDebug("GMLAS", "Child layer %s of %s not found",
+                    oChildLayerDesc.osName.c_str(),
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+
+    if( oLayerDesc.osPKIDName.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Missing %s for layer %s",
+                    szLAYER_PKID_NAME,
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+    int nParentPKIDIdx;
+    if( (nParentPKIDIdx =
+            oLayerDesc.GetOGRIdxFromFieldName( oLayerDesc.osPKIDName )) < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot find field %s in layer %s",
+                    oLayerDesc.osPKIDName.c_str(),
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+    if( !poFeature->IsFieldSetAndNotNull( nParentPKIDIdx ) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Missing value of %s field for feature "
+                    CPL_FRMT_GIB " of layer %s",
+                    oLayerDesc.osPKIDName.c_str(),
+                    poFeature->GetFID(),
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+    if( oChildLayerDesc.osParentPKIDName.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Missing %s for layer %s",
+                    szLAYER_PARENT_PKID_NAME,
+                    oChildLayerDesc.osName.c_str());
+    }
+    if( oSetLayersInIteration.find( oChildLayerDesc.osName ) !=
+                oSetLayersInIteration.end() )
+    {
+        CPLDebug("GMLAS", "Unexpected at line %d", __LINE__);
+        return true;
+    }
+
+    std::set<CPLString> oSetLayersInIterationSub(oSetLayersInIteration);
+    oSetLayersInIterationSub.insert( oChildLayerDesc.osName );
+
+    if( aoLayerComponents.empty() )
+    {
+        aoLayerComponents = SplitXPath(oLayerDesc.osXPath);
+        aoLayerComponents.insert( aoLayerComponents.begin(),
+                                  aoPrefixComponents.begin(),
+                                  aoPrefixComponents.end() );
+    }
+
+    XPathComponents aoFieldComponents = SplitXPath(oField.GetXPath());
+    aoFieldComponents.insert( aoFieldComponents.begin(),
+                              aoPrefixComponents.begin(),
+                              aoPrefixComponents.end() );
+
+    CPLString osParentPKID (
+        poFeature->GetFieldAsString( nParentPKIDIdx ) );
+    poRelLayer->SetAttributeFilter(
+        CPLSPrintf( "%s = '%s'",
+                    oChildLayerDesc.osParentPKIDName.c_str(),
+                    osParentPKID.c_str() ) );
+    poRelLayer->ResetReading();
+
+    OGRFeature* poChildFeature = poRelLayer->GetNextFeature();
+    XPathComponents aoNewInitialContext;
+    if( poChildFeature != NULL )
+    {
+        if( aoFieldComponents.size() == aoLayerComponents.size() + 1 &&
+            oField.GetRepetitionOnSequence() )
+        {
+            /* Case of
+            <xs:element name="sequence_unbounded_dt_1">
+                <xs:complexType>
+                    <xs:sequence maxOccurs="unbounded">
+                        <xs:element name="subelement"
+                                    type="xs:dateTime"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            */
+            aoNewInitialContext = aoFieldComponents;
+        }
+        else if( aoFieldComponents.size() ==
+                                        aoLayerComponents.size() + 2 )
+        {
+            /* Case of
+            <xs:element name="sequence_1_dt_unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="subelement"
+                                    type="xs:dateTime"
+                                    maxOccurs="unbounded"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            */
+            aoNewInitialContext = aoFieldComponents;
+            aoNewInitialContext.resize(
+                                    aoNewInitialContext.size() - 1 );
+        }
+        else
+        {
+            /* Case of
+            <xs:element name="unbounded_sequence_1_dt"
+                        maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="subelement"
+                                    type="xs:dateTime"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            */
+            aoNewInitialContext = aoLayerComponents;
+        }
+
+
+        WriteClosingAndStartingTags( aoCurComponents,
+                                        aoNewInitialContext,
+                                        bCurIsRegularField );
+
+        bAtLeastOneFieldWritten = true;
+        aoCurComponents = aoNewInitialContext;
+        bCurIsRegularField = false;
+    }
+
+    while( poChildFeature )
+    {
+        bool bRet = WriteFeature(poChildFeature,
+                                 oChildLayerDesc,
+                                 oSetLayersInIterationSub,
+                                 aoNewInitialContext,
+                                 aoPrefixComponents,
+                                 nRecLevel + 1);
+
+        delete poChildFeature;
+        if( !bRet )
+            return false;
+
+        poChildFeature = poRelLayer->GetNextFeature();
+    }
+    poRelLayer->ResetReading();
+
+    return true;
+}
+
+/************************************************************************/
+/*                       GetFilteredLayer()                             */
+/************************************************************************/
+
+OGRLayer* GMLASWriter::GetFilteredLayer(
+                            OGRLayer* poSrcLayer,
+                            const CPLString& osFilter,
+                            const std::set<CPLString>& oSetLayersInIteration)
+{
+    if( oSetLayersInIteration.find(poSrcLayer->GetName()) ==
+                                    oSetLayersInIteration.end() )
+    {
+        poSrcLayer->SetAttributeFilter(osFilter);
+        poSrcLayer->ResetReading();
+        return poSrcLayer;
+    }
+
+    // RDBMS drivers will really create a new iterator independent of the
+    // underlying layer when using a SELECT statement
+    GDALDriver* poDriver = m_poSrcDS->GetDriver();
+    if( poDriver != NULL &&
+        ( EQUAL( poDriver->GetDescription(), "SQLite" ) ||
+          EQUAL( poDriver->GetDescription(), "PostgreSQL" ) ) )
+    {
+        CPLString osSQL;
+        osSQL.Printf("SELECT * FROM \"%s\" WHERE %s",
+                     poSrcLayer->GetName(), osFilter.c_str());
+        return m_poSrcDS->ExecuteSQL(osSQL, NULL, NULL);
+    }
+
+    // TODO ?
+    CPLDebug("GMLAS", "Cannot recursively iterate on %s on this driver",
+             poSrcLayer->GetName());
+    return NULL;
+}
+
+/************************************************************************/
+/*                      ReleaseFilteredLayer()                          */
+/************************************************************************/
+
+void GMLASWriter::ReleaseFilteredLayer(OGRLayer* poSrcLayer,
+                                       OGRLayer* poIterLayer)
+{
+    if( poIterLayer != poSrcLayer )
+        m_poSrcDS->ReleaseResultSet(poIterLayer);
+    else
+        poSrcLayer->ResetReading();
+}
+
+/************************************************************************/
+/*                     WriteFieldWithLink()                             */
+/************************************************************************/
+
+bool GMLASWriter::WriteFieldWithLink(
+                        OGRFeature* poFeature,
+                        const GMLASField& oField,
+                        const LayerDescription& oLayerDesc,
+                        XPathComponents& aoLayerComponents,
+                        XPathComponents& aoCurComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        const std::set<CPLString>& oSetLayersInIteration,
+                        int nRecLevel,
+                        bool& bAtLeastOneFieldWritten,
+                        bool& bCurIsRegularField)
+{
+    std::map<CPLString, int>::const_iterator oIter =
+        m_oMapXPathToIdx.find( oField.GetRelatedClassXPath() );
+    if( oIter == m_oMapXPathToIdx.end() )
+    {
+        // Not necessary to be more verbose in case of truncated
+        // source dataset
+        CPLDebug("GMLAS", "No child layer of %s matching xpath = %s",
+                    oLayerDesc.osName.c_str(),
+                    oField.GetRelatedClassXPath().c_str());
+        return true;
+    }
+
+    const LayerDescription& oChildLayerDesc =
+                                    m_aoLayerDesc[oIter->second];
+    OGRLayer* poRelLayer = GetLayerByName( oChildLayerDesc.osName );
+    if( poRelLayer == NULL )
+    {
+        // Not necessary to be more verbose in case of truncated
+        // source dataset
+        CPLDebug("GMLAS", "Referenced layer %s of %s not found",
+                    oChildLayerDesc.osName.c_str(),
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+
+    const int nFieldIdx = oLayerDesc.GetOGRIdxFromFieldName(oField.GetName());
+    XPathComponents aoFieldComponents = SplitXPath(oField.GetXPath());
+    aoFieldComponents.insert( aoFieldComponents.begin(),
+                              aoPrefixComponents.begin(),
+                              aoPrefixComponents.end() );
+
+    if( nFieldIdx < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Missing field %s for layer %s",
+                    oField.GetName().c_str(),
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+    if( !poFeature->IsFieldSetAndNotNull(nFieldIdx) )
+    {
+        // Not an error (unless the field is required)
+        return true;
+    }
+    if( oLayerDesc.osPKIDName.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Missing %s for layer %s",
+                    szLAYER_PKID_NAME,
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+    if( oChildLayerDesc.osPKIDName.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Missing %s for layer %s",
+                    szLAYER_PKID_NAME,
+                    oChildLayerDesc.osName.c_str());
+        return true;
+    }
+    if( aoFieldComponents.size() < 2 )
+    {
+        // Shouldn't happen for well behaved metadata
+        CPLDebug("GMLAS", "Unexpected at line %d", __LINE__);
+        return true;
+    }
+    if( oChildLayerDesc.osXPath.empty() ||
+        aoFieldComponents.back() != SplitXPath(oChildLayerDesc.osXPath).front())
+    {
+        // Shouldn't happen for well behaved metadata
+        CPLDebug("GMLAS", "Unexpected at line %d", __LINE__);
+        return true;
+    }
+
+    CPLString osChildPKID (
+        poFeature->GetFieldAsString( nFieldIdx ) );
+    const CPLString osFilter( CPLSPrintf( "%s = '%s'",
+                                          oChildLayerDesc.osPKIDName.c_str(),
+                                          osChildPKID.c_str() ) );
+    OGRLayer* poIterLayer = GetFilteredLayer(poRelLayer, osFilter,
+                                             oSetLayersInIteration);
+    if( poIterLayer == NULL )
+    {
+        return true;
+    }
+
+    std::set<CPLString> oSetLayersInIterationSub(oSetLayersInIteration);
+    oSetLayersInIterationSub.insert( oChildLayerDesc.osName );
+
+    XPathComponents aoPrefixComponentsNew(aoFieldComponents);
+    aoPrefixComponentsNew.resize( aoPrefixComponentsNew.size() - 1 );
+
+    if( aoLayerComponents.empty() )
+    {
+        aoLayerComponents = SplitXPath(oLayerDesc.osXPath);
+        aoLayerComponents.insert( aoLayerComponents.begin(),
+                                  aoPrefixComponents.begin(),
+                                  aoPrefixComponents.end() );
+    }
+
+    OGRFeature* poChildFeature = poIterLayer->GetNextFeature();
+    XPathComponents aoInitialComponents;
+    const bool bHasChild = poChildFeature != NULL;
+    if( bHasChild )
+    {
+        aoInitialComponents = aoFieldComponents;
+        if( !aoInitialComponents.empty() )
+            aoInitialComponents.resize( aoInitialComponents.size()-1 );
+        WriteClosingAndStartingTags( aoCurComponents,
+                                     aoInitialComponents,
+                                     bCurIsRegularField );
+    }
+
+    bool bRet = true;
+    while( poChildFeature )
+    {
+        bRet = WriteFeature(poChildFeature,
+                            oChildLayerDesc,
+                            oSetLayersInIterationSub,
+                            aoInitialComponents,
+                            aoPrefixComponentsNew,
+                            nRecLevel + 1);
+
+        delete poChildFeature;
+        if( !bRet )
+            break;
+        poChildFeature = poIterLayer->GetNextFeature();
+    }
+    ReleaseFilteredLayer(poRelLayer, poIterLayer);
+
+    if( bHasChild )
+    {
+        bAtLeastOneFieldWritten = true;
+        aoCurComponents = aoInitialComponents;
+        bCurIsRegularField = false;
+    }
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                   WriteFieldJunctionTable()                          */
+/************************************************************************/
+
+bool GMLASWriter::WriteFieldJunctionTable(
+                        OGRFeature* poFeature,
+                        const GMLASField& oField,
+                        const LayerDescription& oLayerDesc,
+                        XPathComponents& /*aoLayerComponents */,
+                        XPathComponents& aoCurComponents,
+                        const XPathComponents& aoPrefixComponents,
+                        const std::set<CPLString>& oSetLayersInIteration,
+                        int nRecLevel,
+                        bool& bAtLeastOneFieldWritten,
+                        bool& bCurIsRegularField)
+{
+    std::map<CPLString, int>::const_iterator oIter =
+        m_oMapXPathToIdx.find( oField.GetRelatedClassXPath() );
+    if( oIter == m_oMapXPathToIdx.end() )
+    {
+        // Not necessary to be more verbose in case of truncated
+        // source dataset
+        CPLDebug("GMLAS", "No related layer of %s matching xpath = %s",
+                    oLayerDesc.osName.c_str(),
+                    oField.GetRelatedClassXPath().c_str());
+        return true;
+    }
+
+    const LayerDescription& oRelLayerDesc = m_aoLayerDesc[oIter->second];
+    OGRLayer* poRelLayer = GetLayerByName(oRelLayerDesc.osName);
+    OGRLayer* poJunctionLayer = GetLayerByName( oField.GetJunctionLayer() );
+    if( poRelLayer == NULL )
+    {
+        // Not necessary to be more verbose in case of truncated
+        // source dataset
+        CPLDebug("GMLAS", "Referenced layer %s of %s not found",
+                    oRelLayerDesc.osName.c_str(),
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+    if( poJunctionLayer == NULL )
+    {
+        // Not necessary to be more verbose in case of truncated
+        // source dataset
+        CPLDebug("GMLAS", "Junction layer %s not found",
+                    oField.GetJunctionLayer().c_str());
+        return true;
+    }
+
+    int nIndexPKID = -1;
+    if( oLayerDesc.osPKIDName.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Missing %s for layer %s",
+                    szLAYER_PKID_NAME,
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+    if( (nIndexPKID =
+            oLayerDesc.GetOGRIdxFromFieldName(oLayerDesc.osPKIDName)) < 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot find %s='%s' in layer %s",
+                    szLAYER_PKID_NAME,
+                    oLayerDesc.osPKIDName.c_str(),
+                    oLayerDesc.osName.c_str());
+        return true;
+    }
+    if( !poFeature->IsFieldSetAndNotNull(nIndexPKID) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Field '%s' in layer %s is not set for "
+                    "feature " CPL_FRMT_GIB,
+                    oLayerDesc.osPKIDName.c_str(),
+                    oLayerDesc.osName.c_str(),
+                    poFeature->GetFID());
+        return true;
+    }
+    if( oRelLayerDesc.osPKIDName.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Missing %s for layer %s",
+                    szLAYER_PKID_NAME,
+                    oRelLayerDesc.osName.c_str());
+        return true;
+    }
+    if( oSetLayersInIteration.find( oRelLayerDesc.osName ) !=
+                oSetLayersInIteration.end() )
+    {
+        // TODO... cycle situation. We will need to open a new
+        // source dataset or something
+        return true;
+    }
+
+    std::set<CPLString> oSetLayersInIterationSub(oSetLayersInIteration);
+    oSetLayersInIterationSub.insert( oRelLayerDesc.osName );
+
+    poJunctionLayer->SetAttributeFilter(
+        CPLSPrintf( "%s = '%s'",
+                    szPARENT_PKID,
+                    poFeature->GetFieldAsString(nIndexPKID) ) );
+    poJunctionLayer->ResetReading();
+    std::vector<CPLString> aoChildPKIDs;
+    while( true )
+    {
+        OGRFeature* poJunctionFeature = poJunctionLayer->GetNextFeature();
+        if( poJunctionFeature == NULL )
+            break;
+
+        aoChildPKIDs.push_back(
+            poJunctionFeature->GetFieldAsString(szCHILD_PKID) );
+
+        delete poJunctionFeature;
+    }
+    poJunctionLayer->ResetReading();
+
+    bool bRet = true;
+    bool bHasChild = false;
+    XPathComponents aoInitialComponents;
+    for(size_t j=0; bRet && j<aoChildPKIDs.size(); j++ )
+    {
+        CPLString osFilter;
+        osFilter.Printf( "%s = '%s'",
+                        oRelLayerDesc.osPKIDName.c_str(),
+                        aoChildPKIDs[j].c_str() );
+        OGRLayer* poIterLayer = GetFilteredLayer(poRelLayer, osFilter,
+                                                 oSetLayersInIteration);
+        if( poIterLayer == NULL )
+        {
+            return true;
+        }
+
+        OGRFeature* poChildFeature = poIterLayer->GetNextFeature();
+        if( poChildFeature != NULL )
+        {
+            if( !bHasChild )
+            {
+                bHasChild = true;
+
+                aoInitialComponents = SplitXPath(oField.GetXPath());
+                aoInitialComponents.insert( aoInitialComponents.begin(),
+                                            aoPrefixComponents.begin(),
+                                            aoPrefixComponents.end() );
+
+                if( !aoInitialComponents.empty() )
+                    aoInitialComponents.resize( aoInitialComponents.size()-1 );
+                WriteClosingAndStartingTags( aoCurComponents,
+                                            aoInitialComponents,
+                                            bCurIsRegularField );
+            }
+
+            bRet = WriteFeature( poChildFeature,
+                                 oRelLayerDesc,
+                                 oSetLayersInIterationSub,
+                                 XPathComponents(),
+                                 XPathComponents(),
+                                 nRecLevel + 1 );
+
+            delete poChildFeature;
+            ReleaseFilteredLayer(poRelLayer, poIterLayer);
+        }
+        else
+        {
+            ReleaseFilteredLayer(poRelLayer, poIterLayer);
+        }
+    }
+
+    if( bHasChild )
+    {
+        bAtLeastOneFieldWritten = true;
+        aoCurComponents = aoInitialComponents;
+        bCurIsRegularField = false;
+    }
+
+    return bRet;
+}
+
+/************************************************************************/
+/*                           PrintIndent()                              */
+/************************************************************************/
+
+void GMLASWriter::PrintIndent(VSILFILE* fp)
+{
+    for( int i = 0; i < m_nIndentLevel; i++ )
+    {
+        VSIFWriteL(m_osIndentation.c_str(), 1, m_osIndentation.size(), fp);
+    }
+}
+
+/************************************************************************/
+/*                            PrintLine()                               */
+/************************************************************************/
+
+void GMLASWriter::PrintLine(VSILFILE* fp, const char *fmt, ...)
+{
+    CPLString osWork;
+    va_list args;
+
+    va_start( args, fmt );
+    osWork.vPrintf( fmt, args );
+    va_end( args );
+
+    VSIFWriteL(osWork.c_str(), 1, osWork.size(), fp);
+    VSIFWriteL(m_osEOL.c_str(), 1, m_osEOL.size(), fp);
+}
+
+}; /* namespace GMLAS */
+
+
+/************************************************************************/
+/*                           GMLASFakeDataset                           */
+/************************************************************************/
+
+class GMLASFakeDataset : public GDALDataset
+{
+    public:
+        GMLASFakeDataset() {}
+};
+
+/************************************************************************/
+/*                        OGRGMLASDriverCreateCopy()                    */
+/************************************************************************/
+
+GDALDataset *OGRGMLASDriverCreateCopy(
+                          const char * pszFilename,
+                          GDALDataset *poSrcDS,
+                          int /*bStrict*/,
+                          char ** papszOptions,
+                          GDALProgressFunc pfnProgress,
+                          void * pProgressData )
+{
+    if( strcmp(CPLGetExtension(pszFilename), "xsd") == 0 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, ".xsd extension is not valid");
+        return NULL;
+    }
+
+    // Strip GMLAS: prefix if specified
+    if( STARTS_WITH_CI(pszFilename, szGMLAS_PREFIX) )
+        pszFilename += strlen(szGMLAS_PREFIX);
+
+    GMLAS::GMLASWriter oWriter(pszFilename, poSrcDS, papszOptions);
+    if( !oWriter.Write(pfnProgress, pProgressData) )
+        return NULL;
+
+    if( CPLString(pszFilename) == "/vsistdout/" ||
+        // This option is mostly useful for tests where we don't want
+        // WFS 2.0 schemas to be pulled from the network
+        !CPLFetchBool(papszOptions, "REOPEN_DATASET_WITH_GMLAS", true) )
+    {
+        return new GMLASFakeDataset();
+    }
+    else
+    {
+        GDALOpenInfo oOpenInfo(
+            (CPLString(szGMLAS_PREFIX) + pszFilename).c_str(), GA_ReadOnly );
+        OGRGMLASDataSource* poOutDS = new OGRGMLASDataSource();
+        if( !poOutDS->Open(  &oOpenInfo ) )
+        {
+            delete poOutDS;
+            poOutDS = NULL;
+        }
+        return poOutDS;
+    }
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlasxlinkresolver.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlasxlinkresolver.cpp
new file mode 100644
index 0000000..fdb3820
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlasxlinkresolver.cpp
@@ -0,0 +1,312 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+
+#include "cpl_http.h"
+
+#include <time.h>
+
+CPL_CVSID("$Id: ogrgmlasxlinkresolver.cpp 36334 2016-11-20 15:42:08Z rouault $");
+
+/************************************************************************/
+/*                         GMLASXLinkResolver()                         */
+/************************************************************************/
+
+GMLASXLinkResolver::GMLASXLinkResolver() :
+    m_nGlobalResolutionTime(0),
+    m_nMaxRAMCacheSize(atoi(CPLGetConfigOption("GMLAS_XLINK_RAM_CACHE_SIZE",
+                                               "10000000"))),
+    m_nCurrentRAMCacheSize(0)
+{
+}
+
+/************************************************************************/
+/*                             SetConf()                                */
+/************************************************************************/
+
+void GMLASXLinkResolver::SetConf( const GMLASXLinkResolutionConf& oConf )
+{
+    m_oConf = oConf;
+    SetCacheDirectory(m_oConf.m_osCacheDirectory);
+}
+
+/************************************************************************/
+/*                          FetchRawContent()                           */
+/************************************************************************/
+
+CPLString GMLASXLinkResolver::FetchRawContent(const CPLString& osURL,
+                                              const char* pszHeaders)
+{
+    char** papszOptions = NULL;
+    if( m_oConf.m_nMaxGlobalResolutionTime > 0 &&
+        m_nGlobalResolutionTime > m_oConf.m_nMaxGlobalResolutionTime )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Maximum global resolution time has been reached. "
+                 "No remote resource will be fetched");
+        return CPLString();
+    }
+    if( m_oConf.m_nTimeOut > 0 || m_oConf.m_nMaxGlobalResolutionTime > 0 )
+    {
+        int nTimeout = m_oConf.m_nTimeOut;
+        if( m_oConf.m_nTimeOut > 0 && m_oConf.m_nMaxGlobalResolutionTime > 0 )
+        {
+            // Select the minimum between the individual timeout and the
+            // remaining time granted by the max global resolution time.
+            int nRemaining = m_oConf.m_nMaxGlobalResolutionTime -
+                             m_nGlobalResolutionTime;
+            if( nRemaining < nTimeout )
+                nTimeout = nRemaining;
+        }
+        else if( m_oConf.m_nMaxGlobalResolutionTime > 0 )
+        {
+            nTimeout = m_oConf.m_nMaxGlobalResolutionTime -
+                       m_nGlobalResolutionTime;
+        }
+        papszOptions = CSLSetNameValue(papszOptions, "TIMEOUT",
+                                       CPLSPrintf("%d", nTimeout));
+    }
+    if( m_oConf.m_nMaxFileSize > 0 )
+    {
+        papszOptions = CSLSetNameValue(papszOptions, "MAX_FILE_SIZE",
+                                       CPLSPrintf("%d", m_oConf.m_nMaxFileSize));
+    }
+    if( !m_oConf.m_osProxyServerPort.empty() )
+    {
+        papszOptions = CSLSetNameValue(papszOptions, "PROXY",
+                                       m_oConf.m_osProxyServerPort);
+    }
+    if( !m_oConf.m_osProxyUserPassword.empty() )
+    {
+        papszOptions = CSLSetNameValue(papszOptions, "PROXYUSERPWD",
+                                       m_oConf.m_osProxyUserPassword);
+    }
+    if( !m_oConf.m_osProxyAuth.empty() )
+    {
+        papszOptions = CSLSetNameValue(papszOptions, "PROXYAUTH",
+                                       m_oConf.m_osProxyAuth);
+    }
+    if( pszHeaders != NULL )
+    {
+        papszOptions = CSLSetNameValue(papszOptions, "HEADERS",
+                                       pszHeaders);
+    }
+    time_t nTimeStart = time(NULL);
+    CPLHTTPResult* psResult = CPLHTTPFetch(osURL, papszOptions);
+    time_t nTimeStop = time(NULL);
+    m_nGlobalResolutionTime += static_cast<int>(nTimeStop - nTimeStart);
+    CSLDestroy(papszOptions);
+    if( psResult == NULL )
+        return CPLString();
+
+    if( psResult->nStatus != 0 ||
+        psResult->pabyData == NULL )
+    {
+        CPLHTTPDestroyResult(psResult);
+        return CPLString();
+    }
+
+    CPLString osResult;
+    osResult.assign( reinterpret_cast<char*>(psResult->pabyData),
+                     psResult->nDataLen );
+    CPLHTTPDestroyResult(psResult);
+    return osResult;
+}
+
+/************************************************************************/
+/*                           GetRawContent()                            */
+/************************************************************************/
+
+CPLString GMLASXLinkResolver::GetRawContent(const CPLString& osURL,
+                                            const char* pszHeaders,
+                                            bool bAllowRemoteDownload,
+                                            bool bCacheResults)
+{
+    bool bDiskCacheAvailable = false;
+    if( !m_osCacheDirectory.empty() &&
+        RecursivelyCreateDirectoryIfNeeded() )
+    {
+        bDiskCacheAvailable = true;
+
+        CPLString osCachedFileName(GetCachedFilename(osURL));
+        VSILFILE* fp = NULL;
+        if( !m_bRefresh ||
+            m_aoSetRefreshedFiles.find(osCachedFileName) !=
+                                            m_aoSetRefreshedFiles.end() )
+        {
+            fp = VSIFOpenL( osCachedFileName, "rb");
+        }
+        if( fp != NULL )
+        {
+            CPLDebug("GMLAS", "Use cached %s", osCachedFileName.c_str());
+            GByte* pabyRet = NULL;
+            vsi_l_offset nSize = 0;
+            CPLString osContent;
+            if( VSIIngestFile( fp, NULL, &pabyRet, &nSize, -1 ) )
+            {
+                osContent.assign( reinterpret_cast<const char*>(pabyRet),
+                                  static_cast<size_t>(nSize) );
+            }
+            VSIFree(pabyRet);
+            VSIFCloseL(fp);
+            return osContent;
+        }
+        else if( bAllowRemoteDownload )
+        {
+            if( m_bRefresh )
+                m_aoSetRefreshedFiles.insert(osCachedFileName);
+        }
+        else
+        {
+            CPLDebug("GMLAS",
+                     "Could not find locally cached %s, and not allowed to"
+                     "download it",
+                     osURL.c_str());
+            return CPLString();
+        }
+    }
+
+    // Check memory cache first
+    {
+        std::map<CPLString,CPLString>::const_iterator oIter =
+            m_oMapURLToContent.find(osURL);
+        if( oIter != m_oMapURLToContent.end() )
+            return oIter->second;
+    }
+
+    const CPLString osContent(FetchRawContent(osURL, pszHeaders));
+    // Cache to disk if possible
+    if( bDiskCacheAvailable && bCacheResults && !osContent.empty() )
+    {
+        CPLString osCachedFileName(GetCachedFilename(osURL));
+        CPLString osTmpfilename( osCachedFileName + ".tmp" );
+        VSILFILE* fpTemp = VSIFOpenL( osTmpfilename, "wb" );
+        if( fpTemp != NULL )
+        {
+            const bool bSuccess = VSIFWriteL( osContent.data(),
+                                              osContent.size(), 1,
+                                              fpTemp ) == 1;
+            VSIFCloseL(fpTemp);
+            if( bSuccess )
+                VSIRename( osTmpfilename, osCachedFileName );
+        }
+    }
+    // Otherwise to RAM
+    else if( !osContent.empty() && osContent.size() < m_nMaxRAMCacheSize )
+    {
+        // If cache is going to be saturated, evict larger objects first
+        while( osContent.size() + m_nCurrentRAMCacheSize > m_nMaxRAMCacheSize )
+        {
+            std::map<size_t, std::vector<CPLString> >::reverse_iterator oIter =
+                m_oMapFileSizeToURLs.rbegin();
+            const size_t nSizeToEvict = oIter->first;
+            m_nCurrentRAMCacheSize -= nSizeToEvict;
+            const CPLString osURLToEvict(oIter->second.front());
+            m_oMapURLToContent.erase(osURLToEvict);
+            oIter->second.erase(oIter->second.begin());
+            if( oIter->second.empty() )
+                m_oMapFileSizeToURLs.erase( nSizeToEvict );
+        }
+        m_oMapURLToContent[osURL] = osContent;
+        m_oMapFileSizeToURLs[osContent.size()].push_back(osURL);
+        m_nCurrentRAMCacheSize += osContent.size();
+    }
+    return osContent;
+}
+
+/************************************************************************/
+/*                     IsRawContentResolutionEnabled()                  */
+/************************************************************************/
+
+bool GMLASXLinkResolver::IsRawContentResolutionEnabled() const
+{
+    return m_oConf.m_bDefaultResolutionEnabled &&
+           m_oConf.m_eDefaultResolutionMode ==
+                                        GMLASXLinkResolutionConf::RawContent;
+}
+
+/************************************************************************/
+/*                      GetMatchingResolutionRule()                      */
+/************************************************************************/
+
+int GMLASXLinkResolver::GetMatchingResolutionRule(const CPLString& osURL) const
+{
+    for(size_t i = 0; i < m_oConf.m_aoURLSpecificRules.size(); ++i )
+    {
+        if( osURL.compare(0,
+                          m_oConf.m_aoURLSpecificRules[i].m_osURLPrefix.size(),
+                          m_oConf.m_aoURLSpecificRules[i].m_osURLPrefix) == 0 )
+        {
+            return static_cast<int>(i);
+        }
+    }
+
+    // No match
+    return -1;
+}
+
+/************************************************************************/
+/*                           GetRawContent()                            */
+/************************************************************************/
+
+CPLString GMLASXLinkResolver::GetRawContent(const CPLString& osURL)
+{
+    return GetRawContent(osURL,
+                         NULL,
+                         m_oConf.m_bDefaultAllowRemoteDownload,
+                         m_oConf.m_bDefaultCacheResults);
+}
+
+/************************************************************************/
+/*                         GetRawContentForRule()                       */
+/************************************************************************/
+
+CPLString GMLASXLinkResolver::GetRawContentForRule(const CPLString& osURL,
+                                                   int nIdxRule)
+{
+    const GMLASXLinkResolutionConf::URLSpecificResolution& oRule(
+                                    m_oConf.m_aoURLSpecificRules[nIdxRule] );
+
+    CPLString osHeaders;
+    for( size_t i=0; i< oRule.m_aosNameValueHTTPHeaders.size(); ++i )
+    {
+        if( !osHeaders.empty() )
+            osHeaders += "\r\n";
+        osHeaders += oRule.m_aosNameValueHTTPHeaders[i].first;
+        osHeaders += ": ";
+        osHeaders += oRule.m_aosNameValueHTTPHeaders[i].second;
+    }
+    return GetRawContent(osURL,
+                         osHeaders.empty() ? NULL : osHeaders.c_str(),
+                         oRule.m_bAllowRemoteDownload,
+                         oRule.m_bCacheResults);
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlasxpatchmatcher.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlasxpatchmatcher.cpp
new file mode 100644
index 0000000..30e795c
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlasxpatchmatcher.cpp
@@ -0,0 +1,236 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+
+CPL_CVSID("$Id: ogrgmlasxpatchmatcher.cpp 36427 2016-11-22 12:56:01Z rouault $");
+
+/************************************************************************/
+/*                          GMLASXPathMatcher()                         */
+/************************************************************************/
+
+GMLASXPathMatcher::GMLASXPathMatcher()
+{
+}
+
+/************************************************************************/
+/*                         ~GMLASXPathMatcher()                         */
+/************************************************************************/
+
+GMLASXPathMatcher::~GMLASXPathMatcher()
+{
+}
+
+/************************************************************************/
+/*                           SetRefXPaths()                             */
+/************************************************************************/
+
+void    GMLASXPathMatcher::SetRefXPaths(const std::map<CPLString, CPLString>&
+                                                oMapPrefixToURIReferenceXPaths,
+                                         const std::vector<CPLString>&
+                                                aosReferenceXPaths)
+{
+    m_oMapPrefixToURIReferenceXPaths = oMapPrefixToURIReferenceXPaths;
+    m_aosReferenceXPathsUncompiled = aosReferenceXPaths;
+}
+
+/************************************************************************/
+/*                     SetDocumentMapURIToPrefix()                      */
+/************************************************************************/
+
+void    GMLASXPathMatcher::SetDocumentMapURIToPrefix(
+                        const std::map<CPLString,CPLString>& oMapURIToPrefix )
+{
+    m_aosReferenceXPaths.clear();
+
+    // Split each reference XPath into its components
+    for(size_t i = 0; i < m_aosReferenceXPathsUncompiled.size(); ++i )
+    {
+        const CPLString& osXPath( m_aosReferenceXPathsUncompiled[i] );
+
+        std::vector<XPathComponent> oVector;
+
+        size_t iPos = 0;
+        bool bDirectChild = false;
+        if( osXPath.size() >= 2 &&
+            osXPath[0] == '/' && osXPath[1] == '/' )
+        {
+            iPos += 2;
+        }
+        else if( osXPath.size() >= 1 && osXPath[0] == '/' )
+        {
+            iPos += 1;
+            bDirectChild = true;
+        }
+
+        while( iPos < osXPath.size() )
+        {
+            size_t iPosNextSlash = osXPath.find('/', iPos);
+
+            if( iPos == iPosNextSlash )
+            {
+                bDirectChild = false;
+                iPos ++;
+                continue;
+            }
+
+            CPLString osCurNode;
+            if( iPosNextSlash == std::string::npos )
+                osCurNode.assign(osXPath, iPos, std::string::npos);
+            else
+                osCurNode.assign(osXPath, iPos, iPosNextSlash - iPos);
+
+            // Translate the configuration prefix to the equivalent in
+            // this current schema
+            size_t iPosColumn = osCurNode.find(':');
+            if( iPosColumn != std::string::npos )
+            {
+                bool bIsAttr = ( osCurNode[0] == '@' );
+                CPLString osPrefix;
+                CPLString osLocalname;
+                osPrefix.assign(osCurNode,
+                                bIsAttr ? 1 : 0,
+                                iPosColumn - (bIsAttr ? 1 : 0));
+                osLocalname.assign(osCurNode, iPosColumn+1,
+                                std::string::npos);
+
+                std::map<CPLString, CPLString>::const_iterator oIter =
+                    m_oMapPrefixToURIReferenceXPaths.find(osPrefix);
+                if( oIter != m_oMapPrefixToURIReferenceXPaths.end() )
+                {
+                    const CPLString& osURI( oIter->second );
+                    oIter = oMapURIToPrefix.find( osURI );
+                    if( oIter == oMapURIToPrefix.end() )
+                        break;
+                    osPrefix.assign(oIter->second);
+                }
+
+                osCurNode.clear();
+                if( bIsAttr )
+                    osCurNode.append(1, '@');
+                osCurNode.append(osPrefix);
+                osCurNode.append(1, ':');
+                osCurNode.append(osLocalname);
+            }
+
+            XPathComponent comp;
+            comp.m_osValue = osCurNode;
+            comp.m_bDirectChild = bDirectChild;
+            oVector.push_back(comp);
+
+            if( iPosNextSlash == std::string::npos )
+                iPos = osXPath.size();
+            else
+                iPos = iPosNextSlash + 1;
+
+            bDirectChild = true;
+        }
+
+        if ( iPos < osXPath.size() )
+            oVector.clear();
+        m_aosReferenceXPaths.push_back(oVector);
+    }
+}
+
+/************************************************************************/
+/*                         MatchesRefXPath()                            */
+/************************************************************************/
+
+// This is a performance critical function, especially on geosciml schemas,
+// and we make careful to not do any string copy or other memory allocation
+// in it.
+bool GMLASXPathMatcher::MatchesRefXPath(
+                        const CPLString& osXPath,
+                        const std::vector<XPathComponent>& oRefXPath)
+{
+    size_t iPos = 0;
+    size_t iIdxInRef = 0;
+
+    bool bDirectChild = oRefXPath[0].m_bDirectChild;
+    while( iPos < osXPath.size() && iIdxInRef < oRefXPath.size() )
+    {
+        bDirectChild = oRefXPath[iIdxInRef].m_bDirectChild;
+        size_t iPosNextSlash = osXPath.find('/', iPos);
+
+        bool bNodeMatch;
+        if( iPosNextSlash == std::string::npos )
+        {
+            bNodeMatch = osXPath.compare(iPos, std::string::npos,
+                                         oRefXPath[iIdxInRef].m_osValue) == 0;
+        }
+        else
+        {
+            bNodeMatch = osXPath.compare(iPos, iPosNextSlash - iPos,
+                                         oRefXPath[iIdxInRef].m_osValue) == 0;
+        }
+
+        if( !bNodeMatch )
+        {
+            if( bDirectChild )
+                return false;
+
+            if( iPosNextSlash == std::string::npos )
+                return false;
+            iPos = iPosNextSlash + 1;
+            continue;
+        }
+
+        if( iPosNextSlash == std::string::npos )
+            iPos = osXPath.size();
+        else
+            iPos = iPosNextSlash + 1;
+        iIdxInRef ++;
+        bDirectChild = true;
+    }
+
+    return (!bDirectChild || iPos == osXPath.size()) &&
+            iIdxInRef == oRefXPath.size();
+}
+
+/************************************************************************/
+/*                         MatchesRefXPath()                            */
+/************************************************************************/
+
+bool GMLASXPathMatcher::MatchesRefXPath(
+                            const CPLString& osXPath,
+                            CPLString& osOutMatchedXPath) const
+{
+    for(size_t i = 0; i < m_aosReferenceXPaths.size(); ++i )
+    {
+        if( !m_aosReferenceXPaths[i].empty() &&
+            MatchesRefXPath(osXPath, m_aosReferenceXPaths[i]) )
+        {
+            osOutMatchedXPath = m_aosReferenceXPathsUncompiled[i];
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/ogr/ogrsf_frmts/gmlas/ogrgmlasxsdcache.cpp b/ogr/ogrsf_frmts/gmlas/ogrgmlasxsdcache.cpp
new file mode 100644
index 0000000..b3f786e
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/ogrgmlasxsdcache.cpp
@@ -0,0 +1,250 @@
+/******************************************************************************
+ * Project:  OGR
+ * Purpose:  OGRGMLASDriver implementation
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Initial development funded by the European Earth observation programme
+ * Copernicus
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+// Must be first for DEBUG_BOOL case
+#include "ogr_gmlas.h"
+
+#include "cpl_sha256.h"
+
+CPL_CVSID("$Id: ogrgmlasxsdcache.cpp 35911 2016-10-24 15:03:26Z goatbar $");
+
+/************************************************************************/
+/*                         GMLASResourceCache()                         */
+/************************************************************************/
+
+GMLASResourceCache::GMLASResourceCache()
+    : m_bHasCheckedCacheDirectory(false)
+    , m_bRefresh(false)
+    , m_bAllowDownload(true)
+{
+}
+
+/************************************************************************/
+/*                        ~GMLASResourceCache()                         */
+/************************************************************************/
+
+GMLASResourceCache::~GMLASResourceCache()
+{
+}
+
+/************************************************************************/
+/*                         SetCacheDirectory()                          */
+/************************************************************************/
+
+void GMLASResourceCache::SetCacheDirectory(const CPLString& osCacheDirectory)
+{
+    m_osCacheDirectory = osCacheDirectory;
+}
+
+/************************************************************************/
+/*                     RecursivelyCreateDirectoryIfNeeded()             */
+/************************************************************************/
+
+bool GMLASResourceCache::RecursivelyCreateDirectoryIfNeeded(
+                                                const CPLString& osDirname)
+{
+    VSIStatBufL sStat;
+    if( VSIStatL(osDirname, &sStat) == 0 )
+    {
+        return true;
+    }
+
+    CPLString osParent = CPLGetDirname(osDirname);
+    if( !osParent.empty() && osParent != "." )
+    {
+        if( !RecursivelyCreateDirectoryIfNeeded(osParent) )
+            return false;
+    }
+    return VSIMkdir( osDirname, 0755 ) == 0;
+}
+
+bool GMLASResourceCache::RecursivelyCreateDirectoryIfNeeded()
+{
+    if( !m_bHasCheckedCacheDirectory )
+    {
+        m_bHasCheckedCacheDirectory = true;
+        if( !RecursivelyCreateDirectoryIfNeeded(m_osCacheDirectory) )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Cannot create %s", m_osCacheDirectory.c_str());
+            m_osCacheDirectory.clear();
+            return false;
+        }
+    }
+    return true;
+}
+
+/************************************************************************/
+/*                        GetCachedFilename()                           */
+/************************************************************************/
+
+CPLString GMLASResourceCache::GetCachedFilename(const CPLString& osResource)
+{
+    CPLString osLaunderedName(osResource);
+    if( osLaunderedName.find("/vsicurl_streaming/") == 0 )
+        osLaunderedName = osLaunderedName.substr(
+                                strlen("/vsicurl_streaming/") );
+    if( osLaunderedName.find("http://") == 0 )
+        osLaunderedName = osLaunderedName.substr( strlen("http://") );
+    else if( osLaunderedName.find("https://") == 0 )
+        osLaunderedName = osLaunderedName.substr( strlen("https://") );
+    for(size_t i=0; i<osLaunderedName.size(); i++)
+    {
+        if( !isalnum(osLaunderedName[i]) && osLaunderedName[i] != '.' )
+            osLaunderedName[i] = '_';
+    }
+
+    // If filename is too long, then truncate it and put a hash at the end
+    if( osLaunderedName.size() >= 255 - strlen(".tmp") )
+    {
+        GByte abyHash[CPL_SHA256_HASH_SIZE];
+        CPL_SHA256(osResource, osResource.size(), abyHash);
+        char* pszHash = CPLBinaryToHex(CPL_SHA256_HASH_SIZE, abyHash);
+        osLaunderedName.resize(255 - strlen(".tmp") -  2 * CPL_SHA256_HASH_SIZE);
+        osLaunderedName += pszHash;
+        CPLFree(pszHash);
+        CPLDebug("GMLAS", "Cached filename truncated to %s",
+                    osLaunderedName.c_str());
+    }
+
+    return CPLFormFilename( m_osCacheDirectory, osLaunderedName, NULL );
+}
+
+/************************************************************************/
+/*                          GMLASXSDCache()                             */
+/************************************************************************/
+
+GMLASXSDCache::GMLASXSDCache()
+{
+}
+
+/************************************************************************/
+/*                         ~GMLASXSDCache()                             */
+/************************************************************************/
+
+GMLASXSDCache::~GMLASXSDCache()
+{
+}
+/************************************************************************/
+/*                               Open()                                 */
+/************************************************************************/
+
+VSILFILE* GMLASXSDCache::Open( const CPLString& osResource,
+                               const CPLString& osBasePath,
+                               CPLString& osOutFilename )
+{
+    osOutFilename = osResource;
+    if( osResource.find("http://") == 0 ||
+        osResource.find("https://") == 0 )
+    {
+        osOutFilename = "/vsicurl_streaming/" + osResource;
+    }
+    else if( CPLIsFilenameRelative( osResource ) && !osResource.empty() )
+    {
+        /* Transform a/b + ../c --> a/c */
+        CPLString osResourceModified(osResource);
+        CPLString osBasePathModified(osBasePath);
+        while( (osResourceModified.find("../") == 0 ||
+                osResourceModified.find("..\\") == 0) &&
+               !osBasePathModified.empty() )
+        {
+            osBasePathModified = CPLGetDirname(osBasePathModified);
+            osResourceModified = osResourceModified.substr(3);
+        }
+
+        osOutFilename = CPLFormFilename(osBasePathModified,
+                                        osResourceModified, NULL);
+    }
+
+    CPLDebug("GMLAS", "Resolving %s (%s) to %s",
+                osResource.c_str(),
+                osBasePath.c_str(),
+                osOutFilename.c_str());
+
+    VSILFILE* fp = NULL;
+    if( !m_osCacheDirectory.empty() &&
+        osOutFilename.find("/vsicurl_streaming/") == 0 &&
+        RecursivelyCreateDirectoryIfNeeded() )
+    {
+        CPLString osCachedFileName(GetCachedFilename(osOutFilename));
+        if( !m_bRefresh ||
+            m_aoSetRefreshedFiles.find(osCachedFileName) !=
+                                            m_aoSetRefreshedFiles.end() )
+        {
+            fp = VSIFOpenL( osCachedFileName, "rb");
+        }
+        if( fp != NULL )
+        {
+            CPLDebug("GMLAS", "Use cached %s", osCachedFileName.c_str());
+        }
+        else if( m_bAllowDownload )
+        {
+            if( m_bRefresh )
+                m_aoSetRefreshedFiles.insert(osCachedFileName);
+
+            CPLString osTmpfilename( osCachedFileName + ".tmp" );
+            if( CPLCopyFile( osTmpfilename, osOutFilename) == 0 )
+            {
+                // Due to the caching done by /vsicurl_streaming/, if the
+                // web server is no longer available but was before in the
+                // same process, then file opening will succeed. Hence we
+                // check that the downloaded file is not 0. This will only
+                // happen in practice with the unit tests.
+                VSIStatBufL sStat;
+                if( VSIStatL(osTmpfilename, &sStat) == 0 &&
+                    sStat.st_size != 0 )
+                {
+                    VSIRename( osTmpfilename, osCachedFileName );
+                    fp = VSIFOpenL(osCachedFileName, "rb");
+                }
+                else
+                {
+                    VSIUnlink(osTmpfilename);
+                }
+            }
+        }
+    }
+    else
+    {
+        if( m_bAllowDownload ||
+            osOutFilename.find("/vsicurl_streaming/") != 0 )
+        {
+            fp = VSIFOpenL(osOutFilename, "rb");
+        }
+    }
+
+    if( fp == NULL )
+    {
+        CPLError(CE_Failure, CPLE_FileIO,
+                 "Cannot resolve %s", osResource.c_str());
+    }
+
+    return fp;
+}
diff --git a/ogr/ogrsf_frmts/gmlas/xercesc_headers.h b/ogr/ogrsf_frmts/gmlas/xercesc_headers.h
new file mode 100644
index 0000000..6e61297
--- /dev/null
+++ b/ogr/ogrsf_frmts/gmlas/xercesc_headers.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ * Project:  GDAL
+ * Purpose:  Includes Xerces-C headers
+ * Author:   Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef XERCESC_HEADERS_H
+#define XERCESC_HEADERS_H
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+// This works around problems with math.h on some platforms #defining INFINITY
+#ifdef INFINITY
+#undef  INFINITY
+#define INFINITY INFINITY_XERCES
+#endif
+
+#include <xercesc/framework/XMLGrammarPoolImpl.hpp>
+#include <xercesc/framework/psvi/XSAnnotation.hpp>
+#include <xercesc/framework/psvi/XSAttributeDeclaration.hpp>
+#include <xercesc/framework/psvi/XSAttributeGroupDefinition.hpp>
+#include <xercesc/framework/psvi/XSAttributeUse.hpp>
+#include <xercesc/framework/psvi/XSComplexTypeDefinition.hpp>
+#include <xercesc/framework/psvi/XSElementDeclaration.hpp>
+#include <xercesc/framework/psvi/XSFacet.hpp>
+#include <xercesc/framework/psvi/XSModel.hpp>
+#include <xercesc/framework/psvi/XSModelGroup.hpp>
+#include <xercesc/framework/psvi/XSModelGroupDefinition.hpp>
+#include <xercesc/framework/psvi/XSNamespaceItem.hpp>
+#include <xercesc/framework/psvi/XSParticle.hpp>
+#include <xercesc/framework/psvi/XSSimpleTypeDefinition.hpp>
+#include <xercesc/framework/psvi/XSTypeDefinition.hpp>
+#include <xercesc/framework/psvi/XSWildcard.hpp>
+#include <xercesc/sax/InputSource.hpp>
+#include <xercesc/sax2/Attributes.hpp>
+#include <xercesc/sax2/DefaultHandler.hpp>
+#include <xercesc/sax2/ContentHandler.hpp>
+#include <xercesc/sax2/SAX2XMLReader.hpp>
+#include <xercesc/sax2/XMLReaderFactory.hpp>
+#include <xercesc/util/BinInputStream.hpp>
+#include <xercesc/util/PlatformUtils.hpp>
+#include <xercesc/util/PSVIUni.hpp>
+
+#ifdef XERCES_CPP_NAMESPACE_USE
+XERCES_CPP_NAMESPACE_USE
+#endif
+
+#endif /* XERCESC_HEADERS_H */
diff --git a/ogr/ogrsf_frmts/gmt/ogr_gmt.h b/ogr/ogrsf_frmts/gmt/ogr_gmt.h
index 0b45abf..a855d2a 100644
--- a/ogr/ogrsf_frmts/gmt/ogr_gmt.h
+++ b/ogr/ogrsf_frmts/gmt/ogr_gmt.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mem.h 10645 2007-01-18 02:22:39Z warmerdam $
+ * $Id: ogr_gmt.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions within the OGR GMT driver.
@@ -54,39 +54,39 @@ class OGRGmtLayer : public OGRLayer
 
     VSILFILE           *fp;
 
-    int                 ReadLine();
+    bool                ReadLine();
     CPLString           osLine;
     char              **papszKeyedValues;
 
-    int                 ScanAheadForHole();
-    int                 NextIsFeature();
+    bool                ScanAheadForHole();
+    bool                NextIsFeature();
 
     OGRFeature         *GetNextRawFeature();
 
-    OGRErr              WriteGeometry( OGRGeometryH hGeom, int bHaveAngle );
+    OGRErr              WriteGeometry( OGRGeometryH hGeom, bool bHaveAngle );
     OGRErr              CompleteHeader( OGRGeometry * );
 
   public:
-    int                 bValidFile;
+    bool                bValidFile;
 
                         OGRGmtLayer( const char *pszFilename, int bUpdate );
-                        ~OGRGmtLayer();
+                        virtual ~OGRGmtLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -104,20 +104,20 @@ class OGRGmtDataSource : public OGRDataSource
 
   public:
                         OGRGmtDataSource();
-                        ~OGRGmtDataSource();
+                        virtual ~OGRGmtDataSource();
 
     int                 Open( const char *pszFilename, int bUpdate );
     int                 Create( const char *pszFilename, char **papszOptions );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
     virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
-    int                 TestCapability( const char * );
+                                      char ** = NULL ) override;
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -127,16 +127,15 @@ class OGRGmtDataSource : public OGRDataSource
 class OGRGmtDriver : public OGRSFDriver
 {
   public:
-                ~OGRGmtDriver();
+                virtual ~OGRGmtDriver();
 
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
-                                             char ** = NULL );
+                                             char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
-
 #endif /* ndef OGRGMT_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp b/ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp
index 9bf9db7..5fa16f5 100644
--- a/ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp
+++ b/ogr/ogrsf_frmts/gmt/ogrgmtdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgmtdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGmtDataSource class.
@@ -31,7 +30,7 @@
 #include "cpl_string.h"
 #include "ogr_gmt.h"
 
-CPL_CVSID("$Id: ogrgmtdatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogrgmtdatasource.cpp 35008 2016-08-09 11:20:52Z goatbar $");
 
 /************************************************************************/
 /*                          OGRGmtDataSource()                          */
@@ -111,7 +110,7 @@ OGRGmtDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Establish the geometry type.  Note this logic                   */
 /* -------------------------------------------------------------------- */
-    const char *pszGeom;
+    const char *pszGeom = NULL;
 
     switch( wkbFlatten(eType) )
     {
diff --git a/ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp b/ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp
index 1d0fd90..4198720 100644
--- a/ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp
+++ b/ogr/ogrsf_frmts/gmt/ogrgmtdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmemdriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGmtDriver class.
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmemdriver.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogrgmtdriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                          ~OGRGmtDriver()                           */
@@ -83,7 +82,6 @@ OGRDataSource *OGRGmtDriver::CreateDataSource( const char * pszName,
     if( poDS->Create( pszName, papszOptions ) )
         return poDS;
 
-
     delete poDS;
     return NULL;
 }
diff --git a/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp b/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
index 5d9e58e..3cc71b2 100644
--- a/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
+++ b/ogr/ogrsf_frmts/gmt/ogrgmtlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgmtlayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGmtLayer class.
@@ -31,7 +30,9 @@
 #include "cpl_conv.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgmtlayer.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrgmtlayer.cpp 36983 2016-12-20 20:07:14Z rouault $");
 
 /************************************************************************/
 /*                            OGRGmtLayer()                             */
@@ -46,18 +47,10 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdateIn ) :
     bHeaderComplete(CPL_TO_BOOL(!bUpdate)),
     bRegionComplete(false),
     nRegionOffset(0),
+    fp(VSIFOpenL( pszFilename, (bUpdateIn ? "r+" : "r" ))),
     papszKeyedValues(NULL),
-    bValidFile(FALSE)
+    bValidFile(false)
 {
-
-/* -------------------------------------------------------------------- */
-/*      Open file.                                                      */
-/* -------------------------------------------------------------------- */
-    if( bUpdate )
-        fp = VSIFOpenL( pszFilename, "r+" );
-    else
-        fp = VSIFOpenL( pszFilename, "r" );
-
     if( fp == NULL )
         return;
 
@@ -77,7 +70,7 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdateIn ) :
     {
         if( strstr( osLine, "FEATURE_DATA" ) )
         {
-            bHeaderComplete = TRUE;
+            bHeaderComplete = true;
             ReadLine();
             break;
         }
@@ -100,7 +93,7 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdateIn ) :
             if( papszKeyedValues[iKey][0] == 'J' )
             {
                 CPLString osArg = papszKeyedValues[iKey] + 2;
-                if( osArg[0] == '"' && osArg[osArg.length()-1] == '"' )
+                if( osArg[0] == '"' && osArg.back() == '"' )
                 {
                     osArg = osArg.substr(1,osArg.length()-2);
                     char *pszArg = CPLUnescapeString(osArg, NULL,
@@ -192,7 +185,7 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdateIn ) :
             sRegion.MaxY = CPLAtofM(papszTokens[3]);
         }
 
-        bRegionComplete = TRUE;
+        bRegionComplete = true;
 
         CSLDestroy( papszTokens );
     }
@@ -206,7 +199,7 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdateIn ) :
                                                    TRUE, TRUE );
         char **papszFT = CSLTokenizeStringComplex( osFieldTypes, "|",
                                                    TRUE, TRUE );
-        const int nFieldCount = MAX(CSLCount(papszFN),CSLCount(papszFT));
+        const int nFieldCount = std::max(CSLCount(papszFN), CSLCount(papszFT));
 
         for( int iField = 0; iField < nFieldCount; iField++ )
         {
@@ -234,7 +227,7 @@ OGRGmtLayer::OGRGmtLayer( const char * pszFilename, int bUpdateIn ) :
         CSLDestroy( papszFT );
     }
 
-    bValidFile = TRUE;
+    bValidFile = true;
 }
 
 /************************************************************************/
@@ -288,7 +281,7 @@ OGRGmtLayer::~OGRGmtLayer()
 /*      papszKeyedValues.                                               */
 /************************************************************************/
 
-int OGRGmtLayer::ReadLine()
+bool OGRGmtLayer::ReadLine()
 
 {
 /* -------------------------------------------------------------------- */
@@ -306,7 +299,7 @@ int OGRGmtLayer::ReadLine()
 /* -------------------------------------------------------------------- */
     const char *pszLine = CPLReadLineL( fp );
     if( pszLine == NULL )
-        return FALSE; // end of file.
+        return false; // end of file.
 
     osLine = pszLine;
 
@@ -315,7 +308,7 @@ int OGRGmtLayer::ReadLine()
 /* -------------------------------------------------------------------- */
 
     if( osLine[0] != '#' || osLine.find_first_of('@') == std::string::npos )
-        return TRUE;
+        return true;
 
     for( size_t i = 0; i < osLine.length(); i++ )
     {
@@ -323,8 +316,8 @@ int OGRGmtLayer::ReadLine()
         {
             bool bInQuotes = false;
 
-            size_t iValEnd;
-            for( iValEnd = i+2; iValEnd < osLine.length(); iValEnd++ )
+            size_t iValEnd = i+2;  // Used after for.
+            for( ; iValEnd < osLine.length(); iValEnd++ )
             {
                 if( !bInQuotes && isspace((unsigned char)osLine[iValEnd]) )
                     break;
@@ -354,7 +347,7 @@ int OGRGmtLayer::ReadLine()
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -376,11 +369,11 @@ void OGRGmtLayer::ResetReading()
 /*                          ScanAheadForHole()                          */
 /*                                                                      */
 /*      Scan ahead to see if the next geometry is a hole.  If so        */
-/*      return TRUE, otherwise seek back to where we were and return    */
-/*      FALSE.                                                          */
+/*      return true, otherwise seek back to where we were and return    */
+/*      false.                                                          */
 /************************************************************************/
 
-int OGRGmtLayer::ScanAheadForHole()
+bool OGRGmtLayer::ScanAheadForHole()
 
 {
     const CPLString osSavedLine = osLine;
@@ -389,7 +382,7 @@ int OGRGmtLayer::ScanAheadForHole()
     while( ReadLine() && osLine[0] == '#' )
     {
         if( papszKeyedValues != NULL && papszKeyedValues[0][0] == 'H' )
-            return TRUE;
+            return true;
     }
 
     VSIFSeekL( fp, nSavedLocation, SEEK_SET );
@@ -399,18 +392,18 @@ int OGRGmtLayer::ScanAheadForHole()
     // assume it does not matter since this method is only called
     // when processing the '>' line.
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                           NextIsFeature()                            */
 /*                                                                      */
-/*      Returns TRUE if the next line is a feature attribute line.      */
+/*      Returns true if the next line is a feature attribute line.      */
 /*      This generally indicates the end of a multilinestring or        */
 /*      multipolygon feature.                                           */
 /************************************************************************/
 
-int OGRGmtLayer::NextIsFeature()
+bool OGRGmtLayer::NextIsFeature()
 
 {
     const CPLString osSavedLine = osLine;
@@ -440,7 +433,7 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
 
 {
 #if 0
-    int bMultiVertex =
+    bool bMultiVertex =
         poFeatureDefn->GetGeomType() != wkbPoint
         && poFeatureDefn->GetGeomType() != wkbUnknown;
 #endif
@@ -503,7 +496,7 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
             else if( poFeatureDefn->GetGeomType() == wkbUnknown )
             {
                 poFeatureDefn->SetGeomType( wkbLineString );
-                /* bMultiVertex = TRUE; */
+                // bMultiVertex = true;
             }
         }
         else if( osLine[0] == '#' )
@@ -519,11 +512,11 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
         else
         {
             // Parse point line.
-            double dfX;
-            double dfY;
+            double dfX = 0.0;
+            double dfY = 0.0;
             double dfZ = 0.0;
-            const int nDim
-                = CPLsscanf( osLine, "%lf %lf %lf", &dfX, &dfY, &dfZ );
+            const int nDim =
+                CPLsscanf( osLine, "%lf %lf %lf", &dfX, &dfY, &dfZ );
 
             if( nDim >= 2 )
             {
@@ -568,7 +561,6 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
                         poGeom = new OGRPoint();
                         break;
                     }
-
                 }
 
                 switch( wkbFlatten(poGeom->getGeometryType()) )
@@ -632,7 +624,7 @@ OGRFeature *OGRGmtLayer::GetNextRawFeature()
                   break;
 
                   default:
-                    CPLAssert( FALSE );
+                    CPLAssert( false );
                 }
             }
         }
@@ -797,8 +789,8 @@ OGRErr OGRGmtLayer::CompleteHeader( OGRGeometry *poThisGeom )
 /* -------------------------------------------------------------------- */
     VSIFPrintfL( fp, "# FEATURE_DATA\n" );
 
-    bHeaderComplete = TRUE;
-    bRegionComplete = TRUE; // no feature written, so we know them all!
+    bHeaderComplete = true;
+    bRegionComplete = true; // no feature written, so we know them all!
 
     return OGRERR_NONE;
 }
@@ -890,13 +882,13 @@ OGRErr OGRGmtLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Write Geometry                                                  */
 /* -------------------------------------------------------------------- */
-    return WriteGeometry( reinterpret_cast<OGRGeometryH>(poGeom), TRUE );
+    return WriteGeometry( reinterpret_cast<OGRGeometryH>(poGeom), true );
 }
 
 /************************************************************************/
 /*                           WriteGeometry()                            */
 /*                                                                      */
-/*      Write a geometry to the file.  If bHaveAngle is TRUE it         */
+/*      Write a geometry to the file.  If bHaveAngle is true it         */
 /*      means the angle bracket preceding the point stream has          */
 /*      already been written out.                                       */
 /*                                                                      */
@@ -904,7 +896,7 @@ OGRErr OGRGmtLayer::ICreateFeature( OGRFeature *poFeature )
 /*      simplified access to vertices and children geometries.          */
 /************************************************************************/
 
-OGRErr OGRGmtLayer::WriteGeometry( OGRGeometryH hGeom, int bHaveAngle )
+OGRErr OGRGmtLayer::WriteGeometry( OGRGeometryH hGeom, bool bHaveAngle )
 
 {
 /* -------------------------------------------------------------------- */
@@ -926,7 +918,7 @@ OGRErr OGRGmtLayer::WriteGeometry( OGRGeometryH hGeom, int bHaveAngle )
                 if( !bHaveAngle )
                 {
                     VSIFPrintfL( fp, ">\n" );
-                    bHaveAngle = TRUE;
+                    bHaveAngle = true;
                 }
                 if( iGeom == 0 )
                     VSIFPrintfL( fp, "# @P\n" );
@@ -936,7 +928,7 @@ OGRErr OGRGmtLayer::WriteGeometry( OGRGeometryH hGeom, int bHaveAngle )
 
             eErr = WriteGeometry( OGR_G_GetGeometryRef( hGeom, iGeom ),
                                   bHaveAngle );
-            bHaveAngle = FALSE;
+            bHaveAngle = false;
         }
         return eErr;
     }
diff --git a/ogr/ogrsf_frmts/gpkg/GNUmakefile b/ogr/ogrsf_frmts/gpkg/GNUmakefile
index 0cfc8c0..c149920 100644
--- a/ogr/ogrsf_frmts/gpkg/GNUmakefile
+++ b/ogr/ogrsf_frmts/gpkg/GNUmakefile
@@ -13,6 +13,10 @@ ifeq ($(SQLITE_HAS_COLUMN_METADATA),yes)
 CPPFLAGS +=  -DSQLITE_HAS_COLUMN_METADATA
 endif
 
+ifeq ($(HAVE_RASTERLITE2),yes)
+CPPFLAGS +=  -DHAVE_RASTERLITE2 $(RASTERLITE2_CFLAGS)
+endif
+
 CPPFLAGS := -I.. -I../sqlite -I../../../frmts/mem $(SQLITE_INC) $(CPPFLAGS)
 
 default: $(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/ogr/ogrsf_frmts/gpkg/drv_geopackage.html b/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
index 8241415..d1758f8 100644
--- a/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
+++ b/ogr/ogrsf_frmts/gpkg/drv_geopackage.html
@@ -8,7 +8,8 @@
 <h1>GeoPackage vector</h1>
 
 <p>This driver implements support for access to spatial tables in the
-<a href="http://www.geopackage.org/spec/">OGC GeoPackage format standard</a>.
+<a href="http://www.opengeospatial.org/standards/geopackage">OGC GeoPackage format standard</a>
+(targeting 1.0/1.0.1)
 The GeoPackage standard uses a SQLite database file as a generic container, and the standard defines:
 </p>
 <ul>
@@ -27,8 +28,6 @@ following non-linear geometry types :CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON
 
 <ul>
 <li>GeoPackage only supports one geometry column per table.</li>
-<li>Before GDAL 2.0, the driver did not implement the GeoPackage spatial index extension.</li>
-<li>The core GeoPackage specification does not currently support non-spatial tables, but starting with GDAL 2.0, the driver allows creating and reading such tables via the <a href="geopackage_aspatial.html">Aspatial Support</a> (<code>gdal_aspatial</code>) extension.</li>
 </ul>
 
 <h2>SQL</h2>
@@ -48,6 +47,15 @@ following non-linear geometry types :CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON
   GeoPackage geometries automatically appear as Spatialite geometries after translation by OGR.
 </p>
 
+<p>Starting with GDAL 2.2, the "DROP TABLE layer_name" and "ALTER TABLE layer_name RENAME TO new_layer"
+statements can be used. They will update GeoPackage system tables.</p>
+
+<p>When dropping a table, or removing records from tables, the space they
+occupied is not immediately released and kept in the pool of file pages that
+SQLite may reuse later. If you need to shrink the file to its minimum size,
+you need to issue an explicit "VACUUM" SQL request. Note that this will
+result in a full rewrite of the file.</p>
+
 <h3>SQL functions</h3>
 
 Starting with GDAL 2.0, the following SQL functions, from the GeoPackage specification, are available :
@@ -93,6 +101,23 @@ The driver implements transactions at the database level, per
 <a href="http://trac.osgeo.org/gdal/wiki/rfc54_dataset_transactions">RFC 54</a>
 </p>
 
+<h2>Opening options</h2>
+
+The following open options are available:
+<ul>
+<li><b>LIST_ALL_TABLES</b>=AUTO/YES/NO: (GDAL >=2.2) Whether all tables, including
+those non listed in gpkg_contents, should be listed. Defaults to AUTO.
+If AUTO, all tables including those non linsted in gpkg_contents will be listed,
+except if the aspatial extension is found or a table is registered as 'attributes'
+in gpkg_contents. If YES, all tables including those non linsted in gpkg_contents will be listed,
+in all cases. If NO, only tables registered as 'features', 'attributes' or 'aspatial'
+will be listed.
+</li>
+</ul>
+
+Note: open options are typically specified with "-oo name=value" syntax in
+most OGR utilities, or with the GDALOpenEx() API call.
+
 <h2>Creation Issues</h2>
 
 <p>When creating a new GeoPackage file, the driver will attempt to
@@ -120,6 +145,18 @@ that exceed the maximum allowed width of text fields, and also to "fix" the pass
 to make it a valid UTF-8 string. If "NO" then the value is not truncated nor modified. The default is "NO".<p>
 <li><b>IDENTIFIER</b>=string: (GDAL >=2.0) Identifier of the layer, as put in the contents table.<p>
 <li><b>DESCRIPTION</b>=string: (GDAL >=2.0) Description of the layer, as put in the contents table.<p>
+<li><b>ASPATIAL_VARIANT</b>=GPKG_ATTRIBUTES/OGR_ASPATIAL/NOT_REGISTERED: (GDAL >=2.2) How to register non spatial tables.
+Defaults to GPKG_ATTRIBUTES in GDAL 2.2 or later (behaviour in previous version
+was equivalent to OGR_ASPATIAL).
+Starting with GeoPackage 1.2, non spatial tables are part of the specification.
+They are recorded with data_type="attributes"
+in the gpkg_contents table. This is only compatible of GDAL 2.2 or later.
+Priorly, in OGR 2.0 and 2.1, the "aspatial" extension had
+been developed for similar purposes, so if selecting OGR_ASPATIAL, non spatial
+tables will be recorded with data_type="aspatial" and the "aspatial" extension
+was declared in the gpkg_extensions table. It is also possible to use the
+NOT_REGISTERED option, in which case the non spatial table is not registered at
+all in any GeoPackage system tables.<p>
 </ul>
 
 <h3>Metadata</h3>
@@ -148,13 +185,50 @@ although it can be through direct SQL commands).</p>
 domain can be used in read/write to read from/update the corresponding columns of
 the gpkg_contents table.</p>
 
+<h3>Non-spatial tables</h3>
+
+<p>The core GeoPackage specification of GeoPackage 1.0 and 1.1 did not support
+non-spatial tables. This was added in GeoPackage 1.2 as the "attributes"
+data type.</p>
+
+<p>Starting with GDAL 2.0, the driver allows creating and reading non-spatial
+tables with the     <a href="geopackage_aspatial.html">Aspatial Support</a>
+(<code>gdal_aspatial</code>) extension.</p>
+
+<p>Starting with GDAL 2.2, the driver will also, by default, list non spatial tables
+that are not registered through the gdal_aspatial extension, and support the
+GeoPackage 1.2 "attributes" data type as well. Starting with GDAL 2.2, non
+spatial tables are by default created following the GeoPackage 1.2 "attributes"
+data type (can be controlled with the ASPATIAL_VARIANT layer creation option)</p>
+
+<h3>Spatial views</h3>
+
+<p>Views can be created and recognized as valid spatial layers if a corresponding
+record is inserted into the gpkg_contents and gpkg_geometry_columns table.</p>
+
+<p>Starting with GDAL 2.2, in the case of the columns in the SELECT clause of
+the view acts a integer primary key, then it can be recognized by OGR as the
+FID column of the view, provided it is renamed as OGC_FID. Selecting a feature
+id from a source table without renaming will not be sufficient, since due to
+joins this feature id could appear several times. Thus the user must explicitly
+acknowledge that the column is really a primary key.</p>
+
+<p>For example:</p>
+<pre>
+CREATE VIEW my_view AS SELECT foo.fid AS OGC_FID, foo.geom, ... FROM foo JOIN another_table ON foo.some_id = another_table.other_id
+INSERT INTO gpkg_contents (table_name, identifier, data_type, srs_id) VALUES ( 'my_view', 'my_view', 'features', 4326)
+INSERT INTO gpkg_geometry_columns (table_name, column_name, geometry_type_name, srs_id, z, m) values ('my_view', 'my_geom', 'GEOMETRY', 4326, 0, 0)
+</pre>
+
 <h3>Examples</h3>
 
 <ul>
 <li>
 Simple translation of a single shapefile into GeoPackage.  The table 'abc' will
 be created with the features from abc.shp and attributes from abc.dbf.
-The file <code>filename.gpkg</code> must <strong>not</strong> already exist, as it will be created.
+The file <code>filename.gpkg</code> must <strong>not</strong> already exist,
+as it will be created. For adding new layers into existing geopackage run 
+ogr2ogr with <strong>-update</strong>.
 <pre>
 % ogr2ogr -f GPKG filename.gpkg abc.shp
 </pre>
@@ -184,7 +258,9 @@ The file <code>filename.gpkg</code> must <strong>not</strong> already exist, as
 
 <ul>
 <li> <a href="http://sqlite.org/">SQLite</a><p>
-<li> <a href="drv_geopackage_raster.html">GeoPackage raster</a> documentation page</li>
+<li> <a href="drv_geopackage_raster.html">GeoPackage raster</a> documentation page</li><p>
+<li> <a href="http://www.geopackage.org/spec/">OGC GeoPackage format standard</a> specification, HTML format (current/development version of the standard)</li><p>
+<li> <a href="http://www.opengeospatial.org/standards/geopackage">OGC GeoPackage Encoding Standard</a> page</li><p>
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html b/ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html
index 586ca52..8793d45 100644
--- a/ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html
+++ b/ogr/ogrsf_frmts/gpkg/drv_geopackage_raster.html
@@ -130,13 +130,16 @@ the appropriate compression. All of this is transparent to the user of GDAL API/
 
 <h3><a id="tile_formats">Tile formats</a></h3>
 
+<h4>Tiled rasters</h4>
+
 <p>GeoPackage can store tiles in different formats, PNG and/or JPEG for the baseline
 specification, and WebP for extended GeoPackage. Support for those tile formats
 depend if the underlying drivers are available in GDAL, which is generally the
 case for PNG and JPEG, but not necessarily for WebP since it requires GDAL to
 be compiled against the optional libwebp.<p>
 
-<p>By default, GDAL will use a mix of PNG and JPEG tiles. PNG tiles will be used
+<p>By default, GDAL will use a mix of PNG and JPEG tiles (PNG_JPEG tile format,
+or AUTO). PNG tiles will be used
 to store tiles that are not completely opaque, either because input dataset has
 an alpha channel with non fully opaque content, or because tiles are partial due
 to clipping at the right or bottom edges of the raster, or when a dataset is opened
@@ -163,6 +166,20 @@ table does not support alpha channel (even if PNG8 format would potentially allo
 color table with transparency). So when selecting PNG8, non fully opaque tiles
 will be stored as 32-bit PNG.</p>
 
+<h4>Tiled gridded elevation data</h4>
+
+<p>Since GeoPackage v1.2 and GDAL 2.2,
+<a href="http://www.geopackage.org/spec/#extension_tiled_gridded_elevation_data">
+tiled gridded elevation data</a> can be stored using
+PNG unsigned 16bit tiles (with potential offset and scaling so as to be able
+to represent floating point data) or TIFF 32-bit floating-point LZW compressed
+tiles.</p>
+
+<p>When converting a GDAL Int16 or UInt16 dataset, PNG tiles will be used.
+When converting a GDAL Float32 dataset, TIFF tiles will be used by default, unless
+PNG is explicitly selected, in which case scaling and offsetting will be
+automatically computed for each tile.</p>
+
 <h3><a id="tiling_schemes">Tiling schemes</a></h3>
 
 <p>
@@ -219,6 +236,46 @@ regarding interoperability with TMS.</li>
 <p>In all the above tiling schemes, consecutive zoom levels defer by a resolution
 of a factor of two.</p>
 
+<h3><a>Nodata value</a></h3>
+
+<p>The concept of the nodata value is only supported for tiled gridded elevation
+datasets. For regular tiled rasters, the alpha band must rather be used.</p>
+
+<p>For Float32 datasets with TIFF tiles, the concepts of nodata in GDAL
+and null_value in the GeoPackage internasl perfectly match.</p>
+
+<p>For Int16, UInt16 or Float32 with PNG tiles, GDAL will generally remap the
+input nodata value to another value.</p>
+
+<p>On writing, for PNG tiles, the behaviour is the following one:</p>
+
+<table border="1">
+<tr><td>GDAL data type</td><td>Input GDAL nodata value</td><td>null_value in GPKG gpkg_2d_gridded_coverage_ancillary</td></tr>
+<tr><td>Int16</td><td>Any</td><td>65535</td></tr>
+<tr><td>UInt16</td><td>X (if coverage offset == 0 and coverage scale == 1)</td><td>X</td></tr>
+<tr><td>Float32</td><td>Any</td><td>65535</td></tr>
+</table>
+
+<p>On reading, for PNG tiles, the behaviour is the following one:</p>
+
+<table border="1">
+<tr><td>GDAL data type</td><td>null_value in GPKG gpkg_2d_gridded_coverage_ancillary</td><td>Exposed GDAL nodata value</td></tr>
+<tr><td>Int16</td><td>>= 32768</td><td>-32768</td></tr>
+<tr><td>Int16</td><td>X <= 32767</td><td>X</td></tr>
+<tr><td>UInt16</td><td>X</td><td>X</td></tr>
+<tr><td>Float32</td><td>X</td><td>X</td></tr>
+</table>
+
+<p>Thus, perfect roundtripping is achieved in the following cases:</p>
+
+<table border="1">
+<tr><td>GDAL data type</td><td>GDAL nodata value</td><td>null_value in GPKG gpkg_2d_gridded_coverage_ancillary</td></tr>
+<tr><td>Int16</td><td>-32768</td><td>65535</td></tr>
+<tr><td>UInt16</td><td>X (if coverage offset == 0 and coverage scale == 1)</td><td>X</td></tr>
+<tr><td>Float32</td><td>65535</td><td>65535</td></tr>
+</table>
+
+
 <h3>Creation options</h3>
 
 <p>The following creation options are available:</p>
@@ -238,8 +295,8 @@ Defaults to 256. Maximum supported is 4096. Should not be set when using a non-c
 Defaults to 256. Maximum supported is 4096.</li>
 <li><b>BLOCKYSIZE</b>=integer. Block height in pixels.
 Defaults to 256. Maximum supported is 4096.</li>
-<li><b>TILE_FORMAT</b>=PNG_JPEG/PNG/PNG8/JPEG/WEBP: Format used to store tiles. See
-<a href="#tile_formats">Tile formats</a> section. Defaults to PNG_JPEG.</li>
+<li><b>TILE_FORMAT</b>=PNG_JPEG/PNG/PNG8/JPEG/WEBP/TIFF/AUTO: Format used to store tiles. See
+<a href="#tile_formats">Tile formats</a> section. Defaults to AUTO.</li>
 <li><b>QUALITY</b>=1-100: Quality setting for JPEG and WEBP compression. Default to 75.</li>
 <li><b>ZLEVEL</b>=1-9: DEFLATE compression level for PNG tiles. Default to 6.</li>
 <li><b>DITHER</b>=YES/NO: Whether to use Floyd-Steinberg dithering (for TILE_FORMAT=PNG8).
@@ -255,6 +312,12 @@ zoom level.</li>
 <li><b>RESAMPLING</b>=NEAREST/BILINEAR/CUBIC/CUBICSPLINE/LANCZOS/MODE/AVERAGE.
 Resampling algorithm. Only used for TILING_SCHEME is different from CUSTOM. Defaults
 to BILINEAR.</li>
+<li><b>PRECISION</b>=floating_point_value_in_vertical_units: Smallest significant value.
+Only used for tile gridded elevation data. Defaults to 1.</li>
+<li><b>VERSION</b>=AUTO/1.0/1.1/1.2: (GDAL > 2.2) Set GeoPackage version
+(for application_id and user_version fields). In AUTO mode, this will be equivalent
+to 1.0, unless a tile gridded elevation dataset is created, in which case 1.2 will
+be used.</li>
 </ul>
 
 <h2>Overviews</h2>
@@ -297,6 +360,9 @@ although it can be through direct SQL commands).</p>
 domain can be used in read/write to read from/update the corresponding columns of
 the gpkg_contents table.</p>
 
+<p>You can set the CREATE_METADATA_TABLES configuration option to NO to avoid
+creating and filling the metadata tables.</p>
+
 <h2>Examples</h2>
 
 <ul>
diff --git a/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp b/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp
index 27fe977..e598c9b 100644
--- a/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp
+++ b/ogr/ogrsf_frmts/gpkg/gdalgeopackagerasterband.cpp
@@ -30,7 +30,10 @@
 #include "memdataset.h"
 #include "gdal_alg_priv.h"
 
-CPL_CVSID("$Id: gdalgeopackagerasterband.cpp 35697 2016-10-11 18:44:52Z rouault $");
+#include <algorithm>
+#include <limits>
+
+CPL_CVSID("$Id: gdalgeopackagerasterband.cpp 37667 2017-03-09 22:57:57Z rouault $");
 
 #if !defined(DEBUG_VERBOSE) && defined(DEBUG_VERBOSE_GPKG)
 #define DEBUG_VERBOSE
@@ -43,6 +46,12 @@ CPL_CVSID("$Id: gdalgeopackagerasterband.cpp 35697 2016-10-11 18:44:52Z rouault
 GDALGPKGMBTilesLikePseudoDataset::GDALGPKGMBTilesLikePseudoDataset() :
     m_bNew(false),
     m_bHasModifiedTiles(false),
+    m_eDT(GDT_Byte),
+    m_nDTSize(1),
+    m_dfOffset(0.0),
+    m_dfScale(1.0),
+    m_dfPrecision(1.0),
+    m_usGPKGNull(0),
     m_nZoomLevel(-1),
     m_pabyCachedTiles(NULL),
     m_nShiftXTiles(0),
@@ -60,9 +69,7 @@ GDALGPKGMBTilesLikePseudoDataset::GDALGPKGMBTilesLikePseudoDataset() :
     m_poCT(NULL),
     m_bTriedEstablishingCT(false),
     m_pabyHugeColorArray(NULL),
-#ifdef HAVE_SQLITE_VFS
-  m_pMyVFS(NULL),
-#endif
+    m_pMyVFS(NULL),
     m_hTempDB(NULL),
     m_nLastSpaceCheckTimestamp(0),
     m_bForceTempDBCompaction(
@@ -95,14 +102,12 @@ GDALGPKGMBTilesLikePseudoDataset::~GDALGPKGMBTilesLikePseudoDataset()
         sqlite3_close(m_hTempDB);
         m_hTempDB = NULL;
         VSIUnlink(m_osTempDBFilename);
-#ifdef HAVE_SQLITE_VFS
         if( m_pMyVFS )
         {
             sqlite3_vfs_unregister(m_pMyVFS);
             CPLFree(m_pMyVFS->pAppData);
             CPLFree(m_pMyVFS);
         }
-#endif
     }
     CPLFree(m_pabyCachedTiles);
     delete m_poCT;
@@ -110,14 +115,41 @@ GDALGPKGMBTilesLikePseudoDataset::~GDALGPKGMBTilesLikePseudoDataset()
 }
 
 /************************************************************************/
+/*                            SetDataType()                             */
+/************************************************************************/
+
+void GDALGPKGMBTilesLikePseudoDataset::SetDataType(GDALDataType eDT)
+{
+    CPLAssert(eDT == GDT_Byte || eDT == GDT_Int16 || eDT == GDT_UInt16 ||
+              eDT == GDT_Float32);
+    m_eDT = eDT;
+    m_nDTSize = GDALGetDataTypeSizeBytes(m_eDT);
+}
+
+/************************************************************************/
+/*                        SetGlobalOffsetScale()                        */
+/************************************************************************/
+
+void GDALGPKGMBTilesLikePseudoDataset::SetGlobalOffsetScale(double dfOffset,
+                                                            double dfScale)
+{
+    m_dfOffset = dfOffset;
+    m_dfScale = dfScale;
+}
+
+/************************************************************************/
 /*                      GDALGPKGMBTilesLikeRasterBand()                 */
 /************************************************************************/
 
 GDALGPKGMBTilesLikeRasterBand::GDALGPKGMBTilesLikeRasterBand(
     GDALGPKGMBTilesLikePseudoDataset* poTPD, int nTileWidth, int nTileHeight) :
-    m_poTPD(poTPD)
+    m_poTPD(poTPD),
+    m_bHasNoData(false),
+    m_dfNoDataValue(0.0)
 {
-    eDataType = GDT_Byte;
+    CPLAssert( m_poTPD != NULL ); // make GCC 7 -Wnull-dereference happy in -O2
+    eDataType = m_poTPD->m_eDT;
+    m_nDTSize = m_poTPD->m_nDTSize;
     nBlockXSize = nTileWidth;
     nBlockYSize = nTileHeight;
 }
@@ -201,21 +233,21 @@ GDALColorTable* GDALGPKGMBTilesLikeRasterBand::GetColorTable()
             char* pszSQL = NULL;
             if( i == 0 )
             {
-                pszSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
+                pszSQL = sqlite3_mprintf("SELECT tile_data FROM \"%w\" "
                     "WHERE zoom_level = %d LIMIT 1",
                     m_poTPD->m_osRasterTable.c_str(), m_poTPD->m_nZoomLevel);
             }
             else
             {
                 // Try a tile in the middle of the raster
-                pszSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
+                pszSQL = sqlite3_mprintf("SELECT tile_data FROM \"%w\" "
                     "WHERE zoom_level = %d AND tile_column = %d AND tile_row = %d",
                     m_poTPD->m_osRasterTable.c_str(), m_poTPD->m_nZoomLevel,
                     m_poTPD->m_nShiftXTiles + nRasterXSize / 2 / nBlockXSize,
                     m_poTPD->GetRowFromIntoTopConvention(m_poTPD->m_nShiftYTiles + nRasterYSize / 2 / nBlockYSize));
             }
             sqlite3_stmt* hStmt = NULL;
-            int rc = sqlite3_prepare(m_poTPD->IGetDB(), pszSQL, -1, &hStmt, NULL);
+            int rc = sqlite3_prepare_v2(m_poTPD->IGetDB(), pszSQL, -1, &hStmt, NULL);
             if( rc == SQLITE_OK )
             {
                 rc = sqlite3_step( hStmt );
@@ -275,6 +307,8 @@ GDALColorTable* GDALGPKGMBTilesLikeRasterBand::GetColorTable()
 
 CPLErr GDALGPKGMBTilesLikeRasterBand::SetColorTable(GDALColorTable* poCT)
 {
+    if( m_poTPD->m_eDT != GDT_Byte )
+        return CE_Failure;
     if( poDS->GetRasterCount() != 1 )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -303,6 +337,8 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::SetColorTable(GDALColorTable* poCT)
 
 GDALColorInterp GDALGPKGMBTilesLikeRasterBand::GetColorInterpretation()
 {
+    if( m_poTPD->m_eDT != GDT_Byte )
+        return GCI_Undefined;
     if( poDS->GetRasterCount() == 1 )
         return GetColorTable() ? GCI_PaletteIndex : GCI_GrayIndex;
     else if( poDS->GetRasterCount() == 2 )
@@ -344,7 +380,7 @@ static int GPKGFindBestEntry(GDALColorTable* poCT,
                              GByte c1, GByte c2, GByte c3, GByte c4,
                              int nTileBandCount)
 {
-    const int nEntries = MIN(256, poCT->GetColorEntryCount());
+    const int nEntries = std::min(256, poCT->GetColorEntryCount());
     int iBestIdx = 0;
     int nBestDistance = 4 * 256 * 256;
     for(int i=0;i<nEntries;i++)
@@ -365,26 +401,81 @@ static int GPKGFindBestEntry(GDALColorTable* poCT,
 }
 
 /************************************************************************/
+/*                             FillBuffer()                             */
+/************************************************************************/
+
+void GDALGPKGMBTilesLikePseudoDataset::FillBuffer(GByte* pabyData,
+                                                  size_t nPixels)
+{
+    int bHasNoData = FALSE;
+    const double dfNoDataValue = IGetRasterBand(1)->GetNoDataValue(&bHasNoData);
+    if( !bHasNoData || dfNoDataValue == 0.0 )
+    {
+        memset(pabyData, 0, nPixels * m_nDTSize );
+    }
+    else
+    {
+        GDALCopyWords(&dfNoDataValue, GDT_Float64, 0,
+                      pabyData, m_eDT, m_nDTSize,
+                      static_cast<int>(nPixels));
+    }
+}
+
+/************************************************************************/
+/*                           FillEmptyTile()                            */
+/************************************************************************/
+
+void GDALGPKGMBTilesLikePseudoDataset::FillEmptyTile(GByte* pabyData)
+{
+    int nBlockXSize, nBlockYSize;
+    IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    const int nBands = IGetRasterCount();
+    const size_t nPixels = static_cast<size_t>(nBands) *
+                             nBlockXSize * nBlockYSize;
+    FillBuffer(pabyData, nPixels);
+}
+
+/************************************************************************/
+/*                    FillEmptyTileSingleBand()                         */
+/************************************************************************/
+
+void GDALGPKGMBTilesLikePseudoDataset::FillEmptyTileSingleBand(GByte* pabyData)
+{
+    int nBlockXSize, nBlockYSize;
+    IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
+    const size_t nPixels = static_cast<size_t>(nBlockXSize) * nBlockYSize;
+    FillBuffer(pabyData, nPixels);
+}
+
+/************************************************************************/
 /*                           ReadTile()                                 */
 /************************************************************************/
 
-CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile(const CPLString& osMemFileName,
+CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile(
+                                       const CPLString& osMemFileName,
                                        GByte* pabyTileData,
+                                       double dfTileOffset,
+                                       double dfTileScale,
                                        bool* pbIsLossyFormat)
 {
-    const char* apszDrivers[] = { "JPEG", "PNG", "WEBP", NULL };
+    const char* apszDriversByte[] = { "JPEG", "PNG", "WEBP", NULL };
+    const char* apszDriversInt[] = { "PNG", NULL };
+    const char* apszDriversFloat[] = { "GTiff", NULL };
     int nBlockXSize, nBlockYSize;
     IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
     const int nBands = IGetRasterCount();
     GDALDataset* poDSTile = reinterpret_cast<GDALDataset*>(
         GDALOpenEx( osMemFileName.c_str(),
                     GDAL_OF_RASTER | GDAL_OF_INTERNAL,
-                    apszDrivers, NULL, NULL ) );
+                    (m_eDT == GDT_Byte) ?                 apszDriversByte :
+                    (m_eTF == GPKG_TF_TIFF_32BIT_FLOAT) ? apszDriversFloat :
+                                                          apszDriversInt,
+                    NULL, NULL ) );
     if( poDSTile == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot parse tile data");
-        memset(pabyTileData, 0, nBands * nBlockXSize * nBlockYSize );
+        FillEmptyTile(pabyTileData);
         return CE_Failure;
     }
 
@@ -392,27 +483,113 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile(const CPLString& osMemFileName
 
     if( !(poDSTile->GetRasterXSize() == nBlockXSize &&
           poDSTile->GetRasterYSize() == nBlockYSize &&
-          (nTileBandCount >= 1 && nTileBandCount <= 4)) )
+          (nTileBandCount >= 1 && nTileBandCount <= 4)) ||
+        (m_eDT != GDT_Byte && nTileBandCount != 1) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Inconsistent tiles characteristics" );
         GDALClose(poDSTile);
-        memset(pabyTileData, 0, nBands * nBlockXSize * nBlockYSize );
+        FillEmptyTile(pabyTileData);
         return CE_Failure;
     }
 
+    GDALDataType eRequestDT = GDT_Byte;
+    if( m_eTF == GPKG_TF_PNG_16BIT )
+    {
+        CPLAssert( m_eDT == GDT_Int16 || m_eDT == GDT_UInt16 ||
+                   m_eDT == GDT_Float32 );
+        eRequestDT = GDT_UInt16;
+    }
+    else if( m_eTF == GPKG_TF_TIFF_32BIT_FLOAT )
+    {
+        CPLAssert( m_eDT == GDT_Float32 );
+        eRequestDT = GDT_Float32;
+    }
+
     if( poDSTile->RasterIO(GF_Read, 0, 0, nBlockXSize, nBlockYSize,
                         pabyTileData,
                         nBlockXSize, nBlockYSize,
-                        GDT_Byte,
+                        eRequestDT,
                         poDSTile->GetRasterCount(), NULL,
                         0, 0, 0, NULL) != CE_None )
     {
         GDALClose(poDSTile);
-        memset(pabyTileData, 0, nBands * nBlockXSize * nBlockYSize );
+        FillEmptyTile(pabyTileData);
         return CE_Failure;
     }
 
+    if( m_eDT != GDT_Byte )
+    {
+        int bHasNoData = FALSE;
+        const double dfNoDataValue =
+                            IGetRasterBand(1)->GetNoDataValue(&bHasNoData);
+        if( m_eDT == GDT_Int16 )
+        {
+            CPLAssert( eRequestDT == GDT_UInt16 );
+            for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
+            {
+                const GUInt16 nVal =
+                    *reinterpret_cast<GUInt16*>(pabyTileData +
+                                                i * sizeof(GUInt16));
+                double dfVal = floor((nVal * dfTileScale + dfTileOffset) *
+                                            m_dfScale + m_dfOffset + 0.5);
+                if( bHasNoData && nVal == m_usGPKGNull )
+                    dfVal = dfNoDataValue;
+                if( dfVal > 32767 )
+                    dfVal = 32767;
+                else if( dfVal < -32768 )
+                    dfVal = -32768;
+                *reinterpret_cast<GInt16*>(pabyTileData + i * sizeof(GInt16)) =
+                    static_cast<GInt16>(dfVal);
+            }
+        }
+        else if( m_eDT == GDT_UInt16 &&
+                 (m_dfOffset != 0.0 || m_dfScale != 1.0 ||
+                  dfTileOffset != 0.0 || dfTileScale != 1.0) )
+        {
+            CPLAssert( eRequestDT == GDT_UInt16 );
+            for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
+            {
+                const GUInt16 nVal =
+                    *reinterpret_cast<GUInt16*>(pabyTileData +
+                                                i * sizeof(GUInt16));
+                double dfVal = floor((nVal * dfTileScale + dfTileOffset) *
+                                            m_dfScale + m_dfOffset + 0.5);
+                if( bHasNoData && nVal == m_usGPKGNull )
+                    dfVal = dfNoDataValue;
+                if( dfVal > 65535 )
+                    dfVal = 65535;
+                else if( dfVal < 0 )
+                    dfVal = 0;
+                *reinterpret_cast<GUInt16*>(pabyTileData + i * sizeof(GUInt16)) =
+                    static_cast<GUInt16>(dfVal);
+            }
+        }
+        else if( m_eDT == GDT_Float32 && eRequestDT == GDT_UInt16 )
+        {
+            // Due to non identical data type size, we need to start from the
+            // end of the buffer.
+            for( int i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
+            {
+                const GUInt16 nVal =
+                    *reinterpret_cast<GUInt16*>(pabyTileData +
+                                                i * sizeof(GUInt16));
+                double dfVal = (nVal * dfTileScale + dfTileOffset) *
+                                            m_dfScale + m_dfOffset;
+                if( m_dfPrecision == 1.0 )
+                    dfVal = floor(dfVal + 0.5);
+                if( bHasNoData && nVal == m_usGPKGNull )
+                    dfVal = dfNoDataValue;
+                *reinterpret_cast<float*>(pabyTileData + i * sizeof(float)) =
+                    static_cast<float>(dfVal);
+            }
+        }
+
+        GDALClose( poDSTile );
+
+        return CE_None;
+    }
+
     GDALColorTable* poCT = NULL;
     if( nBands == 1 || nTileBandCount == 1 )
     {
@@ -429,7 +606,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile(const CPLString& osMemFileName
     if( nBands == 1 && m_poCT != NULL && nTileBandCount != 1 )
     {
         std::map< GUInt32, int > oMapEntryToIndex;
-        int nEntries = MIN(256, m_poCT->GetColorEntryCount());
+        const int nEntries = std::min(256, m_poCT->GetColorEntryCount());
         for(int i=0;i<nEntries;i++)
         {
             const GDALColorEntry* psEntry = m_poCT->GetColorEntry(i);
@@ -520,7 +697,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::ReadTile(const CPLString& osMemFileName
         if( poCT != NULL )
         {
             GByte abyCT[4*256];
-            int nEntries = MIN(256, poCT->GetColorEntryCount());
+            const int nEntries = std::min(256, poCT->GetColorEntryCount());
             for( int i = 0; i < nEntries; i++ )
             {
                 const GDALColorEntry* psEntry = poCT->GetColorEntry(i);
@@ -579,6 +756,8 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile(int nRow, int nCol)
     int nBlockXSize, nBlockYSize;
     IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
     const int nBands = IGetRasterCount();
+    const size_t nBandBlockSize = static_cast<size_t>(nBlockXSize) *
+                                                nBlockYSize * m_nDTSize;
     if( m_nShiftXPixelsMod || m_nShiftYPixelsMod )
     {
         GByte* pabyData = NULL;
@@ -592,7 +771,7 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile(int nRow, int nCol)
                 {
                     return m_pabyCachedTiles +
                         m_asCachedTilesDesc[i].nIdxWithinTileData * 4 *
-                        nBlockXSize * nBlockYSize;
+                        nBandBlockSize;
                 }
                 else
                 {
@@ -609,7 +788,8 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile(int nRow, int nCol)
                         m_asCachedTilesDesc[i].nIdxWithinTileData =
                             (m_asCachedTilesDesc[2].nIdxWithinTileData == 2 ) ? 3 : 2;
                     pabyData = m_pabyCachedTiles +
-                                            m_asCachedTilesDesc[i].nIdxWithinTileData * 4 * nBlockXSize * nBlockYSize;
+                        m_asCachedTilesDesc[i].nIdxWithinTileData * 4 *
+                        nBandBlockSize;
                     break;
                 }
             }
@@ -619,7 +799,7 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile(int nRow, int nCol)
     }
     else
     {
-        GByte* pabyDest = m_pabyCachedTiles + 8 * nBlockXSize * nBlockYSize;
+        GByte* pabyDest = m_pabyCachedTiles + 8 * nBandBlockSize;
         bool bAllNonDirty = true;
         for( int i = 0; i < nBands; i++ )
         {
@@ -639,16 +819,16 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile(int nRow, int nCol)
             m_asCachedTilesDesc[i].nCol = -1;
             m_asCachedTilesDesc[i].nIdxWithinTileData = -1;
         }
-        GByte* pabyTemp = m_pabyCachedTiles + 12 * nBlockXSize * nBlockYSize;
+        GByte* pabyTemp = m_pabyCachedTiles + 12 * nBandBlockSize;
         if( ReadTile(nRow, nCol, pabyTemp) != NULL )
         {
             for( int i = 0; i < nBands; i++ )
             {
                 if( !m_asCachedTilesDesc[0].abBandDirty[i] )
                 {
-                    memcpy(pabyDest + i * nBlockXSize * nBlockYSize,
-                           pabyTemp + i * nBlockXSize * nBlockYSize,
-                           nBlockXSize * nBlockYSize);
+                    memcpy(pabyDest + i * nBandBlockSize,
+                           pabyTemp + i * nBandBlockSize,
+                           nBandBlockSize);
                 }
             }
         }
@@ -657,6 +837,41 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile(int nRow, int nCol)
 }
 
 /************************************************************************/
+/*                         GetTileOffsetAndScale()                      */
+/************************************************************************/
+
+void GDALGPKGMBTilesLikePseudoDataset::GetTileOffsetAndScale(
+                GIntBig nTileId, double& dfTileOffset, double& dfTileScale)
+{
+    dfTileOffset = 0.0;
+    dfTileScale = 1.0;
+
+    if( m_eTF == GPKG_TF_PNG_16BIT )
+    {
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT offset, scale FROM gpkg_2d_gridded_tile_ancillary WHERE "
+            "tpudt_name = '%q' AND tpudt_id = ?",
+            m_osRasterTable.c_str());
+        sqlite3_stmt *hStmt = NULL;
+        int rc = sqlite3_prepare_v2( IGetDB(), pszSQL, -1, &hStmt, NULL );
+        if( rc == SQLITE_OK )
+        {
+            sqlite3_bind_int64(hStmt, 1, nTileId);
+            rc = sqlite3_step( hStmt );
+            if( rc == SQLITE_ROW )
+            {
+                if( sqlite3_column_type(hStmt, 0) == SQLITE_FLOAT )
+                    dfTileOffset = sqlite3_column_double(hStmt, 0);
+                if( sqlite3_column_type(hStmt, 1) == SQLITE_FLOAT )
+                    dfTileScale = sqlite3_column_double(hStmt, 1);
+            }
+            sqlite3_finalize(hStmt);
+        }
+        sqlite3_free(pszSQL);
+    }
+}
+
+/************************************************************************/
 /*                           ReadTile()                                 */
 /************************************************************************/
 
@@ -670,10 +885,12 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile( int nRow, int nCol, GByte *pa
 
     if( pbIsLossyFormat ) *pbIsLossyFormat = false;
 
+    const size_t nBandBlockSize =
+        static_cast<size_t>(nBlockXSize) * nBlockYSize * m_nDTSize;
     if( nRow < 0 || nCol < 0 || nRow >= m_nTileMatrixHeight ||
         nCol >= m_nTileMatrixWidth )
     {
-        memset( pabyData, 0, nBands * nBlockXSize * nBlockYSize );
+        FillEmptyTile(pabyData);
         return pabyData;
     }
 
@@ -681,21 +898,23 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile( int nRow, int nCol, GByte *pa
     CPLDebug( "GPKG", "ReadTile(row=%d, col=%d)", nRow, nCol );
 #endif
 
-    char *pszSQL = sqlite3_mprintf( "SELECT tile_data FROM '%q' "
+    char *pszSQL = sqlite3_mprintf( "SELECT tile_data%s FROM \"%w\" "
         "WHERE zoom_level = %d AND tile_row = %d AND tile_column = %d%s",
+        m_eDT != GDT_Byte ? ", id" : "", // MBTiles do not have an id
         m_osRasterTable.c_str(), m_nZoomLevel, GetRowFromIntoTopConvention(nRow), nCol,
-        m_osWHERE.size() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
+        !m_osWHERE.empty() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
 
 #ifdef DEBUG_VERBOSE
     CPLDebug("GPKG", "%s", pszSQL);
 #endif
 
     sqlite3_stmt *hStmt = NULL;
-    int rc = sqlite3_prepare( IGetDB(), pszSQL, -1, &hStmt, NULL );
+    int rc = sqlite3_prepare_v2( IGetDB(), pszSQL, -1, &hStmt, NULL );
     if ( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "failed to prepare SQL: %s", pszSQL );
+                  "failed to prepare SQL %s: %s",
+                  pszSQL, sqlite3_errmsg( IGetDB() ) );
         sqlite3_free(pszSQL);
         return NULL;
     }
@@ -705,6 +924,7 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile( int nRow, int nCol, GByte *pa
     if( rc == SQLITE_ROW && sqlite3_column_type( hStmt, 0 ) == SQLITE_BLOB )
     {
         const int nBytes = sqlite3_column_bytes( hStmt, 0 );
+        GIntBig nTileId = (m_eDT == GDT_Byte ) ? 0 : sqlite3_column_int64( hStmt, 1 );
         GByte* pabyRawData = static_cast<GByte *>( const_cast<void *>(
             sqlite3_column_blob( hStmt, 0 ) ) );
         CPLString osMemFileName;
@@ -713,7 +933,11 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile( int nRow, int nCol, GByte *pa
             osMemFileName.c_str(), pabyRawData, nBytes, FALSE );
         VSIFCloseL(fp);
 
-        ReadTile(osMemFileName, pabyData, pbIsLossyFormat);
+        double dfTileOffset = 0.0;
+        double dfTileScale = 1.0;
+        GetTileOffsetAndScale(nTileId, dfTileOffset, dfTileScale);
+        ReadTile(osMemFileName, pabyData, dfTileOffset, dfTileScale,
+                 pbIsLossyFormat);
         VSIUnlink(osMemFileName);
         sqlite3_finalize(hStmt);
     }
@@ -737,9 +961,9 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile( int nRow, int nCol, GByte *pa
             rc = sqlite3_prepare_v2(m_hTempDB, pszSQLNew, -1, &hStmt, NULL);
             if ( rc != SQLITE_OK )
             {
-                memset(pabyData, 0, nBands * nBlockXSize * nBlockYSize );
+                FillEmptyTile(pabyData);
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "sqlite3_prepare(%s) failed: %s",
+                          "sqlite3_prepare_v2(%s) failed: %s",
                           pszSQLNew, sqlite3_errmsg( m_hTempDB ) );
                 return pabyData;
             }
@@ -751,30 +975,30 @@ GByte* GDALGPKGMBTilesLikePseudoDataset::ReadTile( int nRow, int nCol, GByte *pa
                 for(int iBand = 1; iBand <= nBands; iBand ++ )
                 {
                     GByte* pabyDestBand
-                        = pabyData + (iBand - 1) * nBlockXSize * nBlockYSize;
+                        = pabyData + (iBand - 1) * nBandBlockSize;
                     if( nPartialFlag & (((1 << 4)-1) << (4 * (iBand - 1))) )
                     {
                         CPLAssert( sqlite3_column_bytes(hStmt, iBand)
-                                   == nBlockXSize * nBlockYSize );
+                                   == static_cast<int>(nBandBlockSize) );
                         memcpy( pabyDestBand,
                                 sqlite3_column_blob(hStmt, iBand),
-                                nBlockXSize * nBlockYSize );
+                                nBandBlockSize );
                     }
                     else
                     {
-                        memset(pabyDestBand, 0, nBlockXSize * nBlockYSize );
+                        FillEmptyTileSingleBand(pabyDestBand);
                     }
                 }
             }
             else
             {
-                memset(pabyData, 0, nBands * nBlockXSize * nBlockYSize );
+                FillEmptyTile(pabyData);
             }
             sqlite3_finalize(hStmt);
         }
         else
         {
-            memset(pabyData, 0, nBands * nBlockXSize * nBlockYSize );
+            FillEmptyTile(pabyData);
         }
     }
 
@@ -841,7 +1065,6 @@ retry:
         m_poTPD->m_asCachedTilesDesc[3].nCol = nColMin + 1;
         m_poTPD->m_asCachedTilesDesc[1].nIdxWithinTileData = -1;
         m_poTPD->m_asCachedTilesDesc[3].nIdxWithinTileData = -1;
-
     }
 
     for(int nRow = nRowMin; nRow <= nRowMax; nRow ++)
@@ -903,12 +1126,16 @@ retry:
                 if( m_poTPD->m_nShiftXPixelsMod == 0
                     && m_poTPD->m_nShiftYPixelsMod == 0 )
                 {
+                    const size_t nBandBlockSize =
+                        static_cast<size_t>(nBlockXSize) *
+                                                nBlockYSize * m_nDTSize;
                     memcpy( pabyDest,
                             pabyTileData +
-                            (iBand - 1) * nBlockXSize * nBlockYSize,
-                            nBlockXSize * nBlockYSize );
+                            (iBand - 1) * nBandBlockSize,
+                            nBandBlockSize );
 #ifdef DEBUG_VERBOSE
-                    if( (nBlockXOff+1) * nBlockXSize <= nRasterXSize &&
+                    if( eDataType == GDT_Byte &&
+                        (nBlockXOff+1) * nBlockXSize <= nRasterXSize &&
                         (nBlockYOff+1) * nBlockYSize > nRasterYSize )
                     {
                         bool bFoundNonZero = false;
@@ -926,7 +1153,6 @@ retry:
                         }
                     }
 #endif
-
                 }
                 else
                 {
@@ -972,20 +1198,19 @@ retry:
                     for( int y=0; y<nSrcYSize; y++ )
                     {
                         GByte *pSrc =
-                          pabyTileData + (iBand - 1) * nBlockXSize * nBlockYSize
-                          + (y + nSrcYOffset) * nBlockXSize + nSrcXOffset;
+                          pabyTileData + ((iBand - 1) * nBlockXSize * nBlockYSize
+                          + (y + nSrcYOffset) * nBlockXSize + nSrcXOffset) * m_nDTSize;
                         GByte *pDst =
-                          pabyDest + (y + nDstYOffset) * nBlockXSize
-                          + nDstXOffset;
-                        GDALCopyWords(pSrc, GDT_Byte, 1,
-                                      pDst, GDT_Byte, 1,
+                          pabyDest + ((y + nDstYOffset) * nBlockXSize
+                          + nDstXOffset) * m_nDTSize;
+                        GDALCopyWords(pSrc, eDataType, m_nDTSize,
+                                      pDst, eDataType, m_nDTSize,
                                       nSrcXSize);
                     }
                 }
 
                 if( poBlock )
                     poBlock->DropLock();
-
             }
         }
     }
@@ -1020,6 +1245,184 @@ static bool WEBPSupports4Bands()
 }
 
 /************************************************************************/
+/*                         GetTileId()                                  */
+/************************************************************************/
+
+GIntBig GDALGPKGMBTilesLikePseudoDataset::GetTileId(int nRow, int nCol)
+{
+    char* pszSQL = sqlite3_mprintf(
+            "SELECT id FROM \"%w\" WHERE zoom_level = %d AND "
+            "tile_row = %d AND tile_column = %d",
+            m_osRasterTable.c_str(), m_nZoomLevel,
+        GetRowFromIntoTopConvention(nRow), nCol);
+    GIntBig nRes = SQLGetInteger64( IGetDB(), pszSQL, NULL );
+    sqlite3_free(pszSQL);
+    return nRes;
+}
+
+/************************************************************************/
+/*                           DeleteTile()                               */
+/************************************************************************/
+
+bool GDALGPKGMBTilesLikePseudoDataset::DeleteTile(int nRow, int nCol)
+{
+    char* pszSQL = sqlite3_mprintf("DELETE FROM \"%w\" "
+        "WHERE zoom_level = %d AND tile_row = %d AND "
+        "tile_column = %d",
+        m_osRasterTable.c_str(), m_nZoomLevel,
+                GetRowFromIntoTopConvention(nRow), nCol);
+#ifdef DEBUG_VERBOSE
+        CPLDebug("GPKG", "%s", pszSQL);
+#endif
+    char* pszErrMsg = NULL;
+    int rc = sqlite3_exec(IGetDB(), pszSQL, NULL, NULL, &pszErrMsg);
+    if( rc != SQLITE_OK )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                    "Failure when deleting tile (row=%d,col=%d) "
+                    "at zoom_level=%d : %s",
+                    GetRowFromIntoTopConvention(nRow), nCol,
+                    m_nZoomLevel, pszErrMsg ? pszErrMsg : "");
+    }
+    sqlite3_free(pszSQL);
+    sqlite3_free(pszErrMsg);
+    return rc == SQLITE_OK;
+}
+
+/************************************************************************/
+/*                   DeleteFromGriddedTileAncillary()                   */
+/************************************************************************/
+
+bool GDALGPKGMBTilesLikePseudoDataset::DeleteFromGriddedTileAncillary(
+                                                            GIntBig nTileId)
+{
+    char* pszSQL = sqlite3_mprintf(
+        "DELETE FROM gpkg_2d_gridded_tile_ancillary WHERE "
+        "tpudt_name = '%q' AND tpudt_id = ?",
+        m_osRasterTable.c_str());
+    sqlite3_stmt* hStmt = NULL;
+    int rc = sqlite3_prepare_v2(IGetDB(), pszSQL, -1, &hStmt, NULL);
+    if( rc == SQLITE_OK )
+    {
+        sqlite3_bind_int64( hStmt, 1, nTileId );
+        rc = sqlite3_step( hStmt );
+        sqlite3_finalize(hStmt);
+    }
+    sqlite3_free(pszSQL);
+    return rc == SQLITE_OK;
+}
+
+/************************************************************************/
+/*                      ProcessInt16UInt16Tile()                        */
+/************************************************************************/
+
+template<class T>
+static void ProcessInt16UInt16Tile( const void* pabyData,
+                                    int nPixels,
+                                    bool bIsInt16,
+                                    bool bHasNoData,
+                                    double dfNoDataValue,
+                                    GUInt16 usGPKGNull,
+                                    double m_dfOffset,
+                                    double m_dfScale,
+                                    GUInt16* pTempTileBuffer,
+                                    double& dfTileOffset,
+                                    double& dfTileScale,
+                                    double& dfTileMin,
+                                    double& dfTileMax,
+                                    double& dfTileMean,
+                                    double& dfTileStdDev,
+                                    int& nValidPixels )
+{
+    const T* pSrc = reinterpret_cast<const T*>(pabyData);
+    T nMin = 0;
+    T nMax = 0;
+    double dfM2 = 0.0;
+    for( int i = 0; i < nPixels; i++ )
+    {
+        const T nVal = pSrc[i];
+        if( bHasNoData && nVal == dfNoDataValue )
+            continue;
+
+        if( nValidPixels == 0 )
+        {
+            nMin = nVal;
+            nMax = nVal;
+        }
+        else
+        {
+            nMin = std::min(nMin, nVal);
+            nMax = std::max(nMax, nVal);
+        }
+        nValidPixels ++;
+        const double dfDelta = nVal - dfTileMean;
+        dfTileMean += dfDelta / nValidPixels;
+        dfM2 += dfDelta * (nVal - dfTileMean);
+    }
+    dfTileMin = nMin;
+    dfTileMax = nMax;
+    if( nValidPixels )
+        dfTileStdDev = sqrt( dfM2 / nValidPixels );
+
+    double dfGlobalMin = (nMin - m_dfOffset) / m_dfScale;
+    double dfGlobalMax = (nMax - m_dfOffset) / m_dfScale;
+    double dfRange = 65535.0;
+    if( bHasNoData && usGPKGNull == 65535 &&
+        dfGlobalMax - dfGlobalMin >= dfRange)
+    {
+        dfRange = 65534.0;
+    }
+
+    if( dfGlobalMax - dfGlobalMin > dfRange )
+    {
+        dfTileScale = (dfGlobalMax - dfGlobalMin) / dfRange;
+    }
+    if( dfGlobalMin < 0.0 )
+    {
+        dfTileOffset = -dfGlobalMin;
+    }
+    else if( dfGlobalMax / dfTileScale > dfRange )
+    {
+        dfTileOffset = dfGlobalMax - dfRange * dfTileScale;
+    }
+
+    if( bHasNoData && std::numeric_limits<T>::min() == 0 &&
+        m_dfOffset == 0.0 && m_dfScale == 1.0 )
+    {
+        dfTileOffset = 0.0;
+        dfTileScale = 1.0;
+    }
+    else if( bHasNoData && bIsInt16 &&
+             dfNoDataValue == -32768.0 && usGPKGNull == 65535 &&
+             m_dfOffset == -32768.0 && m_dfScale == 1.0 )
+    {
+        dfTileOffset = 1.0;
+        dfTileScale = 1.0;
+    }
+
+    for( int i = 0; i < nPixels; i++ )
+    {
+        const T nVal = pSrc[i];
+        if( bHasNoData && nVal == dfNoDataValue )
+            pTempTileBuffer[i] = usGPKGNull;
+        else
+        {
+            double dfVal =  ((nVal - m_dfOffset) / m_dfScale -
+                                            dfTileOffset) / dfTileScale;
+            CPLAssert( dfVal >= 0.0 && dfVal < 65535.5);
+            pTempTileBuffer[i] = static_cast<GUInt16>(dfVal+0.5);
+            if( bHasNoData && pTempTileBuffer[i] == usGPKGNull )
+            {
+                if( usGPKGNull > 0 )
+                    pTempTileBuffer[i] --;
+                else
+                    pTempTileBuffer[i] ++;;
+            }
+        }
+    }
+}
+
+/************************************************************************/
 /*                         WriteTile()                                  */
 /************************************************************************/
 
@@ -1066,6 +1469,8 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
     /* If all bands for that block are not dirty/written, we need to */
     /* fetch the missing ones if the tile exists */
     bool bIsLossyFormat = false;
+    const size_t nBandBlockSize = static_cast<size_t>(nBlockXSize) *
+                                            nBlockYSize * m_nDTSize;
     if( !bAllDirty )
     {
         for( int i = 1; i <= 3; i++ )
@@ -1074,15 +1479,15 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
             m_asCachedTilesDesc[i].nCol = -1;
             m_asCachedTilesDesc[i].nIdxWithinTileData = -1;
         }
-        ReadTile(nRow, nCol, m_pabyCachedTiles + 4 * nBlockXSize * nBlockYSize,
+        ReadTile(nRow, nCol, m_pabyCachedTiles + 4 * nBandBlockSize,
                  &bIsLossyFormat);
         for( int i = 0; i < nBands; i++ )
         {
             if( !m_asCachedTilesDesc[0].abBandDirty[i] )
             {
-                memcpy(m_pabyCachedTiles + i * nBlockXSize * nBlockYSize,
-                       m_pabyCachedTiles + (4 + i) * nBlockXSize * nBlockYSize,
-                       nBlockXSize * nBlockYSize);
+                memcpy(m_pabyCachedTiles + i * nBandBlockSize,
+                       m_pabyCachedTiles + (4 + i) * nBandBlockSize,
+                       nBandBlockSize);
             }
         }
     }
@@ -1092,8 +1497,8 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
     int nYOff = (nRow - m_nShiftYTiles) * nBlockYSize - m_nShiftYPixelsMod;
 
     /* Assert that the tile at least intersects some of the GDAL raster space */
-    CPLAssert(nXOff + nBlockXSize > 0);
-    CPLAssert(nYOff + nBlockYSize > 0);
+    CPLAssert(nXOff > -nBlockXSize);
+    CPLAssert(nYOff > -nBlockYSize);
     /* Can happen if the tile of the raster is less than the block size */
     const int nRasterXSize = IGetRasterBand(1)->GetXSize();
     const int nRasterYSize = IGetRasterBand(1)->GetYSize();
@@ -1101,12 +1506,12 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
         return CE_None;
 
 #ifdef DEBUG_VERBOSE
-    if( m_nShiftXPixelsMod == 0 && m_nShiftYPixelsMod == 0 )
+    if( m_nShiftXPixelsMod == 0 && m_nShiftYPixelsMod == 0 && m_eDT == GDT_Byte )
     {
         int nBlockXOff = nCol;
         int nBlockYOff = nRow;
-        if( (nBlockXOff+1) * nBlockXSize <= nRasterXSize &&
-            (nBlockYOff+1) * nBlockYSize > nRasterYSize )
+        if( nBlockXOff * nBlockXSize <= nRasterXSize - nBlockXSize &&
+            nBlockYOff * nBlockYSize > nRasterYSize - nBlockYSize )
         {
             for(int i = 0; i < nBands; i++ )
             {
@@ -1115,7 +1520,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
                 {
                     for(int x=0;x<nBlockXSize;x++)
                     {
-                        if( m_pabyCachedTiles[y*nBlockXSize+x + i * nBlockXSize * nBlockYSize] != 0 && !bFoundNonZero )
+                        if( m_pabyCachedTiles[y*nBlockXSize+x + i * nBandBlockSize] != 0 && !bFoundNonZero )
                         {
                             CPLDebug("GPKG", "WriteTileInternal(): Found non-zero content in ghost part of tile(band=%d,nBlockXOff=%d,nBlockYOff=%d,m_nZoomLevel=%d)\n",
                                     i+1,nBlockXOff,nBlockYOff,m_nZoomLevel);
@@ -1144,10 +1549,11 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
             iXOff = -nXOff;
             iXCount += nXOff;
         }
-        if( nXOff + nBlockXSize > nRasterXSize )
+        if( nXOff > nRasterXSize - nBlockXSize )
         {
             bPartialTile = true;
-            iXCount -= nXOff + nBlockXSize - nRasterXSize;
+            iXCount -= static_cast<int>(
+                static_cast<GIntBig>(nXOff) + nBlockXSize - nRasterXSize);
         }
         if( nYOff < 0 )
         {
@@ -1155,10 +1561,11 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
             iYOff = -nYOff;
             iYCount += nYOff;
         }
-        if( nYOff + nBlockYSize > nRasterYSize )
+        if( nYOff > nRasterYSize - nBlockYSize )
         {
             bPartialTile = true;
-            iYCount -= nYOff + nBlockYSize - nRasterYSize;
+            iYCount -= static_cast<int>(
+                static_cast<GIntBig>(nYOff) + nBlockYSize - nRasterYSize);
         }
         CPLAssert(iXOff >= 0);
         CPLAssert(iYOff >= 0);
@@ -1179,7 +1586,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
     CPLErr eErr = CE_Failure;
 
     bool bAllOpaque = true;
-    if( m_poCT == NULL && nAlphaBand != 0 )
+    if( m_eDT == GDT_Byte && m_poCT == NULL && nAlphaBand != 0 )
     {
         GByte byFirstAlphaVal =  m_pabyCachedTiles[(nAlphaBand-1) * nBlockXSize * nBlockYSize];
         int i = 1;
@@ -1193,22 +1600,8 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
             // If tile is fully transparent, don't serialize it and remove it if it exists
             if( byFirstAlphaVal == 0 )
             {
-                char* pszSQL = sqlite3_mprintf("DELETE FROM '%q' "
-                    "WHERE zoom_level = %d AND tile_row = %d AND tile_column = %d",
-                    m_osRasterTable.c_str(), m_nZoomLevel, GetRowFromIntoTopConvention(nRow), nCol);
-#ifdef DEBUG_VERBOSE
-                CPLDebug("GPKG", "%s", pszSQL);
-#endif
-                char* pszErrMsg = NULL;
-                int rc = sqlite3_exec(IGetDB(), pszSQL, NULL, NULL, &pszErrMsg);
-                if( rc != SQLITE_OK )
-                {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                            "Failure when deleting tile (row=%d,col=%d) at zoom_level=%d : %s",
-                            GetRowFromIntoTopConvention(nRow), nCol, m_nZoomLevel, pszErrMsg ? pszErrMsg : "");
-                }
-                sqlite3_free(pszSQL);
-                sqlite3_free(pszErrMsg);
+                DeleteTile(nRow, nCol);
+
                 return CE_None;
             }
             bAllOpaque = (byFirstAlphaVal == 255);
@@ -1232,9 +1625,10 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
     bool bTileDriverSupports4Bands = false;
     bool bTileDriverSupportsCT = false;
 
-    if( nBands == 1 )
+    if( nBands == 1 && m_eDT == GDT_Byte )
         IGetRasterBand(1)->GetColorTable();
 
+    GDALDataType eTileDT = GDT_Byte;
     if( m_eTF == GPKG_TF_PNG_JPEG )
     {
         bTileDriverSupports1Band = true;
@@ -1267,16 +1661,28 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
         pszDriverName = "WEBP";
         bTileDriverSupports4Bands = WEBPSupports4Bands();
     }
+    else if( m_eTF == GPKG_TF_PNG_16BIT )
+    {
+        pszDriverName = "PNG";
+        eTileDT = GDT_UInt16;
+        bTileDriverSupports1Band = true;
+    }
+    else if( m_eTF == GPKG_TF_TIFF_32BIT_FLOAT )
+    {
+        pszDriverName = "GTiff";
+        eTileDT = GDT_Float32;
+        bTileDriverSupports1Band = true;
+    }
     else
     {
-        CPLAssert(0);
+        CPLAssert(false);
     }
 
     GDALDriver* l_poDriver = (GDALDriver*) GDALGetDriverByName(pszDriverName);
     if( l_poDriver != NULL)
     {
         GDALDataset* poMEMDS = MEMDataset::Create("", nBlockXSize, nBlockYSize,
-                                                  0, GDT_Byte, NULL);
+                                                  0, eTileDT, NULL);
         int nTileBands = nBands;
         if( bPartialTile && nBands == 1 && m_poCT == NULL && bTileDriverSupports2Bands )
             nTileBands = 2;
@@ -1325,36 +1731,277 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
         if( bPartialTile && (nTileBands == 2 || nTileBands == 4) )
         {
             int nTargetAlphaBand = nTileBands;
-            memset(m_pabyCachedTiles + (nTargetAlphaBand-1) * nBlockXSize * nBlockYSize, 0,
-                  nBlockXSize * nBlockYSize);
+            memset(m_pabyCachedTiles + (nTargetAlphaBand-1) * nBandBlockSize, 0,
+                   nBandBlockSize);
             for(int iY = iYOff; iY < iYOff + iYCount; iY ++)
             {
-                memset(m_pabyCachedTiles + ((nTargetAlphaBand-1) * nBlockYSize + iY) * nBlockXSize + iXOff,
+                memset(m_pabyCachedTiles + (static_cast<size_t>(nTargetAlphaBand-1) * nBlockYSize + iY) * nBlockXSize + iXOff,
                        255, iXCount);
             }
         }
 
-        for( int i = 0; i < nTileBands; i++ )
+        GUInt16* pTempTileBuffer = NULL;
+        int nValidPixels = 0;
+        double dfTileMin = 0.0;
+        double dfTileMax = 0.0;
+        double dfTileMean = 0.0;
+        double dfTileStdDev = 0.0;
+        int bHasNoData = FALSE;
+        double dfNoDataValue = IGetRasterBand(1)->GetNoDataValue(&bHasNoData);
+        double dfTileOffset = 0.0;
+        double dfTileScale = 1.0;
+        if( m_eTF == GPKG_TF_PNG_16BIT )
+        {
+            pTempTileBuffer = static_cast<GUInt16*>(
+                VSI_MALLOC3_VERBOSE(2, nBlockXSize, nBlockYSize));
+
+            if( m_eDT == GDT_Int16 )
+            {
+                ProcessInt16UInt16Tile<GInt16>( m_pabyCachedTiles,
+                                                nBlockXSize * nBlockYSize,
+                                                true,
+                                                CPL_TO_BOOL(bHasNoData),
+                                                dfNoDataValue,
+                                                m_usGPKGNull,
+                                                m_dfOffset,
+                                                m_dfScale,
+                                                pTempTileBuffer,
+                                                dfTileOffset,
+                                                dfTileScale,
+                                                dfTileMin,
+                                                dfTileMax,
+                                                dfTileMean,
+                                                dfTileStdDev,
+                                                nValidPixels );
+            }
+            else if( m_eDT == GDT_UInt16 )
+            {
+                ProcessInt16UInt16Tile<GUInt16>( m_pabyCachedTiles,
+                                                nBlockXSize * nBlockYSize,
+                                                false,
+                                                CPL_TO_BOOL(bHasNoData),
+                                                dfNoDataValue,
+                                                m_usGPKGNull,
+                                                m_dfOffset,
+                                                m_dfScale,
+                                                pTempTileBuffer,
+                                                dfTileOffset,
+                                                dfTileScale,
+                                                dfTileMin,
+                                                dfTileMax,
+                                                dfTileMean,
+                                                dfTileStdDev,
+                                                nValidPixels );
+            }
+            else if( m_eDT == GDT_Float32 )
+            {
+                const float* pSrc = reinterpret_cast<float*>(
+                                                        m_pabyCachedTiles);
+                float fMin = 0.0f;
+                float fMax = 0.0f;
+                double dfM2 = 0.0;
+                const bool bHasNanNoData = bHasNoData &&
+                                           CPLIsNan(dfNoDataValue);
+                for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
+                {
+                    const float fVal = pSrc[i];
+                    if( bHasNanNoData )
+                    {
+                        if( CPLIsNan(fVal) )
+                            continue;
+                    }
+                    else if( bHasNoData && fVal == dfNoDataValue )
+                    {
+                        continue;
+                    }
+                    if( CPLIsInf(fVal) )
+                        continue;
+
+                    if( nValidPixels == 0 )
+                    {
+                        fMin = fVal;
+                        fMax = fVal;
+                    }
+                    else
+                    {
+                        fMin = std::min(fMin, fVal);
+                        fMax = std::max(fMax, fVal);
+                    }
+                    nValidPixels ++;
+                    const double dfDelta = fVal - dfTileMean;
+                    dfTileMean += dfDelta / nValidPixels;
+                    dfM2 += dfDelta * (fVal - dfTileMean);
+                }
+                dfTileMin = fMin;
+                dfTileMax = fMax;
+                if( nValidPixels )
+                    dfTileStdDev = sqrt( dfM2 / nValidPixels );
+
+                double dfGlobalMin = (fMin - m_dfOffset) / m_dfScale;
+                double dfGlobalMax = (fMax - m_dfOffset) / m_dfScale;
+                if( dfGlobalMax > dfGlobalMin )
+                {
+                    if( bHasNoData && m_usGPKGNull == 65535 &&
+                        dfGlobalMax - dfGlobalMin >= 65534.0 )
+                    {
+                        dfTileOffset = dfGlobalMin;
+                        dfTileScale = (dfGlobalMax - dfGlobalMin) / 65534.0;
+                    }
+                    else if( bHasNoData && m_usGPKGNull == 0 &&
+                             (dfNoDataValue - m_dfOffset) / m_dfScale != 0 )
+                    {
+                        dfTileOffset = (65535.0 * dfGlobalMin - dfGlobalMax) / 65534.0;
+                        dfTileScale = dfGlobalMin - dfTileOffset;
+                    }
+                    else
+                    {
+                        dfTileOffset = dfGlobalMin;
+                        dfTileScale = (dfGlobalMax - dfGlobalMin) / 65535.0;
+                    }
+                }
+
+                for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
+                {
+                    const float fVal = pSrc[i];
+                    if( bHasNanNoData )
+                    {
+                        if( CPLIsNan(fVal) )
+                        {
+                            pTempTileBuffer[i] = m_usGPKGNull;
+                            continue;
+                        }
+                    }
+                    else if( bHasNoData )
+                    {
+                        if( fVal == static_cast<float>(dfNoDataValue) )
+                        {
+                            pTempTileBuffer[i] = m_usGPKGNull;
+                            continue;
+                        }
+                    }
+                    double dfVal = CPLIsFinite(fVal) ?
+                        ((fVal - m_dfOffset) / m_dfScale -
+                                    dfTileOffset) / dfTileScale :
+                        (fVal > 0) ? 65535 : 0;
+                    CPLAssert( dfVal >= 0.0 && dfVal < 65535.5);
+                    pTempTileBuffer[i] = static_cast<GUInt16>(dfVal+0.5);
+                    if( bHasNoData && pTempTileBuffer[i] == m_usGPKGNull )
+                    {
+                        if( m_usGPKGNull > 0 )
+                            pTempTileBuffer[i] --;
+                        else
+                            pTempTileBuffer[i] ++;
+                    }
+                }
+            }
+
+            char** papszOptions = NULL;
+            char szDataPointer[32];
+            int nRet = CPLPrintPointer(szDataPointer, pTempTileBuffer,
+                                       sizeof(szDataPointer));
+            szDataPointer[nRet] = '\0';
+            papszOptions = CSLSetNameValue(papszOptions,
+                                            "DATAPOINTER", szDataPointer);
+            poMEMDS->AddBand(GDT_UInt16, papszOptions);
+            CSLDestroy(papszOptions);
+        }
+        else if( m_eTF == GPKG_TF_TIFF_32BIT_FLOAT )
         {
+            const float* pSrc = reinterpret_cast<float*>(m_pabyCachedTiles);
+            float fMin = 0.0f;
+            float fMax = 0.0f;
+            double dfM2 = 0.0;
+            const bool bHasNanNoData = bHasNoData && CPLIsNan(dfNoDataValue);
+            for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
+            {
+                const float fVal = pSrc[i];
+                if( bHasNanNoData )
+                {
+                    if( CPLIsNan(fVal) )
+                        continue;
+                }
+                else if( bHasNoData && fVal == dfNoDataValue )
+                {
+                    continue;
+                }
+
+                if( nValidPixels == 0 )
+                {
+                    fMin = fVal;
+                    fMax = fVal;
+                }
+                else
+                {
+                    fMin = std::min(fMin, fVal);
+                    fMax = std::max(fMax, fVal);
+                }
+                nValidPixels ++;
+                const double dfDelta = fVal - dfTileMean;
+                dfTileMean += dfDelta / nValidPixels;
+                dfM2 += dfDelta * (fVal - dfTileMean);
+            }
+            dfTileMin = fMin;
+            dfTileMax = fMax;
+            if( nValidPixels )
+                dfTileStdDev = sqrt( dfM2 / nValidPixels );
+
             char** papszOptions = NULL;
             char szDataPointer[32];
-            int iSrc = i;
-            if( nBands == 1 && m_poCT == NULL && nTileBands == 3 )
-                iSrc = 0;
-            else if( nBands == 1 && m_poCT == NULL && bPartialTile && nTileBands == 4 )
-                iSrc = (i < 3) ? 0 : 3;
-            else if( nBands == 2 && nTileBands >= 3 )
-                iSrc = (i < 3) ? 0 : 1;
             int nRet = CPLPrintPointer(szDataPointer,
-                                       m_pabyCachedTiles + iSrc * nBlockXSize * nBlockYSize,
-                                       sizeof(szDataPointer));
+                        m_pabyCachedTiles,
+                        sizeof(szDataPointer));
             szDataPointer[nRet] = '\0';
-            papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szDataPointer);
-            poMEMDS->AddBand(GDT_Byte, papszOptions);
-            if( i == 0 && nTileBands == 1 && m_poCT != NULL )
-                poMEMDS->GetRasterBand(1)->SetColorTable(m_poCT);
+            papszOptions = CSLSetNameValue(papszOptions,
+                                            "DATAPOINTER", szDataPointer);
+            poMEMDS->AddBand(GDT_Float32, papszOptions);
             CSLDestroy(papszOptions);
         }
+        else
+        {
+            CPLAssert( m_eDT == GDT_Byte );
+            for( int i = 0; i < nTileBands; i++ )
+            {
+                char** papszOptions = NULL;
+                char szDataPointer[32];
+                int iSrc = i;
+                if( nBands == 1 && m_poCT == NULL && nTileBands == 3 )
+                    iSrc = 0;
+                else if( nBands == 1 && m_poCT == NULL && bPartialTile &&
+                         nTileBands == 4 )
+                    iSrc = (i < 3) ? 0 : 3;
+                else if( nBands == 2 && nTileBands >= 3 )
+                    iSrc = (i < 3) ? 0 : 1;
+                int nRet = CPLPrintPointer(szDataPointer,
+                        m_pabyCachedTiles + iSrc * nBlockXSize * nBlockYSize,
+                        sizeof(szDataPointer));
+                szDataPointer[nRet] = '\0';
+                papszOptions = CSLSetNameValue(papszOptions,
+                                               "DATAPOINTER", szDataPointer);
+                poMEMDS->AddBand(GDT_Byte, papszOptions);
+                if( i == 0 && nTileBands == 1 && m_poCT != NULL )
+                    poMEMDS->GetRasterBand(1)->SetColorTable(m_poCT);
+                CSLDestroy(papszOptions);
+            }
+        }
+
+        if( (m_eTF == GPKG_TF_PNG_16BIT ||
+             m_eTF == GPKG_TF_TIFF_32BIT_FLOAT) &&
+            nValidPixels == 0 )
+        {
+            // If tile is fully transparent, don't serialize it and remove
+            // it if it exists.
+            GIntBig nId = GetTileId(nRow, nCol);
+            if( nId > 0 )
+            {
+                DeleteTile(nRow, nCol);
+
+                DeleteFromGriddedTileAncillary(nId);
+            }
+
+            CPLFree(pTempTileBuffer);
+            delete poMEMDS;
+            return CE_None;
+        }
 
         if( m_eTF == GPKG_TF_PNG8 && nTileBands == 1 && nBands >= 3 )
         {
@@ -1365,7 +2012,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
                 char** papszOptions = NULL;
                 char szDataPointer[32];
                 int nRet = CPLPrintPointer(szDataPointer,
-                                        m_pabyCachedTiles + i * nBlockXSize * nBlockYSize,
+                                        m_pabyCachedTiles + i * nBandBlockSize,
                                         sizeof(szDataPointer));
                 szDataPointer[nRet] = '\0';
                 papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szDataPointer);
@@ -1387,8 +2034,8 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
                                        poMEM_RGB_DS->GetRasterBand(3),
                                        /*NULL, NULL, NULL,*/
                                        m_pabyCachedTiles,
-                                       m_pabyCachedTiles + nBlockXSize * nBlockYSize,
-                                       m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize,
+                                       m_pabyCachedTiles + nBandBlockSize,
+                                       m_pabyCachedTiles + 2 * nBandBlockSize,
                                        NULL,
                                        256, /* max colors */
                                        8, /* bit depth */
@@ -1412,7 +2059,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
         else if( nBands == 1 && m_poCT != NULL && nTileBands > 1 )
         {
             GByte abyCT[4*256];
-            int nEntries = MIN(256, m_poCT->GetColorEntryCount());
+            const int nEntries = std::min(256, m_poCT->GetColorEntryCount());
             for( int i = 0; i < nEntries; i++ )
             {
                 const GDALColorEntry* psEntry = m_poCT->GetColorEntry(i);
@@ -1430,10 +2077,10 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
             }
             if( iYOff > 0 )
             {
-                memset(m_pabyCachedTiles + 0 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
-                memset(m_pabyCachedTiles + 1 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
-                memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
-                memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize, 0, nBlockXSize * iYOff);
+                memset(m_pabyCachedTiles + 0 * nBandBlockSize, 0, nBlockXSize * iYOff);
+                memset(m_pabyCachedTiles + 1 * nBandBlockSize, 0, nBlockXSize * iYOff);
+                memset(m_pabyCachedTiles + 2 * nBandBlockSize, 0, nBlockXSize * iYOff);
+                memset(m_pabyCachedTiles + 3 * nBandBlockSize, 0, nBlockXSize * iYOff);
             }
             int i = 0;  // TODO: Rename variable to make it clear what it is.
             for(int iY = iYOff; iY < iYOff + iYCount; iY ++)
@@ -1441,36 +2088,36 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
                 if( iXOff > 0 )
                 {
                     i = iY * nBlockXSize;
-                    memset(m_pabyCachedTiles + 0 * nBlockXSize * nBlockYSize + i, 0, iXOff);
-                    memset(m_pabyCachedTiles + 1 * nBlockXSize * nBlockYSize + i, 0, iXOff);
-                    memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize + i, 0, iXOff);
-                    memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize + i, 0, iXOff);
+                    memset(m_pabyCachedTiles + 0 * nBandBlockSize + i, 0, iXOff);
+                    memset(m_pabyCachedTiles + 1 * nBandBlockSize + i, 0, iXOff);
+                    memset(m_pabyCachedTiles + 2 * nBandBlockSize + i, 0, iXOff);
+                    memset(m_pabyCachedTiles + 3 * nBandBlockSize + i, 0, iXOff);
                 }
                 for(int iX = iXOff; iX < iXOff + iXCount; iX ++)
                 {
                     i = iY * nBlockXSize + iX;
                     GByte byVal = m_pabyCachedTiles[i];
                     m_pabyCachedTiles[i] = abyCT[4*byVal];
-                    m_pabyCachedTiles[i + 1 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+1];
-                    m_pabyCachedTiles[i + 2 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+2];
-                    m_pabyCachedTiles[i + 3 * nBlockXSize * nBlockYSize] = abyCT[4*byVal+3];
+                    m_pabyCachedTiles[i + 1 * nBandBlockSize] = abyCT[4*byVal+1];
+                    m_pabyCachedTiles[i + 2 * nBandBlockSize] = abyCT[4*byVal+2];
+                    m_pabyCachedTiles[i + 3 * nBandBlockSize] = abyCT[4*byVal+3];
                 }
                 if( iXOff + iXCount < nBlockXSize )
                 {
                     i = iY * nBlockXSize + iXOff + iXCount;
-                    memset(m_pabyCachedTiles + 0 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize - (iXOff + iXCount));
-                    memset(m_pabyCachedTiles + 1 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize - (iXOff + iXCount));
-                    memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize - (iXOff + iXCount));
-                    memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize - (iXOff + iXCount));
+                    memset(m_pabyCachedTiles + 0 * nBandBlockSize + i, 0, nBlockXSize - (iXOff + iXCount));
+                    memset(m_pabyCachedTiles + 1 * nBandBlockSize + i, 0, nBlockXSize - (iXOff + iXCount));
+                    memset(m_pabyCachedTiles + 2 * nBandBlockSize + i, 0, nBlockXSize - (iXOff + iXCount));
+                    memset(m_pabyCachedTiles + 3 * nBandBlockSize + i, 0, nBlockXSize - (iXOff + iXCount));
                 }
             }
             if( iYOff + iYCount < nBlockYSize )
             {
                 i = (iYOff + iYCount) * nBlockXSize;
-                memset(m_pabyCachedTiles + 0 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
-                memset(m_pabyCachedTiles + 1 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
-                memset(m_pabyCachedTiles + 2 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
-                memset(m_pabyCachedTiles + 3 * nBlockXSize * nBlockYSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
+                memset(m_pabyCachedTiles + 0 * nBandBlockSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
+                memset(m_pabyCachedTiles + 1 * nBandBlockSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
+                memset(m_pabyCachedTiles + 2 * nBandBlockSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
+                memset(m_pabyCachedTiles + 3 * nBandBlockSize + i, 0, nBlockXSize * (nBlockYSize - (iYOff + iYCount)));
             }
         }
 
@@ -1485,6 +2132,11 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
             papszDriverOptions = CSLSetNameValue(
                 papszDriverOptions, "ZLEVEL", CPLSPrintf("%d", m_nZLevel));
         }
+        else if( EQUAL(pszDriverName, "GTiff") )
+        {
+            papszDriverOptions = CSLSetNameValue(
+                papszDriverOptions, "COMPRESS", "LZW");
+        }
 #ifdef DEBUG
         VSIStatBufL sStat;
         CPLAssert(VSIStatL(osMemFileName, &sStat) != 0);
@@ -1492,6 +2144,8 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
         GDALDataset* poOutDS = l_poDriver->CreateCopy(osMemFileName, poMEMDS,
                                                     FALSE, papszDriverOptions, NULL, NULL);
         CSLDestroy( papszDriverOptions );
+        CPLFree(pTempTileBuffer);
+
         if( poOutDS )
         {
             GDALClose( poOutDS );
@@ -1520,17 +2174,18 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
             }
             poMainDS->m_nTileInsertionCount ++;
 
-            char* pszSQL = sqlite3_mprintf("INSERT OR REPLACE INTO '%q' "
+            char* pszSQL = sqlite3_mprintf("INSERT OR REPLACE INTO \"%w\" "
                 "(zoom_level, tile_row, tile_column, tile_data) VALUES (%d, %d, %d, ?)",
                 m_osRasterTable.c_str(), m_nZoomLevel, GetRowFromIntoTopConvention(nRow), nCol);
 #ifdef DEBUG_VERBOSE
             CPLDebug("GPKG", "%s", pszSQL);
 #endif
             sqlite3_stmt* hStmt = NULL;
-            int rc = sqlite3_prepare(IGetDB(), pszSQL, -1, &hStmt, NULL);
+            int rc = sqlite3_prepare_v2(IGetDB(), pszSQL, -1, &hStmt, NULL);
             if ( rc != SQLITE_OK )
             {
-                CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL %s: %s",
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "failed to prepare SQL %s: %s",
                           pszSQL, sqlite3_errmsg(IGetDB()) );
                 CPLFree(pabyBlob);
             }
@@ -1549,6 +2204,59 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteTileInternal()
             }
             sqlite3_finalize(hStmt);
             sqlite3_free(pszSQL);
+
+            if( m_eTF == GPKG_TF_PNG_16BIT ||
+                m_eTF == GPKG_TF_TIFF_32BIT_FLOAT )
+            {
+                GIntBig nTileId = GetTileId(nRow, nCol);
+                if( nTileId == 0 )
+                    eErr = CE_Failure;
+                else
+                {
+                    DeleteFromGriddedTileAncillary(nTileId);
+
+                    pszSQL = sqlite3_mprintf(
+                        "INSERT INTO gpkg_2d_gridded_tile_ancillary "
+                        "(tpudt_name, tpudt_id, scale, offset, min, max, "
+                        "mean, std_dev) VALUES "
+                        "('%q', ?, %.18g, %.18g, ?, ?, ?, ?)",
+                        m_osRasterTable.c_str(), dfTileScale, dfTileOffset);
+#ifdef DEBUG_VERBOSE
+                    CPLDebug("GPKG", "%s", pszSQL);
+#endif
+                    hStmt = NULL;
+                    rc = sqlite3_prepare_v2(IGetDB(), pszSQL, -1, &hStmt, NULL);
+                    if ( rc != SQLITE_OK )
+                    {
+                        eErr = CE_Failure;
+                        CPLError( CE_Failure, CPLE_AppDefined,
+                                  "failed to prepare SQL %s: %s",
+                                  pszSQL, sqlite3_errmsg(IGetDB()) );
+                    }
+                    else
+                    {
+                        sqlite3_bind_int64( hStmt, 1, nTileId );
+                        sqlite3_bind_double( hStmt, 2, dfTileMin );
+                        sqlite3_bind_double( hStmt, 3, dfTileMax );
+                        sqlite3_bind_double( hStmt, 4, dfTileMean );
+                        sqlite3_bind_double( hStmt, 5, dfTileStdDev );
+                        rc = sqlite3_step( hStmt );
+                        if( rc == SQLITE_DONE )
+                        {
+                            eErr = CE_None;
+                        }
+                        else
+                        {
+                            CPLError(CE_Failure, CPLE_AppDefined,
+                                "Cannot insert into "
+                                "gpkg_2d_gridded_tile_ancillary");
+                            eErr = CE_Failure;
+                        }
+                    }
+                    sqlite3_finalize(hStmt);
+                    sqlite3_free(pszSQL);
+                }
+            }
         }
 
         VSIUnlink(osMemFileName);
@@ -1625,7 +2333,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushRemainingShiftedTiles(bool bPartia
     int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, -1, &hStmt, NULL);
     if ( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
                   pszSQL, sqlite3_errmsg( m_hTempDB ) );
         return CE_Failure;
     }
@@ -1633,6 +2341,8 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushRemainingShiftedTiles(bool bPartia
     CPLErr eErr = CE_None;
     bool bGotPartialTiles = false;
     int nCountFlushedTiles = 0;
+    const size_t nBandBlockSize = static_cast<size_t>(nBlockXSize) *
+                                                nBlockYSize * m_nDTSize;
     do
     {
         rc = sqlite3_step(hStmt);
@@ -1696,16 +2406,16 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushRemainingShiftedTiles(bool bPartia
             {
                 if( nPartialFlags & (((1 << 4)-1) << (4*(nBand - 1))) )
                 {
-                    CPLAssert( sqlite3_column_bytes(hStmt, 2 + nBand) == nBlockXSize * nBlockYSize );
-                    memcpy( m_pabyCachedTiles + (nBand-1) * nBlockXSize * nBlockYSize,
+                    CPLAssert( sqlite3_column_bytes(hStmt, 2 + nBand) ==
+                                    static_cast<int>(nBandBlockSize) );
+                    memcpy( m_pabyCachedTiles + (nBand-1) * nBandBlockSize,
                             sqlite3_column_blob(hStmt, 2 + nBand),
-                            nBlockXSize * nBlockYSize );
+                            nBandBlockSize);
                 }
                 else
                 {
-                    memset( m_pabyCachedTiles + (nBand-1) * nBlockXSize * nBlockYSize,
-                            0,
-                            nBlockXSize * nBlockYSize );
+                    FillEmptyTileSingleBand(
+                        m_pabyCachedTiles + (nBand-1) * nBandBlockSize );
                 }
             }
 
@@ -1717,21 +2427,24 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushRemainingShiftedTiles(bool bPartia
             // temporary database
             if( nPartialFlags != nFullFlags )
             {
-                char* pszNewSQL = sqlite3_mprintf("SELECT tile_data FROM '%q' "
+                char* pszNewSQL = sqlite3_mprintf(
+                        "SELECT tile_data%s FROM \"%w\" "
                         "WHERE zoom_level = %d AND tile_row = %d AND tile_column = %d%s",
+                        m_eDT != GDT_Byte ? ", id" : "", // MBTiles do not have an id
                         m_osRasterTable.c_str(), m_nZoomLevel, GetRowFromIntoTopConvention(nRow), nCol,
-                        m_osWHERE.size() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
+                        !m_osWHERE.empty() ? CPLSPrintf(" AND (%s)", m_osWHERE.c_str()): "");
 #ifdef DEBUG_VERBOSE
                 CPLDebug("GPKG", "%s", pszNewSQL);
 #endif
                 sqlite3_stmt* hNewStmt = NULL;
-                rc = sqlite3_prepare(IGetDB(), pszNewSQL, -1, &hNewStmt, NULL);
+                rc = sqlite3_prepare_v2(IGetDB(), pszNewSQL, -1, &hNewStmt, NULL);
                 if ( rc == SQLITE_OK )
                 {
                     rc = sqlite3_step( hNewStmt );
                     if( rc == SQLITE_ROW && sqlite3_column_type( hNewStmt, 0 ) == SQLITE_BLOB )
                     {
                         const int nBytes = sqlite3_column_bytes( hNewStmt, 0 );
+                        GIntBig nTileId = (m_eDT == GDT_Byte ) ? 0 : sqlite3_column_int64( hNewStmt, 1 );
                         GByte* pabyRawData = (GByte*)sqlite3_column_blob( hNewStmt, 0 );
                         CPLString osMemFileName;
                         osMemFileName.Printf("/vsimem/gpkg_read_tile_%p", this);
@@ -1739,8 +2452,13 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushRemainingShiftedTiles(bool bPartia
                                                               nBytes, FALSE);
                         VSIFCloseL(fp);
 
+                        double dfTileOffset = 0.0;
+                        double dfTileScale = 1.0;
+                        GetTileOffsetAndScale(nTileId,
+                                              dfTileOffset, dfTileScale);
                         ReadTile(osMemFileName,
-                                 m_pabyCachedTiles + 4 * nBlockXSize * nBlockYSize);
+                                 m_pabyCachedTiles + 4 * nBandBlockSize,
+                                 dfTileOffset, dfTileScale);
                         VSIUnlink(osMemFileName);
 
                         int iYQuadrantMax = ( m_nShiftYPixelsMod ) ? 1 : 0;
@@ -1786,9 +2504,11 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushRemainingShiftedTiles(bool bPartia
                                         }
                                         for( int iY = nYOff; iY < nYOff + nYSize; iY ++ )
                                         {
-                                            memcpy( m_pabyCachedTiles + ((nBand - 1) * nBlockYSize + iY) * nBlockXSize + nXOff,
-                                                    m_pabyCachedTiles + ((4 + nBand - 1) * nBlockYSize + iY) * nBlockXSize + nXOff,
-                                                    nXSize );
+                                            memcpy( m_pabyCachedTiles +
+                                                        ((static_cast<size_t>(nBand - 1) * nBlockYSize + iY) * nBlockXSize + nXOff) * m_nDTSize,
+                                                    m_pabyCachedTiles +
+                                                        ((static_cast<size_t>(4 + nBand - 1) * nBlockYSize + iY) * nBlockXSize + nXOff) * m_nDTSize,
+                                                    nXSize * m_nDTSize );
                                         }
                                     }
                                 }
@@ -1804,7 +2524,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::FlushRemainingShiftedTiles(bool bPartia
                 }
                 else
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+                    CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
                               pszNewSQL, sqlite3_errmsg( m_hTempDB ) );
                 }
                 sqlite3_free(pszNewSQL);
@@ -1916,9 +2636,12 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::DoPartialFlushOfPartialTilesIfNecessary
                 IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
                 const int nBands = IGetRasterCount();
 
-                if( nTempSpace > 4 * static_cast<GIntBig>(IGetRasterBand(1)->GetXSize())  * nBlockYSize * nBands )
+                if( nTempSpace > 4 * static_cast<GIntBig>(
+                        IGetRasterBand(1)->GetXSize())  *
+                        nBlockYSize * nBands * m_nDTSize )
                 {
-                    CPLDebug("GPKG", "Partial tiles DB is " CPL_FRMT_GIB " bytes. Flushing part of partial tiles",
+                    CPLDebug("GPKG", "Partial tiles DB is " CPL_FRMT_GIB
+                             " bytes. Flushing part of partial tiles",
                              nTempSpace);
                     bTryFreeing = true;
                 }
@@ -1962,16 +2685,16 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
         CPLPopErrorHandler();
         m_hTempDB = NULL;
         int rc = 0;
-#ifdef HAVE_SQLITE_VFS
         if (STARTS_WITH(m_osTempDBFilename, "/vsi"))
         {
             m_pMyVFS = OGRSQLiteCreateVFS(NULL, NULL);
             sqlite3_vfs_register(m_pMyVFS, 0);
             rc = sqlite3_open_v2( m_osTempDBFilename, &m_hTempDB,
-                             SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, m_pMyVFS->zName );
+                                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+                                  SQLITE_OPEN_NOMUTEX,
+                                  m_pMyVFS->zName );
         }
         else
-#endif
         {
             rc = sqlite3_open(m_osTempDBFilename, &m_hTempDB);
         }
@@ -2015,6 +2738,8 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
     int nBlockXSize, nBlockYSize;
     IGetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
     const int nBands = IGetRasterCount();
+    const size_t nBandBlockSize = static_cast<size_t>(nBlockXSize) *
+                                                nBlockYSize * m_nDTSize;
 
     int iQuadrantFlag = 0;
     if( nDstXOffset == 0 && nDstYOffset == 0 )
@@ -2047,7 +2772,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
     int rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, -1, &hStmt, NULL);
     if ( rc != SQLITE_OK )
     {
-        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
                   pszSQL, sqlite3_errmsg( m_hTempDB ) );
         return CE_Failure;
     }
@@ -2063,23 +2788,22 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
         CPLAssert(nOldFlags != 0);
         if( (nOldFlags & (((1 << 4)-1) << (4*(nBand - 1)))) == 0 )
         {
-            memset( m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
-                    0,
-                    nBlockXSize * nBlockYSize );
+            FillEmptyTileSingleBand( m_pabyCachedTiles + (4 + nBand - 1) *
+                                                            nBandBlockSize );
         }
         else
         {
-            CPLAssert( sqlite3_column_bytes(hStmt, 2) == nBlockXSize * nBlockYSize );
-            memcpy( m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
+            CPLAssert( sqlite3_column_bytes(hStmt, 2) ==
+                                    static_cast<int>(nBandBlockSize) );
+            memcpy( m_pabyCachedTiles + (4 + nBand - 1) * nBandBlockSize,
                     sqlite3_column_blob(hStmt, 2),
-                    nBlockXSize * nBlockYSize );
+                    nBandBlockSize );
         }
     }
     else
     {
-        memset( m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
-                0,
-                nBlockXSize * nBlockYSize );
+        FillEmptyTileSingleBand( m_pabyCachedTiles + (4 + nBand - 1) *
+                                 nBandBlockSize );
     }
     sqlite3_finalize(hStmt);
     hStmt = NULL;
@@ -2087,22 +2811,24 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
     /* Copy the updated rectangle into the full tile */
     for(int iY = nDstYOffset; iY < nDstYOffset + nDstYSize; iY ++ )
     {
-        memcpy( m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize +
-                    iY * nBlockXSize + nDstXOffset,
-                m_pabyCachedTiles + (nBand - 1) * nBlockXSize * nBlockYSize +
-                    iY * nBlockXSize + nDstXOffset,
-                nDstXSize );
+        memcpy( m_pabyCachedTiles + (static_cast<size_t>(4 + nBand - 1) *
+                    nBlockXSize * nBlockYSize +
+                    iY * nBlockXSize + nDstXOffset) * m_nDTSize,
+                m_pabyCachedTiles + (static_cast<size_t>(nBand - 1) *
+                    nBlockXSize * nBlockYSize +
+                    iY * nBlockXSize + nDstXOffset) * m_nDTSize,
+                nDstXSize * m_nDTSize );
     }
 
 #ifdef notdef
     static int nCounter = 1;
     GDALDataset* poLogDS = ((GDALDriver*)GDALGetDriverByName("GTiff"))->Create(
                 CPLSPrintf("/tmp/partial_band_%d_%d.tif", 1, nCounter++),
-                nBlockXSize, nBlockYSize, nBands, GDT_Byte, NULL);
+                nBlockXSize, nBlockYSize, nBands, m_eDT, NULL);
     poLogDS->RasterIO(GF_Write, 0, 0, nBlockXSize, nBlockYSize,
-                      m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
+                      m_pabyCachedTiles + (4 + nBand - 1) * nBandBlockSize,
                       nBlockXSize, nBlockYSize,
-                      GDT_Byte,
+                      m_eDT,
                       1, NULL,
                       0, 0, 0, NULL);
     GDALClose(poLogDS);
@@ -2134,7 +2860,7 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
                 rc = sqlite3_prepare_v2(m_hTempDB, pszSQL, -1, &hStmt, NULL);
                 if ( rc != SQLITE_OK )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare(%s) failed: %s",
+                    CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
                             pszSQL, sqlite3_errmsg( m_hTempDB ) );
                     return CE_Failure;
                 }
@@ -2142,19 +2868,20 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
                 rc = sqlite3_step(hStmt);
                 if ( rc == SQLITE_ROW )
                 {
-                    CPLAssert( sqlite3_column_bytes(hStmt, 0) == nBlockXSize * nBlockYSize );
-                    memcpy( m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize,
+                    CPLAssert( sqlite3_column_bytes(hStmt, 0) ==
+                                        static_cast<int>(nBandBlockSize) );
+                    memcpy( m_pabyCachedTiles + (iBand - 1) * nBandBlockSize,
                             sqlite3_column_blob(hStmt, 0),
-                            nBlockXSize * nBlockYSize );
+                            nBandBlockSize );
                 }
                 sqlite3_finalize(hStmt);
                 hStmt = NULL;
             }
             else
             {
-                memcpy( m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize,
-                        m_pabyCachedTiles + (4 + iBand - 1) * nBlockXSize * nBlockYSize,
-                        nBlockXSize * nBlockYSize );
+                memcpy( m_pabyCachedTiles + (iBand - 1) * nBandBlockSize,
+                        m_pabyCachedTiles + (4 + iBand - 1) * nBandBlockSize,
+                        nBandBlockSize );
             }
         }
 
@@ -2237,8 +2964,8 @@ CPLErr GDALGPKGMBTilesLikePseudoDataset::WriteShiftedTile(int nRow, int nCol, in
     }
 
     sqlite3_bind_blob( hStmt, 1,
-                       m_pabyCachedTiles + (4 + nBand - 1) * nBlockXSize * nBlockYSize,
-                       nBlockXSize * nBlockYSize,
+                       m_pabyCachedTiles + (4 + nBand - 1) * nBandBlockSize,
+                       static_cast<int>(nBandBlockSize),
                        SQLITE_TRANSIENT );
     rc = sqlite3_step( hStmt );
     CPLErr eErr = CE_Failure;
@@ -2363,16 +3090,20 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff
                 if( m_poTPD->m_nShiftXPixelsMod == 0 && m_poTPD->m_nShiftYPixelsMod == 0 )
                     m_poTPD->m_asCachedTilesDesc[0].abBandDirty[iBand - 1] = true;
 
-                int nDstXOffset = 0, nDstXSize = nBlockXSize,
-                    nDstYOffset = 0, nDstYSize = nBlockYSize;
-                int nSrcXOffset = 0, nSrcYOffset = 0;
+                int nDstXOffset = 0;
+                int nDstXSize = nBlockXSize;
+                int nDstYOffset = 0;
+                int nDstYSize = nBlockYSize;
+                int nSrcXOffset = 0;
+                int nSrcYOffset = 0;
                 // Composite block data into tile data
                 if( m_poTPD->m_nShiftXPixelsMod == 0 && m_poTPD->m_nShiftYPixelsMod == 0 )
                 {
 
 #ifdef DEBUG_VERBOSE
-                    if( (nBlockXOff+1) * nBlockXSize <= nRasterXSize &&
-                        (nBlockYOff+1) * nBlockYSize > nRasterYSize )
+                    if( eDataType == GDT_Byte &&
+                        nBlockXOff * nBlockXSize <= nRasterXSize - nBlockXSize &&
+                        nBlockYOff * nBlockYSize > nRasterYSize - nBlockYSize)
                     {
                         bool bFoundNonZero = false;
                         for(int y = nRasterYSize - nBlockYOff * nBlockYSize; y < nBlockYSize; y++)
@@ -2390,8 +3121,13 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff
                     }
 #endif
 
-                    memcpy( m_poTPD->m_pabyCachedTiles + (iBand - 1) * nBlockXSize * nBlockYSize,
-                            pabySrc, nBlockXSize * nBlockYSize );
+                    const size_t nBandBlockSize =
+                        static_cast<size_t>(nBlockXSize) *
+                                                nBlockYSize * m_nDTSize;
+                    memcpy( m_poTPD->m_pabyCachedTiles +
+                                                (iBand - 1) * nBandBlockSize,
+                            pabySrc,
+                            nBandBlockSize );
 
                     // Make sure partial blocks are zero'ed outside of the validity area
                     // but do that only when know that JPEG will not be used so as to
@@ -2399,8 +3135,8 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff
                     // if we really want to do that, but that only makes sense if readers
                     // only clip to the gpkg_contents extent). Well, ere on the safe side for now
                     if( m_poTPD->m_eTF != GPKG_TF_JPEG &&
-                        ((nBlockXOff+1) * nBlockXSize >= nRasterXSize ||
-                         (nBlockYOff+1) * nBlockYSize >= nRasterYSize) )
+                        (nBlockXOff * nBlockXSize >= nRasterXSize - nBlockXSize ||
+                         nBlockYOff * nBlockYSize >= nRasterYSize - nBlockYSize) )
                     {
                         int nXEndValidity = nRasterXSize - nBlockXOff * nBlockXSize;
                         if( nXEndValidity > nBlockXSize )
@@ -2412,19 +3148,20 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff
                         {
                             for( int iY = 0; iY < nYEndValidity; iY++ )
                             {
-                                memset( m_poTPD->m_pabyCachedTiles + ((iBand - 1) * nBlockYSize + iY) * nBlockXSize + nXEndValidity,
-                                        0,
-                                        nBlockXSize - nXEndValidity );
+                                m_poTPD->FillBuffer( m_poTPD->m_pabyCachedTiles +
+                                        (((iBand - 1) * nBlockYSize + iY) *
+                                            nBlockXSize + nXEndValidity) * m_nDTSize,
+                                        nBlockXSize - nXEndValidity);
                             }
                         }
                         if( nYEndValidity < nBlockYSize )
                         {
-                            memset( m_poTPD->m_pabyCachedTiles + ((iBand - 1) * nBlockYSize + nYEndValidity) * nBlockXSize,
-                                    0,
+                            m_poTPD->FillBuffer( m_poTPD->m_pabyCachedTiles +
+                                        ((iBand - 1) * nBlockYSize +
+                                            nYEndValidity) * nBlockXSize * m_nDTSize,
                                     (nBlockYSize - nYEndValidity) * nBlockXSize );
                         }
                     }
-
                 }
                 else
                 {
@@ -2465,13 +3202,13 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff
                     {
                         GByte* pDst =
                           m_poTPD->m_pabyCachedTiles +
-                          (iBand - 1) * nBlockXSize * nBlockYSize +
-                          (y + nDstYOffset) * nBlockXSize + nDstXOffset;
+                          ((iBand - 1) * nBlockXSize * nBlockYSize +
+                          (y + nDstYOffset) * nBlockXSize + nDstXOffset) * m_nDTSize;
                         GByte* pSrc =
-                            pabySrc + (y + nSrcYOffset) * nBlockXSize +
-                            nSrcXOffset;
-                        GDALCopyWords(pSrc, GDT_Byte, 1,
-                                    pDst, GDT_Byte, 1,
+                            pabySrc + ((y + nSrcYOffset) * nBlockXSize +
+                            nSrcXOffset) * m_nDTSize;
+                        GDALCopyWords(pSrc, eDataType, m_nDTSize,
+                                    pDst, eDataType, m_nDTSize,
                                     nDstXSize);
                     }
                 }
@@ -2506,12 +3243,37 @@ CPLErr GDALGPKGMBTilesLikeRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff
 }
 
 /************************************************************************/
+/*                           GetNoDataValue()                           */
+/************************************************************************/
+
+double GDALGPKGMBTilesLikeRasterBand::GetNoDataValue( int* pbSuccess )
+{
+    if( m_bHasNoData )
+    {
+        if( pbSuccess )
+            *pbSuccess = TRUE;
+        return m_dfNoDataValue;
+    }
+    return GDALPamRasterBand::GetNoDataValue(pbSuccess);
+}
+
+/************************************************************************/
+/*                        SetNoDataValueInternal()                      */
+/************************************************************************/
+
+void GDALGPKGMBTilesLikeRasterBand::SetNoDataValueInternal( double dfNoDataValue )
+{
+    m_bHasNoData = true;
+    m_dfNoDataValue = dfNoDataValue;
+}
+
+/************************************************************************/
 /*                      GDALGeoPackageRasterBand()                      */
 /************************************************************************/
 
 GDALGeoPackageRasterBand::GDALGeoPackageRasterBand(
     GDALGeoPackageDataset* poDSIn, int nTileWidth, int nTileHeight) :
-          GDALGPKGMBTilesLikeRasterBand(poDSIn, nTileWidth, nTileHeight)
+            GDALGPKGMBTilesLikeRasterBand(poDSIn, nTileWidth, nTileHeight)
 {
     poDS = poDSIn;
 }
@@ -2539,3 +3301,167 @@ GDALRasterBand* GDALGeoPackageRasterBand::GetOverview(int nIdx)
         return NULL;
     return poGDS->m_papoOverviewDS[nIdx]->GetRasterBand(nBand);
 }
+
+/************************************************************************/
+/*                           SetNoDataValue()                           */
+/************************************************************************/
+
+CPLErr GDALGeoPackageRasterBand::SetNoDataValue( double dfNoDataValue )
+{
+    if( eDataType == GDT_Byte )
+        return CE_None;
+
+    SetNoDataValueInternal(dfNoDataValue);
+
+    GDALGeoPackageDataset *poGDS
+        = reinterpret_cast<GDALGeoPackageDataset *>( poDS );
+    char* pszSQL = sqlite3_mprintf(
+        "UPDATE gpkg_2d_gridded_coverage_ancillary SET data_null = ? "
+        "WHERE tile_matrix_set_name = '%q'",
+        poGDS->m_osRasterTable.c_str());
+    sqlite3_stmt* hStmt = NULL;
+    int rc = sqlite3_prepare_v2(poGDS->IGetDB(), pszSQL, -1, &hStmt, NULL);
+    if( rc == SQLITE_OK )
+    {
+        if( poGDS->m_eTF == GPKG_TF_PNG_16BIT )
+        {
+            if( eDataType == GDT_UInt16 && poGDS->m_dfOffset == 0.0 &&
+                poGDS->m_dfScale == 1.0 &&
+                dfNoDataValue >= 0 && dfNoDataValue <= 65535 &&
+                static_cast<GUInt16>(dfNoDataValue) == dfNoDataValue )
+            {
+                poGDS->m_usGPKGNull = static_cast<GUInt16>(dfNoDataValue);
+            }
+            else
+            {
+                poGDS->m_usGPKGNull = 65535;
+            }
+            sqlite3_bind_double( hStmt, 1, poGDS->m_usGPKGNull );
+        }
+        else
+        {
+            sqlite3_bind_double( hStmt, 1,
+                                 static_cast<float>(dfNoDataValue) );
+        }
+        rc = sqlite3_step(hStmt);
+        sqlite3_finalize(hStmt);
+    }
+    sqlite3_free(pszSQL);
+
+    return (rc == SQLITE_OK) ? CE_None : CE_Failure;
+}
+
+/************************************************************************/
+/*                            GetMetadata()                             */
+/************************************************************************/
+
+char** GDALGeoPackageRasterBand::GetMetadata(const char* pszDomain)
+{
+    GDALGeoPackageDataset *poGDS
+        = reinterpret_cast<GDALGeoPackageDataset *>( poDS );
+
+    if( eDataType != GDT_Byte &&
+        (pszDomain == NULL || EQUAL(pszDomain, "")) &&
+        CSLFetchNameValue(GDALGPKGMBTilesLikeRasterBand::GetMetadata(),
+                          "STATISTICS_MINIMUM") == NULL )
+    {
+        const int nColMin = poGDS->m_nShiftXTiles;
+        const int nColMax = (nRasterXSize - 1 + poGDS->m_nShiftXPixelsMod) /
+                                        nBlockXSize + poGDS->m_nShiftXTiles;
+        const int nRowMin = poGDS->m_nShiftYTiles;
+        const int nRowMax = (nRasterYSize - 1 + poGDS->m_nShiftYPixelsMod) /
+                                        nBlockYSize + poGDS->m_nShiftYTiles;
+
+        bool bOK = false;
+        if( poGDS->m_nShiftXPixelsMod == 0 &&
+            poGDS->m_nShiftYPixelsMod == 0 &&
+            (nRasterXSize % nBlockXSize) == 0 &&
+            (nRasterYSize % nBlockYSize) == 0 )
+        {
+            // If the area of interest matches entire tiles, then we can
+            // use tile statistics
+            bOK = true;
+        }
+        else if( m_bHasNoData )
+        {
+            // Otherwise, in the case where we have nodata, we assume that
+            // if the area of interest is at least larger than the existing
+            // tiles, the tile statistics will be reliable.
+            char* pszSQL = sqlite3_mprintf(
+                "SELECT MIN(tile_column), MAX(tile_column), "
+                "MIN(tile_row), MAX(tile_row) FROM \"%w\" "
+                "WHERE zoom_level = %d",
+                poGDS->m_osRasterTable.c_str(),
+                poGDS->m_nZoomLevel);
+            SQLResult sResult;
+            if( SQLQuery( poGDS->IGetDB(), pszSQL, &sResult) == OGRERR_NONE &&
+                sResult.nRowCount == 1 )
+            {
+                const char* pszMinX = SQLResultGetValue(&sResult, 0, 0);
+                const char* pszMaxX = SQLResultGetValue(&sResult, 1, 0);
+                const char* pszMinY = SQLResultGetValue(&sResult, 2, 0);
+                const char* pszMaxY = SQLResultGetValue(&sResult, 3, 0);
+                if( pszMinX && pszMaxX && pszMinY && pszMaxY )
+                {
+                    bOK = atoi(pszMinX) >= nColMin &&
+                          atoi(pszMaxX) <= nColMax &&
+                          atoi(pszMinY) >= nRowMin &&
+                          atoi(pszMaxY) <= nRowMax;
+                }
+            }
+            SQLResultFree(&sResult);
+            sqlite3_free(pszSQL);
+        }
+
+        if( bOK )
+        {
+            char* pszSQL = sqlite3_mprintf(
+                "SELECT MIN(min), MAX(max) FROM "
+                "gpkg_2d_gridded_tile_ancillary t_a JOIN \"%w\" tpudt ON "
+                "t_a.tpudt_id = tpudt.id WHERE tpudt.zoom_level = %d AND "
+                "tpudt.tile_column >= %d AND tpudt.tile_column <= %d AND "
+                "tpudt.tile_row >= %d AND tpudt.tile_row <= %d",
+                poGDS->m_osRasterTable.c_str(),
+                poGDS->m_nZoomLevel,
+                nColMin, nColMax,
+                nRowMin, nRowMax);
+            SQLResult sResult;
+            if( SQLQuery( poGDS->IGetDB(), pszSQL, &sResult) == OGRERR_NONE &&
+                sResult.nRowCount == 1 )
+            {
+                const char* pszMin = SQLResultGetValue(&sResult, 0, 0);
+                const char* pszMax = SQLResultGetValue(&sResult, 1, 0);
+                if( pszMin )
+                {
+                    GDALGPKGMBTilesLikeRasterBand::SetMetadataItem(
+                        "STATISTICS_MINIMUM",
+                        CPLSPrintf("%.14g", CPLAtof(pszMin)) );
+                }
+                if( pszMax )
+                {
+                    GDALGPKGMBTilesLikeRasterBand::SetMetadataItem(
+                        "STATISTICS_MAXIMUM",
+                        CPLSPrintf("%.14g", CPLAtof(pszMax)) );
+                }
+            }
+            SQLResultFree(&sResult);
+            sqlite3_free(pszSQL);
+        }
+    }
+    return GDALGPKGMBTilesLikeRasterBand::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                          GetMetadataItem()                           */
+/************************************************************************/
+
+const char* GDALGeoPackageRasterBand::GetMetadataItem(const char* pszName,
+                                                      const char* pszDomain)
+{
+    if( eDataType != GDT_Byte &&
+        (pszDomain == NULL || EQUAL(pszDomain, "")) )
+    {
+        GetMetadata();
+    }
+    return GDALGPKGMBTilesLikeRasterBand::GetMetadataItem(pszName, pszDomain);
+}
diff --git a/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h b/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h
index 699e11a..88682d4 100644
--- a/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h
+++ b/ogr/ogrsf_frmts/gpkg/gpkgmbtilescommon.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gpkgmbtilescommon.h 35697 2016-10-11 18:44:52Z rouault $
+ * $Id: gpkgmbtilescommon.h 37560 2017-03-02 20:44:53Z rouault $
  *
  * Project:  GeoPackage/MBTiles Translator
  * Purpose:  Definition of common classes for GeoPackage and MBTiles drivers.
@@ -48,7 +48,9 @@ typedef enum
     GPKG_TF_PNG,
     GPKG_TF_PNG8,
     GPKG_TF_JPEG,
-    GPKG_TF_WEBP
+    GPKG_TF_WEBP,
+    GPKG_TF_PNG_16BIT, // For GPKG elevation data
+    GPKG_TF_TIFF_32BIT_FLOAT // For GPKG elevation data
 } GPKGTileFormat;
 
 GPKGTileFormat GDALGPKGMBTilesGetTileFormat(const char* pszTF );
@@ -62,6 +64,12 @@ class GDALGPKGMBTilesLikePseudoDataset
     bool                m_bHasModifiedTiles;
 
     CPLString           m_osRasterTable;
+    GDALDataType        m_eDT;
+    int                 m_nDTSize;
+    double              m_dfOffset;
+    double              m_dfScale;
+    double              m_dfPrecision;
+    GUInt16             m_usGPKGNull;
     int                 m_nZoomLevel;
     GByte              *m_pabyCachedTiles;
     CachedTileDesc      m_asCachedTilesDesc[4];
@@ -85,9 +93,7 @@ class GDALGPKGMBTilesLikePseudoDataset
 
     CPLString           m_osWHERE;
 
-#ifdef HAVE_SQLITE_VFS
     sqlite3_vfs*        m_pMyVFS;
-#endif
     sqlite3            *m_hTempDB;
     CPLString           m_osTempDBFilename;
     time_t              m_nLastSpaceCheckTimestamp;
@@ -98,15 +104,31 @@ class GDALGPKGMBTilesLikePseudoDataset
 
     GDALGPKGMBTilesLikePseudoDataset* m_poParentDS;
 
+  private:
         bool                    m_bInWriteTile;
         CPLErr                  WriteTileInternal(); /* should only be called by WriteTile() */
+        GIntBig                 GetTileId(int nRow, int nCol);
+        bool                    DeleteTile(int nRow, int nCol);
+        bool                    DeleteFromGriddedTileAncillary(GIntBig nTileId);
+        void                    GetTileOffsetAndScale(
+                                    GIntBig nTileId,
+                                    double& dfTileOffset, double& dfTileScale);
+        void                    FillBuffer(GByte* pabyData, size_t nPixels);
+        void                    FillEmptyTile(GByte* pabyData);
+        void                    FillEmptyTileSingleBand(GByte* pabyData);
 
   public:
                                 GDALGPKGMBTilesLikePseudoDataset();
         virtual                ~GDALGPKGMBTilesLikePseudoDataset();
 
+        void                    SetDataType(GDALDataType eDT);
+        void                    SetGlobalOffsetScale(double dfOffset,
+                                                     double dfScale);
+
         CPLErr                  ReadTile(const CPLString& osMemFileName,
                                          GByte* pabyTileData,
+                                         double dfTileOffset,
+                                         double dfTileScale,
                                          bool* pbIsLossyFormat = NULL);
         GByte*                  ReadTile(int nRow, int nCol);
         GByte*                  ReadTile(int nRow, int nCol, GByte* pabyData,
@@ -135,29 +157,35 @@ class GDALGPKGMBTilesLikePseudoDataset
 
 class GDALGPKGMBTilesLikeRasterBand: public GDALPamRasterBand
 {
-    GDALGPKGMBTilesLikePseudoDataset* m_poTPD;
+    protected:
+        GDALGPKGMBTilesLikePseudoDataset* m_poTPD;
+        int                               m_nDTSize;
+        bool                              m_bHasNoData;
+        double                            m_dfNoDataValue;
 
     public:
                                 GDALGPKGMBTilesLikeRasterBand(GDALGPKGMBTilesLikePseudoDataset* poTPD,
                                                               int nTileWidth, int nTileHeight);
 
         virtual CPLErr          IReadBlock(int nBlockXOff, int nBlockYOff,
-                                           void* pData);
+                                           void* pData) override;
         virtual CPLErr          IWriteBlock(int nBlockXOff, int nBlockYOff,
-                                           void* pData);
-        virtual CPLErr          FlushCache();
+                                           void* pData) override;
+        virtual CPLErr          FlushCache() override;
 
-        virtual GDALColorTable* GetColorTable();
-        virtual CPLErr          SetColorTable(GDALColorTable* poCT);
+        virtual GDALColorTable* GetColorTable() override;
+        virtual CPLErr          SetColorTable(GDALColorTable* poCT) override;
 
-        virtual GDALColorInterp GetColorInterpretation();
-        virtual CPLErr          SetColorInterpretation( GDALColorInterp );
+        virtual GDALColorInterp GetColorInterpretation() override;
+        virtual CPLErr          SetColorInterpretation( GDALColorInterp ) override;
+
+        virtual double          GetNoDataValue( int* pbSuccess = NULL ) override;
+        void                    SetNoDataValueInternal( double dfNoDataValue );
 
     protected:
         friend class GDALGPKGMBTilesLikePseudoDataset;
 
         GDALRasterBlock*        AccessibleTryGetLockedBlockRef(int nBlockXOff, int nBlockYOff) { return TryGetLockedBlockRef(nBlockXOff, nBlockYOff); }
-
 };
 
 #endif // GPKGMBTILESCOMMON_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h b/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
index 034b9ba..a5b35d7 100644
--- a/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
+++ b/ogr/ogrsf_frmts/gpkg/ogr_geopackage.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_geopackage.h 35695 2016-10-11 17:39:33Z rouault $
+ * $Id: ogr_geopackage.h 37872 2017-03-31 18:59:47Z rouault $
  *
  * Project:  GeoPackage Translator
  * Purpose:  Definition of classes for OGR GeoPackage driver.
@@ -32,14 +32,32 @@
 
 #include "ogrsf_frmts.h"
 #include "ogr_sqlite.h"
-#include "ogrgeopackageutility.h"
 #include "gpkgmbtilescommon.h"
+#include "ogrsqliteutility.h"
 
 #include <vector>
 
 #define UNKNOWN_SRID   -2
 #define DEFAULT_SRID    0
 
+#define ENABLE_GPKG_OGR_CONTENTS
+
+typedef enum
+{
+    GPKG_ATTRIBUTES,
+    OGR_ASPATIAL,
+    NOT_REGISTERED,
+} GPKGASpatialVariant;
+
+// Requirement 2
+static const GUInt32 GP10_APPLICATION_ID = 0x47503130U;
+static const GUInt32 GP11_APPLICATION_ID = 0x47503131U;
+static const GUInt32 GPKG_APPLICATION_ID = 0x47504B47U;
+static const GUInt32 GPKG_1_2_VERSION = 0x000027D8U; // 10200
+
+static const size_t knApplicationIdPos = 68;
+static const size_t knUserVersionPos = 60;
+
 /************************************************************************/
 /*                          GDALGeoPackageDataset                       */
 /************************************************************************/
@@ -51,10 +69,17 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
     friend class GDALGeoPackageRasterBand;
     friend class OGRGeoPackageTableLayer;
 
+    GUInt32             m_nApplicationId;
+    GUInt32             m_nUserVersion;
     OGRGeoPackageTableLayer** m_papoLayers;
     int                 m_nLayers;
     bool                m_bUtf8;
     void                CheckUnknownExtensions(bool bCheckRasterTable = false);
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    bool                m_bHasGPKGOGRContents;
+#endif
+    bool                m_bHasGPKGGeometryColumns;
+    bool                m_bHasDefinition12_063;
 
     CPLString           m_osIdentifier;
     bool                m_bIdentifierAsCO;
@@ -77,9 +102,11 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
 
     bool                m_bInFlushCache;
 
+    bool                m_bTableCreated;
+
     CPLString           m_osTilingScheme;
 
-        void            ComputeTileAndPixelShifts();
+        bool            ComputeTileAndPixelShifts();
         bool            InitRaster ( GDALGeoPackageDataset* poParentDS,
                                      const char* pszTableName,
                                      double dfMinX,
@@ -122,6 +149,7 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
                             const char* pszContentsMinY,
                             const char* pszContentsMaxX,
                             const char* pszContentsMaxY,
+                            bool bIsTiles,
                             char** papszOptions );
         CPLErr   FinalizeRasterRegistration();
 
@@ -138,31 +166,36 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
 
         int                     FindLayerIndex(const char* pszLayerName);
 
+        bool                    CreateTileGriddedTable(char** papszOptions);
+
+        void                    CreateOGREmptyTableIfNeeded();
+        void                    RemoveOGREmptyTable();
+
     public:
                             GDALGeoPackageDataset();
                             virtual ~GDALGeoPackageDataset();
 
-        virtual char **     GetMetadata( const char *pszDomain = NULL );
+        virtual char **     GetMetadata( const char *pszDomain = NULL ) override;
         virtual const char *GetMetadataItem( const char * pszName,
-                                             const char * pszDomain = "" );
-        virtual char **     GetMetadataDomainList();
+                                             const char * pszDomain = "" ) override;
+        virtual char **     GetMetadataDomainList() override;
         virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
         virtual CPLErr      SetMetadataItem( const char * pszName,
                                              const char * pszValue,
-                                             const char * pszDomain = "" );
+                                             const char * pszDomain = "" ) override;
 
-        virtual const char* GetProjectionRef();
-        virtual CPLErr      SetProjection( const char* pszProjection );
+        virtual const char* GetProjectionRef() override;
+        virtual CPLErr      SetProjection( const char* pszProjection ) override;
 
-        virtual CPLErr      GetGeoTransform( double* padfGeoTransform );
-        virtual CPLErr      SetGeoTransform( double* padfGeoTransform );
+        virtual CPLErr      GetGeoTransform( double* padfGeoTransform ) override;
+        virtual CPLErr      SetGeoTransform( double* padfGeoTransform ) override;
 
-        virtual void        FlushCache();
+        virtual void        FlushCache() override;
         virtual CPLErr      IBuildOverviews( const char *, int, int *,
-                                             int, int *, GDALProgressFunc, void * );
+                                             int, int *, GDALProgressFunc, void * ) override;
 
-        virtual int         GetLayerCount() { return m_nLayers; }
+        virtual int         GetLayerCount() override { return m_nLayers; }
         int                 Open( GDALOpenInfo* poOpenInfo );
         int                 Create( const char * pszFilename,
                                     int nXSize,
@@ -170,26 +203,28 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
                                     int nBands,
                                     GDALDataType eDT,
                                     char **papszOptions );
-        OGRLayer*           GetLayer( int iLayer );
-        OGRErr              DeleteLayer( int iLayer );
+        OGRLayer*           GetLayer( int iLayer ) override;
+        OGRErr              DeleteLayer( int iLayer ) override;
         OGRLayer*           ICreateLayer( const char * pszLayerName,
                                          OGRSpatialReference * poSpatialRef,
                                          OGRwkbGeometryType eGType,
-                                         char **papszOptions );
-        int                 TestCapability( const char * );
+                                         char **papszOptions ) override;
+        int                 TestCapability( const char * ) override;
 
-        virtual std::pair<OGRLayer*, IOGRSQLiteGetSpatialWhere*> GetLayerWithGetSpatialWhereByName( const char* pszName );
+        virtual std::pair<OGRLayer*, IOGRSQLiteGetSpatialWhere*> GetLayerWithGetSpatialWhereByName( const char* pszName ) override;
 
         virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                         OGRGeometry *poSpatialFilter,
-                                        const char *pszDialect );
-        virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                        const char *pszDialect ) override;
+        virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
-        virtual OGRErr      CommitTransaction();
-        virtual OGRErr      RollbackTransaction();
+        virtual OGRErr      CommitTransaction() override;
+        virtual OGRErr      RollbackTransaction() override;
 
-        int                 GetSrsId( const OGRSpatialReference * poSRS );
-        const char*         GetSrsName( const OGRSpatialReference * poSRS );
+        bool                IsInTransaction() const;
+
+        int                 GetSrsId( const OGRSpatialReference& oSRS );
+        const char*         GetSrsName( const OGRSpatialReference& oSRS );
         OGRSpatialReference* GetSpatialRef( int iSrsId );
         bool                GetUTF8() { return m_bUtf8; }
         OGRErr              CreateExtensionsTableIfNecessary();
@@ -201,6 +236,8 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
         const char*         GetGeometryTypeString(OGRwkbGeometryType eType);
 
         void                ResetReadingAllLayers();
+        OGRErr              UpdateGpkgContentsLastChange(
+                                                const char* pszTableName);
 
         static GDALDataset* CreateCopy( const char *pszFilename,
                                                    GDALDataset *poSrcDS,
@@ -212,21 +249,21 @@ class GDALGeoPackageDataset CPL_FINAL : public OGRSQLiteBaseDataSource, public G
     protected:
         // Coming from GDALGPKGMBTilesLikePseudoDataset
 
-        virtual CPLErr                  IFlushCacheWithErrCode();
-        virtual int                     IGetRasterCount() { return nBands; }
-        virtual GDALRasterBand*         IGetRasterBand(int nBand) { return GetRasterBand(nBand); }
-        virtual sqlite3                *IGetDB() { return GetDB(); }
-        virtual bool                    IGetUpdate() { return bUpdate != FALSE; }
-        virtual bool                    ICanIWriteBlock();
-        virtual OGRErr                  IStartTransaction() { return SoftStartTransaction(); }
-        virtual OGRErr                  ICommitTransaction() { return SoftCommitTransaction(); }
-        virtual const char             *IGetFilename() { return m_pszFilename; }
-        virtual int                     GetRowFromIntoTopConvention(int nRow) { return nRow; }
+        virtual CPLErr                  IFlushCacheWithErrCode() override;
+        virtual int                     IGetRasterCount() override { return nBands; }
+        virtual GDALRasterBand*         IGetRasterBand(int nBand) override { return GetRasterBand(nBand); }
+        virtual sqlite3                *IGetDB() override { return GetDB(); }
+        virtual bool                    IGetUpdate() override { return bUpdate != FALSE; }
+        virtual bool                    ICanIWriteBlock() override;
+        virtual OGRErr                  IStartTransaction() override { return SoftStartTransaction(); }
+        virtual OGRErr                  ICommitTransaction() override { return SoftCommitTransaction(); }
+        virtual const char             *IGetFilename() override { return m_pszFilename; }
+        virtual int                     GetRowFromIntoTopConvention(int nRow) override { return nRow; }
 
     private:
 
         OGRErr              PragmaCheck(const char * pszPragma, const char * pszExpected, int nRowsExpected);
-        OGRErr              SetApplicationId();
+        OGRErr              SetApplicationAndUserVersionId();
         bool                ReOpenDB();
         bool                OpenOrCreateDB( int flags );
         bool                HasGDALAspatialExtension();
@@ -242,8 +279,14 @@ class GDALGeoPackageRasterBand CPL_FINAL: public GDALGPKGMBTilesLikeRasterBand
                                 GDALGeoPackageRasterBand(GDALGeoPackageDataset* poDS,
                                                          int nTileWidth, int nTileHeight);
 
-        virtual int             GetOverviewCount();
-        virtual GDALRasterBand* GetOverview(int nIdx);
+        virtual int             GetOverviewCount() override;
+        virtual GDALRasterBand* GetOverview(int nIdx) override;
+
+        virtual CPLErr          SetNoDataValue( double dfNoDataValue ) override;
+
+        virtual char**          GetMetadata(const char* pszDomain = "") override;
+        virtual const char*     GetMetadataItem(const char* pszName,
+                                                const char* pszDomain = "") override;
 };
 
 /************************************************************************/
@@ -277,21 +320,20 @@ class OGRGeoPackageLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
 
   public:
 
-                        OGRGeoPackageLayer(GDALGeoPackageDataset* poDS);
+    explicit            OGRGeoPackageLayer(GDALGeoPackageDataset* poDS);
                         virtual ~OGRGeoPackageLayer();
     /************************************************************************/
     /* OGR API methods */
 
-    OGRFeature*         GetNextFeature();
-    const char*         GetFIDColumn();
-    void                ResetReading();
-    int                 TestCapability( const char * );
-    OGRFeatureDefn*     GetLayerDefn() { return m_poFeatureDefn; }
+    OGRFeature*         GetNextFeature() override;
+    const char*         GetFIDColumn() override;
+    void                ResetReading() override;
+    int                 TestCapability( const char * ) override;
+    OGRFeatureDefn*     GetLayerDefn() override { return m_poFeatureDefn; }
 
-    virtual int          HasFastSpatialFilter(int /*iGeomCol*/) { return FALSE; }
+    virtual int          HasFastSpatialFilter(int /*iGeomCol*/) override { return FALSE; }
     virtual CPLString    GetSpatialWhere(int /*iGeomCol*/,
-                                         OGRGeometry* /*poFilterGeom*/) { return ""; }
-
+                                         OGRGeometry* /*poFilterGeom*/) override { return ""; }
 };
 
 /************************************************************************/
@@ -301,11 +343,20 @@ class OGRGeoPackageLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
 class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
 {
     char*                       m_pszTableName;
+    bool                        m_bIsTable;
     int                         m_iSrs;
     OGREnvelope*                m_poExtent;
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    GIntBig                     m_nTotalFeatureCount;
+    bool                        m_bOGRFeatureCountTriggersEnabled;
+    bool                        m_bAddOGRFeatureCountTriggers;
+    bool                        m_bFeatureCountTriggersDeletedInTransaction;
+#endif
     CPLString                   m_soColumns;
     CPLString                   m_soFilter;
     CPLString                   osQuery;
+    CPLString                   m_osRTreeName;
+    CPLString                   m_osFIDForRTree;
     bool                        m_bExtentChanged;
     bool                        m_bContentChanged;
     sqlite3_stmt*               m_poUpdateStatement;
@@ -315,7 +366,7 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
     // m_bHasSpatialIndex cannot be bool.  -1 is unset.
     int                         m_bHasSpatialIndex;
     bool                        m_bDropRTreeTable;
-    bool                        m_abHasGeometryExtension[wkbTIN+1];
+    bool                        m_abHasGeometryExtension[wkbTriangle+1];
     bool                        m_bPreservePrecision;
     bool                        m_bTruncateFields;
     bool                        m_bDeferredCreation;
@@ -324,18 +375,22 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
     CPLString                   m_osIdentifierLCO;
     CPLString                   m_osDescriptionLCO;
     bool                        m_bHasReadMetadataFromStorage;
-    bool                        m_bRegisterAsAspatial;
+    bool                        m_bHasTriedDetectingFID64;
+    GPKGASpatialVariant         m_eASPatialVariant;
 
-    virtual OGRErr      ResetStatement();
+    virtual OGRErr      ResetStatement() override;
 
-    void                BuildWhere(void);
+    void                BuildWhere();
     OGRErr              RegisterGeometryColumn();
 
-    CPLString           GetColumnsOfCreateTable(const std::vector<OGRFieldDefn*> apoFields);
-    CPLString           BuildSelectFieldList(const std::vector<OGRFieldDefn*> apoFields);
+    CPLString           GetColumnsOfCreateTable(const std::vector<OGRFieldDefn*>& apoFields);
+    CPLString           BuildSelectFieldList(const std::vector<OGRFieldDefn*>& apoFields);
     OGRErr              RecreateTable(const CPLString& osColumnsForCreate,
                                       const CPLString& osFieldListForSelect);
-    bool                IsTable();
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    void                CreateTriggers(const char* pszTableName = NULL);
+    void                DisableTriggers(bool bNullifyFeatureCount = true);
+#endif
 
     public:
                         OGRGeoPackageTableLayer( GDALGeoPackageDataset *poDS,
@@ -345,32 +400,34 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
     /************************************************************************/
     /* OGR API methods */
 
-    int                 TestCapability( const char * );
-    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
+    int                 TestCapability( const char * ) override;
+    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE ) override;
     OGRErr              CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
-                                         int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField(  int iFieldToDelete );
-    virtual OGRErr      AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlagsIn );
-    virtual OGRErr      ReorderFields( int* panMap );
-    void                ResetReading();
-    OGRErr              ICreateFeature( OGRFeature *poFeater );
-    OGRErr              ISetFeature( OGRFeature *poFeature );
-    OGRErr              DeleteFeature(GIntBig nFID);
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                                         int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField(  int iFieldToDelete ) override;
+    virtual OGRErr      AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poNewFieldDefn, int nFlagsIn ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    void                ResetReading() override;
+    OGRErr              ICreateFeature( OGRFeature *poFeater ) override;
+    OGRErr              ISetFeature( OGRFeature *poFeature ) override;
+    OGRErr              DeleteFeature(GIntBig nFID) override;
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRGeoPackageLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    OGRErr              SetAttributeFilter( const char *pszQuery );
-    OGRErr              SyncToDisk();
-    OGRFeature*         GetNextFeature();
-    OGRFeature*         GetFeature(GIntBig nFID);
-    OGRErr              StartTransaction();
-    OGRErr              CommitTransaction();
-    OGRErr              RollbackTransaction();
-    GIntBig             GetFeatureCount( int );
-    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    OGRErr              SetAttributeFilter( const char *pszQuery ) override;
+    OGRErr              SyncToDisk() override;
+    OGRFeature*         GetNextFeature() override;
+    OGRFeature*         GetFeature(GIntBig nFID) override;
+    OGRErr              StartTransaction() override;
+    OGRErr              CommitTransaction() override;
+    OGRErr              RollbackTransaction() override;
+    GIntBig             GetFeatureCount( int ) override;
+    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRGeoPackageLayer::GetExtent(iGeomField, psExtent, bForce); }
+
+    void                PostInit();
     void                RecomputeExtent();
 
     OGRErr              ReadTableDefinition(bool bIsSpatial, bool bIsGpkgTable);
@@ -383,29 +440,29 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
                                                const char* pszDescription );
     void                SetDeferredSpatialIndexCreation( bool bFlag )
                                 { m_bDeferredSpatialIndexCreation = bFlag; }
-    void                SetRegisterAsAspatial( bool bFlag )
-                                { m_bRegisterAsAspatial = bFlag; }
+    void                SetASpatialVariant( GPKGASpatialVariant eASPatialVariant )
+                                { m_eASPatialVariant = eASPatialVariant; }
 
     void                CreateSpatialIndexIfNecessary();
     bool                CreateSpatialIndex(const char* pszTableName = NULL);
     bool                DropSpatialIndex(bool bCalledFromSQLFunction = false);
 
-    virtual char **     GetMetadata( const char *pszDomain = NULL );
+    virtual char **     GetMetadata( const char *pszDomain = NULL ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                             const char * pszDomain = "" );
-    virtual char **     GetMetadataDomainList();
+                                             const char * pszDomain = "" ) override;
+    virtual char **     GetMetadataDomainList() override;
 
     virtual CPLErr      SetMetadata( char ** papszMetadata,
-                                        const char * pszDomain = "" );
+                                        const char * pszDomain = "" ) override;
     virtual CPLErr      SetMetadataItem( const char * pszName,
                                             const char * pszValue,
-                                            const char * pszDomain = "" );
+                                            const char * pszDomain = "" ) override;
 
     void                RenameTo(const char* pszDstTableName);
 
-    virtual int          HasFastSpatialFilter(int iGeomCol);
+    virtual int          HasFastSpatialFilter(int iGeomCol) override;
     virtual CPLString    GetSpatialWhere(int iGeomCol,
-                                         OGRGeometry* poFilterGeom);
+                                         OGRGeometry* poFilterGeom) override;
 
     bool                HasSpatialIndex();
     void                SetPrecisionFlag( int bFlag )
@@ -414,22 +471,37 @@ class OGRGeoPackageTableLayer CPL_FINAL : public OGRGeoPackageLayer
                                 { m_bTruncateFields = CPL_TO_BOOL( bFlag ); }
     OGRErr              RunDeferredCreationIfNecessary();
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    bool                GetAddOGRFeatureCountTriggers() const
+                                    { return m_bAddOGRFeatureCountTriggers; }
+    void                SetAddOGRFeatureCountTriggers(bool b)
+                                    { m_bAddOGRFeatureCountTriggers = b; }
+    bool                GetOGRFeatureCountTriggersDeletedInTransaction() const
+                        { return m_bFeatureCountTriggersDeletedInTransaction; }
+    void                SetOGRFeatureCountTriggersEnabled(bool b)
+                                    { m_bOGRFeatureCountTriggersEnabled = b; }
+
+    void                DisableFeatureCount( bool bInMemoryOnly = false );
+#endif
+
     /************************************************************************/
     /* GPKG methods */
 
   private:
+    bool                CheckUpdatableTable(const char* pszOperation);
     OGRErr              UpdateExtent( const OGREnvelope *poExtent );
     OGRErr              SaveExtent();
     OGRErr              SaveTimestamp();
     OGRErr              BuildColumns();
     bool                IsGeomFieldSet( OGRFeature *poFeature );
     CPLString           FeatureGenerateUpdateSQL( OGRFeature *poFeature );
-    CPLString           FeatureGenerateInsertSQL( OGRFeature *poFeature, bool bAddFID, bool bBindNullFields );
+    CPLString           FeatureGenerateInsertSQL( OGRFeature *poFeature, bool bAddFID, bool bBindUnsetFields );
     OGRErr              FeatureBindUpdateParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt );
-    OGRErr              FeatureBindInsertParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, bool bAddFID, bool bBindNullFields );
-    OGRErr              FeatureBindParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, int *pnColCount, bool bAddFID, bool bBindNullFields );
+    OGRErr              FeatureBindInsertParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, bool bAddFID, bool bBindUnsetFields );
+    OGRErr              FeatureBindParameters( OGRFeature *poFeature, sqlite3_stmt *poStmt, int *pnColCount, bool bAddFID, bool bBindUnsetFields );
 
     void                CheckUnknownExtensions();
+    bool                CreateGeometryExtensionIfNecessary(const OGRGeometry* poGeom);
     bool                CreateGeometryExtensionIfNecessary(OGRwkbGeometryType eGType);
 };
 
@@ -441,7 +513,7 @@ class OGRGeoPackageSelectLayer CPL_FINAL : public OGRGeoPackageLayer, public IOG
 {
     OGRSQLiteSelectLayerCommonBehaviour* poBehaviour;
 
-    virtual OGRErr      ResetStatement();
+    virtual OGRErr      ResetStatement() override;
 
   public:
                         OGRGeoPackageSelectLayer( GDALGeoPackageDataset *,
@@ -451,36 +523,35 @@ class OGRGeoPackageSelectLayer CPL_FINAL : public OGRGeoPackageLayer, public IOG
                                               int bEmptyLayer );
                        virtual ~OGRGeoPackageSelectLayer();
 
-    virtual void        ResetReading();
-
-    virtual OGRFeature *GetNextFeature();
-    virtual GIntBig     GetFeatureCount( int );
-
-    virtual void        SetSpatialFilter( OGRGeometry * poGeom ) { SetSpatialFilter(0, poGeom); }
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
-    virtual OGRErr      SetAttributeFilter( const char * );
-
-    virtual int         TestCapability( const char * );
-
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) { return GetExtent(0, psExtent, bForce); }
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
-
-    virtual OGRFeatureDefn *     GetLayerDefn() { return OGRGeoPackageLayer::GetLayerDefn(); }
-    virtual char*&               GetAttrQueryString() { return m_pszAttrQueryString; }
-    virtual OGRFeatureQuery*&    GetFeatureQuery() { return m_poAttrQuery; }
-    virtual OGRGeometry*&        GetFilterGeom() { return m_poFilterGeom; }
-    virtual int&                 GetIGeomFieldFilter() { return m_iGeomFieldFilter; }
-    virtual OGRSpatialReference* GetSpatialRef() { return OGRGeoPackageLayer::GetSpatialRef(); }
-    virtual int                  InstallFilter( OGRGeometry * poGeomIn ) { return OGRGeoPackageLayer::InstallFilter(poGeomIn); }
-    virtual int                  HasReadFeature() { return iNextShapeId > 0; }
-    virtual void                 BaseResetReading() { OGRGeoPackageLayer::ResetReading(); }
-    virtual OGRFeature          *BaseGetNextFeature() { return OGRGeoPackageLayer::GetNextFeature(); }
-    virtual OGRErr               BaseSetAttributeFilter(const char* pszQuery) { return OGRGeoPackageLayer::SetAttributeFilter(pszQuery); }
-    virtual GIntBig              BaseGetFeatureCount(int bForce) { return OGRGeoPackageLayer::GetFeatureCount(bForce); }
-    virtual int                  BaseTestCapability( const char *pszCap ) { return OGRGeoPackageLayer::TestCapability(pszCap); }
-    virtual OGRErr               BaseGetExtent(OGREnvelope *psExtent, int bForce) { return OGRGeoPackageLayer::GetExtent(psExtent, bForce); }
-    virtual OGRErr               BaseGetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) { return OGRGeoPackageLayer::GetExtent(iGeomField, psExtent, bForce); }
+    virtual void        ResetReading() override;
+
+    virtual OGRFeature *GetNextFeature() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
+
+    virtual void        SetSpatialFilter( OGRGeometry * poGeom ) override { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
+
+    virtual int         TestCapability( const char * ) override;
+
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
+
+    virtual OGRFeatureDefn *     GetLayerDefn() override { return OGRGeoPackageLayer::GetLayerDefn(); }
+    virtual char*&               GetAttrQueryString() override { return m_pszAttrQueryString; }
+    virtual OGRFeatureQuery*&    GetFeatureQuery() override { return m_poAttrQuery; }
+    virtual OGRGeometry*&        GetFilterGeom() override { return m_poFilterGeom; }
+    virtual int&                 GetIGeomFieldFilter() override { return m_iGeomFieldFilter; }
+    virtual OGRSpatialReference* GetSpatialRef() override { return OGRGeoPackageLayer::GetSpatialRef(); }
+    virtual int                  InstallFilter( OGRGeometry * poGeomIn ) override { return OGRGeoPackageLayer::InstallFilter(poGeomIn); }
+    virtual int                  HasReadFeature() override { return iNextShapeId > 0; }
+    virtual void                 BaseResetReading() override { OGRGeoPackageLayer::ResetReading(); }
+    virtual OGRFeature          *BaseGetNextFeature() override { return OGRGeoPackageLayer::GetNextFeature(); }
+    virtual OGRErr               BaseSetAttributeFilter(const char* pszQuery) override { return OGRGeoPackageLayer::SetAttributeFilter(pszQuery); }
+    virtual GIntBig              BaseGetFeatureCount(int bForce) override { return OGRGeoPackageLayer::GetFeatureCount(bForce); }
+    virtual int                  BaseTestCapability( const char *pszCap ) override { return OGRGeoPackageLayer::TestCapability(pszCap); }
+    virtual OGRErr               BaseGetExtent(OGREnvelope *psExtent, int bForce) override { return OGRGeoPackageLayer::GetExtent(psExtent, bForce); }
+    virtual OGRErr               BaseGetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override { return OGRGeoPackageLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
-
 #endif /* OGR_GEOPACKAGE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
index 00dcf25..ea2f7ca 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedatasource.cpp
@@ -31,18 +31,14 @@
 #include "ogr_p.h"
 #include "swq.h"
 #include "gdalwarper.h"
+#include "ogrgeopackageutility.h"
+#include "ogrsqliteutility.h"
 
-CPL_CVSID("$Id: ogrgeopackagedatasource.cpp 35695 2016-10-11 17:39:33Z rouault $");
+#include <cstdlib>
 
-// 1.1.1: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) in the
-// application id.
-// http://opengis.github.io/geopackage/#_file_format
-// 0x47503130 = 1196437808
-static const int GPKG_APPLICATION_ID = 1196437808;
+#include <algorithm>
 
-/* "GP10" in ASCII bytes */
-static const char aGpkgId[4] = {0x47, 0x50, 0x31, 0x30};
-static const size_t szGpkgIdPos = 68;
+CPL_CVSID("$Id: ogrgeopackagedatasource.cpp 37945 2017-04-10 14:25:25Z rouault $");
 
 /************************************************************************/
 /*                             Tiling schemes                           */
@@ -106,15 +102,39 @@ static const TilingSchemeDefinition asTilingShemes[] =
       78271.516, 78271.516 },
 };
 
+static const char* pszCREATE_GPKG_GEOMETRY_COLUMNS =
+    "CREATE TABLE gpkg_geometry_columns ("
+    "table_name TEXT NOT NULL,"
+    "column_name TEXT NOT NULL,"
+    "geometry_type_name TEXT NOT NULL,"
+    "srs_id INTEGER NOT NULL,"
+    "z TINYINT NOT NULL,"
+    "m TINYINT NOT NULL,"
+    "CONSTRAINT pk_geom_cols PRIMARY KEY (table_name, column_name),"
+    "CONSTRAINT uk_gc_table_name UNIQUE (table_name),"
+    "CONSTRAINT fk_gc_tn FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name),"
+    "CONSTRAINT fk_gc_srs FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys (srs_id)"
+    ")";
+
 /* Only recent versions of SQLite will let us muck with application_id */
 /* via a PRAGMA statement, so we have to write directly into the */
 /* file header here. */
 /* We do this at the *end* of initialization so that there is */
 /* data to write down to a file, and we will have a writable file */
 /* once we close the SQLite connection */
-OGRErr GDALGeoPackageDataset::SetApplicationId()
+OGRErr GDALGeoPackageDataset::SetApplicationAndUserVersionId()
 {
     CPLAssert( hDB != NULL );
+
+    // PRAGMA application_id available since SQLite 3.7.17
+#if SQLITE_VERSION_NUMBER >= 3007017
+    const char *pszPragma = CPLSPrintf(
+        "PRAGMA application_id = %u;"
+        "PRAGMA user_version = %u",
+        m_nApplicationId,
+        m_nUserVersion);
+    return SQLCommand(hDB, pszPragma);
+#else
     CPLAssert( m_pszFilename != NULL );
 
 #ifdef SPATIALITE_412_OR_LATER
@@ -129,8 +149,16 @@ OGRErr GDALGeoPackageDataset::SetApplicationId()
     VSILFILE *pfFile = VSIFOpenL( m_pszFilename, "rb+" );
     if( pfFile == NULL )
         return OGRERR_FAILURE;
-    VSIFSeekL(pfFile, szGpkgIdPos, SEEK_SET);
-    szWritten = VSIFWriteL(aGpkgId, 1, 4, pfFile);
+    VSIFSeekL(pfFile, knApplicationIdPos, SEEK_SET);
+    const GUInt32 nApplicationIdMSB = CPL_MSBWORD32(m_nApplicationId);
+    szWritten = VSIFWriteL(&nApplicationIdMSB, 1, 4, pfFile);
+    if (szWritten == 4 )
+    {
+        VSIFSeekL(pfFile, knUserVersionPos, SEEK_SET);
+        const GUInt32 nVersionMSB = CPL_MSBWORD32(m_nUserVersion);
+        szWritten = VSIFWriteL(&nVersionMSB, 1, 4, pfFile);
+    }
+
     VSIFCloseL(pfFile);
 
     /* If we didn't write out exactly four bytes, something */
@@ -145,9 +173,9 @@ OGRErr GDALGeoPackageDataset::SetApplicationId()
         return OGRERR_FAILURE;
 
     return OGRERR_NONE;
+#endif
 }
 
-
 bool GDALGeoPackageDataset::ReOpenDB()
 {
     CPLAssert( hDB != NULL );
@@ -162,7 +190,6 @@ bool GDALGeoPackageDataset::ReOpenDB()
     return OpenOrCreateDB(SQLITE_OPEN_READWRITE);
 }
 
-
 /* Returns the first row of first column of SQL as integer */
 OGRErr GDALGeoPackageDataset::PragmaCheck(
     const char * pszPragma, const char * pszExpected, int nRowsExpected )
@@ -219,7 +246,6 @@ static OGRErr GDALGPKGImportFromEPSG(OGRSpatialReference *poSpatialRef,
     return eErr;
 }
 
-
 OGRSpatialReference* GDALGeoPackageDataset::GetSpatialRef(int iSrsId)
 {
     /* Should we do something special with undefined SRS ? */
@@ -228,9 +254,16 @@ OGRSpatialReference* GDALGeoPackageDataset::GetSpatialRef(int iSrsId)
         return NULL;
     }
 
+    // HACK. We don't handle 3D GEOGCS right now, so hardcode 3D WGS 84 to
+    // return 2D WGS 84.
+    if( iSrsId == 4979 )
+        iSrsId = 4326;
+
     CPLString oSQL;
     oSQL.Printf( "SELECT definition, organization, organization_coordsys_id "
-                 "FROM gpkg_spatial_ref_sys WHERE srs_id = %d", iSrsId );
+                 "FROM gpkg_spatial_ref_sys WHERE definition IS NOT NULL AND "
+                 "srs_id = %d LIMIT 2",
+                 iSrsId );
 
     SQLResult oResult;
     OGRErr err = SQLQuery(hDB, oSQL.c_str(), &oResult);
@@ -245,15 +278,6 @@ OGRSpatialReference* GDALGeoPackageDataset::GetSpatialRef(int iSrsId)
     }
 
     const char *pszWkt = SQLResultGetValue(&oResult, 0, 0);
-    if ( ! pszWkt )
-    {
-        SQLResultFree(&oResult);
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "null definition for srs_id '%d' in gpkg_spatial_ref_sys",
-                  iSrsId);
-        return NULL;
-    }
-
     const char* pszOrganization = SQLResultGetValue(&oResult, 1, 0);
     const char* pszOrganizationCoordsysID = SQLResultGetValue(&oResult, 2, 0);
 
@@ -278,9 +302,9 @@ OGRSpatialReference* GDALGeoPackageDataset::GetSpatialRef(int iSrsId)
 }
 
 const char * GDALGeoPackageDataset::GetSrsName(
-    const OGRSpatialReference *poSRS )
+    const OGRSpatialReference& oSRS )
 {
-    const OGR_SRSNode *node = poSRS->GetAttrNode("PROJCS");
+    const OGR_SRSNode *node = oSRS.GetAttrNode("PROJCS");
 
     /* Projected coordinate system? */
     if ( node != NULL )
@@ -289,7 +313,7 @@ const char * GDALGeoPackageDataset::GetSrsName(
     }
 
     /* Geographic coordinate system? */
-    if ( (node = poSRS->GetAttrNode("GEOGCS")) != NULL )
+    if ( (node = oSRS.GetAttrNode("GEOGCS")) != NULL )
     {
         return node->GetChild(0)->GetValue();
     }
@@ -298,12 +322,9 @@ const char * GDALGeoPackageDataset::GetSrsName(
     return "Unnamed SRS";
 }
 
-int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference * cpoSRS)
+int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference& oSRS)
 {
-    if( cpoSRS == NULL )
-        return DEFAULT_SRID;
-
-    OGRSpatialReference *poSRS = cpoSRS->Clone();
+    OGRSpatialReference *poSRS = oSRS.Clone();
 
     const char* pszAuthorityName = poSRS->GetAuthorityName( NULL );
 
@@ -361,7 +382,7 @@ int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference * cpoSRS)
                          "srs_id = %d", nAuthorityCode );
 
         // Yep, we can!
-        if ( ! SQLGetInteger(hDB, pszSQL, &err) && err == OGRERR_NONE )
+        if ( SQLGetInteger(hDB, pszSQL, NULL) == 0 )
             bCanUseAuthorityCode = true;
         sqlite3_free(pszSQL);
     }
@@ -386,38 +407,56 @@ int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference * cpoSRS)
         // Get the current maximum srid in the srs table.
         const int nMaxSRSId
             = SQLGetInteger(
-                hDB, "SELECT MAX(srs_id) FROM gpkg_spatial_ref_sys", &err );
-        if ( OGRERR_NONE != err )
-        {
-            CPLFree(pszWKT);
-            delete poSRS;
-            return DEFAULT_SRID;
-        }
-
+                hDB, "SELECT MAX(srs_id) FROM gpkg_spatial_ref_sys", NULL );
         nSRSId = nMaxSRSId + 1;
     }
 
     // Add new SRS row to gpkg_spatial_ref_sys.
-    if( pszAuthorityName != NULL && nAuthorityCode > 0 )
+    if( m_bHasDefinition12_063 )
     {
-        pszSQL = sqlite3_mprintf(
-            "INSERT INTO gpkg_spatial_ref_sys "
-            "(srs_name,srs_id,organization,organization_coordsys_id,"
-            "definition) VALUES ('%q', %d, upper('%q'), %d, '%q')",
-            GetSrsName(poSRS), nSRSId, pszAuthorityName, nAuthorityCode,
-            pszWKT );
+        if( pszAuthorityName != NULL && nAuthorityCode > 0 )
+        {
+            pszSQL = sqlite3_mprintf(
+                "INSERT INTO gpkg_spatial_ref_sys "
+                "(srs_name,srs_id,organization,organization_coordsys_id,"
+                "definition, definition_12_063) VALUES "
+                "('%q', %d, upper('%q'), %d, '%q', 'undefined')",
+                GetSrsName(*poSRS), nSRSId, pszAuthorityName, nAuthorityCode,
+                pszWKT );
+        }
+        else
+        {
+            pszSQL = sqlite3_mprintf(
+                "INSERT INTO gpkg_spatial_ref_sys "
+                "(srs_name,srs_id,organization,organization_coordsys_id,"
+                "definition, definition_12_063) VALUES "
+                "('%q', %d, upper('%q'), %d, '%q', 'undefined')",
+                GetSrsName(*poSRS), nSRSId, "NONE", nSRSId, pszWKT );
+        }
     }
     else
     {
-        pszSQL = sqlite3_mprintf(
-            "INSERT INTO gpkg_spatial_ref_sys "
-            "(srs_name,srs_id,organization,organization_coordsys_id,"
-            "definition) VALUES ('%q', %d, upper('%q'), %d, '%q')",
-            GetSrsName(poSRS), nSRSId, "NONE", nSRSId, pszWKT );
+        if( pszAuthorityName != NULL && nAuthorityCode > 0 )
+        {
+            pszSQL = sqlite3_mprintf(
+                "INSERT INTO gpkg_spatial_ref_sys "
+                "(srs_name,srs_id,organization,organization_coordsys_id,"
+                "definition) VALUES ('%q', %d, upper('%q'), %d, '%q')",
+                GetSrsName(*poSRS), nSRSId, pszAuthorityName, nAuthorityCode,
+                pszWKT );
+        }
+        else
+        {
+            pszSQL = sqlite3_mprintf(
+                "INSERT INTO gpkg_spatial_ref_sys "
+                "(srs_name,srs_id,organization,organization_coordsys_id,"
+                "definition) VALUES ('%q', %d, upper('%q'), %d, '%q')",
+                GetSrsName(*poSRS), nSRSId, "NONE", nSRSId, pszWKT );
+        }
     }
 
     // Add new row to gpkg_spatial_ref_sys.
-    err = SQLCommand(hDB, pszSQL);
+    CPL_IGNORE_RET_VAL( SQLCommand(hDB, pszSQL) );
 
     // Free everything that was allocated.
     CPLFree(pszWKT);
@@ -427,15 +466,21 @@ int GDALGeoPackageDataset::GetSrsId(const OGRSpatialReference * cpoSRS)
     return nSRSId;
 }
 
-
 /************************************************************************/
 /*                        GDALGeoPackageDataset()                       */
 /************************************************************************/
 
 GDALGeoPackageDataset::GDALGeoPackageDataset() :
+    m_nApplicationId(GP10_APPLICATION_ID),
+    m_nUserVersion(0),
     m_papoLayers(NULL),
     m_nLayers(0),
     m_bUtf8(false),
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    m_bHasGPKGOGRContents(false),
+#endif
+    m_bHasGPKGGeometryColumns(false),
+    m_bHasDefinition12_063(false),
     m_bIdentifierAsCO(false),
     m_bDescriptionAsCO(false),
     m_bHasReadMetadataFromStorage(false),
@@ -451,6 +496,7 @@ GDALGeoPackageDataset::GDALGeoPackageDataset() :
     m_papoOverviewDS(NULL),
     m_bZoomOther(false),
     m_bInFlushCache(false),
+    m_bTableCreated(false),
     m_osTilingScheme("CUSTOM")
 {
     m_adfGeoTransform[0] = 0.0;
@@ -469,7 +515,8 @@ GDALGeoPackageDataset::~GDALGeoPackageDataset()
 {
     SetPamFlags(0);
 
-    if( m_poParentDS == NULL && m_osRasterTable.size() &&
+    if( eAccess == GA_Update &&
+        m_poParentDS == NULL && !m_osRasterTable.empty() &&
         !m_bGeoTransformValid )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -481,6 +528,20 @@ GDALGeoPackageDataset::~GDALGeoPackageDataset()
     FlushCache();
     FlushMetadata();
 
+    if( eAccess == GA_Update )
+    {
+        CreateOGREmptyTableIfNeeded();
+    }
+
+    // Destroy bands now since we don't want
+    // GDALGPKGMBTilesLikeRasterBand::FlushCache() to run after dataset
+    // destruction
+    for( int i = 0; i < nBands; i++ )
+        delete papoBands[i];
+    nBands = 0;
+    CPLFree(papoBands);
+    papoBands = NULL;
+
     // Destroy overviews before cleaning m_hTempDB as they could still
     // need it
     for( int i = 0; i < m_nOverviewCount; i++ )
@@ -534,6 +595,8 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
     SetDescription( poOpenInfo->pszFilename );
     CPLString osFilename( poOpenInfo->pszFilename );
     CPLString osSubdatasetTableName;
+    GByte abyHeaderLetMeHerePlease[100];
+    const GByte* pabyHeader = poOpenInfo->pabyHeader;
     if( STARTS_WITH_CI(poOpenInfo->pszFilename, "GPKG:") )
     {
         char** papszTokens = CSLTokenizeString2(poOpenInfo->pszFilename, ":", 0);
@@ -547,6 +610,13 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
         osSubdatasetTableName = papszTokens[2];
 
         CSLDestroy(papszTokens);
+        VSILFILE *fp = VSIFOpenL(osFilename, "rb");
+        if( fp != NULL )
+        {
+            VSIFReadL( abyHeaderLetMeHerePlease, 1, 100, fp );
+            VSIFCloseL(fp);
+        }
+        pabyHeader = abyHeaderLetMeHerePlease;
     }
 
     bUpdate = poOpenInfo->eAccess == GA_Update;
@@ -559,6 +629,28 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
                         : SQLITE_OPEN_READONLY) )
         return FALSE;
 
+
+    memcpy(&m_nApplicationId, pabyHeader + knApplicationIdPos, 4);
+    m_nApplicationId = CPL_MSBWORD32(m_nApplicationId);
+    memcpy(&m_nUserVersion, pabyHeader + knUserVersionPos, 4);
+    m_nUserVersion = CPL_MSBWORD32(m_nUserVersion);
+    if( m_nApplicationId == GP10_APPLICATION_ID )
+    {
+        CPLDebug("GPKG", "GeoPackage v1.0");
+    }
+    else if( m_nApplicationId == GP11_APPLICATION_ID )
+    {
+        CPLDebug("GPKG", "GeoPackage v1.1");
+    }
+    else if( m_nApplicationId == GPKG_APPLICATION_ID &&
+             m_nUserVersion >= GPKG_1_2_VERSION )
+    {
+        CPLDebug("GPKG", "GeoPackage v%d.%d.%d",
+                 m_nUserVersion / 10000,
+                 (m_nUserVersion % 10000) / 100,
+                 m_nUserVersion % 100);
+    }
+
     /* Requirement 6: The SQLite PRAGMA integrity_check SQL command SHALL return “ok” */
     /* http://opengis.github.io/geopackage/#_file_integrity */
     /* Disable integrity check by default, since it is expensive on big files */
@@ -585,84 +677,105 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
     }
 
     /* OGR UTF-8 capability, we'll advertise UTF-8 support if we have it */
-    if ( OGRERR_NONE == PragmaCheck("encoding", "UTF-8", 1) )
-    {
-        m_bUtf8 = true;
-    }
-    else
-    {
-        m_bUtf8 = false;
-    }
+    m_bUtf8 = ( OGRERR_NONE == PragmaCheck("encoding", "UTF-8", 1) );
 
     /* Check for requirement metadata tables */
     /* Requirement 10: gpkg_spatial_ref_sys must exist */
     /* Requirement 13: gpkg_contents must exist */
-    static std::string aosGpkgTables[] = {
-        "gpkg_spatial_ref_sys",
-        "gpkg_contents"
-    };
-
-    for ( int i = 0;
-          i < (int)(sizeof(aosGpkgTables) / sizeof(aosGpkgTables[0]));
-          i++ )
+    if( SQLGetInteger(hDB,
+        "SELECT COUNT(*) FROM sqlite_master WHERE "
+        "name IN ('gpkg_spatial_ref_sys', 'gpkg_contents') AND "
+        "type IN ('table', 'view')", NULL) != 2 )
     {
-        SQLResult oResult;
-        char *pszSQL = sqlite3_mprintf("pragma table_info('%q')", aosGpkgTables[i].c_str());
-        const OGRErr err = SQLQuery(hDB, pszSQL, &oResult);
-        sqlite3_free(pszSQL);
-
-        if  ( err != OGRERR_NONE )
-            return FALSE;
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "At least one of the required GeoPackage tables, "
+                  "gpkg_spatial_ref_sys or gpkg_contents, is missing");
+        return FALSE;
+    }
 
-        if ( oResult.nRowCount <= 0 )
+    // Detect definition_12_063 column
+    {
+        sqlite3_stmt* hSQLStmt = NULL;
+        int rc = sqlite3_prepare_v2( hDB,
+            "SELECT definition_12_063 FROM gpkg_spatial_ref_sys ", -1,
+            &hSQLStmt, NULL );
+        if( rc == SQLITE_OK )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "required GeoPackage table '%s' is missing", aosGpkgTables[i].c_str());
-            SQLResultFree(&oResult);
-            return FALSE;
+            m_bHasDefinition12_063 = true;
+            sqlite3_finalize(hSQLStmt);
         }
+    }
 
-        SQLResultFree(&oResult);
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( SQLGetInteger(hDB,
+            "SELECT 1 FROM sqlite_master WHERE "
+            "name = 'gpkg_ogr_contents' AND type = 'table'", NULL) == 1 )
+    {
+        m_bHasGPKGOGRContents = true;
     }
+#endif
 
     CheckUnknownExtensions();
 
     int bRet = FALSE;
-    bool bHasGPKGGeometryColumns = false;
     if( poOpenInfo->nOpenFlags & GDAL_OF_VECTOR )
     {
-        SQLResult oResult;
-        const OGRErr err =
-            SQLQuery(hDB, "pragma table_info('gpkg_geometry_columns')", &oResult);
-        bHasGPKGGeometryColumns = err == OGRERR_NONE && oResult.nRowCount > 0;
-        SQLResultFree(&oResult);
+        m_bHasGPKGGeometryColumns = SQLGetInteger(hDB,
+            "SELECT 1 FROM sqlite_master WHERE "
+            "name = 'gpkg_geometry_columns' AND "
+            "type IN ('table', 'view')", NULL) == 1;
     }
-    if( bHasGPKGGeometryColumns )
+    if( m_bHasGPKGGeometryColumns )
     {
         /* Load layer definitions for all tables in gpkg_contents & gpkg_geometry_columns */
         /* and non-spatial tables as well */
         std::string osSQL =
             "SELECT c.table_name, c.identifier, 1 as is_spatial, c.min_x, c.min_y, c.max_x, c.max_y, 1 AS is_gpkg_table "
             "  FROM gpkg_geometry_columns g JOIN gpkg_contents c ON (g.table_name = c.table_name)"
-            "  WHERE c.data_type = 'features' ";
-
-        if (HasGDALAspatialExtension()) {
-            osSQL +=
-                "UNION ALL "
-                "SELECT table_name, identifier, 0 as is_spatial, 0 AS xmin, 0 AS ymin, 0 AS xmax, 0 AS ymax, 1 AS is_gpkg_table "
-                "  FROM gpkg_contents"
-                "  WHERE data_type = 'aspatial' ";
+            "  WHERE c.table_name IS NOT NULL AND"
+            "  c.table_name <> 'ogr_empty_table' AND"
+            "  c.data_type = 'features' "
+            // aspatial: Was the only method available in OGR 2.0 and 2.1
+            // attributes: GPKG 1.2 or later
+            "UNION ALL "
+            "SELECT table_name, identifier, 0 as is_spatial, 0 AS xmin, 0 AS ymin, 0 AS xmax, 0 AS ymax, 1 AS is_gpkg_table "
+            "  FROM gpkg_contents"
+            "  WHERE table_name IS NOT NULL AND data_type IN ('aspatial', 'attributes') ";
+
+        const char* pszListAllTables = CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "LIST_ALL_TABLES", "AUTO");
+        bool bHasASpatialOrAttributes = HasGDALAspatialExtension();
+        if( !bHasASpatialOrAttributes )
+        {
+            SQLResult oResultTable;
+            OGRErr err = SQLQuery(hDB,
+                "SELECT * FROM gpkg_contents WHERE "
+                "data_type = 'attributes' LIMIT 1",
+                &oResultTable);
+            bHasASpatialOrAttributes = ( err == OGRERR_NONE &&
+                                         oResultTable.nRowCount == 1 );
+            SQLResultFree(&oResultTable);
         }
-
-        if( CPLTestBool(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "LIST_ALL_TABLES", "YES")) )
+        if( EQUAL(pszListAllTables, "YES") ||
+            (!bHasASpatialOrAttributes && EQUAL(pszListAllTables, "AUTO")) )
         {
             // vgpkg_ is Spatialite virtual table
             osSQL += "UNION ALL "
                     "SELECT name, name, 0 as is_spatial, 0 AS xmin, 0 AS ymin, 0 AS xmax, 0 AS ymax, 0 AS is_gpkg_table "
-                    "FROM sqlite_master WHERE type IN ('table', 'view') AND name NOT LIKE 'gpkg_%' "
+                    "FROM sqlite_master WHERE type IN ('table', 'view') "
+                    "AND name IS NOT NULL AND name NOT LIKE 'gpkg_%' "
                     "AND name NOT LIKE 'vgpkg_%' "
                     "AND name NOT LIKE 'rtree_%' AND name NOT LIKE 'sqlite_%' "
+                    // Avoid reading those views from simple_sewer_features.gpkg
+                    "AND name NOT IN ('st_spatial_ref_sys', 'spatial_ref_sys', 'st_geometry_columns') "
                     "AND name NOT IN (SELECT table_name FROM gpkg_contents)";
         }
+        const int nTableLimit =
+                    atoi(CPLGetConfigOption("OGR_TABLE_LIMIT", "10000"));
+        if( nTableLimit > 0 )
+        {
+            osSQL += " LIMIT ";
+            osSQL += CPLSPrintf("%d", 1 + nTableLimit);
+        }
 
         SQLResult oResult;
         OGRErr err = SQLQuery(hDB, osSQL.c_str(), &oResult);
@@ -672,18 +785,25 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
             return FALSE;
         }
 
+        if( nTableLimit > 0 && oResult.nRowCount > nTableLimit )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "File has more than %d vector tables. "
+                     "Limiting to first %d (can be overridden with "
+                     "OGR_TABLE_LIMIT config option)",
+                     nTableLimit, nTableLimit);
+            oResult.nRowCount = nTableLimit;
+        }
+
         if ( oResult.nRowCount > 0 )
         {
+            bRet = TRUE;
+
             m_papoLayers = (OGRGeoPackageTableLayer**)CPLMalloc(sizeof(OGRGeoPackageTableLayer*) * oResult.nRowCount);
 
             for ( int i = 0; i < oResult.nRowCount; i++ )
             {
                 const char *pszTableName = SQLResultGetValue(&oResult, 0, i);
-                if ( ! pszTableName )
-                {
-                    CPLError(CE_Warning, CPLE_AppDefined, "unable to read table name for layer(%d)", i);
-                    continue;
-                }
                 bool bIsSpatial = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResult, 2, i));
                 bool bIsGpkgTable = CPL_TO_BOOL(SQLResultGetValueAsInteger(&oResult, 7, i));
                 OGRGeoPackageTableLayer *poLayer = new OGRGeoPackageTableLayer(this, pszTableName);
@@ -695,38 +815,48 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
                 }
                 m_papoLayers[m_nLayers++] = poLayer;
             }
+
+            // For spatial views
+            for ( int i = 0; i < m_nLayers; i++ )
+                m_papoLayers[i]->PostInit();
         }
 
         SQLResultFree(&oResult);
-        bRet = TRUE;
     }
 
     bool bHasTileMatrixSet = false;
     if( poOpenInfo->nOpenFlags & GDAL_OF_RASTER )
     {
-        SQLResult oResult;
-        const OGRErr err =
-            SQLQuery(hDB,
-                     "pragma table_info('gpkg_tile_matrix_set')", &oResult);
-        bHasTileMatrixSet = err == OGRERR_NONE && oResult.nRowCount > 0;
-        SQLResultFree(&oResult);
+        bHasTileMatrixSet = SQLGetInteger(hDB,
+            "SELECT 1 FROM sqlite_master WHERE "
+            "name = 'gpkg_tile_matrix_set' AND "
+            "type IN ('table', 'view')", NULL) == 1;
     }
     if( bHasTileMatrixSet )
     {
         SQLResult oResult;
         std::string osSQL =
-            "SELECT c.table_name, c.identifier, c.description, c.srs_id, c.min_x, c.min_y, c.max_x, c.max_y, "
-            "tms.min_x, tms.min_y, tms.max_x, tms.max_y FROM gpkg_contents c JOIN gpkg_tile_matrix_set tms ON "
-            "c.table_name = tms.table_name WHERE data_type = 'tiles'";
+            "SELECT c.table_name, c.identifier, c.description, c.srs_id, "
+            "c.min_x, c.min_y, c.max_x, c.max_y, "
+            "tms.min_x, tms.min_y, tms.max_x, tms.max_y, c.data_type "
+            "FROM gpkg_contents c JOIN gpkg_tile_matrix_set tms ON "
+            "c.table_name = tms.table_name WHERE "
+            "c.table_name IS NOT NULL AND "
+            "tms.min_x IS NOT NULL AND "
+            "tms.min_y IS NOT NULL AND "
+            "tms.max_x IS NOT NULL AND "
+            "tms.max_y IS NOT NULL AND "
+            "data_type IN ('tiles', '2d-gridded-coverage')";
         if( CSLFetchNameValue( poOpenInfo->papszOpenOptions, "TABLE") )
             osSubdatasetTableName = CSLFetchNameValue( poOpenInfo->papszOpenOptions, "TABLE");
-        if( osSubdatasetTableName.size() )
+        if( !osSubdatasetTableName.empty() )
         {
             char* pszTmp = sqlite3_mprintf(" AND c.table_name='%q'", osSubdatasetTableName.c_str());
             osSQL += pszTmp;
             sqlite3_free(pszTmp);
             SetPhysicalFilename( osFilename.c_str() );
         }
+        osSQL += " LIMIT 1000";
 
         const OGRErr err = SQLQuery(hDB, osSQL.c_str(), &oResult);
         if  ( err != OGRERR_NONE )
@@ -735,7 +865,7 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
             return FALSE;
         }
 
-        if( oResult.nRowCount == 0 && osSubdatasetTableName.size() )
+        if( oResult.nRowCount == 0 && !osSubdatasetTableName.empty() )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot find table '%s' in GeoPackage dataset",
                      osSubdatasetTableName.c_str());
@@ -754,40 +884,45 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
             const char* pszTMSMinY = SQLResultGetValue(&oResult, 9, 0);
             const char* pszTMSMaxX = SQLResultGetValue(&oResult, 10, 0);
             const char* pszTMSMaxY = SQLResultGetValue(&oResult, 11, 0);
-            if( pszTableName != NULL && pszTMSMinX != NULL && pszTMSMinY != NULL &&
-                pszTMSMaxX != NULL && pszTMSMaxY != NULL )
-            {
-                bRet = OpenRaster( pszTableName, pszIdentifier, pszDescription,
-                                   pszSRSId ? atoi(pszSRSId) : 0,
-                                   CPLAtof(pszTMSMinX), CPLAtof(pszTMSMinY),
-                                   CPLAtof(pszTMSMaxX), CPLAtof(pszTMSMaxY),
-                                   pszMinX, pszMinY, pszMaxX, pszMaxY,
-                                   poOpenInfo->papszOpenOptions );
-            }
+            const char* pszDataType = SQLResultGetValue(&oResult, 12, 0);
+
+            bRet = OpenRaster( pszTableName, pszIdentifier, pszDescription,
+                                pszSRSId ? atoi(pszSRSId) : 0,
+                                CPLAtof(pszTMSMinX), CPLAtof(pszTMSMinY),
+                                CPLAtof(pszTMSMaxX), CPLAtof(pszTMSMaxY),
+                                pszMinX, pszMinY, pszMaxX, pszMaxY,
+                                EQUAL(pszDataType, "tiles"),
+                                poOpenInfo->papszOpenOptions );
         }
         else if( oResult.nRowCount >= 1 )
         {
             bRet = TRUE;
 
+            if( oResult.nRowCount == 1000 )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "File has more than 1000 raster tables. "
+                         "Limiting to first 1000");
+            }
+
             int nSDSCount = 0;
             for ( int i = 0; i < oResult.nRowCount; i++ )
             {
                 const char *pszTableName = SQLResultGetValue(&oResult, 0, i);
                 const char *pszIdentifier = SQLResultGetValue(&oResult, 1, i);
-                if( pszTableName != NULL )
-                {
+
+                m_papszSubDatasets = CSLSetNameValue( m_papszSubDatasets,
+                                                    CPLSPrintf("SUBDATASET_%d_NAME", nSDSCount+1),
+                                                    CPLSPrintf("GPKG:%s:%s", m_pszFilename, pszTableName) );
+                if( pszIdentifier )
                     m_papszSubDatasets = CSLSetNameValue( m_papszSubDatasets,
-                                                        CPLSPrintf("SUBDATASET_%d_NAME", nSDSCount+1),
-                                                        CPLSPrintf("GPKG:%s:%s", m_pszFilename, pszTableName) );
-                    if( pszIdentifier )
-                        m_papszSubDatasets = CSLSetNameValue( m_papszSubDatasets,
-                                                              CPLSPrintf("SUBDATASET_%d_DESC", nSDSCount+1),
-                                                              CPLSPrintf("%s - %s", pszTableName, pszIdentifier) );
-                    else
-                        m_papszSubDatasets = CSLSetNameValue( m_papszSubDatasets,
-                                                              CPLSPrintf("SUBDATASET_%d_DESC", nSDSCount+1),
-                                                              pszTableName );
-                }
+                                                            CPLSPrintf("SUBDATASET_%d_DESC", nSDSCount+1),
+                                                            CPLSPrintf("%s - %s", pszTableName, pszIdentifier) );
+                else
+                    m_papszSubDatasets = CSLSetNameValue( m_papszSubDatasets,
+                                                            CPLSPrintf("SUBDATASET_%d_DESC", nSDSCount+1),
+                                                            pszTableName );
+
                 nSDSCount ++;
             }
         }
@@ -795,6 +930,21 @@ int GDALGeoPackageDataset::Open( GDALOpenInfo* poOpenInfo )
         SQLResultFree(&oResult);
     }
 
+    if( !bRet && (poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) )
+    {
+        if ( (poOpenInfo->nOpenFlags & GDAL_OF_UPDATE) )
+        {
+            bRet = TRUE;
+        }
+        else
+        {
+            CPLDebug("GPKG",
+                     "This GeoPackage has no vector content and is opened "
+                     "in read-only mode. If you open it in update mode, "
+                     "opening will be successful.");
+        }
+    }
+
     return bRet;
 }
 
@@ -825,8 +975,12 @@ bool GDALGeoPackageDataset::InitRaster( GDALGeoPackageDataset* poParentDS,
     double dfPixelYSize = CPLAtof(SQLResultGetValue(&oResult, 2, nIdxInResult));
     int nTileWidth = atoi(SQLResultGetValue(&oResult, 3, nIdxInResult));
     int nTileHeight = atoi(SQLResultGetValue(&oResult, 4, nIdxInResult));
-    int nTileMatrixWidth = atoi(SQLResultGetValue(&oResult, 5, nIdxInResult));
-    int nTileMatrixHeight = atoi(SQLResultGetValue(&oResult, 6, nIdxInResult));
+    int nTileMatrixWidth = static_cast<int>(
+        std::min(static_cast<GIntBig>(INT_MAX),
+                 CPLAtoGIntBig(SQLResultGetValue(&oResult, 5, nIdxInResult))));
+    int nTileMatrixHeight = static_cast<int>(
+        std::min(static_cast<GIntBig>(INT_MAX),
+                 CPLAtoGIntBig(SQLResultGetValue(&oResult, 6, nIdxInResult))));
 
     /* Use content bounds in priority over tile_matrix_set bounds */
     double dfGDALMinX = dfMinX;
@@ -847,12 +1001,17 @@ bool GDALGeoPackageDataset::InitRaster( GDALGeoPackageDataset* poParentDS,
     }
     if( dfGDALMinX >= dfGDALMaxX || dfGDALMinY >= dfGDALMaxY )
     {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Illegal min_x/min_y/max_x/max_y values for %s",
+                 pszTableName);
         return false;
     }
 
     int nBandCount = atoi(CSLFetchNameValueDef(papszOpenOptionsIn, "BAND_COUNT", "4"));
     if( nBandCount != 1 && nBandCount != 2 && nBandCount != 3 && nBandCount != 4 )
         nBandCount = 4;
+    if( m_eDT != GDT_Byte )
+        nBandCount = 1;
 
     return InitRaster(poParentDS, pszTableName, nZoomLevel, nBandCount, dfMinX, dfMaxY,
                       dfPixelXSize, dfPixelYSize, nTileWidth, nTileHeight,
@@ -864,19 +1023,27 @@ bool GDALGeoPackageDataset::InitRaster( GDALGeoPackageDataset* poParentDS,
 /*                      ComputeTileAndPixelShifts()                     */
 /************************************************************************/
 
-void GDALGeoPackageDataset::ComputeTileAndPixelShifts()
+bool GDALGeoPackageDataset::ComputeTileAndPixelShifts()
 {
     int nTileWidth, nTileHeight;
     GetRasterBand(1)->GetBlockSize(&nTileWidth, &nTileHeight);
 
     // Compute shift between GDAL origin and TileMatrixSet origin
-    int nShiftXPixels = (int)floor(0.5 + (m_adfGeoTransform[0] - m_dfTMSMinX) /  m_adfGeoTransform[1]);
-    m_nShiftXTiles = (int)floor(1.0 * nShiftXPixels / nTileWidth);
+    double dfShiftXPixels = (m_adfGeoTransform[0] - m_dfTMSMinX) / 
+                                                        m_adfGeoTransform[1];
+    if( dfShiftXPixels < INT_MIN || dfShiftXPixels + 0.5 > INT_MAX )
+        return false;
+    int nShiftXPixels = static_cast<int>(floor(0.5 + dfShiftXPixels));
+    m_nShiftXTiles = static_cast<int>(floor(1.0 * nShiftXPixels / nTileWidth));
     m_nShiftXPixelsMod = ((nShiftXPixels % nTileWidth) + nTileWidth) % nTileWidth;
-    int nShiftYPixels = (int)floor(0.5 + (m_adfGeoTransform[3] - m_dfTMSMaxY) /  m_adfGeoTransform[5]);
-    m_nShiftYTiles = (int)floor(1.0 * nShiftYPixels / nTileHeight);
+    double dfShiftYPixels = (m_adfGeoTransform[3] - m_dfTMSMaxY) /
+                                                        m_adfGeoTransform[5];
+    if( dfShiftYPixels < INT_MIN || dfShiftYPixels + 0.5 > INT_MAX )
+        return false;
+    int nShiftYPixels = static_cast<int>(floor(0.5 + dfShiftYPixels));
+    m_nShiftYTiles = static_cast<int>(floor(1.0 * nShiftYPixels / nTileHeight));
     m_nShiftYPixelsMod = ((nShiftYPixels % nTileHeight) + nTileHeight) % nTileHeight;
-
+    return true;
 }
 
 /************************************************************************/
@@ -915,23 +1082,14 @@ bool GDALGeoPackageDataset::InitRaster( GDALGeoPackageDataset* poParentDS,
     double dfRasterXSize = 0.5 + (dfGDALMaxX - dfGDALMinX) / dfPixelXSize;
     double dfRasterYSize = 0.5 + (dfGDALMaxY - dfGDALMinY) / dfPixelYSize;
     if( dfRasterXSize > INT_MAX || dfRasterYSize > INT_MAX )
-        return false;
-    nRasterXSize = (int)dfRasterXSize;
-    nRasterYSize = (int)dfRasterYSize;
-
-    m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4, nTileWidth, nTileHeight);
-    if( m_pabyCachedTiles == NULL )
     {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Too big raster: %f x %f",
+                 dfRasterXSize, dfRasterYSize);
         return false;
     }
-
-    for(int i = 1; i <= nBandCount; i ++)
-        SetBand( i, new GDALGeoPackageRasterBand(this, nTileWidth, nTileHeight) );
-
-    ComputeTileAndPixelShifts();
-
-    GDALPamDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
-    GDALPamDataset::SetMetadataItem("ZOOM_LEVEL", CPLSPrintf("%d", m_nZoomLevel));
+    nRasterXSize = std::max(1, static_cast<int>(dfRasterXSize));
+    nRasterYSize = std::max(1, static_cast<int>(dfRasterYSize));
 
     if( poParentDS )
     {
@@ -940,6 +1098,12 @@ bool GDALGeoPackageDataset::InitRaster( GDALGeoPackageDataset* poParentDS,
         eAccess = poParentDS->eAccess;
         hDB = poParentDS->hDB;
         m_eTF = poParentDS->m_eTF;
+        m_eDT = poParentDS->m_eDT;
+        m_nDTSize = poParentDS->m_nDTSize;
+        m_dfScale = poParentDS->m_dfScale;
+        m_dfOffset = poParentDS->m_dfOffset;
+        m_dfPrecision = poParentDS->m_dfPrecision;
+        m_usGPKGNull = poParentDS->m_usGPKGNull;
         m_nQuality = poParentDS->m_nQuality;
         m_nZLevel = poParentDS->m_nZLevel;
         m_bDither = poParentDS->m_bDither;
@@ -949,6 +1113,40 @@ bool GDALGeoPackageDataset::InitRaster( GDALGeoPackageDataset* poParentDS,
                                   poParentDS->GetDescription(), m_nZoomLevel));
     }
 
+    for(int i = 1; i <= nBandCount; i ++)
+    {
+        GDALGeoPackageRasterBand* poNewBand =
+            new GDALGeoPackageRasterBand(this, nTileWidth, nTileHeight);
+        if( poParentDS )
+        {
+            int bHasNoData = FALSE;
+            double dfNoDataValue =
+                poParentDS->GetRasterBand(1)->GetNoDataValue(&bHasNoData);
+            if( bHasNoData )
+                poNewBand->SetNoDataValueInternal(dfNoDataValue);
+        }
+        SetBand( i, poNewBand );
+    }
+
+    if( !ComputeTileAndPixelShifts() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Overflow occurred in ComputeTileAndPixelShifts()");
+        return false;
+    }
+
+    GDALPamDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
+    GDALPamDataset::SetMetadataItem("ZOOM_LEVEL", CPLSPrintf("%d", m_nZoomLevel));
+
+    m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4 * m_nDTSize,
+                                                     nTileWidth, nTileHeight);
+    if( m_pabyCachedTiles == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Too big tiles: %d x %d", nTileWidth, nTileHeight);
+        return false;
+    }
+
     return true;
 }
 
@@ -961,7 +1159,7 @@ GPKGTileFormat GDALGPKGMBTilesGetTileFormat(const char* pszTF )
     GPKGTileFormat eTF = GPKG_TF_PNG_JPEG;
     if( pszTF )
     {
-        if( EQUAL(pszTF, "PNG_JPEG") )
+        if( EQUAL(pszTF, "PNG_JPEG") || EQUAL(pszTF, "AUTO") )
             eTF = GPKG_TF_PNG_JPEG;
         else if( EQUAL(pszTF, "PNG") )
             eTF = GPKG_TF_PNG;
@@ -971,6 +1169,11 @@ GPKGTileFormat GDALGPKGMBTilesGetTileFormat(const char* pszTF )
             eTF = GPKG_TF_JPEG;
         else if( EQUAL(pszTF, "WEBP") )
             eTF = GPKG_TF_WEBP;
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsuppoted value for TILE_FORMAT: %s", pszTF);
+        }
     }
     return eTF;
 }
@@ -991,6 +1194,7 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
                                         const char* pszContentsMinY,
                                         const char* pszContentsMaxX,
                                         const char* pszContentsMaxY,
+                                        bool bIsTiles,
                                         char** papszOpenOptionsIn )
 {
     OGRErr err;
@@ -999,6 +1203,113 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
     if( dfMinX >= dfMaxX || dfMinY >= dfMaxY )
         return false;
 
+    CPLString osDataNull;
+    if( !bIsTiles )
+    {
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT datatype, scale, offset, data_null, precision FROM "
+            "gpkg_2d_gridded_coverage_ancillary "
+            "WHERE tile_matrix_set_name = '%q' "
+            "AND datatype IN ('integer', 'float')"
+            "AND (scale > 0 OR scale IS NULL)", pszTableName);
+        err = SQLQuery(hDB, pszSQL, &oResult);
+        sqlite3_free(pszSQL);
+        if( err != OGRERR_NONE || oResult.nRowCount == 0 )
+        {
+
+            SQLResultFree(&oResult);
+            return false;
+        }
+        const char* pszDataType = SQLResultGetValue(&oResult, 0, 0);
+        const char* pszScale = SQLResultGetValue(&oResult, 1, 0);
+        const char* pszOffset = SQLResultGetValue(&oResult, 2, 0);
+        const char* pszDataNull = SQLResultGetValue(&oResult, 3, 0);
+        const char* pszPrecision = SQLResultGetValue(&oResult, 4, 0);
+        if( pszDataNull )
+            osDataNull = pszDataNull;
+        if( EQUAL(pszDataType, "float") )
+        {
+            SetDataType(GDT_Float32);
+            m_eTF = GPKG_TF_TIFF_32BIT_FLOAT;
+        }
+        else
+        {
+            SetDataType(GDT_Float32);
+            m_eTF = GPKG_TF_PNG_16BIT;
+            const double dfScale = pszScale ? CPLAtof(pszScale) : 1.0;
+            const double dfOffset = pszOffset ? CPLAtof(pszOffset) : 0.0;
+            if( dfScale == 1.0 )
+            {
+                if( dfOffset == 0.0 )
+                {
+                    SetDataType(GDT_UInt16);
+                }
+                else if( dfOffset == -32768.0 )
+                {
+                    SetDataType(GDT_Int16);
+                }
+                else if( dfOffset == -32767.0 && !osDataNull.empty() &&
+                         CPLAtof(osDataNull) == 65535.0 )
+                    // Given that we will map the nodata value to -32768
+                {
+                    SetDataType(GDT_Int16);
+                }
+            }
+
+            // Check that the tile offset and scales are compatible of a
+            // final integer result.
+            if( m_eDT != GDT_Float32 )
+            {
+                if( dfScale == 1.0 && dfOffset == -32768.0 &&
+                    !osDataNull.empty() &&
+                    CPLAtof(osDataNull) == 65535.0 )
+                {
+                    // Given that we will map the nodata value to -32768
+                    pszSQL = sqlite3_mprintf(
+                        "SELECT 1 FROM "
+                        "gpkg_2d_gridded_tile_ancillary WHERE "
+                        "tpudt_name = '%q' "
+                        "AND NOT ((offset = 0.0 or offset = 1.0) "
+                        "AND scale = 1.0) "
+                        "LIMIT 1",
+                        pszTableName);
+                }
+                else
+                {
+                    pszSQL = sqlite3_mprintf(
+                        "SELECT 1 FROM "
+                        "gpkg_2d_gridded_tile_ancillary WHERE "
+                        "tpudt_name = '%q' "
+                        "AND NOT (offset = 0.0 AND scale = 1.0) LIMIT 1",
+                        pszTableName);
+                }
+                sqlite3_stmt* hSQLStmt = NULL;
+                int rc = sqlite3_prepare_v2( hDB, pszSQL, -1,
+                                          &hSQLStmt, NULL );
+
+                if( rc == SQLITE_OK )
+                {
+                    if( sqlite3_step(hSQLStmt) == SQLITE_ROW )
+                    {
+                        SetDataType(GDT_Float32);
+                    }
+                    sqlite3_finalize( hSQLStmt );
+                }
+                else
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Error when running %s", pszSQL);
+                }
+                sqlite3_free(pszSQL);
+            }
+
+            SetGlobalOffsetScale(dfOffset, dfScale);
+        }
+        if( pszPrecision )
+            m_dfPrecision = CPLAtof(pszPrecision);
+        SQLResultFree(&oResult);
+    }
+
     m_bRecordInsertedInGPKGContent = true;
     m_nSRID = nSRSId;
     if( nSRSId > 0 )
@@ -1011,15 +1322,22 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         }
     }
 
-    /* The NOT NULL are just in case the tables would have been built without */
-    /* the mandatory constraints */
+    /* Various sanity checks added in the SELECT */
     char* pszQuotedTableName = sqlite3_mprintf("'%q'", pszTableName);
     CPLString osQuotedTableName(pszQuotedTableName);
     sqlite3_free(pszQuotedTableName);
     char* pszSQL = sqlite3_mprintf(
-            "SELECT zoom_level, pixel_x_size, pixel_y_size, tile_width, tile_height, matrix_width, matrix_height FROM gpkg_tile_matrix tm "
-            "WHERE table_name = %s AND pixel_x_size > 0 "
-            "AND pixel_y_size > 0 AND tile_width > 0 AND tile_height > 0 AND matrix_width > 0 AND matrix_height > 0",
+            "SELECT zoom_level, pixel_x_size, pixel_y_size, tile_width, "
+            "tile_height, matrix_width, matrix_height "
+            "FROM gpkg_tile_matrix tm "
+            "WHERE table_name = %s "
+            // INT_MAX would be the theoretical maximum value to avoid
+            // overflows, but that's already a insane value.
+            "AND zoom_level >= 0 AND zoom_level <= 65536 "
+            "AND pixel_x_size > 0 AND pixel_y_size > 0 "
+            "AND tile_width > 0 AND tile_width <= 65536 "
+            "AND tile_height > 0 AND tile_height <= 65536 "
+            "AND matrix_width > 0 AND matrix_height > 0",
             osQuotedTableName.c_str());
     CPLString osSQL(pszSQL);
     const char* pszZoomLevel =  CSLFetchNameValue(papszOpenOptionsIn, "ZOOM_LEVEL");
@@ -1045,6 +1363,8 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
                             osQuotedTableName.c_str());
     }
     osSQL += " ORDER BY zoom_level DESC";
+    // To avoid denial of service.
+    osSQL += " LIMIT 100";
 
     err = SQLQuery(hDB, osSQL.c_str(), &oResult);
     if( err != OGRERR_NONE || oResult.nRowCount == 0 )
@@ -1062,6 +1382,12 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         }
         if( err != OGRERR_NONE || oResult.nRowCount == 0 )
         {
+            if( err == OGRERR_NONE && pszZoomLevel != NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "ZOOM_LEVEL is probably not valid w.r.t tile "
+                         "table content");
+            }
             SQLResultFree(&oResult);
             sqlite3_free(pszSQL);
             return false;
@@ -1071,16 +1397,24 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
 
     // If USE_TILE_EXTENT=YES, then query the tile table to find which tiles
     // actually exist.
+
+    // CAUTION: Do not move those variables inside inner scope !
     CPLString osContentsMinX, osContentsMinY, osContentsMaxX, osContentsMaxY;
+
     if( CPLTestBool(CSLFetchNameValueDef(papszOpenOptionsIn, "USE_TILE_EXTENT", "NO")) )
     {
         pszSQL = sqlite3_mprintf(
-            "SELECT MIN(tile_column), MIN(tile_row), MAX(tile_column), MAX(tile_row) FROM '%q' WHERE zoom_level = %d",
+            "SELECT MIN(tile_column), MIN(tile_row), MAX(tile_column), MAX(tile_row) FROM \"%w\" WHERE zoom_level = %d",
             pszTableName, atoi(SQLResultGetValue(&oResult, 0, 0)));
         SQLResult oResult2;
         err = SQLQuery(hDB, pszSQL, &oResult2);
         sqlite3_free(pszSQL);
-        if  ( err != OGRERR_NONE || oResult2.nRowCount == 0 )
+        if  ( err != OGRERR_NONE || oResult2.nRowCount == 0 ||
+                // Can happen if table is empty
+              SQLResultGetValue(&oResult2, 0, 0) == NULL || 
+                // Can happen if table has no NOT NULL constraint on tile_row
+                // and that all tile_row are NULL
+              SQLResultGetValue(&oResult2, 1, 0) == NULL  )
         {
             SQLResultFree(&oResult);
             SQLResultFree(&oResult2);
@@ -1110,6 +1444,35 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         return false;
     }
 
+    if( !osDataNull.empty() )
+    {
+        double dfGPKGNoDataValue = CPLAtof(osDataNull);
+        if( m_eTF == GPKG_TF_PNG_16BIT )
+        {
+            if( dfGPKGNoDataValue < 0 ||
+                dfGPKGNoDataValue > 65535 ||
+                static_cast<int>(dfGPKGNoDataValue) != dfGPKGNoDataValue )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "data_null = %.18g is invalid for integer data_type",
+                         dfGPKGNoDataValue);
+            }
+            else
+            {
+                m_usGPKGNull = static_cast<GUInt16>(dfGPKGNoDataValue);
+                if( m_eDT == GDT_Int16 && m_usGPKGNull > 32767 )
+                    dfGPKGNoDataValue = -32768.0;
+                reinterpret_cast<GDALGeoPackageRasterBand*>(GetRasterBand(1))->
+                                SetNoDataValueInternal(dfGPKGNoDataValue);
+            }
+        }
+        else
+        {
+            reinterpret_cast<GDALGeoPackageRasterBand*>(GetRasterBand(1))->
+                SetNoDataValueInternal(static_cast<float>(dfGPKGNoDataValue));
+        }
+    }
+
     CheckUnknownExtensions(true);
 
     // Do this after CheckUnknownExtensions() so that m_eTF is set to GPKG_TF_WEBP
@@ -1120,7 +1483,13 @@ bool GDALGeoPackageDataset::OpenRaster( const char* pszTableName,
         if( !bUpdate )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
-                     "DRIVER open option ignored in read-only mode");
+                     "TILE_FORMAT open option ignored in read-only mode");
+        }
+        else if( m_eTF == GPKG_TF_PNG_16BIT ||
+                 m_eTF == GPKG_TF_TIFF_32BIT_FLOAT )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "TILE_FORMAT open option ignored on gridded coverages");
         }
         else
         {
@@ -1209,7 +1578,7 @@ CPLErr GDALGeoPackageDataset::SetProjection( const char* pszProjection )
         OGRSpatialReference oSRS;
         if( oSRS.SetFromUserInput(pszProjection) != OGRERR_NONE )
             return CE_Failure;
-        nSRID = GetSrsId( &oSRS );
+        nSRID = GetSrsId( oSRS );
     }
 
     for(size_t iScheme = 0;
@@ -1347,8 +1716,6 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
 
     int nTileWidth, nTileHeight;
     GetRasterBand(1)->GetBlockSize(&nTileWidth, &nTileHeight);
-    m_nTileMatrixWidth = (nRasterXSize + nTileWidth - 1) / nTileWidth;
-    m_nTileMatrixHeight = (nRasterYSize + nTileHeight - 1) / nTileHeight;
 
     if( m_nZoomLevel < 0 )
     {
@@ -1360,8 +1727,10 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
 
     double dfPixelXSizeZoomLevel0 = m_adfGeoTransform[1] * (1 << m_nZoomLevel);
     double dfPixelYSizeZoomLevel0 = fabs(m_adfGeoTransform[5]) * (1 << m_nZoomLevel);
-    int nTileXCountZoomLevel0 = ((nRasterXSize >> m_nZoomLevel) + nTileWidth - 1) / nTileWidth;
-    int nTileYCountZoomLevel0 = ((nRasterYSize >> m_nZoomLevel) + nTileHeight - 1) / nTileHeight;
+    int nTileXCountZoomLevel0 =
+        std::max(1, DIV_ROUND_UP((nRasterXSize >> m_nZoomLevel), nTileWidth));
+    int nTileYCountZoomLevel0 =
+        std::max(1, DIV_ROUND_UP((nRasterYSize >> m_nZoomLevel), nTileHeight));
 
     for(size_t iScheme = 0;
                iScheme < sizeof(asTilingShemes)/sizeof(asTilingShemes[0]);
@@ -1376,13 +1745,18 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
             dfPixelYSizeZoomLevel0 = asTilingShemes[iScheme].dfPixelYSizeZoomLevel0;
             nTileXCountZoomLevel0 = asTilingShemes[iScheme].nTileXCountZoomLevel0;
             nTileYCountZoomLevel0 = asTilingShemes[iScheme].nTileYCountZoomLevel0;
-            m_nTileMatrixWidth = nTileXCountZoomLevel0 * (1 << m_nZoomLevel);
-            m_nTileMatrixHeight = nTileYCountZoomLevel0 * (1 << m_nZoomLevel);
             break;
         }
     }
+    m_nTileMatrixWidth = nTileXCountZoomLevel0 * (1 << m_nZoomLevel);
+    m_nTileMatrixHeight = nTileYCountZoomLevel0 * (1 << m_nZoomLevel);
 
-    ComputeTileAndPixelShifts();
+    if( !ComputeTileAndPixelShifts() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Overflow occurred in ComputeTileAndPixelShifts()");
+        return CE_Failure;
+    };
 
     double dfGDALMinX = m_adfGeoTransform[0];
     double dfGDALMinY = m_adfGeoTransform[3] + nRasterYSize * m_adfGeoTransform[5];
@@ -1394,12 +1768,13 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
     const char* pszCurrentDate = CPLGetConfigOption("OGR_CURRENT_DATE", NULL);
     CPLString osInsertGpkgContentsFormatting("INSERT INTO gpkg_contents "
             "(table_name,data_type,identifier,description,min_x,min_y,max_x,max_y,last_change,srs_id) VALUES "
-            "('%q','tiles','%q','%q',%.18g,%.18g,%.18g,%.18g,");
+            "('%q','%q','%q','%q',%.18g,%.18g,%.18g,%.18g,");
     osInsertGpkgContentsFormatting += ( pszCurrentDate ) ? "'%q'" : "%s";
     osInsertGpkgContentsFormatting += ",%d)";
     char* pszSQL =
         sqlite3_mprintf(osInsertGpkgContentsFormatting.c_str(),
         m_osRasterTable.c_str(),
+        (m_eDT == GDT_Byte) ? "tiles" : "2d-gridded-coverage",
         m_osIdentifier.c_str(),
         m_osDescription.c_str(),
         dfGDALMinX, dfGDALMinY, dfGDALMaxX, dfGDALMaxY,
@@ -1437,16 +1812,15 @@ CPLErr GDALGeoPackageDataset::FinalizeRasterRegistration()
         {
             dfPixelXSizeZoomLevel = m_adfGeoTransform[1] * (1 << (m_nZoomLevel-i));
             dfPixelYSizeZoomLevel = fabs(m_adfGeoTransform[5]) * (1 << (m_nZoomLevel-i));
-            nTileMatrixWidth = ((nRasterXSize >> (m_nZoomLevel-i)) + nTileWidth - 1) / nTileWidth;
-            nTileMatrixHeight = ((nRasterYSize >> (m_nZoomLevel-i)) + nTileHeight - 1) / nTileHeight;
         }
         else
         {
             dfPixelXSizeZoomLevel = dfPixelXSizeZoomLevel0 / (1 << i);
             dfPixelYSizeZoomLevel = dfPixelYSizeZoomLevel0 / (1 << i);
-            nTileMatrixWidth = nTileXCountZoomLevel0 * (1 << i);
-            nTileMatrixHeight = nTileYCountZoomLevel0 * (1 << i);
         }
+        nTileMatrixWidth = nTileXCountZoomLevel0 * (1 << i);
+        nTileMatrixHeight = nTileYCountZoomLevel0 * (1 << i);
+
         pszSQL = sqlite3_mprintf("INSERT INTO gpkg_tile_matrix "
                 "(table_name,zoom_level,matrix_width,matrix_height,tile_width,tile_height,pixel_x_size,pixel_y_size) VALUES "
                 "('%q',%d,%d,%d,%d,%d,%.18g,%.18g)",
@@ -1507,30 +1881,7 @@ CPLErr GDALGeoPackageDataset::IFlushCacheWithErrCode()
     // Update raster table last_change column in gpkg_contents if needed
     if( m_bHasModifiedTiles )
     {
-        const char* pszCurrentDate = CPLGetConfigOption("OGR_CURRENT_DATE", NULL);
-        char *pszSQL = NULL ;
-
-        if( pszCurrentDate )
-        {
-            pszSQL = sqlite3_mprintf(
-                        "UPDATE gpkg_contents SET "
-                        "last_change = '%q'"
-                        "WHERE table_name = '%q' AND "
-                        "Lower(data_type) = 'tiles'",
-                        m_osRasterTable.c_str(), pszCurrentDate);
-        }
-        else
-        {
-            pszSQL = sqlite3_mprintf(
-                        "UPDATE gpkg_contents SET "
-                        "last_change = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ','now')"
-                        "WHERE table_name = '%q' AND "
-                        "Lower(data_type) = 'tiles'",
-                        m_osRasterTable.c_str());
-        }
-
-        CPL_IGNORE_RET_VAL(SQLCommand(hDB, pszSQL));
-        sqlite3_free(pszSQL);
+        UpdateGpkgContentsLastChange(m_osRasterTable);
 
         m_bHasModifiedTiles = false;
     }
@@ -1542,6 +1893,39 @@ CPLErr GDALGeoPackageDataset::IFlushCacheWithErrCode()
 }
 
 /************************************************************************/
+/*                    UpdateGpkgContentsLastChange()                    */
+/************************************************************************/
+
+OGRErr GDALGeoPackageDataset::UpdateGpkgContentsLastChange(
+                                                const char* pszTableName)
+{
+    const char* pszCurrentDate = CPLGetConfigOption("OGR_CURRENT_DATE", NULL);
+    char *pszSQL = NULL ;
+
+    if( pszCurrentDate )
+    {
+        pszSQL = sqlite3_mprintf(
+                    "UPDATE gpkg_contents SET "
+                    "last_change = '%q'"
+                    "WHERE table_name = '%q'",
+                    pszCurrentDate,
+                    pszTableName);
+    }
+    else
+    {
+        pszSQL = sqlite3_mprintf(
+                    "UPDATE gpkg_contents SET "
+                    "last_change = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ','now')"
+                    "WHERE table_name = '%q'",
+                    pszTableName);
+    }
+
+    OGRErr eErr = SQLCommand(hDB, pszSQL);
+    sqlite3_free(pszSQL);
+    return eErr;
+}
+
+/************************************************************************/
 /*                          IBuildOverviews()                           */
 /************************************************************************/
 
@@ -1558,7 +1942,7 @@ static int GetFloorPowerOfTwo(int n)
 CPLErr GDALGeoPackageDataset::IBuildOverviews(
                         const char * pszResampling,
                         int nOverviews, int * panOverviewList,
-                        int nBandsIn, CPL_UNUSED int * panBandList,
+                        int nBandsIn, int * /*panBandList*/,
                         GDALProgressFunc pfnProgress, void * pProgressData )
 {
     if( GetAccess() != GA_Update )
@@ -1578,19 +1962,41 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
     {
         for(int i=0;i<m_nOverviewCount;i++)
             m_papoOverviewDS[i]->FlushCache();
-        char* pszSQL = sqlite3_mprintf("DELETE FROM '%q' WHERE zoom_level < %d",
+
+        SoftStartTransaction();
+
+        if( m_eTF == GPKG_TF_PNG_16BIT ||
+            m_eTF == GPKG_TF_TIFF_32BIT_FLOAT )
+        {
+            char* pszSQL = sqlite3_mprintf(
+                "DELETE FROM gpkg_2d_gridded_tile_ancillary WHERE id IN "
+                "(SELECT y.id FROM \"%w\" x "
+                "JOIN gpkg_2d_gridded_tile_ancillary y "
+                "ON x.id = y.tpudt_id AND y.tpudt_name = '%q' AND "
+                "x.zoom_level < %d)",
+                m_osRasterTable.c_str(), m_osRasterTable.c_str(), m_nZoomLevel);
+            OGRErr eErr = SQLCommand(hDB, pszSQL);
+            sqlite3_free(pszSQL);
+            if( eErr != OGRERR_NONE )
+            {
+                SoftRollbackTransaction();
+                return CE_Failure;
+            }
+        }
+
+        char* pszSQL = sqlite3_mprintf("DELETE FROM \"%w\" WHERE zoom_level < %d",
                                        m_osRasterTable.c_str(),
                                        m_nZoomLevel);
-        char* pszErrMsg = NULL;
-        int ret = sqlite3_exec(hDB, pszSQL, NULL, NULL, &pszErrMsg);
+        OGRErr eErr = SQLCommand(hDB, pszSQL);
         sqlite3_free(pszSQL);
-        if( ret != SQLITE_OK )
+        if( eErr != OGRERR_NONE )
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "Failure: %s",
-                     pszErrMsg ? pszErrMsg : "");
-            sqlite3_free(pszErrMsg);
+            SoftRollbackTransaction();
             return CE_Failure;
         }
+
+        SoftCommitTransaction();
+
         return CE_None;
     }
 
@@ -1629,7 +2035,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                                                 poODS->GetRasterYSize(),
                                                 GetRasterYSize());
             if( nOvFactor > 64 &&
-                ABS(nOvFactor - GetFloorPowerOfTwo(nOvFactor)) <= 2 )
+                std::abs(nOvFactor - GetFloorPowerOfTwo(nOvFactor)) <= 2 )
             {
                 nOvFactor = GetFloorPowerOfTwo(nOvFactor);
             }
@@ -1731,7 +2137,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                         return CE_Failure;
                     }
 
-                    pszSQL = sqlite3_mprintf("UPDATE '%q' SET zoom_level = %d "
+                    pszSQL = sqlite3_mprintf("UPDATE \"%w\" SET zoom_level = %d "
                         "WHERE zoom_level = %d",
                         m_osRasterTable.c_str(),
                         m_nZoomLevel - k + 1,
@@ -1818,7 +2224,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
                                         poODS->GetRasterYSize(),
                                         GetRasterYSize());
                 if( nOvFactor > 64 &&
-                    ABS(nOvFactor - GetFloorPowerOfTwo(nOvFactor)) <= 2 )
+                    std::abs(nOvFactor - GetFloorPowerOfTwo(nOvFactor)) <= 2 )
                 {
                     nOvFactor = GetFloorPowerOfTwo(nOvFactor);
                 }
@@ -1868,7 +2274,7 @@ CPLErr GDALGeoPackageDataset::IBuildOverviews(
 char **GDALGeoPackageDataset::GetMetadataDomainList()
 {
     GetMetadata();
-    if( m_osRasterTable.size() != 0 )
+    if( !m_osRasterTable.empty() )
         GetMetadata("GEOPACKAGE");
     return BuildMetadataDomainList(GDALPamDataset::GetMetadataDomainList(),
                                    TRUE,
@@ -1882,7 +2288,7 @@ char **GDALGeoPackageDataset::GetMetadataDomainList()
 const char* GDALGeoPackageDataset::CheckMetadataDomain( const char* pszDomain )
 {
     if( pszDomain != NULL && EQUAL(pszDomain, "GEOPACKAGE") &&
-        m_osRasterTable.size() == 0 )
+        m_osRasterTable.empty() )
     {
         CPLError(CE_Warning, CPLE_IllegalArg,
                  "Using GEOPACKAGE for a non-raster geopackage is not supported. "
@@ -1898,12 +2304,11 @@ const char* GDALGeoPackageDataset::CheckMetadataDomain( const char* pszDomain )
 
 bool GDALGeoPackageDataset::HasMetadataTables()
 {
-    OGRErr err;
     const int nCount = SQLGetInteger(hDB,
                   "SELECT COUNT(*) FROM sqlite_master WHERE name IN "
                   "('gpkg_metadata', 'gpkg_metadata_reference') "
-                  "AND type IN ('table', 'view')", &err);
-    return err == OGRERR_NONE && nCount == 2;
+                  "AND type IN ('table', 'view')", NULL);
+    return nCount == 2;
 }
 
 /************************************************************************/
@@ -1926,21 +2331,32 @@ char **GDALGeoPackageDataset::GetMetadata( const char *pszDomain )
         return GDALPamDataset::GetMetadata( pszDomain );
 
     char* pszSQL = NULL;
-    if( m_osRasterTable.size() )
+    if( !m_osRasterTable.empty() )
     {
         pszSQL = sqlite3_mprintf(
-            "SELECT md.metadata, md.md_standard_uri, md.mime_type, mdr.reference_scope FROM gpkg_metadata md "
+            "SELECT md.metadata, md.md_standard_uri, md.mime_type, "
+            "mdr.reference_scope FROM gpkg_metadata md "
             "JOIN gpkg_metadata_reference mdr ON (md.id = mdr.md_file_id ) "
-            "WHERE mdr.reference_scope = 'geopackage' OR "
-            "(mdr.reference_scope = 'table' AND mdr.table_name = '%q') ORDER BY md.id",
+            "WHERE md.metadata IS NOT NULL AND "
+            "md.md_standard_uri IS NOT NULL AND "
+            "md.mime_type IS NOT NULL AND "
+            "(mdr.reference_scope = 'geopackage' OR "
+            "(mdr.reference_scope = 'table' AND mdr.table_name = '%q')) ORDER BY md.id "
+            "LIMIT 1000", // to avoid denial of service
             m_osRasterTable.c_str());
     }
     else
     {
         pszSQL = sqlite3_mprintf(
-            "SELECT md.metadata, md.md_standard_uri, md.mime_type, mdr.reference_scope FROM gpkg_metadata md "
+            "SELECT md.metadata, md.md_standard_uri, md.mime_type, "
+            "mdr.reference_scope FROM gpkg_metadata md "
             "JOIN gpkg_metadata_reference mdr ON (md.id = mdr.md_file_id ) "
-            "WHERE mdr.reference_scope = 'geopackage' ORDER BY md.id");
+            "WHERE md.metadata IS NOT NULL AND "
+            "md.md_standard_uri IS NOT NULL AND "
+            "md.mime_type IS NOT NULL AND "
+            "mdr.reference_scope = 'geopackage' ORDER BY md.id "
+            "LIMIT 1000" // to avoid denial of service
+        );
     }
 
     SQLResult oResult;
@@ -1962,17 +2378,15 @@ char **GDALGeoPackageDataset::GetMetadata( const char *pszDomain )
         const char* pszMimeType = SQLResultGetValue(&oResult, 2, i);
         const char* pszReferenceScope = SQLResultGetValue(&oResult, 3, i);
         int bIsGPKGScope = EQUAL(pszReferenceScope, "geopackage");
-        if( pszMetadata == NULL )
-            continue;
-        if( pszMDStandardURI != NULL && EQUAL(pszMDStandardURI, "http://gdal.org") &&
-            pszMimeType != NULL && EQUAL(pszMimeType, "text/xml") )
+        if( EQUAL(pszMDStandardURI, "http://gdal.org") &&
+            EQUAL(pszMimeType, "text/xml") )
         {
             CPLXMLNode* psXMLNode = CPLParseXMLString(pszMetadata);
             if( psXMLNode )
             {
                 GDALMultiDomainMetadata oLocalMDMD;
                 oLocalMDMD.XMLInit(psXMLNode, FALSE);
-                if( m_osRasterTable.size() && bIsGPKGScope )
+                if( !m_osRasterTable.empty() && bIsGPKGScope )
                 {
                     oMDMD.SetMetadata( oLocalMDMD.GetMetadata(), "GEOPACKAGE" );
                 }
@@ -2007,13 +2421,11 @@ char **GDALGeoPackageDataset::GetMetadata( const char *pszDomain )
         const char* pszMimeType = SQLResultGetValue(&oResult, 2, i);
         const char* pszReferenceScope = SQLResultGetValue(&oResult, 3, i);
         int bIsGPKGScope = EQUAL(pszReferenceScope, "geopackage");
-        if( pszMetadata == NULL )
-            continue;
-        if( pszMDStandardURI != NULL && EQUAL(pszMDStandardURI, "http://gdal.org") &&
-            pszMimeType != NULL && EQUAL(pszMimeType, "text/xml") )
+        if( EQUAL(pszMDStandardURI, "http://gdal.org") &&
+            EQUAL(pszMimeType, "text/xml") )
             continue;
 
-        if( m_osRasterTable.size() && bIsGPKGScope )
+        if( !m_osRasterTable.empty() && bIsGPKGScope )
         {
             oMDMD.SetMetadataItem( CPLSPrintf("GPKG_METADATA_ITEM_%d", nNonGDALMDIGeopackage),
                                    pszMetadata,
@@ -2058,6 +2470,7 @@ void GDALGeoPackageDataset::WriteMetadata(CPLXMLNode* psXMLNode, /* will be dest
         pszXML = CPLSerializeXMLTree(psMasterXMLNode);
         CPLDestroyXMLNode(psMasterXMLNode);
     }
+    // cppcheck-suppress uselessAssignmentPtrArg
     psXMLNode = NULL;
 
     char* pszSQL = NULL;
@@ -2153,18 +2566,15 @@ bool GDALGeoPackageDataset::CreateMetadataTables()
         CPLTestBool(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
 
     /* From C.10. gpkg_metadata Table 35. gpkg_metadata Table Definition SQL  */
-    const char* pszMetadata =
+    CPLString osSQL =
         "CREATE TABLE gpkg_metadata ("
         "id INTEGER CONSTRAINT m_pk PRIMARY KEY ASC NOT NULL UNIQUE,"
         "md_scope TEXT NOT NULL DEFAULT 'dataset',"
         "md_standard_uri TEXT NOT NULL,"
         "mime_type TEXT NOT NULL DEFAULT 'text/xml',"
-        "metadata TEXT NOT NULL"
+        "metadata TEXT NOT NULL DEFAULT ''"
         ")";
 
-    if ( OGRERR_NONE != SQLCommand(hDB, pszMetadata) )
-        return false;
-
     /* From D.2. metadata Table 40. metadata Trigger Definition SQL  */
     const char* pszMetadataTriggers =
     "CREATE TRIGGER 'gpkg_metadata_md_scope_insert' "
@@ -2197,11 +2607,14 @@ bool GDALGeoPackageDataset::CreateMetadataTables()
     "'catalogue','schema','taxonomy','software','service', "
     "'collectionHardware','nonGeographicDataset','dimensionGroup')); "
     "END";
-    if ( bCreateTriggers && OGRERR_NONE != SQLCommand(hDB, pszMetadataTriggers) )
-        return false;
+    if ( bCreateTriggers )
+    {
+        osSQL += ";";
+        osSQL += pszMetadataTriggers;
+    }
 
     /* From C.11. gpkg_metadata_reference Table 36. gpkg_metadata_reference Table Definition SQL */
-    const char* pszMetadataReference =
+    osSQL += ";"
         "CREATE TABLE gpkg_metadata_reference ("
         "reference_scope TEXT NOT NULL,"
         "table_name TEXT,"
@@ -2214,9 +2627,6 @@ bool GDALGeoPackageDataset::CreateMetadataTables()
         "CONSTRAINT crmr_mpi_fk FOREIGN KEY (md_parent_id) REFERENCES gpkg_metadata(id)"
         ")";
 
-    if ( OGRERR_NONE != SQLCommand(hDB, pszMetadataReference) )
-        return false;
-
     /* From D.3. metadata_reference Table 41. gpkg_metadata_reference Trigger Definition SQL   */
     const char* pszMetadataReferenceTriggers =
         "CREATE TRIGGER 'gpkg_metadata_reference_reference_scope_insert' "
@@ -2279,13 +2689,6 @@ bool GDALGeoPackageDataset::CreateMetadataTables()
         "is \"geopackage\", \"table\" or \"column\"') "
         "WHERE NEW.reference_scope IN ('geopackage','table','column') "
         "AND NEW.row_id_value IS NOT NULL; "
-        "SELECT RAISE(ABORT, 'insert on table gpkg_metadata_reference "
-        "violates constraint: row_id_value must exist in specified table when "
-        "reference_scope is \"row\" or \"row/col\"') "
-        "WHERE NEW.reference_scope IN ('row','row/col') "
-        "AND NOT EXISTS (SELECT rowid "
-        "FROM (SELECT NEW.table_name AS table_name) WHERE rowid = "
-        "NEW.row_id_value); "
         "END; "
         "CREATE TRIGGER 'gpkg_metadata_reference_row_id_value_update' "
         "BEFORE UPDATE OF 'row_id_value' ON 'gpkg_metadata_reference' "
@@ -2295,13 +2698,6 @@ bool GDALGeoPackageDataset::CreateMetadataTables()
         "is \"geopackage\", \"table\" or \"column\"') "
         "WHERE NEW.reference_scope IN ('geopackage','table','column') "
         "AND NEW.row_id_value IS NOT NULL; "
-        "SELECT RAISE(ABORT, 'update on table gpkg_metadata_reference "
-        "violates constraint: row_id_value must exist in specified table when "
-        "reference_scope is \"row\" or \"row/col\"') "
-        "WHERE NEW.reference_scope IN ('row','row/col') "
-        "AND NOT EXISTS (SELECT rowid "
-        "FROM (SELECT NEW.table_name AS table_name) WHERE rowid = "
-        "NEW.row_id_value); "
         "END; "
         "CREATE TRIGGER 'gpkg_metadata_reference_timestamp_insert' "
         "BEFORE INSERT ON 'gpkg_metadata_reference' "
@@ -2323,10 +2719,13 @@ bool GDALGeoPackageDataset::CreateMetadataTables()
         "'[1-2][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9].[0-9][0-9][0-9]Z' "
         "AND strftime('%s',NEW.timestamp) NOT NULL); "
         "END";
-    if ( bCreateTriggers && OGRERR_NONE != SQLCommand(hDB, pszMetadataReferenceTriggers) )
-        return false;
+    if ( bCreateTriggers )
+    {
+        osSQL += ";";
+        osSQL += pszMetadataReferenceTriggers;
+    }
 
-    return true;
+    return SQLCommand(hDB, osSQL) == OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -2342,7 +2741,7 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
         return CE_Failure;
     m_bMetadataDirty = false;
 
-    if( m_osRasterTable.size() )
+    if( !m_osRasterTable.empty() )
     {
         const char* pszIdentifier = GetMetadataItem("IDENTIFIER");
         const char* pszDescription = GetMetadataItem("DESCRIPTION");
@@ -2404,7 +2803,7 @@ CPLErr GDALGeoPackageDataset::FlushMetadata()
 
     WriteMetadata(psXMLNode, m_osRasterTable.c_str() );
 
-    if( m_osRasterTable.size() )
+    if( !m_osRasterTable.empty() )
     {
         char** papszGeopackageMD = GetMetadata("GEOPACKAGE");
 
@@ -2535,17 +2934,34 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
 
     if( nBandsIn != 0 )
     {
-        if( eDT != GDT_Byte )
+        if( eDT == GDT_Byte )
         {
-            CPLError(CE_Failure, CPLE_NotSupported, "Only Byte supported");
-            return FALSE;
+            if( nBandsIn != 1 && nBandsIn != 2 && nBandsIn != 3 && nBandsIn != 4 )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                        "Only 1 (Grey/ColorTable), 2 (Grey+Alpha), "
+                        "3 (RGB) or 4 (RGBA) band dataset supported for "
+                        "Byte datatype");
+                return FALSE;
+            }
+        }
+        else if( eDT == GDT_Int16 || eDT == GDT_UInt16 || eDT == GDT_Float32 )
+        {
+            if( nBandsIn != 1 )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                        "Only single band dataset supported for non Byte "
+                        "datatype");
+                return FALSE;
+            }
         }
-        if( nBandsIn != 1 && nBandsIn != 2 && nBandsIn != 3 && nBandsIn != 4 )
+        else
         {
             CPLError(CE_Failure, CPLE_NotSupported,
-                     "Only 1 (Grey/ColorTable), 2 (Grey+Alpha), 3 (RGB) or 4 (RGBA) band dataset supported");
+                     "Only Byte, Int16, UInt16 or Float32 supported");
             return FALSE;
         }
+
     }
 
     bool bFileExists = false;
@@ -2580,89 +2996,116 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
     if( !bFileExists &&
         CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) == NULL )
     {
-        sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, NULL );
+        SQLCommand( hDB, "PRAGMA synchronous = OFF" );
     }
 
     /* OGR UTF-8 support. If we set the UTF-8 Pragma early on, it */
     /* will be written into the main file and supported henceforth */
     SQLCommand(hDB, "PRAGMA encoding = \"UTF-8\"");
 
-    SoftStartTransaction();
+    if( nBandsIn > 0 && eDT != GDT_Byte )
+    {
+        m_nApplicationId = GPKG_APPLICATION_ID;
+        m_nUserVersion = GPKG_1_2_VERSION;
+    }
 
-    int bCreateTriggers = CPLTestBool(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
-    int bCreateGeometryColumns = CPLTestBool(CPLGetConfigOption("CREATE_GEOMETRY_COLUMNS", "YES"));
-    if( !bFileExists )
+    const char* pszVersion = CSLFetchNameValue(papszOptions, "VERSION");
+    if( pszVersion && !EQUAL(pszVersion, "AUTO") )
     {
-        /* Requirement 2: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) in the application id */
-        /* http://opengis.github.io/geopackage/#_file_format */
-        const char *pszPragma = CPLSPrintf("PRAGMA application_id = %d", GPKG_APPLICATION_ID);
+        if( EQUAL(pszVersion, "1.0") )
+        {
+            m_nApplicationId = GP10_APPLICATION_ID;
+            m_nUserVersion = 0;
+        }
+        else if( EQUAL(pszVersion, "1.1") )
+        {
+            m_nApplicationId = GP11_APPLICATION_ID;
+            m_nUserVersion = 0;
+        }
+        else if( EQUAL(pszVersion, "1.2") )
+        {
+            m_nApplicationId = GPKG_APPLICATION_ID;
+            m_nUserVersion = GPKG_1_2_VERSION;
+        }
+    }
 
-        if ( OGRERR_NONE != SQLCommand(hDB, pszPragma) )
-            return FALSE;
+    SoftStartTransaction();
 
+    CPLString osSQL;
+    if( !bFileExists )
+    {
         /* Requirement 10: A GeoPackage SHALL include a gpkg_spatial_ref_sys table */
         /* http://opengis.github.io/geopackage/#spatial_ref_sys */
-        const char *pszSpatialRefSys =
+        osSQL =
             "CREATE TABLE gpkg_spatial_ref_sys ("
             "srs_name TEXT NOT NULL,"
             "srs_id INTEGER NOT NULL PRIMARY KEY,"
             "organization TEXT NOT NULL,"
             "organization_coordsys_id INTEGER NOT NULL,"
             "definition  TEXT NOT NULL,"
-            "description TEXT"
-            ")";
-
-        if ( OGRERR_NONE != SQLCommand(hDB, pszSpatialRefSys) )
-            return FALSE;
-
+            "description TEXT";
+        if( CPLTestBool(CPLGetConfigOption("GPKG_ADD_DEFINITION_12_063", "NO")) )
+        {
+            m_bHasDefinition12_063 = true;
+            osSQL += ", definition_12_063 TEXT NOT NULL";
+        }
+        osSQL += 
+            ")"
+            ";"
         /* Requirement 11: The gpkg_spatial_ref_sys table in a GeoPackage SHALL */
         /* contain a record for EPSG:4326, the geodetic WGS84 SRS */
         /* http://opengis.github.io/geopackage/#spatial_ref_sys */
-        const char *pszSpatialRefSysRecord =
+
             "INSERT INTO gpkg_spatial_ref_sys ("
-            "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
+            "srs_name, srs_id, organization, organization_coordsys_id, definition, description";
+        if( m_bHasDefinition12_063 )
+            osSQL += ", definition_12_063";
+        osSQL +=
             ") VALUES ("
             "'WGS 84 geodetic', 4326, 'EPSG', 4326, '"
             "GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"
-            "', 'longitude/latitude coordinates in decimal degrees on the WGS 84 spheroid'"
-            ")";
-
-        if ( OGRERR_NONE != SQLCommand(hDB, pszSpatialRefSysRecord) )
-            return FALSE;
-
+            "', 'longitude/latitude coordinates in decimal degrees on the WGS 84 spheroid'";
+        if( m_bHasDefinition12_063 )
+            osSQL += ", 'GEODCRS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", ELLIPSOID[\"WGS 84\",6378137, 298.257223563, LENGTHUNIT[\"metre\", 1.0]]], PRIMEM[\"Greenwich\", 0.0, ANGLEUNIT[\"degree\",0.0174532925199433]], CS[ellipsoidal, 2], AXIS[\"latitude\", north, ORDER[1]], AXIS[\"longitude\", east, ORDER[2]], ANGLEUNIT[\"degree\", 0.0174532925199433], ID[\"EPSG\", 4326]]'";
+        osSQL +=
+            ")"
+            ";"
         /* Requirement 11: The gpkg_spatial_ref_sys table in a GeoPackage SHALL */
         /* contain a record with an srs_id of -1, an organization of “NONE”, */
         /* an organization_coordsys_id of -1, and definition “undefined” */
         /* for undefined Cartesian coordinate reference systems */
         /* http://opengis.github.io/geopackage/#spatial_ref_sys */
-        pszSpatialRefSysRecord =
             "INSERT INTO gpkg_spatial_ref_sys ("
-            "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
+            "srs_name, srs_id, organization, organization_coordsys_id, definition, description";
+        if( m_bHasDefinition12_063 )
+            osSQL += ", definition_12_063";
+        osSQL +=
             ") VALUES ("
-            "'Undefined cartesian SRS', -1, 'NONE', -1, 'undefined', 'undefined cartesian coordinate reference system'"
-            ")";
-
-        if ( OGRERR_NONE != SQLCommand(hDB, pszSpatialRefSysRecord) )
-            return FALSE;
-
+            "'Undefined cartesian SRS', -1, 'NONE', -1, 'undefined', 'undefined cartesian coordinate reference system'";
+        if( m_bHasDefinition12_063 )
+            osSQL += ", 'undefined'";
+        osSQL +=
+            ")"
+            ";"
         /* Requirement 11: The gpkg_spatial_ref_sys table in a GeoPackage SHALL */
         /* contain a record with an srs_id of 0, an organization of “NONE”, */
         /* an organization_coordsys_id of 0, and definition “undefined” */
         /* for undefined geographic coordinate reference systems */
         /* http://opengis.github.io/geopackage/#spatial_ref_sys */
-        pszSpatialRefSysRecord =
             "INSERT INTO gpkg_spatial_ref_sys ("
-            "srs_name, srs_id, organization, organization_coordsys_id, definition, description"
+            "srs_name, srs_id, organization, organization_coordsys_id, definition, description";
+        if( m_bHasDefinition12_063 )
+            osSQL += ", definition_12_063";
+        osSQL +=
             ") VALUES ("
-            "'Undefined geographic SRS', 0, 'NONE', 0, 'undefined', 'undefined geographic coordinate reference system'"
-            ")";
-
-        if ( OGRERR_NONE != SQLCommand(hDB, pszSpatialRefSysRecord) )
-            return FALSE;
-
+            "'Undefined geographic SRS', 0, 'NONE', 0, 'undefined', 'undefined geographic coordinate reference system'";
+        if( m_bHasDefinition12_063 )
+            osSQL += ", 'undefined'";
+        osSQL +=
+            ")"
+            ";"
         /* Requirement 13: A GeoPackage file SHALL include a gpkg_contents table */
         /* http://opengis.github.io/geopackage/#_contents */
-        const char *pszContents =
             "CREATE TABLE gpkg_contents ("
             "table_name TEXT NOT NULL PRIMARY KEY,"
             "data_type TEXT NOT NULL,"
@@ -2673,33 +3116,48 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             "max_x DOUBLE, max_y DOUBLE,"
             "srs_id INTEGER,"
             "CONSTRAINT fk_gc_r_srs_id FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys(srs_id)"
-            ")";
+            ")"
+            ;
 
-        if ( OGRERR_NONE != SQLCommand(hDB, pszContents) )
-            return FALSE;
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+        if( CPLFetchBool(papszOptions, "ADD_GPKG_OGR_CONTENTS", true) )
+        {
+            m_bHasGPKGOGRContents = true;
+            osSQL += 
+                ";"
+                "CREATE TABLE gpkg_ogr_contents("
+                "table_name TEXT NOT NULL PRIMARY KEY,"
+                "feature_count INTEGER DEFAULT NULL"
+                ")";
+        }
+#endif
 
         /* Requirement 21: A GeoPackage with a gpkg_contents table row with a “features” */
         /* data_type SHALL contain a gpkg_geometry_columns table or updateable view */
         /* http://opengis.github.io/geopackage/#_geometry_columns */
-        const char *pszGeometryColumns =
-            "CREATE TABLE gpkg_geometry_columns ("
-            "table_name TEXT NOT NULL,"
-            "column_name TEXT NOT NULL,"
-            "geometry_type_name TEXT NOT NULL,"
-            "srs_id INTEGER NOT NULL,"
-            "z TINYINT NOT NULL,"
-            "m TINYINT NOT NULL,"
-            "CONSTRAINT pk_geom_cols PRIMARY KEY (table_name, column_name),"
-            "CONSTRAINT uk_gc_table_name UNIQUE (table_name),"
-            "CONSTRAINT fk_gc_tn FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name),"
-            "CONSTRAINT fk_gc_srs FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys (srs_id)"
-            ")";
+        const bool bCreateGeometryColumns =
+            CPLTestBool(CPLGetConfigOption("CREATE_GEOMETRY_COLUMNS", "YES"));
+        if( bCreateGeometryColumns )
+        {
+            m_bHasGPKGGeometryColumns = true;
+            osSQL += ";";
+            osSQL += pszCREATE_GPKG_GEOMETRY_COLUMNS;
+        }
+    }
 
-        if ( bCreateGeometryColumns && OGRERR_NONE != SQLCommand(hDB, pszGeometryColumns) )
-            return FALSE;
+    const bool bCreateTriggers =
+        CPLTestBool(CPLGetConfigOption("CREATE_TRIGGERS", "YES"));
+    if( (bFileExists && nBandsIn != 0 && SQLGetInteger(hDB,
+            "SELECT 1 FROM sqlite_master WHERE name = 'gpkg_tile_matrix_set' "
+            "AND type in ('table', 'view')", NULL) == 0 ) ||
+        (!bFileExists &&
+         CPLTestBool(CPLGetConfigOption("CREATE_RASTER_TABLES", "YES"))) )
+    {
+        if( !osSQL.empty() )
+            osSQL += ";";
 
         /* From C.5. gpkg_tile_matrix_set Table 28. gpkg_tile_matrix_set Table Creation SQL  */
-        const char *pszTileMatrixSet =
+        osSQL +=
             "CREATE TABLE gpkg_tile_matrix_set ("
             "table_name TEXT NOT NULL PRIMARY KEY,"
             "srs_id INTEGER NOT NULL,"
@@ -2709,13 +3167,10 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             "max_y DOUBLE NOT NULL,"
             "CONSTRAINT fk_gtms_table_name FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name),"
             "CONSTRAINT fk_gtms_srs FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys (srs_id)"
-            ")";
-
-        if ( OGRERR_NONE != SQLCommand(hDB, pszTileMatrixSet) )
-            return FALSE;
+            ")"
+            ";"
 
         /* From C.6. gpkg_tile_matrix Table 29. gpkg_tile_matrix Table Creation SQL */
-        const char *pszTileMatrix =
             "CREATE TABLE gpkg_tile_matrix ("
             "table_name TEXT NOT NULL,"
             "zoom_level INTEGER NOT NULL,"
@@ -2729,9 +3184,8 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             "CONSTRAINT fk_tmm_table_name FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name)"
             ")";
 
-        if ( OGRERR_NONE != SQLCommand(hDB, pszTileMatrix) )
-            return FALSE;
-
+        if( bCreateTriggers )
+        {
         /* From D.1. gpkg_tile_matrix Table 39. gpkg_tile_matrix Trigger Definition SQL */
         const char* pszTileMatrixTrigger =
         "CREATE TRIGGER 'gpkg_tile_matrix_zoom_level_insert' "
@@ -2794,9 +3248,16 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         "SELECT RAISE(ABORT, 'update on table ''gpkg_tile_matrix'' violates constraint: pixel_y_size must be greater than 0') "
         "WHERE NOT (NEW.pixel_y_size > 0); "
         "END;";
-        if ( bCreateTriggers && OGRERR_NONE != SQLCommand(hDB, pszTileMatrixTrigger) )
-            return FALSE;
+            osSQL += ";";
+            osSQL += pszTileMatrixTrigger;
+        }
+    }
 
+    if ( !osSQL.empty() && OGRERR_NONE != SQLCommand(hDB, osSQL) )
+        return FALSE;
+
+    if( !bFileExists )
+    {
         if( CPLTestBool(CPLGetConfigOption("CREATE_METADATA_TABLES", "YES")) &&
             !CreateMetadataTables() )
             return FALSE;
@@ -2806,13 +3267,22 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
     {
         const char* pszTableName = CPLGetBasename(m_pszFilename);
         m_osRasterTable = CSLFetchNameValueDef(papszOptions, "RASTER_TABLE", pszTableName);
+        if( m_osRasterTable.empty() )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "RASTER_TABLE must be set to a non empty value");
+            return FALSE;
+        }
         m_bIdentifierAsCO = CSLFetchNameValue(papszOptions, "RASTER_IDENTIFIER" ) != NULL;
         m_osIdentifier = CSLFetchNameValueDef(papszOptions, "RASTER_IDENTIFIER", m_osRasterTable);
         m_bDescriptionAsCO = CSLFetchNameValue(papszOptions, "RASTER_DESCRIPTION" ) != NULL;
         m_osDescription = CSLFetchNameValueDef(papszOptions, "RASTER_DESCRIPTION", "");
+        SetDataType(eDT);
+        if( eDT == GDT_Int16 )
+            SetGlobalOffsetScale(-32768.0, 1.0);
 
         /* From C.7. sample_tile_pyramid (Informative) Table 31. EXAMPLE: tiles table Create Table SQL (Informative) */
-        char* pszSQL = sqlite3_mprintf("CREATE TABLE '%q' ("
+        char* pszSQL = sqlite3_mprintf("CREATE TABLE \"%w\" ("
           "id INTEGER PRIMARY KEY AUTOINCREMENT,"
           "zoom_level INTEGER NOT NULL,"
           "tile_column INTEGER NOT NULL,"
@@ -2820,50 +3290,50 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
           "tile_data BLOB NOT NULL,"
           "UNIQUE (zoom_level, tile_column, tile_row)"
         ")", m_osRasterTable.c_str());
-        OGRErr eErr = SQLCommand(hDB, pszSQL);
-        sqlite3_free(pszSQL);
-        if ( OGRERR_NONE != eErr )
-            return FALSE;
+        osSQL = pszSQL;
+        sqlite3_free(pszSQL);
 
+        if( bCreateTriggers )
+        {
         /* From D.5. sample_tile_pyramid Table 43. tiles table Trigger Definition SQL  */
-        char* pszSQLTriggers = sqlite3_mprintf("CREATE TRIGGER '%q_zoom_insert' "
-        "BEFORE INSERT ON '%q' "
+        pszSQL = sqlite3_mprintf("CREATE TRIGGER \"%w_zoom_insert\" "
+        "BEFORE INSERT ON \"%w\" "
         "FOR EACH ROW BEGIN "
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: zoom_level not specified for table in gpkg_tile_matrix') "
         "WHERE NOT (NEW.zoom_level IN (SELECT zoom_level FROM gpkg_tile_matrix WHERE table_name = '%q')) ; "
         "END; "
-        "CREATE TRIGGER '%q_zoom_update' "
-        "BEFORE UPDATE OF zoom_level ON '%q' "
+        "CREATE TRIGGER \"%w_zoom_update\" "
+        "BEFORE UPDATE OF zoom_level ON \"%w\" "
         "FOR EACH ROW BEGIN "
         "SELECT RAISE(ABORT, 'update on table ''%q'' violates constraint: zoom_level not specified for table in gpkg_tile_matrix') "
         "WHERE NOT (NEW.zoom_level IN (SELECT zoom_level FROM gpkg_tile_matrix WHERE table_name = '%q')) ; "
         "END; "
-        "CREATE TRIGGER '%q_tile_column_insert' "
-        "BEFORE INSERT ON '%q' "
+        "CREATE TRIGGER \"%w_tile_column_insert\" "
+        "BEFORE INSERT ON \"%w\" "
         "FOR EACH ROW BEGIN "
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: tile_column cannot be < 0') "
         "WHERE (NEW.tile_column < 0) ; "
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: tile_column must by < matrix_width specified for table and zoom level in gpkg_tile_matrix') "
         "WHERE NOT (NEW.tile_column < (SELECT matrix_width FROM gpkg_tile_matrix WHERE table_name = '%q' AND zoom_level = NEW.zoom_level)); "
         "END; "
-        "CREATE TRIGGER '%q_tile_column_update' "
-        "BEFORE UPDATE OF tile_column ON '%q' "
+        "CREATE TRIGGER \"%w_tile_column_update\" "
+        "BEFORE UPDATE OF tile_column ON \"%w\" "
         "FOR EACH ROW BEGIN "
         "SELECT RAISE(ABORT, 'update on table ''%q'' violates constraint: tile_column cannot be < 0') "
         "WHERE (NEW.tile_column < 0) ; "
         "SELECT RAISE(ABORT, 'update on table ''%q'' violates constraint: tile_column must by < matrix_width specified for table and zoom level in gpkg_tile_matrix') "
         "WHERE NOT (NEW.tile_column < (SELECT matrix_width FROM gpkg_tile_matrix WHERE table_name = '%q' AND zoom_level = NEW.zoom_level)); "
         "END; "
-        "CREATE TRIGGER '%q_tile_row_insert' "
-        "BEFORE INSERT ON '%q' "
+        "CREATE TRIGGER \"%w_tile_row_insert\" "
+        "BEFORE INSERT ON \"%w\" "
         "FOR EACH ROW BEGIN "
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: tile_row cannot be < 0') "
         "WHERE (NEW.tile_row < 0) ; "
         "SELECT RAISE(ABORT, 'insert on table ''%q'' violates constraint: tile_row must by < matrix_height specified for table and zoom level in gpkg_tile_matrix') "
         "WHERE NOT (NEW.tile_row < (SELECT matrix_height FROM gpkg_tile_matrix WHERE table_name = '%q' AND zoom_level = NEW.zoom_level)); "
         "END; "
-        "CREATE TRIGGER '%q_tile_row_update' "
-        "BEFORE UPDATE OF tile_row ON '%q' "
+        "CREATE TRIGGER \"%w_tile_row_update\" "
+        "BEFORE UPDATE OF tile_row ON \"%w\" "
         "FOR EACH ROW BEGIN "
         "SELECT RAISE(ABORT, 'update on table ''%q'' violates constraint: tile_row cannot be < 0') "
         "WHERE (NEW.tile_row < 0) ; "
@@ -2899,11 +3369,54 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         m_osRasterTable.c_str(),
         m_osRasterTable.c_str()
         );
-        if( bCreateTriggers )
+
+            osSQL += ";";
+            osSQL += pszSQL;
+            sqlite3_free(pszSQL);
+        }
+
+        OGRErr eErr = SQLCommand(hDB, osSQL);
+        if ( OGRERR_NONE != eErr )
+            return FALSE;
+
+        const char* pszTF = CSLFetchNameValue(papszOptions, "TILE_FORMAT");
+        if( eDT == GDT_Int16 || eDT == GDT_UInt16 )
+        {
+            m_eTF = GPKG_TF_PNG_16BIT;
+            if( pszTF )
+            {
+                if( !EQUAL(pszTF, "AUTO") && !EQUAL(pszTF, "PNG") )
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                             "Only AUTO or PNG supported "
+                             "as tile format for Int16 / UInt16");
+                }
+            }
+        }
+        else if( eDT == GDT_Float32 )
+        {
+            m_eTF = GPKG_TF_TIFF_32BIT_FLOAT;
+            if( pszTF )
+            {
+                if( EQUAL(pszTF, "PNG") )
+                    m_eTF = GPKG_TF_PNG_16BIT;
+                else if( !EQUAL(pszTF, "AUTO") && !EQUAL(pszTF, "TIFF") )
+                {
+                    CPLError(CE_Warning, CPLE_NotSupported,
+                             "Only AUTO, PNG or TIFF supported "
+                             "as tile format for Float32");
+                }
+            }
+        }
+        else
+        {
+            if( pszTF )
+                m_eTF = GDALGPKGMBTilesGetTileFormat(pszTF);
+        }
+
+        if( eDT != GDT_Byte )
         {
-            eErr = SQLCommand(hDB, pszSQLTriggers);
-            sqlite3_free(pszSQLTriggers);
-            if ( OGRERR_NONE != eErr )
+            if( !CreateTileGriddedTable(papszOptions) )
                 return FALSE;
         }
 
@@ -2923,7 +3436,8 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
             return FALSE;
         }
 
-        m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4, nTileWidth, nTileHeight);
+        m_pabyCachedTiles = (GByte*) VSI_MALLOC3_VERBOSE(4 * 4 * m_nDTSize,
+                                                         nTileWidth, nTileHeight);
         if( m_pabyCachedTiles == NULL )
         {
             return FALSE;
@@ -2934,13 +3448,9 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
 
         GDALPamDataset::SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
         GDALPamDataset::SetMetadataItem("IDENTIFIER", m_osIdentifier);
-        if( m_osDescription.size() )
+        if( !m_osDescription.empty() )
             GDALPamDataset::SetMetadataItem("DESCRIPTION", m_osDescription);
 
-        const char* pszTF = CSLFetchNameValue(papszOptions, "TILE_FORMAT");
-        if( pszTF )
-            m_eTF = GDALGPKGMBTilesGetTileFormat(pszTF);
-
         ParseCompressionOptions(papszOptions);
 
         if( m_eTF == GPKG_TF_WEBP )
@@ -2990,25 +3500,226 @@ int GDALGeoPackageDataset::Create( const char * pszFilename,
         }
     }
 
+    if( bFileExists && nBandsIn > 0 && eDT == GDT_Byte )
+    {
+        // If there was an ogr_empty_table table, we can remove it
+        RemoveOGREmptyTable();
+    }
+
     SoftCommitTransaction();
 
-    /* Requirement 2: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) */
-    /* in the application id field of the SQLite database header */
+    /* Requirement 2 */
     /* We have to do this after there's some content so the database file */
     /* is not zero length */
-    SetApplicationId();
+    SetApplicationAndUserVersionId();
 
     /* Default to synchronous=off for performance for new file */
     if( !bFileExists &&
         CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL) == NULL )
     {
-        sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, NULL );
+        SQLCommand( hDB, "PRAGMA synchronous = OFF" );
     }
 
+    m_bTableCreated = true;
+
     return TRUE;
 }
 
 /************************************************************************/
+/*                     CreateOGREmptyTableIfNeeded()                    */
+/************************************************************************/
+
+void GDALGeoPackageDataset::CreateOGREmptyTableIfNeeded()
+{
+    // The specification makes it compulsory (Req 17) to have at least a
+    // features or tiles table, so create a dummy one.
+    if( m_bTableCreated &&
+        !SQLGetInteger(hDB,
+        "SELECT 1 FROM gpkg_contents WHERE data_type IN "
+        "('features', 'tiles')", NULL) &&
+        CPLTestBool(CPLGetConfigOption("OGR_GPKG_CREATE_EMPTY_TABLE", "YES")) )
+    {
+        CPLDebug("GPKG", "Creating a dummy ogr_empty_table features table, "
+                "since there is no features or tiles table.");
+        const char* const apszLayerOptions[] = {
+            "SPATIAL_INDEX=NO",
+            "DESCRIPTION=Technical table needed to be conformant with "
+                        "Requirement 17 of the GeoPackage specification",
+            NULL };
+        CreateLayer("ogr_empty_table", NULL, wkbUnknown,
+                    const_cast<char**>(apszLayerOptions));
+        // Effectively create the table
+        FlushCache();
+    }
+}
+
+/************************************************************************/
+/*                        RemoveOGREmptyTable()                         */
+/************************************************************************/
+
+void GDALGeoPackageDataset::RemoveOGREmptyTable()
+{
+    // Run with sqlite3_exec since we don't want errors to be emitted
+    sqlite3_exec( hDB,
+        "DROP TABLE IF EXISTS ogr_empty_table", NULL, NULL, NULL );
+    sqlite3_exec( hDB,
+        "DELETE FROM gpkg_contents WHERE table_name = 'ogr_empty_table'",
+        NULL, NULL, NULL );
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( m_bHasGPKGOGRContents )
+    {
+        sqlite3_exec( hDB,
+            "DELETE FROM gpkg_ogr_contents WHERE "
+            "table_name = 'ogr_empty_table'",
+            NULL, NULL, NULL );
+    }
+#endif
+    sqlite3_exec( hDB,
+        "DELETE FROM gpkg_geometry_columns WHERE "
+        "table_name = 'ogr_empty_table'",
+        NULL, NULL, NULL );
+}
+
+/************************************************************************/
+/*                        CreateTileGriddedTable()                      */
+/************************************************************************/
+
+bool GDALGeoPackageDataset::CreateTileGriddedTable(char** papszOptions)
+{
+    // Check if gpkg_2d_gridded_coverage_ancillary has been created
+    SQLResult oResultTable;
+    OGRErr eErr = SQLQuery(hDB,
+        "SELECT * FROM sqlite_master WHERE type IN ('table', 'view') AND "
+        "name = 'gpkg_2d_gridded_coverage_ancillary'"
+        , &oResultTable);
+    bool bHasTable = ( eErr == OGRERR_NONE && oResultTable.nRowCount == 1 );
+    SQLResultFree(&oResultTable);
+
+    CPLString osSQL;
+    if( !bHasTable )
+    {
+        // It doesn't exist. So create gpkg_extensions table if necessary, and
+        // gpkg_2d_gridded_coverage_ancillary & gpkg_2d_gridded_tile_ancillary,
+        // and register them as extensions.
+        if( CreateExtensionsTableIfNecessary() != OGRERR_NONE )
+            return false;
+
+        // Requirement 105
+        osSQL =
+            "CREATE TABLE gpkg_2d_gridded_coverage_ancillary ("
+            "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+            "tile_matrix_set_name TEXT NOT NULL UNIQUE,"
+            "datatype TEXT NOT NULL DEFAULT 'integer',"
+            "scale REAL NOT NULL DEFAULT 1.0,"
+            "offset REAL NOT NULL DEFAULT 0.0,"
+            "precision REAL DEFAULT 1.0,"
+            "data_null REAL,"
+            "CONSTRAINT fk_g2dgtct_name FOREIGN KEY('tile_matrix_set_name') "
+            "REFERENCES gpkg_tile_matrix_set ( table_name )"
+            "CHECK (datatype in ('integer','float')))"
+            ";"
+        // Requirement 106
+            "CREATE TABLE gpkg_2d_gridded_tile_ancillary ("
+            "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+            "tpudt_name TEXT NOT NULL,"
+            "tpudt_id INTEGER NOT NULL,"
+            "scale REAL NOT NULL DEFAULT 1.0,"
+            "offset REAL NOT NULL DEFAULT 0.0,"
+            "min REAL DEFAULT NULL,"
+            "max REAL DEFAULT NULL,"
+            "mean REAL DEFAULT NULL,"
+            "std_dev REAL DEFAULT NULL,"
+            "CONSTRAINT fk_g2dgtat_name FOREIGN KEY (tpudt_name) "
+            "REFERENCES gpkg_contents(table_name),"
+            "UNIQUE (tpudt_name, tpudt_id))"
+            ";"
+        // Requirement 110
+            "INSERT INTO gpkg_extensions "
+            "(table_name, column_name, extension_name, definition, scope) "
+            "VALUES ('gpkg_2d_gridded_coverage_ancillary', NULL, "
+            "'gpkg_elevation_tiles', "
+            "'http://www.geopackage.org/spec/#extension_tiled_gridded_elevation_data', "
+            "'read-write')"
+            ";"
+        // Requirement 110
+            "INSERT INTO gpkg_extensions "
+            "(table_name, column_name, extension_name, definition, scope) "
+            "VALUES ('gpkg_2d_gridded_tile_ancillary', NULL, "
+            "'gpkg_elevation_tiles', "
+            "'http://www.geopackage.org/spec/#extension_tiled_gridded_elevation_data', "
+            "'read-write')"
+            ";";
+    }
+
+    // Requirement 110
+    char* pszSQL = sqlite3_mprintf(
+        "INSERT INTO gpkg_extensions "
+        "(table_name, column_name, extension_name, definition, scope) "
+        "VALUES ('%q', 'tile_data', "
+        "'gpkg_elevation_tiles', "
+        "'http://www.geopackage.org/spec/#extension_tiled_gridded_elevation_data', "
+        "'read-write')", m_osRasterTable.c_str());
+    osSQL += pszSQL;
+    osSQL += ";";
+    sqlite3_free(pszSQL);
+
+    // Requirement 111 and 112
+    m_dfPrecision = CPLAtof(CSLFetchNameValueDef(papszOptions,
+                                                      "PRECISION", "1"));
+
+    pszSQL = sqlite3_mprintf(
+        "INSERT INTO gpkg_2d_gridded_coverage_ancillary "
+        "(tile_matrix_set_name, datatype, scale, offset, precision) "
+        "VALUES ('%q', '%s', %.18g, %.18g, %.18g)",
+        m_osRasterTable.c_str(),
+        ( m_eTF == GPKG_TF_PNG_16BIT ) ? "integer" : "float",
+        m_dfScale, m_dfOffset, m_dfPrecision);
+    osSQL += pszSQL;
+    sqlite3_free(pszSQL);
+
+    // Requirement 108
+    eErr = SQLQuery(hDB,
+        "SELECT * FROM gpkg_spatial_ref_sys WHERE srs_id = 4979 LIMIT 2"
+        , &oResultTable);
+    bool bHasEPSG4979 = ( eErr == OGRERR_NONE && oResultTable.nRowCount == 1 );
+    SQLResultFree(&oResultTable);
+    if( !bHasEPSG4979 )
+    {
+        // This is WKT 2...
+        const char* pszWKT = "GEODCRS[\"WGS 84\","
+  "DATUM[\"World Geodetic System 1984\","
+  "  ELLIPSOID[\"WGS 84\",6378137,298.257223563,LENGTHUNIT[\"metre\",1.0]]],"
+  "CS[ellipsoidal,3],"
+  "  AXIS[\"latitude\",north,ORDER[1],ANGLEUNIT[\"degree\",0.01745329252]],"
+  "  AXIS[\"longitude\",east,ORDER[2],ANGLEUNIT[\"degree\",0.01745329252]],"
+  "  AXIS[\"ellipsoidal height\",up,ORDER[3],LENGTHUNIT[\"metre\",1.0]],"
+  "ID[\"EPSG\",4979]]";
+        if( !m_bHasDefinition12_063 )
+        {
+            pszSQL = sqlite3_mprintf(
+                "INSERT INTO gpkg_spatial_ref_sys "
+                "(srs_name,srs_id,organization,organization_coordsys_id,"
+                "definition) VALUES ('WGS 84 3D', 4979, 'EPSG', 4979, '%q')",
+                pszWKT);
+        }
+        else
+        {
+            pszSQL = sqlite3_mprintf(
+                "INSERT INTO gpkg_spatial_ref_sys "
+                "(srs_name,srs_id,organization,organization_coordsys_id,"
+                "definition,definition_12_063) VALUES "
+                "('WGS 84 3D', 4979, 'EPSG', 4979, 'undefined', '%q')",
+                pszWKT);
+        }
+        osSQL += ";";
+        osSQL += pszSQL;
+        sqlite3_free(pszSQL);
+    }
+
+    return SQLCommand(hDB, osSQL) == OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                            CreateCopy()                              */
 /************************************************************************/
 
@@ -3043,27 +3754,27 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
     if( CPLTestBool(CSLFetchNameValueDef(papszOptions, "APPEND_SUBDATASET", "NO")) &&
         CSLFetchNameValue(papszOptions, "RASTER_TABLE") == NULL )
     {
+        CPLString osBasename(CPLGetBasename(poSrcDS->GetDescription()));
         papszUpdatedOptions = CSLSetNameValue(papszUpdatedOptions,
-                                              "RASTER_TABLE",
-                                              CPLGetBasename(poSrcDS->GetDescription()));
+                                              "RASTER_TABLE", osBasename);
     }
 
     if( EQUAL(pszTilingScheme, "CUSTOM") )
     {
-        GDALDriver* poThisDriver = (GDALDriver*)GDALGetDriverByName("GPKG");
-        if( !poThisDriver )
+        GDALDataset* poDS = NULL;
+        GDALDriver* poThisDriver = reinterpret_cast<GDALDriver*>(
+                                                GDALGetDriverByName("GPKG"));
+        if( poThisDriver != NULL )
         {
-            CSLDestroy(papszUpdatedOptions);
-            return NULL;
+            poDS = poThisDriver->DefaultCreateCopy(
+                pszFilename, poSrcDS, bStrict,
+                papszUpdatedOptions, pfnProgress, pProgressData );
         }
-        GDALDataset* poDS = poThisDriver->DefaultCreateCopy(
-                                    pszFilename, poSrcDS, bStrict,
-                                    papszUpdatedOptions, pfnProgress, pProgressData );
         CSLDestroy(papszUpdatedOptions);
         return poDS;
     }
 
-    int nBands = poSrcDS->GetRasterCount();
+    const int nBands = poSrcDS->GetRasterCount();
     if( nBands != 1 && nBands != 2 && nBands != 3 && nBands != 4 )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -3146,14 +3857,15 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
                 oSrcSRS.IsGeographic() )
             {
                 const double minLat =
-                    MIN( adfSrcGeoTransform[3],
-                         adfSrcGeoTransform[3] +
-                         poSrcDS->GetRasterYSize() *
-                         adfSrcGeoTransform[5] );
+                    std::min(adfSrcGeoTransform[3],
+                             adfSrcGeoTransform[3] +
+                             poSrcDS->GetRasterYSize() *
+                             adfSrcGeoTransform[5]);
                 const double maxLat =
-                    MAX( adfSrcGeoTransform[3],
-                         adfSrcGeoTransform[3] +
-                         poSrcDS->GetRasterYSize() * adfSrcGeoTransform[5] );
+                    std::max(adfSrcGeoTransform[3],
+                             adfSrcGeoTransform[3] +
+                             poSrcDS->GetRasterYSize() *
+                             adfSrcGeoTransform[5]);
                 double maxNorthing = adfGeoTransform[3];
                 double minNorthing =
                     adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
@@ -3236,11 +3948,13 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
     adfGeoTransform[1] = dfRes;
     adfGeoTransform[5] = -dfRes;
 
+    const GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     int nTargetBands = nBands;
     /* For grey level or RGB, if there's reprojection involved, add an alpha */
     /* channel */
-    if( (nBands == 1 && poSrcDS->GetRasterBand(1)->GetColorTable() == NULL) ||
-        nBands == 3 )
+    if( eDT == GDT_Byte &&
+        ((nBands == 1 && poSrcDS->GetRasterBand(1)->GetColorTable() == NULL) ||
+        nBands == 3) )
     {
         OGRSpatialReference oSrcSRS;
         oSrcSRS.SetFromUserInput(poSrcDS->GetProjectionRef());
@@ -3277,7 +3991,7 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
     }
 
     GDALGeoPackageDataset* poDS = new GDALGeoPackageDataset();
-    if( !(poDS->Create( pszFilename, nXSize, nYSize, nTargetBands, GDT_Byte,
+    if( !(poDS->Create( pszFilename, nXSize, nYSize, nTargetBands, eDT,
                         papszUpdatedOptions )) )
     {
         delete poDS;
@@ -3297,6 +4011,14 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
         poDS->GetRasterBand(1)->SetColorTable( poSrcDS->GetRasterBand(1)->GetColorTable() );
     }
 
+    int bHasNoData = FALSE;
+    double dfNoDataValue =
+            poSrcDS->GetRasterBand(1)->GetNoDataValue(&bHasNoData);
+    if( eDT != GDT_Byte && bHasNoData )
+    {
+        poDS->GetRasterBand(1)->SetNoDataValue(dfNoDataValue);
+    }
+
     hTransformArg =
         GDALCreateGenImgProjTransformer2( poSrcDS, poDS, papszTO );
     CSLDestroy(papszTO);
@@ -3320,7 +4042,23 @@ GDALDataset* GDALGeoPackageDataset::CreateCopy( const char *pszFilename,
     GDALWarpOptions *psWO = GDALCreateWarpOptions();
 
     psWO->papszWarpOptions = CSLSetNameValue(NULL, "OPTIMIZE_SIZE", "YES");
-    psWO->eWorkingDataType = GDT_Byte;
+    if( bHasNoData )
+    {
+        psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
+                                                 "INIT_DEST", "NO_DATA");
+        psWO->padfSrcNoDataReal =
+            static_cast<double*>(CPLMalloc(sizeof(double)));
+        psWO->padfSrcNoDataReal[0] = dfNoDataValue;
+        psWO->padfSrcNoDataImag = static_cast<double*>(
+                CPLCalloc(1, sizeof(double)));
+
+        psWO->padfDstNoDataReal =
+            static_cast<double*>(CPLMalloc(sizeof(double)));
+        psWO->padfDstNoDataReal[0] = dfNoDataValue;
+        psWO->padfDstNoDataImag = static_cast<double*>(
+                CPLCalloc(1, sizeof(double)));
+    }
+    psWO->eWorkingDataType = eDT;
     psWO->eResampleAlg = eResampleAlg;
 
     psWO->hSrcDS = poSrcDS;
@@ -3409,7 +4147,8 @@ void GDALGeoPackageDataset::ParseCompressionOptions(char** papszOptions)
 
 bool GDALGeoPackageDataset::RegisterWebPExtension()
 {
-    CreateExtensionsTableIfNecessary();
+    if( CreateExtensionsTableIfNecessary() != OGRERR_NONE )
+        return false;
 
     char* pszSQL = sqlite3_mprintf(
         "INSERT INTO gpkg_extensions "
@@ -3429,13 +4168,14 @@ bool GDALGeoPackageDataset::RegisterWebPExtension()
 
 bool GDALGeoPackageDataset::RegisterZoomOtherExtension()
 {
-    CreateExtensionsTableIfNecessary();
+    if( CreateExtensionsTableIfNecessary() != OGRERR_NONE )
+        return false;
 
     char* pszSQL = sqlite3_mprintf(
         "INSERT INTO gpkg_extensions "
-        "(table_name, extension_name, definition, scope) "
+        "(table_name, column_name, extension_name, definition, scope) "
         "VALUES "
-        "('%q', 'gpkg_zoom_other', 'GeoPackage 1.0 Specification Annex O', 'read-write')",
+        "('%q', 'tile_data', 'gpkg_zoom_other', 'GeoPackage 1.0 Specification Annex O', 'read-write')",
         m_osRasterTable.c_str());
     const OGRErr eErr = SQLCommand(hDB, pszSQL);
     sqlite3_free(pszSQL);
@@ -3481,6 +4221,15 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
 
+    if( !m_bHasGPKGGeometryColumns )
+    {
+        if( SQLCommand( hDB, pszCREATE_GPKG_GEOMETRY_COLUMNS ) != OGRERR_NONE )
+        {
+            return NULL;
+        }
+        m_bHasGPKGGeometryColumns = true;
+    }
+
     // Check identifier unicity
     const char* pszIdentifier = CSLFetchNameValue(papszOptions, "IDENTIFIER");
     if( pszIdentifier != NULL && pszIdentifier[0] == '\0' )
@@ -3507,7 +4256,8 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
         // In case there would be table in gpkg_contents not listed as a
         // vector layer
         char* pszSQL = sqlite3_mprintf(
-            "SELECT table_name FROM gpkg_contents WHERE identifier = '%q'",
+            "SELECT table_name FROM gpkg_contents WHERE identifier = '%q' "
+            "LIMIT 2",
             pszIdentifier);
         SQLResult oResult;
         OGRErr eErr = SQLQuery (hDB, pszSQL, &oResult);
@@ -3532,7 +4282,7 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
     if (pszGeomColumnName == NULL)
         pszGeomColumnName = "geom";
     const bool bGeomNullable =
-        CPLFetchBool((const char**)papszOptions, "GEOMETRY_NULLABLE", true);
+        CPLFetchBool(papszOptions, "GEOMETRY_NULLABLE", true);
 
     /* Read FID option */
     const char* pszFIDColumnName = CSLFetchNameValue(papszOptions, "FID");
@@ -3604,15 +4354,39 @@ OGRLayer* GDALGeoPackageDataset::ICreateLayer( const char * pszLayerName,
         poLayer->SetDeferredSpatialIndexCreation(true);
     }
 
-    poLayer->SetPrecisionFlag( CPLFetchBool((const char**)papszOptions, "PRECISION", true) );
+    poLayer->SetPrecisionFlag( CPLFetchBool(papszOptions, "PRECISION", true) );
     poLayer->SetTruncateFieldsFlag(
-        CPLFetchBool((const char**)papszOptions, "TRUNCATE_FIELDS", false));
+        CPLFetchBool(papszOptions, "TRUNCATE_FIELDS", false));
     if( eGType == wkbNone )
     {
-        poLayer->SetRegisterAsAspatial( CPLFetchBool(
-            (const char**)papszOptions,"REGISTER_AS_ASPATIAL",true) );
+        const char* pszASpatialVariant = CSLFetchNameValueDef(papszOptions,
+                                                            "ASPATIAL_VARIANT",
+                                                            "GPKG_ATTRIBUTES");
+        GPKGASpatialVariant eASPatialVariant = GPKG_ATTRIBUTES;
+        if( EQUAL(pszASpatialVariant, "GPKG_ATTRIBUTES") )
+            eASPatialVariant = GPKG_ATTRIBUTES;
+        else if( EQUAL(pszASpatialVariant, "OGR_ASPATIAL") )
+            eASPatialVariant = OGR_ASPATIAL;
+        else if( EQUAL(pszASpatialVariant, "NOT_REGISTERED") )
+            eASPatialVariant = NOT_REGISTERED;
+        else
+        {
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "Unsupported value for ASPATIAL_VARIANT: %s",
+                     pszASpatialVariant);
+        }
+        poLayer->SetASpatialVariant( eASPatialVariant );
+    }
+
+    // If there was an ogr_empty_table table, we can remove it
+    if( strcmp(pszLayerName, "ogr_empty_table") != 0 &&
+        eGType != wkbNone )
+    {
+        RemoveOGREmptyTable();
     }
 
+    m_bTableCreated = true;
+
     m_papoLayers = (OGRGeoPackageTableLayer**)CPLRealloc(m_papoLayers,  sizeof(OGRGeoPackageTableLayer*) * (m_nLayers+1));
     m_papoLayers[m_nLayers++] = poLayer;
     return poLayer;
@@ -3643,8 +4417,7 @@ OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
         return OGRERR_FAILURE;
 
     m_papoLayers[iLayer]->ResetReading();
-    m_papoLayers[iLayer]->RunDeferredCreationIfNecessary();
-    m_papoLayers[iLayer]->CreateSpatialIndexIfNecessary();
+    m_papoLayers[iLayer]->SyncToDisk();
 
     CPLString osLayerName = m_papoLayers[iLayer]->GetName();
 
@@ -3698,9 +4471,20 @@ OGRErr GDALGeoPackageDataset::DeleteLayer( int iLayer )
         sqlite3_free(pszSQL);
     }
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( eErr == OGRERR_NONE && m_bHasGPKGOGRContents )
+    {
+        pszSQL = sqlite3_mprintf(
+                "DELETE FROM gpkg_ogr_contents WHERE table_name = '%q'",
+                osLayerName.c_str());
+        eErr = SQLCommand(hDB, pszSQL);
+        sqlite3_free(pszSQL);
+    }
+#endif
+
     if( eErr == OGRERR_NONE )
     {
-        pszSQL = sqlite3_mprintf("DROP TABLE '%q'", osLayerName.c_str());
+        pszSQL = sqlite3_mprintf("DROP TABLE \"%w\"", osLayerName.c_str());
         eErr = SQLCommand(hDB, pszSQL);
         sqlite3_free(pszSQL);
     }
@@ -3747,6 +4531,8 @@ int GDALGeoPackageDataset::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return bUpdate;
 
     return OGRSQLiteBaseDataSource::TestCapability(pszCap);
 }
@@ -3782,10 +4568,28 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
     m_bHasReadMetadataFromStorage = false;
 
     FlushMetadata();
-    for( int i = 0; i < m_nLayers; i++ )
+
+    CPLString osSQLCommand(pszSQLCommand);
+
+    if( pszDialect == NULL || !EQUAL(pszDialect, "DEBUG") )
     {
-        m_papoLayers[i]->RunDeferredCreationIfNecessary();
-        m_papoLayers[i]->CreateSpatialIndexIfNecessary();
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+        const bool bInsertOrDelete =
+            osSQLCommand.ifind("insert into ") != std::string::npos ||
+            osSQLCommand.ifind("delete from ") != std::string::npos;
+#endif
+
+        for( int i = 0; i < m_nLayers; i++ )
+        {
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+            if( bInsertOrDelete &&
+                osSQLCommand.ifind(m_papoLayers[i]->GetName()) != std::string::npos )
+            {
+                m_papoLayers[i]->DisableFeatureCount(true);
+            }
+#endif
+            m_papoLayers[i]->SyncToDisk();
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -3838,7 +4642,7 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
         while( *pszLayerName == ' ' )
             pszLayerName++;
 
-        int idx = FindLayerIndex( SQLUnescapeDoubleQuote(pszLayerName) );
+        int idx = FindLayerIndex( SQLUnescape(pszLayerName) );
         if( idx >= 0 )
         {
             DeleteLayer( idx );
@@ -3860,10 +4664,10 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
             const char* pszDstTableName = papszTokens[5];
             OGRGeoPackageTableLayer* poSrcLayer =
                 (OGRGeoPackageTableLayer*)GetLayerByName(
-                        SQLUnescapeDoubleQuote(pszSrcTableName));
+                        SQLUnescape(pszSrcTableName));
             if( poSrcLayer )
             {
-                poSrcLayer->RenameTo( SQLUnescapeDoubleQuote(pszDstTableName) );
+                poSrcLayer->RenameTo( SQLUnescape(pszDstTableName) );
                 CSLDestroy(papszTokens);
                 return NULL;
             }
@@ -3901,13 +4705,20 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
                                           poSpatialFilter,
                                           "SQLITE" );
 
+#if SQLITE_VERSION_NUMBER < 3007017
+    // Emulate PRAGMA application_id
+    if( EQUAL(pszSQLCommand, "PRAGMA application_id") )
+    {
+        return new OGRSQLiteSingleFeatureLayer
+                                ( pszSQLCommand + 7, m_nApplicationId );
+    }
+#endif
+
 /* -------------------------------------------------------------------- */
 /*      Prepare statement.                                              */
 /* -------------------------------------------------------------------- */
     sqlite3_stmt *hSQLStmt = NULL;
 
-    CPLString osSQLCommand = pszSQLCommand;
-
     /* This will speed-up layer creation */
     /* ORDER BY are costly to evaluate and are not necessary to establish */
     /* the layer definition. */
@@ -3915,6 +4726,7 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
     bool bEmptyLayer = false;
 
     if( osSQLCommand.ifind("SELECT ") == 0 &&
+        CPLString(osSQLCommand.substr(1)).ifind("SELECT ") == std::string::npos &&
         osSQLCommand.ifind(" UNION ") == std::string::npos &&
         osSQLCommand.ifind(" INTERSECT ") == std::string::npos &&
         osSQLCommand.ifind(" EXCEPT ") == std::string::npos )
@@ -3927,15 +4739,15 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
         }
     }
 
-    int rc = sqlite3_prepare( hDB, osSQLCommand.c_str(),
+    int rc = sqlite3_prepare_v2( hDB, osSQLCommand.c_str(),
                               static_cast<int>(osSQLCommand.size()),
                               &hSQLStmt, NULL );
 
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
-                pszSQLCommand, sqlite3_errmsg(hDB) );
+                "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n  %s",
+                osSQLCommand.c_str(), sqlite3_errmsg(hDB) );
 
         if( hSQLStmt != NULL )
         {
@@ -3955,7 +4767,7 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                   "In ExecuteSQL(): sqlite3_step(%s):\n  %s",
-                  pszSQLCommand, sqlite3_errmsg(hDB) );
+                  osSQLCommand.c_str(), sqlite3_errmsg(hDB) );
 
             sqlite3_finalize( hSQLStmt );
             return NULL;
@@ -3965,7 +4777,7 @@ OGRLayer * GDALGeoPackageDataset::ExecuteSQL( const char *pszSQLCommand,
         {
             sqlite3_finalize( hSQLStmt );
             /* VACUUM rewrites the DB, so we need to reset the application id */
-            SetApplicationId();
+            SetApplicationAndUserVersionId();
             return NULL;
         }
 
@@ -4062,13 +4874,9 @@ void GDALGeoPackageDataset::ReleaseResultSet( OGRLayer * poLayer )
 
 bool GDALGeoPackageDataset::HasExtensionsTable()
 {
-    SQLResult oResultTable;
-    OGRErr err = SQLQuery(hDB,
-        "SELECT * FROM sqlite_master WHERE name = 'gpkg_extensions' "
-        "AND type IN ('table', 'view')", &oResultTable);
-    bool bHasExtensionsTable = ( err == OGRERR_NONE && oResultTable.nRowCount == 1 );
-    SQLResultFree(&oResultTable);
-    return bHasExtensionsTable;
+    return SQLGetInteger(hDB,
+        "SELECT 1 FROM sqlite_master WHERE name = 'gpkg_extensions' "
+        "AND type IN ('table', 'view')", NULL) == 1;
 }
 
 /************************************************************************/
@@ -4083,17 +4891,32 @@ void GDALGeoPackageDataset::CheckUnknownExtensions(bool bCheckRasterTable)
     char* pszSQL = NULL;
     if( !bCheckRasterTable)
         pszSQL = sqlite3_mprintf(
-            "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE (table_name IS NULL AND extension_name != 'gdal_aspatial')"
+            "SELECT extension_name, definition, scope FROM gpkg_extensions "
+            "WHERE (table_name IS NULL "
+            "AND extension_name IS NOT NULL "
+            "AND definition IS NOT NULL "
+            "AND scope IS NOT NULL "
+            "AND extension_name != 'gdal_aspatial' "
+            "AND extension_name != 'gpkg_elevation_tiles' "
+            "AND extension_name != 'gpkg_metadata') "
 #ifdef WORKAROUND_SQLITE3_BUGS
-            " OR 0"
+            "OR 0 "
 #endif
+            "LIMIT 1000"
         );
     else
         pszSQL = sqlite3_mprintf(
-            "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name = '%q'"
+            "SELECT extension_name, definition, scope FROM gpkg_extensions "
+            "WHERE (table_name = '%q' "
+            "AND extension_name IS NOT NULL "
+            "AND definition IS NOT NULL "
+            "AND scope IS NOT NULL "
+            "AND extension_name != 'gpkg_elevation_tiles' "
+            "AND extension_name != 'gpkg_metadata') "
 #ifdef WORKAROUND_SQLITE3_BUGS
-            " OR 0"
+            "OR 0 "
 #endif
+            "LIMIT 1000"
             ,
             m_osRasterTable.c_str());
 
@@ -4107,9 +4930,6 @@ void GDALGeoPackageDataset::CheckUnknownExtensions(bool bCheckRasterTable)
             const char* pszExtName = SQLResultGetValue(&oResultTable, 0, i);
             const char* pszDefinition = SQLResultGetValue(&oResultTable, 1, i);
             const char* pszScope = SQLResultGetValue(&oResultTable, 2, i);
-            if( pszExtName == NULL ) pszExtName = "(null)";
-            if( pszDefinition == NULL ) pszDefinition = "(null)";
-            if( pszScope == NULL ) pszScope = "(null)";
 
             if( EQUAL(pszExtName, "gpkg_webp") )
             {
@@ -4188,7 +5008,8 @@ bool GDALGeoPackageDataset::HasGDALAspatialExtension()
 
 OGRErr GDALGeoPackageDataset::CreateGDALAspatialExtension()
 {
-    CreateExtensionsTableIfNecessary();
+    if( CreateExtensionsTableIfNecessary() != OGRERR_NONE )
+        return OGRERR_FAILURE;
 
     if( HasGDALAspatialExtension() )
         return OGRERR_NONE;
@@ -4249,7 +5070,7 @@ bool GDALGeoPackageDataset::HasDataColumnsTable()
 /************************************************************************/
 
 static bool OGRGeoPackageGetHeader( sqlite3_context* pContext,
-                                    CPL_UNUSED int argc,
+                                    int /*argc*/,
                                     sqlite3_value** argv,
                                     GPkgHeader* psHeader,
                                     bool bNeedExtent )
@@ -4261,13 +5082,37 @@ static bool OGRGeoPackageGetHeader( sqlite3_context* pContext,
     }
     int nBLOBLen = sqlite3_value_bytes (argv[0]);
     const GByte* pabyBLOB = (const GByte *) sqlite3_value_blob (argv[0]);
+
     if( nBLOBLen < 8 ||
         GPkgHeaderFromWKB(pabyBLOB, nBLOBLen, psHeader) != OGRERR_NONE )
     {
+        bool bEmpty = false;
+        memset( psHeader, 0, sizeof(*psHeader) );
+        if( OGRSQLiteLayer::GetSpatialiteGeometryHeader(
+                                        pabyBLOB, nBLOBLen,
+                                        &(psHeader->iSrsId),
+                                        NULL,
+                                        &bEmpty,
+                                        &(psHeader->MinX),
+                                        &(psHeader->MinY),
+                                        &(psHeader->MaxX),
+                                        &(psHeader->MaxY) ) == OGRERR_NONE )
+        {
+            psHeader->bEmpty = bEmpty;
+            if( !(bEmpty && bNeedExtent) )
+                return true;
+        }
+
+        sqlite3_result_null(pContext);
+        return false;
+    }
+
+    if( psHeader->bEmpty && bNeedExtent )
+    {
         sqlite3_result_null(pContext);
         return false;
     }
-    if( !(psHeader->bExtentHasXY) && bNeedExtent )
+    else if( !(psHeader->bExtentHasXY) && bNeedExtent )
     {
         OGRGeometry *poGeom = GPkgGeometryToOGR(pabyBLOB, nBLOBLen, NULL);
         if( poGeom == NULL || poGeom->IsEmpty() )
@@ -4363,21 +5208,46 @@ void OGRGeoPackageSTIsEmpty(sqlite3_context* pContext,
 
 static
 void OGRGeoPackageSTGeometryType(sqlite3_context* pContext,
-                        int argc, sqlite3_value** argv)
+                                 int /*argc*/, sqlite3_value** argv)
 {
     GPkgHeader sHeader;
-    if( !OGRGeoPackageGetHeader(pContext, argc, argv, &sHeader, false) )
-        return;
 
     int nBLOBLen = sqlite3_value_bytes (argv[0]);
     const GByte* pabyBLOB = (const GByte *) sqlite3_value_blob (argv[0]);
     OGRwkbGeometryType eGeometryType;
-    if( nBLOBLen <= (int)sHeader.szHeader )
+
+    if( nBLOBLen < 8 ||
+        GPkgHeaderFromWKB(pabyBLOB, nBLOBLen, &sHeader) != OGRERR_NONE )
+    {
+        if( OGRSQLiteLayer::GetSpatialiteGeometryHeader(
+                                        pabyBLOB, nBLOBLen,
+                                        NULL,
+                                        &eGeometryType,
+                                        NULL,
+                                        NULL,
+                                        NULL,
+                                        NULL,
+                                        NULL ) == OGRERR_NONE )
+        {
+            sqlite3_result_text( pContext,
+                                 OGRToOGCGeomType(eGeometryType),
+                                 -1, SQLITE_TRANSIENT );
+            return;
+        }
+        else
+        {
+            sqlite3_result_null( pContext );
+            return;
+        }
+    }
+
+    if( static_cast<size_t>(nBLOBLen) < sHeader.nHeaderLen + 5 )
     {
         sqlite3_result_null( pContext );
         return;
     }
-    OGRErr err = OGRReadWKBGeometryType( (GByte*)pabyBLOB + sHeader.szHeader,
+
+    OGRErr err = OGRReadWKBGeometryType( (GByte*)pabyBLOB + sHeader.nHeaderLen,
                                          wkbVariantIso, &eGeometryType );
     if( err != OGRERR_NONE )
         sqlite3_result_null( pContext );
@@ -4391,7 +5261,7 @@ void OGRGeoPackageSTGeometryType(sqlite3_context* pContext,
 
 static
 void OGRGeoPackageGPKGIsAssignable(sqlite3_context* pContext,
-                                   CPL_UNUSED int argc,
+                                   int /*argc*/,
                                    sqlite3_value** argv)
 {
     if( sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
@@ -4423,12 +5293,156 @@ void OGRGeoPackageSTSRID(sqlite3_context* pContext,
 }
 
 /************************************************************************/
+/*                      OGRGeoPackageTransform()                        */
+/************************************************************************/
+
+static
+void OGRGeoPackageTransform(sqlite3_context* pContext,
+                            int argc,
+                            sqlite3_value** argv)
+{
+    if( sqlite3_value_type (argv[0]) != SQLITE_BLOB ||
+        sqlite3_value_type (argv[1]) != SQLITE_INTEGER )
+    {
+        sqlite3_result_blob(pContext, NULL, 0, NULL);
+        return;
+    }
+
+    const int nBLOBLen = sqlite3_value_bytes (argv[0]);
+    const GByte* pabyBLOB =
+                reinterpret_cast<const GByte*>(sqlite3_value_blob (argv[0]));
+    GPkgHeader sHeader;
+    if( !OGRGeoPackageGetHeader( pContext, argc, argv, &sHeader, false) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid geometry");
+        sqlite3_result_blob(pContext, NULL, 0, NULL);
+        return;
+    }
+
+    GDALGeoPackageDataset* poDS = static_cast<GDALGeoPackageDataset*>(
+                                                sqlite3_user_data(pContext));
+
+    OGRSpatialReference* poSrcSRS = poDS->GetSpatialRef(sHeader.iSrsId);
+    if( poSrcSRS == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "SRID set on geometry (%d) is invalid", sHeader.iSrsId);
+        sqlite3_result_blob(pContext, NULL, 0, NULL);
+        return;
+    }
+
+    int nDestSRID = sqlite3_value_int (argv[1]);
+    OGRSpatialReference* poDstSRS = poDS->GetSpatialRef(nDestSRID);
+    if( poDstSRS == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Target SRID (%d) is invalid", nDestSRID);
+        sqlite3_result_blob(pContext, NULL, 0, NULL);
+        delete poSrcSRS;
+        return;
+    }
+
+    OGRGeometry* poGeom = GPkgGeometryToOGR(pabyBLOB, nBLOBLen, NULL);
+    if( poGeom == NULL )
+    {
+        // Try also spatialite geometry blobs
+        if( OGRSQLiteLayer::ImportSpatiaLiteGeometry( pabyBLOB, nBLOBLen,
+                                                    &poGeom ) != OGRERR_NONE )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid geometry");
+            sqlite3_result_blob(pContext, NULL, 0, NULL);
+            delete poSrcSRS;
+            delete poDstSRS;
+            return;
+        }
+    }
+
+    poGeom->assignSpatialReference(poSrcSRS);
+    if( poGeom->transformTo(poDstSRS) != OGRERR_NONE )
+    {
+        sqlite3_result_blob(pContext, NULL, 0, NULL);
+        poSrcSRS->Release();
+        poDstSRS->Release();
+        return;
+    }
+
+    size_t nBLOBDestLen = 0;
+    GByte* pabyDestBLOB =
+                    GPkgGeometryFromOGR(poGeom, nDestSRID, &nBLOBDestLen);
+    sqlite3_result_blob(pContext, pabyDestBLOB,
+                        static_cast<int>(nBLOBDestLen), VSIFree);
+
+    poSrcSRS->Release();
+    poDstSRS->Release();
+    delete poGeom;
+}
+
+/************************************************************************/
+/*                      OGRGeoPackageSridFromAuthCRS()                  */
+/************************************************************************/
+
+static
+void OGRGeoPackageSridFromAuthCRS(sqlite3_context* pContext,
+                                  int /*argc*/,
+                                  sqlite3_value** argv)
+{
+    if( sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
+        sqlite3_value_type (argv[1]) != SQLITE_INTEGER )
+    {
+        sqlite3_result_int(pContext, -1);
+        return;
+    }
+
+    GDALGeoPackageDataset* poDS =
+            static_cast<GDALGeoPackageDataset*>(sqlite3_user_data(pContext));
+
+    char* pszSQL = sqlite3_mprintf(
+        "SELECT srs_id FROM gpkg_spatial_ref_sys WHERE "
+        "lower(organization) = lower('%q') AND organization_coordsys_id = %d",
+        sqlite3_value_text( argv[0] ),
+        sqlite3_value_int( argv[1] ) );
+    OGRErr err = OGRERR_NONE;
+    int nSRSId = SQLGetInteger(poDS->GetDB(), pszSQL, &err);
+    sqlite3_free(pszSQL);
+    if( err != OGRERR_NONE )
+        nSRSId = -1;
+    sqlite3_result_int(pContext, nSRSId);
+}
+
+/************************************************************************/
+/*                    OGRGeoPackageImportFromEPSG()                     */
+/************************************************************************/
+
+static
+void OGRGeoPackageImportFromEPSG(sqlite3_context* pContext,
+                                     int /*argc*/,
+                                     sqlite3_value** argv)
+{
+    if( sqlite3_value_type (argv[0]) != SQLITE_INTEGER )
+    {
+        sqlite3_result_int( pContext, -1 );
+        return;
+    }
+
+    GDALGeoPackageDataset* poDS =
+            static_cast<GDALGeoPackageDataset*>(sqlite3_user_data(pContext));
+    OGRSpatialReference oSRS;
+    if( oSRS.importFromEPSG( sqlite3_value_int( argv[0] ) ) != OGRERR_NONE )
+    {
+        sqlite3_result_int( pContext, -1 );
+        return;
+    }
+
+    sqlite3_result_int( pContext,poDS->GetSrsId(oSRS) );
+}
+
+/************************************************************************/
 /*                  OGRGeoPackageCreateSpatialIndex()                   */
 /************************************************************************/
 
 static
 void OGRGeoPackageCreateSpatialIndex(sqlite3_context* pContext,
-                                     CPL_UNUSED int argc,
+                                     int /*argc*/,
                                      sqlite3_value** argv)
 {
     if( sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
@@ -4465,7 +5479,7 @@ void OGRGeoPackageCreateSpatialIndex(sqlite3_context* pContext,
 
 static
 void OGRGeoPackageDisableSpatialIndex(sqlite3_context* pContext,
-                                      CPL_UNUSED int argc,
+                                      int /*argc*/,
                                       sqlite3_value** argv)
 {
     if( sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
@@ -4502,7 +5516,7 @@ void OGRGeoPackageDisableSpatialIndex(sqlite3_context* pContext,
 
 static
 void OGRGeoPackageHasSpatialIndex(sqlite3_context* pContext,
-                                  CPL_UNUSED int argc,
+                                  int /*argc*/,
                                   sqlite3_value** argv)
 {
     if( sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
@@ -4542,7 +5556,7 @@ void OGRGeoPackageHasSpatialIndex(sqlite3_context* pContext,
 
 static
 void GPKG_hstore_get_value(sqlite3_context* pContext,
-                           CPL_UNUSED int argc,
+                           int /*argc*/,
                            sqlite3_value** argv)
 {
     if( sqlite3_value_type (argv[0]) != SQLITE_TEXT ||
@@ -4584,7 +5598,7 @@ static CPLString GPKG_GDAL_GetMemFileFromBlob(sqlite3_value** argv)
 
 static
 void GPKG_GDAL_GetMimeType(sqlite3_context* pContext,
-                           CPL_UNUSED int argc,
+                           int /*argc*/,
                            sqlite3_value** argv)
 {
     if( sqlite3_value_type (argv[0]) != SQLITE_BLOB )
@@ -4604,6 +5618,8 @@ void GPKG_GDAL_GetMimeType(sqlite3_context* pContext,
             pszRes = "image/jpeg";
         else if( EQUAL(poDriver->GetDescription(), "WEBP") )
             pszRes = "image/x-webp";
+        else if( EQUAL(poDriver->GetDescription(), "GTIFF") )
+            pszRes = "image/tiff";
         else
             pszRes = CPLSPrintf("gdal/%s", poDriver->GetDescription());
         sqlite3_result_text( pContext, pszRes, -1, SQLITE_TRANSIENT );
@@ -4619,7 +5635,7 @@ void GPKG_GDAL_GetMimeType(sqlite3_context* pContext,
 
 static
 void GPKG_GDAL_GetBandCount(sqlite3_context* pContext,
-                           CPL_UNUSED int argc,
+                           int /*argc*/,
                            sqlite3_value** argv)
 {
     if( sqlite3_value_type (argv[0]) != SQLITE_BLOB )
@@ -4648,7 +5664,7 @@ void GPKG_GDAL_GetBandCount(sqlite3_context* pContext,
 
 static
 void GPKG_GDAL_HasColorTable(sqlite3_context* pContext,
-                             CPL_UNUSED int argc,
+                             int /*argc*/,
                              sqlite3_value** argv)
 {
     if( sqlite3_value_type (argv[0]) != SQLITE_BLOB )
@@ -4677,6 +5693,10 @@ void GPKG_GDAL_HasColorTable(sqlite3_context* pContext,
 /*                         OpenOrCreateDB()                             */
 /************************************************************************/
 
+#ifndef SQLITE_DETERMINISTIC
+#define SQLITE_DETERMINISTIC 0
+#endif
+
 bool GDALGeoPackageDataset::OpenOrCreateDB(int flags)
 {
     const bool bSuccess =
@@ -4690,51 +5710,84 @@ bool GDALGeoPackageDataset::OpenOrCreateDB(int flags)
     // Enable SpatiaLite 4.3 "amphibious" mode, i.e. that SpatiaLite functions
     // that take geometries will accept GPKG encoded geometries without
     // explicit conversion.
+    // Use sqlite3_exec() instead of SQLCommand() since we don't want verbose
+    // error.
     sqlite3_exec(hDB, "SELECT EnableGpkgAmphibiousMode()", NULL, NULL, NULL);
 #endif
 
     /* Used by RTree Spatial Index Extension */
-    sqlite3_create_function(hDB, "ST_MinX", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ST_MinX", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGRGeoPackageSTMinX, NULL, NULL);
-    sqlite3_create_function(hDB, "ST_MinY", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ST_MinY", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGRGeoPackageSTMinY, NULL, NULL);
-    sqlite3_create_function(hDB, "ST_MaxX", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ST_MaxX", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGRGeoPackageSTMaxX, NULL, NULL);
-    sqlite3_create_function(hDB, "ST_MaxY", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ST_MaxY", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGRGeoPackageSTMaxY, NULL, NULL);
-    sqlite3_create_function(hDB, "ST_IsEmpty", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ST_IsEmpty", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGRGeoPackageSTIsEmpty, NULL, NULL);
 
     /* Used by Geometry Type Triggers Extension */
-    sqlite3_create_function(hDB, "ST_GeometryType", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ST_GeometryType", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGRGeoPackageSTGeometryType, NULL, NULL);
-    sqlite3_create_function(hDB, "GPKG_IsAssignable", 2, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "GPKG_IsAssignable", 2,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGRGeoPackageGPKGIsAssignable, NULL, NULL);
 
     /* Used by Geometry SRS ID Triggers Extension */
-    sqlite3_create_function(hDB, "ST_SRID", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ST_SRID", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGRGeoPackageSTSRID, NULL, NULL);
 
     /* Spatialite-like functions */
-    sqlite3_create_function(hDB, "CreateSpatialIndex", 2, SQLITE_ANY, this,
+    sqlite3_create_function(hDB, "CreateSpatialIndex", 2,
+                            SQLITE_UTF8, this,
                             OGRGeoPackageCreateSpatialIndex, NULL, NULL);
-    sqlite3_create_function(hDB, "DisableSpatialIndex", 2, SQLITE_ANY, this,
+    sqlite3_create_function(hDB, "DisableSpatialIndex", 2,
+                            SQLITE_UTF8, this,
                             OGRGeoPackageDisableSpatialIndex, NULL, NULL);
-    sqlite3_create_function(hDB, "HasSpatialIndex", 2, SQLITE_ANY, this,
-                            OGRGeoPackageHasSpatialIndex, NULL, NULL);
+    sqlite3_create_function(hDB, "HasSpatialIndex", 2, SQLITE_UTF8, this,
+                            OGRGeoPackageHasSpatialIndex,
+                            NULL, NULL);
 
     // HSTORE functions
-    sqlite3_create_function(hDB, "hstore_get_value", 2, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "hstore_get_value", 2,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             GPKG_hstore_get_value, NULL, NULL);
 
+    // Override a few Spatialite functions to work with gpkg_spatial_ref_sys
+    sqlite3_create_function(hDB, "ST_Transform", 2,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, this,
+                            OGRGeoPackageTransform, NULL, NULL);
+    sqlite3_create_function(hDB, "Transform", 2,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, this,
+                            OGRGeoPackageTransform, NULL, NULL);
+    sqlite3_create_function(hDB, "SridFromAuthCRS", 2,
+                            SQLITE_UTF8, this,
+                            OGRGeoPackageSridFromAuthCRS, NULL, NULL);
+
+    // GDAL specific function
+    sqlite3_create_function(hDB, "ImportFromEPSG", 1,
+                            SQLITE_UTF8, this,
+                            OGRGeoPackageImportFromEPSG, NULL, NULL);
+
     // Debug functions
     if( CPLTestBool(CPLGetConfigOption("GPKG_DEBUG", "FALSE")) )
     {
-        sqlite3_create_function(hDB, "GDAL_GetMimeType", 1, SQLITE_ANY, NULL,
+        sqlite3_create_function(hDB, "GDAL_GetMimeType", 1,
+                                SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                                 GPKG_GDAL_GetMimeType, NULL, NULL);
-        sqlite3_create_function(hDB, "GDAL_GetBandCount", 1, SQLITE_ANY, NULL,
+        sqlite3_create_function(hDB, "GDAL_GetBandCount", 1,
+                                SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                                 GPKG_GDAL_GetBandCount, NULL, NULL);
-        sqlite3_create_function(hDB, "GDAL_HasColorTable", 1, SQLITE_ANY, NULL,
+        sqlite3_create_function(hDB, "GDAL_HasColorTable", 1,
+                                SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                                 GPKG_GDAL_HasColorTable, NULL, NULL);
     }
 
@@ -4753,7 +5806,16 @@ std::pair<OGRLayer*, IOGRSQLiteGetSpatialWhere*>
 }
 
 /************************************************************************/
-/*                       CommitTransaction()                        */
+/*                         IsInTransaction()                            */
+/************************************************************************/
+
+bool GDALGeoPackageDataset::IsInTransaction() const
+{
+    return nSoftTransactionLevel > 0;
+}
+
+/************************************************************************/
+/*                       CommitTransaction()                            */
 /************************************************************************/
 
 OGRErr GDALGeoPackageDataset::CommitTransaction()
@@ -4778,18 +5840,49 @@ OGRErr GDALGeoPackageDataset::CommitTransaction()
 OGRErr GDALGeoPackageDataset::RollbackTransaction()
 
 {
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    std::vector<bool> abAddTriggers;
+    std::vector<bool> abTriggersDeletedInTransaction;
+#endif
     if( nSoftTransactionLevel == 1 )
     {
         FlushMetadata();
         for( int i = 0; i < m_nLayers; i++ )
         {
-            m_papoLayers[i]->RunDeferredCreationIfNecessary();
-            m_papoLayers[i]->CreateSpatialIndexIfNecessary();
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+            abAddTriggers.push_back(
+                        m_papoLayers[i]->GetAddOGRFeatureCountTriggers());
+            abTriggersDeletedInTransaction.push_back(
+                m_papoLayers[i]->
+                    GetOGRFeatureCountTriggersDeletedInTransaction());
+            m_papoLayers[i]->SetAddOGRFeatureCountTriggers(false);
+#endif
+            m_papoLayers[i]->SyncToDisk();
             m_papoLayers[i]->ResetReading();
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+            m_papoLayers[i]->DisableFeatureCount();
+#endif
         }
     }
 
-    return OGRSQLiteBaseDataSource::RollbackTransaction();
+    OGRErr eErr = OGRSQLiteBaseDataSource::RollbackTransaction();
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( !abAddTriggers.empty() )
+    {
+        for( int i = 0; i < m_nLayers; i++ )
+        {
+            if( abTriggersDeletedInTransaction[i] )
+            {
+                m_papoLayers[i]->SetOGRFeatureCountTriggersEnabled(true);
+            }
+            else
+            {
+                m_papoLayers[i]->SetAddOGRFeatureCountTriggers(abAddTriggers[i]);
+            }
+        }
+    }
+#endif
+    return eErr;
 }
 
 /************************************************************************/
@@ -4800,7 +5893,7 @@ const char* GDALGeoPackageDataset::GetGeometryTypeString(OGRwkbGeometryType eTyp
 {
     const char* pszGPKGGeomType = OGRToOGCGeomType(eType);
     if( EQUAL(pszGPKGGeomType, "GEOMETRYCOLLECTION") &&
-        CPLTestBool(CPLGetConfigOption("OGR_GPKG_GEOMCOLLECTION", "YES")) )
+        CPLTestBool(CPLGetConfigOption("OGR_GPKG_GEOMCOLLECTION", "NO")) )
     {
         pszGPKGGeomType = "GEOMCOLLECTION";
     }
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
index 4b658b6..a54e0cc 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagedriver.cpp
@@ -28,20 +28,14 @@
 
 #include "ogr_geopackage.h"
 
-CPL_CVSID("$Id: ogrgeopackagedriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+CPL_CVSID("$Id: ogrgeopackagedriver.cpp 37791 2017-03-19 16:05:45Z rouault $");
 
 // g++ -g -Wall -fPIC -shared -o ogr_geopackage.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gpkg ogr/ogrsf_frmts/gpkg/*.c* -L. -lgdal
 
-
-/* "GP10" in ASCII bytes */
-static const char aGpkgId[4] = {0x47, 0x50, 0x31, 0x30};
-// static const size_t szGpkgIdPos = 68;
-
 /************************************************************************/
 /*                       OGRGeoPackageDriverIdentify()                  */
 /************************************************************************/
 
-
 static int OGRGeoPackageDriverIdentify( GDALOpenInfo* poOpenInfo, bool bEmitWarning )
 {
     if( STARTS_WITH_CI(poOpenInfo->pszFilename, "GPKG:") )
@@ -51,7 +45,7 @@ static int OGRGeoPackageDriverIdentify( GDALOpenInfo* poOpenInfo, bool bEmitWarn
     if( poOpenInfo->fpL == NULL)
         return FALSE;
 
-    if ( poOpenInfo->nHeaderBytes < 16 ||
+    if ( poOpenInfo->nHeaderBytes < 100 ||
         !STARTS_WITH((const char*)poOpenInfo->pabyHeader, "SQLite format 3") )
     {
         return FALSE;
@@ -64,12 +58,18 @@ static int OGRGeoPackageDriverIdentify( GDALOpenInfo* poOpenInfo, bool bEmitWarn
     const char* pszExt = CPLGetExtension(poOpenInfo->pszFilename);
     const bool bIsRecognizedExtension = EQUAL(pszExt, "GPKG") || EQUAL(pszExt, "GPKX");
 
-    /* Requirement 2: A GeoPackage SHALL contain 0x47503130 ("GP10" in ASCII) */
-    /* in the application id */
+    /* Requirement 2: application id */
     /* http://opengis.github.io/geopackage/#_file_format */
     /* Be tolerant since some datasets don't actually follow that requirement */
-    if( poOpenInfo->nHeaderBytes < 68 + 4 ||
-        memcmp(poOpenInfo->pabyHeader + 68, aGpkgId, 4) != 0 )
+    GUInt32 nApplicationId;
+    memcpy(&nApplicationId, poOpenInfo->pabyHeader + knApplicationIdPos, 4);
+    nApplicationId = CPL_MSBWORD32(nApplicationId);
+    GUInt32 nUserVersion;
+    memcpy(&nUserVersion, poOpenInfo->pabyHeader + knUserVersionPos, 4);
+    nUserVersion = CPL_MSBWORD32(nUserVersion);
+    if( nApplicationId != GP10_APPLICATION_ID &&
+        nApplicationId != GP11_APPLICATION_ID &&
+        nApplicationId != GPKG_APPLICATION_ID )
     {
 #ifdef DEBUG
         if( EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input")  )
@@ -82,43 +82,106 @@ static int OGRGeoPackageDriverIdentify( GDALOpenInfo* poOpenInfo, bool bEmitWarn
 
         if( bEmitWarning )
         {
-            char szSignature[4+1];
-            memcpy(szSignature, poOpenInfo->pabyHeader + 68, 4);
-            szSignature[4] = '\0';
+            GByte abySignature[4+1];
+            memcpy(abySignature, poOpenInfo->pabyHeader + knApplicationIdPos, 4);
+            abySignature[4] = '\0';
 
             /* Is this a GPxx version ? */
-            const bool bWarn = CPLTestBool(CPLGetConfigOption("GPKG_WARN_UNRECOGNIZED_APPLICATION_ID", "YES"));
-            if( szSignature[0] == 'G' && szSignature[1] == 'P' &&
-                szSignature[2] >= '0' && szSignature[2] <= '9' &&
-                szSignature[3] >= '0' && szSignature[3] <= '9' )
+            const bool bWarn = CPLTestBool(CPLGetConfigOption(
+                "GPKG_WARN_UNRECOGNIZED_APPLICATION_ID", "YES"));
+            if( bWarn )
+            {
+                CPLError( CE_Warning, CPLE_AppDefined,
+                          "GPKG: bad application_id=0x%02X%02X%02X%02X on '%s'",
+                          abySignature[0], abySignature[1],
+                          abySignature[2], abySignature[3],
+                          poOpenInfo->pszFilename );
+            }
+            else
+            {
+                CPLDebug( "GPKG",
+                          "bad application_id=0x%02X%02X%02X%02X on '%s'",
+                          abySignature[0], abySignature[1],
+                          abySignature[2], abySignature[3],
+                          poOpenInfo->pszFilename );
+            }
+        }
+    }
+    else if(nApplicationId == GPKG_APPLICATION_ID &&
+            // Accept any 102XX version
+            !(nUserVersion >= GPKG_1_2_VERSION &&
+              nUserVersion < GPKG_1_2_VERSION + 99))
+    {
+#ifdef DEBUG
+        if( EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input")  )
+        {
+            return FALSE;
+        }
+#endif
+        if( !bIsRecognizedExtension )
+            return FALSE;
+
+        if( bEmitWarning )
+        {
+            GByte abySignature[4+1];
+            memcpy(abySignature, poOpenInfo->pabyHeader + knUserVersionPos, 4);
+            abySignature[4] = '\0';
+
+            const bool bWarn = CPLTestBool(CPLGetConfigOption(
+                            "GPKG_WARN_UNRECOGNIZED_APPLICATION_ID", "YES"));
+            if( bWarn )
             {
-                if( bWarn )
+                if( nUserVersion > GPKG_1_2_VERSION )
                 {
                     CPLError( CE_Warning, CPLE_AppDefined,
-                              "GPKG: '%s' has version '%s' with may be partially supported by this driver",
-                              poOpenInfo->pszFilename, szSignature );
+                              "This version of GeoPackage "
+                              "user_version=0x%02X%02X%02X%02X "
+                              "(%u, v%d.%d.%d) on '%s' may only be "
+                              "partially supported",
+                              abySignature[0], abySignature[1],
+                              abySignature[2], abySignature[3],
+                              nUserVersion,
+                              nUserVersion / 10000,
+                              (nUserVersion % 10000 ) / 100,
+                              nUserVersion % 100,
+                              poOpenInfo->pszFilename );
                 }
                 else
                 {
-                    CPLDebug( "GPKG",
-                              "'%s' has version '%s' with may be partially supported by this driver",
-                              poOpenInfo->pszFilename, szSignature );
+                    CPLError( CE_Warning, CPLE_AppDefined,
+                              "GPKG: unrecognized user_version="
+                              "0x%02X%02X%02X%02X (%u) on '%s'",
+                              abySignature[0], abySignature[1],
+                              abySignature[2], abySignature[3],
+                              nUserVersion,
+                              poOpenInfo->pszFilename );
                 }
             }
             else
             {
-                if( bWarn )
+                if( nUserVersion > GPKG_1_2_VERSION )
                 {
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "GPKG: bad application_id 0x%02X%02X%02X%02X on '%s'",
-                              szSignature[0], szSignature[1], szSignature[2], szSignature[3],
+                    CPLDebug( "GPKG",
+                              "This version of GeoPackage "
+                              "user_version=0x%02X%02X%02X%02X "
+                              "(%u, v%d.%d.%d) on '%s' may only be "
+                              "partially supported",
+                              abySignature[0], abySignature[1],
+                              abySignature[2], abySignature[3],
+                              nUserVersion,
+                              nUserVersion / 10000,
+                              (nUserVersion % 10000 ) / 100,
+                              nUserVersion % 100,
                               poOpenInfo->pszFilename );
                 }
                 else
                 {
                     CPLDebug( "GPKG",
-                              "bad application_id 0x%02X%02X%02X%02X on '%s'",
-                              szSignature[0], szSignature[1], szSignature[2], szSignature[3],
+                              "unrecognized user_version=0x%02X%02X%02X%02X"
+                              "(%u) on '%s'",
+                              abySignature[0], abySignature[1],
+                              abySignature[2], abySignature[3],
+                              nUserVersion,
                               poOpenInfo->pszFilename );
                 }
             }
@@ -128,7 +191,9 @@ static int OGRGeoPackageDriverIdentify( GDALOpenInfo* poOpenInfo, bool bEmitWarn
 #ifdef DEBUG
               && !EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input")
 #endif
-           )
+              && !(STARTS_WITH(poOpenInfo->pszFilename, "/vsizip/") &&
+                   EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "zip") )
+              && !STARTS_WITH(poOpenInfo->pszFilename, "/vsigzip/") )
     {
         if( bEmitWarning )
         {
@@ -231,22 +296,28 @@ void RegisterOGRGeoPackage()
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GeoPackage" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gpkg" );
     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_geopackage.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, "Byte Int16 UInt16 Float32" );
 
 #define COMPRESSION_OPTIONS \
-"  <Option name='TILE_FORMAT' type='string-select' description='Format to use to create tiles' default='PNG_JPEG'>" \
+"  <Option name='TILE_FORMAT' type='string-select' description='Format to use to create tiles' default='AUTO'>" \
+"    <Value>AUTO</Value>" \
 "    <Value>PNG_JPEG</Value>" \
 "    <Value>PNG</Value>" \
 "    <Value>PNG8</Value>" \
 "    <Value>JPEG</Value>" \
 "    <Value>WEBP</Value>" \
+"    <Value>TIFF</Value>" \
 "  </Option>" \
 "  <Option name='QUALITY' type='int' min='1' max='100' description='Quality for JPEG and WEBP tiles' default='75'/>" \
 "  <Option name='ZLEVEL' type='int' min='1' max='9' description='DEFLATE compression level for PNG tiles' default='6'/>" \
 "  <Option name='DITHER' type='boolean' description='Whether to apply Floyd-Steinberg dithering (for TILE_FORMAT=PNG8)' default='NO'/>"
 
     poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST, "<OpenOptionList>"
-"  <Option name='LIST_ALL_TABLES' type='boolean' description='Whether all tables, including those non listed in gpkg_contents, should be listed' default='YES' />"
+"  <Option name='LIST_ALL_TABLES' type='string-select' description='Whether all tables, including those non listed in gpkg_contents, should be listed' default='AUTO'>"
+"    <Value>AUTO</Value>"
+"    <Value>YES</Value>"
+"    <Value>NO</Value>"
+"  </Option>"
 "  <Option name='TABLE' type='string' description='Name of tile user-table'/>"
 "  <Option name='ZOOM_LEVEL' type='integer' description='Zoom level of full resolution. If not specified, maximum non-empty zoom level'/>"
 "  <Option name='BAND_COUNT' type='int' min='1' max='4' description='Number of raster bands' default='4'/>"
@@ -290,6 +361,16 @@ COMPRESSION_OPTIONS
 "    <Value>MODE</Value>"
 "    <Value>AVERAGE</Value>"
 "  </Option>"
+"  <Option name='PRECISION' type='float' description='Smallest significant value. Only used for tiled gridded elevation datasets' default='1'/>"
+"  <Option name='VERSION' type='string-select' description='Set GeoPackage version (for application_id and user_version fields)' default='AUTO'>"
+"     <Value>AUTO</Value>"
+"     <Value>1.0</Value>"
+"     <Value>1.1</Value>"
+"     <Value>1.2</Value>"
+"  </Option>"
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+"  <Option name='ADD_GPKG_OGR_CONTENTS' type='boolean' description='Whether to add a gpkg_ogr_contents table to keep feature count' default='YES'/>"
+#endif
 "</CreationOptionList>");
 
     poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
@@ -303,7 +384,11 @@ COMPRESSION_OPTIONS
 "  <Option name='SPATIAL_INDEX' type='boolean' description='Whether to create a spatial index' default='YES'/>"
 "  <Option name='IDENTIFIER' type='string' description='Identifier of the layer, as put in the contents table'/>"
 "  <Option name='DESCRIPTION' type='string' description='Description of the layer, as put in the contents table'/>"
-"  <Option name='REGISTER_AS_ASPATIAL' type='boolean' description='Whether non spatial tables should be registered as aspatial in gpkg_contents' default='YES'/>"
+"  <Option name='ASPATIAL_VARIANT' type='string-select' description='How to register non spatial tables' default='GPKG_ATTRIBUTES'>"
+"     <Value>GPKG_ATTRIBUTES</Value>"
+"     <Value>OGR_ASPATIAL</Value>"
+"     <Value>NOT_REGISTERED</Value>"
+"  </Option>"
 "</LayerCreationOptionList>");
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
index 145bb53..6cc55e4 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagelayer.cpp
@@ -29,9 +29,10 @@
 
 #include "ogr_geopackage.h"
 #include "ogrgeopackageutility.h"
+#include "ogrsqliteutility.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeopackagelayer.cpp 35503 2016-09-23 18:22:45Z goatbar $");
+CPL_CVSID("$Id: ogrgeopackagelayer.cpp 37809 2017-03-20 15:28:41Z rouault $");
 
 /************************************************************************/
 /*                      OGRGeoPackageLayer()                            */
@@ -67,7 +68,6 @@ OGRGeoPackageLayer::~OGRGeoPackageLayer()
         m_poFeatureDefn->Release();
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -137,8 +137,6 @@ OGRFeature *OGRGeoPackageLayer::GetNextFeature()
         }
 
         OGRFeature *poFeature = TranslateFeature(m_poQueryStatement);
-        if( poFeature == NULL )
-            return NULL;
 
         if( (m_poFilterGeom == NULL
             || FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) )
@@ -166,7 +164,14 @@ OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
 /*      Set FID if we have a column to set it from.                     */
 /* -------------------------------------------------------------------- */
     if( iFIDCol >= 0 )
+    {
         poFeature->SetFID( sqlite3_column_int64( hStmt, iFIDCol ) );
+        if( m_pszFidColumn == NULL && poFeature->GetFID() == 0 )
+        {
+            // Miht be the case for views with joins.
+            poFeature->SetFID( iNextShapeId );
+        }
+    }
     else
         poFeature->SetFID( iNextShapeId );
 
@@ -185,9 +190,10 @@ OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
         {
             OGRSpatialReference* poSrs = poGeomFieldDefn->GetSpatialRef();
             int iGpkgSize = sqlite3_column_bytes(hStmt, iGeomCol);
+            // coverity[tainted_data_return]
             GByte *pabyGpkg = (GByte *)sqlite3_column_blob(hStmt, iGeomCol);
-            OGRGeometry *poGeom = GPkgGeometryToOGR(pabyGpkg, iGpkgSize, poSrs);
-            if ( ! poGeom )
+            OGRGeometry *poGeom = GPkgGeometryToOGR(pabyGpkg, iGpkgSize, NULL);
+            if ( poGeom == NULL )
             {
                 // Try also spatialite geometry blobs
                 if( OGRSQLiteLayer::ImportSpatiaLiteGeometry( pabyGpkg, iGpkgSize,
@@ -196,6 +202,8 @@ OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
                     CPLError( CE_Failure, CPLE_AppDefined, "Unable to read geometry");
                 }
             }
+            if( poGeom != NULL )
+                poGeom->assignSpatialReference(poSrs);
             poFeature->SetGeometryDirectly( poGeom );
         }
     }
@@ -212,7 +220,10 @@ OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
         const int iRawField = panFieldOrdinals[iField];
 
         if( sqlite3_column_type( hStmt, iRawField ) == SQLITE_NULL )
+        {
+            poFeature->SetFieldNull( iField );
             continue;
+        }
 
         switch( poFieldDefn->GetType() )
         {
@@ -234,9 +245,11 @@ OGRFeature *OGRGeoPackageLayer::TranslateFeature( sqlite3_stmt* hStmt )
             case OFTBinary:
             {
                 const int nBytes = sqlite3_column_bytes( hStmt, iRawField );
-
+                // coverity[tainted_data_return]
+                const GByte* pabyData = reinterpret_cast<const GByte*>(
+                    sqlite3_column_blob( hStmt, iRawField ) );
                 poFeature->SetField( iField, nBytes,
-                    (GByte*)sqlite3_column_blob( hStmt, iRawField ) );
+                                     const_cast<GByte*>(pabyData) );
                 break;
             }
 
@@ -313,14 +326,18 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
     m_poFeatureDefn->SetGeomType(wkbNone);
     m_poFeatureDefn->Reference();
 
-    int    nRawColumns = sqlite3_column_count( hStmt );
+    const int    nRawColumns = sqlite3_column_count( hStmt );
 
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
 
+    const bool bPromoteToInteger64 =
+        CPLTestBool(CPLGetConfigOption("OGR_PROMOTE_TO_INTEGER64", "FALSE"));
+
     for( int iCol = 0; iCol < nRawColumns; iCol++ )
     {
-        OGRFieldDefn    oField( OGRSQLiteParamsUnquote(sqlite3_column_name( hStmt, iCol )),
-                                OFTString );
+        OGRFieldDefn    oField(
+            SQLUnescape(sqlite3_column_name( hStmt, iCol )),
+            OFTString );
 
         // In some cases, particularly when there is a real name for
         // the primary key/_rowid_ column we will end up getting the
@@ -328,14 +345,8 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
         if( m_poFeatureDefn->GetFieldIndex( oField.GetNameRef() ) != -1 )
             continue;
 
-        if( EQUAL(oField.GetNameRef(), "FID") )
-        {
-            CPLFree(m_pszFidColumn);
-            m_pszFidColumn = CPLStrdup(oField.GetNameRef());
-            iFIDCol = iCol;
-        }
-
-        if( m_pszFidColumn != NULL && EQUAL(m_pszFidColumn, oField.GetNameRef()))
+        if( m_pszFidColumn != NULL && EQUAL(m_pszFidColumn,
+                                            oField.GetNameRef()) )
             continue;
 
         // The rowid is for internal use, not a real column.
@@ -345,76 +356,127 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
         // this will avoid the old geom field to appear when running something
         // like "select st_buffer(geom,5) as geom, * from my_layer"
         if( m_poFeatureDefn->GetGeomFieldCount() &&
-            EQUAL(oField.GetNameRef(), m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()) )
+            EQUAL(oField.GetNameRef(),
+                  m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()) )
+        {
             continue;
+        }
+
+
+#ifdef SQLITE_HAS_COLUMN_METADATA
+        const char* pszTableName = sqlite3_column_table_name( hStmt, iCol );
+        const char* pszOriginName = sqlite3_column_origin_name( hStmt, iCol );
+        if( pszTableName != NULL && pszOriginName != NULL )
+        {
+            OGRLayer* poLayer = m_poDS->GetLayerByName(pszTableName);
+            if( poLayer != NULL )
+            {
+                if( m_poFeatureDefn->GetGeomFieldCount() == 0 &&
+                    EQUAL(pszOriginName, poLayer->GetGeometryColumn()) )
+                {
+                    OGRGeomFieldDefn oGeomField(
+                            poLayer->GetLayerDefn()->GetGeomFieldDefn(0));
+                    oGeomField.SetName( oField.GetNameRef() );
+                    m_poFeatureDefn->AddGeomFieldDefn(&oGeomField);
+                    iGeomCol = iCol;
+                    continue;
+                }
+                else if( EQUAL(pszOriginName, poLayer->GetFIDColumn()) )
+                {
+                    CPLFree(m_pszFidColumn);
+                    m_pszFidColumn = CPLStrdup(oField.GetNameRef());
+                    iFIDCol = iCol;
+                    continue;
+                }
+                int nSrcIdx = poLayer->GetLayerDefn()->GetFieldIndex(
+                                                        oField.GetNameRef());
+                if( nSrcIdx >= 0 )
+                {
+                    OGRFieldDefn* poSrcField =
+                            poLayer->GetLayerDefn()->GetFieldDefn(nSrcIdx);
+                    oField.SetType( poSrcField->GetType() );
+                    oField.SetSubType( poSrcField->GetSubType() );
+                    oField.SetWidth( poSrcField->GetWidth() );
+                    oField.SetPrecision( poSrcField->GetPrecision() );
+                    m_poFeatureDefn->AddFieldDefn( &oField );
+                    panFieldOrdinals[
+                            m_poFeatureDefn->GetFieldCount() - 1] = iCol;
+                    continue;
+                }
+            }
+        }
+#endif
+
+        const int nColType = sqlite3_column_type( hStmt, iCol );
+        if( m_pszFidColumn == NULL && nColType == SQLITE_INTEGER &&
+            EQUAL(oField.GetNameRef(), "FID") )
+        {
+            m_pszFidColumn = CPLStrdup(oField.GetNameRef());
+            iFIDCol = iCol;
+            continue;
+        }
 
-        int nColType = sqlite3_column_type( hStmt, iCol );
         const char * pszDeclType = sqlite3_column_decltype(hStmt, iCol);
 
         // Recognize a geometry column from trying to build the geometry
-        // Useful for OGRSQLiteSelectLayer
-        if( nColType == SQLITE_BLOB && m_poFeatureDefn->GetGeomFieldCount() == 0 )
+        if( nColType == SQLITE_BLOB &&
+            m_poFeatureDefn->GetGeomFieldCount() == 0 )
         {
             const int nBytes = sqlite3_column_bytes( hStmt, iCol );
             if( nBytes >= 8 )
             {
-                const GByte* pabyGpkg = (const GByte*)sqlite3_column_blob( hStmt, iCol  );
+                // coverity[tainted_data_return]
+                const GByte* pabyGpkg =
+                        (const GByte*)sqlite3_column_blob( hStmt, iCol  );
                 GPkgHeader oHeader;
                 OGRGeometry* poGeom = NULL;
                 int nSRID = 0;
-                if( GPkgHeaderFromWKB(pabyGpkg, nBytes, &oHeader) == OGRERR_NONE &&
-                    (poGeom = GPkgGeometryToOGR(pabyGpkg, nBytes, NULL)) != NULL )
+
+                if( GPkgHeaderFromWKB(pabyGpkg, nBytes, &oHeader) ==
+                                                                OGRERR_NONE )
+                {
+                    poGeom = GPkgGeometryToOGR(pabyGpkg, nBytes, NULL);
+                    nSRID = oHeader.iSrsId;
+                }
+                else
+                {
+                    // Try also spatialite geometry blobs
+                    if( OGRSQLiteLayer::ImportSpatiaLiteGeometry(
+                          pabyGpkg, nBytes, &poGeom, &nSRID ) != OGRERR_NONE )
+                    {
+                        delete poGeom;
+                        poGeom = NULL;
+                    }
+                }
+
+                if( poGeom )
                 {
-                    OGRGeomFieldDefn oGeomField(oField.GetNameRef(), wkbUnknown);
+                    OGRGeomFieldDefn oGeomField(oField.GetNameRef(),
+                                                wkbUnknown);
 
                     /* Read the SRS */
-                    OGRSpatialReference *poSRS = m_poDS->GetSpatialRef(oHeader.iSrsId);
+                    OGRSpatialReference *poSRS =
+                                        m_poDS->GetSpatialRef(nSRID);
                     if ( poSRS )
                     {
                         oGeomField.SetSpatialRef(poSRS);
                         poSRS->Dereference();
                     }
 
-                    OGRwkbGeometryType eGeomType = wkbUnknown;
+                    OGRwkbGeometryType eGeomType = poGeom->getGeometryType();
                     if( pszDeclType != NULL )
                     {
-                        eGeomType = poGeom->getGeometryType();
-                        oGeomField.SetType( eGeomType );
-                    }
-                    delete poGeom;
-                    poGeom = NULL;
-
-#ifdef SQLITE_HAS_COLUMN_METADATA
-                    const char* pszTableName = sqlite3_column_table_name( hStmt, iCol );
-                    if( oGeomField.GetType() == wkbUnknown && pszTableName != NULL )
-                    {
-                        OGRGeoPackageLayer* poLayer = (OGRGeoPackageLayer*)
-                                        m_poDS->GetLayerByName(pszTableName);
-                        if( poLayer != NULL && poLayer->GetLayerDefn()->GetGeomFieldCount() > 0)
+                        OGRwkbGeometryType eDeclaredGeomType =
+                            GPkgGeometryTypeToWKB(pszDeclType, false, false);
+                        if( eDeclaredGeomType != wkbUnknown )
                         {
-                            oGeomField.SetType( poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->GetType() );
+                            eGeomType = OGR_GT_SetModifier(eDeclaredGeomType,
+                                               OGR_GT_HasZ(eGeomType),
+                                               OGR_GT_HasM(eGeomType));
                         }
                     }
-#endif
-
-                    m_poFeatureDefn->AddGeomFieldDefn(&oGeomField);
-                    iGeomCol = iCol;
-                    continue;
-                }
-
-                // Try also spatialite geometry blobs
-                else if( OGRSQLiteLayer::ImportSpatiaLiteGeometry( pabyGpkg, nBytes,
-                                                                   &poGeom, &nSRID ) == OGRERR_NONE )
-                {
-                    OGRGeomFieldDefn oGeomField(oField.GetNameRef(), wkbUnknown);
+                    oGeomField.SetType( eGeomType );
 
-                    /* Read the SRS */
-                    OGRSpatialReference *poSRS = m_poDS->GetSpatialRef(nSRID);
-                    if ( poSRS )
-                    {
-                        oGeomField.SetSpatialRef(poSRS);
-                        poSRS->Dereference();
-                    }
                     delete poGeom;
                     poGeom = NULL;
 
@@ -422,17 +484,13 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
                     iGeomCol = iCol;
                     continue;
                 }
-                // Unlikely to have poGeom be valid, but just in case, check
-                // if we need to delete it.
-                if (poGeom != NULL)
-                    delete poGeom;
             }
         }
 
         switch( nColType )
         {
           case SQLITE_INTEGER:
-            if( CPLTestBool(CPLGetConfigOption("OGR_PROMOTE_TO_INTEGER64", "FALSE")) )
+            if( bPromoteToInteger64 )
                 oField.SetType( OFTInteger64 );
             else
             {
@@ -473,5 +531,4 @@ void OGRGeoPackageLayer::BuildFeatureDefn( const char *pszLayerName,
         m_poFeatureDefn->AddFieldDefn( &oField );
         panFieldOrdinals[m_poFeatureDefn->GetFieldCount() - 1] = iCol;
     }
-
 }
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp
index 0f6d697..cf73445 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageselectlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgeopackageselectlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  GeoPackage Translator
  * Purpose:  Implements OGRGeoPackageSelectLayer class
@@ -29,6 +28,8 @@
 
 #include "ogr_geopackage.h"
 
+CPL_CVSID("$Id: ogrgeopackageselectlayer.cpp 37534 2017-03-01 16:50:58Z rouault $");
+
 /************************************************************************/
 /*                        OGRGeoPackageSelectLayer()                    */
 /************************************************************************/
@@ -37,19 +38,23 @@ OGRGeoPackageSelectLayer::OGRGeoPackageSelectLayer( GDALGeoPackageDataset *poDS,
                                             CPLString osSQLIn,
                                             sqlite3_stmt *hStmtIn,
                                             int bUseStatementForGetNextFeature,
-                                            int bEmptyLayer ) : OGRGeoPackageLayer(poDS)
-
+                                            int bEmptyLayer ) :
+    OGRGeoPackageLayer(poDS)
 {
+    // Cannot be moved to initializer list because of use of this, which MSVC 2008 doesn't like
     poBehaviour = new OGRSQLiteSelectLayerCommonBehaviour(poDS, this, osSQLIn, bEmptyLayer);
+
     BuildFeatureDefn( "SELECT", hStmtIn );
 
     if( bUseStatementForGetNextFeature )
     {
         m_poQueryStatement = hStmtIn;
-        bDoStep = FALSE;
+        bDoStep = false;
     }
     else
+    {
         sqlite3_finalize( hStmtIn );
+    }
 }
 
 /************************************************************************/
@@ -95,20 +100,19 @@ GIntBig OGRGeoPackageSelectLayer::GetFeatureCount( int bForce )
 OGRErr OGRGeoPackageSelectLayer::ResetStatement()
 
 {
-    int rc;
-
     ClearStatement();
 
     iNextShapeId = 0;
-    bDoStep = TRUE;
+    bDoStep = true;
 
 #ifdef DEBUG
-    CPLDebug( "OGR_GPKG", "prepare(%s)", poBehaviour->osSQLCurrent.c_str() );
+    CPLDebug( "OGR_GPKG", "prepare_v2(%s)", poBehaviour->osSQLCurrent.c_str() );
 #endif
 
-    rc = sqlite3_prepare( m_poDS->GetDB(), poBehaviour->osSQLCurrent,
-                          static_cast<int>(poBehaviour->osSQLCurrent.size()),
-                          &m_poQueryStatement, NULL );
+    const int rc =
+        sqlite3_prepare_v2( m_poDS->GetDB(), poBehaviour->osSQLCurrent,
+                         static_cast<int>(poBehaviour->osSQLCurrent.size()),
+                         &m_poQueryStatement, NULL );
 
     if( rc == SQLITE_OK )
     {
@@ -117,7 +121,7 @@ OGRErr OGRGeoPackageSelectLayer::ResetStatement()
     else
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s",
+                  "In ResetStatement(): sqlite3_prepare_v2(%s):\n  %s",
                   poBehaviour->osSQLCurrent.c_str(), sqlite3_errmsg(m_poDS->GetDB()) );
         m_poQueryStatement = NULL;
         return OGRERR_FAILURE;
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
index aed3869..c27af54 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackagetablelayer.cpp
@@ -29,10 +29,11 @@
 
 #include "ogr_geopackage.h"
 #include "ogrgeopackageutility.h"
+#include "ogrsqliteutility.h"
 #include "cpl_time.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeopackagetablelayer.cpp 35695 2016-10-11 17:39:33Z rouault $");
+CPL_CVSID("$Id: ogrgeopackagetablelayer.cpp 37814 2017-03-20 20:37:16Z rouault $");
 
 static const char UNSUPPORTED_OP_READ_ONLY[] =
   "%s : unsupported operation on a read-only datasource.";
@@ -81,34 +82,30 @@ OGRErr OGRGeoPackageTableLayer::SaveTimestamp()
 
     m_bContentChanged = false;
 
-    sqlite3* poDb = m_poDS->GetDB();
-
-    if ( ! poDb ) return OGRERR_FAILURE;
+    OGRErr err = m_poDS->UpdateGpkgContentsLastChange(m_pszTableName);
 
-    const char* pszCurrentDate = CPLGetConfigOption("OGR_CURRENT_DATE", NULL);
-    char *pszSQL = NULL;
-
-    if( pszCurrentDate )
-    {
-        pszSQL = sqlite3_mprintf(
-                    "UPDATE gpkg_contents SET "
-                    "last_change = '%q'"
-                    "WHERE table_name = '%q' AND "
-                    "Lower(data_type) IN ('features', 'gdal_aspatial')",
-                    m_pszTableName, pszCurrentDate);
-    }
-    else
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( m_bIsTable && err == OGRERR_NONE && m_poDS->m_bHasGPKGOGRContents )
     {
-        pszSQL = sqlite3_mprintf(
-                    "UPDATE gpkg_contents SET "
-                    "last_change = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ','now')"
-                    "WHERE table_name = '%q' AND "
-                    "Lower(data_type) IN ('features', 'gdal_aspatial')",
+        CPLString osFeatureCount;
+        if( m_nTotalFeatureCount >= 0 )
+        {
+            osFeatureCount.Printf(CPL_FRMT_GIB, m_nTotalFeatureCount);
+        }
+        else
+        {
+            osFeatureCount = "NULL";
+        }
+        char* pszSQL = sqlite3_mprintf(
+                    "UPDATE gpkg_ogr_contents SET "
+                    "feature_count = %s "
+                    "WHERE table_name = '%q'",
+                    osFeatureCount.c_str(),
                     m_pszTableName);
+        err = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
     }
-
-    OGRErr err = SQLCommand(poDb, pszSQL);
-    sqlite3_free(pszSQL);
+#endif
 
     return err;
 }
@@ -138,34 +135,30 @@ OGRErr OGRGeoPackageTableLayer::UpdateExtent( const OGREnvelope *poExtent )
 //
 OGRErr OGRGeoPackageTableLayer::BuildColumns()
 {
-    if ( ! m_poFeatureDefn )
-    {
-        return OGRERR_FAILURE;
-    }
-
     CPLFree(panFieldOrdinals);
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * m_poFeatureDefn->GetFieldCount() );
 
     /* Always start with a primary key */
-    CPLString soColumns = m_pszFidColumn ? m_pszFidColumn : "_rowid_";
-    CPLString soColumn;
+    CPLString soColumns = "m.";
+    soColumns += m_pszFidColumn ?
+        "\"" + SQLEscapeName(m_pszFidColumn) + "\"" : "_rowid_";
     iFIDCol = 0;
 
     /* Add a geometry column if there is one (just one) */
     if ( m_poFeatureDefn->GetGeomFieldCount() )
     {
-        soColumns += ", ";
-        soColumn.Printf("\"%s\"", SQLEscapeDoubleQuote(m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()).c_str());
-        soColumns += soColumn;
+        soColumns += ", m.\"";
+        soColumns += SQLEscapeName(m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef());
+        soColumns += "\"";
         iGeomCol = 1;
     }
 
     /* Add all the attribute columns */
     for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); i++ )
     {
-        soColumns += ", ";
-        soColumn.Printf("\"%s\"", SQLEscapeDoubleQuote(m_poFeatureDefn->GetFieldDefn(i)->GetNameRef()).c_str());
-        soColumns += soColumn;
+        soColumns += ", m.\"";
+        soColumns += SQLEscapeName(m_poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+        soColumns += "\"";
         panFieldOrdinals[i] = 1 + (iGeomCol >= 0) + i;
     }
 
@@ -186,85 +179,81 @@ bool OGRGeoPackageTableLayer::IsGeomFieldSet( OGRFeature *poFeature )
         poFeature->GetGeomFieldRef(0);
 }
 
+#define MY_CPLAssert CPLAssert
+
 OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
                                                        sqlite3_stmt *poStmt,
                                                        int *pnColCount,
                                                        bool bAddFID,
-                                                       bool bBindNullFields )
+                                                       bool bBindUnsetFields )
 {
-    if ( ! (poFeature && poStmt && pnColCount) )
-        return OGRERR_FAILURE;
-
     OGRFeatureDefn *poFeatureDefn = poFeature->GetDefnRef();
 
     int nColCount = 1;
+    int err = SQLITE_OK;
     if( bAddFID )
     {
-        const int err =
-            sqlite3_bind_int64(poStmt, nColCount++, poFeature->GetFID());
-        if ( err != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "failed to bind FID to statement");
-            return OGRERR_FAILURE;
-        }
+        err = sqlite3_bind_int64(poStmt, nColCount++, poFeature->GetFID());
+        MY_CPLAssert( err == SQLITE_OK );
     }
 
     /* Bind data values to the statement, here bind the blob for geometry */
-    if ( poFeatureDefn->GetGeomFieldCount() )
+    if ( err == SQLITE_OK && poFeatureDefn->GetGeomFieldCount() )
     {
-        GByte *pabyWkb = NULL;
-
-        int err = SQLITE_OK;
         // Non-NULL geometry.
         OGRGeometry* poGeom = poFeature->GetGeomFieldRef(0);
         if ( poGeom )
         {
+            GByte *pabyWkb = NULL;
             size_t szWkb = 0;
             pabyWkb = GPkgGeometryFromOGR(poGeom, m_iSrs, &szWkb);
             err = sqlite3_bind_blob(poStmt, nColCount++, pabyWkb,
                                     static_cast<int>(szWkb), CPLFree);
+            MY_CPLAssert( err == SQLITE_OK );
 
-            // FIXME: in case the geometry is a GeometryCollection, we should
-            // inspect its subgeometries to see if there's non-linear ones.
-            if( OGR_GT_IsNonLinear(poGeom->getGeometryType()) )
-                CreateGeometryExtensionIfNecessary(poGeom->getGeometryType());
+            CreateGeometryExtensionIfNecessary(poGeom);
         }
         /* NULL geometry */
         else
         {
             err = sqlite3_bind_null(poStmt, nColCount++);
-        }
-        if ( err != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "failed to bind geometry to statement");
-            return OGRERR_FAILURE;
+            MY_CPLAssert( err == SQLITE_OK );
         }
     }
 
     /* Bind the attributes using appropriate SQLite data types */
-    int err = SQLITE_OK;
     for( int i = 0;
          err == SQLITE_OK && i < poFeatureDefn->GetFieldCount();
          i++ )
     {
         if( i == m_iFIDAsRegularColumnIndex )
             continue;
+        if( !poFeature->IsFieldSet(i) )
+        {
+            if( bBindUnsetFields )
+            {
+                err = sqlite3_bind_null(poStmt, nColCount++);
+                MY_CPLAssert( err == SQLITE_OK );
+            }
+            continue;
+        }
+
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn(i);
 
-        if( poFeature->IsFieldSet(i) )
+        if( !poFeature->IsFieldNull(i) )
         {
             switch(SQLiteFieldFromOGR(poFieldDefn->GetType()))
             {
                 case SQLITE_INTEGER:
                 {
                     err = sqlite3_bind_int64(poStmt, nColCount++, poFeature->GetFieldAsInteger64(i));
+                    MY_CPLAssert( err == SQLITE_OK );
                     break;
                 }
                 case SQLITE_FLOAT:
                 {
                     err = sqlite3_bind_double(poStmt, nColCount++, poFeature->GetFieldAsDouble(i));
+                    MY_CPLAssert( err == SQLITE_OK );
                     break;
                 }
                 case SQLITE_BLOB:
@@ -272,6 +261,7 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
                     int szBlob = 0;
                     GByte *pabyBlob = poFeature->GetFieldAsBinary(i, &szBlob);
                     err = sqlite3_bind_blob(poStmt, nColCount++, pabyBlob, szBlob, NULL);
+                    MY_CPLAssert( err == SQLITE_OK );
                     break;
                 }
                 default:
@@ -351,18 +341,20 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindParameters( OGRFeature *poFeature,
                         }
                     }
                     err = sqlite3_bind_text(poStmt, nColCount++, pszVal, nValLengthBytes, SQLITE_TRANSIENT);
+                    MY_CPLAssert( err == SQLITE_OK );
                     break;
                 }
             }
         }
         else
         {
-            if( bBindNullFields )
-                err = sqlite3_bind_null(poStmt, nColCount++);
+            err = sqlite3_bind_null(poStmt, nColCount++);
+            MY_CPLAssert( err == SQLITE_OK );
         }
     }
 
-    *pnColCount = nColCount;
+    if( pnColCount != NULL )
+        *pnColCount = nColCount;
     return (err == SQLITE_OK) ? OGRERR_NONE : OGRERR_FAILURE;
 }
 
@@ -379,7 +371,7 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindUpdateParameters( OGRFeature *poFeatu
 
     int nColCount = 0;
     const OGRErr err =
-        FeatureBindParameters( poFeature, poStmt, &nColCount, false, true );
+        FeatureBindParameters( poFeature, poStmt, &nColCount, false, false );
     if ( err != OGRERR_NONE )
         return err;
 
@@ -396,7 +388,6 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindUpdateParameters( OGRFeature *poFeatu
     return OGRERR_NONE;
 }
 
-
 //----------------------------------------------------------------------
 // FeatureBindInsertParameters()
 //
@@ -408,15 +399,11 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindUpdateParameters( OGRFeature *poFeatu
 OGRErr OGRGeoPackageTableLayer::FeatureBindInsertParameters( OGRFeature *poFeature,
                                                              sqlite3_stmt *poStmt,
                                                              bool bAddFID,
-                                                             bool bBindNullFields )
+                                                             bool bBindUnsetFields )
 {
-    int nColCount = 0;
-    return
-        FeatureBindParameters( poFeature, poStmt, &nColCount,
-                               bAddFID, bBindNullFields );
+    return FeatureBindParameters( poFeature, poStmt, NULL, bAddFID, bBindUnsetFields );
 }
 
-
 //----------------------------------------------------------------------
 // FeatureGenerateInsertSQL()
 //
@@ -429,7 +416,7 @@ OGRErr OGRGeoPackageTableLayer::FeatureBindInsertParameters( OGRFeature *poFeatu
 //
 CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeature,
                                                              bool bAddFID,
-                                                             bool bBindNullFields )
+                                                             bool bBindUnsetFields )
 {
     bool bNeedComma = false;
     OGRFeatureDefn *poFeatureDefn = poFeature->GetDefnRef();
@@ -438,12 +425,12 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
         poFeatureDefn->GetGeomFieldCount() == 0 &&
         !bAddFID )
         return CPLSPrintf("INSERT INTO \"%s\" DEFAULT VALUES",
-                          SQLEscapeDoubleQuote(m_pszTableName).c_str());
+                          SQLEscapeName(m_pszTableName).c_str());
 
     /* Set up our SQL string basics */
     CPLString osSQLFront;
     osSQLFront.Printf("INSERT INTO \"%s\" ( ",
-                      SQLEscapeDoubleQuote(m_pszTableName).c_str());
+                      SQLEscapeName(m_pszTableName).c_str());
 
     CPLString osSQLBack;
     osSQLBack = ") VALUES (";
@@ -452,7 +439,7 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
 
     if( bAddFID )
     {
-        osSQLColumn.Printf("\"%s\"", SQLEscapeDoubleQuote(GetFIDColumn()).c_str());
+        osSQLColumn.Printf("\"%s\"", SQLEscapeName(GetFIDColumn()).c_str());
         osSQLFront += osSQLColumn;
         osSQLBack += "?";
         bNeedComma = true;
@@ -466,7 +453,7 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
             osSQLBack += ", ";
         }
 
-        osSQLColumn.Printf("\"%s\"", SQLEscapeDoubleQuote(poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()).c_str());
+        osSQLColumn.Printf("\"%s\"", SQLEscapeName(poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()).c_str());
         osSQLFront += osSQLColumn;
         osSQLBack += "?";
         bNeedComma = true;
@@ -477,7 +464,7 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
     {
         if( i == m_iFIDAsRegularColumnIndex )
             continue;
-        if( !bBindNullFields && !poFeature->IsFieldSet(i) )
+        if( !bBindUnsetFields && !poFeature->IsFieldSet(i) )
             continue;
 
         if( !bNeedComma )
@@ -491,7 +478,7 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
         }
 
         osSQLColumn.Printf("\"%s\"",
-                           SQLEscapeDoubleQuote(poFeatureDefn->GetFieldDefn(i)->GetNameRef()).c_str());
+                           SQLEscapeName(poFeatureDefn->GetFieldDefn(i)->GetNameRef()).c_str());
         osSQLFront += osSQLColumn;
         osSQLBack += "?";
     }
@@ -500,12 +487,11 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateInsertSQL( OGRFeature *poFeatu
 
     if( !bNeedComma )
         return CPLSPrintf("INSERT INTO \"%s\" DEFAULT VALUES",
-                          SQLEscapeDoubleQuote(m_pszTableName).c_str());
+                          SQLEscapeName(m_pszTableName).c_str());
 
     return osSQLFront + osSQLBack;
 }
 
-
 //----------------------------------------------------------------------
 // FeatureGenerateUpdateSQL()
 //
@@ -525,14 +511,14 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeatu
     /* Set up our SQL string basics */
     CPLString osUpdate;
     osUpdate.Printf("UPDATE \"%s\" SET ",
-                    SQLEscapeDoubleQuote(m_pszTableName).c_str());
+                    SQLEscapeName(m_pszTableName).c_str());
 
     CPLString osSQLColumn;
 
     if ( poFeatureDefn->GetGeomFieldCount() > 0 )
     {
         osSQLColumn.Printf("\"%s\"",
-                           SQLEscapeDoubleQuote(poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()).c_str());
+                           SQLEscapeName(poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef()).c_str());
         osUpdate += osSQLColumn;
         osUpdate += "=?";
         bNeedComma = true;
@@ -543,25 +529,28 @@ CPLString OGRGeoPackageTableLayer::FeatureGenerateUpdateSQL( OGRFeature *poFeatu
     {
         if( i == m_iFIDAsRegularColumnIndex )
             continue;
+        if( !poFeature->IsFieldSet(i) )
+            continue;
         if( !bNeedComma )
             bNeedComma = true;
         else
             osUpdate += ", ";
 
         osSQLColumn.Printf("\"%s\"",
-                           SQLEscapeDoubleQuote(poFeatureDefn->GetFieldDefn(i)->GetNameRef()).c_str());
+                           SQLEscapeName(poFeatureDefn->GetFieldDefn(i)->GetNameRef()).c_str());
         osUpdate += osSQLColumn;
         osUpdate += "=?";
     }
+    if( !bNeedComma )
+        return CPLString();
 
     CPLString osWhere;
     osWhere.Printf(" WHERE \"%s\" = ?",
-                   SQLEscapeDoubleQuote(m_pszFidColumn).c_str());
+                   SQLEscapeName(m_pszFidColumn).c_str());
 
     return osUpdate + osWhere;
 }
 
-
 //----------------------------------------------------------------------
 // ReadTableDefinition()
 //
@@ -583,17 +572,43 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
     bool bHasZ = false;
     bool bHasM = false;
 
+    // Is it a table or a view ?
+    {
+        SQLResult oResult;
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT type FROM sqlite_master WHERE name = '%q' AND type "
+            "IN ('view', 'table')",
+            m_pszTableName);
+        err = SQLQuery(poDb, pszSQL, &oResult);
+        sqlite3_free(pszSQL);
+        if ( err == OGRERR_NONE && oResult.nRowCount == 1 )
+        {
+            m_bIsTable = EQUAL(SQLResultGetValue(&oResult, 0, 0),
+                               "table");
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Table or view '%s' does not exist",
+                      m_pszTableName );
+            SQLResultFree(&oResult);
+            return OGRERR_FAILURE;
+        }
+        SQLResultFree(&oResult);
+    }
+
     if( bIsGpkgTable )
     {
         /* Check that the table name is registered in gpkg_contents */
         char* pszSQL = sqlite3_mprintf(
             "SELECT table_name, data_type, identifier, "
-            "description, min_x, min_y, max_x, max_y, srs_id "
+            "description, min_x, min_y, max_x, max_y "
             "FROM gpkg_contents "
-            "WHERE table_name = '%q'"
+            "WHERE (table_name = '%q')"
 #ifdef WORKAROUND_SQLITE3_BUGS
             " OR 0"
 #endif
+            " LIMIT 2"
             , m_pszTableName);
 
         SQLResult oResultContents;
@@ -607,7 +622,9 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
             if ( err != OGRERR_NONE )
                 CPLError( CE_Failure, CPLE_AppDefined, "%s", oResultContents.pszErrMsg ? oResultContents.pszErrMsg : "" );
             else /* if ( oResultContents.nRowCount != 1 ) */
-                CPLError( CE_Failure, CPLE_AppDefined, "layer '%s' is not registered in gpkg_contents", m_pszTableName );
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "layer '%s' is not registered in gpkg_contents",
+                          m_pszTableName );
 
             SQLResultFree(&oResultContents);
             return OGRERR_FAILURE;
@@ -620,6 +637,51 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
         if( pszDescription && pszDescription[0] )
             OGRLayer::SetMetadataItem("DESCRIPTION", pszDescription);
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+        if( m_poDS->m_bHasGPKGOGRContents )
+        {
+            pszSQL = sqlite3_mprintf(
+                "SELECT feature_count "
+                "FROM gpkg_ogr_contents "
+                "WHERE table_name = '%q'"
+#ifdef WORKAROUND_SQLITE3_BUGS
+                " OR 0"
+#endif
+                " LIMIT 2"
+                , m_pszTableName);
+            SQLResult oResultFeatureCount;
+            err = SQLQuery(poDb, pszSQL, &oResultFeatureCount);
+            sqlite3_free(pszSQL);
+            if( err == OGRERR_NONE && oResultFeatureCount.nRowCount == 1 )
+            {
+                const char* pszFeatureCount =
+                                SQLResultGetValue(&oResultFeatureCount, 0, 0);
+                if( pszFeatureCount )
+                {
+                    m_nTotalFeatureCount = CPLAtoGIntBig(pszFeatureCount);
+                }
+            }
+            SQLResultFree(&oResultFeatureCount);
+
+            // Check if the triggers are there. 
+            pszSQL = sqlite3_mprintf(
+                "SELECT COUNT(*) FROM sqlite_master WHERE type = 'trigger' "
+                "AND name IN ('trigger_insert_feature_count_%q', "
+                "'trigger_delete_feature_count_%q')",
+                m_pszTableName, m_pszTableName);
+            if( SQLGetInteger(poDb, pszSQL, NULL) == 2 )
+            {
+                m_bOGRFeatureCountTriggersEnabled = true;
+            }
+            else if( m_bIsTable )
+            {
+                CPLDebug("GPKG", "Insert/delete feature_count triggers "
+                         "missing on %s", m_pszTableName);
+            }
+            sqlite3_free(pszSQL);
+        }
+#endif
+
         if( bIsSpatial )
         {
             const char *pszMinX = SQLResultGetValue(&oResultContents, 4, 0);
@@ -649,6 +711,7 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
 #ifdef WORKAROUND_SQLITE3_BUGS
                         " OR 0"
 #endif
+                        " LIMIT 2"
                         ,m_pszTableName);
 
             SQLResult oResultGeomCols;
@@ -704,12 +767,21 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
     }
 
     /* Populate feature definition from table description */
-    m_poFeatureDefn = new OGRFeatureDefn( m_pszTableName );
-    SetDescription( m_poFeatureDefn->GetName() );
-    m_poFeatureDefn->SetGeomType(wkbNone);
-    m_poFeatureDefn->Reference();
 
-    bool bFidFound = false;
+    // First pass to determine if we have a single PKID column
+    int nCountPKIDColumns = 0;
+    for ( int iRecord = 0; iRecord < oResultTable.nRowCount; iRecord++ )
+    {
+        int nPKIDIndex = SQLResultGetValueAsInteger(&oResultTable, 5, iRecord);
+        if( nPKIDIndex > 0 )
+            nCountPKIDColumns ++;
+    }
+    if( nCountPKIDColumns > 1 )
+    {
+        CPLDebug("GPKG", "For table %s, multiple columns make "
+                         "the primary key. Ignoring them",
+                 m_pszTableName);
+    }
 
     for ( int iRecord = 0; iRecord < oResultTable.nRowCount; iRecord++ )
     {
@@ -717,13 +789,15 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
         const char *pszType = SQLResultGetValue(&oResultTable, 2, iRecord);
         int bNotNull = SQLResultGetValueAsInteger(&oResultTable, 3, iRecord);
         const char* pszDefault = SQLResultGetValue(&oResultTable, 4, iRecord);
-        OGRBoolean bFid = SQLResultGetValueAsInteger(&oResultTable, 5, iRecord);
+        int nPKIDIndex = SQLResultGetValueAsInteger(&oResultTable, 5, iRecord);
         OGRFieldSubType eSubType;
         int nMaxWidth = 0;
-        const OGRFieldType oType = GPkgFieldToOGR(pszType, eSubType, nMaxWidth);
+        OGRFieldType oType = GPkgFieldToOGR(pszType, eSubType, nMaxWidth);
 
         /* Not a standard field type... */
-        if ( (oType > OFTMaxType && osGeomColsType.size()) || EQUAL(osGeomColumnName, pszName) )
+        if ( !EQUAL(pszType, "") && !EQUAL(pszName, "OGC_FID") &&
+            ((oType > OFTMaxType && !osGeomColsType.empty() ) ||
+             EQUAL(osGeomColumnName, pszName)) )
         {
             /* Maybe it's a geometry type? */
             OGRwkbGeometryType oGeomType;
@@ -767,7 +841,6 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
                     SQLResultFree(&oResultTable);
                     return OGRERR_FAILURE;
                 }
-
             }
             else
             {
@@ -776,23 +849,23 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
                 CPLError(CE_Warning, CPLE_AppDefined,
                          "geometry column '%s' of type '%s' ignored", pszName, pszType);
             }
-
         }
         else
         {
+            if( oType > OFTMaxType )
+            {
+                CPLDebug("GPKG",
+                         "For table %s, unrecognized type name %s for "
+                         "column %s. Using string type",
+                         m_pszTableName, pszType, pszName);
+                oType = OFTString;
+            }
+
             /* Is this the FID column? */
-            if ( bFid && (oType == OFTInteger || oType == OFTInteger64) )
+            if ( nPKIDIndex > 0 && nCountPKIDColumns == 1 &&
+                      (oType == OFTInteger || oType == OFTInteger64) )
             {
-                if( bFidFound )
-                {
-                    CPLDebug("GPKG", "For table %s, a new FID column has been found (%s). Keeping previous one (%s)",
-                             m_pszTableName, pszName, m_pszFidColumn);
-                }
-                else
-                {
-                    bFidFound = true;
-                    m_pszFidColumn = CPLStrdup(pszName);
-                }
+                m_pszFidColumn = CPLStrdup(pszName);
             }
             else
             {
@@ -861,32 +934,11 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
     }
 
     /* Wait, we didn't find a FID? Some operations will not be possible */
-    if ( ! bFidFound )
+    if ( m_bIsTable && m_pszFidColumn == NULL )
     {
         CPLDebug("GPKG",
-                 "no integer primary key defined for table '%s'", m_pszTableName);
-    }
-    else
-    {
-    /* -------------------------------------------------------------------- */
-    /*      Find if the FID holds 64bit values                              */
-    /* -------------------------------------------------------------------- */
-        const char* pszSQLStatic = CPLSPrintf("SELECT MAX(%s) FROM '%s'",
-                            OGRSQLiteEscape(m_pszFidColumn).c_str(),
-                            m_pszTableName);
-        sqlite3_stmt* hColStmt = NULL;
-        int rc = sqlite3_prepare( poDb, pszSQLStatic, -1, &hColStmt, NULL );
-        if( rc == SQLITE_OK )
-        {
-            rc = sqlite3_step( hColStmt );
-            if( rc == SQLITE_ROW )
-            {
-                GIntBig nMaxId = sqlite3_column_int64( hColStmt, 0 );
-                if( nMaxId > INT_MAX )
-                    OGRLayer::SetMetadataItem(OLMD_FID64, "YES");
-            }
-        }
-        sqlite3_finalize( hColStmt );
+                 "no integer primary key defined for table '%s'",
+                 m_pszTableName);
     }
 
     if ( bReadExtent )
@@ -904,7 +956,6 @@ OGRErr OGRGeoPackageTableLayer::ReadTableDefinition(bool bIsSpatial, bool bIsGpk
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                      OGRGeoPackageTableLayer()                       */
 /************************************************************************/
@@ -914,8 +965,15 @@ OGRGeoPackageTableLayer::OGRGeoPackageTableLayer(
                     const char * pszTableName) :
     OGRGeoPackageLayer(poDS),
     m_pszTableName(CPLStrdup(pszTableName)),
+    m_bIsTable(true), // sensible init for creation mode
     m_iSrs(0),
     m_poExtent(NULL),
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    m_nTotalFeatureCount(-1),
+    m_bOGRFeatureCountTriggersEnabled(false),
+    m_bAddOGRFeatureCountTriggers(false),
+    m_bFeatureCountTriggersDeletedInTransaction(false),
+#endif
     m_soColumns(""),
     m_soFilter(""),
     m_bExtentChanged(false),
@@ -931,12 +989,16 @@ OGRGeoPackageTableLayer::OGRGeoPackageTableLayer(
     m_bDeferredCreation(false),
     m_iFIDAsRegularColumnIndex(-1),
     m_bHasReadMetadataFromStorage(false),
-    m_bRegisterAsAspatial(false)
+    m_bHasTriedDetectingFID64(false),
+    m_eASPatialVariant(GPKG_ATTRIBUTES)
 {
-    m_poQueryStatement = NULL;
     memset(m_abHasGeometryExtension, 0, sizeof(m_abHasGeometryExtension));
-}
 
+    m_poFeatureDefn = new OGRFeatureDefn( m_pszTableName );
+    SetDescription( m_poFeatureDefn->GetName() );
+    m_poFeatureDefn->SetGeomType(wkbNone);
+    m_poFeatureDefn->Reference();
+}
 
 /************************************************************************/
 /*                      ~OGRGeoPackageTableLayer()                      */
@@ -944,27 +1006,19 @@ OGRGeoPackageTableLayer::OGRGeoPackageTableLayer(
 
 OGRGeoPackageTableLayer::~OGRGeoPackageTableLayer()
 {
-    if( m_bDeferredCreation )
-        RunDeferredCreationIfNecessary();
+    SyncToDisk();
 
     if( m_bDropRTreeTable )
     {
-        const char* pszT = m_pszTableName;
-        const char* pszC =m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
+        ResetReading();
+
         char* pszSQL =
-            sqlite3_mprintf("DROP TABLE \"rtree_%w_%w\"", pszT, pszC);
+            sqlite3_mprintf("DROP TABLE \"%w\"", m_osRTreeName.c_str());
         SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
-    }
-    else
-    {
-        CreateSpatialIndexIfNecessary();
+        m_bDropRTreeTable = false;
     }
 
-    /* Save metadata back to the database */
-    SaveExtent();
-    SaveTimestamp();
-
     /* Clean up resources in memory */
     if ( m_pszTableName )
         CPLFree( m_pszTableName );
@@ -979,23 +1033,140 @@ OGRGeoPackageTableLayer::~OGRGeoPackageTableLayer()
         sqlite3_finalize(m_poInsertStatement);
 }
 
+/************************************************************************/
+/*                        PostInit()                                    */
+/************************************************************************/
+
+void OGRGeoPackageTableLayer::PostInit()
+{
+#ifdef SQLITE_HAS_COLUMN_METADATA
+    if( !m_bIsTable )
+    {
+        /* Detect if the view columns have the FID and geom columns of a */
+        /* table that has itself a spatial index */
+        sqlite3_stmt* hStmt = NULL;
+        char* pszSQL = sqlite3_mprintf("SELECT * FROM \"%w\"", m_pszTableName);
+        CPL_IGNORE_RET_VAL(sqlite3_prepare_v2(m_poDS->GetDB(),
+                                              pszSQL, -1, &hStmt, NULL));
+        sqlite3_free(pszSQL);
+        if( hStmt )
+        {
+            if( sqlite3_step(hStmt) == SQLITE_ROW )
+            {
+                OGRGeoPackageTableLayer* poLayerGeom = NULL;
+                const int nRawColumns = sqlite3_column_count( hStmt );
+                for( int iCol = 0; iCol < nRawColumns; iCol++ )
+                {
+                    CPLString osColName(SQLUnescape(
+                                        sqlite3_column_name( hStmt, iCol )));
+                    const char* pszTableName =
+                        sqlite3_column_table_name( hStmt, iCol );
+                    const char* pszOriginName =
+                        sqlite3_column_origin_name( hStmt, iCol );
+                    if( EQUAL(osColName, "OGC_FID") &&
+                        (pszOriginName == NULL ||
+                         osColName != pszOriginName) )
+                    {
+                        // in the case we have a OGC_FID column, and that
+                        // is not the name of the original column, then
+                        // interpret this as an explicit intent to be a
+                        // PKID.
+                        // We cannot just take the FID of a source table as
+                        // a FID because of potential joins that would result
+                        // in multiple records with same source FID.
+                        m_pszFidColumn = CPLStrdup(osColName);
+                        m_poFeatureDefn->DeleteFieldDefn(
+                            m_poFeatureDefn->GetFieldIndex(osColName));
+                    }
+                    else if( pszTableName != NULL && pszOriginName != NULL )
+                    {
+                        OGRGeoPackageTableLayer* poLayer =
+                            dynamic_cast<OGRGeoPackageTableLayer*>(
+                            m_poDS->GetLayerByName(pszTableName));
+                        if( poLayer != NULL &&
+                            osColName == GetGeometryColumn() &&
+                            strcmp(pszOriginName,
+                                   poLayer->GetGeometryColumn()) == 0 )
+                        {
+                            poLayerGeom = poLayer;
+                        }
+                    }
+                }
+
+                if( poLayerGeom != NULL && poLayerGeom->HasSpatialIndex() )
+                {
+                    for( int iCol = 0; iCol < nRawColumns; iCol++ )
+                    {
+                        CPLString osColName(SQLUnescape(
+                                            sqlite3_column_name( hStmt, iCol )));
+                        const char* pszTableName =
+                            sqlite3_column_table_name( hStmt, iCol );
+                        const char* pszOriginName =
+                            sqlite3_column_origin_name( hStmt, iCol );
+                        if( pszTableName != NULL && pszOriginName != NULL )
+                        {
+                            OGRGeoPackageTableLayer* poLayer =
+                                dynamic_cast<OGRGeoPackageTableLayer*>(
+                                m_poDS->GetLayerByName(pszTableName));
+                            if( poLayer != NULL && poLayer == poLayerGeom &&
+                                 strcmp(pszOriginName,
+                                        poLayer->GetFIDColumn()) == 0 )
+                            {
+                                m_bHasSpatialIndex = true;
+                                m_osRTreeName = poLayerGeom->m_osRTreeName;
+                                m_osFIDForRTree = osColName;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            sqlite3_finalize(hStmt);
+        }
+
+        /* Update the columns string */
+        BuildColumns();
+    }
+#endif
+}
 
 /************************************************************************/
-/*                      CreateField()                                   */
+/*                      CheckUpdatableTable()                           */
 /************************************************************************/
 
-OGRErr OGRGeoPackageTableLayer::CreateField( OGRFieldDefn *poField,
-                                             CPL_UNUSED int bApproxOK )
+bool OGRGeoPackageTableLayer::CheckUpdatableTable(const char* pszOperation)
 {
-    OGRFieldDefn oFieldDefn(poField);
     if( !m_poDS->GetUpdate() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   UNSUPPORTED_OP_READ_ONLY,
-                  "CreateField");
-        return OGRERR_FAILURE;
+                  pszOperation);
+        return false;
     }
+/* -------------------------------------------------------------------- */
+/*      Check that is a table and not a view                            */
+/* -------------------------------------------------------------------- */
+    if( !m_bIsTable )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Layer %s is not a table",
+                 m_pszTableName);
+        return false;
+    }
+    return true;
+}
 
+/************************************************************************/
+/*                      CreateField()                                   */
+/************************************************************************/
+
+OGRErr OGRGeoPackageTableLayer::CreateField( OGRFieldDefn *poField,
+                                             CPL_UNUSED int bApproxOK )
+{
+    if( !CheckUpdatableTable("CreateField") )
+        return OGRERR_FAILURE;
+
+    OGRFieldDefn oFieldDefn(poField);
     int nMaxWidth = 0;
     if( m_bPreservePrecision && poField->GetType() == OFTString )
         nMaxWidth = poField->GetWidth();
@@ -1018,8 +1189,8 @@ OGRErr OGRGeoPackageTableLayer::CreateField( OGRFieldDefn *poField,
         CPLString osCommand;
 
         osCommand.Printf("ALTER TABLE \"%s\" ADD COLUMN \"%s\" %s",
-                          SQLEscapeDoubleQuote(m_pszTableName).c_str(),
-                          SQLEscapeDoubleQuote(poField->GetNameRef()).c_str(),
+                          SQLEscapeName(m_pszTableName).c_str(),
+                          SQLEscapeName(poField->GetNameRef()).c_str(),
                           GPkgFieldFromOGR(poField->GetType(),
                                            poField->GetSubType(),
                                            nMaxWidth));
@@ -1087,8 +1258,11 @@ OGRErr OGRGeoPackageTableLayer::CreateField( OGRFieldDefn *poField,
 /************************************************************************/
 
 OGRErr OGRGeoPackageTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
-                                                 CPL_UNUSED int bApproxOK )
+                                                 int /* bApproxOK */ )
 {
+    if( !CheckUpdatableTable("CreateGeomField") )
+        return OGRERR_FAILURE;
+
     if( m_poFeatureDefn->GetGeomFieldCount() == 1 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -1112,7 +1286,7 @@ OGRErr OGRGeoPackageTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn
 
     OGRSpatialReference* poSRS = oGeomField.GetSpatialRef();
     if( poSRS != NULL )
-        m_iSrs = m_poDS->GetSrsId(poSRS);
+        m_iSrs = m_poDS->GetSrsId(*poSRS);
 
 /* -------------------------------------------------------------------- */
 /*      Create the new field.                                           */
@@ -1120,42 +1294,41 @@ OGRErr OGRGeoPackageTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn
     if( !m_bDeferredCreation )
     {
         char *pszSQL = sqlite3_mprintf(
-            "ALTER TABLE \"%w\" ADD COLUMN \"%w\" %s%s",
+            "ALTER TABLE \"%w\" ADD COLUMN \"%w\" %s%s"
+            ";"
+            "UPDATE gpkg_contents SET data_type = 'features' "
+            "WHERE table_name = '%q'",
             m_pszTableName, oGeomField.GetNameRef(),
             m_poDS->GetGeometryTypeString(oGeomField.GetType()),
-            !oGeomField.IsNullable() ? " NOT NULL DEFAULT ''" : "");
-
-        OGRErr err = SQLCommand(m_poDS->GetDB(), pszSQL);
-        sqlite3_free(pszSQL);
-
-        if ( err != OGRERR_NONE )
-            return err;
-
-        pszSQL = sqlite3_mprintf(
-            "UPDATE gpkg_contents SET data_type = 'features' WHERE table_name = '%q'",
-            GetName());
-        err = SQLCommand(m_poDS->GetDB(), pszSQL);
+            !oGeomField.IsNullable() ? " NOT NULL DEFAULT ''" : "",
+            m_pszTableName);
+        CPLString osSQL(pszSQL);
         sqlite3_free(pszSQL);
-        if ( err != OGRERR_NONE )
-            return OGRERR_FAILURE;
 
-        bool bHasASpatialLayers = false;
-        for(int i=0;i<m_poDS->GetLayerCount();i++)
+        if( m_poDS->HasExtensionsTable() )
         {
-            if( m_poDS->GetLayer(i) != this &&
-                m_poDS->GetLayer(i)->GetLayerDefn()->GetGeomFieldCount() == 0 )
-                bHasASpatialLayers = true;
-        }
-        if( !bHasASpatialLayers )
-        {
-            err = SQLCommand(m_poDS->GetDB(),
-                             "DELETE FROM gpkg_extensions WHERE "
-                             "extension_name = 'gdal_aspatial' "
-                             "AND table_name IS NULL "
-                             "AND column_name IS NULL");
-            if ( err != OGRERR_NONE )
-                return OGRERR_FAILURE;
+            // Suppress gdal_aspatial extension if this was the last
+            // aspatial layer.
+            bool bHasASpatialLayers = false;
+            for(int i=0;i<m_poDS->GetLayerCount();i++)
+            {
+                if( m_poDS->GetLayer(i) != this &&
+                    m_poDS->GetLayer(i)->GetLayerDefn()->GetGeomFieldCount() == 0 )
+                    bHasASpatialLayers = true;
+            }
+            if( !bHasASpatialLayers )
+            {
+                osSQL +=
+                    ";"
+                    "DELETE FROM gpkg_extensions WHERE "
+                    "extension_name = 'gdal_aspatial' "
+                    "AND table_name IS NULL "
+                    "AND column_name IS NULL";
+            }
         }
+        OGRErr err = SQLCommand(m_poDS->GetDB(), osSQL);
+        if ( err != OGRERR_NONE )
+            return err;
     }
 
     m_poFeatureDefn->AddGeomFieldDefn( &oGeomField );
@@ -1172,6 +1345,103 @@ OGRErr OGRGeoPackageTableLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn
     return OGRERR_NONE;
 }
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+
+/************************************************************************/
+/*                      DisableFeatureCount()                           */
+/************************************************************************/
+
+void OGRGeoPackageTableLayer::DisableFeatureCount(bool bInMemoryOnly)
+{
+    m_nTotalFeatureCount = -1;
+    if( !bInMemoryOnly && m_poDS->m_bHasGPKGOGRContents )
+    {
+        char* pszSQL = sqlite3_mprintf(
+            "UPDATE gpkg_ogr_contents SET feature_count = NULL WHERE "
+            "table_name = '%q'",
+            m_pszTableName);
+        SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+    }
+}
+
+/************************************************************************/
+/*                      CreateTriggers()                                */
+/************************************************************************/
+
+void OGRGeoPackageTableLayer::CreateTriggers(const char* pszTableName)
+{
+    if( m_bAddOGRFeatureCountTriggers )
+    {
+        if( pszTableName == NULL )
+            pszTableName = m_pszTableName;
+
+        m_bOGRFeatureCountTriggersEnabled = true;
+        m_bAddOGRFeatureCountTriggers = false;
+        m_bFeatureCountTriggersDeletedInTransaction = false;
+
+        CPLDebug("GPKG", "Creating insert/delete feature_count triggers");
+        char* pszSQL = sqlite3_mprintf(
+            "CREATE TRIGGER \"trigger_insert_feature_count_%w\" "
+            "AFTER INSERT ON \"%w\" "
+            "BEGIN UPDATE gpkg_ogr_contents SET feature_count = "
+            "feature_count + 1 WHERE table_name = '%q'; END;",
+            pszTableName, pszTableName, pszTableName);
+        SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+
+        pszSQL = sqlite3_mprintf(
+            "CREATE TRIGGER \"trigger_delete_feature_count_%w\" "
+            "AFTER DELETE ON \"%w\" "
+            "BEGIN UPDATE gpkg_ogr_contents SET feature_count = "
+            "feature_count - 1 WHERE table_name = '%q'; END;",
+            pszTableName, pszTableName, pszTableName);
+        SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+    }
+}
+
+/************************************************************************/
+/*                      DisableTriggers()                               */
+/************************************************************************/
+
+void OGRGeoPackageTableLayer::DisableTriggers(bool bNullifyFeatureCount)
+{
+    if( m_bOGRFeatureCountTriggersEnabled )
+    {
+        m_bOGRFeatureCountTriggersEnabled = false;
+        m_bAddOGRFeatureCountTriggers = true;
+        m_bFeatureCountTriggersDeletedInTransaction =
+            m_poDS->IsInTransaction();
+
+        CPLDebug("GPKG", "Deleting insert/delete feature_count triggers");
+
+        char* pszSQL = sqlite3_mprintf(
+            "DROP TRIGGER \"trigger_insert_feature_count_%w\"",
+            m_pszTableName);
+        SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+
+        pszSQL = sqlite3_mprintf(
+            "DROP TRIGGER \"trigger_delete_feature_count_%w\"",
+            m_pszTableName);
+        SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+
+        if( m_poDS->m_bHasGPKGOGRContents && bNullifyFeatureCount )
+        {
+            pszSQL = sqlite3_mprintf(
+                "UPDATE gpkg_ogr_contents SET feature_count = NULL WHERE "
+                "table_name = '%q'",
+                m_pszTableName);
+            SQLCommand(m_poDS->GetDB(), pszSQL);
+            sqlite3_free(pszSQL);
+        }
+    }
+}
+
+#endif // #ifdef ENABLE_GPKG_OGR_CONTENTS
+
 /************************************************************************/
 /*                      ICreateFeature()                                 */
 /************************************************************************/
@@ -1180,17 +1450,22 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
 {
     if( !m_poDS->GetUpdate() )
     {
-    {
         CPLError( CE_Failure, CPLE_NotSupported,
                   UNSUPPORTED_OP_READ_ONLY,
                   "CreateFeature");
         return OGRERR_FAILURE;
     }
-    }
 
     if( m_bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( m_bOGRFeatureCountTriggersEnabled )
+    {
+        DisableTriggers();
+    }
+#endif
+
     /* Substitute default values for null Date/DateTime fields as the standard */
     /* format of SQLite is not the one mandated by GeoPackage */
     poFeature->FillUnsetWithDefault(FALSE, NULL);
@@ -1204,7 +1479,6 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
         if( pszDefault != NULL )
         {
             bHasDefaultValue = true;
-            break;
         }
     }
 
@@ -1213,7 +1487,7 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
     {
         if( poFeature->GetFID() == OGRNullFID )
         {
-            if( poFeature->IsFieldSet( m_iFIDAsRegularColumnIndex ) )
+            if( poFeature->IsFieldSetAndNotNull( m_iFIDAsRegularColumnIndex ) )
             {
                 poFeature->SetFID(
                     poFeature->GetFieldAsInteger64(m_iFIDAsRegularColumnIndex));
@@ -1221,7 +1495,7 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
         else
         {
-            if( !poFeature->IsFieldSet( m_iFIDAsRegularColumnIndex ) ||
+            if( !poFeature->IsFieldSetAndNotNull( m_iFIDAsRegularColumnIndex ) ||
                 poFeature->GetFieldAsInteger64(m_iFIDAsRegularColumnIndex) != poFeature->GetFID() )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
@@ -1261,7 +1535,8 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     /* Bind values onto the statement now */
     OGRErr errOgr = FeatureBindInsertParameters(poFeature, m_poInsertStatement,
-                                                m_bInsertStatementWithFID, !bHasDefaultValue);
+                                                m_bInsertStatementWithFID,
+                                                !bHasDefaultValue);
     if ( errOgr != OGRERR_NONE )
     {
         sqlite3_reset(m_poInsertStatement);
@@ -1304,7 +1579,7 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     /* Read the latest FID value */
     GIntBig nFID = sqlite3_last_insert_rowid(m_poDS->GetDB());
-    if( nFID )
+    if( nFID || poFeature->GetFID() == 0 )
     {
         poFeature->SetFID(nFID);
         if( m_iFIDAsRegularColumnIndex >= 0 )
@@ -1315,13 +1590,17 @@ OGRErr OGRGeoPackageTableLayer::ICreateFeature( OGRFeature *poFeature )
         poFeature->SetFID(OGRNullFID);
     }
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( m_nTotalFeatureCount >= 0 )
+        m_nTotalFeatureCount++;
+#endif
+
     m_bContentChanged = true;
 
     /* All done! */
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                          ISetFeature()                                */
 /************************************************************************/
@@ -1347,7 +1626,7 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
     /* In case the FID column has also been created as a regular field */
     if( m_iFIDAsRegularColumnIndex >= 0 )
     {
-        if( !poFeature->IsFieldSet( m_iFIDAsRegularColumnIndex ) ||
+        if( !poFeature->IsFieldSetAndNotNull( m_iFIDAsRegularColumnIndex ) ||
             poFeature->GetFieldAsInteger64(m_iFIDAsRegularColumnIndex) != poFeature->GetFID() )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -1368,7 +1647,7 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
             /* Construct a SQL INSERT statement from the OGRFeature */
             /* Only work with fields that are set */
             /* Do not stick values into SQL, use placeholder and bind values later */
-            CPLString osCommand = FeatureGenerateInsertSQL(poFeature, true, true);
+            CPLString osCommand = FeatureGenerateInsertSQL(poFeature, true);
 
             /* Prepare the SQL into a statement */
             int err = sqlite3_prepare_v2(m_poDS->GetDB(), osCommand, -1, &m_poUpdateStatement, NULL);
@@ -1391,7 +1670,7 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
             return errOgr;
 
         /* Bind values onto the statement now */
-        errOgr = FeatureBindInsertParameters(poFeature, m_poUpdateStatement, true, true);
+        errOgr = FeatureBindInsertParameters(poFeature, m_poUpdateStatement, true);
         if ( errOgr != OGRERR_NONE )
             return errOgr;
     }
@@ -1404,6 +1683,8 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
             /* Only work with fields that are set */
             /* Do not stick values into SQL, use placeholder and bind values later */
             CPLString osCommand = FeatureGenerateUpdateSQL(poFeature);
+            if( osCommand.empty() )
+                return OGRERR_NONE;
 
             /* Prepare the SQL into a statement */
             int err = sqlite3_prepare_v2(m_poDS->GetDB(), osCommand, -1, &m_poUpdateStatement, NULL);
@@ -1459,8 +1740,6 @@ OGRErr OGRGeoPackageTableLayer::ISetFeature( OGRFeature *poFeature )
     return eErr;
 }
 
-
-
 /************************************************************************/
 /*                         SetAttributeFilter()                         */
 /************************************************************************/
@@ -1483,7 +1762,6 @@ OGRErr OGRGeoPackageTableLayer::SetAttributeFilter( const char *pszQuery )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                      ResetReading()                                  */
 /************************************************************************/
@@ -1508,10 +1786,8 @@ void OGRGeoPackageTableLayer::ResetReading()
     }
 
     BuildColumns();
-    return;
 }
 
-
 /************************************************************************/
 /*                           ResetStatement()                           */
 /************************************************************************/
@@ -1525,21 +1801,66 @@ OGRErr OGRGeoPackageTableLayer::ResetStatement()
     /* so job #1 is to prepare the statement. */
     /* Append the attribute filter, if there is one */
     CPLString soSQL;
-    if ( m_soFilter.length() > 0 )
-        soSQL.Printf("SELECT %s FROM \"%s\" WHERE %s",
+    if ( !m_soFilter.empty() )
+    {
+        soSQL.Printf("SELECT %s FROM \"%s\" m WHERE %s",
                      m_soColumns.c_str(),
-                     SQLEscapeDoubleQuote(m_pszTableName).c_str(),
+                     SQLEscapeName(m_pszTableName).c_str(),
                      m_soFilter.c_str());
+
+        if ( m_poFilterGeom != NULL && m_pszAttrQueryString == NULL &&
+            HasSpatialIndex() )
+        {
+            OGREnvelope  sEnvelope;
+
+            m_poFilterGeom->getEnvelope( &sEnvelope );
+
+            bool bUseSpatialIndex = true;
+            if( m_poExtent &&
+                sEnvelope.MinX <= m_poExtent->MinX &&
+                sEnvelope.MinY <= m_poExtent->MinY &&
+                sEnvelope.MaxX >= m_poExtent->MaxX &&
+                sEnvelope.MaxY >= m_poExtent->MaxY )
+            {
+                // Selecting from spatial filter on whole extent can be rather
+                // slow. So use function based filtering, just in case the
+                // advertized global extent might be wrong. Otherwise we might
+                // just discard completely the spatial filter.
+                bUseSpatialIndex = false;
+            }
+
+            if( bUseSpatialIndex &&
+                !CPLIsInf(sEnvelope.MinX) && !CPLIsInf(sEnvelope.MinY) &&
+                !CPLIsInf(sEnvelope.MaxX) && !CPLIsInf(sEnvelope.MaxY) )
+            {
+                soSQL.Printf("SELECT %s FROM \"%s\" m "
+                             "JOIN \"%s\" r "
+                             "ON m.\"%s\" = r.id WHERE "
+                             "r.maxx >= %.12f AND r.minx <= %.12f AND "
+                             "r.maxy >= %.12f AND r.miny <= %.12f",
+                             m_soColumns.c_str(),
+                             SQLEscapeName(m_pszTableName).c_str(),
+                             SQLEscapeName(m_osRTreeName).c_str(),
+                             SQLEscapeName(m_osFIDForRTree).c_str(),
+                             sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
+                             sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
+            }
+        }
+    }
     else
-        soSQL.Printf("SELECT %s FROM \"%s\" ",
+        soSQL.Printf("SELECT %s FROM \"%s\" m",
                      m_soColumns.c_str(),
-                     SQLEscapeDoubleQuote(m_pszTableName).c_str());
+                     SQLEscapeName(m_pszTableName).c_str());
+
+    CPLDebug("GPKG", "ResetStatement(%s)", soSQL.c_str());
 
-    int err = sqlite3_prepare(m_poDS->GetDB(), soSQL.c_str(), -1, &m_poQueryStatement, NULL);
+    int err = sqlite3_prepare_v2(
+        m_poDS->GetDB(), soSQL.c_str(), -1, &m_poQueryStatement, NULL);
     if ( err != SQLITE_OK )
     {
         m_poQueryStatement = NULL;
-        CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL: %s", soSQL.c_str());
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "failed to prepare SQL: %s", soSQL.c_str());
         return OGRERR_FAILURE;
     }
 
@@ -1571,10 +1892,6 @@ OGRFeature* OGRGeoPackageTableLayer::GetNextFeature()
 
 OGRFeature* OGRGeoPackageTableLayer::GetFeature(GIntBig nFID)
 {
-    /* No FID, no answer. */
-    if (nFID == OGRNullFID || m_pszFidColumn == NULL )
-        return NULL;
-
     if( m_bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return NULL;
 
@@ -1583,34 +1900,36 @@ OGRFeature* OGRGeoPackageTableLayer::GetFeature(GIntBig nFID)
     /* Clear out any existing query */
     ResetReading();
 
+    if( m_pszFidColumn == NULL )
+        return OGRLayer::GetFeature(nFID);
+
     /* No filters apply, just use the FID */
     CPLString soSQL;
-    soSQL.Printf("SELECT %s FROM \"%s\" WHERE \"%s\" = " CPL_FRMT_GIB,
+    soSQL.Printf("SELECT %s FROM \"%s\" m "
+                 "WHERE \"%s\" = " CPL_FRMT_GIB,
                  m_soColumns.c_str(),
-                 SQLEscapeDoubleQuote(m_pszTableName).c_str(),
-                 SQLEscapeDoubleQuote(m_pszFidColumn).c_str(), nFID);
+                 SQLEscapeName(m_pszTableName).c_str(),
+                 SQLEscapeName(m_pszFidColumn).c_str(),
+                 nFID);
 
-    int err = sqlite3_prepare(m_poDS->GetDB(), soSQL.c_str(), -1, &m_poQueryStatement, NULL);
+    int err = sqlite3_prepare_v2(
+        m_poDS->GetDB(), soSQL.c_str(), -1, &m_poQueryStatement, NULL);
     if ( err != SQLITE_OK )
     {
         m_poQueryStatement = NULL;
-        CPLError( CE_Failure, CPLE_AppDefined, "failed to prepare SQL: %s", soSQL.c_str());
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "failed to prepare SQL: %s", soSQL.c_str());
         return NULL;
     }
 
     /* Should be only one or zero results */
     err = sqlite3_step(m_poQueryStatement);
 
-    /* Nothing left in statement? NULL return indicates to caller */
-    /* that there are no features left */
-    if ( err == SQLITE_DONE )
-        return NULL;
-
     /* Aha, got one */
     if ( err == SQLITE_ROW )
     {
         OGRFeature* poFeature = TranslateFeature(m_poQueryStatement);
-        if( poFeature && m_iFIDAsRegularColumnIndex >= 0 )
+        if( m_iFIDAsRegularColumnIndex >= 0 )
         {
             poFeature->SetField(m_iFIDAsRegularColumnIndex, poFeature->GetFID());
         }
@@ -1639,24 +1958,24 @@ OGRErr OGRGeoPackageTableLayer::DeleteFeature(GIntBig nFID)
         return OGRERR_FAILURE;
     }
 
-    /* No FID, no answer. */
-    if (nFID == OGRNullFID)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, "delete feature called with null FID");
-        return OGRERR_FAILURE;
-    }
-
     if( m_bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( m_bOGRFeatureCountTriggersEnabled )
+    {
+        DisableTriggers();
+    }
+#endif
+
     /* Clear out any existing query */
     ResetReading();
 
     /* No filters apply, just use the FID */
     CPLString soSQL;
     soSQL.Printf("DELETE FROM \"%s\" WHERE \"%s\" = " CPL_FRMT_GIB,
-                 SQLEscapeDoubleQuote(m_pszTableName).c_str(),
-                 SQLEscapeDoubleQuote(m_pszFidColumn).c_str(), nFID);
+                 SQLEscapeName(m_pszTableName).c_str(),
+                 SQLEscapeName(m_pszFidColumn).c_str(), nFID);
 
     OGRErr eErr = SQLCommand(m_poDS->GetDB(), soSQL.c_str());
     if( eErr == OGRERR_NONE )
@@ -1664,7 +1983,14 @@ OGRErr OGRGeoPackageTableLayer::DeleteFeature(GIntBig nFID)
         eErr = (sqlite3_changes(m_poDS->GetDB()) > 0) ? OGRERR_NONE : OGRERR_NON_EXISTING_FEATURE;
 
         if( eErr == OGRERR_NONE )
+        {
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+            if( m_nTotalFeatureCount >= 0 )
+                m_nTotalFeatureCount--;
+#endif
+
             m_bContentChanged = true;
+        }
     }
     return eErr;
 }
@@ -1678,8 +2004,19 @@ OGRErr OGRGeoPackageTableLayer::SyncToDisk()
     if( m_bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return OGRERR_FAILURE;
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    CreateTriggers();
+#endif
+
+    if( !m_bDropRTreeTable )
+    {
+        CreateSpatialIndexIfNecessary();
+    }
+
+    /* Save metadata back to the database */
     SaveExtent();
     SaveTimestamp();
+
     return OGRERR_NONE;
 }
 
@@ -1692,7 +2029,6 @@ OGRErr OGRGeoPackageTableLayer::StartTransaction()
     return m_poDS->StartTransaction();
 }
 
-
 /************************************************************************/
 /*                        CommitTransaction()                           */
 /************************************************************************/
@@ -1702,7 +2038,6 @@ OGRErr OGRGeoPackageTableLayer::CommitTransaction()
     return m_poDS->CommitTransaction();
 }
 
-
 /************************************************************************/
 /*                        RollbackTransaction()                         */
 /************************************************************************/
@@ -1712,13 +2047,47 @@ OGRErr OGRGeoPackageTableLayer::RollbackTransaction()
     return m_poDS->RollbackTransaction();
 }
 
-
 /************************************************************************/
 /*                        GetFeatureCount()                             */
 /************************************************************************/
 
-GIntBig OGRGeoPackageTableLayer::GetFeatureCount( CPL_UNUSED int bForce )
+GIntBig OGRGeoPackageTableLayer::GetFeatureCount( int /*bForce*/ )
 {
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( m_poFilterGeom == NULL && m_pszAttrQueryString == NULL )
+    {
+        if( m_nTotalFeatureCount >= 0 )
+        {
+            return m_nTotalFeatureCount;
+        }
+
+        if( m_poDS->m_bHasGPKGOGRContents )
+        {
+            char* pszSQL = sqlite3_mprintf(
+                "SELECT feature_count FROM gpkg_ogr_contents WHERE "
+                "table_name = '%q' LIMIT 2",
+                m_pszTableName);
+            SQLResult oResult;
+            OGRErr err = SQLQuery( m_poDS->GetDB(), pszSQL, &oResult);
+            sqlite3_free(pszSQL);
+            if( err == OGRERR_NONE && oResult.nRowCount == 1 )
+            {
+                const char* pszFeatureCount =
+                                            SQLResultGetValue(&oResult, 0, 0);
+                if( pszFeatureCount )
+                {
+                    m_nTotalFeatureCount = CPLAtoGIntBig(pszFeatureCount);
+                }
+            }
+            SQLResultFree( &oResult );
+            if( m_nTotalFeatureCount >= 0 )
+            {
+                return m_nTotalFeatureCount;
+            }
+        }
+    }
+#endif
+
     if( m_poFilterGeom != NULL && !m_bFilterIsEnvelope )
         return OGRGeoPackageLayer::GetFeatureCount();
 
@@ -1728,25 +2097,65 @@ GIntBig OGRGeoPackageTableLayer::GetFeatureCount( CPL_UNUSED int bForce )
     /* Ignore bForce, because we always do a full count on the database */
     OGRErr err;
     CPLString soSQL;
-    if ( m_soFilter.length() > 0 )
-        soSQL.Printf("SELECT Count(*) FROM \"%s\" WHERE %s",
-                     SQLEscapeDoubleQuote(m_pszTableName).c_str(),
-                     m_soFilter.c_str());
-    else
-        soSQL.Printf("SELECT Count(*) FROM \"%s\" ",
-                     SQLEscapeDoubleQuote(m_pszTableName).c_str());
+    if ( m_bIsTable && m_poFilterGeom != NULL && m_pszAttrQueryString == NULL &&
+        HasSpatialIndex() )
+    {
+        OGREnvelope  sEnvelope;
+
+        m_poFilterGeom->getEnvelope( &sEnvelope );
+
+        if( !CPLIsInf(sEnvelope.MinX) && !CPLIsInf(sEnvelope.MinY) &&
+            !CPLIsInf(sEnvelope.MaxX) && !CPLIsInf(sEnvelope.MaxY) )
+        {
+            soSQL.Printf("SELECT COUNT(*) FROM \"%s\" WHERE "
+                         "maxx >= %.12f AND minx <= %.12f AND "
+                         "maxy >= %.12f AND miny <= %.12f",
+                         SQLEscapeName(m_osRTreeName).c_str(),
+                         sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
+                         sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
+        }
+    }
+
+    if( soSQL.empty() )
+    {
+        if ( !m_soFilter.empty() )
+            soSQL.Printf("SELECT Count(*) FROM \"%s\" WHERE %s",
+                         SQLEscapeName(m_pszTableName).c_str(),
+                         m_soFilter.c_str());
+        else
+            soSQL.Printf("SELECT Count(*) FROM \"%s\"",
+                         SQLEscapeName(m_pszTableName).c_str());
+    }
 
     /* Just run the query directly and get back integer */
     GIntBig iFeatureCount = SQLGetInteger64(m_poDS->GetDB(), soSQL.c_str(), &err);
 
     /* Generic implementation uses -1 for error condition, so we will too */
     if ( err == OGRERR_NONE )
+    {
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+        if( m_bIsTable && m_poFilterGeom == NULL && m_pszAttrQueryString == NULL )
+        {
+            m_nTotalFeatureCount = iFeatureCount;
+
+            if( m_poDS->GetUpdate() && m_poDS->m_bHasGPKGOGRContents )
+            {
+                const char* pszCount = CPLSPrintf(CPL_FRMT_GIB,
+                                                  m_nTotalFeatureCount);
+                char* pszSQL = sqlite3_mprintf(
+                    "UPDATE gpkg_ogr_contents SET feature_count = %s WHERE "
+                    "table_name = '%q'", pszCount, m_pszTableName);
+                SQLCommand(m_poDS->GetDB(), pszSQL);
+                sqlite3_free(pszSQL);
+            }
+        }
+#endif
         return iFeatureCount;
+    }
     else
         return -1;
 }
 
-
 /************************************************************************/
 /*                        GetExtent()                                   */
 /************************************************************************/
@@ -1769,20 +2178,33 @@ OGRErr OGRGeoPackageTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     /* User is OK with expensive calculation, fall back to */
     /* default implementation (scan all features) and save */
     /* the result for later */
-    if ( bForce )
+    if ( bForce && m_poFeatureDefn->GetGeomFieldCount() )
     {
-        OGRErr err = OGRLayer::GetExtent(psExtent, bForce);
+        const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT MIN(ST_MinX(\"%w\")), MIN(ST_MinY(\"%w\")), "
+            "MAX(ST_MaxX(\"%w\")), MAX(ST_MaxY(\"%w\")) FROM \"%w\" WHERE "
+            "\"%w\" IS NOT NULL AND NOT ST_IsEmpty(\"%w\")",
+            pszC, pszC, pszC, pszC, m_pszTableName, pszC, pszC);
+        SQLResult oResult;
+        OGRErr err = SQLQuery( m_poDS->GetDB(), pszSQL, &oResult);
+        sqlite3_free(pszSQL);
         delete m_poExtent;
         m_poExtent = NULL;
-        if( err == OGRERR_NONE )
+        if( err == OGRERR_NONE && oResult.nRowCount == 1 &&
+            SQLResultGetValue(&oResult, 0, 0) != NULL )
         {
+            psExtent->MinX = CPLAtof(SQLResultGetValue(&oResult, 0, 0));
+            psExtent->MinY = CPLAtof(SQLResultGetValue(&oResult, 1, 0));
+            psExtent->MaxX = CPLAtof(SQLResultGetValue(&oResult, 2, 0));
+            psExtent->MaxY = CPLAtof(SQLResultGetValue(&oResult, 3, 0));
             m_poExtent = new OGREnvelope( *psExtent );
             m_bExtentChanged = true;
             SaveExtent();
         }
         else
         {
-            char *pszSQL = sqlite3_mprintf(
+            pszSQL = sqlite3_mprintf(
                 "UPDATE gpkg_contents SET "
                 "min_x = NULL, min_y = NULL, "
                 "max_x = NULL, max_y = NULL "
@@ -1792,7 +2214,9 @@ OGRErr OGRGeoPackageTableLayer::GetExtent(OGREnvelope *psExtent, int bForce)
             SQLCommand( m_poDS->GetDB(), pszSQL);
             sqlite3_free(pszSQL);
             m_bExtentChanged = false;
+            err = OGRERR_FAILURE; // we didn't get an extent
         }
+        SQLResultFree(&oResult);
         return err;
     }
 
@@ -1818,31 +2242,44 @@ void OGRGeoPackageTableLayer::RecomputeExtent()
 
 int OGRGeoPackageTableLayer::TestCapability ( const char * pszCap )
 {
-    if ( EQUAL(pszCap, OLCCreateField) ||
-         EQUAL(pszCap, OLCSequentialWrite) ||
-         EQUAL(pszCap, OLCDeleteFeature) ||
-         EQUAL(pszCap, OLCRandomWrite) ||
-         EQUAL(pszCap, OLCDeleteField) ||
-         EQUAL(pszCap, OLCAlterFieldDefn) ||
-         EQUAL(pszCap, OLCReorderFields) )
+    if ( EQUAL(pszCap, OLCSequentialWrite) )
     {
         return m_poDS->GetUpdate();
     }
-    else if ( EQUAL(pszCap, OLCRandomRead) ||
-              EQUAL(pszCap, OLCTransactions) )
+    else if ( EQUAL(pszCap, OLCCreateField) ||
+              EQUAL(pszCap, OLCDeleteField) ||
+              EQUAL(pszCap, OLCAlterFieldDefn) ||
+              EQUAL(pszCap, OLCReorderFields) )
+    {
+        return m_poDS->GetUpdate() && m_bIsTable;
+    }
+    else if ( EQUAL(pszCap, OLCDeleteFeature) ||
+              EQUAL(pszCap, OLCRandomWrite) )
+    {
+        return m_poDS->GetUpdate() && m_pszFidColumn != NULL;
+    }
+    else if ( EQUAL(pszCap, OLCRandomRead) )
+    {
+        return m_pszFidColumn != NULL;
+    }
+    else if ( EQUAL(pszCap, OLCTransactions) )
     {
         return TRUE;
     }
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    else if ( EQUAL(pszCap, OLCFastFeatureCount) )
+    {
+        return  m_poFilterGeom == NULL && m_pszAttrQueryString == NULL &&
+                m_nTotalFeatureCount >= 0;
+    }
+#endif
     else if ( EQUAL(pszCap, OLCFastSpatialFilter) )
     {
-        return HasSpatialIndex();
+        return HasSpatialIndex() || m_bDeferredSpatialIndexCreation;
     }
     else if ( EQUAL(pszCap, OLCFastGetExtent) )
     {
-        if ( m_poExtent )
-            return TRUE;
-        else
-            return FALSE;
+        return ( m_poExtent != NULL );
     }
     else if( EQUAL(pszCap,OLCCurveGeometries) )
         return TRUE;
@@ -1870,10 +2307,22 @@ void OGRGeoPackageTableLayer::CreateSpatialIndexIfNecessary()
 /*                       CreateSpatialIndex()                           */
 /************************************************************************/
 
+typedef struct
+{
+    GIntBig nId;
+    double  dfMinX;
+    double  dfMinY;
+    double  dfMaxX;
+    double  dfMaxY;
+} GPKGRTreeEntry;
+
 bool OGRGeoPackageTableLayer::CreateSpatialIndex(const char* pszTableName)
 {
     OGRErr err;
 
+    if( !CheckUpdatableTable("CreateSpatialIndex") )
+        return false;
+
     if( m_bDeferredCreation && RunDeferredCreationIfNecessary() != OGRERR_NONE )
         return false;
 
@@ -1890,7 +2339,7 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex(const char* pszTableName)
 
     if( m_poFeatureDefn->GetGeomFieldCount() == 0 )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "Spatial index already existing");
+        CPLError(CE_Failure, CPLE_AppDefined, "No geometry column");
         return false;
     }
     if( m_poDS->CreateExtensionsTableIfNecessary() != OGRERR_NONE )
@@ -1900,29 +2349,21 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex(const char* pszTableName)
     const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
     const char* pszI = GetFIDColumn();
 
-    m_poDS->SoftStartTransaction();
+    m_osRTreeName = "rtree_";
+    m_osRTreeName += pszT;
+    m_osRTreeName += "_";
+    m_osRTreeName += pszC;
+    m_osFIDForRTree = m_pszFidColumn;
 
-    /* Register the table in gpkg_extensions */
-    char* pszSQL = sqlite3_mprintf(
-        "INSERT INTO gpkg_extensions "
-        "(table_name,column_name,extension_name,definition,scope) "
-        "VALUES ('%q', '%q', 'gpkg_rtree_index', "
-        "'GeoPackage 1.0 Specification Annex L', 'write-only')",
-        pszT, pszC );
-    err = SQLCommand(m_poDS->GetDB(), pszSQL);
-    sqlite3_free(pszSQL);
-    if( err != OGRERR_NONE )
-    {
-        m_poDS->SoftRollbackTransaction();
-        return false;
-    }
+    m_poDS->SoftStartTransaction();
 
+    char* pszSQL;
     /* Create virtual table */
     if( !m_bDropRTreeTable )
     {
         pszSQL = sqlite3_mprintf(
-                    "CREATE VIRTUAL TABLE \"rtree_%w_%w\" USING rtree(id, minx, maxx, miny, maxy)",
-                    pszT, pszC );
+                    "CREATE VIRTUAL TABLE \"%w\" USING rtree(id, minx, maxx, miny, maxy)",
+                    m_osRTreeName.c_str() );
         err = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
         if( err != OGRERR_NONE )
@@ -1934,10 +2375,13 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex(const char* pszTableName)
     m_bDropRTreeTable = false;
 
     /* Populate the RTree */
+#ifdef NO_PROGRESSIVE_RTREE_INSERTION
     pszSQL = sqlite3_mprintf(
-                 "INSERT OR REPLACE INTO \"rtree_%w_%w\" "
-                 "SELECT \"%w\", st_minx(\"%w\"), st_maxx(\"%w\"), st_miny(\"%w\"), st_maxy(\"%w\") FROM \"%w\"",
-                 pszT, pszC, pszI, pszC, pszC, pszC, pszC, pszT );
+        "INSERT INTO \"%w\" "
+        "SELECT \"%w\", ST_MinX(\"%w\"), ST_MaxX(\"%w\"), "
+        "ST_MinY(\"%w\"), ST_MaxY(\"%w\") FROM \"%w\" "
+        "WHERE \"%w\" NOT NULL AND NOT ST_IsEmpty(\"%w\")",
+        m_osRTreeName.c_str(), pszI, pszC, pszC, pszC, pszC, pszT, pszC, pszC );
     err = SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
     if( err != OGRERR_NONE )
@@ -1945,85 +2389,190 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex(const char* pszTableName)
         m_poDS->SoftRollbackTransaction();
         return false;
     }
+#else
+    pszSQL = sqlite3_mprintf(
+        "SELECT \"%w\", ST_MinX(\"%w\"), ST_MaxX(\"%w\"), "
+        "ST_MinY(\"%w\"), ST_MaxY(\"%w\") FROM \"%w\" "
+        "WHERE \"%w\" NOT NULL AND NOT ST_IsEmpty(\"%w\")",
+            pszI, pszC, pszC, pszC, pszC, pszT, pszC, pszC );
+    sqlite3_stmt* hIterStmt = NULL;
+    if ( sqlite3_prepare_v2(m_poDS->GetDB(), pszSQL, -1, &hIterStmt, NULL)
+                                                            != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "failed to prepare SQL: %s", pszSQL);
+        sqlite3_free(pszSQL);
+        m_poDS->SoftRollbackTransaction();
+        return false;
+    }
+    sqlite3_free(pszSQL);
+
+    pszSQL = sqlite3_mprintf(
+        "INSERT INTO \"%w\" VALUES (?,?,?,?,?)",
+        m_osRTreeName.c_str());
+    sqlite3_stmt* hInsertStmt = NULL;
+    if ( sqlite3_prepare_v2(m_poDS->GetDB(), pszSQL, -1, &hInsertStmt, NULL)
+                                                            != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "failed to prepare SQL: %s", pszSQL);
+        sqlite3_free(pszSQL);
+        sqlite3_finalize(hIterStmt);
+        m_poDS->SoftRollbackTransaction();
+        return false;
+    }
+    sqlite3_free(pszSQL);
+
+    // Insert entries in RTree by chuncks of 100000
+    std::vector<GPKGRTreeEntry> aoEntries;
+    GUIntBig nEntryCount = 0;
+    const size_t nChunkSize = 100000;
+    while( true )
+    {
+        int sqlite_err = sqlite3_step(hIterStmt);
+        bool bFinished = false;
+        if( sqlite_err == SQLITE_ROW )
+        {
+            GPKGRTreeEntry sEntry;
+            sEntry.nId = sqlite3_column_int64(hIterStmt, 0);
+            sEntry.dfMinX = sqlite3_column_double(hIterStmt, 1);
+            sEntry.dfMaxX = sqlite3_column_double(hIterStmt, 2);
+            sEntry.dfMinY = sqlite3_column_double(hIterStmt, 3);
+            sEntry.dfMaxY = sqlite3_column_double(hIterStmt, 4);
+            aoEntries.push_back(sEntry);
+        }
+        else if( sqlite_err == SQLITE_DONE )
+        {
+            bFinished = true;
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "failed to iterate over features while inserting in "
+                      "RTree: %s",
+                      sqlite3_errmsg( m_poDS->GetDB() ) );
+            sqlite3_finalize(hIterStmt);
+            sqlite3_finalize(hInsertStmt);
+            m_poDS->SoftRollbackTransaction();
+            return false;
+        }
+
+        if( aoEntries.size() == nChunkSize || bFinished )
+        {
+            for( size_t i = 0; i < aoEntries.size(); ++i )
+            {
+                sqlite3_reset(hInsertStmt);
+
+                sqlite3_bind_int64(hInsertStmt,1,aoEntries[i].nId);
+                sqlite3_bind_double(hInsertStmt,2,aoEntries[i].dfMinX);
+                sqlite3_bind_double(hInsertStmt,3,aoEntries[i].dfMaxX);
+                sqlite3_bind_double(hInsertStmt,4,aoEntries[i].dfMinY);
+                sqlite3_bind_double(hInsertStmt,5,aoEntries[i].dfMaxY);
+                sqlite_err = sqlite3_step(hInsertStmt);
+                if ( sqlite_err != SQLITE_OK && sqlite_err != SQLITE_DONE )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "failed to execute insertion in RTree : %s",
+                              sqlite3_errmsg( m_poDS->GetDB() ) );
+                    sqlite3_finalize(hIterStmt);
+                    sqlite3_finalize(hInsertStmt);
+                    m_poDS->SoftRollbackTransaction();
+                    return false;
+                }
+            }
+
+            nEntryCount += aoEntries.size();
+            CPLDebug("GPKG", CPL_FRMT_GUIB " rows inserted into %s",
+                     nEntryCount, m_osRTreeName.c_str());
+
+            aoEntries.clear();
+            if( bFinished )
+                break;
+        }
+    }
+
+    sqlite3_finalize(hIterStmt);
+    sqlite3_finalize(hInsertStmt);
+#endif
+
+    CPLString osSQL;
+
+    /* Register the table in gpkg_extensions */
+    pszSQL = sqlite3_mprintf(
+        "INSERT INTO gpkg_extensions "
+        "(table_name,column_name,extension_name,definition,scope) "
+        "VALUES ('%q', '%q', 'gpkg_rtree_index', "
+        "'GeoPackage 1.0 Specification Annex L', 'write-only')",
+        pszT, pszC );
+    osSQL += pszSQL;
+    sqlite3_free(pszSQL);
 
     /* Define Triggers to Maintain Spatial Index Values */
 
     /* Conditions: Insertion of non-empty geometry
        Actions   : Insert record into rtree */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%w_%w_insert\" AFTER INSERT ON \"%w\" "
+                   "CREATE TRIGGER \"%w_insert\" AFTER INSERT ON \"%w\" "
                    "WHEN (new.\"%w\" NOT NULL AND NOT ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "INSERT OR REPLACE INTO \"rtree_%w_%w\" VALUES ("
+                   "INSERT OR REPLACE INTO \"%w\" VALUES ("
                    "NEW.\"%w\","
                    "ST_MinX(NEW.\"%w\"), ST_MaxX(NEW.\"%w\"),"
                    "ST_MinY(NEW.\"%w\"), ST_MaxY(NEW.\"%w\")"
                    "); "
                    "END",
-                   pszT, pszC, pszT,
+                   m_osRTreeName.c_str(), pszT,
                    pszC, pszC,
-                   pszT, pszC,
+                   m_osRTreeName.c_str(),
                    pszI,
                    pszC, pszC,
                    pszC, pszC);
-    err = SQLCommand(m_poDS->GetDB(), pszSQL);
+    osSQL += ";";
+    osSQL += pszSQL;
     sqlite3_free(pszSQL);
-    if( err != OGRERR_NONE )
-    {
-        m_poDS->SoftRollbackTransaction();
-        return false;
-    }
 
     /* Conditions: Update of geometry column to non-empty geometry
                No row ID change
        Actions   : Update record in rtree */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%w_%w_update1\" AFTER UPDATE OF \"%w\" ON \"%w\" "
+                   "CREATE TRIGGER \"%w_update1\" AFTER UPDATE OF \"%w\" ON \"%w\" "
                    "WHEN OLD.\"%w\" = NEW.\"%w\" AND "
                    "(NEW.\"%w\" NOTNULL AND NOT ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "INSERT OR REPLACE INTO \"rtree_%w_%w\" VALUES ("
+                   "INSERT OR REPLACE INTO \"%w\" VALUES ("
                    "NEW.\"%w\","
                    "ST_MinX(NEW.\"%w\"), ST_MaxX(NEW.\"%w\"),"
                    "ST_MinY(NEW.\"%w\"), ST_MaxY(NEW.\"%w\")"
                    "); "
                    "END",
-                   pszT, pszC, pszC, pszT,
+                   m_osRTreeName.c_str(), pszC, pszT,
                    pszI, pszI,
                    pszC, pszC,
-                   pszT, pszC,
+                   m_osRTreeName.c_str(),
                    pszI,
                    pszC, pszC,
                    pszC, pszC);
-    err = SQLCommand(m_poDS->GetDB(), pszSQL);
+    osSQL += ";";
+    osSQL += pszSQL;
     sqlite3_free(pszSQL);
-    if( err != OGRERR_NONE )
-    {
-        m_poDS->SoftRollbackTransaction();
-        return false;
-    }
 
     /* Conditions: Update of geometry column to empty geometry
                No row ID change
        Actions   : Remove record from rtree */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%w_%w_update2\" AFTER UPDATE OF \"%w\" ON \"%w\" "
+                   "CREATE TRIGGER \"%w_update2\" AFTER UPDATE OF \"%w\" ON \"%w\" "
                    "WHEN OLD.\"%w\" = NEW.\"%w\" AND "
                    "(NEW.\"%w\" ISNULL OR ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "DELETE FROM \"rtree_%w_%w\" WHERE id = OLD.\"%w\"; "
+                   "DELETE FROM \"%w\" WHERE id = OLD.\"%w\"; "
                    "END",
-                   pszT, pszC, pszC, pszT,
+                   m_osRTreeName.c_str(), pszC, pszT,
                    pszI, pszI,
                    pszC, pszC,
-                   pszT, pszC, pszI);
-    err = SQLCommand(m_poDS->GetDB(), pszSQL);
+                   m_osRTreeName.c_str(), pszI);
+    osSQL += ";";
+    osSQL += pszSQL;
     sqlite3_free(pszSQL);
-    if( err != OGRERR_NONE )
-    {
-        m_poDS->SoftRollbackTransaction();
-        return false;
-    }
 
     /* Conditions: Update of any column
                     Row ID change
@@ -2031,69 +2580,64 @@ bool OGRGeoPackageTableLayer::CreateSpatialIndex(const char* pszTableName)
         Actions   : Remove record from rtree for old <i>
                     Insert record into rtree for new <i> */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%w_%w_update3\" AFTER UPDATE OF \"%w\" ON \"%w\" "
+                   "CREATE TRIGGER \"%w_update3\" AFTER UPDATE OF \"%w\" ON \"%w\" "
                    "WHEN OLD.\"%w\" != NEW.\"%w\" AND "
                    "(NEW.\"%w\" NOTNULL AND NOT ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "DELETE FROM \"rtree_%w_%w\" WHERE id = OLD.\"%w\"; "
-                   "INSERT OR REPLACE INTO \"rtree_%w_%w\" VALUES ("
+                   "DELETE FROM \"%w\" WHERE id = OLD.\"%w\"; "
+                   "INSERT OR REPLACE INTO \"%w\" VALUES ("
                    "NEW.\"%w\","
                    "ST_MinX(NEW.\"%w\"), ST_MaxX(NEW.\"%w\"),"
                    "ST_MinY(NEW.\"%w\"), ST_MaxY(NEW.\"%w\")"
                    "); "
                    "END",
-                   pszT, pszC, pszC, pszT,
+                   m_osRTreeName.c_str(), pszC, pszT,
                    pszI, pszI,
                    pszC, pszC,
-                   pszT, pszC, pszI,
-                   pszT, pszC,
+                   m_osRTreeName.c_str(), pszI,
+                   m_osRTreeName.c_str(),
                    pszI,
                    pszC, pszC,
                    pszC, pszC);
-    err = SQLCommand(m_poDS->GetDB(), pszSQL);
+    osSQL += ";";
+    osSQL += pszSQL;
     sqlite3_free(pszSQL);
-    if( err != OGRERR_NONE )
-    {
-        m_poDS->SoftRollbackTransaction();
-        return false;
-    }
 
     /* Conditions: Update of any column
                     Row ID change
                     Empty geometry
         Actions   : Remove record from rtree for old and new <i> */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%w_%w_update4\" AFTER UPDATE ON \"%w\" "
+                   "CREATE TRIGGER \"%w_update4\" AFTER UPDATE ON \"%w\" "
                    "WHEN OLD.\"%w\" != NEW.\"%w\" AND "
                    "(NEW.\"%w\" ISNULL OR ST_IsEmpty(NEW.\"%w\")) "
                    "BEGIN "
-                   "DELETE FROM \"rtree_%w_%w\" WHERE id IN (OLD.\"%w\", NEW.\"%w\"); "
+                   "DELETE FROM \"%w\" WHERE id IN (OLD.\"%w\", NEW.\"%w\"); "
                    "END",
-                   pszT, pszC, pszT,
+                   m_osRTreeName.c_str(), pszT,
                    pszI, pszI,
                    pszC, pszC,
-                   pszT, pszC, pszI, pszI);
-    err = SQLCommand(m_poDS->GetDB(), pszSQL);
+                   m_osRTreeName.c_str(), pszI, pszI);
+    osSQL += ";";
+    osSQL += pszSQL;
     sqlite3_free(pszSQL);
-    if( err != OGRERR_NONE )
-    {
-        m_poDS->SoftRollbackTransaction();
-        return false;
-    }
 
     /* Conditions: Row deleted
         Actions   : Remove record from rtree for old <i> */
     pszSQL = sqlite3_mprintf(
-                   "CREATE TRIGGER \"rtree_%w_%w_delete\" AFTER DELETE ON \"%w\" "
+                   "CREATE TRIGGER \"%w_delete\" AFTER DELETE ON \"%w\" "
                    "WHEN old.\"%w\" NOT NULL "
                    "BEGIN "
-                   "DELETE FROM \"rtree_%w_%w\" WHERE id = OLD.\"%w\"; "
+                   "DELETE FROM \"%w\" WHERE id = OLD.\"%w\"; "
                    "END",
-                   pszT, pszC, pszT,
+                   m_osRTreeName.c_str(), pszT,
                    pszC,
-                   pszT, pszC, pszI);
-    err = SQLCommand(m_poDS->GetDB(), pszSQL);
+                   m_osRTreeName.c_str(), pszI);
+    osSQL += ";";
+    osSQL += pszSQL;
     sqlite3_free(pszSQL);
+
+    err = SQLCommand(m_poDS->GetDB(), osSQL);
     if( err != OGRERR_NONE )
     {
         m_poDS->SoftRollbackTransaction();
@@ -2125,23 +2669,34 @@ void OGRGeoPackageTableLayer::CheckUnknownExtensions()
     if( m_poFeatureDefn->GetGeomFieldCount() == 0 )
     {
         pszSQL = sqlite3_mprintf(
-                    "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE table_name='%q'"
+                    "SELECT extension_name, definition, scope "
+                    "FROM gpkg_extensions WHERE (table_name='%q' "
+                    "AND extension_name IS NOT NULL "
+                    "AND definition IS NOT NULL "
+                    "AND scope IS NOT NULL) "
 #ifdef WORKAROUND_SQLITE3_BUGS
-                    " OR 0"
+                    "OR 0 "
 #endif
+                    "LIMIT 1000" // to avoid denial of service
                     ,pszT );
     }
     else
     {
         pszSQL = sqlite3_mprintf(
-                    "SELECT extension_name, definition, scope FROM gpkg_extensions WHERE (table_name='%q' "
+                    "SELECT extension_name, definition, scope "
+                    "FROM gpkg_extensions WHERE (table_name='%q' "
+                    "AND extension_name IS NOT NULL "
+                    "AND definition IS NOT NULL "
+                    "AND scope IS NOT NULL "
                     "AND column_name='%q' AND extension_name NOT IN ('gpkg_geom_CIRCULARSTRING', "
                     "'gpkg_geom_COMPOUNDCURVE', 'gpkg_geom_CURVEPOLYGON', 'gpkg_geom_MULTICURVE', "
                     "'gpkg_geom_MULTISURFACE', 'gpkg_geom_CURVE', 'gpkg_geom_SURFACE', "
-                    "'gpkg_rtree_index', 'gpkg_geometry_type_trigger', 'gpkg_srs_id_trigger'))"
+                    "'gpkg_geom_POLYHEDRALSURFACE', 'gpkg_geom_TIN', 'gpkg_geom_TRIANGLE', "
+                    "'gpkg_rtree_index', 'gpkg_geometry_type_trigger', 'gpkg_srs_id_trigger')) "
 #ifdef WORKAROUND_SQLITE3_BUGS
-                    " OR 0"
+                    "OR 0"
 #endif
+                    "LIMIT 1000" // to avoid denial of service
                     ,pszT,
                     m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef() );
     }
@@ -2155,9 +2710,6 @@ void OGRGeoPackageTableLayer::CheckUnknownExtensions()
             const char* pszExtName = SQLResultGetValue(&oResultTable, 0, i);
             const char* pszDefinition = SQLResultGetValue(&oResultTable, 1, i);
             const char* pszScope = SQLResultGetValue(&oResultTable, 2, i);
-            if( pszExtName == NULL ) pszExtName = "(null)";
-            if( pszDefinition == NULL ) pszDefinition = "(null)";
-            if( pszScope == NULL ) pszScope = "(null)";
             if( m_poDS->GetUpdate() && EQUAL(pszScope, "write-only") )
             {
                 CPLError(CE_Warning, CPLE_AppDefined,
@@ -2191,10 +2743,41 @@ void OGRGeoPackageTableLayer::CheckUnknownExtensions()
 /*                     CreateGeometryExtensionIfNecessary()             */
 /************************************************************************/
 
+bool OGRGeoPackageTableLayer::CreateGeometryExtensionIfNecessary(
+                                                    const OGRGeometry* poGeom)
+{
+    bool bRet = true;
+    if( poGeom != NULL )
+    {
+        OGRwkbGeometryType eGType = wkbFlatten(poGeom->getGeometryType());
+        if( eGType >= wkbGeometryCollection )
+        {
+            if( eGType > wkbGeometryCollection )
+                CreateGeometryExtensionIfNecessary(eGType);
+            const OGRGeometryCollection* poGC =
+                            dynamic_cast<const OGRGeometryCollection*>(poGeom);
+            if( poGC != NULL )
+            {
+                const int nSubGeoms = poGC->getNumGeometries();
+                for( int i = 0; i < nSubGeoms; i++ )
+                {
+                    bRet &=
+                    CreateGeometryExtensionIfNecessary(poGC->getGeometryRef(i));
+                }
+            }
+        }
+    }
+    return bRet;
+}
+
+/************************************************************************/
+/*                     CreateGeometryExtensionIfNecessary()             */
+/************************************************************************/
+
 bool OGRGeoPackageTableLayer::CreateGeometryExtensionIfNecessary(OGRwkbGeometryType eGType)
 {
     eGType = wkbFlatten(eGType);
-    CPLAssert(eGType <= wkbTIN);
+    CPLAssert(eGType > wkbGeometryCollection && eGType <= wkbTriangle);
     if( m_abHasGeometryExtension[eGType] )
         return true;
 
@@ -2210,19 +2793,26 @@ bool OGRGeoPackageTableLayer::CreateGeometryExtensionIfNecessary(OGRwkbGeometryT
         "SELECT 1 FROM gpkg_extensions WHERE table_name = '%q' AND "
         "column_name = '%q' AND extension_name = 'gpkg_geom_%s'",
          pszT, pszC, pszGeometryType);
-    OGRErr err = OGRERR_NONE;
-    SQLGetInteger(m_poDS->GetDB(), pszSQL, &err);
+    const bool bExists = SQLGetInteger(m_poDS->GetDB(), pszSQL, NULL) == 1;
     sqlite3_free(pszSQL);
 
-    if( err != OGRERR_NONE )
+    if( !bExists )
     {
+        if( eGType == wkbPolyhedralSurface ||
+            eGType == wkbTIN || eGType == wkbTriangle )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Registering non-standard gpkg_geom_%s extension",
+                     pszGeometryType);
+        }
+
         /* Register the table in gpkg_extensions */
         pszSQL = sqlite3_mprintf(
                     "INSERT INTO gpkg_extensions "
                     "(table_name,column_name,extension_name,definition,scope) "
                     "VALUES ('%q', '%q', 'gpkg_geom_%s', 'GeoPackage 1.0 Specification Annex J', 'read-write')",
                     pszT, pszC, pszGeometryType);
-        err = SQLCommand(m_poDS->GetDB(), pszSQL);
+        OGRErr err = SQLCommand(m_poDS->GetDB(), pszSQL);
         sqlite3_free(pszSQL);
         if ( err != OGRERR_NONE )
             return false;
@@ -2242,7 +2832,8 @@ bool OGRGeoPackageTableLayer::HasSpatialIndex()
         return CPL_TO_BOOL(m_bHasSpatialIndex);
     m_bHasSpatialIndex = false;
 
-    if( m_poFeatureDefn->GetGeomFieldCount() == 0 ||
+    if( m_pszFidColumn == NULL ||
+        m_poFeatureDefn->GetGeomFieldCount() == 0 ||
         !m_poDS->HasExtensionsTable() )
         return false;
 
@@ -2256,6 +2847,7 @@ bool OGRGeoPackageTableLayer::HasSpatialIndex()
 #ifdef WORKAROUND_SQLITE3_BUGS
                 " OR 0"
 #endif
+                " LIMIT 2"
                  ,pszT, pszC );
     SQLResult oResultTable;
     OGRErr err = SQLQuery(m_poDS->GetDB(), pszSQL, &oResultTable);
@@ -2263,6 +2855,11 @@ bool OGRGeoPackageTableLayer::HasSpatialIndex()
     if ( err == OGRERR_NONE && oResultTable.nRowCount == 1 )
     {
         m_bHasSpatialIndex = true;
+        m_osRTreeName = "rtree_";
+        m_osRTreeName += pszT;
+        m_osRTreeName += "_";
+        m_osRTreeName += pszC;
+        m_osFIDForRTree = m_pszFidColumn;
     }
     SQLResultFree(&oResultTable);
 
@@ -2275,6 +2872,9 @@ bool OGRGeoPackageTableLayer::HasSpatialIndex()
 
 bool OGRGeoPackageTableLayer::DropSpatialIndex(bool bCalledFromSQLFunction)
 {
+    if( !CheckUpdatableTable("DropSpatialIndex") )
+        return false;
+
     if( !HasSpatialIndex() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Spatial index not existing");
@@ -2282,7 +2882,7 @@ bool OGRGeoPackageTableLayer::DropSpatialIndex(bool bCalledFromSQLFunction)
     }
 
     const char* pszT = m_pszTableName;
-    const char* pszC =m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
+    const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(0)->GetNameRef();
     char* pszSQL = sqlite3_mprintf(
         "DELETE FROM gpkg_extensions WHERE table_name='%q' "
         "AND column_name='%q' AND extension_name='gpkg_rtree_index'",
@@ -2296,36 +2896,42 @@ bool OGRGeoPackageTableLayer::DropSpatialIndex(bool bCalledFromSQLFunction)
         /* remove the content and memorize that we will have to delete the */
         /* table later */
         m_bDropRTreeTable = true;
-        pszSQL = sqlite3_mprintf("DELETE FROM \"rtree_%w_%w\"", pszT, pszC);
+        pszSQL = sqlite3_mprintf("DELETE FROM \"%w\"", m_osRTreeName.c_str());
     }
     else
     {
-        pszSQL = sqlite3_mprintf("DROP TABLE \"rtree_%w_%w\"", pszT, pszC);
+        pszSQL = sqlite3_mprintf("DROP TABLE \"%w\"", m_osRTreeName.c_str());
     }
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_insert\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"%w_insert\"",
+                             m_osRTreeName.c_str());
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_update1\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"%w_update1\"",
+                             m_osRTreeName.c_str());
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_update2\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"%w_update2\"",
+                             m_osRTreeName.c_str());
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_update3\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"%w_update3\"",
+                             m_osRTreeName.c_str());
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_update4\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"%w_update4\"",
+                             m_osRTreeName.c_str());
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
-    pszSQL = sqlite3_mprintf("DROP TRIGGER \"rtree_%w_%w_delete\"", pszT, pszC);
+    pszSQL = sqlite3_mprintf("DROP TRIGGER \"%w_delete\"",
+                             m_osRTreeName.c_str());
     SQLCommand(m_poDS->GetDB(), pszSQL);
     sqlite3_free(pszSQL);
 
@@ -2340,19 +2946,15 @@ bool OGRGeoPackageTableLayer::DropSpatialIndex(bool bCalledFromSQLFunction)
 void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
 {
     ResetReading();
-    RunDeferredCreationIfNecessary();
-    CreateSpatialIndexIfNecessary();
+    SyncToDisk();
 
-    SQLResult oResultTable;
     char* pszSQL = sqlite3_mprintf(
-        "SELECT * FROM sqlite_master WHERE name = '%q' "
+        "SELECT 1 FROM sqlite_master WHERE name = '%q' "
         "AND type IN ('table', 'view')",
          pszDstTableName);
-    OGRErr err = SQLQuery(m_poDS->GetDB(), pszSQL, &oResultTable);
+    const bool bAlreadyExists =
+            SQLGetInteger(m_poDS->GetDB(), pszSQL, NULL) == 1;
     sqlite3_free(pszSQL);
-    const bool bAlreadyExists = ( err == OGRERR_NONE &&
-                                  oResultTable.nRowCount == 1 );
-    SQLResultFree(&oResultTable);
     if( bAlreadyExists )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -2370,6 +2972,10 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
         DropSpatialIndex();
     }
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    DisableTriggers(false);
+#endif
+
     pszSQL = sqlite3_mprintf(
         "UPDATE gpkg_geometry_columns SET table_name = '%q' WHERE "
         "table_name = '%q'",
@@ -2428,6 +3034,18 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
         sqlite3_free(pszSQL);
     }
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+    if( eErr == OGRERR_NONE && m_poDS->m_bHasGPKGOGRContents )
+    {
+        pszSQL = sqlite3_mprintf(
+            "UPDATE gpkg_ogr_contents SET table_name = '%q' WHERE "
+            "table_name = '%q'",
+            pszDstTableName, m_pszTableName);
+        eErr = SQLCommand(m_poDS->GetDB(), pszSQL);
+        sqlite3_free(pszSQL);
+    }
+#endif
+
     if( eErr == OGRERR_NONE )
     {
         pszSQL = sqlite3_mprintf(
@@ -2450,6 +3068,10 @@ void OGRGeoPackageTableLayer::RenameTo(const char* pszDstTableName)
             CreateSpatialIndex(pszDstTableName);
         }
 
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+        CreateTriggers(pszDstTableName);
+#endif
+
         eErr = m_poDS->SoftCommitTransaction();
         if( eErr == OGRERR_NONE)
         {
@@ -2501,39 +3123,57 @@ CPLString OGRGeoPackageTableLayer::GetSpatialWhere(int iGeomColIn,
     if( iGeomColIn < 0 || iGeomColIn >= m_poFeatureDefn->GetGeomFieldCount() )
         return osSpatialWHERE;
 
-    const char* pszT = m_pszTableName;
-    const char* pszC = m_poFeatureDefn->GetGeomFieldDefn(iGeomColIn)->GetNameRef();
-
     if( poFilterGeom != NULL )
     {
         OGREnvelope  sEnvelope;
 
         poFilterGeom->getEnvelope( &sEnvelope );
 
-        if( CPLIsInf(sEnvelope.MinX) || CPLIsInf(sEnvelope.MinY) ||
-            CPLIsInf(sEnvelope.MaxX) || CPLIsInf(sEnvelope.MaxY) )
+        if( CPLIsInf(sEnvelope.MinX) && sEnvelope.MinX < 0 &&
+            CPLIsInf(sEnvelope.MinY) && sEnvelope.MinY < 0 &&
+            CPLIsInf(sEnvelope.MaxX) && sEnvelope.MaxX > 0 &&
+            CPLIsInf(sEnvelope.MaxY) && sEnvelope.MaxY > 0 )
+        {
+            return CPLString();
+        }
+
+        bool bUseSpatialIndex = true;
+        if( m_poExtent &&
+            sEnvelope.MinX <= m_poExtent->MinX &&
+            sEnvelope.MinY <= m_poExtent->MinY &&
+            sEnvelope.MaxX >= m_poExtent->MaxX &&
+            sEnvelope.MaxY >= m_poExtent->MaxY )
         {
-            return osSpatialWHERE;
+            // Selecting from spatial filter on whole extent can be rather
+            // slow. So use function based filtering, just in case the
+            // advertized global extent might be wrong. Otherwise we might
+            // just discard completely the spatial filter.
+            bUseSpatialIndex = false;
         }
 
-        if( HasSpatialIndex() )
+        if( bUseSpatialIndex && HasSpatialIndex() )
         {
-            osSpatialWHERE.Printf("ROWID IN ( SELECT id FROM \"rtree_%s_%s\" WHERE "
-                            "maxx >= %.12f AND minx <= %.12f AND maxy >= %.12f AND miny <= %.12f)",
-                            pszT, pszC,
-                            sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
-                            sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
+            osSpatialWHERE.Printf(
+                "\"%s\" IN ( SELECT id FROM \"%s\" WHERE "
+                "maxx >= %.12f AND minx <= %.12f AND "
+                "maxy >= %.12f AND miny <= %.12f)",
+                SQLEscapeName(m_osFIDForRTree).c_str(),
+                SQLEscapeName(m_osRTreeName).c_str(),
+                sEnvelope.MinX - 1e-11, sEnvelope.MaxX + 1e-11,
+                sEnvelope.MinY - 1e-11, sEnvelope.MaxY + 1e-11);
         }
         else
         {
+            const char* pszC =
+                m_poFeatureDefn->GetGeomFieldDefn(iGeomColIn)->GetNameRef();
             /* A bit inefficient but still faster than OGR filtering */
             osSpatialWHERE.Printf(
-                        "(ST_MaxX(\"%s\") >= %.12f AND ST_MinX(\"%s\") <= %.12f AND "
-                        "ST_MaxY(\"%s\") >= %.12f AND ST_MinY(\"%s\") <= %.12f)",
-                        pszC, sEnvelope.MinX - 1e-11,
-                        pszC, sEnvelope.MaxX + 1e-11,
-                        pszC, sEnvelope.MinY - 1e-11,
-                        pszC, sEnvelope.MaxY + 1e-11);
+                "(ST_MaxX(\"%s\") >= %.12f AND ST_MinX(\"%s\") <= %.12f AND "
+                "ST_MaxY(\"%s\") >= %.12f AND ST_MinY(\"%s\") <= %.12f)",
+                SQLEscapeName(pszC).c_str(), sEnvelope.MinX - 1e-11,
+                SQLEscapeName(pszC).c_str(), sEnvelope.MaxX + 1e-11,
+                SQLEscapeName(pszC).c_str(), sEnvelope.MinY - 1e-11,
+                SQLEscapeName(pszC).c_str(), sEnvelope.MaxY + 1e-11);
         }
     }
 
@@ -2553,14 +3193,14 @@ void OGRGeoPackageTableLayer::BuildWhere()
 
     CPLString osSpatialWHERE = GetSpatialWhere(m_iGeomFieldFilter,
                                                m_poFilterGeom);
-    if (osSpatialWHERE.size() != 0)
+    if (!osSpatialWHERE.empty())
     {
         m_soFilter += osSpatialWHERE;
     }
 
-    if( osQuery.size() > 0 )
+    if( !osQuery.empty() )
     {
-        if( m_soFilter.size() == 0 )
+        if( m_soFilter.empty() )
         {
             m_soFilter += osQuery;
         }
@@ -2571,6 +3211,7 @@ void OGRGeoPackageTableLayer::BuildWhere()
             m_soFilter += ")";
         }
     }
+    CPLDebug("GPKG", "Filter: %s", m_soFilter.c_str());
 }
 
 /************************************************************************/
@@ -2586,16 +3227,14 @@ void OGRGeoPackageTableLayer::SetCreationParameters( OGRwkbGeometryType eGType,
                                                      const char* pszDescription )
 {
     m_bDeferredCreation = true;
+    m_bHasTriedDetectingFID64 = true;
     m_pszFidColumn = CPLStrdup(pszFIDColumnName);
-    m_poFeatureDefn = new OGRFeatureDefn( m_pszTableName );
-    SetDescription( m_poFeatureDefn->GetName() );
-    m_poFeatureDefn->SetGeomType(wkbNone);
-    m_poFeatureDefn->Reference();
+
     if( eGType != wkbNone )
     {
         OGRGeomFieldDefn oGeomFieldDefn(pszGeomColumnName, eGType);
         if( poSRS )
-            m_iSrs = m_poDS->GetSrsId(poSRS);
+            m_iSrs = m_poDS->GetSrsId(*poSRS);
         oGeomFieldDefn.SetSpatialRef(poSRS);
         oGeomFieldDefn.SetNullable(bGeomNullable);
         m_poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
@@ -2640,8 +3279,7 @@ OGRErr OGRGeoPackageTableLayer::RegisterGeometryColumn()
     if ( err != OGRERR_NONE )
         return OGRERR_FAILURE;
 
-    if( OGR_GT_IsNonLinear( eGType ) || wkbFlatten(eGType) == wkbCurve ||
-        wkbFlatten(eGType) == wkbSurface )
+    if( wkbFlatten(eGType) > wkbGeometryCollection )
     {
         CreateGeometryExtensionIfNecessary(eGType);
     }
@@ -2653,7 +3291,7 @@ OGRErr OGRGeoPackageTableLayer::RegisterGeometryColumn()
 /*                        GetColumnsOfCreateTable()                     */
 /************************************************************************/
 
-CPLString OGRGeoPackageTableLayer::GetColumnsOfCreateTable(const std::vector<OGRFieldDefn*> apoFields)
+CPLString OGRGeoPackageTableLayer::GetColumnsOfCreateTable(const std::vector<OGRFieldDefn*>& apoFields)
 {
     CPLString osSQL;
 
@@ -2661,7 +3299,7 @@ CPLString OGRGeoPackageTableLayer::GetColumnsOfCreateTable(const std::vector<OGR
     bool bNeedComma = false;
     if( m_pszFidColumn != NULL )
     {
-        pszSQL = sqlite3_mprintf("\"%w\" INTEGER PRIMARY KEY AUTOINCREMENT",
+        pszSQL = sqlite3_mprintf("\"%w\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL",
                                 m_pszFidColumn);
         osSQL += pszSQL;
         sqlite3_free(pszSQL);
@@ -2759,7 +3397,7 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
     /* Create the table! */
     CPLString osCommand;
 
-    char* pszSQL = sqlite3_mprintf("CREATE TABLE '%q' ( ", pszLayerName);
+    char* pszSQL = sqlite3_mprintf("CREATE TABLE \"%w\" ( ", pszLayerName);
     osCommand += pszSQL;
     sqlite3_free(pszSQL);
 
@@ -2787,13 +3425,15 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
     const bool bIsSpatial = (eGType != wkbNone);
     if ( bIsSpatial )
         err = RegisterGeometryColumn();
-    else if( m_bRegisterAsAspatial )
+    else if( m_eASPatialVariant == OGR_ASPATIAL )
         err = m_poDS->CreateGDALAspatialExtension();
 
     if ( err != OGRERR_NONE )
         return OGRERR_FAILURE;
 
-    if( bIsSpatial || m_bRegisterAsAspatial )
+    if( bIsSpatial ||
+        m_eASPatialVariant == OGR_ASPATIAL ||
+        m_eASPatialVariant == GPKG_ATTRIBUTES )
     {
         const char* pszIdentifier = GetMetadataItem("IDENTIFIER");
         if( pszIdentifier == NULL )
@@ -2810,7 +3450,9 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
 
         pszSQL = sqlite3_mprintf(
             osInsertGpkgContentsFormatting.c_str(),
-            pszLayerName, (bIsSpatial ? "features": "aspatial"),
+            pszLayerName, (bIsSpatial ? "features":
+                          (m_eASPatialVariant == GPKG_ATTRIBUTES) ? "attributes" :
+                          "aspatial"),
             pszIdentifier, pszDescription,
             pszCurrentDate ? pszCurrentDate : "strftime('%Y-%m-%dT%H:%M:%fZ','now')",
             m_iSrs);
@@ -2819,6 +3461,29 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
         sqlite3_free(pszSQL);
         if ( err != OGRERR_NONE )
             return OGRERR_FAILURE;
+
+#ifdef ENABLE_GPKG_OGR_CONTENTS
+        if( m_poDS->m_bHasGPKGOGRContents )
+        {
+            pszSQL = sqlite3_mprintf(
+                "DELETE FROM gpkg_ogr_contents WHERE table_name = '%q'",
+                pszLayerName);
+            SQLCommand(m_poDS->GetDB(), pszSQL);
+            sqlite3_free(pszSQL);
+
+            pszSQL = sqlite3_mprintf(
+                "INSERT INTO gpkg_ogr_contents (table_name, feature_count) "
+                "VALUES ('%q', NULL)",
+                pszLayerName);
+            err = SQLCommand(m_poDS->GetDB(), pszSQL);
+            sqlite3_free(pszSQL);
+            if ( err == OGRERR_NONE )
+            {
+                m_nTotalFeatureCount = 0;
+                m_bAddOGRFeatureCountTriggers = true;
+            }
+        }
+#endif
     }
 
     ResetReading();
@@ -2833,6 +3498,39 @@ OGRErr OGRGeoPackageTableLayer::RunDeferredCreationIfNecessary()
 char **OGRGeoPackageTableLayer::GetMetadata( const char *pszDomain )
 
 {
+    if( !m_bHasTriedDetectingFID64 && m_pszFidColumn != NULL )
+    {
+        m_bHasTriedDetectingFID64 = true;
+
+/* -------------------------------------------------------------------- */
+/*      Find if the FID holds 64bit values                              */
+/* -------------------------------------------------------------------- */
+
+        // Normally the fid should be AUTOINCREMENT, so check sqlite_sequence
+        OGRErr err = OGRERR_NONE;
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT seq FROM sqlite_sequence WHERE name = '%q'",
+            m_pszTableName);
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        GIntBig nMaxId = SQLGetInteger64( m_poDS->GetDB(), pszSQL, &err);
+        CPLPopErrorHandler();
+        sqlite3_free(pszSQL);
+        if( err != OGRERR_NONE )
+        {
+            CPLErrorReset();
+
+            // In case of error, fallback to taking the MAX of the FID
+            pszSQL = sqlite3_mprintf("SELECT MAX(\"%w\") FROM \"%w\"",
+                                        m_pszFidColumn,
+                                        m_pszTableName);
+
+            nMaxId = SQLGetInteger64( m_poDS->GetDB(), pszSQL, NULL);
+            sqlite3_free(pszSQL);
+        }
+        if( nMaxId > INT_MAX )
+            OGRLayer::SetMetadataItem(OLMD_FID64, "YES");
+    }
+
     if( m_bHasReadMetadataFromStorage )
         return OGRLayer::GetMetadata( pszDomain );
 
@@ -2845,7 +3543,11 @@ char **OGRGeoPackageTableLayer::GetMetadata( const char *pszDomain )
         "SELECT md.metadata, md.md_standard_uri, md.mime_type, "
         "mdr.reference_scope FROM gpkg_metadata md "
         "JOIN gpkg_metadata_reference mdr ON (md.id = mdr.md_file_id ) "
-        "WHERE mdr.table_name = '%q' ORDER BY md.id",
+        "WHERE md.metadata IS NOT NULL AND "
+        "md.md_standard_uri IS NOT NULL AND "
+        "md.mime_type IS NOT NULL AND "
+        "mdr.table_name = '%q' ORDER BY md.id "
+        "LIMIT 1000", // to avoid denial of service
         m_pszTableName);
 
     SQLResult oResult;
@@ -2867,10 +3569,8 @@ char **OGRGeoPackageTableLayer::GetMetadata( const char *pszDomain )
         const char* pszMimeType = SQLResultGetValue(&oResult, 2, i);
         //const char* pszReferenceScope = SQLResultGetValue(&oResult, 3, i);
         //int bIsGPKGScope = EQUAL(pszReferenceScope, "geopackage");
-        if( pszMetadata == NULL )
-            continue;
-        if( pszMDStandardURI != NULL && EQUAL(pszMDStandardURI, "http://gdal.org") &&
-            pszMimeType != NULL && EQUAL(pszMimeType, "text/xml") )
+        if( EQUAL(pszMDStandardURI, "http://gdal.org") &&
+            EQUAL(pszMimeType, "text/xml") )
         {
             CPLXMLNode* psXMLNode = CPLParseXMLString(pszMetadata);
             if( psXMLNode )
@@ -2906,10 +3606,8 @@ char **OGRGeoPackageTableLayer::GetMetadata( const char *pszDomain )
         const char* pszMimeType = SQLResultGetValue(&oResult, 2, i);
         //const char* pszReferenceScope = SQLResultGetValue(&oResult, 3, i);
         //int bIsGPKGScope = EQUAL(pszReferenceScope, "geopackage");
-        if( pszMetadata == NULL )
-            continue;
-        if( pszMDStandardURI != NULL && EQUAL(pszMDStandardURI, "http://gdal.org") &&
-            pszMimeType != NULL && EQUAL(pszMimeType, "text/xml") )
+        if( EQUAL(pszMDStandardURI, "http://gdal.org") &&
+            EQUAL(pszMimeType, "text/xml") )
             continue;
 
         /*if( strcmp( pszMDStandardURI, "http://www.isotc211.org/2005/gmd" ) == 0 &&
@@ -2964,9 +3662,9 @@ CPLErr OGRGeoPackageTableLayer::SetMetadata( char ** papszMetadata, const char *
     m_poDS->SetMetadataDirty();
     if( pszDomain == NULL || EQUAL(pszDomain, "") )
     {
-        if( m_osIdentifierLCO.size() )
+        if( !m_osIdentifierLCO.empty() )
             OGRLayer::SetMetadataItem("IDENTIFIER", m_osIdentifierLCO);
-        if( m_osDescriptionLCO.size() )
+        if( !m_osDescriptionLCO.empty() )
             OGRLayer::SetMetadataItem("DESCRIPTION", m_osDescriptionLCO);
     }
     return eErr;
@@ -2981,10 +3679,10 @@ CPLErr OGRGeoPackageTableLayer::SetMetadataItem( const char * pszName,
                                                  const char * pszDomain )
 {
     GetMetadata(); /* force loading from storage if needed */
-    if( m_osIdentifierLCO.size() && EQUAL(pszName, "IDENTIFIER") &&
+    if( !m_osIdentifierLCO.empty() && EQUAL(pszName, "IDENTIFIER") &&
         (pszDomain == NULL || EQUAL(pszDomain, "")) )
         return CE_None;
-    if( m_osDescriptionLCO.size() && EQUAL(pszName, "DESCRIPTION") &&
+    if( !m_osDescriptionLCO.empty() && EQUAL(pszName, "DESCRIPTION") &&
         (pszDomain == NULL || EQUAL(pszDomain, "")) )
         return CE_None;
     m_poDS->SetMetadataDirty();
@@ -3005,7 +3703,7 @@ OGRErr OGRGeoPackageTableLayer::RecreateTable(const CPLString& osColumnsForCreat
 
     char* pszSQL = sqlite3_mprintf(
         "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') "
-        "AND tbl_name='%q'",
+        "AND tbl_name='%q' LIMIT 10000",
         m_pszTableName );
     SQLResult oTriggers;
     OGRErr eErr = SQLQuery(hDB, pszSQL, &oTriggers);
@@ -3075,7 +3773,7 @@ OGRErr OGRGeoPackageTableLayer::RecreateTable(const CPLString& osColumnsForCreat
 /*                          BuildSelectFieldList()                      */
 /************************************************************************/
 
-CPLString OGRGeoPackageTableLayer::BuildSelectFieldList(const std::vector<OGRFieldDefn*> apoFields)
+CPLString OGRGeoPackageTableLayer::BuildSelectFieldList(const std::vector<OGRFieldDefn*>& apoFields)
 {
     CPLString osFieldListForSelect;
 
@@ -3121,36 +3819,13 @@ CPLString OGRGeoPackageTableLayer::BuildSelectFieldList(const std::vector<OGRFie
 }
 
 /************************************************************************/
-/*                               IsTable()                              */
-/************************************************************************/
-
-bool OGRGeoPackageTableLayer::IsTable()
-{
-    SQLResult oResultTable;
-    char* pszSQL = sqlite3_mprintf(
-        "SELECT * FROM sqlite_master WHERE name = '%q' AND type = 'table'",
-         m_pszTableName);
-    OGRErr err = SQLQuery(m_poDS->GetDB(), pszSQL, &oResultTable);
-    sqlite3_free(pszSQL);
-    const bool bIsTable = ( err == OGRERR_NONE &&
-                                  oResultTable.nRowCount == 1 );
-    SQLResultFree(&oResultTable);
-    return bIsTable;
-}
-
-/************************************************************************/
 /*                             DeleteField()                            */
 /************************************************************************/
 
 OGRErr OGRGeoPackageTableLayer::DeleteField( int iFieldToDelete )
 {
-    if ( !m_poDS->GetUpdate() )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  UNSUPPORTED_OP_READ_ONLY,
-                  "DeleteField");
+    if( !CheckUpdatableTable("DeleteField") )
         return OGRERR_FAILURE;
-    }
 
     if (iFieldToDelete < 0 || iFieldToDelete >= m_poFeatureDefn->GetFieldCount())
     {
@@ -3164,17 +3839,6 @@ OGRErr OGRGeoPackageTableLayer::DeleteField( int iFieldToDelete )
     CreateSpatialIndexIfNecessary();
 
 /* -------------------------------------------------------------------- */
-/*      Check that is a table and not a view                            */
-/* -------------------------------------------------------------------- */
-    if( !IsTable() )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Layer %s is not a table",
-                 m_pszTableName);
-        return OGRERR_FAILURE;
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Build list of old fields, and the list of new fields.           */
 /* -------------------------------------------------------------------- */
     std::vector<OGRFieldDefn*> apoFields;
@@ -3268,13 +3932,8 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
                                                 OGRFieldDefn* poNewFieldDefn,
                                                 int nFlagsIn )
 {
-    if ( !m_poDS->GetUpdate() )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  UNSUPPORTED_OP_READ_ONLY,
-                  "AlterFieldDefn");
+    if( !CheckUpdatableTable("AlterFieldDefn") )
         return OGRERR_FAILURE;
-    }
 
     if (iFieldToAlter < 0 || iFieldToAlter >= m_poFeatureDefn->GetFieldCount())
     {
@@ -3284,24 +3943,13 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
     }
 
 /* -------------------------------------------------------------------- */
-/*      Defered actions, reset state.                                   */
+/*      Deferred actions, reset state.                                   */
 /* -------------------------------------------------------------------- */
     ResetReading();
     RunDeferredCreationIfNecessary();
     CreateSpatialIndexIfNecessary();
 
 /* -------------------------------------------------------------------- */
-/*      Check that is a table and not a view                            */
-/* -------------------------------------------------------------------- */
-    if( !IsTable() )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Layer %s is not a table",
-                 m_pszTableName);
-        return OGRERR_FAILURE;
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Check that the new column name is not a duplicate.              */
 /* -------------------------------------------------------------------- */
 
@@ -3398,9 +4046,9 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
         char* pszSQL = sqlite3_mprintf(
             "SELECT name, type, sql FROM sqlite_master WHERE "
             "type IN ('trigger','index') "
-            "AND tbl_name='%q' AND sql LIKE '%%%q%%'",
+            "AND tbl_name='%q' AND sql LIKE '%%%q%%' LIMIT 10000",
             m_pszTableName,
-            SQLEscapeDoubleQuote(osOldColName).c_str() );
+            SQLEscapeName(osOldColName).c_str() );
         eErr = SQLQuery(hDB, pszSQL, &oTriggers);
         sqlite3_free(pszSQL);
 
@@ -3417,7 +4065,7 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
     if( !bUseFastMethod )
     {
 /* -------------------------------------------------------------------- */
-/*      If we are withing a transaction, we cannot use the method       */
+/*      If we are within a transaction, we cannot use the method       */
 /*      that consists in altering the database in a raw way.            */
 /* -------------------------------------------------------------------- */
         const CPLString osFieldListForSelect( BuildSelectFieldList(apoFieldsOld) );
@@ -3431,7 +4079,7 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
     {
 /* -------------------------------------------------------------------- */
 /*      Rewrite schema in a transaction by altering the database        */
-/*      schema in a rather raw way, as discribed at bottom of           */
+/*      schema in a rather raw way, as described at bottom of           */
 /*      https://www.sqlite.org/lang_altertable.html                     */
 /* -------------------------------------------------------------------- */
 
@@ -3561,7 +4209,7 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
                     osSQL += " ON ";
                     osSQL += papszTokens[4];
                     osSQL += "(\"";
-                    osSQL += SQLEscapeDoubleQuote(osNewColName);
+                    osSQL += SQLEscapeName(osNewColName);
                     osSQL += "\")";
                     eErr = SQLCommand(hDB, osSQL);
                 }
@@ -3613,13 +4261,8 @@ OGRErr OGRGeoPackageTableLayer::AlterFieldDefn( int iFieldToAlter,
 
 OGRErr OGRGeoPackageTableLayer::ReorderFields( int* panMap )
 {
-    if ( !m_poDS->GetUpdate() )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  UNSUPPORTED_OP_READ_ONLY,
-                  "ReorderFields");
+    if( !CheckUpdatableTable("ReorderFields") )
         return OGRERR_FAILURE;
-    }
 
     if (m_poFeatureDefn->GetFieldCount() == 0)
         return OGRERR_NONE;
@@ -3629,24 +4272,13 @@ OGRErr OGRGeoPackageTableLayer::ReorderFields( int* panMap )
         return eErr;
 
 /* -------------------------------------------------------------------- */
-/*      Defered actions, reset state.                                   */
+/*      Deferred actions, reset state.                                   */
 /* -------------------------------------------------------------------- */
     ResetReading();
     RunDeferredCreationIfNecessary();
     CreateSpatialIndexIfNecessary();
 
 /* -------------------------------------------------------------------- */
-/*      Check that is a table and not a view                            */
-/* -------------------------------------------------------------------- */
-    if( !IsTable() )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Layer %s is not a table",
-                 m_pszTableName);
-        return OGRERR_FAILURE;
-    }
-
-/* -------------------------------------------------------------------- */
 /*      Drop any iterator since we change the DB structure              */
 /* -------------------------------------------------------------------- */
     m_poDS->ResetReadingAllLayers();
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
index 92fa198..0cbc315 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.cpp
@@ -29,166 +29,7 @@
 #include "ogrgeopackageutility.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgeopackageutility.cpp 35692 2016-10-11 15:20:11Z rouault $");
-
-/* Runs a SQL command and ignores the result (good for INSERT/UPDATE/CREATE) */
-OGRErr SQLCommand(sqlite3 * poDb, const char * pszSQL)
-{
-    CPLAssert( poDb != NULL );
-    CPLAssert( pszSQL != NULL );
-
-    char *pszErrMsg = NULL;
-    //CPLDebug("GPKG", "exec(%s)", pszSQL);
-    int rc = sqlite3_exec(poDb, pszSQL, NULL, NULL, &pszErrMsg);
-
-    if ( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "sqlite3_exec(%s) failed: %s",
-                  pszSQL, pszErrMsg ? pszErrMsg : "" );
-        sqlite3_free( pszErrMsg );
-        return OGRERR_FAILURE;
-    }
-
-    return OGRERR_NONE;
-}
-
-
-OGRErr SQLResultInit(SQLResult * poResult)
-{
-    poResult->papszResult = NULL;
-    poResult->pszErrMsg = NULL;
-    poResult->nRowCount = 0;
-    poResult->nColCount = 0;
-    poResult->rc = 0;
-    return OGRERR_NONE;
-}
-
-
-OGRErr SQLQuery(sqlite3 * poDb, const char * pszSQL, SQLResult * poResult)
-{
-    CPLAssert( poDb != NULL );
-    CPLAssert( pszSQL != NULL );
-    CPLAssert( poResult != NULL );
-
-    SQLResultInit(poResult);
-
-    poResult->rc = sqlite3_get_table(
-        poDb, pszSQL,
-        &(poResult->papszResult),
-        &(poResult->nRowCount),
-        &(poResult->nColCount),
-        &(poResult->pszErrMsg) );
-
-    if( poResult->rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "sqlite3_get_table(%s) failed: %s", pszSQL, poResult->pszErrMsg );
-        return OGRERR_FAILURE;
-    }
-
-    return OGRERR_NONE;
-}
-
-
-OGRErr SQLResultFree(SQLResult * poResult)
-{
-    if ( poResult->papszResult )
-        sqlite3_free_table(poResult->papszResult);
-
-    if ( poResult->pszErrMsg )
-        sqlite3_free(poResult->pszErrMsg);
-
-    return OGRERR_NONE;
-}
-
-const char* SQLResultGetColumn(const SQLResult * poResult, int iColNum)
-{
-    if ( ! poResult )
-        return NULL;
-
-    if ( iColNum < 0 || iColNum >= poResult->nColCount )
-        return NULL;
-
-    return poResult->papszResult[iColNum];
-}
-
-const char* SQLResultGetValue(const SQLResult * poResult, int iColNum, int iRowNum)
-{
-    if ( ! poResult )
-        return NULL;
-
-    int nCols = poResult->nColCount;
-    int nRows = poResult->nRowCount;
-
-    if ( iColNum < 0 || iColNum >= nCols )
-        return NULL;
-
-    if ( iRowNum < 0 || iRowNum >= nRows )
-        return NULL;
-
-    return poResult->papszResult[ nCols + iRowNum * nCols + iColNum ];
-}
-
-int SQLResultGetValueAsInteger(const SQLResult * poResult, int iColNum, int iRowNum)
-{
-    if ( ! poResult )
-        return 0;
-
-    int nCols = poResult->nColCount;
-    int nRows = poResult->nRowCount;
-
-    if ( iColNum < 0 || iColNum >= nCols )
-        return 0;
-
-    if ( iRowNum < 0 || iRowNum >= nRows )
-        return 0;
-
-    char *pszValue = poResult->papszResult[ nCols + iRowNum * nCols + iColNum ];
-    if ( ! pszValue )
-        return 0;
-
-    return atoi(pszValue);
-}
-
-/* Returns the first row of first column of SQL as integer */
-GIntBig SQLGetInteger64(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
-{
-    CPLAssert( poDb != NULL );
-
-    sqlite3_stmt *poStmt = NULL;
-
-    /* Prepare the SQL */
-    int rc = sqlite3_prepare_v2(poDb, pszSQL, -1, &poStmt, NULL);
-    if ( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
-                  pszSQL, sqlite3_errmsg( poDb ) );
-        if ( err ) *err = OGRERR_FAILURE;
-        return 0;
-    }
-
-    /* Execute and fetch first row */
-    rc = sqlite3_step(poStmt);
-    if ( rc != SQLITE_ROW )
-    {
-        if ( err ) *err = OGRERR_FAILURE;
-        sqlite3_finalize(poStmt);
-        return 0;
-    }
-
-    /* Read the integer from the row */
-    GIntBig i = sqlite3_column_int64(poStmt, 0);
-    sqlite3_finalize(poStmt);
-
-    if ( err ) *err = OGRERR_NONE;
-    return i;
-}
-
-int SQLGetInteger(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
-{
-    return (int)SQLGetInteger64(poDb, pszSQL, err);
-}
+CPL_CVSID("$Id: ogrgeopackageutility.cpp 37806 2017-03-20 14:59:36Z rouault $");
 
 /* Requirement 20: A GeoPackage SHALL store feature table geometries */
 /* with the basic simple feature geometry types (Geometry, Point, */
@@ -245,7 +86,7 @@ OGRFieldType GPkgFieldToOGR(const char *pszGpkgType, OGRFieldSubType& eSubType,
         return OFTInteger;
     }
     else if ( EQUAL("TINYINT", pszGpkgType) )
-        return OFTInteger;
+        return OFTInteger; // [-128, 127]
     else if ( EQUAL("BOOLEAN", pszGpkgType) )
     {
         eSubType = OFSTBoolean;
@@ -289,10 +130,10 @@ OGRFieldType GPkgFieldToOGR(const char *pszGpkgType, OGRFieldSubType& eSubType,
 /* declared using one of the data types specified in table GeoPackage */
 /* Data Types. */
 /* http://opengis.github.io/geopackage/#table_column_data_types */
-const char* GPkgFieldFromOGR(OGRFieldType nType, OGRFieldSubType eSubType,
+const char* GPkgFieldFromOGR(OGRFieldType eType, OGRFieldSubType eSubType,
                              int nMaxWidth)
 {
-    switch(nType)
+    switch(eType)
     {
         case OFTInteger:
         {
@@ -330,31 +171,6 @@ const char* GPkgFieldFromOGR(OGRFieldType nType, OGRFieldSubType eSubType,
     }
 }
 
-
-int SQLiteFieldFromOGR(OGRFieldType nType)
-{
-    switch(nType)
-    {
-        case OFTInteger:
-            return SQLITE_INTEGER;
-        case OFTReal:
-            return SQLITE_FLOAT;
-        case OFTString:
-            return SQLITE_TEXT;
-        case OFTBinary:
-            return SQLITE_BLOB;
-        case OFTDate:
-            return SQLITE_TEXT;
-        case OFTDateTime:
-            return SQLITE_TEXT;
-        default:
-            return 0;
-    }
-}
-
-
-
-
 /* Requirement 19: A GeoPackage SHALL store feature table geometries
 *  with or without optional elevation (Z) and/or measure (M) values in SQL
 *  BLOBs using the Standard GeoPackageBinary format specified in table GeoPackage
@@ -385,7 +201,8 @@ int SQLiteFieldFromOGR(OGRFieldType nType)
 *
 */
 
-GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *pszWkb)
+GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId,
+                           size_t *pnWkbLen)
 {
     CPLAssert( poGeometry != NULL );
 
@@ -400,17 +217,17 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
     int iDims = poGeometry->getCoordinateDimension();
 
     /* Header has 8 bytes for sure, and optional extra space for bounds */
-    size_t szHeader = 2+1+1+4;
+    size_t nHeaderLen = 2+1+1+4;
     if ( ! bPoint && ! bEmpty )
     {
-        szHeader += 8*2*iDims;
+        nHeaderLen += 8*2*iDims;
     }
 
     /* Total BLOB size is header + WKB size */
-    size_t szWkb = szHeader + poGeometry->WkbSize();
-    GByte *pabyWkb = (GByte *)CPLMalloc(szWkb);
-    if (pszWkb)
-        *pszWkb = szWkb;
+    size_t nWkbLen = nHeaderLen + poGeometry->WkbSize();
+    GByte *pabyWkb = (GByte *)CPLMalloc(nWkbLen);
+    if (pnWkbLen)
+        *pnWkbLen = nWkbLen;
 
     /* Header Magic */
     pabyWkb[0] = 0x47;
@@ -481,7 +298,7 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
         }
     }
 
-    GByte *pabyPtr = pabyWkb + szHeader;
+    GByte *pabyPtr = pabyWkb + nHeaderLen;
 
     /* Use the wkbVariantIso for ISO SQL/MM output (differs for 3d geometry) */
     err = poGeometry->exportToWkb(eByteOrder, pabyPtr, wkbVariantIso);
@@ -494,14 +311,13 @@ GByte* GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *ps
     return pabyWkb;
 }
 
-
-OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t szGpkg, GPkgHeader *poHeader)
+OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t nGpkgLen, GPkgHeader *poHeader)
 {
     CPLAssert( pabyGpkg != NULL );
     CPLAssert( poHeader != NULL );
 
     /* Magic (match required) */
-    if ( szGpkg < 8 ||
+    if ( nGpkgLen < 8 ||
          pabyGpkg[0] != 0x47 ||
          pabyGpkg[1] != 0x50 ||
          pabyGpkg[2] != 0 )  /* Version (only 0 supported at this time)*/
@@ -562,7 +378,7 @@ OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t szGpkg, GPkgHeader *poHea
     }
     poHeader->iSrsId = iSrsId;
 
-    if( szGpkg < static_cast<size_t>(8 + 8*2*nEnvelopeDim) )
+    if( nGpkgLen < static_cast<size_t>(8 + 8*2*nEnvelopeDim) )
     {
         // Not enough bytes
         return OGRERR_FAILURE;
@@ -608,178 +424,32 @@ OGRErr GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t szGpkg, GPkgHeader *poHea
 #endif
 
     /* Header size in byte stream */
-    poHeader->szHeader = 8 + 8*2*nEnvelopeDim;
+    poHeader->nHeaderLen = 8 + 8*2*nEnvelopeDim;
 
     return OGRERR_NONE;
 }
 
-OGRGeometry* GPkgGeometryToOGR(const GByte *pabyGpkg, size_t szGpkg, OGRSpatialReference *poSrs)
+OGRGeometry* GPkgGeometryToOGR(const GByte *pabyGpkg, size_t nGpkgLen, OGRSpatialReference *poSrs)
 {
     CPLAssert( pabyGpkg != NULL );
 
     GPkgHeader oHeader;
 
     /* Read header */
-    OGRErr err = GPkgHeaderFromWKB(pabyGpkg, szGpkg, &oHeader);
+    OGRErr err = GPkgHeaderFromWKB(pabyGpkg, nGpkgLen, &oHeader);
     if ( err != OGRERR_NONE )
         return NULL;
 
     /* WKB pointer */
-    const GByte *pabyWkb = pabyGpkg + oHeader.szHeader;
-    size_t szWkb = szGpkg - oHeader.szHeader;
+    const GByte *pabyWkb = pabyGpkg + oHeader.nHeaderLen;
+    size_t nWkbLen = nGpkgLen - oHeader.nHeaderLen;
 
     /* Parse WKB */
     OGRGeometry *poGeom = NULL;
     err = OGRGeometryFactory::createFromWkb((GByte*)pabyWkb, poSrs, &poGeom,
-                                            static_cast<int>(szWkb));
+                                            static_cast<int>(nWkbLen));
     if ( err != OGRERR_NONE )
         return NULL;
 
     return poGeom;
 }
-
-
-OGRErr GPkgEnvelopeToOGR(GByte *pabyGpkg,
-                         size_t szGpkg,
-                         OGREnvelope *poEnv)
-{
-    CPLAssert( poEnv != NULL );
-    CPLAssert( pabyGpkg != NULL );
-
-    GPkgHeader oHeader;
-
-    /* Read header */
-    OGRErr err = GPkgHeaderFromWKB(pabyGpkg, szGpkg, &oHeader);
-    if ( err != OGRERR_NONE )
-        return err;
-
-    if ( oHeader.bEmpty || !oHeader.bExtentHasXY )
-    {
-        return OGRERR_FAILURE;
-    }
-
-    poEnv->MinX = oHeader.MinX;
-    poEnv->MaxX = oHeader.MaxX;
-    poEnv->MinY = oHeader.MinY;
-    poEnv->MaxY = oHeader.MaxY;
-
-    return OGRERR_NONE;
-}
-
-CPLString SQLEscapeDoubleQuote(const char* pszStr)
-{
-    CPLString osRet;
-    while( *pszStr != '\0' )
-    {
-        if( *pszStr == '"' )
-            osRet += "\"\"";
-        else
-            osRet += *pszStr;
-        pszStr ++;
-    }
-    return osRet;
-}
-
-CPLString SQLUnescapeDoubleQuote(const char* pszStr)
-{
-    CPLString osRet;
-    const bool bStartsWithDoubleQuote = (pszStr[0] == '"');
-    if( bStartsWithDoubleQuote )
-        pszStr ++;
-    while( *pszStr != '\0' )
-    {
-        if( bStartsWithDoubleQuote && *pszStr == '"' && pszStr[1] == '"' )
-        {
-            osRet += "\"";
-            pszStr ++;
-        }
-        else if( bStartsWithDoubleQuote && *pszStr == '"' )
-        {
-            break;
-        }
-        else
-            osRet += *pszStr;
-        pszStr ++;
-    }
-    return osRet;
-}
-
-/************************************************************************/
-/*                             SQLTokenize()                            */
-/************************************************************************/
-
-char** SQLTokenize( const char* pszStr )
-{
-    char** papszTokens = NULL;
-    bool bInQuote = false;
-    char chQuoteChar = '\0';
-    bool bInSpace = true;
-    CPLString osCurrentToken;
-    while( *pszStr != '\0' )
-    {
-        if( *pszStr == ' ' && !bInQuote )
-        {
-            if( !bInSpace )
-            {
-                papszTokens = CSLAddString(papszTokens, osCurrentToken);
-                osCurrentToken.clear();
-            }
-            bInSpace = true;
-        }
-        else if( (*pszStr == '(' || *pszStr == ')' || *pszStr == ',')  && !bInQuote )
-        {
-            if( !bInSpace )
-            {
-                papszTokens = CSLAddString(papszTokens, osCurrentToken);
-                osCurrentToken.clear();
-            }
-            osCurrentToken.clear();
-            osCurrentToken += *pszStr;
-            papszTokens = CSLAddString(papszTokens, osCurrentToken);
-            osCurrentToken.clear();
-            bInSpace = true;
-        }
-        else if( *pszStr == '"' || *pszStr == '\'' )
-        {
-            if( bInQuote && *pszStr == chQuoteChar && pszStr[1] == chQuoteChar )
-            {
-                osCurrentToken += *pszStr;
-                osCurrentToken += *pszStr;
-                pszStr += 2;
-                continue;
-            }
-            else if( bInQuote && *pszStr == chQuoteChar )
-            {
-                osCurrentToken += *pszStr;
-                papszTokens = CSLAddString(papszTokens, osCurrentToken);
-                osCurrentToken.clear();
-                bInSpace = true;
-                bInQuote = false;
-                chQuoteChar = '\0';
-            }
-            else if( bInQuote )
-            {
-                osCurrentToken += *pszStr;
-            }
-            else
-            {
-                chQuoteChar = *pszStr;
-                osCurrentToken.clear();
-                osCurrentToken += chQuoteChar;
-                bInQuote = true;
-                bInSpace = false;
-            }
-        }
-        else
-        {
-            osCurrentToken += *pszStr;
-            bInSpace = false;
-        }
-        pszStr ++;
-    }
-
-    if( !osCurrentToken.empty() )
-        papszTokens = CSLAddString(papszTokens, osCurrentToken);
-
-    return papszTokens;
-}
diff --git a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
index 7471a92..b51d912 100644
--- a/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
+++ b/ogr/ogrsf_frmts/gpkg/ogrgeopackageutility.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgeopackageutility.h 35679 2016-10-10 14:15:22Z rouault $
+ * $Id: ogrgeopackageutility.h 37806 2017-03-20 14:59:36Z rouault $
  *
  * Project:  GeoPackage Translator
  * Purpose:  Utility header for OGR GeoPackage driver.
@@ -28,22 +28,12 @@
  ****************************************************************************/
 
 #include "ogrsf_frmts.h"
-#include "sqlite3.h"
 
 #ifndef OGR_GEOPACKAGEUTILITY_H_INCLUDED
 #define OGR_GEOPACKAGEUTILITY_H_INCLUDED
 
 typedef struct
 {
-    char** papszResult;
-    int nRowCount;
-    int nColCount;
-    char *pszErrMsg;
-    int rc;
-} SQLResult;
-
-typedef struct
-{
     OGRBoolean bEmpty;
     OGRBoolean bExtended;
     OGRwkbByteOrder eByteOrder;
@@ -57,35 +47,16 @@ typedef struct
 #ifdef notdef
     double MinM, MaxM;
 #endif
-    size_t szHeader;
+    size_t nHeaderLen;
 } GPkgHeader;
 
-
-OGRErr              SQLCommand(sqlite3 *poDb, const char * pszSQL);
-int                 SQLGetInteger(sqlite3 * poDb, const char * pszSQL, OGRErr *err);
-GIntBig             SQLGetInteger64(sqlite3 * poDb, const char * pszSQL, OGRErr *err);
-
-OGRErr              SQLResultInit(SQLResult * poResult);
-OGRErr              SQLQuery(sqlite3 *poDb, const char * pszSQL, SQLResult * poResult);
-const char*         SQLResultGetColumn(const SQLResult * poResult, int iColumnNum);
-const char*         SQLResultGetValue(const SQLResult * poResult, int iColumnNum, int iRowNum);
-int                 SQLResultGetValueAsInteger(const SQLResult * poResult, int iColNum, int iRowNum);
-OGRErr              SQLResultFree(SQLResult * poResult);
-
-int                 SQLiteFieldFromOGR(OGRFieldType nType);
-
 OGRFieldType        GPkgFieldToOGR(const char *pszGpkgType, OGRFieldSubType& eSubType, int& nMaxWidth);
-const char*         GPkgFieldFromOGR(OGRFieldType nType, OGRFieldSubType eSubType, int nMaxWidth);
+const char*         GPkgFieldFromOGR(OGRFieldType eType, OGRFieldSubType eSubType, int nMaxWidth);
 OGRwkbGeometryType  GPkgGeometryTypeToWKB(const char *pszGpkgType, bool bHasZ, bool bHasM);
 
-GByte*              GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *szWkb);
-OGRGeometry*        GPkgGeometryToOGR(const GByte *pabyGpkg, size_t szGpkg, OGRSpatialReference *poSrs);
-OGRErr              GPkgEnvelopeToOGR(GByte *pabyGpkg, size_t szGpkg, OGREnvelope *poEnv);
-
-OGRErr              GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t szGpkg, GPkgHeader *poHeader);
+GByte*              GPkgGeometryFromOGR(const OGRGeometry *poGeometry, int iSrsId, size_t *pnWkbLen);
+OGRGeometry*        GPkgGeometryToOGR(const GByte *pabyGpkg, size_t nGpkgLen, OGRSpatialReference *poSrs);
 
-CPLString           SQLEscapeDoubleQuote(const char* pszStr);
-CPLString           SQLUnescapeDoubleQuote(const char* pszStr);
-char**              SQLTokenize( const char* pszSQL );
+OGRErr              GPkgHeaderFromWKB(const GByte *pabyGpkg, size_t nGpkgLen, GPkgHeader *poHeader);
 
 #endif
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h b/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
index 45cca08..2fcd065 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
+++ b/ogr/ogrsf_frmts/gpsbabel/ogr_gpsbabel.h
@@ -1,103 +1,102 @@
-/******************************************************************************
- * $Id: ogr_gpsbabel.h 32577 2015-12-31 06:39:56Z goatbar $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Private definitions for OGR/GPSBabel driver.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef OGR_GPSBABEL_H_INCLUDED
-#define OGR_GPSBABEL_H_INCLUDED
-
-#include "ogrsf_frmts.h"
-#include "cpl_string.h"
-
-/************************************************************************/
-/*                        OGRGPSBabelDataSource                         */
-/************************************************************************/
-
-class OGRGPSBabelDataSource : public OGRDataSource
-{
-    int                 nLayers;
-    OGRLayer*           apoLayers[5];
-    char               *pszName;
-    char               *pszGPSBabelDriverName;
-    char               *pszFilename;
-    CPLString           osTmpFileName;
-    GDALDataset        *poGPXDS;
-
-  public:
-                        OGRGPSBabelDataSource();
-                        ~OGRGPSBabelDataSource();
-
-    virtual int         CloseDependentDatasets();
-
-    virtual const char  *GetName() { return pszName; }
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer   *GetLayer( int );
-
-    virtual int         TestCapability( const char * );
-
-    int                 Open ( const char* pszFilename,
-                               const char* pszGPSBabelDriverNameIn,
-                               char** papszOpenOptions );
-
-    static int          IsSpecialFile(const char* pszFilename);
-    static int          IsValidDriverName(const char* pszGPSBabelDriverName);
-};
-
-
-/************************************************************************/
-/*                   OGRGPSBabelWriteDataSource                         */
-/************************************************************************/
-
-class OGRGPSBabelWriteDataSource : public OGRDataSource
-{
-    char               *pszName;
-    char               *pszGPSBabelDriverName;
-    char               *pszFilename;
-    CPLString           osTmpFileName;
-    GDALDataset        *poGPXDS;
-
-    int                 Convert();
-
-  public:
-                        OGRGPSBabelWriteDataSource();
-                        ~OGRGPSBabelWriteDataSource();
-
-    virtual const char  *GetName() { return pszName; }
-    virtual int         GetLayerCount();
-    virtual OGRLayer   *GetLayer( int );
-
-    virtual int         TestCapability( const char * );
-
-    virtual OGRLayer   *ICreateLayer( const char * pszLayerName,
-                                     OGRSpatialReference *poSRS,
-                                     OGRwkbGeometryType eType,
-                                     char ** papszOptions );
-
-    int                 Create ( const char* pszFilename, char **papszOptions );
-};
-
-#endif /* ndef OGR_GPSBABEL_H_INCLUDED */
+/******************************************************************************
+ * $Id: ogr_gpsbabel.h 36501 2016-11-25 14:09:24Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Private definitions for OGR/GPSBabel driver.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_GPSBABEL_H_INCLUDED
+#define OGR_GPSBABEL_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_string.h"
+
+/************************************************************************/
+/*                        OGRGPSBabelDataSource                         */
+/************************************************************************/
+
+class OGRGPSBabelDataSource : public OGRDataSource
+{
+    int                 nLayers;
+    OGRLayer*           apoLayers[5];
+    char               *pszName;
+    char               *pszGPSBabelDriverName;
+    char               *pszFilename;
+    CPLString           osTmpFileName;
+    GDALDataset        *poGPXDS;
+
+  public:
+                        OGRGPSBabelDataSource();
+                        virtual ~OGRGPSBabelDataSource();
+
+    virtual int         CloseDependentDatasets() override;
+
+    virtual const char  *GetName() override { return pszName; }
+    virtual int         GetLayerCount() override { return nLayers; }
+    virtual OGRLayer   *GetLayer( int ) override;
+
+    virtual int         TestCapability( const char * ) override;
+
+    int                 Open ( const char* pszFilename,
+                               const char* pszGPSBabelDriverNameIn,
+                               char** papszOpenOptions );
+
+    static bool         IsSpecialFile( const char* pszFilename );
+    static bool         IsValidDriverName( const char* pszGPSBabelDriverName );
+};
+
+/************************************************************************/
+/*                   OGRGPSBabelWriteDataSource                         */
+/************************************************************************/
+
+class OGRGPSBabelWriteDataSource : public OGRDataSource
+{
+    char               *pszName;
+    char               *pszGPSBabelDriverName;
+    char               *pszFilename;
+    CPLString           osTmpFileName;
+    GDALDataset        *poGPXDS;
+
+    bool                Convert();
+
+  public:
+                        OGRGPSBabelWriteDataSource();
+                        virtual ~OGRGPSBabelWriteDataSource();
+
+    virtual const char  *GetName() override { return pszName; }
+    virtual int         GetLayerCount() override;
+    virtual OGRLayer   *GetLayer( int ) override;
+
+    virtual int         TestCapability( const char * ) override;
+
+    virtual OGRLayer   *ICreateLayer( const char * pszLayerName,
+                                     OGRSpatialReference *poSRS,
+                                     OGRwkbGeometryType eType,
+                                     char ** papszOptions ) override;
+
+    int                 Create ( const char* pszFilename, char **papszOptions );
+};
+
+#endif /* ndef OGR_GPSBABEL_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
index 95d0af9..3f0f0b2 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldatasource.cpp
@@ -1,406 +1,405 @@
-/******************************************************************************
- * $Id: ogrgpsbabeldatasource.cpp 32982 2016-01-14 16:53:57Z goatbar $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements OGRGPSBabelDataSource class.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "cpl_error.h"
-#include "cpl_spawn.h"
-#include "ogr_gpsbabel.h"
-
-#include <cstring>
-
-CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 32982 2016-01-14 16:53:57Z goatbar $");
-
-/************************************************************************/
-/*                      OGRGPSBabelDataSource()                         */
-/************************************************************************/
-
-OGRGPSBabelDataSource::OGRGPSBabelDataSource() :
-    nLayers(0),
-    pszName(NULL),
-    pszGPSBabelDriverName(NULL),
-    pszFilename(NULL),
-    poGPXDS(NULL)
-{
-  for(int i=0; i<5; ++i)
-  {
-    apoLayers[i] = NULL;
-  }
-}
-
-/************************************************************************/
-/*                     ~OGRGPSBabelDataSource()                         */
-/************************************************************************/
-
-OGRGPSBabelDataSource::~OGRGPSBabelDataSource()
-
-{
-    CPLFree(pszName);
-    CPLFree(pszGPSBabelDriverName);
-    CPLFree(pszFilename);
-
-    CloseDependentDatasets();
-
-    if (osTmpFileName.size() > 0)
-        VSIUnlink(osTmpFileName.c_str());
-}
-
-/************************************************************************/
-/*                     CloseDependentDatasets()                         */
-/************************************************************************/
-
-int OGRGPSBabelDataSource::CloseDependentDatasets()
-{
-    if( poGPXDS == NULL )
-        return FALSE;
-
-    GDALClose( poGPXDS );
-    poGPXDS = NULL;
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             GetArgv()                                */
-/************************************************************************/
-
-static char** GetArgv( int bExplicitFeatures, int bWaypoints, int bRoutes,
-                       int bTracks, const char* pszGPSBabelDriverName,
-                       const char* pszFilename )
-{
-    char** argv = CSLAddString(NULL, "gpsbabel");
-    if (bExplicitFeatures)
-    {
-        if (bWaypoints) argv = CSLAddString(argv, "-w");
-        if (bRoutes) argv = CSLAddString(argv, "-r");
-        if (bTracks) argv = CSLAddString(argv, "-t");
-    }
-    argv = CSLAddString(argv, "-i");
-    argv = CSLAddString(argv, pszGPSBabelDriverName);
-    argv = CSLAddString(argv, "-f");
-    argv = CSLAddString(argv, pszFilename);
-    argv = CSLAddString(argv, "-o");
-    argv = CSLAddString(argv, "gpx,gpxver=1.1");
-    argv = CSLAddString(argv, "-F");
-    argv = CSLAddString(argv, "-");
-
-    return argv;
-}
-
-/************************************************************************/
-/*                         IsSpecialFile()                              */
-/************************************************************************/
-
-int OGRGPSBabelDataSource::IsSpecialFile(const char* pszFilename)
-{
-    return (STARTS_WITH(pszFilename, "/dev/") ||
-            STARTS_WITH(pszFilename, "usb:") ||
-            (STARTS_WITH(pszFilename, "COM")  && atoi(pszFilename + 3) > 0));
-}
-
-/************************************************************************/
-/*                       IsValidDriverName()                            */
-/************************************************************************/
-
-int OGRGPSBabelDataSource::IsValidDriverName(const char* pszGPSBabelDriverName)
-{
-    for( int i = 0; pszGPSBabelDriverName[i] != '\0'; i++ )
-    {
-        char ch = pszGPSBabelDriverName[i];
-        if( !((ch >= 'A' && ch <= 'Z') ||
-              (ch >= 'a' && ch <= 'z') ||
-              (ch >= '0' && ch <= '9') ||
-              ch == '_' || ch == '=' || ch == '.'  || ch == ',') )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Invalid GPSBabel driver name");
-            return FALSE;
-        }
-    }
-    return TRUE;
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
-                                 const char* pszGPSBabelDriverNameIn,
-                                 char** papszOpenOptionsIn )
-
-{
-    if (!STARTS_WITH_CI(pszDatasourceName, "GPSBABEL:"))
-    {
-        CPLAssert(pszGPSBabelDriverNameIn);
-        pszGPSBabelDriverName = CPLStrdup(pszGPSBabelDriverNameIn);
-        pszFilename = CPLStrdup(pszDatasourceName);
-    }
-    else
-    {
-        if( CSLFetchNameValue(papszOpenOptionsIn, "FILENAME") )
-            pszFilename = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn,
-                                                      "FILENAME"));
-
-        if( CSLFetchNameValue(papszOpenOptionsIn, "GPSBABEL_DRIVER") )
-        {
-            if( pszFilename == NULL )
-            {
-                CPLError(CE_Failure, CPLE_AppDefined, "Missing FILENAME");
-                return FALSE;
-            }
-
-            pszGPSBabelDriverName
-                = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn, "DRIVER"));
-
-            /* A bit of validation to avoid command line injection */
-            if (!IsValidDriverName(pszGPSBabelDriverName))
-                return FALSE;
-        }
-    }
-
-    pszName = CPLStrdup( pszDatasourceName );
-
-    bool bExplicitFeatures = false;
-    bool bWaypoints = true;
-    bool bTracks = true;
-    bool bRoutes = true;
-
-    if (pszGPSBabelDriverName == NULL)
-    {
-        const char* pszSep = strchr(pszDatasourceName + 9, ':');
-        if (pszSep == NULL)
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Wrong syntax. Expected GPSBabel:driver_name:file_name");
-            return FALSE;
-        }
-
-        pszGPSBabelDriverName = CPLStrdup(pszDatasourceName + 9);
-        *(strchr(pszGPSBabelDriverName, ':')) = '\0';
-
-        /* A bit of validation to avoid command line injection */
-        if (!IsValidDriverName(pszGPSBabelDriverName))
-            return FALSE;
-
-        /* Parse optional features= option */
-        if (STARTS_WITH_CI(pszSep+1, "features="))
-        {
-            const char* pszNextSep = strchr(pszSep+1, ':');
-            if (pszNextSep == NULL)
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Wrong syntax. Expected "
-                         "GPSBabel:driver_name[,options]*:["
-                         "features=waypoints,tracks,routes:]file_name");
-                return FALSE;
-            }
-
-            char* pszFeatures = CPLStrdup(pszSep+1+9);
-            *strchr(pszFeatures, ':') = 0;
-            char** papszTokens = CSLTokenizeString(pszFeatures);
-            char** papszIter = papszTokens;
-            bool bErr = false;
-            bExplicitFeatures = true;
-            bWaypoints = false;
-            bTracks = false;
-            bRoutes = false;
-            while(papszIter && *papszIter)
-            {
-                if (EQUAL(*papszIter, "waypoints"))
-                    bWaypoints = true;
-                else if (EQUAL(*papszIter, "tracks"))
-                    bTracks = true;
-                else if (EQUAL(*papszIter, "routes"))
-                    bRoutes = true;
-                else
-                {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Wrong value for 'features' options");
-                    bErr = true;
-                }
-                papszIter++;
-            }
-            CSLDestroy(papszTokens);
-            CPLFree(pszFeatures);
-
-            if (bErr)
-                return FALSE;
-
-            pszSep = pszNextSep;
-        }
-
-        if( pszFilename == NULL )
-            pszFilename = CPLStrdup(pszSep+1);
-    }
-
-    const char* pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", NULL);
-    if (pszOptionUseTempFile && CPLTestBool(pszOptionUseTempFile))
-        osTmpFileName = CPLGenerateTempFilename(NULL);
-    else
-        osTmpFileName.Printf("/vsimem/ogrgpsbabeldatasource_%p", this);
-
-    bool bRet = false;
-    if (IsSpecialFile(pszFilename))
-    {
-        /* Special file : don't try to open it */
-        char** argv = GetArgv(bExplicitFeatures, bWaypoints, bRoutes,
-                              bTracks, pszGPSBabelDriverName, pszFilename);
-        VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "wb");
-        bRet = (CPLSpawn(argv, NULL, tmpfp, TRUE) == 0);
-        VSIFCloseL(tmpfp);
-        tmpfp = NULL;
-        CSLDestroy(argv);
-        argv = NULL;
-    }
-    else
-    {
-        VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
-        if (fp == NULL)
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                    "Cannot open file %s", pszFilename);
-            return FALSE;
-        }
-
-        char** argv = GetArgv(bExplicitFeatures, bWaypoints, bRoutes,
-                              bTracks, pszGPSBabelDriverName, "-");
-
-        VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "wb");
-
-        CPLPushErrorHandler(CPLQuietErrorHandler);
-        bRet = (CPLSpawn(argv, fp, tmpfp, TRUE) == 0);
-        CPLPopErrorHandler();
-
-        CSLDestroy(argv);
-        argv = NULL;
-
-        CPLErr nLastErrorType = CPLGetLastErrorType();
-        CPLErrorNum nLastErrorNo = CPLGetLastErrorNo();
-        CPLString osLastErrorMsg = CPLGetLastErrorMsg();
-
-        VSIFCloseL(tmpfp);
-        tmpfp = NULL;
-
-        VSIFCloseL(fp);
-        fp = NULL;
-
-        if (!bRet)
-        {
-            if ( strstr(osLastErrorMsg.c_str(),
-                        "This format cannot be used in piped commands") == NULL)
-            {
-                CPLError( nLastErrorType, nLastErrorNo, "%s",
-                          osLastErrorMsg.c_str());
-            }
-            else
-            {
-                VSIStatBuf sStatBuf;
-                if (VSIStat(pszFilename, &sStatBuf) != 0)
-                {
-                    CPLError( CE_Failure, CPLE_NotSupported,
-                              "Driver %s only supports real (non virtual) "
-                              "files",
-                              pszGPSBabelDriverName );
-                    return FALSE;
-                }
-
-                /* Try without piping in */
-                argv = GetArgv(bExplicitFeatures, bWaypoints, bRoutes,
-                              bTracks, pszGPSBabelDriverName, pszFilename);
-                tmpfp = VSIFOpenL(osTmpFileName.c_str(), "wb");
-                bRet = (CPLSpawn(argv, NULL, tmpfp, TRUE) == 0);
-                VSIFCloseL(tmpfp);
-                tmpfp = NULL;
-
-                CSLDestroy(argv);
-                argv = NULL;
-            }
-        }
-    }
-
-
-    if (bRet)
-    {
-        poGPXDS = static_cast<GDALDataset *>(
-            GDALOpenEx( osTmpFileName.c_str(),
-                        GDAL_OF_VECTOR, NULL, NULL, NULL ) );
-        if (poGPXDS)
-        {
-            if (bWaypoints)
-            {
-                OGRLayer* poLayer = poGPXDS->GetLayerByName("waypoints");
-                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
-                    apoLayers[nLayers++] = poLayer;
-            }
-
-            if (bRoutes)
-            {
-                OGRLayer* poLayer = poGPXDS->GetLayerByName("routes");
-                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
-                    apoLayers[nLayers++] = poLayer;
-                poLayer = poGPXDS->GetLayerByName("route_points");
-                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
-                    apoLayers[nLayers++] = poLayer;
-            }
-
-            if (bTracks)
-            {
-                OGRLayer* poLayer = poGPXDS->GetLayerByName("tracks");
-                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
-                    apoLayers[nLayers++] = poLayer;
-                poLayer = poGPXDS->GetLayerByName("track_points");
-                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
-                    apoLayers[nLayers++] = poLayer;
-            }
-        }
-    }
-
-    return nLayers > 0;
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRGPSBabelDataSource::TestCapability( const char * /* pszCap */ )
-{
-    return FALSE;
-}
-
-/************************************************************************/
-/*                              GetLayer()                              */
-/************************************************************************/
-
-OGRLayer *OGRGPSBabelDataSource::GetLayer( int iLayer )
-
-{
-    if( iLayer < 0 || iLayer >= nLayers )
-        return NULL;
-
-    return apoLayers[iLayer];
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRGPSBabelDataSource class.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "cpl_error.h"
+#include "cpl_spawn.h"
+#include "ogr_gpsbabel.h"
+
+#include <cstring>
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrgpsbabeldatasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+/************************************************************************/
+/*                      OGRGPSBabelDataSource()                         */
+/************************************************************************/
+
+OGRGPSBabelDataSource::OGRGPSBabelDataSource() :
+    nLayers(0),
+    pszName(NULL),
+    pszGPSBabelDriverName(NULL),
+    pszFilename(NULL),
+    poGPXDS(NULL)
+{
+  std::fill_n(apoLayers, CPL_ARRAYSIZE(apoLayers),
+              static_cast<OGRLayer*>(NULL));
+}
+
+/************************************************************************/
+/*                     ~OGRGPSBabelDataSource()                         */
+/************************************************************************/
+
+OGRGPSBabelDataSource::~OGRGPSBabelDataSource()
+
+{
+    CPLFree(pszName);
+    CPLFree(pszGPSBabelDriverName);
+    CPLFree(pszFilename);
+
+    CloseDependentDatasets();
+
+    if (!osTmpFileName.empty())
+        VSIUnlink(osTmpFileName.c_str());
+}
+
+/************************************************************************/
+/*                     CloseDependentDatasets()                         */
+/************************************************************************/
+
+int OGRGPSBabelDataSource::CloseDependentDatasets()
+{
+    if( poGPXDS == NULL )
+        return FALSE;
+
+    GDALClose( poGPXDS );
+    poGPXDS = NULL;
+    return TRUE;
+}
+
+/************************************************************************/
+/*                             GetArgv()                                */
+/************************************************************************/
+
+static char** GetArgv( int bExplicitFeatures, int bWaypoints, int bRoutes,
+                       int bTracks, const char* pszGPSBabelDriverName,
+                       const char* pszFilename )
+{
+    char** argv = CSLAddString(NULL, "gpsbabel");
+    if (bExplicitFeatures)
+    {
+        if (bWaypoints) argv = CSLAddString(argv, "-w");
+        if (bRoutes) argv = CSLAddString(argv, "-r");
+        if (bTracks) argv = CSLAddString(argv, "-t");
+    }
+    argv = CSLAddString(argv, "-i");
+    argv = CSLAddString(argv, pszGPSBabelDriverName);
+    argv = CSLAddString(argv, "-f");
+    argv = CSLAddString(argv, pszFilename);
+    argv = CSLAddString(argv, "-o");
+    argv = CSLAddString(argv, "gpx,gpxver=1.1");
+    argv = CSLAddString(argv, "-F");
+    argv = CSLAddString(argv, "-");
+
+    return argv;
+}
+
+/************************************************************************/
+/*                         IsSpecialFile()                              */
+/************************************************************************/
+
+bool OGRGPSBabelDataSource::IsSpecialFile( const char* pszFilename )
+{
+    return
+        STARTS_WITH(pszFilename, "/dev/") ||
+        STARTS_WITH(pszFilename, "usb:") ||
+        (STARTS_WITH(pszFilename, "COM")  && atoi(pszFilename + 3) > 0);
+}
+
+/************************************************************************/
+/*                       IsValidDriverName()                            */
+/************************************************************************/
+
+bool
+OGRGPSBabelDataSource::IsValidDriverName( const char* pszGPSBabelDriverName )
+{
+    for( int i = 0; pszGPSBabelDriverName[i] != '\0'; i++ )
+    {
+        char ch = pszGPSBabelDriverName[i];
+        if( !((ch >= 'A' && ch <= 'Z') ||
+              (ch >= 'a' && ch <= 'z') ||
+              (ch >= '0' && ch <= '9') ||
+              ch == '_' || ch == '=' || ch == '.'  || ch == ',') )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Invalid GPSBabel driver name");
+            return false;
+        }
+    }
+    return true;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+int OGRGPSBabelDataSource::Open( const char * pszDatasourceName,
+                                 const char* pszGPSBabelDriverNameIn,
+                                 char** papszOpenOptionsIn )
+
+{
+    if (!STARTS_WITH_CI(pszDatasourceName, "GPSBABEL:"))
+    {
+        CPLAssert(pszGPSBabelDriverNameIn);
+        pszGPSBabelDriverName = CPLStrdup(pszGPSBabelDriverNameIn);
+        pszFilename = CPLStrdup(pszDatasourceName);
+    }
+    else
+    {
+        if( CSLFetchNameValue(papszOpenOptionsIn, "FILENAME") )
+            pszFilename = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn,
+                                                      "FILENAME"));
+
+        if( CSLFetchNameValue(papszOpenOptionsIn, "GPSBABEL_DRIVER") )
+        {
+            if( pszFilename == NULL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Missing FILENAME");
+                return FALSE;
+            }
+
+            pszGPSBabelDriverName
+                = CPLStrdup(CSLFetchNameValue(papszOpenOptionsIn, "DRIVER"));
+
+            /* A bit of validation to avoid command line injection */
+            if (!IsValidDriverName(pszGPSBabelDriverName))
+                return FALSE;
+        }
+    }
+
+    pszName = CPLStrdup( pszDatasourceName );
+
+    bool bExplicitFeatures = false;
+    bool bWaypoints = true;
+    bool bTracks = true;
+    bool bRoutes = true;
+
+    if (pszGPSBabelDriverName == NULL)
+    {
+        const char* pszSep = strchr(pszDatasourceName + 9, ':');
+        if (pszSep == NULL)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Wrong syntax. Expected GPSBabel:driver_name:file_name");
+            return FALSE;
+        }
+
+        pszGPSBabelDriverName = CPLStrdup(pszDatasourceName + 9);
+        *(strchr(pszGPSBabelDriverName, ':')) = '\0';
+
+        /* A bit of validation to avoid command line injection */
+        if (!IsValidDriverName(pszGPSBabelDriverName))
+            return FALSE;
+
+        /* Parse optional features= option */
+        if (STARTS_WITH_CI(pszSep+1, "features="))
+        {
+            const char* pszNextSep = strchr(pszSep+1, ':');
+            if (pszNextSep == NULL)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "Wrong syntax. Expected "
+                         "GPSBabel:driver_name[,options]*:["
+                         "features=waypoints,tracks,routes:]file_name");
+                return FALSE;
+            }
+
+            char* pszFeatures = CPLStrdup(pszSep+1+9);
+            *strchr(pszFeatures, ':') = 0;
+            char** papszTokens = CSLTokenizeString(pszFeatures);
+            char** papszIter = papszTokens;
+            bool bErr = false;
+            bExplicitFeatures = true;
+            bWaypoints = false;
+            bTracks = false;
+            bRoutes = false;
+            while(papszIter && *papszIter)
+            {
+                if (EQUAL(*papszIter, "waypoints"))
+                    bWaypoints = true;
+                else if (EQUAL(*papszIter, "tracks"))
+                    bTracks = true;
+                else if (EQUAL(*papszIter, "routes"))
+                    bRoutes = true;
+                else
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined,
+                              "Wrong value for 'features' options");
+                    bErr = true;
+                }
+                papszIter++;
+            }
+            CSLDestroy(papszTokens);
+            CPLFree(pszFeatures);
+
+            if (bErr)
+                return FALSE;
+
+            pszSep = pszNextSep;
+        }
+
+        if( pszFilename == NULL )
+            pszFilename = CPLStrdup(pszSep+1);
+    }
+
+    const char* pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", NULL);
+    if (pszOptionUseTempFile && CPLTestBool(pszOptionUseTempFile))
+        osTmpFileName = CPLGenerateTempFilename(NULL);
+    else
+        osTmpFileName.Printf("/vsimem/ogrgpsbabeldatasource_%p", this);
+
+    bool bRet = false;
+    if (IsSpecialFile(pszFilename))
+    {
+        /* Special file : don't try to open it */
+        char** argv = GetArgv(bExplicitFeatures, bWaypoints, bRoutes,
+                              bTracks, pszGPSBabelDriverName, pszFilename);
+        VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "wb");
+        bRet = (CPLSpawn(argv, NULL, tmpfp, TRUE) == 0);
+        VSIFCloseL(tmpfp);
+        tmpfp = NULL;
+        CSLDestroy(argv);
+        argv = NULL;
+    }
+    else
+    {
+        VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+        if (fp == NULL)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot open file %s", pszFilename);
+            return FALSE;
+        }
+
+        char** argv = GetArgv(bExplicitFeatures, bWaypoints, bRoutes,
+                              bTracks, pszGPSBabelDriverName, "-");
+
+        VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "wb");
+
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        bRet = (CPLSpawn(argv, fp, tmpfp, TRUE) == 0);
+        CPLPopErrorHandler();
+
+        CSLDestroy(argv);
+        argv = NULL;
+
+        CPLErr nLastErrorType = CPLGetLastErrorType();
+        CPLErrorNum nLastErrorNo = CPLGetLastErrorNo();
+        CPLString osLastErrorMsg = CPLGetLastErrorMsg();
+
+        VSIFCloseL(tmpfp);
+        tmpfp = NULL;
+
+        VSIFCloseL(fp);
+        fp = NULL;
+
+        if (!bRet)
+        {
+            if ( strstr(osLastErrorMsg.c_str(),
+                        "This format cannot be used in piped commands") == NULL)
+            {
+                CPLError( nLastErrorType, nLastErrorNo, "%s",
+                          osLastErrorMsg.c_str());
+            }
+            else
+            {
+                VSIStatBuf sStatBuf;
+                if (VSIStat(pszFilename, &sStatBuf) != 0)
+                {
+                    CPLError( CE_Failure, CPLE_NotSupported,
+                              "Driver %s only supports real (non virtual) "
+                              "files",
+                              pszGPSBabelDriverName );
+                    return FALSE;
+                }
+
+                /* Try without piping in */
+                argv = GetArgv(bExplicitFeatures, bWaypoints, bRoutes,
+                              bTracks, pszGPSBabelDriverName, pszFilename);
+                tmpfp = VSIFOpenL(osTmpFileName.c_str(), "wb");
+                bRet = (CPLSpawn(argv, NULL, tmpfp, TRUE) == 0);
+                VSIFCloseL(tmpfp);
+                tmpfp = NULL;
+
+                CSLDestroy(argv);
+                argv = NULL;
+            }
+        }
+    }
+
+    if (bRet)
+    {
+        poGPXDS = static_cast<GDALDataset *>(
+            GDALOpenEx( osTmpFileName.c_str(),
+                        GDAL_OF_VECTOR, NULL, NULL, NULL ) );
+        if (poGPXDS)
+        {
+            if (bWaypoints)
+            {
+                OGRLayer* poLayer = poGPXDS->GetLayerByName("waypoints");
+                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
+                    apoLayers[nLayers++] = poLayer;
+            }
+
+            if (bRoutes)
+            {
+                OGRLayer* poLayer = poGPXDS->GetLayerByName("routes");
+                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
+                    apoLayers[nLayers++] = poLayer;
+                poLayer = poGPXDS->GetLayerByName("route_points");
+                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
+                    apoLayers[nLayers++] = poLayer;
+            }
+
+            if (bTracks)
+            {
+                OGRLayer* poLayer = poGPXDS->GetLayerByName("tracks");
+                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
+                    apoLayers[nLayers++] = poLayer;
+                poLayer = poGPXDS->GetLayerByName("track_points");
+                if (poLayer != NULL && poLayer->GetFeatureCount() != 0)
+                    apoLayers[nLayers++] = poLayer;
+            }
+        }
+    }
+
+    return nLayers > 0;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGPSBabelDataSource::TestCapability( const char * /* pszCap */ )
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRGPSBabelDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+
+    return apoLayers[iLayer];
+}
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
index 5b7951e..7104e1c 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabeldriver.cpp
@@ -1,211 +1,210 @@
-/******************************************************************************
- * $Id$
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements OGRGPSbabelDriver class.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_conv.h"
-#include "cpl_spawn.h"
-
-#include "ogr_gpsbabel.h"
-
-CPL_CVSID("$Id$");
-
-/************************************************************************/
-/*                         OGRGPSBabelDriverIdentify()                  */
-/************************************************************************/
-
-static bool OGRGPSBabelDriverIdentifyInternal(
-    GDALOpenInfo* poOpenInfo,
-    const char** ppszGSPBabelDriverName )
-{
-    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "GPSBABEL:") )
-        return true;
-
-    const char* pszGPSBabelDriverName = NULL;
-    if( poOpenInfo->fpL == NULL )
-            return false;
-
-    if (memcmp(poOpenInfo->pabyHeader, "MsRcd", 5) == 0)
-        pszGPSBabelDriverName = "mapsource";
-    else if (memcmp(poOpenInfo->pabyHeader, "MsRcf", 5) == 0)
-        pszGPSBabelDriverName = "gdb";
-    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "<osm") != NULL)
-        pszGPSBabelDriverName = "osm";
-    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$GPGSA") != NULL ||
-                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$GPGGA") != NULL)
-        pszGPSBabelDriverName = "nmea";
-    else if (STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "OziExplorer"))
-        pszGPSBabelDriverName = "ozi";
-    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "Grid") &&
-                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "Datum") &&
-                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "Header"))
-        pszGPSBabelDriverName = "garmin_txt";
-    else if (poOpenInfo->pabyHeader[0] == 13 && poOpenInfo->pabyHeader[10] == 'M' && poOpenInfo->pabyHeader[11] == 'S' &&
-                (poOpenInfo->pabyHeader[12] >= '0' && poOpenInfo->pabyHeader[12] <= '9') &&
-                (poOpenInfo->pabyHeader[13] >= '0' && poOpenInfo->pabyHeader[13] <= '9') &&
-                poOpenInfo->pabyHeader[12] * 10 + poOpenInfo->pabyHeader[13] >= 30 &&
-                (poOpenInfo->pabyHeader[14] == 1 || poOpenInfo->pabyHeader[14] == 2) && poOpenInfo->pabyHeader[15] == 0 &&
-                poOpenInfo->pabyHeader[16] == 0 && poOpenInfo->pabyHeader[17] == 0)
-        pszGPSBabelDriverName = "mapsend";
-    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$PMGNWPL") != NULL ||
-                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$PMGNRTE") != NULL)
-        pszGPSBabelDriverName = "magellan";
-    else if (poOpenInfo->pabyHeader[0] == 'A' &&
-                poOpenInfo->pabyHeader[1] >= 'A' && poOpenInfo->pabyHeader[1] <= 'Z' &&
-                poOpenInfo->pabyHeader[2] >= 'A' && poOpenInfo->pabyHeader[2] <= 'Z' &&
-                poOpenInfo->pabyHeader[3] >= 'A' && poOpenInfo->pabyHeader[3] <= 'Z' &&
-                EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "igc") )
-        pszGPSBabelDriverName = "igc";
-
-    static int bGPSBabelFound = -1;
-    if( pszGPSBabelDriverName != NULL && bGPSBabelFound < 0 )
-    {
-#ifndef WIN32
-        VSIStatBufL sStat;
-        bGPSBabelFound = VSIStatL("/usr/bin/gpsbabel", &sStat) == 0;
-        if( !bGPSBabelFound )
-#endif
-        {
-            const char* const apszArgs[] = { "gpsbabel", "-V", NULL };
-            CPLString osTmpFileName("/vsimem/gpsbabel_tmp.tmp");
-            VSILFILE* tmpfp = VSIFOpenL(osTmpFileName, "wb");
-            bGPSBabelFound = (CPLSpawn(apszArgs, NULL, tmpfp, FALSE) == 0);
-            VSIFCloseL(tmpfp);
-            VSIUnlink(osTmpFileName);
-        }
-    }
-
-    if( bGPSBabelFound )
-        *ppszGSPBabelDriverName = pszGPSBabelDriverName;
-    return *ppszGSPBabelDriverName != NULL;
-}
-
-static int OGRGPSBabelDriverIdentify( GDALOpenInfo* poOpenInfo )
-{
-    const char* pszGPSBabelDriverName = NULL;
-    return OGRGPSBabelDriverIdentifyInternal( poOpenInfo,
-                                              &pszGPSBabelDriverName );
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-static GDALDataset *OGRGPSBabelDriverOpen( GDALOpenInfo* poOpenInfo )
-
-{
-    const char* pszGPSBabelDriverName = NULL;
-    if (poOpenInfo->eAccess == GA_Update ||
-        !OGRGPSBabelDriverIdentifyInternal(poOpenInfo, &pszGPSBabelDriverName))
-        return NULL;
-
-    OGRGPSBabelDataSource *poDS = new OGRGPSBabelDataSource();
-
-    if( !poDS->Open( poOpenInfo->pszFilename, pszGPSBabelDriverName,
-                     poOpenInfo->papszOpenOptions ) )
-    {
-        delete poDS;
-        poDS = NULL;
-    }
-
-    return poDS;
-}
-
-/************************************************************************/
-/*                               Create()                               */
-/************************************************************************/
-
-static GDALDataset *OGRGPSBabelDriverCreate( const char * pszName,
-                                             int /* nBands */,
-                                             int /* nXSize */,
-                                             int /* nYSize */,
-                                             GDALDataType /* eDT */,
-                                             char **papszOptions )
-{
-    OGRGPSBabelWriteDataSource *poDS = new OGRGPSBabelWriteDataSource();
-
-    if( !poDS->Create( pszName, papszOptions ) )
-    {
-        delete poDS;
-        poDS = NULL;
-    }
-
-    return poDS;
-}
-
-/************************************************************************/
-/*                               Delete()                               */
-/************************************************************************/
-
-static CPLErr OGRGPSBabelDriverDelete( const char *pszFilename )
-
-{
-    if( VSIUnlink( pszFilename ) == 0 )
-        return CE_None;
-
-    return CE_Failure;
-}
-
-/************************************************************************/
-/*                        RegisterOGRGPSBabel()                         */
-/************************************************************************/
-
-void RegisterOGRGPSBabel()
-{
-    if (! GDAL_CHECK_VERSION("OGR/GPSBabel driver"))
-        return;
-
-    if( GDALGetDriverByName( "GPSBabel" ) != NULL )
-        return;
-
-    GDALDriver *poDriver = new GDALDriver();
-
-    poDriver->SetDescription( "GPSBabel" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GPSBabel" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_gpsbabel.html" );
-
-    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "GPSBABEL:" );
-
-    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
-"<OpenOptionList>"
-"  <Option name='FILENAME' type='string' description='Filename to open'/>"
-"  <Option name='GPSBABEL_DRIVER' type='string' description='Name of the GPSBabel to use'/>"
-"</OpenOptionList>");
-
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-"<CreationOptionList>"
-"  <Option name='GPSBABEL_DRIVER' type='string' description='Name of the GPSBabel to use'/>"
-"</CreationOptionList>");
-
-    poDriver->pfnOpen = OGRGPSBabelDriverOpen;
-    poDriver->pfnIdentify = OGRGPSBabelDriverIdentify;
-    poDriver->pfnCreate = OGRGPSBabelDriverCreate;
-    poDriver->pfnDelete = OGRGPSBabelDriverDelete;
-
-    GetGDALDriverManager()->RegisterDriver( poDriver );
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRGPSbabelDriver class.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "cpl_spawn.h"
+
+#include "ogr_gpsbabel.h"
+
+CPL_CVSID("$Id: ogrgpsbabeldriver.cpp 35504 2016-09-23 18:40:40Z goatbar $");
+
+/************************************************************************/
+/*                         OGRGPSBabelDriverIdentify()                  */
+/************************************************************************/
+
+static bool OGRGPSBabelDriverIdentifyInternal(
+    GDALOpenInfo* poOpenInfo,
+    const char** ppszGSPBabelDriverName )
+{
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "GPSBABEL:") )
+        return true;
+
+    const char* pszGPSBabelDriverName = NULL;
+    if( poOpenInfo->fpL == NULL )
+            return false;
+
+    if (memcmp(poOpenInfo->pabyHeader, "MsRcd", 5) == 0)
+        pszGPSBabelDriverName = "mapsource";
+    else if (memcmp(poOpenInfo->pabyHeader, "MsRcf", 5) == 0)
+        pszGPSBabelDriverName = "gdb";
+    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "<osm") != NULL)
+        pszGPSBabelDriverName = "osm";
+    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$GPGSA") != NULL ||
+                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$GPGGA") != NULL)
+        pszGPSBabelDriverName = "nmea";
+    else if (STARTS_WITH_CI((const char*)poOpenInfo->pabyHeader, "OziExplorer"))
+        pszGPSBabelDriverName = "ozi";
+    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "Grid") &&
+                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "Datum") &&
+                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "Header"))
+        pszGPSBabelDriverName = "garmin_txt";
+    else if (poOpenInfo->pabyHeader[0] == 13 && poOpenInfo->pabyHeader[10] == 'M' && poOpenInfo->pabyHeader[11] == 'S' &&
+                (poOpenInfo->pabyHeader[12] >= '0' && poOpenInfo->pabyHeader[12] <= '9') &&
+                (poOpenInfo->pabyHeader[13] >= '0' && poOpenInfo->pabyHeader[13] <= '9') &&
+                poOpenInfo->pabyHeader[12] * 10 + poOpenInfo->pabyHeader[13] >= 30 &&
+                (poOpenInfo->pabyHeader[14] == 1 || poOpenInfo->pabyHeader[14] == 2) && poOpenInfo->pabyHeader[15] == 0 &&
+                poOpenInfo->pabyHeader[16] == 0 && poOpenInfo->pabyHeader[17] == 0)
+        pszGPSBabelDriverName = "mapsend";
+    else if (strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$PMGNWPL") != NULL ||
+                strstr(reinterpret_cast<const char*>(poOpenInfo->pabyHeader), "$PMGNRTE") != NULL)
+        pszGPSBabelDriverName = "magellan";
+    else if (poOpenInfo->pabyHeader[0] == 'A' &&
+                poOpenInfo->pabyHeader[1] >= 'A' && poOpenInfo->pabyHeader[1] <= 'Z' &&
+                poOpenInfo->pabyHeader[2] >= 'A' && poOpenInfo->pabyHeader[2] <= 'Z' &&
+                poOpenInfo->pabyHeader[3] >= 'A' && poOpenInfo->pabyHeader[3] <= 'Z' &&
+                EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "igc") )
+        pszGPSBabelDriverName = "igc";
+
+    static int bGPSBabelFound = -1;
+    if( pszGPSBabelDriverName != NULL && bGPSBabelFound < 0 )
+    {
+#ifndef WIN32
+        VSIStatBufL sStat;
+        bGPSBabelFound = VSIStatL("/usr/bin/gpsbabel", &sStat) == 0;
+        if( !bGPSBabelFound )
+#endif
+        {
+            const char* const apszArgs[] = { "gpsbabel", "-V", NULL };
+            CPLString osTmpFileName("/vsimem/gpsbabel_tmp.tmp");
+            VSILFILE* tmpfp = VSIFOpenL(osTmpFileName, "wb");
+            bGPSBabelFound = CPLSpawn(apszArgs, NULL, tmpfp, FALSE) == 0;
+            VSIFCloseL(tmpfp);
+            VSIUnlink(osTmpFileName);
+        }
+    }
+
+    if( bGPSBabelFound )
+        *ppszGSPBabelDriverName = pszGPSBabelDriverName;
+    return *ppszGSPBabelDriverName != NULL;
+}
+
+static int OGRGPSBabelDriverIdentify( GDALOpenInfo* poOpenInfo )
+{
+    const char* pszGPSBabelDriverName = NULL;
+    return OGRGPSBabelDriverIdentifyInternal( poOpenInfo,
+                                              &pszGPSBabelDriverName );
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+static GDALDataset *OGRGPSBabelDriverOpen( GDALOpenInfo* poOpenInfo )
+
+{
+    const char* pszGPSBabelDriverName = NULL;
+    if (poOpenInfo->eAccess == GA_Update ||
+        !OGRGPSBabelDriverIdentifyInternal(poOpenInfo, &pszGPSBabelDriverName))
+        return NULL;
+
+    OGRGPSBabelDataSource *poDS = new OGRGPSBabelDataSource();
+
+    if( !poDS->Open( poOpenInfo->pszFilename, pszGPSBabelDriverName,
+                     poOpenInfo->papszOpenOptions ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                               Create()                               */
+/************************************************************************/
+
+static GDALDataset *OGRGPSBabelDriverCreate( const char * pszName,
+                                             int /* nBands */,
+                                             int /* nXSize */,
+                                             int /* nYSize */,
+                                             GDALDataType /* eDT */,
+                                             char **papszOptions )
+{
+    OGRGPSBabelWriteDataSource *poDS = new OGRGPSBabelWriteDataSource();
+
+    if( !poDS->Create( pszName, papszOptions ) )
+    {
+        delete poDS;
+        poDS = NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                               Delete()                               */
+/************************************************************************/
+
+static CPLErr OGRGPSBabelDriverDelete( const char *pszFilename )
+
+{
+    if( VSIUnlink( pszFilename ) == 0 )
+        return CE_None;
+
+    return CE_Failure;
+}
+
+/************************************************************************/
+/*                        RegisterOGRGPSBabel()                         */
+/************************************************************************/
+
+void RegisterOGRGPSBabel()
+{
+    if (! GDAL_CHECK_VERSION("OGR/GPSBabel driver"))
+        return;
+
+    if( GDALGetDriverByName( "GPSBabel" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "GPSBabel" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "GPSBabel" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_gpsbabel.html" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "GPSBABEL:" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
+"<OpenOptionList>"
+"  <Option name='FILENAME' type='string' description='Filename to open'/>"
+"  <Option name='GPSBABEL_DRIVER' type='string' description='Name of the GPSBabel to use'/>"
+"</OpenOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+"<CreationOptionList>"
+"  <Option name='GPSBABEL_DRIVER' type='string' description='Name of the GPSBabel to use'/>"
+"</CreationOptionList>");
+
+    poDriver->pfnOpen = OGRGPSBabelDriverOpen;
+    poDriver->pfnIdentify = OGRGPSBabelDriverIdentify;
+    poDriver->pfnCreate = OGRGPSBabelDriverCreate;
+    poDriver->pfnDelete = OGRGPSBabelDriverDelete;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
index eff1a65..0ee64b7 100644
--- a/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
+++ b/ogr/ogrsf_frmts/gpsbabel/ogrgpsbabelwritedatasource.cpp
@@ -1,250 +1,248 @@
-/******************************************************************************
- * $Id: ogrgpsbabelwritedatasource.cpp 32982 2016-01-14 16:53:57Z goatbar $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements OGRGPSBabelWriteDataSource class.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include <cstring>
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "cpl_error.h"
-#include "cpl_spawn.h"
-
-#include "ogr_gpsbabel.h"
-
-CPL_CVSID("$Id: ogrgpsbabelwritedatasource.cpp 32982 2016-01-14 16:53:57Z goatbar $");
-
-/************************************************************************/
-/*                    OGRGPSBabelWriteDataSource()                      */
-/************************************************************************/
-
-OGRGPSBabelWriteDataSource::OGRGPSBabelWriteDataSource() :
-    pszName(NULL),
-    pszGPSBabelDriverName(NULL),
-    pszFilename(NULL),
-    poGPXDS(NULL)
-{}
-
-/************************************************************************/
-/*                  ~OGRGPSBabelWriteDataSource()                       */
-/************************************************************************/
-
-OGRGPSBabelWriteDataSource::~OGRGPSBabelWriteDataSource()
-
-{
-    if (poGPXDS)
-        GDALClose( poGPXDS );
-
-    Convert();
-
-    CPLFree(pszName);
-    CPLFree(pszGPSBabelDriverName);
-    CPLFree(pszFilename);
-}
-
-/************************************************************************/
-/*                                Convert()                             */
-/************************************************************************/
-
-int OGRGPSBabelWriteDataSource::Convert()
-{
-    int nRet = -1;
-    if( osTmpFileName.size() > 0 && pszFilename != NULL &&
-         pszGPSBabelDriverName != NULL )
-    {
-        if (OGRGPSBabelDataSource::IsSpecialFile(pszFilename))
-        {
-            /* Special file : don't try to open it */
-            VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
-            if (tmpfp)
-            {
-                const char* const argv[] = {
-                    "gpsbabel", "-i", "gpx", "-f", "-",
-                    "-o", pszGPSBabelDriverName, "-F", pszFilename, NULL };
-                nRet = CPLSpawn(argv, tmpfp, NULL, TRUE);
-
-                VSIFCloseL(tmpfp);
-                tmpfp = NULL;
-            }
-        }
-        else
-        {
-            VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
-            if (fp == NULL)
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Cannot open file %s", pszFilename );
-            }
-            else
-            {
-                VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
-                if (tmpfp)
-                {
-                    const char* const argv[] = {
-                        "gpsbabel", "-i", "gpx", "-f", "-",
-                        "-o", pszGPSBabelDriverName, "-F", "-", NULL };
-                    nRet = CPLSpawn(argv, tmpfp, fp, TRUE);
-
-                    VSIFCloseL(tmpfp);
-                    tmpfp = NULL;
-                }
-
-                VSIFCloseL(fp);
-                fp = NULL;
-            }
-        }
-
-        VSIUnlink(osTmpFileName.c_str());
-        osTmpFileName = "";
-    }
-
-    return nRet == 0;
-}
-
-/************************************************************************/
-/*                                 Create()                             */
-/************************************************************************/
-
-int OGRGPSBabelWriteDataSource::Create( const char * pszNameIn,
-                                        char **papszOptions )
-{
-    GDALDriver* poGPXDriver
-        = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("GPX");
-    if (poGPXDriver == NULL)
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "GPX driver is necessary for GPSBabel write support" );
-        return FALSE;
-    }
-
-    if (!STARTS_WITH_CI(pszNameIn, "GPSBABEL:"))
-    {
-        const char* pszOptionGPSBabelDriverName =
-                CSLFetchNameValue(papszOptions, "GPSBABEL_DRIVER");
-        if (pszOptionGPSBabelDriverName != NULL)
-            pszGPSBabelDriverName = CPLStrdup(pszOptionGPSBabelDriverName);
-        else
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "GPSBABEL_DRIVER dataset creation option expected" );
-            return FALSE;
-        }
-
-        pszFilename = CPLStrdup(pszNameIn);
-    }
-    else
-    {
-        const char* pszSep = strchr(pszNameIn + 9, ':');
-        if (pszSep == NULL)
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Wrong syntax. Expected GPSBabel:driver_name[,options]*:"
-                      "file_name" );
-            return FALSE;
-        }
-
-        pszGPSBabelDriverName = CPLStrdup(pszNameIn + 9);
-        *(strchr(pszGPSBabelDriverName, ':')) = '\0';
-
-        pszFilename = CPLStrdup(pszSep+1);
-    }
-
-    /* A bit of validation to avoid command line injection */
-    if (!OGRGPSBabelDataSource::IsValidDriverName(pszGPSBabelDriverName))
-        return FALSE;
-
-    const char* pszOptionUseTempFile
-        = CSLFetchNameValue(papszOptions, "USE_TEMPFILE");
-    if (pszOptionUseTempFile == NULL)
-        pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", NULL);
-    if (pszOptionUseTempFile && CPLTestBool(pszOptionUseTempFile))
-        osTmpFileName = CPLGenerateTempFilename(NULL);
-    else
-        osTmpFileName.Printf("/vsimem/ogrgpsbabeldatasource_%p", this);
-
-    poGPXDS = poGPXDriver->Create( osTmpFileName.c_str(), 0, 0, 0,
-                                   GDT_Unknown, papszOptions);
-    if (poGPXDS == NULL)
-        return FALSE;
-
-    this->pszName = CPLStrdup(pszNameIn);
-
-    return TRUE;
-}
-
-/************************************************************************/
-/*                           ICreateLayer()                             */
-/************************************************************************/
-
-OGRLayer *OGRGPSBabelWriteDataSource::ICreateLayer( const char * pszLayerName,
-                                                    OGRSpatialReference *poSRS,
-                                                    OGRwkbGeometryType eType,
-                                                    char ** papszOptions )
-{
-    if( poGPXDS )
-        return poGPXDS->CreateLayer(pszLayerName, poSRS, eType, papszOptions);
-    return NULL;
-}
-
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRGPSBabelWriteDataSource::TestCapability( const char * pszCap )
-
-{
-    if( EQUAL(pszCap,ODsCCreateLayer) )
-        return TRUE;
-
-    return FALSE;
-}
-
-/************************************************************************/
-/*                              GetLayer()                              */
-/************************************************************************/
-
-OGRLayer *OGRGPSBabelWriteDataSource::GetLayer( int iLayer )
-
-{
-    if( poGPXDS )
-        return poGPXDS->GetLayer(iLayer);
-
-    return NULL;
-}
-
-/************************************************************************/
-/*                         GetLayerCount()                              */
-/************************************************************************/
-
-int OGRGPSBabelWriteDataSource::GetLayerCount()
-
-{
-    if( poGPXDS )
-        return poGPXDS->GetLayerCount();
-
-    return 0;
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRGPSBabelWriteDataSource class.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <cstring>
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "cpl_error.h"
+#include "cpl_spawn.h"
+
+#include "ogr_gpsbabel.h"
+
+CPL_CVSID("$Id: ogrgpsbabelwritedatasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+/************************************************************************/
+/*                    OGRGPSBabelWriteDataSource()                      */
+/************************************************************************/
+
+OGRGPSBabelWriteDataSource::OGRGPSBabelWriteDataSource() :
+    pszName(NULL),
+    pszGPSBabelDriverName(NULL),
+    pszFilename(NULL),
+    poGPXDS(NULL)
+{}
+
+/************************************************************************/
+/*                  ~OGRGPSBabelWriteDataSource()                       */
+/************************************************************************/
+
+OGRGPSBabelWriteDataSource::~OGRGPSBabelWriteDataSource()
+
+{
+    if (poGPXDS)
+        GDALClose( poGPXDS );
+
+    Convert();
+
+    CPLFree(pszName);
+    CPLFree(pszGPSBabelDriverName);
+    CPLFree(pszFilename);
+}
+
+/************************************************************************/
+/*                                Convert()                             */
+/************************************************************************/
+
+bool OGRGPSBabelWriteDataSource::Convert()
+{
+    int nRet = -1;
+    if( !osTmpFileName.empty() && pszFilename != NULL &&
+         pszGPSBabelDriverName != NULL )
+    {
+        if (OGRGPSBabelDataSource::IsSpecialFile(pszFilename))
+        {
+            /* Special file : don't try to open it */
+            VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
+            if (tmpfp)
+            {
+                const char* const argv[] = {
+                    "gpsbabel", "-i", "gpx", "-f", "-",
+                    "-o", pszGPSBabelDriverName, "-F", pszFilename, NULL };
+                nRet = CPLSpawn(argv, tmpfp, NULL, TRUE);
+
+                VSIFCloseL(tmpfp);
+                tmpfp = NULL;
+            }
+        }
+        else
+        {
+            VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
+            if (fp == NULL)
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "Cannot open file %s", pszFilename );
+            }
+            else
+            {
+                VSILFILE* tmpfp = VSIFOpenL(osTmpFileName.c_str(), "rb");
+                if (tmpfp)
+                {
+                    const char* const argv[] = {
+                        "gpsbabel", "-i", "gpx", "-f", "-",
+                        "-o", pszGPSBabelDriverName, "-F", "-", NULL };
+                    nRet = CPLSpawn(argv, tmpfp, fp, TRUE);
+
+                    VSIFCloseL(tmpfp);
+                    tmpfp = NULL;
+                }
+
+                VSIFCloseL(fp);
+                fp = NULL;
+            }
+        }
+
+        VSIUnlink(osTmpFileName.c_str());
+        osTmpFileName = "";
+    }
+
+    return nRet == 0;
+}
+
+/************************************************************************/
+/*                                 Create()                             */
+/************************************************************************/
+
+int OGRGPSBabelWriteDataSource::Create( const char * pszNameIn,
+                                        char **papszOptions )
+{
+    GDALDriver* poGPXDriver
+        = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("GPX");
+    if (poGPXDriver == NULL)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "GPX driver is necessary for GPSBabel write support" );
+        return FALSE;
+    }
+
+    if (!STARTS_WITH_CI(pszNameIn, "GPSBABEL:"))
+    {
+        const char* pszOptionGPSBabelDriverName =
+                CSLFetchNameValue(papszOptions, "GPSBABEL_DRIVER");
+        if (pszOptionGPSBabelDriverName != NULL)
+            pszGPSBabelDriverName = CPLStrdup(pszOptionGPSBabelDriverName);
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "GPSBABEL_DRIVER dataset creation option expected" );
+            return FALSE;
+        }
+
+        pszFilename = CPLStrdup(pszNameIn);
+    }
+    else
+    {
+        const char* pszSep = strchr(pszNameIn + 9, ':');
+        if (pszSep == NULL)
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Wrong syntax. Expected GPSBabel:driver_name[,options]*:"
+                      "file_name" );
+            return FALSE;
+        }
+
+        pszGPSBabelDriverName = CPLStrdup(pszNameIn + 9);
+        *(strchr(pszGPSBabelDriverName, ':')) = '\0';
+
+        pszFilename = CPLStrdup(pszSep+1);
+    }
+
+    /* A bit of validation to avoid command line injection */
+    if (!OGRGPSBabelDataSource::IsValidDriverName(pszGPSBabelDriverName))
+        return FALSE;
+
+    const char* pszOptionUseTempFile
+        = CSLFetchNameValue(papszOptions, "USE_TEMPFILE");
+    if (pszOptionUseTempFile == NULL)
+        pszOptionUseTempFile = CPLGetConfigOption("USE_TEMPFILE", NULL);
+    if (pszOptionUseTempFile && CPLTestBool(pszOptionUseTempFile))
+        osTmpFileName = CPLGenerateTempFilename(NULL);
+    else
+        osTmpFileName.Printf("/vsimem/ogrgpsbabeldatasource_%p", this);
+
+    poGPXDS = poGPXDriver->Create( osTmpFileName.c_str(), 0, 0, 0,
+                                   GDT_Unknown, papszOptions);
+    if (poGPXDS == NULL)
+        return FALSE;
+
+    pszName = CPLStrdup(pszNameIn);
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                           ICreateLayer()                             */
+/************************************************************************/
+
+OGRLayer *OGRGPSBabelWriteDataSource::ICreateLayer( const char * pszLayerName,
+                                                    OGRSpatialReference *poSRS,
+                                                    OGRwkbGeometryType eType,
+                                                    char ** papszOptions )
+{
+    if( poGPXDS )
+        return poGPXDS->CreateLayer(pszLayerName, poSRS, eType, papszOptions);
+    return NULL;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRGPSBabelWriteDataSource::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,ODsCCreateLayer) )
+        return TRUE;
+
+    return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRGPSBabelWriteDataSource::GetLayer( int iLayer )
+
+{
+    if( poGPXDS )
+        return poGPXDS->GetLayer(iLayer);
+
+    return NULL;
+}
+
+/************************************************************************/
+/*                         GetLayerCount()                              */
+/************************************************************************/
+
+int OGRGPSBabelWriteDataSource::GetLayerCount()
+
+{
+    if( poGPXDS )
+        return poGPXDS->GetLayerCount();
+
+    return 0;
+}
diff --git a/ogr/ogrsf_frmts/gpx/ogr_gpx.h b/ogr/ogrsf_frmts/gpx/ogr_gpx.h
index c6f3a18..c3c5b2a 100644
--- a/ogr/ogrsf_frmts/gpx/ogr_gpx.h
+++ b/ogr/ogrsf_frmts/gpx/ogr_gpx.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gpx.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_gpx.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GPX Translator
  * Purpose:  Definition of classes for OGR .gpx driver.
@@ -38,7 +38,6 @@
 
 class OGRGPXDataSource;
 
-
 typedef enum
 {
     GPX_NONE,
@@ -128,7 +127,7 @@ class OGRGPXLayer : public OGRLayer
 #ifdef HAVE_EXPAT
     void               AddStrToSubElementValue(const char* pszStr);
 #endif
-    int                OGRGPX_WriteXMLExtension(const char* pszTagName,
+    bool               OGRGPX_WriteXMLExtension(const char* pszTagName,
                                                 const char* pszContent);
 
   public:
@@ -139,15 +138,15 @@ class OGRGPXLayer : public OGRLayer
                                     int bWriteMode = FALSE);
                         ~OGRGPXLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
-    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK );
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
+    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
 #ifdef HAVE_EXPAT
     void                startElementCbk(const char *pszName, const char **ppszAttr);
@@ -217,17 +216,17 @@ class OGRGPXDataSource : public OGRDataSource
     int                 Create( const char *pszFilename,
                               char **papszOptions );
 
-    const char*         GetName() { return pszName; }
+    const char*         GetName() override { return pszName; }
 
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer*           GetLayer( int );
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer*           GetLayer( int ) override;
 
     OGRLayer *          ICreateLayer( const char * pszLayerName,
                                     OGRSpatialReference *poSRS,
                                     OGRwkbGeometryType eType,
-                                    char ** papszOptions );
+                                    char ** papszOptions ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     VSILFILE *              GetOutputFP() { return fpOutput; }
     void                SetLastGPXGeomTypeWritten(GPXGeometryType gpxGeomType)
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
index 714c5d6..310769d 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgpxdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXDataSource class
@@ -32,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_gpx.h"
 
-CPL_CVSID("$Id: ogrgpxdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrgpxdatasource.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 static const int SPACE_FOR_METADATA = 160;
 
@@ -241,7 +240,6 @@ void OGRGPXDataSource::startElementValidateCbk(
     }
 }
 
-
 /************************************************************************/
 /*                      dataHandlerValidateCbk()                        */
 /************************************************************************/
@@ -258,7 +256,6 @@ void OGRGPXDataSource::dataHandlerValidateCbk(CPL_UNUSED const char *data,
     }
 }
 
-
 static void XMLCALL startElementValidateCbk(
     void *pUserData, const char *pszName, const char **ppszAttr)
 {
@@ -311,8 +308,8 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
     XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk);
 
     char aBuf[BUFSIZ];
-    int nDone;
-    unsigned int nLen;
+    int nDone = 0;
+    unsigned int nLen = 0;
     int nCount = 0;
 
     /* Begin to parse the file and look for the <gpx> element */
@@ -404,7 +401,7 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
         papoLayers[4] = new OGRGPXLayer( pszName, "track_points", GPX_TRACK_POINT, this, FALSE );
     }
 
-    return (validity == GPX_VALIDITY_VALID);
+    return validity == GPX_VALIDITY_VALID;
 #else
     VSILFILE* fp = VSIFOpenL(pszFilename, "r");
     if (fp)
@@ -423,7 +420,6 @@ int OGRGPXDataSource::Open( const char * pszFilename, int bUpdateIn)
 #endif
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
@@ -433,7 +429,7 @@ int OGRGPXDataSource::Create( const char *pszFilename,
 {
     if( fpOutput != NULL)
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return FALSE;
     }
 
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp
index 826f661..e08c226 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgpxdriver.cpp 32663 2016-01-02 03:39:54Z goatbar $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXDriver.
@@ -30,7 +29,7 @@
 #include "ogr_gpx.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgpxdriver.cpp 32663 2016-01-02 03:39:54Z goatbar $");
+CPL_CVSID("$Id: ogrgpxdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
diff --git a/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp b/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp
index 0877447..050202b 100644
--- a/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp
+++ b/ogr/ogrsf_frmts/gpx/ogrgpxlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgpxlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GPX Translator
  * Purpose:  Implements OGRGPXLayer class.
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrgpxlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrgpxlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 static const int FLD_TRACK_FID = 0;
 static const int FLD_TRACK_SEG_ID = 1;
@@ -60,6 +59,8 @@ OGRGPXLayer::OGRGPXLayer( const char* pszFilename,
                           GPXGeometryType gpxGeomTypeIn,
                           OGRGPXDataSource* poDSIn,
                           int bWriteModeIn ) :
+    poDS( poDSIn ),
+    gpxGeomType( gpxGeomTypeIn ),
     bWriteMode(CPL_TO_BOOL(bWriteModeIn)),
     nNextFID(0),
 #ifdef HAVE_EXPAT
@@ -96,9 +97,6 @@ OGRGPXLayer::OGRGPXLayer( const char* pszFilename,
     nDataHandlerCounter(0)
 #endif
 {
-    poDS = poDSIn;
-    gpxGeomType = gpxGeomTypeIn;
-
 #ifdef HAVE_EXPAT
     const char* gpxVersion = poDS->GetVersion();
 #endif
@@ -448,8 +446,11 @@ void OGRGPXLayer::ResetReading()
     depthLevel = 0;
     interestingDepthLevel = 0;
 
-    trkFID = trkSegId = trkSegPtId = 0;
-    rteFID = rtePtId = 0;
+    trkFID = 0;
+    trkSegId = 0;
+    trkSegPtId = 0;
+    rteFID = 0;
+    rtePtId = 0;
 }
 
 #ifdef HAVE_EXPAT
@@ -717,19 +718,25 @@ void OGRGPXLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             {
                 for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
                 {
-                    int bMatch;
+                    bool bMatch = false;
                     if (iField >= nGPXFields)
                     {
                         char* pszCompatibleName = OGRGPX_GetOGRCompatibleTagName(pszName);
-                        bMatch = (strcmp(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
-                                        pszCompatibleName ) == 0);
+                        bMatch =
+                            strcmp(poFeatureDefn->
+                                   GetFieldDefn(iField)->GetNameRef(),
+                                   pszCompatibleName ) == 0;
                         CPLFree(pszCompatibleName);
                     }
                     else
-                        bMatch = (strcmp(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(),
-                                        pszName ) == 0);
+                    {
+                        bMatch =
+                            strcmp(poFeatureDefn->
+                                   GetFieldDefn(iField)->GetNameRef(),
+                                   pszName ) == 0;
+                    }
 
-                    if (bMatch)
+                    if( bMatch )
                     {
                         iCurrentField = iField;
                         pszSubElementName = CPLStrdup(pszName);
@@ -818,7 +825,7 @@ void OGRGPXLayer::endElementCbk(const char *pszName)
                         {
                             if (strcmp(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), "ele" ) == 0)
                             {
-                                if( poFeature->IsFieldSet( iField ) )
+                                if( poFeature->IsFieldSetAndNotNull( iField ) )
                                 {
                                     double val =  poFeature->GetFieldAsDouble( iField);
                                     ((OGRPoint*)poFeature->GetGeometryRef())->setZ(val);
@@ -1081,7 +1088,7 @@ OGRFeature *OGRGPXLayer::GetNextFeature()
     nFeatureTabIndex = 0;
     nWithoutEventCounter = 0;
 
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -1145,7 +1152,7 @@ static char* OGRGPX_GetXMLCompatibleTagName(const char* pszExtensionsNS,
 
 static char* OGRGPX_GetUTF8String(const char* pszString)
 {
-    char *pszEscaped;
+    char *pszEscaped = NULL;
     if (!CPLIsUTF8(pszString, -1) &&
          CPLTestBool(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
     {
@@ -1167,7 +1174,9 @@ static char* OGRGPX_GetUTF8String(const char* pszString)
         pszEscaped = CPLForceToASCII(pszString, -1, '?');
     }
     else
+    {
         pszEscaped = CPLStrdup(pszString);
+    }
 
     return pszEscaped;
 }
@@ -1176,20 +1185,19 @@ static char* OGRGPX_GetUTF8String(const char* pszString)
 /*                   OGRGPX_WriteXMLExtension()                          */
 /************************************************************************/
 
-int OGRGPXLayer::OGRGPX_WriteXMLExtension(const char* pszTagName,
-                                          const char* pszContent)
+bool OGRGPXLayer::OGRGPX_WriteXMLExtension( const char* pszTagName,
+                                            const char* pszContent )
 {
     CPLXMLNode* poXML = CPLParseXMLString(pszContent);
     if (poXML)
     {
-        char* pszTagNameWithNS;
-        const char* pszXMLNS = NULL;
         const char* pszUnderscore = strchr(pszTagName, '_');
-        pszTagNameWithNS = CPLStrdup(pszTagName);
+        char* pszTagNameWithNS = CPLStrdup(pszTagName);
         if (pszUnderscore)
             pszTagNameWithNS[pszUnderscore - pszTagName] = ':';
 
         /* If we detect a Garmin GPX extension, add its xmlns */
+        const char* pszXMLNS = NULL;
         if (strcmp(pszTagName, "gpxx_WaypointExtension") == 0)
             pszXMLNS = " xmlns:gpxx=\"http://www.garmin.com/xmlschemas/GpxExtensions/v3\"";
 
@@ -1202,10 +1210,10 @@ int OGRGPXLayer::OGRGPX_WriteXMLExtension(const char* pszTagName,
         CPLFree(pszTagNameWithNS);
         CPLDestroyXMLNode(poXML);
 
-        return TRUE;
+        return true;
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -1227,7 +1235,7 @@ void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeatureIn, int nIdentLev
     for( ; i < nGPXFields; i++ )
     {
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
-        if( poFeatureIn->IsFieldSet( i ) )
+        if( poFeatureIn->IsFieldSetAndNotNull( i ) )
         {
             const char* pszName = poFieldDefn->GetNameRef();
             if (strcmp(pszName, "time") == 0)
@@ -1243,9 +1251,9 @@ void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeatureIn, int nIdentLev
                 {
                     AddIdent(fp, nIdentLevel);
                     VSIFPrintfL(fp, "<link href=\"%s\">", poFeatureIn->GetFieldAsString( i ));
-                    if( poFeatureIn->IsFieldSet( i + 1 ) )
+                    if( poFeatureIn->IsFieldSetAndNotNull( i + 1 ) )
                         VSIFPrintfL(fp, "<text>%s</text>", poFeatureIn->GetFieldAsString( i + 1 ));
-                    if( poFeatureIn->IsFieldSet( i + 2 ) )
+                    if( poFeatureIn->IsFieldSetAndNotNull( i + 2 ) )
                         VSIFPrintfL(fp, "<type>%s</type>", poFeatureIn->GetFieldAsString( i + 2 ));
                     poDS->PrintLine("</link>");
                 }
@@ -1278,7 +1286,7 @@ void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeatureIn, int nIdentLev
         for(;i<n;i++)
         {
             OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
-            if( poFeatureIn->IsFieldSet( i ) )
+            if( poFeatureIn->IsFieldSetAndNotNull( i ) )
             {
                 char* compatibleName =
                         OGRGPX_GetXMLCompatibleTagName(pszExtensionsNS, poFieldDefn->GetNameRef());
@@ -1302,7 +1310,7 @@ void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeatureIn, int nIdentLev
                     /* Try to detect XML content */
                     if (pszRaw[0] == '<' && pszRaw[strlen(pszRaw) - 1] == '>')
                     {
-                        if (OGRGPX_WriteXMLExtension( compatibleName, pszRaw))
+                        if( OGRGPX_WriteXMLExtension( compatibleName, pszRaw) )
                         {
                             CPLFree(compatibleName);
                             continue;
@@ -1315,7 +1323,8 @@ void OGRGPXLayer::WriteFeatureAttributes( OGRFeature *poFeatureIn, int nIdentLev
                     {
                         char* pszUnescapedContent = CPLUnescapeString( pszRaw, NULL, CPLES_XML );
 
-                        if (OGRGPX_WriteXMLExtension(compatibleName, pszUnescapedContent))
+                        if( OGRGPX_WriteXMLExtension(compatibleName,
+                                                     pszUnescapedContent) )
                         {
                             CPLFree(pszUnescapedContent);
                             CPLFree(compatibleName);
@@ -1677,7 +1686,7 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeatureIn )
             return OGRERR_FAILURE;
         }
 
-        if ( !poFeatureIn->IsFieldSet(FLD_ROUTE_FID) )
+        if ( !poFeatureIn->IsFieldSetAndNotNull(FLD_ROUTE_FID) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Field %s must be set.", poFeatureDefn->GetFieldDefn(FLD_ROUTE_FID)->GetNameRef() );
@@ -1699,7 +1708,7 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeatureIn )
                 poDS->PrintLine("</rte>");
             }
             poDS->PrintLine("<rte>");
-            if ( poFeatureIn->IsFieldSet(FLD_ROUTE_NAME) )
+            if ( poFeatureIn->IsFieldSetAndNotNull(FLD_ROUTE_NAME) )
             {
                 char* pszValue =
                             OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( FLD_ROUTE_NAME ));
@@ -1721,7 +1730,6 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeatureIn )
         poDS->PrintLine("  <rtept lat=\"%s\" lon=\"%s\">", szLat, szLon);
         WriteFeatureAttributes(poFeatureIn, 2);
         poDS->PrintLine("  </rtept>");
-
     }
     else
     {
@@ -1746,7 +1754,7 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeatureIn )
             return OGRERR_FAILURE;
         }
 
-        if ( !poFeatureIn->IsFieldSet(FLD_TRACK_FID) )
+        if ( !poFeatureIn->IsFieldSetAndNotNull(FLD_TRACK_FID) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Field %s must be set.", poFeatureDefn->GetFieldDefn(FLD_TRACK_FID)->GetNameRef() );
@@ -1758,7 +1766,7 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeatureIn )
                       "Invalid value for field %s.", poFeatureDefn->GetFieldDefn(FLD_TRACK_FID)->GetNameRef() );
             return OGRERR_FAILURE;
         }
-        if ( !poFeatureIn->IsFieldSet(FLD_TRACK_SEG_ID) )
+        if ( !poFeatureIn->IsFieldSetAndNotNull(FLD_TRACK_SEG_ID) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Field %s must be set.", poFeatureDefn->GetFieldDefn(FLD_TRACK_SEG_ID)->GetNameRef() );
@@ -1782,7 +1790,7 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeatureIn )
             }
             poDS->PrintLine("<trk>");
 
-            if ( poFeatureIn->IsFieldSet(FLD_TRACK_NAME) )
+            if ( poFeatureIn->IsFieldSetAndNotNull(FLD_TRACK_NAME) )
             {
                 char* pszValue =
                             OGRGetXML_UTF8_EscapedString(poFeatureIn->GetFieldAsString( FLD_TRACK_NAME ));
@@ -1817,13 +1825,10 @@ OGRErr OGRGPXLayer::ICreateFeature( OGRFeature *poFeatureIn )
     return OGRERR_NONE;
 }
 
-
-
 /************************************************************************/
 /*                            CreateField()                             */
 /************************************************************************/
 
-
 OGRErr OGRGPXLayer::CreateField( OGRFieldDefn *poField,
                                  CPL_UNUSED int bApproxOK )
 {
@@ -1835,7 +1840,7 @@ OGRErr OGRGPXLayer::CreateField( OGRFieldDefn *poField,
             return OGRERR_NONE;
         }
     }
-    if (poDS->GetUseExtensions() == FALSE)
+    if( !poDS->GetUseExtensions() )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                 "Field of name '%s' is not supported in GPX schema. "
@@ -1868,7 +1873,6 @@ int OGRGPXLayer::TestCapability( const char * pszCap )
         return FALSE;
 }
 
-
 /************************************************************************/
 /*                       LoadExtensionsSchema()                         */
 /************************************************************************/
@@ -1895,7 +1899,6 @@ static void XMLCALL dataHandlerLoadSchemaCbk(
     static_cast<OGRGPXLayer *>(pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
 }
 
-
 /** This function parses the whole file to detect the extensions fields */
 void OGRGPXLayer::LoadExtensionsSchema()
 {
@@ -1917,7 +1920,7 @@ void OGRGPXLayer::LoadExtensionsSchema()
     bStopParsing = false;
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -1951,12 +1954,10 @@ void OGRGPXLayer::LoadExtensionsSchema()
     VSIFSeekL( fpGPX, 0, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                  startElementLoadSchemaCbk()                         */
 /************************************************************************/
 
-
 void OGRGPXLayer::startElementLoadSchemaCbk(const char *pszName,
                                             CPL_UNUSED const char **ppszAttr)
 {
@@ -2007,18 +2008,26 @@ void OGRGPXLayer::startElementLoadSchemaCbk(const char *pszName,
             CPLFree(pszSubElementName);
             pszSubElementName = CPLStrdup(pszName);
 
-            int iField;
-            for(iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+            int iField = 0;  // Used after for.
+            for( ; iField < poFeatureDefn->GetFieldCount(); iField++ )
             {
-                int bMatch;
-                if (iField >= nGPXFields)
+                bool bMatch = false;
+                if( iField >= nGPXFields )
                 {
                     char* pszCompatibleName = OGRGPX_GetOGRCompatibleTagName(pszName);
-                    bMatch = (strcmp(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), pszCompatibleName ) == 0);
+                    bMatch =
+                        strcmp(poFeatureDefn->
+                               GetFieldDefn(iField)->GetNameRef(),
+                               pszCompatibleName ) == 0;
                     CPLFree(pszCompatibleName);
                 }
                 else
-                    bMatch = (strcmp(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), pszName ) == 0);
+                {
+                    bMatch =
+                        strcmp(poFeatureDefn->
+                               GetFieldDefn(iField)->GetNameRef(),
+                               pszName ) == 0;
+                }
 
                 if (bMatch)
                 {
@@ -2049,12 +2058,11 @@ void OGRGPXLayer::startElementLoadSchemaCbk(const char *pszName,
     depthLevel++;
 }
 
-
 /************************************************************************/
 /*                   endElementLoadSchemaCbk()                           */
 /************************************************************************/
 
-static int OGRGPXIsInt(const char* pszStr)
+static bool OGRGPXIsInt( const char* pszStr )
 {
     while(*pszStr == ' ')
         pszStr++;
@@ -2064,15 +2072,14 @@ static int OGRGPXIsInt(const char* pszStr)
         if (pszStr[i] == '+' || pszStr[i] == '-')
         {
             if (i != 0)
-                return FALSE;
+                return false;
         }
         else if (!(pszStr[i] >= '0' && pszStr[i] <= '9'))
-            return FALSE;
+            return false;
     }
-    return TRUE;
+    return true;
 }
 
-
 void OGRGPXLayer::endElementLoadSchemaCbk(const char *pszName)
 {
     if (bStopParsing) return;
@@ -2130,7 +2137,7 @@ void OGRGPXLayer::endElementLoadSchemaCbk(const char *pszName)
                     {
                         if (currentFieldDefn->GetType() == OFTInteger)
                         {
-                            if (OGRGPXIsInt(pszSubElementValue) == FALSE)
+                            if( !OGRGPXIsInt(pszSubElementValue) )
                             {
                                 currentFieldDefn->SetType(OFTReal);
                             }
diff --git a/ogr/ogrsf_frmts/grass/ogrgrass.h b/ogr/ogrsf_frmts/grass/ogrgrass.h
index 3cda766..b98e358 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrass.h
+++ b/ogr/ogrsf_frmts/grass/ogrgrass.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrgrass.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogrgrass.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/GRASS driver.
@@ -50,81 +50,76 @@ extern "C" {
 class OGRGRASSLayer : public OGRLayer
 {
   public:
-                        OGRGRASSLayer(	int layer, struct Map_info * map );
-                        ~OGRGRASSLayer();
+                        OGRGRASSLayer( int layer, struct Map_info * map );
+                        virtual ~OGRGRASSLayer();
 
     // Layer info
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-    GIntBig             GetFeatureCount( int );
-    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
+    GIntBig             GetFeatureCount( int ) override;
+    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-    virtual OGRSpatialReference *GetSpatialRef();
-    int                 TestCapability( const char * );
+    virtual OGRSpatialReference *GetSpatialRef() override;
+    int                 TestCapability( const char * ) override;
 
     // Reading
-    void                ResetReading();
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
-    OGRFeature *        GetNextFeature();
-    OGRFeature         *GetFeature( GIntBig nFeatureId );
+    void                ResetReading() override;
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
+    OGRFeature *        GetNextFeature() override;
+    OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
 
     // Filters
-    virtual OGRErr 	SetAttributeFilter( const char *query );
-    virtual void 	SetSpatialFilter( OGRGeometry * poGeomIn );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual OGRErr      SetAttributeFilter( const char *query ) override;
+    virtual void        SetSpatialFilter( OGRGeometry * poGeomIn ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    // Write access, not supported:
-    virtual OGRErr      CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
-    OGRErr              ISetFeature( OGRFeature *poFeature );
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
-
   private:
-    char		*pszName;
+    char                *pszName;
     OGRSpatialReference *poSRS;
-    OGRFeatureDefn	*poFeatureDefn;
-    char		*pszQuery;	// Attribute filter string
+    OGRFeatureDefn      *poFeatureDefn;
+    char                *pszQuery;      // Attribute filter string
 
-    int			iNextId;
-    int			nTotalCount;
-    int			iLayer;		// Layer number
-    int			iLayerIndex;	// Layer index (in GRASS category index)
-    int			iCatField;	// Field where category (key) is stored
-    int			nFields;
-    int 		*paFeatureIndex; // Array of indexes to category index array
+    int                 iNextId;
+    int                 nTotalCount;
+    int                 iLayer;         // Layer number
+    int                 iLayerIndex;    // Layer index (in GRASS category index)
+    int                 iCatField;      // Field where category (key) is stored
+    int                 nFields;
+    int                 *paFeatureIndex; // Array of indexes to category index array
 
     // Vector map
-    struct Map_info 	*poMap;
+    struct Map_info     *poMap;
     struct field_info   *poLink;
 
     // Database connection
-    bool 		bHaveAttributes;
+    bool                bHaveAttributes;
 
-    dbString		*poDbString;
-    dbDriver		*poDriver;
-    dbCursor		*poCursor;
+    dbString            *poDbString;
+    dbDriver            *poDriver;
+    dbCursor            *poCursor;
 
-    bool		bCursorOpened;	// Sequential database cursor opened
-    int 		iCurrentCat;	// Current category in select cursor
+    bool                bCursorOpened;  // Sequential database cursor opened
+    int                 iCurrentCat;    // Current category in select cursor
 
-    struct line_pnts	*poPoints;
-    struct line_cats	*poCats;
+    struct line_pnts    *poPoints;
+    struct line_cats    *poCats;
 
-    bool		StartDbDriver ();
-    bool		StopDbDriver ();
+    bool                StartDbDriver ();
+    bool                StopDbDriver ();
 
-    OGRGeometry		*GetFeatureGeometry ( long nFeatureId, int *cat );
-    bool		SetAttributes ( OGRFeature *feature, dbTable *table );
+    OGRGeometry         *GetFeatureGeometry ( long nFeatureId, int *cat );
+    bool                SetAttributes ( OGRFeature *feature, dbTable *table );
 
     // Features matching spatial filter for ALL features/elements in GRASS
-    char 		*paSpatialMatch;
-    bool 		SetSpatialMatch();
+    char                *paSpatialMatch;
+    bool                SetSpatialMatch();
 
     // Features matching attribute filter for ALL features/elements in GRASS
-    char 		*paQueryMatch;
-    bool 		OpenSequentialCursor();
-    bool 		ResetSequentialCursor();
-    bool 		SetQueryMatch();
+    char                *paQueryMatch;
+    bool                OpenSequentialCursor();
+    bool                ResetSequentialCursor();
+    bool                SetQueryMatch();
 };
 
 /************************************************************************/
@@ -134,33 +129,26 @@ class OGRGRASSDataSource : public OGRDataSource
 {
   public:
                         OGRGRASSDataSource();
-                        ~OGRGRASSDataSource();
+                        virtual ~OGRGRASSDataSource();
 
     int                 Open( const char *, int bUpdate, int bTestOpen,
                               int bSingleNewFile = FALSE );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
-
-    int                 TestCapability( const char * );
-
-    // Not implemented (returns NULL):
-    virtual OGRLayer    *ICreateLayer( const char *,
-                                      OGRSpatialReference * = NULL,
-                                      OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
+    int                 TestCapability( const char * ) override;
 
   private:
     OGRGRASSLayer     **papoLayers;
-    char                *pszName;	// Date source name
-    char		*pszGisdbase;	// GISBASE
-    char		*pszLocation;	// location name
-    char		*pszMapset;	// mapset name
-    char		*pszMap;	// name of vector map
+    char                *pszName;       // Date source name
+    char                *pszGisdbase;   // GISBASE
+    char                *pszLocation;   // location name
+    char                *pszMapset;     // mapset name
+    char                *pszMap;        // name of vector map
 
-    struct Map_info 	map;
+    struct Map_info     map;
     int                 nLayers;
 
     int                 bOpened;
@@ -174,17 +162,12 @@ class OGRGRASSDataSource : public OGRDataSource
 class OGRGRASSDriver : public OGRSFDriver
 {
   public:
-			~OGRGRASSDriver();
-
-    const char 		*GetName();
-    OGRDataSource 	*Open( const char *, int );
+                        virtual ~OGRGRASSDriver();
 
-    int                 TestCapability( const char * );
+    const char          *GetName() override;
+    OGRDataSource       *Open( const char *, int ) override;
 
-    // Not implemented (return error/NULL):
-    virtual OGRDataSource *CreateDataSource( const char *pszName,
-	    				     char ** = NULL );
-    OGRErr              DeleteDataSource( const char *pszDataSource );
+    int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGRGRASS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp b/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp
index e454f0a..df184b9 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp
+++ b/ogr/ogrsf_frmts/grass/ogrgrassdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgrassdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGRASSDataSource class.
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrgrassdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrgrassdatasource.cpp 36368 2016-11-21 01:47:49Z rouault $");
 
 #if GRASS_VERSION_MAJOR  >= 7
 #define G__setenv                G_setenv_nogisrc
@@ -41,7 +40,7 @@ CPL_CVSID("$Id: ogrgrassdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 /************************************************************************/
 /*                         Grass2CPLErrorHook()                         */
 /************************************************************************/
-int Grass2OGRErrorHook( char * pszMessage, int bFatal )
+static int Grass2OGRErrorHook( char * pszMessage, int bFatal )
 {
     if( !bFatal )
         CPLError( CE_Warning, CPLE_AppDefined, "GRASS warning: %s", pszMessage );
@@ -95,8 +94,8 @@ typedef int (*GrassErrorHandler)(const char *, int);
 typedef int (*GrassErrorHandler)(char *, int);
 #endif
 
-int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
-                              int bTestOpen, int bSingleNewFileIn )
+int OGRGRASSDataSource::Open( const char * pszNewName, int /*bUpdate*/,
+                              int bTestOpen, int /*bSingleNewFileIn*/ )
 {
     VSIStatBuf  stat;
 
@@ -110,11 +109,11 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
     if ( strstr(pszName,"vector") == NULL || strstr(pszName,"head") == NULL )
     {
         if( !bTestOpen )
-	{
+        {
             CPLError( CE_Failure, CPLE_AppDefined,
                  "%s is not GRASS vector, access failed.\n", pszName );
-	}
-	return FALSE;
+        }
+        return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -123,10 +122,10 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
     if( CPLStat( pszName, &stat ) != 0 || !VSI_ISREG(stat.st_mode) )
     {
         if( !bTestOpen )
-	{
+        {
             CPLError( CE_Failure, CPLE_AppDefined,
                  "%s is not GRASS vector, access failed.\n", pszName );
-	}
+        }
 
         return FALSE;
     }
@@ -135,15 +134,15 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
 /*      Parse datasource name                                           */
 /* -------------------------------------------------------------------- */
     if ( !SplitPath(pszName, &pszGisdbase, &pszLocation,
-		    &pszMapset, &pszMap) )
+                    &pszMapset, &pszMap) )
     {
         if( !bTestOpen )
-	{
+        {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "%s is not GRASS datasource name, access failed.\n",
-		      pszName );
-	}
-	return FALSE;
+                      pszName );
+        }
+        return FALSE;
     }
 
     CPLDebug ( "GRASS", "Gisdbase: %s", pszGisdbase );
@@ -202,7 +201,7 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
     if ( level < 2 ) {
         CPLError( CE_Failure, CPLE_AppDefined,
                  "Cannot open GRASS vector %s on level 2.\n", pszName );
-	return FALSE;
+        return FALSE;
     }
 
     CPLDebug ( "GRASS", "Num lines = %d", Vect_get_num_lines(&map) );
@@ -214,15 +213,13 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
     CPLDebug ( "GRASS", "Num layers = %d", ncidx );
 
     for ( int i = 0; i < ncidx; i++ ) {
-	// Create the layer object
-	OGRGRASSLayer       *poLayer;
-
-        poLayer = new OGRGRASSLayer( i, &map );
+        // Create the layer object
+        OGRGRASSLayer *poLayer = new OGRGRASSLayer( i, &map );
 
         // Add layer to data source layer list
-	papoLayers = (OGRGRASSLayer **)
-	    CPLRealloc( papoLayers,  sizeof(OGRGRASSLayer *) * (nLayers+1) );
-	papoLayers[nLayers++] = poLayer;
+        papoLayers = (OGRGRASSLayer **)
+            CPLRealloc( papoLayers,  sizeof(OGRGRASSLayer *) * (nLayers+1) );
+        papoLayers[nLayers++] = poLayer;
     }
 
     bOpened = TRUE;
@@ -231,25 +228,9 @@ int OGRGRASSDataSource::Open( const char * pszNewName, int bUpdate,
 }
 
 /************************************************************************/
-/*                           ICreateLayer()                             */
-/************************************************************************/
-OGRLayer *
-OGRGRASSDataSource::ICreateLayer( const char * pszLayerName,
-                                 OGRSpatialReference *poSRS,
-                                 OGRwkbGeometryType eType,
-                                 char ** papszOptions )
-
-{
-    CPLError( CE_Failure, CPLE_NoWriteAccess,
-	      "CreateLayer is not supported by GRASS driver" );
-
-    return NULL;
-}
-
-/************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
-int OGRGRASSDataSource::TestCapability( const char * pszCap )
+int OGRGRASSDataSource::TestCapability( const char * /* pszCap*/ )
 {
     return FALSE;
 }
@@ -275,7 +256,7 @@ OGRLayer *OGRGRASSDataSource::GetLayer( int iLayer )
 /*          false - failed                                              */
 /************************************************************************/
 bool OGRGRASSDataSource::SplitPath( char *path, char **gisdbase,
-	                     char **location, char **mapset, char **map )
+                                    char **location, char **mapset, char **map )
 {
     char *p, *ptr[5], *tmp;
     int  i = 0;
@@ -285,23 +266,23 @@ bool OGRGRASSDataSource::SplitPath( char *path, char **gisdbase,
     *gisdbase = *location = *mapset = *map = NULL;
 
     if ( !path || strlen(path) == 0 )
-	return false;
+        return false;
 
     tmp = G_store ( path );
 
     while ( (p = strrchr(tmp,'/')) != NULL  && i < 5 ) {
-	*p = '\0';
+        *p = '\0';
 
-	if ( strlen(p+1) == 0 ) /* repeated '/' */
-	    continue;
+        if ( strlen(p+1) == 0 ) /* repeated '/' */
+            continue;
 
-	ptr[i++] = p+1;
+        ptr[i++] = p+1;
     }
 
     /* Note: empty GISDBASE == 0 is not accepted (relative path) */
     if ( i != 5 ) {
         free ( tmp );
-	return false;
+        return false;
     }
 
     if ( strcmp(ptr[0],"head") != 0 || strcmp(ptr[2],"vector") != 0 ) {
diff --git a/ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp b/ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp
index f1a9521..c09d45d 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp
+++ b/ogr/ogrsf_frmts/grass/ogrgrassdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgrassdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGRASSDriver class.
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrgrassdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrgrassdriver.cpp 36368 2016-11-21 01:47:49Z rouault $");
 
 /************************************************************************/
 /*                          ~OGRGRASSDriver()                           */
@@ -54,9 +53,7 @@ const char *OGRGRASSDriver::GetName()
 OGRDataSource *OGRGRASSDriver::Open( const char * pszFilename,
                                      int bUpdate )
 {
-    OGRGRASSDataSource  *poDS;
-
-    poDS = new OGRGRASSDataSource();
+    OGRGRASSDataSource  *poDS = new OGRGRASSDataSource();
 
     if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
     {
@@ -70,32 +67,9 @@ OGRDataSource *OGRGRASSDriver::Open( const char * pszFilename,
 }
 
 /************************************************************************/
-/*                          CreateDataSource()                          */
-/************************************************************************/
-OGRDataSource *OGRGRASSDriver::CreateDataSource( const char * pszName,
-                                                 char **papszOptions )
-{
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "CreateDataSource is not supported by GRASS driver.\n" );
-
-    return NULL;
-}
-
-/************************************************************************/
-/*                          DeleteDataSource()                          */
-/************************************************************************/
-OGRErr OGRGRASSDriver::DeleteDataSource( const char *pszDataSource )
-{
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "DeleteDataSource is not supported by GRASS driver" );
-
-    return OGRERR_FAILURE;
-}
-
-/************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
-int OGRGRASSDriver::TestCapability( const char * pszCap )
+int OGRGRASSDriver::TestCapability( const char * /*pszCap*/ )
 {
     return FALSE;
 }
@@ -120,4 +94,3 @@ void RegisterOGRGRASS()
 
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp b/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp
index a2be8ea..ea2030e 100644
--- a/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp
+++ b/ogr/ogrsf_frmts/grass/ogrgrasslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgrasslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRGRASSLayer class.
@@ -32,7 +31,7 @@
 #include "ogrgrass.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrgrasslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrgrasslayer.cpp 36368 2016-11-21 01:47:49Z rouault $");
 
 /************************************************************************/
 /*                           OGRGRASSLayer()                            */
@@ -50,6 +49,7 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
     pszQuery = NULL;
     paQueryMatch = NULL;
     paSpatialMatch = NULL;
+    iCurrentCat = 0;
 
     iLayer = Vect_cidx_get_field_number ( poMap, iLayerIndex);
     CPLDebug ( "GRASS", "iLayer = %d", iLayer );
@@ -59,13 +59,13 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
     // Layer name
     if ( poLink && poLink->name )
     {
-	pszName = CPLStrdup( poLink->name );
+        pszName = CPLStrdup( poLink->name );
     }
     else
     {
-	char buf[20];
-	sprintf ( buf, "%d", iLayer );
-	pszName = CPLStrdup( buf );
+        char buf[20];
+        snprintf ( buf, sizeof(buf), "%d", iLayer );
+        pszName = CPLStrdup( buf );
     }
 
     // Because we don't represent centroids as any simple feature, we have to scan
@@ -78,12 +78,12 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
     int cnt = 0;
     for ( int i = 0; i < n; i++ )
     {
-	int cat,type, id;
+        int cat,type, id;
 
-	Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, i, &cat, &type, &id );
+        Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, i, &cat, &type, &id );
 
-	if ( !( type & (GV_POINT|GV_LINES|GV_AREA) ) ) continue;
-	paFeatureIndex[cnt++] = i;
+        if ( !( type & (GV_POINT|GV_LINES|GV_AREA) ) ) continue;
+        paFeatureIndex[cnt++] = i;
     }
 
     poFeatureDefn = new OGRFeatureDefn( pszName );
@@ -94,10 +94,10 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
     int nTypes = Vect_cidx_get_num_types_by_index ( poMap, iLayerIndex );
     int types = 0;
     for ( int i = 0; i < nTypes; i++ ) {
-	int type, count;
-	Vect_cidx_get_type_count_by_index ( poMap, iLayerIndex, i, &type, &count);
-	if ( !(type & (GV_POINT|GV_LINES|GV_AREA) ) ) continue;
-	types |= type;
+        int type, count;
+        Vect_cidx_get_type_count_by_index ( poMap, iLayerIndex, i, &type, &count);
+        if ( !(type & (GV_POINT|GV_LINES|GV_AREA) ) ) continue;
+        types |= type;
         CPLDebug ( "GRASS", "type = %d types = %d", type, types );
     }
 
@@ -131,72 +131,71 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
     db_init_string ( poDbString );
     if ( poLink )
     {
-	if ( StartDbDriver() )
-	{
-	    db_set_string ( poDbString, poLink->table );
-	    dbTable *table;
-	    if ( db_describe_table ( poDriver, poDbString, &table) == DB_OK )
-	    {
-		nFields = db_get_table_number_of_columns ( table );
-		iCatField = -1;
-		for ( int i = 0; i < nFields; i++)
-		{
-		    dbColumn *column = db_get_table_column ( table, i );
-		    int ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );
-
-		    OGRFieldType ogrFtype = OFTInteger;
- 	     	    switch ( ctype ) {
-			 case DB_C_TYPE_INT:
-			    ogrFtype = OFTInteger;
-			    break;
-			 case DB_C_TYPE_DOUBLE:
-			    ogrFtype = OFTReal;
-			    break;
-			 case DB_C_TYPE_STRING:
-			    ogrFtype = OFTString;
-			    break;
-			 case DB_C_TYPE_DATETIME:
-			    ogrFtype = OFTDateTime;
-			    break;
-		    }
-
-		    CPLDebug ( "GRASS", "column = %s type = %d",
-			       db_get_column_name(column), ctype );
-
-		    OGRFieldDefn oField ( db_get_column_name(column), ogrFtype );
-		    poFeatureDefn->AddFieldDefn( &oField );
-
-		    if ( G_strcasecmp(db_get_column_name(column),poLink->key) == 0 )
-		    {
-			iCatField = i;
-		    }
-		}
-		if ( iCatField >= 0  )
-		{
-    		    bHaveAttributes = true;
-		}
-		else
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined, "Cannot find key field" );
-		    db_close_database_shutdown_driver ( poDriver );
-		    poDriver = NULL;
+        if ( StartDbDriver() )
+        {
+            db_set_string ( poDbString, poLink->table );
+            dbTable *table = NULL;
+            if ( db_describe_table ( poDriver, poDbString, &table) == DB_OK )
+            {
+                nFields = db_get_table_number_of_columns ( table );
+                iCatField = -1;
+                for ( int i = 0; i < nFields; i++)
+                {
+                    dbColumn *column = db_get_table_column ( table, i );
+                    int ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );
+
+                    OGRFieldType ogrFtype = OFTInteger;
+                    switch ( ctype ) {
+                         case DB_C_TYPE_INT:
+                            ogrFtype = OFTInteger;
+                            break;
+                         case DB_C_TYPE_DOUBLE:
+                            ogrFtype = OFTReal;
+                            break;
+                         case DB_C_TYPE_STRING:
+                            ogrFtype = OFTString;
+                            break;
+                         case DB_C_TYPE_DATETIME:
+                            ogrFtype = OFTDateTime;
+                            break;
+                    }
+
+                    CPLDebug ( "GRASS", "column = %s type = %d",
+                               db_get_column_name(column), ctype );
+
+                    OGRFieldDefn oField ( db_get_column_name(column), ogrFtype );
+                    poFeatureDefn->AddFieldDefn( &oField );
+
+                    if ( G_strcasecmp(db_get_column_name(column),poLink->key) == 0 )
+                    {
+                        iCatField = i;
+                    }
+                }
+                if ( iCatField >= 0  )
+                {
+                    bHaveAttributes = true;
+                }
+                else
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "Cannot find key field" );
+                    db_close_database_shutdown_driver ( poDriver );
+                    poDriver = NULL;
                 }
             }
-	    else
+            else
             {
-		CPLError( CE_Failure, CPLE_AppDefined, "Cannot describe table %s",
-			  poLink->table );
-
+                CPLError( CE_Failure, CPLE_AppDefined, "Cannot describe table %s",
+                          poLink->table );
             }
-	    db_close_database_shutdown_driver ( poDriver );
-	    poDriver = NULL;
+            db_close_database_shutdown_driver ( poDriver );
+            poDriver = NULL;
         }
     }
 
     if ( !bHaveAttributes && iLayer > 0 ) // Because features in layer 0 have no cats
     {
-	OGRFieldDefn oField("cat", OFTInteger);
-	poFeatureDefn->AddFieldDefn( &oField );
+        OGRFieldDefn oField("cat", OFTInteger);
+        poFeatureDefn->AddFieldDefn( &oField );
     }
 
     if ( getenv("GISBASE") )  // We have some projection info in GISBASE
@@ -208,13 +207,13 @@ OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map )
         // where those variables are set
 
         projinfo = G_get_projinfo();
-	projunits = G_get_projunits();
+        projunits = G_get_projunits();
 
-	char *srsWkt = GPJ_grass_to_wkt ( projinfo, projunits, 0, 0);
+        char *srsWkt = GPJ_grass_to_wkt ( projinfo, projunits, 0, 0);
         if ( srsWkt )
         {
-	    poSRS = new OGRSpatialReference ( srsWkt );
-	    G_free ( srsWkt );
+            poSRS = new OGRSpatialReference ( srsWkt );
+            G_free ( srsWkt );
         }
 
         G_free_key_value(projinfo);
@@ -229,12 +228,12 @@ OGRGRASSLayer::~OGRGRASSLayer()
 {
     if ( bCursorOpened )
     {
-	db_close_cursor ( poCursor);
+        db_close_cursor ( poCursor);
     }
 
     if ( poDriver )
     {
-	StopDbDriver();
+        StopDbDriver();
     }
 
     if ( pszName ) CPLFree ( pszName );
@@ -271,16 +270,16 @@ bool OGRGRASSLayer::StartDbDriver()
 
     if ( !poLink )
     {
-	return false;
+        return false;
     }
     poDriver = db_start_driver_open_database ( poLink->driver, poLink->database );
 
     if ( poDriver == NULL)
     {
-	CPLError( CE_Failure, CPLE_AppDefined, "Cannot open database %s by driver %s, "
-		  "check if GISBASE environment variable is set, the driver is available "
-		  " and the database is accessible.", poLink->driver, poLink->database );
-	return false;
+        CPLError( CE_Failure, CPLE_AppDefined, "Cannot open database %s by driver %s, "
+                  "check if GISBASE environment variable is set, the driver is available "
+                  " and the database is accessible.", poLink->driver, poLink->database );
+        return false;
     }
     return true;
 }
@@ -292,8 +291,8 @@ bool OGRGRASSLayer::StopDbDriver()
 {
     if ( !poDriver )
     {
-	CPLError( CE_Failure, CPLE_AppDefined, "Driver is not started" );
-	return true; // I think that true is OK here
+        CPLError( CE_Failure, CPLE_AppDefined, "Driver is not started" );
+        return true; // I think that true is OK here
     }
 
     // TODO!!!: Because of bug in GRASS library it is impossible
@@ -341,25 +340,25 @@ OGRErr OGRGRASSLayer::SetNextByIndex( GIntBig nIndex )
 {
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
     {
-	iNextId = 0;
-	int count = 0;
+        iNextId = 0;
+        int count = 0;
 
-	while ( true ) {
-	    if( iNextId >= nTotalCount ) break;
-	    if ( count == nIndex ) break;
+        while ( true ) {
+            if( iNextId >= nTotalCount ) break;
+            if ( count == nIndex ) break;
 
-	    // Attributes
-	    if( pszQuery != NULL && !paQueryMatch[iNextId] ) {
-		iNextId++;
-		continue;
+            // Attributes
+            if( pszQuery != NULL && !paQueryMatch[iNextId] ) {
+                iNextId++;
+                continue;
             }
 
-	    // Spatial
-	    if( m_poFilterGeom && !paSpatialMatch[iNextId] ) {
-		iNextId++;
-		continue;
-	    }
-	    count++;
+            // Spatial
+            if( m_poFilterGeom && !paSpatialMatch[iNextId] ) {
+                iNextId++;
+                continue;
+            }
+            count++;
         }
     }
 
@@ -376,16 +375,16 @@ OGRErr OGRGRASSLayer::SetAttributeFilter( const char *query )
     CPLDebug ( "GRASS", "SetAttributeFilter: %s", query  );
 
     if ( query == NULL ) {
-	// Release old if any
-	if ( pszQuery ) {
-	    CPLFree ( pszQuery );
-	    pszQuery = NULL;
-	}
-	if ( paQueryMatch ) {
-	    CPLFree ( paQueryMatch );
-	    paQueryMatch = NULL;
-	}
-	return OGRERR_NONE;
+        // Release old if any
+        if ( pszQuery ) {
+            CPLFree ( pszQuery );
+            pszQuery = NULL;
+        }
+        if ( paQueryMatch ) {
+            CPLFree ( paQueryMatch );
+            paQueryMatch = NULL;
+        }
+        return OGRERR_NONE;
     }
 
     paQueryMatch = (char *) CPLMalloc ( nTotalCount );
@@ -396,53 +395,53 @@ OGRErr OGRGRASSLayer::SetAttributeFilter( const char *query )
 
     if ( bHaveAttributes ) {
 
-	if ( !poDriver )
-	{
-	    StartDbDriver();
-	}
-
-	if ( poDriver )
-	{
-	    if ( bCursorOpened )
-	    {
-		db_close_cursor ( poCursor );
-		bCursorOpened = false;
-	    }
-	    OpenSequentialCursor();
-	    if ( bCursorOpened )
-	    {
-		SetQueryMatch();
-		db_close_cursor ( poCursor );
-		bCursorOpened = false;
-	    }
-	    else
-	    {
-		CPLFree ( pszQuery );
-		pszQuery = NULL;
-		return OGRERR_FAILURE;
-	    }
-	    db_close_database_shutdown_driver ( poDriver );
-	    poDriver = NULL;
-	}
-	else
-	{
-	    CPLFree ( pszQuery );
-	    pszQuery = NULL;
-	    return OGRERR_FAILURE;
-	}
+        if ( !poDriver )
+        {
+            StartDbDriver();
+        }
+
+        if ( poDriver )
+        {
+            if ( bCursorOpened )
+            {
+                db_close_cursor ( poCursor );
+                bCursorOpened = false;
+            }
+            OpenSequentialCursor();
+            if ( bCursorOpened )
+            {
+                SetQueryMatch();
+                db_close_cursor ( poCursor );
+                bCursorOpened = false;
+            }
+            else
+            {
+                CPLFree ( pszQuery );
+                pszQuery = NULL;
+                return OGRERR_FAILURE;
+            }
+            db_close_database_shutdown_driver ( poDriver );
+            poDriver = NULL;
+        }
+        else
+        {
+            CPLFree ( pszQuery );
+            pszQuery = NULL;
+            return OGRERR_FAILURE;
+        }
     }
     else
     {
-	// Use OGR to evaluate category match
-	for ( int i = 0; i < nTotalCount; i++ )
-	{
-	    OGRFeature *feature = GetFeature(i);
-	    CPLDebug ( "GRASS", "i = %d eval = %d", i, m_poAttrQuery->Evaluate ( feature ) );
-	    if ( m_poAttrQuery->Evaluate ( feature ) )
-	    {
-		paQueryMatch[i] = 1;
-	    }
-	}
+        // Use OGR to evaluate category match
+        for ( int i = 0; i < nTotalCount; i++ )
+        {
+            OGRFeature *feature = GetFeature(i);
+            CPLDebug ( "GRASS", "i = %d eval = %d", i, m_poAttrQuery->Evaluate ( feature ) );
+            if ( m_poAttrQuery->Evaluate ( feature ) )
+            {
+                paQueryMatch[i] = 1;
+            }
+        }
     }
 
     return OGRERR_NONE;
@@ -459,8 +458,8 @@ bool OGRGRASSLayer::SetQueryMatch()
     // this method is called immediately after OpenSequentialCursor()
 
     if ( !bCursorOpened ) {
-	CPLError( CE_Failure, CPLE_AppDefined, "Cursor is not opened.");
-	return false;
+        CPLError( CE_Failure, CPLE_AppDefined, "Cursor is not opened.");
+        return false;
     }
 
     int more;
@@ -470,58 +469,58 @@ bool OGRGRASSLayer::SetQueryMatch()
     int ncats = Vect_cidx_get_num_cats_by_index ( poMap, iLayerIndex );
     dbTable *table = db_get_cursor_table ( poCursor );
     while ( true ) {
-	if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK )
-	{
-	    CPLError( CE_Failure, CPLE_AppDefined, "Cannot fetch attributes.");
-	    return false;
-	}
-	if ( !more ) break;
-
-	dbColumn *column = db_get_table_column ( table, iCatField );
-	dbValue *value = db_get_column_value ( column );
-	int cat = db_get_value_int ( value );
-
-	// NOTE: because of bug in GRASS library it is impossible to use
-	//       Vect_cidx_find_next
-
-	// Go through category index until first record of current category
-	// is found or a category > current is found
-	int cidxcat, type, id;
-	while ( cidx < ncats ) {
-	    Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, cidx,
-		                         &cidxcat, &type, &id );
-
-	    if ( cidxcat < cat ) {
-	    	cidx++;
-		continue;
-	    }
-	    if ( cidxcat > cat ) break; // Not found
-
-	    // We have the category we want, check type
-	    if ( !(type & (GV_POINT|GV_LINES|GV_AREA)) )
-	    {
-	    	cidx++;
-		continue;
-	    }
-
-	    // Both category and type match -> find feature and set it on
-	    while ( true ) {
-		if ( fidx > nTotalCount || paFeatureIndex[fidx] > cidx ) {
-		    // should not happen
-		    break;
-		}
-
-		if ( paFeatureIndex[fidx] == cidx ) {
-		    paQueryMatch[fidx] = 1;
-		    fidx++;
-		    break;
-		}
-		fidx++;
-	    }
-	    cidx++;
-	}
-
-	if ( id < 0 ) continue; // not found
+        if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Cannot fetch attributes.");
+            return false;
+        }
+        if ( !more ) break;
+
+        dbColumn *column = db_get_table_column ( table, iCatField );
+        dbValue *value = db_get_column_value ( column );
+        int cat = db_get_value_int ( value );
+
+        // NOTE: because of bug in GRASS library it is impossible to use
+        //       Vect_cidx_find_next
+
+        // Go through category index until first record of current category
+        // is found or a category > current is found
+        int cidxcat, type, id;
+        while ( cidx < ncats ) {
+            Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, cidx,
+                                         &cidxcat, &type, &id );
+
+            if ( cidxcat < cat ) {
+                cidx++;
+                continue;
+            }
+            if ( cidxcat > cat ) break; // Not found
+
+            // We have the category we want, check type
+            if ( !(type & (GV_POINT|GV_LINES|GV_AREA)) )
+            {
+                cidx++;
+                continue;
+            }
+
+            // Both category and type match -> find feature and set it on
+            while ( true ) {
+                if ( fidx > nTotalCount || paFeatureIndex[fidx] > cidx ) {
+                    // should not happen
+                    break;
+                }
+
+                if ( paFeatureIndex[fidx] == cidx ) {
+                    paQueryMatch[fidx] = 1;
+                    fidx++;
+                    break;
+                }
+                fidx++;
+            }
+            cidx++;
+        }
+
+        if ( id < 0 ) continue; // not found
     }
 
     return true;
@@ -536,41 +535,41 @@ bool OGRGRASSLayer::OpenSequentialCursor()
 
     if ( !poDriver )
     {
-	CPLError( CE_Failure, CPLE_AppDefined, "Driver not opened.");
-	return false;
+        CPLError( CE_Failure, CPLE_AppDefined, "Driver not opened.");
+        return false;
     }
 
     if ( bCursorOpened )
     {
-	db_close_cursor ( poCursor );
-	bCursorOpened = false;
+        db_close_cursor ( poCursor );
+        bCursorOpened = false;
     }
 
     char buf[2000];
-    sprintf ( buf, "SELECT * FROM %s ", poLink->table );
+    snprintf ( buf, sizeof(buf), "SELECT * FROM %s ", poLink->table );
     db_set_string ( poDbString, buf);
 
     if ( pszQuery ) {
-	sprintf ( buf, "WHERE %s ", pszQuery );
-	db_append_string ( poDbString, buf);
+        snprintf ( buf, sizeof(buf), "WHERE %s ", pszQuery );
+        db_append_string ( poDbString, buf);
     }
 
-    sprintf ( buf, "ORDER BY %s", poLink->key);
+    snprintf ( buf, sizeof(buf), "ORDER BY %s", poLink->key);
     db_append_string ( poDbString, buf);
 
     CPLDebug ( "GRASS", "Query: %s", db_get_string(poDbString) );
 
     if ( db_open_select_cursor ( poDriver, poDbString,
-		poCursor, DB_SCROLL) == DB_OK )
+                poCursor, DB_SCROLL) == DB_OK )
     {
-	iCurrentCat = -1;
-	bCursorOpened = true;
-	CPLDebug ( "GRASS", "num rows = %d", db_get_num_rows ( poCursor ) );
+        iCurrentCat = -1;
+        bCursorOpened = true;
+        CPLDebug ( "GRASS", "num rows = %d", db_get_num_rows ( poCursor ) );
     }
     else
     {
-	CPLError( CE_Failure, CPLE_AppDefined, "Cannot open cursor.");
-	return false;
+        CPLError( CE_Failure, CPLE_AppDefined, "Cannot open cursor.");
+        return false;
     }
     return true;
 }
@@ -585,13 +584,13 @@ bool OGRGRASSLayer::ResetSequentialCursor()
     int more;
     if( db_fetch ( poCursor, DB_FIRST, &more) != DB_OK )
     {
-	CPLError( CE_Failure, CPLE_AppDefined, "Cannot reset cursor.");
-	return false;
+        CPLError( CE_Failure, CPLE_AppDefined, "Cannot reset cursor.");
+        return false;
     }
     if( db_fetch ( poCursor, DB_PREVIOUS, &more) != DB_OK )
     {
-	CPLError( CE_Failure, CPLE_AppDefined, "Cannot reset cursor.");
-	return false;
+        CPLError( CE_Failure, CPLE_AppDefined, "Cannot reset cursor.");
+        return false;
     }
     return true;
 }
@@ -606,12 +605,12 @@ void OGRGRASSLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     OGRLayer::SetSpatialFilter ( poGeomIn );
 
     if ( poGeomIn == NULL ) {
-	// Release old if any
-    	if ( paSpatialMatch ) {
-	    CPLFree ( paSpatialMatch );
-	    paSpatialMatch = NULL;
-	}
-	return;
+        // Release old if any
+        if ( paSpatialMatch ) {
+            CPLFree ( paSpatialMatch );
+            paSpatialMatch = NULL;
+        }
+        return;
     }
 
     SetSpatialMatch();
@@ -626,51 +625,50 @@ bool OGRGRASSLayer::SetSpatialMatch()
 
     if ( !paSpatialMatch )
     {
-	paSpatialMatch = (char *) CPLMalloc ( nTotalCount );
+        paSpatialMatch = (char *) CPLMalloc ( nTotalCount );
     }
     memset ( paSpatialMatch, 0x0, nTotalCount );
 
-    OGRGeometry *geom;
     OGRLineString *lstring = new OGRLineString();
     lstring->setNumPoints ( 5 );
-    geom = lstring;
+    OGRGeometry *geom = lstring;
 
     for ( int i = 0; i < nTotalCount; i++ ) {
-	int cidx = paFeatureIndex[i];
+        int cidx = paFeatureIndex[i];
 
-	int cat, type, id;
+        int cat, type, id;
 
-	Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, cidx, &cat, &type, &id );
+        Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, cidx, &cat, &type, &id );
 
 #if GRASS_VERSION_MAJOR  >= 7
     struct bound_box box;
 #else
-	BOUND_BOX box;
+        BOUND_BOX box;
 #endif
 
-	switch ( type )
-	{
-	    case GV_POINT:
-	    case GV_LINE:
-	    case GV_BOUNDARY:
-		Vect_get_line_box ( poMap, id, &box );
-		break;
-
-	    case GV_AREA:
-		Vect_get_area_box ( poMap, id, &box );
-		break;
-	}
-
-	lstring->setPoint( 0, box.W, box.N, 0. );
-	lstring->setPoint( 1, box.W, box.S, 0. );
-	lstring->setPoint( 2, box.E, box.S, 0. );
-	lstring->setPoint( 3, box.E, box.N, 0. );
-	lstring->setPoint( 4, box.W, box.N, 0. );
-
-	if ( FilterGeometry(geom) ) {
-    	    CPLDebug ( "GRASS", "Feature %d in filter", i );
-	    paSpatialMatch[i] = 1;
-	}
+        switch ( type )
+        {
+            case GV_POINT:
+            case GV_LINE:
+            case GV_BOUNDARY:
+                Vect_get_line_box ( poMap, id, &box );
+                break;
+
+            case GV_AREA:
+                Vect_get_area_box ( poMap, id, &box );
+                break;
+        }
+
+        lstring->setPoint( 0, box.W, box.N, 0. );
+        lstring->setPoint( 1, box.W, box.S, 0. );
+        lstring->setPoint( 2, box.E, box.S, 0. );
+        lstring->setPoint( 3, box.E, box.N, 0. );
+        lstring->setPoint( 4, box.W, box.N, 0. );
+
+        if ( FilterGeometry(geom) ) {
+            CPLDebug ( "GRASS", "Feature %d in filter", i );
+            paSpatialMatch[i] = 1;
+        }
     }
     delete lstring;
     return true;
@@ -688,36 +686,36 @@ OGRFeature *OGRGRASSLayer::GetNextFeature()
 
     // Get next iNextId
     while ( true ) {
-	if( iNextId >= nTotalCount ) // No more features
-	{
-	    // Close cursor / driver if opened
-	    if ( bCursorOpened )
-	    {
-	    	db_close_cursor ( poCursor);
-	    	bCursorOpened = false;
-	    }
-	    if ( poDriver )
-	    {
-    	    	db_close_database_shutdown_driver ( poDriver );
-		poDriver = NULL;
-	    }
-
-	    return NULL;
-	}
-
-	// Attributes
-	if( pszQuery != NULL && !paQueryMatch[iNextId] ) {
-	    iNextId++;
-	    continue;
-	}
-
-	// Spatial
-	if( m_poFilterGeom && !paSpatialMatch[iNextId] ) {
-	    iNextId++;
-	    continue;
-	}
-
-	break; // Attributes & spatial filter match
+        if( iNextId >= nTotalCount ) // No more features
+        {
+            // Close cursor / driver if opened
+            if ( bCursorOpened )
+            {
+                db_close_cursor ( poCursor);
+                bCursorOpened = false;
+            }
+            if ( poDriver )
+            {
+                db_close_database_shutdown_driver ( poDriver );
+                poDriver = NULL;
+            }
+
+            return NULL;
+        }
+
+        // Attributes
+        if( pszQuery != NULL && !paQueryMatch[iNextId] ) {
+            iNextId++;
+            continue;
+        }
+
+        // Spatial
+        if( m_poFilterGeom && !paSpatialMatch[iNextId] ) {
+            iNextId++;
+            continue;
+        }
+
+        break; // Attributes & spatial filter match
     }
 
     OGRGeometry *poOGR = GetFeatureGeometry ( iNextId, &cat );
@@ -731,51 +729,51 @@ OGRFeature *OGRGRASSLayer::GetNextFeature()
     CPLDebug ( "GRASS", "bHaveAttributes = %d", bHaveAttributes );
     if ( bHaveAttributes )
     {
-	if ( !poDriver )
-	{
-	    StartDbDriver();
-	}
-	if ( poDriver ) {
-	    if ( !bCursorOpened )
-	    {
-		OpenSequentialCursor();
-	    }
-	    if ( bCursorOpened )
-	    {
-		dbTable  *table = db_get_cursor_table ( poCursor );
-		if ( iCurrentCat < cat )
-		{
-		    while ( true ) {
-			int more;
-			if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK )
-			{
-			    CPLError( CE_Failure, CPLE_AppDefined,
-				      "Cannot fetch attributes.");
-			    break;
-			}
-			if ( !more ) break;
-
-			dbColumn *column = db_get_table_column ( table, iCatField );
-			dbValue *value = db_get_column_value ( column );
-			iCurrentCat = db_get_value_int ( value );
-
-			if ( iCurrentCat >= cat ) break;
-		    }
-		}
-		if ( cat == iCurrentCat )
-		{
-		    SetAttributes ( poFeature, table );
-		}
-		else
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined, "Attributes not found.");
-		}
-	    }
-	}
+        if ( !poDriver )
+        {
+            StartDbDriver();
+        }
+        if ( poDriver ) {
+            if ( !bCursorOpened )
+            {
+                OpenSequentialCursor();
+            }
+            if ( bCursorOpened )
+            {
+                dbTable  *table = db_get_cursor_table ( poCursor );
+                if ( iCurrentCat < cat )
+                {
+                    while ( true ) {
+                        int more;
+                        if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK )
+                        {
+                            CPLError( CE_Failure, CPLE_AppDefined,
+                                      "Cannot fetch attributes.");
+                            break;
+                        }
+                        if ( !more ) break;
+
+                        dbColumn *column = db_get_table_column ( table, iCatField );
+                        dbValue *value = db_get_column_value ( column );
+                        iCurrentCat = db_get_value_int ( value );
+
+                        if ( iCurrentCat >= cat ) break;
+                    }
+                }
+                if ( cat == iCurrentCat )
+                {
+                    SetAttributes ( poFeature, table );
+                }
+                else
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "Attributes not found.");
+                }
+            }
+        }
     }
     else if ( iLayer > 0 ) // Add category
     {
-	poFeature->SetField( 0, cat );
+        poFeature->SetField( 0, cat );
     }
 
     m_nFeaturesRead++;
@@ -787,7 +785,8 @@ OGRFeature *OGRGRASSLayer::GetNextFeature()
 OGRFeature *OGRGRASSLayer::GetFeature( GIntBig nFeatureId )
 
 {
-    CPLDebug ( "GRASS", "OGRGRASSLayer::GetFeature nFeatureId = %ld", nFeatureId );
+    CPLDebug ( "GRASS", "OGRGRASSLayer::GetFeature nFeatureId = " CPL_FRMT_GIB,
+               nFeatureId );
 
     int cat;
     OGRFeature *poFeature = NULL;
@@ -801,57 +800,57 @@ OGRFeature *OGRGRASSLayer::GetFeature( GIntBig nFeatureId )
     // Get attributes
     if ( bHaveAttributes && !poDriver )
     {
-	StartDbDriver();
+        StartDbDriver();
     }
     if ( poDriver )
     {
-	if ( bCursorOpened )
-	{
-	    db_close_cursor ( poCursor);
-	    bCursorOpened = false;
-	}
-	CPLDebug ( "GRASS", "Open cursor for key = %d", cat );
-	char buf[2000];
-	sprintf ( buf, "SELECT * FROM %s WHERE %s = %d",
-		       poLink->table, poLink->key, cat );
-	db_set_string ( poDbString, buf);
-	if ( db_open_select_cursor ( poDriver, poDbString,
-		    poCursor, DB_SEQUENTIAL) == DB_OK )
-	{
-	    iCurrentCat = cat; // Not important
-	    bCursorOpened = true;
-	}
-	else
-	{
-	    CPLError( CE_Failure, CPLE_AppDefined, "Cannot open cursor.");
-	}
-
-	if ( bCursorOpened )
-	{
-	    int more;
-	    if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK )
-	    {
-		CPLError( CE_Failure, CPLE_AppDefined, "Cannot fetch attributes.");
-	    }
-	    else
-	    {
-		if ( !more )
-		{
-		    CPLError( CE_Failure, CPLE_AppDefined, "Attributes not found.");
-		}
-		else
-		{
-	    	    dbTable *table = db_get_cursor_table ( poCursor );
-		    SetAttributes ( poFeature, table );
-		}
-	    }
-	    db_close_cursor ( poCursor);
-	    bCursorOpened = false;
-	}
+        if ( bCursorOpened )
+        {
+            db_close_cursor ( poCursor);
+            bCursorOpened = false;
+        }
+        CPLDebug ( "GRASS", "Open cursor for key = %d", cat );
+        char buf[2000];
+        snprintf ( buf, sizeof(buf), "SELECT * FROM %s WHERE %s = %d",
+                       poLink->table, poLink->key, cat );
+        db_set_string ( poDbString, buf);
+        if ( db_open_select_cursor ( poDriver, poDbString,
+                    poCursor, DB_SEQUENTIAL) == DB_OK )
+        {
+            iCurrentCat = cat; // Not important
+            bCursorOpened = true;
+        }
+        else
+        {
+            CPLError( CE_Failure, CPLE_AppDefined, "Cannot open cursor.");
+        }
+
+        if ( bCursorOpened )
+        {
+            int more;
+            if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, "Cannot fetch attributes.");
+            }
+            else
+            {
+                if ( !more )
+                {
+                    CPLError( CE_Failure, CPLE_AppDefined, "Attributes not found.");
+                }
+                else
+                {
+                    dbTable *table = db_get_cursor_table ( poCursor );
+                    SetAttributes ( poFeature, table );
+                }
+            }
+            db_close_cursor ( poCursor);
+            bCursorOpened = false;
+        }
     }
     else if ( iLayer > 0 ) // Add category
     {
-	poFeature->SetField( 0, cat );
+        poFeature->SetField( 0, cat );
     }
 
     m_nFeaturesRead++;
@@ -876,9 +875,9 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
     int bIs3D = Vect_is_3d(poMap);
 
     switch ( type ) {
-	case GV_POINT:
+        case GV_POINT:
         {
-	    Vect_read_line ( poMap, poPoints, poCats, id);
+            Vect_read_line ( poMap, poPoints, poCats, id);
             if (bIs3D)
                 poOGR = new OGRPoint( poPoints->x[0], poPoints->y[0], poPoints->z[0] );
             else
@@ -886,11 +885,11 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
         }
         break;
 
-	case GV_LINE:
-	case GV_BOUNDARY:
+        case GV_LINE:
+        case GV_BOUNDARY:
         {
-	    Vect_read_line ( poMap, poPoints, poCats, id);
-	    OGRLineString *poOGRLine = new OGRLineString();
+            Vect_read_line ( poMap, poPoints, poCats, id);
+            OGRLineString *poOGRLine = new OGRLineString();
             if (bIs3D)
                 poOGRLine->setPoints( poPoints->n_points,
                                       poPoints->x, poPoints->y, poPoints->z );
@@ -902,15 +901,13 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
         }
         break;
 
-	case GV_AREA:
+        case GV_AREA:
         {
-	    Vect_get_area_points ( poMap, id, poPoints );
+            Vect_get_area_points ( poMap, id, poPoints );
 
-	    OGRPolygon 		*poOGRPoly;
-	    poOGRPoly = new OGRPolygon();
+            OGRPolygon *poOGRPoly = new OGRPolygon();
 
-	    OGRLinearRing       *poRing;
-	    poRing = new OGRLinearRing();
+            OGRLinearRing *poRing = new OGRLinearRing();
             if (bIs3D)
                 poRing->setPoints( poPoints->n_points,
                                 poPoints->x, poPoints->y, poPoints->z );
@@ -918,15 +915,15 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
                 poRing->setPoints( poPoints->n_points,
                                 poPoints->x, poPoints->y );
 
-	    poOGRPoly->addRingDirectly( poRing );
+            poOGRPoly->addRingDirectly( poRing );
 
-	    // Islands
-	    int nisles = Vect_get_area_num_isles ( poMap, id );
-	    for ( int i = 0; i < nisles; i++ ) {
-		int isle =  Vect_get_area_isle ( poMap, id, i );
-		Vect_get_isle_points ( poMap, isle, poPoints );
+            // Islands
+            int nisles = Vect_get_area_num_isles ( poMap, id );
+            for ( int i = 0; i < nisles; i++ ) {
+                int isle =  Vect_get_area_isle ( poMap, id, i );
+                Vect_get_isle_points ( poMap, isle, poPoints );
 
-		poRing = new OGRLinearRing();
+                poRing = new OGRLinearRing();
                 if (bIs3D)
                     poRing->setPoints( poPoints->n_points,
                                     poPoints->x, poPoints->y, poPoints->z );
@@ -934,17 +931,17 @@ OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat )
                     poRing->setPoints( poPoints->n_points,
                                     poPoints->x, poPoints->y );
 
-		poOGRPoly->addRingDirectly( poRing );
-	    }
+                poOGRPoly->addRingDirectly( poRing );
+            }
 
-	    poOGR = poOGRPoly;
+            poOGR = poOGRPoly;
         }
         break;
 
-	default: // Should not happen
+        default: // Should not happen
         {
-	    CPLError( CE_Failure, CPLE_AppDefined, "Unknown GRASS feature type.");
-	    return NULL;
+            CPLError( CE_Failure, CPLE_AppDefined, "Unknown GRASS feature type.");
+            return NULL;
         }
     }
 
@@ -960,50 +957,34 @@ bool OGRGRASSLayer::SetAttributes ( OGRFeature *poFeature, dbTable *table )
 
     for ( int i = 0; i < nFields; i++)
     {
-	dbColumn *column = db_get_table_column ( table, i );
-	dbValue *value = db_get_column_value ( column );
-
-	int ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );
-
-	if ( !db_test_value_isnull(value) )
-	{
-	    switch ( ctype ) {
-		case DB_C_TYPE_INT:
-		    poFeature->SetField( i, db_get_value_int ( value ));
-		    break;
-		case DB_C_TYPE_DOUBLE:
-		    poFeature->SetField( i, db_get_value_double ( value ));
-		    break;
-		case DB_C_TYPE_STRING:
-		    poFeature->SetField( i, db_get_value_string ( value ));
-		    break;
-		case DB_C_TYPE_DATETIME:
-		    db_convert_column_value_to_string ( column, poDbString );
-		    poFeature->SetField( i, db_get_string ( poDbString ));
-		    break;
-	    }
-	}
-
-	db_convert_column_value_to_string ( column, poDbString );
-	//CPLDebug ( "GRASS", "val = %s", db_get_string ( poDbString ));
-    }
-    return true;
-}
+        dbColumn *column = db_get_table_column ( table, i );
+        dbValue *value = db_get_column_value ( column );
 
-/************************************************************************/
-/*                             ISetFeature()                             */
-/************************************************************************/
-OGRErr OGRGRASSLayer::ISetFeature( OGRFeature *poFeature )
-{
-    return OGRERR_FAILURE;
-}
+        int ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );
 
-/************************************************************************/
-/*                           ICreateFeature()                            */
-/************************************************************************/
-OGRErr OGRGRASSLayer::ICreateFeature( OGRFeature *poFeature )
-{
-    return OGRERR_FAILURE;
+        if ( !db_test_value_isnull(value) )
+        {
+            switch ( ctype ) {
+                case DB_C_TYPE_INT:
+                    poFeature->SetField( i, db_get_value_int ( value ));
+                    break;
+                case DB_C_TYPE_DOUBLE:
+                    poFeature->SetField( i, db_get_value_double ( value ));
+                    break;
+                case DB_C_TYPE_STRING:
+                    poFeature->SetField( i, db_get_value_string ( value ));
+                    break;
+                case DB_C_TYPE_DATETIME:
+                    db_convert_column_value_to_string ( column, poDbString );
+                    poFeature->SetField( i, db_get_string ( poDbString ));
+                    break;
+            }
+        }
+
+        db_convert_column_value_to_string ( column, poDbString );
+        // CPLDebug ( "GRASS", "val = %s", db_get_string ( poDbString ));
+    }
+    return true;
 }
 
 /************************************************************************/
@@ -1031,7 +1012,7 @@ GIntBig OGRGRASSLayer::GetFeatureCount( int bForce )
 /*                                                                      */
 /*      Returns OGRERR_NONE/OGRRERR_FAILURE.                            */
 /************************************************************************/
-OGRErr OGRGRASSLayer::GetExtent (OGREnvelope *psExtent, int bForce)
+OGRErr OGRGRASSLayer::GetExtent (OGREnvelope *psExtent, int /*bForce*/)
 {
 #if GRASS_VERSION_MAJOR  >= 7
     struct bound_box box;
@@ -1074,17 +1055,6 @@ int OGRGRASSLayer::TestCapability( const char * pszCap )
 }
 
 /************************************************************************/
-/*                            CreateField()                             */
-/************************************************************************/
-OGRErr OGRGRASSLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
-{
-    CPLError( CE_Failure, CPLE_NotSupported,
-                  "Can't create fields on a GRASS layer.\n");
-
-    return OGRERR_FAILURE;
-}
-
-/************************************************************************/
 /*                           GetSpatialRef()                            */
 /************************************************************************/
 OGRSpatialReference *OGRGRASSLayer::GetSpatialRef()
diff --git a/ogr/ogrsf_frmts/gtm/gtm.cpp b/ogr/ogrsf_frmts/gtm/gtm.cpp
index 8a8ba13..6594856 100644
--- a/ogr/ogrsf_frmts/gtm/gtm.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtm.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gtm.cpp 32760 2016-01-05 17:50:33Z rouault $
  *
  * Project:  GTM Driver
  * Purpose:  Class for reading, parsing and handling a gtmfile.
@@ -30,6 +29,7 @@
 
 #include "gtm.h"
 
+CPL_CVSID("$Id: gtm.cpp 36948 2016-12-18 13:32:14Z rouault $");
 
 /************************************************************************/
 /*        Methods for dealing with write on files and buffers           */
@@ -105,15 +105,15 @@ static unsigned char readUChar(VSILFILE* fp)
     return val;
 }
 
-static unsigned short readUShort(VSILFILE* fp, int *pbSuccess = NULL)
+static unsigned short readUShort( VSILFILE* fp, bool *pbSuccess = NULL )
 {
     unsigned short val;
     if (VSIFReadL( &val, 1, 2, fp ) != 2)
     {
-        if (pbSuccess) *pbSuccess = FALSE;
+        if (pbSuccess) *pbSuccess = false;
         return 0;
     }
-    if (pbSuccess) *pbSuccess = TRUE;
+    if (pbSuccess) *pbSuccess = true;
     CPL_LSBPTR16(&val);
     return val;
 }
@@ -226,7 +226,6 @@ unsigned char Track::getType() const
     return type;
 }
 
-
 int Track::getColor() const
 {
     return color;
@@ -256,7 +255,6 @@ const TrackPoint* Track::getPoint(int pointNum) const
     return NULL;
 }
 
-
 /************************************************************************/
 /*                Implementation of GTM Function Members                */
 /************************************************************************/
@@ -307,7 +305,6 @@ bool GTM::Open(const char* pszFilenameIn)
     return true;
 }
 
-
 bool GTM::isValid()
 {
 /* -------------------------------------------------------------------- */
@@ -358,7 +355,7 @@ bool GTM::isValid()
         CPLFree(pszGZIPFileName);
     }
 
-    const short version = CPL_LSBINT16PTR(buffer);
+    const short version = CPL_LSBSINT16PTR(buffer);
     /*Skip string length */
     const char* szHeader = buffer + 2;
     if (version == 211 && strcmp(szHeader, "TrackMaker") == 0 )
@@ -430,7 +427,6 @@ bool GTM::readHeaderNumbers()
     stringSize = readUShort(pGTMFile);
     headerSize += stringSize + 2; // String + size field
 
-
     /* Read userfont string size */
     if ( VSIFSeekL(pGTMFile, stringSize, SEEK_CUR) != 0)
         return false;
@@ -513,8 +509,8 @@ Waypoint* GTM::fetchNextWaypoint()
 
     /* Trim string name */
     {
-    int i;
-        for (i = 9; i >= 0; --i)
+        int i = 9;  // Used after for.
+        for( ; i >= 0; --i)
         {
             if (name[i] != ' ')
             {
@@ -561,7 +557,6 @@ Waypoint* GTM::fetchNextWaypoint()
     Waypoint* poWaypoint = new Waypoint(latitude, longitude, altitude,
                                         name, comment, (int) icon, wptdate);
 
-
     /* Set actual waypoint offset to the next it there is one */
     ++waypointFetched;
     if (waypointFetched < nwpts)
@@ -574,7 +569,6 @@ Waypoint* GTM::fetchNextWaypoint()
     return poWaypoint;
 }
 
-
 /************************************************************************/
 /*                        Track control functions                    */
 /************************************************************************/
@@ -598,22 +592,14 @@ void GTM::rewindTrack()
 
 Track* GTM::fetchNextTrack()
 {
-    unsigned short stringSize;
-
-    char* pszName;
-    unsigned char type;
-    int color;
-
-
     /* Point to the actual track offset */
     if ( VSIFSeekL(pGTMFile, actualTrackOffset, SEEK_SET) != 0)
         return NULL;
 
-
     /* Read string length */
-    stringSize = readUShort(pGTMFile);
+    const unsigned short stringSize = readUShort(pGTMFile);
     /* Read name string */
-    pszName = (char*) VSI_MALLOC2_VERBOSE(sizeof(char), stringSize+1);
+    char* pszName = (char*) VSI_MALLOC2_VERBOSE(sizeof(char), stringSize+1);
     if( pszName == NULL )
         return NULL;
     if ( stringSize != 0 && !readFile( pszName, 1, sizeof(char) * stringSize ) )
@@ -624,10 +610,10 @@ Track* GTM::fetchNextTrack()
     pszName[stringSize] = '\0';
 
     /* Read type */
-    type = readUChar(pGTMFile);
+    const unsigned char type = readUChar(pGTMFile);
 
     /* Read color */
-    color = readInt(pGTMFile);
+    const int color = readInt(pGTMFile);
 
     Track* poTrack = new Track(pszName, type, color);
 
@@ -637,10 +623,11 @@ Track* GTM::fetchNextTrack()
     ++trackFetched;
 
     /* Now, We read all trackpoints for this track */
-    double latitude, longitude;
-    GIntBig datetime;
-    unsigned char start;
-    float altitude;
+    double latitude = 0.0;
+    double longitude = 0.0;
+    GIntBig datetime = 0;
+    unsigned char start = 0;
+    float altitude = 0.0f;
     /* NOTE: Parameters are passed by reference */
     if ( !readTrackPoints(latitude, longitude, datetime, start, altitude) )
     {
@@ -678,8 +665,6 @@ Track* GTM::fetchNextTrack()
     return poTrack;
 }
 
-
-
 /************************************************************************/
 /*                        Private Methods Implementation                */
 /************************************************************************/
@@ -713,7 +698,6 @@ vsi_l_offset GTM::findFirstWaypointOffset()
     return VSIFTellL(pGTMFile);
 }
 
-
 vsi_l_offset GTM::findFirstTrackpointOffset()
 {
     if (firstWaypointOffset == 0)
@@ -730,8 +714,6 @@ vsi_l_offset GTM::findFirstTrackpointOffset()
     if (VSIFSeekL(pGTMFile, firstWaypointOffset, SEEK_SET) != 0)
         return 0;
 
-    unsigned short stringSize;
-    int bSuccess;
     /* Skip waypoints */
     for (int i = 0; i < nwpts; ++i)
     {
@@ -739,10 +721,11 @@ vsi_l_offset GTM::findFirstTrackpointOffset()
         if (VSIFSeekL(pGTMFile, 26, SEEK_CUR) != 0)
             return 0;
         /* Read string comment size */
-        stringSize = readUShort(pGTMFile, &bSuccess);
+        bool bSuccess = false;
+        const unsigned short stringSize = readUShort(pGTMFile, &bSuccess);
 
         /* Skip to the next Waypoint */
-        if (bSuccess == FALSE || VSIFSeekL(pGTMFile, stringSize + 15, SEEK_CUR) != 0)
+        if( !bSuccess || VSIFSeekL(pGTMFile, stringSize + 15, SEEK_CUR) != 0 )
             return 0;
     }
 
@@ -758,10 +741,12 @@ vsi_l_offset GTM::findFirstTrackpointOffset()
                 return 0;
 
             /* Read string facename size */
-            stringSize = readUShort(pGTMFile, &bSuccess);
+            bool bSuccess = false;
+            const unsigned short stringSize = readUShort(pGTMFile, &bSuccess);
 
             /* Skip to the next Waypoint Style*/
-            if (bSuccess == FALSE || VSIFSeekL(pGTMFile, stringSize + 24, SEEK_CUR) != 0)
+            if( !bSuccess ||
+                VSIFSeekL(pGTMFile, stringSize + 24, SEEK_CUR) != 0 )
                 return 0;
         }
     }
@@ -827,6 +812,3 @@ bool GTM::readFile(void* pBuffer, size_t nSize, size_t nCount)
     }
     return true;
 }
-
-
-
diff --git a/ogr/ogrsf_frmts/gtm/gtm.h b/ogr/ogrsf_frmts/gtm/gtm.h
index 662459f..1c78b2f 100644
--- a/ogr/ogrsf_frmts/gtm/gtm.h
+++ b/ogr/ogrsf_frmts/gtm/gtm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gtm.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: gtm.h 35933 2016-10-25 16:46:26Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Class for reading, parsing and handling a gtm file.
@@ -40,7 +40,6 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-
 #ifndef FILE_OFFSETS
 #define FILE_OFFSETS
 #define NWPTSTYLES_OFFSET 27
@@ -79,7 +78,6 @@ void writeInt(VSILFILE* fp, int val);
 void writeUChar(VSILFILE* fp, unsigned char val);
 void writeUShort(VSILFILE* fp, unsigned short);
 
-
 class Waypoint
 {
 public:
@@ -138,10 +136,8 @@ private:
     int color;
     int nPoints;
     TrackPoint* pasTrackPoints;
-
 };
 
-
 class GTM
 {
 public:
@@ -149,7 +145,6 @@ public:
     ~GTM();
     bool Open(const char* pszFilename);
 
-
     // Check whether it is a valid GTM file or not.
     bool isValid();
     bool readHeaderNumbers();
@@ -200,7 +195,6 @@ private:
     bool readTrackPoints(double& latitude, double& longitude, GIntBig& datetime,
                          unsigned char& start, float& altitude);
     bool readFile(void* pBuffer, size_t nSize, size_t nCount);
-
 };
 
 #endif // OGR_GTM_GTM
diff --git a/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp b/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
index d906e51..94b4356 100644
--- a/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtmtracklayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gtmtracklayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of GTMTrackLayer class.
@@ -29,6 +28,7 @@
  ****************************************************************************/
 #include "ogr_gtm.h"
 
+CPL_CVSID("$Id: gtmtracklayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 GTMTrackLayer::GTMTrackLayer( const char* pszNameIn,
                               OGRSpatialReference *poSRSIn,
@@ -100,7 +100,6 @@ GTMTrackLayer::GTMTrackLayer( const char* pszNameIn,
 
     OGRFieldDefn oFieldColor( "color", OFTInteger );
     poFeatureDefn->AddFieldDefn( &oFieldColor );
-
 }
 
 GTMTrackLayer::~GTMTrackLayer()
@@ -109,7 +108,6 @@ GTMTrackLayer::~GTMTrackLayer()
        parent class */
 }
 
-
 /************************************************************************/
 /*                      WriteFeatureAttributes()                        */
 /************************************************************************/
@@ -121,7 +119,7 @@ void GTMTrackLayer::WriteFeatureAttributes( OGRFeature *poFeature )
     for (int i = 0; i < poFeatureDefn->GetFieldCount(); ++i)
     {
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
-        if( poFeature->IsFieldSet( i ) )
+        if( poFeature->IsFieldSetAndNotNull( i ) )
         {
             const char* l_pszName = poFieldDefn->GetNameRef();
             /* track name */
@@ -217,7 +215,6 @@ inline void GTMTrackLayer::WriteTrackpoint( double lat, double lon,
     CPLFree(pBuffer);
 }
 
-
 /************************************************************************/
 /*                           ICreateFeature()                            */
 /************************************************************************/
@@ -307,7 +304,6 @@ OGRErr GTMTrackLayer::ICreateFeature (OGRFeature *poFeature)
     return OGRERR_NONE;
 }
 
-
 OGRFeature* GTMTrackLayer::GetNextFeature()
 {
     if( bError )
@@ -360,7 +356,6 @@ GIntBig GTMTrackLayer::GetFeatureCount(int bForce)
     return OGRLayer::GetFeatureCount(bForce);
 }
 
-
 void GTMTrackLayer::ResetReading()
 {
     nNextFID = 0;
diff --git a/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp b/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
index df82b7d..063d948 100644
--- a/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/gtmwaypointlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: gtmwaypointlayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of gtmwaypoint class.
@@ -31,6 +30,8 @@
 #include "ogr_gtm.h"
 #include "cpl_time.h"
 
+CPL_CVSID("$Id: gtmwaypointlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
 GTMWaypointLayer::GTMWaypointLayer( const char* pszNameIn,
                                     OGRSpatialReference* poSRSIn,
                                     CPL_UNUSED int bWriterIn,
@@ -79,7 +80,7 @@ GTMWaypointLayer::GTMWaypointLayer( const char* pszNameIn,
     nNextFID = 0;
     nTotalFCount = poDS->getNWpts();
 
-    this->pszName = CPLStrdup(pszNameIn);
+    pszName = CPLStrdup(pszNameIn);
 
     poFeatureDefn = new OGRFeatureDefn( pszName );
     SetDescription( poFeatureDefn->GetName() );
@@ -102,11 +103,7 @@ GTMWaypointLayer::GTMWaypointLayer( const char* pszNameIn,
     poFeatureDefn->AddFieldDefn( &oFieldTime );
 }
 
-GTMWaypointLayer::~GTMWaypointLayer()
-{
-
-}
-
+GTMWaypointLayer::~GTMWaypointLayer() {}
 
 /************************************************************************/
 /*                      WriteFeatureAttributes()                        */
@@ -120,7 +117,7 @@ void GTMWaypointLayer::WriteFeatureAttributes( OGRFeature *poFeature, float alti
     for (int i = 0; i < poFeatureDefn->GetFieldCount(); ++i)
     {
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( i );
-        if( poFeature->IsFieldSet( i ) )
+        if( poFeature->IsFieldSetAndNotNull( i ) )
         {
             const char* l_pszName = poFieldDefn->GetNameRef();
             /* Waypoint name */
@@ -246,7 +243,6 @@ OGRErr GTMWaypointLayer::ICreateFeature (OGRFeature *poFeature)
         poGeom->transform( poCT );
     }
 
-
     switch( poGeom->getGeometryType() )
     {
     case wkbPoint:
@@ -261,7 +257,7 @@ OGRErr GTMWaypointLayer::ICreateFeature (OGRFeature *poFeature)
         writeDouble(fp, lon);
         float altitude = 0.0;
         if (poGeom->getGeometryType() == wkbPoint25D)
-	    altitude = (float) point->getZ();
+            altitude = (float) point->getZ();
 
         WriteFeatureAttributes(poFeature, altitude);
         break;
@@ -280,12 +276,11 @@ OGRErr GTMWaypointLayer::ICreateFeature (OGRFeature *poFeature)
         delete poGeom;
 
     return OGRERR_NONE;
-
 }
 
 OGRFeature* GTMWaypointLayer::GetNextFeature()
 {
-    if (bError)
+    if( bError )
         return NULL;
 
     while (poDS->hasNextWaypoint())
@@ -295,7 +290,7 @@ OGRFeature* GTMWaypointLayer::GetNextFeature()
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Could not read waypoint. File probably corrupted");
-            bError = TRUE;
+            bError = true;
             return NULL;
         }
 
diff --git a/ogr/ogrsf_frmts/gtm/ogr_gtm.h b/ogr/ogrsf_frmts/gtm/ogr_gtm.h
index cc5c84f..23c93cc 100644
--- a/ogr/ogrsf_frmts/gtm/ogr_gtm.h
+++ b/ogr/ogrsf_frmts/gtm/ogr_gtm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_gtm.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_gtm.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  GTM Driver
  * Purpose:  Declarations for OGR wrapper classes for GTM, and OGR->GTM
@@ -75,10 +75,8 @@ typedef enum
 #  define MAX(a,b)      ((a>b) ? a : b)
 #endif
 
-
 #include "gtm.h"
 
-
 /************************************************************************/
 /*                           OGRGTMLayer                                */
 /************************************************************************/
@@ -86,19 +84,15 @@ class OGRGTMLayer : public OGRLayer
 {
 public:
     OGRGTMLayer();
-    ~OGRGTMLayer();
+    virtual ~OGRGTMLayer();
     //
     // OGRLayer Interface
     //
-    OGRFeatureDefn* GetLayerDefn();
-    virtual void ResetReading() = 0;
-    virtual OGRFeature* GetNextFeature() = 0;
-    virtual GIntBig GetFeatureCount(int bForce = TRUE) = 0;
-    virtual OGRErr ICreateFeature(OGRFeature *poFeature) = 0;
+    OGRFeatureDefn* GetLayerDefn() override;
 
-    int TestCapability( const char* pszCap );
+    int TestCapability( const char* pszCap ) override;
 
-    OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK );
+    OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK ) override;
 
 protected:
     OGRGTMDataSource* poDS;
@@ -113,28 +107,27 @@ protected:
     bool bError;
 
     static OGRErr CheckAndFixCoordinatesValidity( double& pdfLatitude, double& pdfLongitude );
-
 };
 
-
 /************************************************************************/
 /*                           GTMWaypointLayer                           */
 /************************************************************************/
 class GTMWaypointLayer : public OGRGTMLayer
 {
-public:
+  public:
     GTMWaypointLayer( const char* pszName,
                       OGRSpatialReference* poSRSIn,
                       int bWriterIn,
                       OGRGTMDataSource* poDSIn );
     ~GTMWaypointLayer();
-    OGRErr ICreateFeature(OGRFeature *poFeature);
-    void ResetReading();
-    OGRFeature* GetNextFeature();
-    GIntBig GetFeatureCount(int bForce = TRUE);
+    OGRErr ICreateFeature(OGRFeature *poFeature) override;
+    void ResetReading() override;
+    OGRFeature* GetNextFeature() override;
+    GIntBig GetFeatureCount(int bForce = TRUE) override;
 
     enum WaypointFields{NAME, COMMENT, ICON, DATE};
-private:
+
+  private:
     void WriteFeatureAttributes( OGRFeature *poFeature, float altitude );
 };
 
@@ -143,25 +136,23 @@ private:
 /************************************************************************/
 class GTMTrackLayer : public OGRGTMLayer
 {
-public:
+  public:
     GTMTrackLayer( const char* pszName,
                    OGRSpatialReference* poSRSIn,
                    int bWriterIn,
                    OGRGTMDataSource* poDSIn );
     ~GTMTrackLayer();
-    OGRErr ICreateFeature(OGRFeature *poFeature);
-    void ResetReading();
-    OGRFeature* GetNextFeature();
-    GIntBig GetFeatureCount(int bForce = TRUE);
+    OGRErr ICreateFeature(OGRFeature *poFeature) override;
+    void ResetReading() override;
+    OGRFeature* GetNextFeature() override;
+    GIntBig GetFeatureCount(int bForce = TRUE) override;
     enum TrackFields{NAME, TYPE, COLOR};
 
-private:
+  private:
     void WriteFeatureAttributes( OGRFeature *poFeature );
     void WriteTrackpoint( double lat, double lon, float altitude, bool start );
-
 };
 
-
 /************************************************************************/
 /*                           OGRGTMDataSource                           */
 /************************************************************************/
@@ -176,16 +167,16 @@ public:
     int Open( const char *pszFilename, int bUpdate );
     int Create( const char *pszFilename, char **papszOptions );
 
-    const char* GetName() { return pszName; }
-    int GetLayerCount() { return nLayers; }
+    const char* GetName() override { return pszName; }
+    int GetLayerCount() override { return nLayers; }
 
-    OGRLayer* GetLayer( int );
+    OGRLayer* GetLayer( int ) override;
 
     OGRLayer* ICreateLayer(const char *pszName,
                            OGRSpatialReference *poSpatialRef=NULL,
                            OGRwkbGeometryType eGType=wkbUnknown,
-                           char **papszOptions=NULL);
-    int TestCapability( const char * );
+                           char **papszOptions=NULL) override;
+    int TestCapability( const char * ) override;
 
     // OGRGTMDataSource Methods
     VSILFILE* getOutputFP() { return fpOutput; }
@@ -206,7 +197,6 @@ public:
     Track* fetchNextTrack();
     void rewindTrack();
 
-
     /* Functions for writing ne files */
     float getMinLat() { return minlat; }
     float getMaxLat() { return maxlat; }
diff --git a/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp b/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp
index 67d17f6..417e4b3 100644
--- a/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp
+++ b/ogr/ogrsf_frmts/gtm/ogrgtmdatasource.cpp
@@ -1,11 +1,9 @@
 /******************************************************************************
- * $Id: ogrgtmdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of OGRGTMDataSource class.
  * Author:   Leonardo de Paula Rosa Piga; http://lampiao.lsc.ic.unicamp.br/~piga
  *
- *
  ******************************************************************************
  * Copyright (c) 2009, Leonardo de Paula Rosa Piga
  *
@@ -27,8 +25,13 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
+
 #include "ogr_gtm.h"
 
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrgtmdatasource.cpp 36017 2016-10-29 04:27:08Z goatbar $");
+
 /************************************************************************/
 /*                         OGRGTMDataSource()                           */
 /************************************************************************/
@@ -152,7 +155,6 @@ void OGRGTMDataSource::WriteWaypointStyles()
     }
 }
 
-
 /************************************************************************/
 /*                        ~OGRGTMDataSource()                           */
 /************************************************************************/
@@ -209,8 +211,6 @@ OGRGTMDataSource::~OGRGTMDataSource()
         delete poGTMFile;
 }
 
-
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -270,7 +270,6 @@ int OGRGTMDataSource::Open(const char* pszFilename, int bUpdate)
     OGRSpatialReference* poSRS = new OGRSpatialReference(NULL);
     poSRS->SetWellKnownGeogCS( "WGS84" );
 
-
     /* Waypoint layer */
     size_t layerNameSize = strlen(pszBaseFileName) + sizeof("_waypoints");
     char* pszLayerName = (char*) CPLMalloc(layerNameSize);
@@ -305,10 +304,8 @@ int OGRGTMDataSource::Open(const char* pszFilename, int bUpdate)
 
     poSRS->Release();
     return TRUE;
-
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
@@ -320,11 +317,10 @@ int OGRGTMDataSource::Create( const char* pszFilename,
 
     if( fpOutput != NULL )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return FALSE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*     Do not override exiting file.                                    */
 /* -------------------------------------------------------------------- */
@@ -338,7 +334,6 @@ int OGRGTMDataSource::Create( const char* pszFilename,
         return FALSE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
@@ -423,7 +418,6 @@ int OGRGTMDataSource::Create( const char* pszFilename,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                            GetLayer()                                */
 /************************************************************************/
@@ -436,7 +430,6 @@ OGRLayer* OGRGTMDataSource::GetLayer( int iLayer )
     return papoLayers[iLayer];
 }
 
-
 /************************************************************************/
 /*                           ICreateLayer()                             */
 /************************************************************************/
@@ -453,7 +446,6 @@ OGRLayer * OGRGTMDataSource::ICreateLayer( const char * pszLayerName,
         papoLayers = (OGRGTMLayer **) CPLRealloc(papoLayers, nLayers * sizeof(OGRGTMLayer*));
         papoLayers[nLayers-1] = new GTMWaypointLayer( pszName, poSRS, TRUE, this );
         return papoLayers[nLayers-1];
-
     }
     else if (eType == wkbLineString || eType == wkbLineString25D ||
              eType == wkbMultiLineString || eType == wkbMultiLineString25D)
@@ -477,10 +469,8 @@ OGRLayer * OGRGTMDataSource::ICreateLayer( const char * pszLayerName,
                   OGRGeometryTypeToName(eType) );
         return NULL;
     }
-
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -510,25 +500,21 @@ void OGRGTMDataSource::checkBounds(float newLat,
     }
     else
     {
-        minlat = MIN(newLat, minlat);
-        maxlat = MAX(newLat, maxlat);
-        minlon = MIN(newLon, minlon);
-        maxlon = MAX(newLon, maxlon);
+        minlat = std::min(newLat, minlat);
+        maxlat = std::max(newLat, maxlat);
+        minlon = std::min(newLon, minlon);
+        maxlon = std::max(newLon, maxlon);
     }
 }
 
-
-
 /************************************************************************/
 /*               Methods for reading existent file                      */
 /************************************************************************/
 
-
 /*======================================================================*/
 /*                           Waypoint Methods                           */
 /*======================================================================*/
 
-
 /*----------------------------------------------------------------------*/
 /*                              getNWpts()                              */
 /*----------------------------------------------------------------------*/
@@ -541,19 +527,17 @@ int OGRGTMDataSource::getNWpts()
     return poGTMFile->getNWpts();
 }
 
-
 /*----------------------------------------------------------------------*/
 /*                         hasNextWaypoint()                            */
 /*----------------------------------------------------------------------*/
 bool OGRGTMDataSource::hasNextWaypoint()
 {
     if (poGTMFile == NULL)
-        return FALSE;
+        return false;
 
     return poGTMFile->hasNextWaypoint();
 }
 
-
 /*----------------------------------------------------------------------*/
 /*                       fetchNextWaypoint()                            */
 /*----------------------------------------------------------------------*/
@@ -565,7 +549,6 @@ Waypoint* OGRGTMDataSource::fetchNextWaypoint()
     return poGTMFile->fetchNextWaypoint();
 }
 
-
 /*----------------------------------------------------------------------*/
 /*                         rewindWaypoint()                            */
 /*----------------------------------------------------------------------*/
@@ -577,13 +560,10 @@ void OGRGTMDataSource::rewindWaypoint()
     poGTMFile->rewindWaypoint();
 }
 
-
-
 /*======================================================================*/
 /*                             Tracks Methods                           */
 /*======================================================================*/
 
-
 /*----------------------------------------------------------------------*/
 /*                              getNTracks()                            */
 /*----------------------------------------------------------------------*/
@@ -596,19 +576,17 @@ int OGRGTMDataSource::getNTracks()
     return poGTMFile->getNTracks();
 }
 
-
 /*----------------------------------------------------------------------*/
 /*                             hasNextTrack()                           */
 /*----------------------------------------------------------------------*/
 bool OGRGTMDataSource::hasNextTrack()
 {
     if (poGTMFile == NULL)
-        return FALSE;
+        return false;
 
     return poGTMFile->hasNextTrack();
 }
 
-
 /*----------------------------------------------------------------------*/
 /*                            fetchNextTrack()                          */
 /*----------------------------------------------------------------------*/
@@ -620,7 +598,6 @@ Track* OGRGTMDataSource::fetchNextTrack()
     return poGTMFile->fetchNextTrack();
 }
 
-
 /*----------------------------------------------------------------------*/
 /*                           rewindTrack()                              */
 /*----------------------------------------------------------------------*/
diff --git a/ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp b/ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp
index 35d778f..9c0f537 100644
--- a/ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp
+++ b/ogr/ogrsf_frmts/gtm/ogrgtmdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgtmdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of OGRGTMDriver class.
@@ -30,6 +29,8 @@
 #include "cpl_conv.h"
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: ogrgtmdriver.cpp 36948 2016-12-18 13:32:14Z rouault $");
+
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -52,7 +53,7 @@ static GDALDataset *OGRGTMDriverOpen( GDALOpenInfo* poOpenInfo )
     }
     else
     {
-        short version = CPL_LSBINT16PTR(poOpenInfo->pabyHeader);
+        short version = CPL_LSBSINT16PTR(poOpenInfo->pabyHeader);
         if (version != 211 ||
             !STARTS_WITH((const char*)poOpenInfo->pabyHeader + 2, "TrackMaker") )
         {
diff --git a/ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp b/ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp
index db43078..157c1ab 100644
--- a/ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp
+++ b/ogr/ogrsf_frmts/gtm/ogrgtmlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrgtmlayer.cpp 32698 2016-01-03 18:07:36Z goatbar $
  *
  * Project:  GTM Driver
  * Purpose:  Implementation of OGRGTMLayer class.
@@ -29,6 +28,8 @@
 
 #include "ogr_gtm.h"
 
+CPL_CVSID("$Id: ogrgtmlayer.cpp 35911 2016-10-24 15:03:26Z goatbar $");
+
 OGRGTMLayer::OGRGTMLayer() :
     poDS(NULL),
     poSRS(NULL),
@@ -91,7 +92,6 @@ int OGRGTMLayer::TestCapability( const char * pszCap )
     return FALSE;
 }
 
-
 /************************************************************************/
 /*                CheckAndFixCoordinatesValidity()                      */
 /************************************************************************/
@@ -100,26 +100,26 @@ OGRErr OGRGTMLayer::CheckAndFixCoordinatesValidity( double& pdfLatitude, double&
 {
     if (pdfLatitude < -90 || pdfLatitude > 90)
     {
-        static int bFirstWarning = TRUE;
+        static bool bFirstWarning = true;
         if (bFirstWarning)
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Latitude %f is invalid. Valid range is [-90,90]. This warning will not be issued any more",
                      pdfLatitude);
-            bFirstWarning = FALSE;
+            bFirstWarning = false;
         }
         return OGRERR_FAILURE;
     }
 
     if (pdfLongitude < -180 || pdfLongitude > 180)
     {
-        static int bFirstWarning = TRUE;
+        static bool bFirstWarning = true;
         if (bFirstWarning)
         {
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Longitude %f has been modified to fit into range [-180,180]. This warning will not be issued any more",
                      pdfLongitude);
-            bFirstWarning = FALSE;
+            bFirstWarning = false;
         }
 
         if (pdfLongitude > 180)
diff --git a/ogr/ogrsf_frmts/htf/ogr_htf.h b/ogr/ogrsf_frmts/htf/ogr_htf.h
index 46fb1f6..7d94fc1 100644
--- a/ogr/ogrsf_frmts/htf/ogr_htf.h
+++ b/ogr/ogrsf_frmts/htf/ogr_htf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_htf.h 32744 2016-01-04 22:26:42Z goatbar $
+ * $Id: ogr_htf.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  HTF Translator
  * Purpose:  Definition of classes for OGR .htf driver.
@@ -59,17 +59,17 @@ protected:
 
   public:
                         OGRHTFLayer(const char* pszFilename, int nZone, int bIsNorth);
-                        ~OGRHTFLayer();
+                        virtual ~OGRHTFLayer();
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
     void    SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
 };
@@ -81,12 +81,12 @@ protected:
 class OGRHTFPolygonLayer : public OGRHTFLayer
 {
 protected:
-    virtual OGRFeature *       GetNextRawFeature();
+    virtual OGRFeature *       GetNextRawFeature() override;
 
   public:
                         OGRHTFPolygonLayer(const char* pszFilename, int nZone, int bIsNorth);
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 };
 
 /************************************************************************/
@@ -104,17 +104,17 @@ private:
     int                        nTotalSoundings;
 
 protected:
-    virtual OGRFeature *       GetNextRawFeature();
+    virtual OGRFeature *       GetNextRawFeature() override;
 
   public:
                         OGRHTFSoundingLayer(const char* pszFilename, int nZone, int bIsNorth, int nTotalSoundings);
-                       ~OGRHTFSoundingLayer();
+                       virtual ~OGRHTFSoundingLayer();
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
-    virtual GIntBig             GetFeatureCount(int bForce = TRUE);
+    virtual GIntBig             GetFeatureCount(int bForce = TRUE) override;
 };
 
 /************************************************************************/
@@ -131,15 +131,15 @@ protected:
     int                nNextFID;
 
   public:
-                        OGRHTFMetadataLayer(std::vector<CPLString> aosMD);
-                        ~OGRHTFMetadataLayer();
+    explicit            OGRHTFMetadataLayer(const std::vector<CPLString>& aosMD);
+                        virtual ~OGRHTFMetadataLayer();
 
-    virtual void                ResetReading() { nNextFID = 0; }
-    virtual OGRFeature *        GetNextFeature();
+    virtual void                ResetReading() override { nNextFID = 0; }
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int                 TestCapability( const char * ) { return FALSE; }
+    virtual int                 TestCapability( const char * ) override { return FALSE; }
 };
 
 /************************************************************************/
@@ -156,17 +156,17 @@ class OGRHTFDataSource : public OGRDataSource
 
   public:
                         OGRHTFDataSource();
-                        ~OGRHTFDataSource();
+                        virtual ~OGRHTFDataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
-    virtual OGRLayer*           GetLayerByName( const char* pszLayerName );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
+    virtual OGRLayer*           GetLayerByName( const char* pszLayerName ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_HTF_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp b/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
index 1b2e374..54b624f 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtfdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrhtfdatasource.cpp 32744 2016-01-04 22:26:42Z goatbar $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFDataSource class
@@ -31,7 +30,7 @@
 #include "cpl_string.h"
 #include "ogr_htf.h"
 
-CPL_CVSID("$Id: ogrhtfdatasource.cpp 32744 2016-01-04 22:26:42Z goatbar $");
+CPL_CVSID("$Id: ogrhtfdatasource.cpp 35013 2016-08-09 16:03:57Z goatbar $");
 
 /************************************************************************/
 /*                          OGRHTFDataSource()                          */
@@ -115,7 +114,6 @@ int OGRHTFDataSource::Open( const char * pszFilename )
     if (fp == NULL)
         return FALSE;
 
-    const char* pszLine;
     bool bEndOfHTFHeader = false;
     bool bIsSouth = false;
     bool bGeodeticDatumIsWGS84 = false;
@@ -132,6 +130,8 @@ int OGRHTFDataSource::Open( const char * pszFilename )
     double dfNENorthing = 0;
     std::vector<CPLString> aosMD;
     int nTotalSoundings = 0;
+
+    const char* pszLine = NULL;
     while( (pszLine = CPLReadLine2L(fp, 1024, NULL)) != NULL)
     {
         nLines ++;
diff --git a/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp b/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp
index 4fff184..ed7ac7a 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtfdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrhtfdriver.cpp 32744 2016-01-04 22:26:42Z goatbar $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFDriver.
@@ -31,7 +30,7 @@
 #include "ogr_htf.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrhtfdriver.cpp 32744 2016-01-04 22:26:42Z goatbar $");
+CPL_CVSID("$Id: ogrhtfdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -82,4 +81,3 @@ void RegisterOGRHTF()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp b/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp
index 9427ff9..89e6ccd 100644
--- a/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp
+++ b/ogr/ogrsf_frmts/htf/ogrhtflayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrhtflayer.cpp 33199 2016-01-29 15:48:41Z rouault $
  *
  * Project:  HTF Translator
  * Purpose:  Implements OGRHTFLayer class.
@@ -33,7 +32,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrhtflayer.cpp 33199 2016-01-29 15:48:41Z rouault $");
+CPL_CVSID("$Id: ogrhtflayer.cpp 36415 2016-11-21 22:40:20Z rouault $");
 
 /************************************************************************/
 /*                            OGRHTFLayer()                             */
@@ -41,6 +40,8 @@ CPL_CVSID("$Id: ogrhtflayer.cpp 33199 2016-01-29 15:48:41Z rouault $");
 
 OGRHTFLayer::OGRHTFLayer( const char* pszFilename, int nZone, int bIsNorth ) :
     poFeatureDefn(NULL),
+    poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
+    fpHTF(VSIFOpenL(pszFilename, "rb")),
     bEOF(false),
     nNextFID(0),
     bHasExtent(false),
@@ -49,9 +50,6 @@ OGRHTFLayer::OGRHTFLayer( const char* pszFilename, int nZone, int bIsNorth ) :
     dfMaxX(0),
     dfMaxY(0)
 {
-    fpHTF = VSIFOpenL(pszFilename, "rb");
-
-    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
     poSRS->SetUTM( nZone, bIsNorth );
 }
 
@@ -69,15 +67,15 @@ OGRHTFPolygonLayer::OGRHTFPolygonLayer( const char* pszFilename, int nZone,
     poFeatureDefn->SetGeomType( wkbPolygon  );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
-    OGRFieldDefn    oField1( "DESCRIPTION", OFTString);
+    OGRFieldDefn oField1( "DESCRIPTION", OFTString);
     poFeatureDefn->AddFieldDefn( &oField1 );
-    OGRFieldDefn    oField2( "IDENTIFIER", OFTInteger);
+    OGRFieldDefn oField2( "IDENTIFIER", OFTInteger);
     poFeatureDefn->AddFieldDefn( &oField2 );
-    OGRFieldDefn    oField3( "SEAFLOOR_COVERAGE", OFTString);
+    OGRFieldDefn oField3( "SEAFLOOR_COVERAGE", OFTString);
     poFeatureDefn->AddFieldDefn( &oField3 );
-    OGRFieldDefn    oField4( "POSITION_ACCURACY", OFTReal);
+    OGRFieldDefn oField4( "POSITION_ACCURACY", OFTReal);
     poFeatureDefn->AddFieldDefn( &oField4 );
-    OGRFieldDefn    oField5( "DEPTH_ACCURACY", OFTReal);
+    OGRFieldDefn oField5( "DEPTH_ACCURACY", OFTReal);
     poFeatureDefn->AddFieldDefn( &oField5 );
 
     ResetReading();
@@ -104,7 +102,7 @@ OGRHTFSoundingLayer::OGRHTFSoundingLayer( const char* pszFilename, int nZone,
     poFeatureDefn->SetGeomType( wkbPoint  );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
-    const char* pszLine;
+    const char* pszLine = NULL;
     bool bSoundingHeader = false;
     while( fpHTF != NULL &&
            (pszLine = CPLReadLine2L(fpHTF, 1024, NULL)) != NULL)
@@ -221,7 +219,6 @@ OGRHTFLayer::~OGRHTFLayer()
         VSIFCloseL( fpHTF );
 }
 
-
 /************************************************************************/
 /*                       ~OGRHTFSoundingLayer()                         */
 /************************************************************************/
@@ -247,7 +244,6 @@ void OGRHTFLayer::ResetReading()
     }
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -258,7 +254,7 @@ void OGRHTFPolygonLayer::ResetReading()
     OGRHTFLayer::ResetReading();
     if (fpHTF)
     {
-        const char* pszLine;
+        const char* pszLine = NULL;
         while( (pszLine = CPLReadLine2L(fpHTF, 1024, NULL)) != NULL)
         {
             if (strcmp(pszLine, "POLYGON DATA") == 0)
@@ -271,7 +267,6 @@ void OGRHTFPolygonLayer::ResetReading()
     }
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -282,7 +277,7 @@ void OGRHTFSoundingLayer::ResetReading()
     OGRHTFLayer::ResetReading();
     if (fpHTF)
     {
-        const char* pszLine;
+        const char* pszLine = NULL;
         while( (pszLine = CPLReadLine2L(fpHTF, 1024, NULL)) != NULL)
         {
             if (strcmp(pszLine, "SOUNDING DATA") == 0)
@@ -334,8 +329,6 @@ OGRFeature *OGRHTFPolygonLayer::GetNextRawFeature()
 {
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
-    const char* pszLine;
-
     OGRLinearRing oLR;
     bool bHasFirstCoord = false;
     double dfFirstEasting = 0;
@@ -345,6 +338,7 @@ OGRFeature *OGRHTFPolygonLayer::GetNextRawFeature()
     bool bInIsland = false;
     OGRPolygon* poPoly = new OGRPolygon();
 
+    const char* pszLine = NULL;
     while( (pszLine = CPLReadLine2L(fpHTF, 1024, NULL)) != NULL)
     {
         if (pszLine[0] == ';')
@@ -449,17 +443,16 @@ OGRFeature *OGRHTFPolygonLayer::GetNextRawFeature()
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                         GetNextRawFeature()                          */
 /************************************************************************/
 
 OGRFeature *OGRHTFSoundingLayer::GetNextRawFeature()
 {
-    const char* pszLine;
 
     OGRLinearRing oLR;
 
+    const char* pszLine = NULL;
     while( (pszLine = CPLReadLine2L(fpHTF, 1024, NULL)) != NULL)
     {
         if (pszLine[0] == ';')
@@ -533,7 +526,7 @@ GIntBig OGRHTFSoundingLayer::GetFeatureCount(int bForce)
         return 0;
 
     int nCount = 0;
-    const char* pszLine;
+    const char* pszLine = NULL;
     while( (pszLine = CPLReadLine2L(fpHTF, 1024, NULL)) != NULL)
     {
         if (pszLine[0] == ';')
@@ -565,7 +558,6 @@ int OGRHTFLayer::TestCapability( const char * pszCap )
     return FALSE;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -596,7 +588,6 @@ OGRErr OGRHTFLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                             SetExtent()                              */
 /************************************************************************/
@@ -611,12 +602,11 @@ void OGRHTFLayer::SetExtent( double dfMinXIn, double dfMinYIn, double dfMaxXIn,
     dfMaxY = dfMaxYIn;
 }
 
-
 /************************************************************************/
 /*                        OGRHTFMetadataLayer()                         */
 /************************************************************************/
 
-OGRHTFMetadataLayer::OGRHTFMetadataLayer(std::vector<CPLString> aosMDIn) :
+OGRHTFMetadataLayer::OGRHTFMetadataLayer(const std::vector<CPLString>& aosMDIn) :
     poFeatureDefn(new OGRFeatureDefn( "metadata" )),
     aosMD(aosMDIn),
     nNextFID(0)
@@ -635,7 +625,8 @@ OGRHTFMetadataLayer::OGRHTFMetadataLayer(std::vector<CPLString> aosMDIn) :
         if (pszSep)
         {
             *pszSep = 0;
-            int i = 0, j = 0;
+            int i = 0;
+            int j = 0;
             for(;pszStr[i];i++)
             {
                 if (pszStr[i] == ' ' || pszStr[i] == '-' || pszStr[i] == '&')
diff --git a/ogr/ogrsf_frmts/idb/drv_idb.html b/ogr/ogrsf_frmts/idb/drv_idb.html
index d905e8e..f196f56 100644
--- a/ogr/ogrsf_frmts/idb/drv_idb.html
+++ b/ogr/ogrsf_frmts/idb/drv_idb.html
@@ -43,7 +43,7 @@ Informix Client SDK
 <p>This example shows using ogrinfo to list Informix DataBlade layers on a different host.
 
 <pre>
-ogrinfo -ro IDB:'server=demo_on user=informix dbname=frames'
+ogrinfo -ro IDB:"server=demo_on user=informix dbname=frames"
 </pre>
 
 </body>
diff --git a/ogr/ogrsf_frmts/idb/ogr_idb.h b/ogr/ogrsf_frmts/idb/ogr_idb.h
index 6dd1b0a..c36517e 100644
--- a/ogr/ogrsf_frmts/idb/ogr_idb.h
+++ b/ogr/ogrsf_frmts/idb/ogr_idb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_idb.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_idb.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBTableLayer class, access to an existing table
@@ -69,20 +69,20 @@ class OGRIDBLayer : public OGRLayer
                         OGRIDBLayer();
     virtual             ~OGRIDBLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
     virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -103,30 +103,30 @@ class OGRIDBTableLayer : public OGRIDBLayer
     virtual ITCursor *  GetQuery();
 
   public:
-                        OGRIDBTableLayer( OGRIDBDataSource * );
-                        ~OGRIDBTableLayer();
+    explicit            OGRIDBTableLayer( OGRIDBDataSource * );
+                        virtual ~OGRIDBTableLayer();
 
     CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol,
                                     int bUpdate
                                   );
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
 
 #if 0
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
 #endif
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -145,18 +145,18 @@ class OGRIDBSelectLayer : public OGRIDBLayer
   public:
                         OGRIDBSelectLayer( OGRIDBDataSource *,
                                            ITCursor * );
-                        ~OGRIDBSelectLayer();
+                        virtual ~OGRIDBSelectLayer();
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -175,23 +175,23 @@ class OGRIDBDataSource : public OGRDataSource
 
   public:
                         OGRIDBDataSource();
-                        ~OGRIDBDataSource();
+                        virtual ~OGRIDBDataSource();
 
     int                 Open( const char *, int bUpdate, int bTestOpen );
     int                 OpenTable( const char *pszTableName,
                                    const char *pszGeomCol,
                                    int bUpdate );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     // Internal use
     ITConnection *      GetConnection() { return poConn; }
@@ -205,13 +205,13 @@ class OGRIDBDriver : public OGRSFDriver
 {
     public:
                        ~OGRIDBDriver();
-        const char *    GetName();
-        OGRDataSource * Open( const char *, int );
+        const char *    GetName() override;
+        OGRDataSource * Open( const char *, int ) override;
 
         OGRDataSource * CreateDataSource( const char *pszName,
-                                          char ** = NULL );
+                                          char ** = NULL ) override;
 
-        int             TestCapability( const char * );
+        int             TestCapability( const char * ) override;
 };
 
 ITCallbackResult
diff --git a/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp b/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp
index 5e91708..f5e5c66 100644
--- a/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridbdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogridbdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBDataSource class
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogridbdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogridbdatasource.cpp 36347 2016-11-20 20:43:39Z rouault $");
 /************************************************************************/
 /*                         OGRIDBDataSource()                          */
 /************************************************************************/
@@ -44,6 +43,7 @@ OGRIDBDataSource::OGRIDBDataSource()
     papoLayers = NULL;
     nLayers = 0;
     poConn = 0;
+    bDSUpdate = FALSE;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/idb/ogridbdriver.cpp b/ogr/ogrsf_frmts/idb/ogridbdriver.cpp
index ff334e0..36285eb 100644
--- a/ogr/ogrsf_frmts/idb/ogridbdriver.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridbdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogridbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBDriver class.
@@ -31,7 +30,7 @@
 #include "ogr_idb.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogridbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogridbdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                            ~OGRIDBDriver()                            */
diff --git a/ogr/ogrsf_frmts/idb/ogridblayer.cpp b/ogr/ogrsf_frmts/idb/ogridblayer.cpp
index 0833945..524c336 100644
--- a/ogr/ogrsf_frmts/idb/ogridblayer.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridblayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogridblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBLayer class, code shared between
@@ -33,7 +32,7 @@
 #include "ogr_idb.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogridblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogridblayer.cpp 36394 2016-11-21 14:30:55Z rouault $");
 
 /************************************************************************/
 /*                            OGRIDBLayer()                            */
@@ -54,6 +53,7 @@ OGRIDBLayer::OGRIDBLayer()
 
     poSRS = NULL;
     nSRSId = -2; // we haven't even queried the database for it yet.
+    poFeatureDefn = NULL;
 }
 
 /************************************************************************/
@@ -217,7 +217,6 @@ CPLErr OGRIDBLayer::BuildFeatureDefn( const char *pszLayerName,
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -330,7 +329,6 @@ OGRFeature *OGRIDBLayer::GetNextRawFeature()
 
             v->Release();
 
-
             if ( eErr != OGRERR_NONE )
             {
                 const char *pszMessage;
@@ -345,6 +343,7 @@ OGRFeature *OGRIDBLayer::GetNextRawFeature()
                         break;
                     case OGRERR_CORRUPT_DATA:
                         pszMessage = "Corrupt data";
+                        break;
                     default:
                         pszMessage = "Unrecognized error";
                 }
@@ -402,23 +401,10 @@ OGRFeature *OGRIDBLayer::GetFeature( GIntBig nFeatureId )
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRIDBLayer::TestCapability( const char * pszCap )
+int OGRIDBLayer::TestCapability( const char * /*pszCap*/ )
 
 {
-    if( EQUAL(pszCap,OLCRandomRead) )
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCFastFeatureCount) )
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCTransactions) )
-        return FALSE;
-
-    else
-        return FALSE;
+    return FALSE;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/idb/ogridbselectlayer.cpp b/ogr/ogrsf_frmts/idb/ogridbselectlayer.cpp
index fdeb777..28eb7fc 100644
--- a/ogr/ogrsf_frmts/idb/ogridbselectlayer.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridbselectlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogridbselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBSelectLayer class, layer access to the results
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_idb.h"
 
-CPL_CVSID("$Id: ogridbselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogridbselectlayer.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                          OGRIDBSelectLayer()                         */
diff --git a/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp b/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp
index 2eda4e7..39e0000 100644
--- a/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp
+++ b/ogr/ogrsf_frmts/idb/ogridbtablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogridbtablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIDBTableLayer class, access to an existing table
@@ -32,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_idb.h"
 
-CPL_CVSID("$Id: ogridbtablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogridbtablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 /************************************************************************/
 /*                          OGRIDBTableLayer()                         */
 /************************************************************************/
@@ -191,7 +190,6 @@ CPLErr OGRIDBTableLayer::Initialize( const char *pszTableName,
         }*/
     }
 
-
     return CE_None;
 }
 
@@ -540,7 +538,6 @@ OGRErr OGRIDBTableLayer::ISetFeature( OGRFeature *poFeature )
             CPLDebug("OGR_IDB", "SetFeature(): Unknown geometry type. Geometry will not be updated.");
     }
 
-
     // Create query
     CPLString osSql;
     CPLString osFields;
@@ -620,7 +617,7 @@ OGRErr OGRIDBTableLayer::ISetFeature( OGRFeature *poFeature )
             return eErr;
         }
 
-        if ( ! poFeature->IsFieldSet( i ) )
+        if ( ! poFeature->IsFieldSetAndNotNull( i ) )
         {
             if ( ! par->SetNull() )
             {
@@ -757,8 +754,9 @@ OGRErr OGRIDBTableLayer::ISetFeature( OGRFeature *poFeature )
         }
     }
     else
+    {
         bUpdateGeom = FALSE;
-
+    }
 
     // Create query
     CPLString osSql;
@@ -791,7 +789,7 @@ OGRErr OGRIDBTableLayer::ISetFeature( OGRFeature *poFeature )
         osFields += pszFieldName;
         osFields += "=";
 
-        if ( ! poFeature->IsFieldSet( i ) )
+        if ( ! poFeature->IsFieldSetAndNotNull( i ) )
         {
             osFields += "NULL";
             continue;
@@ -945,7 +943,7 @@ OGRErr OGRIDBTableLayer::ICreateFeature( OGRFeature *poFeature )
         const char * pszFieldName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
 
         // Skip NULL fields
-        if ( ! poFeature->IsFieldSet( i ) )
+        if ( ! poFeature->IsFieldSetAndNotNull( i ) )
         {
             continue;
         }
diff --git a/ogr/ogrsf_frmts/idrisi/generate_test_files.c b/ogr/ogrsf_frmts/idrisi/generate_test_files.c
index 24cdd5b..5653210 100644
--- a/ogr/ogrsf_frmts/idrisi/generate_test_files.c
+++ b/ogr/ogrsf_frmts/idrisi/generate_test_files.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: generate_test_files.c 34524 2016-07-03 02:47:25Z goatbar $
  *
  * Project:
  * Purpose:  Generate sample .VCT files
diff --git a/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h b/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
index bcf2a8a..3220067 100644
--- a/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
+++ b/ogr/ogrsf_frmts/idrisi/ogr_idrisi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_idrisi.h 32745 2016-01-04 23:16:43Z goatbar $
+ * $Id: ogr_idrisi.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Idrisi Translator
  * Purpose:  Definition of classes for OGR Idrisi driver.
@@ -57,31 +57,30 @@ protected:
 
     unsigned int       nTotalFeatures;
 
-    int                Detect_AVL_ADC(const char* pszFilename);
-    void               ReadAVLLine(OGRFeature* poFeature);
+    bool               Detect_AVL_ADC( const char* pszFilename );
+    void               ReadAVLLine( OGRFeature* poFeature );
 
     virtual OGRFeature *       GetNextRawFeature();
 
   public:
-                        OGRIdrisiLayer(const char* pszFilename,
-                                       const char* pszLayerName, VSILFILE* fp,
-                                       OGRwkbGeometryType eGeomType, const char* pszWTKString);
-                        ~OGRIdrisiLayer();
+    OGRIdrisiLayer( const char* pszFilename,
+                    const char* pszLayerName, VSILFILE* fp,
+                    OGRwkbGeometryType eGeomType, const char* pszWTKString );
+    virtual ~OGRIdrisiLayer();
 
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual int                 TestCapability( const char * ) override;
 
-    virtual int                 TestCapability( const char * );
-
-    void SetExtent(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    void SetExtent( double dfMinX, double dfMinY, double dfMaxX, double dfMaxY );
+    virtual OGRErr GetExtent( OGREnvelope *psExtent, int bForce = TRUE ) override;
+    virtual OGRErr GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce ) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    virtual GIntBig         GetFeatureCount( int bForce = TRUE );
+    virtual GIntBig         GetFeatureCount( int bForce = TRUE ) override;
 };
 
 /************************************************************************/
@@ -96,17 +95,17 @@ class OGRIdrisiDataSource : public OGRDataSource
     int                 nLayers;
 
   public:
-                        OGRIdrisiDataSource();
-                        ~OGRIdrisiDataSource();
+    OGRIdrisiDataSource();
+    virtual ~OGRIdrisiDataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -116,12 +115,11 @@ class OGRIdrisiDataSource : public OGRDataSource
 class OGRIdrisiDriver : public OGRSFDriver
 {
   public:
-                ~OGRIdrisiDriver();
+    virtual ~OGRIdrisiDriver();
 
-    virtual const char*         GetName();
-    virtual OGRDataSource*      Open( const char *, int );
-    virtual int                 TestCapability( const char * );
+    virtual const char*         GetName() override;
+    virtual OGRDataSource*      Open( const char *, int ) override;
+    virtual int                 TestCapability( const char * ) override;
 };
 
-
-#endif /* ndef OGR_IDRISI_H_INCLUDED */
+#endif // ndef OGR_IDRISI_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
index 220aa94..7a7838a 100644
--- a/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisidatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogridrisidatasource.cpp 32745 2016-01-04 23:16:43Z goatbar $
  *
  * Project:  Idrisi Translator
  * Purpose:  Implements OGRIdrisiDataSource class
@@ -32,7 +31,7 @@
 #include "idrisi.h"
 #include "ogr_idrisi.h"
 
-CPL_CVSID("$Id: ogridrisidatasource.cpp 32745 2016-01-04 23:16:43Z goatbar $");
+CPL_CVSID("$Id: ogridrisidatasource.cpp 34996 2016-08-09 02:25:28Z goatbar $");
 
 /************************************************************************/
 /*                        OGRIdrisiDataSource()                         */
@@ -141,7 +140,7 @@ int OGRIdrisiDataSource::Open( const char * pszFilename )
                                     &pszWTKString);
     }
 
-    GByte chType;
+    GByte chType = 0;
     if (VSIFReadL(&chType, 1, 1, fpVCT) != 1)
     {
         VSIFCloseL(fpVCT);
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
index 2e70ef7..84afbfa 100644
--- a/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisidriver.cpp
@@ -31,7 +31,7 @@
 #include "ogr_idrisi.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogridrisidriver.cpp 32745 2016-01-04 23:16:43Z goatbar $");
+CPL_CVSID("$Id: ogridrisidriver.cpp 34996 2016-08-09 02:25:28Z goatbar $");
 
 // g++ ogr/ogrsf_frmts/idrisi/*.cpp -Wall -g -fPIC -shared -o ogr_Idrisi.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts/idrisi -Iogr/ogrsf_frmts -Ifrmts/idrisi
 
@@ -96,6 +96,9 @@ int OGRIdrisiDriver::TestCapability( const char * /* pszCap */ )
 void RegisterOGRIdrisi()
 
 {
+    if( GDALGetDriverByName( "Idrisi" ) != NULL )
+        return;
+
     OGRSFDriver* poDriver = new OGRIdrisiDriver;
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Idrisi Vector (.vct)" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "vct" );
diff --git a/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp b/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
index 0b696ad..a08c36f 100644
--- a/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
+++ b/ogr/ogrsf_frmts/idrisi/ogridrisilayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogridrisilayer.cpp 32745 2016-01-04 23:16:43Z goatbar $
  *
  * Project:  Idrisi Translator
  * Purpose:  Implements OGRIdrisiLayer class.
@@ -33,7 +32,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogridrisilayer.cpp 32745 2016-01-04 23:16:43Z goatbar $");
+CPL_CVSID("$Id: ogridrisilayer.cpp 34996 2016-08-09 02:25:28Z goatbar $");
 
 /************************************************************************/
 /*                         OGRIdrisiLayer()                             */
@@ -74,13 +73,13 @@ OGRIdrisiLayer::OGRIdrisiLayer( const char* pszFilename,
     poFeatureDefn->AddFieldDefn( &oFieldDefn );
 
     VSIFSeekL( fp, 1, SEEK_SET );
-    if (VSIFReadL( &nTotalFeatures, sizeof(unsigned int), 1, fp ) != 1)
+    if( VSIFReadL( &nTotalFeatures, sizeof(unsigned int), 1, fp ) != 1 )
         nTotalFeatures = 0;
     CPL_LSBPTR32(&nTotalFeatures);
 
-    if (nTotalFeatures != 0)
+    if( nTotalFeatures != 0 )
     {
-        if (!Detect_AVL_ADC(pszFilename))
+        if( !Detect_AVL_ADC(pszFilename) )
         {
             if( fpAVL != NULL )
                 VSIFCloseL( fpAVL );
@@ -113,21 +112,21 @@ OGRIdrisiLayer::~OGRIdrisiLayer()
 /*                           Detect_AVL_ADC()                           */
 /************************************************************************/
 
-int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
+bool OGRIdrisiLayer::Detect_AVL_ADC( const char* pszFilename )
 {
 // --------------------------------------------------------------------
 //      Look for .adc file
 // --------------------------------------------------------------------
     const char* pszADCFilename = CPLResetExtension(pszFilename, "adc");
     VSILFILE* fpADC = VSIFOpenL(pszADCFilename, "rb");
-    if (fpADC == NULL)
+    if( fpADC == NULL )
     {
         pszADCFilename = CPLResetExtension(pszFilename, "ADC");
         fpADC = VSIFOpenL(pszADCFilename, "rb");
     }
 
     char** papszADC = NULL;
-    if (fpADC != NULL)
+    if( fpADC != NULL )
     {
         VSIFCloseL(fpADC);
         fpADC = NULL;
@@ -138,8 +137,8 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
         CPLErrorReset();
     }
 
-    if (papszADC == NULL)
-        return FALSE;
+    if( papszADC == NULL )
+        return false;
 
     CSLSetNameValueSeparator( papszADC, ":" );
 
@@ -147,7 +146,7 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
     if( pszVersion == NULL || !EQUAL( pszVersion, "IDRISI Values A.1" ) )
     {
         CSLDestroy( papszADC );
-        return FALSE;
+        return false;
     }
 
     const char *pszFileType = CSLFetchNameValue( papszADC, "file type   " );
@@ -155,7 +154,7 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
     {
         CPLDebug("IDRISI", ".adc file found, but file type != ascii");
         CSLDestroy( papszADC );
-        return FALSE;
+        return false;
     }
 
     const char* pszRecords = CSLFetchNameValue( papszADC, "records     " );
@@ -164,7 +163,7 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
         CPLDebug("IDRISI", ".adc file found, but 'records' not found or not "
                  "consistent with feature number declared in .vdc");
         CSLDestroy( papszADC );
-        return FALSE;
+        return false;
     }
 
     const char* pszFields = CSLFetchNameValue( papszADC, "fields      " );
@@ -173,7 +172,7 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
         CPLDebug( "IDRISI",
                   ".adc file found, but 'fields' not found or invalid" );
         CSLDestroy( papszADC );
-        return FALSE;
+        return false;
     }
 
 // --------------------------------------------------------------------
@@ -189,7 +188,7 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
     if (fpAVL == NULL)
     {
         CSLDestroy( papszADC );
-        return FALSE;
+        return false;
     }
 
 // --------------------------------------------------------------------
@@ -201,7 +200,7 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
     snprintf(szKey, sizeof(szKey), "field %d ", iCurField);
 
     char** papszIter = papszADC;
-    const char* pszLine;
+    const char* pszLine = NULL;
     bool bFieldFound = false;
     CPLString osFieldName;
     while((pszLine = *papszIter) != NULL)
@@ -228,7 +227,7 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
             if( iCurField == 0 && oFieldDefn.GetType() != OFTInteger )
             {
                 CSLDestroy( papszADC );
-                return FALSE;
+                return false;
             }
 
             if( iCurField != 0 )
@@ -243,7 +242,7 @@ int OGRIdrisiLayer::Detect_AVL_ADC(const char* pszFilename)
 
     CSLDestroy(papszADC);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -272,21 +271,21 @@ OGRFeature *OGRIdrisiLayer::GetNextFeature()
             return NULL;
 
         OGRFeature *poFeature = GetNextRawFeature();
-        if (poFeature == NULL)
+        if( poFeature == NULL )
         {
             bEOF = true;
             return NULL;
         }
 
-        if((m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
-        && (m_poAttrQuery == NULL
-            || m_poAttrQuery->Evaluate( poFeature )) )
+        if( (m_poFilterGeom == NULL
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
         {
             return poFeature;
         }
-        else
-            delete poFeature;
+
+        delete poFeature;
     }
 }
 
@@ -297,10 +296,10 @@ OGRFeature *OGRIdrisiLayer::GetNextFeature()
 int OGRIdrisiLayer::TestCapability( const char * pszCap )
 
 {
-    if (EQUAL(pszCap, OLCFastFeatureCount))
+    if( EQUAL(pszCap, OLCFastFeatureCount) )
         return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
 
-    if (EQUAL(pszCap, OLCFastGetExtent))
+    if( EQUAL(pszCap, OLCFastGetExtent) )
         return bExtentValid;
 
     return FALSE;
@@ -316,9 +315,9 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
     {
         if (eGeomType == wkbPoint)
         {
-            double dfId;
-            double dfX;
-            double dfY;
+            double dfId = 0.0;
+            double dfX = 0.0;
+            double dfY = 0.0;
             if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
                 VSIFReadL(&dfX, sizeof(double), 1, fp) != 1 ||
                 VSIFReadL(&dfY, sizeof(double), 1, fp) != 1)
@@ -351,18 +350,17 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
         }
         else if (eGeomType == wkbLineString)
         {
-            double dfId;
-            double dfMinXShape;
-            double dfMaxXShape;
-            double dfMinYShape;
-            double dfMaxYShape;
-            unsigned int nNodes;
+            double dfId = 0.0;
+            double dfMinXShape = 0.0;
+            double dfMaxXShape = 0.0;
+            double dfMinYShape = 0.0;
+            double dfMaxYShape = 0.0;
 
-            if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
+            if( VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
                 VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 ||
                 VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 ||
                 VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 ||
-                VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1)
+                VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1 )
             {
                 return NULL;
             }
@@ -372,22 +370,23 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
             CPL_LSBPTR64(&dfMinYShape);
             CPL_LSBPTR64(&dfMaxYShape);
 
-            if (VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1)
+            unsigned int nNodes = 0;
+            if( VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1 )
             {
                 return NULL;
             }
             CPL_LSBPTR32(&nNodes);
 
-            if (nNodes > 100 * 1000 * 1000)
+            if( nNodes > 100 * 1000 * 1000 )
                 return NULL;
 
-            if (m_poFilterGeom != NULL &&
+            if( m_poFilterGeom != NULL &&
                 (dfMaxXShape < m_sFilterEnvelope.MinX ||
                  dfMinXShape > m_sFilterEnvelope.MaxX ||
                  dfMaxYShape < m_sFilterEnvelope.MinY ||
-                 dfMinYShape > m_sFilterEnvelope.MaxY))
+                 dfMinYShape > m_sFilterEnvelope.MaxY) )
             {
-                nNextFID ++;
+                nNextFID++;
                 VSIFSeekL(fp, sizeof(OGRRawPoint) * nNodes, SEEK_CUR);
                 continue;
             }
@@ -399,15 +398,15 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
                 return NULL;
             }
 
-            if (static_cast<unsigned int>(VSIFReadL(
-                    poRawPoints, sizeof(OGRRawPoint), nNodes, fp)) != nNodes)
+            if( static_cast<unsigned int>(VSIFReadL(
+                    poRawPoints, sizeof(OGRRawPoint), nNodes, fp)) != nNodes )
             {
                 VSIFree(poRawPoints);
                 return NULL;
             }
 
 #if defined(CPL_MSB)
-            for(unsigned int iNode=0; iNode<nNodes; iNode++)
+            for( unsigned int iNode=0; iNode<nNodes; iNode++ )
             {
                 CPL_LSBPTR64(&poRawPoints[iNode].x);
                 CPL_LSBPTR64(&poRawPoints[iNode].y);
@@ -419,7 +418,7 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
 
             VSIFree(poRawPoints);
 
-            if (poSRS)
+            if( poSRS )
                 poGeom->assignSpatialReference(poSRS);
             OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
             poFeature->SetField(0, dfId);
@@ -428,15 +427,13 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
             ReadAVLLine(poFeature);
             return poFeature;
         }
-        else /* if (eGeomType == wkbPolygon) */
+        else  // if (eGeomType == wkbPolygon)
         {
-            double dfId;
-            double dfMinXShape;
-            double dfMaxXShape;
-            double dfMinYShape;
-            double dfMaxYShape;
-            unsigned int nParts;
-            unsigned int nTotalNodes;
+            double dfId = 0.0;
+            double dfMinXShape = 0.0;
+            double dfMaxXShape = 0.0;
+            double dfMinYShape = 0.0;
+            double dfMaxYShape = 0.0;
 
             if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 ||
                 VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 ||
@@ -451,6 +448,8 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
             CPL_LSBPTR64(&dfMaxXShape);
             CPL_LSBPTR64(&dfMinYShape);
             CPL_LSBPTR64(&dfMaxYShape);
+            unsigned int nParts = 0;
+            unsigned int nTotalNodes = 0;
             if (VSIFReadL(&nParts, sizeof(unsigned int), 1, fp) != 1 ||
                 VSIFReadL(&nTotalNodes, sizeof(unsigned int), 1, fp) != 1)
             {
@@ -501,7 +500,7 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
             }
             else
             {
-                unsigned int nNodes;
+                unsigned int nNodes = 0;
                 if (VSIFReadL(&nNodes, sizeof(unsigned int) * nParts, 1, fp) != 1)
                 {
                     VSIFree(poRawPoints);
@@ -520,10 +519,10 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
             {
                 unsigned int nNodes
                     = (nParts > 1) ? panNodesCount[iPart] : nTotalNodes;
-                if (nNodes > nTotalNodes ||
+                if( nNodes > nTotalNodes ||
                     static_cast<unsigned int>(
                         VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp))
-                    != nNodes)
+                    != nNodes )
                 {
                     VSIFree(poRawPoints);
                     VSIFree(panNodesCount);
@@ -532,7 +531,7 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
                 }
 
 #if defined(CPL_MSB)
-                for(unsigned int iNode=0; iNode<nNodes; iNode++)
+                for( unsigned int iNode=0; iNode<nNodes; iNode++ )
                 {
                     CPL_LSBPTR64(&poRawPoints[iNode].x);
                     CPL_LSBPTR64(&poRawPoints[iNode].y);
@@ -547,7 +546,7 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
             VSIFree(poRawPoints);
             VSIFree(panNodesCount);
 
-            if (poSRS)
+            if( poSRS )
                 poGeom->assignSpatialReference(poSRS);
             OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
             poFeature->SetField(0, dfId);
@@ -565,20 +564,20 @@ OGRFeature *OGRIdrisiLayer::GetNextRawFeature()
 
 void OGRIdrisiLayer::ReadAVLLine(OGRFeature* poFeature)
 {
-    if (fpAVL == NULL)
+    if( fpAVL == NULL )
         return;
 
     const char* pszLine = CPLReadLineL(fpAVL);
-    if (pszLine == NULL)
+    if( pszLine == NULL )
         return;
 
     char** papszTokens = CSLTokenizeStringComplex(pszLine, "\t", TRUE, TRUE);
-    if (CSLCount(papszTokens) == poFeatureDefn->GetFieldCount())
+    if( CSLCount(papszTokens) == poFeatureDefn->GetFieldCount() )
     {
         const int nID = atoi(papszTokens[0]);
-        if (nID == poFeature->GetFID())
+        if( nID == poFeature->GetFID() )
         {
-            for(int i=1;i<poFeatureDefn->GetFieldCount();i++)
+            for( int i = 1; i < poFeatureDefn->GetFieldCount(); i++ )
             {
                 poFeature->SetField(i, papszTokens[i]);
             }
@@ -595,10 +594,10 @@ void OGRIdrisiLayer::SetExtent( double dfMinXIn, double dfMinYIn,
                                 double dfMaxXIn, double dfMaxYIn )
 {
     bExtentValid = true;
-    this->dfMinX = dfMinXIn;
-    this->dfMinY = dfMinYIn;
-    this->dfMaxX = dfMaxXIn;
-    this->dfMaxY = dfMaxYIn;
+    dfMinX = dfMinXIn;
+    dfMinY = dfMinYIn;
+    dfMaxX = dfMaxXIn;
+    dfMaxY = dfMaxYIn;
 }
 
 /************************************************************************/
@@ -623,7 +622,7 @@ OGRErr OGRIdrisiLayer::GetExtent(OGREnvelope *psExtent, int bForce)
 
 GIntBig OGRIdrisiLayer::GetFeatureCount( int bForce )
 {
-    if (nTotalFeatures > 0 && m_poFilterGeom == NULL && m_poAttrQuery == NULL)
+    if( nTotalFeatures > 0 && m_poFilterGeom == NULL && m_poAttrQuery == NULL )
         return nTotalFeatures;
 
     return OGRLayer::GetFeatureCount(bForce);
diff --git a/ogr/ogrsf_frmts/ili/GNUmakefile b/ogr/ogrsf_frmts/ili/GNUmakefile
index b513f6c..3206fe2 100644
--- a/ogr/ogrsf_frmts/ili/GNUmakefile
+++ b/ogr/ogrsf_frmts/ili/GNUmakefile
@@ -11,7 +11,7 @@ ifeq ($(HAVE_GEOS),yes)
 CPPFLAGS 	:=	-DHAVE_GEOS=1 $(GEOS_CFLAGS) $(CPPFLAGS)
 endif
 
-CPPFLAGS :=	-I.. -I../..  $(XERCES_INCLUDE) $(CPPFLAGS)
+CPPFLAGS :=	-I.. -I../.. -DHAVE_XERCES $(XERCES_INCLUDE) $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
diff --git a/ogr/ogrsf_frmts/ili/ili1reader.cpp b/ogr/ogrsf_frmts/ili/ili1reader.cpp
index 8ada9db..8064213 100644
--- a/ogr/ogrsf_frmts/ili/ili1reader.cpp
+++ b/ogr/ogrsf_frmts/ili/ili1reader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ili1reader.cpp 33829 2016-03-31 16:21:01Z rouault $
  *
  * Project:  Interlis 1 Reader
  * Purpose:  Implementation of ILI1Reader class.
@@ -49,7 +48,7 @@
 #  endif
 #endif
 
-CPL_CVSID("$Id: ili1reader.cpp 33829 2016-03-31 16:21:01Z rouault $");
+CPL_CVSID("$Id: ili1reader.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 //
 // ILI1Reader
@@ -471,6 +470,7 @@ void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType,
           OGRErr error =  ogrCurve->addCurveDirectly(arc);
           if (error != OGRERR_NONE) {
             CPLError(CE_Warning, CPLE_AppDefined, "Added geometry: %s", arc->exportToJson() );
+            delete arc;
           }
           arc = NULL;
         }
@@ -488,6 +488,7 @@ void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType,
         } else {
           ogrLine->empty();
         }
+        delete arc;
         arc = new OGRCircularString();
         arc->addPoint(&ogrPoint);
         ogrPoint.setX(CPLAtof(tokens[1])); ogrPoint.setY(CPLAtof(tokens[2]));
@@ -546,6 +547,7 @@ void ILI1Reader::ReadGeom( char **stgeom, int geomIdx, OGRwkbGeometryType eType,
 
       CSLDestroy(tokens);
     }
+    delete arc;
 
     delete ogrLine;
 
@@ -637,11 +639,11 @@ char ** ILI1Reader::ReadParseLine()
 {
     CPLAssert( fpItf != NULL );
     if( fpItf == NULL )
-        return( NULL );
+        return NULL;
 
     const char  *pszLine = CPLReadLine( fpItf );
     if( pszLine == NULL )
-        return( NULL );
+        return NULL;
 
     if (strlen(pszLine) == 0) return NULL;
 
@@ -676,8 +678,6 @@ char ** ILI1Reader::ReadParseLine()
     return tokens;
 }
 
-
-
 IILI1Reader *CreateILI1Reader() {
     return new ILI1Reader();
 }
diff --git a/ogr/ogrsf_frmts/ili/ili1reader.h b/ogr/ogrsf_frmts/ili/ili1reader.h
index df58c9c..97008f8 100644
--- a/ogr/ogrsf_frmts/ili/ili1reader.h
+++ b/ogr/ogrsf_frmts/ili/ili1reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili1reader.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ili1reader.h 34524 2016-07-03 02:47:25Z goatbar $
  *
  * Project:  Interlis 1 Reader
  * Purpose:  Private Declarations for Reader code.
diff --git a/ogr/ogrsf_frmts/ili/ili1readerp.h b/ogr/ogrsf_frmts/ili/ili1readerp.h
index 77b97cd..d2177b7 100644
--- a/ogr/ogrsf_frmts/ili/ili1readerp.h
+++ b/ogr/ogrsf_frmts/ili/ili1readerp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili1readerp.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ili1readerp.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Interlis 1 Reader
  * Purpose:  Private Declarations for Reader code.
@@ -33,7 +33,6 @@
 #include "ili1reader.h"
 #include "ogr_ili1.h"
 
-
 class ILI1Reader;
 class OGRILI1Layer;
 
@@ -56,20 +55,19 @@ public:
                  ILI1Reader();
                 ~ILI1Reader();
 
-    int          OpenFile( const char *pszFilename );
-    int          ReadModel( ImdReader *poImdReader, const char *pszModelFilename, OGRILI1DataSource *poDS );
-    int          ReadFeatures();
+    int          OpenFile( const char *pszFilename ) override;
+    int          ReadModel( ImdReader *poImdReader, const char *pszModelFilename, OGRILI1DataSource *poDS ) override;
+    int          ReadFeatures() override;
     int          ReadTable(const char *layername);
     void         ReadGeom(char **stgeom, int geomIdx, OGRwkbGeometryType eType, OGRFeature *feature);
     char         **ReadParseLine();
 
     void         AddLayer( OGRILI1Layer * poNewLayer );
-    OGRILI1Layer *GetLayer( int );
-    OGRILI1Layer *GetLayerByName( const char* );
-    int          GetLayerCount();
+    OGRILI1Layer *GetLayer( int ) override;
+    OGRILI1Layer *GetLayerByName( const char* ) override;
+    int          GetLayerCount() override;
 
-    const char*  GetLayerNameString(const char* topicname, const char* tablename);
+    static const char*  GetLayerNameString(const char* topicname, const char* tablename);
 };
 
-
 #endif
diff --git a/ogr/ogrsf_frmts/ili/ili2handler.cpp b/ogr/ogrsf_frmts/ili/ili2handler.cpp
index 0eaba04..c2e9cc9 100644
--- a/ogr/ogrsf_frmts/ili/ili2handler.cpp
+++ b/ogr/ogrsf_frmts/ili/ili2handler.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ili2handler.cpp 33109 2016-01-23 16:25:42Z rouault $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Implementation of ILI2Handler class.
@@ -36,7 +35,7 @@
 
 #include <xercesc/sax2/Attributes.hpp>
 
-CPL_CVSID("$Id: ili2handler.cpp 33109 2016-01-23 16:25:42Z rouault $");
+CPL_CVSID("$Id: ili2handler.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 //
 // constants
@@ -47,11 +46,12 @@ static const char* const ILI2_DATASECTION = "DATASECTION";
 // ILI2Handler
 //
 ILI2Handler::ILI2Handler( ILI2Reader *poReader ) :
+    m_poReader(poReader),
     level(0),
+    dom_doc(NULL),
+    dom_elem(NULL),
     m_nEntityCounter(0)
 {
-  m_poReader = poReader;
-
   XMLCh *tmpCh = XMLString::transcode("CORE");
   DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tmpCh);
   XMLString::release(&tmpCh);
@@ -77,7 +77,6 @@ ILI2Handler::~ILI2Handler() {
   dom_doc->release();
 }
 
-
 void ILI2Handler::startDocument() {
   // the level counter starts with DATASECTION
   level = -1;
@@ -144,7 +143,6 @@ void ILI2Handler::endElement(
   }
 }
 
-#if XERCES_VERSION_MAJOR >= 3
 /************************************************************************/
 /*                     characters() (xerces 3 version)                  */
 /************************************************************************/
@@ -163,27 +161,6 @@ void ILI2Handler::characters( const XMLCh *const chars,
   }
 }
 
-#else
-/************************************************************************/
-/*                     characters() (xerces 2 version)                  */
-/************************************************************************/
-
-void ILI2Handler::characters( const XMLCh *const chars,
-                     CPL_UNUSED const unsigned int length ) {
-
-  // add the text element
-  if (level >= 3) {
-    char *tmpC = XMLString::transcode(chars);
-
-    // only add the text if it is not empty
-    if (trim(tmpC) != "")
-      dom_elem->appendChild(dom_doc->createTextNode(chars));
-
-    XMLString::release(&tmpC);
-  }
-}
-#endif
-
 void ILI2Handler::startEntity (CPL_UNUSED const XMLCh *const name)
 {
     m_nEntityCounter++;
diff --git a/ogr/ogrsf_frmts/ili/ili2reader.cpp b/ogr/ogrsf_frmts/ili/ili2reader.cpp
index e5f873e..fe8a222 100644
--- a/ogr/ogrsf_frmts/ili/ili2reader.cpp
+++ b/ogr/ogrsf_frmts/ili/ili2reader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ili2reader.cpp 33123 2016-01-23 18:59:28Z rouault $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Implementation of ILI2Reader class.
@@ -35,19 +34,16 @@
 
 #include "ili2reader.h"
 
-
-//from trstring.cpp/gmlreaderp.h
-char *tr_strdup( const XMLCh * );
-
 using namespace std;
 
-CPL_CVSID("$Id: ili2reader.cpp 33123 2016-01-23 18:59:28Z rouault $");
+CPL_CVSID("$Id: ili2reader.cpp 37743 2017-03-17 13:14:00Z rouault $");
 
 //
 // constants
 //
 static const char * const ILI2_TID = "TID";
-static const char * const ILI2_REF = "REF";
+static const XMLCh xmlch_ILI2_TID[] = {'T', 'I', 'D', '\0' };
+static const XMLCh ILI2_REF[] = {'R', 'E', 'F', '\0' };
 
 static const int ILI2_STRING_TYPE = 0;
 static const int ILI2_COORD_TYPE = 1;
@@ -64,7 +60,6 @@ static const char * const ILI2_BOUNDARY = "BOUNDARY";
 static const char * const ILI2_AREA = "AREA";
 static const char * const ILI2_SURFACE = "SURFACE";
 
-
 //
 // helper functions
 //
@@ -130,18 +125,15 @@ static char *getObjValue(DOMElement *elem) {
   DOMNode* child = elem->getFirstChild();
   if ((child != NULL) && (child->getNodeType() == DOMNode::TEXT_NODE))
   {
-    char* pszNodeValue = tr_strdup(child->getNodeValue());
-    return pszNodeValue;
+    return CPLStrdup(transcode(child->getNodeValue()));
   }
 
   return NULL;
 }
 
 static char *getREFValue(DOMElement *elem) {
-  XMLCh* pszIli2_ref = XMLString::transcode(ILI2_REF);
-  char* pszREFValue = tr_strdup(elem->getAttribute(pszIli2_ref));
-  XMLString::release(&pszIli2_ref);
-  return pszREFValue;
+  CPLString osREFValue(transcode(elem->getAttribute(ILI2_REF)));
+  return CPLStrdup(osREFValue);
 }
 
 static OGRPoint *getPoint(DOMElement *elem) {
@@ -412,8 +404,7 @@ static char* fieldName(DOMElement* elem) {
       CPLError(CE_Failure, CPLE_AssertionFailed, "node == NULL");
       return CPLStrdup("***bug***");
   }
-  char* pszNodeName = tr_strdup(node->getNodeName());
-  return pszNodeName;
+  return CPLStrdup(transcode(node->getNodeName()));
 }
 
 void ILI2Reader::setFieldDefn(OGRFeatureDefn *featureDef, DOMElement* elem) {
@@ -484,20 +475,19 @@ void ILI2Reader::SetFieldValues(OGRFeature *feature, DOMElement* elem) {
   }
 }
 
-
 //
 // ILI2Reader
 //
 IILI2Reader::~IILI2Reader() {
 }
 
-ILI2Reader::ILI2Reader() {
-    m_poILI2Handler = NULL;
-    m_poSAXReader = NULL;
-    m_bReadStarted = FALSE;
-
-    m_pszFilename = NULL;
-
+ILI2Reader::ILI2Reader() :
+    m_pszFilename(NULL),
+    m_poILI2Handler(NULL),
+    m_poSAXReader(NULL),
+    m_bReadStarted(FALSE),
+    m_bXercesInitialized(false)
+{
     SetupParser();
 }
 
@@ -506,11 +496,14 @@ ILI2Reader::~ILI2Reader() {
 
     CleanupParser();
 
+    if( m_bXercesInitialized )
+        OGRDeinitializeXerces();
+
     list<OGRLayer *>::const_iterator layerIt = m_listLayer.begin();
     while (layerIt != m_listLayer.end()) {
         OGRILI2Layer *tmpLayer = (OGRILI2Layer *)*layerIt;
         delete tmpLayer;
-        layerIt++;
+        ++layerIt;
     }
 }
 
@@ -521,26 +514,11 @@ void ILI2Reader::SetSourceFile( const char *pszFilename ) {
 
 int ILI2Reader::SetupParser() {
 
-    static int bXercesInitialized = FALSE;
-
-    if( !bXercesInitialized )
+    if( !m_bXercesInitialized )
     {
-        try
-        {
-            XMLPlatformUtils::Initialize();
-        }
-
-        catch (const XMLException& toCatch)
-        {
-            char* msg = tr_strdup(toCatch.getMessage());
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to initialize Xerces C++ based ILI2 reader. "
-                      "Error message:\n%s\n", msg );
-            CPLFree(msg);
-
+        if( !OGRInitializeXerces() )
             return FALSE;
-        }
-        bXercesInitialized = TRUE;
+        m_bXercesInitialized = true;
     }
 
     // Cleanup any old parser.
@@ -612,15 +590,14 @@ int ILI2Reader::SaveClasses( const char *pszFile = NULL ) {
     }
     catch (const SAXException& toCatch)
     {
-        char* msg = tr_strdup(toCatch.getMessage());
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Parsing failed: %s\n", msg );
-        CPLFree(msg);
+                  "Parsing failed: %s\n",
+                  transcode(toCatch.getMessage()).c_str());
 
         return FALSE;
     }
 
-  if (m_missAttrs.size() != 0) {
+  if (!m_missAttrs.empty()) {
     m_missAttrs.sort();
     m_missAttrs.unique();
     string attrs = "";
@@ -656,19 +633,17 @@ OGRLayer* ILI2Reader::GetLayer(const char* pszName) {
 }
 
 int ILI2Reader::AddFeature(DOMElement *elem) {
-  bool newLayer = true;
-  OGRLayer *curLayer = NULL;
-  char *pszName = tr_strdup(elem->getTagName());
-  //CPLDebug( "OGR_ILI", "Reading layer: %s", pszName );
+  CPLString osName(transcode(elem->getTagName()));
+  //CPLDebug( "OGR_ILI", "Reading layer: %s", osName.c_str() );
 
   // test if this layer exist
-  curLayer = GetLayer(pszName);
-  newLayer = (curLayer == NULL);
+  OGRILI2Layer* curLayer = dynamic_cast<OGRILI2Layer*>(GetLayer(osName));
+  bool newLayer = (curLayer == NULL);
 
   // add a layer
   if (newLayer) {
-    CPLDebug( "OGR_ILI", "Adding layer: %s", pszName );
-    OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(pszName);
+    CPLDebug( "OGR_ILI", "Adding layer: %s", osName.c_str() );
+    OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(osName);
     poFeatureDefn->SetGeomType( wkbUnknown );
     GeomFieldInfos oGeomFieldInfos;
     curLayer = new OGRILI2Layer(poFeatureDefn, oGeomFieldInfos, NULL);
@@ -691,19 +666,13 @@ int ILI2Reader::AddFeature(DOMElement *elem) {
   // assign TID
   int fIndex = feature->GetFieldIndex(ILI2_TID);
   if (fIndex != -1) {
-      XMLCh *pszIli2_tid = XMLString::transcode(ILI2_TID);
-      char *fChVal = tr_strdup(elem->getAttribute(pszIli2_tid));
-      feature->SetField(fIndex, fChVal);
-      XMLString::release(&pszIli2_tid);
-      CPLFree(fChVal);
+      feature->SetField(fIndex, transcode(elem->getAttribute(xmlch_ILI2_TID)).c_str());
   } else {
       CPLDebug( "OGR_ILI","'%s' not found", ILI2_TID);
   }
 
   SetFieldValues(feature, elem);
-  CPL_IGNORE_RET_VAL(curLayer->SetFeature(feature));
-
-  CPLFree(pszName);
+  curLayer->AddFeature(feature);
 
   return 0;
 }
diff --git a/ogr/ogrsf_frmts/ili/ili2reader.h b/ogr/ogrsf_frmts/ili/ili2reader.h
index bd28bcf..6d07ac7 100644
--- a/ogr/ogrsf_frmts/ili/ili2reader.h
+++ b/ogr/ogrsf_frmts/ili/ili2reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2reader.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ili2reader.h 35911 2016-10-24 15:03:26Z goatbar $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Public Declarations for Reader code.
@@ -39,7 +39,6 @@
 #include "imdreader.h"
 #include <list>
 
-
 class CPL_DLL IILI2Reader
 {
 public:
diff --git a/ogr/ogrsf_frmts/ili/ili2readerp.h b/ogr/ogrsf_frmts/ili/ili2readerp.h
index 51420fd..0ac0bbf 100644
--- a/ogr/ogrsf_frmts/ili/ili2readerp.h
+++ b/ogr/ogrsf_frmts/ili/ili2readerp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ili2readerp.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ili2readerp.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Interlis 2 Reader
  * Purpose:  Private Declarations for Reader code.
@@ -31,6 +31,7 @@
 #define CPL_ILI2READERP_H_INCLUDED
 
 #include "xercesc_headers.h"
+#include "ogr_xerces.h"
 
 #include "ili2reader.h"
 #include "ogr_ili2.h"
@@ -44,7 +45,6 @@ std::string ltrim(std::string tmpstr);
 std::string rtrim(std::string tmpstr);
 std::string trim(std::string tmpstr);
 
-
 class ILI2Reader;
 
 /************************************************************************/
@@ -62,37 +62,31 @@ class ILI2Handler : public DefaultHandler
     int m_nEntityCounter;
 
 public:
-    ILI2Handler( ILI2Reader *poReader );
+    explicit ILI2Handler( ILI2Reader *poReader );
     ~ILI2Handler();
 
-    void startDocument();
-    void endDocument();
+    void startDocument() override;
+    void endDocument() override;
 
     void startElement(
         const   XMLCh* const    uri,
         const   XMLCh* const    localname,
         const   XMLCh* const    qname,
         const   Attributes& attrs
-    );
+    ) override;
     void endElement(
         const   XMLCh* const    uri,
         const   XMLCh* const    localname,
         const   XMLCh* const    qname
-    );
-#if XERCES_VERSION_MAJOR >= 3
-    void characters( const XMLCh *const chars,
-                     const XMLSize_t length ); // xerces 3
-#else
+    ) override;
     void characters( const XMLCh *const chars,
-                     const unsigned int length ); // xerces 2
-#endif
+                     const XMLSize_t length ) override; // xerces 3
 
-    void startEntity (const XMLCh *const name);
+    void startEntity (const XMLCh *const name) override;
 
-    void fatalError(const SAXParseException&);
+    void fatalError(const SAXParseException&) override;
 };
 
-
 /************************************************************************/
 /*                              ILI2Reader                               */
 /************************************************************************/
@@ -113,16 +107,18 @@ private:
 
     std::list<OGRLayer *> m_listLayer;
 
+    bool     m_bXercesInitialized;
+
 public:
              ILI2Reader();
             ~ILI2Reader();
 
-    void     SetSourceFile( const char *pszFilename );
-    int      ReadModel( ImdReader *poImdReader, const char *modelFilename );
-    int      SaveClasses( const char *pszFile );
+    void     SetSourceFile( const char *pszFilename ) override;
+    int      ReadModel( ImdReader *poImdReader, const char *modelFilename ) override;
+    int      SaveClasses( const char *pszFile ) override;
 
-    std::list<OGRLayer *> GetLayers();
-    int      GetLayerCount();
+    std::list<OGRLayer *> GetLayers() override;
+    int      GetLayerCount() override;
     OGRLayer* GetLayer(const char* pszName);
 
     int      AddFeature(DOMElement *elem);
diff --git a/ogr/ogrsf_frmts/ili/imdreader.cpp b/ogr/ogrsf_frmts/ili/imdreader.cpp
index e8a3a99..a88f996 100644
--- a/ogr/ogrsf_frmts/ili/imdreader.cpp
+++ b/ogr/ogrsf_frmts/ili/imdreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  Interlis 1/2 Translator
  * Purpose:  IlisMeta model reader.
@@ -29,7 +28,6 @@
 
 // IlisMeta model: http://www.interlis.ch/models/core/IlisMeta07-20111222.ili
 
-
 #include "cpl_minixml.h"
 #include "imdreader.h"
 
@@ -37,8 +35,7 @@
 #include <vector>
 #include <algorithm>
 
-
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: imdreader.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 typedef std::map<CPLString,CPLXMLNode*> StrNodeMap;
 typedef std::vector<CPLXMLNode*> NodeVector;
@@ -194,7 +191,7 @@ public:
         // Delete default geometry field
         poTableDefn->DeleteGeomFieldDefn(0);
 
-        const char* psKind = CPLGetXMLValue( node, "Kind", NULL );
+        const char* psKind = CPLGetXMLValue( node, "Kind", "" );
 #ifdef DEBUG_VERBOSE
         CPLDebug( "OGR_ILI", "InitFieldDefinitions of '%s' kind: %s",
                   GetName(), psKind );
@@ -276,7 +273,7 @@ public:
                 }
                 else if (EQUAL(typeName, "IlisMeta07.ModelData.LineType"))
                 {
-                    const char* psKind = CPLGetXMLValue( psElementNode, "Kind", NULL );
+                    const char* psKind = CPLGetXMLValue( psElementNode, "Kind", "" );
                     poGeomFieldInfos[psName].iliGeomType = psKind;
                     bool isLinearType = (std::find(oArcLineTypes.begin(), oArcLineTypes.end(), psElementNode) == oArcLineTypes.end());
                     bool linearGeom = isLinearType || CPLTestBool(CPLGetConfigOption("OGR_STROKE_CURVE", "FALSE"));
@@ -334,20 +331,18 @@ public:
     }
 
   private:
-    CPL_DISALLOW_COPY_ASSIGN(IliClass);
+    CPL_DISALLOW_COPY_ASSIGN(IliClass)
 };
 
-
 ImdReader::ImdReader(int iliVersionIn) :
     iliVersion(iliVersionIn),
-    modelInfos()
-{
-    mainModelName = "OGR";
-    mainTopicName = "OGR";
-    codeBlank = '_';
-    codeUndefined = '@';
-    codeContinue = '\\';
-}
+    modelInfos(),  // TODO(schwehr): Remove.  No need for default ctor, correct?
+    mainModelName("OGR"),
+    mainTopicName("OGR"),
+    codeBlank('_'),
+    codeUndefined('@'),
+    codeContinue('\\')
+{}
 
 ImdReader::~ImdReader() {}
 
@@ -366,13 +361,12 @@ void ImdReader::ReadModel(const char *pszFilename) {
     ClassesMap oClasses;
     NodeCountMap oAxisCount;
     NodeVector oArcLineTypes;
-    const char *modelName;
 
     /* Fill TID lookup map and IliClasses lookup map */
     CPLXMLNode* psModel = psSectionNode->psChild;
     while( psModel != NULL )
     {
-        modelName = CPLGetXMLValue( psModel, "BID", NULL );
+        const char *modelName = CPLGetXMLValue( psModel, "BID", NULL );
 #ifdef DEBUG_VERBOSE
         CPLDebug( "OGR_ILI", "Model: '%s'", modelName);
 #endif
@@ -389,7 +383,6 @@ void ImdReader::ReadModel(const char *pszFilename) {
                 if( psTID != NULL )
                     oTidLookup[psTID] = psEntry;
 
-
                 if( EQUAL(psEntry->pszValue, "IlisMeta07.ModelData.Model") &&
                     !EQUAL(modelName, "MODEL.INTERLIS"))
                 {
@@ -502,7 +495,6 @@ void ImdReader::ReadModel(const char *pszFilename) {
                 }
             }
             psEntry = psEntry->psNext;
-
         }
 
         psModel = psModel->psNext;
diff --git a/ogr/ogrsf_frmts/ili/imdreader.h b/ogr/ogrsf_frmts/ili/imdreader.h
index 39ad7a2..b237d0e 100644
--- a/ogr/ogrsf_frmts/ili/imdreader.h
+++ b/ogr/ogrsf_frmts/ili/imdreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: imdreader.h 36411 2016-11-21 22:03:48Z rouault $
  *
  * Project:  Interlis 1/2 Translator
  * Purpose:  IlisMeta model reader.
@@ -36,7 +36,6 @@
 #include <list>
 #include <map>
 
-
 class GeomFieldInfo
 {
     OGRFeatureDefn* geomTable; /* separate geometry table for Ili 1 */
@@ -141,7 +140,7 @@ typedef std::list<IliModelInfo> IliModelInfos;
 
 class ImdReader
 {
-public:
+  public:  // TODO(schwehr): Private?
     int                  iliVersion; /* 1 or 2 */
     IliModelInfos        modelInfos;
     CPLString            mainModelName;
@@ -151,8 +150,8 @@ public:
     char                 codeBlank;
     char                 codeUndefined;
     char                 codeContinue;
-public:
-                         ImdReader(int iliVersion);
+  public:
+    explicit             ImdReader(int iliVersion);
                         ~ImdReader();
     void                 ReadModel(const char *pszFilename);
     FeatureDefnInfo      GetFeatureDefnInfo(const char *pszLayerName);
diff --git a/ogr/ogrsf_frmts/ili/makefile.vc b/ogr/ogrsf_frmts/ili/makefile.vc
index 9fa3eca..1f3ac01 100644
--- a/ogr/ogrsf_frmts/ili/makefile.vc
+++ b/ogr/ogrsf_frmts/ili/makefile.vc
@@ -8,7 +8,7 @@ GDAL_ROOT	=	..\..\..
 
 !INCLUDE $(GDAL_ROOT)\nmake.opt
 
-EXTRAFLAGS =	-I. -Iiom -I.. -I..\.. $(XERCES_INCLUDE) $(GEOS_CFLAGS)
+EXTRAFLAGS =	-I. -Iiom -I.. -I..\.. -DHAVE_XERCES $(XERCES_INCLUDE) $(GEOS_CFLAGS)
 
 default:	$(OBJ)
 
diff --git a/ogr/ogrsf_frmts/ili/ogr_ili1.h b/ogr/ogrsf_frmts/ili/ogr_ili1.h
index 940b770..71c110a 100644
--- a/ogr/ogrsf_frmts/ili/ogr_ili1.h
+++ b/ogr/ogrsf_frmts/ili/ogr_ili1.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ili1.h 36502 2016-11-25 14:21:53Z rouault $
+ * $Id: ogr_ili1.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Interlis 1 Translator
  * Purpose:   Definition of classes for OGR Interlis 1 driver.
@@ -33,8 +33,6 @@
 #include "ogrsf_frmts.h"
 #include "ili1reader.h"
 
-
-
 class OGRILI1DataSource;
 
 /************************************************************************/
@@ -60,30 +58,30 @@ private:
 
   public:
                         OGRILI1Layer( OGRFeatureDefn* poFeatureDefn,
-                                      GeomFieldInfos oGeomFieldInfos,
+                                      const GeomFieldInfos& oGeomFieldInfos,
                                       OGRILI1DataSource *poDS );
 
                        ~OGRILI1Layer();
 
     OGRErr              AddFeature(OGRFeature *poFeature);
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
     OGRFeature *        GetNextFeatureRef();
     OGRFeature *        GetFeatureRef( GIntBig nFid );
     OGRFeature *        GetFeatureRef( const char* );
 
-    GIntBig             GetFeatureCount( int bForce = TRUE );
+    GIntBig             GetFeatureCount( int bForce = TRUE ) override;
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
     int                 GeometryAppend( OGRGeometry *poGeometry );
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
     GeomFieldInfos      GetGeomFieldInfos() { return oGeomFieldInfos; }
 
-    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
+    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
   private:
     void                JoinGeomLayers();
@@ -109,24 +107,24 @@ class OGRILI1DataSource : public OGRDataSource
 
   public:
                 OGRILI1DataSource();
-               ~OGRILI1DataSource();
+               virtual ~OGRILI1DataSource();
 
     int         Open( const char *, char** papszOpenOptions, int bTestOpen );
     int         Create( const char *pszFile, char **papszOptions );
 
-    const char *GetName() { return pszName; }
-    int         GetLayerCount() { return poReader ? poReader->GetLayerCount() : 0; }
-    OGRLayer   *GetLayer( int );
-    OGRILI1Layer *GetLayerByName( const char* );
+    const char *GetName() override { return pszName; }
+    int         GetLayerCount() override { return poReader ? poReader->GetLayerCount() : 0; }
+    OGRLayer   *GetLayer( int ) override;
+    OGRILI1Layer *GetLayerByName( const char* ) override;
 
     FILE       *GetTransferFile() { return fpTransfer; }
 
     virtual OGRLayer *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+                                      char ** = NULL ) override;
 
-    int         TestCapability( const char * );
+    int         TestCapability( const char * ) override;
 };
 
 #endif /* OGR_ILI1_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ili/ogr_ili2.h b/ogr/ogrsf_frmts/ili/ogr_ili2.h
index 9ec063b..6abc12d 100644
--- a/ogr/ogrsf_frmts/ili/ogr_ili2.h
+++ b/ogr/ogrsf_frmts/ili/ogr_ili2.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ili2.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_ili2.h 37743 2017-03-17 13:14:00Z rouault $
  *
  * Project:  Interlis 2 Translator
  * Purpose:   Definition of classes for OGR Interlis 2 driver.
@@ -55,27 +55,27 @@ class OGRILI2Layer : public OGRLayer
 
   public:
                         OGRILI2Layer( OGRFeatureDefn* poFeatureDefn,
-                                      GeomFieldInfos oGeomFieldInfos,
+                                      const GeomFieldInfos& oGeomFieldInfos,
                                       OGRILI2DataSource *poDS );
 
                        ~OGRILI2Layer();
 
-    OGRErr              ISetFeature(OGRFeature *poFeature);
+    void                AddFeature(OGRFeature *poFeature);
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    GIntBig             GetFeatureCount( int bForce = TRUE );
+    GIntBig             GetFeatureCount( int bForce = TRUE ) override;
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
     CPLString           GetIliGeomType( const char* cFieldName) { return oGeomFieldInfos[cFieldName].iliGeomType; };
 
-    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
+    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -97,22 +97,22 @@ class OGRILI2DataSource : public OGRDataSource
 
   public:
                 OGRILI2DataSource();
-               ~OGRILI2DataSource();
+               virtual ~OGRILI2DataSource();
 
     int         Open( const char *, char** papszOpenOptions, int bTestOpen );
     int         Create( const char *pszFile, char **papszOptions );
 
-    const char *GetName() { return pszName; }
-    int         GetLayerCount() { return static_cast<int>(listLayer.size()); }
-    OGRLayer   *GetLayer( int );
+    const char *GetName() override { return pszName; }
+    int         GetLayerCount() override { return static_cast<int>(listLayer.size()); }
+    OGRLayer   *GetLayer( int ) override;
 
     virtual OGRLayer *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+                                      char ** = NULL ) override;
 
     VSILFILE *  GetOutputFP() { return fpOutput; }
-    int         TestCapability( const char * );
+    int         TestCapability( const char * ) override;
 };
 
 #endif /* OGR_ILI2_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp b/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
index 669fa84..5fd2fea 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1datasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrili1datasource.cpp 32746 2016-01-05 05:18:43Z goatbar $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1DataSource class.
@@ -36,7 +35,7 @@
 
 #include <string>
 
-CPL_CVSID("$Id: ogrili1datasource.cpp 32746 2016-01-05 05:18:43Z goatbar $");
+CPL_CVSID("$Id: ogrili1datasource.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                         OGRILI1DataSource()                         */
diff --git a/ogr/ogrsf_frmts/ili/ogrili1driver.cpp b/ogr/ogrsf_frmts/ili/ogrili1driver.cpp
index 689a20c..ec635b4 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1driver.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1driver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrili1driver.cpp 32746 2016-01-05 05:18:43Z goatbar $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1Layer class.
@@ -31,7 +30,7 @@
 #include "ogr_ili1.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrili1driver.cpp 32746 2016-01-05 05:18:43Z goatbar $");
+CPL_CVSID("$Id: ogrili1driver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
diff --git a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
index 13c79f6..fa79714 100644
--- a/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili1layer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrili1layer.cpp 36502 2016-11-25 14:21:53Z rouault $
  *
  * Project:  Interlis 1 Translator
  * Purpose:  Implements OGRILI1Layer class.
@@ -36,14 +35,14 @@
 #include <map>
 #include <vector>
 
-CPL_CVSID("$Id: ogrili1layer.cpp 36502 2016-11-25 14:21:53Z rouault $");
+CPL_CVSID("$Id: ogrili1layer.cpp 37472 2017-02-26 02:47:45Z goatbar $");
 
 /************************************************************************/
 /*                           OGRILI1Layer()                              */
 /************************************************************************/
 
 OGRILI1Layer::OGRILI1Layer( OGRFeatureDefn* poFeatureDefnIn,
-                            GeomFieldInfos oGeomFieldInfosIn,
+                            const GeomFieldInfos& oGeomFieldInfosIn,
                             OGRILI1DataSource *poDSIn ) :
     poFeatureDefn(poFeatureDefnIn),
     oGeomFieldInfos(oGeomFieldInfosIn),
@@ -73,7 +72,6 @@ OGRILI1Layer::~OGRILI1Layer()
         poFeatureDefn->Release();
 }
 
-
 OGRErr OGRILI1Layer::AddFeature (OGRFeature *poFeature)
 {
     nFeatures++;
@@ -101,13 +99,11 @@ void OGRILI1Layer::ResetReading()
 
 OGRFeature *OGRILI1Layer::GetNextFeature()
 {
-    OGRFeature *poFeature;
-
     if (!bGeomsJoined) JoinGeomLayers();
 
     while(nFeatureIdx < nFeatures)
     {
-        poFeature = GetNextFeatureRef();
+        OGRFeature *poFeature = GetNextFeatureRef();
         if (poFeature)
             return poFeature->Clone();
     }
@@ -136,9 +132,9 @@ OGRFeature *OGRILI1Layer::GetNextFeatureRef() {
 OGRFeature *OGRILI1Layer::GetFeatureRef( GIntBig nFID )
 
 {
-    OGRFeature *poFeature;
-
     ResetReading();
+
+    OGRFeature *poFeature = NULL;
     while( (poFeature = GetNextFeatureRef()) != NULL )
     {
         if( poFeature->GetFID() == nFID )
@@ -151,9 +147,9 @@ OGRFeature *OGRILI1Layer::GetFeatureRef( GIntBig nFID )
 OGRFeature *OGRILI1Layer::GetFeatureRef( const char *fid )
 
 {
-    OGRFeature *poFeature;
-
     ResetReading();
+
+    OGRFeature *poFeature = NULL;
     while( (poFeature = GetNextFeatureRef()) != NULL )
     {
         if( !strcmp( poFeature->GetFieldAsString(0), fid ) )
@@ -328,7 +324,6 @@ int OGRILI1Layer::GeometryAppend( OGRGeometry *poGeometry )
             if( !GeometryAppend( poMember ) )
                 return FALSE;
         }
-
     }
     else if( poGeometry->getGeometryType() == wkbCompoundCurve
              || poGeometry->getGeometryType() == wkbCompoundCurveZ )
@@ -394,7 +389,7 @@ OGRErr OGRILI1Layer::ICreateFeature( OGRFeature *poFeature ) {
     // Write all fields.
     for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
-        if ( poFeature->IsFieldSet( iField ) )
+        if ( poFeature->IsFieldSetAndNotNull( iField ) )
         {
           const char *pszRaw = poFeature->GetFieldAsString( iField );
           if (poFeatureDefn->GetFieldDefn( iField )->GetType() == OFTString) {
@@ -448,7 +443,6 @@ OGRErr OGRILI1Layer::CreateField( OGRFieldDefn *poField, int /* bApproxOK */ ) {
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                         Internal routines                            */
 /************************************************************************/
@@ -495,7 +489,6 @@ void OGRILI1Layer::JoinGeomLayers()
         CPLSetThreadLocalConfigOption("OGR_ARC_STEPSIZE", NULL);
 }
 
-
 void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer,
                                      int nSurfaceFieldIndex )
 {
@@ -511,7 +504,7 @@ void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer,
     // First map: for each target curvepolygon, find all belonging curves
     while (OGRFeature *linefeature = poSurfaceLineLayer->GetNextFeatureRef()) {
         //OBJE entries with same _RefTID are polygon rings of same feature
-        OGRFeature *feature;
+        OGRFeature *feature = NULL;
         if (poFeatureDefn->GetFieldDefn(0)->GetType() == OFTString)
         {
           feature = GetFeatureRef(linefeature->GetFieldAsString(1));
@@ -563,7 +556,7 @@ void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer,
 
             OGRPoint endPointCC;
             OGRCompoundCurve* poCC = new OGRCompoundCurve();
- 
+
             bool bFirst = true;
             while( true )
             {
@@ -727,7 +720,6 @@ void OGRILI1Layer::JoinSurfaceLayer( OGRILI1Layer* poSurfaceLineLayer,
     }
 
     ResetReading();
-    poSurfaceLineLayer = NULL;
 }
 
 OGRMultiPolygon* OGRILI1Layer::Polygonize( OGRGeometryCollection* poLines,
@@ -814,7 +806,6 @@ OGRMultiPolygon* OGRILI1Layer::Polygonize( OGRGeometryCollection* poLines,
 #endif
 }
 
-
 void OGRILI1Layer::PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer,
                                         int
 #if defined(HAVE_GEOS)
@@ -899,6 +890,5 @@ void OGRILI1Layer::PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer,
     CPLFree( ahInGeoms );
     OGRGeometry::freeGEOSContext( hGEOSCtxt );
 #endif
-    poAreaLineLayer = NULL;
     delete polys;
 }
diff --git a/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp b/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
index b35d6d5..6083e2c 100644
--- a/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili2datasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrili2datasource.cpp 32797 2016-01-07 19:49:33Z rouault $
  *
  * Project:  Interlis 2 Translator
  * Purpose:  Implements OGRILI2DataSource class.
@@ -37,8 +36,7 @@
 
 using namespace std;
 
-
-CPL_CVSID("$Id: ogrili2datasource.cpp 32797 2016-01-07 19:49:33Z rouault $");
+CPL_CVSID("$Id: ogrili2datasource.cpp 37745 2017-03-17 13:43:46Z rouault $");
 
 /************************************************************************/
 /*                         OGRILI2DataSource()                         */
@@ -163,7 +161,7 @@ int OGRILI2DataSource::Open( const char * pszNewName,
         return FALSE;
     }
 
-    if (osModelFilename.size())
+    if (!osModelFilename.empty() )
         poReader->ReadModel( poImdReader, osModelFilename );
 
     poReader->SetSourceFile( pszName );
@@ -179,7 +177,6 @@ int OGRILI2DataSource::Open( const char * pszNewName,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
@@ -194,9 +191,8 @@ int OGRILI2DataSource::Create( const char *pszFilename,
 
     if( pszModelFilename == NULL )
     {
-        CPLError( CE_Warning, CPLE_OpenFailed,
-                  "Model file '%s' (%s) not found : %s.",
-                  pszModelFilename, pszFilename, VSIStrerror( errno ) );
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "Model file not specified." );
         CSLDestroy(filenames);
         return FALSE;
     }
@@ -232,7 +228,6 @@ int OGRILI2DataSource::Create( const char *pszFilename,
         return FALSE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Parse model                                                     */
 /* -------------------------------------------------------------------- */
@@ -326,11 +321,11 @@ OGRLayer *OGRILI2DataSource::GetLayer( int iLayer )
     list<OGRLayer *>::const_iterator layerIt = listLayer.begin();
     int i = 0;
     while (i < iLayer && layerIt != listLayer.end()) {
-        i++;
-        layerIt++;
+        ++i;
+        ++layerIt;
     }
 
-    if (i == iLayer) {
+    if (i == iLayer && layerIt != listLayer.end()) {
         OGRILI2Layer *tmpLayer = reinterpret_cast<OGRILI2Layer *>(*layerIt);
         return tmpLayer;
     }
diff --git a/ogr/ogrsf_frmts/ili/ogrili2driver.cpp b/ogr/ogrsf_frmts/ili/ogrili2driver.cpp
index 76fb7a0..4725e99 100644
--- a/ogr/ogrsf_frmts/ili/ogrili2driver.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili2driver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrili2driver.cpp 33109 2016-01-23 16:25:42Z rouault $
  *
  * Project:  Interlis 2 Translator
  * Purpose:  Implements OGRILI2Layer class.
@@ -33,8 +32,7 @@
 #include "ogr_ili2.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrili2driver.cpp 33109 2016-01-23 16:25:42Z rouault $");
-
+CPL_CVSID("$Id: ogrili2driver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -94,16 +92,6 @@ static GDALDataset *OGRILI2DriverCreate( const char * pszName,
 }
 
 /************************************************************************/
-/*                         OGRILI2DriverUnload()                        */
-/************************************************************************/
-
-static void OGRILI2DriverUnload ( GDALDriver* )
-{
-    if( getenv("ILI2_TERMINATE_XERCES") )
-        XMLPlatformUtils::Terminate();
-}
-
-/************************************************************************/
 /*                           RegisterOGRILI2()                           */
 /************************************************************************/
 
@@ -125,7 +113,6 @@ void RegisterOGRILI2() {
 
     poDriver->pfnOpen = OGRILI2DriverOpen;
     poDriver->pfnCreate = OGRILI2DriverCreate;
-    poDriver->pfnUnloadDriver = OGRILI2DriverUnload;
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/ili/ogrili2layer.cpp b/ogr/ogrsf_frmts/ili/ogrili2layer.cpp
index 91194ba..9edd360 100644
--- a/ogr/ogrsf_frmts/ili/ogrili2layer.cpp
+++ b/ogr/ogrsf_frmts/ili/ogrili2layer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrili2layer.cpp 32765 2016-01-05 19:27:15Z rouault $
  *
  * Project:  Interlis 2 Translator
  * Purpose:  Implements OGRILI2Layer class.
@@ -32,14 +31,14 @@
 #include "cpl_string.h"
 #include "ogr_ili2.h"
 
-CPL_CVSID("$Id: ogrili2layer.cpp 32765 2016-01-05 19:27:15Z rouault $");
+CPL_CVSID("$Id: ogrili2layer.cpp 37743 2017-03-17 13:14:00Z rouault $");
 
 /************************************************************************/
 /*                           OGRILI2Layer()                              */
 /************************************************************************/
 
 OGRILI2Layer::OGRILI2Layer( OGRFeatureDefn* poFeatureDefnIn,
-                            GeomFieldInfos oGeomFieldInfosIn,
+                            const GeomFieldInfos& oGeomFieldInfosIn,
                             OGRILI2DataSource *poDSIn ) :
     poFeatureDefn(poFeatureDefnIn),
     oGeomFieldInfos(oGeomFieldInfosIn),
@@ -68,15 +67,14 @@ OGRILI2Layer::~OGRILI2Layer()
     }
 }
 
-
 /************************************************************************/
-/*                             ISetFeature()                             */
+/*                             AddFeature()                             */
 /************************************************************************/
 
-OGRErr OGRILI2Layer::ISetFeature (OGRFeature *poFeature)
+void OGRILI2Layer::AddFeature (OGRFeature *poFeature)
 {
+    poFeature->SetFID( static_cast<GIntBig>(1 + listFeature.size()) );
     listFeature.push_back(poFeature);
-    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -263,7 +261,6 @@ static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, VSILFILE* fp,
             if( !OGR2ILIGeometryAppend( poMember, fp, NULL, "" ) )
                 return FALSE;
         }
-
     }
 
     else
@@ -278,7 +275,7 @@ static int OGR2ILIGeometryAppend( OGRGeometry *poGeometry, VSILFILE* fp,
 
 OGRErr OGRILI2Layer::ICreateFeature( OGRFeature *poFeature ) {
     char szTempBuffer[80];
-    const char* tid;
+    const char* tid = NULL;
     int iField = 0;
     if( poFeatureDefn->GetFieldCount() &&
         EQUAL(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), "TID") )
@@ -321,7 +318,7 @@ OGRErr OGRILI2Layer::ICreateFeature( OGRFeature *poFeature ) {
 
         OGRFieldDefn *poField = poFeatureDefn->GetFieldDefn( iField );
 
-        if( poFeature->IsFieldSet( iField ) )
+        if( poFeature->IsFieldSetAndNotNull( iField ) )
         {
             const char *pszRaw = poFeature->GetFieldAsString( iField );
             VSIFPrintfL(fp, "<%s>%s</%s>\n", poField->GetNameRef(), pszRaw, poField->GetNameRef());
diff --git a/ogr/ogrsf_frmts/ingres/ogr_ingres.h b/ogr/ogrsf_frmts/ingres/ogr_ingres.h
index 554ecc0..a416a78 100644
--- a/ogr/ogrsf_frmts/ingres/ogr_ingres.h
+++ b/ogr/ogrsf_frmts/ingres/ogr_ingres.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ingres.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_ingres.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Declarations for Ingres OGR Driver Classes.
@@ -46,9 +46,9 @@ public:
     II_PTR            hStmt;
     II_PTR            hTransaction;
 
-    IIAPI_GETDESCRPARM	getDescrParm;
-    IIAPI_GETCOLPARM	getColParm;
-    IIAPI_DATAVALUE	*pasDataBuffer;
+    IIAPI_GETDESCRPARM  getDescrParm;
+    IIAPI_GETCOLPARM    getColParm;
+    IIAPI_DATAVALUE     *pasDataBuffer;
     IIAPI_GETQINFOPARM  queryInfo;
 
     GByte             *pabyWrkBuffer;
@@ -61,7 +61,7 @@ public:
     int               nParmLen;
     GByte            *pabyParmData;
 
-    OGRIngresStatement( II_PTR hConn );
+    explicit OGRIngresStatement( II_PTR hConn );
     ~OGRIngresStatement();
 
     void addInputParameter( IIAPI_DT_ID eDType, int nLength, GByte *pabyData );
@@ -113,20 +113,20 @@ class OGRIngresLayer : public OGRLayer
                         OGRIngresLayer();
     virtual             ~OGRIngresLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
 
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 
     /* custom methods */
     virtual OGRFeature *RecordToFeature( char **papszRow );
@@ -143,9 +143,9 @@ class OGRIngresTableLayer : public OGRIngresLayer
 
     OGRFeatureDefn     *ReadTableDefinition(const char *);
 
-    void                BuildWhere(void);
-    char               *BuildFields(void);
-    void                BuildFullQueryStatement(void);
+    void                BuildWhere();
+    char               *BuildFields();
+    void                BuildFullQueryStatement();
 
     CPLString           osQuery;
     CPLString           osWHERE;
@@ -160,33 +160,33 @@ class OGRIngresTableLayer : public OGRIngresLayer
                         OGRIngresTableLayer( OGRIngresDataSource *,
                                          const char * pszName,
                                          int bUpdate, int nSRSId = -2 );
-                        ~OGRIngresTableLayer();
+                        virtual ~OGRIngresTableLayer();
 
     OGRErr              Initialize(const char* pszTableName);
 
 //    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
 //    virtual GIntBig     GetFeatureCount( int );
 
-    void                SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    void                SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
     void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
     void                SetPrecisionFlag( int bFlag )
                                 { bPreservePrecision = bFlag; }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -195,13 +195,10 @@ class OGRIngresTableLayer : public OGRIngresLayer
 
 class OGRIngresResultLayer : public OGRIngresLayer
 {
-    void                BuildFullQueryStatement(void);
+    void                BuildFullQueryStatement();
 
     char                *pszRawStatement;
 
-    // Layer srid.
-    int                 nSRSId;
-
     int                 nFeatureCount;
 
   public:
@@ -212,9 +209,8 @@ class OGRIngresResultLayer : public OGRIngresLayer
 
     OGRFeatureDefn     *ReadResultDefinition();
 
-
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 };
 
 /************************************************************************/
@@ -232,7 +228,7 @@ class OGRIngresDataSource : public OGRDataSource
 
     II_PTR              hConn;
 
-    int                 DeleteLayer( int iLayer );
+    int                 DeleteLayer( int iLayer ) override;
 
     // We maintain a list of known SRID to reduce the number of trips to
     // the database to get SRSes.
@@ -242,48 +238,46 @@ class OGRIngresDataSource : public OGRDataSource
 
     OGRIngresLayer     *poActiveLayer; /* this layer has active transaction */
 
-    int					bNewIngres; /* TRUE if new spatial library */
+    int                 bNewIngres; /* TRUE if new spatial library */
 
   public:
                         OGRIngresDataSource();
-                        ~OGRIngresDataSource();
+                        virtual ~OGRIngresDataSource();
 
     II_PTR              GetConn() { return hConn; }
 
-
     int                 FetchSRSId( OGRSpatialReference * poSRS );
 
     OGRSpatialReference *FetchSRS( int nSRSId );
 
-    OGRErr              InitializeMetadataTables();
+    static OGRErr              InitializeMetadataTables();
 
     int                 Open( const char *pszFullName,
                               char **papszOptions, int bUpdate );
     int                 OpenTable( const char *, int bUpdate );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
     virtual OGRLayer    *ICreateLayer( const char *,
                                        OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
-
+                                      char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     // nonstandard
 
     char               *LaunderName( const char * );
 
     void                EstablishActiveLayer( OGRIngresLayer * );
-    int					IsNewIngres();
+    int                 IsNewIngres();
 };
 
 /************************************************************************/
@@ -295,14 +289,13 @@ class OGRIngresDriver : public OGRSFDriver
     char         **ParseWrappedName( const char * );
 
   public:
-                ~OGRIngresDriver();
+    virtual ~OGRIngresDriver();
 
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
     virtual OGRDataSource *CreateDataSource( const char *pszName,
-                                             char ** = NULL );
-    int                 TestCapability( const char * );
+                                             char ** = NULL ) override;
+    int                 TestCapability( const char * ) override;
 };
 
-
 #endif /* ndef OGR_PG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp b/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp
index 8a06c7b..30e6491 100644
--- a/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringresdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogringresdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresDataSource class.
@@ -27,13 +26,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
 #include "ogr_ingres.h"
 
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogringresdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogringresdatasource.cpp 36456 2016-11-22 23:34:00Z rouault $");
 
 /************************************************************************/
 /*                            SetConnParam()                            */
@@ -45,8 +43,8 @@ SetConnParam(II_PTR *connHandle,
              II_LONG paramID,
              const II_PTR paramValue)
 {
-    IIAPI_SETCONPRMPARM	setconnParm;
-    IIAPI_WAITPARM	waitParm = { -1 };
+    IIAPI_SETCONPRMPARM setconnParm;
+    IIAPI_WAITPARM      waitParm = { -1 };
 
     setconnParm.sc_genParm.gp_callback = NULL;
     setconnParm.sc_genParm.gp_closure = NULL;
@@ -71,7 +69,7 @@ SetConnParam(II_PTR *connHandle,
         *connHandle = setconnParm.sc_connHandle;
     }
 
-    return (setconnParm.sc_genParm.gp_status);
+    return setconnParm.sc_genParm.gp_status;
 }
 
 /************************************************************************/
@@ -90,6 +88,8 @@ OGRIngresDataSource::OGRIngresDataSource()
     panSRID = NULL;
     papoSRS = NULL;
     poActiveLayer = NULL;
+    bDSUpdate = FALSE;
+    bNewIngres = FALSE;
 }
 
 /************************************************************************/
@@ -129,7 +129,6 @@ OGRIngresDataSource::~OGRIngresDataSource()
 int OGRIngresDataSource::Open( const char *pszFullName,
                                char **papszOptions, int bUpdate )
 
-
 {
     CPLAssert( nLayers == 0 );
 
@@ -239,9 +238,9 @@ int OGRIngresDataSource::Open( const char *pszFullName,
         && strlen(pszDBpwd) > 0 )
     {
         if (SetConnParam(&hConn, IIAPI_CP_EFFECTIVE_USER,
-			(II_PTR)pszEffuser) != IIAPI_ST_SUCCESS
+                        (II_PTR)pszEffuser) != IIAPI_ST_SUCCESS
             || SetConnParam(&hConn, IIAPI_CP_DBMS_PASSWORD,
-			(II_PTR)pszDBpwd) != IIAPI_ST_SUCCESS )
+                        (II_PTR)pszDBpwd) != IIAPI_ST_SUCCESS )
         {
             return FALSE;
         }
@@ -250,8 +249,8 @@ int OGRIngresDataSource::Open( const char *pszFullName,
 /* -------------------------------------------------------------------- */
 /*      Try to connect to the database.                                 */
 /* -------------------------------------------------------------------- */
-    IIAPI_CONNPARM	connParm;
-    IIAPI_WAITPARM	waitParm = { -1 };
+    IIAPI_CONNPARM connParm;
+    IIAPI_WAITPARM waitParm = { -1 };
 
     memset( &connParm, 0, sizeof(connParm) );
     connParm.co_genParm.gp_callback = NULL;
@@ -271,7 +270,7 @@ int OGRIngresDataSource::Open( const char *pszFullName,
     IIapi_connect( &connParm );
 
     while( connParm.co_genParm.gp_completed == FALSE )
-	IIapi_wait( &waitParm );
+        IIapi_wait( &waitParm );
 
     hConn = connParm.co_connHandle;
 
@@ -289,24 +288,24 @@ int OGRIngresDataSource::Open( const char *pszFullName,
 
     // Check for new or old Ingres spatial library
     {
-    	OGRIngresStatement oStmt( hConn );
-
-    	if( oStmt.ExecuteSQL("SELECT COUNT(*) FROM iicolumns WHERE table_name = 'iiattribute' AND column_name = 'attgeomtype'" ) )
-    	{
-    		char **papszFields;
-    		while( (papszFields = oStmt.GetRow()) )
-    		{
-    			CPLString osCount = papszFields[0];
-    			if( osCount[0] == '0' )
-    			{
-    				bNewIngres = FALSE;
-    			}
-    			else
-    			{
-    				bNewIngres = TRUE;
-    			}
-    		}
-    	}
+        OGRIngresStatement oStmt( hConn );
+
+        if( oStmt.ExecuteSQL("SELECT COUNT(*) FROM iicolumns WHERE table_name = 'iiattribute' AND column_name = 'attgeomtype'" ) )
+        {
+            char **papszFields;
+            while( (papszFields = oStmt.GetRow()) )
+            {
+                CPLString osCount = papszFields[0];
+                if( osCount[0] == '0' )
+                {
+                    bNewIngres = FALSE;
+                }
+                else
+                {
+                    bNewIngres = TRUE;
+                }
+            }
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -318,7 +317,7 @@ int OGRIngresDataSource::Open( const char *pszFullName,
 
         if( oStmt.ExecuteSQL( "select table_name from iitables where system_use = 'U' and table_name not like 'iietab_%'" ) )
         {
-            char **papszFields;
+            char **papszFields = NULL;
             while( (papszFields = oStmt.GetRow()) )
             {
                 CPLString osTableName = papszFields[0];
@@ -356,11 +355,8 @@ int OGRIngresDataSource::OpenTable( const char *pszNewName, int bUpdate )
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRIngresTableLayer  *poLayer;
-    OGRErr eErr;
-
-    poLayer = new OGRIngresTableLayer( this, pszNewName, bUpdate );
-    eErr = poLayer->Initialize(pszNewName);
+    OGRIngresTableLayer  *poLayer = new OGRIngresTableLayer( this, pszNewName, bUpdate );
+    OGRErr eErr = poLayer->Initialize(pszNewName);
     if (eErr == OGRERR_FAILURE)
         return FALSE;
 
@@ -402,7 +398,6 @@ OGRLayer *OGRIngresDataSource::GetLayer( int iLayer )
         return papoLayers[iLayer];
 }
 
-
 /************************************************************************/
 /*                      InitializeMetadataTables()                      */
 /*                                                                      */
@@ -415,9 +410,8 @@ OGRErr OGRIngresDataSource::InitializeMetadataTables()
 
 {
 #ifdef notdef
-    char            szCommand[1024];
-    INGRES_RES       *hResult;
-    OGRErr	    eErr = OGRERR_NONE;
+    char   szCommand[1024];
+    OGRErr eErr = OGRERR_NONE;
 
     sprintf( szCommand, "DESCRIBE geometry_columns" );
     if( ingres_query(GetConn(), szCommand ) )
@@ -441,7 +435,7 @@ OGRErr OGRIngresDataSource::InitializeMetadataTables()
     }
 
     // make sure to attempt to free results of successful queries
-    hResult = ingres_store_result( GetConn() );
+    INGRES_RES *hResult = ingres_store_result( GetConn() );
     if( hResult != NULL )
     {
         ingres_free_result( hResult );
@@ -489,8 +483,6 @@ OGRErr OGRIngresDataSource::InitializeMetadataTables()
 
 OGRSpatialReference *OGRIngresDataSource::FetchSRS( int nId )
 {
-    char         szCommand[1024];
-    char           **papszRow;
     OGRIngresStatement oStatement(GetConn());
 
     if( nId < 0 )
@@ -505,9 +497,7 @@ OGRSpatialReference *OGRIngresDataSource::FetchSRS( int nId )
 /* -------------------------------------------------------------------- */
 /*      First, we look through our SRID cache, is it there?             */
 /* -------------------------------------------------------------------- */
-    int  i;
-
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( panSRID[i] == nId )
             return papoSRS[i];
@@ -515,17 +505,16 @@ OGRSpatialReference *OGRIngresDataSource::FetchSRS( int nId )
 
     OGRSpatialReference *poSRS = NULL;
 
+    char szCommand[1024] = {};
     sprintf( szCommand,
-         "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
-         nId );
+             "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
+             nId );
 
     oStatement.ExecuteSQL(szCommand);
 
-    char    *pszWKT = NULL;
-    papszRow = NULL;
-
+    char *pszWKT = NULL;
 
-    papszRow = oStatement.GetRow();
+    char **papszRow = oStatement.GetRow();
 
     if( papszRow != NULL)
     {
@@ -555,8 +544,6 @@ OGRSpatialReference *OGRIngresDataSource::FetchSRS( int nId )
     return poSRS;
 }
 
-
-
 /************************************************************************/
 /*                             FetchSRSId()                             */
 /*                                                                      */
@@ -567,22 +554,20 @@ OGRSpatialReference *OGRIngresDataSource::FetchSRS( int nId )
 int OGRIngresDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
 {
-    char            **papszRow;
-    char            szCommand[10000];
-    char            *pszWKT = NULL;
-    char            *pszProj4 = NULL;
-    const char      *pszAuthName;
-    const char      *pszAuthID;
-    int             nSRSId;
-
     if( poSRS == NULL )
         return -1;
 
+    char **papszRow = NULL;
+    char szCommand[10000] = {};
+    char *pszWKT = NULL;
+    char *pszProj4 = NULL;
+    int nSRSId = 0;
+
     /* -------------------------------------------------------------------- */
-    /*  If it is a EPSG	Spatial Reference, search with special type			*/
+    /*  If it is a EPSG Spatial Reference, search with special type.        */
     /* -------------------------------------------------------------------- */
-    pszAuthName = poSRS->GetAuthorityName(NULL);
-    pszAuthID = poSRS->GetAuthorityCode(NULL);
+    const char *pszAuthName = poSRS->GetAuthorityName(NULL);
+    const char *pszAuthID = poSRS->GetAuthorityCode(NULL);
 
     if (pszAuthName && pszAuthID && EQUAL(pszAuthName, "EPSG"))
     {
@@ -590,7 +575,6 @@ int OGRIngresDataSource::FetchSRSId( OGRSpatialReference * poSRS )
              "SELECT srid FROM spatial_ref_sys WHERE auth_name = 'EPSG' and auth_srid= %s",
              pszAuthID );
 
-
         OGRIngresStatement  oStateSRID(GetConn());
         oStateSRID.ExecuteSQL(szCommand);
 
@@ -670,7 +654,6 @@ int OGRIngresDataSource::FetchSRSId( OGRSpatialReference * poSRS )
             {
                 nSRSId = *((II_INT4 *)papszRow[0]) + 1;
             }
-
         }
         else
             nSRSId = USER_DEFINED_SR_START+1;
@@ -727,8 +710,8 @@ int OGRIngresDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /************************************************************************/
 
 OGRLayer * OGRIngresDataSource::ExecuteSQL( const char *pszSQLCommand,
-                                        OGRGeometry *poSpatialFilter,
-                                        const char *pszDialect )
+                                            OGRGeometry *poSpatialFilter,
+                                            const char *pszDialect )
 
 {
 /* -------------------------------------------------------------------- */
@@ -830,8 +813,8 @@ int OGRIngresDataSource::DeleteLayer( int iLayer)
 /* -------------------------------------------------------------------- */
 /*      Remove from the database.                                       */
 /* -------------------------------------------------------------------- */
-    char        	szCommand[1024];
-    OGRIngresStatement  oStmt( hConn );
+    char               szCommand[1024];
+    OGRIngresStatement oStmt( hConn );
 
     sprintf( szCommand,
              "DROP TABLE %s ",
@@ -846,34 +829,27 @@ int OGRIngresDataSource::DeleteLayer( int iLayer)
         return OGRERR_FAILURE;
 }
 
-
-
 /************************************************************************/
 /*                           ICreateLayer()                             */
 /************************************************************************/
 
 OGRLayer *
 OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
-                              OGRSpatialReference *poSRS,
-                              OGRwkbGeometryType eType,
-                              char ** papszOptions )
+                                   OGRSpatialReference *poSRS,
+                                   OGRwkbGeometryType eType,
+                                   char ** papszOptions )
 
 {
-    const char          *pszGeometryType = NULL;
-    const char		*pszGeomColumnName;
-    const char 		*pszExpectedFIDName;
+    //int                 nDimension = 3; // Ingres only supports 2d currently
 
-    char                *pszLayerName;
-    int                 nDimension = 3; // Ingres only supports 2d currently
-
-
-    if( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) )
+    char *pszLayerName = NULL;
+    if( CPLFetchBool(papszOptions, "LAUNDER", true) )
         pszLayerName = LaunderName( pszLayerNameIn );
     else
         pszLayerName = CPLStrdup( pszLayerNameIn );
 
-    if( wkbFlatten(eType) == eType )
-        nDimension = 2;
+    //if( wkbFlatten(eType) == eType )
+    //    nDimension = 2;
 
     CPLDebug("INGRES","Creating layer %s.", pszLayerName);
 
@@ -909,11 +885,13 @@ OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
 /* -------------------------------------------------------------------- */
 /*      What do we want to use for geometry and FID columns?            */
 /* -------------------------------------------------------------------- */
-    pszGeomColumnName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" );
+    const char *pszGeomColumnName =
+        CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" );
     if (!pszGeomColumnName)
-        pszGeomColumnName="SHAPE";
+        pszGeomColumnName = "SHAPE";
 
-    pszExpectedFIDName = CSLFetchNameValue( papszOptions, "INGRES_FID" );
+    const char *pszExpectedFIDName =
+        CSLFetchNameValue( papszOptions, "INGRES_FID" );
     if (!pszExpectedFIDName)
         pszExpectedFIDName="OGR_FID";
 
@@ -923,65 +901,68 @@ OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
 /* -------------------------------------------------------------------- */
 /*      What sort of geometry column do we want to create?              */
 /* -------------------------------------------------------------------- */
-    pszGeometryType = CSLFetchNameValue( papszOptions, "GEOMETRY_TYPE" );
+    const char *pszGeometryType =
+        CSLFetchNameValue( papszOptions, "GEOMETRY_TYPE" );
 
     if( pszGeometryType != NULL )
+    {
         /* user selected type */;
-
+    }
     else if( wkbFlatten(eType) == wkbPoint )
+    {
         pszGeometryType = "POINT";
-
+    }
     else if( wkbFlatten(eType) == wkbLineString)
     {
-    	if( IsNewIngres() )
-    	{
+        if( IsNewIngres() )
+        {
             pszGeometryType = "LINESTRING";
-    	}
-    	else
-    	{
+        }
+        else
+        {
             pszGeometryType = "LONG LINE";
-    	}
+        }
     }
 
     else if( wkbFlatten(eType) == wkbPolygon )
     {
-    	if( IsNewIngres() )
-    	{
+        if( IsNewIngres() )
+        {
             pszGeometryType = "POLYGON";
-    	}
-    	else
-    	{
+        }
+        else
+        {
             pszGeometryType = "LONG POLYGON";
-    	}
+        }
     }
 
     else if( wkbFlatten(eType) == wkbMultiPolygon )
     {
-    	if( IsNewIngres() )
+        if( IsNewIngres() )
             pszGeometryType = "MULTIPOLYGON";
     }
 
     else if( wkbFlatten(eType) == wkbMultiLineString )
     {
-    	if( IsNewIngres() )
+        if( IsNewIngres() )
             pszGeometryType = "MULTILINESTRING";
     }
 
     else if( wkbFlatten(eType) == wkbMultiPoint )
     {
-    	if( IsNewIngres() )
+        if( IsNewIngres() )
             pszGeometryType = "MULTIPOINT";
     }
 
     else if( wkbFlatten(eType) == wkbGeometryCollection )
     {
-    	if( IsNewIngres() )
+        if( IsNewIngres() )
             pszGeometryType = "GEOMETRYCOLLECTION";
     }
 
     else if( wkbFlatten(eType) == wkbUnknown )
     {
-    	if( IsNewIngres() )
+        if( IsNewIngres() )
             // this is also used as the generic geometry type.
             pszGeometryType = "GEOMETRYCOLLECTION";
     }
@@ -1046,19 +1027,17 @@ OGRIngresDataSource::ICreateLayer( const char * pszLayerNameIn,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRIngresTableLayer     *poLayer;
-    OGRErr                  eErr;
-
-    poLayer = new OGRIngresTableLayer( this, pszLayerName, TRUE, nSRSId );
-    eErr = poLayer->Initialize(pszLayerName);
+    OGRIngresTableLayer *poLayer =
+        new OGRIngresTableLayer( this, pszLayerName, TRUE, nSRSId );
+    OGRErr eErr = poLayer->Initialize(pszLayerName);
     if (eErr == OGRERR_FAILURE)
     {
         delete poLayer;
         return NULL;
     }
 
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
-    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
+    poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", true) );
+    poLayer->SetPrecisionFlag( CPLFetchBool(papszOptions, "PRECISION", true));
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
@@ -1092,5 +1071,5 @@ void OGRIngresDataSource::EstablishActiveLayer( OGRIngresLayer *poNewLayer )
 
 int OGRIngresDataSource::IsNewIngres()
 {
-	return bNewIngres;
+    return bNewIngres;
 }
diff --git a/ogr/ogrsf_frmts/ingres/ogringresdriver.cpp b/ogr/ogrsf_frmts/ingres/ogringresdriver.cpp
index 7515b09..edbc512 100644
--- a/ogr/ogrsf_frmts/ingres/ogringresdriver.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringresdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogringresdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresDriver class.
@@ -30,7 +29,7 @@
 #include "ogr_ingres.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogringresdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogringresdriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                          ~OGRIngresDriver()                           */
@@ -72,11 +71,9 @@ OGRDataSource *OGRIngresDriver::Open( const char * pszFilename,
                                      int bUpdate )
 
 {
-    OGRIngresDataSource     *poDS = NULL;
+    OGRIngresDataSource *poDS = NULL;
     char **papszOptions = ParseWrappedName( pszFilename );
-    const char *pszDriver;
-
-    pszDriver = CSLFetchNameValue( papszOptions, "driver" );
+    const char *pszDriver = CSLFetchNameValue( papszOptions, "driver" );
     if( pszDriver != NULL && EQUAL(pszDriver,"ingres") )
     {
         poDS = new OGRIngresDataSource();
@@ -93,7 +90,6 @@ OGRDataSource *OGRIngresDriver::Open( const char * pszFilename,
     return poDS;
 }
 
-
 /************************************************************************/
 /*                          CreateDataSource()                          */
 /************************************************************************/
@@ -102,13 +98,11 @@ OGRDataSource *OGRIngresDriver::CreateDataSource( const char * pszName,
                                                   char ** /* papszOptions */ )
 
 {
-    OGRIngresDataSource     *poDS = NULL;
-    char **papszOpenOptions;
-    const char *pszDriver;
+    OGRIngresDataSource *poDS = NULL;
 
-    papszOpenOptions = ParseWrappedName( pszName );
+    char **papszOpenOptions = ParseWrappedName( pszName );
 
-    pszDriver = CSLFetchNameValue( papszOpenOptions, "driver" );
+    const char *pszDriver = CSLFetchNameValue( papszOpenOptions, "driver" );
 
     if( pszDriver != NULL && EQUAL(pszDriver,"ingres") )
     {
@@ -128,7 +122,6 @@ OGRDataSource *OGRIngresDriver::CreateDataSource( const char * pszName,
     return poDS;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/ingres/ogringreslayer.cpp b/ogr/ogrsf_frmts/ingres/ogringreslayer.cpp
index d03b0d5..9c61ae3 100644
--- a/ogr/ogrsf_frmts/ingres/ogringreslayer.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringreslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogringreslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresLayer class.
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogringreslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogringreslayer.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                           OGRIngresLayer()                            */
@@ -101,9 +100,7 @@ OGRFeature *OGRIngresLayer::GetNextFeature()
 {
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -121,16 +118,16 @@ OGRFeature *OGRIngresLayer::GetNextFeature()
 /*                              ParseXY()                               */
 /************************************************************************/
 
-static int ParseXY( const char **ppszNext, double *padfXY )
+static bool ParseXY( const char **ppszNext, double *padfXY )
 
 {
-    int iStartY;
     const char *pszNext = *ppszNext;
 
-    for( iStartY = 0; ; iStartY++ )
+    int iStartY = 0;  // Used after for.
+    for( ; ; iStartY++ )
     {
         if( pszNext[iStartY] == '\0' )
-            return FALSE;
+            return false;
 
         if( pszNext[iStartY] == ',' )
         {
@@ -142,19 +139,16 @@ static int ParseXY( const char **ppszNext, double *padfXY )
     padfXY[0] = CPLAtof(pszNext);
     padfXY[1] = CPLAtof(pszNext + iStartY);
 
-    int iEnd;
-
-    for( iEnd = iStartY;
-         pszNext[iEnd] != ')';
-         iEnd++ )
+    int iEnd = iStartY;  // Used after for.
+    for( ; pszNext[iEnd] != ')'; iEnd++ )
     {
         if( pszNext[iEnd] == '\0' )
-            return FALSE;
+            return false;
     }
 
     *ppszNext += iEnd;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -175,8 +169,9 @@ OGRGeometry *OGRIngresLayer::TranslateGeometry( const char *pszGeom )
 /*      spaces may occur between tokens.                                */
 /* -------------------------------------------------------------------- */
     double *padfXY = NULL;
-    int    nVertMax = 0, nVertCount = 0;
-    int    nDepth = 0;
+    int nVertMax = 0;
+    int nVertCount = 0;
+    int nDepth = 0;
     const char *pszNext = pszGeom;
 
     while( *pszNext != '\0' )
@@ -374,25 +369,24 @@ OGRFeature *OGRIngresLayer::RecordToFeature( char **papszRow )
         if( osGeomColumn.size()
             && EQUAL(psFDesc->ds_columnName,osGeomColumn))
         {
-        	if( poDS->IsNewIngres() )
-        	{
-        		OGRGeometry *poGeometry = NULL;
-        		unsigned char *pszWKB = (unsigned char *) papszRow[iField];
-
-//        		OGRGeometryFactory::createFromWkt(&pszWKT, NULL, &poGeometry);
-        		OGRGeometryFactory::createFromWkb(pszWKB, NULL, &poGeometry, -1);
-
-        		poFeature->SetGeometryDirectly(poGeometry);
-        	}
-        	else
-        	{
-        		poFeature->SetGeometryDirectly(
-        			TranslateGeometry( papszRow[iField] ) );
-        	}
+            if( poDS->IsNewIngres() )
+            {
+                OGRGeometry *poGeometry = NULL;
+                unsigned char *pszWKB = (unsigned char *) papszRow[iField];
+
+                // GRGeometryFactory::createFromWkt(&pszWKT, NULL, &poGeometry);
+                OGRGeometryFactory::createFromWkb(pszWKB, NULL, &poGeometry, -1);
+
+                poFeature->SetGeometryDirectly(poGeometry);
+            }
+            else
+            {
+                poFeature->SetGeometryDirectly(
+                    TranslateGeometry( papszRow[iField] ) );
+            }
             continue;
         }
 
-
 /* -------------------------------------------------------------------- */
 /*      Transfer regular data fields.                                   */
 /* -------------------------------------------------------------------- */
@@ -500,7 +494,7 @@ OGRFeature *OGRIngresLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
     if( iNextShapeId == 0 && poResultSet == NULL )
     {
-        CPLAssert( osQueryStatement.size() != 0 );
+        CPLAssert( !osQueryStatement.empty() );
 
         poDS->EstablishActiveLayer( this );
 
@@ -549,25 +543,27 @@ OGRFeature *OGRIngresLayer::GetFeature( GIntBig nFeatureId )
 int OGRIngresLayer::TestCapability( const char * pszCap )
 
 {
-    if( EQUAL(pszCap,OLCRandomRead) )
-        return FALSE;
+    return FALSE;
 
-    else if( EQUAL(pszCap,OLCFastFeatureCount) )
+#if 0
+    if( EQUAL(pszCap, OLCRandomRead) )
         return FALSE;
 
-    else if( EQUAL(pszCap,OLCFastSpatialFilter) )
+    else if( EQUAL(pszCap, OLCFastFeatureCount) )
         return FALSE;
 
-    else if( EQUAL(pszCap,OLCTransactions) )
+    else if( EQUAL(pszCap, OLCFastSpatialFilter) )
         return FALSE;
 
-    else if( EQUAL(pszCap,OLCFastGetExtent) )
+    else if( EQUAL(pszCap, OLCTransactions) )
         return FALSE;
 
-    else
+    else if( EQUAL(pszCap, OLCFastGetExtent) )
         return FALSE;
-}
 
+    return FALSE;
+#endif
+}
 
 /************************************************************************/
 /*                            GetFIDColumn()                            */
@@ -589,7 +585,6 @@ const char *OGRIngresLayer::GetGeometryColumn()
     return osGeomColumn;
 }
 
-
 /************************************************************************/
 /*                         FetchSRSId()                                 */
 /************************************************************************/
@@ -609,10 +604,9 @@ int OGRIngresLayer::FetchSRSId(OGRFeatureDefn *poDefn)
 /* -------------------------------------------------------------------- */
     if( nSRSId == -2 )
     {
-        char         szCommand[1024];
-        char           **papszRow;
         OGRIngresStatement oStatement(poDS->GetConn());
 
+        char szCommand[1024] = {};
         sprintf( szCommand,
                  "SELECT srid FROM geometry_columns "
                  "WHERE f_table_name = '%s' AND f_geometry_column = '%s'",
@@ -621,7 +615,7 @@ int OGRIngresLayer::FetchSRSId(OGRFeatureDefn *poDefn)
 
         oStatement.ExecuteSQL(szCommand);
 
-        papszRow = oStatement.GetRow();
+        char **papszRow = oStatement.GetRow();
 
         if( papszRow != NULL && papszRow[0] != NULL )
         {
diff --git a/ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp b/ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp
index 3c6f601..351334c 100644
--- a/ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringresresultlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogringresresultlayer.cpp 11522 2007-05-15 14:26:10Z mloskot $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresResultLayer class.
@@ -30,7 +29,7 @@
 #include "cpl_conv.h"
 #include "ogr_ingres.h"
 
-CPL_CVSID("$Id: ogringresresultlayer.cpp 11522 2007-05-15 14:26:10Z mloskot $");
+CPL_CVSID("$Id: ogringresresultlayer.cpp 36384 2016-11-21 12:13:10Z rouault $");
 
 /************************************************************************/
 /*                        OGRIngresResultLayer()                         */
@@ -51,6 +50,7 @@ OGRIngresResultLayer::OGRIngresResultLayer( OGRIngresDataSource *poDSIn,
     BuildFullQueryStatement();
 
     poFeatureDefn = ReadResultDefinition();
+    nFeatureCount = 0;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/ingres/ogringresstatement.cpp b/ogr/ogrsf_frmts/ingres/ogringresstatement.cpp
index 6b22963..22f9f75 100644
--- a/ogr/ogrsf_frmts/ingres/ogringresstatement.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringresstatement.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogringresstatement.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresStatement class.
@@ -30,7 +29,7 @@
 #include "ogr_ingres.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogringresstatement.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogringresstatement.cpp 35166 2016-08-21 14:12:23Z goatbar $");
 
 /************************************************************************/
 /*                         OGRIngresStatement()                         */
@@ -133,8 +132,8 @@ int OGRIngresStatement::ExecuteSQL( const char *pszStatement )
 /* -------------------------------------------------------------------- */
 /*      Issue the query.                                                */
 /* -------------------------------------------------------------------- */
-    IIAPI_WAITPARM	waitParm = { -1 };
-    IIAPI_QUERYPARM	queryParm;
+    IIAPI_WAITPARM waitParm = { -1 };
+    IIAPI_QUERYPARM queryParm;
 
     queryParm.qy_genParm.gp_callback = NULL;
     queryParm.qy_genParm.gp_closure = NULL;
@@ -154,7 +153,7 @@ int OGRIngresStatement::ExecuteSQL( const char *pszStatement )
 /*      Capture handles for result.                                     */
 /* -------------------------------------------------------------------- */
     while( queryParm.qy_genParm.gp_completed == FALSE )
-	IIapi_wait( &waitParm );
+        IIapi_wait( &waitParm );
 
     if( queryParm.qy_genParm.gp_status != IIAPI_ST_SUCCESS
         || hConn == NULL )
@@ -194,7 +193,7 @@ int OGRIngresStatement::ExecuteSQL( const char *pszStatement )
     IIapi_getDescriptor( &getDescrParm );
 
     while( getDescrParm.gd_genParm.gp_completed == FALSE )
-	IIapi_wait( &waitParm );
+        IIapi_wait( &waitParm );
 
     if( getDescrParm.gd_genParm.gp_status != IIAPI_ST_SUCCESS )
     {
@@ -307,8 +306,8 @@ int OGRIngresStatement::ExecuteSQL( const char *pszStatement )
 char **OGRIngresStatement::GetRow()
 
 {
-    IIAPI_WAITPARM	waitParm = { -1 };
-    int                 iBaseCol;
+    IIAPI_WAITPARM waitParm = { -1 };
+    int            iBaseCol;
 
     ClearDynamicColumns();
 
@@ -496,39 +495,39 @@ void OGRIngresStatement::ReportError( IIAPI_GENPARM *genParm,
 
     do
     {
-	/*
-	** Invoke API function call.
- 	*/
-    	IIapi_getErrorInfo( &getErrParm );
-
- 	/*
-	** Break out of the loop if no data or failed.
-	*/
-    	if ( getErrParm.ge_status != IIAPI_ST_SUCCESS )
-	    break;
-
-	/*
-	** Process result.
-	*/
-
-	switch( getErrParm.ge_type )
-	{
-           case IIAPI_GE_ERROR		:
+        /*
+        ** Invoke API function call.
+        */
+        IIapi_getErrorInfo( &getErrParm );
+
+        /*
+        ** Break out of the loop if no data or failed.
+        */
+        if ( getErrParm.ge_status != IIAPI_ST_SUCCESS )
+            break;
+
+        /*
+        ** Process result.
+        */
+
+        switch( getErrParm.ge_type )
+        {
+           case IIAPI_GE_ERROR:
             eType = CE_Failure;
             break;
 
-          case IIAPI_GE_WARNING	:
+          case IIAPI_GE_WARNING:
             eType = CE_Warning;
             break;
 
-          case IIAPI_GE_MESSAGE	:
+          case IIAPI_GE_MESSAGE:
             eType = CE_Debug;
             break;
 
           default:
             eType = CE_Failure;
             break;
-	}
+        }
 
         CPLString osMoreMsg;
 
@@ -548,11 +547,11 @@ void OGRIngresStatement::ReportError( IIAPI_GENPARM *genParm,
 int OGRIngresStatement::SendParms()
 
 {
-    IIAPI_SETDESCRPARM		setDescrParm;
-    IIAPI_PUTPARMPARM		putParmParm;
-    IIAPI_DESCRIPTOR    	DescrBuffer;
-    IIAPI_DATAVALUE    		DataBuffer;
-    IIAPI_WAITPARM	        waitParm = { -1 };
+    IIAPI_SETDESCRPARM setDescrParm;
+    IIAPI_PUTPARMPARM  putParmParm;
+    IIAPI_DESCRIPTOR   DescrBuffer;
+    IIAPI_DATAVALUE    DataBuffer;
+    IIAPI_WAITPARM     waitParm = { -1 };
 
 /* -------------------------------------------------------------------- */
 /*      Describe the parameter.                                         */
@@ -574,7 +573,7 @@ int OGRIngresStatement::SendParms()
     IIapi_setDescriptor( &setDescrParm );
 
     while( setDescrParm.sd_genParm.gp_completed == FALSE )
-	IIapi_wait( &waitParm );
+        IIapi_wait( &waitParm );
 
     if( setDescrParm.sd_genParm.gp_status != IIAPI_ST_SUCCESS )
     {
@@ -608,14 +607,14 @@ int OGRIngresStatement::SendParms()
         putParmParm.pp_parmData[0].dv_length = nLen+2;
         putParmParm.pp_parmData[0].dv_value = abyChunk;
 
-	putParmParm.pp_moreSegments = nBytesSent < nParmLen;
+        putParmParm.pp_moreSegments = nBytesSent < nParmLen;
 
-	IIapi_putParms( &putParmParm );
+        IIapi_putParms( &putParmParm );
 
-	while( putParmParm.pp_genParm.gp_completed == FALSE )
-	    IIapi_wait( &waitParm );
+        while( putParmParm.pp_genParm.gp_completed == FALSE )
+            IIapi_wait( &waitParm );
 
-	if ( putParmParm.pp_genParm.gp_status != IIAPI_ST_SUCCESS )
+        if ( putParmParm.pp_genParm.gp_status != IIAPI_ST_SUCCESS )
         {
             ReportError( &(putParmParm.pp_genParm), "SendParm()" );
 
diff --git a/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp b/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp
index 9a221dc..f2f2ead 100644
--- a/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp
+++ b/ogr/ogrsf_frmts/ingres/ogringrestablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogringrestablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRIngresTableLayer class.
@@ -31,7 +30,7 @@
 #include "cpl_string.h"
 #include "ogr_ingres.h"
 
-CPL_CVSID("$Id: ogringrestablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogringrestablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGRIngresTableLayer()                         */
@@ -52,17 +51,14 @@ OGRIngresTableLayer::OGRIngresTableLayer( OGRIngresDataSource *poDSIn,
 
     poFeatureDefn = NULL;
     bLaunderColumnNames = TRUE;
+    bPreservePrecision = FALSE;
 }
 
 /************************************************************************/
 /*                        ~OGRIngresTableLayer()                         */
 /************************************************************************/
 
-OGRIngresTableLayer::~OGRIngresTableLayer()
-
-{
-}
-
+OGRIngresTableLayer::~OGRIngresTableLayer() {}
 
 /************************************************************************/
 /*                        Initialize()                                  */
@@ -120,11 +116,11 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
 /* -------------------------------------------------------------------- */
     OGRFeatureDefn *poDefn = new OGRFeatureDefn( pszTable );
     SetDescription( poDefn->GetName() );
-    char           **papszRow;
 
     poDefn->Reference();
     poDefn->SetGeomType( wkbNone );
 
+    char **papszRow = NULL;
     while( (papszRow = oStatement.GetRow()) != NULL )
     {
         CPLString       osFieldName = papszRow[0];
@@ -141,7 +137,7 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
 
         OGRFieldDefn    oField(osFieldName, OFTString);
 
-        if( osGeomColumn.size() == 0
+        if( osGeomColumn.empty()
             && (EQUAL(osInternalType,"POINT")
                 || EQUAL(osInternalType,"IPOINT")
                 || EQUAL(osInternalType,"BOX")
@@ -172,14 +168,14 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
                      || strstr(osInternalType, "LINESTRING"))
                 poDefn->SetGeomType( wkbLineString );
             else if( strstr(osInternalType,"MULTIPOINT"))
-            	poDefn->SetGeomType(wkbMultiPoint);
+                poDefn->SetGeomType(wkbMultiPoint);
             else if( strstr(osInternalType,"MULTIPOLYGON"))
-            	poDefn->SetGeomType(wkbMultiPolygon);
+                poDefn->SetGeomType(wkbMultiPolygon);
             else if( strstr(osInternalType,"MULTILINESTRING"))
-            	poDefn->SetGeomType(wkbMultiLineString);
+                poDefn->SetGeomType(wkbMultiLineString);
             // Oddly this is the standin for a generic geometry type.
             else if( strstr(osInternalType,"GEOMETRYCOLLECTION"))
-            	poDefn->SetGeomType(wkbUnknown);
+                poDefn->SetGeomType(wkbUnknown);
             else
                 poDefn->SetGeomType( wkbPolygon );
             continue;
@@ -233,7 +229,7 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
 #endif
 
         // Is this an integer primary key field?
-        if( osFIDColumn.size() == 0
+        if( osFIDColumn.empty()
             && oField.GetType() == OFTInteger
             && EQUAL(oField.GetNameRef(),"ogr_fid") )
         {
@@ -244,7 +240,7 @@ OGRFeatureDefn *OGRIngresTableLayer::ReadTableDefinition( const char *pszTable )
         poDefn->AddFieldDefn( &oField );
     }
 
-    if( osFIDColumn.size() )
+    if( !osFIDColumn.empty() )
         CPLDebug( "Ingres", "table %s has FID column %s.",
                   pszTable, osFIDColumn.c_str() );
     else
@@ -312,13 +308,12 @@ void OGRIngresTableLayer::BuildWhere()
         osWHERE.Printf( "WHERE MBRIntersects(GeomFromText('%s'), %s)",
                         szEnvelope,
                         osGeomColumn.c_str() );
-
     }
 #endif
 
-    if( osQuery.size() > 0 )
+    if( !osQuery.empty() )
     {
-        if( osWHERE.size() == 0 )
+        if( osWHERE.empty() )
             osWHERE = "WHERE " + osQuery;
         else
             osWHERE += "&& " + osQuery;
@@ -363,39 +358,37 @@ void OGRIngresTableLayer::ResetReading()
 char *OGRIngresTableLayer::BuildFields()
 
 {
-    int         i, nSize;
-    char        *pszFieldList;
+    int nSize = 25 + osGeomColumn.size() + osFIDColumn.size();
 
-    nSize = 25 + osGeomColumn.size() + osFIDColumn.size();
-
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
         nSize += strlen(poFeatureDefn->GetFieldDefn(i)->GetNameRef()) + 4;
 
-    pszFieldList = (char *) CPLMalloc(nSize);
+    char *pszFieldList = (char *) CPLMalloc(nSize);
     pszFieldList[0] = '\0';
 
     if( osFIDColumn.size()
         && poFeatureDefn->GetFieldIndex( osFIDColumn ) == -1 )
         sprintf( pszFieldList, "%s", osFIDColumn.c_str() );
 
-    if( osGeomColumn.size() )
+    if( !osGeomColumn.empty() )
     {
         if( strlen(pszFieldList) > 0 )
             strcat( pszFieldList, ", " );
 
         if( poDS->IsNewIngres() )
         {
-			sprintf( pszFieldList+strlen(pszFieldList),
-					 "ASBINARY(%s) %s", osGeomColumn.c_str(), osGeomColumn.c_str() );
+            sprintf( pszFieldList+strlen(pszFieldList),
+                     "ASBINARY(%s) %s", osGeomColumn.c_str(),
+                     osGeomColumn.c_str() );
         }
         else
         {
-			sprintf( pszFieldList+strlen(pszFieldList),
-					 "%s %s", osGeomColumn.c_str(), osGeomColumn.c_str() );
+            sprintf( pszFieldList+strlen(pszFieldList),
+                     "%s %s", osGeomColumn.c_str(), osGeomColumn.c_str() );
         }
     }
 
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
 
@@ -440,7 +433,7 @@ int OGRIngresTableLayer::TestCapability( const char * pszCap )
 
 {
     if( EQUAL(pszCap,OLCRandomRead) )
-        return osFIDColumn.size() != 0;
+        return !osFIDColumn.empty();
 
     else if( EQUAL(pszCap,OLCFastFeatureCount) )
         return TRUE;
@@ -452,10 +445,10 @@ int OGRIngresTableLayer::TestCapability( const char * pszCap )
         return bUpdateAccess;
 
     else if( EQUAL(pszCap,OLCRandomWrite) )
-        return bUpdateAccess && osFIDColumn.size() != 0;
+        return bUpdateAccess && !osFIDColumn.empty();
 
     else if( EQUAL(pszCap,OLCDeleteFeature) )
-        return bUpdateAccess && osFIDColumn.size() != 0;
+        return bUpdateAccess && !osFIDColumn.empty();
 
     else
         return OGRIngresLayer::TestCapability( pszCap );
@@ -501,14 +494,13 @@ OGRErr OGRIngresTableLayer::DeleteFeature( GIntBig nFID )
 /*      We can only delete features if we have a well defined FID       */
 /*      column to target.                                               */
 /* -------------------------------------------------------------------- */
-    if( osFIDColumn.size() == 0 )
+    if( osFIDColumn.empty() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "DeleteFeature(%ld) failed.  Unable to delete features "
                   "in tables without\n a recognised FID column.",
                   nFID );
         return OGRERR_FAILURE;
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -738,7 +730,7 @@ OGRErr OGRIngresTableLayer::PrepareNewStyleGeometry(
     OGRGeometry *poGeom, CPLString &osRetGeomText )
 
 {
-	OGRErr eErr = OGRERR_NONE;
+    OGRErr eErr = OGRERR_NONE;
     osRetGeomText = "";
 
     if( poGeom == NULL )
@@ -777,21 +769,21 @@ OGRErr OGRIngresTableLayer::PrepareNewStyleGeometry(
 /* -------------------------------------------------------------------- */
     else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString )
     {
-    	osRetGeomText.Printf("MLINEFROMWKB( ~V , %d)", nSRSId);
+        osRetGeomText.Printf("MLINEFROMWKB( ~V , %d)", nSRSId);
     }
 /* -------------------------------------------------------------------- */
 /*      Multipolygon                                                    */
 /* -------------------------------------------------------------------- */
     else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
     {
-    	osRetGeomText.Printf("MPOLYFROMWKB( ~V , %d)", nSRSId);
+        osRetGeomText.Printf("MPOLYFROMWKB( ~V , %d)", nSRSId);
     }
 /* -------------------------------------------------------------------- */
 /*      Geometry collection.                                            */
 /* -------------------------------------------------------------------- */
     else if( wkbFlatten(poGeom->getGeometryType()) == wkbGeometryCollection )
     {
-    	osRetGeomText.Printf("GEOMCOLLFROMWKB( ~V , %d)", nSRSId);
+        osRetGeomText.Printf("GEOMCOLLFROMWKB( ~V , %d)", nSRSId);
     }
 /* -------------------------------------------------------------------- */
 /*      Fallback generic geometry handling.                             */
@@ -803,7 +795,7 @@ OGRErr OGRIngresTableLayer::PrepareNewStyleGeometry(
             "Unexpected geometry type (%s), attempting to treat generically.",
             poGeom->getGeometryName() );
 
-    	osRetGeomText.Printf("GEOMETRYFROMWKB( ~V , %d)", nSRSId);
+        osRetGeomText.Printf("GEOMETRYFROMWKB( ~V , %d)", nSRSId);
     }
 
     return eErr;
@@ -824,17 +816,16 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     osCommand.Printf( "INSERT INTO %s (", poFeatureDefn->GetName() );
 
-
 /* -------------------------------------------------------------------- */
 /*      Accumulate fields to be inserted.                               */
 /* -------------------------------------------------------------------- */
-    if( poFeature->GetGeometryRef() != NULL && osGeomColumn.size() )
+    if( poFeature->GetGeometryRef() != NULL && !osGeomColumn.empty() )
     {
         osCommand = osCommand + osGeomColumn + " ";
         bNeedComma = TRUE;
     }
 
-    if( poFeature->GetFID() != OGRNullFID && osFIDColumn.size() )
+    if( poFeature->GetFID() != OGRNullFID && !osFIDColumn.empty() )
     {
         if( bNeedComma )
             osCommand += ", ";
@@ -845,7 +836,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
             continue;
 
         if( !bNeedComma )
@@ -866,18 +857,18 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     // Set the geometry
     bNeedComma = FALSE;
-    if( poFeature->GetGeometryRef() != NULL && osGeomColumn.size() )
+    if( poFeature->GetGeometryRef() != NULL && !osGeomColumn.empty() )
     {
         bNeedComma = TRUE;
         OGRErr localErr;
 
         if( poDS->IsNewIngres() )
         {
-        	localErr = PrepareNewStyleGeometry( poFeature->GetGeometryRef(), osGeomText );
+            localErr = PrepareNewStyleGeometry( poFeature->GetGeometryRef(), osGeomText );
         }
         else
         {
-        	localErr = PrepareOldStyleGeometry( poFeature->GetGeometryRef(), osGeomText );
+            localErr = PrepareOldStyleGeometry( poFeature->GetGeometryRef(), osGeomText );
         }
         if( localErr == OGRERR_NONE )
         {
@@ -895,8 +886,8 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
             }
             else
             {
-            	osCommand += osGeomText;
-            	//osGeomText = "";
+                osCommand += osGeomText;
+                // osGeomText = "";
             }
         }
         else
@@ -909,7 +900,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Set the FID                                                     */
 /* -------------------------------------------------------------------- */
-    if( poFeature->GetFID() != OGRNullFID && osFIDColumn.size() )
+    if( poFeature->GetFID() != OGRNullFID && !osFIDColumn.empty() )
     {
         if( bNeedComma )
             osCommand += ", ";
@@ -922,7 +913,7 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
             continue;
 
         if( bNeedComma )
@@ -981,7 +972,6 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
         {
             osCommand += pszStrValue;
         }
-
     }
 
     osCommand += ")";
@@ -994,31 +984,30 @@ OGRErr OGRIngresTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     oStmt.bDebug = FALSE;
 
-    if( osGeomText.size() > 0  && poDS->IsNewIngres() == FALSE )
+    if( !osGeomText.empty()  && poDS->IsNewIngres() == FALSE )
         oStmt.addInputParameter( IIAPI_LVCH_TYPE, osGeomText.size(),
                                  (GByte *) osGeomText.c_str() );
-    if( osGeomText.size() > 0 && poDS->IsNewIngres() == TRUE )
+    if( !osGeomText.empty() && poDS->IsNewIngres() == TRUE )
     {
-    	GByte * pabyWKB;
-    	int nSize = poFeature->GetGeometryRef()->WkbSize();
-    	pabyWKB = (GByte *) CPLMalloc(nSize);
+        GByte * pabyWKB;
+        int nSize = poFeature->GetGeometryRef()->WkbSize();
+        pabyWKB = (GByte *) CPLMalloc(nSize);
 
-    	poFeature->GetGeometryRef()->exportToWkb(wkbNDR, pabyWKB);
+        poFeature->GetGeometryRef()->exportToWkb(wkbNDR, pabyWKB);
 
-    	oStmt.addInputParameter( IIAPI_LBYTE_TYPE, nSize, pabyWKB );
-    	CPLFree(pabyWKB);
+        oStmt.addInputParameter( IIAPI_LBYTE_TYPE, nSize, pabyWKB );
+        CPLFree(pabyWKB);
 /*
  * Test code
-     	char * pszWKT;
-    	poFeature->GetGeometryRef()->exportToWkt(&pszWKT);
-    	oStmt.addInputParameter(IIAPI_LVCH_TYPE, strlen(pszWKT), (GByte *) pszWKT);*/
+        char * pszWKT;
+        poFeature->GetGeometryRef()->exportToWkt(&pszWKT);
+        oStmt.addInputParameter(IIAPI_LVCH_TYPE, strlen(pszWKT), (GByte *) pszWKT);*/
     }
 
     if( !oStmt.ExecuteSQL( osCommand ) )
         return OGRERR_FAILURE;
 
     return OGRERR_NONE;
-
 }
 
 /************************************************************************/
@@ -1176,14 +1165,11 @@ OGRFeature *OGRIngresTableLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
 /*      Fetch the result record.                                        */
 /* -------------------------------------------------------------------- */
-    char **papszRow;
-    unsigned long *panLengths;
-
-    papszRow = ingres_fetch_row( hResultSet );
+    char **papszRow = ingres_fetch_row( hResultSet );
     if( papszRow == NULL )
         return NULL;
 
-    panLengths = ingres_fetch_lengths( hResultSet );
+    unsigned long *panLengths = ingres_fetch_lengths( hResultSet );
 
 /* -------------------------------------------------------------------- */
 /*      Transform into a feature.                                       */
@@ -1199,7 +1185,7 @@ OGRFeature *OGRIngresTableLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
     if( hResultSet != NULL )
         ingres_free_result( hResultSet );
- 		hResultSet = NULL;
+    hResultSet = NULL;
 
     return poFeature;
 }
@@ -1226,11 +1212,9 @@ GIntBig OGRIngresTableLayer::GetFeatureCount( int bForce )
 /* -------------------------------------------------------------------- */
 /*      Issue the appropriate select command.                           */
 /* -------------------------------------------------------------------- */
-    INGRES_RES    *hResult;
-    const char         *pszCommand;
-
-    pszCommand = CPLSPrintf( "SELECT COUNT(*) FROM %s %s",
-                             poFeatureDefn->GetName(), pszWHERE );
+    const char *pszCommand =
+        CPLSPrintf( "SELECT COUNT(*) FROM %s %s",
+                    poFeatureDefn->GetName(), pszWHERE );
 
     if( ingres_query( poDS->GetConn(), pszCommand ) )
     {
@@ -1238,7 +1222,7 @@ GIntBig OGRIngresTableLayer::GetFeatureCount( int bForce )
         return FALSE;
     }
 
-    hResult = ingres_store_result( poDS->GetConn() );
+    INGRES_RES *hResult = ingres_store_result( poDS->GetConn() );
     if( hResult == NULL )
     {
         poDS->ReportError( "ingres_store_result() failed on SELECT COUNT(*)." );
@@ -1256,24 +1240,24 @@ GIntBig OGRIngresTableLayer::GetFeatureCount( int bForce )
 
     if( hResultSet != NULL )
         ingres_free_result( hResultSet );
- 		hResultSet = NULL;
+    hResultSet = NULL;
 
     return nCount;
 }
 #endif
 
 /************************************************************************/
-/*                          GetExtent()					*/
+/*                          GetExtent()                                 */
 /*                                                                      */
-/*      Retrieve the MBR of the Ingres table.  This should be made more  */
-/*      in the future when Ingres adds support for a single MBR query    */
-/*      like PostgreSQL.						*/
+/*      Retrieve the MBR of the Ingres table.  This should be made more */
+/*      in the future when Ingres adds support for a single MBR query   */
+/*      like PostgreSQL.                                                */
 /************************************************************************/
 #ifdef notdef
 OGRErr OGRIngresTableLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 
 {
-	if( GetLayerDefn()->GetGeomType() == wkbNone )
+    if( GetLayerDefn()->GetGeomType() == wkbNone )
     {
         psExtent->MinX = 0.0;
         psExtent->MaxX = 0.0;
@@ -1283,68 +1267,68 @@ OGRErr OGRIngresTableLayer::GetExtent(OGREnvelope *psExtent, int bForce )
         return OGRERR_FAILURE;
     }
 
-	OGREnvelope oEnv;
-	CPLString   osCommand;
-	GBool       bExtentSet = FALSE;
+    OGREnvelope oEnv;
+    CPLString   osCommand;
+    GBool       bExtentSet = FALSE;
 
-	osCommand.Printf( "SELECT Envelope(%s) FROM %s;", pszGeomColumn, pszGeomColumnTable);
+    osCommand.Printf( "SELECT Envelope(%s) FROM %s;", pszGeomColumn, pszGeomColumnTable);
 
-	if (ingres_query(poDS->GetConn(), osCommand) == 0)
-	{
-		INGRES_RES* result = ingres_use_result(poDS->GetConn());
-		if ( result == NULL )
+    if (ingres_query(poDS->GetConn(), osCommand) == 0)
+    {
+        INGRES_RES* result = ingres_use_result(poDS->GetConn());
+        if ( result == NULL )
         {
             poDS->ReportError( "ingres_use_result() failed on extents query." );
             return OGRERR_FAILURE;
         }
 
-		INGRES_ROW row;
-		unsigned long *panLengths = NULL;
-		while ((row = ingres_fetch_row(result)))
-		{
-			if (panLengths == NULL)
-			{
-				panLengths = ingres_fetch_lengths( result );
-				if ( panLengths == NULL )
-				{
-					poDS->ReportError( "ingres_fetch_lengths() failed on extents query." );
-					return OGRERR_FAILURE;
-				}
-			}
-
-			OGRGeometry *poGeometry = NULL;
-			// Geometry columns will have the first 4 bytes contain the SRID.
-			OGRGeometryFactory::createFromWkb(((GByte *)row[0]) + 4,
-											  NULL,
-											  &poGeometry,
-											  panLengths[0] - 4 );
-
-			if ( poGeometry != NULL )
-			{
-				if (poGeometry && !bExtentSet)
-				{
-					poGeometry->getEnvelope(psExtent);
-					bExtentSet = TRUE;
-				}
-				else if (poGeometry)
-				{
-					poGeometry->getEnvelope(&oEnv);
-					if (oEnv.MinX < psExtent->MinX)
-						psExtent->MinX = oEnv.MinX;
-					if (oEnv.MinY < psExtent->MinY)
-						psExtent->MinY = oEnv.MinY;
-					if (oEnv.MaxX > psExtent->MaxX)
-						psExtent->MaxX = oEnv.MaxX;
-					if (oEnv.MaxY > psExtent->MaxY)
-						psExtent->MaxY = oEnv.MaxY;
-				}
-				delete poGeometry;
-			}
-		}
-
-		ingres_free_result(result);
-	}
-
-	return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
+        INGRES_ROW row;
+        unsigned long *panLengths = NULL;
+        while ((row = ingres_fetch_row(result)))
+        {
+            if (panLengths == NULL)
+            {
+                panLengths = ingres_fetch_lengths( result );
+                if ( panLengths == NULL )
+                {
+                    poDS->ReportError( "ingres_fetch_lengths() failed on extents query." );
+                    return OGRERR_FAILURE;
+                }
+            }
+
+            OGRGeometry *poGeometry = NULL;
+            // Geometry columns will have the first 4 bytes contain the SRID.
+            OGRGeometryFactory::createFromWkb(((GByte *)row[0]) + 4,
+                                              NULL,
+                                              &poGeometry,
+                                              panLengths[0] - 4 );
+
+            if ( poGeometry != NULL )
+            {
+                if (poGeometry && !bExtentSet)
+                {
+                    poGeometry->getEnvelope(psExtent);
+                    bExtentSet = TRUE;
+                }
+                else if (poGeometry)
+                {
+                    poGeometry->getEnvelope(&oEnv);
+                    if (oEnv.MinX < psExtent->MinX)
+                        psExtent->MinX = oEnv.MinX;
+                    if (oEnv.MinY < psExtent->MinY)
+                        psExtent->MinY = oEnv.MinY;
+                    if (oEnv.MaxX > psExtent->MaxX)
+                        psExtent->MaxX = oEnv.MaxX;
+                    if (oEnv.MaxY > psExtent->MaxY)
+                        psExtent->MaxY = oEnv.MaxY;
+                }
+                delete poGeometry;
+            }
+        }
+
+        ingres_free_result(result);
+    }
+
+    return bExtentSet ? OGRERR_NONE : OGRERR_FAILURE;
 }
 #endif
diff --git a/ogr/ogrsf_frmts/jml/ogr_jml.h b/ogr/ogrsf_frmts/jml/ogr_jml.h
index 8121c78..6f010a0 100644
--- a/ogr/ogrsf_frmts/jml/ogr_jml.h
+++ b/ogr/ogrsf_frmts/jml/ogr_jml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_jml.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_jml.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  JML .jml Translator
  * Purpose:  Definition of classes for OGR JML driver.
@@ -117,14 +117,14 @@ class OGRJMLLayer : public OGRLayer
                                          VSILFILE* fp );
                         ~OGRJMLLayer();
 
-    const char         *GetName() { return poFeatureDefn->GetName(); }
+    const char         *GetName() override { return poFeatureDefn->GetName(); }
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeatureDefn *    GetLayerDefn();
+    OGRFeatureDefn *    GetLayerDefn() override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     void                startElementCbk(const char *pszName, const char **ppszAttr);
     void                endElementCbk(const char *pszName);
@@ -162,15 +162,15 @@ class OGRJMLWriterLayer : public OGRLayer
                                            bool bClassicGML );
                         ~OGRJMLWriterLayer();
 
-    void                ResetReading() {}
-    OGRFeature *        GetNextFeature() { return NULL; }
+    void                ResetReading() override {}
+    OGRFeature *        GetNextFeature() override { return NULL; }
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
-    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK );
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
+    OGRErr              CreateField( OGRFieldDefn *poField, int bApproxOK ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -188,15 +188,15 @@ class OGRJMLDataset : public GDALDataset
                         OGRJMLDataset();
                         ~OGRJMLDataset();
 
-    int                 GetLayerCount() { return poLayer != NULL ? 1 : 0; }
-    OGRLayer*           GetLayer( int );
+    int                 GetLayerCount() override { return poLayer != NULL ? 1 : 0; }
+    OGRLayer*           GetLayer( int ) override;
 
     OGRLayer *          ICreateLayer( const char * pszLayerName,
                                     OGRSpatialReference *poSRS,
                                     OGRwkbGeometryType eType,
-                                    char ** papszOptions );
+                                    char ** papszOptions ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     static int          Identify( GDALOpenInfo* poOpenInfo );
     static GDALDataset* Open( GDALOpenInfo* poOpenInfo );
diff --git a/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp b/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp
index 9bcce87..8c532f0 100644
--- a/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp
+++ b/ogr/ogrsf_frmts/jml/ogrjmldataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrjmldataset.cpp 32786 2016-01-06 18:29:00Z goatbar $
  *
  * Project:  JML Translator
  * Purpose:  Implements OGRJMLDataset class
@@ -34,7 +33,7 @@
 
 // g++ -DHAVE_EXPAT -fPIC -shared -Wall -g -DDEBUG ogr/ogrsf_frmts/jml/*.cpp -o ogr_JML.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/jml -L. -lgdal
 
-CPL_CVSID("$Id: ogrjmldataset.cpp 32786 2016-01-06 18:29:00Z goatbar $");
+CPL_CVSID("$Id: ogrjmldataset.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                          OGRJMLDataset()                             */
diff --git a/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp b/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp
index 026bf15..0b42fa7 100644
--- a/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp
+++ b/ogr/ogrsf_frmts/jml/ogrjmllayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrjmllayer.cpp 33180 2016-01-28 10:13:57Z rouault $
  *
  * Project:  JML Translator
  * Purpose:  Implements OGRJMLLayer class.
@@ -30,7 +29,7 @@
 #include "ogr_jml.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrjmllayer.cpp 33180 2016-01-28 10:13:57Z rouault $");
+CPL_CVSID("$Id: ogrjmllayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 #ifdef HAVE_EXPAT
 
@@ -95,7 +94,6 @@ OGRJMLLayer::~OGRJMLLayer()
         delete poFeature;
 }
 
-
 /************************************************************************/
 /*                            GetLayerDefn()                            */
 /************************************************************************/
@@ -193,7 +191,7 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
 
             if( oColumn.bIsBody )
             {
-                if( oColumn.osAttributeName.size() &&
+                if( !oColumn.osAttributeName.empty() &&
                     ppszAttr != NULL &&
                     oColumn.osAttributeName.compare(ppszAttr[0]) == 0 &&
                     oColumn.osAttributeValue.compare(ppszAttr[1]) == 0 )
@@ -205,7 +203,7 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
                     iAttr = (i < 0) ? iAttr + 1 : i;
                     break;
                 }
-                else if( oColumn.osAttributeName.size() == 0 )
+                else if( oColumn.osAttributeName.empty() )
                 {
                     /* <osElementName>value</osElementName> */
 
@@ -215,7 +213,7 @@ void OGRJMLLayer::startElementCbk(const char *pszName, const char **ppszAttr)
                     break;
                 }
             }
-            else if( oColumn.osAttributeName.size() &&
+            else if( !oColumn.osAttributeName.empty() &&
                       ppszAttr != NULL &&
                       oColumn.osAttributeName.compare(ppszAttr[0]) == 0 )
             {
@@ -290,6 +288,8 @@ void OGRJMLLayer::endElementCbk(const char *pszName)
     {
         if( nElementValueLen )
             poFeature->SetField(iAttr, pszElementValue);
+        else if( iAttr >= 0 )
+            poFeature->SetFieldNull(iAttr);
         nAttributeElementDepth = 0;
         StopAccumulate();
     }
@@ -323,10 +323,10 @@ void OGRJMLLayer::endElementCbk(const char *pszName)
         /* Builds a style string from R_G_B if we don't already have a */
         /* style string */
         OGRGeometry* poGeom = poFeature->GetGeometryRef();
-        int R;
-        int G;
-        int B;
-        if( iRGBField >= 0 && poFeature->IsFieldSet(iRGBField) &&
+        unsigned int R = 0;
+        unsigned int G = 0;
+        unsigned int B = 0;
+        if( iRGBField >= 0 && poFeature->IsFieldSetAndNotNull(iRGBField) &&
             poFeature->GetStyleString() == NULL && poGeom != NULL &&
             sscanf(poFeature->GetFieldAsString(iRGBField),
                        "%02X%02X%02X", &R, &G, &B) == 3 )
@@ -460,7 +460,7 @@ OGRFeature *OGRJMLLayer::GetNextFeature()
 
     nWithoutEventCounter = 0;
 
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -526,7 +526,7 @@ void OGRJMLLayer::LoadSchema()
     VSIFSeekL( fp, 0, SEEK_SET );
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -557,8 +557,8 @@ void OGRJMLLayer::LoadSchema()
         bStopParsing = true;
     }
 
-    if( osCollectionElement.size() == 0 || osFeatureElement.size() == 0 ||
-        osGeometryElement.size() == 0 )
+    if( osCollectionElement.empty() || osFeatureElement.empty() ||
+        osGeometryElement.empty() )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Missing CollectionElement, FeatureElement or "
@@ -569,7 +569,6 @@ void OGRJMLLayer::LoadSchema()
     ResetReading();
 }
 
-
 /************************************************************************/
 /*                  startElementLoadSchemaCbk()                         */
 /************************************************************************/
@@ -706,19 +705,19 @@ void OGRJMLLayer::endElementLoadSchemaCbk( const char * /* pszName */ )
     else if( nColumnDepth == currentDepth )
     {
         bool bIsOK = true;
-        if( oCurColumn.osName.size() == 0 )
+        if( oCurColumn.osName.empty() )
             bIsOK = false;
-        if( oCurColumn.osType.size() == 0 )
+        if( oCurColumn.osType.empty() )
             bIsOK = false;
-        if( oCurColumn.osElementName.size() == 0 )
+        if( oCurColumn.osElementName.empty() )
             bIsOK = false;
         if( oCurColumn.bIsBody )
         {
-            if( oCurColumn.osAttributeName.size() == 0 &&
-                oCurColumn.osAttributeValue.size() != 0 )
+            if( oCurColumn.osAttributeName.empty() &&
+                !oCurColumn.osAttributeValue.empty() )
                 bIsOK = false;
-            if( oCurColumn.osAttributeName.size() != 0 &&
-                oCurColumn.osAttributeValue.size() == 0 )
+            if( !oCurColumn.osAttributeName.empty() &&
+                oCurColumn.osAttributeValue.empty() )
                 bIsOK = false;
             /* Only 2 valid possibilities : */
             /* <osElementName osAttributeName="osAttributeValue">value</osElementName> */
@@ -727,9 +726,9 @@ void OGRJMLLayer::endElementLoadSchemaCbk( const char * /* pszName */ )
         else
         {
             /* <osElementName osAttributeName="value"></osElementName> */
-            if( oCurColumn.osAttributeName.size() == 0 )
+            if( oCurColumn.osAttributeName.empty() )
                 bIsOK = false;
-            if( oCurColumn.osAttributeValue.size() != 0 )
+            if( !oCurColumn.osAttributeValue.empty() )
                 bIsOK = false;
         }
 
diff --git a/ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp b/ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp
index 5f270db..8fff2e9 100644
--- a/ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp
+++ b/ogr/ogrsf_frmts/jml/ogrjmlwriterlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrjmlwriterlayer.cpp 32783 2016-01-06 16:11:09Z goatbar $
  *
  * Project:  JML Translator
  * Purpose:  Implements OGRJMLWriterLayer class.
@@ -30,7 +29,9 @@
 #include "cpl_conv.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrjmlwriterlayer.cpp 32783 2016-01-06 16:11:09Z goatbar $");
+#include <cstdlib>
+
+CPL_CVSID("$Id: ogrjmlwriterlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                           OGRJMLWriterLayer()                        */
@@ -61,7 +62,6 @@ OGRJMLWriterLayer::OGRJMLWriterLayer( const char* pszLayerName,
                     "<FeatureElement>feature</FeatureElement>\n"
                     "<GeometryElement>geometry</GeometryElement>\n"
                     "<ColumnDefinitions>\n");
-
 }
 
 /************************************************************************/
@@ -161,7 +161,7 @@ OGRErr OGRJMLWriterLayer::ICreateFeature( OGRFeature *poFeature )
             VSIFPrintfL(fp, "          <%s>", pszName);
         else
             VSIFPrintfL(fp, "          <property name=\"%s\">", pszName);
-        if( poFeature->IsFieldSet(i) )
+        if( poFeature->IsFieldSetAndNotNull(i) )
         {
             const OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
             if( eType == OFTString )
@@ -173,13 +173,13 @@ OGRErr OGRJMLWriterLayer::ICreateFeature( OGRFeature *poFeature )
             }
             else if( eType == OFTDateTime )
             {
-                int nYear;
-                int nMonth;
-                int nDay;
-                int nHour;
-                int nMinute;
-                int nTZFlag;
-                float fSecond;
+                int nYear = 0;
+                int nMonth = 0;
+                int nDay = 0;
+                int nHour = 0;
+                int nMinute = 0;
+                int nTZFlag = 0;
+                float fSecond = 0.0f;
                 poFeature->GetFieldAsDateTime(i, &nYear, &nMonth, &nDay,
                                               &nHour, &nMinute, &fSecond, &nTZFlag);
                 /* When writing time zone, OpenJUMP expects .XXX seconds */
@@ -196,12 +196,12 @@ OGRErr OGRJMLWriterLayer::ICreateFeature( OGRFeature *poFeature )
                 {
                     int nOffset = (nTZFlag - 100) * 15;
                     int nHours = (int) (nOffset / 60);  // round towards zero
-                    int nMinutes = ABS(nOffset - nHours * 60);
+                    int nMinutes = std::abs(nOffset - nHours * 60);
 
                     if( nOffset < 0 )
                     {
                         VSIFPrintfL(fp, "-" );
-                        nHours = ABS(nHours);
+                        nHours = std::abs(nHours);
                     }
                     else
                         VSIFPrintfL(fp, "+" );
@@ -310,16 +310,24 @@ OGRErr OGRJMLWriterLayer::CreateField( OGRFieldDefn *poFieldDefn,
     if( !bAddRGBField && strcmp( poFieldDefn->GetNameRef(), "R_G_B" ) == 0 )
         return OGRERR_FAILURE;
 
-    const char* pszType;
+    const char* pszType = NULL;
     OGRFieldType eType = poFieldDefn->GetType();
     if( eType == OFTInteger )
+    {
         pszType = "INTEGER";
+    }
     else if( eType == OFTInteger64 )
+    {
         pszType = "OBJECT";
+    }
     else if( eType == OFTReal )
+    {
         pszType = "DOUBLE";
+    }
     else if( eType == OFTDate || eType == OFTDateTime )
+    {
         pszType = "DATE";
+    }
     else
     {
         if( eType != OFTString )
diff --git a/ogr/ogrsf_frmts/kml/drv_kml.html b/ogr/ogrsf_frmts/kml/drv_kml.html
index f43fa8e..4cb56c0 100644
--- a/ogr/ogrsf_frmts/kml/drv_kml.html
+++ b/ogr/ogrsf_frmts/kml/drv_kml.html
@@ -83,6 +83,9 @@ See the <a href="http://code.google.com/apis/kml/documentation/kml_tags_21.html#
 for further information.
 <pre>ogr2ogr -f KML output.kml input.shp -dsco AltitudeMode=absolute</pre>
 </li>
+<li><b>DOCUMENT_ID</b>=string: Starting with GDAL 2.2, the DOCUMENT_ID datasource
+creation option can be used to specified the id of the root <Document> node.
+The default value is root_doc.</li>
 </ul>
 
 
diff --git a/ogr/ogrsf_frmts/kml/kml.cpp b/ogr/ogrsf_frmts/kml/kml.cpp
index fa46070..71d8f96 100644
--- a/ogr/ogrsf_frmts/kml/kml.cpp
+++ b/ogr/ogrsf_frmts/kml/kml.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: kml.cpp 34104 2016-04-25 17:17:20Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for reading, parsing and handling a kmlfile.
@@ -29,14 +28,17 @@
  ****************************************************************************/
 #include "kmlnode.h"
 #include "kml.h"
-#include "cpl_error.h"
+
 #include "cpl_conv.h"
-// std
+#include "cpl_error.h"
+
 #include <cerrno>
 #include <cstdio>
 #include <iostream>
 #include <string>
 
+CPL_CVSID("$Id: kml.cpp 35775 2016-10-17 00:43:44Z goatbar $");
+
 KML::KML() :
     poTrunk_(NULL),
     nNumLayers_(-1),
@@ -48,7 +50,7 @@ KML::KML() :
     oCurrentParser(NULL),
     nDataHandlerCounter(0),
     nWithoutEventCounter(0)
-{ }
+{}
 
 KML::~KML()
 {
@@ -70,10 +72,6 @@ bool KML::open(const char * pszFilename)
 
 void KML::parse()
 {
-    int nDone = 0;
-    int nLen = 0;
-    char aBuf[BUFSIZ] = { 0 };
-
     if( NULL == pKMLFile_ )
     {
         sError_ = "No file given";
@@ -98,6 +96,10 @@ void KML::parse()
     oCurrentParser = oParser;
     nWithoutEventCounter = 0;
 
+    int nDone = 0;
+    int nLen = 0;
+    char aBuf[BUFSIZ] = { 0 };
+
     do
     {
         nDataHandlerCounter = 0;
@@ -131,10 +133,6 @@ void KML::parse()
 
 void KML::checkValidity()
 {
-    int nDone = 0;
-    int nLen = 0;
-    char aBuf[BUFSIZ] = { 0 };
-
     if(poTrunk_ != NULL)
     {
         delete poTrunk_;
@@ -161,7 +159,11 @@ void KML::checkValidity()
 
     oCurrentParser = oParser;
 
-    /* Parses the file until we find the first element */
+    int nDone = 0;
+    int nLen = 0;
+    char aBuf[BUFSIZ] = { 0 };
+
+    // Parses the file until we find the first element.
     do
     {
         nDataHandlerCounter = 0;
@@ -299,7 +301,9 @@ void XMLCALL KML::startElementValidate( void* pUserData, const char* pszName,
                 }
                 else
                 {
-                    CPLDebug("KML", "Unhandled xmlns value : %s. Going on though...", ppszAttr[i]);
+                    CPLDebug("KML",
+                             "Unhandled xmlns value : %s. Going on though...",
+                             ppszAttr[i]);
                     poKML->validity = KML_VALIDITY_VALID;
                     poKML->sVersion_ = "?";
                 }
@@ -354,10 +358,10 @@ void XMLCALL KML::endElement(void* pUserData, const char* pszName)
             while( true )
             {
                 // Cut off whitespaces
-                while(nPos < nLength &&
-                      (pszData[nPos] == ' ' || pszData[nPos] == '\n'
-                       || pszData[nPos] == '\r' || pszData[nPos] == '\t' ))
-                    nPos ++;
+                while( nPos < nLength &&
+                       (pszData[nPos] == ' ' || pszData[nPos] == '\n'
+                        || pszData[nPos] == '\r' || pszData[nPos] == '\t' ) )
+                    nPos++;
 
                 if (nPos == nLength)
                     break;
@@ -395,20 +399,20 @@ void XMLCALL KML::endElement(void* pUserData, const char* pszName)
             // content as such?
             while(nPos < nLength)
             {
-                char ch = pszData[nPos];
-                if (bLineStart && (ch == ' ' || ch == '\t' || ch == '\n' ||
-                                   ch == '\r'))
+                const char ch = pszData[nPos];
+                if( bLineStart && (ch == ' ' || ch == '\t' || ch == '\n' ||
+                                   ch == '\r') )
                     nLineStartPos ++;
-                else if (ch == '\n' || ch == '\r')
+                else if( ch == '\n' || ch == '\r' )
                 {
-                    if (!bLineStart)
+                    if( !bLineStart )
                     {
                         std::string sTmp( pszData + nLineStartPos,
                                           nPos - nLineStartPos);
-                        if (sDataWithoutNL.size() > 0)
+                        if( !sDataWithoutNL.empty() )
                             sDataWithoutNL += " ";
                         sDataWithoutNL += sTmp;
-                        bLineStart = TRUE;
+                        bLineStart = true;
                     }
                     nLineStartPos = nPos + 1;
                 }
@@ -416,16 +420,16 @@ void XMLCALL KML::endElement(void* pUserData, const char* pszName)
                 {
                     bLineStart = false;
                 }
-                nPos ++;
+                nPos++;
             }
 
-            if (nLineStartPos > 0)
+            if( nLineStartPos > 0 )
             {
                 if (nLineStartPos < nPos)
                 {
                     std::string sTmp( pszData + nLineStartPos,
                                       nPos - nLineStartPos);
-                    if (sDataWithoutNL.size() > 0)
+                    if( !sDataWithoutNL.empty() )
                         sDataWithoutNL += " ";
                     sDataWithoutNL += sTmp;
                 }
@@ -575,7 +579,7 @@ int KML::getNumLayers() const
 }
 
 bool KML::selectLayer(int nNum) {
-    if(this->nNumLayers_ < 1 || nNum >= this->nNumLayers_)
+    if( nNumLayers_ < 1 || nNum >= nNumLayers_ )
         return false;
     poCurrent_ = papoLayers_[nNum];
     return true;
diff --git a/ogr/ogrsf_frmts/kml/kml.h b/ogr/ogrsf_frmts/kml/kml.h
index 7bcebbf..26764ee 100644
--- a/ogr/ogrsf_frmts/kml/kml.h
+++ b/ogr/ogrsf_frmts/kml/kml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kml.h 34104 2016-04-25 17:17:20Z rouault $
+ * $Id: kml.h 35911 2016-10-24 15:03:26Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Class for reading, parsing and handling a kmlfile.
@@ -51,7 +51,6 @@ namespace std
 
 class KMLNode;
 
-
 typedef enum
 {
     KML_VALIDITY_UNKNOWN,
@@ -62,26 +61,26 @@ typedef enum
 class KML
 {
 public:
-	KML();
-	virtual ~KML();
-	bool open(const char* pszFilename);
-	bool isValid();
-	bool isHandled(std::string const& elem) const;
-	virtual bool isLeaf(std::string const& elem) const;
-	virtual bool isFeature(std::string const& elem) const;
-	virtual bool isFeatureContainer(std::string const& elem) const;
-	virtual bool isContainer(std::string const& elem) const;
-	virtual bool isRest(std::string const& elem) const;
+    KML();
+    virtual ~KML();
+    bool open(const char* pszFilename);
+    bool isValid();
+    bool isHandled(std::string const& elem) const;
+    virtual bool isLeaf(std::string const& elem) const;
+    virtual bool isFeature(std::string const& elem) const;
+    virtual bool isFeatureContainer(std::string const& elem) const;
+    virtual bool isContainer(std::string const& elem) const;
+    virtual bool isRest(std::string const& elem) const;
     virtual void findLayers(KMLNode* poNode, int bKeepEmptyContainers);
 
     bool hasOnlyEmpty() const;
 
-	void parse();
-	void print(unsigned short what = 3);
+    void parse();
+    void print(unsigned short what = 3);
     std::string getError() const;
-	int classifyNodes();
-	void eliminateEmpty();
-	int getNumLayers() const;
+    int classifyNodes();
+    void eliminateEmpty();
+    int getNumLayers() const;
     bool selectLayer(int);
     std::string getCurrentName() const;
     Nodetype getCurrentType() const;
@@ -92,38 +91,37 @@ public:
     void unregisterLayerIfMatchingThisNode(KMLNode* poNode);
 
 protected:
-	void checkValidity();
+    void checkValidity();
 
-	static void XMLCALL startElement(void *, const char *, const char **);
-	static void XMLCALL startElementValidate(void *, const char *, const char **);
-	static void XMLCALL dataHandler(void *, const char *, int);
-        static void XMLCALL dataHandlerValidate(void *, const char *, int);
-	static void XMLCALL endElement(void *, const char *);
+    static void XMLCALL startElement(void *, const char *, const char **);
+    static void XMLCALL startElementValidate(void *, const char *, const char **);
+    static void XMLCALL dataHandler(void *, const char *, int);
+    static void XMLCALL dataHandlerValidate(void *, const char *, int);
+    static void XMLCALL endElement(void *, const char *);
 
-	// trunk of KMLnodes
-	KMLNode* poTrunk_;
-	// number of layers;
-	int nNumLayers_;
-        KMLNode** papoLayers_;
+    // Trunk of KMLnodes.
+    KMLNode* poTrunk_;
+    // Number of layers.
+    int nNumLayers_;
+    KMLNode** papoLayers_;
 
 private:
-	// depth of the DOM
-	unsigned int nDepth_;
-	// KML version number
-	std::string sVersion_;
-	// set to KML_VALIDITY_VALID if the beginning of the file is detected as KML
-	OGRKMLValidity validity;
-	// file descriptor
-	VSILFILE *pKMLFile_;
-	// error text ("" when everything is OK")
-	std::string sError_;
-	// current KMLNode
-	KMLNode *poCurrent_;
-
-        XML_Parser oCurrentParser;
-        int nDataHandlerCounter;
-        int nWithoutEventCounter;
+    // Depth of the DOM.
+    unsigned int nDepth_;
+    // KML version number.
+    std::string sVersion_;
+    // Set to KML_VALIDITY_VALID if the beginning of the file is detected as KML
+    OGRKMLValidity validity;
+    // File descriptor.
+    VSILFILE *pKMLFile_;
+    // Error text ("" when everything is OK").
+    std::string sError_;
+    // Current KMLNode.
+    KMLNode *poCurrent_;
+
+    XML_Parser oCurrentParser;
+    int nDataHandlerCounter;
+    int nWithoutEventCounter;
 };
 
 #endif /* OGR_KML_KML_H_INCLUDED */
-
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.cpp b/ogr/ogrsf_frmts/kml/kmlnode.cpp
index b0d63f3..8b476d4 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.cpp
+++ b/ogr/ogrsf_frmts/kml/kmlnode.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: kmlnode.cpp 34104 2016-04-25 17:17:20Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for building up the node structure of the kml file.
@@ -29,10 +28,12 @@
  ****************************************************************************/
 #include "kmlnode.h"
 #include "cpl_conv.h"
-// std
+
 #include <string>
 #include <vector>
 
+CPL_CVSID("$Id: kmlnode.cpp 36981 2016-12-20 19:46:41Z rouault $");
+
 /************************************************************************/
 /*                           Help functions                             */
 /************************************************************************/
@@ -95,12 +96,12 @@ Coordinate* ParseCoordinate(std::string const& text)
     // Z coordinate
     if(pszStr[pos - 1] != ',')
     {
-        psTmp->bHasZ = FALSE;
+        psTmp->bHasZ = false;
         psTmp->dfAltitude = 0;
         return psTmp;
     }
 
-    psTmp->bHasZ = TRUE;
+    psTmp->bHasZ = true;
     psTmp->dfAltitude = CPLAtof(pszStr + pos);
 
     return psTmp;
@@ -253,8 +254,9 @@ int KMLNode::classify(KML* poKML, int nRecLevel)
         eType_ = Empty;
     else if(sName_.compare("coordinates") == 0)
     {
-        unsigned int nCountP;
-        for(nCountP = 0; nCountP < pvsContent_->size(); nCountP++)
+        for( unsigned int nCountP = 0;
+             nCountP < pvsContent_->size();
+             nCountP++ )
         {
             const char* pszCoord = (*pvsContent_)[nCountP].c_str();
             int nComma = 0;
@@ -434,7 +436,7 @@ void KMLNode::addContent(std::string const& text)
 
 void KMLNode::appendContent(std::string const& text)
 {
-    std::string& tmp = (*pvsContent_)[pvsContent_->size() - 1];
+    std::string& tmp = pvsContent_->back();
     tmp += text;
 }
 
@@ -543,7 +545,7 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
                     psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
                     if(psCoord != NULL)
                     {
-                        if (psCoord->bHasZ)
+                        if( psCoord->bHasZ )
                             poGeom = new OGRPoint(psCoord->dfLongitude,
                                                   psCoord->dfLatitude,
                                                   psCoord->dfAltitude);
@@ -574,7 +576,7 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
                     psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
                     if(psCoord != NULL)
                     {
-                        if (psCoord->bHasZ)
+                        if( psCoord->bHasZ )
                             ((OGRLineString*)poGeom)->addPoint(psCoord->dfLongitude,
                                                                psCoord->dfLatitude,
                                                                psCoord->dfAltitude);
@@ -596,7 +598,7 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
         for(unsigned int nCount = 0; nCount < pvpoChildren_->size(); nCount++)
         {
             if((*pvpoChildren_)[nCount]->sName_.compare("outerBoundaryIs") == 0 &&
-               (*pvpoChildren_)[nCount]->pvpoChildren_->size() > 0)
+               !(*pvpoChildren_)[nCount]->pvpoChildren_->empty())
             {
                 poCoor = (*(*pvpoChildren_)[nCount]->pvpoChildren_)[0];
             }
@@ -626,7 +628,7 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
                         {
                             poLinearRing = new OGRLinearRing();
                         }
-                        if (psCoord->bHasZ)
+                        if( psCoord->bHasZ )
                             poLinearRing->addPoint(psCoord->dfLongitude,
                                                    psCoord->dfLatitude,
                                                    psCoord->dfAltitude);
@@ -661,7 +663,7 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
                     ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
                 poLinearRing = NULL;
 
-                if ((*pvpoChildren_)[nCount2]->pvpoChildren_->size() == 0)
+                if ((*pvpoChildren_)[nCount2]->pvpoChildren_->empty())
                     continue;
 
                 poLinearRing = new OGRLinearRing();
@@ -681,7 +683,7 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
                             psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]->pvsContent_)[nCountP]);
                             if(psCoord != NULL)
                             {
-                                if (psCoord->bHasZ)
+                                if( psCoord->bHasZ )
                                     poLinearRing->addPoint(psCoord->dfLongitude,
                                                         psCoord->dfLatitude,
                                                         psCoord->dfAltitude);
@@ -723,18 +725,18 @@ OGRGeometry* KMLNode::getGeometry(Nodetype eType)
 
 Feature* KMLNode::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
 {
-    if(nNum >= this->getNumFeatures())
+    if( nNum >= getNumFeatures() )
         return NULL;
 
-    unsigned int nCount;
+    unsigned int nCount = 0;
     unsigned int nCountP = 0;
     KMLNode* poFeat = NULL;
     KMLNode* poTemp = NULL;
 
     if (nLastAsked + 1 != static_cast<int>(nNum ))
     {
-        nCount = 0;
-        nCountP = 0;
+        // nCount = 0;
+        // nCountP = 0;
     }
     else
     {
diff --git a/ogr/ogrsf_frmts/kml/kmlnode.h b/ogr/ogrsf_frmts/kml/kmlnode.h
index 3e143a4..c185edc 100644
--- a/ogr/ogrsf_frmts/kml/kmlnode.h
+++ b/ogr/ogrsf_frmts/kml/kmlnode.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlnode.h 32872 2016-01-09 10:16:42Z goatbar $
+ * $Id: kmlnode.h 36411 2016-11-21 22:03:48Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Class for building up the node structure of the kml file.
@@ -41,6 +41,7 @@ std::string Nodetype2String(Nodetype const& type);
 
 class KMLNode
 {
+    CPL_DISALLOW_COPY_ASSIGN( KMLNode );
 public:
 
     KMLNode();
diff --git a/ogr/ogrsf_frmts/kml/kmlutility.h b/ogr/ogrsf_frmts/kml/kmlutility.h
index b875a6e..db63014 100644
--- a/ogr/ogrsf_frmts/kml/kmlutility.h
+++ b/ogr/ogrsf_frmts/kml/kmlutility.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlutility.h 33339 2016-02-03 11:48:06Z rouault $
+ * $Id: kmlutility.h 35516 2016-09-25 14:49:04Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  KML driver utilities
@@ -54,10 +54,13 @@ struct Coordinate
     double dfLongitude;
     double dfLatitude;
     double dfAltitude;
-    int    bHasZ;
+    bool   bHasZ;
 
-    Coordinate()
-        : dfLongitude(0), dfLatitude(0), dfAltitude(0), bHasZ(FALSE)
+    Coordinate() :
+        dfLongitude(0),
+        dfLatitude(0),
+        dfAltitude(0),
+        bHasZ(false)
     {}
 };
 
diff --git a/ogr/ogrsf_frmts/kml/kmlvector.cpp b/ogr/ogrsf_frmts/kml/kmlvector.cpp
index 0da556b..b0d46a0 100644
--- a/ogr/ogrsf_frmts/kml/kmlvector.cpp
+++ b/ogr/ogrsf_frmts/kml/kmlvector.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: kmlvector.cpp 32872 2016-01-09 10:16:42Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Specialization of the kml class, only for vectors in kml files.
@@ -33,6 +32,8 @@
 
 #include <string>
 
+CPL_CVSID("$Id: kmlvector.cpp 34717 2016-07-19 15:29:22Z goatbar $");
+
 KMLVector::~KMLVector() {}
 
 bool KMLVector::isLeaf(std::string const& sIn) const
@@ -141,4 +142,3 @@ void KMLVector::findLayers(KMLNode* poNode, int bKeepEmptyContainers)
             print();
     }
 }
-
diff --git a/ogr/ogrsf_frmts/kml/kmlvector.h b/ogr/ogrsf_frmts/kml/kmlvector.h
index a5c3f5e..34cae84 100644
--- a/ogr/ogrsf_frmts/kml/kmlvector.h
+++ b/ogr/ogrsf_frmts/kml/kmlvector.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: kmlvector.h 23978 2012-02-14 20:42:34Z rouault $
+ * $Id: kmlvector.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Specialization of the kml class, only for vectors in kml files.
@@ -40,12 +40,12 @@ public:
     ~KMLVector();
 
     // Container - FeatureContainer - Feature
-    bool isFeature(std::string const& sIn) const;
-    bool isFeatureContainer(std::string const& sIn) const;
-    bool isContainer(std::string const& sIn) const;
-    bool isLeaf(std::string const& sIn) const;
-    bool isRest(std::string const& sIn) const;
-    void findLayers(KMLNode* poNode, int bKeepEmptyContainers);
+    bool isFeature(std::string const& sIn) const override;
+    bool isFeatureContainer(std::string const& sIn) const override;
+    bool isContainer(std::string const& sIn) const override;
+    bool isLeaf(std::string const& sIn) const override;
+    bool isRest(std::string const& sIn) const override;
+    void findLayers(KMLNode* poNode, int bKeepEmptyContainers) override;
 };
 
 #endif /* OGR_KMLVECTOR_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp b/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
index 9fdaf28..7c8399e 100644
--- a/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
+++ b/ogr/ogrsf_frmts/kml/ogr2kmlgeometry.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr2kmlgeometry.cpp 32879 2016-01-09 12:45:12Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGR -> KML geometries writer.
@@ -35,6 +34,9 @@
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
+#include <algorithm>
+
+CPL_CVSID("$Id: ogr2kmlgeometry.cpp 36017 2016-10-29 04:27:08Z goatbar $");
 
 static const double EPSILON = 1e-8;
 
@@ -43,7 +45,7 @@ static const double EPSILON = 1e-8;
 /************************************************************************/
 
 static void MakeKMLCoordinate( char *pszTarget, size_t nTargetLen,
-                               double x, double y, double z, int b3D )
+                               double x, double y, double z, bool b3D )
 
 {
     if (y < -90 || y > 90)
@@ -150,7 +152,7 @@ static void _GrowBuffer( size_t nNeeded, char **ppszText, size_t *pnMaxLength )
 {
     if( nNeeded+1 >= *pnMaxLength )
     {
-        *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
+        *pnMaxLength = std::max(*pnMaxLength * 2, nNeeded + 1);
         *ppszText = static_cast<char *>( CPLRealloc(*ppszText, *pnMaxLength) );
     }
 }
@@ -171,7 +173,6 @@ static void AppendString( char **ppszText, size_t *pnLength,
     *pnLength += strlen( *ppszText + *pnLength );
 }
 
-
 /************************************************************************/
 /*                        AppendCoordinateList()                        */
 /************************************************************************/
@@ -239,7 +240,7 @@ static bool OGR2KMLGeometryAppend( OGRGeometry *poGeometry,
         {
             char szCoordinate[256] = { 0 };
             MakeKMLCoordinate( szCoordinate, sizeof(szCoordinate),
-                            poPoint->getX(), poPoint->getY(), 0.0, FALSE );
+                               poPoint->getX(), poPoint->getY(), 0.0, false );
 
             _GrowBuffer( *pnLength + strlen(szCoordinate) + 60,
                          ppszText, pnMaxLength );
@@ -441,7 +442,7 @@ CPLXMLNode* OGR_G_ExportEnvelopeToKMLTree( OGRGeometryH hGeometry )
 
     char szCoordinate[256] = { 0 };
     MakeKMLCoordinate( szCoordinate, sEnvelope.MinX, sEnvelope.MinY, 0.0,
-                       FALSE );
+                       false );
     char* pszY = strstr(szCoordinate,",") + 1;
     pszY[-1] = '\0';
 
@@ -454,7 +455,7 @@ CPLXMLNode* OGR_G_ExportEnvelopeToKMLTree( OGRGeometryH hGeometry )
     psCoord = CPLCreateXMLNode( psBox, CXT_Element, "coord" );
 
     MakeKMLCoordinate( szCoordinate, sEnvelope.MaxX, sEnvelope.MaxY, 0.0,
-                       FALSE );
+                       false );
     pszY = strstr(szCoordinate,",") + 1;
     pszY[-1] = '\0';
 
diff --git a/ogr/ogrsf_frmts/kml/ogr_kml.h b/ogr/ogrsf_frmts/kml/ogr_kml.h
index 5f9ea11..f7e5d5f 100644
--- a/ogr/ogrsf_frmts/kml/ogr_kml.h
+++ b/ogr/ogrsf_frmts/kml/ogr_kml.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_kml.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_kml.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  KML Driver
  * Purpose:  Declarations for OGR wrapper classes for KML, and OGR->KML
@@ -47,8 +47,7 @@ class OGRKMLDataSource;
 
 class OGRKMLLayer : public OGRLayer
 {
-public:
-
+  public:
     OGRKMLLayer( const char* pszName_,
                  OGRSpatialReference* poSRS,
                  bool bWriter,
@@ -59,13 +58,13 @@ public:
     //
     // OGRLayer Interface
     //
-    OGRFeatureDefn* GetLayerDefn();
-    OGRErr ICreateFeature( OGRFeature* poFeature );
-    OGRErr CreateField( OGRFieldDefn* poField, int bApproxOK = TRUE );
-    void ResetReading();
-    OGRFeature* GetNextFeature();
-    GIntBig GetFeatureCount( int bForce = TRUE );
-    int TestCapability( const char* pszCap );
+    OGRFeatureDefn* GetLayerDefn() override;
+    OGRErr ICreateFeature( OGRFeature* poFeature ) override;
+    OGRErr CreateField( OGRFieldDefn* poField, int bApproxOK = TRUE ) override;
+    void ResetReading() override;
+    OGRFeature* GetNextFeature() override;
+    GIntBig GetFeatureCount( int bForce = TRUE ) override;
+    int TestCapability( const char* pszCap ) override;
 
     //
     // OGRKMLLayer Interface
@@ -76,12 +75,12 @@ public:
 
     CPLString WriteSchema();
 
-private:
+  private:
     friend class OGRKMLDataSource;
 
     OGRKMLDataSource* poDS_;
     OGRSpatialReference* poSRS_;
-	OGRCoordinateTransformation *poCT_;
+    OGRCoordinateTransformation *poCT_;
 
     OGRFeatureDefn* poFeatureDefn_;
 
@@ -104,7 +103,7 @@ private:
 
 class OGRKMLDataSource : public OGRDataSource
 {
-public:
+  public:
     OGRKMLDataSource();
     ~OGRKMLDataSource();
 
@@ -112,14 +111,14 @@ public:
     // OGRDataSource Interface
     //
     int Open( const char* pszName, int bTestOpen );
-    const char* GetName() { return pszName_; }
-    int GetLayerCount() { return nLayers_; }
-    OGRLayer* GetLayer( int nLayer );
+    const char* GetName() override { return pszName_; }
+    int GetLayerCount() override { return nLayers_; }
+    OGRLayer* GetLayer( int nLayer ) override;
     OGRLayer* ICreateLayer( const char* pszName,
                            OGRSpatialReference* poSRS = NULL,
                            OGRwkbGeometryType eGType = wkbUnknown,
-                           char** papszOptions = NULL );
-    int TestCapability( const char* pszCap );
+                           char** papszOptions = NULL ) override;
+    int TestCapability( const char* pszCap ) override;
 
     //
     // OGRKMLDataSource Interface
@@ -134,11 +133,10 @@ public:
     KML* GetKMLFile() { return poKMLFile_; };
 #endif
 
-	bool IsFirstCTError() const { return !bIssuedCTError_; }
-	void IssuedFirstCTError() { bIssuedCTError_ = true; }
-
-private:
+    bool IsFirstCTError() const { return !bIssuedCTError_; }
+    void IssuedFirstCTError() { bIssuedCTError_ = true; }
 
+  private:
 #ifdef HAVE_EXPAT
     KML* poKMLFile_;
 #endif
@@ -148,22 +146,22 @@ private:
     OGRKMLLayer** papoLayers_;
     int nLayers_;
 
-    //The name of the field to use for the KML name element
+    // The name of the field to use for the KML name element.
     char* pszNameField_;
     char* pszDescriptionField_;
 
-    //The KML altitude mode to use
- 	char* pszAltitudeMode_;
+    // The KML altitude mode to use.
+    char* pszAltitudeMode_;
 
     char** papszCreateOptions_;
 
-    // output related parameters
+    // Output related parameters.
     VSILFILE* fpOutput_;
 
     OGREnvelope oEnvelope_;
 
-	//Have we issued a coordinate transformation already for this datasource
-	bool bIssuedCTError_;
+    // Have we issued a coordinate transformation already for this datasource.
+    bool bIssuedCTError_;
 };
 
 #endif /* OGR_KML_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp b/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
index 81d3116..01d621e 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmldatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrkmldatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLDataSource class.
@@ -30,33 +29,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 #include "ogr_kml.h"
+
 #include "cpl_conv.h"
-#include "cpl_string.h"
 #include "cpl_error.h"
 #include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "cpl_vsi_error.h"
+
+CPL_CVSID("$Id: ogrkmldatasource.cpp 37108 2017-01-12 10:16:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRKMLDataSource()                           */
 /************************************************************************/
 
-OGRKMLDataSource::OGRKMLDataSource()
-{
-    pszName_ = NULL;
-    pszNameField_ = NULL;
-    pszDescriptionField_ = NULL;
-    pszAltitudeMode_ = NULL;
-    papoLayers_ = NULL;
-    nLayers_ = 0;
-
-    fpOutput_ = NULL;
-
-    papszCreateOptions_ = NULL;
-
-	bIssuedCTError_ = false;
-
+OGRKMLDataSource::OGRKMLDataSource() :
 #ifdef HAVE_EXPAT
-    poKMLFile_ = NULL;
+    poKMLFile_(NULL),
 #endif
+    pszName_(NULL),
+    papoLayers_(NULL),
+    nLayers_(0),
+    pszNameField_(NULL),
+    pszDescriptionField_(NULL),
+    pszAltitudeMode_(NULL),
+    papszCreateOptions_(NULL),
+    fpOutput_(NULL),
+    bIssuedCTError_(false)
+{
 }
 
 /************************************************************************/
@@ -71,17 +70,19 @@ OGRKMLDataSource::~OGRKMLDataSource()
         {
             if( nLayers_ == 1 && papoLayers_[0]->nWroteFeatureCount_ == 0 )
             {
-                VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n", papoLayers_[0]->GetName() );
+                VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n",
+                             papoLayers_[0]->GetName() );
             }
 
             VSIFPrintfL( fpOutput_, "%s", "</Folder>\n");
 
             for( int i = 0; i < nLayers_; i++ )
             {
-                if( !(papoLayers_[i]->bSchemaWritten_) && papoLayers_[i]->nWroteFeatureCount_ != 0 )
+                if( !(papoLayers_[i]->bSchemaWritten_) &&
+                    papoLayers_[i]->nWroteFeatureCount_ != 0 )
                 {
                     CPLString osRet = papoLayers_[i]->WriteSchema();
-                    if( osRet.size() )
+                    if( !osRet.empty() )
                         VSIFPrintfL( fpOutput_, "%s", osRet.c_str() );
                 }
             }
@@ -118,10 +119,6 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
 {
     CPLAssert( NULL != pszNewName );
 
-    int nCount = 0;
-    OGRKMLLayer *poLayer = NULL;
-    OGRwkbGeometryType poGeotype;
-
 /* -------------------------------------------------------------------- */
 /*      Create a KML object and open the source file.                   */
 /* -------------------------------------------------------------------- */
@@ -161,13 +158,12 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
         return FALSE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Eliminate the empty containers (if there is at least one        */
 /*      valid container !)                                              */
 /* -------------------------------------------------------------------- */
-    int bHasOnlyEmpty = poKMLFile_->hasOnlyEmpty();
-    if (bHasOnlyEmpty)
+    const bool bHasOnlyEmpty = poKMLFile_->hasOnlyEmpty();
+    if( bHasOnlyEmpty )
         CPLDebug("KML", "Has only empty containers");
     else
         poKMLFile_->eliminateEmpty();
@@ -188,8 +184,8 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
 /* -------------------------------------------------------------------- */
 /*      Allocate memory for the Layers                                  */
 /* -------------------------------------------------------------------- */
-    papoLayers_ = (OGRKMLLayer **)
-        CPLMalloc( sizeof(OGRKMLLayer *) * nLayers_ );
+    papoLayers_ = static_cast<OGRKMLLayer **>(
+        CPLMalloc( sizeof(OGRKMLLayer *) * nLayers_ ));
 
     OGRSpatialReference *poSRS = new OGRSpatialReference("GEOGCS[\"WGS 84\", "
         "   DATUM[\"WGS_1984\","
@@ -205,7 +201,7 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
 /* -------------------------------------------------------------------- */
 /*      Create the Layers and fill them                                 */
 /* -------------------------------------------------------------------- */
-    for( nCount = 0; nCount < nLayers_; nCount++ )
+    for( int nCount = 0; nCount < nLayers_; nCount++ )
     {
         if( !poKMLFile_->selectLayer(nCount) )
         {
@@ -214,6 +210,7 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
             break;
         }
 
+        OGRwkbGeometryType poGeotype = wkbUnknown;
         if( poKMLFile_->getCurrentType() == Point )
             poGeotype = wkbPoint;
         else if( poKMLFile_->getCurrentType() == LineString )
@@ -228,8 +225,6 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
             poGeotype = wkbMultiPolygon;
         else if( poKMLFile_->getCurrentType() == MultiGeometry )
             poGeotype = wkbGeometryCollection;
-        else
-            poGeotype = wkbUnknown;
 
         if (poGeotype != wkbUnknown && poKMLFile_->is25D())
             poGeotype = wkbSetZ(poGeotype);
@@ -244,7 +239,8 @@ int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
             sName.Printf( "Layer #%d", nCount );
         }
 
-        poLayer = new OGRKMLLayer( sName.c_str(), poSRS, false, poGeotype, this );
+        OGRKMLLayer *poLayer =
+            new OGRKMLLayer( sName.c_str(), poSRS, false, poGeotype, this );
 
         poLayer->SetLayerNumber( nCount );
 
@@ -270,27 +266,28 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
 
     if( fpOutput_ != NULL )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return FALSE;
     }
 
-    if (CSLFetchNameValue(papszOptions, "NameField"))
+    if( CSLFetchNameValue(papszOptions, "NameField") )
         pszNameField_ = CPLStrdup(CSLFetchNameValue(papszOptions, "NameField"));
     else
         pszNameField_ = CPLStrdup("Name");
 
-    if (CSLFetchNameValue(papszOptions, "DescriptionField"))
-        pszDescriptionField_ = CPLStrdup(CSLFetchNameValue(papszOptions, "DescriptionField"));
+    if( CSLFetchNameValue(papszOptions, "DescriptionField") )
+        pszDescriptionField_ =
+            CPLStrdup(CSLFetchNameValue(papszOptions, "DescriptionField"));
     else
         pszDescriptionField_ = CPLStrdup("Description");
 
     pszAltitudeMode_ = CPLStrdup(CSLFetchNameValue(papszOptions, "AltitudeMode"));
-    if( (NULL != pszAltitudeMode_) && strlen(pszAltitudeMode_) > 0)
+    if( (NULL != pszAltitudeMode_) && strlen(pszAltitudeMode_) > 0 )
     {
         //Check to see that the specified AltitudeMode is valid
         if ( EQUAL(pszAltitudeMode_, "clampToGround")
              || EQUAL(pszAltitudeMode_, "relativeToGround")
-             || EQUAL(pszAltitudeMode_, "absolute"))
+             || EQUAL(pszAltitudeMode_, "absolute") )
         {
             CPLDebug("KML", "Using '%s' for AltitudeMode", pszAltitudeMode_);
         }
@@ -298,7 +295,8 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
         {
             CPLFree( pszAltitudeMode_ );
             pszAltitudeMode_ = NULL;
-            CPLError( CE_Warning, CPLE_AppDefined, "Invalide AltitideMode specified, ignoring" );
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Invalide AltitideMode specified, ignoring" );
         }
     }
     else
@@ -311,16 +309,17 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
 /*      Create the output file.                                         */
 /* -------------------------------------------------------------------- */
 
-    if (strcmp(pszName, "/dev/stdout") == 0)
+    if( strcmp(pszName, "/dev/stdout") == 0 )
         pszName = "/vsistdout/";
 
     pszName_ = CPLStrdup( pszName );
 
-    fpOutput_ = VSIFOpenL( pszName, "wb" );
+    fpOutput_ = VSIFOpenExL( pszName, "wb", true );
     if( fpOutput_ == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to create KML file %s.", pszName );
+                  "Failed to create KML file %s: %s", pszName,
+                  VSIGetLastErrorMsg() );
         return FALSE;
     }
 
@@ -329,7 +328,10 @@ int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
 /* -------------------------------------------------------------------- */
     VSIFPrintfL( fpOutput_, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" );
 
-    VSIFPrintfL( fpOutput_, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document id=\"root_doc\">\n" );
+    VSIFPrintfL( fpOutput_,
+                 "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n"
+                 "<Document id=\"%s\">\n",
+                 CSLFetchNameValueDef(papszOptions, "DOCUMENT_ID", "root_doc") );
 
     return TRUE;
 }
@@ -342,7 +344,7 @@ OGRLayer *
 OGRKMLDataSource::ICreateLayer( const char * pszLayerName,
                                 OGRSpatialReference *poSRS,
                                 OGRwkbGeometryType eType,
-                                CPL_UNUSED char ** papszOptions )
+                                char ** /* papszOptions */ )
 {
     CPLAssert( NULL != pszLayerName);
 
@@ -352,8 +354,8 @@ OGRKMLDataSource::ICreateLayer( const char * pszLayerName,
     if( fpOutput_ == NULL )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
-                  "Data source %s opened for read access.\n"
-                  "New layer %s cannot be created.\n",
+                  "Data source %s opened for read access.  "
+                  "New layer %s cannot be created.",
                   pszName_, pszLayerName );
 
         return NULL;
@@ -362,15 +364,16 @@ OGRKMLDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Close the previous layer (if there is one open)                 */
 /* -------------------------------------------------------------------- */
-    if (GetLayerCount() > 0)
+    if( GetLayerCount() > 0 )
     {
         if( nLayers_ == 1 && papoLayers_[0]->nWroteFeatureCount_ == 0 )
         {
-            VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n", papoLayers_[0]->GetName() );
+            VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n",
+                         papoLayers_[0]->GetName() );
         }
 
-        VSIFPrintfL( fpOutput_, "</Folder>\n");
-        ((OGRKMLLayer*)papoLayers_[GetLayerCount()-1])->SetClosedForWriting();
+        VSIFPrintfL( fpOutput_, "</Folder>\n" );
+        papoLayers_[GetLayerCount()-1]->SetClosedForWriting();
     }
 
 /* -------------------------------------------------------------------- */
@@ -386,24 +389,25 @@ OGRKMLDataSource::ICreateLayer( const char * pszLayerName,
                   pszLayerName, pszCleanLayerName );
     }
 
-    if (GetLayerCount() > 0)
+    if( GetLayerCount() > 0 )
     {
-        VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n", pszCleanLayerName);
+        VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n",
+                     pszCleanLayerName );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRKMLLayer *poLayer;
-    poLayer = new OGRKMLLayer( pszCleanLayerName, poSRS, true, eType, this );
+    OGRKMLLayer *poLayer =
+        new OGRKMLLayer( pszCleanLayerName, poSRS, true, eType, this );
 
     CPLFree( pszCleanLayerName );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
-    papoLayers_ = (OGRKMLLayer **)
-        CPLRealloc( papoLayers_,  sizeof(OGRKMLLayer *) * (nLayers_+1) );
+    papoLayers_ = static_cast<OGRKMLLayer **>(
+        CPLRealloc( papoLayers_,  sizeof(OGRKMLLayer *) * (nLayers_+1) ) );
 
     papoLayers_[nLayers_++] = poLayer;
 
@@ -419,8 +423,8 @@ int OGRKMLDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap, ODsCCreateLayer) )
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -431,8 +435,8 @@ OGRLayer *OGRKMLDataSource::GetLayer( int iLayer )
 {
     if( iLayer < 0 || iLayer >= nLayers_ )
         return NULL;
-    else
-        return papoLayers_[iLayer];
+
+    return papoLayers_[iLayer];
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/kml/ogrkmldriver.cpp b/ogr/ogrsf_frmts/kml/ogrkmldriver.cpp
index 0661af3..a9431b2 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmldriver.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmldriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrkmldriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLDriver class.
@@ -29,9 +28,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "ogr_kml.h"
+
 #include "cpl_conv.h"
 #include "cpl_error.h"
-#include "ogr_kml.h"
+
+CPL_CVSID("$Id: ogrkmldriver.cpp 37108 2017-01-12 10:16:27Z rouault $");
 
 /************************************************************************/
 /*                         OGRKMLDriverIdentify()                       */
@@ -43,7 +45,9 @@ static int OGRKMLDriverIdentify( GDALOpenInfo* poOpenInfo )
     if( poOpenInfo->fpL == NULL )
         return FALSE;
 
-    return( strstr((const char*)poOpenInfo->pabyHeader, "<kml") != NULL );
+    return
+        strstr(reinterpret_cast<char *>(poOpenInfo->pabyHeader),
+               "<kml") != NULL;
 }
 
 /************************************************************************/
@@ -64,14 +68,16 @@ static GDALDataset *OGRKMLDriverOpen( GDALOpenInfo* poOpenInfo )
 
     if( poDS->Open( poOpenInfo->pszFilename, TRUE ) )
     {
-        /*if( poDS->GetLayerCount() == 0 )
+#ifdef DEBUG_VERBOSE
+        if( poDS->GetLayerCount() == 0 )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
                 "No layers in KML file: %s.", pszName );
 
             delete poDS;
             poDS = NULL;
-        }*/
+        }
+#endif
     }
     else
     {
@@ -130,6 +136,7 @@ void RegisterOGRKML()
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
+"  <Option name='DOCUMENT_ID' type='string' description='Id of the root <Document> node' default='root_doc'/>'"
 "  <Option name='GPX_USE_EXTENSIONS' type='boolean' description='Whether to write non-GPX attributes in an <extensions> tag' default='NO'/>"
 "  <Option name='NameField' type='string' description='Field to use to fill the KML <name> element' default='Name'/>"
 "  <Option name='DescriptionField' type='string' description='Field to use to fill the KML <description> element' default='Description'/>"
diff --git a/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp b/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
index 7e9d661..eb0853d 100644
--- a/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
+++ b/ogr/ogrsf_frmts/kml/ogrkmllayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrkmllayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  KML Driver
  * Purpose:  Implementation of OGRKMLLayer class.
@@ -29,12 +28,15 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "ogr_kml.h"
+
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_api.h"
-#include "ogr_kml.h"
 #include "ogr_p.h"
 
+CPL_CVSID("$Id: ogrkmllayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
 /* Function utility to dump OGRGeometry to KML text. */
 char *OGR_G_ExportToKML( OGRGeometryH hGeometry, const char* pszAltitudeMode );
 
@@ -46,43 +48,45 @@ OGRKMLLayer::OGRKMLLayer( const char * pszName,
                           OGRSpatialReference *poSRSIn, bool bWriterIn,
                           OGRwkbGeometryType eReqType,
                           OGRKMLDataSource *poDSIn ) :
-    poDS_(NULL),
-    poSRS_(NULL),
+    poDS_(poDSIn),
+    poSRS_(poSRSIn ? new OGRSpatialReference(NULL) : NULL),
     poCT_(NULL),
+    poFeatureDefn_(new OGRFeatureDefn( pszName )),
     iNextKMLId_(0),
     nTotalKMLCount_(-1),
     bWriter_(bWriterIn),
     nLayerNumber_(0),
     nWroteFeatureCount_(0),
-    bSchemaWritten_(FALSE),
+    bSchemaWritten_(false),
+    pszName_(CPLStrdup(pszName)),
     nLastAsked(-1),
     nLastCount(-1)
 {
-
-    /* KML should be created as WGS84. */
+    // KML should be created as WGS84.
     if( poSRSIn != NULL )
     {
-        poSRS_ = new OGRSpatialReference(NULL);
         poSRS_->SetWellKnownGeogCS( "WGS84" );
-        if (!poSRS_->IsSame(poSRSIn))
+        if( !poSRS_->IsSame(poSRSIn) )
         {
             poCT_ = OGRCreateCoordinateTransformation( poSRSIn, poSRS_ );
             if( poCT_ == NULL && poDSIn->IsFirstCTError() )
             {
-                /* If we can't create a transformation, issue a warning - but continue the transformation*/
+                // If we can't create a transformation, issue a warning - but
+                // continue the transformation.
                 char *pszWKT = NULL;
 
                 poSRSIn->exportToPrettyWkt( &pszWKT, FALSE );
 
-                CPLError( CE_Warning, CPLE_AppDefined,
-                        "Failed to create coordinate transformation between the\n"
-                        "input coordinate system and WGS84.  This may be because they\n"
-                        "are not transformable, or because projection services\n"
-                        "(PROJ.4 DLL/.so) could not be loaded.\n"
-                        "KML geometries may not render correctly.\n"
-                        "This message will not be issued any more. \n"
-                        "\nSource:\n%s\n",
-                        pszWKT );
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Failed to create coordinate transformation between the "
+                    "input coordinate system and WGS84.  This may be because "
+                    "they are not transformable, or because projection "
+                    "services (PROJ.4 DLL/.so) could not be loaded.  "
+                    "KML geometries may not render correctly.  "
+                    "This message will not be issued any more."
+                    "\nSource:\n%s\n",
+                    pszWKT );
 
                 CPLFree( pszWKT );
                 poDSIn->IssuedFirstCTError();
@@ -90,9 +94,6 @@ OGRKMLLayer::OGRKMLLayer( const char * pszName,
         }
     }
 
-    poDS_ = poDSIn;
-
-    poFeatureDefn_ = new OGRFeatureDefn( pszName );
     SetDescription( poFeatureDefn_->GetName() );
     poFeatureDefn_->Reference();
     poFeatureDefn_->SetGeomType( eReqType );
@@ -105,9 +106,7 @@ OGRKMLLayer::OGRKMLLayer( const char * pszName,
     OGRFieldDefn oFieldDesc( "Description", OFTString );
     poFeatureDefn_->AddFieldDefn( &oFieldDesc );
 
-    bClosedForWriting = (bWriterIn == FALSE);
-
-    pszName_ = CPLStrdup(pszName);
+    bClosedForWriting = !bWriterIn;
 }
 
 /************************************************************************/
@@ -163,50 +162,49 @@ OGRFeature *OGRKMLLayer::GetNextFeature()
     KML *poKMLFile = poDS_->GetKMLFile();
     if( poKMLFile == NULL )
         return NULL;
+
     poKMLFile->selectLayer(nLayerNumber_);
 
     while( true )
     {
-        Feature *poFeatureKML = NULL;
-        poFeatureKML = poKMLFile->getFeature(iNextKMLId_++, nLastAsked, nLastCount);
+        Feature *poFeatureKML =
+            poKMLFile->getFeature(iNextKMLId_++, nLastAsked, nLastCount);
 
-        if(poFeatureKML == NULL)
+        if( poFeatureKML == NULL )
             return NULL;
 
-        CPLAssert( poFeatureKML != NULL );
-
         OGRFeature *poFeature = new OGRFeature( poFeatureDefn_ );
 
-        if(poFeatureKML->poGeom)
+        if( poFeatureKML->poGeom )
         {
             poFeature->SetGeometryDirectly(poFeatureKML->poGeom);
             poFeatureKML->poGeom = NULL;
         }
 
-        // Add fields
-        poFeature->SetField( poFeatureDefn_->GetFieldIndex("Name"), poFeatureKML->sName.c_str() );
-        poFeature->SetField( poFeatureDefn_->GetFieldIndex("Description"), poFeatureKML->sDescription.c_str() );
+        // Add fields.
+        poFeature->SetField( poFeatureDefn_->GetFieldIndex("Name"),
+                             poFeatureKML->sName.c_str() );
+        poFeature->SetField( poFeatureDefn_->GetFieldIndex("Description"),
+                             poFeatureKML->sDescription.c_str() );
         poFeature->SetFID( iNextKMLId_ - 1 );
 
-        // Clean up
+        // Clean up.
         delete poFeatureKML;
 
-        if( poFeature->GetGeometryRef() != NULL && poSRS_ != NULL)
+        if( poFeature->GetGeometryRef() != NULL && poSRS_ != NULL )
         {
             poFeature->GetGeometryRef()->assignSpatialReference( poSRS_ );
         }
 
-        /* Check spatial/attribute filters */
-        if ((m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) &&
+        // Check spatial/attribute filters.
+        if( (m_poFilterGeom == NULL ||
+             FilterGeometry( poFeature->GetGeometryRef() ) ) &&
             (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) )
         {
-        // Return the feature
             return poFeature;
         }
-        else
-        {
-            delete poFeature;
-        }
+
+        delete poFeature;
     }
 
 #endif /* HAVE_EXPAT */
@@ -216,31 +214,24 @@ OGRFeature *OGRKMLLayer::GetNextFeature()
 /*                          GetFeatureCount()                           */
 /************************************************************************/
 
-GIntBig OGRKMLLayer::GetFeatureCount(
 #ifndef HAVE_EXPAT
-CPL_UNUSED
-#endif
-                                 int bForce
-                                 )
-{
-    int nCount = 0;
+GIntBig OGRKMLLayer::GetFeatureCount( int /* bForce */ ) { return 0; }
+#else
 
-#ifdef HAVE_EXPAT
-    if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
-    {
-        KML *poKMLFile = poDS_->GetKMLFile();
-        if( NULL != poKMLFile )
-        {
-            poKMLFile->selectLayer(nLayerNumber_);
-            nCount = poKMLFile->getNumFeatures();
-        }
-    }
-    else
+GIntBig OGRKMLLayer::GetFeatureCount( int bForce )
+{
+    if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::GetFeatureCount(bForce);
-#endif
 
-    return nCount;
+    KML *poKMLFile = poDS_->GetKMLFile();
+    if( NULL == poKMLFile )
+        return 0;
+
+    poKMLFile->selectLayer(nLayerNumber_);
+
+    return poKMLFile->getNumFeatures();
 }
+#endif
 
 /************************************************************************/
 /*                           WriteSchema()                              */
@@ -248,75 +239,79 @@ CPL_UNUSED
 
 CPLString OGRKMLLayer::WriteSchema()
 {
+    if( bSchemaWritten_ )
+        return "";
+
     CPLString osRet;
-    if ( !(bSchemaWritten_) )
+
+    OGRFeatureDefn *featureDefinition = GetLayerDefn();
+    for( int j = 0; j < featureDefinition->GetFieldCount(); j++ )
     {
-        OGRFeatureDefn *featureDefinition = GetLayerDefn();
-        for (int j=0; j < featureDefinition->GetFieldCount(); j++)
-        {
-            OGRFieldDefn *fieldDefinition = featureDefinition->GetFieldDefn(j);
+        OGRFieldDefn *fieldDefinition = featureDefinition->GetFieldDefn(j);
 
-            if (NULL != poDS_->GetNameField() &&
-                EQUAL(fieldDefinition->GetNameRef(), poDS_->GetNameField()) )
-                continue;
+        if (NULL != poDS_->GetNameField() &&
+            EQUAL(fieldDefinition->GetNameRef(), poDS_->GetNameField()) )
+            continue;
 
-            if (NULL != poDS_->GetDescriptionField() &&
-                EQUAL(fieldDefinition->GetNameRef(), poDS_->GetDescriptionField()) )
-                continue;
+        if (NULL != poDS_->GetDescriptionField() &&
+            EQUAL(fieldDefinition->GetNameRef(), poDS_->GetDescriptionField()) )
+            continue;
 
-            if( osRet.size() == 0 )
-            {
-                osRet += CPLSPrintf( "<Schema name=\"%s\" id=\"%s\">\n", pszName_, pszName_ );
-            }
+        if( osRet.empty() )
+        {
+            osRet += CPLSPrintf( "<Schema name=\"%s\" id=\"%s\">\n",
+                                 pszName_, pszName_ );
+        }
 
-            const char* pszKMLType = NULL;
-            const char* pszKMLEltName = NULL;
-            // Match the OGR type to the GDAL type
-            switch (fieldDefinition->GetType())
-            {
-              case OFTInteger:
-                pszKMLType = "int";
-                pszKMLEltName = "SimpleField";
-                break;
-              case OFTIntegerList:
-                pszKMLType = "int";
-                pszKMLEltName = "SimpleArrayField";
-                break;
-              case OFTReal:
-                pszKMLType = "float";
-                pszKMLEltName = "SimpleField";
-                break;
-              case OFTRealList:
-                pszKMLType = "float";
-                pszKMLEltName = "SimpleArrayField";
-                break;
-              case OFTString:
-                pszKMLType = "string";
-                pszKMLEltName = "SimpleField";
-                break;
-              case OFTStringList:
-                pszKMLType = "string";
-                pszKMLEltName = "SimpleArrayField";
-                break;
-                //TODO: KML doesn't handle these data types yet...
-              case OFTDate:
-              case OFTTime:
-              case OFTDateTime:
-                pszKMLType = "string";
-                pszKMLEltName = "SimpleField";
-                break;
-
-              default:
-                pszKMLType = "string";
-                pszKMLEltName = "SimpleField";
-                break;
-            }
-            osRet += CPLSPrintf( "\t<%s name=\"%s\" type=\"%s\"></%s>\n",
-                        pszKMLEltName, fieldDefinition->GetNameRef() ,pszKMLType, pszKMLEltName );
+        const char* pszKMLType = NULL;
+        const char* pszKMLEltName = NULL;
+        // Match the OGR type to the GDAL type.
+        switch (fieldDefinition->GetType())
+        {
+          case OFTInteger:
+            pszKMLType = "int";
+            pszKMLEltName = "SimpleField";
+            break;
+          case OFTIntegerList:
+            pszKMLType = "int";
+            pszKMLEltName = "SimpleArrayField";
+            break;
+          case OFTReal:
+            pszKMLType = "float";
+            pszKMLEltName = "SimpleField";
+            break;
+          case OFTRealList:
+            pszKMLType = "float";
+            pszKMLEltName = "SimpleArrayField";
+            break;
+          case OFTString:
+            pszKMLType = "string";
+            pszKMLEltName = "SimpleField";
+            break;
+          case OFTStringList:
+            pszKMLType = "string";
+            pszKMLEltName = "SimpleArrayField";
+            break;
+            //TODO: KML doesn't handle these data types yet...
+          case OFTDate:
+          case OFTTime:
+          case OFTDateTime:
+            pszKMLType = "string";
+            pszKMLEltName = "SimpleField";
+            break;
+
+          default:
+            pszKMLType = "string";
+            pszKMLEltName = "SimpleField";
+            break;
         }
-        if( osRet.size() )
-            osRet += CPLSPrintf( "%s", "</Schema>\n" );
+        osRet += CPLSPrintf( "\t<%s name=\"%s\" type=\"%s\"></%s>\n",
+                    pszKMLEltName, fieldDefinition->GetNameRef() ,pszKMLType, pszKMLEltName );
     }
+
+    if( !osRet.empty() )
+        osRet += CPLSPrintf( "%s", "</Schema>\n" );
+
     return osRet;
 }
 
@@ -334,8 +329,9 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
 
     if( bClosedForWriting )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "Interleaved feature adding to different layers is not supported");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Interleaved feature adding to different layers is not supported");
         return OGRERR_FAILURE;
     }
 
@@ -345,9 +341,9 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
     if( poDS_->GetLayerCount() == 1 && nWroteFeatureCount_ == 0 )
     {
         CPLString osRet = WriteSchema();
-        if( osRet.size() )
+        if( !osRet.empty() )
             VSIFPrintfL( fp, "%s", osRet.c_str() );
-        bSchemaWritten_ = TRUE;
+        bSchemaWritten_ = true;
 
         VSIFPrintfL( fp, "<Folder><name>%s</name>\n", pszName_);
     }
@@ -358,13 +354,15 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
         poFeature->SetFID( iNextKMLId_++ );
 
     // Find and write the name element
-    if (NULL != poDS_->GetNameField())
+    if( NULL != poDS_->GetNameField() )
     {
-        for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ )
+        for( int iField = 0;
+             iField < poFeatureDefn_->GetFieldCount();
+             iField++ )
         {
             OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField );
 
-            if( poFeature->IsFieldSet( iField )
+            if( poFeature->IsFieldSetAndNotNull( iField )
                 && EQUAL(poField->GetNameRef(), poDS_->GetNameField()) )
             {
                 const char *pszRaw = poFeature->GetFieldAsString( iField );
@@ -379,13 +377,15 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
         }
     }
 
-    if (NULL != poDS_->GetDescriptionField())
+    if( NULL != poDS_->GetDescriptionField() )
     {
-        for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ )
+        for( int iField = 0;
+             iField < poFeatureDefn_->GetFieldCount();
+             iField++ )
         {
             OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField );
 
-            if( poFeature->IsFieldSet( iField )
+            if( poFeature->IsFieldSetAndNotNull( iField )
                 && EQUAL(poField->GetNameRef(), poDS_->GetDescriptionField()) )
             {
                 const char *pszRaw = poFeature->GetFieldAsString( iField );
@@ -394,19 +394,21 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
 
                 char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
 
-                VSIFPrintfL( fp, "\t<description>%s</description>\n", pszEscaped);
+                VSIFPrintfL( fp, "\t<description>%s</description>\n",
+                             pszEscaped);
                 CPLFree( pszEscaped );
             }
         }
     }
 
     OGRwkbGeometryType eGeomType = wkbNone;
-    if (poFeature->GetGeometryRef() != NULL)
+    if( poFeature->GetGeometryRef() != NULL )
         eGeomType = wkbFlatten(poFeature->GetGeometryRef()->getGeometryType());
-    if ( wkbPolygon == eGeomType
-         || wkbMultiPolygon == eGeomType
-         || wkbLineString == eGeomType
-         || wkbMultiLineString == eGeomType )
+
+    if( wkbPolygon == eGeomType
+        || wkbMultiPolygon == eGeomType
+        || wkbLineString == eGeomType
+        || wkbMultiLineString == eGeomType )
     {
         OGRStylePen *poPen = NULL;
         OGRStyleMgr oSM;
@@ -415,8 +417,7 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
         {
             oSM.InitFromFeature( poFeature );
 
-            int i;
-            for(i=0; i<oSM.GetPartCount();i++)
+            for( int i = 0; i < oSM.GetPartCount(); i++ )
             {
                 OGRStyleTool *poTool = oSM.GetPart(i);
                 if (poTool && poTool->GetType() == OGRSTCPen )
@@ -431,8 +432,8 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
         VSIFPrintfL( fp, "\t<Style>");
         if( poPen != NULL )
         {
-            GBool  bDefault;
-            int    bHasWidth = FALSE;
+            bool bHasWidth = false;
+            GBool bDefault = FALSE;
 
             /* Require width to be returned in pixel */
             poPen->SetUnit(OGRSTUPixel);
@@ -440,10 +441,12 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
             if( bDefault )
                 fW = 1;
             else
-                bHasWidth = TRUE;
+                bHasWidth = true;
             const char* pszColor = poPen->Color(bDefault);
-            int nColorLen = static_cast<int>(CPLStrnlen(pszColor, 10));
-            if( pszColor != NULL && pszColor[0] == '#' && !bDefault && nColorLen >= 7)
+            const int nColorLen = static_cast<int>(CPLStrnlen(pszColor, 10));
+            if( pszColor != NULL &&
+                pszColor[0] == '#' &&
+                !bDefault && nColorLen >= 7)
             {
                 char acColor[9] = {0};
                 /* Order of KML color is aabbggrr, whereas OGR color is #rrggbb[aa] ! */
@@ -469,23 +472,29 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
                 VSIFPrintfL( fp, "</LineStyle>");
             }
             else
-                VSIFPrintfL( fp, "<LineStyle><color>ff0000ff</color></LineStyle>");
+            {
+                VSIFPrintfL(
+                    fp, "<LineStyle><color>ff0000ff</color></LineStyle>");
+            }
         }
         else
+        {
             VSIFPrintfL( fp, "<LineStyle><color>ff0000ff</color></LineStyle>");
+        }
         delete poPen;
-        //If we're dealing with a polygon, add a line style that will stand out a bit
+        // If we're dealing with a polygon, add a line style that will stand out
+        // a bit.
         VSIFPrintfL( fp, "<PolyStyle><fill>0</fill></PolyStyle></Style>\n" );
     }
 
-    int bHasFoundOtherField = FALSE;
+    bool bHasFoundOtherField = false;
 
     // Write all fields as SchemaData
     for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ )
     {
         OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField );
 
-        if( poFeature->IsFieldSet( iField ))
+        if( poFeature->IsFieldSetAndNotNull( iField ))
         {
             if (NULL != poDS_->GetNameField() &&
                 EQUAL(poField->GetNameRef(), poDS_->GetNameField()) )
@@ -495,17 +504,17 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
                 EQUAL(poField->GetNameRef(), poDS_->GetDescriptionField()) )
                 continue;
 
-            if (!bHasFoundOtherField)
+            if( !bHasFoundOtherField )
             {
                 VSIFPrintfL( fp, "\t<ExtendedData><SchemaData schemaUrl=\"#%s\">\n", pszName_ );
-                bHasFoundOtherField = TRUE;
+                bHasFoundOtherField = true;
             }
             const char *pszRaw = poFeature->GetFieldAsString( iField );
 
             while( *pszRaw == ' ' )
                 pszRaw++;
 
-            char *pszEscaped;
+            char *pszEscaped = NULL;
             if (poFeatureDefn_->GetFieldDefn(iField)->GetType() == OFTReal)
             {
                 pszEscaped = CPLStrdup( pszRaw );
@@ -522,7 +531,7 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
         }
     }
 
-    if (bHasFoundOtherField)
+    if( bHasFoundOtherField )
     {
         VSIFPrintfL( fp, "\t</SchemaData></ExtendedData>\n" );
     }
@@ -532,7 +541,7 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
     {
         char* pszGeometry = NULL;
         OGREnvelope sGeomBounds;
-        OGRGeometry* poWGS84Geom;
+        OGRGeometry *poWGS84Geom = NULL;
 
         if (NULL != poCT_)
         {
@@ -549,8 +558,15 @@ OGRErr OGRKMLLayer::ICreateFeature( OGRFeature* poFeature )
         pszGeometry =
             OGR_G_ExportToKML( (OGRGeometryH)poWGS84Geom,
                                poDS_->GetAltitudeMode());
-
-        VSIFPrintfL( fp, "      %s\n", pszGeometry );
+        if( pszGeometry != NULL )
+        {
+            VSIFPrintfL( fp, "      %s\n", pszGeometry );
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Export of geometry to KML failed");
+        }
         CPLFree( pszGeometry );
 
         poWGS84Geom->getEnvelope( &sGeomBounds );
diff --git a/ogr/ogrsf_frmts/libkml/GNUmakefile b/ogr/ogrsf_frmts/libkml/GNUmakefile
index bb7410c..dff4378 100644
--- a/ogr/ogrsf_frmts/libkml/GNUmakefile
+++ b/ogr/ogrsf_frmts/libkml/GNUmakefile
@@ -28,4 +28,3 @@ $(O_OBJ):	ogrlibkmlgeometry.h \
             ogrlibkmlfeaturestyle.h \
             ogrlibkmlstyle.h \
             ogr_libkml.h
-          
diff --git a/ogr/ogrsf_frmts/libkml/drv_libkml.html b/ogr/ogrsf_frmts/libkml/drv_libkml.html
index 2e4a782..1b88b02 100644
--- a/ogr/ogrsf_frmts/libkml/drv_libkml.html
+++ b/ogr/ogrsf_frmts/libkml/drv_libkml.html
@@ -91,6 +91,9 @@
     The value must follow the syntax of <a href="http://tools.ietf.org/html/rfc3966">IETF RFC 3966</a>.
   </p>
 
+  <p>Starting with GDAL 2.2, the DOCUMENT_ID datasource creation option can be
+  used to specified the id of the root <Document> node. The default value
+  is root_doc.</p>
 
     <h4>Container properties</h4>
 
@@ -782,7 +785,6 @@ Writing to /dev/stdout or /vsistdout/ is also supported.<p>
 
 #!/bin/bash
 # Copyright (c) 2010, Brian Case
- * Copyright (c) 2010-2014, Even Rouault <even dot rouault at mines-paris dot org>
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
diff --git a/ogr/ogrsf_frmts/libkml/ogr_libkml.h b/ogr/ogrsf_frmts/libkml/ogr_libkml.h
index 41d8436..0e09e0c 100644
--- a/ogr/ogrsf_frmts/libkml/ogr_libkml.h
+++ b/ogr/ogrsf_frmts/libkml/ogr_libkml.h
@@ -34,19 +34,6 @@
 
 #include "libkml_headers.h"
 
-using kmldom::KmlFactory;
-using kmldom::KmlPtr;
-using kmldom::DocumentPtr;
-using kmldom::ContainerPtr;
-using kmldom::ElementPtr;
-using kmldom::SchemaPtr;
-using kmldom::UpdatePtr;
-using kmlengine::KmzFile;
-using kmlengine::KmzFilePtr;
-
-using kmlengine::KmlFile;
-using kmlengine::KmlFilePtr;
-
 class OGRLIBKMLDataSource;
 
 CPLString OGRLIBKMLGetSanitizedNCName(const char* pszName);
@@ -58,29 +45,27 @@ CPLString OGRLIBKMLGetSanitizedNCName(const char* pszName);
 class OGRLIBKMLLayer:public OGRLayer
 {
     int                       bUpdate;
-    int                       bUpdated;
+    bool                      bUpdated;
     int                       nFeatures;
     int                       iFeature;
     long                      nFID;
     const char                *m_pszName;
     const char                *m_pszFileName;
 
-    ContainerPtr              m_poKmlLayer;
-    ElementPtr                m_poKmlLayerRoot;
-    UpdatePtr                 m_poKmlUpdate;
+    kmldom::ContainerPtr      m_poKmlLayer;
+    kmldom::ElementPtr        m_poKmlLayerRoot;
+    kmldom::UpdatePtr         m_poKmlUpdate;
 
-    DocumentPtr               m_poKmlDocument;
-    //OGRStyleTable            *m_poStyleTable;
     OGRLIBKMLDataSource      *m_poOgrDS;
     OGRFeatureDefn           *m_poOgrFeatureDefn;
-    SchemaPtr                 m_poKmlSchema;
+    kmldom::SchemaPtr         m_poKmlSchema;
     OGRSpatialReference      *m_poOgrSRS;
 
-    int                       m_bReadGroundOverlay;
-    int                       m_bUseSimpleField;
+    bool                      m_bReadGroundOverlay;
+    bool                      m_bUseSimpleField;
 
-    int                       m_bWriteRegion;
-    int                       m_bRegionBoundsAuto;
+    bool                      m_bWriteRegion;
+    bool                      m_bRegionBoundsAuto;
     double                    m_dfRegionMinLodPixels;
     double                    m_dfRegionMaxLodPixels;
     double                    m_dfRegionMinFadeExtent;
@@ -93,98 +78,99 @@ class OGRLIBKMLLayer:public OGRLayer
     CPLString                 osListStyleType;
     CPLString                 osListStyleIconHref;
 
-    int                       m_bUpdateIsFolder;
+    bool                      m_bUpdateIsFolder;
 
   public:
     OGRLIBKMLLayer            ( const char *pszLayerName,
                                 OGRSpatialReference * poSpatialRef,
                                 OGRwkbGeometryType eGType,
                                 OGRLIBKMLDataSource *poOgrDS,
-                                ElementPtr poKmlRoot,
-                                ContainerPtr poKmlContainer,
-                                UpdatePtr poKmlUpdate,
+                                kmldom::ElementPtr poKmlRoot,
+                                kmldom::ContainerPtr poKmlContainer,
+                                kmldom::UpdatePtr poKmlUpdate,
                                 const char *pszFileName,
                                 int bNew,
-                                int bUpdate);
-    ~OGRLIBKMLLayer           (  );
-
-    void                      ResetReading  (  ) { iFeature = 0; nFID = 1; };
-    OGRFeature               *GetNextFeature (  );
-    OGRFeature               *GetNextRawFeature (  );
-    OGRFeatureDefn           *GetLayerDefn (  ) { return m_poOgrFeatureDefn; };
-    //OGRErr                    SetAttributeFilter (const char * );
-    OGRErr                    ICreateFeature( OGRFeature * poOgrFeat );
-    OGRErr                    ISetFeature( OGRFeature * poOgrFeat );
-    OGRErr                    DeleteFeature( GIntBig nFID );
-
-    GIntBig                   GetFeatureCount ( int bForce = TRUE );
-    OGRErr                    GetExtent ( OGREnvelope * psExtent,
-                                          int bForce = TRUE );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+                                int bUpdate );
+    virtual ~OGRLIBKMLLayer();
+
+    void                      ResetReading() override { iFeature = 0; nFID = 1; };
+    OGRFeature               *GetNextFeature() override;
+    OGRFeature               *GetNextRawFeature();
+    OGRFeatureDefn           *GetLayerDefn() override { return m_poOgrFeatureDefn; };
+    // OGRErr                    SetAttributeFilter(const char * );
+    OGRErr                    ICreateFeature( OGRFeature * poOgrFeat ) override;
+    OGRErr                    ISetFeature( OGRFeature * poOgrFeat ) override;
+    OGRErr                    DeleteFeature( GIntBig nFID ) override;
+
+    GIntBig                   GetFeatureCount( int bForce = TRUE ) override;
+    OGRErr                    GetExtent( OGREnvelope * psExtent,
+                                         int bForce = TRUE ) override;
+    virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    //const char               *GetInfo ( const char * );
-
-    OGRErr                    CreateField ( OGRFieldDefn * poField,
-                                            int bApproxOK = TRUE );
-
-    OGRErr                    SyncToDisk (  );
-
-    OGRStyleTable            *GetStyleTable (  );
-    void                      SetStyleTableDirectly ( OGRStyleTable * poStyleTable );
-    void                      SetStyleTable ( OGRStyleTable * poStyleTable );
-    const char               *GetName(  ) { return m_pszName; };
-    int                       TestCapability ( const char * );
-    ContainerPtr              GetKmlLayer () { return m_poKmlLayer; };
-    ElementPtr                GetKmlLayerRoot () { return m_poKmlLayerRoot; };
-    SchemaPtr                 GetKmlSchema () { return m_poKmlSchema; };
-    const char               *GetFileName (  ) { return m_pszFileName; };
-
-    void                      SetLookAt(const char* pszLookatLongitude,
-                                        const char* pszLookatLatitude,
-                                        const char* pszLookatAltitude,
-                                        const char* pszLookatHeading,
-                                        const char* pszLookatTilt,
-                                        const char* pszLookatRange,
-                                        const char* pszLookatAltitudeMode);
-    void                      SetCamera(const char* pszCameraLongitude,
-                                        const char* pszCameraLatitude,
-                                        const char* pszCameraAltitude,
-                                        const char* pszCameraHeading,
-                                        const char* pszCameraTilt,
-                                        const char* pszCameraRoll,
-                                        const char* pszCameraAltitudeMode);
-
-    static CPLString          LaunderFieldNames(CPLString osName);
-
-    void                      SetWriteRegion(double dfMinLodPixels,
-                                             double dfMaxLodPixels,
-                                             double dfMinFadeExtent,
-                                             double dfMaxFadeExtent);
-    void                      SetRegionBounds(double dfMinX, double dfMinY,
-                                              double dfMaxX, double dfMaxY);
-
-    void                      SetScreenOverlay(const char* pszSOHref,
-                                               const char* pszSOName,
-                                               const char* pszSODescription,
-                                               const char* pszSOOverlayX,
-                                               const char* pszSOOverlayY,
-                                               const char* pszSOOverlayXUnits,
-                                               const char* pszSOOverlayYUnits,
-                                               const char* pszSOScreenX,
-                                               const char* pszSOScreenY,
-                                               const char* pszSOScreenXUnits,
-                                               const char* pszSOScreenYUnits,
-                                               const char* pszSOSizeX,
-                                               const char* pszSOSizeY,
-                                               const char* pszSOSizeXUnits,
-                                               const char* pszSOSizeYUnits);
-
-    void                      SetListStyle(const char* pszListStyleType,
-                                           const char* pszListStyleIconHref);
-
-    void                      Finalize(DocumentPtr poKmlDocument);
-    void                      SetUpdateIsFolder(int bUpdateIsFolder) { m_bUpdateIsFolder = bUpdateIsFolder; }
+    //const char               *GetInfo( const char * );
+
+    OGRErr                    CreateField( OGRFieldDefn * poField,
+                                           int bApproxOK = TRUE ) override;
+
+    OGRErr                    SyncToDisk() override;
+
+    OGRStyleTable            *GetStyleTable() override;
+    void                  SetStyleTableDirectly( OGRStyleTable * poStyleTable ) override;
+    void                      SetStyleTable( OGRStyleTable * poStyleTable ) override;
+    const char               *GetName() override { return m_pszName; };
+    int                       TestCapability( const char * ) override;
+    kmldom::ContainerPtr      GetKmlLayer() { return m_poKmlLayer; };
+    kmldom::ElementPtr        GetKmlLayerRoot() { return m_poKmlLayerRoot; };
+    kmldom::SchemaPtr         GetKmlSchema() { return m_poKmlSchema; };
+    const char               *GetFileName() { return m_pszFileName; };
+
+    void                      SetLookAt( const char* pszLookatLongitude,
+                                         const char* pszLookatLatitude,
+                                         const char* pszLookatAltitude,
+                                         const char* pszLookatHeading,
+                                         const char* pszLookatTilt,
+                                         const char* pszLookatRange,
+                                         const char* pszLookatAltitudeMode );
+    void                      SetCamera( const char* pszCameraLongitude,
+                                         const char* pszCameraLatitude,
+                                         const char* pszCameraAltitude,
+                                         const char* pszCameraHeading,
+                                         const char* pszCameraTilt,
+                                         const char* pszCameraRoll,
+                                         const char* pszCameraAltitudeMode );
+
+    static CPLString          LaunderFieldNames( CPLString osName );
+
+    void                      SetWriteRegion( double dfMinLodPixels,
+                                              double dfMaxLodPixels,
+                                              double dfMinFadeExtent,
+                                              double dfMaxFadeExtent );
+    void                      SetRegionBounds( double dfMinX, double dfMinY,
+                                               double dfMaxX, double dfMaxY );
+
+    void                      SetScreenOverlay( const char* pszSOHref,
+                                                const char* pszSOName,
+                                                const char* pszSODescription,
+                                                const char* pszSOOverlayX,
+                                                const char* pszSOOverlayY,
+                                                const char* pszSOOverlayXUnits,
+                                                const char* pszSOOverlayYUnits,
+                                                const char* pszSOScreenX,
+                                                const char* pszSOScreenY,
+                                                const char* pszSOScreenXUnits,
+                                                const char* pszSOScreenYUnits,
+                                                const char* pszSOSizeX,
+                                                const char* pszSOSizeY,
+                                                const char* pszSOSizeXUnits,
+                                                const char* pszSOSizeYUnits );
+
+    void                      SetListStyle( const char* pszListStyleType,
+                                            const char* pszListStyleIconHref );
+
+    void                      Finalize( kmldom::DocumentPtr poKmlDocument );
+    void                      SetUpdateIsFolder( int bUpdateIsFolder )
+        { m_bUpdateIsFolder = CPL_TO_BOOL(bUpdateIsFolder); }
 };
 
 /******************************************************************************
@@ -196,151 +182,140 @@ class OGRLIBKMLDataSource:public OGRDataSource
     char                     *pszName;
 
     /***** layers *****/
-
     OGRLIBKMLLayer          **papoLayers;
     int                       nLayers;
     int                       nAlloced;
 
-    int                       bUpdate;
-    int                       bUpdated;
+    bool                      bUpdate;
+    bool                      bUpdated;
     CPLString                 osUpdateTargetHref;
 
     char                    **m_papszOptions;
 
     /***** for kml files *****/
-    int                       m_isKml;
-    KmlPtr                    m_poKmlDSKml;
-    ContainerPtr              m_poKmlDSContainer;
-    UpdatePtr                 m_poKmlUpdate;
+    bool                      m_isKml;
+    kmldom::KmlPtr            m_poKmlDSKml;
+    kmldom::ContainerPtr      m_poKmlDSContainer;
+    kmldom::UpdatePtr         m_poKmlUpdate;
 
     /***** for kmz files *****/
-
-    int                       m_isKmz;
-    ContainerPtr              m_poKmlDocKml;
-    ElementPtr                m_poKmlDocKmlRoot;
-    ContainerPtr              m_poKmlStyleKml;
-    char               *pszStylePath;
+    bool                      m_isKmz;
+    kmldom::ContainerPtr      m_poKmlDocKml;
+    kmldom::ElementPtr        m_poKmlDocKmlRoot;
+    kmldom::ContainerPtr      m_poKmlStyleKml;
+    char                     *pszStylePath;
 
     /***** for dir *****/
-
     int                       m_isDir;
 
     /***** the kml factory *****/
-
-    KmlFactory               *m_poKmlFactory;
+    kmldom::KmlFactory       *m_poKmlFactory;
 
     /***** style table pointer *****/
+    void                      SetCommonOptions(
+        kmldom::ContainerPtr poKmlContainer,
+        char** papszOptions );
 
-    void                      SetCommonOptions(ContainerPtr poKmlContainer,
-                                               char** papszOptions);
-
-    void                      ParseDocumentOptions(KmlPtr poKml,
-                                                   DocumentPtr poKmlDocument);
+    void                      ParseDocumentOptions(
+        kmldom::KmlPtr poKml,
+        kmldom::DocumentPtr poKmlDocument );
 
   public:
-    OGRLIBKMLDataSource       ( KmlFactory *poKmlFactory );
-    ~OGRLIBKMLDataSource      (  );
-
-    const char               *GetName (  ) { return pszName; };
+    explicit OGRLIBKMLDataSource       ( kmldom::KmlFactory *poKmlFactory );
+    ~OGRLIBKMLDataSource      ();
 
-    int                       GetLayerCount (  ) { return nLayers; }
-    OGRLayer                 *GetLayer ( int );
-    OGRLayer                 *GetLayerByName ( const char * );
-    OGRErr                    DeleteLayer ( int );
+    const char               *GetName() override { return pszName; };
 
+    int                       GetLayerCount() override { return nLayers; }
+    OGRLayer                 *GetLayer( int ) override;
+    OGRLayer                 *GetLayerByName( const char * ) override;
+    OGRErr                    DeleteLayer( int ) override;
 
     OGRLayer                 *ICreateLayer( const char *pszName,
                                             OGRSpatialReference * poSpatialRef = NULL,
                                             OGRwkbGeometryType eGType = wkbUnknown,
-                                            char **papszOptions = NULL );
+                                            char **papszOptions = NULL ) override;
 
-    OGRStyleTable            *GetStyleTable (  );
-    void                      SetStyleTableDirectly ( OGRStyleTable * poStyleTable );
-    void                      SetStyleTable ( OGRStyleTable * poStyleTable );
+    OGRStyleTable            *GetStyleTable() override;
+    void                      SetStyleTableDirectly( OGRStyleTable * poStyleTable ) override;
+    void                      SetStyleTable( OGRStyleTable * poStyleTable ) override;
 
-    int                       Open ( const char *pszFilename,
+    int                       Open( const char *pszFilename,
                                      int bUpdate );
-    int                       Create ( const char *pszFilename,
-                                       char **papszOptions );
+    int                       Create( const char *pszFilename,
+                                      char **papszOptions );
 
-    void                      FlushCache (  );
-    int                       TestCapability (const char * );
+    void                      FlushCache() override;
+    int                       TestCapability(const char * ) override;
 
-    KmlFactory               *GetKmlFactory() { return m_poKmlFactory; };
+    kmldom::KmlFactory       *GetKmlFactory() { return m_poKmlFactory; };
 
-    const char               *GetStylePath() {return pszStylePath; };
-    int                       ParseIntoStyleTable ( std::string * oKmlStyleKml,
-                                                    const char *pszStylePath);
+    const char               *GetStylePath() { return pszStylePath; };
+    int                       ParseIntoStyleTable( std::string * oKmlStyleKml,
+                                                   const char *pszStylePath );
 
-    //KmzFile                  *GetKmz() { return m_poKmlKmzfile; };
+    // KmzFile                  *GetKmz() { return m_poKmlKmzfile; };
 
-    int                       IsKml() {return m_isKml;};
-    int                       IsKmz() {return m_isKmz;};
-    int                       IsDir() {return m_isDir;};
+    int                       IsKml() const { return m_isKml; };
+    int                       IsKmz() const { return m_isKmz; };
+    int                       IsDir() const { return m_isDir; };
 
-    void                      Updated() {bUpdated = TRUE;};
+    void                      Updated() { bUpdated = true; };
 
-    int                       ParseLayers ( ContainerPtr poKmlContainer,
-                                            OGRSpatialReference *poOgrSRS );
-    SchemaPtr                 FindSchema ( const char *pszSchemaUrl);
+    int                       ParseLayers( kmldom::ContainerPtr poKmlContainer,
+                                           OGRSpatialReference *poOgrSRS );
+    kmldom::SchemaPtr         FindSchema( const char *pszSchemaUrl);
 
   private:
-
     /***** methods to write out various datasource types at destroy *****/
-
     void                      WriteKml();
     void                      WriteKmz();
     void                      WriteDir();
 
     /***** methods to open various datasource types *****/
-
-    int                       OpenKmz ( const char *pszFilename,
-                                        int bUpdate );
-    int                       OpenKml ( const char *pszFilename,
-                                        int bUpdate );
-    int                       OpenDir ( const char *pszFilename,
-                                        int bUpdate );
+    int                       OpenKmz( const char *pszFilename,
+                                       int bUpdate );
+    int                       OpenKml( const char *pszFilename,
+                                       int bUpdate );
+    int                       OpenDir( const char *pszFilename,
+                                       int bUpdate );
 
     /***** methods to create various datasource types *****/
-
-    int                       CreateKml ( const char *pszFilename,
-                                          char **papszOptions );
-    int                       CreateKmz ( const char *pszFilename,
-                                          char **papszOptions );
-    int                       CreateDir ( const char *pszFilename,
-                                          char **papszOptions );
+    int                       CreateKml( const char *pszFilename,
+                                         char **papszOptions );
+    int                       CreateKmz( const char *pszFilename,
+                                         char **papszOptions );
+    int                       CreateDir( const char *pszFilename,
+                                         char **papszOptions );
 
     /***** methods to create layers on various datasource types *****/
-
-    OGRLIBKMLLayer           *CreateLayerKml ( const char *pszLayerName,
-                                               OGRSpatialReference * poOgrSRS,
-                                               OGRwkbGeometryType eGType,
-                                               char **papszOptions );
-    OGRLIBKMLLayer           *CreateLayerKmz ( const char *pszLayerName,
-                                               OGRSpatialReference * poOgrSRS,
-                                               OGRwkbGeometryType eGType,
-                                               char **papszOptions );
+    OGRLIBKMLLayer           *CreateLayerKml( const char *pszLayerName,
+                                              OGRSpatialReference * poOgrSRS,
+                                              OGRwkbGeometryType eGType,
+                                              char **papszOptions );
+    OGRLIBKMLLayer           *CreateLayerKmz( const char *pszLayerName,
+                                              OGRSpatialReference * poOgrSRS,
+                                              OGRwkbGeometryType eGType,
+                                              char **papszOptions );
 
     /***** methods to delete layers on various datasource types *****/
-
-    OGRErr                    DeleteLayerKml ( int );
-    OGRErr                    DeleteLayerKmz ( int );
+    OGRErr                    DeleteLayerKml( int );
+    OGRErr                    DeleteLayerKmz( int );
 
     /***** methods to write a styletable to various datasource types *****/
-
-    void                      SetStyleTable2Kml ( OGRStyleTable * poStyleTable );
-    void                      SetStyleTable2Kmz ( OGRStyleTable * poStyleTable );
-
-    OGRLIBKMLLayer           *AddLayer ( const char *pszLayerName,
-                                         OGRSpatialReference * poSpatialRef,
-                                         OGRwkbGeometryType eGType,
-                                         OGRLIBKMLDataSource * poOgrDS,
-                                         ElementPtr poKmlRoot,
-                                         ContainerPtr poKmlContainer,
-                                         const char *pszFileName,
-                                         int bNew,
-                                         int bUpdate,
-                                         int nGuess);
+    void                      SetStyleTable2Kml( OGRStyleTable * poStyleTable );
+    void                      SetStyleTable2Kmz( OGRStyleTable * poStyleTable );
+
+    OGRLIBKMLLayer           *AddLayer( const char *pszLayerName,
+                                        OGRSpatialReference * poSpatialRef,
+                                        OGRwkbGeometryType eGType,
+                                        OGRLIBKMLDataSource * poOgrDS,
+                                        kmldom::ElementPtr poKmlRoot,
+                                        kmldom::ContainerPtr poKmlContainer,
+                                        const char *pszFileName,
+                                        int bNew,
+                                        int bUpdate,
+                                        int nGuess);
 };
 
 #endif
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
index ac795f4..dbe0afe 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmldatasource.cpp
@@ -27,44 +27,45 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-//#include "cpl_conv.h"
-//#include "cpl_string.h"
-//#include "cpl_error.h"
-#include <iostream>
-//#include <sstream>
 #include "libkml_headers.h"
 
-using kmldom::KmlFactory;
-using kmldom::DocumentPtr;
-using kmldom::FolderPtr;
-using kmldom::FeaturePtr;
-using kmldom::NetworkLinkPtr;
-using kmldom::StyleSelectorPtr;
-using kmldom::LinkPtr;
-using kmldom::SchemaPtr;
-using kmldom::NetworkLinkControlPtr;
-using kmldom::LinkSnippetPtr;
-using kmlbase::File;
-using kmldom::KmlPtr;
-using kmldom::SnippetPtr;
-using kmlbase::Attributes;
-
+#include <string>
 #include "ogr_libkml.h"
 #include "ogrlibkmlstyle.h"
 #include "ogr_p.h"
+#include "cpl_vsi_error.h"
 
-/***** this was shamelessly swiped from the kml driver *****/
+CPL_CVSID("$Id: ogrlibkmldatasource.cpp 37108 2017-01-12 10:16:27Z rouault $");
 
-#define OGRLIBKMLSRSWKT "GEOGCS[\"WGS 84\", "\
-                        "   DATUM[\"WGS_1984\","\
-                        "     SPHEROID[\"WGS 84\",6378137,298.257223563,"\
-                        "           AUTHORITY[\"EPSG\",\"7030\"]],"\
-                        "           AUTHORITY[\"EPSG\",\"6326\"]],"\
-                        "       PRIMEM[\"Greenwich\",0,"\
-                        "           AUTHORITY[\"EPSG\",\"8901\"]],"\
-                        "       UNIT[\"degree\",0.01745329251994328,"\
-                        "           AUTHORITY[\"EPSG\",\"9122\"]],"\
-                        "           AUTHORITY[\"EPSG\",\"4326\"]]"
+using kmlbase::Attributes;
+using kmldom::ContainerPtr;
+using kmldom::DocumentPtr;
+using kmldom::ElementPtr;
+using kmldom::FeaturePtr;
+using kmldom::FolderPtr;
+using kmldom::KmlFactory;
+using kmldom::KmlPtr;
+using kmldom::LinkPtr;
+using kmldom::LinkSnippetPtr;
+using kmldom::NetworkLinkControlPtr;
+using kmldom::NetworkLinkPtr;
+using kmldom::SchemaPtr;
+using kmldom::SnippetPtr;
+using kmldom::StyleSelectorPtr;
+using kmlengine::KmzFile;
+
+// This was taken from the kml driver.
+static const char OGRLIBKMLSRSWKT[] =
+    "GEOGCS[\"WGS 84\", "
+    "   DATUM[\"WGS_1984\","
+    "     SPHEROID[\"WGS 84\",6378137,298.257223563,"
+    "           AUTHORITY[\"EPSG\",\"7030\"]],"
+    "           AUTHORITY[\"EPSG\",\"6326\"]],"
+    "       PRIMEM[\"Greenwich\",0,"
+    "           AUTHORITY[\"EPSG\",\"8901\"]],"
+    "       UNIT[\"degree\",0.01745329251994328,"
+    "           AUTHORITY[\"EPSG\",\"9122\"]],"
+    "           AUTHORITY[\"EPSG\",\"4326\"]]";
 
 /******************************************************************************
  OGRLIBKMLDataSource Constructor
@@ -75,36 +76,34 @@ using kmlbase::Attributes;
 
 ******************************************************************************/
 
-OGRLIBKMLDataSource::OGRLIBKMLDataSource ( KmlFactory * poKmlFactory ) :
+OGRLIBKMLDataSource::OGRLIBKMLDataSource( KmlFactory * poKmlFactory ) :
     pszName(NULL),
     papoLayers(NULL),
     nLayers(0),
     nAlloced(0),
-    bUpdate(FALSE),
-    bUpdated(FALSE),
+    bUpdate(false),
+    bUpdated(false),
     m_papszOptions(NULL),
-    m_isKml(FALSE),
+    m_isKml(false),
     m_poKmlDSKml(NULL),
     m_poKmlDSContainer(NULL),
     m_poKmlUpdate(NULL),
-    m_isKmz(FALSE),
+    m_isKmz(false),
     m_poKmlDocKml(NULL),
     m_poKmlDocKmlRoot(NULL),
     m_poKmlStyleKml(NULL),
-    pszStylePath(NULL),
-    m_isDir(FALSE),
+    pszStylePath(const_cast<char *>("")),
+    m_isDir(false),
     m_poKmlFactory(poKmlFactory)
-{
-    pszStylePath = (char *) "";
-}
+{}
 
 /************************************************************************/
 /*                       OGRLIBKMLPreProcessInput()                     */
 /************************************************************************/
 
-/* Substitute <snippet> by deprecated <Snippet> since libkml currently */
-/* only supports Snippet but ogckml22.xsd has deprecated it in favor of snippet */
-static void OGRLIBKMLPreProcessInput(std::string& oKml)
+// Substitute <snippet> by deprecated <Snippet> since libkml currently
+// only supports Snippet but ogckml22.xsd has deprecated it in favor of snippet.
+static void OGRLIBKMLPreProcessInput( std::string& oKml )
 {
     size_t nPos = 0;
     while( true )
@@ -128,7 +127,8 @@ static void OGRLIBKMLPreProcessInput(std::string& oKml)
 /*                       OGRLIBKMLRemoveSpaces()                        */
 /************************************************************************/
 
-static void OGRLIBKMLRemoveSpaces(std::string& oKml, const std::string& osNeedle)
+static void OGRLIBKMLRemoveSpaces(
+    std::string& oKml, const std::string& osNeedle )
 {
     size_t nPos = 0;
     while( true )
@@ -138,7 +138,7 @@ static void OGRLIBKMLRemoveSpaces(std::string& oKml, const std::string& osNeedle
         {
             break;
         }
-        size_t nPosOri = nPos;
+        const size_t nPosOri = nPos;
         nPos = oKml.find(">", nPos);
         if( nPos == std::string::npos || oKml[nPos+1] != '\n' )
         {
@@ -146,13 +146,16 @@ static void OGRLIBKMLRemoveSpaces(std::string& oKml, const std::string& osNeedle
         }
         oKml = oKml.substr(0, nPos) + ">" + oKml.substr(nPos + strlen(">\n"));
         CPLString osSpaces;
-        for(size_t nPosTmp = nPosOri - 1; oKml[nPosTmp] == ' '; nPosTmp -- )
+        for( size_t nPosTmp = nPosOri - 1; oKml[nPosTmp] == ' '; nPosTmp-- )
         {
             osSpaces += ' ';
         }
         nPos = oKml.find(osSpaces + "</" + osNeedle +">", nPos);
         if( nPos != std::string::npos )
-            oKml = oKml.substr(0, nPos) + "</" + osNeedle +">" + oKml.substr(nPos + osSpaces.size() + strlen("</>") + osNeedle.size());
+            oKml =
+                oKml.substr(0, nPos) + "</" + osNeedle +">" +
+                oKml.substr(nPos + osSpaces.size() + strlen("</>") +
+                            osNeedle.size());
         else
             break;
     }
@@ -162,17 +165,16 @@ static void OGRLIBKMLRemoveSpaces(std::string& oKml, const std::string& osNeedle
 /*                      OGRLIBKMLPostProcessOutput()                    */
 /************************************************************************/
 
-/* Substitute deprecated <Snippet> by <snippet> since libkml currently */
-/* only supports Snippet but ogckml22.xsd has deprecated it in favor of snippet */
-static void OGRLIBKMLPostProcessOutput(std::string& oKml)
+// Substitute deprecated <Snippet> by <snippet> since libkml currently
+// only supports Snippet but ogckml22.xsd has deprecated it in favor of snippet.
+static void OGRLIBKMLPostProcessOutput( std::string& oKml )
 {
-    size_t nPos = 0;
-
-    /* Manually add <?xml> node since libkml does not produce it currently */
-    /* and this is useful in some circumstances (#5407) */
+    // Manually add <?xml> node since libkml does not produce it currently
+    // and this is useful in some circumstances (#5407).
     if( !(oKml[0] == '<' && oKml[1] == '?') )
         oKml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + oKml;
 
+    size_t nPos = 0;
     while( true )
     {
         nPos = oKml.find("<Snippet>", nPos);
@@ -189,14 +191,14 @@ static void OGRLIBKMLPostProcessOutput(std::string& oKml)
         oKml[nPos+2] = 's';
     }
 
-    /* Fix indentation problems */
+    // Fix indentation problems.
     OGRLIBKMLRemoveSpaces(oKml, "snippet");
     OGRLIBKMLRemoveSpaces(oKml, "linkSnippet");
     OGRLIBKMLRemoveSpaces(oKml, "SimpleData");
 }
 
 /******************************************************************************
- method to write a single file ds .kml at ds destroy
+ Method to write a single file ds .kml at ds destroy.
 
  Args:          none
 
@@ -204,35 +206,39 @@ static void OGRLIBKMLPostProcessOutput(std::string& oKml)
 
 ******************************************************************************/
 
-void OGRLIBKMLDataSource::WriteKml (
-     )
+void OGRLIBKMLDataSource::WriteKml()
 {
     std::string oKmlFilename = pszName;
 
-    if ( m_poKmlDSContainer
-         && m_poKmlDSContainer->IsA ( kmldom::Type_Document ) ) {
-        DocumentPtr poKmlDocument = AsDocument ( m_poKmlDSContainer );
-        int iLayer;
+    if( m_poKmlDSContainer
+        && m_poKmlDSContainer->IsA( kmldom::Type_Document ) )
+    {
+        DocumentPtr poKmlDocument = AsDocument( m_poKmlDSContainer );
 
         ParseDocumentOptions(m_poKmlDSKml, poKmlDocument);
 
-        for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
-            SchemaPtr poKmlSchema;
-            SchemaPtr poKmlSchema2;
+        for( int iLayer = 0; iLayer < nLayers; iLayer++ )
+        {
+            SchemaPtr poKmlSchema = NULL;
 
-            if ( ( poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  ) ) ) {
-                size_t nKmlSchemas = poKmlDocument->get_schema_array_size (  );
-                size_t iKmlSchema;
+            if( ( poKmlSchema = papoLayers[iLayer]->GetKmlSchema() ) )
+            {
+                const size_t nKmlSchemas =
+                    poKmlDocument->get_schema_array_size();
+                SchemaPtr poKmlSchema2 = NULL;
 
-                for ( iKmlSchema = 0; iKmlSchema < nKmlSchemas; iKmlSchema++ ) {
+                for( size_t iKmlSchema = 0;
+                     iKmlSchema < nKmlSchemas;
+                     iKmlSchema++ )
+                {
                     poKmlSchema2 =
-                        poKmlDocument->get_schema_array_at ( iKmlSchema );
-                    if ( poKmlSchema2 == poKmlSchema )
+                        poKmlDocument->get_schema_array_at( iKmlSchema );
+                    if( poKmlSchema2 == poKmlSchema )
                         break;
                 }
 
-                if ( poKmlSchema2 != poKmlSchema )
-                    poKmlDocument->add_schema ( poKmlSchema );
+                if( poKmlSchema2 != poKmlSchema )
+                    poKmlDocument->add_schema( poKmlSchema );
             }
 
             papoLayers[iLayer]->Finalize(poKmlDocument);
@@ -244,59 +250,62 @@ void OGRLIBKMLDataSource::WriteKml (
     }
 
     std::string oKmlOut;
-    oKmlOut = kmldom::SerializePretty ( m_poKmlDSKml );
+    oKmlOut = kmldom::SerializePretty( m_poKmlDSKml );
     OGRLIBKMLPostProcessOutput(oKmlOut);
 
-    if (oKmlOut.size() != 0)
+    if( !oKmlOut.empty() )
     {
-        VSILFILE* fp = VSIFOpenL( oKmlFilename.c_str(), "wb" );
-        if (fp == NULL)
+        VSILFILE* fp = VSIFOpenExL( oKmlFilename.c_str(), "wb", true );
+        if( fp == NULL )
         {
-            CPLError ( CE_Failure, CPLE_FileIO,
-                       "ERROR writing %s", oKmlFilename.c_str (  ) );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Error writing %s: %s", oKmlFilename.c_str(),
+                      VSIGetLastErrorMsg() );
             return;
         }
 
         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
         VSIFCloseL(fp);
     }
-
-    return;
 }
 
 /******************************************************************************/
 /*                      OGRLIBKMLCreateOGCKml22()                             */
 /******************************************************************************/
 
-static KmlPtr OGRLIBKMLCreateOGCKml22(KmlFactory* poFactory,
-                                      char** papszOptions = NULL)
+static KmlPtr OGRLIBKMLCreateOGCKml22(
+    KmlFactory* poFactory, char** papszOptions = NULL )
 {
     const char* pszAuthorName = CSLFetchNameValue(papszOptions, "AUTHOR_NAME");
     const char* pszAuthorURI = CSLFetchNameValue(papszOptions, "AUTHOR_URI");
-    const char* pszAuthorEmail = CSLFetchNameValue(papszOptions, "AUTHOR_EMAIL");
+    const char* pszAuthorEmail =
+        CSLFetchNameValue(papszOptions, "AUTHOR_EMAIL");
     const char* pszLink = CSLFetchNameValue(papszOptions, "LINK");
-    int bWithAtom = pszAuthorName != NULL ||
-                    pszAuthorURI != NULL ||
-                    pszAuthorEmail != NULL ||
-                    pszLink != NULL;
+    const bool bWithAtom =
+        pszAuthorName != NULL ||
+        pszAuthorURI != NULL ||
+        pszAuthorEmail != NULL ||
+        pszLink != NULL;
 
-    KmlPtr kml = poFactory->CreateKml (  );
+    KmlPtr kml = poFactory->CreateKml();
     if( bWithAtom )
     {
-        const char* kAttrs[] = { "xmlns", "http://www.opengis.net/kml/2.2",
-                                 "xmlns:atom", "http://www.w3.org/2005/Atom", NULL };
+        const char* kAttrs[] = {
+            "xmlns", "http://www.opengis.net/kml/2.2",
+            "xmlns:atom", "http://www.w3.org/2005/Atom", NULL };
         kml->AddUnknownAttributes(Attributes::Create(kAttrs));
     }
     else
     {
-        const char* kAttrs[] = { "xmlns", "http://www.opengis.net/kml/2.2", NULL };
+        const char* kAttrs[] =
+            { "xmlns", "http://www.opengis.net/kml/2.2", NULL };
         kml->AddUnknownAttributes(Attributes::Create(kAttrs));
     }
     return kml;
 }
 
 /******************************************************************************
- method to write a ds .kmz at ds destroy
+ Method to write a ds .kmz at ds destroy.
 
  Args:          none
 
@@ -304,66 +313,66 @@ static KmlPtr OGRLIBKMLCreateOGCKml22(KmlFactory* poFactory,
 
 ******************************************************************************/
 
-void OGRLIBKMLDataSource::WriteKmz (
-     )
+void OGRLIBKMLDataSource::WriteKmz()
 {
-
     void* hZIP = CPLCreateZip( pszName, NULL );
 
-    if ( !hZIP ) {
-        CPLError ( CE_Failure, CPLE_NoWriteAccess, "ERROR creating %s",
-                   pszName );
+    if( !hZIP )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Error creating %s: %s",
+                  pszName, VSIGetLastErrorMsg() );
         return;
     }
 
     /***** write out the doc.kml ****/
-
     const char *pszUseDocKml =
-        CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
-
-    if ( CPLTestBool ( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) ) {
+        CPLGetConfigOption( "LIBKML_USE_DOC.KML", "yes" );
 
+    if( CPLTestBool( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) )
+    {
         // If we do not have the doc.kmlroot
         // make it and add the container.
-
-        if ( !m_poKmlDocKmlRoot ) {
-            m_poKmlDocKmlRoot = OGRLIBKMLCreateOGCKml22(m_poKmlFactory, m_papszOptions);
+        if( !m_poKmlDocKmlRoot )
+        {
+            m_poKmlDocKmlRoot =
+                OGRLIBKMLCreateOGCKml22(m_poKmlFactory, m_papszOptions);
 
             if( m_poKmlDocKml != NULL )
             {
-                AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
+                AsKml( m_poKmlDocKmlRoot )->set_feature( m_poKmlDocKml );
             }
 
-            ParseDocumentOptions(AsKml( m_poKmlDocKmlRoot ), AsDocument(m_poKmlDocKml));
+            ParseDocumentOptions(
+                AsKml( m_poKmlDocKmlRoot ), AsDocument(m_poKmlDocKml));
         }
 
-        std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
+        std::string oKmlOut = kmldom::SerializePretty( m_poKmlDocKmlRoot );
         OGRLIBKMLPostProcessOutput(oKmlOut);
 
-        if ( CPLCreateFileInZip( hZIP, "doc.kml", NULL ) != CE_None ||
-             CPLWriteFileInZip( hZIP, oKmlOut.data(), static_cast<int>(oKmlOut.size()) ) != CE_None )
-            CPLError ( CE_Failure, CPLE_FileIO,
-                       "ERROR adding %s to %s", "doc.kml", pszName );
+        if( CPLCreateFileInZip( hZIP, "doc.kml", NULL ) != CE_None ||
+            CPLWriteFileInZip( hZIP, oKmlOut.data(),
+                               static_cast<int>(oKmlOut.size()) ) != CE_None )
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "ERROR adding %s to %s", "doc.kml", pszName );
         CPLCloseFileInZip(hZIP);
-
     }
 
     /***** loop though the layers and write them *****/
+    for( int iLayer = 0; iLayer < nLayers && m_poKmlUpdate == NULL; iLayer++ )
+    {
+        ContainerPtr poKmlContainer = papoLayers[iLayer]->GetKmlLayer();
 
-    int iLayer;
-
-    for ( iLayer = 0; iLayer < nLayers && m_poKmlUpdate == NULL; iLayer++ ) {
-        ContainerPtr poKmlContainer = papoLayers[iLayer]->GetKmlLayer (  );
-
-        if ( poKmlContainer->IsA ( kmldom::Type_Document ) ) {
-
-            DocumentPtr poKmlDocument = AsDocument ( poKmlContainer );
-            SchemaPtr poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  );
+        if( poKmlContainer->IsA( kmldom::Type_Document ) )
+        {
+            DocumentPtr poKmlDocument = AsDocument( poKmlContainer );
+            SchemaPtr poKmlSchema = papoLayers[iLayer]->GetKmlSchema();
 
-            if ( !poKmlDocument->get_schema_array_size (  ) &&
-                 poKmlSchema &&
-                 poKmlSchema->get_simplefield_array_size (  ) ) {
-                poKmlDocument->add_schema ( poKmlSchema );
+            if( !poKmlDocument->get_schema_array_size() &&
+                poKmlSchema &&
+                poKmlSchema->get_simplefield_array_size() )
+            {
+                poKmlDocument->add_schema( poKmlSchema );
             }
 
             papoLayers[iLayer]->Finalize(poKmlDocument);
@@ -371,61 +380,61 @@ void OGRLIBKMLDataSource::WriteKmz (
 
         // If we do not have the layers root
         // make it and add the container.
-
         KmlPtr poKmlKml = NULL;
 
-        if ( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot (  ) ) ) ) {
-
+        if( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot() ) ) )
+        {
             poKmlKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory);
 
-            poKmlKml->set_feature ( poKmlContainer );
+            poKmlKml->set_feature( poKmlContainer );
         }
 
-        std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
+        std::string oKmlOut = kmldom::SerializePretty( poKmlKml );
         OGRLIBKMLPostProcessOutput(oKmlOut);
 
-        if( iLayer == 0 && CPLTestBool ( pszUseDocKml ) )
+        if( iLayer == 0 && CPLTestBool( pszUseDocKml ) )
             CPLCreateFileInZip( hZIP, "layers/", NULL );
 
-        const char* pszLayerFileName;
-        if( CPLTestBool ( pszUseDocKml ) )
-            pszLayerFileName = CPLSPrintf("layers/%s", papoLayers[iLayer]->GetFileName (  ));
+        const char* pszLayerFileName = NULL;
+        if( CPLTestBool( pszUseDocKml ) )
+            pszLayerFileName =
+                CPLSPrintf("layers/%s", papoLayers[iLayer]->GetFileName());
         else
-            pszLayerFileName = papoLayers[iLayer]->GetFileName (  );
-
-        if ( CPLCreateFileInZip( hZIP, pszLayerFileName , NULL ) != CE_None ||
-             CPLWriteFileInZip( hZIP, oKmlOut.data(), static_cast<int>(oKmlOut.size()) ) != CE_None )
-            CPLError ( CE_Failure, CPLE_FileIO,
-                       "ERROR adding %s to %s", papoLayers[iLayer]->GetFileName (  ), pszName );
+            pszLayerFileName = papoLayers[iLayer]->GetFileName();
+
+        if( CPLCreateFileInZip( hZIP, pszLayerFileName , NULL ) != CE_None ||
+             CPLWriteFileInZip( hZIP, oKmlOut.data(),
+                                static_cast<int>(oKmlOut.size()) ) != CE_None )
+            CPLError(
+                CE_Failure, CPLE_FileIO,
+                "ERROR adding %s to %s",
+                papoLayers[iLayer]->GetFileName(), pszName );
         CPLCloseFileInZip(hZIP);
-
     }
 
-   /***** write the style table *****/
-
-    if ( m_poKmlStyleKml ) {
-
+    /***** write the style table *****/
+    if( m_poKmlStyleKml )
+    {
         KmlPtr poKmlKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory);
 
-        poKmlKml->set_feature ( m_poKmlStyleKml );
-        std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
+        poKmlKml->set_feature( m_poKmlStyleKml );
+        std::string oKmlOut = kmldom::SerializePretty( poKmlKml );
         OGRLIBKMLPostProcessOutput(oKmlOut);
 
-        if ( CPLCreateFileInZip( hZIP, "style/", NULL ) != CE_None ||
-             CPLCreateFileInZip( hZIP, "style/style.kml", NULL ) != CE_None ||
-             CPLWriteFileInZip( hZIP, oKmlOut.data(), static_cast<int>(oKmlOut.size()) ) != CE_None )
-            CPLError ( CE_Failure, CPLE_FileIO,
-                       "ERROR adding %s to %s", "style/style.kml", pszName );
+        if( CPLCreateFileInZip( hZIP, "style/", NULL ) != CE_None ||
+            CPLCreateFileInZip( hZIP, "style/style.kml", NULL ) != CE_None ||
+            CPLWriteFileInZip( hZIP, oKmlOut.data(),
+                               static_cast<int>(oKmlOut.size()) ) != CE_None )
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "ERROR adding %s to %s", "style/style.kml", pszName );
         CPLCloseFileInZip(hZIP);
     }
 
     CPLCloseZip(hZIP);
-
-    return;
 }
 
 /******************************************************************************
- method to write a dir ds at ds destroy
+ Method to write a dir ds at ds destroy.
 
  Args:          none
 
@@ -433,38 +442,38 @@ void OGRLIBKMLDataSource::WriteKmz (
 
 ******************************************************************************/
 
-void OGRLIBKMLDataSource::WriteDir (
-     )
+void OGRLIBKMLDataSource::WriteDir()
 {
-
     /***** write out the doc.kml ****/
-
     const char *pszUseDocKml =
-        CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
-
-    if ( CPLTestBool ( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) ) {
+        CPLGetConfigOption( "LIBKML_USE_DOC.KML", "yes" );
 
+    if( CPLTestBool( pszUseDocKml ) && (m_poKmlDocKml || m_poKmlUpdate) )
+    {
         // If we don't have the doc.kml root
         // make it and add the container.
-
-        if ( !m_poKmlDocKmlRoot ) {
-            m_poKmlDocKmlRoot = OGRLIBKMLCreateOGCKml22(m_poKmlFactory, m_papszOptions);
+        if( !m_poKmlDocKmlRoot )
+        {
+            m_poKmlDocKmlRoot =
+                OGRLIBKMLCreateOGCKml22(m_poKmlFactory, m_papszOptions);
             if( m_poKmlDocKml != NULL )
-                AsKml( m_poKmlDocKmlRoot )->set_feature ( m_poKmlDocKml );
+                AsKml( m_poKmlDocKmlRoot )->set_feature( m_poKmlDocKml );
 
-            ParseDocumentOptions(AsKml( m_poKmlDocKmlRoot ), AsDocument(m_poKmlDocKml));
+            ParseDocumentOptions(
+                AsKml( m_poKmlDocKmlRoot ), AsDocument(m_poKmlDocKml));
         }
 
-        std::string oKmlOut = kmldom::SerializePretty ( m_poKmlDocKmlRoot );
+        std::string oKmlOut = kmldom::SerializePretty( m_poKmlDocKmlRoot );
         OGRLIBKMLPostProcessOutput(oKmlOut);
 
-        const char *pszOutfile = CPLFormFilename ( pszName, "doc.kml", NULL );
+        const char *pszOutfile = CPLFormFilename( pszName, "doc.kml", NULL );
 
-        VSILFILE* fp = VSIFOpenL( pszOutfile, "wb" );
-        if (fp == NULL)
+        VSILFILE* fp = VSIFOpenExL( pszOutfile, "wb", true );
+        if( fp == NULL )
         {
-            CPLError ( CE_Failure, CPLE_FileIO,
-                       "ERROR Writing %s to %s", "doc.kml", pszName );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "Error writing %s to %s: %s", "doc.kml", pszName,
+                      VSIGetLastErrorMsg() );
             return;
         }
 
@@ -473,21 +482,20 @@ void OGRLIBKMLDataSource::WriteDir (
     }
 
     /***** loop though the layers and write them *****/
+    for( int iLayer = 0; iLayer < nLayers && m_poKmlUpdate == NULL; iLayer++ )
+    {
+        ContainerPtr poKmlContainer = papoLayers[iLayer]->GetKmlLayer();
 
-    int iLayer;
-
-    for ( iLayer = 0; iLayer < nLayers && m_poKmlUpdate == NULL; iLayer++ ) {
-        ContainerPtr poKmlContainer = papoLayers[iLayer]->GetKmlLayer (  );
-
-        if ( poKmlContainer->IsA ( kmldom::Type_Document ) ) {
-
-            DocumentPtr poKmlDocument = AsDocument ( poKmlContainer );
-            SchemaPtr poKmlSchema = papoLayers[iLayer]->GetKmlSchema (  );
+        if( poKmlContainer->IsA( kmldom::Type_Document ) )
+        {
+            DocumentPtr poKmlDocument = AsDocument( poKmlContainer );
+            SchemaPtr poKmlSchema = papoLayers[iLayer]->GetKmlSchema();
 
-            if ( !poKmlDocument->get_schema_array_size (  ) &&
-                 poKmlSchema &&
-                 poKmlSchema->get_simplefield_array_size (  ) ) {
-                poKmlDocument->add_schema ( poKmlSchema );
+            if( !poKmlDocument->get_schema_array_size() &&
+                poKmlSchema &&
+                poKmlSchema->get_simplefield_array_size() )
+            {
+                poKmlDocument->add_schema( poKmlSchema );
             }
 
             papoLayers[iLayer]->Finalize(poKmlDocument);
@@ -495,30 +503,27 @@ void OGRLIBKMLDataSource::WriteDir (
 
         // If we do not have the layers root
         // make it and add the container.
-
         KmlPtr poKmlKml = NULL;
 
-        if ( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot (  ) ) ) ) {
-
+        if( !( poKmlKml = AsKml( papoLayers[iLayer]->GetKmlLayerRoot() ) ) )
+        {
             poKmlKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory);
 
-            poKmlKml->set_feature ( poKmlContainer );
+            poKmlKml->set_feature( poKmlContainer );
         }
 
-        std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
+        std::string oKmlOut = kmldom::SerializePretty( poKmlKml );
         OGRLIBKMLPostProcessOutput(oKmlOut);
 
-        const char *pszOutfile = CPLFormFilename ( pszName,
-                                                   papoLayers[iLayer]->
-                                                   GetFileName (  ),
-                                                   NULL );
+        const char *pszOutfile = CPLFormFilename(
+            pszName, papoLayers[iLayer]->GetFileName(), NULL );
 
         VSILFILE* fp = VSIFOpenL( pszOutfile, "wb" );
-        if (fp == NULL)
+        if( fp == NULL )
         {
-            CPLError ( CE_Failure, CPLE_FileIO,
-                       "ERROR Writing %s to %s",
-                       papoLayers[iLayer]->GetFileName (  ), pszName );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "ERROR Writing %s to %s",
+                      papoLayers[iLayer]->GetFileName(), pszName );
             return;
         }
 
@@ -526,37 +531,33 @@ void OGRLIBKMLDataSource::WriteDir (
         VSIFCloseL(fp);
     }
 
-   /***** write the style table *****/
-
-    if ( m_poKmlStyleKml ) {
-
+    /***** write the style table *****/
+    if( m_poKmlStyleKml )
+    {
         KmlPtr poKmlKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory);
 
-        poKmlKml->set_feature ( m_poKmlStyleKml );
-        std::string oKmlOut = kmldom::SerializePretty ( poKmlKml );
+        poKmlKml->set_feature( m_poKmlStyleKml );
+        std::string oKmlOut = kmldom::SerializePretty( poKmlKml );
         OGRLIBKMLPostProcessOutput(oKmlOut);
 
-        const char *pszOutfile = CPLFormFilename ( pszName,
-                                                   "style.kml",
-                                                   NULL );
+        const char *pszOutfile =
+            CPLFormFilename( pszName, "style.kml",  NULL );
 
         VSILFILE* fp = VSIFOpenL( pszOutfile, "wb" );
-        if (fp == NULL)
+        if( fp == NULL )
         {
-            CPLError ( CE_Failure, CPLE_FileIO,
-                       "ERROR Writing %s to %s", "style.kml", pszName );
+            CPLError( CE_Failure, CPLE_FileIO,
+                      "ERROR Writing %s to %s", "style.kml", pszName );
             return;
         }
 
         VSIFWriteL(oKmlOut.data(), 1, oKmlOut.size(), fp);
         VSIFCloseL(fp);
     }
-
-    return;
 }
 
 /******************************************************************************
- method to write the datasource to disk
+ Method to write the datasource to disk.
 
  Args:      none
 
@@ -564,29 +565,25 @@ void OGRLIBKMLDataSource::WriteDir (
 
 ******************************************************************************/
 
-void OGRLIBKMLDataSource::FlushCache (
-     )
+void OGRLIBKMLDataSource::FlushCache()
 {
+    if( !bUpdated )
+        return;
 
-    if ( bUpdated ) {
-
-        /***** kml *****/
-
-        if ( bUpdate && IsKml (  ) )
-            WriteKml (  );
-
-        /***** kmz *****/
-
-        else if ( bUpdate && IsKmz (  ) ) {
-            WriteKmz (  );
-        }
-
-        else if ( bUpdate && IsDir (  ) ) {
-            WriteDir (  );
-        }
-
-        bUpdated = FALSE;
+    if( bUpdate && IsKml() )
+    {
+        WriteKml();
+    }
+    else if( bUpdate && IsKmz() )
+    {
+        WriteKmz();
     }
+    else if( bUpdate && IsDir() )
+    {
+        WriteDir();
+    }
+
+    bUpdated = false;
 }
 
 /******************************************************************************
@@ -598,33 +595,26 @@ void OGRLIBKMLDataSource::FlushCache (
 
 ******************************************************************************/
 
-OGRLIBKMLDataSource::~OGRLIBKMLDataSource (  )
+OGRLIBKMLDataSource::~OGRLIBKMLDataSource()
 {
-
-
     /***** sync the DS to disk *****/
+    FlushCache();
 
-    FlushCache (  );
+    CPLFree( pszName );
 
-    CPLFree ( pszName );
+    if( !EQUAL(pszStylePath, "") )
+        CPLFree( pszStylePath );
 
-    if (! EQUAL(pszStylePath, ""))
-        CPLFree ( pszStylePath );
-
-    for ( int i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
 
-    CPLFree ( papoLayers );
+    CPLFree( papoLayers );
 
     CSLDestroy( m_papszOptions );
-
-    //delete m_poStyleTable;
-
 }
 
-
 /******************************************************************************
- method to parse a schemas out of a document
+ Method to parse a schemas out of a document.
 
  Args:          poKmlDocument   pointer to the document to parse
 
@@ -632,99 +622,92 @@ OGRLIBKMLDataSource::~OGRLIBKMLDataSource (  )
 
 ******************************************************************************/
 
-SchemaPtr OGRLIBKMLDataSource::FindSchema (
-    const char *pszSchemaUrl )
+SchemaPtr OGRLIBKMLDataSource::FindSchema( const char *pszSchemaUrl )
 {
+    if( !pszSchemaUrl || !*pszSchemaUrl )
+        return NULL;
+
     char *pszID = NULL;
     char *pszFile = NULL;
     char *pszSchemaName = NULL;
-    char *pszPound;
+    char *pszPound = NULL;
     DocumentPtr poKmlDocument = NULL;
     SchemaPtr poKmlSchemaResult = NULL;
 
-    if ( !pszSchemaUrl || !*pszSchemaUrl )
-        return NULL;
-
-    if ( *pszSchemaUrl == '#' ) {
-        pszID = CPLStrdup ( pszSchemaUrl + 1 );
+    if( *pszSchemaUrl == '#' )
+    {
+        pszID = CPLStrdup( pszSchemaUrl + 1 );
 
         /***** kml *****/
-
-        if ( IsKml (  ) && m_poKmlDSContainer->IsA ( kmldom::Type_Document ) )
-            poKmlDocument = AsDocument ( m_poKmlDSContainer );
+        if( IsKml() && m_poKmlDSContainer->IsA( kmldom::Type_Document ) )
+            poKmlDocument = AsDocument( m_poKmlDSContainer );
 
         /***** kmz *****/
-
-        else if ( ( IsKmz (  ) || IsDir (  ) ) && m_poKmlDocKml
-                  && m_poKmlDocKml->IsA ( kmldom::Type_Document ) )
-            poKmlDocument = AsDocument ( m_poKmlDocKml );
-
+        else if( ( IsKmz() || IsDir() ) && m_poKmlDocKml
+                  && m_poKmlDocKml->IsA( kmldom::Type_Document ) )
+            poKmlDocument = AsDocument( m_poKmlDocKml );
     }
-
-
-    else if ( ( pszPound = strchr ( (char *)pszSchemaUrl, '#' ) ) != NULL ) {
-        pszFile = CPLStrdup ( pszSchemaUrl );
-        pszID = CPLStrdup ( pszPound + 1 );
-        pszPound = strchr ( pszFile, '#' );
+    else if( ( pszPound = strchr( const_cast<char *>(pszSchemaUrl), '#' ) )
+             != NULL )
+    {
+        pszFile = CPLStrdup( pszSchemaUrl );
+        pszID = CPLStrdup( pszPound + 1 );
+        pszPound = strchr( pszFile, '#' );
         *pszPound = '\0';
     }
-
-    else {
-        pszSchemaName = CPLStrdup ( pszSchemaUrl );
+    else
+    {
+        pszSchemaName = CPLStrdup( pszSchemaUrl );
 
         /***** kml *****/
-
-        if ( IsKml (  ) && m_poKmlDSContainer->IsA ( kmldom::Type_Document ) )
-            poKmlDocument = AsDocument ( m_poKmlDSContainer );
+        if( IsKml() && m_poKmlDSContainer->IsA( kmldom::Type_Document ) )
+            poKmlDocument = AsDocument( m_poKmlDSContainer );
 
         /***** kmz *****/
 
-        else if ( ( IsKmz (  ) || IsDir (  ) ) && m_poKmlDocKml
-                  && m_poKmlDocKml->IsA ( kmldom::Type_Document ) )
-            poKmlDocument = AsDocument ( m_poKmlDocKml );
-
+        else if( ( IsKmz() || IsDir() ) && m_poKmlDocKml
+                  && m_poKmlDocKml->IsA( kmldom::Type_Document ) )
+            poKmlDocument = AsDocument( m_poKmlDocKml );
     }
 
+    if( poKmlDocument )
+    {
+        size_t nKmlSchemas = poKmlDocument->get_schema_array_size();
 
-    if ( poKmlDocument) {
-
-        size_t nKmlSchemas = poKmlDocument->get_schema_array_size (  );
-        size_t iKmlSchema;
-
-        for ( iKmlSchema = 0; iKmlSchema < nKmlSchemas; iKmlSchema++ ) {
+        for( size_t iKmlSchema = 0; iKmlSchema < nKmlSchemas; iKmlSchema++ )
+        {
             SchemaPtr poKmlSchema =
-                poKmlDocument->get_schema_array_at ( iKmlSchema );
-            if ( poKmlSchema->has_id (  ) && pszID) {
-                if ( EQUAL ( pszID, poKmlSchema->get_id (  ).c_str (  ) ) ) {
+                poKmlDocument->get_schema_array_at( iKmlSchema );
+            if( poKmlSchema->has_id() && pszID)
+            {
+                if( EQUAL( pszID, poKmlSchema->get_id().c_str() ) )
+                {
                     poKmlSchemaResult = poKmlSchema;
                     break;
                 }
             }
 
-            else if ( poKmlSchema->has_name (  ) && pszSchemaName) {
-                if ( EQUAL ( pszSchemaName, poKmlSchema->get_name (  ).c_str (  ) ) ) {
+            else if( poKmlSchema->has_name() && pszSchemaName)
+            {
+                if( EQUAL( pszSchemaName, poKmlSchema->get_name().c_str() ) )
+                {
                     poKmlSchemaResult = poKmlSchema;
                     break;
                 }
             }
-
         }
     }
 
-    if ( pszFile )
-        CPLFree ( pszFile );
-    if ( pszID )
-        CPLFree ( pszID );
-    if ( pszSchemaName )
-        CPLFree ( pszSchemaName );
+    CPLFree( pszFile );
+    CPLFree( pszID );
+    CPLFree( pszSchemaName );
 
     return poKmlSchemaResult;
-
 }
 
 /******************************************************************************
-Method to allocate memory for the layer array, create the layer,
- and add it to the layer array
+ Method to allocate memory for the layer array, create the layer,
+ and add it to the layer array.
 
  Args:          pszLayerName    the name of the layer
                 poSpatialRef    the spacial Refrance for the layer
@@ -740,7 +723,7 @@ Method to allocate memory for the layer array, create the layer,
  Returns:       Pointer to the new layer
 ******************************************************************************/
 
-OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
+OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer(
     const char *pszLayerName,
     OGRSpatialReference * poSpatialRef,
     OGRwkbGeometryType eGType,
@@ -752,22 +735,18 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
     int bUpdateIn,
     int nGuess )
 {
-
     /***** check to see if we have enough space to store the layer *****/
-
-    if ( nLayers == nAlloced ) {
+    if( nLayers == nAlloced )
+    {
         nAlloced += nGuess;
-        void *tmp = CPLRealloc ( papoLayers,
-                                 sizeof ( OGRLIBKMLLayer * ) * nAlloced );
-
-        papoLayers = ( OGRLIBKMLLayer ** ) tmp;
+        papoLayers = static_cast<OGRLIBKMLLayer **>(
+            CPLRealloc( papoLayers, sizeof(OGRLIBKMLLayer *) * nAlloced ) );
     }
 
     /***** create the layer *****/
+    const int iLayer = nLayers++;
 
-    int iLayer = nLayers++;
-
-    OGRLIBKMLLayer *poOgrLayer = new OGRLIBKMLLayer ( pszLayerName,
+    OGRLIBKMLLayer *poOgrLayer = new OGRLIBKMLLayer( pszLayerName,
                                                       poSpatialRef,
                                                       eGType,
                                                       poOgrDS,
@@ -779,7 +758,6 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
                                                       bUpdateIn );
 
     /***** add the layer to the array *****/
-
     papoLayers[iLayer] = poOgrLayer;
 
     return poOgrLayer;
@@ -796,78 +774,78 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::AddLayer (
 
 ******************************************************************************/
 
-int OGRLIBKMLDataSource::ParseLayers (
+int OGRLIBKMLDataSource::ParseLayers(
     ContainerPtr poKmlContainer,
     OGRSpatialReference * poOgrSRS )
 {
-    int nResult = 0;
-
     /***** if container is null just bail now *****/
+    if( !poKmlContainer )
+        return 0;
 
-    if ( !poKmlContainer )
-        return nResult;
-
-    size_t nKmlFeatures = poKmlContainer->get_feature_array_size (  );
+    const size_t nKmlFeatures = poKmlContainer->get_feature_array_size();
 
     /***** loop over the container to separate the style, layers, etc *****/
 
-    size_t iKmlFeature;
-
-    for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
+    int nResult = 0;
+    for( size_t iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ )
+    {
         FeaturePtr poKmlFeat =
-            poKmlContainer->get_feature_array_at ( iKmlFeature );
+            poKmlContainer->get_feature_array_at( iKmlFeature );
 
         /***** container *****/
 
-        if ( poKmlFeat->IsA ( kmldom::Type_Container ) ) {
-
+        if( poKmlFeat->IsA( kmldom::Type_Container ) )
+        {
             /***** see if the container has a name *****/
 
             std::string oKmlFeatName;
-            if ( poKmlFeat->has_name (  ) ) {
+            if( poKmlFeat->has_name() )
+            {
                 /* Strip leading and trailing spaces */
-                const char* l_pszName = poKmlFeat->get_name (  ).c_str();
-                while(*l_pszName == ' ' || *l_pszName == '\n' || *l_pszName == '\r' || *l_pszName == '\t' )
+                const char* l_pszName = poKmlFeat->get_name().c_str();
+                while( *l_pszName == ' ' || *l_pszName == '\n' ||
+                       *l_pszName == '\r' || *l_pszName == '\t' )
                     l_pszName ++;
                 oKmlFeatName = l_pszName;
                 int nSize = (int)oKmlFeatName.size();
-                while (nSize > 0 &&
-                       (oKmlFeatName[nSize-1] == ' ' || oKmlFeatName[nSize-1] == '\n' ||
-                        oKmlFeatName[nSize-1] == '\r' || oKmlFeatName[nSize-1] == '\t'))
+                while( nSize > 0 &&
+                       (oKmlFeatName[nSize-1] == ' ' ||
+                        oKmlFeatName[nSize-1] == '\n' ||
+                        oKmlFeatName[nSize-1] == '\r' ||
+                        oKmlFeatName[nSize-1] == '\t') )
                 {
-                    nSize --;
+                    nSize--;
                     oKmlFeatName.resize(nSize);
                 }
             }
-
             /***** use the feature index number as the name *****/
             /***** not sure i like this c++ ich *****/
-
-            else {
+            else
+            {
                 std::stringstream oOut;
                 oOut << iKmlFeature;
                 oKmlFeatName = "Layer";
-                oKmlFeatName.append(oOut.str (  ));
+                oKmlFeatName.append(oOut.str());
             }
 
             /***** create the layer *****/
 
-            AddLayer ( oKmlFeatName.c_str (  ),
-                       poOgrSRS, wkbUnknown, this,
-                       NULL, AsContainer( poKmlFeat ), "", FALSE, bUpdate,
-                       static_cast<int>(nKmlFeatures) );
-
+            AddLayer( oKmlFeatName.c_str(),
+                      poOgrSRS, wkbUnknown, this,
+                      NULL, AsContainer( poKmlFeat ), "", FALSE, bUpdate,
+                      static_cast<int>(nKmlFeatures) );
         }
-
         else
+        {
             nResult++;
+        }
     }
 
     return nResult;
 }
 
 /******************************************************************************
- function to get the container from the kmlroot
+ Function to get the container from the kmlroot.
 
  Args:          poKmlRoot   the root element
 
@@ -876,78 +854,81 @@ int OGRLIBKMLDataSource::ParseLayers (
 
 ******************************************************************************/
 
-static ContainerPtr GetContainerFromRoot (
+static ContainerPtr GetContainerFromRoot(
     KmlFactory *m_poKmlFactory, ElementPtr poKmlRoot )
 {
     ContainerPtr poKmlContainer = NULL;
 
-    int bReadGroundOverlay = CPLTestBool(CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
-
-    if ( poKmlRoot ) {
+    const bool bReadGroundOverlay =
+        CPLTestBool(CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
 
+    if( poKmlRoot )
+    {
         /***** skip over the <kml> we want the container *****/
+        if( poKmlRoot->IsA( kmldom::Type_kml ) )
+        {
+            KmlPtr poKmlKml = AsKml( poKmlRoot );
 
-        if ( poKmlRoot->IsA ( kmldom::Type_kml ) ) {
-
-            KmlPtr poKmlKml = AsKml ( poKmlRoot );
-
-            if ( poKmlKml->has_feature (  ) ) {
-                FeaturePtr poKmlFeat = poKmlKml->get_feature (  );
+            if( poKmlKml->has_feature() )
+            {
+                FeaturePtr poKmlFeat = poKmlKml->get_feature();
 
-                if ( poKmlFeat->IsA ( kmldom::Type_Container ) )
-                    poKmlContainer = AsContainer ( poKmlFeat );
-                else if ( poKmlFeat->IsA ( kmldom::Type_Placemark ) ||
-                          (bReadGroundOverlay && poKmlFeat->IsA ( kmldom::Type_GroundOverlay )) )
+                if( poKmlFeat->IsA( kmldom::Type_Container ) )
+                    poKmlContainer = AsContainer( poKmlFeat );
+                else if( poKmlFeat->IsA( kmldom::Type_Placemark ) ||
+                         (bReadGroundOverlay &&
+                          poKmlFeat->IsA( kmldom::Type_GroundOverlay )) )
                 {
-                    poKmlContainer = m_poKmlFactory->CreateDocument (  );
-                    poKmlContainer->add_feature ( kmldom::AsFeature(kmlengine::Clone(poKmlFeat)) );
+                    poKmlContainer = m_poKmlFactory->CreateDocument();
+                    poKmlContainer->add_feature(
+                        kmldom::AsFeature(kmlengine::Clone(poKmlFeat)) );
                 }
             }
-
         }
-
-        else if ( poKmlRoot->IsA ( kmldom::Type_Container ) )
-            poKmlContainer = AsContainer ( poKmlRoot );
+        else if( poKmlRoot->IsA( kmldom::Type_Container ) )
+        {
+            poKmlContainer = AsContainer( poKmlRoot );
+        }
     }
 
     return poKmlContainer;
 }
 
 /******************************************************************************
- method to parse a kml string into the style table
+ Method to parse a kml string into the style table.
 ******************************************************************************/
 
-int OGRLIBKMLDataSource::ParseIntoStyleTable (
+int OGRLIBKMLDataSource::ParseIntoStyleTable(
     std::string *poKmlStyleKml,
-    const char *pszMyStylePath)
+    const char *pszMyStylePath )
 {
-
     /***** parse the kml into the dom *****/
-
     std::string oKmlErrors;
-    ElementPtr poKmlRoot = kmldom::Parse ( *poKmlStyleKml, &oKmlErrors );
+    ElementPtr poKmlRoot = kmldom::Parse( *poKmlStyleKml, &oKmlErrors );
 
-    if ( !poKmlRoot ) {
-        CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR parsing style kml %s :%s",
-                   pszStylePath, oKmlErrors.c_str (  ) );
+    if( !poKmlRoot )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "ERROR parsing style kml %s :%s",
+                  pszStylePath, oKmlErrors.c_str() );
         return false;
     }
 
-    ContainerPtr poKmlContainer;
+    ContainerPtr poKmlContainer = NULL;
 
-    if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory, poKmlRoot ) ) ) {
+    if( !( poKmlContainer = GetContainerFromRoot( m_poKmlFactory, poKmlRoot ) ) )
+    {
         return false;
     }
 
-    ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
+    ParseStyles( AsDocument( poKmlContainer ), &m_poStyleTable );
     pszStylePath = CPLStrdup(pszMyStylePath);
 
     return true;
 }
 
 /******************************************************************************
- method to open a kml file
+ Method to open a kml file.
 
  Args:          pszFilename file to open
                 bUpdate     update mode
@@ -956,28 +937,26 @@ int OGRLIBKMLDataSource::ParseIntoStyleTable (
 
 ******************************************************************************/
 
-int OGRLIBKMLDataSource::OpenKml (
-    const char *pszFilename,
-    int bUpdateIn )
+int OGRLIBKMLDataSource::OpenKml( const char *pszFilename, int bUpdateIn )
 {
     std::string oKmlKml;
-    char szBuffer[1024+1];
+    char szBuffer[1024+1] = {};
 
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
-    if (fp == NULL)
+    if( fp == NULL )
     {
-        CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "Cannot open %s", pszFilename );
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Cannot open %s", pszFilename );
         return FALSE;
     }
-    int nRead;
-    while ((nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp))) != 0)
+    int nRead = 0;
+    while( (nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp))) != 0 )
     {
         try
         {
             oKmlKml.append(szBuffer, nRead);
         }
-        catch(const std::bad_alloc& )
+        catch( const std::bad_alloc& )
         {
             VSIFCloseL(fp);
             return FALSE;
@@ -989,62 +968,59 @@ int OGRLIBKMLDataSource::OpenKml (
     CPLLocaleC  oLocaleForcer;
 
     /***** create a SRS *****/
-
     OGRSpatialReference *poOgrSRS =
-        new OGRSpatialReference ( OGRLIBKMLSRSWKT );
+        new OGRSpatialReference( OGRLIBKMLSRSWKT );
 
     /***** parse the kml into the DOM *****/
-
     std::string oKmlErrors;
 
-    ElementPtr poKmlRoot = kmldom::Parse ( oKmlKml, &oKmlErrors );
+    ElementPtr poKmlRoot = kmldom::Parse( oKmlKml, &oKmlErrors );
 
-    if ( !poKmlRoot ) {
-        CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR parsing kml %s :%s",
-                   pszFilename, oKmlErrors.c_str (  ) );
+    if( !poKmlRoot )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "ERROR parsing kml %s :%s",
+                  pszFilename, oKmlErrors.c_str() );
         delete poOgrSRS;
 
         return FALSE;
     }
 
     /***** get the container from root  *****/
-
-    if ( !( m_poKmlDSContainer = GetContainerFromRoot ( m_poKmlFactory,
-                                                        poKmlRoot ) ) ) {
-        CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR parsing kml %s :%s %s",
-                   pszFilename, "This file does not fit the OGR model,",
-                   "there is no container element at the root." );
+    if( !( m_poKmlDSContainer = GetContainerFromRoot( m_poKmlFactory,
+                                                      poKmlRoot ) ) )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "ERROR parsing kml %s :%s %s",
+                  pszFilename, "This file does not fit the OGR model,",
+                  "there is no container element at the root." );
         delete poOgrSRS;
 
         return FALSE;
     }
 
-    m_isKml = TRUE;
+    m_isKml = true;
 
     /***** get the styles *****/
-
-    ParseStyles ( AsDocument ( m_poKmlDSContainer ), &m_poStyleTable );
+    ParseStyles( AsDocument( m_poKmlDSContainer ), &m_poStyleTable );
 
     /***** parse for layers *****/
-
-    int nPlacemarks = ParseLayers ( m_poKmlDSContainer, poOgrSRS );
+    int nPlacemarks = ParseLayers( m_poKmlDSContainer, poOgrSRS );
 
     /***** if there is placemarks in the root its a layer *****/
+    if( nPlacemarks && !nLayers )
+    {
+      std::string layername_default( CPLGetBasename( pszFilename ) );
 
-    if ( nPlacemarks && !nLayers ) {
-
-      std::string layername_default( CPLGetBasename ( pszFilename ) );
-
-      if( m_poKmlDSContainer->has_name ( ) ) {
-	  layername_default = m_poKmlDSContainer->get_name ( );
-	}
-
-      AddLayer ( layername_default.c_str(),
-                   poOgrSRS, wkbUnknown,
-                   this, poKmlRoot, m_poKmlDSContainer, pszFilename, FALSE, bUpdateIn, 1 );
+      if( m_poKmlDSContainer->has_name() )
+      {
+          layername_default = m_poKmlDSContainer->get_name();
+      }
 
+      AddLayer( layername_default.c_str(),
+                poOgrSRS, wkbUnknown,
+                this, poKmlRoot, m_poKmlDSContainer, pszFilename, FALSE,
+                bUpdateIn, 1 );
     }
 
     delete poOgrSRS;
@@ -1053,7 +1029,7 @@ int OGRLIBKMLDataSource::OpenKml (
 }
 
 /******************************************************************************
- method to open a kmz file
+ Method to open a kmz file.
 
  Args:          pszFilename file to open
                 bUpdate     update mode
@@ -1062,29 +1038,26 @@ int OGRLIBKMLDataSource::OpenKml (
 
 ******************************************************************************/
 
-
-int OGRLIBKMLDataSource::OpenKmz (
-    const char *pszFilename,
-    int bUpdateIn )
+int OGRLIBKMLDataSource::OpenKmz( const char *pszFilename, int bUpdateIn )
 {
     std::string oKmlKmz;
-    char szBuffer[1024+1];
+    char szBuffer[1024+1] = {};
 
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
-    if (fp == NULL)
+    if( fp == NULL )
     {
-        CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "Cannot open %s", pszFilename );
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "Cannot open %s", pszFilename );
         return FALSE;
     }
-    int nRead;
-    while ((nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp))) != 0)
+    int nRead = 0;
+    while( (nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp))) != 0 )
     {
         try
         {
             oKmlKmz.append(szBuffer, nRead);
         }
-        catch(const std::bad_alloc&)
+        catch( const std::bad_alloc& )
         {
             VSIFCloseL(fp);
             return FALSE;
@@ -1092,55 +1065,54 @@ int OGRLIBKMLDataSource::OpenKmz (
     }
     VSIFCloseL(fp);
 
-    KmzFile *poKmlKmzfile = KmzFile::OpenFromString ( oKmlKmz );
+    KmzFile *poKmlKmzfile = KmzFile::OpenFromString( oKmlKmz );
 
-    if ( !poKmlKmzfile ) {
-        CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "%s is not a valid kmz file", pszFilename );
+    if( !poKmlKmzfile )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "%s is not a valid kmz file", pszFilename );
         return FALSE;
     }
 
     CPLLocaleC  oLocaleForcer;
 
     /***** read the doc.kml *****/
-
     std::string oKmlKml;
     std::string oKmlKmlPath;
-    if ( !poKmlKmzfile->ReadKmlAndGetPath ( &oKmlKml, &oKmlKmlPath ) ) {
-
+    if( !poKmlKmzfile->ReadKmlAndGetPath( &oKmlKml, &oKmlKmlPath ) )
+    {
         return FALSE;
     }
 
     /***** create a SRS *****/
-
     OGRSpatialReference *poOgrSRS =
-        new OGRSpatialReference ( OGRLIBKMLSRSWKT );
+        new OGRSpatialReference( OGRLIBKMLSRSWKT );
 
     /***** parse the kml into the DOM *****/
-
     std::string oKmlErrors;
-    ElementPtr poKmlDocKmlRoot = kmldom::Parse ( oKmlKml, &oKmlErrors );
+    ElementPtr poKmlDocKmlRoot = kmldom::Parse( oKmlKml, &oKmlErrors );
 
-    if ( !poKmlDocKmlRoot ) {
-        CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR parsing kml layer %s from %s :%s",
-                   oKmlKmlPath.c_str (  ),
-                   pszFilename, oKmlErrors.c_str (  ) );
+    if( !poKmlDocKmlRoot )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "ERROR parsing kml layer %s from %s :%s",
+                  oKmlKmlPath.c_str(),
+                  pszFilename, oKmlErrors.c_str() );
         delete poOgrSRS;
 
         return FALSE;
     }
 
     /***** Get the child container from root. *****/
+    ContainerPtr poKmlContainer = NULL;
 
-    ContainerPtr poKmlContainer;
-
-    if (!(poKmlContainer = GetContainerFromRoot ( m_poKmlFactory,
-                                                  poKmlDocKmlRoot ))) {
-        CPLError ( CE_Failure, CPLE_OpenFailed,
-                   "ERROR parsing %s from %s :%s",
-                   oKmlKmlPath.c_str (  ),
-                   pszFilename, "kml contains no Containers" );
+    if( !(poKmlContainer = GetContainerFromRoot( m_poKmlFactory,
+                                                 poKmlDocKmlRoot )) )
+    {
+        CPLError( CE_Failure, CPLE_OpenFailed,
+                  "ERROR parsing %s from %s :%s",
+                  oKmlKmlPath.c_str(),
+                  pszFilename, "kml contains no Containers" );
         delete poOgrSRS;
 
         return FALSE;
@@ -1148,152 +1120,138 @@ int OGRLIBKMLDataSource::OpenKmz (
 
     /***** loop over the container looking for network links *****/
 
-    size_t nKmlFeatures = poKmlContainer->get_feature_array_size (  );
-    size_t iKmlFeature;
+    size_t nKmlFeatures = poKmlContainer->get_feature_array_size();
     int nLinks = 0;
 
-    for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
+    for( size_t iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ )
+    {
         FeaturePtr poKmlFeat =
-            poKmlContainer->get_feature_array_at ( iKmlFeature );
+            poKmlContainer->get_feature_array_at( iKmlFeature );
 
         /***** is it a network link? *****/
-
-        if ( !poKmlFeat->IsA ( kmldom::Type_NetworkLink ) )
+        if( !poKmlFeat->IsA( kmldom::Type_NetworkLink ) )
             continue;
 
-        NetworkLinkPtr poKmlNetworkLink = AsNetworkLink ( poKmlFeat );
+        NetworkLinkPtr poKmlNetworkLink = AsNetworkLink( poKmlFeat );
 
         /***** does it have a link? *****/
-
-        if ( !poKmlNetworkLink->has_link (  ) )
+        if( !poKmlNetworkLink->has_link() )
             continue;
 
-        LinkPtr poKmlLink = poKmlNetworkLink->get_link (  );
+        LinkPtr poKmlLink = poKmlNetworkLink->get_link();
 
         /***** does the link have a href? *****/
-
-        if ( !poKmlLink->has_href (  ) )
+        if( !poKmlLink->has_href() )
             continue;
 
         kmlengine::Href * poKmlHref =
-            new kmlengine::Href ( poKmlLink->get_href (  ) );
+            new kmlengine::Href( poKmlLink->get_href() );
 
         /***** is the link relative? *****/
-
-        if ( poKmlHref->IsRelativePath (  ) ) {
-
+        if( poKmlHref->IsRelativePath() )
+        {
             nLinks++;
 
             std::string oKml;
-            if ( poKmlKmzfile->
-                 ReadFile ( poKmlHref->get_path (  ).c_str (  ), &oKml ) ) {
-
+            if( poKmlKmzfile->
+                 ReadFile( poKmlHref->get_path().c_str(), &oKml ) )
+            {
                 /***** parse the kml into the DOM *****/
-
                 oKmlErrors.clear();
-                ElementPtr poKmlLyrRoot = kmldom::Parse ( oKml, &oKmlErrors );
+                ElementPtr poKmlLyrRoot = kmldom::Parse( oKml, &oKmlErrors );
 
-                if ( !poKmlLyrRoot ) {
-                    CPLError ( CE_Failure, CPLE_OpenFailed,
-                               "ERROR parseing kml layer %s from %s :%s",
-                               poKmlHref->get_path (  ).c_str (  ),
-                               pszFilename, oKmlErrors.c_str (  ) );
+                if( !poKmlLyrRoot )
+                {
+                    CPLError( CE_Failure, CPLE_OpenFailed,
+                              "ERROR parseing kml layer %s from %s :%s",
+                              poKmlHref->get_path().c_str(),
+                              pszFilename, oKmlErrors.c_str() );
                     delete poKmlHref;
 
                     continue;
                 }
 
                 /***** get the container from root  *****/
-
                 ContainerPtr poKmlLyrContainer =
-                    GetContainerFromRoot ( m_poKmlFactory, poKmlLyrRoot );
+                    GetContainerFromRoot( m_poKmlFactory, poKmlLyrRoot );
 
-                if ( !poKmlLyrContainer )
+                if( !poKmlLyrContainer )
                 {
-                    CPLError ( CE_Failure, CPLE_OpenFailed,
+                    CPLError( CE_Failure, CPLE_OpenFailed,
                                "ERROR parsing kml layer %s from %s :%s",
-                               poKmlHref->get_path (  ).c_str (  ),
-                               pszFilename, oKmlErrors.c_str (  ) );
+                               poKmlHref->get_path().c_str(),
+                               pszFilename, oKmlErrors.c_str() );
                     delete poKmlHref;
 
                     continue;
                 }
 
                 /***** create the layer *****/
-
-                AddLayer ( CPLGetBasename
-                           ( poKmlHref->get_path (  ).c_str (  ) ), poOgrSRS,
+                AddLayer( CPLGetBasename
+                          ( poKmlHref->get_path().c_str() ), poOgrSRS,
                            wkbUnknown, this, poKmlLyrRoot, poKmlLyrContainer,
-                           poKmlHref->get_path (  ).c_str (  ), FALSE, bUpdateIn,
+                           poKmlHref->get_path().c_str(), FALSE, bUpdateIn,
                            static_cast<int>(nKmlFeatures) );
-
             }
         }
 
         /***** cleanup *****/
-
         delete poKmlHref;
     }
 
     /***** if the doc.kml has links store it so if were in update mode we can write it *****/
-
-    if ( nLinks ) {
+    if( nLinks )
+    {
         m_poKmlDocKml = poKmlContainer;
         m_poKmlDocKmlRoot = poKmlDocKmlRoot;
     }
-
     /***** if the doc.kml has no links treat it as a normal kml file *****/
-
-    else {
-
+    else
+    {
         /* TODO: There could still be a separate styles file in the KMZ
            if there is this would be a layer style table IF its only a single
            layer.
          */
 
         /***** get the styles *****/
-
-        ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
+        ParseStyles( AsDocument( poKmlContainer ), &m_poStyleTable );
 
         /***** parse for layers *****/
-
-        int nPlacemarks = ParseLayers ( poKmlContainer, poOgrSRS );
+       const int nPlacemarks = ParseLayers( poKmlContainer, poOgrSRS );
 
         /***** if there is placemarks in the root its a layer *****/
+        if( nPlacemarks && !nLayers )
+        {
+            std::string layername_default( CPLGetBasename( pszFilename ) );
 
-        if ( nPlacemarks && !nLayers ) {
-
-	  std::string layername_default( CPLGetBasename ( pszFilename ) );
-
-	  if( poKmlContainer->has_name ( ) ) {
-	      layername_default = poKmlContainer->get_name ( );
-	    }
+            if( poKmlContainer->has_name() )
+            {
+                layername_default = poKmlContainer->get_name();
+            }
 
-	  AddLayer ( layername_default.c_str(),
-		     poOgrSRS, wkbUnknown,
-		     this, poKmlDocKmlRoot, poKmlContainer,
-		     pszFilename, FALSE, bUpdateIn, 1 );
+            AddLayer( layername_default.c_str(),
+                      poOgrSRS, wkbUnknown,
+                      this, poKmlDocKmlRoot, poKmlContainer,
+                      pszFilename, FALSE, bUpdateIn, 1 );
         }
     }
 
     /***** read the style table if it has one *****/
-
     std::string oKmlStyleKml;
-    if ( poKmlKmzfile->ReadFile ( "style/style.kml", &oKmlStyleKml ) )
-        ParseIntoStyleTable ( &oKmlStyleKml, "style/style.kml");
+    if( poKmlKmzfile->ReadFile( "style/style.kml", &oKmlStyleKml ) )
+        ParseIntoStyleTable( &oKmlStyleKml, "style/style.kml");
 
     /***** cleanup *****/
-
     delete poOgrSRS;
 
     delete poKmlKmzfile;
-    m_isKmz = TRUE;
+    m_isKmz = true;
 
     return TRUE;
 }
 
 /******************************************************************************
- method to open a dir
+ Method to open a dir.
 
  Args:          pszFilename Dir to open
                 bUpdate     update mode
@@ -1302,114 +1260,108 @@ int OGRLIBKMLDataSource::OpenKmz (
 
 ******************************************************************************/
 
-int OGRLIBKMLDataSource::OpenDir (
-    const char *pszFilename,
-    int bUpdateIn )
+int OGRLIBKMLDataSource::OpenDir( const char *pszFilename, int bUpdateIn )
 {
+    char **papszDirList = VSIReadDir( pszFilename );
 
-    char **papszDirList = VSIReadDir ( pszFilename );
-
-    if ( papszDirList == NULL )
+    if( papszDirList == NULL )
         return FALSE;
 
     /***** create a SRS *****/
-
     OGRSpatialReference *poOgrSRS =
-        new OGRSpatialReference ( OGRLIBKMLSRSWKT );
+        new OGRSpatialReference( OGRLIBKMLSRSWKT );
 
-    int nFiles = CSLCount ( papszDirList );
-    int iFile;
-
-    for ( iFile = 0; iFile < nFiles; iFile++ ) {
+    const int nFiles = CSLCount( papszDirList );
 
+    for( int iFile = 0; iFile < nFiles; iFile++ )
+    {
         /***** make sure its a .kml file *****/
-
-        if ( !EQUAL ( CPLGetExtension ( papszDirList[iFile] ), "kml" ) )
+        if( !EQUAL( CPLGetExtension( papszDirList[iFile] ), "kml" ) )
             continue;
 
         /***** read the file *****/
         std::string oKmlKml;
-        char szBuffer[1024+1];
+        char szBuffer[1024+1] = {};
 
         CPLString osFilePath =
-            CPLFormFilename ( pszFilename, papszDirList[iFile], NULL );
+            CPLFormFilename( pszFilename, papszDirList[iFile], NULL );
 
         VSILFILE* fp = VSIFOpenL(osFilePath, "rb");
-        if (fp == NULL)
+        if( fp == NULL )
         {
-             CPLError ( CE_Failure, CPLE_OpenFailed,
+             CPLError( CE_Failure, CPLE_OpenFailed,
                        "Cannot open %s", osFilePath.c_str() );
              continue;
         }
 
-        int nRead;
-        while ((nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp))) != 0)
+        int nRead = 0;
+        while( (nRead = static_cast<int>(VSIFReadL(szBuffer, 1,
+                                                   1024, fp))) != 0 )
         {
             try
             {
                 oKmlKml.append(szBuffer, nRead);
             }
-            catch(const std::bad_alloc&)
+            catch( const std::bad_alloc& )
             {
                 VSIFCloseL(fp);
-                CSLDestroy ( papszDirList );
+                CSLDestroy( papszDirList );
                 return FALSE;
             }
         }
         VSIFCloseL(fp);
 
-        CPLLocaleC  oLocaleForcer;
+        CPLLocaleC oLocaleForcer;
 
         /***** parse the kml into the DOM *****/
-
         std::string oKmlErrors;
-        ElementPtr poKmlRoot = kmldom::Parse ( oKmlKml, &oKmlErrors );
+        ElementPtr poKmlRoot = kmldom::Parse( oKmlKml, &oKmlErrors );
 
-        if ( !poKmlRoot ) {
-            CPLError ( CE_Failure, CPLE_OpenFailed,
-                       "ERROR parsing kml layer %s from %s :%s",
-                       osFilePath.c_str(), pszFilename, oKmlErrors.c_str (  ) );
+        if( !poKmlRoot )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "ERROR parsing kml layer %s from %s :%s",
+                      osFilePath.c_str(), pszFilename, oKmlErrors.c_str() );
 
             continue;
         }
 
         /***** Get the container from the root *****/
+        ContainerPtr poKmlContainer = NULL;
 
-        ContainerPtr poKmlContainer;
-
-        if ( !( poKmlContainer = GetContainerFromRoot ( m_poKmlFactory,
-                                                        poKmlRoot ) ) ) {
-            CPLError ( CE_Failure, CPLE_OpenFailed,
-                       "ERROR parsing kml %s :%s %s",
-                       pszFilename,
-                       "This file does not fit the OGR model,",
-                       "there is no container element at the root." );
+        if( !( poKmlContainer = GetContainerFromRoot( m_poKmlFactory,
+                                                      poKmlRoot ) ) )
+        {
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "ERROR parsing kml %s :%s %s",
+                      pszFilename,
+                      "This file does not fit the OGR model,",
+                      "there is no container element at the root." );
             continue;
         }
 
         /***** is it a style table? *****/
-
-        if ( EQUAL ( papszDirList[iFile], "style.kml" ) ) {
-            ParseStyles ( AsDocument ( poKmlContainer ), &m_poStyleTable );
-            pszStylePath = CPLStrdup((char *) "style.kml");
+        if( EQUAL( papszDirList[iFile], "style.kml" ) )
+        {
+            ParseStyles( AsDocument( poKmlContainer ), &m_poStyleTable );
+            pszStylePath = CPLStrdup(const_cast<char *>("style.kml"));
             continue;
         }
 
-
         /***** create the layer *****/
-
-        AddLayer ( CPLGetBasename ( osFilePath.c_str() ),
-                   poOgrSRS, wkbUnknown,
-                   this, poKmlRoot, poKmlContainer, osFilePath.c_str(), FALSE, bUpdateIn, nFiles );
-
+        AddLayer( CPLGetBasename( osFilePath.c_str() ),
+                  poOgrSRS, wkbUnknown,
+                  this, poKmlRoot, poKmlContainer, osFilePath.c_str(), FALSE,
+                  bUpdateIn, nFiles );
     }
 
     delete poOgrSRS;
 
-    CSLDestroy ( papszDirList );
+    CSLDestroy( papszDirList );
 
-    if ( nLayers > 0 ) {
-        m_isDir = TRUE;
+    if( nLayers > 0 )
+    {
+        m_isDir = true;
         return TRUE;
     }
 
@@ -1417,7 +1369,7 @@ int OGRLIBKMLDataSource::OpenDir (
 }
 
 /******************************************************************************
- Method to open a datasource
+ Method to open a datasource.
 
  Args:          pszFilename Darasource to open
                 bUpdate     update mode
@@ -1426,16 +1378,16 @@ int OGRLIBKMLDataSource::OpenDir (
 
 ******************************************************************************/
 
-static int CheckIsKMZ(const char *pszFilename)
+static bool CheckIsKMZ( const char *pszFilename )
 {
     char** papszFiles = VSIReadDir(pszFilename);
     char** papszIter = papszFiles;
-    int bFoundKML = FALSE;
-    while(papszIter && *papszIter)
+    bool bFoundKML = false;
+    while( papszIter && *papszIter )
     {
-        if (EQUAL(CPLGetExtension(*papszIter), "kml"))
+        if( EQUAL(CPLGetExtension(*papszIter), "kml") )
         {
-            bFoundKML = TRUE;
+            bFoundKML = true;
             break;
         }
         else
@@ -1443,96 +1395,93 @@ static int CheckIsKMZ(const char *pszFilename)
             CPLString osFilename(pszFilename);
             osFilename += "/";
             osFilename += *papszIter;
-            if (CheckIsKMZ(osFilename))
+            if( CheckIsKMZ(osFilename) )
             {
-                bFoundKML = TRUE;
+                bFoundKML = true;
                 break;
             }
         }
-        papszIter ++;
+        papszIter++;
     }
     CSLDestroy(papszFiles);
     return bFoundKML;
 }
 
-int OGRLIBKMLDataSource::Open (
-    const char *pszFilename,
-    int bUpdateIn )
+int OGRLIBKMLDataSource::Open( const char *pszFilename, int bUpdateIn )
 {
-
-    this->bUpdate = bUpdateIn;
-    pszName = CPLStrdup ( pszFilename );
+    bUpdate = CPL_TO_BOOL(bUpdateIn);
+    pszName = CPLStrdup( pszFilename );
 
     /***** dir *****/
-
     VSIStatBufL sStatBuf;
-    if ( !VSIStatExL ( pszFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) &&
-         VSI_ISDIR ( sStatBuf.st_mode ) )
-        return OpenDir ( pszFilename, bUpdate );
-
-   /***** kml *****/
+    if( !VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_NATURE_FLAG ) &&
+         VSI_ISDIR( sStatBuf.st_mode ) )
+    {
+        return OpenDir( pszFilename, bUpdate );
+    }
 
-    else if ( EQUAL ( CPLGetExtension ( pszFilename ), "kml" ) )
-        return OpenKml ( pszFilename, bUpdate );
+    /***** kml *****/
+    if( EQUAL( CPLGetExtension( pszFilename ), "kml" ) )
+    {
+        return OpenKml( pszFilename, bUpdate );
+    }
 
     /***** kmz *****/
-
-    else if ( EQUAL ( CPLGetExtension ( pszFilename ), "kmz" ) )
-        return OpenKmz ( pszFilename, bUpdate );
-
-    else
+    if( EQUAL( CPLGetExtension( pszFilename ), "kmz" ) )
     {
-        char szBuffer[1024+1];
-        VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
-        if (fp == NULL)
-            return FALSE;
-
-        int nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp));
-        szBuffer[nRead] = 0;
+        return OpenKmz( pszFilename, bUpdate );
+    }
 
-        VSIFCloseL(fp);
+    VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
+    if( fp == NULL )
+        return FALSE;
 
-        /* Does it look like a zip file ? */
-        if (nRead == 1024 &&
-            szBuffer[0] == 0x50 && szBuffer[1] == 0x4B &&
-            szBuffer[2] == 0x03  && szBuffer[3] == 0x04)
-        {
-            CPLString osFilename("/vsizip/");
-            osFilename += pszFilename;
-            if (!CheckIsKMZ(osFilename))
-                return FALSE;
+    char szBuffer[1024+1] = {};
+    const int nRead = static_cast<int>(VSIFReadL(szBuffer, 1, 1024, fp));
+    szBuffer[nRead] = 0;
 
-            return OpenKmz ( pszFilename, bUpdate );
-        }
+    VSIFCloseL(fp);
 
-        if (strstr(szBuffer, "<kml>") || strstr(szBuffer, "<kml xmlns="))
-            return OpenKml ( pszFilename, bUpdate );
+    // Does it look like a zip file?
+    if( nRead == 1024 &&
+        szBuffer[0] == 0x50 && szBuffer[1] == 0x4B &&
+        szBuffer[2] == 0x03 && szBuffer[3] == 0x04 )
+    {
+        CPLString osFilename("/vsizip/");
+        osFilename += pszFilename;
+        if( !CheckIsKMZ(osFilename) )
+            return FALSE;
 
-        return FALSE;
+        return OpenKmz( pszFilename, bUpdate );
     }
+
+    if( strstr(szBuffer, "<kml>") || strstr(szBuffer, "<kml xmlns=") )
+        return OpenKml( pszFilename, bUpdate );
+
+    return FALSE;
 }
 
 /************************************************************************/
 /*                         IsValidPhoneNumber()                         */
 /************************************************************************/
 
-/* Very approximative validation of http://tools.ietf.org/html/rfc3966#page-6 */
-static int IsValidPhoneNumber(const char* pszPhoneNumber)
+// Very approximative validation of http://tools.ietf.org/html/rfc3966#page-6
+static bool IsValidPhoneNumber( const char* pszPhoneNumber )
 {
     if( STARTS_WITH(pszPhoneNumber, "tel:") )
         pszPhoneNumber += strlen("tel:");
-    char ch;
-    int bDigitFound = FALSE;
+    char ch = '\0';
+    bool bDigitFound = false;
     if( *pszPhoneNumber == '+' )
         pszPhoneNumber ++;
     while( (ch = *pszPhoneNumber) != '\0' )
     {
         if( ch >= '0' && ch <= '9' )
-            bDigitFound = TRUE;
+            bDigitFound = true;
         else if( ch == ';' )
             break;
         else if( !(ch == '-' || ch == '.' || ch == '(' || ch == ')') )
-            return FALSE;
+            return false;
         pszPhoneNumber ++;
     }
     return bDigitFound;
@@ -1542,8 +1491,8 @@ static int IsValidPhoneNumber(const char* pszPhoneNumber)
 /*                           SetCommonOptions()                         */
 /************************************************************************/
 
-void OGRLIBKMLDataSource::SetCommonOptions(ContainerPtr poKmlContainer,
-                                           char** papszOptions)
+void OGRLIBKMLDataSource::SetCommonOptions( ContainerPtr poKmlContainer,
+                                            char** papszOptions )
 {
     const char* l_pszName = CSLFetchNameValue(papszOptions, "NAME");
     if( l_pszName != NULL )
@@ -1574,26 +1523,34 @@ void OGRLIBKMLDataSource::SetCommonOptions(ContainerPtr poKmlContainer,
 /*                        ParseDocumentOptions()                        */
 /************************************************************************/
 
-void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
-                                               DocumentPtr poKmlDocument)
+void OGRLIBKMLDataSource::ParseDocumentOptions( KmlPtr poKml,
+                                                DocumentPtr poKmlDocument )
 {
     if( poKmlDocument != NULL )
     {
-        poKmlDocument->set_id("root_doc");
-
-        const char* pszAuthorName = CSLFetchNameValue(m_papszOptions, "AUTHOR_NAME");
-        const char* pszAuthorURI = CSLFetchNameValue(m_papszOptions, "AUTHOR_URI");
-        const char* pszAuthorEmail = CSLFetchNameValue(m_papszOptions, "AUTHOR_EMAIL");
-        const char* pszLink = CSLFetchNameValue(m_papszOptions, "LINK");
-
-        if( pszAuthorName != NULL || pszAuthorURI != NULL || pszAuthorEmail != NULL )
+        const char* pszDocumentId =
+            CSLFetchNameValueDef(m_papszOptions, "DOCUMENT_ID", "root_doc");
+        poKmlDocument->set_id(pszDocumentId);
+
+        const char* pszAuthorName =
+            CSLFetchNameValue(m_papszOptions, "AUTHOR_NAME");
+        const char* pszAuthorURI =
+            CSLFetchNameValue(m_papszOptions, "AUTHOR_URI");
+        const char* pszAuthorEmail =
+            CSLFetchNameValue(m_papszOptions, "AUTHOR_EMAIL");
+        const char* pszLink =
+            CSLFetchNameValue(m_papszOptions, "LINK");
+
+        if( pszAuthorName != NULL || pszAuthorURI != NULL ||
+            pszAuthorEmail != NULL )
         {
             kmldom::AtomAuthorPtr author = m_poKmlFactory->CreateAtomAuthor();
             if( pszAuthorName != NULL )
                 author->set_name(pszAuthorName);
             if( pszAuthorURI != NULL )
             {
-                /* Ad-hoc validation. The ABNF is horribly complicated : http://tools.ietf.org/search/rfc3987#page-7 */
+                // Ad-hoc validation. The ABNF is horribly complicated:
+                // http://tools.ietf.org/search/rfc3987#page-7
                 if( STARTS_WITH(pszAuthorURI, "http://") ||
                     STARTS_WITH(pszAuthorURI, "https://") )
                 {
@@ -1601,7 +1558,8 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
                 }
                 else
                 {
-                    CPLError(CE_Warning, CPLE_AppDefined, "Invalid IRI for AUTHOR_URI");
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Invalid IRI for AUTHOR_URI");
                 }
             }
             if( pszAuthorEmail != NULL )
@@ -1613,7 +1571,8 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
                 }
                 else
                 {
-                    CPLError(CE_Warning, CPLE_AppDefined, "Invalid email for AUTHOR_EMAIL");
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Invalid email for AUTHOR_EMAIL");
                 }
             }
             poKmlDocument->set_atomauthor(author);
@@ -1627,13 +1586,15 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
             poKmlDocument->set_atomlink(link);
         }
 
-        const char* pszPhoneNumber = CSLFetchNameValue(m_papszOptions, "PHONENUMBER");
+        const char* pszPhoneNumber =
+            CSLFetchNameValue(m_papszOptions, "PHONENUMBER");
         if( pszPhoneNumber != NULL )
         {
             if( IsValidPhoneNumber(pszPhoneNumber) )
             {
                 if( !STARTS_WITH(pszPhoneNumber, "tel:") )
-                    poKmlDocument->set_phonenumber(CPLSPrintf("tel:%s", pszPhoneNumber));
+                    poKmlDocument->set_phonenumber(
+                        CPLSPrintf("tel:%s", pszPhoneNumber));
                 else
                     poKmlDocument->set_phonenumber(pszPhoneNumber);
             }
@@ -1645,14 +1606,16 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
 
         SetCommonOptions(poKmlDocument, m_papszOptions);
 
-        CPLString osListStyleType = CSLFetchNameValueDef(m_papszOptions, "LISTSTYLE_TYPE", "");
-        CPLString osListStyleIconHref = CSLFetchNameValueDef(m_papszOptions, "LISTSTYLE_ICON_HREF", "");
-        createkmlliststyle (m_poKmlFactory,
-                            "root_doc",
+        CPLString osListStyleType =
+            CSLFetchNameValueDef(m_papszOptions, "LISTSTYLE_TYPE", "");
+        CPLString osListStyleIconHref =
+            CSLFetchNameValueDef(m_papszOptions, "LISTSTYLE_ICON_HREF", "");
+        createkmlliststyle( m_poKmlFactory,
+                            pszDocumentId,
                             poKmlDocument,
                             poKmlDocument,
                             osListStyleType,
-                            osListStyleIconHref);
+                            osListStyleIconHref );
     }
 
     if( poKml != NULL )
@@ -1660,43 +1623,58 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
         if( m_poKmlUpdate != NULL )
         {
             NetworkLinkControlPtr nlc = m_poKmlFactory->CreateNetworkLinkControl();
-            poKml->set_networklinkcontrol ( nlc );
+            poKml->set_networklinkcontrol( nlc );
             if( m_poKmlUpdate->get_updateoperation_array_size() != 0 )
             {
                 nlc->set_update(m_poKmlUpdate);
             }
         }
 
-        const char* pszNLCMinRefreshPeriod = CSLFetchNameValue(m_papszOptions, "NLC_MINREFRESHPERIOD");
-        const char* pszNLCMaxSessionLength = CSLFetchNameValue(m_papszOptions, "NLC_MAXSESSIONLENGTH");
-        const char* pszNLCCookie = CSLFetchNameValue(m_papszOptions, "NLC_COOKIE");
-        const char* pszNLCMessage = CSLFetchNameValue(m_papszOptions, "NLC_MESSAGE");
-        const char* pszNLCLinkName = CSLFetchNameValue(m_papszOptions, "NLC_LINKNAME");
-        const char* pszNLCLinkDescription = CSLFetchNameValue(m_papszOptions, "NLC_LINKDESCRIPTION");
-        const char* pszNLCLinkSnippet = CSLFetchNameValue(m_papszOptions, "NLC_LINKSNIPPET");
-        const char* pszNLCExpires = CSLFetchNameValue(m_papszOptions, "NLC_EXPIRES");
-        if( pszNLCMinRefreshPeriod != NULL || pszNLCMaxSessionLength != NULL ||
-            pszNLCCookie != NULL || pszNLCMessage != NULL || pszNLCLinkName != NULL ||
-            pszNLCLinkDescription != NULL || pszNLCLinkSnippet != NULL ||
+        const char* pszNLCMinRefreshPeriod =
+            CSLFetchNameValue(m_papszOptions, "NLC_MINREFRESHPERIOD");
+        const char* pszNLCMaxSessionLength =
+            CSLFetchNameValue(m_papszOptions, "NLC_MAXSESSIONLENGTH");
+        const char* pszNLCCookie =
+            CSLFetchNameValue(m_papszOptions, "NLC_COOKIE");
+        const char* pszNLCMessage =
+            CSLFetchNameValue(m_papszOptions, "NLC_MESSAGE");
+        const char* pszNLCLinkName =
+            CSLFetchNameValue(m_papszOptions, "NLC_LINKNAME");
+        const char* pszNLCLinkDescription =
+            CSLFetchNameValue(m_papszOptions, "NLC_LINKDESCRIPTION");
+        const char* pszNLCLinkSnippet =
+            CSLFetchNameValue(m_papszOptions, "NLC_LINKSNIPPET");
+        const char* pszNLCExpires =
+            CSLFetchNameValue(m_papszOptions, "NLC_EXPIRES");
+
+        if( pszNLCMinRefreshPeriod != NULL ||
+            pszNLCMaxSessionLength != NULL ||
+            pszNLCCookie != NULL ||
+            pszNLCMessage != NULL ||
+            pszNLCLinkName != NULL ||
+            pszNLCLinkDescription != NULL ||
+            pszNLCLinkSnippet != NULL ||
             pszNLCExpires != NULL )
         {
-            NetworkLinkControlPtr nlc;
+            NetworkLinkControlPtr nlc = NULL;
             if( poKml->has_networklinkcontrol() )
+            {
                 nlc = poKml->get_networklinkcontrol();
+            }
             else
             {
                 nlc = m_poKmlFactory->CreateNetworkLinkControl();
-                poKml->set_networklinkcontrol ( nlc );
+                poKml->set_networklinkcontrol( nlc );
             }
             if( pszNLCMinRefreshPeriod != NULL )
             {
-                double dfVal = CPLAtof(pszNLCMinRefreshPeriod);
+                const double dfVal = CPLAtof(pszNLCMinRefreshPeriod);
                 if( dfVal >= 0 )
                     nlc->set_minrefreshperiod(dfVal);
             }
             if( pszNLCMaxSessionLength != NULL )
             {
-                double dfVal = CPLAtof(pszNLCMaxSessionLength);
+                const double dfVal = CPLAtof(pszNLCMaxSessionLength);
                 nlc->set_maxsessionlength(dfVal);
             }
             if( pszNLCCookie != NULL )
@@ -1717,7 +1695,8 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
             }
             if( pszNLCLinkSnippet != NULL )
             {
-                LinkSnippetPtr linksnippet = m_poKmlFactory->CreateLinkSnippet();
+                LinkSnippetPtr linksnippet =
+                    m_poKmlFactory->CreateLinkSnippet();
                 linksnippet->set_text(pszNLCLinkSnippet);
                 nlc->set_linksnippet(linksnippet);
             }
@@ -1736,7 +1715,7 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
 }
 
 /******************************************************************************
- method to create a single file .kml ds
+ Method to create a single file .kml ds.
 
  Args:          pszFilename     the datasource to create
                 papszOptions    datasource creation options
@@ -1745,26 +1724,26 @@ void OGRLIBKMLDataSource::ParseDocumentOptions(KmlPtr poKml,
 
 ******************************************************************************/
 
-int OGRLIBKMLDataSource::CreateKml (
-    CPL_UNUSED const char *pszFilename,
+int OGRLIBKMLDataSource::CreateKml(
+    const char * /* pszFilename */,
     char **papszOptions )
 {
     m_poKmlDSKml = OGRLIBKMLCreateOGCKml22(m_poKmlFactory, papszOptions);
-    if( osUpdateTargetHref.size() == 0 )
+    if( osUpdateTargetHref.empty() )
     {
-        DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument (  );
-        m_poKmlDSKml->set_feature ( poKmlDocument );
+        DocumentPtr poKmlDocument = m_poKmlFactory->CreateDocument();
+        m_poKmlDSKml->set_feature( poKmlDocument );
         m_poKmlDSContainer = poKmlDocument;
     }
 
-    m_isKml = TRUE;
-    bUpdated = TRUE;
+    m_isKml = true;
+    bUpdated = true;
 
     return true;
 }
 
 /******************************************************************************
- method to create a .kmz ds
+ Method to create a .kmz ds.
 
  Args:          pszFilename     the datasource to create
                 papszOptions    datasource creation options
@@ -1773,31 +1752,32 @@ int OGRLIBKMLDataSource::CreateKml (
 
 ******************************************************************************/
 
-int OGRLIBKMLDataSource::CreateKmz (
-    CPL_UNUSED const char *pszFilename,
-    CPL_UNUSED char **papszOptions )
+int OGRLIBKMLDataSource::CreateKmz(
+    const char * /* pszFilename */,
+    char ** /* papszOptions */ )
 {
     /***** create the doc.kml  *****/
-    if( osUpdateTargetHref.size() == 0 )
+    if( osUpdateTargetHref.empty() )
     {
         const char *pszUseDocKml =
-            CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
+            CPLGetConfigOption( "LIBKML_USE_DOC.KML", "yes" );
 
-        if ( CPLTestBool( pszUseDocKml ) ) {
-            m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
+        if( CPLTestBool( pszUseDocKml ) )
+        {
+            m_poKmlDocKml = m_poKmlFactory->CreateDocument();
         }
     }
 
-    pszStylePath = CPLStrdup((char *) "style/style.kml");
+    pszStylePath = CPLStrdup(const_cast<char *>("style/style.kml"));
 
-    m_isKmz = TRUE;
-    bUpdated = TRUE;
+    m_isKmz = true;
+    bUpdated = true;
 
     return TRUE;
 }
 
 /******************************************************************************
- Method to create a dir datasource
+ Method to create a dir datasource.
 
  Args:          pszFilename     the datasource to create
                 papszOptions    datasource creation options
@@ -1806,37 +1786,38 @@ int OGRLIBKMLDataSource::CreateKmz (
 
 ******************************************************************************/
 
-int OGRLIBKMLDataSource::CreateDir (
+int OGRLIBKMLDataSource::CreateDir(
     const char *pszFilename,
-    CPL_UNUSED char **papszOptions )
+    char ** /* papszOptions */ )
 {
-    if ( VSIMkdir ( pszFilename, 0755 ) ) {
-        CPLError ( CE_Failure, CPLE_AppDefined,
-                   "ERROR Creating dir: %s for KML datasource", pszFilename );
+    if( VSIMkdir( pszFilename, 0755 ) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "ERROR Creating dir: %s for KML datasource", pszFilename );
         return FALSE;
     }
 
-    m_isDir = TRUE;
-    bUpdated = TRUE;
+    m_isDir = true;
+    bUpdated = true;
 
-    if( osUpdateTargetHref.size() == 0 )
+    if( osUpdateTargetHref.empty() )
     {
         const char *pszUseDocKml =
-            CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
+            CPLGetConfigOption( "LIBKML_USE_DOC.KML", "yes" );
 
-        if ( CPLTestBool( pszUseDocKml ) ) {
-            m_poKmlDocKml = m_poKmlFactory->CreateDocument (  );
+        if( CPLTestBool( pszUseDocKml ) )
+        {
+            m_poKmlDocKml = m_poKmlFactory->CreateDocument();
         }
     }
 
-    pszStylePath = CPLStrdup((char *) "style.kml");
+    pszStylePath = CPLStrdup(const_cast<char *>("style.kml"));
 
     return TRUE;
 }
 
-
 /******************************************************************************
- method to create a datasource
+ Method to create a datasource.
 
  Args:          pszFilename     the datasource to create
                 papszOptions    datasource creation options
@@ -1848,21 +1829,19 @@ int OGRLIBKMLDataSource::CreateDir (
 
 ******************************************************************************/
 
-int OGRLIBKMLDataSource::Create (
+int OGRLIBKMLDataSource::Create(
     const char *pszFilename,
     char **papszOptions )
 {
-
-    int bResult = FALSE;
-
-    if (strcmp(pszFilename, "/dev/stdout") == 0)
+    if( strcmp(pszFilename, "/dev/stdout") == 0 )
         pszFilename = "/vsistdout/";
 
-    pszName = CPLStrdup ( pszFilename );
-    bUpdate = TRUE;
+    pszName = CPLStrdup( pszFilename );
+    bUpdate = true;
 
-    osUpdateTargetHref = CSLFetchNameValueDef(papszOptions, "UPDATE_TARGETHREF", "");
-    if( osUpdateTargetHref.size() )
+    osUpdateTargetHref =
+        CSLFetchNameValueDef(papszOptions, "UPDATE_TARGETHREF", "");
+    if( !osUpdateTargetHref.empty() )
     {
         m_poKmlUpdate = m_poKmlFactory->CreateUpdate();
         m_poKmlUpdate->set_targethref(osUpdateTargetHref.c_str());
@@ -1871,27 +1850,21 @@ int OGRLIBKMLDataSource::Create (
     m_papszOptions = CSLDuplicate(papszOptions);
 
     /***** kml *****/
-
-    if ( strcmp(pszFilename, "/vsistdout/") == 0 ||
-         STARTS_WITH(pszFilename, "/vsigzip/") ||
-         EQUAL ( CPLGetExtension ( pszFilename ), "kml" ) )
-        bResult = CreateKml ( pszFilename, papszOptions );
+    if( strcmp(pszFilename, "/vsistdout/") == 0 ||
+        STARTS_WITH(pszFilename, "/vsigzip/") ||
+        EQUAL( CPLGetExtension( pszFilename ), "kml" ) )
+        return CreateKml( pszFilename, papszOptions );
 
     /***** kmz *****/
-
-    else if ( EQUAL ( CPLGetExtension ( pszFilename ), "kmz" ) )
-        bResult = CreateKmz ( pszFilename, papszOptions );
+    if( EQUAL( CPLGetExtension( pszFilename ), "kmz" ) )
+        return CreateKmz( pszFilename, papszOptions );
 
     /***** dir *****/
-
-    else
-        bResult = CreateDir ( pszFilename, papszOptions );
-
-    return bResult;
+    return CreateDir( pszFilename, papszOptions );
 }
 
 /******************************************************************************
- method to get a layer by index
+ Method to get a layer by index.
 
  Args:          iLayer      the index of the layer to get
 
@@ -1899,18 +1872,16 @@ int OGRLIBKMLDataSource::Create (
 
 ******************************************************************************/
 
-OGRLayer *OGRLIBKMLDataSource::GetLayer (
-    int iLayer )
+OGRLayer *OGRLIBKMLDataSource::GetLayer( int iLayer )
 {
-    if ( iLayer < 0 || iLayer >= nLayers )
+    if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
 
+    return papoLayers[iLayer];
 }
 
 /******************************************************************************
- method to get a layer by name
+ Method to get a layer by name.
 
  Args:          pszname     name of the layer to get
 
@@ -1918,22 +1889,19 @@ OGRLayer *OGRLIBKMLDataSource::GetLayer (
 
 ******************************************************************************/
 
-OGRLayer *OGRLIBKMLDataSource::GetLayerByName (
-    const char *pszname )
+OGRLayer *OGRLIBKMLDataSource::GetLayerByName( const char *pszname )
 {
-    int iLayer = 0;
-
-    for ( iLayer = 0; iLayer < nLayers; iLayer++ ) {
-        if ( EQUAL ( pszname, papoLayers[iLayer]->GetName (  ) ) )
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
+    {
+        if( EQUAL( pszname, papoLayers[iLayer]->GetName() ) )
             return papoLayers[iLayer];
     }
 
     return NULL;
 }
 
-
 /******************************************************************************
- method to DeleteLayers in a .kml datasource
+ Method to DeleteLayers in a .kml datasource.
 
  Args:          iLayer  index of the layer to delete
 
@@ -1941,33 +1909,31 @@ OGRLayer *OGRLIBKMLDataSource::GetLayerByName (
 
 ******************************************************************************/
 
-OGRErr OGRLIBKMLDataSource::DeleteLayerKml (
-    int iLayer )
+OGRErr OGRLIBKMLDataSource::DeleteLayerKml( int iLayer )
 {
     OGRLIBKMLLayer *poOgrLayer = ( OGRLIBKMLLayer * ) papoLayers[iLayer];
 
     /***** loop over the features *****/
 
-    size_t nKmlFeatures = m_poKmlDSContainer->get_feature_array_size (  );
-    size_t iKmlFeature;
+    const size_t nKmlFeatures = m_poKmlDSContainer->get_feature_array_size();
 
-    for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
+    for( size_t iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ )
+    {
         FeaturePtr poKmlFeat =
-            m_poKmlDSContainer->get_feature_array_at ( iKmlFeature );
+            m_poKmlDSContainer->get_feature_array_at( iKmlFeature );
 
-        if ( poKmlFeat == poOgrLayer->GetKmlLayer (  ) ) {
-            m_poKmlDSContainer->DeleteFeatureAt ( iKmlFeature );
+        if( poKmlFeat == poOgrLayer->GetKmlLayer() )
+        {
+            m_poKmlDSContainer->DeleteFeatureAt( iKmlFeature );
             break;
         }
-
     }
 
-
     return OGRERR_NONE;
 }
 
 /******************************************************************************
- method to DeleteLayers in a .kmz datasource
+ Method to DeleteLayers in a .kmz datasource.
 
  Args:          iLayer  index of the layer to delete
 
@@ -1975,66 +1941,63 @@ OGRErr OGRLIBKMLDataSource::DeleteLayerKml (
 
 ******************************************************************************/
 
-OGRErr OGRLIBKMLDataSource::DeleteLayerKmz (
-    int iLayer )
+OGRErr OGRLIBKMLDataSource::DeleteLayerKmz( int iLayer )
 {
-    OGRLIBKMLLayer *poOgrLayer = ( OGRLIBKMLLayer * ) papoLayers[iLayer];
+    OGRLIBKMLLayer *poOgrLayer = papoLayers[iLayer];
 
     const char *pszUseDocKml =
-        CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
-
-    if ( CPLTestBool ( pszUseDocKml ) && m_poKmlDocKml ) {
+        CPLGetConfigOption( "LIBKML_USE_DOC.KML", "yes" );
 
+    if( CPLTestBool( pszUseDocKml ) && m_poKmlDocKml )
+    {
         /***** loop over the features *****/
+        const size_t nKmlFeatures = m_poKmlDocKml->get_feature_array_size();
 
-        size_t nKmlFeatures = m_poKmlDocKml->get_feature_array_size (  );
-        size_t iKmlFeature;
-
-        for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
+        for( size_t iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ )
+        {
             FeaturePtr poKmlFeat =
-                m_poKmlDocKml->get_feature_array_at ( iKmlFeature );
+                m_poKmlDocKml->get_feature_array_at( iKmlFeature );
 
-            if ( poKmlFeat->IsA ( kmldom::Type_NetworkLink ) ) {
-                NetworkLinkPtr poKmlNetworkLink = AsNetworkLink ( poKmlFeat );
+            if( poKmlFeat->IsA( kmldom::Type_NetworkLink ) )
+            {
+                NetworkLinkPtr poKmlNetworkLink = AsNetworkLink( poKmlFeat );
 
                 /***** does it have a link? *****/
-
-                if ( poKmlNetworkLink->has_link (  ) ) {
-                    LinkPtr poKmlLink = poKmlNetworkLink->get_link (  );
+                if( poKmlNetworkLink->has_link() )
+                {
+                    LinkPtr poKmlLink = poKmlNetworkLink->get_link();
 
                     /***** does the link have a href? *****/
-
-                    if ( poKmlLink->has_href (  ) ) {
+                    if( poKmlLink->has_href() )
+                    {
                         kmlengine::Href * poKmlHref =
-                            new kmlengine::Href ( poKmlLink->get_href (  ) );
+                            new kmlengine::Href( poKmlLink->get_href() );
 
                         /***** is the link relative? *****/
-
-                        if ( poKmlHref->IsRelativePath (  ) ) {
-
-                            const char *pszLink =
-                                poKmlHref->get_path (  ).c_str (  );
-
-                            if ( EQUAL
-                                 ( pszLink, poOgrLayer->GetFileName (  ) ) ) {
-                                m_poKmlDocKml->DeleteFeatureAt ( iKmlFeature );
+                        if( poKmlHref->IsRelativePath() )
+                        {
+                            const char *pszLink = poKmlHref->get_path().c_str();
+
+                            if( EQUAL( pszLink, poOgrLayer->GetFileName() ) )
+                            {
+                                m_poKmlDocKml->DeleteFeatureAt( iKmlFeature );
+                                delete poKmlHref;
                                 break;
                             }
-
-
                         }
+
+                        delete poKmlHref;
                     }
                 }
             }
         }
-
     }
 
     return OGRERR_NONE;
 }
 
 /******************************************************************************
- method to delete a layer in a datasource
+ Method to delete a layer in a datasource.
 
  Args:          iLayer  index of the layer to delete
 
@@ -2042,52 +2005,53 @@ OGRErr OGRLIBKMLDataSource::DeleteLayerKmz (
 
 ******************************************************************************/
 
-OGRErr OGRLIBKMLDataSource::DeleteLayer (
-    int iLayer )
+OGRErr OGRLIBKMLDataSource::DeleteLayer( int iLayer )
 {
-
-    if ( !bUpdate )
+    if( !bUpdate )
         return OGRERR_UNSUPPORTED_OPERATION;
 
-    if ( iLayer >= nLayers )
+    if( iLayer >= nLayers )
         return OGRERR_FAILURE;
 
-    if ( IsKml (  ) )
-        DeleteLayerKml ( iLayer );
-
-    else if ( IsKmz (  ) )
-        DeleteLayerKmz ( iLayer );
-
-    else if ( IsDir (  ) ) {
-        DeleteLayerKmz ( iLayer );
+    if( IsKml() )
+    {
+        DeleteLayerKml( iLayer );
+    }
+    else if( IsKmz() )
+    {
+        DeleteLayerKmz( iLayer );
+    }
+    else if( IsDir() )
+    {
+        DeleteLayerKmz( iLayer );
 
         /***** delete the file the layer corresponds to *****/
-
         const char *pszFilePath =
-            CPLFormFilename ( pszName, papoLayers[iLayer]->GetFileName (  ),
+            CPLFormFilename( pszName, papoLayers[iLayer]->GetFileName(),
                               NULL );
         VSIStatBufL oStatBufL;
-        if ( !VSIStatL ( pszFilePath, &oStatBufL ) ) {
-            if ( VSIUnlink ( pszFilePath ) ) {
-                CPLError ( CE_Failure, CPLE_AppDefined,
-                           "ERROR Deleteing Layer %s from filesystem as %s",
-                           papoLayers[iLayer]->GetName (  ), pszFilePath );
+        if( !VSIStatL( pszFilePath, &oStatBufL ) )
+        {
+            if( VSIUnlink( pszFilePath ) )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "ERROR Deleting Layer %s from filesystem as %s",
+                          papoLayers[iLayer]->GetName(), pszFilePath );
             }
         }
     }
 
-
     delete papoLayers[iLayer];
-    memmove ( papoLayers + iLayer, papoLayers + iLayer + 1,
-              sizeof ( void * ) * ( nLayers - iLayer - 1 ) );
+    memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
+             sizeof( void * ) * ( nLayers - iLayer - 1 ) );
     nLayers--;
-    bUpdated = TRUE;
+    bUpdated = true;
 
     return OGRERR_NONE;
 }
 
 /******************************************************************************
- method to create a layer in a single file .kml
+ Method to create a layer in a single file .kml.
 
  Args:          pszLayerName    name of the layer to create
                 poOgrSRS        the SRS of the layer
@@ -2098,36 +2062,34 @@ OGRErr OGRLIBKMLDataSource::DeleteLayer (
 
 ******************************************************************************/
 
-OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKml (
+OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKml(
     const char *pszLayerName,
     OGRSpatialReference * poOgrSRS,
     OGRwkbGeometryType eGType,
     char **papszOptions )
 {
-
-    OGRLIBKMLLayer *poOgrLayer = NULL;
     ContainerPtr poKmlLayerContainer = NULL;
 
     if( m_poKmlDSContainer != NULL )
     {
-        if( CSLFetchBoolean( papszOptions, "FOLDER", FALSE ) )
-            poKmlLayerContainer = m_poKmlFactory->CreateFolder (  );
+        if( CPLFetchBool( papszOptions, "FOLDER", false ) )
+            poKmlLayerContainer = m_poKmlFactory->CreateFolder();
         else
-            poKmlLayerContainer = m_poKmlFactory->CreateDocument (  );
+            poKmlLayerContainer = m_poKmlFactory->CreateDocument();
         poKmlLayerContainer->set_id(OGRLIBKMLGetSanitizedNCName(pszLayerName).c_str());
 
-        m_poKmlDSContainer->add_feature ( poKmlLayerContainer );
+        m_poKmlDSContainer->add_feature( poKmlLayerContainer );
     }
 
     /***** create the layer *****/
-
-    poOgrLayer = AddLayer ( pszLayerName, poOgrSRS, eGType, this,
-                            NULL, poKmlLayerContainer, "", TRUE, bUpdate, 1 );
+    OGRLIBKMLLayer *poOgrLayer =
+        AddLayer( pszLayerName, poOgrSRS, eGType, this,
+                  NULL, poKmlLayerContainer, "", TRUE, bUpdate, 1 );
 
     /***** add the layer name as a <Name> *****/
     if( poKmlLayerContainer != NULL )
-        poKmlLayerContainer->set_name ( pszLayerName );
-    else if(  CSLFetchBoolean( papszOptions, "FOLDER", FALSE ) )
+        poKmlLayerContainer->set_name( pszLayerName );
+    else if(  CPLFetchBool( papszOptions, "FOLDER", false ) )
     {
         poOgrLayer->SetUpdateIsFolder(TRUE);
     }
@@ -2136,7 +2098,7 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKml (
 }
 
 /******************************************************************************
- method to create a layer in a .kmz or dir
+ Method to create a layer in a .kmz or dir.
 
  Args:          pszLayerName    name of the layer to create
                 poOgrSRS        the SRS of the layer
@@ -2147,63 +2109,61 @@ OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKml (
 
 ******************************************************************************/
 
-OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKmz (
+OGRLIBKMLLayer *OGRLIBKMLDataSource::CreateLayerKmz(
     const char *pszLayerName,
     OGRSpatialReference * poOgrSRS,
     OGRwkbGeometryType eGType,
-    CPL_UNUSED char **papszOptions )
+    char ** /* papszOptions */ )
 {
-    OGRLIBKMLLayer *poOgrLayer = NULL;
     DocumentPtr poKmlDocument = NULL;
 
     if( m_poKmlUpdate == NULL )
     {
         /***** add a network link to doc.kml *****/
-
         const char *pszUseDocKml =
-            CPLGetConfigOption ( "LIBKML_USE_DOC.KML", "yes" );
-
-        if ( CPLTestBool ( pszUseDocKml ) && m_poKmlDocKml ) {
+            CPLGetConfigOption( "LIBKML_USE_DOC.KML", "yes" );
 
-            poKmlDocument = AsDocument ( m_poKmlDocKml );
+        if( CPLTestBool( pszUseDocKml ) && m_poKmlDocKml )
+        {
+            poKmlDocument = AsDocument( m_poKmlDocKml );
 
-            NetworkLinkPtr poKmlNetLink = m_poKmlFactory->CreateNetworkLink (  );
-            LinkPtr poKmlLink = m_poKmlFactory->CreateLink (  );
+            NetworkLinkPtr poKmlNetLink = m_poKmlFactory->CreateNetworkLink();
+            LinkPtr poKmlLink = m_poKmlFactory->CreateLink();
 
             std::string oHref;
             if( IsKmz() )
-                oHref.append ( "layers/" );
-            oHref.append ( pszLayerName );
-            oHref.append ( ".kml" );
-            poKmlLink->set_href ( oHref );
-
-            poKmlNetLink->set_link ( poKmlLink );
-            poKmlDocument->add_feature ( poKmlNetLink );
+                oHref.append( "layers/" );
+            oHref.append( pszLayerName );
+            oHref.append( ".kml" );
+            poKmlLink->set_href( oHref );
 
+            poKmlNetLink->set_link( poKmlLink );
+            poKmlDocument->add_feature( poKmlNetLink );
         }
 
         /***** create the layer *****/
 
-        poKmlDocument = m_poKmlFactory->CreateDocument (  );
+        poKmlDocument = m_poKmlFactory->CreateDocument();
         poKmlDocument->set_id(OGRLIBKMLGetSanitizedNCName(pszLayerName).c_str());
     }
 
-    poOgrLayer = AddLayer ( pszLayerName, poOgrSRS, eGType, this,
-                            NULL, poKmlDocument,
-                            CPLFormFilename ( NULL, pszLayerName, ".kml" ),
-                            TRUE, bUpdate, 1 );
+    OGRLIBKMLLayer *poOgrLayer =
+        AddLayer( pszLayerName, poOgrSRS, eGType, this,
+                  NULL, poKmlDocument,
+                  CPLFormFilename( NULL, pszLayerName, ".kml" ),
+                  TRUE, bUpdate, 1 );
 
     /***** add the layer name as a <Name> *****/
     if( m_poKmlUpdate == NULL )
     {
-        poKmlDocument->set_name ( pszLayerName );
+        poKmlDocument->set_name( pszLayerName );
     }
 
     return poOgrLayer;
 }
 
 /******************************************************************************
-ICreateLayer()
+ ICreateLayer()
 
  Args:          pszLayerName    name of the layer to create
                 poOgrSRS        the SRS of the layer
@@ -2220,11 +2180,10 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
     OGRwkbGeometryType eGType,
     char **papszOptions )
 {
-
-    if ( !bUpdate )
+    if( !bUpdate )
         return NULL;
 
-    if( (IsKmz () || IsDir ()) && EQUAL(pszLayerName, "doc") )
+    if( (IsKmz() || IsDir()) && EQUAL(pszLayerName, "doc") )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "'doc' is an invalid layer name in a KMZ file");
@@ -2234,27 +2193,33 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
     OGRLIBKMLLayer *poOgrLayer = NULL;
 
     /***** kml DS *****/
-
-    if ( IsKml (  ) ) {
-        poOgrLayer = CreateLayerKml ( pszLayerName, poOgrSRS,
-                                      eGType, papszOptions );
-
-    }
-
-    else if ( IsKmz (  ) || IsDir (  ) ) {
-        poOgrLayer = CreateLayerKmz ( pszLayerName, poOgrSRS,
-                                      eGType, papszOptions );
-
+    if( IsKml() )
+    {
+        poOgrLayer = CreateLayerKml( pszLayerName, poOgrSRS,
+                                     eGType, papszOptions );
     }
-
-    const char* pszLookatLongitude = CSLFetchNameValue(papszOptions, "LOOKAT_LONGITUDE");
-    const char* pszLookatLatitude = CSLFetchNameValue(papszOptions, "LOOKAT_LATITUDE");
-    const char* pszLookatAltitude = CSLFetchNameValue(papszOptions, "LOOKAT_ALTITUDE");
-    const char* pszLookatHeading = CSLFetchNameValue(papszOptions, "LOOKAT_HEADING");
+    else if( IsKmz() || IsDir() )
+    {
+        poOgrLayer = CreateLayerKmz( pszLayerName, poOgrSRS,
+                                     eGType, papszOptions );
+    }
+
+    const char* pszLookatLongitude =
+        CSLFetchNameValue(papszOptions, "LOOKAT_LONGITUDE");
+    const char* pszLookatLatitude =
+        CSLFetchNameValue(papszOptions, "LOOKAT_LATITUDE");
+    const char* pszLookatAltitude =
+        CSLFetchNameValue(papszOptions, "LOOKAT_ALTITUDE");
+    const char* pszLookatHeading =
+        CSLFetchNameValue(papszOptions, "LOOKAT_HEADING");
     const char* pszLookatTilt = CSLFetchNameValue(papszOptions, "LOOKAT_TILT");
-    const char* pszLookatRange = CSLFetchNameValue(papszOptions, "LOOKAT_RANGE");
-    const char* pszLookatAltitudeMode = CSLFetchNameValue(papszOptions, "LOOKAT_ALTITUDEMODE");
-    if( poOgrLayer != NULL && pszLookatLongitude != NULL && pszLookatLatitude != NULL &&
+    const char* pszLookatRange =
+        CSLFetchNameValue(papszOptions, "LOOKAT_RANGE");
+    const char* pszLookatAltitudeMode =
+        CSLFetchNameValue(papszOptions, "LOOKAT_ALTITUDEMODE");
+    if( poOgrLayer != NULL &&
+        pszLookatLongitude != NULL &&
+        pszLookatLatitude != NULL &&
         pszLookatRange != NULL )
     {
         poOgrLayer->SetLookAt(pszLookatLongitude,
@@ -2267,15 +2232,25 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
     }
     else
     {
-        const char* pszCameraLongitude = CSLFetchNameValue(papszOptions, "CAMERA_LONGITUDE");
-        const char* pszCameraLatitude = CSLFetchNameValue(papszOptions, "CAMERA_LATITUDE");
-        const char* pszCameraAltitude = CSLFetchNameValue(papszOptions, "CAMERA_ALTITUDE");
-        const char* pszCameraHeading = CSLFetchNameValue(papszOptions, "CAMERA_HEADING");
-        const char* pszCameraTilt = CSLFetchNameValue(papszOptions, "CAMERA_TILT");
-        const char* pszCameraRoll = CSLFetchNameValue(papszOptions, "CAMERA_ROLL");
-        const char* pszCameraAltitudeMode = CSLFetchNameValue(papszOptions, "CAMERA_ALTITUDEMODE");
-        if( poOgrLayer != NULL && pszCameraLongitude != NULL && pszCameraLatitude != NULL &&
-            pszCameraAltitude != NULL && pszCameraAltitudeMode != NULL )
+        const char* pszCameraLongitude =
+            CSLFetchNameValue(papszOptions, "CAMERA_LONGITUDE");
+        const char* pszCameraLatitude =
+            CSLFetchNameValue(papszOptions, "CAMERA_LATITUDE");
+        const char* pszCameraAltitude =
+            CSLFetchNameValue(papszOptions, "CAMERA_ALTITUDE");
+        const char* pszCameraHeading =
+            CSLFetchNameValue(papszOptions, "CAMERA_HEADING");
+        const char* pszCameraTilt =
+            CSLFetchNameValue(papszOptions, "CAMERA_TILT");
+        const char* pszCameraRoll =
+            CSLFetchNameValue(papszOptions, "CAMERA_ROLL");
+        const char* pszCameraAltitudeMode =
+            CSLFetchNameValue(papszOptions, "CAMERA_ALTITUDEMODE");
+        if( poOgrLayer != NULL &&
+            pszCameraLongitude != NULL &&
+            pszCameraLatitude != NULL &&
+            pszCameraAltitude != NULL &&
+            pszCameraAltitudeMode != NULL )
         {
             poOgrLayer->SetCamera(pszCameraLongitude,
                                 pszCameraLatitude,
@@ -2287,7 +2262,8 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
         }
     }
 
-    const char* pszRegionAdd = CSLFetchNameValueDef(papszOptions, "ADD_REGION", "FALSE");
+    const char* pszRegionAdd =
+        CSLFetchNameValueDef(papszOptions, "ADD_REGION", "FALSE");
     const char* pszRegionXMin = CSLFetchNameValue(papszOptions, "REGION_XMIN");
     const char* pszRegionYMin = CSLFetchNameValue(papszOptions, "REGION_YMIN");
     const char* pszRegionXMax = CSLFetchNameValue(papszOptions, "REGION_XMAX");
@@ -2309,10 +2285,10 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
         if( pszRegionXMin != NULL && pszRegionYMin != NULL &&
             pszRegionXMax != NULL && pszRegionYMax != NULL )
         {
-            double xmin = CPLAtof(pszRegionXMin);
-            double ymin = CPLAtof(pszRegionYMin);
-            double xmax = CPLAtof(pszRegionXMax);
-            double ymax = CPLAtof(pszRegionYMax);
+            const double xmin = CPLAtof(pszRegionXMin);
+            const double ymin = CPLAtof(pszRegionYMin);
+            const double xmax = CPLAtof(pszRegionXMax);
+            const double ymax = CPLAtof(pszRegionYMax);
             if( xmin < xmax && ymin < ymax )
                 poOgrLayer->SetRegionBounds(xmin, ymin, xmax, ymax);
         }
@@ -2365,15 +2341,14 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
     }
 
     /***** mark the dataset as updated *****/
-
-    if ( poOgrLayer )
-        bUpdated = TRUE;
+    if( poOgrLayer )
+        bUpdated = true;
 
     return poOgrLayer;
 }
 
 /******************************************************************************
- method to get a datasources style table
+ Method to get a datasources style table.
 
  Args:          none
 
@@ -2382,15 +2357,13 @@ OGRLayer *OGRLIBKMLDataSource::ICreateLayer(
 
 ******************************************************************************/
 
-OGRStyleTable *OGRLIBKMLDataSource::GetStyleTable (
-     )
+OGRStyleTable *OGRLIBKMLDataSource::GetStyleTable()
 {
-
     return m_poStyleTable;
 }
 
 /******************************************************************************
-  method to write a style table to a single file .kml ds
+  Method to write a style table to a single file .kml ds.
 
  Args:          poStyleTable    pointer to the style table to add
 
@@ -2398,32 +2371,29 @@ OGRStyleTable *OGRLIBKMLDataSource::GetStyleTable (
 
 ******************************************************************************/
 
-void OGRLIBKMLDataSource::SetStyleTable2Kml (
-    OGRStyleTable * poStyleTable )
+void OGRLIBKMLDataSource::SetStyleTable2Kml( OGRStyleTable * poStyleTable )
 {
     if( m_poKmlDSContainer == NULL )
         return;
 
     /***** delete all the styles *****/
 
-    DocumentPtr poKmlDocument = AsDocument ( m_poKmlDSContainer );
-    int nKmlStyles = static_cast<int>(poKmlDocument->get_styleselector_array_size (  ));
-    int iKmlStyle;
+    DocumentPtr poKmlDocument = AsDocument( m_poKmlDSContainer );
+    int nKmlStyles = static_cast<int>(poKmlDocument->get_styleselector_array_size());
 
-    for ( iKmlStyle = nKmlStyles - 1; iKmlStyle >= 0; iKmlStyle-- ) {
-        poKmlDocument->DeleteStyleSelectorAt ( iKmlStyle );
+    for( int iKmlStyle = nKmlStyles - 1; iKmlStyle >= 0; iKmlStyle-- )
+    {
+        poKmlDocument->DeleteStyleSelectorAt( iKmlStyle );
     }
 
     /***** add the new style table to the document *****/
 
-    styletable2kml ( poStyleTable, m_poKmlFactory,
-                     AsContainer ( poKmlDocument ), m_papszOptions );
-
-    return;
+    styletable2kml( poStyleTable, m_poKmlFactory,
+                     AsContainer( poKmlDocument ), m_papszOptions );
 }
 
 /******************************************************************************
- method to write a style table to a kmz ds
+ Method to write a style table to a kmz ds.
 
  Args:          poStyleTable    pointer to the style table to add
 
@@ -2431,105 +2401,93 @@ void OGRLIBKMLDataSource::SetStyleTable2Kml (
 
 ******************************************************************************/
 
-void OGRLIBKMLDataSource::SetStyleTable2Kmz (
-    OGRStyleTable * poStyleTable )
+void OGRLIBKMLDataSource::SetStyleTable2Kmz( OGRStyleTable * poStyleTable )
 {
     if( m_poKmlStyleKml != NULL || poStyleTable != NULL )
     {
         /***** replace the style document with a new one *****/
 
-        m_poKmlStyleKml = m_poKmlFactory->CreateDocument (  );
-        m_poKmlStyleKml->set_id ( "styleId" );
+        m_poKmlStyleKml = m_poKmlFactory->CreateDocument();
+        m_poKmlStyleKml->set_id( "styleId" );
 
-        styletable2kml ( poStyleTable, m_poKmlFactory, m_poKmlStyleKml );
+        styletable2kml( poStyleTable, m_poKmlFactory, m_poKmlStyleKml );
     }
-
-    return;
 }
 
 /******************************************************************************
- method to write a style table to a datasource
+ Method to write a style table to a datasource.
 
  Args:          poStyleTable    pointer to the style table to add
 
  Returns:       nothing
 
- note: this method assumes ownership of the style table
+ Note: This method assumes ownership of the style table.
 
 ******************************************************************************/
 
-void OGRLIBKMLDataSource::SetStyleTableDirectly (
-    OGRStyleTable * poStyleTable )
+void OGRLIBKMLDataSource::SetStyleTableDirectly( OGRStyleTable * poStyleTable )
 {
-
-    if ( !bUpdate )
+    if( !bUpdate )
         return;
 
-    if ( m_poStyleTable )
+    if( m_poStyleTable )
         delete m_poStyleTable;
 
     m_poStyleTable = poStyleTable;
 
     /***** a kml datasource? *****/
+    if( IsKml() )
+        SetStyleTable2Kml( m_poStyleTable );
 
-    if ( IsKml (  ) )
-        SetStyleTable2Kml ( m_poStyleTable );
-
-    else if ( IsKmz (  ) || IsDir (  ) )
-        SetStyleTable2Kmz ( m_poStyleTable );
-
-    bUpdated = TRUE;
+    else if( IsKmz() || IsDir() )
+        SetStyleTable2Kmz( m_poStyleTable );
 
-    return;
+    bUpdated = true;
 }
 
 /******************************************************************************
- method to write a style table to a datasource
+ Method to write a style table to a datasource.
 
  Args:          poStyleTable    pointer to the style table to add
 
  Returns:       nothing
 
- note:  This method copies the style table, and the user will still be
+ Note:  This method copies the style table, and the user will still be
         responsible for its destruction.
 
 ******************************************************************************/
 
-void OGRLIBKMLDataSource::SetStyleTable (
-    OGRStyleTable * poStyleTable )
+void OGRLIBKMLDataSource::SetStyleTable( OGRStyleTable * poStyleTable )
 {
-    if ( !bUpdate )
+    if( !bUpdate )
         return;
 
-    if ( poStyleTable )
-        SetStyleTableDirectly ( poStyleTable->Clone (  ) );
+    if( poStyleTable )
+        SetStyleTableDirectly( poStyleTable->Clone() );
     else
-        SetStyleTableDirectly ( NULL );
-    return;
+        SetStyleTableDirectly( NULL );
 }
 
-
 /******************************************************************************
  Test if capability is available.
 
  Args:          pszCap  datasource capability name to test
 
- Returns:       nothing
+ Returns:       TRUE or FALSE
 
  ODsCCreateLayer: True if this datasource can create new layers.
  ODsCDeleteLayer: True if this datasource can delete existing layers.
 
 ******************************************************************************/
 
-int OGRLIBKMLDataSource::TestCapability (
-    const char *pszCap )
+int OGRLIBKMLDataSource::TestCapability( const char *pszCap )
 {
-
-    if ( EQUAL ( pszCap, ODsCCreateLayer ) )
+    if( EQUAL( pszCap, ODsCCreateLayer ) )
         return bUpdate;
-    else if ( EQUAL ( pszCap, ODsCDeleteLayer ) )
+    if( EQUAL( pszCap, ODsCDeleteLayer ) )
+        return bUpdate;
+    if( EQUAL(pszCap,ODsCRandomLayerWrite) )
         return bUpdate;
-    else
-        return FALSE;
 
+    return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp
index 9d8713c..a12ddc8 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmldriver.cpp
@@ -33,6 +33,8 @@
 #include "cpl_error.h"
 #include "cpl_multiproc.h"
 
+CPL_CVSID("$Id: ogrlibkmldriver.cpp 37108 2017-01-12 10:16:27Z rouault $");
+
 using kmldom::KmlFactory;
 
 static CPLMutex *hMutex = NULL;
@@ -42,7 +44,7 @@ static KmlFactory* m_poKmlFactory = NULL;
  OGRLIBKMLDriverUnload()
 ******************************************************************************/
 
-static void OGRLIBKMLDriverUnload ( CPL_UNUSED GDALDriver* poDriver )
+static void OGRLIBKMLDriverUnload( GDALDriver * /* poDriver */ )
 {
     if( hMutex != NULL )
         CPLDestroyMutex(hMutex);
@@ -62,15 +64,16 @@ static int OGRLIBKMLDriverIdentify( GDALOpenInfo* poOpenInfo )
     if( poOpenInfo->bIsDirectory )
         return -1;
 
-    return( EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "kml") ||
-            EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "kmz") );
+    return
+        EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "kml") ||
+        EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "kmz");
 }
 
 /******************************************************************************
  Open()
 ******************************************************************************/
 
-static GDALDataset *OGRLIBKMLDriverOpen ( GDALOpenInfo* poOpenInfo )
+static GDALDataset *OGRLIBKMLDriverOpen( GDALOpenInfo* poOpenInfo )
 {
     if( OGRLIBKMLDriverIdentify(poOpenInfo) == FALSE )
         return NULL;
@@ -78,12 +81,14 @@ static GDALDataset *OGRLIBKMLDriverOpen ( GDALOpenInfo* poOpenInfo )
     {
         CPLMutexHolderD(&hMutex);
         if( m_poKmlFactory == NULL )
-            m_poKmlFactory = KmlFactory::GetFactory (  );
+            m_poKmlFactory = KmlFactory::GetFactory();
     }
 
-    OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource ( m_poKmlFactory );
+    OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource( m_poKmlFactory );
 
-    if ( !poDS->Open ( poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update ) ) {
+    if( !poDS->Open( poOpenInfo->pszFilename,
+                     poOpenInfo->eAccess == GA_Update ) )
+    {
         delete poDS;
 
         poDS = NULL;
@@ -92,30 +97,29 @@ static GDALDataset *OGRLIBKMLDriverOpen ( GDALOpenInfo* poOpenInfo )
     return poDS;
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
 
 static GDALDataset *OGRLIBKMLDriverCreate( const char * pszName,
-                                           CPL_UNUSED int nBands,
-                                           CPL_UNUSED int nXSize,
-                                           CPL_UNUSED int nYSize,
-                                           CPL_UNUSED GDALDataType eDT,
+                                           int /* nBands */,
+                                           int /* nXSize */,
+                                           int /* nYSize */,
+                                           GDALDataType /* eDT */,
                                            char **papszOptions )
 {
-    CPLAssert ( NULL != pszName );
-    CPLDebug ( "LIBKML", "Attempt to create: %s", pszName );
+    CPLAssert( NULL != pszName );
+    CPLDebug( "LIBKML", "Attempt to create: %s", pszName );
 
     {
         CPLMutexHolderD(&hMutex);
         if( m_poKmlFactory == NULL )
-            m_poKmlFactory = KmlFactory::GetFactory (  );
+            m_poKmlFactory = KmlFactory::GetFactory();
     }
 
-    OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource ( m_poKmlFactory );
+    OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource( m_poKmlFactory );
 
-    if ( !poDS->Create ( pszName, papszOptions ) ) {
+    if( !poDS->Create( pszName, papszOptions ) ) {
         delete poDS;
 
         poDS = NULL;
@@ -127,54 +131,57 @@ static GDALDataset *OGRLIBKMLDriverCreate( const char * pszName,
 /******************************************************************************
  DeleteDataSource()
 
- Note: this method recursively deletes an entire dir if the datasource is a dir
+ Note: This method recursively deletes an entire dir if the datasource is a dir
        and all the files are kml or kmz.
 
 ******************************************************************************/
 
 static CPLErr OGRLIBKMLDriverDelete( const char *pszName )
 {
-
     /***** dir *****/
-
     VSIStatBufL sStatBuf;
-    if ( !VSIStatL ( pszName, &sStatBuf ) && VSI_ISDIR ( sStatBuf.st_mode ) ) {
-
-        char **papszDirList = VSIReadDir ( pszName );
-        for ( int iFile = 0; papszDirList != NULL &&
-                             papszDirList[iFile] != NULL; iFile++ ) {
-            if ( CE_Failure ==
-                 OGRLIBKMLDriverDelete ( papszDirList[iFile] ) ) {
-                CSLDestroy ( papszDirList );
+    if( !VSIStatL( pszName, &sStatBuf ) && VSI_ISDIR( sStatBuf.st_mode ) )
+    {
+        char **papszDirList = VSIReadDir( pszName );
+        for( int iFile = 0;
+             papszDirList != NULL && papszDirList[iFile] != NULL;
+             iFile++ )
+        {
+            if( CE_Failure == OGRLIBKMLDriverDelete( papszDirList[iFile] ) )
+            {
+                CSLDestroy( papszDirList );
                 return CE_Failure;
             }
         }
-        CSLDestroy ( papszDirList );
+        CSLDestroy( papszDirList );
 
-        if ( VSIRmdir ( pszName ) < 0 ) {
+        if( VSIRmdir( pszName ) < 0 )
+        {
             return CE_Failure;
         }
     }
 
-   /***** kml *****/
-
-    else if ( EQUAL ( CPLGetExtension ( pszName ), "kml" ) ) {
-        if ( VSIUnlink ( pszName ) < 0 )
+    /***** kml *****/
+    else if( EQUAL( CPLGetExtension( pszName ), "kml" ) )
+    {
+        if( VSIUnlink( pszName ) < 0 )
             return CE_Failure;
     }
 
     /***** kmz *****/
-
-    else if ( EQUAL ( CPLGetExtension ( pszName ), "kmz" ) ) {
-        if ( VSIUnlink ( pszName ) < 0 )
+    else if( EQUAL( CPLGetExtension( pszName ), "kmz" ) )
+    {
+        if( VSIUnlink( pszName ) < 0 )
             return CE_Failure;
     }
 
     /***** do not delete other types of files *****/
-
     else
+    {
         return CE_Failure;
+    }
 
+    // TODO(schwehr): Isn't this redundant to the else case?
     return CE_None;
 }
 
@@ -182,7 +189,7 @@ static CPLErr OGRLIBKMLDriverDelete( const char *pszName )
  RegisterOGRLIBKML()
 ******************************************************************************/
 
-void RegisterOGRLIBKML ()
+void RegisterOGRLIBKML()
 {
     if( GDALGetDriverByName( "LIBKML" ) != NULL )
         return;
@@ -198,6 +205,7 @@ void RegisterOGRLIBKML ()
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
+"  <Option name='DOCUMENT_ID' type='string' description='Id of the root <Document> node' default='root_doc'/>'"
 "  <Option name='AUTHOR_NAME' type='string' description='Name in <atom:Author> element'/>"
 "  <Option name='AUTHOR_URI' type='string' description='URI in <atom:Author> element'/>"
 "  <Option name='AUTHOR_EMAIL' type='string' description='Email in <atom:Author> element'/>"
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp
index 360b74a..58c4ffc 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.cpp
@@ -28,37 +28,37 @@
  *****************************************************************************/
 
 #include "libkml_headers.h"
+#include "ogrlibkmlfeature.h"
 
-#include <ogrsf_frmts.h>
-#include <ogr_geometry.h>
 #include "gdal.h"
+#include "ogr_geometry.h"
+#include "ogr_libkml.h"
+#include "ogrlibkmlfield.h"
+#include "ogrlibkmlfeaturestyle.h"
+#include "ogrlibkmlgeometry.h"
+#include "ogrsf_frmts.h"
 
-using kmldom::KmlFactory;
-using kmldom::PlacemarkPtr;
+CPL_CVSID("$Id: ogrlibkmlfeature.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
+using kmldom::AliasPtr;
+using kmldom::CameraPtr;
 using kmldom::ElementPtr;
+using kmldom::FeaturePtr;
 using kmldom::GeometryPtr;
-using kmldom::Geometry;
 using kmldom::GroundOverlayPtr;
-using kmldom::CameraPtr;
-using kmldom::ModelPtr;
+using kmldom::IconPtr;
+using kmldom::ImagePyramidPtr;
+using kmldom::KmlFactory;
 using kmldom::LinkPtr;
 using kmldom::LocationPtr;
-using kmldom::OrientationPtr;
-using kmldom::ScalePtr;
-using kmldom::ResourceMapPtr;
-using kmldom::AliasPtr;
+using kmldom::ModelPtr;
 using kmldom::NetworkLinkPtr;
+using kmldom::OrientationPtr;
 using kmldom::PhotoOverlayPtr;
-using kmldom::IconPtr;
+using kmldom::PlacemarkPtr;
+using kmldom::ResourceMapPtr;
+using kmldom::ScalePtr;
 using kmldom::ViewVolumePtr;
-using kmldom::ImagePyramidPtr;
-
-#include "ogr_libkml.h"
-
-#include "ogrlibkmlgeometry.h"
-#include "ogrlibkmlfield.h"
-#include "ogrlibkmlfeaturestyle.h"
-#include "ogrlibkmlfeature.h"
 
 static CameraPtr feat2kmlcamera( const struct fieldconfig& oFC,
                                  int iHeading,
@@ -67,89 +67,117 @@ static CameraPtr feat2kmlcamera( const struct fieldconfig& oFC,
                                  OGRFeature * poOgrFeat,
                                  KmlFactory * poKmlFactory )
 {
-    int iCameraLongitudeField = poOgrFeat->GetFieldIndex(oFC.camera_longitude_field);
-    int iCameraLatitudeField = poOgrFeat->GetFieldIndex(oFC.camera_latitude_field);
-    int iCameraAltitudeField = poOgrFeat->GetFieldIndex(oFC.camera_altitude_field);
-    int iCameraAltitudeModeField = poOgrFeat->GetFieldIndex(oFC.camera_altitudemode_field);
-    if( iCameraLongitudeField >= 0 && poOgrFeat->IsFieldSet(iCameraLongitudeField) &&
-        iCameraLatitudeField >= 0  && poOgrFeat->IsFieldSet(iCameraLatitudeField) &&
-        ((iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading)) ||
-        (iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt)) ||
-        (iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll))) )
+    const int iCameraLongitudeField =
+        poOgrFeat->GetFieldIndex(oFC.camera_longitude_field);
+    const int iCameraLatitudeField =
+        poOgrFeat->GetFieldIndex(oFC.camera_latitude_field);
+    const int iCameraAltitudeField =
+        poOgrFeat->GetFieldIndex(oFC.camera_altitude_field);
+    const int iCameraAltitudeModeField =
+        poOgrFeat->GetFieldIndex(oFC.camera_altitudemode_field);
+
+    const bool bNeedCamera =
+        iCameraLongitudeField >= 0 &&
+        poOgrFeat->IsFieldSetAndNotNull(iCameraLongitudeField) &&
+        iCameraLatitudeField >= 0 &&
+        poOgrFeat->IsFieldSetAndNotNull(iCameraLatitudeField) &&
+        ((iHeading >= 0 && poOgrFeat->IsFieldSetAndNotNull(iHeading)) ||
+        (iTilt >= 0 && poOgrFeat->IsFieldSetAndNotNull(iTilt)) ||
+        (iRoll >= 0 && poOgrFeat->IsFieldSetAndNotNull(iRoll)));
+
+    if( !bNeedCamera )
+        return NULL;
+
+    CameraPtr const camera = poKmlFactory->CreateCamera();
+    camera->set_latitude(poOgrFeat->GetFieldAsDouble(iCameraLatitudeField));
+    camera->set_longitude(poOgrFeat->GetFieldAsDouble(iCameraLongitudeField));
+    int isGX = FALSE;
+    int nAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
+
+    if( iCameraAltitudeModeField >= 0 &&
+        poOgrFeat->IsFieldSetAndNotNull(iCameraAltitudeModeField) )
     {
-        CameraPtr camera = poKmlFactory->CreateCamera();
-        camera->set_latitude(poOgrFeat->GetFieldAsDouble(iCameraLatitudeField));
-        camera->set_longitude(poOgrFeat->GetFieldAsDouble(iCameraLongitudeField));
-        int isGX = FALSE;
-        int nAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
-        if( iCameraAltitudeModeField >= 0 && poOgrFeat->IsFieldSet(iCameraAltitudeModeField) )
-        {
-            nAltitudeMode = kmlAltitudeModeFromString(
-                poOgrFeat->GetFieldAsString(iCameraAltitudeModeField), isGX);
-            camera->set_altitudemode(nAltitudeMode);
-        }
-        else if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
-            CPLError(CE_Warning, CPLE_AppDefined, "Camera should define altitudeMode != 'clampToGround'");
-        if( iCameraAltitudeField >= 0 && poOgrFeat->IsFieldSet(iCameraAltitudeField))
-            camera->set_altitude(poOgrFeat->GetFieldAsDouble(iCameraAltitudeField));
-        else if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
-        {
-            CPLError(CE_Warning, CPLE_AppDefined, "Camera should have an altitude/Z");
-            camera->set_altitude(0.0);
-        }
-        if( iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading) )
-            camera->set_heading(poOgrFeat->GetFieldAsDouble(iHeading));
-        if( iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt) )
-            camera->set_tilt(poOgrFeat->GetFieldAsDouble(iTilt));
-        if( iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll) )
-            camera->set_roll(poOgrFeat->GetFieldAsDouble(iRoll));
-        return camera;
+        nAltitudeMode = kmlAltitudeModeFromString(
+            poOgrFeat->GetFieldAsString(iCameraAltitudeModeField), isGX);
+        camera->set_altitudemode(nAltitudeMode);
+    }
+    else if( CPLTestBool(
+                 CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+    {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Camera should define altitudeMode != 'clampToGround'");
     }
-    else
-        return NULL;
-}
 
+    if( iCameraAltitudeField >= 0 &&
+        poOgrFeat->IsFieldSetAndNotNull(iCameraAltitudeField))
+    {
+        camera->set_altitude(poOgrFeat->GetFieldAsDouble(iCameraAltitudeField));
+    }
+    else if( CPLTestBool(
+                 CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Camera should have an altitude/Z");
+        camera->set_altitude(0.0);
+    }
+
+    if( iHeading >= 0 && poOgrFeat->IsFieldSetAndNotNull(iHeading) )
+        camera->set_heading(poOgrFeat->GetFieldAsDouble(iHeading));
+    if( iTilt >= 0 && poOgrFeat->IsFieldSetAndNotNull(iTilt) )
+        camera->set_tilt(poOgrFeat->GetFieldAsDouble(iTilt));
+    if( iRoll >= 0 && poOgrFeat->IsFieldSetAndNotNull(iRoll) )
+        camera->set_roll(poOgrFeat->GetFieldAsDouble(iRoll));
+
+    return camera;
+}
 
 /************************************************************************/
 /*                 OGRLIBKMLReplaceXYLevelInURL()                       */
 /************************************************************************/
 
-static CPLString OGRLIBKMLReplaceLevelXYInURL(const char* pszURL,
-                                              int level, int x, int y)
+static CPLString OGRLIBKMLReplaceLevelXYInURL( const char* pszURL,
+                                               int level, int x, int y )
 {
     CPLString osRet(pszURL);
     size_t nPos = osRet.find("$[level]");
-    osRet = osRet.substr(0, nPos) + CPLSPrintf("%d", level) + osRet.substr(nPos + strlen("$[level]"));
+    osRet =
+        osRet.substr(0, nPos) + CPLSPrintf("%d", level) +
+        osRet.substr(nPos + strlen("$[level]"));
+
     nPos = osRet.find("$[x]");
-    osRet = osRet.substr(0, nPos) + CPLSPrintf("%d", x) + osRet.substr(nPos + strlen("$[x]"));
+    osRet =
+        osRet.substr(0, nPos) + CPLSPrintf("%d", x) +
+        osRet.substr(nPos + strlen("$[x]"));
+
     nPos = osRet.find("$[y]");
-    osRet = osRet.substr(0, nPos) + CPLSPrintf("%d", y) + osRet.substr(nPos + strlen("$[y]"));
+    osRet =
+        osRet.substr(0, nPos) + CPLSPrintf("%d", y) +
+        osRet.substr(nPos + strlen("$[y]"));
+
     return osRet;
 }
 
-
 /************************************************************************/
 /*                        IsPowerOf2                                    */
 /************************************************************************/
 
-static int IsPowerOf2(int nVal)
+static bool IsPowerOf2( int nVal )
 {
-    unsigned int nTmp = (unsigned int) nVal;
-    while( (nTmp & 1) == 0 )
-    {
-        nTmp >>= 1;
-    }
-    return( nTmp == 1 );
+    if( nVal < 1 ) return false;
+
+    const unsigned int nTmp = static_cast<unsigned int>(nVal);
+
+    return (nTmp & (nTmp - 1)) == 0;
 }
 
 /************************************************************************/
 /*                    OGRLIBKMLGetMaxDimensions()                       */
 /************************************************************************/
 
-static void OGRLIBKMLGetMaxDimensions(const char* pszURL,
-                                      int nTileSize,
-                                      int* panMaxWidth,
-                                      int* panMaxHeight)
+static void OGRLIBKMLGetMaxDimensions( const char* pszURL,
+                                       int nTileSize,
+                                       int* panMaxWidth,
+                                       int* panMaxHeight )
 {
     VSIStatBufL sStat;
     int nMaxLevel = 0;
@@ -161,7 +189,7 @@ static void OGRLIBKMLGetMaxDimensions(const char* pszURL,
         if( strstr(osURL, ".kmz/") )
             osURL = "/vsizip/" + osURL;
         if( VSIStatL(osURL, &sStat) == 0 )
-            nMaxLevel ++;
+            nMaxLevel++;
         else
         {
             if( nMaxLevel == 0 )
@@ -169,21 +197,27 @@ static void OGRLIBKMLGetMaxDimensions(const char* pszURL,
             break;
         }
     }
-    nMaxLevel --;
+    nMaxLevel--;
 
-    int i;
-    for(i = 0; ; i++ )
     {
-        CPLString osURL = OGRLIBKMLReplaceLevelXYInURL(pszURL, nMaxLevel, i + 1, 0);
-        if( strstr(osURL, ".kmz/") )
-            osURL = "/vsizip/" + osURL;
-        if( VSIStatL(osURL, &sStat) != 0 )
-            break;
+        int i = 0;  // Used after for.
+        for( ; ; i++ )
+        {
+            CPLString osURL =
+                OGRLIBKMLReplaceLevelXYInURL(pszURL, nMaxLevel, i + 1, 0);
+            if( strstr(osURL, ".kmz/") )
+                osURL = "/vsizip/" + osURL;
+            if( VSIStatL(osURL, &sStat) != 0 )
+                break;
+        }
+        *panMaxWidth = (i + 1) * nTileSize;
     }
-    *panMaxWidth = (i + 1) * nTileSize;
-    for(i = 0; ; i++ )
+
+    int i = 0;  // Used after for.
+    for( ; ; i++ )
     {
-        CPLString osURL = OGRLIBKMLReplaceLevelXYInURL(pszURL, nMaxLevel, 0, i + 1);
+        CPLString osURL =
+            OGRLIBKMLReplaceLevelXYInURL(pszURL, nMaxLevel, 0, i + 1);
         if( strstr(osURL, ".kmz/") )
             osURL = "/vsizip/" + osURL;
         if( VSIStatL(osURL, &sStat) != 0 )
@@ -196,7 +230,7 @@ static void OGRLIBKMLGetMaxDimensions(const char* pszURL,
 /*                           feat2kml()                                 */
 /************************************************************************/
 
-FeaturePtr feat2kml (
+FeaturePtr feat2kml(
     OGRLIBKMLDataSource * poOgrDS,
     OGRLayer * poOgrLayer,
     OGRFeature * poOgrFeat,
@@ -209,45 +243,56 @@ FeaturePtr feat2kml (
     get_fieldconfig( &oFC );
 
     /***** geometry *****/
-
-    OGRGeometry *poOgrGeom = poOgrFeat->GetGeometryRef (  );
-    int iHeading = poOgrFeat->GetFieldIndex(oFC.headingfield),
-        iTilt = poOgrFeat->GetFieldIndex(oFC.tiltfield),
-        iRoll = poOgrFeat->GetFieldIndex(oFC.rollfield),
-        iModel = poOgrFeat->GetFieldIndex(oFC.modelfield);
-    int iNetworkLink = poOgrFeat->GetFieldIndex(oFC.networklinkfield);
-    int iPhotoOverlay = poOgrFeat->GetFieldIndex(oFC.photooverlayfield);
+    OGRGeometry *poOgrGeom = poOgrFeat->GetGeometryRef();
+    const int iHeading = poOgrFeat->GetFieldIndex(oFC.headingfield);
+    const int iTilt = poOgrFeat->GetFieldIndex(oFC.tiltfield);
+    const int iRoll = poOgrFeat->GetFieldIndex(oFC.rollfield);
+    const int iModel = poOgrFeat->GetFieldIndex(oFC.modelfield);
+    const int iNetworkLink = poOgrFeat->GetFieldIndex(oFC.networklinkfield);
+    const int iPhotoOverlay = poOgrFeat->GetFieldIndex(oFC.photooverlayfield);
     CameraPtr camera = NULL;
 
-    /* PhotoOverlay */
-    if( iPhotoOverlay >= 0 && poOgrFeat->IsFieldSet(iPhotoOverlay) &&
+    // PhotoOverlay.
+    if( iPhotoOverlay >= 0 && poOgrFeat->IsFieldSetAndNotNull(iPhotoOverlay) &&
         poOgrGeom != NULL && !poOgrGeom->IsEmpty() &&
         wkbFlatten(poOgrGeom->getGeometryType()) == wkbPoint &&
-        (camera = feat2kmlcamera(oFC, iHeading, iTilt, iRoll, poOgrFeat, poKmlFactory)) != NULL)
+        (camera = feat2kmlcamera(oFC, iHeading, iTilt, iRoll,
+                                 poOgrFeat, poKmlFactory)) != NULL)
     {
-        int iLeftFovField = poOgrFeat->GetFieldIndex(oFC.leftfovfield);
-        int iRightFovField = poOgrFeat->GetFieldIndex(oFC.rightfovfield);
-        int iBottomFovField = poOgrFeat->GetFieldIndex(oFC.bottomfovfield);
-        int iTopFovField = poOgrFeat->GetFieldIndex(oFC.topfovfield);
-        int iNearField = poOgrFeat->GetFieldIndex(oFC.nearfield);
-        double dfNear;
+        const int iLeftFovField = poOgrFeat->GetFieldIndex(oFC.leftfovfield);
+        const int iRightFovField = poOgrFeat->GetFieldIndex(oFC.rightfovfield);
+        const int iBottomFovField =
+            poOgrFeat->GetFieldIndex(oFC.bottomfovfield);
+        const int iTopFovField = poOgrFeat->GetFieldIndex(oFC.topfovfield);
+        const int iNearField = poOgrFeat->GetFieldIndex(oFC.nearfield);
 
         const char* pszURL = poOgrFeat->GetFieldAsString(iPhotoOverlay);
-        int iImagePyramidTileSize = poOgrFeat->GetFieldIndex(oFC.imagepyramid_tilesize_field);
-        int iImagePyramidMaxWidth = poOgrFeat->GetFieldIndex(oFC.imagepyramid_maxwidth_field);
-        int iImagePyramidMaxHeight = poOgrFeat->GetFieldIndex(oFC.imagepyramid_maxheight_field);
-        int iImagePyramidGridOrigin = poOgrFeat->GetFieldIndex(oFC.imagepyramid_gridorigin_field);
-        int nTileSize = 0, nMaxWidth = 0, nMaxHeight = 0;
-        int bIsTiledPhotoOverlay = FALSE;
-        int bGridOriginIsUpperLeft = TRUE;
-        /* ATC 52 and 62 */
-        if( strstr(pszURL, "$[x]") && strstr(pszURL, "$[y]") && strstr(pszURL, "$[level]") )
+        const int iImagePyramidTileSize =
+            poOgrFeat->GetFieldIndex(oFC.imagepyramid_tilesize_field);
+        const int iImagePyramidMaxWidth =
+            poOgrFeat->GetFieldIndex(oFC.imagepyramid_maxwidth_field);
+        const int iImagePyramidMaxHeight =
+            poOgrFeat->GetFieldIndex(oFC.imagepyramid_maxheight_field);
+        const int iImagePyramidGridOrigin =
+            poOgrFeat->GetFieldIndex(oFC.imagepyramid_gridorigin_field);
+
+        int nTileSize = 0;
+        int nMaxWidth = 0;
+        int nMaxHeight = 0;
+        bool bIsTiledPhotoOverlay = false;
+        bool bGridOriginIsUpperLeft = true;
+        // OGC KML Abstract Test Case (ATC) 52 and 62
+        if( strstr(pszURL, "$[x]") &&
+            strstr(pszURL, "$[y]") &&
+            strstr(pszURL, "$[level]") )
         {
-            bIsTiledPhotoOverlay = TRUE;
-            int bErrorEmitted = FALSE;
-            if( iImagePyramidTileSize < 0 || !poOgrFeat->IsFieldSet(iImagePyramidTileSize) )
+            bIsTiledPhotoOverlay = true;
+            bool bErrorEmitted = false;
+            if( iImagePyramidTileSize < 0 ||
+                !poOgrFeat->IsFieldSetAndNotNull(iImagePyramidTileSize) )
             {
-                CPLDebug("LIBKML", "Missing ImagePyramid tileSize. Computing it");
+                CPLDebug("LIBKML",
+                         "Missing ImagePyramid tileSize. Computing it");
                 CPLString osURL = OGRLIBKMLReplaceLevelXYInURL(pszURL, 0, 0, 0);
                 if( strstr(osURL, ".kmz/") )
                     osURL = "/vsizip/" + osURL;
@@ -257,17 +302,21 @@ FeaturePtr feat2kml (
                     nTileSize = GDALGetRasterXSize(hDS);
                     if( nTileSize != GDALGetRasterYSize(hDS) )
                     {
-                        CPLError(CE_Failure, CPLE_AppDefined, "Non square tile : %dx%d",
-                                 GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));
+                        CPLError(
+                            CE_Failure, CPLE_AppDefined,
+                            "Non square tile : %dx%d",
+                            GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));
                         nTileSize = 0;
-                        bErrorEmitted = TRUE;
+                        bErrorEmitted = true;
                     }
                     GDALClose(hDS);
                 }
                 else
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s", osURL.c_str());
-                    bErrorEmitted = TRUE;
+                    CPLError(
+                        CE_Failure, CPLE_AppDefined,
+                        "Cannot open %s", osURL.c_str());
+                    bErrorEmitted = true;
                 }
             }
             else
@@ -276,82 +325,114 @@ FeaturePtr feat2kml (
             }
             if( !bErrorEmitted && (nTileSize <= 1 || !IsPowerOf2(nTileSize)) )
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "Tile size is not a power of two: %d", nTileSize);
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Tile size is not a power of two: %d", nTileSize);
                 nTileSize = 0;
             }
 
             if( nTileSize > 0 )
             {
-                if( iImagePyramidMaxWidth < 0 || !poOgrFeat->IsFieldSet(iImagePyramidMaxWidth) ||
-                    iImagePyramidMaxHeight < 0 || !poOgrFeat->IsFieldSet(iImagePyramidMaxHeight) )
+                if( iImagePyramidMaxWidth < 0 ||
+                    !poOgrFeat->IsFieldSetAndNotNull(iImagePyramidMaxWidth) ||
+                    iImagePyramidMaxHeight < 0 ||
+                    !poOgrFeat->IsFieldSetAndNotNull(iImagePyramidMaxHeight) )
                 {
-                    CPLDebug("LIBKML", "Missing ImagePyramid maxWidth and/or maxHeight. Computing it");
-                    OGRLIBKMLGetMaxDimensions(pszURL, nTileSize, &nMaxWidth, &nMaxHeight);
+                    CPLDebug(
+                        "LIBKML",
+                        "Missing ImagePyramid maxWidth and/or maxHeight. "
+                        "Computing it");
+                    OGRLIBKMLGetMaxDimensions(pszURL, nTileSize,
+                                              &nMaxWidth, &nMaxHeight);
                 }
                 else
                 {
-                    nMaxWidth = poOgrFeat->GetFieldAsInteger(iImagePyramidMaxWidth);
-                    nMaxHeight = poOgrFeat->GetFieldAsInteger(iImagePyramidMaxHeight);
+                    nMaxWidth =
+                        poOgrFeat->GetFieldAsInteger(iImagePyramidMaxWidth);
+                    nMaxHeight =
+                        poOgrFeat->GetFieldAsInteger(iImagePyramidMaxHeight);
                 }
 
                 if( nTileSize <= 0 || nMaxWidth <= 0 || nMaxHeight <= 0)
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                            "Cannot generate PhotoOverlay object since there are "
-                            "missing information to generate ImagePyramid element");
+                    CPLError(
+                        CE_Failure, CPLE_AppDefined,
+                        "Cannot generate PhotoOverlay object since there are "
+                        "missing information to generate ImagePyramid element");
                 }
             }
 
-            if( iImagePyramidGridOrigin >= 0 && poOgrFeat->IsFieldSet(iImagePyramidGridOrigin) )
+            if( iImagePyramidGridOrigin >= 0 &&
+                poOgrFeat->IsFieldSetAndNotNull(iImagePyramidGridOrigin) )
             {
-                const char* pszGridOrigin = poOgrFeat->GetFieldAsString(iImagePyramidGridOrigin);
+                const char* pszGridOrigin =
+                    poOgrFeat->GetFieldAsString(iImagePyramidGridOrigin);
                 if( EQUAL(pszGridOrigin, "UpperLeft") )
-                    bGridOriginIsUpperLeft = TRUE;
+                {
+                    bGridOriginIsUpperLeft = true;
+                }
                 else if( EQUAL(pszGridOrigin, "BottomLeft") )
-                    bGridOriginIsUpperLeft = FALSE;
+                {
+                    bGridOriginIsUpperLeft = false;
+                }
                 else
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined,
-                             "Unhandled value for imagepyramid_gridorigin : %s. Assuming UpperLeft",
-                             pszGridOrigin);
+                    CPLError(
+                        CE_Failure, CPLE_AppDefined,
+                        "Unhandled value for imagepyramid_gridorigin : %s. "
+                        "Assuming UpperLeft",
+                        pszGridOrigin);
                 }
             }
         }
         else
         {
-            if( (iImagePyramidTileSize >= 0 && poOgrFeat->IsFieldSet(iImagePyramidTileSize)) ||
-                (iImagePyramidMaxWidth >= 0 && poOgrFeat->IsFieldSet(iImagePyramidMaxWidth)) ||
-                (iImagePyramidMaxHeight >= 0 && poOgrFeat->IsFieldSet(iImagePyramidMaxHeight)) ||
-                (iImagePyramidGridOrigin >= 0 && poOgrFeat->IsFieldSet(iImagePyramidGridOrigin)) )
+            if( (iImagePyramidTileSize >= 0 &&
+                 poOgrFeat->IsFieldSetAndNotNull(iImagePyramidTileSize)) ||
+                (iImagePyramidMaxWidth >= 0 &&
+                 poOgrFeat->IsFieldSetAndNotNull(iImagePyramidMaxWidth)) ||
+                (iImagePyramidMaxHeight >= 0 &&
+                 poOgrFeat->IsFieldSetAndNotNull(iImagePyramidMaxHeight)) ||
+                (iImagePyramidGridOrigin >= 0 &&
+                 poOgrFeat->IsFieldSetAndNotNull(iImagePyramidGridOrigin)) )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "Ignoring any ImagePyramid information since the URL does "
-                         "not include $[x] and/or $[y] and/or $[level]");
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Ignoring any ImagePyramid information since the URL does "
+                    "not include $[x] and/or $[y] and/or $[level]");
             }
         }
 
-        /* ATC 19 & 35 */
-        if( (!bIsTiledPhotoOverlay || (nTileSize > 0 && nMaxWidth > 0 && nMaxHeight > 0)) &&
-            iLeftFovField >= 0 && poOgrFeat->IsFieldSet(iLeftFovField) &&
-            iRightFovField >= 0 && poOgrFeat->IsFieldSet(iRightFovField) &&
-            iBottomFovField >= 0 && poOgrFeat->IsFieldSet(iBottomFovField) &&
-            iTopFovField >= 0 && poOgrFeat->IsFieldSet(iTopFovField) &&
-            iNearField >= 0 && (dfNear = poOgrFeat->GetFieldAsDouble(iNearField)) > 0 )
+        // OGC KML Abstract Test Case (ATC) 19 & 35.
+        double dfNear = 0.0;
+
+        if( (!bIsTiledPhotoOverlay ||
+             (nTileSize > 0 && nMaxWidth > 0 && nMaxHeight > 0)) &&
+            iLeftFovField >= 0 && poOgrFeat->IsFieldSetAndNotNull(iLeftFovField) &&
+            iRightFovField >= 0 && poOgrFeat->IsFieldSetAndNotNull(iRightFovField) &&
+            iBottomFovField >= 0 && poOgrFeat->IsFieldSetAndNotNull(iBottomFovField) &&
+            iTopFovField >= 0 && poOgrFeat->IsFieldSetAndNotNull(iTopFovField) &&
+            iNearField >= 0 &&
+            (dfNear = poOgrFeat->GetFieldAsDouble(iNearField)) > 0 )
         {
-            PhotoOverlayPtr poKmlPhotoOverlay = poKmlFactory->CreatePhotoOverlay (  );
+            const PhotoOverlayPtr poKmlPhotoOverlay =
+                poKmlFactory->CreatePhotoOverlay();
             poKmlFeature = poKmlPhotoOverlay;
 
-            IconPtr poKmlIcon = poKmlFactory->CreateIcon (  );
+            const IconPtr poKmlIcon = poKmlFactory->CreateIcon();
             poKmlPhotoOverlay->set_icon(poKmlIcon);
             poKmlIcon->set_href( pszURL );
 
-            ViewVolumePtr poKmlViewVolume = poKmlFactory->CreateViewVolume( );
+            const ViewVolumePtr poKmlViewVolume =
+                poKmlFactory->CreateViewVolume();
             poKmlPhotoOverlay->set_viewvolume(poKmlViewVolume);
 
-            double dfLeftFov = poOgrFeat->GetFieldAsDouble(iLeftFovField);
-            double dfRightFov = poOgrFeat->GetFieldAsDouble(iRightFovField);
-            double dfBottomFov = poOgrFeat->GetFieldAsDouble(iBottomFovField);
-            double dfTopFov = poOgrFeat->GetFieldAsDouble(iTopFovField);
+            const double dfLeftFov = poOgrFeat->GetFieldAsDouble(iLeftFovField);
+            const double dfRightFov =
+                poOgrFeat->GetFieldAsDouble(iRightFovField);
+            const double dfBottomFov =
+                poOgrFeat->GetFieldAsDouble(iBottomFovField);
+            const double dfTopFov = poOgrFeat->GetFieldAsDouble(iTopFovField);
 
             poKmlViewVolume->set_leftfov(dfLeftFov);
             poKmlViewVolume->set_rightfov(dfRightFov);
@@ -361,20 +442,26 @@ FeaturePtr feat2kml (
 
             if( bIsTiledPhotoOverlay )
             {
-                ImagePyramidPtr poKmlImagePyramid = poKmlFactory->CreateImagePyramid( );
+                const ImagePyramidPtr poKmlImagePyramid =
+                    poKmlFactory->CreateImagePyramid();
                 poKmlPhotoOverlay->set_imagepyramid(poKmlImagePyramid);
 
                 poKmlImagePyramid->set_tilesize(nTileSize);
                 poKmlImagePyramid->set_maxwidth(nMaxWidth);
                 poKmlImagePyramid->set_maxheight(nMaxHeight);
-                poKmlImagePyramid->set_gridorigin( (bGridOriginIsUpperLeft) ?
-                    kmldom::GRIDORIGIN_UPPERLEFT : kmldom::GRIDORIGIN_LOWERLEFT );
+                poKmlImagePyramid->set_gridorigin(
+                    bGridOriginIsUpperLeft ?
+                    kmldom::GRIDORIGIN_UPPERLEFT :
+                    kmldom::GRIDORIGIN_LOWERLEFT );
             }
 
-            int iPhotoOverlayShapeField = poOgrFeat->GetFieldIndex(oFC.photooverlay_shape_field);
-            if( iPhotoOverlayShapeField >= 0 && poOgrFeat->IsFieldSet(iPhotoOverlayShapeField) )
+            const int iPhotoOverlayShapeField =
+                poOgrFeat->GetFieldIndex(oFC.photooverlay_shape_field);
+            if( iPhotoOverlayShapeField >= 0 &&
+                poOgrFeat->IsFieldSetAndNotNull(iPhotoOverlayShapeField) )
             {
-                const char* pszShape = poOgrFeat->GetFieldAsString(iPhotoOverlayShapeField);
+                const char* pszShape =
+                    poOgrFeat->GetFieldAsString(iPhotoOverlayShapeField);
                 if( EQUAL(pszShape, "rectangle") )
                     poKmlPhotoOverlay->set_shape(kmldom::SHAPE_RECTANGLE);
                 else if( EQUAL(pszShape, "cylinder") )
@@ -383,41 +470,58 @@ FeaturePtr feat2kml (
                     poKmlPhotoOverlay->set_shape(kmldom::SHAPE_SPHERE);
             }
 
-            ElementPtr poKmlElement = geom2kml ( poOgrGeom, -1, poKmlFactory );
+            ElementPtr poKmlElement = geom2kml( poOgrGeom, -1, poKmlFactory );
 
-            poKmlPhotoOverlay->set_point ( AsPoint ( poKmlElement ) );
+            poKmlPhotoOverlay->set_point( AsPoint( poKmlElement ) );
         }
     }
 
-    /* NetworkLink */
-    if( poKmlFeature == NULL && iNetworkLink >= 0 && poOgrFeat->IsFieldSet(iNetworkLink) )
+    // NetworkLink.
+    if( poKmlFeature == NULL && iNetworkLink >= 0 &&
+        poOgrFeat->IsFieldSetAndNotNull(iNetworkLink) )
     {
-        NetworkLinkPtr poKmlNetworkLink = poKmlFactory->CreateNetworkLink (  );
+        const NetworkLinkPtr poKmlNetworkLink =
+            poKmlFactory->CreateNetworkLink();
         poKmlFeature = poKmlNetworkLink;
 
-        int iRefreshVisibility = poOgrFeat->GetFieldIndex(oFC.networklink_refreshvisibility_field);
-        int iFlyToView = poOgrFeat->GetFieldIndex(oFC.networklink_flytoview_field);
+        const int iRefreshVisibility =
+            poOgrFeat->GetFieldIndex(oFC.networklink_refreshvisibility_field);
 
-        if( iRefreshVisibility >= 0 && poOgrFeat->IsFieldSet(iRefreshVisibility) )
-            poKmlNetworkLink->set_refreshvisibility(CPL_TO_BOOL(poOgrFeat->GetFieldAsInteger(iRefreshVisibility)));
+        if( iRefreshVisibility >= 0 &&
+            poOgrFeat->IsFieldSetAndNotNull(iRefreshVisibility) )
+        {
+            poKmlNetworkLink->set_refreshvisibility(CPL_TO_BOOL(
+                poOgrFeat->GetFieldAsInteger(iRefreshVisibility)));
+        }
 
-        if( iFlyToView >= 0 && poOgrFeat->IsFieldSet(iFlyToView) )
-            poKmlNetworkLink->set_flytoview(CPL_TO_BOOL(poOgrFeat->GetFieldAsInteger(iFlyToView)));
+        const int iFlyToView =
+            poOgrFeat->GetFieldIndex(oFC.networklink_flytoview_field);
 
-        LinkPtr poKmlLink = poKmlFactory->CreateLink (  );
+        if( iFlyToView >= 0 && poOgrFeat->IsFieldSetAndNotNull(iFlyToView) )
+            poKmlNetworkLink->set_flytoview(CPL_TO_BOOL(
+                poOgrFeat->GetFieldAsInteger(iFlyToView)));
+
+        const LinkPtr poKmlLink = poKmlFactory->CreateLink();
         poKmlLink->set_href( poOgrFeat->GetFieldAsString( iNetworkLink ) );
         poKmlNetworkLink->set_link(poKmlLink);
 
-        int iRefreshMode = poOgrFeat->GetFieldIndex(oFC.networklink_refreshMode_field);
-        int iRefreshInterval = poOgrFeat->GetFieldIndex(oFC.networklink_refreshInterval_field);
-        int iViewRefreshMode = poOgrFeat->GetFieldIndex(oFC.networklink_viewRefreshMode_field);
-        int iViewRefreshTime = poOgrFeat->GetFieldIndex(oFC.networklink_viewRefreshTime_field);
-        int iViewBoundScale = poOgrFeat->GetFieldIndex(oFC.networklink_viewBoundScale_field);
-        int iViewFormat = poOgrFeat->GetFieldIndex(oFC.networklink_viewFormat_field);
-        int iHttpQuery = poOgrFeat->GetFieldIndex(oFC.networklink_httpQuery_field);
+        const int iRefreshMode =
+            poOgrFeat->GetFieldIndex(oFC.networklink_refreshMode_field);
+        const int iRefreshInterval =
+            poOgrFeat->GetFieldIndex(oFC.networklink_refreshInterval_field);
+        const int iViewRefreshMode =
+            poOgrFeat->GetFieldIndex(oFC.networklink_viewRefreshMode_field);
+        const int iViewRefreshTime =
+            poOgrFeat->GetFieldIndex(oFC.networklink_viewRefreshTime_field);
+        const int iViewBoundScale =
+            poOgrFeat->GetFieldIndex(oFC.networklink_viewBoundScale_field);
+        const int iViewFormat =
+            poOgrFeat->GetFieldIndex(oFC.networklink_viewFormat_field);
+        const int iHttpQuery =
+            poOgrFeat->GetFieldIndex(oFC.networklink_httpQuery_field);
 
         double dfRefreshInterval = 0.0;
-        if( iRefreshInterval >= 0 && poOgrFeat->IsFieldSet(iRefreshInterval) )
+        if( iRefreshInterval >= 0 && poOgrFeat->IsFieldSetAndNotNull(iRefreshInterval) )
         {
             dfRefreshInterval = poOgrFeat->GetFieldAsDouble(iRefreshInterval);
             if( dfRefreshInterval < 0 )
@@ -425,18 +529,19 @@ FeaturePtr feat2kml (
         }
 
         double dfViewRefreshTime = 0.0;
-        if( iViewRefreshTime >= 0 && poOgrFeat->IsFieldSet(iViewRefreshTime) )
+        if( iViewRefreshTime >= 0 && poOgrFeat->IsFieldSetAndNotNull(iViewRefreshTime) )
         {
             dfViewRefreshTime = poOgrFeat->GetFieldAsDouble(iViewRefreshTime);
             if( dfViewRefreshTime < 0 )
                 dfViewRefreshTime = 0.0;
         }
 
-        if( dfRefreshInterval > 0 ) /* ATC 51 */
+        if( dfRefreshInterval > 0 )  // ATC 51
             poKmlLink->set_refreshmode(kmldom::REFRESHMODE_ONINTERVAL);
-        else if( iRefreshMode >= 0 && poOgrFeat->IsFieldSet(iRefreshMode) )
+        else if( iRefreshMode >= 0 && poOgrFeat->IsFieldSetAndNotNull(iRefreshMode) )
         {
-            const char* pszRefreshMode = poOgrFeat->GetFieldAsString(iRefreshMode);
+            const char * const pszRefreshMode =
+                poOgrFeat->GetFieldAsString(iRefreshMode);
             if( EQUAL(pszRefreshMode, "onChange") )
                 poKmlLink->set_refreshmode(kmldom::REFRESHMODE_ONCHANGE);
             else if( EQUAL(pszRefreshMode, "onInterval") )
@@ -445,63 +550,77 @@ FeaturePtr feat2kml (
                 poKmlLink->set_refreshmode(kmldom::REFRESHMODE_ONEXPIRE);
         }
 
-        if( dfRefreshInterval > 0 ) /* ATC 9 */
+        if( dfRefreshInterval > 0 )  // ATC 9
             poKmlLink->set_refreshinterval(dfRefreshInterval);
 
-        if( dfViewRefreshTime > 0 ) /* ATC  51 */
+        if( dfViewRefreshTime > 0 )  // ATC 51
             poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_ONSTOP);
-        else if( iViewRefreshMode >= 0 && poOgrFeat->IsFieldSet(iViewRefreshMode) )
+        else if( iViewRefreshMode >= 0 &&
+                 poOgrFeat->IsFieldSetAndNotNull(iViewRefreshMode) )
         {
-            const char* pszViewRefreshMode = poOgrFeat->GetFieldAsString(iViewRefreshMode);
+            const char * const pszViewRefreshMode =
+                poOgrFeat->GetFieldAsString(iViewRefreshMode);
             if( EQUAL(pszViewRefreshMode, "never") )
                 poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_NEVER);
             else if( EQUAL(pszViewRefreshMode, "onRequest") )
-                poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_ONREQUEST);
+                poKmlLink->set_viewrefreshmode(
+                    kmldom::VIEWREFRESHMODE_ONREQUEST);
             else if( EQUAL(pszViewRefreshMode, "onStop") )
                 poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_ONSTOP);
             else if( EQUAL(pszViewRefreshMode, "onRegion") )
-                poKmlLink->set_viewrefreshmode(kmldom::VIEWREFRESHMODE_ONREGION);
+                poKmlLink->set_viewrefreshmode(
+                    kmldom::VIEWREFRESHMODE_ONREGION);
         }
 
-        if( dfViewRefreshTime > 0 ) /* ATC 9 */
+        if( dfViewRefreshTime > 0 ) // ATC 9
             poKmlLink->set_viewrefreshtime(dfViewRefreshTime);
 
-        if( iViewBoundScale >= 0 && poOgrFeat->IsFieldSet(iViewBoundScale) )
+        if( iViewBoundScale >= 0 && poOgrFeat->IsFieldSetAndNotNull(iViewBoundScale) )
         {
-            double dfViewBoundScale = poOgrFeat->GetFieldAsDouble(iViewBoundScale);
-            if( dfViewBoundScale > 0 ) /* ATC 9 */
+            const double dfViewBoundScale =
+                poOgrFeat->GetFieldAsDouble(iViewBoundScale);
+            if( dfViewBoundScale > 0 ) // ATC 9
                 poKmlLink->set_viewboundscale(dfViewBoundScale);
         }
 
-        if( iViewFormat >= 0 && poOgrFeat->IsFieldSet(iViewFormat) )
+        if( iViewFormat >= 0 && poOgrFeat->IsFieldSetAndNotNull(iViewFormat) )
         {
-            const char* pszViewFormat = poOgrFeat->GetFieldAsString(iViewFormat);
-            if( pszViewFormat[0] != '\0' ) /* ATC 46 */
+            const char * const pszViewFormat =
+                poOgrFeat->GetFieldAsString(iViewFormat);
+            if( pszViewFormat[0] != '\0' ) // ATC 46
                 poKmlLink->set_viewformat(pszViewFormat);
         }
 
-        if( iHttpQuery >= 0 && poOgrFeat->IsFieldSet(iHttpQuery) )
+        if( iHttpQuery >= 0 && poOgrFeat->IsFieldSetAndNotNull(iHttpQuery) )
         {
-            const char* pszHttpQuery = poOgrFeat->GetFieldAsString(iHttpQuery);
+            const char* const pszHttpQuery =
+                poOgrFeat->GetFieldAsString(iHttpQuery);
             if( strstr(pszHttpQuery, "[clientVersion]") != NULL ||
                 strstr(pszHttpQuery, "[kmlVersion]") != NULL ||
                 strstr(pszHttpQuery, "[clientName]") != NULL ||
-                strstr(pszHttpQuery, "[language]") != NULL ) /* ATC 47 */
+                strstr(pszHttpQuery, "[language]") != NULL )  // ATC 47
             {
                 poKmlLink->set_httpquery(pszHttpQuery);
             }
         }
     }
 
-    /* Model */
-    else if( poKmlFeature == NULL && iModel>= 0 && poOgrFeat->IsFieldSet(iModel) &&
-        poOgrGeom != NULL && !poOgrGeom->IsEmpty() &&
-        wkbFlatten(poOgrGeom->getGeometryType()) == wkbPoint )
+    // Model.
+    else if( poKmlFeature == NULL &&
+             iModel >= 0 &&
+             poOgrFeat->IsFieldSetAndNotNull(iModel) &&
+             poOgrGeom != NULL && !poOgrGeom->IsEmpty() &&
+             wkbFlatten(poOgrGeom->getGeometryType()) == wkbPoint )
     {
-        PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark (  );
+        const PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark();
         poKmlFeature = poKmlPlacemark;
 
-        OGRPoint* poOgrPoint = (OGRPoint*) poOgrGeom;
+        const OGRPoint* const poOgrPoint = dynamic_cast<OGRPoint *>(poOgrGeom);
+        if( poOgrPoint == NULL )
+        {
+          CPLError(CE_Failure, CPLE_AppDefined, "dynamic_cast failed.");
+          return NULL;
+        }
         ModelPtr model = poKmlFactory->CreateModel();
 
         LocationPtr location = poKmlFactory->CreateLocation();
@@ -512,76 +631,80 @@ FeaturePtr feat2kml (
             location->set_altitude(poOgrPoint->getZ());
 
         int isGX = FALSE;
-        int iAltitudeMode = poOgrFeat->GetFieldIndex(oFC.altitudeModefield);
+        const int iAltitudeMode =
+            poOgrFeat->GetFieldIndex(oFC.altitudeModefield);
         int nAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
-        if( iAltitudeMode >= 0 && poOgrFeat->IsFieldSet(iAltitudeMode) )
+        if( iAltitudeMode >= 0 && poOgrFeat->IsFieldSetAndNotNull(iAltitudeMode) )
         {
             nAltitudeMode = kmlAltitudeModeFromString(
                 poOgrFeat->GetFieldAsString(iAltitudeMode), isGX);
             model->set_altitudemode(nAltitudeMode);
 
-            /* ATC 55 */
+            // ATC 55
             if( nAltitudeMode != kmldom::ALTITUDEMODE_CLAMPTOGROUND &&
                 poOgrPoint->getCoordinateDimension() != 3 )
             {
-                if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
-                    CPLError(CE_Warning, CPLE_AppDefined, "Altitude should be defined");
+                if( CPLTestBool(
+                    CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Altitude should be defined");
             }
         }
 
-        if( (iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading)) ||
-            (iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt)) ||
-            (iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll)) )
+        if( (iHeading >= 0 && poOgrFeat->IsFieldSetAndNotNull(iHeading)) ||
+            (iTilt >= 0 && poOgrFeat->IsFieldSetAndNotNull(iTilt)) ||
+            (iRoll >= 0 && poOgrFeat->IsFieldSetAndNotNull(iRoll)) )
         {
-            OrientationPtr orientation = poKmlFactory->CreateOrientation();
+            OrientationPtr const orientation =
+                poKmlFactory->CreateOrientation();
             model->set_orientation(orientation);
-            if( iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading) )
+            if( iHeading >= 0 && poOgrFeat->IsFieldSetAndNotNull(iHeading) )
                 orientation->set_heading(poOgrFeat->GetFieldAsDouble(iHeading));
             else
                 orientation->set_heading(0);
-            if( iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt) )
+            if( iTilt >= 0 && poOgrFeat->IsFieldSetAndNotNull(iTilt) )
                 orientation->set_tilt(poOgrFeat->GetFieldAsDouble(iTilt));
             else
                 orientation->set_tilt(0);
-            if( iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll) )
+            if( iRoll >= 0 && poOgrFeat->IsFieldSetAndNotNull(iRoll) )
                 orientation->set_roll(poOgrFeat->GetFieldAsDouble(iRoll));
             else
                 orientation->set_roll(0);
         }
-        int iScaleX = poOgrFeat->GetFieldIndex(oFC.scalexfield);
-        int iScaleY = poOgrFeat->GetFieldIndex(oFC.scaleyfield);
-        int iScaleZ = poOgrFeat->GetFieldIndex(oFC.scalezfield);
+        const int iScaleX = poOgrFeat->GetFieldIndex(oFC.scalexfield);
+        const int iScaleY = poOgrFeat->GetFieldIndex(oFC.scaleyfield);
+        const int iScaleZ = poOgrFeat->GetFieldIndex(oFC.scalezfield);
 
-        ScalePtr scale = poKmlFactory->CreateScale();
+        const ScalePtr scale = poKmlFactory->CreateScale();
         model->set_scale(scale);
-        if( iScaleX >= 0 && poOgrFeat->IsFieldSet(iScaleX) )
+        if( iScaleX >= 0 && poOgrFeat->IsFieldSetAndNotNull(iScaleX) )
             scale->set_x(poOgrFeat->GetFieldAsDouble(iScaleX));
         else
             scale->set_x(1.0);
-        if( iScaleY >= 0 && poOgrFeat->IsFieldSet(iScaleY) )
+        if( iScaleY >= 0 && poOgrFeat->IsFieldSetAndNotNull(iScaleY) )
             scale->set_y(poOgrFeat->GetFieldAsDouble(iScaleY));
         else
             scale->set_y(1.0);
-        if( iScaleZ >= 0 && poOgrFeat->IsFieldSet(iScaleZ) )
+        if( iScaleZ >= 0 && poOgrFeat->IsFieldSetAndNotNull(iScaleZ) )
             scale->set_z(poOgrFeat->GetFieldAsDouble(iScaleZ));
         else
             scale->set_z(1.0);
 
-        LinkPtr link = poKmlFactory->CreateLink();
+        const LinkPtr link = poKmlFactory->CreateLink();
         model->set_link(link);
-        const char* pszURL = poOgrFeat->GetFieldAsString(oFC.modelfield);
+        const char* const pszURL = poOgrFeat->GetFieldAsString(oFC.modelfield);
         link->set_href( pszURL );
 
-        /* Collada 3D file ? */
+        // Collada 3D file?
         if( EQUAL(CPLGetExtension(pszURL), "dae") &&
             CPLTestBool(CPLGetConfigOption("LIBKML_ADD_RESOURCE_MAP", "TRUE")) )
         {
-            VSILFILE* fp;
-            int bIsURL = FALSE;
+            VSILFILE* fp = NULL;
+            bool bIsURL = false;
             if( STARTS_WITH_CI(pszURL, "http://") ||
                 STARTS_WITH_CI(pszURL, "https://") )
             {
-                bIsURL = TRUE;
+                bIsURL = true;
                 fp = VSIFOpenL(CPLSPrintf("/vsicurl/%s", pszURL), "rb");
             }
             else if( strstr(pszURL, ".kmz/") != NULL )
@@ -595,33 +718,41 @@ FeaturePtr feat2kml (
             if( fp != NULL )
             {
                 ResourceMapPtr resourceMap = NULL;
-                const char* pszLine;
+                const char* pszLine = NULL;
                 while( (pszLine = CPLReadLineL(fp)) != NULL )
                 {
                     const char* pszInitFrom = strstr(pszLine, "<init_from>");
                     if( pszInitFrom )
                     {
                         pszInitFrom += strlen("<init_from>");
-                        const char* pszInitFromEnd = strstr(pszInitFrom, "</init_from>");
+                        const char* const pszInitFromEnd =
+                            strstr(pszInitFrom, "</init_from>");
                         if( pszInitFromEnd )
                         {
                             CPLString osImage(pszInitFrom);
                             osImage.resize(pszInitFromEnd - pszInitFrom);
-                            const char* pszExtension = CPLGetExtension(osImage);
+                            const char* const pszExtension =
+                                CPLGetExtension(osImage);
                             if( EQUAL(pszExtension, "jpg") ||
                                 EQUAL(pszExtension, "jpeg") ||
                                 EQUAL(pszExtension, "png") ||
                                 EQUAL(pszExtension, "gif") )
                             {
                                 if( resourceMap == NULL )
-                                    resourceMap = poKmlFactory->CreateResourceMap();
-                                AliasPtr alias = poKmlFactory->CreateAlias();
+                                    resourceMap =
+                                        poKmlFactory->CreateResourceMap();
+                                const AliasPtr alias =
+                                    poKmlFactory->CreateAlias();
                                 if( bIsURL && CPLIsFilenameRelative(osImage) )
                                 {
                                     if( STARTS_WITH(pszURL, "http") )
-                                        alias->set_targethref(CPLSPrintf("%s/%s", CPLGetPath(pszURL), osImage.c_str()));
+                                        alias->set_targethref(
+                                            CPLSPrintf(
+                                                "%s/%s", CPLGetPath(pszURL),
+                                                osImage.c_str()));
                                     else
-                                        alias->set_targethref(CPLFormFilename(CPLGetPath(pszURL), osImage, NULL));
+                                        alias->set_targethref(CPLFormFilename(
+                                            CPLGetPath(pszURL), osImage, NULL));
                                 }
                                 else
                                     alias->set_targethref(osImage);
@@ -637,153 +768,171 @@ FeaturePtr feat2kml (
             }
         }
 
-        poKmlPlacemark->set_geometry ( AsGeometry ( model ) );
+        poKmlPlacemark->set_geometry( AsGeometry( model ) );
     }
 
-    /* Camera */
-    else if( poKmlFeature == NULL && poOgrGeom != NULL && !poOgrGeom->IsEmpty() &&
-        wkbFlatten(poOgrGeom->getGeometryType()) == wkbPoint &&
-        poOgrFeat->GetFieldIndex(oFC.camera_longitude_field) < 0 &&
-        ((iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading)) ||
-         (iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt)) ||
-         (iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll))) )
+    // Camera.
+    else if( poKmlFeature == NULL && poOgrGeom != NULL &&
+             !poOgrGeom->IsEmpty() &&
+             wkbFlatten(poOgrGeom->getGeometryType()) == wkbPoint &&
+             poOgrFeat->GetFieldIndex(oFC.camera_longitude_field) < 0 &&
+             ((iHeading >= 0 && poOgrFeat->IsFieldSetAndNotNull(iHeading)) ||
+              (iTilt >= 0 && poOgrFeat->IsFieldSetAndNotNull(iTilt)) ||
+              (iRoll >= 0 && poOgrFeat->IsFieldSetAndNotNull(iRoll))) )
     {
-        PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark (  );
+        const PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark();
         poKmlFeature = poKmlPlacemark;
 
-        OGRPoint* poOgrPoint = (OGRPoint*) poOgrGeom;
+        const OGRPoint* const poOgrPoint = dynamic_cast<OGRPoint *>(poOgrGeom);
+              if( poOgrPoint == NULL )
+        {
+          CPLError(CE_Failure, CPLE_AppDefined, "dynamic_cast failed.");
+          return NULL;
+        }
+
         camera = poKmlFactory->CreateCamera();
         camera->set_latitude(poOgrPoint->getY());
         camera->set_longitude(poOgrPoint->getX());
         int isGX = FALSE;
-        int iAltitudeMode = poOgrFeat->GetFieldIndex(oFC.altitudeModefield);
+        const int iAltitudeMode =
+            poOgrFeat->GetFieldIndex(oFC.altitudeModefield);
         int nAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
-        if( iAltitudeMode >= 0 && poOgrFeat->IsFieldSet(iAltitudeMode) )
+        if( iAltitudeMode >= 0 && poOgrFeat->IsFieldSetAndNotNull(iAltitudeMode) )
         {
             nAltitudeMode = kmlAltitudeModeFromString(
                 poOgrFeat->GetFieldAsString(iAltitudeMode), isGX);
             camera->set_altitudemode(nAltitudeMode);
         }
-        else if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
-            CPLError(CE_Warning, CPLE_AppDefined, "Camera should define altitudeMode != 'clampToGround'");
+        else if( CPLTestBool(
+                     CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Camera should define altitudeMode != 'clampToGround'");
+        }
+
         if( poOgrPoint->getCoordinateDimension() == 3 )
+        {
             camera->set_altitude(poOgrPoint->getZ());
-        else if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+        }
+        else if( CPLTestBool(
+                     CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
         {
-            CPLError(CE_Warning, CPLE_AppDefined, "Camera should have an altitude/Z");
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Camera should have an altitude/Z");
             camera->set_altitude(0.0);
         }
-        if( iHeading >= 0 && poOgrFeat->IsFieldSet(iHeading) )
+
+        if( iHeading >= 0 && poOgrFeat->IsFieldSetAndNotNull(iHeading) )
             camera->set_heading(poOgrFeat->GetFieldAsDouble(iHeading));
-        if( iTilt >= 0 && poOgrFeat->IsFieldSet(iTilt) )
+        if( iTilt >= 0 && poOgrFeat->IsFieldSetAndNotNull(iTilt) )
             camera->set_tilt(poOgrFeat->GetFieldAsDouble(iTilt));
-        if( iRoll >= 0 && poOgrFeat->IsFieldSet(iRoll) )
+        if( iRoll >= 0 && poOgrFeat->IsFieldSetAndNotNull(iRoll) )
             camera->set_roll(poOgrFeat->GetFieldAsDouble(iRoll));
         poKmlPlacemark->set_abstractview(camera);
     }
-
     else if( poKmlFeature == NULL )
     {
-        PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark (  );
+        const PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark();
         poKmlFeature = poKmlPlacemark;
 
-        ElementPtr poKmlElement = geom2kml ( poOgrGeom, -1, poKmlFactory );
+        ElementPtr poKmlElement = geom2kml( poOgrGeom, -1, poKmlFactory );
 
-        poKmlPlacemark->set_geometry ( AsGeometry ( poKmlElement ) );
+        poKmlPlacemark->set_geometry( AsGeometry( poKmlElement ) );
     }
 
     if( camera == NULL )
-        camera = feat2kmlcamera(oFC, iHeading, iTilt, iRoll, poOgrFeat, poKmlFactory);
+        camera = feat2kmlcamera(oFC, iHeading, iTilt, iRoll,
+                                poOgrFeat, poKmlFactory);
     if( camera != NULL )
         poKmlFeature->set_abstractview(camera);
 
     /***** style *****/
-
-    featurestyle2kml ( poOgrDS, poOgrLayer, poOgrFeat, poKmlFactory,
-                       poKmlFeature );
+    featurestyle2kml( poOgrDS, poOgrLayer, poOgrFeat, poKmlFactory,
+                      poKmlFeature );
 
     /***** fields *****/
-
-    field2kml ( poOgrFeat, ( OGRLIBKMLLayer * ) poOgrLayer, poKmlFactory,
-                poKmlFeature, bUseSimpleField );
+    OGRLIBKMLLayer * const poKmlLayer =
+        dynamic_cast<OGRLIBKMLLayer *>(poOgrLayer);
+    if( poKmlLayer == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "dynamic_cast failed.");
+        return NULL;
+    }
+    field2kml( poOgrFeat, poKmlLayer, poKmlFactory,
+               poKmlFeature, bUseSimpleField );
 
     return poKmlFeature;
 }
 
-OGRFeature *kml2feat (
+OGRFeature *kml2feat(
     PlacemarkPtr poKmlPlacemark,
     OGRLIBKMLDataSource * poOgrDS,
     OGRLayer * poOgrLayer,
     OGRFeatureDefn * poOgrFeatDefn,
-    OGRSpatialReference *poOgrSRS)
+    OGRSpatialReference *poOgrSRS )
 {
-
-    OGRFeature *poOgrFeat = new OGRFeature ( poOgrFeatDefn );
+    OGRFeature *poOgrFeat = new OGRFeature( poOgrFeatDefn );
 
     /***** style *****/
-
-    kml2featurestyle ( poKmlPlacemark, poOgrDS, poOgrLayer, poOgrFeat );
+    kml2featurestyle( poKmlPlacemark, poOgrDS, poOgrLayer, poOgrFeat );
 
     /***** geometry *****/
-
-    if ( poKmlPlacemark->has_geometry (  ) ) {
-        OGRGeometry *poOgrGeom =
-            kml2geom ( poKmlPlacemark->get_geometry (  ), poOgrSRS );
-        poOgrFeat->SetGeometryDirectly ( poOgrGeom );
-
+    if( poKmlPlacemark->has_geometry() )
+    {
+        OGRGeometry * const poOgrGeom =
+            kml2geom( poKmlPlacemark->get_geometry(), poOgrSRS );
+        poOgrFeat->SetGeometryDirectly( poOgrGeom );
     }
-    else if ( poKmlPlacemark->has_abstractview (  ) &&
-              poKmlPlacemark->get_abstractview()->IsA( kmldom::Type_Camera) ) {
+    else if( poKmlPlacemark->has_abstractview() &&
+             poKmlPlacemark->get_abstractview()->IsA( kmldom::Type_Camera) )
+    {
         const CameraPtr& camera = AsCamera(poKmlPlacemark->get_abstractview());
         if( camera->has_longitude() && camera->has_latitude() )
         {
             if( camera->has_altitude() )
-                poOgrFeat->SetGeometryDirectly( new OGRPoint( camera->get_longitude(), camera->get_latitude(), camera->get_altitude() ) );
+                poOgrFeat->SetGeometryDirectly(
+                    new OGRPoint( camera->get_longitude(),
+                                  camera->get_latitude(),
+                                  camera->get_altitude() ) );
             else
-                poOgrFeat->SetGeometryDirectly( new OGRPoint( camera->get_longitude(), camera->get_latitude() ) );
+                poOgrFeat->SetGeometryDirectly(
+                    new OGRPoint( camera->get_longitude(),
+                                 camera->get_latitude() ) );
             poOgrFeat->GetGeometryRef()->assignSpatialReference( poOgrSRS );
         }
     }
 
     /***** fields *****/
-
-    kml2field ( poOgrFeat, AsFeature ( poKmlPlacemark ) );
+    kml2field( poOgrFeat, AsFeature( poKmlPlacemark ) );
 
     return poOgrFeat;
 }
 
-OGRFeature *kmlgroundoverlay2feat (
+OGRFeature *kmlgroundoverlay2feat(
     GroundOverlayPtr poKmlOverlay,
-    CPL_UNUSED OGRLIBKMLDataSource * poOgrDS,
-    CPL_UNUSED OGRLayer * poOgrLayer,
+    OGRLIBKMLDataSource * /* poOgrDS */,
+    OGRLayer * /* poOgrLayer */,
     OGRFeatureDefn * poOgrFeatDefn,
     OGRSpatialReference *poOgrSRS)
 {
-
-    OGRFeature *poOgrFeat = new OGRFeature ( poOgrFeatDefn );
-
-    /***** style *****/
-
-    //kml2featurestyle ( poKmlPlacemark, poOgrDS, poOgrLayer, poOgrFeat );
+    OGRFeature *poOgrFeat = new OGRFeature( poOgrFeatDefn );
 
     /***** geometry *****/
-
-    if ( poKmlOverlay->has_latlonbox (  ) ) {
-        OGRGeometry *poOgrGeom =
-            kml2geom_latlonbox ( poKmlOverlay->get_latlonbox (  ), poOgrSRS );
-        poOgrFeat->SetGeometryDirectly ( poOgrGeom );
-
+    if( poKmlOverlay->has_latlonbox() )
+    {
+        OGRGeometry * const poOgrGeom =
+            kml2geom_latlonbox( poKmlOverlay->get_latlonbox(), poOgrSRS );
+        poOgrFeat->SetGeometryDirectly( poOgrGeom );
     }
-    else if ( poKmlOverlay->has_gx_latlonquad (  ) ) {
-        OGRGeometry *poOgrGeom =
-            kml2geom_latlonquad ( poKmlOverlay->get_gx_latlonquad (  ), poOgrSRS );
-        poOgrFeat->SetGeometryDirectly ( poOgrGeom );
-
+    else if( poKmlOverlay->has_gx_latlonquad() )
+    {
+        OGRGeometry * const poOgrGeom =
+            kml2geom_latlonquad( poKmlOverlay->get_gx_latlonquad(), poOgrSRS );
+        poOgrFeat->SetGeometryDirectly( poOgrGeom );
     }
 
     /***** fields *****/
-
-    kml2field ( poOgrFeat, AsFeature ( poKmlOverlay ) );
+    kml2field( poOgrFeat, AsFeature( poKmlOverlay ) );
 
     return poOgrFeat;
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h
index f0ccf80..9dc55f0 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeature.h
@@ -31,37 +31,33 @@
 
 #include "ogr_libkml.h"
 
-using kmldom::KmlFactory;
-using kmldom::FeaturePtr;
-using kmldom::PlacemarkPtr;
-
 /******************************************************************************
- function to output a ogr feature to a kml placemark
+ Function to output a ogr feature to a kml placemark.
 ******************************************************************************/
 
-FeaturePtr feat2kml (
+kmldom::FeaturePtr feat2kml(
     OGRLIBKMLDataSource *poOgrDS,
     OGRLayer * poKOgrLayer,
     OGRFeature * poOgrFeat,
-    KmlFactory * poKmlFactory,
+    kmldom::KmlFactory * poKmlFactory,
     int bUseSimpleField );
 
 /******************************************************************************
- function to read a kml placemark into a ogr feature
+ Function to read a kml placemark into a ogr feature.
 ******************************************************************************/
 
-OGRFeature *kml2feat (
-    PlacemarkPtr poKmlPlacemark,
+OGRFeature *kml2feat(
+    kmldom::PlacemarkPtr poKmlPlacemark,
     OGRLIBKMLDataSource * poOgrDS,
     OGRLayer * poOgrLayer,
     OGRFeatureDefn * poOgrFeatDefn,
-    OGRSpatialReference *poOgrSRS);
+    OGRSpatialReference *poOgrSRS );
 
-OGRFeature *kmlgroundoverlay2feat (
-    GroundOverlayPtr poKmlOverlay,
+OGRFeature *kmlgroundoverlay2feat(
+    kmldom::GroundOverlayPtr poKmlOverlay,
     OGRLIBKMLDataSource * poOgrDS,
     OGRLayer * poOgrLayer,
     OGRFeatureDefn * poOgrFeatDefn,
-    OGRSpatialReference *poOgrSRS);
+    OGRSpatialReference *poOgrSRS );
 
 #endif /*  OGR_LIBKML_FEATURE_H */
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
index ed61d50..49989c9 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.cpp
@@ -32,382 +32,318 @@
 #include <ogrsf_frmts.h>
 #include <ogr_featurestyle.h>
 #include <string>
-#include <iostream>
-using namespace std;
+#include "ogrlibkmlfeaturestyle.h"
+#include "ogrlibkmlstyle.h"
 
-using kmldom::KmlFactory;;
+CPL_CVSID("$Id: ogrlibkmlfeaturestyle.cpp 35933 2016-10-25 16:46:26Z goatbar $");
+
+using kmldom::FeaturePtr;
 using kmldom::IconStylePtr;
-using kmldom::PolyStylePtr;
-using kmldom::LineStylePtr;
+using kmldom::KmlFactory;
 using kmldom::LabelStylePtr;
-using kmldom::StylePtr;
-using kmldom::Style;
+using kmldom::LineStylePtr;
+using kmldom::PolyStylePtr;
 using kmldom::StyleMapPtr;
+using kmldom::StylePtr;
 using kmldom::StyleSelectorPtr;
 
-
-#include "ogrlibkmlfeaturestyle.h"
-#include "ogrlibkmlstyle.h"
-
 /******************************************************************************
  function to write out a features style to kml
 
-args:
+Args:
             poOgrLayer      the layer the feature is in
             poOgrFeat       the feature
             poKmlFactory    the kml dom factory
-            poKmlFeature  the placemark to add it to
+            poKmlFeature    the placemark to add it to
 
-returns:
+Returns:
             nothing
 ******************************************************************************/
 
-void featurestyle2kml (
+void featurestyle2kml(
     OGRLIBKMLDataSource * poOgrDS,
     OGRLayer * poOgrLayer,
     OGRFeature * poOgrFeat,
     KmlFactory * poKmlFactory,
     FeaturePtr poKmlFeature )
 {
-
     /***** get the style table *****/
+    OGRStyleTable *poOgrSTBL = NULL;
 
-    OGRStyleTable *poOgrSTBL;
-
-    const char *pszStyleString = poOgrFeat->GetStyleString (  );
+    const char *pszStyleString = poOgrFeat->GetStyleString();
 
     /***** does the feature have style? *****/
-
-    if ( pszStyleString && pszStyleString[0] != '\0' ) {
-
+    if( pszStyleString && pszStyleString[0] != '\0' )
+    {
         /***** does it ref a style table? *****/
-
-        if ( *pszStyleString == '@' ) {
-
+        if( *pszStyleString == '@' )
+        {
             const char* pszStyleName = pszStyleString + 1;
 
-            /***** is the name in the layer style table *****/
+            /***** Is the name in the layer style table *****/
+            OGRStyleTable *hSTBLLayer = poOgrLayer->GetStyleTable();
+            const char *pszTest = (hSTBLLayer != NULL) ?
+                hSTBLLayer->Find( pszStyleName ) : NULL;
 
-            OGRStyleTable *hSTBLLayer = poOgrLayer->GetStyleTable (  );
-            const char *pszTest = NULL;
-
-            if ( hSTBLLayer != NULL )
-                pszTest = hSTBLLayer->Find ( pszStyleName );
-
-            if ( pszTest ) {
+            if( pszTest )
+            {
                 string oTmp = "#";
-
-                oTmp.append ( pszStyleName );
-
-                poKmlFeature->set_styleurl ( oTmp );
+                oTmp.append( pszStyleName );
+                poKmlFeature->set_styleurl( oTmp );
             }
-
-
-            /***** assume its a dataset style, mayby the user will add it later *****/
-
-            else {
+            /***** assume its a dataset style,
+                   maybe the user will add it later *****/
+            else
+            {
                 string oTmp;
 
-                if ( poOgrDS->GetStylePath (  ) )
-                    oTmp.append ( poOgrDS->GetStylePath (  ) );
-                oTmp.append ( "#" );
-                oTmp.append ( pszStyleName );
+                if( poOgrDS->GetStylePath() )
+                    oTmp.append( poOgrDS->GetStylePath() );
+                oTmp.append( "#" );
+                oTmp.append( pszStyleName );
 
-                poKmlFeature->set_styleurl ( oTmp );
+                poKmlFeature->set_styleurl( oTmp );
             }
         }
-
         /***** no style table ref *****/
-
-        else {
+        else
+        {
             /***** parse the style string *****/
-
-            StylePtr poKmlStyle = addstylestring2kml ( pszStyleString, NULL, poKmlFactory,
-                                 poKmlFeature );
+            const StylePtr poKmlStyle =
+                addstylestring2kml( pszStyleString, NULL, poKmlFactory,
+                                    poKmlFeature );
 
             /***** add the style to the placemark *****/
             if( poKmlStyle != NULL )
-                poKmlFeature->set_styleselector ( poKmlStyle );
-
+                poKmlFeature->set_styleselector( poKmlStyle );
         }
     }
-
     /***** get the style table *****/
-
-    else if ( ( poOgrSTBL = poOgrFeat->GetStyleTable (  ) ) != NULL ) {
-
-
-        StylePtr poKmlStyle = NULL;
-
+    else if( ( poOgrSTBL = poOgrFeat->GetStyleTable() ) != NULL )
+    {
         /***** parse the style table *****/
+        poOgrSTBL->ResetStyleStringReading();
 
-        poOgrSTBL->ResetStyleStringReading (  );
-
-        while ( ( pszStyleString = poOgrSTBL->GetNextStyle (  ) ) != NULL ) {
-
-            if ( *pszStyleString == '@' ) {
-
+        while( ( pszStyleString = poOgrSTBL->GetNextStyle() ) != NULL )
+        {
+            if( *pszStyleString == '@' )
+            {
                 const char* pszStyleName = pszStyleString + 1;
 
                 /***** is the name in the layer style table *****/
+                OGRStyleTable *poOgrSTBLLayer = NULL;
 
-                OGRStyleTable *poOgrSTBLLayer;
-                // const char *pszTest = NULL;
-
-                if ( ( poOgrSTBLLayer = poOgrLayer->GetStyleTable (  ) ) != NULL )
-                    poOgrSTBLLayer->Find ( pszStyleName );
-
-                // if ( pszTest ) {
-                //     string oTmp = "#";
-                //     oTmp.append ( pszStyleName );
-                //     poKmlFeature->set_styleurl ( oTmp );
-                // }
-
-                /***** assume its a dataset style,      *****/
-                /***** mayby the user will add it later *****/
-
-                /* else */
+                if( ( poOgrSTBLLayer = poOgrLayer->GetStyleTable() )
+                    != NULL )
                 {
-                    string oTmp;
-
-                    if ( poOgrDS->GetStylePath (  ) )
-                        oTmp.append ( poOgrDS->GetStylePath (  ) );
-                    oTmp.append ( "#" );
-                    oTmp.append ( pszStyleName );
-
-                    poKmlFeature->set_styleurl ( oTmp );
+                    poOgrSTBLLayer->Find( pszStyleName );
                 }
-            }
 
-            else {
+                /***** Assume its a dataset style,       *****/
+                /***** mayby the user will add it later. *****/
 
-                /***** parse the style string *****/
+                string oTmp;
+                if( poOgrDS->GetStylePath() )
+                    oTmp.append( poOgrDS->GetStylePath() );
+                oTmp.append( "#" );
+                oTmp.append( pszStyleName );
 
-                poKmlStyle = addstylestring2kml ( pszStyleString, poKmlStyle,
+                poKmlFeature->set_styleurl( oTmp );
+            }
+            else
+            {
+                /***** parse the style string *****/
+                const StylePtr poKmlStyle =
+                    addstylestring2kml( pszStyleString, NULL,
                                      poKmlFactory, poKmlFeature );
                 if( poKmlStyle != NULL )
                 {
-                    /***** add the style to the placemark *****/
-
-                    poKmlFeature->set_styleselector ( poKmlStyle );
+                    /***** Add the style to the placemark. *****/
+                    poKmlFeature->set_styleselector( poKmlStyle );
                 }
-
             }
         }
     }
 }
 
-
 /******************************************************************************
  function to read a kml style into ogr's featurestyle
 ******************************************************************************/
 
-void kml2featurestyle (
+void kml2featurestyle(
     FeaturePtr poKmlFeature,
     OGRLIBKMLDataSource * poOgrDS,
     OGRLayer * poOgrLayer,
     OGRFeature * poOgrFeat )
 {
-
     /***** does the placemark have a style url? *****/
-
-    if (    poKmlFeature->has_styleurl (  ) ) {
-
-        const string poKmlStyleUrl = poKmlFeature->get_styleurl (  );
+    if( poKmlFeature->has_styleurl() )
+    {
+        const string poKmlStyleUrl = poKmlFeature->get_styleurl();
 
         /***** is the name in the layer style table *****/
+        char *pszUrl = CPLStrdup( poKmlStyleUrl.c_str() );
 
-        char *pszUrl = CPLStrdup ( poKmlStyleUrl.c_str (  ) );
-
-        OGRStyleTable *poOgrSTBLLayer;
+        OGRStyleTable *poOgrSTBLLayer = NULL;
         const char *pszTest = NULL;
 
         /***** is it a layer style ? *****/
-
-        if ( *pszUrl == '#'
-             && ( poOgrSTBLLayer = poOgrLayer->GetStyleTable (  ) ) != NULL )
+        if( *pszUrl == '#' &&
+            ( poOgrSTBLLayer = poOgrLayer->GetStyleTable() ) != NULL )
         {
-             pszTest = poOgrSTBLLayer->Find ( pszUrl + 1 );
+             pszTest = poOgrSTBLLayer->Find( pszUrl + 1 );
         }
 
-        if ( pszTest ) {
-
+        if( pszTest )
+        {
             /***** should we resolve the style *****/
+            const char *pszResolve =
+                CPLGetConfigOption( "LIBKML_RESOLVE_STYLE", "no" );
 
-            const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
-
-            if (CPLTestBool(pszResolve)) {
-
-                poOgrFeat->SetStyleString ( pszTest );
+            if( CPLTestBool(pszResolve) )
+            {
+                poOgrFeat->SetStyleString( pszTest );
             }
-
-            else {
-
+            else
+            {
                 *pszUrl = '@';
-
                 poOgrFeat->SetStyleString( pszUrl );
-
             }
-
         }
-
         /***** is it a dataset style? *****/
+        else
+        {
+            const int nPathLen =
+                static_cast<int>(strlen( poOgrDS->GetStylePath() ));
 
-        else {
-
-            int nPathLen = static_cast<int>(strlen ( poOgrDS->GetStylePath (  ) ));
-
-            if (    nPathLen == 0
-                 || EQUALN ( pszUrl, poOgrDS->GetStylePath (  ), nPathLen ))
+            if( nPathLen == 0 ||
+                EQUALN( pszUrl, poOgrDS->GetStylePath(), nPathLen ) )
             {
-
                 /***** should we resolve the style *****/
-
-                const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
-
-                if ( CPLTestBool(pszResolve)
-                     && ( poOgrSTBLLayer = poOgrDS->GetStyleTable (  ) ) != NULL
-                     && ( pszTest = poOgrSTBLLayer->Find ( pszUrl + nPathLen + 1) ) != NULL
-                   )
+                const char *pszResolve =
+                    CPLGetConfigOption( "LIBKML_RESOLVE_STYLE", "no" );
+
+                if( CPLTestBool(pszResolve) &&
+                    ( poOgrSTBLLayer = poOgrDS->GetStyleTable() ) != NULL &&
+                    ( pszTest =
+                          poOgrSTBLLayer->Find(pszUrl + nPathLen + 1) ) != NULL
+                    )
                 {
-
-                    poOgrFeat->SetStyleString ( pszTest );
+                    poOgrFeat->SetStyleString( pszTest );
                 }
-
-                else {
-
+                else
+                {
                     pszUrl[nPathLen] = '@';
-                    poOgrFeat->SetStyleString ( pszUrl + nPathLen );
+                    poOgrFeat->SetStyleString( pszUrl + nPathLen );
                 }
-
             }
-
             /**** its someplace else *****/
+            else
+            {
+                const char *pszFetch =
+                    CPLGetConfigOption( "LIBKML_EXTERNAL_STYLE", "no" );
 
-            else {
-
-                const char *pszFetch = CPLGetConfigOption ( "LIBKML_EXTERNAL_STYLE", "no" );
-
-                if ( CPLTestBool(pszFetch) ) {
-
+                if( CPLTestBool(pszFetch) )
+                {
                     /***** load up the style table *****/
-
                     char *pszUrlTmp = CPLStrdup(pszUrl);
                     char *pszPound = strchr(pszUrlTmp, '#');
-                    if (pszPound != NULL) {
+                    if( pszPound != NULL )
+                    {
                         *pszPound = '\0';
                     }
 
                     /***** try it as a url then a file *****/
-
                     VSILFILE *fp = NULL;
-
-                    if (    (fp = VSIFOpenL( CPLFormFilename( "/vsicurl/",
-                                                              pszUrlTmp,
-                                                              NULL),
-                                             "r" )) != NULL
-                        ||  (fp = VSIFOpenL( pszUrlTmp, "r" )) != NULL )
+                    if( (fp = VSIFOpenL(
+                             CPLFormFilename( "/vsicurl/", pszUrlTmp, NULL ),
+                              "r" )) != NULL ||
+                        (fp = VSIFOpenL( pszUrlTmp, "r" )) != NULL )
                     {
-
-                        char szbuf[1025];
+                        char szbuf[1025] = { '\0' };
                         std::string oStyle = "";
 
                         /***** loop, read and copy to a string *****/
-
-                        size_t nRead;
-
                         do {
+                            const size_t nRead =
+                                VSIFReadL(szbuf, 1, sizeof(szbuf) - 1, fp);
 
-                            nRead = VSIFReadL(szbuf, 1, sizeof(szbuf) - 1, fp);
-
-                            if (nRead == 0)
+                            if( nRead == 0 )
                                 break;
 
                             /***** copy buf to the string *****/
 
                             szbuf[nRead] = '\0';
                             oStyle.append( szbuf );
-
-                        } while (!VSIFEofL(fp));
+                        } while( !VSIFEofL(fp) );
 
                         VSIFCloseL(fp);
 
                         /***** parse the kml into the ds style table *****/
 
-                        if ( poOgrDS->ParseIntoStyleTable (&oStyle, pszUrlTmp)) {
-
-                            kml2featurestyle (poKmlFeature,
+                        if( poOgrDS->ParseIntoStyleTable(&oStyle, pszUrlTmp) )
+                        {
+                            kml2featurestyle( poKmlFeature,
                                               poOgrDS,
                                               poOgrLayer,
                                               poOgrFeat );
                         }
-
-                        else {
-
+                        else
+                        {
                             /***** if failed just store the url *****/
-
-                            poOgrFeat->SetStyleString ( pszUrl );
+                            poOgrFeat->SetStyleString( pszUrl );
                         }
                     }
                     CPLFree(pszUrlTmp);
                 }
-
-                else {
-
-                    poOgrFeat->SetStyleString ( pszUrl );
+                else
+                {
+                    poOgrFeat->SetStyleString( pszUrl );
                 }
             }
-
         }
-        CPLFree ( pszUrl );
-
+        CPLFree( pszUrl );
     }
 
     /***** does the placemark have a style selector *****/
-
-   if ( poKmlFeature->has_styleselector (  ) ) {
-
+    if( poKmlFeature->has_styleselector() )
+    {
         StyleSelectorPtr poKmlStyleSelector =
-            poKmlFeature->get_styleselector (  );
+            poKmlFeature->get_styleselector();
 
         /***** is the style a style? *****/
-
-        if ( poKmlStyleSelector->IsA ( kmldom::Type_Style ) ) {
-            StylePtr poKmlStyle = AsStyle ( poKmlStyleSelector );
+        if( poKmlStyleSelector->IsA( kmldom::Type_Style ) )
+        {
+            StylePtr poKmlStyle = AsStyle( poKmlStyleSelector );
 
             OGRStyleMgr *poOgrSM = new OGRStyleMgr;
 
             /***** if were resolving style the feature *****/
             /***** might already have styling to add too *****/
-
-            const char *pszResolve = CPLGetConfigOption ( "LIBKML_RESOLVE_STYLE", "no" );
-            if (CPLTestBool(pszResolve)) {
-                 poOgrSM->InitFromFeature ( poOgrFeat );
+            const char *pszResolve =
+                CPLGetConfigOption( "LIBKML_RESOLVE_STYLE", "no" );
+            if( CPLTestBool(pszResolve) ) {
+                 poOgrSM->InitFromFeature( poOgrFeat );
             }
-            else {
-
-                /***** if featyurestyle gets a name tool this needs changed to the above *****/
-
-                poOgrSM->InitStyleString ( NULL );
+            else
+            {
+                /***** if featyurestyle gets a name tool this needs
+                       changed to the above *****/
+                poOgrSM->InitStyleString( NULL );
             }
 
             /***** read the style *****/
-
-            kml2stylestring ( poKmlStyle, poOgrSM );
+            kml2stylestring( poKmlStyle, poOgrSM );
 
             /***** add the style to the feature *****/
-
             poOgrFeat->SetStyleString(poOgrSM->GetStyleString(NULL));
 
             delete poOgrSM;
         }
-
         /***** is the style a stylemap? *****/
-
-        else if ( poKmlStyleSelector->IsA ( kmldom::Type_StyleMap ) ) {
-            /* todo need to figure out what to do with a style map */
+        else if( poKmlStyleSelector->IsA( kmldom::Type_StyleMap ) )
+        {
+            // TODO: Need to figure out what to do with a style map.
         }
-
-
     }
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h
index 8424362..4f56b35 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfeaturestyle.h
@@ -28,21 +28,19 @@
 
 #include "ogr_libkml.h"
 
-using kmldom::FeaturePtr;
-
 void featurestyle2kml (
     OGRLIBKMLDataSource *poOgrDS,
     OGRLayer * poKOgrLayer,
     OGRFeature * poOgrFeat,
-    KmlFactory * poKmlFactory,
-    FeaturePtr poKmlFeature );
+    kmldom::KmlFactory * poKmlFactory,
+    kmldom::FeaturePtr poKmlFeature );
 
 /******************************************************************************
  function to read a kml style into ogr's featurestyle
 ******************************************************************************/
 
 void kml2featurestyle (
-    FeaturePtr poKmlFeature,
+    kmldom::FeaturePtr poKmlFeature,
     OGRLIBKMLDataSource *poOgrDS,
     OGRLayer * poOgrLayer,
-    OGRFeature *poOgrFeat);
+    OGRFeature *poOgrFeat );
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
index f65757c..3390dc3 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.cpp
@@ -28,249 +28,244 @@
  *****************************************************************************/
 
 #include "libkml_headers.h"
+#include "ogrlibkmlfield.h"
+
+#include <string>
 
-#include  <ogrsf_frmts.h>
-#include <ogr_feature.h>
+#include "ogr_feature.h"
 #include "ogr_p.h"
+#include "ogrsf_frmts.h"
 
-#include <iostream>
+CPL_CVSID("$Id: ogrlibkmlfield.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
-using kmldom::ExtendedDataPtr;
-using kmldom::SchemaPtr;
-using kmldom::SchemaDataPtr;
-using kmldom::SimpleDataPtr;
+using kmldom::CameraPtr;
 using kmldom::DataPtr;
-
-using kmldom::TimeStampPtr;
-using kmldom::TimeSpanPtr;
-using kmldom::TimePrimitivePtr;
-using kmldom::SnippetPtr;
-
-using kmldom::PointPtr;
-using kmldom::LineStringPtr;
-using kmldom::PolygonPtr;
-using kmldom::MultiGeometryPtr;
-using kmldom::GeometryPtr;
-
+using kmldom::ExtendedDataPtr;
 using kmldom::FeaturePtr;
+using kmldom::GeometryPtr;
 using kmldom::GroundOverlayPtr;
-using kmldom::IconPtr;
-using kmldom::CameraPtr;
-
-using kmldom::GxTrackPtr;
 using kmldom::GxMultiTrackPtr;
+using kmldom::GxTrackPtr;
+using kmldom::IconPtr;
+using kmldom::KmlFactory;
+using kmldom::LineStringPtr;
+using kmldom::MultiGeometryPtr;
+using kmldom::PlacemarkPtr;
+using kmldom::PointPtr;
+using kmldom::PolygonPtr;
+using kmldom::SchemaDataPtr;
+using kmldom::SchemaPtr;
+using kmldom::SimpleDataPtr;
+using kmldom::SimpleFieldPtr;
+using kmldom::SnippetPtr;
+using kmldom::TimePrimitivePtr;
+using kmldom::TimeSpanPtr;
+using kmldom::TimeStampPtr;
 
-#include "ogr_libkml.h"
-
-#include "ogrlibkmlfield.h"
-
-static void ogr2altitudemode_rec (
-    GeometryPtr poKmlGeometry,
+static void ogr2altitudemode_rec(
+    const GeometryPtr &poKmlGeometry,
     int iAltitudeMode,
     int isGX )
 {
-
-    PointPtr poKmlPoint;
-    LineStringPtr poKmlLineString;
-    PolygonPtr poKmlPolygon;
-    MultiGeometryPtr poKmlMultiGeometry;
-
-    size_t nGeom;
-    size_t i;
-
-    switch ( poKmlGeometry->Type (  ) ) {
-
+    switch( poKmlGeometry->Type() )
+    {
     case kmldom::Type_Point:
-        poKmlPoint = AsPoint ( poKmlGeometry );
+    {
+        PointPtr poKmlPoint = AsPoint( poKmlGeometry );
 
-        if ( !isGX )
-            poKmlPoint->set_altitudemode ( iAltitudeMode );
+        if( !isGX )
+            poKmlPoint->set_altitudemode( iAltitudeMode );
         else
-            poKmlPoint->set_gx_altitudemode ( iAltitudeMode );
+            poKmlPoint->set_gx_altitudemode( iAltitudeMode );
 
         break;
-
+    }
     case kmldom::Type_LineString:
-        poKmlLineString = AsLineString ( poKmlGeometry );
+    {
+        LineStringPtr poKmlLineString = AsLineString( poKmlGeometry );
 
-        if ( !isGX )
-            poKmlLineString->set_altitudemode ( iAltitudeMode );
+        if( !isGX )
+            poKmlLineString->set_altitudemode( iAltitudeMode );
         else
-            poKmlLineString->set_gx_altitudemode ( iAltitudeMode );
+            poKmlLineString->set_gx_altitudemode( iAltitudeMode );
 
         break;
-
+    }
     case kmldom::Type_LinearRing:
+    {
         break;
-
+    }
     case kmldom::Type_Polygon:
-        poKmlPolygon = AsPolygon ( poKmlGeometry );
+    {
+        PolygonPtr poKmlPolygon = AsPolygon( poKmlGeometry );
 
-        if ( !isGX )
-            poKmlPolygon->set_altitudemode ( iAltitudeMode );
+        if( !isGX )
+            poKmlPolygon->set_altitudemode( iAltitudeMode );
         else
-            poKmlPolygon->set_gx_altitudemode ( iAltitudeMode );
+            poKmlPolygon->set_gx_altitudemode( iAltitudeMode );
 
         break;
-
+    }
     case kmldom::Type_MultiGeometry:
-        poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
+    {
+        MultiGeometryPtr poKmlMultiGeometry = AsMultiGeometry( poKmlGeometry );
 
-        nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
-        for ( i = 0; i < nGeom; i++ ) {
-            ogr2altitudemode_rec ( poKmlMultiGeometry->
-                                   get_geometry_array_at ( i ), iAltitudeMode,
-                                   isGX );
+        const size_t nGeom = poKmlMultiGeometry->get_geometry_array_size();
+        for( size_t i = 0; i < nGeom; i++ )
+        {
+            ogr2altitudemode_rec( poKmlMultiGeometry->
+                                  get_geometry_array_at( i ), iAltitudeMode,
+                                  isGX );
         }
 
         break;
-
+    }
     default:
+    {
         break;
-
     }
-
+    }
 }
 
-static void ogr2extrude_rec (
-    bool bExtrude,
-    GeometryPtr poKmlGeometry )
+static void ogr2extrude_rec( bool bExtrude, const GeometryPtr &poKmlGeometry )
 {
-
-    PointPtr poKmlPoint;
-    LineStringPtr poKmlLineString;
-    PolygonPtr poKmlPolygon;
-    MultiGeometryPtr poKmlMultiGeometry;
-
-    size_t nGeom;
-    size_t i;
-
-    switch ( poKmlGeometry->Type (  ) ) {
+    switch( poKmlGeometry->Type() )
+    {
     case kmldom::Type_Point:
-        poKmlPoint = AsPoint ( poKmlGeometry );
-        poKmlPoint->set_extrude ( bExtrude );
+    {
+        PointPtr const poKmlPoint = AsPoint( poKmlGeometry );
+        poKmlPoint->set_extrude( bExtrude );
         break;
-
+    }
     case kmldom::Type_LineString:
-        poKmlLineString = AsLineString ( poKmlGeometry );
-        poKmlLineString->set_extrude ( bExtrude );
+    {
+        LineStringPtr const poKmlLineString = AsLineString( poKmlGeometry );
+        poKmlLineString->set_extrude( bExtrude );
         break;
-
+    }
     case kmldom::Type_LinearRing:
+    {
         break;
-
+    }
     case kmldom::Type_Polygon:
-        poKmlPolygon = AsPolygon ( poKmlGeometry );
-        poKmlPolygon->set_extrude ( bExtrude );
+    {
+        PolygonPtr const poKmlPolygon = AsPolygon( poKmlGeometry );
+        poKmlPolygon->set_extrude( bExtrude );
         break;
-
+    }
     case kmldom::Type_MultiGeometry:
-        poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
+    {
+        MultiGeometryPtr const poKmlMultiGeometry =
+            AsMultiGeometry( poKmlGeometry );
 
-        nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
-        for ( i = 0; i < nGeom; i++ ) {
-            ogr2extrude_rec ( bExtrude,
-                              poKmlMultiGeometry->
-                              get_geometry_array_at ( i ) );
+        const size_t nGeom = poKmlMultiGeometry->get_geometry_array_size();
+        for( size_t i = 0; i < nGeom; i++ )
+        {
+            ogr2extrude_rec( bExtrude,
+                             poKmlMultiGeometry->
+                             get_geometry_array_at( i ) );
         }
         break;
-
+    }
     default:
+    {
         break;
-
+    }
     }
 }
 
-static void ogr2tessellate_rec (
+static void ogr2tessellate_rec(
     bool bTessellate,
-    GeometryPtr poKmlGeometry )
+    const GeometryPtr &poKmlGeometry )
 {
-
-    LineStringPtr poKmlLineString;
-    PolygonPtr poKmlPolygon;
-    MultiGeometryPtr poKmlMultiGeometry;
-
-    size_t nGeom;
-    size_t i;
-
-    switch ( poKmlGeometry->Type (  ) ) {
-
+    switch( poKmlGeometry->Type() )
+    {
     case kmldom::Type_Point:
+    {
         break;
-
+    }
     case kmldom::Type_LineString:
-        poKmlLineString = AsLineString ( poKmlGeometry );
-        poKmlLineString->set_tessellate ( bTessellate );
+    {
+        LineStringPtr const poKmlLineString = AsLineString( poKmlGeometry );
+        poKmlLineString->set_tessellate( bTessellate );
         break;
-
+    }
     case kmldom::Type_LinearRing:
+    {
         break;
-
+    }
     case kmldom::Type_Polygon:
-        poKmlPolygon = AsPolygon ( poKmlGeometry );
+    {
+        PolygonPtr const poKmlPolygon = AsPolygon( poKmlGeometry );
 
-        poKmlPolygon->set_tessellate ( bTessellate );
+        poKmlPolygon->set_tessellate( bTessellate );
         break;
-
+    }
     case kmldom::Type_MultiGeometry:
-        poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
+    {
+        MultiGeometryPtr const poKmlMultiGeometry =
+            AsMultiGeometry( poKmlGeometry );
 
-        nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
-        for ( i = 0; i < nGeom; i++ ) {
-            ogr2tessellate_rec ( bTessellate,
-                                 poKmlMultiGeometry->
-                                 get_geometry_array_at ( i ) );
+        const size_t nGeom = poKmlMultiGeometry->get_geometry_array_size();
+        for( size_t i = 0; i < nGeom; i++ )
+        {
+            ogr2tessellate_rec( bTessellate,
+                                poKmlMultiGeometry->
+                                get_geometry_array_at( i ) );
         }
 
         break;
-
+    }
     default:
+    {
         break;
-
+    }
     }
 }
 
-
 /************************************************************************/
 /*                 OGRLIBKMLSanitizeUTF8String()                        */
 /************************************************************************/
 
-static char* OGRLIBKMLSanitizeUTF8String(const char* pszString)
+static char* OGRLIBKMLSanitizeUTF8String( const char* pszString )
 {
-    if (!CPLIsUTF8(pszString, -1) &&
-         CPLTestBool(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
+    if( !CPLIsUTF8(pszString, -1) &&
+        CPLTestBool(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")) )
     {
-        static int bFirstTime = TRUE;
-        if (bFirstTime)
+        static bool bFirstTime = true;
+        if( bFirstTime )
         {
-            bFirstTime = FALSE;
-            CPLError(CE_Warning, CPLE_AppDefined,
-                    "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
-                    "If you still want the original string and change the XML file encoding\n"
-                    "afterwards, you can define OGR_FORCE_ASCII=NO as configuration option.\n"
-                    "This warning won't be issued anymore", pszString);
+            bFirstTime = false;
+            CPLError(
+                CE_Warning, CPLE_AppDefined,
+                "%s is not a valid UTF-8 string. Forcing it to ASCII.  "
+                "If you still want the original string and change the XML file "
+                "encoding afterwards, you can define OGR_FORCE_ASCII=NO as "
+                "  configuration option.  This warning won't be issued anymore",
+                pszString);
         }
         else
         {
-            CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
-                    pszString);
+            CPLDebug(
+                "OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
+                pszString);
         }
         return CPLForceToASCII(pszString, -1, '?');
     }
-    else
-        return CPLStrdup(pszString);
+
+    return CPLStrdup(pszString);
 }
 
 /******************************************************************************
- function to output ogr fields in kml
+ Function to output ogr fields in kml.
 
- args:
+ Args:
         poOgrFeat       pointer to the feature the field is in
         poOgrLayer      pointer to the layer the feature is in
         poKmlFactory    pointer to the libkml dom factory
         poKmlPlacemark  pointer to the placemark to add to
 
- returns:
+ Returns:
         nothing
 
  env vars:
@@ -280,77 +275,72 @@ static char* OGRLIBKMLSanitizeUTF8String(const char* pszString)
   LIBKML_DESCRIPTION_FIELD       default: none
   LIBKML_NAME_FIELD              default: OFTString field named name
 
-
 ******************************************************************************/
 
-void field2kml (
+void field2kml(
     OGRFeature * poOgrFeat,
     OGRLIBKMLLayer * poOgrLayer,
     KmlFactory * poKmlFactory,
     FeaturePtr poKmlFeature,
-    int bUseSimpleField)
+    int bUseSimpleFieldIn )
 {
-    int i;
-
-    ExtendedDataPtr poKmlExtendedData = NULL;
+    const bool bUseSimpleField = CPL_TO_BOOL(bUseSimpleFieldIn);
     SchemaDataPtr poKmlSchemaData = NULL;
     if( bUseSimpleField )
     {
-        poKmlSchemaData = poKmlFactory->CreateSchemaData (  );
-        SchemaPtr poKmlSchema = poOgrLayer->GetKmlSchema (  );
+        poKmlSchemaData = poKmlFactory->CreateSchemaData();
+        SchemaPtr poKmlSchema = poOgrLayer->GetKmlSchema();
 
         /***** set the url to the schema *****/
-
-        if ( poKmlSchema && poKmlSchema->has_id (  ) ) {
-            std::string oKmlSchemaID = poKmlSchema->get_id (  );
-
-
+        if( poKmlSchema && poKmlSchema->has_id() )
+        {
+            std::string oKmlSchemaID = poKmlSchema->get_id();
             std::string oKmlSchemaURL = "#";
-            oKmlSchemaURL.append ( oKmlSchemaID );
+            oKmlSchemaURL.append( oKmlSchemaID );
 
-            poKmlSchemaData->set_schemaurl ( oKmlSchemaURL );
+            poKmlSchemaData->set_schemaurl( oKmlSchemaURL );
         }
     }
 
-    /***** get the field config *****/
-
+    /***** Get the field config *****/
     struct fieldconfig oFC;
     get_fieldconfig( &oFC );
 
     TimeSpanPtr poKmlTimeSpan = NULL;
 
-    int nFields = poOgrFeat->GetFieldCount (  );
+    const int nFields = poOgrFeat->GetFieldCount();
     int iSkip1 = -1;
     int iSkip2 = -1;
     int iAltitudeMode = kmldom::ALTITUDEMODE_CLAMPTOGROUND;
-    int isGX = FALSE;
-
-    for ( i = 0; i < nFields; i++ ) {
+    int isGX = false;
 
-        /***** if the field is set to skip, do so *****/
+    ExtendedDataPtr poKmlExtendedData = NULL;
 
-        if ( i == iSkip1 || i == iSkip2 )
+    for( int i = 0; i < nFields; i++ )
+    {
+        /***** If the field is set to skip, do so *****/
+        if( i == iSkip1 || i == iSkip2 )
             continue;
 
-        /***** if the field isn't set just bail now *****/
-
-        if ( !poOgrFeat->IsFieldSet ( i ) )
+        /***** If the field isn't set just bail now *****/
+        if( !poOgrFeat->IsFieldSetAndNotNull( i ) )
             continue;
 
-        OGRFieldDefn *poOgrFieldDef = poOgrFeat->GetFieldDefnRef ( i );
-        OGRFieldType type = poOgrFieldDef->GetType (  );
-        const char *name = poOgrFieldDef->GetNameRef (  );
+        OGRFieldDefn *poOgrFieldDef = poOgrFeat->GetFieldDefnRef( i );
+        const OGRFieldType type = poOgrFieldDef->GetType();
+        const char *name = poOgrFieldDef->GetNameRef();
 
         SimpleDataPtr poKmlSimpleData = NULL;
         DataPtr poKmlData = NULL;
         OGRField sFieldDT;
 
-        switch ( type ) {
-
+        // TODO(schwehr): Refactor to get rid of gotos.
+        switch( type )
+        {
         case OFTString:        //     String of ASCII chars
             {
-                char* pszUTF8String = OGRLIBKMLSanitizeUTF8String(
-                                        poOgrFeat->GetFieldAsString ( i ));
+                char* const pszUTF8String = OGRLIBKMLSanitizeUTF8String(
+                    poOgrFeat->GetFieldAsString( i ));
                 if( pszUTF8String[0] == '\0' )
                 {
                     CPLFree( pszUTF8String );
@@ -358,37 +348,38 @@ void field2kml (
                 }
 
                 /***** name *****/
-
-                if ( EQUAL ( name, oFC.namefield ) ) {
-                    poKmlFeature->set_name ( pszUTF8String );
+                if( EQUAL( name, oFC.namefield ) )
+                {
+                    poKmlFeature->set_name( pszUTF8String );
                     CPLFree( pszUTF8String );
                     continue;
                 }
-
                 /***** description *****/
-
-                else if ( EQUAL ( name, oFC.descfield ) ) {
-                    poKmlFeature->set_description ( pszUTF8String );
+                else if( EQUAL( name, oFC.descfield ) )
+                {
+                    poKmlFeature->set_description( pszUTF8String );
                     CPLFree( pszUTF8String );
                     continue;
                 }
-
                 /***** altitudemode *****/
-
-                else if ( EQUAL ( name, oFC.altitudeModefield ) ) {
+                else if( EQUAL( name, oFC.altitudeModefield ) )
+                {
                     const char *pszAltitudeMode = pszUTF8String ;
 
-                    iAltitudeMode = kmlAltitudeModeFromString(pszAltitudeMode, isGX);
+                    iAltitudeMode =
+                        kmlAltitudeModeFromString(pszAltitudeMode, isGX);
 
-                    if ( poKmlFeature->IsA ( kmldom::Type_Placemark ) ) {
-                        PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
-                        if ( poKmlPlacemark->has_geometry (  ) ) {
+                    if( poKmlFeature->IsA( kmldom::Type_Placemark ) )
+                    {
+                        PlacemarkPtr const poKmlPlacemark =
+                            AsPlacemark( poKmlFeature );
+                        if( poKmlPlacemark->has_geometry() )
+                        {
                             GeometryPtr poKmlGeometry =
-                                poKmlPlacemark->get_geometry (  );
-
-                            ogr2altitudemode_rec ( poKmlGeometry, iAltitudeMode,
-                                                isGX );
+                                poKmlPlacemark->get_geometry();
 
+                            ogr2altitudemode_rec( poKmlGeometry, iAltitudeMode,
+                                                  isGX );
                         }
                     }
 
@@ -396,82 +387,72 @@ void field2kml (
 
                     continue;
                 }
-
                 /***** timestamp *****/
-
-                else if ( EQUAL ( name, oFC.tsfield ) ) {
-
+                else if( EQUAL( name, oFC.tsfield ) )
+                {
                     TimeStampPtr poKmlTimeStamp =
-                        poKmlFactory->CreateTimeStamp (  );
-                    poKmlTimeStamp->set_when ( pszUTF8String  );
-                    poKmlFeature->set_timeprimitive ( poKmlTimeStamp );
+                        poKmlFactory->CreateTimeStamp();
+                    poKmlTimeStamp->set_when( pszUTF8String );
+                    poKmlFeature->set_timeprimitive( poKmlTimeStamp );
 
                     CPLFree( pszUTF8String );
 
                     continue;
                 }
-
                 /***** begin *****/
-
-                if ( EQUAL ( name, oFC.beginfield ) ) {
-
-                    if ( !poKmlTimeSpan ) {
-                        poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
-                        poKmlFeature->set_timeprimitive ( poKmlTimeSpan );
+                if( EQUAL( name, oFC.beginfield ) )
+                {
+                    if( !poKmlTimeSpan )
+                    {
+                        poKmlTimeSpan = poKmlFactory->CreateTimeSpan();
+                        poKmlFeature->set_timeprimitive( poKmlTimeSpan );
                     }
 
-                    poKmlTimeSpan->set_begin ( pszUTF8String );
+                    poKmlTimeSpan->set_begin( pszUTF8String );
 
                     CPLFree( pszUTF8String );
 
                     continue;
-
                 }
-
                 /***** end *****/
-
-                else if ( EQUAL ( name, oFC.endfield ) ) {
-
-                    if ( !poKmlTimeSpan ) {
-                        poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
-                        poKmlFeature->set_timeprimitive ( poKmlTimeSpan );
+                else if( EQUAL( name, oFC.endfield ) )
+                {
+                    if( !poKmlTimeSpan )
+                    {
+                        poKmlTimeSpan = poKmlFactory->CreateTimeSpan();
+                        poKmlFeature->set_timeprimitive( poKmlTimeSpan );
                     }
 
-                    poKmlTimeSpan->set_end ( pszUTF8String );
+                    poKmlTimeSpan->set_end( pszUTF8String );
 
                     CPLFree( pszUTF8String );
 
                     continue;
                 }
-
                 /***** snippet *****/
-
-                else if  ( EQUAL ( name, oFC.snippetfield ) ) {
-
-                    SnippetPtr snippet = poKmlFactory->CreateSnippet (  );
+                else if( EQUAL( name, oFC.snippetfield ) )
+                {
+                    SnippetPtr snippet = poKmlFactory->CreateSnippet();
                     snippet->set_text(pszUTF8String);
-                    poKmlFeature->set_snippet ( snippet );
+                    poKmlFeature->set_snippet( snippet );
 
                     CPLFree( pszUTF8String );
 
                     continue;
-
                 }
-
                 /***** other special fields *****/
-
-                else if (  EQUAL ( name, oFC.iconfield ) ||
-                           EQUAL ( name, oFC.modelfield ) ||
-                           EQUAL ( name, oFC.networklinkfield ) ||
-                           EQUAL ( name, oFC.networklink_refreshMode_field ) ||
-                           EQUAL ( name, oFC.networklink_viewRefreshMode_field ) ||
-                           EQUAL ( name, oFC.networklink_viewFormat_field ) ||
-                           EQUAL ( name, oFC.networklink_httpQuery_field ) ||
-                           EQUAL ( name, oFC.camera_altitudemode_field ) ||
-                           EQUAL ( name, oFC.photooverlayfield ) ||
-                           EQUAL ( name, oFC.photooverlay_shape_field ) ||
-                           EQUAL ( name, oFC.imagepyramid_gridorigin_field ) ) {
-
+                else if( EQUAL( name, oFC.iconfield ) ||
+                         EQUAL( name, oFC.modelfield ) ||
+                         EQUAL( name, oFC.networklinkfield ) ||
+                         EQUAL( name, oFC.networklink_refreshMode_field ) ||
+                         EQUAL( name, oFC.networklink_viewRefreshMode_field ) ||
+                         EQUAL( name, oFC.networklink_viewFormat_field ) ||
+                         EQUAL( name, oFC.networklink_httpQuery_field ) ||
+                         EQUAL( name, oFC.camera_altitudemode_field ) ||
+                         EQUAL( name, oFC.photooverlayfield ) ||
+                         EQUAL( name, oFC.photooverlay_shape_field ) ||
+                         EQUAL( name, oFC.imagepyramid_gridorigin_field ) )
+                {
                     CPLFree( pszUTF8String );
 
                     continue;
@@ -481,15 +462,15 @@ void field2kml (
 
                 if( bUseSimpleField )
                 {
-                    poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-                    poKmlSimpleData->set_name ( name );
-                    poKmlSimpleData->set_text ( pszUTF8String );
+                    poKmlSimpleData = poKmlFactory->CreateSimpleData();
+                    poKmlSimpleData->set_name( name );
+                    poKmlSimpleData->set_text( pszUTF8String );
                 }
                 else
                 {
-                    poKmlData = poKmlFactory->CreateData (  );
-                    poKmlData->set_name ( name );
-                    poKmlData->set_value ( pszUTF8String );
+                    poKmlData = poKmlFactory->CreateData();
+                    poKmlData->set_name( name );
+                    poKmlData->set_value( pszUTF8String );
                 }
 
                 CPLFree( pszUTF8String );
@@ -497,36 +478,40 @@ void field2kml (
                 break;
             }
 
-        /* This code checks if there's a OFTTime field with the same name */
-        /* that could be used to compose a DateTime. Not sure this is really */
-        /* supported in OGR data model to have 2 fields with same name... */
+        // This code checks if there's a OFTTime field with the same name
+        // that could be used to compose a DateTime. Not sure this is really
+        // supported in OGR data model to have 2 fields with same name.
         case OFTDate:          //   Date
             {
-                memcpy(&sFieldDT, poOgrFeat->GetRawFieldRef(i), sizeof(OGRField));
+                memcpy(&sFieldDT,
+                       poOgrFeat->GetRawFieldRef(i),
+                       sizeof(OGRField));
 
-                int iTimeField;
-
-                for ( iTimeField = i + 1; iTimeField < nFields; iTimeField++ ) {
-                    if ( iTimeField == iSkip1 || iTimeField == iSkip2 )
+                for( int iTimeField = i + 1;
+                     iTimeField < nFields;
+                     iTimeField++ )
+                {
+                    if( iTimeField == iSkip1 || iTimeField == iSkip2 )
                         continue;
 
                     OGRFieldDefn *poOgrFieldDef2 =
-                        poOgrFeat->GetFieldDefnRef ( i );
-                    OGRFieldType type2 = poOgrFieldDef2->GetType (  );
-                    const char *name2 = poOgrFieldDef2->GetNameRef (  );
-
-                    if ( EQUAL ( name2, name ) && type2 == OFTTime &&
-                         ( EQUAL ( name, oFC.tsfield ) ||
-                           EQUAL ( name, oFC.beginfield ) ||
-                           EQUAL ( name, oFC.endfield ) ) ) {
-
-                        const OGRField* psField2 = poOgrFeat->GetRawFieldRef(iTimeField);
+                        poOgrFeat->GetFieldDefnRef( i );
+                    OGRFieldType type2 = poOgrFieldDef2->GetType();
+                    const char *name2 = poOgrFieldDef2->GetNameRef();
+
+                    if( EQUAL( name2, name ) && type2 == OFTTime &&
+                        ( EQUAL( name, oFC.tsfield ) ||
+                          EQUAL( name, oFC.beginfield ) ||
+                          EQUAL( name, oFC.endfield ) ) )
+                    {
+                        const OGRField* const psField2 =
+                            poOgrFeat->GetRawFieldRef(iTimeField);
                         sFieldDT.Date.Hour = psField2->Date.Hour;
                         sFieldDT.Date.Minute = psField2->Date.Minute;
                         sFieldDT.Date.Second = psField2->Date.Second;
                         sFieldDT.Date.TZFlag = psField2->Date.TZFlag;
 
-                        if ( 0 > iSkip1 )
+                        if( 0 > iSkip1 )
                             iSkip1 = iTimeField;
                         else
                             iSkip2 = iTimeField;
@@ -534,38 +519,41 @@ void field2kml (
                 }
 
                 goto Do_DateTime;
-
             }
 
-        /* This code checks if there's a OFTTime field with the same name */
-        /* that could be used to compose a DateTime. Not sure this is really */
-        /* supported in OGR data model to have 2 fields with same name... */
+        // This code checks if there's a OFTTime field with the same name
+        // that could be used to compose a DateTime. Not sure this is really
+        // supported in OGR data model to have 2 fields with same name.
         case OFTTime:          //   Time
             {
-                memcpy(&sFieldDT, poOgrFeat->GetRawFieldRef(i), sizeof(OGRField));
+                memcpy(&sFieldDT,
+                       poOgrFeat->GetRawFieldRef(i),
+                       sizeof(OGRField));
 
-                int iTimeField;
-
-                for ( iTimeField = i + 1; iTimeField < nFields; iTimeField++ ) {
-                    if ( iTimeField == iSkip1 || iTimeField == iSkip2 )
+                for( int iTimeField = i + 1;
+                     iTimeField < nFields;
+                     iTimeField++ )
+                {
+                    if( iTimeField == iSkip1 || iTimeField == iSkip2 )
                         continue;
 
-                    OGRFieldDefn *poOgrFieldDef2 =
-                        poOgrFeat->GetFieldDefnRef ( i );
-                    OGRFieldType type2 = poOgrFieldDef2->GetType (  );
-                    const char *name2 = poOgrFieldDef2->GetNameRef (  );
-
-                    if ( EQUAL ( name2, name ) && type2 == OFTDate &&
-                         ( EQUAL ( name, oFC.tsfield ) ||
-                           EQUAL ( name, oFC.beginfield ) ||
-                           EQUAL ( name, oFC.endfield ) ) ) {
+                    OGRFieldDefn * const poOgrFieldDef2 =
+                        poOgrFeat->GetFieldDefnRef( i );
+                    OGRFieldType type2 = poOgrFieldDef2->GetType();
+                    const char * const name2 = poOgrFieldDef2->GetNameRef();
 
-                        const OGRField* psField2 = poOgrFeat->GetRawFieldRef(iTimeField);
+                    if( EQUAL( name2, name ) && type2 == OFTDate &&
+                        ( EQUAL( name, oFC.tsfield ) ||
+                          EQUAL( name, oFC.beginfield ) ||
+                          EQUAL( name, oFC.endfield ) ) )
+                    {
+                        const OGRField* psField2 =
+                            poOgrFeat->GetRawFieldRef(iTimeField);
                         sFieldDT.Date.Year = psField2->Date.Year;
                         sFieldDT.Date.Month = psField2->Date.Month;
                         sFieldDT.Date.Day = psField2->Date.Day;
 
-                        if ( 0 > iSkip1 )
+                        if( 0 > iSkip1 )
                             iSkip1 = iTimeField;
                         else
                             iSkip2 = iTimeField;
@@ -573,7 +561,6 @@ void field2kml (
                 }
 
                 goto Do_DateTime;
-
             }
 
         case OFTDateTime:      //  Date and Time
@@ -582,71 +569,67 @@ void field2kml (
 
               Do_DateTime:
                 /***** timestamp *****/
-
-                if ( EQUAL ( name, oFC.tsfield ) ) {
-
-                    char *timebuf = OGRGetXMLDateTime ( &sFieldDT );
+                if( EQUAL( name, oFC.tsfield ) )
+                {
+                    char * const timebuf = OGRGetXMLDateTime( &sFieldDT );
 
                     TimeStampPtr poKmlTimeStamp =
-                        poKmlFactory->CreateTimeStamp (  );
-                    poKmlTimeStamp->set_when ( timebuf );
-                    poKmlFeature->set_timeprimitive ( poKmlTimeStamp );
+                        poKmlFactory->CreateTimeStamp();
+                    poKmlTimeStamp->set_when( timebuf );
+                    poKmlFeature->set_timeprimitive( poKmlTimeStamp );
                     CPLFree( timebuf );
 
                     continue;
                 }
 
                 /***** begin *****/
+                if( EQUAL( name, oFC.beginfield ) )
+                {
+                    char * const timebuf = OGRGetXMLDateTime( &sFieldDT );
 
-                if ( EQUAL ( name, oFC.beginfield ) ) {
-
-                    char *timebuf = OGRGetXMLDateTime ( &sFieldDT );
-
-                    if ( !poKmlTimeSpan ) {
-                        poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
-                        poKmlFeature->set_timeprimitive ( poKmlTimeSpan );
+                    if( !poKmlTimeSpan )
+                    {
+                        poKmlTimeSpan = poKmlFactory->CreateTimeSpan();
+                        poKmlFeature->set_timeprimitive( poKmlTimeSpan );
                     }
 
-                    poKmlTimeSpan->set_begin ( timebuf );
+                    poKmlTimeSpan->set_begin( timebuf );
                     CPLFree( timebuf );
 
                     continue;
-
                 }
 
                 /***** end *****/
+                else if( EQUAL( name, oFC.endfield ) )
+                {
+                    char * const timebuf = OGRGetXMLDateTime( &sFieldDT );
 
-                else if ( EQUAL ( name, oFC.endfield ) ) {
-
-                    char *timebuf = OGRGetXMLDateTime ( &sFieldDT );
-
-
-                    if ( !poKmlTimeSpan ) {
-                        poKmlTimeSpan = poKmlFactory->CreateTimeSpan (  );
-                        poKmlFeature->set_timeprimitive ( poKmlTimeSpan );
+                    if( !poKmlTimeSpan )
+                    {
+                        poKmlTimeSpan = poKmlFactory->CreateTimeSpan();
+                        poKmlFeature->set_timeprimitive( poKmlTimeSpan );
                     }
 
-                    poKmlTimeSpan->set_end ( timebuf );
+                    poKmlTimeSpan->set_end( timebuf );
                     CPLFree( timebuf );
 
                     continue;
                 }
 
                 /***** other *****/
-
                 if( bUseSimpleField )
                 {
-                    poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-                    poKmlSimpleData->set_name ( name );
-                    poKmlSimpleData->set_text ( poOgrFeat->
-                                                GetFieldAsString ( i ) );
+                    poKmlSimpleData = poKmlFactory->CreateSimpleData();
+                    poKmlSimpleData->set_name( name );
+                    poKmlSimpleData->set_text( poOgrFeat->
+                                               GetFieldAsString( i ) );
                 }
                 else
                 {
-                    poKmlData = poKmlFactory->CreateData (  );
-                    poKmlData->set_name ( name );
-                    poKmlData->set_value ( poOgrFeat->
-                                                GetFieldAsString ( i ) );
+                    poKmlData = poKmlFactory->CreateData();
+                    poKmlData->set_name( name );
+                    poKmlData->set_value( poOgrFeat->
+                                          GetFieldAsString( i ) );
                 }
 
                 break;
@@ -655,27 +638,33 @@ void field2kml (
         case OFTInteger:       //    Simple 32bit integer
 
             /***** extrude *****/
-
-            if ( EQUAL ( name, oFC.extrudefield ) ) {
-
-                if ( poKmlFeature->IsA ( kmldom::Type_Placemark ) ) {
-                    PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
-                    if ( poKmlPlacemark->has_geometry (  )
-                        && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
-                        int iExtrude = poOgrFeat->GetFieldAsInteger ( i );
+            if( EQUAL( name, oFC.extrudefield ) )
+            {
+                if( poKmlFeature->IsA( kmldom::Type_Placemark ) )
+                {
+                    PlacemarkPtr poKmlPlacemark = AsPlacemark( poKmlFeature );
+                    if( poKmlPlacemark->has_geometry()
+                        && -1 < poOgrFeat->GetFieldAsInteger( i ) )
+                    {
+                        const int iExtrude = poOgrFeat->GetFieldAsInteger( i );
                         if( iExtrude &&
-                            isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND &&
-                            CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                            !isGX &&
+                            iAltitudeMode ==
+                                kmldom::ALTITUDEMODE_CLAMPTOGROUND &&
+                            CPLTestBool(CPLGetConfigOption(
+                                "LIBKML_STRICT_COMPLIANCE", "TRUE")) )
                         {
-                            CPLError(CE_Warning, CPLE_NotSupported,
-                                "altitudeMode=clampToGround unsupported with extrude=1");
+                            CPLError(
+                                CE_Warning, CPLE_NotSupported,
+                                "altitudeMode=clampToGround unsupported with "
+                                "extrude=1");
                         }
                         else
                         {
                             GeometryPtr poKmlGeometry =
-                                poKmlPlacemark->get_geometry (  );
-                            ogr2extrude_rec ( CPL_TO_BOOL(iExtrude),
-                                            poKmlGeometry );
+                                poKmlPlacemark->get_geometry();
+                            ogr2extrude_rec( CPL_TO_BOOL(iExtrude),
+                                             poKmlGeometry );
                         }
                     }
                 }
@@ -683,19 +672,24 @@ void field2kml (
             }
 
             /***** tessellate *****/
-
-
-            if ( EQUAL ( name, oFC.tessellatefield ) ) {
-
-                if ( poKmlFeature->IsA ( kmldom::Type_Placemark ) ) {
-                    PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
-                    if ( poKmlPlacemark->has_geometry (  )
-                        && -1 < poOgrFeat->GetFieldAsInteger ( i ) ) {
-                        int iTesselate = poOgrFeat->GetFieldAsInteger ( i );
+            if( EQUAL( name, oFC.tessellatefield ) )
+            {
+                if( poKmlFeature->IsA( kmldom::Type_Placemark ) )
+                {
+                    PlacemarkPtr poKmlPlacemark = AsPlacemark( poKmlFeature );
+                    if( poKmlPlacemark->has_geometry()
+                        && -1 < poOgrFeat->GetFieldAsInteger( i ) )
+                    {
+                        const int iTesselate = poOgrFeat->GetFieldAsInteger( i );
                         if( iTesselate &&
-                            !(isGX == FALSE && static_cast<kmldom::AltitudeModeEnum>(iAltitudeMode) == kmldom::ALTITUDEMODE_CLAMPTOGROUND) &&
-                            !(isGX == TRUE && static_cast<kmldom::GxAltitudeModeEnum>(iAltitudeMode) == kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR) &&
-                            CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                            !(!isGX &&
+                              static_cast<kmldom::AltitudeModeEnum>(iAltitudeMode) ==
+                              kmldom::ALTITUDEMODE_CLAMPTOGROUND) &&
+                            !(isGX &&
+                              static_cast<kmldom::GxAltitudeModeEnum>(iAltitudeMode) ==
+                              kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR) &&
+                            CPLTestBool(CPLGetConfigOption(
+                                "LIBKML_STRICT_COMPLIANCE", "TRUE")) )
                         {
                             CPLError( CE_Warning, CPLE_NotSupported,
                                       "altitudeMode!=clampToGround && "
@@ -705,12 +699,15 @@ void field2kml (
                         else
                         {
                             GeometryPtr poKmlGeometry =
-                                poKmlPlacemark->get_geometry (  );
-                            ogr2tessellate_rec ( CPL_TO_BOOL(iTesselate),
+                                poKmlPlacemark->get_geometry();
+                            ogr2tessellate_rec( CPL_TO_BOOL(iTesselate),
                                                 poKmlGeometry );
-                            if( isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND )
-                                ogr2altitudemode_rec ( poKmlGeometry, iAltitudeMode,
-                                                    isGX );
+                            if( !isGX &&
+                                iAltitudeMode ==
+                                    kmldom::ALTITUDEMODE_CLAMPTOGROUND )
+                                ogr2altitudemode_rec(
+                                    poKmlGeometry, iAltitudeMode,
+                                    isGX );
                         }
                     }
                 }
@@ -718,46 +715,41 @@ void field2kml (
                 continue;
             }
 
-
             /***** visibility *****/
-
-            if ( EQUAL ( name, oFC.visibilityfield ) ) {
-                if ( -1 < poOgrFeat->GetFieldAsInteger ( i ) )
-                    poKmlFeature->set_visibility ( CPL_TO_BOOL(poOgrFeat->
-                                                     GetFieldAsInteger ( i )) );
+            if( EQUAL( name, oFC.visibilityfield ) )
+            {
+                if( -1 < poOgrFeat->GetFieldAsInteger( i ) )
+                    poKmlFeature->set_visibility(
+                        CPL_TO_BOOL(poOgrFeat->GetFieldAsInteger( i )) );
 
                 continue;
             }
-
-
             /***** other special fields *****/
-
-            else if (  EQUAL ( name, oFC.drawOrderfield ) ||
-                        EQUAL ( name, oFC.networklink_refreshvisibility_field ) ||
-                        EQUAL ( name, oFC.networklink_flytoview_field ) ||
-                        EQUAL ( name, oFC.networklink_refreshInterval_field ) ||
-                        EQUAL ( name, oFC.networklink_viewRefreshMode_field ) ||
-                        EQUAL ( name, oFC.networklink_viewRefreshTime_field ) ||
-                        EQUAL ( name, oFC.imagepyramid_tilesize_field ) ||
-                        EQUAL ( name, oFC.imagepyramid_maxwidth_field ) ||
-                        EQUAL ( name, oFC.imagepyramid_maxheight_field ) ) {
-
+            else if( EQUAL( name, oFC.drawOrderfield ) ||
+                     EQUAL( name, oFC.networklink_refreshvisibility_field ) ||
+                     EQUAL( name, oFC.networklink_flytoview_field ) ||
+                     EQUAL( name, oFC.networklink_refreshInterval_field ) ||
+                     EQUAL( name, oFC.networklink_viewRefreshMode_field ) ||
+                     EQUAL( name, oFC.networklink_viewRefreshTime_field ) ||
+                     EQUAL( name, oFC.imagepyramid_tilesize_field ) ||
+                     EQUAL( name, oFC.imagepyramid_maxwidth_field ) ||
+                     EQUAL( name, oFC.imagepyramid_maxheight_field ) )
+            {
                 continue;
             }
 
             /***** other *****/
-
             if( bUseSimpleField )
             {
-                poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-                poKmlSimpleData->set_name ( name );
-                poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
+                poKmlSimpleData = poKmlFactory->CreateSimpleData();
+                poKmlSimpleData->set_name( name );
+                poKmlSimpleData->set_text( poOgrFeat->GetFieldAsString( i ) );
             }
             else
             {
-                poKmlData = poKmlFactory->CreateData (  );
-                poKmlData->set_name ( name );
-                poKmlData->set_value ( poOgrFeat->GetFieldAsString ( i ) );
+                poKmlData = poKmlFactory->CreateData();
+                poKmlData->set_name( name );
+                poKmlData->set_value( poOgrFeat->GetFieldAsString( i ) );
             }
 
             break;
@@ -787,19 +779,19 @@ void field2kml (
                 continue;
             }
 
-            char* pszStr = CPLStrdup( poOgrFeat->GetFieldAsString ( i ) );
+            char* pszStr = CPLStrdup( poOgrFeat->GetFieldAsString( i ) );
 
             if( bUseSimpleField )
             {
-                poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-                poKmlSimpleData->set_name ( name );
-                poKmlSimpleData->set_text ( pszStr );
+                poKmlSimpleData = poKmlFactory->CreateSimpleData();
+                poKmlSimpleData->set_name( name );
+                poKmlSimpleData->set_text( pszStr );
             }
             else
             {
-                poKmlData = poKmlFactory->CreateData (  );
-                poKmlData->set_name ( name );
-                poKmlData->set_value ( pszStr );
+                poKmlData = poKmlFactory->CreateData();
+                poKmlData->set_name( name );
+                poKmlData->set_value( pszStr );
             }
 
             CPLFree(pszStr);
@@ -818,15 +810,15 @@ void field2kml (
 
             if( bUseSimpleField )
             {
-                poKmlSimpleData = poKmlFactory->CreateSimpleData (  );
-                poKmlSimpleData->set_name ( name );
-                poKmlSimpleData->set_text ( poOgrFeat->GetFieldAsString ( i ) );
+                poKmlSimpleData = poKmlFactory->CreateSimpleData();
+                poKmlSimpleData->set_name( name );
+                poKmlSimpleData->set_text( poOgrFeat->GetFieldAsString( i ) );
             }
             else
             {
-                poKmlData = poKmlFactory->CreateData (  );
-                poKmlData->set_name ( name );
-                poKmlData->set_value ( poOgrFeat->GetFieldAsString ( i ) );
+                poKmlData = poKmlFactory->CreateData();
+                poKmlData->set_name( name );
+                poKmlData->set_value( poOgrFeat->GetFieldAsString( i ) );
             }
 
             break;
@@ -834,287 +826,291 @@ void field2kml (
 
         if( poKmlSimpleData )
         {
-            poKmlSchemaData->add_simpledata ( poKmlSimpleData );
+            poKmlSchemaData->add_simpledata( poKmlSimpleData );
         }
         else if( poKmlData )
         {
             if( poKmlExtendedData == NULL )
-                poKmlExtendedData = poKmlFactory->CreateExtendedData (  );
-            poKmlExtendedData->add_data ( poKmlData );
+                poKmlExtendedData = poKmlFactory->CreateExtendedData();
+            poKmlExtendedData->add_data( poKmlData );
         }
     }
 
     // Do not add it to the placemark unless there is data.
-
-    if ( bUseSimpleField && poKmlSchemaData->get_simpledata_array_size (  ) > 0 ) {
-        poKmlExtendedData = poKmlFactory->CreateExtendedData (  );
-        poKmlExtendedData->add_schemadata ( poKmlSchemaData );
+    if( bUseSimpleField && poKmlSchemaData->get_simpledata_array_size() > 0 )
+    {
+        poKmlExtendedData = poKmlFactory->CreateExtendedData();
+        poKmlExtendedData->add_schemadata( poKmlSchemaData );
     }
     if( poKmlExtendedData != NULL )
     {
-        poKmlFeature->set_extendeddata ( poKmlExtendedData );
+        poKmlFeature->set_extendeddata( poKmlExtendedData );
     }
-
-    return;
 }
 
 /******************************************************************************
- recursive function to read altitude mode from the geometry
+ Recursive function to read altitude mode from the geometry.
 ******************************************************************************/
 
-static int kml2altitudemode_rec (
+static bool kml2altitudemode_rec(
     GeometryPtr poKmlGeometry,
     int *pnAltitudeMode,
     int *pbIsGX )
 {
-
-    PointPtr poKmlPoint;
-    LineStringPtr poKmlLineString;
-    PolygonPtr poKmlPolygon;
-    MultiGeometryPtr poKmlMultiGeometry;
-
-    size_t nGeom;
-    size_t i;
-
-    switch ( poKmlGeometry->Type (  ) ) {
-
+    switch( poKmlGeometry->Type() )
+    {
     case kmldom::Type_Point:
-        poKmlPoint = AsPoint ( poKmlGeometry );
+    {
+        PointPtr poKmlPoint = AsPoint( poKmlGeometry );
 
-        if ( poKmlPoint->has_altitudemode (  ) ) {
-            *pnAltitudeMode = poKmlPoint->get_altitudemode (  );
-            return TRUE;
+        if( poKmlPoint->has_altitudemode() )
+        {
+            *pnAltitudeMode = poKmlPoint->get_altitudemode();
+            return true;
         }
-        else if ( poKmlPoint->has_gx_altitudemode (  ) ) {
-            *pnAltitudeMode = poKmlPoint->get_gx_altitudemode (  );
-            *pbIsGX = TRUE;
-            return TRUE;
+        else if( poKmlPoint->has_gx_altitudemode() )
+        {
+            *pnAltitudeMode = poKmlPoint->get_gx_altitudemode();
+            *pbIsGX = true;
+            return true;
         }
 
         break;
-
+    }
     case kmldom::Type_LineString:
-        poKmlLineString = AsLineString ( poKmlGeometry );
+    {
+        LineStringPtr poKmlLineString = AsLineString( poKmlGeometry );
 
-        if ( poKmlLineString->has_altitudemode (  ) ) {
-            *pnAltitudeMode = poKmlLineString->get_altitudemode (  );
-            return TRUE;
+        if( poKmlLineString->has_altitudemode() )
+        {
+            *pnAltitudeMode = poKmlLineString->get_altitudemode();
+            return true;
         }
-        else if ( poKmlLineString->has_gx_altitudemode (  ) ) {
-            *pnAltitudeMode = poKmlLineString->get_gx_altitudemode (  );
-            *pbIsGX = TRUE;
-            return TRUE;
+        else if( poKmlLineString->has_gx_altitudemode() )
+        {
+            *pnAltitudeMode = poKmlLineString->get_gx_altitudemode();
+            *pbIsGX = true;
+            return true;
         }
         break;
-
+    }
     case kmldom::Type_LinearRing:
+    {
         break;
-
+    }
     case kmldom::Type_Polygon:
-        poKmlPolygon = AsPolygon ( poKmlGeometry );
+    {
+        PolygonPtr poKmlPolygon = AsPolygon( poKmlGeometry );
 
-        if ( poKmlPolygon->has_altitudemode (  ) ) {
-            *pnAltitudeMode = poKmlPolygon->get_altitudemode (  );
-            return TRUE;
+        if( poKmlPolygon->has_altitudemode() )
+        {
+            *pnAltitudeMode = poKmlPolygon->get_altitudemode();
+            return true;
         }
-        else if ( poKmlPolygon->has_gx_altitudemode (  ) ) {
-            *pnAltitudeMode = poKmlPolygon->get_gx_altitudemode (  );
-            *pbIsGX = TRUE;
-            return TRUE;
+        else if( poKmlPolygon->has_gx_altitudemode() )
+        {
+            *pnAltitudeMode = poKmlPolygon->get_gx_altitudemode();
+            *pbIsGX = true;
+            return true;
         }
 
         break;
-
+    }
     case kmldom::Type_MultiGeometry:
-        poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
-
-        nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
-        for ( i = 0; i < nGeom; i++ ) {
-            if ( kml2altitudemode_rec ( poKmlMultiGeometry->
-                                        get_geometry_array_at ( i ),
-                                        pnAltitudeMode, pbIsGX ) )
-                return TRUE;
+    {
+        MultiGeometryPtr poKmlMultiGeometry = AsMultiGeometry( poKmlGeometry );
+
+        const size_t nGeom = poKmlMultiGeometry->get_geometry_array_size();
+        for( size_t i = 0; i < nGeom; i++ )
+        {
+            if( kml2altitudemode_rec( poKmlMultiGeometry->
+                                      get_geometry_array_at( i ),
+                                      pnAltitudeMode, pbIsGX ) )
+                return true;
         }
 
         break;
-
+    }
     default:
+    {
         break;
+    }
 
     }
 
-    return FALSE;
+    return false;
 }
 
 /******************************************************************************
- recursive function to read extrude from the geometry
+ Recursive function to read extrude from the geometry.
 ******************************************************************************/
 
-static int kml2extrude_rec (
-    GeometryPtr poKmlGeometry,
-    bool *pbExtrude )
+static bool kml2extrude_rec( GeometryPtr poKmlGeometry, bool *pbExtrude )
 {
-
-    PointPtr poKmlPoint;
-    LineStringPtr poKmlLineString;
-    PolygonPtr poKmlPolygon;
-    MultiGeometryPtr poKmlMultiGeometry;
-
-    size_t nGeom;
-    size_t i;
-
-    switch ( poKmlGeometry->Type (  ) ) {
-
+    switch( poKmlGeometry->Type() )
+    {
     case kmldom::Type_Point:
-        poKmlPoint = AsPoint ( poKmlGeometry );
+    {
+        PointPtr poKmlPoint = AsPoint( poKmlGeometry );
 
-        if ( poKmlPoint->has_extrude (  ) ) {
-            *pbExtrude = poKmlPoint->get_extrude (  );
-            return TRUE;
+        if( poKmlPoint->has_extrude() )
+        {
+            *pbExtrude = poKmlPoint->get_extrude();
+            return true;
         }
 
         break;
-
+    }
     case kmldom::Type_LineString:
-        poKmlLineString = AsLineString ( poKmlGeometry );
+    {
+        LineStringPtr poKmlLineString = AsLineString( poKmlGeometry );
 
-        if ( poKmlLineString->has_extrude (  ) ) {
-            *pbExtrude = poKmlLineString->get_extrude (  );
-            return TRUE;
+        if( poKmlLineString->has_extrude() )
+        {
+            *pbExtrude = poKmlLineString->get_extrude();
+            return true;
         }
 
         break;
-
+    }
     case kmldom::Type_LinearRing:
+    {
         break;
-
+    }
     case kmldom::Type_Polygon:
-        poKmlPolygon = AsPolygon ( poKmlGeometry );
+    {
+        PolygonPtr poKmlPolygon = AsPolygon( poKmlGeometry );
 
-        if ( poKmlPolygon->has_extrude (  ) ) {
-            *pbExtrude = poKmlPolygon->get_extrude (  );
-            return TRUE;
+        if( poKmlPolygon->has_extrude() )
+        {
+            *pbExtrude = poKmlPolygon->get_extrude();
+            return true;
         }
 
         break;
-
+    }
     case kmldom::Type_MultiGeometry:
-        poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
+    {
+        MultiGeometryPtr poKmlMultiGeometry = AsMultiGeometry( poKmlGeometry );
 
-        nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
-        for ( i = 0; i < nGeom; i++ ) {
-            if ( kml2extrude_rec ( poKmlMultiGeometry->
-                                   get_geometry_array_at ( i ), pbExtrude ) )
-                return TRUE;
+        const size_t nGeom = poKmlMultiGeometry->get_geometry_array_size();
+        for( size_t i = 0; i < nGeom; i++ )
+        {
+            if( kml2extrude_rec( poKmlMultiGeometry->
+                                 get_geometry_array_at( i ), pbExtrude ) )
+                return true;
         }
 
         break;
-
+    }
     default:
+    {
         break;
-
+    }
     }
 
-    return FALSE;
+    return false;
 }
 
 /******************************************************************************
- recursive function to read tessellate from the geometry
+ Recursive function to read tessellate from the geometry.
 ******************************************************************************/
 
-static int kml2tessellate_rec (
+static bool kml2tessellate_rec(
     GeometryPtr poKmlGeometry,
     int *pnTessellate )
 {
-
-    LineStringPtr poKmlLineString;
-    PolygonPtr poKmlPolygon;
-    MultiGeometryPtr poKmlMultiGeometry;
-
-    size_t nGeom;
-    size_t i;
-
-    switch ( poKmlGeometry->Type (  ) ) {
-
+    switch( poKmlGeometry->Type() )
+    {
     case kmldom::Type_Point:
+    {
         break;
-
+    }
     case kmldom::Type_LineString:
-        poKmlLineString = AsLineString ( poKmlGeometry );
+    {
+        LineStringPtr poKmlLineString = AsLineString( poKmlGeometry );
 
-        if ( poKmlLineString->has_tessellate (  ) ) {
-            *pnTessellate = poKmlLineString->get_tessellate (  );
-            return TRUE;
+        if( poKmlLineString->has_tessellate() )
+        {
+            *pnTessellate = poKmlLineString->get_tessellate();
+            return true;
         }
 
         break;
-
+    }
     case kmldom::Type_LinearRing:
+    {
         break;
-
+    }
     case kmldom::Type_Polygon:
-        poKmlPolygon = AsPolygon ( poKmlGeometry );
+    {
+        PolygonPtr poKmlPolygon = AsPolygon( poKmlGeometry );
 
-        if ( poKmlPolygon->has_tessellate (  ) ) {
-            *pnTessellate = poKmlPolygon->get_tessellate (  );
-            return TRUE;
+        if( poKmlPolygon->has_tessellate() )
+        {
+            *pnTessellate = poKmlPolygon->get_tessellate();
+            return true;
         }
 
         break;
-
+    }
     case kmldom::Type_MultiGeometry:
-        poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
-
-        nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
-        for ( i = 0; i < nGeom; i++ ) {
-            if ( kml2tessellate_rec ( poKmlMultiGeometry->
-                                      get_geometry_array_at ( i ),
-                                      pnTessellate ) )
-                return TRUE;
+    {
+        MultiGeometryPtr poKmlMultiGeometry = AsMultiGeometry( poKmlGeometry );
+
+        const size_t nGeom = poKmlMultiGeometry->get_geometry_array_size();
+        for( size_t i = 0; i < nGeom; i++ )
+        {
+            if( kml2tessellate_rec( poKmlMultiGeometry->
+                                    get_geometry_array_at( i ),
+                                    pnTessellate ) )
+                return true;
         }
 
         break;
-
+    }
     default:
         break;
 
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                     ogrkmlSetAltitudeMode()                          */
 /************************************************************************/
 
-static void ogrkmlSetAltitudeMode(OGRFeature* poOgrFeat, int iField,
-                                  int nAltitudeMode, int bIsGX)
+static void ogrkmlSetAltitudeMode( OGRFeature* poOgrFeat, int iField,
+                                   int nAltitudeMode, bool bIsGX )
 {
-    if ( !bIsGX ) {
-        switch ( nAltitudeMode ) {
+    if( !bIsGX )
+    {
+        switch( nAltitudeMode )
+        {
         case kmldom::ALTITUDEMODE_CLAMPTOGROUND:
-            poOgrFeat->SetField ( iField, "clampToGround" );
+            poOgrFeat->SetField( iField, "clampToGround" );
             break;
 
         case kmldom::ALTITUDEMODE_RELATIVETOGROUND:
-            poOgrFeat->SetField ( iField, "relativeToGround" );
+            poOgrFeat->SetField( iField, "relativeToGround" );
             break;
 
         case kmldom::ALTITUDEMODE_ABSOLUTE:
-            poOgrFeat->SetField ( iField, "absolute" );
+            poOgrFeat->SetField( iField, "absolute" );
             break;
-
         }
     }
-
-    else {
-        switch ( nAltitudeMode ) {
+    else
+    {
+        switch( nAltitudeMode )
+        {
         case kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR:
-            poOgrFeat->SetField ( iField, "relativeToSeaFloor" );
+            poOgrFeat->SetField( iField, "relativeToSeaFloor" );
             break;
 
         case kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR:
-            poOgrFeat->SetField ( iField, "clampToSeaFloor" );
+            poOgrFeat->SetField( iField, "clampToSeaFloor" );
             break;
         }
     }
@@ -1124,22 +1120,21 @@ static void ogrkmlSetAltitudeMode(OGRFeature* poOgrFeat, int iField,
 /*                            TrimSpaces()                              */
 /************************************************************************/
 
-static const char* TrimSpaces(string& oText)
+static const char* TrimSpaces( CPLString& oText )
 {
+    // SerializePretty() adds a new line before the data
+    // ands trailing spaces. I believe this is wrong
+    // as it breaks round-tripping.
 
-    /* SerializePretty() adds a new line before the data */
-    /* ands trailing spaces. I believe this is wrong */
-    /* as it breaks round-tripping */
-
-    /* Trim trailing spaces */
-    while (oText.size() != 0 && oText[oText.size()-1] == ' ')
+    // Trim trailing spaces.
+    while( !oText.empty() && oText.back() == ' ' )
         oText.resize(oText.size()-1);
 
-    /* Skip leading newline and spaces */
-    const char* pszText = oText.c_str (  );
-    if (pszText[0] == '\n')
+    // Skip leading newline and spaces.
+    const char* pszText = oText.c_str();
+    if( pszText[0] == '\n' )
         pszText ++;
-    while (pszText[0] == ' ')
+    while( pszText[0] == ' ' )
         pszText ++;
 
     return pszText;
@@ -1153,13 +1148,14 @@ static void kmldatetime2ogr( OGRFeature* poOgrFeat,
                              const char* pszOGRField,
                              const std::string& osKmlDateTime )
 {
-    int iField = poOgrFeat->GetFieldIndex ( pszOGRField );
+    const int iField = poOgrFeat->GetFieldIndex( pszOGRField );
 
-    if ( iField > -1 ) {
+    if( iField > -1 )
+    {
         OGRField sField;
 
-        if ( OGRParseXMLDateTime( osKmlDateTime.c_str (  ), &sField ) )
-            poOgrFeat->SetField ( iField, &sField );
+        if( OGRParseXMLDateTime( osKmlDateTime.c_str(), &sField ) )
+            poOgrFeat->SetField( iField, &sField );
     }
 }
 
@@ -1167,11 +1163,8 @@ static void kmldatetime2ogr( OGRFeature* poOgrFeat,
  function to read kml into ogr fields
 ******************************************************************************/
 
-void kml2field (
-    OGRFeature * poOgrFeat,
-    FeaturePtr poKmlFeature )
+void kml2field( OGRFeature * poOgrFeat, FeaturePtr poKmlFeature )
 {
-
     /***** get the field config *****/
 
     struct fieldconfig oFC;
@@ -1179,147 +1172,157 @@ void kml2field (
 
     /***** name *****/
 
-    if ( poKmlFeature->has_name (  ) ) {
-        const std::string oKmlName = poKmlFeature->get_name (  );
-        int iField = poOgrFeat->GetFieldIndex ( oFC.namefield );
+    if( poKmlFeature->has_name() )
+    {
+        const std::string oKmlName = poKmlFeature->get_name();
+        int iField = poOgrFeat->GetFieldIndex( oFC.namefield );
 
-        if ( iField > -1 )
-            poOgrFeat->SetField ( iField, oKmlName.c_str (  ) );
+        if( iField > -1 )
+            poOgrFeat->SetField( iField, oKmlName.c_str() );
     }
 
     /***** description *****/
 
-    if ( poKmlFeature->has_description (  ) ) {
-        const std::string oKmlDesc = poKmlFeature->get_description (  );
-        int iField = poOgrFeat->GetFieldIndex ( oFC.descfield );
+    if( poKmlFeature->has_description() )
+    {
+        const std::string oKmlDesc = poKmlFeature->get_description();
+        int iField = poOgrFeat->GetFieldIndex( oFC.descfield );
 
-        if ( iField > -1 )
-            poOgrFeat->SetField ( iField, oKmlDesc.c_str (  ) );
+        if( iField > -1 )
+            poOgrFeat->SetField( iField, oKmlDesc.c_str() );
     }
 
-    if ( poKmlFeature->has_timeprimitive (  ) ) {
+    if( poKmlFeature->has_timeprimitive() )
+    {
         TimePrimitivePtr poKmlTimePrimitive =
-            poKmlFeature->get_timeprimitive (  );
+            poKmlFeature->get_timeprimitive();
 
         /***** timestamp *****/
 
-        if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeStamp ) ) {
-            // probably a libkml bug: AsTimeStamp should really return not NULL on a gx:TimeStamp
-            TimeStampPtr poKmlTimeStamp = AsTimeStamp ( poKmlTimePrimitive );
+        if( poKmlTimePrimitive->IsA( kmldom::Type_TimeStamp ) )
+        {
+            // Probably a libkml bug: AsTimeStamp should really return not NULL
+            // on a gx:TimeStamp.
+            TimeStampPtr poKmlTimeStamp = AsTimeStamp( poKmlTimePrimitive );
             if( poKmlTimeStamp == NULL )
-                poKmlTimeStamp = AsGxTimeStamp ( poKmlTimePrimitive );
+                poKmlTimeStamp = AsGxTimeStamp( poKmlTimePrimitive );
 
-            if ( poKmlTimeStamp && poKmlTimeStamp->has_when (  ) ) {
-                const std::string oKmlWhen = poKmlTimeStamp->get_when (  );
+            if( poKmlTimeStamp && poKmlTimeStamp->has_when() )
+            {
+                const std::string oKmlWhen = poKmlTimeStamp->get_when();
                 kmldatetime2ogr(poOgrFeat, oFC.tsfield, oKmlWhen );
             }
         }
 
         /***** timespan *****/
 
-        if ( poKmlTimePrimitive->IsA ( kmldom::Type_TimeSpan ) ) {
-            // probably a libkml bug: AsTimeSpan should really return not NULL on a gx:TimeSpan
-            TimeSpanPtr poKmlTimeSpan = AsTimeSpan ( poKmlTimePrimitive );
+        if( poKmlTimePrimitive->IsA( kmldom::Type_TimeSpan ) )
+        {
+            // Probably a libkml bug: AsTimeSpan should really return not NULL
+            // on a gx:TimeSpan.
+            TimeSpanPtr poKmlTimeSpan = AsTimeSpan( poKmlTimePrimitive );
             if( poKmlTimeSpan == NULL )
-                poKmlTimeSpan = AsGxTimeSpan ( poKmlTimePrimitive );
+                poKmlTimeSpan = AsGxTimeSpan( poKmlTimePrimitive );
 
             /***** begin *****/
 
-            if ( poKmlTimeSpan && poKmlTimeSpan->has_begin (  ) ) {
-                const std::string oKmlWhen = poKmlTimeSpan->get_begin (  );
+            if( poKmlTimeSpan && poKmlTimeSpan->has_begin() )
+            {
+                const std::string oKmlWhen = poKmlTimeSpan->get_begin();
                 kmldatetime2ogr(poOgrFeat, oFC.beginfield, oKmlWhen );
             }
 
             /***** end *****/
 
-            if ( poKmlTimeSpan && poKmlTimeSpan->has_end (  ) ) {
-                const std::string oKmlWhen = poKmlTimeSpan->get_end (  );
+            if( poKmlTimeSpan && poKmlTimeSpan->has_end() )
+            {
+                const std::string oKmlWhen = poKmlTimeSpan->get_end();
                 kmldatetime2ogr(poOgrFeat, oFC.endfield, oKmlWhen );
             }
         }
     }
 
     /***** placemark *****/
-
-    PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
-    GroundOverlayPtr poKmlGroundOverlay = AsGroundOverlay ( poKmlFeature );
-    if ( poKmlPlacemark && poKmlPlacemark->has_geometry (  ) ) {
-        GeometryPtr poKmlGeometry = poKmlPlacemark->get_geometry (  );
+    PlacemarkPtr poKmlPlacemark = AsPlacemark( poKmlFeature );
+    GroundOverlayPtr poKmlGroundOverlay = AsGroundOverlay( poKmlFeature );
+    if( poKmlPlacemark && poKmlPlacemark->has_geometry() )
+    {
+        GeometryPtr poKmlGeometry = poKmlPlacemark->get_geometry();
 
         /***** altitudeMode *****/
-
-
-        int bIsGX = FALSE;
+        int bIsGX = false;
         int nAltitudeMode = -1;
 
-        int iField = poOgrFeat->GetFieldIndex ( oFC.altitudeModefield );
+        int iField = poOgrFeat->GetFieldIndex( oFC.altitudeModefield );
 
-        if ( iField > -1 ) {
-
-            if ( kml2altitudemode_rec ( poKmlGeometry,
-                                        &nAltitudeMode, &bIsGX ) ) {
-                ogrkmlSetAltitudeMode(poOgrFeat, iField, nAltitudeMode, bIsGX);
+        if( iField > -1 )
+        {
+            if( kml2altitudemode_rec( poKmlGeometry,
+                                      &nAltitudeMode, &bIsGX ) )
+            {
+                ogrkmlSetAltitudeMode(poOgrFeat, iField, nAltitudeMode,
+                                      CPL_TO_BOOL(bIsGX));
             }
-
         }
 
         /***** tessellate *****/
-
         int nTessellate = -1;
 
-        kml2tessellate_rec ( poKmlGeometry, &nTessellate );
+        kml2tessellate_rec( poKmlGeometry, &nTessellate );
 
-        iField = poOgrFeat->GetFieldIndex ( oFC.tessellatefield );
-        if ( iField > -1 )
-            poOgrFeat->SetField ( iField, nTessellate );
+        iField = poOgrFeat->GetFieldIndex( oFC.tessellatefield );
+        if( iField > -1 )
+            poOgrFeat->SetField( iField, nTessellate );
 
         /***** extrude *****/
 
         bool bExtrude = false;
 
-        kml2extrude_rec ( poKmlGeometry, &bExtrude );
+        kml2extrude_rec( poKmlGeometry, &bExtrude );
 
-        iField = poOgrFeat->GetFieldIndex ( oFC.extrudefield );
-        if ( iField > -1 )
-            poOgrFeat->SetField ( iField, bExtrude ? 1 : 0 );
+        iField = poOgrFeat->GetFieldIndex( oFC.extrudefield );
+        if( iField > -1 )
+            poOgrFeat->SetField( iField, bExtrude ? 1 : 0 );
 
         /***** special case for gx:Track ******/
         /* we set the first timestamp as begin and the last one as end */
-        if ( poKmlGeometry->Type (  )  == kmldom::Type_GxTrack &&
-             !poKmlFeature->has_timeprimitive (  ) ) {
-            GxTrackPtr poKmlGxTrack = AsGxTrack ( poKmlGeometry );
+        if( poKmlGeometry->Type()  == kmldom::Type_GxTrack &&
+            !poKmlFeature->has_timeprimitive() )
+        {
+            GxTrackPtr poKmlGxTrack = AsGxTrack( poKmlGeometry );
             size_t nCoords = poKmlGxTrack->get_gx_coord_array_size();
             if( nCoords > 0 )
             {
                 kmldatetime2ogr(poOgrFeat, oFC.beginfield,
-                            poKmlGxTrack->get_when_array_at ( 0 ).c_str() );
+                            poKmlGxTrack->get_when_array_at( 0 ).c_str() );
                 kmldatetime2ogr(poOgrFeat, oFC.endfield,
-                            poKmlGxTrack->get_when_array_at ( nCoords - 1 ).c_str() );
+                            poKmlGxTrack->get_when_array_at( nCoords - 1 ).c_str() );
             }
         }
 
         /***** special case for gx:MultiTrack ******/
         /* we set the first timestamp as begin and the last one as end */
-        else if ( poKmlGeometry->Type (  )  == kmldom::Type_GxMultiTrack &&
-             !poKmlFeature->has_timeprimitive (  ) ) {
-            GxMultiTrackPtr poKmlGxMultiTrack = AsGxMultiTrack ( poKmlGeometry );
-            size_t nGeom = poKmlGxMultiTrack->get_gx_track_array_size (  );
+        else if( poKmlGeometry->Type()  == kmldom::Type_GxMultiTrack &&
+             !poKmlFeature->has_timeprimitive() )
+        {
+            GxMultiTrackPtr poKmlGxMultiTrack = AsGxMultiTrack( poKmlGeometry );
+            size_t nGeom = poKmlGxMultiTrack->get_gx_track_array_size();
             if( nGeom >= 1 )
             {
-                GxTrackPtr poKmlGxTrack = poKmlGxMultiTrack->get_gx_track_array_at ( 0 );
+                GxTrackPtr poKmlGxTrack = poKmlGxMultiTrack->get_gx_track_array_at( 0 );
                 size_t nCoords = poKmlGxTrack->get_gx_coord_array_size();
                 if( nCoords > 0 )
                 {
                     kmldatetime2ogr(poOgrFeat, oFC.beginfield,
-                                poKmlGxTrack->get_when_array_at ( 0 ).c_str() );
+                                poKmlGxTrack->get_when_array_at( 0 ).c_str() );
                 }
 
-                poKmlGxTrack = poKmlGxMultiTrack->get_gx_track_array_at (nGeom -1);
+                poKmlGxTrack = poKmlGxMultiTrack->get_gx_track_array_at(nGeom -1);
                 nCoords = poKmlGxTrack->get_gx_coord_array_size();
                 if( nCoords > 0 )
                 {
                     kmldatetime2ogr(poOgrFeat, oFC.endfield,
-                                poKmlGxTrack->get_when_array_at ( nCoords - 1 ).c_str() );
+                                poKmlGxTrack->get_when_array_at( nCoords - 1 ).c_str() );
                 }
             }
         }
@@ -1327,294 +1330,297 @@ void kml2field (
 
     /***** camera *****/
 
-    else if ( poKmlPlacemark &&
-              poKmlPlacemark->has_abstractview (  ) &&
-              poKmlPlacemark->get_abstractview()->IsA( kmldom::Type_Camera) ) {
-
+    else if( poKmlPlacemark &&
+             poKmlPlacemark->has_abstractview() &&
+             poKmlPlacemark->get_abstractview()->IsA( kmldom::Type_Camera) )
+    {
         const CameraPtr& camera = AsCamera(poKmlPlacemark->get_abstractview());
 
         if( camera->has_heading() )
         {
-            int iField = poOgrFeat->GetFieldIndex ( oFC.headingfield );
-            if ( iField > -1 )
-                poOgrFeat->SetField ( iField, camera->get_heading() );
+            int iField = poOgrFeat->GetFieldIndex( oFC.headingfield );
+            if( iField > -1 )
+                poOgrFeat->SetField( iField, camera->get_heading() );
         }
 
         if( camera->has_tilt() )
         {
-            int iField = poOgrFeat->GetFieldIndex ( oFC.tiltfield );
-            if ( iField > -1 )
-                poOgrFeat->SetField ( iField, camera->get_tilt() );
+            int iField = poOgrFeat->GetFieldIndex( oFC.tiltfield );
+            if( iField > -1 )
+                poOgrFeat->SetField( iField, camera->get_tilt() );
         }
 
         if( camera->has_roll() )
         {
-            int iField = poOgrFeat->GetFieldIndex ( oFC.rollfield );
-            if ( iField > -1 )
-                poOgrFeat->SetField ( iField, camera->get_roll() );
+            int iField = poOgrFeat->GetFieldIndex( oFC.rollfield );
+            if( iField > -1 )
+                poOgrFeat->SetField( iField, camera->get_roll() );
         }
 
         int nAltitudeMode = -1;
 
-        int iField = poOgrFeat->GetFieldIndex ( oFC.altitudeModefield );
+        int iField = poOgrFeat->GetFieldIndex( oFC.altitudeModefield );
 
-        if ( iField > -1 ) {
-
-            if ( camera->has_altitudemode (  ) ) {
-                nAltitudeMode = camera->get_altitudemode (  );
-                ogrkmlSetAltitudeMode(poOgrFeat, iField, nAltitudeMode, FALSE);
+        if( iField > -1 )
+        {
+            if( camera->has_altitudemode() )
+            {
+                nAltitudeMode = camera->get_altitudemode();
+                ogrkmlSetAltitudeMode(poOgrFeat, iField, nAltitudeMode, false);
             }
-            else if ( camera->has_gx_altitudemode (  ) ) {
-                nAltitudeMode = camera->get_gx_altitudemode (  );
-                ogrkmlSetAltitudeMode(poOgrFeat, iField, nAltitudeMode, TRUE);
+            else if( camera->has_gx_altitudemode() )
+            {
+                nAltitudeMode = camera->get_gx_altitudemode();
+                ogrkmlSetAltitudeMode(poOgrFeat, iField, nAltitudeMode, true);
             }
         }
     }
-
     /***** ground overlay *****/
-
-    else if ( poKmlGroundOverlay ) {
-
+    else if( poKmlGroundOverlay )
+    {
         /***** icon *****/
-
-        int iField = poOgrFeat->GetFieldIndex ( oFC.iconfield );
-        if ( iField > -1 ) {
-
-            if ( poKmlGroundOverlay->has_icon (  ) ) {
-                IconPtr icon = poKmlGroundOverlay->get_icon (  );
-                if ( icon->has_href (  ) ) {
-                    poOgrFeat->SetField ( iField, icon->get_href (  ).c_str (  ) );
+        int iField = poOgrFeat->GetFieldIndex( oFC.iconfield );
+        if( iField > -1 )
+        {
+            if( poKmlGroundOverlay->has_icon() )
+            {
+                IconPtr icon = poKmlGroundOverlay->get_icon();
+                if( icon->has_href() )
+                {
+                    poOgrFeat->SetField( iField, icon->get_href().c_str() );
                 }
             }
         }
 
         /***** drawOrder *****/
-
-
-        iField = poOgrFeat->GetFieldIndex ( oFC.drawOrderfield );
-        if ( iField > -1 ) {
-
-            if ( poKmlGroundOverlay->has_draworder (  ) ) {
-                poOgrFeat->SetField ( iField, poKmlGroundOverlay->get_draworder (  ) );
+        iField = poOgrFeat->GetFieldIndex( oFC.drawOrderfield );
+        if( iField > -1 )
+        {
+            if( poKmlGroundOverlay->has_draworder() )
+            {
+                poOgrFeat->SetField( iField,
+                                     poKmlGroundOverlay->get_draworder() );
             }
         }
 
         /***** altitudeMode *****/
 
-        iField = poOgrFeat->GetFieldIndex ( oFC.altitudeModefield );
-
-        if ( iField > -1 ) {
+        iField = poOgrFeat->GetFieldIndex( oFC.altitudeModefield );
 
-            if ( poKmlGroundOverlay->has_altitudemode (  ) ) {
-                switch ( poKmlGroundOverlay->get_altitudemode (  ) ) {
+        if( iField > -1 )
+        {
+            if( poKmlGroundOverlay->has_altitudemode() )
+            {
+                switch( poKmlGroundOverlay->get_altitudemode() )
+                {
                 case kmldom::ALTITUDEMODE_CLAMPTOGROUND:
-                    poOgrFeat->SetField ( iField, "clampToGround" );
+                    poOgrFeat->SetField( iField, "clampToGround" );
                     break;
 
                 case kmldom::ALTITUDEMODE_RELATIVETOGROUND:
-                    poOgrFeat->SetField ( iField, "relativeToGround" );
+                    poOgrFeat->SetField( iField, "relativeToGround" );
                     break;
 
                 case kmldom::ALTITUDEMODE_ABSOLUTE:
-                    poOgrFeat->SetField ( iField, "absolute" );
+                    poOgrFeat->SetField( iField, "absolute" );
                     break;
-
                 }
-            } else if ( poKmlGroundOverlay->has_gx_altitudemode (  ) ) {
-                switch ( poKmlGroundOverlay->get_gx_altitudemode ( ) ) {
+            } else if( poKmlGroundOverlay->has_gx_altitudemode() )
+            {
+                switch( poKmlGroundOverlay->get_gx_altitudemode() )
+                {
                 case kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR:
-                    poOgrFeat->SetField ( iField, "relativeToSeaFloor" );
+                    poOgrFeat->SetField( iField, "relativeToSeaFloor" );
                     break;
 
                 case kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR:
-                    poOgrFeat->SetField ( iField, "clampToSeaFloor" );
+                    poOgrFeat->SetField( iField, "clampToSeaFloor" );
                     break;
                 }
             }
-
         }
     }
 
     /***** visibility *****/
+    const int nVisibility = poKmlFeature->has_visibility() ?
+        poKmlFeature->get_visibility() : -1;
 
-    int nVisibility = -1;
-
-    if ( poKmlFeature->has_visibility (  ) )
-        nVisibility = poKmlFeature->get_visibility (  );
-
-    int iField = poOgrFeat->GetFieldIndex ( oFC.visibilityfield );
+    int iField = poOgrFeat->GetFieldIndex( oFC.visibilityfield );
 
-    if ( iField > -1 )
-        poOgrFeat->SetField ( iField, nVisibility );
+    if( iField > -1 )
+        poOgrFeat->SetField( iField, nVisibility );
 
     /***** snippet *****/
 
-    if ( poKmlFeature->has_snippet (  ) )
+    if( poKmlFeature->has_snippet() )
     {
-        string oText = poKmlFeature->get_snippet (  )->get_text();
+        CPLString oText = poKmlFeature->get_snippet()->get_text();
 
-        iField = poOgrFeat->GetFieldIndex ( oFC.snippetfield );
+        iField = poOgrFeat->GetFieldIndex( oFC.snippetfield );
 
-        if ( iField > -1 )
-            poOgrFeat->SetField ( iField, TrimSpaces(oText) );
+        if( iField > -1 )
+            poOgrFeat->SetField( iField, TrimSpaces(oText) );
     }
 
     /***** extended schema *****/
     ExtendedDataPtr poKmlExtendedData = NULL;
 
-    if ( poKmlFeature->has_extendeddata (  ) ) {
-        poKmlExtendedData = poKmlFeature->get_extendeddata (  );
+    if( poKmlFeature->has_extendeddata() )
+    {
+        poKmlExtendedData = poKmlFeature->get_extendeddata();
 
         /***** loop over the schemadata_arrays *****/
 
-        size_t nSchemaData = poKmlExtendedData->get_schemadata_array_size (  );
-
-        size_t iSchemaData;
+        const size_t nSchemaData =
+            poKmlExtendedData->get_schemadata_array_size();
 
-        for ( iSchemaData = 0; iSchemaData < nSchemaData; iSchemaData++ ) {
+        for( size_t iSchemaData = 0; iSchemaData < nSchemaData; iSchemaData++ )
+        {
             SchemaDataPtr poKmlSchemaData =
-                poKmlExtendedData->get_schemadata_array_at ( iSchemaData );
+                poKmlExtendedData->get_schemadata_array_at( iSchemaData );
 
             /***** loop over the simpledata array *****/
 
-            size_t nSimpleData =
-                poKmlSchemaData->get_simpledata_array_size (  );
+            const size_t nSimpleData =
+                poKmlSchemaData->get_simpledata_array_size();
 
-            size_t iSimpleData;
-
-            for ( iSimpleData = 0; iSimpleData < nSimpleData; iSimpleData++ ) {
+            for( size_t iSimpleData = 0;
+                 iSimpleData < nSimpleData;
+                 iSimpleData++ )
+            {
                 SimpleDataPtr poKmlSimpleData =
-                    poKmlSchemaData->get_simpledata_array_at ( iSimpleData );
+                    poKmlSchemaData->get_simpledata_array_at( iSimpleData );
 
                 /***** find the field index *****/
 
                 iField = -1;
 
-                if ( poKmlSimpleData->has_name (  ) ) {
-                    const string oName = poKmlSimpleData->get_name (  );
-                    const char *pszName = oName.c_str (  );
+                if( poKmlSimpleData->has_name() )
+                {
+                    const string oName = poKmlSimpleData->get_name();
+                    const char *pszName = oName.c_str();
 
-                    iField = poOgrFeat->GetFieldIndex ( pszName );
+                    iField = poOgrFeat->GetFieldIndex( pszName );
                 }
 
                 /***** if it has trxt set the field *****/
 
-                if ( iField > -1 && poKmlSimpleData->has_text (  ) ) {
-                    string oText = poKmlSimpleData->get_text (  );
+                if( iField > -1 && poKmlSimpleData->has_text() )
+                {
+                    CPLString oText = poKmlSimpleData->get_text();
 
-                    poOgrFeat->SetField ( iField, TrimSpaces(oText) );
+                    poOgrFeat->SetField( iField, TrimSpaces(oText) );
                 }
             }
         }
 
-        if (nSchemaData == 0 &&  poKmlExtendedData->get_data_array_size() > 0 )
+        if( nSchemaData == 0 &&  poKmlExtendedData->get_data_array_size() > 0 )
         {
-            int bLaunderFieldNames =
-                CPLTestBool(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
-            size_t nDataArraySize = poKmlExtendedData->get_data_array_size();
-            for(size_t i=0; i < nDataArraySize; i++)
+            const bool bLaunderFieldNames =
+                CPLTestBool(
+                    CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
+            const size_t nDataArraySize =
+                poKmlExtendedData->get_data_array_size();
+            for( size_t i = 0; i < nDataArraySize; i++ )
             {
                 const DataPtr& data = poKmlExtendedData->get_data_array_at(i);
-                if (data->has_name() && data->has_value())
+                if( data->has_name() && data->has_value() )
                 {
-                    CPLString osName = data->get_name();
-                    if (bLaunderFieldNames)
+                    CPLString osName = std::string(data->get_name());
+                    if( bLaunderFieldNames )
                         osName = OGRLIBKMLLayer::LaunderFieldNames(osName);
-                    iField = poOgrFeat->GetFieldIndex ( osName );
-                    if (iField >= 0)
+                    iField = poOgrFeat->GetFieldIndex( osName );
+                    if( iField >= 0 )
                     {
-                        poOgrFeat->SetField ( iField, data->get_value().c_str() );
+                        poOgrFeat->SetField( iField,
+                                             data->get_value().c_str() );
                     }
                 }
             }
         }
     }
-
 }
 
 /******************************************************************************
  function create a simplefield from a FieldDefn
 ******************************************************************************/
 
-SimpleFieldPtr FieldDef2kml (
+SimpleFieldPtr FieldDef2kml(
     OGRFieldDefn * poOgrFieldDef,
     KmlFactory * poKmlFactory )
 {
-    /***** get the field config *****/
-
+    /***** Get the field config. *****/
     struct fieldconfig oFC;
     get_fieldconfig( &oFC );
 
-    const char *pszFieldName = poOgrFieldDef->GetNameRef (  );
-
-    if ( EQUAL ( pszFieldName, oFC.namefield ) ||
-         EQUAL ( pszFieldName, oFC.descfield ) ||
-         EQUAL ( pszFieldName, oFC.tsfield ) ||
-         EQUAL ( pszFieldName, oFC.beginfield ) ||
-         EQUAL ( pszFieldName, oFC.endfield ) ||
-         EQUAL ( pszFieldName, oFC.altitudeModefield ) ||
-         EQUAL ( pszFieldName, oFC.tessellatefield ) ||
-         EQUAL ( pszFieldName, oFC.extrudefield ) ||
-         EQUAL ( pszFieldName, oFC.visibilityfield ) ||
-         EQUAL ( pszFieldName, oFC.drawOrderfield ) ||
-         EQUAL ( pszFieldName, oFC.iconfield ) ||
-         EQUAL ( pszFieldName, oFC.headingfield ) ||
-         EQUAL ( pszFieldName, oFC.tiltfield ) ||
-         EQUAL ( pszFieldName, oFC.rollfield ) ||
-         EQUAL ( pszFieldName, oFC.snippetfield ) ||
-         EQUAL ( pszFieldName, oFC.modelfield ) ||
-         EQUAL ( pszFieldName, oFC.scalexfield ) ||
-         EQUAL ( pszFieldName, oFC.scaleyfield ) ||
-         EQUAL ( pszFieldName, oFC.scalezfield ) ||
-         EQUAL ( pszFieldName, oFC.networklinkfield ) ||
-         EQUAL ( pszFieldName, oFC.networklink_refreshvisibility_field ) ||
-         EQUAL ( pszFieldName, oFC.networklink_flytoview_field ) ||
-         EQUAL ( pszFieldName, oFC.networklink_refreshMode_field ) ||
-         EQUAL ( pszFieldName, oFC.networklink_refreshInterval_field ) ||
-         EQUAL ( pszFieldName, oFC.networklink_viewRefreshMode_field ) ||
-         EQUAL ( pszFieldName, oFC.networklink_viewRefreshTime_field ) ||
-         EQUAL ( pszFieldName, oFC.networklink_viewBoundScale_field ) ||
-         EQUAL ( pszFieldName, oFC.networklink_viewFormat_field ) ||
-         EQUAL ( pszFieldName, oFC.networklink_httpQuery_field ) ||
-         EQUAL ( pszFieldName, oFC.camera_longitude_field ) ||
-         EQUAL ( pszFieldName, oFC.camera_latitude_field ) ||
-         EQUAL ( pszFieldName, oFC.camera_altitude_field ) ||
-         EQUAL ( pszFieldName, oFC.camera_altitudemode_field ) ||
-         EQUAL ( pszFieldName, oFC.photooverlayfield ) ||
-         EQUAL ( pszFieldName, oFC.leftfovfield ) ||
-         EQUAL ( pszFieldName, oFC.rightfovfield ) ||
-         EQUAL ( pszFieldName, oFC.bottomfovfield ) ||
-         EQUAL ( pszFieldName, oFC.topfovfield ) ||
-         EQUAL ( pszFieldName, oFC.nearfield ) ||
-         EQUAL ( pszFieldName, oFC.photooverlay_shape_field ) ||
-         EQUAL ( pszFieldName, oFC.imagepyramid_tilesize_field) ||
-         EQUAL ( pszFieldName, oFC.imagepyramid_maxwidth_field) ||
-         EQUAL ( pszFieldName, oFC.imagepyramid_maxheight_field) ||
-         EQUAL ( pszFieldName, oFC.imagepyramid_gridorigin_field) )
+    const char *pszFieldName = poOgrFieldDef->GetNameRef();
+
+    if( EQUAL( pszFieldName, oFC.namefield ) ||
+        EQUAL( pszFieldName, oFC.descfield ) ||
+        EQUAL( pszFieldName, oFC.tsfield ) ||
+        EQUAL( pszFieldName, oFC.beginfield ) ||
+        EQUAL( pszFieldName, oFC.endfield ) ||
+        EQUAL( pszFieldName, oFC.altitudeModefield ) ||
+        EQUAL( pszFieldName, oFC.tessellatefield ) ||
+        EQUAL( pszFieldName, oFC.extrudefield ) ||
+        EQUAL( pszFieldName, oFC.visibilityfield ) ||
+        EQUAL( pszFieldName, oFC.drawOrderfield ) ||
+        EQUAL( pszFieldName, oFC.iconfield ) ||
+        EQUAL( pszFieldName, oFC.headingfield ) ||
+        EQUAL( pszFieldName, oFC.tiltfield ) ||
+        EQUAL( pszFieldName, oFC.rollfield ) ||
+        EQUAL( pszFieldName, oFC.snippetfield ) ||
+        EQUAL( pszFieldName, oFC.modelfield ) ||
+        EQUAL( pszFieldName, oFC.scalexfield ) ||
+        EQUAL( pszFieldName, oFC.scaleyfield ) ||
+        EQUAL( pszFieldName, oFC.scalezfield ) ||
+        EQUAL( pszFieldName, oFC.networklinkfield ) ||
+        EQUAL( pszFieldName, oFC.networklink_refreshvisibility_field ) ||
+        EQUAL( pszFieldName, oFC.networklink_flytoview_field ) ||
+        EQUAL( pszFieldName, oFC.networklink_refreshMode_field ) ||
+        EQUAL( pszFieldName, oFC.networklink_refreshInterval_field ) ||
+        EQUAL( pszFieldName, oFC.networklink_viewRefreshMode_field ) ||
+        EQUAL( pszFieldName, oFC.networklink_viewRefreshTime_field ) ||
+        EQUAL( pszFieldName, oFC.networklink_viewBoundScale_field ) ||
+        EQUAL( pszFieldName, oFC.networklink_viewFormat_field ) ||
+        EQUAL( pszFieldName, oFC.networklink_httpQuery_field ) ||
+        EQUAL( pszFieldName, oFC.camera_longitude_field ) ||
+        EQUAL( pszFieldName, oFC.camera_latitude_field ) ||
+        EQUAL( pszFieldName, oFC.camera_altitude_field ) ||
+        EQUAL( pszFieldName, oFC.camera_altitudemode_field ) ||
+        EQUAL( pszFieldName, oFC.photooverlayfield ) ||
+        EQUAL( pszFieldName, oFC.leftfovfield ) ||
+        EQUAL( pszFieldName, oFC.rightfovfield ) ||
+        EQUAL( pszFieldName, oFC.bottomfovfield ) ||
+        EQUAL( pszFieldName, oFC.topfovfield ) ||
+        EQUAL( pszFieldName, oFC.nearfield ) ||
+        EQUAL( pszFieldName, oFC.photooverlay_shape_field ) ||
+        EQUAL( pszFieldName, oFC.imagepyramid_tilesize_field) ||
+        EQUAL( pszFieldName, oFC.imagepyramid_maxwidth_field) ||
+        EQUAL( pszFieldName, oFC.imagepyramid_maxheight_field) ||
+        EQUAL( pszFieldName, oFC.imagepyramid_gridorigin_field) )
     {
         return NULL;
     }
 
-    SimpleFieldPtr poKmlSimpleField = poKmlFactory->CreateSimpleField (  );
-    poKmlSimpleField->set_name ( pszFieldName );
-
-
-    SimpleDataPtr poKmlSimpleData = NULL;
+    SimpleFieldPtr poKmlSimpleField = poKmlFactory->CreateSimpleField();
+    poKmlSimpleField->set_name( pszFieldName );
 
-    switch ( poOgrFieldDef->GetType (  ) ) {
+    switch( poOgrFieldDef->GetType() )
+    {
     case OFTInteger:
     case OFTIntegerList:
-        poKmlSimpleField->set_type ( "int" );
+        poKmlSimpleField->set_type( "int" );
         return poKmlSimpleField;
 
     case OFTReal:
     case OFTRealList:
-        poKmlSimpleField->set_type ( "float" );
+        poKmlSimpleField->set_type( "float" );
         return poKmlSimpleField;
 
     case OFTString:
     case OFTStringList:
-        poKmlSimpleField->set_type ( "string" );
+        poKmlSimpleField->set_type( "string" );
         return poKmlSimpleField;
 
     /***** kml has these types but as timestamp/timespan *****/
@@ -1625,7 +1631,7 @@ SimpleFieldPtr FieldDef2kml (
         break;
 
     default:
-        poKmlSimpleField->set_type ( "string" );
+        poKmlSimpleField->set_type( "string" );
         return poKmlSimpleField;
     }
 
@@ -1636,67 +1642,72 @@ SimpleFieldPtr FieldDef2kml (
  function to add the simpleFields in a schema to a featuredefn
 ******************************************************************************/
 
-void kml2FeatureDef (
+void kml2FeatureDef(
     SchemaPtr poKmlSchema,
     OGRFeatureDefn * poOgrFeatureDefn )
 {
+    const size_t nSimpleFields = poKmlSchema->get_simplefield_array_size();
 
-    size_t nSimpleFields = poKmlSchema->get_simplefield_array_size (  );
-    size_t iSimpleField;
-
-    for ( iSimpleField = 0; iSimpleField < nSimpleFields; iSimpleField++ ) {
+    for( size_t iSimpleField = 0; iSimpleField < nSimpleFields; iSimpleField++ )
+    {
         SimpleFieldPtr poKmlSimpleField =
-            poKmlSchema->get_simplefield_array_at ( iSimpleField );
+            poKmlSchema->get_simplefield_array_at( iSimpleField );
 
         const char *pszType = "string";
         string osName = "Unknown";
         string osType;
 
-        if ( poKmlSimpleField->has_type (  ) ) {
-            osType = poKmlSimpleField->get_type (  );
-
-            pszType = osType.c_str (  );
-        }
+        if( poKmlSimpleField->has_type() )
+        {
+            osType = poKmlSimpleField->get_type();
 
-        /* FIXME? We cannot set displayname as the field name because in kml2field() we make the */
-        /* lookup on fields based on their name. We would need some map if we really */
-        /* want to use displayname, but that might not be a good idea because displayname */
-        /* may have HTML formatting, which makes it impractical when converting to other */
-        /* drivers or to make requests */
-        /* Example: http://www.jasonbirch.com/files/newt_combined.kml */
-        /*if ( poKmlSimpleField->has_displayname (  ) ) {
-            osName = poKmlSimpleField->get_displayname (  );
+            pszType = osType.c_str();
         }
 
-        else*/ if ( poKmlSimpleField->has_name (  ) ) {
-            osName = poKmlSimpleField->get_name (  );
+        // TODO: We cannot set displayname as the field name because in
+        // kml2field() we make the lookup on fields based on their name. We
+        // would need some map if we really want to use displayname, but that
+        // might not be a good idea because displayname may have HTML
+        // formatting, which makes it impractical when converting to other
+        // drivers or to make requests.
+        // Example: http://www.jasonbirch.com/files/newt_combined.kml
+
+        // if( poKmlSimpleField->has_displayname() )
+        //   {
+        //       osName = poKmlSimpleField->get_displayname();
+        //   }
+        //   else
+        if( poKmlSimpleField->has_name() )
+        {
+            osName = poKmlSimpleField->get_name();
         }
 
-        if ( EQUAL ( pszType, "bool" ) ||
-             EQUAL ( pszType, "boolean" ) ||
-             EQUAL ( pszType, "int" ) ||
-             EQUAL ( pszType, "short" ) ||
-             EQUAL ( pszType, "ushort" ) ) {
-            OGRFieldDefn oOgrFieldName ( osName.c_str(), OFTInteger );
-            poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
+        if( EQUAL( pszType, "bool" ) ||
+            EQUAL( pszType, "boolean" ) ||
+            EQUAL( pszType, "int" ) ||
+            EQUAL( pszType, "short" ) ||
+            EQUAL( pszType, "ushort" ) )
+        {
+            OGRFieldDefn oOgrFieldName( osName.c_str(), OFTInteger );
+            poOgrFeatureDefn->AddFieldDefn( &oOgrFieldName );
         }
-        else if ( EQUAL ( pszType, "uint" ) )  {
-            OGRFieldDefn oOgrFieldName ( osName.c_str(), OFTInteger64 );
-            poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
+        else if( EQUAL( pszType, "uint" ) )
+        {
+            OGRFieldDefn oOgrFieldName( osName.c_str(), OFTInteger64 );
+            poOgrFeatureDefn->AddFieldDefn( &oOgrFieldName );
         }
-        else if ( EQUAL ( pszType, "float" ) ||
-                  EQUAL ( pszType, "double" ) ) {
-            OGRFieldDefn oOgrFieldName ( osName.c_str(), OFTReal );
-            poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
+        else if( EQUAL( pszType, "float" ) ||
+                 EQUAL( pszType, "double" ) )
+        {
+            OGRFieldDefn oOgrFieldName( osName.c_str(), OFTReal );
+            poOgrFeatureDefn->AddFieldDefn( &oOgrFieldName );
         }
-        else /* string, or any other unrecognized type */
+        else  // string, or any other unrecognized type.
         {
-            OGRFieldDefn oOgrFieldName ( osName.c_str(), OFTString );
-            poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
+            OGRFieldDefn oOgrFieldName( osName.c_str(), OFTString );
+            poOgrFeatureDefn->AddFieldDefn( &oOgrFieldName );
         }
     }
-
-    return;
 }
 
 /*******************************************************************************
@@ -1704,30 +1715,30 @@ void kml2FeatureDef (
  *
 *******************************************************************************/
 
-void get_fieldconfig( struct fieldconfig *oFC) {
-
-    oFC->namefield = CPLGetConfigOption ( "LIBKML_NAME_FIELD",
-                                                  "Name" );
-    oFC->descfield = CPLGetConfigOption ( "LIBKML_DESCRIPTION_FIELD",
-                                                  "description" );
-    oFC->tsfield = CPLGetConfigOption ( "LIBKML_TIMESTAMP_FIELD",
-                                                "timestamp" );
-    oFC->beginfield = CPLGetConfigOption ( "LIBKML_BEGIN_FIELD",
-	                                               "begin" );
-	oFC->endfield = CPLGetConfigOption ( "LIBKML_END_FIELD",
-	                                             "end" );
-    oFC->altitudeModefield = CPLGetConfigOption ( "LIBKML_ALTITUDEMODE_FIELD",
-                                                          "altitudeMode" );
-    oFC->tessellatefield = CPLGetConfigOption ( "LIBKML_TESSELLATE_FIELD",
-                                                        "tessellate" );
-    oFC->extrudefield = CPLGetConfigOption ( "LIBKML_EXTRUDE_FIELD",
-                                                     "extrude" );
-    oFC->visibilityfield = CPLGetConfigOption ( "LIBKML_VISIBILITY_FIELD",
-                                                        "visibility" );
-    oFC->drawOrderfield = CPLGetConfigOption ( "LIBKML_DRAWORDER_FIELD",
-                                                       "drawOrder" );
-    oFC->iconfield = CPLGetConfigOption ( "LIBKML_ICON_FIELD",
-                                                  "icon" );
+void get_fieldconfig( struct fieldconfig *oFC )
+{
+    oFC->namefield = CPLGetConfigOption( "LIBKML_NAME_FIELD",
+                                         "Name" );
+    oFC->descfield = CPLGetConfigOption( "LIBKML_DESCRIPTION_FIELD",
+                                         "description" );
+    oFC->tsfield = CPLGetConfigOption( "LIBKML_TIMESTAMP_FIELD",
+                                       "timestamp" );
+    oFC->beginfield = CPLGetConfigOption( "LIBKML_BEGIN_FIELD",
+                                          "begin" );
+    oFC->endfield = CPLGetConfigOption( "LIBKML_END_FIELD",
+                                        "end" );
+    oFC->altitudeModefield = CPLGetConfigOption( "LIBKML_ALTITUDEMODE_FIELD",
+                                                 "altitudeMode" );
+    oFC->tessellatefield = CPLGetConfigOption( "LIBKML_TESSELLATE_FIELD",
+                                               "tessellate" );
+    oFC->extrudefield = CPLGetConfigOption( "LIBKML_EXTRUDE_FIELD",
+                                            "extrude" );
+    oFC->visibilityfield = CPLGetConfigOption( "LIBKML_VISIBILITY_FIELD",
+                                               "visibility" );
+    oFC->drawOrderfield = CPLGetConfigOption( "LIBKML_DRAWORDER_FIELD",
+                                              "drawOrder" );
+    oFC->iconfield = CPLGetConfigOption( "LIBKML_ICON_FIELD",
+                                         "icon" );
     oFC->headingfield = CPLGetConfigOption( "LIBKML_HEADING_FIELD", "heading");
     oFC->tiltfield = CPLGetConfigOption( "LIBKML_TILT_FIELD", "tilt");
     oFC->rollfield = CPLGetConfigOption( "LIBKML_ROLL_FIELD", "roll");
@@ -1736,59 +1747,104 @@ void get_fieldconfig( struct fieldconfig *oFC) {
     oFC->scalexfield = CPLGetConfigOption( "LIBKML_SCALE_X_FIELD", "scale_x");
     oFC->scaleyfield = CPLGetConfigOption( "LIBKML_SCALE_Y_FIELD", "scale_y");
     oFC->scalezfield = CPLGetConfigOption( "LIBKML_SCALE_Z_FIELD", "scale_z");
-    oFC->networklinkfield = CPLGetConfigOption( "LIBKML_NETWORKLINK_FIELD", "networklink");
-    oFC->networklink_refreshvisibility_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_REFRESHVISIBILITY_FIELD", "networklink_refreshvisibility");
-    oFC->networklink_flytoview_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_FLYTOVIEW_FIELD", "networklink_flytoview");
-    oFC->networklink_refreshMode_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_REFRESHMODE_FIELD", "networklink_refreshmode");
-    oFC->networklink_refreshInterval_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_REFRESHINTERVAL_FIELD", "networklink_refreshinterval");
-    oFC->networklink_viewRefreshMode_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWREFRESHMODE_FIELD", "networklink_viewrefreshmode");
-    oFC->networklink_viewRefreshTime_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWREFRESHTIME_FIELD", "networklink_viewrefreshtime");
-    oFC->networklink_viewBoundScale_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWBOUNDSCALE_FIELD", "networklink_viewboundscale");
-    oFC->networklink_viewFormat_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWFORMAT_FIELD", "networklink_viewformat");
-    oFC->networklink_httpQuery_field = CPLGetConfigOption( "LIBKML_NETWORKLINK_HTTPQUERY_FIELD", "networklink_httpquery");
-    oFC->camera_longitude_field = CPLGetConfigOption( "LIBKML_CAMERA_LONGITUDE_FIELD", "camera_longitude");
-    oFC->camera_latitude_field = CPLGetConfigOption( "LIBKML_CAMERA_LATITUDE_FIELD", "camera_latitude");
-    oFC->camera_altitude_field = CPLGetConfigOption( "LIBKML_CAMERA_ALTITUDE_FIELD", "camera_altitude");
-    oFC->camera_altitudemode_field = CPLGetConfigOption( "LIBKML_CAMERA_ALTITUDEMODE_FIELD", "camera_altitudemode");
-    oFC->photooverlayfield = CPLGetConfigOption( "LIBKML_PHOTOOVERLAY_FIELD", "photooverlay");
-    oFC->leftfovfield = CPLGetConfigOption( "LIBKML_LEFTFOV_FIELD", "leftfov");
-    oFC->rightfovfield = CPLGetConfigOption( "LIBKML_RIGHTFOV_FIELD", "rightfov");
-    oFC->bottomfovfield = CPLGetConfigOption( "LIBKML_BOTTOMFOV_FIELD", "bottomfov");
-    oFC->topfovfield = CPLGetConfigOption( "LIBKML_TOPFOV_FIELD", "topfov");
-    oFC->nearfield = CPLGetConfigOption( "LIBKML_NEARFOV_FIELD", "near");
-    oFC->photooverlay_shape_field = CPLGetConfigOption( "LIBKML_PHOTOOVERLAY_SHAPE_FIELD", "photooverlay_shape");
-    oFC->imagepyramid_tilesize_field = CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_TILESIZE", "imagepyramid_tilesize");
-    oFC->imagepyramid_maxwidth_field = CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_MAXWIDTH", "imagepyramid_maxwidth");
-    oFC->imagepyramid_maxheight_field = CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_MAXHEIGHT", "imagepyramid_maxheight");
-    oFC->imagepyramid_gridorigin_field = CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_GRIDORIGIN", "imagepyramid_gridorigin");
+    oFC->networklinkfield =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_FIELD", "networklink");
+    oFC->networklink_refreshvisibility_field =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_REFRESHVISIBILITY_FIELD",
+                            "networklink_refreshvisibility");
+    oFC->networklink_flytoview_field =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_FLYTOVIEW_FIELD",
+                            "networklink_flytoview" );
+    oFC->networklink_refreshMode_field =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_REFRESHMODE_FIELD",
+                            "networklink_refreshmode" );
+    oFC->networklink_refreshInterval_field =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_REFRESHINTERVAL_FIELD",
+                            "networklink_refreshinterval" );
+    oFC->networklink_viewRefreshMode_field =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWREFRESHMODE_FIELD",
+                            "networklink_viewrefreshmode" );
+    oFC->networklink_viewRefreshTime_field =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWREFRESHTIME_FIELD",
+                            "networklink_viewrefreshtime" );
+    oFC->networklink_viewBoundScale_field =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWBOUNDSCALE_FIELD",
+                            "networklink_viewboundscale" );
+    oFC->networklink_viewFormat_field =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_VIEWFORMAT_FIELD",
+                            "networklink_viewformat" );
+    oFC->networklink_httpQuery_field =
+        CPLGetConfigOption( "LIBKML_NETWORKLINK_HTTPQUERY_FIELD",
+                            "networklink_httpquery" );
+    oFC->camera_longitude_field =
+        CPLGetConfigOption( "LIBKML_CAMERA_LONGITUDE_FIELD",
+                            "camera_longitude" );
+    oFC->camera_latitude_field =
+        CPLGetConfigOption( "LIBKML_CAMERA_LATITUDE_FIELD",
+                            "camera_latitude" );
+    oFC->camera_altitude_field =
+        CPLGetConfigOption( "LIBKML_CAMERA_ALTITUDE_FIELD", "camera_altitude");
+    oFC->camera_altitudemode_field =
+        CPLGetConfigOption( "LIBKML_CAMERA_ALTITUDEMODE_FIELD",
+                            "camera_altitudemode");
+    oFC->photooverlayfield =
+        CPLGetConfigOption( "LIBKML_PHOTOOVERLAY_FIELD", "photooverlay");
+    oFC->leftfovfield =
+        CPLGetConfigOption( "LIBKML_LEFTFOV_FIELD", "leftfov");
+    oFC->rightfovfield =
+        CPLGetConfigOption( "LIBKML_RIGHTFOV_FIELD", "rightfov");
+    oFC->bottomfovfield =
+        CPLGetConfigOption( "LIBKML_BOTTOMFOV_FIELD", "bottomfov");
+    oFC->topfovfield =
+        CPLGetConfigOption( "LIBKML_TOPFOV_FIELD", "topfov");
+    oFC->nearfield =
+        CPLGetConfigOption( "LIBKML_NEARFOV_FIELD", "near");
+    oFC->photooverlay_shape_field =
+        CPLGetConfigOption( "LIBKML_PHOTOOVERLAY_SHAPE_FIELD",
+                            "photooverlay_shape");
+    oFC->imagepyramid_tilesize_field =
+        CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_TILESIZE",
+                            "imagepyramid_tilesize");
+    oFC->imagepyramid_maxwidth_field =
+        CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_MAXWIDTH",
+                            "imagepyramid_maxwidth");
+    oFC->imagepyramid_maxheight_field =
+        CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_MAXHEIGHT",
+                            "imagepyramid_maxheight");
+    oFC->imagepyramid_gridorigin_field =
+        CPLGetConfigOption( "LIBKML_IMAGEPYRAMID_GRIDORIGIN",
+                            "imagepyramid_gridorigin" );
 }
 
 /************************************************************************/
 /*                 kmlAltitudeModeFromString()                          */
 /************************************************************************/
 
-int kmlAltitudeModeFromString(const char* pszAltitudeMode,
-                              int& isGX)
+int kmlAltitudeModeFromString( const char* pszAltitudeMode, int& isGX )
 {
     isGX = FALSE;
     int iAltitudeMode = static_cast<int>(kmldom::ALTITUDEMODE_CLAMPTOGROUND);
 
-    if ( EQUAL ( pszAltitudeMode, "clampToGround" ) )
+    if( EQUAL( pszAltitudeMode, "clampToGround" ) )
+    {
         iAltitudeMode = static_cast<int>(kmldom::ALTITUDEMODE_CLAMPTOGROUND);
-
-    else if ( EQUAL ( pszAltitudeMode, "relativeToGround" ) )
+    }
+    else if( EQUAL( pszAltitudeMode, "relativeToGround" ) )
+    {
         iAltitudeMode = static_cast<int>(kmldom::ALTITUDEMODE_RELATIVETOGROUND);
-
-    else if ( EQUAL ( pszAltitudeMode, "absolute" ) )
+    }
+    else if( EQUAL( pszAltitudeMode, "absolute" ) )
+    {
         iAltitudeMode = static_cast<int>(kmldom::ALTITUDEMODE_ABSOLUTE);
-
-    else if ( EQUAL ( pszAltitudeMode, "relativeToSeaFloor" ) ) {
+    }
+    else if( EQUAL( pszAltitudeMode, "relativeToSeaFloor" ) )
+    {
         iAltitudeMode =
             static_cast<int>(kmldom::GX_ALTITUDEMODE_RELATIVETOSEAFLOOR);
         isGX = TRUE;
     }
-
-    else if ( EQUAL ( pszAltitudeMode, "clampToSeaFloor" ) ) {
+    else if( EQUAL( pszAltitudeMode, "clampToSeaFloor" ) )
+    {
         iAltitudeMode =
             static_cast<int>(kmldom::GX_ALTITUDEMODE_CLAMPTOSEAFLOOR);
         isGX = TRUE;
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h
index d209338..6f6b435 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlfield.h
@@ -27,14 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-using kmldom::SimpleFieldPtr;
-using kmldom::SchemaPtr;
-using kmldom::KmlFactory;
-using kmldom::FeaturePtr;
-using kmldom::PlacemarkPtr;
-
 /******************************************************************************
- function to output ogr fields in kml
+ Function to output ogr fields in kml.
 
  args:
         poOgrFeat       pointer to the feature the field is in
@@ -52,47 +46,47 @@ using kmldom::PlacemarkPtr;
   LIBKML_DESCRIPTION_FIELD       default: none
   LIBKML_NAME_FIELD              default: OFTString field named name
 
-
 ******************************************************************************/
 
+#include "ogr_libkml.h"
+
 void field2kml (
     OGRFeature * poOgrFeat,
     OGRLIBKMLLayer * poOgrLayer,
-    KmlFactory * poKmlFactory,
-    FeaturePtr poKmlPlacemark,
+    kmldom::KmlFactory * poKmlFactory,
+    kmldom::FeaturePtr poKmlPlacemark,
     int bUseSimpleField );
 
 /******************************************************************************
- function to read kml into ogr fields
+ Function to read kml into ogr fields.
 ******************************************************************************/
 
 void kml2field (
     OGRFeature * poOgrFeat,
-    FeaturePtr poKmlFeature );
+    kmldom::FeaturePtr poKmlFeature );
 
 /******************************************************************************
- function create a simplefield from a FieldDefn
+ Function create a simplefield from a FieldDefn.
 ******************************************************************************/
 
-SimpleFieldPtr FieldDef2kml (
+kmldom::SimpleFieldPtr FieldDef2kml (
     OGRFieldDefn *poOgrFieldDef,
-    KmlFactory * poKmlFactory );
+    kmldom::KmlFactory * poKmlFactory );
 
 /******************************************************************************
- function to add the simpleFields in a schema to a featuredefn
+ Function to add the simpleFields in a schema to a featuredefn.
 ******************************************************************************/
 
 void kml2FeatureDef (
-    SchemaPtr poKmlSchema,
-    OGRFeatureDefn *poOgrFeatureDefn);
+    kmldom::SchemaPtr poKmlSchema,
+    OGRFeatureDefn *poOgrFeatureDefn );
 
 /*******************************************************************************
- * function to fetch the field config options
- *
+ Function to fetch the field config options.
 *******************************************************************************/
 
 struct fieldconfig {
-	const char *namefield;
+    const char *namefield;
     const char *descfield;
     const char *tsfield;
     const char *beginfield;
@@ -140,5 +134,5 @@ struct fieldconfig {
 
 void get_fieldconfig( struct fieldconfig *oFC );
 
-int kmlAltitudeModeFromString(const char* pszAltitudeMode,
-                              int& isGX);
+int kmlAltitudeModeFromString( const char* pszAltitudeMode,
+                               int& isGX );
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp
index c780a9f..6fc63e4 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.cpp
@@ -29,127 +29,113 @@
 
 #include "libkml_headers.h"
 
-#include <ogr_geometry.h>
+#include "ogr_geometry.h"
 #include "ogr_p.h"
+#include "ogrlibkmlgeometry.h"
 
-using kmldom::KmlFactory;
+CPL_CVSID("$Id: ogrlibkmlgeometry.cpp 35933 2016-10-25 16:46:26Z goatbar $");
+
+using kmlbase::Vec3;
 using kmldom::CoordinatesPtr;
-using kmldom::PointPtr;
-using kmldom::LatLonBoxPtr;
-using kmldom::LineStringPtr;
-using kmldom::LinearRingPtr;
-using kmldom::OuterBoundaryIsPtr;
-using kmldom::InnerBoundaryIsPtr;
-using kmldom::PolygonPtr;
-using kmldom::MultiGeometryPtr;
-using kmldom::GeometryPtr;
 using kmldom::ElementPtr;
 using kmldom::GeometryPtr;
 using kmldom::GxLatLonQuadPtr;
-using kmldom::GxTrackPtr;
 using kmldom::GxMultiTrackPtr;
-
-using kmlbase::Vec3;
-
-#include "ogrlibkmlgeometry.h"
+using kmldom::GxTrackPtr;
+using kmldom::InnerBoundaryIsPtr;
+using kmldom::KmlFactory;
+using kmldom::LatLonBoxPtr;
+using kmldom::LinearRingPtr;
+using kmldom::LineStringPtr;
+using kmldom::MultiGeometryPtr;
+using kmldom::OuterBoundaryIsPtr;
+using kmldom::PointPtr;
+using kmldom::PolygonPtr;
 
 /******************************************************************************
- function to write out a ogr geometry to kml
+ Function to write out a ogr geometry to kml.
 
-args:
+Args:
           poOgrGeom     the ogr geometry
           extra         used in recursion, just pass -1
           poKmlFactory  pointer to the libkml dom factory
 
-returns:
+Returns:
           ElementPtr to the geometry created
 
 ******************************************************************************/
 
-ElementPtr geom2kml (
+ElementPtr geom2kml(
     OGRGeometry * poOgrGeom,
     int extra,
     KmlFactory * poKmlFactory )
 {
-    int i;
-
-    if ( !poOgrGeom ) {
+    if( !poOgrGeom )
+    {
         return NULL;
     }
 
     /***** ogr geom vars *****/
-
     OGRPoint *poOgrPoint = NULL;
-    OGRLineString *poOgrLineString;
-    OGRPolygon *poOgrPolygon;
-    OGRGeometryCollection *poOgrMultiGeom;
+    OGRLineString *poOgrLineString = NULL;
 
     /***** libkml geom vars *****/
+    CoordinatesPtr coordinates = NULL;
 
-    CoordinatesPtr coordinates;
-    PointPtr poKmlPoint;
-    LineStringPtr poKmlLineString;
-    LinearRingPtr poKmlLinearRing;
-    OuterBoundaryIsPtr poKmlOuterRing;
-    InnerBoundaryIsPtr poKmlInnerRing;
-    PolygonPtr poKmlPolygon;
-    MultiGeometryPtr poKmlMultiGeometry;
-
-    ElementPtr poKmlGeometry;
-    ElementPtr poKmlTmpGeometry;
-
-    /***** other vars *****/
-
-    double x,
-        y,
-        z;
+    // This will be the return value.
+    ElementPtr poKmlGeometry = NULL;
 
+    /***** Other vars *****/
     int numpoints = 0;
-    int nGeom;
-    OGRwkbGeometryType type = poOgrGeom->getGeometryType (  );
-
-    switch ( type ) {
+    const OGRwkbGeometryType type = poOgrGeom->getGeometryType();
 
+    switch( type )
+    {
     case wkbPoint:
-
+    {
         poOgrPoint = ( OGRPoint * ) poOgrGeom;
-        if (poOgrPoint->getCoordinateDimension() == 0)
+        PointPtr poKmlPoint = NULL;
+        if( poOgrPoint->getCoordinateDimension() == 0 )
         {
-            poKmlGeometry = poKmlPoint = poKmlFactory->CreatePoint (  );
+            poKmlPoint = poKmlFactory->CreatePoint();
+            poKmlGeometry = poKmlPoint;
         }
         else
         {
-            x = poOgrPoint->getX (  );
-            y = poOgrPoint->getY (  );
+            double x = poOgrPoint->getX();
+            const double y = poOgrPoint->getY();
 
-            if ( x > 180 )
+            if( x > 180 )
                 x -= 360;
 
-            coordinates = poKmlFactory->CreateCoordinates (  );
-            coordinates->add_latlng ( y, x );
-            poKmlGeometry = poKmlPoint = poKmlFactory->CreatePoint (  );
-            poKmlPoint->set_coordinates ( coordinates );
+            coordinates = poKmlFactory->CreateCoordinates();
+            coordinates->add_latlng( y, x );
+            poKmlPoint = poKmlFactory->CreatePoint();
+            poKmlGeometry = poKmlPoint;
+            poKmlPoint->set_coordinates( coordinates );
         }
 
         break;
-
+    }
     case wkbPoint25D:
+    {
         poOgrPoint = ( OGRPoint * ) poOgrGeom;
 
-        x = poOgrPoint->getX (  );
-        y = poOgrPoint->getY (  );
-        z = poOgrPoint->getZ (  );
+        double x = poOgrPoint->getX();
+        const double y = poOgrPoint->getY();
+        const double z = poOgrPoint->getZ();
 
-        if ( x > 180 )
+        if( x > 180 )
             x -= 360;
 
-        coordinates = poKmlFactory->CreateCoordinates (  );
-        coordinates->add_latlngalt ( y, x, z );
-        poKmlGeometry = poKmlPoint = poKmlFactory->CreatePoint (  );
-        poKmlPoint->set_coordinates ( coordinates );
+        coordinates = poKmlFactory->CreateCoordinates();
+        coordinates->add_latlngalt( y, x, z );
+        PointPtr poKmlPoint = poKmlFactory->CreatePoint();
+        poKmlGeometry = poKmlPoint;
+        poKmlPoint->set_coordinates( coordinates );
 
         break;
-
+    }
     case wkbLineString:
         poOgrLineString = ( OGRLineString * ) poOgrGeom;
 
@@ -158,76 +144,85 @@ ElementPtr geom2kml (
             ((OGRLinearRing*)poOgrGeom)->closeRings();
         }
 
-        numpoints = poOgrLineString->getNumPoints (  );
+        numpoints = poOgrLineString->getNumPoints();
         if( extra >= 0 )
         {
             if( numpoints < 4 &&
-                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                CPLTestBool(
+                    CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
-                CPLError(CE_Failure, CPLE_NotSupported, "A linearring should have at least 4 points");
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "A linearring should have at least 4 points");
                 return NULL;
             }
         }
         else
         {
             if( numpoints < 2 &&
-                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                CPLTestBool(
+                    CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
-                CPLError(CE_Failure, CPLE_NotSupported, "A linestring should have at least 2 points");
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "A linestring should have at least 2 points");
                 return NULL;
             }
         }
 
-        coordinates = poKmlFactory->CreateCoordinates (  );
+        coordinates = poKmlFactory->CreateCoordinates();
 
-        poOgrPoint = new OGRPoint (  );
+        poOgrPoint = new OGRPoint();
 
-        for ( i = 0; i < numpoints; i++ ) {
-            poOgrLineString->getPoint ( i, poOgrPoint );
+        for( int i = 0; i < numpoints; i++ )
+        {
+            poOgrLineString->getPoint( i, poOgrPoint );
 
-            x = poOgrPoint->getX (  );
-            y = poOgrPoint->getY (  );
+            double x = poOgrPoint->getX();
+            const double y = poOgrPoint->getY();
 
-            if ( x > 180 )
+            if( x > 180 )
                 x -= 360;
 
-            coordinates->add_latlng ( y, x );
+            coordinates->add_latlng( y, x );
         }
         delete poOgrPoint;
 
-        /***** check if its a wkbLinearRing *****/
-
-        if ( extra < 0 ) {
-
-            poKmlGeometry = poKmlLineString =
-                poKmlFactory->CreateLineString (  );
-            poKmlLineString->set_coordinates ( coordinates );
+        /***** Check if its a wkbLinearRing *****/
+        if( extra < 0 )
+        {
+            LineStringPtr poKmlLineString = poKmlFactory->CreateLineString();
+            poKmlGeometry = poKmlLineString;
+            poKmlLineString->set_coordinates( coordinates );
 
             break;
         }
+        CPL_FALLTHROUGH
 
       /***** fallthrough *****/
 
-    case wkbLinearRing:        //this case is for readability only
-
-        poKmlLinearRing = poKmlFactory->CreateLinearRing (  );
-        poKmlLinearRing->set_coordinates ( coordinates );
+    case wkbLinearRing:  // This case is for readability only.
+    {
+        LinearRingPtr poKmlLinearRing = poKmlFactory->CreateLinearRing();
+        poKmlLinearRing->set_coordinates( coordinates );
 
-        if ( !extra ) {
-            poKmlOuterRing = poKmlFactory->CreateOuterBoundaryIs (  );
-            poKmlOuterRing->set_linearring ( poKmlLinearRing );
+        if( !extra )
+        {
+            OuterBoundaryIsPtr poKmlOuterRing =
+                poKmlFactory->CreateOuterBoundaryIs();
+            poKmlOuterRing->set_linearring( poKmlLinearRing );
             poKmlGeometry = poKmlOuterRing;
         }
-        else {
-            poKmlGeometry = poKmlInnerRing =
-                poKmlFactory->CreateInnerBoundaryIs (  );
-            poKmlInnerRing->set_linearring ( poKmlLinearRing );
+        else
+        {
+            InnerBoundaryIsPtr poKmlInnerRing =
+                poKmlFactory->CreateInnerBoundaryIs();
+            poKmlGeometry = poKmlInnerRing;
+            poKmlInnerRing->set_linearring( poKmlLinearRing );
         }
 
         break;
-
+    }
     case wkbLineString25D:
-
+    {
         poOgrLineString = ( OGRLineString * ) poOgrGeom;
 
         if( extra >= 0 )
@@ -235,131 +230,147 @@ ElementPtr geom2kml (
             ((OGRLinearRing*)poOgrGeom)->closeRings();
         }
 
-        numpoints = poOgrLineString->getNumPoints (  );
+        numpoints = poOgrLineString->getNumPoints();
         if( extra >= 0 )
         {
             if( numpoints < 4 &&
-                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                CPLTestBool(
+                    CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
-                CPLError(CE_Failure, CPLE_NotSupported, "A linearring should have at least 4 points");
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "A linearring should have at least 4 points");
                 return NULL;
             }
         }
         else
         {
             if( numpoints < 2 &&
-                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                CPLTestBool(
+                    CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
-                CPLError(CE_Failure, CPLE_NotSupported, "A linestring should have at least 2 points");
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "A linestring should have at least 2 points");
                 return NULL;
             }
         }
 
-        coordinates = poKmlFactory->CreateCoordinates (  );
-        poOgrPoint = new OGRPoint (  );
+        coordinates = poKmlFactory->CreateCoordinates();
+        poOgrPoint = new OGRPoint();
 
-        for ( i = 0; i < numpoints; i++ ) {
-            poOgrLineString->getPoint ( i, poOgrPoint );
+        for( int i = 0; i < numpoints; i++ )
+        {
+            poOgrLineString->getPoint( i, poOgrPoint );
 
-            x = poOgrPoint->getX (  );
-            y = poOgrPoint->getY (  );
-            z = poOgrPoint->getZ (  );
+            double x = poOgrPoint->getX();
+            const double y = poOgrPoint->getY();
+            const double z = poOgrPoint->getZ();
 
-            if ( x > 180 )
+            if( x > 180 )
                 x -= 360;
 
-            coordinates->add_latlngalt ( y, x, z );
+            coordinates->add_latlngalt( y, x, z );
         }
         delete poOgrPoint;
 
-        /***** check if its a wkbLinearRing *****/
-
-        if ( extra < 0 ) {
-
-            poKmlGeometry = poKmlLineString =
-                poKmlFactory->CreateLineString (  );
-            poKmlLineString->set_coordinates ( coordinates );
+        /***** Check if its a wkbLinearRing *****/
+        if( extra < 0 )
+        {
+            LineStringPtr poKmlLineString = poKmlFactory->CreateLineString();
+            poKmlGeometry = poKmlLineString;
+            poKmlLineString->set_coordinates( coordinates );
 
             break;
         }
             /***** fallthrough *****/
 
-        //case wkbLinearRing25D: // this case is for readability only
+        // case wkbLinearRing25D: // This case is for readability only.
 
-        poKmlLinearRing = poKmlFactory->CreateLinearRing (  );
-        poKmlLinearRing->set_coordinates ( coordinates );
+        LinearRingPtr poKmlLinearRing =
+            poKmlFactory->CreateLinearRing();
+        poKmlLinearRing->set_coordinates( coordinates );
 
-        if ( !extra ) {
-            poKmlGeometry = poKmlOuterRing =
-                poKmlFactory->CreateOuterBoundaryIs (  );
-            poKmlOuterRing->set_linearring ( poKmlLinearRing );
+        if( !extra )
+        {
+            OuterBoundaryIsPtr poKmlOuterRing =
+                poKmlFactory->CreateOuterBoundaryIs();
+            poKmlGeometry = poKmlOuterRing;
+            poKmlOuterRing->set_linearring( poKmlLinearRing );
         }
-        else {
-            poKmlGeometry = poKmlInnerRing =
-                poKmlFactory->CreateInnerBoundaryIs (  );
-            poKmlInnerRing->set_linearring ( poKmlLinearRing );
+        else
+        {
+            InnerBoundaryIsPtr poKmlInnerRing =
+                poKmlFactory->CreateInnerBoundaryIs();
+            poKmlGeometry = poKmlInnerRing;
+            poKmlInnerRing->set_linearring( poKmlLinearRing );
         }
 
         break;
-
+    }
     case wkbPolygon:
-
+    {
         CPLErrorReset();
-        if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
+        if( CPLTestBool(
+               CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
             OGRGeometryFactory::haveGEOS() && (!poOgrGeom->IsValid() ||
              CPLGetLastErrorType() != CE_None) )
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Invalid polygon");
             return NULL;
         }
-        poOgrPolygon = ( OGRPolygon * ) poOgrGeom;
 
-        poKmlGeometry = poKmlPolygon = poKmlFactory->CreatePolygon (  );
+        PolygonPtr poKmlPolygon = poKmlFactory->CreatePolygon();
+        poKmlGeometry = poKmlPolygon;
 
-        poKmlTmpGeometry = geom2kml ( poOgrPolygon->getExteriorRing (  ),
-                                      0, poKmlFactory );
+        OGRPolygon *poOgrPolygon = ( OGRPolygon * ) poOgrGeom;
+        ElementPtr poKmlTmpGeometry = geom2kml( poOgrPolygon->getExteriorRing(),
+                                                0, poKmlFactory );
         poKmlPolygon->
-            set_outerboundaryis ( AsOuterBoundaryIs ( poKmlTmpGeometry ) );
+            set_outerboundaryis( AsOuterBoundaryIs( poKmlTmpGeometry ) );
 
-        nGeom = poOgrPolygon->getNumInteriorRings (  );
-        for ( i = 0; i < nGeom; i++ ) {
-            poKmlTmpGeometry = geom2kml ( poOgrPolygon->getInteriorRing ( i ),
-                                          i + 1, poKmlFactory );
+        const int nGeom = poOgrPolygon->getNumInteriorRings();
+        for( int i = 0; i < nGeom; i++ )
+        {
+            poKmlTmpGeometry = geom2kml( poOgrPolygon->getInteriorRing ( i ),
+                                         i + 1, poKmlFactory );
             poKmlPolygon->
-                add_innerboundaryis ( AsInnerBoundaryIs ( poKmlTmpGeometry ) );
+                add_innerboundaryis( AsInnerBoundaryIs( poKmlTmpGeometry ) );
         }
 
         break;
-
+    }
     case wkbPolygon25D:
-
+    {
         CPLErrorReset();
-        if( CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
-            OGRGeometryFactory::haveGEOS() && (!poOgrGeom->IsValid() ||
+        if( CPLTestBool(
+               CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) &&
+            OGRGeometryFactory::haveGEOS() &&
+            (!poOgrGeom->IsValid() ||
              CPLGetLastErrorType() != CE_None) )
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Invalid polygon");
             return NULL;
         }
-        poOgrPolygon = ( OGRPolygon * ) poOgrGeom;
 
-        poKmlGeometry = poKmlPolygon = poKmlFactory->CreatePolygon (  );
+        PolygonPtr poKmlPolygon = poKmlFactory->CreatePolygon();
+        poKmlGeometry = poKmlPolygon;
 
-        poKmlTmpGeometry = geom2kml ( poOgrPolygon->getExteriorRing (  ),
-                                      0, poKmlFactory );
+        OGRPolygon *poOgrPolygon = ( OGRPolygon * ) poOgrGeom;
+        ElementPtr poKmlTmpGeometry = geom2kml( poOgrPolygon->getExteriorRing(),
+                                               0, poKmlFactory );
         poKmlPolygon->
-            set_outerboundaryis ( AsOuterBoundaryIs ( poKmlTmpGeometry ) );
+            set_outerboundaryis( AsOuterBoundaryIs( poKmlTmpGeometry ) );
 
-        nGeom = poOgrPolygon->getNumInteriorRings (  );
-        for ( i = 0; i < nGeom; i++ ) {
-            poKmlTmpGeometry = geom2kml ( poOgrPolygon->getInteriorRing ( i ),
-                                          i + 1, poKmlFactory );
+        const int nGeom = poOgrPolygon->getNumInteriorRings();
+        for( int i = 0; i < nGeom; i++ )
+        {
+            poKmlTmpGeometry = geom2kml( poOgrPolygon->getInteriorRing( i ),
+                                         i + 1, poKmlFactory );
             poKmlPolygon->
-                add_innerboundaryis ( AsInnerBoundaryIs ( poKmlTmpGeometry ) );
+                add_innerboundaryis( AsInnerBoundaryIs( poKmlTmpGeometry ) );
         }
 
         break;
-
+    }
     case wkbMultiPoint:
     case wkbMultiLineString:
     case wkbMultiPolygon:
@@ -368,49 +379,57 @@ ElementPtr geom2kml (
     case wkbMultiLineString25D:
     case wkbMultiPolygon25D:
     case wkbGeometryCollection25D:
+    {
+        OGRGeometryCollection *poOgrMultiGeom =
+            ( OGRGeometryCollection * ) poOgrGeom;
 
-        poOgrMultiGeom = ( OGRGeometryCollection * ) poOgrGeom;
-
-        nGeom = poOgrMultiGeom->getNumGeometries (  );
+        const int nGeom = poOgrMultiGeom->getNumGeometries();
 
         if( nGeom == 1 &&
-            CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+            CPLTestBool(
+                CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
         {
             CPLDebug("LIBKML", "Turning multiple geometry into single geometry");
-            poKmlGeometry = geom2kml( poOgrMultiGeom->getGeometryRef ( 0 ),
+            poKmlGeometry = geom2kml( poOgrMultiGeom->getGeometryRef( 0 ),
                                       -1, poKmlFactory );
         }
         else
         {
             if( nGeom == 0 &&
-                CPLTestBool(CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
+                CPLTestBool(
+                    CPLGetConfigOption("LIBKML_STRICT_COMPLIANCE", "TRUE")) )
             {
-                CPLError(CE_Warning, CPLE_AppDefined, "Empty multi geometry are not recommended");
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "Empty multi geometry are not recommended");
             }
-            poKmlGeometry = poKmlMultiGeometry =
-                poKmlFactory->CreateMultiGeometry (  );
-            for ( i = 0; i < nGeom; i++ ) {
-                poKmlTmpGeometry = geom2kml ( poOgrMultiGeom->getGeometryRef ( i ),
-                                            -1, poKmlFactory );
+
+            MultiGeometryPtr poKmlMultiGeometry =
+                poKmlFactory->CreateMultiGeometry();
+            poKmlGeometry = poKmlMultiGeometry;
+
+            for( int i = 0; i < nGeom; i++ )
+            {
+                ElementPtr poKmlTmpGeometry =
+                    geom2kml( poOgrMultiGeom->getGeometryRef(i),
+                              -1, poKmlFactory );
                 poKmlMultiGeometry->
-                    add_geometry ( AsGeometry ( poKmlTmpGeometry ) );
+                    add_geometry( AsGeometry( poKmlTmpGeometry ) );
             }
         }
 
         break;
-
+    }
     case wkbUnknown:
     case wkbNone:
     default:
         break;
-
     }
 
     return poKmlGeometry;
 }
 
 /******************************************************************************
- recursive function to read a kml geometry and translate to ogr
+ Recursive function to read a kml geometry and translate to ogr.
 
 Args:
             poKmlGeometry   pointer to the kml geometry to translate
@@ -421,61 +440,41 @@ Returns:
 
 ******************************************************************************/
 
-static OGRGeometry *kml2geom_rec (
+static OGRGeometry *kml2geom_rec(
     GeometryPtr poKmlGeometry,
-    OGRSpatialReference *poOgrSRS)
-
+    OGRSpatialReference *poOgrSRS )
 {
-
     /***** ogr geom vars *****/
-
-    OGRPoint *poOgrPoint;
-    OGRLineString *poOgrLineString;
-    OGRLinearRing *poOgrLinearRing;
-    OGRPolygon *poOgrPolygon;
-    OGRGeometryCollection *poOgrMultiGeometry;
+    OGRPoint *poOgrPoint = NULL;
+    OGRLineString *poOgrLineString = NULL;
+    OGRLinearRing *poOgrLinearRing = NULL;
+    OGRPolygon *poOgrPolygon = NULL;
+    OGRGeometryCollection *poOgrMultiGeometry = NULL;
     OGRGeometry *poOgrGeometry = NULL;
     OGRGeometry *poOgrTmpGeometry = NULL;
 
-
-    /***** libkml geom vars *****/
-
-    CoordinatesPtr poKmlCoordinates;
-    PointPtr poKmlPoint;
-    LineStringPtr poKmlLineString;
-    LinearRingPtr poKmlLinearRing;
-    OuterBoundaryIsPtr poKmlOuterRing;
-    InnerBoundaryIsPtr poKmlInnerRing;
-    PolygonPtr poKmlPolygon;
-    MultiGeometryPtr poKmlMultiGeometry;
-    GxTrackPtr poKmlGxTrack;
-    GxMultiTrackPtr poKmlGxMultiTrack;
-    GeometryPtr poKmlTmpGeometry;
-
-    Vec3 oKmlVec;
-
-    size_t nRings,
-        nCoords,
-        nGeom,
-        i;
-
-    switch ( poKmlGeometry->Type (  ) ) {
+    switch( poKmlGeometry->Type() )
+    {
     case kmldom::Type_Point:
-        poKmlPoint = AsPoint ( poKmlGeometry );
-        if ( poKmlPoint->has_coordinates (  ) ) {
-            poKmlCoordinates = poKmlPoint->get_coordinates (  );
-            nCoords = poKmlCoordinates->get_coordinates_array_size (  );
-            if (nCoords > 0)
+    {
+        PointPtr poKmlPoint = AsPoint( poKmlGeometry );
+        if( poKmlPoint->has_coordinates() )
+        {
+            CoordinatesPtr poKmlCoordinates = poKmlPoint->get_coordinates();
+            const size_t nCoords =
+                poKmlCoordinates->get_coordinates_array_size();
+            if( nCoords > 0 )
             {
-                oKmlVec = poKmlCoordinates->get_coordinates_array_at ( 0 );
+                const Vec3 oKmlVec =
+                    poKmlCoordinates->get_coordinates_array_at( 0 );
 
-                if ( oKmlVec.has_altitude (  ) )
-                    poOgrPoint = new OGRPoint ( oKmlVec.get_longitude (  ),
-                                                oKmlVec.get_latitude (  ),
-                                                oKmlVec.get_altitude (  ) );
+                if( oKmlVec.has_altitude() )
+                    poOgrPoint = new OGRPoint( oKmlVec.get_longitude(),
+                                               oKmlVec.get_latitude(),
+                                               oKmlVec.get_altitude() );
                 else
-                    poOgrPoint = new OGRPoint ( oKmlVec.get_longitude (  ),
-                                                oKmlVec.get_latitude (  ) );
+                    poOgrPoint = new OGRPoint( oKmlVec.get_longitude(),
+                                               oKmlVec.get_latitude() );
 
                 poOgrGeometry = poOgrPoint;
             }
@@ -490,163 +489,190 @@ static OGRGeometry *kml2geom_rec (
         }
 
         break;
-
+    }
     case kmldom::Type_LineString:
-        poKmlLineString = AsLineString ( poKmlGeometry );
-        poOgrLineString = new OGRLineString (  );
-        if ( poKmlLineString->has_coordinates (  ) ) {
-            poKmlCoordinates = poKmlLineString->get_coordinates (  );
-
-            nCoords = poKmlCoordinates->get_coordinates_array_size (  );
-            for ( i = 0; i < nCoords; i++ ) {
-                oKmlVec = poKmlCoordinates->get_coordinates_array_at ( i );
-                if ( oKmlVec.has_altitude (  ) )
+    {
+        LineStringPtr poKmlLineString = AsLineString( poKmlGeometry );
+        poOgrLineString = new OGRLineString();
+        if( poKmlLineString->has_coordinates() )
+        {
+            CoordinatesPtr poKmlCoordinates = poKmlLineString->get_coordinates();
+
+            const size_t nCoords =
+                poKmlCoordinates->get_coordinates_array_size();
+            for( size_t i = 0; i < nCoords; i++ )
+            {
+                const Vec3 oKmlVec =
+                    poKmlCoordinates->get_coordinates_array_at( i );
+                if( oKmlVec.has_altitude() )
                     poOgrLineString->
-                        addPoint ( oKmlVec.get_longitude (  ),
-                                   oKmlVec.get_latitude (  ),
-                                   oKmlVec.get_altitude (  ) );
+                        addPoint( oKmlVec.get_longitude(),
+                                  oKmlVec.get_latitude(),
+                                  oKmlVec.get_altitude() );
                 else
                     poOgrLineString->
-                        addPoint ( oKmlVec.get_longitude (  ),
-                                   oKmlVec.get_latitude (  ) );
+                        addPoint( oKmlVec.get_longitude(),
+                                  oKmlVec.get_latitude() );
             }
         }
         poOgrGeometry = poOgrLineString;
 
         break;
+    }
     case kmldom::Type_LinearRing:
-        poKmlLinearRing = AsLinearRing ( poKmlGeometry );
-        poOgrLinearRing = new OGRLinearRing (  );
-        if ( poKmlLinearRing->has_coordinates (  ) ) {
-            poKmlCoordinates = poKmlLinearRing->get_coordinates (  );
-
-            nCoords = poKmlCoordinates->get_coordinates_array_size (  );
-            for ( i = 0; i < nCoords; i++ ) {
-                oKmlVec = poKmlCoordinates->get_coordinates_array_at ( i );
-                if ( oKmlVec.has_altitude (  ) )
+    {
+        LinearRingPtr poKmlLinearRing = AsLinearRing( poKmlGeometry );
+        poOgrLinearRing = new OGRLinearRing();
+        if( poKmlLinearRing->has_coordinates() )
+        {
+            CoordinatesPtr poKmlCoordinates =
+                poKmlLinearRing->get_coordinates();
+
+            const size_t nCoords =
+                poKmlCoordinates->get_coordinates_array_size();
+            for( size_t i = 0; i < nCoords; i++ )
+            {
+                const Vec3 oKmlVec =
+                    poKmlCoordinates->get_coordinates_array_at( i );
+                if( oKmlVec.has_altitude() )
                     poOgrLinearRing->
-                        addPoint ( oKmlVec.get_longitude (  ),
-                                   oKmlVec.get_latitude (  ),
-                                   oKmlVec.get_altitude (  ) );
+                        addPoint( oKmlVec.get_longitude(),
+                                  oKmlVec.get_latitude(),
+                                  oKmlVec.get_altitude() );
                 else
                     poOgrLinearRing->
-                        addPoint ( oKmlVec.get_longitude (  ),
-                                   oKmlVec.get_latitude (  ) );
+                        addPoint( oKmlVec.get_longitude(),
+                                  oKmlVec.get_latitude() );
             }
         }
         poOgrGeometry = poOgrLinearRing;
 
         break;
+    }
     case kmldom::Type_Polygon:
-        poKmlPolygon = AsPolygon ( poKmlGeometry );
-
-        poOgrPolygon = new OGRPolygon (  );
-        if ( poKmlPolygon->has_outerboundaryis (  ) ) {
+    {
+        PolygonPtr poKmlPolygon = AsPolygon( poKmlGeometry );
 
-            poKmlOuterRing = poKmlPolygon->get_outerboundaryis (  );
-            poKmlLinearRing = poKmlOuterRing->get_linearring (  );
-            if (poKmlLinearRing)
+        poOgrPolygon = new OGRPolygon();
+        if( poKmlPolygon->has_outerboundaryis() )
+        {
+            OuterBoundaryIsPtr poKmlOuterRing =
+                poKmlPolygon->get_outerboundaryis();
+            LinearRingPtr poKmlLinearRing = poKmlOuterRing->get_linearring();
+            if( poKmlLinearRing )
             {
-                poOgrTmpGeometry = kml2geom_rec ( poKmlLinearRing, poOgrSRS );
+                poOgrTmpGeometry = kml2geom_rec( poKmlLinearRing, poOgrSRS );
 
                 poOgrPolygon->
-                    addRingDirectly ( ( OGRLinearRing * ) poOgrTmpGeometry );
+                    addRingDirectly( ( OGRLinearRing * ) poOgrTmpGeometry );
             }
-
         }
-        nRings = poKmlPolygon->get_innerboundaryis_array_size (  );
-        for ( i = 0; i < nRings; i++ ) {
-            poKmlInnerRing = poKmlPolygon->get_innerboundaryis_array_at ( i );
-            poKmlLinearRing = poKmlInnerRing->get_linearring (  );
-            if (poKmlLinearRing)
+        const size_t nRings =
+            poKmlPolygon->get_innerboundaryis_array_size();
+        for( size_t i = 0; i < nRings; i++ )
+        {
+            InnerBoundaryIsPtr poKmlInnerRing =
+                poKmlPolygon->get_innerboundaryis_array_at( i );
+            LinearRingPtr poKmlLinearRing = poKmlInnerRing->get_linearring();
+            if( poKmlLinearRing )
             {
-                poOgrTmpGeometry = kml2geom_rec ( poKmlLinearRing, poOgrSRS );
+                poOgrTmpGeometry = kml2geom_rec( poKmlLinearRing, poOgrSRS );
 
                 poOgrPolygon->
-                    addRingDirectly ( ( OGRLinearRing * ) poOgrTmpGeometry );
+                    addRingDirectly( ( OGRLinearRing * ) poOgrTmpGeometry );
             }
         }
         poOgrGeometry = poOgrPolygon;
 
         break;
+    }
     case kmldom::Type_MultiGeometry:
     {
-        poKmlMultiGeometry = AsMultiGeometry ( poKmlGeometry );
-        nGeom = poKmlMultiGeometry->get_geometry_array_size (  );
+        MultiGeometryPtr poKmlMultiGeometry = AsMultiGeometry( poKmlGeometry );
+        const size_t nGeom = poKmlMultiGeometry->get_geometry_array_size();
 
         // Detect subgeometry type to instantiate appropriate
         // multi geometry type.
         kmldom::KmlDomType type = kmldom::Type_Unknown;
-        for ( i = 0; i < nGeom; i++ ) {
-            poKmlTmpGeometry = poKmlMultiGeometry->get_geometry_array_at ( i );
-            if (type == kmldom::Type_Unknown)
+        for( size_t i = 0; i < nGeom; i++ )
+        {
+            GeometryPtr poKmlTmpGeometry =
+                poKmlMultiGeometry->get_geometry_array_at( i );
+            if( type == kmldom::Type_Unknown )
+            {
                 type = poKmlTmpGeometry->Type();
-            else if (type != poKmlTmpGeometry->Type())
+            }
+            else if( type != poKmlTmpGeometry->Type() )
             {
                 type = kmldom::Type_Unknown;
                 break;
             }
         }
 
-        if (type == kmldom::Type_Point)
+        if( type == kmldom::Type_Point )
             poOgrMultiGeometry = new OGRMultiPoint();
-        else if (type == kmldom::Type_LineString)
+        else if( type == kmldom::Type_LineString )
             poOgrMultiGeometry = new OGRMultiLineString();
-        else if (type == kmldom::Type_Polygon)
+        else if( type == kmldom::Type_Polygon )
             poOgrMultiGeometry = new OGRMultiPolygon();
         else
-            poOgrMultiGeometry = new OGRGeometryCollection ();
+            poOgrMultiGeometry = new OGRGeometryCollection();
 
-        for ( i = 0; i < nGeom; i++ ) {
-            poKmlTmpGeometry = poKmlMultiGeometry->get_geometry_array_at ( i );
-            poOgrTmpGeometry = kml2geom_rec ( poKmlTmpGeometry, poOgrSRS );
+        for( size_t i = 0; i < nGeom; i++ )
+        {
+            GeometryPtr poKmlTmpGeometry =
+                poKmlMultiGeometry->get_geometry_array_at( i );
+            poOgrTmpGeometry = kml2geom_rec( poKmlTmpGeometry, poOgrSRS );
 
-            poOgrMultiGeometry->addGeometryDirectly ( poOgrTmpGeometry );
+            poOgrMultiGeometry->addGeometryDirectly( poOgrTmpGeometry );
         }
         poOgrGeometry = poOgrMultiGeometry;
         break;
     }
-
     case kmldom::Type_GxTrack:
-        poKmlGxTrack = AsGxTrack ( poKmlGeometry );
-        nCoords = poKmlGxTrack->get_gx_coord_array_size();
-        poOgrLineString = new OGRLineString (  );
-        for ( i = 0; i < nCoords; i++ ) {
-            oKmlVec = poKmlGxTrack->get_gx_coord_array_at ( i );
-            if ( oKmlVec.has_altitude (  ) )
+    {
+        GxTrackPtr poKmlGxTrack = AsGxTrack( poKmlGeometry );
+        const size_t nCoords = poKmlGxTrack->get_gx_coord_array_size();
+        poOgrLineString = new OGRLineString();
+        for( size_t i = 0; i < nCoords; i++ )
+        {
+            const Vec3 oKmlVec = poKmlGxTrack->get_gx_coord_array_at( i );
+            if( oKmlVec.has_altitude() )
                 poOgrLineString->
-                    addPoint ( oKmlVec.get_longitude (  ),
-                                oKmlVec.get_latitude (  ),
-                                oKmlVec.get_altitude (  ) );
+                    addPoint( oKmlVec.get_longitude(),
+                              oKmlVec.get_latitude(),
+                              oKmlVec.get_altitude() );
             else
                 poOgrLineString->
-                    addPoint ( oKmlVec.get_longitude (  ),
-                                oKmlVec.get_latitude (  ) );
+                    addPoint( oKmlVec.get_longitude(),
+                              oKmlVec.get_latitude() );
         }
         poOgrGeometry = poOgrLineString;
         break;
-
+    }
     case kmldom::Type_GxMultiTrack:
     {
-        poKmlGxMultiTrack = AsGxMultiTrack ( poKmlGeometry );
-        nGeom = poKmlGxMultiTrack->get_gx_track_array_size (  );
+        GxMultiTrackPtr poKmlGxMultiTrack = AsGxMultiTrack( poKmlGeometry );
+        const size_t nGeom = poKmlGxMultiTrack->get_gx_track_array_size();
         poOgrMultiGeometry = new OGRMultiLineString();
         for( size_t j = 0; j < nGeom; j++ )
         {
-            poKmlGxTrack = poKmlGxMultiTrack->get_gx_track_array_at ( j );
-            nCoords = poKmlGxTrack->get_gx_coord_array_size();
-            poOgrLineString = new OGRLineString (  );
-            for ( i = 0; i < nCoords; i++ ) {
-                oKmlVec = poKmlGxTrack->get_gx_coord_array_at ( i );
-                if ( oKmlVec.has_altitude (  ) )
+            GxTrackPtr poKmlGxTrack =
+                poKmlGxMultiTrack->get_gx_track_array_at( j );
+            const size_t nCoords = poKmlGxTrack->get_gx_coord_array_size();
+            poOgrLineString = new OGRLineString();
+            for( size_t i = 0; i < nCoords; i++ )
+            {
+                const Vec3 oKmlVec = poKmlGxTrack->get_gx_coord_array_at( i );
+                if( oKmlVec.has_altitude() )
                     poOgrLineString->
-                        addPoint ( oKmlVec.get_longitude (  ),
-                                    oKmlVec.get_latitude (  ),
-                                    oKmlVec.get_altitude (  ) );
+                        addPoint( oKmlVec.get_longitude(),
+                                  oKmlVec.get_latitude(),
+                                  oKmlVec.get_altitude() );
                 else
                     poOgrLineString->
-                        addPoint ( oKmlVec.get_longitude (  ),
-                                    oKmlVec.get_latitude (  ) );
+                        addPoint( oKmlVec.get_longitude(),
+                                  oKmlVec.get_latitude() );
             }
             poOgrMultiGeometry->addGeometryDirectly(poOgrLineString);
         }
@@ -655,53 +681,53 @@ static OGRGeometry *kml2geom_rec (
     }
 
     default:
+    {
         break;
     }
+    }
 
-    if (poOgrGeometry)
+    if( poOgrGeometry )
         poOgrGeometry->assignSpatialReference(poOgrSRS);
 
     return poOgrGeometry;
 }
 
 static
-OGRGeometry *kml2geom_latlonbox_int (
+OGRGeometry *kml2geom_latlonbox_int(
     LatLonBoxPtr poKmlLatLonBox,
-    OGRSpatialReference *poOgrSRS)
-
+    OGRSpatialReference *poOgrSRS )
 {
-    OGRPolygon *poOgrPolygon;
-    double north, south, east, west;
-    if ( !poKmlLatLonBox->has_north (  ) ||
-         !poKmlLatLonBox->has_south (  ) ||
-         !poKmlLatLonBox->has_east (  ) ||
-         !poKmlLatLonBox->has_west (  ) ) {
-
+    if( !poKmlLatLonBox->has_north() ||
+        !poKmlLatLonBox->has_south() ||
+        !poKmlLatLonBox->has_east() ||
+        !poKmlLatLonBox->has_west() )
+    {
         return NULL;
     }
-    poOgrPolygon = new OGRPolygon (  );
-    north = poKmlLatLonBox->get_north (  );
-    south = poKmlLatLonBox->get_south (  );
-    east = poKmlLatLonBox->get_east (  );
-    west = poKmlLatLonBox->get_west (  );
-    OGRLinearRing* poOgrRing = new OGRLinearRing (  );
-    poOgrRing->addPoint ( east, north, 0.0 );
-    poOgrRing->addPoint ( east, south, 0.0 );
-    poOgrRing->addPoint ( west, south, 0.0 );
-    poOgrRing->addPoint ( west, north, 0.0 );
-    poOgrRing->addPoint ( east, north, 0.0 );
+    const double north = poKmlLatLonBox->get_north();
+    const double south = poKmlLatLonBox->get_south();
+    const double east = poKmlLatLonBox->get_east();
+    const double west = poKmlLatLonBox->get_west();
+
+    OGRLinearRing* poOgrRing = new OGRLinearRing();
+    poOgrRing->addPoint( east, north, 0.0 );
+    poOgrRing->addPoint( east, south, 0.0 );
+    poOgrRing->addPoint( west, south, 0.0 );
+    poOgrRing->addPoint( west, north, 0.0 );
+    poOgrRing->addPoint( east, north, 0.0 );
+
+    OGRPolygon *poOgrPolygon = new OGRPolygon();
     poOgrPolygon->
-        addRingDirectly ( poOgrRing );
+        addRingDirectly( poOgrRing );
     poOgrPolygon->assignSpatialReference(poOgrSRS);
 
     return poOgrPolygon;
 }
 
 static
-OGRGeometry *kml2geom_latlonquad_int (
+OGRGeometry *kml2geom_latlonquad_int(
     GxLatLonQuadPtr poKmlLatLonQuad,
-    OGRSpatialReference *poOgrSRS)
-
+    OGRSpatialReference *poOgrSRS )
 {
     if( !poKmlLatLonQuad->has_coordinates() )
         return NULL;
@@ -709,33 +735,34 @@ OGRGeometry *kml2geom_latlonquad_int (
     const CoordinatesPtr& poKmlCoordinates =
         poKmlLatLonQuad->get_coordinates();
 
-    OGRLinearRing* poOgrLinearRing = new OGRLinearRing (  );
+    OGRLinearRing* poOgrLinearRing = new OGRLinearRing();
 
-    size_t nCoords = poKmlCoordinates->get_coordinates_array_size (  );
-    for ( size_t i = 0; i < nCoords; i++ ) {
-        Vec3 oKmlVec = poKmlCoordinates->get_coordinates_array_at ( i );
-        if ( oKmlVec.has_altitude (  ) )
+    size_t nCoords = poKmlCoordinates->get_coordinates_array_size();
+    for( size_t i = 0; i < nCoords; i++ )
+    {
+        Vec3 oKmlVec = poKmlCoordinates->get_coordinates_array_at( i );
+        if( oKmlVec.has_altitude() )
             poOgrLinearRing->
-                addPoint ( oKmlVec.get_longitude (  ),
-                           oKmlVec.get_latitude (  ),
-                           oKmlVec.get_altitude (  ) );
+                addPoint( oKmlVec.get_longitude(),
+                          oKmlVec.get_latitude(),
+                          oKmlVec.get_altitude() );
         else
             poOgrLinearRing->
-                addPoint ( oKmlVec.get_longitude (  ),
-                           oKmlVec.get_latitude (  ) );
+                addPoint( oKmlVec.get_longitude(),
+                          oKmlVec.get_latitude() );
     }
     poOgrLinearRing->closeRings();
 
     OGRPolygon *poOgrPolygon = new OGRPolygon();
     poOgrPolygon->
-        addRingDirectly ( poOgrLinearRing );
+        addRingDirectly( poOgrLinearRing );
     poOgrPolygon->assignSpatialReference(poOgrSRS);
 
     return poOgrPolygon;
 }
 
 /******************************************************************************
- main function to read a kml geometry and translate to ogr
+ Main function to read a kml geometry and translate to ogr.
 
 Args:
             poKmlGeometry   pointer to the kml geometry to translate
@@ -746,119 +773,102 @@ Returns:
 
 ******************************************************************************/
 
-OGRGeometry *kml2geom (
+OGRGeometry *kml2geom(
     GeometryPtr poKmlGeometry,
-    OGRSpatialReference *poOgrSRS)
-
+    OGRSpatialReference *poOgrSRS )
 {
+    /***** Get the geometry *****/
+    OGRGeometry *poOgrGeometry = kml2geom_rec(poKmlGeometry, poOgrSRS);
 
-    /***** get the geometry *****/
-
-    OGRGeometry *poOgrGeometry = kml2geom_rec (poKmlGeometry, poOgrSRS);
-
-    /***** split the geometry at the dateline? *****/
-
-    const char *pszWrap = CPLGetConfigOption ( "LIBKML_WRAPDATELINE", "no" );
-    if (CPLTestBool(pszWrap)) {
+    /***** Split the geometry at the dateline? *****/
+    const char *pszWrap = CPLGetConfigOption( "LIBKML_WRAPDATELINE", "no" );
+    if( !CPLTestBool(pszWrap) )
+        return poOgrGeometry;
 
-        char **papszTransformOptions = NULL;
-        papszTransformOptions = CSLAddString( papszTransformOptions,
-                                                "WRAPDATELINE=YES");
+    char **papszTransformOptions = CSLAddString( NULL, "WRAPDATELINE=YES");
 
-        /***** transform *****/
+    /***** Transform *****/
+    OGRGeometry *poOgrDstGeometry =
+        OGRGeometryFactory::transformWithOptions(poOgrGeometry,
+                                                    NULL,
+                                                    papszTransformOptions);
 
-        OGRGeometry *poOgrDstGeometry =
-            OGRGeometryFactory::transformWithOptions(poOgrGeometry,
-                                                        NULL,
-                                                        papszTransformOptions);
-
-        /***** replace the original geom *****/
-
-        if (poOgrDstGeometry) {
-            delete poOgrGeometry;
-            poOgrGeometry = poOgrDstGeometry;
-        }
-
-        CSLDestroy(papszTransformOptions);
+    /***** Replace the original geom *****/
+    if( poOgrDstGeometry )
+    {
+        delete poOgrGeometry;
+        poOgrGeometry = poOgrDstGeometry;
     }
 
+    CSLDestroy(papszTransformOptions);
+
     return poOgrGeometry;
 }
 
-OGRGeometry *kml2geom_latlonbox (
+OGRGeometry *kml2geom_latlonbox(
     LatLonBoxPtr poKmlLatLonBox,
-    OGRSpatialReference *poOgrSRS)
-
+    OGRSpatialReference *poOgrSRS )
 {
+    /***** Get the geometry *****/
+    OGRGeometry *poOgrGeometry =
+        kml2geom_latlonbox_int(poKmlLatLonBox, poOgrSRS);
 
-    /***** get the geometry *****/
-
-    OGRGeometry *poOgrGeometry = kml2geom_latlonbox_int (poKmlLatLonBox, poOgrSRS);
-
-    /***** split the geometry at the dateline? *****/
-
-    const char *pszWrap = CPLGetConfigOption ( "LIBKML_WRAPDATELINE", "no" );
-    if (CPLTestBool(pszWrap)) {
+    /***** Split the geometry at the dateline? *****/
+    const char *pszWrap =
+        CPLGetConfigOption( "LIBKML_WRAPDATELINE", "no" );
 
-        char **papszTransformOptions = NULL;
-        papszTransformOptions = CSLAddString( papszTransformOptions,
-                                                "WRAPDATELINE=YES");
+    if( !CPLTestBool(pszWrap) )
+        return poOgrGeometry;
 
-        /***** transform *****/
+    char **papszTransformOptions = CSLAddString( NULL, "WRAPDATELINE=YES" );
 
-        OGRGeometry *poOgrDstGeometry =
-            OGRGeometryFactory::transformWithOptions(poOgrGeometry,
-                                                        NULL,
-                                                        papszTransformOptions);
+    /***** Transform *****/
+    OGRGeometry *poOgrDstGeometry =
+        OGRGeometryFactory::transformWithOptions(poOgrGeometry,
+                                                 NULL,
+                                                 papszTransformOptions);
 
-        /***** replace the original geom *****/
-
-        if (poOgrDstGeometry) {
-            delete poOgrGeometry;
-            poOgrGeometry = poOgrDstGeometry;
-        }
-
-        CSLDestroy(papszTransformOptions);
+    /***** Replace the original geom *****/
+    if( poOgrDstGeometry )
+    {
+        delete poOgrGeometry;
+        poOgrGeometry = poOgrDstGeometry;
     }
 
+    CSLDestroy(papszTransformOptions);
+
     return poOgrGeometry;
 }
 
-OGRGeometry *kml2geom_latlonquad (
+OGRGeometry *kml2geom_latlonquad(
     GxLatLonQuadPtr poKmlLatLonQuad,
-    OGRSpatialReference *poOgrSRS)
-
+    OGRSpatialReference *poOgrSRS )
 {
+    /***** Get the geometry *****/
+    OGRGeometry *poOgrGeometry =
+        kml2geom_latlonquad_int(poKmlLatLonQuad, poOgrSRS);
 
-    /***** get the geometry *****/
-
-    OGRGeometry *poOgrGeometry = kml2geom_latlonquad_int (poKmlLatLonQuad, poOgrSRS);
-
-    /***** split the geometry at the dateline? *****/
-
-    const char *pszWrap = CPLGetConfigOption ( "LIBKML_WRAPDATELINE", "no" );
-    if (CPLTestBool(pszWrap)) {
-
-        char **papszTransformOptions = NULL;
-        papszTransformOptions = CSLAddString( papszTransformOptions,
-                                                "WRAPDATELINE=YES");
+    /***** Split the geometry at the dateline? *****/
+    const char *pszWrap = CPLGetConfigOption( "LIBKML_WRAPDATELINE", "no" );
+    if( !CPLTestBool(pszWrap) )
+        return poOgrGeometry;
 
-        /***** transform *****/
+    char **papszTransformOptions = CSLAddString( NULL, "WRAPDATELINE=YES");
 
-        OGRGeometry *poOgrDstGeometry =
-            OGRGeometryFactory::transformWithOptions(poOgrGeometry,
-                                                        NULL,
-                                                        papszTransformOptions);
+    /***** Transform *****/
+    OGRGeometry *poOgrDstGeometry =
+        OGRGeometryFactory::transformWithOptions(poOgrGeometry,
+                                                 NULL,
+                                                 papszTransformOptions);
 
-        /***** replace the original geom *****/
-
-        if (poOgrDstGeometry) {
-            delete poOgrGeometry;
-            poOgrGeometry = poOgrDstGeometry;
-        }
-
-        CSLDestroy(papszTransformOptions);
+    /***** Replace the original geom *****/
+    if( poOgrDstGeometry )
+    {
+        delete poOgrGeometry;
+        poOgrGeometry = poOgrDstGeometry;
     }
 
+    CSLDestroy(papszTransformOptions);
+
     return poOgrGeometry;
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h
index 3c36c7d..ed8d586 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlgeometry.h
@@ -31,33 +31,26 @@
 
 #include "libkml_headers.h"
 
-using kmldom::ElementPtr;
-using kmldom::KmlFactory;
-using kmldom::GeometryPtr;
-using kmldom::LatLonBoxPtr;
-using kmldom::GxLatLonQuadPtr;
-
 /*******************************************************************************
-	function to write out a ogr geometry to km
+ Function to write out a ogr geometry to km.
 
 args:
-						poOgrGeom		the ogr geometry
-						extra		used in recursion, just pass -1
-						poKmlFactory	pointer to the libkml dom factory
+            poOgrGeom     the ogr geometry
+            extra         used in recursion, just pass -1
+            poKmlFactory  pointer to the libkml dom factory
 
 returns:
-						ElementPtr to the geometry created
+            ElementPtr to the geometry created
 
 *******************************************************************************/
 
-ElementPtr geom2kml (
+kmldom::ElementPtr geom2kml (
     OGRGeometry * poOgrGeom,
     int extra,
-    KmlFactory * poKmlFactory );
-
+    kmldom::KmlFactory * poKmlFactory );
 
 /******************************************************************************
- function to read a kml geometry and translate to ogr
+ Function to read a kml geometry and translate to ogr.
 
 Args:
             poKmlGeometry   pointer to the kml geometry to translate
@@ -69,15 +62,15 @@ Returns:
 ******************************************************************************/
 
 OGRGeometry *kml2geom (
-    GeometryPtr poKmlGeometry,
-    OGRSpatialReference *poOgrSRS);
+    kmldom::GeometryPtr poKmlGeometry,
+    OGRSpatialReference *poOgrSRS );
 
 OGRGeometry *kml2geom_latlonbox (
-    LatLonBoxPtr poKmlLatLonBox,
-    OGRSpatialReference *poOgrSRS);
+    kmldom::LatLonBoxPtr poKmlLatLonBox,
+    OGRSpatialReference *poOgrSRS );
 
 OGRGeometry *kml2geom_latlonquad (
-    GxLatLonQuadPtr poKmlLatLonQuad,
-    OGRSpatialReference *poOgrSRS);
+    kmldom::GxLatLonQuadPtr poKmlLatLonQuad,
+    OGRSpatialReference *poOgrSRS );
 
-#endif /* OGR_LIBKML_GEOMETRY_H */
+#endif  // OGR_LIBKML_GEOMETRY_H
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
index 6fa0bad..359e7d3 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmllayer.cpp
@@ -29,69 +29,68 @@
 
 #include "libkml_headers.h"
 
+#include <string>
+
 #include "ogr_libkml.h"
-//#include "cpl_conv.h"
-//#include "cpl_string.h"
 #include "cpl_error.h"
+#include "ogrlibkmlfeature.h"
+#include "ogrlibkmlfield.h"
+#include "ogrlibkmlstyle.h"
 
-using kmldom::KmlFactory;
-using kmldom::PlacemarkPtr;
-using kmldom::Placemark;
-using kmldom::DocumentPtr;
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrlibkmllayer.cpp 36024 2016-10-29 12:53:38Z goatbar $");
+
+using kmldom::CameraPtr;
+using kmldom::ChangePtr;
+using kmldom::CreatePtr;
 using kmldom::ContainerPtr;
+using kmldom::DataPtr;
+using kmldom::DeletePtr;
+using kmldom::DocumentPtr;
+using kmldom::ElementPtr;
+using kmldom::ExtendedDataPtr;
 using kmldom::FeaturePtr;
 using kmldom::GroundOverlayPtr;
+using kmldom::IconPtr;
+using kmldom::KmlFactory;
 using kmldom::KmlPtr;
-using kmldom::Kml;
-using kmlengine::KmzFile;
-using kmlengine::KmlFile;
-using kmlengine::Bbox;
-using kmldom::ExtendedDataPtr;
-using kmldom::SchemaDataPtr;
-using kmldom::DataPtr;
-using kmldom::CameraPtr;
-using kmldom::LookAtPtr;
-using kmldom::RegionPtr;
 using kmldom::LatLonAltBoxPtr;
 using kmldom::LodPtr;
+using kmldom::LookAtPtr;
+using kmldom::PlacemarkPtr;
+using kmldom::RegionPtr;
+using kmldom::SchemaDataPtr;
 using kmldom::ScreenOverlayPtr;
-using kmldom::IconPtr;
-using kmldom::CreatePtr;
-using kmldom::ChangePtr;
-using kmldom::DeletePtr;
-
-#include "ogrlibkmlfeature.h"
-#include "ogrlibkmlfield.h"
-#include "ogrlibkmlstyle.h"
+using kmldom::SimpleFieldPtr;
+using kmldom::UpdatePtr;
+using kmlengine::Bbox;
 
 /************************************************************************/
 /*                    OGRLIBKMLGetSanitizedNCName()                     */
 /************************************************************************/
 
-CPLString OGRLIBKMLGetSanitizedNCName(const char* pszName)
+CPLString OGRLIBKMLGetSanitizedNCName( const char* pszName )
 {
     CPLString osName(pszName);
-    /* (Approximate) validation rules for a valid NCName */
-    for(size_t i = 0; i < osName.size(); i++)
+    // (Approximate) validation rules for a valid NCName.
+    for( size_t i = 0; i < osName.size(); i++)
     {
         char ch = osName[i];
         if( (ch >= 'A' && ch <= 'Z') || ch == '_' || (ch >= 'a' && ch <= 'z') )
         {
             /* ok */
         }
-        else if ( i > 0 && (ch == '-' || ch == '.' || (ch >= '0' && ch <= '9')) )
+        else if ( i > 0 && (ch == '-' || ch == '.' ||
+                            (ch >= '0' && ch <= '9')) )
         {
             /* ok */
         }
-#if 0
-        /* Always false. */
-        else if ( ch > 127 )
-        {
-            /* ok : this is an approximation */
-        }
-#endif
+        // Always false: ch > 127.
         else
+        {
             osName[i] = '_';
+        }
     }
     return osName;
 }
@@ -113,279 +112,242 @@ CPLString OGRLIBKMLGetSanitizedNCName(const char* pszName)
 
 ******************************************************************************/
 
-OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
-                                 OGRSpatialReference * poSpatialRef,
-                                 OGRwkbGeometryType eGType,
-                                 OGRLIBKMLDataSource * poOgrDS,
-                                 ElementPtr poKmlRoot,
-                                 ContainerPtr poKmlContainer,
-                                 UpdatePtr poKmlUpdate,
-                                 const char *pszFileName,
-                                 int bNew,
-                                 int bUpdateIn )
+OGRLIBKMLLayer::OGRLIBKMLLayer( const char *pszLayerName,
+                                OGRSpatialReference * poSpatialRef,
+                                OGRwkbGeometryType eGType,
+                                OGRLIBKMLDataSource * poOgrDS,
+                                ElementPtr poKmlRoot,
+                                ContainerPtr poKmlContainer,
+                                UpdatePtr poKmlUpdate,
+                                const char *pszFileName,
+                                int bNew,
+                                int bUpdateIn ) :
+    bUpdate(CPL_TO_BOOL(bUpdateIn)),
+    bUpdated(false),
+    nFeatures(0),
+    iFeature(0),
+    nFID(1),
+    m_pszName(CPLStrdup(pszLayerName)),
+    m_pszFileName(CPLStrdup(pszFileName)),
+    m_poKmlLayer(poKmlContainer),  // Store the layers container.
+    m_poKmlLayerRoot(poKmlRoot),  // Store the root element pointer.
+    m_poKmlUpdate(poKmlUpdate),
+    m_poOgrDS(poOgrDS),
+    m_poOgrFeatureDefn(new OGRFeatureDefn(pszLayerName)),
+    m_poKmlSchema(NULL),
+    m_poOgrSRS(new OGRSpatialReference(NULL)),
+    m_bReadGroundOverlay(CPLTestBool(
+        CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"))),
+    m_bUseSimpleField(CPLTestBool(
+        CPLGetConfigOption("LIBKML_USE_SIMPLEFIELD", "YES"))),
+    m_bWriteRegion(false),
+    m_bRegionBoundsAuto(false),
+    m_dfRegionMinLodPixels(0),
+    m_dfRegionMaxLodPixels(-1),
+    m_dfRegionMinFadeExtent(0),
+    m_dfRegionMaxFadeExtent(0),
+    m_dfRegionMinX(200),
+    m_dfRegionMinY(200),
+    m_dfRegionMaxX(-200),
+    m_dfRegionMaxY(-200),
+    m_bUpdateIsFolder(false)
 {
-
     m_poStyleTable = NULL;
-    iFeature = 0;
-    nFeatures = 0;
-    nFID = 1;
-
-    this->bUpdate = bUpdateIn;
-    bUpdated = FALSE;
-    m_pszName = CPLStrdup ( pszLayerName );
-    m_pszFileName = CPLStrdup ( pszFileName );
-    m_poOgrDS = poOgrDS;
+    m_poOgrSRS->SetWellKnownGeogCS( "WGS84" );
 
-    m_poOgrSRS = new OGRSpatialReference ( NULL );
-    m_poOgrSRS->SetWellKnownGeogCS ( "WGS84" );
-
-    m_poOgrFeatureDefn = new OGRFeatureDefn ( pszLayerName );
     SetDescription( m_poOgrFeatureDefn->GetName() );
-    m_poOgrFeatureDefn->Reference (  );
-    m_poOgrFeatureDefn->SetGeomType ( eGType );
+    m_poOgrFeatureDefn->Reference();
+    m_poOgrFeatureDefn->SetGeomType( eGType );
     if( m_poOgrFeatureDefn->GetGeomFieldCount() != 0 )
         m_poOgrFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poOgrSRS);
 
-    /***** store the root element pointer *****/
-
-    m_poKmlLayerRoot = poKmlRoot;
-
-    /***** store the layers container *****/
-
-    m_poKmlLayer = poKmlContainer;
-
-    /* update container */
-    m_poKmlUpdate = poKmlUpdate;
-
-    m_poKmlSchema = NULL;
-
-    /***** related to Region *****/
-
-    m_bWriteRegion = FALSE;
-    m_bRegionBoundsAuto = FALSE;
-    m_dfRegionMinLodPixels = 0;
-    m_dfRegionMaxLodPixels = -1;
-    m_dfRegionMinFadeExtent = 0;
-    m_dfRegionMaxFadeExtent = 0;
-    m_dfRegionMinX = 200;
-    m_dfRegionMinY = 200;
-    m_dfRegionMaxX = -200;
-    m_dfRegionMaxY = -200;
-
-
-    m_bReadGroundOverlay = CPLTestBool(
-        CPLGetConfigOption("LIBKML_READ_GROUND_OVERLAY", "YES"));
-    m_bUseSimpleField = CPLTestBool(
-        CPLGetConfigOption("LIBKML_USE_SIMPLEFIELD", "YES"));
-
-    m_bUpdateIsFolder = FALSE;
-
     /***** was the layer created from a DS::Open *****/
-
-    if ( !bNew ) {
-
+    if( !bNew )
+    {
         /***** get the number of features on the layer *****/
-
-        nFeatures = static_cast<int>(m_poKmlLayer->get_feature_array_size (  ));
+        nFeatures = static_cast<int>(m_poKmlLayer->get_feature_array_size());
 
         /***** get the field config *****/
-
         struct fieldconfig oFC;
         get_fieldconfig( &oFC );
 
         /***** name field *****/
-
-        OGRFieldDefn oOgrFieldName ( oFC.namefield,OFTString );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldName );
+        OGRFieldDefn oOgrFieldName( oFC.namefield,OFTString );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldName );
 
         /***** description field *****/
-
-        OGRFieldDefn oOgrFieldDesc ( oFC.descfield, OFTString );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldDesc );
+        OGRFieldDefn oOgrFieldDesc( oFC.descfield, OFTString );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldDesc );
 
         /***** timestamp field *****/
-
-        OGRFieldDefn oOgrFieldTs ( oFC.tsfield, OFTDateTime );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldTs );
+        OGRFieldDefn oOgrFieldTs( oFC.tsfield, OFTDateTime );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldTs );
 
         /*****  timespan begin field *****/
-
-        OGRFieldDefn oOgrFieldBegin ( oFC.beginfield, OFTDateTime );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldBegin );
+        OGRFieldDefn oOgrFieldBegin( oFC.beginfield, OFTDateTime );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldBegin );
 
         /*****  timespan end field *****/
-
-        OGRFieldDefn oOgrFieldEnd ( oFC.endfield, OFTDateTime );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldEnd );
+        OGRFieldDefn oOgrFieldEnd( oFC.endfield, OFTDateTime );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldEnd );
 
         /*****  altitudeMode field *****/
-
-        OGRFieldDefn oOgrFieldAltitudeMode ( oFC.altitudeModefield, OFTString );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldAltitudeMode );
+        OGRFieldDefn oOgrFieldAltitudeMode( oFC.altitudeModefield, OFTString );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldAltitudeMode );
 
         /***** tessellate field *****/
-
-        OGRFieldDefn oOgrFieldTessellate ( oFC.tessellatefield, OFTInteger );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldTessellate );
+        OGRFieldDefn oOgrFieldTessellate( oFC.tessellatefield, OFTInteger );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldTessellate );
 
         /***** extrude field *****/
-
-        OGRFieldDefn oOgrFieldExtrude ( oFC.extrudefield, OFTInteger );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldExtrude );
+        OGRFieldDefn oOgrFieldExtrude( oFC.extrudefield, OFTInteger );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldExtrude );
 
         /***** visibility field *****/
-
-        OGRFieldDefn oOgrFieldVisibility ( oFC.visibilityfield, OFTInteger );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldVisibility );
+        OGRFieldDefn oOgrFieldVisibility( oFC.visibilityfield, OFTInteger );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldVisibility );
 
         /***** draw order field *****/
-
-        OGRFieldDefn oOgrFieldDrawOrder ( oFC.drawOrderfield, OFTInteger );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldDrawOrder );
+        OGRFieldDefn oOgrFieldDrawOrder( oFC.drawOrderfield, OFTInteger );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldDrawOrder );
 
         /***** icon field *****/
-
-        OGRFieldDefn oOgrFieldIcon ( oFC.iconfield, OFTString );
-        m_poOgrFeatureDefn->AddFieldDefn ( &oOgrFieldIcon );
+        OGRFieldDefn oOgrFieldIcon( oFC.iconfield, OFTString );
+        m_poOgrFeatureDefn->AddFieldDefn( &oOgrFieldIcon );
 
         /***** get the styles *****/
-
-        if ( m_poKmlLayer->IsA ( kmldom::Type_Document ) )
-            ParseStyles ( AsDocument ( m_poKmlLayer ), &m_poStyleTable );
+        if( m_poKmlLayer->IsA( kmldom::Type_Document ) )
+            ParseStyles( AsDocument ( m_poKmlLayer ), &m_poStyleTable );
 
         /***** get the schema if the layer is a Document *****/
+        if( m_poKmlLayer->IsA( kmldom::Type_Document ) )
+        {
+            DocumentPtr poKmlDocument = AsDocument( m_poKmlLayer );
 
-        if ( m_poKmlLayer->IsA ( kmldom::Type_Document ) ) {
-            DocumentPtr poKmlDocument = AsDocument ( m_poKmlLayer );
-
-            if ( poKmlDocument->get_schema_array_size (  ) ) {
-                m_poKmlSchema = poKmlDocument->get_schema_array_at ( 0 );
-                kml2FeatureDef ( m_poKmlSchema, m_poOgrFeatureDefn );
+            if( poKmlDocument->get_schema_array_size() )
+            {
+                m_poKmlSchema = poKmlDocument->get_schema_array_at( 0 );
+                kml2FeatureDef( m_poKmlSchema, m_poOgrFeatureDefn );
             }
         }
 
         /***** the schema is somewhere else *****/
-
-        if (m_poKmlSchema == NULL) {
-
+        if( m_poKmlSchema == NULL )
+        {
             /***** try to find the correct schema *****/
-
-            int bHasHeading = FALSE, bHasTilt = FALSE, bHasRoll = FALSE;
-            int bHasSnippet = FALSE;
-            FeaturePtr poKmlFeature;
+            bool bHasHeading = false;
+            bool bHasTilt = false;
+            bool bHasRoll = false;
+            bool bHasSnippet = false;
+            FeaturePtr poKmlFeature = NULL;
 
             /***** find the first placemark *****/
-
             do {
-                if ( iFeature >= nFeatures )
+                if( iFeature >= nFeatures )
                     break;
 
                 poKmlFeature =
-                    m_poKmlLayer->get_feature_array_at ( iFeature++ );
+                    m_poKmlLayer->get_feature_array_at( iFeature++ );
 
                 if( poKmlFeature->Type() == kmldom::Type_Placemark )
                 {
-                    PlacemarkPtr poKmlPlacemark = AsPlacemark ( poKmlFeature );
-                    if( !poKmlPlacemark->has_geometry (  ) &&
-                        poKmlPlacemark->has_abstractview (  ) &&
-                        poKmlPlacemark->get_abstractview()->IsA( kmldom::Type_Camera) )
+                    PlacemarkPtr poKmlPlacemark = AsPlacemark( poKmlFeature );
+                    if( !poKmlPlacemark->has_geometry() &&
+                        poKmlPlacemark->has_abstractview() &&
+                        poKmlPlacemark->get_abstractview()->
+                            IsA( kmldom::Type_Camera) )
                     {
-                        const CameraPtr& camera = AsCamera(poKmlPlacemark->get_abstractview());
+                        const CameraPtr& camera =
+                            AsCamera(poKmlPlacemark->get_abstractview());
                         if( camera->has_heading() && !bHasHeading )
                         {
-                            bHasHeading = TRUE;
-                            OGRFieldDefn oOgrField ( oFC.headingfield, OFTReal );
-                            m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                            bHasHeading = true;
+                            OGRFieldDefn oOgrField( oFC.headingfield, OFTReal );
+                            m_poOgrFeatureDefn->AddFieldDefn( &oOgrField );
                         }
                         if( camera->has_tilt() && !bHasTilt )
                         {
-                            bHasTilt = TRUE;
-                            OGRFieldDefn oOgrField ( oFC.tiltfield, OFTReal );
-                            m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                            bHasTilt = true;
+                            OGRFieldDefn oOgrField( oFC.tiltfield, OFTReal );
+                            m_poOgrFeatureDefn->AddFieldDefn( &oOgrField );
                         }
                         if( camera->has_roll() && !bHasRoll )
                         {
-                            bHasRoll = TRUE;
-                            OGRFieldDefn oOgrField ( oFC.rollfield, OFTReal );
-                            m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                            bHasRoll = true;
+                            OGRFieldDefn oOgrField( oFC.rollfield, OFTReal );
+                            m_poOgrFeatureDefn->AddFieldDefn( &oOgrField );
                         }
                     }
                 }
                 if( !bHasSnippet && poKmlFeature->has_snippet() )
                 {
-                    bHasSnippet = TRUE;
-                    OGRFieldDefn oOgrField ( oFC.snippetfield, OFTString );
-                    m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                    bHasSnippet = true;
+                    OGRFieldDefn oOgrField( oFC.snippetfield, OFTString );
+                    m_poOgrFeatureDefn->AddFieldDefn( &oOgrField );
                 }
-            } while ( poKmlFeature->Type (  ) != kmldom::Type_Placemark );
-
-            if ( iFeature <= nFeatures && poKmlFeature &&
-                 poKmlFeature->Type (  ) == kmldom::Type_Placemark &&
-                 poKmlFeature->has_extendeddata (  ) ) {
+            } while( poKmlFeature->Type() != kmldom::Type_Placemark );
 
-                ExtendedDataPtr poKmlExtendedData = poKmlFeature->
-                    get_extendeddata (  );
+            if( iFeature <= nFeatures && poKmlFeature &&
+                poKmlFeature->Type() == kmldom::Type_Placemark &&
+                poKmlFeature->has_extendeddata() )
+            {
 
-                if ( poKmlExtendedData->get_schemadata_array_size (  ) > 0 ) {
-                    SchemaDataPtr poKmlSchemaData = poKmlExtendedData->
-                        get_schemadata_array_at ( 0 );
+                const ExtendedDataPtr poKmlExtendedData =
+                    poKmlFeature->get_extendeddata();
 
-                    if ( poKmlSchemaData->has_schemaurl (  ) ) {
+                if( poKmlExtendedData->get_schemadata_array_size() > 0 )
+                {
+                    const SchemaDataPtr poKmlSchemaData =
+                        poKmlExtendedData->get_schemadata_array_at( 0 );
 
-                        std::string oKmlSchemaUrl = poKmlSchemaData->
-                            get_schemaurl (  );
-                        if ( ( m_poKmlSchema =
-                               m_poOgrDS->FindSchema ( oKmlSchemaUrl.
-                                                       c_str (  ) ) ) ) {
-                            kml2FeatureDef ( m_poKmlSchema,
-                                             m_poOgrFeatureDefn );
+                    if( poKmlSchemaData->has_schemaurl() )
+                    {
+                        std::string oKmlSchemaUrl =
+                            poKmlSchemaData->get_schemaurl();
+                        if( ( m_poKmlSchema = m_poOgrDS->FindSchema(
+                                  oKmlSchemaUrl.c_str() ) ) )
+                        {
+                            kml2FeatureDef( m_poKmlSchema, m_poOgrFeatureDefn );
                         }
                     }
                 }
-                else if ( poKmlExtendedData->get_data_array_size() > 0 )
+                else if( poKmlExtendedData->get_data_array_size() > 0 )
                 {
-                    /* Use the <Data> of the first placemark to build the feature definition */
-                    /* If others have different fields, too bad... */
-                    int bLaunderFieldNames =
-                        CPLTestBool(CPLGetConfigOption("LIBKML_LAUNDER_FIELD_NAMES", "YES"));
-                    size_t nDataArraySize = poKmlExtendedData->get_data_array_size();
-                    for(size_t i=0; i < nDataArraySize; i++)
+                    // Use the <Data> of the first placemark to build the
+                    // feature definition.  If others have different fields,
+                    // too bad...
+                    const bool bLaunderFieldNames =
+                        CPLTestBool(CPLGetConfigOption(
+                            "LIBKML_LAUNDER_FIELD_NAMES", "YES"));
+                    const size_t nDataArraySize =
+                        poKmlExtendedData->get_data_array_size();
+                    for( size_t i = 0; i < nDataArraySize; i++ )
                     {
-                        const DataPtr& data = poKmlExtendedData->get_data_array_at(i);
-                        if (data->has_name())
+                        const DataPtr& data =
+                            poKmlExtendedData->get_data_array_at(i);
+                        if( data->has_name() )
                         {
-                            CPLString osName = data->get_name();
-                            if (bLaunderFieldNames)
+                            CPLString osName = std::string(data->get_name());
+                            if( bLaunderFieldNames )
                                 osName = LaunderFieldNames(osName);
-                            OGRFieldDefn oOgrField ( osName,
-                                                    OFTString );
-                            m_poOgrFeatureDefn->AddFieldDefn ( &oOgrField );
+                            OGRFieldDefn oOgrField( osName, OFTString );
+                            m_poOgrFeatureDefn->AddFieldDefn( &oOgrField );
                         }
                     }
                 }
             }
-
             iFeature = 0;
-
         }
 
-
-
         /***** check if any features are another layer *****/
-
-        m_poOgrDS->ParseLayers ( m_poKmlLayer, poSpatialRef );
-
+        m_poOgrDS->ParseLayers( m_poKmlLayer, poSpatialRef );
     }
-
     /***** it was from a DS::CreateLayer *****/
-
-    else {
-
+    else
+    {
         /***** mark the layer as updated *****/
-
-        bUpdated = TRUE;
+        bUpdated = true;
     }
-
 }
 
 /******************************************************************************
@@ -397,52 +359,47 @@ OGRLIBKMLLayer::OGRLIBKMLLayer ( const char *pszLayerName,
 
 ******************************************************************************/
 
-OGRLIBKMLLayer::~OGRLIBKMLLayer (  )
+OGRLIBKMLLayer::~OGRLIBKMLLayer()
 {
-
-    CPLFree ( ( void * )m_pszName );
-    CPLFree ( ( void * )m_pszFileName );
+    CPLFree( const_cast<char *>(m_pszName) );
+    CPLFree( const_cast<char *>(m_pszFileName) );
     m_poOgrSRS->Release();
 
-    m_poOgrFeatureDefn->Release (  );
-
-
+    m_poOgrFeatureDefn->Release();
 }
 
-
 /******************************************************************************
- Method to get the next feature on the layer
+ Method to get the next feature on the layer.
 
  Args:          none
 
  Returns:       The next feature, or NULL if there is no more
 
- this function copyed from the sqlite driver
+ This function copyed from the sqlite driver.
 ******************************************************************************/
 
 OGRFeature *OGRLIBKMLLayer::GetNextFeature()
-
 {
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
         if( (m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
             && (m_poAttrQuery == NULL
                 || m_poAttrQuery->Evaluate( poFeature )) )
+        {
             return poFeature;
+        }
 
         delete poFeature;
     }
 }
 
 /******************************************************************************
- Method to get the next feature on the layer
+ Method to get the next feature on the layer.
 
  Args:          none
 
@@ -450,10 +407,8 @@ OGRFeature *OGRLIBKMLLayer::GetNextFeature()
 
 ******************************************************************************/
 
-OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
-     )
+OGRFeature *OGRLIBKMLLayer::GetNextRawFeature()
 {
-    FeaturePtr poKmlFeature;
     OGRFeature *poOgrFeature = NULL;
 
     if( m_poKmlLayer == NULL )
@@ -462,50 +417,47 @@ OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
     /***** loop over the kml features to find the next placemark *****/
 
     do {
-        if ( iFeature >= nFeatures )
+        if( iFeature >= nFeatures )
             break;
 
         /***** get the next kml feature in the container *****/
-
-        poKmlFeature = m_poKmlLayer->get_feature_array_at ( iFeature++ );
+        const FeaturePtr poKmlFeature =
+            m_poKmlLayer->get_feature_array_at( iFeature++ );
 
         /***** what type of kml feature in the container? *****/
-
-        switch (poKmlFeature->Type (  )) {
-
+        switch( poKmlFeature->Type() )
+        {
             case kmldom::Type_Placemark:
-                poOgrFeature = kml2feat ( AsPlacemark ( poKmlFeature ),
-                                          m_poOgrDS, this,
-                                          m_poOgrFeatureDefn, m_poOgrSRS );
+                poOgrFeature = kml2feat( AsPlacemark( poKmlFeature ),
+                                         m_poOgrDS, this,
+                                         m_poOgrFeatureDefn, m_poOgrSRS );
                 break;
 
             case kmldom::Type_GroundOverlay:
-                if (m_bReadGroundOverlay) {
+                if( m_bReadGroundOverlay )
+                {
                     poOgrFeature =
-                        kmlgroundoverlay2feat ( AsGroundOverlay ( poKmlFeature ),
-                                                m_poOgrDS, this,
-                                                m_poOgrFeatureDefn,
-                                                m_poOgrSRS );
+                        kmlgroundoverlay2feat( AsGroundOverlay( poKmlFeature ),
+                                               m_poOgrDS, this,
+                                               m_poOgrFeatureDefn,
+                                               m_poOgrSRS );
                 }
                 break;
 
             default:
                 break;
-
         }
-
     } while ( !poOgrFeature );
 
     /***** set the FID on the ogr feature *****/
-
-    if (poOgrFeature)
-        poOgrFeature->SetFID(nFID ++);
+    if( poOgrFeature )
+        poOgrFeature->SetFID(nFID++);
 
     return poOgrFeature;
 }
 
 /******************************************************************************
- method to add a feature to a layer
+ Method to add a feature to a layer.
 
  Args:          poOgrFeat   pointer to the feature to add
 
@@ -514,11 +466,9 @@ OGRFeature *OGRLIBKMLLayer::GetNextRawFeature (
 
 ******************************************************************************/
 
-OGRErr OGRLIBKMLLayer::ICreateFeature (
-    OGRFeature * poOgrFeat )
+OGRErr OGRLIBKMLLayer::ICreateFeature( OGRFeature * poOgrFeat )
 {
-
-    if ( !bUpdate )
+    if( !bUpdate )
         return OGRERR_UNSUPPORTED_OPERATION;
 
     if( m_bRegionBoundsAuto && poOgrFeat->GetGeometryRef() != NULL &&
@@ -526,22 +476,24 @@ OGRErr OGRLIBKMLLayer::ICreateFeature (
     {
         OGREnvelope sEnvelope;
         poOgrFeat->GetGeometryRef()->getEnvelope(&sEnvelope);
-        m_dfRegionMinX = MIN(m_dfRegionMinX, sEnvelope.MinX);
-        m_dfRegionMinY = MIN(m_dfRegionMinY, sEnvelope.MinY);
-        m_dfRegionMaxX = MAX(m_dfRegionMaxX, sEnvelope.MaxX);
-        m_dfRegionMaxY = MAX(m_dfRegionMaxY, sEnvelope.MaxY);
+        m_dfRegionMinX = std::min(m_dfRegionMinX, sEnvelope.MinX);
+        m_dfRegionMinY = std::min(m_dfRegionMinY, sEnvelope.MinY);
+        m_dfRegionMaxX = std::max(m_dfRegionMaxX, sEnvelope.MaxX);
+        m_dfRegionMaxY = std::max(m_dfRegionMaxY, sEnvelope.MaxY);
     }
 
     FeaturePtr poKmlFeature =
-        feat2kml ( m_poOgrDS, this, poOgrFeat, m_poOgrDS->GetKmlFactory (  ),
-                   m_bUseSimpleField );
+        feat2kml( m_poOgrDS, this, poOgrFeat, m_poOgrDS->GetKmlFactory(),
+                  m_bUseSimpleField );
 
     if( m_poKmlLayer != NULL )
-        m_poKmlLayer->add_feature ( poKmlFeature );
+    {
+        m_poKmlLayer->add_feature( poKmlFeature );
+    }
     else
     {
         CPLAssert( m_poKmlUpdate != NULL );
-        KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+        KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory();
         CreatePtr poCreate = poKmlFactory->CreateCreate();
         ContainerPtr poContainer;
         if( m_bUpdateIsFolder )
@@ -549,19 +501,20 @@ OGRErr OGRLIBKMLLayer::ICreateFeature (
         else
             poContainer = poKmlFactory->CreateDocument();
         poContainer->set_targetid(OGRLIBKMLGetSanitizedNCName(GetName()));
-        poContainer->add_feature ( poKmlFeature );
+        poContainer->add_feature( poKmlFeature );
         poCreate->add_container(poContainer);
         m_poKmlUpdate->add_updateoperation(poCreate);
     }
 
     /***** update the layer class count of features  *****/
-
     if( m_poKmlLayer != NULL )
     {
         nFeatures++;
 
-        const char* pszId = CPLSPrintf("%s.%d",
-                        OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), nFeatures);
+        const char* pszId =
+            CPLSPrintf("%s.%d",
+                       OGRLIBKMLGetSanitizedNCName(GetName()).c_str(),
+                       nFeatures);
         poOgrFeat->SetFID(nFeatures);
         poKmlFeature->set_id(pszId);
     }
@@ -569,34 +522,39 @@ OGRErr OGRLIBKMLLayer::ICreateFeature (
     {
         if( poOgrFeat->GetFID() < 0 )
         {
-            static int bAlreadyWarned = FALSE;
+            static bool bAlreadyWarned = false;
             if( !bAlreadyWarned )
             {
-                bAlreadyWarned = TRUE;
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "It is recommended to define a FID when calling CreateFeature() in a update document");
+                bAlreadyWarned = true;
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "It is recommended to define a FID when calling "
+                    "CreateFeature() in a update document");
             }
         }
         else
         {
-            const char* pszId = CPLSPrintf("%s." CPL_FRMT_GIB,
-                    OGRLIBKMLGetSanitizedNCName(GetName()).c_str(), poOgrFeat->GetFID());
+            const char* pszId =
+                CPLSPrintf(
+                    "%s." CPL_FRMT_GIB,
+                    OGRLIBKMLGetSanitizedNCName(GetName()).c_str(),
+                    poOgrFeat->GetFID());
             poOgrFeat->SetFID(nFeatures);
             poKmlFeature->set_id(pszId);
         }
     }
 
     /***** mark the layer as updated *****/
-
-    bUpdated = TRUE;
-    m_poOgrDS->Updated (  );
+    bUpdated = true;
+    m_poOgrDS->Updated();
 
     return OGRERR_NONE;
 }
 
-
 /******************************************************************************
- method to update a feature to a layer. Only work on a NetworkLinkControl/Update
+ Method to update a feature to a layer.
+
+ Only work on a NetworkLinkControl/Update.
 
  Args:          poOgrFeat   pointer to the feature to update
 
@@ -605,7 +563,7 @@ OGRErr OGRLIBKMLLayer::ICreateFeature (
 
 ******************************************************************************/
 
-OGRErr OGRLIBKMLLayer::ISetFeature ( OGRFeature * poOgrFeat )
+OGRErr OGRLIBKMLLayer::ISetFeature( OGRFeature * poOgrFeat )
 {
     if( !bUpdate || m_poKmlUpdate == NULL )
         return OGRERR_UNSUPPORTED_OPERATION;
@@ -613,11 +571,11 @@ OGRErr OGRLIBKMLLayer::ISetFeature ( OGRFeature * poOgrFeat )
         return OGRERR_FAILURE;
 
     FeaturePtr poKmlFeature =
-        feat2kml ( m_poOgrDS, this, poOgrFeat, m_poOgrDS->GetKmlFactory (  ),
-                   m_bUseSimpleField );
+        feat2kml( m_poOgrDS, this, poOgrFeat, m_poOgrDS->GetKmlFactory(),
+                  m_bUseSimpleField );
 
-    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
-    ChangePtr poChange = poKmlFactory->CreateChange();
+    const KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory();
+    const ChangePtr poChange = poKmlFactory->CreateChange();
     poChange->add_object(poKmlFeature);
     m_poKmlUpdate->add_updateoperation(poChange);
 
@@ -626,15 +584,16 @@ OGRErr OGRLIBKMLLayer::ISetFeature ( OGRFeature * poOgrFeat )
     poKmlFeature->set_targetid(pszId);
 
     /***** mark the layer as updated *****/
-
-    bUpdated = TRUE;
-    m_poOgrDS->Updated (  );
+    bUpdated = true;
+    m_poOgrDS->Updated();
 
     return OGRERR_NONE;
 }
 
 /******************************************************************************
- method to delete a feature to a layer. Only work on a NetworkLinkControl/Update
+ Method to delete a feature to a layer.
+
+ Only work on a NetworkLinkControl/Update.
 
  Args:          nFID   id of the feature to delete
 
@@ -648,7 +607,7 @@ OGRErr OGRLIBKMLLayer::DeleteFeature( GIntBig nFIDIn )
     if( !bUpdate || m_poKmlUpdate == NULL )
         return OGRERR_UNSUPPORTED_OPERATION;
 
-    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory();
     DeletePtr poDelete = poKmlFactory->CreateDelete();
     m_poKmlUpdate->add_updateoperation(poDelete);
     PlacemarkPtr poKmlPlacemark = poKmlFactory->CreatePlacemark();
@@ -659,15 +618,14 @@ OGRErr OGRLIBKMLLayer::DeleteFeature( GIntBig nFIDIn )
     poKmlPlacemark->set_targetid(pszId);
 
     /***** mark the layer as updated *****/
-
-    bUpdated = TRUE;
-    m_poOgrDS->Updated (  );
+    bUpdated = true;
+    m_poOgrDS->Updated();
 
     return OGRERR_NONE;
 }
 
 /******************************************************************************
- method to get the number of features on the layer
+ Method to get the number of features on the layer.
 
  Args:          bForce      no effect as of now
 
@@ -678,47 +636,44 @@ OGRErr OGRLIBKMLLayer::DeleteFeature( GIntBig nFIDIn )
 
 ******************************************************************************/
 
-GIntBig OGRLIBKMLLayer::GetFeatureCount (
-                                     int bForce )
+GIntBig OGRLIBKMLLayer::GetFeatureCount( int bForce )
 {
-
-
-    int i = 0;
-    if (m_poFilterGeom != NULL || m_poAttrQuery != NULL ) {
-        i = static_cast<int>(OGRLayer::GetFeatureCount( bForce ));
+    if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
+    {
+        return static_cast<int>(OGRLayer::GetFeatureCount( bForce ));
     }
 
-    else if( m_poKmlLayer != NULL ) {
-        size_t iKmlFeature;
-        size_t nKmlFeatures = m_poKmlLayer->get_feature_array_size (  );
-        FeaturePtr poKmlFeature;
-
-        /***** loop over the kml features in the container *****/
-
-        for ( iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ ) {
-            poKmlFeature = m_poKmlLayer->get_feature_array_at ( iKmlFeature );
+    if( m_poKmlLayer == NULL )
+      return 0;
 
-            /***** what type of kml feature? *****/
+    int count = 0;
 
-            switch (poKmlFeature->Type (  )) {
+    const size_t nKmlFeatures = m_poKmlLayer->get_feature_array_size();
 
-                case kmldom::Type_Placemark:
-                    i++;
-                    break;
+    /***** loop over the kml features in the container *****/
+    for( size_t iKmlFeature = 0; iKmlFeature < nKmlFeatures; iKmlFeature++ )
+    {
+        FeaturePtr poKmlFeature =
+            m_poKmlLayer->get_feature_array_at( iKmlFeature );
 
-                case kmldom::Type_GroundOverlay:
-                    if (m_bReadGroundOverlay)
-                        i++;
-                    break;
+        /***** what type of kml feature? *****/
+        switch( poKmlFeature->Type() )
+        {
+            case kmldom::Type_Placemark:
+                count++;
+                break;
 
-                default:
-                    break;
+            case kmldom::Type_GroundOverlay:
+                if( m_bReadGroundOverlay )
+                    count++;
+                break;
 
-            }
+            default:
+                break;
         }
     }
 
-    return i;
+    return count;
 }
 
 /******************************************************************************
@@ -731,31 +686,26 @@ GIntBig OGRLIBKMLLayer::GetFeatureCount (
 
 ******************************************************************************/
 
-OGRErr OGRLIBKMLLayer::GetExtent (
-    OGREnvelope * psExtent,
-    int bForce )
+OGRErr OGRLIBKMLLayer::GetExtent( OGREnvelope * psExtent, int bForce )
 {
     Bbox oKmlBbox;
 
-    if ( m_poKmlLayer != NULL &&
-        kmlengine::
-         GetFeatureBounds ( AsFeature ( m_poKmlLayer ), &oKmlBbox ) ) {
-        psExtent->MinX = oKmlBbox.get_west (  );
-        psExtent->MinY = oKmlBbox.get_south (  );
-        psExtent->MaxX = oKmlBbox.get_east (  );
-        psExtent->MaxY = oKmlBbox.get_north (  );
+    if( m_poKmlLayer != NULL &&
+        kmlengine::GetFeatureBounds( AsFeature( m_poKmlLayer ), &oKmlBbox ) )
+    {
+        psExtent->MinX = oKmlBbox.get_west();
+        psExtent->MinY = oKmlBbox.get_south();
+        psExtent->MaxX = oKmlBbox.get_east();
+        psExtent->MaxY = oKmlBbox.get_north();
 
         return OGRERR_NONE;
     }
-    else
-        return OGRLayer::GetExtent(psExtent, bForce);
-}
-
-
 
+    return OGRLayer::GetExtent(psExtent, bForce);
+}
 
 /******************************************************************************
- Method to create a field on a layer
+ Method to create a field on a layer.
 
  Args:          poField     pointer to the Field Definition to add
                 bApproxOK   no effect as of now
@@ -765,52 +715,49 @@ OGRErr OGRLIBKMLLayer::GetExtent (
 
 ******************************************************************************/
 
-OGRErr OGRLIBKMLLayer::CreateField (
+OGRErr OGRLIBKMLLayer::CreateField(
     OGRFieldDefn * poField,
-    CPL_UNUSED int bApproxOK )
+    int /* bApproxOK */ )
 {
-    if ( !bUpdate )
+    if( !bUpdate )
         return OGRERR_UNSUPPORTED_OPERATION;
 
     if( m_bUseSimpleField )
     {
         SimpleFieldPtr poKmlSimpleField = NULL;
 
-        if ( (poKmlSimpleField =
-            FieldDef2kml ( poField, m_poOgrDS->GetKmlFactory (  ) )) != NULL )
+        if( (poKmlSimpleField =
+                 FieldDef2kml( poField, m_poOgrDS->GetKmlFactory() )) != NULL )
         {
             if( m_poKmlSchema == NULL )
             {
-                /***** create a new schema *****/
-
-                KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
-
-                m_poKmlSchema = poKmlFactory->CreateSchema (  );
+                /***** Create a new schema *****/
+                KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory();
 
-                /***** set the id on the new schema *****/
+                m_poKmlSchema = poKmlFactory->CreateSchema();
 
-                std::string oKmlSchemaID = OGRLIBKMLGetSanitizedNCName(m_pszName);
-                oKmlSchemaID.append ( ".schema" );
-                m_poKmlSchema->set_id ( oKmlSchemaID );
+                /***** Set the id on the new schema *****/
+                std::string oKmlSchemaID =
+                    OGRLIBKMLGetSanitizedNCName(m_pszName);
+                oKmlSchemaID.append( ".schema" );
+                m_poKmlSchema->set_id( oKmlSchemaID );
             }
 
-            m_poKmlSchema->add_simplefield ( poKmlSimpleField );
+            m_poKmlSchema->add_simplefield( poKmlSimpleField );
         }
     }
 
-    m_poOgrFeatureDefn->AddFieldDefn ( poField );
+    m_poOgrFeatureDefn->AddFieldDefn( poField );
 
     /***** mark the layer as updated *****/
-
-    bUpdated = TRUE;
-    m_poOgrDS->Updated (  );
+    bUpdated = true;
+    m_poOgrDS->Updated();
 
     return OGRERR_NONE;
 }
 
-
 /******************************************************************************
- method to write the datasource to disk
+ Method to write the datasource to disk.
 
  Args:      none
 
@@ -818,15 +765,13 @@ OGRErr OGRLIBKMLLayer::CreateField (
 
 ******************************************************************************/
 
-OGRErr OGRLIBKMLLayer::SyncToDisk (
-     )
+OGRErr OGRLIBKMLLayer::SyncToDisk()
 {
-
     return OGRERR_NONE;
 }
 
 /******************************************************************************
- method to get a layers style table
+ Method to get a layers style table.
 
  Args:          none
 
@@ -835,87 +780,75 @@ OGRErr OGRLIBKMLLayer::SyncToDisk (
 
 ******************************************************************************/
 
-OGRStyleTable *OGRLIBKMLLayer::GetStyleTable (
-     )
+OGRStyleTable *OGRLIBKMLLayer::GetStyleTable()
 {
-
     return m_poStyleTable;
 }
 
 /******************************************************************************
- method to write a style table to a layer
+ Method to write a style table to a layer.
 
  Args:          poStyleTable    pointer to the style table to add
 
  Returns:       nothing
 
- note: this method assumes ownership of the style table
+ Note: This method assumes ownership of the style table.
 ******************************************************************************/
 
-void OGRLIBKMLLayer::SetStyleTableDirectly (
-    OGRStyleTable * poStyleTable )
+void OGRLIBKMLLayer::SetStyleTableDirectly( OGRStyleTable * poStyleTable )
 {
-
-    if ( !bUpdate || m_poKmlLayer == NULL )
+    if( !bUpdate || m_poKmlLayer == NULL )
         return;
 
-    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory();
 
-    if ( m_poStyleTable )
+    if( m_poStyleTable )
         delete m_poStyleTable;
 
     m_poStyleTable = poStyleTable;
 
-    if ( m_poKmlLayer->IsA ( kmldom::Type_Document ) ) {
-
+    if( m_poKmlLayer->IsA( kmldom::Type_Document ) )
+    {
         /***** delete all the styles *****/
+        DocumentPtr poKmlDocument = AsDocument( m_poKmlLayer );
+        const int nKmlStyles =
+            static_cast<int>(poKmlDocument->get_schema_array_size());
 
-        DocumentPtr poKmlDocument = AsDocument ( m_poKmlLayer );
-        int nKmlStyles = static_cast<int>(poKmlDocument->get_schema_array_size (  ));
-        int iKmlStyle;
-
-        for ( iKmlStyle = nKmlStyles - 1; iKmlStyle >= 0; iKmlStyle-- ) {
-            poKmlDocument->DeleteStyleSelectorAt ( iKmlStyle );
+        for( int iKmlStyle = nKmlStyles - 1; iKmlStyle >= 0; iKmlStyle-- )
+        {
+            poKmlDocument->DeleteStyleSelectorAt( iKmlStyle );
         }
 
         /***** add the new style table to the document *****/
-
-        styletable2kml ( poStyleTable, poKmlFactory,
-                         AsContainer ( poKmlDocument ) );
-
+        styletable2kml( poStyleTable, poKmlFactory,
+                        AsContainer( poKmlDocument ) );
     }
 
     /***** mark the layer as updated *****/
-
-    bUpdated = TRUE;
-    m_poOgrDS->Updated (  );
-
-    return;
+    bUpdated = true;
+    m_poOgrDS->Updated();
 }
 
 /******************************************************************************
- method to write a style table to a layer
+ Method to write a style table to a layer.
 
  Args:          poStyleTable    pointer to the style table to add
 
  Returns:       nothing
 
- note:  This method copies the style table, and the user will still be
-        responsible for its destruction
+ Note:  This method copies the style table, and the user will still be
+        responsible for its destruction.
 ******************************************************************************/
 
-void OGRLIBKMLLayer::SetStyleTable (
-    OGRStyleTable * poStyleTable )
+void OGRLIBKMLLayer::SetStyleTable( OGRStyleTable * poStyleTable )
 {
-
-    if ( !bUpdate || m_poKmlLayer == NULL )
+    if( !bUpdate || m_poKmlLayer == NULL )
         return;
 
-    if ( poStyleTable )
-        SetStyleTableDirectly ( poStyleTable->Clone (  ) );
+    if( poStyleTable )
+        SetStyleTableDirectly( poStyleTable->Clone() );
     else
-        SetStyleTableDirectly ( NULL );
-    return;
+        SetStyleTableDirectly( NULL );
 }
 
 /******************************************************************************
@@ -927,26 +860,26 @@ void OGRLIBKMLLayer::SetStyleTable (
 
 ******************************************************************************/
 
-int OGRLIBKMLLayer::TestCapability (
-    const char *pszCap )
+int OGRLIBKMLLayer::TestCapability( const char *pszCap )
 {
     int result = FALSE;
 
-    if ( EQUAL ( pszCap, OLCRandomRead ) )
+    // TODO(schwehr): The false statements are weird.
+    if( EQUAL( pszCap, OLCRandomRead ) )
         result = FALSE;
-    else if ( EQUAL ( pszCap, OLCSequentialWrite ) )
+    else if( EQUAL( pszCap, OLCSequentialWrite ) )
         result = bUpdate;
-    else if ( EQUAL ( pszCap, OLCRandomWrite ) )
+    else if( EQUAL( pszCap, OLCRandomWrite ) )
         result = FALSE;
-    else if ( EQUAL ( pszCap, OLCFastFeatureCount ) )
+    else if( EQUAL( pszCap, OLCFastFeatureCount ) )
         result = FALSE;
-    else if ( EQUAL ( pszCap, OLCFastSetNextByIndex ) )
+    else if( EQUAL( pszCap, OLCFastSetNextByIndex ) )
         result = FALSE;
-    else if ( EQUAL ( pszCap, OLCCreateField ) )
+    else if( EQUAL( pszCap, OLCCreateField ) )
         result = bUpdate;
-    else if ( EQUAL ( pszCap, OLCDeleteFeature ) )
+    else if( EQUAL( pszCap, OLCDeleteFeature ) )
         result = FALSE;
-    else if ( EQUAL(pszCap, OLCStringsAsUTF8) )
+    else if( EQUAL( pszCap, OLCStringsAsUTF8 ) )
         result = TRUE;
 
     return result;
@@ -956,16 +889,16 @@ int OGRLIBKMLLayer::TestCapability (
 /*                        LaunderFieldNames()                           */
 /************************************************************************/
 
-CPLString OGRLIBKMLLayer::LaunderFieldNames(CPLString osName)
+CPLString OGRLIBKMLLayer::LaunderFieldNames( CPLString osName )
 {
     CPLString osLaunderedName;
-    for(int i=0;i<(int)osName.size();i++)
+    for( int i = 0; i < static_cast<int>(osName.size()); i++ )
     {
-        char ch = osName[i];
-        if ((ch >= '0' && ch <= '9') ||
+        const char ch = osName[i];
+        if( (ch >= '0' && ch <= '9') ||
             (ch >= 'a' && ch <= 'z') ||
             (ch >= 'A' && ch <= 'Z') ||
-            (ch == '_'))
+            (ch == '_') )
             osLaunderedName += ch;
         else
             osLaunderedName += "_";
@@ -985,7 +918,7 @@ void OGRLIBKMLLayer::SetLookAt( const char* pszLookatLongitude,
                                 const char* pszLookatRange,
                                 const char* pszLookatAltitudeMode )
 {
-    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory();
     LookAtPtr lookAt = poKmlFactory->CreateLookAt();
     lookAt->set_latitude(CPLAtof(pszLookatLatitude));
     lookAt->set_longitude(CPLAtof(pszLookatLongitude));
@@ -1006,17 +939,23 @@ void OGRLIBKMLLayer::SetLookAt( const char* pszLookatLongitude,
     if( pszLookatAltitudeMode != NULL )
     {
         int isGX = FALSE;
-        int iAltitudeMode = kmlAltitudeModeFromString(pszLookatAltitudeMode, isGX);
+        const int iAltitudeMode =
+            kmlAltitudeModeFromString(pszLookatAltitudeMode, isGX);
         if( iAltitudeMode != kmldom::ALTITUDEMODE_CLAMPTOGROUND &&
             pszLookatAltitude == NULL )
         {
-            CPLError(CE_Warning, CPLE_AppDefined, "Lookat altitude should be present for altitudeMode = %s",
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Lookat altitude should be present for altitudeMode = %s",
                      pszLookatAltitudeMode);
         }
         else if( isGX )
+        {
             lookAt->set_gx_altitudemode(iAltitudeMode);
+        }
         else
+        {
             lookAt->set_altitudemode(iAltitudeMode);
+        }
     }
 
     m_poKmlLayer->set_abstractview(lookAt);
@@ -1038,17 +977,19 @@ void OGRLIBKMLLayer::SetCamera( const char* pszCameraLongitude,
     int iAltitudeMode = kmlAltitudeModeFromString(pszCameraAltitudeMode, isGX);
     if( isGX == FALSE && iAltitudeMode == kmldom::ALTITUDEMODE_CLAMPTOGROUND )
     {
-        CPLError(CE_Warning, CPLE_AppDefined, "Camera altitudeMode should be different from %s",
-                    pszCameraAltitudeMode);
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Camera altitudeMode should be different from %s",
+                 pszCameraAltitudeMode);
         return;
     }
-    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory();
     CameraPtr camera = poKmlFactory->CreateCamera();
     camera->set_latitude(CPLAtof(pszCameraLatitude));
     camera->set_longitude(CPLAtof(pszCameraLongitude));
     camera->set_altitude(CPLAtof(pszCameraAltitude));
     if( pszCameraHeading != NULL )
         camera->set_heading(CPLAtof(pszCameraHeading));
+
     if( pszCameraTilt != NULL )
     {
         double dfTilt = CPLAtof(pszCameraTilt);
@@ -1058,6 +999,7 @@ void OGRLIBKMLLayer::SetCamera( const char* pszCameraLongitude,
             CPLError(CE_Warning, CPLE_AppDefined, "Invalid value for tilt: %s",
                      pszCameraTilt);
     }
+
     if( pszCameraRoll != NULL )
         camera->set_roll(CPLAtof(pszCameraRoll));
     if( isGX )
@@ -1072,13 +1014,13 @@ void OGRLIBKMLLayer::SetCamera( const char* pszCameraLongitude,
 /*                         SetWriteRegion()                             */
 /************************************************************************/
 
-void OGRLIBKMLLayer::SetWriteRegion(double dfMinLodPixels,
-                                    double dfMaxLodPixels,
-                                    double dfMinFadeExtent,
-                                    double dfMaxFadeExtent)
+void OGRLIBKMLLayer::SetWriteRegion( double dfMinLodPixels,
+                                     double dfMaxLodPixels,
+                                     double dfMinFadeExtent,
+                                     double dfMaxFadeExtent )
 {
-    m_bWriteRegion = TRUE;
-    m_bRegionBoundsAuto = TRUE;
+    m_bWriteRegion = true;
+    m_bRegionBoundsAuto = true;
     m_dfRegionMinLodPixels = dfMinLodPixels;
     m_dfRegionMaxLodPixels = dfMaxLodPixels;
     m_dfRegionMinFadeExtent = dfMinFadeExtent;
@@ -1089,10 +1031,10 @@ void OGRLIBKMLLayer::SetWriteRegion(double dfMinLodPixels,
 /*                          SetRegionBounds()                           */
 /************************************************************************/
 
-void OGRLIBKMLLayer::SetRegionBounds(double dfMinX, double dfMinY,
-                                     double dfMaxX, double dfMaxY)
+void OGRLIBKMLLayer::SetRegionBounds( double dfMinX, double dfMinY,
+                                      double dfMaxX, double dfMaxY )
 {
-    m_bRegionBoundsAuto = FALSE;
+    m_bRegionBoundsAuto = false;
     m_dfRegionMinX = dfMinX;
     m_dfRegionMinY = dfMinY;
     m_dfRegionMaxX = dfMaxX;
@@ -1103,9 +1045,9 @@ void OGRLIBKMLLayer::SetRegionBounds(double dfMinX, double dfMinY,
 /*                            Finalize()                                */
 /************************************************************************/
 
-void OGRLIBKMLLayer::Finalize(DocumentPtr poKmlDocument)
+void OGRLIBKMLLayer::Finalize( DocumentPtr poKmlDocument )
 {
-    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    KmlFactory * const poKmlFactory = m_poOgrDS->GetKmlFactory();
 
     if( m_bWriteRegion && m_dfRegionMinX < m_dfRegionMaxX )
     {
@@ -1133,19 +1075,19 @@ void OGRLIBKMLLayer::Finalize(DocumentPtr poKmlDocument)
         m_poKmlLayer->set_region(region);
     }
 
-    createkmlliststyle (poKmlFactory,
-                        GetName(),
-                        m_poKmlLayer,
-                        poKmlDocument,
-                        osListStyleType,
-                        osListStyleIconHref);
+    createkmlliststyle(poKmlFactory,
+                       GetName(),
+                       m_poKmlLayer,
+                       poKmlDocument,
+                       osListStyleType,
+                       osListStyleIconHref);
 }
 
 /************************************************************************/
 /*                             LIBKMLGetUnits()                         */
 /************************************************************************/
 
-static int LIBKMLGetUnits(const char* pszUnits)
+static int LIBKMLGetUnits( const char* pszUnits )
 {
     if( EQUAL(pszUnits, "fraction") )
         return kmldom::UNITS_FRACTION;
@@ -1153,18 +1095,19 @@ static int LIBKMLGetUnits(const char* pszUnits)
         return  kmldom::UNITS_PIXELS;
     if( EQUAL(pszUnits, "insetPixels") )
         return  kmldom::UNITS_INSETPIXELS;
-    return  kmldom::UNITS_FRACTION;
+    return kmldom::UNITS_FRACTION;
 }
 
 /************************************************************************/
 /*                         LIBKMLSetVec2()                              */
 /************************************************************************/
 
-static void LIBKMLSetVec2(kmldom::Vec2Ptr vec2, const char* pszX, const char* pszY,
-                    const char* pszXUnits, const char* pszYUnits)
+static void LIBKMLSetVec2(
+    kmldom::Vec2Ptr vec2, const char* pszX, const char* pszY,
+    const char* pszXUnits, const char* pszYUnits )
 {
-    double dfX = CPLAtof(pszX);
-    double dfY = CPLAtof(pszY);
+    const double dfX = CPLAtof(pszX);
+    const double dfY = CPLAtof(pszY);
     vec2->set_x(dfX);
     vec2->set_y(dfY);
     if( dfX <= 1 && dfY <= 1 )
@@ -1185,23 +1128,23 @@ static void LIBKMLSetVec2(kmldom::Vec2Ptr vec2, const char* pszX, const char* ps
 /*                         SetScreenOverlay()                           */
 /************************************************************************/
 
-void OGRLIBKMLLayer::SetScreenOverlay(const char* pszSOHref,
-                                      const char* pszSOName,
-                                      const char* pszSODescription,
-                                      const char* pszSOOverlayX,
-                                      const char* pszSOOverlayY,
-                                      const char* pszSOOverlayXUnits,
-                                      const char* pszSOOverlayYUnits,
-                                      const char* pszSOScreenX,
-                                      const char* pszSOScreenY,
-                                      const char* pszSOScreenXUnits,
-                                      const char* pszSOScreenYUnits,
-                                      const char* pszSOSizeX,
-                                      const char* pszSOSizeY,
-                                      const char* pszSOSizeXUnits,
-                                      const char* pszSOSizeYUnits)
+void OGRLIBKMLLayer::SetScreenOverlay( const char* pszSOHref,
+                                       const char* pszSOName,
+                                       const char* pszSODescription,
+                                       const char* pszSOOverlayX,
+                                       const char* pszSOOverlayY,
+                                       const char* pszSOOverlayXUnits,
+                                       const char* pszSOOverlayYUnits,
+                                       const char* pszSOScreenX,
+                                       const char* pszSOScreenY,
+                                       const char* pszSOScreenXUnits,
+                                       const char* pszSOScreenYUnits,
+                                       const char* pszSOSizeX,
+                                       const char* pszSOSizeY,
+                                       const char* pszSOSizeXUnits,
+                                       const char* pszSOSizeYUnits )
 {
-    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory (  );
+    KmlFactory *poKmlFactory = m_poOgrDS->GetKmlFactory();
     ScreenOverlayPtr so = poKmlFactory->CreateScreenOverlay();
 
     if( pszSOName != NULL )
@@ -1250,9 +1193,9 @@ void OGRLIBKMLLayer::SetScreenOverlay(const char* pszSOHref,
 /*                           SetListStyle()                              */
 /************************************************************************/
 
-void OGRLIBKMLLayer::SetListStyle(const char* pszListStyleType,
-                                  const char* pszListStyleIconHref)
+void OGRLIBKMLLayer::SetListStyle( const char* pszListStyleType,
+                                   const char* pszListStyleIconHref )
 {
-    osListStyleType = (pszListStyleType) ? pszListStyleType : "";
-    osListStyleIconHref = (pszListStyleIconHref) ? pszListStyleIconHref : "";
+    osListStyleType = pszListStyleType ? pszListStyleType : "";
+    osListStyleIconHref = pszListStyleIconHref ? pszListStyleIconHref : "";
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
index 22bf975..60ab11e 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.cpp
@@ -29,238 +29,258 @@
 
 #include "libkml_headers.h"
 
-#include <ogr_featurestyle.h>
-
 #include <set>
+#include <string>
+
+#include "ogr_featurestyle.h"
+#include "ogrlibkmlstyle.h"
+#include "ogr_libkml.h"
 
-using kmldom::KmlFactory;;
+CPL_CVSID("$Id: ogrlibkmlstyle.cpp 37911 2017-04-06 16:51:07Z rouault $");
+
+using kmlbase::Color32;
+using kmldom::BalloonStylePtr;
+using kmldom::ContainerPtr;
+using kmldom::DocumentPtr;
 using kmldom::ElementPtr;
-using kmldom::ObjectPtr;
 using kmldom::FeaturePtr;
-using kmldom::StylePtr;
-using kmldom::StyleMapPtr;
-using kmldom::STYLESTATE_NORMAL;
-using kmldom::STYLESTATE_HIGHLIGHT;
-using kmldom::StyleSelectorPtr;
-using kmldom::LineStylePtr;
-using kmldom::PolyStylePtr;
-using kmldom::IconStylePtr;
-using kmldom::IconStyleIconPtr;
-using kmldom::LabelStylePtr;
-using kmldom::BalloonStylePtr;
 using kmldom::HotSpotPtr;
-using kmlbase::Color32;
-using kmldom::PairPtr;
+using kmldom::ItemIconPtr;
+using kmldom::IconStyleIconPtr;
+using kmldom::IconStylePtr;
+using kmldom::KmlFactory;
 using kmldom::KmlPtr;
+using kmldom::LabelStylePtr;
+using kmldom::LineStylePtr;
 using kmldom::ListStylePtr;
-using kmldom::ItemIconPtr;
-
-#include "ogrlibkmlstyle.h"
-#include "ogr_libkml.h"
+using kmldom::ObjectPtr;
+using kmldom::PairPtr;
+using kmldom::PolyStylePtr;
+using kmldom::StyleMapPtr;
+using kmldom::StylePtr;
+using kmldom::StyleSelectorPtr;
+using kmldom::STYLESTATE_HIGHLIGHT;
+using kmldom::STYLESTATE_NORMAL;
 
 /******************************************************************************
- generic function to parse a stylestring and add to a kml style
+ Generic function to parse a stylestring and add to a kml style.
 
-args:
+Args:
             pszStyleString  the stylestring to parse
             poKmlStyle      the kml style to add to (or NULL)
             poKmlFactory    the kml dom factory
 
-returns:
+Returns:
             the kml style
 
 ******************************************************************************/
 
-StylePtr addstylestring2kml (
+StylePtr addstylestring2kml(
     const char *pszStyleString,
     StylePtr poKmlStyle,
     KmlFactory * poKmlFactory,
     FeaturePtr poKmlFeature )
 {
+    /***** just bail now if stylestring is empty *****/
+    if( !pszStyleString || !*pszStyleString )
+    {
+        return poKmlStyle;
+    }
 
     LineStylePtr poKmlLineStyle = NULL;
     PolyStylePtr poKmlPolyStyle = NULL;
     IconStylePtr poKmlIconStyle = NULL;
     LabelStylePtr poKmlLabelStyle = NULL;
 
-    /***** just bail now if stylestring is empty *****/
-
-    if ( !pszStyleString || !*pszStyleString ) {
-        return poKmlStyle;
-    }
-
     /***** create and init a style mamager with the style string *****/
+    OGRStyleMgr * const poOgrSM = new OGRStyleMgr;
 
-    OGRStyleMgr *poOgrSM = new OGRStyleMgr;
-
-    poOgrSM->InitStyleString ( pszStyleString );
+    poOgrSM->InitStyleString( pszStyleString );
 
     /***** loop though the style parts *****/
+    for( int i = 0; i < poOgrSM->GetPartCount( NULL ); i++ )
+    {
+        OGRStyleTool *poOgrST = poOgrSM->GetPart( i, NULL );
 
-    int i;
-
-    for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) {
-        OGRStyleTool *poOgrST = poOgrSM->GetPart ( i, NULL );
-
-        if ( !poOgrST ) {
+        if( !poOgrST )
+        {
             continue;
         }
 
-        switch ( poOgrST->GetType (  ) ) {
-        case OGRSTCPen:
+        switch( poOgrST->GetType() )
+        {
+            case OGRSTCPen:
             {
-                GBool nullcheck;
-
-                poKmlLineStyle = poKmlFactory->CreateLineStyle (  );
+                poKmlLineStyle = poKmlFactory->CreateLineStyle();
 
-                OGRStylePen *poStylePen = ( OGRStylePen * ) poOgrST;
+                OGRStylePen *poStylePen = dynamic_cast<OGRStylePen *>(poOgrST);
+                if( poStylePen == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "dynamic_cast failed.");
+                    delete poOgrSM;
+                    return NULL;
+                }
 
                 /***** pen color *****/
-
-                int nR,
-                    nG,
-                    nB,
-                    nA;
-
-                const char *pszcolor = poStylePen->Color ( nullcheck );
-
-                if ( !nullcheck
-                     && poStylePen->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
-                    poKmlLineStyle->set_color ( Color32 ( static_cast<GByte>(nA),
-                                                          static_cast<GByte>(nB),
-                                                          static_cast<GByte>(nG),
-                                                          static_cast<GByte>(nR) ) );
+                GBool nullcheck = FALSE;
+                const char * const pszColor = poStylePen->Color( nullcheck );
+
+                int nR = 0;
+                int nG = 0;
+                int nB = 0;
+                int nA = 0;
+                if( !nullcheck &&
+                    poStylePen->GetRGBFromString( pszColor, nR, nG, nB, nA ) )
+                {
+                    poKmlLineStyle->set_color(
+                        Color32( static_cast<GByte>(nA),
+                                 static_cast<GByte>(nB),
+                                 static_cast<GByte>(nG),
+                                 static_cast<GByte>(nR) ) );
                 }
                 poStylePen->SetUnit(OGRSTUPixel);
-                double dfWidth = poStylePen->Width ( nullcheck );
+                double dfWidth = poStylePen->Width( nullcheck );
 
-                if ( nullcheck )
+                if( nullcheck )
                     dfWidth = 1.0;
 
-                poKmlLineStyle->set_width ( dfWidth );
+                poKmlLineStyle->set_width( dfWidth );
 
                 break;
             }
-        case OGRSTCBrush:
+            case OGRSTCBrush:
             {
-                GBool nullcheck;
-
-                OGRStyleBrush *poStyleBrush = ( OGRStyleBrush * ) poOgrST;
+                OGRStyleBrush * const poStyleBrush =
+                    dynamic_cast<OGRStyleBrush *>(poOgrST);
+                if( poStyleBrush == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "dynamic_cast failed.");
+                    delete poOgrSM;
+                    return NULL;
+                }
 
                 /***** brush color *****/
-
-                int nR,
-                    nG,
-                    nB,
-                    nA;
-
-                const char *pszcolor = poStyleBrush->ForeColor ( nullcheck );
-
-                if ( !nullcheck
-                     && poStyleBrush->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
-                    poKmlPolyStyle = poKmlFactory->CreatePolyStyle (  );
-                    poKmlPolyStyle->set_color ( Color32 ( static_cast<GByte>(nA),
-                                                          static_cast<GByte>(nB),
-                                                          static_cast<GByte>(nG),
-                                                          static_cast<GByte>(nR) ) );
+                GBool nullcheck = FALSE;
+                const char *pszColor = poStyleBrush->ForeColor( nullcheck );
+
+                int nR = 0;
+                int nG = 0;
+                int nB = 0;
+                int nA = 0;
+                if( !nullcheck &&
+                    poStyleBrush->GetRGBFromString( pszColor, nR, nG, nB, nA ) )
+                {
+                    poKmlPolyStyle = poKmlFactory->CreatePolyStyle();
+                    poKmlPolyStyle->set_color(
+                        Color32( static_cast<GByte>(nA),
+                                 static_cast<GByte>(nB),
+                                 static_cast<GByte>(nG),
+                                 static_cast<GByte>(nR) ) );
                 }
-
-
                 break;
             }
-        case OGRSTCSymbol:
+            case OGRSTCSymbol:
             {
-                GBool nullcheck;
-                GBool nullcheck2;
-
-                OGRStyleSymbol *poStyleSymbol = ( OGRStyleSymbol * ) poOgrST;
+                OGRStyleSymbol * const poStyleSymbol =
+                    dynamic_cast<OGRStyleSymbol *>(poOgrST);
+                if( poStyleSymbol == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "dynamic_cast failed.");
+                    delete poOgrSM;
+                    return NULL;
+                }
 
                 /***** id (kml icon) *****/
+                GBool nullcheck = FALSE;
+                const char *pszId = poStyleSymbol->Id( nullcheck );
 
-                const char *pszId = poStyleSymbol->Id ( nullcheck );
-
-                if ( !nullcheck ) {
-                    if ( !poKmlIconStyle)
-                        poKmlIconStyle = poKmlFactory->CreateIconStyle (  );
+                if( !nullcheck )
+                {
+                    if( !poKmlIconStyle)
+                        poKmlIconStyle = poKmlFactory->CreateIconStyle();
 
                     /***** split it at the ,'s *****/
-
                     char **papszTokens =
-                        CSLTokenizeString2 ( pszId, ",",
-                                             CSLT_HONOURSTRINGS | CSLT_STRIPLEADSPACES |
-                                             CSLT_STRIPENDSPACES );
-
-                    if ( papszTokens ) {
-
-                        /***** for lack of a better solution just take the first one *****/
-                        //todo come up with a better idea
-
-                        if ( papszTokens[0] ) {
+                        CSLTokenizeString2(
+                            pszId, ",",
+                            CSLT_HONOURSTRINGS | CSLT_STRIPLEADSPACES |
+                            CSLT_STRIPENDSPACES );
+
+                    if( papszTokens )
+                    {
+                        // Just take the first one.
+                        // TODO: Come up with a better idea.
+                        if( papszTokens[0] )
+                        {
                             IconStyleIconPtr poKmlIcon =
-                                poKmlFactory->CreateIconStyleIcon (  );
-                            poKmlIcon->set_href ( papszTokens[0] );
-                            poKmlIconStyle->set_icon ( poKmlIcon );
+                                poKmlFactory->CreateIconStyleIcon();
+                            poKmlIcon->set_href( papszTokens[0] );
+                            poKmlIconStyle->set_icon( poKmlIcon );
                         }
 
-                        CSLDestroy ( papszTokens );
-
+                        CSLDestroy( papszTokens );
                     }
-
-
                 }
 
                 /***** heading *****/
+                double heading = poStyleSymbol->Angle( nullcheck );
 
-                double heading = poStyleSymbol->Angle ( nullcheck );
-
-                if ( !nullcheck ) {
-                    if ( !poKmlIconStyle)
-                        poKmlIconStyle = poKmlFactory->CreateIconStyle (  );
-                    poKmlIconStyle->set_heading ( heading );
+                if( !nullcheck )
+                {
+                    if( !poKmlIconStyle)
+                        poKmlIconStyle = poKmlFactory->CreateIconStyle();
+                    poKmlIconStyle->set_heading( heading );
                 }
 
                 /***** scale *****/
+                double dfScale = poStyleSymbol->Size( nullcheck );
 
-                double dfScale = poStyleSymbol->Size ( nullcheck );
-
-                if ( !nullcheck ) {
-                    if ( !poKmlIconStyle)
-                        poKmlIconStyle = poKmlFactory->CreateIconStyle (  );
+                if( !nullcheck )
+                {
+                    if( !poKmlIconStyle )
+                        poKmlIconStyle = poKmlFactory->CreateIconStyle();
 
-                    poKmlIconStyle->set_scale ( dfScale );
+                    poKmlIconStyle->set_scale( dfScale );
                 }
 
                 /***** color *****/
-
-                int nR,
-                    nG,
-                    nB,
-                    nA;
-
-                const char *pszcolor = poStyleSymbol->Color ( nullcheck );
-
-                if ( !nullcheck && poOgrST->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
-                    poKmlIconStyle->set_color ( Color32 ( static_cast<GByte>(nA),
-                                                          static_cast<GByte>(nB),
-                                                          static_cast<GByte>(nG),
-                                                          static_cast<GByte>(nR) ) );
+                const char * const pszcolor =
+                    poStyleSymbol->Color( nullcheck );
+
+                int nR = 0;
+                int nG = 0;
+                int nB = 0;
+                int nA = 0;
+                if( !nullcheck &&
+                    poOgrST->GetRGBFromString( pszcolor, nR, nG, nB, nA ) )
+                {
+                    poKmlIconStyle->set_color(
+                        Color32 ( static_cast<GByte>(nA),
+                                  static_cast<GByte>(nB),
+                                  static_cast<GByte>(nG),
+                                  static_cast<GByte>(nR) ) );
                 }
 
                 /***** hotspot *****/
 
-                double dfDx = poStyleSymbol->SpacingX ( nullcheck );
-                double dfDy = poStyleSymbol->SpacingY ( nullcheck2 );
+                double dfDx = poStyleSymbol->SpacingX( nullcheck );
+                GBool nullcheck2 = FALSE;
+                double dfDy = poStyleSymbol->SpacingY( nullcheck2 );
 
-                if ( !nullcheck && !nullcheck2 ) {
-                    if ( !poKmlIconStyle)
-                        poKmlIconStyle = poKmlFactory->CreateIconStyle (  );
+                if( !nullcheck && !nullcheck2 )
+                {
+                    if( !poKmlIconStyle)
+                        poKmlIconStyle = poKmlFactory->CreateIconStyle();
 
-                    HotSpotPtr poKmlHotSpot = poKmlFactory->CreateHotSpot (  );
+                    HotSpotPtr poKmlHotSpot = poKmlFactory->CreateHotSpot();
 
-                    poKmlHotSpot->set_x ( dfDx );
-                    poKmlHotSpot->set_y ( dfDy );
+                    poKmlHotSpot->set_x( dfDx );
+                    poKmlHotSpot->set_y( dfDy );
 
-                    poKmlIconStyle->set_hotspot ( poKmlHotSpot );
+                    poKmlIconStyle->set_hotspot( poKmlHotSpot );
                 }
 
                 break;
@@ -270,109 +290,121 @@ StylePtr addstylestring2kml (
                 GBool nullcheck;
                 GBool nullcheck2;
 
-                OGRStyleLabel *poStyleLabel = ( OGRStyleLabel * ) poOgrST;
+                OGRStyleLabel *poStyleLabel =
+                    dynamic_cast<OGRStyleLabel *>(poOgrST);
+                if( poStyleLabel == NULL )
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "dynamic_cast failed.");
+                    delete poOgrSM;
+                    return NULL;
+                }
 
                 /***** color *****/
-
-                int nR,
-                    nG,
-                    nB,
-                    nA;
-
-                const char *pszcolor = poStyleLabel->ForeColor ( nullcheck );
-
-                if ( !nullcheck
-                     && poStyleLabel->GetRGBFromString ( pszcolor, nR, nG, nB, nA ) ) {
+                const char *pszcolor = poStyleLabel->ForeColor( nullcheck );
+
+                int nR = 0;
+                int nG = 0;
+                int nB = 0;
+                int nA = 0;
+                if( !nullcheck &&
+                    poStyleLabel->GetRGBFromString( pszcolor, nR, nG, nB, nA ) )
+                {
                     if( poKmlLabelStyle == NULL )
-                        poKmlLabelStyle = poKmlFactory->CreateLabelStyle (  );
-                    poKmlLabelStyle->set_color ( Color32 ( static_cast<GByte>(nA),
-                                                           static_cast<GByte>(nB),
-                                                           static_cast<GByte>(nG),
-                                                           static_cast<GByte>(nR) ) );
+                        poKmlLabelStyle = poKmlFactory->CreateLabelStyle();
+                    poKmlLabelStyle->set_color(
+                        Color32 ( static_cast<GByte>(nA),
+                                  static_cast<GByte>(nB),
+                                  static_cast<GByte>(nG),
+                                  static_cast<GByte>(nR) ) );
                 }
 
                 /***** scale *****/
+                double dfScale = poStyleLabel->Stretch( nullcheck );
 
-                double dfScale = poStyleLabel->Stretch ( nullcheck );
-
-                if ( !nullcheck ) {
+                if( !nullcheck )
+                {
                     dfScale /= 100.0;
                     if( poKmlLabelStyle == NULL )
-                        poKmlLabelStyle = poKmlFactory->CreateLabelStyle (  );
-                    poKmlLabelStyle->set_scale ( dfScale );
+                        poKmlLabelStyle = poKmlFactory->CreateLabelStyle();
+                    poKmlLabelStyle->set_scale( dfScale );
                 }
 
                 /***** heading *****/
+                const double heading = poStyleLabel->Angle( nullcheck );
 
-                double heading = poStyleLabel->Angle ( nullcheck );
-
-                if ( !nullcheck ) {
-                    if ( !poKmlIconStyle) {
-                        poKmlIconStyle = poKmlFactory->CreateIconStyle (  );
-                        IconStyleIconPtr poKmlIcon = poKmlFactory->CreateIconStyleIcon (  );
-                        poKmlIconStyle->set_icon ( poKmlIcon );
+                if( !nullcheck )
+                {
+                    if( !poKmlIconStyle)
+                    {
+                        poKmlIconStyle = poKmlFactory->CreateIconStyle();
+                        const IconStyleIconPtr poKmlIcon =
+                            poKmlFactory->CreateIconStyleIcon();
+                        poKmlIconStyle->set_icon( poKmlIcon );
                     }
 
-                    poKmlIconStyle->set_heading ( heading );
+                    poKmlIconStyle->set_heading( heading );
                 }
 
                 /***** hotspot *****/
+                const double dfDx = poStyleLabel->SpacingX( nullcheck );
+                const double dfDy = poStyleLabel->SpacingY( nullcheck2 );
 
-                double dfDx = poStyleLabel->SpacingX ( nullcheck );
-                double dfDy = poStyleLabel->SpacingY ( nullcheck2 );
-
-                if ( !nullcheck && !nullcheck2 ) {
-                    if ( !poKmlIconStyle) {
-                        poKmlIconStyle = poKmlFactory->CreateIconStyle (  );
-                        IconStyleIconPtr poKmlIcon = poKmlFactory->CreateIconStyleIcon (  );
-                        poKmlIconStyle->set_icon ( poKmlIcon );
+                if( !nullcheck && !nullcheck2 )
+                {
+                    if( !poKmlIconStyle)
+                    {
+                        poKmlIconStyle = poKmlFactory->CreateIconStyle();
+                        const IconStyleIconPtr poKmlIcon =
+                            poKmlFactory->CreateIconStyleIcon();
+                        poKmlIconStyle->set_icon( poKmlIcon );
                     }
 
-                    HotSpotPtr poKmlHotSpot = poKmlFactory->CreateHotSpot (  );
+                    HotSpotPtr poKmlHotSpot = poKmlFactory->CreateHotSpot();
 
-                    poKmlHotSpot->set_x ( dfDx );
-                    poKmlHotSpot->set_y ( dfDy );
+                    poKmlHotSpot->set_x( dfDx );
+                    poKmlHotSpot->set_y( dfDy );
 
-                    poKmlIconStyle->set_hotspot ( poKmlHotSpot );
+                    poKmlIconStyle->set_hotspot( poKmlHotSpot );
                 }
 
                 /***** label text *****/
+                const char * const pszText =
+                    poStyleLabel->TextString( nullcheck );
 
-                const char *pszText = poStyleLabel->TextString ( nullcheck );
-
-                if ( !nullcheck ) {
-                    if ( poKmlFeature ) {
-
+                if( !nullcheck && poKmlFeature != NULL )
+                {
                         poKmlFeature->set_name( pszText );
-                    }
                 }
 
                 break;
             }
-        case OGRSTCNone:
-        default:
-            break;
+            case OGRSTCNone:
+            default:
+            {
+                break;
+            }
         }
 
         delete poOgrST;
     }
 
-    if ( poKmlLineStyle || poKmlPolyStyle || poKmlIconStyle || poKmlLabelStyle )
+    if( poKmlLineStyle || poKmlPolyStyle || poKmlIconStyle || poKmlLabelStyle )
     {
         if( poKmlStyle == NULL )
-            poKmlStyle = poKmlFactory->CreateStyle (  );
+            poKmlStyle = poKmlFactory->CreateStyle();
 
-        if ( poKmlLineStyle )
-            poKmlStyle->set_linestyle ( poKmlLineStyle );
+        if( poKmlLineStyle )
+            poKmlStyle->set_linestyle( poKmlLineStyle );
 
-        if ( poKmlPolyStyle )
-            poKmlStyle->set_polystyle ( poKmlPolyStyle );
+        if( poKmlPolyStyle )
+            poKmlStyle->set_polystyle( poKmlPolyStyle );
 
-        if ( poKmlIconStyle )
-            poKmlStyle->set_iconstyle ( poKmlIconStyle );
+        if( poKmlIconStyle )
+            poKmlStyle->set_iconstyle( poKmlIconStyle );
 
-        if ( poKmlLabelStyle )
-            poKmlStyle->set_labelstyle ( poKmlLabelStyle );
+        if( poKmlLabelStyle )
+            poKmlStyle->set_labelstyle( poKmlLabelStyle );
     }
 
     delete poOgrSM;
@@ -384,224 +416,30 @@ StylePtr addstylestring2kml (
  kml2pen
 ******************************************************************************/
 
-OGRStylePen *kml2pen (
-    LineStylePtr poKmlLineStyle,
-    OGRStylePen *poOgrStylePen);
-
-/******************************************************************************
- kml2brush
-******************************************************************************/
-
-OGRStyleBrush *kml2brush (
-    PolyStylePtr poKmlPolyStyle,
-    OGRStyleBrush *poOgrStyleBrush);
-
-/******************************************************************************
- kml2symbol
-******************************************************************************/
-
-OGRStyleSymbol *kml2symbol (
-    IconStylePtr poKmlIconStyle,
-    OGRStyleSymbol *poOgrStyleSymbol);
-
-/******************************************************************************
- kml2label
-******************************************************************************/
-
-OGRStyleLabel *kml2label (
-    LabelStylePtr poKmlLabelStyle,
-    OGRStyleLabel *poOgrStyleLabel);
-
-/******************************************************************************
- kml2stylemgr
-******************************************************************************/
-
-void kml2stylestring (
-    StylePtr poKmlStyle,
-    OGRStyleMgr * poOgrSM )
-
-{
-
-    OGRStyleMgr * poOgrNewSM ;
-    OGRStyleTool *poOgrST = NULL;
-    OGRStyleTool *poOgrTmpST = NULL;
-    int i;
-
-    poOgrNewSM = new OGRStyleMgr( NULL );
-
-    /***** linestyle / pen *****/
-
-    if ( poKmlStyle->has_linestyle (  ) ) {
-
-        poOgrNewSM->InitStyleString ( NULL );
-
-        LineStylePtr poKmlLineStyle = poKmlStyle->get_linestyle (  );
-
-        poOgrTmpST = NULL;
-        for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) {
-            poOgrST = poOgrSM->GetPart ( i, NULL );
-
-            if ( !poOgrST )
-                continue;
-
-            if ( poOgrST->GetType ( ) == OGRSTCPen ) {
-                poOgrTmpST = poOgrST;
-            }
-            else {
-                poOgrNewSM->AddPart ( poOgrST );
-                delete poOgrST;
-            }
-        }
-
-        OGRStylePen *poOgrStylePen = kml2pen ( poKmlLineStyle,
-                                               ( OGRStylePen *) poOgrTmpST);
-
-        poOgrNewSM->AddPart ( poOgrStylePen );
-
-        delete poOgrStylePen;
-        poOgrSM->InitStyleString ( poOgrNewSM->GetStyleString(NULL) );
-
-    }
-
-    /***** polystyle / brush *****/
-
-    if ( poKmlStyle->has_polystyle (  ) ) {
-
-        poOgrNewSM->InitStyleString ( NULL );
-
-        PolyStylePtr poKmlPolyStyle = poKmlStyle->get_polystyle (  );
-
-        poOgrTmpST = NULL;
-        for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) {
-            poOgrST = poOgrSM->GetPart ( i, NULL );
-
-            if ( !poOgrST )
-                continue;
-
-            if ( poOgrST->GetType ( ) == OGRSTCBrush ) {
-                poOgrTmpST = poOgrST;
-            }
-            else {
-                poOgrNewSM->AddPart ( poOgrST );
-                delete poOgrST;
-            }
-        }
-
-        OGRStyleBrush *poOgrStyleBrush = kml2brush ( poKmlPolyStyle,
-                                                     ( OGRStyleBrush *) poOgrTmpST );
-
-        poOgrNewSM->AddPart ( poOgrStyleBrush );
-
-        delete poOgrStyleBrush;
-        poOgrSM->InitStyleString ( poOgrNewSM->GetStyleString(NULL) );
-
-    }
-
-    /***** iconstyle / symbol *****/
-
-    if ( poKmlStyle->has_iconstyle (  ) ) {
-
-        poOgrNewSM->InitStyleString ( NULL );
-
-        IconStylePtr poKmlIconStyle = poKmlStyle->get_iconstyle (  );
-
-        poOgrTmpST = NULL;
-        for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) {
-            poOgrST = poOgrSM->GetPart ( i, NULL );
-
-            if ( !poOgrST )
-                continue;
-
-            if ( poOgrST->GetType ( ) == OGRSTCSymbol ) {
-                poOgrTmpST = poOgrST;
-            }
-            else {
-                poOgrNewSM->AddPart ( poOgrST );
-                delete poOgrST;
-            }
-        }
-
-        OGRStyleSymbol *poOgrStyleSymbol = kml2symbol ( poKmlIconStyle,
-                                                     ( OGRStyleSymbol *) poOgrTmpST );
-
-        poOgrNewSM->AddPart ( poOgrStyleSymbol );
-
-        delete poOgrStyleSymbol;
-        poOgrSM->InitStyleString ( poOgrNewSM->GetStyleString(NULL) );
-
-    }
-
-    /***** labelstyle / label *****/
-
-    if ( poKmlStyle->has_labelstyle (  ) ) {
-
-        poOgrNewSM->InitStyleString ( NULL );
-
-        LabelStylePtr poKmlLabelStyle = poKmlStyle->get_labelstyle (  );
-
-        poOgrTmpST = NULL;
-        for ( i = 0; i < poOgrSM->GetPartCount ( NULL ); i++ ) {
-            poOgrST = poOgrSM->GetPart ( i, NULL );
-
-            if ( !poOgrST )
-                continue;
-
-            if ( poOgrST->GetType ( ) == OGRSTCLabel ) {
-                poOgrTmpST = poOgrST;
-            }
-            else {
-                poOgrNewSM->AddPart ( poOgrST );
-                delete poOgrST;
-            }
-        }
-
-        OGRStyleLabel *poOgrStyleLabel = kml2label ( poKmlLabelStyle,
-                                                     ( OGRStyleLabel *) poOgrTmpST );
-
-        poOgrNewSM->AddPart ( poOgrStyleLabel );
-
-        delete poOgrStyleLabel;
-        poOgrSM->InitStyleString ( poOgrNewSM->GetStyleString(NULL) );
-
-    }
-
-    delete poOgrNewSM;
-
-}
-
-
-
-/******************************************************************************
- kml2pen
-******************************************************************************/
-
-OGRStylePen *kml2pen (
-    LineStylePtr poKmlLineStyle,
-    OGRStylePen *poOgrStylePen)
+static
+OGRStylePen *kml2pen( LineStylePtr poKmlLineStyle, OGRStylePen *poOgrStylePen )
 {
-
-    if (!poOgrStylePen)
-        poOgrStylePen = new OGRStylePen (  );
+    if( !poOgrStylePen )
+        poOgrStylePen = new OGRStylePen();
 
     /***** <LineStyle> should always have a width in pixels *****/
-
     poOgrStylePen->SetUnit(OGRSTUPixel);
 
     /***** width *****/
-
-    if ( poKmlLineStyle->has_width (  ) )
-        poOgrStylePen->SetWidth ( poKmlLineStyle->get_width (  ) );
+    if( poKmlLineStyle->has_width() )
+        poOgrStylePen->SetWidth( poKmlLineStyle->get_width() );
 
     /***** color *****/
-
-    if ( poKmlLineStyle->has_color (  ) ) {
-        Color32 poKmlColor = poKmlLineStyle->get_color (  );
-        char szColor[10] = { };
-        snprintf ( szColor, sizeof ( szColor ), "#%02X%02X%02X%02X",
-                   poKmlColor.get_red (  ),
-                   poKmlColor.get_green (  ),
-                   poKmlColor.get_blue (  ), poKmlColor.get_alpha (  ) );
-        poOgrStylePen->SetColor ( szColor );
+    if( poKmlLineStyle->has_color() )
+    {
+        Color32 poKmlColor = poKmlLineStyle->get_color();
+        char szColor[10] = {};
+        snprintf( szColor, sizeof( szColor ), "#%02X%02X%02X%02X",
+                  poKmlColor.get_red(),
+                  poKmlColor.get_green(),
+                  poKmlColor.get_blue(),
+                  poKmlColor.get_alpha() );
+        poOgrStylePen->SetColor( szColor );
     }
 
     return poOgrStylePen;
@@ -611,24 +449,25 @@ OGRStylePen *kml2pen (
  kml2brush
 ******************************************************************************/
 
-OGRStyleBrush *kml2brush (
+static
+OGRStyleBrush *kml2brush(
     PolyStylePtr poKmlPolyStyle,
-    OGRStyleBrush *poOgrStyleBrush)
+    OGRStyleBrush *poOgrStyleBrush )
 {
-
-    if (!poOgrStyleBrush)
-        poOgrStyleBrush = new OGRStyleBrush (  );
+    if( !poOgrStyleBrush )
+        poOgrStyleBrush = new OGRStyleBrush();
 
     /***** color *****/
-
-    if ( poKmlPolyStyle->has_color (  ) ) {
-        Color32 poKmlColor = poKmlPolyStyle->get_color (  );
-        char szColor[10] = { };
-        snprintf ( szColor, sizeof ( szColor ), "#%02X%02X%02X%02X",
-                   poKmlColor.get_red (  ),
-                   poKmlColor.get_green (  ),
-                   poKmlColor.get_blue (  ), poKmlColor.get_alpha (  ) );
-        poOgrStyleBrush->SetForeColor ( szColor );
+    if( poKmlPolyStyle->has_color() )
+    {
+        Color32 poKmlColor = poKmlPolyStyle->get_color();
+        char szColor[10] = {};
+        snprintf( szColor, sizeof( szColor ), "#%02X%02X%02X%02X",
+                  poKmlColor.get_red(),
+                  poKmlColor.get_green(),
+                  poKmlColor.get_blue(),
+                  poKmlColor.get_alpha() );
+        poOgrStyleBrush->SetForeColor( szColor );
     }
 
     return poOgrStyleBrush;
@@ -638,60 +477,58 @@ OGRStyleBrush *kml2brush (
  kml2symbol
 ******************************************************************************/
 
-OGRStyleSymbol *kml2symbol (
+static
+OGRStyleSymbol *kml2symbol(
     IconStylePtr poKmlIconStyle,
-    OGRStyleSymbol *poOgrStyleSymbol)
+    OGRStyleSymbol *poOgrStyleSymbol )
 {
-
-    if (!poOgrStyleSymbol)
-        poOgrStyleSymbol = new OGRStyleSymbol (  );
+    if( !poOgrStyleSymbol )
+        poOgrStyleSymbol = new OGRStyleSymbol();
 
     /***** id (kml icon) *****/
+    if( poKmlIconStyle->has_icon() )
+    {
+        IconStyleIconPtr poKmlIcon = poKmlIconStyle->get_icon();
 
-    if ( poKmlIconStyle->has_icon (  ) ) {
-        IconStyleIconPtr poKmlIcon = poKmlIconStyle->get_icon (  );
-
-        if ( poKmlIcon->has_href (  ) ) {
+        if( poKmlIcon->has_href() )
+        {
             std::string oIcon = "\"";
-            oIcon.append ( poKmlIcon->get_href (  ).c_str (  ) );
-            oIcon.append ( "\"" );
-            poOgrStyleSymbol->SetId ( oIcon.c_str (  ) );
-
+            oIcon.append( poKmlIcon->get_href().c_str() );
+            oIcon.append( "\"" );
+            poOgrStyleSymbol->SetId( oIcon.c_str() );
         }
     }
 
     /***** heading *****/
-
-    if ( poKmlIconStyle->has_heading (  ) )
-        poOgrStyleSymbol->SetAngle ( poKmlIconStyle->get_heading (  ) );
+    if( poKmlIconStyle->has_heading() )
+        poOgrStyleSymbol->SetAngle( poKmlIconStyle->get_heading() );
 
     /***** scale *****/
-
-    if ( poKmlIconStyle->has_scale (  ) )
-        poOgrStyleSymbol->SetSize ( poKmlIconStyle->get_scale (  ) );
+    if( poKmlIconStyle->has_scale() )
+        poOgrStyleSymbol->SetSize( poKmlIconStyle->get_scale() );
 
     /***** color *****/
-
-    if ( poKmlIconStyle->has_color (  ) ) {
-        Color32 poKmlColor = poKmlIconStyle->get_color (  );
-        char szColor[10] = { };
-        snprintf ( szColor, sizeof ( szColor ), "#%02X%02X%02X%02X",
-                   poKmlColor.get_red (  ),
-                   poKmlColor.get_green (  ),
-                   poKmlColor.get_blue (  ), poKmlColor.get_alpha (  ) );
-        poOgrStyleSymbol->SetColor ( szColor );
+    if( poKmlIconStyle->has_color() )
+    {
+        Color32 poKmlColor = poKmlIconStyle->get_color();
+        char szColor[10] = {};
+        snprintf( szColor, sizeof( szColor ), "#%02X%02X%02X%02X",
+                  poKmlColor.get_red(),
+                  poKmlColor.get_green(),
+                  poKmlColor.get_blue(),
+                  poKmlColor.get_alpha() );
+        poOgrStyleSymbol->SetColor( szColor );
     }
 
     /***** hotspot *****/
+    if( poKmlIconStyle->has_hotspot() )
+    {
+        const HotSpotPtr poKmlHotSpot = poKmlIconStyle->get_hotspot();
 
-    if ( poKmlIconStyle->has_hotspot (  ) ) {
-        HotSpotPtr poKmlHotSpot = poKmlIconStyle->get_hotspot (  );
-
-        if ( poKmlHotSpot->has_x (  ) )
-            poOgrStyleSymbol->SetSpacingX ( poKmlHotSpot->get_x (  ) );
-        if ( poKmlHotSpot->has_y (  ) )
-            poOgrStyleSymbol->SetSpacingY ( poKmlHotSpot->get_y (  ) );
-
+        if( poKmlHotSpot->has_x() )
+            poOgrStyleSymbol->SetSpacingX( poKmlHotSpot->get_x() );
+        if( poKmlHotSpot->has_y() )
+            poOgrStyleSymbol->SetSpacingY( poKmlHotSpot->get_y() );
     }
 
     return poOgrStyleSymbol;
@@ -701,28 +538,30 @@ OGRStyleSymbol *kml2symbol (
  kml2label
 ******************************************************************************/
 
-OGRStyleLabel *kml2label (
+static
+OGRStyleLabel *kml2label(
     LabelStylePtr poKmlLabelStyle,
-    OGRStyleLabel *poOgrStyleLabel)
+    OGRStyleLabel *poOgrStyleLabel )
 {
-
-    if (!poOgrStyleLabel)
-        poOgrStyleLabel = new OGRStyleLabel (  );
+    if( !poOgrStyleLabel )
+        poOgrStyleLabel = new OGRStyleLabel();
 
     /***** color *****/
-
-    if ( poKmlLabelStyle->has_color (  ) ) {
-        Color32 poKmlColor = poKmlLabelStyle->get_color (  );
-        char szColor[10] = { };
-        snprintf ( szColor, sizeof ( szColor ), "#%02X%02X%02X%02X",
-                   poKmlColor.get_red (  ),
-                   poKmlColor.get_green (  ),
-                   poKmlColor.get_blue (  ), poKmlColor.get_alpha (  ) );
-        poOgrStyleLabel->SetForColor ( szColor );
+    if( poKmlLabelStyle->has_color() )
+    {
+        Color32 poKmlColor = poKmlLabelStyle->get_color();
+        char szColor[10] = {};
+        snprintf( szColor, sizeof( szColor ), "#%02X%02X%02X%02X",
+                  poKmlColor.get_red(),
+                  poKmlColor.get_green(),
+                  poKmlColor.get_blue(),
+                  poKmlColor.get_alpha() );
+        poOgrStyleLabel->SetForColor( szColor );
     }
 
-    if ( poKmlLabelStyle->has_scale (  ) ) {
-        double dfScale = poKmlLabelStyle->get_scale (  );
+    if( poKmlLabelStyle->has_scale() )
+    {
+        double dfScale = poKmlLabelStyle->get_scale();
         dfScale *= 100.0;
 
         poOgrStyleLabel->SetStretch(dfScale);
@@ -732,75 +571,218 @@ OGRStyleLabel *kml2label (
 }
 
 /******************************************************************************
- function to add a kml style to a style table
+ Function to add a kml style to a style table.
 ******************************************************************************/
 
-static void kml2styletable (
+static void kml2styletable(
     OGRStyleTable * poOgrStyleTable,
     StylePtr poKmlStyle )
 {
+    /***** No reason to add it if it don't have an id. *****/
+    if( !poKmlStyle->has_id() )
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "ERROR parsing kml Style: No id" );
+        return;
+    }
+
+    OGRStyleMgr *poOgrSM = new OGRStyleMgr( poOgrStyleTable );
+
+    poOgrSM->InitStyleString( NULL );
+
+    /***** read the style *****/
+    kml2stylestring( poKmlStyle, poOgrSM );
+
+    /***** add the style to the style table *****/
+    const std::string oName = poKmlStyle->get_id();
+
+    poOgrSM->AddStyle(
+        CPLString().Printf( "%s", oName.c_str() ), NULL );
+
+    /***** Cleanup the style manager. *****/
+    delete poOgrSM;
+}
+
+/******************************************************************************
+ Function to follow the kml stylemap if one exists.
+******************************************************************************/
+
+StyleSelectorPtr StyleFromStyleSelector(
+    const StyleSelectorPtr& poKmlStyleSelector,
+    OGRStyleTable * poStyleTable )
+{
+    /***** Is it a style? *****/
+    if( poKmlStyleSelector->IsA( kmldom::Type_Style) )
+        return poKmlStyleSelector;
+
+    /***** Is it a style map? *****/
 
+    else if( poKmlStyleSelector->IsA( kmldom::Type_StyleMap ) )
+        return StyleFromStyleMap(
+            kmldom::AsStyleMap(poKmlStyleSelector), poStyleTable);
 
-    /***** no reason to add it if it don't have an id *****/
+    /***** Not a style or a style map. *****/
+    return NULL;
+}
 
-    if ( poKmlStyle->has_id (  ) ) {
+/******************************************************************************
+ kml2stylemgr
+******************************************************************************/
 
-        OGRStyleMgr *poOgrSM = new OGRStyleMgr ( poOgrStyleTable );
+void kml2stylestring( StylePtr poKmlStyle, OGRStyleMgr * poOgrSM )
 
-        poOgrSM->InitStyleString ( NULL );
+{
+    OGRStyleMgr * const poOgrNewSM = new OGRStyleMgr( NULL );
 
-        /***** read the style *****/
+    /***** linestyle / pen *****/
+    if( poKmlStyle->has_linestyle() )
+    {
+        poOgrNewSM->InitStyleString( NULL );
 
-        kml2stylestring ( poKmlStyle, poOgrSM );
+        LineStylePtr poKmlLineStyle = poKmlStyle->get_linestyle();
 
-        /***** add the style to the style table *****/
+        OGRStyleTool *poOgrTmpST = NULL;
+        for( int i = 0; i < poOgrSM->GetPartCount( NULL ); i++ )
+        {
+            OGRStyleTool *poOgrST = poOgrSM->GetPart( i, NULL );
 
-        const std::string oName = poKmlStyle->get_id (  );
+            if( !poOgrST )
+                continue;
 
+            if( poOgrST->GetType() == OGRSTCPen )
+            {
+                poOgrTmpST = poOgrST;
+            }
+            else
+            {
+                poOgrNewSM->AddPart( poOgrST );
+                delete poOgrST;
+            }
+        }
 
-        poOgrSM->AddStyle ( CPLString (  ).Printf ( "%s",
-                                                    oName.c_str (  ) ), NULL );
+        OGRStylePen *poOgrStylePen =
+            kml2pen( poKmlLineStyle,
+                     ( OGRStylePen *) poOgrTmpST);
 
-        /***** cleanup the style manager *****/
+        poOgrNewSM->AddPart( poOgrStylePen );
 
-        delete poOgrSM;
+        delete poOgrStylePen;
+        poOgrSM->InitStyleString( poOgrNewSM->GetStyleString(NULL) );
     }
 
-    else {
-        CPLError ( CE_Failure, CPLE_AppDefined,
-                   "ERROR parsing kml Style: No id" );
+    /***** polystyle / brush *****/
+    if( poKmlStyle->has_polystyle() )
+    {
+        poOgrNewSM->InitStyleString( NULL );
+
+        PolyStylePtr poKmlPolyStyle = poKmlStyle->get_polystyle();
+
+        OGRStyleTool *poOgrTmpST = NULL;
+        for( int i = 0; i < poOgrSM->GetPartCount( NULL ); i++ )
+        {
+            OGRStyleTool *poOgrST = poOgrSM->GetPart( i, NULL );
+
+            if( !poOgrST )
+                continue;
+
+            if( poOgrST->GetType() == OGRSTCBrush )
+            {
+                poOgrTmpST = poOgrST;
+            }
+            else
+            {
+                poOgrNewSM->AddPart( poOgrST );
+                delete poOgrST;
+            }
+        }
+
+        OGRStyleBrush *poOgrStyleBrush =
+            kml2brush( poKmlPolyStyle,
+                       ( OGRStyleBrush *) poOgrTmpST );
+
+        poOgrNewSM->AddPart( poOgrStyleBrush );
+
+        delete poOgrStyleBrush;
+        poOgrSM->InitStyleString( poOgrNewSM->GetStyleString(NULL) );
     }
 
-    return;
-}
+    /***** iconstyle / symbol *****/
+    if( poKmlStyle->has_iconstyle() )
+    {
+        poOgrNewSM->InitStyleString( NULL );
 
-/******************************************************************************
- function to follow the kml stylemap if one exists
-******************************************************************************/
+        IconStylePtr poKmlIconStyle = poKmlStyle->get_iconstyle();
 
-StyleSelectorPtr StyleFromStyleSelector(
-    const StyleSelectorPtr& poKmlStyleSelector,
-    OGRStyleTable * poStyleTable)
-{
+        OGRStyleTool *poOgrTmpST = NULL;
+        for( int i = 0; i < poOgrSM->GetPartCount( NULL ); i++ )
+        {
+            OGRStyleTool *poOgrST = poOgrSM->GetPart( i, NULL );
 
-    /***** is it a style? *****/
+            if( !poOgrST )
+                continue;
 
-    if ( poKmlStyleSelector->IsA( kmldom::Type_Style) )
-        return poKmlStyleSelector;
+            if( poOgrST->GetType() == OGRSTCSymbol )
+            {
+                poOgrTmpST = poOgrST;
+            }
+            else
+            {
+                poOgrNewSM->AddPart( poOgrST );
+                delete poOgrST;
+            }
+        }
 
-    /***** is it a style map? *****/
+        OGRStyleSymbol *poOgrStyleSymbol =
+            kml2symbol( poKmlIconStyle,
+                        ( OGRStyleSymbol *) poOgrTmpST );
 
-    else if ( poKmlStyleSelector->IsA( kmldom::Type_StyleMap) )
-        return StyleFromStyleMap(kmldom::AsStyleMap(poKmlStyleSelector), poStyleTable);
+        poOgrNewSM->AddPart( poOgrStyleSymbol );
 
-    /***** not a style or a style map *****/
+        delete poOgrStyleSymbol;
+        poOgrSM->InitStyleString( poOgrNewSM->GetStyleString(NULL) );
+    }
 
-    return NULL;
-}
+    /***** labelstyle / label *****/
+    if( poKmlStyle->has_labelstyle() )
+    {
+        poOgrNewSM->InitStyleString( NULL );
+
+        LabelStylePtr poKmlLabelStyle = poKmlStyle->get_labelstyle();
+
+        OGRStyleTool *poOgrTmpST = NULL;
+        for( int i = 0; i < poOgrSM->GetPartCount( NULL ); i++ )
+        {
+            OGRStyleTool *poOgrST = poOgrSM->GetPart( i, NULL );
 
+            if( !poOgrST )
+                continue;
+
+            if( poOgrST->GetType() == OGRSTCLabel )
+            {
+                poOgrTmpST = poOgrST;
+            }
+            else
+            {
+                poOgrNewSM->AddPart( poOgrST );
+                delete poOgrST;
+            }
+        }
+
+        OGRStyleLabel *poOgrStyleLabel =
+            kml2label( poKmlLabelStyle,
+                       ( OGRStyleLabel *) poOgrTmpST );
+
+        poOgrNewSM->AddPart( poOgrStyleLabel );
+
+        delete poOgrStyleLabel;
+        poOgrSM->InitStyleString( poOgrNewSM->GetStyleString(NULL) );
+    }
+
+    delete poOgrNewSM;
+}
 
 /******************************************************************************
- function to get the container from the kmlroot
+ Function to get the container from the kmlroot.
 
  Args:          poKmlRoot   the root element
 
@@ -809,105 +791,101 @@ StyleSelectorPtr StyleFromStyleSelector(
 
 ******************************************************************************/
 
-static ContainerPtr MyGetContainerFromRoot (
+static ContainerPtr MyGetContainerFromRoot(
     KmlFactory *m_poKmlFactory, ElementPtr poKmlRoot )
 {
     ContainerPtr poKmlContainer = NULL;
 
-    if ( poKmlRoot ) {
-
+    if( poKmlRoot )
+    {
         /***** skip over the <kml> we want the container *****/
+        if( poKmlRoot->IsA( kmldom::Type_kml ) )
+        {
+            KmlPtr poKmlKml = AsKml( poKmlRoot );
 
-        if ( poKmlRoot->IsA ( kmldom::Type_kml ) ) {
-
-            KmlPtr poKmlKml = AsKml ( poKmlRoot );
-
-            if ( poKmlKml->has_feature (  ) ) {
-                FeaturePtr poKmlFeat = poKmlKml->get_feature (  );
+            if( poKmlKml->has_feature() )
+            {
+                FeaturePtr poKmlFeat = poKmlKml->get_feature();
 
-                if ( poKmlFeat->IsA ( kmldom::Type_Container ) )
-                    poKmlContainer = AsContainer ( poKmlFeat );
-                else if ( poKmlFeat->IsA ( kmldom::Type_Placemark ) )
+                if( poKmlFeat->IsA( kmldom::Type_Container ) )
                 {
-                    poKmlContainer = m_poKmlFactory->CreateDocument (  );
-                    poKmlContainer->add_feature ( kmldom::AsFeature(kmlengine::Clone(poKmlFeat)) );
+                    poKmlContainer = AsContainer( poKmlFeat );
+                }
+                else if( poKmlFeat->IsA( kmldom::Type_Placemark ) )
+                {
+                    poKmlContainer = m_poKmlFactory->CreateDocument();
+                    poKmlContainer->add_feature(
+                        kmldom::AsFeature(kmlengine::Clone(poKmlFeat)) );
                 }
             }
         }
-
-        else if ( poKmlRoot->IsA ( kmldom::Type_Container ) )
-            poKmlContainer = AsContainer ( poKmlRoot );
+        else if( poKmlRoot->IsA( kmldom::Type_Container ) )
+        {
+            poKmlContainer = AsContainer( poKmlRoot );
+        }
     }
 
     return poKmlContainer;
 }
 
-
-
 static StyleSelectorPtr StyleFromStyleURL(
     const StyleMapPtr& stylemap,
-    const string styleurl,
-    OGRStyleTable * poStyleTable)
+    const string& styleurl,
+    OGRStyleTable * poStyleTable )
 {
-    // TODO:: Parse the styleURL
-
-    char *pszUrl = CPLStrdup ( styleurl.c_str (  ) );
-    char *pszStyleMapId = CPLStrdup ( stylemap->get_id().c_str (  ) );
+    // TODO:: Parse the styleURL.
+    char *pszUrl = CPLStrdup( styleurl.c_str() );
+    char *pszStyleMapId = CPLStrdup( stylemap->get_id().c_str() );
 
     /***** Is it an internal style ref that starts with a #? *****/
-
-    if ( *pszUrl == '#' && poStyleTable ) {
-
+    if( *pszUrl == '#' && poStyleTable )
+    {
         /***** Search the style table for the style we *****/
         /***** want and copy it back into the table.   *****/
-
-        const char *pszTest = NULL;
-        pszTest = poStyleTable->Find ( pszUrl + 1 );
-        if ( pszTest ) {
+        const char *pszTest = poStyleTable->Find( pszUrl + 1 );
+        if( pszTest )
+        {
             poStyleTable->AddStyle(pszStyleMapId, pszTest);
         }
     }
 
     /***** We have a real URL and need to go out and fetch it *****/
     /***** FIXME this could be a relative path in a kmz *****/
-
-    else if ( strchr(pszUrl, '#') ) {
-
-        const char *pszFetch = CPLGetConfigOption ( "LIBKML_EXTERNAL_STYLE", "no" );
-        if ( CPLTestBool(pszFetch) ) {
-
+    else if( strchr(pszUrl, '#') )
+    {
+        const char *pszFetch =
+            CPLGetConfigOption( "LIBKML_EXTERNAL_STYLE", "no" );
+        if( CPLTestBool(pszFetch) )
+        {
             /***** Lets go out and fetch the style from the external URL *****/
-
             char *pszUrlTmp = CPLStrdup(pszUrl);
             char *pszPound = strchr(pszUrlTmp, '#');
             char *pszRemoteStyleName = NULL;
             // Chop off the stuff (style id) after the URL
-            if (pszPound != NULL) {
+            if( pszPound != NULL )
+            {
                 *pszPound = '\0';
                 pszRemoteStyleName = pszPound + 1;
             }
 
             /***** try it as a url then a file *****/
-
             VSILFILE *fp = NULL;
-            if ( (fp = VSIFOpenL( CPLFormFilename( "/vsicurl/",
+            if( (fp = VSIFOpenL( CPLFormFilename( "/vsicurl/",
                                                    pszUrlTmp,
-                                                  NULL), "r" )) != NULL
+                                                   NULL), "r" )) != NULL
                  ||  (fp = VSIFOpenL( pszUrlTmp, "r" )) != NULL )
             {
-                char szbuf[1025];
+                char szbuf[1025] = {};
                 std::string oStyle = "";
 
                 /***** loop, read and copy to a string *****/
-
-                size_t nRead;
                 do {
-                    nRead = VSIFReadL(szbuf, 1, sizeof(szbuf) - 1, fp);
-                    if (nRead == 0)
+                    const size_t nRead =
+                        VSIFReadL(szbuf, 1, sizeof(szbuf) - 1, fp);
+                    if(nRead == 0)
                         break;
 
                     /***** copy buf to the string *****/
-
                     szbuf[nRead] = '\0';
                     oStyle.append( szbuf );
                 } while (!VSIFEofL(fp));
@@ -915,86 +893,83 @@ static StyleSelectorPtr StyleFromStyleURL(
                 VSIFCloseL(fp);
 
                 /***** parse the kml into the dom *****/
-
                 std::string oKmlErrors;
-                ElementPtr poKmlRoot = kmldom::Parse ( oStyle, &oKmlErrors );
+                ElementPtr poKmlRoot = kmldom::Parse( oStyle, &oKmlErrors );
 
-                if ( !poKmlRoot ) {
-                    CPLError ( CE_Failure, CPLE_OpenFailed,
-                               "ERROR parsing style kml %s :%s",
-                               pszUrlTmp, oKmlErrors.c_str (  ) );
+                if( !poKmlRoot )
+                {
+                    CPLError( CE_Warning, CPLE_OpenFailed,
+                              "ERROR parsing style kml %s :%s",
+                              pszUrlTmp, oKmlErrors.c_str() );
                     CPLFree(pszUrlTmp);
-                    CPLFree ( pszUrl );
-                    CPLFree ( pszStyleMapId );
+                    CPLFree(pszUrl);
+                    CPLFree(pszStyleMapId);
 
                     return NULL;
                 }
 
                 /***** get the root container *****/
-
+                kmldom::KmlFactory* poKmlFactory =
+                    kmldom::KmlFactory::GetFactory();
                 ContainerPtr poKmlContainer;
-                kmldom::KmlFactory* poKmlFactory = kmldom::KmlFactory::GetFactory();
-                if ( !( poKmlContainer = MyGetContainerFromRoot ( poKmlFactory, poKmlRoot ) ) ) {
+                if( !( poKmlContainer =
+                      MyGetContainerFromRoot( poKmlFactory, poKmlRoot ) ) )
+                {
                     CPLFree(pszUrlTmp);
-                    CPLFree ( pszUrl );
-                    CPLFree ( pszStyleMapId );
+                    CPLFree(pszUrl);
+                    CPLFree(pszStyleMapId);
 
                     return NULL;
                 }
 
                 /**** parse the styles into the table *****/
-
-                ParseStyles ( AsDocument ( poKmlContainer ), &poStyleTable );
+                ParseStyles( AsDocument( poKmlContainer ), &poStyleTable );
 
                 /***** look for the style we need to map to in the table *****/
-
                 const char *pszTest = NULL;
                 pszTest = poStyleTable->Find(pszRemoteStyleName);
 
                 /***** if found copy it to the table as a new style *****/
-                if ( pszTest )
+                if( pszTest )
                     poStyleTable->AddStyle(pszStyleMapId, pszTest);
-
             }
             CPLFree(pszUrlTmp);
         }
     }
 
     /***** FIXME Add support here for relative links inside KML. *****/
-
-    CPLFree ( pszUrl );
-    CPLFree ( pszStyleMapId );
+    CPLFree( pszUrl );
+    CPLFree( pszStyleMapId );
 
     return NULL;
 }
 
 StyleSelectorPtr StyleFromStyleMap(
     const StyleMapPtr& poKmlStyleMap,
-    OGRStyleTable * poStyleTable)
+    OGRStyleTable * poStyleTable )
 {
-
     /***** check the config option to see if the    *****/
     /***** user wants normal or highlighted mapping *****/
-
-    const char *pszStyleMapKey = CPLGetConfigOption ( "LIBKML_STYLEMAP_KEY", "normal" );
-    int nStyleMapKey = STYLESTATE_NORMAL;
-    if ( EQUAL (pszStyleMapKey, "highlight"))
-         nStyleMapKey = STYLESTATE_HIGHLIGHT;
+    const char *pszStyleMapKey =
+        CPLGetConfigOption( "LIBKML_STYLEMAP_KEY", "normal" );
+    const int nStyleMapKey =
+        EQUAL(pszStyleMapKey, "highlight") ?
+            STYLESTATE_HIGHLIGHT: STYLESTATE_NORMAL;
 
     /*****  Loop through the stylemap pairs and look for the "normal" one *****/
-
-    for (size_t i = 0; i < poKmlStyleMap->get_pair_array_size(); ++i) {
+    for( size_t i = 0; i < poKmlStyleMap->get_pair_array_size(); ++i )
+    {
         PairPtr myPair = poKmlStyleMap->get_pair_array_at(i);
 
         /***** is it the right one of the pair? *****/
-
-        if ( myPair->get_key() == nStyleMapKey ) {
-
-            if (myPair->has_styleselector())
-                return StyleFromStyleSelector(myPair->get_styleselector(), poStyleTable);
-
-            else if (myPair->has_styleurl())
-                return StyleFromStyleURL(poKmlStyleMap, myPair->get_styleurl(), poStyleTable);
+        if( myPair->get_key() == nStyleMapKey )
+        {
+            if( myPair->has_styleselector() )
+                return StyleFromStyleSelector(myPair->get_styleselector(),
+                                              poStyleTable);
+            else if(myPair->has_styleurl() )
+                return StyleFromStyleURL(poKmlStyleMap, myPair->get_styleurl(),
+                                         poStyleTable);
         }
     }
 
@@ -1002,47 +977,41 @@ StyleSelectorPtr StyleFromStyleMap(
 }
 
 /******************************************************************************
- function to parse a style table out of a document
+ Function to parse a style table out of a document.
 ******************************************************************************/
 
-void ParseStyles (
+void ParseStyles(
     DocumentPtr poKmlDocument,
     OGRStyleTable ** poStyleTable )
 {
-
     /***** if document is null just bail now *****/
-
-    if ( !poKmlDocument )
+    if( !poKmlDocument )
         return;
 
     /***** loop over the Styles *****/
-
-    size_t nKmlStyles = poKmlDocument->get_styleselector_array_size (  );
-    size_t iKmlStyle;
+    const size_t nKmlStyles = poKmlDocument->get_styleselector_array_size();
 
     /***** Lets first build the style table.    *****/
     /***** to begin this is just proper styles. *****/
-
-    for ( iKmlStyle = 0; iKmlStyle < nKmlStyles; iKmlStyle++ ) {
+    for( size_t iKmlStyle = 0; iKmlStyle < nKmlStyles; iKmlStyle++ )
+    {
         StyleSelectorPtr poKmlStyle =
-            poKmlDocument->get_styleselector_array_at ( iKmlStyle );
+            poKmlDocument->get_styleselector_array_at( iKmlStyle );
 
         /***** Everything that is not a style you skip *****/
-
-        if ( !poKmlStyle->IsA ( kmldom::Type_Style ) )
+        if( !poKmlStyle->IsA( kmldom::Type_Style ) )
             continue;
 
         /***** We need to check to see if this is the first style. if it *****/
         /***** is we will not have a style table and need to create one  *****/
 
-        if ( !*poStyleTable )
-            *poStyleTable = new OGRStyleTable (  );
+        if( !*poStyleTable )
+            *poStyleTable = new OGRStyleTable();
 
         /***** TODO:: Not sure we need to do this as we seem *****/
         /***** to cast to element and then back to style.    *****/
-
-        ElementPtr poKmlElement = AsElement ( poKmlStyle );
-        kml2styletable ( *poStyleTable, AsStyle ( poKmlElement ) );
+        ElementPtr poKmlElement = AsElement( poKmlStyle );
+        kml2styletable( *poStyleTable, AsStyle( poKmlElement ) );
     }
 
     /***** Now we have to loop back around and get the style maps. We    *****/
@@ -1050,87 +1019,86 @@ void ParseStyles (
     /***** and we are just looping reference styles that are farther     *****/
     /***** down in the file. Order through the XML as it is parsed.      *****/
 
-    for ( iKmlStyle = 0; iKmlStyle < nKmlStyles; iKmlStyle++ ) {
+    for( size_t iKmlStyle = 0; iKmlStyle < nKmlStyles; iKmlStyle++ )
+    {
         StyleSelectorPtr poKmlStyle =
-            poKmlDocument->get_styleselector_array_at ( iKmlStyle );
+            poKmlDocument->get_styleselector_array_at( iKmlStyle );
 
         /***** Everything that is not a stylemap you skip *****/
-
-        if ( !poKmlStyle->IsA ( kmldom::Type_StyleMap ) )
+        if( !poKmlStyle->IsA( kmldom::Type_StyleMap ) )
             continue;
 
         /***** We need to check to see if this is the first style. if it *****/
         /***** is we will not have a style table and need to create one  *****/
-
-        if ( !*poStyleTable )
-            *poStyleTable = new OGRStyleTable (  );
+        if( !*poStyleTable )
+            *poStyleTable = new OGRStyleTable();
 
         /***** copy the style the style map points to since *****/
 
-        char *pszStyleMapId = CPLStrdup ( poKmlStyle->get_id().c_str (  ) );
-        poKmlStyle = StyleFromStyleMap(kmldom::AsStyleMap(poKmlStyle), *poStyleTable);
-        if (poKmlStyle == NULL) {
+        char *pszStyleMapId = CPLStrdup( poKmlStyle->get_id().c_str() );
+        poKmlStyle =
+            StyleFromStyleMap(kmldom::AsStyleMap(poKmlStyle), *poStyleTable);
+        if( poKmlStyle == NULL )
+        {
             CPLFree(pszStyleMapId);
             continue;
         }
-        char *pszStyleId = CPLStrdup ( poKmlStyle->get_id().c_str (  ) );
+        char *pszStyleId = CPLStrdup( poKmlStyle->get_id().c_str() );
 
         /***** TODO:: Not sure we need to do this as we seem *****/
         /***** to cast to element and then back to style.    *****/
-
-        ElementPtr poKmlElement = AsElement ( poKmlStyle );
-        kml2styletable ( *poStyleTable, AsStyle ( poKmlElement ) );
+        ElementPtr poKmlElement = AsElement( poKmlStyle );
+        kml2styletable( *poStyleTable, AsStyle( poKmlElement ) );
 
         // Change the name of the new style in the style table
 
         const char *pszTest = NULL;
         pszTest = (*poStyleTable)->Find(pszStyleId);
         // If we found the style we want in the style table we...
-        if ( pszTest ) {
+        if( pszTest )
+        {
             (*poStyleTable)->AddStyle(pszStyleMapId, pszTest);
-            (*poStyleTable)->RemoveStyle ( pszStyleId );
+            (*poStyleTable)->RemoveStyle( pszStyleId );
         }
-        CPLFree ( pszStyleId );
-        CPLFree ( pszStyleMapId );
+        CPLFree( pszStyleId );
+        CPLFree( pszStyleMapId );
     }
-
-    return;
 }
 
 /******************************************************************************
- function to add a style table to a kml container
+ Function to add a style table to a kml container.
 ******************************************************************************/
 
-void styletable2kml (
+void styletable2kml(
     OGRStyleTable * poOgrStyleTable,
     KmlFactory * poKmlFactory,
     ContainerPtr poKmlContainer,
     char** papszOptions )
 {
-
     /***** just return if the styletable is null *****/
-
-    if ( !poOgrStyleTable )
+    if( !poOgrStyleTable )
         return;
 
     std::set<CPLString> aoSetNormalStyles;
     std::set<CPLString> aoSetHighlightStyles;
-    poOgrStyleTable->ResetStyleStringReading (  );
-    const char *pszStyleString;
+    poOgrStyleTable->ResetStyleStringReading();
 
-    /* Collect styles that end with _normal or _highlight */
-    while ( poOgrStyleTable->GetNextStyle (  ) != NULL ) {
-        const char *pszStyleName = poOgrStyleTable->GetLastStyleName (  );
+    // Collect styles that end with _normal or _highlight.
+    while( poOgrStyleTable->GetNextStyle() != NULL )
+    {
+        const char *pszStyleName = poOgrStyleTable->GetLastStyleName();
 
         if( strlen(pszStyleName) > strlen("_normal") &&
-            EQUAL(pszStyleName + strlen(pszStyleName) - strlen("_normal"), "_normal") )
+            EQUAL(pszStyleName + strlen(pszStyleName) -
+                  strlen("_normal"), "_normal") )
         {
             CPLString osName(pszStyleName);
             osName.resize(strlen(pszStyleName) - strlen("_normal"));
             aoSetNormalStyles.insert(osName);
         }
         else if( strlen(pszStyleName) > strlen("_highlight") &&
-                  EQUAL(pszStyleName + strlen(pszStyleName) - strlen("_highlight"), "_highlight") )
+                 EQUAL(pszStyleName + strlen(pszStyleName) -
+                       strlen("_highlight"), "_highlight") )
         {
             CPLString osName(pszStyleName);
             osName.resize(strlen(pszStyleName) - strlen("_highlight"));
@@ -1139,94 +1107,105 @@ void styletable2kml (
     }
 
     /***** parse the style table *****/
+    poOgrStyleTable->ResetStyleStringReading();
 
-    poOgrStyleTable->ResetStyleStringReading (  );
-
-    while ( ( pszStyleString = poOgrStyleTable->GetNextStyle (  ) ) != NULL ) {
-        const char *pszStyleName = poOgrStyleTable->GetLastStyleName (  );
+    const char *pszStyleString = NULL;
+    while( ( pszStyleString = poOgrStyleTable->GetNextStyle() ) != NULL )
+    {
+        const char *pszStyleName = poOgrStyleTable->GetLastStyleName();
 
         if( aoSetNormalStyles.find(pszStyleName) != aoSetNormalStyles.end() &&
-            aoSetHighlightStyles.find(pszStyleName) != aoSetHighlightStyles.end() )
+            aoSetHighlightStyles.find(pszStyleName) !=
+                aoSetHighlightStyles.end() )
         {
             continue;
         }
 
         /***** add the style header to the kml *****/
+        StylePtr poKmlStyle = poKmlFactory->CreateStyle();
 
-        StylePtr poKmlStyle = poKmlFactory->CreateStyle (  );
-
-        poKmlStyle->set_id ( pszStyleName );
+        poKmlStyle->set_id( pszStyleName );
 
         /***** parse the style string *****/
-
-        addstylestring2kml ( pszStyleString, poKmlStyle, poKmlFactory, NULL );
+        addstylestring2kml( pszStyleString, poKmlStyle, poKmlFactory, NULL );
 
         /***** add balloon style *****/
-        const char* pszBalloonStyleBgColor = CSLFetchNameValue(papszOptions, CPLSPrintf("%s_balloonstyle_bgcolor", pszStyleName));
-        const char* pszBalloonStyleText = CSLFetchNameValue(papszOptions, CPLSPrintf("%s_balloonstyle_text", pszStyleName));
-        int nR, nG, nB, nA;
+        const char* pszBalloonStyleBgColor =
+            CSLFetchNameValue(papszOptions,
+                              CPLSPrintf("%s_balloonstyle_bgcolor",
+                                         pszStyleName));
+        const char* pszBalloonStyleText =
+            CSLFetchNameValue(papszOptions,
+                              CPLSPrintf("%s_balloonstyle_text", pszStyleName));
+        int nR = 0;
+        int nG = 0;
+        int nB = 0;
+        int nA = 0;
         OGRStylePen oStyleTool;
         if( (pszBalloonStyleBgColor != NULL &&
-             oStyleTool.GetRGBFromString ( pszBalloonStyleBgColor, nR, nG, nB, nA )  ) ||
+             oStyleTool.GetRGBFromString( pszBalloonStyleBgColor,
+                                          nR, nG, nB, nA ) ) ||
             pszBalloonStyleText != NULL )
         {
-            BalloonStylePtr poKmlBalloonStyle = poKmlFactory->CreateBalloonStyle();
+            const BalloonStylePtr poKmlBalloonStyle =
+                poKmlFactory->CreateBalloonStyle();
             if( pszBalloonStyleBgColor != NULL &&
-                oStyleTool.GetRGBFromString ( pszBalloonStyleBgColor, nR, nG, nB, nA ) )
-                poKmlBalloonStyle->set_bgcolor ( Color32 ( static_cast<GByte>(nA),
-                                                           static_cast<GByte>(nB),
-                                                           static_cast<GByte>(nG),
-                                                           static_cast<GByte>(nR) ) );
+                oStyleTool.GetRGBFromString( pszBalloonStyleBgColor,
+                                             nR, nG, nB, nA ) )
+                poKmlBalloonStyle->set_bgcolor(
+                    Color32( static_cast<GByte>(nA),
+                             static_cast<GByte>(nB),
+                             static_cast<GByte>(nG),
+                             static_cast<GByte>(nR) ) );
             if( pszBalloonStyleText != NULL )
                 poKmlBalloonStyle->set_text(pszBalloonStyleText);
-            poKmlStyle->set_balloonstyle ( poKmlBalloonStyle );
+            poKmlStyle->set_balloonstyle( poKmlBalloonStyle );
         }
 
         /***** add the style to the container *****/
-
-        DocumentPtr poKmlDocument = AsDocument ( poKmlContainer );
-        poKmlDocument->add_styleselector ( poKmlStyle );
-
+        const DocumentPtr poKmlDocument = AsDocument( poKmlContainer );
+        poKmlDocument->add_styleselector( poKmlStyle );
     }
 
-    /* Find style name that end with _normal and _highlight to create */
-    /* a StyleMap from both */
+    // Find style name that end with _normal and _highlight to create
+    // a StyleMap from both.
     std::set<CPLString>::iterator aoSetNormalStylesIter =
         aoSetNormalStyles.begin();
-    for( ; aoSetNormalStylesIter != aoSetNormalStyles.end(); ++aoSetNormalStylesIter )
+    for( ;
+         aoSetNormalStylesIter != aoSetNormalStyles.end();
+         ++aoSetNormalStylesIter )
     {
         CPLString osStyleName(*aoSetNormalStylesIter);
         if( aoSetHighlightStyles.find(osStyleName) !=
                 aoSetHighlightStyles.end() )
         {
-            StyleMapPtr poKmlStyleMap = poKmlFactory->CreateStyleMap (  );
-            poKmlStyleMap->set_id ( osStyleName );
+            StyleMapPtr poKmlStyleMap = poKmlFactory->CreateStyleMap();
+            poKmlStyleMap->set_id( osStyleName );
 
-            PairPtr poKmlPairNormal = poKmlFactory->CreatePair (  );
+            PairPtr poKmlPairNormal = poKmlFactory->CreatePair();
             poKmlPairNormal->set_key(STYLESTATE_NORMAL);
-            poKmlPairNormal->set_styleurl(CPLSPrintf("#%s_normal", osStyleName.c_str()));
+            poKmlPairNormal->set_styleurl(
+                CPLSPrintf("#%s_normal", osStyleName.c_str()));
             poKmlStyleMap->add_pair(poKmlPairNormal);
 
-            PairPtr poKmlPairHightlight = poKmlFactory->CreatePair (  );
-            poKmlPairHightlight->set_key(STYLESTATE_HIGHLIGHT);
-            poKmlPairHightlight->set_styleurl(CPLSPrintf("#%s_highlight", osStyleName.c_str()));
-            poKmlStyleMap->add_pair(poKmlPairHightlight);
+            PairPtr poKmlPairHighlight = poKmlFactory->CreatePair();
+            poKmlPairHighlight->set_key(STYLESTATE_HIGHLIGHT);
+            poKmlPairHighlight->set_styleurl(
+                CPLSPrintf("#%s_highlight", osStyleName.c_str()));
+            poKmlStyleMap->add_pair(poKmlPairHighlight);
 
             /***** add the style to the container *****/
-            DocumentPtr poKmlDocument = AsDocument ( poKmlContainer );
-            poKmlDocument->add_styleselector ( poKmlStyleMap );
+            DocumentPtr poKmlDocument = AsDocument( poKmlContainer );
+            poKmlDocument->add_styleselector( poKmlStyleMap );
         }
     }
-
-    return;
 }
 
-
 /******************************************************************************
- function to add a ListStyle and select it to a container
+ Function to add a ListStyle and select it to a container.
 ******************************************************************************/
 
-void createkmlliststyle (
+void createkmlliststyle(
     KmlFactory * poKmlFactory,
     const char* pszBaseName,
     ContainerPtr poKmlLayerContainer,
@@ -1234,42 +1213,49 @@ void createkmlliststyle (
     const CPLString& osListStyleType,
     const CPLString& osListStyleIconHref)
 {
-    if( osListStyleType.size() || osListStyleIconHref.size() )
+    if( !osListStyleType.empty() || !osListStyleIconHref.empty() )
     {
-        StylePtr poKmlStyle = poKmlFactory->CreateStyle (  );
+        StylePtr poKmlStyle = poKmlFactory->CreateStyle();
 
-        const char* pszStyleName = CPLSPrintf("%s_liststyle", OGRLIBKMLGetSanitizedNCName(pszBaseName).c_str());
-        poKmlStyle->set_id ( pszStyleName );
+        const char* pszStyleName =
+            CPLSPrintf("%s_liststyle",
+                       OGRLIBKMLGetSanitizedNCName(pszBaseName).c_str());
+        poKmlStyle->set_id( pszStyleName );
 
-        ListStylePtr poKmlListStyle = poKmlFactory->CreateListStyle (  );
-        poKmlStyle->set_liststyle ( poKmlListStyle );
-        if( osListStyleType.size() )
+        ListStylePtr poKmlListStyle = poKmlFactory->CreateListStyle();
+        poKmlStyle->set_liststyle( poKmlListStyle );
+        if( !osListStyleType.empty() )
         {
             if( EQUAL(osListStyleType, "check") )
                 poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_CHECK );
             else if( EQUAL(osListStyleType, "radioFolder") )
-                poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_RADIOFOLDER );
+                poKmlListStyle->set_listitemtype(
+                    kmldom::LISTITEMTYPE_RADIOFOLDER );
             else if( EQUAL(osListStyleType, "checkOffOnly") )
-                poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_CHECKOFFONLY );
+                poKmlListStyle->set_listitemtype(
+                    kmldom::LISTITEMTYPE_CHECKOFFONLY );
             else if( EQUAL(osListStyleType, "checkHideChildren") )
-                poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_CHECKHIDECHILDREN );
+                poKmlListStyle->set_listitemtype(
+                    kmldom::LISTITEMTYPE_CHECKHIDECHILDREN );
             else
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "Invalid value for list style type: %s. Defaulting to Check",
-                         osListStyleType.c_str());
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Invalid value for list style type: %s. "
+                    "Defaulting to Check",
+                    osListStyleType.c_str());
                 poKmlListStyle->set_listitemtype( kmldom::LISTITEMTYPE_CHECK );
             }
         }
 
-        if( osListStyleIconHref.size() )
+        if( !osListStyleIconHref.empty() )
         {
-            ItemIconPtr poItemIcon = poKmlFactory->CreateItemIcon (  );
+            ItemIconPtr poItemIcon = poKmlFactory->CreateItemIcon();
             poItemIcon->set_href( osListStyleIconHref.c_str() );
             poKmlListStyle->add_itemicon(poItemIcon);
         }
 
-        poKmlDocument->add_styleselector ( poKmlStyle );
+        poKmlDocument->add_styleselector( poKmlStyle );
         poKmlLayerContainer->set_styleurl( CPLSPrintf("#%s", pszStyleName) );
     }
 }
diff --git a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h
index 01dca66..7cd8562 100644
--- a/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h
+++ b/ogr/ogrsf_frmts/libkml/ogrlibkmlstyle.h
@@ -26,55 +26,48 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-using kmldom::KmlFactory;
-using kmldom::StyleSelectorPtr;
-using kmldom::StylePtr;
-using kmldom::StyleMapPtr;
-using kmldom::DocumentPtr;
-using kmldom::ContainerPtr;
-using kmldom::FeaturePtr;
-
-StylePtr addstylestring2kml (
-    const char *stylestring,
-    StylePtr poKmlStyle,
-    KmlFactory * poKmlFactory,
-    FeaturePtr poKmlFeature );
+#ifndef OGR_LIBKML_STYLE_H
+#define OGR_LIBKML_STYLE_H
 
+#include <string>
 
+kmldom::StylePtr addstylestring2kml (
+    const char *stylestring,
+    kmldom::StylePtr poKmlStyle,
+    kmldom::KmlFactory *poKmlFactory,
+    kmldom::FeaturePtr poKmlFeature );
 
 /******************************************************************************
  kml2stylemgr
 ******************************************************************************/
 
 void kml2stylestring(
-    StylePtr poKmlStyle,
-    OGRStyleMgr *poOgrSM);
-
-
+    kmldom::StylePtr poKmlStyle,
+    OGRStyleMgr *poOgrSM );
 
 /******************************************************************************
- functions to follow the kml stylemap if one exists
+ Functions to follow the kml stylemap if one exists.
 ******************************************************************************/
 
-StyleSelectorPtr StyleFromStyleSelector(
-    const StyleSelectorPtr& styleselector,
-    OGRStyleTable * poStyleTable);
+kmldom::StyleSelectorPtr StyleFromStyleSelector(
+    const kmldom::StyleSelectorPtr& styleselector,
+    OGRStyleTable * poStyleTable );
 
-StyleSelectorPtr StyleFromStyleURL(
-    const string styleurl,
-    OGRStyleTable * poStyleTable);
+kmldom::StyleSelectorPtr StyleFromStyleURL(
+    const std::string& styleurl,
+    OGRStyleTable * poStyleTable );
 
-StyleSelectorPtr StyleFromStyleMap(
-    const StyleMapPtr& stylemap,
-    OGRStyleTable * poStyleTable);
+kmldom::StyleSelectorPtr StyleFromStyleMap(
+    const kmldom::StyleMapPtr& stylemap,
+    OGRStyleTable * poStyleTable );
 
 /******************************************************************************
- function to parse a style table out of a document
+ Function to parse a style table out of a document.
 ******************************************************************************/
 
 void ParseStyles (
-    DocumentPtr poKmlDocument,
-    OGRStyleTable **poStyleTable);
+    kmldom::DocumentPtr poKmlDocument,
+    OGRStyleTable **poStyleTable );
 
 /******************************************************************************
  function to add a style table to a kml container
@@ -82,18 +75,20 @@ void ParseStyles (
 
 void styletable2kml (
     OGRStyleTable * poOgrStyleTable,
-    KmlFactory * poKmlFactory,
-    ContainerPtr poKmlContainer,
-    char** papszOptions = NULL  );
+    kmldom::KmlFactory * poKmlFactory,
+    kmldom::ContainerPtr poKmlContainer,
+    char** papszOptions = NULL );
 
 /******************************************************************************
- function to add a ListStyle and select it to a container
+ Function to add a ListStyle and select it to a container.
 ******************************************************************************/
 
 void createkmlliststyle (
-    KmlFactory * poKmlFactory,
+    kmldom::KmlFactory * poKmlFactory,
     const char* pszBaseName,
-    ContainerPtr poKmlLayerContainer,
-    DocumentPtr poKmlDocument,
+    kmldom::ContainerPtr poKmlLayerContainer,
+    kmldom::DocumentPtr poKmlDocument,
     const CPLString& osListStyleType,
-    const CPLString& osListStyleIconHref);
+    const CPLString& osListStyleIconHref );
+
+#endif  // OGR_LIBKML_STYLE_H
diff --git a/ogr/ogrsf_frmts/makefile.vc b/ogr/ogrsf_frmts/makefile.vc
index 9c1b954..8004f19 100644
--- a/ogr/ogrsf_frmts/makefile.vc
+++ b/ogr/ogrsf_frmts/makefile.vc
@@ -16,7 +16,7 @@ DIRLIST		=	generic geojson shape ntf sdts tiger s57 dgn mitab gml \
 			$(LIBKMLDIR) $(WFSDIR) $(SOSIDIR) $(GFTDIR) \
 			$(COUCHDBDIR) $(CLOUDANTDIR) $(FGDB_DIR) $(XLSDIR) $(ODSDIR) $(XLSXDIR) \
 			$(INGRESDIR) $(ELASTICDIR) $(OSMDIR) $(VFKDIR) $(CARTODIR) $(AMIGOCLOUD_DIR) \
-			$(PLSCENESDIR) $(CSWDIR) $(MONGODBDIR)
+			$(PLSCENESDIR) $(CSWDIR) $(MONGODBDIR) $(GMLAS_DIR) $(CAD_DIR)
 
 PLUGINDIRLIST	=	$(PLUGIN_ARCOBJECTS_DIR) \
 			$(PLUGIN_DWG_DIR) \
@@ -82,12 +82,12 @@ PLUGIN_PG_DIR = pg
 !ENDIF
 !ENDIF
 
-!IFDEF DWGDIRECT
-!IF "$(DWG_PLUGIN)" != "YES"
-DWGDIR = dxfdwg
-DWG_OBJ = dxfdwg\*.obj
+!IFDEF TD_LIBDIR
+!IF "$(TD_PLUGIN)" != "YES"
+DWGDIR = dwg
+DWG_OBJ = dwg\*.obj
 !ELSE
-PLUGIN_DWGDIR = dxfdwg
+PLUGIN_DWG_DIR = dwg
 !ENDIF
 !ENDIF
 
@@ -134,6 +134,11 @@ NAS_DIR = nas
 NAS_OBJ = nas\*.obj
 !ENDIF
 
+!IFDEF XERCES_INCLUDE
+GMLAS_DIR = gmlas
+GMLAS_OBJ = gmlas\*.obj
+!ENDIF
+
 !IFDEF INFORMIXDIR
 IDB_DIR = idb
 IDB_OBJ = idb\*.obj
@@ -236,6 +241,11 @@ PLUGIN_MONGODBDIR = mongodb
 !ENDIF
 !ENDIF
 
+!IF $(MSVC_VER) >= 1800
+CAD_DIR = cad
+CAD_OBJ = cad\*.obj cad\libopencad\*.obj cad\libopencad\dwg\*.obj
+!ENDIF
+
 !ELSE
 
 DIRLIST		=	generic mitab
@@ -268,7 +278,7 @@ default:
 				$(DODS_OBJ) $(NAS_OBJ) $(LIBKMLOBJ) $(WFS_OBJ) \
 				$(SOSI_OBJ) $(GFT_OBJ) $(COUCHDB_OBJ) $(CLOUDANT_OBJ) $(XLS_OBJ) $(ODS_OBJ) $(XLSX_OBJ)  \
 				$(INGRESOBJ) $(ELASTIC_OBJ) $(OSM_OBJ) $(VFK_OBJ) $(CARTO_OBJ) $(AMIGOCLOUD_OBJ) $(PLSCENES_OBJ) \
-				$(CSW_OBJ) $(MONGODBOBJ)
+				$(CSW_OBJ) $(MONGODBOBJ) $(GMLAS_OBJ) $(CAD_OBJ)
 	lib /out:ogrsf_frmts_sup.lib \
 				 ..\..\frmts\iso8211\*.obj \
 				 ..\..\frmts\sdts\sdtsattrreader.obj \
diff --git a/ogr/ogrsf_frmts/mdb/drv_mdb.html b/ogr/ogrsf_frmts/mdb/drv_mdb.html
index 4cd6a9d..e889a28 100644
--- a/ogr/ogrsf_frmts/mdb/drv_mdb.html
+++ b/ogr/ogrsf_frmts/mdb/drv_mdb.html
@@ -30,7 +30,7 @@
 
   <pre>./configure --with-java=yes --with-mdb=yes</pre>
 
-  On others Linux flavours, you may need to specify :
+  On others Linux flavors, you may need to specify :
 
   <pre>./configure --with-java=/path/to/jdk/root/path --with-jvm-lib=/path/to/libjvm/directory --with-mdb=yes</pre>
 
@@ -45,16 +45,16 @@
 
   <ol>
   <li>If you didn't specify --with-jvm-lib-add-rpath at configure time, set the path of the directory that contains libjvm.so in LD_LIBRARY_PATH or in /etc/ld.so.conf.</li>
-  <li>Download jackcess-1.2.2.jar, commons-lang-2.4.jar and commons-logging-1.1.1.jar (other versions might work)</li>
+  <li>Download jackcess-1.2.XX.jar (but 2.X does not with the current driver), commons-lang-2.4.jar and commons-logging-1.1.1.jar (other versions might work)</li>
   <li>Put the 3 JARs either in the lib/ext directory of the JRE (e.g. /usr/lib/jvm/java-6-openjdk/jre/lib/ext) or in another directory
-  and explicitly point them with the CLASSPATH environment variable.</li>
+  and explicitly point to each of them with the CLASSPATH environment variable.</li>
   </ol>
 
   <h2>Resources</h2>
 
   <ul>
   <li><a href="http://jackcess.sourceforge.net/">Jackcess</a> library home page</li>
-  <li>Utility that contains the needed <a href="http://mdb-sqlite.googlecode.com/files/mdb-sqlite-1.0.2.tar.bz2">JARs dependencies</a></lib>
+  <li>Utility that contains the needed <a href="https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/mdb-sqlite/mdb-sqlite-1.0.2.tar.bz2">JARs dependencies</a></lib>
   </ul>
 
   <h2>See also</h2>
diff --git a/ogr/ogrsf_frmts/mdb/ogr_mdb.h b/ogr/ogrsf_frmts/mdb/ogr_mdb.h
index be0c16c..2e0e0c0 100644
--- a/ogr/ogrsf_frmts/mdb/ogr_mdb.h
+++ b/ogr/ogrsf_frmts/mdb/ogr_mdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mdb.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_mdb.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for MDB driver.
@@ -49,7 +49,6 @@ class OGRMDBJavaEnv
 
         int Init();
 
-
     JavaVM *jvm;
     JNIEnv *env;
     int bCalledFromJava;
@@ -185,7 +184,6 @@ public:
     int GetColumnAsInt(int iCol);
     double GetColumnAsDouble(int iCol);
     GByte* GetColumnAsBinary(int iCol, int* pnBytes);
-
 };
 
 typedef enum
@@ -268,21 +266,21 @@ class OGRMDBLayer : public OGRLayer
                                     const char *pszGeomCol,
                                     OGRSpatialReference* poSRS );
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int bForce );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int bForce ) override;
     virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual const char *GetFIDColumn();
+    virtual const char *GetFIDColumn() override;
 
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
@@ -318,12 +316,12 @@ class OGRMDBDataSource : public OGRDataSource
                                    const char *pszGeomCol,
                                    int bUpdate );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
-    OGRLayer            *GetLayerByName( const char* pszLayerName );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
+    OGRLayer            *GetLayerByName( const char* pszLayerName ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -335,10 +333,10 @@ class OGRMDBDriver : public OGRSFDriver
   public:
                 ~OGRMDBDriver();
 
-    const char  *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char  *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
-    int          TestCapability( const char * );
+    int          TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_MDB_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
index 02f3898..0785dbf 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmdbdatasource.cpp 32983 2016-01-14 18:32:10Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMDBDataSource class.
@@ -33,7 +32,7 @@
 #include <vector>
 #include "ogrgeomediageometry.h"
 
-CPL_CVSID("$Id: ogrmdbdatasource.cpp 32983 2016-01-14 18:32:10Z goatbar $");
+CPL_CVSID("$Id: ogrmdbdatasource.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                         OGRMDBDataSource()                          */
@@ -69,11 +68,9 @@ OGRMDBDataSource::~OGRMDBDataSource()
         delete papoLayersInvisible[i];
     CPLFree( papoLayersInvisible );
 
-
     delete poDB;
 }
 
-
 /************************************************************************/
 /*                              OpenGDB()                               */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
index 43cb085..2c69474 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmdbdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
@@ -30,7 +29,7 @@
 #include "ogr_mdb.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrmdbdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrmdbdriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 // g++ -fPIC -g -Wall ogr/ogrsf_frmts/mdb/*.cpp -shared -o ogr_MDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mdb -L. -lgdal -I/usr/lib/jvm/java-6-openjdk/include -I/usr/lib/jvm/java-6-openjdk/include/linux  -L/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server -ljvm
 
@@ -106,7 +105,6 @@ int OGRMDBDriver::TestCapability( CPL_UNUSED const char * pszCap )
     return FALSE;
 }
 
-
 /************************************************************************/
 /*                           RegisterOGRMDB()                           */
 /************************************************************************/
@@ -121,4 +119,3 @@ void RegisterOGRMDB()
     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mdb.html" );
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
index 684e905..d981b5e 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdbjackcess.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmdbjackcess.cpp 33102 2016-01-23 11:05:59Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMDBJavaEnv class.
@@ -29,7 +28,12 @@
 
 #include "ogr_mdb.h"
 
-CPL_CVSID("$Id: ogrmdbjackcess.cpp 33102 2016-01-23 11:05:59Z rouault $");
+CPL_CVSID("$Id: ogrmdbjackcess.cpp 36981 2016-12-20 19:46:41Z rouault $");
+
+#if JVM_LIB_DLOPEN
+#include <limits.h>
+#include <stdio.h>
+#endif
 
 static JavaVM *jvm_static = NULL;
 static JNIEnv *env_static = NULL;
@@ -149,7 +153,9 @@ OGRMDBJavaEnv::~OGRMDBJavaEnv()
     }
 }
 
-#define CHECK(x, y) do {x = y; if (!x) { CPLError(CE_Failure, CPLE_AppDefined, #y " failed"); return FALSE;} } while(0)
+#define CHECK(x, y) do {x = y; if (!x) { \
+      CPLError(CE_Failure, CPLE_AppDefined, #y " failed"); \
+      return FALSE;} } while( false )
 
 /************************************************************************/
 /*                              Init()                                  */
@@ -161,9 +167,65 @@ int OGRMDBJavaEnv::Init()
     {
         JavaVM* vmBuf[1];
         jsize nVMs;
+        int ret = 0;
+
+#if JVM_LIB_DLOPEN
+#  if defined(__APPLE__) && defined(__MACH__)
+#    define SO_EXT "dylib"
+#  else
+#    define SO_EXT "so"
+#  endif
+        const char *jvmLibPtr = "libjvm." SO_EXT;
+        char jvmLib[PATH_MAX];
+
+        /* libjvm.so's location is hard to predict so
+           ${JAVA_HOME}/bin/java -XshowSettings is executed to find
+           its location. If JAVA_HOME is not set then java is executed
+           from the PATH instead. This is POSIX-compliant code. */
+        FILE *javaCmd = popen("\"${JAVA_HOME}${JAVA_HOME:+/bin/}java\" -XshowSettings 2>&1 | grep 'sun.boot.library.path'", "r");
+
+        if (javaCmd != NULL)
+        {
+            char szTmp[PATH_MAX];
+            size_t javaCmdRead = fread(szTmp, 1, sizeof(szTmp), javaCmd);
+            ret = pclose(javaCmd);
+
+            if (ret == 0 && javaCmdRead >= 2)
+            {
+                /* Chomp the new line */
+                szTmp[javaCmdRead - 1] = '\0';
+                const char* pszPtr = strchr(szTmp, '=');
+                if( pszPtr )
+                {
+                    pszPtr ++;
+                    while( *pszPtr == ' ' )
+                        pszPtr ++;
+                    snprintf(jvmLib, sizeof(jvmLib), "%s/server/libjvm." SO_EXT, pszPtr);
+                    jvmLibPtr = jvmLib;
+                }
+            }
+        }
+
+        CPLDebug("MDB", "Trying %s", jvmLibPtr);
+        jint (*pfnJNI_GetCreatedJavaVMs)(JavaVM **, jsize, jsize *);
+        pfnJNI_GetCreatedJavaVMs = (jint (*)(JavaVM **, jsize, jsize *))
+            CPLGetSymbol(jvmLibPtr, "JNI_GetCreatedJavaVMs");
+
+        if (pfnJNI_GetCreatedJavaVMs == NULL)
+        {
+            CPLDebug("MDB", "Cannot find JNI_GetCreatedJavaVMs function");
+            return FALSE;
+        }
+        else
+        {
+            ret = pfnJNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs);
+        }
+#else
+        ret = JNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs);
+#endif
 
         /* Are we already called from Java ? */
-        if (JNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs) == JNI_OK && nVMs == 1)
+        if (ret == JNI_OK && nVMs == 1)
         {
             jvm = vmBuf[0];
             if (jvm->GetEnv((void **)&env, JNI_VERSION_1_2) == JNI_OK)
@@ -194,11 +256,22 @@ int OGRMDBJavaEnv::Init()
                 args.nOptions = 0;
             args.ignoreUnrecognized = JNI_FALSE;
 
-            int ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
+#if JVM_LIB_DLOPEN
+            jint (*pfnJNI_CreateJavaVM)(JavaVM **, void **, void *);
+            pfnJNI_CreateJavaVM = (jint (*)(JavaVM **, void **, void *))
+                CPLGetSymbol(jvmLibPtr, "JNI_CreateJavaVM");
+
+            if (pfnJNI_CreateJavaVM == NULL)
+                return FALSE;
+            else
+                ret = pfnJNI_CreateJavaVM(&jvm, (void **)&env, &args);
+#else
+            ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
+#endif
 
             CPLFree(pszClassPathOption);
 
-            if (ret != 0 || jvm == NULL || env == NULL)
+            if (ret != JNI_OK || jvm == NULL || env == NULL)
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "JNI_CreateJavaVM failed (%d)", ret);
                 return FALSE;
@@ -278,7 +351,6 @@ int OGRMDBJavaEnv::Init()
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                       ExceptionOccurred()                             */
 /************************************************************************/
@@ -295,7 +367,6 @@ int OGRMDBJavaEnv::ExceptionOccurred()
     return FALSE;
 }
 
-
 /************************************************************************/
 /*                           OGRMDBDatabase()                           */
 /************************************************************************/
@@ -414,12 +485,13 @@ OGRMDBTable* OGRMDBDatabase::GetTable(const char* pszTableName)
 /*                           OGRMDBTable()                              */
 /************************************************************************/
 
-OGRMDBTable::OGRMDBTable(OGRMDBJavaEnv* envIn, OGRMDBDatabase* poDBIn, jobject tableIn, const char* pszTableName )
+OGRMDBTable::OGRMDBTable(OGRMDBJavaEnv* envIn, OGRMDBDatabase* poDBIn,
+                         jobject tableIn, const char* pszTableName ) :
+    osTableName( pszTableName )
 {
     this->env = envIn;
     this->poDB = poDBIn;
     this->table = tableIn;
-    osTableName = pszTableName;
     table_iterator_obj = NULL;
     row = NULL;
 }
@@ -495,7 +567,7 @@ int OGRMDBTable::FetchColumns()
         else
             apoColumnLengths.push_back(0);
 
-        //CPLDebug("MDB", "Column %s, type = %d", apoColumnNames[apoColumnNames.size()-1].c_str(), type);
+        //CPLDebug("MDB", "Column %s, type = %d", apoColumnNames.back().c_str(), type);
 
         env->env->DeleteLocalRef(column_type);
 
@@ -691,34 +763,34 @@ void OGRMDBTable::DumpTable()
     int nCols = static_cast<int>(apoColumnNames.size());
     while(GetNextRow())
     {
-        printf("Row = %d\n", iRow ++);
+        printf("Row = %d\n", iRow ++);/*ok*/
         for(int i=0;i<nCols;i++)
         {
-            printf("%s = ", apoColumnNames[i].c_str());
+            printf("%s = ", apoColumnNames[i].c_str());/*ok*/
             if (apoColumnTypes[i] == MDB_Float ||
                 apoColumnTypes[i] == MDB_Double)
             {
-                printf("%.15f\n", GetColumnAsDouble(i));
+                printf("%.15f\n", GetColumnAsDouble(i));/*ok*/
             }
             else if (apoColumnTypes[i] == MDB_Boolean ||
                      apoColumnTypes[i] == MDB_Byte ||
                      apoColumnTypes[i] == MDB_Short ||
                      apoColumnTypes[i] == MDB_Int)
             {
-                printf("%d\n", GetColumnAsInt(i));
+                printf("%d\n", GetColumnAsInt(i));/*ok*/
             }
             else if (apoColumnTypes[i] == MDB_Binary ||
                      apoColumnTypes[i] == MDB_OLE)
             {
                 int nBytes;
                 GByte* pData = GetColumnAsBinary(i, &nBytes);
-                printf("(%d bytes)\n", nBytes);
+                printf("(%d bytes)\n", nBytes);/*ok*/
                 CPLFree(pData);
             }
             else
             {
                 char* val = GetColumnAsString(i);
-                printf("'%s'\n", val);
+                printf("'%s'\n", val);/*ok*/
                 CPLFree(val);
             }
         }
diff --git a/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp b/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
index 21677b0..3572c33 100644
--- a/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
+++ b/ogr/ogrsf_frmts/mdb/ogrmdblayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmdblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMDBLayer class
@@ -33,34 +32,27 @@
 #include "ogrpgeogeometry.h"
 #include "ogrgeomediageometry.h"
 
-CPL_CVSID("$Id: ogrmdblayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrmdblayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                            OGRMDBLayer()                            */
 /************************************************************************/
 
-OGRMDBLayer::OGRMDBLayer(OGRMDBDataSource* poDSIn, OGRMDBTable* poMDBTableIn)
+OGRMDBLayer::OGRMDBLayer(OGRMDBDataSource* poDSIn, OGRMDBTable* poMDBTableIn) :
+    poMDBTable(poMDBTableIn),
+    eGeometryType(MDB_GEOM_NONE),
+    poFeatureDefn(NULL),
+    poSRS(NULL),
+    nSRSId(-2), // we haven't even queried the database for it yet.
+    iNextShapeId(0),
+    poDS(poDSIn),
+    iGeomColumn(-1),
+    pszGeomColumn(NULL),
+    pszFIDColumn(NULL),
+    panFieldOrdinals(NULL),
+    bHasExtent(FALSE)
 
 {
-    this->poDS = poDSIn;
-    this->poMDBTable = poMDBTableIn;
-
-    eGeometryType = MDB_GEOM_NONE;
-
-    iGeomColumn = -1;
-    pszGeomColumn = NULL;
-    pszFIDColumn = NULL;
-
-    panFieldOrdinals = NULL;
-
-    poFeatureDefn = NULL;
-
-    iNextShapeId = 0;
-
-    poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet.
-
-    bHasExtent = FALSE;
 }
 
 /************************************************************************/
@@ -112,7 +104,6 @@ CPLErr OGRMDBLayer::BuildFeatureDefn()
 
     poFeatureDefn->Reference();
 
-
     int nRawColumns = poMDBTable->GetColumnCount();
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
 
@@ -185,7 +176,6 @@ CPLErr OGRMDBLayer::BuildFeatureDefn()
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -270,7 +260,7 @@ OGRFeature *OGRMDBLayer::GetNextRawFeature()
         OGRFieldType eType = poFeature->GetFieldDefnRef(iField)->GetType();
 
         if( pszValue == NULL )
-            /* no value */;
+            poFeature->SetFieldNull( iField );
         else if( eType == OFTBinary )
         {
             int nBytes = 0;
@@ -493,7 +483,6 @@ CPLErr OGRMDBLayer::Initialize( CPL_UNUSED const char *pszTableName,
                                 int nSRID,
                                 int bHasZ )
 
-
 {
     CPLFree( pszGeomColumn );
 
@@ -565,7 +554,6 @@ CPLErr OGRMDBLayer::Initialize( CPL_UNUSED const char *pszTableName,
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                             Initialize()                             */
 /************************************************************************/
@@ -574,7 +562,6 @@ CPLErr OGRMDBLayer::Initialize( const char * /*pszTableName */,
                                 const char *pszGeomCol,
                                 OGRSpatialReference* poSRSIn )
 
-
 {
     CPLFree( pszGeomColumn );
 
diff --git a/ogr/ogrsf_frmts/mem/ogr_mem.h b/ogr/ogrsf_frmts/mem/ogr_mem.h
index e6cb092..dd447b9 100644
--- a/ogr/ogrsf_frmts/mem/ogr_mem.h
+++ b/ogr/ogrsf_frmts/mem/ogr_mem.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mem.h 32896 2016-01-10 13:37:26Z goatbar $
+ * $Id: ogr_mem.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions within the OGR Memory driver.
@@ -52,7 +52,7 @@ class OGRMemLayer : public OGRLayer
     GIntBig             m_nFeatureCount;
 
     GIntBig             m_iNextReadFID;
-    GIntBig             m_nMaxFeatureCount; // max size of papoFeatures
+    GIntBig             m_nMaxFeatureCount;  // Max size of papoFeatures.
     OGRFeature        **m_papoFeatures;
     bool                m_bHasHoles;
 
@@ -66,40 +66,45 @@ class OGRMemLayer : public OGRLayer
 
     bool                m_bUpdated;
 
-    // only use it in the lifetime of a function where the list of features doesn't change
+    // Only use it in the lifetime of a function where the list of features
+    // doesn't change.
     IOGRMemLayerFeatureIterator* GetIterator();
 
   public:
                         OGRMemLayer( const char * pszName,
                                      OGRSpatialReference *poSRS,
                                      OGRwkbGeometryType eGeomType );
-                        ~OGRMemLayer();
+    virtual            ~OGRMemLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
 
-    OGRFeature         *GetFeature( GIntBig nFeatureId );
-    OGRErr              ISetFeature( OGRFeature *poFeature );
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
+    OGRErr              ISetFeature( OGRFeature *poFeature ) override;
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return m_poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return m_poFeatureDefn; }
 
-    GIntBig             GetFeatureCount( int );
+    GIntBig             GetFeatureCount( int ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+                                     int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    virtual OGRErr      AlterFieldDefn( int iField,
+                                        OGRFieldDefn* poNewFieldDefn,
+                                        int nFlags ) override;
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
-                                         int bApproxOK = TRUE );
+                                         int bApproxOK = TRUE ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
-    void                SetUpdatable( bool bUpdatableIn ) { m_bUpdatable = bUpdatableIn; }
-    void                SetAdvertizeUTF8( bool bAdvertizeUTF8In ) { m_bAdvertizeUTF8 = bAdvertizeUTF8In; }
+    void                SetUpdatable( bool bUpdatableIn )
+        { m_bUpdatable = bUpdatableIn; }
+    void                SetAdvertizeUTF8( bool bAdvertizeUTF8In )
+        { m_bAdvertizeUTF8 = bAdvertizeUTF8In; }
 
     bool                HasBeenUpdated() const { return m_bUpdated; }
     void                SetUpdated(bool bUpdated) { m_bUpdated = bUpdated; }
@@ -120,19 +125,19 @@ class OGRMemDataSource : public OGRDataSource
 
   public:
                         OGRMemDataSource( const char *, char ** );
-                        ~OGRMemDataSource();
+                        virtual ~OGRMemDataSource();
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
     virtual OGRLayer    *ICreateLayer( const char *,
-                                      OGRSpatialReference * = NULL,
-                                      OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
-    OGRErr              DeleteLayer( int iLayer );
+                                       OGRSpatialReference * = NULL,
+                                       OGRwkbGeometryType = wkbUnknown,
+                                       char ** = NULL ) override;
+    OGRErr              DeleteLayer( int iLayer ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -142,16 +147,15 @@ class OGRMemDataSource : public OGRDataSource
 class OGRMemDriver : public OGRSFDriver
 {
   public:
-                ~OGRMemDriver();
+    virtual ~OGRMemDriver();
 
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
-                                             char ** = NULL );
+                                             char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int TestCapability( const char * ) override;
 };
 
-
-#endif /* ndef OGRMEM_H_INCLUDED */
+#endif  // ndef OGRMEM_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp b/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp
index bb1303b..e806a43 100644
--- a/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp
+++ b/ogr/ogrsf_frmts/mem/ogrmemdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmemdatasource.cpp 33400 2016-02-10 07:55:48Z ajolma $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMemDataSource class.
@@ -27,11 +26,11 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_mem.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_mem.h"
 
-CPL_CVSID("$Id: ogrmemdatasource.cpp 33400 2016-02-10 07:55:48Z ajolma $");
+CPL_CVSID("$Id: ogrmemdatasource.cpp 35649 2016-10-08 10:16:30Z rouault $");
 
 /************************************************************************/
 /*                          OGRMemDataSource()                          */
@@ -74,14 +73,14 @@ OGRMemDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     OGRMemLayer *poLayer = new OGRMemLayer( pszLayerName, poSRS, eType );
 
-    if( CSLFetchBoolean(papszOptions, "ADVERTIZE_UTF8", FALSE) )
-        poLayer->SetAdvertizeUTF8(TRUE);
+    if( CPLFetchBool(papszOptions, "ADVERTIZE_UTF8", false) )
+        poLayer->SetAdvertizeUTF8(true);
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
-    papoLayers = (OGRMemLayer **)
-        CPLRealloc( papoLayers,  sizeof(OGRMemLayer *) * (nLayers+1) );
+    papoLayers = static_cast<OGRMemLayer **>(
+        CPLRealloc( papoLayers,  sizeof(OGRMemLayer *) * (nLayers+1) ) );
 
     papoLayers[nLayers++] = poLayer;
 
@@ -99,10 +98,10 @@ OGRErr OGRMemDataSource::DeleteLayer( int iLayer )
     {
         delete papoLayers[iLayer];
 
-        for( int i = iLayer+1; i < nLayers; i++ )
+        for( int i = iLayer+1; i < nLayers; ++i )
             papoLayers[i-1] = papoLayers[i];
 
-        nLayers--;
+        --nLayers;
 
         return OGRERR_NONE;
     }
@@ -127,6 +126,8 @@ int OGRMemDataSource::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return TRUE;
 
     return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/mem/ogrmemdriver.cpp b/ogr/ogrsf_frmts/mem/ogrmemdriver.cpp
index 4d3c1d8..3294f62 100644
--- a/ogr/ogrsf_frmts/mem/ogrmemdriver.cpp
+++ b/ogr/ogrsf_frmts/mem/ogrmemdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmemdriver.cpp 32896 2016-01-10 13:37:26Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMemDriver class.
@@ -27,14 +26,14 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "ogr_mem.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_mem.h"
 
-CPL_CVSID("$Id: ogrmemdriver.cpp 32896 2016-01-10 13:37:26Z goatbar $");
+CPL_CVSID("$Id: ogrmemdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
-/*                          ~OGRMemDriver()                           */
+/*                          ~OGRMemDriver()                             */
 /************************************************************************/
 
 OGRMemDriver::~OGRMemDriver() {}
diff --git a/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp b/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
index 92bcb02..7bf9c11 100644
--- a/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
+++ b/ogr/ogrsf_frmts/mem/ogrmemlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmemlayer.cpp 35794 2016-10-17 19:29:48Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMemLayer class.
@@ -32,7 +31,9 @@
 #include "ogr_mem.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrmemlayer.cpp 35794 2016-10-17 19:29:48Z rouault $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrmemlayer.cpp 37988 2017-04-14 07:47:29Z rouault $");
 
 /************************************************************************/
 /*                      IOGRMemLayerFeatureIterator                     */
@@ -176,7 +177,7 @@ OGRErr OGRMemLayer::SetNextByIndex( GIntBig nIndex )
         m_papoFeatures == NULL || m_bHasHoles )
         return OGRLayer::SetNextByIndex( nIndex );
 
-    if (nIndex < 0 || nIndex >= m_nMaxFeatureCount)
+    if( nIndex < 0 || nIndex >= m_nMaxFeatureCount )
         return OGRERR_FAILURE;
 
     m_iNextReadFID = nIndex;
@@ -220,7 +221,7 @@ OGRFeature *OGRMemLayer::GetFeature( GIntBig nFeatureId )
 OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
 
 {
-    if (!m_bUpdatable)
+    if( !m_bUpdatable )
         return OGRERR_FAILURE;
 
     if( poFeature == NULL )
@@ -242,11 +243,11 @@ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
             FeatureIterator oIter;
             while( (oIter = m_oMapFeatures.find(m_iNextCreateFID)) !=
                    m_oMapFeatures.end() )
-                m_iNextCreateFID++;
+                ++m_iNextCreateFID;
         }
         poFeature->SetFID( m_iNextCreateFID++ );
     }
-    else if ( poFeature->GetFID() < OGRNullFID )
+    else if( poFeature->GetFID() < OGRNullFID )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "negative FID are not supported" );
@@ -261,11 +262,11 @@ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
     if( m_papoFeatures != NULL && nFID > 100000 &&
         nFID > m_nMaxFeatureCount + 1000 )
     {
-        // Convert to map if gap from current max size is too big
+        // Convert to map if gap from current max size is too big.
         IOGRMemLayerFeatureIterator* poIter = GetIterator();
         try
         {
-            OGRFeature* poFeatureIter;
+            OGRFeature* poFeatureIter = NULL;
             while( (poFeatureIter = poIter->Next()) != NULL )
             {
                 m_oMapFeatures[poFeatureIter->GetFID()] = poFeatureIter;
@@ -287,12 +288,13 @@ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
     }
 
     if( m_papoFeatures != NULL ||
-        (m_oMapFeatures.size() == 0 && nFID <= 100000) )
+        (m_oMapFeatures.empty() && nFID <= 100000) )
     {
         if( nFID >= m_nMaxFeatureCount )
         {
             const GIntBig nNewCount =
-                MAX(m_nMaxFeatureCount+m_nMaxFeatureCount/3+10, nFID + 1 );
+                std::max(m_nMaxFeatureCount + m_nMaxFeatureCount/3+10,
+                         nFID + 1);
             if( static_cast<GIntBig>(static_cast<size_t>(sizeof(OGRFeature *)) *
                                      nNewCount) !=
                 static_cast<GIntBig>(sizeof(OGRFeature *)) * nNewCount )
@@ -308,7 +310,7 @@ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
                 VSI_REALLOC_VERBOSE(
                     m_papoFeatures,
                     static_cast<size_t>(sizeof(OGRFeature *) * nNewCount) ) );
-            if (papoNewFeatures == NULL)
+            if( papoNewFeatures == NULL )
             {
                 delete poFeatureCloned;
                 return OGRERR_FAILURE;
@@ -320,7 +322,7 @@ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
             m_nMaxFeatureCount = nNewCount;
         }
 #ifdef DEBUG
-        /* Just to please Coverity. Cannot happen */
+        // Just to please Coverity. Cannot happen.
         if( m_papoFeatures == NULL )
         {
             delete poFeatureCloned;
@@ -334,10 +336,11 @@ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
             m_papoFeatures[nFID] = NULL;
         }
         else
-            m_nFeatureCount++;
+        {
+            ++m_nFeatureCount;
+        }
 
         m_papoFeatures[nFID] = poFeatureCloned;
-
     }
     else
     {
@@ -364,7 +367,7 @@ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
         }
     }
 
-    for(int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); i ++)
+    for( int i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i )
     {
         OGRGeometry* poGeom = poFeatureCloned->GetGeomFieldRef(i);
         if( poGeom != NULL && poGeom->getSpatialReference() == NULL )
@@ -386,7 +389,7 @@ OGRErr OGRMemLayer::ISetFeature( OGRFeature *poFeature )
 OGRErr OGRMemLayer::ICreateFeature( OGRFeature *poFeature )
 
 {
-    if (!m_bUpdatable)
+    if( !m_bUpdatable )
         return OGRERR_FAILURE;
 
     if( poFeature->GetFID() != OGRNullFID &&
@@ -394,7 +397,7 @@ OGRErr OGRMemLayer::ICreateFeature( OGRFeature *poFeature )
         m_bHasHoles = true;
 
     // If the feature has already a FID and that a feature with the same
-    // FID is already registered in the layer, then unset our FID
+    // FID is already registered in the layer, then unset our FID.
     if( poFeature->GetFID() >= 0 )
     {
         if( m_papoFeatures != NULL )
@@ -423,7 +426,7 @@ OGRErr OGRMemLayer::ICreateFeature( OGRFeature *poFeature )
 OGRErr OGRMemLayer::DeleteFeature( GIntBig nFID )
 
 {
-    if (!m_bUpdatable)
+    if( !m_bUpdatable )
         return OGRERR_FAILURE;
 
     if( nFID < 0 )
@@ -452,7 +455,7 @@ OGRErr OGRMemLayer::DeleteFeature( GIntBig nFID )
     }
 
     m_bHasHoles = true;
-    m_nFeatureCount--;
+    --m_nFeatureCount;
 
     m_bUpdated = true;
 
@@ -510,7 +513,7 @@ int OGRMemLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
         return m_poFilterGeom == NULL && m_poAttrQuery == NULL &&
                ((m_papoFeatures != NULL && !m_bHasHoles) ||
-                m_oMapFeatures.size() == 0);
+                m_oMapFeatures.empty());
 
     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
         return m_bAdvertizeUTF8;
@@ -521,8 +524,7 @@ int OGRMemLayer::TestCapability( const char * pszCap )
     else if( EQUAL(pszCap,OLCMeasuredGeometries) )
         return TRUE;
 
-    else
-        return FALSE;
+    return FALSE;
 }
 
 /************************************************************************/
@@ -532,7 +534,7 @@ int OGRMemLayer::TestCapability( const char * pszCap )
 OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField,
                                  int /* bApproxOK */ )
 {
-    if (!m_bUpdatable)
+    if( !m_bUpdatable )
         return OGRERR_FAILURE;
 
 /* -------------------------------------------------------------------- */
@@ -551,10 +553,10 @@ OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField,
 
     int *panRemap = static_cast<int *>(
         CPLMalloc(sizeof(int) * m_poFeatureDefn->GetFieldCount()) );
-    for( GIntBig i = 0; i < m_poFeatureDefn->GetFieldCount(); ++i )
+    for( int i = 0; i < m_poFeatureDefn->GetFieldCount(); ++i )
     {
         if( i < m_poFeatureDefn->GetFieldCount() - 1 )
-            panRemap[i] = static_cast<int>(i);
+            panRemap[i] = i;
         else
             panRemap[i] = -1;
     }
@@ -564,7 +566,7 @@ OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField,
 /*      external features referring to our OGRFeatureDefn!              */
 /* -------------------------------------------------------------------- */
     IOGRMemLayerFeatureIterator* poIter = GetIterator();
-    OGRFeature* poFeature;
+    OGRFeature* poFeature = NULL;
     while( (poFeature = poIter->Next()) != NULL )
     {
         poFeature->RemapFields( NULL, panRemap );
@@ -584,10 +586,10 @@ OGRErr OGRMemLayer::CreateField( OGRFieldDefn *poField,
 
 OGRErr OGRMemLayer::DeleteField( int iField )
 {
-    if (!m_bUpdatable)
+    if( !m_bUpdatable )
         return OGRERR_FAILURE;
 
-    if (iField < 0 || iField >= m_poFeatureDefn->GetFieldCount())
+    if( iField < 0 || iField >= m_poFeatureDefn->GetFieldCount() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid field index");
@@ -599,23 +601,25 @@ OGRErr OGRMemLayer::DeleteField( int iField )
 /*      external features referring to our OGRFeatureDefn!              */
 /* -------------------------------------------------------------------- */
     IOGRMemLayerFeatureIterator* poIter = GetIterator();
-    OGRFeature* poFeature;
+    OGRFeature* poFeature = NULL;
     while( (poFeature = poIter->Next()) != NULL )
     {
         OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
-        if( poFeature->IsFieldSet(iField) )
+        if( poFeature->IsFieldSetAndNotNull(iField) &&
+            !poFeature->IsFieldNull(iField) )
         {
             /* Little trick to unallocate the field */
             OGRField sField;
-            sField.Set.nMarker1 = OGRUnsetMarker;
-            sField.Set.nMarker2 = OGRUnsetMarker;
+            OGR_RawField_SetUnset(&sField);
             poFeature->SetField(iField, &sField);
         }
 
-        if (iField < m_poFeatureDefn->GetFieldCount() - 1)
+        if( iField < m_poFeatureDefn->GetFieldCount() - 1 )
         {
-            memmove( poFieldRaw, poFieldRaw + 1,
-                     sizeof(OGRField) * (m_poFeatureDefn->GetFieldCount() - 1 - iField) );
+            memmove(
+                poFieldRaw, poFieldRaw + 1,
+                sizeof(OGRField) *
+                (m_poFeatureDefn->GetFieldCount() - 1 - iField) );
         }
     }
     delete poIter;
@@ -631,14 +635,15 @@ OGRErr OGRMemLayer::DeleteField( int iField )
 
 OGRErr OGRMemLayer::ReorderFields( int* panMap )
 {
-    if (!m_bUpdatable)
+    if( !m_bUpdatable )
         return OGRERR_FAILURE;
 
-    if (m_poFeatureDefn->GetFieldCount() == 0)
+    if( m_poFeatureDefn->GetFieldCount() == 0 )
         return OGRERR_NONE;
 
-    OGRErr eErr = OGRCheckPermutation(panMap, m_poFeatureDefn->GetFieldCount());
-    if (eErr != OGRERR_NONE)
+    const OGRErr eErr =
+        OGRCheckPermutation(panMap, m_poFeatureDefn->GetFieldCount() );
+    if( eErr != OGRERR_NONE)
         return eErr;
 
 /* -------------------------------------------------------------------- */
@@ -646,7 +651,7 @@ OGRErr OGRMemLayer::ReorderFields( int* panMap )
 /*      external features referring to our OGRFeatureDefn!              */
 /* -------------------------------------------------------------------- */
     IOGRMemLayerFeatureIterator* poIter = GetIterator();
-    OGRFeature* poFeature;
+    OGRFeature* poFeature = NULL;
     while( (poFeature = poIter->Next()) != NULL )
     {
         poFeature->RemapFields( NULL, panMap );
@@ -665,10 +670,10 @@ OGRErr OGRMemLayer::ReorderFields( int* panMap )
 OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
                                     int nFlagsIn )
 {
-    if (!m_bUpdatable)
+    if( !m_bUpdatable )
         return OGRERR_FAILURE;
 
-    if (iField < 0 || iField >= m_poFeatureDefn->GetFieldCount())
+    if( iField < 0 || iField >= m_poFeatureDefn->GetFieldCount() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid field index");
@@ -677,83 +682,87 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
 
     OGRFieldDefn* poFieldDefn = m_poFeatureDefn->GetFieldDefn(iField);
 
-    if ((nFlagsIn & ALTER_TYPE_FLAG) &&
+    if( (nFlagsIn & ALTER_TYPE_FLAG) &&
         (poFieldDefn->GetType() != poNewFieldDefn->GetType() ||
-         poFieldDefn->GetSubType() != poNewFieldDefn->GetSubType()) )
+         poFieldDefn->GetSubType() != poNewFieldDefn->GetSubType()))
     {
-        if ((poNewFieldDefn->GetType() == OFTDate ||
+        if( (poNewFieldDefn->GetType() == OFTDate ||
              poNewFieldDefn->GetType() == OFTTime ||
              poNewFieldDefn->GetType() == OFTDateTime) &&
             (poFieldDefn->GetType() == OFTDate ||
              poFieldDefn->GetType() == OFTTime ||
-             poFieldDefn->GetType() == OFTDateTime))
+             poFieldDefn->GetType() == OFTDateTime) )
         {
-            /* do nothing on features */
+            // Do nothing on features.
         }
-        else if (poNewFieldDefn->GetType() == OFTInteger64 &&
-                 poFieldDefn->GetType() == OFTInteger)
+        else if( poNewFieldDefn->GetType() == OFTInteger64 &&
+                 poFieldDefn->GetType() == OFTInteger )
         {
     /* -------------------------------------------------------------------- */
     /*      Update all the internal features.  Hopefully there aren't any   */
     /*      external features referring to our OGRFeatureDefn!              */
     /* -------------------------------------------------------------------- */
             IOGRMemLayerFeatureIterator* poIter = GetIterator();
-            OGRFeature* poFeature;
+            OGRFeature* poFeature = NULL;
             while( (poFeature = poIter->Next()) != NULL )
             {
                 OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
-                if( poFeature->IsFieldSet(iField) )
+                if( poFeature->IsFieldSetAndNotNull(iField) &&
+                    !poFeature->IsFieldNull(iField) )
                 {
                     poFieldRaw->Integer64 = poFieldRaw->Integer;
                 }
             }
             delete poIter;
         }
-        else if (poNewFieldDefn->GetType() == OFTReal &&
-                 poFieldDefn->GetType() == OFTInteger)
+        else if( poNewFieldDefn->GetType() == OFTReal &&
+                 poFieldDefn->GetType() == OFTInteger )
         {
     /* -------------------------------------------------------------------- */
     /*      Update all the internal features.  Hopefully there aren't any   */
     /*      external features referring to our OGRFeatureDefn!              */
     /* -------------------------------------------------------------------- */
             IOGRMemLayerFeatureIterator* poIter = GetIterator();
-            OGRFeature* poFeature;
+            OGRFeature* poFeature = NULL;
             while( (poFeature = poIter->Next()) != NULL )
             {
                 OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
-                if( poFeature->IsFieldSet(iField) )
+                if( poFeature->IsFieldSetAndNotNull(iField) &&
+                    !poFeature->IsFieldNull(iField) )
                 {
                     poFieldRaw->Real = poFieldRaw->Integer;
                 }
             }
             delete poIter;
         }
-        else if (poNewFieldDefn->GetType() == OFTReal &&
-                 poFieldDefn->GetType() == OFTInteger64)
+        else if( poNewFieldDefn->GetType() == OFTReal &&
+                 poFieldDefn->GetType() == OFTInteger64 )
         {
     /* -------------------------------------------------------------------- */
     /*      Update all the internal features.  Hopefully there aren't any   */
     /*      external features referring to our OGRFeatureDefn!              */
     /* -------------------------------------------------------------------- */
             IOGRMemLayerFeatureIterator* poIter = GetIterator();
-            OGRFeature* poFeature;
+            OGRFeature* poFeature = NULL;
             while( (poFeature = poIter->Next()) != NULL )
             {
                 OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
-                if( poFeature->IsFieldSet(iField) )
+                if( poFeature->IsFieldSetAndNotNull(iField) &&
+                    !poFeature->IsFieldNull(iField) )
                 {
-                    poFieldRaw->Real = (double) poFieldRaw->Integer64;
+                    poFieldRaw->Real =
+                        static_cast<double>( poFieldRaw->Integer64 );
                 }
             }
             delete poIter;
         }
         else
         {
-            if (poNewFieldDefn->GetType() != OFTString)
+            if( poNewFieldDefn->GetType() != OFTString )
             {
                 CPLError( CE_Failure, CPLE_NotSupported,
                           "Can only convert from OFTInteger to OFTReal, "
-                          "or from anything to OFTString");
+                          "or from anything to OFTString" );
                 return OGRERR_FAILURE;
             }
 
@@ -762,18 +771,19 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
     /*      external features referring to our OGRFeatureDefn!              */
     /* -------------------------------------------------------------------- */
             IOGRMemLayerFeatureIterator* poIter = GetIterator();
-            OGRFeature* poFeature;
+            OGRFeature* poFeature = NULL;
             while( (poFeature = poIter->Next()) != NULL )
             {
                 OGRField* poFieldRaw = poFeature->GetRawFieldRef(iField);
-                if( poFeature->IsFieldSet(iField) )
+                if( poFeature->IsFieldSetAndNotNull(iField) &&
+                    !poFeature->IsFieldNull(iField) )
                 {
-                    char* pszVal = CPLStrdup(poFeature->GetFieldAsString(iField));
+                    char* pszVal =
+                        CPLStrdup(poFeature->GetFieldAsString(iField));
 
                     /* Little trick to unallocate the field */
                     OGRField sField;
-                    sField.Set.nMarker1 = OGRUnsetMarker;
-                    sField.Set.nMarker2 = OGRUnsetMarker;
+                    OGR_RawField_SetUnset(&sField);
                     poFeature->SetField(iField, &sField);
 
                     poFieldRaw->String = pszVal;
@@ -787,9 +797,9 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
         poFieldDefn->SetSubType(poNewFieldDefn->GetSubType());
     }
 
-    if (nFlagsIn & ALTER_NAME_FLAG)
+    if( nFlagsIn & ALTER_NAME_FLAG )
         poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
-    if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
+    if( nFlagsIn & ALTER_WIDTH_PRECISION_FLAG )
     {
         poFieldDefn->SetWidth(poNewFieldDefn->GetWidth());
         poFieldDefn->SetPrecision(poNewFieldDefn->GetPrecision());
@@ -800,15 +810,14 @@ OGRErr OGRMemLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                          CreateGeomField()                           */
 /************************************************************************/
 
 OGRErr OGRMemLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField,
-                                     CPL_UNUSED int bApproxOK )
+                                     int /* bApproxOK */ )
 {
-    if (!m_bUpdatable)
+    if( !m_bUpdatable )
         return OGRERR_FAILURE;
 
 /* -------------------------------------------------------------------- */
@@ -827,7 +836,7 @@ OGRErr OGRMemLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField,
 
     int *panRemap = static_cast<int *>(
         CPLMalloc(sizeof(int) * m_poFeatureDefn->GetGeomFieldCount()) );
-    for( GIntBig i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); i++ )
+    for( GIntBig i = 0; i < m_poFeatureDefn->GetGeomFieldCount(); ++i )
     {
         if( i < m_poFeatureDefn->GetGeomFieldCount() - 1 )
             panRemap[i] = static_cast<int>(i);
@@ -840,7 +849,7 @@ OGRErr OGRMemLayer::CreateGeomField( OGRGeomFieldDefn *poGeomField,
 /*      external features referring to our OGRFeatureDefn!              */
 /* -------------------------------------------------------------------- */
     IOGRMemLayerFeatureIterator* poIter = GetIterator();
-    OGRFeature* poFeature;
+    OGRFeature* poFeature = NULL;
     while( (poFeature = poIter->Next()) != NULL )
     {
         poFeature->RemapGeomFields( NULL, panRemap );
@@ -865,23 +874,21 @@ class OGRMemLayerIteratorArray: public IOGRMemLayerFeatureIterator
             OGRFeature **m_papoFeatures;
 
     public:
-        OGRMemLayerIteratorArray(GIntBig nMaxFeatureCount,
-                                 OGRFeature **papoFeatures):
-            m_iCurIdx(0), m_nMaxFeatureCount(nMaxFeatureCount),
+        OGRMemLayerIteratorArray( GIntBig nMaxFeatureCount,
+                                  OGRFeature **papoFeatures ):
+            m_iCurIdx(0),
+            m_nMaxFeatureCount(nMaxFeatureCount),
             m_papoFeatures(papoFeatures)
-        {
-        }
+        {}
 
-       ~OGRMemLayerIteratorArray()
-       {
-       }
+        virtual ~OGRMemLayerIteratorArray() {}
 
-       virtual OGRFeature* Next()
+       virtual OGRFeature* Next() override
        {
            while( m_iCurIdx < m_nMaxFeatureCount )
            {
                OGRFeature* poFeature = m_papoFeatures[m_iCurIdx];
-               m_iCurIdx ++;
+               ++m_iCurIdx;
                if( poFeature != NULL )
                    return poFeature;
            }
@@ -902,14 +909,14 @@ class OGRMemLayerIteratorMap: public IOGRMemLayerFeatureIterator
             FeatureIterator      m_oIter;
 
     public:
-        OGRMemLayerIteratorMap(FeatureMap& oMapFeatures):
+        explicit OGRMemLayerIteratorMap(FeatureMap& oMapFeatures):
             m_oMapFeatures(oMapFeatures),
             m_oIter(oMapFeatures.begin())
         {}
 
-       ~OGRMemLayerIteratorMap() {}
+       virtual ~OGRMemLayerIteratorMap() {}
 
-       virtual OGRFeature* Next()
+       virtual OGRFeature* Next() override
        {
            if( m_oIter != m_oMapFeatures.end() )
            {
@@ -930,7 +937,7 @@ class OGRMemLayerIteratorMap: public IOGRMemLayerFeatureIterator
 
 IOGRMemLayerFeatureIterator* OGRMemLayer::GetIterator()
 {
-    if( m_oMapFeatures.size() == 0 )
+    if( m_oMapFeatures.empty() )
         return new OGRMemLayerIteratorArray(m_nMaxFeatureCount, m_papoFeatures);
 
     return new OGRMemLayerIteratorMap(m_oMapFeatures);
diff --git a/ogr/ogrsf_frmts/mitab/HISTORY.TXT b/ogr/ogrsf_frmts/mitab/HISTORY.TXT
index 751b15c..7926add 100644
--- a/ogr/ogrsf_frmts/mitab/HISTORY.TXT
+++ b/ogr/ogrsf_frmts/mitab/HISTORY.TXT
@@ -4,7 +4,7 @@ MITAB Library - Revision History
 This is a human-readable revision history which will attempt to document
 required changes for users to migrate from one version of MITAB to the
 next.  Developers are strongly encouraged to document their changes and
-their impacts on the users here.  (Please add the most recent changes to 
+their impacts on the users here.  (Please add the most recent changes to
 the top of the list.)
 
 For a complete change history, please see the CVS log comments.
@@ -20,14 +20,14 @@ Version 2.0-dev (CVS)
   OGRLayer::SetFeature() is intended to be used only in random write mode.
   However, MITAB 1.x had a poorly named SetFeature() that was really doing
   the job of OGRLayer::CreateFeature(). In order to implement random write
-  support through OGRLayer::SetFeature() in a way that is consistent with 
+  support through OGRLayer::SetFeature() in a way that is consistent with
   the OGRLayer methods, we had to fix this error from the early MITAB days.
 
   In MITAB 2.x, we have replaced the old SetFeature() with a CreateFeature(),
-  and a new SetFeature() has been added that's in line with the 
+  and a new SetFeature() has been added that's in line with the
   OGRLayer::SetFeature() signature and behavior.
-  Application code that was writing features using SetFeature() with 
-  MITAB 1.x will need to be changed to use CreateFeature() with MITAB 2.x. 
+  Application code that was writing features using SetFeature() with
+  MITAB 1.x will need to be changed to use CreateFeature() with MITAB 2.x.
 
   Note that the return value of CreateFeature() is an OGRErr code and not
   a feature id as was the case with the MITAB 1.x SetFeature() implementation.
@@ -35,7 +35,7 @@ Version 2.0-dev (CVS)
   passed in feature instead of through the return value of the method as
   was the case with the old SetFeature() method in MITAB 1.x.
 
-- Added Visual Studio Project files in contrib/vcproj, contributed by 
+- Added Visual Studio Project files in contrib/vcproj, contributed by
   Tony Wells (bug 1877)
 
 - Updated contrib/mitab_dyn.pas and contrib/mitab.vb for V1.7.0 changes
@@ -48,7 +48,7 @@ Version 2.0-dev (CVS)
 
 - Fixed deprecated warnings generated by mitab.h (bug 1907)
 
-- Fixed multi-line text rendering (bug 1916) 
+- Fixed multi-line text rendering (bug 1916)
 
 - Fixed multi-line text height problem (bug 1919)
 
@@ -59,19 +59,19 @@ Version 2.0-dev (CVS)
 - Add font text styles support (bold, italic, etc.) (bug 1922)
 
 - Added Font Point styles support (halo, border) (bug 1925)
- 
+
 - C API: Added mitab_c_get_feature_count_by_type() (bug 1952)
 
 - Fixed bug: MITAB doesn't support writing DateTime type (bug 1948)
 
-- Fixed bug with the characters ",\n in the tab2tab application. (bug 
+- Fixed bug with the characters ",\n in the tab2tab application. (bug
   1945)
- 
+
 - mitab.h: Export MITABSpatialRef2CoordSys() and MITABCoordSys2SpatialRef()
-  from the DLL.  Mostly for use in GDAL 
+  from the DLL.  Mostly for use in GDAL
 
 - Added support to use OFTDateTime/OFTDate/OFTTime type when compiled with
-  OGR and fixed reading/writing support for these types. (Bug 1948 and 
+  OGR and fixed reading/writing support for these types. (Bug 1948 and
   GDAL ticket #2585)
 
 
@@ -91,7 +91,7 @@ Version 1.7.0-beta1 (2007-02-29)
 
 - Fixed the internal compressed coordinate range detection test to prevent
   possible overflow of the compressed integer coordinate values leading
-  to some coordinate errors in very rare cases while writing to TAB (bug 1854) 
+  to some coordinate errors in very rare cases while writing to TAB (bug 1854)
 
 
 Version 1.6.4 (2007-12-10)
@@ -112,14 +112,14 @@ Version 1.6.4 (2007-12-10)
 Version 1.6.3 (2007-10-12)
 --------------------------
 
-- Remove static variables that interfere with reentrancy. 
+- Remove static variables that interfere with reentrancy.
   http://trac.osgeo.org/gdal/ticket/1883
 
 
 Version 1.6.3-beta2 (2007-09-18)
 --------------------------------
 
-- Fixed another issue related to splitting of object blocks with the 
+- Fixed another issue related to splitting of object blocks with the
   optimized spatial index. The compressed coordinate origin values were
   not initialized properly before being written (bug 1732)
 
@@ -134,7 +134,7 @@ Version 1.6.3-beta1 (2007-09-14)
   index is still disabled by default in this release and we still use
   the quick (i.e. traditional) spatial index mode by default.
 
-- Fixed problem with MIF parser being confused by special attribute 
+- Fixed problem with MIF parser being confused by special attribute
   names (bug 1795)
 
 
@@ -142,7 +142,7 @@ Version 1.6.2 (2007-07-12)
 --------------------------
 
 ***   ***   ***   ***   ***
-- IMPORTANT: The optimized spatial index introduced in V1.6.0 has been 
+- IMPORTANT: The optimized spatial index introduced in V1.6.0 has been
   disabled by default in this release after we found that the current block
   splitting technique often produces files that confuse MapInfo (bug 1732).
   The Quick Spatial Index Mode is used by default until bug 1732 is fixed.
@@ -172,7 +172,7 @@ Version 1.6.2 (2007-07-12)
 - Fixed support for predefined datums with non-greenwich prime meridians per
    http://trac.osgeo.org/gdal/ticket/1416
 
-- Updated mitab_dyn.pas to support both Delphi and Kylix (contrib by 
+- Updated mitab_dyn.pas to support both Delphi and Kylix (contrib by
   UffeK and MaximV, bug 1746)
 
 - Added support for building libmitab.so shared lib (contrib by UffeK and
@@ -191,13 +191,13 @@ Version 1.6.1 (2007-03-30)
 
 - Added mitab_c_set_quick_spatial_index_mode() to C API (bug 1669)
 
-- Fixed problem writing collections where MITAB was sometimes trying to 
+- Fixed problem writing collections where MITAB was sometimes trying to
   read past EOF in write mode (bug 1657).
 
-- Fixed another problem writing collections when the header of objects 
+- Fixed another problem writing collections when the header of objects
   part of a collection were split on multiple blocks (bug 1663)
 
-- Added missing NULL pointer checks in SetPenFromStyleString(), 
+- Added missing NULL pointer checks in SetPenFromStyleString(),
   SetBrushFromStyleString() and SetSymbolFromStyleString() (bug 1670)
 
 
@@ -205,8 +205,8 @@ Version 1.6.0 (2007-02-15)
 --------------------------
 
 - Improved generation of the .map's internal spatial index and object
-  data blocks to produce an optimal r-tree, resulting in performance 
-  improvements of up to 30 times faster on some spatial searches, 
+  data blocks to produce an optimal r-tree, resulting in performance
+  improvements of up to 30 times faster on some spatial searches,
   matching the performance of files generated by MapInfo. (bug 1585)
   (Thanks to Aircom International (Andrew Blake) for funding this.)
 
@@ -222,24 +222,24 @@ Version 1.5.1 (2006-07-25)
 
 - Fixed initialization of MBR of TABCollection members (bug 1520)
 
-- Added mapping for datum name "North_American_Datum_1927". 
+- Added mapping for datum name "North_American_Datum_1927".
 
-- Fixed problem with uninitialized affine parameters written to .MAP header, 
-  resulting in files not readable in MapInfo, introduced by bug 1155 in 
+- Fixed problem with uninitialized affine parameters written to .MAP header,
+  resulting in files not readable in MapInfo, introduced by bug 1155 in
   MITAB 1.5.0 (bug 1254, 1319)
 
 - Fixed problem writing PLINE MULTIPLE to TAB format introduced in
   MITAB 1.5.0 (bug 1466).
 
 - tab2tab: Set dataset bounds only after setting spatialref to prevent
-  default coordsys bounds from taking precedence when bounds are 
+  default coordsys bounds from taking precedence when bounds are
   available in source dataset (bug 1511)
 
 - Coordsys false easting and northing are in the units of the coordsys, not
-  necessarily meters.  Adjusted mitab_coordsys.cpp to reflect this. 
+  necessarily meters.  Adjusted mitab_coordsys.cpp to reflect this.
   http://bugzilla.remotesensing.org/show_bug.cgi?id=1113
 
-- Similar problem in mitab_spatialref.cpp for TAB files also fixed. 
+- Similar problem in mitab_spatialref.cpp for TAB files also fixed.
   http://bugzilla.remotesensing.org/show_bug.cgi?id=1113
 
 
@@ -299,7 +299,7 @@ Version 1.5.0-beta1 (2005-10-07)
      - mitab_c_get_affine_params()
      - mitab_c_set_affine_params()
 
-- All datum definitions in mitab_spatialref.cpp now have the correct 
+- All datum definitions in mitab_spatialref.cpp now have the correct
   names (Anthony D, bug 1155)
 
 - Added bounds entries for Finnish KKJ and Swedish projections (AJD, bug 1155)
@@ -308,7 +308,7 @@ Version 1.5.0-beta1 (2005-10-07)
 
 - gcc4 related warnings in mitab_coordsys.cpp and mitab_utils.cpp avoided.
 
-- Change the way \n and \ are handled internally. Now they are stored 
+- Change the way \n and \ are handled internally. Now they are stored
   unescaped in memory and escaped only when writing MIF files. (bug 1107)
 
 - Improved handling of Danish modified TM proj#21-24 (HSS, bugs 976,1010)
@@ -327,28 +327,28 @@ Version 1.5.0-beta1 (2005-10-07)
 
 - A few fixes to support for modified TM projections #21-24 (AJD, bug 1155)
 
-- Fixed missing initialization of default .MID file delimiter ("\t") 
+- Fixed missing initialization of default .MID file delimiter ("\t")
   (Anthony D - bugs 1155 and 37)
 
 
 Version 1.4.0 (2005-04-01)
 --------------------------
 
- - Added bounds entry to match datum 1011 based on MapInfo's "Svenska 
+ - Added bounds entry to match datum 1011 based on MapInfo's "Svenska
    rikssystemet, 2,5 gon väst (RT 90 7 parametrar)" (bug 997)
 
  - Added initial version of .NET bindings, contributed by Graham Sims in
    mitab/contrib/dotnet directory (bug 992)
 
  - Added support for Datum Id field in .MAP header, this is new in MapInfo
-   7.8+ and solves problem with multiple datums with same params (bug 910) 
+   7.8+ and solves problem with multiple datums with same params (bug 910)
 
  - Fixed internal integer coordinates rounding error (bug 894)
 
  - Fixed potential memory leaks in error conditions in mitab_feature.cpp
    and mitab_rawbinblock.cpp (bug 881)
 
- - Support pen width bigger than 7. Note that any pen bigger than 10 are 
+ - Support pen width bigger than 7. Note that any pen bigger than 10 are
    considered as point, not pixel. (bug 683)
 
  - Updated list of datum parameters from data made available by Bill Wemple
@@ -358,13 +358,13 @@ Version 1.4.0 (2005-04-01)
  - Do not output a BG color in style string for transparent brushes (bug 693)
 
  - mitab_tabfile.cpp: Several fixes for TABFile::Open() when loading the
-   tabfile fails. (provided by Stephen Cheesman). 
+   tabfile fails. (provided by Stephen Cheesman).
 
  - mitab_mapfile.cpp: Fixed error return value in LoadNextMatchingObjectBlock()
    per http://bugzilla.remotesensing.org/show_bug.cgi?id=615. NFW
 
- - mitab_ogr_datasource.cpp: Modified CreateLayer() to use 
-   -1000,-1000,1000,1000 bounds for GEOGCS much like in mitab_bounds.cpp. 
+ - mitab_ogr_datasource.cpp: Modified CreateLayer() to use
+   -1000,-1000,1000,1000 bounds for GEOGCS much like in mitab_bounds.cpp.
    This ensures that geographic files in the range 0-360 works as well as
    -180 to 180.
 
@@ -372,14 +372,14 @@ Version 1.4.0 (2005-04-01)
 Version 1.3.0 (2004-07-07)
 --------------------------
 
- - Use tab as default delimiter (if none is explicitly specified) when 
-   reading .MIF/.MID files (Anthony D, bug 37)  We still generate new files 
+ - Use tab as default delimiter (if none is explicitly specified) when
+   reading .MIF/.MID files (Anthony D, bug 37)  We still generate new files
    using comma as delimiter.
 
  - C API: Added mitab_c_get_feature_count() and mitab_c_get_field_as_double(),
    added ability to create a feature of type TABFC_NoGeom (Anthony D)
 
- - Added support for reading affine coordsys parameters in extended 
+ - Added support for reading affine coordsys parameters in extended
    .map header block of v500+  (Anthony D, bug 41)
 
  - Added mitab_c_getlibversion() to C API. (Uffe K. - bug 21)
@@ -404,7 +404,7 @@ Version 1.3.0 (2004-07-07)
    It is important to cleanup other used memory.
 
  - mitab_coordsys.cpp: fixed small memory leak for non-earth coordinate
-   systems.  (bug supplied by Stephen Cheeseman, Geosoft). 
+   systems.  (bug supplied by Stephen Cheeseman, Geosoft).
 
  - Added mitab_c_load_coordsys_table() to C API (bug 469)
 
@@ -416,7 +416,7 @@ Version 1.2.4 (2003-07-23)
 --------------------------
 
  - Added 'indexed' and 'unique' parameters to mitab_c_add_field().
-   Applications written for older versions of the C API will have to 
+   Applications written for older versions of the C API will have to
    be updated to pass these two new parameters.
 
  - Ensure that a blank line in a mid file is treated as one field containing
@@ -424,7 +424,7 @@ Version 1.2.4 (2003-07-23)
 
  - Fixes to support mif/mid files produced by Geomedia V5 (bug 1631):
     - Do not produce an error if .mid data records end with a stray ','
-    - Treat tabs (\t) as a blank space delimiter when reading coordinate 
+    - Treat tabs (\t) as a blank space delimiter when reading coordinate
       values in .mif file
 
  - Fixed sign of rotation parameters in TOWGS84 parameters in WKT.  MapInfo
@@ -466,7 +466,7 @@ Version 1.2.3 - (2002-10-15)
 
 - Fixed lots of places that check for errors by examining CPLGetLastErrorNo().
   A warning will trigger all these places as an error.  Changed to check that
-  the last error type was CE_Failure and add a CPLErrorReset() at the 
+  the last error type was CE_Failure and add a CPLErrorReset() at the
   beginning of many affected sections.  NFW
 
 - Modified TABGetBasename() (in mitab_utils.cpp) to stop at the first
@@ -479,38 +479,38 @@ Version 1.2.3 - (2002-10-15)
 - Fix memory leak of m_pszIndex in mitab_miffile.cpp, the poSpatialRef
   in TABFile::SetMIFCoordSys(), and a leak in MITABExtractCoordSysBounds(). NFW
 
-- Added untested support in mitab_spatialref.cpp, and mitab_coordsys.cpp for 
-  projections Regional Mercator (26), Polyconic (27), Azimuthal Equidistant - 
-  All origin latitudes (28), and Lambert Azimuthal Equal Area - any aspect 
+- Added untested support in mitab_spatialref.cpp, and mitab_coordsys.cpp for
+  projections Regional Mercator (26), Polyconic (27), Azimuthal Equidistant -
+  All origin latitudes (28), and Lambert Azimuthal Equal Area - any aspect
   (29). NFW
 
 
 Version 1.2.2 - (2002-07-06)
 ----------------------------
 
-- Added a validation in TABMAPFile::GetFeatureId(). When there's no .map file 
+- Added a validation in TABMAPFile::GetFeatureId(). When there's no .map file
   or no spatial indexes or no geometry, the function return -1 like an Eof.
   This prevent the reading of a file set to NULL. (bug 169 (MapServer))
 
 - Treat Region as MultiPolygon in mitab_c_set_point() to support Regions
-  with multiple islands and holes. Passing a part number <= 0 (second 
-  parameter in mitab_c_set_point()) will result in adding a new island 
+  with multiple islands and holes. Passing a part number <= 0 (second
+  parameter in mitab_c_set_point()) will result in adding a new island
   (i.e. polygon).  By default, parts > 1 are treated as holes in the
   last island (polygon) that was created.
 
-- Added IsInteriorRing() function in the TABRegion class to validate if a ring 
-  in a polygon is an external or an internal ring. The function returns 
-  true if the specified ring is an interior ring. The function 
-  mitab_c_is_interior_ring() in mitab_capi.c has been created too to call 
+- Added IsInteriorRing() function in the TABRegion class to validate if a ring
+  in a polygon is an external or an internal ring. The function returns
+  true if the specified ring is an interior ring. The function
+  mitab_c_is_interior_ring() in mitab_capi.c has been created too to call
   IsInteriorRing() if the feature is a region.
 
-- In mitab_mapheaderblock.cpp, the Coordsys2Int() function used integer values 
+- In mitab_mapheaderblock.cpp, the Coordsys2Int() function used integer values
   to check for overflow. However, in some case, integer was to small and caused
-  problems with applications that called SetSpatialFilter() with a filter 
-  much larger than the file's bounds.  So, this function now uses doubles 
+  problems with applications that called SetSpatialFilter() with a filter
+  much larger than the file's bounds.  So, this function now uses doubles
   internally for comparison, but still returns and receives integers.
 
-- Add SetSpatialFilter function in the TABSeamless class, to use seamless 
+- Add SetSpatialFilter function in the TABSeamless class, to use seamless
   layer in the right way. Now, the filter is applied on each data file and
   on the index file. (Bug 164 (MapServer))
 
@@ -518,12 +518,12 @@ Version 1.2.2 - (2002-07-06)
 Version 1.2.1 - (2002-05-08)
 ----------------------------
 
-- Implement SetMIFCoordSys in the MIFFile class. The coordsys was not 
-  written when calling mitab_c_create for MIF files because 
+- Implement SetMIFCoordSys in the MIFFile class. The coordsys was not
+  written when calling mitab_c_create for MIF files because
   MIFFile::SetMIFCoordSys always returned -1 (Bug 984).
 
 - Added support for TABFC_FontPoint and TABFC_CustomPoint in
-  mitab_c_create_feature(), mitab_c_set_points(), mitab_c_set_font() and 
+  mitab_c_create_feature(), mitab_c_set_points(), mitab_c_set_font() and
   mitab_c_get_font().
 
 - mitab_capi.h: Use stdcall by default for all public mitab.dll functions
@@ -536,13 +536,13 @@ Version 1.2.0 - (2002-05-03)
 
 - Made changes in TABRelation to avoid an infinite loop. The m_poCurFeature
   object have been deleted and the function GetFeatureRef() have been replace
-  by GetFeature(). This new function return a TABFeature object that must be 
+  by GetFeature(). This new function return a TABFeature object that must be
   control by the calling method. (bug 706)
 
-- Made important changes in order to support writing objects in 16 bits 
-  coordinate format. New TABMAPObjHdr-derived classes are used to hold 
-  object info in memory until block is full. 
-  This was required in order to fix a problem when very small regions 
+- Made important changes in order to support writing objects in 16 bits
+  coordinate format. New TABMAPObjHdr-derived classes are used to hold
+  object info in memory until block is full.
+  This was required in order to fix a problem when very small regions
   were written in 32 bits coordinates when 16 bits should have been used
   because MBR < 65536.  In this case MapInfo would attempt to rewrite the
   modified object info in 16 bits format while the coordinates blocks are
@@ -552,7 +552,7 @@ Version 1.2.0 - (2002-05-03)
 
 - Prevent writing of coordinates outside of the +/-1e9 integer bounds.
   If coordinates outside of that range are written then the values are
-  written as +/-1e9 instead and a warning (ERROR 503) is produced when 
+  written as +/-1e9 instead and a warning (ERROR 503) is produced when
   the file is closed.  Coordinates outside of the +/-1e9 bounds limits
   seemed to confuse MapInfo.
 
@@ -560,14 +560,14 @@ Version 1.2.0 - (2002-05-03)
   integer bounds in SetCoordFilter().
 
 - Modified the conversion of double to integer coordinates to fix an old
-  problem where coordinates written by MITAB would be a little bit off 
+  problem where coordinates written by MITAB would be a little bit off
   sometimes compared with the same values written by MapInfo.
 
 - Modified mitab_capi.cpp to correctly produce "point" style arcs from
   mitab_c_set_arc().  It now sets a point geometry ensuring that the
   TABArc::ValidateMapInfoType() method will succeed.  As per DMSG Bug 644. NFW
 
-- Fixed some TABView issues (bug 703): 
+- Fixed some TABView issues (bug 703):
   - Support "select * ..." syntax
   - Accept source table names with or without the .tab extension
   - Avoid crash if .IND file for related table is missing (i.e. deleted)
@@ -576,14 +576,14 @@ Version 1.2.0 - (2002-05-03)
   create a dataset of mif files instead of tab files. NFW
 
 - Prevent an infinite loop of calls to LoadNextMatchingObjectBlock() in
-  GetNextFeatureId() if no objects found in spatial index when using a 
+  GetNextFeatureId() if no objects found in spatial index when using a
   spatial filter.
 
 - False Easting/Northing should be in the linear units of measure in MapInfo,
-  but in OGRSpatialReference/WKT they are always in meters.  Convert 
+  but in OGRSpatialReference/WKT they are always in meters.  Convert
   accordingly in mitab_coordsys.cpp and mitab_spatialref.cpp.  NFW
 
-- Added support for reading and writing new V650 Multipoint for both TAB and 
+- Added support for reading and writing new V650 Multipoint for both TAB and
   MIF.
 
 - Added support for Cassini Soldner projection (projection 30). NFW
@@ -615,7 +615,7 @@ Version 1.1.3 - (2001-11-02)
   when calculating text height.
 
 - Test for NULL geometries if spatial filter enabled in GetNextFeature()
-  (objects with NONE geometry would have caused a crash when a spatial 
+  (objects with NONE geometry would have caused a crash when a spatial
    filter was set).
 
 - Fixed a few memory leaks in mitab_miffile.cpp.  NFW.
@@ -638,7 +638,7 @@ Version 1.1.3 - (2001-11-02)
 - Seamless files: when reading on Unix, replace '\\' with '/' in file path
   read from the index table.
 
-- Modified mitab_miffile.cpp to keep track of the feature id of the 
+- Modified mitab_miffile.cpp to keep track of the feature id of the
   preloaded text line in m_nPreloadedId instead of m_nCurFeatureId to fix
   serious problems with access through IMapInfo::GetNextFeature() - this
   affects applications using the pure OGRLayer API to access mif files. NFW
@@ -649,14 +649,14 @@ Version 1.1.3 - (2001-11-02)
 - mitab_miffile.cpp: modified to return extents collected by PreParse.  Made
   distinction between extents and projection bounds explicit.  NFW
 
-- mitab_spatialref.cpp: added OGC name for datum 12. 
+- mitab_spatialref.cpp: added OGC name for datum 12.
 
 
 Version 1.1.2 - (2001-06-24)
 ----------------------------
 
 - Support reading and writing TEXT objects with strings longer than 512
-  bytes.  MITABMAPCoordBlock's Read/WriteBytes() had to be fixed to 
+  bytes.  MITABMAPCoordBlock's Read/WriteBytes() had to be fixed to
   allow reading/writing data split over more than 2 blocks.
 
 - StyleString fixes: include font name in text style string, and placed
@@ -672,11 +672,11 @@ Version 1.1.2 - (2001-06-24)
 Version 1.1.1 - (2001-05-01)
 ----------------------------
 
-- Added implementation for OGRLayer::GetExtent() that returns extents 
+- Added implementation for OGRLayer::GetExtent() that returns extents
   of the data, which is different from the bounds of the projection.
 
-- Added code to set TOWGS84 values for mitab_coordsys.cpp and 
-  mitab_spatialref.cpp.  
+- Added code to set TOWGS84 values for mitab_coordsys.cpp and
+  mitab_spatialref.cpp.
 
   See http://bugzilla.remotesensing.org/show_bug.cgi?id=41
 
@@ -704,14 +704,14 @@ Version 1.1.0 - (2001-03-08)
 
 - Make default and max char field with 254 chars in TABFile::AddFieldNative()
 
-- Added a warning (TAB_WarningBoundsOverflow) on close of .MAP file if any 
-  object was written with coordinates outside of the file's predefined 
+- Added a warning (TAB_WarningBoundsOverflow) on close of .MAP file if any
+  object was written with coordinates outside of the file's predefined
   bounds.  (Causing an overflow of the +/-1e9 integer coord. range)
 
 - Use MI defaults for Pen, Brush, Font, Symbol when creating new objects
   and when reading objects with no Pen, Brush, etc. set (used to just set
   everything to zero which was inconsistent with MI's behavior)
-  New defaults are: PEN(1,2,0), BRUSH(2,16777215,16777215), 
+  New defaults are: PEN(1,2,0), BRUSH(2,16777215,16777215),
   FONT("Arial",0,0,0), SYMBOL(35,0,12)
 
 - Accept "TABLE TYPE LINKED" and handle them the same way as type NATIVE
@@ -730,8 +730,8 @@ Version 1.1.0 - (2001-03-08)
 
 - Fixed small memory leak in OGRTABDataSource::CreateLayer() (NFW)
 
-- Support SpatialFilter inside IMapInfoFile::GetNextFeature().  
-  TAB files should support spatial filter via their spatial index for 
+- Support SpatialFilter inside IMapInfoFile::GetNextFeature().
+  TAB files should support spatial filter via their spatial index for
   optimal performance.
 
 - Avoid unnecessary cloning of features in IMapInfoFile::GetNextFeature() and
@@ -740,7 +740,7 @@ Version 1.1.0 - (2001-03-08)
 - Added TABText::Get/SetTextLineEndPoint() and properly read/write label
   line end point in TAB files.
 
-- Fixed writing MIF header: for decimal fields, an extra field of type 
+- Fixed writing MIF header: for decimal fields, an extra field of type
   logical with same name was always added because of a missing break; (Kieron)
 
 - Added support for reading seamless TAB files (TABSeamless class)
@@ -751,13 +751,13 @@ Version 1.1.0 - (2001-03-08)
 Version 1.0.4 - (2000-11-14)
 ----------------------------
 
-- Fixed a problem writing indexes - When a new entry was inserted at the 
-  beginning of an index node (changing this node's key) then the parent was 
+- Fixed a problem writing indexes - When a new entry was inserted at the
+  beginning of an index node (changing this node's key) then the parent was
   not properly updated and some records were not queryable through that index.
 
 - Handle '\t' just like a space when parsing mif files.
 
-- Fixed MIFFile::GotoFeature() to avoid calling ResetReading() before moving 
+- Fixed MIFFile::GotoFeature() to avoid calling ResetReading() before moving
   forward.
 
 - Fixed writing of drawing tool blocks - when more than 512 bytes worth of
@@ -771,15 +771,15 @@ Version 1.0.3 - (2000-10-19)
 - Fixed reading of MAPCoordBlocks to accept text strings that overlap on
   2 data blocks.
 
-- Added graceful recovery from NULL OGRSpatialReference pointers in 
+- Added graceful recovery from NULL OGRSpatialReference pointers in
   mitab_capi.cpp, and mitab_spatialref.cpp (NFW).
 
-- Added what I hope to be working support for NonEarth translation 
+- Added what I hope to be working support for NonEarth translation
   (into LOCAL_CS in WKT format) (NFW).
 
 - Initialize m_dWidth to 0 in TABText constructor. (NFW)
 
-- Made TABFile::GetBounds() return bounds corresponding to the +/- 1e9 
+- Made TABFile::GetBounds() return bounds corresponding to the +/- 1e9
   integer coordinate limits instead of using min/max int. coord. from header
 
 
@@ -815,8 +815,8 @@ Version 1.0.2 - (2000-10-03)
 
 - Added support for writing arcs, ellipses and rectangles using the C API
 
-- Flushed tab2mif.cpp and mif2tab.cpp.  There is now a single tab2tab.cpp 
-  conversion program that can generate both TAB or MIF output, depending 
+- Flushed tab2mif.cpp and mif2tab.cpp.  There is now a single tab2tab.cpp
+  conversion program that can generate both TAB or MIF output, depending
   on output filename extension
 
 - Added #define MITAB_VERSION for apps that want to report library version.
@@ -829,7 +829,7 @@ Version 1.0.1 - (2000-04-21)
   and field information and included C API in public release.
 
 - Modified filtering of new table field name to accept extended chars with
-  accents. 
+  accents.
 
 
 Version 1.0 - (2000-03-26)
@@ -839,10 +839,10 @@ Version 1.0 - (2000-03-26)
 
 - Fixed problem opening datasets with 0 features in them.
 
-- Added support for reading TAB datasets with "Table Type DBF"... only 
+- Added support for reading TAB datasets with "Table Type DBF"... only
   type "NATIVE" was supported until now.
 
-- Produce only a warning when unsupported feature types encountered in the 
+- Produce only a warning when unsupported feature types encountered in the
   .MAP file, and return a valid feature with a NONE geometry.
 
 - Done more tests (and required changes) to fix the way the quadrant
@@ -857,21 +857,21 @@ Version 1.0 - (2000-03-26)
   9999 datums with big parameter values or with some unrecognized projections.
 
 - Outside/inside ring relationship from a TABRegion's OGRPolygon is now
-  properly written to the .MAP file's coord block section header.  
-  Prior to MapInfo 5.0, this info was ignored, but now it has to be valid 
+  properly written to the .MAP file's coord block section header.
+  Prior to MapInfo 5.0, this info was ignored, but now it has to be valid
   otherwise some parts of a region won't be displayed properly in MI5.0
 
 - Added support to write indexed fields and create joined tables (TABView).
 
-- Added validation on field names (no special chars) on write and 
+- Added validation on field names (no special chars) on write and
   produce a warning if name had to be fixed.
 
 - Added support for V450 object types with num_points > 32767 and for
-  pen width in points.  
-  This also resulted in changes to the ITABFeaturePen methods, mainly the 
-  Get/SetPenStyle() method has been removed since this style value was 
-  actually a part of the point width value.  
-  Finally, the 'style' parameter was also removed in the 
+  pen width in points.
+  This also resulted in changes to the ITABFeaturePen methods, mainly the
+  Get/SetPenStyle() method has been removed since this style value was
+  actually a part of the point width value.
+  Finally, the 'style' parameter was also removed in the
   mitab_c_set_pen() C API method.
 
 - Support for Version 450 objects forced creation of version 500 .MAP files
@@ -917,9 +917,9 @@ Version 0.2 - (1999-12-20)
    with multiple rings.  This change had to be done because OGRPolygons
    MUST have only one outer ring with a set of inner rings, and this
    cannot be guaranteed to be the case with a MapInfo file.
-   Also added TABRegion::GetNumRings() and TABRegion::GetRing() to 
-   make it simpler to manipulate the complex geometry as if it was a 
-   simple collection of rings which is actually what we have in the 
+   Also added TABRegion::GetNumRings() and TABRegion::GetRing() to
+   make it simpler to manipulate the complex geometry as if it was a
+   simple collection of rings which is actually what we have in the
    MapInfo model.
 
  - Fixed some problems with MIF generation of Float fields and PLINE MULTIPLE
diff --git a/ogr/ogrsf_frmts/mitab/README.TXT b/ogr/ogrsf_frmts/mitab/README.TXT
index 528e80f..965ce0a 100644
--- a/ogr/ogrsf_frmts/mitab/README.TXT
+++ b/ogr/ogrsf_frmts/mitab/README.TXT
@@ -17,11 +17,11 @@ Please also visit the following URLs:
 COPYRIGHT AND LICENSE TERMS:
 ----------------------------
 
-The most part of the MITAB library is 
+The most part of the MITAB library is
    Copyright (c) 1998-2005, Daniel Morissette (morissette at dmsolutions.ca)
 it also contains parts and uses support libraries that are
    Copyright (c) 1998-2005, Frank Warmerdam (warmerdam at pobox.com)
-and 
+and
    Copyright (c) 1999, 2000, Stephane Villeneuve (stephane.v at videotron.ca)
 
 The MITAB library, and its supporting libraries (OGR and CPL) are freely
@@ -38,16 +38,16 @@ available under the following OpenSource license terms:
  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  * and/or sell copies of the Software, and to permit persons to whom the
  * Software is furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  **********************************************************************
 
@@ -55,7 +55,7 @@ available under the following OpenSource license terms:
 USING THE TAB2TAB CONVERSION PROGRAM:
 -------------------------------------
 
-MITAB comes with a conversion program called TAB2TAB that can do tab-to-mif 
+MITAB comes with a conversion program called TAB2TAB that can do tab-to-mif
 and mif-to-tab translations:
 
 Usage: tab2tab <src_filename> <dst_filename>
@@ -66,18 +66,18 @@ Usage: tab2tab <src_filename> <dst_filename>
 COMPILING THE LIBRARY:
 ----------------------
 
-When you extract the ZIP (or .tar.gz) file, you will get 3 directories 
-and the makefiles to compile the library using VC++ 6 under Windows or 
-using GNU make and GCC on Unix.  
+When you extract the ZIP (or .tar.gz) file, you will get 3 directories
+and the makefiles to compile the library using VC++ 6 under Windows or
+using GNU make and GCC on Unix.
 
-The MITAB directory contains the core of the library and the TAB2TAB 
+The MITAB directory contains the core of the library and the TAB2TAB
 conversion program.
 The OGR and CPL directories are support libraries used by MITAB and probably
 won't be of much interest to you at the beginning.
 
-To compile the lib on Windows: 
+To compile the lib on Windows:
   In a DOS prompt, setup the VC++ environment variables by executing
-  VCVARS32.BAT (somewhere in your VC++ install) and start the build 
+  VCVARS32.BAT (somewhere in your VC++ install) and start the build
   using:
         nmake -f makefile.vc
 
@@ -89,12 +89,12 @@ To compile the lib on Windows:
 
 To compile the library on Unix:
 
-  The main directory contains a GNUmakefile whose default target will 
+  The main directory contains a GNUmakefile whose default target will
   compile the contents of the 3 sub-directories and the test programs
   in the mitab directory.
 
   Note about byte ordering: by default, the library is built for systems
-  with LSB first (Intel) byte ordering.  To build the library on systems 
+  with LSB first (Intel) byte ordering.  To build the library on systems
   that use MSB first byte ordering (such as SUN systems), you should add
   the "-DCPL_MSB" flag to the compile flags in the "GNUmake.opt" file.
 
@@ -113,9 +113,9 @@ There are 2 interfaces to access the library:
    Bo Thomsen)
 
 2- The C++ API will give you full access to every feature of the MapInfo
-   data model.  Unfortunately there is no complete documentation for the 
-   library's C++ classes yet, but tab2tab.cpp is a good example that 
-   shows how to open TAB files for read and write.  Also, the main 
+   data model.  Unfortunately there is no complete documentation for the
+   library's C++ classes yet, but tab2tab.cpp is a good example that
+   shows how to open TAB files for read and write.  Also, the main
    classes you will need to deal with live in the header MITAB.H.
 
 
@@ -139,13 +139,13 @@ to the type of file that was opened:
                   Note that you cannot use it to modify existing datasets
                   (not yet!).
 
-  class TABView:  Class to handle views on pairs of .TAB files linked 
+  class TABView:  Class to handle views on pairs of .TAB files linked
                   through an indexed field of type integer.
 
   class MIFFile:  Class to handle MIF files for read/write.
 
 
-The method IMapInfoFile::GetFileClass() can be used to establish the 
+The method IMapInfoFile::GetFileClass() can be used to establish the
 type of object that has been returned by SmartOpen().
 
 
@@ -153,7 +153,7 @@ TO CREATE NEW FILES:
 --------------------
 
 For write access, you create an instance of TABFile or MIFFile and use
-it to open the new file and write to it.  Note that only sequential write is 
+it to open the new file and write to it.  Note that only sequential write is
 supported.
 
 
@@ -164,7 +164,7 @@ On read access, GetFeatureRef() returns object of classes derived from
 class TABFeature.  You can tell the type of an object using the method
 TABFeature::GetFeatureClass().
 
-The following table lists the various feature types and the geometry 
+The following table lists the various feature types and the geometry
 types that can be returned and that are accepted (for writing) by each
 of them:
 
@@ -182,16 +182,16 @@ of them:
 
     TABRegion        OGRPolygon (with a     OGRPolygon (with 1 or more
                      single ring) or        rings) or OGRMultiPolygon
-                     OGRMultiPolygon (for 
+                     OGRMultiPolygon (for
                      multiple rings)
 
     TABRectangle     OGRPolygon             OGRPolygon
 
-    TABEllipse       OGRPolygon             OGRPolygon or 
+    TABEllipse       OGRPolygon             OGRPolygon or
                                             OGRPoint corresponding to the
                                             ellipse center
 
-    TABArc           OGRLineString          OGRLineString or 
+    TABArc           OGRLineString          OGRLineString or
                                             OGRPoint corresponding to the
                                             arc's defining ellipse center
 
@@ -214,7 +214,7 @@ NOTE ABOUT "\n" IN STRINGS ON TABText OBJECTS:
 ----------------------------------------------
 
 The text strings on text object may contain embedded "\n" characters in
-MapInfo.  
+MapInfo.
 
 In those cases, the library returns strings in which the "\n" character
 is escaped on two characters: "\" + "n"
@@ -225,8 +225,8 @@ strings into a binary "\n" when it writes text objects to TAB files.
 This also implies that a single "\" character also has to be converted
 to "\"+"\".
 
-Also note that this conversion does not apply to table fields of type 
-"Char" since there appears to be no special treatment in MapInfo for 
+Also note that this conversion does not apply to table fields of type
+"Char" since there appears to be no special treatment in MapInfo for
 the "\n" sequence in char attribute field values.
 
 
diff --git a/ogr/ogrsf_frmts/mitab/TODO.TXT b/ogr/ogrsf_frmts/mitab/TODO.TXT
index de6e846..3237ce2 100644
--- a/ogr/ogrsf_frmts/mitab/TODO.TXT
+++ b/ogr/ogrsf_frmts/mitab/TODO.TXT
@@ -12,7 +12,7 @@ MITAB Library - ToDo, Open Questions:
 
  - TABView support:
      - Complete and tested only for cases in which 2 tables
-       are linked with a many-to-1 relation through an integer field.  
+       are linked with a many-to-1 relation through an integer field.
      - The merge operation involves 3 features in memory and cloning the
        geometry... this could perhaps be optimized but would require changes
        at the lower-level in the lib.
@@ -21,19 +21,19 @@ MITAB Library - ToDo, Open Questions:
 
  - "Table Type DBF" are supported for reading, but no charset conversion
    is done... however, when the same datasets are exported to MIF by MapInfo
-   it apparently converts the DBF file's charset (e.g. CodePage863) to 
+   it apparently converts the DBF file's charset (e.g. CodePage863) to
    the dataset charset (e.g. WindowsLatin1)
 
  - Will we ever want to support Table Type ACCESS?
 
  - When regions with multiple rings are read from MIF, the inside/outside
    ring relationship is not reconstructed.  This may cause display problems
-   when MIF files containing regions are converted to TAB: it has been 
+   when MIF files containing regions are converted to TAB: it has been
    reported that some regions may not be filled properly when viewed in
    MapInfo Versions 5.0 and up when the inside/outside ring relationship
    is not properly written.
 
 
 ------------
-$Id: TODO.TXT 11171 2007-04-02 19:04:13Z dmorissette $
+$Id: TODO.TXT 35222 2016-08-28 06:06:11Z goatbar $
 ------------
diff --git a/ogr/ogrsf_frmts/mitab/mitab.h b/ogr/ogrsf_frmts/mitab/mitab.h
index 6b5dbfd..d4ed339 100644
--- a/ogr/ogrsf_frmts/mitab/mitab.h
+++ b/ogr/ogrsf_frmts/mitab/mitab.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab.h,v 1.121 2010-10-08 18:38:13 aboudreault Exp $
+ * $Id: mitab.h 37335 2017-02-09 14:29:57Z goatbar $
  *
  * Name:     mitab.h
  * Project:  MapInfo TAB Read/Write library
@@ -28,89 +28,6 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab.h,v $
- * Revision 1.121  2010-10-08 18:38:13  aboudreault
- * Added attribute index support for the sql queries in mapinfo tab format (GDAL bug #3687)
- *
- * Revision 1.120  2010-01-07 20:39:11  aboudreault
- * Added support to handle duplicate field names, Added validation to check if a field name start with a number (bug 2141)
- *
- * Revision 1.119  2009-07-28 21:35:29  aboudreault
- * Added functions to get the file version (bug 1961)
- *
- * Revision 1.118  2009-03-10 13:50:02  aboudreault
- * Fixed Overflow of FIDs in Seamless tables (bug 2015)
- *
- * Revision 1.117  2008-10-29 12:55:10  dmorissette
- * Update version to 2.0.0-dev (2008-10) for GDAL 1.6.0 release
- *
- * Revision 1.116  2008/08/22 16:14:19  fwarmerdam
- * export spatialref/coordsys transformers
- *
- * Revision 1.115  2008/07/21 14:09:41  aboudreault
- * Add font text styles support (bold, italic, etc.) (bug 1922)
- *
- * Revision 1.114  2008/07/17 14:09:30  aboudreault
- * Add text outline color support (halo background in MapInfo)
- *
- * Revision 1.113  2008/07/01 14:33:17  aboudreault
- * * Fixed deprecated warnings generated by mitab.h by moving SetFontName to
- *   mitab_feature.cpp.
- *
- * Revision 1.112  2008/03/05 20:35:39  dmorissette
- * Replace MITAB 1.x SetFeature() with a CreateFeature() for V2.x (bug 1859)
- *
- * Revision 1.111  2008/02/29 21:27:41  dmorissette
- * Update to v1.7.0-beta1
- *
- * Revision 1.110  2008/02/20 21:35:30  dmorissette
- * Added support for V800 COLLECTION of large objects (bug 1496)
- *
- * Revision 1.109  2008/02/13 21:10:43  dmorissette
- * Fixed error in TAB_GEOM_GET_VERSION() macro logic
- *
- * Revision 1.108  2008/02/05 22:21:59  dmorissette
- * Added macro TAB_GEOM_GET_VERSION()
- *
- * Revision 1.107  2008/02/01 19:55:55  dmorissette
- * Set version to 1.7.0-dev
- *
- * Revision 1.106  2008/02/01 19:36:31  dmorissette
- * Initial support for V800 REGION and MULTIPLINE (bug 1496)
- *
- * Revision 1.105  2008/01/29 21:56:39  dmorissette
- * Update dataset version properly for Date/Time/DateTime field types (#1754)
- *
- * Revision 1.104  2007/12/11 04:26:29  dmorissette
- * Update for 1.6.4 release
- *
- * Revision 1.103  2007/10/12 15:47:48  dmorissette
- * Updated for 1.6.3 release
- *
- * Revision 1.102  2007/09/18 18:13:42  dmorissette
- * Updated for 1.6.3-beta2
- *
- * Revision 1.101  2007/09/14 20:03:08  dmorissette
- * Removed stray ReadGeometryFromMAPFile() declaration
- *
- * Revision 1.100  2007/09/14 19:42:39  dmorissette
- * Updated for 1.6.3-beta1
- *
- * Revision 1.99  2007/09/14 18:30:18  dmorissette
- * Fixed the splitting of object blocks with the optimized spatial
- * index mode that was producing files with misaligned bytes that
- * confused MapInfo (bug 1732)
- *
- * Revision 1.98  2007/09/12 20:22:31  dmorissette
- * Added TABFeature::CreateFromMapInfoType()
- *
- * ...
- *
- * Revision 1.1  1999/07/12 04:18:23  daniel
- * Initial checkin
- *
  **********************************************************************/
 
 #ifndef MITAB_H_INCLUDED_
@@ -131,7 +48,6 @@
 #  define ROUND_INT(dX) ((int)((dX) < 0.0 ? (dX)-0.5 : (dX)+0.5 ))
 #endif
 
-
 #define MITAB_AREA(x1, y1, x2, y2)  ((double)((x2)-(x1))*(double)((y2)-(y1)))
 
 class TABFeature;
@@ -148,7 +64,6 @@ typedef enum
     TABFC_MIFFile
 } TABFileClass;
 
-
 /*---------------------------------------------------------------------
  *                      class IMapInfoFile
  *
@@ -160,8 +75,6 @@ typedef enum
 
 class IMapInfoFile : public OGRLayer
 {
-  private:
-
   protected:
     GIntBig             m_nCurFeatureId;
     TABFeature         *m_poCurFeature;
@@ -197,14 +110,14 @@ class IMapInfoFile : public OGRLayer
 
     ///////////////
     //  OGR methods for read support
-    virtual void        ResetReading() = 0;
-    virtual GIntBig     GetFeatureCount (int bForce) = 0;
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeature *GetFeature(GIntBig nFeatureId);
-    virtual OGRErr      ICreateFeature(OGRFeature *poFeature);
-    virtual int         TestCapability( const char * pszCap ) =0;
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) =0;
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual void        ResetReading() override = 0;
+    virtual GIntBig     GetFeatureCount (int bForce) override = 0;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
+    virtual OGRErr      ICreateFeature(OGRFeature *poFeature) override;
+    virtual int         TestCapability( const char * pszCap ) override =0;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override =0;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     ///////////////
@@ -212,7 +125,7 @@ class IMapInfoFile : public OGRLayer
     //
     virtual GIntBig GetNextFeatureId(GIntBig nPrevId) = 0;
     virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) = 0;
-    virtual OGRFeatureDefn *GetLayerDefn() = 0;
+    virtual OGRFeatureDefn *GetLayerDefn() override = 0;
 
     virtual TABFieldType GetNativeFieldType(int nFieldId) = 0;
 
@@ -220,7 +133,7 @@ class IMapInfoFile : public OGRLayer
                           double &dXMax, double &dYMax,
                           GBool bForce = TRUE ) = 0;
 
-    virtual OGRSpatialReference *GetSpatialRef() = 0;
+    virtual OGRSpatialReference *GetSpatialRef() override = 0;
 
     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
                                       int &numRegions, int &numTexts,
@@ -241,7 +154,7 @@ class IMapInfoFile : public OGRLayer
                                int nWidth=0, int nPrecision=0,
                                GBool bIndexed=FALSE, GBool bUnique=FALSE,
                                int bApproxOK = TRUE) = 0;
-    virtual OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE );
+    virtual OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE ) override;
 
     virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) = 0;
 
@@ -314,42 +227,42 @@ class TABFile CPL_FINAL : public IMapInfoFile
     TABFile();
     virtual ~TABFile();
 
-    virtual TABFileClass GetFileClass() {return TABFC_TABFile;}
+    virtual TABFileClass GetFileClass() override {return TABFC_TABFile;}
 
     virtual int Open(const char *pszFname, const char* pszAccess,
-                     GBool bTestOpenNoError = FALSE )
+                     GBool bTestOpenNoError = FALSE ) override
             { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError); }
     virtual int Open(const char *pszFname, TABAccess eAccess,
-                     GBool bTestOpenNoError = FALSE )
+                     GBool bTestOpenNoError = FALSE ) override
             { return Open(pszFname, eAccess, bTestOpenNoError, 512); }
 
     virtual int Open(const char *pszFname, TABAccess eAccess,
                      GBool bTestOpenNoError,
                      int nBlockSizeForCreate );
 
-    virtual int Close();
+    virtual int Close() override;
 
-    virtual int SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode=TRUE);
+    virtual int SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode=TRUE) override;
 
-    virtual const char *GetTableName()
+    virtual const char *GetTableName() override
                             {return m_poDefn?m_poDefn->GetName():"";};
 
-    virtual void        ResetReading();
-    virtual int         TestCapability( const char * pszCap );
-    virtual GIntBig     GetFeatureCount (int bForce);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual void        ResetReading() override;
+    virtual int         TestCapability( const char * pszCap ) override;
+    virtual GIntBig     GetFeatureCount (int bForce) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     /* Implement OGRLayer's SetFeature() for random write, only with TABFile */
-    virtual OGRErr      ISetFeature( OGRFeature * );
-    virtual OGRErr      DeleteFeature(GIntBig nFeatureId);
+    virtual OGRErr      ISetFeature( OGRFeature * ) override;
+    virtual OGRErr      DeleteFeature(GIntBig nFeatureId) override;
 
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 
     ///////////////
     // Read access specific stuff
@@ -357,17 +270,17 @@ class TABFile CPL_FINAL : public IMapInfoFile
 
     int         GetNextFeatureId_Spatial( int nPrevId );
 
-    virtual GIntBig GetNextFeatureId(GIntBig nPrevId);
-    virtual TABFeature *GetFeatureRef(GIntBig nFeatureId);
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual GIntBig GetNextFeatureId(GIntBig nPrevId) override;
+    virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual TABFieldType GetNativeFieldType(int nFieldId);
+    virtual TABFieldType GetNativeFieldType(int nFieldId) override;
 
     virtual int GetBounds(double &dXMin, double &dYMin,
                           double &dXMax, double &dYMax,
-                          GBool bForce = TRUE );
+                          GBool bForce = TRUE ) override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
     static OGRSpatialReference* GetSpatialRefFromTABProj(const TABProjInfo& sTABProj);
     static int                  GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
@@ -375,10 +288,10 @@ class TABFile CPL_FINAL : public IMapInfoFile
 
     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
                                       int &numRegions, int &numTexts,
-                                      GBool bForce = TRUE);
+                                      GBool bForce = TRUE) override;
 
-    virtual GBool IsFieldIndexed(int nFieldId);
-    virtual GBool IsFieldUnique(int /*nFieldId*/)   {return FALSE;};
+    virtual GBool IsFieldIndexed(int nFieldId) override;
+    virtual GBool IsFieldUnique(int /*nFieldId*/) override   {return FALSE;};
 
     virtual int GetVersion() { return m_nVersion; };
 
@@ -386,25 +299,25 @@ class TABFile CPL_FINAL : public IMapInfoFile
     // Write access specific stuff
     //
     virtual int SetBounds(double dXMin, double dYMin,
-                          double dXMax, double dYMax);
+                          double dXMax, double dYMax) override;
     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
-                            TABFieldType *paeMapInfoNativeFieldTypes = NULL);
+                            TABFieldType *paeMapInfoNativeFieldTypes = NULL) override;
     virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                int nWidth=0, int nPrecision=0,
                                GBool bIndexed=FALSE, GBool bUnique=FALSE,
-                               int bApproxOK = TRUE);
-    virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef);
+                               int bApproxOK = TRUE) override;
+    virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) override;
 
-    virtual OGRErr CreateFeature(TABFeature *poFeature);
+    virtual OGRErr CreateFeature(TABFeature *poFeature) override;
 
-    virtual int SetFieldIndexed(int nFieldId);
+    virtual int SetFieldIndexed(int nFieldId) override;
 
     ///////////////
     // semi-private.
-    virtual int  GetProjInfo(TABProjInfo *poPI)
+    virtual int  GetProjInfo(TABProjInfo *poPI) override
             { return m_poMAPFile->GetHeaderBlock()->GetProjInfo( poPI ); }
-    virtual int  SetProjInfo(TABProjInfo *poPI);
-    virtual int  SetMIFCoordSys(const char *pszMIFCoordSys);
+    virtual int  SetProjInfo(TABProjInfo *poPI) override;
+    virtual int  SetMIFCoordSys(const char *pszMIFCoordSys) override;
 
     int         GetFieldIndexNumber(int nFieldId);
     TABINDFile  *GetINDFileRef();
@@ -414,11 +327,10 @@ class TABFile CPL_FINAL : public IMapInfoFile
     int         WriteFeature(TABFeature *poFeature);
 
 #ifdef DEBUG
-    virtual void Dump(FILE *fpOut = NULL);
+    virtual void Dump(FILE *fpOut = NULL) override;
 #endif
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABView
  *
@@ -464,88 +376,86 @@ class TABView CPL_FINAL : public IMapInfoFile
     int         OpenForWrite(const char *pszFname );
     int         WriteTABFile();
 
-
   public:
     TABView();
     virtual ~TABView();
 
-    virtual TABFileClass GetFileClass() {return TABFC_TABView;}
+    virtual TABFileClass GetFileClass() override {return TABFC_TABView;}
 
     virtual int Open(const char *pszFname, const char* pszAccess,
-                     GBool bTestOpenNoError = FALSE ) { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError); }
+                     GBool bTestOpenNoError = FALSE ) override { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError); }
     virtual int Open(const char *pszFname, TABAccess eAccess,
-                     GBool bTestOpenNoError = FALSE );
-    virtual int Close();
+                     GBool bTestOpenNoError = FALSE ) override;
+    virtual int Close() override;
 
-    virtual int SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode=TRUE);
+    virtual int SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode=TRUE) override;
 
-    virtual const char *GetTableName()
+    virtual const char *GetTableName() override
            {return m_poRelation?m_poRelation->GetFeatureDefn()->GetName():"";};
 
-    virtual void        ResetReading();
-    virtual int         TestCapability( const char * pszCap );
-    virtual GIntBig     GetFeatureCount (int bForce);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual void        ResetReading() override;
+    virtual int         TestCapability( const char * pszCap ) override;
+    virtual GIntBig     GetFeatureCount (int bForce) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     ///////////////
     // Read access specific stuff
     //
 
-    virtual GIntBig GetNextFeatureId(GIntBig nPrevId);
-    virtual TABFeature *GetFeatureRef(GIntBig nFeatureId);
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual GIntBig GetNextFeatureId(GIntBig nPrevId) override;
+    virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual TABFieldType GetNativeFieldType(int nFieldId);
+    virtual TABFieldType GetNativeFieldType(int nFieldId) override;
 
     virtual int GetBounds(double &dXMin, double &dYMin,
                           double &dXMax, double &dYMax,
-                          GBool bForce = TRUE );
+                          GBool bForce = TRUE ) override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
                                       int &numRegions, int &numTexts,
-                                      GBool bForce = TRUE);
+                                      GBool bForce = TRUE) override;
 
-    virtual GBool IsFieldIndexed(int nFieldId);
-    virtual GBool IsFieldUnique(int nFieldId);
+    virtual GBool IsFieldIndexed(int nFieldId) override;
+    virtual GBool IsFieldUnique(int nFieldId) override;
 
     ///////////////
     // Write access specific stuff
     //
     virtual int SetBounds(double dXMin, double dYMin,
-                          double dXMax, double dYMax);
+                          double dXMax, double dYMax) override;
     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
-                           TABFieldType *paeMapInfoNativeFieldTypes=NULL);
+                           TABFieldType *paeMapInfoNativeFieldTypes=NULL) override;
     virtual int AddFieldNative(const char *pszName,
                                TABFieldType eMapInfoType,
                                int nWidth=0, int nPrecision=0,
                                GBool bIndexed=FALSE, GBool bUnique=FALSE,
-                               int bApproxOK = TRUE);
-    virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef);
+                               int bApproxOK = TRUE) override;
+    virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) override;
 
-    virtual OGRErr CreateFeature(TABFeature *poFeature);
+    virtual OGRErr CreateFeature(TABFeature *poFeature) override;
 
-    virtual int SetFieldIndexed(int nFieldId);
+    virtual int SetFieldIndexed(int nFieldId) override;
 
     ///////////////
     // semi-private.
-    virtual int  GetProjInfo(TABProjInfo *poPI)
+    virtual int  GetProjInfo(TABProjInfo *poPI) override
             { return m_nMainTableIndex!=-1?
                      m_papoTABFiles[m_nMainTableIndex]->GetProjInfo(poPI):-1; }
-    virtual int  SetProjInfo(TABProjInfo *poPI)
+    virtual int  SetProjInfo(TABProjInfo *poPI) override
             { return m_nMainTableIndex!=-1?
                      m_papoTABFiles[m_nMainTableIndex]->SetProjInfo(poPI):-1; }
-    virtual int  SetMIFCoordSys(const char * /*pszMIFCoordSys*/) {return -1;};
+    virtual int  SetMIFCoordSys(const char * /*pszMIFCoordSys*/) override {return -1;};
 
 #ifdef DEBUG
-    virtual void Dump(FILE *fpOut = NULL);
+    virtual void Dump(FILE *fpOut = NULL) override;
 #endif
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABSeamless
  *
@@ -578,66 +488,66 @@ class TABSeamless CPL_FINAL : public IMapInfoFile
                               GBool bTestOpenNoError = FALSE);
     int         OpenBaseTable(int nTableId, GBool bTestOpenNoError = FALSE);
     int         OpenNextBaseTable(GBool bTestOpenNoError =FALSE);
-    GIntBig     EncodeFeatureId(int nTableId, int nBaseFeatureId);
-    int         ExtractBaseTableId(GIntBig nEncodedFeatureId);
-    int         ExtractBaseFeatureId(GIntBig nEncodedFeatureId);
+    static GIntBig     EncodeFeatureId(int nTableId, int nBaseFeatureId);
+    static int         ExtractBaseTableId(GIntBig nEncodedFeatureId);
+    static int         ExtractBaseFeatureId(GIntBig nEncodedFeatureId);
 
   public:
     TABSeamless();
     virtual ~TABSeamless();
 
-    virtual TABFileClass GetFileClass() {return TABFC_TABSeamless;}
+    virtual TABFileClass GetFileClass() override {return TABFC_TABSeamless;}
 
     virtual int Open(const char *pszFname, const char* pszAccess,
-                     GBool bTestOpenNoError = FALSE ) { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError); }
+                     GBool bTestOpenNoError = FALSE ) override { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError); }
     virtual int Open(const char *pszFname, TABAccess eAccess,
-                     GBool bTestOpenNoError = FALSE );
-    virtual int Close();
+                     GBool bTestOpenNoError = FALSE ) override;
+    virtual int Close() override;
 
-    virtual const char *GetTableName()
+    virtual const char *GetTableName() override
            {return m_poFeatureDefnRef?m_poFeatureDefnRef->GetName():"";};
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual void        ResetReading();
-    virtual int         TestCapability( const char * pszCap );
-    virtual GIntBig     GetFeatureCount (int bForce);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual void        ResetReading() override;
+    virtual int         TestCapability( const char * pszCap ) override;
+    virtual GIntBig     GetFeatureCount (int bForce) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     ///////////////
     // Read access specific stuff
     //
 
-    virtual GIntBig GetNextFeatureId(GIntBig nPrevId);
-    virtual TABFeature *GetFeatureRef(GIntBig nFeatureId);
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual GIntBig GetNextFeatureId(GIntBig nPrevId) override;
+    virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual TABFieldType GetNativeFieldType(int nFieldId);
+    virtual TABFieldType GetNativeFieldType(int nFieldId) override;
 
     virtual int GetBounds(double &dXMin, double &dYMin,
                           double &dXMax, double &dYMax,
-                          GBool bForce = TRUE );
+                          GBool bForce = TRUE ) override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
                                       int &numRegions, int &numTexts,
-                                      GBool bForce = TRUE);
+                                      GBool bForce = TRUE) override;
 
-    virtual GBool IsFieldIndexed(int nFieldId);
-    virtual GBool IsFieldUnique(int nFieldId);
+    virtual GBool IsFieldIndexed(int nFieldId) override;
+    virtual GBool IsFieldUnique(int nFieldId) override;
 
     ///////////////
     // Write access specific stuff
     //
     virtual int SetBounds(CPL_UNUSED double dXMin, CPL_UNUSED double dYMin,
-                          CPL_UNUSED double dXMax, CPL_UNUSED double dYMax)   {return -1;}
+                          CPL_UNUSED double dXMax, CPL_UNUSED double dYMax) override   {return -1;}
     virtual int SetFeatureDefn(CPL_UNUSED OGRFeatureDefn *poFeatureDefn,
-                               CPL_UNUSED TABFieldType *paeMapInfoNativeFieldTypes=NULL)
+                               CPL_UNUSED TABFieldType *paeMapInfoNativeFieldTypes=NULL) override
                                                         {return -1;}
     virtual int AddFieldNative(CPL_UNUSED const char *pszName,
                                CPL_UNUSED TABFieldType eMapInfoType,
@@ -645,28 +555,27 @@ class TABSeamless CPL_FINAL : public IMapInfoFile
                                CPL_UNUSED int nPrecision=0,
                                CPL_UNUSED GBool bIndexed=FALSE,
                                CPL_UNUSED GBool bUnique=FALSE,
-                               CPL_UNUSED int bApproxOK = TRUE) {return -1;}
+                               CPL_UNUSED int bApproxOK = TRUE) override {return -1;}
 
-    virtual int SetSpatialRef(CPL_UNUSED OGRSpatialReference *poSpatialRef) {return -1;}
+    virtual int SetSpatialRef(CPL_UNUSED OGRSpatialReference *poSpatialRef) override {return -1;}
 
-    virtual OGRErr CreateFeature(CPL_UNUSED TABFeature *poFeature)
+    virtual OGRErr CreateFeature(CPL_UNUSED TABFeature *poFeature) override
                                         {return OGRERR_UNSUPPORTED_OPERATION;}
 
-    virtual int SetFieldIndexed(CPL_UNUSED int nFieldId) {return -1;}
+    virtual int SetFieldIndexed(CPL_UNUSED int nFieldId) override {return -1;}
 
     ///////////////
     // semi-private.
-    virtual int  GetProjInfo(TABProjInfo *poPI)
+    virtual int  GetProjInfo(TABProjInfo *poPI) override
             { return m_poIndexTable?m_poIndexTable->GetProjInfo(poPI):-1; }
-    virtual int SetProjInfo(CPL_UNUSED TABProjInfo *poPI)         { return -1; }
-    virtual int SetMIFCoordSys(const char * /*pszMIFCoordSys*/) {return -1;};
+    virtual int SetProjInfo(CPL_UNUSED TABProjInfo *poPI) override         { return -1; }
+    virtual int SetMIFCoordSys(const char * /*pszMIFCoordSys*/) override {return -1;};
 
 #ifdef DEBUG
-    virtual void Dump(FILE *fpOut = NULL);
+    virtual void Dump(FILE *fpOut = NULL) override;
 #endif
 };
 
-
 /*---------------------------------------------------------------------
  *                      class MIFFile
  *
@@ -718,7 +627,7 @@ class MIFFile CPL_FINAL : public IMapInfoFile
 
     int         m_nFeatureCount;
     int         m_nWriteFeatureId;
-    int         m_nAttribut;
+    int         m_nAttribute;
 
     ///////////////
     // Private Read access specific stuff
@@ -743,46 +652,46 @@ class MIFFile CPL_FINAL : public IMapInfoFile
     MIFFile();
     virtual ~MIFFile();
 
-    virtual TABFileClass GetFileClass() {return TABFC_MIFFile;}
+    virtual TABFileClass GetFileClass() override {return TABFC_MIFFile;}
 
     virtual int Open(const char *pszFname, const char* pszAccess,
-                     GBool bTestOpenNoError = FALSE ) { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError); }
+                     GBool bTestOpenNoError = FALSE ) override { return IMapInfoFile::Open(pszFname, pszAccess, bTestOpenNoError); }
     virtual int Open(const char *pszFname, TABAccess eAccess,
-                     GBool bTestOpenNoError = FALSE );
-    virtual int Close();
+                     GBool bTestOpenNoError = FALSE ) override;
+    virtual int Close() override;
 
-    virtual const char *GetTableName()
+    virtual const char *GetTableName() override
                            {return m_poDefn?m_poDefn->GetName():"";};
 
-    virtual int         TestCapability( const char * pszCap ) ;
-    virtual GIntBig     GetFeatureCount (int bForce);
-    virtual void        ResetReading();
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual int         TestCapability( const char * pszCap ) override ;
+    virtual GIntBig     GetFeatureCount (int bForce) override;
+    virtual void        ResetReading() override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     ///////////////
     // Read access specific stuff
     //
 
-    virtual GIntBig GetNextFeatureId(GIntBig nPrevId);
-    virtual TABFeature *GetFeatureRef(GIntBig nFeatureId);
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual GIntBig GetNextFeatureId(GIntBig nPrevId) override;
+    virtual TABFeature *GetFeatureRef(GIntBig nFeatureId) override;
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual TABFieldType GetNativeFieldType(int nFieldId);
+    virtual TABFieldType GetNativeFieldType(int nFieldId) override;
 
     virtual int GetBounds(double &dXMin, double &dYMin,
                           double &dXMax, double &dYMax,
-                          GBool bForce = TRUE );
+                          GBool bForce = TRUE ) override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
     virtual int GetFeatureCountByType(int &numPoints, int &numLines,
                                       int &numRegions, int &numTexts,
-                                      GBool bForce = TRUE);
+                                      GBool bForce = TRUE) override;
 
-    virtual GBool IsFieldIndexed(int nFieldId);
-    virtual GBool IsFieldUnique(int nFieldId);
+    virtual GBool IsFieldIndexed(int nFieldId) override;
+    virtual GBool IsFieldUnique(int nFieldId) override;
 
     virtual int GetVersion() { return m_nVersion; };
 
@@ -790,30 +699,30 @@ class MIFFile CPL_FINAL : public IMapInfoFile
     // Write access specific stuff
     //
     virtual int SetBounds(double dXMin, double dYMin,
-                          double dXMax, double dYMax);
+                          double dXMax, double dYMax) override;
     virtual int SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
-                            TABFieldType *paeMapInfoNativeFieldTypes = NULL);
+                            TABFieldType *paeMapInfoNativeFieldTypes = NULL) override;
     virtual int AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                int nWidth=0, int nPrecision=0,
                                GBool bIndexed=FALSE, GBool bUnique=FALSE,
-                               int bApproxOK = TRUE);
+                               int bApproxOK = TRUE) override;
     /* TODO */
-    virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef);
+    virtual int SetSpatialRef(OGRSpatialReference *poSpatialRef) override;
 
-    virtual OGRErr CreateFeature(TABFeature *poFeature);
+    virtual OGRErr CreateFeature(TABFeature *poFeature) override;
 
-    virtual int SetFieldIndexed(int nFieldId);
+    virtual int SetFieldIndexed(int nFieldId) override;
 
     ///////////////
     // semi-private.
-    virtual int  GetProjInfo(TABProjInfo * /*poPI*/){return -1;}
+    virtual int  GetProjInfo(TABProjInfo * /*poPI*/) override{return -1;}
     /*  { return m_poMAPFile->GetHeaderBlock()->GetProjInfo( poPI ); }*/
-    virtual int  SetProjInfo(TABProjInfo * /*poPI*/){return -1;}
+    virtual int  SetProjInfo(TABProjInfo * /*poPI*/) override{return -1;}
     /*  { return m_poMAPFile->GetHeaderBlock()->SetProjInfo( poPI ); }*/
-    virtual int  SetMIFCoordSys(const char * pszMIFCoordSys);
+    virtual int  SetMIFCoordSys(const char * pszMIFCoordSys) override;
 
 #ifdef DEBUG
-    virtual void Dump(FILE * /*fpOut*/ = NULL) {};
+    virtual void Dump(FILE * /*fpOut*/ = NULL) override {};
 #endif
 };
 
@@ -1012,7 +921,6 @@ class ITABFeatureSymbol
     void        DumpSymbolDef(FILE *fpOut = NULL);
 };
 
-
 /*=====================================================================
                         Feature Classes
  =====================================================================*/
@@ -1031,7 +939,7 @@ class ITABFeatureSymbol
  * The logic to read/write the object from/to the .DAT and .MAP files is also
  * implemented as part of this class and derived classes.
  *--------------------------------------------------------------------*/
-class TABFeature: public OGRFeature
+class TABFeature : public OGRFeature
 {
   protected:
     TABGeomType m_nMapInfoType;
@@ -1056,7 +964,7 @@ class TABFeature: public OGRFeature
     virtual int UpdateMBR(TABMAPFile *poMapFile = NULL);
 
   public:
-             TABFeature(OGRFeatureDefn *poDefnIn );
+    explicit TABFeature(OGRFeatureDefn *poDefnIn );
     virtual ~TABFeature();
 
     static  TABFeature     *CreateFromMapInfoType(int nMapInfoType,
@@ -1118,10 +1026,8 @@ class TABFeature: public OGRFeature
 
     virtual void DumpMID(FILE *fpOut = NULL);
     virtual void DumpMIF(FILE *fpOut = NULL);
-
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABPoint
  *
@@ -1142,33 +1048,32 @@ class TABPoint: public TABFeature,
                 public ITABFeatureSymbol
 {
   public:
-             TABPoint(OGRFeatureDefn *poDefnIn);
+    explicit TABPoint(OGRFeatureDefn *poDefnIn);
     virtual ~TABPoint();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCPoint; };
-    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL);
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCPoint; };
+    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL) override;
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     double      GetX();
     double      GetY();
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABFontPoint
  *
@@ -1190,24 +1095,24 @@ class TABFontPoint CPL_FINAL : public TABPoint,
     GInt16      m_nFontStyle;           // Bold/shadow/halo/etc.
 
   public:
-             TABFontPoint(OGRFeatureDefn *poDefnIn);
+    explicit TABFontPoint(OGRFeatureDefn *poDefnIn);
     virtual ~TABFontPoint();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCFontPoint; };
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCFontPoint; };
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
     GBool       QueryFontStyle(TABFontStyle eStyleToQuery);
     void        ToggleFontStyle(TABFontStyle eStyleToToggle, GBool bStatus);
@@ -1222,7 +1127,6 @@ class TABFontPoint CPL_FINAL : public TABPoint,
     void        SetSymbolAngle(double dAngle);
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABCustomPoint
  *
@@ -1247,24 +1151,24 @@ class TABCustomPoint CPL_FINAL : public TABPoint,
     GByte       m_nUnknown_;
 
   public:
-             TABCustomPoint(OGRFeatureDefn *poDefnIn);
+    explicit TABCustomPoint(OGRFeatureDefn *poDefnIn);
     virtual ~TABCustomPoint();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCCustomPoint; };
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCCustomPoint; };
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
     const char *GetSymbolNameRef()      { return GetFontNameRef(); };
     void        SetSymbolName(const char *pszName) {SetFontName(pszName);};
@@ -1273,7 +1177,6 @@ class TABCustomPoint CPL_FINAL : public TABPoint,
     void        SetCustomSymbolStyle(GByte nStyle)  {m_nCustomStyle = nStyle;}
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABPolyline
  *
@@ -1295,17 +1198,18 @@ class TABPolyline CPL_FINAL : public TABFeature,
 {
   private:
     GBool       m_bCenterIsSet;
-    double      m_dCenterX, m_dCenterY;
+    double      m_dCenterX;
+    double      m_dCenterY;
     GBool       m_bWriteTwoPointLineAsPolyline;
 
   public:
-             TABPolyline(OGRFeatureDefn *poDefnIn);
+    explicit TABPolyline(OGRFeatureDefn *poDefnIn);
     virtual ~TABPolyline();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCPolyline; };
-    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL);
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCPolyline; };
+    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL) override;
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     /* 2 methods to simplify access to rings in a multiple polyline
      */
@@ -1317,17 +1221,17 @@ class TABPolyline CPL_FINAL : public TABFeature,
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 
     int         GetCenter(double &dX, double &dY);
     void        SetCenter(double dX, double dY);
@@ -1335,7 +1239,6 @@ class TABPolyline CPL_FINAL : public TABFeature,
     // MapInfo-specific attributes... made available through public vars
     // for now.
     GBool       m_bSmooth;
-
 };
 
 /*---------------------------------------------------------------------
@@ -1361,26 +1264,27 @@ class TABRegion CPL_FINAL : public TABFeature,
                  public ITABFeaturePen,
                  public ITABFeatureBrush
 {
-    GBool       m_bSmooth;
   private:
+    GBool       m_bSmooth;
     GBool       m_bCenterIsSet;
-    double      m_dCenterX, m_dCenterY;
+    double      m_dCenterX;
+    double      m_dCenterY;
 
     int     ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
                             TABMAPFile *poMAPFile);
-    int     AppendSecHdrs(OGRPolygon *poPolygon,
+    static int     AppendSecHdrs(OGRPolygon *poPolygon,
                           TABMAPCoordSecHdr * &pasSecHdrs,
                           TABMAPFile *poMAPFile,
                           int &iLastRing);
 
   public:
-             TABRegion(OGRFeatureDefn *poDefnIn);
+    explicit TABRegion(OGRFeatureDefn *poDefnIn);
     virtual ~TABRegion();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCRegion; };
-    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL);
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCRegion; };
+    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL) override;
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     /* 2 methods to make the REGION's geometry look like a single collection
      * of OGRLinearRings
@@ -1391,23 +1295,22 @@ class TABRegion CPL_FINAL : public TABFeature,
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 
     int         GetCenter(double &dX, double &dY);
     void        SetCenter(double dX, double dY);
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABRectangle
  *
@@ -1429,40 +1332,38 @@ class TABRectangle CPL_FINAL : public TABFeature,
                     public ITABFeatureBrush
 {
   private:
-    virtual int UpdateMBR(TABMAPFile *poMapFile = NULL);
+    virtual int UpdateMBR(TABMAPFile *poMapFile = NULL) override;
 
   public:
-             TABRectangle(OGRFeatureDefn *poDefnIn);
+    explicit TABRectangle(OGRFeatureDefn *poDefnIn);
     virtual ~TABRectangle();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCRectangle; };
-    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL);
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCRectangle; };
+    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL) override;
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 
     // MapInfo-specific attributes... made available through public vars
     // for now.
     GBool       m_bRoundCorners;
     double      m_dRoundXRadius;
     double      m_dRoundYRadius;
-
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABEllipse
  *
@@ -1490,30 +1391,30 @@ class TABEllipse CPL_FINAL : public TABFeature,
                   public ITABFeatureBrush
 {
   private:
-    virtual int UpdateMBR(TABMAPFile *poMapFile = NULL);
+    virtual int UpdateMBR(TABMAPFile *poMapFile = NULL) override;
 
   public:
-             TABEllipse(OGRFeatureDefn *poDefnIn);
+    explicit TABEllipse(OGRFeatureDefn *poDefnIn);
     virtual ~TABEllipse();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCEllipse; };
-    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL);
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCEllipse; };
+    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL) override;
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 
     // MapInfo-specific attributes... made available through public vars
     // for now.
@@ -1521,10 +1422,8 @@ class TABEllipse CPL_FINAL : public TABFeature,
     double      m_dCenterY;
     double      m_dXRadius;
     double      m_dYRadius;
-
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABArc
  *
@@ -1552,30 +1451,30 @@ class TABArc CPL_FINAL : public TABFeature,
     double      m_dStartAngle;  // In degrees, counterclockwise,
     double      m_dEndAngle;    // starting at 3 o'clock
 
-    virtual int UpdateMBR(TABMAPFile *poMapFile = NULL);
+    virtual int UpdateMBR(TABMAPFile *poMapFile = NULL) override;
 
   public:
-             TABArc(OGRFeatureDefn *poDefnIn);
+    explicit TABArc(OGRFeatureDefn *poDefnIn);
     virtual ~TABArc();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCArc; };
-    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL);
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCArc; };
+    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL) override;
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 
     double      GetStartAngle() { return m_dStartAngle; };
     double      GetEndAngle()   { return m_dEndAngle; };
@@ -1590,7 +1489,6 @@ class TABArc CPL_FINAL : public TABFeature,
     double      m_dYRadius;
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABText
  *
@@ -1631,30 +1529,30 @@ class TABText CPL_FINAL : public TABFeature,
 
     const char *GetLabelStyleString();
 
-    virtual int UpdateMBR(TABMAPFile *poMapFile = NULL);
+    virtual int UpdateMBR(TABMAPFile *poMapFile = NULL) override;
 
   public:
-             TABText(OGRFeatureDefn *poDefnIn);
+    explicit TABText(OGRFeatureDefn *poDefnIn);
     virtual ~TABText();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCText; };
-    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL);
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCText; };
+    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL) override;
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 
     const char *GetTextString();
     double      GetTextAngle();
@@ -1696,10 +1594,8 @@ class TABText CPL_FINAL : public TABFeature,
     GBool       IsFontUnderline();
     int         GetFontStyleTABValue()           {return m_nFontStyle;};
     void        SetFontStyleTABValue(int nStyle){m_nFontStyle=(GInt16)nStyle;};
-
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABMultiPoint
  *
@@ -1720,16 +1616,17 @@ class TABMultiPoint CPL_FINAL : public TABFeature,
     // We call it center, but it's more like a label point
     // Its value default to be the location of the first point
     GBool       m_bCenterIsSet;
-    double      m_dCenterX, m_dCenterY;
+    double      m_dCenterX;
+    double      m_dCenterY;
 
   public:
-             TABMultiPoint(OGRFeatureDefn *poDefnIn);
+    explicit TABMultiPoint(OGRFeatureDefn *poDefnIn);
     virtual ~TABMultiPoint();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCMultiPoint; };
-    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL);
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCMultiPoint; };
+    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL) override;
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     int         GetXY(int i, double &dX, double &dY);
     int         GetNumPoints();
@@ -1739,17 +1636,17 @@ class TABMultiPoint CPL_FINAL : public TABFeature,
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 };
 
 /*---------------------------------------------------------------------
@@ -1786,13 +1683,13 @@ class TABCollection CPL_FINAL : public TABFeature,
     TABMultiPoint   *m_poMpoint;
 
     void    EmptyCollection();
-    int     ReadLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
+    static int     ReadLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
                             GBool bComprCoord,
                             GInt32 nComprOrgX, GInt32 nComprOrgY,
                             GInt32 &pnMinX, GInt32 &pnMinY,
                             GInt32 &pnMaxX, GInt32 &pnMaxY,
                             GInt32 &pnLabelX, GInt32 &pnLabelY );
-    int     WriteLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
+    static int     WriteLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
                              GBool bComprCoord,
                              GInt32 nMinX, GInt32 nMinY,
                              GInt32 nMaxX, GInt32 nMaxY,
@@ -1802,27 +1699,27 @@ class TABCollection CPL_FINAL : public TABFeature,
                                       GBool bSyncMpoint);
 
   public:
-             TABCollection(OGRFeatureDefn *poDefnIn);
+    explicit TABCollection(OGRFeatureDefn *poDefnIn);
     virtual ~TABCollection();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCCollection; };
-    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL);
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCCollection; };
+    virtual TABGeomType     ValidateMapInfoType(TABMAPFile *poMapFile = NULL) override;
 
-    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL );
+    virtual TABFeature *CloneTABFeature(OGRFeatureDefn *poNewDefn = NULL ) override;
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual const char *GetStyleString();
+    virtual const char *GetStyleString() override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 
     TABRegion           *GetRegionRef()         {return m_poRegion; };
     TABPolyline         *GetPolylineRef()       {return m_poPline; };
@@ -1833,7 +1730,6 @@ class TABCollection CPL_FINAL : public TABFeature,
     int                 SetMultiPointDirectly(TABMultiPoint *poMpoint);
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABDebugFeature
  *
@@ -1850,22 +1746,22 @@ class TABDebugFeature CPL_FINAL : public TABFeature
     int         m_nCoordDataSize;
 
   public:
-             TABDebugFeature(OGRFeatureDefn *poDefnIn);
+    explicit TABDebugFeature(OGRFeatureDefn *poDefnIn);
     virtual ~TABDebugFeature();
 
-    virtual TABFeatureClass GetFeatureClass() { return TABFCDebugFeature; };
+    virtual TABFeatureClass GetFeatureClass() override { return TABFCDebugFeature; };
 
     virtual int ReadGeometryFromMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                         GBool bCoordDataOnly=FALSE,
-                                        TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                        TABMAPCoordBlock **ppoCoordBlock=NULL) override;
     virtual int WriteGeometryToMAPFile(TABMAPFile *poMapFile, TABMAPObjHdr *,
                                        GBool bCoordDataOnly=FALSE,
-                                       TABMAPCoordBlock **ppoCoordBlock=NULL);
+                                       TABMAPCoordBlock **ppoCoordBlock=NULL) override;
 
-    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp);
-    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp);
+    virtual int ReadGeometryFromMIFFile(MIDDATAFile *fp) override;
+    virtual int WriteGeometryToMIFFile(MIDDATAFile *fp) override;
 
-    virtual void DumpMIF(FILE *fpOut = NULL);
+    virtual void DumpMIF(FILE *fpOut = NULL) override;
 };
 
 /* -------------------------------------------------------------------- */
@@ -1879,9 +1775,9 @@ class TABDebugFeature CPL_FINAL : public TABFeature
 char CPL_DLL *MITABSpatialRef2CoordSys( OGRSpatialReference * );
 OGRSpatialReference CPL_DLL * MITABCoordSys2SpatialRef( const char * );
 
-GBool MITABExtractCoordSysBounds( const char * pszCoordSys,
-                                  double &dXMin, double &dYMin,
-                                  double &dXMax, double &dYMax );
+bool MITABExtractCoordSysBounds( const char * pszCoordSys,
+                                 double &dXMin, double &dYMin,
+                                 double &dXMax, double &dYMax );
 int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj);
 
 typedef struct {
@@ -1907,17 +1803,16 @@ typedef struct
     double      dfInvFlattening; /* Inverse flattening */
 } MapInfoSpheroidInfo;
 
-
 /*---------------------------------------------------------------------
  * The following are used for coordsys bounds lookup
  *--------------------------------------------------------------------*/
 
-GBool   MITABLookupCoordSysBounds(TABProjInfo *psCS,
+bool    MITABLookupCoordSysBounds(TABProjInfo *psCS,
                                   double &dXMin, double &dYMin,
                                   double &dXMax, double &dYMax,
-                                  int bOnlyUserTable = FALSE);
+                                  bool bOnlyUserTable = false);
 int     MITABLoadCoordSysTable(const char *pszFname);
 void    MITABFreeCoordSysTable();
-GBool   MITABCoordSysTableLoaded();
+bool    MITABCoordSysTableLoaded();  // TODO(schwehr): Unused?
 
 #endif /* MITAB_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/mitab/mitab_bounds.cpp b/ogr/ogrsf_frmts/mitab/mitab_bounds.cpp
index 75817ac..f2a4f62 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_bounds.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_bounds.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_bounds.cpp,v 1.8 2008-01-29 20:53:10 dmorissette Exp $
  *
  * Name:     mitab_bounds.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -27,50 +26,37 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_bounds.cpp,v $
- * Revision 1.8  2008-01-29 20:53:10  dmorissette
- * Added bounds for PSAD56 (Patch from AJD sent for bug #1754)
- *
- * Revision 1.7  2005/09/29 18:31:28  dmorissette
- * New bounds entry for Finnish KKJ and Swedish projections (AJD, bug 1155)
- *
- * Revision 1.6  2005/03/31 22:00:38  dmorissette
- * Added bounds entry to match datum 1011 based on MapInfo's "Svenska
- * rikssystemet, 2,5 gon väst (RT 90 7 parametrar)" (bug 997)
- *
- * Revision 1.5  2005/03/22 23:24:54  dmorissette
- * Added support for datum id in .MAP header (bug 910)
- *
- * Revision 1.4  2004/06/30 20:29:03  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.3  2001/02/14 21:17:33  daniel
- * Check only if first char is "#" for comments in MITABLoadCoordSysTable()
- *
- * Revision 1.2  2001/01/23 22:06:50  daniel
- * Added MITABCoordSysTableLoaded()
- *
- * Revision 1.1  2001/01/23 21:23:41  daniel
- * Added projection bounds lookup table, called from TABFile::SetProjInfo()
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+#include "mitab_priv.h"
+
+#include <cmath>
+#include <cstring>
+#if HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+
+CPL_CVSID("$Id: mitab_bounds.cpp 37427 2017-02-19 23:16:04Z goatbar $");
 
 typedef struct
 {
-    TABProjInfo sProj;          /* Projection/datum definition */
-    double      dXMin;          /* Default bounds for that coordsys */
-    double      dYMin;
-    double      dXMax;
-    double      dYMax;
+    TABProjInfo sProj; // Projection/datum definition.
+    double dXMin;      // Default bounds for that coordsys.
+    double dYMin;
+    double dXMax;
+    double dYMax;
 } MapInfoBoundsInfo;
 
 typedef struct
 {
-    TABProjInfo       sProjIn;
+    TABProjInfo sProjIn;
     MapInfoBoundsInfo sBoundsInfo;
 } MapInfoRemapProjInfo;
 
@@ -1052,10 +1038,12 @@ static const MapInfoBoundsInfo gasBoundsList[] = {
 {{0xff, 0, 0, {0,0,0,0,0,0}, 0,0,0,0, {0,0,0,0,0}, 0,0,0,0,0,0,0,0},  0, 0, 0, 0}
 };
 
+static bool TAB_EQUAL( double a, double b, double eps )
+{
+    return fabs(a - b) < eps;
+}
 
-#define TAB_EQUAL(a, b, eps) (fabs((a)-(b)) < eps)
-
-static char szPreviousMitabBoundsFile[2048] = { 0 };
+static char szPreviousMitabBoundsFile[2048] = {};
 static VSIStatBufL sStatBoundsFile;
 
 /**********************************************************************
@@ -1066,20 +1054,18 @@ static VSIStatBufL sStatBoundsFile;
  * This can modify that passed TABProjInfo struct if a match is found
  * in an external bound file with proj remapping.
  *
- * Returns TRUE if valid bounds were found, FALSE otherwise.
+ * Returns true if valid bounds were found, false otherwise.
  **********************************************************************/
-GBool MITABLookupCoordSysBounds(TABProjInfo *psCS,
+bool MITABLookupCoordSysBounds( TABProjInfo *psCS,
                                 double &dXMin, double &dYMin,
                                 double &dXMax, double &dYMax,
-                                int bOnlyUserTable)
+                                bool bOnlyUserTable )
 {
-    GBool bFound = FALSE;
-    const MapInfoBoundsInfo *psList;
+    bool bFound = false;
 
-    /*-----------------------------------------------------------------
-    * Try to load the user defined table if not loaded yet .
-    *----------------------------------------------------------------*/
-    const char * pszMitabBoundsFile = CPLGetConfigOption("MITAB_BOUNDS_FILE", NULL);
+    // Try to load the user defined table if not loaded yet.
+    const char *pszMitabBoundsFile =
+        CPLGetConfigOption("MITAB_BOUNDS_FILE", NULL);
     if (pszMitabBoundsFile != NULL && pszMitabBoundsFile[0] != '\0' )
     {
         if( strcmp(pszMitabBoundsFile, szPreviousMitabBoundsFile) != 0)
@@ -1094,7 +1080,7 @@ GBool MITABLookupCoordSysBounds(TABProjInfo *psCS,
         }
         else
         {
-            /* Reload file if its modification file has changed */
+            // Reload file if its modification file has changed.
             VSIStatBufL sStat;
             if( VSIStatL(pszMitabBoundsFile, &sStat) == 0 )
             {
@@ -1112,22 +1098,21 @@ GBool MITABLookupCoordSysBounds(TABProjInfo *psCS,
         strcpy(szPreviousMitabBoundsFile, "");
     }
 
-    for(int iLoop=0; !bFound && iLoop < 2; iLoop++)
+    for( int iLoop = 0; !bFound && iLoop < 2; iLoop++ )
     {
-        /* MapInfo uses a hack to differentiate some SRS that have the same */
-        /* definition, but different bounds, e.g. Lambet 93 France with French */
-        /* Bounds or with European bounds. It alters slightly one of the projection */
-        /* parameters, e.g. std_parallel_1 = 49.00000000001 or 49.00000000002 */
-        double eps = (iLoop == 0) ? 1e-12 : 1e-6;
+        // MapInfo uses a hack to differentiate some SRS that have the same
+        // definition, but different bounds, e.g. Lambet 93 France with French
+        // Bounds or with European bounds. It alters slightly one of the
+        // projection parameters, e.g. std_parallel_1 = 49.00000000001 or
+        // 49.00000000002
+        const double eps = iLoop == 0 ? 1.0e-12 : 1.0e-6;
 
-        /*-----------------------------------------------------------------
-        * Lookup table...
-        * Lookup external file if one was loaded, then lookup internal table.
-        *
-        * Note that entries in lookup table with 0xff for projId, UnitsId,
-        * means ignore that param, and 0xff in ellipsoidId means ignore the
-        * whole datum.
-        *----------------------------------------------------------------*/
+        // Lookup table.
+        // Lookup external file if one was loaded, then lookup internal table.
+        //
+        // Note that entries in lookup table with 0xff for projId, UnitsId,
+        // means ignore that param, and 0xff in ellipsoidId means ignore the
+        // whole datum.
         for( int i = 0 ; !bFound && i < nExtBoundsListCount; i++)
         {
             TABProjInfo *p = &(gpasExtBoundsList[i].sProjIn);
@@ -1136,22 +1121,23 @@ GBool MITABLookupCoordSysBounds(TABProjInfo *psCS,
                 (p->nUnitsId == 0xff || p->nUnitsId == psCS->nUnitsId) &&
                 (p->nEllipsoidId == 0xff ||
                 (p->nEllipsoidId == psCS->nEllipsoidId &&
-                ( (p->nDatumId > 0 && p->nDatumId == psCS->nDatumId) ||
-                    ((p->nDatumId <= 0 || psCS->nDatumId <= 0) &&
-                    TAB_EQUAL(p->dDatumShiftX, psCS->dDatumShiftX, eps) &&
-                    TAB_EQUAL(p->dDatumShiftY, psCS->dDatumShiftY, eps) &&
-                    TAB_EQUAL(p->dDatumShiftZ, psCS->dDatumShiftZ, eps) &&
-                    TAB_EQUAL(p->adDatumParams[0], psCS->adDatumParams[0], eps) &&
-                    TAB_EQUAL(p->adDatumParams[1], psCS->adDatumParams[1], eps) &&
-                    TAB_EQUAL(p->adDatumParams[2], psCS->adDatumParams[2], eps) &&
-                    TAB_EQUAL(p->adDatumParams[3], psCS->adDatumParams[3], eps) &&
-                    TAB_EQUAL(p->adDatumParams[4], psCS->adDatumParams[4], eps) )))) &&
+                ((p->nDatumId > 0 && p->nDatumId == psCS->nDatumId) ||
+                 ((p->nDatumId <= 0 || psCS->nDatumId <= 0) &&
+                  TAB_EQUAL(p->dDatumShiftX, psCS->dDatumShiftX, eps) &&
+                  TAB_EQUAL(p->dDatumShiftY, psCS->dDatumShiftY, eps) &&
+                  TAB_EQUAL(p->dDatumShiftZ, psCS->dDatumShiftZ, eps) &&
+                  TAB_EQUAL(p->adDatumParams[0], psCS->adDatumParams[0], eps) &&
+                  TAB_EQUAL(p->adDatumParams[1], psCS->adDatumParams[1], eps) &&
+                  TAB_EQUAL(p->adDatumParams[2], psCS->adDatumParams[2], eps) &&
+                  TAB_EQUAL(p->adDatumParams[3], psCS->adDatumParams[3], eps) &&
+                  TAB_EQUAL(p->adDatumParams[4],
+                            psCS->adDatumParams[4], eps))))) &&
                 (TAB_EQUAL(p->adProjParams[0], psCS->adProjParams[0], eps) &&
-                TAB_EQUAL(p->adProjParams[1], psCS->adProjParams[1], eps) &&
-                TAB_EQUAL(p->adProjParams[2], psCS->adProjParams[2], eps) &&
-                TAB_EQUAL(p->adProjParams[3], psCS->adProjParams[3], eps) &&
-                TAB_EQUAL(p->adProjParams[4], psCS->adProjParams[4], eps) &&
-                TAB_EQUAL(p->adProjParams[5], psCS->adProjParams[5], eps) )  )
+                 TAB_EQUAL(p->adProjParams[1], psCS->adProjParams[1], eps) &&
+                 TAB_EQUAL(p->adProjParams[2], psCS->adProjParams[2], eps) &&
+                 TAB_EQUAL(p->adProjParams[3], psCS->adProjParams[3], eps) &&
+                 TAB_EQUAL(p->adProjParams[4], psCS->adProjParams[4], eps) &&
+                 TAB_EQUAL(p->adProjParams[5], psCS->adProjParams[5], eps)) )
             {
                 memcpy(psCS, &gpasExtBoundsList[i].sBoundsInfo.sProj,
                        sizeof(TABProjInfo));
@@ -1159,12 +1145,13 @@ GBool MITABLookupCoordSysBounds(TABProjInfo *psCS,
                 dYMin = gpasExtBoundsList[i].sBoundsInfo.dYMin;
                 dXMax = gpasExtBoundsList[i].sBoundsInfo.dXMax;
                 dYMax = gpasExtBoundsList[i].sBoundsInfo.dYMax;
-                bFound = TRUE;
+                bFound = true;
             }
         }
 
-        psList = gasBoundsList;
-        for( ; !bOnlyUserTable && !bFound && psList->sProj.nProjId!=0xff; psList++)
+        const MapInfoBoundsInfo *psList = gasBoundsList;
+        for( ; !bOnlyUserTable && !bFound && psList->sProj.nProjId!=0xff;
+             psList++ )
         {
             const TABProjInfo *p = &(psList->sProj);
 
@@ -1172,28 +1159,29 @@ GBool MITABLookupCoordSysBounds(TABProjInfo *psCS,
                 (p->nUnitsId == 0xff || p->nUnitsId == psCS->nUnitsId) &&
                 (p->nEllipsoidId == 0xff ||
                 (p->nEllipsoidId == psCS->nEllipsoidId &&
-                ( (p->nDatumId > 0 && p->nDatumId == psCS->nDatumId) ||
-                    ((p->nDatumId <= 0 || psCS->nDatumId <= 0) &&
-                    TAB_EQUAL(p->dDatumShiftX, psCS->dDatumShiftX, eps) &&
-                    TAB_EQUAL(p->dDatumShiftY, psCS->dDatumShiftY, eps) &&
-                    TAB_EQUAL(p->dDatumShiftZ, psCS->dDatumShiftZ, eps) &&
-                    TAB_EQUAL(p->adDatumParams[0], psCS->adDatumParams[0], eps) &&
-                    TAB_EQUAL(p->adDatumParams[1], psCS->adDatumParams[1], eps) &&
-                    TAB_EQUAL(p->adDatumParams[2], psCS->adDatumParams[2], eps) &&
-                    TAB_EQUAL(p->adDatumParams[3], psCS->adDatumParams[3], eps) &&
-                    TAB_EQUAL(p->adDatumParams[4], psCS->adDatumParams[4], eps) )))) &&
+                ((p->nDatumId > 0 && p->nDatumId == psCS->nDatumId) ||
+                 ((p->nDatumId <= 0 || psCS->nDatumId <= 0) &&
+                  TAB_EQUAL(p->dDatumShiftX, psCS->dDatumShiftX, eps) &&
+                  TAB_EQUAL(p->dDatumShiftY, psCS->dDatumShiftY, eps) &&
+                  TAB_EQUAL(p->dDatumShiftZ, psCS->dDatumShiftZ, eps) &&
+                  TAB_EQUAL(p->adDatumParams[0], psCS->adDatumParams[0], eps) &&
+                  TAB_EQUAL(p->adDatumParams[1], psCS->adDatumParams[1], eps) &&
+                  TAB_EQUAL(p->adDatumParams[2], psCS->adDatumParams[2], eps) &&
+                  TAB_EQUAL(p->adDatumParams[3], psCS->adDatumParams[3], eps) &&
+                  TAB_EQUAL(p->adDatumParams[4],
+                            psCS->adDatumParams[4], eps))))) &&
                 (TAB_EQUAL(p->adProjParams[0], psCS->adProjParams[0], eps) &&
-                TAB_EQUAL(p->adProjParams[1], psCS->adProjParams[1], eps) &&
-                TAB_EQUAL(p->adProjParams[2], psCS->adProjParams[2], eps) &&
-                TAB_EQUAL(p->adProjParams[3], psCS->adProjParams[3], eps) &&
-                TAB_EQUAL(p->adProjParams[4], psCS->adProjParams[4], eps) &&
-                TAB_EQUAL(p->adProjParams[5], psCS->adProjParams[5], eps) )  )
+                 TAB_EQUAL(p->adProjParams[1], psCS->adProjParams[1], eps) &&
+                 TAB_EQUAL(p->adProjParams[2], psCS->adProjParams[2], eps) &&
+                 TAB_EQUAL(p->adProjParams[3], psCS->adProjParams[3], eps) &&
+                 TAB_EQUAL(p->adProjParams[4], psCS->adProjParams[4], eps) &&
+                 TAB_EQUAL(p->adProjParams[5], psCS->adProjParams[5], eps)) )
             {
                 dXMin = psList->dXMin;
                 dYMin = psList->dYMin;
                 dXMax = psList->dXMax;
                 dYMax = psList->dYMax;
-                bFound = TRUE;
+                bFound = true;
             }
         }
     }
@@ -1201,7 +1189,6 @@ GBool MITABLookupCoordSysBounds(TABProjInfo *psCS,
     return bFound;
 }
 
-
 /**********************************************************************
  *                     MITABLoadCoordSysTable()
  *
@@ -1225,50 +1212,54 @@ GBool MITABLookupCoordSysBounds(TABProjInfo *psCS,
  **********************************************************************/
 int MITABLoadCoordSysTable(const char *pszFname)
 {
-    VSILFILE *fp;
-    int nStatus = 0, iLine = 0;
-
     MITABFreeCoordSysTable();
 
-    if ((fp = VSIFOpenL(pszFname, "rt")) != NULL)
+    int nStatus = 0;
+    int iLine = 0;
+
+    VSILFILE *fp = VSIFOpenL(pszFname, "rt");
+    if( fp != NULL )
     {
-        const char *pszLine;
-        int         iEntry=0, numEntries=100;
+        int iEntry = 0;
+        int numEntries = 100;
 
-        gpasExtBoundsList = (MapInfoRemapProjInfo *)CPLMalloc(numEntries*
-                                                  sizeof(MapInfoRemapProjInfo));
+        gpasExtBoundsList = static_cast<MapInfoRemapProjInfo *>(
+            CPLMalloc(numEntries * sizeof(MapInfoRemapProjInfo)));
 
+        const char *pszLine = NULL;
         while( (pszLine = CPLReadLineL(fp)) != NULL)
         {
-            double dXMin, dYMin, dXMax, dYMax;
-            int bHasProjIn = FALSE;
-            TABProjInfo sProjIn;
-            TABProjInfo sProj;
-
             iLine++;
 
             if (strlen(pszLine) < 10 || STARTS_WITH_CI(pszLine, "#"))
-                continue;  // Skip empty lines/comments
+                continue;  // Skip empty lines/comments.
+
+            bool bHasProjIn = false;
+            TABProjInfo sProjIn;
+            TABProjInfo sProj;
 
             if( STARTS_WITH_CI(pszLine, "Source") )
             {
-                const char* pszEqual = strchr(pszLine, '=');
+                const char *pszEqual = strchr(pszLine, '=');
                 if( !pszEqual )
                 {
-                    CPLError(CE_Warning, CPLE_IllegalArg, "Invalid format at line %d", iLine);
+                    CPLError(CE_Warning, CPLE_IllegalArg,
+                             "Invalid format at line %d", iLine);
                     break;
                 }
                 pszLine = pszEqual + 1;
-                if ((nStatus = MITABCoordSys2TABProjInfo(pszLine, &sProjIn)) != 0)
+                if ((nStatus = MITABCoordSys2TABProjInfo(pszLine,
+                                                         &sProjIn)) != 0)
                 {
                     break;  // Abort and return
                 }
                 if( strstr(pszLine, "Bounds") != NULL )
                 {
-                    CPLError(CE_Warning, CPLE_IllegalArg, "Unexpected Bounds parameter at line %d",
+                    CPLError(CE_Warning, CPLE_IllegalArg,
+                             "Unexpected Bounds parameter at line %d",
                              iLine);
                 }
-                bHasProjIn = TRUE;
+                bHasProjIn = true;
 
                 iLine++;
                 pszLine = CPLReadLineL(fp);
@@ -1276,8 +1267,9 @@ int MITABLoadCoordSysTable(const char *pszFname)
                     !STARTS_WITH_CI(pszLine, "Destination") ||
                     (pszEqual = strchr(pszLine, '=')) == NULL )
                 {
-                    CPLError(CE_Warning, CPLE_IllegalArg, "Invalid format at line %d", iLine);
-                        break;
+                    CPLError(CE_Warning, CPLE_IllegalArg,
+                             "Invalid format at line %d", iLine);
+                    break;
                 }
                 pszLine = pszEqual + 1;
             }
@@ -1287,7 +1279,13 @@ int MITABLoadCoordSysTable(const char *pszFname)
                 break;  // Abort and return
             }
 
-            if (!MITABExtractCoordSysBounds(pszLine, dXMin,dYMin,dXMax,dYMax))
+            double dXMin = 0.0;
+            double dYMin = 0.0;
+            double dXMax = 0.0;
+            double dYMax = 0.0;
+            if( !MITABExtractCoordSysBounds(pszLine,
+                                            dXMin, dYMin,
+                                            dXMax, dYMax) )
             {
                 CPLError(CE_Warning, CPLE_IllegalArg,
                          "Missing Bounds parameters in line %d of %s",
@@ -1297,19 +1295,19 @@ int MITABLoadCoordSysTable(const char *pszFname)
 
             if (iEntry >= numEntries-1)
             {
-                numEntries+= 100;
-                gpasExtBoundsList =
-                    (MapInfoRemapProjInfo *)CPLRealloc(gpasExtBoundsList,
-                                        numEntries* sizeof(MapInfoRemapProjInfo));
+                numEntries += 100;
+                gpasExtBoundsList = static_cast<MapInfoRemapProjInfo *>(
+                    CPLRealloc(gpasExtBoundsList,
+                               numEntries * sizeof(MapInfoRemapProjInfo)));
             }
 
-            gpasExtBoundsList[iEntry].sProjIn = (bHasProjIn) ? sProjIn : sProj;
+            gpasExtBoundsList[iEntry].sProjIn = bHasProjIn ? sProjIn : sProj;
             gpasExtBoundsList[iEntry].sBoundsInfo.sProj = sProj;
             gpasExtBoundsList[iEntry].sBoundsInfo.dXMin = dXMin;
             gpasExtBoundsList[iEntry].sBoundsInfo.dYMin = dYMin;
             gpasExtBoundsList[iEntry].sBoundsInfo.dXMax = dXMax;
             gpasExtBoundsList[iEntry].sBoundsInfo.dYMax = dYMax;
-            iEntry ++;
+            iEntry++;
         }
         nExtBoundsListCount = iEntry;
 
@@ -1323,7 +1321,6 @@ int MITABLoadCoordSysTable(const char *pszFname)
     return nStatus;
 }
 
-
 /**********************************************************************
  *                     MITABFreeCoordSysTable()
  *
@@ -1341,7 +1338,4 @@ void MITABFreeCoordSysTable()
  *
  * Returns TRUE if a coordsys table was loaded, FALSE otherwise.
  **********************************************************************/
-GBool MITABCoordSysTableLoaded()
-{
-    return (nExtBoundsListCount >= 0);
-}
+bool MITABCoordSysTableLoaded() { return nExtBoundsListCount >= 0; }
diff --git a/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp b/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
index fbbb94c..53edc12 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_coordsys.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_coordsys.cpp,v 1.42 2011-06-11 00:35:00 fwarmerdam Exp $
  *
  * Name:     mitab_coordsys.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -28,96 +27,25 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_coordsys.cpp,v $
- * Revision 1.42  2011-06-11 00:35:00  fwarmerdam
- * add support for reading google mercator (#4115)
- *
- * Revision 1.41  2010-10-07 18:46:26  aboudreault
- * Fixed bad use of CPLAtof when locale setting doesn't use . for float (GDAL bug #3775)
- *
- * Revision 1.40  2010-09-07 16:48:08  aboudreault
- * Removed incomplete patch for affine params support in mitab. (bug 1155)
- *
- * Revision 1.39  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.38  2010-07-05 18:32:48  aboudreault
- * Fixed memory leaks in mitab_capi.cpp and mitab_coordsys.cpp
- *
- * Revision 1.37  2010-07-05 17:20:14  aboudreault
- * Added Krovak projection support (bug 2230)
- *
- * Revision 1.36  2007-11-21 21:15:45  dmorissette
- * Fix asDatumInfoList[] and asSpheroidInfoList[] defns/refs (bug 1826)
- *
- * Revision 1.35  2007/06/21 13:23:43  fwarmerdam
- * Fixed support for predefined datums with non-greenwich prime meridians
- *
- * Revision 1.34  2006/03/10 19:50:45  fwarmerdam
- * Coordsys false easting and northing are in the units of the coordsys, not
- * necessarily meters.  Adjusted mitab_coordsys.cpp to reflect this.
- * http://bugzilla.remotesensing.org/show_bug.cgi?id=1113
- *
- * Revision 1.33  2005/09/29 20:13:57  dmorissette
- * MITABCoordSys2SpatialRef() patches from Anthony D (bug 1155):
- * Improved support for modified TM projections 21-24.
- * Added support for affine parameters (inside #ifdef MITAB_AFFINE_PARAMS since
- * affine params cannot be stored directly in OGRSpatialReference)
- *
- * Revision 1.32  2005/08/07 21:00:38  fwarmerdam
- * Initialize adfDatumParm[] to avoid warnings with gcc 4.
- *
- * Revision 1.31  2005/05/12 22:07:52  dmorissette
- * Improved handling of Danish modified TM proj#21-24 (hss, bugs 976,1010)
- *
- * Revision 1.30  2005/03/22 23:24:54  dmorissette
- * Added support for datum id in .MAP header (bug 910)
- *
- * Revision 1.29  2004/06/03 19:36:53  fwarmerdam
- * fixed memory leak processing non-earth coordsys
- *
- * Revision 1.28  2003/03/21 14:20:42  warmerda
- * fixed up regional mercator handling, was screwing up transverse mercator
- *
- * Revision 1.27  2003/01/09 17:33:26  warmerda
- * fixed ellipsoid extraction for datum 999/9999
- *
- * Revision 1.26  2002/12/12 20:12:18  warmerda
- * fixed signs of rotational parameters for TOWGS84 in WKT
- *
- * Revision 1.25  2002/10/15 14:33:30  warmerda
- * Added untested support in mitab_spatialref.cpp, and mitab_coordsys.cpp for
- * projections Regional Mercator (26), Polyconic (27), Azimuthal Equidistant -
- * All origin latitudes (28), and Lambert Azimuthal Equal Area - any aspect (29).
- *
- * Revision 1.24  2002/09/23 13:16:04  warmerda
- * fixed leak in MITABExtractCoordSysBounds()
- *
- * Revision 1.23  2002/04/01 19:49:24  warmerda
- * added support for cassini/soldner - proj 30
- *
- * Revision 1.22  2002/03/01 19:00:15  warmerda
- * False Easting/Northing should be in the linear units of measure in MapInfo,
- * but in OGRSpatialReference/WKT they are always in meters.  Convert accordingly.
- *
- * Revision 1.21  2001/04/04 21:43:19  warmerda
- * added code to set WGS84 values
- *
- * Revision 1.20  2001/01/23 21:23:42  daniel
- * Added projection bounds lookup table, called from TABFile::SetProjInfo()
- *
- * Revision 1.19  2001/01/22 16:00:53  warmerda
- * reworked swiss projection support
- *
- * Revision 1.18  2001/01/19 21:56:18  warmerda
- * added untested support for Swiss Oblique Mercator
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
 #include "mitab_utils.h"
 
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "mitab_priv.h"
+#include "ogr_spatialref.h"
+
+CPL_CVSID("$Id: mitab_coordsys.cpp 37428 2017-02-19 23:32:58Z goatbar $");
+
 extern const MapInfoDatumInfo asDatumInfoList[];
 extern const MapInfoSpheroidInfo asSpheroidInfoList[];
 
@@ -134,20 +62,18 @@ OGRSpatialReference *MITABCoordSys2SpatialRef( const char * pszCoordSys )
     TABProjInfo sTABProj;
     if(MITABCoordSys2TABProjInfo(pszCoordSys, &sTABProj) < 0 )
         return NULL;
-    OGRSpatialReference* poSR = TABFile::GetSpatialRefFromTABProj(sTABProj);
+    OGRSpatialReference *poSR = TABFile::GetSpatialRefFromTABProj(sTABProj);
 
-/* -------------------------------------------------------------------- */
-/*      Report on translation.                                          */
-/* -------------------------------------------------------------------- */
-    char        *pszWKT;
+    // Report on translation.
+    char *pszWKT = NULL;
 
-    poSR->exportToWkt( &pszWKT );
+    poSR->exportToWkt(&pszWKT);
     if( pszWKT != NULL )
     {
-        CPLDebug( "MITAB",
-                  "This CoordSys value:\n%s\nwas translated to:\n%s\n",
-                  pszCoordSys, pszWKT );
-        CPLFree( pszWKT );
+        CPLDebug("MITAB",
+                 "This CoordSys value:\n%s\nwas translated to:\n%s",
+                 pszCoordSys, pszWKT);
+        CPLFree(pszWKT);
     }
 
     return poSR;
@@ -169,101 +95,87 @@ char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
     if( poSR == NULL )
         return NULL;
 
-    TABProjInfo     sTABProj;
-    int             nParmCount;
+    TABProjInfo sTABProj;
+    int nParmCount = 0;
     TABFile::GetTABProjFromSpatialRef(poSR, sTABProj, nParmCount);
 
-/* -------------------------------------------------------------------- */
-/*      Do coordsys lookup                                              */
-/* -------------------------------------------------------------------- */
-    double dXMin = 0.0, dYMin = 0.0, dXMax = 0.0, dYMax = 0.0;
-    int bHasBounds = FALSE;
-    if (sTABProj.nProjId > 1 &&
-        MITABLookupCoordSysBounds(&sTABProj, dXMin, dYMin, dXMax, dYMax, TRUE) == TRUE)
+    // Do coordsys lookup.
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
+    bool bHasBounds = false;
+    if( sTABProj.nProjId > 1 &&
+        MITABLookupCoordSysBounds(&sTABProj,
+                                  dXMin, dYMin,
+                                  dXMax, dYMax, true) )
     {
-        bHasBounds = TRUE;
+        bHasBounds = true;
     }
 
-/*-----------------------------------------------------------------
- * Translate the units
- *----------------------------------------------------------------*/
-    const char  *pszMIFUnits = TABUnitIdToString(sTABProj.nUnitsId);
+    // Translate the units.
+    const char *pszMIFUnits = TABUnitIdToString(sTABProj.nUnitsId);
 
-/* -------------------------------------------------------------------- */
-/*      Build coordinate system definition.                             */
-/* -------------------------------------------------------------------- */
+    // Build coordinate system definition.
     CPLString osCoordSys;
 
     if( sTABProj.nProjId != 0 )
     {
-        osCoordSys.Printf(
-                 "Earth Projection %d",
-                 sTABProj.nProjId );
-
+        osCoordSys.Printf("Earth Projection %d", sTABProj.nProjId);
     }
     else
-        osCoordSys.Printf(
-                 "NonEarth Units" );
+    {
+        osCoordSys.Printf("NonEarth Units");
+    }
 
-/* -------------------------------------------------------------------- */
-/*      Append Datum                                                    */
-/* -------------------------------------------------------------------- */
+    // Append Datum.
     if( sTABProj.nProjId != 0 )
     {
-        osCoordSys += CPLSPrintf(
-                 ", %d",
-                 sTABProj.nDatumId );
+        osCoordSys += CPLSPrintf(", %d", sTABProj.nDatumId);
 
         if( sTABProj.nDatumId == 999 || sTABProj.nDatumId == 9999 )
         {
-            osCoordSys += CPLSPrintf(
-                     ", %d, %.15g, %.15g, %.15g",
-                     sTABProj.nEllipsoidId,
-                     sTABProj.dDatumShiftX, sTABProj.dDatumShiftY, sTABProj.dDatumShiftZ );
+            osCoordSys +=
+                CPLSPrintf(", %d, %.15g, %.15g, %.15g", sTABProj.nEllipsoidId,
+                           sTABProj.dDatumShiftX, sTABProj.dDatumShiftY,
+                           sTABProj.dDatumShiftZ);
         }
 
         if( sTABProj.nDatumId == 9999 )
         {
-            osCoordSys += CPLSPrintf(
-                     ", %.15g, %.15g, %.15g, %.15g, %.15g",
-                     sTABProj.adDatumParams[0], sTABProj.adDatumParams[1], sTABProj.adDatumParams[2],
-                     sTABProj.adDatumParams[3], sTABProj.adDatumParams[4] );
+            osCoordSys +=
+                CPLSPrintf(", %.15g, %.15g, %.15g, %.15g, %.15g",
+                           sTABProj.adDatumParams[0], sTABProj.adDatumParams[1],
+                           sTABProj.adDatumParams[2], sTABProj.adDatumParams[3],
+                           sTABProj.adDatumParams[4]);
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Append units.                                                   */
-/* -------------------------------------------------------------------- */
+    // Append units.
     if( sTABProj.nProjId != 1 && pszMIFUnits != NULL )
     {
         if( sTABProj.nProjId != 0 )
-            osCoordSys += "," ;
+            osCoordSys += ",";
 
-        osCoordSys += CPLSPrintf(
-                 " \"%s\"",
-                 pszMIFUnits );
+        osCoordSys += CPLSPrintf(" \"%s\"", pszMIFUnits);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Append Projection Parms.                                        */
-/* -------------------------------------------------------------------- */
+    // Append Projection Parms.
     for( int iParm = 0; iParm < nParmCount; iParm++ )
-        osCoordSys += CPLSPrintf(
-                 ", %.15g",
-                 sTABProj.adProjParams[iParm] );
-
-/* -------------------------------------------------------------------- */
-/*      Append user bounds                                              */
-/* -------------------------------------------------------------------- */
-    if (bHasBounds)
+        osCoordSys += CPLSPrintf(", %.15g", sTABProj.adProjParams[iParm]);
+
+    // Append user bounds.
+    if( bHasBounds )
     {
-        if( fabs(dXMin - (int)floor(dXMin+0.5)) < 1e-8 &&
-            fabs(dYMin - (int)floor(dYMin+0.5)) < 1e-8 &&
-            fabs(dXMax - (int)floor(dXMax+0.5)) < 1e-8 &&
-            fabs(dYMax - (int)floor(dYMax+0.5)) < 1e-8 )
+        if( fabs(dXMin - floor(dXMin + 0.5)) < 1e-8 &&
+            fabs(dYMin - floor(dYMin + 0.5)) < 1e-8 &&
+            fabs(dXMax - floor(dXMax + 0.5)) < 1e-8 &&
+            fabs(dYMax - floor(dYMax + 0.5)) < 1e-8 )
         {
-            osCoordSys += CPLSPrintf(" Bounds (%d, %d) (%d, %d)",
-                                     (int)dXMin, (int)dYMin, (int)dXMax, (int)dYMax);
+            osCoordSys +=
+                CPLSPrintf(" Bounds (%d, %d) (%d, %d)",
+                           static_cast<int>(dXMin), static_cast<int>(dYMin),
+                           static_cast<int>(dXMax), static_cast<int>(dYMax));
         }
         else
         {
@@ -272,44 +184,40 @@ char *MITABSpatialRef2CoordSys( OGRSpatialReference * poSR )
         }
     }
 
-/* -------------------------------------------------------------------- */
-/*      Report on translation                                           */
-/* -------------------------------------------------------------------- */
-    char        *pszWKT = NULL;
+    // Report on translation.
+    char *pszWKT = NULL;
 
-    poSR->exportToWkt( &pszWKT );
+    poSR->exportToWkt(&pszWKT);
     if( pszWKT != NULL )
     {
-        CPLDebug( "MITAB",
-                  "This WKT Projection:\n%s\n\ntranslates to:\n%s\n",
-                  pszWKT, osCoordSys.c_str() );
-        CPLFree( pszWKT );
+        CPLDebug("MITAB",
+                 "This WKT Projection:\n%s\n\ntranslates to:\n%s",
+                 pszWKT, osCoordSys.c_str());
+        CPLFree(pszWKT);
     }
 
-    return( CPLStrdup( osCoordSys.c_str() ) );
+    return CPLStrdup(osCoordSys.c_str());
 }
 
-
 /************************************************************************/
 /*                      MITABExtractCoordSysBounds                      */
 /*                                                                      */
-/* Return TRUE if MIF coordsys string contains a BOUNDS parameter and   */
+/* Return true if MIF coordsys string contains a BOUNDS parameter and   */
 /* Set x/y min/max values.                                              */
 /************************************************************************/
 
-GBool MITABExtractCoordSysBounds( const char * pszCoordSys,
-                                  double &dXMin, double &dYMin,
-                                  double &dXMax, double &dYMax )
+bool MITABExtractCoordSysBounds( const char * pszCoordSys,
+                                 double &dXMin, double &dYMin,
+                                 double &dXMax, double &dYMax )
 
 {
-    char        **papszFields;
-
     if( pszCoordSys == NULL )
-        return FALSE;
+        return false;
 
-    papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,()", TRUE, FALSE );
+    char **papszFields =
+        CSLTokenizeStringComplex(pszCoordSys, " ,()", TRUE, FALSE);
 
-    int iBounds = CSLFindString( papszFields, "Bounds" );
+    int iBounds = CSLFindString(papszFields, "Bounds");
 
     if (iBounds >= 0 && iBounds + 4 < CSLCount(papszFields))
     {
@@ -317,15 +225,14 @@ GBool MITABExtractCoordSysBounds( const char * pszCoordSys,
         dYMin = CPLAtof(papszFields[++iBounds]);
         dXMax = CPLAtof(papszFields[++iBounds]);
         dYMax = CPLAtof(papszFields[++iBounds]);
-        CSLDestroy( papszFields );
-        return TRUE;
+        CSLDestroy(papszFields);
+        return true;
     }
 
-    CSLDestroy( papszFields );
-    return FALSE;
+    CSLDestroy(papszFields);
+    return false;
 }
 
-
 /**********************************************************************
  *                     MITABCoordSys2TABProjInfo()
  *
@@ -336,27 +243,23 @@ GBool MITABExtractCoordSysBounds( const char * pszCoordSys,
 int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
 
 {
-    char        **papszFields;
-
     // Set all fields to zero, equivalent of NonEarth Units "mi"
     memset(psProj, 0, sizeof(TABProjInfo));
 
     if( pszCoordSys == NULL )
         return -1;
 
-    /*-----------------------------------------------------------------
-     * Parse the passed string into words.
-     *----------------------------------------------------------------*/
-    while(*pszCoordSys == ' ') pszCoordSys++;  // Eat leading spaces
+    // Parse the passed string into words.
+    while(*pszCoordSys == ' ')
+        pszCoordSys++;  // Eat leading spaces.
     if( STARTS_WITH_CI(pszCoordSys, "CoordSys") )
         pszCoordSys += 9;
 
-    papszFields = CSLTokenizeStringComplex( pszCoordSys, " ,", TRUE, FALSE );
+    char **papszFields =
+        CSLTokenizeStringComplex(pszCoordSys, " ,", TRUE, FALSE);
 
-    /*-----------------------------------------------------------------
-     * Clip off Bounds information.
-     *----------------------------------------------------------------*/
-    int         iBounds = CSLFindString( papszFields, "Bounds" );
+    // Clip off Bounds information.
+    int iBounds = CSLFindString(papszFields, "Bounds");
 
     while( iBounds != -1 && papszFields[iBounds] != NULL )
     {
@@ -365,31 +268,29 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
         iBounds++;
     }
 
-    /*-----------------------------------------------------------------
-     * Fetch the projection.
-     *----------------------------------------------------------------*/
-    char        **papszNextField;
+    // Fetch the projection.
+    char **papszNextField = NULL;
 
-    if( CSLCount( papszFields ) >= 3
-        && EQUAL(papszFields[0],"Earth")
-        && EQUAL(papszFields[1],"Projection") )
+    if( CSLCount(papszFields) >= 3 &&
+        EQUAL(papszFields[0], "Earth") &&
+        EQUAL(papszFields[1], "Projection") )
     {
         int nProjId = atoi(papszFields[2]);
-        if (nProjId>=3000) nProjId -=3000;
-        else if (nProjId>=2000) nProjId -=2000;
-        else if (nProjId>=1000) nProjId -=1000;
+        if (nProjId >= 3000) nProjId -= 3000;
+        else if (nProjId >= 2000) nProjId -= 2000;
+        else if (nProjId >= 1000) nProjId -= 1000;
 
-        psProj->nProjId = (GByte)nProjId;
+        psProj->nProjId = static_cast<GByte>(nProjId);
         papszNextField = papszFields + 3;
     }
-    else if (CSLCount( papszFields ) >= 2
-             && EQUAL(papszFields[0],"NonEarth") )
+    else if (CSLCount(papszFields) >= 2 &&
+             EQUAL(papszFields[0],"NonEarth") )
     {
         // NonEarth Units "..." Bounds (x, y) (x, y)
         psProj->nProjId = 0;
         papszNextField = papszFields + 2;
 
-        if( papszNextField[0] != NULL && EQUAL(papszNextField[0],"Units") )
+        if( papszNextField[0] != NULL && EQUAL(papszNextField[0], "Units") )
             papszNextField++;
     }
     else
@@ -402,10 +303,8 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
         return -1;
     }
 
-    /*-----------------------------------------------------------------
-     * Fetch the datum information.
-     *----------------------------------------------------------------*/
-    int         nDatum = 0;
+    // Fetch the datum information.
+    int nDatum = 0;
 
     if( psProj->nProjId != 0 && CSLCount(papszNextField) > 0 )
     {
@@ -413,17 +312,17 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
         papszNextField++;
     }
 
-    if( (nDatum == 999 || nDatum == 9999)
-        && CSLCount(papszNextField) >= 4 )
+    if( (nDatum == 999 || nDatum == 9999) &&
+        CSLCount(papszNextField) >= 4 )
     {
-        psProj->nEllipsoidId = (GByte)atoi(papszNextField[0]);
+        psProj->nEllipsoidId = static_cast<GByte>(atoi(papszNextField[0]));
         psProj->dDatumShiftX = CPLAtof(papszNextField[1]);
         psProj->dDatumShiftY = CPLAtof(papszNextField[2]);
         psProj->dDatumShiftZ = CPLAtof(papszNextField[3]);
         papszNextField += 4;
 
-        if( nDatum == 9999
-            && CSLCount(papszNextField) >= 5 )
+        if( nDatum == 9999 &&
+            CSLCount(papszNextField) >= 5 )
         {
             psProj->adDatumParams[0] = CPLAtof(papszNextField[0]);
             psProj->adDatumParams[1] = CPLAtof(papszNextField[1]);
@@ -435,13 +334,11 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
     }
     else if (nDatum != 999 && nDatum != 9999)
     {
-    /*-----------------------------------------------------------------
-     * Find the datum, and collect it's parameters if possible.
-     *----------------------------------------------------------------*/
-        int         iDatum;
+        // Find the datum, and collect it's parameters if possible.
         const MapInfoDatumInfo *psDatumInfo = NULL;
 
-        for(iDatum=0; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++)
+        int iDatum = 0;  // Used after for.
+        for( ; asDatumInfoList[iDatum].nMapInfoDatumID != -1; iDatum++ )
         {
             if( asDatumInfoList[iDatum].nMapInfoDatumID == nDatum )
             {
@@ -450,17 +347,18 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
             }
         }
 
-        if( asDatumInfoList[iDatum].nMapInfoDatumID == -1
-            && nDatum != 999 && nDatum != 9999 )
+        if( asDatumInfoList[iDatum].nMapInfoDatumID == -1 &&
+            nDatum != 999 && nDatum != 9999 )
         {
-            /* use WGS84 */
+            // Use WGS84.
             psDatumInfo = asDatumInfoList + 0;
         }
 
         if( psDatumInfo != NULL )
         {
-            psProj->nEllipsoidId = (GByte)psDatumInfo->nEllipsoid;
-            psProj->nDatumId = (GInt16)psDatumInfo->nMapInfoDatumID;
+            psProj->nEllipsoidId = static_cast<GByte>(psDatumInfo->nEllipsoid);
+            psProj->nDatumId =
+                static_cast<GInt16>(psDatumInfo->nMapInfoDatumID);
             psProj->dDatumShiftX = psDatumInfo->dfShiftX;
             psProj->dDatumShiftY = psDatumInfo->dfShiftY;
             psProj->dDatumShiftZ = psDatumInfo->dfShiftZ;
@@ -472,19 +370,16 @@ int MITABCoordSys2TABProjInfo(const char * pszCoordSys, TABProjInfo *psProj)
         }
     }
 
-    /*-----------------------------------------------------------------
-     * Fetch the units string.
-     *----------------------------------------------------------------*/
+    // Fetch the units string.
     if( CSLCount(papszNextField) > 0 )
     {
-        psProj->nUnitsId = (GByte)TABUnitIdFromString(papszNextField[0]);
+        psProj->nUnitsId =
+            static_cast<GByte>(TABUnitIdFromString(papszNextField[0]));
         papszNextField++;
     }
 
-    /*-----------------------------------------------------------------
-     * Finally the projection parameters.
-     *----------------------------------------------------------------*/
-    for(int iParam=0; iParam < 6 && CSLCount(papszNextField) > 0; iParam++)
+    // Finally the projection parameters.
+    for(int iParam = 0; iParam < 6 && CSLCount(papszNextField) > 0; iParam++)
     {
         psProj->adProjParams[iParam] = CPLAtof(papszNextField[0]);
         papszNextField++;
diff --git a/ogr/ogrsf_frmts/mitab/mitab_datfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_datfile.cpp
index 4e1cf04..6dba288 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_datfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_datfile.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_datfile.cpp,v 1.22 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_datfile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,84 +28,32 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_datfile.cpp,v $
- * Revision 1.22  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.21  2009-06-08 20:30:46  dmorissette
- * Fixed threading issue (static buffer) in Date and DateTime code (GDAL
- * ticket #1883)
- *
- * Revision 1.20  2008-11-27 20:50:22  aboudreault
- * Improved support for OGR date/time types. New Read/Write methods (bug 1948)
- * Added support of OGR date/time types for MIF features.
- *
- * Revision 1.19  2008/01/29 20:46:32  dmorissette
- * Added support for v9 Time and DateTime fields (byg 1754)
- *
- * Revision 1.18  2007/10/09 17:43:16  fwarmerdam
- * Remove static variables that interfere with reentrancy. (GDAL #1883)
- *
- * Revision 1.17  2004/06/30 20:29:03  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.16  2001/05/01 12:32:03  daniel
- * Get rid of leading spaces in WriteDateField().
- *
- * Revision 1.15  2000/04/27 15:42:03  daniel
- * Map variable field length (width=0) coming from OGR to acceptable default
- *
- * Revision 1.14  2000/02/28 16:52:52  daniel
- * Added support for writing indexes, removed validation on field name in
- * NATIVE tables, and remove trailing spaces in DBF char field values
- *
- * Revision 1.13  2000/01/28 07:31:49  daniel
- * Validate char field width (must be <= 254 chars)
- *
- * Revision 1.12  2000/01/16 19:08:48  daniel
- * Added support for reading 'Table Type DBF' tables
- *
- * Revision 1.11  2000/01/15 22:30:43  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.10  1999/12/20 18:59:20  daniel
- * Dates again... now returned as "YYYYMMDD"
- *
- * Revision 1.9  1999/12/16 17:11:45  daniel
- * Date fields: return as "YYYY/MM/DD", and accept 3 diff. formats as input
- *
- * Revision 1.8  1999/12/14 03:58:29  daniel
- * Fixed date read/write (bytes were reversed)
- *
- * Revision 1.7  1999/11/09 07:34:35  daniel
- * Return default values when deleted attribute records are encountered
- *
- * Revision 1.6  1999/10/19 06:09:25  daniel
- * Removed obsolete GetFieldDef() method
- *
- * Revision 1.5  1999/10/01 03:56:28  daniel
- * Avoid multiple InitWriteHeader() calls (caused a leak) and added a fix
- * in WriteCharField() to prevent reading bytes past end of string buffer
- *
- * Revision 1.4  1999/10/01 02:02:36  warmerda
- * Added assertions to try and track TABRawBinBlock leak.
- *
- * Revision 1.3  1999/09/26 14:59:36  daniel
- * Implemented write support
- *
- * Revision 1.2  1999/09/20 18:43:20  daniel
- * Use binary access to open file.
- *
- * Revision 1.1  1999/07/12 04:18:23  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
 #include "ogr_p.h"
 
+CPL_CVSID("$Id: mitab_datfile.cpp 37429 2017-02-20 08:11:20Z goatbar $");
+
 /*=====================================================================
  *                      class TABDATFile
  *
@@ -120,34 +67,36 @@
  * in binary form inside a 4 bytes string field.
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABDATFile::TABDATFile()
  *
  * Constructor.
  **********************************************************************/
-TABDATFile::TABDATFile()
+TABDATFile::TABDATFile() :
+    m_pszFname(NULL),
+    m_fp(NULL),
+    m_eAccessMode(TABRead),
+    m_eTableType(TABTableNative),
+    m_poHeaderBlock(NULL),
+    m_numFields(-1),
+    m_pasFieldDef(NULL),
+    m_poRecordBlock(NULL),
+    m_nBlockSize(0),
+    m_nRecordSize(-1),
+    m_nCurRecordId(-1),
+    m_bCurRecordDeletedFlag(FALSE),
+    m_numRecords(-1),
+    m_nFirstRecordPtr(0),
+    m_bWriteHeaderInitialized(FALSE),
+    m_bWriteEOF(FALSE),
+    m_bUpdated(FALSE)
+#if HAVE_CXX11
+    , m_szBuffer{}
+#endif
 {
-    m_fp = NULL;
-    m_pszFname = NULL;
-    m_eTableType = TABTableNative;
-
-    m_poHeaderBlock = NULL;
-    m_poRecordBlock = NULL;
-    m_pasFieldDef = NULL;
-
-    m_numFields = -1;
-    m_numRecords = -1;
-    m_nFirstRecordPtr = 0;
-    m_nBlockSize = 0;
-    m_nRecordSize = -1;
-    m_nCurRecordId = -1;
-    m_bCurRecordDeletedFlag = FALSE;
-    m_bWriteHeaderInitialized = FALSE;
-    m_bWriteEOF = FALSE;
-
-    m_bUpdated = FALSE;
-    m_eAccessMode = TABRead;
+#ifndef HAVE_CXX11
+  memset(m_szBuffer, 0, sizeof(m_szBuffer));
+#endif
 }
 
 /**********************************************************************
@@ -155,10 +104,7 @@ TABDATFile::TABDATFile()
  *
  * Destructor.
  **********************************************************************/
-TABDATFile::~TABDATFile()
-{
-    Close();
-}
+TABDATFile::~TABDATFile() { Close(); }
 
 /**********************************************************************
  *                   TABDATFile::Open()
@@ -167,12 +113,18 @@ TABDATFile::~TABDATFile()
  * Return 0 on success, -1 in case of failure.
  **********************************************************************/
 
-int TABDATFile::Open(const char *pszFname, const char* pszAccess, TABTableType eTableType)
+int TABDATFile::Open(const char *pszFname, const char *pszAccess,
+                     TABTableType eTableType)
 {
+    // cppcheck-suppress nullPointer
     if( STARTS_WITH_CI(pszAccess, "r") )
+    {
         return Open(pszFname, TABRead, eTableType);
+    }
     else if( STARTS_WITH_CI(pszAccess, "w") )
+    {
         return Open(pszFname, TABWrite, eTableType);
+    }
     else
     {
         CPLError(CE_Failure, CPLE_FileIO,
@@ -195,8 +147,6 @@ int TABDATFile::Open(const char *pszFname, const char* pszAccess, TABTableType e
 int TABDATFile::Open(const char *pszFname, TABAccess eAccess,
                      TABTableType eTableType /*=TABNativeTable*/)
 {
-    int i;
-
     if (m_fp)
     {
         CPLError(CE_Failure, CPLE_FileIO,
@@ -204,43 +154,39 @@ int TABDATFile::Open(const char *pszFname, TABAccess eAccess,
         return -1;
     }
 
-    /*-----------------------------------------------------------------
-     * Validate access mode and make sure we use binary access.
-     *----------------------------------------------------------------*/
-    const char* pszAccess = NULL;
-    if (eAccess == TABRead && (eTableType==TABTableNative ||
-                                      eTableType==TABTableDBF)  )
+    // Validate access mode and make sure we use binary access.
+    const char *pszAccess = NULL;
+    if(eAccess == TABRead &&
+       (eTableType == TABTableNative || eTableType == TABTableDBF))
     {
         pszAccess = "rb";
     }
-    else if (eAccess == TABWrite && eTableType==TABTableNative)
+    else if (eAccess == TABWrite && eTableType == TABTableNative)
     {
         pszAccess = "wb+";
     }
-    else if (eAccess == TABReadWrite && eTableType==TABTableNative)
+    else if (eAccess == TABReadWrite && eTableType == TABTableNative)
     {
         pszAccess = "rb+";
     }
     else
     {
         CPLError(CE_Failure, CPLE_FileIO,
-                 "Open() failed: access mode \"%d\" not supported with eTableType=%d",
+                 "Open() failed: access mode \"%d\" "
+                 "not supported with eTableType=%d",
                  eAccess, eTableType);
         return -1;
     }
     m_eAccessMode = eAccess;
 
-    /*-----------------------------------------------------------------
-     * Open file for reading
-     *----------------------------------------------------------------*/
+    // Open file for reading.
     m_pszFname = CPLStrdup(pszFname);
     m_fp = VSIFOpenL(m_pszFname, pszAccess);
     m_eTableType = eTableType;
 
     if (m_fp == NULL)
     {
-        CPLError(CE_Failure, CPLE_FileIO,
-                 "Open() failed for %s", m_pszFname);
+        CPLError(CE_Failure, CPLE_FileIO, "Open() failed for %s", m_pszFname);
         CPLFree(m_pszFname);
         m_pszFname = NULL;
         return -1;
@@ -248,22 +194,20 @@ int TABDATFile::Open(const char *pszFname, TABAccess eAccess,
 
     if (m_eAccessMode == TABRead || m_eAccessMode == TABReadWrite)
     {
-        /*------------------------------------------------------------
-         * READ ACCESS:
-         * Read .DAT file header (record size, num records, etc...)
-         * m_poHeaderBlock will be reused later to read field definition
-         *-----------------------------------------------------------*/
+        // READ ACCESS:
+        // Read .DAT file header (record size, num records, etc...)
+        // m_poHeaderBlock will be reused later to read field definition
         m_poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE);
         CPL_IGNORE_RET_VAL(m_poHeaderBlock->ReadFromFile(m_fp, 0, 32));
 
-        m_poHeaderBlock->ReadByte();       // Table type ??? 0x03
-        m_poHeaderBlock->ReadByte();       // Last update year
-        m_poHeaderBlock->ReadByte();       // Last update month
-        m_poHeaderBlock->ReadByte();       // Last update day
+        m_poHeaderBlock->ReadByte();  // Table type ??? 0x03
+        m_poHeaderBlock->ReadByte();  // Last update year
+        m_poHeaderBlock->ReadByte();  // Last update month
+        m_poHeaderBlock->ReadByte();  // Last update day
 
-        m_numRecords      = m_poHeaderBlock->ReadInt32();
+        m_numRecords = m_poHeaderBlock->ReadInt32();
         m_nFirstRecordPtr = m_poHeaderBlock->ReadInt16();
-        m_nRecordSize     = m_poHeaderBlock->ReadInt16();
+        m_nRecordSize = m_poHeaderBlock->ReadInt16();
         if( m_nFirstRecordPtr < 32 || m_nRecordSize <= 0 || m_numRecords < 0 )
         {
             VSIFCloseL(m_fp);
@@ -274,39 +218,38 @@ int TABDATFile::Open(const char *pszFname, TABAccess eAccess,
             m_poHeaderBlock = NULL;
             return -1;
         }
-        m_numFields = m_nFirstRecordPtr/32 - 1;
+        m_numFields = m_nFirstRecordPtr / 32 - 1;
 
-        /*-------------------------------------------------------------
-         * Read the field definitions
-         * First 32 bytes field definition starts at byte 32 in file
-         *------------------------------------------------------------*/
-        m_pasFieldDef = (TABDATFieldDef*)CPLCalloc(m_numFields,
-                                                   sizeof(TABDATFieldDef));
+        // Read the field definitions.
+        // First 32 bytes field definition starts at byte 32 in file.
+        m_pasFieldDef = static_cast<TABDATFieldDef*>(
+            CPLCalloc(m_numFields, sizeof(TABDATFieldDef)));
 
-        for(i=0; i<m_numFields; i++)
+        for( int i = 0; i < m_numFields; i++ )
         {
-            m_poHeaderBlock->GotoByteInFile((i+1)*32);
-            m_poHeaderBlock->ReadBytes(11, (GByte*)m_pasFieldDef[i].szName);
+            m_poHeaderBlock->GotoByteInFile((i + 1) * 32);
+            m_poHeaderBlock->ReadBytes(
+                11, reinterpret_cast<GByte *>(m_pasFieldDef[i].szName));
             m_pasFieldDef[i].szName[10] = '\0';
-            m_pasFieldDef[i].cType = (char)m_poHeaderBlock->ReadByte();
+            m_pasFieldDef[i].cType =
+                static_cast<char>(m_poHeaderBlock->ReadByte());
 
-            m_poHeaderBlock->ReadInt32();       // Skip Bytes 12-15
+            m_poHeaderBlock->ReadInt32();  // Skip Bytes 12-15
             m_pasFieldDef[i].byLength = m_poHeaderBlock->ReadByte();
             m_pasFieldDef[i].byDecimals = m_poHeaderBlock->ReadByte();
 
             m_pasFieldDef[i].eTABType = TABFUnknown;
         }
 
-        /*-------------------------------------------------------------
-         * Establish a good record block size to use based on record size, and
-         * then create m_poRecordBlock
-         * Record block size has to be a multiple of record size.
-         *------------------------------------------------------------*/
-        m_nBlockSize = ((1024/m_nRecordSize)+1)*m_nRecordSize;
+        // Establish a good record block size to use based on record size, and
+        // then create m_poRecordBlock.
+        // Record block size has to be a multiple of record size.
+        m_nBlockSize = ((1024 / m_nRecordSize) + 1) * m_nRecordSize;
         if( m_numRecords < INT_MAX / m_nRecordSize )
-            m_nBlockSize = MIN(m_nBlockSize, (m_numRecords*m_nRecordSize));
+            m_nBlockSize =
+                std::min(m_nBlockSize, (m_numRecords * m_nRecordSize));
 
-        CPLAssert( m_poRecordBlock == NULL );
+        CPLAssert(m_poRecordBlock == NULL);
         m_poRecordBlock = new TABRawBinBlock(m_eAccessMode, FALSE);
         m_poRecordBlock->InitNewBlock(m_fp, m_nBlockSize);
         m_poRecordBlock->SetFirstBlockPtr(m_nFirstRecordPtr);
@@ -315,17 +258,15 @@ int TABDATFile::Open(const char *pszFname, TABAccess eAccess,
     }
     else
     {
-        /*------------------------------------------------------------
-         * WRITE ACCESS:
-         * Set acceptable defaults for all class members.
-         * The real header initialization will be done when the first
-         * record is written
-         *-----------------------------------------------------------*/
+        // WRITE ACCESS:
+        // Set acceptable defaults for all class members.
+        // The real header initialization will be done when the first
+        // record is written.
         m_poHeaderBlock = NULL;
 
-        m_numRecords      = 0;
+        m_numRecords = 0;
         m_nFirstRecordPtr = 0;
-        m_nRecordSize     = 0;
+        m_nRecordSize = 0;
         m_numFields = 0;
         m_pasFieldDef = NULL;
         m_bWriteHeaderInitialized = FALSE;
@@ -346,10 +287,8 @@ int TABDATFile::Close()
     if (m_fp == NULL)
         return 0;
 
-    /*----------------------------------------------------------------
-     * Write access: Update the header with number of records, etc.
-     * and add a CTRL-Z char at the end of the file.
-     *---------------------------------------------------------------*/
+    // Write access: Update the header with number of records, etc.
+    // and add a CTRL-Z char at the end of the file.
     if (m_eAccessMode != TABRead )
     {
         SyncToDisk();
@@ -424,37 +363,29 @@ int TABDATFile::SyncToDisk()
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int  TABDATFile::InitWriteHeader()
+int TABDATFile::InitWriteHeader()
 {
-    int i;
-
     if (m_eAccessMode == TABRead || m_bWriteHeaderInitialized)
         return 0;
 
-    /*------------------------------------------------------------
-     * Compute values for Record size, header size, etc.
-     *-----------------------------------------------------------*/
-    m_nFirstRecordPtr = (m_numFields+1)*32 + 1;
+    // Compute values for Record size, header size, etc.
+    m_nFirstRecordPtr = (m_numFields + 1) * 32 + 1;
 
     m_nRecordSize = 1;
-    for(i=0; i<m_numFields; i++)
+    for( int i = 0; i < m_numFields; i++ )
     {
         m_nRecordSize += m_pasFieldDef[i].byLength;
     }
 
-    /*-------------------------------------------------------------
-     * Create m_poRecordBlock the size of a data record.
-     *------------------------------------------------------------*/
+    // Create m_poRecordBlock the size of a data record.
     m_nBlockSize = m_nRecordSize;
 
-    CPLAssert( m_poRecordBlock == NULL );
+    CPLAssert(m_poRecordBlock == NULL);
     m_poRecordBlock = new TABRawBinBlock(TABReadWrite, FALSE);
     m_poRecordBlock->InitNewBlock(m_fp, m_nBlockSize);
     m_poRecordBlock->SetFirstBlockPtr(m_nFirstRecordPtr);
 
-    /*-------------------------------------------------------------
-     * Make sure this init. will be performed only once
-     *------------------------------------------------------------*/
+    // Make sure this init. will be performed only once.
     m_bWriteHeaderInitialized = TRUE;
 
     return 0;
@@ -470,8 +401,6 @@ int  TABDATFile::InitWriteHeader()
  **********************************************************************/
 int  TABDATFile::WriteHeader()
 {
-    int i;
-
     if (m_eAccessMode == TABRead)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -482,58 +411,47 @@ int  TABDATFile::WriteHeader()
     if (!m_bWriteHeaderInitialized)
         InitWriteHeader();
 
-    /*------------------------------------------------------------
-     * Create a single block that will be used to generate the whole header.
-     *-----------------------------------------------------------*/
+    // Create a single block that will be used to generate the whole header.
     if (m_poHeaderBlock == NULL)
         m_poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE);
     m_poHeaderBlock->InitNewBlock(m_fp, m_nFirstRecordPtr, 0);
 
-    /*------------------------------------------------------------
-     * First 32 bytes: main header block
-     *-----------------------------------------------------------*/
+    // First 32 bytes: main header block.
     m_poHeaderBlock->WriteByte(0x03);  // Table type ??? 0x03
 
     // __TODO__ Write the correct update date value
-    m_poHeaderBlock->WriteByte(99);    // Last update year
-    m_poHeaderBlock->WriteByte(9);     // Last update month
-    m_poHeaderBlock->WriteByte(9);     // Last update day
+    m_poHeaderBlock->WriteByte(99);  // Last update year
+    m_poHeaderBlock->WriteByte(9);   // Last update month
+    m_poHeaderBlock->WriteByte(9);   // Last update day
 
     m_poHeaderBlock->WriteInt32(m_numRecords);
-    m_poHeaderBlock->WriteInt16((GInt16)m_nFirstRecordPtr);
-    m_poHeaderBlock->WriteInt16((GInt16)m_nRecordSize);
+    m_poHeaderBlock->WriteInt16(static_cast<GInt16>(m_nFirstRecordPtr));
+    m_poHeaderBlock->WriteInt16(static_cast<GInt16>(m_nRecordSize));
 
-    m_poHeaderBlock->WriteZeros(20);    // Pad rest with zeros
+    m_poHeaderBlock->WriteZeros(20);  // Pad rest with zeros.
 
-    /*-------------------------------------------------------------
-     * Field definitions follow.  Each field def is 32 bytes.
-     *------------------------------------------------------------*/
-    for(i=0; i<m_numFields; i++)
+    // Field definitions follow.  Each field def is 32 bytes.
+    for( int i = 0; i < m_numFields; i++ )
     {
-        m_poHeaderBlock->WriteBytes(11, (GByte*)m_pasFieldDef[i].szName);
+        m_poHeaderBlock->WriteBytes(
+            11, reinterpret_cast<GByte *>(m_pasFieldDef[i].szName));
         m_poHeaderBlock->WriteByte(m_pasFieldDef[i].cType);
 
-        m_poHeaderBlock->WriteInt32(0);       // Skip Bytes 12-15
+        m_poHeaderBlock->WriteInt32(0);  // Skip Bytes 12-15
 
         m_poHeaderBlock->WriteByte(m_pasFieldDef[i].byLength);
         m_poHeaderBlock->WriteByte(m_pasFieldDef[i].byDecimals);
 
-        m_poHeaderBlock->WriteZeros(14);    // Pad rest with zeros
+        m_poHeaderBlock->WriteZeros(14);  // Pad rest with zeros
     }
 
-    /*-------------------------------------------------------------
-     * Header ends with a 0x0d character.
-     *------------------------------------------------------------*/
+    // Header ends with a 0x0d character.
     m_poHeaderBlock->WriteByte(0x0d);
 
-    /*-------------------------------------------------------------
-     * Write the block to the file and return.
-     *------------------------------------------------------------*/
+    // Write the block to the file and return.
     return m_poHeaderBlock->CommitToFile();
 }
 
-
-
 /**********************************************************************
  *                   TABDATFile::GetNumFields()
  *
@@ -541,10 +459,7 @@ int  TABDATFile::WriteHeader()
  *
  * Returns a value >= 0 on success, -1 on error.
  **********************************************************************/
-int  TABDATFile::GetNumFields()
-{
-    return m_numFields;
-}
+int TABDATFile::GetNumFields() { return m_numFields; }
 
 /**********************************************************************
  *                   TABDATFile::GetNumRecords()
@@ -553,10 +468,7 @@ int  TABDATFile::GetNumFields()
  *
  * Returns a value >= 0 on success, -1 on error.
  **********************************************************************/
-int  TABDATFile::GetNumRecords()
-{
-    return m_numRecords;
-}
+int TABDATFile::GetNumRecords() { return m_numRecords; }
 
 /**********************************************************************
  *                   TABDATFile::GetRecordBlock()
@@ -584,16 +496,11 @@ TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId)
 
     if (m_eAccessMode == TABRead || nRecordId <= m_numRecords)
     {
-        /*-------------------------------------------------------------
-         * READ ACCESS
-         *------------------------------------------------------------*/
-        int nFileOffset;
-
-        nFileOffset = m_nFirstRecordPtr+(nRecordId-1)*m_nRecordSize;
+        // READ ACCESS
+        const int nFileOffset =
+            m_nFirstRecordPtr + (nRecordId - 1) * m_nRecordSize;
 
-        /*-------------------------------------------------------------
-         * Move record block pointer to the right location
-         *------------------------------------------------------------*/
+        // Move record block pointer to the right location.
         if ( m_poRecordBlock == NULL ||
              nRecordId < 1 || nRecordId > m_numRecords ||
              m_poRecordBlock->GotoByteInFile(nFileOffset) != 0 )
@@ -604,13 +511,11 @@ TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId)
             return NULL;
         }
 
-        /*-------------------------------------------------------------
-         * The first char of the record is a ' ' for an active record, or
-         * '*' for a deleted one.
-         * In the case of a deleted record, we simply return default
-         * values for each attribute... this is what MapInfo seems to do
-         * when it takes a .TAB with deleted records and exports it to .MIF
-         *------------------------------------------------------------*/
+        // The first char of the record is a ' ' for an active record, or
+        // '*' for a deleted one.
+        // In the case of a deleted record, we simply return default
+        // values for each attribute... this is what MapInfo seems to do
+        // when it takes a .TAB with deleted records and exports it to .MIF
         if (m_poRecordBlock->ReadByte() != ' ')
         {
             m_bCurRecordDeletedFlag = TRUE;
@@ -618,16 +523,11 @@ TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId)
     }
     else if (nRecordId > 0)
     {
-        /*-------------------------------------------------------------
-         * WRITE ACCESS
-         *------------------------------------------------------------*/
-        int nFileOffset;
+        // WRITE ACCESS
 
-        /*-------------------------------------------------------------
-         * Before writing the first record, we must generate the file
-         * header.  We will also initialize class members such as record
-         * size, etc. and will create m_poRecordBlock.
-         *------------------------------------------------------------*/
+        // Before writing the first record, we must generate the file
+        // header.  We will also initialize class members such as record
+        // size, etc. and will create m_poRecordBlock.
         if (!m_bWriteHeaderInitialized)
         {
             WriteHeader();
@@ -635,20 +535,18 @@ TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId)
 
         m_bUpdated = TRUE;
 
-        m_numRecords = MAX(nRecordId, m_numRecords);
+        m_numRecords = std::max(nRecordId, m_numRecords);
         if( nRecordId == m_numRecords )
             m_bWriteEOF = TRUE;
 
-        nFileOffset = m_nFirstRecordPtr+(nRecordId-1)*m_nRecordSize;
+        const int nFileOffset =
+            m_nFirstRecordPtr + (nRecordId - 1) * m_nRecordSize;
 
         m_poRecordBlock->InitNewBlock(m_fp, m_nRecordSize, nFileOffset);
 
-        /*-------------------------------------------------------------
-         * The first char of the record is the active/deleted flag.
-         * Automatically set it to ' ' (active).
-         *------------------------------------------------------------*/
+        // The first char of the record is the active/deleted flag.
+        // Automatically set it to ' ' (active).
         m_poRecordBlock->WriteByte(' ');
-
     }
 
     m_nCurRecordId = nRecordId;
@@ -666,7 +564,7 @@ TABRawBinBlock *TABDATFile::GetRecordBlock(int nRecordId)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int  TABDATFile::CommitRecordToFile()
+int TABDATFile::CommitRecordToFile()
 {
     if (m_eAccessMode == TABRead || m_poRecordBlock == NULL)
         return -1;
@@ -674,7 +572,7 @@ int  TABDATFile::CommitRecordToFile()
     if (m_poRecordBlock->CommitToFile() != 0)
         return -1;
 
-    /* If this is the end of file, write EOF character */
+    // If this is the end of file, write EOF character.
     if (m_bWriteEOF)
     {
         m_bWriteEOF = FALSE;
@@ -696,8 +594,8 @@ int TABDATFile::MarkAsDeleted()
     if (m_eAccessMode == TABRead || m_poRecordBlock == NULL)
         return -1;
 
-    int nFileOffset;
-    nFileOffset = m_nFirstRecordPtr+(m_nCurRecordId-1)*m_nRecordSize;
+    const int nFileOffset =
+        m_nFirstRecordPtr + (m_nCurRecordId - 1) * m_nRecordSize;
 
     if (m_poRecordBlock->GotoByteInFile(nFileOffset) != 0)
         return -1;
@@ -723,8 +621,8 @@ int TABDATFile::MarkRecordAsExisting()
     if (m_eAccessMode == TABRead || m_poRecordBlock == NULL)
         return -1;
 
-    int nFileOffset;
-    nFileOffset = m_nFirstRecordPtr+(m_nCurRecordId-1)*m_nRecordSize;
+    const int nFileOffset =
+        m_nFirstRecordPtr + (m_nCurRecordId - 1) * m_nRecordSize;
 
     if (m_poRecordBlock->GotoByteInFile(nFileOffset) != 0)
         return -1;
@@ -737,7 +635,6 @@ int TABDATFile::MarkRecordAsExisting()
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABDATFile::ValidateFieldInfoFromTAB()
  *
@@ -765,23 +662,23 @@ int  TABDATFile::ValidateFieldInfoFromTAB(int iField, const char *pszName,
 
     if (m_pasFieldDef == NULL || iField < 0 || iField >= m_numFields)
     {
-        CPLError(CE_Failure, CPLE_FileIO,
-          "Invalid field %d (%s) in .TAB header. %s contains only %d fields.",
-                 iField+1, pszName, m_pszFname, m_pasFieldDef? m_numFields:0);
+        CPLError(
+            CE_Failure, CPLE_FileIO,
+            "Invalid field %d (%s) in .TAB header. %s contains only %d fields.",
+            iField + 1, pszName, m_pszFname, m_pasFieldDef ? m_numFields : 0);
         return -1;
     }
 
-    /*-----------------------------------------------------------------
-     * We used to check that the .TAB field name matched the .DAT
-     * name stored internally, but apparently some tools that rename table
-     * field names only update the .TAB file and not the .DAT, so we won't
-     * do that name validation any more... we'll just check the type.
-     *
-     * With TABTableNative, we have to validate the field sizes as well
-     * because .DAT files use char fields to store binary values.
-     * With TABTableDBF, no need to validate field type since all
-     * fields are stored as strings internally.
-     *----------------------------------------------------------------*/
+    // We used to check that the .TAB field name matched the .DAT
+    // name stored internally, but apparently some tools that rename table
+    // field names only update the .TAB file and not the .DAT, so we won't
+    // do that name validation any more... we'll just check the type.
+    //
+    // With TABTableNative, we have to validate the field sizes as well
+    // because .DAT files use char fields to store binary values.
+    // With TABTableDBF, no need to validate field type since all
+    // fields are stored as strings internally.
+
     if ((m_eTableType == TABTableNative &&
          ((eType == TABFChar && (m_pasFieldDef[i].cType != 'C' ||
                                 m_pasFieldDef[i].byLength != nWidth )) ||
@@ -806,7 +703,7 @@ int  TABDATFile::ValidateFieldInfoFromTAB(int iField, const char *pszName,
         CPLError(CE_Failure, CPLE_FileIO,
                  "Definition of field %d (%s) from .TAB file does not match "
                  "what is found in %s (name=%s, type=%c, width=%d, prec=%d)",
-                 iField+1, pszName, m_pszFname,
+                 iField + 1, pszName, m_pszFname,
                  m_pasFieldDef[i].szName, m_pasFieldDef[i].cType,
                  m_pasFieldDef[i].byLength, m_pasFieldDef[i].byDecimals);
         return -1;
@@ -821,14 +718,11 @@ int  TABDATFile::ValidateFieldInfoFromTAB(int iField, const char *pszName,
  *                  TABDATFileSetFieldDefinition()
  *
  **********************************************************************/
-static int TABDATFileSetFieldDefinition(TABDATFieldDef* psFieldDef,
+static int TABDATFileSetFieldDefinition(TABDATFieldDef *psFieldDef,
                                         const char *pszName, TABFieldType eType,
                                         int nWidth, int nPrecision)
 {
-
-    /*-----------------------------------------------------------------
-     * Validate field width... must be <= 254
-     *----------------------------------------------------------------*/
+    // Validate field width.
     if (nWidth > 254)
     {
         CPLError(CE_Failure, CPLE_IllegalArg,
@@ -837,57 +731,55 @@ static int TABDATFileSetFieldDefinition(TABDATFieldDef* psFieldDef,
         return -1;
     }
 
-    /*-----------------------------------------------------------------
-     * Map fields with width=0 (variable length in OGR) to a valid default
-     *----------------------------------------------------------------*/
+    // Map fields with width=0 (variable length in OGR) to a valid default.
     if (eType == TABFDecimal && nWidth == 0)
-        nWidth=20;
+        nWidth = 20;
     else if (nWidth == 0)
-        nWidth=254; /* char fields */
+        nWidth = 254;  // char fields.
 
-    strncpy(psFieldDef->szName, pszName, 10);
-    psFieldDef->szName[10] = '\0';
+    strncpy(psFieldDef->szName, pszName, sizeof(psFieldDef->szName) - 1);
+    psFieldDef->szName[sizeof(psFieldDef->szName) - 1] = '\0';
     psFieldDef->eTABType = eType;
-    psFieldDef->byLength = (GByte)nWidth;
-    psFieldDef->byDecimals = (GByte)nPrecision;
+    psFieldDef->byLength = static_cast<GByte>(nWidth);
+    psFieldDef->byDecimals = static_cast<GByte>(nPrecision);
 
     switch(eType)
     {
-      case TABFChar:
+    case TABFChar:
         psFieldDef->cType = 'C';
         break;
-      case TABFDecimal:
+    case TABFDecimal:
         psFieldDef->cType = 'N';
         break;
-      case TABFInteger:
+    case TABFInteger:
         psFieldDef->cType = 'C';
         psFieldDef->byLength = 4;
         break;
-      case TABFSmallInt:
+    case TABFSmallInt:
         psFieldDef->cType = 'C';
         psFieldDef->byLength = 2;
         break;
-      case TABFFloat:
+    case TABFFloat:
         psFieldDef->cType = 'C';
         psFieldDef->byLength = 8;
         break;
-      case TABFDate:
+    case TABFDate:
         psFieldDef->cType = 'C';
         psFieldDef->byLength = 4;
         break;
-      case TABFTime:
+    case TABFTime:
         psFieldDef->cType = 'C';
         psFieldDef->byLength = 4;
         break;
-      case TABFDateTime:
+    case TABFDateTime:
         psFieldDef->cType = 'C';
         psFieldDef->byLength = 8;
         break;
-      case TABFLogical:
+    case TABFLogical:
         psFieldDef->cType = 'L';
         psFieldDef->byLength = 1;
         break;
-      default:
+    default:
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Unsupported field type for field `%s'", pszName);
         return -1;
@@ -905,13 +797,14 @@ static int TABDATFileSetFieldDefinition(TABDATFieldDef* psFieldDef,
  *
  * Returns the new field index (a value >= 0) if OK, -1 on error.
  **********************************************************************/
-int  TABDATFile::AddField(const char *pszName, TABFieldType eType,
-                          int nWidth, int nPrecision /*=0*/)
+int TABDATFile::AddField(const char *pszName, TABFieldType eType,
+                         int nWidth, int nPrecision /* =0 */)
 {
     if (m_eAccessMode == TABRead || m_eTableType != TABTableNative)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "Operation not supported on read-only files or on non-native table.");
+                 "Operation not supported on read-only files or "
+                 "on non-native table.");
         return -1;
     }
 
@@ -924,13 +817,13 @@ int  TABDATFile::AddField(const char *pszName, TABFieldType eType,
         m_numFields = 0;
 
     m_numFields++;
-    m_pasFieldDef = (TABDATFieldDef*)CPLRealloc(m_pasFieldDef,
-                                          m_numFields*sizeof(TABDATFieldDef));
-    memcpy(&m_pasFieldDef[m_numFields-1], &sFieldDef, sizeof(sFieldDef));
+    m_pasFieldDef = static_cast<TABDATFieldDef *>(
+        CPLRealloc(m_pasFieldDef, m_numFields * sizeof(TABDATFieldDef)));
+    memcpy(&m_pasFieldDef[m_numFields - 1], &sFieldDef, sizeof(sFieldDef));
 
-    /* If there are already records, we cannot update in place */
-    /* so create a temporary .dat.tmp in which we create the new structure */
-    /* and then copy the widen records */
+    // If there are already records, we cannot update in place.
+    // Create a temporary .dat.tmp in which we create the new structure
+    // and then copy the widen records.
     if( m_numRecords > 0 )
     {
         TABDATFile oTempFile;
@@ -940,23 +833,21 @@ int  TABDATFile::AddField(const char *pszName, TABFieldType eType,
         if( oTempFile.Open( osTmpFile.c_str(), TABWrite ) != 0 )
             return -1;
 
-        int i;
-        /* Create field structure */
-        for(i = 0; i < m_numFields; i++)
+        // Create field structure.
+        for( int i = 0; i < m_numFields; i++ )
         {
-            oTempFile.AddField(m_pasFieldDef[i].szName,
-                               m_pasFieldDef[i].eTABType,
-                               m_pasFieldDef[i].byLength,
-                               m_pasFieldDef[i].byDecimals);
+            oTempFile.AddField(
+                m_pasFieldDef[i].szName, m_pasFieldDef[i].eTABType,
+                m_pasFieldDef[i].byLength, m_pasFieldDef[i].byDecimals);
         }
 
-        GByte* pabyRecord = (GByte*)CPLMalloc(m_nRecordSize);
+        GByte *pabyRecord = static_cast<GByte *>(CPLMalloc(m_nRecordSize));
 
-        /* Copy records */
+        // Copy records.
         for(int j = 0; j < m_numRecords; j++)
         {
-            if( GetRecordBlock(1+j) == NULL ||
-                oTempFile.GetRecordBlock(1+j) == NULL )
+            if( GetRecordBlock(1 + j) == NULL ||
+                oTempFile.GetRecordBlock(1 + j) == NULL )
             {
                 CPLFree(pabyRecord);
                 oTempFile.Close();
@@ -969,8 +860,8 @@ int  TABDATFile::AddField(const char *pszName, TABFieldType eType,
             }
             else
             {
-                if( m_poRecordBlock->ReadBytes(m_nRecordSize-1, pabyRecord) != 0 ||
-                    oTempFile.m_poRecordBlock->WriteBytes(m_nRecordSize-1, pabyRecord) != 0 ||
+                if( m_poRecordBlock->ReadBytes(m_nRecordSize - 1, pabyRecord) != 0 ||
+                    oTempFile.m_poRecordBlock->WriteBytes(m_nRecordSize - 1, pabyRecord) != 0 ||
                     oTempFile.m_poRecordBlock->WriteZeros(m_pasFieldDef[m_numFields-1].byLength) != 0 )
                 {
                     CPLFree(pabyRecord);
@@ -984,28 +875,29 @@ int  TABDATFile::AddField(const char *pszName, TABFieldType eType,
 
         CPLFree(pabyRecord);
 
-        /* Close temporary file */
+        // Close temporary file.
         oTempFile.Close();
 
-        /* Backup field definitions as we will need to set the TABFieldType */
-        TABDATFieldDef* pasFieldDefTmp = (TABDATFieldDef*)CPLMalloc(m_numFields*sizeof(TABDATFieldDef));
-        memcpy(pasFieldDefTmp, m_pasFieldDef, m_numFields*sizeof(TABDATFieldDef));
+        // Backup field definitions as we will need to set the TABFieldType.
+        TABDATFieldDef *pasFieldDefTmp = static_cast<TABDATFieldDef *>(
+            CPLMalloc(m_numFields * sizeof(TABDATFieldDef)));
+        memcpy(pasFieldDefTmp, m_pasFieldDef,
+               m_numFields * sizeof(TABDATFieldDef));
 
-        /* Close ourselves */
-        m_numFields--; /* so that Close() doesn't see the new field */
+        m_numFields--;  // So that Close() doesn't see the new field.
         Close();
 
-        /* Move temporary file as main .data file and reopen it */
+        // Move temporary file as main .data file and reopen it.
         VSIUnlink(osOriginalFile);
         VSIRename(osTmpFile, osOriginalFile);
-        if( Open( osOriginalFile, TABReadWrite ) < 0 )
+        if( Open(osOriginalFile, TABReadWrite) < 0 )
         {
             CPLFree(pasFieldDefTmp);
             return -1;
         }
 
-        /* Restore saved TABFieldType */
-        for(i = 0; i < m_numFields; i++)
+        // Restore saved TABFieldType.
+        for( int i = 0; i < m_numFields; i++ )
         {
             m_pasFieldDef[i].eTABType = pasFieldDefTmp[i].eTABType;
         }
@@ -1015,7 +907,6 @@ int  TABDATFile::AddField(const char *pszName, TABFieldType eType,
     return 0;
 }
 
-
 /************************************************************************/
 /*                            DeleteField()                             */
 /************************************************************************/
@@ -1025,69 +916,74 @@ int TABDATFile::DeleteField( int iField )
     if (m_eAccessMode == TABRead || m_eTableType != TABTableNative)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "Operation not supported on read-only files or on non-native table.");
+                 "Operation not supported on read-only files or "
+                 "on non-native table.");
         return -1;
     }
 
     if( iField < 0 || iField >= m_numFields )
     {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Invalid field index: %d", iField);
+        CPLError(CE_Failure, CPLE_IllegalArg, "Invalid field index: %d",
+                 iField);
         return -1;
     }
 
-    /* If no records have been written, then just remove from the field */
-    /* definition array */
+    // If no records have been written, then just remove from the field
+    // definition array.
     if( m_numRecords <= 0 )
     {
-        if( iField < m_numFields-1 )
+        if( iField < m_numFields - 1 )
         {
             memmove(m_pasFieldDef + iField, m_pasFieldDef + iField + 1,
-                    (m_numFields-1-iField)*sizeof(TABDATFieldDef));
+                    (m_numFields - 1 - iField) * sizeof(TABDATFieldDef));
         }
-        m_numFields --;
+        m_numFields--;
         return 0;
     }
 
     if( m_numFields == 1 )
     {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Cannot delete the single remaining field.");
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "Cannot delete the single remaining field.");
         return -1;
     }
 
-    /* Otherwise we need to do a temporary file */
+    // Otherwise we need to do a temporary file.
     TABDATFile oTempFile;
     CPLString osOriginalFile(m_pszFname);
     CPLString osTmpFile(m_pszFname);
     osTmpFile += ".tmp";
-    if( oTempFile.Open( osTmpFile.c_str(), TABWrite ) != 0 )
+    if( oTempFile.Open(osTmpFile.c_str(), TABWrite) != 0 )
         return -1;
 
-    int i;
-    /* Create field structure */
+    // Create field structure.
     int nRecordSizeBefore = 0;
     int nRecordSizeAfter = 0;
-    for(i = 0; i < m_numFields; i++)
+    for( int i = 0; i < m_numFields; i++ )
     {
         if( i != iField )
         {
-            if( i < iField ) nRecordSizeBefore += m_pasFieldDef[i].byLength;
-            else if( i > iField ) nRecordSizeAfter += m_pasFieldDef[i].byLength;
-            oTempFile.AddField(m_pasFieldDef[i].szName,
-                                m_pasFieldDef[i].eTABType,
-                                m_pasFieldDef[i].byLength,
-                                m_pasFieldDef[i].byDecimals);
+            if( i < iField )
+                nRecordSizeBefore += m_pasFieldDef[i].byLength;
+            else if( i > iField )
+                nRecordSizeAfter += m_pasFieldDef[i].byLength;
+            oTempFile.AddField(
+                m_pasFieldDef[i].szName, m_pasFieldDef[i].eTABType,
+                m_pasFieldDef[i].byLength, m_pasFieldDef[i].byDecimals);
         }
     }
 
-    CPLAssert(nRecordSizeBefore + m_pasFieldDef[iField].byLength + nRecordSizeAfter == m_nRecordSize - 1);
+    CPLAssert(nRecordSizeBefore + m_pasFieldDef[iField].byLength +
+                  nRecordSizeAfter ==
+              m_nRecordSize - 1);
 
-    GByte* pabyRecord = (GByte*)CPLMalloc(m_nRecordSize);
+    GByte *pabyRecord = static_cast<GByte *>(CPLMalloc(m_nRecordSize));
 
-    /* Copy records */
+    // Copy records.
     for(int j = 0; j < m_numRecords; j++)
     {
-        if( GetRecordBlock(1+j) == NULL ||
-            oTempFile.GetRecordBlock(1+j) == NULL )
+        if( GetRecordBlock(1 + j) == NULL ||
+            oTempFile.GetRecordBlock(1 + j) == NULL )
         {
             CPLFree(pabyRecord);
             oTempFile.Close();
@@ -1116,32 +1012,32 @@ int TABDATFile::DeleteField( int iField )
 
     CPLFree(pabyRecord);
 
-    /* Close temporary file */
+    // Close temporary file.
     oTempFile.Close();
 
-    /* Backup field definitions as we will need to set the TABFieldType */
-    TABDATFieldDef* pasFieldDefTmp = (TABDATFieldDef*)CPLMalloc(m_numFields*sizeof(TABDATFieldDef));
-    memcpy(pasFieldDefTmp, m_pasFieldDef, m_numFields*sizeof(TABDATFieldDef));
+    // Backup field definitions as we will need to set the TABFieldType.
+    TABDATFieldDef *pasFieldDefTmp = static_cast<TABDATFieldDef *>(
+        CPLMalloc(m_numFields * sizeof(TABDATFieldDef)));
+    memcpy(pasFieldDefTmp, m_pasFieldDef, m_numFields * sizeof(TABDATFieldDef));
 
-    /* Close ourselves */
     Close();
 
-    /* Move temporary file as main .data file and reopen it */
+    // Move temporary file as main .data file and reopen it.
     VSIUnlink(osOriginalFile);
     VSIRename(osTmpFile, osOriginalFile);
-    if( Open( osOriginalFile, TABReadWrite ) < 0 )
+    if( Open(osOriginalFile, TABReadWrite) < 0 )
     {
         CPLFree(pasFieldDefTmp);
         return -1;
     }
 
-    /* Restore saved TABFieldType */
-    for(i = 0; i < m_numFields; i++)
+    // Restore saved TABFieldType.
+    for( int i = 0; i < m_numFields; i++ )
     {
         if( i < iField )
             m_pasFieldDef[i].eTABType = pasFieldDefTmp[i].eTABType;
         else
-            m_pasFieldDef[i].eTABType = pasFieldDefTmp[i+1].eTABType;
+            m_pasFieldDef[i].eTABType = pasFieldDefTmp[i + 1].eTABType;
     }
     CPLFree(pasFieldDefTmp);
 
@@ -1152,12 +1048,13 @@ int TABDATFile::DeleteField( int iField )
 /*                           ReorderFields()                            */
 /************************************************************************/
 
-int TABDATFile::ReorderFields( int* panMap )
+int TABDATFile::ReorderFields( int *panMap )
 {
     if (m_eAccessMode == TABRead || m_eTableType != TABTableNative)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "Operation not supported on read-only files or on non-native table.");
+                 "Operation not supported on read-only files or "
+                 "on non-native table.");
         return -1;
     }
 
@@ -1168,12 +1065,14 @@ int TABDATFile::ReorderFields( int* panMap )
     if (eErr != OGRERR_NONE)
         return -1;
 
-    /* If no records have been written, then just reorder the field */
-    /* definition array */
+    // If no records have been written, then just reorder the field
+    // definition array.
     if( m_numRecords <= 0 )
     {
-        TABDATFieldDef* pasFieldDefTmp = (TABDATFieldDef*)CPLMalloc(m_numFields*sizeof(TABDATFieldDef));
-        memcpy(pasFieldDefTmp, m_pasFieldDef, m_numFields*sizeof(TABDATFieldDef));
+        TABDATFieldDef *pasFieldDefTmp = static_cast<TABDATFieldDef *>(
+            CPLMalloc(m_numFields * sizeof(TABDATFieldDef)));
+        memcpy(pasFieldDefTmp, m_pasFieldDef,
+               m_numFields * sizeof(TABDATFieldDef));
         for(int i = 0; i < m_numFields; i++)
         {
             memcpy(m_pasFieldDef + i, pasFieldDefTmp + panMap[i],
@@ -1190,32 +1089,33 @@ int TABDATFile::ReorderFields( int* panMap )
     CPLString osOriginalFile(m_pszFname);
     CPLString osTmpFile(m_pszFname);
     osTmpFile += ".tmp";
-    if( oTempFile.Open( osTmpFile.c_str(), TABWrite ) != 0 )
+    if( oTempFile.Open(osTmpFile.c_str(), TABWrite) != 0 )
         return -1;
 
-    int i;
-    /* Create field structure */
-    int* panOldOffset = (int*)CPLMalloc(m_numFields * sizeof(int));
-    for(i = 0; i < m_numFields; i++)
+    // Create field structure.
+    int *panOldOffset =
+        static_cast<int *>(CPLMalloc(m_numFields * sizeof(int)));
+    for( int i = 0; i < m_numFields; i++ )
     {
         int iBefore = panMap[i];
         if( i == 0 )
             panOldOffset[i] = 0;
         else
-            panOldOffset[i] = panOldOffset[i-1] + m_pasFieldDef[i-1].byLength;
+            panOldOffset[i] =
+                panOldOffset[i - 1] + m_pasFieldDef[i - 1].byLength;
         oTempFile.AddField(m_pasFieldDef[iBefore].szName,
                             m_pasFieldDef[iBefore].eTABType,
                             m_pasFieldDef[iBefore].byLength,
                             m_pasFieldDef[iBefore].byDecimals);
     }
 
-    GByte* pabyRecord = (GByte*)CPLMalloc(m_nRecordSize);
+    GByte *pabyRecord = static_cast<GByte *>(CPLMalloc(m_nRecordSize));
 
-    /* Copy records */
+    // Copy records.
     for(int j = 0; j < m_numRecords; j++)
     {
-        if( GetRecordBlock(1+j) == NULL ||
-            oTempFile.GetRecordBlock(1+j) == NULL )
+        if( GetRecordBlock(1 + j) == NULL ||
+            oTempFile.GetRecordBlock(1 + j) == NULL )
         {
             CPLFree(pabyRecord);
             CPLFree(panOldOffset);
@@ -1229,7 +1129,7 @@ int TABDATFile::ReorderFields( int* panMap )
         }
         else
         {
-            if( m_poRecordBlock->ReadBytes(m_nRecordSize-1, pabyRecord) != 0 )
+            if( m_poRecordBlock->ReadBytes(m_nRecordSize - 1, pabyRecord) != 0 )
             {
                 CPLFree(pabyRecord);
                 CPLFree(panOldOffset);
@@ -1237,11 +1137,12 @@ int TABDATFile::ReorderFields( int* panMap )
                 VSIUnlink(osTmpFile);
                 return -1;
             }
-            for(i = 0; i < m_numFields; i++)
+            for( int i = 0; i < m_numFields; i++ )
             {
                 int iBefore = panMap[i];
                 if( oTempFile.m_poRecordBlock->WriteBytes(
-                        m_pasFieldDef[iBefore].byLength, pabyRecord + panOldOffset[iBefore]) != 0 )
+                        m_pasFieldDef[iBefore].byLength,
+                        pabyRecord + panOldOffset[iBefore]) != 0 )
                 {
                     CPLFree(pabyRecord);
                     CPLFree(panOldOffset);
@@ -1258,27 +1159,27 @@ int TABDATFile::ReorderFields( int* panMap )
     CPLFree(pabyRecord);
     CPLFree(panOldOffset);
 
-    /* Close temporary file */
     oTempFile.Close();
 
-    /* Backup field definitions as we will need to set the TABFieldType */
-    TABDATFieldDef* pasFieldDefTmp = (TABDATFieldDef*)CPLMalloc(m_numFields*sizeof(TABDATFieldDef));
-    memcpy(pasFieldDefTmp, m_pasFieldDef, m_numFields*sizeof(TABDATFieldDef));
+    // Backup field definitions as we will need to set the TABFieldType.
+    TABDATFieldDef *pasFieldDefTmp = static_cast<TABDATFieldDef *>(
+        CPLMalloc(m_numFields * sizeof(TABDATFieldDef)));
+    memcpy(pasFieldDefTmp, m_pasFieldDef, m_numFields * sizeof(TABDATFieldDef));
 
-    /* Close ourselves */
+    // Close ourselves.
     Close();
 
-    /* Move temporary file as main .data file and reopen it */
+    // Move temporary file as main .data file and reopen it.
     VSIUnlink(osOriginalFile);
     VSIRename(osTmpFile, osOriginalFile);
-    if( Open( osOriginalFile, TABReadWrite ) < 0 )
+    if( Open(osOriginalFile, TABReadWrite) < 0 )
     {
         CPLFree(pasFieldDefTmp);
         return -1;
     }
 
-    /* Restore saved TABFieldType */
-    for(i = 0; i < m_numFields; i++)
+    // Restore saved TABFieldType.
+    for( int i = 0; i < m_numFields; i++ )
     {
         int iBefore = panMap[i];
         m_pasFieldDef[i].eTABType = pasFieldDefTmp[iBefore].eTABType;
@@ -1292,35 +1193,40 @@ int TABDATFile::ReorderFields( int* panMap )
 /*                           AlterFieldDefn()                           */
 /************************************************************************/
 
-int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags )
+int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn *poNewFieldDefn,
+                                int nFlags )
 {
     if (m_eAccessMode == TABRead || m_eTableType != TABTableNative)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "Operation not supported on read-only files or on non-native table.");
+                 "Operation not supported on read-only files or "
+                 "on non-native table.");
         return -1;
     }
 
     if( iField < 0 || iField >= m_numFields )
     {
-        CPLError(CE_Failure, CPLE_IllegalArg, "Invalid field index: %d", iField);
+        CPLError(CE_Failure, CPLE_IllegalArg,
+                 "Invalid field index: %d", iField);
         return -1;
     }
 
-    TABFieldType        eTABType = m_pasFieldDef[iField].eTABType;
-    int                 nWidth = m_pasFieldDef[iField].byLength ;
-    int                 nPrecision = m_pasFieldDef[iField].byDecimals ;
-    int                 nWidthDummy;
-    int                 nPrecisionDummy;
-    if( (nFlags & ALTER_TYPE_FLAG) )
+    TABFieldType eTABType = m_pasFieldDef[iField].eTABType;
+    int nWidth = m_pasFieldDef[iField].byLength;
+    int nPrecision = m_pasFieldDef[iField].byDecimals;
+    int nWidthDummy = 0;
+    int nPrecisionDummy = 0;
+    if( nFlags & ALTER_TYPE_FLAG )
     {
-        if( IMapInfoFile::GetTABType( poNewFieldDefn, &eTABType, &nWidthDummy, &nPrecisionDummy ) < 0 )
+        if( IMapInfoFile::GetTABType(poNewFieldDefn, &eTABType, &nWidthDummy,
+                                     &nPrecisionDummy) < 0 )
             return -1;
     }
-    if( (nFlags & ALTER_WIDTH_PRECISION_FLAG) )
+    if( nFlags & ALTER_WIDTH_PRECISION_FLAG )
     {
         TABFieldType eTABTypeDummy;
-        if( IMapInfoFile::GetTABType( poNewFieldDefn, &eTABTypeDummy, &nWidth, &nPrecision ) < 0 )
+        if( IMapInfoFile::GetTABType(poNewFieldDefn, &eTABTypeDummy, &nWidth,
+                                     &nPrecision) < 0 )
             return -1;
     }
 
@@ -1329,8 +1235,8 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
     {
         if ( eTABType != TABFChar )
         {
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "Can only convert to OFTString");
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Can only convert to OFTString");
             return -1;
         }
         if( (nFlags & ALTER_WIDTH_PRECISION_FLAG) == 0 )
@@ -1341,17 +1247,19 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
     {
         if( eTABType != TABFChar && nWidth != m_pasFieldDef[iField].byLength )
         {
-            CPLError( CE_Failure, CPLE_NotSupported,
-                      "Resizing only supported on String fields");
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Resizing only supported on String fields");
             return -1;
         }
     }
 
     if (nFlags & ALTER_NAME_FLAG)
     {
-        strncpy(m_pasFieldDef[iField].szName, poNewFieldDefn->GetNameRef(), 10);
-        m_pasFieldDef[iField].szName[10] = '\0';
-        /* If renaming is the only operation, then nothing more to do */
+        strncpy(m_pasFieldDef[iField].szName, poNewFieldDefn->GetNameRef(),
+                sizeof(m_pasFieldDef[iField].szName) - 1);
+        m_pasFieldDef[iField].szName[sizeof(m_pasFieldDef[iField].szName) - 1] =
+            '\0';
+        // If renaming is the only operation, then nothing more to do.
         if( nFlags == ALTER_NAME_FLAG )
         {
             m_bUpdated = TRUE;
@@ -1373,22 +1281,21 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
         }
         if (nFlags & ALTER_WIDTH_PRECISION_FLAG)
         {
-            m_pasFieldDef[iField].byLength = (GByte)nWidth;
-            m_pasFieldDef[iField].byDecimals = (GByte)nPrecision;
+            m_pasFieldDef[iField].byLength = static_cast<GByte>(nWidth);
+            m_pasFieldDef[iField].byDecimals = static_cast<GByte>(nPrecision);
         }
         return 0;
     }
 
-    /* Otherwise we need to do a temporary file */
+    // Otherwise we need to do a temporary file.
     TABDATFile oTempFile;
     CPLString osOriginalFile(m_pszFname);
     CPLString osTmpFile(m_pszFname);
     osTmpFile += ".tmp";
-    if( oTempFile.Open( osTmpFile.c_str(), TABWrite ) != 0 )
+    if( oTempFile.Open(osTmpFile.c_str(), TABWrite) != 0 )
         return -1;
 
-    int i;
-    /* Create field structure */
+    // Create field structure.
     int nRecordSizeBefore = 0;
     int nRecordSizeAfter = 0;
     TABDATFieldDef sFieldDef;
@@ -1398,16 +1305,16 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
                                  nWidth,
                                  nPrecision);
 
-    for(i = 0; i < m_numFields; i++)
+    for( int i = 0; i < m_numFields; i++ )
     {
         if( i != iField )
         {
             if( i < iField ) nRecordSizeBefore += m_pasFieldDef[i].byLength;
             else if( i > iField ) nRecordSizeAfter += m_pasFieldDef[i].byLength;
             oTempFile.AddField(m_pasFieldDef[i].szName,
-                                m_pasFieldDef[i].eTABType,
-                                m_pasFieldDef[i].byLength,
-                                m_pasFieldDef[i].byDecimals);
+                               m_pasFieldDef[i].eTABType,
+                               m_pasFieldDef[i].byLength,
+                               m_pasFieldDef[i].byDecimals);
         }
         else
         {
@@ -1418,14 +1325,14 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
         }
     }
 
-    GByte* pabyRecord = (GByte*)CPLMalloc(m_nRecordSize);
-    char* pabyNewField = (char*)CPLMalloc(sFieldDef.byLength + 1);
+    GByte *pabyRecord = static_cast<GByte *>(CPLMalloc(m_nRecordSize));
+    char *pabyNewField = static_cast<char *>(CPLMalloc(sFieldDef.byLength + 1));
 
-    /* Copy records */
+    // Copy records.
     for(int j = 0; j < m_numRecords; j++)
     {
-        if( GetRecordBlock(1+j) == NULL ||
-            oTempFile.GetRecordBlock(1+j) == NULL )
+        if( GetRecordBlock(1 + j) == NULL ||
+            oTempFile.GetRecordBlock(1 + j) == NULL )
         {
             CPLFree(pabyRecord);
             CPLFree(pabyNewField);
@@ -1453,45 +1360,63 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
             memset(pabyNewField, 0, sFieldDef.byLength + 1);
             if( m_pasFieldDef[iField].eTABType == TABFChar )
             {
-                strncpy(pabyNewField, ReadCharField(m_pasFieldDef[iField].byLength), sFieldDef.byLength);
+                strncpy(pabyNewField,
+                        ReadCharField(m_pasFieldDef[iField].byLength),
+                        sFieldDef.byLength);
             }
             else if( m_pasFieldDef[iField].eTABType == TABFInteger )
             {
-                snprintf(pabyNewField, sFieldDef.byLength, "%d", ReadIntegerField(m_pasFieldDef[iField].byLength));
+                snprintf(pabyNewField, sFieldDef.byLength, "%d",
+                         ReadIntegerField(m_pasFieldDef[iField].byLength));
             }
             else if( m_pasFieldDef[iField].eTABType == TABFSmallInt )
             {
-                snprintf(pabyNewField, sFieldDef.byLength, "%d", ReadSmallIntField(m_pasFieldDef[iField].byLength));
+                snprintf(pabyNewField, sFieldDef.byLength, "%d",
+                         ReadSmallIntField(m_pasFieldDef[iField].byLength));
             }
             else if( m_pasFieldDef[iField].eTABType == TABFFloat )
             {
-                CPLsnprintf(pabyNewField, sFieldDef.byLength, "%.18f", ReadFloatField(m_pasFieldDef[iField].byLength));
+                CPLsnprintf(pabyNewField, sFieldDef.byLength, "%.18f",
+                            ReadFloatField(m_pasFieldDef[iField].byLength));
             }
             else if( m_pasFieldDef[iField].eTABType == TABFDecimal )
             {
-                CPLsnprintf(pabyNewField, sFieldDef.byLength, "%.18f", ReadFloatField(m_pasFieldDef[iField].byLength));
+                CPLsnprintf(pabyNewField, sFieldDef.byLength, "%.18f",
+                            ReadFloatField(m_pasFieldDef[iField].byLength));
             }
             else if( m_pasFieldDef[iField].eTABType == TABFLogical )
             {
-                strncpy(pabyNewField, ReadLogicalField(m_pasFieldDef[iField].byLength), sFieldDef.byLength);
+                strncpy(pabyNewField,
+                        ReadLogicalField(m_pasFieldDef[iField].byLength),
+                        sFieldDef.byLength);
             }
             else if( m_pasFieldDef[iField].eTABType == TABFDate )
             {
-                strncpy(pabyNewField, ReadDateField(m_pasFieldDef[iField].byLength), sFieldDef.byLength);
+                strncpy(pabyNewField,
+                        ReadDateField(m_pasFieldDef[iField].byLength),
+                        sFieldDef.byLength);
             }
             else if( m_pasFieldDef[iField].eTABType == TABFTime )
             {
-                strncpy(pabyNewField, ReadTimeField(m_pasFieldDef[iField].byLength), sFieldDef.byLength);
+                strncpy(pabyNewField,
+                        ReadTimeField(m_pasFieldDef[iField].byLength),
+                        sFieldDef.byLength);
             }
             else if( m_pasFieldDef[iField].eTABType == TABFDateTime )
             {
-                strncpy(pabyNewField, ReadDateTimeField(m_pasFieldDef[iField].byLength), sFieldDef.byLength);
+                strncpy(pabyNewField,
+                        ReadDateTimeField(m_pasFieldDef[iField].byLength),
+                        sFieldDef.byLength);
             }
 
-            if( oTempFile.m_poRecordBlock->WriteBytes(sFieldDef.byLength, (GByte*)pabyNewField) != 0 ||
+            if( oTempFile.m_poRecordBlock->WriteBytes(
+                    sFieldDef.byLength,
+                    reinterpret_cast<GByte*>(pabyNewField)) != 0 ||
                 (nRecordSizeAfter > 0 &&
-                (m_poRecordBlock->ReadBytes(nRecordSizeAfter, pabyRecord) != 0 ||
-                 oTempFile.m_poRecordBlock->WriteBytes(nRecordSizeAfter, pabyRecord) != 0)) )
+                (m_poRecordBlock->ReadBytes(nRecordSizeAfter,
+                                            pabyRecord) != 0 ||
+                 oTempFile.m_poRecordBlock->WriteBytes(nRecordSizeAfter,
+                                                       pabyRecord) != 0)) )
             {
                 CPLFree(pabyRecord);
                 CPLFree(pabyNewField);
@@ -1506,27 +1431,26 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
     CPLFree(pabyRecord);
     CPLFree(pabyNewField);
 
-    /* Close temporary file */
     oTempFile.Close();
 
-    /* Backup field definitions as we will need to set the TABFieldType */
-    TABDATFieldDef* pasFieldDefTmp = (TABDATFieldDef*)CPLMalloc(m_numFields*sizeof(TABDATFieldDef));
-    memcpy(pasFieldDefTmp, m_pasFieldDef, m_numFields*sizeof(TABDATFieldDef));
+    // Backup field definitions as we will need to set the TABFieldType.
+    TABDATFieldDef *pasFieldDefTmp = static_cast<TABDATFieldDef *>(
+        CPLMalloc(m_numFields * sizeof(TABDATFieldDef)));
+    memcpy(pasFieldDefTmp, m_pasFieldDef, m_numFields * sizeof(TABDATFieldDef));
 
-    /* Close ourselves */
     Close();
 
-    /* Move temporary file as main .data file and reopen it */
+    // Move temporary file as main .data file and reopen it.
     VSIUnlink(osOriginalFile);
     VSIRename(osTmpFile, osOriginalFile);
-    if( Open( osOriginalFile, TABReadWrite ) < 0 )
+    if( Open(osOriginalFile, TABReadWrite) < 0 )
     {
         CPLFree(pasFieldDefTmp);
         return -1;
     }
 
-    /* Restore saved TABFieldType */
-    for(i = 0; i < m_numFields; i++)
+    // Restore saved TABFieldType.
+    for( int i = 0; i < m_numFields; i++ )
     {
         if( i != iField )
             m_pasFieldDef[i].eTABType = pasFieldDefTmp[i].eTABType;
@@ -1538,7 +1462,6 @@ int TABDATFile::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nF
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABDATFile::GetFieldType()
  *
@@ -1623,7 +1546,8 @@ const char *TABDATFile::ReadCharField(int nWidth)
         return "";
     }
 
-    if (m_poRecordBlock->ReadBytes(nWidth, (GByte*)m_szBuffer) != 0)
+    if (m_poRecordBlock->ReadBytes(nWidth,
+                                   reinterpret_cast<GByte *>(m_szBuffer)) != 0)
         return "";
 
     m_szBuffer[nWidth] = '\0';
@@ -1632,8 +1556,8 @@ const char *TABDATFile::ReadCharField(int nWidth)
     // with spaces... get rid of the trailing spaces.
     if (m_eTableType == TABTableDBF)
     {
-        int nLen = static_cast<int>(strlen(m_szBuffer))-1;
-        while(nLen>=0 && m_szBuffer[nLen] == ' ')
+        int nLen = static_cast<int>(strlen(m_szBuffer)) - 1;
+        while(nLen >= 0 && m_szBuffer[nLen] == ' ')
             m_szBuffer[nLen--] = '\0';
     }
 
@@ -1695,7 +1619,7 @@ GInt16 TABDATFile::ReadSmallIntField(int nWidth)
     }
 
     if (m_eTableType == TABTableDBF)
-        return (GInt16)atoi(ReadCharField(nWidth));
+        return static_cast<GInt16>(atoi(ReadCharField(nWidth)));
 
     return m_poRecordBlock->ReadInt16();
 }
@@ -1743,10 +1667,8 @@ double TABDATFile::ReadFloatField(int nWidth)
  *
  * CPLError() will have been called if something fails.
  **********************************************************************/
-const char *TABDATFile::ReadLogicalField(int nWidth)
+const char *TABDATFile::ReadLogicalField( int nWidth )
 {
-    GByte bValue;
-
     // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
@@ -1759,18 +1681,19 @@ const char *TABDATFile::ReadLogicalField(int nWidth)
         return "";
     }
 
+    bool bValue = false;
     if (m_eTableType == TABTableDBF)
     {
         const char *pszVal = ReadCharField(nWidth);
-        bValue = (pszVal && strchr("1YyTt", pszVal[0]) != NULL);
+        bValue = pszVal && strchr("1YyTt", pszVal[0]) != NULL;
     }
     else
     {
         // In Native tables, we are guaranteed it is 1 byte with 0/1 value
-        bValue =  m_poRecordBlock->ReadByte();
+        bValue = CPL_TO_BOOL(m_poRecordBlock->ReadByte());
     }
 
-    return bValue? "T":"F";
+    return bValue ? "T" : "F";
 }
 
 /**********************************************************************
@@ -1792,13 +1715,16 @@ const char *TABDATFile::ReadLogicalField(int nWidth)
  **********************************************************************/
 const char *TABDATFile::ReadDateField(int nWidth)
 {
-    int nDay, nMonth, nYear, status;
-    nDay = nMonth = nYear = 0;
+    int nDay = 0;
+    int nMonth = 0;
+    int nYear = 0;
+    int status = ReadDateField(nWidth, &nYear, &nMonth, &nDay);
 
-    if ((status = ReadDateField(nWidth, &nYear, &nMonth, &nDay)) == -1)
+    if ( status == -1)
        return "";
 
-    snprintf(m_szBuffer, sizeof(m_szBuffer), "%4.4d%2.2d%2.2d", nYear, nMonth, nDay);
+    snprintf(m_szBuffer, sizeof(m_szBuffer), "%4.4d%2.2d%2.2d", nYear, nMonth,
+             nDay);
 
     return m_szBuffer;
 }
@@ -1821,17 +1747,17 @@ int TABDATFile::ReadDateField(int nWidth, int *nYear, int *nMonth, int *nDay)
     // stored in YYYYMMDD format according to DBF specs.
     if (m_eTableType == TABTableDBF)
     {
-       strcpy(m_szBuffer,ReadCharField(nWidth));
-       sscanf(m_szBuffer, "%4d%2d%2d", nYear, nMonth, nDay);
+        strcpy(m_szBuffer, ReadCharField(nWidth));
+        sscanf(m_szBuffer, "%4d%2d%2d", nYear, nMonth, nDay);
     }
     else
     {
-       *nYear  = m_poRecordBlock->ReadInt16();
-       *nMonth = m_poRecordBlock->ReadByte();
-       *nDay   = m_poRecordBlock->ReadByte();
+        *nYear = m_poRecordBlock->ReadInt16();
+        *nMonth = m_poRecordBlock->ReadByte();
+        *nDay = m_poRecordBlock->ReadByte();
     }
 
-    if (CPLGetLastErrorNo() != 0 || (*nYear==0 && *nMonth==0 && *nDay==0))
+    if (CPLGetLastErrorNo() != 0 || (*nYear == 0 && *nMonth == 0 && *nDay == 0))
        return -1;
 
     return 0;
@@ -1856,13 +1782,17 @@ int TABDATFile::ReadDateField(int nWidth, int *nYear, int *nMonth, int *nDay)
  **********************************************************************/
 const char *TABDATFile::ReadTimeField(int nWidth)
 {
-    int nHour, nMinute, nSecond, nMS, status;
-    nHour = nMinute = nSecond = nMS = 0;
+    int nHour = 0;
+    int nMinute = 0;
+    int nSecond = 0;
+    int nMS = 0;
+    int status = ReadTimeField(nWidth, &nHour, &nMinute, &nSecond, &nMS);
 
-    if ((status = ReadTimeField(nWidth, &nHour, &nMinute, &nSecond, &nMS)) == -1)
+    if (status == -1)
        return "";
 
-    snprintf(m_szBuffer, sizeof(m_szBuffer), "%2.2d%2.2d%2.2d%3.3d", nHour, nMinute, nSecond, nMS);
+    snprintf(m_szBuffer, sizeof(m_szBuffer), "%2.2d%2.2d%2.2d%3.3d", nHour,
+             nMinute, nSecond, nMS);
 
     return m_szBuffer;
 }
@@ -1887,9 +1817,8 @@ int TABDATFile::ReadTimeField(int nWidth, int *nHour, int *nMinute,
     // HHMMSSMMM format according to DBF specs.
     if (m_eTableType == TABTableDBF)
     {
-       strcpy(m_szBuffer,ReadCharField(nWidth));
-       sscanf(m_szBuffer,"%2d%2d%2d%3d",
-              nHour, nMinute, nSecond, nMS);
+        strcpy(m_szBuffer, ReadCharField(nWidth));
+        sscanf(m_szBuffer, "%2d%2d%2d%3d", nHour, nMinute, nSecond, nMS);
     }
     else
     {
@@ -1897,13 +1826,13 @@ int TABDATFile::ReadTimeField(int nWidth, int *nHour, int *nMinute,
     }
 
     // nS is set to -1 when the value is 'not set'
-    if (CPLGetLastErrorNo() != 0 || nS < 0 || (nS>86400000))
-       return -1;
+    if (CPLGetLastErrorNo() != 0 || nS < 0 || (nS > 86400000))
+        return -1;
 
-    *nHour = int(nS/3600000);
-    *nMinute  = int((nS/1000 - *nHour*3600)/60);
-    *nSecond  = int(nS/1000 - *nHour*3600 - *nMinute*60);
-    *nMS   = int(nS-*nHour*3600000-*nMinute*60000-*nSecond*1000);
+    *nHour = int(nS / 3600000);
+    *nMinute = int((nS / 1000 - *nHour * 3600) / 60);
+    *nSecond = int(nS / 1000 - *nHour * 3600 - *nMinute * 60);
+    *nMS = int(nS - *nHour * 3600000 - *nMinute * 60000 - *nSecond * 1000);
 
     return 0;
 }
@@ -1928,21 +1857,29 @@ int TABDATFile::ReadTimeField(int nWidth, int *nHour, int *nMinute,
  **********************************************************************/
 const char *TABDATFile::ReadDateTimeField(int nWidth)
 {
-    int nDay, nMonth, nYear, nHour, nMinute, nSecond, nMS, status;
-    nDay = nMonth = nYear = nHour = nMinute = nSecond = nMS = 0;
-
-    if ((status = ReadDateTimeField(nWidth, &nYear, &nMonth, &nDay, &nHour,
-                                    &nMinute, &nSecond, &nMS)) == -1)
+    int nDay = 0;
+    int nMonth = 0;
+    int nYear = 0;
+    int nHour = 0;
+    int nMinute = 0;
+    int nSecond = 0;
+    int nMS = 0;
+    int status = ReadDateTimeField(nWidth, &nYear, &nMonth, &nDay, &nHour,
+                                   &nMinute, &nSecond, &nMS);
+
+    if ( status == -1)
        return "";
 
-    snprintf(m_szBuffer, sizeof(m_szBuffer), "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d%3.3d",
-            nYear, nMonth, nDay, nHour, nMinute, nSecond, nMS);
+    snprintf(m_szBuffer, sizeof(m_szBuffer),
+             "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d%3.3d", nYear, nMonth, nDay, nHour,
+             nMinute, nSecond, nMS);
 
     return m_szBuffer;
 }
 
-int TABDATFile::ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay,
-                                 int *nHour, int *nMinute, int *nSecond, int *nMS)
+int TABDATFile::ReadDateTimeField(int nWidth, int *nYear, int *nMonth,
+                                  int *nDay, int *nHour, int *nMinute,
+                                  int *nSecond, int *nMS)
 {
     GInt32 nS = 0;
     // If current record has been deleted, then return an acceptable
@@ -1961,26 +1898,26 @@ int TABDATFile::ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay
     // YYYYMMDD format according to DBF specs.
     if (m_eTableType == TABTableDBF)
     {
-       strcpy(m_szBuffer,ReadCharField(nWidth));
-       sscanf(m_szBuffer, "%4d%2d%2d%2d%2d%2d%3d",
-              nYear, nMonth, nDay, nHour, nMinute, nSecond, nMS);
+        strcpy(m_szBuffer, ReadCharField(nWidth));
+        sscanf(m_szBuffer, "%4d%2d%2d%2d%2d%2d%3d", nYear, nMonth, nDay, nHour,
+               nMinute, nSecond, nMS);
     }
     else
     {
-       *nYear  = m_poRecordBlock->ReadInt16();
-       *nMonth = m_poRecordBlock->ReadByte();
-       *nDay   = m_poRecordBlock->ReadByte();
-       nS      = m_poRecordBlock->ReadInt32();
+        *nYear = m_poRecordBlock->ReadInt16();
+        *nMonth = m_poRecordBlock->ReadByte();
+        *nDay = m_poRecordBlock->ReadByte();
+        nS = m_poRecordBlock->ReadInt32();
     }
 
     if (CPLGetLastErrorNo() != 0 ||
-        (*nYear==0 && *nMonth==0 && *nDay==0) || (nS>86400000))
+        (*nYear == 0 && *nMonth == 0 && *nDay == 0) || (nS > 86400000))
         return -1;
 
-    *nHour = int(nS/3600000);
-    *nMinute  = int((nS/1000 - *nHour*3600)/60);
-    *nSecond  = int(nS/1000 - *nHour*3600 - *nMinute*60);
-    *nMS   = int(nS-*nHour*3600000-*nMinute*60000-*nSecond*1000);
+    *nHour = int(nS / 3600000);
+    *nMinute = int((nS / 1000 - *nHour * 3600) / 60);
+    *nSecond = int(nS / 1000 - *nHour * 3600 - *nMinute * 60);
+    *nMS = int(nS - *nHour * 3600000 - *nMinute * 60000 - *nSecond * 1000);
 
     return 0;
 }
@@ -2002,19 +1939,16 @@ int TABDATFile::ReadDateTimeField(int nWidth, int *nYear, int *nMonth, int *nDay
  **********************************************************************/
 double TABDATFile::ReadDecimalField(int nWidth)
 {
-    const char *pszVal;
-
     // If current record has been deleted, then return an acceptable
     // default value.
     if (m_bCurRecordDeletedFlag)
         return 0.0;
 
-    pszVal = ReadCharField(nWidth);
+    const char *pszVal = ReadCharField(nWidth);
 
     return CPLAtof(pszVal);
 }
 
-
 /**********************************************************************
  *                   TABDATFile::WriteCharField()
  *
@@ -2034,7 +1968,8 @@ int TABDATFile::WriteCharField(const char *pszStr, int nWidth,
 {
     if (m_poRecordBlock == NULL)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
             "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
@@ -2052,11 +1987,12 @@ int TABDATFile::WriteCharField(const char *pszStr, int nWidth,
     // be padded with zeros if source string is shorter than specified
     // field width.
     //
-    int nLen = static_cast<int>(strlen(pszStr));
-    nLen = MIN(nLen, nWidth);
+    const int nLen = std::min(static_cast<int>(strlen(pszStr)), nWidth);
 
-    if ((nLen>0 && m_poRecordBlock->WriteBytes(nLen, (GByte*)pszStr) != 0) ||
-        (nWidth-nLen > 0 && m_poRecordBlock->WriteZeros(nWidth-nLen)!=0) )
+    if((nLen > 0 &&
+        m_poRecordBlock->WriteBytes(
+            nLen, reinterpret_cast<const GByte *>(pszStr)) != 0) ||
+       (nWidth - nLen > 0 && m_poRecordBlock->WriteZeros(nWidth - nLen) != 0))
         return -1;
 
     // Update Index
@@ -2083,7 +2019,8 @@ int TABDATFile::WriteIntegerField(GInt32 nValue,
 {
     if (m_poRecordBlock == NULL)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
             "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
@@ -2112,7 +2049,8 @@ int TABDATFile::WriteSmallIntField(GInt16 nValue,
 {
     if (m_poRecordBlock == NULL)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
             "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
@@ -2136,12 +2074,13 @@ int TABDATFile::WriteSmallIntField(GInt16 nValue,
  *
  * CPLError() will have been called if something fails.
  **********************************************************************/
-int TABDATFile::WriteFloatField(double dValue,
-                                TABINDFile *poINDFile, int nIndexNo)
+int TABDATFile::WriteFloatField( double dValue,
+                                 TABINDFile *poINDFile, int nIndexNo )
 {
     if (m_poRecordBlock == NULL)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
             "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
@@ -2171,24 +2110,21 @@ int TABDATFile::WriteFloatField(double dValue,
 int TABDATFile::WriteLogicalField(const char *pszValue,
                                   TABINDFile *poINDFile, int nIndexNo)
 {
-    GByte bValue;
-
     if (m_poRecordBlock == NULL)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
             "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
 
-    if (STARTS_WITH_CI(pszValue, "T"))
-        bValue = 1;
-    else
-        bValue = 0;
+    // TODO(schwehr): bValue should be a bool.
+    const GByte bValue = STARTS_WITH_CI(pszValue, "T") ? 1 : 0;
 
     // Update Index
     if (poINDFile && nIndexNo > 0)
     {
-        GByte *pKey = poINDFile->BuildKey(nIndexNo, (int)bValue);
+        GByte *pKey = poINDFile->BuildKey(nIndexNo, static_cast<int>(bValue));
         if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0)
             return -1;
     }
@@ -2214,29 +2150,25 @@ int TABDATFile::WriteLogicalField(const char *pszValue,
 int TABDATFile::WriteDateField(const char *pszValue,
                                TABINDFile *poINDFile, int nIndexNo)
 {
-    int nDay, nMonth, nYear;
     char **papszTok = NULL;
 
-    /*-----------------------------------------------------------------
-     * Get rid of leading spaces.
-     *----------------------------------------------------------------*/
+    // Get rid of leading spaces.
     while ( *pszValue == ' ' ) { pszValue++; }
 
-    /*-----------------------------------------------------------------
-     * Try to automagically detect date format, one of:
-     * "YYYY/MM/DD", "DD/MM/YYYY", or "YYYYMMDD"
-     *----------------------------------------------------------------*/
+    // Try to automagically detect date format, one of:
+    // "YYYY/MM/DD", "DD/MM/YYYY", or "YYYYMMDD"
+    int nDay = 0;
+    int nMonth = 0;
+    int nYear = 0;
 
     if (strlen(pszValue) == 8)
     {
-        /*-------------------------------------------------------------
-         * "YYYYMMDD"
-         *------------------------------------------------------------*/
-        char szBuf[9];
+        // "YYYYMMDD"
+        char szBuf[9] = {};
         strcpy(szBuf, pszValue);
-        nDay = atoi(szBuf+6);
+        nDay = atoi(szBuf + 6);
         szBuf[6] = '\0';
-        nMonth = atoi(szBuf+4);
+        nMonth = atoi(szBuf + 4);
         szBuf[4] = '\0';
         nYear = atoi(szBuf);
     }
@@ -2246,9 +2178,7 @@ int TABDATFile::WriteDateField(const char *pszValue,
              CSLCount(papszTok) == 3 &&
              (strlen(papszTok[0]) == 4 || strlen(papszTok[2]) == 4) )
     {
-        /*-------------------------------------------------------------
-         * Either "YYYY/MM/DD" or "DD/MM/YYYY"
-         *------------------------------------------------------------*/
+        // Either "YYYY/MM/DD" or "DD/MM/YYYY"
         if (strlen(papszTok[0]) == 4)
         {
             nYear = atoi(papszTok[0]);
@@ -2264,7 +2194,9 @@ int TABDATFile::WriteDateField(const char *pszValue,
     }
     else if (strlen(pszValue) == 0)
     {
-        nYear = nMonth = nDay = 0;
+        nYear = 0;
+        nMonth = 0;
+        nDay = 0;
     }
     else
     {
@@ -2285,14 +2217,15 @@ int TABDATFile::WriteDateField(int nYear, int nMonth, int nDay,
 {
     if (m_poRecordBlock == NULL)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
-                 "Can't write field value: GetRecordBlock() has not been called.");
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
+            "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
 
-    m_poRecordBlock->WriteInt16((GInt16)nYear);
-    m_poRecordBlock->WriteByte((GByte)nMonth);
-    m_poRecordBlock->WriteByte((GByte)nDay);
+    m_poRecordBlock->WriteInt16(static_cast<GInt16>(nYear));
+    m_poRecordBlock->WriteByte(static_cast<GByte>(nMonth));
+    m_poRecordBlock->WriteByte(static_cast<GByte>(nDay));
 
     if (CPLGetLastErrorNo() != 0)
         return -1;
@@ -2300,8 +2233,8 @@ int TABDATFile::WriteDateField(int nYear, int nMonth, int nDay,
     // Update Index
     if (poINDFile && nIndexNo > 0)
     {
-        GByte *pKey = poINDFile->BuildKey(nIndexNo, (nYear*0x10000 +
-                                                     nMonth * 0x100 + nDay));
+        GByte *pKey = poINDFile->BuildKey(
+            nIndexNo, (nYear * 0x10000 + nMonth * 0x100 + nDay));
         if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0)
             return -1;
     }
@@ -2327,58 +2260,59 @@ int TABDATFile::WriteDateField(int nYear, int nMonth, int nDay,
 int TABDATFile::WriteTimeField(const char *pszValue,
                                TABINDFile *poINDFile, int nIndexNo)
 {
-    int nHour, nMin, nSec, nMS;
-    char **papszTok = NULL;
-
-    /*-----------------------------------------------------------------
-     * Get rid of leading spaces.
-     *----------------------------------------------------------------*/
+    // Get rid of leading spaces.
     while ( *pszValue == ' ' ) { pszValue++; }
 
-    /*-----------------------------------------------------------------
-     * Try to automagically detect time format, one of:
-     * "HH:MM:SS", or "HHMMSSmmm"
-     *----------------------------------------------------------------*/
+    // Try to automagically detect time format, one of:
+    // "HH:MM:SS", or "HHMMSSmmm"
+    int nHour = 0;
+    int nMin = 0;
+    int nSec = 0;
+    int nMS = 0;
 
     if (strlen(pszValue) == 8)
     {
-        /*-------------------------------------------------------------
-         * "HH:MM:SS"
-         *------------------------------------------------------------*/
-        char szBuf[9];
+        // "HH:MM:SS"
+        char szBuf[9] = {};
         strcpy(szBuf, pszValue);
-        szBuf[2]=0;
-        szBuf[5]=0;
+        szBuf[2] = 0;
+        szBuf[5] = 0;
         nHour = atoi(szBuf);
-        nMin  = atoi(szBuf+3);
-        nSec  = atoi(szBuf+6);
-        nMS   = 0;
+        nMin = atoi(szBuf + 3);
+        nSec = atoi(szBuf + 6);
+        nMS = 0;
     }
     else if (strlen(pszValue) == 9)
     {
-        /*-------------------------------------------------------------
-         * "HHMMSSmmm"
-         *------------------------------------------------------------*/
-        char szBuf[4];
-        strncpy(szBuf,pszValue,2);
-        szBuf[2]=0;
+        // "HHMMSSmmm"
+        char szBuf[4] = {};
+        const int HHLength = 2;
+        strncpy(szBuf, pszValue, HHLength);
+        szBuf[HHLength] = 0;
         nHour = atoi(szBuf);
 
-        strncpy(szBuf,pszValue+2,2);
-        szBuf[2]=0;
+        const int MMLength = 2;
+        strncpy(szBuf, pszValue + HHLength, MMLength);
+        szBuf[MMLength] = 0;
         nMin = atoi(szBuf);
 
-        strncpy(szBuf,pszValue+4,2);
-        szBuf[2]=0;
+        const int SSLength = 2;
+        strncpy(szBuf, pszValue + HHLength + MMLength, SSLength);
+        szBuf[SSLength] = 0;
         nSec = atoi(szBuf);
 
-        strncpy(szBuf,pszValue+6,3);
-        szBuf[3]=0;
+        const int mmmLength = 3;
+        strncpy(szBuf, pszValue + HHLength + MMLength + SSLength, mmmLength);
+        szBuf[mmmLength] = 0;
         nMS = atoi(szBuf);
     }
     else if (strlen(pszValue) == 0)
     {
-       nHour = nMin = nSec = nMS = -1;  // Write -1 to .DAT file if value is not set
+        // Write -1 to .DAT file if value is not set
+        nHour = -1;
+        nMin = -1;
+        nSec = -1;
+        nMS = -1;
     }
     else
     {
@@ -2386,10 +2320,8 @@ int TABDATFile::WriteTimeField(const char *pszValue,
                  "Invalid time field value `%s'.  Time field values must "
                  "be in the format `HH:MM:SS', or `HHMMSSmmm'",
                  pszValue);
-        CSLDestroy(papszTok);
         return -1;
     }
-    CSLDestroy(papszTok);
 
     return WriteTimeField(nHour, nMin, nSec, nMS, poINDFile, nIndexNo);
 }
@@ -2401,14 +2333,15 @@ int TABDATFile::WriteTimeField(int nHour, int nMinute, int nSecond, int nMS,
 
     if (m_poRecordBlock == NULL)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
             "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
 
-    nS = (nHour*3600+nMinute*60+nSecond)*1000+nMS;
-    if (nS < 0)
-       nS = -1;
+    nS = (nHour * 3600 + nMinute * 60 + nSecond) * 1000 + nMS;
+    if(nS < 0)
+        nS = -1;
     m_poRecordBlock->WriteInt32(nS);
 
     if (CPLGetLastErrorNo() != 0)
@@ -2446,37 +2379,38 @@ d by 1 byte for the month, and 2 bytes for the year.
 int TABDATFile::WriteDateTimeField(const char *pszValue,
                                    TABINDFile *poINDFile, int nIndexNo)
 {
-    int nDay, nMonth, nYear, nHour, nMin, nSec, nMS;
-    char **papszTok = NULL;
-
-    /*-----------------------------------------------------------------
-     * Get rid of leading spaces.
-     *----------------------------------------------------------------*/
+    // Get rid of leading spaces.
     while ( *pszValue == ' ' ) { pszValue++; }
 
     /*-----------------------------------------------------------------
      * Try to automagically detect date format, one of:
      * "YYYY/MM/DD HH:MM:SS", "DD/MM/YYYY HH:MM:SS", or "YYYYMMDDhhmmssmmm"
      *----------------------------------------------------------------*/
+    int nDay = 0;
+    int nMonth = 0;
+    int nYear = 0;
+    int nHour = 0;
+    int nMin = 0;
+    int nSec = 0;
+    int nMS = 0;
+    char **papszTok = NULL;
 
     if (strlen(pszValue) == 17)
     {
-        /*-------------------------------------------------------------
-         * "YYYYMMDDhhmmssmmm"
-         *------------------------------------------------------------*/
-        char szBuf[18];
+        // "YYYYMMDDhhmmssmmm"
+        char szBuf[18] = {};
         strcpy(szBuf, pszValue);
-        nMS  = atoi(szBuf+14);
-        szBuf[14]=0;
-        nSec = atoi(szBuf+12);
-        szBuf[12]=0;
-        nMin = atoi(szBuf+10);
-        szBuf[10]=0;
-        nHour = atoi(szBuf+8);
-        szBuf[8]=0;
-        nDay = atoi(szBuf+6);
+        nMS = atoi(szBuf + 14);
+        szBuf[14] = 0;
+        nSec = atoi(szBuf + 12);
+        szBuf[12] = 0;
+        nMin = atoi(szBuf + 10);
+        szBuf[10] = 0;
+        nHour = atoi(szBuf + 8);
+        szBuf[8] = 0;
+        nDay = atoi(szBuf + 6);
         szBuf[6] = 0;
-        nMonth = atoi(szBuf+4);
+        nMonth = atoi(szBuf + 4);
         szBuf[4] = 0;
         nYear = atoi(szBuf);
     }
@@ -2486,34 +2420,37 @@ int TABDATFile::WriteDateTimeField(const char *pszValue,
              CSLCount(papszTok) == 6 &&
              (strlen(papszTok[0]) == 4 || strlen(papszTok[2]) == 4) )
     {
-        /*-------------------------------------------------------------
-         * Either "YYYY/MM/DD HH:MM:SS" or "DD/MM/YYYY HH:MM:SS"
-         *------------------------------------------------------------*/
-        if (strlen(papszTok[0]) == 4)
+        // Either "YYYY/MM/DD HH:MM:SS" or "DD/MM/YYYY HH:MM:SS"
+        if(strlen(papszTok[0]) == 4)
         {
             nYear = atoi(papszTok[0]);
-            nMonth= atoi(papszTok[1]);
-            nDay  = atoi(papszTok[2]);
+            nMonth = atoi(papszTok[1]);
+            nDay = atoi(papszTok[2]);
             nHour = atoi(papszTok[3]);
-            nMin  = atoi(papszTok[4]);
-            nSec  = atoi(papszTok[5]);
-            nMS   = 0;
+            nMin = atoi(papszTok[4]);
+            nSec = atoi(papszTok[5]);
+            nMS = 0;
         }
         else
         {
             nYear = atoi(papszTok[2]);
-            nMonth= atoi(papszTok[1]);
-            nDay  = atoi(papszTok[0]);
+            nMonth = atoi(papszTok[1]);
+            nDay = atoi(papszTok[0]);
             nHour = atoi(papszTok[3]);
-            nMin  = atoi(papszTok[4]);
-            nSec  = atoi(papszTok[5]);
-            nMS   = 0;
+            nMin = atoi(papszTok[4]);
+            nSec = atoi(papszTok[5]);
+            nMS = 0;
         }
     }
     else if (strlen(pszValue) == 0)
     {
-        nYear = nMonth = nDay = 0;
-        nHour = nMin = nSec = nMS = 0;
+        nYear = 0;
+        nMonth = 0;
+        nDay = 0;
+        nHour = 0;
+        nMin = 0;
+        nSec = 0;
+        nMS = 0;
     }
     else
     {
@@ -2535,18 +2472,19 @@ int TABDATFile::WriteDateTimeField(int nYear, int nMonth, int nDay,
                                    int nHour, int nMinute, int nSecond, int nMS,
                                    TABINDFile *poINDFile, int nIndexNo)
 {
-    GInt32 nS = (nHour*3600+nMinute*60+nSecond)*1000+nMS;
+    GInt32 nS = (nHour * 3600 + nMinute * 60 + nSecond) * 1000 + nMS;
 
     if (m_poRecordBlock == NULL)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
             "Can't write field value: GetRecordBlock() has not been called.");
         return -1;
     }
 
-    m_poRecordBlock->WriteInt16((GInt16)nYear);
-    m_poRecordBlock->WriteByte((GByte)nMonth);
-    m_poRecordBlock->WriteByte((GByte)nDay);
+    m_poRecordBlock->WriteInt16(static_cast<GInt16>(nYear));
+    m_poRecordBlock->WriteByte(static_cast<GByte>(nMonth));
+    m_poRecordBlock->WriteByte(static_cast<GByte>(nDay));
     m_poRecordBlock->WriteInt32(nS);
 
     if (CPLGetLastErrorNo() != 0)
@@ -2558,9 +2496,9 @@ int TABDATFile::WriteDateTimeField(int nYear, int nMonth, int nDay,
         // __TODO__  (see bug #1844)
         // Indexing on DateTime Fields not currently supported, that will
         // require passing the 8 bytes datetime value to BuildKey() here...
-        CPLAssert(FALSE);
-        GByte *pKey = poINDFile->BuildKey(nIndexNo, (nYear*0x10000 +
-                                                     nMonth * 0x100 + nDay));
+        CPLAssert(false);
+        GByte *pKey = poINDFile->BuildKey(
+            nIndexNo, (nYear * 0x10000 + nMonth * 0x100 + nDay));
         if (poINDFile->AddEntry(nIndexNo, pKey, m_nCurRecordId) != 0)
             return -1;
     }
@@ -2584,12 +2522,11 @@ int TABDATFile::WriteDateTimeField(int nYear, int nMonth, int nDay,
 int TABDATFile::WriteDecimalField(double dValue, int nWidth, int nPrec,
                                   TABINDFile *poINDFile, int nIndexNo)
 {
-    char szFormat[10];
-    const char *pszVal;
+    char szFormat[10] = {};
 
     snprintf(szFormat, sizeof(szFormat), "%%%d.%df", nWidth, nPrec);
-    pszVal = CPLSPrintf(szFormat, dValue);
-    if ((int)strlen(pszVal) > nWidth)
+    const char *pszVal = CPLSPrintf(szFormat, dValue);
+    if (static_cast<int>(strlen(pszVal)) > nWidth)
         pszVal += strlen(pszVal) - nWidth;
 
     // Update Index
@@ -2600,11 +2537,10 @@ int TABDATFile::WriteDecimalField(double dValue, int nWidth, int nPrec,
             return -1;
     }
 
-    return m_poRecordBlock->WriteBytes(nWidth, (GByte*)pszVal);
+    return m_poRecordBlock->WriteBytes(nWidth,
+                                       reinterpret_cast<const GByte *>(pszVal));
 }
 
-
-
 /**********************************************************************
  *                   TABDATFile::Dump()
  *
@@ -2612,7 +2548,7 @@ int TABDATFile::WriteDecimalField(double dValue, int nWidth, int nPrec,
  **********************************************************************/
 #ifdef DEBUG
 
-void TABDATFile::Dump(FILE *fpOut /*=NULL*/)
+void TABDATFile::Dump(FILE *fpOut /* =NULL */)
 {
     if (fpOut == NULL)
         fpOut = stdout;
diff --git a/ogr/ogrsf_frmts/mitab/mitab_feature.cpp b/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
index 0a7d64e..81e19b7 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_feature.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_feature.cpp,v 1.100 2010-10-12 19:55:32 aboudreault Exp $
  *
  * Name:     mitab_feature.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -28,190 +27,66 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_feature.cpp,v $
- * Revision 1.100  2010-10-12 19:55:32  aboudreault
- * Fixed style string ID parameter to use the proper delimiter as per OGR Feature Style Specification
- *
- * Revision 1.99  2010-10-08 19:36:44  aboudreault
- * Fixed memory leak (GDAL bug #3045)
- *
- * Revision 1.98  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.97  2010-07-06 13:56:26  aboudreault
- * Fixed TABText::GetLabelStyleString() doesn't escape the double quote character (bug 2236)
- *
- * Revision 1.96  2009-07-30 13:13:43  dmorissette
- * Fixed incorrect text justification returned by GetLabelStyleString()
- * for TABTJRight (bug 2085)
- *
- * Revision 1.95  2008-11-27 20:50:22  aboudreault
- * Improved support for OGR date/time types. New Read/Write methods (bug 1948)
- * Added support of OGR date/time types for MIF features.
- *
- * Revision 1.94  2008/11/18 16:47:44  dmorissette
- * Fixed compile warning when MITAB_USE_OFTDATETIME is set
- *
- * Revision 1.93  2008/11/17 22:06:21  aboudreault
- * Added support to use OFTDateTime/OFTDate/OFTTime type when compiled with
- * OGR and fixed reading/writing support for these types.
- *
- * Revision 1.92  2008/07/29 13:06:17  aboudreault
- * Added Font Point styles support (halo, border) (bug 1925)
- *
- * Revision 1.91  2008/07/21 19:23:03  aboudreault
- * Fixed another small error with expanded text.
- *
- * Revision 1.90  2008/07/21 18:17:19  dmorissette
- * Fixed a few compile warnings
- *
- * Revision 1.89  2008/07/21 17:59:28  aboudreault
- * Fixed error in GetLabelStyleString() function: when text style expanded is
- * set, no space is needed after the last char.
- *
- * Revision 1.88  2008/07/21 14:09:41  aboudreault
- * Add font text styles support (bold, italic, etc.) (bug 1922)
- *
- * Revision 1.87  2008/07/17 14:09:30  aboudreault
- * Add text outline color support (halo background in MapInfo)
- *
- * Revision 1.86  2008/07/14 17:51:21  aboudreault
- * Fixed the text font size problem (bug 1918)
- *
- * Revision 1.85  2008/07/14 16:09:10  aboudreault
- * Fixed multi-line text height problem (bug 1919)
- *
- * Revision 1.84  2008/07/14 14:39:52  aboudreault
- * Fixed multi-line text rendering by adding support of the end of line char
- * "\n" as well as the "\\n".
- *
- * Revision 1.83  2008/07/01 14:33:17  aboudreault
- * * Fixed deprecated warnings generated by mitab.h by moving SetFontName to
- *   mitab_feature.cpp.
- *
- * Revision 1.82  2008/02/22 20:20:44  dmorissette
- * Fixed the internal compressed coordinate range detection test to prevent
- * possible overflow of the compressed integer coordinate values leading
- * to some coord. errors in very rare cases while writing to TAB (bug 1854)
- *
- * Revision 1.81  2008/02/20 21:35:30  dmorissette
- * Added support for V800 COLLECTION of large objects (bug 1496)
- *
- * Revision 1.80  2008/02/05 22:22:48  dmorissette
- * Added support for TAB_GEOM_V800_MULTIPOINT (bug 1496)
- *
- * Revision 1.79  2008/02/01 19:36:31  dmorissette
- * Initial support for V800 REGION and MULTIPLINE (bug 1496)
- *
- * Revision 1.78  2008/01/29 20:46:32  dmorissette
- * Added support for v9 Time and DateTime fields (byg 1754)
- *
- * Revision 1.77  2007/12/11 04:21:54  dmorissette
- * Fixed leaks in ITABFeature???::Set???FromStyleString() (GDAL ticket 1696)
- *
- * Revision 1.76  2007/09/18 17:43:56  dmorissette
- * Fixed another index splitting issue: compr coordinates origin was not
- * stored in the TABFeature in ReadGeometry... (bug 1732)
- *
- * Revision 1.75  2007/09/14 19:29:24  dmorissette
- * Completed handling of bCoordBlockDataOnly arg to Read/WriteGeometry()
- * functions to avoid screwing up pen/brush ref counters (bug 1732)
- *
- * Revision 1.74  2007/09/14 18:30:19  dmorissette
- * Fixed the splitting of object blocks with the optimized spatial
- * index mode that was producing files with misaligned bytes that
- * confused MapInfo (bug 1732)
- *
- * Revision 1.73  2007/09/12 20:22:31  dmorissette
- * Added TABFeature::CreateFromMapInfoType()
- *
- * Revision 1.72  2007/06/12 14:17:16  dmorissette
- * Added TABFile::TwoPointLineAsPolyline() to allow writing two point lines
- * as polylines (bug 1735)
- *
- * Revision 1.71  2007/06/11 17:57:06  dmorissette
- * Removed stray calls to poMapFile->GetCurObjBlock()
- *
- * Revision 1.70  2007/06/11 14:52:30  dmorissette
- * Return a valid m_nCoordDatasize value for Collection objects to prevent
- * trashing of collection data during object splitting (bug 1728)
- *
- * Revision 1.69  2007/02/28 20:41:40  dmorissette
- * Added missing NULL pointer checks in SetPenFromStyleString(),
- * SetBrushFromStyleString() and SetSymbolFromStyleString() (bug 1670)
- *
- * Revision 1.68  2007/02/22 18:35:53  dmorissette
- * Fixed problem writing collections where MITAB was sometimes trying to
- * read past EOF in write mode (bug 1657).
- *
- * Revision 1.67  2006/11/28 18:49:07  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.66  2006/10/17 14:34:31  dmorissette
- * Fixed problem with null brush bg color (bug 1603)
- *
- * Revision 1.65  2006/07/25 13:22:58  dmorissette
- * Fixed initialization of MBR of TABCollection members (bug 1520)
- *
- * Revision 1.64  2006/06/29 19:49:35  dmorissette
- * Fixed problem writing PLINE MULTIPLE to TAB format introduced in
- * MITAB 1.5.0 (bug 1466).
- *
- * Revision 1.63  2006/02/08 05:02:57  dmorissette
- * Fixed crash when attempting to write TABPolyline object with an invalid
- * geometry (GDAL bug 1059)
- *
- * ...
- *
- * Revision 1.1  1999/07/12 04:18:24  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+#include "mitab_geometry.h"
 #include "mitab_utils.h"
+
+#include <cctype>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "mitab.h"
 #include "mitab_geometry.h"
+#include "mitab_priv.h"
+#include "mitab_utils.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_featurestyle.h"
+#include "ogr_geometry.h"
+
+CPL_CVSID("$Id: mitab_feature.cpp 37434 2017-02-22 07:35:34Z goatbar $");
 
 /*=====================================================================
  *                      class TABFeature
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABFeature::TABFeature()
  *
  * Constructor.
  **********************************************************************/
-TABFeature::TABFeature(OGRFeatureDefn *poDefnIn):
-               OGRFeature(poDefnIn)
-{
-    m_nMapInfoType = TAB_GEOM_NONE;
-    m_bDeletedFlag = FALSE;
-
-    m_nXMin = 0;
-    m_nYMin = 0;
-    m_nXMax = 0;
-    m_nYMax = 0;
-    m_nComprOrgX = 0;
-    m_nComprOrgY = 0;
-    m_dXMin = 0;
-    m_dYMin = 0;
-    m_dXMax = 0;
-    m_dYMax = 0;
-}
+TABFeature::TABFeature(OGRFeatureDefn *poDefnIn) :
+    OGRFeature(poDefnIn),
+    m_nMapInfoType(TAB_GEOM_NONE),
+    m_dXMin(0),
+    m_dYMin(0),
+    m_dXMax(0),
+    m_dYMax(0),
+    m_bDeletedFlag(FALSE),
+    m_nXMin(0),
+    m_nYMin(0),
+    m_nXMax(0),
+    m_nYMax(0),
+    m_nComprOrgX(0),
+    m_nComprOrgY(0)
+{}
 
 /**********************************************************************
  *                   TABFeature::~TABFeature()
  *
  * Destructor.
  **********************************************************************/
-TABFeature::~TABFeature()
-{
-}
-
+TABFeature::~TABFeature() {}
 
 /**********************************************************************
  *                     TABFeature::CreateFromMapInfoType()
@@ -230,80 +105,80 @@ TABFeature *TABFeature::CreateFromMapInfoType(int nMapInfoType,
      *----------------------------------------------------------------*/
     switch(nMapInfoType)
     {
-      case TAB_GEOM_NONE:
+    case TAB_GEOM_NONE:
         poFeature = new TABFeature(poDefn);
         break;
-      case TAB_GEOM_SYMBOL_C:
-      case TAB_GEOM_SYMBOL:
+    case TAB_GEOM_SYMBOL_C:
+    case TAB_GEOM_SYMBOL:
         poFeature = new TABPoint(poDefn);
         break;
-      case TAB_GEOM_FONTSYMBOL_C:
-      case TAB_GEOM_FONTSYMBOL:
+    case TAB_GEOM_FONTSYMBOL_C:
+    case TAB_GEOM_FONTSYMBOL:
         poFeature = new TABFontPoint(poDefn);
         break;
-      case TAB_GEOM_CUSTOMSYMBOL_C:
-      case TAB_GEOM_CUSTOMSYMBOL:
+    case TAB_GEOM_CUSTOMSYMBOL_C:
+    case TAB_GEOM_CUSTOMSYMBOL:
         poFeature = new TABCustomPoint(poDefn);
         break;
-      case TAB_GEOM_LINE_C:
-      case TAB_GEOM_LINE:
-      case TAB_GEOM_PLINE_C:
-      case TAB_GEOM_PLINE:
-      case TAB_GEOM_MULTIPLINE_C:
-      case TAB_GEOM_MULTIPLINE:
-      case TAB_GEOM_V450_MULTIPLINE_C:
-      case TAB_GEOM_V450_MULTIPLINE:
-      case TAB_GEOM_V800_MULTIPLINE_C:
-      case TAB_GEOM_V800_MULTIPLINE:
-       poFeature = new TABPolyline(poDefn);
+    case TAB_GEOM_LINE_C:
+    case TAB_GEOM_LINE:
+    case TAB_GEOM_PLINE_C:
+    case TAB_GEOM_PLINE:
+    case TAB_GEOM_MULTIPLINE_C:
+    case TAB_GEOM_MULTIPLINE:
+    case TAB_GEOM_V450_MULTIPLINE_C:
+    case TAB_GEOM_V450_MULTIPLINE:
+    case TAB_GEOM_V800_MULTIPLINE_C:
+    case TAB_GEOM_V800_MULTIPLINE:
+        poFeature = new TABPolyline(poDefn);
         break;
-      case TAB_GEOM_ARC_C:
-      case TAB_GEOM_ARC:
+    case TAB_GEOM_ARC_C:
+    case TAB_GEOM_ARC:
         poFeature = new TABArc(poDefn);
         break;
 
-      case TAB_GEOM_REGION_C:
-      case TAB_GEOM_REGION:
-      case TAB_GEOM_V450_REGION_C:
-      case TAB_GEOM_V450_REGION:
-      case TAB_GEOM_V800_REGION_C:
-      case TAB_GEOM_V800_REGION:
+    case TAB_GEOM_REGION_C:
+    case TAB_GEOM_REGION:
+    case TAB_GEOM_V450_REGION_C:
+    case TAB_GEOM_V450_REGION:
+    case TAB_GEOM_V800_REGION_C:
+    case TAB_GEOM_V800_REGION:
         poFeature = new TABRegion(poDefn);
         break;
-      case TAB_GEOM_RECT_C:
-      case TAB_GEOM_RECT:
-      case TAB_GEOM_ROUNDRECT_C:
-      case TAB_GEOM_ROUNDRECT:
+    case TAB_GEOM_RECT_C:
+    case TAB_GEOM_RECT:
+    case TAB_GEOM_ROUNDRECT_C:
+    case TAB_GEOM_ROUNDRECT:
         poFeature = new TABRectangle(poDefn);
         break;
-      case TAB_GEOM_ELLIPSE_C:
-      case TAB_GEOM_ELLIPSE:
+    case TAB_GEOM_ELLIPSE_C:
+    case TAB_GEOM_ELLIPSE:
         poFeature = new TABEllipse(poDefn);
         break;
-      case TAB_GEOM_TEXT_C:
-      case TAB_GEOM_TEXT:
+    case TAB_GEOM_TEXT_C:
+    case TAB_GEOM_TEXT:
         poFeature = new TABText(poDefn);
         break;
-      case TAB_GEOM_MULTIPOINT_C:
-      case TAB_GEOM_MULTIPOINT:
-      case TAB_GEOM_V800_MULTIPOINT_C:
-      case TAB_GEOM_V800_MULTIPOINT:
+    case TAB_GEOM_MULTIPOINT_C:
+    case TAB_GEOM_MULTIPOINT:
+    case TAB_GEOM_V800_MULTIPOINT_C:
+    case TAB_GEOM_V800_MULTIPOINT:
         poFeature = new TABMultiPoint(poDefn);
         break;
-      case TAB_GEOM_COLLECTION_C:
-      case TAB_GEOM_COLLECTION:
-      case TAB_GEOM_V800_COLLECTION_C:
-      case TAB_GEOM_V800_COLLECTION:
+    case TAB_GEOM_COLLECTION_C:
+    case TAB_GEOM_COLLECTION:
+    case TAB_GEOM_V800_COLLECTION_C:
+    case TAB_GEOM_V800_COLLECTION:
         poFeature = new TABCollection(poDefn);
         break;
-      default:
+    default:
         /*-------------------------------------------------------------
          * Unsupported feature type... we still return a valid feature
          * with NONE geometry after producing a Warning.
          * Callers can trap that case by checking CPLGetLastErrorNo()
          * against TAB_WarningFeatureTypeNotSupported
          *------------------------------------------------------------*/
-//        poFeature = new TABDebugFeature(poDefn);
+        // poFeature = new TABDebugFeature(poDefn);
         poFeature = new TABFeature(poDefn);
 
         CPLError(CE_Warning, (CPLErrorNum)TAB_WarningFeatureTypeNotSupported,
@@ -315,7 +190,6 @@ TABFeature *TABFeature::CreateFromMapInfoType(int nMapInfoType,
     return poFeature;
 }
 
-
 /**********************************************************************
  *                     TABFeature::CopyTABFeatureBase()
  *
@@ -340,20 +214,26 @@ void TABFeature::CopyTABFeatureBase(TABFeature *poDestFeature)
     {
         for( int i = 0; i < poThisDefnRef->GetFieldCount(); i++ )
         {
-            poDestFeature->SetField( i, GetRawFieldRef( i ) );
+            poDestFeature->SetField(i, GetRawFieldRef(i));
         }
     }
 
     /*-----------------------------------------------------------------
      * Copy the geometry
      *----------------------------------------------------------------*/
-    poDestFeature->SetGeometry( GetGeometryRef() );
+    poDestFeature->SetGeometry(GetGeometryRef());
 
-    double dXMin, dYMin, dXMax, dYMax;
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     GetMBR(dXMin, dYMin, dXMax, dYMax);
     poDestFeature->SetMBR(dXMin, dYMin, dXMax, dYMax);
 
-    GInt32 nXMin, nYMin, nXMax, nYMax;
+    GInt32 nXMin = 0;
+    GInt32 nYMin = 0;
+    GInt32 nXMax = 0;
+    GInt32 nYMax = 0;
     GetIntMBR(nXMin, nYMin, nXMax, nYMax);
     poDestFeature->SetIntMBR(nXMin, nYMin, nXMax, nYMax);
 
@@ -361,7 +241,6 @@ void TABFeature::CopyTABFeatureBase(TABFeature *poDestFeature)
     // it will default to TAB_GEOM_NONE
 }
 
-
 /**********************************************************************
  *                     TABFeature::CloneTABFeature()
  *
@@ -376,7 +255,7 @@ void TABFeature::CopyTABFeatureBase(TABFeature *poDestFeature)
  * This method calls the generic TABFeature::CopyTABFeatureBase() and
  * then copies any members specific to its own type.
  **********************************************************************/
-TABFeature *TABFeature::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
+TABFeature *TABFeature::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/ )
 {
     /*-----------------------------------------------------------------
      * Alloc new feature and copy the base stuff
@@ -398,13 +277,13 @@ TABFeature *TABFeature::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
  *
  * Set the values for the MBR corners for this feature.
  **********************************************************************/
-void TABFeature::SetMBR(double dXMin, double dYMin,
-                        double dXMax, double dYMax)
+void TABFeature::SetMBR( double dXMin, double dYMin,
+                         double dXMax, double dYMax )
 {
-    m_dXMin = MIN(dXMin, dXMax);
-    m_dYMin = MIN(dYMin, dYMax);
-    m_dXMax = MAX(dXMin, dXMax);
-    m_dYMax = MAX(dYMin, dYMax);
+    m_dXMin = std::min(dXMin, dXMax);
+    m_dYMin = std::min(dYMin, dYMax);
+    m_dXMax = std::max(dXMin, dXMax);
+    m_dYMax = std::max(dYMin, dYMax);
 }
 
 /**********************************************************************
@@ -412,8 +291,8 @@ void TABFeature::SetMBR(double dXMin, double dYMin,
  *
  * Return the values for the MBR corners for this feature.
  **********************************************************************/
-void TABFeature::GetMBR(double &dXMin, double &dYMin,
-                        double &dXMax, double &dYMax)
+void TABFeature::GetMBR( double &dXMin, double &dYMin,
+                         double &dXMax, double &dYMax )
 {
     dXMin = m_dXMin;
     dYMin = m_dYMin;
@@ -461,102 +340,131 @@ void TABFeature::GetIntMBR(GInt32 &nXMin, GInt32 &nYMin,
  **********************************************************************/
 int TABFeature::ReadRecordFromDATFile(TABDATFile *poDATFile)
 {
-    int         iField, numFields, nValue;
-    double      dValue;
-    const char *pszValue;
-#ifdef MITAB_USE_OFTDATETIME
-    int nYear, nMonth, nDay, nHour, nMin, nMS, status;
-    nYear = nMonth = nDay = nHour = nMin = nMS = 0;
-#endif
-
     CPLAssert(poDATFile);
 
-    numFields = poDATFile->GetNumFields();
+    const int numFields = poDATFile->GetNumFields();
 
-    for(iField=0; iField<numFields; iField++)
+    for( int iField = 0; iField < numFields; iField++)
     {
         switch(poDATFile->GetFieldType(iField))
         {
-          case TABFChar:
-            pszValue = poDATFile->ReadCharField(poDATFile->
-                                                GetFieldWidth(iField));
+        case TABFChar:
+        {
+            const char *pszValue =
+                poDATFile->ReadCharField(poDATFile->GetFieldWidth(iField));
             SetField(iField, pszValue);
             break;
-          case TABFDecimal:
-            dValue = poDATFile->ReadDecimalField(poDATFile->
-                                                 GetFieldWidth(iField));
+        }
+        case TABFDecimal:
+        {
+            const double dValue =
+                poDATFile->ReadDecimalField(poDATFile->GetFieldWidth(iField));
             SetField(iField, dValue);
             break;
-          case TABFInteger:
-            nValue = poDATFile->ReadIntegerField(poDATFile->
-                                                 GetFieldWidth(iField));
+        }
+        case TABFInteger:
+        {
+            const int nValue =
+                poDATFile->ReadIntegerField(poDATFile->GetFieldWidth(iField));
             SetField(iField, nValue);
             break;
-          case TABFSmallInt:
-            nValue = poDATFile->ReadSmallIntField(poDATFile->
-                                                 GetFieldWidth(iField));
+        }
+        case TABFSmallInt:
+        {
+            const int nValue =
+                poDATFile->ReadSmallIntField(poDATFile->GetFieldWidth(iField));
             SetField(iField, nValue);
             break;
-          case TABFFloat:
-            dValue = poDATFile->ReadFloatField(poDATFile->
-                                                 GetFieldWidth(iField));
+        }
+        case TABFFloat:
+        {
+            const double dValue =
+                poDATFile->ReadFloatField(poDATFile->GetFieldWidth(iField));
             SetField(iField, dValue);
             break;
-          case TABFLogical:
-            pszValue = poDATFile->ReadLogicalField(poDATFile->
-                                                 GetFieldWidth(iField));
+        }
+        case TABFLogical:
+        {
+            const char *pszValue =
+                poDATFile->ReadLogicalField(poDATFile->GetFieldWidth(iField));
             SetField(iField, pszValue);
             break;
-          case TABFDate:
+        }
+        case TABFDate:
+        {
 #ifdef MITAB_USE_OFTDATETIME
-             if ((status = poDATFile->ReadDateField(poDATFile->GetFieldWidth(iField),
-                                                    &nYear, &nMonth, &nDay)) == 0)
-             {
+            int nYear = 0;
+            int nMonth = 0;
+            int nDay = 0;
+            int status = 0;
+
+            if((status =
+                    poDATFile->ReadDateField(poDATFile->GetFieldWidth(iField),
+                                             &nYear, &nMonth, &nDay)) == 0)
+            {
                 SetField(iField, nYear, nMonth, nDay, 0, 0, 0, 0);
-             }
+            }
 #else
-            pszValue = poDATFile->ReadDateField(poDATFile->
-                                            GetFieldWidth(iField));
+            const char *pszValue =
+                poDATFile->ReadDateField(poDATFile->GetFieldWidth(iField));
             SetField(iField, pszValue);
 #endif
             break;
-          case TABFTime:
-          {
+        }
+        case TABFTime:
+        {
 #ifdef MITAB_USE_OFTDATETIME
-             int nSec;
-             if ((status = poDATFile->ReadTimeField(poDATFile->GetFieldWidth(iField),
-                                                    &nHour, &nMin, &nSec, &nMS)) == 0)
-             {
-                SetField(iField, nYear, nMonth, nDay, nHour, nMin, nSec + nMS / 1000.0f, 0);
-             }
+            int nHour = 0;
+            int nMin = 0;
+            int nMS = 0;
+            int nSec = 0;
+            const int status = poDATFile->ReadTimeField(
+                poDATFile->GetFieldWidth(iField), &nHour, &nMin, &nSec, &nMS);
+            if( status == 0 )
+            {
+                int nYear = 0;
+                int nMonth = 0;
+                int nDay = 0;
+                SetField(iField, nYear, nMonth, nDay, nHour, nMin,
+                         nSec + nMS / 1000.0f, 0);
+            }
 #else
-             pszValue = poDATFile->ReadTimeField(poDATFile->
-                                                     GetFieldWidth(iField));
-             SetField(iField, pszValue);
+            const char *pszValue =
+                poDATFile->ReadTimeField(poDATFile->GetFieldWidth(iField));
+            SetField(iField, pszValue);
 #endif
             break;
-          }
-          case TABFDateTime:
+        }
+        case TABFDateTime:
+        {
 #ifdef MITAB_USE_OFTDATETIME
-            int nSec;
-            if ((status = poDATFile->ReadDateTimeField(poDATFile->GetFieldWidth(iField),
-                                                       &nYear, &nMonth, &nDay,
-                                                       &nHour, &nMin, &nSec, &nMS)) == 0)
+            int nYear = 0;
+            int nMonth = 0;
+            int nDay = 0;
+            int nHour = 0;
+            int nMin = 0;
+            int nMS = 0;
+            int nSec = 0;
+            const int status = poDATFile->ReadDateTimeField(
+                poDATFile->GetFieldWidth(iField), &nYear, &nMonth, &nDay,
+                &nHour, &nMin, &nSec, &nMS);
+            if( status == 0 )
             {
-               SetField(iField, nYear, nMonth, nDay, nHour, nMin, nSec + nMS / 1000.0f, 0);
+                SetField(iField, nYear, nMonth, nDay, nHour, nMin,
+                         nSec + nMS / 1000.0f, 0);
             }
 #else
-            pszValue = poDATFile->ReadDateTimeField(poDATFile->
-                                                    GetFieldWidth(iField));
+            const char *pszValue =
+                poDATFile->ReadDateTimeField(poDATFile->GetFieldWidth(iField));
             SetField(iField, pszValue);
 #endif
             break;
-          default:
+        }
+        default:
             // Other type???  Impossible!
             CPLError(CE_Failure, CPLE_AssertionFailed,
                      "Unsupported field type!");
         }
-
     }
 
     return 0;
@@ -576,126 +484,140 @@ int TABFeature::ReadRecordFromDATFile(TABDATFile *poDATFile)
 int TABFeature::WriteRecordToDATFile(TABDATFile *poDATFile,
                                      TABINDFile *poINDFile, int *panIndexNo)
 {
-    int         iField, numFields, nStatus=0;
 #ifdef MITAB_USE_OFTDATETIME
-    int         nYear, nMon, nDay, nHour, nMin, nTZFlag;
-    nYear = nMon = nDay = nHour = nMin = nTZFlag = 0;
-    float       fSec = 0;
+    int nYear = 0;
+    int nMon = 0;
+    int nDay = 0;
+    int nHour = 0;
+    int nMin = 0;
+    int nTZFlag = 0;
+    float fSec = 0.0f;
 #endif
 
     CPLAssert(poDATFile);
 
-    numFields = poDATFile->GetNumFields();
+    const int numFields = poDATFile->GetNumFields();
 
     poDATFile->MarkRecordAsExisting();
 
-    for(iField=0; nStatus == 0 && iField<numFields; iField++)
+    // int nStatus = 0;
+    for( int iField = 0, nStatus = 0;
+         nStatus == 0 && iField < numFields;
+         iField++ )
     {
         // Hack for "extra" introduced field.
         if( iField >= GetDefnRef()->GetFieldCount() )
         {
-            CPLAssert( poDATFile->GetFieldType(iField) == TABFInteger
-                       && iField == 0 );
-            nStatus = poDATFile->WriteIntegerField( (int)GetFID(), poINDFile, 0 );
+            CPLAssert(poDATFile->GetFieldType(iField) == TABFInteger &&
+                      iField == 0);
+            nStatus = poDATFile->WriteIntegerField((int)GetFID(), poINDFile, 0);
             continue;
         }
         CPLAssert(panIndexNo != NULL);
 
         switch(poDATFile->GetFieldType(iField))
         {
-          case TABFChar:
-            nStatus = poDATFile->WriteCharField(GetFieldAsString(iField),
-                                      poDATFile->GetFieldWidth(iField),
-                                                poINDFile, panIndexNo[iField]);
+        case TABFChar:
+            nStatus = poDATFile->WriteCharField(
+                GetFieldAsString(iField), poDATFile->GetFieldWidth(iField),
+                poINDFile, panIndexNo[iField]);
             break;
-          case TABFDecimal:
-            nStatus = poDATFile->WriteDecimalField(GetFieldAsDouble(iField),
-                                      poDATFile->GetFieldWidth(iField),
-                                      poDATFile->GetFieldPrecision(iField),
-                                             poINDFile, panIndexNo[iField]);
+        case TABFDecimal:
+            nStatus = poDATFile->WriteDecimalField(
+                GetFieldAsDouble(iField), poDATFile->GetFieldWidth(iField),
+                poDATFile->GetFieldPrecision(iField), poINDFile,
+                panIndexNo[iField]);
             break;
-          case TABFInteger:
-            nStatus = poDATFile->WriteIntegerField(GetFieldAsInteger(iField),
-                                                poINDFile, panIndexNo[iField]);
+        case TABFInteger:
+            nStatus = poDATFile->WriteIntegerField(
+                GetFieldAsInteger(iField), poINDFile, panIndexNo[iField]);
             break;
-          case TABFSmallInt:
-            nStatus = poDATFile->WriteSmallIntField((GInt16)GetFieldAsInteger(iField),
-                                                poINDFile, panIndexNo[iField]);
+        case TABFSmallInt:
+            nStatus =
+                poDATFile->WriteSmallIntField((GInt16)GetFieldAsInteger(iField),
+                                              poINDFile, panIndexNo[iField]);
             break;
-          case TABFFloat:
+        case TABFFloat:
             nStatus = poDATFile->WriteFloatField(GetFieldAsDouble(iField),
-                                                poINDFile, panIndexNo[iField]);
+                                                 poINDFile, panIndexNo[iField]);
             break;
-          case TABFLogical:
-            nStatus = poDATFile->WriteLogicalField(GetFieldAsString(iField),
-                                                poINDFile, panIndexNo[iField]);
+        case TABFLogical:
+            nStatus = poDATFile->WriteLogicalField(
+                GetFieldAsString(iField), poINDFile, panIndexNo[iField]);
             break;
-          case TABFDate:
+        case TABFDate:
 #ifdef MITAB_USE_OFTDATETIME
-             if (IsFieldSet(iField))
-             {
-                GetFieldAsDateTime(iField, &nYear, &nMon, &nDay,
-                                   &nHour, &nMin, &fSec, &nTZFlag);
-             }
-             else
-                 nYear = nMon = nDay = 0;
-
-             nStatus = poDATFile->WriteDateField(nYear, nMon, nDay,
-                                                 poINDFile, panIndexNo[iField]);
+            if (IsFieldSetAndNotNull(iField))
+            {
+                GetFieldAsDateTime(iField, &nYear, &nMon, &nDay, &nHour, &nMin,
+                                   &fSec, &nTZFlag);
+            }
+            else
+            {
+                nYear = 0;
+                nMon = 0;
+                nDay = 0;
+            }
+
+            nStatus = poDATFile->WriteDateField(nYear, nMon, nDay, poINDFile,
+                                                panIndexNo[iField]);
 #else
-             nStatus = poDATFile->WriteDateField(GetFieldAsString(iField),
-                                                 poINDFile, panIndexNo[iField]);
+            nStatus = poDATFile->WriteDateField(GetFieldAsString(iField),
+                                                poINDFile, panIndexNo[iField]);
 #endif
             break;
-          case TABFTime:
+        case TABFTime:
 #ifdef MITAB_USE_OFTDATETIME
-             if (IsFieldSet(iField))
-             {
-                GetFieldAsDateTime(iField, &nYear, &nMon, &nDay,
-                                   &nHour, &nMin, &fSec, &nTZFlag);
-             }
-             else
-             {
-                nHour = nMin = 0;
+            if (IsFieldSetAndNotNull(iField))
+            {
+                GetFieldAsDateTime(iField, &nYear, &nMon, &nDay, &nHour, &nMin,
+                                   &fSec, &nTZFlag);
+            }
+            else
+            {
+                nHour = 0;
+                nMin = 0;
                 fSec = 0;
-             }
-             nStatus = poDATFile->WriteTimeField(nHour, nMin, (int)fSec,
-                                                 OGR_GET_MS(fSec),
-                                                 poINDFile, panIndexNo[iField]);
+            }
+            nStatus = poDATFile->WriteTimeField(nHour, nMin, (int)fSec,
+                                                OGR_GET_MS(fSec), poINDFile,
+                                                panIndexNo[iField]);
 
 #else
-             nStatus = poDATFile->WriteTimeField(GetFieldAsString(iField),
-                                                 poINDFile, panIndexNo[iField]);
+            nStatus = poDATFile->WriteTimeField(GetFieldAsString(iField),
+                                                poINDFile, panIndexNo[iField]);
 #endif
             break;
-          case TABFDateTime:
+        case TABFDateTime:
 #ifdef MITAB_USE_OFTDATETIME
-             if (IsFieldSet(iField))
-             {
-                GetFieldAsDateTime(iField, &nYear, &nMon, &nDay,
-                                   &nHour, &nMin, &fSec, &nTZFlag);
-             }
-             else
-             {
-                 nYear = nMon = nDay = nHour = nMin = 0;
-                 fSec = 0;
-             }
-
-             nStatus = poDATFile->WriteDateTimeField(nYear, nMon, nDay,
-                                                     nHour, nMin, (int)fSec,
-                                                     OGR_GET_MS(fSec),
-                                                     poINDFile, panIndexNo[iField]);
+            if (IsFieldSetAndNotNull(iField))
+            {
+                GetFieldAsDateTime(iField, &nYear, &nMon, &nDay, &nHour, &nMin,
+                                   &fSec, &nTZFlag);
+            }
+            else
+            {
+                nYear = 0;
+                nMon = 0;
+                nDay = 0;
+                nHour = 0;
+                nMin = 0;
+                fSec = 0;
+            }
+
+            nStatus = poDATFile->WriteDateTimeField(
+                nYear, nMon, nDay, nHour, nMin, (int)fSec, OGR_GET_MS(fSec),
+                poINDFile, panIndexNo[iField]);
 #else
-             nStatus = poDATFile->WriteDateTimeField(GetFieldAsString(iField),
-                                                     poINDFile, panIndexNo[iField]);
+            nStatus = poDATFile->WriteDateTimeField(
+                GetFieldAsString(iField), poINDFile, panIndexNo[iField]);
 #endif
             break;
-          default:
+        default:
             // Other type???  Impossible!
             CPLError(CE_Failure, CPLE_AssertionFailed,
                      "Unsupported field type!");
         }
-
     }
 
     if (poDATFile->CommitRecordToFile() != 0)
@@ -735,14 +657,10 @@ int TABFeature::ReadGeometryFromMAPFile(TABMAPFile * /*poMapFile*/,
                                         GBool /*bCoordBlockDataOnly=FALSE*/,
                                         TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    /*-----------------------------------------------------------------
-     * Nothing to do... instances of TABFeature objects contain no geometry.
-     *----------------------------------------------------------------*/
-
+    // Nothing to do. Instances of TABFeature objects contain no geometry.
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABFeature::UpdateMBR()
  *
@@ -751,11 +669,9 @@ int TABFeature::ReadGeometryFromMAPFile(TABMAPFile * /*poMapFile*/,
  *
  * Returns 0 on success, or -1 if there is no geometry in object
  **********************************************************************/
-int TABFeature::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
+int TABFeature::UpdateMBR(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
 
     if (poGeom)
     {
@@ -792,7 +708,7 @@ int TABFeature::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
  *
  * Returns TRUE if coord. should be compressed, FALSE otherwise
  **********************************************************************/
-GBool TABFeature::ValidateCoordType(TABMAPFile * poMapFile)
+GBool TABFeature::ValidateCoordType(TABMAPFile *poMapFile)
 {
     GBool bCompr = FALSE;
 
@@ -815,9 +731,9 @@ GBool TABFeature::ValidateCoordType(TABMAPFile * poMapFile)
     /*-------------------------------------------------------------
      * Adjust native type
      *------------------------------------------------------------*/
-    if (bCompr && ((m_nMapInfoType%3) == 2))
+    if (bCompr && ((m_nMapInfoType % 3) == 2))
         m_nMapInfoType = (TABGeomType)(m_nMapInfoType - 1);  // compr = 1, 4, 7, ...
-    else if (!bCompr && ((m_nMapInfoType%3) == 1))
+    else if (!bCompr && ((m_nMapInfoType % 3) == 1))
         m_nMapInfoType = (TABGeomType)(m_nMapInfoType + 1);  // non-compr = 2, 5, 8, ...
 
     return bCompr;
@@ -844,9 +760,9 @@ void TABFeature::ForceCoordTypeAndOrigin(TABGeomType nMapInfoType, GBool bCompr,
 
     m_nMapInfoType = nMapInfoType;
 
-    if (bCompr && ((m_nMapInfoType%3) == 2))
+    if (bCompr && ((m_nMapInfoType % 3) == 2))
         m_nMapInfoType = (TABGeomType)(m_nMapInfoType - 1);  // compr = 1, 4, 7, ...
-    else if (!bCompr && ((m_nMapInfoType%3) == 1))
+    else if (!bCompr && ((m_nMapInfoType % 3) == 1))
         m_nMapInfoType = (TABGeomType)(m_nMapInfoType + 1);  // non-compr = 2, 5, 8, ...
 
     m_nXMin = nXMin;
@@ -901,19 +817,19 @@ int TABFeature::WriteGeometryToMAPFile(TABMAPFile * /* poMapFile*/,
  **********************************************************************/
 void TABFeature::DumpMID(FILE *fpOut /*=NULL*/)
 {
-    OGRFeatureDefn      *l_poDefn = GetDefnRef();
+    OGRFeatureDefn *l_poDefn = GetDefnRef();
 
     if (fpOut == NULL)
         fpOut = stdout;
 
     for( int iField = 0; iField < GetFieldCount(); iField++ )
     {
-        OGRFieldDefn    *poFDefn = l_poDefn->GetFieldDefn(iField);
+        OGRFieldDefn *poFDefn = l_poDefn->GetFieldDefn(iField);
 
-        fprintf( fpOut, "  %s (%s) = %s\n",
-                 poFDefn->GetNameRef(),
-                 OGRFieldDefn::GetFieldTypeName(poFDefn->GetType()),
-                 GetFieldAsString( iField ) );
+        fprintf(fpOut, "  %s (%s) = %s\n",
+                poFDefn->GetNameRef(),
+                OGRFieldDefn::GetFieldTypeName(poFDefn->GetType()),
+                GetFieldAsString(iField));
     }
 
     fflush(fpOut);
@@ -932,35 +848,28 @@ void TABFeature::DumpMIF(FILE *fpOut /*=NULL*/)
     /*-----------------------------------------------------------------
      * Generate output... not much to do, feature contains no geometry.
      *----------------------------------------------------------------*/
-    fprintf(fpOut, "NONE\n" );
+    fprintf(fpOut, "NONE\n");
 
     fflush(fpOut);
 }
 
-
 /*=====================================================================
  *                      class TABPoint
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABPoint::TABPoint()
  *
  * Constructor.
  **********************************************************************/
-TABPoint::TABPoint(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
-{
-}
+TABPoint::TABPoint(OGRFeatureDefn *poDefnIn) : TABFeature(poDefnIn) {}
 
 /**********************************************************************
  *                   TABPoint::~TABPoint()
  *
  * Destructor.
  **********************************************************************/
-TABPoint::~TABPoint()
-{
-}
+TABPoint::~TABPoint() {}
 
 /**********************************************************************
  *                     TABPoint::CloneTABFeature()
@@ -988,7 +897,6 @@ TABFeature *TABPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
     return poNew;
 }
 
-
 /**********************************************************************
  *                   TABPoint::ValidateMapInfoType()
  *
@@ -1001,8 +909,6 @@ TABFeature *TABPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
  **********************************************************************/
 TABGeomType TABPoint::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      * __TODO__ For now we always write in uncompressed format (until we
@@ -1011,19 +917,19 @@ TABGeomType TABPoint::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
      * the distance between the point and the object block center in
      * integer coordinates being > 32767 or not... remains to be verified)
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
     {
         switch(GetFeatureClass())
         {
-          case TABFCFontPoint:
+        case TABFCFontPoint:
             m_nMapInfoType = TAB_GEOM_FONTSYMBOL;
             break;
-          case TABFCCustomPoint:
+        case TABFCCustomPoint:
             m_nMapInfoType = TAB_GEOM_CUSTOMSYMBOL;
             break;
-          case TABFCPoint:
-          default:
+        case TABFCPoint:
+        default:
             m_nMapInfoType = TAB_GEOM_SYMBOL;
             break;
         }
@@ -1057,9 +963,6 @@ int TABPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                       GBool bCoordBlockDataOnly /*=FALSE*/,
                                       TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    double              dX, dY;
-    OGRGeometry         *poGeometry;
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -1072,9 +975,10 @@ int TABPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     if (m_nMapInfoType != TAB_GEOM_SYMBOL &&
         m_nMapInfoType != TAB_GEOM_SYMBOL_C )
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
-           "ReadGeometryFromMAPFile(): unsupported geometry type %d (0x%2.2x)",
-                 m_nMapInfoType, m_nMapInfoType);
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
+            "ReadGeometryFromMAPFile(): unsupported geometry type %d (0x%2.2x)",
+            m_nMapInfoType, m_nMapInfoType);
         return -1;
     }
 
@@ -1083,15 +987,18 @@ int TABPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      *----------------------------------------------------------------*/
     TABMAPObjPoint *poPointHdr = (TABMAPObjPoint *)poObjHdr;
 
-    m_nSymbolDefIndex = poPointHdr->m_nSymbolId;   // Symbol index
+    m_nSymbolDefIndex = poPointHdr->m_nSymbolId;  // Symbol index
 
     poMapFile->ReadSymbolDef(m_nSymbolDefIndex, &m_sSymbolDef);
 
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      *----------------------------------------------------------------*/
+    double dX = 0.0;
+    double dY = 0.0;
+
     poMapFile->Int2Coordsys(poPointHdr->m_nX, poPointHdr->m_nY, dX, dY);
-    poGeometry = new OGRPoint(dX, dY);
+    OGRGeometry *poGeometry = new OGRPoint(dX, dY);
 
     SetGeometryDirectly(poGeometry);
 
@@ -1118,10 +1025,6 @@ int TABPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                      GBool bCoordBlockDataOnly /*=FALSE*/,
                                      TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    GInt32              nX, nY;
-    OGRGeometry         *poGeom;
-    OGRPoint            *poPoint;
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -1135,9 +1038,10 @@ int TABPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
-        poPoint = (OGRPoint*)poGeom;
+        poPoint = (OGRPoint *)poGeom;
     else
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1145,6 +1049,8 @@ int TABPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         return -1;
     }
 
+    GInt32 nX = 0;
+    GInt32 nY = 0;
     poMapFile->Coordsys2Int(poPoint->getX(), poPoint->getY(), nX, nY);
 
     /*-----------------------------------------------------------------
@@ -1157,7 +1063,7 @@ int TABPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     poPointHdr->SetMBR(nX, nY, nX, nY);
 
     m_nSymbolDefIndex = poMapFile->WriteSymbolDef(&m_sSymbolDef);
-    poPointHdr->m_nSymbolId = (GByte)m_nSymbolDefIndex;      // Symbol index
+    poPointHdr->m_nSymbolId = (GByte)m_nSymbolDefIndex;  // Symbol index
 
     if (CPLGetLastErrorNo() != 0)
         return -1;
@@ -1165,7 +1071,6 @@ int TABPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABPoint::GetX()
  *
@@ -1173,15 +1078,14 @@ int TABPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
  **********************************************************************/
 double TABPoint::GetX()
 {
-    OGRGeometry *poGeom;
-    OGRPoint    *poPoint=NULL;
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
-        poPoint = (OGRPoint*)poGeom;
+        poPoint = (OGRPoint *)poGeom;
     else
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1199,15 +1103,13 @@ double TABPoint::GetX()
  **********************************************************************/
 double TABPoint::GetY()
 {
-    OGRGeometry *poGeom;
-    OGRPoint    *poPoint=NULL;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
-        poPoint = (OGRPoint*)poGeom;
+        poPoint = (OGRPoint *)poGeom;
     else
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1218,7 +1120,6 @@ double TABPoint::GetY()
     return poPoint->getY();
 }
 
-
 /**********************************************************************
  *                   TABPoint::GetStyleString()
  *
@@ -1236,7 +1137,6 @@ const char *TABPoint::GetStyleString()
     return m_pszStyleString;
 }
 
-
 /**********************************************************************
  *                   TABPoint::DumpMIF()
  *
@@ -1244,18 +1144,16 @@ const char *TABPoint::GetStyleString()
  **********************************************************************/
 void TABPoint::DumpMIF(FILE *fpOut /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-    OGRPoint    *poPoint;
-
     if (fpOut == NULL)
         fpOut = stdout;
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
-        poPoint = (OGRPoint*)poGeom;
+        poPoint = (OGRPoint *)poGeom;
     else
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1266,13 +1164,14 @@ void TABPoint::DumpMIF(FILE *fpOut /*=NULL*/)
     /*-----------------------------------------------------------------
      * Generate output
      *----------------------------------------------------------------*/
-    fprintf(fpOut, "POINT %.15g %.15g\n", poPoint->getX(), poPoint->getY() );
+    fprintf(fpOut, "POINT %.15g %.15g\n", poPoint->getX(), poPoint->getY());
 
     DumpSymbolDef(fpOut);
 
     /*-----------------------------------------------------------------
      * Handle stuff specific to derived classes
      *----------------------------------------------------------------*/
+    // cppcheck-suppress knownConditionTrueFalse
     if (GetFeatureClass() == TABFCFontPoint)
     {
         TABFontPoint *poFeature = (TABFontPoint *)this;
@@ -1282,6 +1181,7 @@ void TABPoint::DumpMIF(FILE *fpOut /*=NULL*/)
 
         poFeature->DumpFontDef(fpOut);
     }
+    // cppcheck-suppress knownConditionTrueFalse
     if (GetFeatureClass() == TABFCCustomPoint)
     {
         TABCustomPoint *poFeature = (TABCustomPoint *)this;
@@ -1302,27 +1202,23 @@ void TABPoint::DumpMIF(FILE *fpOut /*=NULL*/)
  *                      class TABFontPoint
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABFontPoint::TABFontPoint()
  *
  * Constructor.
  **********************************************************************/
-TABFontPoint::TABFontPoint(OGRFeatureDefn *poDefnIn):
-              TABPoint(poDefnIn)
-{
-    m_nFontStyle = 0;
-    m_dAngle = 0.0;
-}
+TABFontPoint::TABFontPoint(OGRFeatureDefn *poDefnIn) :
+    TABPoint(poDefnIn),
+    m_dAngle(0.0),
+    m_nFontStyle(0)
+{}
 
 /**********************************************************************
  *                   TABFontPoint::~TABFontPoint()
  *
  * Destructor.
  **********************************************************************/
-TABFontPoint::~TABFontPoint()
-{
-}
+TABFontPoint::~TABFontPoint() {}
 
 /**********************************************************************
  *                     TABFontPoint::CloneTABFeature()
@@ -1337,8 +1233,8 @@ TABFeature *TABFontPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
     /*-----------------------------------------------------------------
      * Alloc new feature and copy the base stuff
      *----------------------------------------------------------------*/
-    TABFontPoint *poNew = new TABFontPoint(poNewDefn ? poNewDefn :
-                                                       GetDefnRef());
+    TABFontPoint *poNew =
+        new TABFontPoint(poNewDefn ? poNewDefn : GetDefnRef());
 
     CopyTABFeatureBase(poNew);
 
@@ -1351,8 +1247,8 @@ TABFeature *TABFontPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
     // ITABFeatureFont
     *(poNew->GetFontDefRef()) = *GetFontDefRef();
 
-    poNew->SetSymbolAngle( GetSymbolAngle() );
-    poNew->SetFontStyleTABValue( GetFontStyleTABValue() );
+    poNew->SetSymbolAngle(GetSymbolAngle());
+    poNew->SetFontStyleTABValue(GetFontStyleTABValue());
 
     return poNew;
 }
@@ -1374,9 +1270,6 @@ int TABFontPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                           GBool bCoordBlockDataOnly /*=FALSE*/,
                                           TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    double              dX, dY;
-    OGRGeometry         *poGeometry;
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -1389,9 +1282,10 @@ int TABFontPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     if (m_nMapInfoType != TAB_GEOM_FONTSYMBOL &&
         m_nMapInfoType != TAB_GEOM_FONTSYMBOL_C )
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
-           "ReadGeometryFromMAPFile(): unsupported geometry type %d (0x%2.2x)",
-                 m_nMapInfoType, m_nMapInfoType);
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
+            "ReadGeometryFromMAPFile(): unsupported geometry type %d (0x%2.2x)",
+            m_nMapInfoType, m_nMapInfoType);
         return -1;
     }
 
@@ -1407,31 +1301,33 @@ int TABFontPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     m_nSymbolDefIndex = -1;
     m_sSymbolDef.nRefCount = 0;
 
-    m_sSymbolDef.nSymbolNo  = poPointHdr->m_nSymbolId;  // shape
-    m_sSymbolDef.nPointSize = poPointHdr->m_nPointSize; // point size
+    m_sSymbolDef.nSymbolNo = poPointHdr->m_nSymbolId;    // shape
+    m_sSymbolDef.nPointSize = poPointHdr->m_nPointSize;  // point size
 
-    m_nFontStyle            = poPointHdr->m_nFontStyle; // font style
+    m_nFontStyle = poPointHdr->m_nFontStyle;  // font style
 
-    m_sSymbolDef.rgbColor   = (poPointHdr->m_nR*256*256 +
-                               poPointHdr->m_nG*256 +
-                               poPointHdr->m_nB);
+    m_sSymbolDef.rgbColor = poPointHdr->m_nR * 256 * 256 +
+                            poPointHdr->m_nG * 256 +
+                            poPointHdr->m_nB;
 
     /*-------------------------------------------------------------
      * Symbol Angle, in tenths of degree.
      * Contrary to arc start/end angles, no conversion based on
      * origin quadrant is required here.
      *------------------------------------------------------------*/
-    m_dAngle       = poPointHdr->m_nAngle/10.0;
+    m_dAngle = poPointHdr->m_nAngle / 10.0;
 
-    m_nFontDefIndex = poPointHdr->m_nFontId;      // Font name index
+    m_nFontDefIndex = poPointHdr->m_nFontId;  // Font name index
 
     poMapFile->ReadFontDef(m_nFontDefIndex, &m_sFontDef);
 
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      *----------------------------------------------------------------*/
+    double dX = 0.0;
+    double dY = 0.0;
     poMapFile->Int2Coordsys(poPointHdr->m_nX, poPointHdr->m_nY, dX, dY);
-    poGeometry = new OGRPoint(dX, dY);
+    OGRGeometry *poGeometry = new OGRPoint(dX, dY);
 
     SetGeometryDirectly(poGeometry);
 
@@ -1458,10 +1354,6 @@ int TABFontPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                          GBool bCoordBlockDataOnly /*=FALSE*/,
                                          TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    GInt32              nX, nY;
-    OGRGeometry         *poGeom;
-    OGRPoint            *poPoint;
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -1475,9 +1367,10 @@ int TABFontPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
-        poPoint = (OGRPoint*)poGeom;
+        poPoint = (OGRPoint *)poGeom;
     else
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1485,6 +1378,8 @@ int TABFontPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         return -1;
     }
 
+    GInt32 nX = 0;
+    GInt32 nY = 0;
     poMapFile->Coordsys2Int(poPoint->getX(), poPoint->getY(), nX, nY);
 
     /*-----------------------------------------------------------------
@@ -1517,7 +1412,7 @@ int TABFontPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
 
     // Write Font Def
     m_nFontDefIndex = poMapFile->WriteFontDef(&m_sFontDef);
-    poPointHdr->m_nFontId = (GByte)m_nFontDefIndex;      // Font name index
+    poPointHdr->m_nFontId = (GByte)m_nFontDefIndex;  // Font name index
 
     if (CPLGetLastErrorNo() != 0)
         return -1;
@@ -1534,15 +1429,15 @@ int TABFontPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
  **********************************************************************/
 GBool TABFontPoint::QueryFontStyle(TABFontStyle eStyleToQuery)
 {
-    return (m_nFontStyle & (int)eStyleToQuery) ? TRUE: FALSE;
+    return (m_nFontStyle & (int)eStyleToQuery) ? TRUE : FALSE;
 }
 
 void TABFontPoint::ToggleFontStyle(TABFontStyle eStyleToToggle, GBool bStyleOn)
 {
     if (bStyleOn)
-        m_nFontStyle |=  (int)eStyleToToggle;
+        m_nFontStyle |= (int)eStyleToToggle;
     else
-        m_nFontStyle &=  ~(int)eStyleToToggle;
+        m_nFontStyle &= ~(int)eStyleToToggle;
 }
 
 /**********************************************************************
@@ -1566,12 +1461,12 @@ int TABFontPoint::GetFontStyleMIFValue()
 {
     // The conversion is simply to remove bit 0x100 from the value and shift
     // down all values past this bit.
-    return (m_nFontStyle & 0xff) + (m_nFontStyle & (0xff00-0x0100))/2;
+    return (m_nFontStyle & 0xff) + (m_nFontStyle & (0xff00 - 0x0100)) / 2;
 }
 
-void TABFontPoint:: SetFontStyleMIFValue(int nStyle)
+void TABFontPoint::SetFontStyleMIFValue(int nStyle)
 {
-    m_nFontStyle = (GByte)((nStyle & 0xff) + (nStyle & 0x7f00)*2);
+    m_nFontStyle = (GByte)((nStyle & 0xff) + (nStyle & 0x7f00) * 2);
 }
 
 /**********************************************************************
@@ -1582,13 +1477,14 @@ void TABFontPoint:: SetFontStyleMIFValue(int nStyle)
  **********************************************************************/
 void TABFontPoint::SetSymbolAngle(double dAngle)
 {
-    while(dAngle < 0.0)   dAngle += 360.0;
-    while(dAngle > 360.0) dAngle -= 360.0;
+    while(dAngle < 0.0)
+        dAngle += 360.0;
+    while(dAngle > 360.0)
+        dAngle -= 360.0;
 
     m_dAngle = dAngle;
 }
 
-
 /**********************************************************************
  *                   TABFontPoint::GetStyleString()
  *
@@ -1602,11 +1498,12 @@ const char *TABFontPoint::GetStyleString()
     {
         /* Get the SymbolStyleString, and add the outline Color
            (halo/border in MapInfo Symbol terminology) */
-        char *pszSymbolStyleString = CPLStrdup(GetSymbolStyleString(GetSymbolAngle()));
+        char *pszSymbolStyleString =
+            CPLStrdup(GetSymbolStyleString(GetSymbolAngle()));
         int nStyleStringlen = static_cast<int>(strlen(pszSymbolStyleString));
-        pszSymbolStyleString[nStyleStringlen-1] = '\0';
+        pszSymbolStyleString[nStyleStringlen - 1] = '\0';
 
-        const char *outlineColor;
+        const char *outlineColor = NULL;
         if (m_nFontStyle & 16)
             outlineColor = ",o:#000000";
         else if (m_nFontStyle & 512)
@@ -1614,40 +1511,35 @@ const char *TABFontPoint::GetStyleString()
         else
             outlineColor = "";
 
-        m_pszStyleString = CPLStrdup(CPLSPrintf("%s%s)",
-                                                pszSymbolStyleString,
-                                                outlineColor));
+        m_pszStyleString =
+            CPLStrdup(CPLSPrintf("%s%s)", pszSymbolStyleString, outlineColor));
         CPLFree(pszSymbolStyleString);
     }
 
     return m_pszStyleString;
 }
 
-
 /*=====================================================================
  *                      class TABCustomPoint
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABCustomPoint::TABCustomPoint()
  *
  * Constructor.
  **********************************************************************/
-TABCustomPoint::TABCustomPoint(OGRFeatureDefn *poDefnIn):
-                    TABPoint(poDefnIn)
-{
-    m_nUnknown_ = m_nCustomStyle = 0;
-}
+TABCustomPoint::TABCustomPoint(OGRFeatureDefn *poDefnIn) :
+    TABPoint(poDefnIn),
+    m_nCustomStyle(0),
+    m_nUnknown_(0)
+{}
 
 /**********************************************************************
  *                   TABCustomPoint::~TABCustomPoint()
  *
  * Destructor.
  **********************************************************************/
-TABCustomPoint::~TABCustomPoint()
-{
-}
+TABCustomPoint::~TABCustomPoint() {}
 
 /**********************************************************************
  *                     TABCustomPoint::CloneTABFeature()
@@ -1657,13 +1549,13 @@ TABCustomPoint::~TABCustomPoint()
  * This method calls the generic TABFeature::CloneTABFeature() and
  * then copies any members specific to its own type.
  **********************************************************************/
-TABFeature *TABCustomPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
+TABFeature *TABCustomPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
 {
     /*-----------------------------------------------------------------
      * Alloc new feature and copy the base stuff
      *----------------------------------------------------------------*/
-    TABCustomPoint *poNew = new TABCustomPoint(poNewDefn ? poNewDefn :
-                                                           GetDefnRef());
+    TABCustomPoint *poNew =
+        new TABCustomPoint(poNewDefn ? poNewDefn : GetDefnRef());
 
     CopyTABFeatureBase(poNew);
 
@@ -1676,7 +1568,7 @@ TABFeature *TABCustomPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
     // ITABFeatureFont
     *(poNew->GetFontDefRef()) = *GetFontDefRef();
 
-    poNew->SetCustomSymbolStyle( GetCustomSymbolStyle() );
+    poNew->SetCustomSymbolStyle(GetCustomSymbolStyle());
 
     return poNew;
 }
@@ -1698,9 +1590,6 @@ int TABCustomPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                             GBool bCoordBlockDataOnly /*=FALSE*/,
                                             TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    double              dX, dY;
-    OGRGeometry         *poGeometry;
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -1711,11 +1600,12 @@ int TABCustomPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     m_nMapInfoType = poObjHdr->m_nType;
 
     if (m_nMapInfoType != TAB_GEOM_CUSTOMSYMBOL &&
-        m_nMapInfoType != TAB_GEOM_CUSTOMSYMBOL_C )
+        m_nMapInfoType != TAB_GEOM_CUSTOMSYMBOL_C)
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
-           "ReadGeometryFromMAPFile(): unsupported geometry type %d (0x%2.2x)",
-                 m_nMapInfoType, m_nMapInfoType);
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
+            "ReadGeometryFromMAPFile(): unsupported geometry type %d (0x%2.2x)",
+            m_nMapInfoType, m_nMapInfoType);
         return -1;
     }
 
@@ -1724,21 +1614,23 @@ int TABCustomPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      *----------------------------------------------------------------*/
     TABMAPObjCustomPoint *poPointHdr = (TABMAPObjCustomPoint *)poObjHdr;
 
-    m_nUnknown_    = poPointHdr->m_nUnknown_;   // ???
-    m_nCustomStyle = poPointHdr->m_nCustomStyle;// 0x01=Show BG,
-                                                // 0x02=Apply Color
+    m_nUnknown_ = poPointHdr->m_nUnknown_;        // ???
+    m_nCustomStyle = poPointHdr->m_nCustomStyle;  // 0x01=Show BG,
+                                                  // 0x02=Apply Color
 
-    m_nSymbolDefIndex = poPointHdr->m_nSymbolId;   // Symbol index
+    m_nSymbolDefIndex = poPointHdr->m_nSymbolId;  // Symbol index
     poMapFile->ReadSymbolDef(m_nSymbolDefIndex, &m_sSymbolDef);
 
-    m_nFontDefIndex = poPointHdr->m_nFontId;    // Font index
+    m_nFontDefIndex = poPointHdr->m_nFontId;  // Font index
     poMapFile->ReadFontDef(m_nFontDefIndex, &m_sFontDef);
 
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      *----------------------------------------------------------------*/
+    double dX = 0.0;
+    double dY = 0.0;
     poMapFile->Int2Coordsys(poPointHdr->m_nX, poPointHdr->m_nY, dX, dY);
-    poGeometry = new OGRPoint(dX, dY);
+    OGRGeometry *poGeometry = new OGRPoint(dX, dY);
 
     SetGeometryDirectly(poGeometry);
 
@@ -1765,10 +1657,6 @@ int TABCustomPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                            GBool bCoordBlockDataOnly /*=FALSE*/,
                                            TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    GInt32              nX, nY;
-    OGRGeometry         *poGeom;
-    OGRPoint            *poPoint;
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -1782,9 +1670,10 @@ int TABCustomPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
-        poPoint = (OGRPoint*)poGeom;
+        poPoint = (OGRPoint *)poGeom;
     else
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1792,6 +1681,8 @@ int TABCustomPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         return -1;
     }
 
+    GInt32 nX = 0;
+    GInt32 nY = 0;
     poMapFile->Coordsys2Int(poPoint->getX(), poPoint->getY(), nX, nY);
 
     /*-----------------------------------------------------------------
@@ -1803,14 +1694,14 @@ int TABCustomPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     poPointHdr->m_nY = nY;
     poPointHdr->SetMBR(nX, nY, nX, nY);
     poPointHdr->m_nUnknown_ = m_nUnknown_;
-    poPointHdr->m_nCustomStyle = m_nCustomStyle;// 0x01=Show BG,
-                                               // 0x02=Apply Color
+    poPointHdr->m_nCustomStyle = m_nCustomStyle;  // 0x01=Show BG,
+                                                  // 0x02=Apply Color
 
     m_nSymbolDefIndex = poMapFile->WriteSymbolDef(&m_sSymbolDef);
-    poPointHdr->m_nSymbolId = (GByte)m_nSymbolDefIndex;      // Symbol index
+    poPointHdr->m_nSymbolId = (GByte)m_nSymbolDefIndex;  // Symbol index
 
     m_nFontDefIndex = poMapFile->WriteFontDef(&m_sFontDef);
-    poPointHdr->m_nFontId = (GByte)m_nFontDefIndex;      // Font index
+    poPointHdr->m_nFontId = (GByte)m_nFontDefIndex;  // Font index
 
     if (CPLGetLastErrorNo() != 0)
         return -1;
@@ -1818,7 +1709,6 @@ int TABCustomPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABCustomPoint::GetStyleString()
  *
@@ -1840,30 +1730,26 @@ const char *TABCustomPoint::GetStyleString()
  *                      class TABPolyline
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABPolyline::TABPolyline()
  *
  * Constructor.
  **********************************************************************/
-TABPolyline::TABPolyline(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
-{
-    m_bCenterIsSet = FALSE;
-    m_bSmooth = FALSE;
-    m_bWriteTwoPointLineAsPolyline = FALSE;
-    m_dCenterX = 0;
-    m_dCenterY = 0;
-}
+TABPolyline::TABPolyline(OGRFeatureDefn *poDefnIn) :
+    TABFeature(poDefnIn),
+    m_bCenterIsSet(FALSE),
+    m_dCenterX(0.0),
+    m_dCenterY(0.0),
+    m_bWriteTwoPointLineAsPolyline(FALSE),
+    m_bSmooth(FALSE)
+{}
 
 /**********************************************************************
  *                   TABPolyline::~TABPolyline()
  *
  * Destructor.
  **********************************************************************/
-TABPolyline::~TABPolyline()
-{
-}
+TABPolyline::~TABPolyline() {}
 
 /**********************************************************************
  *                     TABPolyline::CloneTABFeature()
@@ -1873,7 +1759,7 @@ TABPolyline::~TABPolyline()
  * This method calls the generic TABFeature::CloneTABFeature() and
  * then copies any members specific to its own type.
  **********************************************************************/
-TABFeature *TABPolyline::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
+TABFeature *TABPolyline::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
 {
     /*-----------------------------------------------------------------
      * Alloc new feature and copy the base stuff
@@ -1905,10 +1791,9 @@ TABFeature *TABPolyline::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
  **********************************************************************/
 int TABPolyline::GetNumParts()
 {
-    OGRGeometry         *poGeom;
-    int                 numParts = 0;
+    int numParts = 0;
 
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
     {
         /*-------------------------------------------------------------
@@ -1921,7 +1806,7 @@ int TABPolyline::GetNumParts()
         /*-------------------------------------------------------------
          * Multiple polyline
          *------------------------------------------------------------*/
-        OGRMultiLineString *poMultiLine = (OGRMultiLineString*)poGeom;
+        OGRMultiLineString *poMultiLine = (OGRMultiLineString *)poGeom;
         numParts = poMultiLine->getNumGeometries();
     }
 
@@ -1939,9 +1824,7 @@ int TABPolyline::GetNumParts()
  **********************************************************************/
 OGRLineString *TABPolyline::GetPartRef(int nPartIndex)
 {
-    OGRGeometry         *poGeom;
-
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString && nPartIndex==0)
     {
         /*-------------------------------------------------------------
@@ -1954,7 +1837,7 @@ OGRLineString *TABPolyline::GetPartRef(int nPartIndex)
         /*-------------------------------------------------------------
          * Multiple polyline
          *------------------------------------------------------------*/
-        OGRMultiLineString *poMultiLine = (OGRMultiLineString*)poGeom;
+        OGRMultiLineString *poMultiLine = (OGRMultiLineString *)poGeom;
         if (nPartIndex >= 0 &&
             nPartIndex < poMultiLine->getNumGeometries())
         {
@@ -1979,13 +1862,10 @@ OGRLineString *TABPolyline::GetPartRef(int nPartIndex)
  **********************************************************************/
 TABGeomType TABPolyline::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry   *poGeom;
-    OGRMultiLineString *poMultiLine = NULL;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
     {
         /*-------------------------------------------------------------
@@ -2026,14 +1906,13 @@ TABGeomType TABPolyline::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
         /*-------------------------------------------------------------
          * Multiple polyline... validate all components
          *------------------------------------------------------------*/
-        int iLine, numLines;
         GInt32 numPointsTotal = 0;
-        poMultiLine = (OGRMultiLineString*)poGeom;
-        numLines = poMultiLine->getNumGeometries();
+        OGRMultiLineString *poMultiLine = (OGRMultiLineString *)poGeom;
+        int numLines = poMultiLine->getNumGeometries();
 
         m_nMapInfoType = TAB_GEOM_MULTIPLINE;
 
-        for(iLine=0; iLine < numLines; iLine++)
+        for( int iLine = 0; iLine < numLines; iLine++ )
         {
             poGeom = poMultiLine->getGeometryRef(iLine);
             if (poGeom && wkbFlatten(poGeom->getGeometryType()) != wkbLineString)
@@ -2044,7 +1923,7 @@ TABGeomType TABPolyline::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
                 numPointsTotal = 0;
                 break;
             }
-            OGRLineString *poLine = (OGRLineString*)poGeom;
+            OGRLineString *poLine = (OGRLineString *)poGeom;
             numPointsTotal += poLine->getNumPoints();
         }
 
@@ -2082,7 +1961,6 @@ TABGeomType TABPolyline::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
     return m_nMapInfoType;
 }
 
-
 /**********************************************************************
  *                   TABPolyline::ReadGeometryFromMAPFile()
  *
@@ -2100,12 +1978,18 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                          GBool bCoordBlockDataOnly /*=FALSE*/,
                                          TABMAPCoordBlock **ppoCoordBlock/*=NULL*/)
 {
-    GInt32              nX, nY;
-    double              dX, dY, dXMin, dYMin, dXMax, dYMax;
-    OGRGeometry         *poGeometry;
-    OGRLineString       *poLine;
-    GBool               bComprCoord = poObjHdr->IsCompressedType();
-    TABMAPCoordBlock    *poCoordBlock = NULL;
+    GInt32 nX = 0;
+    GInt32 nY = 0;
+    double dX = 0.0;
+    double dY = 0.0;
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
+    OGRGeometry *poGeometry = NULL;
+    OGRLineString *poLine = NULL;
+    GBool bComprCoord = poObjHdr->IsCompressedType();
+    TABMAPCoordBlock *poCoordBlock = NULL;
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry type
@@ -2113,7 +1997,7 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     m_nMapInfoType = poObjHdr->m_nType;
 
     if (m_nMapInfoType == TAB_GEOM_LINE ||
-        m_nMapInfoType == TAB_GEOM_LINE_C )
+        m_nMapInfoType == TAB_GEOM_LINE_C)
     {
         /*=============================================================
          * LINE (2 vertices)
@@ -2122,7 +2006,8 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         m_bSmooth = FALSE;
 
-        poGeometry = poLine = new OGRLineString();
+        poLine = new OGRLineString();
+        poGeometry = poLine;
         poLine->setNumPoints(2);
 
         poMapFile->Int2Coordsys(poLineHdr->m_nX1, poLineHdr->m_nY1,
@@ -2135,7 +2020,7 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         if (!bCoordBlockDataOnly)
         {
-            m_nPenDefIndex = poLineHdr->m_nPenId;      // Pen index
+            m_nPenDefIndex = poLineHdr->m_nPenId;  // Pen index
             poMapFile->ReadPenDef(m_nPenDefIndex, &m_sPenDef);
         }
     }
@@ -2145,19 +2030,16 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         /*=============================================================
          * PLINE ( > 2 vertices)
          *============================================================*/
-        int     i, numPoints, nStatus;
-        GUInt32 nCoordDataSize;
-        GInt32  nCoordBlockPtr;
 
         /*-------------------------------------------------------------
          * Copy data from poObjHdr
          *------------------------------------------------------------*/
         TABMAPObjPLine *poPLineHdr = (TABMAPObjPLine *)poObjHdr;
 
-        nCoordBlockPtr  = poPLineHdr->m_nCoordBlockPtr;
-        nCoordDataSize  = poPLineHdr->m_nCoordDataSize;
-        //numLineSections = poPLineHdr->m_numLineSections; // Always 1
-        m_bSmooth       = poPLineHdr->m_bSmooth;
+        GInt32 nCoordBlockPtr = poPLineHdr->m_nCoordBlockPtr;
+        const GUInt32 nCoordDataSize = poPLineHdr->m_nCoordDataSize;
+        // numLineSections = poPLineHdr->m_numLineSections; // Always 1
+        m_bSmooth = poPLineHdr->m_bSmooth;
 
         // Centroid/label point
         poMapFile->Int2Coordsys(poPLineHdr->m_nLabelX, poPLineHdr->m_nLabelY,
@@ -2176,14 +2058,14 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         if (!bCoordBlockDataOnly)
         {
-            m_nPenDefIndex = poPLineHdr->m_nPenId;        // Pen index
+            m_nPenDefIndex = poPLineHdr->m_nPenId;  // Pen index
             poMapFile->ReadPenDef(m_nPenDefIndex, &m_sPenDef);
         }
 
         /*-------------------------------------------------------------
          * Create Geometry and read coordinates
          *------------------------------------------------------------*/
-        numPoints = nCoordDataSize/(bComprCoord?4:8);
+        const int numPoints = nCoordDataSize / (bComprCoord ? 4 : 8);
 
         if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
             poCoordBlock = *ppoCoordBlock;
@@ -2199,11 +2081,12 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         poCoordBlock->SetComprCoordOrigin(m_nComprOrgX, m_nComprOrgY);
 
-        poGeometry = poLine = new OGRLineString();
+        poLine = new OGRLineString();
+        poGeometry = poLine;
         poLine->setNumPoints(numPoints);
 
-        nStatus = 0;
-        for(i=0; nStatus == 0 && i<numPoints; i++)
+        int nStatus = 0;
+        for( int i = 0; nStatus == 0 && i<numPoints; i++ )
         {
             nStatus = poCoordBlock->ReadIntCoord(bComprCoord, nX, nY);
             if (nStatus != 0)
@@ -2218,7 +2101,6 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             delete poGeometry;
             return nStatus;
         }
-
     }
     else if (m_nMapInfoType == TAB_GEOM_MULTIPLINE ||
              m_nMapInfoType == TAB_GEOM_MULTIPLINE_C ||
@@ -2230,22 +2112,17 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         /*=============================================================
          * PLINE MULTIPLE
          *============================================================*/
-        int     i, iSection;
-        GInt32  nCoordBlockPtr, numLineSections;
-        GInt32  /* nCoordDataSize, */ numPointsTotal, *panXY;
-        OGRMultiLineString      *poMultiLine;
-        TABMAPCoordSecHdr       *pasSecHdrs;
-        int nVersion = TAB_GEOM_GET_VERSION(m_nMapInfoType);
+        const int nVersion = TAB_GEOM_GET_VERSION(m_nMapInfoType);
 
         /*-------------------------------------------------------------
          * Copy data from poObjHdr
          *------------------------------------------------------------*/
         TABMAPObjPLine *poPLineHdr = (TABMAPObjPLine *)poObjHdr;
 
-        nCoordBlockPtr  = poPLineHdr->m_nCoordBlockPtr;
-        /* nCoordDataSize  = poPLineHdr->m_nCoordDataSize; */
-        numLineSections = poPLineHdr->m_numLineSections;
-        m_bSmooth       = poPLineHdr->m_bSmooth;
+        GInt32 nCoordBlockPtr = poPLineHdr->m_nCoordBlockPtr;
+        /* GInt32 nCoordDataSize  = poPLineHdr->m_nCoordDataSize; */
+        GInt32 numLineSections = poPLineHdr->m_numLineSections;
+        m_bSmooth = poPLineHdr->m_bSmooth;
 
         // Centroid/label point
         poMapFile->Int2Coordsys(poPLineHdr->m_nLabelX, poPLineHdr->m_nLabelY,
@@ -2264,15 +2141,16 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         if (!bCoordBlockDataOnly)
         {
-            m_nPenDefIndex = poPLineHdr->m_nPenId;        // Pen index
+            m_nPenDefIndex = poPLineHdr->m_nPenId;  // Pen index
             poMapFile->ReadPenDef(m_nPenDefIndex, &m_sPenDef);
         }
 
         /*-------------------------------------------------------------
          * Read data from the coord. block
          *------------------------------------------------------------*/
-        pasSecHdrs = (TABMAPCoordSecHdr*)VSI_MALLOC2_VERBOSE(numLineSections,
-                                                   sizeof(TABMAPCoordSecHdr));
+        TABMAPCoordSecHdr *pasSecHdrs =
+            (TABMAPCoordSecHdr *)VSI_MALLOC2_VERBOSE(numLineSections,
+                                                     sizeof(TABMAPCoordSecHdr));
         if( pasSecHdrs == NULL )
             return -1;
 
@@ -2281,6 +2159,7 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         else
             poCoordBlock = poMapFile->GetCoordBlock(nCoordBlockPtr);
 
+        GInt32 numPointsTotal = 0;
         if (poCoordBlock == NULL ||
             poCoordBlock->ReadCoordSecHdrs(bComprCoord, nVersion,
                                            numLineSections,
@@ -2295,14 +2174,15 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         poCoordBlock->SetComprCoordOrigin(m_nComprOrgX, m_nComprOrgY);
 
-        panXY = (GInt32*)VSI_MALLOC2_VERBOSE(numPointsTotal,2*sizeof(GInt32));
+        GInt32 *panXY = static_cast<GInt32 *>(
+            VSI_MALLOC2_VERBOSE(numPointsTotal, 2 * sizeof(GInt32)));
         if( panXY == NULL )
         {
             CPLFree(pasSecHdrs);
             return -1;
         }
 
-        if (poCoordBlock->ReadIntCoords(bComprCoord,numPointsTotal,panXY) != 0)
+        if (poCoordBlock->ReadIntCoords(bComprCoord, numPointsTotal, panXY) != 0)
         {
             CPLError(CE_Failure, CPLE_FileIO,
                      "Failed reading coordinate data at offset %d",
@@ -2317,34 +2197,33 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
          * each coordinates section
          * If object contains only one section, then return a simple LineString
          *------------------------------------------------------------*/
+        OGRMultiLineString *poMultiLine = NULL;
         if (numLineSections > 1)
-            poGeometry = poMultiLine = new OGRMultiLineString();
-        else
-            poGeometry = poMultiLine = NULL;
-
-        for(iSection=0; iSection<numLineSections; iSection++)
         {
-            GInt32 *pnXYPtr;
-            int     numSectionVertices;
+            poMultiLine = new OGRMultiLineString();
+            poGeometry = poMultiLine;
+        }
 
-            numSectionVertices = pasSecHdrs[iSection].numVertices;
-            pnXYPtr = panXY + (pasSecHdrs[iSection].nVertexOffset * 2);
+        for( int iSection = 0; iSection < numLineSections; iSection++ )
+        {
+            const int numSectionVertices = pasSecHdrs[iSection].numVertices;
+            GInt32 *pnXYPtr = panXY + (pasSecHdrs[iSection].nVertexOffset * 2);
 
             poLine = new OGRLineString();
             poLine->setNumPoints(numSectionVertices);
 
-            for(i=0; i<numSectionVertices; i++)
+            for( int i = 0; i < numSectionVertices; i++ )
             {
-                poMapFile->Int2Coordsys(*pnXYPtr, *(pnXYPtr+1), dX, dY);
+                poMapFile->Int2Coordsys(*pnXYPtr, *(pnXYPtr + 1), dX, dY);
                 poLine->setPoint(i, dX, dY);
                 pnXYPtr += 2;
             }
 
-            if (poGeometry==NULL)
+            if (poGeometry == NULL)
                 poGeometry = poLine;
             else if (poMultiLine->addGeometryDirectly(poLine) != OGRERR_NONE)
             {
-                CPLAssert(FALSE); // Just in case lower-level lib is modified
+                CPLAssert(false);  // Just in case lower-level lib is modified
             }
             poLine = NULL;
         }
@@ -2354,9 +2233,10 @@ int TABPolyline::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     }
     else
     {
-        CPLError(CE_Failure, CPLE_AssertionFailed,
-           "ReadGeometryFromMAPFile(): unsupported geometry type %d (0x%2.2x)",
-                 m_nMapInfoType, m_nMapInfoType);
+        CPLError(
+            CE_Failure, CPLE_AssertionFailed,
+            "ReadGeometryFromMAPFile(): unsupported geometry type %d (0x%2.2x)",
+            m_nMapInfoType, m_nMapInfoType);
         return -1;
     }
 
@@ -2391,10 +2271,10 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                         GBool bCoordBlockDataOnly /*=FALSE*/,
                                         TABMAPCoordBlock **ppoCoordBlock/*=NULL*/)
 {
-    GInt32              nX, nY;
-    OGRGeometry         *poGeom;
-    OGRLineString       *poLine=NULL;
-    TABMAPCoordBlock    *poCoordBlock = NULL;
+    GInt32 nX = 0;
+    GInt32 nY = 0;
+    OGRLineString *poLine = NULL;
+    TABMAPCoordBlock *poCoordBlock = NULL;
 
     /*-----------------------------------------------------------------
      * We assume that ValidateMapInfoType() was called already and that
@@ -2406,7 +2286,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
 
     if ((m_nMapInfoType == TAB_GEOM_LINE ||
          m_nMapInfoType == TAB_GEOM_LINE_C ) &&
@@ -2430,7 +2310,6 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             m_nPenDefIndex = poMapFile->WritePenDef(&m_sPenDef);
             poLineHdr->m_nPenId = (GByte)m_nPenDefIndex;      // Pen index
         }
-
     }
     else if ((m_nMapInfoType == TAB_GEOM_PLINE ||
               m_nMapInfoType == TAB_GEOM_PLINE_C ) &&
@@ -2439,16 +2318,13 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         /*=============================================================
          * PLINE ( > 2 vertices and less than 32767 vertices)
          *============================================================*/
-        int     i, numPoints, nStatus;
-        GUInt32 nCoordDataSize;
-        GInt32  nCoordBlockPtr;
-        GBool   bCompressed = poObjHdr->IsCompressedType();
+        GBool bCompressed = poObjHdr->IsCompressedType();
 
         /*-------------------------------------------------------------
          * Process geometry first...
          *------------------------------------------------------------*/
         poLine = (OGRLineString*)poGeom;
-        numPoints = poLine->getNumPoints();
+        const int numPoints = poLine->getNumPoints();
         CPLAssert(numPoints <= TAB_REGION_PLINE_300_MAX_VERTICES);
 
         if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
@@ -2456,11 +2332,11 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         else
             poCoordBlock = poMapFile->GetCurCoordBlock();
         poCoordBlock->StartNewFeature();
-        nCoordBlockPtr = poCoordBlock->GetCurAddress();
+        const GInt32 nCoordBlockPtr = poCoordBlock->GetCurAddress();
         poCoordBlock->SetComprCoordOrigin(m_nComprOrgX, m_nComprOrgY);
 
-        nStatus = 0;
-        for(i=0; nStatus == 0 && i<numPoints; i++)
+        int nStatus = 0;
+        for( int i = 0; nStatus == 0 && i<numPoints; i++ )
         {
             poMapFile->Coordsys2Int(poLine->getX(i), poLine->getY(i), nX, nY);
             if ((nStatus = poCoordBlock->WriteIntCoord(nX, nY,
@@ -2471,7 +2347,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             }
         }
 
-        nCoordDataSize = poCoordBlock->GetFeatureDataSize();
+        const GUInt32 nCoordDataSize = poCoordBlock->GetFeatureDataSize();
 
         /*-------------------------------------------------------------
          * Copy info to poObjHdr
@@ -2488,7 +2364,8 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         poPLineHdr->SetMBR(m_nXMin, m_nYMin, m_nXMax, m_nYMax);
 
         // Polyline center/label point
-        double dX, dY;
+        double dX = 0.0;
+        double dY = 0.0;
         if (GetCenter(dX, dY) != -1)
         {
             poMapFile->Coordsys2Int(dX, dY, poPLineHdr->m_nLabelX,
@@ -2509,7 +2386,6 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             m_nPenDefIndex = poMapFile->WritePenDef(&m_sPenDef);
             poPLineHdr->m_nPenId = (GByte)m_nPenDefIndex;      // Pen index
         }
-
     }
     else if ((m_nMapInfoType == TAB_GEOM_MULTIPLINE ||
               m_nMapInfoType == TAB_GEOM_MULTIPLINE_C ||
@@ -2523,14 +2399,6 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         /*=============================================================
          * PLINE MULTIPLE (or single PLINE with more than 32767 vertices)
          *============================================================*/
-        int     nStatus=0, i, iLine;
-        GInt32  numPointsTotal, numPoints;
-        GUInt32 nCoordDataSize;
-        GInt32  nCoordBlockPtr, numLines;
-        OGRMultiLineString      *poMultiLine=NULL;
-        TABMAPCoordSecHdr       *pasSecHdrs;
-        OGREnvelope             sEnvelope;
-        GBool   bCompressed = poObjHdr->IsCompressedType();
 
         CPLAssert(m_nMapInfoType == TAB_GEOM_MULTIPLINE ||
                   m_nMapInfoType == TAB_GEOM_MULTIPLINE_C ||
@@ -2538,6 +2406,11 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                   m_nMapInfoType == TAB_GEOM_V450_MULTIPLINE_C ||
                   m_nMapInfoType == TAB_GEOM_V800_MULTIPLINE ||
                   m_nMapInfoType == TAB_GEOM_V800_MULTIPLINE_C);
+
+        int nStatus = 0;
+        OGREnvelope sEnvelope;
+        GBool bCompressed = poObjHdr->IsCompressedType();
+
         /*-------------------------------------------------------------
          * Process geometry first...
          *------------------------------------------------------------*/
@@ -2546,25 +2419,27 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         else
             poCoordBlock = poMapFile->GetCurCoordBlock();
         poCoordBlock->StartNewFeature();
-        nCoordBlockPtr = poCoordBlock->GetCurAddress();
+        const GInt32 nCoordBlockPtr = poCoordBlock->GetCurAddress();
         poCoordBlock->SetComprCoordOrigin(m_nComprOrgX, m_nComprOrgY);
 
+        OGRMultiLineString *poMultiLine = NULL;
+        GInt32 numLines = 1;
         if (wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString)
         {
             poMultiLine = (OGRMultiLineString*)poGeom;
             numLines = poMultiLine->getNumGeometries();
         }
-        else
-        {
-            poMultiLine = NULL;
-            numLines = 1;
-        }
+        // else
+        // {
+        //     poMultiLine = NULL;
+        //     numLines = 1;
+        // }
 
         /*-------------------------------------------------------------
          * Build and write array of coord sections headers
          *------------------------------------------------------------*/
-        pasSecHdrs = (TABMAPCoordSecHdr*)VSI_CALLOC_VERBOSE(numLines,
-                                                   sizeof(TABMAPCoordSecHdr));
+        TABMAPCoordSecHdr *pasSecHdrs = (TABMAPCoordSecHdr*)
+            VSI_CALLOC_VERBOSE(numLines, sizeof(TABMAPCoordSecHdr));
         if( pasSecHdrs == NULL )
         {
             return -1;
@@ -2577,14 +2452,11 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
          *------------------------------------------------------------*/
         int nVersion = TAB_GEOM_GET_VERSION(m_nMapInfoType);
 
-        int nTotalHdrSizeUncompressed;
-        if (nVersion >= 450)
-            nTotalHdrSizeUncompressed = 28 * numLines;
-        else
-            nTotalHdrSizeUncompressed = 24 * numLines;
+        const int nTotalHdrSizeUncompressed =
+            (nVersion >= 450 ? 28 : 24) * numLines;
 
-        numPointsTotal = 0;
-        for(iLine=0; iLine < numLines; iLine++)
+        GInt32 numPointsTotal = 0;
+        for( int iLine = 0; iLine < numLines; iLine++ )
         {
             if (poMultiLine)
                 poGeom = poMultiLine->getGeometryRef(iLine);
@@ -2592,7 +2464,7 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
             {
                 poLine = (OGRLineString*)poGeom;
-                numPoints = poLine->getNumPoints();
+                const GInt32 numPoints = poLine->getNumPoints();
                 poLine->getEnvelope(&sEnvelope);
 
                 pasSecHdrs[iLine].numVertices = poLine->getNumPoints();
@@ -2616,7 +2488,6 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                          "TABPolyline: Object contains an invalid Geometry!");
                 nStatus = -1;
             }
-
         }
 
         if (nStatus == 0)
@@ -2632,17 +2503,17 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         /*-------------------------------------------------------------
          * Then write the coordinates themselves...
          *------------------------------------------------------------*/
-        for(iLine=0; nStatus == 0 && iLine < numLines; iLine++)
+        for( int iLine = 0; nStatus == 0 && iLine < numLines; iLine++ )
         {
-            if (poMultiLine)
+            if( poMultiLine )
                 poGeom = poMultiLine->getGeometryRef(iLine);
 
-            if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
+            if( poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
             {
                 poLine = (OGRLineString*)poGeom;
-                numPoints = poLine->getNumPoints();
+                GInt32 numPoints = poLine->getNumPoints();
 
-                for(i=0; nStatus == 0 && i<numPoints; i++)
+                for( int i = 0; nStatus == 0 && i<numPoints; i++ )
                 {
                     poMapFile->Coordsys2Int(poLine->getX(i), poLine->getY(i),
                                             nX, nY);
@@ -2660,10 +2531,9 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                          "TABPolyline: Object contains an invalid Geometry!");
                 return -1;
             }
-
         }
 
-        nCoordDataSize = poCoordBlock->GetFeatureDataSize();
+        const GUInt32 nCoordDataSize = poCoordBlock->GetFeatureDataSize();
 
         /*-------------------------------------------------------------
          * ... and finally copy info to poObjHdr
@@ -2680,7 +2550,8 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         poPLineHdr->SetMBR(m_nXMin, m_nYMin, m_nXMax, m_nYMax);
 
         // Polyline center/label point
-        double dX, dY;
+        double dX = 0.0;
+        double dY = 0.0;
         if (GetCenter(dX, dY) != -1)
         {
             poMapFile->Coordsys2Int(dX, dY, poPLineHdr->m_nLabelX,
@@ -2701,7 +2572,6 @@ int TABPolyline::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             m_nPenDefIndex = poMapFile->WritePenDef(&m_sPenDef);
             poPLineHdr->m_nPenId = (GByte)m_nPenDefIndex;      // Pen index
         }
-
     }
     else
     {
@@ -2739,7 +2609,6 @@ const char *TABPolyline::GetStyleString()
     return m_pszStyleString;
 }
 
-
 /**********************************************************************
  *                   TABPolyline::DumpMIF()
  *
@@ -2747,7 +2616,6 @@ const char *TABPolyline::GetStyleString()
  **********************************************************************/
 void TABPolyline::DumpMIF(FILE *fpOut /*=NULL*/)
 {
-    OGRGeometry   *poGeom;
     OGRMultiLineString *poMultiLine = NULL;
     OGRLineString *poLine = NULL;
     int i, numPoints;
@@ -2758,7 +2626,7 @@ void TABPolyline::DumpMIF(FILE *fpOut /*=NULL*/)
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
     {
         /*-------------------------------------------------------------
@@ -2796,7 +2664,6 @@ void TABPolyline::DumpMIF(FILE *fpOut /*=NULL*/)
                          "TABPolyline: Object contains an invalid Geometry!");
                 return;
             }
-
         }
     }
     else
@@ -2829,14 +2696,13 @@ void TABPolyline::DumpMIF(FILE *fpOut /*=NULL*/)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABPolyline::GetCenter(double &dX, double &dY)
+int TABPolyline::GetCenter( double &dX, double &dY )
 {
     if (!m_bCenterIsSet)
     {
-        OGRGeometry     *poGeom;
-        OGRLineString   *poLine = NULL;
+        OGRLineString *poLine = NULL;
 
-        poGeom = GetGeometryRef();
+        OGRGeometry *poGeom = GetGeometryRef();
         if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
         {
             poLine = (OGRLineString *)poGeom;
@@ -2907,7 +2773,6 @@ void TABPolyline::TwoPointLineAsPolyline(GBool bTwoPointLineAsPolyline)
     m_bWriteTwoPointLineAsPolyline = bTwoPointLineAsPolyline;
 }
 
-
 /*=====================================================================
  *                      class TABRegion
  *====================================================================*/
@@ -2917,23 +2782,20 @@ void TABPolyline::TwoPointLineAsPolyline(GBool bTwoPointLineAsPolyline)
  *
  * Constructor.
  **********************************************************************/
-TABRegion::TABRegion(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
-{
-    m_bCenterIsSet = FALSE;
-    m_bSmooth = FALSE;
-    m_dCenterX = 0;
-    m_dCenterY = 0;
-}
+TABRegion::TABRegion(OGRFeatureDefn *poDefnIn) :
+    TABFeature(poDefnIn),
+    m_bSmooth(FALSE),
+    m_bCenterIsSet(FALSE),
+    m_dCenterX(0.0),
+    m_dCenterY(0.0)
+{}
 
 /**********************************************************************
  *                   TABRegion::~TABRegion()
  *
  * Destructor.
  **********************************************************************/
-TABRegion::~TABRegion()
-{
-}
+TABRegion::~TABRegion() {}
 
 /**********************************************************************
  *                     TABRegion::CloneTABFeature()
@@ -2981,16 +2843,15 @@ TABFeature *TABRegion::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
  **********************************************************************/
 TABGeomType TABRegion::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && (wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ||
                    wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon))
     {
-        GInt32 numPointsTotal=0, numRings=GetNumRings();
+        GInt32 numPointsTotal = 0;
+        GInt32 numRings = GetNumRings();
         for(int i=0; i<numRings; i++)
         {
             OGRLinearRing *poRing = GetRingRef(i);
@@ -3003,7 +2864,6 @@ TABGeomType TABRegion::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
             m_nMapInfoType = TAB_GEOM_V450_REGION;
         else
             m_nMapInfoType = TAB_GEOM_REGION;
-
     }
     else
     {
@@ -3037,10 +2897,12 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                        GBool bCoordBlockDataOnly /*=FALSE*/,
                                        TABMAPCoordBlock **ppoCoordBlock/*=NULL*/)
 {
-    double              dX, dY, dXMin, dYMin, dXMax, dYMax;
-    OGRGeometry         *poGeometry;
-    OGRLinearRing       *poRing;
-    TABMAPCoordBlock    *poCoordBlock = NULL;
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
+    OGRGeometry *poGeometry = NULL;
+    TABMAPCoordBlock *poCoordBlock = NULL;
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry type
@@ -3057,13 +2919,10 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         /*=============================================================
          * REGION (Similar to PLINE MULTIPLE)
          *============================================================*/
-        int     i, iSection;
-        GInt32  nCoordBlockPtr, numLineSections;
-        GInt32  /* nCoordDataSize, */ numPointsTotal, *panXY;
-        OGRMultiPolygon         *poMultiPolygon = NULL;
-        OGRPolygon              *poPolygon = NULL;
-        TABMAPCoordSecHdr       *pasSecHdrs;
-        GBool                   bComprCoord = poObjHdr->IsCompressedType();
+        GInt32 /* nCoordDataSize, */ numPointsTotal;
+        OGRMultiPolygon *poMultiPolygon = NULL;
+        OGRPolygon *poPolygon = NULL;
+        GBool bComprCoord = poObjHdr->IsCompressedType();
         int nVersion = TAB_GEOM_GET_VERSION(m_nMapInfoType);
 
         /*-------------------------------------------------------------
@@ -3071,12 +2930,14 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
          *------------------------------------------------------------*/
         TABMAPObjPLine *poPLineHdr = (TABMAPObjPLine *)poObjHdr;
 
-        nCoordBlockPtr  = poPLineHdr->m_nCoordBlockPtr;
+        GInt32 nCoordBlockPtr = poPLineHdr->m_nCoordBlockPtr;
         /* nCoordDataSize  = poPLineHdr->m_nCoordDataSize; */
-        numLineSections = poPLineHdr->m_numLineSections;
+        GInt32 numLineSections = poPLineHdr->m_numLineSections;
         m_bSmooth       = poPLineHdr->m_bSmooth;
 
         // Centroid/label point
+        double dX = 0.0;
+        double dY = 0.0;
         poMapFile->Int2Coordsys(poPLineHdr->m_nLabelX, poPLineHdr->m_nLabelY,
                                 dX, dY);
         SetCenter(dX, dY);
@@ -3093,17 +2954,17 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         if (!bCoordBlockDataOnly)
         {
-            m_nPenDefIndex = poPLineHdr->m_nPenId;        // Pen index
+            m_nPenDefIndex = poPLineHdr->m_nPenId;  // Pen index
             poMapFile->ReadPenDef(m_nPenDefIndex, &m_sPenDef);
-            m_nBrushDefIndex = poPLineHdr->m_nBrushId;    // Brush index
+            m_nBrushDefIndex = poPLineHdr->m_nBrushId;  // Brush index
             poMapFile->ReadBrushDef(m_nBrushDefIndex, &m_sBrushDef);
         }
 
         /*-------------------------------------------------------------
          * Read data from the coord. block
          *------------------------------------------------------------*/
-        pasSecHdrs = (TABMAPCoordSecHdr*)VSI_MALLOC2_VERBOSE(numLineSections,
-                                                   sizeof(TABMAPCoordSecHdr));
+        TABMAPCoordSecHdr *pasSecHdrs = static_cast<TABMAPCoordSecHdr *>(
+            VSI_MALLOC2_VERBOSE(numLineSections, sizeof(TABMAPCoordSecHdr)));
         if( pasSecHdrs == NULL )
             return -1;
 
@@ -3127,7 +2988,8 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             return -1;
         }
 
-        panXY = (GInt32*)VSI_MALLOC2_VERBOSE(numPointsTotal,2*sizeof(GInt32));
+        GInt32 *panXY = static_cast<GInt32 *>(
+            VSI_MALLOC2_VERBOSE(numPointsTotal, 2 * sizeof(GInt32)));
         if( panXY == NULL )
         {
             CPLFree(pasSecHdrs);
@@ -3159,7 +3021,7 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
          * be lost.
          *------------------------------------------------------------*/
         int numOuterRings = 0;
-        for(iSection=0; iSection<numLineSections; iSection++)
+        for( int iSection = 0; iSection < numLineSections; iSection++ )
         {
             // Count this as an outer ring.
             numOuterRings++;
@@ -3168,19 +3030,22 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         }
 
         if (numOuterRings > 1)
-            poGeometry = poMultiPolygon = new OGRMultiPolygon;
+        {
+            poMultiPolygon = new OGRMultiPolygon;
+            poGeometry = poMultiPolygon;
+        }
         else
+        {
             poGeometry = NULL;  // Will be set later
+        }
 
         /*-------------------------------------------------------------
          * OK, build the OGRGeometry object.
          *------------------------------------------------------------*/
         int numHolesToRead = 0;
         poPolygon = NULL;
-        for(iSection=0; iSection<numLineSections; iSection++)
+        for( int iSection = 0; iSection < numLineSections; iSection++ )
         {
-            GInt32 *pnXYPtr;
-            int     numSectionVertices;
 
             if (poPolygon == NULL)
                 poPolygon = new OGRPolygon();
@@ -3190,13 +3055,13 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             else
                 numHolesToRead--;
 
-            numSectionVertices = pasSecHdrs[iSection].numVertices;
-            pnXYPtr = panXY + (pasSecHdrs[iSection].nVertexOffset * 2);
+            int numSectionVertices = pasSecHdrs[iSection].numVertices;
+            GInt32 *pnXYPtr = panXY + (pasSecHdrs[iSection].nVertexOffset * 2);
 
-            poRing = new OGRLinearRing();
+            OGRLinearRing *poRing = new OGRLinearRing();
             poRing->setNumPoints(numSectionVertices);
 
-            for(i=0; i<numSectionVertices; i++)
+            for( int i = 0; i < numSectionVertices; i++ )
             {
                 poMapFile->Int2Coordsys(*pnXYPtr, *(pnXYPtr+1), dX, dY);
                 poRing->setPoint(i, dX, dY);
@@ -3220,7 +3085,6 @@ int TABRegion::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
                 poPolygon = NULL;  // We'll alloc a new polygon next loop.
             }
-
         }
 
         CPLFree(pasSecHdrs);
@@ -3265,10 +3129,6 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                       GBool bCoordBlockDataOnly /*=FALSE*/,
                                       TABMAPCoordBlock **ppoCoordBlock/*=NULL*/)
 {
-    GInt32              nX, nY;
-    OGRGeometry         *poGeom;
-    TABMAPCoordBlock    *poCoordBlock=NULL;
-
     /*-----------------------------------------------------------------
      * We assume that ValidateMapInfoType() was called already and that
      * the type in poObjHdr->m_nType is valid.
@@ -3278,7 +3138,8 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    TABMAPCoordBlock *poCoordBlock=NULL;
 
     if ((m_nMapInfoType == TAB_GEOM_REGION ||
          m_nMapInfoType == TAB_GEOM_REGION_C ||
@@ -3295,11 +3156,6 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
          * We accept both OGRPolygons (with one or multiple rings) and
          * OGRMultiPolygons as input.
          *============================================================*/
-        int     nStatus=0, i, iRing;
-        int     numRingsTotal;
-        GUInt32 nCoordDataSize;
-        GInt32  nCoordBlockPtr;
-        TABMAPCoordSecHdr       *pasSecHdrs = NULL;
         GBool   bCompressed = poObjHdr->IsCompressedType();
 
         /*-------------------------------------------------------------
@@ -3310,34 +3166,34 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         else
             poCoordBlock = poMapFile->GetCurCoordBlock();
         poCoordBlock->StartNewFeature();
-        nCoordBlockPtr = poCoordBlock->GetCurAddress();
+        GInt32 nCoordBlockPtr = poCoordBlock->GetCurAddress();
         poCoordBlock->SetComprCoordOrigin(m_nComprOrgX, m_nComprOrgY);
 
 #ifdef TABDUMP
-    printf("TABRegion::WriteGeometryToMAPFile(): ComprOrgX,Y= (%d,%d)\n",
+    printf("TABRegion::WriteGeometryToMAPFile(): ComprOrgX,Y= (%d,%d)\n",/*ok*/
            m_nComprOrgX, m_nComprOrgY);
 #endif
         /*-------------------------------------------------------------
          * Fetch total number of rings and build array of coord
          * sections headers.
          *------------------------------------------------------------*/
-        numRingsTotal = ComputeNumRings(&pasSecHdrs, poMapFile);
-        if (numRingsTotal == 0)
-            nStatus = -1;
+        TABMAPCoordSecHdr *pasSecHdrs = NULL;
+        int numRingsTotal = ComputeNumRings(&pasSecHdrs, poMapFile);
+        int nStatus = numRingsTotal == 0 ? -1 : 0;
 
         /*-------------------------------------------------------------
          * Write the Coord. Section Header
          *------------------------------------------------------------*/
-        int nVersion = TAB_GEOM_GET_VERSION(m_nMapInfoType);
+        const int nVersion = TAB_GEOM_GET_VERSION(m_nMapInfoType);
 
-        if (nStatus == 0)
+        if( nStatus == 0 )
             nStatus = poCoordBlock->WriteCoordSecHdrs(nVersion, numRingsTotal,
                                                       pasSecHdrs, bCompressed);
 
         CPLFree(pasSecHdrs);
         pasSecHdrs = NULL;
 
-        if (nStatus != 0)
+        if( nStatus != 0 )
             return nStatus;  // Error has already been reported.
 
         /*-------------------------------------------------------------
@@ -3345,11 +3201,10 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
          * to write the coordinates themselves...
          *------------------------------------------------------------*/
 
-        for(iRing=0; iRing < numRingsTotal; iRing++)
+        GInt32 nX, nY;
+        for( int iRing=0; iRing < numRingsTotal; iRing++ )
         {
-            OGRLinearRing       *poRing;
-
-            poRing = GetRingRef(iRing);
+            OGRLinearRing *poRing = GetRingRef(iRing);
             if (poRing == NULL)
             {
                 CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -3359,7 +3214,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
 
             int numPoints = poRing->getNumPoints();
 
-            for(i=0; nStatus == 0 && i<numPoints; i++)
+            for( int i=0; nStatus == 0 && i<numPoints; i++ )
             {
                 poMapFile->Coordsys2Int(poRing->getX(i), poRing->getY(i),
                                         nX, nY);
@@ -3372,7 +3227,7 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
             }
         }/* for iRing*/
 
-        nCoordDataSize = poCoordBlock->GetFeatureDataSize();
+        GUInt32 nCoordDataSize = poCoordBlock->GetFeatureDataSize();
 
         /*-------------------------------------------------------------
          * ... and finally copy info to poObjHdr
@@ -3389,7 +3244,8 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         poPLineHdr->SetMBR(m_nXMin, m_nYMin, m_nXMax, m_nYMax);
 
         // Region center/label point
-        double dX, dY;
+        double dX = 0.0;
+        double dY = 0.0;
         if (GetCenter(dX, dY) != -1)
         {
             poMapFile->Coordsys2Int(dX, dY, poPLineHdr->m_nLabelX,
@@ -3433,7 +3289,6 @@ int TABRegion::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABRegion::GetNumRings()
  *
@@ -3452,12 +3307,13 @@ int TABRegion::GetNumRings()
 int TABRegion::ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
                                TABMAPFile *poMapFile)
 {
-    OGRGeometry         *poGeom;
-    int                 numRingsTotal = 0, iLastSect = 0;
+    int numRingsTotal = 0;
+    int iLastSect = 0;
 
     if (ppasSecHdrs)
         *ppasSecHdrs = NULL;
-    poGeom = GetGeometryRef();
+
+    OGRGeometry *poGeom = GetGeometryRef();
 
     if (poGeom && (wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ||
                    wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon))
@@ -3480,21 +3336,20 @@ int TABRegion::ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
 
                 numRingsTotal += poPolygon->getNumInteriorRings()+1;
 
-                if (ppasSecHdrs)
+                if (ppasSecHdrs && poMapFile)
                 {
                     if (AppendSecHdrs(poPolygon, *ppasSecHdrs,
                                       poMapFile, iLastSect) != 0)
                         return 0; // An error happened, return count=0
                 }
-
-            }/*for*/
+            }  // for
         }
         else
         {
             poPolygon = (OGRPolygon*)poGeom;
             numRingsTotal = poPolygon->getNumInteriorRings()+1;
 
-            if (ppasSecHdrs)
+            if (ppasSecHdrs && poMapFile)
             {
                 if (AppendSecHdrs(poPolygon, *ppasSecHdrs,
                                   poMapFile, iLastSect) != 0)
@@ -3511,20 +3366,19 @@ int TABRegion::ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
      * V450 header section uses int32 instead of int16 for numVertices
      * and we add another 2 bytes to align with a 4 bytes boundary.
      *------------------------------------------------------------*/
-    int nTotalHdrSizeUncompressed;
-    if (m_nMapInfoType == TAB_GEOM_V450_REGION ||
-        m_nMapInfoType == TAB_GEOM_V450_REGION_C ||
-        m_nMapInfoType == TAB_GEOM_V800_REGION ||
-        m_nMapInfoType == TAB_GEOM_V800_REGION_C)
-        nTotalHdrSizeUncompressed = 28 * numRingsTotal;
-    else
-        nTotalHdrSizeUncompressed = 24 * numRingsTotal;
+    const int nTotalHdrSizeUncompressed =
+        (m_nMapInfoType == TAB_GEOM_V450_REGION ||
+         m_nMapInfoType == TAB_GEOM_V450_REGION_C ||
+         m_nMapInfoType == TAB_GEOM_V800_REGION ||
+         m_nMapInfoType == TAB_GEOM_V800_REGION_C)
+        ? 28 * numRingsTotal
+        : 24 * numRingsTotal;
 
-    if (ppasSecHdrs)
+    if( ppasSecHdrs )
     {
         int numPointsTotal = 0;
         CPLAssert(iLastSect == numRingsTotal);
-        for (int iRing=0; iRing<numRingsTotal; iRing++)
+        for( int iRing=0; iRing < numRingsTotal; iRing++ )
         {
             (*ppasSecHdrs)[iRing].nDataOffset = nTotalHdrSizeUncompressed +
                                                    numPointsTotal*4*2;
@@ -3537,7 +3391,6 @@ int TABRegion::ComputeNumRings(TABMAPCoordSecHdr **ppasSecHdrs,
     return numRingsTotal;
 }
 
-
 /**********************************************************************
  *                   TABRegion::AppendSecHdrs()
  *
@@ -3550,20 +3403,19 @@ int TABRegion::AppendSecHdrs(OGRPolygon *poPolygon,
                              TABMAPFile *poMapFile,
                              int &iLastRing)
 {
-    int iRing, numRingsInPolygon;
     /*-------------------------------------------------------------
      * Add a pasSecHdrs[] entry for each ring in this polygon.
      * Note that the structs won't be fully initialized.
      *------------------------------------------------------------*/
-    numRingsInPolygon = poPolygon->getNumInteriorRings()+1;
+    int numRingsInPolygon = poPolygon->getNumInteriorRings()+1;
 
     pasSecHdrs = (TABMAPCoordSecHdr*)CPLRealloc(pasSecHdrs,
                                                 (iLastRing+numRingsInPolygon)*
                                                 sizeof(TABMAPCoordSecHdr));
 
-    for(iRing=0; iRing < numRingsInPolygon; iRing++)
+    for( int iRing=0; iRing < numRingsInPolygon; iRing++ )
     {
-        OGRLinearRing   *poRing;
+        OGRLinearRing *poRing = NULL;
         OGREnvelope     sEnvelope;
 
         if (iRing == 0)
@@ -3613,10 +3465,9 @@ int TABRegion::AppendSecHdrs(OGRPolygon *poPolygon,
  **********************************************************************/
 OGRLinearRing *TABRegion::GetRingRef(int nRequestedRingIndex)
 {
-    OGRGeometry     *poGeom;
     OGRLinearRing   *poRing = NULL;
 
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
 
     if (poGeom && (wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ||
                    wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon))
@@ -3644,7 +3495,7 @@ OGRLinearRing *TABRegion::GetRingRef(int nRequestedRingIndex)
         iCurRing = 0;
         for(int iPoly=0; poRing == NULL && iPoly < numOGRPolygons; iPoly++)
         {
-            OGRPolygon      *poPolygon;
+            OGRPolygon *poPolygon = NULL;
             if (poMultiPolygon)
                 poPolygon = (OGRPolygon*)poMultiPolygon->getGeometryRef(iPoly);
             else
@@ -3676,10 +3527,9 @@ OGRLinearRing *TABRegion::GetRingRef(int nRequestedRingIndex)
  **********************************************************************/
 GBool TABRegion::IsInteriorRing(int nRequestedRingIndex)
 {
-    OGRGeometry     *poGeom;
     OGRLinearRing   *poRing = NULL;
 
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
 
     if (poGeom && (wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ||
                    wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon))
@@ -3707,7 +3557,7 @@ GBool TABRegion::IsInteriorRing(int nRequestedRingIndex)
         iCurRing = 0;
         for(int iPoly=0; poRing == NULL && iPoly < numOGRPolygons; iPoly++)
         {
-            OGRPolygon* poPolygon;
+            OGRPolygon* poPolygon = NULL;
             if (poMultiPolygon)
                 poPolygon = (OGRPolygon*)poMultiPolygon->getGeometryRef(iPoly);
             else
@@ -3756,8 +3606,6 @@ const char *TABRegion::GetStyleString()
     return m_pszStyleString;
 }
 
-
-
 /**********************************************************************
  *                   TABRegion::DumpMIF()
  *
@@ -3765,16 +3613,13 @@ const char *TABRegion::GetStyleString()
  **********************************************************************/
 void TABRegion::DumpMIF(FILE *fpOut /*=NULL*/)
 {
-    OGRGeometry   *poGeom;
-    int i, numPoints;
-
     if (fpOut == NULL)
         fpOut = stdout;
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && (wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ||
                    wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon))
     {
@@ -3784,15 +3629,13 @@ void TABRegion::DumpMIF(FILE *fpOut /*=NULL*/)
          * Note that we want to handle both OGRPolygons and OGRMultiPolygons
          * that's why we use the GetNumRings()/GetRingRef() interface.
          *------------------------------------------------------------*/
-        int iRing, numRingsTotal = GetNumRings();
+        int numRingsTotal = GetNumRings();
 
         fprintf(fpOut, "REGION %d\n", numRingsTotal);
 
-        for(iRing=0; iRing < numRingsTotal; iRing++)
+        for( int iRing = 0; iRing < numRingsTotal; iRing++ )
         {
-            OGRLinearRing       *poRing;
-
-            poRing = GetRingRef(iRing);
+            OGRLinearRing *poRing = GetRingRef(iRing);
 
             if (poRing == NULL)
             {
@@ -3801,9 +3644,9 @@ void TABRegion::DumpMIF(FILE *fpOut /*=NULL*/)
                 return;
             }
 
-            numPoints = poRing->getNumPoints();
+            const int numPoints = poRing->getNumPoints();
             fprintf(fpOut, " %d\n", numPoints);
-            for(i=0; i<numPoints; i++)
+            for( int i = 0;  i < numPoints; i++ )
                 fprintf(fpOut, "%.15g %.15g\n",poRing->getX(i),poRing->getY(i));
         }
     }
@@ -3833,7 +3676,7 @@ void TABRegion::DumpMIF(FILE *fpOut /*=NULL*/)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABRegion::GetCenter(double &dX, double &dY)
+int TABRegion::GetCenter( double &dX, double &dY )
 {
     if (!m_bCenterIsSet)
     {
@@ -3841,14 +3684,12 @@ int TABRegion::GetCenter(double &dX, double &dY)
          * Calculate label point.  If we have a multipolygon then we use
          * the first OGRPolygon in the feature to calculate the point.
          *------------------------------------------------------------*/
-        OGRPoint        oLabelPoint;
-        OGRPolygon      *poPolygon=NULL;
-        OGRGeometry     *poGeom;
-
-        poGeom = GetGeometryRef();
+        OGRGeometry *poGeom = GetGeometryRef();
         if (poGeom == NULL)
             return -1;
 
+        OGRPolygon *poPolygon=NULL;
+
         if (wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon)
         {
             OGRMultiPolygon *poMultiPolygon = (OGRMultiPolygon *)poGeom;
@@ -3860,6 +3701,7 @@ int TABRegion::GetCenter(double &dX, double &dY)
             poPolygon = (OGRPolygon*)poGeom;
         }
 
+        OGRPoint oLabelPoint;
         if (poPolygon != NULL &&
             OGRPolygonLabelPoint(poPolygon, &oLabelPoint) == OGRERR_NONE)
         {
@@ -3897,7 +3739,6 @@ void TABRegion::SetCenter(double dX, double dY)
     m_bCenterIsSet = TRUE;
 }
 
-
 /*=====================================================================
  *                      class TABRectangle
  *====================================================================*/
@@ -3907,21 +3748,19 @@ void TABRegion::SetCenter(double dX, double dY)
  *
  * Constructor.
  **********************************************************************/
-TABRectangle::TABRectangle(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
-{
-    m_bRoundCorners = FALSE;
-    m_dRoundXRadius = m_dRoundYRadius = 0.0;
-}
+TABRectangle::TABRectangle( OGRFeatureDefn *poDefnIn ) :
+    TABFeature(poDefnIn),
+    m_bRoundCorners(FALSE),
+    m_dRoundXRadius(0.0),
+    m_dRoundYRadius(0.0)
+{}
 
 /**********************************************************************
  *                   TABRectangle::~TABRectangle()
  *
  * Destructor.
  **********************************************************************/
-TABRectangle::~TABRectangle()
-{
-}
+TABRectangle::~TABRectangle() {}
 
 /**********************************************************************
  *                     TABRectangle::CloneTABFeature()
@@ -3969,12 +3808,10 @@ TABFeature *TABRectangle::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
  **********************************************************************/
 TABGeomType TABRectangle::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon)
     {
         if (m_bRoundCorners && m_dRoundXRadius!=0.0 && m_dRoundYRadius!=0.0)
@@ -4008,13 +3845,12 @@ TABGeomType TABRectangle::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
  **********************************************************************/
 int TABRectangle::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
     OGREnvelope sEnvelope;
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon)
         poGeom->getEnvelope(&sEnvelope);
     else
@@ -4060,10 +3896,6 @@ int TABRectangle::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                           GBool bCoordBlockDataOnly /*=FALSE*/,
                                           TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    double              dXMin, dYMin, dXMax, dYMax;
-    OGRPolygon          *poPolygon;
-    OGRLinearRing       *poRing;
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -4108,11 +3940,16 @@ int TABRectangle::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     else
     {
         m_bRoundCorners = FALSE;
-        m_dRoundXRadius = m_dRoundYRadius = 0.0;
+        m_dRoundXRadius = 0.0;
+        m_dRoundYRadius = 0.0;
     }
 
     // A rectangle is defined by its MBR
 
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     poMapFile->Int2Coordsys(poRectHdr->m_nMinX, poRectHdr->m_nMinY,
                             dXMin, dYMin);
     poMapFile->Int2Coordsys(poRectHdr->m_nMaxX, poRectHdr->m_nMaxY,
@@ -4138,8 +3975,8 @@ int TABRectangle::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      *----------------------------------------------------------------*/
-    poPolygon = new OGRPolygon;
-    poRing = new OGRLinearRing();
+    OGRPolygon *poPolygon = new OGRPolygon;
+    OGRLinearRing *poRing = new OGRLinearRing();
     if (m_bRoundCorners && m_dRoundXRadius != 0.0 && m_dRoundYRadius != 0.0)
     {
         /*-------------------------------------------------------------
@@ -4152,8 +3989,10 @@ int TABRectangle::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
          * is the way MapInfo seems to do it when a radius bigger than
          * the MBR is passed from TBA to MIF.
          *------------------------------------------------------------*/
-        double dXRadius = MIN(m_dRoundXRadius, (dXMax-dXMin)/2.0);
-        double dYRadius = MIN(m_dRoundYRadius, (dYMax-dYMin)/2.0);
+        const double dXRadius =
+            std::min(m_dRoundXRadius, (dXMax - dXMin) / 2.0);
+        const double dYRadius =
+            std::min(m_dRoundYRadius, (dYMax - dYMin) / 2.0);
         TABGenerateArc(poRing, 45,
                        dXMin + dXRadius, dYMin + dYRadius, dXRadius, dYRadius,
                        M_PI, 3.0*M_PI/2.0);
@@ -4200,7 +4039,6 @@ int TABRectangle::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                          GBool bCoordBlockDataOnly /*=FALSE*/,
                                          TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -4234,7 +4072,8 @@ int TABRectangle::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     }
     else
     {
-        poRectHdr->m_nCornerWidth = poRectHdr->m_nCornerHeight = 0;
+        poRectHdr->m_nCornerWidth = 0;
+        poRectHdr->m_nCornerHeight = 0;
     }
 
     // A rectangle is defined by its MBR (values were set in UpdateMBR())
@@ -4287,43 +4126,43 @@ const char *TABRectangle::GetStyleString()
  **********************************************************************/
 void TABRectangle::DumpMIF(FILE *fpOut /*=NULL*/)
 {
-    OGRGeometry   *poGeom;
-    OGRPolygon    *poPolygon = NULL;
-    int i, numPoints;
-
     if (fpOut == NULL)
         fpOut = stdout;
 
     /*-----------------------------------------------------------------
      * Output RECT or ROUNDRECT parameters
      *----------------------------------------------------------------*/
-    double dXMin, dYMin, dXMax, dYMax;
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     GetMBR(dXMin, dYMin, dXMax, dYMax);
+
     if (m_bRoundCorners)
         fprintf(fpOut, "(ROUNDRECT %.15g %.15g %.15g %.15g    %.15g %.15g)\n",
                 dXMin, dYMin, dXMax, dYMax,
                 m_dRoundXRadius, m_dRoundYRadius);
     else
-        fprintf(fpOut, "(RECT %.15g %.15g %.15g %.15g)\n", dXMin, dYMin, dXMax, dYMax);
+       fprintf(fpOut, "(RECT %.15g %.15g %.15g %.15g)\n",
+               dXMin, dYMin, dXMax, dYMax);
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon)
     {
         /*-------------------------------------------------------------
          * Generate rectangle output as a region
          * We could also output as a RECT or ROUNDRECT in a real MIF generator
          *------------------------------------------------------------*/
-        int iRing, numIntRings;
-        poPolygon = (OGRPolygon*)poGeom;
-        numIntRings = poPolygon->getNumInteriorRings();
+        OGRPolygon *poPolygon = (OGRPolygon*)poGeom;
+        int numIntRings = poPolygon->getNumInteriorRings();
         fprintf(fpOut, "REGION %d\n", numIntRings+1);
         // In this loop, iRing=-1 for the outer ring.
-        for(iRing=-1; iRing < numIntRings; iRing++)
+        for( int iRing = -1; iRing < numIntRings; iRing++ )
         {
-            OGRLinearRing       *poRing;
+            OGRLinearRing *poRing = NULL;
 
             if (iRing == -1)
                 poRing = poPolygon->getExteriorRing();
@@ -4337,9 +4176,9 @@ void TABRectangle::DumpMIF(FILE *fpOut /*=NULL*/)
                 return;
             }
 
-            numPoints = poRing->getNumPoints();
+            const int numPoints = poRing->getNumPoints();
             fprintf(fpOut, " %d\n", numPoints);
-            for(i=0; i<numPoints; i++)
+            for( int i = 0; i < numPoints; i++ )
                 fprintf(fpOut, "%.15g %.15g\n",poRing->getX(i),poRing->getY(i));
         }
     }
@@ -4357,7 +4196,6 @@ void TABRectangle::DumpMIF(FILE *fpOut /*=NULL*/)
     fflush(fpOut);
 }
 
-
 /*=====================================================================
  *                      class TABEllipse
  *====================================================================*/
@@ -4367,23 +4205,20 @@ void TABRectangle::DumpMIF(FILE *fpOut /*=NULL*/)
  *
  * Constructor.
  **********************************************************************/
-TABEllipse::TABEllipse(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
-{
-    m_dCenterX = 0;
-    m_dCenterY = 0;
-    m_dXRadius = 0;
-    m_dYRadius = 0;
-}
+TABEllipse::TABEllipse( OGRFeatureDefn *poDefnIn ) :
+    TABFeature(poDefnIn),
+    m_dCenterX(0.0),
+    m_dCenterY(0.0),
+    m_dXRadius(0.0),
+    m_dYRadius(0.0)
+{}
 
 /**********************************************************************
  *                   TABEllipse::~TABEllipse()
  *
  * Destructor.
  **********************************************************************/
-TABEllipse::~TABEllipse()
-{
-}
+TABEllipse::~TABEllipse() {}
 
 /**********************************************************************
  *                     TABEllipse::CloneTABFeature()
@@ -4432,12 +4267,10 @@ TABFeature *TABEllipse::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
  **********************************************************************/
 TABGeomType TABEllipse::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if ( (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ) ||
          (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint ) )
     {
@@ -4469,7 +4302,6 @@ TABGeomType TABEllipse::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
  **********************************************************************/
 int TABEllipse::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
     OGREnvelope sEnvelope;
 
     /*-----------------------------------------------------------------
@@ -4478,7 +4310,7 @@ int TABEllipse::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
      * read the polygon geometry... this should be OK unless the
      * polygon geometry was not really an ellipse.
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if ( (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ) ||
          (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )  )
         poGeom->getEnvelope(&sEnvelope);
@@ -4494,13 +4326,12 @@ int TABEllipse::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
      * X/Y radius to define the MBR size.  If X/Y radius are null then
      * we'll try to use the MBR to recompute them.
      *----------------------------------------------------------------*/
-    double      dXCenter, dYCenter;
-    dXCenter = (sEnvelope.MaxX + sEnvelope.MinX)/2.0;
-    dYCenter = (sEnvelope.MaxY + sEnvelope.MinY)/2.0;
+    const double dXCenter = (sEnvelope.MaxX + sEnvelope.MinX) / 2.0;
+    const double dYCenter = (sEnvelope.MaxY + sEnvelope.MinY) / 2.0;
     if (m_dXRadius == 0.0 && m_dYRadius == 0.0)
     {
-        m_dXRadius = ABS(sEnvelope.MaxX - sEnvelope.MinX) / 2.0;
-        m_dYRadius = ABS(sEnvelope.MaxY - sEnvelope.MinY) / 2.0;
+        m_dXRadius = std::abs(sEnvelope.MaxX - sEnvelope.MinX) / 2.0;
+        m_dYRadius = std::abs(sEnvelope.MaxY - sEnvelope.MinY) / 2.0;
     }
 
     m_dXMin = dXCenter - m_dXRadius;
@@ -4534,10 +4365,6 @@ int TABEllipse::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                         GBool bCoordBlockDataOnly /*=FALSE*/,
                                         TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    double              dXMin, dYMin, dXMax, dYMax;
-    OGRPolygon          *poPolygon;
-    OGRLinearRing       *poRing;
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -4563,6 +4390,10 @@ int TABEllipse::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
     // An ellipse is defined by its MBR
 
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     poMapFile->Int2Coordsys(poRectHdr->m_nMinX, poRectHdr->m_nMinY,
                             dXMin, dYMin);
     poMapFile->Int2Coordsys(poRectHdr->m_nMaxX, poRectHdr->m_nMaxY,
@@ -4579,8 +4410,8 @@ int TABEllipse::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      *----------------------------------------------------------------*/
     m_dCenterX = (dXMin + dXMax) / 2.0;
     m_dCenterY = (dYMin + dYMax) / 2.0;
-    m_dXRadius = ABS( (dXMax - dXMin) / 2.0 );
-    m_dYRadius = ABS( (dYMax - dYMin) / 2.0 );
+    m_dXRadius = std::abs( (dXMax - dXMin) / 2.0 );
+    m_dYRadius = std::abs( (dYMax - dYMin) / 2.0 );
 
     SetMBR(dXMin, dYMin, dXMax, dYMax);
 
@@ -4590,9 +4421,8 @@ int TABEllipse::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      *----------------------------------------------------------------*/
-    poPolygon = new OGRPolygon;
-    poRing = new OGRLinearRing();
-
+    OGRPolygon *poPolygon = new OGRPolygon;
+    OGRLinearRing *poRing = new OGRLinearRing();
 
     /*-----------------------------------------------------------------
      * For the OGR geometry, we generate an ellipse with 2 degrees line
@@ -4655,7 +4485,8 @@ int TABEllipse::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     TABMAPObjRectEllipse *poRectHdr = (TABMAPObjRectEllipse *)poObjHdr;
 
     // Reset RoundRect Corner members... just in case (unused for ellipse)
-    poRectHdr->m_nCornerWidth = poRectHdr->m_nCornerHeight = 0;
+    poRectHdr->m_nCornerWidth = 0;
+    poRectHdr->m_nCornerHeight = 0;
 
     // An ellipse is defined by its MBR (values were set in UpdateMBR())
     poRectHdr->m_nMinX = m_nXMin;
@@ -4700,7 +4531,6 @@ const char *TABEllipse::GetStyleString()
     return m_pszStyleString;
 }
 
-
 /**********************************************************************
  *                   TABEllipse::DumpMIF()
  *
@@ -4708,38 +4538,37 @@ const char *TABEllipse::GetStyleString()
  **********************************************************************/
 void TABEllipse::DumpMIF(FILE *fpOut /*=NULL*/)
 {
-    OGRGeometry   *poGeom;
-    OGRPolygon    *poPolygon = NULL;
-    int i, numPoints;
-
     if (fpOut == NULL)
         fpOut = stdout;
 
     /*-----------------------------------------------------------------
      * Output ELLIPSE parameters
      *----------------------------------------------------------------*/
-    double dXMin, dYMin, dXMax, dYMax;
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     GetMBR(dXMin, dYMin, dXMax, dYMax);
-    fprintf(fpOut, "(ELLIPSE %.15g %.15g %.15g %.15g)\n", dXMin, dYMin, dXMax, dYMax);
+    fprintf(fpOut, "(ELLIPSE %.15g %.15g %.15g %.15g)\n",
+            dXMin, dYMin, dXMax, dYMax);
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon)
     {
         /*-------------------------------------------------------------
          * Generate ellipse output as a region
          * We could also output as an ELLIPSE in a real MIF generator
          *------------------------------------------------------------*/
-        int iRing, numIntRings;
-        poPolygon = (OGRPolygon*)poGeom;
-        numIntRings = poPolygon->getNumInteriorRings();
+        OGRPolygon *poPolygon = (OGRPolygon*)poGeom;
+        int numIntRings = poPolygon->getNumInteriorRings();
         fprintf(fpOut, "REGION %d\n", numIntRings+1);
         // In this loop, iRing=-1 for the outer ring.
-        for(iRing=-1; iRing < numIntRings; iRing++)
+        for( int iRing=-1; iRing < numIntRings; iRing++ )
         {
-            OGRLinearRing       *poRing;
+            OGRLinearRing *poRing = NULL;
 
             if (iRing == -1)
                 poRing = poPolygon->getExteriorRing();
@@ -4753,9 +4582,9 @@ void TABEllipse::DumpMIF(FILE *fpOut /*=NULL*/)
                 return;
             }
 
-            numPoints = poRing->getNumPoints();
+            int numPoints = poRing->getNumPoints();
             fprintf(fpOut, " %d\n", numPoints);
-            for(i=0; i<numPoints; i++)
+            for( int i = 0; i < numPoints; i++ )
                 fprintf(fpOut, "%.15g %.15g\n",poRing->getX(i),poRing->getY(i));
         }
     }
@@ -4773,7 +4602,6 @@ void TABEllipse::DumpMIF(FILE *fpOut /*=NULL*/)
     fflush(fpOut);
 }
 
-
 /*=====================================================================
  *                      class TABArc
  *====================================================================*/
@@ -4783,22 +4611,22 @@ void TABEllipse::DumpMIF(FILE *fpOut /*=NULL*/)
  *
  * Constructor.
  **********************************************************************/
-TABArc::TABArc(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
-{
-    m_dStartAngle = m_dEndAngle = 0.0;
-    m_dCenterX = m_dCenterY = m_dXRadius = m_dYRadius = 0.0;
-
-}
+TABArc::TABArc( OGRFeatureDefn *poDefnIn ) :
+    TABFeature(poDefnIn),
+    m_dStartAngle(0.0),
+    m_dEndAngle(0.0),
+    m_dCenterX(0.0),
+    m_dCenterY(0.0),
+    m_dXRadius(0.0),
+    m_dYRadius(0.0)
+{}
 
 /**********************************************************************
  *                   TABArc::~TABArc()
  *
  * Destructor.
  **********************************************************************/
-TABArc::~TABArc()
-{
-}
+TABArc::~TABArc() {}
 
 /**********************************************************************
  *                     TABArc::CloneTABFeature()
@@ -4846,12 +4674,10 @@ TABFeature *TABArc::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
  **********************************************************************/
 TABGeomType TABArc::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if ( (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString ) ||
          (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint ) )
     {
@@ -4883,10 +4709,9 @@ TABGeomType TABArc::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
  **********************************************************************/
 int TABArc::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
     OGREnvelope sEnvelope;
 
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if ( (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString ) )
     {
         /*-------------------------------------------------------------
@@ -4915,10 +4740,10 @@ int TABArc::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
         OGRLineString oTmpLine;
         int numPts=0;
         if (m_dEndAngle < m_dStartAngle)
-            numPts = (int) ABS( ((m_dEndAngle+360)-m_dStartAngle)/2 ) + 1;
+            numPts = (int) std::abs( ((m_dEndAngle+360)-m_dStartAngle)/2 ) + 1;
         else
-            numPts = (int) ABS( (m_dEndAngle-m_dStartAngle)/2 ) + 1;
-        numPts = MAX(2, numPts);
+            numPts = (int) std::abs( (m_dEndAngle-m_dStartAngle)/2 ) + 1;
+        numPts = std::max(2, numPts);
 
         TABGenerateArc(&oTmpLine, numPts,
                        m_dCenterX, m_dCenterY,
@@ -4966,10 +4791,6 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                     GBool bCoordBlockDataOnly /*=FALSE*/,
                                     TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    double              dXMin, dYMin, dXMax, dYMax;
-    OGRLineString       *poLine;
-    int                 numPts;
-
     /* Nothing to do for bCoordBlockDataOnly (used by index splitting) */
     if (bCoordBlockDataOnly)
         return 0;
@@ -4988,7 +4809,6 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         return -1;
     }
 
-
     /*-----------------------------------------------------------------
      * Read object information
      *----------------------------------------------------------------*/
@@ -5078,6 +4898,11 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
     // An arc is defined by its defining ellipse's MBR:
 
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
+
     poMapFile->Int2Coordsys(poArcHdr->m_nArcEllipseMinX,
                             poArcHdr->m_nArcEllipseMinY , dXMin, dYMin);
     poMapFile->Int2Coordsys(poArcHdr->m_nArcEllipseMaxX,
@@ -5085,8 +4910,8 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
     m_dCenterX = (dXMin + dXMax) / 2.0;
     m_dCenterY = (dYMin + dYMax) / 2.0;
-    m_dXRadius = ABS( (dXMax - dXMin) / 2.0 );
-    m_dYRadius = ABS( (dYMax - dYMin) / 2.0 );
+    m_dXRadius = std::abs( (dXMax - dXMin) / 2.0 );
+    m_dYRadius = std::abs( (dYMax - dYMin) / 2.0 );
 
     // Read the Arc's MBR and use that as this feature's MBR
     poMapFile->Int2Coordsys(poArcHdr->m_nMinX, poArcHdr->m_nMinY,
@@ -5098,19 +4923,18 @@ int TABArc::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     m_nPenDefIndex = poArcHdr->m_nPenId;        // Pen index
     poMapFile->ReadPenDef(m_nPenDefIndex, &m_sPenDef);
 
-
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      * For the OGR geometry, we generate an arc with 2 degrees line
      * segments.
      *----------------------------------------------------------------*/
-    poLine = new OGRLineString;
+    OGRLineString *poLine = new OGRLineString;
 
-    if (m_dEndAngle < m_dStartAngle)
-        numPts = (int) ABS( ((m_dEndAngle+360.0)-m_dStartAngle)/2.0 ) + 1;
-    else
-        numPts = (int) ABS( (m_dEndAngle-m_dStartAngle)/2.0 ) + 1;
-    numPts = MAX(2, numPts);
+    const int numPts =
+        std::max(2,
+            (m_dEndAngle < m_dStartAngle
+             ? (int) std::abs( ((m_dEndAngle+360.0)-m_dStartAngle)/2.0 ) + 1
+             : (int) std::abs( (m_dEndAngle-m_dStartAngle)/2.0 ) + 1));
 
     TABGenerateArc(poLine, numPts,
                    m_dCenterX, m_dCenterY,
@@ -5217,7 +5041,6 @@ void TABArc::SetEndAngle(double dAngle)
     m_dEndAngle = dAngle;
 }
 
-
 /**********************************************************************
  *                   TABArc::GetStyleString()
  *
@@ -5242,10 +5065,6 @@ const char *TABArc::GetStyleString()
  **********************************************************************/
 void TABArc::DumpMIF(FILE *fpOut /*=NULL*/)
 {
-    OGRGeometry   *poGeom;
-    OGRLineString *poLine = NULL;
-    int i, numPoints;
-
     if (fpOut == NULL)
         fpOut = stdout;
 
@@ -5260,17 +5079,17 @@ void TABArc::DumpMIF(FILE *fpOut /*=NULL*/)
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
     {
         /*-------------------------------------------------------------
          * Generate arc output as a simple polyline
          * We could also output as an ELLIPSE in a real MIF generator
          *------------------------------------------------------------*/
-        poLine = (OGRLineString*)poGeom;
-        numPoints = poLine->getNumPoints();
+        OGRLineString *poLine = (OGRLineString*)poGeom;
+        const int numPoints = poLine->getNumPoints();
         fprintf(fpOut, "PLINE %d\n", numPoints);
-        for(i=0; i<numPoints; i++)
+        for( int i = 0; i < numPoints; i++ )
             fprintf(fpOut, "%.15g %.15g\n", poLine->getX(i), poLine->getY(i));
     }
     else
@@ -5286,8 +5105,6 @@ void TABArc::DumpMIF(FILE *fpOut /*=NULL*/)
     fflush(fpOut);
 }
 
-
-
 /*=====================================================================
  *                      class TABText
  *====================================================================*/
@@ -5297,24 +5114,22 @@ void TABArc::DumpMIF(FILE *fpOut /*=NULL*/)
  *
  * Constructor.
  **********************************************************************/
-TABText::TABText(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
-{
-    m_pszString = NULL;
-
-    m_dAngle = m_dHeight = 0.0;
-    m_dfLineEndX = m_dfLineEndY = 0.0;
-    m_bLineEndSet = FALSE;
-
-    m_rgbForeground = 0x000000;
-    m_rgbBackground = 0xffffff;
-    m_rgbOutline    = 0xffffff;
-    m_rgbShadow     = 0x808080;
-
-    m_nTextAlignment = 0;
-    m_nFontStyle = 0;
-    m_dWidth = 0;
-}
+TABText::TABText( OGRFeatureDefn *poDefnIn ) :
+    TABFeature(poDefnIn),
+    m_pszString(NULL),
+    m_dAngle(0.0),
+    m_dHeight(0.0),
+    m_dWidth(0.0),
+    m_dfLineEndX(0.0),
+    m_dfLineEndY(0.0),
+    m_bLineEndSet(FALSE),
+    m_rgbForeground(0x000000),
+    m_rgbBackground(0xffffff),
+    m_rgbOutline(0xffffff),
+    m_rgbShadow(0x808080),
+    m_nTextAlignment(0),
+    m_nFontStyle(0)
+{}
 
 /**********************************************************************
  *                   TABText::~TABText()
@@ -5352,7 +5167,6 @@ TABFeature *TABText::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
     // ITABFeatureFont
     *(poNew->GetFontDefRef()) = *GetFontDefRef();
 
-
     poNew->SetTextString( GetTextString() );
     poNew->SetTextAngle( GetTextAngle() );
     poNew->SetTextBoxHeight( GetTextBoxHeight() );
@@ -5384,12 +5198,10 @@ TABFeature *TABText::CloneTABFeature(OGRFeatureDefn *poNewDefn/*=NULL*/)
  **********************************************************************/
 TABGeomType TABText::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
     {
         m_nMapInfoType = TAB_GEOM_TEXT;
@@ -5428,9 +5240,6 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                      GBool bCoordBlockDataOnly /*=FALSE*/,
                                      TABMAPCoordBlock **ppoCoordBlock/*=NULL*/)
 {
-    double              dXMin, dYMin, dXMax, dYMax;
-    OGRGeometry         *poGeometry;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry type
      *----------------------------------------------------------------*/
@@ -5448,17 +5257,15 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     /*=============================================================
      * TEXT
      *============================================================*/
-    int     nStringLen;
-    GInt32  nCoordBlockPtr;
-    double  dJunk;
 
     /*-----------------------------------------------------------------
      * Read object information
      *----------------------------------------------------------------*/
     TABMAPObjText *poTextHdr = (TABMAPObjText *)poObjHdr;
 
-    nCoordBlockPtr = poTextHdr->m_nCoordBlockPtr;   // String position
-    nStringLen      = poTextHdr->m_nCoordDataSize;   // String length
+    const GInt32 nCoordBlockPtr =
+        poTextHdr->m_nCoordBlockPtr;   // String position
+    const int nStringLen = poTextHdr->m_nCoordDataSize;   // String length
     m_nTextAlignment = poTextHdr->m_nTextAlignment; // just./spacing/arrow
 
     /*-------------------------------------------------------------
@@ -5486,6 +5293,7 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     m_bLineEndSet = TRUE;
 
     // Text Height
+    double dJunk = 0.0;
     poMapFile->Int2CoordsysDist(0, poTextHdr->m_nHeight, dJunk, m_dHeight);
 
     if (!bCoordBlockDataOnly)
@@ -5495,6 +5303,10 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     }
 
     // MBR after rotation
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     poMapFile->Int2Coordsys(poTextHdr->m_nMinX, poTextHdr->m_nMinY,
                             dXMin, dYMin);
     poMapFile->Int2Coordsys(poTextHdr->m_nMaxX, poTextHdr->m_nMaxY,
@@ -5516,7 +5328,7 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
     if (nStringLen > 0)
     {
-        TABMAPCoordBlock        *poCoordBlock;
+        TABMAPCoordBlock *poCoordBlock = NULL;
 
         if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
             poCoordBlock = *ppoCoordBlock;
@@ -5544,7 +5356,6 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     CPLFree(m_pszString);
     m_pszString = pszTmpString; // This string was Escaped before 20050714
 
-
     /* Set/retrieve the MBR to make sure Mins are smaller than Maxs
      */
     SetMBR(dXMin, dYMin, dXMax, dYMax);
@@ -5562,9 +5373,10 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      * We need to calculate the true lower left corner of the text based
      * on the MBR after rotation, the text height and the rotation angle.
      *----------------------------------------------------------------*/
-    double dCos, dSin, dX, dY;
-    dSin = sin(m_dAngle*M_PI/180.0);
-    dCos = cos(m_dAngle*M_PI/180.0);
+    double dSin = sin(m_dAngle * M_PI/180.0);
+    double dCos = cos(m_dAngle * M_PI/180.0);
+    double dX = 0.0;
+    double dY = 0.0;
     if (dSin > 0.0  && dCos > 0.0)
     {
         dX = dXMin + m_dHeight * dSin;
@@ -5586,7 +5398,7 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         dY = dYMax - m_dHeight * dCos;
     }
 
-    poGeometry = new OGRPoint(dX, dY);
+    OGRGeometry *poGeometry = new OGRPoint(dX, dY);
 
     SetGeometryDirectly(poGeometry);
 
@@ -5607,8 +5419,8 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
      * and for other teta values, use:
      *   W = H * (dY - H * cos(teta)) / (H * sin(teta))
      *----------------------------------------------------------------*/
-    dSin = ABS(dSin);
-    dCos = ABS(dCos);
+    dSin = std::abs(dSin);
+    dCos = std::abs(dCos);
     if (m_dHeight == 0.0)
         m_dWidth = 0.0;
     else if ( dCos > dSin )
@@ -5617,7 +5429,7 @@ int TABText::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     else
         m_dWidth = m_dHeight * ((dYMax-dYMin) - m_dHeight*dCos) /
                                                         (m_dHeight*dSin);
-    m_dWidth = ABS(m_dWidth);
+    m_dWidth = std::abs(m_dWidth);
 
     return 0;
 }
@@ -5639,11 +5451,6 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                     TABMAPCoordBlock **ppoCoordBlock/*=NULL*/)
 {
     GInt32              nX, nY, nXMin, nYMin, nXMax, nYMax;
-    OGRGeometry         *poGeom;
-    OGRPoint            *poPoint;
-    GInt32              nCoordBlockPtr;
-    TABMAPCoordBlock    *poCoordBlock;
-    int                 nStringLen;
 
     /*-----------------------------------------------------------------
      * We assume that ValidateMapInfoType() was called already and that
@@ -5654,7 +5461,8 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
         poPoint = (OGRPoint*)poGeom;
     else
@@ -5672,17 +5480,18 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
      * that we have to keep like that for the MAP file.
      * See MapTools bug 1107 for more details.
      *----------------------------------------------------------------*/
+    TABMAPCoordBlock *poCoordBlock = NULL;
     if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
         poCoordBlock = *ppoCoordBlock;
     else
         poCoordBlock = poMapFile->GetCurCoordBlock();
     poCoordBlock->StartNewFeature();
-    nCoordBlockPtr = poCoordBlock->GetCurAddress();
+    GInt32 nCoordBlockPtr = poCoordBlock->GetCurAddress();
 
     // This string was escaped before 20050714
     char *pszTmpString = m_pszString;
 
-    nStringLen = static_cast<int>(strlen(pszTmpString));
+    int nStringLen = static_cast<int>(strlen(pszTmpString));
 
     if (nStringLen > 0)
     {
@@ -5728,7 +5537,10 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
      * The Feature's MBR is the MBR of the text after rotation... that's
      * what MapInfo uses to define the text location.
      *----------------------------------------------------------------*/
-    double dXMin, dYMin, dXMax, dYMax;
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     // Make sure Feature MBR is in sync with other params
 
     UpdateMBR();
@@ -5738,7 +5550,8 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     poMapFile->Coordsys2Int(dXMax, dYMax, nXMax, nYMax);
 
     // Label line end point
-    double dX, dY;
+    double dX = 0.0;
+    double dY = 0.0;
     GetTextLineEndPoint(dX, dY); // Make sure a default line end point is set
     poMapFile->Coordsys2Int(m_dfLineEndX, m_dfLineEndY,
                            poTextHdr->m_nLineEndX, poTextHdr->m_nLineEndY);
@@ -5775,7 +5588,6 @@ int TABText::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABText::GetTextString()
  *
@@ -5878,7 +5690,10 @@ void TABText::GetTextLineEndPoint(double &dX, double &dY)
     if (!m_bLineEndSet)
     {
         // Set default location at center of text MBR
-        double dXMin, dYMin, dXMax, dYMax;
+        double dXMin = 0.0;
+        double dYMin = 0.0;
+        double dXMax = 0.0;
+        double dYMax = 0.0;
         UpdateMBR();
         GetMBR(dXMin, dYMin, dXMax, dYMax);
         m_dfLineEndX = (dXMin + dXMax) /2.0;
@@ -5910,39 +5725,38 @@ void TABText::SetTextLineEndPoint(double dX, double dY)
  **********************************************************************/
 int TABText::UpdateMBR(TABMAPFile * poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-    OGRPoint *poPoint=NULL;
-
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
     {
-        double dSin, dCos, dX0, dY0, dX1, dY1;
-        double dX[4], dY[4];
-        poPoint = (OGRPoint *)poGeom;
+        OGRPoint *poPoint = (OGRPoint *)poGeom;
 
-        dX0 = poPoint->getX();
-        dY0 = poPoint->getY();
+        const double dX0 = poPoint->getX();
+        const double dY0 = poPoint->getY();
 
-        dSin = sin(m_dAngle*M_PI/180.0);
-        dCos = cos(m_dAngle*M_PI/180.0);
+        const double dSin = sin(m_dAngle*M_PI/180.0);
+        const double dCos = cos(m_dAngle*M_PI/180.0);
 
         GetTextBoxWidth();  // Force default width value if necessary.
 
-        dX[0] = dX0;
-        dY[0] = dY0;
-        dX[1] = dX0 + m_dWidth;
-        dY[1] = dY0;
-        dX[2] = dX0 + m_dWidth;
-        dY[2] = dY0 + m_dHeight;
-        dX[3] = dX0;
-        dY[3] = dY0 + m_dHeight;
+        const double dX[4] = {
+            dX0,
+            dX0 + m_dWidth,
+            dX0 + m_dWidth,
+            dX0
+        };
+        const double dY[4] = {
+            dY0,
+            dY0,
+            dY0 + m_dHeight,
+            dY0 + m_dHeight
+        };
 
         SetMBR(dX0, dY0, dX0, dY0);
-        for(int i=0; i<4; i++)
+        for( int i = 0; i < 4; i++ )
         {
             // Rotate one of the box corners
-            dX1 = dX0 + (dX[i]-dX0)*dCos - (dY[i]-dY0)*dSin;
-            dY1 = dY0 + (dX[i]-dX0)*dSin + (dY[i]-dY0)*dCos;
+            const double dX1 = dX0 + (dX[i]-dX0)*dCos - (dY[i]-dY0)*dSin;
+            const double dY1 = dY0 + (dX[i]-dX0)*dSin + (dY[i]-dY0)*dCos;
 
             // And update feature MBR with rotated coordinate
             if (dX1 < m_dXMin) m_dXMin = dX1;
@@ -6127,7 +5941,6 @@ void TABText::ToggleFontStyle(TABFontStyle eStyleToToggle, GBool bStyleOn)
         m_nFontStyle &=  ~ (int)eStyleToToggle;
 }
 
-
 /**********************************************************************
  *                   TABText::GetFontStyleMIFValue()
  *
@@ -6160,37 +5973,37 @@ void TABText:: SetFontStyleMIFValue(int nStyle, GBool bBGColorSet)
 int TABText::IsFontBGColorUsed()
 {
     // Font BG color is used only when BOX is set.
-    return (QueryFontStyle(TABFSBox));
+    return QueryFontStyle(TABFSBox);
 }
 
 int TABText::IsFontOColorUsed()
 {
     // Font outline color is used only when HALO is set.
-    return (QueryFontStyle(TABFSHalo));
+    return QueryFontStyle(TABFSHalo);
 }
 
 int TABText::IsFontSColorUsed()
 {
     // Font shadow color is used only when Shadow is set.
-    return (QueryFontStyle(TABFSShadow));
+    return QueryFontStyle(TABFSShadow);
 }
 
 int TABText::IsFontBold()
 {
     // Font bold is used only when Bold is set.
-    return (QueryFontStyle(TABFSBold));
+    return QueryFontStyle(TABFSBold);
 }
 
 int TABText::IsFontItalic()
 {
     // Font italic is used only when Italic is set.
-    return (QueryFontStyle(TABFSItalic));
+    return QueryFontStyle(TABFSItalic);
 }
 
 int TABText::IsFontUnderline()
 {
     // Font underline is used only when Underline is set.
-    return (QueryFontStyle(TABFSUnderline));
+    return QueryFontStyle(TABFSUnderline);
 }
 
 /**********************************************************************
@@ -6262,15 +6075,15 @@ const char *TABText::GetLabelStyleString()
                 pszTextString[i] = (char)toupper(pszTextString[i]);
 
     /* Escape the double quote chars and expand the text */
-    char *pszTmpTextString;
-    int j = 0;
+    char *pszTmpTextString = NULL;
 
     if  (QueryFontStyle(TABFSExpanded))
         pszTmpTextString = (char*)CPLMalloc(((nStringLen*4)+1)*sizeof(char));
     else
         pszTmpTextString = (char*)CPLMalloc(((nStringLen*2)+1)*sizeof(char));
 
-    for (int i =0; i < nStringLen; ++i,++j)
+    int j = 0;
+    for( int i = 0; i < nStringLen; ++i,++j )
     {
         if (pszTextString[i] == '"')
         {
@@ -6311,7 +6124,6 @@ const char *TABText::GetLabelStyleString()
 
     CPLFree(pszTextString);
     return pszStyle;
-
 }
 
 /**********************************************************************
@@ -6331,8 +6143,6 @@ const char *TABText::GetStyleString()
     return m_pszStyleString;
 }
 
-
-
 /**********************************************************************
  *                   TABText::DumpMIF()
  *
@@ -6340,22 +6150,19 @@ const char *TABText::GetStyleString()
  **********************************************************************/
 void TABText::DumpMIF(FILE *fpOut /*=NULL*/)
 {
-    OGRGeometry   *poGeom;
-    OGRPoint      *poPoint = NULL;
-
     if (fpOut == NULL)
         fpOut = stdout;
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
     {
         /*-------------------------------------------------------------
          * Generate output for text object
          *------------------------------------------------------------*/
-        poPoint = (OGRPoint*)poGeom;
+        OGRPoint *poPoint = (OGRPoint*)poGeom;
 
         fprintf(fpOut, "TEXT \"%s\" %.15g %.15g\n", m_pszString?m_pszString:"",
                 poPoint->getX(), poPoint->getY());
@@ -6393,22 +6200,19 @@ void TABText::DumpMIF(FILE *fpOut /*=NULL*/)
  *
  * Constructor.
  **********************************************************************/
-TABMultiPoint::TABMultiPoint(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
-{
-    m_bCenterIsSet = FALSE;
-    m_dCenterX = 0;
-    m_dCenterY = 0;
-}
+TABMultiPoint::TABMultiPoint( OGRFeatureDefn *poDefnIn ) :
+    TABFeature(poDefnIn),
+    m_bCenterIsSet(FALSE),
+    m_dCenterX(0.0),
+    m_dCenterY(0.0)
+{}
 
 /**********************************************************************
  *                   TABMultiPoint::~TABMultiPoint()
  *
  * Destructor.
  **********************************************************************/
-TABMultiPoint::~TABMultiPoint()
-{
-}
+TABMultiPoint::~TABMultiPoint() {}
 
 /**********************************************************************
  *                     TABMultiPoint::CloneTABFeature()
@@ -6440,7 +6244,6 @@ TABFeature *TABMultiPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
     return poNew;
 }
 
-
 /**********************************************************************
  *                   TABMultiPoint::ValidateMapInfoType()
  *
@@ -6453,12 +6256,10 @@ TABFeature *TABMultiPoint::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
  **********************************************************************/
 TABGeomType TABMultiPoint::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint)
     {
         OGRMultiPoint *poMPoint = (OGRMultiPoint*)poGeom;
@@ -6483,8 +6284,6 @@ TABGeomType TABMultiPoint::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
     return m_nMapInfoType;
 }
 
-
-
 /**********************************************************************
  *                   TABMultiPoint::ReadGeometryFromMAPFile()
  *
@@ -6502,8 +6301,10 @@ int TABMultiPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                            GBool bCoordBlockDataOnly /*=FALSE*/,
                                            TABMAPCoordBlock **ppoCoordBlock/*=NULL*/)
 {
-    GInt32              nX, nY;
-    double              dX, dY, dXMin, dYMin, dXMax, dYMax;
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     OGRGeometry         *poGeometry=NULL;
     GBool               bComprCoord = poObjHdr->IsCompressedType();
     TABMAPCoordBlock    *poCoordBlock = NULL;
@@ -6538,6 +6339,8 @@ int TABMultiPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             poMapFile->ReadSymbolDef(m_nSymbolDefIndex, &m_sSymbolDef);
         }
 
+        double dX = 0.0;
+        double dY = 0.0;
         // Centroid/label point
         poMapFile->Int2Coordsys(poMPointHdr->m_nLabelX, poMPointHdr->m_nLabelY,
                                 dX, dY);
@@ -6550,8 +6353,8 @@ int TABMultiPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         /*-------------------------------------------------------------
          * Read Point Coordinates
          *------------------------------------------------------------*/
-        OGRMultiPoint   *poMultiPoint;
-        poGeometry = poMultiPoint = new OGRMultiPoint();
+        OGRMultiPoint   *poMultiPoint = new OGRMultiPoint();
+        poGeometry = poMultiPoint;
 
         if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
             poCoordBlock = *ppoCoordBlock;
@@ -6567,6 +6370,8 @@ int TABMultiPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
         for(int iPoint=0; iPoint<poMPointHdr->m_nNumPoints; iPoint++)
         {
+            GInt32 nX = 0;
+            GInt32 nY = 0;
             if (poCoordBlock->ReadIntCoord(bComprCoord, nX, nY) != 0)
             {
                 CPLError(CE_Failure, CPLE_FileIO,
@@ -6581,10 +6386,9 @@ int TABMultiPoint::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
 
             if (poMultiPoint->addGeometryDirectly(poPoint) != OGRERR_NONE)
             {
-                CPLAssert(FALSE); // Just in case lower-level lib is modified
+                CPLAssert(false); // Just in case lower-level lib is modified
             }
         }
-
     }
     else
     {
@@ -6628,8 +6432,6 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                                           TABMAPCoordBlock **ppoCoordBlock/*=NULL*/)
 {
     GInt32              nX, nY;
-    OGRGeometry         *poGeom;
-    OGRMultiPoint       *poMPoint;
 
     /*-----------------------------------------------------------------
      * We assume that ValidateMapInfoType() was called already and that
@@ -6642,7 +6444,8 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRMultiPoint *poMPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint)
         poMPoint = (OGRMultiPoint*)poGeom;
     else
@@ -6657,10 +6460,9 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     /*-----------------------------------------------------------------
      * Write data to coordinate block
      *----------------------------------------------------------------*/
-    int iPoint, nStatus;
-    TABMAPCoordBlock *poCoordBlock;
-    GBool   bCompressed = poObjHdr->IsCompressedType();
+    const GBool bCompressed = poObjHdr->IsCompressedType();
 
+    TABMAPCoordBlock *poCoordBlock = NULL;
     if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
         poCoordBlock = *ppoCoordBlock;
     else
@@ -6669,9 +6471,9 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     poMPointHdr->m_nCoordBlockPtr = poCoordBlock->GetCurAddress();
     poCoordBlock->SetComprCoordOrigin(m_nComprOrgX, m_nComprOrgY);
 
-
-    for(iPoint=0, nStatus=0;
-        nStatus == 0 && iPoint < poMPointHdr->m_nNumPoints; iPoint++)
+    for( int iPoint=0, nStatus=0;
+         nStatus == 0 && iPoint < poMPointHdr->m_nNumPoints;
+         iPoint++)
     {
         poGeom = poMPoint->getGeometryRef(iPoint);
 
@@ -6693,7 +6495,6 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
                 // Failed ... error message has already been produced
                 return nStatus;
             }
-
         }
         else
         {
@@ -6715,7 +6516,8 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     poMPointHdr->SetMBR(m_nXMin, m_nYMin, m_nXMax, m_nYMax);
 
     // Center/label point (default value already set above)
-    double dX, dY;
+    double dX = 0.0;
+    double dY = 0.0;
     if (GetCenter(dX, dY) != -1)
     {
         poMapFile->Coordsys2Int(dX, dY, poMPointHdr->m_nLabelX,
@@ -6740,20 +6542,17 @@ int TABMultiPoint::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMultiPoint::GetXY()
  *
  * Return this point's X,Y coordinates.
  **********************************************************************/
-int TABMultiPoint::GetXY(int i, double &dX, double &dY)
+int TABMultiPoint::GetXY( int i, double &dX, double &dY )
 {
-    OGRGeometry *poGeom;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint)
     {
         OGRMultiPoint *poMPoint = (OGRMultiPoint*)poGeom;
@@ -6772,7 +6571,8 @@ int TABMultiPoint::GetXY(int i, double &dX, double &dY)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
                  "TABMultiPoint: Missing or Invalid Geometry!");
-        dX = dY = 0.0;
+        dX = 0.0;
+        dY = 0.0;
         return -1;
     }
 
@@ -6786,12 +6586,10 @@ int TABMultiPoint::GetXY(int i, double &dX, double &dY)
  **********************************************************************/
 int TABMultiPoint::GetNumPoints()
 {
-    OGRGeometry *poGeom;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint)
     {
         OGRMultiPoint *poMPoint = (OGRMultiPoint*)poGeom;
@@ -6806,7 +6604,6 @@ int TABMultiPoint::GetNumPoints()
     }
 }
 
-
 /**********************************************************************
  *                   TABMultiPoint::GetStyleString()
  *
@@ -6835,7 +6632,7 @@ const char *TABMultiPoint::GetStyleString()
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMultiPoint::GetCenter(double &dX, double &dY)
+int TABMultiPoint::GetCenter( double &dX, double &dY )
 {
     if (!m_bCenterIsSet && GetNumPoints() > 0)
     {
@@ -6865,7 +6662,6 @@ void TABMultiPoint::SetCenter(double dX, double dY)
     m_bCenterIsSet = TRUE;
 }
 
-
 /**********************************************************************
  *                   TABMultiPoint::DumpMIF()
  *
@@ -6873,16 +6669,14 @@ void TABMultiPoint::SetCenter(double dX, double dY)
  **********************************************************************/
 void TABMultiPoint::DumpMIF(FILE *fpOut /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-    OGRMultiPoint *poMPoint;
-
     if (fpOut == NULL)
         fpOut = stdout;
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRMultiPoint *poMPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint)
         poMPoint = (OGRMultiPoint*)poGeom;
     else
@@ -6931,13 +6725,12 @@ void TABMultiPoint::DumpMIF(FILE *fpOut /*=NULL*/)
  *
  * Constructor.
  **********************************************************************/
-TABCollection::TABCollection(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
-{
-    m_poRegion = NULL;
-    m_poPline = NULL;
-    m_poMpoint = NULL;
-}
+TABCollection::TABCollection( OGRFeatureDefn *poDefnIn ) :
+    TABFeature(poDefnIn),
+    m_poRegion(NULL),
+    m_poPline(NULL),
+    m_poMpoint(NULL)
+{}
 
 /**********************************************************************
  *                   TABCollection::~TABCollection()
@@ -6977,7 +6770,6 @@ void TABCollection::EmptyCollection()
 
     // Empty OGR Geometry Collection as well
     SyncOGRGeometryCollection(TRUE, TRUE, TRUE);
-
 }
 
 /**********************************************************************
@@ -7013,7 +6805,6 @@ TABFeature *TABCollection::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
     return poNew;
 }
 
-
 /**********************************************************************
  *                   TABCollection::ValidateMapInfoType()
  *
@@ -7026,14 +6817,15 @@ TABFeature *TABCollection::CloneTABFeature(OGRFeatureDefn *poNewDefn /*=NULL*/)
  **********************************************************************/
 TABGeomType TABCollection::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
 {
-    OGRGeometry *poGeom;
-    int nRegionType=TAB_GEOM_NONE, nPLineType=TAB_GEOM_NONE,
-        nMPointType=TAB_GEOM_NONE, nVersion = 650;
+    int nRegionType=TAB_GEOM_NONE;
+    int nPLineType=TAB_GEOM_NONE;
+    int nMPointType=TAB_GEOM_NONE;
+    int nVersion = 650;
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbGeometryCollection)
     {
         m_nMapInfoType = TAB_GEOM_COLLECTION;
@@ -7093,7 +6885,10 @@ TABGeomType TABCollection::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
     // of each component
     if (m_poRegion && nRegionType != TAB_GEOM_NONE)
     {
-        GInt32 nXMin=0, nYMin=0, nXMax=0, nYMax=0;
+        GInt32 nXMin = 0;
+        GInt32 nYMin = 0;
+        GInt32 nXMax = 0;
+        GInt32 nYMax = 0;
         m_poRegion->GetIntMBR(nXMin, nYMin, nXMax, nYMax);
         m_poRegion->ForceCoordTypeAndOrigin((nVersion == 800 ?
                                              TAB_GEOM_V800_REGION:
@@ -7103,7 +6898,6 @@ TABGeomType TABCollection::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
                                             nXMin, nYMin, nXMax, nYMax);
     }
 
-
     if (m_poPline && nPLineType != TAB_GEOM_NONE)
     {
         GInt32 nXMin, nYMin, nXMax, nYMax;
@@ -7128,11 +6922,9 @@ TABGeomType TABCollection::ValidateMapInfoType(TABMAPFile *poMapFile /*=NULL*/)
                                             nXMin, nYMin, nXMax, nYMax);
     }
 
-
     return m_nMapInfoType;
 }
 
-
 /**********************************************************************
  *                   TABCollection::ReadLabelAndMBR()
  *
@@ -7201,14 +6993,13 @@ int  TABCollection::WriteLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
                                      GInt32 nMaxX, GInt32 nMaxY,
                                      GInt32 nLabelX, GInt32 nLabelY )
 {
-    int nStatus;
-
     //
     // The sections in the collection's coord blocks start with center/label
     // point + MBR that are normally found in the object data blocks
     // of regular region/pline/mulitpoint objects.
     //
 
+    int nStatus = 0;
     if ((nStatus = poCoordBlock->WriteIntCoord(nLabelX, nLabelY,
                                                bComprCoord)) != 0 ||
         (nStatus = poCoordBlock->WriteIntCoord(nMinX, nMinY,
@@ -7223,7 +7014,6 @@ int  TABCollection::WriteLabelAndMBR(TABMAPCoordBlock *poCoordBlock,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABCollection::ReadGeometryFromMAPFile()
  *
@@ -7241,10 +7031,7 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                            GBool bCoordBlockDataOnly /*=FALSE*/,
                                            TABMAPCoordBlock **ppoCoordBlock/*=NULL*/)
 {
-    double              dXMin, dYMin, dXMax, dYMax;
-    GBool               bComprCoord = poObjHdr->IsCompressedType();
-    TABMAPCoordBlock*   poCoordBlock = NULL;
-    int                 nCurCoordBlockPtr;
+    const GBool bComprCoord = poObjHdr->IsCompressedType();
 
     /*-----------------------------------------------------------------
      * Fetch and validate geometry type
@@ -7273,6 +7060,10 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     TABMAPObjCollection *poCollHdr = (TABMAPObjCollection *)poObjHdr;
 
     // MBR
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     poMapFile->Int2Coordsys(poCollHdr->m_nMinX, poCollHdr->m_nMinY,
                             dXMin, dYMin);
     poMapFile->Int2Coordsys(poCollHdr->m_nMaxX, poCollHdr->m_nMaxY,
@@ -7283,7 +7074,8 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     SetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
               poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
-    nCurCoordBlockPtr = poCollHdr->m_nCoordBlockPtr;
+    int nCurCoordBlockPtr = poCollHdr->m_nCoordBlockPtr;
+    TABMAPCoordBlock* poCoordBlock = NULL;
     if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
         poCoordBlock = *ppoCoordBlock;
     else
@@ -7315,8 +7107,7 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         // In V800 the mini-header starts with a copy of num_parts
         if (nVersion >= 800)
         {
-            /* int numParts; */
-            /* numParts = poCoordBlock->ReadInt32(); */
+            // int numParts = poCoordBlock->ReadInt32();
             CPLAssert(poCoordBlock->ReadInt32() == poCollHdr->m_nNumRegSections);
         }
 
@@ -7355,7 +7146,6 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
             nCurCoordBlockPtr = poCoordBlock->GetCurAddress();*/
     }
 
-
     /*-----------------------------------------------------------------
      * PLine Component
      *----------------------------------------------------------------*/
@@ -7378,9 +7168,9 @@ int TABCollection::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
         // In V800 the mini-header starts with a copy of num_parts
         if (nVersion >= 800)
         {
-            /* int numParts; */
-            /* numParts = poCoordBlock->ReadInt32(); */
-            CPLAssert(poCoordBlock->ReadInt32() == poCollHdr->m_nNumPLineSections);
+            // int numParts = poCoordBlock->ReadInt32();
+            CPLAssert(poCoordBlock->ReadInt32() ==
+                      poCollHdr->m_nNumPLineSections);
         }
 
         ReadLabelAndMBR(poCoordBlock, bComprCoord,
@@ -7515,7 +7305,6 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
      * won't work unless OGRFeature::SetGeometry*() are made virtual in OGR.
      *----------------------------------------------------------------*/
 
-
     /*-----------------------------------------------------------------
      * We assume that ValidateMapInfoType() was called already and that
      * the type in poObjHdr->m_nType is valid.
@@ -7533,13 +7322,13 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
      * ForceCoordTypeAndCoordOrigin() so the objects are ready to have
      * their respective WriteGeometryToMapFile() called.
      *----------------------------------------------------------------*/
-    TABMAPCoordBlock *poCoordBlock;
-    GBool   bCompressed = poObjHdr->IsCompressedType();
+    const GBool   bCompressed = poObjHdr->IsCompressedType();
     // TODO: ??? Do we need to track overall collection coord data size???
     int     nTotalFeatureDataSize = 0;
 
-    int nVersion = TAB_GEOM_GET_VERSION(m_nMapInfoType);
+    const int nVersion = TAB_GEOM_GET_VERSION(m_nMapInfoType);
 
+    TABMAPCoordBlock *poCoordBlock = NULL;
     if (ppoCoordBlock != NULL && *ppoCoordBlock != NULL)
         poCoordBlock = *ppoCoordBlock;
     else
@@ -7745,7 +7534,6 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         poCollHdr->m_nPolylinePenId = 0;
     }
 
-
     /*-----------------------------------------------------------------
      * MultiPoint component
      *----------------------------------------------------------------*/
@@ -7832,7 +7620,6 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
         poCollHdr->m_nMultiPointSymbolId = 0;
     }
 
-
     /*-----------------------------------------------------------------
      * Copy object information
      *----------------------------------------------------------------*/
@@ -7845,7 +7632,6 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
 
     poCollHdr->SetMBR(m_nXMin, m_nYMin, m_nXMax, m_nYMax);
 
-
     if (CPLGetLastErrorNo() != 0)
         return -1;
 
@@ -7858,7 +7644,6 @@ int TABCollection::WriteGeometryToMAPFile(TABMAPFile *poMapFile,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABCollection::SyncOGRGeometryCollection()
  *
@@ -7870,7 +7655,7 @@ int    TABCollection::SyncOGRGeometryCollection(GBool bSyncRegion,
                                                 GBool bSyncMpoint)
 {
     OGRGeometry         *poThisGeom = GetGeometryRef();
-    OGRGeometryCollection *poGeomColl;
+    OGRGeometryCollection *poGeomColl = NULL;
 
     // poGeometry is defined in the OGRFeature class
     if (poThisGeom == NULL)
@@ -7941,7 +7726,6 @@ int    TABCollection::SyncOGRGeometryCollection(GBool bSyncRegion,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABCollection::SetRegionDirectly()
  *
@@ -8005,7 +7789,6 @@ int    TABCollection::SetMultiPointDirectly(TABMultiPoint *poMpoint)
     return SyncOGRGeometryCollection(FALSE, FALSE, TRUE);
 }
 
-
 /**********************************************************************
  *                   TABCollection::GetStyleString()
  *
@@ -8023,7 +7806,6 @@ const char *TABCollection::GetStyleString()
     return m_pszStyleString;
 }
 
-
 /**********************************************************************
  *                   TABCollection::DumpMIF()
  *
@@ -8053,7 +7835,6 @@ void TABCollection::DumpMIF(FILE *fpOut /*=NULL*/)
     if (m_poMpoint)
         m_poMpoint->DumpMIF(fpOut);
 
-
     DumpSymbolDef(fpOut);
 
     fflush(fpOut);
@@ -8068,12 +7849,13 @@ void TABCollection::DumpMIF(FILE *fpOut /*=NULL*/)
  *
  * Constructor.
  **********************************************************************/
-TABDebugFeature::TABDebugFeature(OGRFeatureDefn *poDefnIn):
-              TABFeature(poDefnIn)
+TABDebugFeature::TABDebugFeature( OGRFeatureDefn *poDefnIn ) :
+    TABFeature(poDefnIn),
+    m_nSize(0),
+    m_nCoordDataPtr(0),
+    m_nCoordDataSize(0)
 {
-    m_nSize = 0;
-    m_nCoordDataPtr = 0;
-    m_nCoordDataSize = 0;
+    memset( m_abyBuf, 0, sizeof(m_abyBuf) );
 }
 
 /**********************************************************************
@@ -8081,9 +7863,7 @@ TABDebugFeature::TABDebugFeature(OGRFeatureDefn *poDefnIn):
  *
  * Destructor.
  **********************************************************************/
-TABDebugFeature::~TABDebugFeature()
-{
-}
+TABDebugFeature::~TABDebugFeature() {}
 
 /**********************************************************************
  *                   TABDebugFeature::ReadGeometryFromMAPFile()
@@ -8102,16 +7882,13 @@ int TABDebugFeature::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
                                              GBool /*bCoordBlockDataOnly=FALSE*/,
                                              TABMAPCoordBlock ** /*ppoCoordBlock=NULL*/)
 {
-    TABMAPObjectBlock   *poObjBlock;
-    TABMAPHeaderBlock   *poHeader;
-
     /*-----------------------------------------------------------------
      * Fetch geometry type
      *----------------------------------------------------------------*/
     m_nMapInfoType = poObjHdr->m_nType;
 
-    poObjBlock = poMapFile->GetCurObjBlock();
-    poHeader = poMapFile->GetHeaderBlock();
+    TABMAPObjectBlock *poObjBlock = poMapFile->GetCurObjBlock();
+    TABMAPHeaderBlock *poHeader = poMapFile->GetHeaderBlock();
 
     /*-----------------------------------------------------------------
      * If object type has coords in a type 3 block, then its position
@@ -8132,7 +7909,10 @@ int TABDebugFeature::ReadGeometryFromMAPFile(TABMAPFile *poMapFile,
     if (m_nSize > 0)
     {
         poObjBlock->GotoByteRel(-5);    // Go back to beginning of header
-        poObjBlock->ReadBytes(MIN(m_nSize, (int)sizeof(m_abyBuf)), m_abyBuf);
+        poObjBlock->ReadBytes(
+           std::min(m_nSize,
+                    static_cast<int>(sizeof(m_abyBuf))),
+           m_abyBuf);
     }
 
     return 0;
@@ -8169,8 +7949,6 @@ int TABDebugFeature::WriteGeometryToMAPFile(TABMAPFile * /*poMapFile*/,
  **********************************************************************/
 void TABDebugFeature::DumpMIF(FILE *fpOut /*=NULL*/)
 {
-    int i;
-
     if (fpOut == NULL)
         fpOut = stdout;
 
@@ -8181,16 +7959,14 @@ void TABDebugFeature::DumpMIF(FILE *fpOut /*=NULL*/)
     fprintf(fpOut, "  m_nCoordDataSize = %d\n", m_nCoordDataSize);
     fprintf(fpOut, "  ");
 
-    for(i=0; i<m_nSize; i++)
+    for( int i = 0; i < m_nSize; i++ )
         fprintf(fpOut, " %2.2x", m_abyBuf[i]);
 
     fprintf(fpOut, "  \n");
 
-
     fflush(fpOut);
 }
 
-
 /*=====================================================================
  *                      class ITABFeaturePen
  *====================================================================*/
@@ -8199,16 +7975,13 @@ void TABDebugFeature::DumpMIF(FILE *fpOut /*=NULL*/)
  *                   ITABFeaturePen::ITABFeaturePen()
  **********************************************************************/
 
-ITABFeaturePen::ITABFeaturePen()
-{
-    static const TABPenDef csDefaultPen = MITAB_PEN_DEFAULT;
-
-    m_nPenDefIndex=-1;
-
-    /* MI default is PEN(1,2,0) */
-    m_sPenDef = csDefaultPen;
-}
+// MI default is PEN(1, 2, 0)
+static const TABPenDef csDefaultPen = MITAB_PEN_DEFAULT;
 
+ITABFeaturePen::ITABFeaturePen() :
+    m_nPenDefIndex(-1),
+    m_sPenDef(csDefaultPen)
+{}
 
 /**********************************************************************
  *                   ITABFeaturePen::GetPenWidthPixel()
@@ -8241,7 +8014,10 @@ GByte ITABFeaturePen::GetPenWidthPixel()
 
 void  ITABFeaturePen::SetPenWidthPixel(GByte val)
 {
-    m_sPenDef.nPixelWidth = MIN(MAX(val, 1), 7);
+    const GByte nPixelWidthMin = 1;
+    const GByte nPixelWidthMax = 7;
+    m_sPenDef.nPixelWidth =
+        std::min(std::max(val, nPixelWidthMin), nPixelWidthMax);
     m_sPenDef.nPointWidth = 0;
 }
 
@@ -8253,7 +8029,8 @@ double ITABFeaturePen::GetPenWidthPoint()
 
 void  ITABFeaturePen::SetPenWidthPoint(double val)
 {
-    m_sPenDef.nPointWidth = MIN(MAX(((int)(val*10)), 1), 2037);
+    m_sPenDef.nPointWidth =
+         std::min(std::max(static_cast<int>(val*10), 1), 2037);
     m_sPenDef.nPixelWidth = 1;
 }
 
@@ -8271,16 +8048,16 @@ int     ITABFeaturePen::GetPenWidthMIF()
              (m_sPenDef.nPointWidth+10): m_sPenDef.nPixelWidth );
 }
 
-void  ITABFeaturePen::SetPenWidthMIF(int val)
+void ITABFeaturePen::SetPenWidthMIF( int val )
 {
     if (val > 10)
     {
-        m_sPenDef.nPointWidth = MIN((val-10), 2037);
+        m_sPenDef.nPointWidth = std::min((val-10), 2037);
         m_sPenDef.nPixelWidth = 0;
     }
     else
     {
-        m_sPenDef.nPixelWidth = (GByte)MIN(MAX(val, 1), 7);
+        m_sPenDef.nPixelWidth = (GByte)std::min(std::max(val, 1), 7);
         m_sPenDef.nPointWidth = 0;
     }
 }
@@ -8444,19 +8221,8 @@ const char *ITABFeaturePen::GetPenStyleString()
  **********************************************************************/
 void  ITABFeaturePen::SetPenFromStyleString(const char *pszStyleString)
 {
-    int numParts, i;
     GBool bIsNull = 0;
 
-    const char *pszPenName, *pszPenPattern;
-
-    double nPenWidth;
-
-    GInt32 nPenColor;
-    const char *pszPenColor;
-
-    int   nPenId;
-    const char* pszPenId;
-
     // Use the Style Manager to retrieve all the information we need.
     OGRStyleMgr *poStyleMgr = new OGRStyleMgr(NULL);
     OGRStyleTool *poStylePart = NULL;
@@ -8465,8 +8231,8 @@ void  ITABFeaturePen::SetPenFromStyleString(const char *pszStyleString)
     poStyleMgr->InitStyleString(pszStyleString);
 
     // Retrieve the Pen info.
-    numParts = poStyleMgr->GetPartCount();
-    for(i=0; i<numParts; i++)
+    const int numParts = poStyleMgr->GetPartCount();
+    for( int i = 0; i < numParts; i++ )
     {
         poStylePart = poStyleMgr->GetPart(i);
         if( poStylePart == NULL )
@@ -8503,13 +8269,13 @@ void  ITABFeaturePen::SetPenFromStyleString(const char *pszStyleString)
     poPenStyle->SetUnit(OGRSTUPoints, 1);
 
     // Get the Pen Id or pattern
-    pszPenName = poPenStyle->Id(bIsNull);
+    const char *pszPenName = poPenStyle->Id(bIsNull);
     if (bIsNull) pszPenName = NULL;
 
     // Set the width
-    if(poPenStyle->Width(bIsNull))
+    if(poPenStyle->Width(bIsNull) != 0.0)
     {
-        nPenWidth = poPenStyle->Width(bIsNull);
+        const double nPenWidth = poPenStyle->Width(bIsNull);
         // Width < 10 is a pixel
         if(nPenWidth > 10)
             SetPenWidthPoint(nPenWidth);
@@ -8518,21 +8284,25 @@ void  ITABFeaturePen::SetPenFromStyleString(const char *pszStyleString)
     }
 
     //Set the color
-    pszPenColor = poPenStyle->Color(bIsNull);
+    const char *pszPenColor = poPenStyle->Color(bIsNull);
     if(pszPenColor != NULL)
     {
         if(pszPenColor[0] == '#')
             pszPenColor++;
         // The Pen color is an Hexa string that need to be convert in a int
-        nPenColor = static_cast<int>(strtol(pszPenColor, NULL, 16));
+        const GInt32 nPenColor =
+            static_cast<int>(strtol(pszPenColor, NULL, 16));
         SetPenColor(nPenColor);
     }
 
+    const char *pszPenPattern = NULL;
+
+    int nPenId = 0;
     // Set the Id of the Pen, use Pattern if necessary.
     if(pszPenName &&
        (strstr(pszPenName, "mapinfo-pen-") || strstr(pszPenName, "ogr-pen-")) )
     {
-        pszPenId = strstr(pszPenName, "mapinfo-pen-");
+        const char* pszPenId = strstr(pszPenName, "mapinfo-pen-");
         if( pszPenId != NULL )
         {
             nPenId = atoi(pszPenId+12);
@@ -8625,8 +8395,8 @@ void ITABFeaturePen::DumpPenDef(FILE *fpOut /*=NULL*/)
 
     fprintf(fpOut, "  m_nPenDefIndex         = %d\n", m_nPenDefIndex);
     fprintf(fpOut, "  m_sPenDef.nRefCount    = %d\n", m_sPenDef.nRefCount);
-    fprintf(fpOut, "  m_sPenDef.nPixelWidth  = %d\n", m_sPenDef.nPixelWidth);
-    fprintf(fpOut, "  m_sPenDef.nLinePattern = %d\n", m_sPenDef.nLinePattern);
+    fprintf(fpOut, "  m_sPenDef.nPixelWidth  = %u\n", m_sPenDef.nPixelWidth);
+    fprintf(fpOut, "  m_sPenDef.nLinePattern = %u\n", m_sPenDef.nLinePattern);
     fprintf(fpOut, "  m_sPenDef.nPointWidth  = %d\n", m_sPenDef.nPointWidth);
     fprintf(fpOut, "  m_sPenDef.rgbColor     = 0x%6.6x (%d)\n",
                                      m_sPenDef.rgbColor, m_sPenDef.rgbColor);
@@ -8642,16 +8412,13 @@ void ITABFeaturePen::DumpPenDef(FILE *fpOut /*=NULL*/)
  *                   ITABFeatureBrush::ITABFeatureBrush()
  **********************************************************************/
 
-ITABFeatureBrush::ITABFeatureBrush()
-{
-    static const TABBrushDef csDefaultBrush = MITAB_BRUSH_DEFAULT;
-
-    m_nBrushDefIndex=-1;
-
-    /* MI default is BRUSH(2,16777215,16777215) */
-    m_sBrushDef = csDefaultBrush;
-}
+// MI default is BRUSH(2, 16777215, 16777215)
+static const TABBrushDef csDefaultBrush = MITAB_BRUSH_DEFAULT;
 
+ITABFeatureBrush::ITABFeatureBrush() :
+    m_nBrushDefIndex(-1),
+    m_sBrushDef(csDefaultBrush)
+{}
 
 /**********************************************************************
  *                   ITABFeatureBrush::GetBrushStyleString()
@@ -8698,7 +8465,6 @@ const char *ITABFeatureBrush::GetBrushStyleString()
      return pszStyle;
 }
 
-
 /**********************************************************************
  *                   ITABFeatureBrush::SetBrushFromStyleString()
  *
@@ -8707,15 +8473,8 @@ const char *ITABFeatureBrush::GetBrushStyleString()
  **********************************************************************/
 void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
 {
-    int numParts, i;
     GBool bIsNull = 0;
 
-    const char *pszBrushId;
-    int nBrushId;
-
-    const char *pszBrushColor;
-    int nBrushColor;
-
     // Use the Style Manager to retrieve all the information we need.
     OGRStyleMgr *poStyleMgr = new OGRStyleMgr(NULL);
     OGRStyleTool *poStylePart = NULL;
@@ -8724,8 +8483,8 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     poStyleMgr->InitStyleString(pszStyleString);
 
     // Retrieve the Brush info.
-    numParts = poStyleMgr->GetPartCount();
-    for(i=0; i<numParts; i++)
+    const int numParts = poStyleMgr->GetPartCount();
+    for( int i = 0; i < numParts; i++ )
     {
         poStylePart = poStyleMgr->GetPart(i);
         if( poStylePart == NULL )
@@ -8752,7 +8511,7 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     OGRStyleBrush *poBrushStyle = (OGRStyleBrush*)poStylePart;
 
     // Set the Brush Id (FillPattern)
-    pszBrushId = poBrushStyle->Id(bIsNull);
+    const char *pszBrushId = poBrushStyle->Id(bIsNull);
     if(bIsNull) pszBrushId = NULL;
 
     if(pszBrushId &&
@@ -8761,12 +8520,12 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     {
         if(strstr(pszBrushId, "mapinfo-brush-"))
         {
-            nBrushId = atoi(pszBrushId+14);
+            const int nBrushId = atoi(pszBrushId+14);
             SetBrushPattern((GByte)nBrushId);
         }
         else if(strstr(pszBrushId, "ogr-brush-"))
         {
-            nBrushId = atoi(pszBrushId+10);
+            int nBrushId = atoi(pszBrushId+10);
             if(nBrushId > 1)
                 nBrushId++;
             SetBrushPattern((GByte)nBrushId);
@@ -8774,14 +8533,15 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     }
 
     // Set the BackColor, if not set, then it's transparent
-    pszBrushColor = poBrushStyle->BackColor(bIsNull);
+    const char *pszBrushColor = poBrushStyle->BackColor(bIsNull);
     if(bIsNull) pszBrushColor = NULL;
 
     if(pszBrushColor)
     {
         if(pszBrushColor[0] == '#')
             pszBrushColor++;
-        nBrushColor = static_cast<int>(strtol(pszBrushColor, NULL, 16));
+        const int nBrushColor =
+            static_cast<int>(strtol(pszBrushColor, NULL, 16));
         SetBrushBGColor((GInt32)nBrushColor);
     }
     else
@@ -8797,7 +8557,8 @@ void  ITABFeatureBrush::SetBrushFromStyleString(const char *pszStyleString)
     {
         if(pszBrushColor[0] == '#')
             pszBrushColor++;
-        nBrushColor = static_cast<int>(strtol(pszBrushColor, NULL, 16));
+        const int nBrushColor =
+            static_cast<int>(strtol(pszBrushColor, NULL, 16));
         SetBrushFGColor((GInt32)nBrushColor);
     }
 
@@ -8839,23 +8600,21 @@ void ITABFeatureBrush::DumpBrushDef(FILE *fpOut /*=NULL*/)
  *                   ITABFeatureFont::ITABFeatureFont()
  **********************************************************************/
 
-ITABFeatureFont::ITABFeatureFont()
-{
-    static const TABFontDef csDefaultFont = MITAB_FONT_DEFAULT;
+// MI default is Font("Arial", 0, 0, 0)
+static const TABFontDef csDefaultFont = MITAB_FONT_DEFAULT;
 
-    m_nFontDefIndex=-1;
-
-    /* MI default is Font("Arial",0,0,0) */
-    m_sFontDef = csDefaultFont;
-}
+ITABFeatureFont::ITABFeatureFont() :
+    m_nFontDefIndex(-1),
+    m_sFontDef(csDefaultFont)
+{}
 
 /**********************************************************************
  *                   ITABFeatureFont::SetFontName()
  **********************************************************************/
 void ITABFeatureFont::SetFontName(const char *pszName)
 {
-    strncpy( m_sFontDef.szFontName, pszName, 32);
-    m_sFontDef.szFontName[32] = '\0';
+    strncpy( m_sFontDef.szFontName, pszName, sizeof(m_sFontDef.szFontName)-1);
+    m_sFontDef.szFontName[sizeof(m_sFontDef.szFontName)-1] = '\0';
 }
 
 /**********************************************************************
@@ -8875,7 +8634,6 @@ void ITABFeatureFont::DumpFontDef(FILE *fpOut /*=NULL*/)
     fflush(fpOut);
 }
 
-
 /*=====================================================================
  *                      class ITABFeatureSymbol
  *====================================================================*/
@@ -8884,15 +8642,13 @@ void ITABFeatureFont::DumpFontDef(FILE *fpOut /*=NULL*/)
  *                   ITABFeatureSymbol::ITABFeatureSymbol()
  **********************************************************************/
 
-ITABFeatureSymbol::ITABFeatureSymbol()
-{
-    static const TABSymbolDef csDefaultSymbol = MITAB_SYMBOL_DEFAULT;
-
-    m_nSymbolDefIndex=-1;
+// MI default is Symbol(35, 0, 12)
+static const TABSymbolDef csDefaultSymbol = MITAB_SYMBOL_DEFAULT;
 
-    /* MI default is Symbol(35,0,12) */
-    m_sSymbolDef = csDefaultSymbol;
-}
+ITABFeatureSymbol::ITABFeatureSymbol() :
+    m_nSymbolDefIndex(-1),
+    m_sSymbolDef(csDefaultSymbol)
+{}
 
 /**********************************************************************
  *                   ITABFeatureSymbol::GetSymbolStyleString()
@@ -8975,17 +8731,8 @@ const char *ITABFeatureSymbol::GetSymbolStyleString(double dfAngle)
  **********************************************************************/
 void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
 {
-    int numParts, i;
     GBool bIsNull = 0;
 
-    const char *pszSymbolId;
-    int nSymbolId;
-
-    const char *pszSymbolColor;
-    int nSymbolColor;
-
-    double dSymbolSize;
-
     // Use the Style Manager to retrieve all the information we need.
     OGRStyleMgr *poStyleMgr = new OGRStyleMgr(NULL);
     OGRStyleTool *poStylePart = NULL;
@@ -8994,8 +8741,8 @@ void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
     poStyleMgr->InitStyleString(pszStyleString);
 
     // Retrieve the Symbol info.
-    numParts = poStyleMgr->GetPartCount();
-    for(i=0; i<numParts; i++)
+    const int numParts = poStyleMgr->GetPartCount();
+    for( int i = 0; i < numParts; i++ )
     {
         poStylePart = poStyleMgr->GetPart(i);
         if( poStylePart == NULL )
@@ -9031,7 +8778,7 @@ void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
     poSymbolStyle->SetUnit(OGRSTUPoints, (72.0 * 39.37));
 
     // Set the Symbol Id (SymbolNo)
-    pszSymbolId = poSymbolStyle->Id(bIsNull);
+    const char *pszSymbolId = poSymbolStyle->Id(bIsNull);
     if(bIsNull) pszSymbolId = NULL;
 
     if(pszSymbolId &&
@@ -9040,12 +8787,12 @@ void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
     {
         if(strstr(pszSymbolId, "mapinfo-sym-"))
         {
-            nSymbolId = atoi(pszSymbolId+12);
+            const int nSymbolId = atoi(pszSymbolId+12);
             SetSymbolNo((GByte)nSymbolId);
         }
         else if(strstr(pszSymbolId, "ogr-sym-"))
         {
-            nSymbolId = atoi(pszSymbolId+8);
+            const int nSymbolId = atoi(pszSymbolId+8);
 
             // The OGR symbol is not the MapInfo one
             // Here's some mapping
@@ -9089,19 +8836,19 @@ void ITABFeatureSymbol::SetSymbolFromStyleString(const char *pszStyleString)
     }
 
     // Set SymbolSize
-    dSymbolSize = poSymbolStyle->Size(bIsNull);
-    if(dSymbolSize)
+    const double dSymbolSize = poSymbolStyle->Size(bIsNull);
+    if(dSymbolSize != 0.0)
     {
         SetSymbolSize((GInt16)dSymbolSize);
     }
 
     // Set Symbol Color
-    pszSymbolColor = poSymbolStyle->Color(bIsNull);
+    const char *pszSymbolColor = poSymbolStyle->Color(bIsNull);
     if(pszSymbolColor)
     {
         if(pszSymbolColor[0] == '#')
             pszSymbolColor++;
-        nSymbolColor = static_cast<int>(strtol(pszSymbolColor, NULL, 16));
+        int nSymbolColor = static_cast<int>(strtol(pszSymbolColor, NULL, 16));
         SetSymbolColor((GInt32)nSymbolColor);
     }
 
diff --git a/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp b/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp
index 64bd6bb..079048e 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_feature_mif.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_feature_mif.cpp,v 1.39 2010-09-07 16:07:53 aboudreault Exp $
  *
  * Name:     mitab_feature.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -28,147 +27,29 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_feature_mif.cpp,v $
- * Revision 1.39  2010-09-07 16:07:53  aboudreault
- * Added the use of OGRGeometryFactory::organizePolygons for mif features
- *
- * Revision 1.38  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.37  2008-12-17 14:55:20  aboudreault
- * Fixed mitab mif/mid importer fails when a Text geometry have an empty
- * text value (bug 1978)
- *
- * Revision 1.36  2008-11-27 20:50:22  aboudreault
- * Improved support for OGR date/time types. New Read/Write methods (bug 1948)
- * Added support of OGR date/time types for MIF features.
- *
- * Revision 1.35  2008/09/23 14:56:03  aboudreault
- * Fixed an error related to the " character when converting mif to tab file.
- *
- * Revision 1.34  2008/09/23 13:45:03  aboudreault
- * Fixed bug with the characters ",\n in the tab2tab application. (bug 1945)
- *
- * Revision 1.33  2008/02/01 20:30:59  dmorissette
- * Use %.15g instead of %.16g as number precision in .MIF output
- *
- * Revision 1.32  2007/06/07 20:27:21  dmorissette
- * Fixed memory leaks when reading multipoint objects from .MIF files
- *
- * Revision 1.31  2006/01/27 13:44:44  fwarmerdam
- * fixed Mills.mif reading, crash at file end
- *
- * Revision 1.30  2006/01/26 21:26:36  fwarmerdam
- * Fixed bug with multi-character delimiters in .mid file
- *
- * Revision 1.29  2005/10/04 19:36:10  dmorissette
- * Added support for reading collections from MIF files (bug 1126)
- *
- * Revision 1.28  2005/10/04 15:44:31  dmorissette
- * First round of support for Collection objects. Currently supports reading
- * from .TAB/.MAP and writing to .MIF. Still lacks symbol support and write
- * support. (Based in part on patch and docs from Jim Hope, bug 1126)
- *
- * Revision 1.27  2005/10/04 15:35:52  dmorissette
- * Fixed an instance of hardcoded delimiter (",") in WriteRecordToMIDFile()
- * (patch by KB Kieron, bug 1126)
- *
- * Revision 1.26  2005/07/14 16:15:05  jlacroix
- * \n and \ are now unescaped internally.
- *
- * Revision 1.25  2003/12/19 07:52:34  fwarmerdam
- * write 3d as 2d
- *
- * Revision 1.24  2002/11/27 22:51:52  daniel
- * Bug 1631:Do not produce an error if .mid data records end with a stray ','
- * Treat tabs (\t) as a blank space delimiter when reading .mif coordinates
- *
- * Revision 1.23  2002/10/29 21:09:20  warmerda
- * Ensure that a blank line in a mid file is treated as one field containing
- * an empty string.
- *
- * Revision 1.22  2002/04/26 14:16:49  julien
- * Finishing the implementation of Multipoint (support for MIF)
- *
- * Revision 1.21  2002/03/26 01:48:40  daniel
- * Added Multipoint object type (V650)
- *
- * Revision 1.20  2002/01/23 20:31:21  daniel
- * Fixed warning produced by CPLAssert() in non-DEBUG mode.
- *
- * Revision 1.19  2001/06/25 01:50:42  daniel
- * Fixed MIF Text object output: negative text angles were lost.  Also use
- * TABText::SetTextAngle() when reading MIF instead of setting class members
- * directly so that negative angles get converted to the [0..360] range.
- *
- * Revision 1.18  2001/02/28 07:15:09  daniel
- * Added support for text label line end point
- *
- * Revision 1.17  2001/01/22 16:03:58  warmerda
- * expanded tabs
- *
- * Revision 1.16  2000/10/03 19:29:51  daniel
- * Include OGR StyleString stuff (implemented by Stephane)
- *
- * Revision 1.15  2000/09/28 16:39:44  warmerda
- * Avoid warnings for unused, and uninitialized variables
- *
- * Revision 1.14  2000/09/19 17:23:53  daniel
- * Maintain and/or compute valid region and polyline center/label point
- *
- * Revision 1.13  2000/03/27 03:33:45  daniel
- * Treat SYMBOL line as optional when reading TABPoint
- *
- * Revision 1.12  2000/02/28 16:56:32  daniel
- * Support pen width in points (width values 11 to 2047)
- *
- * Revision 1.11  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.10  2000/01/14 23:51:37  daniel
- * Fixed handling of "\n" in TABText strings... now the external interface
- * of the lib returns and expects escaped "\"+"n" as described in MIF specs
- *
- * Revision 1.9  1999/12/19 17:37:14  daniel
- * Fixed memory leaks
- *
- * Revision 1.8  1999/12/19 01:02:50  stephane
- * Add a test on the CENTER information
- *
- * Revision 1.7  1999/12/18 23:23:23  stephane
- * Change the format of the output double from %g to %.16g
- *
- * Revision 1.6  1999/12/18 08:22:57  daniel
- * Removed stray break statement in PLINE MULTIPLE write code
- *
- * Revision 1.5  1999/12/18 07:21:30  daniel
- * Fixed test on geometry type when writing OGRMultiLineStrings
- *
- * Revision 1.4  1999/12/18 07:11:57  daniel
- * Return regions as OGRMultiPolygons instead of multiple rings OGRPolygons
- *
- * Revision 1.3  1999/12/16 17:16:44  daniel
- * Use addRing/GeometryDirectly() (prevents leak), and rounded rectangles
- * always return real corner radius from file even if it is bigger than MBR
- *
- * Revision 1.2  1999/11/11 01:22:05  stephane
- * Remove DebugFeature call, Point Reading error, add IsValidFeature() to
- * test correctly if we are on a feature
- *
- * Revision 1.1  1999/11/08 19:20:30  stephane
- * First version
- *
- * Revision 1.1  1999/11/08 04:16:07  stephane
- * First Revision
- *
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <cctype>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
 #include "mitab_utils.h"
-#include <ctype.h>
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
+
+CPL_CVSID("$Id: mitab_feature_mif.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /*=====================================================================
  *                      class TABFeature
@@ -186,7 +67,9 @@ static char **MIDTokenize( const char *pszLine, const char *pszDelim )
 
 {
     char **papszResult = NULL;
-    int iChar, iTokenChar = 0, bInQuotes = FALSE;
+    int iChar;
+    int iTokenChar = 0;
+    int bInQuotes = FALSE;
     char *pszToken = (char *) CPLMalloc(strlen(pszLine)+1);
     int nDelimLen = static_cast<int>(strlen(pszDelim));
 
@@ -203,7 +86,7 @@ static char **MIDTokenize( const char *pszLine, const char *pszDelim )
         }
         else if( !bInQuotes && strncmp(pszLine+iChar,pszDelim,nDelimLen) == 0 )
         {
-            pszToken[iTokenChar++] = '\0';
+            pszToken[iTokenChar] = '\0';
             papszResult = CSLAddString( papszResult, pszToken );
 
             iChar += static_cast<int>(strlen(pszDelim)) - 1;
@@ -234,18 +117,20 @@ static char **MIDTokenize( const char *pszLine, const char *pszDelim )
  **********************************************************************/
 int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
 {
-    const char       *pszLine;
-    char            **papszToken;
-    int               nFields,i;
-    OGRFieldDefn        *poFDefn = NULL;
 #ifdef MITAB_USE_OFTDATETIME
-    int nYear, nMonth, nDay, nHour, nMin, nSec, nMS, nTZFlag;
-    nYear = nMonth = nDay = nHour = nMin = nSec = nMS = nTZFlag = 0;
+    int nYear = 0;
+    int nMonth = 0;
+    int nDay = 0;
+    int nHour = 0;
+    int nMin = 0;
+    int nSec = 0;
+    int nMS = 0;
+    // int nTZFlag = 0;
 #endif
 
-    nFields = GetFieldCount();
+    const int nFields = GetFieldCount();
 
-    pszLine = fp->GetLastLine();
+    const char *pszLine = fp->GetLastLine();
 
     if (pszLine == NULL)
     {
@@ -254,7 +139,7 @@ int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
         return -1;
     }
 
-    papszToken = MIDTokenize( pszLine, fp->GetDelimiter() );
+    char **papszToken = MIDTokenize( pszLine, fp->GetDelimiter() );
 
     // Ensure that a blank line in a mid file is treated as one field
     // containing an empty string.
@@ -271,7 +156,8 @@ int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
         return -1;
     }
 
-    for (i=0;i<nFields;i++)
+    OGRFieldDefn *poFDefn = NULL;
+    for( int i = 0; i < nFields; i++ )
     {
         poFDefn = GetFieldDefnRef(i);
         switch(poFDefn->GetType())
@@ -331,22 +217,26 @@ int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
 {
-    int                  iField, numFields;
-    OGRFieldDefn        *poFDefn = NULL;
+    CPLAssert(fp);
+
 #ifdef MITAB_USE_OFTDATETIME
     char szBuffer[20];
-    int nYear, nMonth, nDay, nHour, nMin, nMS, nTZFlag;
-    nYear = nMonth = nDay = nHour = nMin = nMS = nTZFlag = 0;
+    int nYear = 0;
+    int nMonth = 0;
+    int nDay = 0;
+    int nHour = 0;
+    int nMin = 0;
+    // int nMS = 0;
+    int nTZFlag = 0;
     float fSec = 0.0f;
 #endif
 
-    CPLAssert(fp);
-
     const char *delimiter = fp->GetDelimiter();
 
-    numFields = GetFieldCount();
+    OGRFieldDefn *poFDefn = NULL;
+    const int numFields = GetFieldCount();
 
-    for(iField=0; iField<numFields; iField++)
+    for( int iField = 0; iField < numFields; iField++ )
     {
         if (iField != 0)
           fp->WriteLine("%s", delimiter);
@@ -392,7 +282,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
 #ifdef MITAB_USE_OFTDATETIME
           case OFTTime:
           {
-              if (!IsFieldSet(iField))
+              if (!IsFieldSetAndNotNull(iField))
               {
                  szBuffer[0] = '\0';
               }
@@ -408,7 +298,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
           }
           case OFTDate:
           {
-              if (!IsFieldSet(iField))
+              if (!IsFieldSetAndNotNull(iField))
               {
                  szBuffer[0] = '\0';
               }
@@ -423,7 +313,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
           }
           case OFTDateTime:
           {
-              if (!IsFieldSet(iField))
+              if (!IsFieldSetAndNotNull(iField))
               {
                  szBuffer[0] = '\0';
               }
@@ -467,7 +357,7 @@ int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABFeature::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    const char *pszLine;
+    const char *pszLine = NULL;
 
     /* Go to the first line of the next feature */
 
@@ -506,13 +396,8 @@ int TABFeature::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeometry;
-
-    char               **papszToken;
-    const char *pszLine;
-    double dfX,dfY;
-    papszToken = CSLTokenizeString2(fp->GetSavedLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    char **papszToken =
+        CSLTokenizeString2(fp->GetSavedLine(), " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) !=3)
     {
@@ -520,14 +405,14 @@ int TABPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
-    dfX = fp->GetXTrans(CPLAtof(papszToken[1]));
-    dfY = fp->GetYTrans(CPLAtof(papszToken[2]));
+    const double dfX = fp->GetXTrans(CPLAtof(papszToken[1]));
+    const double dfY = fp->GetYTrans(CPLAtof(papszToken[2]));
 
     CSLDestroy(papszToken);
     papszToken = NULL;
 
     // Read optional SYMBOL line...
-    pszLine = fp->GetLastLine();
+    const char *pszLine = fp->GetLastLine();
     if( pszLine != NULL )
         papszToken = CSLTokenizeStringComplex(pszLine," ,()\t",
                                               TRUE,FALSE);
@@ -549,13 +434,12 @@ int TABPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         pszLine = fp->GetLine();
     }
 
-    poGeometry = new OGRPoint(dfX, dfY);
+    OGRGeometry *poGeometry = new OGRPoint(dfX, dfY);
 
     SetGeometryDirectly(poGeometry);
 
     SetMBR(dfX, dfY, dfX, dfY);
 
-
     return 0;
 }
 
@@ -564,13 +448,11 @@ int TABPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeom;
-    OGRPoint            *poPoint;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
         poPoint = (OGRPoint*)poGeom;
     else
@@ -592,13 +474,8 @@ int TABPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeometry;
-
-    char               **papszToken;
-    const char *pszLine;
-    double dfX,dfY;
-    papszToken = CSLTokenizeString2(fp->GetSavedLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    char **papszToken =
+        CSLTokenizeString2(fp->GetSavedLine(), " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) !=3)
     {
@@ -606,8 +483,8 @@ int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
-    dfX = fp->GetXTrans(CPLAtof(papszToken[1]));
-    dfY = fp->GetYTrans(CPLAtof(papszToken[2]));
+    const double dfX = fp->GetXTrans(CPLAtof(papszToken[1]));
+    const double dfY = fp->GetYTrans(CPLAtof(papszToken[2]));
 
     CSLDestroy(papszToken);
 
@@ -629,7 +506,7 @@ int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     CSLDestroy(papszToken);
 
-    poGeometry = new OGRPoint(dfX, dfY);
+    OGRGeometry *poGeometry = new OGRPoint(dfX, dfY);
 
     SetGeometryDirectly(poGeometry);
 
@@ -637,6 +514,7 @@ int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     /* Go to the first line of the next feature */
 
+    const char *pszLine = NULL;
     while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
       ;
@@ -648,13 +526,11 @@ int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABFontPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeom;
-    OGRPoint            *poPoint;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
         poPoint = (OGRPoint*)poGeom;
     else
@@ -678,15 +554,8 @@ int TABFontPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABCustomPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeometry;
-
-    char               **papszToken;
-    const char          *pszLine;
-    double               dfX,dfY;
-
-    papszToken = CSLTokenizeString2(fp->GetSavedLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
-
+    char **papszToken =
+        CSLTokenizeString2(fp->GetSavedLine(), " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) !=3)
     {
@@ -694,8 +563,8 @@ int TABCustomPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
-    dfX = fp->GetXTrans(CPLAtof(papszToken[1]));
-    dfY = fp->GetYTrans(CPLAtof(papszToken[2]));
+    double dfX = fp->GetXTrans(CPLAtof(papszToken[1]));
+    double dfY = fp->GetYTrans(CPLAtof(papszToken[2]));
 
     CSLDestroy(papszToken);
 
@@ -715,7 +584,7 @@ int TABCustomPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     CSLDestroy(papszToken);
 
-    poGeometry = new OGRPoint(dfX, dfY);
+    OGRGeometry *poGeometry = new OGRPoint(dfX, dfY);
 
     SetGeometryDirectly(poGeometry);
 
@@ -723,12 +592,12 @@ int TABCustomPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     /* Go to the first line of the next feature */
 
+    const char *pszLine = NULL;
     while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
       ;
 
     return 0;
-
 }
 
 /**********************************************************************
@@ -736,13 +605,11 @@ int TABCustomPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABCustomPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeom;
-    OGRPoint            *poPoint;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPoint *poPoint = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
         poPoint = (OGRPoint*)poGeom;
     else
@@ -752,7 +619,6 @@ int TABCustomPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
-
     fp->WriteLine("Point %.15g %.15g\n",poPoint->getX(),poPoint->getY());
     fp->WriteLine("    Symbol (\"%s\",%d,%d,%d)\n",GetFontNameRef(),
                   GetSymbolColor(), GetSymbolSize(),m_nCustomStyle);
@@ -765,17 +631,8 @@ int TABCustomPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    const char          *pszLine;
-    char               **papszToken;
-    OGRLineString       *poLine;
-    OGRMultiLineString  *poMultiLine;
-    GBool                bMultiple = FALSE;
-    int                  nNumPoints=0,nNumSec=0,i,j;
-    OGREnvelope          sEnvelope;
-
-
-    papszToken = CSLTokenizeString2(fp->GetLastLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    char **papszToken =
+        CSLTokenizeString2(fp->GetLastLine(), " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) < 1)
     {
@@ -783,6 +640,14 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
+    const char          *pszLine = NULL;
+    OGRLineString       *poLine = NULL;
+    OGRMultiLineString  *poMultiLine = NULL;
+    GBool bMultiple = FALSE;
+    int nNumPoints=0;
+    int nNumSec=0;
+    OGREnvelope sEnvelope;
+
     if (STARTS_WITH_CI(papszToken[0], "LINE"))
     {
         if (CSLCount(papszToken) != 5)
@@ -862,9 +727,9 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         if (bMultiple)
         {
             poMultiLine = new OGRMultiLineString();
-            for (j=0;j<nNumSec;j++)
+            for( int j = 0; j < nNumSec; j++ )
             {
-                if (j != 0)
+                if( j != 0 )
                 {
                     pszLine = fp->GetLine();
                     if( pszLine == NULL )
@@ -896,7 +761,7 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                     CSLDestroy(papszToken);
                     return -1;
                 }
-                for (i=0;i<nNumPoints;i++)
+                for( int i = 0; i < nNumPoints; i++ )
                 {
                     if( i == MAX_INITIAL_POINTS )
                     {
@@ -924,13 +789,13 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                 }
                 if (poMultiLine->addGeometryDirectly(poLine) != OGRERR_NONE)
                 {
-                    CPLAssert(FALSE); // Just in case OGR is modified
+                    CPLAssert(false); // Just in case OGR is modified
                 }
             }
             poMultiLine->getEnvelope(&sEnvelope);
             if (SetGeometryDirectly(poMultiLine) != OGRERR_NONE)
             {
-                CPLAssert(FALSE); // Just in case OGR is modified
+                CPLAssert(false); // Just in case OGR is modified
             }
             SetMBR(sEnvelope.MinX, sEnvelope.MinY,
                    sEnvelope.MaxX,sEnvelope.MaxY);
@@ -956,7 +821,7 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                 CSLDestroy(papszToken);
                 return -1;
             }
-            for (i=0;i<nNumPoints;i++)
+            for( int i = 0; i < nNumPoints; i++ )
             {
                 if( i == MAX_INITIAL_POINTS )
                 {
@@ -1024,16 +889,14 @@ int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABPolyline::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry   *poGeom;
     OGRMultiLineString *poMultiLine = NULL;
     OGRLineString *poLine = NULL;
     int nNumPoints,i;
 
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
     {
         /*-------------------------------------------------------------
@@ -1101,7 +964,6 @@ int TABPolyline::WriteGeometryToMIFFile(MIDDATAFile *fp)
       fp->WriteLine("    Smooth\n");
 
     return 0;
-
 }
 
 /**********************************************************************
@@ -1115,27 +977,19 @@ int TABPolyline::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    double               dX, dY;
-    OGRLinearRing       *poRing;
-    OGRGeometry         *poGeometry = NULL;
-    OGRPolygon          **tabPolygons = NULL;
-    int                  i,iSection, numLineSections=0;
-    char               **papszToken;
-    const char          *pszLine;
-    OGREnvelope          sEnvelope;
-
     m_bSmooth = FALSE;
+
     /*=============================================================
      * REGION (Similar to PLINE MULTIPLE)
      *============================================================*/
-    papszToken = CSLTokenizeString2(fp->GetLastLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    char **papszToken =
+        CSLTokenizeString2(fp->GetLastLine(), " \t", CSLT_HONOURSTRINGS);
 
-    if (CSLCount(papszToken) ==2)
-      numLineSections = atoi(papszToken[1]);
+    int numLineSections = (CSLCount(papszToken) == 2) ? atoi(papszToken[1]) : 0;
     CSLDestroy(papszToken);
     papszToken = NULL;
 
+    OGRPolygon **tabPolygons = NULL;
     if (numLineSections > 0)
     {
         tabPolygons = static_cast<OGRPolygon**>(
@@ -1144,9 +998,15 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
             return -1;
     }
 
+    OGRLinearRing *poRing = NULL;
+    OGRGeometry         *poGeometry = NULL;
+    int                  i,iSection;
+    const char          *pszLine = NULL;
+    OGREnvelope          sEnvelope;
+
     for(iSection=0; iSection<numLineSections; iSection++)
     {
-        int     numSectionVertices = 0;
+        int numSectionVertices = 0;
 
         tabPolygons[iSection] = new OGRPolygon();
 
@@ -1207,8 +1067,8 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                 return -1;
             }
 
-            dX = fp->GetXTrans(CPLAtof(papszToken[0]));
-            dY = fp->GetYTrans(CPLAtof(papszToken[1]));
+            const double dX = fp->GetXTrans(CPLAtof(papszToken[0]));
+            const double dY = fp->GetYTrans(CPLAtof(papszToken[1]));
             poRing->setPoint(i, dX, dY);
 
             CSLDestroy(papszToken);
@@ -1227,7 +1087,7 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     if (numLineSections > 1)
     {
-        int isValidGeometry;
+        int isValidGeometry = FALSE;
         const char* papszOptions[] = { "METHOD=DEFAULT", NULL };
         poGeometry = OGRGeometryFactory::organizePolygons(
             (OGRGeometry**)tabPolygons, numLineSections, &isValidGeometry, papszOptions );
@@ -1267,7 +1127,6 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                     SetPenPattern((GByte)atoi(papszToken[2]));
                     SetPenColor((GInt32)atoi(papszToken[3]));
                 }
-
             }
             else if (STARTS_WITH_CI(papszToken[0], "BRUSH"))
             {
@@ -1281,7 +1140,6 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                     else
                       SetBrushTransparent(TRUE);
                 }
-
             }
             else if (STARTS_WITH_CI(papszToken[0], "CENTER"))
             {
@@ -1296,7 +1154,6 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         papszToken = NULL;
     }
 
-
     return 0;
 }
 
@@ -1311,9 +1168,7 @@ int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeom;
-
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
 
     if (poGeom && (wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ||
                    wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon ) )
@@ -1332,9 +1187,7 @@ int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
 
         for(iRing=0; iRing < numRingsTotal; iRing++)
         {
-            OGRLinearRing       *poRing;
-
-            poRing = GetRingRef(iRing);
+            OGRLinearRing *poRing = GetRingRef(iRing);
             if (poRing == NULL)
             {
                 CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1356,7 +1209,6 @@ int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
                           GetPenWidthMIF(),GetPenPattern(),
                           GetPenColor());
 
-
         if (GetBrushPattern())
         {
             if (GetBrushTransparent() == 0)
@@ -1371,8 +1223,6 @@ int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
         {
             fp->WriteLine("    Center %.15g %.15g\n", m_dCenterX, m_dCenterY);
         }
-
-
     }
     else
     {
@@ -1389,14 +1239,8 @@ int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    const char          *pszLine;
-    char               **papszToken;
-    double               dXMin, dYMin, dXMax, dYMax;
-    OGRPolygon          *poPolygon;
-    OGRLinearRing       *poRing;
-
-    papszToken = CSLTokenizeString2(fp->GetLastLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    char **papszToken =
+        CSLTokenizeString2(fp->GetLastLine(), " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) <  5)
     {
@@ -1404,10 +1248,10 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
-    dXMin = fp->GetXTrans(CPLAtof(papszToken[1]));
-    dXMax = fp->GetXTrans(CPLAtof(papszToken[3]));
-    dYMin = fp->GetYTrans(CPLAtof(papszToken[2]));
-    dYMax = fp->GetYTrans(CPLAtof(papszToken[4]));
+    double dXMin = fp->GetXTrans(CPLAtof(papszToken[1]));
+    double dXMax = fp->GetXTrans(CPLAtof(papszToken[3]));
+    double dYMin = fp->GetYTrans(CPLAtof(papszToken[2]));
+    double dYMax = fp->GetYTrans(CPLAtof(papszToken[4]));
 
     /*-----------------------------------------------------------------
      * Call SetMBR() and GetMBR() now to make sure that min values are
@@ -1417,14 +1261,17 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     GetMBR(dXMin, dYMin, dXMax, dYMax);
 
     m_bRoundCorners = FALSE;
-    m_dRoundXRadius  = 0.0;
-    m_dRoundYRadius  = 0.0;
+    m_dRoundXRadius = 0.0;
+    m_dRoundYRadius = 0.0;
 
     if (STARTS_WITH_CI(papszToken[0], "ROUNDRECT"))
     {
         m_bRoundCorners = TRUE;
         if (CSLCount(papszToken) == 6)
-          m_dRoundXRadius = m_dRoundYRadius = CPLAtof(papszToken[5])/2.0;
+        {
+          m_dRoundXRadius = CPLAtof(papszToken[5]) / 2.0;
+          m_dRoundYRadius = m_dRoundXRadius;
+        }
         else
         {
             CSLDestroy(papszToken);
@@ -1441,8 +1288,8 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
      * Create and fill geometry object
      *----------------------------------------------------------------*/
 
-    poPolygon = new OGRPolygon;
-    poRing = new OGRLinearRing();
+    OGRPolygon *poPolygon = new OGRPolygon;
+    OGRLinearRing *poRing = new OGRLinearRing();
     if (m_bRoundCorners && m_dRoundXRadius != 0.0 && m_dRoundYRadius != 0.0)
     {
         /*-------------------------------------------------------------
@@ -1455,8 +1302,10 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
          * is the way MapInfo seems to do it when a radius bigger than
          * the MBR is passed from TBA to MIF.
          *------------------------------------------------------------*/
-        double dXRadius = MIN(m_dRoundXRadius, (dXMax-dXMin)/2.0);
-        double dYRadius = MIN(m_dRoundYRadius, (dYMax-dYMin)/2.0);
+        const double dXRadius =
+            std::min(m_dRoundXRadius, (dXMax - dXMin) / 2.0);
+        const double dYRadius =
+            std::min(m_dRoundYRadius, (dYMax - dYMin) / 2.0);
         TABGenerateArc(poRing, 45,
                        dXMin + dXRadius, dYMin + dYRadius, dXRadius, dYRadius,
                        M_PI, 3.0*M_PI/2.0);
@@ -1484,10 +1333,10 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     poPolygon->addRingDirectly(poRing);
     SetGeometryDirectly(poPolygon);
 
-
-   while (((pszLine = fp->GetLine()) != NULL) &&
-          fp->IsValidFeature(pszLine) == FALSE)
-   {
+    const char *pszLine = NULL;
+    while (((pszLine = fp->GetLine()) != NULL) &&
+           fp->IsValidFeature(pszLine) == FALSE)
+    {
        papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
                                              TRUE,FALSE);
 
@@ -1501,7 +1350,6 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                    SetPenPattern((GByte)atoi(papszToken[2]));
                    SetPenColor((GInt32)atoi(papszToken[3]));
                }
-
            }
            else if (STARTS_WITH_CI(papszToken[0], "BRUSH"))
            {
@@ -1515,7 +1363,6 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                    else
                       SetBrushTransparent(TRUE);
                }
-
            }
        }
        CSLDestroy(papszToken);
@@ -1525,20 +1372,16 @@ int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
    return 0;
 }
 
-
 /**********************************************************************
  *
  **********************************************************************/
 int TABRectangle::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeom;
-    OGRPolygon          *poPolygon;
-    OGREnvelope         sEnvelope;
-
-     /*-----------------------------------------------------------------
+    /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
+    OGRPolygon *poPolygon = NULL;
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon)
         poPolygon = (OGRPolygon*)poGeom;
     else
@@ -1552,6 +1395,7 @@ int TABRectangle::WriteGeometryToMIFFile(MIDDATAFile *fp)
      * read the polygon geometry... this should be OK unless the
      * polygon geometry was not really a rectangle.
      *----------------------------------------------------------------*/
+    OGREnvelope sEnvelope;
     poPolygon->getEnvelope(&sEnvelope);
 
     if (m_bRoundCorners == TRUE)
@@ -1588,14 +1432,8 @@ int TABRectangle::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    const char *pszLine;
-    char **papszToken;
-    double              dXMin, dYMin, dXMax, dYMax;
-    OGRPolygon          *poPolygon;
-    OGRLinearRing       *poRing;
-
-    papszToken = CSLTokenizeString2(fp->GetLastLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    char **papszToken =
+        CSLTokenizeString2(fp->GetLastLine(), " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) != 5)
     {
@@ -1603,10 +1441,10 @@ int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
-    dXMin = fp->GetXTrans(CPLAtof(papszToken[1]));
-    dXMax = fp->GetXTrans(CPLAtof(papszToken[3]));
-    dYMin = fp->GetYTrans(CPLAtof(papszToken[2]));
-    dYMax = fp->GetYTrans(CPLAtof(papszToken[4]));
+    double dXMin = fp->GetXTrans(CPLAtof(papszToken[1]));
+    double dXMax = fp->GetXTrans(CPLAtof(papszToken[3]));
+    double dYMin = fp->GetYTrans(CPLAtof(papszToken[2]));
+    double dYMax = fp->GetYTrans(CPLAtof(papszToken[4]));
 
     CSLDestroy(papszToken);
     papszToken = NULL;
@@ -1616,16 +1454,16 @@ int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
      *----------------------------------------------------------------*/
     m_dCenterX = (dXMin + dXMax) / 2.0;
     m_dCenterY = (dYMin + dYMax) / 2.0;
-    m_dXRadius = ABS( (dXMax - dXMin) / 2.0 );
-    m_dYRadius = ABS( (dYMax - dYMin) / 2.0 );
+    m_dXRadius = std::abs( (dXMax - dXMin) / 2.0 );
+    m_dYRadius = std::abs( (dYMax - dYMin) / 2.0 );
 
     SetMBR(dXMin, dYMin, dXMax, dYMax);
 
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      *----------------------------------------------------------------*/
-    poPolygon = new OGRPolygon;
-    poRing = new OGRLinearRing();
+    OGRPolygon *poPolygon = new OGRPolygon;
+    OGRLinearRing *poRing = new OGRLinearRing();
 
     /*-----------------------------------------------------------------
      * For the OGR geometry, we generate an ellipse with 2 degrees line
@@ -1640,6 +1478,7 @@ int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     poPolygon->addRingDirectly(poRing);
     SetGeometryDirectly(poPolygon);
 
+    const char *pszLine = NULL;
     while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
@@ -1656,7 +1495,6 @@ int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                     SetPenPattern((GByte)atoi(papszToken[2]));
                     SetPenColor((GInt32)atoi(papszToken[3]));
                 }
-
             }
             else if (STARTS_WITH_CI(papszToken[0], "BRUSH"))
             {
@@ -1669,9 +1507,7 @@ int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                       SetBrushBGColor(atoi(papszToken[3]));
                     else
                       SetBrushTransparent(TRUE);
-
                 }
-
             }
         }
         CSLDestroy(papszToken);
@@ -1685,10 +1521,8 @@ int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABEllipse::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeom;
-    OGREnvelope         sEnvelope;
-
-    poGeom = GetGeometryRef();
+    OGREnvelope sEnvelope;
+    OGRGeometry *poGeom = GetGeometryRef();
     if ( (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ) ||
          (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )  )
         poGeom->getEnvelope(&sEnvelope);
@@ -1723,14 +1557,13 @@ int TABEllipse::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    const char          *pszLine;
-    OGRLineString       *poLine;
-    char               **papszToken;
-    double               dXMin,dXMax, dYMin,dYMax;
-    int                  numPts;
+    double dXMin = 0.0;
+    double dXMax = 0.0;
+    double dYMin = 0.0;
+    double dYMax = 0.0;
 
-    papszToken = CSLTokenizeString2(fp->GetLastLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    char **papszToken =
+        CSLTokenizeString2(fp->GetLastLine(), " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) == 5)
     {
@@ -1788,21 +1621,21 @@ int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     m_dCenterX = (dXMin + dXMax) / 2.0;
     m_dCenterY = (dYMin + dYMax) / 2.0;
-    m_dXRadius = ABS( (dXMax - dXMin) / 2.0 );
-    m_dYRadius = ABS( (dYMax - dYMin) / 2.0 );
+    m_dXRadius = std::abs( (dXMax - dXMin) / 2.0 );
+    m_dYRadius = std::abs( (dYMax - dYMin) / 2.0 );
 
     /*-----------------------------------------------------------------
      * Create and fill geometry object
      * For the OGR geometry, we generate an arc with 2 degrees line
      * segments.
      *----------------------------------------------------------------*/
-    poLine = new OGRLineString;
+    OGRLineString *poLine = new OGRLineString;
 
-    if (m_dEndAngle < m_dStartAngle)
-        numPts = (int) ABS( ((m_dEndAngle+360.0)-m_dStartAngle)/2.0 ) + 1;
-    else
-        numPts = (int) ABS( (m_dEndAngle-m_dStartAngle)/2.0 ) + 1;
-    numPts = MAX(2, numPts);
+    int numPts =
+         std::max(2,
+             (m_dEndAngle < m_dStartAngle
+              ? (int) std::abs( ((m_dEndAngle+360.0)-m_dStartAngle)/2.0 ) + 1
+              : (int) std::abs( (m_dEndAngle-m_dStartAngle)/2.0 ) + 1));
 
     TABGenerateArc(poLine, numPts,
                    m_dCenterX, m_dCenterY,
@@ -1812,6 +1645,7 @@ int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     SetMBR(dXMin, dYMin, dXMax, dYMax);
     SetGeometryDirectly(poLine);
 
+    const char *pszLine = NULL;
     while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
@@ -1829,7 +1663,6 @@ int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
                     SetPenPattern((GByte)atoi(papszToken[2]));
                     SetPenColor((GInt32)atoi(papszToken[3]));
                 }
-
             }
         }
         CSLDestroy(papszToken);
@@ -1849,7 +1682,6 @@ int TABArc::WriteGeometryToMIFFile(MIDDATAFile *fp)
      * ignore the special angle conversion required by flipped axis.
      *------------------------------------------------------------*/
 
-
     // Write the Arc's actual MBR
      fp->WriteLine("Arc %.15g %.15g %.15g %.15g\n", m_dCenterX-m_dXRadius,
                    m_dCenterY-m_dYRadius, m_dCenterX+m_dXRadius,
@@ -1869,23 +1701,17 @@ int TABArc::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    double               dXMin, dYMin, dXMax, dYMax;
-    OGRGeometry         *poGeometry;
-    const char          *pszLine;
-    char               **papszToken;
-    const char          *pszString;
-    char                *pszTmpString;
-    int                  bXYBoxRead = 0;
-    int                  tokenLen;
-
-    papszToken = CSLTokenizeString2(fp->GetLastLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    const char *pszString = NULL;
+    int bXYBoxRead = 0;
+
+    char **papszToken =
+        CSLTokenizeString2(fp->GetLastLine(), " \t", CSLT_HONOURSTRINGS);
     if (CSLCount(papszToken) == 1)
     {
         CSLDestroy(papszToken);
         papszToken = CSLTokenizeString2(fp->GetLine(),
                                         " \t", CSLT_HONOURSTRINGS);
-        tokenLen = CSLCount(papszToken);
+        const int tokenLen = CSLCount(papszToken);
         if (tokenLen == 4)
         {
            pszString = NULL;
@@ -1920,7 +1746,7 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
      * sstore them in memory in the UnEscaped form to be OGR
      * compliant. See Maptools bug 1107 for more details.
      *------------------------------------------------------------*/
-    pszTmpString = CPLStrdup(pszString);
+    char *pszTmpString = CPLStrdup(pszString);
     m_pszString = TABUnEscapeString(pszTmpString, TRUE);
     if (pszTmpString != m_pszString)
         CPLFree(pszTmpString);
@@ -1937,21 +1763,19 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         CSLDestroy(papszToken);
         return -1;
     }
-    else
-    {
-        dXMin = fp->GetXTrans(CPLAtof(papszToken[0]));
-        dXMax = fp->GetXTrans(CPLAtof(papszToken[2]));
-        dYMin = fp->GetYTrans(CPLAtof(papszToken[1]));
-        dYMax = fp->GetYTrans(CPLAtof(papszToken[3]));
 
-        m_dHeight = dYMax - dYMin;  //SetTextBoxHeight(dYMax - dYMin);
-        m_dWidth  = dXMax - dXMin;  //SetTextBoxWidth(dXMax - dXMin);
+    double dXMin = fp->GetXTrans(CPLAtof(papszToken[0]));
+    double dXMax = fp->GetXTrans(CPLAtof(papszToken[2]));
+    double dYMin = fp->GetYTrans(CPLAtof(papszToken[1]));
+    double dYMax = fp->GetYTrans(CPLAtof(papszToken[3]));
 
-        if (m_dHeight <0.0)
-          m_dHeight*=-1.0;
-        if (m_dWidth <0.0)
-          m_dWidth*=-1.0;
-    }
+    m_dHeight = dYMax - dYMin;  //SetTextBoxHeight(dYMax - dYMin);
+    m_dWidth  = dXMax - dXMin;  //SetTextBoxWidth(dXMax - dXMin);
+
+    if (m_dHeight <0.0)
+      m_dHeight*=-1.0;
+    if (m_dWidth <0.0)
+      m_dWidth*=-1.0;
 
     CSLDestroy(papszToken);
     papszToken = NULL;
@@ -1962,6 +1786,7 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     SetMBR(dXMin, dYMin, dXMax, dYMax);
     GetMBR(dXMin, dYMin, dXMax, dYMax);
 
+    const char *pszLine = NULL;
     while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
@@ -1986,7 +1811,6 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
                     // papsztoken[3] = Size ???
                 }
-
             }
             else if (STARTS_WITH_CI(papszToken[0], "SPACING"))
             {
@@ -2073,9 +1897,10 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
      * We need to calculate the true lower left corner of the text based
      * on the MBR after rotation, the text height and the rotation angle.
      *---------------------------------------------------------------- */
-    double dCos, dSin, dX, dY;
-    dSin = sin(m_dAngle*M_PI/180.0);
-    dCos = cos(m_dAngle*M_PI/180.0);
+    double dSin = sin(m_dAngle*M_PI/180.0);
+    double dCos = cos(m_dAngle*M_PI/180.0);
+    double dX = 0.0;
+    double dY = 0.0;
     if (dSin > 0.0  && dCos > 0.0)
     {
         dX = dXMin + m_dHeight * dSin;
@@ -2097,8 +1922,7 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         dY = dYMax - m_dHeight * dCos;
     }
 
-
-    poGeometry = new OGRPoint(dX, dY);
+    OGRGeometry *poGeometry = new OGRPoint(dX, dY);
 
     SetGeometryDirectly(poGeometry);
 
@@ -2119,8 +1943,8 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
      * and for other teta values, use:
      *   W = H * (dY - H * cos(teta)) / (H * sin(teta))
      *---------------------------------------------------------------- */
-    dSin = ABS(dSin);
-    dCos = ABS(dCos);
+    dSin = std::abs(dSin);
+    dCos = std::abs(dCos);
     if (m_dHeight == 0.0)
         m_dWidth = 0.0;
     else if ( dCos > dSin )
@@ -2129,7 +1953,7 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     else
         m_dWidth = m_dHeight * ((dYMax-dYMin) - m_dHeight*dCos) /
                                                         (m_dHeight*dSin);
-    m_dWidth = ABS(m_dWidth);
+    m_dWidth = std::abs(m_dWidth);
 
    return 0;
 }
@@ -2139,16 +1963,13 @@ int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
-    double dXMin,dYMin,dXMax,dYMax;
-    char   *pszTmpString;
-
     /*-------------------------------------------------------------
      * Note: The text string may contain unescaped "\n" chars or
      * "\\" chars and we expect to receive them in an unescaped
      * form. Those characters are unescaped in memory to be like
      * other OGR drivers. See MapTools bug 1107 for more details.
      *------------------------------------------------------------*/
-    pszTmpString = TABEscapeString(m_pszString);
+    char *pszTmpString = TABEscapeString(m_pszString);
     if(pszTmpString == NULL)
         fp->WriteLine("Text \"\"\n" );
     else
@@ -2157,10 +1978,14 @@ int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
         CPLFree(pszTmpString);
 
     //    UpdateTextMBR();
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     GetMBR(dXMin, dYMin, dXMax, dYMax);
-    fp->WriteLine("    %.15g %.15g %.15g %.15g\n",dXMin, dYMin,dXMax, dYMax);
+    fp->WriteLine("    %.15g %.15g %.15g %.15g\n", dXMin, dYMin, dXMax, dYMax);
 
-    if (IsFontBGColorUsed())
+    if( IsFontBGColorUsed() )
       fp->WriteLine("    Font (\"%s\",%d,%d,%d,%d)\n", GetFontNameRef(),
                     GetFontStyleMIFValue(),0,GetFontFGColor(),
                     GetFontBGColor());
@@ -2194,7 +2019,7 @@ int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
         break;
     }
 
-    if (ABS(GetTextAngle()) >  0.000001)
+    if (std::abs(GetTextAngle()) >  0.000001)
         fp->WriteLine("    Angle %.15g\n",GetTextAngle());
 
     switch (GetTextLineType())
@@ -2214,7 +2039,6 @@ int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
         break;
     }
     return 0;
-
 }
 
 /**********************************************************************
@@ -2222,16 +2046,8 @@ int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    OGRPoint            *poPoint;
-    OGRMultiPoint       *poMultiPoint;
-    char                **papszToken;
-    const char          *pszLine;
-    int                 nNumPoint, i;
-    double              dfX,dfY;
-    OGREnvelope         sEnvelope;
-
-    papszToken = CSLTokenizeString2(fp->GetLastLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    char **papszToken =
+        CSLTokenizeString2(fp->GetLastLine(), " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) !=2)
     {
@@ -2239,14 +2055,14 @@ int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
-    nNumPoint = atoi(papszToken[1]);
-    poMultiPoint = new OGRMultiPoint;
+    int nNumPoint = atoi(papszToken[1]);
+    OGRMultiPoint *poMultiPoint = new OGRMultiPoint;
 
     CSLDestroy(papszToken);
     papszToken = NULL;
 
     // Get each point and add them to the multipoint feature
-    for(i=0; i<nNumPoint; i++)
+    for( int i = 0; i<nNumPoint; i++ )
     {
         papszToken = CSLTokenizeString2(fp->GetLine(),
                                         " \t", CSLT_HONOURSTRINGS);
@@ -2257,12 +2073,12 @@ int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
             return -1;
         }
 
-        dfX = fp->GetXTrans(CPLAtof(papszToken[0]));
-        dfY = fp->GetXTrans(CPLAtof(papszToken[1]));
-        poPoint = new OGRPoint(dfX, dfY);
+        const double dfX = fp->GetXTrans(CPLAtof(papszToken[0]));
+        const double dfY = fp->GetXTrans(CPLAtof(papszToken[1]));
+        OGRPoint *poPoint = new OGRPoint(dfX, dfY);
         if ( poMultiPoint->addGeometryDirectly( poPoint ) != OGRERR_NONE)
         {
-            CPLAssert(FALSE); // Just in case OGR is modified
+            CPLAssert(false); // Just in case OGR is modified
         }
 
         // Set center
@@ -2273,10 +2089,11 @@ int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         CSLDestroy(papszToken);
     }
 
+    OGREnvelope sEnvelope;
     poMultiPoint->getEnvelope(&sEnvelope);
     if( SetGeometryDirectly( poMultiPoint ) != OGRERR_NONE)
     {
-        CPLAssert(FALSE); // Just in case OGR is modified
+        CPLAssert(false); // Just in case OGR is modified
     }
 
     SetMBR(sEnvelope.MinX, sEnvelope.MinY,
@@ -2284,6 +2101,7 @@ int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 
     // Read optional SYMBOL line...
 
+    const char *pszLine = NULL;
     while (((pszLine = fp->GetLine()) != NULL) &&
            fp->IsValidFeature(pszLine) == FALSE)
     {
@@ -2306,23 +2124,18 @@ int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
  **********************************************************************/
 int TABMultiPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
 {
-    OGRGeometry         *poGeom;
-    OGRPoint            *poPoint;
-    OGRMultiPoint       *poMultiPoint;
-    int                 nNumPoints, iPoint;
-
     /*-----------------------------------------------------------------
      * Fetch and validate geometry
      *----------------------------------------------------------------*/
-    poGeom = GetGeometryRef();
+    OGRGeometry *poGeom = GetGeometryRef();
     if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint)
     {
-        poMultiPoint = (OGRMultiPoint*)poGeom;
-        nNumPoints = poMultiPoint->getNumGeometries();
+        OGRMultiPoint *poMultiPoint = (OGRMultiPoint*)poGeom;
+        const int nNumPoints = poMultiPoint->getNumGeometries();
 
         fp->WriteLine("MultiPoint %d\n", nNumPoints);
 
-        for(iPoint=0; iPoint < nNumPoints; iPoint++)
+        for( int iPoint = 0; iPoint < nNumPoints; iPoint++ )
         {
             /*------------------------------------------------------------
              * Validate each point
@@ -2330,7 +2143,7 @@ int TABMultiPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
             poGeom = poMultiPoint->getGeometryRef(iPoint);
             if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
             {
-                poPoint = (OGRPoint*)poGeom;
+                OGRPoint *poPoint = (OGRPoint*)poGeom;
                 fp->WriteLine("%.15g %.15g\n",poPoint->getX(),poPoint->getY());
             }
             else
@@ -2348,22 +2161,16 @@ int TABMultiPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
     return 0;
 }
 
-
 /**********************************************************************
  *
  **********************************************************************/
 int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
 {
-    char                **papszToken;
-    const char          *pszLine;
-    int                 numParts, i;
-    OGREnvelope         sEnvelope;
-
     /*-----------------------------------------------------------------
      * Fetch number of parts in "COLLECTION %d" line
      *----------------------------------------------------------------*/
-    papszToken = CSLTokenizeString2(fp->GetLastLine(),
-                                    " \t", CSLT_HONOURSTRINGS);
+    char **papszToken =
+        CSLTokenizeString2(fp->GetLastLine(), " \t", CSLT_HONOURSTRINGS);
 
     if (CSLCount(papszToken) !=2)
     {
@@ -2371,19 +2178,19 @@ int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
         return -1;
     }
 
-    numParts = atoi(papszToken[1]);
+    int numParts = atoi(papszToken[1]);
     CSLDestroy(papszToken);
     papszToken = NULL;
 
     // Make sure collection is empty
     EmptyCollection();
 
-    pszLine = fp->GetLine();
+    const char *pszLine = fp->GetLine();
 
     /*-----------------------------------------------------------------
      * Read each part and add them to the feature
      *----------------------------------------------------------------*/
-    for (i=0; i < numParts; i++)
+    for( int i=0; i < numParts; i++ )
     {
         if (pszLine == NULL)
         {
@@ -2468,6 +2275,7 @@ int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
     if(m_poMpoint && m_poMpoint->GetGeometryRef() != NULL)
         poGeomColl->addGeometry(m_poMpoint->GetGeometryRef());
 
+    OGREnvelope sEnvelope;
     poGeomColl->getEnvelope(&sEnvelope);
     this->SetGeometryDirectly(poGeomColl);
 
@@ -2513,23 +2321,23 @@ int TABCollection::WriteGeometryToMIFFile(MIDDATAFile *fp)
 /**********************************************************************
  *
  **********************************************************************/
-int TABDebugFeature::ReadGeometryFromMIFFile(MIDDATAFile *fp)
+int TABDebugFeature::ReadGeometryFromMIFFile( MIDDATAFile *fp )
 {
-   const char *pszLine;
-
-
-  /* Go to the first line of the next feature */
-   printf("%s\n", fp->GetLastLine());
+    // Go to the first line of the next feature.
+    printf("%s\n", fp->GetLastLine());/*ok*/
 
-   while (((pszLine = fp->GetLine()) != NULL) &&
-          fp->IsValidFeature(pszLine) == FALSE)
-     ;
+    const char *pszLine = NULL;
+    while (((pszLine = fp->GetLine()) != NULL) &&
+           fp->IsValidFeature(pszLine) == FALSE)
+    {}
 
-   return 0;
+    return 0;
 }
 
-
 /**********************************************************************
  *
  **********************************************************************/
-int TABDebugFeature::WriteGeometryToMIFFile(CPL_UNUSED MIDDATAFile *fp){ return -1; }
+int TABDebugFeature::WriteGeometryToMIFFile( MIDDATAFile * /* fp */ )
+{
+    return -1;
+}
diff --git a/ogr/ogrsf_frmts/mitab/mitab_geometry.cpp b/ogr/ogrsf_frmts/mitab/mitab_geometry.cpp
index 5940acb..d41c4c3 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_geometry.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_geometry.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_geometry.cpp,v 1.5 2004-06-30 20:29:04 dmorissette Exp $
  *
  * Name:     mitab_geometry.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -28,33 +27,23 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_geometry.cpp,v $
- * Revision 1.5  2004-06-30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.4  2001/12/18 23:42:28  daniel
- * Added a test in OGRPolygonLabelPoint() to prevent returning a point
- * outside of the polygon MBR (bug 673).
- *
- * Revision 1.3  2001/01/22 16:03:58  warmerda
- * expanded tabs
- *
- * Revision 1.2  2000/09/28 16:39:44  warmerda
- * Avoid warnings for unused, and uninitialized variables
- *
- * Revision 1.1  2000/09/19 17:19:40  daniel
- * Initial Revision
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab_geometry.h"
 
+#include <cmath>
+#include <cstdlib>
+#include <algorithm>
+#include <utility>
+
+#include "ogr_core.h"
+
+CPL_CVSID("$Id: mitab_geometry.cpp 37347 2017-02-12 03:10:54Z goatbar $");
+
 #define OGR_NUM_RINGS(poly)   (poly->getNumInteriorRings()+1)
 #define OGR_GET_RING(poly, i) (i==0?poly->getExteriorRing():poly->getInteriorRing(i-1))
 
-
 /**********************************************************************
  *                   OGRPointInRing()
  *
@@ -97,10 +86,9 @@ GBool OGRPointInRing(OGRPoint *poPoint, OGRLineString *poRing)
  **********************************************************************/
 GBool OGRIntersectPointPolygon(OGRPoint *poPoint, OGRPolygon *poPoly)
 {
-    int i;
     GBool status = FALSE;
 
-    for(i=0; i<OGR_NUM_RINGS(poPoly); i++)
+    for( int i = 0; i<OGR_NUM_RINGS(poPoly); i++ )
     {
         if (OGRPointInRing(poPoint, OGR_GET_RING(poPoly, i)))
         {
@@ -112,7 +100,6 @@ GBool OGRIntersectPointPolygon(OGRPoint *poPoint, OGRPolygon *poPoly)
     return status;
 }
 
-
 /**********************************************************************
  *                   OGRPolygonLabelPoint()
  *
@@ -129,45 +116,40 @@ GBool OGRIntersectPointPolygon(OGRPoint *poPoint, OGRPolygon *poPoly)
  * Adapted version of msPolygonLabelPoint() from MapServer's mapprimitive.c
  **********************************************************************/
 
-typedef enum {CLIP_LEFT, CLIP_MIDDLE, CLIP_RIGHT} CLIP_STATE;
-#define CLIP_CHECK(min, a, max) ((a) < (min) ? CLIP_LEFT : ((a) > (max) ? CLIP_RIGHT : CLIP_MIDDLE));
-#define ROUND(a)       ( (a) + 0.5 )
-#define SWAP( a, b, t) ( (t) = (a), (a) = (b), (b) = (t) )
-#define EDGE_CHECK( x0, x, x1) ((x) < MIN( (x0), (x1)) ? CLIP_LEFT : ((x) > MAX( (x0), (x1)) ? CLIP_RIGHT : CLIP_MIDDLE ))
+typedef enum { CLIP_LEFT, CLIP_MIDDLE, CLIP_RIGHT } CLIP_STATE;
+static CLIP_STATE EDGE_CHECK( double x0, double x, double x1 )
+{
+    if( x < std::min(x0, x1) )
+        return CLIP_LEFT;
+    if( x > std::max(x0, x1) )
+        return CLIP_RIGHT;
+    return CLIP_MIDDLE;
+}
 
-#define NUM_SCANLINES 5
+static const int NUM_SCANLINES = 5;
 
 int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
 {
-    double        slope;
-    OGRRawPoint   point1, point2;
-    int           i, j, k, nfound;
-    double        x, y, *xintersect, temp;
-    double        hi_y, lo_y;
-    int           wrong_order, n;
-    double        len, max_len=0;
-    double        skip;
-    OGREnvelope   oEnv;
-
     if (poPoly == NULL)
         return OGRERR_FAILURE;
 
+    OGREnvelope   oEnv;
     poPoly->getEnvelope(&oEnv);
 
     poLabelPoint->setX((oEnv.MaxX + oEnv.MinX)/2.0);
     poLabelPoint->setY((oEnv.MaxY + oEnv.MinY)/2.0);
 
-    //if(get_centroid(p, lp, &miny, &maxy) == -1) return(-1);
+    // if( get_centroid(p, lp, &miny, &maxy) == -1 ) return -1;
 
     if(OGRIntersectPointPolygon(poLabelPoint, poPoly) == TRUE) /* cool, done */
         return OGRERR_NONE;
 
     /* do it the hard way - scanline */
 
-    skip = (oEnv.MaxY - oEnv.MinY)/NUM_SCANLINES;
+    double skip = (oEnv.MaxY - oEnv.MinY)/NUM_SCANLINES;
 
-    n=0;
-    for(j=0; j<OGR_NUM_RINGS(poPoly); j++)
+    int n = 0;
+    for( int j = 0; j < OGR_NUM_RINGS(poPoly); j++ )
     {
         /* count total number of points */
         n += OGR_GET_RING(poPoly, j)->getNumPoints();
@@ -175,26 +157,30 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
     if( n == 0 )
         return OGRERR_FAILURE;
 
-    xintersect = (double *)calloc(n, sizeof(double));
-    if (xintersect == NULL)
+    double *xintersect = (double *)calloc(n, sizeof(double));
+    if( xintersect == NULL )
         return OGRERR_FAILURE;
 
-    for(k=1; k<=NUM_SCANLINES; k++)
+    double max_len = 0.0;
+
+    for( int k = 1; k <= NUM_SCANLINES; k++ )
     {
         /* sample the shape in the y direction */
 
-        y = oEnv.MaxY - k*skip;
+        double y = oEnv.MaxY - k*skip;
 
-        /* need to find a y that won't intersect any vertices exactly */
-        hi_y = y - 1; /* first initializing lo_y, hi_y to be any 2 pnts on either side of lp->y */
-        lo_y = y + 1;
-        for(j=0; j<OGR_NUM_RINGS(poPoly); j++)
+        // Need to find a y that won't intersect any vertices exactly.
+        // First initializing lo_y, hi_y to be any 2 pnts on either side of
+        // lp->y.
+        double hi_y = y - 1;
+        double lo_y = y + 1;
+        for( int j = 0; j < OGR_NUM_RINGS(poPoly); j++ )
         {
             OGRLinearRing *poRing = OGR_GET_RING(poPoly,j);
 
             if((lo_y < y) && (hi_y >= y))
                 break; /* already initialized */
-            for(i=0; i < poRing->getNumPoints(); i++)
+            for( int i = 0; i < poRing->getNumPoints(); i++ )
             {
                 if((lo_y < y) && (hi_y >= y))
                     break; /* already initialized */
@@ -205,11 +191,11 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
             }
         }
 
-        for(j=0; j<OGR_NUM_RINGS(poPoly); j++)
+        for( int j = 0; j<OGR_NUM_RINGS(poPoly); j++ )
         {
             OGRLinearRing *poRing = OGR_GET_RING(poPoly,j);
 
-            for(i=0; i < poRing->getNumPoints(); i++)
+            for( int i = 0; i < poRing->getNumPoints(); i++ )
             {
                 if((poRing->getY(i) < y) &&
                    ((y - poRing->getY(i)) < (y - lo_y)))
@@ -220,22 +206,25 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
             }
         }
 
-        if(lo_y == hi_y)
+        if( lo_y == hi_y )
         {
             free(xintersect);
             return OGRERR_FAILURE;
         }
-        else
-            y = (hi_y + lo_y)/2.0;
 
-        nfound = 0;
-        for(j=0; j<OGR_NUM_RINGS(poPoly); j++)   /* for each line */
+        y = (hi_y + lo_y) / 2.0;
+
+        OGRRawPoint point1;
+        OGRRawPoint point2;
+
+        int nfound = 0;
+        for( int j = 0; j < OGR_NUM_RINGS(poPoly); j++ )   // For each line.
         {
             OGRLinearRing *poRing = OGR_GET_RING(poPoly,j);
             point1.x = poRing->getX(poRing->getNumPoints()-1);
             point1.y = poRing->getY(poRing->getNumPoints()-1);
 
-            for(i=0; i < poRing->getNumPoints(); i++)
+            for( int i = 0; i < poRing->getNumPoints(); i++ )
             {
                 point2.x = poRing->getX(i);
                 point2.y = poRing->getY(i);
@@ -243,11 +232,12 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
                 if(EDGE_CHECK(point1.y, y, point2.y) == CLIP_MIDDLE)
                 {
                     if(point1.y == point2.y)
-                        continue; /* ignore horizontal edges */
-                    else
-                        slope = (point2.x - point1.x) / (point2.y - point1.y);
+                        continue;  // Ignore horizontal edges.
+
+                    const double slope =
+                        (point2.x - point1.x) / (point2.y - point1.y);
 
-                    x = point1.x + (y - point1.y)*slope;
+                    double x = point1.x + (y - point1.y)*slope;
                     xintersect[nfound++] = x;
                 } /* End of checking this edge */
 
@@ -256,27 +246,29 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
         } /* Finished the scanline */
 
         /* First, sort the intersections */
+        bool wrong_order = false;
         do
         {
-            wrong_order = 0;
-            for(i=0; i < nfound-1; i++)
+            wrong_order = false;
+            for( int i = 0; i < nfound-1; i++ )
             {
                 if(xintersect[i] > xintersect[i+1])
                 {
-                    wrong_order = 1;
-                    SWAP(xintersect[i], xintersect[i+1], temp);
+                    wrong_order = true;
+                    std::swap(xintersect[i], xintersect[i+1]);
                 }
             }
-        } while(wrong_order);
+        } while( wrong_order );
 
-        /* Great, now find longest span */
-        //point1.y = point2.y = y;
-        for(i=0; i < nfound; i += 2)
+        // Great, now find longest span.
+        // point1.y = y;
+        // point2.y = y;
+        for( int i = 0; i < nfound; i += 2 )
         {
             point1.x = xintersect[i];
             point2.x = xintersect[i+1];
             /* len = length(point1, point2); */
-            len = ABS((point2.x - point1.x));
+            const double len = std::abs((point2.x - point1.x));
             if(len > max_len)
             {
                 max_len = len;
@@ -327,22 +319,22 @@ int OGRPolygonLabelPoint(OGRPolygon *poPoly, OGRPoint *poLabelPoint)
 
 int OGRGetCentroid(OGRPolygon *poPoly, OGRPoint *poCentroid)
 {
-    int i,j;
-    double cent_weight_x=0.0, cent_weight_y=0.0;
-    double len, total_len=0;
+    double cent_weight_x = 0.0;
+    double cent_weight_y = 0.0;
+    double len = 0.0;
+    double total_len = 0.0;
 
-    for(i=0; i<OGR_NUM_RINGS(poPoly); i++)
+    for( int i = 0; i<OGR_NUM_RINGS(poPoly); i++ )
     {
-        double x1, y1, x2, y2;
         OGRLinearRing *poRing = OGR_GET_RING(poPoly, i);
 
-        x2 = poRing->getX(0);
-        y2 = poRing->getY(0);
+        double x2 = poRing->getX(0);
+        double y2 = poRing->getY(0);
 
-        for(j=1; j<poRing->getNumPoints(); j++)
+        for( int j = 1; j<poRing->getNumPoints(); j++ )
         {
-            x1 = x2;
-            y1 = y2;
+            double x1 = x2;
+            double y1 = y2;
             x2 = poRing->getX(j);
             y2 = poRing->getY(j);
 
@@ -354,7 +346,7 @@ int OGRGetCentroid(OGRPolygon *poPoly, OGRPoint *poCentroid)
     }
 
     if(total_len == 0)
-        return(OGRERR_FAILURE);
+        return OGRERR_FAILURE;
 
     poCentroid->setX( cent_weight_x / total_len );
     poCentroid->setY( cent_weight_y / total_len );
@@ -363,7 +355,6 @@ int OGRGetCentroid(OGRPolygon *poPoly, OGRPoint *poCentroid)
 }
 #endif
 
-
 /**********************************************************************
  *                   OGRPolylineCenterPoint()
  *
@@ -399,7 +390,6 @@ int OGRPolylineCenterPoint(OGRLineString *poLine, OGRPoint *poLabelPoint)
     return OGRERR_NONE;
 }
 
-
 /**********************************************************************
  *                   OGRPolylineLabelPoint()
  *
@@ -410,25 +400,22 @@ int OGRPolylineCenterPoint(OGRLineString *poLine, OGRPoint *poLabelPoint)
 
 int OGRPolylineLabelPoint(OGRLineString *poLine, OGRPoint *poLabelPoint)
 {
-    double      segment_length, max_segment_length = 0.0;
-    double      x1, y1, x2, y2;
-
     if (poLine == NULL || poLine->getNumPoints() < 2)
         return OGRERR_FAILURE;
 
-    max_segment_length = -1.0;
+    double max_segment_length = -1.0;
 
-    x2 = poLine->getX(0);
-    y2 = poLine->getY(0);
+    double x2 = poLine->getX(0);
+    double y2 = poLine->getY(0);
 
-    for(int i=1; i<poLine->getNumPoints(); i++)
+    for( int i = 1; i < poLine->getNumPoints(); i++ )
     {
-        x1 = x2;
-        y1 = y2;
+        double x1 = x2;
+        double y1 = y2;
         x2 = poLine->getX(i);
         y2 = poLine->getY(i);
 
-        segment_length = pow((x2-x1),2) + pow((y2-y1),2);
+        double segment_length = pow((x2-x1),2) + pow((y2-y1),2);
         if (segment_length > max_segment_length)
         {
             max_segment_length = segment_length;
diff --git a/ogr/ogrsf_frmts/mitab/mitab_geometry.h b/ogr/ogrsf_frmts/mitab/mitab_geometry.h
index 84c5841..e752904 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_geometry.h
+++ b/ogr/ogrsf_frmts/mitab/mitab_geometry.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab_geometry.h,v 1.2 2004-06-30 20:29:04 dmorissette Exp $
+ * $Id: mitab_geometry.h 37335 2017-02-09 14:29:57Z goatbar $
  *
  * Name:     mitab_geometry.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -28,15 +28,6 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_geometry.h,v $
- * Revision 1.2  2004-06-30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.1  2000/09/19 17:19:40  daniel
- * Initial Revision
- *
  **********************************************************************/
 
 #ifndef MITAB_GEOMETRY_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/mitab/mitab_idfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_idfile.cpp
index 2d18ffb..9dd37b0 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_idfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_idfile.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_idfile.cpp,v 1.8 2006-11-28 18:49:08 dmorissette Exp $
  *
  * Name:     mitab_idfile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,44 +28,27 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_idfile.cpp,v $
- * Revision 1.8  2006-11-28 18:49:08  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.7  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.6  2000/01/18 22:08:56  daniel
- * Allow opening of 0-size .ID file (dataset with 0 features)
- *
- * Revision 1.5  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.4  1999/09/26 14:59:36  daniel
- * Implemented write support
- *
- * Revision 1.3  1999/09/20 18:43:01  daniel
- * Use binary access to open file.
- *
- * Revision 1.2  1999/09/16 02:39:16  daniel
- * Completed read support for most feature types
- *
- * Revision 1.1  1999/07/12 04:18:24  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <algorithm>
+#include <limits.h>
+#include <string.h>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
 #include "mitab_utils.h"
 
+CPL_CVSID("$Id: mitab_idfile.cpp 37366 2017-02-13 02:48:11Z goatbar $");
+
 /*=====================================================================
  *                      class TABIDFile
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABIDFile::TABIDFile()
  *
@@ -79,18 +61,14 @@ TABIDFile::TABIDFile() :
     m_poIDBlock(NULL),
     m_nBlockSize(0),
     m_nMaxId(-1)
-{
-}
+{}
 
 /**********************************************************************
  *                   TABIDFile::~TABIDFile()
  *
  * Destructor.
  **********************************************************************/
-TABIDFile::~TABIDFile()
-{
-    Close();
-}
+TABIDFile::~TABIDFile() { Close(); }
 
 /**********************************************************************
  *                   TABIDFile::Open()
@@ -99,18 +77,17 @@ TABIDFile::~TABIDFile()
  * Return 0 on success, -1 in case of failure.
  **********************************************************************/
 
-int TABIDFile::Open(const char *pszFname, const char* pszAccess)
+int TABIDFile::Open(const char *pszFname, const char *pszAccess)
 {
+    // cppcheck-suppress nullPointer
     if( STARTS_WITH_CI(pszAccess, "r") )
         return Open(pszFname, TABRead);
-    else if( STARTS_WITH_CI(pszAccess, "w") )
+    if( STARTS_WITH_CI(pszAccess, "w") )
         return Open(pszFname, TABWrite);
-    else
-    {
-        CPLError(CE_Failure, CPLE_FileIO,
-                 "Open() failed: access mode \"%s\" not supported", pszAccess);
-        return -1;
-    }
+
+    CPLError(CE_Failure, CPLE_FileIO,
+             "Open() failed: access mode \"%s\" not supported", pszAccess);
+    return -1;
 }
 
 /**********************************************************************
@@ -133,12 +110,10 @@ int TABIDFile::Open(const char *pszFname, TABAccess eAccess)
         return -1;
     }
 
-    /*-----------------------------------------------------------------
-     * Validate access mode and make sure we use binary access.
-     * Note that in Write mode we need TABReadWrite since we do random
-     * updates in the index as data blocks are split
-     *----------------------------------------------------------------*/
-    const char* pszAccess = NULL;
+    // Validate access mode and make sure we use binary access.
+    // Note that in Write mode we need TABReadWrite since we do random
+    // updates in the index as data blocks are split.
+    const char *pszAccess = NULL;
     if (eAccess == TABRead)
     {
         m_eAccessMode = TABRead;
@@ -161,33 +136,26 @@ int TABIDFile::Open(const char *pszFname, TABAccess eAccess)
         return -1;
     }
 
-    /*-----------------------------------------------------------------
-     * Change .MAP extension to .ID if necessary
-     *----------------------------------------------------------------*/
+    // Change .MAP extension to .ID if necessary.
     m_pszFname = CPLStrdup(pszFname);
 
-    int nLen = static_cast<int>(strlen(m_pszFname));
-    if (nLen > 4 && strcmp(m_pszFname+nLen-4, ".MAP")==0)
-        strcpy(m_pszFname+nLen-4, ".ID");
-    else if (nLen > 4 && strcmp(m_pszFname+nLen-4, ".map")==0)
-        strcpy(m_pszFname+nLen-4, ".id");
+    const int nLen = static_cast<int>(strlen(m_pszFname));
+    if (nLen > 4 && strcmp(m_pszFname + nLen - 4, ".MAP") == 0)
+        strcpy(m_pszFname + nLen - 4, ".ID");
+    else if (nLen > 4 && strcmp(m_pszFname + nLen - 4, ".map") == 0)
+        strcpy(m_pszFname + nLen - 4, ".id");
 
-    /*-----------------------------------------------------------------
-     * Change .MAP extension to .ID if necessary
-     *----------------------------------------------------------------*/
 #ifndef _WIN32
+    // Change .MAP extension to .ID if necessary.
     TABAdjustFilenameExtension(m_pszFname);
 #endif
 
-    /*-----------------------------------------------------------------
-     * Open file
-     *----------------------------------------------------------------*/
+    // Open file.
     m_fp = VSIFOpenL(m_pszFname, pszAccess);
 
     if (m_fp == NULL)
     {
-        CPLError(CE_Failure, CPLE_FileIO,
-                 "Open() failed for %s", m_pszFname);
+        CPLError(CE_Failure, CPLE_FileIO, "Open() failed for %s", m_pszFname);
         CPLFree(m_pszFname);
         m_pszFname = NULL;
         return -1;
@@ -195,28 +163,25 @@ int TABIDFile::Open(const char *pszFname, TABAccess eAccess)
 
     if (m_eAccessMode == TABRead || m_eAccessMode == TABReadWrite)
     {
-        /*-------------------------------------------------------------
-         * READ access:
-         * Establish the number of object IDs from the size of the file
-         *------------------------------------------------------------*/
-        VSIStatBufL  sStatBuf;
+        // READ access:
+        // Establish the number of object IDs from the size of the file.
+        VSIStatBufL sStatBuf;
         if ( VSIStatL(m_pszFname, &sStatBuf) == -1 )
         {
-            CPLError(CE_Failure, CPLE_FileIO,
-                     "stat() failed for %s\n", m_pszFname);
+            CPLError(CE_Failure, CPLE_FileIO, "stat() failed for %s",
+                     m_pszFname);
             Close();
             return -1;
         }
 
-        if( static_cast<vsi_l_offset>(sStatBuf.st_size) > static_cast<vsi_l_offset>(INT_MAX / 4) )
+        if( static_cast<vsi_l_offset>(sStatBuf.st_size) >
+            static_cast<vsi_l_offset>(INT_MAX / 4) )
             m_nMaxId = INT_MAX / 4;
         else
-            m_nMaxId = (int)(sStatBuf.st_size/4);
-        m_nBlockSize = MIN(1024, m_nMaxId*4);
+            m_nMaxId = static_cast<int>(sStatBuf.st_size / 4);
+        m_nBlockSize = std::min(1024, m_nMaxId * 4);
 
-        /*-------------------------------------------------------------
-         * Read the first block from the file
-         *------------------------------------------------------------*/
+        // Read the first block from the file.
         m_poIDBlock = new TABRawBinBlock(m_eAccessMode, FALSE);
 
         if (m_nMaxId == 0)
@@ -235,10 +200,8 @@ int TABIDFile::Open(const char *pszFname, TABAccess eAccess)
     }
     else
     {
-        /*-------------------------------------------------------------
-         * WRITE access:
-         * Get ready to write to the file
-         *------------------------------------------------------------*/
+        // WRITE access:
+        // Get ready to write to the file.
         m_poIDBlock = new TABRawBinBlock(m_eAccessMode, FALSE);
         m_nMaxId = 0;
         m_nBlockSize = 1024;
@@ -260,9 +223,7 @@ int TABIDFile::Close()
     if (m_fp == NULL)
         return 0;
 
-    /*----------------------------------------------------------------
-     * Write access: commit latest changes to the file.
-     *---------------------------------------------------------------*/
+    // Write access: commit latest changes to the file.
     if (m_eAccessMode != TABRead)
         SyncToDisk();
 
@@ -324,7 +285,7 @@ GInt32 TABIDFile::GetObjPtr(GInt32 nObjId)
         return -1;
     }
 
-    if (m_poIDBlock->GotoByteInFile( (nObjId-1)*4 ) != 0)
+    if (m_poIDBlock->GotoByteInFile((nObjId - 1) * 4) != 0)
         return -1;
 
     return m_poIDBlock->ReadInt32();
@@ -356,40 +317,36 @@ int TABIDFile::SetObjPtr(GInt32 nObjId, GInt32 nObjPtr)
 
     if (nObjId < 1)
     {
-        CPLError(CE_Failure, CPLE_IllegalArg,
-               "SetObjPtr(): Invalid object ID %d (must be greater than zero)",
-                 nObjId);
+        CPLError(
+            CE_Failure, CPLE_IllegalArg,
+            "SetObjPtr(): Invalid object ID %d (must be greater than zero)",
+            nObjId);
         return -1;
     }
 
-    /*-----------------------------------------------------------------
-     * GotoByteInFile() will automagically commit current block and init
-     * a new one if necessary.
-     *----------------------------------------------------------------*/
-    GInt32 nLastIdBlock = ((m_nMaxId-1)*4) / m_nBlockSize;
-    GInt32 nTargetIdBlock = ((nObjId-1)*4) / m_nBlockSize;
+    // GotoByteInFile() will automagically commit current block and init
+    // a new one if necessary.
+    const GInt32 nLastIdBlock = ((m_nMaxId - 1) * 4) / m_nBlockSize;
+    const GInt32 nTargetIdBlock = ((nObjId - 1) * 4) / m_nBlockSize;
     if (m_nMaxId > 0 && nTargetIdBlock <= nLastIdBlock)
     {
-        /* Pass second arg to GotoByteInFile() to force reading from file
-         * when going back to blocks already committed
-         */
-        if (m_poIDBlock->GotoByteInFile( (nObjId-1)*4, TRUE ) != 0)
+        // Pass second arg to GotoByteInFile() to force reading from file
+        // when going back to blocks already committed.
+        if (m_poIDBlock->GotoByteInFile((nObjId - 1) * 4, TRUE) != 0)
             return -1;
     }
     else
     {
-        /* If we reach EOF then a new empty block will have to be allocated
-         */
-        if (m_poIDBlock->GotoByteInFile( (nObjId-1)*4 ) != 0)
+        // If we reach EOF then a new empty block will have to be allocated.
+        if (m_poIDBlock->GotoByteInFile((nObjId - 1) * 4) != 0)
             return -1;
     }
 
-    m_nMaxId = MAX(m_nMaxId, nObjId);
+    m_nMaxId = std::max(m_nMaxId, nObjId);
 
     return m_poIDBlock->WriteInt32(nObjPtr);
 }
 
-
 /**********************************************************************
  *                   TABIDFile::GetMaxObjId()
  *
@@ -399,11 +356,7 @@ int TABIDFile::SetObjPtr(GInt32 nObjId, GInt32 nObjPtr)
  *
  * Returns a value >= 0 on success, -1 on error.
  **********************************************************************/
-GInt32 TABIDFile::GetMaxObjId()
-{
-    return m_nMaxId;
-}
-
+GInt32 TABIDFile::GetMaxObjId() { return m_nMaxId; }
 
 /**********************************************************************
  *                   TABIDFile::Dump()
@@ -429,10 +382,9 @@ void TABIDFile::Dump(FILE *fpOut /*=NULL*/)
         fprintf(fpOut, "Current index block follows ...\n\n");
         m_poIDBlock->Dump(fpOut);
         fprintf(fpOut, "... end of index block.\n\n");
-
     }
 
     fflush(fpOut);
 }
 
-#endif // DEBUG
+#endif  // DEBUG
diff --git a/ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp b/ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp
index b2ed38d..293bf9c 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_imapinfofile.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_imapinfofile.cpp,v 1.31 2010-01-07 20:39:12 aboudreault Exp $
  *
  * Name:     mitab_imapinfo
  * Project:  MapInfo mid/mif Tab Read/Write library
@@ -29,111 +28,23 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_imapinfofile.cpp,v $
- * Revision 1.31  2010-01-07 20:39:12  aboudreault
- * Added support to handle duplicate field names, Added validation to check if a field name start with a number (bug 2141)
- *
- * Revision 1.30  2009-01-23 16:50:27  aboudreault
- * Fixed wrong return value of IMapInfoFile::SetCharset() method (bug 1987)
- *
- * Revision 1.29  2008/11/27 20:50:22  aboudreault
- * Improved support for OGR date/time types. New Read/Write methods (bug 1948)
- * Added support of OGR date/time types for MIF features.
- *
- * Revision 1.28  2008/11/17 22:06:21  aboudreault
- * Added support to use OFTDateTime/OFTDate/OFTTime type when compiled with
- * OGR and fixed reading/writing support for these types.
- *
- * Revision 1.27  2008/09/26 14:40:24  aboudreault
- * Fixed bug: MITAB doesn't support writing DateTime type (bug 1948)
- *
- * Revision 1.26  2008/03/07 20:16:17  dmorissette
- * Fixed typos in comments
- *
- * Revision 1.25  2008/03/05 20:35:39  dmorissette
- * Replace MITAB 1.x SetFeature() with a CreateFeature() for V2.x (bug 1859)
- *
- * Revision 1.24  2007/06/21 14:00:23  dmorissette
- * Added missing cast in isspace() calls to avoid failed assertion on Windows
- * (MITAB bug 1737, GDAL ticket 1678))
- *
- * Revision 1.23  2007/06/12 14:43:19  dmorissette
- * Use iswspace instead of ispace in IMapInfoFile::SmartOpen() (bug 1737)
- *
- * Revision 1.22  2007/06/12 13:52:37  dmorissette
- * Added IMapInfoFile::SetCharset() method (bug 1734)
- *
- * Revision 1.21  2005/05/19 21:10:50  fwarmerdam
- * changed to use OGRLayers spatial filter support
- *
- * Revision 1.20  2005/05/19 15:27:00  jlacroix
- * Implement a method to set the StyleString of a TABFeature.
- * This is done via the ITABFeaturePen, Brush and Symbol classes.
- *
- * Revision 1.19  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.18  2003/12/19 07:55:55  fwarmerdam
- * treat 3D features as 2D on write
- *
- * Revision 1.17  2001/09/14 19:14:43  warmerda
- * added attribute query support
- *
- * Revision 1.16  2001/09/14 03:23:55  warmerda
- * Substantial upgrade to support spatial queries using spatial indexes
- *
- * Revision 1.15  2001/07/03 23:11:21  daniel
- * Test for NULL geometries if spatial filter enabled in GetNextFeature().
- *
- * Revision 1.14  2001/03/09 04:16:02  daniel
- * Added TABSeamless for reading seamless TAB files
- *
- * Revision 1.13  2001/02/27 19:59:05  daniel
- * Enabled spatial filter in IMapInfoFile::GetNextFeature(), and avoid
- * unnecessary feature cloning in GetNextFeature() and GetFeature()
- *
- * Revision 1.12  2001/02/06 22:03:24  warmerda
- * fixed memory leak of whole features in CreateFeature
- *
- * Revision 1.11  2001/01/23 21:23:42  daniel
- * Added projection bounds lookup table, called from TABFile::SetProjInfo()
- *
- * Revision 1.10  2001/01/22 16:03:58  warmerda
- * expanded tabs
- *
- * Revision 1.9  2000/11/30 20:27:56  warmerda
- * make variable length string fields 254 wide, not 255
- *
- * Revision 1.8  2000/02/28 03:11:35  warmerda
- * fix support for zero width fields
- *
- * Revision 1.7  2000/02/02 20:14:03  warmerda
- * made safer when encountering geometryless features
- *
- * Revision 1.6  2000/01/26 18:17:35  warmerda
- * added CreateField method
- *
- * Revision 1.5  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.4  2000/01/11 19:06:25  daniel
- * Added support for conversion of collections in CreateFeature()
- *
- * Revision 1.3  1999/12/14 02:14:50  daniel
- * Added static SmartOpen() method + TABView support
- *
- * Revision 1.2  1999/11/08 19:15:44  stephane
- * Add headers method
- *
- * Revision 1.1  1999/11/08 04:17:27  stephane
- * First Revision
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <cctype>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
 #include "mitab_utils.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
 
 #ifdef __HP_aCC
 #  include <wchar.h>      /* iswspace() */
@@ -141,19 +52,19 @@
 #  include <wctype.h>      /* iswspace() */
 #endif
 
+CPL_CVSID("$Id: mitab_imapinfofile.cpp 37347 2017-02-12 03:10:54Z goatbar $");
+
 /**********************************************************************
  *                   IMapInfoFile::IMapInfoFile()
  *
  * Constructor.
  **********************************************************************/
-IMapInfoFile::IMapInfoFile()
-{
-    m_nCurFeatureId = 0;
-    m_poCurFeature = NULL;
-    m_bBoundsSet = FALSE;
-    m_pszCharset = NULL;
-}
-
+IMapInfoFile::IMapInfoFile() :
+    m_nCurFeatureId(0),
+    m_poCurFeature(NULL),
+    m_bBoundsSet(FALSE),
+    m_pszCharset(NULL)
+{}
 
 /**********************************************************************
  *                   IMapInfoFile::~IMapInfoFile()
@@ -162,7 +73,7 @@ IMapInfoFile::IMapInfoFile()
  **********************************************************************/
 IMapInfoFile::~IMapInfoFile()
 {
-    if (m_poCurFeature)
+    if( m_poCurFeature )
     {
         delete m_poCurFeature;
         m_poCurFeature = NULL;
@@ -182,6 +93,7 @@ IMapInfoFile::~IMapInfoFile()
 int IMapInfoFile::Open(const char *pszFname, const char* pszAccess,
                        GBool bTestOpenNoError)
 {
+    // cppcheck-suppress nullPointer
     if( STARTS_WITH_CI(pszAccess, "r") )
         return Open(pszFname, TABRead, bTestOpenNoError);
     else if( STARTS_WITH_CI(pszAccess, "w") )
@@ -197,7 +109,7 @@ int IMapInfoFile::Open(const char *pszFname, const char* pszAccess,
 /**********************************************************************
  *                   IMapInfoFile::SmartOpen()
  *
- * Use this static method to automatically open any flavour of MapInfo
+ * Use this static method to automatically open any flavor of MapInfo
  * dataset.  This method will detect the file type, create an object
  * of the right type, and open the file.
  *
@@ -230,13 +142,14 @@ IMapInfoFile *IMapInfoFile::SmartOpen(const char *pszFname,
          * .TAB file ... is it a TABFileView or a TABFile?
          * We have to read the .tab header to find out.
          *------------------------------------------------------------*/
-        VSILFILE *fp;
-        const char *pszLine;
         char *pszAdjFname = CPLStrdup(pszFname);
-        GBool bFoundFields = FALSE, bFoundView=FALSE, bFoundSeamless=FALSE;
+        GBool bFoundFields = FALSE;
+        GBool bFoundView = FALSE;
+        GBool bFoundSeamless = FALSE;
 
         TABAdjustFilenameExtension(pszAdjFname);
-        fp = VSIFOpenL(pszAdjFname, "r");
+        VSILFILE *fp = VSIFOpenL(pszAdjFname, "r");
+        const char *pszLine = NULL;
         while(fp && (pszLine = CPLReadLineL(fp)) != NULL)
         {
             while (isspace((unsigned char)*pszLine))  pszLine++;
@@ -279,8 +192,6 @@ IMapInfoFile *IMapInfoFile::SmartOpen(const char *pszFname,
     return poFile;
 }
 
-
-
 /**********************************************************************
  *                   IMapInfoFile::GetNextFeature()
  *
@@ -289,13 +200,12 @@ IMapInfoFile *IMapInfoFile::SmartOpen(const char *pszFname,
  **********************************************************************/
 OGRFeature *IMapInfoFile::GetNextFeature()
 {
-    OGRFeature *poFeatureRef;
-    OGRGeometry *poGeom;
-    GIntBig nFeatureId;
+    GIntBig nFeatureId = 0;
 
     while( (nFeatureId = GetNextFeatureId(m_nCurFeatureId)) != -1 )
     {
-        poFeatureRef = GetFeatureRef(nFeatureId);
+        OGRGeometry *poGeom = NULL;
+        OGRFeature *poFeatureRef = GetFeatureRef(nFeatureId);
         if (poFeatureRef == NULL)
             return NULL;
         else if( (m_poFilterGeom == NULL ||
@@ -323,8 +233,8 @@ OGRFeature *IMapInfoFile::GetNextFeature()
 
 TABFeature* IMapInfoFile::CreateTABFeature(OGRFeature *poFeature)
 {
-    TABFeature *poTABFeature;
-    OGRGeometry   *poGeom;
+    TABFeature *poTABFeature = NULL;
+    OGRGeometry   *poGeom = NULL;
     OGRwkbGeometryType eGType;
     TABPoint *poTABPointFeature = NULL;
     TABRegion *poTABRegionFeature = NULL;
@@ -392,11 +302,12 @@ TABFeature* IMapInfoFile::CreateTABFeature(OGRFeature *poFeature)
       case wkbMultiPoint:
       {
           OGRErr eStatus = OGRERR_NONE;
-          int i;
           OGRGeometryCollection *poColl = (OGRGeometryCollection*)poGeom;
           OGRFeature *poTmpFeature = poFeature->Clone();
 
-          for (i=0; eStatus==OGRERR_NONE && i<poColl->getNumGeometries(); i++)
+          for( int i = 0;
+               eStatus==OGRERR_NONE && i<poColl->getNumGeometries();
+               i++)
           {
               poTmpFeature->SetFID(OGRNullFID);
               poTmpFeature->SetGeometry(poColl->getGeometryRef(i));
@@ -404,7 +315,7 @@ TABFeature* IMapInfoFile::CreateTABFeature(OGRFeature *poFeature)
           }
           delete poTmpFeature;
           return NULL;
-        }
+      }
         break;
       /*-------------------------------------------------------------
        * Unsupported type.... convert to MapInfo geometry NONE
@@ -436,14 +347,11 @@ TABFeature* IMapInfoFile::CreateTABFeature(OGRFeature *poFeature)
  **********************************************************************/
 OGRErr     IMapInfoFile::ICreateFeature(OGRFeature *poFeature)
 {
-    TABFeature *poTABFeature;
-    OGRErr  eErr;
-
-    poTABFeature = CreateTABFeature(poFeature);
+    TABFeature *poTABFeature = CreateTABFeature(poFeature);
     if( poTABFeature == NULL ) /* MultiGeometry */
         return OGRERR_NONE;
 
-    eErr = CreateFeature(poTABFeature);
+    OGRErr eErr = CreateFeature(poTABFeature);
     if( eErr == OGRERR_NONE )
         poFeature->SetFID(poTABFeature->GetFID());
 
@@ -461,11 +369,9 @@ OGRErr     IMapInfoFile::ICreateFeature(OGRFeature *poFeature)
  **********************************************************************/
 OGRFeature *IMapInfoFile::GetFeature(GIntBig nFeatureId)
 {
-    OGRFeature *poFeatureRef;
-
     /*fprintf(stderr, "GetFeature(%ld)\n", nFeatureId);*/
 
-    poFeatureRef = GetFeatureRef(nFeatureId);
+    OGRFeature *poFeatureRef = GetFeatureRef(nFeatureId);
     if (poFeatureRef)
     {
         // Avoid cloning feature... return the copy owned by the class
@@ -550,7 +456,7 @@ int IMapInfoFile::GetTABType( OGRFieldDefn *poField,
         if( nWidth == 0 )
             nWidth = 254;
         else
-            nWidth = MIN(254,nWidth);
+            nWidth = std::min(254, nWidth);
     }
     else
     {
@@ -579,9 +485,9 @@ int IMapInfoFile::GetTABType( OGRFieldDefn *poField,
 OGRErr IMapInfoFile::CreateField( OGRFieldDefn *poField, int bApproxOK )
 
 {
-    TABFieldType        eTABType;
-    int                 nWidth;
-    int                 nPrecision;
+    TABFieldType eTABType;
+    int nWidth = 0;
+    int nPrecision = 0;
 
     if( GetTABType( poField, &eTABType, &nWidth, &nPrecision ) < 0 )
         return OGRERR_FAILURE;
@@ -589,10 +495,9 @@ OGRErr IMapInfoFile::CreateField( OGRFieldDefn *poField, int bApproxOK )
     if( AddFieldNative( poField->GetNameRef(), eTABType,
                         nWidth, nPrecision, FALSE, FALSE, bApproxOK ) > -1 )
         return OGRERR_NONE;
-    else
-        return OGRERR_FAILURE;
-}
 
+    return OGRERR_FAILURE;
+}
 
 /**********************************************************************
  *                   IMapInfoFile::SetCharset()
diff --git a/ogr/ogrsf_frmts/mitab/mitab_indfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_indfile.cpp
index 83af153..1f8e408 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_indfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_indfile.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_indfile.cpp,v 1.14 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_indfile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,79 +28,42 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_indfile.cpp,v $
- * Revision 1.14  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.13  2008-01-29 20:46:32  dmorissette
- * Added support for v9 Time and DateTime fields (byg 1754)
- *
- * Revision 1.12  2007/12/11 03:43:03  dmorissette
- * Added reporting access mode to error message in TABINDFile::Open()
- * (GDAL changeset r12460, ticket 1620)
- *
- * Revision 1.11  2005/04/29 19:08:56  dmorissette
- * Produce an error if m_nSubtreeDepth > 255 when creating a .IND (OGR bug 839)
- *
- * Revision 1.10  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.9  2003/07/24 02:45:57  daniel
- * Fixed problem scanning node in TABINDNode::FindNext() - bug 2176, FW
- *
- * Revision 1.8  2001/05/01 03:38:23  daniel
- * Added update support (allows creating new index in existing IND files).
- *
- * Revision 1.7  2000/11/13 22:17:57  daniel
- * When a (child) node's first entry is replaced by InsertEntry() then make
- * sure that node's key is updated in its parent node.
- *
- * Revision 1.6  2000/03/01 00:32:00  daniel
- * Added support for float keys, and completed support for generating indexes
- *
- * Revision 1.5  2000/02/28 16:57:42  daniel
- * Added support for writing indexes
- *
- * Revision 1.4  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.3  1999/12/14 05:52:05  daniel
- * Fixed compile error on Windows
- *
- * Revision 1.2  1999/12/14 02:19:42  daniel
- * Completed .IND support for simple TABViews
- *
- * Revision 1.1  1999/11/20 15:49:07  daniel
- * Initial version
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <cctype>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
 #include "mitab_utils.h"
 
-#include <ctype.h>      /* toupper() */
+CPL_CVSID("$Id: mitab_indfile.cpp 37347 2017-02-12 03:10:54Z goatbar $");
 
 /*=====================================================================
  *                      class TABINDFile
  *====================================================================*/
 
-#define IND_MAGIC_COOKIE  24242424
+static const GUInt32 IND_MAGIC_COOKIE = 24242424;
 
 /**********************************************************************
  *                   TABINDFile::TABINDFile()
  *
  * Constructor.
  **********************************************************************/
-TABINDFile::TABINDFile()
+TABINDFile::TABINDFile() :
+    m_pszFname(NULL),
+    m_fp(NULL),
+    m_eAccessMode(TABRead),
+    m_numIndexes(0),
+    m_papoIndexRootNodes(NULL),
+    m_papbyKeyBuffers(NULL)
 {
-    m_fp = NULL;
-    m_pszFname = NULL;
-    m_eAccessMode = TABRead;
-    m_numIndexes = 0;
-    m_papoIndexRootNodes = NULL;
-    m_papbyKeyBuffers = NULL;
     m_oBlockManager.SetName("IND");
     m_oBlockManager.SetBlockSize(512);
 }
@@ -136,8 +98,6 @@ TABINDFile::~TABINDFile()
 int TABINDFile::Open(const char *pszFname, const char *pszAccess,
                      GBool bTestOpenNoError /*=FALSE*/)
 {
-    int         nLen;
-
     if (m_fp)
     {
         CPLError(CE_Failure, CPLE_FileIO,
@@ -177,7 +137,7 @@ int TABINDFile::Open(const char *pszFname, const char *pszAccess,
      *----------------------------------------------------------------*/
     m_pszFname = CPLStrdup(pszFname);
 
-    nLen = static_cast<int>(strlen(m_pszFname));
+    const int nLen = static_cast<int>(strlen(m_pszFname));
     if (nLen > 4 && !EQUAL(m_pszFname+nLen-4, ".IND") )
         strcpy(m_pszFname+nLen-4, ".ind");
 
@@ -294,7 +254,6 @@ int TABINDFile::Close()
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABINDFile::ReadHeader()
  *
@@ -321,8 +280,7 @@ int TABINDFile::ReadHeader()
     /*-----------------------------------------------------------------
      * Read the header block
      *----------------------------------------------------------------*/
-    TABRawBinBlock *poHeaderBlock;
-    poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE);
+    TABRawBinBlock *poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE);
     if (poHeaderBlock->ReadFromFile(m_fp, 0, 512) != 0)
     {
         // CPLError() has already been called.
@@ -415,7 +373,6 @@ int TABINDFile::ReadHeader()
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABINDFile::WriteHeader()
  *
@@ -432,8 +389,7 @@ int TABINDFile::WriteHeader()
     /*-----------------------------------------------------------------
      * Write the 48 bytes of file header
      *----------------------------------------------------------------*/
-    TABRawBinBlock *poHeaderBlock;
-    poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE);
+    TABRawBinBlock *poHeaderBlock = new TABRawBinBlock(m_eAccessMode, TRUE);
     poHeaderBlock->InitNewBlock(m_fp, 512, 0);
 
     poHeaderBlock->WriteInt32( IND_MAGIC_COOKIE );
@@ -578,7 +534,7 @@ int TABINDFile::SetIndexUnique(int nIndexNumber, GBool bUnique/*=TRUE*/)
  * next call to BuildKey().  (should not be freed by the caller).
  * Returns NULL if field index is invalid.
  *
- * The first flavour of the function handles integer type of values, this
+ * The first flavor of the function handles integer type of values, this
  * corresponds to MapInfo types: integer, smallint, logical and date
  **********************************************************************/
 GByte *TABINDFile::BuildKey(int nIndexNumber, GInt32 nValue)
@@ -657,12 +613,12 @@ GByte *TABINDFile::BuildKey(int nIndexNumber, const char *pszStr)
  *
  * BuildKey() for float and decimal fields
  **********************************************************************/
-GByte *TABINDFile::BuildKey(int nIndexNumber, double dValue)
+GByte *TABINDFile::BuildKey( int nIndexNumber, double dValue )
 {
     if (ValidateIndexNo(nIndexNumber) != 0)
         return NULL;
 
-    int nKeyLength = m_papoIndexRootNodes[nIndexNumber-1]->GetKeyLength();
+    const int nKeyLength = m_papoIndexRootNodes[nIndexNumber-1]->GetKeyLength();
     CPLAssert(nKeyLength == 8 && sizeof(double) == 8);
 
     /*-----------------------------------------------------------------
@@ -680,7 +636,6 @@ GByte *TABINDFile::BuildKey(int nIndexNumber, double dValue)
     return m_papbyKeyBuffers[nIndexNumber-1];
 }
 
-
 /**********************************************************************
  *                   TABINDFile::FindFirst()
  *
@@ -723,7 +678,6 @@ GInt32 TABINDFile::FindNext(int nIndexNumber, GByte *pKeyValue)
     return m_papoIndexRootNodes[nIndexNumber-1]->FindNext(pKeyValue);
 }
 
-
 /**********************************************************************
  *                   TABINDFile::CreateIndex()
  *
@@ -807,7 +761,7 @@ int TABINDFile::CreateIndex(TABFieldType eType, int nFieldSize)
                       (eType == TABFDate)     ? 4:
                       (eType == TABFTime)     ? 4:
                       /*(eType == TABFDateTime) ? 8: */
-                      (eType == TABFLogical)  ? 4: MIN(128,nFieldSize));
+                      (eType == TABFLogical)  ? 4: std::min(128, nFieldSize));
 
     m_papoIndexRootNodes[nNewIndexNo] = new TABINDNode(m_eAccessMode);
     if (m_papoIndexRootNodes[nNewIndexNo]->InitNode(m_fp, 0, nKeyLength,
@@ -829,7 +783,6 @@ int TABINDFile::CreateIndex(TABFieldType eType, int nFieldSize)
     return nNewIndexNo+1;
 }
 
-
 /**********************************************************************
  *                   TABINDFile::AddEntry()
  *
@@ -849,7 +802,6 @@ int TABINDFile::AddEntry(int nIndexNumber, GByte *pKeyValue, GInt32 nRecordNo)
     return m_papoIndexRootNodes[nIndexNumber-1]->AddEntry(pKeyValue,nRecordNo);
 }
 
-
 /**********************************************************************
  *                   TABINDFile::Dump()
  *
@@ -880,7 +832,6 @@ void TABINDFile::Dump(FILE *fpOut /*=NULL*/)
                 m_papoIndexRootNodes[i]->Dump(fpOut);
             }
         }
-
     }
 
     fflush(fpOut);
@@ -888,10 +839,6 @@ void TABINDFile::Dump(FILE *fpOut /*=NULL*/)
 
 #endif // DEBUG
 
-
-
-
-
 /*=====================================================================
  *                      class TABINDNode
  *====================================================================*/
@@ -901,25 +848,23 @@ void TABINDFile::Dump(FILE *fpOut /*=NULL*/)
  *
  * Constructor.
  **********************************************************************/
-TABINDNode::TABINDNode(TABAccess eAccessMode /*=TABRead*/)
-{
-    m_fp = NULL;
-    m_poCurChildNode = NULL;
-    m_nSubTreeDepth = 0;
-    m_nKeyLength = 0;
-    m_eFieldType = TABFUnknown;
-    m_poDataBlock = NULL;
-    m_numEntriesInNode = 0;
-    m_nCurIndexEntry = 0;
-    m_nPrevNodePtr = 0;
-    m_nNextNodePtr = 0;
-    m_poBlockManagerRef = NULL;
-    m_poParentNodeRef = NULL;
-    m_bUnique = FALSE;
-
-    m_eAccessMode = eAccessMode;
-    m_nCurDataBlockPtr = 0;
-}
+TABINDNode::TABINDNode( TABAccess eAccessMode /*=TABRead*/ ) :
+    m_fp(NULL),
+    m_eAccessMode(eAccessMode),
+    m_poCurChildNode(NULL),
+    m_poParentNodeRef(NULL),
+    m_poBlockManagerRef(NULL),
+    m_nSubTreeDepth(0),
+    m_nKeyLength(0),
+    m_eFieldType(TABFUnknown),
+    m_bUnique(FALSE),
+    m_nCurDataBlockPtr(0),
+    m_nCurIndexEntry(0),
+    m_poDataBlock(NULL),
+    m_numEntriesInNode(0),
+    m_nPrevNodePtr(0),
+    m_nNextNodePtr(0)
+{}
 
 /**********************************************************************
  *                   TABINDNode::~TABINDNode()
@@ -1031,7 +976,6 @@ int TABINDNode::InitNode(VSILFILE *fp, int nBlockPtr,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABINDNode::GotoNodePtr()
  *
@@ -1336,14 +1280,12 @@ GInt32 TABINDNode::FindFirst(GByte *pKeyValue)
                 }/*for iChild*/
 
                 return nRetValue;
-
-            }/*else*/
-
-        }/*while numEntries*/
+            }  // else
+        }  // while numEntries
 
         // No node was found that contains the key value.
         // We should never get here... only leaf nodes should return 0
-        CPLAssert(FALSE);
+        CPLAssert(false);
         return 0;
     }
 
@@ -1416,7 +1358,6 @@ GInt32 TABINDNode::FindNext(GByte *pKeyValue)
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABINDNode::CommitToFile()
  *
@@ -1480,7 +1421,7 @@ int TABINDNode::AddEntry(GByte *pKeyValue, GInt32 nRecordNo,
 
     /*-----------------------------------------------------------------
      * If I'm the root node, then do a FindFirst() to init all the nodes
-     * and to make all of them point ot the insertion point.
+     * and to make all of them point to the insertion point.
      *----------------------------------------------------------------*/
     if (m_poParentNodeRef == NULL && !bAddInThisNodeOnly)
     {
@@ -1608,7 +1549,6 @@ int TABINDNode::InsertEntry(GByte *pKeyValue, GInt32 nRecordNo,
         memmove(m_poDataBlock->GetCurDataPtr()+(m_nKeyLength+4),
                 m_poDataBlock->GetCurDataPtr(),
                 (m_numEntriesInNode-iInsertAt)*(m_nKeyLength+4));
-
     }
 
     /*-----------------------------------------------------------------
@@ -1640,7 +1580,6 @@ int TABINDNode::InsertEntry(GByte *pKeyValue, GInt32 nRecordNo,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABINDNode::UpdateCurChildEntry()
  *
@@ -1673,8 +1612,6 @@ int TABINDNode::UpdateCurChildEntry(GByte *pKeyValue, GInt32 nRecordNo)
     return 0;
 }
 
-
-
 /**********************************************************************
  *                   TABINDNode::UpdateSplitChild()
  *
@@ -1722,7 +1659,6 @@ int TABINDNode::UpdateSplitChild(GByte *pKeyValue1, GInt32 nRecordNo1,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABINDNode::SplitNode()
  *
@@ -1821,7 +1757,6 @@ int TABINDNode::SplitNode()
                 return -1;
             }
         }
-
     }
     else
     {
@@ -1896,7 +1831,6 @@ int TABINDNode::SplitNode()
                 return -1;
             }
         }
-
     }
 
     /*-----------------------------------------------------------------
@@ -2082,8 +2016,6 @@ int TABINDNode::SetNextNodePtr(GInt32 nNextNodePtr)
     return m_poDataBlock->WriteInt32(nNextNodePtr);
 }
 
-
-
 /**********************************************************************
  *                   TABINDNode::Dump()
  *
@@ -2147,12 +2079,12 @@ void TABINDNode::Dump(FILE *fpOut /*=NULL*/)
               }
               else if (m_nKeyLength != 4)
               {
-                GInt32 nInt32;
-                GInt16 nInt16;
-                GUInt32 nUInt32;
                 nRecordPtr = ReadIndexEntry(i, aKeyValBuf);
+                GInt32 nInt32 = 0;
                 memcpy(&nInt32, aKeyValBuf, 4);
+                GInt16 nInt16 = 0;
                 memcpy(&nInt16, aKeyValBuf + 2, 2);
+                GUInt32 nUInt32 = 0;
                 memcpy(&nUInt32, aKeyValBuf, 4);
                 fprintf(fpOut, "   nRecordPtr = %d\n", nRecordPtr);
                 fprintf(fpOut, "   Int Value = %d\n", nInt32);
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp
index d657f8c..5bc89c7 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapcoordblock.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_mapcoordblock.cpp,v 1.18 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_mapcoordblock.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,113 +28,60 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_mapcoordblock.cpp,v $
- * Revision 1.18  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.17  2008-02-01 19:36:31  dmorissette
- * Initial support for V800 REGION and MULTIPLINE (bug 1496)
- *
- * Revision 1.16  2007/02/23 18:56:44  dmorissette
- * Fixed another problem writing collections when the header of objects
- * part of a collection were split on multiple blocks. Fix WriteBytes()
- * to reload next coord block in TABReadWrite mode if there is one (bug 1663)
- *
- * Revision 1.15  2006/11/28 18:49:08  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.14  2005/10/06 19:15:31  dmorissette
- * Collections: added support for reading/writing pen/brush/symbol ids and
- * for writing collection objects to .TAB/.MAP (bug 1126)
- *
- * Revision 1.13  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.12  2002/08/27 17:18:23  warmerda
- * improved CPL error testing
- *
- * Revision 1.11  2001/11/17 21:54:06  daniel
- * Made several changes in order to support writing objects in 16 bits coordinate format.
- * New TABMAPObjHdr-derived classes are used to hold object info in mem until block is full.
- *
- * Revision 1.10  2001/05/09 17:45:12  daniel
- * Support reading and writing data blocks > 512 bytes (for text objects).
- *
- * Revision 1.9  2000/10/10 19:05:12  daniel
- * Fixed ReadBytes() to allow strings overlapping on 2 blocks
- *
- * Revision 1.8  2000/02/28 16:58:55  daniel
- * Added V450 object types with num_points > 32767 and pen width in points
- *
- * Revision 1.7  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.6  1999/11/08 04:29:31  daniel
- * Fixed problem with compressed coord. offset for regions and multiplines
- *
- * Revision 1.5  1999/10/06 15:19:11  daniel
- * Do not automatically init. curr. feature MBR when block is initialized
- *
- * Revision 1.4  1999/10/06 13:18:55  daniel
- * Fixed uninitialized class members
- *
- * Revision 1.3  1999/09/29 04:25:42  daniel
- * Fixed typo in GetFeatureMBR()
- *
- * Revision 1.2  1999/09/26 14:59:36  daniel
- * Implemented write support
- *
- * Revision 1.1  1999/07/12 04:18:24  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <climits>
+#include <cstddef>
+#include <algorithm>
+
+#include "mitab_priv.h"
 #include "mitab_utils.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+
+CPL_CVSID("$Id: mitab_mapcoordblock.cpp 37347 2017-02-12 03:10:54Z goatbar $");
 
 /*=====================================================================
  *                      class TABMAPCoordBlock
  *====================================================================*/
 
-#define MAP_COORD_HEADER_SIZE   8
+static const int MAP_COORD_HEADER_SIZE = 8;
 
 /**********************************************************************
  *                   TABMAPCoordBlock::TABMAPCoordBlock()
  *
  * Constructor.
  **********************************************************************/
-TABMAPCoordBlock::TABMAPCoordBlock(TABAccess eAccessMode /*= TABRead*/):
-    TABRawBinBlock(eAccessMode, TRUE)
-{
-    m_nComprOrgX = m_nComprOrgY = m_nNextCoordBlock = m_numDataBytes = 0;
-
-    m_numBlocksInChain = 1;  // Current block counts as 1
-
-    m_poBlockManagerRef = NULL;
-
-    m_nTotalDataSize = 0;
-    m_nFeatureDataSize = 0;
-
-    m_nFeatureXMin = m_nMinX = 1000000000;
-    m_nFeatureYMin = m_nMinY = 1000000000;
-    m_nFeatureXMax = m_nMaxX = -1000000000;
-    m_nFeatureYMax = m_nMaxY = -1000000000;
-
-}
+TABMAPCoordBlock::TABMAPCoordBlock( TABAccess eAccessMode /*= TABRead*/ ) :
+    TABRawBinBlock(eAccessMode, TRUE),
+    m_numDataBytes(0),
+    m_nNextCoordBlock(0),
+    m_numBlocksInChain(1),  // Current block counts as 1
+    m_nComprOrgX(0),
+    m_nComprOrgY(0),
+    m_nMinX(1000000000),
+    m_nMinY(1000000000),
+    m_nMaxX(-1000000000),
+    m_nMaxY(-1000000000),
+    m_poBlockManagerRef(NULL),
+    m_nTotalDataSize(0),
+    m_nFeatureDataSize(0),
+    m_nFeatureXMin(1000000000),
+    m_nFeatureYMin(1000000000),
+    m_nFeatureXMax(-1000000000),
+    m_nFeatureYMax(-1000000000)
+{}
 
 /**********************************************************************
  *                   TABMAPCoordBlock::~TABMAPCoordBlock()
  *
  * Destructor.
  **********************************************************************/
-TABMAPCoordBlock::~TABMAPCoordBlock()
-{
-
-}
-
+TABMAPCoordBlock::~TABMAPCoordBlock() {}
 
 /**********************************************************************
  *                   TABMAPCoordBlock::InitBlockFromData()
@@ -152,15 +98,15 @@ int     TABMAPCoordBlock::InitBlockFromData(GByte *pabyBuf,
                                             VSILFILE *fpSrc /* = NULL */,
                                             int nOffset /* = 0 */)
 {
-    int nStatus;
 #ifdef DEBUG_VERBOSE
     CPLDebug("MITAB", "Instantiating COORD block to/from offset %d", nOffset);
 #endif
     /*-----------------------------------------------------------------
      * First of all, we must call the base class' InitBlockFromData()
      *----------------------------------------------------------------*/
-    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf, nBlockSize, nSizeUsed,
-                                                bMakeCopy, fpSrc, nOffset);
+    const int nStatus =
+        TABRawBinBlock::InitBlockFromData(pabyBuf, nBlockSize, nSizeUsed,
+                                          bMakeCopy, fpSrc, nOffset);
     if (nStatus != 0)
         return nStatus;
 
@@ -338,7 +284,6 @@ void     TABMAPCoordBlock::SetNextCoordBlock(GInt32 nNextCoordBlockAddress)
     m_bModified = TRUE;
 }
 
-
 /**********************************************************************
  *                   TABMAPObjectBlock::SetComprCoordOrigin()
  *
@@ -469,8 +414,6 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
                                            TABMAPCoordSecHdr *pasHdrs,
                                            GInt32    &numVerticesTotal)
 {
-    int i, nTotalHdrSizeUncompressed;
-
     CPLErrorReset();
 
     /*-------------------------------------------------------------
@@ -491,11 +434,11 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
                  "Invalid numSections");
         return -1;
     }
-    nTotalHdrSizeUncompressed = nSectionSize * numSections;
+    int nTotalHdrSizeUncompressed = nSectionSize * numSections;
 
     numVerticesTotal = 0;
 
-    for(i=0; i<numSections; i++)
+    for( int i = 0;  i < numSections; i++ )
     {
         /*-------------------------------------------------------------
          * Read the coord. section header blocks
@@ -544,11 +487,10 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
         }
         numVerticesTotal += pasHdrs[i].numVertices;
 
-
         pasHdrs[i].nVertexOffset = (pasHdrs[i].nDataOffset -
                                     nTotalHdrSizeUncompressed ) / 8;
 #ifdef TABDUMP
-        printf("READING pasHdrs[%d] @ %d = \n"
+        printf("READING pasHdrs[%d] @ %d = \n"/*ok*/
                "              { numVertices = %d, numHoles = %d, \n"
                "                nXMin=%d, nYMin=%d, nXMax=%d, nYMax=%d,\n"
                "                nDataOffset=%d, nVertexOffset=%d }\n",
@@ -556,14 +498,14 @@ int     TABMAPCoordBlock::ReadCoordSecHdrs(GBool bCompressed,
                pasHdrs[i].nXMin, pasHdrs[i].nYMin, pasHdrs[i].nXMax,
                pasHdrs[i].nYMax, pasHdrs[i].nDataOffset,
                pasHdrs[i].nVertexOffset);
-        printf("                dX = %d, dY = %d  (center = %d , %d)\n",
+        printf("                dX = %d, dY = %d  (center = %d , %d)\n",/*ok*/
                pasHdrs[i].nXMax - pasHdrs[i].nXMin,
                pasHdrs[i].nYMax - pasHdrs[i].nYMin,
                m_nComprOrgX, m_nComprOrgY);
 #endif
     }
 
-    for(i=0; i<numSections; i++)
+    for( int i = 0; i < numSections; i++ )
     {
         /*-------------------------------------------------------------
          * Make sure all coordinates are grouped together
@@ -607,17 +549,15 @@ int     TABMAPCoordBlock::WriteCoordSecHdrs(int nVersion,
                                             TABMAPCoordSecHdr *pasHdrs,
                                             GBool bCompressed /*=FALSE*/)
 {
-    int i;
-
     CPLErrorReset();
 
-    for(i=0; i<numSections; i++)
+    for( int i = 0; i < numSections; i++ )
     {
         /*-------------------------------------------------------------
          * Write the coord. section header blocks
          *------------------------------------------------------------*/
 #ifdef TABDUMP
-        printf("WRITING pasHdrs[%d] @ %d = \n"
+        printf("WRITING pasHdrs[%d] @ %d = \n"/*ok*/
                "              { numVertices = %d, numHoles = %d, \n"
                "                nXMin=%d, nYMin=%d, nXMax=%d, nYMax=%d,\n"
                "                nDataOffset=%d, nVertexOffset=%d }\n",
@@ -625,7 +565,7 @@ int     TABMAPCoordBlock::WriteCoordSecHdrs(int nVersion,
                pasHdrs[i].nXMin, pasHdrs[i].nYMin, pasHdrs[i].nXMax,
                pasHdrs[i].nYMax, pasHdrs[i].nDataOffset,
                pasHdrs[i].nVertexOffset);
-        printf("                dX = %d, dY = %d  (center = %d , %d)\n",
+        printf("                dX = %d, dY = %d  (center = %d , %d)\n",/*ok*/
                pasHdrs[i].nXMax - pasHdrs[i].nXMin,
                pasHdrs[i].nYMax - pasHdrs[i].nYMin,
                m_nComprOrgX, m_nComprOrgY);
@@ -650,7 +590,6 @@ int     TABMAPCoordBlock::WriteCoordSecHdrs(int nVersion,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPCoordBlock::WriteIntCoord()
  *
@@ -714,7 +653,6 @@ void TABMAPCoordBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr)
     m_poBlockManagerRef = poBlockMgr;
 };
 
-
 /**********************************************************************
  *                   TABMAPCoordBlock::ReadBytes()
  *
@@ -737,15 +675,15 @@ void TABMAPCoordBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr)
  **********************************************************************/
 int     TABMAPCoordBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
 {
-    int nStatus;
 
     if (m_pabyBuf &&
         m_nCurPos >= (m_numDataBytes+MAP_COORD_HEADER_SIZE) &&
         m_nNextCoordBlock > 0)
     {
         // We're at end of current block... advance to next block.
+        int nStatus = GotoByteInFile(m_nNextCoordBlock, TRUE);
 
-        if ( (nStatus=GotoByteInFile(m_nNextCoordBlock, TRUE)) != 0)
+        if( nStatus != 0 )
         {
             // Failed.... an error has already been reported.
             return nStatus;
@@ -765,18 +703,17 @@ int     TABMAPCoordBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
         // for the rest.
         int numBytesInThisBlock =
                       (m_numDataBytes+MAP_COORD_HEADER_SIZE)-m_nCurPos;
-        nStatus = TABRawBinBlock::ReadBytes(numBytesInThisBlock, pabyDstBuf);
-        if (nStatus == 0)
+        int nStatus =
+            TABRawBinBlock::ReadBytes(numBytesInThisBlock, pabyDstBuf);
+        if( nStatus == 0 )
             nStatus = TABMAPCoordBlock::ReadBytes(numBytes-numBytesInThisBlock,
                                                pabyDstBuf+numBytesInThisBlock);
         return nStatus;
     }
 
-
     return TABRawBinBlock::ReadBytes(numBytes, pabyDstBuf);
 }
 
-
 /**********************************************************************
  *                   TABMAPCoordBlock::WriteBytes()
  *
@@ -860,7 +797,7 @@ int  TABMAPCoordBlock::WriteBytes(int nBytesToWrite, const GByte *pabySrcBuf)
                     nBytes = (m_nBlockSize - m_nCurPos);
                 }
 
-                nBytes = MIN(nBytes, nBytesToWrite);
+                nBytes = std::min(nBytes, nBytesToWrite);
 
                 // The following call will result in a new block being
                 // allocated in the if() block above.
@@ -930,7 +867,6 @@ void TABMAPCoordBlock::GetFeatureMBR(GInt32 &nXMin, GInt32 &nYMin,
     nYMax = m_nFeatureYMax;
 }
 
-
 /**********************************************************************
  *                   TABMAPCoordBlock::Dump()
  *
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp
index 2c825b8..a63791c 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapfile.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_mapfile.cpp,v 1.46 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_mapfile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,214 +28,66 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_mapfile.cpp,v $
- * Revision 1.46  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.45  2010-01-08 22:02:51  aboudreault
- * Fixed error issued when reading empty TAB with spatial index active (bug 2136)
- *
- * Revision 1.44  2009-03-03 20:44:23  dmorissette
- * Use transparent brush in DumpSpatialIndexToMIF()
- *
- * Revision 1.43  2008/02/20 21:35:30  dmorissette
- * Added support for V800 COLLECTION of large objects (bug 1496)
- *
- * Revision 1.42  2008/02/01 19:36:31  dmorissette
- * Initial support for V800 REGION and MULTIPLINE (bug 1496)
- *
- * Revision 1.41  2007/11/08 18:57:56  dmorissette
- * Upgrade of OGR and CPL libs to the version from GDAL/OGR 1.4.3
- *
- * Revision 1.40  2007/09/14 18:30:19  dmorissette
- * Fixed the splitting of object blocks with the optimized spatial
- * index mode that was producing files with misaligned bytes that
- * confused MapInfo (bug 1732)
- *
- * Revision 1.39  2007/07/11 15:51:52  dmorissette
- * Fixed duplicate 'int i' definition build errors in SplitObjBlock()
- *
- * Revision 1.38  2007/06/12 12:50:39  dmorissette
- * Use Quick Spatial Index by default until bug 1732 is fixed (broken files
- * produced by current coord block splitting technique).
- *
- * Revision 1.37  2007/06/05 13:23:57  dmorissette
- * Fixed memory leak when writing .TAB with new (optimized) spatial index
- * introduced in v1.6.0 (bug 1725)
- *
- * Revision 1.36  2007/03/21 21:15:56  dmorissette
- * Added SetQuickSpatialIndexMode() which generates a non-optimal spatial
- * index but results in faster write time (bug 1669)
- *
- * Revision 1.35  2006/11/28 18:49:08  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.34  2006/11/20 20:05:58  dmorissette
- * First pass at improving generation of spatial index in .map file (bug 1585)
- * New methods for insertion and splitting the spatial index are done.
- * Also implemented a method to dump the spatial index to .mif/.mid
- * Still need to implement splitting of TABMapObjectBlock to get optimal
- * results.
- *
- * Revision 1.33  2006/09/05 23:05:08  dmorissette
- * Added TABMAPFile::DumpSpatialIndex() (bug 1585)
- *
- * Revision 1.32  2005/10/06 19:15:31  dmorissette
- * Collections: added support for reading/writing pen/brush/symbol ids and
- * for writing collection objects to .TAB/.MAP (bug 1126)
- *
- * Revision 1.31  2004/09/22 13:07:58  fwarmerdam
- * fixed return value in LoadNextMatchingObjectBlock() per rso bug 615
- *
- * Revision 1.30  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.29  2003/08/12 23:17:21  dmorissette
- * Added reading of v500+ coordsys affine params (Anthony D. - Encom)
- *
- * Revision 1.28  2002/08/27 17:18:43  warmerda
- * improved CPL error testing
- *
- * Revision 1.27  2002/07/30 13:54:12  julien
- * TABMAPFile::GetFeatureId() now return -1 when there's no geometry. (bug 169)
- *
- * Revision 1.26  2002/04/25 16:05:24  julien
- * Disabled the overflow warning in SetCoordFilter() by adding bIgnoreOverflow
- * variable in Coordsys2Int of the TABMAPFile class and TABMAPHeaderBlock class
- *
- * Revision 1.25  2002/03/26 19:27:43  daniel
- * Got rid of tabs in source
- *
- * Revision 1.24  2002/03/26 01:48:40  daniel
- * Added Multipoint object type (V650)
- *
- * Revision 1.23  2002/02/20 13:53:40  daniel
- * Prevent an infinite loop of calls to LoadNextMatchingObjectBlock() in
- * GetNextFeatureId() if no objects found in spatial index.
- *
- * Revision 1.22  2001/11/19 15:04:41  daniel
- * Prevent writing of coordinates outside of the +/-1e9 integer bounds.
- *
- * Revision 1.21  2001/11/17 21:54:06  daniel
- * Made several changes in order to support writing objects in 16 bits
- * coordinate format. New TABMAPObjHdr-derived classes are used to hold
- * object info in mem until block is full.
- *
- * Revision 1.20  2001/09/18 20:33:52  warmerda
- * fixed case of spatial search on file with just one object block
- *
- * Revision 1.19  2001/09/14 03:23:55  warmerda
- * Substantial upgrade to support spatial queries using spatial indexes
- *
- * Revision 1.18  2001/03/15 03:57:51  daniel
- * Added implementation for new OGRLayer::GetExtent(), returning data MBR.
- *
- * Revision 1.17  2000/11/23 21:11:07  daniel
- * OOpps... VC++ didn't like the way TABPenDef, etc. were initialized
- *
- * Revision 1.16  2000/11/23 20:47:46  daniel
- * Use MI defaults for Pen, Brush, Font, Symbol instead of all zeros
- *
- * Revision 1.15  2000/11/22 04:03:10  daniel
- * Added warning when objects written outside of the +/-1e9 int. coord. range
- *
- * Revision 1.14  2000/11/15 04:13:49  daniel
- * Fixed writing of TABMAPToolBlock to allocate a new block when full
- *
- * Revision 1.13  2000/05/19 06:44:55  daniel
- * Modified generation of spatial index to split index nodes and produce a
- * more balanced tree.
- *
- * Revision 1.12  2000/03/13 05:58:01  daniel
- * Create 1024 bytes V500 .MAP header + limit m_nMaxCoordBufSize for V450 obj.
- *
- * Revision 1.11  2000/02/28 17:00:00  daniel
- * Added V450 object types
- *
- * Revision 1.10  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.9  1999/12/19 17:37:52  daniel
- * Fixed memory leaks
- *
- * Revision 1.8  1999/11/14 04:43:31  daniel
- * Support dataset with no .MAP/.ID files
- *
- * Revision 1.7  1999/10/19 22:57:17  daniel
- * Create m_poCurObjBlock only when needed to avoid empty blocks in files
- * and problems with MBR in header block of files with only "NONE" geometries
- *
- * Revision 1.6  1999/10/06 13:17:46  daniel
- * Update m_nMaxCoordBufSize in header block
- *
- * Revision 1.5  1999/10/01 03:52:22  daniel
- * Avoid producing an unused block in the file when closing it.
- *
- * Revision 1.4  1999/09/26 14:59:36  daniel
- * Implemented write support
- *
- * Revision 1.3  1999/09/20 18:42:42  daniel
- * Use binary access to open file.
- *
- * Revision 1.2  1999/09/16 02:39:16  daniel
- * Completed read support for most feature types
- *
- * Revision 1.1  1999/07/12 04:18:24  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
 
+#include <cstddef>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+#include <utility>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
+#include "ogr_feature.h"
+
+CPL_CVSID("$Id: mitab_mapfile.cpp 37472 2017-02-26 02:47:45Z goatbar $");
+
 /*=====================================================================
  *                      class TABMAPFile
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABMAPFile::TABMAPFile()
  *
  * Constructor.
  **********************************************************************/
-TABMAPFile::TABMAPFile()
+TABMAPFile::TABMAPFile() :
+    m_nMinTABVersion(300),
+    m_pszFname(NULL),
+    m_fp(NULL),
+    m_eAccessMode(TABRead),
+    m_poHeader(NULL),
+    m_poSpIndex(NULL),
+    // See bug 1732: Optimized spatial index produces broken files because of
+    // the way CoordBlocks are split. For now we have to force using the quick
+    // (old) spatial index mode by default until bug 1732 is fixed.
+    m_bQuickSpatialIndexMode(TRUE),
+    m_poIdIndex(NULL),
+    m_poCurObjBlock(NULL),
+    m_nCurObjPtr(-1),
+    m_nCurObjType(TAB_GEOM_UNSET),
+    m_nCurObjId(-1),
+    m_poCurCoordBlock(NULL),
+    m_poToolDefTable(NULL),
+    m_XMinFilter(0),
+    m_YMinFilter(0),
+    m_XMaxFilter(0),
+    m_YMaxFilter(0),
+    m_bUpdated(FALSE),
+    m_bLastOpWasRead(FALSE),
+    m_bLastOpWasWrite(FALSE),
+    m_poSpIndexLeaf(NULL)
 {
-    m_nMinTABVersion = 300;
-    m_fp = NULL;
-    m_pszFname = NULL;
-    m_poHeader = NULL;
-    m_poSpIndex = NULL;
-    m_poSpIndexLeaf = NULL;
-/* See bug 1732: Optimized spatial index produces broken files because
- * of the way CoordBlocks are split. For now we have to force using the
- * Quick (old) spatial index mode by default until bug 1732 is fixed.
- */
-    m_bQuickSpatialIndexMode = TRUE;
-//  m_bQuickSpatialIndexMode = FALSE;
-
-    m_poCurObjBlock = NULL;
-    m_nCurObjPtr = -1;
-    m_nCurObjType = TAB_GEOM_UNSET;
-    m_nCurObjId = -1;
-    m_poCurCoordBlock = NULL;
-    m_poToolDefTable = NULL;
-
-    m_bUpdated = FALSE;
-    m_bLastOpWasRead = FALSE;
-    m_bLastOpWasWrite = FALSE;
-
-    m_eAccessMode = TABRead;
-    m_poIdIndex = NULL;
     m_sMinFilter.x = 0;
     m_sMinFilter.y = 0;
     m_sMaxFilter.x = 0;
     m_sMaxFilter.y = 0;
-    m_XMinFilter = 0;
-    m_YMinFilter = 0;
-    m_XMaxFilter = 0;
-    m_YMaxFilter = 0;
 
     m_oBlockManager.SetName("MAP");
 }
@@ -261,6 +112,7 @@ TABMAPFile::~TABMAPFile()
 int TABMAPFile::Open(const char *pszFname, const char* pszAccess, GBool bNoErrorMsg,
                      int nBlockSizeForCreate)
 {
+    // cppcheck-suppress nullPointer
     if( STARTS_WITH_CI(pszAccess, "r") )
         return Open(pszFname, TABRead, bNoErrorMsg, nBlockSizeForCreate);
     else if( STARTS_WITH_CI(pszAccess, "w") )
@@ -525,8 +377,8 @@ int TABMAPFile::Open(const char *pszFname, TABAccess eAccess,
             m_oBlockManager.PushGarbageBlockAsLast(nCurGarbBlock);
             while( true )
             {
-                GUInt16 nBlockType;
-                int     nNextGarbBlockPtr;
+                GUInt16 nBlockType = 0;
+                int nNextGarbBlockPtr = 0;
                 if( VSIFSeekL(fp, nCurGarbBlock, SEEK_SET) != 0 ||
                     VSIFReadL(&nBlockType, sizeof(nBlockType), 1, fp) != 1 ||
                     VSIFReadL(&nNextGarbBlockPtr, sizeof(nNextGarbBlockPtr), 1, fp) != 1 )
@@ -677,7 +529,7 @@ int TABMAPFile::SyncToDisk()
         if (m_nMinTABVersion >= 450)
         {
             m_poHeader->m_nMaxCoordBufSize =
-                                MIN(m_poHeader->m_nMaxCoordBufSize, 512*1024);
+                std::min(m_poHeader->m_nMaxCoordBufSize, 512*1024);
         }
 
         // Write Ref to beginning of the chain of garbage blocks
@@ -692,7 +544,10 @@ int TABMAPFile::SyncToDisk()
     // if that happened...
     if (m_poHeader && m_poHeader->m_bIntBoundsOverflow)
     {
-        double dBoundsMinX, dBoundsMinY, dBoundsMaxX, dBoundsMaxY;
+        double dBoundsMinX = 0.0;
+        double dBoundsMinY = 0.0;
+        double dBoundsMaxX = 0.0;
+        double dBoundsMaxY = 0.0;
         Int2Coordsys(-1000000000, -1000000000, dBoundsMinX, dBoundsMinY);
         Int2Coordsys(1000000000, 1000000000, dBoundsMaxX, dBoundsMaxY);
 
@@ -779,9 +634,7 @@ int TABMAPFile::SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode/*=TRUE*/)
 TABRawBinBlock *TABMAPFile::PushBlock( int nFileOffset )
 
 {
-    TABRawBinBlock *poBlock;
-
-    poBlock = GetIndexObjectBlock( nFileOffset );
+    TABRawBinBlock *poBlock = GetIndexObjectBlock( nFileOffset );
     if( poBlock == NULL )
         return NULL;
 
@@ -792,7 +645,8 @@ TABRawBinBlock *TABMAPFile::PushBlock( int nFileOffset )
         if( m_poSpIndexLeaf == NULL )
         {
             delete m_poSpIndex;
-            m_poSpIndexLeaf = m_poSpIndex = poIndex;
+            m_poSpIndexLeaf = poIndex;
+            m_poSpIndex = poIndex;
         }
         else
         {
@@ -884,7 +738,6 @@ int TABMAPFile::LoadNextMatchingObjectBlock( int bFirstObject )
         m_poSpIndexLeaf->SetCurChildRef( NULL, ++iEntry );
 
         TABMAPIndexEntry *psEntry = m_poSpIndexLeaf->GetEntry( iEntry );
-        TABRawBinBlock *poBlock;
 
         if( psEntry->XMax < m_XMinFilter
             || psEntry->YMax < m_YMinFilter
@@ -892,7 +745,7 @@ int TABMAPFile::LoadNextMatchingObjectBlock( int bFirstObject )
             || psEntry->YMin > m_YMaxFilter )
             continue;
 
-        poBlock = PushBlock( psEntry->nBlockPtr );
+        TABRawBinBlock *poBlock = PushBlock( psEntry->nBlockPtr );
         if( poBlock == NULL )
             return FALSE;
         else if( poBlock->GetBlockType() == TABMAP_OBJECT_BLOCK )
@@ -1026,9 +879,9 @@ int TABMAPFile::GetNextFeatureId( int nPrevId )
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPFile::Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY)
+int TABMAPFile::Int2Coordsys( GInt32 nX, GInt32 nY, double &dX, double &dY )
 {
-    if (m_poHeader == NULL)
+    if( m_poHeader == NULL )
         return -1;
 
     return m_poHeader->Int2Coordsys(nX, nY, dX, dY);
@@ -1045,10 +898,10 @@ int TABMAPFile::Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPFile::Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY,
-                             GBool bIgnoreOverflow/*=FALSE*/)
+int TABMAPFile::Coordsys2Int( double dX, double dY, GInt32 &nX, GInt32 &nY,
+                              GBool bIgnoreOverflow/*=FALSE*/ )
 {
-    if (m_poHeader == NULL)
+    if( m_poHeader == NULL )
         return -1;
 
     return m_poHeader->Coordsys2Int(dX, dY, nX, nY, bIgnoreOverflow);
@@ -1069,9 +922,9 @@ int TABMAPFile::Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPFile::Int2CoordsysDist(GInt32 nX, GInt32 nY, double &dX, double &dY)
+int TABMAPFile::Int2CoordsysDist( GInt32 nX, GInt32 nY, double &dX, double &dY )
 {
-    if (m_poHeader == NULL)
+    if( m_poHeader == NULL )
         return -1;
 
     return m_poHeader->Int2CoordsysDist(nX, nY, dX, dY);
@@ -1092,7 +945,7 @@ int TABMAPFile::Int2CoordsysDist(GInt32 nX, GInt32 nY, double &dX, double &dY)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPFile::Coordsys2IntDist(double dX, double dY, GInt32 &nX, GInt32 &nY)
+int TABMAPFile::Coordsys2IntDist( double dX, double dY, GInt32 &nX, GInt32 &nY )
 {
     if (m_poHeader == NULL)
         return -1;
@@ -1110,15 +963,14 @@ int TABMAPFile::Coordsys2IntDist(double dX, double dY, GInt32 &nX, GInt32 &nY)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPFile::SetCoordsysBounds(double dXMin, double dYMin,
-                                  double dXMax, double dYMax)
+int TABMAPFile::SetCoordsysBounds( double dXMin, double dYMin,
+                                   double dXMax, double dYMax )
 {
-    int nStatus = 0;
-
     if (m_poHeader == NULL)
         return -1;
 
-    nStatus = m_poHeader->SetCoordsysBounds(dXMin, dYMin, dXMax, dYMax);
+    const int nStatus =
+        m_poHeader->SetCoordsysBounds(dXMin, dYMin, dXMax, dYMax);
 
     if (nStatus == 0)
         ResetCoordFilter();
@@ -1157,10 +1009,8 @@ GInt32 TABMAPFile::GetMaxObjId()
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int   TABMAPFile::MoveToObjId(int nObjId)
+int TABMAPFile::MoveToObjId(int nObjId)
 {
-    int nFileOffset;
-
     if( m_bLastOpWasWrite )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -1193,7 +1043,8 @@ int   TABMAPFile::MoveToObjId(int nObjId)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
                  "MoveToObjId(): file not opened!");
-        m_nCurObjPtr = m_nCurObjId = -1;
+        m_nCurObjPtr = -1;
+        m_nCurObjId = -1;
         m_nCurObjType = TAB_GEOM_UNSET;
         return -1;
     }
@@ -1202,16 +1053,16 @@ int   TABMAPFile::MoveToObjId(int nObjId)
      * Move map object pointer to the right location.  Fetch location
      * from the index file, unless we are already pointing at it.
      *----------------------------------------------------------------*/
-    if( m_nCurObjId == nObjId )
-        nFileOffset = m_nCurObjPtr;
-    else
-        nFileOffset = m_poIdIndex->GetObjPtr(nObjId);
+    int nFileOffset = m_nCurObjId == nObjId
+        ? m_nCurObjPtr
+        : m_poIdIndex->GetObjPtr(nObjId);
 
     if (nFileOffset != 0 && m_poCurObjBlock == NULL)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
                  "MoveToObjId(): no current object block!");
-        m_nCurObjPtr = m_nCurObjId = -1;
+        m_nCurObjPtr = -1;
+        m_nCurObjId = -1;
         m_nCurObjType = TAB_GEOM_UNSET;
         return -1;
     }
@@ -1251,7 +1102,8 @@ int   TABMAPFile::MoveToObjId(int nObjId)
                     "in the .MAP file (%d).  File may be corrupt.",
                     nObjId, m_nCurObjId);
             }
-            m_nCurObjPtr = m_nCurObjId = -1;
+            m_nCurObjPtr = -1;
+            m_nCurObjId = -1;
             m_nCurObjType = TAB_GEOM_UNSET;
             return -1;
         }
@@ -1261,7 +1113,8 @@ int   TABMAPFile::MoveToObjId(int nObjId)
         /*---------------------------------------------------------
          * Failed positioning input file... CPLError has been called.
          *--------------------------------------------------------*/
-        m_nCurObjPtr = m_nCurObjId = -1;
+        m_nCurObjPtr = -1;
+        m_nCurObjId = -1;
         m_nCurObjType = TAB_GEOM_UNSET;
         return -1;
     }
@@ -1269,7 +1122,6 @@ int   TABMAPFile::MoveToObjId(int nObjId)
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPFile::MarkAsDeleted()
  *
@@ -1298,14 +1150,14 @@ int TABMAPFile::MarkAsDeleted()
     if( m_poIdIndex->SetObjPtr(m_nCurObjId, 0) != 0 )
         ret = -1;
 
-    m_nCurObjPtr = m_nCurObjId = -1;
+    m_nCurObjPtr = -1;
+    m_nCurObjId = -1;
     m_nCurObjType = TAB_GEOM_UNSET;
     m_bUpdated = TRUE;
 
     return ret;
 }
 
-
 /**********************************************************************
  *                   TABMAPFile::UpdateMapHeaderInfo()
  *
@@ -1377,7 +1229,6 @@ void  TABMAPFile::UpdateMapHeaderInfo(TABGeomType nObjType)
     {
         m_nMinTABVersion = nVersion;
     }
-
 }
 
 /**********************************************************************
@@ -1412,9 +1263,10 @@ void  TABMAPFile::UpdateMapHeaderInfo(TABGeomType nObjType)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int   TABMAPFile::PrepareNewObj(TABMAPObjHdr *poObjHdr)
+int TABMAPFile::PrepareNewObj( TABMAPObjHdr *poObjHdr )
 {
-    m_nCurObjPtr = m_nCurObjId = -1;
+    m_nCurObjPtr = -1;
+    m_nCurObjId = -1;
     m_nCurObjType = TAB_GEOM_UNSET;
 
     if (m_eAccessMode == TABRead ||
@@ -1453,7 +1305,6 @@ int   TABMAPFile::PrepareNewObj(TABMAPObjHdr *poObjHdr)
      *----------------------------------------------------------------*/
     UpdateMapHeaderInfo(poObjHdr->m_nType);
 
-
     /*-----------------------------------------------------------------
      * Depending on the selected spatial index mode, we will either insert
      * new objects via the spatial index (slower write but results in optimal
@@ -1523,7 +1374,6 @@ int   TABMAPFile::PrepareNewObj(TABMAPObjHdr *poObjHdr)
  **********************************************************************/
 int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
 {
-    int nObjSize;
     GInt32 nObjBlockForInsert = -1;
 
     /*-----------------------------------------------------------------
@@ -1564,7 +1414,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         m_poHeader->m_nFirstIndexBlock = m_poSpIndex->GetNodeBlockPtr();
 
         /* We'll also need to create an object data block (later) */
-        nObjBlockForInsert = -1;
+        // nObjBlockForInsert = -1;
 
         CPLAssert(m_poCurObjBlock == NULL);
     }
@@ -1578,7 +1428,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
                                                             poObjHdr->m_nMinY,
                                                             poObjHdr->m_nMaxX,
                                                             poObjHdr->m_nMaxY);
-        if (nObjBlockForInsert == -1)
+        if( nObjBlockForInsert == -1 )
         {
             /* ChooseLeafForInsert() should not fail unless file is corrupt*/
             CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1587,8 +1437,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         }
     }
 
-
-    if (nObjBlockForInsert == -1)
+    if( nObjBlockForInsert == -1 )
     {
         /*-------------------------------------------------------------
          * Create a new object data block from scratch
@@ -1612,8 +1461,9 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         m_poCurObjBlock->SetMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
                                 poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
 
-        m_poHeader->m_nMaxSpIndexDepth = MAX(m_poHeader->m_nMaxSpIndexDepth,
-                                      (GByte)m_poSpIndex->GetCurMaxDepth()+1);
+        const int nNextDepth = m_poSpIndex->GetCurMaxDepth() + 1;
+        m_poHeader->m_nMaxSpIndexDepth = static_cast<GByte>(
+            std::max(static_cast<int>(m_poHeader->m_nMaxSpIndexDepth), nNextDepth));
     }
     else
     {
@@ -1655,8 +1505,7 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
      * Fetch new object size, make sure there is enough room in obj.
      * block for new object, update spatial index and split if necessary.
      *----------------------------------------------------------------*/
-    nObjSize = m_poHeader->GetMapObjectSize(poObjHdr->m_nType);
-
+    int nObjSize = m_poHeader->GetMapObjectSize(poObjHdr->m_nType);
 
     /*-----------------------------------------------------------------
      * But first check if we can recover space from this block in case
@@ -1743,10 +1592,10 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         m_poCurObjBlock->GetMBR(nMinX, nMinY, nMaxX, nMaxY);
 
         /* Need to calculate the enlarged MBR that includes new object */
-        nMinX = MIN(nMinX, poObjHdr->m_nMinX);
-        nMinY = MIN(nMinY, poObjHdr->m_nMinY);
-        nMaxX = MAX(nMaxX, poObjHdr->m_nMaxX);
-        nMaxY = MAX(nMaxY, poObjHdr->m_nMaxY);
+        nMinX = std::min(nMinX, poObjHdr->m_nMinX);
+        nMinY = std::min(nMinY, poObjHdr->m_nMinY);
+        nMaxX = std::max(nMaxX, poObjHdr->m_nMaxX);
+        nMaxY = std::max(nMaxY, poObjHdr->m_nMaxY);
 
         m_poCurObjBlock->SetMBR(nMinX, nMinY, nMaxX, nMaxY);
 
@@ -1775,15 +1624,18 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
          * This is important since UpdateLeafEntry() needs the chain of
          * index nodes preloaded by ChooseLeafEntry() in order to do its job
          *------------------------------------------------------------*/
-        GInt32 nMinX, nMinY, nMaxX, nMaxY;
+        GInt32 nMinX = 0;
+        GInt32 nMinY = 0;
+        GInt32 nMaxX = 0;
+        GInt32 nMaxY = 0;
         m_poCurObjBlock->GetMBR(nMinX, nMinY, nMaxX, nMaxY);
         CPLAssert(nMinX <= nMaxX);
 
         /* Need to calculate the enlarged MBR that includes new object */
-        nMinX = MIN(nMinX, poObjHdr->m_nMinX);
-        nMinY = MIN(nMinY, poObjHdr->m_nMinY);
-        nMaxX = MAX(nMaxX, poObjHdr->m_nMaxX);
-        nMaxY = MAX(nMaxY, poObjHdr->m_nMaxY);
+        nMinX = std::min(nMinX, poObjHdr->m_nMinX);
+        nMinY = std::min(nMinY, poObjHdr->m_nMinY);
+        nMaxX = std::max(nMaxX, poObjHdr->m_nMaxX);
+        nMaxY = std::max(nMaxY, poObjHdr->m_nMaxY);
 
         m_poCurObjBlock->SetMBR(nMinX, nMinY, nMaxX, nMaxY);
 
@@ -1800,8 +1652,9 @@ int   TABMAPFile::PrepareNewObjViaSpatialIndex(TABMAPObjHdr *poObjHdr)
         if (m_poSpIndex->AddEntry(nMinX, nMinY, nMaxX, nMaxY,
                                   poNewObjBlock->GetStartAddress()) != 0)
             return -1;
-        m_poHeader->m_nMaxSpIndexDepth = MAX(m_poHeader->m_nMaxSpIndexDepth,
-                                      (GByte)m_poSpIndex->GetCurMaxDepth()+1);
+        const int nNextDepth = m_poSpIndex->GetCurMaxDepth() + 1;
+        m_poHeader->m_nMaxSpIndexDepth = static_cast<GByte>(
+            std::max(static_cast<int>(m_poHeader->m_nMaxSpIndexDepth), nNextDepth));
 
         /*-------------------------------------------------------------
          * Delete second object block, no need to commit to file first since
@@ -1878,7 +1731,6 @@ int   TABMAPFile::PrepareNewObjViaObjBlock(TABMAPObjHdr *poObjHdr)
             delete m_poCurCoordBlock;
             m_poCurCoordBlock = NULL;
         }
-
     }
 
     return 0;
@@ -1915,7 +1767,6 @@ int   TABMAPFile::CommitNewObj(TABMAPObjHdr *poObjHdr)
     return m_poCurObjBlock->CommitNewObject(poObjHdr);
 }
 
-
 /**********************************************************************
  *                   TABMAPFile::CommitObjAndCoordBlocks()
  *
@@ -1989,7 +1840,6 @@ int TABMAPFile::CommitObjAndCoordBlocks(GBool bDeleteObjects /*=FALSE*/)
         nStatus = m_poCurObjBlock->CommitToFile();
     }
 
-
     /*-----------------------------------------------------------------
      * Update the spatial index ** only in "quick spatial index" mode **
      * In the (default) optimized spatial index mode, the spatial index
@@ -2017,8 +1867,9 @@ int TABMAPFile::CommitObjAndCoordBlocks(GBool bDeleteObjects /*=FALSE*/)
         nStatus = m_poSpIndex->AddEntry(nXMin, nYMin, nXMax, nYMax,
                                         m_poCurObjBlock->GetStartAddress());
 
-        m_poHeader->m_nMaxSpIndexDepth = MAX(m_poHeader->m_nMaxSpIndexDepth,
-                                      (GByte)m_poSpIndex->GetCurMaxDepth()+1);
+        const int nNextDepth = m_poSpIndex->GetCurMaxDepth() + 1;
+        m_poHeader->m_nMaxSpIndexDepth = static_cast<GByte>(
+            std::max(static_cast<int>(m_poHeader->m_nMaxSpIndexDepth), nNextDepth));
     }
 
     /*-----------------------------------------------------------------
@@ -2124,8 +1975,10 @@ int TABMAPFile::LoadObjAndCoordBlocks(GInt32 nBlockPtr)
 TABMAPObjectBlock *TABMAPFile::SplitObjBlock(TABMAPObjHdr *poObjHdrToAdd,
                                              int nSizeOfObjToAdd)
 {
-    TABMAPObjHdr **papoSrcObjHdrs = NULL, *poObjHdr=NULL;
-    int i, numSrcObj = 0;
+    TABMAPObjHdr **papoSrcObjHdrs = NULL;
+    TABMAPObjHdr *poObjHdr=NULL;
+    int i;
+    int numSrcObj = 0;
 
     /*-----------------------------------------------------------------
      * Read all object headers
@@ -2396,7 +2249,6 @@ int TABMAPFile::MoveObjToBlock(TABMAPObjHdr       *poObjHdr,
         TABFeature *poFeature =
             TABFeature::CreateFromMapInfoType(poObjHdr->m_nType, poDummyDefn);
 
-
         if (PrepareCoordBlock(poObjHdrCoord->m_nType,
                               poDstObjBlock, ppoDstCoordBlock) != 0)
             return -1;
@@ -2421,7 +2273,6 @@ int TABMAPFile::MoveObjToBlock(TABMAPObjHdr       *poObjHdr,
             return -1;
         }
 
-
         // Update the references to dest coord block in the MAPObjBlock
         // in case new block has been alloc'd since PrepareCoordBlock()
         //
@@ -2692,7 +2543,7 @@ TABRawBinBlock *TABMAPFile::GetIndexObjectBlock( int nFileOffset )
 /*      Create and initialize depending on the block type.              */
 /* -------------------------------------------------------------------- */
     int nBlockType = pabyData[0];
-    TABRawBinBlock *poBlock;
+    TABRawBinBlock *poBlock = NULL;
 
     if( nBlockType == TABMAP_INDEX_BLOCK )
     {
@@ -2744,9 +2595,7 @@ int TABMAPFile::InitDrawingTools()
     if ((m_eAccessMode == TABRead || m_eAccessMode == TABReadWrite) &&
         m_poHeader->m_nFirstToolBlock != 0)
     {
-        TABMAPToolBlock *poBlock;
-
-        poBlock = new TABMAPToolBlock(TABRead);
+        TABMAPToolBlock *poBlock = new TABMAPToolBlock(TABRead);
         poBlock->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize);
 
         /*-------------------------------------------------------------
@@ -2771,7 +2620,6 @@ int TABMAPFile::InitDrawingTools()
     return nStatus;
 }
 
-
 /**********************************************************************
  *                   TABMAPFile::CommitDrawingTools()
  *
@@ -2804,9 +2652,7 @@ int TABMAPFile::CommitDrawingTools()
     /*-------------------------------------------------------------
      * Create a new TABMAPToolBlock and update header fields
      *------------------------------------------------------------*/
-    TABMAPToolBlock *poBlock;
-
-    poBlock = new TABMAPToolBlock(m_eAccessMode);
+    TABMAPToolBlock *poBlock = new TABMAPToolBlock(m_eAccessMode);
     if( m_poHeader->m_nFirstToolBlock != 0 )
         poBlock->InitNewBlock(m_fp, m_poHeader->m_nRegularBlockSize, m_poHeader->m_nFirstToolBlock);
     else
@@ -2834,7 +2680,6 @@ int TABMAPFile::CommitDrawingTools()
     return nStatus;
 }
 
-
 /**********************************************************************
  *                   TABMAPFile::ReadPenDef()
  *
@@ -2847,11 +2692,10 @@ int TABMAPFile::CommitDrawingTools()
  **********************************************************************/
 int   TABMAPFile::ReadPenDef(int nPenIndex, TABPenDef *psDef)
 {
-    TABPenDef *psTmp;
-
     if (m_poToolDefTable == NULL && InitDrawingTools() != 0)
         return -1;
 
+    TABPenDef *psTmp = NULL;
     if (psDef && m_poToolDefTable &&
         (psTmp = m_poToolDefTable->GetPenDefRef(nPenIndex)) != NULL)
     {
@@ -2891,7 +2735,6 @@ int   TABMAPFile::WritePenDef(TABPenDef *psDef)
     return m_poToolDefTable->AddPenDefRef(psDef);
 }
 
-
 /**********************************************************************
  *                   TABMAPFile::ReadBrushDef()
  *
@@ -2904,11 +2747,10 @@ int   TABMAPFile::WritePenDef(TABPenDef *psDef)
  **********************************************************************/
 int   TABMAPFile::ReadBrushDef(int nBrushIndex, TABBrushDef *psDef)
 {
-    TABBrushDef *psTmp;
-
     if (m_poToolDefTable == NULL && InitDrawingTools() != 0)
         return -1;
 
+    TABBrushDef *psTmp = NULL;
     if (psDef && m_poToolDefTable &&
         (psTmp = m_poToolDefTable->GetBrushDefRef(nBrushIndex)) != NULL)
     {
@@ -2948,7 +2790,6 @@ int   TABMAPFile::WriteBrushDef(TABBrushDef *psDef)
     return m_poToolDefTable->AddBrushDefRef(psDef);
 }
 
-
 /**********************************************************************
  *                   TABMAPFile::ReadFontDef()
  *
@@ -2961,11 +2802,10 @@ int   TABMAPFile::WriteBrushDef(TABBrushDef *psDef)
  **********************************************************************/
 int   TABMAPFile::ReadFontDef(int nFontIndex, TABFontDef *psDef)
 {
-    TABFontDef *psTmp;
-
     if (m_poToolDefTable == NULL && InitDrawingTools() != 0)
         return -1;
 
+    TABFontDef *psTmp = NULL;
     if (psDef && m_poToolDefTable &&
         (psTmp = m_poToolDefTable->GetFontDefRef(nFontIndex)) != NULL)
     {
@@ -3017,11 +2857,10 @@ int   TABMAPFile::WriteFontDef(TABFontDef *psDef)
  **********************************************************************/
 int   TABMAPFile::ReadSymbolDef(int nSymbolIndex, TABSymbolDef *psDef)
 {
-    TABSymbolDef *psTmp;
-
     if (m_poToolDefTable == NULL && InitDrawingTools() != 0)
         return -1;
 
+    TABSymbolDef *psTmp = NULL;
     if (psDef && m_poToolDefTable &&
         (psTmp = m_poToolDefTable->GetSymbolDefRef(nSymbolIndex)) != NULL)
     {
@@ -3061,9 +2900,17 @@ int   TABMAPFile::WriteSymbolDef(TABSymbolDef *psDef)
     return m_poToolDefTable->AddSymbolDefRef(psDef);
 }
 
-#define ORDER_MIN_MAX(type,min,max)                                    \
-    {   if( (max) < (min) )                                            \
-          { type temp = (max); (max) = (min); (min) = temp; } }
+static void ORDER_MIN_MAX( double &min, double &max )
+{
+    if( max < min )
+      std::swap(min, max);
+}
+
+static void ORDER_MIN_MAX( int &min, int &max )
+{
+    if( max < min )
+      std::swap(min, max);
+}
 
 /**********************************************************************
  *                   TABMAPFile::SetCoordFilter()
@@ -3082,10 +2929,10 @@ void TABMAPFile::SetCoordFilter(TABVertex sMin, TABVertex sMax)
     Coordsys2Int(sMin.x, sMin.y, m_XMinFilter, m_YMinFilter, TRUE);
     Coordsys2Int(sMax.x, sMax.y, m_XMaxFilter, m_YMaxFilter, TRUE);
 
-    ORDER_MIN_MAX(int,m_XMinFilter,m_XMaxFilter);
-    ORDER_MIN_MAX(int,m_YMinFilter,m_YMaxFilter);
-    ORDER_MIN_MAX(double,m_sMinFilter.x,m_sMaxFilter.x);
-    ORDER_MIN_MAX(double,m_sMinFilter.y,m_sMaxFilter.y);
+    ORDER_MIN_MAX(m_XMinFilter, m_XMaxFilter);
+    ORDER_MIN_MAX(m_YMinFilter, m_YMaxFilter);
+    ORDER_MIN_MAX(m_sMinFilter.x, m_sMaxFilter.x);
+    ORDER_MIN_MAX(m_sMinFilter.y, m_sMaxFilter.y);
 }
 
 /**********************************************************************
@@ -3107,10 +2954,10 @@ void TABMAPFile::ResetCoordFilter()
     Int2Coordsys(m_XMaxFilter, m_YMaxFilter,
                  m_sMaxFilter.x, m_sMaxFilter.y);
 
-    ORDER_MIN_MAX(int,m_XMinFilter,m_XMaxFilter);
-    ORDER_MIN_MAX(int,m_YMinFilter,m_YMaxFilter);
-    ORDER_MIN_MAX(double,m_sMinFilter.x,m_sMaxFilter.x);
-    ORDER_MIN_MAX(double,m_sMinFilter.y,m_sMaxFilter.y);
+    ORDER_MIN_MAX(m_XMinFilter, m_XMaxFilter);
+    ORDER_MIN_MAX(m_YMinFilter, m_YMaxFilter);
+    ORDER_MIN_MAX(m_sMinFilter. x,m_sMaxFilter.x);
+    ORDER_MIN_MAX(m_sMinFilter. y,m_sMaxFilter.y);
 }
 
 /**********************************************************************
@@ -3156,8 +3003,9 @@ int TABMAPFile::CommitSpatialIndex()
      * (it's children will be recursively committed as well)
      *------------------------------------------------------------*/
     // Add 1 to Spatial Index Depth to account to the MapObjectBlocks
-    m_poHeader->m_nMaxSpIndexDepth = MAX(m_poHeader->m_nMaxSpIndexDepth,
-                                  (GByte)m_poSpIndex->GetCurMaxDepth()+1);
+    const int nNextDepth = m_poSpIndex->GetCurMaxDepth() + 1;
+    m_poHeader->m_nMaxSpIndexDepth = static_cast<GByte>(
+        std::max(static_cast<int>(m_poHeader->m_nMaxSpIndexDepth), nNextDepth));
 
     m_poSpIndex->GetMBR(m_poHeader->m_nXMin, m_poHeader->m_nYMin,
                         m_poHeader->m_nXMax, m_poHeader->m_nYMax);
@@ -3165,7 +3013,6 @@ int TABMAPFile::CommitSpatialIndex()
     return m_poSpIndex->CommitToFile();
 }
 
-
 /**********************************************************************
  *                   TABMAPFile::GetMinTABFileVersion()
  *
@@ -3179,10 +3026,9 @@ int   TABMAPFile::GetMinTABFileVersion()
     if (m_poToolDefTable)
         nToolVersion = m_poToolDefTable->GetMinVersionNumber();
 
-    return MAX(nToolVersion, m_nMinTABVersion);
+    return std::max(nToolVersion, m_nMinTABVersion);
 }
 
-
 /**********************************************************************
  *                   TABMAPFile::Dump()
  *
@@ -3223,7 +3069,6 @@ void TABMAPFile::Dump(FILE *fpOut /*=NULL*/)
 
 #endif // DEBUG
 
-
 /**********************************************************************
  *                   TABMAPFile::DumpSpatialIndexToMIF()
  *
@@ -3242,9 +3087,8 @@ void TABMAPFile::DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode,
     {
         if (m_poHeader && m_poHeader->m_nFirstIndexBlock != 0)
         {
-            TABRawBinBlock *poBlock;
-
-            poBlock = GetIndexObjectBlock(m_poHeader->m_nFirstIndexBlock);
+            TABRawBinBlock *poBlock =
+                GetIndexObjectBlock(m_poHeader->m_nFirstIndexBlock);
             if (poBlock && poBlock->GetBlockType() == TABMAP_INDEX_BLOCK)
                 poNode = (TABMAPIndexBlock *)poBlock;
         }
@@ -3253,17 +3097,22 @@ void TABMAPFile::DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode,
             return;
     }
 
-
     /*-------------------------------------------------------------
      * Report info on current tree node
      *------------------------------------------------------------*/
-    int numEntries = poNode->GetNumEntries();
-    GInt32 nXMin, nYMin, nXMax, nYMax;
-    double dXMin, dYMin, dXMax, dYMax;
+    const int numEntries = poNode->GetNumEntries();
+    GInt32 nXMin = 0;
+    GInt32 nYMin = 0;
+    GInt32 nXMax = 0;
+    GInt32 nYMax = 0;
 
     poNode->RecomputeMBR();
     poNode->GetMBR(nXMin, nYMin, nXMax, nYMax);
 
+    double dXMin = 0.0;
+    double dYMin = 0.0;
+    double dXMax = 0.0;
+    double dYMax = 0.0;
     Int2Coordsys(nXMin, nYMin, dXMin, dYMin);
     Int2Coordsys(nXMax, nYMax, dXMax, dYMax);
 
@@ -3287,8 +3136,7 @@ void TABMAPFile::DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode,
         {
             TABMAPIndexEntry *psEntry = poNode->GetEntry(i);
 
-            TABRawBinBlock *poBlock;
-            poBlock = GetIndexObjectBlock( psEntry->nBlockPtr );
+            TABRawBinBlock *poBlock = GetIndexObjectBlock( psEntry->nBlockPtr );
             if( poBlock == NULL )
                 continue;
 
@@ -3324,9 +3172,7 @@ void TABMAPFile::DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode,
 
             delete poBlock;
         }
-
     }
-
 }
 
 #endif // DEBUG
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp
index 7b3e15b..e7a0a5d 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapheaderblock.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_mapheaderblock.cpp,v 1.33 2008-02-01 19:36:31 dmorissette Exp $
  *
  * Name:     mitab_mapheaderblock.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,116 +28,21 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_mapheaderblock.cpp,v $
- * Revision 1.33  2008-02-01 19:36:31  dmorissette
- * Initial support for V800 REGION and MULTIPLINE (bug 1496)
- *
- * Revision 1.32  2006/11/28 18:49:08  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.31  2005/09/29 20:16:54  dmorissette
- *  Support for writing affine projection params in .MAP header (AJD, bug 1155)
- *
- * Revision 1.30  2005/05/12 20:46:15  dmorissette
- * Initialize m_sProj.nDatumId in InitNewBlock(). (hss/geh)
- *
- * Revision 1.29  2005/03/22 23:24:54  dmorissette
- * Added support for datum id in .MAP header (bug 910)
- *
- * Revision 1.28  2004/12/15 22:52:49  dmorissette
- * Revert back to using doubles for range check in CoordSys2Int(). Hopefully
- * I got it right this time. (bug 894)
- *
- * Revision 1.27  2004/12/08 23:27:35  dmorissette
- * Fixed coordinates rounding error in Coordsys2Int() (bug 894)
- *
- * Revision 1.26  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.25  2003/08/12 23:17:21  dmorissette
- * Added reading of v500+ coordsys affine params (Anthony D. - Encom)
- *
- * Revision 1.24  2002/06/28 18:32:37  julien
- * Add SetSpatialFilter() in TABSeamless class (Bug 164, MapServer)
- * Use double for comparison in Coordsys2Int() in mitab_mapheaderblock.cpp
- *
- * Revision 1.23  2002/04/25 16:05:24  julien
- * Disabled the overflow warning in SetCoordFilter() by adding bIgnoreOverflow
- * variable in Coordsys2Int of the TABMAPFile class and TABMAPHeaderBlock class
- *
- * Revision 1.22  2002/03/26 01:48:40  daniel
- * Added Multipoint object type (V650)
- *
- * Revision 1.21  2001/12/05 22:23:06  daniel
- * Can't use rint() on Windows... replace rint() with (int)(val+0.5)
- *
- * Revision 1.20  2001/12/05 21:56:15  daniel
- * Mod. CoordSys2Int() to use rint() for double to integer coord. conversion.
- *
- * Revision 1.19  2001/11/19 15:05:42  daniel
- * Prevent writing of coordinates outside of the +/-1e9 integer bounds.
- *
- * Revision 1.18  2000/12/07 03:58:20  daniel
- * Pass first arg of pow() as double
- *
- * Revision 1.17  2000/09/19 19:35:53  daniel
- * Set default scale/displacement when reading V100 headers
- *
- * Revision 1.16  2000/07/10 14:56:52  daniel
- * Handle m_nOriginQuadrant==0 as quadrant 3 (reverse x and y axis)
- *
- * Revision 1.15  2000/03/13 05:59:25  daniel
- * Switch from V400 to V500 .MAP header (1024 bytes)
- *
- * Revision 1.14  2000/02/28 17:01:05  daniel
- * Use a #define for header version number
- *
- * Revision 1.13  2000/02/07 18:09:10  daniel
- * OOpppps ... test on version number was reversed!
- *
- * Revision 1.12  2000/02/07 17:41:02  daniel
- * Ignore the values of 5 last datum params in version=200 headers
- *
- * Revision 1.11  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.10  2000/01/15 05:37:47  daniel
- * Use a #define for default quadrant value in new files
- *
- * Revision 1.9  1999/10/19 16:27:10  warmerda
- * Default unitsid to 7 (meters) instead of 0 (miles).
- *
- * Revision 1.8  1999/10/19 06:05:35  daniel
- * Removed obsolete code segments in the coord. conversion functions.
- *
- * Revision 1.7  1999/10/06 13:21:37  daniel
- * Reworked int<->coordsys coords. conversion... hopefully it's OK this time!
- *
- * Revision 1.6  1999/10/01 03:47:38  daniel
- * Better defaults for header fields, and more complete Dump() for debugging
- *
- * Revision 1.5  1999/09/29 04:25:03  daniel
- * Set default scale so that default coord range is +/-1000000.000
- *
- * Revision 1.4  1999/09/26 14:59:36  daniel
- * Implemented write support
- *
- * Revision 1.3  1999/09/21 03:36:33  warmerda
- * slight modification to dump precision
- *
- * Revision 1.2  1999/09/16 02:39:16  daniel
- * Completed read support for most feature types
- *
- * Revision 1.1  1999/07/12 04:18:24  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
 
+#include <cmath>
+#include <cstddef>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
+
+CPL_CVSID("$Id: mitab_mapheaderblock.cpp 37351 2017-02-12 05:22:20Z goatbar $");
+
 #ifdef WIN32
 inline double round(double r) {
     return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
@@ -148,17 +52,17 @@ inline double round(double r) {
 /*---------------------------------------------------------------------
  * Set various constants used in generating the header block.
  *--------------------------------------------------------------------*/
-#define HDR_MAGIC_COOKIE        42424242
-#define HDR_VERSION_NUMBER      500
+static const GInt32 HDR_MAGIC_COOKIE = 42424242;
+static const GInt16 HDR_VERSION_NUMBER = 500;
 
-#define HDR_DEF_ORG_QUADRANT    1       // N-E Quadrant
-#define HDR_DEF_REFLECTXAXIS    0
+static const GByte HDR_DEF_ORG_QUADRANT = 1;  // N-E Quadrant
+static const GByte HDR_DEF_REFLECTXAXIS = 0;
 
 /*---------------------------------------------------------------------
  * The header block starts with an array of map object length constants.
  *--------------------------------------------------------------------*/
-#define HDR_OBJ_LEN_ARRAY_SIZE   73
-static const GByte  gabyObjLenArray[ HDR_OBJ_LEN_ARRAY_SIZE  ] = {
+static const GByte HDR_OBJ_LEN_ARRAY_SIZE = 73;
+static const GByte gabyObjLenArray[ HDR_OBJ_LEN_ARRAY_SIZE  ] = {
             0x00,0x0a,0x0e,0x15,0x0e,0x16,0x1b,0xa2,
             0xa6,0xab,0x1a,0x2a,0x2f,0xa5,0xa9,0xb5,
             0xa7,0xb5,0xd9,0x0f,0x17,0x23,0x13,0x1f,
@@ -170,24 +74,22 @@ static const GByte  gabyObjLenArray[ HDR_OBJ_LEN_ARRAY_SIZE  ] = {
             0xc7,0xcb,0xd0,0xd3,0xd7,0xfd,0xc2,0xc2,
             0xf9};
 
-
-
 /*=====================================================================
  *                      class TABMAPHeaderBlock
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABMAPHeaderBlock::TABMAPHeaderBlock()
  *
  * Constructor.
  **********************************************************************/
-TABMAPHeaderBlock::TABMAPHeaderBlock(TABAccess eAccessMode /*= TABRead*/):
+TABMAPHeaderBlock::TABMAPHeaderBlock( TABAccess eAccessMode /*= TABRead*/ ):
     TABRawBinBlock(eAccessMode, TRUE)
 {
+    // TODO(schwehr): Consider using initializer list for most values.
     InitMembersWithDefaultValues();
 
-    /* We don't want to reset it once it is set */
+    // We don't want to reset it once it is set.
     m_bIntBoundsOverflow = FALSE;
 }
 
@@ -196,18 +98,13 @@ TABMAPHeaderBlock::TABMAPHeaderBlock(TABAccess eAccessMode /*= TABRead*/):
  *
  * Destructor.
  **********************************************************************/
-TABMAPHeaderBlock::~TABMAPHeaderBlock()
-{
-
-}
+TABMAPHeaderBlock::~TABMAPHeaderBlock() {}
 
 /**********************************************************************
  *            TABMAPHeaderBlock::InitMembersWithDefaultValues()
  **********************************************************************/
 void TABMAPHeaderBlock::InitMembersWithDefaultValues()
 {
-    int i;
-
     /*-----------------------------------------------------------------
      * Set acceptable default values for member vars.
      *----------------------------------------------------------------*/
@@ -254,13 +151,13 @@ void TABMAPHeaderBlock::InitMembersWithDefaultValues()
     m_XPrecision = 0.0;  // not specified
     m_YPrecision = 0.0;  // not specified
 
-    for(i=0; i<6; i++)
+    for( int i = 0; i<6; i++ )
         m_sProj.adProjParams[i] = 0.0;
 
     m_sProj.dDatumShiftX = 0.0;
     m_sProj.dDatumShiftY = 0.0;
     m_sProj.dDatumShiftZ = 0.0;
-    for(i=0; i<5; i++)
+    for( int i = 0; i < 5; i++ )
         m_sProj.adDatumParams[i] = 0.0;
 
     m_sProj.nAffineFlag = 0;    // Only in version 500 and up
@@ -273,7 +170,6 @@ void TABMAPHeaderBlock::InitMembersWithDefaultValues()
     m_sProj.dAffineParamF = 0.0;
 }
 
-
 /**********************************************************************
  *                   TABMAPHeaderBlock::InitBlockFromData()
  *
@@ -289,16 +185,14 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
                                              VSILFILE *fpSrc /* = NULL */,
                                              int nOffset /* = 0 */)
 {
-    int i, nStatus;
-    GInt32 nMagicCookie;
-
     /*-----------------------------------------------------------------
      * First of all, we must call the base class' InitBlockFromData()
      *----------------------------------------------------------------*/
-    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf,
-                                                nBlockSize, nSizeUsed,
-                                                bMakeCopy,
-                                                fpSrc, nOffset);
+    const int nStatus =
+        TABRawBinBlock::InitBlockFromData(pabyBuf,
+                                          nBlockSize, nSizeUsed,
+                                          bMakeCopy,
+                                          fpSrc, nOffset);
     if (nStatus != 0)
         return nStatus;
 
@@ -307,7 +201,7 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
      * Header blocks have a magic cookie at byte 0x100
      *----------------------------------------------------------------*/
     GotoByteInBlock(0x100);
-    nMagicCookie = ReadInt32();
+    const GInt32 nMagicCookie = ReadInt32();
     if (nMagicCookie != HDR_MAGIC_COOKIE)
     {
         CPLError(CE_Failure, CPLE_FileIO,
@@ -397,17 +291,19 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
      */
     if (m_nMAPVersionNumber <= 100)
     {
-        m_XScale = m_YScale = pow(10.0, m_nCoordPrecision);
-        m_XDispl = m_YDispl = 0.0;
+        m_XScale = pow(10.0, m_nCoordPrecision);
+        m_YScale = m_XScale;
+        m_XDispl = 0.0;
+        m_YDispl = 0.0;
     }
 
-    for(i=0; i<6; i++)
+    for( int i = 0; i < 6; i++ )
         m_sProj.adProjParams[i] = ReadDouble();
 
     m_sProj.dDatumShiftX = ReadDouble();
     m_sProj.dDatumShiftY = ReadDouble();
     m_sProj.dDatumShiftZ = ReadDouble();
-    for(i=0; i<5; i++)
+    for( int i = 0; i < 5; i++ )
     {
         /* In V.200 files, the next 5 datum params are unused and they
          * sometimes contain junk bytes... in this case we set adDatumParams[]
@@ -443,7 +339,6 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPHeaderBlock::Int2Coordsys()
  *
@@ -455,8 +350,8 @@ int     TABMAPHeaderBlock::InitBlockFromData(GByte *pabyBuf,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::Int2Coordsys(GInt32 nX, GInt32 nY,
-                                    double &dX, double &dY)
+int TABMAPHeaderBlock::Int2Coordsys( GInt32 nX, GInt32 nY,
+                                     double &dX, double &dY )
 {
     if (m_pabyBuf == NULL)
         return -1;
@@ -501,9 +396,9 @@ int TABMAPHeaderBlock::Int2Coordsys(GInt32 nX, GInt32 nY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::Coordsys2Int(double dX, double dY,
-                                    GInt32 &nX, GInt32 &nY,
-                                    GBool bIgnoreOverflow /*=FALSE*/)
+int TABMAPHeaderBlock::Coordsys2Int( double dX, double dY,
+                                     GInt32 &nX, GInt32 &nY,
+                                     GBool bIgnoreOverflow /*=FALSE*/ )
 {
     if (m_pabyBuf == NULL)
         return -1;
@@ -518,7 +413,8 @@ int TABMAPHeaderBlock::Coordsys2Int(double dX, double dY,
      * NOTE: double values must be used here, the limit of integer value
      * have been reached some times due to the very big numbers used here.
      *----------------------------------------------------------------*/
-    double dTempX, dTempY;
+    double dTempX = 0.0;
+    double dTempY = 0.0;
 
     if (m_nCoordOriginQuadrant==2 || m_nCoordOriginQuadrant==3 ||
         m_nCoordOriginQuadrant==0 )
@@ -589,9 +485,9 @@ int TABMAPHeaderBlock::Coordsys2Int(double dX, double dY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY,
-                                         int nDeltaX, int nDeltaY,
-                                         double &dX, double &dY)
+int TABMAPHeaderBlock::ComprInt2Coordsys( GInt32 nCenterX, GInt32 nCenterY,
+                                          int nDeltaX, int nDeltaY,
+                                          double &dX, double &dY )
 {
     if (m_pabyBuf == NULL)
         return -1;
@@ -599,7 +495,6 @@ int TABMAPHeaderBlock::ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY,
     return Int2Coordsys(nCenterX+nDeltaX, nCenterY+nDeltaY, dX, dY);
 }
 
-
 /**********************************************************************
  *                   TABMAPHeaderBlock::Int2CoordsysDist()
  *
@@ -615,8 +510,8 @@ int TABMAPHeaderBlock::ComprInt2Coordsys(GInt32 nCenterX, GInt32 nCenterY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::Int2CoordsysDist(GInt32 nX, GInt32 nY,
-                                    double &dX, double &dY)
+int TABMAPHeaderBlock::Int2CoordsysDist( GInt32 nX, GInt32 nY,
+                                         double &dX, double &dY )
 {
     if (m_pabyBuf == NULL)
         return -1;
@@ -642,8 +537,8 @@ int TABMAPHeaderBlock::Int2CoordsysDist(GInt32 nX, GInt32 nY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::Coordsys2IntDist(double dX, double dY,
-                                        GInt32 &nX, GInt32 &nY)
+int TABMAPHeaderBlock::Coordsys2IntDist( double dX, double dY,
+                                         GInt32 &nX, GInt32 &nY )
 {
     if (m_pabyBuf == NULL)
         return -1;
@@ -654,7 +549,6 @@ int TABMAPHeaderBlock::Coordsys2IntDist(double dX, double dY,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPHeaderBlock::SetCoordsysBounds()
  *
@@ -666,8 +560,8 @@ int TABMAPHeaderBlock::Coordsys2IntDist(double dX, double dY,
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABMAPHeaderBlock::SetCoordsysBounds(double dXMin, double dYMin,
-                                         double dXMax, double dYMax)
+int TABMAPHeaderBlock::SetCoordsysBounds( double dXMin, double dYMin,
+                                          double dXMax, double dYMax )
 {
 //printf("SetCoordsysBounds(%10g, %10g, %10g, %10g)\n", dXMin, dYMin, dXMax, dYMax);
     /*-----------------------------------------------------------------
@@ -733,7 +627,7 @@ int TABMAPHeaderBlock::GetMapObjectSize(int nObjType)
     }
 
     // Byte 0x80 is set for objects that have coordinates inside type 3 blocks
-    return (m_pabyBuf[nObjType] & 0x7f);
+    return m_pabyBuf[nObjType] & 0x7f;
 }
 
 /**********************************************************************
@@ -764,7 +658,6 @@ GBool TABMAPHeaderBlock::MapObjectUsesCoordBlock(int nObjType)
     return ((m_pabyBuf[nObjType] & 0x80) != 0) ? TRUE: FALSE;
 }
 
-
 /**********************************************************************
  *                   TABMAPHeaderBlock::GetProjInfo()
  *
@@ -810,7 +703,6 @@ int  TABMAPHeaderBlock::SetProjInfo(TABProjInfo *psProjInfo)
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPHeaderBlock::CommitToFile()
  *
@@ -826,7 +718,7 @@ int  TABMAPHeaderBlock::SetProjInfo(TABProjInfo *psProjInfo)
  **********************************************************************/
 int     TABMAPHeaderBlock::CommitToFile()
 {
-    int i, nStatus = 0;
+    int i;
 
     if ( m_pabyBuf == NULL || m_nRegularBlockSize == 0 )
     {
@@ -935,15 +827,10 @@ int     TABMAPHeaderBlock::CommitToFile()
     /*-----------------------------------------------------------------
      * OK, call the base class to write the block to disk.
      *----------------------------------------------------------------*/
-    if (nStatus == 0)
-    {
 #ifdef DEBUG_VERBOSE
-        CPLDebug("MITAB", "Committing HEADER block to offset %d", m_nFileOffset);
+    CPLDebug("MITAB", "Committing HEADER block to offset %d", m_nFileOffset);
 #endif
-        nStatus = TABRawBinBlock::CommitToFile();
-    }
-
-    return nStatus;
+    return TABRawBinBlock::CommitToFile();
 }
 
 /**********************************************************************
@@ -1017,8 +904,6 @@ void TABMAPHeaderBlock::UpdatePrecision()
 
 void TABMAPHeaderBlock::Dump(FILE *fpOut /*=NULL*/)
 {
-    int i;
-
     if (fpOut == NULL)
         fpOut = stdout;
 
@@ -1072,7 +957,7 @@ void TABMAPHeaderBlock::Dump(FILE *fpOut /*=NULL*/)
                                                     (int)m_sProj.nEllipsoidId);
         fprintf(fpOut,"  m_sProj.nUnitsId      = %d\n", (int)m_sProj.nUnitsId);
         fprintf(fpOut,"  m_sProj.adProjParams  =");
-        for(i=0; i<6; i++)
+        for( int i = 0; i < 6; i++)
             fprintf(fpOut, " %g",  m_sProj.adProjParams[i]);
         fprintf(fpOut,"\n");
 
@@ -1080,7 +965,7 @@ void TABMAPHeaderBlock::Dump(FILE *fpOut /*=NULL*/)
         fprintf(fpOut,"  m_sProj.dDatumShiftY  = %.15g\n", m_sProj.dDatumShiftY);
         fprintf(fpOut,"  m_sProj.dDatumShiftZ  = %.15g\n", m_sProj.dDatumShiftZ);
         fprintf(fpOut,"  m_sProj.adDatumParams =");
-        for(i=0; i<5; i++)
+        for( int i = 0; i < 5; i++ )
             fprintf(fpOut, " %.15g",  m_sProj.adDatumParams[i]);
         fprintf(fpOut,"\n");
 
@@ -1088,7 +973,7 @@ void TABMAPHeaderBlock::Dump(FILE *fpOut /*=NULL*/)
         if (FALSE)
         {
             fprintf(fpOut, "-- Header bytes 00-FF: Array of map object lengths --\n");
-            for(i=0; i<256; i++)
+            for( int i = 0; i < 256; i++ )
             {
                 fprintf(fpOut, "0x%2.2x", (int)m_pabyBuf[i]);
                 if (i != 255)
@@ -1097,7 +982,6 @@ void TABMAPHeaderBlock::Dump(FILE *fpOut /*=NULL*/)
                     fprintf(fpOut, "\n");
             }
         }
-
     }
 
     fflush(fpOut);
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp
index 6e32141..eade815 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapindexblock.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_mapindexblock.cpp,v 1.14 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_mapindexblock.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,86 +28,45 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_mapindexblock.cpp,v $
- * Revision 1.14  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.13  2007-04-02 18:58:03  dmorissette
- * Fixed uninitialized variable warning in PickSeedsForSplit()
- *
- * Revision 1.12  2006/12/14 20:03:02  dmorissette
- * Improve write performance by keeping track of changes to index blocks
- * and committing to disk only if modified (related to bug 1585)
- *
- * Revision 1.11  2006/11/28 18:49:08  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.10  2006/11/20 20:05:58  dmorissette
- * First pass at improving generation of spatial index in .map file (bug 1585)
- * New methods for insertion and splitting the spatial index are done.
- * Also implemented a method to dump the spatial index to .mif/.mid
- * Still need to implement splitting of TABMapObjectBlock to get optimal
- * results.
- *
- * Revision 1.9  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.8  2001/09/14 03:23:55  warmerda
- * Substantial upgrade to support spatial queries using spatial indexes
- *
- * Revision 1.7  2000/05/23 17:02:54  daniel
- * Removed unused variables
- *
- * Revision 1.6  2000/05/19 06:45:10  daniel
- * Modified generation of spatial index to split index nodes and produce a
- * more balanced tree.
- *
- * Revision 1.5  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.4  1999/10/01 03:46:31  daniel
- * Added ReadAllEntries() and more complete Dump() for debugging files
- *
- * Revision 1.3  1999/09/29 04:23:51  daniel
- * Fixed typo in GetMBR()
- *
- * Revision 1.2  1999/09/26 14:59:37  daniel
- * Implemented write support
- *
- * Revision 1.1  1999/07/12 04:18:25  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
 
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
+
+CPL_CVSID("$Id: mitab_mapindexblock.cpp 37351 2017-02-12 05:22:20Z goatbar $");
+
 /*=====================================================================
  *                      class TABMAPIndexBlock
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABMAPIndexBlock::TABMAPIndexBlock()
  *
  * Constructor.
  **********************************************************************/
-TABMAPIndexBlock::TABMAPIndexBlock(TABAccess eAccessMode /*= TABRead*/):
-    TABRawBinBlock(eAccessMode, TRUE)
+TABMAPIndexBlock::TABMAPIndexBlock( TABAccess eAccessMode /*= TABRead*/ ) :
+    TABRawBinBlock(eAccessMode, TRUE),
+    m_numEntries(0),
+    m_nMinX(1000000000),
+    m_nMinY(1000000000),
+    m_nMaxX(-1000000000),
+    m_nMaxY(-1000000000),
+    m_poBlockManagerRef(NULL),
+    m_poCurChild(NULL),
+    m_nCurChildIndex(-1),
+    m_poParentRef(NULL)
 {
-    m_numEntries = 0;
-
-    m_nMinX = 1000000000;
-    m_nMinY = 1000000000;
-    m_nMaxX = -1000000000;
-    m_nMaxY = -1000000000;
-
-    m_poCurChild = NULL;
-    m_nCurChildIndex = -1;
-    m_poParentRef = NULL;
-    m_poBlockManagerRef = NULL;
     memset(m_asEntries, 0, sizeof(m_asEntries));
 }
 
@@ -153,15 +111,14 @@ int     TABMAPIndexBlock::InitBlockFromData(GByte *pabyBuf,
                                             VSILFILE *fpSrc /* = NULL */,
                                             int nOffset /* = 0 */)
 {
-    int nStatus;
-
     /*-----------------------------------------------------------------
      * First of all, we must call the base class' InitBlockFromData()
      *----------------------------------------------------------------*/
-    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf,
-                                                nBlockSize, nSizeUsed,
-                                                bMakeCopy,
-                                                fpSrc, nOffset);
+    const int nStatus =
+        TABRawBinBlock::InitBlockFromData(pabyBuf,
+                                          nBlockSize, nSizeUsed,
+                                          bMakeCopy,
+                                          fpSrc, nOffset);
     if (nStatus != 0)
         return nStatus;
 
@@ -250,7 +207,6 @@ int     TABMAPIndexBlock::CommitToFile()
             nStatus = WriteNextEntry(&(m_asEntries[i]));
     }
 
-
     /*-----------------------------------------------------------------
      * OK, call the base class to write the block to disk.
      *----------------------------------------------------------------*/
@@ -265,7 +221,6 @@ int     TABMAPIndexBlock::CommitToFile()
     return nStatus;
 }
 
-
 /**********************************************************************
  *                   TABMAPIndexBlock::InitNewBlock()
  *
@@ -314,8 +269,6 @@ int     TABMAPIndexBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
     return 0;
 }
 
-
-
 /**********************************************************************
  *                   TABMAPIndexBlock::ReadNextEntry()
  *
@@ -406,7 +359,7 @@ int     TABMAPIndexBlock::WriteNextEntry(TABMAPIndexEntry *psEntry)
  **********************************************************************/
 int     TABMAPIndexBlock::GetNumFreeEntries()
 {
-    return ((m_nBlockSize-4)/20 - m_numEntries);
+    return (m_nBlockSize-4)/20 - m_numEntries;
 }
 
 /**********************************************************************
@@ -525,28 +478,30 @@ int     TABMAPIndexBlock::InsertEntry(GInt32 nXMin, GInt32 nYMin,
 int     TABMAPIndexBlock::ChooseSubEntryForInsert(GInt32 nXMin, GInt32 nYMin,
                                                   GInt32 nXMax, GInt32 nYMax)
 {
-    GInt32 i, nBestCandidate=-1;
+    GInt32 nBestCandidate = -1;
 
-    double dOptimalAreaDiff=0;
+    double dOptimalAreaDiff = 0.0;
 
-    double dNewEntryArea = MITAB_AREA(nXMin, nYMin, nXMax, nYMax);
+    const double dNewEntryArea = MITAB_AREA(nXMin, nYMin, nXMax, nYMax);
 
-    for(i=0; i<m_numEntries; i++)
+    for( GInt32 i = 0; i<m_numEntries; i++ )
     {
-        double dAreaDiff = 0;
-        double dAreaBefore = MITAB_AREA(m_asEntries[i].XMin,
-                                        m_asEntries[i].YMin,
-                                        m_asEntries[i].XMax,
-                                        m_asEntries[i].YMax);
+        double dAreaDiff = 0.0;
+        const double dAreaBefore =
+            MITAB_AREA(m_asEntries[i].XMin,
+                       m_asEntries[i].YMin,
+                       m_asEntries[i].XMax,
+                       m_asEntries[i].YMax);
 
         /* Does this entry fully contain the new entry's MBR ?
          */
-        GBool bIsContained = (nXMin >= m_asEntries[i].XMin &&
-                              nYMin >= m_asEntries[i].YMin &&
-                              nXMax <= m_asEntries[i].XMax &&
-                              nYMax <= m_asEntries[i].YMax );
+        const GBool bIsContained =
+            nXMin >= m_asEntries[i].XMin &&
+            nYMin >= m_asEntries[i].YMin &&
+            nXMax <= m_asEntries[i].XMax &&
+            nYMax <= m_asEntries[i].YMax;
 
-        if (bIsContained)
+        if( bIsContained )
         {
             /* If new entry is fully contained in this entry then
              * the area difference will be the difference between the area
@@ -561,11 +516,10 @@ int     TABMAPIndexBlock::ChooseSubEntryForInsert(GInt32 nXMin, GInt32 nYMin,
             /* Need to calculate the expanded MBR to calculate the area
              * difference.
              */
-            GInt32 nXMin2, nYMin2, nXMax2, nYMax2;
-            nXMin2 = MIN(m_asEntries[i].XMin, nXMin);
-            nYMin2 = MIN(m_asEntries[i].YMin, nYMin);
-            nXMax2 = MAX(m_asEntries[i].XMax, nXMax);
-            nYMax2 = MAX(m_asEntries[i].YMax, nYMax);
+            GInt32 nXMin2 = std::min(m_asEntries[i].XMin, nXMin);
+            GInt32 nYMin2 = std::min(m_asEntries[i].YMin, nYMin);
+            GInt32 nXMax2 = std::max(m_asEntries[i].XMax, nXMax);
+            GInt32 nYMax2 = std::max(m_asEntries[i].YMax, nYMax);
 
             dAreaDiff = MITAB_AREA(nXMin2,nYMin2,nXMax2,nYMax2) - dAreaBefore;
         }
@@ -585,12 +539,11 @@ int     TABMAPIndexBlock::ChooseSubEntryForInsert(GInt32 nXMin, GInt32 nYMin,
              */
             || (((dOptimalAreaDiff < 0 && dAreaDiff < 0) ||
                  (dOptimalAreaDiff > 0 && dAreaDiff > 0)) &&
-                ABS(dAreaDiff) < ABS(dOptimalAreaDiff)) )
+                std::abs(dAreaDiff) < std::abs(dOptimalAreaDiff)) )
         {
             nBestCandidate = i;
             dOptimalAreaDiff = dAreaDiff;
         }
-
     }
 
     return nBestCandidate;
@@ -664,7 +617,6 @@ GInt32  TABMAPIndexBlock::ChooseLeafForInsert(GInt32 nXMin, GInt32 nYMin,
     CPLPopErrorHandler();
     CPLErrorReset();
 
-
     if (bFound)
     {
         /*-------------------------------------------------------------
@@ -681,7 +633,6 @@ GInt32  TABMAPIndexBlock::ChooseLeafForInsert(GInt32 nXMin, GInt32 nYMin,
     return m_asEntries[nBestCandidate].nBlockPtr;
 }
 
-
 /**********************************************************************
  *                   TABMAPIndexBlock::GetCurLeafEntryMBR()
  *
@@ -724,10 +675,8 @@ int     TABMAPIndexBlock::GetCurLeafEntryMBR(GInt32 nBlockPtr,
     CPLError(CE_Failure, CPLE_AssertionFailed,
              "Entry to update not found in GetCurLeafEntryMBR()!");
     return -1;
-
 }
 
-
 /**********************************************************************
  *                   TABMAPIndexBlock::UpdateLeafEntry()
  *
@@ -786,7 +735,6 @@ int     TABMAPIndexBlock::UpdateLeafEntry(GInt32 nBlockPtr,
     return -1;
 }
 
-
 /**********************************************************************
  *                   TABMAPIndexBlock::AddEntry()
  *
@@ -941,27 +889,28 @@ int     TABMAPIndexBlock::AddEntry(GInt32 nXMin, GInt32 nYMin,
  * The returned AreaDiff value is positive if NodeMBR has to be enlarged
  * and negative if new Entry is fully contained in the NodeMBR.
  **********************************************************************/
-double  TABMAPIndexBlock::ComputeAreaDiff(GInt32 nNodeXMin, GInt32 nNodeYMin,
-                                          GInt32 nNodeXMax, GInt32 nNodeYMax,
-                                          GInt32 nEntryXMin, GInt32 nEntryYMin,
-                                          GInt32 nEntryXMax, GInt32 nEntryYMax)
+double  TABMAPIndexBlock::ComputeAreaDiff( GInt32 nNodeXMin, GInt32 nNodeYMin,
+                                           GInt32 nNodeXMax, GInt32 nNodeYMax,
+                                           GInt32 nEntryXMin, GInt32 nEntryYMin,
+                                           GInt32 nEntryXMax,
+                                           GInt32 nEntryYMax )
 {
-
-    double dAreaDiff=0;
-
-    double dNodeAreaBefore = MITAB_AREA(nNodeXMin,
-                                        nNodeYMin,
-                                        nNodeXMax,
-                                        nNodeYMax);
-
-    /* Does the node fully contain the new entry's MBR ?
-     */
-    GBool bIsContained = (nEntryXMin >= nNodeXMin &&
-                          nEntryYMin >= nNodeYMin &&
-                          nEntryXMax <= nNodeXMax &&
-                          nEntryYMax <= nNodeYMax );
-
-    if (bIsContained)
+    double dAreaDiff = 0.0;
+
+    const double dNodeAreaBefore =
+        MITAB_AREA(nNodeXMin,
+                   nNodeYMin,
+                   nNodeXMax,
+                   nNodeYMax);
+
+    // Does the node fully contain the new entry's MBR?
+    const GBool bIsContained =
+        nEntryXMin >= nNodeXMin &&
+        nEntryYMin >= nNodeYMin &&
+        nEntryXMax <= nNodeXMax &&
+        nEntryYMax <= nNodeYMax;
+
+    if( bIsContained )
     {
         /* If new entry is fully contained in this entry then
          * the area difference will be the difference between the area
@@ -975,10 +924,10 @@ double  TABMAPIndexBlock::ComputeAreaDiff(GInt32 nNodeXMin, GInt32 nNodeYMin,
         /* Need to calculate the expanded MBR to calculate the area
          * difference.
          */
-        nNodeXMin = MIN(nNodeXMin, nEntryXMin);
-        nNodeYMin = MIN(nNodeYMin, nEntryYMin);
-        nNodeXMax = MAX(nNodeXMax, nEntryXMax);
-        nNodeYMax = MAX(nNodeYMax, nEntryYMax);
+        nNodeXMin = std::min(nNodeXMin, nEntryXMin);
+        nNodeYMin = std::min(nNodeYMin, nEntryYMin);
+        nNodeXMax = std::max(nNodeXMax, nEntryXMax);
+        nNodeYMax = std::max(nNodeYMax, nEntryYMax);
 
         dAreaDiff = MITAB_AREA(nNodeXMin,nNodeYMin,
                                nNodeXMax,nNodeYMax) - dNodeAreaBefore;
@@ -987,8 +936,6 @@ double  TABMAPIndexBlock::ComputeAreaDiff(GInt32 nNodeXMin, GInt32 nNodeYMin,
     return dAreaDiff;
 }
 
-
-
 /**********************************************************************
  *                   TABMAPIndexBlock::PickSeedsForSplit()
  *
@@ -1005,21 +952,30 @@ double  TABMAPIndexBlock::ComputeAreaDiff(GInt32 nNodeXMin, GInt32 nNodeYMin,
  * - Choose the pair with the greatest normalized separation along
  *   any dimension
  **********************************************************************/
-int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
+int TABMAPIndexBlock::PickSeedsForSplit( TABMAPIndexEntry *pasEntries,
                                          int numEntries,
                                          int nSrcCurChildIndex,
                                          GInt32 nNewEntryXMin,
                                          GInt32 nNewEntryYMin,
                                          GInt32 nNewEntryXMax,
                                          GInt32 nNewEntryYMax,
-                                         int &nSeed1, int &nSeed2)
+                                         int &nSeed1, int &nSeed2 )
 {
-    GInt32 nSrcMinX=0, nSrcMinY=0, nSrcMaxX=0, nSrcMaxY=0;
-    int nLowestMaxX=-1, nHighestMinX=-1, nLowestMaxY=-1, nHighestMinY=-1;
-    GInt32 nLowestMaxXId=-1, nHighestMinXId=-1, nLowestMaxYId=-1, nHighestMinYId=-1;
-
-    nSeed1=-1;
-    nSeed2=-1;
+    GInt32 nSrcMinX = 0;
+    GInt32 nSrcMinY = 0;
+    GInt32 nSrcMaxX = 0;
+    GInt32 nSrcMaxY = 0;
+    int nLowestMaxX = -1;
+    int nHighestMinX = -1;
+    int nLowestMaxY = -1;
+    int nHighestMinY = -1;
+    GInt32 nLowestMaxXId=-1;
+    GInt32 nHighestMinXId=-1;
+    GInt32 nLowestMaxYId=-1;
+    GInt32 nHighestMinYId = -1;
+
+    nSeed1 = -1;
+    nSeed2 = -1;
 
     // Along each dimension find the entry whose rectangle has the
     // highest low side, and the one with the lowest high side
@@ -1063,25 +1019,24 @@ int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
         }
         else
         {
-            nSrcMinX = MIN(nSrcMinX, pasEntries[iEntry].XMin);
-            nSrcMinY = MIN(nSrcMinY ,pasEntries[iEntry].YMin);
-            nSrcMaxX = MAX(nSrcMaxX ,pasEntries[iEntry].XMax);
-            nSrcMaxY = MAX(nSrcMaxY ,pasEntries[iEntry].YMax);
+            nSrcMinX = std::min(nSrcMinX, pasEntries[iEntry].XMin);
+            nSrcMinY = std::min(nSrcMinY, pasEntries[iEntry].YMin);
+            nSrcMaxX = std::max(nSrcMaxX, pasEntries[iEntry].XMax);
+            nSrcMaxY = std::max(nSrcMaxY, pasEntries[iEntry].YMax);
         }
     }
 
-    int nSrcWidth, nSrcHeight;
-    nSrcWidth = ABS(nSrcMaxX - nSrcMinX);
-    nSrcHeight = ABS(nSrcMaxY - nSrcMinY);
+    const int nSrcWidth = std::abs(nSrcMaxX - nSrcMinX);
+    const int nSrcHeight = std::abs(nSrcMaxY - nSrcMinY);
 
     // Calculate the separation for each pair (note that it may be negative
     // in case of overlap)
     // Normalize the separation by dividing by the extents of the
     // corresponding dimension
-    double dX, dY;
-
-    dX = (nSrcWidth == 0) ? 0 : (double)(nHighestMinX - nLowestMaxX) / nSrcWidth;
-    dY = (nSrcHeight == 0) ? 0 : (double)(nHighestMinY - nLowestMaxY) / nSrcHeight;
+    const double dX =
+        nSrcWidth == 0 ? 0 : (double)(nHighestMinX - nLowestMaxX) / nSrcWidth;
+    const double dY =
+        nSrcHeight == 0 ? 0 : (double)(nHighestMinY - nLowestMaxY) / nSrcHeight;
 
     // Choose the pair with the greatest normalized separation along
     // any dimension
@@ -1110,20 +1065,21 @@ int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
     // Decide which of the two seeds best matches the new entry. That seed and
     // the new entry will stay in current node (new entry will be added by the
     // caller later). The other seed will go in the 2nd node
-    double dAreaDiff1, dAreaDiff2;
-    dAreaDiff1 = ComputeAreaDiff(pasEntries[nSeed1].XMin,
-                                 pasEntries[nSeed1].YMin,
-                                 pasEntries[nSeed1].XMax,
-                                 pasEntries[nSeed1].YMax,
-                                 nNewEntryXMin, nNewEntryYMin,
-                                 nNewEntryXMax, nNewEntryYMax);
-
-    dAreaDiff2 = ComputeAreaDiff(pasEntries[nSeed2].XMin,
-                                 pasEntries[nSeed2].YMin,
-                                 pasEntries[nSeed2].XMax,
-                                 pasEntries[nSeed2].YMax,
-                                 nNewEntryXMin, nNewEntryYMin,
-                                 nNewEntryXMax, nNewEntryYMax);
+    const double dAreaDiff1 =
+        ComputeAreaDiff(pasEntries[nSeed1].XMin,
+                        pasEntries[nSeed1].YMin,
+                        pasEntries[nSeed1].XMax,
+                        pasEntries[nSeed1].YMax,
+                        nNewEntryXMin, nNewEntryYMin,
+                        nNewEntryXMax, nNewEntryYMax);
+
+    const double dAreaDiff2 =
+        ComputeAreaDiff(pasEntries[nSeed2].XMin,
+                        pasEntries[nSeed2].YMin,
+                        pasEntries[nSeed2].XMax,
+                        pasEntries[nSeed2].YMax,
+                        nNewEntryXMin, nNewEntryYMin,
+                        nNewEntryXMax, nNewEntryYMax);
 
     /* Note that we want to keep this node's current child in here.
      * Since splitting happens only during an addentry() operation and
@@ -1143,7 +1099,6 @@ int  TABMAPIndexBlock::PickSeedsForSplit(TABMAPIndexEntry *pasEntries,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPIndexBlock::SplitNode()
  *
@@ -1243,7 +1198,6 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
             m_nCurChildIndex = m_numEntries-1;
 
             continue;
-
         }
         else if (m_numEntries >= GetMaxEntries()-1)
         {
@@ -1264,27 +1218,30 @@ int     TABMAPIndexBlock::SplitNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
             continue;
         }
 
-
         // Decide which of the two nodes to put this entry in
-        double dAreaDiff1, dAreaDiff2;
         RecomputeMBR();
-        dAreaDiff1 = ComputeAreaDiff(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY,
-                                     pasSrcEntries[iEntry].XMin,
-                                     pasSrcEntries[iEntry].YMin,
-                                     pasSrcEntries[iEntry].XMax,
-                                     pasSrcEntries[iEntry].YMax);
-
-        GInt32 nXMin2, nYMin2, nXMax2, nYMax2;
+        const double dAreaDiff1 =
+            ComputeAreaDiff(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY,
+                            pasSrcEntries[iEntry].XMin,
+                            pasSrcEntries[iEntry].YMin,
+                            pasSrcEntries[iEntry].XMax,
+                            pasSrcEntries[iEntry].YMax);
+
+        GInt32 nXMin2 = 0;
+        GInt32 nYMin2 = 0;
+        GInt32 nXMax2 = 0;
+        GInt32 nYMax2 = 0;
         poNewNode->RecomputeMBR();
         poNewNode->GetMBR(nXMin2, nYMin2, nXMax2, nYMax2);
-        dAreaDiff2 = ComputeAreaDiff(nXMin2, nYMin2, nXMax2, nYMax2,
-                                     pasSrcEntries[iEntry].XMin,
-                                     pasSrcEntries[iEntry].YMin,
-                                     pasSrcEntries[iEntry].XMax,
-                                     pasSrcEntries[iEntry].YMax);
-        if (dAreaDiff1 < dAreaDiff2)
+        const double dAreaDiff2 =
+            ComputeAreaDiff(nXMin2, nYMin2, nXMax2, nYMax2,
+                            pasSrcEntries[iEntry].XMin,
+                            pasSrcEntries[iEntry].YMin,
+                            pasSrcEntries[iEntry].XMax,
+                            pasSrcEntries[iEntry].YMax);
+        if( dAreaDiff1 < dAreaDiff2 )
         {
-            // This entry stays in this node
+            // This entry stays in this node.
             InsertEntry(pasSrcEntries[iEntry].XMin,
                         pasSrcEntries[iEntry].YMin,
                         pasSrcEntries[iEntry].XMax,
@@ -1401,7 +1358,6 @@ int TABMAPIndexBlock::SplitRootNode(GInt32 nNewEntryXMin, GInt32 nNewEntryYMin,
                                    nNewEntryXMax, nNewEntryYMax);
 }
 
-
 /**********************************************************************
  *                   TABMAPIndexBlock::RecomputeMBR()
  *
@@ -1446,7 +1402,6 @@ void TABMAPIndexBlock::RecomputeMBR()
                                              m_nMaxX, m_nMaxY,
                                              GetNodeBlockPtr());
     }
-
 }
 
 /**********************************************************************
@@ -1499,10 +1454,8 @@ void TABMAPIndexBlock::UpdateCurChildMBR(GInt32 nXMin, GInt32 nYMin,
     if (m_poParentRef)
         m_poParentRef->UpdateCurChildMBR(m_nMinX, m_nMinY, m_nMaxX, m_nMaxY,
                                          GetNodeBlockPtr());
-
 }
 
-
 /**********************************************************************
  *                   TABMAPIndexBlock::SetMAPBlockManagerRef()
  *
@@ -1573,7 +1526,6 @@ void TABMAPIndexBlock::Dump(FILE *fpOut /*=NULL*/)
                     m_asEntries[i].XMin, m_asEntries[i].YMin,
                     m_asEntries[i].XMax, m_asEntries[i].YMax );
         }
-
     }
 
     fflush(fpOut);
diff --git a/ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp
index 331ce3b..8db86d8 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_mapobjectblock.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_mapobjectblock.cpp,v 1.23 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_mapobjectblock.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,119 +28,50 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_mapobjectblock.cpp,v $
- * Revision 1.23  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.22  2008-02-20 21:35:30  dmorissette
- * Added support for V800 COLLECTION of large objects (bug 1496)
- *
- * Revision 1.21  2008/02/05 22:22:48  dmorissette
- * Added support for TAB_GEOM_V800_MULTIPOINT (bug 1496)
- *
- * Revision 1.20  2008/02/01 19:36:31  dmorissette
- * Initial support for V800 REGION and MULTIPLINE (bug 1496)
- *
- * Revision 1.19  2007/09/18 17:43:56  dmorissette
- * Fixed another index splitting issue: compr coordinates origin was not
- * stored in the TABFeature in ReadGeometry... (bug 1732)
- *
- * Revision 1.18  2007/06/11 14:52:31  dmorissette
- * Return a valid m_nCoordDatasize value for Collection objects to prevent
- * trashing of collection data during object splitting (bug 1728)
- *
- * Revision 1.17  2007/05/22 14:53:10  dmorissette
- * Fixed error reading compressed text objects introduced in v1.6.0 (bug 1722)
- *
- * Revision 1.16  2006/11/28 18:49:08  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.15  2005/10/06 19:15:31  dmorissette
- * Collections: added support for reading/writing pen/brush/symbol ids and
- * for writing collection objects to .TAB/.MAP (bug 1126)
- *
- * Revision 1.14  2005/10/04 15:44:31  dmorissette
- * First round of support for Collection objects. Currently supports reading
- * from .TAB/.MAP and writing to .MIF. Still lacks symbol support and write
- * support. (Based in part on patch and docs from Jim Hope, bug 1126)
- *
- * Revision 1.13  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.12  2002/03/26 01:48:40  daniel
- * Added Multipoint object type (V650)
- *
- * Revision 1.11  2001/12/05 22:40:27  daniel
- * Init MBR to 0 in TABMAPObjHdr and modif. SetMBR() to validate min/max
- *
- * Revision 1.10  2001/11/19 15:07:06  daniel
- * Handle the case of TAB_GEOM_NONE with the new TABMAPObjHdr classes.
- *
- * Revision 1.9  2001/11/17 21:54:06  daniel
- * Made several changes in order to support writing objects in 16 bits
- * coordinate format. New TABMAPObjHdr-derived classes are used to hold
- * object info in mem until block is full.
- *
- * Revision 1.8  2001/09/19 19:19:11  warmerda
- * modified AdvanceToNextObject() to skip deleted objects
- *
- * Revision 1.7  2001/09/14 03:23:55  warmerda
- * Substantial upgrade to support spatial queries using spatial indexes
- *
- * Revision 1.6  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.5  1999/10/19 06:07:29  daniel
- * Removed obsolete comment.
- *
- * Revision 1.4  1999/10/18 15:41:00  daniel
- * Added WriteIntMBRCoord()
- *
- * Revision 1.3  1999/09/29 04:23:06  daniel
- * Fixed typo in GetMBR()
- *
- * Revision 1.2  1999/09/26 14:59:37  daniel
- * Implemented write support
- *
- * Revision 1.1  1999/07/12 04:18:25  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <algorithm>
+#include <limits.h>
+#include <stddef.h>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
 #include "mitab_utils.h"
 
+CPL_CVSID("$Id: mitab_mapobjectblock.cpp 37351 2017-02-12 05:22:20Z goatbar $");
+
 /*=====================================================================
  *                      class TABMAPObjectBlock
  *====================================================================*/
 
-#define MAP_OBJECT_HEADER_SIZE   20
+static const int MAP_OBJECT_HEADER_SIZE = 20;
 
 /**********************************************************************
  *                   TABMAPObjectBlock::TABMAPObjectBlock()
  *
  * Constructor.
  **********************************************************************/
-TABMAPObjectBlock::TABMAPObjectBlock(TABAccess eAccessMode /*= TABRead*/):
-    TABRawBinBlock(eAccessMode, TRUE)
-{
-    m_bLockCenter = FALSE;
-    m_numDataBytes = 0;
-    m_nFirstCoordBlock = 0;
-    m_nLastCoordBlock = 0;
-    m_nCenterX = 0;
-    m_nCenterY = 0;
-    m_nMinX = 0;
-    m_nMinY = 0;
-    m_nMaxX = 0;
-    m_nMaxY = 0;
-    m_nCurObjectOffset = 0;
-    m_nCurObjectId = 0;
-    m_nCurObjectType = TAB_GEOM_UNSET;
-}
+TABMAPObjectBlock::TABMAPObjectBlock( TABAccess eAccessMode /*= TABRead*/ ) :
+    TABRawBinBlock(eAccessMode, TRUE),
+    m_numDataBytes(0),
+    m_nFirstCoordBlock(0),
+    m_nLastCoordBlock(0),
+    m_nCenterX(0),
+    m_nCenterY(0),
+    m_nMinX(0),
+    m_nMinY(0),
+    m_nMaxX(0),
+    m_nMaxY(0),
+    m_nCurObjectOffset(0),
+    m_nCurObjectId(0),
+    m_nCurObjectType(TAB_GEOM_UNSET),
+    m_bLockCenter(FALSE)
+{}
 
 /**********************************************************************
  *                   TABMAPObjectBlock::~TABMAPObjectBlock()
@@ -150,14 +80,13 @@ TABMAPObjectBlock::TABMAPObjectBlock(TABAccess eAccessMode /*= TABRead*/):
  **********************************************************************/
 TABMAPObjectBlock::~TABMAPObjectBlock()
 {
-
+    // TODO(schwehr): Why set these?  Should remove.
     m_nMinX = 1000000000;
     m_nMinY = 1000000000;
     m_nMaxX = -1000000000;
     m_nMaxY = -1000000000;
 }
 
-
 /**********************************************************************
  *                   TABMAPObjectBlock::InitBlockFromData()
  *
@@ -173,15 +102,14 @@ int     TABMAPObjectBlock::InitBlockFromData(GByte *pabyBuf,
                                              VSILFILE *fpSrc /* = NULL */,
                                              int nOffset /* = 0 */)
 {
-    int nStatus;
-
     /*-----------------------------------------------------------------
      * First of all, we must call the base class' InitBlockFromData()
      *----------------------------------------------------------------*/
-    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf,
-                                                nBlockSize, nSizeUsed,
-                                                bMakeCopy,
-                                                fpSrc, nOffset);
+    const int nStatus =
+        TABRawBinBlock::InitBlockFromData(pabyBuf,
+                                          nBlockSize, nSizeUsed,
+                                          bMakeCopy,
+                                          fpSrc, nOffset);
     if (nStatus != 0)
         return nStatus;
 
@@ -417,8 +345,8 @@ int     TABMAPObjectBlock::CommitToFile()
  * Returns 0 if successful or -1 if an error happened, in which case
  * CPLError() will have been called.
  **********************************************************************/
-int     TABMAPObjectBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
-                                        int nFileOffset /* = 0*/)
+int TABMAPObjectBlock::InitNewBlock( VSILFILE *fpSrc, int nBlockSize,
+                                     int nFileOffset /* = 0*/ )
 {
     /*-----------------------------------------------------------------
      * Start with the default initialization
@@ -442,7 +370,8 @@ int     TABMAPObjectBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
     m_nCurObjectType = TAB_GEOM_UNSET;
 
     m_numDataBytes = 0;       /* Data size excluding header */
-    m_nCenterX = m_nCenterY = 0;
+    m_nCenterX = 0;
+    m_nCenterY = 0;
     m_nFirstCoordBlock = 0;
     m_nLastCoordBlock = 0;
 
@@ -553,9 +482,9 @@ int     TABMAPObjectBlock::WriteIntMBRCoord(GInt32 nXMin, GInt32 nYMin,
                                             GInt32 nXMax, GInt32 nYMax,
                                             GBool bCompressed /*=FALSE*/)
 {
-    if (WriteIntCoord(MIN(nXMin, nXMax), MIN(nYMin, nYMax),
+    if (WriteIntCoord(std::min(nXMin, nXMax), std::min(nYMin, nYMax),
                       bCompressed) != 0 ||
-        WriteIntCoord(MAX(nXMin, nXMax), MAX(nYMin, nYMax),
+        WriteIntCoord(std::max(nXMin, nXMax), std::max(nYMin, nYMax),
                       bCompressed) != 0 )
     {
         return -1;
@@ -564,7 +493,6 @@ int     TABMAPObjectBlock::WriteIntMBRCoord(GInt32 nXMin, GInt32 nYMin,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPObjectBlock::UpdateMBR()
  *
@@ -649,7 +577,6 @@ void TABMAPObjectBlock::GetMBR(GInt32 &nXMin, GInt32 &nYMin,
     nYMax = m_nMaxY;
 }
 
-
 /**********************************************************************
  *                   TABMAPObjectBlock::PrepareNewObject()
  *
@@ -761,20 +688,18 @@ void TABMAPObjectBlock::Dump(FILE *fpOut, GBool bDetails)
     if (bDetails)
     {
         /* We need the mapfile's header block */
-        TABRawBinBlock *poBlock;
-        TABMAPHeaderBlock *poHeader;
-        TABMAPObjHdr *poObjHdr;
-
-        poBlock = TABCreateMAPBlockFromFile(m_fp, 0, m_nBlockSize);
+        TABRawBinBlock *poBlock =
+            TABCreateMAPBlockFromFile(m_fp, 0, m_nBlockSize);
         if (poBlock==NULL || poBlock->GetBlockClass() != TABMAP_HEADER_BLOCK)
         {
             CPLError(CE_Failure, CPLE_AssertionFailed,
                      "Failed reading header block.");
             return;
         }
-        poHeader = (TABMAPHeaderBlock *)poBlock;
+        TABMAPHeaderBlock *poHeader = (TABMAPHeaderBlock *)poBlock;
 
         Rewind();
+        TABMAPObjHdr *poObjHdr = NULL;
         while((poObjHdr = TABMAPObjHdr::ReadNextObj(this, poHeader)) != NULL)
         {
             fprintf(fpOut,
@@ -796,8 +721,6 @@ void TABMAPObjectBlock::Dump(FILE *fpOut, GBool bDetails)
 
 #endif // DEBUG
 
-
-
 /*=====================================================================
  *                      class TABMAPObjHdr and family
  *====================================================================*/
@@ -810,7 +733,6 @@ void TABMAPObjectBlock::Dump(FILE *fpOut, GBool bDetails)
  *
  **********************************************************************/
 
-
 /**********************************************************************
  *                    TABMAPObjHdr::NewObj()
  *
@@ -902,7 +824,6 @@ TABMAPObjHdr *TABMAPObjHdr::NewObj(TABGeomType nNewObjType, GInt32 nId /*=0*/)
     return poObj;
 }
 
-
 /**********************************************************************
  *                    TABMAPObjHdr::ReadNextObj()
  *
@@ -940,7 +861,7 @@ TABMAPObjHdr *TABMAPObjHdr::ReadNextObj(TABMAPObjectBlock *poObjBlock,
 GBool TABMAPObjHdr::IsCompressedType()
 {
     // Compressed types are 1, 4, 7, etc.
-    return ((m_nType % 3) == 1 ? TRUE : FALSE);
+    return (m_nType % 3) == 1 ? TRUE : FALSE;
 }
 
 /**********************************************************************
@@ -964,13 +885,12 @@ int TABMAPObjHdr::WriteObjTypeAndId(TABMAPObjectBlock *poObjBlock)
 void TABMAPObjHdr::SetMBR(GInt32 nMinX, GInt32 nMinY,
                           GInt32 nMaxX, GInt32 nMaxY)
 {
-    m_nMinX = MIN(nMinX, nMaxX);
-    m_nMinY = MIN(nMinY, nMaxY);
-    m_nMaxX = MAX(nMinX, nMaxX);
-    m_nMaxY = MAX(nMinY, nMaxY);
+    m_nMinX = std::min(nMinX, nMaxX);
+    m_nMinY = std::min(nMinY, nMaxY);
+    m_nMaxX = std::max(nMinX, nMaxX);
+    m_nMaxY = std::max(nMinY, nMaxY);
 }
 
-
 /**********************************************************************
  *                   class TABMAPObjLine
  *
@@ -1055,7 +975,7 @@ int TABMAPObjPLine::ReadObj(TABMAPObjectBlock *poObjBlock)
     }
 
 #ifdef TABDUMP
-    printf("TABMAPObjPLine::ReadObj: m_nCoordDataSize = %d @ %d\n",
+    printf("TABMAPObjPLine::ReadObj: m_nCoordDataSize = %d @ %d\n",/*ok*/
            m_nCoordDataSize, m_nCoordBlockPtr);
 #endif
 
@@ -1097,7 +1017,7 @@ int TABMAPObjPLine::ReadObj(TABMAPObjectBlock *poObjBlock)
     }
 
 #ifdef TABDUMP
-    printf("PLINE/REGION: id=%d, type=%d, "
+    printf("PLINE/REGION: id=%d, type=%d, "/*ok*/
            "CoordBlockPtr=%d, CoordDataSize=%d, numLineSect=%d, bSmooth=%d\n",
            m_nId, m_nType, m_nCoordBlockPtr, m_nCoordDataSize,
            m_numLineSections, m_bSmooth);
@@ -1139,7 +1059,6 @@ int TABMAPObjPLine::ReadObj(TABMAPObjectBlock *poObjBlock)
         m_nMaxY = poObjBlock->ReadInt32();
     }
 
-
     if ( ! IsCompressedType() )
     {
         // Init. Compr. Origin to a default value in case type is ever changed
@@ -1169,7 +1088,6 @@ int TABMAPObjPLine::ReadObj(TABMAPObjectBlock *poObjBlock)
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPObjPLine::WriteObj()
  *
@@ -1261,7 +1179,6 @@ int TABMAPObjPLine::WriteObj(TABMAPObjectBlock *poObjBlock)
     return 0;
 }
 
-
 /**********************************************************************
  *                   class TABMAPObjPoint
  *
@@ -1308,7 +1225,6 @@ int TABMAPObjPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
     return 0;
 }
 
-
 /**********************************************************************
  *                   class TABMAPObjFontPoint
  *
@@ -1383,7 +1299,6 @@ int TABMAPObjFontPoint::WriteObj(TABMAPObjectBlock *poObjBlock)
     return 0;
 }
 
-
 /**********************************************************************
  *                   class TABMAPObjCustomPoint
  *
@@ -1515,7 +1430,6 @@ int TABMAPObjRectEllipse::WriteObj(TABMAPObjectBlock *poObjBlock)
     return 0;
 }
 
-
 /**********************************************************************
  *                   class TABMAPObjArc
  *
@@ -1581,8 +1495,6 @@ int TABMAPObjArc::WriteObj(TABMAPObjectBlock *poObjBlock)
     return 0;
 }
 
-
-
 /**********************************************************************
  *                   class TABMAPObjText
  *
@@ -1722,7 +1634,7 @@ int TABMAPObjMultiPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
     m_nCoordDataSize = m_nNumPoints * nPointSize;
 
 #ifdef TABDUMP
-    printf("MULTIPOINT: id=%d, type=%d, "
+    printf("MULTIPOINT: id=%d, type=%d, "/*ok*/
            "CoordBlockPtr=%d, CoordDataSize=%d, numPoints=%d\n",
            m_nId, m_nType, m_nCoordBlockPtr, m_nCoordDataSize, m_nNumPoints);
 #endif
@@ -1800,7 +1712,6 @@ int TABMAPObjMultiPoint::ReadObj(TABMAPObjectBlock *poObjBlock)
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPObjMultiPoint::WriteObj()
  *
@@ -2014,9 +1925,8 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
         m_nCoordDataSize += SIZE_OF_MPOINT_MINI_HDR + m_nMPointDataSize;
     }
 
-
 #ifdef TABDUMP
-    printf("COLLECTION: id=%d, type=%d (0x%x), "
+    printf("COLLECTION: id=%d, type=%d (0x%x), "/*ok*/
            "CoordBlockPtr=%d, numRegionSections=%d (size=%d+%d), "
            "numPlineSections=%d (size=%d+%d), numPoints=%d (size=%d+%d)\n",
            m_nId, m_nType, m_nType, m_nCoordBlockPtr,
@@ -2060,7 +1970,7 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
     if (IsCompressedType())
     {
 #ifdef TABDUMP
-    printf("COLLECTION: READING ComprOrg @ %d\n",
+    printf("COLLECTION: READING ComprOrg @ %d\n",/*ok*/
            poObjBlock->GetCurAddress());
 #endif
         // Compressed coordinate origin
@@ -2076,7 +1986,7 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
         TABSaturatedAdd(m_nMaxX, m_nComprOrgX);
         TABSaturatedAdd(m_nMaxY, m_nComprOrgY);
 #ifdef TABDUMP
-    printf("COLLECTION: ComprOrgX,Y= (%d,%d)\n",
+    printf("COLLECTION: ComprOrgX,Y= (%d,%d)\n",/*ok*/
            m_nComprOrgX, m_nComprOrgY);
 #endif
     }
@@ -2098,7 +2008,6 @@ int TABMAPObjCollection::ReadObj(TABMAPObjectBlock *poObjBlock)
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABMAPObjCollection::WriteObj()
  *
@@ -2169,7 +2078,7 @@ int TABMAPObjCollection::WriteObj(TABMAPObjectBlock *poObjBlock)
     if (IsCompressedType())
     {
 #ifdef TABDUMP
-    printf("COLLECTION: WRITING ComprOrgX,Y= (%d,%d) @ %d\n",
+    printf("COLLECTION: WRITING ComprOrgX,Y= (%d,%d) @ %d\n",/*ok*/
            m_nComprOrgX, m_nComprOrgY, poObjBlock->GetCurAddress());
 #endif
         // Compressed coordinate origin
diff --git a/ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp
index 979fb9c..89277f4 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_maptoolblock.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_maptoolblock.cpp,v 1.8 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_maptoollock.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,58 +28,38 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_maptoolblock.cpp,v $
- * Revision 1.8  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.7  2006-11-28 18:49:08  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.6  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.5  2000/11/15 04:13:50  daniel
- * Fixed writing of TABMAPToolBlock to allocate a new block when full
- *
- * Revision 1.4  2000/02/28 17:03:30  daniel
- * Changed TABMAPBlockManager to TABBinBlockManager
- *
- * Revision 1.3  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.2  1999/09/26 14:59:37  daniel
- * Implemented write support
- *
- * Revision 1.1  1999/09/16 02:39:17  daniel
- * Completed read support for most feature types
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
 
+#include <cstddef>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
+
+CPL_CVSID("$Id: mitab_maptoolblock.cpp 37351 2017-02-12 05:22:20Z goatbar $");
+
 /*=====================================================================
  *                      class TABMAPToolBlock
  *====================================================================*/
 
-#define MAP_TOOL_HEADER_SIZE   8
+static const int MAP_TOOL_HEADER_SIZE = 8;
 
 /**********************************************************************
  *                   TABMAPToolBlock::TABMAPToolBlock()
  *
  * Constructor.
  **********************************************************************/
-TABMAPToolBlock::TABMAPToolBlock(TABAccess eAccessMode /*= TABRead*/):
-    TABRawBinBlock(eAccessMode, TRUE)
-{
-    m_nNextToolBlock = m_numDataBytes = 0;
-
-    m_numBlocksInChain = 1;  // Current block counts as 1
-
-    m_poBlockManagerRef = NULL;
-}
+TABMAPToolBlock::TABMAPToolBlock( TABAccess eAccessMode /*= TABRead*/ ) :
+    TABRawBinBlock(eAccessMode, TRUE),
+    m_numDataBytes(0),
+    m_nNextToolBlock(0),
+    m_numBlocksInChain(1),  // Current block counts as 1
+    m_poBlockManagerRef(NULL)
+{}
 
 /**********************************************************************
  *                   TABMAPToolBlock::~TABMAPToolBlock()
@@ -89,7 +68,6 @@ TABMAPToolBlock::TABMAPToolBlock(TABAccess eAccessMode /*= TABRead*/):
  **********************************************************************/
 TABMAPToolBlock::~TABMAPToolBlock() {}
 
-
 /**********************************************************************
  *                   TABMAPToolBlock::EndOfChain()
  *
@@ -124,13 +102,12 @@ int     TABMAPToolBlock::InitBlockFromData(GByte *pabyBuf,
                                            VSILFILE *fpSrc /* = NULL */,
                                            int nOffset /* = 0 */)
 {
-    int nStatus;
-
     /*-----------------------------------------------------------------
      * First of all, we must call the base class' InitBlockFromData()
      *----------------------------------------------------------------*/
-    nStatus = TABRawBinBlock::InitBlockFromData(pabyBuf, nBlockSize, nSizeUsed,
-                                                bMakeCopy, fpSrc, nOffset);
+    const int nStatus =
+        TABRawBinBlock::InitBlockFromData(pabyBuf, nBlockSize, nSizeUsed,
+                                          bMakeCopy, fpSrc, nOffset);
     if (nStatus != 0)
         return nStatus;
 
@@ -311,7 +288,6 @@ void TABMAPToolBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr)
     m_poBlockManagerRef = poBlockMgr;
 };
 
-
 /**********************************************************************
  *                   TABMAPToolBlock::ReadBytes()
  *
@@ -334,13 +310,12 @@ void TABMAPToolBlock::SetMAPBlockManagerRef(TABBinBlockManager *poBlockMgr)
  **********************************************************************/
 int     TABMAPToolBlock::ReadBytes(int numBytes, GByte *pabyDstBuf)
 {
-    int nStatus;
-
     if (m_pabyBuf &&
         m_nCurPos >= (m_numDataBytes+MAP_TOOL_HEADER_SIZE) &&
         m_nNextToolBlock > 0)
     {
-        if ( (nStatus=GotoByteInFile(m_nNextToolBlock)) != 0)
+        int nStatus = GotoByteInFile(m_nNextToolBlock);
+        if( nStatus != 0 )
         {
             // Failed.... an error has already been reported.
             return nStatus;
@@ -420,7 +395,7 @@ int  TABMAPToolBlock::CheckAvailableSpace(int nToolType)
         nBytesToWrite = 13;
         break;
       default:
-        CPLAssert(FALSE);
+        CPLAssert(false);
     }
 
     if (GetNumUnusedBytes() < nBytesToWrite)
@@ -441,9 +416,6 @@ int  TABMAPToolBlock::CheckAvailableSpace(int nToolType)
     return 0;
 }
 
-
-
-
 /**********************************************************************
  *                   TABMAPToolBlock::Dump()
  *
diff --git a/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp b/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp
index fffcdd5..ad9cfa5 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_middatafile.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_middatafile.cpp,v 1.15 2010-10-12 19:02:40 aboudreault Exp $
  *
  * Name:     mitab_datfile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -28,120 +27,74 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_middatafile.cpp,v $
- * Revision 1.15  2010-10-12 19:02:40  aboudreault
- * Fixed incomplete patch to handle differently indented lines in MIF
- * files (gdal #3694).
- *
- * Revision 1.14  2006-01-27 13:54:06  fwarmerdam
- * fixed memory leak
- *
- * Revision 1.13  2005/10/04 19:36:10  dmorissette
- * Added support for reading collections from MIF files (bug 1126)
- *
- * Revision 1.12  2005/09/29 19:46:55  dmorissette
- * Use "\t" as default delimiter in constructor (Anthony D - bugs 1155 and 37)
- *
- * Revision 1.11  2004/05/20 13:50:06  fwarmerdam
- * Call CPLReadLine(NULL) in Close() method to clean up working buffer.
- *
- * Revision 1.10  2002/04/26 14:16:49  julien
- * Finishing the implementation of Multipoint (support for MIF)
- *
- * Revision 1.9  2002/04/24 18:37:39  daniel
- * Added return statement at end of GetLastLine()
- *
- * Revision 1.8  2002/04/22 13:49:09  julien
- * Add EOF validation in MIDDATAFile::GetLastLine() (Bug 819)
- *
- * Revision 1.7  2001/09/19 14:49:49  warmerda
- * use VSIRewind() instead of rewind()
- *
- * Revision 1.6  2001/01/22 16:03:58  warmerda
- * expanded tabs
- *
- * Revision 1.5  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.4  1999/12/19 17:41:29  daniel
- * Fixed a memory leak
- *
- * Revision 1.3  1999/11/14 17:43:32  stephane
- * Add ifdef to remove CPLError if OGR is define
- *
- * Revision 1.2  1999/11/11 01:22:05  stephane
- * Remove DebugFeature call, Point Reading error, add IsValidFeature() to
- * test correctly if we are on a feature
- *
- * Revision 1.1  1999/11/08 04:16:07  stephane
- * First Revision
- *
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
 
+#include <cstdarg>
+#include <cstddef>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
+
+CPL_CVSID("$Id: mitab_middatafile.cpp 37363 2017-02-12 22:25:59Z goatbar $");
+
 /*=====================================================================
  *                      class MIDDATAFile
  *
  *====================================================================*/
 
-MIDDATAFile::MIDDATAFile()
+MIDDATAFile::MIDDATAFile() :
+    m_fp(NULL),
+    m_pszDelimiter("\t"),  // Encom 2003 (was NULL).
+    m_pszFname(NULL),
+    m_eAccessMode(TABRead),
+    // TODO(schwehr): m_szLastRead({}),
+    // TODO(schwehr): m_szSavedLine({}),
+    m_dfXMultiplier(1.0),
+    m_dfYMultiplier(1.0),
+    m_dfXDisplacement(0.0),
+    m_dfYDisplacement(0.0),
+    m_bEof(FALSE)
 {
-    m_fp = NULL;
     m_szLastRead[0] = '\0';
     m_szSavedLine[0] = '\0';
-    m_pszDelimiter = "\t"; // Encom 2003 (was NULL)
-
-    m_dfXMultiplier = 1.0;
-    m_dfYMultiplier = 1.0;
-    m_dfXDisplacement = 0.0;
-    m_dfYDisplacement = 0.0;
-    m_pszFname = NULL;
-    m_eAccessMode = TABRead;
-    m_bEof = FALSE;
 }
 
-MIDDATAFile::~MIDDATAFile()
-{
-    Close();
-}
+MIDDATAFile::~MIDDATAFile() { Close(); }
 
 void MIDDATAFile::SaveLine(const char *pszLine)
 {
-    if (pszLine == NULL)
+    if(pszLine == NULL)
     {
         m_szSavedLine[0] = '\0';
     }
     else
     {
-        CPLStrlcpy(m_szSavedLine,pszLine,MIDMAXCHAR);
+        CPLStrlcpy(m_szSavedLine, pszLine, MIDMAXCHAR);
     }
 }
 
-const char *MIDDATAFile::GetSavedLine()
-{
-    return m_szSavedLine;
-}
+const char *MIDDATAFile::GetSavedLine() { return m_szSavedLine; }
 
 int MIDDATAFile::Open(const char *pszFname, const char *pszAccess)
 {
-   if (m_fp)
-   {
-       return -1;
-   }
-
-    /*-----------------------------------------------------------------
-     * Validate access mode and make sure we use Text access.
-     *----------------------------------------------------------------*/
-    if (STARTS_WITH_CI(pszAccess, "r"))
+    if(m_fp)
+    {
+        return -1;
+    }
+
+    // Validate access mode and make sure we use Text access.
+    if(STARTS_WITH_CI(pszAccess, "r"))
     {
         m_eAccessMode = TABRead;
         pszAccess = "rt";
     }
-    else if (STARTS_WITH_CI(pszAccess, "w"))
+    else if(STARTS_WITH_CI(pszAccess, "w"))
     {
         m_eAccessMode = TABWrite;
         pszAccess = "wt";
@@ -151,13 +104,11 @@ int MIDDATAFile::Open(const char *pszFname, const char *pszAccess)
         return -1;
     }
 
-    /*-----------------------------------------------------------------
-     * Open file for reading
-     *----------------------------------------------------------------*/
+    // Open file for reading.
     m_pszFname = CPLStrdup(pszFname);
     m_fp = VSIFOpenL(m_pszFname, pszAccess);
 
-    if (m_fp == NULL)
+    if(m_fp == NULL)
     {
         CPLFree(m_pszFname);
         m_pszFname = NULL;
@@ -170,7 +121,7 @@ int MIDDATAFile::Open(const char *pszFname, const char *pszAccess)
 
 int MIDDATAFile::Rewind()
 {
-    if (m_fp == NULL || m_eAccessMode == TABWrite)
+    if(m_fp == NULL || m_eAccessMode == TABWrite)
         return -1;
 
     else
@@ -183,7 +134,7 @@ int MIDDATAFile::Rewind()
 
 int MIDDATAFile::Close()
 {
-    if (m_fp == NULL)
+    if(m_fp == NULL)
         return 0;
 
     // Close file
@@ -191,88 +142,87 @@ int MIDDATAFile::Close()
     m_fp = NULL;
 
     // clear readline buffer.
-    CPLReadLineL( NULL );
+    CPLReadLineL(NULL);
 
     CPLFree(m_pszFname);
     m_pszFname = NULL;
 
     return 0;
-
 }
 
 const char *MIDDATAFile::GetLine()
 {
-    const char *pszLine;
-
-    if (m_eAccessMode == TABRead)
+    if(m_eAccessMode != TABRead)
     {
+        CPLAssert(false);
+        return NULL;
+    }
+
+    const char *pszLine = CPLReadLineL(m_fp);
 
-        pszLine = CPLReadLineL(m_fp);
-
-        if (pszLine == NULL)
-        {
-            SetEof(TRUE);
-            m_szLastRead[0] = '\0';
-        }
-        else
-        {
-            // skip leading spaces and tabs (except is the delimiter is tab)
-            while(pszLine && (*pszLine == ' ' || (*m_pszDelimiter != '\t' && *pszLine == '\t')) )
-                    pszLine++;
-
-            CPLStrlcpy(m_szLastRead,pszLine,MIDMAXCHAR);
-        }
-        //if (pszLine)
-        //  printf("%s\n",pszLine);
-        return pszLine;
+    if(pszLine == NULL)
+    {
+        SetEof(TRUE);
+        m_szLastRead[0] = '\0';
     }
     else
     {
-      CPLAssert(FALSE);
+        // Skip leading spaces and tabs except if the delimiter is tab.
+        while(pszLine && (*pszLine == ' ' ||
+                          (*m_pszDelimiter != '\t' && *pszLine == '\t')))
+            pszLine++;
+
+        CPLStrlcpy(m_szLastRead, pszLine, MIDMAXCHAR);
     }
-    return NULL;
+
+#if DEBUG_VERBOSE
+    if(pszLine)
+        CPLDebug("MITAB", "pszLine: %s", pszLine);
+#endif
+
+    return pszLine;
 }
 
 const char *MIDDATAFile::GetLastLine()
 {
-    // Return NULL if EOF
+    // Return NULL if EOF.
     if(GetEof())
     {
         return NULL;
     }
-    else if (m_eAccessMode == TABRead)
+    if(m_eAccessMode == TABRead)
     {
-        // printf("%s\n",m_szLastRead);
+#if DEBUG_VERBOSE
+        CPLDebug("MITAB", "m_szLastRead: %s", m_szLastRead);
+#endif
         return m_szLastRead;
     }
 
-    // We should never get here (Read/Write mode not implemented)
-    CPLAssert(FALSE);
+    // We should never get here.  Read/Write mode not implemented.
+    CPLAssert(false);
     return NULL;
 }
 
-void MIDDATAFile::WriteLine(const char *pszFormat,...)
+void MIDDATAFile::WriteLine(const char *pszFormat, ...)
 {
     va_list args;
 
-    if (m_eAccessMode == TABWrite  && m_fp)
+    if(m_eAccessMode == TABWrite && m_fp)
     {
         va_start(args, pszFormat);
         CPLString osStr;
-        osStr.vPrintf( pszFormat, args );
-        VSIFWriteL( osStr.c_str(), 1, osStr.size(), m_fp);
+        osStr.vPrintf(pszFormat, args);
+        VSIFWriteL(osStr.c_str(), 1, osStr.size(), m_fp);
         va_end(args);
     }
     else
     {
-        CPLAssert(FALSE);
+        CPLAssert(false);
     }
 }
 
-
-void MIDDATAFile::SetTranslation(double dfXMul,double dfYMul,
-                                 double dfXTran,
-                                 double dfYTran)
+void MIDDATAFile::SetTranslation( double dfXMul,double dfYMul,
+                                  double dfXTran, double dfYTran )
 {
     m_dfXMultiplier = dfXMul;
     m_dfYMultiplier = dfYMul;
@@ -290,27 +240,22 @@ double MIDDATAFile::GetYTrans(double dfY)
     return (dfY * m_dfYMultiplier) + m_dfYDisplacement;
 }
 
-
 GBool MIDDATAFile::IsValidFeature(const char *pszString)
 {
-    char **papszToken ;
+    char **papszToken = CSLTokenizeString(pszString);
 
-    papszToken = CSLTokenizeString(pszString);
-
-    //   printf("%s\n",pszString);
-
-    if (CSLCount(papszToken) == 0)
+    if(CSLCount(papszToken) == 0)
     {
         CSLDestroy(papszToken);
         return FALSE;
     }
 
-    if (EQUAL(papszToken[0],"NONE")      || EQUAL(papszToken[0],"POINT") ||
-        EQUAL(papszToken[0],"LINE")      || EQUAL(papszToken[0],"PLINE") ||
-        EQUAL(papszToken[0],"REGION")    || EQUAL(papszToken[0],"ARC") ||
-        EQUAL(papszToken[0],"TEXT")      || EQUAL(papszToken[0],"RECT") ||
-        EQUAL(papszToken[0],"ROUNDRECT") || EQUAL(papszToken[0],"ELLIPSE") ||
-        EQUAL(papszToken[0],"MULTIPOINT")|| EQUAL(papszToken[0],"COLLECTION") )
+    if(EQUAL(papszToken[0], "NONE") || EQUAL(papszToken[0], "POINT") ||
+       EQUAL(papszToken[0], "LINE") || EQUAL(papszToken[0], "PLINE") ||
+       EQUAL(papszToken[0], "REGION") || EQUAL(papszToken[0], "ARC") ||
+       EQUAL(papszToken[0], "TEXT") || EQUAL(papszToken[0], "RECT") ||
+       EQUAL(papszToken[0], "ROUNDRECT") || EQUAL(papszToken[0], "ELLIPSE") ||
+       EQUAL(papszToken[0], "MULTIPOINT") || EQUAL(papszToken[0], "COLLECTION"))
     {
         CSLDestroy(papszToken);
         return TRUE;
@@ -318,17 +263,8 @@ GBool MIDDATAFile::IsValidFeature(const char *pszString)
 
     CSLDestroy(papszToken);
     return FALSE;
-
 }
 
+GBool MIDDATAFile::GetEof() { return m_bEof; }
 
-GBool MIDDATAFile::GetEof()
-{
-    return m_bEof;
-}
-
-
-void MIDDATAFile::SetEof(GBool bEof)
-{
-    m_bEof = bEof;
-}
+void MIDDATAFile::SetEof(GBool bEof) { m_bEof = bEof; }
diff --git a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
index b6f493b..cf37e67 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_miffile.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_miffile.cpp,v 1.58 2011-09-22 21:57:46 dmorissette Exp $
  *
  * Name:     mitab_miffile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -31,229 +30,78 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_miffile.cpp,v $
- * Revision 1.58  2011-09-22 21:57:46  dmorissette
- *  Fixed problem with tab delimiter used in MIF files (GDAL #4257)
- *
- * Revision 1.57  2010-10-15 12:06:44  aboudreault
- * Fixed crash when trying to get the same mitab mif feature twice (GDAL #3765)
- *
- * Revision 1.56  2010-10-12 19:02:40  aboudreault
- * Fixed incomplete patch to handle differently indented lines in MIF
- * files (gdal #3694).
- *
- * Revision 1.55  2010-10-08 18:50:52  aboudreault
- * Fixed handle differently indented lines in mif files. (GDAL bug #3694)
- *
- * Revision 1.54  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.53  2010-05-07 19:39:19  aboudreault
- * Fixed MIF driver: doesn't create a layer defn at layer creation (bug 2180)
- *
- * Revision 1.52  2010-01-07 20:39:12  aboudreault
- * Added support to handle duplicate field names, Added validation to check if
- * a field name start with a number (bug 2141).
- *
- * Revision 1.51  2009-07-27 14:08:41  dmorissette
- * Fixed dataset version check in AddFieldNative for type TABFDateTime
- *
- * Revision 1.50  2008-12-17 14:55:20  aboudreault
- * Fixed mitab mif/mid importer fails when a Text geometry have an empty
- * text value (bug 1978)
- *
- * Revision 1.49  2008/11/17 22:06:21  aboudreault
- * Added support to use OFTDateTime/OFTDate/OFTTime type when compiled with
- * OGR and fixed reading/writing support for these types.
- *
- * Revision 1.48  2008/09/26 14:40:24  aboudreault
- * Fixed bug: MITAB doesn't support writing DateTime type (bug 1948)
- *
- * Revision 1.47  2008/03/05 20:35:39  dmorissette
- * Replace MITAB 1.x SetFeature() with a CreateFeature() for V2.x (bug 1859)
- *
- * Revision 1.46  2008/02/01 20:30:59  dmorissette
- * Use %.15g instead of %.16g as number precision in .MIF output
- *
- * Revision 1.45  2008/01/29 21:56:39  dmorissette
- * Update dataset version properly for Date/Time/DateTime field types (#1754)
- *
- * Revision 1.44  2008/01/29 20:46:32  dmorissette
- * Added support for v9 Time and DateTime fields (byg 1754)
- *
- * Revision 1.43  2007/09/14 15:35:21  dmorissette
- * Fixed problem with MIF parser being confused by special attribute
- * names (bug 1795)
- *
- * Revision 1.42  2007/06/12 13:52:37  dmorissette
- * Added IMapInfoFile::SetCharset() method (bug 1734)
- *
- * Revision 1.41  2005/10/13 20:12:03  fwarmerdam
- * layers with just regions can't be set as type wkbPolygon because they may
- * have multipolygons (bug GDAL:958)
- *     http://bugzilla.remotesensing.org/show_bug.cgi?id=958
- *
- * Revision 1.40  2005/10/12 14:03:02  fwarmerdam
- * Fixed problem with white space parsing in mitab_miffile.cpp (bug GDAL:954)
- *
- * Revision 1.39  2005/10/04 19:36:10  dmorissette
- * Added support for reading collections from MIF files (bug 1126)
- *
- * Revision 1.38  2004/02/27 21:04:14  fwarmerdam
- * Do not write MIF header if file is readonly - gdal bugzilla 509
- *
- * Revision 1.37  2003/12/19 07:54:50  fwarmerdam
- * write mif header on close if not already written out
- *
- * Revision 1.36  2003/08/13 02:49:02  dmorissette
- * Use tab as default delimiter if not explicitly specified (Anthony D, bug 37)
- *
- * Revision 1.35  2003/01/30 22:42:39  daniel
- * Fixed crash in ParseMIFHeader() when .mif doesn't contain a DATA line
- *
- * Revision 1.34  2002/09/23 12:53:29  warmerda
- * fix memory leak of m_pszIndex
- *
- * Revision 1.33  2002/05/08 15:10:48  julien
- * Implement MIFFile::SetMIFCoordSys in mitab_capi.cpp (Bug 984)
- *
- * Revision 1.32  2002/04/26 14:16:49  julien
- * Finishing the implementation of Multipoint (support for MIF)
- *
- * Revision 1.31  2001/09/19 21:39:15  warmerda
- * get extents efficiently
- *
- * Revision 1.30  2001/09/19 14:31:22  warmerda
- * added m_nPreloadedId to keep track of preloaded line
- *
- * Revision 1.29  2001/09/14 19:14:43  warmerda
- * added attribute query support
- *
- * Revision 1.28  2001/08/10 17:49:01  warmerda
- * fixed a few memory leaks
- *
- * Revision 1.27  2001/03/15 03:57:51  daniel
- * Added implementation for new OGRLayer::GetExtent(), returning data MBR.
- *
- * Revision 1.26  2001/03/09 04:14:19  daniel
- * Fixed problem creating new files with mixed case extensions (e.g. ".Tab")
- *
- * Revision 1.25  2001/03/09 03:51:48  daniel
- * Fixed writing MIF header: missing break; for decimal fields
- *
- * Revision 1.24  2001/02/27 19:59:05  daniel
- * Enabled spatial filter in IMapInfoFile::GetNextFeature(), and avoid
- * unnecessary feature cloning in GetNextFeature() and GetFeature()
- *
- * Revision 1.23  2001/01/23 21:23:42  daniel
- * Added projection bounds lookup table, called from TABFile::SetProjInfo()
- *
- * Revision 1.22  2001/01/22 16:03:58  warmerda
- * expanded tabs
- *
- * Revision 1.21  2000/12/15 05:38:38  daniel
- * Produce Warning instead of an error when nWidth>254 in AddFieldNative()
- *
- * Revision 1.20  2000/11/14 06:15:37  daniel
- * Handle '\t' as spaces in parsing, and fixed GotoFeature() to avoid calling
- * ResetReading() when reading forward.
- *
- * Revision 1.19  2000/07/04 01:50:40  warmerda
- * Removed unprotected debugging printf.
- *
- * Revision 1.18  2000/06/28 00:32:04  warmerda
- * Make GetFeatureCountByType() actually work if bForce is TRUE
- * Collect detailed (by feature type) feature counts in PreParse().
- *
- * Revision 1.17  2000/04/27 15:46:25  daniel
- * Make SetFeatureDefn() use AddFieldNative(), scan field names for invalid
- * chars, and map field width=0 (variable length in OGR) to valid defaults
- *
- * Revision 1.16  2000/03/27 03:37:59  daniel
- * Handle bounds in CoordSys for read and write, + handle point SYMBOL line as
- * optional + fixed reading of bounds in PreParseFile()
- *
- * Revision 1.15  2000/02/28 17:05:06  daniel
- * Added support for index and unique directives for read and write
- *
- * Revision 1.14  2000/01/28 07:32:25  daniel
- * Validate char field width (must be <= 254 chars)
- *
- * Revision 1.13  2000/01/24 19:51:33  warmerda
- * AddFieldNative should not fail for read-only datasets
- *
- * Revision 1.12  2000/01/18 23:13:41  daniel
- * Implemented AddFieldNative()
- *
- * ...
- *
- * Revision 1.1  1999/11/08 04:16:07  stephane
- * First Revision
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "mitab_priv.h"
 #include "mitab_utils.h"
-#include <ctype.h>
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_spatialref.h"
+#include "ogrsf_frmts.h"
+
+CPL_CVSID("$Id: mitab_miffile.cpp 37458 2017-02-25 18:58:53Z rouault $");
 
 /*=====================================================================
  *                      class MIFFile
  *====================================================================*/
 
-
 /**********************************************************************
  *                   MIFFile::MIFFile()
  *
  * Constructor.
  **********************************************************************/
-MIFFile::MIFFile()
-{
-    m_pszFname = NULL;
-    m_nVersion = 300;
-
+MIFFile::MIFFile() :
+    m_pszFname(NULL),
+    m_eAccessMode(TABRead),
+    m_nVersion(300),
     // Tab is default delimiter in MIF spec if not explicitly specified.  Use
     // that by default for read mode. In write mode, we will use "," as
     // delimiter since it's more common than tab (we do this in Open())
-    m_pszDelimiter = CPLStrdup("\t");
-
-    m_pszUnique = NULL;
-    m_pszIndex = NULL;
-    m_pszCoordSys = NULL;
-
-    m_paeFieldType = NULL;
-    m_pabFieldIndexed = NULL;
-    m_pabFieldUnique = NULL;
-
-    m_dfXMultiplier = 1.0;
-    m_dfYMultiplier = 1.0;
-    m_dfXDisplacement = 0.0;
-    m_dfYDisplacement = 0.0;
-
-    m_poMIDFile = NULL;
-    m_poMIFFile = NULL;
-    m_nPreloadedId = 0;
-
-    m_poDefn = NULL;
-    m_poSpatialRef = NULL;
-
+    m_pszDelimiter(CPLStrdup("\t")),
+    m_pszUnique(NULL),
+    m_pszIndex(NULL),
+    m_pszCoordSys(NULL),
+    m_paeFieldType(NULL),
+    m_pabFieldIndexed(NULL),
+    m_pabFieldUnique(NULL),
+    m_dfXMultiplier(1.0),
+    m_dfYMultiplier(1.0),
+    m_dfXDisplacement(0.0),
+    m_dfYDisplacement(0.0),
+    m_dXMin(0),
+    m_dYMin(0),
+    m_dXMax(0),
+    m_dYMax(0),
+    m_bExtentsSet(FALSE),
+    m_nPoints(0),
+    m_nLines(0),
+    m_nRegions(0),
+    m_nTexts(0),
+    m_nPreloadedId(0),
+    m_poMIDFile(NULL),
+    m_poMIFFile(NULL),
+    m_poDefn(NULL),
+    m_poSpatialRef(NULL),
+    m_nFeatureCount(0),
+    m_nWriteFeatureId(-1),
+    m_nAttribute(0),
+    m_bPreParsed(FALSE),
+    m_bHeaderWrote(FALSE)
+{
     m_nCurFeatureId = 0;
-    m_nFeatureCount = 0;
-    m_nWriteFeatureId = -1;
     m_poCurFeature = NULL;
-
-    m_bPreParsed = FALSE;
-    m_nAttribut = 0;
-    m_bHeaderWrote = FALSE;
-    m_nPoints = m_nLines = m_nRegions = m_nTexts = 0;
-
-    m_bExtentsSet = FALSE;
-    m_eAccessMode = TABRead;
-    m_dXMin = 0;
-    m_dYMin = 0;
-    m_dXMax = 0;
-    m_dYMax = 0;
 }
 
 /**********************************************************************
@@ -389,7 +237,7 @@ int MIFFile::Open(const char *pszFname, TABAccess eAccess,
         return -1;
     }
 
-    if ( m_nAttribut > 0 || m_eAccessMode == TABWrite )
+    if ( m_nAttribute > 0 || m_eAccessMode == TABWrite )
     {
         /*-----------------------------------------------------------------
         * Open .MID file
@@ -424,7 +272,7 @@ int MIFFile::Open(const char *pszFname, TABAccess eAccess,
             {
                 CPLDebug("MITAB",
                          "%s is not found, although %d attributes are declared",
-                         pszTmpFname, m_nAttribut);
+                         pszTmpFname, m_nAttribute);
                 delete m_poMIDFile;
                 m_poMIDFile = NULL;
             }
@@ -508,14 +356,6 @@ int MIFFile::Open(const char *pszFname, TABAccess eAccess,
  **********************************************************************/
 int MIFFile::ParseMIFHeader(int* pbIsEmpty)
 {
-    GBool  bColumns = FALSE, bAllColumnsRead =  FALSE;
-    int    nColumns = 0;
-    GBool  bCoordSys = FALSE;
-    char  *pszTmp;
-
-    const char *pszLine;
-    char **papszToken;
-
     *pbIsEmpty = FALSE;
 
     char *pszFeatureClassName = TABGetBasename(m_pszFname);
@@ -524,7 +364,6 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
     // Ref count defaults to 0... set it to 1
     m_poDefn->Reference();
 
-
     if (m_eAccessMode != TABRead)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -532,10 +371,16 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
         return -1;
     }
 
-
     /*-----------------------------------------------------------------
      * Parse header until we find the "Data" line
      *----------------------------------------------------------------*/
+    char **papszToken = NULL;
+    GBool bColumns = FALSE;
+    GBool bAllColumnsRead =  FALSE;
+    int nColumns = 0;
+    GBool bCoordSys = FALSE;
+
+    const char *pszLine = NULL;
     while (((pszLine = m_poMIFFile->GetLine()) != NULL) &&
            ((bAllColumnsRead == FALSE) || !STARTS_WITH_CI(pszLine, "Data")))
     {
@@ -563,7 +408,6 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
               m_nVersion = atoi(papszToken[1]);
 
             CSLDestroy(papszToken);
-
         }
         else if (STARTS_WITH_CI(pszLine, "CHARSET"))
         {
@@ -576,7 +420,6 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
                 m_pszCharset = CPLStrdup(papszToken[1]);
             }
             CSLDestroy(papszToken);
-
         }
         else if (STARTS_WITH_CI(pszLine, "DELIMITER"))
         {
@@ -589,7 +432,6 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
                m_pszDelimiter = CPLStrdup(papszToken[1]);
            }
           CSLDestroy(papszToken);
-
         }
         else if (STARTS_WITH_CI(pszLine, "UNIQUE"))
         {
@@ -609,9 +451,8 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
             m_pszCoordSys = CPLStrdup(pszLine + 9);
 
             // Extract bounds if present
-            char  **papszFields;
-            papszFields = CSLTokenizeStringComplex(m_pszCoordSys, " ,()\t",
-                                                   TRUE, FALSE );
+            char  **papszFields =
+                CSLTokenizeStringComplex(m_pszCoordSys, " ,()\t", TRUE, FALSE );
             int iBounds = CSLFindString( papszFields, "Bounds" );
             if (iBounds >= 0 && iBounds + 4 < CSLCount(papszFields))
             {
@@ -650,7 +491,7 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
             if (CSLCount(papszToken) == 2)
             {
                 nColumns = atoi(papszToken[1]);
-                m_nAttribut = nColumns;
+                m_nAttribute = nColumns;
                 if (nColumns == 0)
                 {
                     // Permit to 0 columns
@@ -661,20 +502,19 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
             else
             {
                 bColumns = FALSE;
-                m_nAttribut = 0;
+                m_nAttribute = 0;
             }
             CSLDestroy(papszToken);
         }
         else if (bCoordSys == TRUE)
         {
-            pszTmp = m_pszCoordSys;
+            char *pszTmp = m_pszCoordSys;
             m_pszCoordSys = CPLStrdup(CPLSPrintf("%s %s",m_pszCoordSys,
                                                  pszLine));
             CPLFree(pszTmp);
             //printf("Reading CoordSys\n");
             // Reading CoordSys
         }
-
     }
 
     if (!bAllColumnsRead)
@@ -731,7 +571,6 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
     }
 
     return 0;
-
 }
 
 /************************************************************************/
@@ -740,12 +579,12 @@ int MIFFile::ParseMIFHeader(int* pbIsEmpty)
 
 int  MIFFile::AddFields(const char *pszLine)
 {
-    char **papszToken;
-    int nStatus = 0,numTok;
+    int nStatus = 0;
 
     CPLAssert(m_bHeaderWrote == FALSE);
-    papszToken = CSLTokenizeStringComplex(pszLine," (,)\t",TRUE,FALSE);
-    numTok = CSLCount(papszToken);
+    char **papszToken =
+        CSLTokenizeStringComplex(pszLine, " (,)\t", TRUE, FALSE);
+    int numTok = CSLCount(papszToken);
 
     if (numTok >= 3 && EQUAL(papszToken[1], "char"))
     {
@@ -877,10 +716,9 @@ GIntBig MIFFile::GetFeatureCount (int bForce)
 void MIFFile::ResetReading()
 
 {
-    const char *pszLine;
-
     m_poMIFFile->Rewind();
 
+    const char *pszLine = NULL;
     while ((pszLine = m_poMIFFile->GetLine()) != NULL)
       if (STARTS_WITH_CI(pszLine, "DATA"))
         break;
@@ -915,7 +753,6 @@ void MIFFile::ResetReading()
 void MIFFile::PreParseFile()
 {
     char **papszToken = NULL;
-    const char *pszLine;
 
     GBool bPLine = FALSE;
     GBool bText = FALSE;
@@ -925,6 +762,7 @@ void MIFFile::PreParseFile()
 
     m_poMIFFile->Rewind();
 
+    const char *pszLine = NULL;
     while ((pszLine = m_poMIFFile->GetLine()) != NULL)
       if (STARTS_WITH_CI(pszLine, "DATA"))
         break;
@@ -951,7 +789,6 @@ void MIFFile::PreParseFile()
                 UpdateExtents(m_poMIFFile->GetXTrans(CPLAtof(papszToken[1])),
                              m_poMIFFile->GetYTrans(CPLAtof(papszToken[2])));
             }
-
         }
         else if (STARTS_WITH_CI(pszLine, "LINE") ||
                  STARTS_WITH_CI(pszLine, "RECT") ||
@@ -1003,7 +840,6 @@ void MIFFile::PreParseFile()
                              m_poMIFFile->GetYTrans(CPLAtof(papszToken[3])));
             }
         }
-
       }
 
     CSLDestroy(papszToken);
@@ -1027,7 +863,6 @@ void MIFFile::PreParseFile()
     }
 
     m_bPreParsed = TRUE;
-
 }
 
 /**********************************************************************
@@ -1039,7 +874,6 @@ void MIFFile::PreParseFile()
  **********************************************************************/
 int MIFFile::WriteMIFHeader()
 {
-    int iField;
     GBool bFound;
 
     if (m_eAccessMode != TABWrite)
@@ -1069,7 +903,8 @@ int MIFFile::WriteMIFHeader()
         m_poMIFFile->WriteLine("Delimiter \"%s\"\n", m_pszDelimiter);
 
     bFound = FALSE;
-    for(iField=0; iField<m_poDefn->GetFieldCount(); iField++)
+
+    for( int iField = 0; iField<m_poDefn->GetFieldCount(); iField++ )
     {
         if (m_pabFieldUnique[iField])
         {
@@ -1084,7 +919,7 @@ int MIFFile::WriteMIFHeader()
         m_poMIFFile->WriteLine("\n");
 
     bFound = FALSE;
-    for(iField=0; iField<m_poDefn->GetFieldCount(); iField++)
+    for( int iField = 0; iField < m_poDefn->GetFieldCount(); iField++ )
     {
         if (m_pabFieldIndexed[iField])
         {
@@ -1117,10 +952,9 @@ int MIFFile::WriteMIFHeader()
 
     m_poMIFFile->WriteLine("Columns %d\n", m_poDefn->GetFieldCount());
 
-    for(iField=0; iField<m_poDefn->GetFieldCount(); iField++)
+    for( int iField = 0; iField < m_poDefn->GetFieldCount(); iField++ )
     {
-        OGRFieldDefn *poFieldDefn;
-        poFieldDefn = m_poDefn->GetFieldDefn(iField);
+        OGRFieldDefn *poFieldDefn = m_poDefn->GetFieldDefn(iField);
 
         switch(m_paeFieldType[iField])
         {
@@ -1320,7 +1154,7 @@ int MIFFile::GotoFeature(int nFeatureId)
 
 GBool MIFFile::NextFeature()
 {
-    const char *pszLine;
+    const char *pszLine = NULL;
     while ((pszLine = m_poMIFFile->GetLine()) != NULL)
     {
         if (m_poMIFFile->IsValidFeature(pszLine))
@@ -1350,8 +1184,6 @@ GBool MIFFile::NextFeature()
  **********************************************************************/
 TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
 {
-    const char *pszLine;
-
     if (m_eAccessMode != TABRead)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -1378,10 +1210,10 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
         return NULL;
     }
 
-
     /*-----------------------------------------------------------------
      * Create new feature object of the right type
      *----------------------------------------------------------------*/
+    const char *pszLine = NULL;
     if ((pszLine = m_poMIFFile->GetLastLine()) != NULL)
     {
         // Delete previous feature... we'll start we a clean one.
@@ -1398,8 +1230,8 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
         else if (STARTS_WITH_CI(pszLine, "POINT"))
         {
             // Special case, we need to know two lines to decide the type
-            char **papszToken;
-            papszToken = CSLTokenizeString2(pszLine, " \t", CSLT_HONOURSTRINGS);
+            char **papszToken =
+                CSLTokenizeString2(pszLine, " \t", CSLT_HONOURSTRINGS);
 
             if (CSLCount(papszToken) !=3)
             {
@@ -1438,7 +1270,6 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
                         return NULL;
                         break;
                     }
-
                 }
             }
             CSLDestroy(papszToken);
@@ -1531,17 +1362,16 @@ TABFeature *MIFFile::GetFeatureRef(GIntBig nFeatureId)
        it to a geometry none */
     if (m_poCurFeature->GetFeatureClass() == TABFCText)
     {
-       TABFeature *poTmpFeature;
        TABText *poTextFeature = (TABText*)m_poCurFeature;
        if (strlen(poTextFeature->GetTextString()) == 0)
        {
-          poTmpFeature = new TABFeature(m_poDefn);
-          for( int i = 0; i < m_poDefn->GetFieldCount(); i++ )
-          {
-             poTmpFeature->SetField( i, m_poCurFeature->GetRawFieldRef( i ) );
-          }
-          delete m_poCurFeature;
-          m_poCurFeature = poTmpFeature;
+           TABFeature *poTmpFeature = new TABFeature(m_poDefn);
+           for( int i = 0; i < m_poDefn->GetFieldCount(); i++ )
+           {
+               poTmpFeature->SetField( i, m_poCurFeature->GetRawFieldRef( i ) );
+           }
+           delete m_poCurFeature;
+           m_poCurFeature = poTmpFeature;
        }
     }
 
@@ -1608,7 +1438,6 @@ OGRErr MIFFile::CreateFeature(TABFeature *poFeature)
         nFeatureId = ++ m_nWriteFeatureId;
     }
 
-
     /*-----------------------------------------------------------------
      * Write geometry to the .Mif file
      *----------------------------------------------------------------*/
@@ -1635,8 +1464,6 @@ OGRErr MIFFile::CreateFeature(TABFeature *poFeature)
     return OGRERR_NONE;
 }
 
-
-
 /**********************************************************************
  *                   MIFFile::GetLayerDefn()
  *
@@ -1670,9 +1497,6 @@ OGRFeatureDefn *MIFFile::GetLayerDefn()
 int MIFFile::SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
                          TABFieldType *paeMapInfoNativeFieldTypes /* =NULL */)
 {
-    int numFields;
-    int nStatus = 0;
-
     /*-----------------------------------------------------------------
      * Check that call happens at the right time in dataset's life.
      *----------------------------------------------------------------*/
@@ -1695,9 +1519,10 @@ int MIFFile::SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
     /*-----------------------------------------------------------------
      * Copy field information
      *----------------------------------------------------------------*/
-    numFields = poFeatureDefn->GetFieldCount();
+    const int numFields = poFeatureDefn->GetFieldCount();
+    int nStatus = 0;
 
-    for(int iField=0; iField<numFields; iField++)
+    for( int iField = 0; iField<numFields; iField++ )
     {
         TABFieldType eMapInfoType;
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
@@ -1761,11 +1586,10 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                             int nWidth /*=0*/, int nPrecision /*=0*/,
                             GBool bIndexed /*=FALSE*/, GBool bUnique/*=FALSE*/, int bApproxOK )
 {
-    OGRFieldDefn *poFieldDefn;
     char *pszCleanName = NULL;
     int nStatus = 0;
     char szNewFieldName[31+1]; /* 31 is the max characters for a field name*/
-    int nRenameNum = 1;
+    unsigned int nRenameNum = 1;
 
     /*-----------------------------------------------------------------
      * Check that call happens at the right time in dataset's life.
@@ -1824,14 +1648,20 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                   pszName );
     }
 
-    strncpy(szNewFieldName, pszCleanName, 31);
-    szNewFieldName[31] = '\0';
+    strncpy(szNewFieldName, pszCleanName, sizeof(szNewFieldName)-1);
+    szNewFieldName[sizeof(szNewFieldName)-1] = '\0';
 
     while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 10)
-      snprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s_%.1d", pszCleanName, nRenameNum++ );
+    {
+      CPLsnprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s_%.1u", pszCleanName, nRenameNum );
+      nRenameNum ++;
+    }
 
     while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 100)
-      snprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s%.2d", pszCleanName, nRenameNum++ );
+    {
+      CPLsnprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s%.2u", pszCleanName, nRenameNum );
+      nRenameNum ++;
+    }
 
     if (m_poDefn->GetFieldIndex(szNewFieldName) >= 0)
     {
@@ -1848,11 +1678,10 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                 szNewFieldName );
     }
 
-
     /*-----------------------------------------------------------------
      * Map MapInfo native types to OGR types
      *----------------------------------------------------------------*/
-    poFieldDefn = NULL;
+    OGRFieldDefn *poFieldDefn = NULL;
 
     switch(eMapInfoType)
     {
@@ -1902,7 +1731,7 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                                    OFTString);
 #endif
         poFieldDefn->SetWidth(10);
-        m_nVersion = MAX(m_nVersion, 450);
+        m_nVersion = std::max(m_nVersion, 450);
         break;
       case TABFTime:
         /*-------------------------------------------------
@@ -1915,7 +1744,7 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                                    OFTString);
 #endif
         poFieldDefn->SetWidth(9);
-        m_nVersion = MAX(m_nVersion, 900);
+        m_nVersion = std::max(m_nVersion, 900);
         break;
       case TABFDateTime:
         /*-------------------------------------------------
@@ -1929,7 +1758,7 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                                    OFTString);
 #endif
         poFieldDefn->SetWidth(19);
-        m_nVersion = MAX(m_nVersion, 900);
+        m_nVersion = std::max(m_nVersion, 900);
         break;
       case TABFLogical:
         /*-------------------------------------------------
@@ -1974,7 +1803,6 @@ int MIFFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     return nStatus;
 }
 
-
 /**********************************************************************
  *                   MIFFile::GetNativeFieldType()
  *
@@ -2036,7 +1864,6 @@ GBool MIFFile::IsFieldUnique( int nFieldId )
     return m_pabFieldUnique[nFieldId];
 }
 
-
 /************************************************************************/
 /*                       MIFFile::SetSpatialRef()                       */
 /************************************************************************/
@@ -2053,10 +1880,9 @@ int MIFFile::SetSpatialRef( OGRSpatialReference * poSpatialRef )
         CPLFree(pszCoordSys);
     }
 
-    return( m_pszCoordSys != NULL );
+    return m_pszCoordSys != NULL;
 }
 
-
 /************************************************************************/
 /*                      MIFFile::SetMIFCoordSys()                       */
 /************************************************************************/
@@ -2064,8 +1890,7 @@ int MIFFile::SetSpatialRef( OGRSpatialReference * poSpatialRef )
 int MIFFile::SetMIFCoordSys(const char * pszMIFCoordSys)
 
 {
-    char        **papszFields, *pszCoordSys;
-    int         iBounds;
+    char *pszCoordSys = NULL;
 
     // Extract the word 'COORDSYS' if present
     if (STARTS_WITH_CI(pszMIFCoordSys, "COORDSYS") )
@@ -2078,9 +1903,9 @@ int MIFFile::SetMIFCoordSys(const char * pszMIFCoordSys)
     }
 
     // Extract bounds if present
-    papszFields = CSLTokenizeStringComplex(pszCoordSys, " ,()\t",
-                                           TRUE, FALSE );
-    iBounds = CSLFindString( papszFields, "Bounds" );
+    char **papszFields =
+        CSLTokenizeStringComplex(pszCoordSys, " ,()\t", TRUE, FALSE );
+    int iBounds = CSLFindString( papszFields, "Bounds" );
     if (iBounds >= 0 && iBounds + 4 < CSLCount(papszFields))
     {
         m_dXMin = CPLAtof(papszFields[++iBounds]);
@@ -2102,7 +1927,7 @@ int MIFFile::SetMIFCoordSys(const char * pszMIFCoordSys)
     m_pszCoordSys = CPLStrdup(pszCoordSys);
     CPLFree(pszCoordSys);
 
-    return( m_pszCoordSys != NULL );
+    return m_pszCoordSys != NULL;
 }
 
 /************************************************************************/
@@ -2154,8 +1979,8 @@ void MIFFile::UpdateExtents(double dfX, double dfY)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int MIFFile::SetBounds(double dXMin, double dYMin,
-                       double dXMax, double dYMax)
+int MIFFile::SetBounds( double dXMin, double dYMin,
+                        double dXMax, double dYMax )
 {
     if (m_eAccessMode != TABWrite)
     {
@@ -2173,7 +1998,6 @@ int MIFFile::SetBounds(double dXMin, double dYMin,
     return 0;
 }
 
-
 /**********************************************************************
  *                   MIFFile::GetFeatureCountByType()
  *
diff --git a/ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp b/ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp
index 3502e1c..f55751e 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_ogr_datasource.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_ogr_datasource.cpp,v 1.12 2007-03-22 20:01:36 dmorissette Exp $
  *
  * Name:     mitab_ogr_datasource.cpp
  * Project:  MapInfo Mid/Mif, Tab ogr support
@@ -29,50 +28,11 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_ogr_datasource.cpp,v $
- * Revision 1.12  2007-03-22 20:01:36  dmorissette
- * Added SPATIAL_INDEX_MODE=QUICK creation option (MITAB bug 1669)
- *
- * Revision 1.11  2006/01/27 14:27:35  fwarmerdam
- * fixed ogr bounds setting problems (bug 1198)
- *
- * Revision 1.9  2004/10/15 01:52:30  fwarmerdam
- * ModifiedICreateLayer() to use  -1000,-1000,1000,1000 bounds for GEOGCS
- * much like in mitab_bounds.cpp.  This ensures that geographic files in
- * the range 0-360 works as well as -180 to 180.
- *
- * Revision 1.8  2004/07/07 15:42:46  fwarmerdam
- * fixed up some single layer creation issues
- *
- * Revision 1.7  2004/02/27 21:06:03  fwarmerdam
- * Better support for "single file" creation ... don't allow other layers to
- * be created.  But *do* single file to satisfy the first layer creation request
- * made.  Also, allow creating a datasource "on" an existing directory.
- *
- * Revision 1.6  2003/03/21 14:20:49  warmerda
- * fixed email
- *
- * Revision 1.5  2002/02/08 16:52:16  warmerda
- * added support for FORMAT=MIF option for creating layers
- *
- * Revision 1.4  2001/02/06 22:13:54  warmerda
- * fixed memory leak in OGRTABDataSource::ICreateLayer()
- *
- * Revision 1.3  2001/01/22 16:03:58  warmerda
- * expanded tabs
- *
- * Revision 1.2  2000/07/04 01:46:23  warmerda
- * Avoid warnings on unused arguments.
- *
- * Revision 1.1  2000/01/26 18:17:09  warmerda
- * New
- *
  **********************************************************************/
 
 #include "mitab_ogr_driver.h"
 
+CPL_CVSID("$Id: mitab_ogr_datasource.cpp 37386 2017-02-15 17:19:05Z goatbar $");
 
 /*=======================================================================
  *                 OGRTABDataSource
@@ -86,21 +46,19 @@
 /*                         OGRTABDataSource()                           */
 /************************************************************************/
 
-OGRTABDataSource::OGRTABDataSource()
-
-{
-    m_pszName = NULL;
-    m_pszDirectory = NULL;
-    m_nLayerCount = 0;
-    m_papoLayers = NULL;
-    m_papszOptions = NULL;
-    m_bCreateMIF = FALSE;
-    m_bSingleFile = FALSE;
-    m_bSingleLayerAlreadyCreated = FALSE;
-    m_bQuickSpatialIndexMode = -1;
-    m_nBlockSize = 512;
-    m_bUpdate = FALSE;
-}
+OGRTABDataSource::OGRTABDataSource() :
+    m_pszName(NULL),
+    m_pszDirectory(NULL),
+    m_nLayerCount(0),
+    m_papoLayers(NULL),
+    m_papszOptions(NULL),
+    m_bCreateMIF(FALSE),
+    m_bSingleFile(FALSE),
+    m_bSingleLayerAlreadyCreated(FALSE),
+    m_bQuickSpatialIndexMode(-1),
+    m_bUpdate(FALSE),
+    m_nBlockSize(512)
+{}
 
 /************************************************************************/
 /*                         ~OGRTABDataSource()                          */
@@ -109,14 +67,14 @@ OGRTABDataSource::OGRTABDataSource()
 OGRTABDataSource::~OGRTABDataSource()
 
 {
-    CPLFree( m_pszName );
-    CPLFree( m_pszDirectory );
+    CPLFree(m_pszName);
+    CPLFree(m_pszDirectory);
 
     for( int i = 0; i < m_nLayerCount; i++ )
         delete m_papoLayers[i];
 
-    CPLFree( m_papoLayers );
-    CSLDestroy( m_papszOptions );
+    CPLFree(m_papoLayers);
+    CSLDestroy(m_papszOptions);
 }
 
 /************************************************************************/
@@ -128,55 +86,53 @@ OGRTABDataSource::~OGRTABDataSource()
 int OGRTABDataSource::Create( const char * pszName, char **papszOptions )
 
 {
-    VSIStatBufL  sStat;
-    const char *pszOpt;
+    CPLAssert(m_pszName == NULL);
 
-    CPLAssert( m_pszName == NULL );
-
-    m_pszName = CPLStrdup( pszName );
-    m_papszOptions = CSLDuplicate( papszOptions );
+    m_pszName = CPLStrdup(pszName);
+    m_papszOptions = CSLDuplicate(papszOptions);
     m_bUpdate = TRUE;
 
-    if( (pszOpt=CSLFetchNameValue(papszOptions,"FORMAT")) != NULL
-        && EQUAL(pszOpt, "MIF") )
+    const char *pszOpt = CSLFetchNameValue(papszOptions, "FORMAT");
+    if( pszOpt != NULL && EQUAL(pszOpt, "MIF") )
         m_bCreateMIF = TRUE;
-    else if( EQUAL(CPLGetExtension(pszName),"mif")
-             || EQUAL(CPLGetExtension(pszName),"mid") )
+    else if( EQUAL(CPLGetExtension(pszName),"mif") ||
+             EQUAL(CPLGetExtension(pszName),"mid") )
         m_bCreateMIF = TRUE;
 
-    if( (pszOpt=CSLFetchNameValue(papszOptions,"SPATIAL_INDEX_MODE")) != NULL )
+    if( (pszOpt = CSLFetchNameValue(papszOptions,"SPATIAL_INDEX_MODE")) != NULL )
     {
-        if ( EQUAL(pszOpt, "QUICK") )
+        if( EQUAL(pszOpt, "QUICK") )
             m_bQuickSpatialIndexMode = TRUE;
-        else if ( EQUAL(pszOpt, "OPTIMIZED") )
+        else if( EQUAL(pszOpt, "OPTIMIZED") )
             m_bQuickSpatialIndexMode = FALSE;
     }
 
     m_nBlockSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKSIZE", "512"));
 
-/* -------------------------------------------------------------------- */
-/*      Create a new empty directory.                                   */
-/* -------------------------------------------------------------------- */
+
+    // Create a new empty directory.
+    VSIStatBufL sStat;
+
     if( strlen(CPLGetExtension(pszName)) == 0 )
     {
         if( VSIStatL( pszName, &sStat ) == 0 )
         {
             if( !VSI_ISDIR(sStat.st_mode) )
             {
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                          "Attempt to create dataset named %s,\n"
-                          "but that is an existing file.\n",
-                          pszName );
+                CPLError(CE_Failure, CPLE_OpenFailed,
+                         "Attempt to create dataset named %s,\n"
+                         "but that is an existing file.",
+                         pszName);
                 return FALSE;
             }
         }
         else
         {
-            if( VSIMkdir( pszName, 0755 ) != 0 )
+            if( VSIMkdir(pszName, 0755) != 0 )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "Unable to create directory %s.\n",
-                          pszName );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Unable to create directory %s.",
+                         pszName);
                 return FALSE;
             }
         }
@@ -184,17 +140,16 @@ int OGRTABDataSource::Create( const char * pszName, char **papszOptions )
         m_pszDirectory = CPLStrdup(pszName);
     }
 
-/* -------------------------------------------------------------------- */
-/*      Create a new single file.                                       */
-/* -------------------------------------------------------------------- */
+
+    // Create a new single file.
     else
     {
-        IMapInfoFile    *poFile;
+        IMapInfoFile *poFile = NULL;
 
         if( m_bCreateMIF )
         {
             poFile = new MIFFile;
-            if( poFile->Open( m_pszName, TABWrite, FALSE ) != 0 )
+            if( poFile->Open(m_pszName, TABWrite, FALSE) != 0 )
             {
                 delete poFile;
                 return FALSE;
@@ -202,8 +157,8 @@ int OGRTABDataSource::Create( const char * pszName, char **papszOptions )
         }
         else
         {
-            TABFile* poTabFile = new TABFile;
-            if( poTabFile->Open( m_pszName, TABWrite, FALSE, m_nBlockSize ) != 0 )
+            TABFile *poTabFile = new TABFile;
+            if( poTabFile->Open(m_pszName, TABWrite, FALSE, m_nBlockSize) != 0 )
             {
                 delete poTabFile;
                 return FALSE;
@@ -212,10 +167,10 @@ int OGRTABDataSource::Create( const char * pszName, char **papszOptions )
         }
 
         m_nLayerCount = 1;
-        m_papoLayers = (IMapInfoFile **) CPLMalloc(sizeof(void*));
+        m_papoLayers = static_cast<IMapInfoFile **>(CPLMalloc(sizeof(void *)));
         m_papoLayers[0] = poFile;
 
-        m_pszDirectory = CPLStrdup( CPLGetPath(pszName) );
+        m_pszDirectory = CPLStrdup(CPLGetPath(pszName));
         m_bSingleFile = TRUE;
     }
 
@@ -228,85 +183,79 @@ int OGRTABDataSource::Create( const char * pszName, char **papszOptions )
 /*      Open an existing file, or directory of files.                   */
 /************************************************************************/
 
-int OGRTABDataSource::Open( GDALOpenInfo* poOpenInfo, int bTestOpen )
+int OGRTABDataSource::Open( GDALOpenInfo *poOpenInfo, int bTestOpen )
 
 {
-    CPLAssert( m_pszName == NULL );
+    CPLAssert(m_pszName == NULL);
 
-    m_pszName = CPLStrdup( poOpenInfo->pszFilename );
-    m_bUpdate = (poOpenInfo->eAccess == GA_Update );
+    m_pszName = CPLStrdup(poOpenInfo->pszFilename);
+    m_bUpdate = poOpenInfo->eAccess == GA_Update;
 
-/* -------------------------------------------------------------------- */
-/*      If it is a file, try to open as a Mapinfo file.                 */
-/* -------------------------------------------------------------------- */
+    // If it is a file, try to open as a Mapinfo file.
     if( !poOpenInfo->bIsDirectory )
     {
-        IMapInfoFile    *poFile;
-
-        poFile = IMapInfoFile::SmartOpen( m_pszName, m_bUpdate, bTestOpen );
+        IMapInfoFile *poFile =
+            IMapInfoFile::SmartOpen(m_pszName, m_bUpdate, bTestOpen);
         if( poFile == NULL )
             return FALSE;
 
-        poFile->SetDescription( poFile->GetName() );
+        poFile->SetDescription(poFile->GetName());
 
         m_nLayerCount = 1;
-        m_papoLayers = (IMapInfoFile **) CPLMalloc(sizeof(void*));
+        m_papoLayers = static_cast<IMapInfoFile **>(CPLMalloc(sizeof(void *)));
         m_papoLayers[0] = poFile;
 
-        m_pszDirectory = CPLStrdup( CPLGetPath(m_pszName) );
+        m_pszDirectory = CPLStrdup(CPLGetPath(m_pszName));
 
         m_bSingleFile = TRUE;
         m_bSingleLayerAlreadyCreated = TRUE;
     }
 
-/* -------------------------------------------------------------------- */
-/*      Otherwise, we need to scan the whole directory for files        */
-/*      ending in .tab or .mif.                                         */
-/* -------------------------------------------------------------------- */
+    // Otherwise, we need to scan the whole directory for files
+    // ending in .tab or .mif.
     else
     {
-        char    **papszFileList = VSIReadDir( m_pszName );
+        char **papszFileList = VSIReadDir(m_pszName);
 
-        m_pszDirectory = CPLStrdup( m_pszName );
+        m_pszDirectory = CPLStrdup(m_pszName);
 
         for( int iFile = 0;
              papszFileList != NULL && papszFileList[iFile] != NULL;
              iFile++ )
         {
-            IMapInfoFile *poFile;
-            const char  *pszExtension = CPLGetExtension(papszFileList[iFile]);
-            char        *pszSubFilename;
+            const char *pszExtension = CPLGetExtension(papszFileList[iFile]);
 
-            if( !EQUAL(pszExtension,"tab") && !EQUAL(pszExtension,"mif") )
+            if( !EQUAL(pszExtension, "tab") && !EQUAL(pszExtension, "mif") )
                 continue;
 
-            pszSubFilename = CPLStrdup(
-                CPLFormFilename( m_pszDirectory, papszFileList[iFile], NULL ));
+            char *pszSubFilename = CPLStrdup(
+                CPLFormFilename(m_pszDirectory, papszFileList[iFile], NULL));
 
-            poFile = IMapInfoFile::SmartOpen( pszSubFilename, m_bUpdate, bTestOpen );
-            CPLFree( pszSubFilename );
+            IMapInfoFile *poFile =
+                IMapInfoFile::SmartOpen(pszSubFilename, m_bUpdate, bTestOpen);
+            CPLFree(pszSubFilename);
 
             if( poFile == NULL )
             {
-                CSLDestroy( papszFileList );
+                CSLDestroy(papszFileList);
                 return FALSE;
             }
             poFile->SetDescription( poFile->GetName() );
 
             m_nLayerCount++;
-            m_papoLayers = (IMapInfoFile **)
-                CPLRealloc(m_papoLayers,sizeof(void*)*m_nLayerCount);
+            m_papoLayers = static_cast<IMapInfoFile **>(
+                CPLRealloc(m_papoLayers,sizeof(void *) * m_nLayerCount));
             m_papoLayers[m_nLayerCount-1] = poFile;
         }
 
-        CSLDestroy( papszFileList );
+        CSLDestroy(papszFileList);
 
         if( m_nLayerCount == 0 )
         {
             if( !bTestOpen )
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                          "No mapinfo files found in directory %s.\n",
-                          m_pszDirectory );
+                CPLError(CE_Failure, CPLE_OpenFailed,
+                         "No mapinfo files found in directory %s.",
+                         m_pszDirectory);
 
             return FALSE;
         }
@@ -346,16 +295,12 @@ OGRLayer *OGRTABDataSource::GetLayer( int iLayer )
 /************************************************************************/
 
 OGRLayer *
-OGRTABDataSource::ICreateLayer( const char * pszLayerName,
-                               OGRSpatialReference *poSRSIn,
-                               OGRwkbGeometryType /* eGeomTypeIn */,
-                               char ** papszOptions )
+OGRTABDataSource::ICreateLayer( const char *pszLayerName,
+                                OGRSpatialReference *poSRSIn,
+                                OGRwkbGeometryType /* eGeomTypeIn */,
+                                char **papszOptions )
 
 {
-    IMapInfoFile        *poFile;
-    char                *pszFullFilename;
-    const char          *pszOpt = NULL;
-
     if( !m_bUpdate )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -363,17 +308,19 @@ OGRTABDataSource::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
 
-/* -------------------------------------------------------------------- */
-/*      If it's a single file mode file, then we may have already       */
-/*      instantiated the low level layer.   We would just need to       */
-/*      reset the coordinate system and (potentially) bounds.           */
-/* -------------------------------------------------------------------- */
+    // If it's a single file mode file, then we may have already
+    // instantiated the low level layer.   We would just need to
+    // reset the coordinate system and (potentially) bounds.
+    IMapInfoFile *poFile = NULL;
+    char *pszFullFilename = NULL;
+
     if( m_bSingleFile )
     {
         if( m_bSingleLayerAlreadyCreated )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to create new layers in this single file dataset.");
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Unable to create new layers in this single file dataset.");
             return NULL;
         }
 
@@ -386,90 +333,93 @@ OGRTABDataSource::ICreateLayer( const char * pszLayerName,
     {
         if( m_bCreateMIF )
         {
-            pszFullFilename = CPLStrdup( CPLFormFilename( m_pszDirectory,
-                                                          pszLayerName, "mif" ) );
+            pszFullFilename =
+                CPLStrdup(CPLFormFilename(m_pszDirectory, pszLayerName, "mif"));
 
             poFile = new MIFFile;
 
-            if( poFile->Open( pszFullFilename, TABWrite, FALSE ) != 0 )
+            if( poFile->Open(pszFullFilename, TABWrite, FALSE) != 0 )
             {
-                CPLFree( pszFullFilename );
+                CPLFree(pszFullFilename);
                 delete poFile;
                 return NULL;
             }
         }
         else
         {
-            pszFullFilename = CPLStrdup( CPLFormFilename( m_pszDirectory,
-                                                          pszLayerName, "tab" ) );
+            pszFullFilename =
+                CPLStrdup(CPLFormFilename(m_pszDirectory, pszLayerName, "tab"));
 
-            TABFile* poTABFile = new TABFile;
-            if( poTABFile->Open( pszFullFilename, TABWrite, FALSE, m_nBlockSize ) != 0 )
+            TABFile *poTABFile = new TABFile;
+            if( poTABFile->Open(pszFullFilename, TABWrite, FALSE, m_nBlockSize) != 0 )
             {
-                CPLFree( pszFullFilename );
+                CPLFree(pszFullFilename);
                 delete poTABFile;
                 return NULL;
             }
             poFile = poTABFile;
         }
 
-
         m_nLayerCount++;
-        m_papoLayers = (IMapInfoFile **)
-            CPLRealloc(m_papoLayers,sizeof(void*)*m_nLayerCount);
+        m_papoLayers = static_cast<IMapInfoFile **>(
+            CPLRealloc(m_papoLayers,sizeof(void*)*m_nLayerCount));
         m_papoLayers[m_nLayerCount-1] = poFile;
 
-        CPLFree( pszFullFilename );
+        CPLFree(pszFullFilename);
     }
 
-    poFile->SetDescription( poFile->GetName() );
+    poFile->SetDescription(poFile->GetName());
 
-/* -------------------------------------------------------------------- */
-/*      Assign the coordinate system (if provided) and set              */
-/*      reasonable bounds.                                              */
-/* -------------------------------------------------------------------- */
+    // Assign the coordinate system (if provided) and set
+    // reasonable bounds.
     if( poSRSIn != NULL )
     {
-        poFile->SetSpatialRef( poSRSIn );
+        poFile->SetSpatialRef(poSRSIn);
         // SetSpatialRef() has cloned the passed geometry
-        poFile->GetLayerDefn()->GetGeomFieldDefn(0)->SetSpatialRef(poFile->GetSpatialRef());
+        poFile->GetLayerDefn()->GetGeomFieldDefn(0)->SetSpatialRef(
+            poFile->GetSpatialRef());
     }
 
     // Pull out the bounds if supplied
-    if( (pszOpt=CSLFetchNameValue(papszOptions, "BOUNDS")) != NULL ) {
+    const char *pszOpt = NULL;
+    if( (pszOpt = CSLFetchNameValue(papszOptions, "BOUNDS")) != NULL ) {
         double dfBounds[4];
         if( CPLsscanf(pszOpt, "%lf,%lf,%lf,%lf", &dfBounds[0],
                                           &dfBounds[1],
                                           &dfBounds[2],
                                           &dfBounds[3]) != 4 )
         {
-            CPLError( CE_Failure, CPLE_IllegalArg,
-                        "Invalid BOUNDS parameter, expected min_x,min_y,max_x,max_y\n" );
+            CPLError(
+                CE_Failure, CPLE_IllegalArg,
+                "Invalid BOUNDS parameter, expected min_x,min_y,max_x,max_y");
         }
         else
         {
-            poFile->SetBounds( dfBounds[0], dfBounds[1], dfBounds[2], dfBounds[3] );
+            poFile->SetBounds(dfBounds[0], dfBounds[1], dfBounds[2],
+                              dfBounds[3]);
         }
     }
 
     if( !poFile->IsBoundsSet() && !m_bCreateMIF )
     {
-        if( poSRSIn != NULL && poSRSIn->GetRoot() != NULL
-            && EQUAL(poSRSIn->GetRoot()->GetValue(),"GEOGCS") )
-            poFile->SetBounds( -1000, -1000, 1000, 1000 );
+        if( poSRSIn != NULL && poSRSIn->GetRoot() != NULL &&
+            EQUAL(poSRSIn->GetRoot()->GetValue(),"GEOGCS") )
+            poFile->SetBounds(-1000, -1000, 1000, 1000);
         else
-            poFile->SetBounds( -30000000, -15000000, 30000000, 15000000 );
+            poFile->SetBounds(-30000000, -15000000, 30000000, 15000000);
     }
 
-    if (m_bQuickSpatialIndexMode == TRUE && poFile->SetQuickSpatialIndexMode(TRUE) != 0)
+    if(m_bQuickSpatialIndexMode == TRUE &&
+       poFile->SetQuickSpatialIndexMode(TRUE) != 0)
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Setting Quick Spatial Index Mode failed.");
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Setting Quick Spatial Index Mode failed.");
     }
-    else if (m_bQuickSpatialIndexMode == FALSE && poFile->SetQuickSpatialIndexMode(FALSE) != 0)
+    else if(m_bQuickSpatialIndexMode == FALSE &&
+            poFile->SetQuickSpatialIndexMode(FALSE) != 0)
     {
-        CPLError( CE_Warning, CPLE_AppDefined,
-                  "Setting Normal Spatial Index Mode failed.");
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "Setting Normal Spatial Index Mode failed.");
     }
 
     return poFile;
@@ -479,11 +429,13 @@ OGRTABDataSource::ICreateLayer( const char * pszLayerName,
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRTABDataSource::TestCapability( const char * pszCap )
+int OGRTABDataSource::TestCapability( const char *pszCap )
 
 {
-    if( EQUAL(pszCap,ODsCCreateLayer) )
+    if( EQUAL(pszCap, ODsCCreateLayer) )
         return m_bUpdate && (!m_bSingleFile || !m_bSingleLayerAlreadyCreated);
+    else if( EQUAL(pszCap, ODsCRandomLayerWrite) )
+        return m_bUpdate;
     else
         return FALSE;
 }
@@ -497,34 +449,31 @@ char **OGRTABDataSource::GetFileList()
     VSIStatBufL sStatBuf;
     CPLStringList osList;
 
-    if( VSIStatL( m_pszName, &sStatBuf ) == 0 &&
-        VSI_ISDIR(sStatBuf.st_mode) )
+    if( VSIStatL(m_pszName, &sStatBuf) == 0 && VSI_ISDIR(sStatBuf.st_mode) )
     {
         static const char * const apszExtensions[] =
             { "mif", "mid", "tab", "map", "ind", "dat", "id", NULL };
-        char **papszDirEntries = VSIReadDir( m_pszName );
-        int  iFile;
+        char **papszDirEntries = VSIReadDir(m_pszName);
 
-        for( iFile = 0;
+        for( int iFile = 0;
              papszDirEntries != NULL && papszDirEntries[iFile] != NULL;
              iFile++ )
         {
-            if( CSLFindString( (char **) apszExtensions,
-                               CPLGetExtension(papszDirEntries[iFile])) != -1)
+            if( CSLFindString((char **)apszExtensions,
+                              CPLGetExtension(papszDirEntries[iFile])) != -1)
             {
-                osList.AddString( CPLFormFilename( m_pszName,
-                                            papszDirEntries[iFile],
-                                            NULL ) );
+                osList.AddString(
+                    CPLFormFilename(m_pszName, papszDirEntries[iFile], NULL));
             }
         }
 
-        CSLDestroy( papszDirEntries );
+        CSLDestroy(papszDirEntries);
     }
     else
     {
-        static const char* const apszMIFExtensions[] = { "mif", "mid", NULL };
-        static const char* const apszTABExtensions[] = { "tab", "map", "ind", "dat", "id", NULL };
-        const char* const * papszExtensions;
+        static const char *const apszMIFExtensions[] = { "mif", "mid", NULL };
+        static const char *const apszTABExtensions[] = { "tab", "map", "ind", "dat", "id", NULL };
+        const char *const *papszExtensions = NULL;
         if( EQUAL(CPLGetExtension(m_pszName), "mif") ||
             EQUAL(CPLGetExtension(m_pszName), "mid") )
         {
@@ -534,21 +483,21 @@ char **OGRTABDataSource::GetFileList()
         {
             papszExtensions = apszTABExtensions;
         }
-        const char* const * papszIter = papszExtensions;
+        const char *const *papszIter = papszExtensions;
         while( *papszIter )
         {
-            const char *pszFile = CPLResetExtension(m_pszName, *papszIter );
-            if( VSIStatL( pszFile, &sStatBuf ) != 0)
+            const char *pszFile = CPLResetExtension(m_pszName, *papszIter);
+            if( VSIStatL(pszFile, &sStatBuf) != 0)
             {
                 pszFile = CPLResetExtension(m_pszName, CPLString(*papszIter).toupper() );
-                if( VSIStatL( pszFile, &sStatBuf ) != 0)
+                if( VSIStatL(pszFile, &sStatBuf) != 0)
                 {
                     pszFile = NULL;
                 }
             }
             if( pszFile )
-                osList.AddString( pszFile );
-            papszIter ++;
+                osList.AddString(pszFile);
+            papszIter++;
         }
     }
     return osList.StealList();
diff --git a/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp b/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp
index 041c504..fbf9d42 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_ogr_driver.cpp,v 1.11 2005-05-21 03:15:18 fwarmerdam Exp $
  *
  * Name:     mitab_ogr_driver.cpp
  * Project:  MapInfo Mid/Mif, Tab ogr support
@@ -29,64 +28,24 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_ogr_driver.cpp,v $
- * Revision 1.11  2005-05-21 03:15:18  fwarmerdam
- * Removed unused stat buffer.
- *
- * Revision 1.10  2004/02/27 21:06:03  fwarmerdam
- * Better support for "single file" creation ... don't allow other layers to
- * be created.  But *do* single file to satisfy the first layer creation request
- * made.  Also, allow creating a datasource "on" an existing directory.
- *
- * Revision 1.9  2003/03/20 15:57:46  warmerda
- * Added delete datasource support
- *
- * Revision 1.8  2001/01/22 16:03:58  warmerda
- * expanded tabs
- *
- * Revision 1.7  2000/01/26 18:17:00  warmerda
- * reimplement OGR driver
- *
- * Revision 1.6  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.5  1999/12/15 17:05:24  warmerda
- * Only create OGRTABDataSource if SmartOpen() result is non-NULL.
- *
- * Revision 1.4  1999/12/15 16:28:17  warmerda
- * fixed a few type problems
- *
- * Revision 1.3  1999/12/14 02:22:29  daniel
- * Merged TAB+MIF DataSource/Driver into ane using IMapInfoFile class
- *
- * Revision 1.2  1999/11/12 02:44:36  stephane
- * added comment, change Register name.
- *
- * Revision 1.1  1999/11/08 21:05:51  svillene
- * first revision
- *
- * Revision 1.1  1999/11/08 04:16:07  stephane
- * First Revision
- *
  **********************************************************************/
 
 #include "mitab_ogr_driver.h"
 
+CPL_CVSID("$Id: mitab_ogr_driver.cpp 37365 2017-02-12 23:25:40Z goatbar $");
 
 /************************************************************************/
 /*                  OGRTABDriverIdentify()                              */
 /************************************************************************/
 
-static int OGRTABDriverIdentify( GDALOpenInfo* poOpenInfo )
+static int OGRTABDriverIdentify( GDALOpenInfo *poOpenInfo )
 
 {
-    /* Files not ending with .tab, .mif or .mid are not handled by this driver */
+    // Files not ending with .tab, .mif or .mid are not handled by this driver.
     if( !poOpenInfo->bStatOK )
         return FALSE;
     if( poOpenInfo->bIsDirectory )
-        return -1; /* unsure */
+        return -1;  // Unsure.
     if( poOpenInfo->fpL == NULL )
         return FALSE;
     if (EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MIF") ||
@@ -98,7 +57,7 @@ static int OGRTABDriverIdentify( GDALOpenInfo* poOpenInfo )
     {
         for( int i = 0; i < poOpenInfo->nHeaderBytes; i++)
         {
-            const char* pszLine = (const char*)poOpenInfo->pabyHeader + i;
+            const char *pszLine = (const char *)poOpenInfo->pabyHeader + i;
             if (STARTS_WITH_CI(pszLine, "Fields"))
                 return TRUE;
             else if (STARTS_WITH_CI(pszLine, "create view"))
@@ -108,7 +67,7 @@ static int OGRTABDriverIdentify( GDALOpenInfo* poOpenInfo )
         }
     }
 #ifdef DEBUG
-    /* For AFL, so that .cur_input is detected as the archive filename */
+    // For AFL, so that .cur_input is detected as the archive filename.
     if( !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
         EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") )
     {
@@ -122,11 +81,9 @@ static int OGRTABDriverIdentify( GDALOpenInfo* poOpenInfo )
 /*                  OGRTABDriver::Open()                                */
 /************************************************************************/
 
-static GDALDataset *OGRTABDriverOpen( GDALOpenInfo* poOpenInfo )
+static GDALDataset *OGRTABDriverOpen( GDALOpenInfo *poOpenInfo )
 
 {
-    OGRTABDataSource    *poDS;
-
     if( OGRTABDriverIdentify(poOpenInfo) == FALSE )
     {
         return NULL;
@@ -140,53 +97,49 @@ static GDALDataset *OGRTABDriverOpen( GDALOpenInfo* poOpenInfo )
     }
 
 #ifdef DEBUG
-    /* For AFL, so that .cur_input is detected as the archive filename */
+    // For AFL, so that .cur_input is detected as the archive filename.
     if( poOpenInfo->fpL != NULL &&
         !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
         EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") )
     {
-        GDALOpenInfo oOpenInfo( (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
-                                poOpenInfo->nOpenFlags );
+        GDALOpenInfo oOpenInfo(
+            (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
+            poOpenInfo->nOpenFlags);
         oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions;
         return OGRTABDriverOpen(&oOpenInfo);
     }
 #endif
 
-    poDS = new OGRTABDataSource();
-    if( poDS->Open( poOpenInfo, TRUE ) )
-        return poDS;
-    else
+    OGRTABDataSource *poDS = new OGRTABDataSource();
+    if( !poDS->Open(poOpenInfo, TRUE) )
     {
         delete poDS;
         return NULL;
     }
-}
 
+    return poDS;
+}
 
 /************************************************************************/
 /*                              Create()                                */
 /************************************************************************/
 
-static GDALDataset *OGRTABDriverCreate( const char * pszName,
+static GDALDataset *OGRTABDriverCreate( const char *pszName,
                                         CPL_UNUSED int nBands,
                                         CPL_UNUSED int nXSize,
                                         CPL_UNUSED int nYSize,
                                         CPL_UNUSED GDALDataType eDT,
                                         char **papszOptions )
 {
-    OGRTABDataSource *poDS;
-
-/* -------------------------------------------------------------------- */
-/*      Try to create the data source.                                  */
-/* -------------------------------------------------------------------- */
-    poDS = new OGRTABDataSource();
-    if( !poDS->Create( pszName, papszOptions ) )
+    // Try to create the data source.
+    OGRTABDataSource *poDS = new OGRTABDataSource();
+    if( !poDS->Create(pszName, papszOptions) )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -196,7 +149,7 @@ static GDALDataset *OGRTABDriverCreate( const char * pszName,
 static CPLErr OGRTABDriverDelete( const char *pszDataSource )
 
 {
-    GDALDataset* poDS;
+    GDALDataset *poDS = NULL;
     {
         // Make sure that the file opened by GDALOpenInfo is closed
         // when the object goes out of scope
@@ -205,22 +158,21 @@ static CPLErr OGRTABDriverDelete( const char *pszDataSource )
     }
     if( poDS == NULL )
         return CE_Failure;
-    char** papszFileList = poDS->GetFileList();
+    char **papszFileList = poDS->GetFileList();
     delete poDS;
 
-    char** papszIter = papszFileList;
+    char **papszIter = papszFileList;
     while( papszIter && *papszIter )
     {
-        VSIUnlink( *papszIter );
-        papszIter ++;
+        VSIUnlink(*papszIter);
+        papszIter++;
     }
     CSLDestroy(papszFileList);
 
     VSIStatBufL sStatBuf;
-    if( VSIStatL( pszDataSource, &sStatBuf ) == 0 &&
-        VSI_ISDIR(sStatBuf.st_mode) )
+    if( VSIStatL(pszDataSource, &sStatBuf) == 0 && VSI_ISDIR(sStatBuf.st_mode) )
     {
-        VSIRmdir( pszDataSource );
+        VSIRmdir(pszDataSource);
     }
 
     return CE_None;
@@ -230,7 +182,7 @@ static CPLErr OGRTABDriverDelete( const char *pszDataSource )
 /*                          OGRTABDriverUnload()                        */
 /************************************************************************/
 
-static void OGRTABDriverUnload(CPL_UNUSED GDALDriver* poDriver)
+static void OGRTABDriverUnload(CPL_UNUSED GDALDriver *poDriver)
 {
     MITABFreeCoordSysTable();
 }
@@ -239,29 +191,26 @@ static void OGRTABDriverUnload(CPL_UNUSED GDALDriver* poDriver)
 /*              RegisterOGRTAB()                                        */
 /************************************************************************/
 
-extern "C"
-{
-
 void RegisterOGRTAB()
 
 {
-    if( GDALGetDriverByName( "MapInfo File" ) != NULL )
+    if( GDALGetDriverByName("MapInfo File") != NULL )
         return;
 
     GDALDriver *poDriver = new GDALDriver();
 
-    poDriver->SetDescription( "MapInfo File" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "MapInfo File" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "tab mif mid" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mitab.html" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    poDriver->SetDescription("MapInfo File");
+    poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
+    poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "MapInfo File");
+    poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "tab mif mid");
+    poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC, "drv_mitab.html");
+    poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
+    poDriver->SetMetadataItem(GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
 "  <Option name='BOUNDS' type='string' description='Custom bounds. Expect format is xmin,ymin,xmax,ymax'/>"
 "</LayerCreationOptionList>");
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
 "<CreationOptionList>"
 "  <Option name='FORMAT' type='string-select' description='type of MapInfo format'>"
 "    <Value>MIF</Value>"
@@ -274,8 +223,8 @@ void RegisterOGRTAB()
 "  <Option name='BLOCKSIZE' type='int' description='.map block size' min='512' max='32256' default='512'/>"
 "</CreationOptionList>");
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
-                               "Integer Real String Date DateTime Time" );
+    poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
+                              "Integer Real String Date DateTime Time");
 
     poDriver->pfnOpen = OGRTABDriverOpen;
     poDriver->pfnIdentify = OGRTABDriverIdentify;
@@ -283,7 +232,5 @@ void RegisterOGRTAB()
     poDriver->pfnDelete = OGRTABDriverDelete;
     poDriver->pfnUnloadDriver = OGRTABDriverUnload;
 
-    GetGDALDriverManager()->RegisterDriver( poDriver );
-}
-
+    GetGDALDriverManager()->RegisterDriver(poDriver);
 }
diff --git a/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h b/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h
index dc21e71..c2e9c32 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h
+++ b/ogr/ogrsf_frmts/mitab/mitab_ogr_driver.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab_ogr_driver.h,v 1.14 2007-03-22 20:01:36 dmorissette Exp $
+ * $Id: mitab_ogr_driver.h 37335 2017-02-09 14:29:57Z goatbar $
  *
  * Name:     mitab_ogr_drive.h
  * Project:  Mid/mif tab ogr support
@@ -28,53 +28,6 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_ogr_driver.h,v $
- * Revision 1.14  2007-03-22 20:01:36  dmorissette
- * Added SPATIAL_INDEX_MODE=QUICK creation option (MITAB bug 1669)
- *
- * Revision 1.13  2004/07/07 16:11:39  fwarmerdam
- * fixed up some single layer creation issues
- *
- * Revision 1.12  2004/02/27 21:06:03  fwarmerdam
- * Better support for "single file" creation ... don't allow other layers to
- * be created.  But *do* single file to satisfy the first layer creation request
- * made.  Also, allow creating a datasource "on" an existing directory.
- *
- * Revision 1.11  2003/03/20 15:57:46  warmerda
- * Added delete datasource support
- *
- * Revision 1.10  2002/02/08 16:52:16  warmerda
- * added support for FORMAT=MIF option for creating layers
- *
- * Revision 1.9  2001/09/14 03:22:58  warmerda
- * added RegisterOGRTAB() prototype
- *
- * Revision 1.8  2001/01/22 16:03:59  warmerda
- * expanded tabs
- *
- * Revision 1.7  2000/01/26 18:17:00  warmerda
- * reimplement OGR driver
- *
- * Revision 1.6  2000/01/15 22:30:44  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.5  1999/12/15 16:28:17  warmerda
- * fixed a few type problems
- *
- * Revision 1.4  1999/12/15 16:15:05  warmerda
- * Avoid unused parameter warnings.
- *
- * Revision 1.3  1999/12/14 02:23:05  daniel
- * Merged TAB+MIF DataSource/Driver into one using IMapInfoFile class
- *
- * Revision 1.2  1999/11/12 02:44:36  stephane
- * added comment, change Register name.
- *
- * Revision 1.1  1999/11/08 21:05:51  svillene
- * first revision
- *
  **********************************************************************/
 
 #include "mitab.h"
@@ -113,17 +66,17 @@ class OGRTABDataSource : public OGRDataSource
     int         Open( GDALOpenInfo* poOpenInfo, int bTestOpen );
     int         Create( const char *pszName, char ** papszOptions );
 
-    const char  *GetName() { return m_pszName; }
-    int          GetLayerCount();
-    OGRLayer    *GetLayer( int );
-    int          TestCapability( const char * );
+    const char  *GetName() override { return m_pszName; }
+    int          GetLayerCount() override;
+    OGRLayer    *GetLayer( int ) override;
+    int          TestCapability( const char * ) override;
 
     OGRLayer    *ICreateLayer(const char *,
                              OGRSpatialReference * = NULL,
                              OGRwkbGeometryType = wkbUnknown,
-                             char ** = NULL );
+                             char ** = NULL ) override;
 
-    char        **GetFileList();
+    char        **GetFileList() override;
 };
 
 void CPL_DLL RegisterOGRTAB();
diff --git a/ogr/ogrsf_frmts/mitab/mitab_priv.h b/ogr/ogrsf_frmts/mitab/mitab_priv.h
index 9ebca58..1eccde0 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_priv.h
+++ b/ogr/ogrsf_frmts/mitab/mitab_priv.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab_priv.h,v 1.55 2010-01-07 20:39:12 aboudreault Exp $
+ * $Id: mitab_priv.h 37762 2017-03-18 15:23:31Z rouault $
  *
  * Name:     mitab_priv.h
  * Project:  MapInfo TAB Read/Write library
@@ -28,153 +28,6 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_priv.h,v $
- * Revision 1.55  2010-01-07 20:39:12  aboudreault
- * Added support to handle duplicate field names, Added validation to check if a field name start with a number (bug 2141)
- *
- * Revision 1.54  2008-11-27 20:50:23  aboudreault
- * Improved support for OGR date/time types. New Read/Write methods (bug 1948)
- * Added support of OGR date/time types for MIF features.
- *
- * Revision 1.53  2008/03/05 20:35:39  dmorissette
- * Replace MITAB 1.x SetFeature() with a CreateFeature() for V2.x (bug 1859)
- *
- * Revision 1.52  2008/02/20 21:35:30  dmorissette
- * Added support for V800 COLLECTION of large objects (bug 1496)
- *
- * Revision 1.51  2008/02/05 22:22:48  dmorissette
- * Added support for TAB_GEOM_V800_MULTIPOINT (bug 1496)
- *
- * Revision 1.50  2008/02/01 19:36:31  dmorissette
- * Initial support for V800 REGION and MULTIPLINE (bug 1496)
- *
- * Revision 1.49  2008/01/29 20:46:32  dmorissette
- * Added support for v9 Time and DateTime fields (byg 1754)
- *
- * Revision 1.48  2007/10/09 17:43:16  fwarmerdam
- * Remove static variables that interfere with reentrancy. (GDAL #1883)
- *
- * Revision 1.47  2007/06/12 12:50:39  dmorissette
- * Use Quick Spatial Index by default until bug 1732 is fixed (broken files
- * produced by current coord block splitting technique).
- *
- * Revision 1.46  2007/06/11 14:52:31  dmorissette
- * Return a valid m_nCoordDatasize value for Collection objects to prevent
- * trashing of collection data during object splitting (bug 1728)
- *
- * Revision 1.45  2007/03/21 21:15:56  dmorissette
- * Added SetQuickSpatialIndexMode() which generates a non-optimal spatial
- * index but results in faster write time (bug 1669)
- *
- * Revision 1.44  2007/02/22 18:35:53  dmorissette
- * Fixed problem writing collections where MITAB was sometimes trying to
- * read past EOF in write mode (bug 1657).
- *
- * Revision 1.43  2006/11/28 18:49:08  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.42  2006/11/20 20:05:58  dmorissette
- * First pass at improving generation of spatial index in .map file (bug 1585)
- * New methods for insertion and splitting in the spatial index are done.
- * Also implemented a method to dump the spatial index to .mif/.mid
- * Still need to implement splitting of TABMapObjectBlock to get optimal
- * results.
- *
- * Revision 1.41  2006/09/05 23:05:08  dmorissette
- * Added TABMAPFile::DumpSpatialIndex() (bug 1585)
- *
- * Revision 1.40  2005/10/06 19:15:31  dmorissette
- * Collections: added support for reading/writing pen/brush/symbol ids and
- * for writing collection objects to .TAB/.MAP (bug 1126)
- *
- * Revision 1.39  2005/10/04 15:44:31  dmorissette
- * First round of support for Collection objects. Currently supports reading
- * from .TAB/.MAP and writing to .MIF. Still lacks symbol support and write
- * support. (Based in part on patch and docs from Jim Hope, bug 1126)
- *
- * Revision 1.38  2005/03/22 23:24:54  dmorissette
- * Added support for datum id in .MAP header (bug 910)
- *
- * Revision 1.37  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.36  2003/08/12 23:17:21  dmorissette
- * Added reading of v500+ coordsys affine params (Anthony D. - Encom)
- *
- * Revision 1.35  2003/01/18 20:25:44  daniel
- * Increased MIDMAXCHAR value to 10000
- *
- * Revision 1.34  2002/04/25 16:05:24  julien
- * Disabled the overflow warning in SetCoordFilter() by adding bIgnoreOverflow
- * variable in Coordsys2Int of the TABMAPFile class and TABMAPHeaderBlock class
- *
- * Revision 1.33  2002/04/22 13:49:09  julien
- * Add EOF validation in MIDDATAFile::GetLastLine() (Bug 819)
- *
- * Revision 1.32  2002/03/26 19:27:43  daniel
- * Got rid of tabs in source
- *
- * Revision 1.31  2002/03/26 01:48:40  daniel
- * Added Multipoint object type (V650)
- *
- * Revision 1.30  2002/02/22 20:44:51  julien
- * Prevent infinite loop with TABRelation by suppress the m_poCurFeature object
- * from the class and setting it in the calling function and add GetFeature in
- * the class. (bug 706)
- *
- * Revision 1.29  2001/11/19 15:07:54  daniel
- * Added TABMAPObjNone to handle the case of TAB_GEOM_NONE
- *
- * Revision 1.28  2001/11/17 21:54:06  daniel
- * Made several changes in order to support writing objects in 16 bits
- * coordinate format. New TABMAPObjHdr-derived classes are used to hold
- * object info in mem until block is full.
- *
- * Revision 1.27  2001/09/18 20:33:52  warmerda
- * fixed case of spatial search on file with just one object block
- *
- * Revision 1.26  2001/09/14 03:23:55  warmerda
- * Substantial upgrade to support spatial queries using spatial indexes
- *
- * Revision 1.25  2001/05/01 18:28:10  daniel
- * Fixed default BRUSH, should be BRUSH(1,0,16777215).
- *
- * Revision 1.24  2001/05/01 03:39:51  daniel
- * Added SetLastPtr() to TABBinBlockManager.
- *
- * Revision 1.23  2001/03/15 03:57:51  daniel
- * Added implementation for new OGRLayer::GetExtent(), returning data MBR.
- *
- * Revision 1.22  2000/11/23 21:11:07  daniel
- * OOpps... VC++ didn't like the way TABPenDef, etc. were initialized
- *
- * Revision 1.21  2000/11/23 20:47:46  daniel
- * Use MI defaults for Pen, Brush, Font, Symbol instead of all zeros
- *
- * Revision 1.20  2000/11/15 04:13:50  daniel
- * Fixed writing of TABMAPToolBlock to allocate a new block when full
- *
- * Revision 1.19  2000/11/13 22:19:30  daniel
- * Added TABINDNode::UpdateCurChildEntry()
- *
- * Revision 1.18  2000/05/19 06:45:25  daniel
- * Modified generation of spatial index to split index nodes and produce a
- * more balanced tree.
- *
- * Revision 1.17  2000/03/01 00:30:03  daniel
- * Completed support for joined tables
- *
- * Revision 1.16  2000/02/28 16:53:23  daniel
- * Added support for indexed, unique, and for new V450 object types
- *
- * ...
- *
- * Revision 1.1  1999/07/12 04:18:25  daniel
- * Initial checkin
- *
  **********************************************************************/
 
 #ifndef MITAB_PRIV_H_INCLUDED_
@@ -237,7 +90,6 @@ typedef enum
     ((numSegments) > TAB_REGION_PLINE_450_MAX_SEGMENTS || \
      ((numSegments)*3 + numVerticesTotal) > TAB_REGION_PLINE_450_MAX_VERTICES )
 
-
 /*---------------------------------------------------------------------
  * Codes for the known MapInfo Geometry types
  *--------------------------------------------------------------------*/
@@ -299,7 +151,6 @@ typedef enum
      ((nGeomType) < TAB_GEOM_MULTIPOINT_C)   ? 450:         \
      ((nGeomType) < TAB_GEOM_UNKNOWN1_C)     ? 650: 800 )
 
-
 /*---------------------------------------------------------------------
  * struct TABMAPIndexEntry - Entries found in type 1 blocks of .MAP files
  *
@@ -320,7 +171,6 @@ typedef struct TABMAPIndexEntry_t
 
 #define TAB_MAX_ENTRIES_INDEX_BLOCK     ((TAB_MAX_BLOCK_SIZE-4)/20)
 
-
 /*---------------------------------------------------------------------
  * TABVertex
  *--------------------------------------------------------------------*/
@@ -429,7 +279,6 @@ typedef struct TABProjInfo_t
 
 } TABProjInfo;
 
-
 /*---------------------------------------------------------------------
  * TABPenDef - Pen definition information
  *--------------------------------------------------------------------*/
@@ -590,7 +439,6 @@ class TABMAPObjHdrWithCoord : public TABMAPObjHdr
      */
 };
 
-
 class TABMAPObjNone CPL_FINAL : public TABMAPObjHdr
 {
   public:
@@ -598,13 +446,12 @@ class TABMAPObjNone CPL_FINAL : public TABMAPObjHdr
     TABMAPObjNone() {};
     virtual ~TABMAPObjNone() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *) {return 0;};
+    virtual int WriteObj(TABMAPObjectBlock *) override {return 0;};
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *) {return 0;};
+    virtual int ReadObj(TABMAPObjectBlock *) override {return 0;};
 };
 
-
 class TABMAPObjPoint: public TABMAPObjHdr
 {
   public:
@@ -616,10 +463,10 @@ class TABMAPObjPoint: public TABMAPObjHdr
         m_nX(0), m_nY(0), m_nSymbolId(0) {};
     virtual ~TABMAPObjPoint() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 };
 
 class TABMAPObjFontPoint: public TABMAPObjPoint
@@ -644,10 +491,10 @@ class TABMAPObjFontPoint: public TABMAPObjPoint
         {};
     virtual ~TABMAPObjFontPoint() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 };
 
 class TABMAPObjCustomPoint CPL_FINAL : public TABMAPObjPoint
@@ -664,13 +511,12 @@ class TABMAPObjCustomPoint CPL_FINAL : public TABMAPObjPoint
         {};
     virtual ~TABMAPObjCustomPoint() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 };
 
-
 class TABMAPObjLine CPL_FINAL : public TABMAPObjHdr
 {
   public:
@@ -689,10 +535,10 @@ class TABMAPObjLine CPL_FINAL : public TABMAPObjHdr
         {};
     virtual ~TABMAPObjLine() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 };
 
 class TABMAPObjPLine CPL_FINAL : public TABMAPObjHdrWithCoord
@@ -719,10 +565,10 @@ class TABMAPObjPLine CPL_FINAL : public TABMAPObjHdrWithCoord
         {};
     virtual ~TABMAPObjPLine() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 };
 
 class TABMAPObjRectEllipse CPL_FINAL : public TABMAPObjHdr
@@ -741,10 +587,10 @@ class TABMAPObjRectEllipse CPL_FINAL : public TABMAPObjHdr
         {};
     virtual ~TABMAPObjRectEllipse() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 };
 
 class TABMAPObjArc CPL_FINAL : public TABMAPObjHdr
@@ -769,13 +615,12 @@ class TABMAPObjArc CPL_FINAL : public TABMAPObjHdr
         {};
     virtual ~TABMAPObjArc() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 };
 
-
 class TABMAPObjText CPL_FINAL : public TABMAPObjHdrWithCoord
 {
   public:
@@ -818,13 +663,12 @@ class TABMAPObjText CPL_FINAL : public TABMAPObjHdrWithCoord
         {};
     virtual ~TABMAPObjText() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 };
 
-
 class TABMAPObjMultiPoint CPL_FINAL : public TABMAPObjHdrWithCoord
 {
   public:
@@ -845,10 +689,10 @@ class TABMAPObjMultiPoint CPL_FINAL : public TABMAPObjHdrWithCoord
         {};
     virtual ~TABMAPObjMultiPoint() {};
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 };
 
 class TABMAPObjCollection CPL_FINAL : public TABMAPObjHdrWithCoord
@@ -885,10 +729,10 @@ class TABMAPObjCollection CPL_FINAL : public TABMAPObjHdrWithCoord
     virtual ~TABMAPObjCollection()
     {}
 
-    virtual int WriteObj(TABMAPObjectBlock *);
+    virtual int WriteObj(TABMAPObjectBlock *) override;
 
 //  protected:
-    virtual int ReadObj(TABMAPObjectBlock *);
+    virtual int ReadObj(TABMAPObjectBlock *) override;
 
   private:
     // private copy ctor and assignment operator to prevent shallow copying
@@ -991,7 +835,7 @@ class TABRawBinBlock
 #ifdef DEBUG
     virtual void Dump(FILE *fpOut = NULL);
 #endif
-    void        DumpBytes(GInt32 nValue, int nOffset=0, FILE *fpOut=NULL);
+    static void        DumpBytes(GInt32 nValue, int nOffset=0, FILE *fpOut=NULL);
 
     int         GotoByteRel(int nOffset);
     int         GotoByteInBlock(int nOffset);
@@ -1006,16 +850,24 @@ class TABRawBinBlock
 
     virtual int ReadBytes(int numBytes, GByte *pabyDstBuf);
     GByte       ReadByte();
+    // cppcheck-suppress functionStatic
     GInt16      ReadInt16();
+    // cppcheck-suppress functionStatic
     GInt32      ReadInt32();
+    // cppcheck-suppress functionStatic
     float       ReadFloat();
+    // cppcheck-suppress functionStatic
     double      ReadDouble();
 
     virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf);
     int         WriteByte(GByte byValue);
+    // cppcheck-suppress functionStatic
     int         WriteInt16(GInt16 n16Value);
+    // cppcheck-suppress functionStatic
     int         WriteInt32(GInt32 n32Value);
+    // cppcheck-suppress functionStatic
     int         WriteFloat(float fValue);
+    // cppcheck-suppress functionStatic
     int         WriteDouble(double dValue);
     int         WriteZeros(int nBytesToWrite);
     int         WritePaddedString(int nFieldSize, const char *pszString);
@@ -1027,7 +879,6 @@ class TABRawBinBlock
     GByte *     GetCurDataPtr() { return (m_pabyBuf + m_nCurPos); } ;
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABMAPHeaderBlock
  *
@@ -1043,18 +894,18 @@ class TABMAPHeaderBlock CPL_FINAL : public TABRawBinBlock
     TABProjInfo m_sProj;
 
   public:
-    TABMAPHeaderBlock(TABAccess eAccessMode = TABRead);
-    ~TABMAPHeaderBlock();
+    explicit TABMAPHeaderBlock(TABAccess eAccessMode = TABRead);
+    virtual ~TABMAPHeaderBlock();
 
-    virtual int CommitToFile();
+    virtual int CommitToFile() override;
 
     virtual int InitBlockFromData(GByte *pabyBuf,
                                   int nBlockSize, int nSizeUsed,
                                   GBool bMakeCopy = TRUE,
-                                  VSILFILE *fpSrc = NULL, int nOffset = 0);
-    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0);
+                                  VSILFILE *fpSrc = NULL, int nOffset = 0) override;
+    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0) override;
 
-    virtual int GetBlockClass() { return TABMAP_HEADER_BLOCK; };
+    virtual int GetBlockClass() override { return TABMAP_HEADER_BLOCK; };
 
     int         Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY);
     int         Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY,
@@ -1074,7 +925,7 @@ class TABMAPHeaderBlock CPL_FINAL : public TABRawBinBlock
     int         SetProjInfo(TABProjInfo *psProjInfo);
 
 #ifdef DEBUG
-    virtual void Dump(FILE *fpOut = NULL);
+    virtual void Dump(FILE *fpOut = NULL) override;
 #endif
 
     // Instead of having over 30 get/set methods, we'll make all data
@@ -1155,17 +1006,17 @@ class TABMAPIndexBlock CPL_FINAL : public TABRawBinBlock
     int         GetMaxEntries() const { return ((m_nBlockSize-4)/20); }
 
   public:
-    TABMAPIndexBlock(TABAccess eAccessMode = TABRead);
-    ~TABMAPIndexBlock();
+    explicit TABMAPIndexBlock(TABAccess eAccessMode = TABRead);
+    virtual ~TABMAPIndexBlock();
 
     virtual int InitBlockFromData(GByte *pabyBuf,
                                   int nBlockSize, int nSizeUsed,
                                   GBool bMakeCopy = TRUE,
-                                  VSILFILE *fpSrc = NULL, int nOffset = 0);
-    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0);
-    virtual int CommitToFile();
+                                  VSILFILE *fpSrc = NULL, int nOffset = 0) override;
+    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0) override;
+    virtual int CommitToFile() override;
 
-    virtual int GetBlockClass() { return TABMAP_INDEX_BLOCK; };
+    virtual int GetBlockClass() override { return TABMAP_INDEX_BLOCK; };
 
     void        UnsetCurChild();
 
@@ -1228,7 +1079,7 @@ class TABMAPIndexBlock CPL_FINAL : public TABRawBinBlock
                                     GInt32 nNewEntryYMax,
                                     int &nSeed1, int &nSeed2);
 #ifdef DEBUG
-    virtual void Dump(FILE *fpOut = NULL);
+    virtual void Dump(FILE *fpOut = NULL) override;
 #endif
 
 };
@@ -1262,17 +1113,17 @@ class TABMAPObjectBlock CPL_FINAL : public TABRawBinBlock
     int         m_bLockCenter;
 
   public:
-    TABMAPObjectBlock(TABAccess eAccessMode = TABRead);
-    ~TABMAPObjectBlock();
+    explicit TABMAPObjectBlock(TABAccess eAccessMode = TABRead);
+    virtual ~TABMAPObjectBlock();
 
-    virtual int CommitToFile();
+    virtual int CommitToFile() override;
     virtual int InitBlockFromData(GByte *pabyBuf,
                                   int nBlockSize, int nSizeUsed,
                                   GBool bMakeCopy = TRUE,
-                                  VSILFILE *fpSrc = NULL, int nOffset = 0);
-    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0);
+                                  VSILFILE *fpSrc = NULL, int nOffset = 0) override;
+    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0) override;
 
-    virtual int GetBlockClass() { return TABMAP_OBJECT_BLOCK; };
+    virtual int GetBlockClass() override { return TABMAP_OBJECT_BLOCK; };
 
     virtual int ReadIntCoord(GBool bCompressed, GInt32 &nX, GInt32 &nY);
     int         WriteIntCoord(GInt32 nX, GInt32 nY, GBool bCompressed);
@@ -1303,10 +1154,9 @@ class TABMAPObjectBlock CPL_FINAL : public TABRawBinBlock
     TABGeomType GetCurObjectType() { return m_nCurObjectType; }
 
 #ifdef DEBUG
-    virtual void Dump(FILE *fpOut = NULL) { Dump(fpOut, FALSE); };
+    virtual void Dump(FILE *fpOut = NULL) override { Dump(fpOut, FALSE); };
     void Dump(FILE *fpOut, GBool bDetails);
 #endif
-
 };
 
 /*---------------------------------------------------------------------
@@ -1342,21 +1192,21 @@ class TABMAPCoordBlock CPL_FINAL : public TABRawBinBlock
     GInt32      m_nFeatureYMax;
 
   public:
-    TABMAPCoordBlock(TABAccess eAccessMode = TABRead);
-    ~TABMAPCoordBlock();
+    explicit TABMAPCoordBlock(TABAccess eAccessMode = TABRead);
+    virtual ~TABMAPCoordBlock();
 
     virtual int InitBlockFromData(GByte *pabyBuf,
                                   int nBlockSize, int nSizeUsed,
                                   GBool bMakeCopy = TRUE,
-                                  VSILFILE *fpSrc = NULL, int nOffset = 0);
-    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0);
-    virtual int CommitToFile();
+                                  VSILFILE *fpSrc = NULL, int nOffset = 0) override;
+    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0) override;
+    virtual int CommitToFile() override;
 
-    virtual int GetBlockClass() { return TABMAP_COORD_BLOCK; };
+    virtual int GetBlockClass() override { return TABMAP_COORD_BLOCK; };
 
     void        SetMAPBlockManagerRef(TABBinBlockManager *poBlockManager);
-    virtual int ReadBytes(int numBytes, GByte *pabyDstBuf);
-    virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf);
+    virtual int ReadBytes(int numBytes, GByte *pabyDstBuf) override;
+    virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf) override;
     void        SetComprCoordOrigin(GInt32 nX, GInt32 nY);
     int         ReadIntCoord(GBool bCompressed, GInt32 &nX, GInt32 &nY);
     int         ReadIntCoords(GBool bCompressed, int numCoords, GInt32 *panXY);
@@ -1385,9 +1235,8 @@ class TABMAPCoordBlock CPL_FINAL : public TABRawBinBlock
                               GInt32 &nXMax, GInt32 &nYMax);
 
 #ifdef DEBUG
-    virtual void Dump(FILE *fpOut = NULL);
+    virtual void Dump(FILE *fpOut = NULL) override;
 #endif
-
 };
 
 /*---------------------------------------------------------------------
@@ -1409,21 +1258,21 @@ class TABMAPToolBlock CPL_FINAL : public TABRawBinBlock
     TABBinBlockManager *m_poBlockManagerRef;
 
   public:
-    TABMAPToolBlock(TABAccess eAccessMode = TABRead);
-    ~TABMAPToolBlock();
+    explicit TABMAPToolBlock(TABAccess eAccessMode = TABRead);
+    virtual ~TABMAPToolBlock();
 
     virtual int InitBlockFromData(GByte *pabyBuf,
                                   int nBlockSize, int nSizeUsed,
                                   GBool bMakeCopy = TRUE,
-                                  VSILFILE *fpSrc = NULL, int nOffset = 0);
-    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0);
-    virtual int CommitToFile();
+                                  VSILFILE *fpSrc = NULL, int nOffset = 0) override;
+    virtual int InitNewBlock(VSILFILE *fpSrc, int nBlockSize, int nFileOffset=0) override;
+    virtual int CommitToFile() override;
 
-    virtual int GetBlockClass() { return TABMAP_TOOL_BLOCK; };
+    virtual int GetBlockClass() override { return TABMAP_TOOL_BLOCK; };
 
     void        SetMAPBlockManagerRef(TABBinBlockManager *poBlockManager);
-    virtual int ReadBytes(int numBytes, GByte *pabyDstBuf);
-    virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf);
+    virtual int ReadBytes(int numBytes, GByte *pabyDstBuf) override;
+    virtual int WriteBytes(int nBytesToWrite, const GByte *pBuf) override;
 
     void        SetNextToolBlock(GInt32 nNextCoordBlockAddress);
 
@@ -1433,12 +1282,10 @@ class TABMAPToolBlock CPL_FINAL : public TABRawBinBlock
     int         CheckAvailableSpace(int nToolType);
 
 #ifdef DEBUG
-    virtual void Dump(FILE *fpOut = NULL);
+    virtual void Dump(FILE *fpOut = NULL) override;
 #endif
-
 };
 
-
 /*=====================================================================
        Classes to deal with .MAP files at the MapInfo object level
  =====================================================================*/
@@ -1478,7 +1325,6 @@ class TABIDFile
 #ifdef DEBUG
     void Dump(FILE *fpOut = NULL);
 #endif
-
 };
 
 /*---------------------------------------------------------------------
@@ -1575,7 +1421,7 @@ class TABMAPFile
 
     int         Int2Coordsys(GInt32 nX, GInt32 nY, double &dX, double &dY);
     int         Coordsys2Int(double dX, double dY, GInt32 &nX, GInt32 &nY,
-                             GBool bIgnoreOveflow=FALSE);
+                             GBool bIgnoreOverflow=FALSE);
     int         Int2CoordsysDist(GInt32 nX, GInt32 nY, double &dX, double &dY);
     int         Coordsys2IntDist(double dX, double dY, GInt32 &nX, GInt32 &nY);
     void        SetCoordFilter(TABVertex sMin, TABVertex sMax);
@@ -1621,16 +1467,13 @@ class TABMAPFile
     void Dump(FILE *fpOut = NULL);
     void DumpSpatialIndexToMIF(TABMAPIndexBlock *poNode,
                                FILE *fpMIF, FILE *fpMID,
-                               int nIndexInNode=-1,
                                int nParentId=-1,
+                               int nIndexInNode=-1,
                                int nCurDepth=0,
                                int nMaxDepth=-1);
 #endif
-
 };
 
-
-
 /*---------------------------------------------------------------------
  *                      class TABINDNode
  *
@@ -1674,7 +1517,7 @@ class TABINDNode
                                       TABINDNode *poCurChild=NULL);
 
    public:
-    TABINDNode(TABAccess eAccessMode = TABRead);
+    explicit TABINDNode(TABAccess eAccessMode = TABRead);
     ~TABINDNode();
 
     int         InitNode(VSILFILE *fp, int nBlockPtr,
@@ -1719,10 +1562,8 @@ class TABINDNode
 #ifdef DEBUG
     void Dump(FILE *fpOut = NULL);
 #endif
-
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABINDFile
  *
@@ -1771,10 +1612,8 @@ class TABINDFile
 #ifdef DEBUG
     void Dump(FILE *fpOut = NULL);
 #endif
-
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABDATFile
  *
@@ -1810,9 +1649,9 @@ class TABDATFile
     int         InitWriteHeader();
     int         WriteHeader();
 
-	// We know that character strings are limited to 254 chars in MapInfo
-	// Using a buffer pr. class instance to avoid threading issues with the library
-	char		m_szBuffer[256];
+    // We know that character strings are limited to 254 chars in MapInfo
+    // Using a buffer pr. class instance to avoid threading issues with the library
+    char        m_szBuffer[256];
 
    public:
     TABDATFile();
@@ -1893,10 +1732,8 @@ class TABDATFile
 #ifdef DEBUG
     void Dump(FILE *fpOut = NULL);
 #endif
-
 };
 
-
 /*---------------------------------------------------------------------
  *                      class TABRelation
  *
@@ -1974,7 +1811,6 @@ class TABRelation
     const char *GetRelFieldName()       {return m_pszRelFieldName;};
 };
 
-
 /*---------------------------------------------------------------------
  *                      class MIDDATAFile
  *
@@ -1997,7 +1833,7 @@ class MIDDATAFile
      void SaveLine(const char *pszLine);
      const char *GetSavedLine();
      void WriteLine(const char*, ...) CPL_PRINT_FUNC_FORMAT (2, 3);
-     GBool IsValidFeature(const char *pszString);
+     static GBool IsValidFeature(const char *pszString);
 
 //  Translation information
      void SetTranslation(double, double, double, double);
@@ -2028,8 +1864,6 @@ class MIDDATAFile
        GBool       m_bEof;
 };
 
-
-
 /*=====================================================================
                         Function prototypes
  =====================================================================*/
@@ -2039,5 +1873,4 @@ TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
                                           GBool bHardBlockSize = TRUE,
                                           TABAccess eAccessMode = TABRead);
 
-
 #endif /* MITAB_PRIV_H_INCLUDED_ */
diff --git a/ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp b/ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp
index 6f7b4f7..0a03315 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_rawbinblock.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_rawbinblock.cpp,v 1.11 2007-06-11 14:40:03 dmorissette Exp $
  *
  * Name:     mitab_rawbinblock.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,75 +28,51 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_rawbinblock.cpp,v $
- * Revision 1.11  2007-06-11 14:40:03  dmorissette
- * Fixed another issue related to attempting to read past EOF while writing
- * collections (bug 1657)
- *
- * Revision 1.10  2007/02/22 18:35:53  dmorissette
- * Fixed problem writing collections where MITAB was sometimes trying to
- * read past EOF in write mode (bug 1657).
- *
- * Revision 1.9  2006/11/28 18:49:08  dmorissette
- * Completed changes to split TABMAPObjectBlocks properly and produce an
- * optimal spatial index (bug 1585)
- *
- * Revision 1.8  2005/10/06 19:15:31  dmorissette
- * Collections: added support for reading/writing pen/brush/symbol ids and
- * for writing collection objects to .TAB/.MAP (bug 1126)
- *
- * Revision 1.7  2004/12/01 18:25:03  dmorissette
- * Fixed potential memory leaks in error conditions (bug 881)
- *
- * Revision 1.6  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.5  2000/02/28 17:06:06  daniel
- * Added m_bModified flag
- *
- * Revision 1.4  2000/01/15 22:30:45  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.3  1999/09/26 14:59:37  daniel
- * Implemented write support
- *
- * Revision 1.2  1999/09/16 02:39:17  daniel
- * Completed read support for most feature types
- *
- * Revision 1.1  1999/07/12 04:18:25  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
 
+#include <cctype>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
+
+CPL_CVSID("$Id: mitab_rawbinblock.cpp 37351 2017-02-12 05:22:20Z goatbar $");
+
 /*=====================================================================
  *                      class TABRawBinBlock
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABRawBinBlock::TABRawBinBlock()
  *
  * Constructor.
  **********************************************************************/
-TABRawBinBlock::TABRawBinBlock(TABAccess eAccessMode /*= TABRead*/,
-                               GBool bHardBlockSize /*= TRUE*/)
-{
-    m_fp = NULL;
-    m_pabyBuf = NULL;
-    m_nFirstBlockPtr = 0;
-    m_nBlockSize = m_nSizeUsed = m_nFileOffset = m_nCurPos = 0;
-    m_bHardBlockSize = bHardBlockSize;
-    m_nFileSize = -1;
-
-    m_bModified = FALSE;
-
-    m_eAccess = eAccessMode;
-    m_nBlockType = 0;
-}
+TABRawBinBlock::TABRawBinBlock( TABAccess eAccessMode /*= TABRead*/,
+                                GBool bHardBlockSize /*= TRUE*/ ) :
+    m_fp(NULL),
+    m_eAccess(eAccessMode),
+    m_nBlockType(0),
+    m_pabyBuf(NULL),
+    m_nBlockSize(0),
+    m_nSizeUsed(0),
+    m_bHardBlockSize(bHardBlockSize),
+    m_nFileOffset(0),
+    m_nCurPos(0),
+    m_nFirstBlockPtr(0),
+    m_nFileSize(-1),
+    m_bModified(FALSE)
+{}
 
 /**********************************************************************
  *                   TABRawBinBlock::~TABRawBinBlock()
@@ -110,7 +85,6 @@ TABRawBinBlock::~TABRawBinBlock()
         CPLFree(m_pabyBuf);
 }
 
-
 /**********************************************************************
  *                   TABRawBinBlock::ReadFromFile()
  *
@@ -122,8 +96,6 @@ TABRawBinBlock::~TABRawBinBlock()
 int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset,
                                      int nSize)
 {
-    GByte *pabyBuf;
-
     if (fpSrc == NULL || nSize == 0)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -143,7 +115,7 @@ int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset,
     /*----------------------------------------------------------------
      * Alloc a buffer to contain the data
      *---------------------------------------------------------------*/
-    pabyBuf = (GByte*)CPLMalloc(nSize*sizeof(GByte));
+    GByte *pabyBuf = (GByte*)CPLMalloc(nSize*sizeof(GByte));
 
     /*----------------------------------------------------------------
      * Read from the file
@@ -166,7 +138,6 @@ int     TABRawBinBlock::ReadFromFile(VSILFILE *fpSrc, int nOffset,
                              FALSE, fpSrc, nOffset);
 }
 
-
 /**********************************************************************
  *                   TABRawBinBlock::CommitToFile()
  *
@@ -210,14 +181,13 @@ int     TABRawBinBlock::CommitToFile()
          * Moving pointer failed... we may need to pad with zeros if
          * block destination is beyond current end of file.
          *-----------------------------------------------------------*/
-        int nCurPos;
-        nCurPos = (int)VSIFTellL(m_fp);
+        int nCurPos = (int)VSIFTellL(m_fp);
 
         if (nCurPos < m_nFileOffset &&
             VSIFSeekL(m_fp, 0L, SEEK_END) == 0 &&
             (nCurPos = (int)VSIFTellL(m_fp)) < m_nFileOffset)
         {
-            GByte cZero = 0;
+            const GByte cZero = 0;
 
             while(nCurPos < m_nFileOffset && nStatus == 0)
             {
@@ -234,7 +204,6 @@ int     TABRawBinBlock::CommitToFile()
 
         if (nCurPos != m_nFileOffset)
             nStatus = -1; // Error message will follow below
-
     }
 
     /*----------------------------------------------------------------
@@ -422,7 +391,6 @@ int     TABRawBinBlock::InitNewBlock(VSILFILE *fpSrc, int nBlockSize,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABRawBinBlock::GetBlockType()
  *
@@ -479,7 +447,7 @@ int     TABRawBinBlock::GotoByteInBlock(int nOffset)
 
     m_nCurPos = nOffset;
 
-    m_nSizeUsed = MAX(m_nSizeUsed, m_nCurPos);
+    m_nSizeUsed = std::max(m_nSizeUsed, m_nCurPos);
 
     return 0;
 }
@@ -530,8 +498,6 @@ int     TABRawBinBlock::GotoByteInFile(int nOffset,
                                        GBool bForceReadFromFile /*=FALSE*/,
                                        GBool bOffsetIsEndOfData /*=FALSE*/)
 {
-    int nNewBlockPtr;
-
     if (nOffset < 0)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -539,8 +505,9 @@ int     TABRawBinBlock::GotoByteInFile(int nOffset,
         return -1;
     }
 
-    nNewBlockPtr = ( (nOffset-m_nFirstBlockPtr)/m_nBlockSize)*m_nBlockSize +
-                     m_nFirstBlockPtr;
+    int nNewBlockPtr =
+        ( (nOffset-m_nFirstBlockPtr)/m_nBlockSize)*m_nBlockSize +
+        m_nFirstBlockPtr;
 
     if (m_eAccess == TABRead)
     {
@@ -635,12 +602,11 @@ int     TABRawBinBlock::GotoByteInFile(int nOffset,
 
     m_nCurPos = nOffset-m_nFileOffset;
 
-    m_nSizeUsed = MAX(m_nSizeUsed, m_nCurPos);
+    m_nSizeUsed = std::max(m_nSizeUsed, m_nCurPos);
 
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABRawBinBlock::SetFirstBlockPtr()
  *
@@ -657,7 +623,6 @@ void  TABRawBinBlock::SetFirstBlockPtr(int nOffset)
     m_nFirstBlockPtr = nOffset;
 }
 
-
 /**********************************************************************
  *                   TABRawBinBlock::GetNumUnusedBytes()
  *
@@ -665,7 +630,7 @@ void  TABRawBinBlock::SetFirstBlockPtr(int nOffset)
  **********************************************************************/
 int     TABRawBinBlock::GetNumUnusedBytes()
 {
-    return (m_nBlockSize - m_nSizeUsed);
+    return m_nBlockSize - m_nSizeUsed;
 }
 
 /**********************************************************************
@@ -689,7 +654,7 @@ int     TABRawBinBlock::GetFirstUnusedByteOffset()
  **********************************************************************/
 int     TABRawBinBlock::GetCurAddress()
 {
-    return (m_nFileOffset + m_nCurPos);
+    return m_nFileOffset + m_nCurPos;
 }
 
 /**********************************************************************
@@ -803,8 +768,6 @@ double  TABRawBinBlock::ReadDouble()
     return dValue;
 }
 
-
-
 /**********************************************************************
  *                   TABRawBinBlock::WriteBytes()
  *
@@ -857,14 +820,13 @@ int  TABRawBinBlock::WriteBytes(int nBytesToWrite, const GByte *pabySrcBuf)
 
     m_nCurPos += nBytesToWrite;
 
-    m_nSizeUsed = MAX(m_nSizeUsed, m_nCurPos);
+    m_nSizeUsed = std::max(m_nSizeUsed, m_nCurPos);
 
     m_bModified = TRUE;
 
     return 0;
 }
 
-
 /**********************************************************************
  *                    TABRawBinBlock::Write<datatype>()
  *
@@ -917,7 +879,6 @@ int  TABRawBinBlock::WriteDouble(double dValue)
     return WriteBytes(8, (GByte*)&dValue);
 }
 
-
 /**********************************************************************
  *                    TABRawBinBlock::WriteZeros()
  *
@@ -930,15 +891,13 @@ int  TABRawBinBlock::WriteDouble(double dValue)
  **********************************************************************/
 int  TABRawBinBlock::WriteZeros(int nBytesToWrite)
 {
-    char acZeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-    int i;
+    const char acZeros[8] = {0, 0, 0, 0, 0, 0, 0, 0};
     int nStatus = 0;
 
-    /* Write by 8 bytes chunks.  The last chunk may be less than 8 bytes
-     */
-    for(i=0; nStatus == 0 && i< nBytesToWrite; i+=8)
+    // Write by 8 bytes chunks.  The last chunk may be less than 8 bytes.
+    for( int i = 0; nStatus == 0 && i< nBytesToWrite; i += 8 )
     {
-        nStatus = WriteBytes(MIN(8,(nBytesToWrite-i)), (GByte*)acZeros);
+        nStatus = WriteBytes(std::min(8, nBytesToWrite - i), (GByte*)acZeros);
     }
 
     return nStatus;
@@ -961,7 +920,7 @@ int  TABRawBinBlock::WritePaddedString(int nFieldSize, const char *pszString)
     int nStatus = 0;
 
     nLen = static_cast<int>(strlen(pszString));
-    nLen = MIN(nLen, nFieldSize);
+    nLen = std::min(nLen, nFieldSize);
     numSpaces = nFieldSize - nLen;
 
     if (nLen > 0)
@@ -971,7 +930,7 @@ int  TABRawBinBlock::WritePaddedString(int nFieldSize, const char *pszString)
      */
     for(i=0; nStatus == 0 && i< numSpaces; i+=8)
     {
-        nStatus = WriteBytes(MIN(8,(numSpaces-i)), (GByte*)acSpaces);
+        nStatus = WriteBytes(std::min(8, numSpaces - i), (GByte*)acSpaces);
     }
 
     return nStatus;
@@ -1000,7 +959,7 @@ void TABRawBinBlock::Dump(FILE *fpOut /*=NULL*/)
         {
             fprintf(fpOut,"Garbage Block (type %d) at offset %d.\n",
                                                     m_nBlockType, m_nFileOffset);
-            int nNextGarbageBlock;
+            int nNextGarbageBlock = 0;
             memcpy(&nNextGarbageBlock, m_pabyBuf + 2, 4);
             CPL_LSBPTR32(&nNextGarbageBlock);
             fprintf(fpOut,"  m_nNextGarbageBlock     = %d\n", nNextGarbageBlock);
@@ -1018,7 +977,6 @@ void TABRawBinBlock::Dump(FILE *fpOut /*=NULL*/)
 
 #endif // DEBUG
 
-
 /**********************************************************************
  *                          DumpBytes()
  *
@@ -1027,30 +985,27 @@ void TABRawBinBlock::Dump(FILE *fpOut /*=NULL*/)
 void TABRawBinBlock::DumpBytes(GInt32 nValue, int nOffset /*=0*/,
                                FILE *fpOut /*=NULL*/)
 {
-    GInt32      anVal[2];
-    GInt16      n16Val1, n16Val2;
-    float       fValue;
-    char        *pcValue;
-    double      dValue;
-
-    pcValue = (char*)&nValue;
+    float fValue = 0.0f;
     memcpy(&fValue, &nValue, 4);
 
+    char *pcValue = (char*)&nValue;
+
+    GInt16 n16Val1 = 0;
     memcpy(&n16Val1, pcValue + 2, sizeof(GInt16));
+    GInt16 n16Val2 = 0;
     memcpy(&n16Val2, pcValue, sizeof(GInt16));
 
-    anVal[0] = anVal[1] = 0;
-
     /* For double precision values, we only use the first half
      * of the height bytes... and leave the other 4 bytes as zeros!
      * It's a bit of a hack, but it seems to be enough for the
      * precision of the values we print!
      */
 #ifdef CPL_MSB
-    anVal[0] = nValue;
+    const GInt32 anVal[2] = { nValue, 0 };
 #else
-    anVal[1] = nValue;
+    const GInt32 anVal[2] = { 0, nValue };
 #endif
+    double dValue = 0.0;
     memcpy(&dValue, anVal, 8);
 
     if (fpOut == NULL)
@@ -1060,14 +1015,12 @@ void TABRawBinBlock::DumpBytes(GInt32 nValue, int nOffset /*=0*/,
                     nOffset, nValue, nValue,
                     n16Val1, n16Val2, fValue, dValue);
 
-    printf("\t[%c%c%c%c]\n", isprint(pcValue[0])?pcValue[0]:'.',
+    fprintf(fpOut, "\t[%c%c%c%c]\n", isprint(pcValue[0])?pcValue[0]:'.',
                              isprint(pcValue[1])?pcValue[1]:'.',
                              isprint(pcValue[2])?pcValue[2]:'.',
                              isprint(pcValue[3])?pcValue[3]:'.');
 }
 
-
-
 /**********************************************************************
  *                   TABCreateMAPBlockFromFile()
  *
@@ -1082,9 +1035,6 @@ TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
                                           GBool bHardBlockSize /*= TRUE */,
                                           TABAccess eAccessMode /*= TABRead*/)
 {
-    TABRawBinBlock *poBlock = NULL;
-    GByte *pabyBuf;
-
     if (fpSrc == NULL || nSize == 0)
     {
         CPLError(CE_Failure, CPLE_AssertionFailed,
@@ -1095,7 +1045,7 @@ TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
     /*----------------------------------------------------------------
      * Alloc a buffer to contain the data
      *---------------------------------------------------------------*/
-    pabyBuf = (GByte*)CPLMalloc(nSize*sizeof(GByte));
+    GByte *pabyBuf = (GByte*)CPLMalloc(nSize*sizeof(GByte));
 
     /*----------------------------------------------------------------
      * Read from the file
@@ -1115,6 +1065,8 @@ TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
      * Header block is different: it does not start with the object
      * type byte but it is always the first block in a file
      *---------------------------------------------------------------*/
+    TABRawBinBlock *poBlock = NULL;
+
     if (nOffset == 0)
     {
         poBlock = new TABMAPHeaderBlock(eAccessMode);
@@ -1160,19 +1112,17 @@ TABRawBinBlock *TABCreateMAPBlockFromFile(VSILFILE *fpSrc, int nOffset,
  *                      class TABBinBlockManager
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABBinBlockManager::TABBinBlockManager()
  *
  * Constructor.
  **********************************************************************/
-TABBinBlockManager::TABBinBlockManager()
+TABBinBlockManager::TABBinBlockManager() :
+    m_nBlockSize(0),
+    m_nLastAllocatedBlock(-1),
+    m_psGarbageBlocksFirst(NULL),
+    m_psGarbageBlocksLast(NULL)
 {
-
-    m_nBlockSize=0;
-    m_nLastAllocatedBlock = -1;
-    m_psGarbageBlocksFirst = NULL;
-    m_psGarbageBlocksLast = NULL;
     m_szName[0] = '\0';
 }
 
diff --git a/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp b/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
index fb433af..7504052 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_spatialref.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_spatialref.cpp,v 1.55 2011-06-11 00:35:00 fwarmerdam Exp $
  *
  * Name:     mitab_spatialref.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -28,189 +27,26 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_spatialref.cpp,v $
- * Revision 1.55  2011-06-11 00:35:00  fwarmerdam
- * add support for reading google mercator (#4115)
- *
- * Revision 1.54  2010-10-07 18:46:26  aboudreault
- * Fixed bad use of CPLAtof when locale setting doesn't use . for float (GDAL bug #3775)
- *
- * Revision 1.53  2010-09-07 16:48:08  aboudreault
- * Removed incomplete patch for affine params support in mitab. (bug 1155)
- *
- * Revision 1.52  2010-07-08 17:21:12  aboudreault
- * Put back New_Zealand Datum in asDatumInfoList
- *
- * Revision 1.51  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.50  2010-07-05 17:20:14  aboudreault
- * Added Krovak projection support (bug 2230)
- *
- * Revision 1.49  2009-10-15 16:16:37  fwarmerdam
- * add the default EPSG/OGR name for new zealand datums (gdal #3187)
- *
- * Revision 1.48  2007/11/21 21:15:45  dmorissette
- * Fix asDatumInfoList[] and asSpheroidInfoList[] defns/refs (bug 1826)
- *
- * Revision 1.47  2006/07/10 17:58:48  fwarmerdam
- * North_American_Datum_1927 support
- *
- * Revision 1.46  2006/07/07 19:41:32  dmorissette
- * Fixed problem with uninitialized sTABProj.nAffineFlag (bug 1254,1319)
- *
- * Revision 1.45  2006/05/09 20:21:29  fwarmerdam
- * Coordsys false easting and northing are in the units of the coordsys, not
- * necessarily meters.  Adjusted mitab_spatialref.cpp to reflect this.
- * http://bugzilla.remotesensing.org/show_bug.cgi?id=1113
- *
- * Revision 1.44  2005/09/29 20:15:36  dmorissette
- * More improvements to handling of modified TM projections 21-24.
- * Added correct name stings to all datum definitions (Anthony D, bug 1155)
- *
- * Revision 1.43  2005/05/12 22:07:52  dmorissette
- * Improved handling of Danish modified TM proj#21-24 (hss, bugs 976,1010)
- *
- * Revision 1.42  2005/03/22 23:24:54  dmorissette
- * Added support for datum id in .MAP header (bug 910)
- *
- * Revision 1.41  2004/10/11 20:50:04  dmorissette
- * 7 new datum defns, 1 fixed and list of ellipsoids updated (Bug 608,Uffe K.)
- *
- * Revision 1.40  2003/03/21 14:20:42  warmerda
- * fixed up regional mercator handling, was screwing up transverse mercator
- *
- * Revision 1.39  2002/12/19 20:46:01  warmerda
- * fixed spelling of Provisional_South_American_Datum_1956
- *
- * Revision 1.38  2002/12/12 20:12:18  warmerda
- * fixed signs of rotational parameters for TOWGS84 in WKT
- *
- * Revision 1.37  2002/10/15 14:33:30  warmerda
- * Added untested support in mitab_spatialref.cpp, and mitab_coordsys.cpp for
- * projections Regional Mercator (26), Polyconic (27), Azimuthal Equidistant -
- * All origin latitudes (28), and Lambert Azimuthal Equal Area - any aspect
- * (29).
- *
- * Revision 1.36  2002/09/05 15:38:16  warmerda
- * one more ogc datum name
- *
- * Revision 1.35  2002/09/05 15:23:22  warmerda
- * added some EPSG datum names provided by Siro Martello @ Cadcorp
- *
- * Revision 1.34  2002/04/01 19:49:24  warmerda
- * added support for cassini/soldner - proj 30
- *
- * Revision 1.33  2002/03/01 19:00:15  warmerda
- * False Easting/Northing should be in the linear units of measure in MapInfo,
- * but in OGRSpatialReference/WKT they are always in meters.  Convert accordingly.
- *
- * Revision 1.32  2001/10/25 16:13:41  warmerda
- * Added OGC string for datum 12
- *
- * Revision 1.31  2001/08/10 21:25:59  warmerda
- * SetSpatialRef() now makes a clone of the srs instead of taking a ref to it
- *
- * Revision 1.30  2001/04/23 17:38:06  warmerda
- * fixed use of freed points bug for datum 999/9999
- *
- * Revision 1.29  2001/04/04 21:43:19  warmerda
- * added code to set WGS84 values
- *
- * Revision 1.28  2001/01/23 21:23:42  daniel
- * Added projection bounds lookup table, called from TABFile::SetProjInfo()
- *
- * Revision 1.27  2001/01/22 16:00:53  warmerda
- * reworked swiss projection support
- *
- * Revision 1.26  2001/01/19 21:56:18  warmerda
- * added untested support for Swiss Oblique Mercator
- *
- * Revision 1.25  2000/12/05 14:56:55  daniel
- * Added some missing unit names (aliases) in TABFile::SetSpatialRef()
- *
- * Revision 1.24  2000/10/16 21:44:50  warmerda
- * added nonearth support
- *
- * Revision 1.23  2000/10/16 18:01:20  warmerda
- * added check for NULL on passed in spatial ref
- *
- * Revision 1.22  2000/10/02 14:46:36  daniel
- * Added 7 parameter datums with id 1000+
- *
- * Revision 1.21  2000/09/29 22:09:18  daniel
- * Added new datums/ellipsoid from MapInfo V6.0
- *
- * Revision 1.20  2000/09/28 16:39:44  warmerda
- * Avoid warnings for unused, and uninitialized variables
- *
- * Revision 1.19  2000/02/07 17:43:17  daniel
- * Fixed offset in parsing of custom datum string in SetSpatialRef()
- *
- * Revision 1.18  2000/02/04 05:30:50  daniel
- * Fixed problem in GetSpatialRef() with szDatumName[] buffer size and added
- * use of an epsilon in comparing of datum parameters.
- *
- * Revision 1.17  2000/01/15 22:30:45  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.16  1999/12/21 20:01:47  warmerda
- * added support for DATUM 0
- *
- * Revision 1.15  1999/11/11 02:56:17  warmerda
- * fixed problems with stereographic
- *
- * Revision 1.14  1999/11/10 20:13:12  warmerda
- * implement spheroid table
- *
- * Revision 1.13  1999/11/09 22:31:38  warmerda
- * initial implementation of MIF CoordSys support
- *
- * Revision 1.12  1999/10/19 16:31:32  warmerda
- * Improved mile support.
- *
- * Revision 1.11  1999/10/19 16:27:50  warmerda
- * Added support for Mile (units=0).  Also added support for nonearth
- * projections.
- *
- * Revision 1.10  1999/10/05 18:56:08  warmerda
- * fixed lots of bugs with projection parameters
- *
- * Revision 1.9  1999/10/04 21:17:47  warmerda
- * Make sure that asDatumInfoList comparisons include the ellipsoid code.
- * Don't include OGC name for local NAD27 values.  Put NAD83 ahead of GRS80
- * so it will be used in preference even though they are identical parms.
- *
- * Revision 1.8  1999/10/04 19:46:42  warmerda
- * assorted changes, including rework of units
- *
- * Revision 1.7  1999/09/28 04:52:17  daniel
- * Added missing param in sprintf() format for szDatumName[]
- *
- * Revision 1.6  1999/09/28 02:51:46  warmerda
- * Added ellipsoid codes, and bulk of write implementation.
- *
- * Revision 1.5  1999/09/27 21:23:41  warmerda
- * added more projections
- *
- * Revision 1.4  1999/09/24 04:01:28  warmerda
- * remember nMIDatumId changes
- *
- * Revision 1.3  1999/09/23 19:51:38  warmerda
- * added datum mapping table support
- *
- * Revision 1.2  1999/09/22 23:04:59  daniel
- * Handle reference count on OGRSpatialReference properly
- *
- * Revision 1.1  1999/09/21 19:39:22  daniel
- * Moved Get/SetSpatialRef() to a separate file
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
 
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "mitab_priv.h"
+#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
+
+CPL_CVSID("$Id: mitab_spatialref.cpp 37449 2017-02-25 15:23:08Z rouault $");
+
 /* -------------------------------------------------------------------- */
 /*      This table was automatically generated by doing translations    */
 /*      between mif and tab for each datum, and extracting the          */
@@ -272,7 +108,7 @@ const MapInfoDatumInfo asDatumInfoList[] =
 { 6236, 39, "Hu_Tzu_Shan",                 4, -634, -549, -201,0, 0, 0, 0, 0},
 { 0,    40, "Indian_Thailand_Vietnam",     11,214,  836,  303, 0, 0, 0, 0, 0},
 { 0,    41, "Indian_Bangladesh",           11,289,  734,  257, 0, 0, 0, 0, 0},
-{ 0,    42, "Ireland_1965",                13,506,  -122, 611, 0, 0, 0, 0, 0},
+{ 6299, 42, "Ireland_1965",                13,506,  -122, 611, 0, 0, 0, 0, 0},
 { 0,    43, "ISTS_073_Astro_1969",         4, 208,  -435, -229,0, 0, 0, 0, 0},
 { 6725, 44, "Johnston_Island_1961",        4, 191,  -77,  -204,0, 0, 0, 0, 0},
 { 6244, 45, "Kandawala",                   11,-97,  787,  86,  0, 0, 0, 0, 0},
@@ -345,7 +181,7 @@ const MapInfoDatumInfo asDatumInfoList[] =
 { 6124, 112, "Rikets_koordinatsystem_1990",10,498,  -36, 568,  0, 0, 0, 0, 0},
 { 0,    113, "Lisboa_DLX",                 4, -303, -62, 105,  0, 0, 0, 0, 0},
 { 0,    114, "Melrica_1973_D73",           4, -223, 110, 37,   0, 0, 0, 0, 0},
-{ 0,    115, "Euref_98",                   0, 0,    0,   0,    0, 0, 0, 0, 0},
+{ 6258, 115, "Euref_89",                   0, 0,    0,   0,    0, 0, 0, 0, 0},
 { 6283, 116, "GDA94",                      0, 0,    0,   0,    0, 0, 0, 0, 0},
 { 6283, 116, "Geocentric_Datum_of_Australia_1994", 0, 0, 0, 0, 0, 0, 0, 0, 0},
 { 6167, 117, "NZGD2000",                   0, 0,    0,   0,    0, 0, 0, 0, 0},
@@ -404,7 +240,7 @@ const MapInfoDatumInfo asDatumInfoList[] =
 { 6301, 1015,"Tokyo",                      10, -146.414, 507.337, 680.507,0,0,0,0,0},
 { 0,    1016,"Finnish_KKJ",                4, -96.062, -82.428, -121.754, -4.801, -0.345, 1.376, 1.496, 0},
 { 6610, 1017,"Xian 1980",                  53, 24, -123, -94, -0.02, -0.25, 0.13, 1.1, 0},
-{ 0,    1018,"Lithuanian Pulkovo 1942",	   4, -40.59527, -18.54979, -69.33956, -2.508, -1.8319, 2.6114, -4.2991, 0},
+{ 0,    1018,"Lithuanian Pulkovo 1942",    4, -40.59527, -18.54979, -69.33956, -2.508, -1.8319, 2.6114, -4.2991, 0},
 { 0,    1019,"Belgian 1972 7 Parameter",   4, -99.059, 53.322, -112.486, -0.419, 0.83, -1.885, 0.999999, 0},
 { 6818, 1020,"S-JTSK with Ferro prime meridian", 10, 589, 76, 480, 0, 0, 0, 0, -17.666666666667},
 
@@ -821,13 +657,12 @@ OGRSpatialReference *TABFile::GetSpatialRef()
     if (m_poSpatialRef != NULL)
         return m_poSpatialRef;
 
-
     /*-----------------------------------------------------------------
      * Fetch the parameters from the header.
      *----------------------------------------------------------------*/
-    TABMAPHeaderBlock *poHeader;
-    TABProjInfo     sTABProj;
+    TABProjInfo sTABProj;
 
+    TABMAPHeaderBlock *poHeader = NULL;
     if ((poHeader = m_poMAPFile->GetHeaderBlock()) == NULL ||
         poHeader->GetProjInfo( &sTABProj ) != 0)
     {
@@ -844,13 +679,19 @@ OGRSpatialReference *TABFile::GetSpatialRef()
  *                   TABFile::GetSpatialRefFromTABProj()
  **********************************************************************/
 
+static bool TAB_EQUAL( double a, double b )
+{
+    // TODO(schwehr): Use std::abs.
+    return (a < b ? (b - a) : (a - b)) < 1.0e-10;
+}
+
 OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABProj)
 {
     /*-----------------------------------------------------------------
      * Get the units name, and translation factor.
      *----------------------------------------------------------------*/
-    const char *pszUnitsName;
-    const char *pszUnitsConv;
+    const char *pszUnitsName = NULL;
+    const char *pszUnitsConv = NULL;
     /* double      dfConv = 1.0; */
 
     switch( sTABProj.nUnitsId )
@@ -1177,7 +1018,6 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
          * Stereographic
          *-------------------------------------------------------------*/
       case 20:
-      case 31: /* this is called Double Stereographic, whats the diff? */
         poSpatialRef->SetStereographic( sTABProj.adProjParams[1],
                                           sTABProj.adProjParams[0],
                                           sTABProj.adProjParams[2],
@@ -1224,6 +1064,17 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
                                sTABProj.adProjParams[3] );
         break;
 
+        /*--------------------------------------------------------------
+         * Oblique Stereographic
+         *-------------------------------------------------------------*/
+      case 31:
+        poSpatialRef->SetOS( sTABProj.adProjParams[1],
+                                          sTABProj.adProjParams[0],
+                                          sTABProj.adProjParams[2],
+                                          sTABProj.adProjParams[3],
+                                          sTABProj.adProjParams[4] );
+        break;
+
      /*--------------------------------------------------------------
       * Krovak
       *-------------------------------------------------------------*/
@@ -1232,7 +1083,7 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
                                    sTABProj.adProjParams[0],   // dfCenterLong
                                    sTABProj.adProjParams[3],   // dfAzimuth
                                    sTABProj.adProjParams[2],   // dfPseudoStdParallelLat
-                                   1.0,					     // dfScale
+                                   1.0,                        // dfScale
                                    sTABProj.adProjParams[4],   // dfFalseEasting
                                    sTABProj.adProjParams[5] ); // dfFalseNorthing
         break;
@@ -1280,12 +1131,9 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
      * were in the order of 1e-150 when they should have actually been zeros,
      * we will use an epsilon in our scan instead of looking for equality.
      *----------------------------------------------------------------*/
-#define TAB_EQUAL(a, b) (((a)<(b) ? ((b)-(a)) : ((a)-(b))) < 1e-10)
-    char        szDatumName[160];
-    int         iDatumInfo;
     const MapInfoDatumInfo *psDatumInfo = NULL;
 
-    for( iDatumInfo = 0;
+    for( int iDatumInfo = 0;
          asDatumInfoList[iDatumInfo].nMapInfoDatumID != -1;
          iDatumInfo++ )
     {
@@ -1308,6 +1156,7 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
         psDatumInfo = NULL;
     }
 
+    char szDatumName[200] = {};
     if( psDatumInfo == NULL )
     {
         if( sTABProj.adDatumParams[0] == 0.0
@@ -1317,7 +1166,7 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
             && sTABProj.adDatumParams[4] == 0.0 )
         {
             snprintf( szDatumName, sizeof(szDatumName),
-                     "MIF 999,%d,%.15g,%.15g,%.15g",
+                     "MIF 999,%u,%.15g,%.15g,%.15g",
                      sTABProj.nEllipsoidId,
                      sTABProj.dDatumShiftX,
                      sTABProj.dDatumShiftY,
@@ -1326,7 +1175,7 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
         else
         {
             snprintf( szDatumName, sizeof(szDatumName),
-                     "MIF 9999,%d,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g",
+                     "MIF 9999,%u,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g,%.15g",
                      sTABProj.nEllipsoidId,
                      sTABProj.dDatumShiftX,
                      sTABProj.dDatumShiftY,
@@ -1389,7 +1238,8 @@ OGRSpatialReference* TABFile::GetSpatialRefFromTABProj(const TABProjInfo& sTABPr
     /*-----------------------------------------------------------------
      * Set the spheroid.
      *----------------------------------------------------------------*/
-    double      dfSemiMajor=0.0, dfInvFlattening=0.0;
+    double dfSemiMajor = 0.0;
+    double dfInvFlattening = 0.0;
     const char *pszSpheroidName = NULL;
 
     for( int i = 0; asSpheroidInfoList[i].nMapInfoId != -1; i++ )
@@ -1525,8 +1375,8 @@ int TABFile::SetSpatialRef(OGRSpatialReference *poSpatialRef)
 
     m_poSpatialRef = poSpatialRef->Clone();
 
-    TABProjInfo     sTABProj;
-    int             nParmCount;
+    TABProjInfo sTABProj;
+    int nParmCount = 0;
     GetTABProjFromSpatialRef(poSpatialRef, sTABProj, nParmCount);
 
     /*-----------------------------------------------------------------
@@ -1578,10 +1428,8 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
     /*-----------------------------------------------------------------
      * Get the linear units and conversion.
      *----------------------------------------------------------------*/
-    char        *pszLinearUnits;
-    double      dfLinearConv;
-
-    dfLinearConv = poSpatialRef->GetLinearUnits( &pszLinearUnits );
+    char *pszLinearUnits = NULL;
+    double dfLinearConv = poSpatialRef->GetLinearUnits( &pszLinearUnits );
     if( dfLinearConv == 0.0 )
         dfLinearConv = 1.0;
 
@@ -1623,7 +1471,7 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
         parms[2] = 90.0;
         nParmCount = 3;
 
-        if( ABS((ABS(parms[1]) - 90)) > 0.001 )
+        if( std::abs((std::abs(parms[1]) - 90)) > 0.001 )
             sTABProj.nProjId = 28;
     }
 
@@ -1688,7 +1536,7 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
         parms[2] = 90.0;
         nParmCount = 3;
 
-        if( ABS((ABS(parms[1]) - 90)) > 0.001 )
+        if( std::abs((std::abs(parms[1]) - 90)) > 0.001 )
             sTABProj.nProjId = 29;
     }
 
@@ -1790,6 +1638,17 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
         nParmCount = 5;
     }
 
+    else if (EQUAL(pszProjection,SRS_PT_OBLIQUE_STEREOGRAPHIC))
+    {
+        sTABProj.nProjId = 31;
+        parms[0] = poSpatialRef->GetProjParm(SRS_PP_CENTRAL_MERIDIAN, 0.0);
+        parms[1] = poSpatialRef->GetProjParm(SRS_PP_LATITUDE_OF_ORIGIN, 0.0);
+        parms[2] = poSpatialRef->GetProjParm(SRS_PP_SCALE_FACTOR, 1.0);
+        parms[3] = poSpatialRef->GetProjParm(SRS_PP_FALSE_EASTING, 0.0);
+        parms[4] = poSpatialRef->GetProjParm(SRS_PP_FALSE_NORTHING, 0.0);
+        nParmCount = 5;
+    }
+
     else if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
     {
         sTABProj.nProjId = 8;
@@ -1899,7 +1758,7 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
 
     if (pszDatumCode && pszDatumAuthority && EQUAL(pszDatumAuthority, "EPSG"))
     {
-    	nDatumEPSGCode = atoi(pszDatumCode);
+        nDatumEPSGCode = atoi(pszDatumCode);
     }
 
     /*-----------------------------------------------------------------
@@ -1923,10 +1782,8 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
              && atoi(pszWKTDatum+4) != 999
              && atoi(pszWKTDatum+4) != 9999 )
     {
-        int     i;
-
         int nDatum = atoi(pszWKTDatum+4);
-        for( i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ )
+        for( int i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ )
         {
             if( nDatum == asDatumInfoList[i].nMapInfoDatumID )
             {
@@ -1949,10 +1806,8 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
     else if( STARTS_WITH_CI(pszWKTDatum, "MIF ")
              && (atoi(pszWKTDatum+4) == 999 || atoi(pszWKTDatum+4) == 9999) )
     {
-        char **papszFields;
-
         sTABProj.nDatumId = static_cast<GInt16>(atoi(pszWKTDatum+4));
-        papszFields =
+        char **papszFields =
             CSLTokenizeStringComplex( pszWKTDatum+4, ",", FALSE, TRUE);
 
         if( CSLCount(papszFields) >= 5 )
@@ -1989,12 +1844,10 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
      *----------------------------------------------------------------*/
     else
     {
-        int     i;
-
-        for( i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ )
+        for( int i = 0; asDatumInfoList[i].nMapInfoDatumID != -1; i++ )
         {
-        	if ( (nDatumEPSGCode > 0 && asDatumInfoList[i].nDatumEPSGCode == nDatumEPSGCode) ||
-        		   EQUAL(pszWKTDatum,asDatumInfoList[i].pszOGCDatumName) )
+            if ( (nDatumEPSGCode > 0 && asDatumInfoList[i].nDatumEPSGCode == nDatumEPSGCode) ||
+                 EQUAL(pszWKTDatum,asDatumInfoList[i].pszOGCDatumName) )
             {
                 psDatumInfo = asDatumInfoList + i;
                 break;
@@ -2058,12 +1911,15 @@ int TABFile::GetTABProjFromSpatialRef(const OGRSpatialReference* poSpatialRef,
     }
 
     // Google Merc
-    if( (poSpatialRef->GetAuthorityName(NULL) != NULL &&
-        EQUAL(poSpatialRef->GetAuthorityName(NULL), "EPSG") &&
-        poSpatialRef->GetAuthorityCode(NULL) != NULL &&
-        atoi(poSpatialRef->GetAuthorityCode(NULL)) == 3857) ||
-        (poSpatialRef->GetExtension(NULL, "PROJ4") != NULL &&
-         EQUAL(poSpatialRef->GetExtension(NULL, "PROJ4"),
+    const char* pszAuthorityName = NULL;
+    const char* pszAuthorityCode = NULL;
+    const char* pszExtension = NULL;
+    if( ((pszAuthorityName = poSpatialRef->GetAuthorityName(NULL)) != NULL &&
+        EQUAL(pszAuthorityName, "EPSG") &&
+        (pszAuthorityCode = poSpatialRef->GetAuthorityCode(NULL)) != NULL &&
+        atoi(pszAuthorityCode) == 3857) ||
+        ((pszExtension = poSpatialRef->GetExtension(NULL, "PROJ4")) != NULL &&
+         EQUAL(pszExtension,
                "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs")) )
     {
         sTABProj.nDatumId = 157;
diff --git a/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp b/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp
index e4dbcc7..52b0e5b 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_tabfile.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_tabfile.cpp,v 1.78 2010-10-08 18:40:12 aboudreault Exp $
  *
  * Name:     mitab_tabfile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -30,123 +29,68 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_tabfile.cpp,v $
- * Revision 1.78  2010-10-08 18:40:12  aboudreault
- * Fixed missing initializations that cause crashes
- *
- * Revision 1.77  2010-10-08 18:38:13  aboudreault
- * Added attribute index support for the sql queries in mapinfo tab format
- * (GDAL bug #3687)
- *
- * Revision 1.76  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.75  2010-07-05 14:58:33  aboudreault
- * Fixed bad feature count after we deleted a feature in MapInfo (bug 2227)
- *
- * Revision 1.74  2010-01-07 20:39:12  aboudreault
- * Added support to handle duplicate field names, Added validation to check
- * if a field name start with a number (bug 2141)
- *
- * Revision 1.73  2008-11-27 20:50:23  aboudreault
- * Improved support for OGR date/time types. New Read/Write methods (bug 1948)
- * Added support of OGR date/time types for MIF features.
- *
- * Revision 1.72  2008/11/17 22:06:21  aboudreault
- * Added support to use OFTDateTime/OFTDate/OFTTime type when compiled with
- * OGR and fixed reading/writing support for these types.
- *
- * Revision 1.71  2008/09/26 14:40:24  aboudreault
- * Fixed bug: MITAB doesn't support writing DateTime type (bug 1948)
- *
- * Revision 1.70  2008/06/13 18:39:21  aboudreault
- * Fixed problem with corrupt pointer if file not found (bug 1899) and
- * fixed tabdump build problem if DEBUG option not provided (bug 1898)
- *
- * Revision 1.69  2008/03/05 20:59:10  dmorissette
- * Purged CVS logs in header
- *
- * Revision 1.68  2008/03/05 20:35:39  dmorissette
- * Replace MITAB 1.x SetFeature() with a CreateFeature() for V2.x (bug 1859)
- *
- * Revision 1.67  2008/01/29 21:56:39  dmorissette
- * Update dataset version properly for Date/Time/DateTime field types (#1754)
- *
- * Revision 1.66  2008/01/29 20:46:32  dmorissette
- * Added support for v9 Time and DateTime fields (byg 1754)
- *
- * Revision 1.65  2007/09/12 20:22:31  dmorissette
- * Added TABFeature::CreateFromMapInfoType()
- *
- * Revision 1.64  2007/06/21 14:00:23  dmorissette
- * Added missing cast in isspace() calls to avoid failed assertion on Windows
- * (MITAB bug 1737, GDAL ticket 1678))
- *
- * Revision 1.63  2007/06/12 13:52:38  dmorissette
- * Added IMapInfoFile::SetCharset() method (bug 1734)
- *
- * Revision 1.62  2007/06/12 12:50:40  dmorissette
- * Use Quick Spatial Index by default until bug 1732 is fixed (broken files
- * produced by current coord block splitting technique).
- *
- * Revision 1.61  2007/03/21 21:15:56  dmorissette
- * Added SetQuickSpatialIndexMode() which generates a non-optimal spatial
- * index but results in faster write time (bug 1669)
- *
- * ...
- *
- * Revision 1.1  1999/07/12 04:18:25  daniel
- * Initial checkin
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
-#include "mitab_utils.h"
+
+#include <cctype>
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_minixml.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
+#include "mitab_utils.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
 #include "ogr_p.h"
+#include "ogr_spatialref.h"
+#include "ogrsf_frmts.h"
 
-#include <ctype.h>      /* isspace() */
+CPL_CVSID("$Id: mitab_tabfile.cpp 37351 2017-02-12 05:22:20Z goatbar $");
 
-#define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
+static const char UNSUPPORTED_OP_READ_ONLY[] =
+  "%s : unsupported operation on a read-only datasource.";
 
 /*=====================================================================
  *                      class TABFile
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABFile::TABFile()
  *
  * Constructor.
  **********************************************************************/
-TABFile::TABFile()
+TABFile::TABFile() :
+    m_pszFname(NULL),
+    m_eAccessMode(TABRead),
+    m_papszTABFile(NULL),
+    m_nVersion(300),
+    m_panIndexNo(NULL),
+    m_eTableType(TABTableNative),
+    m_poDATFile(NULL),
+    m_poMAPFile(NULL),
+    m_poINDFile(NULL),
+    m_poDefn(NULL),
+    m_poSpatialRef(NULL),
+    bUseSpatialTraversal(FALSE),
+    m_nLastFeatureId(0),
+    m_panMatchingFIDs(NULL),
+    m_iMatchingFID(0),
+    m_bNeedTABRewrite(FALSE),
+    m_bLastOpWasRead(FALSE),
+    m_bLastOpWasWrite(FALSE)
 {
-    m_eAccessMode = TABRead;
-    m_pszFname = NULL;
-    m_papszTABFile = NULL;
-    m_nVersion = 300;
-    m_eTableType = TABTableNative;
-
-    m_poMAPFile = NULL;
-    m_poDATFile = NULL;
-    m_poINDFile = NULL;
-    m_poDefn = NULL;
-    m_poSpatialRef = NULL;
     m_poCurFeature = NULL;
     m_nCurFeatureId = 0;
-    m_nLastFeatureId = 0;
-    m_panIndexNo = NULL;
-
-    bUseSpatialTraversal = FALSE;
-
-    m_panMatchingFIDs = NULL;
-    m_iMatchingFID = 0;
-
-    m_bNeedTABRewrite = FALSE;
-    m_bLastOpWasRead = FALSE;
-    m_bLastOpWasWrite = FALSE;
 }
 
 /**********************************************************************
@@ -159,7 +103,6 @@ TABFile::~TABFile()
     Close();
 }
 
-
 /************************************************************************/
 /*                         GetFeatureCount()                          */
 /************************************************************************/
@@ -199,12 +142,13 @@ void TABFile::ResetReading()
 
         if( m_poFilterGeom != NULL )
         {
-            OGREnvelope  sEnvelope;
-            TABVertex sMin, sMax;
-            /* TABMAPHeaderBlock *poHeader; */
-            /* poHeader = m_poMAPFile->GetHeaderBlock(); */
+            // TABMAPHeaderBlock *poHeader = m_poMAPFile->GetHeaderBlock();
 
+            OGREnvelope  sEnvelope;
             m_poFilterGeom->getEnvelope( &sEnvelope );
+
+            TABVertex sMin;
+            TABVertex sMax;
             m_poMAPFile->GetCoordFilter( sMin, sMax );
 
             if( sEnvelope.MinX > sMin.x
@@ -298,7 +242,6 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
 
     pszTmpFname = CPLStrdup(m_pszFname);
 
-
 #ifndef _WIN32
     /*-----------------------------------------------------------------
      * On Unix, make sure extension uses the right cases
@@ -374,7 +317,6 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
         m_bNeedTABRewrite = TRUE;
     }
 
-
     /*-----------------------------------------------------------------
      * Open .DAT file (or .DBF)
      *----------------------------------------------------------------*/
@@ -412,7 +354,6 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
 
     m_nLastFeatureId = m_poDATFile->GetNumRecords();
 
-
     /*-----------------------------------------------------------------
      * Parse .TAB file field defs and build FeatureDefn (only in read access)
      *----------------------------------------------------------------*/
@@ -427,7 +368,6 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
         return -1;
     }
 
-
     /*-----------------------------------------------------------------
      * Open .MAP (and .ID) file
      * Note that the .MAP and .ID files are optional.  Failure to open them
@@ -539,7 +479,6 @@ int TABFile::Open(const char *pszFname, TABAccess eAccess,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABFile::ParseTABFileFirstPass()
  *
@@ -589,7 +528,6 @@ int TABFile::ParseTABFileFirstPass(GBool bTestOpenNoError)
                 m_pszCharset = CPLStrdup("Neutral");
                 m_eTableType = TABTableNative;
             }
-
         }
         else if (EQUAL(papszTok[0], "!edit_version"))
         {
@@ -689,9 +627,6 @@ int TABFile::ParseTABFileFirstPass(GBool bTestOpenNoError)
  **********************************************************************/
 int TABFile::ParseTABFileFields()
 {
-    int         iLine, numLines=0, numTok, nStatus;
-    char        **papszTok=NULL;
-    OGRFieldDefn *poFieldDefn;
 
     if (m_eAccessMode == TABWrite)
     {
@@ -709,8 +644,13 @@ int TABFile::ParseTABFileFields()
     /*-------------------------------------------------------------
      * Scan for fields.
      *------------------------------------------------------------*/
-    numLines = CSLCount(m_papszTABFile);
-    for(iLine=0; iLine<numLines; iLine++)
+    OGRFieldDefn *poFieldDefn = NULL;
+    char **papszTok = NULL;
+
+    const int numLines = CSLCount(m_papszTABFile);
+    int numTok = 0;
+    int nStatus = 0;
+    for( int iLine=0; iLine<numLines; iLine++ )
     {
         /*-------------------------------------------------------------
          * Tokenize the next .TAB line, and check first keyword
@@ -724,8 +664,8 @@ int TABFile::ParseTABFileFields()
             /*---------------------------------------------------------
              * We found the list of table fields
              *--------------------------------------------------------*/
-            int iField, numFields;
-            numFields = atoi(pszStr+7);
+            int iField = 0;
+            int numFields = atoi(pszStr+7);
             if (numFields < 1 || numFields > 2048 ||
                 iLine+numFields >= numLines)
             {
@@ -936,7 +876,6 @@ int TABFile::ParseTABFileFields()
         {
             // Simply Ignore unrecognized lines
         }
-
     }
 
     CSLDestroy(papszTok);
@@ -963,8 +902,6 @@ int TABFile::ParseTABFileFields()
  **********************************************************************/
 int TABFile::WriteTABFile()
 {
-    VSILFILE *fp;
-
     if (!m_bNeedTABRewrite )
     {
         return 0;
@@ -979,9 +916,10 @@ int TABFile::WriteTABFile()
 
     // First update file version number...
     int nMapObjVersion = m_poMAPFile->GetMinTABFileVersion();
-    m_nVersion = MAX(m_nVersion, nMapObjVersion);
+    m_nVersion = std::max(m_nVersion, nMapObjVersion);
 
-    if ( (fp = VSIFOpenL(m_pszFname, "wt")) != NULL)
+    VSILFILE *fp = VSIFOpenL(m_pszFname, "wt");
+    if( fp != NULL )
     {
         VSIFPrintfL(fp, "!table\n");
         VSIFPrintfL(fp, "!version %d\n", m_nVersion);
@@ -990,17 +928,14 @@ int TABFile::WriteTABFile()
 
         if (m_poDefn && m_poDefn->GetFieldCount() > 0)
         {
-            int iField;
-            OGRFieldDefn *poFieldDefn;
-            const char *pszFieldType;
-
             VSIFPrintfL(fp, "Definition Table\n");
             VSIFPrintfL(fp, "  Type NATIVE Charset \"%s\"\n", m_pszCharset);
             VSIFPrintfL(fp, "  Fields %d\n", m_poDefn->GetFieldCount());
 
-            for(iField=0; iField<m_poDefn->GetFieldCount(); iField++)
+            for( int iField = 0; iField < m_poDefn->GetFieldCount(); iField++ )
             {
-                poFieldDefn = m_poDefn->GetFieldDefn(iField);
+                const char *pszFieldType = NULL;
+                OGRFieldDefn *poFieldDefn = m_poDefn->GetFieldDefn(iField);
                 switch(GetNativeFieldType(iField))
                 {
                   case TABFChar:
@@ -1060,7 +995,6 @@ int TABFile::WriteTABFile()
                             poFieldDefn->GetNameRef(), pszFieldType,
                             GetFieldIndexNumber(iField) );
                 }
-
             }
         }
         else
@@ -1183,12 +1117,9 @@ int TABFile::SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode/*=TRUE*/)
         return -1;
     }
 
-
     return m_poMAPFile->SetQuickSpatialIndexMode(bQuickSpatialIndexMode);
 }
 
-
-
 /**********************************************************************
  *                   TABFile::GetNextFeatureId()
  *
@@ -1506,7 +1437,7 @@ int TABFile::WriteFeature(TABFeature *poFeature)
         return -1;
     }
 
-    int nFeatureId;
+    int nFeatureId = 0;
     if ( poFeature->GetFID() >= 0 )
     {
         nFeatureId = (int)poFeature->GetFID();
@@ -1534,7 +1465,6 @@ int TABFile::WriteFeature(TABFeature *poFeature)
 
     poFeature->SetFID(nFeatureId);
 
-
     /*-----------------------------------------------------------------
      * Write fields to the .DAT file and update .IND if necessary
      *----------------------------------------------------------------*/
@@ -1585,7 +1515,7 @@ int TABFile::WriteFeature(TABFeature *poFeature)
      * feature's IntMBR. Store that value in the ObjHdr for use by
      * PrepareNewObj() to search the best node to insert the feature.
      *----------------------------------------------------------------*/
-    if ( poObjHdr && poObjHdr->m_nType != TAB_GEOM_NONE)
+    if ( poObjHdr->m_nType != TAB_GEOM_NONE)
     {
         poFeature->GetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
                              poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
@@ -1610,7 +1540,7 @@ int TABFile::WriteFeature(TABFeature *poFeature)
         return -1;
     }
 
-    m_nLastFeatureId = MAX(m_nLastFeatureId, nFeatureId);
+    m_nLastFeatureId = std::max(m_nLastFeatureId, nFeatureId);
     m_nCurFeatureId = nFeatureId;
 
     delete poObjHdr;
@@ -1618,7 +1548,6 @@ int TABFile::WriteFeature(TABFeature *poFeature)
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABFile::CreateFeature()
  *
@@ -1800,7 +1729,6 @@ OGRErr TABFile::ISetFeature( OGRFeature *poFeature )
     return OGRERR_NONE;
 }
 
-
 /**********************************************************************
  *                   TABFile::GetLayerDefn()
  *
@@ -1834,11 +1762,6 @@ OGRFeatureDefn *TABFile::GetLayerDefn()
 int TABFile::SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
                          TABFieldType *paeMapInfoNativeFieldTypes /* =NULL */)
 {
-    int           iField, numFields;
-    OGRFieldDefn *poFieldDefn;
-    TABFieldType eMapInfoType = TABFUnknown;
-    int nStatus = 0;
-
     if (m_eAccessMode != TABWrite)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -1869,10 +1792,12 @@ int TABFile::SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
         return -1;
     }
 
-    numFields = poFeatureDefn->GetFieldCount();
-    for(iField=0; nStatus==0 && iField < numFields; iField++)
+    const int numFields = poFeatureDefn->GetFieldCount();
+    TABFieldType eMapInfoType = TABFUnknown;
+    int nStatus = 0;
+    for( int iField = 0; nStatus==0 && iField < numFields; iField++ )
     {
-        poFieldDefn = m_poDefn->GetFieldDefn(iField);
+        OGRFieldDefn *poFieldDefn = m_poDefn->GetFieldDefn(iField);
 
         /*-------------------------------------------------------------
          * Make sure field name is valid... check for special chars, etc.
@@ -1952,12 +1877,6 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                             int nWidth /*=0*/, int nPrecision /*=0*/,
                             GBool bIndexed /*=FALSE*/, GBool /*bUnique=FALSE*/, int bApproxOK)
 {
-    OGRFieldDefn *poFieldDefn;
-    int nStatus = 0;
-    char *pszCleanName = NULL;
-    char szNewFieldName[31+1]; /* 31 is the max characters for a field name*/
-    int nRenameNum = 1;
-
     if (m_eAccessMode == TABRead || m_poDATFile == NULL)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
@@ -1990,7 +1909,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
      * Make sure field name is valid... check for special chars, etc.
      * (pszCleanName will have to be freed.)
      *----------------------------------------------------------------*/
-    pszCleanName = TABCleanFieldName(pszName);
+    char *pszCleanName = TABCleanFieldName(pszName);
 
     if( !bApproxOK &&
         ( m_poDefn->GetFieldIndex(pszCleanName) >= 0 ||
@@ -2001,14 +1920,17 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                   pszName );
     }
 
-    strncpy(szNewFieldName, pszCleanName, 31);
-    szNewFieldName[31] = '\0';
+    char szNewFieldName[31+1];  // 31 is the max characters for a field name.
+    strncpy(szNewFieldName, pszCleanName, sizeof(szNewFieldName)-1);
+    szNewFieldName[sizeof(szNewFieldName)-1] = '\0';
+
+    int nRenameNum = 1;
 
     while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 10)
-      snprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s_%.1d", pszCleanName, nRenameNum++ );
+      CPLsnprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s_%.1d", pszCleanName, nRenameNum++ );
 
     while (m_poDefn->GetFieldIndex(szNewFieldName) >= 0 && nRenameNum < 100)
-      snprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s%.2d", pszCleanName, nRenameNum++ );
+      CPLsnprintf( szNewFieldName, sizeof(szNewFieldName), "%.29s%.2d", pszCleanName, nRenameNum++ );
 
     if (m_poDefn->GetFieldIndex(szNewFieldName) >= 0)
     {
@@ -2028,7 +1950,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     /*-----------------------------------------------------------------
      * Map MapInfo native types to OGR types
      *----------------------------------------------------------------*/
-    poFieldDefn = NULL;
+    OGRFieldDefn *poFieldDefn = NULL;
 
     switch(eMapInfoType)
     {
@@ -2080,7 +2002,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                                    OFTString);
 #endif
         poFieldDefn->SetWidth(10);
-        m_nVersion = MAX(m_nVersion, 450);
+        m_nVersion = std::max(m_nVersion, 450);
         break;
       case TABFTime:
         /*-------------------------------------------------
@@ -2093,7 +2015,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                                    OFTString);
 #endif
         poFieldDefn->SetWidth(8);
-        m_nVersion = MAX(m_nVersion, 900);
+        m_nVersion = std::max(m_nVersion, 900);
         break;
       case TABFDateTime:
         /*-------------------------------------------------
@@ -2106,7 +2028,7 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
                                                    OFTString);
 #endif
         poFieldDefn->SetWidth(19);
-        m_nVersion = MAX(m_nVersion, 900);
+        m_nVersion = std::max(m_nVersion, 900);
         break;
       case TABFLogical:
         /*-------------------------------------------------
@@ -2131,8 +2053,8 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     /*-----------------------------------------------------
      * ... and pass field info to the .DAT file.
      *----------------------------------------------------*/
-    nStatus = m_poDATFile->AddField(szNewFieldName, eMapInfoType,
-                                    nWidth, nPrecision);
+    int nStatus = m_poDATFile->AddField(szNewFieldName, eMapInfoType,
+                                        nWidth, nPrecision);
 
     /*-----------------------------------------------------------------
      * Extend the array to keep track of indexed fields (default=NOT indexed)
@@ -2154,7 +2076,6 @@ int TABFile::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     return nStatus;
 }
 
-
 /**********************************************************************
  *                   TABFile::GetNativeFieldType()
  *
@@ -2174,8 +2095,6 @@ TABFieldType TABFile::GetNativeFieldType(int nFieldId)
     return TABFUnknown;
 }
 
-
-
 /**********************************************************************
  *                   TABFile::GetFieldIndexNumber()
  *
@@ -2231,7 +2150,6 @@ int TABFile::SetFieldIndexed( int nFieldId )
     if (m_panIndexNo[nFieldId] != 0)
         return 0;  // Nothing to do
 
-
     /*-----------------------------------------------------------------
      * Create .IND file if it's not done yet.
      *
@@ -2254,12 +2172,14 @@ int TABFile::SetFieldIndexed( int nFieldId )
     /*-----------------------------------------------------------------
      * Init new index.
      *----------------------------------------------------------------*/
-    int nNewIndexNo;
     OGRFieldDefn *poFieldDefn = m_poDefn->GetFieldDefn(nFieldId);
 
-    if (poFieldDefn == NULL ||
-        (nNewIndexNo = m_poINDFile->CreateIndex(GetNativeFieldType(nFieldId),
-                                                poFieldDefn->GetWidth()) ) < 1)
+    if( poFieldDefn == NULL )
+        return -1;
+    const int nNewIndexNo =
+        m_poINDFile->CreateIndex(GetNativeFieldType(nFieldId),
+                                 poFieldDefn->GetWidth());
+    if( nNewIndexNo < 1 )
     {
         // Failed... an error has already been reported.
         return -1;
@@ -2277,11 +2197,9 @@ int TABFile::SetFieldIndexed( int nFieldId )
  ************************************************************************/
 GBool TABFile::IsFieldIndexed( int nFieldId )
 {
-    return (GetFieldIndexNumber(nFieldId) > 0 ? TRUE:FALSE);
+    return GetFieldIndexNumber(nFieldId) > 0 ? TRUE : FALSE;
 }
 
-
-
 /**********************************************************************
  *                   TABFile::GetINDFileRef()
  *
@@ -2336,7 +2254,6 @@ TABINDFile  *TABFile::GetINDFileRef()
     return m_poINDFile;
 }
 
-
 /**********************************************************************
  *                   TABFile::SetBounds()
  *
@@ -2377,7 +2294,6 @@ int TABFile::SetBounds(double dXMin, double dYMin,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABFile::GetBounds()
  *
@@ -2392,37 +2308,38 @@ int TABFile::GetBounds(double &dXMin, double &dYMin,
                        double &dXMax, double &dYMax,
                        GBool /*bForce = TRUE*/)
 {
-    TABMAPHeaderBlock *poHeader;
-
-    if (m_poMAPFile && (poHeader=m_poMAPFile->GetHeaderBlock()) != NULL)
+    if (m_poMAPFile)
     {
+        TABMAPHeaderBlock* poHeader =m_poMAPFile->GetHeaderBlock();
+        if( poHeader != NULL)
+        {
         /*-------------------------------------------------------------
          * Projection bounds correspond to the +/- 1e9 integer coord. limits
          *------------------------------------------------------------*/
-        double dX0, dX1, dY0, dY1;
-        m_poMAPFile->Int2Coordsys(-1000000000, -1000000000,
-                                  dX0, dY0);
-        m_poMAPFile->Int2Coordsys(1000000000, 1000000000,
-                                  dX1, dY1);
+            double dX0 = 0.0;
+            double dX1 = 0.0;
+            double dY0 = 0.0;
+            double dY1 = 0.0;
+            m_poMAPFile->Int2Coordsys(-1000000000, -1000000000,
+                                    dX0, dY0);
+            m_poMAPFile->Int2Coordsys(1000000000, 1000000000,
+                                        dX1, dY1);
         /*-------------------------------------------------------------
          * ... and make sure that Min < Max
-         *------------------------------------------------------------*/
-        dXMin = MIN(dX0, dX1);
-        dXMax = MAX(dX0, dX1);
-        dYMin = MIN(dY0, dY1);
-        dYMax = MAX(dY0, dY1);
-    }
-    else
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-             "GetBounds() can be called only after dataset has been opened.");
-        return -1;
+            *------------------------------------------------------------*/
+            dXMin = std::min(dX0, dX1);
+            dXMax = std::max(dX0, dX1);
+            dYMin = std::min(dY0, dY1);
+            dYMax = std::max(dY0, dY1);
+            return 0;
+        }
     }
 
-    return 0;
+    CPLError(CE_Failure, CPLE_AppDefined,
+            "GetBounds() can be called only after dataset has been opened.");
+    return -1;
 }
 
-
 /**********************************************************************
  *                   TABFile::GetExtent()
  *
@@ -2436,11 +2353,14 @@ int TABFile::GetBounds(double &dXMin, double &dYMin,
 OGRErr TABFile::GetExtent (OGREnvelope *psExtent,
                            CPL_UNUSED int bForce)
 {
-    TABMAPHeaderBlock *poHeader;
+    TABMAPHeaderBlock *poHeader = NULL;
 
     if (m_poMAPFile && (poHeader=m_poMAPFile->GetHeaderBlock()) != NULL)
     {
-        double dX0, dX1, dY0, dY1;
+        double dX0 = 0.0;
+        double dX1 = 0.0;
+        double dY0 = 0.0;
+        double dY1 = 0.0;
         /*-------------------------------------------------------------
          * Fetch extent of the data from the .map header block
          * this value is different from the projection bounds.
@@ -2453,10 +2373,10 @@ OGRErr TABFile::GetExtent (OGREnvelope *psExtent,
        /*-------------------------------------------------------------
          * ... and make sure that Min < Max
          *------------------------------------------------------------*/
-        psExtent->MinX = MIN(dX0, dX1);
-        psExtent->MaxX = MAX(dX0, dX1);
-        psExtent->MinY = MIN(dY0, dY1);
-        psExtent->MaxY = MAX(dY0, dY1);
+        psExtent->MinX = std::min(dX0, dX1);
+        psExtent->MaxX = std::max(dX0, dX1);
+        psExtent->MinY = std::min(dY0, dY1);
+        psExtent->MaxY = std::max(dY0, dY1);
 
         return OGRERR_NONE;
     }
@@ -2483,7 +2403,7 @@ int TABFile::GetFeatureCountByType(int &numPoints, int &numLines,
                                    int &numRegions, int &numTexts,
                                    GBool /* bForce = TRUE*/ )
 {
-    TABMAPHeaderBlock *poHeader;
+    TABMAPHeaderBlock *poHeader = NULL;
 
     if (m_poMAPFile && (poHeader=m_poMAPFile->GetHeaderBlock()) != NULL)
     {
@@ -2501,7 +2421,6 @@ int TABFile::GetFeatureCountByType(int &numPoints, int &numLines,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABFile::SetMIFCoordSys()
  *
@@ -2526,18 +2445,20 @@ int TABFile::SetMIFCoordSys(const char *pszMIFCoordSys)
      *----------------------------------------------------------------*/
     if (m_poMAPFile && m_nLastFeatureId < 1)
     {
-        OGRSpatialReference *poSpatialRef;
-
-        poSpatialRef = MITABCoordSys2SpatialRef( pszMIFCoordSys );
+        OGRSpatialReference *poSpatialRef =
+            MITABCoordSys2SpatialRef( pszMIFCoordSys );
 
         if (poSpatialRef)
         {
-            double dXMin, dYMin, dXMax, dYMax;
+            double dXMin = 0.0;
+            double dYMin = 0.0;
+            double dXMax = 0.0;
+            double dYMax = 0.0;
             if (SetSpatialRef(poSpatialRef) == 0)
             {
-                if (MITABExtractCoordSysBounds(pszMIFCoordSys,
+                if( MITABExtractCoordSysBounds(pszMIFCoordSys,
                                                dXMin, dYMin,
-                                               dXMax, dYMax) == TRUE)
+                                               dXMax, dYMax) )
                 {
                     // If the coordsys string contains bounds, then use them
                     if (SetBounds(dXMin, dYMin, dXMax, dYMax) != 0)
@@ -2596,10 +2517,13 @@ int TABFile::SetProjInfo(TABProjInfo *poPI)
     /*-----------------------------------------------------------------
      * Lookup default bounds and reset m_bBoundsSet flag
      *----------------------------------------------------------------*/
-    double dXMin, dYMin, dXMax, dYMax;
+    double dXMin;
+    double dYMin;
+    double dXMax;
+    double dYMax;
 
     m_bBoundsSet = FALSE;
-    if (MITABLookupCoordSysBounds(poPI, dXMin, dYMin, dXMax, dYMax) == TRUE)
+    if( MITABLookupCoordSysBounds(poPI, dXMin, dYMin, dXMax, dYMax) )
     {
         SetBounds(dXMin, dYMin, dXMax, dYMax);
     }
@@ -2623,7 +2547,6 @@ int TABFile::SetProjInfo(TABProjInfo *poPI)
     return 0;
 }
 
-
 /************************************************************************/
 /*                            DeleteField()                             */
 /************************************************************************/
@@ -2860,16 +2783,15 @@ void TABFile::Dump(FILE *fpOut /*=NULL*/)
         fprintf(fpOut, "... end of TABLE file dump.\n\n");
         if( GetSpatialRef() != NULL )
         {
-            char        *pszWKT;
+            char *pszWKT = NULL;
 
             GetSpatialRef()->exportToWkt( &pszWKT );
             fprintf( fpOut, "SRS = %s\n", pszWKT );
-            OGRFree( pszWKT );
+            CPLFree( pszWKT );
         }
         fprintf(fpOut, "Associated .MAP file ...\n\n");
         m_poMAPFile->Dump(fpOut);
         fprintf(fpOut, "... end of .MAP file dump.\n\n");
-
     }
 
     fflush(fpOut);
diff --git a/ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp b/ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp
index b9ff062..dd2bcb6 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_tabseamless.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_tabseamless.cpp,v 1.10 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_tabseamless.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -29,50 +28,26 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_tabseamless.cpp,v $
- * Revision 1.10  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.9  2009-03-10 13:50:02  aboudreault
- * Fixed Overflow of FIDs in Seamless tables (bug 2015)
- *
- * Revision 1.8  2009-03-04 21:22:44  dmorissette
- * Set m_nCurFeatureId=-1 in TABSeamless::ResetReading() (bug 2017)
- *
- * Revision 1.7  2007-06-21 14:00:23  dmorissette
- * Added missing cast in isspace() calls to avoid failed assertion on Windows
- * (MITAB bug 1737, GDAL ticket 1678))
- *
- * Revision 1.6  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.5  2004/03/12 16:29:05  dmorissette
- * Fixed 2 memory leaks (bug 283)
- *
- * Revision 1.4  2002/06/28 18:32:37  julien
- * Add SetSpatialFilter() in TABSeamless class (Bug 164, MapServer)
- * Use double for comparison in Coordsys2Int() in mitab_mapheaderblock.cpp
- *
- * Revision 1.3  2001/09/19 14:21:36  daniel
- * On Unix: replace '\\' in file path read from tab index with '/'
- *
- * Revision 1.2  2001/03/15 03:57:51  daniel
- * Added implementation for new OGRLayer::GetExtent(), returning data MBR.
- *
- * Revision 1.1  2001/03/09 04:38:04  danmo
- * Update from master - version 1.1.0
- *
- * Revision 1.1  2001/03/09 04:16:02  daniel
- * Added TABSeamless for reading seamless TAB files
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <cctype>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "mitab_priv.h"
 #include "mitab_utils.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
+#include "ogrsf_frmts.h"
 
-#include <ctype.h>      /* isspace() */
+CPL_CVSID("$Id: mitab_tabseamless.cpp 37351 2017-02-12 05:22:20Z goatbar $");
 
 /*=====================================================================
  *                      class TABSeamless
@@ -89,26 +64,24 @@
  *
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABSeamless::TABSeamless()
  *
  * Constructor.
  **********************************************************************/
-TABSeamless::TABSeamless()
+TABSeamless::TABSeamless() :
+    m_pszFname(NULL),
+    m_pszPath(NULL),
+    m_eAccessMode(TABRead),
+    m_poFeatureDefnRef(NULL),
+    m_poIndexTable(NULL),
+    m_nTableNameField(-1),
+    m_nCurBaseTableId(-1),
+    m_poCurBaseTable(NULL),
+    m_bEOF(FALSE)
 {
-    m_pszFname = NULL;
-    m_pszPath = NULL;
-    m_eAccessMode = TABRead;
-    m_poFeatureDefnRef = NULL;
     m_poCurFeature = NULL;
     m_nCurFeatureId = -1;
-
-    m_poIndexTable = NULL;
-    m_nTableNameField = -1;
-    m_nCurBaseTableId = -1;
-    m_poCurBaseTable = NULL;
-    m_bEOF = FALSE;
 }
 
 /**********************************************************************
@@ -121,7 +94,6 @@ TABSeamless::~TABSeamless()
     Close();
 }
 
-
 void TABSeamless::ResetReading()
 {
     if (m_poIndexTable)
@@ -132,7 +104,6 @@ void TABSeamless::ResetReading()
     m_nCurFeatureId = -1;
 }
 
-
 /**********************************************************************
  *                   TABSeamless::Open()
  *
@@ -179,7 +150,6 @@ int TABSeamless::Open(const char *pszFname, TABAccess eAccess,
     return nStatus;
 }
 
-
 /**********************************************************************
  *                   TABSeamless::OpenForRead()
  *
@@ -321,7 +291,6 @@ int TABSeamless::OpenForRead(const char *pszFname,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABSeamless::Close()
  *
@@ -521,7 +490,6 @@ int TABSeamless::OpenNextBaseTable(GBool bTestOpenNoError /*=FALSE*/)
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABSeamless::EncodeFeatureId()
  *
@@ -536,7 +504,7 @@ GIntBig TABSeamless::EncodeFeatureId(int nTableId, int nBaseFeatureId)
     /* Feature encoding is now based on the numbers of bits on the number
        of features in the index table. */
 
-    return (((GIntBig)nTableId<<32) + nBaseFeatureId);
+    return ((GIntBig)nTableId<<32) + nBaseFeatureId;
 }
 
 int TABSeamless::ExtractBaseTableId(GIntBig nEncodedFeatureId)
@@ -544,7 +512,7 @@ int TABSeamless::ExtractBaseTableId(GIntBig nEncodedFeatureId)
     if (nEncodedFeatureId == -1)
         return -1;
 
-    return ((int)(nEncodedFeatureId>>32));
+    return (int)(nEncodedFeatureId>>32);
 }
 
 int TABSeamless::ExtractBaseFeatureId(GIntBig nEncodedFeatureId)
@@ -552,7 +520,7 @@ int TABSeamless::ExtractBaseFeatureId(GIntBig nEncodedFeatureId)
     if (nEncodedFeatureId == -1)
         return -1;
 
-    return ((int)(nEncodedFeatureId & 0xffffffff));
+    return (int)(nEncodedFeatureId & 0xffffffff);
 }
 
 /**********************************************************************
@@ -580,7 +548,6 @@ GIntBig TABSeamless::GetNextFeatureId(GIntBig nPrevId)
             return EncodeFeatureId(m_nCurBaseTableId, nId);  // Found one!
         else
             OpenNextBaseTable();  // Skip to next tile and loop again
-
     } while (nId == -1 && !m_bEOF && m_poCurBaseTable);
 
     return -1;
@@ -637,7 +604,6 @@ TABFeature *TABSeamless::GetFeatureRef(GIntBig nFeatureId)
     return NULL;
 }
 
-
 /**********************************************************************
  *                   TABSeamless::GetLayerDefn()
  *
@@ -672,8 +638,6 @@ TABFieldType TABSeamless::GetNativeFieldType(int nFieldId)
     return TABFUnknown;
 }
 
-
-
 /**********************************************************************
  *                   TABSeamless::IsFieldIndexed()
  *
@@ -700,7 +664,6 @@ GBool TABSeamless::IsFieldUnique(int nFieldId)
     return FALSE;
 }
 
-
 /**********************************************************************
  *                   TABSeamless::GetBounds()
  *
@@ -711,9 +674,9 @@ GBool TABSeamless::IsFieldUnique(int nFieldId)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int TABSeamless::GetBounds(double &dXMin, double &dYMin,
-                       double &dXMax, double &dYMax,
-                       GBool bForce /*= TRUE*/)
+int TABSeamless::GetBounds( double &dXMin, double &dYMin,
+                            double &dXMax, double &dYMax,
+                            GBool bForce /*= TRUE*/ )
 {
     if (m_poIndexTable == NULL)
     {
@@ -745,7 +708,6 @@ OGRErr TABSeamless::GetExtent (OGREnvelope *psExtent, int bForce)
     }
 
     return m_poIndexTable->GetExtent(psExtent, bForce);
-
 }
 
 /**********************************************************************
@@ -784,7 +746,6 @@ GIntBig TABSeamless::GetFeatureCount(int bForce)
     return OGRLayer::GetFeatureCount(bForce);
 }
 
-
 /**********************************************************************
  *                   TABSeamless::GetSpatialRef()
  *
@@ -809,8 +770,6 @@ OGRSpatialReference *TABSeamless::GetSpatialRef()
     return m_poIndexTable->GetSpatialRef();
 }
 
-
-
 /**********************************************************************
  *                   IMapInfoFile::SetSpatialFilter()
  *
@@ -829,8 +788,6 @@ void TABSeamless::SetSpatialFilter (OGRGeometry * poGeomIn )
         m_poCurBaseTable->SetSpatialFilter( poGeomIn );
 }
 
-
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -858,8 +815,6 @@ int TABSeamless::TestCapability( const char * pszCap )
         return FALSE;
 }
 
-
-
 /**********************************************************************
  *                   TABSeamless::Dump()
  *
@@ -881,7 +836,6 @@ void TABSeamless::Dump(FILE *fpOut /*=NULL*/)
     else
     {
         fprintf(fpOut, "File is opened: %s\n", m_pszFname);
-
     }
 
     fflush(fpOut);
diff --git a/ogr/ogrsf_frmts/mitab/mitab_tabview.cpp b/ogr/ogrsf_frmts/mitab/mitab_tabview.cpp
index 31caf04..4dd5fc4 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_tabview.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_tabview.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_tabview.cpp,v 1.22 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_tabfile.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -30,115 +29,52 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_tabview.cpp,v $
- * Revision 1.22  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.21  2010-07-05 19:01:20  aboudreault
- * Reverted last SetFeature change in mitab_capi.cpp and fixed another memory leak
- *
- * Revision 1.20  2010-01-07 20:39:12  aboudreault
- * Added support to handle duplicate field names, Added validation to check if a field name start with a number (bug 2141)
- *
- * Revision 1.19  2008-03-05 20:35:39  dmorissette
- * Replace MITAB 1.x SetFeature() with a CreateFeature() for V2.x (bug 1859)
- *
- * Revision 1.18  2008/01/29 20:46:32  dmorissette
- * Added support for v9 Time and DateTime fields (byg 1754)
- *
- * Revision 1.17  2007/06/21 14:00:23  dmorissette
- * Added missing cast in isspace() calls to avoid failed assertion on Windows
- * (MITAB bug 1737, GDAL ticket 1678))
- *
- * Revision 1.16  2007/06/12 13:52:38  dmorissette
- * Added IMapInfoFile::SetCharset() method (bug 1734)
- *
- * Revision 1.15  2007/06/12 12:50:40  dmorissette
- * Use Quick Spatial Index by default until bug 1732 is fixed (broken files
- * produced by current coord block splitting technique).
- *
- * Revision 1.14  2007/03/21 21:15:56  dmorissette
- * Added SetQuickSpatialIndexMode() which generates a non-optimal spatial
- * index but results in faster write time (bug 1669)
- *
- * Revision 1.13  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.12  2002/02/22 20:44:51  julien
- * Prevent infinite loop with TABRelation by suppress the m_poCurFeature object
- * from the class and setting it in the calling function and add GetFeature in
- * the class. (bug 706)
- *
- * Revision 1.11  2002/01/10 05:13:22  daniel
- * Prevent crash if .IND file is deleted (but 703)
- *
- * Revision 1.10  2002/01/10 04:52:58  daniel
- * Support 'select * ...' syntax + 'open table..." directives with/without .tab
- *
- * Revision 1.9  2001/06/27 19:52:26  warmerda
- * use VSIUnlink() instead of unlink()
- *
- * Revision 1.8  2001/03/15 03:57:51  daniel
- * Added implementation for new OGRLayer::GetExtent(), returning data MBR.
- *
- * Revision 1.7  2000/09/28 16:39:44  warmerda
- * Avoid warnings for unused, and uninitialized variables
- *
- * Revision 1.6  2000/02/28 17:12:22  daniel
- * Write support for joined tables and indexed fields
- *
- * Revision 1.5  2000/01/15 22:30:45  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.4  1999/12/19 17:40:16  daniel
- * Init + delete m_poRelation properly
- *
- * Revision 1.3  1999/12/14 05:53:00  daniel
- * Fixed compile warnings
- *
- * Revision 1.2  1999/12/14 04:04:10  daniel
- * Added bforceFlags to GetBounds() and GetFeatureCountByType()
- *
- * Revision 1.1  1999/12/14 02:10:32  daniel
- * Initial revision
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <cctype>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "mitab_priv.h"
 #include "mitab_utils.h"
+#include "ogr_core.h"
+#include "ogr_feature.h"
+#include "ogr_geometry.h"
+#include "ogr_spatialref.h"
 
-#include <ctype.h>      /* isspace() */
+CPL_CVSID("$Id: mitab_tabview.cpp 37351 2017-02-12 05:22:20Z goatbar $");
 
 /*=====================================================================
  *                      class TABView
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABView::TABView()
  *
  * Constructor.
  **********************************************************************/
-TABView::TABView()
-{
-    m_pszFname = NULL;
-    m_eAccessMode = TABRead;
-    m_papszTABFile = NULL;
-    m_pszVersion = NULL;
-
-    m_numTABFiles = 0;
-    m_papszTABFnames = NULL;
-    m_papoTABFiles = NULL;
-    m_nMainTableIndex = -1;
-
-    m_papszFieldNames = NULL;
-    m_papszWhereClause = NULL;
-
-    m_poRelation = NULL;
-    m_bRelFieldsCreated = FALSE;
-}
+TABView::TABView() :
+    m_pszFname(NULL),
+    m_eAccessMode(TABRead),
+    m_papszTABFile(NULL),
+    m_pszVersion(NULL),
+    m_papszTABFnames(NULL),
+    m_papoTABFiles(NULL),
+    m_numTABFiles(0),
+    m_nMainTableIndex(-1),
+    m_papszFieldNames(NULL),
+    m_papszWhereClause(NULL),
+    m_poRelation(NULL),
+    m_bRelFieldsCreated(FALSE)
+{}
 
 /**********************************************************************
  *                   TABView::~TABView()
@@ -150,7 +86,6 @@ TABView::~TABView()
     Close();
 }
 
-
 GIntBig TABView::GetFeatureCount (int bForce)
 {
 
@@ -166,7 +101,6 @@ void TABView::ResetReading()
         m_papoTABFiles[m_nMainTableIndex]->ResetReading();
 }
 
-
 /**********************************************************************
  *                   TABView::Open()
  *
@@ -219,7 +153,6 @@ int TABView::Open(const char *pszFname, TABAccess eAccess,
     return nStatus;
 }
 
-
 /**********************************************************************
  *                   TABView::OpenForRead()
  *
@@ -392,7 +325,6 @@ int TABView::OpenForRead(const char *pszFname,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABView::OpenForWrite()
  *
@@ -494,8 +426,6 @@ int TABView::OpenForWrite(const char *pszFname)
     return 0;
 }
 
-
-
 /**********************************************************************
  *                   TABView::ParseTABFile()
  *
@@ -570,11 +500,9 @@ int TABView::ParseTABFile(const char *pszDatasetPath,
             /*---------------------------------------------------------
              * We found the list of table fields (comma-delimited list)
              *--------------------------------------------------------*/
-            int iTok;
-            for(iTok=1; papszTok[iTok] != NULL; iTok++)
+            for( int iTok = 1; papszTok[iTok] != NULL; iTok++ )
                 m_papszFieldNames = CSLAddString(m_papszFieldNames,
                                                  papszTok[iTok]);
-
         }
         else if (bInsideTableDef &&
                  (EQUAL(papszTok[0],"where")))
@@ -654,7 +582,6 @@ int TABView::ParseTABFile(const char *pszDatasetPath,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABView::WriteTABFile()
  *
@@ -665,8 +592,6 @@ int TABView::ParseTABFile(const char *pszDatasetPath,
  **********************************************************************/
 int TABView::WriteTABFile()
 {
-    VSILFILE *fp;
-
     CPLAssert(m_eAccessMode == TABWrite);
     CPLAssert(m_numTABFiles == 2);
     CPLAssert(GetLayerDefn());
@@ -675,7 +600,8 @@ int TABView::WriteTABFile()
     char *pszTable1 = TABGetBasename(m_papszTABFnames[0]);
     char *pszTable2 = TABGetBasename(m_papszTABFnames[1]);
 
-    if ( (fp = VSIFOpenL(m_pszFname, "wt")) != NULL)
+    VSILFILE *fp = VSIFOpenL(m_pszFname, "wt");
+    if( fp != NULL )
     {
         // Version is always 100, no matter what the sub-table's version is
         VSIFPrintfL(fp, "!Table\n");
@@ -704,7 +630,6 @@ int TABView::WriteTABFile()
                                            pszTable1,
                                            m_poRelation->GetMainFieldName());
 
-
         VSIFCloseL(fp);
     }
     else
@@ -725,7 +650,6 @@ int TABView::WriteTABFile()
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABView::Close()
  *
@@ -748,7 +672,6 @@ int TABView::Close()
     m_papoTABFiles = NULL;
     m_numTABFiles = 0;
 
-
     /*-----------------------------------------------------------------
      * __TODO__ OK, MapInfo does not like to see a .map and .id file
      * attached to the second table, even if they're empty.
@@ -770,7 +693,6 @@ int TABView::Close()
     }
     // End of hack!
 
-
     CPLFree(m_pszFname);
     m_pszFname = NULL;
 
@@ -839,7 +761,6 @@ int TABView::SetQuickSpatialIndexMode(GBool bQuickSpatialIndexMode/*=TRUE*/)
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABView::GetNextFeatureId()
  *
@@ -896,7 +817,6 @@ TABFeature *TABView::GetFeatureRef(GIntBig nFeatureId)
     return m_poCurFeature;
 }
 
-
 /**********************************************************************
  *                   TABView::CreateFeature()
  *
@@ -943,8 +863,6 @@ OGRErr TABView::CreateFeature(TABFeature *poFeature)
     return OGRERR_NONE;
 }
 
-
-
 /**********************************************************************
  *                   TABView::GetLayerDefn()
  *
@@ -981,7 +899,6 @@ int TABView::SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
     return -1;
 }
 
-
 /**********************************************************************
  *                   TABView::GetNativeFieldType()
  *
@@ -1000,7 +917,6 @@ TABFieldType TABView::GetNativeFieldType(int nFieldId)
     return TABFUnknown;
 }
 
-
 /**********************************************************************
  *                   TABView::AddFieldNative()
  *
@@ -1072,7 +988,6 @@ GBool TABView::IsFieldUnique(int nFieldId)
     return FALSE;
 }
 
-
 /**********************************************************************
  *                   TABView::GetBounds()
  *
@@ -1119,7 +1034,6 @@ OGRErr TABView::GetExtent (OGREnvelope *psExtent, int bForce)
     }
 
     return m_papoTABFiles[m_nMainTableIndex]->GetExtent(psExtent, bForce);
-
 }
 
 /**********************************************************************
@@ -1151,7 +1065,6 @@ int TABView::GetFeatureCountByType(int &numPoints, int &numLines,
                                                                     bForce);
 }
 
-
 /**********************************************************************
  *                   TABView::GetSpatialRef()
  *
@@ -1191,8 +1104,6 @@ int TABView::SetSpatialRef(OGRSpatialReference *poSpatialRef)
     return m_papoTABFiles[m_nMainTableIndex]->SetSpatialRef(poSpatialRef);
 }
 
-
-
 /**********************************************************************
  *                   TABView::SetBounds()
  **********************************************************************/
@@ -1239,11 +1150,6 @@ int TABView::TestCapability( const char * pszCap )
         return FALSE;
 }
 
-
-
-
-
-
 /**********************************************************************
  *                   TABView::Dump()
  *
@@ -1266,7 +1172,6 @@ void TABView::Dump(FILE *fpOut /*=NULL*/)
     {
         fprintf(fpOut, "File is opened: %s\n", m_pszFname);
         fprintf(fpOut, "View contains %d tables\n", m_numTABFiles);
-
     }
 
     fflush(fpOut);
@@ -1274,37 +1179,29 @@ void TABView::Dump(FILE *fpOut /*=NULL*/)
 
 #endif // DEBUG
 
-
-
 /*=====================================================================
  *                      class TABRelation
  *====================================================================*/
 
-
 /**********************************************************************
  *                   TABRelation::TABRelation()
  *
  * Constructor.
  **********************************************************************/
-TABRelation::TABRelation()
-{
-    m_poMainTable = NULL;
-    m_pszMainFieldName = NULL;
-    m_nMainFieldNo = -1;
-
-    m_poRelTable = NULL;
-    m_pszRelFieldName = NULL;
-    m_nRelFieldNo = -1;
-    m_nRelFieldIndexNo = -1;
-    m_poRelINDFileRef = NULL;
-
-    m_nUniqueRecordNo = 0;
-
-    m_panMainTableFieldMap = NULL;
-    m_panRelTableFieldMap = NULL;
-
-    m_poDefn = NULL;
-}
+TABRelation::TABRelation() :
+    m_poMainTable(NULL),
+    m_pszMainFieldName(NULL),
+    m_nMainFieldNo(-1),
+    m_poRelTable(NULL),
+    m_pszRelFieldName(NULL),
+    m_nRelFieldNo(-1),
+    m_poRelINDFileRef(NULL),
+    m_nRelFieldIndexNo(-1),
+    m_nUniqueRecordNo(0),
+    m_panMainTableFieldMap(NULL),
+    m_panRelTableFieldMap(NULL),
+    m_poDefn(NULL)
+{}
 
 /**********************************************************************
  *                   TABRelation::~TABRelation()
@@ -1350,7 +1247,6 @@ void TABRelation::ResetAllMembers()
     if (m_poDefn && m_poDefn->Dereference() == 0)
         delete m_poDefn;
     m_poDefn = NULL;
-
 }
 
 /**********************************************************************
@@ -1378,10 +1274,8 @@ int  TABRelation::Init(const char *pszViewName,
         return -1;
 
     // We'll need the feature Defn later...
-    OGRFeatureDefn *poMainDefn, *poRelDefn;
-
-    poMainDefn = poMainTable->GetLayerDefn();
-    poRelDefn = poRelTable->GetLayerDefn();
+    OGRFeatureDefn *poMainDefn = poMainTable->GetLayerDefn();
+    OGRFeatureDefn *poRelDefn = poRelTable->GetLayerDefn();
 
     /*-----------------------------------------------------------------
      * Keep info for later use about source tables, etc.
@@ -1417,15 +1311,14 @@ int  TABRelation::Init(const char *pszViewName,
      * the field is not selected, and a value >=0 is the index of the
      * field in the view's FeatureDefn
      *----------------------------------------------------------------*/
-    int i;
-    int numFields1 = (poMainDefn?poMainDefn->GetFieldCount():0);
-    int numFields2 = (poRelDefn?poRelDefn->GetFieldCount():0);
+    const int numFields1 = poMainDefn ? poMainDefn->GetFieldCount() : 0;
+    const int numFields2 = poRelDefn ? poRelDefn->GetFieldCount() : 0;
 
     m_panMainTableFieldMap = (int*)CPLMalloc((numFields1+1)*sizeof(int));
-    for(i=0; i<numFields1; i++)
+    for( int i = 0; i < numFields1; i++ )
         m_panMainTableFieldMap[i] = -1;
     m_panRelTableFieldMap = (int*)CPLMalloc((numFields2+1)*sizeof(int));
-    for(i=0; i<numFields2; i++)
+    for( int i = 0; i<numFields2; i++ )
         m_panRelTableFieldMap[i] = -1;
 
     /*-----------------------------------------------------------------
@@ -1437,7 +1330,7 @@ int  TABRelation::Init(const char *pszViewName,
         CSLDestroy(papszSelectedFields);
         papszSelectedFields = NULL;
 
-        for(i=0; i<numFields1; i++)
+        for( int i = 0; i<numFields1; i++ )
         {
             OGRFieldDefn *poFieldDefn = poMainDefn->GetFieldDefn(i);
 
@@ -1445,7 +1338,7 @@ int  TABRelation::Init(const char *pszViewName,
                                                poFieldDefn->GetNameRef());
         }
 
-        for(i=0; i<numFields2; i++)
+        for( int i = 0; i < numFields2; i++)
         {
             OGRFieldDefn *poFieldDefn = poRelDefn->GetFieldDefn(i);
 
@@ -1456,21 +1349,22 @@ int  TABRelation::Init(const char *pszViewName,
             papszSelectedFields = CSLAddString(papszSelectedFields,
                                                poFieldDefn->GetNameRef());
         }
-
     }
 
     /*-----------------------------------------------------------------
      * Create new FeatureDefn and copy selected fields definitions
      * while updating the appropriate field maps.
      *----------------------------------------------------------------*/
-    int nIndex;
-    OGRFieldDefn *poFieldDefn;
+    int nIndex = 0;
+    OGRFieldDefn *poFieldDefn = NULL;
 
     m_poDefn = new OGRFeatureDefn(pszViewName);
     // Ref count defaults to 0... set it to 1
     m_poDefn->Reference();
 
-    for(i=0; papszSelectedFields != NULL && papszSelectedFields[i] != NULL ; i++)
+    for( int i = 0;
+         papszSelectedFields != NULL && papszSelectedFields[i] != NULL;
+         i++ )
     {
         if (poMainDefn &&
             (nIndex=poMainDefn->GetFieldIndex(papszSelectedFields[i])) >=0)
@@ -1505,7 +1399,6 @@ int  TABRelation::Init(const char *pszViewName,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABRelation::CreateRelFields()
  *
@@ -1518,8 +1411,6 @@ int  TABRelation::Init(const char *pszViewName,
  **********************************************************************/
 int  TABRelation::CreateRelFields()
 {
-    int i;
-
     /*-----------------------------------------------------------------
      * Create the field in each table.
      * The default name is "MI_refnum" but if a field with the same name
@@ -1528,7 +1419,7 @@ int  TABRelation::CreateRelFields()
     m_pszMainFieldName = CPLStrdup("MI_Refnum      ");
     const size_t nLen = strlen(m_pszMainFieldName) + 1;
     strcpy(m_pszMainFieldName, "MI_Refnum");
-    i = 1;
+    int i = 1;
     while(m_poDefn->GetFieldIndex(m_pszMainFieldName) >= 0)
     {
         snprintf(m_pszMainFieldName, nLen, "MI_Refnum_%d", i++);
@@ -1558,10 +1449,8 @@ int  TABRelation::CreateRelFields()
     /*-----------------------------------------------------------------
      * Update field maps
      *----------------------------------------------------------------*/
-    OGRFeatureDefn *poMainDefn, *poRelDefn;
-
-    poMainDefn = m_poMainTable->GetLayerDefn();
-    poRelDefn = m_poRelTable->GetLayerDefn();
+    OGRFeatureDefn *poMainDefn = m_poMainTable->GetLayerDefn();
+    OGRFeatureDefn *poRelDefn = m_poRelTable->GetLayerDefn();
 
     m_panMainTableFieldMap = (int*)CPLRealloc(m_panMainTableFieldMap,
                                       poMainDefn->GetFieldCount()*sizeof(int));
@@ -1601,9 +1490,6 @@ int  TABRelation::CreateRelFields()
  **********************************************************************/
 TABFeature *TABRelation::GetFeature(int nFeatureId)
 {
-    TABFeature *poMainFeature;
-    TABFeature *poCurFeature;
-
     /*-----------------------------------------------------------------
      * Make sure init() has been called
      *----------------------------------------------------------------*/
@@ -1617,14 +1503,15 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
     /*-----------------------------------------------------------------
      * Read main feature and create a new one of the right type
      *----------------------------------------------------------------*/
-    if ((poMainFeature = m_poMainTable->GetFeatureRef(nFeatureId)) == NULL)
+    TABFeature *poMainFeature = m_poMainTable->GetFeatureRef(nFeatureId);
+    if( poMainFeature == NULL )
     {
         // Feature cannot be read from main table...
         // an error has already been reported.
         return NULL;
     }
 
-    poCurFeature = poMainFeature->CloneTABFeature(m_poDefn);
+    TABFeature *poCurFeature = poMainFeature->CloneTABFeature(m_poDefn);
 
     /*-----------------------------------------------------------------
      * Keep track of FID and copy the geometry
@@ -1633,8 +1520,7 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
 
     if (poCurFeature->GetFeatureClass() != TABFCNoGeomFeature)
     {
-        OGRGeometry *poGeom;
-        poGeom = poMainFeature->GetGeometryRef();
+        OGRGeometry *poGeom = poMainFeature->GetGeometryRef();
         poCurFeature->SetGeometry(poGeom);
     }
 
@@ -1650,7 +1536,6 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
     GByte *pKey = BuildFieldKey(poMainFeature, m_nMainFieldNo,
                             m_poMainTable->GetNativeFieldType(m_nMainFieldNo),
                                 m_nRelFieldIndexNo);
-    int i;
     int nRelFeatureId = m_poRelINDFileRef->FindFirst(m_nRelFieldIndexNo, pKey);
 
     if (nRelFeatureId > 0)
@@ -1659,7 +1544,7 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
     /*-----------------------------------------------------------------
      * Copy fields from poMainFeature
      *----------------------------------------------------------------*/
-    for(i=0; i<poMainFeature->GetFieldCount(); i++)
+    for( int i = 0; i < poMainFeature->GetFieldCount(); i++ )
     {
         if (m_panMainTableFieldMap[i] != -1)
         {
@@ -1674,7 +1559,7 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
      * NOTE: For now, if no corresponding feature is found in RelTable
      *       then we will just leave the corresponding fields unset.
      *----------------------------------------------------------------*/
-    for(i=0; poRelFeature && i<poRelFeature->GetFieldCount(); i++)
+    for( int i = 0; poRelFeature && i < poRelFeature->GetFieldCount(); i++ )
     {
         if (m_panRelTableFieldMap[i] != -1)
         {
@@ -1686,8 +1571,6 @@ TABFeature *TABRelation::GetFeature(int nFeatureId)
     return poCurFeature;
 }
 
-
-
 /**********************************************************************
  *                   TABRelation::BuildFieldKey()
  *
@@ -1736,7 +1619,6 @@ GByte *TABRelation::BuildFieldKey(TABFeature *poFeature, int nFieldNo,
     return pKey;
 }
 
-
 /**********************************************************************
  *                   TABRelation::GetNativeFieldType()
  *
@@ -1780,7 +1662,6 @@ TABFieldType TABRelation::GetNativeFieldType(int nFieldId)
     return TABFUnknown;
 }
 
-
 /**********************************************************************
  *                   TABRelation::AddFieldNative()
  *
@@ -1854,7 +1735,6 @@ int TABRelation::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
     return 0;
 }
 
-
 /**********************************************************************
  *                   TABRelation::IsFieldIndexed()
  *
@@ -1995,10 +1875,8 @@ int TABRelation::WriteFeature(TABFeature *poFeature, int nFeatureId /*=-1*/)
     CPLAssert(m_poMainTable && m_poRelTable);
 
     // We'll need the feature Defn later...
-    OGRFeatureDefn *poMainDefn, *poRelDefn;
-
-    poMainDefn = m_poMainTable->GetLayerDefn();
-    poRelDefn = m_poRelTable->GetLayerDefn();
+    OGRFeatureDefn *poMainDefn = m_poMainTable->GetLayerDefn();
+    OGRFeatureDefn *poRelDefn = m_poRelTable->GetLayerDefn();
 
     /*-----------------------------------------------------------------
      * Create one feature for each table
@@ -2008,8 +1886,7 @@ int TABRelation::WriteFeature(TABFeature *poFeature, int nFeatureId /*=-1*/)
 
     if (poFeature->GetFeatureClass() != TABFCNoGeomFeature)
     {
-        OGRGeometry *poGeom;
-        poGeom = poFeature->GetGeometryRef();
+        OGRGeometry *poGeom = poFeature->GetGeometryRef();
         poMainFeature->SetGeometry(poGeom);
     }
 
@@ -2071,7 +1948,6 @@ int TABRelation::WriteFeature(TABFeature *poFeature, int nFeatureId /*=-1*/)
         }
     }
 
-
     /*-----------------------------------------------------------------
      * Write poMainFeature to the main table
      *----------------------------------------------------------------*/
@@ -2087,7 +1963,6 @@ int TABRelation::WriteFeature(TABFeature *poFeature, int nFeatureId /*=-1*/)
     return nFeatureId;
 }
 
-
 /**********************************************************************
  *                   TABFile::SetFeatureDefn()
  *
diff --git a/ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp b/ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp
index d91dbbe..a40f530 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_tooldef.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_tooldef.cpp,v 1.7 2010-07-07 19:00:15 aboudreault Exp $
  *
  * Name:     mitab_tooldef.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -28,35 +27,21 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_tooldef.cpp,v $
- * Revision 1.7  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.6  2004-06-30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.5  2000/11/15 04:13:50  daniel
- * Fixed writing of TABMAPToolBlock to allocate a new block when full
- *
- * Revision 1.4  2000/02/28 17:06:54  daniel
- * Support pen width in points and V450 check
- *
- * Revision 1.3  2000/01/15 22:30:45  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.2  1999/10/18 15:39:21  daniel
- * Handle case of "no pen" or "no brush" in AddPen/BrushRef()
- *
- * Revision 1.1  1999/09/26 14:59:37  daniel
- * Implemented write support
- *
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "mitab.h"
+
+#include <cstddef>
+#include <algorithm>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "mitab_priv.h"
 #include "mitab_utils.h"
 
+CPL_CVSID("$Id: mitab_tooldef.cpp 37351 2017-02-12 05:22:20Z goatbar $");
+
 /*=====================================================================
  *                      class TABToolDefTable
  *====================================================================*/
@@ -66,22 +51,20 @@
  *
  * Constructor.
  **********************************************************************/
-TABToolDefTable::TABToolDefTable()
-{
-    m_papsPen = NULL;
-    m_papsBrush = NULL;
-    m_papsFont = NULL;
-    m_papsSymbol = NULL;
-    m_numPen = 0;
-    m_numBrushes = 0;
-    m_numFonts = 0;
-    m_numSymbols = 0;
-    m_numAllocatedPen = 0;
-    m_numAllocatedBrushes = 0;
-    m_numAllocatedFonts = 0;
-    m_numAllocatedSymbols = 0;
-
-}
+TABToolDefTable::TABToolDefTable() :
+    m_papsPen(NULL),
+    m_numPen(0),
+    m_numAllocatedPen(0),
+    m_papsBrush(NULL),
+    m_numBrushes(0),
+    m_numAllocatedBrushes(0),
+    m_papsFont(NULL),
+    m_numFonts(0),
+    m_numAllocatedFonts(0),
+    m_papsSymbol(NULL),
+    m_numSymbols(0),
+    m_numAllocatedSymbols(0)
+{}
 
 /**********************************************************************
  *                   TABToolDefTable::~TABToolDefTable()
@@ -90,27 +73,23 @@ TABToolDefTable::TABToolDefTable()
  **********************************************************************/
 TABToolDefTable::~TABToolDefTable()
 {
-    int i;
-
-    for(i=0; m_papsPen && i < m_numPen; i++)
+    for( int i = 0; m_papsPen && i < m_numPen; i++ )
         CPLFree(m_papsPen[i]);
     CPLFree(m_papsPen);
 
-    for(i=0; m_papsBrush && i < m_numBrushes; i++)
+    for( int i = 0; m_papsBrush && i < m_numBrushes; i++ )
         CPLFree(m_papsBrush[i]);
     CPLFree(m_papsBrush);
 
-    for(i=0; m_papsFont && i < m_numFonts; i++)
+    for( int i = 0; m_papsFont && i < m_numFonts; i++ )
         CPLFree(m_papsFont[i]);
     CPLFree(m_papsFont);
 
-    for(i=0; m_papsSymbol && i < m_numSymbols; i++)
+    for( int i = 0; m_papsSymbol && i < m_numSymbols; i++ )
         CPLFree(m_papsSymbol[i]);
     CPLFree(m_papsSymbol);
-
 }
 
-
 /**********************************************************************
  *                   TABToolDefTable::ReadAllToolDefs()
  *
@@ -120,10 +99,9 @@ TABToolDefTable::~TABToolDefTable()
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
+int TABToolDefTable::ReadAllToolDefs( TABMAPToolBlock *poBlock )
 {
     int nStatus = 0;
-    int nDefType;
 
     /*-----------------------------------------------------------------
      * Loop until we reach the end of the chain of blocks... we assume
@@ -131,7 +109,7 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
      *----------------------------------------------------------------*/
     while( ! poBlock->EndOfChain() )
     {
-        nDefType = poBlock->ReadByte();
+        const int nDefType = poBlock->ReadByte();
         switch(nDefType)
         {
           case TABMAP_TOOL_PEN:       // PEN
@@ -247,7 +225,6 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
     return nStatus;
 }
 
-
 /**********************************************************************
  *                   TABToolDefTable::WriteAllToolDefs()
  *
@@ -258,17 +235,18 @@ int     TABToolDefTable::ReadAllToolDefs(TABMAPToolBlock *poBlock)
  *
  * Returns 0 on success, -1 on error.
  **********************************************************************/
-int     TABToolDefTable::WriteAllToolDefs(TABMAPToolBlock *poBlock)
+int TABToolDefTable::WriteAllToolDefs( TABMAPToolBlock *poBlock )
 {
-    int i, nStatus = 0;
+    int nStatus = 0;
 
     /*-----------------------------------------------------------------
      * Write Pen Defs
      *----------------------------------------------------------------*/
-    for(i=0; nStatus == 0 && i< m_numPen; i++)
+    for( int i = 0; nStatus == 0 && i< m_numPen; i++ )
     {
         // The pen width is encoded over 2 bytes
-        GByte byPixelWidth=1, byPointWidth=0;
+        GByte byPixelWidth=1;
+        GByte byPointWidth = 0;
         if (m_papsPen[i]->nPointWidth > 0)
         {
             byPointWidth = (GByte)(m_papsPen[i]->nPointWidth & 0xff);
@@ -276,7 +254,13 @@ int     TABToolDefTable::WriteAllToolDefs(TABMAPToolBlock *poBlock)
                 byPixelWidth = 8 + (GByte)(m_papsPen[i]->nPointWidth/0x100);
         }
         else
-            byPixelWidth = MIN(MAX(m_papsPen[i]->nPixelWidth, 1), 7);
+        {
+            const GByte nMinWidth = 1;
+            const GByte nMaxWidth = 7;
+            byPixelWidth =
+                std::min(
+                    std::max(m_papsPen[i]->nPixelWidth, nMinWidth), nMaxWidth);
+        }
 
         poBlock->CheckAvailableSpace(TABMAP_TOOL_PEN);
         poBlock->WriteByte(TABMAP_TOOL_PEN);  // Def Type = Pen
@@ -299,7 +283,7 @@ int     TABToolDefTable::WriteAllToolDefs(TABMAPToolBlock *poBlock)
     /*-----------------------------------------------------------------
      * Write Brush Defs
      *----------------------------------------------------------------*/
-    for(i=0; nStatus == 0 && i< m_numBrushes; i++)
+    for( int i = 0; nStatus == 0 && i< m_numBrushes; i++ )
     {
         poBlock->CheckAvailableSpace(TABMAP_TOOL_BRUSH);
 
@@ -325,7 +309,7 @@ int     TABToolDefTable::WriteAllToolDefs(TABMAPToolBlock *poBlock)
     /*-----------------------------------------------------------------
      * Write Font Defs
      *----------------------------------------------------------------*/
-    for(i=0; nStatus == 0 && i< m_numFonts; i++)
+    for( int i = 0; nStatus == 0 && i< m_numFonts; i++ )
     {
         poBlock->CheckAvailableSpace(TABMAP_TOOL_FONT);
 
@@ -344,7 +328,7 @@ int     TABToolDefTable::WriteAllToolDefs(TABMAPToolBlock *poBlock)
     /*-----------------------------------------------------------------
      * Write Symbol Defs
      *----------------------------------------------------------------*/
-    for(i=0; nStatus == 0 && i< m_numSymbols; i++)
+    for( int i = 0; nStatus == 0 && i< m_numSymbols; i++ )
     {
         poBlock->CheckAvailableSpace(TABMAP_TOOL_SYMBOL);
 
@@ -371,8 +355,6 @@ int     TABToolDefTable::WriteAllToolDefs(TABMAPToolBlock *poBlock)
     return nStatus;
 }
 
-
-
 /**********************************************************************
  *                   TABToolDefTable::GetNumPen()
  *
@@ -413,9 +395,6 @@ TABPenDef *TABToolDefTable::GetPenDefRef(int nIndex)
  **********************************************************************/
 int TABToolDefTable::AddPenDefRef(TABPenDef *poNewPenDef)
 {
-    int i, nNewPenIndex = 0;
-    TABPenDef *poDef;
-
     if (poNewPenDef == NULL)
         return -1;
 
@@ -428,9 +407,10 @@ int TABToolDefTable::AddPenDefRef(TABPenDef *poNewPenDef)
     /*-----------------------------------------------------------------
      * Start by searching the list of existing pens
      *----------------------------------------------------------------*/
-    for (i=0; nNewPenIndex == 0 && i<m_numPen; i++)
+    int nNewPenIndex = 0;
+    for( int i = 0; nNewPenIndex == 0 && i<m_numPen; i++ )
     {
-        poDef = m_papsPen[i];
+        TABPenDef *poDef = m_papsPen[i];
         if (poDef->nPixelWidth == poNewPenDef->nPixelWidth &&
             poDef->nLinePattern == poNewPenDef->nLinePattern &&
             poDef->nPointWidth == poNewPenDef->nPointWidth &&
@@ -503,9 +483,6 @@ TABBrushDef *TABToolDefTable::GetBrushDefRef(int nIndex)
  **********************************************************************/
 int TABToolDefTable::AddBrushDefRef(TABBrushDef *poNewBrushDef)
 {
-    int i, nNewBrushIndex = 0;
-    TABBrushDef *poDef;
-
     if (poNewBrushDef == NULL)
         return -1;
 
@@ -518,9 +495,10 @@ int TABToolDefTable::AddBrushDefRef(TABBrushDef *poNewBrushDef)
     /*-----------------------------------------------------------------
      * Start by searching the list of existing Brushs
      *----------------------------------------------------------------*/
-    for (i=0; nNewBrushIndex == 0 && i<m_numBrushes; i++)
+    int nNewBrushIndex = 0;
+    for( int i = 0; nNewBrushIndex == 0 && i<m_numBrushes; i++ )
     {
-        poDef = m_papsBrush[i];
+        TABBrushDef *poDef = m_papsBrush[i];
         if (poDef->nFillPattern == poNewBrushDef->nFillPattern &&
             poDef->bTransparentFill == poNewBrushDef->bTransparentFill &&
             poDef->rgbFGColor == poNewBrushDef->rgbFGColor &&
@@ -594,18 +572,16 @@ TABFontDef *TABToolDefTable::GetFontDefRef(int nIndex)
  **********************************************************************/
 int TABToolDefTable::AddFontDefRef(TABFontDef *poNewFontDef)
 {
-    int i, nNewFontIndex = 0;
-    TABFontDef *poDef;
-
     if (poNewFontDef == NULL)
         return -1;
 
     /*-----------------------------------------------------------------
      * Start by searching the list of existing Fonts
      *----------------------------------------------------------------*/
-    for (i=0; nNewFontIndex == 0 && i<m_numFonts; i++)
+    int nNewFontIndex = 0;
+    for( int i = 0; nNewFontIndex == 0 && i<m_numFonts; i++ )
     {
-        poDef = m_papsFont[i];
+        TABFontDef *poDef = m_papsFont[i];
         if (EQUAL(poDef->szFontName, poNewFontDef->szFontName))
         {
             nNewFontIndex = i+1; // Fount it!
@@ -663,7 +639,6 @@ TABSymbolDef *TABToolDefTable::GetSymbolDefRef(int nIndex)
     return NULL;
 }
 
-
 /**********************************************************************
  *                   TABToolDefTable::AddSymbolDefRef()
  *
@@ -677,18 +652,16 @@ TABSymbolDef *TABToolDefTable::GetSymbolDefRef(int nIndex)
  **********************************************************************/
 int TABToolDefTable::AddSymbolDefRef(TABSymbolDef *poNewSymbolDef)
 {
-    int i, nNewSymbolIndex = 0;
-    TABSymbolDef *poDef;
-
     if (poNewSymbolDef == NULL)
         return -1;
 
     /*-----------------------------------------------------------------
      * Start by searching the list of existing Symbols
      *----------------------------------------------------------------*/
-    for (i=0; nNewSymbolIndex == 0 && i<m_numSymbols; i++)
+    int nNewSymbolIndex = 0;
+    for( int i = 0; nNewSymbolIndex == 0 && i<m_numSymbols; i++ )
     {
-        poDef = m_papsSymbol[i];
+        TABSymbolDef *poDef = m_papsSymbol[i];
         if (poDef->nSymbolNo == poNewSymbolDef->nSymbolNo &&
             poDef->nPointSize == poNewSymbolDef->nPointSize &&
             poDef->_nUnknownValue_ == poNewSymbolDef->_nUnknownValue_ &&
@@ -722,7 +695,6 @@ int TABToolDefTable::AddSymbolDefRef(TABSymbolDef *poNewSymbolDef)
     return nNewSymbolIndex;
 }
 
-
 /**********************************************************************
  *                   TABToolDefTable::GetMinVersionNumber()
  *
@@ -743,7 +715,7 @@ int     TABToolDefTable::GetMinVersionNumber()
     {
         if (m_papsPen[i]->nPointWidth > 0 )
         {
-            nVersion = MAX(nVersion, 450);  // Raise version to 450
+            nVersion = std::max(nVersion, 450);  // Raise version to 450
         }
     }
 
diff --git a/ogr/ogrsf_frmts/mitab/mitab_utils.cpp b/ogr/ogrsf_frmts/mitab/mitab_utils.cpp
index 27769ab..7fa6ff6 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_utils.cpp
+++ b/ogr/ogrsf_frmts/mitab/mitab_utils.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: mitab_utils.cpp,v 1.26 2011-06-16 15:53:12 fwarmerdam Exp $
  *
  * Name:     mitab_utils.cpp
  * Project:  MapInfo TAB Read/Write library
@@ -27,98 +26,28 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_utils.cpp,v $
- * Revision 1.26  2011-06-16 15:53:12  fwarmerdam
- * improve TABBasename() for filenames with an embedded dot (gdal #4123)
- *
- * Revision 1.25  2010-07-07 19:00:15  aboudreault
- * Cleanup Win32 Compile Warnings (GDAL bug #2930)
- *
- * Revision 1.24  2010-07-05 17:41:07  aboudreault
- * Fixed TABCleanFieldName() function should allow char '#' in field name (bug 2231)
- *
- * Revision 1.23  2010-01-07 20:39:12  aboudreault
- * Added support to handle duplicate field names, Added validation to check if a field name start with a number (bug 2141)
- *
- * Revision 1.22  2008-07-21 16:04:58  dmorissette
- * Fixed const char * warnings with GCC 4.3 (GDAL ticket #2325)
- *
- * Revision 1.20  2005/08/07 21:02:14  fwarmerdam
- * avoid warnings about testing for characters > 255.
- *
- * Revision 1.19  2004/06/30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.18  2002/08/28 14:19:22  warmerda
- * fix TABGetBasename() for mixture of path divider types like 'mi/abc\def.tab'
- *
- * Revision 1.17  2001/06/27 19:52:54  warmerda
- * avoid multi byte support if _WIN32 and unix defined for cygwin support
- *
- * Revision 1.16  2001/01/23 21:23:42  daniel
- * Added projection bounds lookup table, called from TABFile::SetProjInfo()
- *
- * Revision 1.15  2001/01/19 06:06:18  daniel
- * Don't filter chars in TABCleanFieldName() if we're on a DBCS system
- *
- * Revision 1.14  2000/09/28 16:39:44  warmerda
- * Avoid warnings for unused, and uninitialized variables
- *
- * Revision 1.13  2000/09/20 18:35:51  daniel
- * Fixed TABAdjustFilenameExtension() to also handle basename and path
- * using TABAdjustCaseSensitiveFilename()
- *
- * Revision 1.12  2000/04/18 04:19:22  daniel
- * Now accept extended chars with accents in TABCleanFieldName()
- *
- * Revision 1.11  2000/02/28 17:08:56  daniel
- * Avoid using isalnum() in TABCleanFieldName
- *
- * Revision 1.10  2000/02/18 20:46:35  daniel
- * Added TABCleanFieldName()
- *
- * Revision 1.9  2000/01/15 22:30:45  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.8  2000/01/14 23:46:59  daniel
- * Added TABEscapeString()/TABUnEscapeString()
- *
- * Revision 1.7  1999/12/16 06:10:24  daniel
- * TABGetBasename(): make sure last '/' of path is removed
- *
- * Revision 1.6  1999/12/14 02:08:37  daniel
- * Added TABGetBasename() + TAB_CSLLoad()
- *
- * Revision 1.5  1999/11/08 04:30:59  stephane
- * Modify TABGenerateArc()
- *
- * Revision 1.4  1999/09/29 17:59:21  daniel
- * Definition for PI was gone on Windows
- *
- * Revision 1.3  1999/09/16 02:39:17  daniel
- * Completed read support for most feature types
- *
- * Revision 1.2  1999/07/12 05:44:59  daniel
- * Added include math.h for VC++
- *
- * Revision 1.1  1999/07/12 04:18:25  daniel
- * Initial checkin
- *
  **********************************************************************/
 
-#include "mitab.h"
+#include "cpl_port.h"
 #include "mitab_utils.h"
-#include "cpl_conv.h"
 
-#include <math.h>       /* sin()/cos() */
-#include <ctype.h>      /* toupper()/tolower() */
+#include <cctype>
+#include <climits>
+#include <cmath>
+#include <cstring>
+#include <limits>
+
+#include "mitab.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 
 #if defined(_WIN32) && !defined(unix)
-#  include <mbctype.h>  /* Multibyte chars stuff */
+#  include <mbctype.h>  // Multibyte chars stuff.
 #endif
 
+CPL_CVSID("$Id: mitab_utils.cpp 37355 2017-02-12 15:52:53Z goatbar $");
 
 /**********************************************************************
  *                       TABGenerateArc()
@@ -141,35 +70,30 @@ int TABGenerateArc(OGRLineString *poLine, int numPoints,
                    double dXRadius, double dYRadius,
                    double dStartAngle, double dEndAngle)
 {
-    double dX, dY, dAngleStep, dAngle=0.0;
-    int i;
-
     // Adjust angles to go counterclockwise
     if (dEndAngle < dStartAngle)
         dEndAngle += 2.0*M_PI;
 
-    dAngleStep = (dEndAngle-dStartAngle)/(numPoints-1.0);
+    const double dAngleStep = (dEndAngle - dStartAngle) / (numPoints - 1.0);
 
-    for(i=0; i<numPoints; i++)
+    double dAngle = 0.0;
+    for( int i = 0; i<numPoints; i++ )
     {
-        dAngle = (dStartAngle + (double)i*dAngleStep);
-        dX = dCenterX + dXRadius*cos(dAngle);
-        dY = dCenterY + dYRadius*sin(dAngle);
+        dAngle = dStartAngle + i * dAngleStep;
+        const double dX = dCenterX + dXRadius*cos(dAngle);
+        const double dY = dCenterY + dYRadius*sin(dAngle);
         poLine->addPoint(dX, dY);
     }
 
     // Complete the arc with the last EndAngle, to make sure that
     // the arc is correctly closed.
-
-    dX = dCenterX + dXRadius*cos(dAngle);
-    dY = dCenterY + dYRadius*sin(dAngle);
+    const double dX = dCenterX + dXRadius*cos(dAngle);
+    const double dY = dCenterY + dYRadius*sin(dAngle);
     poLine->addPoint(dX,dY);
 
-
     return 0;
 }
 
-
 /**********************************************************************
  *                       TABCloseRing()
  *
@@ -199,50 +123,34 @@ int TABCloseRing(OGRLineString *poRing)
  * This function works on the original buffer and returns a reference to it.
  * It does nothing on Windows systems where filenames are not case sensitive.
  **********************************************************************/
-static GBool TABAdjustCaseSensitiveFilename(char *
-#ifndef _WIN32
-                                            pszFname
-#endif
-                                            )
-{
-
 #ifdef _WIN32
-    /*-----------------------------------------------------------------
-     * Nothing to do on Windows
-     *----------------------------------------------------------------*/
-    return TRUE;
-
+static bool TABAdjustCaseSensitiveFilename(char * /* pszFname */ )
+{
+    // Nothing to do on Windows.
+    return true;
+}
 #else
-    /*-----------------------------------------------------------------
-     * Unix case.
-     *----------------------------------------------------------------*/
-    VSIStatBufL  sStatBuf;
-    char        *pszTmpPath = NULL;
-    int         nTotalLen, iTmpPtr;
-    GBool       bValidPath;
+// Unix case.
+static bool TABAdjustCaseSensitiveFilename(char *pszFname)
+{
+    VSIStatBufL sStatBuf;
 
-    /*-----------------------------------------------------------------
-     * First check if the filename is OK as is.
-     *----------------------------------------------------------------*/
+    // First check if the filename is OK as is.
     if (VSIStatL(pszFname, &sStatBuf) == 0)
     {
-        return TRUE;
+        return true;
     }
 
-    /*-----------------------------------------------------------------
-     * OK, file either does not exist or has the wrong cases... we'll
-     * go backwards until we find a portion of the path that is valid.
-     *----------------------------------------------------------------*/
-    pszTmpPath = CPLStrdup(pszFname);
-    nTotalLen = static_cast<int>(strlen(pszTmpPath));
-    iTmpPtr = nTotalLen;
-    bValidPath = FALSE;
+    // File either does not exist or has the wrong cases.
+    // Go backwards until we find a portion of the path that is valid.
+    char *pszTmpPath = CPLStrdup(pszFname);
+    const int nTotalLen = static_cast<int>(strlen(pszTmpPath));
+    int iTmpPtr = nTotalLen;
+    GBool bValidPath = false;
 
     while(iTmpPtr > 0 && !bValidPath)
     {
-        /*-------------------------------------------------------------
-         * Move back to the previous '/' separator
-         *------------------------------------------------------------*/
+        // Move back to the previous '/' separator.
         pszTmpPath[--iTmpPtr] = '\0';
         while( iTmpPtr > 0 && pszTmpPath[iTmpPtr-1] != '/' )
         {
@@ -250,34 +158,25 @@ static GBool TABAdjustCaseSensitiveFilename(char *
         }
 
         if (iTmpPtr > 0 && VSIStatL(pszTmpPath, &sStatBuf) == 0)
-            bValidPath = TRUE;
+            bValidPath = true;
     }
 
     CPLAssert(iTmpPtr >= 0);
 
-    /*-----------------------------------------------------------------
-     * Assume that CWD is valid... so an empty path is a valid path
-     *----------------------------------------------------------------*/
+    // Assume that CWD is valid.  Therefor an empty path is a valid.
     if (iTmpPtr == 0)
-        bValidPath = TRUE;
-
-    /*-----------------------------------------------------------------
-     * OK, now that we have a valid base, reconstruct the whole path
-     * by scanning all the sub-directories.
-     * If we get to a point where a path component does not exist then
-     * we simply return the rest of the path as is.
-     *----------------------------------------------------------------*/
+        bValidPath = true;
+
+    // Now that we have a valid base, reconstruct the whole path
+    // by scanning all the sub-directories.
+    // If we get to a point where a path component does not exist then
+    // we simply return the rest of the path as is.
     while(bValidPath && (int)strlen(pszTmpPath) < nTotalLen)
     {
-        char    **papszDir=NULL;
-        int     iEntry, iLastPartStart;
+        int iLastPartStart = iTmpPtr;
+        char **papszDir = VSIReadDir(pszTmpPath);
 
-        iLastPartStart = iTmpPtr;
-        papszDir = VSIReadDir(pszTmpPath);
-
-        /*-------------------------------------------------------------
-         * Add one component to the current path
-         *------------------------------------------------------------*/
+        // Add one component to the current path.
         pszTmpPath[iTmpPtr] = pszFname[iTmpPtr];
         iTmpPtr++;
         for( ; pszFname[iTmpPtr] != '\0' && pszFname[iTmpPtr]!='/'; iTmpPtr++)
@@ -288,54 +187,44 @@ static GBool TABAdjustCaseSensitiveFilename(char *
         while(iLastPartStart < iTmpPtr && pszTmpPath[iLastPartStart] == '/')
             iLastPartStart++;
 
-        /*-------------------------------------------------------------
-         * And do a case insensitive search in the current dir...
-         *------------------------------------------------------------*/
-        for(iEntry=0; papszDir && papszDir[iEntry]; iEntry++)
+        // And do a case insensitive search in the current dir.
+        for(int iEntry = 0; papszDir && papszDir[iEntry]; iEntry++)
         {
-            if (EQUAL(pszTmpPath+iLastPartStart, papszDir[iEntry]))
+            if (EQUAL(pszTmpPath + iLastPartStart, papszDir[iEntry]))
             {
-                /* Fount it! */
+                // Fount it.
                 strcpy(pszTmpPath+iLastPartStart, papszDir[iEntry]);
                 break;
             }
         }
 
         if (iTmpPtr > 0 && VSIStatL(pszTmpPath, &sStatBuf) != 0)
-            bValidPath = FALSE;
+            bValidPath = false;
 
         CSLDestroy(papszDir);
     }
 
-    /*-----------------------------------------------------------------
-     * We reached the last valid path component... just copy the rest
-     * of the path as is.
-     *----------------------------------------------------------------*/
+    // We reached the last valid path component... just copy the rest
+    // of the path as is.
     if (iTmpPtr < nTotalLen-1)
     {
         strncpy(pszTmpPath+iTmpPtr, pszFname+iTmpPtr, nTotalLen-iTmpPtr);
     }
 
-    /*-----------------------------------------------------------------
-     * Update the source buffer and return.
-     *----------------------------------------------------------------*/
+    // Update the source buffer and return.
     strcpy(pszFname, pszTmpPath);
     CPLFree(pszTmpPath);
 
     return bValidPath;
-
-#endif
 }
-
-
-
+#endif // Not win32.
 
 /**********************************************************************
  *                       TABAdjustFilenameExtension()
  *
  * Because Unix filenames are case sensitive and MapInfo datasets often have
  * mixed cases filenames, we use this function to find the right filename
- * to use ot open a specific file.
+ * to use to open a specific file.
  *
  * This function works directly on the source string, so the filename it
  * contains at the end of the call is the one that should be used.
@@ -347,22 +236,19 @@ static GBool TABAdjustCaseSensitiveFilename(char *
 GBool TABAdjustFilenameExtension(char *pszFname)
 {
     VSIStatBufL  sStatBuf;
-    int         i;
 
-    /*-----------------------------------------------------------------
-     * First try using filename as provided
-     *----------------------------------------------------------------*/
+    // First try using filename as provided
     if (VSIStatL(pszFname, &sStatBuf) == 0)
     {
         return TRUE;
     }
 
-    /*-----------------------------------------------------------------
-     * Try using uppercase extension (we assume that fname contains a '.')
-     *----------------------------------------------------------------*/
-    for(i = static_cast<int>(strlen(pszFname))-1; i >= 0 && pszFname[i] != '.'; i--)
+    // Try using uppercase extension (we assume that fname contains a '.')
+    for( int i = static_cast<int>(strlen(pszFname)) - 1;
+         i >= 0 && pszFname[i] != '.';
+         i-- )
     {
-        pszFname[i] = (char)toupper(pszFname[i]);
+        pszFname[i] = static_cast<char>(toupper(pszFname[i]));
     }
 
     if (VSIStatL(pszFname, &sStatBuf) == 0)
@@ -370,12 +256,12 @@ GBool TABAdjustFilenameExtension(char *pszFname)
         return TRUE;
     }
 
-    /*-----------------------------------------------------------------
-     * Try using lowercase extension
-     *----------------------------------------------------------------*/
-    for(i = static_cast<int>(strlen(pszFname))-1; i >= 0 && pszFname[i] != '.'; i--)
+    // Try using lowercase extension.
+    for( int i = static_cast<int>(strlen(pszFname))-1;
+         i >= 0 && pszFname[i] != '.';
+         i-- )
     {
-        pszFname[i] = (char)tolower(pszFname[i]);
+        pszFname[i] = static_cast<char>(tolower(pszFname[i]));
     }
 
     if (VSIStatL(pszFname, &sStatBuf) == 0)
@@ -383,15 +269,11 @@ GBool TABAdjustFilenameExtension(char *pszFname)
         return TRUE;
     }
 
-    /*-----------------------------------------------------------------
-     * None of the extensions worked!
-     * Try adjusting cases in the whole path and filename
-     *----------------------------------------------------------------*/
+    // None of the extensions worked.
+    // Try adjusting cases in the whole path and filename.
     return TABAdjustCaseSensitiveFilename(pszFname);
 }
 
-
-
 /**********************************************************************
  *                       TABGetBasename()
  *
@@ -402,13 +284,8 @@ GBool TABAdjustFilenameExtension(char *pszFname)
  **********************************************************************/
 char *TABGetBasename(const char *pszFname)
 {
-    const char *pszTmp = NULL;
-
-    /*-----------------------------------------------------------------
-     * Skip leading path or use whole name if no path dividers are
-     * encountered.
-     *----------------------------------------------------------------*/
-    pszTmp = pszFname + strlen(pszFname) - 1;
+    // Skip leading path or use whole name if no path dividers are encountered.
+    const char *pszTmp = pszFname + strlen(pszFname) - 1;
     while ( pszTmp != pszFname
             && *pszTmp != '/' && *pszTmp != '\\' )
         pszTmp--;
@@ -416,12 +293,9 @@ char *TABGetBasename(const char *pszFname)
     if( pszTmp != pszFname )
         pszTmp++;
 
-    /*-----------------------------------------------------------------
-     * Now allocate our own copy and remove extension
-     *----------------------------------------------------------------*/
+    // Now allocate our own copy and remove extension.
     char *pszBasename = CPLStrdup(pszTmp);
-    int i;
-    for(i=static_cast<int>(strlen(pszBasename))-1; i >= 0; i-- )
+    for( int i = static_cast<int>(strlen(pszBasename))-1; i >= 0; i-- )
     {
         if (pszBasename[i] == '.')
         {
@@ -433,8 +307,6 @@ char *TABGetBasename(const char *pszFname)
     return pszBasename;
 }
 
-
-
 /**********************************************************************
  *                       TAB_CSLLoad()
  *
@@ -447,16 +319,15 @@ char *TABGetBasename(const char *pszFname)
  **********************************************************************/
 char **TAB_CSLLoad(const char *pszFname)
 {
-    VSILFILE    *fp;
-    const char  *pszLine;
-    char        **papszStrList=NULL;
+    char **papszStrList = NULL;
 
-    fp = VSIFOpenL(pszFname, "rt");
+    VSILFILE *fp = VSIFOpenL(pszFname, "rt");
 
-    if (fp)
+    if( fp )
     {
         while(!VSIFEofL(fp))
         {
+            const char *pszLine = NULL;
             if ( (pszLine = CPLReadLineL(fp)) != NULL )
             {
                 papszStrList = CSLAddString(papszStrList, pszLine);
@@ -469,8 +340,6 @@ char **TAB_CSLLoad(const char *pszFname)
     return papszStrList;
 }
 
-
-
 /**********************************************************************
  *                       TABUnEscapeString()
  *
@@ -486,41 +355,34 @@ char **TAB_CSLLoad(const char *pszFname)
  **********************************************************************/
 char *TABUnEscapeString(char *pszString, GBool bSrcIsConst)
 {
-
-    /*-----------------------------------------------------------------
-     * First check if we need to do any replacement
-     *----------------------------------------------------------------*/
+    // First check if we need to do any replacement.
     if (pszString == NULL || strstr(pszString, "\\n") == NULL)
     {
         return pszString;
     }
 
-    /*-----------------------------------------------------------------
-     * Yes, we need to replace at least one "\n"
-     * We try to work on the original buffer unless we have bSrcIsConst=TRUE
-     *
-     * Note that we do not worry about freeing the source buffer when we
-     * return a copy... it is up to the caller to decide if the source needs
-     * to be freed based on context and by comparing pszString with
-     * the returned pointer (pszWorkString) to see if they are identical.
-     *----------------------------------------------------------------*/
+    // Yes, we need to replace at least one "\n".
+    // We try to work on the original buffer unless we have bSrcIsConst=TRUE.
+    //
+    // Note that we do not worry about freeing the source buffer when we
+    // return a copy.  It is up to the caller to decide if the source needs
+    // to be freed based on context and by comparing pszString with
+    // the returned pointer (pszWorkString) to see if they are identical.
     char *pszWorkString = NULL;
-    int i =0;
-    int j =0;
-
     if (bSrcIsConst)
     {
         // We have to create a copy to work on.
-        pszWorkString = (char *)CPLMalloc(sizeof(char) *
-                                          (strlen(pszString) +1));
+        pszWorkString = static_cast<char *>(
+            CPLMalloc(sizeof(char) * (strlen(pszString) +1)));
     }
     else
     {
-        // We'll work on the original.
+        // Work on the original.
         pszWorkString = pszString;
     }
 
-
+    int i = 0;
+    int j = 0;
     while (pszString[i])
     {
         if (pszString[i] =='\\' &&
@@ -561,23 +423,19 @@ char *TABUnEscapeString(char *pszString, GBool bSrcIsConst)
  **********************************************************************/
 char *TABEscapeString(char *pszString)
 {
-    /*-----------------------------------------------------------------
-     * First check if we need to do any replacement
-     *----------------------------------------------------------------*/
+    // First check if we need to do any replacement
     if (pszString == NULL || strchr(pszString, '\n') == NULL)
     {
         return pszString;
     }
 
-    /*-----------------------------------------------------------------
-     * OK, we need to do some replacements... alloc a copy big enough
-     * to hold the worst possible case
-     *----------------------------------------------------------------*/
-    char *pszWorkString = (char *)CPLMalloc(2*sizeof(char) *
-                                            (strlen(pszString) +1));
+    // Need to do some replacements.  Alloc a copy big enough
+    // to hold the worst possible case.
+    char *pszWorkString = static_cast<char *>(CPLMalloc(2*sizeof(char) *
+                                                        (strlen(pszString) +1)));
 
-    int i =0;
-    int j =0;
+    int i = 0;
+    int j = 0;
 
     while (pszString[i])
     {
@@ -613,57 +471,52 @@ char *TABEscapeString(char *pszString)
  **********************************************************************/
 char *TABCleanFieldName(const char *pszSrcName)
 {
-    char *pszNewName;
-    int numInvalidChars = 0;
-
-    pszNewName = CPLStrdup(pszSrcName);
+    char *pszNewName = CPLStrdup(pszSrcName);
 
     if (strlen(pszNewName) > 31)
     {
         pszNewName[31] = '\0';
-        CPLError(CE_Warning, (CPLErrorNum)TAB_WarningInvalidFieldName,
-                 "Field name '%s' is longer than the max of 31 characters. "
-                 "'%s' will be used instead.", pszSrcName, pszNewName);
+        CPLError(
+            CE_Warning, static_cast<CPLErrorNum>(TAB_WarningInvalidFieldName),
+            "Field name '%s' is longer than the max of 31 characters. "
+            "'%s' will be used instead.", pszSrcName, pszNewName);
     }
 
 #if defined(_WIN32) && !defined(unix)
-    /*-----------------------------------------------------------------
-     * On Windows, check if we're using a double-byte codepage, and
-     * if so then just keep the field name as is...
-     *----------------------------------------------------------------*/
+    // On Windows, check if we're using a double-byte codepage, and
+    // if so then just keep the field name as is.
     if (_getmbcp() != 0)
         return pszNewName;
 #endif
 
-    /*-----------------------------------------------------------------
-     * According to the MapInfo User's Guide (p. 240, v5.5)
-     * New Table Command:
-     *  Name:
-     * Displays the field name in the name box. You can also enter new field
-     * names here. Defaults are Field1, Field2, etc. A field name can contain
-     * up to 31 alphanumeric characters. Use letters, numbers, and the
-     * underscore. Do not use spaces; instead, use the underscore character
-     * (_) to separate words in a field name. Use upper and lower case for
-     * legibility, but MapInfo is not case-sensitive.
-     *
-     * It was also verified that extended chars with accents are also
-     * accepted.
-     *----------------------------------------------------------------*/
-    for(int i=0; pszSrcName && pszSrcName[i] != '\0'; i++)
+    // According to the MapInfo User's Guide (p. 240, v5.5).
+    // New Table Command:
+    //  Name:
+    // Displays the field name in the name box. You can also enter new field
+    // names here. Defaults are Field1, Field2, etc. A field name can contain
+    // up to 31 alphanumeric characters. Use letters, numbers, and the
+    // underscore. Do not use spaces; instead, use the underscore character
+    // (_) to separate words in a field name. Use upper and lower case for
+    // legibility, but MapInfo is not case-sensitive.
+    //
+    // It was also verified that extended chars with accents are also
+    // accepted.
+    int numInvalidChars = 0;
+    for( int i = 0; pszSrcName && pszSrcName[i] != '\0'; i++ )
     {
         if ( pszSrcName[i]=='#' )
-	{
+        {
             if (i == 0)
             {
                 pszNewName[i] = '_';
                 numInvalidChars++;
             }
         }
-        else if ( !( pszSrcName[i] == '_' ||
-                     (i!=0 && pszSrcName[i]>='0' && pszSrcName[i]<='9') ||
-                     (pszSrcName[i]>='a' && pszSrcName[i]<='z') ||
-                     (pszSrcName[i]>='A' && pszSrcName[i]<='Z') ||
-                     (GByte)pszSrcName[i]>=192 ) )
+        else if ( !(pszSrcName[i] == '_' ||
+                    (i!=0 && pszSrcName[i]>='0' && pszSrcName[i]<='9') ||
+                    (pszSrcName[i]>='a' && pszSrcName[i]<='z') ||
+                    (pszSrcName[i]>='A' && pszSrcName[i]<='Z') ||
+                    static_cast<GByte>(pszSrcName[i])>=192) )
         {
             pszNewName[i] = '_';
             numInvalidChars++;
@@ -672,15 +525,15 @@ char *TABCleanFieldName(const char *pszSrcName)
 
     if (numInvalidChars > 0)
     {
-        CPLError(CE_Warning, (CPLErrorNum)TAB_WarningInvalidFieldName,
-                 "Field name '%s' contains invalid characters. "
-                 "'%s' will be used instead.", pszSrcName, pszNewName);
+        CPLError(
+            CE_Warning, static_cast<CPLErrorNum>(TAB_WarningInvalidFieldName),
+            "Field name '%s' contains invalid characters. "
+            "'%s' will be used instead.", pszSrcName, pszNewName);
     }
 
     return pszNewName;
 }
 
-
 /**********************************************************************
  * MapInfo Units string to numeric ID conversion
  **********************************************************************/
@@ -710,7 +563,6 @@ static const MapInfoUnitsInfo gasUnitsList[] =
     {-1, NULL}
 };
 
-
 /**********************************************************************
  *                       TABUnitIdToString()
  *
@@ -721,9 +573,7 @@ static const MapInfoUnitsInfo gasUnitsList[] =
  **********************************************************************/
 const char *TABUnitIdToString(int nId)
 {
-    const MapInfoUnitsInfo *psList;
-
-    psList = gasUnitsList;
+    const MapInfoUnitsInfo *psList = gasUnitsList;
 
     while(psList->nUnitId != -1)
     {
@@ -744,13 +594,11 @@ const char *TABUnitIdToString(int nId)
  **********************************************************************/
 int TABUnitIdFromString(const char *pszName)
 {
-    const MapInfoUnitsInfo *psList;
-
-    psList = gasUnitsList;
-
     if( pszName == NULL )
         return 13;
 
+    const MapInfoUnitsInfo *psList = gasUnitsList;
+
     while(psList->nUnitId != -1)
     {
         if (psList->pszAbbrev != NULL &&
@@ -762,19 +610,21 @@ int TABUnitIdFromString(const char *pszName)
     return -1;
 }
 
-
 /**********************************************************************
  *                       TABSaturatedAdd()
  ***********************************************************************/
 
 void TABSaturatedAdd(GInt32& nVal, GInt32 nAdd)
 {
-    if( nAdd >= 0 && nVal > INT_MAX - nAdd )
-        nVal = INT_MAX;
-    else if( nAdd == INT_MIN && nVal < 0 )
-        nVal = INT_MIN;
-    else if( nAdd != INT_MIN && nAdd < 0 && nVal < INT_MIN - nAdd )
-        nVal = INT_MIN;
+    const GInt32 int_max = std::numeric_limits<GInt32>::max();
+    const GInt32 int_min = std::numeric_limits<GInt32>::min();
+
+    if( nAdd >= 0 && nVal > int_max - nAdd )
+        nVal = int_max;
+    else if( nAdd == int_min && nVal < 0 )
+        nVal = int_min;
+    else if( nAdd != int_min && nAdd < 0 && nVal < int_min - nAdd )
+        nVal = int_min;
     else
         nVal += nAdd;
 }
diff --git a/ogr/ogrsf_frmts/mitab/mitab_utils.h b/ogr/ogrsf_frmts/mitab/mitab_utils.h
index 40bd6a6..2e62d90 100644
--- a/ogr/ogrsf_frmts/mitab/mitab_utils.h
+++ b/ogr/ogrsf_frmts/mitab/mitab_utils.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: mitab_utils.h,v 1.10 2004-06-30 20:29:04 dmorissette Exp $
+ * $Id: mitab_utils.h 37335 2017-02-09 14:29:57Z goatbar $
  *
  * Name:     mitab_utils.h
  * Project:  MapInfo TAB Read/Write library
@@ -27,39 +27,6 @@
  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
- **********************************************************************
- *
- * $Log: mitab_utils.h,v $
- * Revision 1.10  2004-06-30 20:29:04  dmorissette
- * Fixed refs to old address danmo at videotron.ca
- *
- * Revision 1.9  2001/01/23 21:23:42  daniel
- * Added projection bounds lookup table, called from TABFile::SetProjInfo()
- *
- * Revision 1.8  2000/02/18 20:46:58  daniel
- * Added TABCleanFieldName()
- *
- * Revision 1.7  2000/01/15 22:30:45  daniel
- * Switch to MIT/X-Consortium OpenSource license
- *
- * Revision 1.6  2000/01/14 23:47:00  daniel
- * Added TABEscapeString()/TABUnEscapeString()
- *
- * Revision 1.5  1999/12/14 02:08:16  daniel
- * Added TABGetBasename() + TAB_CSLLoad()
- *
- * Revision 1.4  1999/09/28 13:33:32  daniel
- * Moved definition for PI to mitab.h
- *
- * Revision 1.3  1999/09/26 14:59:38  daniel
- * Implemented write support
- *
- * Revision 1.2  1999/09/16 02:39:17  daniel
- * Completed read support for most feature types
- *
- * Revision 1.1  1999/07/12 04:18:25  daniel
- * Initial checkin
- *
  **********************************************************************/
 
 #ifndef MITAB_UTILS_H_INCLUDED_
@@ -81,7 +48,6 @@ int TABGenerateArc(OGRLineString *poLine, int numPoints,
                    double dStartAngle, double dEndAngle);
 int TABCloseRing(OGRLineString *poRing);
 
-
 GBool TABAdjustFilenameExtension(char *pszFname);
 char *TABGetBasename(const char *pszFname);
 char **TAB_CSLLoad(const char *pszFname);
diff --git a/ogr/ogrsf_frmts/mongodb/drv_mongodb.html b/ogr/ogrsf_frmts/mongodb/drv_mongodb.html
index a959d99..ca4d91d 100644
--- a/ogr/ogrsf_frmts/mongodb/drv_mongodb.html
+++ b/ogr/ogrsf_frmts/mongodb/drv_mongodb.html
@@ -10,7 +10,9 @@
 (GDAL/OGR >= 2.1.0)<p>
 
 This driver can connect to the a MongoDB service.<p>
-The driver supports read, creation, update and delete operations.<p>
+The driver supports read, creation, update and delete operations of documents/features
+and collections/layers. The MongoDB database must exist before operating on it
+with OGR.<p>
 
 <h2>MongoDB vs OGR concepts</h2>
 
@@ -164,7 +166,7 @@ ogrinfo -ro mongodb://user:password@ds047612.mongolab.com:47612/gdalautotest -wh
 <li>
 Creating and populating a collection from a shapefile:
 <pre>
-ogr2ogr -f mongodb mongodb://user:password@ds047612.mongolab.com:47612/gdalautotest shapefile.shp
+ogr2ogr -update mongodb://user:password@ds047612.mongolab.com:47612/gdalautotest shapefile.shp
 </pre>
 <p>
 
diff --git a/ogr/ogrsf_frmts/mongodb/ogrmongodbdriver.cpp b/ogr/ogrsf_frmts/mongodb/ogrmongodbdriver.cpp
index 6c3017f..cdd3388 100644
--- a/ogr/ogrsf_frmts/mongodb/ogrmongodbdriver.cpp
+++ b/ogr/ogrsf_frmts/mongodb/ogrmongodbdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmongodbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  MongoDB Translator
  * Purpose:  Implements OGRMongoDBDriver.
@@ -38,7 +37,7 @@
 #include <limits>
 
 // g++ -DDEBUG -g -Wall -fPIC -shared -o ogr_MongoDB.so -I/home/even/boost_1_53_0 -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/mongodb ogr/ogrsf_frmts/mongodb/*.c* -L. -lgdal -I/home/even/mongo-cxx-1.0.2-install/include -L/home/even/mongo-cxx-1.0.2-install/lib -lmongoclient -L/home/even/boost_1_53_0/stage/lib -lboost_system -lboost_thread -lboost_regex
-CPL_CVSID("$Id: ogrmongodbdriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrmongodbdriver.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 #define MAX_DOCS_IN_BULK                1000
 
@@ -124,7 +123,7 @@ class OGRMongoDBLayer: public OGRLayer
             void                     SerializeRecursive(BSONObjBuilder& b,
                                          OGRFeature *poFeature,
                                          std::map< CPLString, IntOrMap*>& aoMap );
-            void                     InsertInMap(IntOrMap* rootMap,
+            static void                     InsertInMap(IntOrMap* rootMap,
                                                   std::map< std::vector<CPLString>, IntOrMap*>& aoMap,
                                                   const std::vector<CPLString>& aosFieldPathFull,
                                                   int nField);
@@ -135,26 +134,26 @@ public:
             OGRMongoDBLayer(OGRMongoDBDataSource* m_poDS,
                             const char* pszDatabase,
                             const char* pszCollection);
-           ~OGRMongoDBLayer();
-
-            virtual OGRFeatureDefn* GetLayerDefn();
-            virtual const char* GetName() { return m_poFeatureDefn->GetName(); }
-            virtual void        ResetReading();
-            virtual OGRFeature* GetNextFeature();
-            virtual OGRFeature* GetFeature(GIntBig nFID);
-            virtual OGRErr      DeleteFeature(GIntBig nFID);
-            virtual int         TestCapability(const char* pszCap);
-            virtual GIntBig     GetFeatureCount(int bForce);
-            virtual OGRErr      SetAttributeFilter(const char* pszFilter);
-            virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
-            virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
-            virtual const char* GetFIDColumn();
-            virtual OGRErr      CreateField( OGRFieldDefn *poFieldIn, int bApproxOK );
-            virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poFieldIn, int bApproxOK );
-            virtual OGRErr      ICreateFeature(OGRFeature* poFeature);
-            virtual OGRErr      ISetFeature(OGRFeature* poFeature);
-
-            virtual OGRErr      SyncToDisk();
+          virtual ~OGRMongoDBLayer();
+
+            virtual OGRFeatureDefn* GetLayerDefn() override;
+            virtual const char* GetName() override { return m_poFeatureDefn->GetName(); }
+            virtual void        ResetReading() override;
+            virtual OGRFeature* GetNextFeature() override;
+            virtual OGRFeature* GetFeature(GIntBig nFID) override;
+            virtual OGRErr      DeleteFeature(GIntBig nFID) override;
+            virtual int         TestCapability(const char* pszCap) override;
+            virtual GIntBig     GetFeatureCount(int bForce) override;
+            virtual OGRErr      SetAttributeFilter(const char* pszFilter) override;
+            virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override { SetSpatialFilter(0, poGeom); }
+            virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override;
+            virtual const char* GetFIDColumn() override;
+            virtual OGRErr      CreateField( OGRFieldDefn *poFieldIn, int bApproxOK ) override;
+            virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poFieldIn, int bApproxOK ) override;
+            virtual OGRErr      ICreateFeature(OGRFeature* poFeature) override;
+            virtual OGRErr      ISetFeature(OGRFeature* poFeature) override;
+
+            virtual OGRErr      SyncToDisk() override;
 
             const CPLString&    GetDatabase() const { return m_osDatabase; }
             const CPLString&    GetCollection() const { return m_osCollection; }
@@ -166,7 +165,6 @@ public:
             void                SetCreateSpatialIndex(int bFlag) { m_bCreateSpatialIndex = bFlag; }
 };
 
-
 class OGRMongoDBDataSource: public GDALDataset
 {
             DBClientBase *m_poConn;
@@ -185,23 +183,23 @@ class OGRMongoDBDataSource: public GDALDataset
 
 public:
             OGRMongoDBDataSource();
-            ~OGRMongoDBDataSource();
+            virtual ~OGRMongoDBDataSource();
 
             int Open(const char* pszFilename, GDALAccess eAccess, char** papszOpenOptions);
-            virtual int GetLayerCount() { return (int)m_apoLayers.size(); }
-            virtual OGRLayer* GetLayer(int nIdx);
-            virtual int         TestCapability(const char* pszCap);
+            virtual int GetLayerCount() override { return (int)m_apoLayers.size(); }
+            virtual OGRLayer* GetLayer(int nIdx) override;
+            virtual int         TestCapability(const char* pszCap) override;
             virtual OGRLayer   *ICreateLayer( const char *pszName,
                                              OGRSpatialReference *poSpatialRef = NULL,
                                              OGRwkbGeometryType eGType = wkbUnknown,
-                                             char ** papszOptions = NULL );
-            virtual OGRErr      DeleteLayer( int iLayer );
-            virtual OGRLayer   *GetLayerByName(const char* pszLayerName);
+                                             char ** papszOptions = NULL ) override;
+            virtual OGRErr      DeleteLayer( int iLayer ) override;
+            virtual OGRLayer   *GetLayerByName(const char* pszLayerName) override;
 
             virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                             OGRGeometry *poSpatialFilter,
-                                            const char *pszDialect );
-            virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                            const char *pszDialect ) override;
+            virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
             const CPLString& GetDatabase() const { return m_osDatabase; }
             DBClientBase    *GetConn() const { return m_poConn; }
@@ -220,13 +218,13 @@ public:
 
 OGRMongoDBLayer::OGRMongoDBLayer(OGRMongoDBDataSource* poDS,
                             const char* pszDatabase,
-                            const char* pszCollection)
+                            const char* pszCollection) :
+    m_osDatabase( pszDatabase),
+    m_osCollection( pszCollection )
 {
     m_poDS = poDS;
-    m_osDatabase = pszDatabase;
-    m_osCollection = pszCollection;
     m_osQualifiedCollection = CPLSPrintf("%s.%s", m_osDatabase.c_str(), m_osCollection.c_str());
-    if( m_poDS->GetDatabase().size() )
+    if( !m_poDS->GetDatabase().empty() )
         m_poFeatureDefn = new OGRFeatureDefn(pszCollection);
     else
         m_poFeatureDefn = new OGRFeatureDefn(m_osQualifiedCollection);
@@ -282,7 +280,7 @@ void OGRMongoDBLayer::WriteOGRMetadata()
 
         b.append("layer", m_osCollection.c_str());
 
-        if( m_osFID.size() )
+        if( !m_osFID.empty() )
         {
             b.append( "fid", m_osFID.c_str() );
         }
@@ -980,9 +978,8 @@ static void OGRMongoDBReaderSetField( OGRLayer* poLayer,
     BSONType eBSONType = poElt->type();
     OGRFieldType eType = poFieldDefn->GetType();
     if( eBSONType == jstNULL )
-        return;
-
-    if( eBSONType == NumberInt )
+        poFeature->SetFieldNull( nField );
+    else if( eBSONType == NumberInt )
         poFeature->SetField( nField, poElt->Int() );
     else if( eBSONType == NumberLong )
         poFeature->SetField( nField, poElt->Long() );
@@ -1093,7 +1090,7 @@ static void OGRMongoDBReaderSetField( OGRLayer* poLayer,
                     double dfVal = elt.Double();
                     if( dfVal < std::numeric_limits<GIntBig>::min() )
                         panValues[i] = std::numeric_limits<GIntBig>::min();
-                    else if( dfVal > std::numeric_limits<GIntBig>::max() )
+                    else if( dfVal > static_cast<double>(std::numeric_limits<GIntBig>::max()) )
                         panValues[i] = std::numeric_limits<GIntBig>::max();
                     else
                         panValues[i] = (int)dfVal;
@@ -1137,7 +1134,7 @@ OGRFeature* OGRMongoDBLayer::Translate(BSONObj& obj)
         for( BSONObj::iterator i(obj); i.more(); )
         {
             BSONElement elt(i.next());
-            if( m_osFID.size() && EQUAL(m_osFID, elt.fieldName()) )
+            if( !m_osFID.empty() && EQUAL(m_osFID, elt.fieldName()) )
             {
                 BSONType eBSONType = elt.type();
                 if( eBSONType == NumberInt )
@@ -1235,7 +1232,7 @@ OGRFeature* OGRMongoDBLayer::GetFeature(GIntBig nFID)
     if( m_poBulkBuilder )
         SyncToDisk();
 
-    if( m_osFID.size() == 0 )
+    if( m_osFID.empty() )
     {
         BSONObj oQueryAttrBak(m_oQueryAttr), oQuerySpatBak(m_oQuerySpat);
         OGRFeature* poFeature = OGRLayer::GetFeature(nFID);
@@ -1282,7 +1279,7 @@ OGRErr OGRMongoDBLayer::DeleteFeature(GIntBig nFID)
         EstablishFeatureDefn();
     if( m_poBulkBuilder )
         SyncToDisk();
-    if( m_osFID.size() == 0 )
+    if( m_osFID.empty() )
         return OGRERR_FAILURE;
 
     try
@@ -1417,7 +1414,7 @@ OGRErr OGRMongoDBLayer::CreateGeomField( OGRGeomFieldDefn *poFieldIn, CPL_UNUSED
                 pszIndexType = CPLGetConfigOption("OGR_MONGODB_SPAT_INDEX_TYPE", "2dsphere");
             m_poDS->GetConn()->createIndex(m_osQualifiedCollection,
                                          BSON( oFieldDefn.GetNameRef() << pszIndexType ));
-            m_aosGeomIndexes[m_aosGeomIndexes.size()-1] = pszIndexType;
+            m_aosGeomIndexes.back() = pszIndexType;
         }
         catch( const DBException &e )
         {
@@ -1441,7 +1438,11 @@ void OGRMongoDBLayer::SerializeField(BSONObjBuilder& b,
                                      const char* pszJSonField)
 {
     OGRFieldType eType = m_poFeatureDefn->GetFieldDefn(iField)->GetType();
-    if( eType == OFTInteger )
+    if( poFeature->IsFieldNull(iField) )
+    {
+        b.appendNull( pszJSonField );
+    }
+    else if( eType == OFTInteger )
     {
         if( m_poFeatureDefn->GetFieldDefn(iField)->GetSubType() == OFSTBoolean )
             b.append( pszJSonField, CPL_TO_BOOL(poFeature->GetFieldAsInteger(iField)) );
@@ -1624,7 +1625,7 @@ void OGRMongoDBLayer::InsertInMap(IntOrMap* rootMap,
     intOrMap->bIsMap = FALSE;
     intOrMap->u.nField = nField;
     std::map< CPLString, IntOrMap* >* poPrevMap = aoMap[aosFieldPathPrev]->u.poMap;
-    const CPLString& osLastComponent(aosFieldPathFull[aosFieldPathFull.size() - 1]);
+    const CPLString& osLastComponent(aosFieldPathFull.back());
     CPLAssert( (*poPrevMap).find(osLastComponent) == (*poPrevMap).end() );
     (*(poPrevMap))[osLastComponent] = intOrMap;
 }
@@ -1638,7 +1639,7 @@ BSONObj OGRMongoDBLayer::BuildBSONObjFromFeature(OGRFeature* poFeature, int bUpd
     BSONObjBuilder b;
 
     int nJSonFieldIndex = m_poFeatureDefn->GetFieldIndex("_json");
-    if( nJSonFieldIndex >= 0 && poFeature->IsFieldSet(nJSonFieldIndex) )
+    if( nJSonFieldIndex >= 0 && poFeature->IsFieldSetAndNotNull(nJSonFieldIndex) )
     {
         CPLString osJSon(poFeature->GetFieldAsString(nJSonFieldIndex));
 
@@ -1672,14 +1673,14 @@ BSONObj OGRMongoDBLayer::BuildBSONObjFromFeature(OGRFeature* poFeature, int bUpd
         return b.obj();
     }
 
-    if( poFeature->GetFID() >= 0 && m_osFID.size() )
+    if( poFeature->GetFID() >= 0 && !m_osFID.empty() )
     {
         b.append( m_osFID.c_str(), poFeature->GetFID() );
     }
 
     CPLAssert((int)m_aaosFieldPaths.size() == m_poFeatureDefn->GetFieldCount());
 
-    if( !poFeature->IsFieldSet(0) || (!bUpdate && m_bIgnoreSourceID) )
+    if( !poFeature->IsFieldSetAndNotNull(0) || (!bUpdate && m_bIgnoreSourceID) )
     {
         const OID generated = OID::gen();
         b.append("_id", generated);
@@ -1804,7 +1805,7 @@ OGRErr OGRMongoDBLayer::ISetFeature( OGRFeature *poFeature )
     if( m_poBulkBuilder )
         SyncToDisk();
 
-    if( !poFeature->IsFieldSet(0) )
+    if( !poFeature->IsFieldSetAndNotNull(0) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "_id field not set");
         return OGRERR_FAILURE;
@@ -1840,7 +1841,7 @@ int OGRMongoDBLayer::TestCapability(const char* pszCap)
     else if( EQUAL(pszCap,OLCRandomRead) )
     {
         EstablishFeatureDefn();
-        return m_osFID.size() > 0;
+        return !m_osFID.empty();
     }
     else if( EQUAL(pszCap, OLCFastSpatialFilter) )
     {
@@ -1865,7 +1866,7 @@ int OGRMongoDBLayer::TestCapability(const char* pszCap)
     {
         EstablishFeatureDefn();
         return m_poDS->GetAccess() == GA_Update &&
-               m_osFID.size() > 0;
+               !m_osFID.empty();
     }
 
     return FALSE;
@@ -2026,7 +2027,7 @@ OGRLayer *OGRMongoDBDataSource::GetLayerByName(const char* pszLayerName)
     }
 
     CPLString osDatabase;
-    if( m_osDatabase.size() == 0 )
+    if( m_osDatabase.empty() )
     {
         const char* pszDot = strchr(pszLayerName, '.');
         if( pszDot == NULL )
@@ -2043,7 +2044,7 @@ OGRLayer *OGRMongoDBDataSource::GetLayerByName(const char* pszLayerName)
         try
         {
             std::list<std::string> l = m_poConn->getCollectionNames( osDatabase );
-            for ( std::list<std::string>::iterator oIter = l.begin(); oIter != l.end(); oIter++ )
+            for ( std::list<std::string>::iterator oIter = l.begin(); oIter != l.end(); ++oIter )
             {
                 const std::string& osCollection(*oIter);
                 if( EQUAL(osCollection.c_str(),pszLayerName) )
@@ -2062,7 +2063,7 @@ OGRLayer *OGRMongoDBDataSource::GetLayerByName(const char* pszLayerName)
         }
         if( i == 0 )
         {
-            if( m_osDatabase.size() == 0 )
+            if( m_osDatabase.empty() )
                 break;
             const char* pszDot = strchr(pszLayerName, '.');
             if( pszDot == NULL )
@@ -2086,9 +2087,11 @@ int OGRMongoDBDataSource::Initialize(char** papszOpenOptions)
     CPLString osPEMKeyPassword = CSLFetchNameValueDef(papszOpenOptions, "SSL_PEM_KEY_PASSWORD", "");
     CPLString osCAFile = CSLFetchNameValueDef(papszOpenOptions, "SSL_CA_FILE", "");
     CPLString osCRLFile = CSLFetchNameValueDef(papszOpenOptions, "SSL_CRL_FILE", "");
-    int bAllowInvalidCertificates = CSLFetchBoolean(papszOpenOptions, "SSL_ALLOW_INVALID_CERTIFICATES", FALSE);
-    int bAllowInvalidHostnames = CSLFetchBoolean(papszOpenOptions, "SSL_ALLOW_INVALID_HOSTNAMES", FALSE);
-    int bFIPSMode = CSLFetchBoolean(papszOpenOptions, "FIPS_MODE", FALSE);
+    int bAllowInvalidCertificates =
+        CPLFetchBool(papszOpenOptions, "SSL_ALLOW_INVALID_CERTIFICATES", false);
+    int bAllowInvalidHostnames =
+        CPLFetchBool(papszOpenOptions, "SSL_ALLOW_INVALID_HOSTNAMES", false);
+    int bFIPSMode = CPLFetchBool(papszOpenOptions, "FIPS_MODE", false);
     if( bMongoInitialized < 0 )
     {
         Options options;
@@ -2100,17 +2103,17 @@ int OGRMongoDBDataSource::Initialize(char** papszOpenOptions)
         bStaticAllowInvalidHostnames = bAllowInvalidHostnames;
         bStaticFIPSMode = bFIPSMode;
 
-        if( osPEMKeyFile.size() || osPEMKeyPassword.size() ||
-            osCAFile.size() || osCRLFile.size() )
+        if( !osPEMKeyFile.empty() || !osPEMKeyPassword.empty() ||
+            !osCAFile.empty() || !osCRLFile.empty() )
         {
             options.setSSLMode(Options::kSSLRequired);
-            if( osPEMKeyFile.size() )
+            if( !osPEMKeyFile.empty() )
                 options.setSSLPEMKeyFile(osPEMKeyFile);
             if( osPEMKeyPassword )
                 options.setSSLPEMKeyPassword(osPEMKeyPassword);
-            if( osCAFile.size() )
+            if( !osCAFile.empty() )
                 options.setSSLCAFile(osCAFile);
-            if( osCRLFile.size() )
+            if( !osCRLFile.empty() )
                 options.setSSLCRLFile(osCRLFile);
             if( bAllowInvalidCertificates )
                 options.setSSLAllowInvalidCertificates(true);
@@ -2265,10 +2268,10 @@ int OGRMongoDBDataSource::Open(const char* pszFilename,
         }
     }
 
-    if( m_osDatabase.size() == 0 )
+    if( m_osDatabase.empty() )
     {
         m_osDatabase = CSLFetchNameValueDef(papszOpenOptionsIn, "DBNAME", "");
-        /*if( m_osDatabase.size() == 0 )
+        /*if( m_osDatabase.empty() )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "No database name specified");
             return FALSE;
@@ -2320,7 +2323,7 @@ int OGRMongoDBDataSource::Open(const char* pszFilename,
         }
         if( pszUser && pszPassword )
         {
-            if( m_osDatabase.size() == 0 && pszAuthDBName == NULL)
+            if( m_osDatabase.empty() && pszAuthDBName == NULL)
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "No database or authentication database name specified.");
@@ -2353,21 +2356,21 @@ int OGRMongoDBDataSource::Open(const char* pszFilename,
     m_nBatchSize = atoi(CSLFetchNameValueDef(papszOpenOptionsIn, "BATCH_SIZE", "0"));
     m_nFeatureCountToEstablishFeatureDefn = atoi(CSLFetchNameValueDef(
         papszOpenOptionsIn, "FEATURE_COUNT_TO_ESTABLISH_FEATURE_DEFN", "100"));
-    m_bJSonField = CSLFetchBoolean(papszOpenOptionsIn, "JSON_FIELD", FALSE);
-    m_bFlattenNestedAttributes = CPL_TO_BOOL(CSLFetchBoolean(
-            papszOpenOptionsIn, "FLATTEN_NESTED_ATTRIBUTES", TRUE));
+    m_bJSonField = CPLFetchBool(papszOpenOptionsIn, "JSON_FIELD", false);
+    m_bFlattenNestedAttributes =
+        CPLFetchBool(papszOpenOptionsIn, "FLATTEN_NESTED_ATTRIBUTES", true);
     m_osFID = CSLFetchNameValueDef(papszOpenOptionsIn, "FID", "ogc_fid");
-    m_bUseOGRMetadata = CSLFetchBoolean(
-            papszOpenOptionsIn, "USE_OGR_METADATA", TRUE);
-    m_bBulkInsert = CSLFetchBoolean(papszOpenOptionsIn, "BULK_INSERT", TRUE);
+    m_bUseOGRMetadata =
+        CPLFetchBool( papszOpenOptionsIn, "USE_OGR_METADATA", true);
+    m_bBulkInsert = CPLFetchBool(papszOpenOptionsIn, "BULK_INSERT", true);
 
     int bRet = TRUE;
-    if( m_osDatabase.size() == 0 )
+    if( m_osDatabase.empty() )
     {
         try
         {
             std::list<std::string> l = m_poConn->getDatabaseNames();
-            for ( std::list<std::string>::iterator i = l.begin(); i != l.end(); i++ )
+            for ( std::list<std::string>::iterator i = l.begin(); i != l.end(); ++i )
             {
                 bRet &= ListLayers((*i).c_str());
             }
@@ -2445,7 +2448,7 @@ OGRLayer* OGRMongoDBDataSource::ICreateLayer( const char *pszName,
                                               OGRwkbGeometryType eGType,
                                               char ** papszOptions )
 {
-    if( m_osDatabase.size() == 0 )
+    if( m_osDatabase.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot create layer/collection when dataset opened without explicit database");
@@ -2482,10 +2485,14 @@ OGRLayer* OGRMongoDBDataSource::ICreateLayer( const char *pszName,
     OGRMongoDBLayer* poLayer = new OGRMongoDBLayer(this, m_osDatabase, pszName);
 
     poLayer->SetFID(CSLFetchNameValueDef(papszOptions, "FID", "ogc_fid"));
-    poLayer->SetCreateLayerMetadata(CSLFetchBoolean(papszOptions, "WRITE_OGR_METADATA", TRUE));
-    poLayer->SetDotAsNestedField(CSLFetchBoolean(papszOptions, "DOT_AS_NESTED_FIELD", TRUE));
-    poLayer->SetIgnoreSourceID(CSLFetchBoolean(papszOptions, "IGNORE_SOURCE_ID", FALSE));
-    poLayer->SetCreateSpatialIndex(CSLFetchBoolean(papszOptions, "SPATIAL_INDEX", TRUE));
+    poLayer->SetCreateLayerMetadata(
+        CPLFetchBool(papszOptions, "WRITE_OGR_METADATA", true));
+    poLayer->SetDotAsNestedField(
+        CPLFetchBool(papszOptions, "DOT_AS_NESTED_FIELD", true));
+    poLayer->SetIgnoreSourceID(
+        CPLFetchBool(papszOptions, "IGNORE_SOURCE_ID", false));
+    poLayer->SetCreateSpatialIndex(
+        CPLFetchBool(papszOptions, "SPATIAL_INDEX", true));
 
     if( eGType != wkbNone )
     {
@@ -2571,12 +2578,12 @@ class OGRMongoDBSingleFeatureLayer: public OGRLayer
     CPLString           osVal;
     int                 iNextShapeId;
     public:
-        OGRMongoDBSingleFeatureLayer( const char *pszVal );
+       explicit OGRMongoDBSingleFeatureLayer( const char *pszVal );
        ~OGRMongoDBSingleFeatureLayer() { m_poFeatureDefn->Release(); }
-       void             ResetReading() { iNextShapeId = 0; }
-       OGRFeature      *GetNextFeature();
-       OGRFeatureDefn  *GetLayerDefn() { return m_poFeatureDefn; }
-       int              TestCapability( const char * ) { return FALSE; }
+       void             ResetReading() override { iNextShapeId = 0; }
+       OGRFeature      *GetNextFeature() override;
+       OGRFeatureDefn  *GetLayerDefn() override { return m_poFeatureDefn; }
+       int              TestCapability( const char * ) override { return FALSE; }
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/mssqlspatial/GNUmakefile b/ogr/ogrsf_frmts/mssqlspatial/GNUmakefile
index d4e8cee..13847e9 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/GNUmakefile
+++ b/ogr/ogrsf_frmts/mssqlspatial/GNUmakefile
@@ -1,12 +1,12 @@
-
-
-include ../../../GDALmake.opt
-
-OBJ	=	ogrmssqlspatialdatasource.o ogrmssqlspatiallayer.o ogrmssqlspatialtablelayer.o ogrmssqlspatialselectlayer.o ogrmssqlspatialdriver.o ogrmssqlgeometryparser.o ogrmssqlgeometryvalidator.o ogrmssqlgeometrywriter.o
-
-CPPFLAGS	:=	 -I.. -I../.. $(CPPFLAGS)
-
-default:	$(O_OBJ:.o=.$(OBJ_EXT))
-
-clean:
-	rm -f *.o $(O_OBJ)
+
+
+include ../../../GDALmake.opt
+
+OBJ	=	ogrmssqlspatialdatasource.o ogrmssqlspatiallayer.o ogrmssqlspatialtablelayer.o ogrmssqlspatialselectlayer.o ogrmssqlspatialdriver.o ogrmssqlgeometryparser.o ogrmssqlgeometryvalidator.o ogrmssqlgeometrywriter.o
+
+CPPFLAGS	:=	 -I.. -I../.. $(CPPFLAGS)
+
+default:	$(O_OBJ:.o=.$(OBJ_EXT))
+
+clean:
+	rm -f *.o $(O_OBJ)
diff --git a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
index d43cd3f..520de27 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
+++ b/ogr/ogrsf_frmts/mssqlspatial/drv_mssqlspatial.html
@@ -127,8 +127,8 @@ Options</a> which help control the behavior of this driver.</p>
     Client 11.0. To specify a BCP supported driver in the connection string, use the
     driver parameter, like DRIVER={SQL Server Native Client 11.0}. If GDAL is
     compiled against SQL Server Native Client 10.0 or 11.0 the driver is selected
-    automatically not requiring to specify that in the connection string. If GDAL is 
-    compiled against SQL Server Native Client 10.0 or 11.0 the default setting of 
+    automatically not requiring to specify that in the connection string. If GDAL is
+    compiled against SQL Server Native Client 10.0 or 11.0 the default setting of
     this parameter is TRUE, otherwise the parameter is ignored by the driver.</li>
 <li><b>MSSQLSPATIAL_BCP_SIZE</b>: (From GDAL 2.1.0) Specifies the bulk insert batch size. The larger value makes the insert faster, but consumes more memory. Default = 1000.</li>
 <li><b>MSSQLSPATIAL_OGR_FID</b>: Override FID column name. Default = ogr_fid.</li>
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h b/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
index 5090774..2765ee8 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogr_mssqlspatial.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mssqlspatial.h 33807 2016-03-29 19:06:42Z tamas $
+ * $Id: ogr_mssqlspatial.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
@@ -91,10 +91,12 @@ protected:
     OGRGeometry*    poOriginalGeometry;
 
 public:
-                    OGRMSSQLGeometryValidator(OGRGeometry* poGeom);
+    explicit         OGRMSSQLGeometryValidator(OGRGeometry* poGeom);
                     ~OGRMSSQLGeometryValidator();
 
+    // cppcheck-suppress functionStatic
     int             ValidatePoint(OGRPoint * poGeom);
+    // cppcheck-suppress functionStatic
     int             ValidateMultiPoint(OGRMultiPoint * poGeom);
     int             ValidateLineString(OGRLineString * poGeom);
     int             ValidateLinearRing(OGRLinearRing * poGeom);
@@ -114,7 +116,7 @@ public:
 
 class OGRMSSQLGeometryParser
 {
-protected:    
+protected:
     unsigned char* pszData;
     /* serialization properties */
     char chProps;
@@ -142,13 +144,12 @@ protected:
     OGRGeometryCollection* ReadGeometryCollection(int iShape);
 
 public:
-                        OGRMSSQLGeometryParser( int nGeomColumnType );
+    explicit            OGRMSSQLGeometryParser( int nGeomColumnType );
     OGRErr              ParseSqlGeometry(unsigned char* pszInput, int nLen,
                                                         OGRGeometry **poGeom);
     int                 GetSRSId() { return nSRSId; };
 };
 
-
 /************************************************************************/
 /*                           OGRMSSQLGeometryWriter                     */
 /************************************************************************/
@@ -194,7 +195,6 @@ public:
     int              GetDataLen() { return nLen; }
 };
 
-
 /************************************************************************/
 /*                             OGRMSSQLSpatialLayer                     */
 /************************************************************************/
@@ -236,24 +236,24 @@ class OGRMSSQLSpatialLayer : public OGRLayer
                         OGRMSSQLSpatialLayer();
     virtual             ~OGRMSSQLSpatialLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
     virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
+
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
-    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual OGRErr     StartTransaction();
-    virtual OGRErr     CommitTransaction();
-    virtual OGRErr     RollbackTransaction();
+    virtual OGRErr     StartTransaction() override;
+    virtual OGRErr     CommitTransaction() override;
+    virtual OGRErr     RollbackTransaction() override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
     char*               GByteArrayToHexString( const GByte* pabyData, int nLen);
 
     void               SetLayerStatus( int nStatus ) { nLayerStatus = nStatus; }
@@ -274,7 +274,7 @@ typedef union {
         int     iIndicator;
         GIntBig     Value;
     } Integer64;
-    
+
     struct {
         int     iIndicator;
         double  Value;
@@ -302,7 +302,7 @@ class OGRMSSQLSpatialTableLayer : public OGRMSSQLSpatialLayer
     int                 nBCPSize;
 
     int                 nUploadGeometryFormat;
-    
+
     char                *pszQuery;
 
     SQLHANDLE           hEnvBCP;
@@ -312,12 +312,12 @@ class OGRMSSQLSpatialTableLayer : public OGRMSSQLSpatialLayer
 
     int                 bIdentityInsert;
 
-    void		ClearStatement();
+    void                ClearStatement();
     CPLODBCStatement* BuildStatement(const char* pszColumns);
 
     CPLString BuildFields();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *  GetStatement() override;
 
     char               *pszTableName;
     char               *pszLayerName;
@@ -325,15 +325,14 @@ class OGRMSSQLSpatialTableLayer : public OGRMSSQLSpatialLayer
 
     OGRwkbGeometryType eGeomType;
 
-
   public:
-                        OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource * );
-                        ~OGRMSSQLSpatialTableLayer();
+    explicit            OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource * );
+                        virtual ~OGRMSSQLSpatialTableLayer();
 
     CPLErr              Initialize( const char *pszSchema,
-                                    const char *pszTableName, 
-                                    const char *pszGeomCol, 
-                                    int nCoordDimension, 
+                                    const char *pszTableName,
+                                    const char *pszGeomCol,
+                                    int nCoordDimension,
                                     int nSRId,
                                     const char *pszSRText,
                                     OGRwkbGeometryType eType);
@@ -341,31 +340,31 @@ class OGRMSSQLSpatialTableLayer : public OGRMSSQLSpatialLayer
     OGRErr              CreateSpatialIndex();
     void                DropSpatialIndex();
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual const char* GetName();
+    virtual const char* GetName() override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
 
     const char*         GetTableName() { return pszTableName; }
     const char*         GetLayerName() { return pszLayerName; }
     const char*         GetSchemaName() { return pszSchemaName; }
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-   
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+                                     int bApproxOK = TRUE ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    void                SetLaunderFlag( int bFlag ) 
+    virtual int         TestCapability( const char * ) override;
+
+    void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
     void                SetPrecisionFlag( int bFlag )
                                 { bPreservePrecision = bFlag; }
@@ -396,26 +395,26 @@ class OGRMSSQLSpatialSelectLayer : public OGRMSSQLSpatialLayer
 {
     char                *pszBaseStatement;
 
-    void		ClearStatement();
+    void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *  GetStatement() override;
 
   public:
-                        OGRMSSQLSpatialSelectLayer( OGRMSSQLSpatialDataSource *, 
+                        OGRMSSQLSpatialSelectLayer( OGRMSSQLSpatialDataSource *,
                                            CPLODBCStatement * );
-                        ~OGRMSSQLSpatialSelectLayer();
+                        virtual ~OGRMSSQLSpatialSelectLayer();
+
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -426,7 +425,7 @@ class OGRMSSQLSpatialDataSource : public OGRDataSource
 {
     OGRMSSQLSpatialTableLayer    **papoLayers;
     int                 nLayers;
-    
+
     char               *pszName;
 
     char               *pszCatalog;
@@ -444,48 +443,48 @@ class OGRMSSQLSpatialDataSource : public OGRDataSource
     int                 bUseCopy;
 
     // We maintain a list of known SRID to reduce the number of trips to
-    // the database to get SRSes. 
+    // the database to get SRSes.
     int                 nKnownSRID;
     int                *panSRID;
     OGRSpatialReference **papoSRS;
 
     char                *pszConnection;
-    
+
   public:
                         OGRMSSQLSpatialDataSource();
-                        ~OGRMSSQLSpatialDataSource();
+                        virtual ~OGRMSSQLSpatialDataSource();
 
     const char          *GetCatalog() { return pszCatalog; }
 
-    int                 ParseValue(char** pszValue, char* pszSource, const char* pszKey,
+    static int                 ParseValue(char** pszValue, char* pszSource, const char* pszKey,
                                   int nStart, int nNext, int nTerm, int bRemove);
 
     int                 Open( const char *, int bUpdate, int bTestOpen );
-    int                 OpenTable( const char *pszSchemaName, const char *pszTableName, 
+    int                 OpenTable( const char *pszSchemaName, const char *pszTableName,
                                    const char *pszGeomCol,int nCoordDimension,
-                                   int nSRID, const char *pszSRText, 
+                                   int nSRID, const char *pszSRText,
                                    OGRwkbGeometryType eType, int bUpdate );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount();
-    OGRLayer            *GetLayer( int );
-    OGRLayer            *GetLayerByName( const char* pszLayerName );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override;
+    OGRLayer            *GetLayer( int ) override;
+    OGRLayer            *GetLayerByName( const char* pszLayerName ) override;
 
     int                 GetGeometryFormat() { return nGeometryFormat; }
     int                 UseGeometryColumns() { return bUseGeometryColumns; }
 
-    virtual OGRErr       DeleteLayer( int iLayer );
+    virtual OGRErr       DeleteLayer( int iLayer ) override;
     virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+                                      char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     char                *LaunderName( const char *pszSrcName );
     OGRErr              InitializeMetadataTables();
@@ -493,9 +492,9 @@ class OGRMSSQLSpatialDataSource : public OGRDataSource
     OGRSpatialReference* FetchSRS( int nId );
     int                 FetchSRSId( OGRSpatialReference * poSRS );
 
-    OGRErr              StartTransaction(CPL_UNUSED int bForce);
-    OGRErr              CommitTransaction();
-    OGRErr              RollbackTransaction();
+    OGRErr              StartTransaction(CPL_UNUSED int bForce) override;
+    OGRErr              CommitTransaction() override;
+    OGRErr              RollbackTransaction() override;
 
     // Internal use
     CPLODBCSession     *GetSession() { return &oSession; }
@@ -509,15 +508,15 @@ class OGRMSSQLSpatialDataSource : public OGRDataSource
 class OGRMSSQLSpatialDriver : public OGRSFDriver
 {
   public:
-    ~OGRMSSQLSpatialDriver();
-                
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
+    virtual ~OGRMSSQLSpatialDriver();
+
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
-                                             char ** = NULL );
-    
-    int                 TestCapability( const char * );
+                                             char ** = NULL ) override;
+
+    int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_MSSQLSPATIAL_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryparser.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryparser.cpp
index 152aa5e..fb411e7 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryparser.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryparser.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmssqlgeometryparser.cpp 33775 2016-03-23 20:25:05Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLGeometryParser class to parse native SqlGeometries.
@@ -30,7 +29,7 @@
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlgeometryparser.cpp 33775 2016-03-23 20:25:05Z tamas $");
+CPL_CVSID("$Id: ogrmssqlgeometryparser.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /*   SqlGeometry serialization format
 
@@ -363,7 +362,6 @@ OGRGeometryCollection* OGRMSSQLGeometryParser::ReadGeometryCollection(int iShape
 /*                         ParseSqlGeometry()                           */
 /************************************************************************/
 
-
 OGRErr OGRMSSQLGeometryParser::ParseSqlGeometry(unsigned char* pszInput,
                                 int nLen, OGRGeometry **poGeom)
 {
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryvalidator.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryvalidator.cpp
index f2e46e5..ca76227 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryvalidator.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometryvalidator.cpp
@@ -1,493 +1,492 @@
-/******************************************************************************
- * $Id: ogrmssqlgeometryvalidator.cpp 27745 2014-09-27 16:38:57Z goatbar $
- *
- * Project:  MSSQL Spatial driver
- * Purpose:  Implements OGRMSSQLGeometryValidator class to create valid SqlGeometries.
- * Author:   Tamas Szekeres, szekerest at gmail.com
- *
- ******************************************************************************
- * Copyright (c) 2010, Tamas Szekeres
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_conv.h"
-#include "ogr_mssqlspatial.h"
-
-CPL_CVSID("$Id: ogrmssqlgeometryvalidator.cpp 27745 2014-09-27 16:38:57Z goatbar $");
-
-/************************************************************************/
-/*                   OGRMSSQLGeometryValidator()                        */
-/************************************************************************/
-
-OGRMSSQLGeometryValidator::OGRMSSQLGeometryValidator(OGRGeometry *poGeom)
-{
-    poOriginalGeometry = poGeom;
-    poValidGeometry = NULL;
-    bIsValid = ValidateGeometry(poGeom);
-}
-
-/************************************************************************/
-/*                      ~OGRMSSQLGeometryValidator()                    */
-/************************************************************************/
-
-OGRMSSQLGeometryValidator::~OGRMSSQLGeometryValidator()
-{
-    if (poValidGeometry)
-        delete poValidGeometry;
-}
-
-/************************************************************************/
-/*                         ValidatePoint()                              */
-/************************************************************************/
-
-int OGRMSSQLGeometryValidator::ValidatePoint(CPL_UNUSED OGRPoint* poGeom)
-{
-    return TRUE;
-}
-
-/************************************************************************/
-/*                     ValidateMultiPoint()                             */
-/************************************************************************/
-
-int OGRMSSQLGeometryValidator::ValidateMultiPoint(CPL_UNUSED OGRMultiPoint* poGeom)
-{
-    return TRUE;
-}
-
-/************************************************************************/
-/*                         ValidateLineString()                         */
-/************************************************************************/
-
-int OGRMSSQLGeometryValidator::ValidateLineString(OGRLineString * poGeom)
-{
-    OGRPoint* poPoint0 = NULL;
-    int i;
-    int bResult = FALSE;
-
-    for (i = 0; i < poGeom->getNumPoints(); i++)
-    {
-        if (poPoint0 == NULL)
-        {
-            poPoint0 = new OGRPoint();
-            poGeom->getPoint(i, poPoint0);
-            continue;
-        }
-
-        if (poPoint0->getX() == poGeom->getX(i) && poPoint0->getY() == poGeom->getY(i))
-            continue;
-
-        bResult = TRUE;
-        break;
-    }
-
-    if (!bResult)
-    {
-        if (poValidGeometry)
-            delete poValidGeometry;
-
-        poValidGeometry = NULL;
-
-        // create a compatible geometry
-        if (poPoint0 != NULL)
-        {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                      "Linestring has no distinct points constructing point geometry instead." );
-            
-            // create a point
-            poValidGeometry = poPoint0;
-            poPoint0 = NULL;
-        }
-        else
-        {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                      "Linestring has no points. Removing the geometry from the output." );
-        }
-    }
-
-    if (poPoint0)
-        delete poPoint0;
-
-    return bResult;
-}
-
-/************************************************************************/
-/*                         ValidateLinearRing()                         */
-/************************************************************************/
-
-int OGRMSSQLGeometryValidator::ValidateLinearRing(OGRLinearRing * poGeom)
-{
-    OGRPoint* poPoint0 = NULL;
-    OGRPoint* poPoint1 = NULL;
-    int i;
-    int bResult = FALSE;
-
-    poGeom->closeRings();
-
-    for (i = 0; i < poGeom->getNumPoints(); i++)
-    {
-        if (poPoint0 == NULL)
-        {
-            poPoint0 = new OGRPoint();
-            poGeom->getPoint(i, poPoint0);
-            continue;
-        }
-
-        if (poPoint0->getX() == poGeom->getX(i) && poPoint0->getY() == poGeom->getY(i))
-            continue;
-
-        if (poPoint1 == NULL)
-        {
-            poPoint1 = new OGRPoint();
-            poGeom->getPoint(i, poPoint1);
-            continue;
-        }
-
-        if (poPoint1->getX() == poGeom->getX(i) && poPoint1->getY() == poGeom->getY(i))
-            continue;
-
-        bResult = TRUE;
-        break;
-    }
-
-    if (!bResult)
-    {
-        if (poValidGeometry)
-            delete poValidGeometry;
-        
-        poValidGeometry = NULL;
-
-        // create a compatible geometry
-        if (poPoint1 != NULL)
-        {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                      "Linear ring has only 2 distinct points constructing linestring geometry instead." );
-            
-            // create a linestring
-            poValidGeometry = new OGRLineString();
-            ((OGRLineString*)poValidGeometry)->setNumPoints( 2 );
-            ((OGRLineString*)poValidGeometry)->addPoint(poPoint0);
-            ((OGRLineString*)poValidGeometry)->addPoint(poPoint1);
-        }
-        else if (poPoint0 != NULL)
-        {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                      "Linear ring has no distinct points constructing point geometry instead." );
-            
-            // create a point
-            poValidGeometry = poPoint0;
-            poPoint0 = NULL;
-        }
-        else
-        {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                      "Linear ring has no points. Removing the geometry from the output." );
-        }
-    }
-
-    if (poPoint0)
-        delete poPoint0;
-
-    if (poPoint1)
-        delete poPoint1;
-
-    return bResult;
-}
-
-/************************************************************************/
-/*                     ValidateMultiLineString()                        */
-/************************************************************************/
-
-int OGRMSSQLGeometryValidator::ValidateMultiLineString(OGRMultiLineString * poGeom)
-{
-    int i, j;
-    OGRGeometry* poLineString;
-    OGRGeometryCollection* poGeometries = NULL;
-
-    for (i = 0; i < poGeom->getNumGeometries(); i++)
-    {
-        poLineString = poGeom->getGeometryRef(i);
-        if (poLineString->getGeometryType() != wkbLineString && poLineString->getGeometryType() != wkbLineString25D)
-        {
-            // non linestring geometry
-            if (!poGeometries)
-            {
-                poGeometries = new OGRGeometryCollection();
-                for (j = 0; j < i; j++)
-                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
-            }
-            if (ValidateGeometry(poLineString))
-                poGeometries->addGeometry(poLineString);
-            else
-                poGeometries->addGeometry(poValidGeometry);
-
-            continue;
-        }
-
-        if (!ValidateLineString((OGRLineString*)poLineString))
-        {
-            // non valid linestring
-            if (!poGeometries)
-            {
-                poGeometries = new OGRGeometryCollection();
-                for (j = 0; j < i; j++)
-                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
-            }
-            
-            poGeometries->addGeometry(poValidGeometry);
-            continue;
-        }
-
-        if (poGeometries)
-            poGeometries->addGeometry(poLineString);
-    }
-
-    if (poGeometries)
-    {
-         if (poValidGeometry)
-            delete poValidGeometry;
-
-        poValidGeometry = poGeometries;
-    }
-
-    return (poValidGeometry == NULL);
-}
-
-/************************************************************************/
-/*                         ValidatePolygon()                            */
-/************************************************************************/
-
-int OGRMSSQLGeometryValidator::ValidatePolygon(OGRPolygon* poGeom)
-{
-    int i,j;
-    OGRLinearRing* poRing = poGeom->getExteriorRing();
-    OGRGeometry* poInteriorRing;
-
-    if (poRing == NULL)
-        return FALSE;
-
-    OGRGeometryCollection* poGeometries = NULL;
-
-    if (!ValidateLinearRing(poRing))
-    {
-        if (poGeom->getNumInteriorRings() > 0)
-        {
-            poGeometries = new OGRGeometryCollection();
-            poGeometries->addGeometryDirectly(poValidGeometry);
-        }
-    }
-
-    for (i = 0; i < poGeom->getNumInteriorRings(); i++)
-    {
-        poInteriorRing = poGeom->getInteriorRing(i);
-        if (!ValidateLinearRing((OGRLinearRing*)poInteriorRing))
-        {
-            if (!poGeometries)
-            {
-                poGeometries = new OGRGeometryCollection();
-                poGeometries->addGeometry(poRing);
-                for (j = 0; j < i; j++)
-                    poGeometries->addGeometry(poGeom->getInteriorRing(j));
-            }
-
-            poGeometries->addGeometry(poValidGeometry);
-            continue;
-        }
-
-        if (poGeometries)
-            poGeometries->addGeometry(poInteriorRing);
-    }
-
-    if (poGeometries)
-    {
-        if (poValidGeometry)
-            delete poValidGeometry;
-
-        poValidGeometry = poGeometries;
-    }
-
-    return (poValidGeometry == NULL);
-}
-
-/************************************************************************/
-/*                         ValidateMultiPolygon()                       */
-/************************************************************************/
-
-int OGRMSSQLGeometryValidator::ValidateMultiPolygon(OGRMultiPolygon* poGeom)
-{
-    int i, j;
-    OGRGeometry* poPolygon;
-    OGRGeometryCollection* poGeometries = NULL;
-
-    for (i = 0; i < poGeom->getNumGeometries(); i++)
-    {
-        poPolygon = poGeom->getGeometryRef(i);
-        if (poPolygon->getGeometryType() != wkbPolygon && poPolygon->getGeometryType() != wkbPolygon25D)
-        {
-            // non polygon geometry
-            if (!poGeometries)
-            {
-                poGeometries = new OGRGeometryCollection();
-                for (j = 0; j < i; j++)
-                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
-            }
-            if (ValidateGeometry(poPolygon))
-                poGeometries->addGeometry(poPolygon);
-            else
-                poGeometries->addGeometry(poValidGeometry);
-
-            continue;
-        }
-
-        if (!ValidatePolygon((OGRPolygon*)poPolygon))
-        {
-            // non valid polygon
-            if (!poGeometries)
-            {
-                poGeometries = new OGRGeometryCollection();
-                for (j = 0; j < i; j++)
-                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
-            }
-            
-            poGeometries->addGeometry(poValidGeometry);
-            continue;
-        }
-
-        if (poGeometries)
-            poGeometries->addGeometry(poPolygon);
-    }
-
-    if (poGeometries)
-    {
-        if (poValidGeometry)
-            delete poValidGeometry;
-
-        poValidGeometry = poGeometries;
-    }
-
-    return poValidGeometry == NULL;
-}
-
-/************************************************************************/
-/*                     ValidateGeometryCollection()                     */
-/************************************************************************/
-
-int OGRMSSQLGeometryValidator::ValidateGeometryCollection(OGRGeometryCollection* poGeom)
-{
-    int i, j;
-    OGRGeometry* poGeometry;
-    OGRGeometryCollection* poGeometries = NULL;
-
-    for (i = 0; i < poGeom->getNumGeometries(); i++)
-    {
-        poGeometry = poGeom->getGeometryRef(i);
-        
-        if (!ValidateGeometry(poGeometry))
-        {
-            // non valid geometry
-            if (!poGeometries)
-            {
-                poGeometries = new OGRGeometryCollection();
-                for (j = 0; j < i; j++)
-                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
-            }
-            
-            if (poValidGeometry)
-                poGeometries->addGeometry(poValidGeometry);
-            continue;
-        }
-
-        if (poGeometries)
-            poGeometries->addGeometry(poGeometry);
-    }
-
-    if (poGeometries)
-    {
-        if (poValidGeometry)
-            delete poValidGeometry;
-
-        poValidGeometry = poGeometries;
-    }
-
-    return (poValidGeometry == NULL);
-}
-
-/************************************************************************/
-/*                         ValidateGeometry()                           */
-/************************************************************************/
-
-int OGRMSSQLGeometryValidator::ValidateGeometry(OGRGeometry* poGeom)
-{
-    if (!poGeom)
-        return FALSE;
-    
-    switch (poGeom->getGeometryType())
-    {
-    case wkbPoint:
-    case wkbPoint25D:
-        return ValidatePoint((OGRPoint*)poGeom);
-    case wkbLineString:
-    case wkbLineString25D:
-        return ValidateLineString((OGRLineString*)poGeom);
-    case wkbPolygon:
-    case wkbPolygon25D:
-        return ValidatePolygon((OGRPolygon*)poGeom);
-    case wkbMultiPoint:
-    case wkbMultiPoint25D:
-        return ValidateMultiPoint((OGRMultiPoint*)poGeom);
-    case wkbMultiLineString:
-    case wkbMultiLineString25D:
-        return ValidateMultiLineString((OGRMultiLineString*)poGeom);
-    case wkbMultiPolygon:
-    case wkbMultiPolygon25D:
-        return ValidateMultiPolygon((OGRMultiPolygon*)poGeom);
-    case wkbGeometryCollection:
-    case wkbGeometryCollection25D:
-        return ValidateGeometryCollection((OGRGeometryCollection*)poGeom);
-    case wkbLinearRing:
-        return ValidateLinearRing((OGRLinearRing*)poGeom);
-    default:
-        return FALSE;
-    }
-}
-
-/************************************************************************/
-/*                      GetValidGeometryRef()                           */
-/************************************************************************/
-OGRGeometry* OGRMSSQLGeometryValidator::GetValidGeometryRef()
-{
-    if (bIsValid || poOriginalGeometry == NULL)
-        return poOriginalGeometry;
-
-    if (poValidGeometry)
-    {
-        CPLError( CE_Warning, CPLE_NotSupported,
-                      "Invalid geometry has been converted from %s to %s.",
-                      poOriginalGeometry->getGeometryName(),
-                      poValidGeometry->getGeometryName() );
-    }
-    else
-    {
-        CPLError( CE_Warning, CPLE_NotSupported,
-                      "Invalid geometry has been converted from %s to null.",
-                      poOriginalGeometry->getGeometryName());
-    }
-
-    return poValidGeometry;
-}
+/******************************************************************************
+ *
+ * Project:  MSSQL Spatial driver
+ * Purpose:  Implements OGRMSSQLGeometryValidator class to create valid SqlGeometries.
+ * Author:   Tamas Szekeres, szekerest at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogr_mssqlspatial.h"
+
+CPL_CVSID("$Id: ogrmssqlgeometryvalidator.cpp 35675 2016-10-10 04:57:58Z goatbar $");
+
+/************************************************************************/
+/*                   OGRMSSQLGeometryValidator()                        */
+/************************************************************************/
+
+OGRMSSQLGeometryValidator::OGRMSSQLGeometryValidator(OGRGeometry *poGeom)
+{
+    poOriginalGeometry = poGeom;
+    poValidGeometry = NULL;
+    bIsValid = ValidateGeometry(poGeom);
+}
+
+/************************************************************************/
+/*                      ~OGRMSSQLGeometryValidator()                    */
+/************************************************************************/
+
+OGRMSSQLGeometryValidator::~OGRMSSQLGeometryValidator()
+{
+    if (poValidGeometry)
+        delete poValidGeometry;
+}
+
+/************************************************************************/
+/*                         ValidatePoint()                              */
+/************************************************************************/
+
+int OGRMSSQLGeometryValidator::ValidatePoint(CPL_UNUSED OGRPoint* poGeom)
+{
+    return TRUE;
+}
+
+/************************************************************************/
+/*                     ValidateMultiPoint()                             */
+/************************************************************************/
+
+int OGRMSSQLGeometryValidator::ValidateMultiPoint(CPL_UNUSED OGRMultiPoint* poGeom)
+{
+    return TRUE;
+}
+
+/************************************************************************/
+/*                         ValidateLineString()                         */
+/************************************************************************/
+
+int OGRMSSQLGeometryValidator::ValidateLineString(OGRLineString * poGeom)
+{
+    OGRPoint* poPoint0 = NULL;
+    int i;
+    int bResult = FALSE;
+
+    for (i = 0; i < poGeom->getNumPoints(); i++)
+    {
+        if (poPoint0 == NULL)
+        {
+            poPoint0 = new OGRPoint();
+            poGeom->getPoint(i, poPoint0);
+            continue;
+        }
+
+        if (poPoint0->getX() == poGeom->getX(i) && poPoint0->getY() == poGeom->getY(i))
+            continue;
+
+        bResult = TRUE;
+        break;
+    }
+
+    if (!bResult)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = NULL;
+
+        // create a compatible geometry
+        if (poPoint0 != NULL)
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linestring has no distinct points constructing point geometry instead." );
+
+            // create a point
+            poValidGeometry = poPoint0;
+            poPoint0 = NULL;
+        }
+        else
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linestring has no points. Removing the geometry from the output." );
+        }
+    }
+
+    if (poPoint0)
+        delete poPoint0;
+
+    return bResult;
+}
+
+/************************************************************************/
+/*                         ValidateLinearRing()                         */
+/************************************************************************/
+
+int OGRMSSQLGeometryValidator::ValidateLinearRing(OGRLinearRing * poGeom)
+{
+    OGRPoint* poPoint0 = NULL;
+    OGRPoint* poPoint1 = NULL;
+    int i;
+    int bResult = FALSE;
+
+    poGeom->closeRings();
+
+    for (i = 0; i < poGeom->getNumPoints(); i++)
+    {
+        if (poPoint0 == NULL)
+        {
+            poPoint0 = new OGRPoint();
+            poGeom->getPoint(i, poPoint0);
+            continue;
+        }
+
+        if (poPoint0->getX() == poGeom->getX(i) && poPoint0->getY() == poGeom->getY(i))
+            continue;
+
+        if (poPoint1 == NULL)
+        {
+            poPoint1 = new OGRPoint();
+            poGeom->getPoint(i, poPoint1);
+            continue;
+        }
+
+        if (poPoint1->getX() == poGeom->getX(i) && poPoint1->getY() == poGeom->getY(i))
+            continue;
+
+        bResult = TRUE;
+        break;
+    }
+
+    if (!bResult)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = NULL;
+
+        // create a compatible geometry
+        if (poPoint1 != NULL)
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linear ring has only 2 distinct points constructing linestring geometry instead." );
+
+            // create a linestring
+            poValidGeometry = new OGRLineString();
+            ((OGRLineString*)poValidGeometry)->setNumPoints( 2 );
+            ((OGRLineString*)poValidGeometry)->addPoint(poPoint0);
+            ((OGRLineString*)poValidGeometry)->addPoint(poPoint1);
+        }
+        else if (poPoint0 != NULL)
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linear ring has no distinct points constructing point geometry instead." );
+
+            // create a point
+            poValidGeometry = poPoint0;
+            poPoint0 = NULL;
+        }
+        else
+        {
+            CPLError( CE_Warning, CPLE_NotSupported,
+                      "Linear ring has no points. Removing the geometry from the output." );
+        }
+    }
+
+    if (poPoint0)
+        delete poPoint0;
+
+    if (poPoint1)
+        delete poPoint1;
+
+    return bResult;
+}
+
+/************************************************************************/
+/*                     ValidateMultiLineString()                        */
+/************************************************************************/
+
+int OGRMSSQLGeometryValidator::ValidateMultiLineString(OGRMultiLineString * poGeom)
+{
+    int i, j;
+    OGRGeometry* poLineString;
+    OGRGeometryCollection* poGeometries = NULL;
+
+    for (i = 0; i < poGeom->getNumGeometries(); i++)
+    {
+        poLineString = poGeom->getGeometryRef(i);
+        if (poLineString->getGeometryType() != wkbLineString && poLineString->getGeometryType() != wkbLineString25D)
+        {
+            // non linestring geometry
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+            if (ValidateGeometry(poLineString))
+                poGeometries->addGeometry(poLineString);
+            else
+                poGeometries->addGeometry(poValidGeometry);
+
+            continue;
+        }
+
+        if (!ValidateLineString((OGRLineString*)poLineString))
+        {
+            // non valid linestring
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+
+            poGeometries->addGeometry(poValidGeometry);
+            continue;
+        }
+
+        if (poGeometries)
+            poGeometries->addGeometry(poLineString);
+    }
+
+    if (poGeometries)
+    {
+         if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = poGeometries;
+    }
+
+    return poValidGeometry == NULL;
+}
+
+/************************************************************************/
+/*                         ValidatePolygon()                            */
+/************************************************************************/
+
+int OGRMSSQLGeometryValidator::ValidatePolygon(OGRPolygon* poGeom)
+{
+    int i,j;
+    OGRLinearRing* poRing = poGeom->getExteriorRing();
+    OGRGeometry* poInteriorRing;
+
+    if (poRing == NULL)
+        return FALSE;
+
+    OGRGeometryCollection* poGeometries = NULL;
+
+    if (!ValidateLinearRing(poRing))
+    {
+        if (poGeom->getNumInteriorRings() > 0)
+        {
+            poGeometries = new OGRGeometryCollection();
+            poGeometries->addGeometryDirectly(poValidGeometry);
+        }
+    }
+
+    for (i = 0; i < poGeom->getNumInteriorRings(); i++)
+    {
+        poInteriorRing = poGeom->getInteriorRing(i);
+        if (!ValidateLinearRing((OGRLinearRing*)poInteriorRing))
+        {
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                poGeometries->addGeometry(poRing);
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getInteriorRing(j));
+            }
+
+            poGeometries->addGeometry(poValidGeometry);
+            continue;
+        }
+
+        if (poGeometries)
+            poGeometries->addGeometry(poInteriorRing);
+    }
+
+    if (poGeometries)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = poGeometries;
+    }
+
+    return poValidGeometry == NULL;
+}
+
+/************************************************************************/
+/*                         ValidateMultiPolygon()                       */
+/************************************************************************/
+
+int OGRMSSQLGeometryValidator::ValidateMultiPolygon(OGRMultiPolygon* poGeom)
+{
+    int i, j;
+    OGRGeometry* poPolygon;
+    OGRGeometryCollection* poGeometries = NULL;
+
+    for (i = 0; i < poGeom->getNumGeometries(); i++)
+    {
+        poPolygon = poGeom->getGeometryRef(i);
+        if (poPolygon->getGeometryType() != wkbPolygon && poPolygon->getGeometryType() != wkbPolygon25D)
+        {
+            // non polygon geometry
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+            if (ValidateGeometry(poPolygon))
+                poGeometries->addGeometry(poPolygon);
+            else
+                poGeometries->addGeometry(poValidGeometry);
+
+            continue;
+        }
+
+        if (!ValidatePolygon((OGRPolygon*)poPolygon))
+        {
+            // non valid polygon
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+
+            poGeometries->addGeometry(poValidGeometry);
+            continue;
+        }
+
+        if (poGeometries)
+            poGeometries->addGeometry(poPolygon);
+    }
+
+    if (poGeometries)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = poGeometries;
+    }
+
+    return poValidGeometry == NULL;
+}
+
+/************************************************************************/
+/*                     ValidateGeometryCollection()                     */
+/************************************************************************/
+
+int OGRMSSQLGeometryValidator::ValidateGeometryCollection(OGRGeometryCollection* poGeom)
+{
+    int i, j;
+    OGRGeometry* poGeometry;
+    OGRGeometryCollection* poGeometries = NULL;
+
+    for (i = 0; i < poGeom->getNumGeometries(); i++)
+    {
+        poGeometry = poGeom->getGeometryRef(i);
+
+        if (!ValidateGeometry(poGeometry))
+        {
+            // non valid geometry
+            if (!poGeometries)
+            {
+                poGeometries = new OGRGeometryCollection();
+                for (j = 0; j < i; j++)
+                    poGeometries->addGeometry(poGeom->getGeometryRef(j));
+            }
+
+            if (poValidGeometry)
+                poGeometries->addGeometry(poValidGeometry);
+            continue;
+        }
+
+        if (poGeometries)
+            poGeometries->addGeometry(poGeometry);
+    }
+
+    if (poGeometries)
+    {
+        if (poValidGeometry)
+            delete poValidGeometry;
+
+        poValidGeometry = poGeometries;
+    }
+
+    return poValidGeometry == NULL;
+}
+
+/************************************************************************/
+/*                         ValidateGeometry()                           */
+/************************************************************************/
+
+int OGRMSSQLGeometryValidator::ValidateGeometry(OGRGeometry* poGeom)
+{
+    if (!poGeom)
+        return FALSE;
+
+    switch (poGeom->getGeometryType())
+    {
+    case wkbPoint:
+    case wkbPoint25D:
+        return ValidatePoint((OGRPoint*)poGeom);
+    case wkbLineString:
+    case wkbLineString25D:
+        return ValidateLineString((OGRLineString*)poGeom);
+    case wkbPolygon:
+    case wkbPolygon25D:
+        return ValidatePolygon((OGRPolygon*)poGeom);
+    case wkbMultiPoint:
+    case wkbMultiPoint25D:
+        return ValidateMultiPoint((OGRMultiPoint*)poGeom);
+    case wkbMultiLineString:
+    case wkbMultiLineString25D:
+        return ValidateMultiLineString((OGRMultiLineString*)poGeom);
+    case wkbMultiPolygon:
+    case wkbMultiPolygon25D:
+        return ValidateMultiPolygon((OGRMultiPolygon*)poGeom);
+    case wkbGeometryCollection:
+    case wkbGeometryCollection25D:
+        return ValidateGeometryCollection((OGRGeometryCollection*)poGeom);
+    case wkbLinearRing:
+        return ValidateLinearRing((OGRLinearRing*)poGeom);
+    default:
+        return FALSE;
+    }
+}
+
+/************************************************************************/
+/*                      GetValidGeometryRef()                           */
+/************************************************************************/
+OGRGeometry* OGRMSSQLGeometryValidator::GetValidGeometryRef()
+{
+    if (bIsValid || poOriginalGeometry == NULL)
+        return poOriginalGeometry;
+
+    if (poValidGeometry)
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                      "Invalid geometry has been converted from %s to %s.",
+                      poOriginalGeometry->getGeometryName(),
+                      poValidGeometry->getGeometryName() );
+    }
+    else
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                      "Invalid geometry has been converted from %s to null.",
+                      poOriginalGeometry->getGeometryName());
+    }
+
+    return poValidGeometry;
+}
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometrywriter.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometrywriter.cpp
index 2c79cf2..3f3790a 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometrywriter.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlgeometrywriter.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLGeometryWriter class to write native SqlGeometries.
@@ -30,7 +29,7 @@
 #include "cpl_conv.h"
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: ogrmssqlgeometrywriter.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /*   SqlGeometry serialization format
 
@@ -236,7 +235,7 @@ void OGRMSSQLGeometryWriter::WriteLineString(OGRLineString* poGeom)
     else
     {
         for (i = 0; i < poGeom->getNumPoints(); i++)
-            WritePoint(poGeom->getX(i), poGeom->getY(i));          
+            WritePoint(poGeom->getX(i), poGeom->getY(i));
     }
     ++iFigure;
 }
@@ -288,7 +287,7 @@ void OGRMSSQLGeometryWriter::WritePolygon(OGRPolygon* poGeom)
                 WritePoint(poRing->getX(i), poRing->getY(i));
             ++iFigure;
         }
-    }  
+    }
 }
 
 /************************************************************************/
@@ -313,7 +312,7 @@ void OGRMSSQLGeometryWriter::WriteGeometry(OGRGeometry* poGeom, int iParent)
     WriteInt32(FigureOffset(iShape), iFigure);
 
     iParent = iShape;
-    
+
     switch (poGeom->getGeometryType())
     {
     case wkbPoint:
@@ -324,7 +323,7 @@ void OGRMSSQLGeometryWriter::WriteGeometry(OGRGeometry* poGeom, int iParent)
         WritePoint((OGRPoint*)poGeom);
         ++iFigure;
         break;
-        
+
     case wkbLineString:
     case wkbLineString25D:
         WriteByte(ShapeType(iShape++), ST_LINESTRING);
@@ -380,7 +379,7 @@ void OGRMSSQLGeometryWriter::TrackGeometry(OGRGeometry* poGeom)
         ++nNumFigures;
         ++nNumPoints;
         break;
-        
+
     case wkbLineString:
     case wkbLineString25D:
         ++nNumFigures;
@@ -430,7 +429,7 @@ OGRErr OGRMSSQLGeometryWriter::WriteSqlGeometry(unsigned char* pszBuffer, int nB
 
     if (nBufLen < nLen)
         return OGRERR_FAILURE;
-    
+
     OGRwkbGeometryType geomType = poGeom2->getGeometryType();
 
     if (nNumPoints == 1 && (geomType == wkbPoint || geomType == wkbPoint25D))
@@ -504,4 +503,3 @@ OGRErr OGRMSSQLGeometryWriter::WriteSqlGeometry(unsigned char* pszBuffer, int nB
     }
     return OGRERR_NONE;
 }
-
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
index 176a808..468e742 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialdatasource.cpp 33834 2016-03-31 18:36:27Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialDataSource class..
@@ -30,7 +29,7 @@
 
 #include "ogr_mssqlspatial.h"
 
-CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 33834 2016-03-31 18:36:27Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 36387 2016-11-21 12:56:56Z rouault $");
 
 /************************************************************************/
 /*                          OGRMSSQLSpatialDataSource()                 */
@@ -60,7 +59,7 @@ OGRMSSQLSpatialDataSource::OGRMSSQLSpatialDataSource() :
     else
         nBCPSize = 1000;
 #ifdef MSSQL_BCP_SUPPORTED
-    bUseCopy = CSLTestBoolean(CPLGetConfigOption("MSSQLSPATIAL_USE_BCP", "TRUE"));
+    bUseCopy = CPLTestBool(CPLGetConfigOption("MSSQLSPATIAL_USE_BCP", "TRUE"));
 #else
     bUseCopy = FALSE;
 #endif
@@ -104,6 +103,8 @@ int OGRMSSQLSpatialDataSource::TestCapability( const char * pszCap )
 #endif
     if( EQUAL(pszCap,ODsCCreateLayer) || EQUAL(pszCap,ODsCDeleteLayer) )
         return TRUE;
+    if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -264,7 +265,7 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
       strncpy(pszSchemaName, pszLayerName, length);
       pszSchemaName[length] = '\0';
 
-      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+      if( CPLFetchBool(papszOptions, "LAUNDER", true) )
           pszTableName = LaunderName( pszDotPos + 1 ); //skip "."
       else
           pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "."
@@ -272,7 +273,7 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
     else
     {
       pszSchemaName = NULL;
-      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+      if( CPLFetchBool(papszOptions, "LAUNDER", TRUE) )
           pszTableName = LaunderName( pszLayerName ); //skip "."
       else
           pszTableName = CPLStrdup( pszLayerName ); //skip "."
@@ -350,7 +351,8 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
         if (!pszGeomColumn)
             pszGeomColumn = "ogr_geometry";
     }
-    int bGeomNullable = CSLFetchBoolean(papszOptions, "GEOMETRY_NULLABLE", TRUE);
+    const bool bGeomNullable =
+        CPLFetchBool(papszOptions, "GEOMETRY_NULLABLE", true);
 
 /* -------------------------------------------------------------------- */
 /*      Initialize the metadata tables                                  */
@@ -402,13 +404,13 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
 
      /* determine the FID column name */
     const char* pszFIDColumnNameIn = CSLFetchNameValueDef(papszOptions, "FID", "ogr_fid");
-    if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+    if( CPLFetchBool(papszOptions, "LAUNDER", TRUE) )
         pszFIDColumnName = LaunderName( pszFIDColumnNameIn );
     else
         pszFIDColumnName = CPLStrdup( pszFIDColumnNameIn );
 
-    int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE);
- 	const char* pszFIDType = bFID64 ? "bigint": "int";
+    const bool bFID64 = CPLFetchBool(papszOptions, "FID64", FALSE);
+    const char* pszFIDType = bFID64 ? "bigint": "int";
 
     if( eType == wkbNone )
     {
@@ -421,7 +423,7 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
         oStmt.Appendf("CREATE TABLE [%s].[%s] ([%s] [%s] IDENTITY(1,1) NOT NULL, "
             "[%s] [%s] %s, CONSTRAINT [PK_%s] PRIMARY KEY CLUSTERED ([%s] ASC))",
             pszSchemaName, pszTableName, pszFIDColumnName, pszFIDType, pszGeomColumn, pszGeomType,
-            bGeomNullable? "NULL":"NOT NULL", pszTableName, pszFIDColumnName);
+            bGeomNullable ? "NULL":"NOT NULL", pszTableName, pszFIDColumnName);
     }
 
     CPLFree( pszFIDColumnName );
@@ -456,8 +458,8 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
     else
         poLayer->SetLayerStatus(MSSQLLAYERSTATUS_CREATED);
 
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
-    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
+    poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", true) );
+    poLayer->SetPrecisionFlag( CPLFetchBool(papszOptions, "PRECISION", true));
 
     if( bUseCopy )
         poLayer->SetUseCopy(nBCPSize);
@@ -508,7 +510,6 @@ OGRLayer * OGRMSSQLSpatialDataSource::ICreateLayer( const char * pszLayerName,
 
     papoLayers[nLayers++] = poLayer;
 
-
     return poLayer;
 }
 
@@ -545,7 +546,6 @@ int OGRMSSQLSpatialDataSource::OpenTable( const char *pszSchemaName, const char
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                       GetLayerCount()                                */
 /************************************************************************/
@@ -582,7 +582,6 @@ int OGRMSSQLSpatialDataSource::ParseValue(char** pszValue, char* pszSource, cons
     return FALSE;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -767,14 +766,14 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
             SQLSMALLINT attr_ret;
             SQLCHAR attr[256];
             SQLCHAR driver[256];
-            while(SQL_SUCCEEDED(SQLDrivers(hEnv, direction, 
-                driver, sizeof(driver), &driver_ret, attr, sizeof(attr), &attr_ret))) 
+            while(SQL_SUCCEEDED(SQLDrivers(hEnv, direction,
+                driver, sizeof(driver), &driver_ret, attr, sizeof(attr), &attr_ret)))
             {
-	            direction = SQL_FETCH_NEXT;
+                direction = SQL_FETCH_NEXT;
                 osDriverList += CPLSPrintf("%s\n", driver);
-	        }
+            }
 
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                 "Unable to initialize connection to the server for %s,\n"
                 "%s\n"
                 "Try specifying the driver in the connection string from the list of available drivers:\n"
@@ -782,7 +781,7 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
         }
         else
         {
-            CPLError( CE_Failure, CPLE_AppDefined, 
+            CPLError( CE_Failure, CPLE_AppDefined,
                 "Unable to initialize connection to the server for %s,\n"
                 "%s\n", pszNewName, oSession.GetLastError() );
         }
@@ -846,25 +845,25 @@ int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     }
 
     /* if requesting all user database table then this takes priority */
- 	if (papszTableNames == NULL && bListAllTables)
- 	{
- 	    CPLODBCStatement oStmt( &oSession );
-
- 	    oStmt.Append( "select sys.schemas.name, sys.schemas.name + '.' + sys.objects.name, sys.columns.name from sys.columns join sys.types on sys.columns.system_type_id = sys.types.system_type_id and sys.columns.user_type_id = sys.types.user_type_id join sys.objects on sys.objects.object_id = sys.columns.object_id join sys.schemas on sys.objects.schema_id = sys.schemas.schema_id where (sys.types.name = 'geometry' or sys.types.name = 'geography') and (sys.objects.type = 'U' or sys.objects. [...]
-
- 	    if( oStmt.ExecuteSQL() )
- 	    {
- 	        while( oStmt.Fetch() )
- 	        {
- 	            papszSchemaNames =
- 	                    CSLAddString( papszSchemaNames, oStmt.GetColData(0) );
- 	            papszTableNames =
- 	                    CSLAddString( papszTableNames, oStmt.GetColData(1) );
- 	            papszGeomColumnNames =
- 	                    CSLAddString( papszGeomColumnNames, oStmt.GetColData(2) );
- 	        }
- 	    }
- 	}
+    if (papszTableNames == NULL && bListAllTables)
+    {
+        CPLODBCStatement oStmt( &oSession );
+
+        oStmt.Append( "select sys.schemas.name, sys.schemas.name + '.' + sys.objects.name, sys.columns.name from sys.columns join sys.types on sys.columns.system_type_id = sys.types.system_type_id and sys.columns.user_type_id = sys.types.user_type_id join sys.objects on sys.objects.object_id = sys.columns.object_id join sys.schemas on sys.objects.schema_id = sys.schemas.schema_id where (sys.types.name = 'geometry' or sys.types.name = 'geography') and (sys.objects.type = 'U' or sys.object [...]
+
+        if( oStmt.ExecuteSQL() )
+        {
+            while( oStmt.Fetch() )
+            {
+                papszSchemaNames =
+                    CSLAddString( papszSchemaNames, oStmt.GetColData(0) );
+                papszTableNames =
+                    CSLAddString( papszTableNames, oStmt.GetColData(1) );
+                papszGeomColumnNames =
+                    CSLAddString( papszGeomColumnNames, oStmt.GetColData(2) );
+            }
+        }
+    }
 
     /* Determine the available tables if not specified. */
     if (papszTableNames == NULL && bUseGeometryColumns)
@@ -1164,7 +1163,6 @@ OGRErr OGRMSSQLSpatialDataSource::InitializeMetadataTables()
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                              FetchSRS()                              */
 /*                                                                      */
@@ -1262,6 +1260,7 @@ int OGRMSSQLSpatialDataSource::FetchSRSId( OGRSpatialReference * poSRS)
         return 0;
 
     OGRSpatialReference oSRS(*poSRS);
+    // cppcheck-suppress uselessAssignmentPtrArg
     poSRS = NULL;
 
     pszAuthorityName = oSRS.GetAuthorityName(NULL);
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp
index 2682d1e..195c85c 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdriver.cpp
@@ -1,167 +1,165 @@
-/******************************************************************************
- * $Id: ogrmssqlspatialdriver.cpp 35970 2016-10-27 11:27:30Z jef $
- *
- * Project:  MSSQL Spatial driver
- * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
- * Author:   Tamas Szekeres, szekerest at gmail.com
- *
- ******************************************************************************
- * Copyright (c) 2010, Tamas Szekeres
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_mssqlspatial.h"
-#include "cpl_conv.h"
-
-CPL_CVSID("$Id: ogrmssqlspatialdriver.cpp 35970 2016-10-27 11:27:30Z jef $");
-
-/************************************************************************/
-/*                           ~OGRMSSQLSpatialDriver()                   */
-/************************************************************************/
-
-OGRMSSQLSpatialDriver::~OGRMSSQLSpatialDriver()
-
-{
-}
-
-/************************************************************************/
-/*                              GetName()                               */
-/************************************************************************/
-
-const char *OGRMSSQLSpatialDriver::GetName()
-
-{
-    return "MSSQLSpatial";
-}
-
-/************************************************************************/
-/*                                Open()                                */
-/************************************************************************/
-
-OGRDataSource *OGRMSSQLSpatialDriver::Open( const char * pszFilename, int bUpdate )
-
-{
-    OGRMSSQLSpatialDataSource     *poDS;
-
-    if( !STARTS_WITH_CI(pszFilename, "MSSQL:") )
-        return NULL;
-
-    poDS = new OGRMSSQLSpatialDataSource();
-
-    if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
-    {
-        delete poDS;
-        return NULL;
-    }
-    else
-        return poDS;
-}
-
-/************************************************************************/
-/*                          CreateDataSource()                          */
-/************************************************************************/
-
-OGRDataSource *OGRMSSQLSpatialDriver::CreateDataSource( const char * pszName,
-                                                        CPL_UNUSED char **papszOptions )
-{
-    if( !STARTS_WITH_CI(pszName, "MSSQL:") )
-        return NULL;
-
-    OGRMSSQLSpatialDataSource   *poDS = new OGRMSSQLSpatialDataSource();
-    if( !poDS->Open( pszName, TRUE, TRUE ) )
-    {
-        delete poDS;
-        CPLError( CE_Failure, CPLE_AppDefined,
-         "MSSQL Spatial driver doesn't currently support database creation.\n"
-                  "Please create database with the Microsoft SQL Server Client Tools." );
-        return NULL;
-    }
-
-    return poDS;
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRMSSQLSpatialDriver::TestCapability( const char * pszCap )
-
-{
-    if( EQUAL(pszCap,ODrCCreateDataSource) )
-        return TRUE;
-    else
-        return FALSE;
-}
-
-
-/************************************************************************/
-/*                           RegisterOGRMSSQLSpatial()                  */
-/************************************************************************/
-
-void RegisterOGRMSSQLSpatial()
-
-{
-    if (! GDAL_CHECK_VERSION("OGR/MSSQLSpatial driver"))
-        return;
-
-    OGRSFDriver* poDriver = new OGRMSSQLSpatialDriver;
-
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                               "Microsoft SQL Server Spatial Database"
-#ifdef MSSQL_BCP_SUPPORTED
-			       " (BCP)"
-#endif
-	);
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mssqlspatial.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-                               "<CreationOptionList/>");
-
-    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
-"<LayerCreationOptionList>"
-"  <Option name='GEOM_TYPE' type='string-select' description='Format of geometry columns' default='geometry'>"
-"    <Value>geometry</Value>"
-"    <Value>geography</Value>"
-"  </Option>"
-"  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing table with the layer name to be created' default='NO'/>"
-"  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='YES'/>"
-"  <Option name='PRECISION' type='boolean' description='Whether fields created should keep the width and precision' default='YES'/>"
-"  <Option name='DIM' type='integer' description='Set to 2 to force the geometries to be 2D, or 3 to be 2.5D'/>"
-"  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column.' default='ogr_geometry' deprecated_alias='GEOM_NAME'/>"
-"  <Option name='SCHEMA' type='string' description='Name of schema into which to create the new table' default='dbo'/>"
-"  <Option name='SRID' type='int' description='Forced SRID of the layer'/>"
-"  <Option name='SPATIAL_INDEX' type='boolean' description='Whether to create a spatial index' default='YES'/>"
-"  <Option name='UPLOAD_GEOM_FORMAT' type='string-select' description='Geometry format when creating or modifying features' default='wkb'>"
-"    <Value>wkb</Value>"
-"    <Value>wkt</Value>"
-"  </Option>"
-"  <Option name='FID' type='string' description='Name of the FID column to create' default='ogr_fid'/>"
-"  <Option name='FID64' type='boolean' description='Whether to create the FID column with bigint type to handle 64bit wide ids' default='NO'/>"
-"  <Option name='GEOMETRY_NULLABLE' type='boolean' description='Whether the values of the geometry column can be NULL' default='YES'/>"
-"</LayerCreationOptionList>");
-
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
-                               "Integer Integer64 Real String Date Time "
-                               "DateTime Binary" );
-    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
-    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
-
-    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
-}
+/******************************************************************************
+ *
+ * Project:  MSSQL Spatial driver
+ * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
+ * Author:   Tamas Szekeres, szekerest at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_mssqlspatial.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrmssqlspatialdriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
+
+/************************************************************************/
+/*                           ~OGRMSSQLSpatialDriver()                   */
+/************************************************************************/
+
+OGRMSSQLSpatialDriver::~OGRMSSQLSpatialDriver()
+
+{
+}
+
+/************************************************************************/
+/*                              GetName()                               */
+/************************************************************************/
+
+const char *OGRMSSQLSpatialDriver::GetName()
+
+{
+    return "MSSQLSpatial";
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+OGRDataSource *OGRMSSQLSpatialDriver::Open( const char * pszFilename, int bUpdate )
+
+{
+    OGRMSSQLSpatialDataSource     *poDS;
+
+    if( !STARTS_WITH_CI(pszFilename, "MSSQL:") )
+        return NULL;
+
+    poDS = new OGRMSSQLSpatialDataSource();
+
+    if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
+    {
+        delete poDS;
+        return NULL;
+    }
+    else
+        return poDS;
+}
+
+/************************************************************************/
+/*                          CreateDataSource()                          */
+/************************************************************************/
+
+OGRDataSource *OGRMSSQLSpatialDriver::CreateDataSource( const char * pszName,
+                                                        CPL_UNUSED char **papszOptions )
+{
+    if( !STARTS_WITH_CI(pszName, "MSSQL:") )
+        return NULL;
+
+    OGRMSSQLSpatialDataSource   *poDS = new OGRMSSQLSpatialDataSource();
+    if( !poDS->Open( pszName, TRUE, TRUE ) )
+    {
+        delete poDS;
+        CPLError( CE_Failure, CPLE_AppDefined,
+         "MSSQL Spatial driver doesn't currently support database creation.\n"
+                  "Please create database with the Microsoft SQL Server Client Tools." );
+        return NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRMSSQLSpatialDriver::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,ODrCCreateDataSource) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                           RegisterOGRMSSQLSpatial()                  */
+/************************************************************************/
+
+void RegisterOGRMSSQLSpatial()
+
+{
+    if (! GDAL_CHECK_VERSION("OGR/MSSQLSpatial driver"))
+        return;
+
+    OGRSFDriver* poDriver = new OGRMSSQLSpatialDriver;
+
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               "Microsoft SQL Server Spatial Database"
+#ifdef MSSQL_BCP_SUPPORTED
+                               " (BCP)"
+#endif
+                               );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_mssqlspatial.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+                               "<CreationOptionList/>");
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+"<LayerCreationOptionList>"
+"  <Option name='GEOM_TYPE' type='string-select' description='Format of geometry columns' default='geometry'>"
+"    <Value>geometry</Value>"
+"    <Value>geography</Value>"
+"  </Option>"
+"  <Option name='OVERWRITE' type='boolean' description='Whether to overwrite an existing table with the layer name to be created' default='NO'/>"
+"  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='YES'/>"
+"  <Option name='PRECISION' type='boolean' description='Whether fields created should keep the width and precision' default='YES'/>"
+"  <Option name='DIM' type='integer' description='Set to 2 to force the geometries to be 2D, or 3 to be 2.5D'/>"
+"  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column.' default='ogr_geometry' deprecated_alias='GEOM_NAME'/>"
+"  <Option name='SCHEMA' type='string' description='Name of schema into which to create the new table' default='dbo'/>"
+"  <Option name='SRID' type='int' description='Forced SRID of the layer'/>"
+"  <Option name='SPATIAL_INDEX' type='boolean' description='Whether to create a spatial index' default='YES'/>"
+"  <Option name='UPLOAD_GEOM_FORMAT' type='string-select' description='Geometry format when creating or modifying features' default='wkb'>"
+"    <Value>wkb</Value>"
+"    <Value>wkt</Value>"
+"  </Option>"
+"  <Option name='FID' type='string' description='Name of the FID column to create' default='ogr_fid'/>"
+"  <Option name='FID64' type='boolean' description='Whether to create the FID column with bigint type to handle 64bit wide ids' default='NO'/>"
+"  <Option name='GEOMETRY_NULLABLE' type='boolean' description='Whether the values of the geometry column can be NULL' default='YES'/>"
+"</LayerCreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date Time "
+                               "DateTime Binary" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+
+    OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
+}
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
index 5f1e6e8..f311f7c 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatiallayer.cpp
@@ -1,637 +1,636 @@
-/******************************************************************************
- * $Id: ogrmssqlspatiallayer.cpp 33807 2016-03-29 19:06:42Z tamas $
- *
- * Project:  MSSQL Spatial driver
- * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
- * Author:   Tamas Szekeres, szekerest at gmail.com
- *
- ******************************************************************************
- * Copyright (c) 2010, Tamas Szekeres
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_mssqlspatial.h"
-
-CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 33807 2016-03-29 19:06:42Z tamas $");
-/************************************************************************/
-/*                        OGRMSSQLSpatialLayer()                        */
-/************************************************************************/
-
-OGRMSSQLSpatialLayer::OGRMSSQLSpatialLayer()
-
-{
-    poDS = NULL;
-
-    poFeatureDefn = NULL;
-    nGeomColumnType = -1;
-    pszGeomColumn = NULL;
-    pszFIDColumn = NULL;
-    bIsIdentityFid = FALSE;
-    panFieldOrdinals = NULL;
-
-    poStmt = NULL;
-
-    iNextShapeId = 0;
-
-    poSRS = NULL;
-    nSRSId = -1; // we haven't even queried the database for it yet. 
-    nLayerStatus = MSSQLLAYERSTATUS_ORIGINAL;
-
-    nGeomColumnIndex = -1;
-    nFIDColumnIndex = -1;
-    nRawColumns = 0;
-}
-
-/************************************************************************/
-/*                      ~OGRMSSQLSpatialLayer()                         */
-/************************************************************************/
-
-OGRMSSQLSpatialLayer::~OGRMSSQLSpatialLayer()
-
-{
-    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
-    {
-        CPLDebug( "OGR_MSSQLSpatial", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead, 
-                  poFeatureDefn->GetName() );
-    }
-
-    if( poStmt )
-    {
-        delete poStmt;
-        poStmt = NULL;
-    }
-
-    CPLFree( pszGeomColumn );
-    CPLFree( pszFIDColumn );
-    CPLFree( panFieldOrdinals );
-
-    if( poFeatureDefn )
-    {
-        poFeatureDefn->Release();
-        poFeatureDefn = NULL;
-    }
-
-    if( poSRS )
-        poSRS->Release();
-}
-
-/************************************************************************/
-/*                          BuildFeatureDefn()                          */
-/*                                                                      */
-/*      Build feature definition from a set of column definitions       */
-/*      set on a statement.  Sift out geometry and FID fields.          */
-/************************************************************************/
-
-CPLErr OGRMSSQLSpatialLayer::BuildFeatureDefn( const char *pszLayerName, 
-                                    CPLODBCStatement *poStmtIn )
-
-{
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
-    nRawColumns = poStmtIn->GetColCount();
-
-    poFeatureDefn->Reference();
-
-    CPLFree(panFieldOrdinals);
-    panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
-
-    for( int iCol = 0; iCol < nRawColumns; iCol++ )
-    {
-        if ( pszGeomColumn == NULL )
-        {
-            /* need to identify the geometry column */
-            if ( EQUAL(poStmtIn->GetColTypeName( iCol ), "geometry") )
-            {
-                nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
-                pszGeomColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
-                if (poFeatureDefn->GetGeomFieldCount() == 1)
-                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmtIn->GetColNullable(iCol) );
-                nGeomColumnIndex = iCol;
-                continue;
-            }
-            else if ( EQUAL(poStmtIn->GetColTypeName( iCol ), "geography") )
-            {
-                nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
-                pszGeomColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
-                if (poFeatureDefn->GetGeomFieldCount() == 1)
-                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmtIn->GetColNullable(iCol) );
-                nGeomColumnIndex = iCol;
-                continue;
-            }
-        }
-        else
-        {
-            if( EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )
-            {
-                if (poFeatureDefn->GetGeomFieldCount() == 1)
-                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmtIn->GetColNullable(iCol) );
-                nGeomColumnIndex = iCol;
-                continue;
-            }
-        }
-
-        if( pszFIDColumn != NULL)
-        {
-            if (EQUAL(poStmtIn->GetColName(iCol), pszFIDColumn) )
-            {
-                bool bIntegerFID = false;
-                switch( CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)) )
-                {
-                    case SQL_C_SSHORT:
-                    case SQL_C_USHORT:
-                    case SQL_C_SLONG:
-                    case SQL_C_ULONG:
-                    case SQL_C_SBIGINT:
-                    case SQL_C_UBIGINT:
-                        bIntegerFID = true;
-                        break;
-                    default:
-                        break;
-                }
-                if( !bIntegerFID )
-                {
-                    CPLDebug("MSSQL", "Ignoring FID column %s as it is of non integer type",
-                             pszFIDColumn);
-                    CPLFree(pszFIDColumn);
-                    pszFIDColumn = NULL;
-                }
-                else
-                {
-                    if (STARTS_WITH_CI(poStmtIn->GetColTypeName( iCol ), "bigint"))
-                        SetMetadataItem(OLMD_FID64, "YES");
-
-                    if ( EQUAL(poStmtIn->GetColTypeName( iCol ), "int identity") ||
-                        EQUAL(poStmtIn->GetColTypeName( iCol ), "bigint identity"))
-                        bIsIdentityFid = TRUE;
-
-                    nFIDColumnIndex = iCol;
-                    continue;
-                }
-            }
-        }
-        else
-        {
-            if (EQUAL(poStmtIn->GetColTypeName( iCol ), "int identity"))
-            {
-                pszFIDColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
-                bIsIdentityFid = TRUE;
-                nFIDColumnIndex = iCol;
-                continue;
-            }
-            else if (EQUAL(poStmtIn->GetColTypeName( iCol ), "bigint identity"))
-            {
-                pszFIDColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
-                bIsIdentityFid = TRUE;
-                SetMetadataItem(OLMD_FID64, "YES");
-                nFIDColumnIndex = iCol;
-                continue;
-            }
-        }
-
-        OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
-        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
-
-        switch( CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)) )
-        {
-            case SQL_C_SSHORT:
-            case SQL_C_USHORT:
-            case SQL_C_SLONG:
-            case SQL_C_ULONG:
-                oField.SetType( OFTInteger );
-                break;
-
-            case SQL_C_SBIGINT:
-            case SQL_C_UBIGINT:
-                oField.SetType( OFTInteger64 );
-                break;
-
-            case SQL_C_BINARY:
-                oField.SetType( OFTBinary );
-                break;
-
-            case SQL_C_NUMERIC:
-                oField.SetType( OFTReal );
-                oField.SetPrecision( poStmtIn->GetColPrecision(iCol) );
-                break;
-
-            case SQL_C_FLOAT:
-            case SQL_C_DOUBLE:
-                oField.SetType( OFTReal );
-                oField.SetWidth( 0 );
-                break;
-
-            case SQL_C_DATE:
-                oField.SetType( OFTDate );
-                break;
-
-            case SQL_C_TIME:
-                oField.SetType( OFTTime );
-                break;
-
-            case SQL_C_TIMESTAMP:
-                oField.SetType( OFTDateTime );
-                break;
-
-            default:
-                /* leave it as OFTString */;
-        }
-
-        oField.SetNullable( poStmtIn->GetColNullable(iCol) );
-
-        if ( poStmtIn->GetColColumnDef(iCol) )
-        {         
-            /* process default value specification */
-            if ( EQUAL(poStmtIn->GetColColumnDef(iCol), "(getdate())") )
-                oField.SetDefault( "CURRENT_TIMESTAMP" );
-            else if ( STARTS_WITH_CI(poStmtIn->GetColColumnDef(iCol), "(CONVERT([time],getdate()") )
-                oField.SetDefault( "CURRENT_TIME" );
-            else if ( STARTS_WITH_CI(poStmtIn->GetColColumnDef(iCol), "(CONVERT([date],getdate()") )
-                oField.SetDefault( "CURRENT_DATE" );
-            else
-            {
-                char* pszDefault = CPLStrdup(poStmtIn->GetColColumnDef(iCol));
-                int nLen = static_cast<int>(strlen(pszDefault));
-                if (nLen >= 1 && pszDefault[0] == '(' && pszDefault[nLen-1] == ')')
-                {
-                    // All default values are encapsulated in brackets
-                    // by MSSQL server.
-                    if (nLen >= 4 && pszDefault[1] == '(' && pszDefault[nLen-2] == ')')
-                    {
-                        /* for numeric values double brackets are used */
-                        pszDefault[nLen-2] = '\0';
-                        oField.SetDefault(pszDefault + 2);
-                    }
-                    else
-                    {
-                        pszDefault[nLen-1] = '\0';
-                        oField.SetDefault(pszDefault + 1);
-                    }
-                }
-                else
-                    oField.SetDefault( pszDefault );
-
-                CPLFree(pszDefault);
-            }
-        }
-
-        poFeatureDefn->AddFieldDefn( &oField );
-        panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      If we don't already have an FID, check if there is a special    */
-/*      FID named column available.                                     */
-/* -------------------------------------------------------------------- */
-    if( pszFIDColumn == NULL )
-    {
-        const char *pszOGR_FID = CPLGetConfigOption("MSSQLSPATIAL_OGR_FID","OGR_FID");
-        if( poFeatureDefn->GetFieldIndex( pszOGR_FID ) != -1 )
-            pszFIDColumn = CPLStrdup(pszOGR_FID);
-    }
-
-    if( pszFIDColumn != NULL )
-        CPLDebug( "OGR_MSSQLSpatial", "Using column %s as FID for table %s.",
-                  pszFIDColumn, poFeatureDefn->GetName() );
-    else
-        CPLDebug( "OGR_MSSQLSpatial", "Table %s has no identified FID column.",
-                  poFeatureDefn->GetName() );
-
-    return CE_None;
-}
-
-
-/************************************************************************/
-/*                            ResetReading()                            */
-/************************************************************************/
-
-void OGRMSSQLSpatialLayer::ResetReading()
-
-{
-    iNextShapeId = 0;
-}
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRFeature *OGRMSSQLSpatialLayer::GetNextFeature()
-
-{
-    while( true )
-    {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
-        if( poFeature == NULL )
-            return NULL;
-
-        if( (m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
-            && (m_poAttrQuery == NULL
-                || m_poAttrQuery->Evaluate( poFeature )) )
-            return poFeature;
-
-        delete poFeature;
-    }
-}
-
-/************************************************************************/
-/*                         GetNextRawFeature()                          */
-/************************************************************************/
-
-OGRFeature *OGRMSSQLSpatialLayer::GetNextRawFeature()
-
-{
-    if( GetStatement() == NULL )
-        return NULL;
-
-/* -------------------------------------------------------------------- */
-/*      If we are marked to restart then do so, and fetch a record.     */
-/* -------------------------------------------------------------------- */
-    if( !poStmt->Fetch() )
-    {
-        delete poStmt;
-        poStmt = NULL;
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create a feature from the current result.                       */
-/* -------------------------------------------------------------------- */
-    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
-
-    if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
-        poFeature->SetFID( 
-            CPLAtoGIntBig(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) );
-    else
-        poFeature->SetFID( iNextShapeId );
-
-    iNextShapeId++;
-    m_nFeaturesRead++;
-
-/* -------------------------------------------------------------------- */
-/*      Set the fields.                                                 */
-/* -------------------------------------------------------------------- */
-    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
-    {
-        if ( poFeatureDefn->GetFieldDefn(iField)->IsIgnored() )
-            continue;
-        
-        int iSrcField = panFieldOrdinals[iField];
-        const char *pszValue = poStmt->GetColData( iSrcField );
-
-        if( pszValue == NULL )
-            /* no value */;
-        else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
-            poFeature->SetField( iField, 
-                                 poStmt->GetColDataLength(iSrcField),
-                                 (GByte *) pszValue );
-        else
-            poFeature->SetField( iField, pszValue );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Try to extract a geometry.                                      */
-/* -------------------------------------------------------------------- */
-    if( pszGeomColumn != NULL && !poFeatureDefn->IsGeometryIgnored())
-    {
-        int iField = poStmt->GetColId( pszGeomColumn );
-        const char *pszGeomText = poStmt->GetColData( iField );
-        OGRGeometry *poGeom = NULL;
-        OGRErr eErr = OGRERR_NONE;
-
-        if( pszGeomText != NULL )
-        {
-            int nLength = poStmt->GetColDataLength( iField );
-
-            if ( nGeomColumnType == MSSQLCOLTYPE_GEOMETRY || 
-                 nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY ||
-                 nGeomColumnType == MSSQLCOLTYPE_BINARY)
-            {
-                switch ( poDS->GetGeometryFormat() )
-                {
-                case MSSQLGEOMETRY_NATIVE:
-                    {
-                        OGRMSSQLGeometryParser oParser( nGeomColumnType ); 
-                        eErr = oParser.ParseSqlGeometry( 
-                            (unsigned char *) pszGeomText, nLength, &poGeom );
-                        nSRSId = oParser.GetSRSId();
-                    }
-                    break;
-                case MSSQLGEOMETRY_WKB:
-                case MSSQLGEOMETRY_WKBZM:
-                    eErr = OGRGeometryFactory::createFromWkb((unsigned char *) pszGeomText,
-                                                      NULL, &poGeom, nLength);
-                    break;
-                case MSSQLGEOMETRY_WKT:
-                    eErr = OGRGeometryFactory::createFromWkt((char **) &pszGeomText,
-                                                      NULL, &poGeom);
-                    break;
-                } 
-            }
-            else if (nGeomColumnType == MSSQLCOLTYPE_TEXT)
-            {
-                eErr = OGRGeometryFactory::createFromWkt((char **) &pszGeomText,
-                                                      NULL, &poGeom);
-            }    
-        }
-        
-        if ( eErr != OGRERR_NONE )
-        {
-            const char *pszMessage;
-
-            switch ( eErr )
-            {
-                case OGRERR_NOT_ENOUGH_DATA:
-                    pszMessage = "Not enough data to deserialize";
-                    break;
-                case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
-                    pszMessage = "Unsupported geometry type";
-                    break;
-                case OGRERR_CORRUPT_DATA:
-                    pszMessage = "Corrupt data";
-                    break;
-                default:
-                    pszMessage = "Unrecognized error";
-            }
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "GetNextRawFeature(): %s", pszMessage);
-        }
-
-        if( poGeom != NULL )
-        {
-            if ( GetSpatialRef() )
-                poGeom->assignSpatialReference( poSRS );
-
-            poFeature->SetGeometryDirectly( poGeom );
-        }
-    }
-
-    return poFeature;
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *OGRMSSQLSpatialLayer::GetFeature( GIntBig nFeatureId )
-
-{
-    /* This should be implemented directly! */
-
-    return OGRLayer::GetFeature( nFeatureId );
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRMSSQLSpatialLayer::TestCapability( CPL_UNUSED const char * pszCap )
-{
-    return FALSE;
-}
-
-/************************************************************************/
-/*                          StartTransaction()                          */
-/************************************************************************/
-
-OGRErr OGRMSSQLSpatialLayer::StartTransaction()
-
-{
-    if (!poDS->GetSession()->BeginTransaction())
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                    "Failed to start transaction: %s", poDS->GetSession()->GetLastError() );
-        return OGRERR_FAILURE;
-    }
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                         CommitTransaction()                          */
-/************************************************************************/
-
-OGRErr OGRMSSQLSpatialLayer::CommitTransaction()
-
-{
-    if (!poDS->GetSession()->CommitTransaction())
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                    "Failed to commit transaction: %s", poDS->GetSession()->GetLastError() );
-        return OGRERR_FAILURE;
-    }
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                        RollbackTransaction()                         */
-/************************************************************************/
-
-OGRErr OGRMSSQLSpatialLayer::RollbackTransaction()
-
-{
-    if (!poDS->GetSession()->RollbackTransaction())
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                    "Failed to roll back transaction: %s", poDS->GetSession()->GetLastError() );
-        return OGRERR_FAILURE;
-    }
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           GetSpatialRef()                            */
-/************************************************************************/
-
-OGRSpatialReference *OGRMSSQLSpatialLayer::GetSpatialRef()
-
-{
-    if( poSRS == NULL && nSRSId > 0 )
-    {
-        poSRS = poDS->FetchSRS( nSRSId );
-        if( poSRS != NULL )
-            poSRS->Reference();
-        else
-            nSRSId = 0;
-    }
-
-    return poSRS;
-}
-
-/************************************************************************/
-/*                            GetFIDColumn()                            */
-/************************************************************************/
-
-const char *OGRMSSQLSpatialLayer::GetFIDColumn() 
-
-{
-    GetLayerDefn();
-
-    if( pszFIDColumn != NULL )
-        return pszFIDColumn;
-    else
-        return "";
-}
-
-/************************************************************************/
-/*                         GetGeometryColumn()                          */
-/************************************************************************/
-
-const char *OGRMSSQLSpatialLayer::GetGeometryColumn() 
-
-{
-    GetLayerDefn();
-
-    if( pszGeomColumn != NULL )
-        return pszGeomColumn;
-    else
-        return "";
-}
-
-/************************************************************************/
-/*                        GByteArrayToHexString()                       */
-/************************************************************************/
-
-char* OGRMSSQLSpatialLayer::GByteArrayToHexString( const GByte* pabyData, int nLen)
-{
-    char* pszTextBuf;
-
-    const size_t nTextBufLen = nLen*2+3;
-    pszTextBuf = (char *) CPLMalloc(nTextBufLen);
-
-    int  iSrc, iDst=0;
-
-    for( iSrc = 0; iSrc < nLen; iSrc++ )
-    {
-        if( iSrc == 0 )
-        {
-            snprintf( pszTextBuf+iDst, nTextBufLen-iDst, "0x%02x", pabyData[iSrc] );
-            iDst += 4;
-        }
-        else
-        {
-            snprintf( pszTextBuf+iDst, nTextBufLen-iDst, "%02x", pabyData[iSrc] );
-            iDst += 2;
-        }
-    }
-    pszTextBuf[iDst] = 0;
-
-    return pszTextBuf;
-}
+/******************************************************************************
+ *
+ * Project:  MSSQL Spatial driver
+ * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
+ * Author:   Tamas Szekeres, szekerest at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_mssqlspatial.h"
+
+CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+/************************************************************************/
+/*                        OGRMSSQLSpatialLayer()                        */
+/************************************************************************/
+
+OGRMSSQLSpatialLayer::OGRMSSQLSpatialLayer()
+
+{
+    poDS = NULL;
+
+    poFeatureDefn = NULL;
+    nGeomColumnType = -1;
+    pszGeomColumn = NULL;
+    pszFIDColumn = NULL;
+    bIsIdentityFid = FALSE;
+    panFieldOrdinals = NULL;
+
+    poStmt = NULL;
+
+    iNextShapeId = 0;
+
+    poSRS = NULL;
+    nSRSId = -1; // we haven't even queried the database for it yet.
+    nLayerStatus = MSSQLLAYERSTATUS_ORIGINAL;
+
+    nGeomColumnIndex = -1;
+    nFIDColumnIndex = -1;
+    nRawColumns = 0;
+}
+
+/************************************************************************/
+/*                      ~OGRMSSQLSpatialLayer()                         */
+/************************************************************************/
+
+OGRMSSQLSpatialLayer::~OGRMSSQLSpatialLayer()
+
+{
+    if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
+    {
+        CPLDebug( "OGR_MSSQLSpatial", "%d features read on layer '%s'.",
+                  (int) m_nFeaturesRead,
+                  poFeatureDefn->GetName() );
+    }
+
+    if( poStmt )
+    {
+        delete poStmt;
+        poStmt = NULL;
+    }
+
+    CPLFree( pszGeomColumn );
+    CPLFree( pszFIDColumn );
+    CPLFree( panFieldOrdinals );
+
+    if( poFeatureDefn )
+    {
+        poFeatureDefn->Release();
+        poFeatureDefn = NULL;
+    }
+
+    if( poSRS )
+        poSRS->Release();
+}
+
+/************************************************************************/
+/*                          BuildFeatureDefn()                          */
+/*                                                                      */
+/*      Build feature definition from a set of column definitions       */
+/*      set on a statement.  Sift out geometry and FID fields.          */
+/************************************************************************/
+
+CPLErr OGRMSSQLSpatialLayer::BuildFeatureDefn( const char *pszLayerName,
+                                    CPLODBCStatement *poStmtIn )
+
+{
+    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
+    nRawColumns = poStmtIn->GetColCount();
+
+    poFeatureDefn->Reference();
+
+    CPLFree(panFieldOrdinals);
+    panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
+
+    for( int iCol = 0; iCol < nRawColumns; iCol++ )
+    {
+        if ( pszGeomColumn == NULL )
+        {
+            /* need to identify the geometry column */
+            if ( EQUAL(poStmtIn->GetColTypeName( iCol ), "geometry") )
+            {
+                nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
+                pszGeomColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
+                if (poFeatureDefn->GetGeomFieldCount() == 1)
+                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmtIn->GetColNullable(iCol) );
+                nGeomColumnIndex = iCol;
+                continue;
+            }
+            else if ( EQUAL(poStmtIn->GetColTypeName( iCol ), "geography") )
+            {
+                nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
+                pszGeomColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
+                if (poFeatureDefn->GetGeomFieldCount() == 1)
+                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmtIn->GetColNullable(iCol) );
+                nGeomColumnIndex = iCol;
+                continue;
+            }
+        }
+        else
+        {
+            if( EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )
+            {
+                if (poFeatureDefn->GetGeomFieldCount() == 1)
+                    poFeatureDefn->GetGeomFieldDefn(0)->SetNullable( poStmtIn->GetColNullable(iCol) );
+                nGeomColumnIndex = iCol;
+                continue;
+            }
+        }
+
+        if( pszFIDColumn != NULL)
+        {
+            if (EQUAL(poStmtIn->GetColName(iCol), pszFIDColumn) )
+            {
+                bool bIntegerFID = false;
+                switch( CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)) )
+                {
+                    case SQL_C_SSHORT:
+                    case SQL_C_USHORT:
+                    case SQL_C_SLONG:
+                    case SQL_C_ULONG:
+                    case SQL_C_SBIGINT:
+                    case SQL_C_UBIGINT:
+                        bIntegerFID = true;
+                        break;
+                    default:
+                        break;
+                }
+                if( !bIntegerFID )
+                {
+                    CPLDebug("MSSQL", "Ignoring FID column %s as it is of non integer type",
+                             pszFIDColumn);
+                    CPLFree(pszFIDColumn);
+                    pszFIDColumn = NULL;
+                }
+                else
+                {
+                    if (STARTS_WITH_CI(poStmtIn->GetColTypeName( iCol ), "bigint"))
+                        SetMetadataItem(OLMD_FID64, "YES");
+
+                    if ( EQUAL(poStmtIn->GetColTypeName( iCol ), "int identity") ||
+                        EQUAL(poStmtIn->GetColTypeName( iCol ), "bigint identity"))
+                        bIsIdentityFid = TRUE;
+
+                    nFIDColumnIndex = iCol;
+                    continue;
+                }
+            }
+        }
+        else
+        {
+            if (EQUAL(poStmtIn->GetColTypeName( iCol ), "int identity"))
+            {
+                pszFIDColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
+                bIsIdentityFid = TRUE;
+                nFIDColumnIndex = iCol;
+                continue;
+            }
+            else if (EQUAL(poStmtIn->GetColTypeName( iCol ), "bigint identity"))
+            {
+                pszFIDColumn = CPLStrdup( poStmtIn->GetColName(iCol) );
+                bIsIdentityFid = TRUE;
+                SetMetadataItem(OLMD_FID64, "YES");
+                nFIDColumnIndex = iCol;
+                continue;
+            }
+        }
+
+        OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
+        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
+
+        switch( CPLODBCStatement::GetTypeMapping(poStmtIn->GetColType(iCol)) )
+        {
+            case SQL_C_SSHORT:
+            case SQL_C_USHORT:
+            case SQL_C_SLONG:
+            case SQL_C_ULONG:
+                oField.SetType( OFTInteger );
+                break;
+
+            case SQL_C_SBIGINT:
+            case SQL_C_UBIGINT:
+                oField.SetType( OFTInteger64 );
+                break;
+
+            case SQL_C_BINARY:
+                oField.SetType( OFTBinary );
+                break;
+
+            case SQL_C_NUMERIC:
+                oField.SetType( OFTReal );
+                oField.SetPrecision( poStmtIn->GetColPrecision(iCol) );
+                break;
+
+            case SQL_C_FLOAT:
+            case SQL_C_DOUBLE:
+                oField.SetType( OFTReal );
+                oField.SetWidth( 0 );
+                break;
+
+            case SQL_C_DATE:
+                oField.SetType( OFTDate );
+                break;
+
+            case SQL_C_TIME:
+                oField.SetType( OFTTime );
+                break;
+
+            case SQL_C_TIMESTAMP:
+                oField.SetType( OFTDateTime );
+                break;
+
+            default:
+                /* leave it as OFTString */;
+        }
+
+        oField.SetNullable( poStmtIn->GetColNullable(iCol) );
+
+        if ( poStmtIn->GetColColumnDef(iCol) )
+        {
+            /* process default value specification */
+            if ( EQUAL(poStmtIn->GetColColumnDef(iCol), "(getdate())") )
+                oField.SetDefault( "CURRENT_TIMESTAMP" );
+            else if ( STARTS_WITH_CI(poStmtIn->GetColColumnDef(iCol), "(CONVERT([time],getdate()") )
+                oField.SetDefault( "CURRENT_TIME" );
+            else if ( STARTS_WITH_CI(poStmtIn->GetColColumnDef(iCol), "(CONVERT([date],getdate()") )
+                oField.SetDefault( "CURRENT_DATE" );
+            else
+            {
+                char* pszDefault = CPLStrdup(poStmtIn->GetColColumnDef(iCol));
+                int nLen = static_cast<int>(strlen(pszDefault));
+                if (nLen >= 1 && pszDefault[0] == '(' && pszDefault[nLen-1] == ')')
+                {
+                    // All default values are encapsulated in brackets
+                    // by MSSQL server.
+                    if (nLen >= 4 && pszDefault[1] == '(' && pszDefault[nLen-2] == ')')
+                    {
+                        /* for numeric values double brackets are used */
+                        pszDefault[nLen-2] = '\0';
+                        oField.SetDefault(pszDefault + 2);
+                    }
+                    else
+                    {
+                        pszDefault[nLen-1] = '\0';
+                        oField.SetDefault(pszDefault + 1);
+                    }
+                }
+                else
+                    oField.SetDefault( pszDefault );
+
+                CPLFree(pszDefault);
+            }
+        }
+
+        poFeatureDefn->AddFieldDefn( &oField );
+        panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If we don't already have an FID, check if there is a special    */
+/*      FID named column available.                                     */
+/* -------------------------------------------------------------------- */
+    if( pszFIDColumn == NULL )
+    {
+        const char *pszOGR_FID = CPLGetConfigOption("MSSQLSPATIAL_OGR_FID","OGR_FID");
+        if( poFeatureDefn->GetFieldIndex( pszOGR_FID ) != -1 )
+            pszFIDColumn = CPLStrdup(pszOGR_FID);
+    }
+
+    if( pszFIDColumn != NULL )
+        CPLDebug( "OGR_MSSQLSpatial", "Using column %s as FID for table %s.",
+                  pszFIDColumn, poFeatureDefn->GetName() );
+    else
+        CPLDebug( "OGR_MSSQLSpatial", "Table %s has no identified FID column.",
+                  poFeatureDefn->GetName() );
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRMSSQLSpatialLayer::ResetReading()
+
+{
+    iNextShapeId = 0;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRMSSQLSpatialLayer::GetNextFeature()
+
+{
+    while( true )
+    {
+        OGRFeature      *poFeature;
+
+        poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
+            return NULL;
+
+        if( (m_poFilterGeom == NULL
+            || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
+            return poFeature;
+
+        delete poFeature;
+    }
+}
+
+/************************************************************************/
+/*                         GetNextRawFeature()                          */
+/************************************************************************/
+
+OGRFeature *OGRMSSQLSpatialLayer::GetNextRawFeature()
+
+{
+    if( GetStatement() == NULL )
+        return NULL;
+
+/* -------------------------------------------------------------------- */
+/*      If we are marked to restart then do so, and fetch a record.     */
+/* -------------------------------------------------------------------- */
+    if( !poStmt->Fetch() )
+    {
+        delete poStmt;
+        poStmt = NULL;
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create a feature from the current result.                       */
+/* -------------------------------------------------------------------- */
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
+
+    const char* pszFID;
+    if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 &&
+        (pszFID = poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) != NULL )
+        poFeature->SetFID( CPLAtoGIntBig(pszFID) );
+    else
+        poFeature->SetFID( iNextShapeId );
+
+    iNextShapeId++;
+    m_nFeaturesRead++;
+
+/* -------------------------------------------------------------------- */
+/*      Set the fields.                                                 */
+/* -------------------------------------------------------------------- */
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    {
+        if ( poFeatureDefn->GetFieldDefn(iField)->IsIgnored() )
+            continue;
+
+        int iSrcField = panFieldOrdinals[iField];
+        const char *pszValue = poStmt->GetColData( iSrcField );
+
+        if( pszValue == NULL )
+            poFeature->SetFieldNull( iField );
+        else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
+            poFeature->SetField( iField,
+                                 poStmt->GetColDataLength(iSrcField),
+                                 (GByte *) pszValue );
+        else
+            poFeature->SetField( iField, pszValue );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to extract a geometry.                                      */
+/* -------------------------------------------------------------------- */
+    if( pszGeomColumn != NULL && !poFeatureDefn->IsGeometryIgnored())
+    {
+        int iField = poStmt->GetColId( pszGeomColumn );
+        const char *pszGeomText = poStmt->GetColData( iField );
+        OGRGeometry *poGeom = NULL;
+        OGRErr eErr = OGRERR_NONE;
+
+        if( pszGeomText != NULL )
+        {
+            int nLength = poStmt->GetColDataLength( iField );
+
+            if ( nGeomColumnType == MSSQLCOLTYPE_GEOMETRY ||
+                 nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY ||
+                 nGeomColumnType == MSSQLCOLTYPE_BINARY)
+            {
+                switch ( poDS->GetGeometryFormat() )
+                {
+                case MSSQLGEOMETRY_NATIVE:
+                    {
+                        OGRMSSQLGeometryParser oParser( nGeomColumnType );
+                        eErr = oParser.ParseSqlGeometry(
+                            (unsigned char *) pszGeomText, nLength, &poGeom );
+                        nSRSId = oParser.GetSRSId();
+                    }
+                    break;
+                case MSSQLGEOMETRY_WKB:
+                case MSSQLGEOMETRY_WKBZM:
+                    eErr = OGRGeometryFactory::createFromWkb((unsigned char *) pszGeomText,
+                                                      NULL, &poGeom, nLength);
+                    break;
+                case MSSQLGEOMETRY_WKT:
+                    eErr = OGRGeometryFactory::createFromWkt((char **) &pszGeomText,
+                                                      NULL, &poGeom);
+                    break;
+                }
+            }
+            else if (nGeomColumnType == MSSQLCOLTYPE_TEXT)
+            {
+                eErr = OGRGeometryFactory::createFromWkt((char **) &pszGeomText,
+                                                      NULL, &poGeom);
+            }
+        }
+
+        if ( eErr != OGRERR_NONE )
+        {
+            const char *pszMessage;
+
+            switch ( eErr )
+            {
+                case OGRERR_NOT_ENOUGH_DATA:
+                    pszMessage = "Not enough data to deserialize";
+                    break;
+                case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
+                    pszMessage = "Unsupported geometry type";
+                    break;
+                case OGRERR_CORRUPT_DATA:
+                    pszMessage = "Corrupt data";
+                    break;
+                default:
+                    pszMessage = "Unrecognized error";
+            }
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "GetNextRawFeature(): %s", pszMessage);
+        }
+
+        if( poGeom != NULL )
+        {
+            if ( GetSpatialRef() )
+                poGeom->assignSpatialReference( poSRS );
+
+            poFeature->SetGeometryDirectly( poGeom );
+        }
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRMSSQLSpatialLayer::GetFeature( GIntBig nFeatureId )
+
+{
+    /* This should be implemented directly! */
+
+    return OGRLayer::GetFeature( nFeatureId );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRMSSQLSpatialLayer::TestCapability( CPL_UNUSED const char * pszCap )
+{
+    return FALSE;
+}
+
+/************************************************************************/
+/*                          StartTransaction()                          */
+/************************************************************************/
+
+OGRErr OGRMSSQLSpatialLayer::StartTransaction()
+
+{
+    if (!poDS->GetSession()->BeginTransaction())
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Failed to start transaction: %s", poDS->GetSession()->GetLastError() );
+        return OGRERR_FAILURE;
+    }
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                         CommitTransaction()                          */
+/************************************************************************/
+
+OGRErr OGRMSSQLSpatialLayer::CommitTransaction()
+
+{
+    if (!poDS->GetSession()->CommitTransaction())
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Failed to commit transaction: %s", poDS->GetSession()->GetLastError() );
+        return OGRERR_FAILURE;
+    }
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        RollbackTransaction()                         */
+/************************************************************************/
+
+OGRErr OGRMSSQLSpatialLayer::RollbackTransaction()
+
+{
+    if (!poDS->GetSession()->RollbackTransaction())
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "Failed to roll back transaction: %s", poDS->GetSession()->GetLastError() );
+        return OGRERR_FAILURE;
+    }
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           GetSpatialRef()                            */
+/************************************************************************/
+
+OGRSpatialReference *OGRMSSQLSpatialLayer::GetSpatialRef()
+
+{
+    if( poSRS == NULL && nSRSId > 0 )
+    {
+        poSRS = poDS->FetchSRS( nSRSId );
+        if( poSRS != NULL )
+            poSRS->Reference();
+        else
+            nSRSId = 0;
+    }
+
+    return poSRS;
+}
+
+/************************************************************************/
+/*                            GetFIDColumn()                            */
+/************************************************************************/
+
+const char *OGRMSSQLSpatialLayer::GetFIDColumn()
+
+{
+    GetLayerDefn();
+
+    if( pszFIDColumn != NULL )
+        return pszFIDColumn;
+    else
+        return "";
+}
+
+/************************************************************************/
+/*                         GetGeometryColumn()                          */
+/************************************************************************/
+
+const char *OGRMSSQLSpatialLayer::GetGeometryColumn()
+
+{
+    GetLayerDefn();
+
+    if( pszGeomColumn != NULL )
+        return pszGeomColumn;
+    else
+        return "";
+}
+
+/************************************************************************/
+/*                        GByteArrayToHexString()                       */
+/************************************************************************/
+
+char* OGRMSSQLSpatialLayer::GByteArrayToHexString( const GByte* pabyData, int nLen)
+{
+    char* pszTextBuf;
+
+    const size_t nTextBufLen = nLen*2+3;
+    pszTextBuf = (char *) CPLMalloc(nTextBufLen);
+
+    int  iSrc, iDst=0;
+
+    for( iSrc = 0; iSrc < nLen; iSrc++ )
+    {
+        if( iSrc == 0 )
+        {
+            snprintf( pszTextBuf+iDst, nTextBufLen-iDst, "0x%02x", pabyData[iSrc] );
+            iDst += 4;
+        }
+        else
+        {
+            snprintf( pszTextBuf+iDst, nTextBufLen-iDst, "%02x", pabyData[iSrc] );
+            iDst += 2;
+        }
+    }
+    pszTextBuf[iDst] = 0;
+
+    return pszTextBuf;
+}
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp
index 596c24f..614f414 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialselectlayer.cpp
@@ -1,257 +1,256 @@
-/******************************************************************************
- * $Id: ogrmssqlspatialselectlayer.cpp 35339 2016-09-05 21:50:17Z tamas $
- *
- * Project:  MSSQL Spatial driver
- * Purpose:  Implements OGRMSSQLSpatialSelectLayer class, layer access to the results
- *           of a SELECT statement executed via ExecuteSQL().
- * Author:   Tamas Szekeres, szekerest at gmail.com
- *
- ******************************************************************************
- * Copyright (c) 2010, Tamas Szekeres
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "cpl_conv.h"
-#include "ogr_mssqlspatial.h"
+/******************************************************************************
+ *
+ * Project:  MSSQL Spatial driver
+ * Purpose:  Implements OGRMSSQLSpatialSelectLayer class, layer access to the results
+ *           of a SELECT statement executed via ExecuteSQL().
+ * Author:   Tamas Szekeres, szekerest at gmail.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Tamas Szekeres
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_conv.h"
+#include "ogr_mssqlspatial.h"
 #ifdef SQLNCLI_VERSION
 #include <sqlncli.h>
-#endif
-
-CPL_CVSID("$Id: ogrmssqlspatialselectlayer.cpp 35339 2016-09-05 21:50:17Z tamas $");
-/************************************************************************/
-/*                     OGRMSSQLSpatialSelectLayer()                     */
-/************************************************************************/
-
-OGRMSSQLSpatialSelectLayer::OGRMSSQLSpatialSelectLayer( OGRMSSQLSpatialDataSource *poDSIn,
-                                        CPLODBCStatement * poStmtIn )
-
-{
-    poDS = poDSIn;
-
-    iNextShapeId = 0;
-    nSRSId = -1;
-    poFeatureDefn = NULL;
-
-    poStmt = poStmtIn;
-    pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
-
-    /* identify the geometry column */
-    pszGeomColumn = NULL;
-    int iImageCol = -1;
-    for ( int iColumn = 0; iColumn < poStmt->GetColCount(); iColumn++ )
-    {
-        if ( EQUAL(poStmt->GetColTypeName( iColumn ), "image") )
-        {
-            SQLCHAR     szTableName[256];
-            SQLSMALLINT nTableNameLength = 0;
-
-            SQLColAttribute(poStmt->GetStatement(), (SQLSMALLINT)(iColumn + 1), SQL_DESC_TABLE_NAME,
-                                     szTableName, sizeof(szTableName),
-                                     &nTableNameLength, NULL);
-
-            if (nTableNameLength > 0)
-            {
-                OGRLayer *poBaseLayer = poDS->GetLayerByName((const char*)szTableName);
-                if (poBaseLayer != NULL && EQUAL(poBaseLayer->GetGeometryColumn(), poStmt->GetColName(iColumn)))
-                {
-                    nGeomColumnType = MSSQLCOLTYPE_BINARY;
-                    pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
-                    /* copy spatial reference */
-                    if (!poSRS && poBaseLayer->GetSpatialRef())
-                        poSRS = poBaseLayer->GetSpatialRef()->Clone();
-                    break;
-                }
-            }
-            else if (iImageCol == -1)
-                iImageCol = iColumn;
-        }
-        else if ( EQUAL(poStmt->GetColTypeName( iColumn ), "geometry") )
-        {
-            nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
-            pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
-            break;
-        }
-        else if ( EQUAL(poStmt->GetColTypeName( iColumn ), "geography") )
-        {
-            nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
-            pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
-            break;
-        }
-        else if ( EQUAL(poStmt->GetColTypeName( iColumn ), "udt") )
-        {
-#ifdef SQL_CA_SS_UDT_TYPE_NAME
-            SQLCHAR     szUDTTypeName[256];
-            SQLSMALLINT nUDTTypeNameLength = 0;
-
-            SQLColAttribute(poStmt->GetStatement(), (SQLSMALLINT)(iColumn + 1), SQL_CA_SS_UDT_TYPE_NAME,
-                                     szUDTTypeName, sizeof(szUDTTypeName),
-                                     &nUDTTypeNameLength, NULL);
-
-            if ( EQUAL((char*)szUDTTypeName, "geometry") )
-            {
-                nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
-                pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
-            }
-            else if ( EQUAL((char*)szUDTTypeName, "geography") )
-            {
-                nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
-                pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
-            }
-#endif
-            break;
-        }   
-    }
-
-    if (pszGeomColumn == NULL && iImageCol >= 0)
-    {
-        /* set the image col as geometry column as the last resort */
-        nGeomColumnType = MSSQLCOLTYPE_BINARY;
-        pszGeomColumn = CPLStrdup(poStmt->GetColName(iImageCol));
-    }
-
-    BuildFeatureDefn( "SELECT", poStmt );
-
-    if ( GetSpatialRef() && poFeatureDefn->GetGeomFieldCount() == 1)
-        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSRS );
-}
-
-/************************************************************************/
-/*                    ~OGRMSSQLSpatialSelectLayer()                     */
-/************************************************************************/
-
-OGRMSSQLSpatialSelectLayer::~OGRMSSQLSpatialSelectLayer()
-
-{
-    ClearStatement();
-    CPLFree(pszBaseStatement);
-}
-
-/************************************************************************/
-/*                           ClearStatement()                           */
-/************************************************************************/
-
-void OGRMSSQLSpatialSelectLayer::ClearStatement()
-
-{
-    if( poStmt != NULL )
-    {
-        delete poStmt;
-        poStmt = NULL;
-    }
-}
-
-/************************************************************************/
-/*                            GetStatement()                            */
-/************************************************************************/
-
-CPLODBCStatement *OGRMSSQLSpatialSelectLayer::GetStatement()
-
-{
-    if( poStmt == NULL )
-        ResetStatement();
-
-    return poStmt;
-}
-
-/************************************************************************/
-/*                           ResetStatement()                           */
-/************************************************************************/
-
-OGRErr OGRMSSQLSpatialSelectLayer::ResetStatement()
-
-{
-    ClearStatement();
-
-    iNextShapeId = 0;
-
-    CPLDebug( "OGR_MSSQLSpatial", "Recreating statement." );
-    poStmt = new CPLODBCStatement( poDS->GetSession() );
-    poStmt->Append( pszBaseStatement );
-
-    if( poStmt->ExecuteSQL() )
-        return OGRERR_NONE;
-    else
-    {
-        delete poStmt;
-        poStmt = NULL;
-        return OGRERR_FAILURE;
-    }
-}
-
-/************************************************************************/
-/*                            ResetReading()                            */
-/************************************************************************/
-
-void OGRMSSQLSpatialSelectLayer::ResetReading()
-
-{
-    if( iNextShapeId != 0 )
-        ClearStatement();
-
-    OGRMSSQLSpatialLayer::ResetReading();
-}
-
-/************************************************************************/
-/*                             GetFeature()                             */
-/************************************************************************/
-
-OGRFeature *OGRMSSQLSpatialSelectLayer::GetFeature( GIntBig nFeatureId )
-
-{
-    return OGRMSSQLSpatialLayer::GetFeature( nFeatureId );
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRMSSQLSpatialSelectLayer::TestCapability( const char * pszCap )
-
-{
-    return OGRMSSQLSpatialLayer::TestCapability( pszCap );
-}
-
-/************************************************************************/
-/*                             GetExtent()                              */
-/*                                                                      */
-/*      Since SELECT layers currently cannot ever have geometry, we     */
-/*      can optimize the GetExtent() method!                            */
-/************************************************************************/
-
-OGRErr OGRMSSQLSpatialSelectLayer::GetExtent(OGREnvelope *, int )
-
-{
-    return OGRERR_FAILURE;
-}
-
-/************************************************************************/
-/*                          GetFeatureCount()                           */
-/*                                                                      */
-/*      If a spatial filter is in effect, we turn control over to       */
-/*      the generic counter.  Otherwise we return the total count.      */
-/*      Eventually we should consider implementing a more efficient     */
-/*      way of counting features matching a spatial query.              */
-/************************************************************************/
-
-GIntBig OGRMSSQLSpatialSelectLayer::GetFeatureCount( int bForce )
-
-{
-    return OGRMSSQLSpatialLayer::GetFeatureCount( bForce );
-}
+#endif
+
+CPL_CVSID("$Id: ogrmssqlspatialselectlayer.cpp 35338 2016-09-05 21:49:05Z tamas $");
+/************************************************************************/
+/*                     OGRMSSQLSpatialSelectLayer()                     */
+/************************************************************************/
+
+OGRMSSQLSpatialSelectLayer::OGRMSSQLSpatialSelectLayer( OGRMSSQLSpatialDataSource *poDSIn,
+                                        CPLODBCStatement * poStmtIn )
+
+{
+    poDS = poDSIn;
+
+    iNextShapeId = 0;
+    nSRSId = -1;
+    poFeatureDefn = NULL;
+
+    poStmt = poStmtIn;
+    pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
+
+    /* identify the geometry column */
+    pszGeomColumn = NULL;
+    int iImageCol = -1;
+    for ( int iColumn = 0; iColumn < poStmt->GetColCount(); iColumn++ )
+    {
+        if ( EQUAL(poStmt->GetColTypeName( iColumn ), "image") )
+        {
+            SQLCHAR     szTableName[256];
+            SQLSMALLINT nTableNameLength = 0;
+
+            SQLColAttribute(poStmt->GetStatement(), (SQLSMALLINT)(iColumn + 1), SQL_DESC_TABLE_NAME,
+                                     szTableName, sizeof(szTableName),
+                                     &nTableNameLength, NULL);
+
+            if (nTableNameLength > 0)
+            {
+                OGRLayer *poBaseLayer = poDS->GetLayerByName((const char*)szTableName);
+                if (poBaseLayer != NULL && EQUAL(poBaseLayer->GetGeometryColumn(), poStmt->GetColName(iColumn)))
+                {
+                    nGeomColumnType = MSSQLCOLTYPE_BINARY;
+                    pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
+                    /* copy spatial reference */
+                    if (!poSRS && poBaseLayer->GetSpatialRef())
+                        poSRS = poBaseLayer->GetSpatialRef()->Clone();
+                    break;
+                }
+            }
+            else if (iImageCol == -1)
+                iImageCol = iColumn;
+        }
+        else if ( EQUAL(poStmt->GetColTypeName( iColumn ), "geometry") )
+        {
+            nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
+            pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
+            break;
+        }
+        else if ( EQUAL(poStmt->GetColTypeName( iColumn ), "geography") )
+        {
+            nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
+            pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
+            break;
+        }
+        else if ( EQUAL(poStmt->GetColTypeName( iColumn ), "udt") )
+        {
+#ifdef SQL_CA_SS_UDT_TYPE_NAME
+            SQLCHAR     szUDTTypeName[256];
+            SQLSMALLINT nUDTTypeNameLength = 0;
+
+            SQLColAttribute(poStmt->GetStatement(), (SQLSMALLINT)(iColumn + 1), SQL_CA_SS_UDT_TYPE_NAME,
+                                     szUDTTypeName, sizeof(szUDTTypeName),
+                                     &nUDTTypeNameLength, NULL);
+
+            if ( EQUAL((char*)szUDTTypeName, "geometry") )
+            {
+                nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
+                pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
+            }
+            else if ( EQUAL((char*)szUDTTypeName, "geography") )
+            {
+                nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
+                pszGeomColumn = CPLStrdup(poStmt->GetColName(iColumn));
+            }
+#endif
+            break;
+        }
+    }
+
+    if (pszGeomColumn == NULL && iImageCol >= 0)
+    {
+        /* set the image col as geometry column as the last resort */
+        nGeomColumnType = MSSQLCOLTYPE_BINARY;
+        pszGeomColumn = CPLStrdup(poStmt->GetColName(iImageCol));
+    }
+
+    BuildFeatureDefn( "SELECT", poStmt );
+
+    if ( GetSpatialRef() && poFeatureDefn->GetGeomFieldCount() == 1)
+        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSRS );
+}
+
+/************************************************************************/
+/*                    ~OGRMSSQLSpatialSelectLayer()                     */
+/************************************************************************/
+
+OGRMSSQLSpatialSelectLayer::~OGRMSSQLSpatialSelectLayer()
+
+{
+    ClearStatement();
+    CPLFree(pszBaseStatement);
+}
+
+/************************************************************************/
+/*                           ClearStatement()                           */
+/************************************************************************/
+
+void OGRMSSQLSpatialSelectLayer::ClearStatement()
+
+{
+    if( poStmt != NULL )
+    {
+        delete poStmt;
+        poStmt = NULL;
+    }
+}
+
+/************************************************************************/
+/*                            GetStatement()                            */
+/************************************************************************/
+
+CPLODBCStatement *OGRMSSQLSpatialSelectLayer::GetStatement()
+
+{
+    if( poStmt == NULL )
+        ResetStatement();
+
+    return poStmt;
+}
+
+/************************************************************************/
+/*                           ResetStatement()                           */
+/************************************************************************/
+
+OGRErr OGRMSSQLSpatialSelectLayer::ResetStatement()
+
+{
+    ClearStatement();
+
+    iNextShapeId = 0;
+
+    CPLDebug( "OGR_MSSQLSpatial", "Recreating statement." );
+    poStmt = new CPLODBCStatement( poDS->GetSession() );
+    poStmt->Append( pszBaseStatement );
+
+    if( poStmt->ExecuteSQL() )
+        return OGRERR_NONE;
+    else
+    {
+        delete poStmt;
+        poStmt = NULL;
+        return OGRERR_FAILURE;
+    }
+}
+
+/************************************************************************/
+/*                            ResetReading()                            */
+/************************************************************************/
+
+void OGRMSSQLSpatialSelectLayer::ResetReading()
+
+{
+    if( iNextShapeId != 0 )
+        ClearStatement();
+
+    OGRMSSQLSpatialLayer::ResetReading();
+}
+
+/************************************************************************/
+/*                             GetFeature()                             */
+/************************************************************************/
+
+OGRFeature *OGRMSSQLSpatialSelectLayer::GetFeature( GIntBig nFeatureId )
+
+{
+    return OGRMSSQLSpatialLayer::GetFeature( nFeatureId );
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRMSSQLSpatialSelectLayer::TestCapability( const char * pszCap )
+
+{
+    return OGRMSSQLSpatialLayer::TestCapability( pszCap );
+}
+
+/************************************************************************/
+/*                             GetExtent()                              */
+/*                                                                      */
+/*      Since SELECT layers currently cannot ever have geometry, we     */
+/*      can optimize the GetExtent() method!                            */
+/************************************************************************/
+
+OGRErr OGRMSSQLSpatialSelectLayer::GetExtent(OGREnvelope *, int )
+
+{
+    return OGRERR_FAILURE;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/*                                                                      */
+/*      If a spatial filter is in effect, we turn control over to       */
+/*      the generic counter.  Otherwise we return the total count.      */
+/*      Eventually we should consider implementing a more efficient     */
+/*      way of counting features matching a spatial query.              */
+/************************************************************************/
+
+GIntBig OGRMSSQLSpatialSelectLayer::GetFeatureCount( int bForce )
+
+{
+    return OGRMSSQLSpatialLayer::GetFeatureCount( bForce );
+}
diff --git a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
index 3d72fcf..841bfae 100644
--- a/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
+++ b/ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialtablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmssqlspatialtablelayer.cpp 34289 2016-05-24 19:43:40Z tamas $
  *
  * Project:  MSSQL Spatial driver
  * Purpose:  Implements OGRMSSQLSpatialTableLayer class, access to an existing table.
@@ -34,7 +33,7 @@
 #include <sqlncli.h>
 #endif
 
-CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 34289 2016-05-24 19:43:40Z tamas $");
+CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGRMSSQLAppendEscaped( )                     */
@@ -83,7 +82,8 @@ void OGRMSSQLAppendEscaped( CPLODBCStatement* poStatement, const char* pszStrVal
 
 OGRMSSQLSpatialTableLayer::OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource *poDSIn ) :
     bLaunderColumnNames(FALSE),
-    bPreservePrecision(FALSE)
+    bPreservePrecision(FALSE),
+    eGeomType(wkbNone)
 {
     poDS = poDSIn;
 
@@ -101,8 +101,6 @@ OGRMSSQLSpatialTableLayer::OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource
     pszLayerName = NULL;
     pszSchemaName = NULL;
 
-    eGeomType = wkbNone;
-
     bNeedSpatialIndex = FALSE;
 #ifdef SQL_SS_UDT
     nUploadGeometryFormat = MSSQLGEOMETRY_NATIVE;
@@ -129,7 +127,7 @@ OGRMSSQLSpatialTableLayer::~OGRMSSQLSpatialTableLayer()
 #ifdef MSSQL_BCP_SUPPORTED
     CloseBCP();
 #endif
-    
+
     if ( bNeedSpatialIndex && nLayerStatus == MSSQLLAYERSTATUS_CREATED )
     {
         /* recreate spatial index */
@@ -312,7 +310,6 @@ CPLErr OGRMSSQLSpatialTableLayer::Initialize( const char *pszSchema,
     if (eType != wkbNone)
         eGeomType = eType;
 
-
 /* -------------------------------------------------------------------- */
 /*             Try to find out the spatial reference                    */
 /* -------------------------------------------------------------------- */
@@ -565,7 +562,6 @@ CPLODBCStatement *OGRMSSQLSpatialTableLayer::GetStatement()
     return poStmt;
 }
 
-
 /************************************************************************/
 /*                           BuildStatement()                           */
 /************************************************************************/
@@ -699,7 +695,6 @@ OGRErr OGRMSSQLSpatialTableLayer::SetAttributeFilter( const char *pszQueryIn )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -714,7 +709,7 @@ int OGRMSSQLSpatialTableLayer::TestCapability( const char * pszCap )
             return TRUE;
 
         else if( EQUAL(pszCap,OLCRandomWrite) )
-            return (pszFIDColumn != NULL);
+            return pszFIDColumn != NULL;
     }
 
 #if (ODBCVER >= 0x0300)
@@ -729,7 +724,7 @@ int OGRMSSQLSpatialTableLayer::TestCapability( const char * pszCap )
         return TRUE;
 
     if( EQUAL(pszCap,OLCRandomRead) )
-        return (pszFIDColumn != NULL);
+        return pszFIDColumn != NULL;
     else if( EQUAL(pszCap,OLCFastFeatureCount) )
         return TRUE;
     else
@@ -763,7 +758,6 @@ GIntBig OGRMSSQLSpatialTableLayer::GetFeatureCount( int bForce )
     return nRet;
 }
 
-
 /************************************************************************/
 /*                            CreateField()                             */
 /************************************************************************/
@@ -932,7 +926,6 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
                   "Unable to update features in tables without\n"
                   "a recognised FID column.");
         return eErr;
-
     }
 
     ClearStatement();
@@ -957,7 +950,6 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
     int bind_num = 0;
     void** bind_buffer = (void**)CPLMalloc(sizeof(void*) * nFieldCount);
 
-
     int bNeedComma = FALSE;
     SQLLEN nWKBLenBindParameter;
     if(poGeom != NULL && pszGeomColumn != NULL)
@@ -973,12 +965,12 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
             {
                 char* pszBytes = GByteArrayToHexString( pabyData, nDataLen);
                 SQLLEN nts = SQL_NTS;
-                int nRetCode = SQLBindParameter(oStmt.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
+                int nRetCode = SQLBindParameter(oStmt.GetStatement(), (SQLUSMALLINT)(bind_num + 1),
                     SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR,
                     nDataLen, 0, (SQLPOINTER)pszBytes, 0, &nts);
                 if ( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
                 {
-                    oStmt.Append( "?" );   
+                    oStmt.Append( "?" );
                     bind_buffer[bind_num] = pszBytes;
                     ++bind_num;
                 }
@@ -986,7 +978,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
                 {
                     oStmt.Append( "null" );
                     CPLFree(pszBytes);
-                }       
+                }
             }
             else
             {
@@ -1090,7 +1082,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ISetFeature( OGRFeature *poFeature )
             bNeedComma = TRUE;
         }
 
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
             oStmt.Append( "null" );
         else
             AppendFieldValue(&oStmt, poFeature, i, &bind_num, bind_buffer);
@@ -1192,7 +1184,7 @@ int OGRMSSQLSpatialTableLayer::Failed( int nRetCode )
     int iRc = SQLGetDiagRec(SQL_HANDLE_ENV, hEnvBCP, 1,
     (SQLCHAR*)SQLState, &iNativeError, (SQLCHAR*)Msg, 256, &iMsgLen);
     if (iRc != SQL_NO_DATA) {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "SQL Error SQLState=%s, NativeError=%d, Msg=%s\n", SQLState,
                   static_cast<int>(iNativeError), Msg );
     }
@@ -1219,7 +1211,7 @@ int OGRMSSQLSpatialTableLayer::Failed2( int nRetCode )
     int iRc = SQLGetDiagRec(SQL_HANDLE_DBC, hDBCBCP, 1,
     (SQLCHAR*)SQLState, &iNativeError, (SQLCHAR*)Msg, 256, &iMsgLen);
     if (iRc != SQL_NO_DATA) {
-        CPLError( CE_Failure, CPLE_AppDefined, 
+        CPLError( CE_Failure, CPLE_AppDefined,
                   "SQL Error SQLState=%s, NativeError=%d, Msg=%s\n", SQLState,
                   static_cast<int>(iNativeError), Msg );
     }
@@ -1265,9 +1257,9 @@ int OGRMSSQLSpatialTableLayer::InitBCP(const char* pszDSN)
     SQLSMALLINT nOutConnStringLen = 0;
 
     if ( Failed(
-        SQLDriverConnect( hDBCBCP, NULL, 
-                            (SQLCHAR *) pszDSN, (SQLSMALLINT)strlen(pszDSN), 
-                            szOutConnString, sizeof(szOutConnString), 
+        SQLDriverConnect( hDBCBCP, NULL,
+                            (SQLCHAR *) pszDSN, (SQLSMALLINT)strlen(pszDSN),
+                            szOutConnString, sizeof(szOutConnString),
                             &nOutConnStringLen, SQL_DRIVER_NOPROMPT ) ))
     {
         CloseBCP();
@@ -1299,7 +1291,7 @@ void OGRMSSQLSpatialTableLayer::CloseBCP()
         if( bIdentityInsert )
         {
             bIdentityInsert = FALSE;
-            
+
             /* restore identity insert if needed */
             CPLODBCStatement oStatement( poDS->GetSession() );
 
@@ -1315,14 +1307,14 @@ void OGRMSSQLSpatialTableLayer::CloseBCP()
         }
     }
 
-    if( hDBCBCP!=NULL ) 
+    if( hDBCBCP!=NULL )
     {
         CPLDebug( "ODBC", "SQLDisconnect()" );
         SQLDisconnect( hDBCBCP );
         SQLFreeHandle( SQL_HANDLE_DBC, hDBCBCP );
         hDBCBCP = NULL;
     }
-    
+
     if( hEnvBCP!=NULL )
     {
         SQLFreeHandle( SQL_HANDLE_ENV, hEnvBCP );
@@ -1330,25 +1322,22 @@ void OGRMSSQLSpatialTableLayer::CloseBCP()
     }
 }
 
-
-
 /************************************************************************/
 /*                            CreateFeatureBCP()                        */
 /************************************************************************/
 
-
 OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
 
 {
     int iCol;
     int iField = 0;
-    
+
     if ( hDBCBCP == NULL )
     {
         nBCPCount = 0;
 
         CPLODBCSession* poSession = poDS->GetSession();
-        
+
         if (poSession->IsInTransaction())
             poSession->CommitTransaction(); /* commit creating the table */
 
@@ -1397,7 +1386,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                                 "Failed to set identity insert bulk copy mode, %s.",
-                                poDS->GetSession()->GetLastError());    
+                                poDS->GetSession()->GetLastError());
                 return OGRERR_FAILURE;
             }
         }
@@ -1407,11 +1396,11 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
         for( iCol = 0; iCol < nRawColumns; iCol++ )
         {
             papstBindBuffer[iCol] = NULL;
-            
+
             if (iCol == nGeomColumnIndex)
             {
                 papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
-                if (Failed2( bcp_bind(hDBCBCP, NULL /* data is provided later */, 
+                if (Failed2( bcp_bind(hDBCBCP, NULL /* data is provided later */,
                     0, 0/*or any value < 8000*/, NULL, 0, SQLUDT, iCol + 1) ))
                     return OGRERR_FAILURE;
             }
@@ -1423,8 +1412,8 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                 papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
                 papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
 
-                if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
-                    0, SQL_VARLEN_DATA, 
+                if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData,
+                    0, SQL_VARLEN_DATA,
                         (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
                     return OGRERR_FAILURE;
             }
@@ -1451,9 +1440,9 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     /* int */
                     papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
                     papstBindBuffer[iCol]->Integer.iIndicator = sizeof(papstBindBuffer[iCol]->Integer.Value);
-                
-                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol], 
-                        sizeof(papstBindBuffer[iCol]->Integer.iIndicator), sizeof(papstBindBuffer[iCol]->Integer.Value), 
+
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol],
+                        sizeof(papstBindBuffer[iCol]->Integer.iIndicator), sizeof(papstBindBuffer[iCol]->Integer.Value),
                             NULL, 0, SQLINT4, iCol + 1) ))
                         return OGRERR_FAILURE;
                 }
@@ -1463,8 +1452,8 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
 
-                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
-                        0, SQL_VARLEN_DATA, 
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData,
+                        0, SQL_VARLEN_DATA,
                             (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
                         return OGRERR_FAILURE;
                 }
@@ -1475,8 +1464,8 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
 
-                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
-                        0, SQL_VARLEN_DATA, 
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData,
+                        0, SQL_VARLEN_DATA,
                             (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
                         return OGRERR_FAILURE;
                 }
@@ -1487,14 +1476,14 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     papstBindBuffer[iCol]->VarChar.nSize = poFDefn->GetWidth();
                     if (poFDefn->GetWidth() == 0)
                     {
-                        if (Failed2( bcp_bind(hDBCBCP, NULL /* data is provided later */, 
+                        if (Failed2( bcp_bind(hDBCBCP, NULL /* data is provided later */,
                             0, 0/*or any value < 8000*/, NULL, 0, 0, iCol + 1) ))
                             return OGRERR_FAILURE;
                     }
                     else
                     {
-                        if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol], 
-                            sizeof(papstBindBuffer[iCol]->VarChar.nSize), poFDefn->GetWidth(), 
+                        if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol],
+                            sizeof(papstBindBuffer[iCol]->VarChar.nSize), poFDefn->GetWidth(),
                                 NULL, 0, SQLNVARCHAR, iCol + 1) ))
                             return OGRERR_FAILURE;
                     }
@@ -1505,8 +1494,8 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
 
-                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
-                        0, SQL_VARLEN_DATA, 
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData,
+                        0, SQL_VARLEN_DATA,
                             (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
                         return OGRERR_FAILURE;
                 }
@@ -1516,8 +1505,8 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
 
-                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
-                        0, SQL_VARLEN_DATA, 
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData,
+                        0, SQL_VARLEN_DATA,
                             (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
                         return OGRERR_FAILURE;
                 }
@@ -1527,8 +1516,8 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
 
-                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData, 
-                        0, SQL_VARLEN_DATA, 
+                    if (Failed2( bcp_bind(hDBCBCP, (LPCBYTE)papstBindBuffer[iCol]->VarChar.pData,
+                        0, SQL_VARLEN_DATA,
                             (LPCBYTE)"", 1, SQLVARCHAR, iCol + 1) ))
                         return OGRERR_FAILURE;
                 }
@@ -1536,7 +1525,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                 {
                     /* image */
                     papstBindBuffer[iCol] = (BCPData*)CPLMalloc(sizeof(BCPData));
-                    if (Failed2( bcp_bind(hDBCBCP, NULL /* data is provided later */, 
+                    if (Failed2( bcp_bind(hDBCBCP, NULL /* data is provided later */,
                         0, 0/*or any value < 8000*/, NULL, 0, 0, iCol + 1) ))
                         return OGRERR_FAILURE;
                 }
@@ -1591,7 +1580,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
         {
             if ( !bIdentityInsert )
                     continue;
-            
+
             GIntBig nFID = poFeature->GetFID();
             if ( nFID == OGRNullFID )
             {
@@ -1622,7 +1611,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
             if( poFDefn->GetType() == OFTInteger )
             {
                 /* int */
-                if (!poFeature->IsFieldSet( iField ))
+                if (!poFeature->IsFieldSetAndNotNull( iField ))
                     papstBindBuffer[iCol]->Integer.iIndicator = SQL_NULL_DATA;
                 else
                 {
@@ -1633,7 +1622,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
             else if( poFDefn->GetType() == OFTInteger64 )
             {
                 /* bigint */
-                if (!poFeature->IsFieldSet( iField ))
+                if (!poFeature->IsFieldSetAndNotNull( iField ))
                 {
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
                     /* set NULL */
@@ -1652,7 +1641,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
             else if( poFDefn->GetType() == OFTReal )
             {
                 /* float */
-                if (!poFeature->IsFieldSet( iField ))
+                if (!poFeature->IsFieldSetAndNotNull( iField ))
                 {
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
                     /* set NULL */
@@ -1673,7 +1662,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                 /* nvarchar */
                 if (poFDefn->GetWidth() != 0)
                 {
-                    if (!poFeature->IsFieldSet( iField ))
+                    if (!poFeature->IsFieldSetAndNotNull( iField ))
                     {
                         papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
                         if (Failed2( bcp_collen( hDBCBCP, SQL_NULL_DATA, iCol + 1) ))
@@ -1681,7 +1670,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     }
                     else
                     {
-                    
+
                         papstBindBuffer[iCol]->VarChar.nSize = CPLStrlenUTF8(poFeature->GetFieldAsString(iField)) * 2;
                         wchar_t* buffer = CPLRecodeToWChar( poFeature->GetFieldAsString(iField), CPL_ENC_UTF8, CPL_ENC_UCS2);
                         memcpy(papstBindBuffer[iCol]->VarChar.pData, buffer, papstBindBuffer[iCol]->VarChar.nSize + 2);
@@ -1695,7 +1684,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
             else if( poFDefn->GetType() == OFTDate )
             {
                 /* date */
-                if (!poFeature->IsFieldSet( iField ))
+                if (!poFeature->IsFieldSetAndNotNull( iField ))
                 {
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
                     /* set NULL */
@@ -1704,7 +1693,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                 }
                 else
                 {
-                    int	pnYear;
+                    int pnYear;
                     int pnMonth;
                     int pnDay;
                     int pnHour;
@@ -1712,9 +1701,9 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     float pfSecond;
                     int pnTZFlag;
 
-                    poFeature->GetFieldAsDateTime(iField, &pnYear, &pnMonth, &pnDay, 
+                    poFeature->GetFieldAsDateTime(iField, &pnYear, &pnMonth, &pnDay,
                         &pnHour, &pnMinute, &pfSecond, &pnTZFlag);
-                
+
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
                     snprintf((char*)papstBindBuffer[iCol]->VarChar.pData, 8000, "%4d-%02d-%02d %02d:%02d:%06.3f", pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond);
                     if (Failed2( bcp_collen( hDBCBCP, SQL_VARLEN_DATA, iCol + 1) ))
@@ -1724,7 +1713,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
             else if( poFDefn->GetType() == OFTTime )
             {
                 /* time(7) */
-                if (!poFeature->IsFieldSet( iField ))
+                if (!poFeature->IsFieldSetAndNotNull( iField ))
                 {
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
                     /* set NULL */
@@ -1733,7 +1722,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                 }
                 else
                 {
-                    int	pnYear;
+                    int pnYear;
                     int pnMonth;
                     int pnDay;
                     int pnHour;
@@ -1741,19 +1730,19 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     float pfSecond;
                     int pnTZFlag;
 
-                    poFeature->GetFieldAsDateTime(iField, &pnYear, &pnMonth, &pnDay, 
+                    poFeature->GetFieldAsDateTime(iField, &pnYear, &pnMonth, &pnDay,
                         &pnHour, &pnMinute, &pfSecond, &pnTZFlag);
-                
+
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
                     snprintf((char*)papstBindBuffer[iCol]->VarChar.pData, 8000, "%4d-%02d-%02d %02d:%02d:%06.3f", pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond);
                     if (Failed2( bcp_collen( hDBCBCP, SQL_VARLEN_DATA, iCol + 1) ))
                         return OGRERR_FAILURE;
-                }              
+                }
             }
             else if( poFDefn->GetType() == OFTDateTime )
             {
                 /* datetime */
-                if (!poFeature->IsFieldSet( iField ))
+                if (!poFeature->IsFieldSetAndNotNull( iField ))
                 {
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_NULL_DATA;
                     /* set NULL */
@@ -1762,7 +1751,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                 }
                 else
                 {
-                    int	pnYear;
+                    int pnYear;
                     int pnMonth;
                     int pnDay;
                     int pnHour;
@@ -1770,19 +1759,19 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                     float pfSecond;
                     int pnTZFlag;
 
-                    poFeature->GetFieldAsDateTime(iField, &pnYear, &pnMonth, &pnDay, 
+                    poFeature->GetFieldAsDateTime(iField, &pnYear, &pnMonth, &pnDay,
                         &pnHour, &pnMinute, &pfSecond, &pnTZFlag);
-                
+
                     papstBindBuffer[iCol]->VarChar.nSize = SQL_VARLEN_DATA;
                     snprintf((char*)papstBindBuffer[iCol]->VarChar.pData, 8000, "%4d-%02d-%02d %02d:%02d:%06.3f", pnYear, pnMonth, pnDay, pnHour, pnMinute, pfSecond);
 
                     if (Failed2( bcp_collen( hDBCBCP, SQL_VARLEN_DATA, iCol + 1) ))
                         return OGRERR_FAILURE;
-                }              
+                }
             }
             else if( poFDefn->GetType() == OFTBinary )
             {
-                if (!poFeature->IsFieldSet( iField ))
+                if (!poFeature->IsFieldSetAndNotNull( iField ))
                 {
                     papstBindBuffer[iCol]->RawData.nSize = SQL_NULL_DATA;
                     /* set NULL */
@@ -1793,7 +1782,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                 {
                     /* image */
                     papstBindBuffer[iCol]->RawData.pData = poFeature->GetFieldAsBinary(iField, &papstBindBuffer[iCol]->RawData.nSize);
-                
+
                     /* set data length */
                     if (Failed2( bcp_collen( hDBCBCP, papstBindBuffer[iCol]->RawData.nSize, iCol + 1) ))
                         return OGRERR_FAILURE;
@@ -1825,23 +1814,23 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
         {
             if (papstBindBuffer[iCol]->RawData.nSize != SQL_NULL_DATA)
             {
-                if (Failed2( bcp_moretext( hDBCBCP, 
-                    papstBindBuffer[iCol]->RawData.nSize,  
+                if (Failed2( bcp_moretext( hDBCBCP,
+                    papstBindBuffer[iCol]->RawData.nSize,
                     papstBindBuffer[iCol]->RawData.pData ) ))
                 {
-                
+
                 }
                 CPLFree(papstBindBuffer[iCol]->RawData.pData);
                 if (Failed2( bcp_moretext( hDBCBCP, 0, NULL) ))
                 {
-                
+
                 }
             }
             else
             {
                 if (Failed2( bcp_moretext( hDBCBCP, SQL_NULL_DATA, NULL) ))
                 {
-                
+
                 }
             }
         }
@@ -1858,17 +1847,17 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
             {
                 if (poFDefn->GetWidth() == 0)
                 {
-                    if (poFeature->IsFieldSet( iField ))
+                    if (poFeature->IsFieldSetAndNotNull( iField ))
                     {
                         papstBindBuffer[iCol]->VarChar.nSize = CPLStrlenUTF8(poFeature->GetFieldAsString(iField)) * 2;
                         if (papstBindBuffer[iCol]->VarChar.nSize > 0)
                         {
-                            wchar_t* buffer = CPLRecodeToWChar( poFeature->GetFieldAsString(iField), CPL_ENC_UTF8, CPL_ENC_UCS2);                       
-                            if (Failed2( bcp_moretext( hDBCBCP, 
-                                papstBindBuffer[iCol]->VarChar.nSize,  
+                            wchar_t* buffer = CPLRecodeToWChar( poFeature->GetFieldAsString(iField), CPL_ENC_UTF8, CPL_ENC_UCS2);
+                            if (Failed2( bcp_moretext( hDBCBCP,
+                                papstBindBuffer[iCol]->VarChar.nSize,
                                 (LPCBYTE)buffer ) ))
                             {
-                
+
                             }
 
                             CPLFree(buffer);
@@ -1876,14 +1865,14 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
 
                         if (Failed2( bcp_moretext( hDBCBCP, 0, NULL) ))
                         {
-                
+
                         }
                     }
                     else
                     {
                         if (Failed2( bcp_moretext( hDBCBCP, SQL_NULL_DATA, NULL) ))
                         {
-                
+
                         }
                     }
                 }
@@ -1894,23 +1883,23 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
                 {
                     if (papstBindBuffer[iCol]->RawData.nSize > 0)
                     {
-                        if (Failed2( bcp_moretext( hDBCBCP, 
-                            papstBindBuffer[iCol]->RawData.nSize,  
+                        if (Failed2( bcp_moretext( hDBCBCP,
+                            papstBindBuffer[iCol]->RawData.nSize,
                             papstBindBuffer[iCol]->RawData.pData ) ))
                         {
-                
+
                         }
                     }
                     if (Failed2( bcp_moretext( hDBCBCP, 0, NULL) ))
                     {
-                
+
                     }
                 }
                 else
                 {
                     if (Failed2( bcp_moretext( hDBCBCP, SQL_NULL_DATA, NULL) ))
                     {
-                
+
                     }
                 }
             }
@@ -1924,7 +1913,7 @@ OGRErr OGRMSSQLSpatialTableLayer::CreateFeatureBCP( OGRFeature *poFeature )
         int nRecNum = bcp_batch( hDBCBCP );
         if (nRecNum == -1)
             Failed2(nRecNum);
-        
+
         nBCPCount = 0;
     }
 
@@ -1954,7 +1943,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
         return CreateFeatureBCP( poFeature );
     }
 #endif
-    
+
     ClearStatement();
 
     CPLODBCSession* poSession = poDS->GetSession();
@@ -2020,11 +2009,11 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
 #ifdef SQL_SS_UDT
     int* bind_datalen = (int*)CPLMalloc(sizeof(int) * (nFieldCount + 1));
 #endif
-    
+
     int i;
     for( i = 0; i < nFieldCount; i++ )
     {
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
             continue;
 
         if (bNeedComma)
@@ -2059,14 +2048,14 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
                 if (poWriter.WriteSqlGeometry(pabyData, bind_datalen[bind_num]) == OGRERR_NONE)
                 {
                     SQLHANDLE ipd;
-                    if ((!poSession->Failed( SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1), 
+                    if ((!poSession->Failed( SQLBindParameter(oStatement.GetStatement(), (SQLUSMALLINT)(bind_num + 1),
                         SQL_PARAM_INPUT, SQL_C_BINARY, SQL_SS_UDT,
                         SQL_SS_LENGTH_UNLIMITED, 0, (SQLPOINTER)pabyData, bind_datalen[bind_num], (SQLLEN*)&bind_datalen[bind_num])))
                         && (!poSession->Failed(SQLGetStmtAttr(oStatement.GetStatement(), SQL_ATTR_IMP_PARAM_DESC, &ipd, 0, 0)))
-                        && (!poSession->Failed(SQLSetDescField(ipd, 1, SQL_CA_SS_UDT_TYPE_NAME, 
+                        && (!poSession->Failed(SQLSetDescField(ipd, 1, SQL_CA_SS_UDT_TYPE_NAME,
                             (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY? "geography" : "geometry"), SQL_NTS))))
                     {
-                        oStatement.Append( "?" );   
+                        oStatement.Append( "?" );
                         bind_buffer[bind_num] = pabyData;
                         ++bind_num;
                     }
@@ -2074,7 +2063,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
                     {
                         oStatement.Append( "null" );
                         CPLFree(pabyData);
-                    }       
+                    }
                 }
                 else
                 {
@@ -2191,7 +2180,7 @@ OGRErr OGRMSSQLSpatialTableLayer::ICreateFeature( OGRFeature *poFeature )
 
         for( i = 0; i < nFieldCount; i++ )
         {
-            if( !poFeature->IsFieldSet( i ) )
+            if( !poFeature->IsFieldSetAndNotNull( i ) )
                 continue;
 
             if (bNeedComma)
diff --git a/ogr/ogrsf_frmts/mysql/ogr_mysql.h b/ogr/ogrsf_frmts/mysql/ogr_mysql.h
index 306ee6a..07a6827 100644
--- a/ogr/ogrsf_frmts/mysql/ogr_mysql.h
+++ b/ogr/ogrsf_frmts/mysql/ogr_mysql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_mysql.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_mysql.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Declarations for MySQL OGR Driver Classes.
@@ -32,7 +32,6 @@
 #ifndef OGR_MYSQL_H_INCLUDED
 #define OGR_MYSQL_H_INCLUDED
 
-
 #ifdef _MSC_VER
 #pragma warning( push )
 #pragma warning( disable : 4324 ) /* 'my_alignment_imp<0x02>' : structure was padded due to __declspec(align()) */
@@ -95,24 +94,24 @@ class OGRMySQLLayer : public OGRLayer
 
     MYSQL_RES           *hResultSet;
 
-	int                 FetchSRSId();
+    int                 FetchSRSId();
 
   public:
                         OGRMySQLLayer();
     virtual             ~OGRMySQLLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
 
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 
     /* custom methods */
     virtual OGRFeature *RecordToFeature( char **papszRow, unsigned long * );
@@ -129,9 +128,9 @@ class OGRMySQLTableLayer : public OGRMySQLLayer
 
     OGRFeatureDefn     *ReadTableDefinition(const char *);
 
-    void                BuildWhere(void);
-    char               *BuildFields(void);
-    void                BuildFullQueryStatement(void);
+    void                BuildWhere();
+    char               *BuildFields();
+    void                BuildFullQueryStatement();
 
     char                *pszQuery;
     char                *pszWHERE;
@@ -141,36 +140,36 @@ class OGRMySQLTableLayer : public OGRMySQLLayer
 
   public:
                         OGRMySQLTableLayer( OGRMySQLDataSource *,
-                                         const char * pszName,
-                                         int bUpdate, int nSRSId = -2 );
-                        ~OGRMySQLTableLayer();
+                                            const char * pszName,
+                                            int bUpdate, int nSRSId = -2 );
+                        virtual ~OGRMySQLTableLayer();
 
     OGRErr              Initialize(const char* pszTableName);
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    void                SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    void                SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual OGRErr      SetAttributeFilter( const char * );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 
     void                SetLaunderFlag( int bFlag )
                                 { bLaunderColumnNames = bFlag; }
     void                SetPrecisionFlag( int bFlag )
                                 { bPreservePrecision = bFlag; }
 
-    virtual int         TestCapability( const char * );
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual int         TestCapability( const char * ) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
@@ -180,13 +179,10 @@ class OGRMySQLTableLayer : public OGRMySQLLayer
 
 class OGRMySQLResultLayer : public OGRMySQLLayer
 {
-    void                BuildFullQueryStatement(void);
+    void                BuildFullQueryStatement();
 
     char                *pszRawStatement;
 
-    // Layer srid.
-    int                 nSRSId;
-
   public:
                         OGRMySQLResultLayer( OGRMySQLDataSource *,
                                              const char * pszRawStatement,
@@ -195,11 +191,10 @@ class OGRMySQLResultLayer : public OGRMySQLLayer
 
     OGRFeatureDefn     *ReadResultDefinition();
 
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
-
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -217,7 +212,7 @@ class OGRMySQLDataSource : public OGRDataSource
 
     MYSQL              *hConn;
 
-    OGRErr              DeleteLayer( int iLayer );
+    OGRErr              DeleteLayer( int iLayer ) override;
 
     // We maintain a list of known SRID to reduce the number of trips to
     // the database to get SRSes.
@@ -229,11 +224,10 @@ class OGRMySQLDataSource : public OGRDataSource
 
   public:
                         OGRMySQLDataSource();
-                        ~OGRMySQLDataSource();
+                        virtual ~OGRMySQLDataSource();
 
     MYSQL              *GetConn() { return hConn; }
 
-
     int                 FetchSRSId( OGRSpatialReference * poSRS );
 
     OGRSpatialReference *FetchSRS( int nSRSId );
@@ -243,22 +237,21 @@ class OGRMySQLDataSource : public OGRDataSource
     int                 Open( const char *, char** papszOpenOptions, int bUpdate );
     int                 OpenTable( const char *, int bUpdate );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
     virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
-
+                                      char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     // nonstandard
 
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
index f10959e..e694bbd 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqldatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmysqldatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLDataSource class.
@@ -29,7 +28,6 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
 #include <string>
 #include "ogr_mysql.h"
 
@@ -41,7 +39,15 @@
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
 #endif
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
 #include <my_sys.h>
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
 #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
 #pragma GCC diagnostic pop
 #endif
@@ -52,7 +58,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmysqldatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrmysqldatasource.cpp 37230 2017-01-28 19:24:50Z rouault $");
 /************************************************************************/
 /*                         OGRMySQLDataSource()                         */
 /************************************************************************/
@@ -67,7 +73,7 @@ OGRMySQLDataSource::OGRMySQLDataSource() :
     panSRID(NULL),
     papoSRS(NULL),
     poLongResultLayer(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                        ~OGRMySQLDataSource()                         */
@@ -139,7 +145,7 @@ int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptionsIn
         const char* pszVal = CSLFetchNameValue(papszOpenOptionsIn, apszOpenOptions[i]);
         if( pszVal )
         {
-            if( osNewName[osNewName.size()-1] != ':' )
+            if( osNewName.back() != ':' )
                 osNewName += ",";
             if( i > 0 )
             {
@@ -300,9 +306,7 @@ int OGRMySQLDataSource::Open( const char * pszNewName, char** papszOpenOptionsIn
 /* -------------------------------------------------------------------- */
 /*      Get the schema of the available tables.                         */
 /* -------------------------------------------------------------------- */
-    int iRecord;
-
-    for( iRecord = 0;
+    for( int iRecord = 0;
          papszTableNames != NULL && papszTableNames[iRecord] != NULL;
          iRecord++ )
     {
@@ -355,6 +359,8 @@ int OGRMySQLDataSource::TestCapability( const char * pszCap )
         return TRUE;
     if( EQUAL(pszCap, ODsCDeleteLayer))
         return TRUE;
+    if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -372,7 +378,6 @@ OGRLayer *OGRMySQLDataSource::GetLayer( int iLayer )
         return papoLayers[iLayer];
 }
 
-
 /************************************************************************/
 /*                      InitializeMetadataTables()                      */
 /*                                                                      */
@@ -386,7 +391,7 @@ OGRErr OGRMySQLDataSource::InitializeMetadataTables()
 {
     const char*      pszCommand;
     MYSQL_RES       *hResult;
-    OGRErr	    eErr = OGRERR_NONE;
+    OGRErr          eErr = OGRERR_NONE;
 
     pszCommand = "DESCRIBE geometry_columns";
     if( mysql_query(GetConn(), pszCommand ) )
@@ -456,19 +461,13 @@ OGRErr OGRMySQLDataSource::InitializeMetadataTables()
 
 OGRSpatialReference *OGRMySQLDataSource::FetchSRS( int nId )
 {
-    char         szCommand[128];
-    char           **papszRow;
-    MYSQL_RES       *hResult;
-
     if( nId < 0 )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      First, we look through our SRID cache, is it there?             */
 /* -------------------------------------------------------------------- */
-    int  i;
-
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( panSRID[i] == nId )
             return papoSRS[i];
@@ -477,21 +476,21 @@ OGRSpatialReference *OGRMySQLDataSource::FetchSRS( int nId )
     OGRSpatialReference *poSRS = NULL;
 
     // make sure to attempt to free any old results
-    hResult = mysql_store_result( GetConn() );
+    MYSQL_RES *hResult = mysql_store_result( GetConn() );
     if( hResult != NULL )
         mysql_free_result( hResult );
     hResult = NULL;
 
+    char szCommand[128] = {};
     snprintf( szCommand, sizeof(szCommand),
-         "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
-         nId );
+              "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
+              nId );
 
     if( !mysql_query( GetConn(), szCommand ) )
         hResult = mysql_store_result( GetConn() );
 
     char  *pszWKT = NULL;
-    papszRow = NULL;
-
+    char **papszRow = NULL;
 
     if( hResult != NULL )
         papszRow = mysql_fetch_row( hResult );
@@ -528,8 +527,6 @@ OGRSpatialReference *OGRMySQLDataSource::FetchSRS( int nId )
     return poSRS;
 }
 
-
-
 /************************************************************************/
 /*                             FetchSRSId()                             */
 /*                                                                      */
@@ -540,29 +537,25 @@ OGRSpatialReference *OGRMySQLDataSource::FetchSRS( int nId )
 int OGRMySQLDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
 {
-    char           **papszRow;
-    MYSQL_RES       *hResult=NULL;
-
-    CPLString            osCommand;
-    char                *pszWKT = NULL;
-    int                 nSRSId;
-
     if( poSRS == NULL )
         return -1;
 
 /* -------------------------------------------------------------------- */
 /*      Translate SRS to WKT.                                           */
 /* -------------------------------------------------------------------- */
+    char *pszWKT = NULL;
     if( poSRS->exportToWkt( &pszWKT ) != OGRERR_NONE )
         return -1;
 
 /* -------------------------------------------------------------------- */
 /*      Try to find in the existing table.                              */
 /* -------------------------------------------------------------------- */
+    CPLString osCommand;
     osCommand.Printf(
              "SELECT srid FROM spatial_ref_sys WHERE srtext = '%s'",
              pszWKT );
 
+    MYSQL_RES *hResult = NULL;
     if( !mysql_query( GetConn(), osCommand ) )
         hResult = mysql_store_result( GetConn() );
 
@@ -572,13 +565,13 @@ int OGRMySQLDataSource::FetchSRSId( OGRSpatialReference * poSRS )
         mysql_free_result( hResult );
         hResult = NULL;
     }
-    papszRow = NULL;
+    char **papszRow = NULL;
     if( hResult != NULL )
         papszRow = mysql_fetch_row( hResult );
 
     if( papszRow != NULL && papszRow[0] != NULL )
     {
-        nSRSId = atoi(papszRow[0]);
+        const int nSRSId = atoi(papszRow[0]);
         if( hResult != NULL )
             mysql_free_result( hResult );
         hResult = NULL;
@@ -602,12 +595,9 @@ int OGRMySQLDataSource::FetchSRSId( OGRSpatialReference * poSRS )
         papszRow = mysql_fetch_row( hResult );
     }
 
-    if( papszRow != NULL && papszRow[0] != NULL )
-    {
-        nSRSId = atoi(papszRow[0]) + 1;
-    }
-    else
-        nSRSId = 1;
+    const int nSRSId = papszRow != NULL && papszRow[0] != NULL
+        ? atoi(papszRow[0]) + 1
+        : 1;
 
     if( hResult != NULL )
         mysql_free_result( hResult );
@@ -735,10 +725,9 @@ void OGRMySQLDataSource::ReleaseResultSet( OGRLayer * poLayer )
 char *OGRMySQLDataSource::LaunderName( const char *pszSrcName )
 
 {
-    char    *pszSafeName = CPLStrdup( pszSrcName );
-    int     i;
+    char *pszSafeName = CPLStrdup( pszSrcName );
 
-    for( i = 0; pszSafeName[i] != '\0'; i++ )
+    for( int i = 0; pszSafeName[i] != '\0'; i++ )
     {
         pszSafeName[i] = (char) tolower( pszSafeName[i] );
         if( pszSafeName[i] == '-' || pszSafeName[i] == '#' )
@@ -782,7 +771,6 @@ void OGRMySQLDataSource::InterruptLongResult()
     }
 }
 
-
 /************************************************************************/
 /*                            DeleteLayer()                             */
 /************************************************************************/
@@ -825,7 +813,6 @@ OGRErr OGRMySQLDataSource::DeleteLayer( int iLayer)
         ReportError( osCommand );
         return OGRERR_FAILURE;
     }
-
 }
 
 /************************************************************************/
@@ -839,22 +826,20 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
                               char ** papszOptions )
 
 {
-    MYSQL_RES           *hResult=NULL;
-    CPLString            osCommand;
-    const char          *pszGeometryType;
-    const char		*pszGeomColumnName;
-    const char		*pszExpectedFIDName;
-    char                *pszLayerName;
-    // int                 nDimension = 3; // MySQL only supports 2d currently
-
+    MYSQL_RES  *hResult=NULL;
+    CPLString   osCommand;
+    const char *pszGeometryType;
+    const char *pszGeomColumnName;
+    const char *pszExpectedFIDName;
+    char       *pszLayerName;
+    // int        nDimension = 3; // MySQL only supports 2d currently
 
 /* -------------------------------------------------------------------- */
 /*      Make sure there isn't an active transaction already.            */
 /* -------------------------------------------------------------------- */
     InterruptLongResult();
 
-
-    if( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) )
+    if( CPLFetchBool(papszOptions, "LAUNDER", true) )
         pszLayerName = LaunderName( pszLayerNameIn );
     else
         pszLayerName = CPLStrdup( pszLayerNameIn );
@@ -869,8 +854,7 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
 
-    int iLayer;
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
         {
@@ -903,13 +887,15 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
     if (!pszExpectedFIDName)
         pszExpectedFIDName="OGR_FID";
 
-    int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE);
+    const bool bFID64 = CPLFetchBool(papszOptions, "FID64", false);
     const char* pszFIDType = bFID64 ? "BIGINT": "INT";
 
-
     CPLDebug("MYSQL","Geometry Column Name %s.", pszGeomColumnName);
     CPLDebug("MYSQL","FID Column Name %s.", pszExpectedFIDName);
 
+    const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
+    const bool bHasSI = ( eType != wkbNone && (pszSI == NULL || CPLTestBool(pszSI)) );
+
     if( wkbFlatten(eType) == wkbNone )
     {
         osCommand.Printf(
@@ -922,8 +908,9 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
         osCommand.Printf(
                  "CREATE TABLE `%s` ( "
                  "   %s %s UNIQUE NOT NULL AUTO_INCREMENT, "
-                 "   %s GEOMETRY NOT NULL )",
-                 pszLayerName, pszExpectedFIDName, pszFIDType, pszGeomColumnName );
+                 "   %s GEOMETRY %s)",
+                 pszLayerName, pszExpectedFIDName, pszFIDType, pszGeomColumnName,
+                 bHasSI ? "NOT NULL" : "");
     }
 
     if( CSLFetchNameValue( papszOptions, "ENGINE" ) != NULL )
@@ -994,11 +981,7 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
 /* -------------------------------------------------------------------- */
     if( eType != wkbNone )
     {
-        int nCoordDimension;
-        if( eType == wkbFlatten(eType) )
-            nCoordDimension = 2;
-        else
-            nCoordDimension = 3;
+        const int nCoordDimension = eType == wkbFlatten(eType) ? 2 : 3;
 
         pszGeometryType = OGRToOGCGeomType(eType);
 
@@ -1048,9 +1031,7 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
 /*      We're doing this before we add geometry and record to the table */
 /*      so this may not be exactly the best way to do it.               */
 /* -------------------------------------------------------------------- */
-    const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
-
-    if( eType != wkbNone && (pszSI == NULL || CPLTestBool(pszSI)) )
+    if( bHasSI )
     {
         osCommand.Printf(
                  "ALTER TABLE `%s` ADD SPATIAL INDEX(`%s`) ",
@@ -1083,8 +1064,8 @@ OGRMySQLDataSource::ICreateLayer( const char * pszLayerNameIn,
     if( eType != wkbNone )
         poLayer->GetLayerDefn()->GetGeomFieldDefn(0)->SetNullable(FALSE);
 
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
-    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
+    poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", true) );
+    poLayer->SetPrecisionFlag( CPLFetchBool(papszOptions, "PRECISION", true));
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp
index 7c4b217..50c0b6d 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqldriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmysqldriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLDriver class.
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrmysqldriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrmysqldriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 static CPLMutex* hMutex = NULL;
 static int   bInitialized = FALSE;
@@ -101,7 +100,6 @@ static GDALDataset *OGRMySQLDriverOpen( GDALOpenInfo* poOpenInfo )
         return poDS;
 }
 
-
 /************************************************************************/
 /*                               Create()                               */
 /************************************************************************/
@@ -117,7 +115,6 @@ static GDALDataset *OGRMySQLDriverCreate( const char * pszName,
 
     poDS = new OGRMySQLDataSource();
 
-
     if( !poDS->Open( pszName, NULL, TRUE ) )
     {
         delete poDS;
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp
index 7fcdb33..2b45432 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqllayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmysqllayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLLayer class.
@@ -32,35 +31,27 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrmysqllayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrmysqllayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                           OGRMySQLLayer()                            */
 /************************************************************************/
 
 OGRMySQLLayer::OGRMySQLLayer() :
-    nGeomType(0)
-{
-    poDS = NULL;
-
-    pszGeomColumn = NULL;
-    pszGeomColumnTable = NULL;
-    pszFIDColumn = NULL;
-    pszQueryStatement = NULL;
-
-    bHasFid = FALSE;
-    pszFIDColumn = NULL;
-
-    iNextShapeId = 0;
-    nResultOffset = 0;
-
-    poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet.
-
-    poFeatureDefn = NULL;
-
-    hResultSet = NULL;
-}
+    poFeatureDefn(NULL),
+    poSRS(NULL),
+    nSRSId(-2), // we haven't even queried the database for it yet.
+    iNextShapeId(0),
+    poDS(NULL),
+    pszQueryStatement(NULL),
+    nResultOffset(0),
+    pszGeomColumn(NULL),
+    pszGeomColumnTable(NULL),
+    nGeomType(0),
+    bHasFid(FALSE),
+    pszFIDColumn(NULL),
+    hResultSet(NULL)
+{}
 
 /************************************************************************/
 /*                           ~OGRMySQLLayer()                           */
@@ -149,7 +140,6 @@ OGRFeature *OGRMySQLLayer::RecordToFeature( char **papszRow,
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
-    int         iField;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     poFeature->SetFID( iNextShapeId );
@@ -158,11 +148,10 @@ OGRFeature *OGRMySQLLayer::RecordToFeature( char **papszRow,
 /* ==================================================================== */
 /*      Transfer all result fields we can.                              */
 /* ==================================================================== */
-    for( iField = 0;
+    for( int iField = 0;
          iField < (int) mysql_num_fields(hResultSet);
          iField++ )
     {
-        int     iOGRField;
         MYSQL_FIELD *psMSField = mysql_fetch_field(hResultSet);
 
 /* -------------------------------------------------------------------- */
@@ -182,8 +171,10 @@ OGRFeature *OGRMySQLLayer::RecordToFeature( char **papszRow,
 
         if( papszRow[iField] == NULL )
         {
-//            CPLDebug("MYSQL", "%s was null for %d", psMSField->name,
-//                     iNextShapeId);
+            const int iOGRField = poFeatureDefn->GetFieldIndex(psMSField->name);
+            if( iOGRField >= 0 )
+                poFeature->SetFieldNull( iOGRField );
+
             continue;
         }
 
@@ -209,11 +200,10 @@ OGRFeature *OGRMySQLLayer::RecordToFeature( char **papszRow,
             continue;
         }
 
-
 /* -------------------------------------------------------------------- */
 /*      Transfer regular data fields.                                   */
 /* -------------------------------------------------------------------- */
-        iOGRField = poFeatureDefn->GetFieldIndex(psMSField->name);
+        const int iOGRField = poFeatureDefn->GetFieldIndex(psMSField->name);
         if( iOGRField < 0 )
             continue;
 
@@ -326,19 +316,18 @@ const char *OGRMySQLLayer::GetGeometryColumn()
         return "";
 }
 
-
 /************************************************************************/
 /*                         FetchSRSId()                                 */
 /************************************************************************/
 
 int OGRMySQLLayer::FetchSRSId()
 {
-	CPLString        osCommand;
+    CPLString        osCommand;
     char           **papszRow;
 
     if( hResultSet != NULL )
         mysql_free_result( hResultSet );
-		hResultSet = NULL;
+    hResultSet = NULL;
 
     osCommand.Printf(
              "SELECT srid FROM geometry_columns "
@@ -360,9 +349,9 @@ int OGRMySQLLayer::FetchSRSId()
     // make sure to free our results
     if( hResultSet != NULL )
         mysql_free_result( hResultSet );
-		hResultSet = NULL;
+    hResultSet = NULL;
 
-	return nSRSId;
+    return nSRSId;
 }
 
 /************************************************************************/
@@ -372,8 +361,6 @@ int OGRMySQLLayer::FetchSRSId()
 OGRSpatialReference *OGRMySQLLayer::GetSpatialRef()
 
 {
-
-
     if( poSRS == NULL && nSRSId > -1 )
     {
         poSRS = poDS->FetchSRS( nSRSId );
@@ -384,5 +371,4 @@ OGRSpatialReference *OGRMySQLLayer::GetSpatialRef()
     }
 
     return poSRS;
-
 }
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp
index 0297f06..f0a6251 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqlresultlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmysqlresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLResultLayer class.
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_mysql.h"
 
-CPL_CVSID("$Id: ogrmysqlresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrmysqlresultlayer.cpp 36384 2016-11-21 12:13:10Z rouault $");
 
 /************************************************************************/
 /*                        OGRMySQLResultLayer()                         */
@@ -40,18 +39,13 @@ CPL_CVSID("$Id: ogrmysqlresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 OGRMySQLResultLayer::OGRMySQLResultLayer( OGRMySQLDataSource *poDSIn,
                                           const char * pszRawQueryIn,
-                                          MYSQL_RES *hResultSetIn )
+                                          MYSQL_RES *hResultSetIn ) :
+    pszRawStatement(CPLStrdup(pszRawQueryIn))
 {
     poDS = poDSIn;
-
     iNextShapeId = 0;
-
-    pszRawStatement = CPLStrdup(pszRawQueryIn);
-
     hResultSet = hResultSetIn;
-
     BuildFullQueryStatement();
-
     poFeatureDefn = ReadResultDefinition();
 }
 
@@ -74,25 +68,21 @@ OGRMySQLResultLayer::~OGRMySQLResultLayer()
 OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
 
 {
-
 /* -------------------------------------------------------------------- */
 /*      Parse the returned table information.                           */
 /* -------------------------------------------------------------------- */
     OGRFeatureDefn *poDefn = new OGRFeatureDefn( "sql_statement" );
     SetDescription( poDefn->GetName() );
-    int            iRawField;
 
     poDefn->Reference();
-    int width;
-    int precision;
 
     mysql_field_seek( hResultSet, 0 );
-    for( iRawField = 0;
+    for( int iRawField = 0;
          iRawField < (int) mysql_num_fields(hResultSet);
          iRawField++ )
     {
         MYSQL_FIELD *psMSField = mysql_fetch_field( hResultSet );
-        OGRFieldDefn    oField( psMSField->name, OFTString);
+        OGRFieldDefn oField( psMSField->name, OFTString);
 
         switch( psMSField->type )
         {
@@ -101,22 +91,24 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
           case FIELD_TYPE_LONG:
           case FIELD_TYPE_INT24:
           case FIELD_TYPE_LONGLONG:
+          {
             oField.SetType( OFTInteger );
-            width = (int)psMSField->length;
+            const int width = (int)psMSField->length;
             oField.SetWidth(width);
             poDefn->AddFieldDefn( &oField );
             break;
-
+          }
           case FIELD_TYPE_DECIMAL:
 #ifdef FIELD_TYPE_NEWDECIMAL
           case FIELD_TYPE_NEWDECIMAL:
 #endif
+          {
             oField.SetType( OFTReal );
 
             // a bunch of hackery to munge the widths that MySQL gives
             // us into corresponding widths and precisions for OGR
-            precision =    (int)psMSField->decimals;
-            width = (int)psMSField->length;
+            const int precision = (int)psMSField->decimals;
+            int width = (int)psMSField->length;
             if (!precision)
                 width = width - 1;
             width = width - precision;
@@ -125,7 +117,7 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
             oField.SetPrecision(precision);
             poDefn->AddFieldDefn( &oField );
             break;
-
+          }
           case FIELD_TYPE_FLOAT:
           case FIELD_TYPE_DOUBLE:
          /* MYSQL_FIELD is always reporting ->length = 22 and ->decimals = 31
@@ -135,8 +127,9 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
             as 31. */
          /* Assuming that a length of 22 means no particular width and 31
             decimals means no particular precision. */
-            width = (int)psMSField->length;
-            precision = (int)psMSField->decimals;
+          {
+            const int width = (int)psMSField->length;
+            const int precision = (int)psMSField->decimals;
             oField.SetType( OFTReal );
             if( width != 22 )
                 oField.SetWidth(width);
@@ -144,38 +137,43 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
                 oField.SetPrecision(precision);
             poDefn->AddFieldDefn( &oField );
             break;
-
+          }
           case FIELD_TYPE_DATE:
+          {
             oField.SetType( OFTDate );
             oField.SetWidth(0);
             poDefn->AddFieldDefn( &oField );
             break;
-
+          }
           case FIELD_TYPE_TIME:
+          {
             oField.SetType( OFTTime );
             oField.SetWidth(0);
             poDefn->AddFieldDefn( &oField );
             break;
-
+          }
           case FIELD_TYPE_TIMESTAMP:
           case FIELD_TYPE_DATETIME:
+          {
             oField.SetType( OFTDateTime );
             oField.SetWidth(0);
             poDefn->AddFieldDefn( &oField );
             break;
-
+          }
           case FIELD_TYPE_YEAR:
           case FIELD_TYPE_STRING:
           case FIELD_TYPE_VAR_STRING:
+          {
             oField.SetType( OFTString );
             oField.SetWidth((int)psMSField->length);
             poDefn->AddFieldDefn( &oField );
             break;
-
+          }
           case FIELD_TYPE_TINY_BLOB:
           case FIELD_TYPE_MEDIUM_BLOB:
           case FIELD_TYPE_LONG_BLOB:
           case FIELD_TYPE_BLOB:
+          {
             if( psMSField->charsetnr == 63 )
                 oField.SetType( OFTBinary );
             else
@@ -183,15 +181,16 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
             oField.SetWidth((int)psMSField->max_length);
             poDefn->AddFieldDefn( &oField );
             break;
-
+          }
           case FIELD_TYPE_GEOMETRY:
+          {
             if (pszGeomColumn == NULL)
             {
                 pszGeomColumnTable = CPLStrdup( psMSField->table);
                 pszGeomColumn = CPLStrdup( psMSField->name);
             }
             break;
-
+          }
           default:
             // any other field we ignore.
             break;
@@ -224,7 +223,6 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
         }
     }
 
-
     poDefn->SetGeomType( wkbNone );
 
     if (pszGeomColumn)
@@ -242,7 +240,7 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
 
         if( hResultSet != NULL )
             mysql_free_result( hResultSet );
-     		hResultSet = NULL;
+        hResultSet = NULL;
 
         if( !mysql_query( poDS->GetConn(), osCommand ) )
             hResultSet = mysql_store_result( poDS->GetConn() );
@@ -251,7 +249,6 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
         if( hResultSet != NULL )
             papszRow = mysql_fetch_row( hResultSet );
 
-
         if( papszRow != NULL && papszRow[0] != NULL )
         {
             pszType = papszRow[0];
@@ -261,10 +258,9 @@ OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
             poDefn->SetGeomType( l_nGeomType );
         }
 
-		nSRSId = FetchSRSId();
+        nSRSId = FetchSRSId();
     }
 
-
     return poDefn;
 }
 
diff --git a/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp b/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
index 0492f5f..e5a47ac 100644
--- a/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
+++ b/ogr/ogrsf_frmts/mysql/ogrmysqltablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrmysqltablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRMySQLTableLayer class.
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_mysql.h"
 
-CPL_CVSID("$Id: ogrmysqltablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrmysqltablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGRMySQLTableLayer()                         */
@@ -41,23 +40,22 @@ CPL_CVSID("$Id: ogrmysqltablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 OGRMySQLTableLayer::OGRMySQLTableLayer( OGRMySQLDataSource *poDSIn,
                                         CPL_UNUSED const char * pszTableName,
-                                        int bUpdate, int nSRSIdIn )
+                                        int bUpdate, int nSRSIdIn ) :
+    bUpdateAccess(bUpdate),
+    pszQuery(NULL),
+    pszWHERE(CPLStrdup("")),
+    bLaunderColumnNames(TRUE),
+    bPreservePrecision(FALSE)
 {
     poDS = poDSIn;
 
-    pszQuery = NULL;
-    pszWHERE = CPLStrdup( "" );
     pszQueryStatement = NULL;
 
-    bUpdateAccess = bUpdate;
-
     iNextShapeId = 0;
 
     nSRSId = nSRSIdIn;
 
     poFeatureDefn = NULL;
-    bLaunderColumnNames = TRUE;
-    bPreservePrecision = FALSE;
 
     SetDescription( pszTableName );
 }
@@ -73,7 +71,6 @@ OGRMySQLTableLayer::~OGRMySQLTableLayer()
     CPLFree( pszWHERE );
 }
 
-
 /************************************************************************/
 /*                        Initialize()                                  */
 /*                                                                      */
@@ -139,16 +136,13 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
 
     while( (papszRow = mysql_fetch_row( hResult )) != NULL )
     {
-        const char      *pszType;
         OGRFieldDefn    oField( papszRow[0], OFTString);
-        int             nLenType;
-
-        pszType = papszRow[1];
 
+        const char *pszType = papszRow[1];
         if( pszType == NULL )
             continue;
 
-        nLenType = (int)strlen(pszType);
+        int nLenType = (int)strlen(pszType);
 
         if( EQUAL(pszType,"varbinary")
             || (nLenType>=4 && EQUAL(pszType+nLenType-4,"blob")))
@@ -160,7 +154,6 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
                  || (nLenType>=3 && EQUAL(pszType+nLenType-3,"set")) )
         {
             oField.SetType( OFTString );
-
         }
         else if( STARTS_WITH_CI(pszType, "char")  )
         {
@@ -176,7 +169,6 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
 
             CSLDestroy( papszTokens );
             oField.SetType( OFTString );
-
         }
 
         if(nLenType>=4 && EQUAL(pszType+nLenType-4,"text"))
@@ -240,8 +232,6 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
                 oField.SetPrecision(atoi(papszTokens[2]));
             }
             CSLDestroy( papszTokens );
-
-
         }
         else if( STARTS_WITH_CI(pszType, "float") )
         {
@@ -334,8 +324,12 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
                 pszDefault[0] != '\'' &&
                 CPLGetValueType(pszDefault) == CPL_VALUE_STRING )
             {
-                int nYear, nMonth, nDay, nHour, nMinute;
-                float fSecond;
+                int nYear = 0;
+                int nMonth = 0;
+                int nDay = 0;
+                int nHour = 0;
+                int nMinute = 0;
+                float fSecond = 0.0f;
                 if( oField.GetType() == OFTDateTime &&
                     sscanf(pszDefault, "%d-%d-%d %d:%d:%f", &nYear, &nMonth, &nDay,
                                 &nHour, &nMinute, &fSecond) == 6 )
@@ -409,7 +403,6 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
                 l_nGeomType = wkbSetZ(l_nGeomType);
 
             poDefn->SetGeomType( l_nGeomType );
-
         }
         else if (eForcedGeomType != wkbUnknown)
             poDefn->SetGeomType(eForcedGeomType);
@@ -419,7 +412,7 @@ OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
 
         if( hResult != NULL )
             mysql_free_result( hResult );   //Free our query results for finding type.
-			hResult = NULL;
+        hResult = NULL;
     }
 
     // Fetch the SRID for this table now
@@ -442,8 +435,6 @@ void OGRMySQLTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     ResetReading();
 }
 
-
-
 /************************************************************************/
 /*                             BuildWhere()                             */
 /*                                                                      */
@@ -477,10 +468,10 @@ void OGRMySQLTableLayer::BuildWhere()
                 sEnvelope.MinX, sEnvelope.MinY);
 
         snprintf( pszWHERE, nWHERELen,
-                 "WHERE MBRIntersects(GeomFromText('%s'), `%s`)",
+                 "WHERE MBRIntersects(GeomFromText('%s', '%d'), `%s`)",
                  szEnvelope,
+                 nSRSId,
                  pszGeomColumn);
-
     }
 
     if( pszQuery != NULL )
@@ -542,22 +533,17 @@ void OGRMySQLTableLayer::ResetReading()
 char *OGRMySQLTableLayer::BuildFields()
 
 {
-    int         i;
-    size_t      nSize;
-    char        *pszFieldList;
-
-    nSize = 25;
+    size_t nSize = 25;
     if( pszGeomColumn )
         nSize += strlen(pszGeomColumn);
 
     if( bHasFid )
         nSize += strlen(pszFIDColumn);
 
-
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
         nSize += strlen(poFeatureDefn->GetFieldDefn(i)->GetNameRef()) + 6;
 
-    pszFieldList = (char *) CPLMalloc(nSize);
+    char *pszFieldList = (char *) CPLMalloc(nSize);
     pszFieldList[0] = '\0';
 
     if( bHasFid && poFeatureDefn->GetFieldIndex( pszFIDColumn ) == -1 )
@@ -568,16 +554,16 @@ char *OGRMySQLTableLayer::BuildFields()
         if( strlen(pszFieldList) > 0 )
             strcat( pszFieldList, ", " );
 
-	/* ------------------------------------------------------------ */
-	/*      Geometry returned from MySQL is as WKB, with the        */
+        /* ------------------------------------------------------------ */
+        /*      Geometry returned from MySQL is as WKB, with the        */
         /*      first 4 bytes being an int that defines the SRID        */
         /*      and the rest being the WKB.                             */
-	/* ------------------------------------------------------------ */
+        /* ------------------------------------------------------------ */
         snprintf( pszFieldList+strlen(pszFieldList), nSize-strlen(pszFieldList),
                  "`%s` `%s`", pszGeomColumn, pszGeomColumn );
     }
 
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
 
@@ -602,14 +588,14 @@ OGRErr OGRMySQLTableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
     CPLFree(m_pszAttrQueryString);
-    m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
+    m_pszAttrQueryString = pszQueryIn ? CPLStrdup(pszQueryIn) : NULL;
 
-    CPLFree( this->pszQuery );
+    CPLFree( pszQuery );
 
     if( pszQueryIn == NULL || strlen(pszQueryIn) == 0 )
-        this->pszQuery = NULL;
+        pszQuery = NULL;
     else
-        this->pszQuery = CPLStrdup( pszQueryIn );
+        pszQuery = CPLStrdup( pszQueryIn );
 
     BuildWhere();
 
@@ -690,7 +676,6 @@ OGRErr OGRMySQLTableLayer::DeleteFeature( GIntBig nFID )
     MYSQL_RES           *hResult=NULL;
     CPLString           osCommand;
 
-
 /* -------------------------------------------------------------------- */
 /*      We can only delete features if we have a well defined FID       */
 /*      column to target.                                               */
@@ -702,7 +687,6 @@ OGRErr OGRMySQLTableLayer::DeleteFeature( GIntBig nFID )
                   "in tables without\n a recognised FID column.",
                   nFID );
         return OGRERR_FAILURE;
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -729,7 +713,6 @@ OGRErr OGRMySQLTableLayer::DeleteFeature( GIntBig nFID )
     return mysql_affected_rows( poDS->GetConn() ) > 0 ? OGRERR_NONE : OGRERR_NON_EXISTING_FEATURE;
 }
 
-
 /************************************************************************/
 /*                       ICreateFeature()                                */
 /************************************************************************/
@@ -737,9 +720,8 @@ OGRErr OGRMySQLTableLayer::DeleteFeature( GIntBig nFID )
 OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
 
 {
-    MYSQL_RES           *hResult=NULL;
-    CPLString           osCommand;
-    int                 i, bNeedComma = FALSE;
+    int bNeedComma = FALSE;
+    CPLString osCommand;
 
 /* -------------------------------------------------------------------- */
 /*      Form the INSERT command.                                        */
@@ -761,7 +743,7 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
         bNeedComma = TRUE;
     }
 
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         if( !poFeature->IsFieldSet( i ) )
             continue;
@@ -799,13 +781,12 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
                 CPLString().Printf(
                     "GeometryFromText('%s',%d) ", pszWKT, nSRSId );
 
-            OGRFree( pszWKT );
+            CPLFree( pszWKT );
         }
         else
             osCommand += "''";
     }
 
-
     // Set the FID
     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     {
@@ -825,7 +806,7 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
             }
 
             // make sure to attempt to free results of successful queries
-            hResult = mysql_store_result( poDS->GetConn() );
+            MYSQL_RES *hResult = mysql_store_result( poDS->GetConn() );
             if( hResult != NULL )
                 mysql_free_result( hResult );
             hResult = NULL;
@@ -839,7 +820,7 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
         bNeedComma = TRUE;
     }
 
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         if( !poFeature->IsFieldSet( i ) )
             continue;
@@ -851,17 +832,19 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
 
         const char *pszStrValue = poFeature->GetFieldAsString(i);
 
-        if( poFeatureDefn->GetFieldDefn(i)->GetType() != OFTInteger
+        if( poFeature->IsFieldNull(i) )
+        {
+            osCommand += "NULL";
+        }
+        else if( poFeatureDefn->GetFieldDefn(i)->GetType() != OFTInteger
                  && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTInteger64
                  && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTReal
                  && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTBinary )
         {
-            int         iChar;
-
-            //We need to quote and escape string fields.
+            // We need to quote and escape string fields.
             osCommand += "'";
 
-            for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
+            for( int iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
             {
                 if( poFeatureDefn->GetFieldDefn(i)->GetType() != OFTIntegerList
                     && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTInteger64List
@@ -903,7 +886,6 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
         {
             osCommand += pszStrValue;
         }
-
     }
 
     osCommand += ")";
@@ -928,7 +910,7 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
 
         // make sure to attempt to free results
-        hResult = mysql_store_result( poDS->GetConn() );
+        MYSQL_RES *hResult = mysql_store_result( poDS->GetConn() );
         if( hResult != NULL )
             mysql_free_result( hResult );
         hResult = NULL;
@@ -941,14 +923,14 @@ OGRErr OGRMySQLTableLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
     // make sure to attempt to free results of successful queries
-    hResult = mysql_store_result( poDS->GetConn() );
+    MYSQL_RES *hResult = mysql_store_result( poDS->GetConn() );
     if( hResult != NULL )
         mysql_free_result( hResult );
     hResult = NULL;
 
     return OGRERR_NONE;
-
 }
+
 /************************************************************************/
 /*                            CreateField()                             */
 /************************************************************************/
@@ -1087,7 +1069,6 @@ OGRErr OGRMySQLTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                             GetFeature()                             */
 /************************************************************************/
@@ -1158,7 +1139,7 @@ OGRFeature *OGRMySQLTableLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
     if( hResultSet != NULL )
         mysql_free_result( hResultSet );
- 		hResultSet = NULL;
+    hResultSet = NULL;
 
     return poFeature;
 }
@@ -1218,16 +1199,16 @@ GIntBig OGRMySQLTableLayer::GetFeatureCount( CPL_UNUSED int bForce )
 }
 
 /************************************************************************/
-/*                          GetExtent()					*/
+/*                          GetExtent()                                 */
 /*                                                                      */
 /*      Retrieve the MBR of the MySQL table.  This should be made more  */
 /*      in the future when MySQL adds support for a single MBR query    */
-/*      like PostgreSQL.						*/
+/*      like PostgreSQL.                                                */
 /************************************************************************/
 
 OGRErr OGRMySQLTableLayer::GetExtent(OGREnvelope *psExtent, CPL_UNUSED int bForce )
 {
-	if( GetLayerDefn()->GetGeomType() == wkbNone )
+    if( GetLayerDefn()->GetGeomType() == wkbNone )
     {
         psExtent->MinX = 0.0;
         psExtent->MaxX = 0.0;
@@ -1237,67 +1218,67 @@ OGRErr OGRMySQLTableLayer::GetExtent(OGREnvelope *psExtent, CPL_UNUSED int bForc
         return OGRERR_FAILURE;
     }
 
-	OGREnvelope oEnv;
-	CPLString   osCommand;
-	GBool       bExtentSet = FALSE;
+    OGREnvelope oEnv;
+    CPLString   osCommand;
+    GBool       bExtentSet = FALSE;
 
-	osCommand.Printf( "SELECT Envelope(`%s`) FROM `%s`;", pszGeomColumn, pszGeomColumnTable);
+    osCommand.Printf( "SELECT Envelope(`%s`) FROM `%s`;", pszGeomColumn, pszGeomColumnTable);
 
-	if (mysql_query(poDS->GetConn(), osCommand) == 0)
-	{
-		MYSQL_RES* result = mysql_use_result(poDS->GetConn());
-		if ( result == NULL )
+    if (mysql_query(poDS->GetConn(), osCommand) == 0)
+    {
+        MYSQL_RES* result = mysql_use_result(poDS->GetConn());
+        if ( result == NULL )
         {
             poDS->ReportError( "mysql_use_result() failed on extents query." );
             return OGRERR_FAILURE;
         }
 
-		MYSQL_ROW row;
-		unsigned long *panLengths = NULL;
-		while ((row = mysql_fetch_row(result)) != NULL)
-		{
-			if (panLengths == NULL)
-			{
-				panLengths = mysql_fetch_lengths( result );
-				if ( panLengths == NULL )
-				{
-					poDS->ReportError( "mysql_fetch_lengths() failed on extents query." );
-					return OGRERR_FAILURE;
-				}
-			}
-
-			OGRGeometry *poGeometry = NULL;
-			// Geometry columns will have the first 4 bytes contain the SRID.
-			OGRGeometryFactory::createFromWkb(((GByte *)row[0]) + 4,
-											  NULL,
-											  &poGeometry,
-											  static_cast<int>(panLengths[0] - 4) );
-
-			if ( poGeometry != NULL )
-			{
-				if (poGeometry && !bExtentSet)
-				{
-					poGeometry->getEnvelope(psExtent);
-					bExtentSet = TRUE;
-				}
-				else if (poGeometry)
-				{
-					poGeometry->getEnvelope(&oEnv);
-					if (oEnv.MinX < psExtent->MinX)
-						psExtent->MinX = oEnv.MinX;
-					if (oEnv.MinY < psExtent->MinY)
-						psExtent->MinY = oEnv.MinY;
-					if (oEnv.MaxX > psExtent->MaxX)
-						psExtent->MaxX = oEnv.MaxX;
-					if (oEnv.MaxY > psExtent->MaxY)
-						psExtent->MaxY = oEnv.MaxY;
-				}
-				delete poGeometry;
-			}
-		}
-
-		mysql_free_result(result);
-	}
-
-	return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
+        MYSQL_ROW row;
+        unsigned long *panLengths = NULL;
+        while ((row = mysql_fetch_row(result)) != NULL)
+        {
+            if (panLengths == NULL)
+            {
+                panLengths = mysql_fetch_lengths( result );
+                if ( panLengths == NULL )
+                {
+                    poDS->ReportError( "mysql_fetch_lengths() failed on extents query." );
+                    return OGRERR_FAILURE;
+                }
+            }
+
+            OGRGeometry *poGeometry = NULL;
+            // Geometry columns will have the first 4 bytes contain the SRID.
+            OGRGeometryFactory::createFromWkb(((GByte *)row[0]) + 4,
+                                              NULL,
+                                              &poGeometry,
+                                              static_cast<int>(panLengths[0] - 4) );
+
+            if ( poGeometry != NULL )
+            {
+                if (poGeometry && !bExtentSet)
+                {
+                    poGeometry->getEnvelope(psExtent);
+                    bExtentSet = TRUE;
+                }
+                else if (poGeometry)
+                {
+                    poGeometry->getEnvelope(&oEnv);
+                    if (oEnv.MinX < psExtent->MinX)
+                        psExtent->MinX = oEnv.MinX;
+                    if (oEnv.MinY < psExtent->MinY)
+                        psExtent->MinY = oEnv.MinY;
+                    if (oEnv.MaxX > psExtent->MaxX)
+                        psExtent->MaxX = oEnv.MaxX;
+                    if (oEnv.MaxY > psExtent->MaxY)
+                        psExtent->MaxY = oEnv.MaxY;
+                }
+                delete poGeometry;
+            }
+        }
+
+        mysql_free_result(result);
+    }
+
+    return bExtentSet ? OGRERR_NONE : OGRERR_FAILURE;
 }
diff --git a/ogr/ogrsf_frmts/nas/nashandler.cpp b/ogr/ogrsf_frmts/nas/nashandler.cpp
index 727848b..01da31b 100644
--- a/ogr/ogrsf_frmts/nas/nashandler.cpp
+++ b/ogr/ogrsf_frmts/nas/nashandler.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: nashandler.cpp 34726 2016-07-19 21:49:14Z jef $
  *
  * Project:  NAS Reader
  * Purpose:  Implementation of NASHandler class.
@@ -32,8 +31,9 @@
 #include "nasreaderp.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogr_xerces.h"
 
-static const int MAX_TOKEN_SIZE = 1000;
+CPL_CVSID("$Id: nashandler.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /*
   Update modes:
@@ -74,7 +74,6 @@ static const int MAX_TOKEN_SIZE = 1000;
         </geaenderteObjekte>
 */
 
-
 /************************************************************************/
 /*                             NASHandler()                             */
 /************************************************************************/
@@ -92,7 +91,7 @@ NASHandler::NASHandler( NASReader *poReader ) :
     m_bInUpdate(false),
     m_bInUpdateProperty(false),
     m_nDepthElement(0)
-{ }
+{}
 
 /************************************************************************/
 /*                            ~NASHandler()                             */
@@ -116,19 +115,14 @@ CPLString NASHandler::GetAttributes(const Attributes* attrs)
     for(unsigned int i=0; i < attrs->getLength(); i++)
     {
         osRes += " ";
-        char *pszString = tr_strdup(attrs->getQName(i));
-        osRes += pszString;
-        CPLFree( pszString );
+        osRes += transcode(attrs->getQName(i), m_osAttrName);
         osRes += "=\"";
-        pszString = tr_strdup(attrs->getValue(i));
-        osRes += pszString;
-        CPLFree( pszString );
+        osRes += transcode(attrs->getValue(i), m_osAttrValue);
         osRes += "\"";
     }
     return osRes;
 }
 
-
 /************************************************************************/
 /*                            startElement()                            */
 /************************************************************************/
@@ -139,10 +133,9 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
                                const Attributes& attrs )
 
 {
-    char        szElementName[MAX_TOKEN_SIZE];
     GMLReadState *poState = m_poReader->GetState();
 
-    tr_strcpy( szElementName, localname );
+    transcode( localname, m_osElementName );
 
     if ( ( m_bIgnoreFeature && m_nDepth >= m_nDepthFeature ) ||
          ( m_osIgnoredElement != "" && m_nDepth >= m_nDepthElement ) )
@@ -153,10 +146,10 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
 
     // ignore attributes of external references and "objektkoordinaten"
     // (see PostNAS #3 and #15)
-    if ( EQUAL( szElementName, "zeigtAufExternes" ) ||
-         EQUAL( szElementName, "objektkoordinaten" ) )
+    if (m_osElementName == "zeigtAufExternes" ||
+        m_osElementName== "objektkoordinaten" )
     {
-        m_osIgnoredElement = szElementName;
+        m_osIgnoredElement = m_osElementName;
         m_nDepthElement    = m_nDepth;
         m_nDepth ++;
 
@@ -167,7 +160,7 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
     CPLDebug( "NAS",
               "%*sstartElement %s m_bIgnoreFeature:%d depth:%d "
               "depthFeature:%d featureClass:%s",
-              m_nDepth, "", szElementName,
+              m_nDepth, "", m_osElementName.c_str(),
               m_bIgnoreFeature, m_nDepth, m_nDepthFeature,
               poState->m_poFeature ? poState->m_poFeature->
                   GetClass()->GetElementName() : "(no feature)"
@@ -193,9 +186,9 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
     const char *pszLast = NULL;
 
     if( m_pszGeometry != NULL
-        || IsGeometryElement( szElementName ) )
+        || IsGeometryElement( m_osElementName ) )
     {
-        const int nLNLen = tr_strlen( localname );
+        const int nLNLen = static_cast<int>(m_osElementName.size());
         CPLString osAttributes = GetAttributes( &attrs );
 
         /* should save attributes too! */
@@ -212,9 +205,9 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
         }
 
         strcpy( m_pszGeometry+m_nGeomLen, "<" );
-        tr_strcpy( m_pszGeometry+m_nGeomLen+1, localname );
+        strcpy( m_pszGeometry+m_nGeomLen+1, m_osElementName );
 
-        if( osAttributes.size() > 0 )
+        if( !osAttributes.empty() )
         {
             strcat( m_pszGeometry+m_nGeomLen, " " );
             strcat( m_pszGeometry+m_nGeomLen, osAttributes );
@@ -229,7 +222,7 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
 /*      (wfs:Delete, wfsext:Replace or wfs:Update)?                     */
 /*      specialized sort of feature.                                    */
 /* -------------------------------------------------------------------- */
-    else if( EQUAL(szElementName,"Filter")
+    else if( m_osElementName == "Filter"
              && (pszLast = m_poReader->GetState()->GetLastComponent()) != NULL
              && (EQUAL(pszLast,"Delete") || EQUAL(pszLast,"Replace") ||
                  EQUAL(pszLast,"Update")) )
@@ -323,19 +316,17 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
 /* -------------------------------------------------------------------- */
 /*      Is it a feature?  If so push a whole new state, and return.     */
 /* -------------------------------------------------------------------- */
-    else if( m_poReader->IsFeatureElement( szElementName ) )
+    else if( m_poReader->IsFeatureElement( m_osElementName ) )
     {
-        m_osLastTypeName = szElementName;
+        m_osLastTypeName = m_osElementName;
 
         const char* pszFilteredClassName = m_poReader->GetFilteredClassName();
 
         pszLast = m_poReader->GetState()->GetLastComponent();
         if( pszLast != NULL && EQUAL(pszLast,"Replace") )
         {
-            XMLCh  Name[100];
-
-            tr_strcpy( Name, "gml:id" );
-            int nIndex = attrs.getIndex( Name );
+            const XMLCh achFID[] = { 'g', 'm', 'l', ':', 'i', 'd', '\0' };
+            int nIndex = attrs.getIndex( achFID );
 
             if( nIndex == -1 || m_osLastReplacingFID !="" )
             {
@@ -351,9 +342,7 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
 
             // Capture "gml:id" attribute as part of the property value -
             // primarily this is for the wfsext:Replace operation's attribute.
-            char *pszReplacingFID = tr_strdup( attrs.getValue( nIndex ) );
-            m_osLastReplacingFID = pszReplacingFID;
-            CPLFree( pszReplacingFID );
+            transcode( attrs.getValue( nIndex ), m_osLastReplacingFID );
 
 #ifdef DEBUG_VERBOSE
             CPLDebug( "NAS", "%*s### Replace typeName=%s replacedBy=%s",
@@ -363,7 +352,7 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
         }
 
         if ( pszFilteredClassName != NULL &&
-             strcmp(szElementName, pszFilteredClassName) != 0 )
+             m_osElementName != pszFilteredClassName )
         {
             m_bIgnoreFeature = true;
             m_nDepthFeature = m_nDepth;
@@ -374,7 +363,7 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
 
         m_bIgnoreFeature = false;
 
-        m_poReader->PushFeature( szElementName, attrs );
+        m_poReader->PushFeature( m_osElementName, attrs );
 
         m_nDepthFeature = m_nDepth;
         m_nDepth ++;
@@ -387,36 +376,33 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
 /*      the typeName attribute so we can assign it to the feature that  */
 /*      will be produced when we process the Filter element.            */
 /* -------------------------------------------------------------------- */
-    else if( EQUAL(szElementName,"Delete") || EQUAL(szElementName,"Update") )
+    else if( m_osElementName == "Delete" || m_osElementName == "Update" )
     {
-        XMLCh  Name[100];
+        const XMLCh Name[] = { 't', 'y', 'p', 'e', 'N', 'a', 'm', 'e', '\0' };
 
-        tr_strcpy( Name, "typeName" );
         int nIndex = attrs.getIndex( Name );
 
         if( nIndex != -1 )
         {
-            char *pszTypeName = tr_strdup( attrs.getValue( nIndex ) );
-            m_osLastTypeName = pszTypeName;
-            CPLFree( pszTypeName );
+            transcode( attrs.getValue( nIndex ), m_osLastTypeName );
         }
 
         m_osLastSafeToIgnore = "";
         m_osLastReplacingFID = "";
 
-        if( EQUAL(szElementName,"Update") )
+        if( m_osElementName == "Update" )
         {
             m_bInUpdate = true;
         }
     }
 
-    else if ( m_bInUpdate && EQUAL(szElementName, "Property") )
+    else if ( m_bInUpdate && m_osElementName == "Property" )
     {
         m_bInUpdateProperty = true;
     }
 
-    else if ( m_bInUpdateProperty && ( EQUAL(szElementName, "Name" ) ||
-                                       EQUAL(szElementName, "Value" ) ) )
+    else if ( m_bInUpdateProperty && ( m_osElementName == "Name" ||
+                                       m_osElementName == "Value" ) )
     {
         // collect attribute name or value
         CPLFree( m_pszCurField );
@@ -428,18 +414,15 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
 /*      safeToIgnore attribute so we can assign it to the feature       */
 /*      that will be produced when we process the Filter element.       */
 /* -------------------------------------------------------------------- */
-    else if( EQUAL(szElementName,"Replace") )
+    else if( m_osElementName ==  "Replace" )
     {
-        XMLCh  Name[100];
+        const XMLCh Name[] = { 's', 'a', 'f', 'e', 'T', 'o', 'I', 'g', 'n', 'o', 'r', 'e', '\0' };
 
-        tr_strcpy( Name, "safeToIgnore" );
         int nIndex = attrs.getIndex( Name );
 
         if( nIndex != -1 )
         {
-            char *pszSafeToIgnore = tr_strdup( attrs.getValue( nIndex ) );
-            m_osLastSafeToIgnore = pszSafeToIgnore;
-            CPLFree( pszSafeToIgnore );
+            transcode( attrs.getValue( nIndex ), m_osLastSafeToIgnore );
         }
         else
         {
@@ -455,24 +438,24 @@ void NASHandler::startElement( const XMLCh* const /* uri */,
 /*      If it is (or at least potentially is) a simple attribute,       */
 /*      then start collecting it.                                       */
 /* -------------------------------------------------------------------- */
-    else if( m_poReader->IsAttributeElement( szElementName ) )
+    else if( m_poReader->IsAttributeElement( m_osElementName ) )
     {
         CPLFree( m_pszCurField );
         m_pszCurField = CPLStrdup("");
 
         // Capture href as OB property.
-        m_poReader->CheckForRelations( szElementName, attrs, &m_pszCurField );
+        m_poReader->CheckForRelations( m_osElementName, attrs, &m_pszCurField );
 
         // Capture "fid" attribute as part of the property value -
         // primarily this is for wfs:Delete operation's FeatureId attribute.
-        if( EQUAL(szElementName,"FeatureId") )
+        if( m_osElementName == "FeatureId" )
             m_poReader->CheckForFID( attrs, &m_pszCurField );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Push the element onto the current state's path.                 */
 /* -------------------------------------------------------------------- */
-    poState->PushPath( szElementName );
+    poState->PushPath( m_osElementName );
 
     m_nDepth ++;
 }
@@ -485,10 +468,9 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
                              const XMLCh* const /* qname */)
 
 {
-    char        szElementName[MAX_TOKEN_SIZE];
     GMLReadState *poState = m_poReader->GetState();
 
-    tr_strcpy( szElementName, localname );
+    transcode( localname, m_osElementName );
 
     m_nDepth --;
 
@@ -515,7 +497,7 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
 #ifdef DEBUG_VERBOSE
     CPLDebug("NAS",
               "%*sendElement %s m_bIgnoreFeature:%d depth:%d depthFeature:%d featureClass:%s",
-              m_nDepth, "", szElementName,
+              m_nDepth, "", m_osElementName.c_str(),
               m_bIgnoreFeature, m_nDepth, m_nDepthFeature,
               poState->m_poFeature ? poState->m_poFeature->GetClass()->GetElementName() : "(no feature)"
             );
@@ -523,19 +505,19 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
 
    if( m_bInUpdateProperty )
    {
-       if( EQUAL( szElementName, "Name" ) )
+       if( m_osElementName == "Name" )
        {
            CPLAssert( m_osLastPropertyName == "" );
            m_osLastPropertyName = m_pszCurField;
            m_pszCurField = NULL;
        }
-       else if( EQUAL( szElementName, "Value" ) )
+       else if( m_osElementName == "Value" )
        {
            CPLAssert( m_osLastPropertyValue == "" );
            m_osLastPropertyValue = m_pszCurField;
            m_pszCurField = NULL;
        }
-       else if( EQUAL( szElementName, "Property" ) )
+       else if( m_osElementName == "Property" )
        {
            if( EQUAL( m_osLastPropertyName, "adv:lebenszeitintervall/adv:AA_Lebenszeitintervall/adv:endet" ) )
            {
@@ -564,7 +546,7 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
        return;
    }
 
-   if ( m_bInUpdate && EQUAL( szElementName, "Update" ) )
+   if ( m_bInUpdate && m_osElementName == "Update" )
    {
        m_bInUpdate = false;
    }
@@ -589,7 +571,7 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
 /* -------------------------------------------------------------------- */
     if( m_pszGeometry != NULL )
     {
-        int nLNLen = tr_strlen( localname );
+        int nLNLen = static_cast<int>(m_osElementName.size());
 
         /* should save attributes too! */
 
@@ -601,7 +583,7 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
         }
 
         strcat( m_pszGeometry+m_nGeomLen, "</" );
-        tr_strcpy( m_pszGeometry+m_nGeomLen+2, localname );
+        strcpy( m_pszGeometry+m_nGeomLen+2, m_osElementName );
         strcat( m_pszGeometry+m_nGeomLen+nLNLen+2, ">" );
         m_nGeomLen += static_cast<int>(strlen(m_pszGeometry+m_nGeomLen));
 
@@ -620,9 +602,9 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
                      * </gml:Point>
                      *
                      */
-                    const char *pszPos;
-                    if( (pszPos = CPLGetXMLValue( psNode, "=Point.pos", NULL ) ) != NULL
-                        && strstr(pszPos, " ") == NULL )
+                    const char *pszPos =
+                        CPLGetXMLValue( psNode, "=Point.pos", NULL );
+                    if( pszPos != NULL && strstr(pszPos, " ") == NULL )
                     {
                         CPLSetXMLValue( psNode, "pos", CPLSPrintf("0 0 %s", pszPos) );
                     }
@@ -670,8 +652,8 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
     const char *pszLast = NULL;
 
     if( m_nDepth == m_nDepthFeature && poState->m_poFeature != NULL
-        && EQUAL(szElementName,
-                 poState->m_poFeature->GetClass()->GetElementName()) )
+        && m_osElementName ==
+                 poState->m_poFeature->GetClass()->GetElementName() )
     {
         m_nDepthFeature = 0;
         m_poReader->PopState();
@@ -683,7 +665,7 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
 /* -------------------------------------------------------------------- */
     else if( m_nDepth == m_nDepthFeature
              && poState->m_poFeature != NULL
-             && EQUAL(szElementName,"Filter")
+             && m_osElementName == "Filter"
              && (pszLast=poState->m_poFeature->GetClass()->GetElementName())
                 != NULL
              && ( EQUAL(pszLast, "Delete") || EQUAL(pszLast, "Update") ) )
@@ -698,7 +680,7 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
 /* -------------------------------------------------------------------- */
     else
     {
-        if( EQUAL(szElementName,poState->GetLastComponent()) )
+        if( m_osElementName == poState->GetLastComponent() )
             poState->PopPath();
         else
         {
@@ -711,54 +693,53 @@ void NASHandler::endElement( const XMLCh* const /* uri */ ,
 /*                             characters()                             */
 /************************************************************************/
 
-#if XERCES_VERSION_MAJOR >= 3
-void NASHandler::characters( const XMLCh *const chars_in,
-                             const XMLSize_t /* length */ )
-#else
-void NASHandler::characters( const XMLCh* const chars_in,
-                             const unsigned int /* length */ )
-#endif
+void NASHandler::characters( const XMLCh *const chars,
+                             const XMLSize_t length )
 {
-    const XMLCh *chars = chars_in;
-
     if( m_pszCurField != NULL )
     {
         const int nCurFieldLength = static_cast<int>(strlen(m_pszCurField));
 
+        int nSkipped = 0;
         if (nCurFieldLength == 0)
         {
             // Ignore white space
-            while( *chars == ' ' || *chars == 10 || *chars == 13 ||
-                   *chars == '\t')
-                chars++;
+            while( chars[nSkipped] == ' ' || chars[nSkipped] == 10 || chars[nSkipped] == 13 ||
+                   chars[nSkipped] == '\t')
+                nSkipped++;
         }
 
-        char *pszTranslated = tr_strdup(chars);
+        transcode( chars + nSkipped, m_osCharacters,
+                   static_cast<int>(length) - nSkipped );
 
         if( m_pszCurField == NULL )
         {
-            m_pszCurField = pszTranslated;
+            m_pszCurField = CPLStrdup(m_osCharacters);
         }
         else
         {
             m_pszCurField = static_cast<char *>(
                 CPLRealloc( m_pszCurField,
-                            nCurFieldLength+strlen(pszTranslated)+1 ) );
-            strcpy( m_pszCurField + nCurFieldLength, pszTranslated );
-            CPLFree( pszTranslated );
+                            nCurFieldLength+m_osCharacters.size()+1 ) );
+            memcpy( m_pszCurField + nCurFieldLength, m_osCharacters.c_str(),
+                    m_osCharacters.size() + 1 );
         }
     }
     else if( m_pszGeometry != NULL )
     {
+        int nSkipped = 0;
         if (m_nGeomLen == 0)
         {
             // Ignore white space
-            while( *chars == ' ' || *chars == 10 || *chars == 13 ||
-                   *chars == '\t')
-                chars++;
+            while( chars[nSkipped] == ' ' || chars[nSkipped] == 10 || chars[nSkipped] == 13 ||
+                   chars[nSkipped] == '\t')
+                nSkipped++;
         }
 
-        const int nCharsLen = tr_strlen(chars);
+        transcode( chars + nSkipped, m_osCharacters,
+                   static_cast<int>(length) - nSkipped );
+
+        const int nCharsLen = static_cast<int>(m_osCharacters.size());
 
         if( m_nGeomLen + nCharsLen*4 + 4 > m_nGeomAlloc )
         {
@@ -767,7 +748,8 @@ void NASHandler::characters( const XMLCh* const chars_in,
                 CPLRealloc( m_pszGeometry, m_nGeomAlloc);
         }
 
-        tr_strcpy( m_pszGeometry+m_nGeomLen, chars );
+        memcpy( m_pszGeometry+m_nGeomLen, m_osCharacters.c_str(),
+                m_osCharacters.size() + 1 );
         m_nGeomLen += static_cast<int>(strlen(m_pszGeometry+m_nGeomLen));
     }
 }
@@ -779,14 +761,13 @@ void NASHandler::characters( const XMLCh* const chars_in,
 void NASHandler::fatalError( const SAXParseException &exception)
 
 {
-    char *pszErrorMessage = tr_strdup( exception.getMessage() );
+    CPLString osErrMsg;
+    transcode( exception.getMessage(), osErrMsg );
     CPLError( CE_Failure, CPLE_AppDefined,
               "XML Parsing Error: %s at line %d, column %d\n",
-              pszErrorMessage,
+              osErrMsg.c_str(),
               static_cast<int>(exception.getLineNumber()),
               static_cast<int>(exception.getColumnNumber()) );
-
-    CPLFree( pszErrorMessage );
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/nas/nasreader.cpp b/ogr/ogrsf_frmts/nas/nasreader.cpp
index 1c442a9..b8fd047 100644
--- a/ogr/ogrsf_frmts/nas/nasreader.cpp
+++ b/ogr/ogrsf_frmts/nas/nasreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: nasreader.cpp 36296 2016-11-19 15:02:05Z jef $
  *
  * Project:  NAS Reader
  * Purpose:  Implementation of NASReader class.
@@ -35,11 +34,11 @@
 #include "gmlutils.h"
 #include "cpl_multiproc.h"
 
-#define SUPPORT_GEOMETRY
+#include "ogr_geometry.h"
 
-#ifdef SUPPORT_GEOMETRY
-#  include "ogr_geometry.h"
-#endif
+#include <algorithm>
+
+CPL_CVSID("$Id: nasreader.cpp 36300 2016-11-19 15:05:34Z jef $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -50,8 +49,6 @@
 #include "nasreaderp.h"
 #include "cpl_conv.h"
 
-CPLMutex *NASReader::hMutex = NULL;
-
 /************************************************************************/
 /*                          CreateNASReader()                           */
 /************************************************************************/
@@ -74,6 +71,7 @@ NASReader::NASReader() :
     m_poNASHandler(NULL),
     m_poSAXReader(NULL),
     m_bReadStarted(false),
+    m_bXercesInitialized(false),
     m_poState(NULL),
     m_poCompleteFeature(NULL),
     m_pszFilteredClassName(NULL)
@@ -92,8 +90,8 @@ NASReader::~NASReader()
 
     CleanupParser();
 
-    if (CPLTestBool(CPLGetConfigOption("NAS_XERCES_TERMINATE", "FALSE")))
-        XMLPlatformUtils::Terminate();
+    if( m_bXercesInitialized )
+        OGRDeinitializeXerces();
 
     CPLFree( m_pszFilteredClassName );
 }
@@ -126,29 +124,11 @@ const char* NASReader::GetSourceFileName()
 bool NASReader::SetupParser()
 
 {
+    if( !m_bXercesInitialized )
     {
-    CPLMutexHolderD(&hMutex);
-    static int nXercesInitialized = -1;
-
-    if( nXercesInitialized < 0)
-    {
-        try
-        {
-            XMLPlatformUtils::Initialize();
-        }
-
-        catch (const XMLException& toCatch)
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Exception initializing Xerces based GML reader.\n%s",
-                      tr_strdup(toCatch.getMessage()) );
-            nXercesInitialized = FALSE;
+        if( !OGRInitializeXerces() )
             return false;
-        }
-        nXercesInitialized = TRUE;
-    }
-    if( !nXercesInitialized )
-        return false;
+        m_bXercesInitialized = true;
     }
 
     // Cleanup any old parser.
@@ -187,11 +167,7 @@ bool NASReader::SetupParser()
 #else
         m_poSAXReader->setFeature( XMLUni::fgSAX2CoreValidation, false);
 
-#if XERCES_VERSION_MAJOR >= 3
         m_poSAXReader->setFeature( XMLUni::fgXercesSchema, false);
-#else
-        m_poSAXReader->setFeature( XMLUni::fgSAX2CoreNameSpaces, false);
-#endif
 
 #endif
         XMLString::release( &xmlUriValid );
@@ -255,6 +231,8 @@ GMLFeature *NASReader::NextFeature()
         {
             if( m_poSAXReader == NULL )
                 SetupParser();
+            if( m_poSAXReader == NULL )
+                return NULL;
 
             if( !m_poSAXReader->parseFirst( m_pszFilename, m_oToFill ) )
                 return NULL;
@@ -266,13 +244,12 @@ GMLFeature *NASReader::NextFeature()
 
         poReturn = m_poCompleteFeature;
         m_poCompleteFeature = NULL;
-
     }
     catch (const XMLException& toCatch)
     {
         CPLDebug( "NAS",
                   "Error during NextFeature()! Message:\n%s",
-                  tr_strdup( toCatch.getMessage() ) );
+                  transcode( toCatch.getMessage() ).c_str() );
     }
 
     return poReturn;
@@ -331,16 +308,13 @@ void NASReader::PushFeature( const char *pszElement,
 /*      Check for gml:id, and if found push it as an attribute named    */
 /*      gml_id.                                                         */
 /* -------------------------------------------------------------------- */
-    XMLCh   anFID[100];
-
-    tr_strcpy( anFID, "gml:id" );
-    int nFIDIndex = attrs.getIndex( anFID );
+    const XMLCh achFID[] = { 'g', 'm', 'l', ':', 'i', 'd', '\0' };
+    int nFIDIndex = attrs.getIndex( achFID );
     if( nFIDIndex != -1 )
     {
-        char *pszFID = tr_strdup( attrs.getValue( nFIDIndex ) );
+        char *pszFID = CPLStrdup( transcode( attrs.getValue( nFIDIndex ) ) );
         SetFeaturePropertyDirectly( "gml_id", pszFID );
     }
-
 }
 
 /************************************************************************/
@@ -861,7 +835,7 @@ bool NASReader::PrescanForSchema( bool bGetExtents,
         return false;
 
     std::string osWork;
-    GMLFeature  *poFeature;
+    GMLFeature  *poFeature = NULL;
 
     while( (poFeature = NextFeature()) != NULL )
     {
@@ -872,7 +846,6 @@ bool NASReader::PrescanForSchema( bool bGetExtents,
         else
             poClass->SetFeatureCount( poClass->GetFeatureCount() + 1 );
 
-#ifdef SUPPORT_GEOMETRY
         if( bGetExtents )
         {
             OGRGeometry *poGeometry = NULL;
@@ -886,7 +859,6 @@ bool NASReader::PrescanForSchema( bool bGetExtents,
 
             if( poGeometry != NULL )
             {
-                double  dfXMin, dfXMax, dfYMin, dfYMax;
                 OGREnvelope sEnvelope;
 
                 if( poClass->GetGeometryPropertyCount() == 0 )
@@ -913,12 +885,16 @@ bool NASReader::PrescanForSchema( bool bGetExtents,
                 // merge extents.
                 poGeometry->getEnvelope( &sEnvelope );
                 delete poGeometry;
+                double dfXMin = 0.0;
+                double dfXMax = 0.0;
+                double dfYMin = 0.0;
+                double dfYMax = 0.0;
                 if( poClass->GetExtents(&dfXMin, &dfXMax, &dfYMin, &dfYMax) )
                 {
-                    dfXMin = MIN(dfXMin,sEnvelope.MinX);
-                    dfXMax = MAX(dfXMax,sEnvelope.MaxX);
-                    dfYMin = MIN(dfYMin,sEnvelope.MinY);
-                    dfYMax = MAX(dfYMax,sEnvelope.MaxY);
+                    dfXMin = std::min(dfXMin, sEnvelope.MinX);
+                    dfXMax = std::max(dfXMax, sEnvelope.MaxX);
+                    dfYMin = std::min(dfYMin, sEnvelope.MinY);
+                    dfYMax = std::max(dfYMax, sEnvelope.MaxY);
                 }
                 else
                 {
@@ -939,7 +915,6 @@ bool NASReader::PrescanForSchema( bool bGetExtents,
                     poClass->ClearGeometryProperties();
                 }
             }
-#endif /* def SUPPORT_GEOMETRY */
         }
 
         delete poFeature;
@@ -971,18 +946,14 @@ void NASReader::CheckForFID( const Attributes &attrs,
                              char **ppszCurField )
 
 {
-    XMLCh  Name[100];
-
-    tr_strcpy( Name, "fid" );
+    const XMLCh  Name[] = { 'f', 'i', 'd', '\0' };
     int nIndex = attrs.getIndex( Name );
 
     if( nIndex != -1 )
     {
-        char *pszFID = tr_strdup( attrs.getValue( nIndex ) );
         CPLString osCurField = *ppszCurField;
 
-        osCurField += pszFID;
-        CPLFree( pszFID );
+        osCurField += transcode( attrs.getValue( nIndex ) );
 
         CPLFree( *ppszCurField );
         *ppszCurField = CPLStrdup(osCurField);
@@ -1002,23 +973,19 @@ void NASReader::CheckForRelations( const char *pszElement,
 
     CPLAssert( poFeature  != NULL );
 
-    XMLCh  Name[100];
-
-    tr_strcpy( Name, "xlink:href" );
+    const XMLCh  Name[] = { 'x', 'l', 'i', 'n', 'k', ':', 'h', 'r', 'e', 'f', '\0' };
     const int nIndex = attrs.getIndex( Name );
 
     if( nIndex != -1 )
     {
-        char *pszHRef = tr_strdup( attrs.getValue( nIndex ) );
+        CPLString osVal( transcode( attrs.getValue( nIndex ) ) );
 
-        if( STARTS_WITH_CI(pszHRef, "urn:adv:oid:") )
+        if( STARTS_WITH_CI(osVal, "urn:adv:oid:") )
         {
-            poFeature->AddOBProperty( pszElement, pszHRef );
+            poFeature->AddOBProperty( pszElement, osVal );
             CPLFree( *ppszCurField );
-            *ppszCurField = CPLStrdup( pszHRef + 12 );
+            *ppszCurField = CPLStrdup( osVal.c_str() + 12 );
         }
-
-        CPLFree( pszHRef );
     }
 }
 
diff --git a/ogr/ogrsf_frmts/nas/nasreaderp.h b/ogr/ogrsf_frmts/nas/nasreaderp.h
index 7c02f87..f0a71a4 100644
--- a/ogr/ogrsf_frmts/nas/nasreaderp.h
+++ b/ogr/ogrsf_frmts/nas/nasreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: nasreaderp.h 34462 2016-06-28 18:51:52Z jef $
+ * $Id: nasreaderp.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  NAS Reader
  * Purpose:  Private Declarations for OGR NAS Reader code.
@@ -31,6 +31,10 @@
 #ifndef CPL_NASREADERP_H_INCLUDED
 #define CPL_NASREADERP_H_INCLUDED
 
+// Must be first for DEBUG_BOOL case
+#include "xercesc_headers.h"
+#include "ogr_xerces.h"
+
 #include "gmlreader.h"
 #include "gmlreaderp.h"
 #include "ogr_api.h"
@@ -80,8 +84,13 @@ class NASHandler : public DefaultHandler
 
     std::list<CPLString> m_LastOccasions;
 
+    CPLString  m_osElementName;
+    CPLString  m_osAttrName;
+    CPLString  m_osAttrValue;
+    CPLString  m_osCharacters;
+
 public:
-    NASHandler( NASReader *poReader );
+    explicit NASHandler( NASReader *poReader );
     virtual ~NASHandler();
 
     void startElement(
@@ -89,21 +98,21 @@ public:
         const   XMLCh* const    localname,
         const   XMLCh* const    qname,
         const   Attributes& attrs
-    );
+    ) override;
     void endElement(
         const   XMLCh* const    uri,
         const   XMLCh* const    localname,
         const   XMLCh* const    qname
-    );
+    ) override;
 #if XERCES_VERSION_MAJOR >= 3
     void characters( const XMLCh *const chars,
-                     const XMLSize_t length );
+                     const XMLSize_t length ) override;
 #else
     void characters( const XMLCh *const chars,
                      const unsigned int length );
 #endif
 
-    void fatalError(const SAXParseException&);
+    void fatalError(const SAXParseException&) override;
 
     CPLString GetAttributes( const Attributes* attr );
 };
@@ -156,6 +165,7 @@ private:
     NASHandler    *m_poNASHandler;
     SAX2XMLReader *m_poSAXReader;
     bool          m_bReadStarted;
+    bool          m_bXercesInitialized;
     XMLPScanToken m_oToFill;
 
     GMLReadState *m_poState;
@@ -171,41 +181,41 @@ public:
                 NASReader();
     virtual     ~NASReader();
 
-    bool            IsClassListLocked() const { return m_bClassListLocked; }
-    void             SetClassListLocked( bool bFlag )
+    bool            IsClassListLocked() const override { return m_bClassListLocked; }
+    void             SetClassListLocked( bool bFlag ) override
         { m_bClassListLocked = bFlag; }
 
-    void             SetSourceFile( const char *pszFilename );
-    const char      *GetSourceFileName();
+    void             SetSourceFile( const char *pszFilename ) override;
+    const char      *GetSourceFileName() override;
 
-    int              GetClassCount() const { return m_nClassCount; }
-    GMLFeatureClass *GetClass( int i ) const;
-    GMLFeatureClass *GetClass( const char *pszName ) const;
+    int              GetClassCount() const override { return m_nClassCount; }
+    GMLFeatureClass *GetClass( int i ) const override;
+    GMLFeatureClass *GetClass( const char *pszName ) const override;
 
-    int              AddClass( GMLFeatureClass *poClass );
-    void             ClearClasses();
+    int              AddClass( GMLFeatureClass *poClass ) override;
+    void             ClearClasses() override;
 
-    GMLFeature       *NextFeature();
+    GMLFeature       *NextFeature() override;
 
-    bool             LoadClasses( const char *pszFile = NULL );
-    bool             SaveClasses( const char *pszFile = NULL );
+    bool             LoadClasses( const char *pszFile = NULL ) override;
+    bool             SaveClasses( const char *pszFile = NULL ) override;
 
     bool             PrescanForSchema(bool bGetExtents = true,
                                       bool bAnalyzeSRSPerFeature = true,
-                                      bool bOnlyDetectSRS = false);
-    bool             PrescanForTemplate( void );
-    void             ResetReading();
+                                      bool bOnlyDetectSRS = false) override;
+    bool             PrescanForTemplate() override;
+    void             ResetReading() override;
 
     bool             ParseXSD( const char * /* pszFile */ ) { return false; }
 
     bool             ResolveXlinks( const char *pszFile,
                                     bool* pbOutIsTempFile,
                                     char **papszSkip = NULL,
-                                    const bool bStrict = false );
+                                    const bool bStrict = false ) override;
 
     bool             HugeFileResolver( const char *pszFile,
                                        bool bSqliteIsTempFile,
-                                       int iSqliteCacheMB );
+                                       int iSqliteCacheMB ) override;
 
 // ---
 
@@ -222,21 +232,19 @@ public:
     void        SetFeaturePropertyDirectly( const char *pszElement,
                                     char *pszValue );
 
-    bool        HasStoppedParsing() { return false; }
+    bool        HasStoppedParsing() override { return false; }
 
     void        CheckForFID( const Attributes &attrs, char **ppszCurField );
     void        CheckForRelations( const char *pszElement,
                                    const Attributes &attrs,
                                    char **ppszCurField );
 
-    virtual const char* GetGlobalSRSName() { return NULL; }
-
-    virtual bool        CanUseGlobalSRSName() { return false; }
+    virtual const char* GetGlobalSRSName() override { return NULL; }
 
-    bool        SetFilteredClassName(const char* pszClassName);
-    const char* GetFilteredClassName() { return m_pszFilteredClassName; }
+    virtual bool        CanUseGlobalSRSName() override { return false; }
 
-    static CPLMutex* hMutex;
+    bool        SetFilteredClassName(const char* pszClassName) override;
+    const char* GetFilteredClassName() override { return m_pszFilteredClassName; }
 
     static      OGRGeometry* ConvertGeometry(OGRGeometry*);
 };
diff --git a/ogr/ogrsf_frmts/nas/ogr_nas.h b/ogr/ogrsf_frmts/nas/ogr_nas.h
index 61e914c..3661f6f 100644
--- a/ogr/ogrsf_frmts/nas/ogr_nas.h
+++ b/ogr/ogrsf_frmts/nas/ogr_nas.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_nas.h 32898 2016-01-10 14:44:10Z goatbar $
+ * $Id: ogr_nas.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  NAS Reader
  * Purpose:  Declarations for OGR wrapper classes for NAS, and NAS<->OGR
@@ -59,19 +59,19 @@ class OGRNASLayer : public OGRLayer
                                      OGRwkbGeometryType eType,
                                      OGRNASDataSource *poDS );
 
-                        ~OGRNASLayer();
+                        virtual ~OGRNASLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    GIntBig             GetFeatureCount( int bForce = TRUE );
-    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    GIntBig             GetFeatureCount( int bForce = TRUE ) override;
+    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -88,15 +88,15 @@ class OGRNASRelationLayer : public OGRLayer
     std::vector<CPLString> aoRelationCollection;
 
   public:
-                        OGRNASRelationLayer( OGRNASDataSource *poDS );
+    explicit             OGRNASRelationLayer( OGRNASDataSource *poDS );
                         ~OGRNASRelationLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    GIntBig             GetFeatureCount( int bForce = TRUE );
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-    int                 TestCapability( const char * );
+    GIntBig             GetFeatureCount( int bForce = TRUE ) override;
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
+    int                 TestCapability( const char * ) override;
 
     // For use populating.
     void                AddRelation( const char *pszFromID,
@@ -132,11 +132,11 @@ class OGRNASDataSource : public OGRDataSource
     int                 Open( const char * );
     int                 Create( const char *pszFile, char **papszOptions );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     IGMLReader          *GetReader() { return poReader; }
 
diff --git a/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp b/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
index 1d0b5c7..ee87e49 100644
--- a/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnasdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrnasdatasource.cpp 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRNASDataSource class.
@@ -32,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_nas.h"
 
-CPL_CVSID("$Id: ogrnasdatasource.cpp 32898 2016-01-10 14:44:10Z goatbar $");
+CPL_CVSID("$Id: ogrnasdatasource.cpp 35142 2016-08-18 11:30:22Z goatbar $");
 
 static const char * const apszURNNames[] =
 {
@@ -320,9 +319,9 @@ int OGRNASDataSource::TestCapability( const char * /* pszCap */ )
 void OGRNASDataSource::PopulateRelations()
 
 {
-    GMLFeature  *poFeature;
-
     poReader->ResetReading();
+
+    GMLFeature  *poFeature = NULL;
     while( (poFeature = poReader->NextFeature()) != NULL )
     {
         char **papszOBProperties = poFeature->GetOBProperties();
diff --git a/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp b/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
index 1a3f456..da4d27c 100644
--- a/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnasdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrnasdriver.cpp 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  OGR
  * Purpose:  OGRNASDriver implementation
@@ -32,19 +31,7 @@
 #include "nasreaderp.h"
 #include "ogr_nas.h"
 
-CPL_CVSID("$Id: ogrnasdriver.cpp 32898 2016-01-10 14:44:10Z goatbar $");
-
-
-/************************************************************************/
-/*                       OGRNASDriverUnload()                           */
-/************************************************************************/
-
-static void OGRNASDriverUnload(CPL_UNUSED GDALDriver* poDriver)
-{
-    if( NASReader::hMutex != NULL )
-        CPLDestroyMutex( NASReader::hMutex );
-    NASReader::hMutex = NULL;
-}
+CPL_CVSID("$Id: ogrnasdriver.cpp 35809 2016-10-19 12:08:05Z rouault $");
 
 /************************************************************************/
 /*                     OGRNASDriverIdentify()                           */
@@ -151,7 +138,6 @@ void RegisterOGRNAS()
 
     poDriver->pfnOpen = OGRNASDriverOpen;
     poDriver->pfnIdentify = OGRNASDriverIdentify;
-    poDriver->pfnUnloadDriver = OGRNASDriverUnload;
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
diff --git a/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp b/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
index 97b0b4c..e695388 100644
--- a/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnaslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrnaslayer.cpp 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRNASLayer class.
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_nas.h"
 
-CPL_CVSID("$Id: ogrnaslayer.cpp 32898 2016-01-10 14:44:10Z goatbar $");
+CPL_CVSID("$Id: ogrnaslayer.cpp 37141 2017-01-14 13:09:04Z rouault $");
 
 /************************************************************************/
 /*                           OGRNASLayer()                              */
@@ -106,12 +105,10 @@ OGRFeature *OGRNASLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Cleanup last feature, and get a new raw nas feature.            */
 /* -------------------------------------------------------------------- */
-        delete poNASFeature;
         delete poGeom;
-
-        poNASFeature = NULL;
         poGeom = NULL;
 
+        delete poNASFeature;
         poNASFeature = poDS->GetReader()->NextFeature();
         if( poNASFeature == NULL )
             return NULL;
@@ -137,16 +134,43 @@ OGRFeature *OGRNASLayer::GetNextFeature()
             poNASFeature->GetGeometryList();
         if (papsGeometry[0] != NULL)
         {
+            CPLString osLastErrorMsg;
+            CPLPushErrorHandler(CPLQuietErrorHandler);
             poGeom = (OGRGeometry*) OGR_G_CreateFromGMLTree(papsGeometry[0]);
+            CPLPopErrorHandler();
+            if( poGeom == NULL )
+                osLastErrorMsg = CPLGetLastErrorMsg();
             poGeom = NASReader::ConvertGeometry(poGeom);
             poGeom = OGRGeometryFactory::forceTo(poGeom, GetGeomType());
             // poGeom->dumpReadable( 0, "NAS: " );
 
-            // We assume the OGR_G_CreateFromGMLTree() function would
-            // have already reported an error.
             if( poGeom == NULL )
             {
+                CPLString osGMLId;
+                if( poFClass->GetPropertyIndex("gml_id") == 0 )
+                {
+                     const GMLProperty *psGMLProperty =
+                            poNASFeature->GetProperty( 0 );
+                    if( psGMLProperty && psGMLProperty->nSubProperties == 1 )
+                    {
+                        osGMLId.Printf("(gml_id=%s) ",
+                                       psGMLProperty->papszSubProperties[0]);
+                    }
+                }
+
+                const bool bGoOn =CPLTestBool(
+                    CPLGetConfigOption("NAS_SKIP_CORRUPTED_FEATURES", "NO"));
+                CPLError(bGoOn ? CE_Warning : CE_Failure, CPLE_AppDefined,
+                         "Geometry of feature %d %scannot be parsed: %s%s",
+                         iNextNASId, osGMLId.c_str(), osLastErrorMsg.c_str(),
+                         bGoOn ? ". Skipping to next feature.":
+                         ". You may set the NAS_SKIP_CORRUPTED_FEATURES "
+                         "configuration option to YES to skip to the next "
+                         "feature");
                 delete poNASFeature;
+                poNASFeature = NULL;
+                if( bGoOn )
+                    continue;
                 return NULL;
             }
 
@@ -268,10 +292,10 @@ GIntBig OGRNASLayer::GetFeatureCount( int bForce )
 OGRErr OGRNASLayer::GetExtent(OGREnvelope *psExtent, int bForce )
 
 {
-    double dfXMin;
-    double dfXMax;
-    double dfYMin;
-    double dfYMax;
+    double dfXMin = 0.0;
+    double dfXMax = 0.0;
+    double dfYMin = 0.0;
+    double dfYMax = 0.0;
 
     if( poFClass != NULL &&
         poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax ) )
@@ -296,14 +320,14 @@ int OGRNASLayer::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,OLCFastGetExtent) )
     {
-        double  dfXMin;
-        double  dfXMax;
-        double  dfYMin;
-        double  dfYMax;
-
         if( poFClass == NULL )
             return FALSE;
 
+        double dfXMin = 0.0;
+        double dfXMax = 0.0;
+        double dfYMin = 0.0;
+        double dfYMax = 0.0;
+
         return poFClass->GetExtents( &dfXMin, &dfXMax, &dfYMin, &dfYMax );
     }
 
diff --git a/ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp b/ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp
index 866c276..21b6565 100644
--- a/ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp
+++ b/ogr/ogrsf_frmts/nas/ogrnasrelationlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrnasrelationlayer.cpp 32898 2016-01-10 14:44:10Z goatbar $
  *
  * Project:  OGR
  * Purpose:  Implements OGRNASRelationLayer class, a special layer holding all
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "ogr_nas.h"
 
-CPL_CVSID("$Id: ogrnasrelationlayer.cpp 32898 2016-01-10 14:44:10Z goatbar $");
+CPL_CVSID("$Id: ogrnasrelationlayer.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                        OGRNASRelationLayer()                         */
@@ -198,4 +197,3 @@ void OGRNASRelationLayer::AddRelation( const char *pszFromID,
 
     aoRelationCollection.push_back( osRelation );
 }
-
diff --git a/ogr/ogrsf_frmts/ntf/README.txt b/ogr/ogrsf_frmts/ntf/README.txt
index a06ac06..e188602 100644
--- a/ogr/ogrsf_frmts/ntf/README.txt
+++ b/ogr/ogrsf_frmts/ntf/README.txt
@@ -34,12 +34,12 @@ Boundaryline:
 	BOUNDARYLINE_POLY
 	BOUNDARYLINE_COLLECTIONS
 
-	The _POLY layer has links to links allowing true polygons to  
+	The _POLY layer has links to links allowing true polygons to
         be formed (otherwise the _POLY's only have a seed point for geometry.
 	The collections are collections of polygons (also without geometry
 	as read).  This is the only product from which polygons can be
 	constructed.
-	
+
 Boundary Line 2000:
 	BL2000_LINK
 	BL2000_POLY
@@ -47,7 +47,7 @@ Boundary Line 2000:
 
 	Similar to Boundaryline, but with different attributes, feature code
 	is largely unused, and the _POLY layer doesn't have a seed point.
-	
+
 BaseData.GB:
 	BASEDATA_POINT
 	BASEDATA_LINE
@@ -73,104 +73,104 @@ Code Point:
 Code Point Plus:
 	CODE_POINT_PLUS
 
-The dataset as a whole will also have a FEATURE_CLASSES layer containing a 
-pure table relating FEAT_CODE numbers with feature class names (FC_NAME).  
-This applies to all products in the dataset.  A few layer types (such as 
+The dataset as a whole will also have a FEATURE_CLASSES layer containing a
+pure table relating FEAT_CODE numbers with feature class names (FC_NAME).
+This applies to all products in the dataset.  A few layer types (such as
 the Code Point, and Address Point products) don't include feature classes.
 Some products use features classes that are not defined in the file, and
-so they will not appear in the FEATURE_CLASSES layer. 
-	
-	
+so they will not appear in the FEATURE_CLASSES layer.
+
+
 Product Schemas
 ---------------
 
 The approach taken in this reader is to treat one file, or a directory
-of files as a single dataset.  All files in the dataset are scanned on 
+of files as a single dataset.  All files in the dataset are scanned on
 open.  For each particular product (listed above) a set of layers are
 created; however, these layers may be extracted from several files of the
-same product. 
+same product.
 
 The layers are based on a low level feature type in the NTF file, but will
-generally contain features of many different feature codes (FEAT_CODE 
+generally contain features of many different feature codes (FEAT_CODE
 attribute).  Different features within a given layer may have a variety of
 attributes in the file; however, the schema is established based on the
 union of all attributes possible within features of a particular type
 (i.e. POINT) of that product family (i.e. OSCAR Network).
 
 If an NTF product is read that doesn't match one of the known schema's
-it will go through a different generic handler which has only 
+it will go through a different generic handler which has only
 layers of type GENERIC_POINT and GENERIC_LINE.  The features only have
-a FEAT_CODE attribute.  
+a FEAT_CODE attribute.
 
 Details of what layers of what products have what attributes can be found
 in the NTFFileReader::EstablishLayers() method at the end of ntf_estlayers.cpp.
-This file also contains all the product specific translation code. 
+This file also contains all the product specific translation code.
 
 
 Special Attributes
 ------------------
 
 FEAT_CODE: General feature code integer, can be used to lookup a name in the
-           FEATURE_CLASSES layer/table. 
+           FEATURE_CLASSES layer/table.
 
 TEXT_ID/POINT_ID/LINE_ID/NAME_ID/COLL_ID/POLY_ID/GEOM_ID:
-          Unique identifier for a feature of the appropriate type.  
+          Unique identifier for a feature of the appropriate type.
 
 TILE_REF: All layers (except FEATURE_CLASSES) contain a TILE_REF attribute
           which indicates which tile (file) the features came from.  Generally
           speaking the id numbers are only unique within the tile and so
           the TILE_REF can be used restrict id links within features from
-          the same file. 
+          the same file.
 
 FONT/TEXT_HT/DIG_POSTN/ORIENT:
-	Detailed information on the font, text height, digitizing position, 
+	Detailed information on the font, text height, digitizing position,
         and orientation of text or name objects.  Review the OS product
-        manuals to understand the units, and meaning of these codes. 
+        manuals to understand the units, and meaning of these codes.
 
 GEOM_ID_OF_POINT:
 	For _NODE features this defines the POINT_ID of the point layer object
         to which this node corresponds.  Generally speaking the nodes don't
         carry a geometry of their own.  The node must be related to a point
-        to establish it's position. 
+        to establish it's position.
 
 GEOM_ID_OF_LINK:
 	A _list_ of _LINK or _LINE features to end/start at a node.  Nodes,
-        and this field are generally only of value when establishing 
+        and this field are generally only of value when establishing
         connectivity of line features for network analysis.   Note that this
         should be related to the target features GEOM_ID, not it's LINE_ID.
 
         On the BOUNDARYLINE_POLY layer this attribute contains the GEOM_IDs
-        of the lines which form the edge of the polygon. 
+        of the lines which form the edge of the polygon.
 
 POLY_ID:
 	A list of POLY_ID's from the BOUNDARYLINE_POLY layer associated with
-        a given collection in the BOUNDARYLINE_COLLECTIONS layer. 
+        a given collection in the BOUNDARYLINE_COLLECTIONS layer.
 
 
 Adding a New Product
 --------------------
 
-It is anticipated that over time the UK Ordnance Survey will define new 
+It is anticipated that over time the UK Ordnance Survey will define new
 product formats, and to get decent mileage out of them this library should
 be updated to support them.  While I will endeavor to do this myself, it
 seems prudent to define how it is done in case I am not available to do it,
-or am unwilling to do it on a timely basis.  To add a new product type the 
+or am unwilling to do it on a timely basis.  To add a new product type the
 following steps are required:
 
  o Add an NPC_ code for the product in ntf.h
  o Add a case in NTFFileReader::Open() to translate the GetProduct() result
-   into the NPC_ code. 
+   into the NPC_ code.
  o Add a case in NTFFileReader::EstablishLayers() defining the layers found
-   on this product.  
+   on this product.
  o Add translate functions for layers of this product.  Generally they can
    be cloned from an existing translate function, and the attribute mapping
-   in the NTFReader::ApplyAttributeValues() call can be modified. 
+   in the NTFReader::ApplyAttributeValues() call can be modified.
 
 Occasionally existing products will change slightly.  This may result in a
 slight change to the detection logic in NTFFileReader::Open() and changes
 in the list of user attributes associated with the layer.  If the differences
-are significant it may be necessary to define a whole new product family 
-type (as is done for Code Point Plus vs. Code Point). 
+are significant it may be necessary to define a whole new product family
+type (as is done for Code Point Plus vs. Code Point).
 
 Generic Products
 ----------------
@@ -179,7 +179,7 @@ In situations where a file is not identified as being part of an existing
 known product it will be treated generically.  In this case the entire dataset
 is scanned to establish what features have what attributes.  Because of this,
 opening a generic dataset can be much slower than opening a recognized dataset.
-Based on this scan a list of generic features (layers) are defined from the 
+Based on this scan a list of generic features (layers) are defined from the
 following set:
 
  GENERIC_POINT
@@ -191,7 +191,7 @@ following set:
  GENERIC_COLLECTION
 
 Generic products are primarily handled by the ntf_generic.cpp module whereas
-specific products are handled in ntf_estlayers.cpp.  
+specific products are handled in ntf_estlayers.cpp.
 
 Because some data products (OSNI datasets) not from the Ordnance Survey
 were found to have record groups in unusual orders compared to what the
@@ -202,11 +202,11 @@ orderings.  This is accomplished by the NTFFileReader "indexing" capability
 near the bottom of ntffilereader.cpp.  Because of this in memory indexing
 accessing generic datasets can be much more memory intensive than accessing
 known data products, though it isn't necessary for generic level 1 and 2
-products. 
+products.
 
 It is possible to force a known product to be treated as generic by setting
 the FORCE_GENERIC option to "ON" using OGRNTFDataSource::SetOptionsList() as
-is demonstrated in ntfdump.cpp. 
+is demonstrated in ntfdump.cpp.
 
 
 
diff --git a/ogr/ogrsf_frmts/ntf/ntf.h b/ogr/ogrsf_frmts/ntf/ntf.h
index ad3f6f8..c4c3fa9 100644
--- a/ogr/ogrsf_frmts/ntf/ntf.h
+++ b/ogr/ogrsf_frmts/ntf/ntf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ntf.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ntf.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  NTF Translator
  * Purpose:  Main declarations for NTF translator.
@@ -118,10 +118,10 @@ class NTFRecord
     int      nLength;
     char    *pszData;
 
-    int      ReadPhysicalLine( FILE *fp, char *pszLine );
+    static int      ReadPhysicalLine( FILE *fp, char *pszLine );
 
   public:
-             NTFRecord( FILE * );
+    explicit  NTFRecord( FILE * );
              ~NTFRecord();
 
     int      GetType() { return nType; }
@@ -161,7 +161,7 @@ public:
 class NTFCodeList
 {
 public:
-                NTFCodeList( NTFRecord * );
+    explicit     NTFCodeList( NTFRecord * );
                 ~NTFCodeList();
 
     const char  *Lookup( const char * );
@@ -172,7 +172,6 @@ public:
     int         nNumCode;
     char        **papszCodeVal; /* Short code value */
     char        **papszCodeDes; /* Long description of code */
-
 };
 
 /************************************************************************/
@@ -189,7 +188,6 @@ typedef struct
 
 } NTFAttDesc;
 
-
 class OGRNTFLayer;
 class OGRNTFRasterLayer;
 class OGRNTFDataSource;
@@ -282,7 +280,7 @@ class NTFFileReader
     OGRGeometry     **papoLineCache;
 
   public:
-                      NTFFileReader( OGRNTFDataSource * );
+    explicit           NTFFileReader( OGRNTFDataSource * );
                       ~NTFFileReader();
 
     int               Open( const char * pszFilename = NULL );
@@ -293,10 +291,9 @@ class NTFFileReader
     void              Reset();
     void              SetBaseFID( long nFeatureId );
 
-
     OGRGeometry      *ProcessGeometry( NTFRecord *, int * = NULL );
     OGRGeometry      *ProcessGeometry3D( NTFRecord *, int * = NULL );
-    int               ProcessAttDesc( NTFRecord *, NTFAttDesc * );
+    static int               ProcessAttDesc( NTFRecord *, NTFAttDesc * );
     int               ProcessAttRec( NTFRecord *, int *, char ***, char ***);
     int               ProcessAttRecGroup( NTFRecord **, char ***, char ***);
 
@@ -392,8 +389,8 @@ class OGRNTFLayer : public OGRLayer
 
                         ~OGRNTFLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
 #ifdef notdef
     OGRFeature         *GetFeature( GIntBig nFeatureId );
@@ -401,13 +398,13 @@ class OGRNTFLayer : public OGRLayer
     OGRErr              ICreateFeature( OGRFeature *poFeature );
 #endif
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
 #ifdef notdef
     GIntBig             GetFeatureCount( int );
 #endif
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     // special to NTF
     OGRFeature         *FeatureTranslate( NTFFileReader *, NTFRecord ** );
@@ -427,24 +424,24 @@ class OGRNTFFeatureClassLayer : public OGRLayer
     int                 iCurrentFC;
 
   public:
-                        OGRNTFFeatureClassLayer( OGRNTFDataSource * poDS );
+    explicit             OGRNTFFeatureClassLayer( OGRNTFDataSource * poDS );
                         ~OGRNTFFeatureClassLayer();
 
-    OGRGeometry *       GetSpatialFilter() { return poFilterGeom; }
-    void                SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    OGRGeometry *       GetSpatialFilter() override { return poFilterGeom; }
+    void                SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeature         *GetFeature( GIntBig nFeatureId );
+    OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    GIntBig             GetFeatureCount( int = TRUE );
+    GIntBig             GetFeatureCount( int = TRUE ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -456,8 +453,6 @@ class OGRNTFRasterLayer : public OGRLayer
     OGRFeatureDefn     *poFeatureDefn;
     OGRGeometry        *poFilterGeom;
 
-    OGRNTFDataSource   *poDS;
-
     NTFFileReader      *poReader;
 
     float              *pafColumn;
@@ -471,23 +466,23 @@ class OGRNTFRasterLayer : public OGRLayer
   public:
                         OGRNTFRasterLayer( OGRNTFDataSource * poDS,
                                            NTFFileReader * poReaderIn );
-                        ~OGRNTFRasterLayer();
+                        virtual ~OGRNTFRasterLayer();
 
-    OGRGeometry *       GetSpatialFilter() { return poFilterGeom; }
-    void                SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    OGRGeometry *       GetSpatialFilter() override { return poFilterGeom; }
+    void                SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeature         *GetFeature( GIntBig nFeatureId );
+    OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    GIntBig             GetFeatureCount( int = TRUE );
+    GIntBig             GetFeatureCount( int = TRUE ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -533,16 +528,19 @@ class OGRNTFDataSource : public OGRDataSource
     int                 Open( const char * pszName, int bTestOpen = FALSE,
                               char ** papszFileList = NULL );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount();
-    OGRLayer            *GetLayer( int );
-    int                 TestCapability( const char * );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override;
+    OGRLayer            *GetLayer( int ) override;
+    int                 TestCapability( const char * ) override;
 
     // Note: these are specific to NTF for now, but eventually might
     // might be available as part of a more object oriented approach to
     // features like that in FME or SFCORBA.
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    virtual void        ResetReading() override;
+    virtual OGRFeature* GetNextFeature( OGRLayer** ppoBelongingLayer,
+                                        double* pdfProgressPct,
+                                        GDALProgressFunc pfnProgress,
+                                        void* pProgressData ) override;
 
     // these are only for the use of the NTFFileReader class.
     OGRNTFLayer         *GetNamedLayer( const char * );
diff --git a/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp b/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp
index 1388a21..bdd8d51 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_codelist.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ntf_codelist.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTFCodeList class implementation.
@@ -32,37 +31,31 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_codelist.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ntf_codelist.cpp 35191 2016-08-24 01:33:06Z goatbar $");
 
 /************************************************************************/
 /*                             NTFCodeList                              */
 /************************************************************************/
 
-NTFCodeList::NTFCodeList( NTFRecord * poRecord )
-
+NTFCodeList::NTFCodeList( NTFRecord * poRecord ) :
+    nNumCode(atoi(poRecord->GetField(20,22))),
+    papszCodeVal(static_cast<char **>(CPLMalloc(sizeof(char*) * nNumCode))),
+    papszCodeDes(static_cast<char **>(CPLMalloc(sizeof(char*) * nNumCode)))
 {
-    int         iThisField;
-    const char  *pszText;
 
     CPLAssert( EQUAL(poRecord->GetField(1,2),"42") );
 
     snprintf( szValType, sizeof(szValType), "%s", poRecord->GetField(13,14) );
     snprintf( szFInter, sizeof(szFInter), "%s", poRecord->GetField(15,19) );
 
-    nNumCode = atoi(poRecord->GetField(20,22));
-
-    papszCodeVal = (char **) CPLMalloc(sizeof(char*) * nNumCode );
-    papszCodeDes = (char **) CPLMalloc(sizeof(char*) * nNumCode );
-
-    pszText = poRecord->GetData() + 22;
-    for( iThisField=0;
+    const char *pszText = poRecord->GetData() + 22;
+    int iThisField = 0;
+    for( ;
          *pszText != '\0' && iThisField < nNumCode;
          iThisField++ )
     {
-        char    szVal[128], szDes[128];
-        int     iLen;
-
-        iLen = 0;
+        char szVal[128] = {};
+        int iLen = 0;
         while( *pszText != '\\' && *pszText != '\0' )
             szVal[iLen++] = *(pszText++);
         szVal[iLen] = '\0';
@@ -71,6 +64,7 @@ NTFCodeList::NTFCodeList( NTFRecord * poRecord )
             pszText++;
 
         iLen = 0;
+        char szDes[128] = {};
         while( *pszText != '\\' && *pszText != '\0' )
             szDes[iLen++] = *(pszText++);
         szDes[iLen] = '\0';
diff --git a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp b/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
index bc25656..5407c57 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_estlayers.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ntf_estlayers.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTFFileReader methods related to establishing the schemas
@@ -33,9 +32,9 @@
 #include "ntf.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_estlayers.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ntf_estlayers.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
-#define MAX_LINK        5000
+static const int MAX_LINK = 5000;
 
 /************************************************************************/
 /*                         TranslateCodePoint()                         */
@@ -141,7 +140,7 @@ static OGRFeature *TranslateOscarPoint( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -176,7 +175,7 @@ static OGRFeature *TranslateOscarLine( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -212,7 +211,7 @@ static OGRFeature *TranslateOscarRoutePoint( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -270,7 +269,7 @@ static OGRFeature *TranslateOscarRouteLine( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -355,7 +354,7 @@ static OGRFeature *TranslateOscarNetworkPoint( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -391,7 +390,7 @@ static OGRFeature *TranslateOscarNetworkLine( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -427,7 +426,7 @@ static OGRFeature *TranslateBasedataPoint( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -464,7 +463,7 @@ static OGRFeature *TranslateBasedataLine( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -500,7 +499,7 @@ static OGRFeature *TranslateBoundarylineCollection( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // NUM_PARTS
-    int         nNumLinks = atoi(papoGroup[0]->GetField( 9, 12 ));
+    int nNumLinks = atoi(papoGroup[0]->GetField( 9, 12 ));
 
     if( nNumLinks > MAX_LINK )
     {
@@ -603,9 +602,9 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
 /* -------------------------------------------------------------------- */
 /*      First we do validation of the grouping.                         */
 /* -------------------------------------------------------------------- */
-    int         iRec;
+    int iRec = 0;  // Used after for.
 
-    for( iRec = 0;
+    for( ;
          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
              && papoGroup[iRec]->GetType() == NRT_POLYGON
              && papoGroup[iRec+1]->GetType() == NRT_CHAIN;
@@ -625,10 +624,12 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
 /*      boundaries are.  The boundary information will be emitted      */
 /*      in the RingStart field.                                         */
 /* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
-    int         nNumLink = 0;
-    int         anDirList[MAX_LINK*2], anGeomList[MAX_LINK*2];
-    int         anRingStart[MAX_LINK], nRings = 0;
+    OGRFeature *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
+    int nNumLink = 0;
+    int anDirList[MAX_LINK*2] = {};
+    int anGeomList[MAX_LINK*2] = {};
+    int anRingStart[MAX_LINK] = {};
+    int nRings = 0;
 
     for( iRec = 0;
          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
@@ -636,13 +637,11 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
              && papoGroup[iRec+1]->GetType() == NRT_CHAIN;
          iRec += 2 )
     {
-        int             i, nLineCount;
-
-        nLineCount = atoi(papoGroup[iRec+1]->GetField(9,12));
+        const int nLineCount = atoi(papoGroup[iRec+1]->GetField(9,12));
 
         anRingStart[nRings++] = nNumLink;
 
-        for( i = 0; i < nLineCount && nNumLink < MAX_LINK*2; i++ )
+        for( int i = 0; i < nLineCount && nNumLink < MAX_LINK*2; i++ )
         {
             anDirList[nNumLink] =
                 atoi(papoGroup[iRec+1]->GetField( 19+i*7, 19+i*7 ));
@@ -673,7 +672,6 @@ static OGRFeature *TranslateBoundarylinePoly( NTFFileReader *poReader,
     // RingStart
     poFeature->SetField( 7, nRings, anRingStart );
 
-
 /* -------------------------------------------------------------------- */
 /*      collect information for whole complex polygon.                  */
 /* -------------------------------------------------------------------- */
@@ -713,7 +711,7 @@ static OGRFeature *TranslateBoundarylineLink( NTFFileReader *poReader,
     OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[0],
                                                              &nGeomId));
@@ -801,9 +799,9 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
 /* -------------------------------------------------------------------- */
 /*      First we do validation of the grouping.                         */
 /* -------------------------------------------------------------------- */
-    int         iRec;
+    int iRec = 0;  // Used after for.
 
-    for( iRec = 0;
+    for( ;
          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
              && papoGroup[iRec]->GetType() == NRT_POLYGON
              && papoGroup[iRec+1]->GetType() == NRT_CHAIN;
@@ -822,10 +820,12 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
 /*      boundaries are.  The boundary information will be emitted      */
 /*      in the RingStart field.                                         */
 /* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
-    int         nNumLink = 0;
-    int         anDirList[MAX_LINK*2], anGeomList[MAX_LINK*2];
-    int         anRingStart[MAX_LINK], nRings = 0;
+    OGRFeature *poFeature = new OGRFeature( poLayer->GetLayerDefn() );
+    int nNumLink = 0;
+    int anDirList[MAX_LINK*2] = {};
+    int anGeomList[MAX_LINK*2] = {};
+    int anRingStart[MAX_LINK] = {};
+    int nRings = 0;
 
     for( iRec = 0;
          papoGroup[iRec] != NULL && papoGroup[iRec+1] != NULL
@@ -833,13 +833,11 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
              && papoGroup[iRec+1]->GetType() == NRT_CHAIN;
          iRec += 2 )
     {
-        int             i, nLineCount;
-
-        nLineCount = atoi(papoGroup[iRec+1]->GetField(9,12));
+        const int nLineCount = atoi(papoGroup[iRec+1]->GetField(9,12));
 
         anRingStart[nRings++] = nNumLink;
 
-        for( i = 0; i < nLineCount && nNumLink < MAX_LINK*2; i++ )
+        for( int i = 0; i < nLineCount && nNumLink < MAX_LINK*2; i++ )
         {
             anDirList[nNumLink] =
                 atoi(papoGroup[iRec+1]->GetField( 19+i*7, 19+i*7 ));
@@ -870,7 +868,6 @@ static OGRFeature *TranslateBL2000Poly( NTFFileReader *poReader,
     // RingStart
     poFeature->SetField( 6, nRings, anRingStart );
 
-
 /* -------------------------------------------------------------------- */
 /*      collect information for whole complex polygon.                  */
 /* -------------------------------------------------------------------- */
@@ -910,7 +907,7 @@ static OGRFeature *TranslateBL2000Link( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -1008,7 +1005,7 @@ static OGRFeature *TranslateMeridianPoint( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -1046,7 +1043,7 @@ static OGRFeature *TranslateMeridianLine( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -1084,7 +1081,7 @@ static OGRFeature *TranslateMeridian2Point( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -1123,7 +1120,7 @@ static OGRFeature *TranslateMeridian2Line( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -1138,7 +1135,6 @@ static OGRFeature *TranslateMeridian2Line( NTFFileReader *poReader,
                                     "RC", 10, "LD", 11, "RD", 12, "WI", 14,
                                     NULL );
 
-
     return poFeature;
 }
 
@@ -1284,7 +1280,7 @@ static OGRFeature *TranslateStrategiPoint( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -1326,7 +1322,7 @@ static OGRFeature *TranslateStrategiLine( NTFFileReader *poReader,
     poFeature->SetField( 0, atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    int         nGeomId;
+    int nGeomId = 0;
 
     poFeature->SetGeometryDirectly(poReader->ProcessGeometry(papoGroup[1],
                                                              &nGeomId));
@@ -1676,15 +1672,11 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
                                     ... )
 
 {
-    va_list     hVaArgs;
-    OGRFeatureDefn *poDefn;
-    OGRNTFLayer         *poLayer;
-
 /* -------------------------------------------------------------------- */
 /*      Does this layer already exist?  If so, we do nothing            */
 /*      ... note that we don't check the definition.                    */
 /* -------------------------------------------------------------------- */
-    poLayer = poDS->GetNamedLayer(pszLayerName);
+    OGRNTFLayer *poLayer = poDS->GetNamedLayer(pszLayerName);
 
 /* ==================================================================== */
 /*      Create a new layer matching the request if we don't already      */
@@ -1695,7 +1687,7 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Create a new feature definition.                                */
 /* -------------------------------------------------------------------- */
-        poDefn = new OGRFeatureDefn( pszLayerName );
+        OGRFeatureDefn *poDefn = new OGRFeatureDefn( pszLayerName );
         poDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->GetSpatialRef());
         poDefn->SetGeomType( eGeomType );
         poDefn->Reference();
@@ -1703,21 +1695,20 @@ void NTFFileReader::EstablishLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Fetch definitions of each field in turn.                        */
 /* -------------------------------------------------------------------- */
+        va_list hVaArgs;
         va_start(hVaArgs, poClass);
         while( true )
         {
-            const char  *pszFieldName = va_arg(hVaArgs, const char *);
-            OGRFieldType     eType;
-            int          nWidth, nPrecision;
+            const char *pszFieldName = va_arg(hVaArgs, const char *);
 
             if( pszFieldName == NULL )
                 break;
 
-            eType = (OGRFieldType) va_arg(hVaArgs, int);
-            nWidth = va_arg(hVaArgs, int);
-            nPrecision = va_arg(hVaArgs, int);
+            const OGRFieldType eType = (OGRFieldType) va_arg(hVaArgs, int);
+            const int nWidth = va_arg(hVaArgs, int);
+            const int nPrecision = va_arg(hVaArgs, int);
 
-            OGRFieldDefn         oFieldDefn( pszFieldName, eType );
+            OGRFieldDefn oFieldDefn( pszFieldName, eType );
             oFieldDefn.SetWidth( nWidth );
             oFieldDefn.SetPrecision( nPrecision );
 
diff --git a/ogr/ogrsf_frmts/ntf/ntf_generic.cpp b/ogr/ogrsf_frmts/ntf/ntf_generic.cpp
index 09b866b..49053da 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_generic.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_generic.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ntf_generic.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  Handle NTF products that aren't recognised generically.
@@ -31,9 +30,9 @@
 #include "ntf.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntf_generic.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ntf_generic.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
-#define MAX_LINK        5000
+static const int MAX_LINK = 5000;
 
 /************************************************************************/
 /* ==================================================================== */
@@ -50,17 +49,15 @@ CPL_CVSID("$Id: ntf_generic.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 /*                           NTFGenericClass                            */
 /************************************************************************/
 
-NTFGenericClass::NTFGenericClass()
-{
-    nFeatureCount = 0;
-
-    b3D = FALSE;
-    nAttrCount = 0;
-    papszAttrNames = NULL;
-    papszAttrFormats = NULL;
-    panAttrMaxWidth = NULL;
-    pabAttrMultiple = NULL;
-}
+NTFGenericClass::NTFGenericClass() :
+    nFeatureCount(0),
+    b3D(FALSE),
+    nAttrCount(0),
+    papszAttrNames(NULL),
+    papszAttrFormats(NULL),
+    panAttrMaxWidth(NULL),
+    pabAttrMultiple(NULL)
+{}
 
 /************************************************************************/
 /*                           ~NTFGenericClass                           */
@@ -88,14 +85,12 @@ void NTFGenericClass::CheckAddAttr( const char * pszName,
                                     int nWidth )
 
 {
-    int         iAttrOffset;
-
     if( EQUAL(pszName,"TX") )
         pszName = "TEXT";
     if( EQUAL(pszName,"FC") )
         pszName = "FEAT_CODE";
 
-    iAttrOffset = CSLFindString( papszAttrNames, pszName );
+    const int iAttrOffset = CSLFindString( papszAttrNames, pszName );
 
     if( iAttrOffset == -1 )
     {
@@ -131,14 +126,12 @@ void NTFGenericClass::CheckAddAttr( const char * pszName,
 void NTFGenericClass::SetMultiple( const char *pszName )
 
 {
-    int         iAttrOffset;
-
     if( EQUAL(pszName,"TX") )
         pszName = "TEXT";
     if( EQUAL(pszName,"FC") )
         pszName = "FEAT_CODE";
 
-    iAttrOffset = CSLFindString( papszAttrNames, pszName );
+    const int iAttrOffset = CSLFindString( papszAttrNames, pszName );
     if( iAttrOffset == -1 )
         return;
 
@@ -208,9 +201,8 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
 
                   for( int iAtt = 0; papszTypes[iAtt] != NULL; iAtt++ )
                   {
-                      NTFAttDesc        *poAttDesc;
-
-                      poAttDesc = poReader->GetAttDesc( papszTypes[iAtt] );
+                      NTFAttDesc *poAttDesc =
+                          poReader->GetAttDesc( papszTypes[iAtt] );
                       if( poAttDesc != NULL )
                       {
                           poClass->CheckAddAttr( poAttDesc->val_type,
@@ -259,9 +251,8 @@ void OGRNTFDataSource::WorkupGeneric( NTFFileReader * poReader )
               case NRT_LINEREC:
                 if( poReader->GetNTFLevel() < 3 )
                 {
-                    NTFAttDesc  *poAttDesc;
-
-                    poAttDesc = poReader->GetAttDesc(poRecord->GetField(9,10));
+                    NTFAttDesc *poAttDesc =
+                        poReader->GetAttDesc(poRecord->GetField(9,10));
                     if( poAttDesc != NULL )
                         poClass->CheckAddAttr( poAttDesc->val_type,
                                                poAttDesc->finter, 6 );
@@ -295,14 +286,15 @@ static void AddGenericAttributes( NTFFileReader * poReader,
                                   OGRFeature * poFeature )
 
 {
-    char        **papszTypes, **papszValues;
+    char **papszTypes = NULL;
+    char **papszValues = NULL;
 
     if( !poReader->ProcessAttRecGroup( papoGroup, &papszTypes, &papszValues ) )
         return;
 
     for( int iAtt = 0; papszTypes != NULL && papszTypes[iAtt] != NULL; iAtt++ )
     {
-        int             iField;
+        int iField = 0;
 
         if( EQUAL(papszTypes[iAtt],"TX") )
             iField = poFeature->GetFieldIndex("TEXT");
@@ -321,12 +313,11 @@ static void AddGenericAttributes( NTFFileReader * poReader,
 /*      Do we have a corresponding list field we should be              */
 /*      accumulating this into?                                         */
 /* -------------------------------------------------------------------- */
-        char  szListName[128];
-        int   iListField;
+        char szListName[128] = {};
 
         snprintf( szListName, sizeof(szListName), "%s_LIST",
                  poFeature->GetFieldDefnRef(iField)->GetNameRef() );
-        iListField = poFeature->GetFieldIndex( szListName );
+        const int iListField = poFeature->GetFieldIndex( szListName );
 
 /* -------------------------------------------------------------------- */
 /*      Yes, so perform processing similar to ApplyAttributeValue(),    */
@@ -334,13 +325,15 @@ static void AddGenericAttributes( NTFFileReader * poReader,
 /* -------------------------------------------------------------------- */
         if( iListField != -1 )
         {
-            char        *pszAttLongName, *pszAttValue, *pszCodeDesc;
+            char *pszAttLongName = NULL;
+            char *pszAttValue = NULL;
+            char *pszCodeDesc = NULL;
 
             poReader->ProcessAttValue( papszTypes[iAtt], papszValues[iAtt],
                                        &pszAttLongName, &pszAttValue,
                                        &pszCodeDesc );
 
-            if( poFeature->IsFieldSet( iListField ) )
+            if( poFeature->IsFieldSetAndNotNull( iListField ) )
             {
                 poFeature->SetField( iListField,
                     CPLSPrintf( "%s,%s",
@@ -397,19 +390,20 @@ static OGRFeature *TranslateGenericNode( NTFFileReader *poReader,
     poFeature->SetField( "NUM_LINKS", nLinkCount );
 
     // GEOM_ID_OF_LINK
-    int      iLink;
-    for( iLink = 0; iLink < nLinkCount; iLink++ )
+    for( int iLink = 0; iLink < nLinkCount; iLink++ )
         panLinks[iLink] = atoi(papoGroup[0]->GetField(20+iLink*12,
                                                       25+iLink*12));
 
-    poFeature->SetField( "GEOM_ID_OF_LINK", nLinkCount, panLinks );
+    if( panLinks != NULL )
+        poFeature->SetField( "GEOM_ID_OF_LINK", nLinkCount, panLinks );
 
     // DIR
-    for( iLink = 0; iLink < nLinkCount; iLink++ )
+    for( int iLink = 0; iLink < nLinkCount; iLink++ )
         panLinks[iLink] = atoi(papoGroup[0]->GetField(19+iLink*12,
                                                       19+iLink*12));
 
-    poFeature->SetField( "DIR", nLinkCount, panLinks );
+    if( panLinks != NULL )
+        poFeature->SetField( "DIR", nLinkCount, panLinks );
 
     // should we add LEVEL and/or ORIENT?
 
@@ -449,19 +443,20 @@ static OGRFeature *TranslateGenericCollection( NTFFileReader *poReader,
     poFeature->SetField( "NUM_PARTS", nPartCount );
 
     // TYPE
-    int      iPart;
-    for( iPart = 0; iPart < nPartCount; iPart++ )
+    for( int iPart = 0; iPart < nPartCount; iPart++ )
         panParts[iPart] = atoi(papoGroup[0]->GetField(13+iPart*8,
                                                       14+iPart*8));
 
-    poFeature->SetField( "TYPE", nPartCount, panParts );
+    if( panParts != NULL )
+        poFeature->SetField( "TYPE", nPartCount, panParts );
 
     // ID
-    for( iPart = 0; iPart < nPartCount; iPart++ )
+    for( int iPart = 0; iPart < nPartCount; iPart++ )
         panParts[iPart] = atoi(papoGroup[0]->GetField(15+iPart*8,
                                                       20+iPart*8));
 
-    poFeature->SetField( "ID", nPartCount, panParts );
+    if( panParts != NULL )
+        poFeature->SetField( "ID", nPartCount, panParts );
 
     CPLFree( panParts );
 
@@ -480,8 +475,6 @@ static OGRFeature *TranslateGenericText( NTFFileReader *poReader,
                                          NTFRecord **papoGroup )
 
 {
-    int         iRec;
-
     if( CSLCount((char **) papoGroup) < 2
         || papoGroup[0]->GetType() != NRT_TEXTREC )
         return NULL;
@@ -492,7 +485,7 @@ static OGRFeature *TranslateGenericText( NTFFileReader *poReader,
     poFeature->SetField( "TEXT_ID", atoi(papoGroup[0]->GetField( 3, 8 )) );
 
     // Geometry
-    for( iRec = 0; papoGroup[iRec] != NULL; iRec++ )
+    for( int iRec = 0; papoGroup[iRec] != NULL; iRec++ )
     {
         if( papoGroup[iRec]->GetType() == NRT_GEOMETRY
             || papoGroup[iRec]->GetType() == NRT_GEOMETRY3D )
@@ -508,9 +501,9 @@ static OGRFeature *TranslateGenericText( NTFFileReader *poReader,
     AddGenericAttributes( poReader, papoGroup, poFeature );
 
     // TEXTREP information
-    for( iRec = 0; papoGroup[iRec] != NULL; iRec++ )
+    for( int iRec = 0; papoGroup[iRec] != NULL; iRec++ )
     {
-        NTFRecord       *poRecord = papoGroup[iRec];
+        NTFRecord *poRecord = papoGroup[iRec];
 
         if( poRecord->GetType() == NRT_TEXTREP )
         {
@@ -540,8 +533,6 @@ static OGRFeature *TranslateGenericName( NTFFileReader *poReader,
                                          NTFRecord **papoGroup )
 
 {
-    int         iRec;
-
     if( CSLCount((char **) papoGroup) < 2
         || papoGroup[0]->GetType() != NRT_NAMEREC )
         return NULL;
@@ -560,7 +551,7 @@ static OGRFeature *TranslateGenericName( NTFFileReader *poReader,
     poFeature->SetField( "TEXT", papoGroup[0]->GetField( 15, 15+nNumChar-1));
 
     // Geometry
-    for( iRec = 0; papoGroup[iRec] != NULL; iRec++ )
+    for( int iRec = 0; papoGroup[iRec] != NULL; iRec++ )
     {
         if( papoGroup[iRec]->GetType() == NRT_GEOMETRY
             || papoGroup[iRec]->GetType() == NRT_GEOMETRY3D )
@@ -576,7 +567,7 @@ static OGRFeature *TranslateGenericName( NTFFileReader *poReader,
     AddGenericAttributes( poReader, papoGroup, poFeature );
 
     // NAMEPOSTN information
-    for( iRec = 0; papoGroup[iRec] != NULL; iRec++ )
+    for( int iRec = 0; papoGroup[iRec] != NULL; iRec++ )
     {
         NTFRecord       *poRecord = papoGroup[iRec];
 
@@ -636,7 +627,7 @@ static OGRFeature *TranslateGenericPoint( NTFFileReader *poReader,
         snprintf( szValType, sizeof(szValType), "%s", papoGroup[0]->GetField(9,10) );
         if( !EQUAL(szValType,"  ") )
         {
-            char        *pszProcessedValue;
+            char *pszProcessedValue = NULL;
 
             if( poReader->ProcessAttValue(szValType,
                                           papoGroup[0]->GetField(11,16),
@@ -683,12 +674,12 @@ static OGRFeature *TranslateGenericLine( NTFFileReader *poReader,
     // Handle singular attribute in pre-level 3 LINEREC.
     if( poReader->GetNTFLevel() < 3 )
     {
-        char    szValType[3];
+        char szValType[3] = {};
 
         snprintf( szValType, sizeof(szValType), "%s", papoGroup[0]->GetField(9,10) );
         if( !EQUAL(szValType,"  ") )
         {
-            char        *pszProcessedValue;
+            char *pszProcessedValue = NULL;
 
             if( poReader->ProcessAttValue(szValType,
                                           papoGroup[0]->GetField(11,16),
@@ -827,11 +818,11 @@ static OGRFeature *TranslateGenericCPoly( NTFFileReader *poReader,
 /*      boundaries are.  The boundary information will be emitted      */
 /*      in the RingStart field.                                         */
 /* -------------------------------------------------------------------- */
-    int         nNumLink = 0, iLink;
+    int         nNumLink = 0;
     int         anPolyId[MAX_LINK*2];
 
     nNumLink = atoi(papoGroup[0]->GetField(9,12));
-    for( iLink = 0; iLink < nNumLink; iLink++ )
+    for( int iLink = 0; iLink < nNumLink; iLink++ )
     {
         anPolyId[iLink] = atoi(papoGroup[0]->GetField(13 + iLink*7,
                                                       18 + iLink*7));
@@ -853,8 +844,6 @@ static OGRFeature *TranslateGenericCPoly( NTFFileReader *poReader,
 void OGRNTFDataSource::EstablishGenericLayers()
 
 {
-    int         iType;
-
 /* -------------------------------------------------------------------- */
 /*      Pick an initial NTFFileReader to build the layers against.      */
 /* -------------------------------------------------------------------- */
@@ -871,7 +860,7 @@ void OGRNTFDataSource::EstablishGenericLayers()
 /*      If any of the generic classes are 3D, then assume all our       */
 /*      geometry should be marked as 3D.                                */
 /* -------------------------------------------------------------------- */
-        for( iType = 0; iType < 99; iType++ )
+        for( int iType = 0; iType < 99; iType++ )
         {
             NTFGenericClass     *poClass = aoGenericClass + iType;
 
@@ -882,7 +871,7 @@ void OGRNTFDataSource::EstablishGenericLayers()
 /* -------------------------------------------------------------------- */
 /*      Create layers for all recognised layer types with features.     */
 /* -------------------------------------------------------------------- */
-        for( iType = 0; iType < 99; iType++ )
+        for( int iType = 0; iType < 99; iType++ )
         {
             NTFGenericClass     *poClass = aoGenericClass + iType;
 
diff --git a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
index 2952639..b9b0ec1 100644
--- a/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntf_raster.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ntf_raster.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  Handle UK Ordnance Survey Raster DTM products.  Includes some
@@ -31,7 +30,9 @@
 
 #include "ntf.h"
 
-CPL_CVSID("$Id: ntf_raster.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ntf_raster.cpp 36332 2016-11-20 15:19:39Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -60,7 +61,7 @@ void NTFFileReader::EstablishRasterAccess()
 /* -------------------------------------------------------------------- */
 /*      Read the type 50 record.                                        */
 /* -------------------------------------------------------------------- */
-    NTFRecord   *poRecord;
+    NTFRecord *poRecord = NULL;
 
     while( (poRecord = ReadRecord()) != NULL
            && poRecord->GetType() != NRT_GRIDHREC
@@ -153,9 +154,7 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
 /* -------------------------------------------------------------------- */
     if( panColumnOffset[iColumn] == 0 )
     {
-        int     iPrev;
-
-        for( iPrev = 0; iPrev < iColumn-1; iPrev++ )
+        for( int iPrev = 0; iPrev < iColumn-1; iPrev++ )
         {
             if( panColumnOffset[iPrev+1] == 0 )
             {
@@ -177,10 +176,8 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
 /* -------------------------------------------------------------------- */
 /*      Read requested record.                                          */
 /* -------------------------------------------------------------------- */
-    NTFRecord   *poRecord;
-
     SetFPPos( panColumnOffset[iColumn], iColumn );
-    poRecord = ReadRecord();
+    NTFRecord *poRecord = ReadRecord();
 
     if( iColumn < nRasterXSize-1 )
     {
@@ -192,10 +189,8 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
 /* -------------------------------------------------------------------- */
     if( pafElev != NULL && GetProductId() == NPC_LANDRANGER_DTM )
     {
-        double  dfVScale, dfVOffset;
-
-        dfVOffset = atoi(poRecord->GetField(56,65));
-        dfVScale = atoi(poRecord->GetField(66,75)) * 0.001;
+        const double dfVOffset = atoi(poRecord->GetField(56,65));
+        const double dfVScale = atoi(poRecord->GetField(66,75)) * 0.001;
 
         for( int iPixel = 0; iPixel < nRasterXSize; iPixel++ )
         {
@@ -232,38 +227,31 @@ CPLErr NTFFileReader::ReadRasterColumn( int iColumn, float *pafElev )
 /************************************************************************/
 
 OGRNTFRasterLayer::OGRNTFRasterLayer( OGRNTFDataSource *poDSIn,
-                                      NTFFileReader * poReaderIn )
-
+                                      NTFFileReader * poReaderIn ) :
+    poFeatureDefn(NULL),
+    poFilterGeom(NULL),
+    poReader(poReaderIn),
+    pafColumn(static_cast<float *>(
+        CPLCalloc(sizeof(float), poReaderIn->GetRasterYSize()))),
+    iColumnOffset(-1),
+    iCurrentFC(0),
+    // Check for DEM subsampling.
+    nDEMSample(poDSIn->GetOption( "DEM_SAMPLE" ) == NULL ?
+               1 : std::max(1, atoi(poDSIn->GetOption("DEM_SAMPLE")))),
+    nFeatureCount(0)
 {
-    char        szLayerName[128];
-
-    snprintf( szLayerName, sizeof(szLayerName), "DTM_%s", poReaderIn->GetTileName() );
+    char szLayerName[128];
+    snprintf( szLayerName, sizeof(szLayerName),
+              "DTM_%s", poReaderIn->GetTileName() );
     poFeatureDefn = new OGRFeatureDefn( szLayerName );
+
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPoint25D );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDSIn->GetSpatialRef());
 
-    OGRFieldDefn      oHeight( "HEIGHT", OFTReal );
+    OGRFieldDefn oHeight( "HEIGHT", OFTReal );
     poFeatureDefn->AddFieldDefn( &oHeight );
 
-    poReader = poReaderIn;
-    poDS = poDSIn;
-    poFilterGeom = NULL;
-
-    pafColumn = (float *) CPLCalloc(sizeof(float),
-                                    poReader->GetRasterYSize());
-    iColumnOffset = -1;
-    iCurrentFC = 0;
-
-/* -------------------------------------------------------------------- */
-/*      Check for DEM subsampling, and compute total feature count      */
-/*      accordingly.                                                    */
-/* -------------------------------------------------------------------- */
-    if( poDS->GetOption( "DEM_SAMPLE" ) == NULL )
-        nDEMSample = 1;
-    else
-        nDEMSample = MAX(1,atoi(poDS->GetOption("DEM_SAMPLE")));
-
     nFeatureCount = (poReader->GetRasterXSize() / nDEMSample)
                   * (poReader->GetRasterYSize() / nDEMSample);
 }
@@ -417,16 +405,8 @@ int OGRNTFRasterLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite)
-             || EQUAL(pszCap,OLCRandomWrite) )
-        return FALSE;
-
     else if( EQUAL(pszCap,OLCFastFeatureCount) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return FALSE;
-
-    else
-        return FALSE;
+    return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/ntf/ntfdump.cpp b/ogr/ogrsf_frmts/ntf/ntfdump.cpp
index 1fad9c5..72e3252 100644
--- a/ogr/ogrsf_frmts/ntf/ntfdump.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntfdump.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ntfdump.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  Simple test harness.
@@ -31,7 +30,7 @@
 #include "cpl_vsi.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntfdump.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+CPL_CVSID("$Id: ntfdump.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 static void NTFDump( const char * pszFile, char **papszOptions );
 static void NTFCount( const char * pszFile );
@@ -82,30 +81,25 @@ int main( int argc, char ** argv )
 static void NTFCount( const char * pszFile )
 
 {
-    FILE      *fp;
-    NTFRecord *poRecord = NULL;
-    int       anCount[100], i;
-
-    for( i = 0; i < 100; i++ )
-        anCount[i] = 0;
-
-    fp = VSIFOpen( pszFile, "r" );
+    FILE *fp = VSIFOpen( pszFile, "r" );
     if( fp == NULL )
         return;
 
+    int anCount[100] = {};
+
+    NTFRecord *poRecord = NULL;
     do {
         if( poRecord != NULL )
             delete poRecord;
 
         poRecord = new NTFRecord( fp );
         anCount[poRecord->GetType()]++;
-
     } while( poRecord->GetType() != 99 );
 
     VSIFClose( fp );
 
     printf( "\nReporting on: %s\n", pszFile );
-    for( i = 0; i < 100; i++ )
+    for( int i = 0; i < 100; i++ )
     {
         if( anCount[i] > 0 )
             printf( "Found %d records of type %d\n", anCount[i], i );
@@ -119,14 +113,14 @@ static void NTFCount( const char * pszFile )
 static void NTFDump( const char * pszFile, char **papszOptions )
 
 {
-    OGRFeature         *poFeature;
-    OGRNTFDataSource   oDS;
+    OGRNTFDataSource oDS;
 
     oDS.SetOptionList( papszOptions );
 
     if( !oDS.Open( pszFile ) )
         return;
 
+    OGRFeature *poFeature = NULL;
     while( (poFeature = oDS.GetNextFeature()) != NULL )
     {
         printf( "-------------------------------------\n" );
diff --git a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp b/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
index f58a689..1342e5f 100644
--- a/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntffilereader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ntffilereader.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTFFileReader class implementation.
@@ -34,7 +33,9 @@
 #include "cpl_string.h"
 #include "ogr_api.h"
 
-CPL_CVSID("$Id: ntffilereader.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ntffilereader.cpp 36776 2016-12-10 11:17:47Z rouault $");
 
 static int DefaultNTFRecordGrouper( NTFFileReader *, NTFRecord **,
                                     NTFRecord * );
@@ -87,6 +88,7 @@ NTFFileReader::NTFFileReader( OGRNTFDataSource * poDataSource ) :
     papoLineCache(NULL)
 {
     apoCGroup[0] = NULL;
+    memset( adfGeoTransform, 0, sizeof(adfGeoTransform) );
     memset( apoTypeTranslation, 0, sizeof(apoTypeTranslation) );
     for( int i = 0; i < 100; i++ )
     {
@@ -136,8 +138,6 @@ void NTFFileReader::SetBaseFID( long nNewBase )
 void NTFFileReader::ClearDefs()
 
 {
-    int         i;
-
     Close();
 
     ClearCGroup();
@@ -148,7 +148,7 @@ void NTFFileReader::ClearDefs()
     papszFCName = NULL;
     nFCCount = 0;
 
-    for( i = 0; i < nAttCount; i++ )
+    for( int i = 0; i < nAttCount; i++ )
     {
         if( pasAttDesc[i].poCodeList != NULL )
             delete pasAttDesc[i].poCodeList;
@@ -231,7 +231,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 /* -------------------------------------------------------------------- */
     if( pszFilenameIn == NULL )
     {
-        NTFRecord      *poRecord;
+        NTFRecord *poRecord = NULL;
 
         for( poRecord = new NTFRecord( fp );
              poRecord->GetType() != NRT_VTR && poRecord->GetType() != NRT_SHR;
@@ -269,7 +269,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 /* -------------------------------------------------------------------- */
 /*      Read records till we get the section header.                    */
 /* -------------------------------------------------------------------- */
-    NTFRecord      *poRecord;
+    NTFRecord *poRecord = NULL;
 
     for( poRecord = new NTFRecord( fp );
          poRecord->GetType() != NRT_VTR && poRecord->GetType() != NRT_SHR;
@@ -280,18 +280,16 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 /* -------------------------------------------------------------------- */
         if( poRecord->GetType() == NRT_FCR )
         {
-            const char      *pszData;
-            int             iChar;
-
             nFCCount++;
 
             papszFCNum = CSLAddString( papszFCNum, poRecord->GetField(3,6) );
 
             CPLString osFCName;
-            pszData = poRecord->GetData();
+            const char *pszData = poRecord->GetData();
 
             // CODE_COM
-            for( iChar = 15; pszData[iChar] == ' ' && iChar > 5; iChar-- ) {}
+            int iChar = 15;
+            for( ; pszData[iChar] == ' ' && iChar > 5; iChar-- ) {}
 
             if( iChar > 6 )
                 osFCName += poRecord->GetField(7,iChar+1);
@@ -301,7 +299,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 
             if( iChar > 15 )
             {
-                if( osFCName.size() )
+                if( !osFCName.empty() )
                     osFCName += " : " ;
                 osFCName += poRecord->GetField(17,iChar+1);
             }
@@ -313,7 +311,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 
             if( iChar > 37 )
             {
-                if( osFCName.size() )
+                if( !osFCName.empty() )
                     osFCName += " : " ;
                 osFCName += poRecord->GetField(37,iChar);
             }
@@ -339,11 +337,8 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 /* -------------------------------------------------------------------- */
         else if( poRecord->GetType() == NRT_CODELIST )
         {
-            NTFCodeList *poCodeList;
-            NTFAttDesc  *psAttDesc;
-
-            poCodeList = new NTFCodeList( poRecord );
-            psAttDesc = GetAttDesc( poCodeList->szValType );
+            NTFCodeList *poCodeList = new NTFCodeList( poRecord );
+            NTFAttDesc  *psAttDesc = GetAttDesc( poCodeList->szValType );
             if( psAttDesc == NULL )
             {
                 CPLDebug( "NTF", "Got CODELIST for %s without ATTDESC.",
@@ -361,17 +356,15 @@ int NTFFileReader::Open( const char * pszFilenameIn )
 /* -------------------------------------------------------------------- */
         else if( poRecord->GetType() == NRT_DHR )
         {
-            int         iChar;
             pszProduct = CPLStrdup(poRecord->GetField(3,22));
-            for( iChar = static_cast<int>(strlen(pszProduct))-1;
+            for( int iChar = static_cast<int>(strlen(pszProduct))-1;
                  iChar > 0 && pszProduct[iChar] == ' ';
                  pszProduct[iChar--] = '\0' ) {}
 
             pszPVName = CPLStrdup(poRecord->GetField(76+3,76+22));
-            for( iChar = static_cast<int>(strlen(pszPVName))-1;
+            for( int iChar = static_cast<int>(strlen(pszPVName))-1;
                  iChar > 0 && pszPVName[iChar] == ' ';
                  pszPVName[iChar--] = '\0' ) {}
-
         }
 
         delete poRecord;
@@ -501,9 +494,7 @@ int NTFFileReader::Open( const char * pszFilenameIn )
         dfScale = 10000;
     else if( nProduct == NPC_BASEDATA )
         dfScale = 625000;
-    else if( nProduct == NPC_BOUNDARYLINE )
-        dfScale = 10000;
-    else
+    else /*if( nProduct == NPC_BOUNDARYLINE ) or default case */
         dfScale = 10000;
 
     if( dfScale != 0.0 )
@@ -555,30 +546,28 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
                                              int * pnGeomId )
 
 {
-    int            nGType, nNumCoord;
-    OGRGeometry    *poGeometry = NULL;
-
     if( poRecord->GetType() == NRT_GEOMETRY3D )
         return ProcessGeometry3D( poRecord, pnGeomId );
 
     else if( poRecord->GetType() != NRT_GEOMETRY )
         return NULL;
 
-    nGType = atoi(poRecord->GetField(9,9));            // GTYPE
-    nNumCoord = atoi(poRecord->GetField(10,13));       // NUM_COORD
+    const int nGType = atoi(poRecord->GetField(9,9));            // GTYPE
+    const int nNumCoord = atoi(poRecord->GetField(10,13));       // NUM_COORD
     if( pnGeomId != NULL )
         *pnGeomId = atoi(poRecord->GetField(3,8));     // GEOM_ID
 
 /* -------------------------------------------------------------------- */
 /*      Point                                                           */
 /* -------------------------------------------------------------------- */
+    OGRGeometry *poGeometry = NULL;
     if( nGType == 1 )
     {
-        double      dfX, dfY;
-
-        dfX = atoi(poRecord->GetField(14,14+GetXYLen()-1)) * GetXYMult()
+        const double dfX =
+            atoi(poRecord->GetField(14,14+GetXYLen()-1)) * GetXYMult()
             + GetXOrigin();
-        dfY = atoi(poRecord->GetField(14+GetXYLen(),14+GetXYLen()*2-1))
+        const double dfY =
+            atoi(poRecord->GetField(14+GetXYLen(),14+GetXYLen()*2-1))
             * GetXYMult() + GetYOrigin();
 
         poGeometry = new OGRPoint( dfX, dfY );
@@ -590,19 +579,20 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
     else if( nGType == 2 || nGType == 3 || nGType == 4 )
     {
         OGRLineString      *poLine = new OGRLineString;
-        double             dfX, dfY, dfXLast=0.0, dfYLast=0.0;
-        int                iCoord, nOutCount = 0;
+        double dfXLast = 0.0;
+        double dfYLast = 0.0;
+        int nOutCount = 0;
 
         poGeometry = poLine;
         poLine->setNumPoints( nNumCoord );
-        for( iCoord = 0; iCoord < nNumCoord; iCoord++ )
+        for( int iCoord = 0; iCoord < nNumCoord; iCoord++ )
         {
-            int            iStart = 14 + iCoord * (GetXYLen()*2+1);
+            const int iStart = 14 + iCoord * (GetXYLen()*2+1);
 
-            dfX = atoi(poRecord->GetField(iStart+0,
+            const double dfX = atoi(poRecord->GetField(iStart+0,
                                           iStart+GetXYLen()-1))
                 * GetXYMult() + GetXOrigin();
-            dfY = atoi(poRecord->GetField(iStart+GetXYLen(),
+            const double dfY = atoi(poRecord->GetField(iStart+GetXYLen(),
                                           iStart+GetXYLen()*2-1))
                 * GetXYMult() + GetYOrigin();
 
@@ -629,12 +619,12 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
 /* -------------------------------------------------------------------- */
     else if( nGType == 5 && nNumCoord == 3 )
     {
-        double  adfX[3], adfY[3];
-        int     iCoord;
+        double adfX[3] = { 0.0, 0.0, 0.0 };
+        double adfY[3] = { 0.0, 0.0, 0.0 };
 
-        for( iCoord = 0; iCoord < nNumCoord; iCoord++ )
+        for( int iCoord = 0; iCoord < nNumCoord; iCoord++ )
         {
-            int            iStart = 14 + iCoord * (GetXYLen()*2+1);
+            const int iStart = 14 + iCoord * (GetXYLen()*2+1);
 
             adfX[iCoord] = atoi(poRecord->GetField(iStart+0,
                                                   iStart+GetXYLen()-1))
@@ -654,26 +644,28 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
 /* -------------------------------------------------------------------- */
     else if( nGType == 7 )
     {
-        double  dfCenterX, dfCenterY, dfArcX, dfArcY, dfRadius;
-        int     iCenterStart = 14;
-        int     iArcStart = 14 + 2 * GetXYLen() + 1;
+        const int iCenterStart = 14;
+        const int iArcStart = 14 + 2 * GetXYLen() + 1;
 
-        dfCenterX = atoi(poRecord->GetField(iCenterStart,
-                                            iCenterStart+GetXYLen()-1))
+        const double dfCenterX =
+            atoi(poRecord->GetField(iCenterStart, iCenterStart+GetXYLen()-1))
             * GetXYMult() + GetXOrigin();
-        dfCenterY = atoi(poRecord->GetField(iCenterStart+GetXYLen(),
-                                            iCenterStart+GetXYLen()*2-1))
+        const double dfCenterY =
+            atoi(poRecord->GetField(iCenterStart+GetXYLen(),
+                                    iCenterStart+GetXYLen()*2-1))
             * GetXYMult() + GetYOrigin();
 
-        dfArcX = atoi(poRecord->GetField(iArcStart,
-                                         iArcStart+GetXYLen()-1))
+        const double dfArcX =
+            atoi(poRecord->GetField(iArcStart, iArcStart+GetXYLen()-1))
             * GetXYMult() + GetXOrigin();
-        dfArcY = atoi(poRecord->GetField(iArcStart+GetXYLen(),
-                                         iArcStart+GetXYLen()*2-1))
+        const double dfArcY =
+            atoi(poRecord->GetField(iArcStart+GetXYLen(),
+                                    iArcStart+GetXYLen()*2-1))
             * GetXYMult() + GetYOrigin();
 
-        dfRadius = sqrt( (dfCenterX - dfArcX) * (dfCenterX - dfArcX)
-                         + (dfCenterY - dfArcY) * (dfCenterY - dfArcY) );
+        const double dfRadius =
+            sqrt( (dfCenterX - dfArcX) * (dfCenterX - dfArcX)
+                  + (dfCenterY - dfArcY) * (dfCenterY - dfArcY) );
 
         poGeometry = NTFStrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY,
                                                        dfRadius,
@@ -683,8 +675,9 @@ OGRGeometry *NTFFileReader::ProcessGeometry( NTFRecord * poRecord,
 
     else
     {
-        fprintf( stderr, "GType = %d\n", nGType );
-        CPLAssert( FALSE );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "GType = %d", nGType );
+        CPLAssert( false );
     }
 
     if( poGeometry != NULL )
@@ -701,52 +694,52 @@ OGRGeometry *NTFFileReader::ProcessGeometry3D( NTFRecord * poRecord,
                                                int * pnGeomId )
 
 {
-    int            nGType, nNumCoord;
-    OGRGeometry    *poGeometry = NULL;
+    OGRGeometry *poGeometry = NULL;
 
     if( poRecord->GetType() != NRT_GEOMETRY3D )
         return NULL;
 
-    nGType = atoi(poRecord->GetField(9,9));            // GTYPE
-    nNumCoord = atoi(poRecord->GetField(10,13));       // NUM_COORD
+    const int nGType = atoi(poRecord->GetField(9,9));  // GTYPE
+    const int nNumCoord = atoi(poRecord->GetField(10,13));       // NUM_COORD
     if( pnGeomId != NULL )
         *pnGeomId = atoi(poRecord->GetField(3,8));     // GEOM_ID
 
     if( nGType == 1 )
     {
-        double      dfX, dfY, dfZ;
-
-        dfX = atoi(poRecord->GetField(14,14+GetXYLen()-1)) * GetXYMult()
+        const double dfX =
+            atoi(poRecord->GetField(14,14+GetXYLen()-1)) * GetXYMult()
             + GetXOrigin();
-        dfY = atoi(poRecord->GetField(14+GetXYLen(),14+GetXYLen()*2-1))
+        const double dfY =
+            atoi(poRecord->GetField(14+GetXYLen(),14+GetXYLen()*2-1))
             * GetXYMult() + GetYOrigin();
-        dfZ = atoi(poRecord->GetField(14+1+2*GetXYLen(),
-                                      14+1+2*GetXYLen()+nZWidth-1)) * dfZMult;
-
+        const double dfZ =
+            atoi(poRecord->GetField(14+1+2*GetXYLen(),
+                                    14+1+2*GetXYLen()+nZWidth-1)) * dfZMult;
 
         poGeometry = new OGRPoint( dfX, dfY, dfZ );
     }
 
     else if( nGType == 2 )
     {
-        OGRLineString      *poLine = new OGRLineString;
-        double             dfX, dfY, dfZ, dfXLast=0.0, dfYLast=0.0;
-        int                iCoord, nOutCount = 0;
+        OGRLineString *poLine = new OGRLineString;
+        double dfXLast = 0.0;
+        double dfYLast = 0.0;
+        int nOutCount = 0;
 
         poGeometry = poLine;
         poLine->setNumPoints( nNumCoord );
-        for( iCoord = 0; iCoord < nNumCoord; iCoord++ )
+        for( int iCoord = 0; iCoord < nNumCoord; iCoord++ )
         {
-            int            iStart = 14 + iCoord * (GetXYLen()*2+nZWidth+2);
+            const int iStart = 14 + iCoord * (GetXYLen()*2+nZWidth+2);
 
-            dfX = atoi(poRecord->GetField(iStart+0,
+            const double dfX = atoi(poRecord->GetField(iStart+0,
                                           iStart+GetXYLen()-1))
                 * GetXYMult() + GetXOrigin();
-            dfY = atoi(poRecord->GetField(iStart+GetXYLen(),
+            const double dfY = atoi(poRecord->GetField(iStart+GetXYLen(),
                                           iStart+GetXYLen()*2-1))
                 * GetXYMult() + GetYOrigin();
 
-            dfZ = atoi(poRecord->GetField(iStart+1+2*GetXYLen(),
+            const double dfZ = atoi(poRecord->GetField(iStart+1+2*GetXYLen(),
                                           iStart+1+2*GetXYLen()+nZWidth-1))
                 * dfZMult;
 
@@ -781,9 +774,6 @@ OGRGeometry *NTFFileReader::ProcessGeometry3D( NTFRecord * poRecord,
 int NTFFileReader::ProcessAttDesc( NTFRecord * poRecord, NTFAttDesc* psAD )
 
 {
-    int      iChar;
-    const char *pszData;
-
     if( poRecord->GetType() != NRT_ADR )
         return FALSE;
 
@@ -792,8 +782,9 @@ int NTFFileReader::ProcessAttDesc( NTFRecord * poRecord, NTFAttDesc* psAD )
     snprintf( psAD->fwidth, sizeof(psAD->fwidth), "%s", poRecord->GetField( 5, 7 ));
     snprintf( psAD->finter, sizeof(psAD->finter), "%s", poRecord->GetField( 8, 12 ));
 
-    pszData = poRecord->GetData();
-    for( iChar = 12;
+    const char *pszData = poRecord->GetData();
+    int iChar = 12;  // Used after for.
+    for( ;
          pszData[iChar] != '\0' && pszData[iChar] != '\\';
          iChar++ ) {}
 
@@ -819,11 +810,11 @@ int NTFFileReader::ProcessAttRecGroup( NTFRecord **papoRecords,
 
     for( int iRec = 0; papoRecords[iRec] != NULL; iRec++ )
     {
-        char    **papszTypes1 = NULL, **papszValues1 = NULL;
-
         if( papoRecords[iRec]->GetType() != NRT_ATTREC )
             continue;
 
+        char **papszTypes1 = NULL;
+        char **papszValues1 = NULL;
         if( !ProcessAttRec( papoRecords[iRec], NULL,
                             &papszTypes1, &papszValues1 ) )
             return FALSE;
@@ -858,9 +849,6 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
                                   char *** ppapszValues )
 
 {
-    int            iOffset;
-    const char     *pszData;
-
     if( poRecord->GetType() != NRT_ATTREC )
         return FALSE;
 
@@ -877,20 +865,16 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
     *ppapszTypes = NULL;
     *ppapszValues = NULL;
 
-    iOffset = 8;
-    pszData = poRecord->GetData();
+    int iOffset = 8;
+    const char *pszData = poRecord->GetData();
 
     while( pszData[iOffset] != '0' && pszData[iOffset] != '\0' )
     {
-        NTFAttDesc *psAttDesc;
-        int         nEnd;
-        int         nFWidth;
-
 /* -------------------------------------------------------------------- */
 /*      Extract the two letter code name for the attribute, and use     */
 /*      it to find the correct ATTDESC info.                            */
 /* -------------------------------------------------------------------- */
-        psAttDesc = GetAttDesc(pszData + iOffset );
+        NTFAttDesc *psAttDesc = GetAttDesc(pszData + iOffset );
         if( psAttDesc == NULL )
         {
             CPLDebug( "NTF", "Couldn't translate attrec type `%2.2s'.",
@@ -906,7 +890,8 @@ int NTFFileReader::ProcessAttRec( NTFRecord * poRecord,
 /*      Establish the width of the value.  Zero width fields are        */
 /*      terminated by a backslash.                                      */
 /* -------------------------------------------------------------------- */
-        nFWidth = atoi(psAttDesc->fwidth);
+        const int nFWidth = atoi(psAttDesc->fwidth);
+        int nEnd = 0;
         if( nFWidth == 0 )
         {
             const char * pszData2 = poRecord->GetData();
@@ -981,7 +966,7 @@ int NTFFileReader::ProcessAttValue( const char *pszValType,
 /* -------------------------------------------------------------------- */
 /*      Find the ATTDESC for this attribute, and assign return name value.*/
 /* -------------------------------------------------------------------- */
-    NTFAttDesc      *psAttDesc = GetAttDesc(pszValType);
+    NTFAttDesc *psAttDesc = GetAttDesc(pszValType);
 
     if( psAttDesc == NULL )
         return FALSE;
@@ -995,17 +980,17 @@ int NTFFileReader::ProcessAttValue( const char *pszValType,
 /* -------------------------------------------------------------------- */
     if( psAttDesc->finter[0] == 'R' )
     {
-        static char      szRealString[30];
-        const char *pszDecimalPortion;
-        int       nWidth, nPrecision;
+        const char *pszDecimalPortion = NULL; // Used after for.
 
         for( pszDecimalPortion = psAttDesc->finter;
              *pszDecimalPortion != ',' && *pszDecimalPortion != '\0';
              pszDecimalPortion++ ) {}
 
-        nWidth = static_cast<int>(strlen(pszRawValue));
-        nPrecision = atoi(pszDecimalPortion+1);
+        const int nWidth = static_cast<int>(strlen(pszRawValue));
+        const int nPrecision = atoi(pszDecimalPortion+1);
 
+        // TODO(schwehr): Why static?
+        static char szRealString[30] = {};
         strncpy( szRealString, pszRawValue, nWidth - nPrecision );
         szRealString[nWidth-nPrecision] = '.';
         strcpy( szRealString+nWidth-nPrecision+1,
@@ -1020,7 +1005,8 @@ int NTFFileReader::ProcessAttValue( const char *pszValType,
 /* -------------------------------------------------------------------- */
     else if( psAttDesc->finter[0] == 'I' )
     {
-        static char    szIntString[30]; // FIXME thread unsafe
+        // TODO(schwehr): Why static?
+        static char szIntString[30]; // FIXME thread unsafe
 
         snprintf( szIntString, sizeof(szIntString), "%d", atoi(pszRawValue) );
 
@@ -1065,25 +1051,26 @@ void NTFFileReader::ApplyAttributeValues( OGRFeature * poFeature,
                                           NTFRecord ** papoGroup, ... )
 
 {
-    char        **papszTypes = NULL, **papszValues = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Extract attribute values from record group.                     */
 /* -------------------------------------------------------------------- */
+    char **papszTypes = NULL;
+    char **papszValues = NULL;
+
     if( !ProcessAttRecGroup( papoGroup, &papszTypes, &papszValues ) )
         return;
 
 /* -------------------------------------------------------------------- */
 /*      Handle attribute pairs                                          */
 /* -------------------------------------------------------------------- */
-    va_list     hVaArgs;
-    const char  *pszAttName;
+    va_list hVaArgs;
 
     va_start(hVaArgs, papoGroup);
 
+    const char *pszAttName = NULL;
     while( (pszAttName = va_arg(hVaArgs, const char *)) != NULL )
     {
-        int     iField = va_arg(hVaArgs, int);
+        const int iField = va_arg(hVaArgs, int);
 
         ApplyAttributeValue( poFeature, iField, pszAttName,
                              papszTypes, papszValues );
@@ -1098,7 +1085,6 @@ void NTFFileReader::ApplyAttributeValues( OGRFeature * poFeature,
     CSLDestroy( papszValues );
 }
 
-
 /************************************************************************/
 /*                        ApplyAttributeValue()                         */
 /*                                                                      */
@@ -1117,9 +1103,7 @@ int NTFFileReader::ApplyAttributeValue( OGRFeature * poFeature, int iField,
 /*      provided.  If not found that's fine, just return with           */
 /*      notification.                                                   */
 /* -------------------------------------------------------------------- */
-    int         iValue;
-
-    iValue = CSLFindString( papszTypes, pszAttName );
+    const int iValue = CSLFindString( papszTypes, pszAttName );
     if( iValue < 0 )
         return FALSE;
 
@@ -1128,10 +1112,12 @@ int NTFFileReader::ApplyAttributeValue( OGRFeature * poFeature, int iField,
 /*      Process the attribute value ... this really only has a          */
 /*      useful effect for real numbers.                                 */
 /* -------------------------------------------------------------------- */
-    char        *pszAttLongName, *pszAttValue, *pszCodeDesc;
+    char *pszAttLongName = NULL;
+    char *pszAttValue = NULL;
+    char *pszCodeDesc = NULL;
 
     if( !ProcessAttValue( pszAttName, papszValues[iValue],
-                     &pszAttLongName, &pszAttValue, &pszCodeDesc ) )
+                          &pszAttLongName, &pszAttValue, &pszCodeDesc ) )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -1176,9 +1162,7 @@ NTFRecord *NTFFileReader::ReadRecord()
 {
     if( poSavedRecord != NULL )
     {
-        NTFRecord       *poReturn;
-
-        poReturn = poSavedRecord;
+        NTFRecord *poReturn = poSavedRecord;
 
         poSavedRecord = NULL;
 
@@ -1186,12 +1170,10 @@ NTFRecord *NTFFileReader::ReadRecord()
     }
     else
     {
-        NTFRecord       *poRecord;
-
         CPLErrorReset();
         if( fp != NULL )
             nPreSavedPos = VSIFTell( fp );
-        poRecord = new NTFRecord( fp );
+        NTFRecord *poRecord = new NTFRecord( fp );
         if( fp != NULL )
             nPostSavedPos = VSIFTell( fp );
 
@@ -1350,8 +1332,8 @@ int DefaultNTFRecordGrouper( NTFFileReader *, NTFRecord ** papoGroup,
 /* -------------------------------------------------------------------- */
     if (poCandidate->GetType() != NRT_ATTREC )
     {
-        int     iRec;
-        for( iRec = 0; papoGroup[iRec] != NULL; iRec++ )
+        int iRec = 0;  // Used after for.
+        for( ; papoGroup[iRec] != NULL; iRec++ )
         {
             if( poCandidate->GetType() == papoGroup[iRec]->GetType() )
                 break;
@@ -1373,14 +1355,14 @@ int DefaultNTFRecordGrouper( NTFFileReader *, NTFRecord ** papoGroup,
 NTFRecord **NTFFileReader::ReadRecordGroup()
 
 {
-   NTFRecord     *poRecord;
-   int            nRecordCount = 0;
 
    ClearCGroup();
 
 /* -------------------------------------------------------------------- */
 /*      Loop, reading records till we think we have a grouping.         */
 /* -------------------------------------------------------------------- */
+   int nRecordCount = 0;
+   NTFRecord *poRecord = NULL;
    while( (poRecord = ReadRecord()) != NULL && poRecord->GetType() != NRT_VTR )
    {
        CPLAssert( nRecordCount < MAX_REC_GROUP);
@@ -1444,10 +1426,6 @@ int NTFFileReader::GetFeatureClass( int iFCIndex,
 OGRFeature * NTFFileReader::ReadOGRFeature( OGRNTFLayer * poTargetLayer )
 
 {
-    OGRNTFLayer *poLayer = NULL;
-    NTFRecord   **papoGroup;
-    OGRFeature  *poFeature = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      If this is a raster file, use a custom method to read the       */
 /*      feature.                                                        */
@@ -1459,8 +1437,13 @@ OGRFeature * NTFFileReader::ReadOGRFeature( OGRNTFLayer * poTargetLayer )
 /*      Loop looking for a group we can translate, and that if          */
 /*      needed matches our layer request.                               */
 /* -------------------------------------------------------------------- */
+    OGRNTFLayer *poLayer = NULL;
+    OGRFeature *poFeature = NULL;
+
     while( true )
     {
+        NTFRecord **papoGroup = NULL;
+
         if( GetProductId() == NPC_UNKNOWN && nNTFLevel > 2 )
             papoGroup = GetNextIndexedRecordGroup( apoCGroup + 1 );
         else
@@ -1495,7 +1478,9 @@ OGRFeature * NTFFileReader::ReadOGRFeature( OGRNTFLayer * poTargetLayer )
                       GetProduct() );
         }
         else
+        {
             break;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1503,9 +1488,7 @@ OGRFeature * NTFFileReader::ReadOGRFeature( OGRNTFLayer * poTargetLayer )
 /* -------------------------------------------------------------------- */
     if( poFeature != NULL )
     {
-        int             iTileRefField;
-
-        iTileRefField = poLayer->GetLayerDefn()->GetFieldCount()-1;
+        int iTileRefField = poLayer->GetLayerDefn()->GetFieldCount()-1;
 
         CPLAssert( EQUAL(poLayer->GetLayerDefn()->GetFieldDefn(iTileRefField)->
                          GetNameRef(), "TILE_REF") );
@@ -1527,7 +1510,7 @@ OGRFeature * NTFFileReader::ReadOGRFeature( OGRNTFLayer * poTargetLayer )
         nFeatureCount = nSavedFeatureId - nBaseFeatureId;
     }
 
-    return( poFeature );
+    return poFeature;
 }
 
 /************************************************************************/
@@ -1572,8 +1555,6 @@ void NTFFileReader::FreshenIndex()
 void NTFFileReader::IndexFile()
 
 {
-    NTFRecord   *poRecord;
-
     Reset();
 
     DestroyIndex();
@@ -1586,10 +1567,11 @@ void NTFFileReader::IndexFile()
 /*      Process all records after the section header, and before 99     */
 /*      to put them in the index.                                       */
 /* -------------------------------------------------------------------- */
+    NTFRecord *poRecord = NULL;
     while( (poRecord = ReadRecord()) != NULL && poRecord->GetType() != 99 )
     {
-        int     iType = poRecord->GetType();
-        int     iId = atoi(poRecord->GetField( 3, 8 ));
+        const int iType = poRecord->GetType();
+        const int iId = atoi(poRecord->GetField( 3, 8 ));
 
         if( iType < 0 || iType >= 100 )
         {
@@ -1605,7 +1587,7 @@ void NTFFileReader::IndexFile()
 /* -------------------------------------------------------------------- */
         if( anIndexSize[iType] <= iId )
         {
-            int nNewSize = MAX(iId+1,anIndexSize[iType] * 2 + 10);
+            const int nNewSize = std::max(iId+1, anIndexSize[iType] * 2 + 10);
 
             apapoRecordIndex[iType] = (NTFRecord **)
                 CPLRealloc(apapoRecordIndex[iType],
@@ -1687,15 +1669,13 @@ NTFRecord * NTFFileReader::GetIndexedRecord( int iType, int iId )
 static void AddToIndexGroup( NTFRecord **papoGroup, NTFRecord * poRecord )
 
 {
-    int         i;
-
-    for( i = 1; papoGroup[i] != NULL; i++ ) {}
+    int i = 1;  // Used after for.
+    for( ; papoGroup[i] != NULL; i++ ) {}
 
     papoGroup[i] = poRecord;
     papoGroup[i+1] = NULL;
 }
 
-
 /************************************************************************/
 /*                     GetNextIndexedRecordGroup()                      */
 /************************************************************************/
@@ -1816,13 +1796,12 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
         // records.
         for( int iRec = 1; apoCGroup[iRec] != NULL; iRec++ )
         {
-            int         nNumTEXR;
             NTFRecord  *poRecord = apoCGroup[iRec];
 
             if( poRecord->GetType() != NRT_TEXTPOS )
                 continue;
 
-            nNumTEXR = atoi(poRecord->GetField(9,10));
+            const int nNumTEXR = atoi(poRecord->GetField(9,10));
             for( int iTEXR = 0; iTEXR < nNumTEXR; iTEXR++ )
             {
                 AddToIndexGroup(
@@ -1852,7 +1831,6 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
                 GetIndexedRecord( NRT_ATTREC,
                                   atoi(poAnchor->GetField(iStart,iStart+5)) ));
         }
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -1870,16 +1848,16 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
 /* -------------------------------------------------------------------- */
     else if( poAnchor->GetType() == NRT_COLLECT )
     {
-        int     nParts = atoi(poAnchor->GetField(9,12));
-        int     nAttOffset = 13 + nParts * 8;
-        int     l_nAttCount = 0;
+        const int nParts = atoi(poAnchor->GetField(9,12));
+        const int nAttOffset = 13 + nParts * 8;
+        int l_nAttCount = 0;
 
         if( poAnchor->GetLength() > nAttOffset + 2 )
             l_nAttCount = atoi(poAnchor->GetField(nAttOffset,nAttOffset+1));
 
         for( int iAtt = 0; iAtt < l_nAttCount; iAtt++ )
         {
-            int iStart = nAttOffset + 2 + iAtt * 6;
+            const int iStart = nAttOffset + 2 + iAtt * 6;
 
             AddToIndexGroup(
                 apoCGroup,
@@ -1903,8 +1881,7 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
                                           atoi(poAnchor->GetField(15,20)) ) );
 
         // Attributes
-
-        int     l_nAttCount = 0;
+        int l_nAttCount = 0;
 
         if( poAnchor->GetLength() >= 22 )
             l_nAttCount = atoi(poAnchor->GetField(21,22));
@@ -1923,8 +1900,8 @@ NTFRecord **NTFFileReader::GetNextIndexedRecordGroup( NTFRecord **
 /* -------------------------------------------------------------------- */
     else if( poAnchor->GetType() == NRT_CPOLY )
     {
-        int     nPolyCount = atoi(poAnchor->GetField(9,12));
-        int     nPostPoly = nPolyCount*7 + 12;
+        int nPolyCount = atoi(poAnchor->GetField(9,12));
+        int nPostPoly = nPolyCount*7 + 12;
 
         if( poAnchor->GetLength() >= nPostPoly + 6 )
         {
@@ -2074,20 +2051,20 @@ int NTFFileReader::FormPolygonFromCache( OGRFeature * poFeature )
     if( !bCacheLines )
         return FALSE;
 
-    OGRGeometryCollection oLines;
-    const int *panLinks;
-    int        nLinkCount, i;
-
 /* -------------------------------------------------------------------- */
 /*      Collect all the linked lines.                                   */
 /* -------------------------------------------------------------------- */
-    panLinks = poFeature->GetFieldAsIntegerList( "GEOM_ID_OF_LINK",
-                                                 &nLinkCount );
+    int nLinkCount = 0;
+    const int *panLinks =
+        poFeature->GetFieldAsIntegerList( "GEOM_ID_OF_LINK",
+                                          &nLinkCount );
 
     if( panLinks == NULL )
         return FALSE;
 
-    for( i = 0; i < nLinkCount; i++ )
+    OGRGeometryCollection oLines;
+
+    for( int i = 0; i < nLinkCount; i++ )
     {
         OGRGeometry *poLine = CacheGetByGeomId( panLinks[i] );
         if( poLine == NULL )
@@ -2102,9 +2079,7 @@ int NTFFileReader::FormPolygonFromCache( OGRFeature * poFeature )
 /* -------------------------------------------------------------------- */
 /*      Assemble into a polygon geometry.                               */
 /* -------------------------------------------------------------------- */
-    OGRPolygon *poPoly;
-
-    poPoly = (OGRPolygon *)
+    OGRPolygon *poPoly = (OGRPolygon *)
         OGRBuildPolygonFromEdges( (OGRGeometryH) &oLines, FALSE, FALSE, 0.1,
                                   NULL );
 
diff --git a/ogr/ogrsf_frmts/ntf/ntfrecord.cpp b/ogr/ogrsf_frmts/ntf/ntfrecord.cpp
index 8e32efc..71d909c 100644
--- a/ogr/ogrsf_frmts/ntf/ntfrecord.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntfrecord.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ntfrecord.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTFRecord class implementation.
@@ -31,12 +30,12 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ntfrecord.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ntfrecord.cpp 35614 2016-10-05 16:34:38Z goatbar $");
 
 static int nFieldBufSize = 0;
 static char *pszFieldBuf = NULL;
 
-#define MAX_RECORD_LEN  160
+static const int MAX_RECORD_LEN = 160;
 
 /************************************************************************/
 /*                             NTFRecord()                              */
@@ -45,21 +44,19 @@ static char *pszFieldBuf = NULL;
 /*      transparent merging of continuation lines.                      */
 /************************************************************************/
 
-NTFRecord::NTFRecord( FILE * fp )
-
+NTFRecord::NTFRecord( FILE * fp ) :
+    nType(99),
+    nLength(0),
+    pszData(NULL)
 {
-    nType = 99;
-    nLength = 0;
-    pszData = NULL;
-
     if( fp == NULL )
         return;
 
 /* ==================================================================== */
 /*      Read lines until we get to one without a continuation mark.     */
 /* ==================================================================== */
-    char      szLine[MAX_RECORD_LEN+3];
-    int       nNewLength;
+    char szLine[MAX_RECORD_LEN+3] = {};
+    int nNewLength = 0;
 
     do {
         nNewLength = ReadPhysicalLine( fp, szLine );
@@ -119,7 +116,7 @@ NTFRecord::NTFRecord( FILE * fp )
 /* -------------------------------------------------------------------- */
     if( pszData != NULL )
     {
-        char      szType[3];
+        char  szType[3];
 
         strncpy( szType, pszData, 2 );
         szType[2] = '\0';
@@ -152,14 +149,12 @@ NTFRecord::~NTFRecord()
 int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
 
 {
-    int         nBytesRead = 0;
-    int         nRecordStart, nRecordEnd, i, l_nLength = 0;
-
 /* -------------------------------------------------------------------- */
 /*      Read enough data that we are sure we have a whole record.       */
 /* -------------------------------------------------------------------- */
-    nRecordStart = static_cast<int>(VSIFTell( fp ));
-    nBytesRead = static_cast<int>(VSIFRead( pszLine, 1, MAX_RECORD_LEN+2, fp ));
+    int nRecordStart = static_cast<int>(VSIFTell( fp ));
+    const int nBytesRead =
+        static_cast<int>(VSIFRead( pszLine, 1, MAX_RECORD_LEN+2, fp ));
 
     if( nBytesRead == 0 )
     {
@@ -176,7 +171,8 @@ int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
 /* -------------------------------------------------------------------- */
 /*      Search for CR or LF.                                            */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < nBytesRead; i++ )
+    int i = 0;  // Used after for.
+    for( ; i < nBytesRead; i++ )
     {
         if( pszLine[i] == 10 || pszLine[i] == 13 )
             break;
@@ -189,8 +185,9 @@ int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
     if( i == MAX_RECORD_LEN+2 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "%d byte record too long for NTF format.\n"
-                  "No line may be longer than 80 characters though up to %d tolerated.\n",
+                  "%d byte record too long for NTF format.  "
+                  "No line may be longer than 80 characters though up "
+                  "to %d tolerated.",
                   nBytesRead, MAX_RECORD_LEN );
         return -2;
     }
@@ -198,11 +195,9 @@ int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
 /* -------------------------------------------------------------------- */
 /*      Trim CR/LF.                                                     */
 /* -------------------------------------------------------------------- */
-    l_nLength = i;
-    if( pszLine[i+1] == 10 || pszLine[i+1] == 13 )
-        nRecordEnd = nRecordStart + i + 2;
-    else
-        nRecordEnd = nRecordStart + i + 1;
+    const int l_nLength = i;
+    const int nRecordEnd =
+        nRecordStart + i + ( pszLine[i+1] == 10 || pszLine[i+1] == 13 ? 2 : 1 );
 
     pszLine[l_nLength] = '\0';
 
@@ -226,7 +221,7 @@ int NTFRecord::ReadPhysicalLine( FILE *fp, char *pszLine )
 const char * NTFRecord::GetField( int nStart, int nEnd )
 
 {
-    int      nSize = nEnd - nStart + 1;
+    const int nSize = nEnd - nStart + 1;
 
 /* -------------------------------------------------------------------- */
 /*      Reallocate working buffer larger if needed.                     */
diff --git a/ogr/ogrsf_frmts/ntf/ntfstroke.cpp b/ogr/ogrsf_frmts/ntf/ntfstroke.cpp
index b5a3a52..ae0a872 100644
--- a/ogr/ogrsf_frmts/ntf/ntfstroke.cpp
+++ b/ogr/ogrsf_frmts/ntf/ntfstroke.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ntfstroke.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  NTF Translator
  * Purpose:  NTF Arc to polyline stroking code.  This code is really generic,
@@ -34,7 +33,9 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntfstroke.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ntfstroke.cpp 36024 2016-10-29 12:53:38Z goatbar $");
 
 /************************************************************************/
 /*                     NTFArcCenterFromEdgePoints()                     */
@@ -69,54 +70,46 @@ int NTFArcCenterFromEdgePoints( double x_c0, double y_c0,
 /*      second points.  Also compute the center point of the two        */
 /*      lines ... the point our crossing line will go through.          */
 /* -------------------------------------------------------------------- */
-    double m1, x1, y1;
-
-    if( (y_c1 - y_c0) != 0.0 )
-        m1 = (x_c0 - x_c1) / (y_c1 - y_c0);
-    else
-        m1 = 1e+10;
+    const double m1 =
+        (y_c1 - y_c0) != 0.0
+        ? (x_c0 - x_c1) / (y_c1 - y_c0)
+        : 1e+10;
 
-    x1 = (x_c0 + x_c1) * 0.5;
-    y1 = (y_c0 + y_c1) * 0.5;
+    const double x1 = (x_c0 + x_c1) * 0.5;
+    const double y1 = (y_c0 + y_c1) * 0.5;
 
 /* -------------------------------------------------------------------- */
 /*      Compute the same for the second point compared to the third     */
 /*      point.                                                          */
 /* -------------------------------------------------------------------- */
-    double m2, x2, y2;
-
-    if( (y_c2 - y_c1) != 0.0 )
-        m2 = (x_c1 - x_c2) / (y_c2 - y_c1);
-    else
-        m2 = 1e+10;
+    const double m2 =
+        (y_c2 - y_c1) != 0.0
+        ? (x_c1 - x_c2) / (y_c2 - y_c1)
+        : 1e+10;
 
-    x2 = (x_c1 + x_c2) * 0.5;
-    y2 = (y_c1 + y_c2) * 0.5;
+    const double x2 = (x_c1 + x_c2) * 0.5;
+    const double y2 = (y_c1 + y_c2) * 0.5;
 
 /* -------------------------------------------------------------------- */
 /*      Turn these into the Ax+By+C = 0 form of the lines.              */
 /* -------------------------------------------------------------------- */
-    double      a1, a2, b1, b2, c1, c2;
+    const double a1 = m1;
+    const double a2 = m2;
 
-    a1 = m1;
-    a2 = m2;
+    const double b1 = -1.0;
+    const double b2 = -1.0;
 
-    b1 = -1.0;
-    b2 = -1.0;
-
-    c1 = (y1 - m1*x1);
-    c2 = (y2 - m2*x2);
+    const double c1 = (y1 - m1*x1);
+    const double c2 = (y2 - m2*x2);
 
 /* -------------------------------------------------------------------- */
 /*      Compute the intersection of the two lines through the center    */
 /*      of the circle, using Kramers rule.                              */
 /* -------------------------------------------------------------------- */
-    double      det_inv;
-
     if( a1*b2 - a2*b1 == 0.0 )
         return FALSE;
 
-    det_inv = 1 / (a1*b2 - a2*b1);
+    const double det_inv = 1 / (a1*b2 - a2*b1);
 
     *x_center = (b1*c2 - b2*c1) * det_inv;
     *y_center = (a2*c1 - a1*c2) * det_inv;
@@ -135,8 +128,12 @@ NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
                                   int nVertexCount )
 
 {
-    double      dfStartAngle, dfEndAngle, dfAlongAngle;
-    double      dfCenterX, dfCenterY, dfRadius;
+    double dfStartAngle = 0.0;
+    double dfEndAngle = 0.0;
+    double dfAlongAngle = 0.0;
+    double dfCenterX = 0.0;
+    double dfCenterY = 0.0;
+    double dfRadius = 0.0;
 
     if( !NTFArcCenterFromEdgePoints( dfStartX, dfStartY, dfAlongX, dfAlongY,
                                      dfEndX, dfEndY, &dfCenterX, &dfCenterY ) )
@@ -149,15 +146,13 @@ NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
     }
     else
     {
-        double  dfDeltaX, dfDeltaY;
-
-        dfDeltaX = dfStartX - dfCenterX;
-        dfDeltaY = dfStartY - dfCenterY;
-        dfStartAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
+        double dfDeltaX = dfStartX - dfCenterX;
+        double dfDeltaY = dfStartY - dfCenterY;
+        dfStartAngle = atan2(dfDeltaY, dfDeltaX) * 180.0 / M_PI;
 
         dfDeltaX = dfAlongX - dfCenterX;
         dfDeltaY = dfAlongY - dfCenterY;
-        dfAlongAngle = atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
+        dfAlongAngle = atan2(dfDeltaY, dfDeltaX) * 180.0 / M_PI;
 
         dfDeltaX = dfEndX - dfCenterX;
         dfDeltaY = dfEndY - dfCenterY;
@@ -166,9 +161,7 @@ NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 #ifdef notdef
         if( dfStartAngle > dfAlongAngle && dfAlongAngle > dfEndAngle )
         {
-            double dfTempAngle;
-
-            dfTempAngle = dfStartAngle;
+            const double dfTempAngle = dfStartAngle;
             dfStartAngle = dfEndAngle;
             dfEndAngle = dfTempAngle;
         }
@@ -182,9 +175,7 @@ NTFStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 
         if( dfEndAngle - dfStartAngle > 360.0 )
         {
-            double dfTempAngle;
-
-            dfTempAngle = dfStartAngle;
+            const double dfTempAngle = dfStartAngle;
             dfStartAngle = dfEndAngle;
             dfEndAngle = dfTempAngle;
 
@@ -213,21 +204,19 @@ NTFStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
                                   int nVertexCount )
 
 {
-    OGRLineString      *poLine = new OGRLineString;
-    double             dfArcX, dfArcY, dfSlice;
-    int                iPoint;
+    OGRLineString *poLine = new OGRLineString;
 
-    nVertexCount = MAX(2,nVertexCount);
-    dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
+    nVertexCount = std::max(2, nVertexCount);
+    const double dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
 
     poLine->setNumPoints( nVertexCount );
 
-    for( iPoint=0; iPoint < nVertexCount; iPoint++ )
+    for( int iPoint = 0; iPoint < nVertexCount; iPoint++ )
     {
         double dfAngle = (dfStartAngle + iPoint * dfSlice) * M_PI / 180.0;
 
-        dfArcX = dfCenterX + cos(dfAngle) * dfRadius;
-        dfArcY = dfCenterY + sin(dfAngle) * dfRadius;
+        const double dfArcX = dfCenterX + cos(dfAngle) * dfRadius;
+        const double dfArcY = dfCenterY + sin(dfAngle) * dfRadius;
 
         poLine->setPoint( iPoint, dfArcX, dfArcY );
     }
diff --git a/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp b/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp
index 940c5f6..9bf64ea 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntfdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrntfdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  UK NTF Reader
  * Purpose:  Implements OGRNTFDataSource class
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrntfdatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrntfdatasource.cpp 36677 2016-12-04 13:42:55Z rouault $");
 
 /************************************************************************/
 /*                          OGRNTFDataSource()                          */
@@ -51,10 +50,22 @@ OGRNTFDataSource::OGRNTFDataSource() :
     nFCCount(0),
     papszFCNum(NULL),
     papszFCName(NULL),
+    poSpatialRef(new OGRSpatialReference(
+        "PROJCS[\"OSGB 1936 / British National Grid\",GEOGCS[\"OSGB 1936\","
+        "DATUM[\"OSGB_1936\",SPHEROID[\"Airy 1830\",6377563.396,299.3249646,"
+        "AUTHORITY[\"EPSG\",\"7001\"]],AUTHORITY[\"EPSG\",\"6277\"]],"
+        "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],"
+        "UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4277\"]],"
+        "PROJECTION[\"Transverse_Mercator\"],"
+        "PARAMETER[\"latitude_of_origin\",49],"
+        "PARAMETER[\"central_meridian\",-2],"
+        "PARAMETER[\"scale_factor\",0.999601272],"
+        "PARAMETER[\"false_easting\",400000],"
+        "PARAMETER[\"false_northing\",-100000],"
+        "UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],"
+        "AUTHORITY[\"EPSG\",\"27700\"]]")),
     papszOptions(NULL)
 {
-    poSpatialRef = new OGRSpatialReference( "PROJCS[\"OSGB 1936 / British National Grid\",GEOGCS[\"OSGB 1936\",DATUM[\"OSGB_1936\",SPHEROID[\"Airy 1830\",6377563.396,299.3249646,AUTHORITY[\"EPSG\",\"7001\"]],AUTHORITY[\"EPSG\",\"6277\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4277\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",49],PARAMETER[\"central_meridian\",-2],PARAMETER[\"scale_factor\", [...]
-
 /* -------------------------------------------------------------------- */
 /*      Allow initialization of options from the environment.           */
 /* -------------------------------------------------------------------- */
@@ -164,7 +175,6 @@ int OGRNTFDataSource::GetLayerCount()
         return nLayers + 1;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -201,10 +211,9 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
     }
     else
     {
-        char      **candidateFileList = VSIReadDir( pszFilename );
-        int         i;
+        char **candidateFileList = VSIReadDir( pszFilename );
 
-        for( i = 0;
+        for( int i = 0;
              candidateFileList != NULL && candidateFileList[i] != NULL;
              i++ )
         {
@@ -218,7 +227,7 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
             if( strlen(candidateFileList[i]) > 4
               && STARTS_WITH_CI(candidateFileList[i] + strlen(candidateFileList[i])-4, ".ntf") )
             {
-                char       fullFilename[2048];
+                char fullFilename[2048];
 
                 snprintf( fullFilename, sizeof(fullFilename), "%s%c%s",
                          pszFilename,
@@ -254,23 +263,18 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
 /*      open ... we don't want to occupy a lot of file handles when      */
 /*      handling a whole directory.                                     */
 /* -------------------------------------------------------------------- */
-    int         i;
-
     papoNTFFileReader = (NTFFileReader **)
         CPLCalloc(sizeof(void*), CSLCount(papszFileList));
 
-    for( i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
+    for( int i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
     {
         if( bTestOpen )
         {
-            char        szHeader[80];
-            FILE        *fp;
-            int         j;
-
-            fp = VSIFOpen( papszFileList[i], "rb" );
+            FILE *fp = VSIFOpen( papszFileList[i], "rb" );
             if( fp == NULL )
                 continue;
 
+            char szHeader[80] = {};
             if( VSIFRead( szHeader, 80, 1, fp ) < 1 )
             {
                 VSIFClose( fp );
@@ -282,7 +286,8 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
             if( !STARTS_WITH_CI(szHeader, "01") )
                 continue;
 
-            for( j = 0; j < 80; j++ )
+            int j = 0;  // Used after for.
+            for( ; j < 80; j++ )
             {
                 if( szHeader[j] == 10 || szHeader[j] == 13 )
                     break;
@@ -290,12 +295,9 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
 
             if( j == 80 || szHeader[j-1] != '%' )
                 continue;
-
         }
 
-        NTFFileReader   *poFR;
-
-        poFR = new NTFFileReader( this );
+        NTFFileReader *poFR = new NTFFileReader( this );
 
         if( !poFR->Open( papszFileList[i] ) )
         {
@@ -329,16 +331,17 @@ int OGRNTFDataSource::Open( const char * pszFilename, int bTestOpen,
 /* -------------------------------------------------------------------- */
     for( int iSrcFile = 0; iSrcFile < nNTFFileCount; iSrcFile++ )
     {
-        NTFFileReader   *poSrcReader = papoNTFFileReader[iSrcFile];
+        NTFFileReader *poSrcReader = papoNTFFileReader[iSrcFile];
 
         for( int iSrcFC = 0; iSrcFC < poSrcReader->GetFCCount(); iSrcFC++ )
         {
-            int         iDstFC;
-            char       *pszSrcFCName, *pszSrcFCNum;
+            char *pszSrcFCName = NULL;
+            char *pszSrcFCNum = NULL;
 
             poSrcReader->GetFeatureClass( iSrcFC, &pszSrcFCNum, &pszSrcFCName);
 
-            for( iDstFC = 0; iDstFC < nFCCount; iDstFC++ )
+            int iDstFC = 0;
+            for( ; iDstFC < nFCCount; iDstFC++ )
             {
                 if( EQUAL(pszSrcFCNum,papszFCNum[iDstFC]) )
                     break;
@@ -386,9 +389,17 @@ void OGRNTFDataSource::ResetReading()
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
-OGRFeature *OGRNTFDataSource::GetNextFeature()
+OGRFeature *OGRNTFDataSource::GetNextFeature( OGRLayer** ppoBelongingLayer,
+                                              double* pdfProgressPct,
+                                              GDALProgressFunc /* pfnProgress */,
+                                              void* /* pProgressData */ )
 
 {
+    if( pdfProgressPct != NULL )
+        *pdfProgressPct = 0.0;
+    if( ppoBelongingLayer != NULL )
+        *ppoBelongingLayer = NULL;
+
     OGRFeature  *poFeature = NULL;
 
 /* -------------------------------------------------------------------- */
@@ -442,7 +453,7 @@ OGRFeature *OGRNTFDataSource::GetNextFeature()
         nCurrentPos = -1;
         nCurrentFID = 1;
 
-        poFeature = GetNextFeature();
+        poFeature = GetNextFeature(NULL, NULL, NULL, NULL);
     }
     else
     {
@@ -511,16 +522,16 @@ const char *OGRNTFDataSource::GetOption( const char * pszOption )
 void OGRNTFDataSource::EnsureTileNameUnique( NTFFileReader *poNewReader )
 
 {
-    int       iSequenceNumber = -1;
-    int       bIsUnique;
-    char      szCandidateName[11];
+    int iSequenceNumber = -1;
+    bool bIsUnique = false;
+    char szCandidateName[11] = {};
 
-    szCandidateName[10] = '\0';
     do
     {
         bIsUnique = TRUE;
         if( iSequenceNumber++ == -1 )
-            strncpy( szCandidateName, poNewReader->GetTileName(), 10 );
+            strncpy( szCandidateName, poNewReader->GetTileName(),
+                     sizeof(szCandidateName) - 1 );
         else
             snprintf( szCandidateName, sizeof(szCandidateName), "%010d", iSequenceNumber );
 
@@ -540,5 +551,4 @@ void OGRNTFDataSource::EnsureTileNameUnique( NTFFileReader *poNewReader )
                   "to avoid conflict with other tiles in this data source.",
                   szCandidateName, poNewReader->GetFilename() );
     }
-
 }
diff --git a/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp b/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp
index f7ca088..4a2fa3a 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntfdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrntfdriver.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  UK NTF Reader
  * Purpose:  Implements OGRNTFDriver
@@ -30,7 +29,7 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrntfdriver.cpp 33105 2016-01-23 15:27:32Z rouault $");
+CPL_CVSID("$Id: ogrntfdriver.cpp 36334 2016-11-20 15:42:08Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -55,8 +54,8 @@ static GDALDataset *OGRNTFDriverOpen( GDALOpenInfo* poOpenInfo )
         if( !STARTS_WITH_CI(pszHeader, "01") )
             return NULL;
 
-        int j;
-        for( j = 0; j < 80; j++ )
+        int j = 0;  // Used after for.
+        for( ; j < 80; j++ )
         {
             if( pszHeader[j] == 10 || pszHeader[j] == 13 )
                 break;
@@ -66,7 +65,7 @@ static GDALDataset *OGRNTFDriverOpen( GDALOpenInfo* poOpenInfo )
             return NULL;
     }
 
-    OGRNTFDataSource    *poDS = new OGRNTFDataSource;
+    OGRNTFDataSource *poDS = new OGRNTFDataSource;
     if( !poDS->Open( poOpenInfo->pszFilename, TRUE ) )
     {
         delete poDS;
@@ -105,4 +104,3 @@ void RegisterOGRNTF()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp b/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp
index 620bc6d..13fcedd 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntffeatureclasslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrntffeatureclasslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  UK NTF Reader
  * Purpose:  Implements OGRNTFFeatureClassLayer class.
@@ -30,7 +29,7 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrntffeatureclasslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrntffeatureclasslayer.cpp 35191 2016-08-24 01:33:06Z goatbar $");
 
 /************************************************************************/
 /*                      OGRNTFFeatureClassLayer()                       */
@@ -39,29 +38,25 @@ CPL_CVSID("$Id: ogrntffeatureclasslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
 /*      OGRFeatureDefn object.                                          */
 /************************************************************************/
 
-OGRNTFFeatureClassLayer::OGRNTFFeatureClassLayer( OGRNTFDataSource *poDSIn )
-
+OGRNTFFeatureClassLayer::OGRNTFFeatureClassLayer( OGRNTFDataSource *poDSIn ) :
+    poFeatureDefn(new OGRFeatureDefn("FEATURE_CLASSES")),
+    poFilterGeom(NULL),
+    poDS(poDSIn),
+    iCurrentFC(0)
 {
-    poFilterGeom = NULL;
-
-    poDS = poDSIn;
-
-    iCurrentFC = 0;
-
 /* -------------------------------------------------------------------- */
 /*      Establish the schema.                                           */
 /* -------------------------------------------------------------------- */
-    poFeatureDefn = new OGRFeatureDefn( "FEATURE_CLASSES" );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->SetGeomType( wkbNone );
     poFeatureDefn->Reference();
 
-    OGRFieldDefn      oFCNum( "FEAT_CODE", OFTString );
+    OGRFieldDefn oFCNum( "FEAT_CODE", OFTString );
 
     oFCNum.SetWidth( 4 );
     poFeatureDefn->AddFieldDefn( &oFCNum );
 
-    OGRFieldDefn      oFCName( "FC_NAME", OFTString );
+    OGRFieldDefn oFCName( "FC_NAME", OFTString );
 
     oFCNum.SetWidth( 80 );
     poFeatureDefn->AddFieldDefn( &oFCName );
diff --git a/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp b/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp
index 93d19f9..4e393c2 100644
--- a/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp
+++ b/ogr/ogrsf_frmts/ntf/ogrntflayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrntflayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  UK NTF Reader
  * Purpose:  Implements OGRNTFLayer class.
@@ -30,7 +29,7 @@
 #include "ntf.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrntflayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrntflayer.cpp 36332 2016-11-20 15:19:39Z rouault $");
 
 /************************************************************************/
 /*                            OGRNTFLayer()                             */
@@ -41,17 +40,15 @@ CPL_CVSID("$Id: ogrntflayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 OGRNTFLayer::OGRNTFLayer( OGRNTFDataSource *poDSIn,
                           OGRFeatureDefn * poFeatureDefine,
-                          NTFFeatureTranslator pfnTranslatorIn )
-
+                          NTFFeatureTranslator pfnTranslatorIn ) :
+    poFeatureDefn(poFeatureDefine),
+    pfnTranslator(pfnTranslatorIn),
+    poDS(poDSIn),
+    iCurrentReader(-1),
+    nCurrentPos(-1),
+    nCurrentFID(1)
 {
-    poDS = poDSIn;
-    poFeatureDefn = poFeatureDefine;
     SetDescription( poFeatureDefn->GetName() );
-    pfnTranslator = pfnTranslatorIn;
-
-    iCurrentReader = -1;
-    nCurrentPos = -1;
-    nCurrentFID = 1;
 }
 
 /************************************************************************/
@@ -182,24 +179,10 @@ OGRFeature *OGRNTFLayer::GetNextFeature()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRNTFLayer::TestCapability( const char * pszCap )
+int OGRNTFLayer::TestCapability( const char * /* pszCap */ )
 
 {
-    if( EQUAL(pszCap,OLCRandomRead) )
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCSequentialWrite)
-             || EQUAL(pszCap,OLCRandomWrite) )
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCFastFeatureCount) )
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return FALSE;
-
-    else
-        return FALSE;
+    return FALSE;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/null/ogrnulldriver.cpp b/ogr/ogrsf_frmts/null/ogrnulldriver.cpp
index b93935b..bed1057 100644
--- a/ogr/ogrsf_frmts/null/ogrnulldriver.cpp
+++ b/ogr/ogrsf_frmts/null/ogrnulldriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrnulldriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  NULL output driver.
@@ -36,7 +35,7 @@
 
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrnulldriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrnulldriver.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 extern "C" void CPL_DLL RegisterOGRNULL();
 
@@ -55,18 +54,18 @@ class OGRNULLLayer : public OGRLayer
                                       OGRwkbGeometryType eType );
     virtual             ~OGRNULLLayer();
 
-    virtual OGRFeatureDefn *GetLayerDefn() {return poFeatureDefn;}
-    virtual OGRSpatialReference * GetSpatialRef() { return poSRS; }
+    virtual OGRFeatureDefn *GetLayerDefn() override {return poFeatureDefn;}
+    virtual OGRSpatialReference * GetSpatialRef() override { return poSRS; }
 
-    virtual void        ResetReading() {}
-    virtual int         TestCapability( const char * );
+    virtual void        ResetReading() override {}
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRFeature *GetNextFeature() { return NULL; }
+    virtual OGRFeature *GetNextFeature() override { return NULL; }
 
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) { return OGRERR_NONE; }
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override { return OGRERR_NONE; }
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 };
 
 /************************************************************************/
@@ -80,20 +79,19 @@ class OGRNULLDataSource : public OGRDataSource
     char*               pszName;
 
   public:
-                        OGRNULLDataSource(const char* pszNameIn);
-                        ~OGRNULLDataSource();
+               explicit OGRNULLDataSource(const char* pszNameIn);
+               virtual ~OGRNULLDataSource();
 
-    virtual const char *GetName() { return pszName; }
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer   *GetLayer( int );
+    virtual const char *GetName() override { return pszName; }
+    virtual int         GetLayerCount() override { return nLayers; }
+    virtual OGRLayer   *GetLayer( int ) override;
 
     virtual OGRLayer    *ICreateLayer( const char *pszLayerName,
                                       OGRSpatialReference *poSRS,
                                       OGRwkbGeometryType eType,
-                                      char **papszOptions );
-
-    virtual int         TestCapability( const char * );
+                                      char **papszOptions ) override;
 
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -103,14 +101,14 @@ class OGRNULLDataSource : public OGRDataSource
 class OGRNULLDriver : public OGRSFDriver
 {
   public:
-                ~OGRNULLDriver() {};
+    virtual ~OGRNULLDriver() {};
 
-    virtual const char    *GetName() { return "NULL"; }
-    virtual OGRDataSource *Open( const char *, int ) { return NULL; }
+    virtual const char    *GetName() override { return "NULL"; }
+    virtual OGRDataSource *Open( const char *, int ) override { return NULL; }
     virtual OGRDataSource *CreateDataSource( const char * pszName,
-                                             char **papszOptions );
+                                             char **papszOptions ) override;
 
-    virtual int            TestCapability( const char * );
+    virtual int            TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -119,15 +117,15 @@ class OGRNULLDriver : public OGRSFDriver
 
 OGRNULLLayer::OGRNULLLayer( const char *pszLayerName,
                             OGRSpatialReference *poSRSIn,
-                            OGRwkbGeometryType eType )
+                            OGRwkbGeometryType eType ) :
+    poFeatureDefn(new OGRFeatureDefn(pszLayerName)),
+    poSRS(poSRSIn)
 {
-    poFeatureDefn = new OGRFeatureDefn(pszLayerName);
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->SetGeomType(eType);
     poFeatureDefn->Reference();
 
-    poSRS = poSRSIn ? poSRSIn : NULL;
-    if (poSRS)
+    if( poSRS )
         poSRS->Reference();
 }
 
@@ -172,12 +170,11 @@ OGRErr OGRNULLLayer::CreateField( OGRFieldDefn *poField,
 /*                          OGRNULLDataSource()                         */
 /************************************************************************/
 
-OGRNULLDataSource::OGRNULLDataSource(const char* pszNameIn)
-{
-    pszName = CPLStrdup(pszNameIn);
-    nLayers = 0;
-    papoLayers = NULL;
-}
+OGRNULLDataSource::OGRNULLDataSource(const char* pszNameIn) :
+    nLayers(0),
+    papoLayers(NULL),
+    pszName(CPLStrdup(pszNameIn))
+{}
 
 /************************************************************************/
 /*                         ~OGRNULLDataSource()                         */
diff --git a/ogr/ogrsf_frmts/o/README.TXT b/ogr/ogrsf_frmts/o/README.TXT
index 71f041c..0c71f60 100644
--- a/ogr/ogrsf_frmts/o/README.TXT
+++ b/ogr/ogrsf_frmts/o/README.TXT
@@ -4,4 +4,4 @@ gdal/ogr/ogrsf_frmts/o
 This directory is where object files are put from the various format
 drivers so they can be easily linked into GDAL.  This file is here to
 ensure that the "o" directory isn't lost when people do a cvs checkout
-with pruning. 
+with pruning.
diff --git a/ogr/ogrsf_frmts/oci/GNUmakefile b/ogr/ogrsf_frmts/oci/GNUmakefile
index 987d2e8..4de72a6 100644
--- a/ogr/ogrsf_frmts/oci/GNUmakefile
+++ b/ogr/ogrsf_frmts/oci/GNUmakefile
@@ -16,7 +16,7 @@ default:	$(O_OBJ:.o=.$(OBJ_EXT))
 clean:
 	rm -f *.o $(O_OBJ) $(PLUGIN_SO)
 
-$(O_OBJ):	ogr_oci.h 
+$(O_OBJ):	ogr_oci.h
 
 fastload:	fastload.cpp
 	$(CXX) $(CPPFLAGS) $(CFLAGS) fastload.cpp -L../../.. -lgdal.1.1 \
diff --git a/ogr/ogrsf_frmts/oci/drv_oci.html b/ogr/ogrsf_frmts/oci/drv_oci.html
index 28f9a1c..a8b193a 100644
--- a/ogr/ogrsf_frmts/oci/drv_oci.html
+++ b/ogr/ogrsf_frmts/oci/drv_oci.html
@@ -101,7 +101,7 @@ in USER_SDO_GEOM_METADATA and rebuilding the spatial index.<p>
 <ul>
 
 <li> <b>OVERWRITE</b>: This may be "YES" to force an existing layer (=table) of the
-same desired name to be destroyed before creating the requested layer. 
+same desired name to be destroyed before creating the requested layer.
 The default value is “NO"<p>
 
 <li> <b>TRUNCATE</b>: This may be "YES" to force the existing table to
@@ -119,7 +119,8 @@ using NUMBER(width,precision) or VARCHAR2(width) types.  If "NO" then the types
 NUMBER, INTEGER and VARCHAR2 will be used instead.  The default is "YES".<p>
 
 <li> <b>DIM</b>: This may be set to 2 or 3 to force the dimension of the
-created layer.  If not set 3 is used by default.<p>
+created layer. Prior to GDAL 2.2, 3 is used by default. Starting with GDAL 2.2,
+the dimension of the layer geometry type is used by default.<p>
 
 <li> <b>SPATIAL_INDEX</b>: This may be set to FALSE to disable creation of a spatial
 index when a layer load is complete.  By default an index is created if
@@ -165,19 +166,19 @@ Multi-load mode is enabled by default, and may be forced off for existing
 layers or for new layers by setting to NO. The number of rows in each group is defined by
 MULTI_LOAD_COUNT. To load one row at a time, set MULTI_LOAD to NO.<p>
 
-<li> <b>MULTI_LOAD_COUNT</b>: Define the number of features on each ARRAY INSERT command, 
-instead of the default 100 item defined by MULTI_LOAD. Since each array insert will commit 
-a transaction, this options shouldn't be combined with ogr2ogr "-gt N". 
-Use "-gt unlimited" preferably when using MULTI_LOAD_COUNT. The default is 100. 
+<li> <b>MULTI_LOAD_COUNT</b>: Define the number of features on each ARRAY INSERT command,
+instead of the default 100 item defined by MULTI_LOAD. Since each array insert will commit
+a transaction, this options shouldn't be combined with ogr2ogr "-gt N".
+Use "-gt unlimited" preferably when using MULTI_LOAD_COUNT. The default is 100.
 If neither MULTI_LOAD nor MULTI_LOAD_COUNT are specified, then the loading happens
 in groups of 100 rows.<p>
-    
+
 <li> <b>FIRST_ID</b>: Define the first numeric value of the id column on the first
 rows. It's also work as a open option when used to append or update an existing dataset.<p>
-    
-<li> <b>NO_LOGGING</b>: Define that the table and the geomtry will be create 
+
+<li> <b>NO_LOGGING</b>: Define that the table and the geometry will be create
 with nologging attributes.<p>
-    
+
 <li> <b>LOADER_FILE</b>: If this option is set, all feature information will
 be written to a file suitable for use with SQL*Loader instead of inserted
 directly in the database.  The layer itself is still created in the database
@@ -196,7 +197,7 @@ it can be supplied with the GEOMETRY_NAME layer creation option.<p>
 <ul>
 
 <li> <b>FIRST_ID</b>: See Layer Create Options comments on FIRST_ID.<p>
-    
+
 <li> <b>MULTI_LOAD_COUNT</b>: See Layer Create Options comments on MULTI_LOAD_COUNT.<p>
 
 <li> <b>WORKSPACE</b>: Define what user workspace to use.<p>
diff --git a/ogr/ogrsf_frmts/oci/fastload.cpp b/ogr/ogrsf_frmts/oci/fastload.cpp
index 7a7bad4..3dbe271 100644
--- a/ogr/ogrsf_frmts/oci/fastload.cpp
+++ b/ogr/ogrsf_frmts/oci/fastload.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: fastload.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Test mainline for fast loading.
@@ -30,6 +29,8 @@
 #include <stdio.h>
 #include "ogr_oci.h"
 
+CPL_CVSID("$Id: fastload.cpp 36456 2016-11-22 23:34:00Z rouault $");
+
 int main()
 
 {
@@ -72,7 +73,7 @@ int main()
     SDO_GEOMETRY_ind   aoGeometryIndicators[100];
     SDO_GEOMETRY_TYPE *apoGeomMap[100];
     SDO_GEOMETRY_ind  *apoGeomIndMap[100];
-    double adfX[100], adfY[100];
+    //double adfX[100], adfY[100];
 
     memset( aphElemInfos, 0, sizeof(OCIArray*) * 100 );
     memset( aphOrdinates, 0, sizeof(OCIArray*) * 100 );
@@ -122,12 +123,13 @@ int main()
 
     for( iRow = 0; iRow < 100; iRow++ )
     {
+        // cppcheck-suppress unreadVariable
         anField1[iRow] = iRow;
         sprintf( szField2 + iRow*4, "%3d", iRow );
         anGType[iRow] = 3001;
         anSRID[iRow] = -1;
-        adfX[iRow] = 100.0 + iRow;
-        adfY[iRow] = 100.0 - iRow;
+        //adfX[iRow] = 100.0 + iRow;
+        //adfY[iRow] = 100.0 - iRow;
 
         //---------------------------------------------------------------
         int anElemInfo[3], nElemInfoCount;
diff --git a/ogr/ogrsf_frmts/oci/oci_utils.cpp b/ogr/ogrsf_frmts/oci/oci_utils.cpp
index 8ea4a27..fdd1d78 100644
--- a/ogr/ogrsf_frmts/oci/oci_utils.cpp
+++ b/ogr/ogrsf_frmts/oci/oci_utils.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: oci_utils.cpp 10645 2007-01-18 02:22:39Z warmerdam $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Various low level utility functions for OCI connections.
@@ -29,5 +28,4 @@
 
 #include "ogr_oci.h"
 
-CPL_CVSID("$Id: oci_utils.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
-
+CPL_CVSID("$Id: oci_utils.cpp 34819 2016-07-28 22:32:18Z goatbar $");
diff --git a/ogr/ogrsf_frmts/oci/ocitest.cpp b/ogr/ogrsf_frmts/oci/ocitest.cpp
index fbbcb3b..179d98e 100644
--- a/ogr/ogrsf_frmts/oci/ocitest.cpp
+++ b/ogr/ogrsf_frmts/oci/ocitest.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ocitest.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Test mainline for Oracle Spatial Driver low level functions.
@@ -30,7 +29,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ocitest.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ocitest.cpp 36447 2016-11-22 22:25:08Z rouault $");
 
 /************************************************************************/
 /*                                main()                                */
@@ -41,7 +40,6 @@ int main( int nArgc, char ** papszArgv )
 {
     OGROCISession *poSession = NULL;
     const char *pszStatement = "SELECT * FROM NEPSITE";
-    int  nColCount;
     char **papszResult;
 
     if( nArgc > 1 )
diff --git a/ogr/ogrsf_frmts/oci/ogr_oci.h b/ogr/ogrsf_frmts/oci/ogr_oci.h
index 6eadf36..2438475 100644
--- a/ogr/ogrsf_frmts/oci/ogr_oci.h
+++ b/ogr/ogrsf_frmts/oci/ogr_oci.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_oci.h 34888 2016-08-03 19:59:19Z ilucena $
+ * $Id: ogr_oci.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Oracle Spatial OGR Driver Declarations.
@@ -89,7 +89,6 @@ typedef struct
 #define ORA_GTYPE_SOLID           8
 #define ORA_GTYPE_MULTISOLID      9
 
-
 /************************************************************************/
 /*                            OGROCISession                             */
 /************************************************************************/
@@ -122,12 +121,11 @@ class CPL_DLL OGROCISession {
     CPLErr   GetParmInfo( OCIParam *hParmDesc, OGRFieldDefn *poOGRDefn,
                           ub2 *pnOCIType, ub4 *pnOCILen );
 
-    void     CleanName( char * );
+    static void     CleanName( char * );
 
     OCIType *PinTDO( const char * );
 
   private:
-
 };
 
 OGROCISession CPL_DLL*
@@ -140,7 +138,7 @@ OGRGetOCISession( const char *pszUserid,
 /************************************************************************/
 class CPL_DLL OGROCIStatement {
   public:
-                 OGROCIStatement( OGROCISession * );
+    explicit     OGROCIStatement( OGROCISession * );
     virtual     ~OGROCIStatement();
 
     OCIStmt     *GetStatement() { return hStatement; }
@@ -255,18 +253,18 @@ class OGROCILayer : public OGRLayer
   public:
                         OGROCILayer();
     virtual             ~OGROCILayer();
-    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch ) { return OGRLayer::FindFieldIndex( pszFieldName, bExactMatch ); }
+    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch ) override { return OGRLayer::FindFieldIndex( pszFieldName, bExactMatch ); }
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
     virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 
     int                 LookupTableSRID();
 };
@@ -313,10 +311,10 @@ protected:
     virtual            ~OGROCIWritableLayer();
 public:
 
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
+    virtual OGRSpatialReference *GetSpatialRef() override { return poSRS; }
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch );
+                                     int bApproxOK = TRUE ) override;
+    virtual int         FindFieldIndex( const char *pszFieldName, int bExactMatch ) override;
 
     // following methods are not base class overrides
     void                SetOptions( char ** );
@@ -356,6 +354,7 @@ class OGROCILoaderLayer : public OGROCIWritableLayer
 
     OGRErr              WriteFeatureStreamMode( OGRFeature * );
     OGRErr              WriteFeatureVariableMode( OGRFeature * );
+    // cppcheck-suppress functionStatic
     OGRErr              WriteFeatureBinaryMode( OGRFeature * );
 
   public:
@@ -364,26 +363,25 @@ class OGROCILoaderLayer : public OGROCIWritableLayer
                                            const char *pszGeomCol,
                                            int nSRID,
                                            const char *pszLoaderFile );
-                        ~OGROCILoaderLayer();
+                        virtual ~OGROCILoaderLayer();
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry * ) {}
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void        SetSpatialFilter( OGRGeometry * ) override {}
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual OGRErr      SetAttributeFilter( const char * )
+    virtual OGRErr      SetAttributeFilter( const char * ) override
                                 { return OGRERR_UNSUPPORTED_OPERATION; }
 
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
 
-    virtual OGRSpatialReference *GetSpatialRef() { return poSRS; }
-
-    virtual int         TestCapability( const char * );
+    virtual OGRSpatialReference *GetSpatialRef() override { return poSRS; }
 
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -402,9 +400,9 @@ class OGROCITableLayer : public OGROCIWritableLayer
 
     OGRFeatureDefn     *ReadTableDefinition(const char *);
 
-    void                BuildWhere(void);
-    char               *BuildFields(void);
-    void                BuildFullQueryStatement(void);
+    void                BuildWhere();
+    char               *BuildFields();
+    void                BuildFullQueryStatement();
 
     char               *pszQuery;
     char               *pszWHERE;
@@ -450,31 +448,31 @@ class OGROCITableLayer : public OGROCIWritableLayer
                         OGROCITableLayer( OGROCIDataSource *,
                                           const char * pszName, OGRwkbGeometryType eGType,
                                           int nSRID, int bUpdate, int bNew );
-                        ~OGROCITableLayer();
+                        virtual ~OGROCITableLayer();
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 
     // following methods are not base class overrides
     int                 IsValid() { return bValidTable; }
@@ -522,7 +520,7 @@ class OGROCIDataSource : public OGRDataSource
 
   public:
                         OGROCIDataSource();
-                        ~OGROCIDataSource();
+                        virtual ~OGROCIDataSource();
 
     OGROCISession      *GetSession() { return poSession; }
 
@@ -532,18 +530,18 @@ class OGROCIDataSource : public OGRDataSource
                                    int nSRID, int bUpdate, int bTestOpen,
                                    char** papszOpenOptions );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
-    OGRLayer            *GetLayerByName(const char * pszName);
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
+    OGRLayer            *GetLayerByName(const char * pszName) override;
 
-    virtual OGRErr      DeleteLayer(int);
+    virtual OGRErr      DeleteLayer(int) override;
     virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+                                      char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     void                DeleteLayer( const char * );
 
@@ -552,8 +550,8 @@ class OGROCIDataSource : public OGRDataSource
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     int                 FetchSRSId( OGRSpatialReference * poSRS );
     OGRSpatialReference *FetchSRS( int nSRID );
@@ -570,5 +568,4 @@ OGROCIStrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
                                      int bForceWholeCircle,
                                      OGRLineString *poLine );
 
-
 #endif /* ndef OGR_OCI_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
index a8b14c2..db46b32 100644
--- a/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocidatasource.cpp
@@ -30,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrocidatasource.cpp 35116 2016-08-15 14:54:25Z ilucena $");
+CPL_CVSID("$Id: ogrocidatasource.cpp 36385 2016-11-21 12:24:06Z rouault $");
 
 static const int anEPSGOracleMapping[] =
 {
@@ -58,6 +58,8 @@ OGROCIDataSource::OGROCIDataSource()
     pszDBName = NULL;
     papoLayers = NULL;
     nLayers = 0;
+    bDSUpdate = FALSE;
+    bNoLogging = FALSE;
     poSession = NULL;
     papoSRS = NULL;
     panSRID = NULL;
@@ -500,7 +502,7 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
     poSession->CleanName( pszSafeLayerName );
     CPLDebug( "OCI", "In Create Layer ..." );
 
-    bNoLogging = CSLFetchBoolean( papszOptions, "NO_LOGGING", false );
+    bNoLogging = CPLFetchBool( papszOptions, "NO_LOGGING", false );
 
 /* -------------------------------------------------------------------- */
 /*      Do we already have this layer?  If so, should we blow it        */
@@ -508,7 +510,7 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     int iLayer;
 
-    if( CSLFetchBoolean( papszOptions, "TRUNCATE", false ) )
+    if( CPLFetchBool( papszOptions, "TRUNCATE", false ) )
     {
         CPLDebug( "OCI", "Calling TruncateLayer for %s", pszLayerName );
         TruncateLayer( pszSafeLayerName );
@@ -545,8 +547,9 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     char szSRSId[100];
 
-    if( CSLFetchNameValue( papszOptions, "SRID" ) != NULL )
-        strcpy( szSRSId, CSLFetchNameValue( papszOptions, "SRID" ) );
+    const char* pszSRID = CSLFetchNameValue( papszOptions, "SRID" );
+    if( pszSRID != NULL )
+        snprintf( szSRSId, sizeof(szSRSId), "%s", pszSRID );
     else if( poSRS != NULL )
         snprintf( szSRSId, sizeof(szSRSId), "%d", FetchSRSId( poSRS ) );
     else
@@ -560,7 +563,7 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
     if( pszGeometryName == NULL )
         pszGeometryName = "ORA_GEOMETRY";
     const bool bGeomNullable =
-        CPLFetchBool(const_cast<const char**>(papszOptions), "GEOMETRY_NULLABLE", true);
+        CPLFetchBool(papszOptions, "GEOMETRY_NULLABLE", true);
 
 /* -------------------------------------------------------------------- */
 /*      Create a basic table with the FID.  Also include the            */
@@ -599,7 +602,7 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
         {
             char     szCommand2[1024];
 
-            strncpy( szCommand2, szCommand, sizeof(szCommand) );
+            snprintf( szCommand2, sizeof(szCommand2), "%s", szCommand );
 
             snprintf( szCommand, sizeof(szCommand), "%s NOLOGGING "
               "VARRAY %s.SDO_ELEM_INFO STORE AS SECUREFILE LOB (NOCACHE NOLOGGING) "
@@ -634,11 +637,14 @@ OGROCIDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Set various options on the layer.                               */
 /* -------------------------------------------------------------------- */
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions, "LAUNDER", false) );
-    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions, "PRECISION", true));
+    poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", false) );
+    poLayer->SetPrecisionFlag( CPLFetchBool(papszOptions, "PRECISION", true));
 
-    if( CSLFetchNameValue(papszOptions,"DIM") != NULL )
-        poLayer->SetDimension( atoi(CSLFetchNameValue(papszOptions,"DIM")) );
+    const char* pszDIM = CSLFetchNameValue(papszOptions,"DIM");
+    if( pszDIM != NULL )
+        poLayer->SetDimension( atoi(pszDIM) );
+    else if( eType != wkbNone )
+        poLayer->SetDimension( (wkbFlatten(eType) == eType) ? 2 : 3 );
 
     poLayer->SetOptions( papszOptions );
     if( eType != wkbNone && !bGeomNullable )
@@ -668,6 +674,8 @@ int OGROCIDataSource::TestCapability( const char * pszCap )
         return TRUE;
     else if( EQUAL(pszCap,ODsCDeleteLayer) && bDSUpdate )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return bDSUpdate;
     else
         return FALSE;
 }
@@ -685,8 +693,6 @@ OGRLayer *OGROCIDataSource::GetLayer( int iLayer )
         return papoLayers[iLayer];
 }
 
-
-
 /************************************************************************/
 /*                             ExecuteSQL()                             */
 /************************************************************************/
@@ -1018,7 +1024,6 @@ int OGROCIDataSource::FetchSRSId( OGRSpatialReference * poSRS )
         return nSRSId;
 }
 
-
 /************************************************************************/
 /*                           GetLayerByName()                           */
 /************************************************************************/
@@ -1030,7 +1035,7 @@ OGRLayer *OGROCIDataSource::GetLayerByName( const char *pszNameIn )
     int  i, count;
 
     if ( !pszNameIn )
-	return NULL;
+        return NULL;
 
     count = GetLayerCount();
 
diff --git a/ogr/ogrsf_frmts/oci/ogrocidriver.cpp b/ogr/ogrsf_frmts/oci/ogrocidriver.cpp
index 71f192a..40a6992 100644
--- a/ogr/ogrsf_frmts/oci/ogrocidriver.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocidriver.cpp
@@ -28,8 +28,7 @@
 
 #include "ogr_oci.h"
 
-CPL_CVSID("$Id: ogrocidriver.cpp 34888 2016-08-03 19:59:19Z ilucena $");
-
+CPL_CVSID("$Id: ogrocidriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                        OGROCIDriverIdentify()                        */
@@ -80,7 +79,6 @@ static GDALDataset *OGROCIDriverCreate( const char * pszName,
 
     poDS = new OGROCIDataSource();
 
-
     if( !poDS->Open( pszName, NULL, TRUE, TRUE ) )
     {
         delete poDS;
diff --git a/ogr/ogrsf_frmts/oci/ogrocilayer.cpp b/ogr/ogrsf_frmts/oci/ogrocilayer.cpp
index bd70197..2247d4e 100644
--- a/ogr/ogrsf_frmts/oci/ogrocilayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocilayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrocilayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCILayer class.  This is layer semantics
@@ -32,7 +31,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrocilayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrocilayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                           OGROCILayer()                               */
@@ -41,10 +40,12 @@ CPL_CVSID("$Id: ogrocilayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 OGROCILayer::OGROCILayer()
 
 {
+    poFeatureDefn = NULL;
     poDS = NULL;
     poStatement = NULL;
 
     pszQueryStatement = NULL;
+    nResultOffset = 0;
     pszGeomName = NULL;
     iGeomColumn = -1;
     pszFIDName = NULL;
@@ -186,6 +187,8 @@ OGRFeature *OGROCILayer::GetNextRawFeature()
     {
         if( papszResult[iField] != NULL )
             poFeature->SetField( iField, papszResult[iField] );
+        else
+            poFeature->SetFieldNull( iField );
     }
 
 /* -------------------------------------------------------------------- */
@@ -514,7 +517,6 @@ OGROCILayer::LoadElementInfo( int iElement, int nElemCount, int nTotalOrdCount,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                      TranslateGeometryElement()                      */
 /************************************************************************/
@@ -798,7 +800,6 @@ OGROCILayer::TranslateGeometryElement( int *piElement,
 
                 delete poElemLS;
             }
-
         }
 
         *piElement -= 3;
@@ -878,7 +879,6 @@ int OGROCILayer::TestCapability( const char * pszCap )
         return FALSE;
 }
 
-
 /************************************************************************/
 /*                          LookupTableSRID()                           */
 /*                                                                      */
diff --git a/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp b/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp
index 76c1fdd..35d9257 100644
--- a/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrociloaderlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrociloaderlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCILoaderLayer class.  This implements
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrociloaderlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrociloaderlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGROCILoaderLayer()                          */
@@ -60,7 +59,6 @@ OGROCILoaderLayer::OGROCILoaderLayer( OGROCIDataSource *poDSIn,
     pszGeomName = CPLStrdup( pszGeomColIn );
     pszFIDName = (char*)CPLGetConfigOption( "OCI_FID", "OGR_FID" );
 
-
     nSRID = nSRIDIn;
     poSRS = poDSIn->FetchSRS( nSRID );
 
@@ -81,7 +79,6 @@ OGROCILoaderLayer::OGROCILoaderLayer( OGROCIDataSource *poDSIn,
                   pszLoaderFilename );
         return;
     }
-
 }
 
 /************************************************************************/
@@ -191,7 +188,7 @@ void OGROCILoaderLayer::WriteLoaderHeader()
             VSIFPrintf( fpLoader, "    \"%s\" INTEGER EXTERNAL",
                         poFldDefn->GetNameRef() );
         }
-        else if( poFldDefn->GetType() == OFTInteger )
+        else if( poFldDefn->GetType() == OFTInteger64 )
         {
             VSIFPrintf( fpLoader, "    \"%s\" LONGINTEGER EXTERNAL",
                         poFldDefn->GetNameRef() );
@@ -201,12 +198,7 @@ void OGROCILoaderLayer::WriteLoaderHeader()
             VSIFPrintf( fpLoader, "    \"%s\" FLOAT EXTERNAL",
                         poFldDefn->GetNameRef() );
         }
-        else if( poFldDefn->GetType() == OFTString )
-        {
-            VSIFPrintf( fpLoader, "    \"%s\" VARCHARC(4)",
-                        poFldDefn->GetNameRef() );
-        }
-        else
+        else /* if( poFldDefn->GetType() == OFTString ) or default case */
         {
             VSIFPrintf( fpLoader, "    \"%s\" VARCHARC(4)",
                         poFldDefn->GetNameRef() );
@@ -327,7 +319,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureStreamMode( OGRFeature *poFeature )
     {
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(i);
 
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
         {
             if( poFldDefn->GetType() != OFTInteger
                 && poFldDefn->GetType() != OFTInteger64
@@ -451,7 +443,7 @@ OGRErr OGROCILoaderLayer::WriteFeatureVariableMode( OGRFeature *poFeature )
     {
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(i);
 
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
         {
             if( poFldDefn->GetType() != OFTInteger
                 && poFldDefn->GetType() != OFTInteger64
diff --git a/ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp b/ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp
index a98ec8c..4100368 100644
--- a/ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrociselectlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrociselectlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCISelectLayer class.  This class
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrociselectlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrociselectlayer.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                          OGROCISelectLayer()                         */
diff --git a/ogr/ogrsf_frmts/oci/ogrocisession.cpp b/ogr/ogrsf_frmts/oci/ogrocisession.cpp
index ee3a1b2..2a0a587 100644
--- a/ogr/ogrsf_frmts/oci/ogrocisession.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocisession.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrocisession.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of OGROCISession, which encapsulates much of the
@@ -31,7 +30,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrocisession.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrocisession.cpp 36802 2016-12-11 23:03:54Z rouault $");
 
 /************************************************************************/
 /*                          OGRGetOCISession()                          */
@@ -275,14 +274,14 @@ int OGROCISession::EstablishSession( const char *pszUseridIn,
 /* -------------------------------------------------------------------- */
 /*      Record information about the session.                           */
 /* -------------------------------------------------------------------- */
-    this->pszUserid = CPLStrdup(pszUseridIn);
-    this->pszPassword = CPLStrdup(pszPasswordIn);
-    this->pszDatabase = CPLStrdup(pszDatabaseIn);
+    pszUserid = CPLStrdup(pszUseridIn);
+    pszPassword = CPLStrdup(pszPasswordIn);
+    pszDatabase = CPLStrdup(pszDatabaseIn);
 
 /* -------------------------------------------------------------------- */
 /*      Setting up the OGR compatible time formatting rules.            */
 /* -------------------------------------------------------------------- */
-    OGROCIStatement     oSetNLSTimeFormat( this );
+    OGROCIStatement oSetNLSTimeFormat( this );
     if( oSetNLSTimeFormat.Execute( "ALTER SESSION SET NLS_DATE_FORMAT='YYYY/MM/DD' \
         NLS_TIME_FORMAT='HH24:MI:SS' NLS_TIME_TZ_FORMAT='HH24:MI:SS TZHTZM' \
         NLS_TIMESTAMP_FORMAT='YYYY/MM/DD HH24:MI:SS' \
@@ -368,24 +367,24 @@ OGROCISession::GetParmInfo( OCIParam *hParmDesc, OGRFieldDefn *poOGRDefn,
 /* -------------------------------------------------------------------- */
     if( Failed(
         OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM,
-                    (dvoid **)&nOCIType, 0, OCI_ATTR_DATA_TYPE, hError ),
+                    &nOCIType, 0, OCI_ATTR_DATA_TYPE, hError ),
         "OCIAttrGet(Type)" ) )
         return CE_Failure;
 
     if( Failed(
         OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM,
-                    (dvoid **)&nOCILen, 0, OCI_ATTR_DATA_SIZE, hError ),
+                    &nOCILen, 0, OCI_ATTR_DATA_SIZE, hError ),
         "OCIAttrGet(Size)" ) )
         return CE_Failure;
 
     if( Failed(
-        OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, (dvoid **)&pszColName,
+        OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, &pszColName,
                     &nColLen, OCI_ATTR_NAME, hError ),
         "OCIAttrGet(Name)") )
         return CE_Failure;
 
     if( Failed(
-        OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, (dvoid **)&bOCINull,
+        OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, &bOCINull,
                     0, OCI_ATTR_IS_NULL, hError ),
         "OCIAttrGet(Null)") )
         return CE_Failure;
@@ -427,12 +426,12 @@ OGROCISession::GetParmInfo( OCIParam *hParmDesc, OGRFieldDefn *poOGRDefn,
             sb1  nScale;
 
             if( Failed(
-                OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, (dvoid **)&byPrecision,
+                OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, &byPrecision,
                             0, OCI_ATTR_PRECISION, hError ),
                 "OCIAttrGet(Precision)" ) )
                 return CE_Failure;
             if( Failed(
-                OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, (dvoid **)&nScale,
+                OCIAttrGet( hParmDesc, OCI_DTYPE_PARAM, &nScale,
                             0, OCI_ATTR_SCALE, hError ),
                 "OCIAttrGet(Scale)") )
                 return CE_Failure;
diff --git a/ogr/ogrsf_frmts/oci/ogrocistatement.cpp b/ogr/ogrsf_frmts/oci/ogrocistatement.cpp
index 4e922cf..1eb1552 100644
--- a/ogr/ogrsf_frmts/oci/ogrocistatement.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocistatement.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrocistatement.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of OGROCIStatement, which encapsulates the
@@ -31,7 +30,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrocistatement.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrocistatement.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                          OGROCIStatement()                           */
diff --git a/ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp b/ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp
index ab911a4..612f340 100644
--- a/ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocistringbuf.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrocistringbuf.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Simple string buffer used to accumulate text of commands
@@ -31,7 +30,7 @@
 #include "ogr_oci.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrocistringbuf.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrocistringbuf.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                          OGROCIStringBuf()                           */
diff --git a/ogr/ogrsf_frmts/oci/ogrocistroke.cpp b/ogr/ogrsf_frmts/oci/ogrocistroke.cpp
index da7aa4d..9570bda 100644
--- a/ogr/ogrsf_frmts/oci/ogrocistroke.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocistroke.cpp
@@ -30,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ntfstroke.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: ogrocistroke.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                   OGROCIArcCenterFromEdgePoints()                    */
@@ -175,7 +175,6 @@ OGROCIStrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                OGROCIStrokeArcToOGRGeometry_Points()                 */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
index 4c853b3..703b79b 100644
--- a/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrocitablelayer.cpp
@@ -32,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrocitablelayer.cpp 34888 2016-08-03 19:59:19Z ilucena $");
+CPL_CVSID("$Id: ogrocitablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 static int nDiscarded = 0;
 static int nHits = 0;
@@ -133,7 +133,6 @@ OGROCITableLayer::~OGROCITableLayer()
     CPLFree( papsWriteGeomMap );
     CPLFree( pasWriteGeoms );
 
-
     CPLFree( pszQuery );
     CPLFree( pszWHERE );
 
@@ -916,7 +915,7 @@ OGRErr OGROCITableLayer::ICreateFeature( OGRFeature *poFeature )
 /*      Get the multi load count value from open options                */
 /* -------------------------------------------------------------------- */
 
-    this->bMultiLoad = CSLFetchBoolean( papszOptions, "MULTI_LOAD", true );
+    this->bMultiLoad = CPLFetchBool( papszOptions, "MULTI_LOAD", true );
 
     this->nMultiLoadCount = 100;
 
@@ -974,10 +973,9 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
         bNeedComma = TRUE;
     }
 
-
     for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
             continue;
 
         if( !bNeedComma )
@@ -1081,7 +1079,7 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
             continue;
 
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(i);
@@ -1312,7 +1310,6 @@ OGRErr OGROCITableLayer::UnboundCreateFeature( OGRFeature *poFeature )
         return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           GetExtent()                                */
 /************************************************************************/
@@ -1595,7 +1592,6 @@ void OGROCITableLayer::UpdateLayerExtents()
 
         sDimUpdate.Appendf(static_cast<int>(strlen(poFeatureDefn->GetName()) + 100),
                            ") WHERE TABLE_NAME = '%s'", poFeatureDefn->GetName());
-
     }
     else
     {
@@ -1852,7 +1848,7 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
     /* of BoundCreateFeature() doesn't work. */
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
-        if( !poFeature->IsFieldSet( i ) &&
+        if( !poFeature->IsFieldSetAndNotNull( i ) &&
             poFeature->GetFieldDefnRef(i)->GetDefault() != NULL )
         {
             FlushPendingFeatures();
@@ -2018,7 +2014,7 @@ OGRErr OGROCITableLayer::BoundCreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
-        if( !poFeature->IsFieldSet( i ) )
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
         {
             papaeWriteFieldInd[i][iCache] = OCI_IND_NULL;
             continue;
@@ -2143,8 +2139,8 @@ void OGROCITableLayer::CreateSpatialIndex()
 /*      If the user has disabled INDEX support then don't create the    */
 /*      index.                                                          */
 /* -------------------------------------------------------------------- */
-        if( !CSLFetchBoolean( papszOptions, "SPATIAL_INDEX", true ) ||
-            !CSLFetchBoolean( papszOptions, "INDEX", true ) )
+        if( !CPLFetchBool( papszOptions, "SPATIAL_INDEX", true ) ||
+            !CPLFetchBool( papszOptions, "INDEX", true ) )
             return;
 
 /* -------------------------------------------------------------------- */
@@ -2178,7 +2174,6 @@ void OGROCITableLayer::CreateSpatialIndex()
         OGROCIStringBuf  sIndexCmd;
         OGROCIStatement oExecStatement( poDS->GetSession() );
 
-
         sIndexCmd.Appendf( 10000, "CREATE INDEX \"%s\" ON %s(\"%s\") "
                            "INDEXTYPE IS MDSYS.SPATIAL_INDEX ",
                            szIndexName,
@@ -2190,15 +2185,15 @@ void OGROCITableLayer::CreateSpatialIndex()
             GetGeomType() != wkbUnknown;
 
         CPLString osParams(CSLFetchNameValueDef(papszOptions,"INDEX_PARAMETERS", ""));
-        if( bAddLayerGType || osParams.size() != 0 )
+        if( bAddLayerGType || !osParams.empty() )
         {
             sIndexCmd.Append( " PARAMETERS( '" );
-            if( osParams.size() != 0 )
+            if( !osParams.empty() )
                 sIndexCmd.Append( osParams.c_str() );
             if( bAddLayerGType &&
                 osParams.ifind("LAYER_GTYPE") == std::string::npos )
             {
-                if( osParams.size() != 0 )
+                if( !osParams.empty() )
                     sIndexCmd.Append( ", " );
                 sIndexCmd.Append( "LAYER_GTYPE=" );
                 if( wkbFlatten(GetGeomType()) == wkbPoint )
diff --git a/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp b/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp
index 219cf54..467a9b0 100644
--- a/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp
+++ b/ogr/ogrsf_frmts/oci/ogrociwritablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrociwritablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  Oracle Spatial Driver
  * Purpose:  Implementation of the OGROCIWritableLayer class.  This provides
@@ -33,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrociwritablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrociwritablelayer.cpp 36347 2016-11-20 20:43:39Z rouault $");
 
 /************************************************************************/
 /*                        OGROCIWritableLayer()                         */
@@ -54,6 +53,7 @@ OGROCIWritableLayer::OGROCIWritableLayer()
     panElemInfo = NULL;
 
     bLaunderColumnNames = TRUE;
+    bPreservePrecision = FALSE;
     bTruncationReported = FALSE;
     poSRS = NULL;
 
diff --git a/ogr/ogrsf_frmts/odbc/ogr_odbc.h b/ogr/ogrsf_frmts/odbc/ogr_odbc.h
index d0cd383..b04e1d5 100644
--- a/ogr/ogrsf_frmts/odbc/ogr_odbc.h
+++ b/ogr/ogrsf_frmts/odbc/ogr_odbc.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_odbc.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_odbc.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/ODBC driver.
@@ -70,17 +70,17 @@ class OGRODBCLayer : public OGRLayer
                         OGRODBCLayer();
     virtual             ~OGRODBCLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
     virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -89,31 +89,29 @@ class OGRODBCLayer : public OGRLayer
 
 class OGRODBCTableLayer : public OGRODBCLayer
 {
-    int                 bUpdateAccess;
-
     char                *pszQuery;
 
     int                 bHaveSpatialExtents;
 
-    void		ClearStatement();
+    void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *  GetStatement() override;
 
     char               *pszTableName;
     char               *pszSchemaName;
 
   public:
-                        OGRODBCTableLayer( OGRODBCDataSource * );
-                        ~OGRODBCTableLayer();
+    explicit            OGRODBCTableLayer( OGRODBCDataSource * );
+                        virtual ~OGRODBCTableLayer();
 
     CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol );
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 #ifdef notdef
     virtual OGRErr      ISetFeature( OGRFeature *poFeature );
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
@@ -121,11 +119,11 @@ class OGRODBCTableLayer : public OGRODBCLayer
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
                                      int bApproxOK = TRUE );
 #endif
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
 #ifdef notdef
     // follow methods are not base class overrides
@@ -144,26 +142,26 @@ class OGRODBCSelectLayer : public OGRODBCLayer
 {
     char                *pszBaseStatement;
 
-    void		ClearStatement();
+    void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *  GetStatement() override;
 
   public:
                         OGRODBCSelectLayer( OGRODBCDataSource *,
                                            CPLODBCStatement * );
-                        ~OGRODBCSelectLayer();
+                        virtual ~OGRODBCSelectLayer();
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -190,27 +188,26 @@ class OGRODBCDataSource : public OGRDataSource
 
   public:
                         OGRODBCDataSource();
-                        ~OGRODBCDataSource();
+                        virtual ~OGRODBCDataSource();
 
     int                 Open( const char *, int bUpdate, int bTestOpen );
     int                 OpenTable( const char *pszTableName,
                                    const char *pszGeomCol,
                                    int bUpdate );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     // Internal use
     CPLODBCSession     *GetSession() { return &oSession; }
-
 };
 
 /************************************************************************/
@@ -220,16 +217,15 @@ class OGRODBCDataSource : public OGRDataSource
 class OGRODBCDriver : public OGRSFDriver
 {
   public:
-                ~OGRODBCDriver();
+                virtual ~OGRODBCDriver();
 
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
-                                             char ** = NULL );
+                                             char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
-
 #endif /* ndef OGR_ODBC_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp b/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp
index 338ad75..3415ab1 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbcdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrodbcdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCDataSource class.
@@ -32,22 +31,20 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrodbcdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrodbcdatasource.cpp 36455 2016-11-22 23:11:35Z rouault $");
 /************************************************************************/
 /*                         OGRODBCDataSource()                          */
 /************************************************************************/
 
 OGRODBCDataSource::OGRODBCDataSource() :
-    bDSUpdate(FALSE)
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-
-    nKnownSRID = 0;
-    panSRID = NULL;
-    papoSRS = NULL;
-}
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    bDSUpdate(FALSE),
+    nKnownSRID(0),
+    panSRID(NULL),
+    papoSRS(NULL)
+{}
 
 /************************************************************************/
 /*                         ~OGRODBCDataSource()                         */
@@ -56,16 +53,14 @@ OGRODBCDataSource::OGRODBCDataSource() :
 OGRODBCDataSource::~OGRODBCDataSource()
 
 {
-    int         i;
-
     CPLFree( pszName );
 
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
 
     CPLFree( papoLayers );
 
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( papoSRS[i] != NULL )
             papoSRS[i]->Release();
@@ -110,8 +105,7 @@ static int CheckDSNStringTemplate(const char* pszStr)
 
 int OGRODBCDataSource::OpenMDB( const char * pszNewName, int bUpdate )
 {
-    const char* pszOptionName = "";
-    pszOptionName = "PGEO_DRIVER_TEMPLATE";
+    const char* pszOptionName = "PGEO_DRIVER_TEMPLATE";
     const char* pszDSNStringTemplate = CPLGetConfigOption( pszOptionName, NULL );
     if( pszDSNStringTemplate == NULL )
     {
@@ -226,17 +220,21 @@ int OGRODBCDataSource::OpenMDB( const char * pszNewName, int bUpdate )
         while( oTableList.Fetch() )
         {
             const char *pszSchema = oTableList.GetColData(1);
-            CPLString osLayerName;
-
-            if( pszSchema != NULL && strlen(pszSchema) > 0 )
+            const char* pszTableName = oTableList.GetColData(2);
+            if( pszTableName != NULL )
             {
-                osLayerName = pszSchema;
-                osLayerName += ".";
-            }
+                CPLString osLayerName;
 
-            osLayerName += oTableList.GetColData(2);
+                if( pszSchema != NULL && strlen(pszSchema) > 0 )
+                {
+                    osLayerName = pszSchema;
+                    osLayerName += ".";
+                }
 
-            OpenTable( osLayerName, NULL, bUpdate );
+                osLayerName += pszTableName;
+
+                OpenTable( osLayerName, NULL, bUpdate );
+            }
         }
 
         return TRUE;
@@ -266,8 +264,9 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
     char **papszTables = NULL;
     char **papszGeomCol = NULL;
     char *pszSRSTableName = NULL;
-    char *pszSRIDCol = NULL, *pszSRTextCol = NULL;
-    char *pszDelimiter;
+    char *pszSRIDCol = NULL;
+    char *pszSRTextCol = NULL;
+    char *pszDelimiter = NULL;
 
     if ( (pszDelimiter = strrchr( pszWrkName, ':' )) != NULL )
     {
@@ -349,19 +348,18 @@ int OGRODBCDataSource::Open( const char * pszNewName, int bUpdate,
     }
     else
     {
-        char *pszTarget;
 
         pszDSN = CPLStrdup(strstr(pszWrkName, "@") + 1);
         if( *pszWrkName == '/' )
         {
             pszPassword = CPLStrdup(pszWrkName + 1);
-            pszTarget = strstr(pszPassword,"@");
+            char *pszTarget = strstr(pszPassword,"@");
             *pszTarget = '\0';
         }
         else
         {
             pszUserid = CPLStrdup(pszWrkName);
-            pszTarget = strstr(pszUserid,"@");
+            char *pszTarget = strstr(pszUserid,"@");
             *pszTarget = '\0';
 
             pszTarget = strstr(pszUserid,"/");
@@ -560,9 +558,7 @@ int OGRODBCDataSource::OpenTable( const char *pszNewName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRODBCTableLayer  *poLayer;
-
-    poLayer = new OGRODBCTableLayer( this );
+    OGRODBCTableLayer *poLayer = new OGRODBCTableLayer( this );
 
     if( poLayer->Initialize( pszNewName, pszGeomCol ) )
     {
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp b/ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp
index b077616..e811ebd 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbcdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrodbcdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCDriver class.
@@ -30,7 +29,7 @@
 #include "ogr_odbc.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrodbcdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrodbcdriver.cpp 35145 2016-08-18 14:47:27Z goatbar $");
 
 /************************************************************************/
 /*                            ~OGRODBCDriver()                            */
@@ -59,8 +58,6 @@ OGRDataSource *OGRODBCDriver::Open( const char * pszFilename,
                                      int bUpdate )
 
 {
-    OGRODBCDataSource     *poDS;
-
     if( !STARTS_WITH_CI(pszFilename, "ODBC:")
 #ifdef WIN32
         && !EQUAL(CPLGetExtension(pszFilename), "MDB")
@@ -68,7 +65,7 @@ OGRDataSource *OGRODBCDriver::Open( const char * pszFilename,
         )
         return NULL;
 
-    poDS = new OGRODBCDataSource();
+    OGRODBCDataSource *poDS = new OGRODBCDataSource();
 
     if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
     {
@@ -87,13 +84,10 @@ OGRDataSource *OGRODBCDriver::CreateDataSource( const char * pszName,
                                               char ** /* papszOptions */ )
 
 {
-    OGRODBCDataSource     *poDS;
-
     if( !STARTS_WITH_CI(pszName, "ODBC:") )
         return NULL;
 
-    poDS = new OGRODBCDataSource();
-
+    OGRODBCDataSource *poDS = new OGRODBCDataSource();
 
     if( !poDS->Open( pszName, TRUE, TRUE ) )
     {
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp b/ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp
index 52b15bb..f7e64a8 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbclayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrodbclayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCLayer class, code shared between
@@ -32,30 +31,24 @@
 #include "ogr_odbc.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrodbclayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrodbclayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                            OGRODBCLayer()                            */
 /************************************************************************/
 
-OGRODBCLayer::OGRODBCLayer()
-
-{
-    poDS = NULL;
-
-    bGeomColumnWKB = FALSE;
-    pszGeomColumn = NULL;
-    pszFIDColumn = NULL;
-    panFieldOrdinals = NULL;
-
-    poStmt = NULL;
-
-    iNextShapeId = 0;
-
-    poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet.
-    poFeatureDefn = NULL;
-}
+OGRODBCLayer::OGRODBCLayer() :
+    poFeatureDefn(NULL),
+    poStmt(NULL),
+    poSRS(NULL),
+    nSRSId(-2),  // Have not queried the database for it yet.
+    iNextShapeId(0),
+    poDS(NULL),
+    bGeomColumnWKB(FALSE),
+    pszGeomColumn(NULL),
+    pszFIDColumn(NULL),
+    panFieldOrdinals(NULL)
+{}
 
 /************************************************************************/
 /*                            ~OGRODBCLayer()                             */
@@ -192,7 +185,6 @@ CPLErr OGRODBCLayer::BuildFeatureDefn( const char *pszLayerName,
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -212,9 +204,7 @@ OGRFeature *OGRODBCLayer::GetNextFeature()
 {
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -271,7 +261,7 @@ OGRFeature *OGRODBCLayer::GetNextRawFeature()
         const char *pszValue = poStmt->GetColData( iSrcField );
 
         if( pszValue == NULL )
-            /* no value */;
+            poFeature->SetFieldNull( iField );
         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
             poFeature->SetField( iField,
                                  poStmt->GetColDataLength(iSrcField),
@@ -307,7 +297,7 @@ OGRFeature *OGRODBCLayer::GetNextRawFeature()
 
         if ( eErr != OGRERR_NONE )
         {
-            const char *pszMessage;
+            const char *pszMessage = NULL;
 
             switch ( eErr )
             {
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbcselectlayer.cpp b/ogr/ogrsf_frmts/odbc/ogrodbcselectlayer.cpp
index 7e99a25..752840c 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbcselectlayer.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbcselectlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrodbcselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCSelectLayer class, layer access to the results
@@ -31,14 +30,14 @@
 #include "cpl_conv.h"
 #include "ogr_odbc.h"
 
-CPL_CVSID("$Id: ogrodbcselectlayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
+CPL_CVSID("$Id: ogrodbcselectlayer.cpp 35191 2016-08-24 01:33:06Z goatbar $");
 /************************************************************************/
 /*                          OGRODBCSelectLayer()                         */
 /************************************************************************/
 
 OGRODBCSelectLayer::OGRODBCSelectLayer( OGRODBCDataSource *poDSIn,
-                                        CPLODBCStatement * poStmtIn )
-
+                                        CPLODBCStatement * poStmtIn ) :
+    pszBaseStatement(CPLStrdup(poStmtIn->GetCommand()))
 {
     poDS = poDSIn;
 
@@ -47,7 +46,6 @@ OGRODBCSelectLayer::OGRODBCSelectLayer( OGRODBCDataSource *poDSIn,
     poFeatureDefn = NULL;
 
     poStmt = poStmtIn;
-    pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
 
     BuildFeatureDefn( "SELECT", poStmt );
 }
diff --git a/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp b/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp
index aa0cf96..3ffeaa5 100644
--- a/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp
+++ b/ogr/ogrsf_frmts/odbc/ogrodbctablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrodbctablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRODBCTableLayer class, access to an existing table.
@@ -31,29 +30,23 @@
 #include "cpl_conv.h"
 #include "ogr_odbc.h"
 
-CPL_CVSID("$Id: ogrodbctablelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrodbctablelayer.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 /************************************************************************/
 /*                          OGRODBCTableLayer()                         */
 /************************************************************************/
 
-OGRODBCTableLayer::OGRODBCTableLayer( OGRODBCDataSource *poDSIn )
-
+OGRODBCTableLayer::OGRODBCTableLayer( OGRODBCDataSource *poDSIn ) :
+    pszQuery(NULL),
+    bHaveSpatialExtents(FALSE),
+    pszTableName(NULL),
+    pszSchemaName(NULL)
 {
     poDS = poDSIn;
-
-    pszQuery = NULL;
-
-    bUpdateAccess = TRUE;
-    bHaveSpatialExtents = FALSE;
-
     iNextShapeId = 0;
 
     nSRSId = -1;
 
     poFeatureDefn = NULL;
-
-    pszTableName = NULL;
-    pszSchemaName = NULL;
 }
 
 /************************************************************************/
@@ -187,7 +180,6 @@ CPLErr OGRODBCTableLayer::Initialize( const char *pszLayerName,
         }
     }
 
-
     return CE_None;
 }
 
@@ -312,20 +304,19 @@ OGRErr OGRODBCTableLayer::SetAttributeFilter( const char *pszQueryIn )
     CPLFree(m_pszAttrQueryString);
     m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
 
-    if( (pszQueryIn == NULL && this->pszQuery == NULL)
-        || (pszQueryIn != NULL && this->pszQuery != NULL
-            && EQUAL(pszQueryIn,this->pszQuery)) )
+    if( (pszQueryIn == NULL && pszQuery == NULL)
+        || (pszQueryIn != NULL && pszQuery != NULL
+            && EQUAL(pszQueryIn, pszQuery)) )
         return OGRERR_NONE;
 
-    CPLFree( this->pszQuery );
-    this->pszQuery = (pszQueryIn != NULL ) ? CPLStrdup( pszQueryIn ) : NULL;
+    CPLFree( pszQuery );
+    pszQuery = pszQueryIn != NULL ? CPLStrdup( pszQueryIn ) : NULL;
 
     ClearStatement();
 
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -388,18 +379,17 @@ OGRSpatialReference *OGRODBCTableLayer::GetSpatialRef()
     if( nSRSId == -2 )
     {
         PGconn          *hPGConn = poDS->GetPGConn();
-        PGresult        *hResult;
-        char            szCommand[1024];
 
         nSRSId = -1;
 
         poDS->SoftStartTransaction();
 
+        char szCommand[1024] = {};
         sprintf( szCommand,
                  "SELECT srid FROM geometry_columns "
                  "WHERE f_table_name = '%s'",
                  poFeatureDefn->GetName() );
-        hResult = PQexec(hPGConn, szCommand );
+        PGresult *hResult = PQexec(hPGConn, szCommand );
 
         if( hResult
             && PQresultStatus(hResult) == PGRES_TUPLES_OK
diff --git a/ogr/ogrsf_frmts/ods/ods_formula.cpp b/ogr/ogrsf_frmts/ods/ods_formula.cpp
index 3d949f8..15225b3 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula.cpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ods_formula.cpp 32967 2016-01-13 14:40:01Z goatbar $
  *
  * Component: ODS formula Engine
  * Purpose:
@@ -34,6 +33,8 @@
 #include "cpl_conv.h"
 #include "ods_formula.h"
 
+CPL_CVSID("$Id: ods_formula.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+
 namespace {
 #include "ods_formula_parser.hpp"
 
diff --git a/ogr/ogrsf_frmts/ods/ods_formula.h b/ogr/ogrsf_frmts/ods/ods_formula.h
index 289cfae..d087a10 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula.h
+++ b/ogr/ogrsf_frmts/ods/ods_formula.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ods_formula.h 32967 2016-01-13 14:40:01Z goatbar $
+ * $Id: ods_formula.h 36411 2016-11-21 22:03:48Z rouault $
  *
  * Component: ODS formula Engine
  * Purpose: Implementation of the ods_formula_node class used to represent a
@@ -112,44 +112,49 @@ typedef enum {
 class IODSCellEvaluator;
 
 class ods_formula_node {
-private:
+  private:
     void           FreeSubExpr();
     std::string    TransformToString() const;
 
     // TODO: It appears that all the Evaluate methods should return bool.
-    int            EvaluateOR(IODSCellEvaluator* poEvaluator);
-    int            EvaluateAND(IODSCellEvaluator* poEvaluator);
-    int            EvaluateNOT(IODSCellEvaluator* poEvaluator);
-    int            EvaluateIF(IODSCellEvaluator* poEvaluator);
+    bool           EvaluateOR( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateAND( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateNOT( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateIF( IODSCellEvaluator* poEvaluator );
 
-    int            EvaluateLEN(IODSCellEvaluator* poEvaluator);
-    int            EvaluateLEFT(IODSCellEvaluator* poEvaluator);
-    int            EvaluateRIGHT(IODSCellEvaluator* poEvaluator);
-    int            EvaluateMID(IODSCellEvaluator* poEvaluator);
+    bool           EvaluateLEN( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateLEFT( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateRIGHT( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateMID( IODSCellEvaluator* poEvaluator );
 
-    int            EvaluateListArgOp(IODSCellEvaluator* poEvaluator);
+    bool           EvaluateListArgOp( IODSCellEvaluator* poEvaluator );
 
-    int            EvaluateSingleArgOp(IODSCellEvaluator* poEvaluator);
+    bool           EvaluateSingleArgOp( IODSCellEvaluator* poEvaluator );
 
-    int            EvaluateEQ(IODSCellEvaluator* poEvaluator);
-    int            EvaluateNE(IODSCellEvaluator* poEvaluator);
-    int            EvaluateLE(IODSCellEvaluator* poEvaluator);
-    int            EvaluateGE(IODSCellEvaluator* poEvaluator);
-    int            EvaluateLT(IODSCellEvaluator* poEvaluator);
-    int            EvaluateGT(IODSCellEvaluator* poEvaluator);
+    bool           EvaluateEQ( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateNE( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateLE( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateGE( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateLT( IODSCellEvaluator* poEvaluator );
+    bool           EvaluateGT( IODSCellEvaluator* poEvaluator );
 
-    int            EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator);
+    bool           EvaluateBinaryArithmetic( IODSCellEvaluator* poEvaluator );
 
-    int            EvaluateCONCAT(IODSCellEvaluator* poEvaluator);
+    bool           EvaluateCONCAT( IODSCellEvaluator* poEvaluator );
 
-    int            EvaluateCELL(IODSCellEvaluator* poEvaluator);
+    bool           EvaluateCELL( IODSCellEvaluator* poEvaluator );
 
-public:
+ public:
     ods_formula_node();
 
-    ods_formula_node( const char *, ods_formula_field_type field_type_in = ODS_FIELD_TYPE_STRING );
+    ods_formula_node(
+        const char *,
+        ods_formula_field_type field_type_in = ODS_FIELD_TYPE_STRING );
+    // cppcheck-suppress noExplicitConstructor
     ods_formula_node( int );
+    // cppcheck-suppress noExplicitConstructor
     ods_formula_node( double );
+    // cppcheck-suppress noExplicitConstructor
     ods_formula_node( ods_formula_op );
 
     ods_formula_node( const ods_formula_node& other );
@@ -159,7 +164,7 @@ public:
     void           Initialize();
     void           Dump( FILE *fp, int depth );
 
-    int            Evaluate(IODSCellEvaluator* poEvaluator);
+    bool           Evaluate( IODSCellEvaluator* poEvaluator );
 
     ods_formula_node_type eNodeType;
     ods_formula_field_type field_type;
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_node.cpp b/ogr/ogrsf_frmts/ods/ods_formula_node.cpp
index ae59eb8..9e7fe4f 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_node.cpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula_node.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ods_formula_node.cpp 32967 2016-01-13 14:40:01Z goatbar $
  *
  * Component: ODS formula Engine
  * Purpose: Implementation of the ods_formula_node class used to represent a
@@ -32,6 +31,8 @@
 #include "cpl_conv.h"
 #include "ods_formula.h"
 
+CPL_CVSID("$Id: ods_formula_node.cpp 36979 2016-12-20 18:40:40Z rouault $");
+
 /************************************************************************/
 /*                          ods_formula_node()                          */
 /************************************************************************/
@@ -112,26 +113,25 @@ ods_formula_node::ods_formula_node( ods_formula_op eOpIn ) :
 /*              ods_formula_node(const ods_formula_node&)               */
 /************************************************************************/
 
-ods_formula_node::ods_formula_node( const ods_formula_node& other )
+ods_formula_node::ods_formula_node( const ods_formula_node& other ) :
+    eNodeType(other.eNodeType),
+    field_type(other.field_type),
+    eOp(other.eOp),
+    nSubExprCount(other.nSubExprCount),
+    papoSubExpr(NULL),
+    string_value(other.string_value ? CPLStrdup(other.string_value) : NULL),
+    int_value(other.int_value),
+    float_value(other.float_value)
 {
-    eNodeType = other.eNodeType;
-    eOp = other.eOp;
-    field_type = other.field_type;
-    int_value = other.int_value;
-    float_value = other.float_value;
-    string_value = other.string_value ? CPLStrdup(other.string_value) : NULL;
-    nSubExprCount = other.nSubExprCount;
-    if (nSubExprCount)
+    if( nSubExprCount )
     {
         papoSubExpr = static_cast<ods_formula_node **>(
             CPLMalloc( sizeof(void*) * nSubExprCount ) );
-        for(int i=0;i<nSubExprCount;i++)
+        for( int i = 0; i < nSubExprCount; i++ )
         {
             papoSubExpr[i] = new ods_formula_node( *(other.papoSubExpr[i]) );
         }
     }
-    else
-        papoSubExpr = NULL;
 }
 
 /************************************************************************/
@@ -280,10 +280,10 @@ void  ods_formula_node::FreeSubExpr()
 /*                              Evaluate()                              */
 /************************************************************************/
 
-int ods_formula_node::Evaluate(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::Evaluate(IODSCellEvaluator* poEvaluator)
 {
     if (eNodeType == SNT_CONSTANT)
-        return TRUE;
+        return true;
 
     CPLAssert( eNodeType == SNT_OPERATION );
 
@@ -298,7 +298,7 @@ int ods_formula_node::Evaluate(IODSCellEvaluator* poEvaluator)
             eNodeType = SNT_CONSTANT;
             field_type = ODS_FIELD_TYPE_FLOAT;
             float_value = M_PI;
-            return TRUE;
+            return true;
 
         case ODS_LEN : return EvaluateLEN(poEvaluator);
         case ODS_LEFT : return EvaluateLEFT(poEvaluator);
@@ -326,7 +326,6 @@ int ods_formula_node::Evaluate(IODSCellEvaluator* poEvaluator)
         case ODS_LOG:
             return EvaluateSingleArgOp(poEvaluator);
 
-
         case ODS_EQ: return EvaluateEQ(poEvaluator);
         case ODS_NE: return EvaluateNE(poEvaluator);
         case ODS_LE: return EvaluateLE(poEvaluator);
@@ -350,7 +349,7 @@ int ods_formula_node::Evaluate(IODSCellEvaluator* poEvaluator)
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Unhandled case in Evaluate() for %s",
                      ODSGetOperatorName(eOp));
-            return FALSE;
+            return false;
         }
     }
 }
@@ -359,7 +358,7 @@ int ods_formula_node::Evaluate(IODSCellEvaluator* poEvaluator)
 /*                             EvaluateOR()                             */
 /************************************************************************/
 
-int ods_formula_node::EvaluateOR(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateOR( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_OR );
@@ -371,7 +370,7 @@ int ods_formula_node::EvaluateOR(IODSCellEvaluator* poEvaluator)
     for(int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
     {
         if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
-            return FALSE;
+            return false;
         CPLAssert(papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
         if( papoSubExpr[0]->papoSubExpr[i]->field_type ==
             ODS_FIELD_TYPE_INTEGER )
@@ -387,7 +386,7 @@ int ods_formula_node::EvaluateOR(IODSCellEvaluator* poEvaluator)
         {
             CPLError( CE_Failure, CPLE_NotSupported,
                       "Bad argument type for %s", ODSGetOperatorName(eOp));
-            return FALSE;
+            return false;
         }
     }
 
@@ -397,14 +396,14 @@ int ods_formula_node::EvaluateOR(IODSCellEvaluator* poEvaluator)
     field_type = ODS_FIELD_TYPE_INTEGER;
     int_value = bVal;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                            EvaluateAND()                             */
 /************************************************************************/
 
-int ods_formula_node::EvaluateAND(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateAND( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_AND );
@@ -416,7 +415,7 @@ int ods_formula_node::EvaluateAND(IODSCellEvaluator* poEvaluator)
     for(int i = 0; i < papoSubExpr[0]->nSubExprCount; i++)
     {
         if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
-            return FALSE;
+            return false;
         CPLAssert(papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
         if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_INTEGER)
         {
@@ -431,7 +430,7 @@ int ods_formula_node::EvaluateAND(IODSCellEvaluator* poEvaluator)
         {
             CPLError( CE_Failure, CPLE_NotSupported,
                       "Bad argument type for %s", ODSGetOperatorName(eOp));
-            return FALSE;
+            return false;
         }
     }
 
@@ -441,21 +440,21 @@ int ods_formula_node::EvaluateAND(IODSCellEvaluator* poEvaluator)
     field_type = ODS_FIELD_TYPE_INTEGER;
     int_value = bVal;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                            EvaluateNOT()                             */
 /************************************************************************/
 
-int ods_formula_node::EvaluateNOT(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateNOT( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_NOT );
 
     CPLAssert(nSubExprCount == 1);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
 
     bool bVal = false;
@@ -471,7 +470,7 @@ int ods_formula_node::EvaluateNOT(IODSCellEvaluator* poEvaluator)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Bad argument type for %s", ODSGetOperatorName(eOp));
-        return FALSE;
+        return false;
     }
 
     FreeSubExpr();
@@ -480,25 +479,25 @@ int ods_formula_node::EvaluateNOT(IODSCellEvaluator* poEvaluator)
     field_type = ODS_FIELD_TYPE_INTEGER;
     int_value = bVal;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                            EvaluateIF()                              */
 /************************************************************************/
 
-int ods_formula_node::EvaluateIF(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateIF( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_IF );
 
     CPLAssert(nSubExprCount == 2 || nSubExprCount == 3);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (nSubExprCount == 3 && !(papoSubExpr[2]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -519,7 +518,7 @@ int ods_formula_node::EvaluateIF(IODSCellEvaluator* poEvaluator)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Bad argument type for %s", ODSGetOperatorName(eOp));
-        return FALSE;
+        return false;
     }
 
     if (bCond)
@@ -559,23 +558,23 @@ int ods_formula_node::EvaluateIF(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                            EvaluateEQ()                              */
 /************************************************************************/
 
-int ods_formula_node::EvaluateEQ(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateEQ( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_EQ );
 
     CPLAssert(nSubExprCount == 2);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -617,7 +616,7 @@ int ods_formula_node::EvaluateEQ(IODSCellEvaluator* poEvaluator)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Bad argument type for %s", ODSGetOperatorName(eOp));
-        return FALSE;
+        return false;
     }
 
     eNodeType = SNT_CONSTANT;
@@ -626,24 +625,24 @@ int ods_formula_node::EvaluateEQ(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                           EvaluateNE()                               */
 /************************************************************************/
 
-int ods_formula_node::EvaluateNE(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateNE( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_NE );
 
     eOp = ODS_EQ;
     if (!EvaluateEQ(poEvaluator))
-        return FALSE;
+        return false;
 
     int_value = !int_value;
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -660,7 +659,7 @@ typedef enum
 static CaseType GetCase(const char* pszStr)
 {
     bool bInit = true;
-    char ch;
+    char ch = '\0';
     CaseType eCase = CASE_UNKNOWN;
     while((ch = *(pszStr++)) != '\0')
     {
@@ -688,16 +687,16 @@ static CaseType GetCase(const char* pszStr)
 /*                            EvaluateLE()                              */
 /************************************************************************/
 
-int ods_formula_node::EvaluateLE(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateLE( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_LE );
 
     CPLAssert(nSubExprCount == 2);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -748,7 +747,7 @@ int ods_formula_node::EvaluateLE(IODSCellEvaluator* poEvaluator)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Bad argument type for %s", ODSGetOperatorName(eOp));
-        return FALSE;
+        return false;
     }
 
     eNodeType = SNT_CONSTANT;
@@ -757,23 +756,23 @@ int ods_formula_node::EvaluateLE(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                            EvaluateGE()                              */
 /************************************************************************/
 
-int ods_formula_node::EvaluateGE(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateGE( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_GE );
 
     CPLAssert(nSubExprCount == 2);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -822,7 +821,7 @@ int ods_formula_node::EvaluateGE(IODSCellEvaluator* poEvaluator)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Bad argument type for %s", ODSGetOperatorName(eOp));
-        return FALSE;
+        return false;
     }
 
     eNodeType = SNT_CONSTANT;
@@ -831,23 +830,23 @@ int ods_formula_node::EvaluateGE(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                            EvaluateLT()                              */
 /************************************************************************/
 
-int ods_formula_node::EvaluateLT(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateLT( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_LT );
 
     CPLAssert(nSubExprCount == 2);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -898,7 +897,7 @@ int ods_formula_node::EvaluateLT(IODSCellEvaluator* poEvaluator)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Bad argument type for %s", ODSGetOperatorName(eOp));
-        return FALSE;
+        return false;
     }
 
     eNodeType = SNT_CONSTANT;
@@ -907,23 +906,23 @@ int ods_formula_node::EvaluateLT(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                            EvaluateGT()                              */
 /************************************************************************/
 
-int ods_formula_node::EvaluateGT(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateGT( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_GT );
 
     CPLAssert(nSubExprCount == 2);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -972,7 +971,7 @@ int ods_formula_node::EvaluateGT(IODSCellEvaluator* poEvaluator)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Bad argument type for %s", ODSGetOperatorName(eOp));
-        return FALSE;
+        return false;
     }
 
     eNodeType = SNT_CONSTANT;
@@ -981,14 +980,14 @@ int ods_formula_node::EvaluateGT(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                         EvaluateSingleArgOp()                        */
 /************************************************************************/
 
-int ods_formula_node::EvaluateSingleArgOp(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateSingleArgOp( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
 
@@ -997,7 +996,7 @@ int ods_formula_node::EvaluateSingleArgOp(IODSCellEvaluator* poEvaluator)
 
     CPLAssert(nSubExprCount == 1);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     double dfVal = 0.0;
@@ -1014,7 +1013,7 @@ int ods_formula_node::EvaluateSingleArgOp(IODSCellEvaluator* poEvaluator)
     {
         CPLError(CE_Failure, CPLE_NotSupported, "Bad argument type for %s",
                  psSingleOp->pszName);
-        return FALSE;
+        return false;
     }
 
     eNodeType = SNT_CONSTANT;
@@ -1023,23 +1022,24 @@ int ods_formula_node::EvaluateSingleArgOp(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                       EvaluateBinaryArithmetic()                     */
 /************************************************************************/
 
-int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
+bool
+ods_formula_node::EvaluateBinaryArithmetic( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp >= ODS_ADD && eOp<= ODS_MODULUS );
 
     CPLAssert(nSubExprCount == 2);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -1066,17 +1066,17 @@ int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
                         nVal = papoSubExpr[0]->int_value /
                             papoSubExpr[1]->int_value;
                     else
-                        return FALSE;
+                        return false;
                     break;
                 case ODS_MODULUS  :
                     if( papoSubExpr[1]->int_value != 0 )
                         nVal = papoSubExpr[0]->int_value %
                             papoSubExpr[1]->int_value;
                     else
-                        return FALSE;
+                        return false;
                     break;
                 default:
-                    CPLAssert(0);
+                    CPLAssert(false);
             }
 
             eNodeType = SNT_CONSTANT;
@@ -1085,7 +1085,7 @@ int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
 
             FreeSubExpr();
 
-            return TRUE;
+            return true;
         }
         else if (papoSubExpr[1]->field_type == ODS_FIELD_TYPE_FLOAT)
         {
@@ -1096,7 +1096,7 @@ int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Bad argument type for %s", ODSGetOperatorName(eOp));
-            return FALSE;
+            return false;
         }
     }
 
@@ -1121,15 +1121,15 @@ int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
                     if (papoSubExpr[1]->float_value != 0)
                         dfVal = (papoSubExpr[0]->float_value / papoSubExpr[1]->float_value);
                     else
-                        return FALSE;
+                        return false;
                     break;
                 case ODS_MODULUS  :
                     if (papoSubExpr[1]->float_value != 0)
                         dfVal = fmod(papoSubExpr[0]->float_value, papoSubExpr[1]->float_value);
                     else
-                        return FALSE;
+                        return false;
                     break;
-                default: CPLAssert(0);
+                default: CPLAssert(false);
             }
 
             eNodeType = SNT_CONSTANT;
@@ -1138,24 +1138,23 @@ int ods_formula_node::EvaluateBinaryArithmetic(IODSCellEvaluator* poEvaluator)
 
             FreeSubExpr();
 
-            return TRUE;
+            return true;
         }
         else
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Bad argument type for %s", ODSGetOperatorName(eOp));
-            return FALSE;
+            return false;
         }
     }
     else
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Bad argument type for %s", ODSGetOperatorName(eOp));
-        return FALSE;
+        return false;
     }
 }
 
-
 /************************************************************************/
 /*                         TransformToString()                          */
 /************************************************************************/
@@ -1187,16 +1186,16 @@ std::string ods_formula_node::TransformToString() const
 /*                           EvaluateCONCAT()                           */
 /************************************************************************/
 
-int ods_formula_node::EvaluateCONCAT(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateCONCAT( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_CONCAT );
 
     CPLAssert(nSubExprCount == 2);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -1210,7 +1209,7 @@ int ods_formula_node::EvaluateCONCAT(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1241,7 +1240,7 @@ static bool GetRowCol(const char* pszCell, int& nRow, int& nCol)
 /*                         EvaluateListArgOp()                          */
 /************************************************************************/
 
-int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateListArgOp( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp >= ODS_SUM && eOp <= ODS_COUNTA );
@@ -1251,12 +1250,11 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
     CPLAssert(papoSubExpr[0]->eOp == ODS_LIST );
 
     std::vector<double> adfVal;
-    int i;
 
     int nCount = 0;
     int nCountA = 0;
 
-    for(i=0;i<papoSubExpr[0]->nSubExprCount;i++)
+    for( int i = 0; i < papoSubExpr[0]->nSubExprCount; i++ )
     {
         if (papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_OPERATION &&
             papoSubExpr[0]->papoSubExpr[i]->eOp == ODS_CELL_RANGE)
@@ -1270,7 +1268,7 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
             if (poEvaluator == NULL)
             {
                 CPLError(CE_Failure, CPLE_AppDefined, "No cell evaluator provided");
-                return FALSE;
+                return false;
             }
 
             const char* psz1 = papoSubExpr[0]->papoSubExpr[i]->papoSubExpr[0]->string_value;
@@ -1278,11 +1276,11 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
             int nRow1 = 0;
             int nCol1 = 0;
             if (!GetRowCol(psz1, nRow1, nCol1))
-                return FALSE;
+                return false;
             int nRow2 = 0;
             int nCol2 = 0;
             if (!GetRowCol(psz2, nRow2, nCol2))
-                return FALSE;
+                return false;
 
             std::vector<ods_formula_node> aoOutValues;
             if (poEvaluator->EvaluateRange(nRow1, nCol1, nRow2, nCol2, aoOutValues))
@@ -1314,7 +1312,7 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
         else
         {
             if (!(papoSubExpr[0]->papoSubExpr[i]->Evaluate(poEvaluator)))
-                return FALSE;
+                return false;
 
             CPLAssert (papoSubExpr[0]->papoSubExpr[i]->eNodeType == SNT_CONSTANT );
             if (papoSubExpr[0]->papoSubExpr[i]->field_type == ODS_FIELD_TYPE_INTEGER)
@@ -1339,7 +1337,7 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
 
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "Bad argument type for %s", ODSGetOperatorName(eOp));
-                return FALSE;
+                return false;
             }
         }
     }
@@ -1351,7 +1349,7 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
         int_value = nCount;
 
         FreeSubExpr();
-        return TRUE;
+        return true;
     }
 
     if (eOp == ODS_COUNTA)
@@ -1361,7 +1359,7 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
         int_value = nCountA;
 
         FreeSubExpr();
-        return TRUE;
+        return true;
     }
 
     double dfVal = 0.0;
@@ -1370,7 +1368,7 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
     {
         case ODS_SUM:
         {
-            for(i=0;i<(int)adfVal.size();i++)
+            for( int i = 0; i < (int)adfVal.size(); i++ )
             {
                 dfVal += adfVal[i];
             }
@@ -1379,7 +1377,7 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
 
         case ODS_AVERAGE:
         {
-            for(i=0;i<(int)adfVal.size();i++)
+            for( int i = 0; i < (int)adfVal.size(); i++ )
             {
                 dfVal += adfVal[i];
             }
@@ -1389,8 +1387,8 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
 
         case ODS_MIN:
         {
-            dfVal = (adfVal.size() == 0) ? 0 :adfVal[0];
-            for(i=1;i<(int)adfVal.size();i++)
+            dfVal = (adfVal.empty()) ? 0 :adfVal[0];
+            for( int i = 1; i < (int)adfVal.size(); i++ )
             {
                 if (adfVal[i] < dfVal) dfVal = adfVal[i];
             }
@@ -1399,8 +1397,8 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
 
         case ODS_MAX:
         {
-            dfVal = (adfVal.size() == 0) ? 0 :adfVal[0];
-            for(i=1;i<(int)adfVal.size();i++)
+            dfVal = (adfVal.empty()) ? 0 :adfVal[0];
+            for( int i = 1; i < (int)adfVal.size(); i++ )
             {
                 if (adfVal[i] > dfVal) dfVal = adfVal[i];
             }
@@ -1417,14 +1415,14 @@ int ods_formula_node::EvaluateListArgOp(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                           EvaluateCELL()                             */
 /************************************************************************/
 
-int ods_formula_node::EvaluateCELL(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateCELL( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
     CPLAssert( eOp == ODS_CELL );
@@ -1436,13 +1434,13 @@ int ods_formula_node::EvaluateCELL(IODSCellEvaluator* poEvaluator)
     if (poEvaluator == NULL)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "No cell evaluator provided");
-        return FALSE;
+        return false;
     }
 
     int nRow = 0;
     int nCol = 0;
     if (!GetRowCol(papoSubExpr[0]->string_value, nRow, nCol))
-        return FALSE;
+        return false;
 
     std::vector<ods_formula_node> aoOutValues;
     if (poEvaluator->EvaluateRange(nRow, nCol, nRow, nCol, aoOutValues) &&
@@ -1459,24 +1457,24 @@ int ods_formula_node::EvaluateCELL(IODSCellEvaluator* poEvaluator)
             string_value = aoOutValues[0].string_value ?
                 CPLStrdup(aoOutValues[0].string_value) : NULL;
 
-            return TRUE;
+            return true;
         }
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                           EvaluateLEN()                              */
 /************************************************************************/
 
-int ods_formula_node::EvaluateLEN(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateLEN( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
 
     CPLAssert(nSubExprCount == 1);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
 
@@ -1484,26 +1482,26 @@ int ods_formula_node::EvaluateLEN(IODSCellEvaluator* poEvaluator)
 
     eNodeType = SNT_CONSTANT;
     field_type = ODS_FIELD_TYPE_INTEGER;
-    int_value = static_cast<int>(strlen(osVal.c_str())); // FIXME : UTF8 support
+    int_value = static_cast<int>(osVal.size()); // FIXME : UTF8 support
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                           EvaluateLEFT()                             */
 /************************************************************************/
 
-int ods_formula_node::EvaluateLEFT(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateLEFT( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
 
     CPLAssert(nSubExprCount == 2);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -1511,12 +1509,12 @@ int ods_formula_node::EvaluateLEFT(IODSCellEvaluator* poEvaluator)
     std::string osVal = papoSubExpr[0]->TransformToString();
 
     if (papoSubExpr[1]->field_type != ODS_FIELD_TYPE_INTEGER)
-        return FALSE;
+        return false;
 
     // FIXME : UTF8 support
     const int nVal = papoSubExpr[1]->int_value;
     if (nVal < 0)
-        return FALSE;
+        return false;
 
     osVal = osVal.substr(0,nVal);
 
@@ -1526,22 +1524,22 @@ int ods_formula_node::EvaluateLEFT(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                           EvaluateRIGHT()                            */
 /************************************************************************/
 
-int ods_formula_node::EvaluateRIGHT(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateRIGHT( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
 
     CPLAssert(nSubExprCount == 2);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -1549,13 +1547,13 @@ int ods_formula_node::EvaluateRIGHT(IODSCellEvaluator* poEvaluator)
     std::string osVal = papoSubExpr[0]->TransformToString();
 
     if (papoSubExpr[1]->field_type != ODS_FIELD_TYPE_INTEGER)
-        return FALSE;
+        return false;
 
     // FIXME : UTF8 support
     const size_t nLen = osVal.size();
     const int nVal = papoSubExpr[1]->int_value;
     if (nVal < 0)
-        return FALSE;
+        return false;
 
     if (nLen > (size_t) nVal)
         osVal = osVal.substr(nLen-nVal);
@@ -1566,24 +1564,24 @@ int ods_formula_node::EvaluateRIGHT(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                           EvaluateMID()                             */
 /************************************************************************/
 
-int ods_formula_node::EvaluateMID(IODSCellEvaluator* poEvaluator)
+bool ods_formula_node::EvaluateMID( IODSCellEvaluator* poEvaluator )
 {
     CPLAssert( eNodeType == SNT_OPERATION );
 
     CPLAssert(nSubExprCount == 3);
     if (!(papoSubExpr[0]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[1]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
     if (!(papoSubExpr[2]->Evaluate(poEvaluator)))
-        return FALSE;
+        return false;
 
     CPLAssert(papoSubExpr[0]->eNodeType == SNT_CONSTANT );
     CPLAssert(papoSubExpr[1]->eNodeType == SNT_CONSTANT );
@@ -1592,19 +1590,19 @@ int ods_formula_node::EvaluateMID(IODSCellEvaluator* poEvaluator)
     std::string osVal = papoSubExpr[0]->TransformToString();
 
     if (papoSubExpr[1]->field_type != ODS_FIELD_TYPE_INTEGER)
-        return FALSE;
+        return false;
 
     if (papoSubExpr[2]->field_type != ODS_FIELD_TYPE_INTEGER)
-        return FALSE;
+        return false;
 
     // FIXME : UTF8 support
     const size_t nLen = osVal.size();
     const int nStart = papoSubExpr[1]->int_value;
     const int nExtractLen = papoSubExpr[2]->int_value;
     if (nStart <= 0)
-        return FALSE;
+        return false;
     if (nExtractLen < 0)
-        return FALSE;
+        return false;
 
     if ((size_t)nStart <= nLen)
     {
@@ -1622,5 +1620,5 @@ int ods_formula_node::EvaluateMID(IODSCellEvaluator* poEvaluator)
 
     FreeSubExpr();
 
-    return TRUE;
+    return true;
 }
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp b/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp
index 1da46ff..5fdeb02 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp
+++ b/ogr/ogrsf_frmts/ods/ods_formula_parser.cpp
@@ -58,7 +58,6 @@
 /* Pull parsers.  */
 #define YYPULL 1
 
-
 /* Substitute the variable and function names.  */
 #define yyparse         ods_formulaparse
 #define yylex           ods_formulalex
@@ -66,12 +65,10 @@
 #define yydebug         ods_formuladebug
 #define yynerrs         ods_formulanerrs
 
-
 /* Copy the first part of user declarations.  */
 #line 1 "ods_formula_parser.y" /* yacc.c:339  */
 
 /******************************************************************************
- * $Id: ods_formula_parser.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Component: OGR ODS Formula Engine
  * Purpose: expression and select parser grammar.
@@ -121,7 +118,6 @@ static void ods_formulaerror( ods_formula_parse_context * /* context */,
               "Formula Parsing Error: %s", msg );
 }
 
-
 #line 126 "ods_formula_parser.cpp" /* yacc.c:339  */
 
 # ifndef YY_NULL
diff --git a/ogr/ogrsf_frmts/ods/ods_formula_parser.y b/ogr/ogrsf_frmts/ods/ods_formula_parser.y
index 67187ea..2104784 100644
--- a/ogr/ogrsf_frmts/ods/ods_formula_parser.y
+++ b/ogr/ogrsf_frmts/ods/ods_formula_parser.y
@@ -1,6 +1,5 @@
 %{
 /******************************************************************************
- * $Id: ods_formula_parser.y 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Component: OGR ODS Formula Engine
  * Purpose: expression and select parser grammar.
@@ -34,6 +33,8 @@
 #include "cpl_string.h"
 #include "ods_formula.h"
 
+CPL_CVSID("$Id: ods_formula_parser.y 34819 2016-07-28 22:32:18Z goatbar $");
+
 #define YYSTYPE  ods_formula_node*
 
 /* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */
diff --git a/ogr/ogrsf_frmts/ods/ogr_ods.h b/ogr/ogrsf_frmts/ods/ogr_ods.h
index 47af44f..7118cac 100644
--- a/ogr/ogrsf_frmts/ods/ogr_ods.h
+++ b/ogr/ogrsf_frmts/ods/ogr_ods.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_ods.h 32989 2016-01-14 21:28:07Z rouault $
+ * $Id: ogr_ods.h 37192 2017-01-20 14:17:37Z rouault $
  *
  * Project:  ODS Translator
  * Purpose:  Definition of classes for OGR OpenOfficeSpreadsheet .ods driver.
@@ -52,48 +52,56 @@ class OGRODSLayer : public OGRMemLayer
     OGRODSDataSource* poDS;
     bool              bUpdated;
     bool              bHasHeaderLine;
+    OGRFeatureQuery  *m_poAttrQueryODS;
 
     public:
         OGRODSLayer( OGRODSDataSource* poDSIn,
                       const char * pszName,
                       bool bUpdateIn = FALSE);
+       ~OGRODSLayer();
 
     void                SetUpdated(bool bUpdatedIn = true);
 
     bool                GetHasHeaderLine() { return bHasHeaderLine; }
     void                SetHasHeaderLine(bool bIn) { bHasHeaderLine = bIn; }
 
-    const char         *GetName() { return OGRMemLayer::GetLayerDefn()->GetName(); };
-    OGRwkbGeometryType  GetGeomType() { return wkbNone; }
-    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
+    const char         *GetName() override { return OGRMemLayer::GetLayerDefn()->GetName(); };
+    OGRwkbGeometryType  GetGeomType() override { return wkbNone; }
+    virtual OGRSpatialReference *GetSpatialRef() override { return NULL; }
 
     /* For external usage. Mess with FID */
-    virtual OGRFeature *        GetNextFeature();
-    virtual OGRFeature         *GetFeature( GIntBig nFeatureId );
-    virtual OGRErr              ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr              DeleteFeature( GIntBig nFID );
+    virtual OGRFeature *        GetNextFeature() override;
+    virtual OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
+    virtual OGRErr              ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr              DeleteFeature( GIntBig nFID ) override;
+
+    virtual GIntBig             GetFeatureCount( int ) override;
+
+    virtual OGRErr              SetAttributeFilter( const char *pszQuery ) override;
+
+    virtual int                 TestCapability( const char * pszCap ) override;
 
     /* For internal usage, for cell resolver */
     OGRFeature *        GetNextFeatureWithoutFIDHack() { return OGRMemLayer::GetNextFeature(); }
     OGRErr              SetFeatureWithoutFIDHack( OGRFeature *poFeature ) { SetUpdated(); return OGRMemLayer::ISetFeature(poFeature); }
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature )
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override
     { SetUpdated(); return OGRMemLayer::ICreateFeature(poFeature); }
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE )
+                                     int bApproxOK = TRUE ) override
     {  SetUpdated(); return OGRMemLayer::CreateField(poField, bApproxOK); }
 
-    virtual OGRErr      DeleteField( int iField )
+    virtual OGRErr      DeleteField( int iField ) override
     { SetUpdated(); return OGRMemLayer::DeleteField(iField); }
 
-    virtual OGRErr      ReorderFields( int* panMap )
+    virtual OGRErr      ReorderFields( int* panMap ) override
     { SetUpdated(); return OGRMemLayer::ReorderFields(panMap); }
 
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn ) override
     { SetUpdated(); return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn); }
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 };
 
 /************************************************************************/
@@ -148,7 +156,7 @@ class OGRODSDataSource : public OGRDataSource
     int                 nRowsRepeated;
     int                 nCurCol;
     int                 nCellsRepeated;
-    int                 bEndTableParsing;
+    bool                bEndTableParsing;
 
     OGRODSLayer        *poCurLayer;
 
@@ -184,7 +192,7 @@ class OGRODSDataSource : public OGRDataSource
 
   public:
                         OGRODSDataSource();
-                        ~OGRODSDataSource();
+                        virtual ~OGRODSDataSource();
 
     int                 Open( const char * pszFilename,
                               VSILFILE* fpContentIn,
@@ -192,20 +200,20 @@ class OGRODSDataSource : public OGRDataSource
                               int bUpdatableIn );
     int                 Create( const char * pszName, char **papszOptions );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount();
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override;
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     virtual OGRLayer* ICreateLayer( const char * pszLayerName,
                                 OGRSpatialReference *poSRS,
                                 OGRwkbGeometryType eType,
-                                char ** papszOptions );
-    virtual OGRErr      DeleteLayer(int iLayer);
+                                char ** papszOptions ) override;
+    virtual OGRErr      DeleteLayer(int iLayer) override;
 
-    virtual void        FlushCache();
+    virtual void        FlushCache() override;
 
     void startElementCbk(const char *pszName, const char **ppszAttr);
     void endElementCbk(const char *pszName);
@@ -228,15 +236,15 @@ class OGRODSDataSource : public OGRDataSource
 class OGRODSDriver : public OGRSFDriver
 {
   public:
-                ~OGRODSDriver();
+                virtual ~OGRODSDriver();
 
-    virtual const char*         GetName();
-    virtual OGRDataSource*      Open( const char *, int );
-    virtual int                 TestCapability( const char * );
+    virtual const char*         GetName() override;
+    virtual OGRDataSource*      Open( const char *, int ) override;
+    virtual int                 TestCapability( const char * ) override;
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
-                                             char ** = NULL );
-    virtual OGRErr      DeleteDataSource( const char *pszName );
+                                             char ** = NULL ) override;
+    virtual OGRErr      DeleteDataSource( const char *pszName ) override;
 };
 
 #endif /* ndef OGR_ODS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp b/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp
index 4e84acc..bae9716 100644
--- a/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp
+++ b/ogr/ogrsf_frmts/ods/ogrodsdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrodsdatasource.cpp 33199 2016-01-29 15:48:41Z rouault $
  *
  * Project:  ODS Translator
  * Purpose:  Implements OGRODSDataSource class
@@ -31,10 +30,11 @@
 #include "ogr_mem.h"
 #include "ogr_p.h"
 #include "cpl_conv.h"
+#include "cpl_vsi_error.h"
 #include "ods_formula.h"
 #include <set>
 
-CPL_CVSID("$Id: ogrodsdatasource.cpp 33199 2016-01-29 15:48:41Z rouault $");
+CPL_CVSID("$Id: ogrodsdatasource.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 namespace OGRODS {
 
@@ -49,16 +49,16 @@ private:
         std::set<std::pair<int,int> > oVisisitedCells;
 
 public:
-        ODSCellEvaluator(OGRODSLayer* poLayerIn) : poLayer(poLayerIn) {}
+        explicit ODSCellEvaluator(OGRODSLayer* poLayerIn) : poLayer(poLayerIn) {}
 
         int EvaluateRange(int nRow1, int nCol1, int nRow2, int nCol2,
-                          std::vector<ods_formula_node>& aoOutValues);
+                          std::vector<ods_formula_node>& aoOutValues) override;
 
         int Evaluate(int nRow, int nCol);
 };
 
 /************************************************************************/
-/*                            OGRODSLayer()                            */
+/*                            OGRODSLayer()                             */
 /************************************************************************/
 
 OGRODSLayer::OGRODSLayer( OGRODSDataSource* poDSIn,
@@ -67,10 +67,20 @@ OGRODSLayer::OGRODSLayer( OGRODSDataSource* poDSIn,
     OGRMemLayer(pszName, NULL, wkbNone),
     poDS(poDSIn),
     bUpdated(CPL_TO_BOOL(bUpdatedIn)),
-    bHasHeaderLine(false)
+    bHasHeaderLine(false),
+    m_poAttrQueryODS(NULL)
 {}
 
 /************************************************************************/
+/*                            ~OGRODSLayer()                            */
+/************************************************************************/
+
+OGRODSLayer::~OGRODSLayer()
+{
+    delete m_poAttrQueryODS;
+}
+
+/************************************************************************/
 /*                             Updated()                                */
 /************************************************************************/
 
@@ -103,10 +113,19 @@ OGRErr OGRODSLayer::SyncToDisk()
 
 OGRFeature* OGRODSLayer::GetNextFeature()
 {
-    OGRFeature* poFeature = OGRMemLayer::GetNextFeature();
-    if (poFeature)
+    while(true)
+    {
+        OGRFeature* poFeature = OGRMemLayer::GetNextFeature();
+        if (poFeature == NULL )
+            return NULL;
         poFeature->SetFID(poFeature->GetFID() + 1 + (bHasHeaderLine ? 1 : 0));
-    return poFeature;
+        if( m_poAttrQueryODS == NULL
+               || m_poAttrQueryODS->Evaluate( poFeature ) )
+        {
+            return poFeature;
+        }
+        delete poFeature;
+    }
 }
 
 /************************************************************************/
@@ -123,6 +142,17 @@ OGRFeature* OGRODSLayer::GetFeature( GIntBig nFeatureId )
 }
 
 /************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig OGRODSLayer::GetFeatureCount( int bForce )
+{
+    if( m_poAttrQueryODS == NULL )
+        return OGRMemLayer::GetFeatureCount(bForce);
+    return OGRLayer::GetFeatureCount( bForce );
+}
+
+/************************************************************************/
 /*                           ISetFeature()                               */
 /************************************************************************/
 
@@ -151,44 +181,65 @@ OGRErr OGRODSLayer::DeleteFeature( GIntBig nFID )
 }
 
 /************************************************************************/
-/*                          OGRODSDataSource()                          */
+/*                         SetAttributeFilter()                         */
 /************************************************************************/
 
-OGRODSDataSource::OGRODSDataSource() :
-    nFlags(0)
+OGRErr OGRODSLayer::SetAttributeFilter( const char *pszQuery )
+
 {
-    pszName = NULL;
-    fpContent = NULL;
-    fpSettings = NULL;
-    bUpdatable = false;
-    bUpdated = false;
-    bAnalysedFile = false;
+    // Intercept attribute filter since we mess up with FIDs
+    OGRErr eErr = OGRLayer::SetAttributeFilter(pszQuery);
+    delete m_poAttrQueryODS;
+    m_poAttrQueryODS = m_poAttrQuery;
+    m_poAttrQuery = NULL;
+    return eErr;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
 
-    nLayers = 0;
-    papoLayers = NULL;
+int OGRODSLayer::TestCapability( const char * pszCap )
 
-    bFirstLineIsHeaders = false;
+{
+    if( EQUAL(pszCap,OLCFastFeatureCount) )
+        return m_poFilterGeom == NULL && m_poAttrQueryODS == NULL;
+    return OGRMemLayer::TestCapability(pszCap);
+}
 
-    oParser = NULL;
-    bStopParsing = false;
-    nWithoutEventCounter = 0;
-    nDataHandlerCounter = 0;
-    nStackDepth = 0;
-    nDepth = 0;
-    nCurLine = 0;
-    nEmptyRowsAccumulated = 0;
-    nCurCol = 0;
-    nRowsRepeated = 0;
-    nCellsRepeated = 0;
+/************************************************************************/
+/*                          OGRODSDataSource()                          */
+/************************************************************************/
+
+OGRODSDataSource::OGRODSDataSource() :
+    pszName(NULL),
+    bUpdatable(false),
+    bUpdated(false),
+    bAnalysedFile(false),
+    nLayers(0),
+    papoLayers(NULL),
+    fpSettings(NULL),
+    nFlags(0),
+    fpContent(NULL),
+    bFirstLineIsHeaders(false),
+    bAutodetectTypes(
+        !EQUAL(CPLGetConfigOption("OGR_ODS_FIELD_TYPES", ""), "STRING")),
+    oParser(NULL),
+    bStopParsing(false),
+    nWithoutEventCounter(0),
+    nDataHandlerCounter(0),
+    nCurLine(0),
+    nEmptyRowsAccumulated(0),
+    nRowsRepeated(0),
+    nCurCol(0),
+    nCellsRepeated(0),
+    bEndTableParsing(false),
+    poCurLayer(NULL),
+    nStackDepth(0),
+    nDepth(0)
+{
     stateStack[0].eVal = STATE_DEFAULT;
     stateStack[0].nBeginDepth = 0;
-    bEndTableParsing = FALSE;
-
-    poCurLayer = NULL;
-
-    const char* pszODSFieldTypes =
-                CPLGetConfigOption("OGR_ODS_FIELD_TYPES", "");
-    bAutodetectTypes = !EQUAL(pszODSFieldTypes, "STRING");
 }
 
 /************************************************************************/
@@ -223,11 +274,12 @@ int OGRODSDataSource::TestCapability( const char * pszCap )
         return bUpdatable;
     else if( EQUAL(pszCap,ODsCDeleteLayer) )
         return bUpdatable;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return bUpdatable;
     else
         return FALSE;
 }
 
-
 /************************************************************************/
 /*                              GetLayer()                              */
 /************************************************************************/
@@ -477,7 +529,7 @@ static void SetField(OGRFeature* poFeature,
     if (eType == OFTTime)
     {
         int nHour, nHourRepeated, nMinute, nSecond;
-        char c;
+        char c = '\0';
         if (STARTS_WITH(pszValue, "PT") &&
             sscanf(pszValue + 2, "%02d%c%02d%c%02d%c",
                    &nHour, &c, &nMinute, &c, &nSecond, &c) == 6)
@@ -513,22 +565,22 @@ static void SetField(OGRFeature* poFeature,
 void OGRODSDataSource::DetectHeaderLine()
 
 {
-    int bHeaderLineCandidate = TRUE;
-    size_t i;
-    for(i = 0; i < apoFirstLineTypes.size(); i++)
+    bool bHeaderLineCandidate = true;
+
+    for( size_t i = 0; i < apoFirstLineTypes.size(); i++ )
     {
         if (apoFirstLineTypes[i] != "string")
         {
             /* If the values in the first line are not text, then it is */
             /* not a header line */
-            bHeaderLineCandidate = FALSE;
+            bHeaderLineCandidate = false;
             break;
         }
     }
 
     size_t nCountTextOnCurLine = 0;
     size_t nCountNonEmptyOnCurLine = 0;
-    for(i = 0; bHeaderLineCandidate && i < apoCurLineTypes.size(); i++)
+    for( size_t i = 0; bHeaderLineCandidate && i < apoCurLineTypes.size(); i++ )
     {
         if (apoCurLineTypes[i] == "string")
         {
@@ -553,11 +605,11 @@ void OGRODSDataSource::DetectHeaderLine()
     {
         bFirstLineIsHeaders = true;
     }
-    else if (bHeaderLineCandidate &&
-             apoFirstLineTypes.size() != 0 &&
+    else if( bHeaderLineCandidate &&
+             !apoFirstLineTypes.empty() &&
              apoFirstLineTypes.size() == apoCurLineTypes.size() &&
              nCountTextOnCurLine != apoFirstLineTypes.size() &&
-             nCountNonEmptyOnCurLine != 0)
+             nCountNonEmptyOnCurLine != 0 )
     {
         bFirstLineIsHeaders = true;
     }
@@ -587,7 +639,7 @@ void OGRODSDataSource::startElementDefault(const char *pszNameIn,
         apoFirstLineValues.resize(0);
         apoFirstLineTypes.resize(0);
         PushState(STATE_TABLE);
-        bEndTableParsing = FALSE;
+        bEndTableParsing = false;
     }
 }
 
@@ -598,13 +650,13 @@ void OGRODSDataSource::startElementDefault(const char *pszNameIn,
 void OGRODSDataSource::startElementTable(const char *pszNameIn,
                                          const char **ppszAttr)
 {
-    if (strcmp(pszNameIn, "table:table-row") == 0 && !bEndTableParsing)
+    if( strcmp(pszNameIn, "table:table-row") == 0 && !bEndTableParsing )
     {
         nRowsRepeated = atoi(
             GetAttributeValue(ppszAttr, "table:number-rows-repeated", "1"));
         if (nRowsRepeated > 65536)
         {
-            bEndTableParsing = TRUE;
+            bEndTableParsing = true;
             return;
         }
 
@@ -629,7 +681,7 @@ void OGRODSDataSource::endElementTable( CPL_UNUSED /* in non-DEBUG*/ const char
         CPLAssert(strcmp(pszNameIn, "table:table") == 0);
 
         if (nCurLine == 0 ||
-            (nCurLine == 1 && apoFirstLineValues.size() == 0))
+            (nCurLine == 1 && apoFirstLineValues.empty()))
         {
             /* Remove empty sheet */
             delete poCurLayer;
@@ -639,8 +691,8 @@ void OGRODSDataSource::endElementTable( CPL_UNUSED /* in non-DEBUG*/ const char
         else if (nCurLine == 1)
         {
             /* If we have only one single line in the sheet */
-            size_t i;
-            for(i = 0; i < apoFirstLineValues.size(); i++)
+
+            for( size_t i = 0; i < apoFirstLineValues.size(); i++ )
             {
                 const char* pszFieldName = CPLSPrintf("Field%d", (int)i + 1);
                 OGRFieldType eType = GetOGRFieldType(apoFirstLineValues[i].c_str(),
@@ -650,7 +702,7 @@ void OGRODSDataSource::endElementTable( CPL_UNUSED /* in non-DEBUG*/ const char
             }
 
             OGRFeature* poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
-            for(i = 0; i < apoFirstLineValues.size(); i++)
+            for( size_t i = 0; i < apoFirstLineValues.size(); i++ )
             {
                 SetField(poFeature, static_cast<int>(i), apoFirstLineValues[i].c_str());
             }
@@ -660,19 +712,17 @@ void OGRODSDataSource::endElementTable( CPL_UNUSED /* in non-DEBUG*/ const char
 
         if (poCurLayer)
         {
-            OGRFeature* poFeature;
-
             if( CPLTestBool(CPLGetConfigOption("ODS_RESOLVE_FORMULAS", "YES")) )
             {
                 poCurLayer->ResetReading();
 
                 int nRow = 0;
-                poFeature = poCurLayer->GetNextFeature();
+                OGRFeature* poFeature = poCurLayer->GetNextFeature();
                 while (poFeature)
                 {
-                    for(int i=0;i<poFeature->GetFieldCount();i++)
+                    for( int i = 0; i < poFeature->GetFieldCount(); i++ )
                     {
-                        if (poFeature->IsFieldSet(i) &&
+                        if (poFeature->IsFieldSetAndNotNull(i) &&
                             poFeature->GetFieldDefnRef(i)->GetType() == OFTString)
                         {
                             const char* pszVal = poFeature->GetFieldAsString(i);
@@ -732,7 +782,7 @@ void OGRODSDataSource::startElementRow(const char *pszNameIn,
         if (pszFormula && STARTS_WITH(pszFormula, "of:="))
         {
             osFormula = pszFormula;
-            if (osValueType.size() == 0)
+            if (osValueType.empty())
                 osValueType = "formula";
         }
         else
@@ -761,12 +811,9 @@ void OGRODSDataSource::endElementRow( CPL_UNUSED /*in non-DEBUG*/ const char * p
     {
         CPLAssert(strcmp(pszNameIn, "table:table-row") == 0);
 
-        OGRFeature* poFeature;
-        size_t i;
-
         /* Remove blank columns at the right to defer type evaluation */
         /* until necessary */
-        i = apoCurLineTypes.size();
+        size_t i = apoCurLineTypes.size();
         while(i > 0)
         {
             i --;
@@ -776,12 +823,16 @@ void OGRODSDataSource::endElementRow( CPL_UNUSED /*in non-DEBUG*/ const char * p
                 apoCurLineTypes.resize(i);
             }
             else
+            {
                 break;
+            }
         }
 
         /* Do not add immediately empty rows. Wait until there is another non */
         /* empty row */
-        if (nCurLine >= 2 && apoCurLineTypes.size() == 0)
+        OGRFeature* poFeature = NULL;
+
+        if (nCurLine >= 2 && apoCurLineTypes.empty())
         {
             nEmptyRowsAccumulated += nRowsRepeated;
             return;
@@ -805,7 +856,7 @@ void OGRODSDataSource::endElementRow( CPL_UNUSED /*in non-DEBUG*/ const char * p
             apoFirstLineValues = apoCurLineValues;
 
     #if skip_leading_empty_rows
-            if (apoFirstLineTypes.size() == 0)
+            if (apoFirstLineTypes.empty())
             {
                 /* Skip leading empty rows */
                 apoFirstLineTypes.resize(0);
@@ -887,7 +938,7 @@ void OGRODSDataSource::endElementRow( CPL_UNUSED /*in non-DEBUG*/ const char * p
             {
                 for(i = 0; i < apoCurLineValues.size(); i++)
                 {
-                    if (apoCurLineValues[i].size())
+                    if (!apoCurLineValues[i].empty() )
                     {
                         const OGRFieldType eValType = GetOGRFieldType(
                             apoCurLineValues[i].c_str(),
@@ -963,7 +1014,7 @@ void OGRODSDataSource::endElementRow( CPL_UNUSED /*in non-DEBUG*/ const char * p
 void OGRODSDataSource::startElementCell(const char *pszNameIn,
                                         const char ** /*ppszAttr*/)
 {
-    if (osValue.size() == 0 && strcmp(pszNameIn, "text:p") == 0)
+    if (osValue.empty() && strcmp(pszNameIn, "text:p") == 0)
     {
         PushState(STATE_TEXTP);
     }
@@ -981,7 +1032,7 @@ void OGRODSDataSource::endElementCell( CPL_UNUSED /*in non-DEBUG*/ const char *
 
         for(int i = 0; i < nCellsRepeated; i++)
         {
-            if( osValue.size() )
+            if( !osValue.empty() )
                 apoCurLineValues.push_back(osValue);
             else
                 apoCurLineValues.push_back(osFormula);
@@ -1029,7 +1080,7 @@ void OGRODSDataSource::AnalyseFile()
     VSIFSeekL( fpContent, 0, SEEK_SET );
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -1212,7 +1263,7 @@ void OGRODSDataSource::AnalyseSettings()
     VSIFSeekL( fpSettings, 0, SEEK_SET );
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -1451,7 +1502,7 @@ static void WriteLayer(VSILFILE* fp, OGRLayer* poLayer)
         VSIFPrintfL(fp, "<table:table-row>\n");
         for( int j=0; j<poFeature->GetFieldCount(); j++ )
         {
-            if (poFeature->IsFieldSet(j))
+            if (poFeature->IsFieldSetAndNotNull(j))
             {
                 const OGRFieldType eType = poFDefn->GetFieldDefn(j)->GetType();
 
@@ -1479,13 +1530,13 @@ static void WriteLayer(VSILFILE* fp, OGRLayer* poLayer)
                 }
                 else if (eType == OFTDateTime)
                 {
-                    int nYear;
-                    int  nMonth;
-                    int  nDay;
-                    int  nHour;
-                    int  nMinute;
-                    int  nTZFlag;
-                    float fSecond;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMinute = 0;
+                    int nTZFlag = 0;
+                    float fSecond = 0.0f;
                     poFeature->GetFieldAsDateTime(
                         j, &nYear, &nMonth, &nDay,
                         &nHour, &nMinute, &fSecond, &nTZFlag );
@@ -1526,13 +1577,13 @@ static void WriteLayer(VSILFILE* fp, OGRLayer* poLayer)
                 }
                 else if (eType == OFTDate)
                 {
-                    int nYear;
-                    int  nMonth;
-                    int  nDay;
-                    int  nHour;
-                    int  nMinute;
-                    int  nSecond;
-                    int  nTZFlag;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMinute = 0;
+                    int nSecond = 0;
+                    int nTZFlag = 0;
                     poFeature->GetFieldAsDateTime(
                         j, &nYear, &nMonth, &nDay,
                         &nHour, &nMinute, &nSecond, &nTZFlag );
@@ -1547,13 +1598,13 @@ static void WriteLayer(VSILFILE* fp, OGRLayer* poLayer)
                 }
                 else if (eType == OFTTime)
                 {
-                    int nYear;
-                    int  nMonth;
-                    int  nDay;
-                    int  nHour;
-                    int  nMinute;
-                    int  nSecond;
-                    int  nTZFlag;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMinute = 0;
+                    int nSecond = 0;
+                    int nTZFlag = 0;
                     poFeature->GetFieldAsDateTime(
                         j, &nYear, &nMonth, &nDay,
                         &nHour, &nMinute, &nSecond, &nTZFlag );
@@ -1630,7 +1681,7 @@ void OGRODSDataSource::FlushCache()
     if (hZIP == NULL)
     {
         CPLError( CE_Failure, CPLE_FileIO,
-                  "Cannot create %s", pszName);
+                  "Cannot create %s: %s", pszName, VSIGetLastErrorMsg() );
         return;
     }
 
@@ -1925,7 +1976,7 @@ int ODSCellEvaluator::EvaluateRange(int nRow1, int nCol1, int nRow2, int nCol2,
 
         for(int nCol = nCol1; nCol <= nCol2; nCol++)
         {
-            if (!poFeature->IsFieldSet(nCol))
+            if (!poFeature->IsFieldSetAndNotNull(nCol))
             {
                 aoOutValues.push_back(ods_formula_node());
             }
@@ -1962,7 +2013,7 @@ int ODSCellEvaluator::EvaluateRange(int nRow1, int nCol1, int nRow2, int nCol2,
                     poLayer->SetNextByIndex(nRow);
                     poFeature = poLayer->GetNextFeatureWithoutFIDHack();
 
-                    if (!poFeature->IsFieldSet(nCol))
+                    if (!poFeature->IsFieldSetAndNotNull(nCol))
                     {
                         aoOutValues.push_back(ods_formula_node());
                     }
@@ -2031,7 +2082,7 @@ int ODSCellEvaluator::Evaluate(int nRow, int nCol)
     }
 
     OGRFeature* poFeature = poLayer->GetNextFeatureWithoutFIDHack();
-    if (poFeature->IsFieldSet(nCol) &&
+    if (poFeature->IsFieldSetAndNotNull(nCol) &&
         poFeature->GetFieldDefnRef(nCol)->GetType() == OFTString)
     {
         const char* pszVal = poFeature->GetFieldAsString(nCol);
diff --git a/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp b/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp
index a546b8f..e018f04 100644
--- a/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp
+++ b/ogr/ogrsf_frmts/ods/ogrodsdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrodsdriver.cpp 32967 2016-01-13 14:40:01Z goatbar $
  *
  * Project:  ODS Translator
  * Purpose:  Implements OGRODSDriver.
@@ -31,7 +30,7 @@
 #include "ogr_ods.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrodsdriver.cpp 32967 2016-01-13 14:40:01Z goatbar $");
+CPL_CVSID("$Id: ogrodsdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 using namespace OGRODS;
 
@@ -230,4 +229,3 @@ void RegisterOGRODS()
 
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/ods/testparser.cpp b/ogr/ogrsf_frmts/ods/testparser.cpp
index ae91a37..2f87483 100644
--- a/ogr/ogrsf_frmts/ods/testparser.cpp
+++ b/ogr/ogrsf_frmts/ods/testparser.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: testparser.cpp 27044 2014-03-16 23:41:27Z rouault $
  *
  * Component: Test ODS formula Engine
  * Purpose:
diff --git a/ogr/ogrsf_frmts/ogdi/drv_ogdi.html b/ogr/ogrsf_frmts/ogdi/drv_ogdi.html
index afaeaa4..fee0501 100644
--- a/ogr/ogrsf_frmts/ogdi/drv_ogdi.html
+++ b/ogr/ogrsf_frmts/ogdi/drv_ogdi.html
@@ -55,6 +55,18 @@ There is no update or creation support in the OGDI driver.<p>
 Raster layers cannot be accessed with this driver but can be accessed
 using the GDAL OGDI Raster driver.<p>
 
+<H3>Error handling</H3>
+
+<p>
+Starting with GDAL 2.2 and OGDI > 3.2.0beta2, if the OGDI_STOP_ON_ERROR environment
+variable is set to NO, some errors can be gracefully recovered by OGDI (in VPF driver).
+They will still be caught by GDAL and emitted as regular GDAL errors.
+</p>
+<p>
+Note: be aware that this is a work in progress. Not all recoverable errors can be recovered, and
+some errors might be recovered silently.
+</p>
+
 <H3>Examples</H3>
 
 Usage example 'ogrinfo':<BR>
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdi.h b/ogr/ogrsf_frmts/ogdi/ogrogdi.h
index 6c20c56..13e7765 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdi.h
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrogdi.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrogdi.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OGDI Bridge
  * Purpose:  Private definitions within the OGDI driver to implement
@@ -38,7 +38,6 @@ extern "C" {
 }
 #include "ogrsf_frmts.h"
 
-
 /************************************************************************/
 /*                             OGROGDILayer                             */
 /************************************************************************/
@@ -64,23 +63,23 @@ class OGROGDILayer : public OGRLayer
   public:
                         OGROGDILayer(OGROGDIDataSource *, const char *,
                                      ecs_Family);
-                        ~OGROGDILayer();
+                        virtual ~OGROGDILayer();
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
-    virtual OGRErr      SetAttributeFilter( const char *pszQuery );
+    virtual OGRErr      SetAttributeFilter( const char *pszQuery ) override;
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeature         *GetFeature( GIntBig nFeatureId );
+    OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return m_poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return m_poFeatureDefn; }
 
-    GIntBig             GetFeatureCount( int );
+    GIntBig             GetFeatureCount( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
   private:
     void                BuildFeatureDefn();
@@ -113,13 +112,13 @@ class OGROGDIDataSource : public OGRDataSource
                         OGROGDIDataSource();
                         ~OGROGDIDataSource();
 
-    int                 Open( const char *, int bTestOpen );
+    int                 Open( const char * );
 
-    const char          *GetName() { return m_pszFullName; }
-    int                 GetLayerCount() { return m_nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return m_pszFullName; }
+    int                 GetLayerCount() override { return m_nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     ecs_Region         *GetGlobalBounds() { return &m_sGlobalBounds; }
     OGRSpatialReference*GetSpatialRef() { return m_poSpatialRef; }
@@ -140,11 +139,10 @@ class OGROGDIDriver : public OGRSFDriver
   public:
                 ~OGROGDIDriver();
 
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
-    int         TestCapability( const char * );
+    int         TestCapability( const char * ) override;
 };
 
-
 #endif /* OGDOGDI_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp
index 5853378..d7e3bf2 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdidatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrogdidatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OGDI Bridge
  * Purpose:  Implements OGROGDIDataSource class.
@@ -29,26 +28,32 @@
  ****************************************************************************/
 
 #include "ogrogdi.h"
+
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrogdidatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrogdidatasource.cpp 36334 2016-11-20 15:42:08Z rouault $");
 
 /************************************************************************/
 /*                         OGROGDIDataSource()                          */
 /************************************************************************/
 
-OGROGDIDataSource::OGROGDIDataSource()
-
+OGROGDIDataSource::OGROGDIDataSource() :
+    m_papoLayers(NULL),
+    m_nLayers(0),
+    m_nClientID(-1),
+    m_poSpatialRef(NULL),
+    m_poCurrentLayer(NULL),
+    m_pszFullName(NULL),
+    m_bLaunderLayerNames(
+        CPLTestBool(CPLGetConfigOption("OGR_OGDI_LAUNDER_LAYER_NAMES", "NO")))
 {
-    m_pszFullName = NULL;
-    m_papoLayers = NULL;
-    m_nLayers = 0;
-    m_nClientID = -1;
-    m_poSpatialRef = NULL;
-    m_poCurrentLayer = NULL;
-    m_bLaunderLayerNames =
-            CPLTestBool(CPLGetConfigOption("OGR_OGDI_LAUNDER_LAYER_NAMES", "NO"));
+    m_sGlobalBounds.north = 0.0;
+    m_sGlobalBounds.south = 0.0;
+    m_sGlobalBounds.east = 0.0;
+    m_sGlobalBounds.west = 0.0;
+    m_sGlobalBounds.ns_res = 0.0;
+    m_sGlobalBounds.ew_res = 0.0;
 }
 
 /************************************************************************/
@@ -66,9 +71,7 @@ OGROGDIDataSource::~OGROGDIDataSource()
 
     if (m_nClientID != -1)
     {
-        ecs_Result *psResult;
-
-        psResult = cln_DestroyClient( m_nClientID );
+        ecs_Result *psResult = cln_DestroyClient( m_nClientID );
         ecs_CleanUp( psResult );
     }
 
@@ -80,13 +83,9 @@ OGROGDIDataSource::~OGROGDIDataSource()
 /*                                Open()                                */
 /************************************************************************/
 
-int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
+int OGROGDIDataSource::Open( const char * pszNewName )
 
 {
-    ecs_Result *psResult;
-    char *pszFamily=NULL, *pszLyrName=NULL;
-    char *pszWorkingName;
-
     CPLAssert( m_nLayers == 0 );
 
 /* -------------------------------------------------------------------- */
@@ -96,154 +95,171 @@ int OGROGDIDataSource::Open( const char * pszNewName, int bTestOpen )
 /*                                                                      */
 /*      Where <Family> is one of: Line, Area, Point, and Text           */
 /* -------------------------------------------------------------------- */
-        if( !STARTS_WITH_CI(pszNewName, "gltp:") )
-            return FALSE;
+    if( !STARTS_WITH_CI(pszNewName, "gltp:") )
+        return FALSE;
+
+    char *pszWorkingName = CPLStrdup( pszNewName );
 
-        pszWorkingName = CPLStrdup( pszNewName );
+    char *pszFamily = strrchr(pszWorkingName, ':');
 
-        pszFamily = strrchr(pszWorkingName, ':');
+    // Don't treat drive name colon as family separator.  It is assumed
+    // that drive names are on character long, and preceded by a
+    // forward or backward slash.
+    if( pszFamily < pszWorkingName+2
+        || pszFamily[-2] == '/'
+        || pszFamily[-2] == '\\' )
+        pszFamily = NULL;
+
+    char *pszLyrName = NULL;
+    if (pszFamily && pszFamily != pszWorkingName + 4)
+    {
+        *pszFamily = '\0';
+        pszFamily++;
 
-        // Don't treat drive name colon as family separator.  It is assumed
-        // that drive names are on character long, and preceded by a
-        // forward or backward slash.
-        if( pszFamily < pszWorkingName+2
-            || pszFamily[-2] == '/'
-            || pszFamily[-2] == '\\' )
-            pszFamily = NULL;
+        pszLyrName = strrchr(pszWorkingName, ':');
+        if (pszLyrName == pszWorkingName + 4)
+            pszLyrName = NULL;
 
-        if (pszFamily && pszFamily != pszWorkingName + 4)
+        if( pszLyrName != NULL )
         {
-            *pszFamily = '\0';
-            pszFamily++;
-
-            pszLyrName = strrchr(pszWorkingName, ':');
-            if (pszLyrName == pszWorkingName + 4)
-                pszLyrName = NULL;
-
-            if( pszLyrName != NULL )
-            {
-                *pszLyrName = '\0';
-                pszLyrName++;
-            }
+            *pszLyrName = '\0';
+            pszLyrName++;
         }
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Open the client interface.                                      */
 /* -------------------------------------------------------------------- */
-        psResult = cln_CreateClient(&m_nClientID, pszWorkingName);
-        CPLFree( pszWorkingName );
+    ecs_Result *psResult = cln_CreateClient(&m_nClientID, pszWorkingName);
 
-        if( ECSERROR( psResult ) )
-        {
-            if (!bTestOpen)
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "OGDI DataSource Open Failed: %s\n",
-                          psResult->message );
-            }
-            return FALSE;
-        }
+    if( ECSERROR( psResult ) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "OGDI DataSource Open Failed: %s\n",
+                  psResult->message ? psResult->message : "(no message string)");
+        CPLFree( pszWorkingName );
+        return FALSE;
+    }
 
-        m_pszFullName = CPLStrdup(pszNewName);
+    m_pszFullName = CPLStrdup(pszNewName);
 
 /* -------------------------------------------------------------------- */
 /*      Capture some information from the file.                         */
 /* -------------------------------------------------------------------- */
-        psResult = cln_GetGlobalBound( m_nClientID );
-        if( ECSERROR(psResult) )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s", psResult->message );
-            return FALSE;
-        }
+    psResult = cln_GetGlobalBound( m_nClientID );
+    if( ECSERROR(psResult) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "GetGlobalBound failed: %s",
+                  psResult->message ? psResult->message : "(no message string)");
+        CPLFree( pszWorkingName );
+        return FALSE;
+    }
 
-        m_sGlobalBounds = ECSREGION(psResult);
+    m_sGlobalBounds = ECSREGION(psResult);
 
-        psResult = cln_GetServerProjection(m_nClientID);
-        if( ECSERROR(psResult) )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s", psResult->message );
-            return FALSE;
-        }
+    psResult = cln_GetServerProjection(m_nClientID);
+    if( ECSERROR(psResult) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "GetServerProjection failed: %s",
+                  psResult->message ? psResult->message : "(no message string)");
+        CPLFree( pszWorkingName );
+        return FALSE;
+    }
 
-        m_poSpatialRef = new OGRSpatialReference;
+    m_poSpatialRef = new OGRSpatialReference;
 
-        if( m_poSpatialRef->importFromProj4( ECSTEXT(psResult) ) != OGRERR_NONE )
-        {
-            CPLError( CE_Warning, CPLE_NotSupported,
-                      "untranslatable PROJ.4 projection: %s\n",
-                      ECSTEXT(psResult) );
-            delete m_poSpatialRef;
-            m_poSpatialRef = NULL;
-        }
+    if( m_poSpatialRef->importFromProj4( ECSTEXT(psResult) ) != OGRERR_NONE )
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                  "untranslatable PROJ.4 projection: %s\n",
+                  ECSTEXT(psResult) ? ECSTEXT(psResult): "(no message string)" );
+        delete m_poSpatialRef;
+        m_poSpatialRef = NULL;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Select the global region.                                       */
 /* -------------------------------------------------------------------- */
-        psResult = cln_SelectRegion( m_nClientID, &m_sGlobalBounds );
-        if( ECSERROR(psResult) )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s", psResult->message );
-            return FALSE;
-        }
+    psResult = cln_SelectRegion( m_nClientID, &m_sGlobalBounds );
+    if( ECSERROR(psResult) )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "SelectRegion failed: %s",
+                  psResult->message ? psResult->message : "(no message string)");
+        CPLFree( pszWorkingName );
+        return FALSE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      If an explicit layer was selected, just create that layer.      */
 /* -------------------------------------------------------------------- */
-        m_poCurrentLayer = NULL;
+    m_poCurrentLayer = NULL;
 
-        if( pszLyrName != NULL )
+    if( pszLyrName != NULL )
+    {
+        ecs_Family  eFamily;
+
+        if (EQUAL(pszFamily, "Line"))
+            eFamily = Line;
+        else if (EQUAL(pszFamily, "Area"))
+            eFamily = Area;
+        else if (EQUAL(pszFamily, "Point"))
+            eFamily = Point;
+        else if (EQUAL(pszFamily, "Text"))
+            eFamily = Text;
+        else
         {
-            ecs_Family  eFamily;
-
-            if (EQUAL(pszFamily, "Line"))
-                eFamily = Line;
-            else if (EQUAL(pszFamily, "Area"))
-                eFamily = Area;
-            else if (EQUAL(pszFamily, "Point"))
-                eFamily = Point;
-            else if (EQUAL(pszFamily, "Text"))
-                eFamily = Text;
-            else
-            {
-                if (!bTestOpen)
-                {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Invalid or unsupported family name (%s) in URL %s\n",
-                              pszFamily, m_pszFullName);
-                }
-                return FALSE;
-            }
-
-            IAddLayer( pszLyrName, eFamily );
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Invalid or unsupported family name (%s) in URL %s\n",
+                      pszFamily, m_pszFullName);
+            CPLFree( pszWorkingName );
+            return FALSE;
         }
 
+        IAddLayer( pszLyrName, eFamily );
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Otherwise create a layer for every layer in the capabilities.   */
 /* -------------------------------------------------------------------- */
-        else
+    else
+    {
+        // Call cln_UpdateDictionary so as to be able to report errors
+        // since cln_GetLayerCapabilities() cannot do that
+        // Help in the case of DNC17/COA17A that has a missing env/fcs file
+        char* szEmpty = CPLStrdup("");
+        psResult = cln_UpdateDictionary( m_nClientID, szEmpty );
+        CPLFree(szEmpty);
+        if( ECSERROR(psResult) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "UpdateDictionary failed: %s",
+                      psResult->message ? psResult->message : "(no message string)");
+            CPLFree( pszWorkingName );
+            return FALSE;
+        }
+
+        const ecs_LayerCapabilities *psLayerCap = NULL;
+        for( int i = 0;
+             (psLayerCap = cln_GetLayerCapabilities(m_nClientID,i)) != NULL;
+             i++ )
         {
-            int         i;
-            const ecs_LayerCapabilities *psLayerCap;
-
-            for( i = 0;
-                (psLayerCap = cln_GetLayerCapabilities(m_nClientID,i)) != NULL;
-                 i++ )
-            {
-                if( psLayerCap->families[Point] )
-                    IAddLayer( psLayerCap->name, Point );
-                if( psLayerCap->families[Line] )
-                    IAddLayer( psLayerCap->name, Line );
-                if( psLayerCap->families[Area] )
-                    IAddLayer( psLayerCap->name, Area );
-                if( psLayerCap->families[Text] )
-                    IAddLayer( psLayerCap->name, Text );
-            }
+            if( psLayerCap->families[Point] )
+                IAddLayer( psLayerCap->name, Point );
+            if( psLayerCap->families[Line] )
+                IAddLayer( psLayerCap->name, Line );
+            if( psLayerCap->families[Area] )
+                IAddLayer( psLayerCap->name, Area );
+            if( psLayerCap->families[Text] )
+                IAddLayer( psLayerCap->name, Text );
         }
+    }
+
+    CPLFree( pszWorkingName );
 
-        return TRUE;
+    return TRUE;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp
index 6d864e7..c4d648d 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdidriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrogdidriver.cpp 33199 2016-01-29 15:48:41Z rouault $
  *
  * Project:  OGDI Bridge
  * Purpose:  Implements OGROGDIDriver class.
@@ -31,7 +30,7 @@
 #include "ogrogdi.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrogdidriver.cpp 33199 2016-01-29 15:48:41Z rouault $");
+CPL_CVSID("$Id: ogrogdidriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                           ~OGROGDIDriver()                           */
@@ -53,6 +52,19 @@ const char *OGROGDIDriver::GetName()
 }
 
 /************************************************************************/
+/*                         MyOGDIReportErrorFunction()                  */
+/************************************************************************/
+
+#if OGDI_RELEASEDATE >= 20160705
+static int MyOGDIReportErrorFunction(int errorcode, const char *error_message)
+{
+    CPLError(CE_Failure, CPLE_AppDefined, "OGDI error %d: %s",
+             errorcode, error_message);
+    return FALSE; // go on
+}
+#endif
+
+/************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
 
@@ -60,14 +72,18 @@ OGRDataSource *OGROGDIDriver::Open( const char * pszFilename,
                                      int bUpdate )
 
 {
-    OGROGDIDataSource   *poDS;
-
     if( !STARTS_WITH_CI(pszFilename, "gltp:") )
         return NULL;
 
-    poDS = new OGROGDIDataSource();
+#if OGDI_RELEASEDATE >= 20160705
+    // Available only in post OGDI 3.2.0beta2
+    // and only called if env variable OGDI_STOP_ON_ERROR is set to NO
+    ecs_SetReportErrorFunction( MyOGDIReportErrorFunction );
+#endif
+
+    OGROGDIDataSource *poDS = new OGROGDIDataSource();
 
-    if( !poDS->Open( pszFilename, TRUE ) )
+    if( !poDS->Open( pszFilename ) )
     {
         delete poDS;
         poDS = NULL;
@@ -84,7 +100,6 @@ OGRDataSource *OGROGDIDriver::Open( const char * pszFilename,
     return poDS;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -112,4 +127,3 @@ void RegisterOGROGDI()
 
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp b/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
index 5fd073c..c998360 100644
--- a/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
+++ b/ogr/ogrsf_frmts/ogdi/ogrogdilayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrogdilayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OGDI Bridge
  * Purpose:  Implements OGROGDILayer class.
@@ -28,59 +27,32 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************
- * http://bugzilla.remotesensing.org/show_bug.cgi?id=372
- *
- * Revision 1.6  2003/05/21 03:58:49  warmerda
- * expand tabs
- *
- * Revision 1.5  2001/07/18 04:55:16  warmerda
- * added CPL_CSVID
- *
- * Revision 1.4  2001/06/19 15:50:23  warmerda
- * added feature attribute query support
- *
- * Revision 1.3  2001/04/17 21:41:02  warmerda
- * Added use of cln_GetLayerCapabilities() to query list of available layers.
- * Restructured OGROGDIDataSource and OGROGDILayer classes somewhat to
- * avoid passing so much information in the layer creation call.  Added support
- * for preserving text on OGDI text features.
- *
- * Revision 1.2  2000/08/30 01:36:57  danmo
- * Added GetSpatialRef() support
- *
- * Revision 1.1  2000/08/24 04:16:19  danmo
- * Initial revision
- *
  */
 
 #include "ogrogdi.h"
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrogdilayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrogdilayer.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 /************************************************************************/
 /*                           OGROGDILayer()                            */
 /************************************************************************/
 
 OGROGDILayer::OGROGDILayer( OGROGDIDataSource *poODS,
-                            const char * pszName, ecs_Family eFamily )
-
-{
-    m_poODS = poODS;
-    m_nClientID = m_poODS->GetClientID();
-    m_eFamily = eFamily;
-
-    m_pszOGDILayerName = CPLStrdup(pszName);
-
-    m_sFilterBounds = *(m_poODS->GetGlobalBounds());
-
-    m_iNextShapeId = 0;
-    m_nTotalShapeCount = -1;
-    m_poFeatureDefn = NULL;
-
+                            const char * pszName, ecs_Family eFamily ) :
+    m_poODS(poODS),
+    m_nClientID(poODS->GetClientID()),
+    m_pszOGDILayerName(CPLStrdup(pszName)),
+    m_eFamily(eFamily),
+    m_poFeatureDefn(NULL),
     // Keep a reference on the SpatialRef (owned by the dataset).
-    m_poSpatialRef = m_poODS->GetSpatialRef();
+    m_poSpatialRef(m_poODS->GetSpatialRef()),
+    m_sFilterBounds(*(m_poODS->GetGlobalBounds())),
+    m_iNextShapeId(0),
+    m_nTotalShapeCount(-1),
+    m_nFilteredOutShapes(0)
+{
 
     // Select layer and feature family.
     ResetReading();
@@ -147,25 +119,25 @@ OGRErr OGROGDILayer::SetAttributeFilter( const char *pszQuery )
 void OGROGDILayer::ResetReading()
 
 {
-    ecs_Result *psResult;
     ecs_LayerSelection sSelectionLayer;
 
     sSelectionLayer.Select = m_pszOGDILayerName;
     sSelectionLayer.F = m_eFamily;
 
-    psResult = cln_SelectLayer(m_nClientID, &sSelectionLayer);
+    ecs_Result *psResult = cln_SelectLayer(m_nClientID, &sSelectionLayer);
     if( ECSERROR( psResult ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Access to layer '%s' Failed: %s\n",
-                  m_pszOGDILayerName, psResult->message );
+                  m_pszOGDILayerName,
+                  psResult->message ? psResult->message : "(no message string)" );
         return;
     }
 
     /* Reset spatial filter */
     if( m_poFilterGeom != NULL )
     {
-        OGREnvelope     oEnv;
+        OGREnvelope oEnv;
 
         m_poFilterGeom->getEnvelope(&oEnv);
 
@@ -178,7 +150,8 @@ void OGROGDILayer::ResetReading()
         if( ECSERROR(psResult) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s", psResult->message );
+                      "SelectRegion failed: %s",
+                      psResult->message ? psResult->message : "(no message string)" );
             return;
         }
     }
@@ -189,7 +162,8 @@ void OGROGDILayer::ResetReading()
         if( ECSERROR(psResult) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s", psResult->message );
+                      "SelectRegion failed: %s",
+                      psResult->message ? psResult->message : "(no message string)");
             return;
         }
     }
@@ -205,7 +179,6 @@ void OGROGDILayer::ResetReading()
 OGRFeature *OGROGDILayer::GetNextFeature()
 
 {
-    OGRFeature  *poFeature;
 
     /* Reset reading if we are not the current layer */
     /* WARNING : this does not allow interleaved reading of layers */
@@ -217,7 +190,7 @@ OGRFeature *OGROGDILayer::GetNextFeature()
 
     while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -243,23 +216,27 @@ OGRFeature *OGROGDILayer::GetNextFeature()
 
 OGRFeature *OGROGDILayer::GetNextRawFeature()
 {
-    ecs_Result  *psResult;
-    int         i;
-    OGRFeature  *poFeature;
-
 /* -------------------------------------------------------------------- */
 /*      Retrieve object from OGDI server and create new feature         */
 /* -------------------------------------------------------------------- */
-
-    psResult = cln_GetNextObject(m_nClientID);
+    ecs_Result *psResult = cln_GetNextObject(m_nClientID);
     if (! ECSSUCCESS(psResult))
     {
+        if( ECSERROR( psResult ) &&
+            (psResult->message == NULL ||
+             strstr(psResult->message, "End of selection") == NULL) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Access to next object of layer '%s' failed: %s\n",
+                      m_pszOGDILayerName,
+                      psResult->message ? psResult->message : "(no error string)" );
+        }
         // We probably reached EOF... keep track of shape count.
         m_nTotalShapeCount = m_iNextShapeId - m_nFilteredOutShapes;
         return NULL;
     }
 
-    poFeature = new OGRFeature(m_poFeatureDefn);
+    OGRFeature *poFeature = new OGRFeature(m_poFeatureDefn);
 
     poFeature->SetFID( m_iNextShapeId++ );
     m_nFeaturesRead++;
@@ -269,8 +246,8 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
     if (m_eFamily == Point)
     {
-        ecs_Point       *psPoint = &(ECSGEOM(psResult).point);
-        OGRPoint        *poOGRPoint = new OGRPoint(psPoint->c.x, psPoint->c.y);
+        ecs_Point *psPoint = &(ECSGEOM(psResult).point);
+        OGRPoint *poOGRPoint = new OGRPoint(psPoint->c.x, psPoint->c.y);
 
         poOGRPoint->assignSpatialReference(m_poSpatialRef);
         poFeature->SetGeometryDirectly(poOGRPoint);
@@ -282,7 +259,7 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
 
         poOGRLine->setNumPoints( psLine->c.c_len );
 
-        for( i=0; i < (int) psLine->c.c_len; i++ )
+        for( int i = 0; i < (int) psLine->c.c_len; i++ )
         {
             poOGRLine->setPoint(i, psLine->c.c_val[i].x, psLine->c.c_val[i].y);
         }
@@ -295,14 +272,14 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
         ecs_Area        *psArea = &(ECSGEOM(psResult).area);
         OGRPolygon      *poOGRPolygon = new OGRPolygon();
 
-        for(int iRing=0; iRing < (int) psArea->ring.ring_len; iRing++)
+        for( int iRing = 0; iRing < (int) psArea->ring.ring_len; iRing++ )
         {
             ecs_FeatureRing     *psRing = &(psArea->ring.ring_val[iRing]);
             OGRLinearRing       *poOGRRing = new OGRLinearRing();
 
             poOGRRing->setNumPoints( psRing->c.c_len );
 
-            for( i=0; i < (int) psRing->c.c_len; i++ )
+            for( int i = 0; i < (int) psRing->c.c_len; i++ )
             {
                 poOGRRing->setPoint(i, psRing->c.c_val[i].x,
                                     psRing->c.c_val[i].y);
@@ -329,7 +306,7 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
     }
     else
     {
-        CPLAssert(FALSE);
+        CPLAssert(false);
     }
 
 /* -------------------------------------------------------------------- */
@@ -339,9 +316,8 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
 
     for( int iField = 0; iField < m_poFeatureDefn->GetFieldCount(); iField++ )
     {
-        char        *pszFieldStart;
-        int         nNameLen;
-        char        chSavedChar;
+        char *pszFieldStart = NULL;
+        int nNameLen = 0;
 
         /* parse out the next attribute value */
         if( !ecs_FindElement( pszAttrList, &pszFieldStart, &pszAttrList,
@@ -366,7 +342,7 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
         /* zero terminate the single field value, but save the          */
         /* character we overwrote, so we can restore it when done.      */
 
-        chSavedChar = pszFieldStart[nNameLen];
+        char chSavedChar = pszFieldStart[nNameLen];
         pszFieldStart[nNameLen] = '\0';
 
         /* OGR takes care of all field type conversions for us! */
@@ -394,7 +370,6 @@ OGRFeature *OGROGDILayer::GetNextRawFeature()
 OGRFeature *OGROGDILayer::GetFeature( GIntBig nFeatureId )
 
 {
-    ecs_Result  *psResult;
 
     if (m_nTotalShapeCount != -1 && nFeatureId > m_nTotalShapeCount)
         return NULL;
@@ -416,7 +391,7 @@ OGRFeature *OGROGDILayer::GetFeature( GIntBig nFeatureId )
 
     while(m_iNextShapeId != nFeatureId)
     {
-        psResult = cln_GetNextObject(m_nClientID);
+        ecs_Result  *psResult = cln_GetNextObject(m_nClientID);
         if (ECSSUCCESS(psResult))
             m_iNextShapeId++;
         else
@@ -492,8 +467,6 @@ int OGROGDILayer::TestCapability( const char * pszCap )
         return FALSE;
 }
 
-
-
 /************************************************************************/
 /*                          BuildFeatureDefn()                          */
 /*                                                                      */
@@ -502,17 +475,14 @@ int OGROGDILayer::TestCapability( const char * pszCap )
 
 void OGROGDILayer::BuildFeatureDefn()
 {
-    ecs_Result  *psResult;
-    ecs_ObjAttributeFormat *oaf;
-    int         i, numFields;
-    const char  *pszGeomName;
-    OGRwkbGeometryType eLayerGeomType;
+    const char  *pszGeomName = NULL;
+    OGRwkbGeometryType eLayerGeomType = wkbUnknown;
 
 /* -------------------------------------------------------------------- */
 /*      Feature Defn name will be "<OGDILyrName>_<FeatureFamily>"       */
 /* -------------------------------------------------------------------- */
 
-    switch(m_eFamily)
+    switch( m_eFamily )
     {
       case Point:
         pszGeomName = "point";
@@ -536,7 +506,7 @@ void OGROGDILayer::BuildFeatureDefn()
         break;
     }
 
-    char* pszFeatureDefnName;
+    char* pszFeatureDefnName = NULL;
     if (m_poODS->LaunderLayerNames())
     {
         pszFeatureDefnName = CPLStrdup(m_pszOGDILayerName);
@@ -564,19 +534,20 @@ void OGROGDILayer::BuildFeatureDefn()
 /* -------------------------------------------------------------------- */
 /*      Fetch schema from OGDI server and map to OGR types              */
 /* -------------------------------------------------------------------- */
-    psResult = cln_GetAttributesFormat( m_nClientID );
+    ecs_Result  *psResult = cln_GetAttributesFormat( m_nClientID );
     if( ECSERROR( psResult ) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "ECSERROR: %s\n", psResult->message);
+                 "ECSERROR: %s\n",
+                 psResult->message ? psResult->message : "(no message string)");
         return;
     }
 
-    oaf = &(ECSRESULT(psResult).oaf);
-    numFields = oaf->oa.oa_len;
-    for( i = 0; i < numFields; i++ )
+    ecs_ObjAttributeFormat *oaf = &(ECSRESULT(psResult).oaf);
+    const int numFields = oaf->oa.oa_len;
+    for( int i = 0; i < numFields; i++ )
     {
-        OGRFieldDefn    oField("", OFTInteger);
+        OGRFieldDefn oField("", OFTInteger);
 
         oField.SetName( oaf->oa.oa_val[i].name );
         oField.SetPrecision( 0 );
@@ -621,7 +592,6 @@ void OGROGDILayer::BuildFeatureDefn()
             else
                 oField.SetWidth( 64 );
             break;
-
         }
 
         m_poFeatureDefn->AddFieldDefn( &oField );
diff --git a/ogr/ogrsf_frmts/ogr_attrind.h b/ogr/ogrsf_frmts/ogr_attrind.h
index 593b343..0478842 100644
--- a/ogr/ogrsf_frmts/ogr_attrind.h
+++ b/ogr/ogrsf_frmts/ogr_attrind.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_attrind.h 32177 2015-12-14 07:25:30Z goatbar $
+ * $Id: ogr_attrind.h 34921 2016-08-04 22:26:31Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to generic implementation of attribute indexing.
@@ -32,6 +32,8 @@
 
 #include "ogrsf_frmts.h"
 
+//! @cond Doxygen_Suppress
+
 /************************************************************************/
 /*                             OGRAttrIndex                             */
 /*                                                                      */
@@ -88,6 +90,7 @@ public:
 
 OGRLayerAttrIndex CPL_DLL *OGRCreateDefaultLayerIndex();
 
+//! @endcond
 
 #endif /* ndef OGR_ATTRIND_H_INCLUDED */
 
diff --git a/ogr/ogrsf_frmts/ogr_formats.html b/ogr/ogrsf_frmts/ogr_formats.html
index e0d1fcd..b621203 100644
--- a/ogr/ogrsf_frmts/ogr_formats.html
+++ b/ogr/ogrsf_frmts/ogr_formats.html
@@ -66,6 +66,13 @@
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_cad.html">AutoCAD DWG</a>
+</td><td> CAD
+</td><td> No
+</td><td> Yes
+</td><td> Yes (internal libopencad provided)
+</td></tr>
+
 <tr><td> <a href="drv_dwg.html">AutoCAD DWG</a>
 </td><td> DWG
 </td><td> No
@@ -235,6 +242,13 @@
 </td><td> Yes (read support needs Xerces or libexpat)
 </td></tr>
 
+<tr><td> <a href="drv_gmlas.html">GMLAS</a>
+</td><td> GMLAS
+</td><td> Yes
+</td><td> Yes
+</td><td> Yes (requires Xerces)
+</td></tr>
+
 <tr><td> <a href="drv_gmt.html">GMT</a>
 </td><td> GMT
 </td><td> Yes
@@ -333,13 +347,20 @@
 </td><td> Yes
 </td></tr>
 
-<tr><td> <a href="drv_dgn.html">Microstation DGN</a>
+<tr><td> <a href="drv_dgn.html">Microstation DGN v7</a>
 </td><td> DGN
 </td><td> Yes
 </td><td> No
 </td><td> Yes
 </td></tr>
 
+<tr><td> <a href="drv_dgn.html">Microstation DGN v8</a>
+</td><td> DGNv8
+</td><td> Yes
+</td><td> No
+</td><td> No, needs Open Design Alliance Teigha library
+</td></tr>
+
 <tr><td> <a href="drv_mdb.html">Access MDB (PGeo and Geomedia capable)</a>
 </td><td> MDB
 </td><td> No
diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.dox b/ogr/ogrsf_frmts/ogrsf_frmts.dox
index 6f8d05c..a533b3d 100644
--- a/ogr/ogrsf_frmts/ogrsf_frmts.dox
+++ b/ogr/ogrsf_frmts/ogrsf_frmts.dox
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsf_frmts.dox 32114 2015-12-10 22:03:51Z rouault $
+ * $Id: ogrsf_frmts.dox 37831 2017-03-23 18:51:49Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Documentation for ogrsf_frmts.h classes.
@@ -32,7 +32,7 @@
 /************************************************************************/
 
 /**
- 
+
   \fn OGRDataSourceH OGROpen( const char *pszName, int bUpdate,
                         OGRSFDriverH *pahDriverList );
 
@@ -56,9 +56,9 @@
   @deprecated Use GDALOpenEx() in GDAL 2.0
 
   @param pszName the name of the file, or data source to open.
-  @param bUpdate FALSE for read-only access (the default) or TRUE for 
+  @param bUpdate FALSE for read-only access (the default) or TRUE for
          read-write access.
-  @param pahDriverList if non-NULL, this argument will be updated with a 
+  @param pahDriverList if non-NULL, this argument will be updated with a
          pointer to the driver which was used to open the data source.
 
   @return NULL on error or if the pass name is not supported by this driver,
@@ -84,6 +84,58 @@
 
 */
 
+
+/**
+
+  \fn OGRDataSourceH OGROpenShared( const char *pszName, int bUpdate,
+                        OGRSFDriverH *pahDriverList );
+
+  \brief Open a file / data source with one of the registered drivers if not
+  already opened, or increment reference count of already opened data source
+  previously opened with OGROpenShared()
+
+  This function loops through all the drivers registered with the driver
+  manager trying each until one succeeds with the given data source.
+
+  If this function fails, CPLGetLastErrorMsg() can be used to check if there
+  is an error message explaining why.
+
+  NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned handle to
+  OGRDataSource*. If a C++ object is needed, the handle should be cast to GDALDataset*.
+  Similarly, the returned OGRSFDriverH handle should be cast to GDALDriver*, and
+  *NOT* OGRSFDriver*.
+
+  @deprecated Use GDALOpenEx() in GDAL 2.0
+
+  @param pszName the name of the file, or data source to open.
+  @param bUpdate FALSE for read-only access (the default) or TRUE for
+         read-write access.
+  @param pahDriverList if non-NULL, this argument will be updated with a
+         pointer to the driver which was used to open the data source.
+
+  @return NULL on error or if the pass name is not supported by this driver,
+  otherwise an handle to a GDALDataset.  This GDALDataset should be
+  closed by deleting the object when it is no longer needed.
+
+  <b>Example:</b>
+
+  <pre>
+    OGRDataSourceH  hDS;
+    OGRSFDriverH        *pahDriver;
+
+    hDS = OGROpenShared( "polygon.shp", 0, pahDriver );
+    if( hDS == NULL )
+    {
+        return;
+    }
+
+    ... use the data source ...
+
+    OGRReleaseDataSource( hDS );
+  </pre>
+
+*/
+
 /**
 
   \fn int OGRGetDriverCount();
@@ -97,7 +149,7 @@
 */
 
 /**
- 
+
   \fn OGRSFDriverH OGRGetDriver( int iDriver );
 
   \brief Fetch the indicated driver.
@@ -141,7 +193,7 @@
 /*                             OGRSFDriver                              */
 /************************************************************************/
 
-/** 
+/**
 
   \fn const char *OGR_Dr_GetName( OGRSFDriverH hDriver );
 
@@ -154,15 +206,15 @@
 
   @param hDriver handle to the driver to get the name from.
   @return driver name.  This is an internal string and should not be modified
-  or freed. 
+  or freed.
 */
 
 /**
 
-  \fn OGRDataSourceH OGR_Dr_Open( OGRSFDriverH hDriver, const char *pszName, 
+  \fn OGRDataSourceH OGR_Dr_Open( OGRSFDriverH hDriver, const char *pszName,
                             int bUpdate );
 
-  \brief Attempt to open file with this driver. 
+  \brief Attempt to open file with this driver.
 
   NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned handle to
   OGRDataSource*. If a C++ object is needed, the handle should be cast to GDALDataset*.
@@ -206,16 +258,16 @@
 
  @return TRUE if capability available otherwise FALSE.
 
-*/ 
+*/
 
 /**
- \fn OGRErr OGR_Dr_DeleteDataSource( OGRSFDriverH hDriver, 
+ \fn OGRErr OGR_Dr_DeleteDataSource( OGRSFDriverH hDriver,
                                 const char *pszDataSource )
 
  \brief Delete a datasource.
 
  Delete (from the disk, in the database, ...) the named datasource.
- Normally it would be safest if the datasource was not open at the time. 
+ Normally it would be safest if the datasource was not open at the time.
 
  Whether this is a supported operation on this driver case be tested
  using TestCapability() on ODrCDeleteDataSource.
@@ -225,24 +277,24 @@
  @param hDriver handle to the driver on which data source deletion is
 based.
 
- @param pszDataSource the name of the datasource to delete. 
+ @param pszDataSource the name of the datasource to delete.
 
  @return OGRERR_NONE on success, and OGRERR_UNSUPPORTED_OPERATION if this
- is not supported by this driver. 
+ is not supported by this driver.
 
 */
 
-/** 
+/**
 
   \fn OGRDataSourceH OGR_Dr_CreateDataSource( OGRSFDriverH hDriver,
-                                        const char *pszName, 
+                                        const char *pszName,
                                         char ** papszOptions )
 
  \brief This function attempts to create a new data source based on the passed driver.
 
  The papszOptions argument can be used to control driver specific
  creation options.  These options are normally documented in the format
- specific documentation. 
+ specific documentation.
 
  It is important to call OGR_DS_Destroy() when the datasource is no longer
  used to ensure that all data has been properly flushed to disk.
@@ -253,17 +305,17 @@ based.
 based.
  @param pszName the name for the new data source. UTF-8 encoded.
  @param papszOptions a StringList of name=value options.  Options are driver
-specific, and driver information can be found at the following url:  
-http://www.gdal.org/ogr_formats.html 
+specific, and driver information can be found at the following url:
+http://www.gdal.org/ogr_formats.html
 
- @return NULL is returned on failure, or a new OGRDataSource handle on 
-success. 
+ @return NULL is returned on failure, or a new OGRDataSource handle on
+success.
 */
 
 /**
 
-   \fn OGRDataSourceH OGR_Dr_CopyDataSource( OGRSFDriverH hDriver, 
-                                      OGRDataSourceH hSrcDS, 
+   \fn OGRDataSourceH OGR_Dr_CopyDataSource( OGRSFDriverH hDriver,
+                                      OGRDataSourceH hSrcDS,
                                       const char *pszNewName,
                                       char **papszOptions )
 
@@ -279,11 +331,11 @@ based.
  @param hSrcDS source datasource
  @param pszNewName the name for the new data source.
  @param papszOptions a StringList of name=value options.  Options are driver
-specific, and driver information can be found at the following url:  
-http://www.gdal.org/ogr_formats.html 
+specific, and driver information can be found at the following url:
+http://www.gdal.org/ogr_formats.html
 
- @return NULL is returned on failure, or a new OGRDataSource handle on 
-success. 
+ @return NULL is returned on failure, or a new OGRDataSource handle on
+success.
 */
 
 /************************************************************************/
@@ -302,7 +354,7 @@ success.
   @param hDataSource handle to allocated datasource object.
 */
 
-/** 
+/**
  \fn const char *OGR_DS_GetName( OGRDataSourceH hDS );
 
  \brief Returns the name of the data source.
@@ -310,7 +362,7 @@ success.
   This string should be sufficient to
  open the data source if passed to the same OGRSFDriver that this data
  source was opened with, but it need not be exactly the same string that
- was used to open the data source.  Normally this is a filename. 
+ was used to open the data source.  Normally this is a filename.
 
  @deprecated Use GDALGetDescription() in GDAL 2.0
 
@@ -338,7 +390,7 @@ success.
 
  \brief Fetch a layer by index.
 
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  OGRDataSource and should not be deleted by the application.
 
  @deprecated Use GDALDatasetGetLayer() in GDAL 2.0
@@ -352,12 +404,12 @@ success.
 */
 
 /**
- \fn OGRLayerH OGR_DS_GetLayerByName(OGRDataSourceH hDS, 
+ \fn OGRLayerH OGR_DS_GetLayerByName(OGRDataSourceH hDS,
                                      const char *pszLayerName );
 
  \brief Fetch a layer by name.
 
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  OGRDataSource and should not be deleted by the application.
 
  @deprecated Use GDALDatasetGetLayerByName() in GDAL 2.0
@@ -371,7 +423,7 @@ success.
 */
 
 /**
- \fn OGRLayerH OGR_DS_CopyLayer( OGRDataSourceH hDS, 
+ \fn OGRLayerH OGR_DS_CopyLayer( OGRDataSourceH hDS,
                             OGRLayerH hSrcLayer, const char *pszNewName,
                             char **papszOptions )
 
@@ -406,7 +458,7 @@ success.
  @deprecated Use GDALDatasetDeleteLayer() in GDAL 2.0
 
  @param hDS handle to the datasource
- @param iLayer the index of the layer to delete. 
+ @param iLayer the index of the layer to delete.
 
  @return OGRERR_NONE on success, or OGRERR_UNSUPPORTED_OPERATION if deleting
  layers is not supported for this datasource.
@@ -414,19 +466,19 @@ success.
 */
 
 /**
- \fn OGRLayerH OGR_DS_ExecuteSQL( OGRDataSourceH hDS, 
+ \fn OGRLayerH OGR_DS_ExecuteSQL( OGRDataSourceH hDS,
                              const char *pszSQLCommand,
                              OGRGeometryH hSpatialFilter,
                              const char *pszDialect );
 
- \brief Execute an SQL statement against the data store. 
+ \brief Execute an SQL statement against the data store.
 
  The result of an SQL query is either NULL for statements that are in error,
  or that have no results set, or an OGRLayer handle representing a results
  set from the query.  Note that this OGRLayer is in addition to the layers
- in the data store and must be destroyed with 
+ in the data store and must be destroyed with
  OGR_DS_ReleaseResultSet() before the data source is closed
- (destroyed).  
+ (destroyed).
 
  For more information on the SQL dialect supported internally by OGR
  review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (i.e.
@@ -438,14 +490,14 @@ success.
  @deprecated Use GDALDatasetExecuteSQL() in GDAL 2.0
 
  @param hDS handle to the data source on which the SQL query is executed.
- @param pszSQLCommand the SQL statement to execute. 
+ @param pszSQLCommand the SQL statement to execute.
  @param hSpatialFilter handle to a geometry which represents a spatial filter. Can be NULL.
  @param pszDialect allows control of the statement dialect. If set to NULL, the
 OGR SQL engine will be used, except for RDBMS drivers that will use their dedicated SQL engine,
 unless OGRSQL is explicitly passed as the dialect. Starting with OGR 1.10, the SQLITE dialect
 can also be used.
 
- @return an handle to a OGRLayer containing the results of the query.  
+ @return an handle to a OGRLayer containing the results of the query.
  Deallocate with OGR_DS_ReleaseResultSet().
 
 */
@@ -457,17 +509,17 @@ can also be used.
  \brief Release results of OGR_DS_ExecuteSQL().
 
  This function should only be used to deallocate OGRLayers resulting from
- an OGR_DS_ExecuteSQL() call on the same OGRDataSource.  
- Failure to deallocate a results set before destroying the OGRDataSource 
- may cause errors. 
+ an OGR_DS_ExecuteSQL() call on the same OGRDataSource.
+ Failure to deallocate a results set before destroying the OGRDataSource
+ may cause errors.
 
  @deprecated Use GDALDatasetReleaseResultSet() in GDAL 2.0
 
- @param hDS an handle to the data source on which was executed an 
+ @param hDS an handle to the data source on which was executed an
  SQL query.
  @param hLayer handle to the result of a previous OGR_DS_ExecuteSQL() call.
 
-*/ 
+*/
 
 /**
  \fn int OGR_DS_TestCapability( OGRDataSourceH hDS, const char *pszCapability );
@@ -475,7 +527,7 @@ can also be used.
  \brief Test if capability is available.
 
  One of the following data source capability names can be passed into this
- function, and a TRUE or FALSE value will be returned indicating whether 
+ function, and a TRUE or FALSE value will be returned indicating whether
  or not the capability is available for this object.
 
  <ul>
@@ -498,10 +550,10 @@ can also be used.
 
  @return TRUE if capability available otherwise FALSE.
 
-*/ 
+*/
 
 /**
- \fn OGRLayerH OGR_DS_CreateLayer( OGRDataSourceH hDS, 
+ \fn OGRLayerH OGR_DS_CreateLayer( OGRDataSourceH hDS,
                               const char * pszName,
                               OGRSpatialReferenceH hSpatialRef,
                               OGRwkbGeometryType eType,
@@ -511,27 +563,27 @@ can also be used.
 
 The papszOptions argument
 can be used to control driver specific creation options.  These options are
-normally documented in the format specific documentation. 
+normally documented in the format specific documentation.
 
 @deprecated Use GDALDatasetCreateLayer() in GDAL 2.0
 
  @param hDS The dataset handle.
- @param pszName the name for the new layer.  This should ideally not 
+ @param pszName the name for the new layer.  This should ideally not
 match any existing layer on the datasource.
  @param hSpatialRef handle to the coordinate system to use for the new layer,
-or NULL if no coordinate system is available. 
+or NULL if no coordinate system is available.
  @param eType the geometry type for the layer.  Use wkbUnknown if there
-are no constraints on the types geometry to be written. 
+are no constraints on the types geometry to be written.
  @param papszOptions a StringList of name=value options.  Options are driver
-specific, and driver information can be found at the following url:  
-http://www.gdal.org/ogr_formats.html 
+specific, and driver information can be found at the following url:
+http://www.gdal.org/ogr_formats.html
 
- @return NULL is returned on failure, or a new OGRLayer handle on success. 
+ @return NULL is returned on failure, or a new OGRLayer handle on success.
 
 <b>Example:</b>
 
 \code
-#include "ogrsf_frmts.h" 
+#include "ogrsf_frmts.h"
 #include "cpl_string.h"
 
 ...
@@ -552,7 +604,7 @@ http://www.gdal.org/ogr_formats.html
         if( hLayer == NULL )
         {
             ...
-        }        
+        }
 \endcode
 */
 
@@ -563,19 +615,19 @@ http://www.gdal.org/ogr_formats.html
 
 Internally this actually calls
 the OGRSFDriverRegistrar::ReleaseDataSource() method.  This method is
-essentially a convenient alias. 
+essentially a convenient alias.
 
 @deprecated Use GDALClose() in GDAL 2.0
 
 @param hDS handle to the data source to release
 
- at return OGRERR_NONE on success or an error code. 
+ at return OGRERR_NONE on success or an error code.
 */
 
 /**
  \fn OGRSFDriverH OGR_DS_GetDriver( OGRDataSourceH hDS );
 
-\brief Returns the driver that the dataset was opened with. 
+\brief Returns the driver that the dataset was opened with.
 
 NOTE: Starting with GDAL 2.0, it is *NOT* safe to cast the returned handle to
 OGRSFDriver*. If a C++ object is needed, the handle should be cast to GDALDriver*.
@@ -707,11 +759,11 @@ by the OGRSFDriverManager.
  features associated with an OGRLayer (more specifically an
  OGRFeatureDefn) be deleted before that layer/datasource is deleted.
 
- Only features matching the current spatial filter (set with 
- SetSpatialFilter()) will be returned.  
+ Only features matching the current spatial filter (set with
+ SetSpatialFilter()) will be returned.
 
  This method implements sequential access to the features of a layer.  The
- ResetReading() method can be used to start at the beginning again.  
+ ResetReading() method can be used to start at the beginning again.
 
  Features returned by GetNextFeature() may or may not be affected by
  concurrent modifications depending on drivers. A guaranteed way of seeing
@@ -724,7 +776,7 @@ by the OGRSFDriverManager.
 
  This method is the same as the C function OGR_L_GetNextFeature().
 
- @return a feature, or NULL if no more features are available. 
+ @return a feature, or NULL if no more features are available.
 
 */
 
@@ -739,11 +791,11 @@ by the OGRSFDriverManager.
  associated with an OGRLayer (more specifically an OGRFeatureDefn) be
  deleted before that layer/datasource is deleted.
 
- Only features matching the current spatial filter (set with 
- SetSpatialFilter()) will be returned.  
+ Only features matching the current spatial filter (set with
+ SetSpatialFilter()) will be returned.
 
  This function implements sequential access to the features of a layer.
- The OGR_L_ResetReading() function can be used to start at the beginning 
+ The OGR_L_ResetReading() function can be used to start at the beginning
  again.
 
  Features returned by OGR_GetNextFeature() may or may not be affected by
@@ -758,7 +810,7 @@ by the OGRSFDriverManager.
  This function is the same as the C++ method OGRLayer::GetNextFeature().
 
  @param hLayer handle to the layer from which feature are read.
- @return an handle to a feature, or NULL if no more features are available. 
+ @return an handle to a feature, or NULL if no more features are available.
 
 */
 
@@ -766,42 +818,42 @@ by the OGRSFDriverManager.
 
  \fn GIntBig OGRLayer::GetFeatureCount( int bForce = TRUE );
 
- \brief Fetch the feature count in this layer. 
+ \brief Fetch the feature count in this layer.
 
  Returns the number of features in the layer.  For dynamic databases the
  count may not be exact.  If bForce is FALSE, and it would be expensive
  to establish the feature count a value of -1 may be returned indicating
  that the count isn't know.  If bForce is TRUE some implementations will
- actually scan the entire layer once to count objects. 
+ actually scan the entire layer once to count objects.
 
- The returned count takes the spatial filter into account. 
+ The returned count takes the spatial filter into account.
 
  Note that some implementations of this method may alter the read cursor
  of the layer.
 
  This method is the same as the C function OGR_L_GetFeatureCount().
- 
+
  Note: since GDAL 2.0, this method returns a GIntBig (previously a int)
 
  @param bForce Flag indicating whether the count should be computed even
  if it is expensive.
 
- @return feature count, -1 if count not known. 
+ @return feature count, -1 if count not known.
 
 */
 
 /**
  \fn GIntBig OGR_L_GetFeatureCount( OGRLayerH hLayer, int bForce );
 
- \brief Fetch the feature count in this layer. 
+ \brief Fetch the feature count in this layer.
 
  Returns the number of features in the layer.  For dynamic databases the
  count may not be exact.  If bForce is FALSE, and it would be expensive
  to establish the feature count a value of -1 may be returned indicating
  that the count isn't know.  If bForce is TRUE some implementations will
- actually scan the entire layer once to count objects. 
+ actually scan the entire layer once to count objects.
 
- The returned count takes the spatial filter into account. 
+ The returned count takes the spatial filter into account.
 
  Note that some implementations of this method may alter the read cursor
  of the layer.
@@ -814,7 +866,7 @@ by the OGRSFDriverManager.
  @param bForce Flag indicating whether the count should be computed even
  if it is expensive.
 
- @return feature count, -1 if count not known. 
+ @return feature count, -1 if count not known.
 
 */
 
@@ -826,7 +878,7 @@ by the OGRSFDriverManager.
 
  Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
  and it would be expensive to establish the extent then OGRERR_FAILURE
- will be returned indicating that the extent isn't know.  If bForce is 
+ will be returned indicating that the extent isn't know.  If bForce is
  TRUE then some implementations will actually scan the entire layer once
  to compute the MBR of all the features in the layer.
 
@@ -846,7 +898,7 @@ by the OGRSFDriverManager.
  @param bForce Flag indicating whether the extent should be computed even
  if it is expensive.
 
- @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known. 
+ @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known.
 
 */
 
@@ -859,7 +911,7 @@ by the OGRSFDriverManager.
 
  Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
  and it would be expensive to establish the extent then OGRERR_FAILURE
- will be returned indicating that the extent isn't know.  If bForce is 
+ will be returned indicating that the extent isn't know.  If bForce is
  TRUE then some implementations will actually scan the entire layer once
  to compute the MBR of all the features in the layer.
 
@@ -880,7 +932,7 @@ by the OGRSFDriverManager.
  @param bForce Flag indicating whether the extent should be computed even
  if it is expensive.
 
- @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known. 
+ @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known.
 
 */
 
@@ -892,7 +944,7 @@ by the OGRSFDriverManager.
 
  Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
  and it would be expensive to establish the extent then OGRERR_FAILURE
- will be returned indicating that the extent isn't know.  If bForce is 
+ will be returned indicating that the extent isn't know.  If bForce is
  TRUE then some implementations will actually scan the entire layer once
  to compute the MBR of all the features in the layer.
 
@@ -917,7 +969,7 @@ by the OGRSFDriverManager.
  @param bForce Flag indicating whether the extent should be computed even
  if it is expensive.
 
- @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known. 
+ @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known.
 
 */
 
@@ -930,7 +982,7 @@ by the OGRSFDriverManager.
 
  Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
  and it would be expensive to establish the extent then OGRERR_FAILURE
- will be returned indicating that the extent isn't know.  If bForce is 
+ will be returned indicating that the extent isn't know.  If bForce is
  TRUE then some implementations will actually scan the entire layer once
  to compute the MBR of all the features in the layer.
 
@@ -952,64 +1004,64 @@ by the OGRSFDriverManager.
  @param bForce Flag indicating whether the extent should be computed even
  if it is expensive.
 
- @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known. 
+ @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known.
 
 */
 
-/** 
+/**
  \fn void OGRLayer::SetSpatialFilter( OGRGeometry * poFilter );
 
- \brief Set a new spatial filter. 
+ \brief Set a new spatial filter.
 
- This method set the geometry to be used as a spatial filter when 
+ This method set the geometry to be used as a spatial filter when
  fetching features via the GetNextFeature() method.  Only features that
- geometrically intersect the filter geometry will be returned.  
+ geometrically intersect the filter geometry will be returned.
 
  Currently this test is may be inaccurately implemented, but it is
  guaranteed that all features who's envelope (as returned by
  OGRGeometry::getEnvelope()) overlaps the envelope of the spatial filter
- will be returned.  This can result in more shapes being returned that 
- should strictly be the case. 
+ will be returned.  This can result in more shapes being returned that
+ should strictly be the case.
 
- This method makes an internal copy of the passed geometry.  The 
- passed geometry remains the responsibility of the caller, and may 
- be safely destroyed. 
+ This method makes an internal copy of the passed geometry.  The
+ passed geometry remains the responsibility of the caller, and may
+ be safely destroyed.
 
  For the time being the passed filter geometry should be in the same
  SRS as the layer (as returned by OGRLayer::GetSpatialRef()).  In the
- future this may be generalized. 
+ future this may be generalized.
 
  This method is the same as the C function OGR_L_SetSpatialFilter().
 
  @param poFilter the geometry to use as a filtering region.  NULL may
  be passed indicating that the current spatial filter should be cleared,
  but no new one instituted.
- 
+
  */
 
-/** 
+/**
  \fn void OGR_L_SetSpatialFilter( OGRLayerH hLayer, OGRGeometryH hGeom );
 
- \brief Set a new spatial filter. 
+ \brief Set a new spatial filter.
 
- This function set the geometry to be used as a spatial filter when 
- fetching features via the OGR_L_GetNextFeature() function.  Only 
- features that geometrically intersect the filter geometry will be 
- returned.  
+ This function set the geometry to be used as a spatial filter when
+ fetching features via the OGR_L_GetNextFeature() function.  Only
+ features that geometrically intersect the filter geometry will be
+ returned.
 
  Currently this test is may be inaccurately implemented, but it is
  guaranteed that all features who's envelope (as returned by
  OGR_G_GetEnvelope()) overlaps the envelope of the spatial filter
- will be returned.  This can result in more shapes being returned that 
- should strictly be the case. 
+ will be returned.  This can result in more shapes being returned that
+ should strictly be the case.
 
- This function makes an internal copy of the passed geometry.  The 
- passed geometry remains the responsibility of the caller, and may 
- be safely destroyed. 
+ This function makes an internal copy of the passed geometry.  The
+ passed geometry remains the responsibility of the caller, and may
+ be safely destroyed.
 
  For the time being the passed filter geometry should be in the same
  SRS as the layer (as returned by OGR_L_GetSpatialRef()).  In the
- future this may be generalized. 
+ future this may be generalized.
 
  This function is the same as the C++ method OGRLayer::SetSpatialFilter.
 
@@ -1017,27 +1069,27 @@ by the OGRSFDriverManager.
  @param hGeom handle to the geometry to use as a filtering region.  NULL may
  be passed indicating that the current spatial filter should be cleared,
  but no new one instituted.
- 
+
  */
 
-/** 
- \fn void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY, 
+/**
+ \fn void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
                                           double dfMaxX, double dfMaxY );
 
- \brief Set a new rectangular spatial filter. 
+ \brief Set a new rectangular spatial filter.
 
- This method set rectangle to be used as a spatial filter when 
+ This method set rectangle to be used as a spatial filter when
  fetching features via the GetNextFeature() method.  Only features that
- geometrically intersect the given rectangle will be returned.  
+ geometrically intersect the given rectangle will be returned.
 
  The x/y values should be in the same coordinate system as the layer as
- a whole (as returned by OGRLayer::GetSpatialRef()).   Internally this 
+ a whole (as returned by OGRLayer::GetSpatialRef()).   Internally this
  method is normally implemented as creating a 5 vertex closed rectangular
  polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
- a convenience. 
+ a convenience.
 
- The only way to clear a spatial filter set with this method is to 
- call OGRLayer::SetSpatialFilter(NULL). 
+ The only way to clear a spatial filter set with this method is to
+ call OGRLayer::SetSpatialFilter(NULL).
 
  This method is the same as the C function OGR_L_SetSpatialFilterRect().
 
@@ -1045,28 +1097,28 @@ by the OGRSFDriverManager.
  @param dfMinY the minimum Y coordinate for the rectangular region.
  @param dfMaxX the maximum X coordinate for the rectangular region.
  @param dfMaxY the maximum Y coordinate for the rectangular region.
- 
+
  */
 
-/** 
+/**
  \fn void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer,
-                                      double dfMinX, double dfMinY, 
+                                      double dfMinX, double dfMinY,
                                       double dfMaxX, double dfMaxY );
 
- \brief Set a new rectangular spatial filter. 
+ \brief Set a new rectangular spatial filter.
 
- This method set rectangle to be used as a spatial filter when 
+ This method set rectangle to be used as a spatial filter when
  fetching features via the OGR_L_GetNextFeature() method.  Only features that
- geometrically intersect the given rectangle will be returned.  
+ geometrically intersect the given rectangle will be returned.
 
  The x/y values should be in the same coordinate system as the layer as
- a whole (as returned by OGRLayer::GetSpatialRef()).   Internally this 
+ a whole (as returned by OGRLayer::GetSpatialRef()).   Internally this
  method is normally implemented as creating a 5 vertex closed rectangular
  polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
- a convenience. 
+ a convenience.
 
- The only way to clear a spatial filter set with this method is to 
- call OGRLayer::SetSpatialFilter(NULL). 
+ The only way to clear a spatial filter set with this method is to
+ call OGRLayer::SetSpatialFilter(NULL).
 
  This method is the same as the C++ method OGRLayer::SetSpatialFilterRect().
 
@@ -1075,28 +1127,28 @@ by the OGRSFDriverManager.
  @param dfMinY the minimum Y coordinate for the rectangular region.
  @param dfMaxX the maximum X coordinate for the rectangular region.
  @param dfMaxY the maximum Y coordinate for the rectangular region.
- 
+
  */
 
 
-/** 
+/**
  \fn void OGRLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poFilter );
 
- \brief Set a new spatial filter. 
+ \brief Set a new spatial filter.
 
- This method set the geometry to be used as a spatial filter when 
+ This method set the geometry to be used as a spatial filter when
  fetching features via the GetNextFeature() method.  Only features that
- geometrically intersect the filter geometry will be returned.  
+ geometrically intersect the filter geometry will be returned.
 
  Currently this test is may be inaccurately implemented, but it is
  guaranteed that all features who's envelope (as returned by
  OGRGeometry::getEnvelope()) overlaps the envelope of the spatial filter
- will be returned.  This can result in more shapes being returned that 
- should strictly be the case. 
+ will be returned.  This can result in more shapes being returned that
+ should strictly be the case.
 
- This method makes an internal copy of the passed geometry.  The 
- passed geometry remains the responsibility of the caller, and may 
- be safely destroyed. 
+ This method makes an internal copy of the passed geometry.  The
+ passed geometry remains the responsibility of the caller, and may
+ be safely destroyed.
 
  For the time being the passed filter geometry should be in the same
  SRS as the geometry field definition it corresponds to (as returned by
@@ -1119,28 +1171,28 @@ by the OGRSFDriverManager.
  but no new one instituted.
 
  @since GDAL 1.11
- 
+
  */
 
-/** 
+/**
  \fn void OGR_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField, OGRGeometryH hGeom );
 
- \brief Set a new spatial filter. 
+ \brief Set a new spatial filter.
 
- This function set the geometry to be used as a spatial filter when 
- fetching features via the OGR_L_GetNextFeature() function.  Only 
- features that geometrically intersect the filter geometry will be 
- returned.  
+ This function set the geometry to be used as a spatial filter when
+ fetching features via the OGR_L_GetNextFeature() function.  Only
+ features that geometrically intersect the filter geometry will be
+ returned.
 
  Currently this test is may be inaccurately implemented, but it is
  guaranteed that all features who's envelope (as returned by
  OGR_G_GetEnvelope()) overlaps the envelope of the spatial filter
- will be returned.  This can result in more shapes being returned that 
- should strictly be the case. 
+ will be returned.  This can result in more shapes being returned that
+ should strictly be the case.
 
- This function makes an internal copy of the passed geometry.  The 
- passed geometry remains the responsibility of the caller, and may 
- be safely destroyed. 
+ This function makes an internal copy of the passed geometry.  The
+ passed geometry remains the responsibility of the caller, and may
+ be safely destroyed.
 
  For the time being the passed filter geometry should be in the same
  SRS as the geometry field definition it corresponds to (as returned by
@@ -1160,29 +1212,29 @@ by the OGRSFDriverManager.
  but no new one instituted.
 
  @since GDAL 1.11
- 
+
  */
 
-/** 
- \fn void OGRLayer::SetSpatialFilterRect( int iGeomField, 
-                                          double dfMinX, double dfMinY, 
+/**
+ \fn void OGRLayer::SetSpatialFilterRect( int iGeomField,
+                                          double dfMinX, double dfMinY,
                                           double dfMaxX, double dfMaxY );
 
- \brief Set a new rectangular spatial filter. 
+ \brief Set a new rectangular spatial filter.
 
- This method set rectangle to be used as a spatial filter when 
+ This method set rectangle to be used as a spatial filter when
  fetching features via the GetNextFeature() method.  Only features that
- geometrically intersect the given rectangle will be returned.  
+ geometrically intersect the given rectangle will be returned.
 
  The x/y values should be in the same coordinate system as as the geometry
  field definition it corresponds to (as returned by
- GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpatialRef()). Internally this 
+ GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpatialRef()). Internally this
  method is normally implemented as creating a 5 vertex closed rectangular
  polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
- a convenience. 
+ a convenience.
 
- The only way to clear a spatial filter set with this method is to 
- call OGRLayer::SetSpatialFilter(NULL). 
+ The only way to clear a spatial filter set with this method is to
+ call OGRLayer::SetSpatialFilter(NULL).
 
  This method is the same as the C function OGR_L_SetSpatialFilterRectEx().
 
@@ -1192,31 +1244,31 @@ by the OGRSFDriverManager.
  @param dfMinY the minimum Y coordinate for the rectangular region.
  @param dfMaxX the maximum X coordinate for the rectangular region.
  @param dfMaxY the maximum Y coordinate for the rectangular region.
- 
+
  @since GDAL 1.11
  */
 
-/** 
+/**
  \fn void OGR_L_SetSpatialFilterRectEx( OGRLayerH hLayer,
-                                        int iGeomField, 
-                                        double dfMinX, double dfMinY, 
+                                        int iGeomField,
+                                        double dfMinX, double dfMinY,
                                         double dfMaxX, double dfMaxY );
 
- \brief Set a new rectangular spatial filter. 
+ \brief Set a new rectangular spatial filter.
 
- This method set rectangle to be used as a spatial filter when 
+ This method set rectangle to be used as a spatial filter when
  fetching features via the OGR_L_GetNextFeature() method.  Only features that
- geometrically intersect the given rectangle will be returned.  
+ geometrically intersect the given rectangle will be returned.
 
  The x/y values should be in the same coordinate system as as the geometry
  field definition it corresponds to (as returned by
- GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpatialRef()). Internally this 
+ GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpatialRef()). Internally this
  method is normally implemented as creating a 5 vertex closed rectangular
  polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
- a convenience. 
+ a convenience.
 
- The only way to clear a spatial filter set with this method is to 
- call OGRLayer::SetSpatialFilter(NULL). 
+ The only way to clear a spatial filter set with this method is to
+ call OGRLayer::SetSpatialFilter(NULL).
 
  This method is the same as the C++ method OGRLayer::SetSpatialFilterRect().
 
@@ -1227,7 +1279,7 @@ by the OGRSFDriverManager.
  @param dfMinY the minimum Y coordinate for the rectangular region.
  @param dfMaxX the maximum X coordinate for the rectangular region.
  @param dfMaxY the maximum Y coordinate for the rectangular region.
- 
+
  @since GDAL 1.11
  */
 
@@ -1235,70 +1287,70 @@ by the OGRSFDriverManager.
 /**
  \fn OGRGeometry *OGRLayer::GetSpatialFilter();
 
- \brief This method returns the current spatial filter for this layer. 
+ \brief This method returns the current spatial filter for this layer.
 
  The returned pointer is to an internally owned object, and should not
- be altered or deleted by the caller.  
+ be altered or deleted by the caller.
 
  This method is the same as the C function OGR_L_GetSpatialFilter().
 
  @return spatial filter geometry.
- 
+
  */
 
 
 /**
  \fn OGRGeometryH OGR_L_GetSpatialFilter( OGRLayerH hLayer );
 
- \brief This function returns the current spatial filter for this layer. 
+ \brief This function returns the current spatial filter for this layer.
 
  The returned pointer is to an internally owned object, and should not
- be altered or deleted by the caller.  
+ be altered or deleted by the caller.
 
  This function is the same as the C++ method OGRLayer::GetSpatialFilter().
 
  @param hLayer handle to the layer to get the spatial filter from.
  @return an handle to the spatial filter geometry.
- 
+
  */
 
-/** 
+/**
  \fn void OGRLayer::SetAttributeFilter( const char *pszQuery );
 
  \brief Set a new attribute query.
 
- This method sets the attribute query string to be used when 
+ This method sets the attribute query string to be used when
  fetching features via the GetNextFeature() method.  Only features for which
  the query evaluates as true will be returned.
 
  The query string should be in the format of an SQL WHERE clause.  For
  instance "population > 1000000 and population < 5000000" where population
- is an attribute in the layer.  The query format is normally a restricted 
- form of SQL  WHERE clause as described in the "WHERE" section of the 
- <a href="ogr_sql.html">OGR SQL</a> tutorial.  In some cases (RDBMS 
- backed drivers) the native capabilities of the database may be used to 
+ is an attribute in the layer.  The query format is normally a restricted
+ form of SQL  WHERE clause as described in the "WHERE" section of the
+ <a href="ogr_sql.html">OGR SQL</a> tutorial.  In some cases (RDBMS
+ backed drivers) the native capabilities of the database may be used to
  interpret the WHERE clause in which case the capabilities will be broader
  than those of OGR SQL.
 
  Note that installing a query string will generally result in resetting
- the current reading position (ala ResetReading()).  
+ the current reading position (ala ResetReading()).
 
  This method is the same as the C function OGR_L_SetAttributeFilter().
 
  @param pszQuery query in restricted SQL WHERE format, or NULL to clear the
  current query.
 
- @return OGRERR_NONE if successfully installed, or an error code if the 
- query expression is in error, or some other failure occurs. 
- 
+ @return OGRERR_NONE if successfully installed, or an error code if the
+ query expression is in error, or some other failure occurs.
+
  */
 
-/** 
+/**
  \fn OGRErr OGR_L_SetAttributeFilter(OGRLayerH hLayer, const char *pszQuery);
 
  \brief Set a new attribute query.
 
- This function sets the attribute query string to be used when 
+ This function sets the attribute query string to be used when
  fetching features via the OGR_L_GetNextFeature() function.
  Only features for which the query evaluates as true will be returned.
 
@@ -1311,7 +1363,7 @@ by the OGRSFDriverManager.
    http://ogdi.sourceforge.net/prop/6.2.CapabilitiesMetadata.html
 
  Note that installing a query string will generally result in resetting
- the current reading position (ala OGR_L_ResetReading()).  
+ the current reading position (ala OGR_L_ResetReading()).
 
  This function is the same as the C++ method OGRLayer::SetAttributeFilter().
 
@@ -1319,19 +1371,19 @@ by the OGRSFDriverManager.
  @param pszQuery query in restricted SQL WHERE format, or NULL to clear the
  current query.
 
- @return OGRERR_NONE if successfully installed, or an error code if the 
- query expression is in error, or some other failure occurs. 
- 
+ @return OGRERR_NONE if successfully installed, or an error code if the
+ query expression is in error, or some other failure occurs.
+
  */
 
-/** 
+/**
  \fn OGRFeatureDefn *OGRLayer::GetLayerDefn();
 
  \brief Fetch the schema information for this layer.
 
  The returned OGRFeatureDefn is owned by the OGRLayer, and should not be
  modified or freed by the application.  It encapsulates the attribute schema
- of the features of the layer. 
+ of the features of the layer.
 
  This method is the same as the C function OGR_L_GetLayerDefn().
 
@@ -1339,14 +1391,14 @@ by the OGRSFDriverManager.
 
 */
 
-/** 
+/**
  \fn OGRFeatureDefnH OGR_L_GetLayerDefn( OGRLayerH hLayer );
 
  \brief Fetch the schema information for this layer.
 
  The returned handle to the OGRFeatureDefn is owned by the OGRLayer,
  and should not be modified or freed by the application.  It encapsulates
- the attribute schema of the features of the layer. 
+ the attribute schema of the features of the layer.
 
  This function is the same as the C++ method OGRLayer::GetLayerDefn().
 
@@ -1367,7 +1419,7 @@ by the OGRSFDriverManager.
  If bExactMatch is set to FALSE and the field doesn't exists in the given form
  the driver might apply some changes to make it match, like those it might do
  if the layer was created (eg. like LAUNDER in the OCI driver).
- 
+
  This method is the same as the C++ method OGRLayer::FindFieldIndex().
 
  @return field index, or -1 if the field doesn't exist
@@ -1386,7 +1438,7 @@ by the OGRSFDriverManager.
  If bExactMatch is set to FALSE and the field doesn't exists in the given form
  the driver might apply some changes to make it match, like those it might do
  if the layer was created (eg. like LAUNDER in the OCI driver).
- 
+
  This method is the same as the C function OGR_L_FindFieldIndex().
 
  @return field index, or -1 if the field doesn't exist
@@ -1397,11 +1449,11 @@ by the OGRSFDriverManager.
 
  \fn OGRSpatialReference *OGRLayer::GetSpatialRef();
 
- \brief Fetch the spatial reference system for this layer. 
+ \brief Fetch the spatial reference system for this layer.
 
  The returned object is owned by the OGRLayer and should not be modified
  or freed by the application.
- 
+
  Starting with OGR 1.11, several geometry fields can be associated to a
  feature definition. Each geometry field can have its own spatial reference
  system, which is returned by OGRGeomFieldDefn::GetSpatialRef().
@@ -1419,10 +1471,10 @@ by the OGRSFDriverManager.
 
  \fn OGRSpatialReferenceH OGR_L_GetSpatialRef( OGRLayerH hLayer );
 
- \brief Fetch the spatial reference system for this layer. 
+ \brief Fetch the spatial reference system for this layer.
 
  The returned object is owned by the OGRLayer and should not be modified
- or freed by the application.  
+ or freed by the application.
 
  This function is the same as the C++ method OGRLayer::GetSpatialRef().
 
@@ -1443,24 +1495,24 @@ by the OGRSFDriverManager.
  in drivers should make sure that they do not take into account spatial or
  attribute filters).
 
- If this method returns a non-NULL feature, it is guaranteed that its  
+ If this method returns a non-NULL feature, it is guaranteed that its
  feature id (OGRFeature::GetFID()) will be the same as nFID.
 
  Use OGRLayer::TestCapability(OLCRandomRead) to establish if this layer
  supports efficient random access reading via GetFeature(); however, the
  call should always work if the feature exists as a fallback implementation
  just scans all the features in the layer looking for the desired feature.
- 
+
  Sequential reads (with GetNextFeature()) are generally considered interrupted
  by a GetFeature() call.
- 
+
  The returned feature should be free with OGRFeature::DestroyFeature().
 
  This method is the same as the C function OGR_L_GetFeature().
 
- @param nFID the feature id of the feature to read. 
+ @param nFID the feature id of the feature to read.
 
- @return a feature now owned by the caller, or NULL on failure. 
+ @return a feature now owned by the caller, or NULL on failure.
 
 */
 
@@ -1477,37 +1529,37 @@ by the OGRSFDriverManager.
  in drivers should make sure that they do not take into account spatial or
  attribute filters).
 
- If this function returns a non-NULL feature, it is guaranteed that its  
+ If this function returns a non-NULL feature, it is guaranteed that its
  feature id (OGR_F_GetFID()) will be the same as nFID.
 
  Use OGR_L_TestCapability(OLCRandomRead) to establish if this layer
- supports efficient random access reading via OGR_L_GetFeature(); however, 
- the call should always work if the feature exists as a fallback 
- implementation just scans all the features in the layer looking for the 
+ supports efficient random access reading via OGR_L_GetFeature(); however,
+ the call should always work if the feature exists as a fallback
+ implementation just scans all the features in the layer looking for the
  desired feature.
- 
- Sequential reads (with OGR_L_GetNextFeature()) are generally considered interrupted by a 
+
+ Sequential reads (with OGR_L_GetNextFeature()) are generally considered interrupted by a
  OGR_L_GetFeature() call.
- 
+
  The returned feature should be free with OGR_F_Destroy().
- 
+
  This function is the same as the C++ method OGRLayer::GetFeature( ).
 
  @param hLayer handle to the layer that owned the feature.
- @param nFeatureId the feature id of the feature to read. 
+ @param nFeatureId the feature id of the feature to read.
 
- @return an handle to a feature now owned by the caller, or NULL on failure. 
+ @return an handle to a feature now owned by the caller, or NULL on failure.
 
 */
 
 /**
- 
+
  \fn OGRErr OGRLayer::SetFeature( OGRFeature * poFeature );
 
  \brief Rewrite an existing feature.
 
  This method will write a feature to the layer, based on the feature id
- within the OGRFeature.   
+ within the OGRFeature.
 
  Use OGRLayer::TestCapability(OLCRandomWrite) to establish if this layer
  supports random access writing via SetFeature().
@@ -1525,7 +1577,7 @@ by the OGRSFDriverManager.
 */
 
 /**
- 
+
  \fn OGRErr OGRLayer::ISetFeature( OGRFeature * poFeature );
 
  \brief Rewrite an existing feature.
@@ -1534,7 +1586,7 @@ by the OGRSFDriverManager.
  use SetFeature() instead.
 
  This method will write a feature to the layer, based on the feature id
- within the OGRFeature.   
+ within the OGRFeature.
 
  @param poFeature the feature to write.
 
@@ -1545,13 +1597,13 @@ by the OGRSFDriverManager.
 */
 
 /**
- 
+
  \fn OGRErr OGR_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat );
 
  \brief Rewrite an existing feature.
 
  This function will write a feature to the layer, based on the feature id
- within the OGRFeature.   
+ within the OGRFeature.
 
  Use OGR_L_TestCapability(OLCRandomWrite) to establish if this layer
  supports random access writing via OGR_L_SetFeature().
@@ -1575,15 +1627,15 @@ by the OGRSFDriverManager.
  The passed feature is written to the layer as a new feature, rather than
  overwriting an existing one.  If the feature has a feature id other than
  OGRNullFID, then the native implementation may use that as the feature id
- of the new feature, but not necessarily.  Upon successful return the 
- passed feature will have been updated with the new feature id. 
+ of the new feature, but not necessarily.  Upon successful return the
+ passed feature will have been updated with the new feature id.
 
  Starting with GDAL 2.0, drivers should specialize the ICreateFeature() method,
  since CreateFeature() is no longer virtual.
 
  This method is the same as the C function OGR_L_CreateFeature().
 
- @param poFeature the feature to write to disk. 
+ @param poFeature the feature to write to disk.
 
  @return OGRERR_NONE on success.
 
@@ -1601,10 +1653,10 @@ by the OGRSFDriverManager.
  The passed feature is written to the layer as a new feature, rather than
  overwriting an existing one.  If the feature has a feature id other than
  OGRNullFID, then the native implementation may use that as the feature id
- of the new feature, but not necessarily.  Upon successful return the 
- passed feature will have been updated with the new feature id. 
+ of the new feature, but not necessarily.  Upon successful return the
+ passed feature will have been updated with the new feature id.
 
- @param poFeature the feature to write to disk. 
+ @param poFeature the feature to write to disk.
 
  @return OGRERR_NONE on success.
  @since GDAL 2.0
@@ -1620,13 +1672,13 @@ by the OGRSFDriverManager.
  The passed feature is written to the layer as a new feature, rather than
  overwriting an existing one.  If the feature has a feature id other than
  OGRNullFID, then the native implementation may use that as the feature id
- of the new feature, but not necessarily.  Upon successful return the 
- passed feature will have been updated with the new feature id. 
+ of the new feature, but not necessarily.  Upon successful return the
+ passed feature will have been updated with the new feature id.
 
  This function is the same as the C++ method OGRLayer::CreateFeature().
 
  @param hLayer handle to the layer to write the feature to.
- @param hFeat the handle of the feature to write to disk. 
+ @param hFeat the handle of the feature to write to disk.
 
  @return OGRERR_NONE on success.
 
@@ -1641,12 +1693,12 @@ by the OGRSFDriverManager.
  The feature with the indicated feature id is deleted from the layer if
  supported by the driver.  Most drivers do not support feature deletion,
  and will return OGRERR_UNSUPPORTED_OPERATION.  The TestCapability()
- layer method may be called with OLCDeleteFeature to check if the driver 
+ layer method may be called with OLCDeleteFeature to check if the driver
  supports feature deletion.
 
  This method is the same as the C function OGR_L_DeleteFeature().
 
- @param nFID the feature id to be deleted from the layer 
+ @param nFID the feature id to be deleted from the layer
 
  @return OGRERR_NONE if the operation works, otherwise an appropriate error
  code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
@@ -1662,13 +1714,13 @@ by the OGRSFDriverManager.
  The feature with the indicated feature id is deleted from the layer if
  supported by the driver.  Most drivers do not support feature deletion,
  and will return OGRERR_UNSUPPORTED_OPERATION.  The OGR_L_TestCapability()
- function may be called with OLCDeleteFeature to check if the driver 
+ function may be called with OLCDeleteFeature to check if the driver
  supports feature deletion.
 
  This method is the same as the C++ method OGRLayer::DeleteFeature().
 
  @param hLayer handle to the layer
- @param nFID the feature id to be deleted from the layer 
+ @param nFID the feature id to be deleted from the layer
 
  @return OGRERR_NONE if the operation works, otherwise an appropriate error
  code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
@@ -1683,53 +1735,53 @@ by the OGRSFDriverManager.
  \brief Test if this layer supported the named capability.
 
  The capability codes that can be tested are represented as strings, but
- \#defined constants exists to ensure correct spelling.  Specific layer 
+ \#defined constants exists to ensure correct spelling.  Specific layer
  types may implement class specific capabilities, but this can't generally
  be discovered by the caller. <p>
 
 <ul>
 
- <li> <b>OLCRandomRead</b> / "RandomRead": TRUE if the GetFeature() method 
+ <li> <b>OLCRandomRead</b> / "RandomRead": TRUE if the GetFeature() method
 is implemented in an optimized way for this layer, as opposed to the default
 implementation using ResetReading() and GetNextFeature() to find the requested
 feature id.<p>
 
- <li> <b>OLCSequentialWrite</b> / "SequentialWrite": TRUE if the 
-CreateFeature() method works for this layer.  Note this means that this 
-particular layer is writable.  The same OGRLayer class  may returned FALSE 
+ <li> <b>OLCSequentialWrite</b> / "SequentialWrite": TRUE if the
+CreateFeature() method works for this layer.  Note this means that this
+particular layer is writable.  The same OGRLayer class  may returned FALSE
 for other layer instances that are effectively read-only.<p>
 
  <li> <b>OLCRandomWrite</b> / "RandomWrite": TRUE if the SetFeature() method
-is operational on this layer.   Note this means that this 
-particular layer is writable.  The same OGRLayer class  may returned FALSE 
+is operational on this layer.   Note this means that this
+particular layer is writable.  The same OGRLayer class  may returned FALSE
 for other layer instances that are effectively read-only.<p>
 
  <li> <b>OLCFastSpatialFilter</b> / "FastSpatialFilter": TRUE if this layer
 implements spatial filtering efficiently.  Layers that effectively read all
 features, and test them with the OGRFeature intersection methods should
-return FALSE.  This can be used as a clue by the application whether it 
+return FALSE.  This can be used as a clue by the application whether it
 should build and maintain its own spatial index for features in this layer.<p>
 
- <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount": 
+ <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount":
 TRUE if this layer can return a feature
 count (via GetFeatureCount()) efficiently. i.e. without counting
 the features.  In some cases this will return TRUE until a spatial filter is
 installed after which it will return FALSE.<p>
 
- <li> <b>OLCFastGetExtent</b> / "FastGetExtent": 
+ <li> <b>OLCFastGetExtent</b> / "FastGetExtent":
 TRUE if this layer can return its data extent (via GetExtent())
 efficiently, i.e. without scanning all the features.  In some cases this
 will return TRUE until a spatial filter is installed after which it will
 return FALSE.<p>
 
- <li> <b>OLCFastSetNextByIndex</b> / "FastSetNextByIndex": 
+ <li> <b>OLCFastSetNextByIndex</b> / "FastSetNextByIndex":
 TRUE if this layer can perform the SetNextByIndex() call efficiently, otherwise
 FALSE.<p>
 
- <li> <b>OLCCreateField</b> / "CreateField": TRUE if this layer can create 
+ <li> <b>OLCCreateField</b> / "CreateField": TRUE if this layer can create
 new fields on the current layer using CreateField(), otherwise FALSE.<p>
 
- <li> <b>OLCCreateGeomField</b> / "CreateGeomField": (GDAL >= 1.11) TRUE if this layer can create 
+ <li> <b>OLCCreateGeomField</b> / "CreateGeomField": (GDAL >= 1.11) TRUE if this layer can create
 new geometry fields on the current layer using CreateGeomField(), otherwise FALSE.<p>
 
  <li> <b>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
@@ -1745,7 +1797,7 @@ the definition of an existing field on the current layer using AlterFieldDefn(),
 method is supported on this layer, otherwise FALSE.<p>
 
  <li> <b>OLCStringsAsUTF8</b> / "StringsAsUTF8": TRUE if values of OFTString
-fields are assured to be in UTF-8 format.  If FALSE the encoding of fields 
+fields are assured to be in UTF-8 format.  If FALSE the encoding of fields
 is uncertain, though it might still be UTF-8.<p>
 
 <li> <b>OLCTransactions</b> / "Transactions": TRUE if the StartTransaction(),
@@ -1761,7 +1813,7 @@ writing curve geometries or may return such geometries. (GDAL 2.0).
 <p>
 
 </ul>
- 
+
  This method is the same as the C function OGR_L_TestCapability().
 
  @param pszCap the name of the capability to test.
@@ -1779,54 +1831,54 @@ OGRLayers will return FALSE for any unrecognized capabilities.<p>
  \brief Test if this layer supported the named capability.
 
  The capability codes that can be tested are represented as strings, but
- \#defined constants exists to ensure correct spelling.  Specific layer 
+ \#defined constants exists to ensure correct spelling.  Specific layer
  types may implement class specific capabilities, but this can't generally
  be discovered by the caller. <p>
 
 <ul>
 
- <li> <b>OLCRandomRead</b> / "RandomRead": TRUE if the GetFeature() method 
+ <li> <b>OLCRandomRead</b> / "RandomRead": TRUE if the GetFeature() method
 is implemented in an optimized way for this layer, as opposed to the default
 implementation using ResetReading() and GetNextFeature() to find the requested
 feature id.<p>
 
- <li> <b>OLCSequentialWrite</b> / "SequentialWrite": TRUE if the 
-CreateFeature() method works for this layer.  Note this means that this 
-particular layer is writable.  The same OGRLayer class  may returned FALSE 
+ <li> <b>OLCSequentialWrite</b> / "SequentialWrite": TRUE if the
+CreateFeature() method works for this layer.  Note this means that this
+particular layer is writable.  The same OGRLayer class  may returned FALSE
 for other layer instances that are effectively read-only.<p>
 
  <li> <b>OLCRandomWrite</b> / "RandomWrite": TRUE if the SetFeature() method
-is operational on this layer.   Note this means that this 
-particular layer is writable.  The same OGRLayer class  may returned FALSE 
+is operational on this layer.   Note this means that this
+particular layer is writable.  The same OGRLayer class  may returned FALSE
 for other layer instances that are effectively read-only.<p>
 
  <li> <b>OLCFastSpatialFilter</b> / "FastSpatialFilter": TRUE if this layer
 implements spatial filtering efficiently.  Layers that effectively read all
 features, and test them with the OGRFeature intersection methods should
-return FALSE.  This can be used as a clue by the application whether it 
-should build and maintain its own spatial index for features in this 
+return FALSE.  This can be used as a clue by the application whether it
+should build and maintain its own spatial index for features in this
 layer.<p>
 
- <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount": 
+ <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount":
 TRUE if this layer can return a feature
 count (via OGR_L_GetFeatureCount()) efficiently, i.e. without counting
 the features.  In some cases this will return TRUE until a spatial filter is
 installed after which it will return FALSE.<p>
 
- <li> <b>OLCFastGetExtent</b> / "FastGetExtent": 
+ <li> <b>OLCFastGetExtent</b> / "FastGetExtent":
 TRUE if this layer can return its data extent (via OGR_L_GetExtent())
 efficiently, i.e. without scanning all the features.  In some cases this
 will return TRUE until a spatial filter is installed after which it will
 return FALSE.<p>
 
- <li> <b>OLCFastSetNextByIndex</b> / "FastSetNextByIndex": 
+ <li> <b>OLCFastSetNextByIndex</b> / "FastSetNextByIndex":
 TRUE if this layer can perform the SetNextByIndex() call efficiently, otherwise
 FALSE.<p>
 
- <li> <b>OLCCreateField</b> / "CreateField": TRUE if this layer can create 
+ <li> <b>OLCCreateField</b> / "CreateField": TRUE if this layer can create
 new fields on the current layer using CreateField(), otherwise FALSE.<p>
 
- <li> <b>OLCCreateGeomField</b> / "CreateGeomField": (GDAL >= 1.11) TRUE if this layer can create 
+ <li> <b>OLCCreateGeomField</b> / "CreateGeomField": (GDAL >= 1.11) TRUE if this layer can create
 new geometry fields on the current layer using CreateGeomField(), otherwise FALSE.<p>
 
  <li> <b>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
@@ -1842,7 +1894,7 @@ the definition of an existing field on the current layer using AlterFieldDefn(),
 method is supported on this layer, otherwise FALSE.<p>
 
  <li> <b>OLCStringsAsUTF8</b> / "StringsAsUTF8": TRUE if values of OFTString
-fields are assured to be in UTF-8 format.  If FALSE the encoding of fields 
+fields are assured to be in UTF-8 format.  If FALSE the encoding of fields
 is uncertain, though it might still be UTF-8.<p>
 
 <li> <b>OLCTransactions</b> / "Transactions": TRUE if the StartTransaction(),
@@ -1855,7 +1907,7 @@ writing curve geometries or may return such geometries. (GDAL 2.0).
 <p>
 
 </ul>
- 
+
  This function is the same as the C++ method OGRLayer::TestCapability().
 
  @param hLayer handle to the layer to get the capability from.
@@ -1873,11 +1925,11 @@ OGRLayers will return FALSE for any unrecognized capabilities.<p>
 
 This call is intended to force the layer to flush any pending writes to
 disk, and leave the disk file in a consistent state.  It would not normally
-have any effect on read-only datasources. 
+have any effect on read-only datasources.
 
-Some layers do not implement this method, and will still return 
+Some layers do not implement this method, and will still return
 OGRERR_NONE.  The default implementation just returns OGRERR_NONE.  An error
-is only returned if an error occurs while attempting to flush to disk.  
+is only returned if an error occurs while attempting to flush to disk.
 
 In any event, you should always close any opened datasource with
 OGRDataSource::DestroyDataSource() that will ensure all data is correctly flushed.
@@ -1895,11 +1947,11 @@ error code.
 
 This call is intended to force the layer to flush any pending writes to
 disk, and leave the disk file in a consistent state.  It would not normally
-have any effect on read-only datasources. 
+have any effect on read-only datasources.
 
-Some layers do not implement this method, and will still return 
+Some layers do not implement this method, and will still return
 OGRERR_NONE.  The default implementation just returns OGRERR_NONE.  An error
-is only returned if an error occurs while attempting to flush to disk.  
+is only returned if an error occurs while attempting to flush to disk.
 
 In any event, you should always close any opened datasource with
 OGR_DS_Destroy() that will ensure all data is correctly flushed.
@@ -1915,25 +1967,25 @@ error code.
 /**
  \fn OGRErr OGRLayer::SetNextByIndex( GIntBig nIndex );
 
- \brief Move read cursor to the nIndex'th feature in the current resultset. 
+ \brief Move read cursor to the nIndex'th feature in the current resultset.
 
  This method allows positioning of a layer such that the GetNextFeature()
  call will read the requested feature, where nIndex is an absolute index
  into the current result set.   So, setting it to 3 would mean the next
  feature read with GetNextFeature() would have been the 4th feature to have
  been read if sequential reading took place from the beginning of the layer,
- including accounting for spatial and attribute filters. 
+ including accounting for spatial and attribute filters.
 
- Only in rare circumstances is SetNextByIndex() efficiently implemented.  
+ Only in rare circumstances is SetNextByIndex() efficiently implemented.
  In all other cases the default implementation which calls ResetReading()
- and then calls GetNextFeature() nIndex times is used.  To determine if 
+ and then calls GetNextFeature() nIndex times is used.  To determine if
  fast seeking is available on the current layer use the TestCapability()
- method with a value of OLCFastSetNextByIndex.  
+ method with a value of OLCFastSetNextByIndex.
 
  This method is the same as the C function OGR_L_SetNextByIndex().
 
  @param nIndex the index indicating how many steps into the result set
- to seek. 
+ to seek.
 
  @return OGRERR_NONE on success or an error code.
 
@@ -1943,26 +1995,26 @@ error code.
 /**
  \fn OGRErr OGR_L_SetNextByIndex( OGRLayerH hLayer, GIntBig nIndex );
 
- \brief Move read cursor to the nIndex'th feature in the current resultset. 
+ \brief Move read cursor to the nIndex'th feature in the current resultset.
 
  This method allows positioning of a layer such that the GetNextFeature()
  call will read the requested feature, where nIndex is an absolute index
  into the current result set.   So, setting it to 3 would mean the next
  feature read with GetNextFeature() would have been the 4th feature to have
  been read if sequential reading took place from the beginning of the layer,
- including accounting for spatial and attribute filters. 
+ including accounting for spatial and attribute filters.
 
- Only in rare circumstances is SetNextByIndex() efficiently implemented.  
+ Only in rare circumstances is SetNextByIndex() efficiently implemented.
  In all other cases the default implementation which calls ResetReading()
- and then calls GetNextFeature() nIndex times is used.  To determine if 
+ and then calls GetNextFeature() nIndex times is used.  To determine if
  fast seeking is available on the current layer use the TestCapability()
- method with a value of OLCFastSetNextByIndex.  
+ method with a value of OLCFastSetNextByIndex.
 
  This method is the same as the C++ method OGRLayer::SetNextByIndex()
 
  @param hLayer handle to the layer
  @param nIndex the index indicating how many steps into the result set
- to seek. 
+ to seek.
 
  @return OGRERR_NONE on success or an error code.
 
@@ -1977,7 +2029,7 @@ This method is the same as the C function OGR_L_Reference().
 
 @return the reference count after incrementing.
 */
-				         
+
 /**
  \fn int OGRLayer::Dereference();
 
@@ -1987,7 +2039,7 @@ This method is the same as the C function OGR_L_Dereference().
 
 @return the reference count after decrementing.
 */
-				         
+
 /**
  \fn int OGRLayer::GetRefCount() const;
 
@@ -1999,7 +2051,7 @@ This method is the same as the C function OGR_L_GetRefCount().
 */
 
 /**
-\fn OGRErr OGRLayer::CreateField( OGRFieldDefn *poField, 
+\fn OGRErr OGRLayer::CreateField( OGRFieldDefn *poField,
 				  int bApproxOK = TRUE );
 
 \brief Create a new field on a layer.
@@ -2022,16 +2074,16 @@ fields with not-null constraints, this is generally before creating any feature
 
 This function is the same as the C function OGR_L_CreateField().
 
- at param poField field definition to write to disk. 
+ at param poField field definition to write to disk.
 @param bApproxOK If TRUE, the field may be created in a slightly different
 form depending on the limitations of the format driver.
 
 @return OGRERR_NONE on success.
 */
- 
+
 /**
 
- \fn OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField, 
+ \fn OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
                           int bApproxOK );
 
 \brief Create a new field on a layer.
@@ -2055,7 +2107,7 @@ fields with not-null constraints, this is generally before creating any feature
  This function is the same as the C++ method OGRLayer::CreateField().
 
  @param hLayer handle to the layer to write the field definition.
- @param hField handle of the field definition to write to disk. 
+ @param hField handle of the field definition to write to disk.
  @param bApproxOK If TRUE, the field may be created in a slightly different
 form depending on the limitations of the format driver.
 
@@ -2094,7 +2146,7 @@ This function is the same as the C function OGR_L_DeleteField().
 
 \fn OGRErr OGR_L_DeleteField( OGRLayerH hLayer, int iField);
 
-\brief Create a new field on a layer.
+\brief Delete an existing field on a layer.
 
 You must use this to delete existing fields
 on a real layer. Internally the OGRFeatureDefn for the layer will be updated
@@ -2333,7 +2385,7 @@ definition must be taken into account.
 
 
 /**
-\fn OGRErr OGRLayer::CreateGeomField( OGRGeomFieldDefn *poField, 
+\fn OGRErr OGRLayer::CreateGeomField( OGRGeomFieldDefn *poField,
                   int bApproxOK = TRUE );
 
 \brief Create a new geometry field on a layer.
@@ -2356,7 +2408,7 @@ fields with not-null constraints, this is generally before creating any feature
 
 This function is the same as the C function OGR_L_CreateGeomField().
 
- at param poField geometry field definition to write to disk. 
+ at param poField geometry field definition to write to disk.
 @param bApproxOK If TRUE, the field may be created in a slightly different
 form depending on the limitations of the format driver.
 
@@ -2364,10 +2416,10 @@ form depending on the limitations of the format driver.
 
 @since OGR 1.11
 */
- 
+
 /**
 
- \fn OGRErr OGR_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField, 
+ \fn OGRErr OGR_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
                           int bApproxOK );
 
 \brief Create a new geometry field on a layer.
@@ -2391,7 +2443,7 @@ fields with not-null constraints, this is generally before creating any feature
  This function is the same as the C++ method OGRLayer::CreateField().
 
  @param hLayer handle to the layer to write the field definition.
- @param hField handle of the geometry field definition to write to disk. 
+ @param hField handle of the geometry field definition to write to disk.
  @param bApproxOK If TRUE, the field may be created in a slightly different
 form depending on the limitations of the format driver.
 
@@ -2404,9 +2456,9 @@ form depending on the limitations of the format driver.
  \fn  void OGRLayer::GetStyleTable();
 
  \brief Returns layer style table.
- 
+
  This method is the same as the C function OGR_L_GetStyleTable().
- 
+
  @return pointer to a style table which should not be modified or freed by the
  caller.
 */
@@ -2415,12 +2467,12 @@ form depending on the limitations of the format driver.
  \fn  void OGRLayer::SetStyleTable(OGRStyleTable *poStyleTable);
 
  \brief Set layer style table.
- 
+
  This method operate exactly as OGRLayer::SetStyleTableDirectly() except
  that it does not assume ownership of the passed table.
- 
+
  This method is the same as the C function OGR_L_SetStyleTable().
- 
+
  @param poStyleTable pointer to style table to set
 
 */
@@ -2429,34 +2481,71 @@ form depending on the limitations of the format driver.
  \fn  void OGRLayer::SetStyleTableDirectly(OGRStyleTable *poStyleTable);
 
  \brief Set layer style table.
- 
+
  This method operate exactly as OGRLayer::SetStyleTable() except that it
  assumes ownership of the passed table.
- 
+
  This method is the same as the C function OGR_L_SetStyleTableDirectly().
- 
+
  @param poStyleTable pointer to style table to set
 
 */
 
 /**
 
+ \fn OGRErr OGRLayer::StartTransaction():
+
+ \brief For datasources which support transactions, StartTransaction creates a transaction.
+
+ If starting the transaction fails, will return
+ OGRERR_FAILURE. Datasources which do not support transactions will
+ always return OGRERR_NONE.
+
+ Note: as of GDAL 2.0, use of this API is discouraged when the dataset offers
+ dataset level transaction with GDALDataset::StartTransaction(). The reason is
+ that most drivers can only offer transactions at dataset level, and not layer level.
+ Very few drivers really support transactions at layer scope.
+
+ This function is the same as the C function OGR_L_StartTransaction().
+
+ @return OGRERR_NONE on success.
+
+*/
+
+/**
+
  \fn OGRErr OGR_L_StartTransaction( OGRLayerH hLayer );
 
  \brief For datasources which support transactions, StartTransaction creates a transaction.
 
- If starting the transaction fails, will return 
- OGRERR_FAILURE. Datasources which do not support transactions will 
- always return OGRERR_NONE. 
+ If starting the transaction fails, will return
+ OGRERR_FAILURE. Datasources which do not support transactions will
+ always return OGRERR_NONE.
 
  Note: as of GDAL 2.0, use of this API is discouraged when the dataset offers
  dataset level transaction with GDALDataset::StartTransaction(). The reason is
  that most drivers can only offer transactions at dataset level, and not layer level.
  Very few drivers really support transactions at layer scope.
- 
+
  This function is the same as the C++ method OGRLayer::StartTransaction().
 
- @param hLayer handle to the layer 
+ @param hLayer handle to the layer
+
+ @return OGRERR_NONE on success.
+
+*/
+
+/**
+
+ \fn OGRErr OGRLayer::CommitTransaction():
+
+ \brief For datasources which support transactions, CommitTransaction commits a transaction.
+
+ If no transaction is active, or the commit fails, will return
+ OGRERR_FAILURE. Datasources which do not support transactions will
+ always return OGRERR_NONE.
+
+ This function is the same as the C function OGR_L_CommitTransaction().
 
  @return OGRERR_NONE on success.
 
@@ -2468,9 +2557,9 @@ form depending on the limitations of the format driver.
 
  \brief For datasources which support transactions, CommitTransaction commits a transaction.
 
- If no transaction is active, or the commit fails, will return 
- OGRERR_FAILURE. Datasources which do not support transactions will 
- always return OGRERR_NONE. 
+ If no transaction is active, or the commit fails, will return
+ OGRERR_FAILURE. Datasources which do not support transactions will
+ always return OGRERR_NONE.
 
  This function is the same as the C++ method OGRLayer::CommitTransaction().
 
@@ -2482,12 +2571,27 @@ form depending on the limitations of the format driver.
 
 /**
 
+ \fn OGRErr OGRLayer::RollbackTransaction():
+
+ \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction.
+ If no transaction is active, or the rollback fails, will return
+ OGRERR_FAILURE. Datasources which do not support transactions will
+ always return OGRERR_NONE.
+
+ This function is the same as the C function OGR_L_RollbackTransaction().
+
+ @return OGRERR_NONE on success.
+
+*/
+
+/**
+
  \fn OGRErr OGR_L_RollbackTransaction( OGRLayerH hLayer );
 
- \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction. 
- If no transaction is active, or the rollback fails, will return  
+ \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction.
+ If no transaction is active, or the rollback fails, will return
  OGRERR_FAILURE. Datasources which do not support transactions will
- always return OGRERR_NONE. 
+ always return OGRERR_NONE.
 
  This function is the same as the C++ method OGRLayer::RollbackTransaction().
 
@@ -2505,7 +2609,7 @@ form depending on the limitations of the format driver.
  This method is the same as the C function OGR_L_GetFIDColumn().
 
  @return fid column name.
- 
+
  */
 
 /**
@@ -2517,7 +2621,7 @@ form depending on the limitations of the format driver.
 
  @param hLayer handle to the layer
  @return fid column name.
- 
+
  */
 
 /**
@@ -2532,7 +2636,7 @@ form depending on the limitations of the format driver.
  This method is the same as the C function OGR_L_GetGeometryColumn().
 
  @return geometry column name.
- 
+
  */
 
 /**
@@ -2548,7 +2652,7 @@ form depending on the limitations of the format driver.
 
  @param hLayer handle to the layer
  @return geometry column name.
- 
+
  */
 
 /**
diff --git a/ogr/ogrsf_frmts/ogrsf_frmts.h b/ogr/ogrsf_frmts/ogrsf_frmts.h
index f846586..f396730 100644
--- a/ogr/ogrsf_frmts/ogrsf_frmts.h
+++ b/ogr/ogrsf_frmts/ogrsf_frmts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsf_frmts.h 35040 2016-08-10 14:02:46Z rouault $
+ * $Id: ogrsf_frmts.h 37968 2017-04-12 07:16:55Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Classes related to format registration, and file opening.
@@ -42,11 +42,13 @@
  * Classes related to registration of format support, and opening datasets.
  */
 
+//! @cond Doxygen_Suppress
 #if !defined(GDAL_COMPILATION) && !defined(SUPPRESS_DEPRECATION_WARNINGS)
 #define OGR_DEPRECATED(x) CPL_WARN_DEPRECATED(x)
 #else
 #define OGR_DEPRECATED(x)
 #endif
+//! @endcond
 
 class OGRLayerAttrIndex;
 class OGRSFDriver;
@@ -69,6 +71,7 @@ class CPL_DLL OGRLayer : public GDALMajorObject
     void         ConvertGeomsIfNecessary( OGRFeature *poFeature );
 
   protected:
+//! @cond Doxygen_Suppress
     int          m_bFilterIsEnvelope;
     OGRGeometry *m_poFilterGeom;
     OGRPreparedGeometry *m_pPreparedFilterGeom; /* m_poFilterGeom compiled as a prepared geometry */
@@ -81,6 +84,7 @@ class CPL_DLL OGRLayer : public GDALMajorObject
     int          InstallFilter( OGRGeometry * );
 
     OGRErr       GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bForce );
+//! @endcond
 
     virtual OGRErr      ISetFeature( OGRFeature *poFeature ) CPL_WARN_UNUSED_RESULT;
     virtual OGRErr      ICreateFeature( OGRFeature *poFeature )  CPL_WARN_UNUSED_RESULT;
@@ -189,19 +193,23 @@ class CPL_DLL OGRLayer : public GDALMajorObject
     int                 Reference();
     int                 Dereference();
     int                 GetRefCount() const;
-
+//! @cond Doxygen_Suppress
     GIntBig             GetFeaturesRead();
+//! @endcond
 
     /* non virtual : convenience wrapper for ReorderFields() */
     OGRErr              ReorderField( int iOldFieldPos, int iNewFieldPos );
 
+//! @cond Doxygen_Suppress
     int                 AttributeFilterEvaluationNeedsGeometry();
 
     /* consider these private */
     OGRErr               InitializeIndexSupport( const char * );
     OGRLayerAttrIndex   *GetIndex() { return m_poAttrIndex; }
+//! @endcond
 
  protected:
+//! @cond Doxygen_Suppress
     OGRStyleTable       *m_poStyleTable;
     OGRFeatureQuery     *m_poAttrQuery;
     char                *m_pszAttrQueryString;
@@ -210,6 +218,7 @@ class CPL_DLL OGRLayer : public GDALMajorObject
     int                  m_nRefCount;
 
     GIntBig              m_nFeaturesRead;
+//! @endcond
 };
 
 /************************************************************************/
@@ -239,10 +248,11 @@ class CPL_DLL OGRDataSource : public GDALDataset
 {
 public:
                         OGRDataSource();
-
+//! @cond Doxygen_Suppress
     virtual const char  *GetName() OGR_DEPRECATED("Use GDALDataset class instead") = 0;
 
     static void         DestroyDataSource( OGRDataSource * ) OGR_DEPRECATED("Use GDALDataset class instead");
+//! @endcond
 };
 
 /************************************************************************/
@@ -270,6 +280,7 @@ public:
 class CPL_DLL OGRSFDriver : public GDALDriver
 {
   public:
+//! @cond Doxygen_Suppress
     virtual     ~OGRSFDriver();
 
     virtual const char  *GetName() OGR_DEPRECATED("Use GDALDriver class instead") = 0;
@@ -281,9 +292,9 @@ class CPL_DLL OGRSFDriver : public GDALDriver
     virtual OGRDataSource *CreateDataSource( const char *pszName,
                                              char ** = NULL ) OGR_DEPRECATED("Use GDALDriver class instead");
     virtual OGRErr      DeleteDataSource( const char *pszName ) OGR_DEPRECATED("Use GDALDriver class instead");
+//! @endcond
 };
 
-
 /************************************************************************/
 /*                         OGRSFDriverRegistrar                         */
 /************************************************************************/
@@ -316,17 +327,24 @@ class CPL_DLL OGRSFDriverRegistrar
                                           const char * pszName );
 
   public:
-
+//! @cond Doxygen_Suppress
     static OGRSFDriverRegistrar *GetRegistrar() OGR_DEPRECATED("Use GDALDriverManager class instead");
 
+    // cppcheck-suppress functionStatic
     void        RegisterDriver( OGRSFDriver * poDriver ) OGR_DEPRECATED("Use GDALDriverManager class instead");
 
+    // cppcheck-suppress functionStatic
     int         GetDriverCount( void ) OGR_DEPRECATED("Use GDALDriverManager class instead");
+    // cppcheck-suppress functionStatic
     GDALDriver *GetDriver( int iDriver ) OGR_DEPRECATED("Use GDALDriverManager class instead");
+    // cppcheck-suppress functionStatic
     GDALDriver *GetDriverByName( const char * ) OGR_DEPRECATED("Use GDALDriverManager class instead");
 
+    // cppcheck-suppress functionStatic
     int         GetOpenDSCount() OGR_DEPRECATED("Use GDALDriverManager class instead");
+    // cppcheck-suppress functionStatic
     OGRDataSource *GetOpenDS( int ) OGR_DEPRECATED("Use GDALDriverManager class instead");
+//! @endcond
 };
 
 /* -------------------------------------------------------------------- */
@@ -334,6 +352,8 @@ class CPL_DLL OGRSFDriverRegistrar
 /* -------------------------------------------------------------------- */
 CPL_C_START
 void CPL_DLL OGRRegisterAll();
+
+//! @cond Doxygen_Suppress
 void OGRRegisterAllInternal();
 
 void CPL_DLL RegisterOGRFileGDB();
@@ -370,9 +390,10 @@ void CPL_DLL RegisterOGRILI1();
 void CPL_DLL RegisterOGRILI2();
 void CPL_DLL RegisterOGRGRASS();
 void CPL_DLL RegisterOGRPGeo();
-void CPL_DLL RegisterOGRDXFDWG();
 void CPL_DLL RegisterOGRDXF();
+void CPL_DLL RegisterOGRCAD();
 void CPL_DLL RegisterOGRDWG();
+void CPL_DLL RegisterOGRDGNV8();
 void CPL_DLL RegisterOGRSDE();
 void CPL_DLL RegisterOGRIDB();
 void CPL_DLL RegisterOGRGMT();
@@ -413,7 +434,6 @@ void CPL_DLL RegisterOGRElastic();
 void CPL_DLL RegisterOGRGeoPackage();
 void CPL_DLL RegisterOGRWalk();
 void CPL_DLL RegisterOGRCarto();
-void CPL_DLL RegisterOGRCartoDB(); // Just kept for C ABI stability
 void CPL_DLL RegisterOGRAmigoCloud();
 void CPL_DLL RegisterOGRSXF();
 void CPL_DLL RegisterOGROpenFileGDB();
@@ -423,6 +443,9 @@ void CPL_DLL RegisterOGRPLSCENES();
 void CPL_DLL RegisterOGRCSW();
 void CPL_DLL RegisterOGRMongoDB();
 void CPL_DLL RegisterOGRVDV();
+void CPL_DLL RegisterOGRGMLAS();
+// @endcond
+
 CPL_C_END
 
 #endif /* ndef OGRSF_FRMTS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/openair/ogr_openair.h b/ogr/ogrsf_frmts/openair/ogr_openair.h
index 895c04c..1d0ef97 100644
--- a/ogr/ogrsf_frmts/openair/ogr_openair.h
+++ b/ogr/ogrsf_frmts/openair/ogr_openair.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_openair.h 32976 2016-01-14 00:07:34Z goatbar $
+ * $Id: ogr_openair.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenAir Translator
  * Purpose:  Definition of classes for OGR .sua driver.
@@ -64,16 +64,15 @@ class OGROpenAirLayer : public OGRLayer
     OGRFeature *       GetNextRawFeature();
 
   public:
-                        OGROpenAirLayer(VSILFILE* fp);
-                        ~OGROpenAirLayer();
+    explicit            OGROpenAirLayer(VSILFILE* fp);
+                        virtual ~OGROpenAirLayer();
 
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -98,15 +97,15 @@ class OGROpenAirLabelLayer : public OGRLayer
     CPLString          osCEILING;
 
   public:
-                        OGROpenAirLabelLayer(VSILFILE* fp);
-                        ~OGROpenAirLabelLayer();
+    explicit            OGROpenAirLabelLayer(VSILFILE* fp);
+                        virtual ~OGROpenAirLabelLayer();
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -122,16 +121,16 @@ class OGROpenAirDataSource : public OGRDataSource
 
   public:
                         OGROpenAirDataSource();
-                        ~OGROpenAirDataSource();
+                        virtual ~OGROpenAirDataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 bool OGROpenAirGetLatLon( const char* pszStr, double& dfLat, double& dfLon );
diff --git a/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp b/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
index 089a454..f4372fc 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogropenairdatasource.cpp 32976 2016-01-14 00:07:34Z goatbar $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirDataSource class
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogropenairdatasource.cpp 32976 2016-01-14 00:07:34Z goatbar $");
+CPL_CVSID("$Id: ogropenairdatasource.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                        OGROpenAirDataSource()                        */
@@ -109,7 +108,6 @@ int OGROpenAirDataSource::Open( const char * pszFilename )
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                              GetLatLon()                             */
 /************************************************************************/
@@ -128,7 +126,7 @@ bool OGROpenAirGetLatLon( const char* pszStr, double& dfLat, double& dfLon )
     double dfDegree = 0;
     double dfMinute = 0;
     double dfSecond = 0;
-    char c;
+    char c = '\0';
     bool bHasLat = false;
     bool bHasLon = false;
     while((c = *pszStr) != 0)
diff --git a/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp b/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
index 9af6d1d..f653322 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogropenairdriver.cpp 32976 2016-01-14 00:07:34Z goatbar $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirDriver.
@@ -31,7 +30,7 @@
 #include "ogr_openair.h"
 #include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogropenairdriver.cpp 32976 2016-01-14 00:07:34Z goatbar $");
+CPL_CVSID("$Id: ogropenairdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -125,4 +124,3 @@ void RegisterOGROpenAir()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp b/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp
index 2153793..1c90309 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairlabellayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogropenairlabellayer.cpp 32976 2016-01-14 00:07:34Z goatbar $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirLabelLayer class.
@@ -33,7 +32,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogropenairlabellayer.cpp 32976 2016-01-14 00:07:34Z goatbar $");
+CPL_CVSID("$Id: ogropenairlabellayer.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                      OGROpenAirLabelLayer()                          */
@@ -50,13 +49,13 @@ OGROpenAirLabelLayer::OGROpenAirLabelLayer( VSILFILE* fp ) :
     poFeatureDefn->SetGeomType( wkbPoint );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
-    OGRFieldDefn    oField1( "CLASS", OFTString);
+    OGRFieldDefn oField1( "CLASS", OFTString);
     poFeatureDefn->AddFieldDefn( &oField1 );
-    OGRFieldDefn    oField2( "NAME", OFTString);
+    OGRFieldDefn oField2( "NAME", OFTString);
     poFeatureDefn->AddFieldDefn( &oField2 );
-    OGRFieldDefn    oField3( "FLOOR", OFTString);
+    OGRFieldDefn oField3( "FLOOR", OFTString);
     poFeatureDefn->AddFieldDefn( &oField3 );
-    OGRFieldDefn    oField4( "CEILING", OFTString);
+    OGRFieldDefn oField4( "CEILING", OFTString);
     poFeatureDefn->AddFieldDefn( &oField4 );
 }
 
@@ -75,7 +74,6 @@ OGROpenAirLabelLayer::~OGROpenAirLabelLayer()
     VSIFCloseL( fpOpenAir );
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -87,7 +85,6 @@ void OGROpenAirLabelLayer::ResetReading()
     VSIFSeekL( fpOpenAir, 0, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -133,7 +130,7 @@ OGRFeature *OGROpenAirLabelLayer::GetNextRawFeature()
 
         if (STARTS_WITH_CI(pszLine, "AC "))
         {
-            if (osCLASS.size() != 0)
+            if (!osCLASS.empty())
             {
                 osNAME = "";
                 osCEILING = "";
diff --git a/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp b/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp
index 3f1c449..bfa55c4 100644
--- a/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp
+++ b/ogr/ogrsf_frmts/openair/ogropenairlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogropenairlayer.cpp 32977 2016-01-14 00:52:59Z goatbar $
  *
  * Project:  OpenAir Translator
  * Purpose:  Implements OGROpenAirLayer class.
@@ -34,7 +33,7 @@
 #include "ogr_srs_api.h"
 #include "ogr_xplane_geo_utils.h"
 
-CPL_CVSID("$Id: ogropenairlayer.cpp 32977 2016-01-14 00:52:59Z goatbar $");
+CPL_CVSID("$Id: ogropenairlayer.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                         OGROpenAirLayer()                            */
@@ -53,13 +52,13 @@ OGROpenAirLayer::OGROpenAirLayer( VSILFILE* fp ) :
     poFeatureDefn->SetGeomType( wkbPolygon );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
-    OGRFieldDefn    oField1( "CLASS", OFTString);
+    OGRFieldDefn oField1( "CLASS", OFTString);
     poFeatureDefn->AddFieldDefn( &oField1 );
-    OGRFieldDefn    oField2( "NAME", OFTString);
+    OGRFieldDefn oField2( "NAME", OFTString);
     poFeatureDefn->AddFieldDefn( &oField2 );
-    OGRFieldDefn    oField3( "FLOOR", OFTString);
+    OGRFieldDefn oField3( "FLOOR", OFTString);
     poFeatureDefn->AddFieldDefn( &oField3 );
-    OGRFieldDefn    oField4( "CEILING", OFTString);
+    OGRFieldDefn oField4( "CEILING", OFTString);
     poFeatureDefn->AddFieldDefn( &oField4 );
 }
 
@@ -85,7 +84,6 @@ OGROpenAirLayer::~OGROpenAirLayer()
     VSIFCloseL( fpOpenAir );
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -99,7 +97,6 @@ void OGROpenAirLayer::ResetReading()
     VSIFSeekL( fpOpenAir, 0, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -138,10 +135,12 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
     CPLString osFLOOR;
     CPLString osCEILING;
     OGRLinearRing oLR;
-    /* double dfLastLat = 0, dfLastLon = 0; */
+    // double dfLastLat = 0.0;
+    // double dfLastLon = 0.0;
     bool bFirst = true;
     bool bClockWise = true;
-    double dfCenterLat = 0, dfCenterLon = 0;
+    double dfCenterLat = 0.0;
+    double dfCenterLon = 0.0;
     bool bHasCenter = false;
     OpenAirStyle sStyle;
     sStyle.penStyle = -1;
@@ -166,7 +165,7 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                 if (oLR.getNumPoints() == 0)
                     return NULL;
 
-                if (osCLASS.size() != 0 &&
+                if (!osCLASS.empty() &&
                     oStyleMap.find(osCLASS) != oStyleMap.end())
                 {
                     memcpy(&sStyle, oStyleMap[osCLASS], sizeof(sStyle));
@@ -182,13 +181,13 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
 
         if (STARTS_WITH_CI(pszLine, "AC ") || STARTS_WITH_CI(pszLine, "AC,"))
         {
-            if (osCLASS.size() != 0)
+            if (!osCLASS.empty())
             {
                 if (sStyle.penStyle != -1 || sStyle.fillR != -1)
                 {
                     if (oLR.getNumPoints() == 0)
                     {
-                        OpenAirStyle* psStyle;
+                        OpenAirStyle* psStyle = NULL;
                         if (oStyleMap.find(osCLASS) == oStyleMap.end())
                         {
                             psStyle = (OpenAirStyle*)CPLMalloc(
@@ -220,7 +219,7 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
         }
         else if (STARTS_WITH_CI(pszLine, "AN "))
         {
-            if (osNAME.size() != 0)
+            if (!osNAME.empty())
                 break;
             osNAME = pszLine + 3;
         }
@@ -234,7 +233,7 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
         }
         else if (STARTS_WITH_CI(pszLine, "SP "))
         {
-            if (osCLASS.size() != 0)
+            if (!osCLASS.empty())
             {
                 char** papszTokens = CSLTokenizeString2(pszLine+3, ", ", 0);
                 if (CSLCount(papszTokens) == 5)
@@ -250,7 +249,7 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
         }
         else if (STARTS_WITH_CI(pszLine, "SB "))
         {
-            if (osCLASS.size() != 0)
+            if (!osCLASS.empty())
             {
                 char** papszTokens = CSLTokenizeString2(pszLine+3, ", ", 0);
                 if (CSLCount(papszTokens) == 3)
@@ -266,8 +265,8 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
         {
             pszLine += 3;
 
-            double dfLat;
-            double dfLon;
+            double dfLat = 0.0;
+            double dfLon = 0.0;
             if (!OGROpenAirGetLatLon(pszLine, dfLat, dfLon))
                 continue;
 
@@ -298,8 +297,8 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                 const double dfStartDistance = dfRadius;
                 const double dfEndDistance = dfRadius;
                 const int nSign = (bClockWise) ? 1 : -1;
-                double dfLat;
-                double dfLon;
+                double dfLat = 0.0;
+                double dfLon = 0.0;
                 for(double dfAngle = dfStartAngle;
                     (dfAngle - dfEndAngle) * nSign < 0;
                     dfAngle += nSign)
@@ -329,15 +328,15 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
             char* pszStar = strchr(const_cast<char *>(pszLine), '*');
             if (pszStar) *pszStar = 0;
             char** papszTokens = CSLTokenizeString2(pszLine, ",", 0);
-            double dfFirstLat;
-            double dfFirstLon;
-            double dfSecondLat;
-            double dfSecondLon;
+            double dfFirstLat = 0.0;
+            double dfFirstLon = 0.0;
+            double dfSecondLat = 0.0;
+            double dfSecondLon = 0.0;
             if (bHasCenter && CSLCount(papszTokens) == 2 &&
                 OGROpenAirGetLatLon(papszTokens[0], dfFirstLat, dfFirstLon) &&
                 OGROpenAirGetLatLon(papszTokens[1], dfSecondLat, dfSecondLon))
             {
-                const double dfStartDistance =OGRXPlane_Distance(dfCenterLat,
+                const double dfStartDistance = OGRXPlane_Distance(dfCenterLat,
                         dfCenterLon, dfFirstLat, dfFirstLon);
                 const double dfEndDistance = OGRXPlane_Distance(dfCenterLat,
                         dfCenterLon, dfSecondLat, dfSecondLon);
@@ -356,8 +355,8 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                     (dfAngle - dfEndAngle) * nSign < 0;
                     dfAngle += nSign)
                 {
-                    double dfLat;
-                    double dfLon;
+                    double dfLat = 0.0;
+                    double dfLon = 0.0;
                     const double pct = (dfAngle - dfStartAngle) /
                         (dfEndAngle - dfStartAngle);
                     const double dfDist = dfStartDistance * (1-pct) +
@@ -389,9 +388,9 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
                 pszLine += 3;
 
                 const double dfRADIUS = CPLAtof(pszLine) * 1852;
-                double dfLat;
-                double dfLon;
-                for(double dfAngle = 0; dfAngle < 360; dfAngle += 1)
+                double dfLat = 0.0;
+                double dfLon = 0.0;
+                for( double dfAngle = 0; dfAngle < 360; dfAngle += 1.0 )
                 {
                     OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon,
                                              dfRADIUS, dfAngle, &dfLat, &dfLon);
@@ -444,18 +443,18 @@ OGRFeature *OGROpenAirLayer::GetNextRawFeature()
         }
         if (sStyle.fillR != -1)
         {
-            if (osStyle.size() != 0)
+            if (!osStyle.empty())
                 osStyle += ";";
             osStyle += CPLString().Printf("BRUSH(fc:#%02X%02X%02X)",
                                  sStyle.fillR, sStyle.fillG, sStyle.fillB);
         }
         else
         {
-            if (osStyle.size() != 0)
+            if (!osStyle.empty())
                 osStyle += ";";
             osStyle += "BRUSH(fc:#00000000,id:\"ogr-brush-1\")";
         }
-        if (osStyle.size() != 0)
+        if (!osStyle.empty())
             poFeature->SetStyleString(osStyle);
     }
 
diff --git a/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html b/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html
index cf79d0b..8ea95e0 100644
--- a/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html
+++ b/ogr/ogrsf_frmts/openfilegdb/drv_openfilegdb.html
@@ -11,15 +11,18 @@
 
 <p>
 The OpenFileGDB driver provides read access to File Geodatabases
-(.gdb directories) created by ArcGIS 9 and above.
+(.gdb directories) created by ArcGIS 9 and above. The dataset name must be
+the directory/folder name, and it must end with the .gdb extension.
 </p>
 <p>
-It can also read directly zipped .gdb directories (.gdb.zip)
+It can also read directly zipped .gdb directories (with .gdb.zip extension),
+provided they contain a .gdb directory at their first level.
 </p>
 <p>
 A specific .gdbtable file (including "system" tables) can also be opened
 directly.
 </p>
+<p>Curve in geometries are supported with GDAL >= 2.2.</p>
 
 <h2>Spatial filtering</h2>
 
@@ -76,12 +79,6 @@ Drawbacks of the OpenFileGDB driver:
 <li>Cannot read data from compressed data in CDF format (Compressed Data Format).</li>
 </ul>
 
-<h2>Known Issues</h2>
-
-<ul>
-        <li>Curve in geometries are not currently supported.</li>
-</ul>
-
 <h2>Examples</h2>
 
 <ul>
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp b/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
index 44a07f4..6723789 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbindex.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: filegdbindex.cpp 33027 2016-01-17 18:47:10Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB indexes
@@ -32,7 +31,7 @@
 #include "cpl_time.h"
 #include <algorithm>
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: filegdbindex.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 namespace OpenFileGDB
 {
@@ -45,15 +44,17 @@ static bool FileGDBOGRDateToDoubleDate( const OGRField* psField,
                                         double *pdfVal )
 {
     struct tm brokendowntime;
+    /* workaround cppcheck false positive */
+    struct tm* pBrokendowntime = &brokendowntime;
 
-    brokendowntime.tm_year = psField->Date.Year - 1900;
-    brokendowntime.tm_mon = psField->Date.Month - 1;
-    brokendowntime.tm_mday = psField->Date.Day;
-    brokendowntime.tm_hour = psField->Date.Hour;
-    brokendowntime.tm_min = psField->Date.Minute;
-    brokendowntime.tm_sec = static_cast<int>(psField->Date.Second);
+    pBrokendowntime->tm_year = psField->Date.Year - 1900;
+    pBrokendowntime->tm_mon = psField->Date.Month - 1;
+    pBrokendowntime->tm_mday = psField->Date.Day;
+    pBrokendowntime->tm_hour = psField->Date.Hour;
+    pBrokendowntime->tm_min = psField->Date.Minute;
+    pBrokendowntime->tm_sec = static_cast<int>(psField->Date.Second);
 
-    const GIntBig nTime = CPLYMDHMSToUnixTime(&brokendowntime);
+    const GIntBig nTime = CPLYMDHMSToUnixTime(pBrokendowntime);
 
     *pdfVal = nTime / 3600. / 24 + 25569;
 
@@ -71,24 +72,24 @@ class FileGDBTrivialIterator CPL_FINAL : public FileGDBIterator
         int                         iRow;
 
     public:
-                                     FileGDBTrivialIterator(FileGDBIterator *poParentIter);
+        explicit                     FileGDBTrivialIterator(FileGDBIterator *poParentIter);
         virtual                     ~FileGDBTrivialIterator() { delete poParentIter; }
 
-        virtual FileGDBTable        *GetTable() { return poTable; }
-        virtual void                 Reset() { iRow = 0; poParentIter->Reset(); }
-        virtual int                  GetNextRowSortedByFID();
-        virtual int                  GetRowCount()
+        virtual FileGDBTable        *GetTable() override { return poTable; }
+        virtual void                 Reset() override { iRow = 0; poParentIter->Reset(); }
+        virtual int                  GetNextRowSortedByFID() override;
+        virtual int                  GetRowCount() override
                 { return poTable->GetTotalRecordCount(); }
 
-        virtual int                  GetNextRowSortedByValue()
+        virtual int                  GetNextRowSortedByValue() override
                 { return poParentIter->GetNextRowSortedByValue(); }
 
-        virtual const OGRField*      GetMinValue(int& eOutType)
+        virtual const OGRField*      GetMinValue(int& eOutType) override
                 { return poParentIter->GetMinValue(eOutType); }
-        virtual const OGRField*      GetMaxValue(int& eOutType)
+        virtual const OGRField*      GetMaxValue(int& eOutType) override
                 { return poParentIter->GetMaxValue(eOutType); }
         virtual int                  GetMinMaxSumCount(double& dfMin, double& dfMax,
-                                                       double& dfSum, int& nCount)
+                                                       double& dfSum, int& nCount) override
             { return poParentIter->GetMinMaxSumCount(dfMin, dfMax, dfSum, nCount); }
 };
 
@@ -105,13 +106,13 @@ class FileGDBNotIterator CPL_FINAL : public FileGDBIterator
         int                         bNoHoles;
 
     public:
-                                     FileGDBNotIterator(FileGDBIterator* poIterBase);
+        explicit                     FileGDBNotIterator(FileGDBIterator* poIterBase);
         virtual                     ~FileGDBNotIterator();
 
-        virtual FileGDBTable        *GetTable() { return poTable; }
-        virtual void                 Reset();
-        virtual int                  GetNextRowSortedByFID();
-        virtual int                  GetRowCount();
+        virtual FileGDBTable        *GetTable() override { return poTable; }
+        virtual void                 Reset() override;
+        virtual int                  GetNextRowSortedByFID() override;
+        virtual int                  GetRowCount() override;
 };
 
 /************************************************************************/
@@ -130,9 +131,9 @@ class FileGDBAndIterator CPL_FINAL : public FileGDBIterator
                                                         FileGDBIterator* poIter2);
         virtual                     ~FileGDBAndIterator();
 
-        virtual FileGDBTable        *GetTable() { return poIter1->GetTable(); }
-        virtual void                 Reset();
-        virtual int                  GetNextRowSortedByFID();
+        virtual FileGDBTable        *GetTable() override { return poIter1->GetTable(); }
+        virtual void                 Reset() override;
+        virtual int                  GetNextRowSortedByFID() override;
 };
 
 /************************************************************************/
@@ -154,10 +155,10 @@ class FileGDBOrIterator CPL_FINAL : public FileGDBIterator
                                                        int bIteratorAreExclusive = FALSE);
         virtual                     ~FileGDBOrIterator();
 
-        virtual FileGDBTable        *GetTable() { return poIter1->GetTable(); }
-        virtual void                 Reset();
-        virtual int                  GetNextRowSortedByFID();
-        virtual int                  GetRowCount();
+        virtual FileGDBTable        *GetTable() override { return poIter1->GetTable(); }
+        virtual void                 Reset() override;
+        virtual int                  GetNextRowSortedByFID() override;
+        virtual int                  GetRowCount() override;
 };
 
 /************************************************************************/
@@ -238,17 +239,17 @@ class FileGDBIndexIterator CPL_FINAL : public FileGDBIterator
                                            OGRFieldType eOGRFieldType,
                                            const OGRField* psValue);
 
-        virtual FileGDBTable        *GetTable() { return poParent; }
-        virtual void                 Reset();
-        virtual int                  GetNextRowSortedByFID();
-        virtual int                  GetRowCount();
+        virtual FileGDBTable        *GetTable() override { return poParent; }
+        virtual void                 Reset() override;
+        virtual int                  GetNextRowSortedByFID() override;
+        virtual int                  GetRowCount() override;
 
-        virtual int                  GetNextRowSortedByValue() { return GetNextRow(); }
+        virtual int                  GetNextRowSortedByValue() override { return GetNextRow(); }
 
-        virtual const OGRField*      GetMinValue(int& eOutType);
-        virtual const OGRField*      GetMaxValue(int& eOutType);
+        virtual const OGRField*      GetMinValue(int& eOutType) override;
+        virtual const OGRField*      GetMaxValue(int& eOutType) override;
         virtual int                  GetMinMaxSumCount(double& dfMin, double& dfMax,
-                                                       double& dfSum, int& nCount);
+                                                       double& dfSum, int& nCount) override;
 };
 
 /************************************************************************/
@@ -383,10 +384,12 @@ int FileGDBIterator::GetRowCount()
 /*                         FileGDBTrivialIterator()                     */
 /************************************************************************/
 
-FileGDBTrivialIterator::FileGDBTrivialIterator(FileGDBIterator* poParentIterIn) :
-        poParentIter(poParentIterIn), poTable(poParentIterIn->GetTable()), iRow(0)
-{
-}
+FileGDBTrivialIterator::FileGDBTrivialIterator(
+    FileGDBIterator* poParentIterIn ) :
+    poParentIter(poParentIterIn),
+    poTable(poParentIterIn->GetTable()),
+    iRow(0)
+{}
 
 /************************************************************************/
 /*                        GetNextRowSortedByFID()                       */
@@ -405,7 +408,10 @@ int FileGDBTrivialIterator::GetNextRowSortedByFID()
 /************************************************************************/
 
 FileGDBNotIterator::FileGDBNotIterator(FileGDBIterator* poIterBaseIn) :
-    poIterBase(poIterBaseIn), poTable(poIterBaseIn->GetTable()), iRow(0), iNextRowBase(-1)
+    poIterBase(poIterBaseIn),
+    poTable(poIterBaseIn->GetTable()),
+    iRow(0),
+    iNextRowBase(-1)
 {
     bNoHoles = (poTable->GetValidRecordCount() == poTable->GetTotalRecordCount());
 }
@@ -477,15 +483,16 @@ int FileGDBNotIterator::GetRowCount()
     return poTable->GetValidRecordCount() - poIterBase->GetRowCount();
 }
 
-
 /************************************************************************/
 /*                          FileGDBAndIterator()                        */
 /************************************************************************/
 
-FileGDBAndIterator::FileGDBAndIterator(FileGDBIterator* poIter1In,
-                                       FileGDBIterator* poIter2In) :
-                                       poIter1(poIter1In), poIter2(poIter2In),
-                                       iNextRow1(-1), iNextRow2(-1)
+FileGDBAndIterator::FileGDBAndIterator( FileGDBIterator* poIter1In,
+                                        FileGDBIterator* poIter2In ) :
+    poIter1(poIter1In),
+    poIter2(poIter2In),
+    iNextRow1(-1),
+    iNextRow2(-1)
 {
     CPLAssert(poIter1->GetTable() == poIter2->GetTable());
 }
@@ -551,10 +558,9 @@ int FileGDBAndIterator::GetNextRowSortedByFID()
 /*                          FileGDBOrIterator()                         */
 /************************************************************************/
 
-
-FileGDBOrIterator::FileGDBOrIterator(FileGDBIterator* poIter1In,
-                                     FileGDBIterator* poIter2In,
-                                     int bIteratorAreExclusiveIn) :
+FileGDBOrIterator::FileGDBOrIterator( FileGDBIterator* poIter1In,
+                                      FileGDBIterator* poIter2In,
+                                      int bIteratorAreExclusiveIn ) :
     poIter1(poIter1In),
     poIter2(poIter2In),
     bIteratorAreExclusive(bIteratorAreExclusiveIn),
@@ -646,7 +652,7 @@ int FileGDBOrIterator::GetRowCount()
 /************************************************************************/
 
 FileGDBIndexIterator::FileGDBIndexIterator( FileGDBTable* poParentIn,
-                                            int bAscendingIn) :
+                                            int bAscendingIn ) :
   poParent(poParentIn),
   bAscending(CPL_TO_BOOL(bAscendingIn)),
   fpCurIdx(NULL),
@@ -715,7 +721,7 @@ static const char* FileGDBSQLOpToStr(FileGDBSQLOp op)
     switch( op )
     {
         case FGSO_ISNOTNULL : return "IS NOT NULL";
-        case FGSO_LT: return "<";;
+        case FGSO_LT: return "<";
         case FGSO_LE: return "<=";
         case FGSO_EQ: return "=";
         case FGSO_GE: return ">=";
@@ -916,6 +922,7 @@ int FileGDBIndexIterator::SetConstraint(int nFieldIdx,
             {
                 returnErrorIf(eOGRFieldType != OFTString);
                 memset(szUUID, 0, UUID_LEN_AS_STRING + 1);
+                // cppcheck-suppress redundantCopy
                 strncpy(szUUID, psValue->String, UUID_LEN_AS_STRING);
                 bEvaluateToFALSE =
                     eOp == FGSO_EQ &&
@@ -926,7 +933,7 @@ int FileGDBIndexIterator::SetConstraint(int nFieldIdx,
         }
 
         default:
-            CPLAssert(FALSE);
+            CPLAssert(false);
             break;
     }
 
@@ -1050,7 +1057,8 @@ int FileGDBIndexIterator::FindPages(int iLevel, int nPage)
             case FGFT_FLOAT64:
             case FGFT_DATETIME:
             {
-                double dfVal = GetFloat64(abyPage[iLevel] + nOffsetFirstValInPage, i);
+                const double dfVal =
+                    GetFloat64(abyPage[iLevel] + nOffsetFirstValInPage, i);
 #ifdef DEBUG_INDEX_CONSISTENCY
                 returnErrorIf(i > 0 && dfVal < dfLastMax);
                 dfLastMax = dfVal;
@@ -1097,7 +1105,7 @@ int FileGDBIndexIterator::FindPages(int iLevel, int nPage)
             }
 
             default:
-                CPLAssert(FALSE);
+                CPLAssert(false);
                 nComp = 0;
                 break;
         }
@@ -1164,7 +1172,7 @@ int FileGDBIndexIterator::FindPages(int iLevel, int nPage)
                 break;
 
             default:
-                CPLAssert(FALSE);
+                CPLAssert(false);
                 break;
         }
         if( bStop )
@@ -1316,36 +1324,39 @@ int FileGDBIndexIterator::GetNextRow()
             }
         }
 
-        int bMatch;
+        bool bMatch = false;
         if( eOp == FGSO_ISNOTNULL )
         {
-            bMatch = TRUE;
+            bMatch = true;
         }
         else
         {
-            int nComp;
+            int nComp = 0;
             switch( eFieldType )
             {
                 case FGFT_INT16:
                 {
-                    GInt16 nVal = GetInt16(abyPageFeature + nOffsetFirstValInPage,
-                                           iCurFeatureInPage);
+                    const GInt16 nVal =
+                        GetInt16(abyPageFeature + nOffsetFirstValInPage,
+                                 iCurFeatureInPage);
                     nComp = COMPARE(sValue.Integer, nVal);
                     break;
                 }
 
                 case FGFT_INT32:
                 {
-                    GInt32 nVal = GetInt32(abyPageFeature + nOffsetFirstValInPage,
-                                           iCurFeatureInPage);
+                    const GInt32 nVal =
+                        GetInt32(abyPageFeature + nOffsetFirstValInPage,
+                                 iCurFeatureInPage);
                     nComp = COMPARE(sValue.Integer, nVal);
                     break;
                 }
 
                 case FGFT_FLOAT32:
                 {
-                    float fVal = GetFloat32(abyPageFeature + nOffsetFirstValInPage,
-                                           iCurFeatureInPage);
+                    const float fVal =
+                        GetFloat32(abyPageFeature + nOffsetFirstValInPage,
+                                   iCurFeatureInPage);
                     nComp = COMPARE(sValue.Real, fVal);
                     break;
                 }
@@ -1353,8 +1364,9 @@ int FileGDBIndexIterator::GetNextRow()
                 case FGFT_FLOAT64:
                 case FGFT_DATETIME:
                 {
-                    double dfVal = GetFloat64(abyPageFeature + nOffsetFirstValInPage,
-                                           iCurFeatureInPage);
+                    const double dfVal =
+                        GetFloat64(abyPageFeature + nOffsetFirstValInPage,
+                                   iCurFeatureInPage);
                     nComp = COMPARE(sValue.Real, dfVal);
                     break;
                 }
@@ -1387,12 +1399,12 @@ int FileGDBIndexIterator::GetNextRow()
                 }
 
                 default:
-                    CPLAssert(FALSE);
+                    CPLAssert(false);
                     nComp = 0;
                     break;
             }
 
-            bMatch = FALSE;
+            bMatch = false;
             CPL_IGNORE_RET_VAL(bMatch);
             switch( eOp )
             {
@@ -1402,7 +1414,7 @@ int FileGDBIndexIterator::GetNextRow()
                         bEOF = TRUE;
                         return -1;
                     }
-                    bMatch = TRUE;
+                    bMatch = true;
                     break;
 
                 case FGSO_LE:
@@ -1411,7 +1423,7 @@ int FileGDBIndexIterator::GetNextRow()
                         bEOF = TRUE;
                         return -1;
                     }
-                    bMatch = TRUE;
+                    bMatch = true;
                     break;
 
                 case FGSO_EQ:
@@ -1420,26 +1432,27 @@ int FileGDBIndexIterator::GetNextRow()
                         bEOF = TRUE;
                         return -1;
                     }
-                    bMatch = ( nComp == 0 );
+                    bMatch = nComp == 0;
                     break;
 
                 case FGSO_GE:
-                    bMatch = ( nComp <= 0 );
+                    bMatch = nComp <= 0;
                     break;
 
                 case FGSO_GT:
-                    bMatch = ( nComp < 0 );
+                    bMatch = nComp < 0;
                     break;
 
                 default:
-                    CPLAssert(FALSE);
+                    CPLAssert(false);
                     break;
             }
         }
 
         if( bMatch )
         {
-            GUInt32 nFID = GetUInt32(abyPageFeature + 12, iCurFeatureInPage);
+            const GUInt32 nFID =
+                GetUInt32(abyPageFeature + 12, iCurFeatureInPage);
             if( bAscending )
                 iCurFeatureInPage ++;
             else
@@ -1593,7 +1606,8 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
     {
         case FGFT_INT16:
         {
-            GInt16 nVal = GetInt16(l_abyPage + nOffsetFirstValInPage, iFeature);
+            const GInt16 nVal =
+                GetInt16(l_abyPage + nOffsetFirstValInPage, iFeature);
             psField->Integer = nVal;
             eOutType = OFTInteger;
             return psField;
@@ -1601,7 +1615,8 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
 
         case FGFT_INT32:
         {
-            GInt32 nVal = GetInt32(l_abyPage + nOffsetFirstValInPage, iFeature);
+            const GInt32 nVal =
+                GetInt32(l_abyPage + nOffsetFirstValInPage, iFeature);
             psField->Integer = nVal;
             eOutType = OFTInteger;
             return psField;
@@ -1609,7 +1624,8 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
 
         case FGFT_FLOAT32:
         {
-            float fVal = GetFloat32(l_abyPage + nOffsetFirstValInPage, iFeature);
+            const float fVal =
+                GetFloat32(l_abyPage + nOffsetFirstValInPage, iFeature);
             psField->Real = fVal;
             eOutType = OFTReal;
             return psField;
@@ -1617,7 +1633,8 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
 
         case FGFT_FLOAT64:
         {
-            double dfVal = GetFloat64(l_abyPage + nOffsetFirstValInPage, iFeature);
+            const double dfVal =
+                GetFloat64(l_abyPage + nOffsetFirstValInPage, iFeature);
             psField->Real = dfVal;
             eOutType = OFTReal;
             return psField;
@@ -1625,7 +1642,8 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
 
         case FGFT_DATETIME:
         {
-            double dfVal = GetFloat64(l_abyPage + nOffsetFirstValInPage, iFeature);
+            const double dfVal =
+                GetFloat64(l_abyPage + nOffsetFirstValInPage, iFeature);
             FileGDBDoubleDateToOGRDate(dfVal, psField);
             eOutType = OFTDateTime;
             return psField;
@@ -1633,7 +1651,7 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
 
         case FGFT_STRING:
         {
-            wchar_t awsVal[MAX_CAR_COUNT_STR+1];
+            wchar_t awsVal[MAX_CAR_COUNT_STR+1] = { 0 };
             for(int j=0;j<nStrLen;j++)
             {
                 GUInt16 nCh = GetUInt16(l_abyPage + nOffsetFirstValInPage +
@@ -1663,7 +1681,7 @@ const OGRField* FileGDBIndexIterator::GetMinMaxValue(OGRField* psField,
         }
 
         default:
-            CPLAssert(FALSE);
+            CPLAssert(false);
             break;
     }
     return NULL;
@@ -1810,7 +1828,7 @@ int FileGDBIndexIterator::GetMinMaxSumCount(double& dfMin, double& dfMax,
             break;
         }
         default:
-            CPLAssert(FALSE);
+            CPLAssert(false);
             break;
     }
 
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
index c755488..42ef7db 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: filegdbtable.cpp 34423 2016-06-25 10:03:48Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB tables
@@ -31,9 +30,10 @@
 #include "cpl_port.h"
 #include "cpl_string.h"
 #include "cpl_time.h"
+#include "ogr_api.h" // for OGR_RawField_xxxxx()
 #include "ogrpgeogeometry.h" /* SHPT_ constants and OGRCreateFromMultiPatchPart() */
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: filegdbtable.cpp 37648 2017-03-08 02:32:09Z rouault $");
 
 #define TEST_BIT(ar, bit)                       (ar[(bit) / 8] & (1 << ((bit) % 8)))
 #define BIT_ARRAY_SIZE_IN_BYTES(bitsize)        (((bitsize)+7)/8)
@@ -48,6 +48,14 @@ CPL_CVSID("$Id");
 /*       or for 4 ReadVarUInt64NoCheck */
 #define ZEROES_AFTER_END_OF_BUFFER      4
 
+static const GUInt32 EXT_SHAPE_Z_FLAG     = 0x80000000U;
+static const GUInt32 EXT_SHAPE_M_FLAG     = 0x40000000U;
+static const GUInt32 EXT_SHAPE_CURVE_FLAG = 0x20000000U;
+
+static const GUInt32 EXT_SHAPE_SEGMENT_ARC = 1;
+static const GUInt32 EXT_SHAPE_SEGMENT_BEZIER = 4;
+static const GUInt32 EXT_SHAPE_SEGMENT_ELLIPSE = 5;
+
 namespace OpenFileGDB
 {
 
@@ -110,6 +118,7 @@ void FileGDBTable::Init()
     nFilterYMin = 0;
     nFilterYMax = 0;
     osObjectIdColName = "";
+    achGUIDBuffer[0] = 0;
     nChSaved = -1;
     pabyTablXBlockMap = NULL;
     nCountBlocksBeforeIBlockIdx = 0;
@@ -230,19 +239,25 @@ static int ReadVarUInt(GByte*& pabyIter, GByte* pabyEnd, OutType& nOutVal)
 
 struct ControleTypeVerboseErrorTrue
 {
+    // cppcheck-suppress unusedStructMember
     static const EMULATED_BOOL check_bounds = true;
+    // cppcheck-suppress unusedStructMember
     static const EMULATED_BOOL verbose_error = true;
 };
 
 struct ControleTypeVerboseErrorFalse
 {
+    // cppcheck-suppress unusedStructMember
     static const EMULATED_BOOL check_bounds = true;
+    // cppcheck-suppress unusedStructMember
     static const EMULATED_BOOL verbose_error = false;
 };
 
 struct ControleTypeNone
 {
+    // cppcheck-suppress unusedStructMember
     static const EMULATED_BOOL check_bounds = false;
+    // cppcheck-suppress unusedStructMember
     static const EMULATED_BOOL verbose_error = false;
 };
 
@@ -359,7 +374,7 @@ int FileGDBTable::IsLikelyFeatureAtOffset(vsi_l_offset nOffset,
             case FGFT_UUID_2: nRequiredLength += UUID_SIZE_IN_BYTES; break;
 
             default:
-                CPLAssert(FALSE);
+                CPLAssert(false);
                 break;
         }
     }
@@ -434,7 +449,7 @@ int FileGDBTable::IsLikelyFeatureAtOffset(vsi_l_offset nOffset,
                 case FGFT_UUID_2: nRequiredLength += UUID_SIZE_IN_BYTES; break;
 
                 default:
-                    CPLAssert(FALSE);
+                    CPLAssert(false);
                     break;
             }
             if( nRequiredLength > nRowBlobLength )
@@ -712,12 +727,13 @@ int FileGDBTable::Open(const char* pszFilename,
 #endif
     }
 
-    nOffsetFieldDesc = GetUInt32(abyHeader + 32, 0);
+    nOffsetFieldDesc = GetUInt32(abyHeader + 32, 0) |
+            (static_cast<GUIntBig>(GetUInt32(abyHeader + 36, 0)) << 32);
 
 #ifdef DEBUG_VERBOSE
     if( nOffsetFieldDesc != 40 )
     {
-        CPLDebug("OpenFileGDB", "%s: nOffsetFieldDesc=%d",
+        CPLDebug("OpenFileGDB", "%s: nOffsetFieldDesc=" CPL_FRMT_GUIB,
                  pszFilename, nOffsetFieldDesc);
     }
 #endif
@@ -824,8 +840,7 @@ int FileGDBTable::Open(const char* pszFilename,
             }
 
             OGRField sDefault;
-            sDefault.Set.nMarker1 = OGRUnsetMarker;
-            sDefault.Set.nMarker2 = OGRUnsetMarker;
+            OGR_RawField_SetUnset(&sDefault);
             if( (flags & 4) != 0 )
             {
                 /* Default value */
@@ -843,11 +858,13 @@ int FileGDBTable::Open(const char* pszFilename,
                     {
                         sDefault.Integer = GetInt16(pabyIter, 0);
                         sDefault.Set.nMarker2 = 0;
+                        sDefault.Set.nMarker3 = 0;
                     }
                     else if( eType == FGFT_INT32 && defaultValueLength == 4 )
                     {
                         sDefault.Integer = GetInt32(pabyIter, 0);
                         sDefault.Set.nMarker2 = 0;
+                        sDefault.Set.nMarker3 = 0;
                     }
                     else if( eType == FGFT_FLOAT32 && defaultValueLength == 4 )
                     {
@@ -859,7 +876,7 @@ int FileGDBTable::Open(const char* pszFilename,
                     }
                     else if( eType == FGFT_DATETIME && defaultValueLength == 8 )
                     {
-                        double dfVal = GetFloat64(pabyIter, 0);
+                        const double dfVal = GetFloat64(pabyIter, 0);
                         FileGDBDoubleDateToOGRDate(dfVal, &sDefault);
                     }
                 }
@@ -870,7 +887,7 @@ int FileGDBTable::Open(const char* pszFilename,
 
             if( eType == FGFT_OBJECTID )
             {
-                returnErrorIf(osObjectIdColName.size() > 0 );
+                returnErrorIf(!osObjectIdColName.empty() );
                 osObjectIdColName = osName;
                 continue;
             }
@@ -950,7 +967,7 @@ int FileGDBTable::Open(const char* pszFilename,
     #define READ_DOUBLE(field) do { \
         field = GetFloat64(pabyIter, 0); \
         pabyIter += sizeof(double); \
-        nRemaining -= sizeof(double); } while(0)
+        nRemaining -= sizeof(double); } while( false )
 
                 READ_DOUBLE(poField->dfXOrigin);
                 READ_DOUBLE(poField->dfYOrigin);
@@ -1033,7 +1050,7 @@ int FileGDBTable::Open(const char* pszFilename,
             }
         }
 
-        nCountNullableFields += apoFields[apoFields.size()-1]->bNullable;
+        nCountNullableFields += apoFields.back()->bNullable;
     }
     nNullableFieldsSizeInBytes = BIT_ARRAY_SIZE_IN_BYTES(nCountNullableFields);
 
@@ -1176,7 +1193,7 @@ vsi_l_offset FileGDBTable::GetOffsetInTableForRow(int iRow)
 #ifdef DEBUG_VERBOSE
     if( iRow == 0 && nOffset != 0 &&
         nOffset != nOffsetHeaderEnd && nOffset != nOffsetHeaderEnd + 4 )
-        CPLDebug("OpenFileGDB", "%s: first feature offset = " CPL_FRMT_GUIB ". Expected %d",
+        CPLDebug("OpenFileGDB", "%s: first feature offset = " CPL_FRMT_GUIB ". Expected " CPL_FRMT_GUIB,
                  osFilename.c_str(), nOffset, nOffsetHeaderEnd);
 #endif
 
@@ -1252,7 +1269,7 @@ int FileGDBTable::SelectRow(int iRow)
             nRowBlobLength = (GUInt32)(-(int)nRowBlobLength);
         }
 
-        if( !(apoFields.size() == 0 && nRowBlobLength == 0) )
+        if( !(apoFields.empty() && nRowBlobLength == 0) )
         {
             /* CPLDebug("OpenFileGDB", "nRowBlobLength = %u", nRowBlobLength); */
             returnErrorAndCleanupIf(
@@ -1392,7 +1409,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
             case FGFT_UUID_2: nLength = UUID_SIZE_IN_BYTES; break;
 
             default:
-                CPLAssert(FALSE);
+                CPLAssert(false);
                 break;
         }
 
@@ -1524,7 +1541,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
             }
 
             /* Number of days since 1899/12/30 00:00:00 */
-            double dfVal = GetFloat64(pabyIterVals, 0);
+            const double dfVal = GetFloat64(pabyIterVals, 0);
 
             FileGDBDoubleDateToOGRDate(dfVal, &sCurField);
             /* eCurFieldType = OFTDateTime; */
@@ -1576,8 +1593,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
             /* GInt32 nVal = GetInt32(pabyIterVals, 0); */
 
             /* eCurFieldType = OFTBinary; */
-            sCurField.Set.nMarker1 = OGRUnsetMarker;
-            sCurField.Set.nMarker2 = OGRUnsetMarker;
+            OGR_RawField_SetUnset(&sCurField);
 
             pabyIterVals += sizeof(GInt32);
             /* CPLDebug("OpenFileGDB", "Field %d, row %d: %d", iCol, nCurRow, sCurField.Integer); */
@@ -1612,7 +1628,7 @@ const OGRField* FileGDBTable::GetFieldValue(int iCol)
         }
 
         default:
-            CPLAssert(FALSE);
+            CPLAssert(false);
             break;
     }
 
@@ -1757,7 +1773,7 @@ void FileGDBTable::InstallFilterEnvelope(const OGREnvelope* psFilterEnvelope)
         else
             nFilterXMin = 0;
         if( psFilterEnvelope->MaxX - poGeomField->dfXOrigin <
-                                        MAX_GUINTBIG / poGeomField->dfXYScale )
+                                        static_cast<double>(MAX_GUINTBIG) / poGeomField->dfXYScale )
             nFilterXMax = (GUIntBig)(0.5 + (psFilterEnvelope->MaxX -
                             poGeomField->dfXOrigin) * poGeomField->dfXYScale);
         else
@@ -1768,7 +1784,7 @@ void FileGDBTable::InstallFilterEnvelope(const OGREnvelope* psFilterEnvelope)
         else
             nFilterYMin = 0;
         if( psFilterEnvelope->MaxY - poGeomField->dfYOrigin <
-                                        MAX_GUINTBIG / poGeomField->dfXYScale )
+                                        static_cast<double>(MAX_GUINTBIG) / poGeomField->dfXYScale )
             nFilterYMax = (GUIntBig)(0.5 + (psFilterEnvelope->MaxY -
                                 poGeomField->dfYOrigin) * poGeomField->dfXYScale);
         else
@@ -1847,7 +1863,7 @@ int FileGDBTable::GetFeatureExtent(const OGRField* psField,
         case SHPT_GENERALPOLYLINE:
         case SHPT_GENERALPOLYGON:
         {
-            nToSkip = 1 + ((nGeomType & 0x20000000) ? 1 : 0);
+            nToSkip = 1 + ((nGeomType & EXT_SHAPE_CURVE_FLAG) ? 1 : 0);
             break;
         }
 
@@ -1917,7 +1933,7 @@ int FileGDBTable::DoesGeometryIntersectsFilterEnvelope(const OGRField* psField)
                 return FALSE;
             ReadVarUInt64NoCheck(pabyCur, y);
             y --;
-            return( y >= nFilterYMin && y <= nFilterYMax );
+            return y >= nFilterYMin && y <= nFilterYMax;
         }
 
         case SHPT_MULTIPOINTZM:
@@ -1944,7 +1960,7 @@ int FileGDBTable::DoesGeometryIntersectsFilterEnvelope(const OGRField* psField)
         case SHPT_GENERALPOLYLINE:
         case SHPT_GENERALPOLYGON:
         {
-            nToSkip = 1 + ((nGeomType & 0x20000000) ? 1 : 0);
+            nToSkip = 1 + ((nGeomType & EXT_SHAPE_CURVE_FLAG) ? 1 : 0);
             break;
         }
 
@@ -1986,12 +2002,14 @@ int FileGDBTable::DoesGeometryIntersectsFilterEnvelope(const OGRField* psField)
 /*                           FileGDBField()                             */
 /************************************************************************/
 
-FileGDBField::FileGDBField(FileGDBTable* poParentIn) :
-    poParent(poParentIn), eType(FGFT_UNDEFINED), bNullable(FALSE),
-    nMaxWidth(0), poIndex(NULL)
+FileGDBField::FileGDBField( FileGDBTable* poParentIn ) :
+    poParent(poParentIn),
+    eType(FGFT_UNDEFINED),
+    bNullable(FALSE),
+    nMaxWidth(0),
+    poIndex(NULL)
 {
-    sDefault.Set.nMarker1 = OGRUnsetMarker;
-    sDefault.Set.nMarker2 = OGRUnsetMarker;
+    OGR_RawField_SetUnset(&sDefault);
 }
 
 /************************************************************************/
@@ -2001,12 +2019,11 @@ FileGDBField::FileGDBField(FileGDBTable* poParentIn) :
 FileGDBField::~FileGDBField()
 {
     if( eType == FGFT_STRING &&
-        !(sDefault.Set.nMarker1 == OGRUnsetMarker &&
-          sDefault.Set.nMarker2 == OGRUnsetMarker) )
+        !OGR_RawField_IsUnset(&sDefault) &&
+        !OGR_RawField_IsNull(&sDefault) )
         CPLFree(sDefault.String);
 }
 
-
 /************************************************************************/
 /*                            HasIndex()                                */
 /************************************************************************/
@@ -2031,14 +2048,26 @@ FileGDBIndex *FileGDBField::GetIndex()
 /*                           FileGDBGeomField()                         */
 /************************************************************************/
 
-FileGDBGeomField::FileGDBGeomField(FileGDBTable* poParentIn) :
-    FileGDBField(poParentIn), bHasZ(FALSE), bHasM(FALSE),
-    dfXOrigin(0.0), dfYOrigin(0.0), dfXYScale(0.0), dfMOrigin(0.0),
-    dfMScale(0.0), dfZOrigin(0.0), dfZScale(0.0), dfXYTolerance(0.0),
-    dfMTolerance(0.0), dfZTolerance(0.0), dfXMin(0.0), dfYMin(0.0),
-    dfXMax(0.0), dfYMax(0.0), bHas3D(FALSE)
-{
-}
+FileGDBGeomField::FileGDBGeomField( FileGDBTable* poParentIn ) :
+    FileGDBField(poParentIn),
+    bHasZ(FALSE),
+    bHasM(FALSE),
+    dfXOrigin(0.0),
+    dfYOrigin(0.0),
+    dfXYScale(0.0),
+    dfMOrigin(0.0),
+    dfMScale(0.0),
+    dfZOrigin(0.0),
+    dfZScale(0.0),
+    dfXYTolerance(0.0),
+    dfMTolerance(0.0),
+    dfZTolerance(0.0),
+    dfXMin(0.0),
+    dfYMin(0.0),
+    dfXMax(0.0),
+    dfYMax(0.0),
+    bHas3D(FALSE)
+{}
 
 /************************************************************************/
 /*                      FileGDBOGRGeometryConverterImpl                 */
@@ -2053,12 +2082,13 @@ class FileGDBOGRGeometryConverterImpl CPL_FINAL : public FileGDBOGRGeometryConve
         int                          bUseOrganize;
 #endif
 
-        int                         ReadPartDefs( GByte*& pabyCur,
+        bool                        ReadPartDefs( GByte*& pabyCur,
                                                   GByte* pabyEnd,
                                                   GUInt32& nPoints,
                                                   GUInt32& nParts,
-                                                  int bHasCurveDesc,
-                                                  int bIsMultiPatch );
+                                                  GUInt32& nCurves,
+                                                  bool bHasCurveDesc,
+                                                  bool bIsMultiPatch );
         template <class XYSetter> int ReadXYArray(XYSetter& setter,
                                                   GByte*& pabyCur,
                                                   GByte* pabyEnd,
@@ -2076,12 +2106,18 @@ class FileGDBOGRGeometryConverterImpl CPL_FINAL : public FileGDBOGRGeometryConve
                                                 GUInt32 nPoints,
                                                 GIntBig& dm);
 
+        OGRGeometry* CreateCurveGeometry(
+                  GUInt32 nBaseShapeType,
+                  GUInt32 nParts, GUInt32 nPoints, GUInt32 nCurves,
+                  bool bHasZ, bool bHasM,
+                  GByte*& pabyCur, GByte* pabyEnd );
+
     public:
-                                        FileGDBOGRGeometryConverterImpl(
+       explicit                         FileGDBOGRGeometryConverterImpl(
                                             const FileGDBGeomField* poGeomField);
        virtual                         ~FileGDBOGRGeometryConverterImpl();
 
-       virtual OGRGeometry*             GetAsGeometry(const OGRField* psField);
+       virtual OGRGeometry*             GetAsGeometry(const OGRField* psField) override;
 };
 
 /************************************************************************/
@@ -2089,15 +2125,15 @@ class FileGDBOGRGeometryConverterImpl CPL_FINAL : public FileGDBOGRGeometryConve
 /************************************************************************/
 
 FileGDBOGRGeometryConverterImpl::FileGDBOGRGeometryConverterImpl(
-                                    const FileGDBGeomField* poGeomFieldIn) :
-                                                poGeomField(poGeomFieldIn)
-{
-    panPointCount = NULL;
-    nPointCountMax = 0;
+    const FileGDBGeomField* poGeomFieldIn) :
+    poGeomField(poGeomFieldIn),
+    panPointCount(NULL),
+    nPointCountMax(0)
 #ifdef ASSUME_INNER_RINGS_IMMEDIATELY_AFTER_OUTER_RING
-    bUseOrganize = CPLGetConfigOption("OGR_ORGANIZE_POLYGONS", NULL) != NULL;
+    ,
+    bUseOrganize(CPLGetConfigOption("OGR_ORGANIZE_POLYGONS", NULL) != NULL)
 #endif
-}
+{}
 
 /************************************************************************/
 /*                 ~FileGDBOGRGeometryConverter()                       */
@@ -2112,29 +2148,37 @@ FileGDBOGRGeometryConverterImpl::~FileGDBOGRGeometryConverterImpl()
 /*                          ReadPartDefs()                              */
 /************************************************************************/
 
-int FileGDBOGRGeometryConverterImpl::ReadPartDefs( GByte*& pabyCur,
+bool FileGDBOGRGeometryConverterImpl::ReadPartDefs( GByte*& pabyCur,
                                 GByte* pabyEnd,
                                 GUInt32& nPoints,
                                 GUInt32& nParts,
-                                int bHasCurveDesc,
-                                int bIsMultiPatch )
+                                GUInt32& nCurves,
+                                bool bHasCurveDesc,
+                                bool bIsMultiPatch )
 {
-    const int errorRetValue = FALSE;
+    const bool errorRetValue = false;
     returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nPoints));
     if( nPoints == 0 )
     {
         nParts = 0;
-        return TRUE;
+        nCurves = 0;
+        return true;
     }
     returnErrorIf(nPoints > (GUInt32)(pabyEnd - pabyCur) );
     if( bIsMultiPatch )
         returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd) );
     returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nParts));
     returnErrorIf(nParts > (GUInt32)(pabyEnd - pabyCur));
+    returnErrorIf(nParts > static_cast<GUInt32>(INT_MAX) / sizeof(GUInt32));
     if( bHasCurveDesc )
-        returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd) );
+    {
+        returnErrorIf(!ReadVarUInt32(pabyCur, pabyEnd, nCurves) );
+        returnErrorIf(nCurves > (GUInt32)(pabyEnd - pabyCur));
+    }
+    else
+        nCurves = 0;
     if( nParts == 0 )
-        return TRUE;
+        return true;
     GUInt32 i;
     returnErrorIf(!SkipVarUInt(pabyCur, pabyEnd, 4) );
     if( nParts > nPointCountMax )
@@ -2157,7 +2201,7 @@ int FileGDBOGRGeometryConverterImpl::ReadPartDefs( GByte*& pabyCur,
     returnErrorIf(nSumNPartsM1 > nPoints );
     panPointCount[nParts-1] = (GUInt32)(nPoints - nSumNPartsM1);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -2184,7 +2228,8 @@ class XYLineStringSetter
 {
         OGRRawPoint* paoPoints;
     public:
-        XYLineStringSetter(OGRRawPoint* paoPointsIn) : paoPoints(paoPointsIn) {}
+        explicit XYLineStringSetter(OGRRawPoint* paoPointsIn) :
+                                            paoPoints(paoPointsIn) {}
 
         void set(int i, double dfX, double dfY)
         {
@@ -2201,7 +2246,8 @@ class XYMultiPointSetter
 {
         OGRMultiPoint* poMPoint;
     public:
-        XYMultiPointSetter(OGRMultiPoint* poMPointIn) : poMPoint(poMPointIn) {}
+        explicit XYMultiPointSetter(OGRMultiPoint* poMPointIn) :
+                                                poMPoint(poMPointIn) {}
 
         void set(int i, double dfX, double dfY)
         {
@@ -2268,7 +2314,7 @@ class ZLineStringSetter
 {
         OGRLineString* poLS;
     public:
-        ZLineStringSetter(OGRLineString* poLSIn) : poLS(poLSIn) {}
+        explicit ZLineStringSetter(OGRLineString* poLSIn) : poLS(poLSIn) {}
 
         void set(int i, double dfZ)
         {
@@ -2284,7 +2330,8 @@ class ZMultiPointSetter
 {
         OGRMultiPoint* poMPoint;
     public:
-        ZMultiPointSetter(OGRMultiPoint* poMPointIn) : poMPoint(poMPointIn) {}
+        explicit ZMultiPointSetter(OGRMultiPoint* poMPointIn) :
+                                                    poMPoint(poMPointIn) {}
 
         void set(int i, double dfZ)
         {
@@ -2300,7 +2347,8 @@ class FileGDBArraySetter
 {
         double* padfValues;
     public:
-        FileGDBArraySetter(double* padfValuesIn) : padfValues(padfValuesIn) {}
+        explicit FileGDBArraySetter(double* padfValuesIn) :
+                                                padfValues(padfValuesIn) {}
 
         void set(int i, double dfValue)
         {
@@ -2338,7 +2386,7 @@ class MLineStringSetter
 {
         OGRLineString* poLS;
     public:
-        MLineStringSetter(OGRLineString* poLSIn) : poLS(poLSIn) {}
+        explicit MLineStringSetter(OGRLineString* poLSIn) : poLS(poLSIn) {}
 
         void set(int i, double dfM)
         {
@@ -2354,7 +2402,8 @@ class MMultiPointSetter
 {
         OGRMultiPoint* poMPoint;
     public:
-        MMultiPointSetter(OGRMultiPoint* poMPointIn) : poMPoint(poMPointIn) {}
+        explicit MMultiPointSetter(OGRMultiPoint* poMPointIn) :
+                                                    poMPoint(poMPointIn) {}
 
         void set(int i, double dfM)
         {
@@ -2385,6 +2434,172 @@ template <class MSetter> int FileGDBOGRGeometryConverterImpl::ReadMArray(MSetter
 }
 
 /************************************************************************/
+/*                          CreateCurveGeometry()                       */
+/************************************************************************/
+
+class XYBufferSetter
+{
+        GByte* pabyBuffer;
+    public:
+        explicit XYBufferSetter(GByte* pabyBufferIn) :
+                                                    pabyBuffer(pabyBufferIn) {}
+
+        void set(int i, double dfX, double dfY)
+        {
+            CPL_LSBPTR64(&dfX);
+            memcpy( pabyBuffer + 16 * i, &dfX, 8 );
+            CPL_LSBPTR64(&dfY);
+            memcpy( pabyBuffer + 16 * i + 8, &dfY, 8 );
+        }
+};
+
+class ZOrMBufferSetter
+{
+        GByte* pabyBuffer;
+    public:
+        explicit ZOrMBufferSetter(GByte* pabyBufferIn) :
+                                                    pabyBuffer(pabyBufferIn) {}
+
+        void set(int i, double dfValue)
+        {
+            CPL_LSBPTR64(&dfValue);
+            memcpy( pabyBuffer + 8 * i, &dfValue, 8 );
+        }
+};
+
+/* We first create an extended shape buffer from the compressed stream */
+/* and finally use OGRCreateFromShapeBin() to make a geometry from it */
+
+OGRGeometry* FileGDBOGRGeometryConverterImpl::CreateCurveGeometry(
+                  GUInt32 nBaseShapeType,
+                  GUInt32 nParts, GUInt32 nPoints, GUInt32 nCurves,
+                  bool bHasZ, bool bHasM,
+                  GByte*& pabyCur, GByte* pabyEnd )
+{
+    OGRGeometry* errorRetValue = NULL;
+    GUInt32 i;
+    const int nDims = 2 + (bHasZ ? 1 : 0) + (bHasM ? 1 : 0);
+    GIntBig nMaxSize64 = 44 + 4 * static_cast<GUIntBig>(nParts) +
+                         8 * nDims * static_cast<GUIntBig>(nPoints);
+    nMaxSize64 += 4; // nCurves
+    nMaxSize64 += static_cast<GUIntBig>(nCurves) * (4 + /* start index */
+                            4 + /* curve type */
+                            44 /* size of ellipse struct */ );
+    nMaxSize64 += ((bHasZ ? 1 : 0) + (bHasM ? 1 : 0)) * 16; // space for bounding boxes
+    if( nMaxSize64 >= INT_MAX )
+    {
+        returnError();
+    }
+    const int nMaxSize = static_cast<int>(nMaxSize64);
+    GByte* pabyExtShapeBuffer = (GByte*) VSI_MALLOC_VERBOSE(nMaxSize);
+    if( pabyExtShapeBuffer == NULL )
+    {
+        VSIFree(pabyExtShapeBuffer);
+        returnError();
+    }
+    GUInt32 nShapeType = nBaseShapeType | EXT_SHAPE_CURVE_FLAG;
+    if( bHasZ ) nShapeType |= EXT_SHAPE_Z_FLAG;
+    if( bHasM ) nShapeType |= EXT_SHAPE_M_FLAG;
+    GUInt32 nTmp;
+    nTmp = CPL_LSBWORD32(nShapeType);
+    memcpy( pabyExtShapeBuffer, &nTmp, 4 );
+    memset( pabyExtShapeBuffer + 4, 0, 32 ); /* bbox: unused */
+    nTmp = CPL_LSBWORD32(nParts);
+    memcpy( pabyExtShapeBuffer + 36, &nTmp, 4 );
+    nTmp = CPL_LSBWORD32(nPoints);
+    memcpy( pabyExtShapeBuffer + 40, &nTmp, 4 );
+    GUInt32 nIdx = 0;
+    for( i=0; i<nParts; i++ )
+    {
+        nTmp = CPL_LSBWORD32(nIdx);
+        nIdx += panPointCount[i];
+        memcpy( pabyExtShapeBuffer + 44 + 4 * i, &nTmp, 4 );
+    }
+    int nOffset = 44 + 4 * nParts;
+    GIntBig dx = 0;
+    GIntBig dy = 0;
+    XYBufferSetter arraySetter(pabyExtShapeBuffer + nOffset);
+    if( !ReadXYArray<XYBufferSetter>(arraySetter,
+                    pabyCur, pabyEnd, nPoints, dx, dy) )
+    {
+        VSIFree(pabyExtShapeBuffer);
+        returnError();
+    }
+    nOffset += 16 * nPoints;
+
+    if( bHasZ )
+    {
+        memset( pabyExtShapeBuffer + nOffset, 0, 16 ); /* bbox: unused */
+        nOffset += 16;
+        GIntBig dz = 0;
+        ZOrMBufferSetter arrayzSetter(pabyExtShapeBuffer + nOffset);
+        if( !ReadZArray<ZOrMBufferSetter>(arrayzSetter,
+                        pabyCur, pabyEnd, nPoints, dz) )
+        {
+            VSIFree(pabyExtShapeBuffer);
+            returnError();
+        }
+        nOffset += 8 * nPoints;
+    }
+    if( bHasM )
+    {
+        memset( pabyExtShapeBuffer + nOffset, 0, 16 ); /* bbox: unused */
+        nOffset += 16;
+        ZOrMBufferSetter arraymSetter(pabyExtShapeBuffer + nOffset);
+        GIntBig dm = 0;
+        if( !ReadMArray<ZOrMBufferSetter>(arraymSetter,
+                        pabyCur, pabyEnd, nPoints, dm) )
+        {
+            VSIFree(pabyExtShapeBuffer);
+            returnError();
+        }
+        nOffset += 8 * nPoints;
+    }
+
+    nTmp = CPL_LSBWORD32(nCurves);
+    memcpy( pabyExtShapeBuffer + nOffset, &nTmp, 4 );
+    nOffset += 4;
+    for( i=0; i<nCurves; i++ )
+    {
+        // start index
+        returnErrorAndCleanupIf( !ReadVarUInt32(pabyCur, pabyEnd, nTmp),
+                                 VSIFree(pabyExtShapeBuffer) );
+        nTmp = CPL_LSBWORD32(nTmp);
+        memcpy( pabyExtShapeBuffer + nOffset, &nTmp, 4 );
+        nOffset += 4;
+
+        GUInt32 nCurveType;
+        returnErrorAndCleanupIf( !ReadVarUInt32(pabyCur, pabyEnd, nCurveType),
+                                 VSIFree(pabyExtShapeBuffer) );
+        nTmp = CPL_LSBWORD32(nCurveType);
+        memcpy( pabyExtShapeBuffer + nOffset, &nTmp, 4 );
+        nOffset += 4;
+
+        int nStructureSize = 0;
+        if( nCurveType == EXT_SHAPE_SEGMENT_ARC )
+            nStructureSize = 2 * 8 + 4;
+        else if( nCurveType == EXT_SHAPE_SEGMENT_BEZIER )
+            nStructureSize = 4 * 8;
+        else if( nCurveType == EXT_SHAPE_SEGMENT_ELLIPSE )
+            nStructureSize = 5 * 8 + 4;
+        if( nStructureSize == 0 || pabyCur + nStructureSize > pabyEnd )
+        {
+            VSIFree(pabyExtShapeBuffer);
+            returnError();
+        }
+        memcpy( pabyExtShapeBuffer + nOffset, pabyCur, nStructureSize );
+        pabyCur += nStructureSize;
+        nOffset += nStructureSize;
+    }
+    CPLAssert( nOffset <= nMaxSize );
+
+    OGRGeometry* poRet = NULL;
+    OGRCreateFromShapeBin(pabyExtShapeBuffer, &poRet, nOffset);
+    VSIFree(pabyExtShapeBuffer);
+    return poRet;
+}
+
+/************************************************************************/
 /*                          GetAsGeometry()                             */
 /************************************************************************/
 
@@ -2393,14 +2608,14 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
     OGRGeometry* errorRetValue = NULL;
     GByte* pabyCur = psField->Binary.paData;
     GByte* pabyEnd = pabyCur + psField->Binary.nCount;
-    GUInt32 nGeomType, i, nPoints, nParts;
+    GUInt32 nGeomType, i, nPoints, nParts, nCurves;
     GUIntBig x, y, z;
     GIntBig dx, dy, dz;
 
     ReadVarUInt32NoCheck(pabyCur, nGeomType);
 
-    int bHasZ = (nGeomType & 0x80000000) != 0;
-    bool bHasM = (nGeomType & 0x40000000) != 0;
+    bool bHasZ = (nGeomType & EXT_SHAPE_Z_FLAG) != 0;
+    bool bHasM = (nGeomType & EXT_SHAPE_M_FLAG) != 0;
     switch( (nGeomType & 0xff) )
     {
         case SHPT_NULL:
@@ -2408,8 +2623,8 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
 
         case SHPT_POINTZ:
         case SHPT_POINTZM:
-            bHasZ = TRUE; /* go on */
-            // CPL_FALLTHROUGH
+            bHasZ = true; /* go on */
+            CPL_FALLTHROUGH
         case SHPT_POINT:
         case SHPT_POINTM:
         case SHPT_GENERALPOINT:
@@ -2417,21 +2632,25 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
             if( nGeomType == SHPT_POINTM || nGeomType == SHPT_POINTZM )
                 bHasM = true;
 
-            double dfX, dfY, dfZ;
             ReadVarUInt64NoCheck(pabyCur, x);
             ReadVarUInt64NoCheck(pabyCur, y);
 
-            dfX = (x - 1) / poGeomField->GetXYScale() + poGeomField->GetXOrigin();
-            dfY = (y - 1) / poGeomField->GetXYScale() + poGeomField->GetYOrigin();
+            const double dfX =
+                (x - 1) / poGeomField->GetXYScale() + poGeomField->GetXOrigin();
+            const double dfY =
+                (y - 1) / poGeomField->GetXYScale() + poGeomField->GetYOrigin();
+            double dfZ = 0.0;
             if( bHasZ )
             {
                 ReadVarUInt64NoCheck(pabyCur, z);
                 dfZ = (z - 1) / poGeomField->GetZScale() + poGeomField->GetZOrigin();
                 if( bHasM )
                 {
-                    GUIntBig m;
+                    GUIntBig m = 0;
                     ReadVarUInt64NoCheck(pabyCur, m);
-                    double dfM = (m - 1) / poGeomField->GetMScale() + poGeomField->GetMOrigin();
+                    const double dfM =
+                        (m - 1) /
+                        poGeomField->GetMScale() + poGeomField->GetMOrigin();
                     return new OGRPoint(dfX, dfY, dfZ, dfM);
                 }
                 return new OGRPoint(dfX, dfY, dfZ);
@@ -2439,9 +2658,11 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
             else if( bHasM )
             {
                 OGRPoint* poPoint = new OGRPoint(dfX, dfY);
-                GUIntBig m;
+                GUIntBig m = 0;
                 ReadVarUInt64NoCheck(pabyCur, m);
-                double dfM = (m - 1) / poGeomField->GetMScale() + poGeomField->GetMOrigin();
+                const double dfM =
+                    (m - 1) /
+                    poGeomField->GetMScale() + poGeomField->GetMOrigin();
                 poPoint->setM(dfM);
                 return poPoint;
             }
@@ -2454,8 +2675,8 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
 
         case SHPT_MULTIPOINTZM:
         case SHPT_MULTIPOINTZ:
-            bHasZ = TRUE; /* go on */
-            // CPL_FALLTHROUGH
+            bHasZ = true; /* go on */
+            CPL_FALLTHROUGH
         case SHPT_MULTIPOINT:
         case SHPT_MULTIPOINTM:
         {
@@ -2516,13 +2737,14 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
             }
 
             return poMP;
+            // cppcheck-suppress duplicateBreak
             break;
         }
 
         case SHPT_ARCZ:
         case SHPT_ARCZM:
-            bHasZ = TRUE; /* go on */
-            // CPL_FALLTHROUGH
+            bHasZ = true; /* go on */
+            CPL_FALLTHROUGH
         case SHPT_ARC:
         case SHPT_ARCM:
         case SHPT_GENERALPOLYLINE:
@@ -2530,9 +2752,9 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
             if( nGeomType == SHPT_ARCM || nGeomType == SHPT_ARCZM )
                 bHasM = true;
 
-            returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts,
-                              (nGeomType & 0x20000000) != 0,
-                              FALSE) );
+            returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts, nCurves,
+                              (nGeomType & EXT_SHAPE_CURVE_FLAG) != 0,
+                              false) );
 
             if( nPoints == 0 || nParts == 0 )
             {
@@ -2544,6 +2766,20 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                 return poLS;
             }
 
+            if( nCurves )
+            {
+                GByte* pabyCurBackup = pabyCur;
+                OGRGeometry* poRet = CreateCurveGeometry(
+                    SHPT_GENERALPOLYLINE,
+                    nParts, nPoints, nCurves,
+                    bHasZ, bHasM,
+                    pabyCur, pabyEnd );
+                if( poRet )
+                    return poRet;
+                // In case something went wrong, go on without curves
+                pabyCur = pabyCurBackup;
+            }
+
             OGRMultiLineString* poMLS = NULL;
             FileGDBOGRLineString* poLS = NULL;
             if( nParts > 1 )
@@ -2614,7 +2850,7 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                             poMLS->setMeasured(FALSE);
                         break;
                     }
-                    
+
                     MLineStringSetter lsmSetter(poLS);
                     if( !ReadMArray<MLineStringSetter>(lsmSetter,
                                     pabyCur, pabyEnd,
@@ -2639,8 +2875,8 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
 
         case SHPT_POLYGONZ:
         case SHPT_POLYGONZM:
-            bHasZ = TRUE; /* go on */
-            // CPL_FALLTHROUGH
+            bHasZ = true; /* go on */
+            CPL_FALLTHROUGH
         case SHPT_POLYGON:
         case SHPT_POLYGONM:
         case SHPT_GENERALPOLYGON:
@@ -2648,9 +2884,9 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
             if( nGeomType == SHPT_POLYGONM || nGeomType == SHPT_POLYGONZM )
                 bHasM = true;
 
-            returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts,
-                              (nGeomType & 0x20000000) != 0,
-                              FALSE) );
+            returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts, nCurves,
+                              (nGeomType & EXT_SHAPE_CURVE_FLAG) != 0,
+                              false) );
 
             if( nPoints == 0 || nParts == 0 )
             {
@@ -2662,6 +2898,20 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                 return poPoly;
             }
 
+            if( nCurves )
+            {
+                GByte* pabyCurBackup = pabyCur;
+                OGRGeometry* poRet = CreateCurveGeometry(
+                    SHPT_GENERALPOLYGON,
+                    nParts, nPoints, nCurves,
+                    bHasZ, bHasM,
+                    pabyCur, pabyEnd );
+                if( poRet )
+                    return poRet;
+                // In case something went wrong, go on without curves
+                pabyCur = pabyCurBackup;
+            }
+
             OGRLinearRing** papoRings = new OGRLinearRing*[nParts];
 
             dx = dy = dz = 0;
@@ -2685,6 +2935,8 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                         i--;
                     }
                     delete[] papoRings;
+                    // For some reason things that papoRings is leaking
+                    // cppcheck-suppress memleak
                     returnError();
                 }
             }
@@ -2726,7 +2978,7 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                         }
                         break;
                     }
-                    
+
                     papoRings[i]->setMeasured(TRUE);
 
                     MLineStringSetter lsmSetter(papoRings[i]);
@@ -2742,7 +2994,7 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                 }
             }
 
-            OGRGeometry* poRet;
+            OGRGeometry* poRet = NULL;
             if( nParts == 1 )
             {
                 OGRPolygon* poPoly = new OGRPolygon();
@@ -2814,17 +3066,17 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
 
             delete[] papoRings;
             return poRet;
-
+            // cppcheck-suppress duplicateBreak
             break;
         }
 
         case SHPT_MULTIPATCHM:
         case SHPT_MULTIPATCH:
-            bHasZ = TRUE; /* go on */
-            // CPL_FALLTHROUGH
+            bHasZ = true; /* go on */
+            CPL_FALLTHROUGH
         case SHPT_GENERALMULTIPATCH:
         {
-            returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts, FALSE, TRUE ) );
+            returnErrorIf(!ReadPartDefs(pabyCur, pabyEnd, nPoints, nParts, nCurves, false, true ) );
 
             if( nPoints == 0 || nParts == 0 )
             {
@@ -2834,13 +3086,15 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                 return poPoly;
             }
             int* panPartType = (int*) VSI_MALLOC_VERBOSE(sizeof(int) * nParts);
+            int* panPartStart = (int*) VSI_MALLOC_VERBOSE(sizeof(int) * nParts);
             double* padfXYZ =  (double*) VSI_MALLOC_VERBOSE(3 * sizeof(double) * nPoints);
             double* padfX = padfXYZ;
             double* padfY = padfXYZ + nPoints;
             double* padfZ = padfXYZ + 2 * nPoints;
-            if( panPartType == NULL || padfXYZ == NULL  )
+            if( panPartType == NULL || panPartStart == NULL || padfXYZ == NULL  )
             {
                 VSIFree(panPartType);
+                VSIFree(panPartStart);
                 VSIFree(padfXYZ);
                 returnError();
             }
@@ -2850,6 +3104,7 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                 if( !ReadVarUInt32(pabyCur, pabyEnd, nPartType) )
                 {
                     VSIFree(panPartType);
+                    VSIFree(panPartStart);
                     VSIFree(padfXYZ);
                     returnError();
                 }
@@ -2862,6 +3117,7 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                              pabyCur, pabyEnd, nPoints, dx, dy) )
             {
                 VSIFree(panPartType);
+                VSIFree(panPartStart);
                 VSIFree(padfXYZ);
                 returnError();
             }
@@ -2873,6 +3129,7 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                                 pabyCur, pabyEnd, nPoints, dz) )
                 {
                     VSIFree(panPartType);
+                    VSIFree(panPartStart);
                     VSIFree(padfXYZ);
                     returnError();
                 }
@@ -2882,32 +3139,22 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
                 memset(padfZ, 0, nPoints * sizeof(double));
             }
 
-            OGRMultiPolygon* poMP = new OGRMultiPolygon();
-            poMP->setCoordinateDimension(3);
-            OGRPolygon* poLastPoly = NULL;
-            int iAccPoints = 0;
-            for(i=0;i<nParts;i++)
-            {
-                OGRCreateFromMultiPatchPart(poMP, poLastPoly,
-                                            panPartType[i],
-                                            (int) panPointCount[i],
-                                            padfX + iAccPoints,
-                                            padfY + iAccPoints,
-                                            padfZ + iAccPoints);
-                iAccPoints += (int) panPointCount[i];
-            }
-
-            if( poLastPoly != NULL )
-            {
-                poMP->addGeometryDirectly( poLastPoly );
-                poLastPoly = NULL;
-            }
+            panPartStart[0] = 0;
+            for( i = 1; i < nParts; ++i )
+                panPartStart[i] = panPartStart[i-1] + panPointCount[i-1];
+            OGRGeometry* poRet = OGRCreateFromMultiPatch(
+                                            static_cast<int>(nParts),
+                                            panPartStart,
+                                            panPartType,
+                                            static_cast<int>(nPoints),
+                                            padfX, padfY, padfZ );
 
             VSIFree(panPartType);
+            VSIFree(panPartStart);
             VSIFree(padfXYZ);
 
-            return poMP;
-
+            return poRet;
+            // cppcheck-suppress duplicateBreak
             break;
         }
 
@@ -2921,7 +3168,6 @@ OGRGeometry* FileGDBOGRGeometryConverterImpl::GetAsGeometry(const OGRField* psFi
     return NULL;
 }
 
-
 /************************************************************************/
 /*                           BuildConverter()                           */
 /************************************************************************/
@@ -2947,7 +3193,7 @@ static const struct
     { "esriGeometryLine", wkbMultiLineString },
     { "esriGeometryPolyline", wkbMultiLineString },
     { "esriGeometryPolygon", wkbMultiPolygon },
-    { "esriGeometryMultiPatch", wkbMultiPolygon }
+    { "esriGeometryMultiPatch", wkbUnknown }
 };
 
 OGRwkbGeometryType FileGDBOGRGeometryConverter::GetGeometryTypeFromESRI(
diff --git a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
index 090e5fe..f9be713 100644
--- a/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
+++ b/ogr/ogrsf_frmts/openfilegdb/filegdbtable.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: filegdbtable.h 33024 2016-01-17 16:10:22Z goatbar $
+ * $Id: filegdbtable.h 37648 2017-03-08 02:32:09Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements reading of FileGDB tables
@@ -104,7 +104,7 @@ class FileGDBField
 
     public:
 
-                            FileGDBField(FileGDBTable* poParent);
+        explicit            FileGDBField(FileGDBTable* poParent);
         virtual            ~FileGDBField();
 
         const std::string&  GetName() const { return osName; }
@@ -146,7 +146,7 @@ class FileGDBGeomField: public FileGDBField
         int               bHas3D;
 
     public:
-                          FileGDBGeomField(FileGDBTable* poParent);
+        explicit          FileGDBGeomField(FileGDBTable* poParent);
         virtual          ~FileGDBGeomField() {}
 
         const std::string& GetWKT() const { return osWKT; }
@@ -186,11 +186,10 @@ class FileGDBRasterField: public FileGDBGeomField
         std::string       osRasterColumnName;
 
     public:
-                          FileGDBRasterField(FileGDBTable* poParentIn) : FileGDBGeomField(poParentIn) {}
+        explicit          FileGDBRasterField(FileGDBTable* poParentIn) : FileGDBGeomField(poParentIn) {}
         virtual          ~FileGDBRasterField() {}
 
         const std::string& GetRasterColumnName() const { return osRasterColumnName; }
-
 };
 
 /************************************************************************/
@@ -228,7 +227,7 @@ class FileGDBTable
         int                         bHasReadGDBIndexes;
         std::vector<FileGDBIndex*>  apoIndexes;
 
-        GUInt32                     nOffsetFieldDesc;
+        GUIntBig                    nOffsetFieldDesc;
         GUInt32                     nFieldDescLength;
 
         GUInt32                     nTablxOffsetSize;
@@ -266,7 +265,7 @@ class FileGDBTable
 
         GUIntBig                    nFilterXMin, nFilterXMax, nFilterYMin, nFilterYMax;
 
-        GUInt32                     nOffsetHeaderEnd;
+        GUIntBig                    nOffsetHeaderEnd;
 
         int                         ReadTableXHeader();
         int                         IsLikelyFeatureAtOffset(
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h b/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h
index 8c56200..aace765 100644
--- a/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h
+++ b/ogr/ogrsf_frmts/openfilegdb/ogr_openfilegdb.h
@@ -1,5 +1,5 @@
 /******************************************************************************
-* $Id: ogr_openfilegdb.h 33024 2016-01-17 16:10:22Z goatbar $
+* $Id: ogr_openfilegdb.h 37643 2017-03-07 22:41:04Z rouault $
 *
 * Project:  OpenGIS Simple Features Reference Implementation
 * Purpose:  Implements Open FileGDB OGR driver.
@@ -93,6 +93,7 @@ class OGROpenFileGDBLayer : public OGRLayer
     static void         GetBoundsFuncEx(const void* hFeature,
                                         CPLRectObj* pBounds,
                                         void* pQTUserData);
+    void                TryToDetectMultiPatchKind();
 
 public:
 
@@ -120,29 +121,29 @@ public:
   SPIState              GetSpatialIndexState() const { return m_eSpatialIndexState; }
   int                   IsValidLayerDefn() { return BuildLayerDefinition(); }
 
-  virtual const char* GetName() { return m_osName.c_str(); }
-  virtual OGRwkbGeometryType GetGeomType();
+  virtual const char* GetName() override { return m_osName.c_str(); }
+  virtual OGRwkbGeometryType GetGeomType() override;
 
-  virtual const char* GetFIDColumn();
+  virtual const char* GetFIDColumn() override;
 
-  virtual void        ResetReading();
-  virtual OGRFeature* GetNextFeature();
-  virtual OGRFeature* GetFeature( GIntBig nFeatureId );
-  virtual OGRErr      SetNextByIndex( GIntBig nIndex );
+  virtual void        ResetReading() override;
+  virtual OGRFeature* GetNextFeature() override;
+  virtual OGRFeature* GetFeature( GIntBig nFeatureId ) override;
+  virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
 
-  virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-  virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-  virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+  virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+  virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+  virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-  virtual OGRFeatureDefn* GetLayerDefn();
+  virtual OGRFeatureDefn* GetLayerDefn() override;
 
-  virtual void        SetSpatialFilter( OGRGeometry * );
-  virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+  virtual void        SetSpatialFilter( OGRGeometry * ) override;
+  virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
-  virtual OGRErr      SetAttributeFilter( const char* pszFilter );
+  virtual OGRErr      SetAttributeFilter( const char* pszFilter ) override;
 
-  virtual int         TestCapability( const char * );
+  virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -183,20 +184,20 @@ public:
 
   int                 Open(const char * );
 
-  virtual const char* GetName() { return m_pszName; }
-  virtual int         GetLayerCount() { return static_cast<int>(m_apoLayers.size()); }
+  virtual const char* GetName() override { return m_pszName; }
+  virtual int         GetLayerCount() override { return static_cast<int>(m_apoLayers.size()); }
 
-  virtual OGRLayer*   GetLayer( int );
-  virtual OGRLayer*   GetLayerByName( const char* pszName );
+  virtual OGRLayer*   GetLayer( int ) override;
+  virtual OGRLayer*   GetLayerByName( const char* pszName ) override;
 
   virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                   OGRGeometry *poSpatialFilter,
-                                  const char *pszDialect );
-  virtual void        ReleaseResultSet( OGRLayer * poResultsSet );
+                                  const char *pszDialect ) override;
+  virtual void        ReleaseResultSet( OGRLayer * poResultsSet ) override;
 
-  virtual int         TestCapability( const char * );
+  virtual int         TestCapability( const char * ) override;
 
-  virtual char      **GetFileList();
+  virtual char      **GetFileList() override;
 };
 
 int OGROpenFileGDBIsComparisonOp(int op);
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp
index e6e3ceb..ef409ac 100644
--- a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogropenfilegdbdatasource.cpp 33712 2016-03-12 10:51:56Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Open FileGDB OGR driver.
@@ -31,7 +30,7 @@
 #include "ogr_mem.h"
 #include <map>
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: ogropenfilegdbdatasource.cpp 37643 2017-03-07 22:41:04Z rouault $");
 
 /************************************************************************/
 /*                      OGROpenFileGDBDataSource()                      */
@@ -82,11 +81,13 @@ int OGROpenFileGDBDataSource::Open( const char* pszFilename )
 
     m_osDirName = pszFilename;
     int nInterestTable = -1;
+    unsigned int unInterestTable = 0;
     const char* pszFilenameWithoutPath = CPLGetFilename(pszFilename);
     if( strlen(pszFilenameWithoutPath) == strlen("a00000000.gdbtable") &&
         pszFilenameWithoutPath[0] == 'a' &&
-        sscanf(pszFilenameWithoutPath, "a%08x.gdbtable", &nInterestTable) == 1 )
+        sscanf(pszFilenameWithoutPath, "a%08x.gdbtable", &unInterestTable) == 1 )
     {
+        nInterestTable = static_cast<int>(unInterestTable);
         m_osDirName = CPLGetPath(m_osDirName);
     }
     else
@@ -237,13 +238,13 @@ int OGROpenFileGDBDataSource::Open( const char* pszFilename )
         return FALSE;
     }
 
-    if( m_apoLayers.size() == 0 && nInterestTable >= 0 )
+    if( m_apoLayers.empty() && nInterestTable >= 0 )
     {
         if( FileExists(m_pszName) )
         {
-            const char* pszLyrName;
+            const char* pszLyrName = NULL;
             if( nInterestTable <= (int)aosTableNames.size()  &&
-                aosTableNames[nInterestTable-1].size() != 0 )
+                !aosTableNames[nInterestTable-1].empty() )
                 pszLyrName = aosTableNames[nInterestTable-1].c_str();
             else
                 pszLyrName = CPLSPrintf("a%08x", nInterestTable);
@@ -378,7 +379,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv10(int iGDBItems,
         }
     }
 
-    if( m_apoLayers.size() == 0 && nCandidateLayers > 0 &&
+    if( m_apoLayers.empty() && nCandidateLayers > 0 &&
         nCandidateLayers == nLayersSDCOrCDF )
         return FALSE;
 
@@ -394,7 +395,6 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
                                             int nInterestTable)
 {
     FileGDBTable oTable;
-    int i;
 
     CPLDebug("OpenFileGDB", "FileGDB v9");
 
@@ -415,7 +415,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
 
     std::vector< std::string > aosName;
     int nCandidateLayers = 0, nLayersSDCOrCDF = 0;
-    for(i=0;i<oTable.GetTotalRecordCount();i++)
+    for( int i = 0; i < oTable.GetTotalRecordCount(); i++ )
     {
         if( !oTable.SelectRow(i) )
         {
@@ -467,7 +467,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
         return FALSE;
     }
 
-    for(i=0;i<oTable.GetTotalRecordCount();i++)
+    for( int i = 0; i < oTable.GetTotalRecordCount(); i++ )
     {
         if( !oTable.SelectRow(i) )
         {
@@ -476,9 +476,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
             continue;
         }
 
-        const OGRField* psField;
-
-        psField = oTable.GetFieldValue(iGeometryType);
+        const OGRField* psField = oTable.GetFieldValue(iGeometryType);
         if( psField == NULL )
             continue;
         const int nGeomType = psField->Integer;
@@ -490,7 +488,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
             case FGTGT_MULTIPOINT: eGeomType = wkbMultiPoint; break;
             case FGTGT_LINE: eGeomType = wkbMultiLineString; break;
             case FGTGT_POLYGON: eGeomType = wkbMultiPolygon; break;
-            case FGTGT_MULTIPATCH: eGeomType = wkbMultiPolygon; break;
+            case FGTGT_MULTIPATCH: eGeomType = wkbUnknown; break;
         }
 
         psField = oTable.GetFieldValue(iShapeField);
@@ -504,7 +502,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
 
         int idx = psField->Integer;
         if( idx > 0 && idx <= static_cast<int>(aosName.size()) &&
-            aosName[idx-1].size() > 0 )
+            !aosName[idx-1].empty() )
         {
             const std::string osName(aosName[idx-1]);
             AddLayer( osName, nInterestTable, nCandidateLayers, nLayersSDCOrCDF,
@@ -512,7 +510,7 @@ int OGROpenFileGDBDataSource::OpenFileGDBv9(int iGDBFeatureClasses,
         }
     }
 
-    if( m_apoLayers.size() == 0 && nCandidateLayers > 0 &&
+    if( m_apoLayers.empty() && nCandidateLayers > 0 &&
         nCandidateLayers == nLayersSDCOrCDF )
         return FALSE;
 
@@ -545,9 +543,7 @@ OGRLayer* OGROpenFileGDBDataSource::GetLayer( int iIndex )
 
 OGRLayer* OGROpenFileGDBDataSource::GetLayerByName( const char* pszName )
 {
-    OGRLayer* poLayer;
-
-    poLayer = OGRDataSource::GetLayerByName(pszName);
+    OGRLayer* poLayer = OGRDataSource::GetLayerByName(pszName);
     if( poLayer != NULL )
         return poLayer;
 
@@ -574,7 +570,6 @@ OGRLayer* OGROpenFileGDBDataSource::GetLayerByName( const char* pszName )
     return NULL;
 }
 
-
 /************************************************************************/
 /*                   OGROpenFileGDBSingleFeatureLayer                   */
 /************************************************************************/
@@ -589,29 +584,29 @@ class OGROpenFileGDBSingleFeatureLayer : public OGRLayer
   public:
                         OGROpenFileGDBSingleFeatureLayer( const char* pszLayerName,
                                                           const char *pszVal );
-                        ~OGROpenFileGDBSingleFeatureLayer();
+               virtual ~OGROpenFileGDBSingleFeatureLayer();
 
-    virtual void        ResetReading() { iNextShapeId = 0; }
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
-    virtual int         TestCapability( const char * ) { return FALSE; }
+    virtual void        ResetReading() override { iNextShapeId = 0; }
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
+    virtual int         TestCapability( const char * ) override { return FALSE; }
 };
 
 /************************************************************************/
 /*                 OGROpenFileGDBSingleFeatureLayer()                   */
 /************************************************************************/
 
-OGROpenFileGDBSingleFeatureLayer::OGROpenFileGDBSingleFeatureLayer(const char* pszLayerName,
-                                                                   const char *pszValIn )
+OGROpenFileGDBSingleFeatureLayer::OGROpenFileGDBSingleFeatureLayer(
+    const char* pszLayerName,
+    const char *pszValIn ) :
+    pszVal(pszValIn ? CPLStrdup(pszValIn) : NULL),
+    poFeatureDefn(new OGRFeatureDefn( pszLayerName )),
+    iNextShapeId(0)
 {
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     OGRFieldDefn oField( "FIELD_1", OFTString );
     poFeatureDefn->AddFieldDefn( &oField );
-
-    iNextShapeId = 0;
-    this->pszVal = pszValIn ? CPLStrdup(pszValIn) : NULL;
 }
 
 /************************************************************************/
@@ -625,7 +620,6 @@ OGROpenFileGDBSingleFeatureLayer::~OGROpenFileGDBSingleFeatureLayer()
     CPLFree(pszVal);
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -657,19 +651,19 @@ class OGROpenFileGDBSimpleSQLLayer: public OGRLayer
                                      FileGDBIterator* poIter,
                                      int nColumns,
                                      swq_col_def* pasColDefs);
-       ~OGROpenFileGDBSimpleSQLLayer();
-
-       virtual void        ResetReading();
-       virtual OGRFeature* GetNextFeature();
-       virtual OGRFeature* GetFeature( GIntBig nFeatureId );
-       virtual OGRFeatureDefn* GetLayerDefn() { return poFeatureDefn; }
-       virtual int         TestCapability( const char * );
-       virtual const char* GetFIDColumn() { return poBaseLayer->GetFIDColumn(); }
-       virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce )
+       virtual ~OGROpenFileGDBSimpleSQLLayer();
+
+       virtual void        ResetReading() override;
+       virtual OGRFeature* GetNextFeature() override;
+       virtual OGRFeature* GetFeature( GIntBig nFeatureId ) override;
+       virtual OGRFeatureDefn* GetLayerDefn() override { return poFeatureDefn; }
+       virtual int         TestCapability( const char * ) override;
+       virtual const char* GetFIDColumn() override { return poBaseLayer->GetFIDColumn(); }
+       virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override
                             { return poBaseLayer->GetExtent(psExtent, bForce); }
-       virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+       virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-       virtual GIntBig     GetFeatureCount(int bForce);
+       virtual GIntBig     GetFeatureCount(int bForce) override;
 };
 
 /***********************************************************************/
@@ -677,11 +671,13 @@ class OGROpenFileGDBSimpleSQLLayer: public OGRLayer
 /***********************************************************************/
 
 OGROpenFileGDBSimpleSQLLayer::OGROpenFileGDBSimpleSQLLayer(
-                                            OGRLayer* poBaseLayerIn,
-                                            FileGDBIterator* poIterIn,
-                                            int nColumns,
-                                            swq_col_def* pasColDefs) :
-        poBaseLayer(poBaseLayerIn), poIter(poIterIn)
+    OGRLayer* poBaseLayerIn,
+    FileGDBIterator* poIterIn,
+    int nColumns,
+    swq_col_def* pasColDefs) :
+    poBaseLayer(poBaseLayerIn),
+    poIter(poIterIn),
+    poFeatureDefn(NULL)
 {
     if( nColumns == 1 && strcmp(pasColDefs[0].field_name, "*") == 0 )
     {
@@ -814,7 +810,7 @@ int OGROpenFileGDBSimpleSQLLayer::TestCapability( const char * pszCap )
 
     if( EQUAL(pszCap,OLCFastFeatureCount) )
     {
-        return( m_poFilterGeom == NULL && m_poAttrQuery == NULL );
+        return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
     }
     else if( EQUAL(pszCap,OLCFastGetExtent) )
     {
@@ -952,8 +948,8 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
             {
                 OGRMemLayer* poMemLayer = NULL;
 
-                int i;
-                for(i = 0; i < oSelect.result_columns; i ++ )
+                int i = 0;  // Used after for.
+                for( ; i < oSelect.result_columns; i ++ )
                 {
                     swq_col_func col_func = oSelect.column_defs[i].col_func;
                     if( !(col_func == SWQCF_MIN || col_func == SWQCF_MAX ||
@@ -1109,8 +1105,8 @@ OGRLayer* OGROpenFileGDBDataSource::ExecuteSQL( const char *pszSQLCommand,
                 }
                 if( eErr == OGRERR_NONE )
                 {
-                    int i;
-                    for(i = 0; i < oSelect.result_columns; i ++ )
+                    int i = 0;  // Used after for.
+                    for( ; i < oSelect.result_columns; i++ )
                     {
                         if( oSelect.column_defs[i].col_func != SWQCF_NONE )
                             break;
@@ -1186,10 +1182,12 @@ char** OGROpenFileGDBDataSource::GetFileList()
     int nInterestTable = -1;
     const char* pszFilenameWithoutPath = CPLGetFilename(m_pszName);
     CPLString osFilenameRadix;
+    unsigned int unInterestTable = 0;
     if( strlen(pszFilenameWithoutPath) == strlen("a00000000.gdbtable") &&
         pszFilenameWithoutPath[0] == 'a' &&
-        sscanf(pszFilenameWithoutPath, "a%08x.gdbtable", &nInterestTable) == 1 )
+        sscanf(pszFilenameWithoutPath, "a%08x.gdbtable", &unInterestTable) == 1 )
     {
+        nInterestTable = static_cast<int>(unInterestTable);
         osFilenameRadix = CPLSPrintf("a%08x.", nInterestTable);
     }
 
@@ -1200,7 +1198,7 @@ char** OGROpenFileGDBDataSource::GetFileList()
     {
         if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 )
             continue;
-        if( osFilenameRadix.size() == 0 ||
+        if( osFilenameRadix.empty() ||
             strncmp(*papszIter, osFilenameRadix, osFilenameRadix.size()) == 0 )
         {
             osStringList.AddString(CPLFormFilename(m_osDirName, *papszIter, NULL));
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp
index 2fea181..5a83378 100644
--- a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdbdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogropenfilegdbdriver.cpp 33031 2016-01-17 19:21:44Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Open FileGDB OGR driver.
@@ -29,7 +28,7 @@
 
 #include "ogr_openfilegdb.h"
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: ogropenfilegdbdriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 // g++ -O2 -Wall -Wextra -g -shared -fPIC ogr/ogrsf_frmts/openfilegdb/*.cpp
 // -o ogr_OpenFileGDB.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts
@@ -37,7 +36,6 @@ CPL_CVSID("$Id");
 
 extern "C" void RegisterOGROpenFileGDB();
 
-
 #define ENDS_WITH(str, strLen, end) \
     (strLen >= strlen(end) && EQUAL(str + strLen - strlen(end), end))
 
@@ -124,6 +122,19 @@ static GDALIdentifyEnum OGROpenFileGDBDriverIdentifyInternal( GDALOpenInfo* poOp
     }
 #endif
 
+    else if( EQUAL(pszFilename, ".") )
+    {
+        GDALIdentifyEnum eRet = GDAL_IDENTIFY_FALSE;
+        char* pszCurrentDir = CPLGetCurrentDir();
+        if( pszCurrentDir )
+        {
+            const char* pszTmp = pszCurrentDir;
+            eRet = OGROpenFileGDBDriverIdentifyInternal(poOpenInfo, pszTmp);
+            CPLFree(pszCurrentDir);
+        }
+        return eRet;
+    }
+
     else
     {
         return GDAL_IDENTIFY_FALSE;
diff --git a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
index 9c66afc..5c0f7e6 100644
--- a/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
+++ b/ogr/ogrsf_frmts/openfilegdb/ogropenfilegdblayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogropenfilegdblayer.cpp 34480 2016-06-30 16:07:59Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Open FileGDB OGR driver.
@@ -31,7 +30,7 @@
 #include "cpl_minixml.h"
 #include <algorithm>
 
-CPL_CVSID("$Id");
+CPL_CVSID("$Id: ogropenfilegdblayer.cpp 37643 2017-03-07 22:41:04Z rouault $");
 
 /************************************************************************/
 /*                      OGROpenFileGDBGeomFieldDefn                     */
@@ -52,7 +51,7 @@ class OGROpenFileGDBGeomFieldDefn: public OGRGeomFieldDefn
 
         void UnsetLayer() { m_poLayer = NULL; }
 
-        virtual OGRSpatialReference* GetSpatialRef()
+        virtual OGRSpatialReference* GetSpatialRef() override
         {
             if( poSRS )
                 return poSRS;
@@ -88,7 +87,7 @@ class OGROpenFileGDBFeatureDefn: public OGRFeatureDefn
             m_poLayer = NULL;
         }
 
-        virtual int GetFieldCount()
+        virtual int GetFieldCount() override
         {
             if( nFieldCount )
                 return nFieldCount;
@@ -100,12 +99,12 @@ class OGROpenFileGDBFeatureDefn: public OGRFeatureDefn
             return nFieldCount;
         }
 
-        virtual int GetGeomFieldCount()
+        virtual int GetGeomFieldCount() override
         {
             /* FileGDB v9 case */
             if( !m_bHasBuildFieldDefn &&
                 m_poLayer != NULL && m_poLayer->m_eGeomType != wkbNone &&
-                m_poLayer->m_osDefinition.size() == 0 )
+                m_poLayer->m_osDefinition.empty() )
             {
                 m_bHasBuildFieldDefn = TRUE;
                 (void) m_poLayer->BuildLayerDefinition();
@@ -113,12 +112,12 @@ class OGROpenFileGDBFeatureDefn: public OGRFeatureDefn
             return nGeomFieldCount;
         }
 
-        virtual OGRGeomFieldDefn* GetGeomFieldDefn( int i )
+        virtual OGRGeomFieldDefn* GetGeomFieldDefn( int i ) override
         {
             /* FileGDB v9 case */
             if( !m_bHasBuildFieldDefn &&
                 m_poLayer != NULL && m_poLayer->m_eGeomType != wkbNone &&
-                m_poLayer->m_osDefinition.size() == 0 )
+                m_poLayer->m_osDefinition.empty() )
             {
                 m_bHasBuildFieldDefn = TRUE;
                 (void) m_poLayer->BuildLayerDefinition();
@@ -131,34 +130,36 @@ class OGROpenFileGDBFeatureDefn: public OGRFeatureDefn
 /*                      OGROpenFileGDBLayer()                           */
 /************************************************************************/
 
-OGROpenFileGDBLayer::OGROpenFileGDBLayer(const char* pszGDBFilename,
-                                         const char* pszName,
-                                         const std::string& osDefinition,
-                                         const std::string& osDocumentation,
-                                         const char* /* pszGeomName */,
-                                         OGRwkbGeometryType eGeomType) :
-            m_osGDBFilename(pszGDBFilename),
-            m_osName(pszName),
-            m_poLyrTable(NULL),
-            m_poFeatureDefn(NULL),
-            m_iGeomFieldIdx(-1),
-            m_iCurFeat(0),
-            m_osDefinition(osDefinition),
-            m_osDocumentation(osDocumentation),
-            m_eGeomType(wkbNone),
-            m_bValidLayerDefn(-1),
-            m_bEOF(FALSE),
-            m_poGeomConverter(NULL),
-            m_iFieldToReadAsBinary(-1),
-            m_poIterator(NULL),
-            m_bIteratorSufficientToEvaluateFilter(FALSE),
-            m_poIterMinMax(NULL),
-            m_eSpatialIndexState(SPI_IN_BUILDING),
-            m_pQuadTree(NULL),
-            m_pahFilteredFeatures(NULL),
-            m_nFilteredFeatureCount(-1)
+OGROpenFileGDBLayer::OGROpenFileGDBLayer( const char* pszGDBFilename,
+                                          const char* pszName,
+                                          const std::string& osDefinition,
+                                          const std::string& osDocumentation,
+                                          const char* /* pszGeomName */,
+                                          OGRwkbGeometryType eGeomType ) :
+    m_osGDBFilename(pszGDBFilename),
+    m_osName(pszName),
+    m_poLyrTable(NULL),
+    m_poFeatureDefn(NULL),
+    m_iGeomFieldIdx(-1),
+    m_iCurFeat(0),
+    m_osDefinition(osDefinition),
+    m_osDocumentation(osDocumentation),
+    m_eGeomType(wkbNone),
+    m_bValidLayerDefn(-1),
+    m_bEOF(FALSE),
+    m_poGeomConverter(NULL),
+    m_iFieldToReadAsBinary(-1),
+    m_poIterator(NULL),
+    m_bIteratorSufficientToEvaluateFilter(FALSE),
+    m_poIterMinMax(NULL),
+    m_eSpatialIndexState(SPI_IN_BUILDING),
+    m_pQuadTree(NULL),
+    m_pahFilteredFeatures(NULL),
+    m_nFilteredFeatureCount(-1)
 {
-    // We cannot initialize m_poFeatureDefn in above list since MSVC doesn't like
+    // TODO(rouault): What error on compiler versions?  r33032 does not say.
+
+    // We cannot initialize m_poFeatureDefn in above list. MSVC doesn't like
     // this to be used in initialization list.
     m_poFeatureDefn = new OGROpenFileGDBFeatureDefn(this, pszName);
     SetDescription( m_poFeatureDefn->GetName() );
@@ -167,9 +168,9 @@ OGROpenFileGDBLayer::OGROpenFileGDBLayer(const char* pszGDBFilename,
 
     m_eGeomType = eGeomType;
 
-    if( m_osDefinition.size() )
+    if( !m_osDefinition.empty() )
     {
-        (void) BuildGeometryColumnGDBv10();
+        BuildGeometryColumnGDBv10();
     }
 }
 
@@ -230,10 +231,42 @@ int OGROpenFileGDBLayer::BuildGeometryColumnGDBv10()
     {
         m_eGeomType =
             FileGDBOGRGeometryConverter::GetGeometryTypeFromESRI(pszShapeType);
+
+        if( EQUAL(pszShapeType, "esriGeometryMultiPatch") )
+        {
+            if( m_poLyrTable == NULL )
+            {
+                m_poLyrTable = new FileGDBTable();
+                if( !(m_poLyrTable->Open(m_osGDBFilename, GetDescription())) )
+                {
+                    delete m_poLyrTable;
+                    m_poLyrTable = NULL;
+                    m_bValidLayerDefn = FALSE;
+                }
+            }
+            if( m_poLyrTable != NULL )
+            {
+                m_iGeomFieldIdx = m_poLyrTable->GetGeomFieldIdx();
+                if( m_iGeomFieldIdx >= 0 )
+                {
+                    FileGDBGeomField* poGDBGeomField =
+                        reinterpret_cast<FileGDBGeomField *>(
+                            m_poLyrTable->GetField(m_iGeomFieldIdx));
+                    if( m_poGeomConverter == NULL )
+                    {
+                        m_poGeomConverter =
+                            FileGDBOGRGeometryConverter::BuildConverter(poGDBGeomField);
+                    }
+                    TryToDetectMultiPatchKind();
+                }
+            }
+        }
+
         if( bHasZ )
             m_eGeomType = wkbSetZ( m_eGeomType );
         if( bHasM )
             m_eGeomType = wkbSetM( m_eGeomType );
+
         const char* pszWKT =
             CPLGetXMLValue( psInfo, "SpatialReference.WKT", NULL );
         const int nWKID =
@@ -327,10 +360,63 @@ int OGROpenFileGDBLayer::BuildGeometryColumnGDBv10()
         m_eGeomType = wkbNone;
     }
     CPLDestroyXMLNode(psTree);
+
     return TRUE;
 }
 
 /************************************************************************/
+/*                   TryToDetectMultiPatchKind()                        */
+/************************************************************************/
+
+// If the first and last feature have the same geometry type, then use
+// it for the whole layer.
+void OGROpenFileGDBLayer::TryToDetectMultiPatchKind()
+{
+    CPLAssert( m_poLyrTable != NULL );
+    CPLAssert( m_iGeomFieldIdx >= 0 );
+
+    if( m_poLyrTable->GetTotalRecordCount() == 0 )
+        return;
+    int nFirstIdx = m_poLyrTable->GetAndSelectNextNonEmptyRow(0);
+    if( nFirstIdx < 0 )
+        return;
+
+    const OGRField* psField = m_poLyrTable->GetFieldValue(m_iGeomFieldIdx);
+    if( psField == NULL )
+        return;
+    OGRGeometry* poGeom = m_poGeomConverter->GetAsGeometry(psField);
+    if( poGeom == NULL )
+        return;
+    const OGRwkbGeometryType eType = poGeom->getGeometryType();
+    delete poGeom;
+
+    int nLastIdx = m_poLyrTable->GetTotalRecordCount()-1;
+    while( nLastIdx > nFirstIdx && 
+           m_poLyrTable->GetOffsetInTableForRow(nLastIdx) == 0 )
+    {
+        nLastIdx --;
+    }
+    if( nLastIdx > nFirstIdx && m_poLyrTable->SelectRow(nLastIdx) )
+    {
+        psField = m_poLyrTable->GetFieldValue(m_iGeomFieldIdx);
+        if( psField == NULL )
+        {
+            m_eGeomType = eType;
+            return;
+        }
+        poGeom = m_poGeomConverter->GetAsGeometry(psField);
+        if( poGeom == NULL )
+        {
+            m_eGeomType = eType;
+            return;
+        }
+        if( eType == poGeom->getGeometryType() )
+            m_eGeomType = eType;
+        delete poGeom;
+    }
+}
+
+/************************************************************************/
 /*                      BuildLayerDefinition()                          */
 /************************************************************************/
 
@@ -339,13 +425,16 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
     if( m_bValidLayerDefn >= 0 )
         return m_bValidLayerDefn;
 
-    m_poLyrTable = new FileGDBTable();
-    if( !(m_poLyrTable->Open(m_osGDBFilename, GetDescription())) )
+    if( m_poLyrTable == NULL )
     {
-        delete m_poLyrTable;
-        m_poLyrTable = NULL;
-        m_bValidLayerDefn = FALSE;
-        return FALSE;
+        m_poLyrTable = new FileGDBTable();
+        if( !(m_poLyrTable->Open(m_osGDBFilename, GetDescription())) )
+        {
+            delete m_poLyrTable;
+            m_poLyrTable = NULL;
+            m_bValidLayerDefn = FALSE;
+            return FALSE;
+        }
     }
 
     m_bValidLayerDefn = TRUE;
@@ -356,8 +445,11 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
         FileGDBGeomField* poGDBGeomField =
             reinterpret_cast<FileGDBGeomField *>(
                 m_poLyrTable->GetField(m_iGeomFieldIdx));
-        m_poGeomConverter =
+        if( m_poGeomConverter == NULL )
+        {
+            m_poGeomConverter =
             FileGDBOGRGeometryConverter::BuildConverter(poGDBGeomField);
+        }
 
         if( CPLTestBool(
                 CPLGetConfigOption("OPENFILEGDB_IN_MEMORY_SPI", "YES")) )
@@ -380,7 +472,7 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
     }
 
     if( m_iGeomFieldIdx >= 0 &&
-        (m_osDefinition.size() == 0 ||
+        (m_osDefinition.empty() ||
          m_poFeatureDefn->OGRFeatureDefn::GetGeomFieldCount() == 0) )
     {
         /* FileGDB v9 case */
@@ -398,7 +490,7 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
             case FGTGT_MULTIPOINT: eGeomType = wkbMultiPoint; break;
             case FGTGT_LINE: eGeomType = wkbMultiLineString; break;
             case FGTGT_POLYGON: eGeomType = wkbMultiPolygon; break;
-            case FGTGT_MULTIPATCH: eGeomType = wkbMultiPolygon; break;
+            case FGTGT_MULTIPATCH: eGeomType = wkbUnknown; break;
         }
 
         if( m_eGeomType != wkbUnknown && wkbFlatten(eGeomType) != wkbFlatten(m_eGeomType) )
@@ -408,9 +500,16 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
         }
 
         m_eGeomType = eGeomType;
+
+        if( eGDBGeomType == FGTGT_MULTIPATCH )
+        {
+            TryToDetectMultiPatchKind();
+        }
+
         if( poGDBGeomField->Has3D() )
             m_eGeomType = wkbSetZ(m_eGeomType);
 
+
         // Check that the first feature has actually a M value before advertizing
         // it.
         if( poGDBGeomField->HasM() &&
@@ -427,16 +526,14 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
             }
         }
 
-        OGROpenFileGDBGeomFieldDefn* poGeomFieldDefn;
-
-        poGeomFieldDefn =
+        OGROpenFileGDBGeomFieldDefn* poGeomFieldDefn =
                 new OGROpenFileGDBGeomFieldDefn(NULL, pszName, m_eGeomType);
         poGeomFieldDefn->SetNullable(poGDBGeomField->IsNullable());
 
         m_poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
 
         OGRSpatialReference* poSRS = NULL;
-        if( poGDBGeomField->GetWKT().size() &&
+        if( !poGDBGeomField->GetWKT().empty() &&
             poGDBGeomField->GetWKT()[0] != '{' )
         {
             poSRS = new OGRSpatialReference( poGDBGeomField->GetWKT().c_str() );
@@ -452,7 +549,7 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
             poSRS->Dereference();
         }
     }
-    else if( m_osDefinition.size() == 0 && m_iGeomFieldIdx < 0 )
+    else if( m_osDefinition.empty() && m_iGeomFieldIdx < 0 )
     {
         m_eGeomType = wkbNone;
     }
@@ -500,7 +597,7 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
             case FGFT_UNDEFINED:
             case FGFT_OBJECTID:
             case FGFT_GEOMETRY:
-                CPLAssert(FALSE);
+                CPLAssert(false);
                 break;
             case FGFT_BINARY:
             case FGFT_RASTER:
@@ -527,8 +624,7 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
             oFieldDefn.SetWidth(nWidth);
         oFieldDefn.SetNullable(poGDBField->IsNullable());
         const OGRField* psDefault = poGDBField->GetDefault();
-        if( !(psDefault->Set.nMarker1 == OGRUnsetMarker &&
-              psDefault->Set.nMarker2 == OGRUnsetMarker) )
+        if( !OGR_RawField_IsUnset(psDefault) && !OGR_RawField_IsNull(psDefault) )
         {
             if( eType == OFTString )
             {
@@ -546,7 +642,7 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
                 // a00000004.gdbtable does not match the default values (in
                 // binary) found in the field definition section of the
                 // .gdbtable of the layers themselves So check consistency.
-                if( m_osDefinition.size() && psTree == NULL )
+                if( !m_osDefinition.empty() && psTree == NULL )
                 {
                     psTree = CPLParseXMLString(m_osDefinition.c_str());
                     if( psTree != NULL )
@@ -657,7 +753,7 @@ int OGROpenFileGDBLayer::BuildLayerDefinition()
 OGRwkbGeometryType OGROpenFileGDBLayer::GetGeomType()
 {
     if( m_eGeomType == wkbUnknown ||
-        m_osDefinition.size() == 0 /* FileGDB v9 case */ )
+        m_osDefinition.empty() /* FileGDB v9 case */ )
     {
         (void) BuildLayerDefinition();
     }
@@ -770,6 +866,7 @@ static int CompValues(OGRFieldDefn* poFieldDefn,
                       const swq_expr_node* poValue1,
                       const swq_expr_node* poValue2)
 {
+    int ret = 0;
     switch( poFieldDefn->GetType() )
     {
         case OFTInteger:
@@ -784,26 +881,25 @@ static int CompValues(OGRFieldDefn* poFieldDefn,
             else
                 n2 = (int) poValue2->int_value;
             if( n1 < n2 )
-                return -1;
-
-            if( n1 == n2 )
-                return 0;
+                ret = -1;
+            else if( n1 == n2 )
+                ret = 0;
             else
-                return 1;
+                ret = 1;
             break;
         }
 
         case OFTReal:
             if( poValue1->float_value < poValue2->float_value )
-                return -1;
-            if( poValue1->float_value == poValue2->float_value )
-                return 0;
+                ret = -1;
+            else if( poValue1->float_value == poValue2->float_value )
+                ret = 0;
             else
-                return 1;
+                ret = 1;
             break;
 
         case OFTString:
-            return strcmp(poValue1->string_value, poValue2->string_value);
+            ret = strcmp(poValue1->string_value, poValue2->string_value);
             break;
 
         case OFTDate:
@@ -817,16 +913,15 @@ static int CompValues(OGRFieldDefn* poFieldDefn,
                  poValue2->field_type == SWQ_DATE ||
                  poValue2->field_type == SWQ_TIME))
             {
-                return strcmp(poValue1->string_value, poValue2->string_value);
+                ret = strcmp(poValue1->string_value, poValue2->string_value);
             }
-            return 0;
             break;
         }
 
         default:
-            return 0;
             break;
     }
+    return ret;
 }
 
 /***********************************************************************/
@@ -927,7 +1022,6 @@ static int AreExprExclusive(OGRFeatureDefn* poFeatureDefn,
     return FALSE;
 }
 
-
 /***********************************************************************/
 /*                     FillTargetValueFromSrcExpr()                    */
 /***********************************************************************/
@@ -1091,8 +1185,8 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
         if( poColumn != NULL && poValue != NULL &&
             poColumn->field_index < GetLayerDefn()->GetFieldCount())
         {
-            OGRFieldDefn *poFieldDefn;
-            poFieldDefn = GetLayerDefn()->GetFieldDefn(poColumn->field_index);
+            OGRFieldDefn *poFieldDefn =
+                GetLayerDefn()->GetFieldDefn(poColumn->field_index);
 
             int nTableColIdx = m_poLyrTable->GetFieldIdx(poFieldDefn->GetNameRef());
             if( nTableColIdx >= 0 && m_poLyrTable->GetField(nTableColIdx)->HasIndex() )
@@ -1113,7 +1207,7 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
                             case SWQ_EQ: eOp = FGSO_EQ; break;
                             case SWQ_GE: eOp = FGSO_GE; break;
                             case SWQ_GT: eOp = FGSO_GT; break;
-                            default: CPLAssert(FALSE); break;
+                            default: CPLAssert(false); break;
                         }
                     }
                     else
@@ -1128,7 +1222,7 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
                             case SWQ_EQ: eOp = FGSO_EQ; break;
                             case SWQ_GE: eOp = FGSO_LE; break;
                             case SWQ_GT: eOp = FGSO_LT; break;
-                            default: CPLAssert(FALSE); break;
+                            default: CPLAssert(false); break;
                         }
                     }
 
@@ -1265,7 +1359,6 @@ FileGDBIterator* OGROpenFileGDBLayer::BuildIteratorFromExprNode(swq_expr_node* p
         }
     }
 
-
     if( m_bIteratorSufficientToEvaluateFilter == TRUE )
         CPLDebug("OpenFileGDB", "Disabling use of indexes");
     m_bIteratorSufficientToEvaluateFilter = FALSE;
@@ -1358,8 +1451,21 @@ OGRFeature* OGROpenFileGDBLayer::GetCurrentFeature()
                     OGRwkbGeometryType eFlattenType = wkbFlatten(poGeom->getGeometryType());
                     if( eFlattenType == wkbPolygon )
                         poGeom = OGRGeometryFactory::forceToMultiPolygon(poGeom);
+                    else if( eFlattenType == wkbCurvePolygon)
+                    {
+                        OGRMultiSurface* poMS = new OGRMultiSurface();
+                        poMS->addGeometryDirectly( poGeom );
+                        poGeom = poMS;
+                    }
                     else if( eFlattenType == wkbLineString )
                         poGeom = OGRGeometryFactory::forceToMultiLineString(poGeom);
+                    else if (eFlattenType == wkbCompoundCurve)
+                    {
+                        OGRMultiCurve* poMC = new OGRMultiCurve();
+                        poMC->addGeometryDirectly( poGeom );
+                        poGeom = poMC;
+                    }
+
                     poGeom->assignSpatialReference(
                         m_poFeatureDefn->GetGeomFieldDefn(0)->GetSpatialRef() );
 
@@ -1374,10 +1480,14 @@ OGRFeature* OGROpenFileGDBLayer::GetCurrentFeature()
             if( !m_poFeatureDefn->GetFieldDefn(iOGRIdx)->IsIgnored() )
             {
                 const OGRField* psField = m_poLyrTable->GetFieldValue(iGDBIdx);
-                if( psField != NULL )
+                if( poFeature == NULL )
+                    poFeature = new OGRFeature(m_poFeatureDefn);
+                if( psField == NULL )
+                {
+                    poFeature->SetFieldNull(iOGRIdx);
+                }
+                else
                 {
-                    if( poFeature == NULL )
-                        poFeature = new OGRFeature(m_poFeatureDefn);
 
                     if( iGDBIdx == m_iFieldToReadAsBinary )
                         poFeature->SetField(iOGRIdx, (const char*) psField->Binary.paData);
@@ -1423,7 +1533,7 @@ OGRFeature* OGROpenFileGDBLayer::GetNextFeature()
                 {
                     return NULL;
                 }
-                int iRow = (int)(size_t)m_pahFilteredFeatures[m_iCurFeat++];
+                int iRow = (int)(GUIntptr_t)m_pahFilteredFeatures[m_iCurFeat++];
                 if( m_poLyrTable->SelectRow(iRow) )
                 {
                     poFeature = GetCurrentFeature();
diff --git a/ogr/ogrsf_frmts/osm/drv_osm.html b/ogr/ogrsf_frmts/osm/drv_osm.html
index 80cf888..27f010b 100644
--- a/ogr/ogrsf_frmts/osm/drv_osm.html
+++ b/ogr/ogrsf_frmts/osm/drv_osm.html
@@ -76,10 +76,20 @@ effect of this option will be less efficient. This option consumes addionnal 60
 
 <h3>Interleaved reading</h3>
 
+<p>
 Due to the nature of OSM files and how the driver works internally,
-the default reading mode might not work correctly, because too many
+the default reading mode that works per-layer might not work correctly, because too many
 features will accumulate in the layers before being consumed by the
-user application.  For large files, applications should set the
+user application.
+</p>
+
+<p>
+Starting with GDAL 2.2, applications should use the GDALDataset::GetNextFeature()
+API to iterate over features in the order they are produced.
+</p>
+
+<p>
+For earlier versions, for large files, applications should set the
 OGR_INTERLEAVED_READING=YES configuration option to turn on a special
 reading mode where the following reading pattern must be used:
 
@@ -103,12 +113,25 @@ reading mode where the following reading pattern must be used:
     }
     while( bHasLayersNonEmpty );
 </pre>
+</p>
 
 <p>
 
 Note : the ogr2ogr application has been modified to use that OGR_INTERLEAVED_READING mode without any
 particular user action.<p>
 
+<h3>Spatial filtering</h3>
+
+<p>Due to way .osm or .pbf files are structured and the parsing of the file is done,
+for efficiency reasons, a spatial filter applied on the points layer will also affect other layers.
+This may result in lines or polygons that have missing vertices.</p>
+
+<p>To improve this, a possibility is using a larger spatial filter with some buffer
+for the points layer, and then post-process the output to apply the desired filter.
+This would not work however if a polygon has vertices very far away from the interest
+area. In which case full conversion of the file to another format, and filtering of
+the resulting lines or polygons layers would be needed.</p>
+
 <h3>Reading .osm.bz2 files and/or online files</h3>
 
 .osm.bz2 are not natively recognized, however you can process them (on Unix), with the following command :
diff --git a/ogr/ogrsf_frmts/osm/ogr_osm.h b/ogr/ogrsf_frmts/osm/ogr_osm.h
index 95588c9..6a04fc9 100644
--- a/ogr/ogrsf_frmts/osm/ogr_osm.h
+++ b/ogr/ogrsf_frmts/osm/ogr_osm.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_osm.h 34096 2016-04-25 10:10:12Z rouault $
+ * $Id: ogr_osm.h 37534 2017-03-01 16:50:58Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/OpenStreeMap driver.
@@ -66,7 +66,8 @@ class OGROSMComputedAttribute
         std::vector<int> anIndexToBind;
 
         OGROSMComputedAttribute() : nIndex(-1), eType(OFTString), hStmt(NULL) {}
-        OGROSMComputedAttribute(const char* pszName) : osName(pszName), nIndex(-1), eType(OFTString), hStmt(NULL) {}
+        explicit OGROSMComputedAttribute(const char* pszName) :
+                osName(pszName), nIndex(-1), eType(OFTString), hStmt(NULL) {}
 };
 
 /************************************************************************/
@@ -117,7 +118,8 @@ class OGROSMLayer : public OGRLayer
 
     bool                  bUserInterested;
 
-    int                  AddToArray(OGRFeature* poFeature, int bCheckFeatureThreshold);
+    bool                  AddToArray( OGRFeature* poFeature,
+                                      int bCheckFeatureThreshold );
 
     int                   AddInOtherOrAllTags(const char* pszK);
 
@@ -138,18 +140,23 @@ class OGROSMLayer : public OGRLayer
                                      const char* pszName );
     virtual             ~OGROSMLayer();
 
-    virtual OGRFeatureDefn *GetLayerDefn() {return poFeatureDefn;}
+    virtual OGRFeatureDefn *GetLayerDefn() override {return poFeatureDefn;}
 
-    virtual void        ResetReading();
-    virtual int         TestCapability( const char * );
+    virtual void        ResetReading() override;
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRFeature *GetNextFeature();
-    virtual GIntBig     GetFeatureCount( int bForce );
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRErr      SetAttributeFilter( const char* pszAttrQuery );
+    OGRFeature*         MyGetNextFeature( OGROSMLayer** ppoNewCurLayer,
+                                          GDALProgressFunc pfnProgress,
+                                          void* pProgressData );
 
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual GIntBig     GetFeatureCount( int bForce ) override;
+
+    virtual OGRErr      SetAttributeFilter( const char* pszAttrQuery ) override;
+
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     const OGREnvelope*  GetSpatialFilterEnvelope();
@@ -189,7 +196,7 @@ class OGROSMLayer : public OGRLayer
 
     void                SetFieldsFromTags(OGRFeature* poFeature,
                                           GIntBig nID,
-                                          int bIsWayID,
+                                          bool bIsWayID,
                                           unsigned int nTags, OSMTag* pasTags,
                                           OSMInfo* psInfo);
 
@@ -292,9 +299,7 @@ class OGROSMDataSource : public OGRDataSource
     bool                bHasParsedFirstChunk;
     bool                bStopParsing;
 
-#ifdef HAVE_SQLITE_VFS
     sqlite3_vfs*        pMyVFS;
-#endif
 
     sqlite3            *hDB;
     sqlite3_stmt       *hInsertNodeStmt;
@@ -395,6 +400,10 @@ class OGROSMDataSource : public OGRDataSource
 
     bool                bNeedsToSaveWayInfo;
 
+    static const GIntBig FILESIZE_NOT_INIT = -2;
+    static const GIntBig FILESIZE_INVALID = -1;
+    GIntBig             m_nFileSize;
+
     int                 CompressWay (bool bIsArea, unsigned int nTags, IndexedKVP* pasTags,
                                      int nPoints, LonLat* pasLonLatPairs,
                                      OSMInfo* psInfo,
@@ -405,18 +414,18 @@ class OGROSMDataSource : public OGRDataSource
                                        OSMInfo* psInfo );
 
     bool                ParseConf(char** papszOpenOptions);
-    int                 CreateTempDB();
+    bool                CreateTempDB();
     bool                SetDBOptions();
     bool                SetCacheSize();
     bool                CreatePreparedStatements();
     void                CloseDB();
 
-    int                 IndexPoint(OSMNode* psNode);
-    int                 IndexPointSQLite(OSMNode* psNode);
+    bool                IndexPoint( OSMNode* psNode );
+    bool                IndexPointSQLite( OSMNode* psNode );
     bool                FlushCurrentSector();
     bool                FlushCurrentSectorCompressedCase();
     bool                FlushCurrentSectorNonCompressedCase();
-    bool                IndexPointCustom(OSMNode* psNode);
+    bool                IndexPointCustom( OSMNode* psNode );
 
     void                IndexWay(GIntBig nWayID, bool bIsArea,
                                  unsigned int nTags, IndexedKVP* pasTags,
@@ -457,24 +466,31 @@ class OGROSMDataSource : public OGRDataSource
 
   public:
                         OGROSMDataSource();
-                        ~OGROSMDataSource();
+                        virtual ~OGROSMDataSource();
 
-    virtual const char *GetName() { return pszName; }
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer   *GetLayer( int );
+    virtual const char *GetName() override { return pszName; }
+    virtual int         GetLayerCount() override { return nLayers; }
+    virtual OGRLayer   *GetLayer( int ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
+    virtual void        ResetReading() override;
+    virtual OGRFeature* GetNextFeature( OGRLayer** ppoBelongingLayer,
+                                        double* pdfProgressPct,
+                                       GDALProgressFunc pfnProgress,
+                                        void* pProgressData ) override;
 
     int                 Open ( const char* pszFilename, char** papszOpenOptions );
 
-    int                 ResetReading();
-    bool                ParseNextChunk(int nIdxLayer);
+    int                 MyResetReading();
+    bool                ParseNextChunk(int nIdxLayer,
+                                       GDALProgressFunc pfnProgress,
+                                       void* pProgressData);
     OGRErr              GetExtent( OGREnvelope *psExtent );
     int                 IsInterleavedReading();
 
diff --git a/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp b/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
index 827c13b..f58ce36 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrosmdatasource.cpp 34098 2016-04-25 10:11:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMDataSource class.
@@ -47,78 +46,103 @@
 
 static const int LIMIT_IDS_PER_REQUEST = 200;
 
-#define MAX_NODES_PER_WAY 2000
+static const int MAX_NODES_PER_WAY = 2000;
 
-#define IDX_LYR_POINTS           0
-#define IDX_LYR_LINES            1
-#define IDX_LYR_MULTILINESTRINGS 2
-#define IDX_LYR_MULTIPOLYGONS    3
-#define IDX_LYR_OTHER_RELATIONS  4
+static const int IDX_LYR_POINTS = 0;
+static const int IDX_LYR_LINES = 1;
+static const int IDX_LYR_MULTILINESTRINGS = 2;
+static const int IDX_LYR_MULTIPOLYGONS = 3;
+static const int IDX_LYR_OTHER_RELATIONS = 4;
 
-#define DBL_TO_INT(x)            (int)floor((x) * 1e7 + 0.5)
-#define INT_TO_DBL(x)            ((x) / 1e7)
-
-#define MAX_COUNT_FOR_TAGS_IN_WAY   255  /* must fit on 1 byte */
-#define MAX_SIZE_FOR_TAGS_IN_WAY    1024
-
-/* 5 bytes for encoding a int : really the worst case scenario ! */
-#define WAY_BUFFER_SIZE (1 /*is_area*/ + 1 + MAX_NODES_PER_WAY * 2 * 5 + MAX_SIZE_FOR_TAGS_IN_WAY)
-
-#define NODE_PER_BUCKET     65536
+static int DBL_TO_INT( double x )
+{
+  return static_cast<int>(floor(x * 1.0e7 + 0.5));
+}
+static double INT_TO_DBL( int x ) { return x / 1.0e7; }
 
- /* Initial Maximum count of buckets */
-#define INIT_BUCKET_COUNT        65536
+static const int MAX_COUNT_FOR_TAGS_IN_WAY = 255;  // Must fit on 1 byte.
+static const int MAX_SIZE_FOR_TAGS_IN_WAY = 1024;
 
-#define VALID_ID_FOR_CUSTOM_INDEXING(_id) ((_id) >= 0 && (_id / NODE_PER_BUCKET) < INT_MAX)
+// 5 bytes for encoding a int : really the worst case scenario!
+static const int WAY_BUFFER_SIZE =
+    1 /*is_area*/ + 1 + MAX_NODES_PER_WAY * 2 * 5 + MAX_SIZE_FOR_TAGS_IN_WAY;
 
-/* Minimum size of data written on disk, in *uncompressed* case */
-#define SECTOR_SIZE         512
-/* Which represents, 64 nodes */
-/* #define NODE_PER_SECTOR     SECTOR_SIZE / (2 * 4) */
-#define NODE_PER_SECTOR     64
-#define NODE_PER_SECTOR_SHIFT   6
+static const int NODE_PER_BUCKET = 65536;
 
-/* Per bucket, we keep track of the absence/presence of sectors */
-/* only, to reduce memory usage */
-/* #define BUCKET_BITMAP_SIZE  NODE_PER_BUCKET / (8 * NODE_PER_SECTOR) */
-#define BUCKET_BITMAP_SIZE  128
+// Initial Maximum count of buckets.
+static const int INIT_BUCKET_COUNT = 65536;
 
-/* #define BUCKET_SECTOR_SIZE_ARRAY_SIZE  NODE_PER_BUCKET / NODE_PER_SECTOR */
-/* Per bucket, we keep track of the real size of the sector. Each sector */
-/* size is encoded in a single byte, whose value is : */
-/* (sector_size in bytes - 8 ) / 2, minus 8. 252 means uncompressed */
-#define BUCKET_SECTOR_SIZE_ARRAY_SIZE   1024
+static bool VALID_ID_FOR_CUSTOM_INDEXING( GIntBig _id )
+{
+    return
+        _id >= 0 &&
+        _id / NODE_PER_BUCKET < INT_MAX;
+}
 
-/* Must be a multiple of both BUCKET_BITMAP_SIZE and BUCKET_SECTOR_SIZE_ARRAY_SIZE */
-#define PAGE_SIZE   4096
+// Minimum size of data written on disk, in *uncompressed* case.
+static const int SECTOR_SIZE = 512;
+// Which represents, 64 nodes
+// static const int NODE_PER_SECTOR = SECTOR_SIZE / (2 * 4);
+static const int NODE_PER_SECTOR = 64;
+static const int NODE_PER_SECTOR_SHIFT = 6;
+
+// Per bucket, we keep track of the absence/presence of sectors
+// only, to reduce memory usage.
+// #define BUCKET_BITMAP_SIZE  NODE_PER_BUCKET / (8 * NODE_PER_SECTOR)
+static const int BUCKET_BITMAP_SIZE = 128;
+
+// #define BUCKET_SECTOR_SIZE_ARRAY_SIZE  NODE_PER_BUCKET / NODE_PER_SECTOR
+// Per bucket, we keep track of the real size of the sector. Each sector
+// size is encoded in a single byte, whose value is:
+// (sector_size in bytes - 8 ) / 2, minus 8. 252 means uncompressed
+static const int BUCKET_SECTOR_SIZE_ARRAY_SIZE = 1024;
+
+// Must be a multiple of both BUCKET_BITMAP_SIZE and
+// BUCKET_SECTOR_SIZE_ARRAY_SIZE
+static const int PAGE_SIZE = 4096;
+
+// compressSize should not be greater than 512, so COMPRESS_SIZE_TO_BYTE() fits
+// on a byte.
+static GByte COMPRESS_SIZE_TO_BYTE( size_t nCompressSize )
+{
+    return static_cast<GByte>((nCompressSize - 8) / 2);
+}
 
-/* compressSize should not be greater than 512, so COMPRESS_SIZE_TO_BYTE() fits on a byte */
-#define COMPRESS_SIZE_TO_BYTE(nCompressSize)  (GByte)(((nCompressSize) - 8) / 2)
-#define ROUND_COMPRESS_SIZE(nCompressSize)    (((nCompressSize) + 1) / 2) * 2;
-#define COMPRESS_SIZE_FROM_BYTE(byte_on_size) ((byte_on_size) * 2 + 8)
+template<typename T> static T ROUND_COMPRESS_SIZE( T nCompressSize )
+{
+    return ((nCompressSize + 1) / 2) * 2;
+}
+static int COMPRESS_SIZE_FROM_BYTE( GByte byte_on_size )
+{
+    return static_cast<int>(byte_on_size) * 2 + 8;
+}
 
-/* Max number of features that are accumulated in pasWayFeaturePairs */
-#define MAX_DELAYED_FEATURES        75000
-/* Max number of tags that are accumulated in pasAccumulatedTags */
-#define MAX_ACCUMULATED_TAGS        MAX_DELAYED_FEATURES * 5
-/* Max size of the string with tag values that are accumulated in pabyNonRedundantValues */
-#define MAX_NON_REDUNDANT_VALUES    MAX_DELAYED_FEATURES * 10
-/* Max number of features that are accumulated in panUnsortedReqIds */
-#define MAX_ACCUMULATED_NODES       1000000
+// Max number of features that are accumulated in pasWayFeaturePairs.
+static const int MAX_DELAYED_FEATURES = 75000;
+// Max number of tags that are accumulated in pasAccumulatedTags.
+static const int MAX_ACCUMULATED_TAGS  = MAX_DELAYED_FEATURES * 5;
+// Max size of the string with tag values that are accumulated in
+// pabyNonRedundantValues.
+static const int MAX_NON_REDUNDANT_VALUES = MAX_DELAYED_FEATURES * 10;
+// Max number of features that are accumulated in panUnsortedReqIds
+static const int MAX_ACCUMULATED_NODES = 1000000;
 
 #ifdef ENABLE_NODE_LOOKUP_BY_HASHING
-/* Size of panHashedIndexes array. Must be in the list at */
-/* http://planetmath.org/goodhashtableprimes , and greater than MAX_ACCUMULATED_NODES */
-#define HASHED_INDEXES_ARRAY_SIZE   3145739
-//#define HASHED_INDEXES_ARRAY_SIZE   1572869
-#define COLLISION_BUCKET_ARRAY_SIZE ((MAX_ACCUMULATED_NODES / 100) * 40)
-/* hash function = identity ! */
+// Size of panHashedIndexes array. Must be in the list at
+// http://planetmath.org/goodhashtableprimes , and greater than
+// MAX_ACCUMULATED_NODES.
+static const int HASHED_INDEXES_ARRAY_SIZE = 3145739;
+// #define HASHED_INDEXES_ARRAY_SIZE   1572869
+static const int COLLISION_BUCKET_ARRAY_SIZE =
+    (MAX_ACCUMULATED_NODES / 100) * 40;
+
+// hash function = identity
 #define HASH_ID_FUNC(x)             ((GUIntBig)(x))
 #endif // ENABLE_NODE_LOOKUP_BY_HASHING
 
-//#define FAKE_LOOKUP_NODES
+// #define FAKE_LOOKUP_NODES
 
-//#define DEBUG_MEM_USAGE
+// #define DEBUG_MEM_USAGE
 #ifdef DEBUG_MEM_USAGE
 size_t GetMaxTotalAllocs();
 #endif
@@ -126,7 +150,7 @@ size_t GetMaxTotalAllocs();
 static void WriteVarInt64(GUIntBig nSVal, GByte** ppabyData);
 static void WriteVarSInt64(GIntBig nSVal, GByte** ppabyData);
 
-CPL_CVSID("$Id: ogrosmdatasource.cpp 34098 2016-04-25 10:11:11Z rouault $");
+CPL_CVSID("$Id: ogrosmdatasource.cpp 37689 2017-03-11 20:30:47Z rouault $");
 
 class DSToBeOpened
 {
@@ -143,8 +167,8 @@ static std::vector<DSToBeOpened>  oListDSToBeOpened;
 /*                    AddInterestLayersForDSName()                      */
 /************************************************************************/
 
-static void AddInterestLayersForDSName(const CPLString& osDSName,
-                                       const CPLString& osInterestLayers)
+static void AddInterestLayersForDSName( const CPLString& osDSName,
+                                        const CPLString& osInterestLayers )
 {
     CPLMutexHolder oMutexHolder(&hMutex);
     DSToBeOpened oDSToBeOpened;
@@ -158,7 +182,7 @@ static void AddInterestLayersForDSName(const CPLString& osDSName,
 /*                    GetInterestLayersForDSName()                      */
 /************************************************************************/
 
-static CPLString GetInterestLayersForDSName(const CPLString& osDSName)
+static CPLString GetInterestLayersForDSName( const CPLString& osDSName )
 {
     CPLMutexHolder oMutexHolder(&hMutex);
     GIntBig nPID = CPLGetPID();
@@ -189,9 +213,7 @@ OGROSMDataSource::OGROSMDataSource() :
     psParser(NULL),
     bHasParsedFirstChunk(false),
     bStopParsing(false),
-#ifdef HAVE_SQLITE_VFS
     pMyVFS(NULL),
-#endif
     hDB(NULL),
     hInsertNodeStmt(NULL),
     hInsertWayStmt(NULL),
@@ -256,7 +278,8 @@ OGROSMDataSource::OGROSMDataSource() :
     pabySector(NULL),
     papsBuckets(NULL),
     nBuckets(0),
-    bNeedsToSaveWayInfo(false)
+    bNeedsToSaveWayInfo(false),
+    m_nFileSize(FILESIZE_NOT_INIT)
 {}
 
 /************************************************************************/
@@ -287,16 +310,14 @@ OGROSMDataSource::~OGROSMDataSource()
     if( hDBForComputedAttributes != NULL )
         sqlite3_close(hDBForComputedAttributes);
 
-#ifdef HAVE_SQLITE_VFS
-    if (pMyVFS)
+    if( pMyVFS )
     {
         sqlite3_vfs_unregister(pMyVFS);
         CPLFree(pMyVFS->pAppData);
         CPLFree(pMyVFS);
     }
-#endif
 
-    if( osTmpDBName.size() && bMustUnlink )
+    if( !osTmpDBName.empty() && bMustUnlink )
     {
         const char* pszVal = CPLGetConfigOption("OSM_UNLINK_TMPFILE", "YES");
         if( !EQUAL(pszVal, "NOT_EVEN_AT_END") )
@@ -343,7 +364,7 @@ OGROSMDataSource::~OGROSMDataSource()
 
     if( fpNodes )
         VSIFCloseL(fpNodes);
-    if( osNodesFilename.size() && bMustUnlinkNodesFile )
+    if( !osNodesFilename.empty() && bMustUnlinkNodesFile )
     {
         const char* pszVal = CPLGetConfigOption("OSM_UNLINK_TMPFILE", "YES");
         if( !EQUAL(pszVal, "NOT_EVEN_AT_END") )
@@ -450,10 +471,10 @@ static const GByte abyBitsCount[] = {
 4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
 };
 
-int OGROSMDataSource::IndexPoint(OSMNode* psNode)
+bool OGROSMDataSource::IndexPoint( OSMNode* psNode )
 {
     if( !bIndexPoints )
-        return TRUE;
+        return true;
 
     if( bCustomIndexing)
         return IndexPointCustom(psNode);
@@ -465,7 +486,7 @@ int OGROSMDataSource::IndexPoint(OSMNode* psNode)
 /*                          IndexPointSQLite()                          */
 /************************************************************************/
 
-int OGROSMDataSource::IndexPointSQLite(OSMNode* psNode)
+bool OGROSMDataSource::IndexPointSQLite(OSMNode* psNode)
 {
     sqlite3_bind_int64( hInsertNodeStmt, 1, psNode->nID );
 
@@ -476,7 +497,7 @@ int OGROSMDataSource::IndexPointSQLite(OSMNode* psNode)
     sqlite3_bind_blob( hInsertNodeStmt, 2, &sLonLat, sizeof(sLonLat),
                        SQLITE_STATIC );
 
-    int rc = sqlite3_step( hInsertNodeStmt );
+    const int rc = sqlite3_step( hInsertNodeStmt );
     sqlite3_reset( hInsertNodeStmt );
     if( !(rc == SQLITE_OK || rc == SQLITE_DONE) )
     {
@@ -485,7 +506,7 @@ int OGROSMDataSource::IndexPointSQLite(OSMNode* psNode)
             psNode->nID, sqlite3_errmsg(hDB));
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -508,7 +529,7 @@ bool OGROSMDataSource::FlushCurrentSector()
 /*                            AllocBucket()                             */
 /************************************************************************/
 
-bool OGROSMDataSource::AllocBucket(int iBucket)
+bool OGROSMDataSource::AllocBucket( int iBucket )
 {
     if( bCompressNodes )
     {
@@ -552,11 +573,11 @@ bool OGROSMDataSource::AllocBucket(int iBucket)
 /*                         AllocMoreBuckets()                           */
 /************************************************************************/
 
-bool OGROSMDataSource::AllocMoreBuckets(int nNewBucketIdx, bool bAllocBucket)
+bool OGROSMDataSource::AllocMoreBuckets( int nNewBucketIdx, bool bAllocBucket )
 {
     CPLAssert(nNewBucketIdx >= nBuckets);
 
-    const int nNewBuckets = MAX(nBuckets + nBuckets / 2, nNewBucketIdx);
+    const int nNewBuckets = std::max(nBuckets + nBuckets / 2, nNewBucketIdx);
 
     size_t nNewSize = sizeof(Bucket) * nNewBuckets;
     if( static_cast<GUIntBig>(nNewSize) !=
@@ -577,8 +598,8 @@ bool OGROSMDataSource::AllocMoreBuckets(int nNewBucketIdx, bool bAllocBucket)
     papsBuckets = papsNewBuckets;
 
     bool bOOM = false;
-    int i;
-    for(i = nBuckets; i < nNewBuckets && !bOOM; i++)
+    int i = nBuckets;  // Used after for.
+    for( ; i < nNewBuckets && !bOOM; i++)
     {
         papsBuckets[i].nOff = -1;
         if( bAllocBucket )
@@ -654,8 +675,8 @@ bool OGROSMDataSource::FlushCurrentSectorCompressedCase()
     abyOutBuffer[nCompressSize] = 0;
 
     nCompressSize = ROUND_COMPRESS_SIZE(nCompressSize);
-    GByte* pabyToWrite;
-    if(nCompressSize >= SECTOR_SIZE)
+    GByte* pabyToWrite = NULL;
+    if( nCompressSize >= static_cast<size_t>(SECTOR_SIZE) )
     {
         nCompressSize = SECTOR_SIZE;
         pabyToWrite = pabySector;
@@ -696,7 +717,8 @@ bool OGROSMDataSource::FlushCurrentSectorCompressedCase()
 
 bool OGROSMDataSource::FlushCurrentSectorNonCompressedCase()
 {
-    if( VSIFWriteL(pabySector, 1, SECTOR_SIZE, fpNodes) == SECTOR_SIZE )
+    if( VSIFWriteL(pabySector, 1, static_cast<size_t>(SECTOR_SIZE),
+                   fpNodes) == static_cast<size_t>(SECTOR_SIZE) )
     {
         memset(pabySector, 0, SECTOR_SIZE);
         nNodesFileSize += SECTOR_SIZE;
@@ -797,7 +819,7 @@ bool OGROSMDataSource::IndexPointCustom(OSMNode* psNode)
 /*                             NotifyNodes()                            */
 /************************************************************************/
 
-void OGROSMDataSource::NotifyNodes(unsigned int nNodes, OSMNode* pasNodes)
+void OGROSMDataSource::NotifyNodes( unsigned int nNodes, OSMNode* pasNodes )
 {
     const OGREnvelope* psEnvelope =
         papoLayers[IDX_LYR_POINTS]->GetSpatialFilterEnvelope();
@@ -829,7 +851,7 @@ void OGROSMDataSource::NotifyNodes(unsigned int nNodes, OSMNode* pasNodes)
                 const char* pszK = pasTags[j].pszK;
                 if( papoLayers[IDX_LYR_POINTS]->IsSignificantKey(pszK) )
                 {
-                    bInterestingTag = TRUE;
+                    bInterestingTag = true;
                     break;
                 }
             }
@@ -844,7 +866,7 @@ void OGROSMDataSource::NotifyNodes(unsigned int nNodes, OSMNode* pasNodes)
                 new OGRPoint(pasNodes[i].dfLon, pasNodes[i].dfLat));
 
             papoLayers[IDX_LYR_POINTS]->SetFieldsFromTags(
-                poFeature, pasNodes[i].nID, FALSE, pasNodes[i].nTags,
+                poFeature, pasNodes[i].nID, false, pasNodes[i].nTags,
                 pasTags, &pasNodes[i].sInfo );
 
             int bFilteredOut = FALSE;
@@ -855,7 +877,7 @@ void OGROSMDataSource::NotifyNodes(unsigned int nNodes, OSMNode* pasNodes)
                 bStopParsing = true;
                 break;
             }
-            else if (!bFilteredOut)
+            else if( !bFilteredOut )
                 bFeatureAdded = true;
         }
     }
@@ -904,7 +926,7 @@ void OGROSMDataSource::LookupNodes( )
 #ifdef DEBUG_COLLISIONS
                 nCollisions ++;
 #endif
-                int iBucket;
+                int iBucket = 0;
                 if( nIdx >= 0 )
                 {
                     if(iNextFreeBucket == COLLISION_BUCKET_ARRAY_SIZE)
@@ -921,7 +943,9 @@ void OGROSMDataSource::LookupNodes( )
                     iNextFreeBucket ++;
                 }
                 else
+                {
                     iBucket = -nIdx - 2;
+                }
                 if(iNextFreeBucket == COLLISION_BUCKET_ARRAY_SIZE)
                 {
                     CPLDebug("OSM", "Too many collisions. Disabling hashed indexing");
@@ -963,7 +987,8 @@ void OGROSMDataSource::LookupNodes( )
 
 void OGROSMDataSource::LookupNodesSQLite( )
 {
-    CPLAssert(nUnsortedReqIds <= MAX_ACCUMULATED_NODES);
+    CPLAssert(
+        nUnsortedReqIds <= static_cast<unsigned int>(MAX_ACCUMULATED_NODES));
 
     nReqIds = 0;
     for( unsigned int i = 0; i < nUnsortedReqIds; i++)
@@ -978,7 +1003,7 @@ void OGROSMDataSource::LookupNodesSQLite( )
     unsigned int j = 0;
     for( unsigned int i = 0; i < nReqIds; i++)
     {
-        if (!(i > 0 && panReqIds[i] == panReqIds[i-1]))
+        if( !(i > 0 && panReqIds[i] == panReqIds[i-1]) )
             panReqIds[j++] = panReqIds[i];
     }
     nReqIds = j;
@@ -1031,7 +1056,7 @@ static GIntBig ReadVarSInt64(GByte** ppabyPtr)
 /*                           DecompressSector()                         */
 /************************************************************************/
 
-static int DecompressSector(GByte* pabyIn, int nSectorSize, GByte* pabyOut)
+static bool DecompressSector( GByte* pabyIn, int nSectorSize, GByte* pabyOut )
 {
     GByte* pabyPtr = pabyIn;
     LonLat* pasLonLatOut = (LonLat*) pabyOut;
@@ -1068,7 +1093,7 @@ static int DecompressSector(GByte* pabyIn, int nSectorSize, GByte* pabyOut)
 
     int nRead = (int)(pabyPtr - pabyIn);
     nRead = ROUND_COMPRESS_SIZE(nRead);
-    return( nRead == nSectorSize );
+    return nRead == nSectorSize;
 }
 
 /************************************************************************/
@@ -1090,11 +1115,10 @@ void OGROSMDataSource::LookupNodesCustom( )
         nBucketOld = -1;
     }
 
-    unsigned int i;
-
-    CPLAssert(nUnsortedReqIds <= MAX_ACCUMULATED_NODES);
+    CPLAssert(
+        nUnsortedReqIds <= static_cast<unsigned int>(MAX_ACCUMULATED_NODES));
 
-    for(i = 0; i < nUnsortedReqIds; i++)
+    for( unsigned int i = 0; i < nUnsortedReqIds; i++ )
     {
         GIntBig id = panUnsortedReqIds[i];
 
@@ -1130,16 +1154,16 @@ void OGROSMDataSource::LookupNodesCustom( )
     std::sort(panReqIds, panReqIds + nReqIds);
 
     /* Remove duplicates */
-    unsigned int j = 0;
-    for(i = 0; i < nReqIds; i++)
+    unsigned int j = 0;  // Used after for.
+    for( unsigned int i = 0; i < nReqIds; i++)
     {
-        if (!(i > 0 && panReqIds[i] == panReqIds[i-1]))
+        if( !(i > 0 && panReqIds[i] == panReqIds[i-1]) )
             panReqIds[j++] = panReqIds[i];
     }
     nReqIds = j;
 
 #ifdef FAKE_LOOKUP_NODES
-    for(i = 0; i < nReqIds; i++)
+    for( unsigned int i = 0; i < nReqIds; i++)
     {
         pasLonLatArray[i].nLon = 0;
         pasLonLatArray[i].nLat = 0;
@@ -1158,9 +1182,7 @@ void OGROSMDataSource::LookupNodesCustom( )
 
 void OGROSMDataSource::LookupNodesCustomCompressedCase()
 {
-    unsigned int i;
-    unsigned int j = 0;
-#define SECURITY_MARGIN     (8 + 8 + 2 * NODE_PER_SECTOR)
+    static const int SECURITY_MARGIN = 8 + 8 + 2 * NODE_PER_SECTOR;
     GByte abyRawSector[SECTOR_SIZE + SECURITY_MARGIN];
     memset(abyRawSector + SECTOR_SIZE, 0, SECURITY_MARGIN);
 
@@ -1169,14 +1191,15 @@ void OGROSMDataSource::LookupNodesCustomCompressedCase()
     int k = 0;
     int nOffFromBucketStart = 0;
 
-    for(i = 0; i < nReqIds; i++)
+    unsigned int j = 0;  // Used after for.
+    for( unsigned int i = 0; i < nReqIds; i++ )
     {
-        GIntBig id = panReqIds[i];
-
-        int nBucket = static_cast<int>(id / NODE_PER_BUCKET);
-        int nOffInBucket = static_cast<int>(id % NODE_PER_BUCKET);
-        int nOffInBucketReduced = nOffInBucket >> NODE_PER_SECTOR_SHIFT;
-        int nOffInBucketReducedRemainer = nOffInBucket & ((1 << NODE_PER_SECTOR_SHIFT) - 1);
+        const GIntBig id = panReqIds[i];
+        const int nBucket = static_cast<int>(id / NODE_PER_BUCKET);
+        const int nOffInBucket = static_cast<int>(id % NODE_PER_BUCKET);
+        const int nOffInBucketReduced = nOffInBucket >> NODE_PER_SECTOR_SHIFT;
+        const int nOffInBucketReducedRemainer =
+            nOffInBucket & ((1 << NODE_PER_SECTOR_SHIFT) - 1);
 
         if( nBucket != l_nBucketOld )
         {
@@ -1185,7 +1208,7 @@ void OGROSMDataSource::LookupNodesCustomCompressedCase()
             nOffFromBucketStart = 0;
         }
 
-        if ( nOffInBucketReduced != l_nOffInBucketReducedOld )
+        if( nOffInBucketReduced != l_nOffInBucketReducedOld )
         {
             if( nBucket >= nBuckets )
             {
@@ -1202,20 +1225,25 @@ void OGROSMDataSource::LookupNodesCustomCompressedCase()
                 continue;
                 // FIXME ?
             }
-            int nSectorSize = COMPRESS_SIZE_FROM_BYTE(psBucket->u.panSectorSize[nOffInBucketReduced]);
+            const int nSectorSize =
+                COMPRESS_SIZE_FROM_BYTE(
+                    psBucket->u.panSectorSize[nOffInBucketReduced]);
 
             /* If we stay in the same bucket, we can reuse the previously */
             /* computed offset, instead of starting from bucket start */
-            for(; k < nOffInBucketReduced; k++)
+            for( ; k < nOffInBucketReduced; k++ )
             {
                 if( psBucket->u.panSectorSize[k] )
-                    nOffFromBucketStart += COMPRESS_SIZE_FROM_BYTE(psBucket->u.panSectorSize[k]);
+                    nOffFromBucketStart +=
+                        COMPRESS_SIZE_FROM_BYTE(psBucket->u.panSectorSize[k]);
             }
 
             VSIFSeekL(fpNodes, psBucket->nOff + nOffFromBucketStart, SEEK_SET);
             if( nSectorSize == SECTOR_SIZE )
             {
-                if( VSIFReadL(pabySector, 1, SECTOR_SIZE, fpNodes) != SECTOR_SIZE )
+                if( VSIFReadL(pabySector, 1,
+                              static_cast<size_t>(SECTOR_SIZE),
+                              fpNodes) != static_cast<size_t>(SECTOR_SIZE) )
                 {
                     CPLError(CE_Failure,  CPLE_AppDefined,
                             "Cannot read node " CPL_FRMT_GIB, id);
@@ -1225,7 +1253,8 @@ void OGROSMDataSource::LookupNodesCustomCompressedCase()
             }
             else
             {
-                if( (int)VSIFReadL(abyRawSector, 1, nSectorSize, fpNodes) != nSectorSize )
+                if( static_cast<int>(VSIFReadL(abyRawSector, 1, nSectorSize,
+                                               fpNodes)) != nSectorSize )
                 {
                     CPLError(CE_Failure,  CPLE_AppDefined,
                             "Cannot read sector for node " CPL_FRMT_GIB, id);
@@ -1265,20 +1294,19 @@ void OGROSMDataSource::LookupNodesCustomCompressedCase()
 
 void OGROSMDataSource::LookupNodesCustomNonCompressedCase()
 {
-    unsigned int i;
-    unsigned int j = 0;
+    unsigned int j = 0;  // Used after for.
 
-    for(i = 0; i < nReqIds; i++)
+    for( unsigned int i = 0; i < nReqIds; i++ )
     {
-        GIntBig id = panReqIds[i];
-
-        int nBucket = static_cast<int>(id / NODE_PER_BUCKET);
-        int nOffInBucket = static_cast<int>(id % NODE_PER_BUCKET);
-        int nOffInBucketReduced = nOffInBucket >> NODE_PER_SECTOR_SHIFT;
-        int nOffInBucketReducedRemainer = nOffInBucket & ((1 << NODE_PER_SECTOR_SHIFT) - 1);
+        const GIntBig id = panReqIds[i];
+        const int nBucket = static_cast<int>(id / NODE_PER_BUCKET);
+        const int nOffInBucket = static_cast<int>(id % NODE_PER_BUCKET);
+        const int nOffInBucketReduced = nOffInBucket >> NODE_PER_SECTOR_SHIFT;
+        const int nOffInBucketReducedRemainer =
+            nOffInBucket & ((1 << NODE_PER_SECTOR_SHIFT) - 1);
 
-        int nBitmapIndex = nOffInBucketReduced / 8;
-        int nBitmapRemainer = nOffInBucketReduced % 8;
+        const int nBitmapIndex = nOffInBucketReduced / 8;
+        const int nBitmapRemainer = nOffInBucketReduced % 8;
 
         if( nBucket >= nBuckets )
         {
@@ -1296,15 +1324,21 @@ void OGROSMDataSource::LookupNodesCustomNonCompressedCase()
             // FIXME ?
         }
 
-        int k;
         int nSector = 0;
-        for(k = 0; k < nBitmapIndex; k++)
+        for( int k = 0; k < nBitmapIndex; k++ )
             nSector += abyBitsCount[psBucket->u.pabyBitmap[k]];
-        if (nBitmapRemainer)
-            nSector += abyBitsCount[psBucket->u.pabyBitmap[nBitmapIndex] & ((1 << nBitmapRemainer) - 1)];
-
-        VSIFSeekL(fpNodes, psBucket->nOff + nSector * SECTOR_SIZE + nOffInBucketReducedRemainer * sizeof(LonLat), SEEK_SET);
-        if( VSIFReadL(pasLonLatArray + j, 1, sizeof(LonLat), fpNodes) != sizeof(LonLat) )
+        if( nBitmapRemainer )
+            nSector +=
+                abyBitsCount[psBucket->u.pabyBitmap[nBitmapIndex] &
+                             ((1 << nBitmapRemainer) - 1)];
+
+        VSIFSeekL(
+            fpNodes,
+            psBucket->nOff + nSector * SECTOR_SIZE +
+            nOffInBucketReducedRemainer * sizeof(LonLat),
+            SEEK_SET);
+        if( VSIFReadL(pasLonLatArray + j, 1,
+                      sizeof(LonLat), fpNodes) != sizeof(LonLat) )
         {
             CPLError(CE_Failure,  CPLE_AppDefined,
                      "Cannot read node " CPL_FRMT_GIB, id);
@@ -1324,7 +1358,7 @@ void OGROSMDataSource::LookupNodesCustomNonCompressedCase()
 /*                            WriteVarInt()                             */
 /************************************************************************/
 
-static void WriteVarInt(unsigned int nVal, GByte** ppabyData)
+static void WriteVarInt( unsigned int nVal, GByte** ppabyData )
 {
     GByte* pabyData = *ppabyData;
     while( true )
@@ -1346,7 +1380,7 @@ static void WriteVarInt(unsigned int nVal, GByte** ppabyData)
 /*                           WriteVarInt64()                            */
 /************************************************************************/
 
-static void WriteVarInt64(GUIntBig nVal, GByte** ppabyData)
+static void WriteVarInt64( GUIntBig nVal, GByte** ppabyData )
 {
     GByte* pabyData = *ppabyData;
     while( true )
@@ -1368,13 +1402,11 @@ static void WriteVarInt64(GUIntBig nVal, GByte** ppabyData)
 /*                           WriteVarSInt64()                           */
 /************************************************************************/
 
-static void WriteVarSInt64(GIntBig nSVal, GByte** ppabyData)
+static void WriteVarSInt64( GIntBig nSVal, GByte** ppabyData )
 {
-    GIntBig nVal;
-    if( nSVal >= 0 )
-        nVal = nSVal << 1;
-    else
-        nVal = ((-1-nSVal) << 1) + 1;
+    GIntBig nVal = nSVal >= 0
+        ? nSVal << 1
+        : ((-1-nSVal) << 1) + 1;
 
     GByte* pabyData = *ppabyData;
     while( true )
@@ -1388,7 +1420,7 @@ static void WriteVarSInt64(GIntBig nSVal, GByte** ppabyData)
 
         *pabyData = 0x80 | (GByte)(nVal & 0x7f);
         nVal >>= 7;
-        pabyData ++;
+        pabyData++;
     }
 }
 
@@ -1396,31 +1428,34 @@ static void WriteVarSInt64(GIntBig nSVal, GByte** ppabyData)
 /*                             CompressWay()                            */
 /************************************************************************/
 
-int OGROSMDataSource::CompressWay ( bool bIsArea, unsigned int nTags, IndexedKVP* pasTags,
+int OGROSMDataSource::CompressWay ( bool bIsArea, unsigned int nTags,
+                                    IndexedKVP* pasTags,
                                     int nPoints, LonLat* pasLonLatPairs,
                                     OSMInfo* psInfo,
                                     GByte* pabyCompressedWay )
 {
     GByte* pabyPtr = pabyCompressedWay;
     *pabyPtr = (bIsArea) ? 1 : 0;
-    pabyPtr ++;
-    pabyPtr ++; // skip tagCount
+    pabyPtr++;
+    pabyPtr++; // skip tagCount
 
     int nTagCount = 0;
-    CPLAssert(nTags < MAX_COUNT_FOR_TAGS_IN_WAY);
-    for(unsigned int iTag = 0; iTag < nTags; iTag++)
+    CPLAssert(nTags < static_cast<unsigned int>(MAX_COUNT_FOR_TAGS_IN_WAY));
+    for( unsigned int iTag = 0; iTag < nTags; iTag++ )
     {
-        if ((int)(pabyPtr - pabyCompressedWay) + 2 >= MAX_SIZE_FOR_TAGS_IN_WAY)
+        if( static_cast<int>(pabyPtr - pabyCompressedWay) + 2 >=
+            MAX_SIZE_FOR_TAGS_IN_WAY )
         {
             break;
         }
 
         WriteVarInt(pasTags[iTag].nKeyIndex, &pabyPtr);
 
-        /* to fit in 2 bytes, the theoretical limit would be 127 * 128 + 127 */
+        // To fit in 2 bytes, the theoretical limit would be 127 * 128 + 127.
         if( pasTags[iTag].bVIsIndex )
         {
-            if ((int)(pabyPtr - pabyCompressedWay) + 2 >= MAX_SIZE_FOR_TAGS_IN_WAY)
+            if( static_cast<int>(pabyPtr - pabyCompressedWay) + 2 >=
+                MAX_SIZE_FOR_TAGS_IN_WAY )
             {
                 break;
             }
@@ -1433,7 +1468,8 @@ int OGROSMDataSource::CompressWay ( bool bIsArea, unsigned int nTags, IndexedKVP
                 pasTags[iTag].u.nOffsetInpabyNonRedundantValues;
 
             int nLenV = static_cast<int>(strlen(pszV)) + 1;
-            if ((int)(pabyPtr - pabyCompressedWay) + 2 + nLenV >= MAX_SIZE_FOR_TAGS_IN_WAY)
+            if( static_cast<int>(pabyPtr - pabyCompressedWay) +
+                2 + nLenV >= MAX_SIZE_FOR_TAGS_IN_WAY )
             {
                 break;
             }
@@ -1473,9 +1509,8 @@ int OGROSMDataSource::CompressWay ( bool bIsArea, unsigned int nTags, IndexedKVP
     pabyPtr += sizeof(LonLat);
     for(int i=1;i<nPoints;i++)
     {
-        GIntBig nDiff64;
-
-        nDiff64 = (GIntBig)pasLonLatPairs[i].nLon - (GIntBig)pasLonLatPairs[i-1].nLon;
+        GIntBig nDiff64 =
+            (GIntBig)pasLonLatPairs[i].nLon - (GIntBig)pasLonLatPairs[i-1].nLon;
         WriteVarSInt64(nDiff64, &pabyPtr);
 
         nDiff64 = pasLonLatPairs[i].nLat - pasLonLatPairs[i-1].nLat;
@@ -1502,10 +1537,10 @@ int OGROSMDataSource::UncompressWay( int nBytes, GByte* pabyCompressedWay,
     unsigned int nTags = *pabyPtr;
     pabyPtr ++;
 
-    if (pnTags)
+    if( pnTags )
         *pnTags = nTags;
 
-    /* TODO? : some additional safety checks */
+    // TODO: Some additional safety checks.
     for(unsigned int iTag = 0; iTag < nTags; iTag++)
     {
         int nK = ReadVarInt32(&pabyPtr);
@@ -1523,8 +1558,10 @@ int OGROSMDataSource::UncompressWay( int nBytes, GByte* pabyCompressedWay,
         {
             CPLAssert(nK >= 0 && nK < (int)asKeys.size());
             pasTags[iTag].pszK = asKeys[nK]->pszK;
-            CPLAssert(nV == 0 || (nV > 0 && nV < (int)asKeys[nK]->asValues.size()));
-            pasTags[iTag].pszV = nV ? asKeys[nK]->asValues[nV] : (const char*) pszV;
+            CPLAssert(nV == 0 ||
+                      (nV > 0 && nV < (int)asKeys[nK]->asValues.size()));
+            pasTags[iTag].pszV =
+                nV ? asKeys[nK]->asValues[nV] : (const char*) pszV;
         }
     }
 
@@ -1664,7 +1701,7 @@ void OGROSMDataSource::ProcessWaysBatch()
                          panReqIds[nIdx] != psWayFeaturePairs->panNodeRefs[i] )
                     nIdx = -1;
 
-                if (nIdx >= 0)
+                if( nIdx >= 0 )
                 {
                     pasLonLatCache[nFound].nLon = pasLonLatArray[nIdx].nLon;
                     pasLonLatCache[nFound].nLat = pasLonLatArray[nIdx].nLat;
@@ -1689,7 +1726,7 @@ void OGROSMDataSource::ProcessWaysBatch()
                 }
                 else
                     nIdx = FindNode( psWayFeaturePairs->panNodeRefs[i] );
-                if (nIdx >= 0)
+                if( nIdx >= 0 )
                 {
                     pasLonLatCache[nFound].nLon = pasLonLatArray[nIdx].nLon;
                     pasLonLatCache[nFound].nLat = pasLonLatArray[nIdx].nLat;
@@ -1757,7 +1794,7 @@ void OGROSMDataSource::ProcessWaysBatch()
                                                    &bFilteredOut,
                                                    !bFeatureAdded) )
             bStopParsing = true;
-        else if (!bFilteredOut)
+        else if( !bFilteredOut )
             bFeatureAdded = true;
     }
 
@@ -1818,6 +1855,12 @@ bool OGROSMDataSource::IsClosedWayTaggedAsPolygon( unsigned int nTags, const OSM
         {
             bIsArea = true;
         }
+        else if( aoSetClosedWaysArePolygons.find(
+                        pszK + std::string("=") + pasTags[i].pszV) !=
+                  aoSetClosedWaysArePolygons.end() )
+        {
+            bIsArea = true;
+        }
     }
     return bIsArea;
 }
@@ -1826,14 +1869,15 @@ bool OGROSMDataSource::IsClosedWayTaggedAsPolygon( unsigned int nTags, const OSM
 /*                              NotifyWay()                             */
 /************************************************************************/
 
-void OGROSMDataSource::NotifyWay (OSMWay* psWay)
+void OGROSMDataSource::NotifyWay( OSMWay* psWay )
 {
     nWaysProcessed++;
-    if( (nWaysProcessed % 10000) == 0 )
+    if( nWaysProcessed % 10000 == 0 )
     {
         CPLDebug("OSM", "Ways processed : %d", nWaysProcessed);
 #ifdef DEBUG_MEM_USAGE
-        CPLDebug("OSM", "GetMaxTotalAllocs() = " CPL_FRMT_GUIB, (GUIntBig)GetMaxTotalAllocs());
+        CPLDebug("OSM", "GetMaxTotalAllocs() = " CPL_FRMT_GUIB,
+                 static_cast<GUIntBig>(GetMaxTotalAllocs()));
 #endif
     }
 
@@ -1841,7 +1885,7 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
         return;
 
     //printf("way %d : %d nodes\n", (int)psWay->nID, (int)psWay->nRefs);
-    if( psWay->nRefs > MAX_NODES_PER_WAY )
+    if( psWay->nRefs > static_cast<unsigned int>(MAX_NODES_PER_WAY) )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Ways with more than %d nodes are not supported",
@@ -1879,18 +1923,21 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
 
     OGRFeature* poFeature = NULL;
     bool bAttrFilterAlreadyEvaluated = false;
-    if( !bIsArea && papoLayers[IDX_LYR_LINES]->IsUserInterested() && bInterestingTag )
+    if( !bIsArea && papoLayers[IDX_LYR_LINES]->IsUserInterested() &&
+        bInterestingTag )
     {
         poFeature = new OGRFeature(papoLayers[IDX_LYR_LINES]->GetLayerDefn());
 
         papoLayers[IDX_LYR_LINES]->SetFieldsFromTags(
-            poFeature, psWay->nID, FALSE, psWay->nTags, psWay->pasTags, &psWay->sInfo );
+            poFeature, psWay->nID, false, psWay->nTags, psWay->pasTags,
+            &psWay->sInfo );
 
-        /* Optimization : if we have an attribute filter, that does not require geometry, */
-        /* and if we don't need to index ways, then we can just evaluate the attribute */
-        /* filter without the geometry */
+        // Optimization: if we have an attribute filter, that does not require
+        // geometry, and if we don't need to index ways, then we can just
+        // evaluate the attribute filter without the geometry.
         if( papoLayers[IDX_LYR_LINES]->HasAttributeFilter() &&
-            !papoLayers[IDX_LYR_LINES]->AttributeFilterEvaluationNeedsGeometry() &&
+            !papoLayers[IDX_LYR_LINES]->
+                AttributeFilterEvaluationNeedsGeometry() &&
             !bIndexWays )
         {
             if( !papoLayers[IDX_LYR_LINES]->EvaluateAttributeFilter(poFeature) )
@@ -1906,9 +1953,11 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
         return;
     }
 
-    if( nUnsortedReqIds + psWay->nRefs > MAX_ACCUMULATED_NODES ||
+    if( nUnsortedReqIds + psWay->nRefs >
+        static_cast<unsigned int>(MAX_ACCUMULATED_NODES) ||
         nWayFeaturePairs == MAX_DELAYED_FEATURES ||
-        nAccumulatedTags + psWay->nTags > MAX_ACCUMULATED_TAGS ||
+        nAccumulatedTags + psWay->nTags >
+        static_cast<unsigned int>(MAX_ACCUMULATED_TAGS) ||
         nNonRedundantValuesLen + 1024 > MAX_NON_REDUNDANT_VALUES )
     {
         ProcessWaysBatch();
@@ -1921,7 +1970,8 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
     psWayFeaturePairs->panNodeRefs = panUnsortedReqIds + nUnsortedReqIds;
     psWayFeaturePairs->poFeature = poFeature;
     psWayFeaturePairs->bIsArea = bIsArea;
-    psWayFeaturePairs->bAttrFilterAlreadyEvaluated = bAttrFilterAlreadyEvaluated;
+    psWayFeaturePairs->bAttrFilterAlreadyEvaluated =
+        bAttrFilterAlreadyEvaluated;
 
     if( bIsArea && papoLayers[IDX_LYR_MULTIPOLYGONS]->IsUserInterested() )
     {
@@ -1935,7 +1985,7 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
             else
             {
                 OGRField sField;
-                if (OGRParseXMLDateTime(psWay->sInfo.ts.pszTimeStamp, &sField))
+                if( OGRParseXMLDateTime(psWay->sInfo.ts.pszTimeStamp, &sField) )
                 {
                     struct tm brokendown;
                     brokendown.tm_year = sField.Date.Year - 1900;
@@ -1973,25 +2023,25 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
             const char* pszK = psWay->pasTags[iTag].pszK;
             const char* pszV = psWay->pasTags[iTag].pszV;
 
-            if (strcmp(pszK, "area") == 0)
+            if( strcmp(pszK, "area") == 0 )
                 continue;
-            if (strcmp(pszK, "created_by") == 0)
+            if( strcmp(pszK, "created_by") == 0 )
                 continue;
-            if (strcmp(pszK, "converted_by") == 0)
+            if( strcmp(pszK, "converted_by") == 0 )
                 continue;
-            if (strcmp(pszK, "note") == 0)
+            if( strcmp(pszK, "note") == 0 )
                 continue;
-            if (strcmp(pszK, "todo") == 0)
+            if( strcmp(pszK, "todo") == 0 )
                 continue;
-            if (strcmp(pszK, "fixme") == 0)
+            if( strcmp(pszK, "fixme") == 0 )
                 continue;
-            if (strcmp(pszK, "FIXME") == 0)
+            if( strcmp(pszK, "FIXME") == 0 )
                 continue;
 
             std::map<const char*, KeyDesc*, ConstCharComp>::iterator oIterK =
                 aoMapIndexedKeys.find(pszK);
-            KeyDesc* psKD;
-            if (oIterK == aoMapIndexedKeys.end())
+            KeyDesc* psKD = NULL;
+            if( oIterK == aoMapIndexedKeys.end() )
             {
                 if( nNextKeyIndex >= 32768 ) /* somewhat arbitrary */
                 {
@@ -2023,8 +2073,8 @@ void OGROSMDataSource::NotifyWay (OSMWay* psWay)
             {
                 std::map<const char*, int, ConstCharComp>::iterator oIterV;
                 oIterV = psKD->anMapV.find(pszV);
-                int nValueIndex;
-                if (oIterV == psKD->anMapV.end())
+                int nValueIndex = 0;
+                if( oIterV == psKD->anMapV.end() )
                 {
                     char* pszVDup = CPLStrdup(pszV);
                     nValueIndex = (int)psKD->asValues.size();
@@ -2103,12 +2153,12 @@ unsigned int OGROSMDataSource::LookupWays( std::map< GIntBig,
 {
     unsigned int nFound = 0;
     unsigned int iCur = 0;
-    unsigned int i;
 
     while( iCur < psRelation->nMembers )
     {
         unsigned int nToQuery = 0;
-        for(i=iCur;i<psRelation->nMembers;i++)
+        unsigned int i = iCur;  // Used after for.
+        for( ; i < psRelation->nMembers; i++ )
         {
             if( psRelation->pasMembers[i].eType == MEMBER_WAY &&
                 strcmp(psRelation->pasMembers[i].pszRole, "subarea") != 0 )
@@ -2169,13 +2219,12 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
                                                  unsigned int* pnTags,
                                                  OSMTag* pasTags)
 {
-
     std::map< GIntBig, std::pair<int,void*> > aoMapWays;
     LookupWays( aoMapWays, psRelation );
 
     bool bMissing = false;
-    unsigned int i;
-    for(i = 0; i < psRelation->nMembers; i ++ )
+
+    for( unsigned int i = 0; i < psRelation->nMembers; i++ )
     {
         if( psRelation->pasMembers[i].eType == MEMBER_WAY &&
             strcmp(psRelation->pasMembers[i].pszRole, "subarea") != 0 )
@@ -2207,7 +2256,7 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
     if( pnTags != NULL )
         *pnTags = 0;
 
-    for(i = 0; i < psRelation->nMembers; i ++ )
+    for( unsigned int i = 0; i < psRelation->nMembers; i++ )
     {
         if( psRelation->pasMembers[i].eType == MEMBER_WAY &&
             strcmp(psRelation->pasMembers[i].pszRole, "subarea") != 0  )
@@ -2215,7 +2264,7 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
             const std::pair<int, void*>& oGeom = aoMapWays[ psRelation->pasMembers[i].nID ];
 
             LonLat* pasCoords = (LonLat*) pasLonLatCache;
-            int nPoints;
+            int nPoints = 0;
 
             if( pnTags != NULL && *pnTags == 0 &&
                 strcmp(psRelation->pasMembers[i].pszRole, "outer") == 0 )
@@ -2235,10 +2284,10 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
                                          NULL, NULL, NULL);
             }
 
-            OGRLineString* poLS;
+            OGRLineString* poLS = NULL;
 
-            if ( pasCoords[0].nLon == pasCoords[nPoints - 1].nLon &&
-                 pasCoords[0].nLat == pasCoords[nPoints - 1].nLat )
+            if( pasCoords[0].nLon == pasCoords[nPoints - 1].nLon &&
+                pasCoords[0].nLat == pasCoords[nPoints - 1].nLat )
             {
                 OGRPolygon* poPoly = new OGRPolygon();
                 OGRLinearRing* poRing = new OGRLinearRing();
@@ -2266,7 +2315,6 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
                                 INT_TO_DBL(pasCoords[j].nLon),
                                 INT_TO_DBL(pasCoords[j].nLat) );
             }
-
         }
     }
 
@@ -2280,7 +2328,9 @@ OGRGeometry* OGROSMDataSource::BuildMultiPolygon(OSMRelation* psRelation,
         if( hPoly != NULL && OGR_G_GetGeometryType(hPoly) == wkbPolygon )
         {
             OGRPolygon* poSuperPoly = (OGRPolygon* ) hPoly;
-            for(i = 0; i < 1 + (unsigned int)poSuperPoly->getNumInteriorRings(); i++)
+            for( unsigned int i = 0;
+                 i < 1 + (unsigned int)poSuperPoly->getNumInteriorRings();
+                 i++ )
             {
                 OGRLinearRing* poRing =  (i == 0) ? poSuperPoly->getExteriorRing() :
                                                     poSuperPoly->getInteriorRing(i - 1);
@@ -2381,8 +2431,8 @@ OGRGeometry* OGROSMDataSource::BuildGeometryCollection(OSMRelation* psRelation,
                 oGeom.first,
                 reinterpret_cast<GByte *>(oGeom.second),
                 &bIsArea, pasCoords, NULL, NULL, NULL );
-            OGRLineString* poLS;
-            if( bIsArea )
+            OGRLineString* poLS = NULL;
+            if( bIsArea && !bMultiLineString )
             {
                 OGRLinearRing* poLR = new OGRLinearRing();
                 OGRPolygon* poPoly = new OGRPolygon();
@@ -2403,7 +2453,6 @@ OGRGeometry* OGROSMDataSource::BuildGeometryCollection(OSMRelation* psRelation,
                                 INT_TO_DBL(pasCoords[j].nLon),
                                 INT_TO_DBL(pasCoords[j].nLat) );
             }
-
         }
     }
 
@@ -2465,15 +2514,17 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
                 bMultiLineString = true;
             }
         }
-        else if ( strcmp(pszK, "created_by") != 0 )
+        else if( strcmp(pszK, "created_by") != 0 )
             bInterestingTagFound = true;
     }
 
-    /* Optimization : if we have an attribute filter, that does not require geometry, */
-    /* then we can just evaluate the attribute filter without the geometry */
-    int iCurLayer = (bMultiPolygon) ?    IDX_LYR_MULTIPOLYGONS :
-                    (bMultiLineString) ? IDX_LYR_MULTILINESTRINGS :
-                                         IDX_LYR_OTHER_RELATIONS;
+    // Optimization: If we have an attribute filter, that does not require
+    // geometry, then we can just evaluate the attribute filter without the
+    // geometry.
+    const int iCurLayer =
+        bMultiPolygon ?    IDX_LYR_MULTIPOLYGONS :
+        bMultiLineString ? IDX_LYR_MULTILINESTRINGS :
+        IDX_LYR_OTHER_RELATIONS;
     if( !papoLayers[iCurLayer]->IsUserInterested() )
         return;
 
@@ -2489,7 +2540,7 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
 
         papoLayers[iCurLayer]->SetFieldsFromTags( poFeature,
                                                   psRelation->nID,
-                                                  FALSE,
+                                                  false,
                                                   psRelation->nTags,
                                                   psRelation->pasTags,
                                                   &psRelation->sInfo);
@@ -2501,7 +2552,7 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
         }
     }
 
-    OGRGeometry* poGeom;
+    OGRGeometry* poGeom = NULL;
 
     unsigned int nExtraTags = 0;
     OSMTag pasExtraTags[1 + MAX_COUNT_FOR_TAGS_IN_WAY];
@@ -2511,7 +2562,8 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
         if( !bInterestingTagFound )
         {
             poGeom = BuildMultiPolygon(psRelation, &nExtraTags, pasExtraTags);
-            CPLAssert(nExtraTags <= MAX_COUNT_FOR_TAGS_IN_WAY);
+            CPLAssert(nExtraTags <=
+                      static_cast<unsigned int>(MAX_COUNT_FOR_TAGS_IN_WAY));
             pasExtraTags[nExtraTags].pszK = "type";
             pasExtraTags[nExtraTags].pszV = pszTypeV;
             nExtraTags ++;
@@ -2532,7 +2584,7 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
             papoLayers[iCurLayer]->SetFieldsFromTags(
                 poFeature,
                 psRelation->nID,
-                FALSE,
+                false,
                 nExtraTags ? nExtraTags : psRelation->nTags,
                 nExtraTags ? pasExtraTags : psRelation->pasTags,
                 &psRelation->sInfo);
@@ -2548,11 +2600,13 @@ void OGROSMDataSource::NotifyRelation (OSMRelation* psRelation)
                                                 &bFilteredOut,
                                                 !bFeatureAdded ) )
             bStopParsing = true;
-        else if (!bFilteredOut)
+        else if( !bFilteredOut )
             bFeatureAdded = true;
     }
     else
+    {
         delete poFeature;
+    }
 }
 
 static void OGROSMNotifyRelation ( OSMRelation *psRelation,
@@ -2562,7 +2616,6 @@ static void OGROSMNotifyRelation ( OSMRelation *psRelation,
     static_cast<OGROSMDataSource *>(user_data)->NotifyRelation(psRelation);
 }
 
-
 /************************************************************************/
 /*                      ProcessPolygonsStandalone()                     */
 /************************************************************************/
@@ -2608,8 +2661,8 @@ void OGROSMDataSource::ProcessPolygonsStandalone()
             const int nPoints = UncompressWay(
                 nBlobSize, reinterpret_cast<GByte *>(const_cast<void *>(blob)),
                 NULL, pasCoords, &nTags, pasTags, &sInfo );
-            CPLAssert(nTags <= MAX_COUNT_FOR_TAGS_IN_WAY);
-
+            CPLAssert(
+                nTags <= static_cast<unsigned int>(MAX_COUNT_FOR_TAGS_IN_WAY));
 
             OGRMultiPolygon* poMulti = new OGRMultiPolygon();
             OGRPolygon* poPoly = new OGRPolygon();
@@ -2632,7 +2685,7 @@ void OGROSMDataSource::ProcessPolygonsStandalone()
 
             papoLayers[IDX_LYR_MULTIPOLYGONS]->SetFieldsFromTags( poFeature,
                                                                   id,
-                                                                  TRUE,
+                                                                  true,
                                                                   nTags,
                                                                   pasTags,
                                                                   &sInfo);
@@ -2648,11 +2701,13 @@ void OGROSMDataSource::ProcessPolygonsStandalone()
                 bStopParsing = true;
                 break;
             }
-            else if (!bFilteredOut)
+            else if( !bFilteredOut )
+            {
                 bFeatureAdded = true;
-
+            }
         }
-        else {
+        else
+        {
             CPLAssert(false);
         }
 
@@ -2667,8 +2722,8 @@ void OGROSMDataSource::ProcessPolygonsStandalone()
 /*                             NotifyBounds()                           */
 /************************************************************************/
 
-void OGROSMDataSource::NotifyBounds (double dfXMin, double dfYMin,
-                                     double dfXMax, double dfYMax)
+void OGROSMDataSource::NotifyBounds ( double dfXMin, double dfYMin,
+                                      double dfXMax, double dfYMax )
 {
     sExtent.MinX = dfXMin;
     sExtent.MinY = dfYMin;
@@ -2677,7 +2732,7 @@ void OGROSMDataSource::NotifyBounds (double dfXMin, double dfYMin,
     bExtentValid = true;
 
     CPLDebug( "OSM", "Got bounds : minx=%f, miny=%f, maxx=%f, maxy=%f",
-              dfXMin, dfYMin, dfXMax, dfYMax);
+              dfXMin, dfYMin, dfXMax, dfYMax );
 }
 
 static void OGROSMNotifyBounds( double dfXMin, double dfYMin,
@@ -2708,7 +2763,7 @@ int OGROSMDataSource::Open( const char * pszFilename,
     if( psParser == NULL )
         return FALSE;
 
-    if( CSLFetchBoolean(papszOpenOptionsIn, "INTERLEAVED_READING", FALSE) )
+    if( CPLFetchBool(papszOpenOptionsIn, "INTERLEAVED_READING", false) )
         bInterleavedReading = TRUE;
 
     /* The following 4 config options are only useful for debugging */
@@ -2810,7 +2865,7 @@ int OGROSMDataSource::Open( const char * pszFilename,
         "MAX_TMPFILE_SIZE", CPLGetConfigOption("OSM_MAX_TMPFILE_SIZE", "100")));
     GIntBig nSize =
         static_cast<GIntBig>(nMaxSizeForInMemoryDBInMB) * 1024 * 1024;
-    if (nSize < 0 || (GIntBig)(size_t)nSize != nSize)
+    if( nSize < 0 || (GIntBig)(size_t)nSize != nSize )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Invalid value for OSM_MAX_TMPFILE_SIZE. Using 100 instead." );
@@ -2878,13 +2933,13 @@ int OGROSMDataSource::Open( const char * pszFilename,
         }
     }
 
-    const int bRet = CreateTempDB();
+    const bool bRet = CreateTempDB();
     if( bRet )
     {
         CPLString osInterestLayers = GetInterestLayersForDSName(GetName());
-        if( osInterestLayers.size() )
+        if( !osInterestLayers.empty() )
         {
-            ExecuteSQL( osInterestLayers, NULL, NULL );
+            delete ExecuteSQL( osInterestLayers, NULL, NULL );
         }
     }
     return bRet;
@@ -2894,7 +2949,7 @@ int OGROSMDataSource::Open( const char * pszFilename,
 /*                             CreateTempDB()                           */
 /************************************************************************/
 
-int OGROSMDataSource::CreateTempDB()
+bool OGROSMDataSource::CreateTempDB()
 {
     char* pszErrMsg = NULL;
 
@@ -2902,9 +2957,8 @@ int OGROSMDataSource::CreateTempDB()
     bool bIsExisting = false;
     bool bSuccess = false;
 
-#ifdef HAVE_SQLITE_VFS
     const char* pszExistingTmpFile = CPLGetConfigOption("OSM_EXISTING_TMPFILE", NULL);
-    if ( pszExistingTmpFile != NULL )
+    if( pszExistingTmpFile != NULL )
     {
         bSuccess = true;
         bIsExisting = true;
@@ -2917,14 +2971,14 @@ int OGROSMDataSource::CreateTempDB()
         osTmpDBName.Printf("/vsimem/osm_importer/osm_temp_%p.sqlite", this);
 
         // On 32 bit, the virtual memory space is scarce, so we need to
-        // reserve it right now Will not hurt on 64 bit either.
+        // reserve it right now. Will not hurt on 64 bit either.
         VSILFILE* fp = VSIFOpenL(osTmpDBName, "wb");
         if( fp )
         {
             GIntBig nSize =
                 static_cast<GIntBig>(nMaxSizeForInMemoryDBInMB) * 1024 * 1024;
             if( bCustomIndexing && bInMemoryNodesFile )
-                nSize = nSize * 1 / 4;
+                nSize = nSize / 4;
 
             CPLPushErrorHandler(CPLQuietErrorHandler);
             bSuccess =
@@ -2932,7 +2986,7 @@ int OGROSMDataSource::CreateTempDB()
             CPLPopErrorHandler();
 
             if( bSuccess )
-                 VSIFTruncateL(fp, 0);
+                 bSuccess = VSIFTruncateL(fp, 0) == 0;
 
             VSIFCloseL(fp);
 
@@ -2957,7 +3011,6 @@ int OGROSMDataSource::CreateTempDB()
                 pMyVFS->zName );
         }
     }
-#endif
 
     if( !bSuccess )
     {
@@ -2984,12 +3037,12 @@ int OGROSMDataSource::CreateTempDB()
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "sqlite3_open(%s) failed: %s",
                   osTmpDBName.c_str(), sqlite3_errmsg( hDB ) );
-        return FALSE;
+        return false;
     }
 
     if( !SetDBOptions() )
     {
-        return FALSE;
+        return false;
     }
 
     if( !bIsExisting )
@@ -3003,7 +3056,7 @@ int OGROSMDataSource::CreateTempDB()
             CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to create table nodes : %s", pszErrMsg );
             sqlite3_free( pszErrMsg );
-            return FALSE;
+            return false;
         }
 
         rc = sqlite3_exec(
@@ -3015,7 +3068,7 @@ int OGROSMDataSource::CreateTempDB()
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Unable to create table ways : %s", pszErrMsg );
             sqlite3_free( pszErrMsg );
-            return FALSE;
+            return false;
         }
 
         rc = sqlite3_exec(
@@ -3028,12 +3081,13 @@ int OGROSMDataSource::CreateTempDB()
                       "Unable to create table polygons_standalone : %s",
                       pszErrMsg );
             sqlite3_free( pszErrMsg );
-            return FALSE;
+            return false;
         }
     }
 
     return CreatePreparedStatements();
 }
+
 /************************************************************************/
 /*                            SetDBOptions()                            */
 /************************************************************************/
@@ -3091,15 +3145,16 @@ bool OGROSMDataSource::SetCacheSize()
 {
     const char* pszSqliteCacheMB = CPLGetConfigOption("OSM_SQLITE_CACHE", NULL);
 
-    if (pszSqliteCacheMB == NULL)
+    if( pszSqliteCacheMB == NULL )
         return true;
 
     char* pszErrMsg = NULL;
-    char **papszResult;
-    int nRowCount;
-    int nColCount;
+    char **papszResult = NULL;
+    int nRowCount = 0;
+    int nColCount = 0;
     int iSqlitePageSize = -1;
-    const int iSqliteCacheBytes = atoi( pszSqliteCacheMB ) * 1024 * 1024;
+    const GIntBig iSqliteCacheBytes =
+            static_cast<GIntBig>(atoi( pszSqliteCacheMB )) * 1024 * 1024;
 
     /* querying the current PageSize */
     int rc = sqlite3_get_table( hDB, "PRAGMA page_size",
@@ -3107,8 +3162,7 @@ bool OGROSMDataSource::SetCacheSize()
                                 &pszErrMsg );
     if( rc == SQLITE_OK )
     {
-        int iRow;
-        for (iRow = 1; iRow <= nRowCount; iRow++)
+        for( int iRow = 1; iRow <= nRowCount; iRow++ )
         {
             iSqlitePageSize = atoi( papszResult[(iRow * nColCount) + 0] );
         }
@@ -3126,7 +3180,8 @@ bool OGROSMDataSource::SetCacheSize()
         return true;
 
     /* computing the CacheSize as #Pages */
-    const int iSqliteCachePages = iSqliteCacheBytes / iSqlitePageSize;
+    const int iSqliteCachePages = static_cast<int>(
+                                    iSqliteCacheBytes / iSqlitePageSize);
     if( iSqliteCachePages <= 0)
         return true;
 
@@ -3151,12 +3206,13 @@ bool OGROSMDataSource::SetCacheSize()
 bool OGROSMDataSource::CreatePreparedStatements()
 {
     int rc =
-        sqlite3_prepare( hDB, "INSERT INTO nodes (id, coords) VALUES (?,?)", -1,
-                         &hInsertNodeStmt, NULL );
+        sqlite3_prepare_v2( hDB,
+                            "INSERT INTO nodes (id, coords) VALUES (?,?)", -1,
+                            &hInsertNodeStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
+                  "sqlite3_prepare_v2() failed :  %s", sqlite3_errmsg(hDB) );
         return false;
     }
 
@@ -3178,21 +3234,21 @@ bool OGROSMDataSource::CreatePreparedStatements()
             strcpy(szTmp + nLen -1, ",?) ORDER BY id ASC");
             nLen += 2;
         }
-        rc = sqlite3_prepare( hDB, szTmp, -1, &pahSelectNodeStmt[i], NULL );
+        rc = sqlite3_prepare_v2( hDB, szTmp, -1, &pahSelectNodeStmt[i], NULL );
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
+                    "sqlite3_prepare_v2() failed :  %s", sqlite3_errmsg(hDB) );
             return false;
         }
     }
 
-    rc = sqlite3_prepare( hDB, "INSERT INTO ways (id, data) VALUES (?,?)", -1,
+    rc = sqlite3_prepare_v2( hDB, "INSERT INTO ways (id, data) VALUES (?,?)", -1,
                           &hInsertWayStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
+                  "sqlite3_prepare_v2() failed :  %s", sqlite3_errmsg(hDB) );
         return false;
     }
 
@@ -3213,42 +3269,42 @@ bool OGROSMDataSource::CreatePreparedStatements()
             strcpy(szTmp + nLen -1, ",?)");
             nLen += 2;
         }
-        rc = sqlite3_prepare( hDB, szTmp, -1, &pahSelectWayStmt[i], NULL );
+        rc = sqlite3_prepare_v2( hDB, szTmp, -1, &pahSelectWayStmt[i], NULL );
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
+                    "sqlite3_prepare_v2() failed :  %s", sqlite3_errmsg(hDB) );
             return false;
         }
     }
 
-    rc = sqlite3_prepare(
+    rc = sqlite3_prepare_v2(
         hDB, "INSERT INTO polygons_standalone (id) VALUES (?)", -1,
         &hInsertPolygonsStandaloneStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
+                  "sqlite3_prepare_v2() failed :  %s", sqlite3_errmsg(hDB) );
         return false;
     }
 
-    rc = sqlite3_prepare(
+    rc = sqlite3_prepare_v2(
         hDB, "DELETE FROM polygons_standalone WHERE id = ?", -1,
         &hDeletePolygonsStandaloneStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
+                  "sqlite3_prepare_v2() failed :  %s", sqlite3_errmsg(hDB) );
         return false;
     }
 
-    rc = sqlite3_prepare(
+    rc = sqlite3_prepare_v2(
         hDB, "SELECT id FROM polygons_standalone ORDER BY id", -1,
         &hSelectPolygonsStandaloneStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                "sqlite3_prepare() failed :  %s", sqlite3_errmsg(hDB) );
+                "sqlite3_prepare_v2() failed :  %s", sqlite3_errmsg(hDB) );
         return false;
     }
 
@@ -3313,7 +3369,7 @@ void OGROSMDataSource::AddComputedAttributes(
 {
     for(size_t i=0; i<oAttributes.size();i++)
     {
-        if( oAttributes[i].osSQL.size() )
+        if( !oAttributes[i].osSQL.empty() )
         {
             papoLayers[iCurLayer]->AddComputedAttribute(oAttributes[i].osName,
                                                         oAttributes[i].eType,
@@ -3326,7 +3382,7 @@ void OGROSMDataSource::AddComputedAttributes(
 /*                           ParseConf()                                */
 /************************************************************************/
 
-bool OGROSMDataSource::ParseConf(char** papszOpenOptionsIn)
+bool OGROSMDataSource::ParseConf( char** papszOpenOptionsIn )
 {
     const char *pszFilename =
         CSLFetchNameValueDef(papszOpenOptionsIn, "CONFIG_FILE",
@@ -3344,7 +3400,7 @@ bool OGROSMDataSource::ParseConf(char** papszOpenOptionsIn)
     if( fpConf == NULL )
         return false;
 
-    const char* pszLine;
+    const char* pszLine = NULL;
     int iCurLayer = -1;
     std::vector<OGROSMComputedAttribute> oAttributes;
 
@@ -3378,18 +3434,15 @@ bool OGROSMDataSource::ParseConf(char** papszOpenOptionsIn)
             continue;
         }
 
-        if( STARTS_WITH(pszLine, "closed_ways_are_polygons="))        {
-            char** papszTokens = CSLTokenizeString2(pszLine, "=", 0);
-            if( CSLCount(papszTokens) == 2)
+        if( STARTS_WITH(pszLine, "closed_ways_are_polygons="))
+        {
+            char** papszTokens2 = CSLTokenizeString2(
+                    pszLine + strlen("closed_ways_are_polygons="), ",", 0);
+            for(int i=0;papszTokens2[i] != NULL;i++)
             {
-                char** papszTokens2 = CSLTokenizeString2(papszTokens[1], ",", 0);
-                for(int i=0;papszTokens2[i] != NULL;i++)
-                {
-                    aoSetClosedWaysArePolygons.insert(papszTokens2[i]);
-                }
-                CSLDestroy(papszTokens2);
+                aoSetClosedWaysArePolygons.insert(papszTokens2[i]);
             }
-            CSLDestroy(papszTokens);
+            CSLDestroy(papszTokens2);
         }
 
         else if(STARTS_WITH(pszLine, "report_all_nodes="))
@@ -3498,37 +3551,45 @@ bool OGROSMDataSource::ParseConf(char** papszOpenOptionsIn)
                     papoLayers[iCurLayer]->AddField("osm_user", OFTString);
                 }
             }
-            else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "osm_changeset") == 0 )
+            else if( CSLCount(papszTokens) == 2 &&
+                     strcmp(papszTokens[0], "osm_changeset") == 0 )
             {
                 if( strcmp(papszTokens[1], "no") == 0 )
                     papoLayers[iCurLayer]->SetHasChangeset(false);
                 else if( strcmp(papszTokens[1], "yes") == 0 )
                 {
                     papoLayers[iCurLayer]->SetHasChangeset(true);
-                    papoLayers[iCurLayer]->AddField("osm_changeset", OFTInteger);
+                    papoLayers[iCurLayer]->AddField("osm_changeset",
+                                                    OFTInteger);
                 }
             }
-            else if( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "attributes") == 0 )
+            else if( CSLCount(papszTokens) == 2 &&
+                     strcmp(papszTokens[0], "attributes") == 0 )
             {
-                char** papszTokens2 = CSLTokenizeString2(papszTokens[1], ",", 0);
+                char** papszTokens2 =
+                    CSLTokenizeString2(papszTokens[1], ",", 0);
                 for(int i=0;papszTokens2[i] != NULL;i++)
                 {
                     papoLayers[iCurLayer]->AddField(papszTokens2[i], OFTString);
                 }
                 CSLDestroy(papszTokens2);
             }
-            else if ( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "unsignificant") == 0 )
+            else if( CSLCount(papszTokens) == 2 &&
+                     strcmp(papszTokens[0], "unsignificant") == 0 )
             {
-                char** papszTokens2 = CSLTokenizeString2(papszTokens[1], ",", 0);
+                char** papszTokens2 =
+                    CSLTokenizeString2(papszTokens[1], ",", 0);
                 for(int i=0;papszTokens2[i] != NULL;i++)
                 {
                     papoLayers[iCurLayer]->AddUnsignificantKey(papszTokens2[i]);
                 }
                 CSLDestroy(papszTokens2);
             }
-            else if ( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "ignore") == 0 )
+            else if( CSLCount(papszTokens) == 2 &&
+                     strcmp(papszTokens[0], "ignore") == 0 )
             {
-                char** papszTokens2 = CSLTokenizeString2(papszTokens[1], ",", 0);
+                char** papszTokens2 =
+                    CSLTokenizeString2(papszTokens[1], ",", 0);
                 for(int i=0;papszTokens2[i] != NULL;i++)
                 {
                     papoLayers[iCurLayer]->AddIgnoreKey(papszTokens2[i]);
@@ -3536,18 +3597,23 @@ bool OGROSMDataSource::ParseConf(char** papszOpenOptionsIn)
                 }
                 CSLDestroy(papszTokens2);
             }
-            else if ( CSLCount(papszTokens) == 2 && strcmp(papszTokens[0], "computed_attributes") == 0 )
+            else if( CSLCount(papszTokens) == 2 &&
+                     strcmp(papszTokens[0], "computed_attributes") == 0 )
             {
-                char** papszTokens2 = CSLTokenizeString2(papszTokens[1], ",", 0);
+                char** papszTokens2 =
+                    CSLTokenizeString2(papszTokens[1], ",", 0);
                 oAttributes.resize(0);
                 for(int i=0;papszTokens2[i] != NULL;i++)
                 {
-                    oAttributes.push_back(OGROSMComputedAttribute(papszTokens2[i]));
+                    oAttributes.push_back(
+                        OGROSMComputedAttribute(papszTokens2[i]));
                 }
                 CSLDestroy(papszTokens2);
             }
-            else if ( CSLCount(papszTokens) == 2 && strlen(papszTokens[0]) >= 5 &&
-                      strcmp(papszTokens[0] + strlen(papszTokens[0]) - 5, "_type") == 0 )
+            else if( CSLCount(papszTokens) == 2 &&
+                     strlen(papszTokens[0]) >= 5 &&
+                     strcmp(papszTokens[0] + strlen(papszTokens[0]) - 5,
+                            "_type") == 0 )
             {
                 CPLString osName(papszTokens[0]);
                 osName.resize(strlen(papszTokens[0]) - 5);
@@ -3579,41 +3645,47 @@ bool OGROSMDataSource::ParseConf(char** papszOpenOptionsIn)
                 }
                 if( !bFound )
                 {
-                    int idx = papoLayers[iCurLayer]->GetLayerDefn()->GetFieldIndex(osName);
+                    const int idx =
+                        papoLayers[iCurLayer]->
+                            GetLayerDefn()->GetFieldIndex(osName);
                     if( idx >= 0 )
                     {
-                        papoLayers[iCurLayer]->GetLayerDefn()->GetFieldDefn(idx)->SetType(eType);
+                        papoLayers[iCurLayer]->
+                            GetLayerDefn()->GetFieldDefn(idx)->SetType(eType);
                         bFound = true;
                     }
                 }
                 if( !bFound )
                 {
-                    CPLError(CE_Warning, CPLE_AppDefined, "Undeclared attribute : %s",
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Undeclared attribute : %s",
                              osName.c_str());
                 }
             }
-            else if ( CSLCount(papszTokens) >= 2 && strlen(papszTokens[0]) >= 4 &&
-                      strcmp(papszTokens[0] + strlen(papszTokens[0]) - 4, "_sql") == 0 )
+            else if( CSLCount(papszTokens) >= 2 &&
+                     strlen(papszTokens[0]) >= 4 &&
+                     strcmp(papszTokens[0] + strlen(papszTokens[0]) - 4,
+                            "_sql") == 0 )
             {
                 CPLString osName(papszTokens[0]);
                 osName.resize(strlen(papszTokens[0]) - 4);
-                size_t i;
-                for(i = 0; i < oAttributes.size(); i++ )
+                size_t i = 0;  // Used after for.
+                for( ; i < oAttributes.size(); i++ )
                 {
                     if( oAttributes[i].osName == osName )
                     {
                         const char* pszSQL = strchr(pszLine, '=') + 1;
                         while( *pszSQL == ' ' )
                             pszSQL ++;
-                        int bInQuotes = FALSE;
+                        bool bInQuotes = false;
                         if( *pszSQL == '"' )
                         {
-                            bInQuotes = TRUE;
+                            bInQuotes = true;
                             pszSQL ++;
                         }
                         oAttributes[i].osSQL = pszSQL;
                         if( bInQuotes && oAttributes[i].osSQL.size() > 1 &&
-                            oAttributes[i].osSQL[oAttributes[i].osSQL.size()-1] == '"' )
+                            oAttributes[i].osSQL.back() == '"' )
                             oAttributes[i].osSQL.resize(oAttributes[i].osSQL.size()-1);
                         break;
                     }
@@ -3652,10 +3724,10 @@ bool OGROSMDataSource::ParseConf(char** papszOpenOptionsIn)
 }
 
 /************************************************************************/
-/*                           ResetReading()                            */
+/*                          MyResetReading()                            */
 /************************************************************************/
 
-int OGROSMDataSource::ResetReading()
+int OGROSMDataSource::MyResetReading()
 {
     if( hDB == NULL )
         return FALSE;
@@ -3694,6 +3766,9 @@ int OGROSMDataSource::ResetReading()
     }
     bHasRowInPolygonsStandalone = false;
 
+    if( hSelectPolygonsStandaloneStmt != NULL )
+        sqlite3_reset( hSelectPolygonsStandaloneStmt );
+
     {
         for( int i = 0; i < nWayFeaturePairs; i++)
         {
@@ -3751,15 +3826,95 @@ int OGROSMDataSource::ResetReading()
     }
 
     bStopParsing = false;
+    poCurrentLayer = NULL;
 
     return TRUE;
 }
 
 /************************************************************************/
+/*                             ResetReading()                           */
+/************************************************************************/
+
+void OGROSMDataSource::ResetReading()
+{
+    MyResetReading();
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature* OGROSMDataSource::GetNextFeature( OGRLayer** ppoBelongingLayer,
+                                              double* pdfProgressPct,
+                                              GDALProgressFunc pfnProgress,
+                                              void* pProgressData )
+{
+    bInterleavedReading = TRUE;
+
+    if( poCurrentLayer == NULL )
+    {
+        poCurrentLayer = papoLayers[0];
+    }
+    if( pdfProgressPct != NULL || pfnProgress != NULL )
+    {
+        if( m_nFileSize == FILESIZE_NOT_INIT )
+        {
+            VSIStatBufL sStat;
+            if( VSIStatL( pszName, &sStat ) == 0 )
+            {
+                m_nFileSize = static_cast<GIntBig>(sStat.st_size);
+            }
+            else
+            {
+                m_nFileSize = FILESIZE_INVALID;
+            }
+        }
+    }
+
+    while( true )
+    {
+        OGROSMLayer* poNewCurLayer = NULL;
+        CPLAssert( poCurrentLayer != NULL );
+        OGRFeature* poFeature = poCurrentLayer->MyGetNextFeature(&poNewCurLayer,
+                                                                 pfnProgress,
+                                                                 pProgressData);
+        poCurrentLayer = poNewCurLayer;
+        if( poFeature == NULL)
+        {
+            if( poCurrentLayer != NULL )
+                continue;
+            if( ppoBelongingLayer != NULL )
+                *ppoBelongingLayer = NULL;
+            if( pdfProgressPct != NULL )
+                *pdfProgressPct = 1.0;
+            return NULL;
+        }
+        if( ppoBelongingLayer != NULL )
+            *ppoBelongingLayer = poCurrentLayer;
+        if( pdfProgressPct != NULL )
+        {
+            if( m_nFileSize != FILESIZE_INVALID )
+            {
+                *pdfProgressPct = 1.0 * OSM_GetBytesRead(psParser) /
+                                        m_nFileSize;
+            }
+            else
+            {
+                *pdfProgressPct = -1.0;
+            }
+        }
+
+        return poFeature;
+    }
+}
+
+/************************************************************************/
 /*                           ParseNextChunk()                           */
 /************************************************************************/
 
-bool OGROSMDataSource::ParseNextChunk(int nIdxLayer)
+bool OGROSMDataSource::ParseNextChunk( int nIdxLayer,
+                                       GDALProgressFunc pfnProgress,
+                                       void* pProgressData )
 {
     if( bStopParsing )
         return false;
@@ -3771,12 +3926,30 @@ bool OGROSMDataSource::ParseNextChunk(int nIdxLayer)
 #ifdef DEBUG_MEM_USAGE
         static int counter = 0;
         counter ++;
-        if ((counter % 1000) == 0)
+        if( (counter % 1000) == 0 )
             CPLDebug("OSM", "GetMaxTotalAllocs() = " CPL_FRMT_GUIB,
                      static_cast<GUIntBig>(GetMaxTotalAllocs()));
 #endif
 
         OSMRetCode eRet = OSM_ProcessBlock(psParser);
+        if( pfnProgress != NULL )
+        {
+            double dfPct = -1.0;
+            if( m_nFileSize != FILESIZE_INVALID )
+            {
+                dfPct = 1.0 * OSM_GetBytesRead(psParser) / m_nFileSize;
+            }
+            if( !pfnProgress( dfPct, "", pProgressData ) )
+            {
+                bStopParsing = true;
+                for(int i=0;i<nLayers;i++)
+                {
+                    papoLayers[i]->ForceResetReading();
+                }
+                return false;
+            }
+        }
+
         if( eRet == OSM_EOF || eRet == OSM_ERROR )
         {
             if( eRet == OSM_EOF )
@@ -3921,7 +4094,6 @@ bool OGROSMDataSource::TransferToDiskIfNecesserary()
             CloseDB();
 
             CPLString osNewTmpDBName;
-            int rc;
 
             osNewTmpDBName = CPLGenerateTempFilename("osm_tmp");
 
@@ -3942,13 +4114,10 @@ bool OGROSMDataSource::TransferToDiskIfNecesserary()
 
             osTmpDBName = osNewTmpDBName;
 
-#ifdef HAVE_SQLITE_VFS
-            rc = sqlite3_open_v2( osTmpDBName.c_str(), &hDB,
-                                  SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX,
-                                  NULL );
-#else
-            rc = sqlite3_open( osTmpDBName.c_str(), &hDB );
-#endif
+            const int rc =
+                sqlite3_open_v2( osTmpDBName.c_str(), &hDB,
+                                 SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX,
+                                 NULL );
             if( rc != SQLITE_OK )
             {
                 CPLError( CE_Failure, CPLE_OpenFailed,
@@ -3986,9 +4155,9 @@ bool OGROSMDataSource::TransferToDiskIfNecesserary()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGROSMDataSource::TestCapability( const char * /* pszCap */ )
+int OGROSMDataSource::TestCapability( const char * pszCap )
 {
-    return FALSE;
+    return EQUAL(pszCap, ODsCRandomLayerRead);
 }
 
 /************************************************************************/
@@ -4010,13 +4179,13 @@ OGRLayer *OGROSMDataSource::GetLayer( int iLayer )
 
 OGRErr OGROSMDataSource::GetExtent( OGREnvelope *psExtent )
 {
-    if (!bHasParsedFirstChunk)
+    if( !bHasParsedFirstChunk )
     {
         bHasParsedFirstChunk = true;
         OSM_ProcessBlock(psParser);
     }
 
-    if (bExtentValid)
+    if( bExtentValid )
     {
         memcpy(psExtent, &sExtent, sizeof(sExtent));
         return OGRERR_NONE;
@@ -4025,7 +4194,6 @@ OGRErr OGROSMDataSource::GetExtent( OGREnvelope *psExtent )
     return OGRERR_FAILURE;
 }
 
-
 /************************************************************************/
 /*                   OGROSMSingleFeatureLayer                           */
 /************************************************************************/
@@ -4040,18 +4208,17 @@ class OGROSMSingleFeatureLayer : public OGRLayer
 
   public:
                         OGROSMSingleFeatureLayer( const char* pszLayerName,
-                                                     int nVal );
+                                                  int nVal );
                         OGROSMSingleFeatureLayer( const char* pszLayerName,
-                                                     const char *pszVal );
-                        ~OGROSMSingleFeatureLayer();
+                                                  const char *pszVal );
+                        virtual ~OGROSMSingleFeatureLayer();
 
-    virtual void        ResetReading() { iNextShapeId = 0; }
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
-    virtual int         TestCapability( const char * ) { return FALSE; }
+    virtual void        ResetReading() override { iNextShapeId = 0; }
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
+    virtual int         TestCapability( const char * ) override { return FALSE; }
 };
 
-
 /************************************************************************/
 /*                    OGROSMSingleFeatureLayer()                        */
 /************************************************************************/
@@ -4082,7 +4249,6 @@ OGROSMSingleFeatureLayer::OGROSMSingleFeatureLayer( const char* pszLayerName,
     poFeatureDefn->Reference();
     OGRFieldDefn oField( pszLayerName, OFTString );
     poFeatureDefn->AddFieldDefn( &oField );
-
 }
 
 /************************************************************************/
@@ -4101,11 +4267,11 @@ OGROSMSingleFeatureLayer::~OGROSMSingleFeatureLayer()
 
 OGRFeature * OGROSMSingleFeatureLayer::GetNextFeature()
 {
-    if (iNextShapeId != 0)
+    if( iNextShapeId != 0 )
         return NULL;
 
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
-    if (pszVal)
+    if( pszVal )
         poFeature->SetField(0, pszVal);
     else
         poFeature->SetField(0, nVal);
@@ -4130,7 +4296,7 @@ class OGROSMResultLayerDecorator : public OGRLayerDecorator
                                         osDSName(osDSNameIn),
                                         osInterestLayers(osInterestLayersIn) {}
 
-        virtual GIntBig     GetFeatureCount( int bForce = TRUE )
+        virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override
         {
             /* When we run GetFeatureCount() with SQLite SQL dialect, */
             /* the OSM dataset will be re-opened. Make sure that it is */
@@ -4152,9 +4318,9 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special GetBytesRead() command                                  */
 /* -------------------------------------------------------------------- */
-    if (strcmp(pszSQLCommand, "GetBytesRead()") == 0)
+    if( strcmp(pszSQLCommand, "GetBytesRead()") == 0 )
     {
-        char szVal[64];
+        char szVal[64] = {};
         snprintf( szVal, sizeof(szVal), CPL_FRMT_GUIB,
                   OSM_GetBytesRead(psParser) );
         return new OGROSMSingleFeatureLayer( "GetBytesRead", szVal );
@@ -4170,7 +4336,7 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Special SET interest_layers = command                           */
 /* -------------------------------------------------------------------- */
-    if (STARTS_WITH(pszSQLCommand, "SET interest_layers ="))
+    if( STARTS_WITH(pszSQLCommand, "SET interest_layers =") )
     {
         char** papszTokens =
             CSLTokenizeString2(pszSQLCommand + 21, ",",
@@ -4253,7 +4419,7 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
             for(; oIter != oSetLayers.end(); ++oIter)
             {
                 const LayerDesc& oLayerDesc = *oIter;
-                if( oLayerDesc.osDSName.size() == 0 )
+                if( oLayerDesc.osDSName.empty() )
                 {
                     if( bLayerAlreadyAdded ) osInterestLayers += ",";
                     bLayerAlreadyAdded = true;
@@ -4305,9 +4471,9 @@ OGRLayer * OGROSMDataSource::ExecuteSQL( const char *pszSQLCommand,
             bUseWaysIndexBackup = bUseWaysIndex;
 
             /* Update optimization parameters */
-            ExecuteSQL(osInterestLayers, NULL, NULL);
+            delete ExecuteSQL(osInterestLayers, NULL, NULL);
 
-            ResetReading();
+            MyResetReading();
 
             /* Run the request */
             poResultSetLayer = OGRDataSource::ExecuteSQL( pszSQLCommand,
@@ -4380,4 +4546,3 @@ int OGROSMDataSource::IsInterleavedReading()
     }
     return bInterleavedReading;
 }
-
diff --git a/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp b/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
index 6963a76..04f17d0 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrosmdriver.cpp 33039 2016-01-18 17:04:21Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMDriver class.
@@ -34,7 +33,7 @@
 
 extern "C" void CPL_DLL RegisterOGROSM();
 
-CPL_CVSID("$Id: ogrosmdriver.cpp 33039 2016-01-18 17:04:21Z rouault $");
+CPL_CVSID("$Id: ogrosmdriver.cpp 35847 2016-10-21 06:06:13Z goatbar $");
 
 /************************************************************************/
 /*                      OGROSMDriverIdentify()                          */
@@ -43,7 +42,7 @@ CPL_CVSID("$Id: ogrosmdriver.cpp 33039 2016-01-18 17:04:21Z rouault $");
 static int OGROSMDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
-    if (poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes == 0)
+    if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes == 0 )
         return GDAL_IDENTIFY_FALSE;
 
     if( strstr((const char*)poOpenInfo->pabyHeader, "<osm") != NULL )
@@ -72,7 +71,7 @@ static int OGROSMDriverIdentify( GDALOpenInfo* poOpenInfo )
 static GDALDataset *OGROSMDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    if (poOpenInfo->eAccess == GA_Update )
+    if( poOpenInfo->eAccess == GA_Update )
         return NULL;
     if( OGROSMDriverIdentify(poOpenInfo) == FALSE )
         return NULL;
@@ -123,4 +122,3 @@ void RegisterOGROSM()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp b/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp
index df53bd2..07afd9f 100644
--- a/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp
+++ b/ogr/ogrsf_frmts/osm/ogrosmlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrosmlayer.cpp 35846 2016-10-21 05:20:10Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGROSMLayer class
@@ -33,18 +32,17 @@
 #include "cpl_time.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrosmlayer.cpp 35846 2016-10-21 05:20:10Z goatbar $");
+CPL_CVSID("$Id: ogrosmlayer.cpp 37534 2017-03-01 16:50:58Z rouault $");
 
-#define SWITCH_THRESHOLD   10000
-#define MAX_THRESHOLD      100000
+static const int SWITCH_THRESHOLD = 10000;
+static const int MAX_THRESHOLD = 100000;
 
-#define ALLTAGS_LENGTH     8192
+static const int ALLTAGS_LENGTH = 8192;
 
 /************************************************************************/
 /*                          OGROSMLayer()                               */
 /************************************************************************/
 
-
 OGROSMLayer::OGROSMLayer( OGROSMDataSource* poDSIn, int nIdxLayerIn,
                           const char* pszName ) :
     poDS(poDSIn),
@@ -90,12 +88,12 @@ OGROSMLayer::~OGROSMLayer()
 {
     poFeatureDefn->Release();
 
-    if (poSRS)
+    if( poSRS )
         poSRS->Release();
 
     for( int i=0; i<nFeatureArraySize; i++ )
     {
-        if (papoFeatures[i])
+        if( papoFeatures[i] )
             delete papoFeatures[i];
     }
 
@@ -124,10 +122,10 @@ OGROSMLayer::~OGROSMLayer()
 
 void OGROSMLayer::ResetReading()
 {
-    if ( !bResetReadingAllowed || poDS->IsInterleavedReading() )
+    if( !bResetReadingAllowed || poDS->IsInterleavedReading() )
         return;
 
-    poDS->ResetReading();
+    poDS->MyResetReading();
 }
 
 /************************************************************************/
@@ -138,7 +136,7 @@ void OGROSMLayer::ForceResetReading()
 {
     for(int i=0;i<nFeatureArraySize;i++)
     {
-        if (papoFeatures[i])
+        if( papoFeatures[i] )
             delete papoFeatures[i];
     }
     nFeatureArrayIndex = 0;
@@ -167,7 +165,7 @@ OGRErr OGROSMLayer::SetAttributeFilter( const char* pszAttrQuery )
     {
         if( !poDS->IsInterleavedReading() )
         {
-            poDS->ResetReading();
+            poDS->MyResetReading();
         }
     }
     else
@@ -200,33 +198,40 @@ GIntBig OGROSMLayer::GetFeatureCount( int bForce )
 
 OGRFeature *OGROSMLayer::GetNextFeature()
 {
+    OGROSMLayer* poNewCurLayer = NULL;
+    OGRFeature* poFeature = MyGetNextFeature(&poNewCurLayer, NULL, NULL);
+    poDS->SetCurrentLayer(poNewCurLayer);
+    return poFeature;
+}
+
+OGRFeature *OGROSMLayer::MyGetNextFeature( OGROSMLayer** ppoNewCurLayer,
+                                           GDALProgressFunc pfnProgress,
+                                           void* pProgressData )
+{
+    *ppoNewCurLayer = poDS->GetCurrentLayer();
     bResetReadingAllowed = true;
 
-    if ( nFeatureArraySize == 0)
+    if( nFeatureArraySize == 0 )
     {
-        if ( poDS->IsInterleavedReading() )
+        if( poDS->IsInterleavedReading() )
         {
-            int i;
-
-            OGRLayer* poCurrentLayer = poDS->GetCurrentLayer();
-            if ( poCurrentLayer == NULL )
+            if( *ppoNewCurLayer  == NULL )
             {
-                poDS->SetCurrentLayer(this);
+                 *ppoNewCurLayer = this;
             }
-            else if( poCurrentLayer != this )
+            else if( *ppoNewCurLayer  != this )
             {
                 return NULL;
             }
 
-            /* If too many features have been accumulated in */
-            /* another layer, we force */
-            /* a switch to that layer, so that it gets emptied */
-            for(i=0;i<poDS->GetLayerCount();i++)
+            // If too many features have been accumulated in another layer, we
+            // force a switch to that layer, so that it gets emptied.
+            for( int i = 0; i < poDS->GetLayerCount(); i++ )
             {
-                if (poDS->papoLayers[i] != this &&
-                    poDS->papoLayers[i]->nFeatureArraySize > SWITCH_THRESHOLD)
+                if( poDS->papoLayers[i] != this &&
+                    poDS->papoLayers[i]->nFeatureArraySize > SWITCH_THRESHOLD )
                 {
-                    poDS->SetCurrentLayer(poDS->papoLayers[i]);
+                    *ppoNewCurLayer = poDS->papoLayers[i];
                     CPLDebug("OSM", "Switching to '%s' as they are too many "
                                     "features in '%s'",
                              poDS->papoLayers[i]->GetName(),
@@ -235,22 +240,23 @@ OGRFeature *OGROSMLayer::GetNextFeature()
                 }
             }
 
-            /* Read some more data and accumulate features */
-            poDS->ParseNextChunk(nIdxLayer);
+            // Read some more data and accumulate features.
+            poDS->ParseNextChunk(nIdxLayer, pfnProgress, pProgressData);
 
-            if ( nFeatureArraySize == 0 )
+            if( nFeatureArraySize == 0 )
             {
-                /* If there are really no more features to read in the */
-                /* current layer, force a switch to another non-empty layer */
+                // If there are really no more features to read in the
+                // current layer, force a switch to another non-empty layer.
 
-                for(i=0;i<poDS->GetLayerCount();i++)
+                for( int i = 0; i < poDS->GetLayerCount(); i++ )
                 {
-                    if (poDS->papoLayers[i] != this &&
-                        poDS->papoLayers[i]->nFeatureArraySize > 0)
+                    if( poDS->papoLayers[i] != this &&
+                        poDS->papoLayers[i]->nFeatureArraySize > 0 )
                     {
-                        poDS->SetCurrentLayer(poDS->papoLayers[i]);
+                        *ppoNewCurLayer = poDS->papoLayers[i];
                         CPLDebug("OSM",
-                                 "Switching to '%s' as they are no more feature in '%s'",
+                                 "Switching to '%s' as they are "
+                                 "no more feature in '%s'",
                                  poDS->papoLayers[i]->GetName(),
                                  GetName());
                         return NULL;
@@ -258,7 +264,7 @@ OGRFeature *OGROSMLayer::GetNextFeature()
                 }
 
                 /* Game over : no more data to read from the stream */
-                poDS->SetCurrentLayer(NULL);
+                *ppoNewCurLayer = NULL;
                 return NULL;
             }
         }
@@ -266,10 +272,10 @@ OGRFeature *OGROSMLayer::GetNextFeature()
         {
             while( true )
             {
-                int bRet = poDS->ParseNextChunk(nIdxLayer);
-                if (nFeatureArraySize != 0)
+                int bRet = poDS->ParseNextChunk(nIdxLayer, NULL, NULL);
+                if( nFeatureArraySize != 0 )
                     break;
-                if (bRet == FALSE)
+                if( bRet == FALSE )
                     return NULL;
             }
         }
@@ -280,7 +286,7 @@ OGRFeature *OGROSMLayer::GetNextFeature()
     papoFeatures[nFeatureArrayIndex] = NULL;
     nFeatureArrayIndex++;
 
-    if ( nFeatureArrayIndex == nFeatureArraySize)
+    if( nFeatureArrayIndex == nFeatureArraySize )
         nFeatureArrayIndex = nFeatureArraySize = 0;
 
     return poFeature;
@@ -295,7 +301,7 @@ int OGROSMLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap, OLCFastGetExtent) )
     {
         OGREnvelope sExtent;
-        if (poDS->GetExtent(&sExtent) == OGRERR_NONE)
+        if( poDS->GetExtent(&sExtent) == OGRERR_NONE )
             return TRUE;
     }
 
@@ -306,9 +312,10 @@ int OGROSMLayer::TestCapability( const char * pszCap )
 /*                             AddToArray()                             */
 /************************************************************************/
 
-int  OGROSMLayer::AddToArray(OGRFeature* poFeature, int bCheckFeatureThreshold)
+bool OGROSMLayer::AddToArray( OGRFeature* poFeature,
+                              int bCheckFeatureThreshold )
 {
-    if( bCheckFeatureThreshold && nFeatureArraySize > MAX_THRESHOLD)
+    if( bCheckFeatureThreshold && nFeatureArraySize > MAX_THRESHOLD )
     {
         if( !bHasWarnedTooManyFeatures )
         {
@@ -318,27 +325,31 @@ int  OGROSMLayer::AddToArray(OGRFeature* poFeature, int bCheckFeatureThreshold)
                     GetName());
         }
         bHasWarnedTooManyFeatures = true;
-        return FALSE;
+        return false;
     }
 
-    if (nFeatureArraySize == nFeatureArrayMaxSize)
+    if( nFeatureArraySize == nFeatureArrayMaxSize )
     {
-        nFeatureArrayMaxSize = nFeatureArrayMaxSize + nFeatureArrayMaxSize / 2 + 128;
-        CPLDebug("OSM", "For layer %s, new max size is %d", GetName(), nFeatureArrayMaxSize);
-        OGRFeature** papoNewFeatures = (OGRFeature**)VSI_REALLOC_VERBOSE(papoFeatures,
-                                nFeatureArrayMaxSize * sizeof(OGRFeature*));
-        if (papoNewFeatures == NULL)
+        nFeatureArrayMaxSize =
+            nFeatureArrayMaxSize + nFeatureArrayMaxSize / 2 + 128;
+        CPLDebug("OSM",
+                 "For layer %s, new max size is %d",
+                 GetName(), nFeatureArrayMaxSize);
+        OGRFeature** papoNewFeatures = static_cast<OGRFeature **>(
+            VSI_REALLOC_VERBOSE(papoFeatures,
+                                nFeatureArrayMaxSize * sizeof(OGRFeature*)));
+        if( papoNewFeatures == NULL )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "For layer %s, cannot resize feature array to %d features",
                      GetName(), nFeatureArrayMaxSize);
-            return FALSE;
+            return false;
         }
         papoFeatures = papoNewFeatures;
     }
     papoFeatures[nFeatureArraySize ++] = poFeature;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -362,14 +373,14 @@ int  OGROSMLayer::AddFeature(OGRFeature* poFeature,
 {
     if( !bUserInterested )
     {
-        if (pbFilteredOut)
+        if( pbFilteredOut )
             *pbFilteredOut = TRUE;
         delete poFeature;
         return TRUE;
     }
 
     OGRGeometry* poGeom = poFeature->GetGeometryRef();
-    if (poGeom)
+    if( poGeom )
         poGeom->assignSpatialReference( poSRS );
 
     if( (m_poFilterGeom == NULL
@@ -377,7 +388,7 @@ int  OGROSMLayer::AddFeature(OGRFeature* poFeature,
         && (m_poAttrQuery == NULL || bAttrFilterAlreadyEvaluated
             || m_poAttrQuery->Evaluate( poFeature )) )
     {
-        if (!AddToArray(poFeature, bCheckFeatureThreshold))
+        if( !AddToArray(poFeature, bCheckFeatureThreshold) )
         {
             delete poFeature;
             return FALSE;
@@ -385,13 +396,13 @@ int  OGROSMLayer::AddFeature(OGRFeature* poFeature,
     }
     else
     {
-        if (pbFilteredOut)
+        if( pbFilteredOut )
             *pbFilteredOut = TRUE;
         delete poFeature;
         return TRUE;
     }
 
-    if (pbFilteredOut)
+    if( pbFilteredOut )
         *pbFilteredOut = FALSE;
     return TRUE;
 }
@@ -403,7 +414,7 @@ int  OGROSMLayer::AddFeature(OGRFeature* poFeature,
 OGRErr OGROSMLayer::GetExtent( OGREnvelope *psExtent,
                                int /* bForce */ )
 {
-    if (poDS->GetExtent(psExtent) == OGRERR_NONE)
+    if( poDS->GetExtent(psExtent) == OGRERR_NONE )
         return OGRERR_NONE;
 
     /* return OGRLayer::GetExtent(psExtent, bForce);*/
@@ -414,7 +425,7 @@ OGRErr OGROSMLayer::GetExtent( OGREnvelope *psExtent,
 /*                          GetLaunderedFieldName()                     */
 /************************************************************************/
 
-const char* OGROSMLayer::GetLaunderedFieldName(const char* pszName)
+const char* OGROSMLayer::GetLaunderedFieldName( const char* pszName )
 {
     if( poDS->DoesAttributeNameLaundering()  &&
         strchr(pszName, ':') != NULL )
@@ -440,7 +451,7 @@ const char* OGROSMLayer::GetLaunderedFieldName(const char* pszName)
 /*                              AddField()                              */
 /************************************************************************/
 
-void OGROSMLayer::AddField(const char* pszName, OGRFieldType eFieldType)
+void OGROSMLayer::AddField( const char* pszName, OGRFieldType eFieldType )
 {
     const char* pszLaunderedName = GetLaunderedFieldName(pszName);
     OGRFieldDefn oField(pszLaunderedName, eFieldType);
@@ -468,7 +479,7 @@ void OGROSMLayer::AddField(const char* pszName, OGRFieldType eFieldType)
 /*                              GetFieldIndex()                         */
 /************************************************************************/
 
-int OGROSMLayer::GetFieldIndex(const char* pszName)
+int OGROSMLayer::GetFieldIndex( const char* pszName )
 {
     std::map<const char*, int, ConstCharComp>::iterator oIter =
         oMapFieldNameToIndex.find(pszName);
@@ -482,11 +493,11 @@ int OGROSMLayer::GetFieldIndex(const char* pszName)
 /*                         AddInOtherOrAllTags()                        */
 /************************************************************************/
 
-int OGROSMLayer::AddInOtherOrAllTags(const char* pszK)
+int OGROSMLayer::AddInOtherOrAllTags( const char* pszK )
 {
     bool bAddToOtherTags = false;
 
-    if ( aoSetIgnoreKeys.find(pszK) == aoSetIgnoreKeys.end() )
+    if( aoSetIgnoreKeys.find(pszK) == aoSetIgnoreKeys.end() )
     {
         char* pszColon = strchr((char*) pszK, ':');
         if( pszColon )
@@ -495,6 +506,7 @@ int OGROSMLayer::AddInOtherOrAllTags(const char* pszK)
             pszColon[1] = '\0';  /* Evil but OK */
             bAddToOtherTags = ( aoSetIgnoreKeys.find(pszK) ==
                                 aoSetIgnoreKeys.end() );
+            // cppcheck-suppress redundantAssignment
             pszColon[1] = chBackup;
         }
         else
@@ -508,7 +520,7 @@ int OGROSMLayer::AddInOtherOrAllTags(const char* pszK)
 /*                        OGROSMFormatForHSTORE()                       */
 /************************************************************************/
 
-static int OGROSMFormatForHSTORE(const char* pszV, char* pszAllTags)
+static int OGROSMFormatForHSTORE( const char* pszV, char* pszAllTags )
 {
     int nAllTagsOff = 0;
 
@@ -532,7 +544,7 @@ static int OGROSMFormatForHSTORE(const char* pszV, char* pszAllTags)
 
 void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
                                     GIntBig nID,
-                                    int bIsWayID,
+                                    bool bIsWayID,
                                     unsigned int nTags, OSMTag* pasTags,
                                     OSMInfo* psInfo)
 {
@@ -568,7 +580,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
         if( psInfo->bTimeStampIsStr )
         {
             OGRField sField;
-            if (OGRParseXMLDateTime(psInfo->ts.pszTimeStamp, &sField))
+            if( OGRParseXMLDateTime(psInfo->ts.pszTimeStamp, &sField) )
             {
                 poFeature->SetField("osm_timestamp", &sField);
             }
@@ -586,7 +598,6 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
                                 static_cast<float>(brokendown.tm_sec),
                                 0);
         }
-
     }
     if( bHasUID )
     {
@@ -613,9 +624,9 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
             if( nIndexAllTags < 0 )
                 continue;
         }
-        if ( nIndexAllTags >= 0 || nIndexOtherTags >= 0 )
+        if( nIndexAllTags >= 0 || nIndexOtherTags >= 0 )
         {
-            if ( AddInOtherOrAllTags(pszK) )
+            if( AddInOtherOrAllTags(pszK) )
             {
                 int nLenK = (int)strlen(pszK);
                 int nLenV = (int)strlen(pszV);
@@ -647,8 +658,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
             }
 
 #ifdef notdef
-            if ( aoSetWarnKeys.find(pszK) ==
-                 aoSetWarnKeys.end() )
+            if( aoSetWarnKeys.find(pszK) == aoSetWarnKeys.end() )
             {
                 aoSetWarnKeys.insert(pszK);
                 CPLDebug("OSM_KEY", "Ignored key : %s", pszK);
@@ -673,7 +683,7 @@ void OGROSMLayer::SetFieldsFromTags(OGRFeature* poFeature,
         {
             if( oAttr.anIndexToBind[j] >= 0 )
             {
-                if( !poFeature->IsFieldSet(oAttr.anIndexToBind[j]) )
+                if( !poFeature->IsFieldSetAndNotNull(oAttr.anIndexToBind[j]) )
                 {
                     sqlite3_bind_null( oAttr.hStmt, j + 1 );
                 }
@@ -758,7 +768,7 @@ const OGREnvelope* OGROSMLayer::GetSpatialFilterEnvelope()
 /*                        AddUnsignificantKey()                         */
 /************************************************************************/
 
-void OGROSMLayer::AddUnsignificantKey(const char* pszK)
+void OGROSMLayer::AddUnsignificantKey( const char* pszK )
 {
     char* pszKDup = CPLStrdup(pszK);
     apszUnsignificantKeys.push_back(pszKDup);
@@ -769,7 +779,7 @@ void OGROSMLayer::AddUnsignificantKey(const char* pszK)
 /*                          AddIgnoreKey()                              */
 /************************************************************************/
 
-void OGROSMLayer::AddIgnoreKey(const char* pszK)
+void OGROSMLayer::AddIgnoreKey( const char* pszK )
 {
     char* pszKDup = CPLStrdup(pszK);
     apszIgnoreKeys.push_back(pszKDup);
@@ -780,7 +790,7 @@ void OGROSMLayer::AddIgnoreKey(const char* pszK)
 /*                           AddWarnKey()                               */
 /************************************************************************/
 
-void OGROSMLayer::AddWarnKey(const char* pszK)
+void OGROSMLayer::AddWarnKey( const char* pszK )
 {
     aoSetWarnKeys.insert(pszK);
 }
@@ -789,19 +799,18 @@ void OGROSMLayer::AddWarnKey(const char* pszK)
 /*                           AddWarnKey()                               */
 /************************************************************************/
 
-void OGROSMLayer::AddComputedAttribute(const char* pszName,
-                                       OGRFieldType eType,
-                                       const char* pszSQL)
+void OGROSMLayer::AddComputedAttribute( const char* pszName,
+                                        OGRFieldType eType,
+                                        const char* pszSQL )
 {
     if( poDS->hDBForComputedAttributes == NULL )
     {
-        int rc;
-#ifdef HAVE_SQLITE_VFS
-        rc = sqlite3_open_v2( ":memory:", &(poDS->hDBForComputedAttributes),
-                              SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX, NULL );
-#else
-        rc = sqlite3_open( ":memory:", &(poDS->hDBForComputedAttributes) );
-#endif
+        const int rc =
+            sqlite3_open_v2(
+                ":memory:", &(poDS->hDBForComputedAttributes),
+                SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+                SQLITE_OPEN_NOMUTEX,
+                NULL );
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -851,13 +860,13 @@ void OGROSMLayer::AddComputedAttribute(const char* pszName,
 
     CPLDebug("OSM", "SQL : \"%s\"", osSQL.c_str());
 
-    sqlite3_stmt  *hStmt;
-    int rc = sqlite3_prepare( poDS->hDBForComputedAttributes, osSQL, -1,
+    sqlite3_stmt *hStmt = NULL;
+    int rc = sqlite3_prepare_v2( poDS->hDBForComputedAttributes, osSQL, -1,
                               &hStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "sqlite3_prepare() failed :  %s",
+                  "sqlite3_prepare_v2() failed :  %s",
                   sqlite3_errmsg(poDS->hDBForComputedAttributes) );
         return;
     }
@@ -865,10 +874,10 @@ void OGROSMLayer::AddComputedAttribute(const char* pszName,
     OGRFieldDefn oField(pszName, eType);
     poFeatureDefn->AddFieldDefn(&oField);
     oComputedAttributes.push_back(OGROSMComputedAttribute(pszName));
-    oComputedAttributes[oComputedAttributes.size()-1].eType = eType;
-    oComputedAttributes[oComputedAttributes.size()-1].nIndex = poFeatureDefn->GetFieldCount() - 1;
-    oComputedAttributes[oComputedAttributes.size()-1].osSQL = pszSQL;
-    oComputedAttributes[oComputedAttributes.size()-1].hStmt = hStmt;
-    oComputedAttributes[oComputedAttributes.size()-1].aosAttrToBind = aosAttrToBind;
-    oComputedAttributes[oComputedAttributes.size()-1].anIndexToBind = anIndexToBind;
+    oComputedAttributes.back().eType = eType;
+    oComputedAttributes.back().nIndex = poFeatureDefn->GetFieldCount() - 1;
+    oComputedAttributes.back().osSQL = pszSQL;
+    oComputedAttributes.back().hStmt = hStmt;
+    oComputedAttributes.back().aosAttrToBind = aosAttrToBind;
+    oComputedAttributes.back().anIndexToBind = anIndexToBind;
 }
diff --git a/ogr/ogrsf_frmts/osm/osm_parser.cpp b/ogr/ogrsf_frmts/osm/osm_parser.cpp
index ec6353f..11098b3 100644
--- a/ogr/ogrsf_frmts/osm/osm_parser.cpp
+++ b/ogr/ogrsf_frmts/osm/osm_parser.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: osm_parser.cpp 33138 2016-01-24 11:18:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
@@ -38,28 +37,30 @@
 #include "ogr_expat.h"
 #endif
 
-/* The buffer that are passed to GPB decoding are extended with 0's */
-/* to be sure that we will be able to read a single 64bit value without */
-/* doing checks for each byte */
-#define EXTRA_BYTES     1
+#include <algorithm>
 
-#define XML_BUFSIZE 64*1024
+CPL_CVSID("$Id: osm_parser.cpp 37052 2017-01-01 18:36:35Z rouault $");
 
-CPL_CVSID("$Id: osm_parser.cpp 33138 2016-01-24 11:18:11Z rouault $");
+// The buffer that are passed to GPB decoding are extended with 0's
+// to be sure that we will be able to read a single 64bit value without
+// doing checks for each byte.
+static const int EXTRA_BYTES = 1;
+
+static const int XML_BUFSIZE = 64 * 1024;
 
 /************************************************************************/
 /*                            INIT_INFO()                               */
 /************************************************************************/
 
-#define INIT_INFO(sInfo) \
-    sInfo.ts.nTimeStamp = 0; \
-    sInfo.nChangeset = 0; \
-    sInfo.nVersion = 0; \
-    sInfo.nUID = 0; \
-    sInfo.bTimeStampIsStr = false; \
-    sInfo.pszUserSID = NULL;
-/*    \    sInfo.nVisible = 1; */
-
+static void INIT_INFO( OSMInfo *sInfo )
+{
+    sInfo->ts.nTimeStamp = 0;
+    sInfo->nChangeset = 0;
+    sInfo->nVersion = 0;
+    sInfo->nUID = 0;
+    sInfo->bTimeStampIsStr = false;
+    sInfo->pszUserSID = NULL;
+}
 
 /************************************************************************/
 /*                            _OSMContext                               */
@@ -118,7 +119,7 @@ struct _OSMContext
 
     VSILFILE      *fp;
 
-    int            bPBF;
+    bool           bPBF;
 
     double         dfLeft;
     double         dfRight;
@@ -138,9 +139,9 @@ struct _OSMContext
 /*                          ReadBlobHeader()                            */
 /************************************************************************/
 
-#define BLOBHEADER_IDX_TYPE         1
-#define BLOBHEADER_IDX_INDEXDATA    2
-#define BLOBHEADER_IDX_DATASIZE     3
+static const int BLOBHEADER_IDX_TYPE = 1;
+static const int BLOBHEADER_IDX_INDEXDATA = 2;
+static const int BLOBHEADER_IDX_DATASIZE = 3;
 
 typedef enum
 {
@@ -150,45 +151,45 @@ typedef enum
 } BlobType;
 
 static
-int ReadBlobHeader(GByte* pabyData, GByte* pabyDataLimit,
-                   unsigned int* pnBlobSize, BlobType* peBlobType)
+bool ReadBlobHeader( GByte* pabyData, GByte* pabyDataLimit,
+                     unsigned int* pnBlobSize, BlobType* peBlobType )
 {
     *pnBlobSize = 0;
     *peBlobType = BLOB_UNKNOWN;
 
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(BLOBHEADER_IDX_TYPE, WT_DATA))
+        if( nKey == MAKE_KEY(BLOBHEADER_IDX_TYPE, WT_DATA) )
         {
-            unsigned int nDataLength;
+            unsigned int nDataLength = 0;
             READ_SIZE(pabyData, pabyDataLimit, nDataLength);
 
-            if (nDataLength == 7 && memcmp(pabyData, "OSMData", 7) == 0)
+            if( nDataLength == 7 && memcmp(pabyData, "OSMData", 7) == 0 )
             {
                 *peBlobType = BLOB_OSMDATA;
             }
-            else if (nDataLength == 9 && memcmp(pabyData, "OSMHeader", 9) == 0)
+            else if( nDataLength == 9 && memcmp(pabyData, "OSMHeader", 9) == 0 )
             {
                 *peBlobType = BLOB_OSMHEADER;
             }
 
             pabyData += nDataLength;
         }
-        else if (nKey == MAKE_KEY(BLOBHEADER_IDX_INDEXDATA, WT_DATA))
+        else if( nKey == MAKE_KEY(BLOBHEADER_IDX_INDEXDATA, WT_DATA) )
         {
-            /* Ignored if found */
-            unsigned int nDataLength;
+            // Ignored if found.
+            unsigned int nDataLength = 0;
             READ_SIZE(pabyData, pabyDataLimit, nDataLength);
             pabyData += nDataLength;
         }
-        else if (nKey == MAKE_KEY(BLOBHEADER_IDX_DATASIZE, WT_VARINT))
+        else if( nKey == MAKE_KEY(BLOBHEADER_IDX_DATASIZE, WT_VARINT) )
         {
-            unsigned int nBlobSize;
+            unsigned int nBlobSize = 0;
             READ_VARUINT32(pabyData, pabyDataLimit, nBlobSize);
-            /* printf("nBlobSize = %d\n", nBlobSize); */
+            // printf("nBlobSize = %d\n", nBlobSize);
             *pnBlobSize = nBlobSize;
         }
         else
@@ -200,21 +201,21 @@ int ReadBlobHeader(GByte* pabyData, GByte* pabyDataLimit,
     return pabyData == pabyDataLimit;
 
 end_error:
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                          ReadHeaderBBox()                            */
 /************************************************************************/
 
-#define HEADERBBOX_IDX_LEFT     1
-#define HEADERBBOX_IDX_RIGHT    2
-#define HEADERBBOX_IDX_TOP      3
-#define HEADERBBOX_IDX_BOTTOM   4
+static const int HEADERBBOX_IDX_LEFT = 1;
+static const int HEADERBBOX_IDX_RIGHT = 2;
+static const int HEADERBBOX_IDX_TOP = 3;
+static const int HEADERBBOX_IDX_BOTTOM = 4;
 
 static
-int ReadHeaderBBox(GByte* pabyData, GByte* pabyDataLimit,
-                   OSMContext* psCtxt)
+bool ReadHeaderBBox( GByte* pabyData, GByte* pabyDataLimit,
+                     OSMContext* psCtxt )
 {
     psCtxt->dfLeft = 0.0;
     psCtxt->dfRight = 0.0;
@@ -225,30 +226,30 @@ int ReadHeaderBBox(GByte* pabyData, GByte* pabyDataLimit,
 
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(HEADERBBOX_IDX_LEFT, WT_VARINT))
+        if( nKey == MAKE_KEY(HEADERBBOX_IDX_LEFT, WT_VARINT) )
         {
-            GIntBig nLeft;
+            GIntBig nLeft = 0;
             READ_VARSINT64(pabyData, pabyDataLimit, nLeft);
             psCtxt->dfLeft = nLeft * 1e-9;
         }
-        else if (nKey == MAKE_KEY(HEADERBBOX_IDX_RIGHT, WT_VARINT))
+        else if( nKey == MAKE_KEY(HEADERBBOX_IDX_RIGHT, WT_VARINT) )
         {
-            GIntBig nRight;
+            GIntBig nRight = 0;
             READ_VARSINT64(pabyData, pabyDataLimit, nRight);
             psCtxt->dfRight = nRight * 1e-9;
         }
-        else if (nKey == MAKE_KEY(HEADERBBOX_IDX_TOP, WT_VARINT))
+        else if( nKey == MAKE_KEY(HEADERBBOX_IDX_TOP, WT_VARINT) )
         {
-            GIntBig nTop;
+            GIntBig nTop = 0;
             READ_VARSINT64(pabyData, pabyDataLimit, nTop);
             psCtxt->dfTop = nTop * 1e-9;
         }
-        else if (nKey == MAKE_KEY(HEADERBBOX_IDX_BOTTOM, WT_VARINT))
+        else if( nKey == MAKE_KEY(HEADERBBOX_IDX_BOTTOM, WT_VARINT) )
         {
-            GIntBig nBottom;
+            GIntBig nBottom = 0;
             READ_VARSINT64(pabyData, pabyDataLimit, nBottom);
             psCtxt->dfBottom = nBottom * 1e-9;
         }
@@ -267,84 +268,92 @@ int ReadHeaderBBox(GByte* pabyData, GByte* pabyDataLimit,
 
 end_error:
     /* printf("<ReadHeaderBBox\n"); */
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                          ReadOSMHeader()                             */
 /************************************************************************/
 
-#define OSMHEADER_IDX_BBOX                  1
-#define OSMHEADER_IDX_REQUIRED_FEATURES     4
-#define OSMHEADER_IDX_OPTIONAL_FEATURES     5
-#define OSMHEADER_IDX_WRITING_PROGRAM       16
-#define OSMHEADER_IDX_SOURCE                17
+static const int OSMHEADER_IDX_BBOX              = 1;
+static const int OSMHEADER_IDX_REQUIRED_FEATURES = 4;
+static const int OSMHEADER_IDX_OPTIONAL_FEATURES = 5;
+static const int OSMHEADER_IDX_WRITING_PROGRAM   = 16;
+static const int OSMHEADER_IDX_SOURCE            = 17;
 
 /* Ignored */
-#define OSMHEADER_IDX_OSMOSIS_REPLICATION_TIMESTAMP  32
-#define OSMHEADER_IDX_OSMOSIS_REPLICATION_SEQ_NUMBER 33
-#define OSMHEADER_IDX_OSMOSIS_REPLICATION_BASE_URL   34
+static const int OSMHEADER_IDX_OSMOSIS_REPLICATION_TIMESTAMP  = 32;
+static const int OSMHEADER_IDX_OSMOSIS_REPLICATION_SEQ_NUMBER = 33;
+static const int OSMHEADER_IDX_OSMOSIS_REPLICATION_BASE_URL   = 34;
 
 static
-int ReadOSMHeader(GByte* pabyData, GByte* pabyDataLimit,
-                  OSMContext* psCtxt)
+bool ReadOSMHeader( GByte* pabyData, GByte* pabyDataLimit,
+                    OSMContext* psCtxt )
 {
-    char* pszTxt;
+    char* pszTxt = NULL;
+
+    // TODO(schwehr): Remove goto macros.
 
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(OSMHEADER_IDX_BBOX, WT_DATA))
+        if( nKey == MAKE_KEY(OSMHEADER_IDX_BBOX, WT_DATA) )
         {
-            unsigned int nBBOXSize;
+            unsigned int nBBOXSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nBBOXSize);
 
-            if (!ReadHeaderBBox(pabyData, pabyData + nBBOXSize, psCtxt)) GOTO_END_ERROR;
+            if( !ReadHeaderBBox(pabyData, pabyData + nBBOXSize, psCtxt) )
+                GOTO_END_ERROR;
 
             pabyData += nBBOXSize;
         }
-        else if (nKey == MAKE_KEY(OSMHEADER_IDX_REQUIRED_FEATURES, WT_DATA))
+        else if( nKey == MAKE_KEY(OSMHEADER_IDX_REQUIRED_FEATURES, WT_DATA) )
         {
             READ_TEXT(pabyData, pabyDataLimit, pszTxt);
-            /* printf("OSMHEADER_IDX_REQUIRED_FEATURES = %s\n", pszTxt); */
-            if (!(strcmp(pszTxt, "OsmSchema-V0.6") == 0 ||
-                  strcmp(pszTxt, "DenseNodes") == 0))
+            // printf("OSMHEADER_IDX_REQUIRED_FEATURES = %s\n", pszTxt)
+            if( !(strcmp(pszTxt, "OsmSchema-V0.6") == 0 ||
+                  strcmp(pszTxt, "DenseNodes") == 0) )
             {
-                fprintf(stderr, "Error: unsupported required feature : %s\n", pszTxt);
+                CPLError(CE_Failure, CPLE_NotSupported,
+                        "Error: unsupported required feature : %s",
+                        pszTxt);
                 VSIFree(pszTxt);
-                GOTO_END_ERROR;
+                GOTO_END_ERROR;  // TODO(schwehr): Get rid of goto.
             }
             VSIFree(pszTxt);
         }
-        else if (nKey == MAKE_KEY(OSMHEADER_IDX_OPTIONAL_FEATURES, WT_DATA))
+        else if( nKey == MAKE_KEY(OSMHEADER_IDX_OPTIONAL_FEATURES, WT_DATA) )
         {
             READ_TEXT(pabyData, pabyDataLimit, pszTxt);
-            /* printf("OSMHEADER_IDX_OPTIONAL_FEATURES = %s\n", pszTxt); */
+            // printf("OSMHEADER_IDX_OPTIONAL_FEATURES = %s\n", pszTxt);
             VSIFree(pszTxt);
         }
-        else if (nKey == MAKE_KEY(OSMHEADER_IDX_WRITING_PROGRAM, WT_DATA))
+        else if( nKey == MAKE_KEY(OSMHEADER_IDX_WRITING_PROGRAM, WT_DATA) )
         {
             READ_TEXT(pabyData, pabyDataLimit, pszTxt);
-            /* printf("OSMHEADER_IDX_WRITING_PROGRAM = %s\n", pszTxt); */
+            // printf("OSMHEADER_IDX_WRITING_PROGRAM = %s\n", pszTxt);
             VSIFree(pszTxt);
         }
-        else if (nKey == MAKE_KEY(OSMHEADER_IDX_SOURCE, WT_DATA))
+        else if( nKey == MAKE_KEY(OSMHEADER_IDX_SOURCE, WT_DATA) )
         {
             READ_TEXT(pabyData, pabyDataLimit, pszTxt);
-            /* printf("OSMHEADER_IDX_SOURCE = %s\n", pszTxt); */
+            // printf("OSMHEADER_IDX_SOURCE = %s\n", pszTxt);
             VSIFree(pszTxt);
         }
-        else if (nKey == MAKE_KEY(OSMHEADER_IDX_OSMOSIS_REPLICATION_TIMESTAMP, WT_VARINT))
+        else if( nKey == MAKE_KEY(OSMHEADER_IDX_OSMOSIS_REPLICATION_TIMESTAMP,
+                                  WT_VARINT) )
         {
             SKIP_VARINT(pabyData, pabyDataLimit);
         }
-        else if (nKey == MAKE_KEY(OSMHEADER_IDX_OSMOSIS_REPLICATION_SEQ_NUMBER, WT_VARINT))
+        else if( nKey == MAKE_KEY(OSMHEADER_IDX_OSMOSIS_REPLICATION_SEQ_NUMBER,
+                                  WT_VARINT) )
         {
             SKIP_VARINT(pabyData, pabyDataLimit);
         }
-        else if (nKey == MAKE_KEY(OSMHEADER_IDX_OSMOSIS_REPLICATION_BASE_URL, WT_DATA))
+        else if( nKey == MAKE_KEY(OSMHEADER_IDX_OSMOSIS_REPLICATION_BASE_URL,
+                                  WT_DATA) )
         {
             READ_TEXT(pabyData, pabyDataLimit, pszTxt);
             /* printf("OSMHEADER_IDX_OSMOSIS_REPLICATION_BASE_URL = %s\n", pszTxt); */
@@ -359,18 +368,18 @@ int ReadOSMHeader(GByte* pabyData, GByte* pabyDataLimit,
     return pabyData == pabyDataLimit;
 
 end_error:
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                         ReadStringTable()                            */
 /************************************************************************/
 
-#define READSTRINGTABLE_IDX_STRING  1
+static const int READSTRINGTABLE_IDX_STRING = 1;
 
 static
-int ReadStringTable(GByte* pabyData, GByte* pabyDataLimit,
-                    OSMContext* psCtxt)
+bool ReadStringTable( GByte* pabyData, GByte* pabyDataLimit,
+                      OSMContext* psCtxt )
 {
     char* pszStrBuf = (char*)pabyData;
 
@@ -379,12 +388,11 @@ int ReadStringTable(GByte* pabyData, GByte* pabyDataLimit,
 
     psCtxt->pszStrBuf = pszStrBuf;
 
-    if ((unsigned int)(pabyDataLimit - pabyData) > psCtxt->nStrAllocated)
+    if( (unsigned int)(pabyDataLimit - pabyData) > psCtxt->nStrAllocated )
     {
-        int* panStrOffNew;
-        psCtxt->nStrAllocated = MAX(psCtxt->nStrAllocated * 2,
+        psCtxt->nStrAllocated = std::max(psCtxt->nStrAllocated * 2,
                                           (unsigned int)(pabyDataLimit - pabyData));
-        panStrOffNew = (int*) VSI_REALLOC_VERBOSE(
+        int* panStrOffNew = (int*) VSI_REALLOC_VERBOSE(
             panStrOff, psCtxt->nStrAllocated * sizeof(int));
         if( panStrOffNew == NULL )
             GOTO_END_ERROR;
@@ -393,21 +401,20 @@ int ReadStringTable(GByte* pabyData, GByte* pabyDataLimit,
 
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
         while (nKey == MAKE_KEY(READSTRINGTABLE_IDX_STRING, WT_DATA))
         {
-            GByte* pbSaved;
-            unsigned int nDataLength;
+            unsigned int nDataLength = 0;
             READ_SIZE(pabyData, pabyDataLimit, nDataLength);
 
             panStrOff[nStrCount ++] = static_cast<int>(pabyData - (GByte*)pszStrBuf);
-            pbSaved = &pabyData[nDataLength];
+            GByte* pbSaved = &pabyData[nDataLength];
 
             pabyData += nDataLength;
 
-            if (pabyData < pabyDataLimit)
+            if( pabyData < pabyDataLimit )
             {
                 READ_FIELD_KEY(nKey);
                 *pbSaved = 0;
@@ -421,7 +428,7 @@ int ReadStringTable(GByte* pabyData, GByte* pabyDataLimit,
             }
         }
 
-        if (pabyData < pabyDataLimit)
+        if( pabyData < pabyDataLimit )
         {
             SKIP_UNKNOWN_FIELD(pabyData, pabyDataLimit, TRUE);
         }
@@ -444,22 +451,22 @@ end_error:
 /*                         ReadDenseNodes()                             */
 /************************************************************************/
 
-#define DENSEINFO_IDX_VERSION     1
-#define DENSEINFO_IDX_TIMESTAMP   2
-#define DENSEINFO_IDX_CHANGESET   3
-#define DENSEINFO_IDX_UID         4
-#define DENSEINFO_IDX_USER_SID    5
-#define DENSEINFO_IDX_VISIBLE     6
+static const int DENSEINFO_IDX_VERSION   = 1;
+static const int DENSEINFO_IDX_TIMESTAMP = 2;
+static const int DENSEINFO_IDX_CHANGESET = 3;
+static const int DENSEINFO_IDX_UID       = 4;
+static const int DENSEINFO_IDX_USER_SID  = 5;
+static const int DENSEINFO_IDX_VISIBLE   = 6;
 
-#define DENSENODES_IDX_ID           1
-#define DENSENODES_IDX_DENSEINFO    5
-#define DENSENODES_IDX_LAT          8
-#define DENSENODES_IDX_LON          9
-#define DENSENODES_IDX_KEYVALS      10
+static const int DENSENODES_IDX_ID        = 1;
+static const int DENSENODES_IDX_DENSEINFO = 5;
+static const int DENSENODES_IDX_LAT       = 8;
+static const int DENSENODES_IDX_LON       = 9;
+static const int DENSENODES_IDX_KEYVALS   = 10;
 
 static
-int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
-                   OSMContext* psCtxt)
+bool ReadDenseNodes( GByte* pabyData, GByte* pabyDataLimit,
+                     OSMContext* psCtxt )
 {
     GByte* pabyDataIDs = NULL;
     GByte* pabyDataIDsLimit = NULL;
@@ -471,23 +478,22 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
     /* printf(">ReadDenseNodes\n"); */
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
         if( nKey == MAKE_KEY(DENSENODES_IDX_ID, WT_DATA) )
         {
-            unsigned int nSize;
+            unsigned int nSize = 0;
 
-            if (pabyDataIDs != NULL)
+            if( pabyDataIDs != NULL )
                 GOTO_END_ERROR;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (nSize > psCtxt->nNodesAllocated)
+            if( nSize > psCtxt->nNodesAllocated )
             {
-                OSMNode* pasNodesNew;
-                psCtxt->nNodesAllocated = MAX(psCtxt->nNodesAllocated * 2,
+                psCtxt->nNodesAllocated = std::max(psCtxt->nNodesAllocated * 2,
                                                  nSize);
-                pasNodesNew = (OSMNode*) VSI_REALLOC_VERBOSE(
+                OSMNode* pasNodesNew = (OSMNode*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasNodes, psCtxt->nNodesAllocated * sizeof(OSMNode));
                 if( pasNodesNew == NULL )
                     GOTO_END_ERROR;
@@ -500,22 +506,21 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
         }
         else if( nKey == MAKE_KEY(DENSENODES_IDX_DENSEINFO, WT_DATA) )
         {
-            unsigned int nSize;
-            GByte* pabyDataNewLimit;
+            unsigned int nSize = 0;
 
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
             /* Inline reading of DenseInfo structure */
 
-            pabyDataNewLimit = pabyData + nSize;
+            GByte* pabyDataNewLimit = pabyData + nSize;
             while(pabyData < pabyDataNewLimit)
             {
-                int nFieldNumber;
                 READ_FIELD_KEY(nKey);
 
-                nFieldNumber = GET_FIELDNUMBER(nKey);
-                if (GET_WIRETYPE(nKey) == WT_DATA &&
-                    nFieldNumber >= DENSEINFO_IDX_VERSION && nFieldNumber <= DENSEINFO_IDX_VISIBLE)
+                const int nFieldNumber = GET_FIELDNUMBER(nKey);
+                if( GET_WIRETYPE(nKey) == WT_DATA &&
+                    nFieldNumber >= DENSEINFO_IDX_VERSION &&
+                    nFieldNumber <= DENSEINFO_IDX_VISIBLE )
                 {
                     if( apabyData[nFieldNumber - 1] != NULL) GOTO_END_ERROR;
                     READ_SIZE(pabyData, pabyDataNewLimit, nSize);
@@ -534,38 +539,37 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
         }
         else if( nKey == MAKE_KEY(DENSENODES_IDX_LAT, WT_DATA) )
         {
-            unsigned int nSize;
-            if (pabyDataLat != NULL)
+            if( pabyDataLat != NULL )
                 GOTO_END_ERROR;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
             pabyDataLat = pabyData;
             pabyData += nSize;
         }
         else if( nKey == MAKE_KEY(DENSENODES_IDX_LON, WT_DATA) )
         {
-            unsigned int nSize;
-            if (pabyDataLon != NULL)
+            if( pabyDataLon != NULL )
                 GOTO_END_ERROR;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
             pabyDataLon = pabyData;
             pabyData += nSize;
         }
         else if( nKey == MAKE_KEY(DENSENODES_IDX_KEYVALS, WT_DATA) )
         {
-            unsigned int nSize;
             if( pabyDataKeyVal != NULL )
                 GOTO_END_ERROR;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
             pabyDataKeyVal = pabyData;
 
-            if (nSize > psCtxt->nTagsAllocated)
+            if( nSize > psCtxt->nTagsAllocated )
             {
-                OSMTag* pasTagsNew;
 
-                psCtxt->nTagsAllocated = MAX(
+                psCtxt->nTagsAllocated = std::max(
                     psCtxt->nTagsAllocated * 2, nSize);
-                pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
+                OSMTag* pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasTags,
                     psCtxt->nTagsAllocated * sizeof(OSMTag));
                 if( pasTagsNew == NULL )
@@ -641,16 +645,16 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
             }
             if( pabyDataUID )
             {
-                int nDeltaUID;
+                int nDeltaUID = 0;
                 READ_VARSINT32(pabyDataUID, pabyDataLimit, nDeltaUID);
                 nUID += nDeltaUID;
             }
             if( pabyDataUserSID )
             {
-                int nDeltaUserSID;
+                int nDeltaUserSID = 0;
                 READ_VARSINT32(pabyDataUserSID, pabyDataLimit, nDeltaUserSID);
                 nUserSID += nDeltaUserSID;
-                if (nUserSID >= nStrCount)
+                if( nUserSID >= nStrCount )
                     GOTO_END_ERROR;
             }
             /* if( pabyDataVisible )
@@ -662,13 +666,13 @@ int ReadDenseNodes(GByte* pabyData, GByte* pabyDataLimit,
                 {
                     unsigned int nKey, nVal;
                     READ_VARUINT32(pabyDataKeyVal, pabyDataLimit, nKey);
-                    if (nKey == 0)
+                    if( nKey == 0 )
                         break;
-                    if (nKey >= nStrCount)
+                    if( nKey >= nStrCount )
                         GOTO_END_ERROR;
 
                     READ_VARUINT32(pabyDataKeyVal, pabyDataLimit, nVal);
-                    if (nVal >= nStrCount)
+                    if( nVal >= nStrCount )
                         GOTO_END_ERROR;
 
                     pasTags[nTags].pszK = pszStrBuf + panStrOff[nKey];
@@ -725,56 +729,56 @@ end_error:
 /*                           ReadOSMInfo()                              */
 /************************************************************************/
 
-#define INFO_IDX_VERSION     1
-#define INFO_IDX_TIMESTAMP   2
-#define INFO_IDX_CHANGESET   3
-#define INFO_IDX_UID         4
-#define INFO_IDX_USER_SID    5
-#define INFO_IDX_VISIBLE     6
+static const int INFO_IDX_VERSION   = 1;
+static const int INFO_IDX_TIMESTAMP = 2;
+static const int INFO_IDX_CHANGESET = 3;
+static const int INFO_IDX_UID       = 4;
+static const int INFO_IDX_USER_SID  = 5;
+static const int INFO_IDX_VISIBLE   = 6;
 
 static
-int ReadOSMInfo(GByte* pabyData, GByte* pabyDataLimit,
-             OSMInfo* psInfo, OSMContext* psContext) CPL_NO_INLINE;
+bool ReadOSMInfo( GByte* pabyData, GByte* pabyDataLimit,
+                  OSMInfo* psInfo, OSMContext* psContext ) CPL_NO_INLINE;
 
 static
-int ReadOSMInfo(GByte* pabyData, GByte* pabyDataLimit,
-             OSMInfo* psInfo, OSMContext* psContext)
+bool ReadOSMInfo( GByte* pabyData, GByte* pabyDataLimit,
+                  OSMInfo* psInfo, OSMContext* psContext )
 {
     /* printf(">ReadOSMInfo\n"); */
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(INFO_IDX_VERSION, WT_VARINT))
+        if( nKey == MAKE_KEY(INFO_IDX_VERSION, WT_VARINT) )
         {
             READ_VARINT32(pabyData, pabyDataLimit, psInfo->nVersion);
         }
-        else if (nKey == MAKE_KEY(INFO_IDX_TIMESTAMP, WT_VARINT))
+        else if( nKey == MAKE_KEY(INFO_IDX_TIMESTAMP, WT_VARINT) )
         {
             READ_VARINT64(pabyData, pabyDataLimit, psInfo->ts.nTimeStamp);
         }
-        else if (nKey == MAKE_KEY(INFO_IDX_CHANGESET, WT_VARINT))
+        else if( nKey == MAKE_KEY(INFO_IDX_CHANGESET, WT_VARINT) )
         {
             READ_VARINT64(pabyData, pabyDataLimit, psInfo->nChangeset);
         }
-        else if (nKey == MAKE_KEY(INFO_IDX_UID, WT_VARINT))
+        else if( nKey == MAKE_KEY(INFO_IDX_UID, WT_VARINT) )
         {
             READ_VARINT32(pabyData, pabyDataLimit, psInfo->nUID);
         }
-        else if (nKey == MAKE_KEY(INFO_IDX_USER_SID, WT_VARINT))
+        else if( nKey == MAKE_KEY(INFO_IDX_USER_SID, WT_VARINT) )
         {
-            unsigned int nUserSID;
+            unsigned int nUserSID = 0;
             READ_VARUINT32(pabyData, pabyDataLimit, nUserSID);
             if( nUserSID < psContext->nStrCount)
                 psInfo->pszUserSID = psContext->pszStrBuf +
                                      psContext->panStrOff[nUserSID];
         }
-        else if (nKey == MAKE_KEY(INFO_IDX_VISIBLE, WT_VARINT))
+        else if( nKey == MAKE_KEY(INFO_IDX_VISIBLE, WT_VARINT) )
         {
             SKIP_VARINT(pabyData, pabyDataLimit);
-            //int nVisible;
-            //READ_VARINT32(pabyData, pabyDataLimit, /*psInfo->*/nVisible);
+            // int nVisible = 0;
+            // READ_VARINT32(pabyData, pabyDataLimit, /*psInfo->*/nVisible);
         }
         else
         {
@@ -788,7 +792,7 @@ int ReadOSMInfo(GByte* pabyData, GByte* pabyDataLimit,
 end_error:
     /* printf("<ReadOSMInfo\n"); */
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -799,63 +803,65 @@ end_error:
 /* The one advertized in http://wiki.openstreetmap.org/wiki/PBF_Format and */
 /* used previously seem wrong/old-dated */
 
-#define NODE_IDX_ID      1
-#define NODE_IDX_LAT     8
-#define NODE_IDX_LON     9
-#define NODE_IDX_KEYS    2
-#define NODE_IDX_VALS    3
-#define NODE_IDX_INFO    4
+static const int NODE_IDX_ID   = 1;
+static const int NODE_IDX_LAT  = 8;
+static const int NODE_IDX_LON  = 9;
+static const int NODE_IDX_KEYS = 2;
+static const int NODE_IDX_VALS = 3;
+static const int NODE_IDX_INFO = 4;
 
 static
-int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
-             OSMContext* psCtxt)
+bool ReadNode( GByte* pabyData, GByte* pabyDataLimit,
+               OSMContext* psCtxt )
 {
     OSMNode sNode;
 
     sNode.nID = 0;
     sNode.dfLat = 0.0;
     sNode.dfLon = 0.0;
-    INIT_INFO(sNode.sInfo);
+    INIT_INFO(&(sNode.sInfo));
     sNode.nTags = 0;
     sNode.pasTags = NULL;
 
     /* printf(">ReadNode\n"); */
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(NODE_IDX_ID, WT_VARINT))
+        if( nKey == MAKE_KEY(NODE_IDX_ID, WT_VARINT) )
         {
             READ_VARSINT64_NOCHECK(pabyData, pabyDataLimit, sNode.nID);
         }
-        else if (nKey == MAKE_KEY(NODE_IDX_LAT, WT_VARINT))
+        else if( nKey == MAKE_KEY(NODE_IDX_LAT, WT_VARINT) )
         {
-            GIntBig nLat;
+            GIntBig nLat = 0;
             READ_VARSINT64_NOCHECK(pabyData, pabyDataLimit, nLat);
-            sNode.dfLat = .000000001 * (psCtxt->nLatOffset + ((double)psCtxt->nGranularity * nLat));
+            sNode.dfLat =
+                0.000000001 * (psCtxt->nLatOffset +
+                               ((double)psCtxt->nGranularity * nLat));
         }
-        else if (nKey == MAKE_KEY(NODE_IDX_LON, WT_VARINT))
+        else if( nKey == MAKE_KEY(NODE_IDX_LON, WT_VARINT) )
         {
-            GIntBig nLon;
+            GIntBig nLon = 0;
             READ_VARSINT64_NOCHECK(pabyData, pabyDataLimit, nLon);
-            sNode.dfLon = .000000001 * (psCtxt->nLonOffset + ((double)psCtxt->nGranularity * nLon));
+            sNode.dfLon =
+                0.000000001 * (psCtxt->nLonOffset +
+                               ((double)psCtxt->nGranularity * nLon));
         }
-        else if (nKey == MAKE_KEY(NODE_IDX_KEYS, WT_DATA))
+        else if( nKey == MAKE_KEY(NODE_IDX_KEYS, WT_DATA) )
         {
-            unsigned int nSize;
-            GByte* pabyDataNewLimit;
-            if (sNode.nTags != 0)
+            unsigned int nSize = 0;
+            GByte* pabyDataNewLimit = NULL;
+            if( sNode.nTags != 0 )
                 GOTO_END_ERROR;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (nSize > psCtxt->nTagsAllocated)
+            if( nSize > psCtxt->nTagsAllocated )
             {
-                OSMTag* pasTagsNew;
-
-                psCtxt->nTagsAllocated = MAX(
+                psCtxt->nTagsAllocated = std::max(
                     psCtxt->nTagsAllocated * 2, nSize);
-                pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
+                OSMTag* pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasTags,
                     psCtxt->nTagsAllocated * sizeof(OSMTag));
                 if( pasTagsNew == NULL )
@@ -866,10 +872,10 @@ int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
             pabyDataNewLimit = pabyData + nSize;
             while (pabyData < pabyDataNewLimit)
             {
-                unsigned int nKey2;
+                unsigned int nKey2 = 0;
                 READ_VARUINT32(pabyData, pabyDataNewLimit, nKey2);
 
-                if (nKey2 >= psCtxt->nStrCount)
+                if( nKey2 >= psCtxt->nStrCount )
                     GOTO_END_ERROR;
 
                 psCtxt->pasTags[sNode.nTags].pszK = psCtxt->pszStrBuf +
@@ -877,36 +883,37 @@ int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
                 psCtxt->pasTags[sNode.nTags].pszV = "";
                 sNode.nTags ++;
             }
-            if (pabyData != pabyDataNewLimit)
+            if( pabyData != pabyDataNewLimit )
                 GOTO_END_ERROR;
         }
-        else if (nKey == MAKE_KEY(NODE_IDX_VALS, WT_DATA))
+        else if( nKey == MAKE_KEY(NODE_IDX_VALS, WT_DATA) )
         {
-            //unsigned int nSize;
             unsigned int nIter = 0;
-            if (sNode.nTags == 0)
+            if( sNode.nTags == 0 )
                 GOTO_END_ERROR;
-            //READ_VARUINT32(pabyData, pabyDataLimit, nSize);
+            // unsigned int nSize = 0;
+            // READ_VARUINT32(pabyData, pabyDataLimit, nSize);
             SKIP_VARINT(pabyData, pabyDataLimit);
 
-            for(; nIter < sNode.nTags; nIter ++)
+            for( ; nIter < sNode.nTags; nIter++)
             {
-                unsigned int nVal;
+                unsigned int nVal = 0;
                 READ_VARUINT32(pabyData, pabyDataLimit, nVal);
 
-                if (nVal >= psCtxt->nStrCount)
+                if( nVal >= psCtxt->nStrCount )
                     GOTO_END_ERROR;
 
                 psCtxt->pasTags[nIter].pszV = psCtxt->pszStrBuf +
                                               psCtxt->panStrOff[nVal];
             }
         }
-        else if (nKey == MAKE_KEY(NODE_IDX_INFO, WT_DATA))
+        else if( nKey == MAKE_KEY(NODE_IDX_INFO, WT_DATA) )
         {
-            unsigned int nSize;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (!ReadOSMInfo(pabyData, pabyDataLimit + nSize, &sNode.sInfo, psCtxt))
+            if( !ReadOSMInfo(pabyData, pabyDataLimit + nSize,
+                             &sNode.sInfo, psCtxt) )
                 GOTO_END_ERROR;
 
             pabyData += nSize;
@@ -924,68 +931,65 @@ int ReadNode(GByte* pabyData, GByte* pabyDataLimit,
     if( pabyData != pabyDataLimit )
         GOTO_END_ERROR;
 
-    if (sNode.nTags)
+    if( sNode.nTags )
         sNode.pasTags = psCtxt->pasTags;
     else
         sNode.pasTags = NULL;
     psCtxt->pfnNotifyNodes(1, &sNode, psCtxt, psCtxt->user_data);
 
-    /* printf("<ReadNode\n"); */
+    // printf("<ReadNode\n");
 
-    return TRUE;
+    return true;
 
 end_error:
     /* printf("<ReadNode\n"); */
 
-    return FALSE;
+    return false;
 }
 
-
 /************************************************************************/
 /*                              ReadWay()                               */
 /************************************************************************/
 
-#define WAY_IDX_ID      1
-#define WAY_IDX_KEYS    2
-#define WAY_IDX_VALS    3
-#define WAY_IDX_INFO    4
-#define WAY_IDX_REFS    8
+static const int WAY_IDX_ID   = 1;
+static const int WAY_IDX_KEYS = 2;
+static const int WAY_IDX_VALS = 3;
+static const int WAY_IDX_INFO = 4;
+static const int WAY_IDX_REFS = 8;
 
 static
-int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
-            OSMContext* psCtxt)
+bool ReadWay( GByte* pabyData, GByte* pabyDataLimit,
+              OSMContext* psCtxt )
 {
     OSMWay sWay;
     sWay.nID = 0;
-    INIT_INFO(sWay.sInfo);
+    INIT_INFO(&(sWay.sInfo));
     sWay.nTags = 0;
     sWay.nRefs = 0;
 
-    /* printf(">ReadWay\n"); */
+    // printf(">ReadWay\n");
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(WAY_IDX_ID, WT_VARINT))
+        if( nKey == MAKE_KEY(WAY_IDX_ID, WT_VARINT) )
         {
             READ_VARINT64(pabyData, pabyDataLimit, sWay.nID);
         }
-        else if (nKey == MAKE_KEY(WAY_IDX_KEYS, WT_DATA))
+        else if( nKey == MAKE_KEY(WAY_IDX_KEYS, WT_DATA) )
         {
-            unsigned int nSize;
-            GByte* pabyDataNewLimit;
-            if (sWay.nTags != 0)
+            unsigned int nSize = 0;
+            GByte* pabyDataNewLimit = NULL;
+            if( sWay.nTags != 0 )
                 GOTO_END_ERROR;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (nSize > psCtxt->nTagsAllocated)
+            if( nSize > psCtxt->nTagsAllocated )
             {
-                OSMTag* pasTagsNew;
-
-                psCtxt->nTagsAllocated = MAX(
+                psCtxt->nTagsAllocated = std::max(
                     psCtxt->nTagsAllocated * 2, nSize);
-                pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
+                OSMTag* pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasTags,
                     psCtxt->nTagsAllocated * sizeof(OSMTag));
                 if( pasTagsNew == NULL )
@@ -996,10 +1000,10 @@ int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
             pabyDataNewLimit = pabyData + nSize;
             while (pabyData < pabyDataNewLimit)
             {
-                unsigned int nKey2;
+                unsigned int nKey2 = 0;
                 READ_VARUINT32(pabyData, pabyDataNewLimit, nKey2);
 
-                if (nKey2 >= psCtxt->nStrCount)
+                if( nKey2 >= psCtxt->nStrCount )
                     GOTO_END_ERROR;
 
                 psCtxt->pasTags[sWay.nTags].pszK = psCtxt->pszStrBuf +
@@ -1007,55 +1011,54 @@ int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
                 psCtxt->pasTags[sWay.nTags].pszV = "";
                 sWay.nTags ++;
             }
-            if (pabyData != pabyDataNewLimit)
+            if( pabyData != pabyDataNewLimit )
                 GOTO_END_ERROR;
         }
-        else if (nKey == MAKE_KEY(WAY_IDX_VALS, WT_DATA))
+        else if( nKey == MAKE_KEY(WAY_IDX_VALS, WT_DATA) )
         {
-            //unsigned int nSize;
             unsigned int nIter = 0;
-            if (sWay.nTags == 0)
+            if( sWay.nTags == 0 )
                 GOTO_END_ERROR;
-            //READ_VARUINT32(pabyData, pabyDataLimit, nSize);
+            // unsigned int nSize = 0;
+            // READ_VARUINT32(pabyData, pabyDataLimit, nSize);
             SKIP_VARINT(pabyData, pabyDataLimit);
 
             for(; nIter < sWay.nTags; nIter ++)
             {
-                unsigned int nVal;
+                unsigned int nVal = 0;
                 READ_VARUINT32(pabyData, pabyDataLimit, nVal);
 
-                if (nVal >= psCtxt->nStrCount)
+                if( nVal >= psCtxt->nStrCount )
                     GOTO_END_ERROR;
 
                 psCtxt->pasTags[nIter].pszV = psCtxt->pszStrBuf +
                                               psCtxt->panStrOff[nVal];
             }
         }
-        else if (nKey == MAKE_KEY(WAY_IDX_INFO, WT_DATA))
+        else if( nKey == MAKE_KEY(WAY_IDX_INFO, WT_DATA) )
         {
-            unsigned int nSize;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (!ReadOSMInfo(pabyData, pabyData + nSize, &sWay.sInfo, psCtxt))
+            if( !ReadOSMInfo(pabyData, pabyData + nSize, &sWay.sInfo, psCtxt) )
                 GOTO_END_ERROR;
 
             pabyData += nSize;
         }
-        else if (nKey == MAKE_KEY(WAY_IDX_REFS, WT_DATA))
+        else if( nKey == MAKE_KEY(WAY_IDX_REFS, WT_DATA) )
         {
             GIntBig nRefVal = 0;
-            unsigned int nSize;
-            GByte* pabyDataNewLimit;
-            if (sWay.nRefs != 0)
+            unsigned int nSize = 0;
+            GByte* pabyDataNewLimit = NULL;
+            if( sWay.nRefs != 0 )
                 GOTO_END_ERROR;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (nSize > psCtxt->nNodeRefsAllocated)
+            if( nSize > psCtxt->nNodeRefsAllocated )
             {
-                GIntBig* panNodeRefsNew;
                 psCtxt->nNodeRefsAllocated =
-                    MAX(psCtxt->nNodeRefsAllocated * 2, nSize);
-                panNodeRefsNew = (GIntBig*) VSI_REALLOC_VERBOSE(
+                    std::max(psCtxt->nNodeRefsAllocated * 2, nSize);
+                GIntBig* panNodeRefsNew = (GIntBig*) VSI_REALLOC_VERBOSE(
                         psCtxt->panNodeRefs,
                         psCtxt->nNodeRefsAllocated * sizeof(GIntBig));
                 if( panNodeRefsNew == NULL )
@@ -1066,14 +1069,14 @@ int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
             pabyDataNewLimit = pabyData + nSize;
             while (pabyData < pabyDataNewLimit)
             {
-                GIntBig nDeltaRef;
+                GIntBig nDeltaRef = 0;
                 READ_VARSINT64_NOCHECK(pabyData, pabyDataNewLimit, nDeltaRef);
                 nRefVal += nDeltaRef;
 
                 psCtxt->panNodeRefs[sWay.nRefs ++] = nRefVal;
             }
 
-            if (pabyData != pabyDataNewLimit)
+            if( pabyData != pabyDataNewLimit )
                 GOTO_END_ERROR;
         }
         else
@@ -1085,9 +1088,9 @@ int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
     if( pabyData != pabyDataLimit )
         GOTO_END_ERROR;
 
-    /* printf("<ReadWay\n"); */
+    // printf("<ReadWay\n");
 
-    if (sWay.nTags)
+    if( sWay.nTags )
         sWay.pasTags = psCtxt->pasTags;
     else
         sWay.pasTags = NULL;
@@ -1095,61 +1098,59 @@ int ReadWay(GByte* pabyData, GByte* pabyDataLimit,
 
     psCtxt->pfnNotifyWay(&sWay, psCtxt, psCtxt->user_data);
 
-    return TRUE;
+    return true;
 
 end_error:
-    /* printf("<ReadWay\n"); */
+    // printf("<ReadWay\n");
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                            ReadRelation()                            */
 /************************************************************************/
 
-#define RELATION_IDX_ID           1
-#define RELATION_IDX_KEYS         2
-#define RELATION_IDX_VALS         3
-#define RELATION_IDX_INFO         4
-#define RELATION_IDX_ROLES_SID    8
-#define RELATION_IDX_MEMIDS       9
-#define RELATION_IDX_TYPES        10
+static const int RELATION_IDX_ID        = 1;
+static const int RELATION_IDX_KEYS      = 2;
+static const int RELATION_IDX_VALS      = 3;
+static const int RELATION_IDX_INFO      = 4;
+static const int RELATION_IDX_ROLES_SID = 8;
+static const int RELATION_IDX_MEMIDS    = 9;
+static const int RELATION_IDX_TYPES     = 10;
 
 static
-int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
-                 OSMContext* psCtxt)
+bool ReadRelation( GByte* pabyData, GByte* pabyDataLimit,
+                   OSMContext* psCtxt )
 {
     OSMRelation sRelation;
     sRelation.nID = 0;
-    INIT_INFO(sRelation.sInfo);
+    INIT_INFO(&(sRelation.sInfo));
     sRelation.nTags = 0;
     sRelation.nMembers = 0;
 
     /* printf(">ReadRelation\n"); */
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(RELATION_IDX_ID, WT_VARINT))
+        if( nKey == MAKE_KEY(RELATION_IDX_ID, WT_VARINT) )
         {
             READ_VARINT64(pabyData, pabyDataLimit, sRelation.nID);
         }
-        else if (nKey == MAKE_KEY(RELATION_IDX_KEYS, WT_DATA))
+        else if( nKey == MAKE_KEY(RELATION_IDX_KEYS, WT_DATA) )
         {
-            unsigned int nSize;
-            GByte* pabyDataNewLimit;
-            if (sRelation.nTags != 0)
+            unsigned int nSize = 0;
+            GByte* pabyDataNewLimit = NULL;
+            if( sRelation.nTags != 0 )
                 GOTO_END_ERROR;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (nSize > psCtxt->nTagsAllocated)
+            if( nSize > psCtxt->nTagsAllocated )
             {
-                OSMTag* pasTagsNew;
-
-                psCtxt->nTagsAllocated = MAX(
+                psCtxt->nTagsAllocated = std::max(
                     psCtxt->nTagsAllocated * 2, nSize);
-                pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
+                OSMTag* pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasTags,
                     psCtxt->nTagsAllocated * sizeof(OSMTag));
                 if( pasTagsNew == NULL )
@@ -1160,65 +1161,65 @@ int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
             pabyDataNewLimit = pabyData + nSize;
             while (pabyData < pabyDataNewLimit)
             {
-                unsigned int nKey2;
+                unsigned int nKey2 = 0;
                 READ_VARUINT32(pabyData, pabyDataNewLimit, nKey2);
 
-                if (nKey2 >= psCtxt->nStrCount)
+                if( nKey2 >= psCtxt->nStrCount )
                     GOTO_END_ERROR;
 
-                psCtxt->pasTags[sRelation.nTags].pszK = psCtxt->pszStrBuf +
-                                                        psCtxt->panStrOff[nKey2];
+                psCtxt->pasTags[sRelation.nTags].pszK =
+                    psCtxt->pszStrBuf + psCtxt->panStrOff[nKey2];
                 psCtxt->pasTags[sRelation.nTags].pszV = "";
                 sRelation.nTags ++;
             }
-            if (pabyData != pabyDataNewLimit)
+            if( pabyData != pabyDataNewLimit )
                 GOTO_END_ERROR;
         }
-        else if (nKey == MAKE_KEY(RELATION_IDX_VALS, WT_DATA))
+        else if( nKey == MAKE_KEY(RELATION_IDX_VALS, WT_DATA) )
         {
-            //unsigned int nSize;
             unsigned int nIter = 0;
-            if (sRelation.nTags == 0)
+            if( sRelation.nTags == 0 )
                 GOTO_END_ERROR;
-            //READ_VARUINT32(pabyData, pabyDataLimit, nSize);
+            // unsigned int nSize = 0;
+            // READ_VARUINT32(pabyData, pabyDataLimit, nSize);
             SKIP_VARINT(pabyData, pabyDataLimit);
 
             for(; nIter < sRelation.nTags; nIter ++)
             {
-                unsigned int nVal;
+                unsigned int nVal = 0;
                 READ_VARUINT32(pabyData, pabyDataLimit, nVal);
 
-                if (nVal >= psCtxt->nStrCount)
+                if( nVal >= psCtxt->nStrCount )
                     GOTO_END_ERROR;
 
                 psCtxt->pasTags[nIter].pszV = psCtxt->pszStrBuf +
                                               psCtxt->panStrOff[nVal];
             }
         }
-        else if (nKey == MAKE_KEY(RELATION_IDX_INFO, WT_DATA))
+        else if( nKey == MAKE_KEY(RELATION_IDX_INFO, WT_DATA) )
         {
-            unsigned int nSize;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (!ReadOSMInfo(pabyData, pabyData + nSize, &sRelation.sInfo, psCtxt))
+            if( !ReadOSMInfo(pabyData, pabyData + nSize,
+                             &sRelation.sInfo, psCtxt) )
                 GOTO_END_ERROR;
 
             pabyData += nSize;
         }
-        else if (nKey == MAKE_KEY(RELATION_IDX_ROLES_SID, WT_DATA))
+        else if( nKey == MAKE_KEY(RELATION_IDX_ROLES_SID, WT_DATA) )
         {
-            unsigned int nSize;
-            GByte* pabyDataNewLimit;
-            if (sRelation.nMembers != 0)
+            unsigned int nSize = 0;
+            GByte* pabyDataNewLimit = NULL;
+            if( sRelation.nMembers != 0 )
                 GOTO_END_ERROR;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (nSize > psCtxt->nMembersAllocated)
+            if( nSize > psCtxt->nMembersAllocated )
             {
-                OSMMember* pasMembersNew;
                 psCtxt->nMembersAllocated =
-                    MAX(psCtxt->nMembersAllocated * 2, nSize);
-                pasMembersNew = (OSMMember*) VSI_REALLOC_VERBOSE(
+                    std::max(psCtxt->nMembersAllocated * 2, nSize);
+                OSMMember* pasMembersNew = (OSMMember*) VSI_REALLOC_VERBOSE(
                         psCtxt->pasMembers,
                         psCtxt->nMembersAllocated * sizeof(OSMMember));
                 if( pasMembersNew == NULL )
@@ -1229,9 +1230,9 @@ int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
             pabyDataNewLimit = pabyData + nSize;
             while (pabyData < pabyDataNewLimit)
             {
-                unsigned int nRoleSID;
+                unsigned int nRoleSID = 0;
                 READ_VARUINT32(pabyData, pabyDataNewLimit, nRoleSID);
-                if (nRoleSID >= psCtxt->nStrCount)
+                if( nRoleSID >= psCtxt->nStrCount )
                     GOTO_END_ERROR;
 
                 psCtxt->pasMembers[sRelation.nMembers].pszRole =
@@ -1241,42 +1242,42 @@ int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
                 sRelation.nMembers ++;
             }
 
-            if (pabyData != pabyDataNewLimit)
+            if( pabyData != pabyDataNewLimit )
                 GOTO_END_ERROR;
         }
-        else if (nKey == MAKE_KEY(RELATION_IDX_MEMIDS, WT_DATA))
+        else if( nKey == MAKE_KEY(RELATION_IDX_MEMIDS, WT_DATA) )
         {
             unsigned int nIter = 0;
             GIntBig nMemID = 0;
-            //unsigned int nSize;
-            if (sRelation.nMembers == 0)
+            if( sRelation.nMembers == 0 )
                 GOTO_END_ERROR;
-            //READ_VARUINT32(pabyData, pabyDataLimit, nSize);
+            // unsigned int nSize = 0;
+            // READ_VARUINT32(pabyData, pabyDataLimit, nSize);
             SKIP_VARINT(pabyData, pabyDataLimit);
 
             for(; nIter < sRelation.nMembers; nIter++)
             {
-                GIntBig nDeltaMemID;
+                GIntBig nDeltaMemID = 0;
                 READ_VARSINT64(pabyData, pabyDataLimit, nDeltaMemID);
                 nMemID += nDeltaMemID;
 
                 psCtxt->pasMembers[nIter].nID = nMemID;
             }
         }
-        else if (nKey == MAKE_KEY(RELATION_IDX_TYPES, WT_DATA))
+        else if( nKey == MAKE_KEY(RELATION_IDX_TYPES, WT_DATA) )
         {
             unsigned int nIter = 0;
-            unsigned int nSize;
-            if (sRelation.nMembers == 0)
+            if( sRelation.nMembers == 0 )
                 GOTO_END_ERROR;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
-            if (nSize != sRelation.nMembers)
+            if( nSize != sRelation.nMembers )
                 GOTO_END_ERROR;
 
             for(; nIter < sRelation.nMembers; nIter++)
             {
                 unsigned int nType = pabyData[nIter];
-                if (nType > MEMBER_RELATION)
+                if( nType > MEMBER_RELATION )
                     GOTO_END_ERROR;
 
                 psCtxt->pasMembers[nIter].eType = (OSMMemberType) nType;
@@ -1293,7 +1294,7 @@ int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
     if( pabyData != pabyDataLimit )
         GOTO_END_ERROR;
 
-    if (sRelation.nTags)
+    if( sRelation.nTags )
         sRelation.pasTags = psCtxt->pasTags;
     else
         sRelation.pasTags = NULL;
@@ -1302,26 +1303,26 @@ int ReadRelation(GByte* pabyData, GByte* pabyDataLimit,
 
     psCtxt->pfnNotifyRelation(&sRelation, psCtxt, psCtxt->user_data);
 
-    return TRUE;
+    return true;
 
 end_error:
     /* printf("<ReadRelation\n"); */
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                          ReadPrimitiveGroup()                        */
 /************************************************************************/
 
-#define PRIMITIVEGROUP_IDX_NODES      1
-#define PRIMITIVEGROUP_IDX_DENSE      2
-#define PRIMITIVEGROUP_IDX_WAYS       3
-#define PRIMITIVEGROUP_IDX_RELATIONS  4
-#define PRIMITIVEGROUP_IDX_CHANGESETS 5
+static const int PRIMITIVEGROUP_IDX_NODES = 1;
+// static const int PRIMITIVEGROUP_IDX_DENSE = 2;
+// static const int PRIMITIVEGROUP_IDX_WAYS = 3;
+static const int PRIMITIVEGROUP_IDX_RELATIONS = 4;
+// static const int PRIMITIVEGROUP_IDX_CHANGESETS = 5;
 
-typedef int (*PrimitiveFuncType)(GByte* pabyData, GByte* pabyDataLimit,
-                                 OSMContext* psCtxt);
+typedef bool (*PrimitiveFuncType)( GByte* pabyData, GByte* pabyDataLimit,
+                                   OSMContext* psCtxt );
 
 static const PrimitiveFuncType apfnPrimitives[] =
 {
@@ -1332,25 +1333,25 @@ static const PrimitiveFuncType apfnPrimitives[] =
 };
 
 static
-int ReadPrimitiveGroup(GByte* pabyData, GByte* pabyDataLimit,
-                       OSMContext* psCtxt)
+bool ReadPrimitiveGroup( GByte* pabyData, GByte* pabyDataLimit,
+                         OSMContext* psCtxt )
 {
     /* printf(">ReadPrimitiveGroup\n"); */
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
-        int nFieldNumber;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        nFieldNumber = GET_FIELDNUMBER(nKey) - 1;
+        const int nFieldNumber = GET_FIELDNUMBER(nKey) - 1;
         if( GET_WIRETYPE(nKey) == WT_DATA &&
             nFieldNumber >= PRIMITIVEGROUP_IDX_NODES - 1 &&
             nFieldNumber <= PRIMITIVEGROUP_IDX_RELATIONS - 1 )
         {
-            unsigned int nSize;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (!apfnPrimitives[nFieldNumber](pabyData, pabyData + nSize, psCtxt))
+            if( !apfnPrimitives[nFieldNumber](pabyData, pabyData + nSize,
+                                              psCtxt) )
                 GOTO_END_ERROR;
 
             pabyData += nSize;
@@ -1374,16 +1375,16 @@ end_error:
 /*                          ReadPrimitiveBlock()                        */
 /************************************************************************/
 
-#define PRIMITIVEBLOCK_IDX_STRINGTABLE      1
-#define PRIMITIVEBLOCK_IDX_PRIMITIVEGROUP   2
-#define PRIMITIVEBLOCK_IDX_GRANULARITY      17
-#define PRIMITIVEBLOCK_IDX_DATE_GRANULARITY 18
-#define PRIMITIVEBLOCK_IDX_LAT_OFFSET       19
-#define PRIMITIVEBLOCK_IDX_LON_OFFSET       20
+static const int PRIMITIVEBLOCK_IDX_STRINGTABLE      = 1;
+static const int PRIMITIVEBLOCK_IDX_PRIMITIVEGROUP   = 2;
+static const int PRIMITIVEBLOCK_IDX_GRANULARITY      = 17;
+static const int PRIMITIVEBLOCK_IDX_DATE_GRANULARITY = 18;
+static const int PRIMITIVEBLOCK_IDX_LAT_OFFSET       = 19;
+static const int PRIMITIVEBLOCK_IDX_LON_OFFSET       = 20;
 
 static
-int ReadPrimitiveBlock(GByte* pabyData, GByte* pabyDataLimit,
-                       OSMContext* psCtxt)
+bool ReadPrimitiveBlock( GByte* pabyData, GByte* pabyDataLimit,
+                         OSMContext* psCtxt )
 {
     GByte* pabyDataSave = pabyData;
 
@@ -1396,24 +1397,25 @@ int ReadPrimitiveBlock(GByte* pabyData, GByte* pabyDataLimit,
 
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_GRANULARITY, WT_VARINT))
+        if( nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_GRANULARITY, WT_VARINT) )
         {
             READ_VARINT32(pabyData, pabyDataLimit, psCtxt->nGranularity);
             if( psCtxt->nGranularity <= 0 )
                 GOTO_END_ERROR;
         }
-        else if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_DATE_GRANULARITY, WT_VARINT))
+        else if( nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_DATE_GRANULARITY,
+                                  WT_VARINT) )
         {
             READ_VARINT32(pabyData, pabyDataLimit, psCtxt->nDateGranularity);
         }
-        else if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_LAT_OFFSET, WT_VARINT))
+        else if( nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_LAT_OFFSET, WT_VARINT) )
         {
             READ_VARINT64(pabyData, pabyDataLimit, psCtxt->nLatOffset);
         }
-        else if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_LON_OFFSET, WT_VARINT))
+        else if( nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_LON_OFFSET, WT_VARINT) )
         {
             READ_VARINT64(pabyData, pabyDataLimit, psCtxt->nLonOffset);
         }
@@ -1423,61 +1425,59 @@ int ReadPrimitiveBlock(GByte* pabyData, GByte* pabyDataLimit,
         }
     }
 
-    if (pabyData != pabyDataLimit)
+    if( pabyData != pabyDataLimit )
         GOTO_END_ERROR;
 
     pabyData = pabyDataSave;
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_STRINGTABLE, WT_DATA))
+        if( nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_STRINGTABLE, WT_DATA) )
         {
-            GByte bSaveAfterByte;
-            GByte* pbSaveAfterByte;
-            unsigned int nSize;
-            if (psCtxt->nStrCount != 0)
+            GByte bSaveAfterByte = 0;
+            GByte* pbSaveAfterByte = NULL;
+            if( psCtxt->nStrCount != 0 )
                 GOTO_END_ERROR;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            /* Dirty little trick */
-            /* ReadStringTable() will over-write the byte after the */
-            /* StringTable message with a NUL character, so we backup */
-            /* it to be able to restore it just before issuing the next */
-            /* READ_FIELD_KEY. Then we will re-NUL it to have valid */
-            /* NUL terminated strings */
-            /* This trick enable us to keep the strings where there are */
-            /* in RAM */
+            // Dirty little trick:
+            // ReadStringTable() will over-write the byte after the
+            // StringTable message with a NUL character, so we backup
+            // it to be able to restore it just before issuing the next
+            // READ_FIELD_KEY. Then we will re-NUL it to have valid
+            // NUL terminated strings.
+            // This trick enable us to keep the strings where there are
+            // in RAM.
             pbSaveAfterByte = pabyData + nSize;
             bSaveAfterByte = *pbSaveAfterByte;
 
-            if (!ReadStringTable(pabyData, pabyData + nSize,
-                                 psCtxt))
+            if( !ReadStringTable(pabyData, pabyData + nSize, psCtxt) )
                 GOTO_END_ERROR;
 
             pabyData += nSize;
 
             *pbSaveAfterByte = bSaveAfterByte;
-            if (pabyData == pabyDataLimit)
+            if( pabyData == pabyDataLimit )
                 break;
 
             READ_FIELD_KEY(nKey);
             *pbSaveAfterByte = 0;
 
-            if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_STRINGTABLE, WT_DATA))
+            if( nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_STRINGTABLE, WT_DATA) )
                 GOTO_END_ERROR;
 
             /* Yes we go on ! */
         }
 
-        if (nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_PRIMITIVEGROUP, WT_DATA))
+        if( nKey == MAKE_KEY(PRIMITIVEBLOCK_IDX_PRIMITIVEGROUP, WT_DATA) )
         {
-            unsigned int nSize;
+            unsigned int nSize = 0;
             READ_SIZE(pabyData, pabyDataLimit, nSize);
 
-            if (!ReadPrimitiveGroup(pabyData, pabyData + nSize,
-                                    psCtxt))
+            if( !ReadPrimitiveGroup(pabyData, pabyData + nSize, psCtxt))
                 GOTO_END_ERROR;
 
             pabyData += nSize;
@@ -1492,43 +1492,43 @@ int ReadPrimitiveBlock(GByte* pabyData, GByte* pabyDataLimit,
 
 end_error:
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                              ReadBlob()                              */
 /************************************************************************/
 
-#define BLOB_IDX_RAW         1
-#define BLOB_IDX_RAW_SIZE    2
-#define BLOB_IDX_ZLIB_DATA   3
+static const int BLOB_IDX_RAW       = 1;
+static const int BLOB_IDX_RAW_SIZE  = 2;
+static const int BLOB_IDX_ZLIB_DATA = 3;
 
 static
-int ReadBlob(GByte* pabyData, unsigned int nDataSize, BlobType eType,
-             OSMContext* psCtxt)
+bool ReadBlob( GByte* pabyData, unsigned int nDataSize, BlobType eType,
+               OSMContext* psCtxt )
 {
     unsigned int nUncompressedSize = 0;
-    int bRet = TRUE;
+    bool bRet = true;
     GByte* pabyDataLimit = pabyData + nDataSize;
 
     while(pabyData < pabyDataLimit)
     {
-        int nKey;
+        int nKey = 0;
         READ_FIELD_KEY(nKey);
 
-        if (nKey == MAKE_KEY(BLOB_IDX_RAW, WT_DATA))
+        if( nKey == MAKE_KEY(BLOB_IDX_RAW, WT_DATA) )
         {
-            unsigned int nDataLength;
+            unsigned int nDataLength = 0;
             READ_SIZE(pabyData, pabyDataLimit, nDataLength);
-            if (nDataLength > 64 * 1024 * 1024) GOTO_END_ERROR;
+            if( nDataLength > 64 * 1024 * 1024 ) GOTO_END_ERROR;
 
-            /* printf("raw data size = %d\n", nDataLength); */
+            // printf("raw data size = %d\n", nDataLength);
 
-            if (eType == BLOB_OSMHEADER)
+            if( eType == BLOB_OSMHEADER )
             {
                 bRet = ReadOSMHeader(pabyData, pabyData + nDataLength, psCtxt);
             }
-            else if (eType == BLOB_OSMDATA)
+            else if( eType == BLOB_OSMDATA )
             {
                 bRet = ReadPrimitiveBlock(pabyData, pabyData + nDataLength,
                                           psCtxt);
@@ -1536,29 +1536,27 @@ int ReadBlob(GByte* pabyData, unsigned int nDataSize, BlobType eType,
 
             pabyData += nDataLength;
         }
-        else if (nKey == MAKE_KEY(BLOB_IDX_RAW_SIZE, WT_VARINT))
+        else if( nKey == MAKE_KEY(BLOB_IDX_RAW_SIZE, WT_VARINT) )
         {
             READ_VARUINT32(pabyData, pabyDataLimit, nUncompressedSize);
-            /* printf("nUncompressedSize = %d\n", nUncompressedSize); */
+            // printf("nUncompressedSize = %d\n", nUncompressedSize);
         }
-        else if (nKey == MAKE_KEY(BLOB_IDX_ZLIB_DATA, WT_DATA))
+        else if( nKey == MAKE_KEY(BLOB_IDX_ZLIB_DATA, WT_DATA) )
         {
-            unsigned int nZlibCompressedSize;
+            unsigned int nZlibCompressedSize = 0;
             READ_VARUINT32(pabyData, pabyDataLimit, nZlibCompressedSize);
-            if (CHECK_OOB && nZlibCompressedSize > nDataSize) GOTO_END_ERROR;
+            if( CHECK_OOB && nZlibCompressedSize > nDataSize ) GOTO_END_ERROR;
 
-            /* printf("nZlibCompressedSize = %d\n", nZlibCompressedSize); */
+            // printf("nZlibCompressedSize = %d\n", nZlibCompressedSize);
 
-            if (nUncompressedSize != 0)
+            if( nUncompressedSize != 0 )
             {
-                void* pOut;
-
-                if (nUncompressedSize > psCtxt->nUncompressedAllocated)
+                if( nUncompressedSize > psCtxt->nUncompressedAllocated )
                 {
-                    GByte* pabyUncompressedNew;
+                    GByte* pabyUncompressedNew = NULL;
                     if( psCtxt->nUncompressedAllocated <= INT_MAX )
                         psCtxt->nUncompressedAllocated =
-                            MAX(psCtxt->nUncompressedAllocated * 2, nUncompressedSize);
+                            std::max(psCtxt->nUncompressedAllocated * 2, nUncompressedSize);
                     else
                         psCtxt->nUncompressedAllocated = nUncompressedSize;
                     if( psCtxt->nUncompressedAllocated > 0xFFFFFFFFU - EXTRA_BYTES )
@@ -1573,19 +1571,20 @@ int ReadBlob(GByte* pabyData, unsigned int nDataSize, BlobType eType,
 
                 /* printf("inflate %d -> %d\n", nZlibCompressedSize, nUncompressedSize); */
 
-                pOut = CPLZLibInflate( pabyData, nZlibCompressedSize,
-                                       psCtxt->pabyUncompressed, nUncompressedSize,
-                                       NULL );
+                void* pOut =
+                    CPLZLibInflate( pabyData, nZlibCompressedSize,
+                                    psCtxt->pabyUncompressed, nUncompressedSize,
+                                    NULL );
                 if( pOut == NULL )
                     GOTO_END_ERROR;
 
-                if (eType == BLOB_OSMHEADER)
+                if( eType == BLOB_OSMHEADER )
                 {
                     bRet = ReadOSMHeader(psCtxt->pabyUncompressed,
                                          psCtxt->pabyUncompressed + nUncompressedSize,
                                          psCtxt);
                 }
-                else if (eType == BLOB_OSMDATA)
+                else if( eType == BLOB_OSMDATA )
                 {
                     bRet = ReadPrimitiveBlock(psCtxt->pabyUncompressed,
                                               psCtxt->pabyUncompressed + nUncompressedSize,
@@ -1604,27 +1603,26 @@ int ReadBlob(GByte* pabyData, unsigned int nDataSize, BlobType eType,
     return bRet;
 
 end_error:
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                        EmptyNotifyNodesFunc()                        */
 /************************************************************************/
 
-static void EmptyNotifyNodesFunc(unsigned int /* nNodes */,
-                                 OSMNode* /* pasNodes */,
-                                 OSMContext* /* psCtxt */,
-                                 void* /* user_data */)
+static void EmptyNotifyNodesFunc( unsigned int /* nNodes */,
+                                  OSMNode* /* pasNodes */,
+                                  OSMContext* /* psCtxt */,
+                                  void* /* user_data */ )
 {}
 
-
 /************************************************************************/
 /*                         EmptyNotifyWayFunc()                         */
 /************************************************************************/
 
-static void EmptyNotifyWayFunc(OSMWay* /* psWay */,
-                               OSMContext* /* psCtxt */,
-                               void* /* user_data */)
+static void EmptyNotifyWayFunc( OSMWay* /* psWay */,
+                                OSMContext* /* psCtxt */,
+                                void* /* user_data */ )
 {}
 
 /************************************************************************/
@@ -1633,7 +1631,7 @@ static void EmptyNotifyWayFunc(OSMWay* /* psWay */,
 
 static void EmptyNotifyRelationFunc( OSMRelation* /* psRelation */,
                                      OSMContext* /* psCtxt */,
-                                     void* /* user_data */)
+                                     void* /* user_data */ )
 {}
 
 /************************************************************************/
@@ -1656,35 +1654,32 @@ static void EmptyNotifyBoundsFunc( double /* dfXMin */,
 
 static const char* OSM_AddString(OSMContext* psCtxt, const char* pszStr)
 {
-    char* pszRet;
     int nLen = (int)strlen(pszStr);
     if( psCtxt->nStrLength + nLen + 1 > psCtxt->nStrAllocated )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "String buffer too small");
         return "";
     }
-    pszRet = psCtxt->pszStrBuf + psCtxt->nStrLength;
+    char* pszRet = psCtxt->pszStrBuf + psCtxt->nStrLength;
     memcpy(pszRet, pszStr, nLen);
     pszRet[nLen] = '\0';
     psCtxt->nStrLength += nLen + 1;
     return pszRet;
 }
 
-
 /************************************************************************/
 /*                            OSM_Atoi64()                              */
 /************************************************************************/
 
 static GIntBig OSM_Atoi64( const char *pszString )
 {
-    GIntBig    iValue;
 
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
-    iValue = (GIntBig)_atoi64( pszString );
+    const GIntBig iValue = (GIntBig)_atoi64( pszString );
 # elif HAVE_ATOLL
-    iValue = atoll( pszString );
+    const GIntBig iValue = atoll( pszString );
 #else
-    iValue = atol( pszString );
+    const GIntBig iValue = atol( pszString );
 #endif
 
     return iValue;
@@ -1701,7 +1696,7 @@ static void XMLCALL OSM_XML_startElementCbk( void *pUserData,
     OSMContext* psCtxt = (OSMContext*) pUserData;
     const char** ppszIter = ppszAttr;
 
-    if (psCtxt->bStopParsing) return;
+    if( psCtxt->bStopParsing ) return;
 
     psCtxt->nWithoutEventCounter = 0;
 
@@ -1905,7 +1900,6 @@ static void XMLCALL OSM_XML_startElementCbk( void *pUserData,
                 {
                     psCtxt->sRelation.sInfo.ts.pszTimeStamp = OSM_AddString(psCtxt, ppszIter[1]);
                     psCtxt->sRelation.sInfo.bTimeStampIsStr = true;
-
                 }
                 ppszIter += 2;
             }
@@ -1937,12 +1931,11 @@ static void XMLCALL OSM_XML_startElementCbk( void *pUserData,
     {
         /* 300 is the recommended value, but there are files with more than 2000 so we should be able */
         /* to realloc over that value */
-        if (psCtxt->sRelation.nMembers >= psCtxt->nMembersAllocated)
+        if( psCtxt->sRelation.nMembers >= psCtxt->nMembersAllocated )
         {
-            OSMMember* pasMembersNew;
             int nMembersAllocated =
-                MAX(psCtxt->nMembersAllocated * 2, psCtxt->sRelation.nMembers + 1);
-            pasMembersNew = (OSMMember*) VSI_REALLOC_VERBOSE(
+                std::max(psCtxt->nMembersAllocated * 2, psCtxt->sRelation.nMembers + 1);
+            OSMMember* pasMembersNew = (OSMMember*) VSI_REALLOC_VERBOSE(
                     psCtxt->pasMembers,
                     nMembersAllocated * sizeof(OSMMember));
             if( pasMembersNew == NULL )
@@ -1991,45 +1984,53 @@ static void XMLCALL OSM_XML_startElementCbk( void *pUserData,
     else if( (psCtxt->bInNode || psCtxt->bInWay || psCtxt->bInRelation) &&
              strcmp(pszName, "tag") == 0 )
     {
-        if( psCtxt->nTags < psCtxt->nTagsAllocated )
-        {
-            OSMTag* psTag = &(psCtxt->pasTags[psCtxt->nTags]);
-            psCtxt->nTags ++;
+        if( psCtxt->nTags == psCtxt->nTagsAllocated )
+        {
+            psCtxt->nTagsAllocated =
+                psCtxt->nTagsAllocated * 2;
+            OSMTag* pasTagsNew = (OSMTag*) VSI_REALLOC_VERBOSE(
+                psCtxt->pasTags,
+                psCtxt->nTagsAllocated * sizeof(OSMTag));
+            if( pasTagsNew == NULL )
+            {
+                if( psCtxt->bInNode )
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                            "Too many tags in node " CPL_FRMT_GIB,
+                            psCtxt->pasNodes[0].nID);
+                else if( psCtxt->bInWay )
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                            "Too many tags in way " CPL_FRMT_GIB,
+                            psCtxt->sWay.nID);
+                else if( psCtxt->bInRelation )
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                            "Too many tags in relation " CPL_FRMT_GIB,
+                            psCtxt->sRelation.nID);
+                return;
+            }
+            psCtxt->pasTags = pasTagsNew;
+        }
 
-            psTag->pszK = "";
-            psTag->pszV = "";
+        OSMTag* psTag = &(psCtxt->pasTags[psCtxt->nTags]);
+        psCtxt->nTags ++;
 
-            if( ppszIter )
+        psTag->pszK = "";
+        psTag->pszV = "";
+
+        if( ppszIter )
+        {
+            while( ppszIter[0] != NULL )
             {
-                while( ppszIter[0] != NULL )
+                if( ppszIter[0][0] == 'k' )
                 {
-                    if( ppszIter[0][0] == 'k' )
-                    {
-                        psTag->pszK = OSM_AddString(psCtxt, ppszIter[1]);
-                    }
-                    else if( ppszIter[0][0] == 'v' )
-                    {
-                        psTag->pszV = OSM_AddString(psCtxt, ppszIter[1]);
-                    }
-                    ppszIter += 2;
+                    psTag->pszK = OSM_AddString(psCtxt, ppszIter[1]);
+                }
+                else if( ppszIter[0][0] == 'v' )
+                {
+                    psTag->pszV = OSM_AddString(psCtxt, ppszIter[1]);
                 }
+                ppszIter += 2;
             }
         }
-        else
-        {
-            if (psCtxt->bInNode)
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Too many tags in node " CPL_FRMT_GIB,
-                         psCtxt->pasNodes[0].nID);
-            else if (psCtxt->bInWay)
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Too many tags in way " CPL_FRMT_GIB,
-                         psCtxt->sWay.nID);
-            else if (psCtxt->bInRelation)
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Too many tags in relation " CPL_FRMT_GIB,
-                         psCtxt->sRelation.nID);
-        }
     }
 }
 
@@ -2037,11 +2038,12 @@ static void XMLCALL OSM_XML_startElementCbk( void *pUserData,
 /*                       OSM_XML_endElementCbk()                        */
 /************************************************************************/
 
-static void XMLCALL OSM_XML_endElementCbk(void *pUserData, const char *pszName)
+static void XMLCALL OSM_XML_endElementCbk( void *pUserData,
+                                           const char *pszName )
 {
     OSMContext* psCtxt = (OSMContext*) pUserData;
 
-    if (psCtxt->bStopParsing) return;
+    if( psCtxt->bStopParsing ) return;
 
     psCtxt->nWithoutEventCounter = 0;
 
@@ -2064,7 +2066,7 @@ static void XMLCALL OSM_XML_endElementCbk(void *pUserData, const char *pszName)
 
             psCtxt->bHasFoundFeature = true;
         }
-        psCtxt->bInNode = FALSE;
+        psCtxt->bInNode = false;
     }
 
     else
@@ -2079,7 +2081,7 @@ static void XMLCALL OSM_XML_endElementCbk(void *pUserData, const char *pszName)
 
         psCtxt->bHasFoundFeature = true;
 
-        psCtxt->bInWay = FALSE;
+        psCtxt->bInWay = false;
     }
 
     else
@@ -2107,12 +2109,12 @@ static void XMLCALL OSM_XML_dataHandlerCbk( void *pUserData,
 {
     OSMContext* psCtxt = static_cast<OSMContext *>(pUserData);
 
-    if (psCtxt->bStopParsing) return;
+    if( psCtxt->bStopParsing ) return;
 
     psCtxt->nWithoutEventCounter = 0;
 
     psCtxt->nDataHandlerCounter ++;
-    if (psCtxt->nDataHandlerCounter >= XML_BUFSIZE)
+    if( psCtxt->nDataHandlerCounter >= XML_BUFSIZE )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "File probably corrupted (million laugh pattern)");
@@ -2138,21 +2140,20 @@ static OSMRetCode XML_ProcessBlock(OSMContext* psCtxt)
 
     do
     {
-        int eErr;
-        unsigned int nLen;
-
         psCtxt->nDataHandlerCounter = 0;
 
-        nLen = (unsigned int)VSIFReadL( psCtxt->pabyBlob, 1,
-                                        XML_BUFSIZE, psCtxt->fp );
+        const unsigned int nLen =
+            (unsigned int)VSIFReadL( psCtxt->pabyBlob, 1,
+                                     XML_BUFSIZE, psCtxt->fp );
 
         psCtxt->nBytesRead += nLen;
 
         psCtxt->bEOF = CPL_TO_BOOL(VSIFEofL(psCtxt->fp));
-        eErr = XML_Parse(psCtxt->hXMLParser, (const char*) psCtxt->pabyBlob,
-                         nLen, psCtxt->bEOF );
+        const int eErr =
+            XML_Parse(psCtxt->hXMLParser, (const char*) psCtxt->pabyBlob,
+                      nLen, psCtxt->bEOF );
 
-        if (eErr == XML_STATUS_ERROR)
+        if( eErr == XML_STATUS_ERROR )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                      "XML parsing of OSM file failed : %s "
@@ -2167,7 +2168,7 @@ static OSMRetCode XML_ProcessBlock(OSMContext* psCtxt)
              !psCtxt->bHasFoundFeature &&
              psCtxt->nWithoutEventCounter < 10);
 
-    if (psCtxt->nWithoutEventCounter == 10)
+    if( psCtxt->nWithoutEventCounter == 10 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
@@ -2192,7 +2193,7 @@ OSMContext* OSM_Open( const char* pszFilename,
 {
 
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
-    if (fp == NULL)
+    if( fp == NULL )
         return NULL;
 
     GByte abyHeader[1024];
@@ -2219,7 +2220,7 @@ OSMContext* OSM_Open( const char* pszFilename,
         {
             if( memcmp(abyHeader + i, "OSMHeader", strlen("OSMHeader") ) == 0 )
             {
-                bPBF = TRUE;
+                bPBF = true;
                 break;
             }
         }
@@ -2234,7 +2235,7 @@ OSMContext* OSM_Open( const char* pszFilename,
 
     OSMContext* psCtxt = static_cast<OSMContext *>(
         VSI_MALLOC_VERBOSE(sizeof(OSMContext)) );
-    if (psCtxt == NULL)
+    if( psCtxt == NULL )
     {
         VSIFCloseL(fp);
         return NULL;
@@ -2302,7 +2303,6 @@ OSMContext* OSM_Open( const char* pszFilename,
             OSM_Close(psCtxt);
             return NULL;
         }
-
     }
 #endif
 
@@ -2328,7 +2328,7 @@ void OSM_Close(OSMContext* psCtxt)
 #ifdef HAVE_EXPAT
     if( !psCtxt->bPBF )
     {
-        if (psCtxt->hXMLParser)
+        if( psCtxt->hXMLParser )
             XML_ParserFree(psCtxt->hXMLParser);
 
         CPLFree(psCtxt->pszStrBuf); /* only for XML case ! */
@@ -2374,7 +2374,7 @@ void OSM_ResetReading( OSMContext* psCtxt )
 
         psCtxt->bTryToFetchBounds = true;
         psCtxt->bInNode = false;
-        psCtxt->bInWay = FALSE;
+        psCtxt->bInWay = false;
         psCtxt->bInRelation = false;
     }
 #endif
@@ -2386,47 +2386,49 @@ void OSM_ResetReading( OSMContext* psCtxt )
 
 static OSMRetCode PBF_ProcessBlock(OSMContext* psCtxt)
 {
-    int nRet = FALSE;
+    bool nRet = false;
     GByte abyHeaderSize[4];
-    unsigned int nHeaderSize;
     unsigned int nBlobSize = 0;
     BlobType eType;
 
-    if (VSIFReadL(abyHeaderSize, 4, 1, psCtxt->fp) != 1)
+    if( VSIFReadL(abyHeaderSize, 4, 1, psCtxt->fp) != 1 )
     {
         return OSM_EOF;
     }
-    nHeaderSize = (abyHeaderSize[0] << 24) | (abyHeaderSize[1] << 16) |
-                    (abyHeaderSize[2] << 8) | abyHeaderSize[3];
+    const unsigned int nHeaderSize =
+        (abyHeaderSize[0] << 24) | (abyHeaderSize[1] << 16) |
+        (abyHeaderSize[2] << 8) | abyHeaderSize[3];
 
     psCtxt->nBytesRead += 4;
 
     /* printf("nHeaderSize = %d\n", nHeaderSize); */
-    if (nHeaderSize > 64 * 1024)
+    if( nHeaderSize > 64 * 1024 )
         GOTO_END_ERROR;
-    if (VSIFReadL(psCtxt->pabyBlob, 1, nHeaderSize, psCtxt->fp) != nHeaderSize)
+    if( VSIFReadL(psCtxt->pabyBlob, 1, nHeaderSize, psCtxt->fp) != nHeaderSize )
         GOTO_END_ERROR;
 
     psCtxt->nBytesRead += nHeaderSize;
 
     memset(psCtxt->pabyBlob + nHeaderSize, 0, EXTRA_BYTES);
-    nRet = ReadBlobHeader(psCtxt->pabyBlob, psCtxt->pabyBlob + nHeaderSize, &nBlobSize, &eType);
-    if (!nRet || eType == BLOB_UNKNOWN)
+    nRet = ReadBlobHeader(psCtxt->pabyBlob, psCtxt->pabyBlob + nHeaderSize,
+                          &nBlobSize, &eType);
+    if( !nRet || eType == BLOB_UNKNOWN )
         GOTO_END_ERROR;
 
-    if (nBlobSize > 64*1024*1024)
+    if( nBlobSize > 64*1024*1024 )
         GOTO_END_ERROR;
-    if (nBlobSize > psCtxt->nBlobSizeAllocated)
+    if( nBlobSize > psCtxt->nBlobSizeAllocated )
     {
-        GByte* pabyBlobNew;
-        psCtxt->nBlobSizeAllocated = MAX(psCtxt->nBlobSizeAllocated * 2, nBlobSize);
-        pabyBlobNew = (GByte*)VSI_REALLOC_VERBOSE(psCtxt->pabyBlob,
-                                        psCtxt->nBlobSizeAllocated + EXTRA_BYTES);
+        psCtxt->nBlobSizeAllocated =
+            std::max(psCtxt->nBlobSizeAllocated * 2, nBlobSize);
+        GByte* pabyBlobNew = static_cast<GByte *>(
+            VSI_REALLOC_VERBOSE(psCtxt->pabyBlob,
+                                psCtxt->nBlobSizeAllocated + EXTRA_BYTES));
         if( pabyBlobNew == NULL )
             GOTO_END_ERROR;
         psCtxt->pabyBlob = pabyBlobNew;
     }
-    if (VSIFReadL(psCtxt->pabyBlob, 1, nBlobSize, psCtxt->fp) != nBlobSize)
+    if( VSIFReadL(psCtxt->pabyBlob, 1, nBlobSize, psCtxt->fp) != nBlobSize )
         GOTO_END_ERROR;
 
     psCtxt->nBytesRead += nBlobSize;
@@ -2434,7 +2436,7 @@ static OSMRetCode PBF_ProcessBlock(OSMContext* psCtxt)
     memset(psCtxt->pabyBlob + nBlobSize, 0, EXTRA_BYTES);
     nRet = ReadBlob(psCtxt->pabyBlob, nBlobSize, eType,
                     psCtxt);
-    if (!nRet)
+    if( !nRet )
         GOTO_END_ERROR;
 
     return OSM_OK;
@@ -2448,7 +2450,7 @@ end_error:
 /*                          OSM_ProcessBlock()                          */
 /************************************************************************/
 
-OSMRetCode OSM_ProcessBlock(OSMContext* psCtxt)
+OSMRetCode OSM_ProcessBlock( OSMContext* psCtxt )
 {
 #ifdef HAVE_EXPAT
     if( psCtxt->bPBF )
diff --git a/ogr/ogrsf_frmts/pds/ogr_pds.h b/ogr/ogrsf_frmts/pds/ogr_pds.h
index c9e975d..adbe352 100644
--- a/ogr/ogrsf_frmts/pds/ogr_pds.h
+++ b/ogr/ogrsf_frmts/pds/ogr_pds.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pds.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_pds.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  PDS Translator
  * Purpose:  Definition of classes for OGR .pdstable driver.
@@ -85,21 +85,20 @@ class OGRPDSLayer : public OGRLayer
                                          int nRecords,
                                          int nStartBytes, int nRecordSize,
                                          GByte* pabyRecord, bool bIsASCII);
-                        ~OGRPDSLayer();
+                        virtual ~OGRPDSLayer();
 
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual int                 TestCapability( const char * ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual GIntBig             GetFeatureCount(int bForce = TRUE ) override;
 
-    virtual GIntBig             GetFeatureCount(int bForce = TRUE );
+    virtual OGRFeature         *GetFeature( GIntBig nFID ) override;
 
-    virtual OGRFeature         *GetFeature( GIntBig nFID );
-
-    virtual OGRErr              SetNextByIndex( GIntBig nIndex );
+    virtual OGRErr              SetNextByIndex( GIntBig nIndex ) override;
 };
 
 } /* end of OGRPDS namespace */
@@ -122,22 +121,22 @@ class OGRPDSDataSource : public OGRDataSource
                                        int iSubscript,
                                        const char *pszDefault );
 
-    int                 LoadTable(const char* pszFilename,
-                                  int nRecordSize,
-                                  CPLString osTableID);
+    bool                LoadTable( const char* pszFilename,
+                                   int nRecordSize,
+                                   CPLString osTableID );
 
   public:
                         OGRPDSDataSource();
-                        ~OGRPDSDataSource();
+                        virtual ~OGRPDSDataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     static void         CleanString( CPLString &osInput );
 };
diff --git a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
index 48a25ea..a292cf1 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdsdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpdsdatasource.cpp 33047 2016-01-19 14:47:32Z goatbar $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSDataSource class
@@ -31,7 +30,7 @@
 #include "cpl_string.h"
 #include "ogr_pds.h"
 
-CPL_CVSID("$Id: ogrpdsdatasource.cpp 33047 2016-01-19 14:47:32Z goatbar $");
+CPL_CVSID("$Id: ogrpdsdatasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 using namespace OGRPDS;
 
@@ -81,7 +80,6 @@ OGRLayer *OGRPDSDataSource::GetLayer( int iLayer )
     return papoLayers[iLayer];
 }
 
-
 /************************************************************************/
 /*                          GetKeywordSub()                             */
 /************************************************************************/
@@ -151,12 +149,12 @@ static CPLString MakeAttr(CPLString os1, CPLString os2)
     return os1 + "." + os2;
 }
 
-int OGRPDSDataSource::LoadTable( const char* pszFilename,
-                                 int nRecordSize,
-                                 CPLString osTableID )
+bool OGRPDSDataSource::LoadTable( const char* pszFilename,
+                                  int nRecordSize,
+                                  CPLString osTableID )
 {
     CPLString osTableFilename;
-    int nStartBytes;
+    int nStartBytes = 0;
 
     CPLString osTableLink = "^";
     osTableLink += osTableID;
@@ -167,12 +165,12 @@ int OGRPDSDataSource::LoadTable( const char* pszFilename,
         osTableFilename = GetKeywordSub(osTableLink, 1, "");
         CPLString osStartRecord = GetKeywordSub(osTableLink, 2, "");
         nStartBytes = (atoi(osStartRecord.c_str()) - 1) * nRecordSize;
-        if (osTableFilename.size() == 0 || osStartRecord.size() == 0 ||
+        if (osTableFilename.empty() || osStartRecord.empty() ||
             nStartBytes < 0)
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                     "Cannot parse %s line", osTableLink.c_str());
-            return FALSE;
+            return false;
         }
         CPLString osTPath = CPLGetPath(pszFilename);
         CleanString( osTableFilename );
@@ -181,7 +179,7 @@ int OGRPDSDataSource::LoadTable( const char* pszFilename,
     else
     {
         osTableFilename = oKeywords.GetKeyword( osTableLink, "" );
-        if (osTableFilename.size() != 0 && osTableFilename[0] >= '0' &&
+        if (!osTableFilename.empty() && osTableFilename[0] >= '0' &&
             osTableFilename[0] <= '9')
         {
             nStartBytes = atoi(osTableFilename.c_str()) - 1;
@@ -201,7 +199,7 @@ int OGRPDSDataSource::LoadTable( const char* pszFilename,
 
     CPLString osTableName =
         oKeywords.GetKeyword( MakeAttr(osTableID, "NAME"), "" );
-    if (osTableName.size() == 0)
+    if (osTableName.empty())
     {
         if (GetLayerByName(osTableID.c_str()) == NULL)
             osTableName = osTableID;
@@ -215,12 +213,12 @@ int OGRPDSDataSource::LoadTable( const char* pszFilename,
     CPLString osTableRows =
         oKeywords.GetKeyword( MakeAttr(osTableID, "ROWS"), "" );
     const int nRecords = atoi(osTableRows);
-    if (osTableInterchangeFormat.size() == 0 ||
-        osTableRows.size() == 0 || nRecords < 0)
+    if (osTableInterchangeFormat.empty() ||
+        osTableRows.empty() || nRecords < 0)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "One of TABLE.INTERCHANGE_FORMAT or TABLE.ROWS is missing");
-        return FALSE;
+        return false;
     }
 
     CleanString(osTableInterchangeFormat);
@@ -229,7 +227,7 @@ int OGRPDSDataSource::LoadTable( const char* pszFilename,
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Only INTERCHANGE_FORMAT=ASCII or BINARY is supported");
-        return FALSE;
+        return false;
     }
 
     VSILFILE* fp = VSIFOpenL(osTableFilename, "rb");
@@ -237,12 +235,12 @@ int OGRPDSDataSource::LoadTable( const char* pszFilename,
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot open %s",
                  osTableFilename.c_str());
-        return FALSE;
+        return false;
     }
 
     CPLString osTableStructure =
         oKeywords.GetKeyword( MakeAttr(osTableID, "^STRUCTURE"), "" );
-    if (osTableStructure.size() != 0)
+    if (!osTableStructure.empty())
     {
         CPLString osTPath = CPLGetPath(pszFilename);
         CleanString( osTableStructure );
@@ -253,7 +251,7 @@ int OGRPDSDataSource::LoadTable( const char* pszFilename,
     if (pabyRecord == NULL)
     {
         VSIFCloseL(fp);
-        return FALSE;
+        return false;
     }
     pabyRecord[nRecordSize] = 0;
 
@@ -268,7 +266,7 @@ int OGRPDSDataSource::LoadTable( const char* pszFilename,
         osTableInterchangeFormat.compare("ASCII") == 0);
     nLayers++;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -313,8 +311,8 @@ int OGRPDSDataSource::Open( const char * pszFilename )
     CPLString osFileRecords = oKeywords.GetKeyword( "FILE_RECORDS", "" );
     CPLString osRecordBytes = oKeywords.GetKeyword( "RECORD_BYTES", "" );
     int nRecordSize = atoi(osRecordBytes);
-    if (osRecordType.size() == 0 || osFileRecords.size() == 0 ||
-        osRecordBytes.size() == 0 || nRecordSize <= 0)
+    if (osRecordType.empty() || osFileRecords.empty() ||
+        osRecordBytes.empty() || nRecordSize <= 0)
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "One of RECORD_TYPE, FILE_RECORDS or RECORD_BYTES is missing");
@@ -329,8 +327,10 @@ int OGRPDSDataSource::Open( const char * pszFilename )
     }
 
     CPLString osTable = oKeywords.GetKeyword( "^TABLE", "" );
-    if (osTable.size() != 0)
+    if (!osTable.empty())
+    {
         LoadTable(pszFilename, nRecordSize, "TABLE");
+    }
     else
     {
         fp = VSIFOpenL(pszFilename, "rb");
diff --git a/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp b/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp
index f7a5cf8..b92f1f3 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdsdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpdsdriver.cpp 33047 2016-01-19 14:47:32Z goatbar $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSDriver.
@@ -30,7 +29,7 @@
 #include "cpl_conv.h"
 #include "ogr_pds.h"
 
-CPL_CVSID("$Id: ogrpdsdriver.cpp 33047 2016-01-19 14:47:32Z goatbar $");
+CPL_CVSID("$Id: ogrpdsdriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 extern "C" void RegisterOGRPDS();
 
@@ -61,7 +60,6 @@ static GDALDataset *OGRPDSDriverOpen( GDALOpenInfo* poOpenInfo )
     return poDS;
 }
 
-
 /************************************************************************/
 /*                           RegisterOGRPDS()                           */
 /************************************************************************/
@@ -85,4 +83,3 @@ void RegisterOGRPDS()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp b/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp
index 2ed8d51..29bdfc0 100644
--- a/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp
+++ b/ogr/ogrsf_frmts/pds/ogrpdslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpdslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  PDS Translator
  * Purpose:  Implements OGRPDSLayer class.
@@ -32,7 +31,9 @@
 #include "cpl_string.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrpdslayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrpdslayer.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 namespace OGRPDS {
 
@@ -40,13 +41,13 @@ namespace OGRPDS {
 /*                           OGRPDSLayer()                              */
 /************************************************************************/
 
-OGRPDSLayer::OGRPDSLayer(   CPLString osTableIDIn,
-                            const char* pszLayerName, VSILFILE* fp,
-                            CPLString osLabelFilename,
-                            CPLString osStructureFilename,
-                            int nRecordsIn,
-                            int nStartBytesIn, int nRecordSizeIn,
-                            GByte* pabyRecordIn, bool bIsASCII) :
+OGRPDSLayer::OGRPDSLayer( CPLString osTableIDIn,
+                          const char* pszLayerName, VSILFILE* fp,
+                          CPLString osLabelFilename,
+                          CPLString osStructureFilename,
+                          int nRecordsIn,
+                          int nStartBytesIn, int nRecordSizeIn,
+                          GByte* pabyRecordIn, bool bIsASCII ) :
     poFeatureDefn(new OGRFeatureDefn( pszLayerName )),
     osTableID(osTableIDIn),
     fpPDS(fp),
@@ -63,7 +64,7 @@ OGRPDSLayer::OGRPDSLayer(   CPLString osTableIDIn,
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    if (osStructureFilename.size() != 0)
+    if (!osStructureFilename.empty())
     {
         ReadStructure(osStructureFilename);
     }
@@ -81,10 +82,10 @@ OGRPDSLayer::OGRPDSLayer(   CPLString osTableIDIn,
         char **papszTokens = CSLTokenizeString2(
                 (const char*)pabyRecord, " ", CSLT_HONOURSTRINGS );
         const int nTokens = CSLCount(papszTokens);
-        for( int i=0; i<nTokens; i++)
+        for( int i = 0; i < nTokens; i++ )
         {
             const char* pszStr = papszTokens[i];
-            char ch;
+            char ch = '\0';
             OGRFieldType eFieldType = OFTInteger;
             while((ch = *pszStr) != 0)
             {
@@ -133,7 +134,6 @@ OGRPDSLayer::~OGRPDSLayer()
     VSIFCloseL( fpPDS );
 }
 
-
 /************************************************************************/
 /*                           ReadStructure()                            */
 /************************************************************************/
@@ -173,10 +173,10 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
         if (bInObjectColumn && nTokens >= 1 &&
             EQUAL(papszTokens[0], "END_OBJECT"))
         {
-            if (osColumnName.size() != 0 &&
-                osColumnDataType.size() != 0 &&
-                osColumnStartByte.size() != 0 &&
-                osColumnBytes.size() != 0)
+            if (!osColumnName.empty() &&
+                !osColumnDataType.empty() &&
+                !osColumnStartByte.empty() &&
+                !osColumnBytes.empty())
             {
                 pasFieldDesc =
                     static_cast<FieldDesc*>(
@@ -255,10 +255,10 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
 
                     OGRFieldDefn oFieldDefn(osColumnName, eFieldType);
                     if ((pasFieldDesc[nFields].eFormat == ASCII_REAL &&
-                            osColumnFormat.size() != 0 &&
+                            !osColumnFormat.empty() &&
                             osColumnFormat[0] == 'F') ||
                         (pasFieldDesc[nFields].eFormat == ASCII_INTEGER &&
-                            osColumnFormat.size() != 0 &&
+                            !osColumnFormat.empty() &&
                             osColumnFormat[0] == 'I'))
                     {
                         const char* pszFormat = osColumnFormat.c_str();
@@ -272,7 +272,7 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
                         }
                     }
                     else if (oFieldDefn.GetType() == OFTString &&
-                                osColumnFormat.size() != 0 &&
+                                !osColumnFormat.empty() &&
                                 osColumnFormat[0] == 'A')
                     {
                         const char* pszFormat = osColumnFormat.c_str();
@@ -425,7 +425,6 @@ void OGRPDSLayer::ReadStructure(CPLString osStructureFilename)
     VSIFCloseL(fpStructure);
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -437,7 +436,6 @@ void OGRPDSLayer::ResetReading()
     VSIFSeekL( fpPDS, nStartBytes, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -462,7 +460,6 @@ OGRFeature *OGRPDSLayer::GetNextFeature()
     }
 }
 
-
 /************************************************************************/
 /*                         GetNextRawFeature()                          */
 /************************************************************************/
@@ -479,7 +476,6 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
     int nFieldCount = poFeatureDefn->GetFieldCount();
     if (pasFieldDesc != NULL)
     {
-        int j;
         for( int i=0;i<nFieldCount;i++)
         {
             if (pasFieldDesc[i].eFormat == ASCII_REAL ||
@@ -505,7 +501,7 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     {
                         int* panValues = static_cast<int *>(
                             CPLMalloc(sizeof(int) * pasFieldDesc[i].nItems) );
-                        for(j=0;j<pasFieldDesc[i].nItems;j++)
+                        for( int j = 0; j < pasFieldDesc[i].nItems; j++ )
                         {
                             panValues[j] = pabyRecord[pasFieldDesc[i].nStartByte + j];
                         }
@@ -522,9 +518,9 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     if (pasFieldDesc[i].nItems > 1)
                     {
                         int* panValues = (int*)CPLMalloc(sizeof(int) * pasFieldDesc[i].nItems);
-                        for(j=0;j<pasFieldDesc[i].nItems;j++)
+                        for( int j = 0; j < pasFieldDesc[i].nItems; j++ )
                         {
-                            unsigned short sVal;
+                            unsigned short sVal = 0;
                             memcpy(&sVal, pabyRecord + pasFieldDesc[i].nStartByte + 2 * j, 2);
                             CPL_MSBPTR16(&sVal);
                             panValues[j] = sVal;
@@ -534,7 +530,7 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     }
                     else
                     {
-                        unsigned short sVal;
+                        unsigned short sVal = 0;
                         memcpy(&sVal, pabyRecord + pasFieldDesc[i].nStartByte, 2);
                         CPL_MSBPTR16(&sVal);
                         poFeature->SetField(i, (int)sVal);
@@ -545,9 +541,9 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     if (pasFieldDesc[i].nItems > 1)
                     {
                         double* padfValues = (double*)CPLMalloc(sizeof(double) * pasFieldDesc[i].nItems);
-                        for(j=0;j<pasFieldDesc[i].nItems;j++)
+                        for( int j = 0; j < pasFieldDesc[i].nItems; j++ )
                         {
-                            unsigned int nVal;
+                            unsigned int nVal = 0;
                             memcpy(&nVal, pabyRecord + pasFieldDesc[i].nStartByte + 4 * j, 4);
                             CPL_MSBPTR32(&nVal);
                             padfValues[j] = (double)nVal;
@@ -557,7 +553,7 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     }
                     else
                     {
-                        unsigned int nVal;
+                        unsigned int nVal = 0;
                         memcpy(&nVal, pabyRecord + pasFieldDesc[i].nStartByte, 4);
                         CPL_MSBPTR32(&nVal);
                         poFeature->SetField(i, (double)nVal);
@@ -573,7 +569,7 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     if (pasFieldDesc[i].nItems > 1)
                     {
                         int* panValues = (int*)CPLMalloc(sizeof(int) * pasFieldDesc[i].nItems);
-                        for(j=0;j<pasFieldDesc[i].nItems;j++)
+                        for( int j = 0; j < pasFieldDesc[i].nItems; j++ )
                         {
                             panValues[j] = ((char*)pabyRecord)[pasFieldDesc[i].nStartByte + j];
                         }
@@ -590,9 +586,9 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     if (pasFieldDesc[i].nItems > 1)
                     {
                         int* panValues = (int*)CPLMalloc(sizeof(int) * pasFieldDesc[i].nItems);
-                        for(j=0;j<pasFieldDesc[i].nItems;j++)
+                        for( int j = 0; j < pasFieldDesc[i].nItems; j++ )
                         {
-                            short sVal;
+                            short sVal = 0;
                             memcpy(&sVal, pabyRecord + pasFieldDesc[i].nStartByte + 2 * j, 2);
                             CPL_MSBPTR16(&sVal);
                             panValues[j] = sVal;
@@ -602,7 +598,7 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     }
                     else
                     {
-                        short sVal;
+                        short sVal = 0;
                         memcpy(&sVal, pabyRecord + pasFieldDesc[i].nStartByte, 2);
                         CPL_MSBPTR16(&sVal);
                         poFeature->SetField(i, (int)sVal);
@@ -613,9 +609,9 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     if (pasFieldDesc[i].nItems > 1)
                     {
                         int* panValues = (int*)CPLMalloc(sizeof(int) * pasFieldDesc[i].nItems);
-                        for(j=0;j<pasFieldDesc[i].nItems;j++)
+                        for( int j = 0; j < pasFieldDesc[i].nItems; j++ )
                         {
-                            int nVal;
+                            int nVal = 0;
                             memcpy(&nVal, pabyRecord + pasFieldDesc[i].nStartByte + 4 * j, 4);
                             CPL_MSBPTR32(&nVal);
                             panValues[j] = nVal;
@@ -625,7 +621,7 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                     }
                     else
                     {
-                        int nVal;
+                        int nVal = 0;
                         memcpy(&nVal, pabyRecord + pasFieldDesc[i].nStartByte, 4);
                         CPL_MSBPTR32(&nVal);
                         poFeature->SetField(i, nVal);
@@ -640,9 +636,9 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                 if (pasFieldDesc[i].nItems > 1)
                 {
                     double* padfValues = (double*)CPLMalloc(sizeof(double) * pasFieldDesc[i].nItems);
-                    for(j=0;j<pasFieldDesc[i].nItems;j++)
+                    for( int j = 0; j < pasFieldDesc[i].nItems; j++ )
                     {
-                        float fVal;
+                        float fVal = 0.0f;
                         memcpy(&fVal, pabyRecord + pasFieldDesc[i].nStartByte + 4 * j, 4);
                         CPL_MSBPTR32(&fVal);
                         padfValues[j] = (double)fVal;
@@ -652,7 +648,7 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
                 }
                 else
                 {
-                    float fVal;
+                    float fVal = 0.0f;
                     memcpy(&fVal, pabyRecord + pasFieldDesc[i].nStartByte, 4);
                     CPL_MSBPTR32(&fVal);
                     poFeature->SetField(i, (double)fVal);
@@ -664,10 +660,8 @@ OGRFeature *OGRPDSLayer::GetNextRawFeature()
     {
         char **papszTokens = CSLTokenizeString2(
                 (const char*)pabyRecord, " ", CSLT_HONOURSTRINGS );
-        int nTokens = CSLCount(papszTokens);
-        nTokens = MIN(nTokens, nFieldCount);
-        int i;
-        for(i=0;i<nTokens;i++)
+        const int nTokens = std::min(CSLCount(papszTokens), nFieldCount);
+        for( int i = 0; i < nTokens; i++ )
         {
             poFeature->SetField(i, papszTokens[i]);
         }
diff --git a/ogr/ogrsf_frmts/pg/drv_pg.html b/ogr/ogrsf_frmts/pg/drv_pg.html
index a04df22..f8184bc 100644
--- a/ogr/ogrsf_frmts/pg/drv_pg.html
+++ b/ogr/ogrsf_frmts/pg/drv_pg.html
@@ -17,7 +17,7 @@ This driver requires a connection to a Postgres database. If you want to
 prepare a SQL dump to inject it later into a Postgres database, you can
 instead use the <a href="drv_pgdump.html">PostgreSQL SQL Dump driver</a> (GDAL/OGR >= 1.8.0)<p>
 
-You can find additionnal information on the driver in the <a href="drv_pg_advanced.html">Advanced OGR PostgreSQL driver Information</a> page.
+You can find additional information on the driver in the <a href="drv_pg_advanced.html">Advanced OGR PostgreSQL driver Information</a> page.
 
 <h2>Connecting to a database</h2>
 
@@ -248,6 +248,16 @@ ogrinfo -ro PG:'host=myserver.velocet.ca user=postgres dbname=warmerda'
 </pre>
 </li>
 
+<li>
+<p>
+This example shows use of PRELUDE_STATEMENTS and CLOSING_STATEMENTS as
+destination open options of ogr2ogr.<p>
+
+<pre>
+ogrinfo "pg:dbname=mydb" poly.shp -doo "PRELUDE_STATEMENTS=BEGIN; SET LOCAL statement_timeout TO '1h';" -doo CLOSING_STATEMENTS=COMMIT
+</pre>
+</li>
+
 </ul>
 
 <h3>FAQs</h3>
diff --git a/ogr/ogrsf_frmts/pg/ogr_pg.h b/ogr/ogrsf_frmts/pg/ogr_pg.h
index d484d01..91923aa 100644
--- a/ogr/ogrsf_frmts/pg/ogr_pg.h
+++ b/ogr/ogrsf_frmts/pg/ogr_pg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pg.h 35632 2016-10-07 13:45:42Z rouault $
+ * $Id: ogr_pg.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/PostgreSQL driver.
@@ -67,12 +67,12 @@
 #define INT8ARRAYOID            1016
 #define FLOAT4ARRAYOID          1021
 #define FLOAT8ARRAYOID          1022
-#define BPCHAROID		1042
-#define VARCHAROID		1043
-#define DATEOID			1082
-#define TIMEOID			1083
-#define TIMESTAMPOID	        1114
-#define TIMESTAMPTZOID	        1184
+#define BPCHAROID               1042
+#define VARCHAROID              1043
+#define DATEOID                 1082
+#define TIMEOID                 1083
+#define TIMESTAMPOID            1114
+#define TIMESTAMPTZOID          1184
 #define NUMERICOID              1700
 #define NUMERICARRAYOID         1231
 
@@ -122,7 +122,7 @@ class OGRPGGeomFieldDefn : public OGRGeomFieldDefn
             {
             }
 
-        virtual OGRSpatialReference* GetSpatialRef();
+        virtual OGRSpatialReference* GetSpatialRef() override;
 
         void UnsetLayer() { poLayer = NULL; }
 
@@ -138,7 +138,7 @@ class OGRPGGeomFieldDefn : public OGRGeomFieldDefn
 class OGRPGFeatureDefn : public OGRFeatureDefn
 {
     public:
-        OGRPGFeatureDefn( const char * pszName = NULL ) :
+        explicit OGRPGFeatureDefn( const char * pszName = NULL ) :
             OGRFeatureDefn(pszName)
         {
             SetGeomType(wkbNone);
@@ -218,23 +218,23 @@ class OGRPGLayer : public OGRLayer
                         OGRPGLayer();
     virtual             ~OGRPGLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
     virtual OGRPGFeatureDefn *  myGetLayerDefn() { return (OGRPGFeatureDefn*) GetLayerDefn(); }
 
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) { return GetExtent(0, psExtent, bForce); }
-    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce ) override;
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction() override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
     void                InvalidateCursor();
 
-    virtual const char *GetFIDColumn();
+    virtual const char *GetFIDColumn() override;
 
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
 
     OGRPGDataSource    *GetDS() { return poDS; }
 
@@ -249,9 +249,9 @@ class OGRPGTableLayer : public OGRPGLayer
 {
     int                 bUpdateAccess;
 
-    void                BuildWhere(void);
-    CPLString           BuildFields(void);
-    void                BuildFullQueryStatement(void);
+    void                BuildWhere();
+    CPLString           BuildFields();
+    void                BuildFullQueryStatement();
 
     char               *pszTableName;
     char               *pszSchemaName;
@@ -279,8 +279,8 @@ class OGRPGTableLayer : public OGRPGLayer
     int                 bFIDColumnInCopyFields;
     int                 bFirstInsertion;
 
-    OGRErr		CreateFeatureViaCopy( OGRFeature *poFeature );
-    OGRErr		CreateFeatureViaInsert( OGRFeature *poFeature );
+    OGRErr              CreateFeatureViaCopy( OGRFeature *poFeature );
+    OGRErr              CreateFeatureViaInsert( OGRFeature *poFeature );
     CPLString           BuildCopyFields();
 
     int                 bHasWarnedIncompatibleGeom;
@@ -305,7 +305,7 @@ class OGRPGTableLayer : public OGRPGLayer
 
     CPLString           m_osFirstGeometryFieldName;
 
-    virtual CPLString   GetFromClauseForGetExtent() { return pszSqlTableName; }
+    virtual CPLString   GetFromClauseForGetExtent() override { return pszSqlTableName; }
 
     OGRErr              RunAddGeometryColumn( OGRPGGeomFieldDefn *poGeomField );
     OGRErr              RunCreateSpatialIndex( OGRPGGeomFieldDefn *poGeomField );
@@ -318,47 +318,47 @@ public:
                                          const char * pszDescriptionIn,
                                          const char * pszGeomColForced,
                                          int bUpdate );
-                        ~OGRPGTableLayer();
+                        virtual ~OGRPGTableLayer();
 
     void                SetGeometryInformation(PGGeomColumnDesc* pasDesc,
                                                int nGeomFieldCount);
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
+    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
-                                         int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+                                         int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) { return GetExtent(0, psExtent, bForce); }
-    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce );
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce ) override;
 
     const char*         GetTableName() { return pszTableName; }
     const char*         GetSchemaName() { return pszSchemaName; }
 
-    virtual const char *GetFIDColumn();
+    virtual const char *GetFIDColumn() override;
 
-    virtual char      **GetMetadataDomainList();
-    virtual char      **GetMetadata(const char* pszDomain = "");
-    virtual const char *GetMetadataItem(const char* pszName, const char* pszDomain = "");
-    virtual CPLErr      SetMetadata(char** papszMD, const char* pszDomain = "");
-    virtual CPLErr      SetMetadataItem(const char* pszName, const char* pszValue, const char* pszDomain = "");
+    virtual char      **GetMetadataDomainList() override;
+    virtual char      **GetMetadata(const char* pszDomain = "") override;
+    virtual const char *GetMetadataItem(const char* pszName, const char* pszDomain = "") override;
+    virtual CPLErr      SetMetadata(char** papszMD, const char* pszDomain = "") override;
+    virtual CPLErr      SetMetadataItem(const char* pszName, const char* pszValue, const char* pszDomain = "") override;
 
     // follow methods are not base class overrides
     void                SetLaunderFlag( int bFlag )
@@ -393,7 +393,7 @@ public:
     void                SetDeferredCreation(int bDeferredCreationIn, CPLString osCreateTable);
     OGRErr              RunDeferredCreationIfNecessary();
 
-    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn);
+    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn) override;
 };
 
 /************************************************************************/
@@ -402,7 +402,7 @@ public:
 
 class OGRPGResultLayer : public OGRPGLayer
 {
-    void                BuildFullQueryStatement(void);
+    void                BuildFullQueryStatement();
 
     char                *pszRawStatement;
 
@@ -411,7 +411,7 @@ class OGRPGResultLayer : public OGRPGLayer
 
     CPLString           osWHERE;
 
-    virtual CPLString   GetFromClauseForGetExtent()
+    virtual CPLString   GetFromClauseForGetExtent() override
         { CPLString osStr("(");
           osStr += pszRawStatement; osStr += ")"; return osStr; }
 
@@ -421,17 +421,17 @@ class OGRPGResultLayer : public OGRPGLayer
                                           PGresult *hInitialResult );
     virtual             ~OGRPGResultLayer();
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) { SetSpatialFilter(0, poGeom); }
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom );
+    virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn);
+    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn) override;
 };
 
 /************************************************************************/
@@ -462,7 +462,7 @@ class OGRPGDataSource : public OGRDataSource
 
     PGconn              *hPGConn;
 
-    OGRErr              DeleteLayer( int iLayer );
+    OGRErr              DeleteLayer( int iLayer ) override;
 
     Oid                 nGeometryOID;
     Oid                 nGeographyOID;
@@ -475,7 +475,7 @@ class OGRPGDataSource : public OGRDataSource
 
     OGRPGTableLayer     *poLayerInCopyMode;
 
-    void                OGRPGDecodeVersionString(PGver* psVersion, const char* pszVer);
+    static void                OGRPGDecodeVersionString(PGver* psVersion, const char* pszVer);
 
     CPLString           osCurrentSchema;
     CPLString           GetCurrentSchema();
@@ -509,13 +509,13 @@ class OGRPGDataSource : public OGRDataSource
 
   public:
                         OGRPGDataSource();
-                        ~OGRPGDataSource();
+                        virtual ~OGRPGDataSource();
 
     PGconn              *GetPGConn() { return hPGConn; }
 
     int                 FetchSRSId( OGRSpatialReference * poSRS );
     OGRSpatialReference *FetchSRS( int nSRSId );
-    OGRErr              InitializeMetadataTables();
+    static OGRErr              InitializeMetadataTables();
 
     int                 Open( const char *, int bUpdate, int bTestOpen,
                               char** papszOpenOptions );
@@ -526,23 +526,23 @@ class OGRPGDataSource : public OGRDataSource
                                    const char * pszGeomColForced,
                                    int bUpdate, int bTestOpen );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount();
-    OGRLayer            *GetLayer( int );
-    OGRLayer            *GetLayerByName(const char * pszName);
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override;
+    OGRLayer            *GetLayer( int ) override;
+    OGRLayer            *GetLayerByName(const char * pszName) override;
 
-    virtual void        FlushCache(void);
+    virtual void        FlushCache() override;
 
     virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+                                      char ** = NULL ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
-    virtual OGRErr      StartTransaction(int bForce = FALSE);
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction(int bForce = FALSE) override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
     OGRErr              SoftStartTransaction();
     OGRErr              SoftCommitTransaction();
@@ -553,11 +553,11 @@ class OGRPGDataSource : public OGRDataSource
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     virtual const char* GetMetadataItem(const char* pszKey,
-                                             const char* pszDomain);
+                                             const char* pszDomain) override;
 
     int                 UseCopy();
     void                StartCopy( OGRPGTableLayer *poPGLayer );
diff --git a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
index 7bcad5c..161b456 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgdatasource.cpp 35632 2016-10-07 13:45:42Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDataSource class.
@@ -37,7 +36,7 @@
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpgdatasource.cpp 35632 2016-10-07 13:45:42Z rouault $");
+CPL_CVSID("$Id: ogrpgdatasource.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 static void OGRPGNoticeProcessor( void *arg, const char * pszMessage );
 
@@ -46,45 +45,41 @@ static void OGRPGNoticeProcessor( void *arg, const char * pszMessage );
 /************************************************************************/
 
 OGRPGDataSource::OGRPGDataSource() :
-    bDSUpdate(FALSE)
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    pszDBName(NULL),
+    bDSUpdate(FALSE),
+    bHavePostGIS(FALSE),
+    bHaveGeography(FALSE),
+    bUserTransactionActive(FALSE),
+    bSavePointActive(FALSE),
+    nSoftTransactionLevel(0),
+    hPGConn(NULL),
+    nGeometryOID(static_cast<Oid>(0)),
+    nGeographyOID(static_cast<Oid>(0)),
+    nKnownSRID(0),
+    panSRID(NULL),
+    papoSRS(NULL),
+    poLayerInCopyMode(NULL),
+    // Actual value will be auto-detected if PostGIS >= 2.0 detected.
+    nUndefinedSRID(-1),
+    pszForcedTables(NULL),
+    papszSchemaList(NULL),
+    bHasLoadTables(FALSE),
+    bListAllTables(FALSE),
+    bUseBinaryCursor(FALSE),
+    bBinaryTimeFormatIsInt8(FALSE),
+    bUseEscapeStringSyntax(FALSE),
+    m_bHasGeometryColumns(true),
+    m_bHasSpatialRefSys(true)
 {
-    pszName = NULL;
-    pszDBName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-    hPGConn = NULL;
-    bHavePostGIS = FALSE;
-    bHaveGeography = FALSE;
     sPostgreSQLVersion.nMajor = 0;
     sPostgreSQLVersion.nMinor = 0;
     sPostgreSQLVersion.nRelease = 0;
     sPostGISVersion.nMajor = 0;
     sPostGISVersion.nMinor = 0;
     sPostGISVersion.nRelease = 0;
-    bUseBinaryCursor = FALSE;
-    bUserTransactionActive = FALSE;
-    bSavePointActive = FALSE;
-    nSoftTransactionLevel = 0;
-    bBinaryTimeFormatIsInt8 = FALSE;
-    bUseEscapeStringSyntax = FALSE;
-    m_bHasGeometryColumns = true;
-    m_bHasSpatialRefSys = true;
-
-    nGeometryOID = (Oid) 0;
-    nGeographyOID = (Oid) 0;
-
-    nKnownSRID = 0;
-    panSRID = NULL;
-    papoSRS = NULL;
-
-    poLayerInCopyMode = NULL;
-    // Actual value will be auto-detected if PostGIS >= 2.0 detected.
-    nUndefinedSRID = -1;
-
-    pszForcedTables = NULL;
-    papszSchemaList = NULL;
-    bListAllTables = FALSE;
-    bHasLoadTables = FALSE;
 }
 
 /************************************************************************/
@@ -94,8 +89,6 @@ OGRPGDataSource::OGRPGDataSource() :
 OGRPGDataSource::~OGRPGDataSource()
 
 {
-    int         i;
-
     FlushCache();
 
     CPLFree( pszName );
@@ -103,14 +96,14 @@ OGRPGDataSource::~OGRPGDataSource()
     CPLFree( pszForcedTables );
     CSLDestroy( papszSchemaList );
 
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
 
     CPLFree( papoLayers );
 
     if( hPGConn != NULL )
     {
-        /* If there are prelude statements we don't want to mess with transactions */
+        // If there are prelude statements, don't mess with transactions.
         if( CSLFetchNameValue(papszOpenOptions, "PRELUDE_STATEMENTS") == NULL )
             FlushSoftTransaction();
 
@@ -121,7 +114,8 @@ OGRPGDataSource::~OGRPGDataSource()
                                                              "CLOSING_STATEMENTS");
         if( pszClosingStatements != NULL )
         {
-            PGresult    *hResult = OGRPG_PQexec( hPGConn, pszClosingStatements, TRUE );
+            PGresult *hResult =
+                OGRPG_PQexec( hPGConn, pszClosingStatements, TRUE );
             OGRPGClearResult(hResult);
         }
 
@@ -132,7 +126,7 @@ OGRPGDataSource::~OGRPGDataSource()
         hPGConn = NULL;
     }
 
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( papoSRS[i] != NULL )
             papoSRS[i]->Release();
@@ -179,17 +173,13 @@ CPLString OGRPGDataSource::GetCurrentSchema()
 
 void OGRPGDataSource::OGRPGDecodeVersionString(PGver* psVersion, const char* pszVer)
 {
-    GUInt32 iLen;
-    const char* ptr;
-    char szNum[25];
-    char szVer[10];
-
     while ( *pszVer == ' ' ) pszVer++;
 
-    ptr = pszVer;
+    const char* ptr = pszVer;
     // get Version string
     while (*ptr && *ptr != ' ') ptr++;
-    iLen = static_cast<int>(ptr-pszVer);
+    GUInt32 iLen = static_cast<int>(ptr-pszVer);
+    char szVer[10] = {};
     if ( iLen > sizeof(szVer) - 1 ) iLen = sizeof(szVer) - 1;
     strncpy(szVer,pszVer,iLen);
     szVer[iLen] = '\0';
@@ -199,6 +189,7 @@ void OGRPGDataSource::OGRPGDecodeVersionString(PGver* psVersion, const char* psz
     // get Major number
     while (*ptr && *ptr != '.') ptr++;
     iLen = static_cast<int>(ptr-pszVer);
+    char szNum[25] = {};
     if ( iLen > sizeof(szNum) - 1) iLen = sizeof(szNum) - 1;
     strncpy(szNum,pszVer,iLen);
     szNum[iLen] = '\0';
@@ -216,7 +207,6 @@ void OGRPGDataSource::OGRPGDecodeVersionString(PGver* psVersion, const char* psz
     szNum[iLen] = '\0';
     psVersion->nMinor = atoi(szNum);
 
-
     if ( *ptr )
     {
         pszVer = ++ptr;
@@ -229,15 +219,12 @@ void OGRPGDataSource::OGRPGDecodeVersionString(PGver* psVersion, const char* psz
         szNum[iLen] = '\0';
         psVersion->nRelease = atoi(szNum);
     }
-
 }
 
-
 /************************************************************************/
 /*                     One entry for each PG table                      */
 /************************************************************************/
 
-
 typedef struct
 {
     char* pszTableName;
@@ -303,8 +290,7 @@ static void OGRPGFreeTableEntry(void * _psTableEntry)
     CPLFree(psTableEntry->pszTableName);
     CPLFree(psTableEntry->pszSchemaName);
     CPLFree(psTableEntry->pszDescription);
-    int i;
-    for(i=0;i<psTableEntry->nGeomColumnCount;i++)
+    for( int i = 0; i < psTableEntry->nGeomColumnCount; i++ )
     {
         CPLFree(psTableEntry->pasGeomColumns[i].pszName);
         CPLFree(psTableEntry->pasGeomColumns[i].pszGeomType);
@@ -389,7 +375,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         const char* pszVal = CSLFetchNameValue(papszOpenOptions, apszOpenOptions[i]);
         if( pszVal )
         {
-            if( osConnectionName[osConnectionName.size()-1] != ':' )
+            if( osConnectionName.back() != ':' )
                 osConnectionName += " ";
             osConnectionName += apszOpenOptions[i];
             osConnectionName += "=";
@@ -399,30 +385,27 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
 
     char* pszConnectionName = CPLStrdup(osConnectionName);
 
-
 /* -------------------------------------------------------------------- */
 /*      Determine if the connection string contains an optional         */
 /*      ACTIVE_SCHEMA portion. If so, parse it out.                     */
 /* -------------------------------------------------------------------- */
-    char             *pszActiveSchemaStart;
-    pszActiveSchemaStart = strstr(pszConnectionName, "active_schema=");
+    char *pszActiveSchemaStart = strstr(pszConnectionName, "active_schema=");
     if (pszActiveSchemaStart == NULL)
         pszActiveSchemaStart = strstr(pszConnectionName, "ACTIVE_SCHEMA=");
     if (pszActiveSchemaStart != NULL)
     {
-        char           *pszActiveSchema;
-        const char     *pszEnd = NULL;
+        char *pszActiveSchema =
+            CPLStrdup( pszActiveSchemaStart + strlen("active_schema=") );
 
-        pszActiveSchema = CPLStrdup( pszActiveSchemaStart + strlen("active_schema=") );
-
-        pszEnd = strchr(pszActiveSchemaStart, ' ');
+        const char *pszEnd = strchr(pszActiveSchemaStart, ' ');
         if( pszEnd == NULL )
             pszEnd = pszConnectionName + strlen(pszConnectionName);
 
         // Remove ACTIVE_SCHEMA=xxxxx from pszConnectionName string
         memmove( pszActiveSchemaStart, pszEnd, strlen(pszEnd) + 1 );
 
-        pszActiveSchema[pszEnd - pszActiveSchemaStart - strlen("active_schema=")] = '\0';
+        pszActiveSchema[pszEnd - pszActiveSchemaStart -
+                        strlen("active_schema=")] = '\0';
 
         osActiveSchema = pszActiveSchema;
         CPLFree(pszActiveSchema);
@@ -442,12 +425,9 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         pszSchemasStart = strstr(pszConnectionName, "SCHEMAS=");
     if (pszSchemasStart != NULL)
     {
-        char           *pszSchemas;
-        const char     *pszEnd = NULL;
-
-        pszSchemas = CPLStrdup( pszSchemasStart + strlen("schemas=") );
+        char *pszSchemas = CPLStrdup( pszSchemasStart + strlen("schemas=") );
 
-        pszEnd = strchr(pszSchemasStart, ' ');
+        const char *pszEnd = strchr(pszSchemasStart, ' ');
         if( pszEnd == NULL )
             pszEnd = pszConnectionName + strlen(pszConnectionName);
 
@@ -478,8 +458,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
 /*      string; PQconnectdb() does not like unknown directives          */
 /* -------------------------------------------------------------------- */
 
-    char             *pszTableStart;
-    pszTableStart = strstr(pszConnectionName, "tables=");
+    char *pszTableStart = strstr(pszConnectionName, "tables=");
     if (pszTableStart == NULL)
         pszTableStart = strstr(pszConnectionName, "TABLES=");
 
@@ -499,7 +478,6 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
         pszForcedTables[pszEnd - pszTableStart - 7] = '\0';
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Try to establish connection.                                    */
 /* -------------------------------------------------------------------- */
@@ -621,13 +599,12 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
     if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
         && PQntuples(hResult) > 0 )
     {
-        const char* pszSpace;
         char * pszVer = PQgetvalue(hResult,0,0);
 
         CPLDebug("PG","PostgreSQL version string : '%s'", pszVer);
 
         /* Should work with "PostgreSQL X.Y.Z ..." or "EnterpriseDB X.Y.Z ..." */
-        pszSpace = strchr(pszVer, ' ');
+        const char* pszSpace = strchr(pszVer, ' ');
         if( pszSpace != NULL && isdigit(pszSpace[1]) )
         {
             OGRPGDecodeVersionString(&sPostgreSQLVersion, pszSpace + 1);
@@ -662,7 +639,7 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
 /* -------------------------------------------------------------------- */
 /*      Test if time binary format is int8 or float8                    */
 /* -------------------------------------------------------------------- */
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
     if (bUseBinaryCursor)
     {
         SoftStartTransaction();
@@ -776,11 +753,9 @@ int OGRPGDataSource::Open( const char * pszNewName, int bUpdate,
             CPLDebug("PG","PostGIS version string : '%s'", pszVer);
 
             OGRPGDecodeVersionString(&sPostGISVersion, pszVer);
-
         }
         OGRPGClearResult(hResult);
 
-
         if (sPostGISVersion.nMajor == 0 && sPostGISVersion.nMinor < 8)
         {
             // Turning off sequential scans for PostGIS < 0.8
@@ -839,7 +814,6 @@ void OGRPGDataSource::LoadTables()
         return;
     bHasLoadTables = TRUE;
 
-    PGresult            *hResult;
     PGTableEntry **papsTables = NULL;
     int            nTableCount = 0;
     CPLHashSet    *hSetTables = NULL;
@@ -852,16 +826,12 @@ void OGRPGDataSource::LoadTables()
 
     if( pszForcedTables )
     {
-        char          **papszTableList;
-
-        papszTableList = CSLTokenizeString2( pszForcedTables, ",", 0 );
+        char **papszTableList = CSLTokenizeString2( pszForcedTables, ",", 0 );
 
         for( int i = 0; i < CSLCount(papszTableList); i++ )
         {
-            char      **papszQualifiedParts;
-
             // Get schema and table name
-            papszQualifiedParts = CSLTokenizeString2( papszTableList[i],
+            char **papszQualifiedParts = CSLTokenizeString2( papszTableList[i],
                                                       ".", 0 );
             int nParts = CSLCount( papszQualifiedParts );
 
@@ -907,11 +877,10 @@ void OGRPGDataSource::LoadTables()
 /*      Get a list of available tables if they have not been            */
 /*      specified through the TABLES connection string param           */
 /* -------------------------------------------------------------------- */
-    const char* pszAllowedRelations;
-    if( CPLTestBool(CPLGetConfigOption("PG_SKIP_VIEWS", "NO")) )
-        pszAllowedRelations = "'r'";
-    else
-        pszAllowedRelations = "'r','v','m','f'";
+    const char* pszAllowedRelations =
+        CPLTestBool(CPLGetConfigOption("PG_SKIP_VIEWS", "NO"))
+        ? "'r'"
+        : "'r','v','m','f'";
 
     hSetTables = CPLHashSetNew(OGRPGHashTableEntry, OGRPGEqualTableEntry, OGRPGFreeTableEntry);
 
@@ -945,7 +914,7 @@ void OGRPGDataSource::LoadTables()
               "GROUP BY c.relname, n.nspname, c.relkind, a.attname, t.typname, dim, srid, geomtyp, a.attnotnull, c.oid, a.attnum, d.description "
               "ORDER BY c.oid, a.attnum",
               pszAllowedRelations);
-        hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+        PGresult *hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
         if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK )
         {
@@ -1116,7 +1085,7 @@ void OGRPGDataSource::LoadTables()
                                 "WHERE (c.relkind in (%s) AND c.relname !~ '^pg_' AND c.relnamespace=n.oid)",
                                 pszAllowedRelations);
 
-        hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+        PGresult *hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
         if( !hResult || PQresultStatus(hResult) != PGRES_TUPLES_OK )
         {
@@ -1307,9 +1276,8 @@ void OGRPGDataSource::LoadTables()
 /* -------------------------------------------------------------------- */
     for( int iRecord = 0; iRecord < nTableCount; iRecord++ )
     {
-        PGTableEntry* psEntry;
-        CPLString osDefnName;
-        psEntry = (PGTableEntry* )CPLHashSetLookup(hSetTables, papsTables[iRecord]);
+        PGTableEntry* psEntry =
+            (PGTableEntry* )CPLHashSetLookup(hSetTables, papsTables[iRecord]);
 
         /* If SCHEMAS= is specified, only take into account tables inside */
         /* one of the specified schemas */
@@ -1319,6 +1287,8 @@ void OGRPGDataSource::LoadTables()
             continue;
         }
 
+        CPLString osDefnName;
+
         if ( papsTables[iRecord]->pszSchemaName &&
             osCurrentSchema != papsTables[iRecord]->pszSchemaName )
         {
@@ -1334,11 +1304,11 @@ void OGRPGDataSource::LoadTables()
             continue;
         osRegisteredLayers.insert( osDefnName );
 
-        OGRPGTableLayer* poLayer;
-        poLayer = OpenTable( osCurrentSchema, papsTables[iRecord]->pszTableName,
-                             papsTables[iRecord]->pszSchemaName,
-                             papsTables[iRecord]->pszDescription,
-                             NULL, bDSUpdate, FALSE );
+        OGRPGTableLayer* poLayer =
+            OpenTable( osCurrentSchema, papsTables[iRecord]->pszTableName,
+                       papsTables[iRecord]->pszSchemaName,
+                       papsTables[iRecord]->pszDescription,
+                       NULL, bDSUpdate, FALSE );
         if( psEntry != NULL )
         {
             if( psEntry->nGeomColumnCount > 0 )
@@ -1382,12 +1352,11 @@ OGRPGTableLayer* OGRPGDataSource::OpenTable( CPLString& osCurrentSchemaIn,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRPGTableLayer  *poLayer;
-
-    poLayer = new OGRPGTableLayer( this, osCurrentSchemaIn,
-                                   pszNewName, pszSchemaName,
-                                   pszDescription,
-                                   pszGeomColumnForced, bUpdate );
+    OGRPGTableLayer  *poLayer =
+        new OGRPGTableLayer( this, osCurrentSchemaIn,
+                             pszNewName, pszSchemaName,
+                             pszDescription,
+                             pszGeomColumnForced, bUpdate );
     if( bTestOpen && !(poLayer->ReadTableDefinition()) )
     {
         delete poLayer;
@@ -1433,13 +1402,12 @@ OGRErr OGRPGDataSource::DeleteLayer( int iLayer )
              sizeof(void *) * (nLayers - iLayer - 1) );
     nLayers--;
 
-    if (osLayerName.size() == 0)
+    if (osLayerName.empty())
         return OGRERR_NONE;
 
 /* -------------------------------------------------------------------- */
 /*      Remove from the database.                                       */
 /* -------------------------------------------------------------------- */
-    PGresult            *hResult;
     CPLString            osCommand;
 
     SoftStartTransaction();
@@ -1453,14 +1421,14 @@ OGRErr OGRPGDataSource::DeleteLayer( int iLayer )
             "f_table_schema='%s'",
             osTableName.c_str(), osSchemaName.c_str() );
 
-        hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
+        PGresult *hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
         OGRPGClearResult( hResult );
     }
 
     osCommand.Printf("DROP TABLE %s.%s CASCADE",
                      OGRPGEscapeColumnName(osSchemaName).c_str(),
                      OGRPGEscapeColumnName(osTableName).c_str() );
-    hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
+    PGresult *hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
     OGRPGClearResult( hResult );
 
     SoftCommitTransaction();
@@ -1497,7 +1465,7 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
         osFIDColumnName = "ogc_fid";
     else
     {
-        if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+        if( CPLFetchBool(papszOptions,"LAUNDER", true) )
         {
             char* pszLaunderedFid = OGRPGCommonLaunderName(pszFIDColumnNameIn, "PG");
             osFIDColumnName += pszLaunderedFid;
@@ -1556,7 +1524,6 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
     if (bNoneAsUnknown && eType == wkbNone)
         eType = wkbUnknown;
 
-
     int bExtractSchemaFromLayerName = CPLTestBool(CSLFetchNameValueDef(
                                     papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES"));
 
@@ -1573,7 +1540,7 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
       strncpy(pszSchemaName, pszLayerName, length);
       pszSchemaName[length] = '\0';
 
-      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+      if( CPLFetchBool(papszOptions, "LAUNDER", true) )
           pszTableName = OGRPGCommonLaunderName( pszDotPos + 1, "PG" ); //skip "."
       else
           pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "."
@@ -1581,7 +1548,7 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
     else
     {
       pszSchemaName = NULL;
-      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+      if( CPLFetchBool(papszOptions, "LAUNDER", true) )
           pszTableName = OGRPGCommonLaunderName( pszLayerName, "PG" ); //skip "."
       else
           pszTableName = CPLStrdup( pszLayerName ); //skip "."
@@ -1609,7 +1576,7 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
 
     CPLString osSQLLayerName;
     if (pszSchemaName == NULL ||
-        ( strlen(osCurrentSchema) > 0 &&
+        ( !osCurrentSchema.empty() &&
           EQUAL(pszSchemaName, osCurrentSchema.c_str() ) ) )
         osSQLLayerName = pszTableName;
     else
@@ -1726,12 +1693,12 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
 /*      Create a basic table with the FID.  Also include the            */
 /*      geometry if this is not a PostGIS enabled table.                */
 /* -------------------------------------------------------------------- */
-    int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE);
+    const bool bFID64 = CPLFetchBool(papszOptions, "FID64", false);
     const char* pszSerialType = bFID64 ? "BIGSERIAL": "SERIAL";
 
     CPLString osCreateTable;
-    int bTemporary = CSLFetchBoolean( papszOptions, "TEMPORARY", FALSE );
-    if (bTemporary)
+    const bool bTemporary = CPLFetchBool( papszOptions, "TEMPORARY", false );
+    if( bTemporary )
     {
         CPLFree(pszSchemaName);
         pszSchemaName = CPLStrdup("pg_temp_1");
@@ -1739,12 +1706,15 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
                              OGRPGEscapeColumnName(pszTableName).c_str());
     }
     else
+    {
         osCreateTable.Printf("CREATE%s TABLE %s.%s",
-                             CSLFetchBoolean( papszOptions, "UNLOGGED", FALSE ) ? " UNLOGGED": "",
+                             CPLFetchBool( papszOptions, "UNLOGGED", false ) ?
+                             " UNLOGGED": "",
                              OGRPGEscapeColumnName(pszSchemaName).c_str(),
                              OGRPGEscapeColumnName(pszTableName).c_str());
+    }
 
-    const char *suffix;
+    const char *suffix = NULL;
     if( (GeometryTypeFlags & OGRGeometry::OGR_G_3D) && (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
         suffix = "ZM";
     else if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) &&
@@ -1810,7 +1780,7 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
     int bCreateSpatialIndex = ( pszSI == NULL || CPLTestBool(pszSI) );
     if( eType != wkbNone &&
         pszSI == NULL &&
-        CSLFetchBoolean( papszOptions, "UNLOGGED", FALSE ) &&
+        CPLFetchBool( papszOptions, "UNLOGGED", false ) &&
         !(sPostgreSQLVersion.nMajor > 9 ||
          (sPostgreSQLVersion.nMajor == 9 && sPostgreSQLVersion.nMinor >= 3)) )
     {
@@ -1949,14 +1919,13 @@ OGRPGDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRPGTableLayer     *poLayer;
-
-    poLayer = new OGRPGTableLayer( this, osCurrentSchema, pszTableName,
-                                   pszSchemaName, "", NULL, TRUE );
+    OGRPGTableLayer *poLayer =
+        new OGRPGTableLayer( this, osCurrentSchema, pszTableName,
+                             pszSchemaName, "", NULL, TRUE );
     poLayer->SetTableDefinition(osFIDColumnName, pszGFldName, eType,
                                 pszGeomType, nSRSId, GeometryTypeFlags);
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
-    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
+    poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", true) );
+    poLayer->SetPrecisionFlag( CPLFetchBool(papszOptions, "PRECISION", true));
     //poLayer->SetForcedSRSId(nForcedSRSId);
     poLayer->SetForcedGeometryTypeFlags(ForcedGeometryTypeFlags);
     poLayer->SetCreateSpatialIndexFlag(bCreateSpatialIndex);
@@ -2012,6 +1981,8 @@ int OGRPGDataSource::TestCapability( const char * pszCap )
         return TRUE;
     else if ( EQUAL(pszCap,ODsCMeasuredGeometries) )
         return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return TRUE;
     else
         return FALSE;
 }
@@ -2144,7 +2115,6 @@ OGRLayer *OGRPGDataSource::GetLayerByName( const char *pszNameIn )
     return poLayer;
 }
 
-
 /************************************************************************/
 /*                        OGRPGNoticeProcessor()                        */
 /************************************************************************/
@@ -2212,9 +2182,7 @@ OGRSpatialReference *OGRPGDataSource::FetchSRS( int nId )
         && PQresultStatus(hResult) == PGRES_TUPLES_OK
         && PQntuples(hResult) == 1 )
     {
-        char *pszWKT;
-
-        pszWKT = PQgetvalue(hResult,0,0);
+        char *pszWKT = PQgetvalue(hResult,0,0);
         poSRS = new OGRSpatialReference();
         if( poSRS->importFromWkt( &pszWKT ) != OGRERR_NONE )
         {
@@ -2253,18 +2221,14 @@ OGRSpatialReference *OGRPGDataSource::FetchSRS( int nId )
 int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
 {
-    PGresult            *hResult = NULL;
-    CPLString           osCommand;
-    char                *pszWKT = NULL;
-    const char*         pszAuthorityName;
-
     if( poSRS == NULL || !m_bHasSpatialRefSys )
         return nUndefinedSRID;
 
     OGRSpatialReference oSRS(*poSRS);
+    // cppcheck-suppress uselessAssignmentPtrArg
     poSRS = NULL;
 
-    pszAuthorityName = oSRS.GetAuthorityName(NULL);
+    const char* pszAuthorityName = oSRS.GetAuthorityName(NULL);
 
     if( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
     {
@@ -2290,6 +2254,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*      Check whether the authority name/code is already mapped to a    */
 /*      SRS ID.                                                         */
 /* -------------------------------------------------------------------- */
+    CPLString osCommand;
     int nAuthorityCode = 0;
     if( pszAuthorityName != NULL )
     {
@@ -2301,7 +2266,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
                             "auth_name = '%s' AND auth_srid = %d",
                             pszAuthorityName,
                             nAuthorityCode );
-            hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+            PGresult *hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
             if( hResult && PQresultStatus(hResult) == PGRES_TUPLES_OK
                 && PQntuples(hResult) > 0 )
@@ -2320,6 +2285,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
 /*      Translate SRS to WKT.                                           */
 /* -------------------------------------------------------------------- */
+    char *pszWKT = NULL;
     if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
     {
         CPLFree(pszWKT);
@@ -2333,7 +2299,7 @@ int OGRPGDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     osCommand.Printf(
              "SELECT srid FROM spatial_ref_sys WHERE srtext = %s",
              osWKT.c_str() );
-    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
+    PGresult *hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
     CPLFree( pszWKT );  // CM:  Added to prevent mem leaks
     pszWKT = NULL;      // CM:  Added
 
@@ -2597,7 +2563,7 @@ OGRErr OGRPGDataSource::SoftCommitTransaction()
 
     if( nSoftTransactionLevel <= 0 )
     {
-        CPLAssert(FALSE);
+        CPLAssert(false);
         return OGRERR_FAILURE;
     }
 
@@ -2630,7 +2596,7 @@ OGRErr OGRPGDataSource::SoftRollbackTransaction()
 
     if( nSoftTransactionLevel <= 0 )
     {
-        CPLAssert(FALSE);
+        CPLAssert(false);
         return OGRERR_FAILURE;
     }
 
@@ -2710,17 +2676,16 @@ class OGRPGNoResetResultLayer : public OGRPGLayer
 
     virtual             ~OGRPGNoResetResultLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
 
-    virtual int         TestCapability( const char * ) { return FALSE; }
+    virtual int         TestCapability( const char * ) override { return FALSE; }
 
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual CPLString   GetFromClauseForGetExtent() { CPLAssert(FALSE); return ""; }
-    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn) { poGFldDefn->nSRSId = -1; }
+    virtual CPLString   GetFromClauseForGetExtent() override { CPLAssert(false); return ""; }
+    virtual void        ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn) override { poGFldDefn->nSRSId = -1; }
 };
 
-
 /************************************************************************/
 /*                     OGRPGNoResetResultLayer()                        */
 /************************************************************************/
@@ -2785,18 +2750,18 @@ class OGRPGMemLayerWrapper : public OGRLayer
       OGRLayer       *poMemLayer;
 
   public:
-                        OGRPGMemLayerWrapper( GDALDataset  *poMemDSIn )
+                        explicit OGRPGMemLayerWrapper( GDALDataset  *poMemDSIn )
                         {
                             poMemDS = poMemDSIn;
                             poMemLayer = poMemDS->GetLayer(0);
                         }
 
-                        ~OGRPGMemLayerWrapper() { delete poMemDS; }
+                        virtual ~OGRPGMemLayerWrapper() { delete poMemDS; }
 
-    virtual void        ResetReading() { poMemLayer->ResetReading(); }
-    virtual OGRFeature *GetNextFeature() { return poMemLayer->GetNextFeature(); }
-    virtual OGRFeatureDefn *GetLayerDefn() { return poMemLayer->GetLayerDefn(); }
-    virtual int         TestCapability( const char * ) { return FALSE; }
+    virtual void        ResetReading() override { poMemLayer->ResetReading(); }
+    virtual OGRFeature *GetNextFeature() override { return poMemLayer->GetNextFeature(); }
+    virtual OGRFeatureDefn *GetLayerDefn() override { return poMemLayer->GetLayerDefn(); }
+    virtual int         TestCapability( const char * ) override { return FALSE; }
 };
 
 /************************************************************************/
@@ -2824,12 +2789,10 @@ const char* OGRPGDataSource::GetMetadataItem(const char* pszKey,
             osDebugLastTransactionCommand = "";
             return pszRet;
         }
-
     }
     return OGRDataSource::GetMetadataItem(pszKey, pszDomain);
 }
 
-
 /************************************************************************/
 /*                             ExecuteSQL()                             */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/pg/ogrpgdriver.cpp b/ogr/ogrsf_frmts/pg/ogrpgdriver.cpp
index 15bb1a5..bce7c30 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgdriver.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGDriver class.
@@ -30,8 +29,7 @@
 #include "ogr_pg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgdriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
-
+CPL_CVSID("$Id: ogrpgdriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                              Identify()                              */
@@ -52,12 +50,10 @@ static int OGRPGDriverIdentify( GDALOpenInfo* poOpenInfo )
 static GDALDataset *OGRPGDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRPGDataSource     *poDS;
-
     if( !OGRPGDriverIdentify(poOpenInfo) )
         return NULL;
 
-    poDS = new OGRPGDataSource();
+    OGRPGDataSource *poDS = new OGRPGDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename,
                      poOpenInfo->eAccess == GA_Update, TRUE,
@@ -82,9 +78,7 @@ static GDALDataset *OGRPGDriverCreate( const char * pszName,
                                           char **papszOptions )
 
 {
-    OGRPGDataSource     *poDS;
-
-    poDS = new OGRPGDataSource();
+    OGRPGDataSource *poDS = new OGRPGDataSource();
 
     if( !poDS->Open( pszName, TRUE, TRUE, papszOptions ) )
     {
diff --git a/ogr/ogrsf_frmts/pg/ogrpglayer.cpp b/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
index f2a9187..542cbe4 100644
--- a/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpglayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpglayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGLayer class  which implements shared handling
@@ -65,7 +64,7 @@ PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpglayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrpglayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 // These originally are defined in libpq-fs.h.
 
@@ -78,30 +77,23 @@ CPL_CVSID("$Id: ogrpglayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 /*                           OGRPGLayer()                               */
 /************************************************************************/
 
-OGRPGLayer::OGRPGLayer()
-
+OGRPGLayer::OGRPGLayer() :
+    poFeatureDefn(NULL),
+    nCursorPage(atoi(CPLGetConfigOption("OGR_PG_CURSOR_PAGE", "500"))),
+    iNextShapeId(0),
+    poDS(NULL),
+    pszQueryStatement(NULL),
+    pszCursorName(NULL),
+    hCursorResult(NULL),
+    bInvalidated(FALSE),
+    nResultOffset(0),
+    bWkbAsOid(FALSE),
+    pszFIDColumn(NULL),
+    bCanUseBinaryCursor(TRUE),
+    m_panMapFieldNameToIndex(NULL),
+    m_panMapFieldNameToGeomIndex(NULL)
 {
-    poDS = NULL;
-
-    bWkbAsOid = FALSE;
-    pszQueryStatement = NULL;
-
-    pszFIDColumn = NULL;
-
-    nCursorPage = atoi(CPLGetConfigOption("OGR_PG_CURSOR_PAGE", "500"));
-    iNextShapeId = 0;
-    nResultOffset = 0;
-
     pszCursorName = CPLStrdup(CPLSPrintf("OGRPGLayerReader%p", this));
-
-    hCursorResult = NULL;
-    bInvalidated = FALSE;
-
-    bCanUseBinaryCursor = TRUE;
-
-    poFeatureDefn = NULL;
-    m_panMapFieldNameToIndex = NULL;
-    m_panMapFieldNameToGeomIndex = NULL;
 }
 
 /************************************************************************/
@@ -198,18 +190,18 @@ typedef short NumericDigit;
 
 typedef struct NumericVar
 {
-        int			ndigits;		/* # of digits in digits[] - can be 0! */
-        int			weight;			/* weight of first digit */
-        int			sign;			/* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
-        int			dscale;			/* display scale */
-        NumericDigit *digits;		/* base-NBASE digits */
+        int ndigits;           /* # of digits in digits[] - can be 0! */
+        int weight;            /* weight of first digit */
+        int sign;              /* NUMERIC_POS, NUMERIC_NEG, or NUMERIC_NAN */
+        int dscale;            /* display scale */
+        NumericDigit *digits;  /* base-NBASE digits */
 } NumericVar;
 
-#define NUMERIC_POS			0x0000
-#define NUMERIC_NEG			0x4000
-#define NUMERIC_NAN			0xC000
+#define NUMERIC_POS 0x0000
+#define NUMERIC_NEG 0x4000
+#define NUMERIC_NAN 0xC000
 
-#define DEC_DIGITS	4
+#define DEC_DIGITS 4
 /*
 * get_str_from_var() -
 *
@@ -220,11 +212,11 @@ typedef struct NumericVar
 static char *
 OGRPGGetStrFromBinaryNumeric(NumericVar *var)
 {
-        char	   *str;
-        char	   *cp;
-        char	   *endcp;
-        int			i;
-        int			d;
+        char   *str;
+        char   *cp;
+        char   *endcp;
+        int     i;
+        int     d;
         NumericDigit dig;
         NumericDigit d1;
 
@@ -330,41 +322,40 @@ OGRPGGetStrFromBinaryNumeric(NumericVar *var)
 
 /* Coming from j2date() in pgsql/src/backend/utils/adt/datetime.c */
 
-#define POSTGRES_EPOCH_JDATE	2451545 /* == date2j(2000, 1, 1) */
+#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
 
 static
 void OGRPGj2date(int jd, int *year, int *month, int *day)
 {
-	unsigned int julian;
-	unsigned int quad;
-	unsigned int extra;
-	int			y;
-
-	julian = jd;
-	julian += 32044;
-	quad = julian / 146097;
-	extra = (julian - quad * 146097) * 4 + 3;
-	julian += 60 + quad * 3 + extra / 146097;
-	quad = julian / 1461;
-	julian -= quad * 1461;
-	y = julian * 4 / 1461;
-	julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
-		+ 123;
-	y += quad * 4;
-	*year = y - 4800;
-	quad = julian * 2141 / 65536;
-	*day = julian - 7834 * quad / 256;
-	*month = (quad + 10) % 12 + 1;
-
-	return;
-}	/* j2date() */
-
+    unsigned int julian;
+    unsigned int quad;
+    unsigned int extra;
+    int y;
+
+    julian = jd;
+    julian += 32044;
+    quad = julian / 146097;
+    extra = (julian - quad * 146097) * 4 + 3;
+    julian += 60 + quad * 3 + extra / 146097;
+    quad = julian / 1461;
+    julian -= quad * 1461;
+    y = julian * 4 / 1461;
+    julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))
+        + 123;
+    y += quad * 4;
+    *year = y - 4800;
+    quad = julian * 2141 / 65536;
+    *day = julian - 7834 * quad / 256;
+    *month = (quad + 10) % 12 + 1;
+
+    return;
+}  /* j2date() */
 
 /************************************************************************/
 /*                              OGRPGdt2time()                          */
 /************************************************************************/
 
-#define USECS_PER_SEC	1000000
+#define USECS_PER_SEC 1000000
 #define USECS_PER_MIN   ((GIntBig) 60 * USECS_PER_SEC)
 #define USECS_PER_HOUR  ((GIntBig) 3600 * USECS_PER_SEC)
 #define USECS_PER_DAY   ((GIntBig) 3600 * 24 * USECS_PER_SEC)
@@ -375,32 +366,32 @@ static
 void
 OGRPGdt2timeInt8(GIntBig jd, int *hour, int *min, int *sec, double *fsec)
 {
-	GIntBig		time;
+    GIntBig time;
 
-	time = jd;
+    time = jd;
 
-	*hour = (int) (time / USECS_PER_HOUR);
-	time -= (GIntBig) (*hour) * USECS_PER_HOUR;
-	*min = (int) (time / USECS_PER_MIN);
-	time -=  (GIntBig) (*min) * USECS_PER_MIN;
-	*sec = (int)time / USECS_PER_SEC;
-	*fsec = (double)(time - *sec * USECS_PER_SEC);
-}	/* dt2time() */
+    *hour = (int) (time / USECS_PER_HOUR);
+    time -= (GIntBig) (*hour) * USECS_PER_HOUR;
+    *min = (int) (time / USECS_PER_MIN);
+    time -=  (GIntBig) (*min) * USECS_PER_MIN;
+    *sec = (int)time / USECS_PER_SEC;
+    *fsec = (double)(time - *sec * USECS_PER_SEC);
+}  /* dt2time() */
 
 static
 void
 OGRPGdt2timeFloat8(double jd, int *hour, int *min, int *sec, double *fsec)
 {
-	double	time;
+    double time;
 
-	time = jd;
+    time = jd;
 
-	*hour = (int) (time / 3600.);
-	time -= (*hour) * 3600.;
-	*min = (int) (time / 60.);
-	time -=  (*min) * 60.;
-	*sec = (int)time;
-	*fsec = time - *sec;
+    *hour = (int) (time / 3600.);
+    time -= (*hour) * 3600.;
+    *min = (int) (time / 60.);
+    time -=  (*min) * 60.;
+    *sec = (int)time;
+    *fsec = time - *sec;
 }
 
 /************************************************************************/
@@ -409,9 +400,9 @@ OGRPGdt2timeFloat8(double jd, int *hour, int *min, int *sec, double *fsec)
 
 #define TMODULO(t,q,u) \
 do { \
-	(q) = ((t) / (u)); \
-	if ((q) != 0) (t) -= ((q) * (u)); \
-} while(0)
+        (q) = ((t) / (u)); \
+        if ((q) != 0) (t) -= ((q) * (u)); \
+} while( false )
 
 /* Coming from timestamp2tm() in pgsql/src/backend/utils/adt/timestamp.c */
 
@@ -419,32 +410,32 @@ static
 int OGRPGTimeStamp2DMYHMS(GIntBig dt, int *year, int *month, int *day,
                                       int* hour, int* min, double* pdfSec)
 {
-        GIntBig date;
-	GIntBig time;
-        int nSec;
-        double dfSec;
+    GIntBig date;
+    GIntBig time;
+    int nSec;
+    double dfSec;
 
-        time = dt;
-	TMODULO(time, date, USECS_PER_DAY);
+    time = dt;
+    TMODULO(time, date, USECS_PER_DAY);
 
-	if (time < 0)
-	{
-		time += USECS_PER_DAY;
-		date -= 1;
-	}
+    if (time < 0)
+    {
+        time += USECS_PER_DAY;
+        date -= 1;
+    }
 
-	/* add offset to go from J2000 back to standard Julian date */
-	date += POSTGRES_EPOCH_JDATE;
+    /* add offset to go from J2000 back to standard Julian date */
+    date += POSTGRES_EPOCH_JDATE;
 
-	/* Julian day routine does not work for negative Julian days */
-	if (date < 0 || date > (double) INT_MAX)
-		return -1;
+    /* Julian day routine does not work for negative Julian days */
+    if (date < 0 || date > (double) INT_MAX)
+        return -1;
 
-	OGRPGj2date((int) date, year, month, day);
-	OGRPGdt2timeInt8(time, hour, min, &nSec, &dfSec);
-        *pdfSec += nSec + dfSec;
+    OGRPGj2date((int) date, year, month, day);
+    OGRPGdt2timeInt8(time, hour, min, &nSec, &dfSec);
+    *pdfSec += nSec + dfSec;
 
-        return 0;
+    return 0;
 }
 
 #endif // defined(BINARY_CURSOR_ENABLED)
@@ -603,7 +594,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
     {
         int     iOGRField;
 
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
         int nTypeOID = PQftype(hResult, iField);
 #endif
         const char* pszFieldName = PQfname(hResult,iField);
@@ -613,7 +604,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
 /* -------------------------------------------------------------------- */
         if( pszFIDColumn != NULL && EQUAL(pszFieldName,pszFIDColumn) )
         {
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
                 if ( nTypeOID == INT4OID)
@@ -639,7 +630,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 }
             }
             else
-#endif /* notdef PG_PRE74 */
+#endif /* defined(BINARY_CURSOR_ENABLED) */
             {
                 char* pabyData = PQgetvalue(hResult,iRecord,iField);
                 /* ogr_pg_20 may crash if PostGIS is unavailable and we don't test pabyData */
@@ -733,7 +724,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 if (nLength == 0)
                     continue;
 
-                OGRGeometry * poGeom;
+                OGRGeometry * poGeom = NULL;
 
                 if( !poDS->bUseBinaryCursor &&
                     (STARTS_WITH(pabyData, "\\x00") || STARTS_WITH(pabyData, "\\x01") ||
@@ -769,12 +760,8 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                      EQUAL(pszFieldName,"ST_AsText") )*/
             {
                 /* Handle WKT */
-                char        *pszWKT;
-                char        *pszPostSRID;
-                OGRGeometry *poGeometry = NULL;
-
-                pszWKT = PQgetvalue( hResult, iRecord, iField );
-                pszPostSRID = pszWKT;
+                char *pszWKT = PQgetvalue( hResult, iRecord, iField );
+                char *pszPostSRID = pszWKT;
 
                 // optionally strip off PostGIS SRID identifier.  This
                 // happens if we got a raw geometry field.
@@ -786,6 +773,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                         pszPostSRID++;
                 }
 
+                OGRGeometry *poGeometry = NULL;
                 if( STARTS_WITH_CI(pszPostSRID, "00") || STARTS_WITH_CI(pszPostSRID, "01") )
                 {
                     poGeometry = OGRGeometryFromHexEWKB( pszWKT, NULL,
@@ -822,9 +810,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
             {
 #if defined(BINARY_CURSOR_ENABLED)
                 if (poDS->bUseBinaryCursor
-#if !defined(PG_PRE74)
                     && PQfformat( hResult, iField ) == 1
-#endif
                    )
                 {
                     int nLength = PQgetlength(hResult, iRecord, iField);
@@ -857,7 +843,10 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
             continue;
 
         if( PQgetisnull( hResult, iRecord, iField ) )
+        {
+            poFeature->SetFieldNull( iOGRField );
             continue;
+        }
 
         OGRFieldType eOGRType =
             poFeatureDefn->GetFieldDefn(iOGRField)->GetType();
@@ -866,7 +855,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
         {
             int *panList, nCount, i;
 
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
                 if (nTypeOID == INT2ARRAYOID || nTypeOID == INT4ARRAYOID)
@@ -915,10 +904,9 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 }
             }
             else
-#endif /* notdef PG_PRE74 */
+#endif
             {
-                char **papszTokens;
-                papszTokens = CSLTokenizeStringComplex(
+                char **papszTokens = CSLTokenizeStringComplex(
                     PQgetvalue( hResult, iRecord, iField ),
                     "{,}", FALSE, FALSE );
 
@@ -943,10 +931,10 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
 
         else if( eOGRType == OFTInteger64List)
         {
-            GIntBig *panList;
-            int nCount, i;
+            int nCount = 0;
+            GIntBig *panList = NULL;
 
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
                 if (nTypeOID == INT8ARRAYOID)
@@ -963,7 +951,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                     // goto first array element
                     pData += 2 * sizeof(int);
 
-                    for( i = 0; i < nCount; i++ )
+                    for( int i = 0; i < nCount; i++ )
                     {
                         // get element size
                         int nSize = *(int *)(pData);
@@ -986,10 +974,9 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 }
             }
             else
-#endif /* notdef PG_PRE74 */
+#endif
             {
-                char **papszTokens;
-                papszTokens = CSLTokenizeStringComplex(
+                char **papszTokens = CSLTokenizeStringComplex(
                     PQgetvalue( hResult, iRecord, iField ),
                     "{,}", FALSE, FALSE );
 
@@ -998,12 +985,12 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
 
                 if( poFeatureDefn->GetFieldDefn(iOGRField)->GetSubType() == OFSTBoolean )
                 {
-                    for( i = 0; i < nCount; i++ )
+                    for( int i = 0; i < nCount; i++ )
                         panList[i] = EQUAL(papszTokens[i], "t");
                 }
                 else
                 {
-                    for( i = 0; i < nCount; i++ )
+                    for( int i = 0; i < nCount; i++ )
                         panList[i] = CPLAtoGIntBig(papszTokens[i]);
                 }
                 CSLDestroy( papszTokens );
@@ -1015,9 +1002,9 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
         else if( eOGRType == OFTRealList )
         {
             int nCount, i;
-            double *padfList;
+            double *padfList = NULL;
 
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
                 if (nTypeOID == FLOAT8ARRAYOID || nTypeOID == FLOAT4ARRAYOID)
@@ -1070,10 +1057,9 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 }
             }
             else
-#endif /* notdef PG_PRE74 */
+#endif
             {
-                char **papszTokens;
-                papszTokens = CSLTokenizeStringComplex(
+                char **papszTokens = CSLTokenizeStringComplex(
                     PQgetvalue( hResult, iRecord, iField ),
                     "{,}", FALSE, FALSE );
 
@@ -1093,7 +1079,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
         {
             char **papszTokens = NULL;
 
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data representation
             {
                 char * pData = PQgetvalue( hResult, iRecord, iField );
@@ -1135,7 +1121,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 }
             }
             else
-#endif /* notdef PG_PRE74 */
+#endif
             {
                 papszTokens =
                         OGRPGTokenizeStringListFromText(PQgetvalue(hResult, iRecord, iField ));
@@ -1152,7 +1138,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                  || eOGRType == OFTTime
                  || eOGRType == OFTDateTime )
         {
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 ) // Binary data
             {
                 if ( nTypeOID == DATEOID )
@@ -1220,7 +1206,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 }
             }
             else
-#endif /* notdef PG_PRE74 */
+#endif
             {
                 OGRField  sFieldValue;
 
@@ -1233,7 +1219,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
         }
         else if( eOGRType == OFTBinary )
         {
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1)
             {
                 int nLength = PQgetlength(hResult, iRecord, iField);
@@ -1241,7 +1227,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 poFeature->SetField( iOGRField, nLength, pabyData );
             }
             else
-#endif  /* notdef PG_PRE74 */
+#endif  /* defined(BINARY_CURSOR_ENABLED) */
             {
                 int nLength = PQgetlength(hResult, iRecord, iField);
                 const char* pszBytea = (const char*) PQgetvalue( hResult, iRecord, iField );
@@ -1252,7 +1238,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
         }
         else
         {
-#if !defined(PG_PRE74) && defined(BINARY_CURSOR_ENABLED)
+#if defined(BINARY_CURSOR_ENABLED)
             if ( PQfformat( hResult, iField ) == 1 &&
                  eOGRType != OFTString ) // Binary data
             {
@@ -1345,7 +1331,7 @@ OGRFeature *OGRPGLayer::RecordToFeature( PGresult* hResult,
                 }
             }
             else
-#endif /* notdef PG_PRE74 */
+#endif /* defined(BINARY_CURSOR_ENABLED) */
             {
                 if ( eOGRType == OFTInteger &&
                      poFeatureDefn->GetFieldDefn(iOGRField)->GetWidth() == 1)
@@ -1445,7 +1431,6 @@ void OGRPGLayer::CreateMapFromFieldNameToIndex(PGresult* hResult,
     }
 }
 
-
 /************************************************************************/
 /*                     SetInitialQueryCursor()                          */
 /************************************************************************/
@@ -1558,7 +1543,6 @@ OGRFeature *OGRPGLayer::GetNextRawFeature()
         return NULL;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
@@ -1640,9 +1624,6 @@ OGRErr OGRPGLayer::SetNextByIndex( GIntBig nIndex )
 
 GByte* OGRPGLayer::BYTEAToGByteArray( const char *pszBytea, int* pnLength )
 {
-    GByte* pabyData;
-    int iSrc=0, iDst=0;
-
     if( pszBytea == NULL )
     {
         if (pnLength) *pnLength = 0;
@@ -1654,8 +1635,10 @@ GByte* OGRPGLayer::BYTEAToGByteArray( const char *pszBytea, int* pnLength )
         return CPLHexToBinary(pszBytea + 2, pnLength);
 
     /* +1 just to please Coverity that thinks we allocate for a null-terminate string */
-    pabyData = (GByte *) CPLMalloc(strlen(pszBytea)+1);
+    GByte* pabyData = (GByte *) CPLMalloc(strlen(pszBytea)+1);
 
+    int iSrc = 0;
+    int iDst = 0;
     while( pszBytea[iSrc] != '\0' )
     {
         if( pszBytea[iSrc] == '\\' )
@@ -1691,7 +1674,6 @@ GByte* OGRPGLayer::BYTEAToGByteArray( const char *pszBytea, int* pnLength )
     return pabyData;
 }
 
-
 /************************************************************************/
 /*                          BYTEAToGeometry()                           */
 /************************************************************************/
@@ -1699,16 +1681,13 @@ GByte* OGRPGLayer::BYTEAToGByteArray( const char *pszBytea, int* pnLength )
 OGRGeometry *OGRPGLayer::BYTEAToGeometry( const char *pszBytea, int bIsPostGIS1 )
 
 {
-    GByte       *pabyWKB;
-    int nLen=0;
-    OGRGeometry *poGeometry;
-
     if( pszBytea == NULL )
         return NULL;
 
-    pabyWKB = BYTEAToGByteArray(pszBytea, &nLen);
+    int nLen = 0;
+    GByte *pabyWKB = BYTEAToGByteArray(pszBytea, &nLen);
 
-    poGeometry = NULL;
+    OGRGeometry *poGeometry = NULL;
     OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeometry, nLen,
                                        (bIsPostGIS1) ? wkbVariantPostGIS1 : wkbVariantOldOgc );
 
@@ -1716,21 +1695,18 @@ OGRGeometry *OGRPGLayer::BYTEAToGeometry( const char *pszBytea, int bIsPostGIS1
     return poGeometry;
 }
 
-
 /************************************************************************/
 /*                        GByteArrayToBYTEA()                           */
 /************************************************************************/
 
 char* OGRPGLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
 {
-    char* pszTextBuf;
-
     const size_t nTextBufLen = nLen*5+1;
-    pszTextBuf = (char *) CPLMalloc(nTextBufLen);
+    char* pszTextBuf = (char *) CPLMalloc(nTextBufLen);
 
-    int  iSrc, iDst=0;
+    int iDst = 0;
 
-    for( iSrc = 0; iSrc < nLen; iSrc++ )
+    for( int iSrc = 0; iSrc < nLen; iSrc++ )
     {
         if( pabyData[iSrc] < 40 || pabyData[iSrc] > 126
             || pabyData[iSrc] == '\\' )
@@ -1753,11 +1729,9 @@ char* OGRPGLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
 char *OGRPGLayer::GeometryToBYTEA( OGRGeometry * poGeometry, int nPostGISMajor, int nPostGISMinor )
 
 {
-    int         nWkbSize = poGeometry->WkbSize();
-    GByte       *pabyWKB;
-    char        *pszTextBuf;
+    const int nWkbSize = poGeometry->WkbSize();
 
-    pabyWKB = (GByte *) CPLMalloc(nWkbSize);
+    GByte *pabyWKB = (GByte *) CPLMalloc(nWkbSize);
     if( (nPostGISMajor > 2 || (nPostGISMajor == 2 && nPostGISMinor >= 2)) &&
         wkbFlatten(poGeometry->getGeometryType()) == wkbPoint &&
         poGeometry->IsEmpty() )
@@ -1775,7 +1749,7 @@ char *OGRPGLayer::GeometryToBYTEA( OGRGeometry * poGeometry, int nPostGISMajor,
         return CPLStrdup("");
     }
 
-    pszTextBuf = GByteArrayToBYTEA( pabyWKB, nWkbSize );
+    char *pszTextBuf = GByteArrayToBYTEA( pabyWKB, nWkbSize );
     CPLFree(pabyWKB);
 
     return pszTextBuf;
@@ -1788,27 +1762,25 @@ char *OGRPGLayer::GeometryToBYTEA( OGRGeometry * poGeometry, int nPostGISMajor,
 OGRGeometry *OGRPGLayer::OIDToGeometry( Oid oid )
 
 {
-    PGconn      *hPGConn = poDS->GetPGConn();
-    GByte       *pabyWKB;
-    int         fd, nBytes;
-    OGRGeometry *poGeometry;
-
-#define MAX_WKB 500000
-
     if( oid == 0 )
         return NULL;
 
-    fd = lo_open( hPGConn, oid, INV_READ );
+    PGconn *hPGConn = poDS->GetPGConn();
+    const int fd = lo_open( hPGConn, oid, INV_READ );
     if( fd < 0 )
         return NULL;
 
-    pabyWKB = (GByte *) CPLMalloc(MAX_WKB);
-    nBytes = lo_read( hPGConn, fd, (char *) pabyWKB, MAX_WKB );
+    static const int MAX_WKB = 500000;
+    GByte *pabyWKB = (GByte *) CPLMalloc(MAX_WKB);
+    const int nBytes = lo_read( hPGConn, fd, (char *) pabyWKB, MAX_WKB );
     lo_close( hPGConn, fd );
 
-    poGeometry = NULL;
-    OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeometry, nBytes,
-                                       (poDS->sPostGISVersion.nMajor < 2) ? wkbVariantPostGIS1 : wkbVariantOldOgc );
+    OGRGeometry *poGeometry = NULL;
+    OGRGeometryFactory::createFromWkb(
+        pabyWKB, NULL, &poGeometry, nBytes,
+        poDS->sPostGISVersion.nMajor < 2
+        ? wkbVariantPostGIS1
+        : wkbVariantOldOgc );
 
     CPLFree( pabyWKB );
 
@@ -1822,21 +1794,18 @@ OGRGeometry *OGRPGLayer::OIDToGeometry( Oid oid )
 Oid OGRPGLayer::GeometryToOID( OGRGeometry * poGeometry )
 
 {
-    PGconn      *hPGConn = poDS->GetPGConn();
-    int         nWkbSize = poGeometry->WkbSize();
-    GByte       *pabyWKB;
-    Oid         oid;
-    int         fd, nBytesWritten;
+    PGconn *hPGConn = poDS->GetPGConn();
+    const int nWkbSize = poGeometry->WkbSize();
 
-    pabyWKB = (GByte *) CPLMalloc(nWkbSize);
+    GByte *pabyWKB = (GByte *) CPLMalloc(nWkbSize);
     if( poGeometry->exportToWkb( wkbNDR, pabyWKB,
                                  (poDS->sPostGISVersion.nMajor < 2) ? wkbVariantPostGIS1 : wkbVariantOldOgc ) != OGRERR_NONE )
         return 0;
 
-    oid = lo_creat( hPGConn, INV_READ|INV_WRITE );
+    Oid oid = lo_creat( hPGConn, INV_READ|INV_WRITE );
 
-    fd = lo_open( hPGConn, oid, INV_WRITE );
-    nBytesWritten = lo_write( hPGConn, fd, (char *) pabyWKB, nWkbSize );
+    const int fd = lo_open( hPGConn, oid, INV_WRITE );
+    const int nBytesWritten = lo_write( hPGConn, fd, (char *) pabyWKB, nWkbSize );
     lo_close( hPGConn, fd );
 
     if( nBytesWritten != nWkbSize )
@@ -1921,11 +1890,8 @@ OGRErr OGRPGLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce
     OGRPGGeomFieldDefn* poGeomFieldDefn =
         poFeatureDefn->myGetGeomFieldDefn(iGeomField);
 
-    const char* pszExtentFct;
-    if (poDS->sPostGISVersion.nMajor >= 2)
-        pszExtentFct = "ST_Extent";
-    else
-        pszExtentFct = "Extent";
+    const char* pszExtentFct =
+        poDS->sPostGISVersion.nMajor >= 2 ? "ST_Extent" : "Extent";
 
     if ( TestCapability(OLCFastGetExtent) )
     {
@@ -1944,7 +1910,7 @@ OGRErr OGRPGLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce
                           GetFromClauseForGetExtent().c_str() );
     }
 
-    if( osCommand.size() != 0 )
+    if( !osCommand.empty() )
     {
         if( RunGetExtentRequest(psExtent, bForce, osCommand, FALSE) == OGRERR_NONE )
             return OGRERR_NONE;
diff --git a/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp b/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
index 87cc9bc..6d55cd4 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgresultlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGResultLayer class, access the resultset from
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "ogr_pg.h"
 
-CPL_CVSID("$Id: ogrpgresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrpgresultlayer.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 #define PQexec this_is_an_error
 
@@ -42,30 +41,29 @@ CPL_CVSID("$Id: ogrpgresultlayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
                                     const char * pszRawQueryIn,
-                                    PGresult *hInitialResultIn )
+                                    PGresult *hInitialResultIn ) :
+    pszRawStatement(CPLStrdup(pszRawQueryIn)),
+    pszGeomTableName(NULL),
+    pszGeomTableSchemaName(NULL),
+    osWHERE("")
 {
     poDS = poDSIn;
 
     iNextShapeId = 0;
 
-    pszRawStatement = CPLStrdup(pszRawQueryIn);
-
-    osWHERE = "";
-
     BuildFullQueryStatement();
 
     ReadResultDefinition(hInitialResultIn);
 
-    pszGeomTableName = NULL;
-    pszGeomTableSchemaName = NULL;
-
     /* Find at which index the geometry column is */
     /* and prepare a request to identify not-nullable fields */
     int iGeomCol = -1;
     CPLString osRequest;
     std::map< std::pair<int,int>, int> oMapAttributeToFieldIndex;
 
-    for( int iRawField = 0; iRawField < PQnfields(hInitialResultIn); iRawField++ )
+    for( int iRawField = 0;
+         iRawField < PQnfields(hInitialResultIn);
+         iRawField++ )
     {
         if( poFeatureDefn->GetGeomFieldCount() == 1 &&
             strcmp(PQfname(hInitialResultIn,iRawField),
@@ -78,7 +76,7 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
         int tableCol = PQftablecol(hInitialResultIn, iRawField);
         if( tableOID != InvalidOid && tableCol > 0 )
         {
-            if( osRequest.size() )
+            if( !osRequest.empty() )
                 osRequest += " OR ";
             osRequest += "(attrelid = ";
             osRequest += CPLSPrintf("%d", tableOID);
@@ -88,7 +86,7 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
         }
     }
 
-    if( osRequest.size() )
+    if( !osRequest.empty() )
     {
         osRequest = "SELECT attnum, attrelid FROM pg_attribute WHERE attnotnull = 't' AND (" + osRequest + ")";
         PGresult* hResult = OGRPG_PQexec(poDS->GetPGConn(), osRequest );
@@ -115,7 +113,6 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
         OGRPGClearResult( hResult );
     }
 
-#ifndef PG_PRE74
     /* Determine the table from which the geometry column is extracted */
     if (iGeomCol != -1)
     {
@@ -137,7 +134,6 @@ OGRPGResultLayer::OGRPGResultLayer( OGRPGDataSource *poDSIn,
             OGRPGClearResult( hTableNameResult );
         }
     }
-#endif
 }
 
 /************************************************************************/
@@ -152,7 +148,6 @@ OGRPGResultLayer::~OGRPGResultLayer()
     CPLFree( pszGeomTableSchemaName );
 }
 
-
 /************************************************************************/
 /*                      BuildFullQueryStatement()                       */
 /************************************************************************/
@@ -166,10 +161,10 @@ void OGRPGResultLayer::BuildFullQueryStatement()
         pszQueryStatement = NULL;
     }
 
-    const size_t nLen = strlen(pszRawStatement) + strlen(osWHERE) + 40;
+    const size_t nLen = strlen(pszRawStatement) + osWHERE.size() + 40;
     pszQueryStatement = (char*) CPLMalloc(nLen);
 
-    if (strlen(osWHERE) == 0)
+    if (osWHERE.empty())
         strcpy(pszQueryStatement, pszRawStatement);
     else
         snprintf(pszQueryStatement, nLen, "SELECT * FROM (%s) AS ogrpgsubquery %s",
@@ -215,7 +210,6 @@ GIntBig OGRPGResultLayer::GetFeatureCount( int bForce )
     return nCount;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -264,7 +258,6 @@ int OGRPGResultLayer::TestCapability( const char * pszCap )
         return FALSE;
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -278,9 +271,7 @@ OGRFeature *OGRPGResultLayer::GetNextFeature()
 
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -358,7 +349,6 @@ void OGRPGResultLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn
 
         ResetReading();
     }
-
 }
 
 /************************************************************************/
@@ -397,11 +387,8 @@ void OGRPGResultLayer::ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn)
         {
             CPLString osGetSRID;
 
-            const char* psGetSRIDFct;
-            if (poDS->sPostGISVersion.nMajor >= 2)
-                psGetSRIDFct = "ST_SRID";
-            else
-                psGetSRIDFct = "getsrid";
+            const char* psGetSRIDFct =
+                poDS->sPostGISVersion.nMajor >= 2 ? "ST_SRID" : "getsrid";
 
             osGetSRID += "SELECT ";
             osGetSRID += psGetSRIDFct;
diff --git a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
index 62bce45..26865a0 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgtablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgtablelayer.cpp 35794 2016-10-17 19:29:48Z rouault $
 
  *
  * Project:  OpenGIS Simple Features Reference Implementation
@@ -37,8 +36,7 @@
 
 #define PQexec this_is_an_error
 
-CPL_CVSID("$Id: ogrpgtablelayer.cpp 35794 2016-10-17 19:29:48Z rouault $");
-
+CPL_CVSID("$Id: ogrpgtablelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 #define USE_COPY_UNSET  -10
 
@@ -62,32 +60,31 @@ class OGRPGTableFeatureDefn : public OGRPGFeatureDefn
         {
         }
 
-        virtual void UnsetLayer()
+        virtual void UnsetLayer() override
         {
             poLayer = NULL;
             OGRPGFeatureDefn::UnsetLayer();
         }
 
-        virtual int         GetFieldCount()
+        virtual int         GetFieldCount() override
             { SolveFields(); return OGRPGFeatureDefn::GetFieldCount(); }
-        virtual OGRFieldDefn *GetFieldDefn( int i )
+        virtual OGRFieldDefn *GetFieldDefn( int i ) override
             { SolveFields(); return OGRPGFeatureDefn::GetFieldDefn(i); }
-        virtual int         GetFieldIndex( const char * pszName )
+        virtual int         GetFieldIndex( const char * pszName ) override
             { SolveFields(); return OGRPGFeatureDefn::GetFieldIndex(pszName); }
 
-        virtual int         GetGeomFieldCount()
+        virtual int         GetGeomFieldCount() override
             { if (poLayer != NULL && !poLayer->HasGeometryInformation())
                   SolveFields();
               return OGRPGFeatureDefn::GetGeomFieldCount(); }
-        virtual OGRGeomFieldDefn *GetGeomFieldDefn( int i )
+        virtual OGRGeomFieldDefn *GetGeomFieldDefn( int i ) override
             { if (poLayer != NULL && !poLayer->HasGeometryInformation())
                   SolveFields();
               return OGRPGFeatureDefn::GetGeomFieldDefn(i); }
-        virtual int         GetGeomFieldIndex( const char * pszName)
+        virtual int         GetGeomFieldIndex( const char * pszName) override
             { if (poLayer != NULL && !poLayer->HasGeometryInformation())
                   SolveFields();
               return OGRPGFeatureDefn::GetGeomFieldIndex(pszName); }
-
 };
 
 /************************************************************************/
@@ -127,56 +124,58 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
                                   const char * pszSchemaNameIn,
                                   const char * pszDescriptionIn,
                                   const char * pszGeomColForcedIn,
-                                  int bUpdate )
-
+                                  int bUpdate ) :
+    bUpdateAccess(bUpdate),
+    pszTableName(CPLStrdup(pszTableNameIn)),
+    pszSchemaName(CPLStrdup(pszSchemaNameIn ?
+                            pszSchemaNameIn : osCurrentSchema.c_str())),
+    pszDescription(pszDescriptionIn ? CPLStrdup(pszDescriptionIn) : NULL),
+    pszSqlTableName(NULL),
+    bTableDefinitionValid(-1),
+    osPrimaryKey(CPLGetConfigOption( "PGSQL_OGR_FID", "ogc_fid" )),
+    bGeometryInformationSet(FALSE),
+    pszSqlGeomParentTableName(NULL),
+    pszGeomColForced(pszGeomColForcedIn ? CPLStrdup(pszGeomColForcedIn) : NULL),
+    bLaunderColumnNames(TRUE),
+    bPreservePrecision(TRUE),
+    bUseCopy(USE_COPY_UNSET),  // unknown
+    bCopyActive(FALSE),
+    bFIDColumnInCopyFields(FALSE),
+    bFirstInsertion(TRUE),
+    bHasWarnedIncompatibleGeom(FALSE),
+    // Just in provision for people yelling about broken backward compatibility.
+    bRetrieveFID(CPLTestBool(
+        CPLGetConfigOption("OGR_PG_RETRIEVE_FID", "TRUE"))),
+    bHasWarnedAlreadySetFID(FALSE),
+    papszOverrideColumnTypes(NULL),
+    nForcedSRSId(UNDETERMINED_SRID),
+    nForcedGeometryTypeFlags(-1),
+    bCreateSpatialIndexFlag(TRUE),
+    bInResetReading(FALSE),
+    bAutoFIDOnCreateViaCopy(FALSE),
+    bUseCopyByDefault(FALSE),
+    bDeferredCreation(FALSE),
+    iFIDAsRegularColumnIndex(-1)
 {
     poDS = poDSIn;
-
     pszQueryStatement = NULL;
 
-    bUpdateAccess = bUpdate;
-
-    bGeometryInformationSet = FALSE;
-
-    bLaunderColumnNames = TRUE;
-    bPreservePrecision = TRUE;
-    bCopyActive = FALSE;
-    bUseCopy = USE_COPY_UNSET;  // unknown
-    bUseCopyByDefault = FALSE;
-    bFIDColumnInCopyFields = FALSE;
-    bFirstInsertion = TRUE;
-
-    pszTableName = CPLStrdup( pszTableNameIn );
-    if (pszSchemaNameIn)
-        pszSchemaName = CPLStrdup( pszSchemaNameIn );
-    else
-        pszSchemaName = CPLStrdup( osCurrentSchema );
-    this->pszGeomColForced =
-        pszGeomColForcedIn ? CPLStrdup(pszGeomColForcedIn) : NULL;
-
-    pszSqlGeomParentTableName = NULL;
-    bTableDefinitionValid = -1;
-
-    bHasWarnedIncompatibleGeom = FALSE;
-    bHasWarnedAlreadySetFID = FALSE;
-
-    /* Just in provision for people yelling about broken backward compatibility ... */
-    bRetrieveFID = CPLTestBool(CPLGetConfigOption("OGR_PG_RETRIEVE_FID", "TRUE"));
-
 /* -------------------------------------------------------------------- */
 /*      Build the layer defn name.                                      */
 /* -------------------------------------------------------------------- */
     CPLString osDefnName;
-    if ( pszSchemaNameIn && osCurrentSchema != pszSchemaNameIn )
+    if( pszSchemaNameIn && osCurrentSchema != pszSchemaNameIn )
     {
         osDefnName.Printf("%s.%s", pszSchemaNameIn, pszTableName );
-        pszSqlTableName = CPLStrdup(CPLString().Printf("%s.%s",
+        pszSqlTableName = CPLStrdup(
+            CPLString().Printf("%s.%s",
                                OGRPGEscapeColumnName(pszSchemaNameIn).c_str(),
                                OGRPGEscapeColumnName(pszTableName).c_str() ));
     }
     else
     {
-        //no prefix for current_schema in layer name, for backwards compatibility
+        // no prefix for current_schema in layer name, for backwards
+        // compatibility.
         osDefnName = pszTableName;
         pszSqlTableName = CPLStrdup(OGRPGEscapeColumnName(pszTableName));
     }
@@ -187,24 +186,10 @@ OGRPGTableLayer::OGRPGTableLayer( OGRPGDataSource *poDSIn,
         osDefnName += ")";
     }
 
-    osPrimaryKey = CPLGetConfigOption( "PGSQL_OGR_FID", "ogc_fid" );
-
-    papszOverrideColumnTypes = NULL;
-    nForcedSRSId = UNDETERMINED_SRID;
-    nForcedGeometryTypeFlags = -1;
-    bCreateSpatialIndexFlag = TRUE;
-    bInResetReading = FALSE;
-
     poFeatureDefn = new OGRPGTableFeatureDefn( this, osDefnName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
 
-    bAutoFIDOnCreateViaCopy = FALSE;
-
-    bDeferredCreation = FALSE;
-    iFIDAsRegularColumnIndex = -1;
-
-    pszDescription = (pszDescriptionIn) ? CPLStrdup(pszDescriptionIn) : NULL;
     if( pszDescriptionIn != NULL && !EQUAL(pszDescriptionIn, "") )
     {
         OGRLayer::SetMetadataItem("DESCRIPTION", pszDescriptionIn);
@@ -219,7 +204,7 @@ OGRPGTableLayer::~OGRPGTableLayer()
 
 {
     if( bDeferredCreation ) RunDeferredCreationIfNecessary();
-    if ( bCopyActive ) EndCopy();
+    if( bCopyActive ) EndCopy();
     CPLFree( pszSqlTableName );
     CPLFree( pszTableName );
     CPLFree( pszSqlGeomParentTableName );
@@ -296,7 +281,7 @@ const char *OGRPGTableLayer::GetMetadataItem(const char* pszName, const char* ps
 CPLErr OGRPGTableLayer::SetMetadata(char** papszMD, const char* pszDomain)
 {
     OGRLayer::SetMetadata(papszMD, pszDomain);
-    if( osForcedDescription.size() && (pszDomain == NULL || EQUAL(pszDomain, "")) )
+    if( !osForcedDescription.empty() && (pszDomain == NULL || EQUAL(pszDomain, "")) )
     {
         OGRLayer::SetMetadataItem("DESCRIPTION", osForcedDescription);
     }
@@ -329,7 +314,7 @@ CPLErr OGRPGTableLayer::SetMetadataItem(const char* pszName, const char* pszValu
                                         const char* pszDomain)
 {
     if( (pszDomain == NULL || EQUAL(pszDomain, "")) && pszName != NULL &&
-        EQUAL(pszName, "DESCRIPTION") && osForcedDescription.size() )
+        EQUAL(pszName, "DESCRIPTION") && !osForcedDescription.empty() )
     {
         pszValue = osForcedDescription;
     }
@@ -386,7 +371,6 @@ void  OGRPGTableLayer::SetGeometryInformation(PGGeomColumnDesc* pasDesc,
     }
 }
 
-
 /************************************************************************/
 /*                        ReadTableDefinition()                         */
 /*                                                                      */
@@ -397,9 +381,7 @@ void  OGRPGTableLayer::SetGeometryInformation(PGGeomColumnDesc* pasDesc,
 int OGRPGTableLayer::ReadTableDefinition()
 
 {
-    PGresult            *hResult;
-    CPLString           osCommand;
-    PGconn              *hPGConn = poDS->GetPGConn();
+    PGconn *hPGConn = poDS->GetPGConn();
 
     if( bTableDefinitionValid >= 0 )
         return bTableDefinitionValid;
@@ -411,26 +393,27 @@ int OGRPGTableLayer::ReadTableDefinition()
     osSchemaClause.Printf("AND n.nspname=%s",
                               OGRPGEscapeString(hPGConn, pszSchemaName).c_str());
 
-    const char* pszTypnameEqualsAnyClause;
-    if (poDS->sPostgreSQLVersion.nMajor == 7 && poDS->sPostgreSQLVersion.nMinor <= 3)
-        pszTypnameEqualsAnyClause = "ANY(SELECT '{int2, int4, int8, serial, bigserial}')";
-    else
-        pszTypnameEqualsAnyClause = "ANY(ARRAY['int2','int4','int8','serial','bigserial'])";
-
-    const char* pszAttnumEqualAnyIndkey;
-    if( poDS->sPostgreSQLVersion.nMajor > 8 || (
-        poDS->sPostgreSQLVersion.nMajor == 8 && poDS->sPostgreSQLVersion.nMinor >= 2) )
-        pszAttnumEqualAnyIndkey = "a.attnum = ANY(i.indkey)";
-    else
-        pszAttnumEqualAnyIndkey = "(i.indkey[0]=a.attnum OR i.indkey[1]=a.attnum OR i.indkey[2]=a.attnum "
-              "OR i.indkey[3]=a.attnum OR i.indkey[4]=a.attnum OR i.indkey[5]=a.attnum "
-              "OR i.indkey[6]=a.attnum OR i.indkey[7]=a.attnum OR i.indkey[8]=a.attnum "
-              "OR i.indkey[9]=a.attnum)";
+    const char* pszTypnameEqualsAnyClause =
+        poDS->sPostgreSQLVersion.nMajor == 7 &&
+        poDS->sPostgreSQLVersion.nMinor <= 3
+        ? "ANY(SELECT '{int2, int4, int8, serial, bigserial}')"
+        : "ANY(ARRAY['int2','int4','int8','serial','bigserial'])";
+
+    const char* pszAttnumEqualAnyIndkey =
+        poDS->sPostgreSQLVersion.nMajor > 8 ||
+        (poDS->sPostgreSQLVersion.nMajor == 8 &&
+         poDS->sPostgreSQLVersion.nMinor >= 2)
+        ? "a.attnum = ANY(i.indkey)"
+        : "(i.indkey[0]=a.attnum OR i.indkey[1]=a.attnum OR i.indkey[2]=a.attnum "
+        "OR i.indkey[3]=a.attnum OR i.indkey[4]=a.attnum OR i.indkey[5]=a.attnum "
+        "OR i.indkey[6]=a.attnum OR i.indkey[7]=a.attnum OR i.indkey[8]=a.attnum "
+        "OR i.indkey[9]=a.attnum)";
 
     CPLString osEscapedTableNameSingleQuote = OGRPGEscapeString(hPGConn, pszTableName);
     const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
 
     /* See #1889 for why we don't use 'AND a.attnum = ANY(i.indkey)' */
+    CPLString osCommand;
     osCommand.Printf("SELECT a.attname, a.attnum, t.typname, "
               "t.typname = %s AS isfid "
               "FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n, pg_index i "
@@ -442,7 +425,7 @@ int OGRPGTableLayer::ReadTableDefinition()
               pszTypnameEqualsAnyClause, pszEscapedTableNameSingleQuote,
               pszAttnumEqualAnyIndkey, osSchemaClause.c_str() );
 
-    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
+    PGresult *hResult = OGRPG_PQexec(hPGConn, osCommand.c_str() );
 
     if ( hResult && PGRES_TUPLES_OK == PQresultStatus(hResult) )
     {
@@ -775,7 +758,9 @@ void OGRPGTableLayer::SetTableDefinition(const char* pszFIDColumnName,
         poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
     }
     else if( pszGFldName != NULL )
+    {
         m_osFirstGeometryFieldName = pszGFldName;
+    }
 }
 
 /************************************************************************/
@@ -849,9 +834,9 @@ void OGRPGTableLayer::BuildWhere()
                        szBox3D_1, szBox3D_2, poGeomFieldDefn->nSRSId );
     }
 
-    if( strlen(osQuery) > 0 )
+    if( !osQuery.empty() )
     {
-        if( strlen(osWHERE) == 0 )
+        if( osWHERE.empty() )
         {
             osWHERE.Printf( "WHERE %s ", osQuery.c_str()  );
         }
@@ -878,10 +863,10 @@ void OGRPGTableLayer::BuildFullQueryStatement()
         pszQueryStatement = NULL;
     }
     pszQueryStatement = (char *)
-        CPLMalloc(strlen(osFields)+strlen(osWHERE)
+        CPLMalloc(osFields.size()+osWHERE.size()
                   +strlen(pszSqlTableName) + 40);
     snprintf( pszQueryStatement,
-              strlen(osFields)+strlen(osWHERE)
+              osFields.size()+osWHERE.size()
                   +strlen(pszSqlTableName) + 40,
              "SELECT %s FROM %s %s",
              osFields.c_str(), pszSqlTableName, osWHERE.c_str() );
@@ -933,9 +918,7 @@ OGRFeature *OGRPGTableLayer::GetNextFeature()
 
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -987,7 +970,7 @@ CPLString OGRPGTableLayer::BuildFields()
         CPLString osEscapedGeom =
             OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef());
 
-        if( osFieldList.size() > 0 )
+        if( !osFieldList.empty() )
             osFieldList += ", ";
 
         if( poGeomFieldDefn->ePostgisType == GEOM_TYPE_GEOMETRY )
@@ -1025,7 +1008,6 @@ CPLString OGRPGTableLayer::BuildFields()
                 osFieldList += ") AS ";
                 osFieldList += OGRPGEscapeColumnName(
                     CPLSPrintf("AsEWKT_%s", poGeomFieldDefn->GetNameRef()));
-
             }
             else
             {
@@ -1080,7 +1062,7 @@ CPLString OGRPGTableLayer::BuildFields()
     {
         const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
 
-        if( osFieldList.size() > 0 )
+        if( !osFieldList.empty() )
             osFieldList += ", ";
 
 #if defined(BINARY_CURSOR_ENABLED)
@@ -1162,7 +1144,6 @@ OGRErr OGRPGTableLayer::DeleteFeature( GIntBig nFID )
                   "a recognised FID column.",
                   nFID );
         return OGRERR_FAILURE;
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -1249,13 +1230,12 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
                   "Unable to update features in tables without\n"
                   "a recognised FID column.");
         return eErr;
-
     }
 
     /* In case the FID column has also been created as a regular field */
     if( iFIDAsRegularColumnIndex >= 0 )
     {
-        if( !poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) ||
+        if( !poFeature->IsFieldSetAndNotNull( iFIDAsRegularColumnIndex ) ||
             poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex) != poFeature->GetFID() )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -1345,7 +1325,7 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
                         osCommand += CPLString().Printf("'%s'::GEOGRAPHY", pszHexEWKB);
                     else
                         osCommand += CPLString().Printf("'%s'::GEOMETRY", pszHexEWKB);
-                    OGRFree( pszHexEWKB );
+                    CPLFree( pszHexEWKB );
                 }
                 else
                     osCommand += "NULL";
@@ -1372,11 +1352,10 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
                         osCommand +=
                             CPLString().Printf(
                                 "GeometryFromText('%s'::TEXT,%d) ", pszWKT, nSRSId );
-                    OGRFree( pszWKT );
+                    CPLFree( pszWKT );
                 }
                 else
                     osCommand += "NULL";
-
             }
         }
     }
@@ -1385,6 +1364,8 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
     {
         if( iFIDAsRegularColumnIndex == i )
             continue;
+        if( !poFeature->IsFieldSet(i) )
+            continue;
         if( bNeedComma )
             osCommand += ", ";
         else
@@ -1393,7 +1374,7 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
         osCommand = osCommand
             + OGRPGEscapeColumnName(poFeatureDefn->GetFieldDefn(i)->GetNameRef()) + " = ";
 
-        if( !poFeature->IsFieldSet( i ) )
+        if( poFeature->IsFieldNull( i ) )
         {
             osCommand += "NULL";
         }
@@ -1403,6 +1384,8 @@ OGRErr OGRPGTableLayer::ISetFeature( OGRFeature *poFeature )
                                         (OGRPGCommonEscapeStringCbk)OGRPGEscapeString, hPGConn);
         }
     }
+    if( !bNeedComma ) // nothing to do
+        return OGRERR_NONE;
 
     /* Add the WHERE clause */
     osCommand += " WHERE ";
@@ -1466,7 +1449,7 @@ OGRErr OGRPGTableLayer::ICreateFeature( OGRFeature *poFeature )
     {
         if( nFID == OGRNullFID )
         {
-            if( poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) )
+            if( poFeature->IsFieldSetAndNotNull( iFIDAsRegularColumnIndex ) )
             {
                 poFeature->SetFID(
                     poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex));
@@ -1474,7 +1457,7 @@ OGRErr OGRPGTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
         else
         {
-            if( !poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) ||
+            if( !poFeature->IsFieldSetAndNotNull( iFIDAsRegularColumnIndex ) ||
                 poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex) != nFID )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
@@ -1518,12 +1501,11 @@ OGRErr OGRPGTableLayer::ICreateFeature( OGRFeature *poFeature )
         bFirstInsertion = FALSE;
         if( CPLTestBool(CPLGetConfigOption("OGR_TRUNCATE", "NO")) )
         {
-            PGconn              *hPGConn = poDS->GetPGConn();
-            PGresult            *hResult;
-            CPLString            osCommand;
+            PGconn *hPGConn = poDS->GetPGConn();
+            CPLString osCommand;
 
             osCommand.Printf("TRUNCATE TABLE %s", pszSqlTableName );
-            hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
+            PGresult *hResult = OGRPG_PQexec( hPGConn, osCommand.c_str() );
             OGRPGClearResult( hResult );
         }
     }
@@ -1636,7 +1618,6 @@ CPLString OGRPGEscapeString(PGconn *hPGConn,
     /* We need to quote and escape string fields. */
     osCommand += "'";
 
-
     int nSrcLen = static_cast<int>(strlen(pszStrValue));
     int nSrcLenUTF = CPLStrlenUTF8(pszStrValue);
 
@@ -1663,13 +1644,6 @@ CPLString OGRPGEscapeString(PGconn *hPGConn,
 
     char* pszDestStr = (char*)CPLMalloc(2 * nSrcLen + 1);
 
-    /* -------------------------------------------------------------------- */
-    /*  PQescapeStringConn was introduced in PostgreSQL security releases   */
-    /*  8.1.4, 8.0.8, 7.4.13, 7.3.15                                        */
-    /*  PG_HAS_PQESCAPESTRINGCONN is added by a test in 'configure'         */
-    /*  so it is not set by default when building OGR for Win32             */
-    /* -------------------------------------------------------------------- */
-#if defined(PG_HAS_PQESCAPESTRINGCONN)
     int nError;
     PQescapeStringConn (hPGConn, pszDestStr, pszStrValue, nSrcLen, &nError);
     if (nError == 0)
@@ -1681,10 +1655,7 @@ CPLString OGRPGEscapeString(PGconn *hPGConn,
                  "    got: '%s'\n",
                  PQerrorMessage( hPGConn ),
                  pszStrValue, pszDestStr );
-#else
-    PQescapeString(pszDestStr, pszStrValue, nSrcLen);
-    osCommand += pszDestStr;
-#endif
+
     CPLFree(pszDestStr);
 
     osCommand += "'";
@@ -1700,7 +1671,6 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 
 {
     PGconn              *hPGConn = poDS->GetPGConn();
-    PGresult            *hResult;
     CPLString           osCommand;
     int                 i;
     int                 bNeedComma = FALSE;
@@ -1794,7 +1764,7 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
                     osCommand += CPLString().Printf("'%s'::GEOGRAPHY", pszHexEWKB);
                 else
                     osCommand += CPLString().Printf("'%s'::GEOMETRY", pszHexEWKB);
-                OGRFree( pszHexEWKB );
+                CPLFree( pszHexEWKB );
             }
             else
             {
@@ -1815,11 +1785,10 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
                         osCommand +=
                             CPLString().Printf(
                                 "GeometryFromText('%s'::TEXT,%d) ", pszWKT, nSRSId );
-                    OGRFree( pszWKT );
+                    CPLFree( pszWKT );
                 }
                 else
                     osCommand += "''";
-
             }
         }
         else if( !bWkbAsOid )
@@ -1860,7 +1829,6 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
         bNeedComma = TRUE;
     }
 
-
     for( i = 0; i < nFieldCount; i++ )
     {
         if( iFIDAsRegularColumnIndex == i )
@@ -1898,7 +1866,7 @@ OGRErr OGRPGTableLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Execute the insert.                                             */
 /* -------------------------------------------------------------------- */
-    hResult = OGRPG_PQexec(hPGConn, osCommand);
+    PGresult *hResult = OGRPG_PQexec(hPGConn, osCommand);
     if (bReturnRequested && PQresultStatus(hResult) == PGRES_TUPLES_OK &&
         PQntuples(hResult) == 1 && PQnfields(hResult) == 1 )
     {
@@ -1971,7 +1939,7 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
                                                 poDS->sPostGISVersion.nMinor );
         }
 
-        if (osCommand.size() > 0)
+        if (!osCommand.empty())
             osCommand += "\t";
 
         if ( pszGeom )
@@ -1988,24 +1956,21 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
     OGRPGCommonAppendCopyFieldsExceptGeom(osCommand,
                                           poFeature,
                                           pszFIDColumn,
-                                          bFIDColumnInCopyFields,
+                                          CPL_TO_BOOL(bFIDColumnInCopyFields),
                                           (OGRPGCommonEscapeStringCbk)OGRPGEscapeString,
                                           hPGConn);
 
     /* Add end of line marker */
     osCommand += "\n";
 
-
     /* ------------------------------------------------------------ */
     /*      Execute the copy.                                       */
     /* ------------------------------------------------------------ */
 
     OGRErr result = OGRERR_NONE;
 
-    /* This is for postgresql  7.4 and higher */
-#if !defined(PG_PRE74)
     int copyResult = PQputCopyData(hPGConn, osCommand.c_str(),
-                                   static_cast<int>(strlen(osCommand.c_str())));
+                                   static_cast<int>(osCommand.size()));
 #ifdef DEBUG_VERBOSE
     CPLDebug("PG", "PQputCopyData(%s)", osCommand.c_str());
 #endif
@@ -2021,20 +1986,10 @@ OGRErr OGRPGTableLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
         result = OGRERR_FAILURE;
         break;
     }
-#else /* else defined(PG_PRE74) */
-    int copyResult = PQputline(hPGConn, osCommand.c_str());
-
-    if (copyResult == EOF)
-    {
-      CPLError( CE_Failure, CPLE_AppDefined, "Writing COPY data blocked.");
-      result = OGRERR_FAILURE;
-    }
-#endif /* end of defined(PG_PRE74) */
 
     return result;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -2168,14 +2123,15 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
         }
     }
 
-
     const char* pszOverrideType = CSLFetchNameValue(papszOverrideColumnTypes, oField.GetNameRef());
     if( pszOverrideType != NULL )
         osFieldType = pszOverrideType;
     else
     {
-        osFieldType = OGRPGCommonLayerGetType(oField, bPreservePrecision, bApproxOK);
-        if (osFieldType.size() == 0)
+        osFieldType = OGRPGCommonLayerGetType(oField,
+                                              CPL_TO_BOOL(bPreservePrecision),
+                                              CPL_TO_BOOL(bApproxOK));
+        if (osFieldType.empty())
             return OGRERR_FAILURE;
     }
 
@@ -2238,16 +2194,13 @@ OGRErr OGRPGTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                        RunAddGeometryColumn()                        */
 /************************************************************************/
 
 OGRErr OGRPGTableLayer::RunAddGeometryColumn( OGRPGGeomFieldDefn *poGeomField )
 {
-    PGconn              *hPGConn = poDS->GetPGConn();
-    PGresult            *hResult;
-    CPLString            osCommand;
+    PGconn *hPGConn = poDS->GetPGConn();
 
     const char *pszGeometryType = OGRToOGCGeomType(poGeomField->GetType());
     const char *suffix = "";
@@ -2264,6 +2217,7 @@ OGRErr OGRPGTableLayer::RunAddGeometryColumn( OGRPGGeomFieldDefn *poGeomField )
     else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D )
         dim = 3;
 
+    CPLString osCommand;
     osCommand.Printf(
             "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s%s',%d)",
             OGRPGEscapeString(hPGConn, pszSchemaName).c_str(),
@@ -2271,7 +2225,7 @@ OGRErr OGRPGTableLayer::RunAddGeometryColumn( OGRPGGeomFieldDefn *poGeomField )
             OGRPGEscapeString(hPGConn, poGeomField->GetNameRef()).c_str(),
             poGeomField->nSRSId, pszGeometryType, suffix, dim );
 
-    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+    PGresult *hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
     if( !hResult
         || PQresultStatus(hResult) != PGRES_TUPLES_OK )
@@ -2299,16 +2253,14 @@ OGRErr OGRPGTableLayer::RunAddGeometryColumn( OGRPGGeomFieldDefn *poGeomField )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                        RunCreateSpatialIndex()                       */
 /************************************************************************/
 
 OGRErr OGRPGTableLayer::RunCreateSpatialIndex( OGRPGGeomFieldDefn *poGeomField )
 {
-    PGconn              *hPGConn = poDS->GetPGConn();
-    PGresult            *hResult;
-    CPLString            osCommand;
+    PGconn *hPGConn = poDS->GetPGConn();
+    CPLString osCommand;
 
     osCommand.Printf("CREATE INDEX %s ON %s USING GIST (%s)",
                     OGRPGEscapeColumnName(
@@ -2316,7 +2268,7 @@ OGRErr OGRPGTableLayer::RunCreateSpatialIndex( OGRPGGeomFieldDefn *poGeomField )
                     pszSqlTableName,
                     OGRPGEscapeColumnName(poGeomField->GetNameRef()).c_str());
 
-    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+    PGresult *hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
 
     if( !hResult
         || PQresultStatus(hResult) != PGRES_COMMAND_OK )
@@ -2539,9 +2491,9 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
         (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG))
     {
         CPLString osFieldType = OGRPGCommonLayerGetType(oField,
-                                                       bPreservePrecision,
-                                                       TRUE);
-        if (osFieldType.size() == 0)
+                                                       CPL_TO_BOOL(bPreservePrecision),
+                                                       true);
+        if (osFieldType.empty())
         {
             poDS->SoftRollbackTransaction();
 
@@ -2697,7 +2649,6 @@ OGRErr OGRPGTableLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn
         poFieldDefn->SetDefault(oField.GetDefault());
 
     return OGRERR_NONE;
-
 }
 
 /************************************************************************/
@@ -2878,14 +2829,10 @@ void OGRPGTableLayer::ResolveSRID(OGRPGGeomFieldDefn* poGFldDefn)
     if( nSRSId <= 0 && poGFldDefn->ePostgisType == GEOM_TYPE_GEOMETRY &&
         poDS->sPostGISVersion.nMajor >= 0 )
     {
-        CPLString osGetSRID;
-
-        const char* psGetSRIDFct;
-        if (poDS->sPostGISVersion.nMajor >= 2)
-            psGetSRIDFct = "ST_SRID";
-        else
-            psGetSRIDFct = "getsrid";
+        const char* psGetSRIDFct
+            = poDS->sPostGISVersion.nMajor >= 2 ? "ST_SRID" : "getsrid";
 
+        CPLString osGetSRID;
         osGetSRID += "SELECT ";
         osGetSRID += psGetSRIDFct;
         osGetSRID += "(";
@@ -2919,7 +2866,7 @@ OGRErr OGRPGTableLayer::StartCopy()
 
     CPLString osFields = BuildCopyFields();
 
-    size_t size = strlen(osFields) +  strlen(pszSqlTableName) + 100;
+    size_t size = osFields.size() +  strlen(pszSqlTableName) + 100;
     char *pszCommand = (char *) CPLMalloc(size);
 
     snprintf( pszCommand, size,
@@ -2963,8 +2910,6 @@ OGRErr OGRPGTableLayer::EndCopy()
 
     bCopyActive = FALSE;
 
-    /* This is for postgresql 7.4 and higher */
-#if !defined(PG_PRE74)
     int copyResult = PQputCopyEnd(hPGConn, NULL);
 
     switch (copyResult)
@@ -2979,17 +2924,6 @@ OGRErr OGRPGTableLayer::EndCopy()
         break;
     }
 
-#else /* defined(PG_PRE74) */
-    PQputline(hPGConn, "\\.\n");
-    int copyResult = PQendcopy(hPGConn);
-
-    if (copyResult != 0)
-    {
-      CPLError( CE_Failure, CPLE_AppDefined, "%s", PQerrorMessage(hPGConn) );
-      result = OGRERR_FAILURE;
-    }
-#endif /* defined(PG_PRE74) */
-
     /* Now check the results of the copy */
     PGresult * hResult = PQgetResult( hPGConn );
 
@@ -3024,14 +2958,14 @@ CPLString OGRPGTableLayer::BuildCopyFields()
     {
         OGRGeomFieldDefn* poGeomFieldDefn =
             poFeatureDefn->myGetGeomFieldDefn(i);
-        if( osFieldList.size() > 0 )
+        if( !osFieldList.empty() )
             osFieldList += ", ";
         osFieldList += OGRPGEscapeColumnName(poGeomFieldDefn->GetNameRef());
     }
 
     if( bFIDColumnInCopyFields )
     {
-        if( osFieldList.size() > 0 )
+        if( !osFieldList.empty() )
             osFieldList += ", ";
 
         nFIDIndex = poFeatureDefn->GetFieldIndex( pszFIDColumn );
@@ -3046,7 +2980,7 @@ CPLString OGRPGTableLayer::BuildCopyFields()
 
         const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
 
-        if( osFieldList.size() > 0 )
+        if( !osFieldList.empty() )
             osFieldList += ", ";
 
         osFieldList += OGRPGEscapeColumnName(pszName);
@@ -3130,7 +3064,7 @@ void OGRPGTableLayer::SetOverrideColumnTypes( const char* pszOverrideColumnTypes
             osCur += *pszIter;
         pszIter ++;
     }
-    if( osCur.size() )
+    if( !osCur.empty() )
         papszOverrideColumnTypes = CSLAddString(papszOverrideColumnTypes, osCur);
 }
 
@@ -3163,7 +3097,6 @@ OGRErr OGRPGTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bF
     OGRPGGeomFieldDefn* poGeomFieldDefn =
         poFeatureDefn->myGetGeomFieldDefn(iGeomField);
 
-    const char* pszExtentFct;
     // if bForce is 0 and ePostgisType is not GEOM_TYPE_GEOGRAPHY we can use
     // the ST_EstimatedExtent function which is quicker
     // ST_EstimatedExtent was called ST_Estimated_Extent up to PostGIS 2.0.x
@@ -3171,13 +3104,13 @@ OGRErr OGRPGTableLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bF
     //   PostGIS 1.5.4)
     if ( bForce == 0 && TestCapability(OLCFastGetExtent) )
     {
-        PGconn              *hPGConn = poDS->GetPGConn();
+        PGconn *hPGConn = poDS->GetPGConn();
 
-        if ( poDS->sPostGISVersion.nMajor > 2 ||
-             ( poDS->sPostGISVersion.nMajor == 2 && poDS->sPostGISVersion.nMinor >= 1 ) )
-            pszExtentFct = "ST_EstimatedExtent";
-        else
-            pszExtentFct = "ST_Estimated_Extent";
+        const char* pszExtentFct =
+            poDS->sPostGISVersion.nMajor > 2 ||
+            ( poDS->sPostGISVersion.nMajor == 2 && poDS->sPostGISVersion.nMinor >= 1 )
+            ? "ST_EstimatedExtent"
+            : "ST_Estimated_Extent";
 
         osCommand.Printf( "SELECT %s(%s, %s, %s)",
                         pszExtentFct,
@@ -3256,10 +3189,9 @@ OGRErr OGRPGTableLayer::RunDeferredCreationIfNecessary()
     osCreateTable += " )";
     CPLString osCommand(osCreateTable);
 
-    PGresult            *hResult;
-    PGconn              *hPGConn = poDS->GetPGConn();
+    PGconn *hPGConn = poDS->GetPGConn();
 
-    hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
+    PGresult *hResult = OGRPG_PQexec(hPGConn, osCommand.c_str());
     if( PQresultStatus(hResult) != PGRES_COMMAND_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
diff --git a/ogr/ogrsf_frmts/pg/ogrpgutility.cpp b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
index 01c6add..6053239 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
+++ b/ogr/ogrsf_frmts/pg/ogrpgutility.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgutility.cpp 35632 2016-10-07 13:45:42Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Utility methods
@@ -30,7 +29,7 @@
 #include "ogr_pg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgutility.cpp 35632 2016-10-07 13:45:42Z rouault $");
+CPL_CVSID("$Id: ogrpgutility.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                         OGRPG_PQexec()                               */
@@ -39,21 +38,13 @@ CPL_CVSID("$Id: ogrpgutility.cpp 35632 2016-10-07 13:45:42Z rouault $");
 PGresult *OGRPG_PQexec(PGconn *conn, const char *query, int bMultipleCommandAllowed,
                        int bErrorAsDebug)
 {
-    PGresult* hResult;
-#if defined(PG_PRE74)
-    /* PQexecParams introduced in PG >= 7.4 */
-    hResult = PQexec(conn, query);
-#else
-    if (bMultipleCommandAllowed)
-        hResult = PQexec(conn, query);
-    else
-        hResult = PQexecParams(conn, query, 0, NULL, NULL, NULL, NULL, 0);
-#endif
+    PGresult* hResult = bMultipleCommandAllowed
+        ? PQexec(conn, query)
+        : PQexecParams(conn, query, 0, NULL, NULL, NULL, NULL, 0);
 
 #ifdef DEBUG
     const char* pszRetCode = "UNKNOWN";
-    char szNTuples[32];
-    szNTuples[0] = '\0';
+    char szNTuples[32] = {};
     if (hResult)
     {
         switch(PQresultStatus(hResult))
@@ -95,7 +86,6 @@ PGresult *OGRPG_PQexec(PGconn *conn, const char *query, int bMultipleCommandAllo
     return hResult;
 }
 
-
 /************************************************************************/
 /*                       OGRPG_Check_Table_Exists()                     */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/pg/ogrpgutility.h b/ogr/ogrsf_frmts/pg/ogrpgutility.h
index 5401909..0fd1521 100644
--- a/ogr/ogrsf_frmts/pg/ogrpgutility.h
+++ b/ogr/ogrsf_frmts/pg/ogrpgutility.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrpgutility.h 35632 2016-10-07 13:45:42Z rouault $
+ * $Id: ogrpgutility.h 35631 2016-10-07 13:45:32Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private utilities for OGR/PostgreSQL driver.
diff --git a/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h b/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
index 4711eb8..4fd69ee 100644
--- a/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
+++ b/ogr/ogrsf_frmts/pgdump/ogr_pgdump.h
@@ -1,219 +1,226 @@
-/******************************************************************************
- * $Id: ogr_pgdump.h 33639 2016-03-04 23:39:40Z rouault $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Private definitions for OGR/PostgreSQL dump driver.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#ifndef OGR_PGDUMP_H_INCLUDED
-#define OGR_PGDUMP_H_INCLUDED
-
-#include "ogrsf_frmts.h"
-#include "cpl_string.h"
-
-CPLString OGRPGDumpEscapeColumnName(const char* pszColumnName);
-CPLString OGRPGDumpEscapeString(   const char* pszStrValue, int nMaxLength = -1,
-                                   const char* pszFieldName = "");
-CPLString CPL_DLL OGRPGCommonLayerGetType(OGRFieldDefn& oField,
-                                          int bPreservePrecision,
-                                          int bApproxOK);
-int CPL_DLL OGRPGCommonLayerSetType(OGRFieldDefn& oField,
-                                    const char* pszType,
-                                    const char* pszFormatType,
-                                    int nWidth);
-void CPL_DLL OGRPGCommonLayerNormalizeDefault(OGRFieldDefn* poFieldDefn,
-                                              const char* pszDefault);
-CPLString CPL_DLL OGRPGCommonLayerGetPGDefault(OGRFieldDefn* poFieldDefn);
-
-typedef CPLString (*OGRPGCommonEscapeStringCbk)(void* userdata,
-                                                const char* pszValue, 
-                                                int nWidth,
-                                                const char* pszLayerName,
-                                                const char* pszFieldRef);
-void CPL_DLL OGRPGCommonAppendCopyFieldsExceptGeom(CPLString& osCommand,
-                                           OGRFeature* poFeature,
-                                           const char* pszFIDColumn,
-                                           int bFIDColumnInCopyFields,
-                                           OGRPGCommonEscapeStringCbk pfnEscapeString,
-                                           void* userdata);
-void CPL_DLL OGRPGCommonAppendFieldValue(CPLString& osCommand,
-                                 OGRFeature* poFeature, int i,
-                                 OGRPGCommonEscapeStringCbk pfnEscapeString,
-                                 void* userdata);
-
-char CPL_DLL *OGRPGCommonLaunderName( const char *pszSrcName,
-                                      const char* pszDebugPrefix = "OGR" );
-
-/************************************************************************/
-/*                        OGRPGDumpGeomFieldDefn                        */
-/************************************************************************/
-
-class OGRPGDumpGeomFieldDefn : public OGRGeomFieldDefn
-{
-    public:
-        OGRPGDumpGeomFieldDefn( OGRGeomFieldDefn *poGeomField ) :
-            OGRGeomFieldDefn(poGeomField), nSRSId(-1), GeometryTypeFlags(0)
-            {
-            }
-            
-        int nSRSId;
-        int GeometryTypeFlags;
-};
-
-/************************************************************************/
-/*                          OGRPGDumpLayer                              */
-/************************************************************************/
-
-
-class OGRPGDumpDataSource;
-
-class OGRPGDumpLayer : public OGRLayer
-{
-    char                *pszSchemaName;
-    char                *pszSqlTableName;
-    CPLString           osForcedDescription;
-    char                *pszFIDColumn;
-    OGRFeatureDefn      *poFeatureDefn;
-    OGRPGDumpDataSource *poDS;
-    int                 bLaunderColumnNames;
-    int                 bPreservePrecision;
-    int                 bUseCopy;
-    int                 bWriteAsHex;
-    int                 bCopyActive;
-    int                 bFIDColumnInCopyFields;
-    int                 bCreateTable;
-    int                 nUnknownSRSId;
-    int                 nForcedSRSId;
-    int                 nForcedGeometryTypeFlags;
-    int                 bCreateSpatialIndexFlag;
-    int                 nPostGISMajor;
-    int                 nPostGISMinor;
-
-    int                 iNextShapeId;
-    int                 iFIDAsRegularColumnIndex;
-    int                 bAutoFIDOnCreateViaCopy;
-    int                 bCopyStatementWithFID;
-
-    char              **papszOverrideColumnTypes;
-
-    CPLString           m_osFirstGeometryFieldName;
-
-    OGRErr              StartCopy(int bSetFID);
-    CPLString           BuildCopyFields(int bSetFID);
-
-  public:
-                        OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
-                                       const char* pszSchemaName,
-                                       const char* pszLayerName,
-                                       const char *pszFIDColumn,
-                                       int         bWriteAsHexIn,
-                                       int         bCreateTable);
-    virtual             ~OGRPGDumpLayer();
-
-    virtual OGRFeatureDefn *GetLayerDefn() {return poFeatureDefn;}
-    virtual const char* GetFIDColumn() { return pszFIDColumn; }
-    
-    virtual void        ResetReading()  { }
-    virtual int         TestCapability( const char * );
-    
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      CreateFeatureViaInsert( OGRFeature *poFeature );
-    virtual OGRErr      CreateFeatureViaCopy( OGRFeature *poFeature );
-
-    virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
-                                         int bApproxOK = TRUE );
-
-    virtual OGRFeature *GetNextFeature();
-
-    virtual CPLErr      SetMetadata(char** papszMD, const char* pszDomain = "");
-    virtual CPLErr      SetMetadataItem(const char* pszName, const char* pszValue, const char* pszDomain = "");
-
-    // follow methods are not base class overrides
-    void                SetLaunderFlag( int bFlag )
-                                { bLaunderColumnNames = bFlag; }
-    void                SetPrecisionFlag( int bFlag )
-                                { bPreservePrecision = bFlag; }
-
-    void                SetOverrideColumnTypes( const char* pszOverrideColumnTypes );
-    void                SetUnknownSRSId( int nUnknownSRSIdIn )
-                                { nUnknownSRSId = nUnknownSRSIdIn; }
-    void                SetForcedSRSId( int nForcedSRSIdIn )
-                                { nForcedSRSId = nForcedSRSIdIn; }
-    void                SetForcedGeometryTypeFlags( int GeometryTypeFlagsIn )
-                                { nForcedGeometryTypeFlags = GeometryTypeFlagsIn; }
-    void                SetCreateSpatialIndexFlag( int bFlag )
-                                { bCreateSpatialIndexFlag = bFlag; }
-    void                SetPostGISVersion(int nPostGISMajorIn, int nPostGISMinorIn)
-                                { nPostGISMajor = nPostGISMajorIn; nPostGISMinor = nPostGISMinorIn; }
-    void                SetGeometryFieldName( const char* pszGeomFieldName ) { m_osFirstGeometryFieldName = pszGeomFieldName; }
-    void                SetForcedDescription( const char* pszDescriptionIn );
-    OGRErr              EndCopy();
-
-    static char*        GByteArrayToBYTEA( const GByte* pabyData, int nLen);
-};
-
-/************************************************************************/
-/*                       OGRPGDumpDataSource                            */
-/************************************************************************/
-class OGRPGDumpDataSource : public OGRDataSource
-{
-    int                 nLayers;
-    OGRPGDumpLayer**    papoLayers;
-    char*               pszName;
-    int                 bTriedOpen;
-    VSILFILE*           fp;
-    int                 bInTransaction;
-    OGRPGDumpLayer*     poLayerInCopyMode;
-    const char*         pszEOL;
-
-  public:
-                        OGRPGDumpDataSource(const char* pszName,
-                                            char** papszOptions);
-                        ~OGRPGDumpDataSource();
-
-    int                 Log(const char* pszStr, int bAddSemiColumn = TRUE);
-
-    virtual const char  *GetName() { return pszName; }
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer   *GetLayer( int );
-
-    virtual OGRLayer    *ICreateLayer( const char *,
-                                      OGRSpatialReference * = NULL,
-                                      OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
-
-    virtual int         TestCapability( const char * );
-
-    void                LogStartTransaction();
-    void                LogCommit();
-
-    void                StartCopy( OGRPGDumpLayer *poPGLayer );
-    OGRErr              EndCopy( );
-};
-
-#endif /* ndef OGR_PGDUMP_H_INCLUDED */
-
+/******************************************************************************
+ * $Id: ogr_pgdump.h 36501 2016-11-25 14:09:24Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Private definitions for OGR/PostgreSQL dump driver.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_PGDUMP_H_INCLUDED
+#define OGR_PGDUMP_H_INCLUDED
+
+#include "ogrsf_frmts.h"
+#include "cpl_string.h"
+
+CPLString OGRPGDumpEscapeColumnName(const char* pszColumnName);
+CPLString OGRPGDumpEscapeString( const char* pszStrValue, int nMaxLength = -1,
+                                 const char* pszFieldName = "");
+CPLString CPL_DLL OGRPGCommonLayerGetType( OGRFieldDefn& oField,
+                                           bool bPreservePrecision,
+                                           bool bApproxOK );
+bool CPL_DLL OGRPGCommonLayerSetType( OGRFieldDefn& oField,
+                                      const char* pszType,
+                                      const char* pszFormatType,
+                                      int nWidth );
+void CPL_DLL OGRPGCommonLayerNormalizeDefault( OGRFieldDefn* poFieldDefn,
+                                               const char* pszDefault );
+CPLString CPL_DLL OGRPGCommonLayerGetPGDefault( OGRFieldDefn* poFieldDefn );
+
+typedef CPLString (*OGRPGCommonEscapeStringCbk)( void* userdata,
+                                                 const char* pszValue,
+                                                 int nWidth,
+                                                 const char* pszLayerName,
+                                                 const char* pszFieldRef );
+void CPL_DLL
+OGRPGCommonAppendCopyFieldsExceptGeom(
+    CPLString& osCommand,
+    OGRFeature* poFeature,
+    const char* pszFIDColumn,
+    bool bFIDColumnInCopyFields,
+    OGRPGCommonEscapeStringCbk pfnEscapeString,
+    void* userdata );
+
+void CPL_DLL OGRPGCommonAppendFieldValue(
+    CPLString& osCommand,
+    OGRFeature* poFeature, int i,
+    OGRPGCommonEscapeStringCbk pfnEscapeString,
+    void* userdata);
+
+char CPL_DLL *OGRPGCommonLaunderName( const char *pszSrcName,
+                                      const char* pszDebugPrefix = "OGR" );
+
+/************************************************************************/
+/*                        OGRPGDumpGeomFieldDefn                        */
+/************************************************************************/
+
+class OGRPGDumpGeomFieldDefn : public OGRGeomFieldDefn
+{
+    public:
+        explicit OGRPGDumpGeomFieldDefn( OGRGeomFieldDefn *poGeomField ) :
+            OGRGeomFieldDefn(poGeomField),
+            nSRSId(-1),
+            GeometryTypeFlags(0)
+            {}
+
+        int nSRSId;
+        int GeometryTypeFlags;
+};
+
+/************************************************************************/
+/*                          OGRPGDumpLayer                              */
+/************************************************************************/
+
+class OGRPGDumpDataSource;
+
+class OGRPGDumpLayer : public OGRLayer
+{
+    char                *pszSchemaName;
+    char                *pszSqlTableName;
+    CPLString           osForcedDescription;
+    char                *pszFIDColumn;
+    OGRFeatureDefn      *poFeatureDefn;
+    OGRPGDumpDataSource *poDS;
+    bool                bLaunderColumnNames;
+    bool                bPreservePrecision;
+    int                 bUseCopy;
+    bool                bWriteAsHex;
+    bool                bCopyActive;
+    bool                bFIDColumnInCopyFields;
+    int                 bCreateTable;
+    int                 nUnknownSRSId;
+    int                 nForcedSRSId;
+    int                 nForcedGeometryTypeFlags;
+    bool                bCreateSpatialIndexFlag;
+    int                 nPostGISMajor;
+    int                 nPostGISMinor;
+
+    int                 iNextShapeId;
+    int                 iFIDAsRegularColumnIndex;
+    bool                bAutoFIDOnCreateViaCopy;
+    bool                bCopyStatementWithFID;
+
+    char              **papszOverrideColumnTypes;
+
+    CPLString           m_osFirstGeometryFieldName;
+
+    OGRErr              StartCopy(int bSetFID);
+    CPLString           BuildCopyFields(int bSetFID);
+
+  public:
+                        OGRPGDumpLayer(OGRPGDumpDataSource* poDS,
+                                       const char* pszSchemaName,
+                                       const char* pszLayerName,
+                                       const char *pszFIDColumn,
+                                       int         bWriteAsHexIn,
+                                       int         bCreateTable);
+    virtual             ~OGRPGDumpLayer();
+
+    virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
+    virtual const char* GetFIDColumn() override { return pszFIDColumn; }
+
+    virtual void        ResetReading() override {}
+    virtual int         TestCapability( const char * ) override;
+
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      CreateFeatureViaInsert( OGRFeature *poFeature );
+    virtual OGRErr      CreateFeatureViaCopy( OGRFeature *poFeature );
+
+    virtual OGRErr      CreateField( OGRFieldDefn *poField,
+                                     int bApproxOK = TRUE ) override;
+    virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
+                                         int bApproxOK = TRUE ) override;
+
+    virtual OGRFeature *GetNextFeature() override;
+
+    virtual CPLErr      SetMetadata( char** papszMD,
+                                     const char* pszDomain = "" ) override;
+    virtual CPLErr      SetMetadataItem( const char* pszName,
+                                         const char* pszValue,
+                                         const char* pszDomain = "" ) override;
+
+    // follow methods are not base class overrides
+    void                SetLaunderFlag( bool bFlag )
+                                { bLaunderColumnNames = bFlag; }
+    void                SetPrecisionFlag( bool bFlag )
+                                { bPreservePrecision = bFlag; }
+
+    void                SetOverrideColumnTypes( const char* pszOverrideColumnTypes );
+    void                SetUnknownSRSId( int nUnknownSRSIdIn )
+                                { nUnknownSRSId = nUnknownSRSIdIn; }
+    void                SetForcedSRSId( int nForcedSRSIdIn )
+                                { nForcedSRSId = nForcedSRSIdIn; }
+    void                SetForcedGeometryTypeFlags( int GeometryTypeFlagsIn )
+                                { nForcedGeometryTypeFlags = GeometryTypeFlagsIn; }
+    void                SetCreateSpatialIndexFlag( bool bFlag )
+                                { bCreateSpatialIndexFlag = bFlag; }
+    void                SetPostGISVersion(int nPostGISMajorIn, int nPostGISMinorIn)
+                                { nPostGISMajor = nPostGISMajorIn; nPostGISMinor = nPostGISMinorIn; }
+    void                SetGeometryFieldName( const char* pszGeomFieldName )
+                                { m_osFirstGeometryFieldName = pszGeomFieldName; }
+    void                SetForcedDescription( const char* pszDescriptionIn );
+    OGRErr              EndCopy();
+
+    static char*        GByteArrayToBYTEA( const GByte* pabyData, int nLen);
+};
+
+/************************************************************************/
+/*                       OGRPGDumpDataSource                            */
+/************************************************************************/
+class OGRPGDumpDataSource : public OGRDataSource
+{
+    int                 nLayers;
+    OGRPGDumpLayer**    papoLayers;
+    char*               pszName;
+    bool                bTriedOpen;
+    VSILFILE*           fp;
+    bool                bInTransaction;
+    OGRPGDumpLayer*     poLayerInCopyMode;
+    const char*         pszEOL;
+
+  public:
+                        OGRPGDumpDataSource(const char* pszName,
+                                            char** papszOptions);
+                        virtual ~OGRPGDumpDataSource();
+
+    bool                Log( const char* pszStr, bool bAddSemiColumn = true );
+
+    virtual const char  *GetName() override { return pszName; }
+    virtual int         GetLayerCount() override { return nLayers; }
+    virtual OGRLayer   *GetLayer( int ) override;
+
+    virtual OGRLayer    *ICreateLayer( const char *,
+                                      OGRSpatialReference * = NULL,
+                                      OGRwkbGeometryType = wkbUnknown,
+                                      char ** = NULL ) override;
+
+    virtual int         TestCapability( const char * ) override;
+
+    void                LogStartTransaction();
+    void                LogCommit();
+
+    void                StartCopy( OGRPGDumpLayer *poPGLayer );
+    OGRErr              EndCopy( );
+};
+
+#endif /* ndef OGR_PGDUMP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
index e9814f4..4c3c4d1 100644
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdatasource.cpp
@@ -1,670 +1,710 @@
-/******************************************************************************
- * $Id: ogrpgdumpdatasource.cpp 33639 2016-03-04 23:39:40Z rouault $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements OGRPGDumpDataSource class.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include <string.h>
-#include "ogr_pgdump.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-
-CPL_CVSID("$Id: ogrpgdumpdatasource.cpp 33639 2016-03-04 23:39:40Z rouault $");
-
-/************************************************************************/
-/*                      OGRPGDumpDataSource()                           */
-/************************************************************************/
-
-OGRPGDumpDataSource::OGRPGDumpDataSource(const char* pszNameIn,
-                                         char** papszOptions)
-
-{
-    nLayers = 0;
-    papoLayers = NULL;
-    this->pszName = CPLStrdup(pszNameIn);
-    bTriedOpen = FALSE;
-    fp = NULL;
-    bInTransaction = FALSE;
-    poLayerInCopyMode = NULL;
-
-    const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
-
-    int bUseCRLF;
-    if( pszCRLFFormat == NULL )
-    {
-#ifdef WIN32
-        bUseCRLF = TRUE;
-#else
-        bUseCRLF = FALSE;
-#endif
-    }
-    else if( EQUAL(pszCRLFFormat,"CRLF") )
-        bUseCRLF = TRUE;
-    else if( EQUAL(pszCRLFFormat,"LF") )
-        bUseCRLF = FALSE;
-    else
-    {
-        CPLError( CE_Warning, CPLE_AppDefined, 
-                  "LINEFORMAT=%s not understood, use one of CRLF or LF.",
-                  pszCRLFFormat );
-#ifdef WIN32
-        bUseCRLF = TRUE;
-#else
-        bUseCRLF = FALSE;
-#endif
-    }
-    pszEOL = (bUseCRLF) ? "\r\n" : "\n";
-}
-
-/************************************************************************/
-/*                          ~OGRPGDumpDataSource()                          */
-/************************************************************************/
-
-OGRPGDumpDataSource::~OGRPGDumpDataSource()
-
-{
-    int i;
-
-    if (fp)
-    {
-        LogCommit();
-        VSIFCloseL(fp);
-        fp = NULL;
-    }
-
-    for(i=0;i<nLayers;i++)
-        delete papoLayers[i];
-    CPLFree(papoLayers);
-    CPLFree(pszName);
-}
-
-/************************************************************************/
-/*                         LogStartTransaction()                        */
-/************************************************************************/
-
-void OGRPGDumpDataSource::LogStartTransaction()
-{
-    if (bInTransaction)
-        return;
-    bInTransaction = TRUE;
-    Log("BEGIN");
-}
-
-/************************************************************************/
-/*                             LogCommit()                              */
-/************************************************************************/
-
-void OGRPGDumpDataSource::LogCommit()
-{
-    EndCopy();
-
-    if (!bInTransaction)
-        return;
-    bInTransaction = FALSE;
-    Log("COMMIT");
-}
-
-/************************************************************************/
-/*                         OGRPGCommonLaunderName()                     */
-/************************************************************************/
-
-char *OGRPGCommonLaunderName( const char *pszSrcName, const char* pszDebugPrefix )
-
-{
-    char    *pszSafeName = CPLStrdup( pszSrcName );
-
-    for( int i = 0; pszSafeName[i] != '\0'; i++ )
-    {
-        pszSafeName[i] = (char) tolower( pszSafeName[i] );
-        if( pszSafeName[i] == '\'' || pszSafeName[i] == '-' || pszSafeName[i] == '#' )
-            pszSafeName[i] = '_';
-    }
-
-    if( strcmp(pszSrcName,pszSafeName) != 0 )
-        CPLDebug(pszDebugPrefix,"LaunderName('%s') -> '%s'", 
-                 pszSrcName, pszSafeName);
-
-    return pszSafeName;
-}
-
-/************************************************************************/
-/*                           ICreateLayer()                             */
-/************************************************************************/
-
-OGRLayer *
-OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
-                                  OGRSpatialReference *poSRS,
-                                  OGRwkbGeometryType eType,
-                                  char ** papszOptions )
-
-{
-    CPLString            osCommand;
-    const char          *pszGeomType = NULL;
-    char                *pszTableName = NULL;
-    char                *pszSchemaName = NULL;
-    int                  bHavePostGIS = TRUE;
-    int                 GeometryTypeFlags = 0;
-
-    const char* pszFIDColumnNameIn = CSLFetchNameValue(papszOptions, "FID");
-    CPLString osFIDColumnName, osFIDColumnNameEscaped;
-    if (pszFIDColumnNameIn == NULL)
-        osFIDColumnName = "ogc_fid";
-    else
-    {
-        if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
-        {
-            char* pszLaunderedFid = OGRPGCommonLaunderName(pszFIDColumnNameIn, "PGDump");
-            osFIDColumnName = pszLaunderedFid;
-            CPLFree(pszLaunderedFid);
-        }
-        else
-        {
-            osFIDColumnName = pszFIDColumnNameIn;
-        }
-    }
-    osFIDColumnNameEscaped = OGRPGDumpEscapeColumnName(osFIDColumnName);
-
-    if (STARTS_WITH(pszLayerName, "pg"))
-    {
-        CPLError(CE_Warning, CPLE_AppDefined,
-                 "The layer name should not begin by 'pg' as it is a reserved prefix");
-    }
-    
-    //bHavePostGIS = CSLFetchBoolean(papszOptions,"POSTGIS", TRUE);
-
-    int bCreateTable = CSLFetchBoolean(papszOptions,"CREATE_TABLE", TRUE);
-    int bCreateSchema = CSLFetchBoolean(papszOptions,"CREATE_SCHEMA", TRUE);
-    const char* pszDropTable = CSLFetchNameValueDef(papszOptions,"DROP_TABLE", "IF_EXISTS");
-
-    if( OGR_GT_HasZ((OGRwkbGeometryType)eType) )
-        GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
-    if( OGR_GT_HasM((OGRwkbGeometryType)eType) )
-        GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
-
-    int ForcedGeometryTypeFlags = -1;
-    const char* pszDim = CSLFetchNameValue( papszOptions, "DIM");
-    if( pszDim != NULL )
-    {
-        if( EQUAL(pszDim, "XY") || EQUAL(pszDim, "2") )
-        {
-            GeometryTypeFlags = 0;
-            ForcedGeometryTypeFlags = GeometryTypeFlags;
-        }
-        else if( EQUAL(pszDim, "XYZ") || EQUAL(pszDim, "3") )
-        {
-            GeometryTypeFlags = OGRGeometry::OGR_G_3D;
-            ForcedGeometryTypeFlags = GeometryTypeFlags;
-        }
-        else if( EQUAL(pszDim, "XYM") )
-        {
-            GeometryTypeFlags = OGRGeometry::OGR_G_MEASURED;
-            ForcedGeometryTypeFlags = GeometryTypeFlags;
-        }
-        else if( EQUAL(pszDim, "XYZM") || EQUAL(pszDim, "4") )
-        {
-            GeometryTypeFlags = OGRGeometry::OGR_G_3D | OGRGeometry::OGR_G_MEASURED;
-            ForcedGeometryTypeFlags = GeometryTypeFlags;
-        }
-        else
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for DIM");
-        }
-    }
-
-    const int nDimension = 2 + ((GeometryTypeFlags & OGRGeometry::OGR_G_3D) ? 1 : 0)
-                       + ((GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) ? 1 : 0);
-
-    /* Should we turn layers with None geometry type as Unknown/GEOMETRY */
-    /* so they are still recorded in geometry_columns table ? (#4012) */
-    int bNoneAsUnknown = CPLTestBool(CSLFetchNameValueDef(
-                                    papszOptions, "NONE_AS_UNKNOWN", "NO"));
-    if (bNoneAsUnknown && eType == wkbNone)
-        eType = wkbUnknown;
-    else if (eType == wkbNone)
-        bHavePostGIS = FALSE;
-
-    int bExtractSchemaFromLayerName = CPLTestBool(CSLFetchNameValueDef(
-                                    papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES"));
-
-    /* Postgres Schema handling:
-       Extract schema name from input layer name or passed with -lco SCHEMA.
-       Set layer name to "schema.table" or to "table" if schema == current_schema()
-       Usage without schema name is backwards compatible
-    */
-    const char* pszDotPos = strstr(pszLayerName,".");
-    if ( pszDotPos != NULL && bExtractSchemaFromLayerName )
-    {
-      int length = static_cast<int>(pszDotPos - pszLayerName);
-      pszSchemaName = (char*)CPLMalloc(length+1);
-      strncpy(pszSchemaName, pszLayerName, length);
-      pszSchemaName[length] = '\0';
-
-      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
-          pszTableName = OGRPGCommonLaunderName( pszDotPos + 1, "PGDump" ); //skip "."
-      else
-          pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "."
-    }
-    else
-    {
-      pszSchemaName = NULL;
-      if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
-          pszTableName = OGRPGCommonLaunderName( pszLayerName, "PGDump" ); //skip "."
-      else
-          pszTableName = CPLStrdup( pszLayerName ); //skip "."
-    }
-
-    LogCommit();
-
-/* -------------------------------------------------------------------- */
-/*      Set the default schema for the layers.                          */
-/* -------------------------------------------------------------------- */
-    if( CSLFetchNameValue( papszOptions, "SCHEMA" ) != NULL )
-    {
-        CPLFree(pszSchemaName);
-        pszSchemaName = CPLStrdup(CSLFetchNameValue( papszOptions, "SCHEMA" ));
-        if (bCreateSchema)
-        {
-            osCommand.Printf("CREATE SCHEMA \"%s\"", pszSchemaName);
-            Log(osCommand);
-        }
-    }
-
-    if ( pszSchemaName == NULL)
-    {
-        pszSchemaName = CPLStrdup("public");
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Do we already have this layer?                                  */
-/* -------------------------------------------------------------------- */
-    int iLayer;
-
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
-    {
-        if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Layer %s already exists, CreateLayer failed.\n", 
-                      pszLayerName );
-            CPLFree( pszTableName );
-            CPLFree( pszSchemaName );
-            return NULL;
-        }
-    }
-
-
-    if (bCreateTable && (EQUAL(pszDropTable, "YES") ||
-                         EQUAL(pszDropTable, "ON") ||
-                         EQUAL(pszDropTable, "TRUE") ||
-                         EQUAL(pszDropTable, "IF_EXISTS")))
-    {
-        if (EQUAL(pszDropTable, "IF_EXISTS"))
-            osCommand.Printf("DROP TABLE IF EXISTS \"%s\".\"%s\" CASCADE", pszSchemaName, pszTableName );
-        else
-            osCommand.Printf("DROP TABLE \"%s\".\"%s\" CASCADE", pszSchemaName, pszTableName );
-        Log(osCommand);
-    }
-    
-/* -------------------------------------------------------------------- */
-/*      Handle the GEOM_TYPE option.                                    */
-/* -------------------------------------------------------------------- */
-    pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" );
-    if( pszGeomType == NULL )
-    {
-        pszGeomType = "geometry";
-    }
-
-    if( !EQUAL(pszGeomType,"geometry") && !EQUAL(pszGeomType, "geography"))
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                    "GEOM_TYPE in PostGIS enabled databases must be 'geometry' or 'geography'.\n"
-                    "Creation of layer %s with GEOM_TYPE %s has failed.",
-                    pszLayerName, pszGeomType );
-        CPLFree( pszTableName );
-        CPLFree( pszSchemaName );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Try to get the SRS Id of this spatial reference system,         */
-/*      adding tot the srs table if needed.                             */
-/* -------------------------------------------------------------------- */
-    int nUnknownSRSId = -1;
-    const char* pszPostgisVersion = CSLFetchNameValue( papszOptions, "POSTGIS_VERSION" );
-    int nPostGISMajor = 1;
-    int nPostGISMinor = 5;
-    if( pszPostgisVersion != NULL && atoi(pszPostgisVersion) >= 2 )
-    {
-        nPostGISMajor = atoi(pszPostgisVersion);
-        if( strchr(pszPostgisVersion, '.') )
-            nPostGISMinor = atoi(strchr(pszPostgisVersion, '.')+1);
-        else
-            nPostGISMinor = 0;
-        nUnknownSRSId = 0;
-    }
-
-    int nSRSId = nUnknownSRSId;
-    int nForcedSRSId = -2;
-    if( CSLFetchNameValue( papszOptions, "SRID") != NULL )
-    {
-        nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID"));
-        nForcedSRSId = nSRSId;
-    }
-    else
-    {
-        if (poSRS)
-        {
-            const char* pszAuthorityName = poSRS->GetAuthorityName(NULL);
-            if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
-            {
-                /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */
-                nSRSId = atoi( poSRS->GetAuthorityCode(NULL) );
-            }
-            else
-            {
-                const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS");
-                if (pszGeogCSName != NULL && EQUAL(pszGeogCSName, "GCS_WGS_1984"))
-                    nSRSId = 4326;
-            }
-        }
-    }
-
-    CPLString osEscapedTableNameSingleQuote = OGRPGDumpEscapeString(pszTableName);
-    const char* pszEscapedTableNameSingleQuote = osEscapedTableNameSingleQuote.c_str();
-
-    const char *pszGeometryType = OGRToOGCGeomType(eType);
-
-    const char *pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
-    if( bHavePostGIS && !EQUAL(pszGeomType, "geography"))
-    {
-        if( pszGFldName == NULL )
-            pszGFldName = "wkb_geometry";
-
-        if( nPostGISMajor < 2 )
-        {
-            /* Sometimes there is an old cruft entry in the geometry_columns
-            * table if things were not properly cleaned up before.  We make
-            * an effort to clean out such cruft.
-            * Note: PostGIS 2.0 defines geometry_columns as a view (no clean up is needed)
-            */
-            osCommand.Printf(
-                    "DELETE FROM geometry_columns WHERE f_table_name = %s AND f_table_schema = '%s'",
-                    pszEscapedTableNameSingleQuote, pszSchemaName );
-            if (bCreateTable)
-                Log(osCommand);
-        }
-    }
-
-
-    LogStartTransaction();
-
-/* -------------------------------------------------------------------- */
-/*      Create a basic table with the FID.  Also include the            */
-/*      geometry if this is not a PostGIS enabled table.                */
-/* -------------------------------------------------------------------- */
-    int bFID64 = CSLFetchBoolean(papszOptions, "FID64", FALSE);
-    const char* pszSerialType = bFID64 ? "BIGSERIAL": "SERIAL";
-    
-    CPLString osCreateTable;
-    int bTemporary = CSLFetchBoolean( papszOptions, "TEMPORARY", FALSE );
-    if (bTemporary)
-    {
-        CPLFree(pszSchemaName);
-        pszSchemaName = CPLStrdup("pg_temp_1");
-        osCreateTable.Printf("CREATE TEMPORARY TABLE \"%s\"", pszTableName);
-    }
-    else
-        osCreateTable.Printf("CREATE TABLE%s \"%s\".\"%s\"",
-                             CSLFetchBoolean( papszOptions, "UNLOGGED", FALSE ) ? " UNLOGGED": "",
-                             pszSchemaName, pszTableName);
-
-    if( !bHavePostGIS )
-    {
-        if (eType == wkbNone)
-            osCommand.Printf(
-                    "%s ( "
-                    "   %s %s, "
-                    "   CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                    osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() );
-        else
-            osCommand.Printf(
-                    "%s ( "
-                    "   %s %s, "
-                    "   WKB_GEOMETRY %s, "
-                    "   CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                    osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGeomType, pszTableName, osFIDColumnNameEscaped.c_str() );
-    }
-    else if ( EQUAL(pszGeomType, "geography") )
-    {
-        if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
-            pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
-        else
-            pszGFldName = "the_geog";
-
-        const char *suffix = "";
-        if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) && (GeometryTypeFlags & OGRGeometry::OGR_G_3D) )
-        {
-            suffix = "ZM";
-        }
-        else if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
-        {
-            suffix = "M";
-        }
-        else if( (GeometryTypeFlags & OGRGeometry::OGR_G_3D) )
-        {
-            suffix = "Z";
-        }
-
-        if (nSRSId)
-            osCommand.Printf(
-                     "%s ( %s %s, \"%s\" geography(%s%s,%d), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                     osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, suffix, nSRSId, pszTableName, osFIDColumnNameEscaped.c_str() );
-        else
-            osCommand.Printf(
-                     "%s ( %s %s, \"%s\" geography(%s%s), CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                     osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszGFldName, pszGeometryType, suffix, pszTableName, osFIDColumnNameEscaped.c_str() );
-    }
-    else
-    {
-        osCommand.Printf(
-                 "%s ( %s %s, CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
-                 osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(), pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() );
-    }
-
-    if (bCreateTable)
-        Log(osCommand);
-
-/* -------------------------------------------------------------------- */
-/*      Eventually we should be adding this table to a table of         */
-/*      "geometric layers", capturing the WKT projection, and           */
-/*      perhaps some other housekeeping.                                */
-/* -------------------------------------------------------------------- */
-    if( bCreateTable && bHavePostGIS && !EQUAL(pszGeomType, "geography"))
-    {
-        const char *suffix = "";
-        if( GeometryTypeFlags == static_cast<int>(OGRGeometry::OGR_G_MEASURED) &&
-            wkbFlatten(eType) != wkbUnknown )
-        {
-            suffix = "M";
-        }
-
-        osCommand.Printf(
-                "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s%s',%d)",
-                pszSchemaName, pszEscapedTableNameSingleQuote, pszGFldName,
-                nSRSId, pszGeometryType, suffix, nDimension );
-        Log(osCommand);
-    }
-
-    const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
-    int bCreateSpatialIndex = ( pszSI == NULL || CPLTestBool(pszSI) );
-    if( bCreateTable && bHavePostGIS && bCreateSpatialIndex )
-    {
-/* -------------------------------------------------------------------- */
-/*      Create the spatial index.                                       */
-/*                                                                      */
-/*      We're doing this before we add geometry and record to the table */
-/*      so this may not be exactly the best way to do it.               */
-/* -------------------------------------------------------------------- */
-        osCommand.Printf("CREATE INDEX \"%s_%s_geom_idx\" "
-                        "ON \"%s\".\"%s\" "
-                        "USING GIST (\"%s\")",
-                pszTableName, pszGFldName, pszSchemaName, pszTableName, pszGFldName);
-
-        Log(osCommand);
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create the layer object.                                        */
-/* -------------------------------------------------------------------- */
-    OGRPGDumpLayer     *poLayer;
-
-    int bWriteAsHex = !CSLFetchBoolean(papszOptions,"WRITE_EWKT_GEOM",FALSE);
-
-    poLayer = new OGRPGDumpLayer( this, pszSchemaName, pszTableName,
-                                  osFIDColumnName, bWriteAsHex, bCreateTable );
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
-    poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
-
-    const char* pszOverrideColumnTypes = CSLFetchNameValue( papszOptions, "COLUMN_TYPES" );
-    poLayer->SetOverrideColumnTypes(pszOverrideColumnTypes);
-    poLayer->SetUnknownSRSId(nUnknownSRSId);
-    poLayer->SetForcedSRSId(nForcedSRSId);
-    poLayer->SetCreateSpatialIndexFlag(bCreateSpatialIndex);
-    poLayer->SetPostGISVersion(nPostGISMajor, nPostGISMinor);
-    poLayer->SetForcedGeometryTypeFlags(ForcedGeometryTypeFlags);
-
-    const char* pszDescription = CSLFetchNameValue(papszOptions, "DESCRIPTION");
-    if( pszDescription != NULL )
-        poLayer->SetForcedDescription( pszDescription );
-
-    if( bHavePostGIS )
-    {
-        OGRGeomFieldDefn oTmp( pszGFldName, eType );
-        OGRPGDumpGeomFieldDefn *poGeomField =
-            new OGRPGDumpGeomFieldDefn(&oTmp);
-        poGeomField->nSRSId = nSRSId;
-        poGeomField->GeometryTypeFlags = GeometryTypeFlags;
-        poLayer->GetLayerDefn()->AddGeomFieldDefn(poGeomField, FALSE);
-    }
-    else if( pszGFldName )
-        poLayer->SetGeometryFieldName(pszGFldName);
-
-/* -------------------------------------------------------------------- */
-/*      Add layer to data source layer list.                            */
-/* -------------------------------------------------------------------- */
-    papoLayers = (OGRPGDumpLayer **)
-        CPLRealloc( papoLayers,  sizeof(OGRPGDumpLayer *) * (nLayers+1) );
-
-    papoLayers[nLayers++] = poLayer;
-
-    CPLFree( pszTableName );
-    CPLFree( pszSchemaName );
-
-    return poLayer;
-}
-
-/************************************************************************/
-/*                           TestCapability()                           */
-/************************************************************************/
-
-int OGRPGDumpDataSource::TestCapability( const char * pszCap )
-
-{
-    if( EQUAL(pszCap,ODsCCreateLayer) )
-        return TRUE;
-    else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
-        return TRUE;
-    else if( EQUAL(pszCap,ODsCCurveGeometries) )
-        return TRUE;
-    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
-        return TRUE;
-    else
-        return FALSE;
-}
-
-/************************************************************************/
-/*                              GetLayer()                              */
-/************************************************************************/
-
-OGRLayer *OGRPGDumpDataSource::GetLayer( int iLayer )
-
-{
-    if( iLayer < 0 || iLayer >= nLayers )
-        return NULL;
-    else
-        return papoLayers[iLayer];
-}
-
-/************************************************************************/
-/*                                  Log()                               */
-/************************************************************************/
-
-int  OGRPGDumpDataSource::Log(const char* pszStr, int bAddSemiColumn)
-{
-    if (fp == NULL)
-    {
-        if (bTriedOpen)
-            return FALSE;
-        bTriedOpen = TRUE;
-        fp = VSIFOpenL(pszName, "wb");
-        if (fp == NULL)
-        {
-            CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s", pszName);
-            return FALSE;
-        }
-    }
-
-    if (bAddSemiColumn)
-        VSIFPrintfL(fp, "%s;%s", pszStr, pszEOL);
-    else
-        VSIFPrintfL(fp, "%s%s", pszStr, pszEOL);
-    return TRUE;
-}
-
-/************************************************************************/
-/*                             StartCopy()                              */
-/************************************************************************/
-void OGRPGDumpDataSource::StartCopy( OGRPGDumpLayer *poPGLayer )
-{
-    EndCopy();
-    poLayerInCopyMode = poPGLayer;
-}
-
-/************************************************************************/
-/*                              EndCopy()                               */
-/************************************************************************/
-OGRErr OGRPGDumpDataSource::EndCopy( )
-{
-    if( poLayerInCopyMode != NULL )
-    {
-        OGRErr result = poLayerInCopyMode->EndCopy();
-        poLayerInCopyMode = NULL;
-
-        return result;
-    }
-    else
-        return OGRERR_NONE;
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRPGDumpDataSource class.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <cstring>
+#include "ogr_pgdump.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: ogrpgdumpdatasource.cpp 35911 2016-10-24 15:03:26Z goatbar $");
+
+/************************************************************************/
+/*                      OGRPGDumpDataSource()                           */
+/************************************************************************/
+
+OGRPGDumpDataSource::OGRPGDumpDataSource( const char* pszNameIn,
+                                          char** papszOptions ) :
+    nLayers(0),
+    papoLayers(NULL),
+    pszName(CPLStrdup(pszNameIn)),
+    bTriedOpen(false),
+    fp(NULL),
+    bInTransaction(false),
+    poLayerInCopyMode(NULL),
+    pszEOL("\n")
+{
+    const char *pszCRLFFormat = CSLFetchNameValue( papszOptions, "LINEFORMAT");
+
+    bool bUseCRLF = false;
+    if( pszCRLFFormat == NULL )
+    {
+#ifdef WIN32
+        bUseCRLF = true;
+#endif
+    }
+    else if( EQUAL(pszCRLFFormat, "CRLF") )
+    {
+        bUseCRLF = true;
+    }
+    else if( EQUAL(pszCRLFFormat, "LF") )
+    {
+        bUseCRLF = false;
+    }
+    else
+    {
+        CPLError( CE_Warning, CPLE_AppDefined,
+                  "LINEFORMAT=%s not understood, use one of CRLF or LF.",
+                  pszCRLFFormat );
+#ifdef WIN32
+        bUseCRLF = true;
+#endif
+    }
+
+    if( bUseCRLF )
+        pszEOL =  "\r\n";
+}
+
+/************************************************************************/
+/*                          ~OGRPGDumpDataSource()                          */
+/************************************************************************/
+
+OGRPGDumpDataSource::~OGRPGDumpDataSource()
+
+{
+    if( fp )
+    {
+        LogCommit();
+        VSIFCloseL(fp);
+        fp = NULL;
+    }
+
+    for( int i = 0; i < nLayers; i++ )
+        delete papoLayers[i];
+    CPLFree(papoLayers);
+    CPLFree(pszName);
+}
+
+/************************************************************************/
+/*                         LogStartTransaction()                        */
+/************************************************************************/
+
+void OGRPGDumpDataSource::LogStartTransaction()
+{
+    if( bInTransaction )
+        return;
+    bInTransaction = true;
+    Log("BEGIN");
+}
+
+/************************************************************************/
+/*                             LogCommit()                              */
+/************************************************************************/
+
+void OGRPGDumpDataSource::LogCommit()
+{
+    EndCopy();
+
+    if( !bInTransaction )
+        return;
+    bInTransaction = false;
+    Log("COMMIT");
+}
+
+/************************************************************************/
+/*                         OGRPGCommonLaunderName()                     */
+/************************************************************************/
+
+char *OGRPGCommonLaunderName( const char *pszSrcName,
+                              const char* pszDebugPrefix )
+
+{
+    char *pszSafeName = CPLStrdup( pszSrcName );
+
+    for( int i = 0; pszSafeName[i] != '\0'; i++ )
+    {
+        pszSafeName[i] = (char) tolower( pszSafeName[i] );
+        if( pszSafeName[i] == '\'' ||
+            pszSafeName[i] == '-' ||
+            pszSafeName[i] == '#' )
+        {
+            pszSafeName[i] = '_';
+        }
+    }
+
+    if( strcmp(pszSrcName,pszSafeName) != 0 )
+        CPLDebug(pszDebugPrefix, "LaunderName('%s') -> '%s'",
+                 pszSrcName, pszSafeName);
+
+    return pszSafeName;
+}
+
+/************************************************************************/
+/*                           ICreateLayer()                             */
+/************************************************************************/
+
+OGRLayer *
+OGRPGDumpDataSource::ICreateLayer( const char * pszLayerName,
+                                   OGRSpatialReference *poSRS,
+                                   OGRwkbGeometryType eType,
+                                   char ** papszOptions )
+
+{
+    const char* pszFIDColumnNameIn = CSLFetchNameValue(papszOptions, "FID");
+    CPLString osFIDColumnName;
+    if (pszFIDColumnNameIn == NULL)
+        osFIDColumnName = "ogc_fid";
+    else
+    {
+        if( CPLFetchBool(papszOptions,"LAUNDER", true) )
+        {
+            char *pszLaunderedFid =
+                OGRPGCommonLaunderName(pszFIDColumnNameIn, "PGDump");
+            osFIDColumnName = pszLaunderedFid;
+            CPLFree(pszLaunderedFid);
+        }
+        else
+        {
+            osFIDColumnName = pszFIDColumnNameIn;
+        }
+    }
+    const CPLString osFIDColumnNameEscaped =
+        OGRPGDumpEscapeColumnName(osFIDColumnName);
+
+    if (STARTS_WITH(pszLayerName, "pg"))
+    {
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "The layer name should not begin by 'pg' as it is a reserved "
+                 "prefix");
+    }
+
+    bool bHavePostGIS = true;
+    // bHavePostGIS = CPLFetchBool(papszOptions, "POSTGIS", true);
+
+    const bool bCreateTable = CPLFetchBool(papszOptions, "CREATE_TABLE", true);
+    const bool bCreateSchema =
+        CPLFetchBool(papszOptions, "CREATE_SCHEMA", true);
+    const char* pszDropTable =
+        CSLFetchNameValueDef(papszOptions, "DROP_TABLE", "IF_EXISTS");
+    int GeometryTypeFlags = 0;
+
+    if( OGR_GT_HasZ((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
+    if( OGR_GT_HasM((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
+
+    int ForcedGeometryTypeFlags = -1;
+    const char* pszDim = CSLFetchNameValue( papszOptions, "DIM");
+    if( pszDim != NULL )
+    {
+        if( EQUAL(pszDim, "XY") || EQUAL(pszDim, "2") )
+        {
+            GeometryTypeFlags = 0;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else if( EQUAL(pszDim, "XYZ") || EQUAL(pszDim, "3") )
+        {
+            GeometryTypeFlags = OGRGeometry::OGR_G_3D;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else if( EQUAL(pszDim, "XYM") )
+        {
+            GeometryTypeFlags = OGRGeometry::OGR_G_MEASURED;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else if( EQUAL(pszDim, "XYZM") || EQUAL(pszDim, "4") )
+        {
+            GeometryTypeFlags = OGRGeometry::OGR_G_3D | OGRGeometry::OGR_G_MEASURED;
+            ForcedGeometryTypeFlags = GeometryTypeFlags;
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for DIM");
+        }
+    }
+
+    const int nDimension =
+        2 + ((GeometryTypeFlags & OGRGeometry::OGR_G_3D) ? 1 : 0)
+        + ((GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) ? 1 : 0);
+
+    /* Should we turn layers with None geometry type as Unknown/GEOMETRY */
+    /* so they are still recorded in geometry_columns table ? (#4012) */
+    const bool bNoneAsUnknown =
+        CPLTestBool(
+            CSLFetchNameValueDef(papszOptions, "NONE_AS_UNKNOWN", "NO"));
+
+    if( bNoneAsUnknown && eType == wkbNone )
+        eType = wkbUnknown;
+    else if( eType == wkbNone )
+        bHavePostGIS = false;
+
+    const bool bExtractSchemaFromLayerName =
+        CPLTestBool(CSLFetchNameValueDef(
+            papszOptions, "EXTRACT_SCHEMA_FROM_LAYER_NAME", "YES"));
+
+    // Postgres Schema handling:
+
+    // Extract schema name from input layer name or passed with -lco SCHEMA.
+    // Set layer name to "schema.table" or to "table" if schema ==
+    // current_schema() Usage without schema name is backwards compatible
+
+    const char* pszDotPos = strstr(pszLayerName,".");
+    char *pszTableName = NULL;
+    char *pszSchemaName = NULL;
+
+    if ( pszDotPos != NULL && bExtractSchemaFromLayerName )
+    {
+      const int length = static_cast<int>(pszDotPos - pszLayerName);
+      pszSchemaName = (char*)CPLMalloc(length+1);
+      strncpy(pszSchemaName, pszLayerName, length);
+      pszSchemaName[length] = '\0';
+
+      if( CPLFetchBool(papszOptions, "LAUNDER", true) )
+          pszTableName = OGRPGCommonLaunderName( pszDotPos + 1, "PGDump" ); //skip "."
+      else
+          pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "."
+    }
+    else
+    {
+      pszSchemaName = NULL;
+      if( CPLFetchBool(papszOptions, "LAUNDER", true) )
+          pszTableName = OGRPGCommonLaunderName( pszLayerName, "PGDump" ); //skip "."
+      else
+          pszTableName = CPLStrdup( pszLayerName ); //skip "."
+    }
+
+    LogCommit();
+
+/* -------------------------------------------------------------------- */
+/*      Set the default schema for the layers.                          */
+/* -------------------------------------------------------------------- */
+    CPLString osCommand;
+
+    if( CSLFetchNameValue( papszOptions, "SCHEMA" ) != NULL )
+    {
+        CPLFree(pszSchemaName);
+        pszSchemaName = CPLStrdup(CSLFetchNameValue( papszOptions, "SCHEMA" ));
+        if( bCreateSchema )
+        {
+            osCommand.Printf("CREATE SCHEMA \"%s\"", pszSchemaName);
+            Log(osCommand);
+        }
+    }
+
+    if ( pszSchemaName == NULL)
+    {
+        pszSchemaName = CPLStrdup("public");
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we already have this layer?                                  */
+/* -------------------------------------------------------------------- */
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
+    {
+        if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Layer %s already exists, CreateLayer failed.\n",
+                      pszLayerName );
+            CPLFree( pszTableName );
+            CPLFree( pszSchemaName );
+            return NULL;
+        }
+    }
+
+    if( bCreateTable && (EQUAL(pszDropTable, "YES") ||
+                         EQUAL(pszDropTable, "ON") ||
+                         EQUAL(pszDropTable, "TRUE") ||
+                         EQUAL(pszDropTable, "IF_EXISTS")) )
+    {
+        if (EQUAL(pszDropTable, "IF_EXISTS"))
+            osCommand.Printf("DROP TABLE IF EXISTS \"%s\".\"%s\" CASCADE",
+                             pszSchemaName, pszTableName );
+        else
+            osCommand.Printf("DROP TABLE \"%s\".\"%s\" CASCADE",
+                             pszSchemaName, pszTableName );
+        Log(osCommand);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Handle the GEOM_TYPE option.                                    */
+/* -------------------------------------------------------------------- */
+    const char *pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" );
+    if( pszGeomType == NULL )
+    {
+        pszGeomType = "geometry";
+    }
+
+    if( !EQUAL(pszGeomType,"geometry") && !EQUAL(pszGeomType, "geography"))
+    {
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "GEOM_TYPE in PostGIS enabled databases must be 'geometry' or "
+            "'geography'.  Creation of layer %s with GEOM_TYPE %s has failed.",
+            pszLayerName, pszGeomType );
+        CPLFree( pszTableName );
+        CPLFree( pszSchemaName );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to get the SRS Id of this spatial reference system,         */
+/*      adding tot the srs table if needed.                             */
+/* -------------------------------------------------------------------- */
+    int nUnknownSRSId = -1;
+    const char* pszPostgisVersion =
+        CSLFetchNameValue( papszOptions, "POSTGIS_VERSION" );
+    int nPostGISMajor = 1;
+    int nPostGISMinor = 5;
+    if( pszPostgisVersion != NULL && atoi(pszPostgisVersion) >= 2 )
+    {
+        nPostGISMajor = atoi(pszPostgisVersion);
+        if( strchr(pszPostgisVersion, '.') )
+            nPostGISMinor = atoi(strchr(pszPostgisVersion, '.')+1);
+        else
+            nPostGISMinor = 0;
+        nUnknownSRSId = 0;
+    }
+
+    int nSRSId = nUnknownSRSId;
+    int nForcedSRSId = -2;
+    if( CSLFetchNameValue( papszOptions, "SRID") != NULL )
+    {
+        nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID"));
+        nForcedSRSId = nSRSId;
+    }
+    else
+    {
+        if( poSRS )
+        {
+            const char* pszAuthorityName = poSRS->GetAuthorityName(NULL);
+            if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
+            {
+                /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */
+                nSRSId = atoi( poSRS->GetAuthorityCode(NULL) );
+            }
+            else
+            {
+                const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS");
+                if( pszGeogCSName != NULL &&
+                    EQUAL(pszGeogCSName, "GCS_WGS_1984") )
+                {
+                    nSRSId = 4326;
+                }
+            }
+        }
+    }
+
+    CPLString osEscapedTableNameSingleQuote =
+        OGRPGDumpEscapeString(pszTableName);
+    const char* pszEscapedTableNameSingleQuote =
+        osEscapedTableNameSingleQuote.c_str();
+
+    const char *pszGeometryType = OGRToOGCGeomType(eType);
+
+    const char *pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
+    if( bHavePostGIS && !EQUAL(pszGeomType, "geography") )
+    {
+        if( pszGFldName == NULL )
+            pszGFldName = "wkb_geometry";
+
+        if( nPostGISMajor < 2 )
+        {
+            // Sometimes there is an old cruft entry in the geometry_columns
+            // table if things were not properly cleaned up before.  We make
+            // an effort to clean out such cruft.
+            //
+            // Note: PostGIS 2.0 defines geometry_columns as a view (no clean up
+            // is needed).
+
+            osCommand.Printf(
+                "DELETE FROM geometry_columns "
+                "WHERE f_table_name = %s AND f_table_schema = '%s'",
+                pszEscapedTableNameSingleQuote, pszSchemaName );
+            if( bCreateTable )
+                Log(osCommand);
+        }
+    }
+
+    LogStartTransaction();
+
+/* -------------------------------------------------------------------- */
+/*      Create a basic table with the FID.  Also include the            */
+/*      geometry if this is not a PostGIS enabled table.                */
+/* -------------------------------------------------------------------- */
+    const bool bFID64 = CPLFetchBool(papszOptions, "FID64", false);
+    const char* pszSerialType = bFID64 ? "BIGSERIAL": "SERIAL";
+
+    CPLString osCreateTable;
+    const bool bTemporary = CPLFetchBool( papszOptions, "TEMPORARY", false );
+    if( bTemporary )
+    {
+        CPLFree(pszSchemaName);
+        pszSchemaName = CPLStrdup("pg_temp_1");
+        osCreateTable.Printf("CREATE TEMPORARY TABLE \"%s\"", pszTableName);
+    }
+    else
+    {
+        osCreateTable.Printf("CREATE TABLE%s \"%s\".\"%s\"",
+                             CPLFetchBool( papszOptions, "UNLOGGED", false ) ?
+                             " UNLOGGED": "",
+                             pszSchemaName, pszTableName);
+    }
+
+    if( !bHavePostGIS )
+    {
+        if (eType == wkbNone)
+            osCommand.Printf(
+                "%s ( "
+                "   %s %s, "
+                "   CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
+                osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
+                pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() );
+        else
+            osCommand.Printf(
+                "%s ( "
+                "   %s %s, "
+                "   WKB_GEOMETRY %s, "
+                "   CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
+                osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
+                pszSerialType, pszGeomType, pszTableName,
+                osFIDColumnNameEscaped.c_str() );
+    }
+    else if ( EQUAL(pszGeomType, "geography") )
+    {
+        if( CSLFetchNameValue( papszOptions, "GEOMETRY_NAME") != NULL )
+            pszGFldName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME");
+        else
+            pszGFldName = "the_geog";
+
+        const char *suffix = "";
+        if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) &&
+            (GeometryTypeFlags & OGRGeometry::OGR_G_3D) )
+        {
+            suffix = "ZM";
+        }
+        else if( (GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
+        {
+            suffix = "M";
+        }
+        else if( (GeometryTypeFlags & OGRGeometry::OGR_G_3D) )
+        {
+            suffix = "Z";
+        }
+
+        if( nSRSId )
+            osCommand.Printf(
+                "%s ( %s %s, \"%s\" geography(%s%s,%d), "
+                "CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
+                osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
+                pszSerialType, pszGFldName, pszGeometryType, suffix, nSRSId,
+                pszTableName, osFIDColumnNameEscaped.c_str() );
+        else
+            osCommand.Printf(
+                "%s ( %s %s, \"%s\" geography(%s%s), "
+                "CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
+                osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
+                pszSerialType, pszGFldName, pszGeometryType, suffix,
+                pszTableName, osFIDColumnNameEscaped.c_str() );
+    }
+    else
+    {
+        osCommand.Printf(
+            "%s ( %s %s, CONSTRAINT \"%s_pk\" PRIMARY KEY (%s) )",
+            osCreateTable.c_str(), osFIDColumnNameEscaped.c_str(),
+            pszSerialType, pszTableName, osFIDColumnNameEscaped.c_str() );
+    }
+
+    if( bCreateTable )
+        Log(osCommand);
+
+/* -------------------------------------------------------------------- */
+/*      Eventually we should be adding this table to a table of         */
+/*      "geometric layers", capturing the WKT projection, and           */
+/*      perhaps some other housekeeping.                                */
+/* -------------------------------------------------------------------- */
+    if( bCreateTable && bHavePostGIS && !EQUAL(pszGeomType, "geography") )
+    {
+        const char *suffix = "";
+        if( GeometryTypeFlags == static_cast<int>(OGRGeometry::OGR_G_MEASURED) &&
+            wkbFlatten(eType) != wkbUnknown )
+        {
+            suffix = "M";
+        }
+
+        osCommand.Printf(
+                "SELECT AddGeometryColumn('%s',%s,'%s',%d,'%s%s',%d)",
+                pszSchemaName, pszEscapedTableNameSingleQuote, pszGFldName,
+                nSRSId, pszGeometryType, suffix, nDimension );
+        Log(osCommand);
+    }
+
+    const char *pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
+    const bool bCreateSpatialIndex = pszSI == NULL || CPLTestBool(pszSI);
+    if( bCreateTable && bHavePostGIS && bCreateSpatialIndex )
+    {
+/* -------------------------------------------------------------------- */
+/*      Create the spatial index.                                       */
+/*                                                                      */
+/*      We're doing this before we add geometry and record to the table */
+/*      so this may not be exactly the best way to do it.               */
+/* -------------------------------------------------------------------- */
+        osCommand.Printf(
+            "CREATE INDEX \"%s_%s_geom_idx\" "
+            "ON \"%s\".\"%s\" "
+            "USING GIST (\"%s\")",
+            pszTableName, pszGFldName, pszSchemaName, pszTableName,
+            pszGFldName);
+
+        Log(osCommand);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create the layer object.                                        */
+/* -------------------------------------------------------------------- */
+    const bool bWriteAsHex =
+        !CPLFetchBool(papszOptions, "WRITE_EWKT_GEOM", false);
+
+    OGRPGDumpLayer *poLayer =
+        new OGRPGDumpLayer( this, pszSchemaName, pszTableName,
+                            osFIDColumnName, bWriteAsHex, bCreateTable );
+    poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", true) );
+    poLayer->SetPrecisionFlag( CPLFetchBool(papszOptions, "PRECISION", true));
+
+    const char* pszOverrideColumnTypes =
+        CSLFetchNameValue( papszOptions, "COLUMN_TYPES" );
+    poLayer->SetOverrideColumnTypes(pszOverrideColumnTypes);
+    poLayer->SetUnknownSRSId(nUnknownSRSId);
+    poLayer->SetForcedSRSId(nForcedSRSId);
+    poLayer->SetCreateSpatialIndexFlag(bCreateSpatialIndex);
+    poLayer->SetPostGISVersion(nPostGISMajor, nPostGISMinor);
+    poLayer->SetForcedGeometryTypeFlags(ForcedGeometryTypeFlags);
+
+    const char* pszDescription = CSLFetchNameValue(papszOptions, "DESCRIPTION");
+    if( pszDescription != NULL )
+        poLayer->SetForcedDescription( pszDescription );
+
+    if( bHavePostGIS )
+    {
+        OGRGeomFieldDefn oTmp( pszGFldName, eType );
+        OGRPGDumpGeomFieldDefn *poGeomField =
+            new OGRPGDumpGeomFieldDefn(&oTmp);
+        poGeomField->nSRSId = nSRSId;
+        poGeomField->GeometryTypeFlags = GeometryTypeFlags;
+        poLayer->GetLayerDefn()->AddGeomFieldDefn(poGeomField, FALSE);
+    }
+    else if( pszGFldName )
+        poLayer->SetGeometryFieldName(pszGFldName);
+
+/* -------------------------------------------------------------------- */
+/*      Add layer to data source layer list.                            */
+/* -------------------------------------------------------------------- */
+    papoLayers = (OGRPGDumpLayer **)
+        CPLRealloc( papoLayers,  sizeof(OGRPGDumpLayer *) * (nLayers+1) );
+
+    papoLayers[nLayers++] = poLayer;
+
+    CPLFree( pszTableName );
+    CPLFree( pszSchemaName );
+
+    return poLayer;
+}
+
+/************************************************************************/
+/*                           TestCapability()                           */
+/************************************************************************/
+
+int OGRPGDumpDataSource::TestCapability( const char * pszCap )
+
+{
+    if( EQUAL(pszCap,ODsCCreateLayer) )
+        return TRUE;
+    else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
+        return TRUE;
+    else if( EQUAL(pszCap,ODsCCurveGeometries) )
+        return TRUE;
+    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
+        return TRUE;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRPGDumpDataSource::GetLayer( int iLayer )
+
+{
+    if( iLayer < 0 || iLayer >= nLayers )
+        return NULL;
+    else
+        return papoLayers[iLayer];
+}
+
+/************************************************************************/
+/*                                  Log()                               */
+/************************************************************************/
+
+bool OGRPGDumpDataSource::Log( const char* pszStr, bool bAddSemiColumn )
+{
+    if( fp == NULL )
+    {
+        if( bTriedOpen )
+            return false;
+        bTriedOpen = true;
+        fp = VSIFOpenL(pszName, "wb");
+        if (fp == NULL)
+        {
+            CPLError(CE_Failure, CPLE_FileIO, "Cannot create %s", pszName);
+            return false;
+        }
+    }
+
+    if( bAddSemiColumn )
+        VSIFPrintfL(fp, "%s;%s", pszStr, pszEOL);
+    else
+        VSIFPrintfL(fp, "%s%s", pszStr, pszEOL);
+    return true;
+}
+
+/************************************************************************/
+/*                             StartCopy()                              */
+/************************************************************************/
+void OGRPGDumpDataSource::StartCopy( OGRPGDumpLayer *poPGLayer )
+{
+    EndCopy();
+    poLayerInCopyMode = poPGLayer;
+}
+
+/************************************************************************/
+/*                              EndCopy()                               */
+/************************************************************************/
+OGRErr OGRPGDumpDataSource::EndCopy()
+{
+    if( poLayerInCopyMode != NULL )
+    {
+        OGRErr result = poLayerInCopyMode->EndCopy();
+        poLayerInCopyMode = NULL;
+
+        return result;
+    }
+
+    return OGRERR_NONE;
+}
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
index c9f7acb..d96f162 100644
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumpdriver.cpp
@@ -1,140 +1,137 @@
-/******************************************************************************
- * $Id: ogrpgdumpdriver.cpp 33639 2016-03-04 23:39:40Z rouault $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements OGRPGDumpDriver class.
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_pgdump.h"
-#include "cpl_conv.h"
-
-CPL_CVSID("$Id: ogrpgdumpdriver.cpp 33639 2016-03-04 23:39:40Z rouault $");
-
-/************************************************************************/
-/*                         OGRPGDumpDriverCreate()                      */
-/************************************************************************/
-
-static GDALDataset* OGRPGDumpDriverCreate( const char * pszName,
-                                           CPL_UNUSED int nXSize,
-                                           CPL_UNUSED int nYSize,
-                                           CPL_UNUSED int nBands,
-                                           CPL_UNUSED GDALDataType eDT,
-                                           char ** papszOptions )
-{
-    OGRPGDumpDataSource     *poDS;
-
-    if (strcmp(pszName, "/dev/stdout") == 0)
-        pszName = "/vsistdout/";
-
-    poDS = new OGRPGDumpDataSource(pszName, papszOptions);
-    if( !poDS->Log("SET standard_conforming_strings = OFF") )
-    {
-        delete poDS;
-        return NULL;
-    }
-
-    return poDS;
-}
-
-/************************************************************************/
-/*                        RegisterOGRPGDump()                           */
-/************************************************************************/
-
-void RegisterOGRPGDump()
-
-{
-    if( GDALGetDriverByName( "PGDUMP" ) != NULL )
-        return;
-
-    GDALDriver *poDriver = new GDALDriver();
-
-    poDriver->SetDescription( "PGDUMP" );
-    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
-    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "PostgreSQL SQL dump" );
-    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_pgdump.html" );
-    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sql" );
-
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
-    "<CreationOptionList>"
-    #ifdef WIN32
-    "  <Option name='LINEFORMAT' type='string-select' description='end-of-line sequence' default='CRLF'>"
-    #else
-    "  <Option name='LINEFORMAT' type='string-select' description='end-of-line sequence' default='LF'>"
-    #endif
-    "    <Value>CRLF</Value>"
-    "    <Value>LF</Value>"
-    "  </Option>"
-    "</CreationOptionList>");
-
-    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
-    "<LayerCreationOptionList>"
-    "  <Option name='GEOM_TYPE' type='string-select' description='Format of geometry columns' default='geometry'>"
-    "    <Value>geometry</Value>"
-    "    <Value>geography</Value>"
-    "  </Option>"
-    "  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='YES'/>"
-    "  <Option name='PRECISION' type='boolean' description='Whether fields created should keep the width and precision' default='YES'/>"
-    "  <Option name='DIM' type='string' description='Set to 2 to force the geometries to be 2D, 3 to be 2.5D, XYM or XYZM'/>"
-    "  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column. Defaults to wkb_geometry for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography'/>"
-    "  <Option name='SCHEMA' type='string' description='Name of schema into which to create the new table'/>"
-    "  <Option name='CREATE_SCHEMA' type='boolean' description='Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema' default='YES'/>"
-    "  <Option name='SPATIAL_INDEX' type='boolean' description='Whether to create a spatial index' default='YES'/>"
-    "  <Option name='TEMPORARY' type='boolean' description='Whether to a temporary table instead of a permanent one' default='NO'/>"
-    "  <Option name='UNLOGGED' type='boolean' description='Whether to create the table as a unlogged one' default='NO'/>"
-    "  <Option name='WRITE_EWKT_GEOM' type='boolean' description='Whether to write EWKT geometries instead of HEX geometry' default='NO'/>"
-    "  <Option name='CREATE_TABLE' type='boolean' description='Whether to explicitly recreate the table if necessary' default='YES'/>"
-    "  <Option name='DROP_TABLE' type='string-select' description='Whether to explicitly destroy tables before recreating them' default='YES'>"
-    "    <Value>YES</Value>"
-    "    <Value>ON</Value>"
-    "    <Value>TRUE</Value>"
-    "    <Value>NO</Value>"
-    "    <Value>OFF</Value>"
-    "    <Value>FALSE</Value>"
-    "    <Value>IF_EXISTS</Value>"
-    "  </Option>"
-    "  <Option name='SRID' type='int' description='Forced SRID of the layer'/>"
-    "  <Option name='NONE_AS_UNKNOWN' type='boolean' description='Whether to force non-spatial layers to be created as spatial tables' default='NO'/>"
-    "  <Option name='FID' type='string' description='Name of the FID column to create' default='ogc_fid'/>"
-    "  <Option name='FID64' type='boolean' description='Whether to create the FID column with BIGSERIAL type to handle 64bit wide ids' default='NO'/>"
-    "  <Option name='EXTRACT_SCHEMA_FROM_LAYER_NAME' type='boolean' description='Whether a dot in a layer name should be considered as the separator for the schema and table name' default='YES'/>"
-    "  <Option name='COLUMN_TYPES' type='string' description='A list of strings of format field_name=pg_field_type (separated by comma) to force the PG column type of fields to be created'/>"
-    "  <Option name='POSTGIS_VERSION' type='string' description='Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. Important to set it correctly if using non-linear geometry types'/>"
-    "  <Option name='DESCRIPTION' type='string' description='Description string to put in the pg_description system table'/>"
-    "</LayerCreationOptionList>");
-
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
-                               "Integer Integer64 Real String Date DateTime "
-                               "Time IntegerList Integer64List RealList "
-                               "StringList Binary" );
-    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
-    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
-    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
-
-    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
-
-    poDriver->pfnCreate = OGRPGDumpDriverCreate;
-
-    GetGDALDriverManager()->RegisterDriver( poDriver );
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRPGDumpDriver class.
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_pgdump.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: ogrpgdumpdriver.cpp 35219 2016-08-27 22:39:24Z goatbar $");
+
+/************************************************************************/
+/*                         OGRPGDumpDriverCreate()                      */
+/************************************************************************/
+
+static GDALDataset* OGRPGDumpDriverCreate( const char * pszName,
+                                           CPL_UNUSED int nXSize,
+                                           CPL_UNUSED int nYSize,
+                                           CPL_UNUSED int nBands,
+                                           CPL_UNUSED GDALDataType eDT,
+                                           char ** papszOptions )
+{
+    if (strcmp(pszName, "/dev/stdout") == 0)
+        pszName = "/vsistdout/";
+
+    OGRPGDumpDataSource *poDS = new OGRPGDumpDataSource(pszName, papszOptions);
+    if( !poDS->Log("SET standard_conforming_strings = OFF") )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    return poDS;
+}
+
+/************************************************************************/
+/*                        RegisterOGRPGDump()                           */
+/************************************************************************/
+
+void RegisterOGRPGDump()
+
+{
+    if( GDALGetDriverByName( "PGDUMP" ) != NULL )
+        return;
+
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "PGDUMP" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "PostgreSQL SQL dump" );
+    poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_pgdump.html" );
+    poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sql" );
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    "<CreationOptionList>"
+    #ifdef WIN32
+    "  <Option name='LINEFORMAT' type='string-select' description='end-of-line sequence' default='CRLF'>"
+    #else
+    "  <Option name='LINEFORMAT' type='string-select' description='end-of-line sequence' default='LF'>"
+    #endif
+    "    <Value>CRLF</Value>"
+    "    <Value>LF</Value>"
+    "  </Option>"
+    "</CreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
+    "<LayerCreationOptionList>"
+    "  <Option name='GEOM_TYPE' type='string-select' description='Format of geometry columns' default='geometry'>"
+    "    <Value>geometry</Value>"
+    "    <Value>geography</Value>"
+    "  </Option>"
+    "  <Option name='LAUNDER' type='boolean' description='Whether layer and field names will be laundered' default='YES'/>"
+    "  <Option name='PRECISION' type='boolean' description='Whether fields created should keep the width and precision' default='YES'/>"
+    "  <Option name='DIM' type='string' description='Set to 2 to force the geometries to be 2D, 3 to be 2.5D, XYM or XYZM'/>"
+    "  <Option name='GEOMETRY_NAME' type='string' description='Name of geometry column. Defaults to wkb_geometry for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography'/>"
+    "  <Option name='SCHEMA' type='string' description='Name of schema into which to create the new table'/>"
+    "  <Option name='CREATE_SCHEMA' type='boolean' description='Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema' default='YES'/>"
+    "  <Option name='SPATIAL_INDEX' type='boolean' description='Whether to create a spatial index' default='YES'/>"
+    "  <Option name='TEMPORARY' type='boolean' description='Whether to a temporary table instead of a permanent one' default='NO'/>"
+    "  <Option name='UNLOGGED' type='boolean' description='Whether to create the table as a unlogged one' default='NO'/>"
+    "  <Option name='WRITE_EWKT_GEOM' type='boolean' description='Whether to write EWKT geometries instead of HEX geometry' default='NO'/>"
+    "  <Option name='CREATE_TABLE' type='boolean' description='Whether to explicitly recreate the table if necessary' default='YES'/>"
+    "  <Option name='DROP_TABLE' type='string-select' description='Whether to explicitly destroy tables before recreating them' default='YES'>"
+    "    <Value>YES</Value>"
+    "    <Value>ON</Value>"
+    "    <Value>TRUE</Value>"
+    "    <Value>NO</Value>"
+    "    <Value>OFF</Value>"
+    "    <Value>FALSE</Value>"
+    "    <Value>IF_EXISTS</Value>"
+    "  </Option>"
+    "  <Option name='SRID' type='int' description='Forced SRID of the layer'/>"
+    "  <Option name='NONE_AS_UNKNOWN' type='boolean' description='Whether to force non-spatial layers to be created as spatial tables' default='NO'/>"
+    "  <Option name='FID' type='string' description='Name of the FID column to create' default='ogc_fid'/>"
+    "  <Option name='FID64' type='boolean' description='Whether to create the FID column with BIGSERIAL type to handle 64bit wide ids' default='NO'/>"
+    "  <Option name='EXTRACT_SCHEMA_FROM_LAYER_NAME' type='boolean' description='Whether a dot in a layer name should be considered as the separator for the schema and table name' default='YES'/>"
+    "  <Option name='COLUMN_TYPES' type='string' description='A list of strings of format field_name=pg_field_type (separated by comma) to force the PG column type of fields to be created'/>"
+    "  <Option name='POSTGIS_VERSION' type='string' description='Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. Important to set it correctly if using non-linear geometry types'/>"
+    "  <Option name='DESCRIPTION' type='string' description='Description string to put in the pg_description system table'/>"
+    "</LayerCreationOptionList>");
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
+                               "Integer Integer64 Real String Date DateTime "
+                               "Time IntegerList Integer64List RealList "
+                               "StringList Binary" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
+
+    poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
+
+    poDriver->pfnCreate = OGRPGDumpDriverCreate;
+
+    GetGDALDriverManager()->RegisterDriver( poDriver );
+}
diff --git a/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp b/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
index a884986..25e96cb 100644
--- a/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
+++ b/ogr/ogrsf_frmts/pgdump/ogrpgdumplayer.cpp
@@ -1,1827 +1,1844 @@
-/******************************************************************************
- * $Id: ogrpgdumplayer.cpp 34482 2016-06-30 18:57:36Z rouault $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Implements OGRPGDumpLayer class
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogr_pgdump.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-#include "ogr_p.h"
-
-CPL_CVSID("$Id: ogrpgdumplayer.cpp 34482 2016-06-30 18:57:36Z rouault $");
-
-#define USE_COPY_UNSET -1
-
-static CPLString OGRPGDumpEscapeStringList(
-                                       char** papszItems, int bForInsertOrUpdate,
-                                       OGRPGCommonEscapeStringCbk pfnEscapeString,
-                                       void* userdata);
-
-static CPLString OGRPGDumpEscapeStringWithUserData(   CPL_UNUSED void* user_data,
-                                   const char* pszStrValue, int nMaxLength,
-                                   CPL_UNUSED const char* pszLayerName,
-                                   const char* pszFieldName)
-{
-    return OGRPGDumpEscapeString(pszStrValue, nMaxLength, pszFieldName);
-}
-
-/************************************************************************/
-/*                        OGRPGDumpLayer()                              */
-/************************************************************************/
-
-OGRPGDumpLayer::OGRPGDumpLayer(OGRPGDumpDataSource* poDSIn,
-                               const char* pszSchemaNameIn,
-                               const char* pszTableName,
-                               const char *pszFIDColumnIn,
-                               int         bWriteAsHexIn,
-                               int         bCreateTableIn)
-{
-    this->poDS = poDSIn;
-    this->pszSchemaName = CPLStrdup(pszSchemaNameIn);
-    this->pszFIDColumn = CPLStrdup(pszFIDColumnIn);
-    this->bCreateTable = bCreateTableIn;
-    poFeatureDefn = new OGRFeatureDefn( pszTableName );
-    SetDescription( poFeatureDefn->GetName() );
-    poFeatureDefn->SetGeomType(wkbNone);
-    poFeatureDefn->Reference();
-    pszSqlTableName = CPLStrdup(CPLString().Printf("%s.%s",
-                               OGRPGDumpEscapeColumnName(pszSchemaName).c_str(),
-                               OGRPGDumpEscapeColumnName(pszTableName).c_str() ));
-    bLaunderColumnNames = TRUE;
-    bPreservePrecision = TRUE;
-    bUseCopy = USE_COPY_UNSET;
-    bFIDColumnInCopyFields = FALSE;
-    bWriteAsHex = bWriteAsHexIn;
-    bCopyActive = FALSE;
-    papszOverrideColumnTypes = NULL;
-    nUnknownSRSId = -1;
-    nForcedSRSId = -2;
-    nForcedGeometryTypeFlags = -1;
-    bCreateSpatialIndexFlag = TRUE;
-    nPostGISMajor = 1;
-    nPostGISMinor = 2;
-    iNextShapeId = 0;
-    iFIDAsRegularColumnIndex = -1;
-    bAutoFIDOnCreateViaCopy = TRUE;
-    bCopyStatementWithFID = FALSE;
-}
-
-/************************************************************************/
-/*                          ~OGRPGDumpLayer()                           */
-/************************************************************************/
-
-OGRPGDumpLayer::~OGRPGDumpLayer()
-{
-    EndCopy();
-
-    poFeatureDefn->Release();
-    CPLFree(pszSchemaName);
-    CPLFree(pszSqlTableName);
-    CPLFree(pszFIDColumn);
-    CSLDestroy(papszOverrideColumnTypes);
-}
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRFeature *OGRPGDumpLayer::GetNextFeature()
-{
-    CPLError(CE_Failure, CPLE_NotSupported, "PGDump driver is write only");
-    return NULL;
-}
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-int OGRPGDumpLayer::TestCapability( const char * pszCap )
-{
-    if( EQUAL(pszCap,OLCSequentialWrite) ||
-        EQUAL(pszCap,OLCCreateField) ||
-        EQUAL(pszCap,OLCCreateGeomField) ||
-        EQUAL(pszCap,OLCCurveGeometries) ||
-        EQUAL(pszCap,OLCMeasuredGeometries) )
-        return TRUE;
-    else
-        return FALSE;
-}
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRErr OGRPGDumpLayer::ICreateFeature( OGRFeature *poFeature )
-{
-    if( NULL == poFeature )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "NULL pointer to OGRFeature passed to CreateFeature()." );
-        return OGRERR_FAILURE;
-    }
-
-    /* In case the FID column has also been created as a regular field */
-    if( iFIDAsRegularColumnIndex >= 0 )
-    {
-        if( poFeature->GetFID() == OGRNullFID )
-        {
-            if( poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) )
-            {
-                poFeature->SetFID(
-                    poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex));
-            }
-        }
-        else
-        {
-            if( !poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) ||
-                poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex) != poFeature->GetFID() )
-            {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                            "Inconsistent values of FID and field of same name");
-                return OGRERR_FAILURE;
-            }
-        }
-    }
-
-    if( !poFeature->Validate((OGR_F_VAL_ALL & ~OGR_F_VAL_WIDTH) | OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM, TRUE ) )
-        return OGRERR_FAILURE;
-
-    // We avoid testing the config option too often. 
-    if( bUseCopy == USE_COPY_UNSET )
-        bUseCopy = CPLTestBool( CPLGetConfigOption( "PG_USE_COPY", "NO") );
-
-    OGRErr eErr;
-    if( !bUseCopy )
-    {
-        eErr = CreateFeatureViaInsert( poFeature );
-    }
-    else
-    {
-        /* If there's a unset field with a default value, then we must use */
-        /* a specific INSERT statement to avoid unset fields to be bound to NULL */
-        int bHasDefaultValue = FALSE;
-        int iField;
-        int nFieldCount = poFeatureDefn->GetFieldCount();
-        for( iField = 0; iField < nFieldCount; iField++ )
-        {
-            if( !poFeature->IsFieldSet( iField ) &&
-                poFeature->GetFieldDefnRef(iField)->GetDefault() != NULL )
-            {
-                bHasDefaultValue = TRUE;
-                break;
-            }
-        }
-        if( bHasDefaultValue )
-        {
-            EndCopy();
-            eErr = CreateFeatureViaInsert( poFeature );
-        }
-        else
-        {
-            int bFIDSet = (poFeature->GetFID() != OGRNullFID);
-            if( bCopyActive && bFIDSet != bCopyStatementWithFID )
-            {
-                EndCopy();
-                eErr = CreateFeatureViaInsert( poFeature );
-            }
-            else
-            {
-                if ( !bCopyActive )
-                {
-                    /* This is a heuristics. If the first feature to be copied has a */
-                    /* FID set (and that a FID column has been identified), then we will */
-                    /* try to copy FID values from features. Otherwise, we will not */
-                    /* do and assume that the FID column is an autoincremented column. */
-                    StartCopy(bFIDSet);
-                    bCopyStatementWithFID = bFIDSet;
-                }
-
-                eErr = CreateFeatureViaCopy( poFeature );
-                if( bFIDSet )
-                    bAutoFIDOnCreateViaCopy = FALSE;
-                if( eErr == OGRERR_NONE && bAutoFIDOnCreateViaCopy )
-                {
-                    poFeature->SetFID( ++iNextShapeId );
-                }
-            }
-        }
-    }
-
-    if( eErr == OGRERR_NONE && iFIDAsRegularColumnIndex >= 0 )
-    {
-        poFeature->SetField(iFIDAsRegularColumnIndex, poFeature->GetFID());
-    }
-    return eErr;
-}
-
-/************************************************************************/
-/*                       CreateFeatureViaInsert()                       */
-/************************************************************************/
-
-OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
-
-{
-    CPLString           osCommand;
-    int                 i = 0;
-    int                 bNeedComma = FALSE;
-    OGRErr              eErr = OGRERR_FAILURE;
-    int bEmptyInsert = FALSE;
-    
-    if( NULL == poFeature )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "NULL pointer to OGRFeature passed to CreateFeatureViaInsert()." );
-        return eErr;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Form the INSERT command.                                        */
-/* -------------------------------------------------------------------- */
-    osCommand.Printf( "INSERT INTO %s (", pszSqlTableName );
-
-    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
-    {
-        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
-        if( poGeom != NULL )
-        {
-            if( bNeedComma )
-                osCommand += ", ";
-
-            OGRGeomFieldDefn* poGFldDefn = poFeature->GetGeomFieldDefnRef(i);
-            osCommand = osCommand + OGRPGDumpEscapeColumnName(poGFldDefn->GetNameRef()) + " ";
-            bNeedComma = TRUE;
-        }
-    }
-
-    if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
-    {
-        if( bNeedComma )
-            osCommand += ", ";
-        
-        osCommand = osCommand + OGRPGDumpEscapeColumnName(pszFIDColumn) + " ";
-        bNeedComma = TRUE;
-    }
-
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
-    {
-        if( i == iFIDAsRegularColumnIndex )
-            continue;
-        if( !poFeature->IsFieldSet( i ) )
-            continue;
-
-        if( !bNeedComma )
-            bNeedComma = TRUE;
-        else
-            osCommand += ", ";
-
-        osCommand = osCommand 
-            + OGRPGDumpEscapeColumnName(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
-    }
-
-    if (!bNeedComma)
-        bEmptyInsert = TRUE;
-
-    osCommand += ") VALUES (";
-
-    /* Set the geometry */
-    bNeedComma = FALSE;
-    for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
-    {
-        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
-        if( poGeom != NULL )
-        {
-            char    *pszWKT = NULL;
-            
-            OGRPGDumpGeomFieldDefn* poGFldDefn =
-                (OGRPGDumpGeomFieldDefn*) poFeature->GetGeomFieldDefnRef(i);
-
-            poGeom->closeRings();
-            poGeom->set3D(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D);
-            poGeom->setMeasured(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
-
-            if( bNeedComma )
-                osCommand += ", ";
-
-            if( bWriteAsHex )
-            {
-                char* pszHex = OGRGeometryToHexEWKB( poGeom, poGFldDefn->nSRSId,
-                                                     nPostGISMajor,
-                                                     nPostGISMinor );
-                osCommand += "'";
-                if (pszHex)
-                    osCommand += pszHex;
-                osCommand += "'";
-                CPLFree(pszHex);
-            }
-            else
-            {
-                poGeom->exportToWkt( &pszWKT );
-
-                if( pszWKT != NULL )
-                {
-                    osCommand +=
-                        CPLString().Printf(
-                            "GeomFromEWKT('SRID=%d;%s'::TEXT) ", poGFldDefn->nSRSId, pszWKT );
-                    OGRFree( pszWKT );
-                }
-                else
-                    osCommand += "''";
-            }
-
-            bNeedComma = TRUE;
-        }
-    }
-
-    /* Set the FID */
-    if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
-    {
-        if( bNeedComma )
-            osCommand += ", ";
-        osCommand += CPLString().Printf( CPL_FRMT_GIB, poFeature->GetFID() );
-        bNeedComma = TRUE;
-    }
-
-
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
-    {
-        if( i == iFIDAsRegularColumnIndex )
-            continue;
-        if( !poFeature->IsFieldSet( i ) )
-            continue;
-
-        if( bNeedComma )
-            osCommand += ", ";
-        else
-            bNeedComma = TRUE;
-
-        OGRPGCommonAppendFieldValue(osCommand, poFeature, i,
-                                    OGRPGDumpEscapeStringWithUserData, NULL);
-    }
-
-    osCommand += ")";
-
-    if (bEmptyInsert)
-        osCommand.Printf( "INSERT INTO %s DEFAULT VALUES", pszSqlTableName );
-
-/* -------------------------------------------------------------------- */
-/*      Execute the insert.                                             */
-/* -------------------------------------------------------------------- */
-    poDS->Log(osCommand);
-
-    if( poFeature->GetFID() == OGRNullFID )
-        poFeature->SetFID( ++iNextShapeId );
-
-    return OGRERR_NONE;
-}
-
-
-/************************************************************************/
-/*                        CreateFeatureViaCopy()                        */
-/************************************************************************/
-
-OGRErr OGRPGDumpLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
-{
-    int                  i;
-    CPLString            osCommand;
-
-    /* First process geometry */
-    for( i = 0; i < poFeature->GetGeomFieldCount(); i++ )
-    {
-        OGRGeometry *poGeometry = poFeature->GetGeomFieldRef(i);
-        char *pszGeom = NULL;
-        if ( NULL != poGeometry /* && (bHasWkb || bHasPostGISGeometry || bHasPostGISGeography) */)
-        {
-            OGRPGDumpGeomFieldDefn* poGFldDefn =
-                (OGRPGDumpGeomFieldDefn*) poFeature->GetGeomFieldDefnRef(i);
-
-            poGeometry->closeRings();
-            poGeometry->set3D(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D);
-            poGeometry->setMeasured(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
-
-            //CheckGeomTypeCompatibility(poGeometry);
-    
-            /*if (bHasWkb)
-                pszGeom = GeometryToBYTEA( poGeometry );
-            else*/
-                pszGeom = OGRGeometryToHexEWKB( poGeometry, poGFldDefn->nSRSId,
-                                                nPostGISMajor,
-                                                nPostGISMinor );
-        }
-    
-        if (osCommand.size() > 0)
-            osCommand += "\t";
-        if ( pszGeom )
-        {
-            osCommand += pszGeom,
-            CPLFree( pszGeom );
-        }
-        else
-        {
-            osCommand += "\\N";
-        }
-    }
-    
-    OGRPGCommonAppendCopyFieldsExceptGeom(osCommand,
-                                          poFeature,
-                                          pszFIDColumn,
-                                          bFIDColumnInCopyFields,
-                                          OGRPGDumpEscapeStringWithUserData,
-                                          NULL);
-
-    /* Add end of line marker */
-    //osCommand += "\n";
-
-
-    /* ------------------------------------------------------------ */
-    /*      Execute the copy.                                       */
-    /* ------------------------------------------------------------ */
-
-    OGRErr result = OGRERR_NONE;
-
-    poDS->Log(osCommand, FALSE);
-
-    return result;
-}
-
-/************************************************************************/
-/*                OGRPGCommonAppendCopyFieldsExceptGeom()               */
-/************************************************************************/
-
-void OGRPGCommonAppendCopyFieldsExceptGeom(CPLString& osCommand,
-                                           OGRFeature* poFeature,
-                                           const char* pszFIDColumn,
-                                           int bFIDColumnInCopyFields,
-                                           OGRPGCommonEscapeStringCbk pfnEscapeString,
-                                           void* userdata)
-{
-    int i;
-    OGRFeatureDefn* poFeatureDefn = poFeature->GetDefnRef();
-    
-    /* Next process the field id column */
-    int nFIDIndex = -1;
-    if( bFIDColumnInCopyFields )
-    {
-        if (osCommand.size() > 0)
-            osCommand += "\t";
-
-        nFIDIndex = poFeatureDefn->GetFieldIndex( pszFIDColumn ); 
-
-        /* Set the FID */
-        if( poFeature->GetFID() != OGRNullFID )
-        {
-            osCommand += CPLString().Printf( CPL_FRMT_GIB, poFeature->GetFID());
-        }
-        else
-        {
-            osCommand += "\\N" ;
-        }
-    }
-
-
-    /* Now process the remaining fields */
-
-    int nFieldCount = poFeatureDefn->GetFieldCount();
-    int bAddTab = osCommand.size() > 0; 
-
-    for( i = 0; i < nFieldCount;  i++ )
-    {
-        if (i == nFIDIndex)
-            continue;
-
-        const char *pszStrValue = poFeature->GetFieldAsString(i);
-        char *pszNeedToFree = NULL;
-
-        if (bAddTab)
-            osCommand += "\t";
-        bAddTab = TRUE; 
-
-        if( !poFeature->IsFieldSet( i ) )
-        {
-            osCommand += "\\N" ;
-
-            continue;
-        }
-
-        int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
-
-        // We need special formatting for integer list values.
-        if( nOGRFieldType == OFTIntegerList )
-        {
-            int nCount, nOff = 0, j;
-            const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);
-
-            const size_t nLen = nCount * 13 + 10;
-            pszNeedToFree = (char *) CPLMalloc(nLen);
-            strcpy( pszNeedToFree, "{" );
-            for( j = 0; j < nCount; j++ )
-            {
-                if( j != 0 )
-                    strcat( pszNeedToFree+nOff, "," );
-
-                nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
-                snprintf( pszNeedToFree+nOff, nLen-nOff, "%d", panItems[j] );
-            }
-            strcat( pszNeedToFree+nOff, "}" );
-            pszStrValue = pszNeedToFree;
-        }
-        
-        else if( nOGRFieldType == OFTInteger64List )
-        {
-            int nCount, nOff = 0, j;
-            const GIntBig *panItems = poFeature->GetFieldAsInteger64List(i,&nCount);
-
-            const size_t nLen = nCount * 26 + 10;
-            pszNeedToFree = (char *) CPLMalloc(nLen);
-            strcpy( pszNeedToFree, "{" );
-            for( j = 0; j < nCount; j++ )
-            {
-                if( j != 0 )
-                    strcat( pszNeedToFree+nOff, "," );
-
-                nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
-                snprintf( pszNeedToFree+nOff, nLen-nOff, CPL_FRMT_GIB, panItems[j] );
-            }
-            strcat( pszNeedToFree+nOff, "}" );
-            pszStrValue = pszNeedToFree;
-        }
-
-        // We need special formatting for real list values.
-        else if( nOGRFieldType == OFTRealList )
-        {
-            int nCount, nOff = 0, j;
-            const double *padfItems =poFeature->GetFieldAsDoubleList(i,&nCount);
-
-            const size_t nLen = nCount * 40 + 10;
-            pszNeedToFree = (char *) CPLMalloc(nLen);
-            strcpy( pszNeedToFree, "{" );
-            for( j = 0; j < nCount; j++ )
-            {
-                if( j != 0 )
-                    strcat( pszNeedToFree+nOff, "," );
-
-                nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
-                //Check for special values. They need to be quoted.
-                if( CPLIsNan(padfItems[j]) )
-                    snprintf( pszNeedToFree+nOff, nLen-nOff, "NaN" );
-                else if( CPLIsInf(padfItems[j]) )
-                    snprintf( pszNeedToFree+nOff, nLen-nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
-                else
-                    CPLsnprintf( pszNeedToFree+nOff, nLen-nOff, "%.16g", padfItems[j] );
-
-            }
-            strcat( pszNeedToFree+nOff, "}" );
-            pszStrValue = pszNeedToFree;
-        }
-
-
-        // We need special formatting for string list values.
-        else if( nOGRFieldType == OFTStringList )
-        {
-            CPLString osStr;
-            char **papszItems = poFeature->GetFieldAsStringList(i);
-
-            pszStrValue = pszNeedToFree = CPLStrdup(
-                OGRPGDumpEscapeStringList(papszItems, FALSE,
-                                          pfnEscapeString, userdata));
-        }
-
-        // Binary formatting
-        else if( nOGRFieldType == OFTBinary )
-        {
-            int nLen = 0;
-            GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );
-            char* pszBytea = OGRPGDumpLayer::GByteArrayToBYTEA( pabyData, nLen);
-
-            pszStrValue = pszNeedToFree = pszBytea;
-        }
-
-        else if( nOGRFieldType == OFTReal )
-        {
-            //Check for special values. They need to be quoted.
-            double dfVal = poFeature->GetFieldAsDouble(i);
-            if( CPLIsNan(dfVal) )
-                pszStrValue = "NaN";
-            else if( CPLIsInf(dfVal) )
-                pszStrValue = (dfVal > 0) ? "Infinity" : "-Infinity";
-        }
-
-        if( nOGRFieldType != OFTIntegerList &&
-            nOGRFieldType != OFTInteger64List &&
-            nOGRFieldType != OFTRealList &&
-            nOGRFieldType != OFTInteger &&
-            nOGRFieldType != OFTInteger64 &&
-            nOGRFieldType != OFTReal &&
-            nOGRFieldType != OFTBinary )
-        {
-            int         iChar;
-            int         iUTFChar = 0;
-            int         nMaxWidth = poFeatureDefn->GetFieldDefn(i)->GetWidth();
-
-            for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
-            {
-                //count of utf chars
-                if (nOGRFieldType != OFTStringList && (pszStrValue[iChar] & 0xc0) != 0x80) 
-                {
-                    if( nMaxWidth > 0 && iUTFChar == nMaxWidth )
-                    {
-                        CPLDebug( "PG",
-                                "Truncated %s field value, it was too long.",
-                                poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
-                        break;
-                    }
-                    iUTFChar++;
-                }
-
-                /* Escape embedded \, \t, \n, \r since they will cause COPY
-                   to misinterpret a line of text and thus abort */
-                if( pszStrValue[iChar] == '\\' || 
-                    pszStrValue[iChar] == '\t' || 
-                    pszStrValue[iChar] == '\r' || 
-                    pszStrValue[iChar] == '\n'   )
-                {
-                    osCommand += '\\';
-                }
-
-                osCommand += pszStrValue[iChar];
-            }
-        }
-        else
-        {
-            osCommand += pszStrValue;
-        }
-
-        if( pszNeedToFree )
-            CPLFree( pszNeedToFree );
-    }
-}
-
-/************************************************************************/
-/*                             StartCopy()                              */
-/************************************************************************/
-
-OGRErr OGRPGDumpLayer::StartCopy(int bSetFID)
-
-{
-    /* Tell the datasource we are now planning to copy data */
-    poDS->StartCopy( this ); 
-
-    CPLString osFields = BuildCopyFields(bSetFID);
-
-    size_t size = strlen(osFields) +  strlen(pszSqlTableName) + 100;
-    char *pszCommand = (char *) CPLMalloc(size);
-
-    snprintf( pszCommand, size,
-             "COPY %s (%s) FROM STDIN",
-             pszSqlTableName, osFields.c_str() );
-
-    poDS->Log(pszCommand);
-    bCopyActive = TRUE;
-
-    CPLFree( pszCommand );
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                              EndCopy()                               */
-/************************************************************************/
-
-OGRErr OGRPGDumpLayer::EndCopy()
-
-{
-    if( !bCopyActive )
-        return OGRERR_NONE;
-
-    bCopyActive = FALSE;
-
-    poDS->Log("\\.", FALSE);
-    poDS->Log("END");
-
-    bUseCopy = USE_COPY_UNSET;
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                          BuildCopyFields()                           */
-/************************************************************************/
-
-CPLString OGRPGDumpLayer::BuildCopyFields(int bSetFID)
-{
-    int     i = 0;
-    int     nFIDIndex = -1; 
-    CPLString osFieldList;
-
-    for( i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
-    {
-        if( osFieldList.size() > 0 )
-            osFieldList += ", ";
-        
-        OGRGeomFieldDefn* poGFldDefn = poFeatureDefn->GetGeomFieldDefn(i);
-        
-        osFieldList += OGRPGDumpEscapeColumnName(poGFldDefn->GetNameRef());
-    }
-
-    bFIDColumnInCopyFields = (pszFIDColumn != NULL && bSetFID);
-    if( bFIDColumnInCopyFields )
-    {
-        if( osFieldList.size() > 0 )
-            osFieldList += ", ";
-
-        nFIDIndex = poFeatureDefn->GetFieldIndex( pszFIDColumn );
-
-        osFieldList += OGRPGDumpEscapeColumnName(pszFIDColumn); 
-    }
-
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
-    {
-        if (i == nFIDIndex)
-            continue;
-
-        const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
-
-       if( osFieldList.size() > 0 )
-            osFieldList += ", ";
-
-        osFieldList += OGRPGDumpEscapeColumnName(pszName);
-    }
-
-    return osFieldList;
-}
-
-/************************************************************************/
-/*                       OGRPGDumpEscapeColumnName( )                   */
-/************************************************************************/
-
-CPLString OGRPGDumpEscapeColumnName(const char* pszColumnName)
-{
-    CPLString osStr;
-
-    osStr += "\"";
-
-    char ch;
-    for(int i=0; (ch = pszColumnName[i]) != '\0'; i++)
-    {
-        if (ch == '"')
-            osStr.append(1, ch);
-        osStr.append(1, ch);
-    }
-
-    osStr += "\"";
-
-    return osStr;
-}
-
-/************************************************************************/
-/*                             EscapeString( )                          */
-/************************************************************************/
-
-CPLString OGRPGDumpEscapeString(   
-                                   const char* pszStrValue, int nMaxLength,
-                                   const char* pszFieldName)
-{
-    CPLString osCommand;
-
-    /* We need to quote and escape string fields. */
-    osCommand += "'";
-
-    int nSrcLen = static_cast<int>(strlen(pszStrValue));
-    int nSrcLenUTF = CPLStrlenUTF8(pszStrValue);
-
-    if (nMaxLength > 0 && nSrcLenUTF > nMaxLength)
-    {
-        CPLDebug( "PG",
-                  "Truncated %s field value, it was too long.",
-                  pszFieldName );
-
-        int iUTF8Char = 0;
-        for(int iChar = 0; iChar < nSrcLen; iChar++ )
-        {
-            if( (((unsigned char *) pszStrValue)[iChar] & 0xc0) != 0x80 )
-            {
-                if( iUTF8Char == nMaxLength )
-                {
-                    nSrcLen = iChar;
-                    break;
-                }
-                iUTF8Char ++;
-            }
-        }
-    }
-
-    char* pszDestStr = (char*)CPLMalloc(2 * nSrcLen + 1);
-
-    /* -------------------------------------------------------------------- */
-    /*  PQescapeStringConn was introduced in PostgreSQL security releases   */
-    /*  8.1.4, 8.0.8, 7.4.13, 7.3.15                                        */
-    /*  PG_HAS_PQESCAPESTRINGCONN is added by a test in 'configure'         */
-    /*  so it is not set by default when building OGR for Win32             */
-    /* -------------------------------------------------------------------- */
-#if defined(PG_HAS_PQESCAPESTRINGCONN)
-    int nError;
-    PQescapeStringConn (hPGConn, pszDestStr, pszStrValue, nSrcLen, &nError);
-    if (nError == 0)
-        osCommand += pszDestStr;
-    else
-        CPLError(CE_Warning, CPLE_AppDefined, 
-                 "PQescapeString(): %s\n"
-                 "  input: '%s'\n"
-                 "    got: '%s'\n",
-                 PQerrorMessage( hPGConn ),
-                 pszStrValue, pszDestStr );
-#else
-    //PQescapeString(pszDestStr, pszStrValue, nSrcLen);
-    
-    int i, j;
-    for(i=0,j=0; i < nSrcLen; i++)
-    {
-        if (pszStrValue[i] == '\'')
-        {
-            pszDestStr[j++] = '\'';
-            pszDestStr[j++] = '\'';
-        }
-        /* FIXME: at some point (when we drop PostgreSQL < 9.1 support, remove
-           the escaping of backslash and remove 'SET standard_conforming_strings = OFF'
-           inICreateLayer() */
-        else if (pszStrValue[i] == '\\')
-        {
-            pszDestStr[j++] = '\\';
-            pszDestStr[j++] = '\\';
-        }
-        else
-            pszDestStr[j++] = pszStrValue[i];
-    }
-    pszDestStr[j] = 0;
-
-    osCommand += pszDestStr;
-#endif
-    CPLFree(pszDestStr);
-
-    osCommand += "'";
-
-    return osCommand;
-}
-
-
-/************************************************************************/
-/*                    OGRPGDumpEscapeStringList( )                      */
-/************************************************************************/
-
-static CPLString OGRPGDumpEscapeStringList(
-                                       char** papszItems, int bForInsertOrUpdate,
-                                       OGRPGCommonEscapeStringCbk pfnEscapeString,
-                                       void* userdata)
-{
-    int bFirstItem = TRUE;
-    CPLString osStr;
-    if (bForInsertOrUpdate)
-        osStr += "ARRAY[";
-    else
-        osStr += "{";
-    while(papszItems && *papszItems)
-    {
-        if (!bFirstItem)
-        {
-            osStr += ',';
-        }
-
-        char* pszStr = *papszItems;
-        if (*pszStr != '\0')
-        {
-            if (bForInsertOrUpdate)
-                osStr += pfnEscapeString(userdata, pszStr, 0, "", "");
-            else
-            {
-                osStr += '"';
-
-                while(*pszStr)
-                {
-                    if (*pszStr == '"' )
-                        osStr += "\\";
-                    osStr += *pszStr;
-                    pszStr++;
-                }
-
-                osStr += '"';
-            }
-        }
-        else
-            osStr += "NULL";
-
-        bFirstItem = FALSE;
-
-        papszItems++;
-    }
-    if (bForInsertOrUpdate)
-    {
-        osStr += "]";
-        if( papszItems == NULL )
-            osStr += "::varchar[]";
-    }
-    else
-        osStr += "}";
-    return osStr;
-}
-
-/************************************************************************/
-/*                          AppendFieldValue()                          */
-/*                                                                      */
-/* Used by CreateFeatureViaInsert() and SetFeature() to format a        */
-/* non-empty field value                                                */
-/************************************************************************/
-
-void OGRPGCommonAppendFieldValue(CPLString& osCommand,
-                                 OGRFeature* poFeature, int i,
-                                 OGRPGCommonEscapeStringCbk pfnEscapeString,
-                                 void* userdata)
-{
-    OGRFeatureDefn* poFeatureDefn = poFeature->GetDefnRef();
-    OGRFieldType nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
-    OGRFieldSubType eSubType = poFeatureDefn->GetFieldDefn(i)->GetSubType();
-
-    // We need special formatting for integer list values.
-    if(  nOGRFieldType == OFTIntegerList )
-    {
-        int nCount, nOff = 0, j;
-        const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);
-        char *pszNeedToFree = NULL;
-
-        const size_t nLen = nCount * 13 + 10;
-        pszNeedToFree = (char *) CPLMalloc(nLen);
-        strcpy( pszNeedToFree, "'{" );
-        for( j = 0; j < nCount; j++ )
-        {
-            if( j != 0 )
-                strcat( pszNeedToFree+nOff, "," );
-
-            nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
-            snprintf( pszNeedToFree+nOff, nLen-nOff, "%d", panItems[j] );
-        }
-        strcat( pszNeedToFree+nOff, "}'" );
-
-        osCommand += pszNeedToFree;
-        CPLFree(pszNeedToFree);
-
-        return;
-    }
-    
-    else if(  nOGRFieldType == OFTInteger64List )
-    {
-        int nCount, nOff = 0, j;
-        const GIntBig *panItems = poFeature->GetFieldAsInteger64List(i,&nCount);
-        char *pszNeedToFree = NULL;
-
-        const size_t nLen = nCount * 26 + 10;
-        pszNeedToFree = (char *) CPLMalloc(nLen);
-        strcpy( pszNeedToFree, "'{" );
-        for( j = 0; j < nCount; j++ )
-        {
-            if( j != 0 )
-                strcat( pszNeedToFree+nOff, "," );
-
-            nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
-            snprintf( pszNeedToFree+nOff, nLen-nOff, CPL_FRMT_GIB, panItems[j] );
-        }
-        strcat( pszNeedToFree+nOff, "}'" );
-
-        osCommand += pszNeedToFree;
-        CPLFree(pszNeedToFree);
-
-        return;
-    }
-
-    // We need special formatting for real list values.
-    else if( nOGRFieldType == OFTRealList )
-    {
-        int nCount, nOff = 0, j;
-        const double *padfItems =poFeature->GetFieldAsDoubleList(i,&nCount);
-        char *pszNeedToFree = NULL;
-
-        const size_t nLen = nCount * 40 + 10;
-        pszNeedToFree = (char *) CPLMalloc(nLen);
-        strcpy( pszNeedToFree, "'{" );
-        for( j = 0; j < nCount; j++ )
-        {
-            if( j != 0 )
-                strcat( pszNeedToFree+nOff, "," );
-
-            nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
-            //Check for special values. They need to be quoted.
-            if( CPLIsNan(padfItems[j]) )
-                snprintf( pszNeedToFree+nOff, nLen-nOff, "NaN" );
-            else if( CPLIsInf(padfItems[j]) )
-                snprintf( pszNeedToFree+nOff, nLen-nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
-            else
-                CPLsnprintf( pszNeedToFree+nOff, nLen-nOff, "%.16g", padfItems[j] );
-
-        }
-        strcat( pszNeedToFree+nOff, "}'" );
-
-        osCommand += pszNeedToFree;
-        CPLFree(pszNeedToFree);
-
-        return;
-    }
-
-    // We need special formatting for string list values.
-    else if( nOGRFieldType == OFTStringList )
-    {
-        char **papszItems = poFeature->GetFieldAsStringList(i);
-
-        osCommand += OGRPGDumpEscapeStringList(papszItems, TRUE,
-                                               pfnEscapeString, userdata);
-
-        return;
-    }
-
-    // Binary formatting
-    else if( nOGRFieldType == OFTBinary )
-    {
-        osCommand += "E'";
-
-        int nLen = 0;
-        GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );
-        char* pszBytea = OGRPGDumpLayer::GByteArrayToBYTEA( pabyData, nLen);
-
-        osCommand += pszBytea;
-
-        CPLFree(pszBytea);
-        osCommand += "'";
-
-        return;
-    }
-
-    // Flag indicating NULL or not-a-date date value
-    // e.g. 0000-00-00 - there is no year 0
-    OGRBoolean bIsDateNull = FALSE;
-
-    const char *pszStrValue = poFeature->GetFieldAsString(i);
-
-    // Check if date is NULL: 0000-00-00
-    if( nOGRFieldType == OFTDate )
-    {
-        if( STARTS_WITH_CI(pszStrValue, "0000") )
-        {
-            pszStrValue = "NULL";
-            bIsDateNull = TRUE;
-        }
-    }
-    else if ( nOGRFieldType == OFTReal )
-    {
-        //Check for special values. They need to be quoted.
-        double dfVal = poFeature->GetFieldAsDouble(i);
-        if( CPLIsNan(dfVal) )
-            pszStrValue = "'NaN'";
-        else if( CPLIsInf(dfVal) )
-            pszStrValue = (dfVal > 0) ? "'Infinity'" : "'-Infinity'";
-    }
-    else if ( (nOGRFieldType == OFTInteger ||
-               nOGRFieldType == OFTInteger64) && eSubType == OFSTBoolean )
-        pszStrValue = poFeature->GetFieldAsInteger(i) ? "'t'" : "'f'";
-
-    if( nOGRFieldType != OFTInteger && nOGRFieldType != OFTInteger64 && 
-        nOGRFieldType != OFTReal && nOGRFieldType != OFTStringList 
-        && !bIsDateNull )
-    {
-        osCommand += pfnEscapeString( userdata, pszStrValue,
-                                      poFeatureDefn->GetFieldDefn(i)->GetWidth(),
-                                      poFeatureDefn->GetName(),
-                                      poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
-    }
-    else
-    {
-        osCommand += pszStrValue;
-    }
-}
-
-
-/************************************************************************/
-/*                        GByteArrayToBYTEA()                           */
-/************************************************************************/
-
-char* OGRPGDumpLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
-{
-    char* pszTextBuf;
-
-    const size_t nTextBufLen = nLen * 5 + 1;
-    pszTextBuf = (char *) CPLMalloc(nTextBufLen);
-
-    int  iSrc, iDst=0;
-
-    for( iSrc = 0; iSrc < nLen; iSrc++ )
-    {
-        if( pabyData[iSrc] < 40 || pabyData[iSrc] > 126
-            || pabyData[iSrc] == '\\' )
-        {
-            snprintf( pszTextBuf+iDst, nTextBufLen - iDst, "\\\\%03o", pabyData[iSrc] );
-            iDst += 5;
-        }
-        else
-            pszTextBuf[iDst++] = pabyData[iSrc];
-    }
-    pszTextBuf[iDst] = '\0';
-
-    return pszTextBuf;
-}
-
-/************************************************************************/
-/*                       OGRPGCommonLayerGetType()                      */
-/************************************************************************/
-
-CPLString OGRPGCommonLayerGetType(OGRFieldDefn& oField,
-                                  int bPreservePrecision,
-                                  int bApproxOK)
-{
-    char                szFieldType[256];
-
-/* -------------------------------------------------------------------- */
-/*      Work out the PostgreSQL type.                                   */
-/* -------------------------------------------------------------------- */
-    if( oField.GetType() == OFTInteger )
-    {
-        if( oField.GetSubType() == OFSTBoolean )
-            strcpy( szFieldType, "BOOLEAN" );
-        else if( oField.GetSubType() == OFSTInt16 )
-            strcpy( szFieldType, "SMALLINT" );
-        else if( oField.GetWidth() > 0 && bPreservePrecision )
-            snprintf( szFieldType, sizeof(szFieldType), "NUMERIC(%d,0)", oField.GetWidth() );
-        else
-            strcpy( szFieldType, "INTEGER" );
-    }
-    else if( oField.GetType() == OFTInteger64 )
-    {
-        if( oField.GetWidth() > 0 && bPreservePrecision )
-            snprintf( szFieldType, sizeof(szFieldType), "NUMERIC(%d,0)", oField.GetWidth() );
-        else
-            strcpy( szFieldType, "INT8" );
-    }
-    else if( oField.GetType() == OFTReal )
-    {
-        if( oField.GetSubType() == OFSTFloat32 )
-            strcpy( szFieldType, "REAL" );
-        else if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
-            && bPreservePrecision )
-            snprintf( szFieldType, sizeof(szFieldType), "NUMERIC(%d,%d)",
-                     oField.GetWidth(), oField.GetPrecision() );
-        else
-            strcpy( szFieldType, "FLOAT8" );
-    }
-    else if( oField.GetType() == OFTString )
-    {
-        if (oField.GetWidth() > 0 &&  bPreservePrecision )
-            snprintf( szFieldType, sizeof(szFieldType), "VARCHAR(%d)",  oField.GetWidth() );
-        else
-            strcpy( szFieldType, "VARCHAR");
-    }
-    else if( oField.GetType() == OFTIntegerList )
-    {
-        if( oField.GetSubType() == OFSTBoolean )
-            strcpy( szFieldType, "BOOLEAN[]" );
-        else if( oField.GetSubType() == OFSTInt16 )
-            strcpy( szFieldType, "INT2[]" );
-        else
-            strcpy( szFieldType, "INTEGER[]" );
-    }
-    else if( oField.GetType() == OFTInteger64List )
-    {
-        strcpy( szFieldType, "INT8[]" );
-    }
-    else if( oField.GetType() == OFTRealList )
-    {
-        if( oField.GetSubType() == OFSTFloat32 )
-            strcpy( szFieldType, "REAL[]" );
-        else
-            strcpy( szFieldType, "FLOAT8[]" );
-    }
-    else if( oField.GetType() == OFTStringList )
-    {
-        strcpy( szFieldType, "varchar[]" );
-    }
-    else if( oField.GetType() == OFTDate )
-    {
-        strcpy( szFieldType, "date" );
-    }
-    else if( oField.GetType() == OFTTime )
-    {
-        strcpy( szFieldType, "time" );
-    }
-    else if( oField.GetType() == OFTDateTime )
-    {
-        strcpy( szFieldType, "timestamp with time zone" );
-    }
-    else if( oField.GetType() == OFTBinary )
-    {
-        strcpy( szFieldType, "bytea" );
-    }
-    else if( bApproxOK )
-    {
-        CPLError( CE_Warning, CPLE_NotSupported,
-                  "Can't create field %s with type %s on PostgreSQL layers.  Creating as VARCHAR.",
-                  oField.GetNameRef(),
-                  OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
-        strcpy( szFieldType, "VARCHAR" );
-    }
-    else
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Can't create field %s with type %s on PostgreSQL layers.",
-                  oField.GetNameRef(),
-                  OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
-        strcpy( szFieldType, "");
-    }
-
-    return szFieldType;
-}
-
-/************************************************************************/
-/*                         OGRPGCommonLayerSetType()                    */
-/************************************************************************/
-
-int OGRPGCommonLayerSetType(OGRFieldDefn& oField,
-                            const char* pszType,
-                            const char* pszFormatType,
-                            int nWidth)
-{
-    if( EQUAL(pszType,"text") )
-    {
-        oField.SetType( OFTString );
-    }
-    else if( EQUAL(pszType,"_bpchar") ||
-            EQUAL(pszType,"_varchar") ||
-            EQUAL(pszType,"_text"))
-    {
-        oField.SetType( OFTStringList );
-    }
-    else if( EQUAL(pszType,"bpchar") || EQUAL(pszType,"varchar") )
-    {
-        if( nWidth == -1 )
-        {
-            if( STARTS_WITH_CI(pszFormatType, "character(") )
-                nWidth = atoi(pszFormatType+10);
-            else if( STARTS_WITH_CI(pszFormatType, "character varying(") )
-                nWidth = atoi(pszFormatType+18);
-            else
-                nWidth = 0;
-        }
-        oField.SetType( OFTString );
-        oField.SetWidth( nWidth );
-    }
-    else if( EQUAL(pszType,"bool") )
-    {
-        oField.SetType( OFTInteger );
-        oField.SetSubType( OFSTBoolean );
-        oField.SetWidth( 1 );
-    }
-    else if( EQUAL(pszType,"_numeric") )
-    {
-        if( EQUAL(pszFormatType, "numeric[]") )
-            oField.SetType( OFTRealList );
-        else
-        {
-            const char *pszPrecision = strstr(pszFormatType,",");
-            int    nPrecision = 0;
-
-            nWidth = atoi(pszFormatType + 8);
-            if( pszPrecision != NULL )
-                nPrecision = atoi(pszPrecision+1);
-
-            if( nPrecision == 0 )
-            {
-                if( nWidth >= 10 )
-                    oField.SetType( OFTInteger64List );
-                else
-                    oField.SetType( OFTIntegerList );
-            }
-            else
-                oField.SetType( OFTRealList );
-
-            oField.SetWidth( nWidth );
-            oField.SetPrecision( nPrecision );
-        }
-    }
-    else if( EQUAL(pszType,"numeric") )
-    {
-        if( EQUAL(pszFormatType, "numeric") )
-            oField.SetType( OFTReal );
-        else
-        {
-            const char *pszPrecision = strstr(pszFormatType,",");
-            int    nPrecision = 0;
-
-            nWidth = atoi(pszFormatType + 8);
-            if( pszPrecision != NULL )
-                nPrecision = atoi(pszPrecision+1);
-
-            if( nPrecision == 0 )
-            {
-                if( nWidth >= 10 )
-                    oField.SetType( OFTInteger64 );
-                else
-                    oField.SetType( OFTInteger );
-            }
-            else
-                oField.SetType( OFTReal );
-
-            oField.SetWidth( nWidth );
-            oField.SetPrecision( nPrecision );
-        }
-    }
-    else if( EQUAL(pszFormatType,"integer[]") )
-    {
-        oField.SetType( OFTIntegerList );
-    }
-    else if( EQUAL(pszFormatType,"smallint[]") )
-    {
-        oField.SetType( OFTIntegerList );
-        oField.SetSubType( OFSTInt16 );
-    }
-    else if( EQUAL(pszFormatType,"boolean[]") )
-    {
-        oField.SetType( OFTIntegerList );
-        oField.SetSubType( OFSTBoolean );
-    }
-    else if( EQUAL(pszFormatType, "float[]") ||
-            EQUAL(pszFormatType, "real[]") )
-    {
-        oField.SetType( OFTRealList );
-        oField.SetSubType( OFSTFloat32 );
-    }
-    else if( EQUAL(pszFormatType, "double precision[]") )
-    {
-        oField.SetType( OFTRealList );
-    }
-    else if( EQUAL(pszType,"int2") )
-    {
-        oField.SetType( OFTInteger );
-        oField.SetSubType( OFSTInt16 );
-        oField.SetWidth( 5 );
-    }
-    else if( EQUAL(pszType,"int8") )
-    {
-        oField.SetType( OFTInteger64 );
-    }
-    else if( EQUAL(pszFormatType,"bigint[]") )
-    {
-        oField.SetType( OFTInteger64List );
-    }
-    else if( STARTS_WITH_CI(pszType, "int") )
-    {
-        oField.SetType( OFTInteger );
-    }
-    else if( EQUAL(pszType,"float4")  )
-    {
-        oField.SetType( OFTReal );
-        oField.SetSubType( OFSTFloat32 );
-    }
-    else if( STARTS_WITH_CI(pszType, "float") ||
-            STARTS_WITH_CI(pszType, "double") ||
-            EQUAL(pszType,"real") )
-    {
-        oField.SetType( OFTReal );
-    }
-    else if( STARTS_WITH_CI(pszType, "timestamp") )
-    {
-        oField.SetType( OFTDateTime );
-    }
-    else if( STARTS_WITH_CI(pszType, "date") )
-    {
-        oField.SetType( OFTDate );
-    }
-    else if( STARTS_WITH_CI(pszType, "time") )
-    {
-        oField.SetType( OFTTime );
-    }
-    else if( EQUAL(pszType,"bytea") )
-    {
-        oField.SetType( OFTBinary );
-    }
-    else
-    {
-        CPLDebug( "PGCommon", "Field %s is of unknown format type %s (type=%s).", 
-                oField.GetNameRef(), pszFormatType, pszType );
-        return FALSE;
-    }
-    return TRUE;
-}
-
-/************************************************************************/
-/*                  OGRPGCommonLayerNormalizeDefault()                  */
-/************************************************************************/
-
-void OGRPGCommonLayerNormalizeDefault(OGRFieldDefn* poFieldDefn,
-                                      const char* pszDefault)
-{
-    if(pszDefault==NULL)
-        return;
-    CPLString osDefault(pszDefault);
-    size_t nPos = osDefault.find("::character varying");
-    if( nPos != std::string::npos )
-        osDefault.resize(nPos);
-    else if( strcmp(osDefault, "now()") == 0 )
-        osDefault = "CURRENT_TIMESTAMP";
-    else if( strcmp(osDefault, "('now'::text)::date") == 0 )
-        osDefault = "CURRENT_DATE";
-    else if( strcmp(osDefault, "('now'::text)::time with time zone") == 0 )
-        osDefault = "CURRENT_TIME";
-    else
-    {
-        nPos = osDefault.find("::timestamp with time zone");
-        if( poFieldDefn->GetType() == OFTDateTime && nPos != std::string::npos )
-        {
-            osDefault.resize(nPos);
-            nPos = osDefault.find("'+");
-            if( nPos != std::string::npos )
-            {
-                osDefault.resize(nPos);
-                osDefault += "'";
-            }
-            int nYear, nMonth, nDay, nHour, nMinute;
-            float fSecond;
-            if( sscanf(osDefault, "'%d-%d-%d %d:%d:%f'", &nYear, &nMonth, &nDay,
-                                &nHour, &nMinute, &fSecond) == 6 ||
-                sscanf(osDefault, "'%d-%d-%d %d:%d:%f+00'", &nYear, &nMonth, &nDay,
-                                &nHour, &nMinute, &fSecond) == 6)
-            {
-                if( osDefault.find('.') == std::string::npos )
-                    osDefault = CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%02d'",
-                                            nYear, nMonth, nDay, nHour, nMinute, (int)(fSecond+0.5));
-                else
-                    osDefault = CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%06.3f'",
-                                                    nYear, nMonth, nDay, nHour, nMinute, fSecond);
-            }
-        }
-    }
-    poFieldDefn->SetDefault(osDefault);
-}
-
-/************************************************************************/
-/*                     OGRPGCommonLayerGetPGDefault()                   */
-/************************************************************************/
-
-CPLString OGRPGCommonLayerGetPGDefault(OGRFieldDefn* poFieldDefn)
-{
-    CPLString osRet = poFieldDefn->GetDefault();
-    int nYear, nMonth, nDay, nHour, nMinute;
-    float fSecond;
-    if( sscanf(osRet, "'%d/%d/%d %d:%d:%f'",
-                &nYear, &nMonth, &nDay,
-                &nHour, &nMinute, &fSecond) == 6 )
-    {
-        osRet.resize(osRet.size()-1);
-        osRet += "+00'::timestamp with time zone";
-    }
-    return osRet;
-}
-
-/************************************************************************/
-/*                           GetNextFeature()                           */
-/************************************************************************/
-
-OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
-                                     int bApproxOK )
-{
-    CPLString           osCommand;
-    CPLString           osFieldType;
-    OGRFieldDefn        oField( poFieldIn );
-    
-    // Can be set to NO to test ogr2ogr default behaviour
-    int bAllowCreationOfFieldWithFIDName =
-        CPLTestBool(CPLGetConfigOption("PGDUMP_DEBUG_ALLOW_CREATION_FIELD_WITH_FID_NAME", "YES"));
-
-    if( bAllowCreationOfFieldWithFIDName && pszFIDColumn != NULL &&
-        EQUAL( oField.GetNameRef(), pszFIDColumn ) &&
-        oField.GetType() != OFTInteger &&
-        oField.GetType() != OFTInteger64 )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Wrong field type for %s",
-                 oField.GetNameRef());
-        return OGRERR_FAILURE;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Do we want to "launder" the column names into Postgres          */
-/*      friendly format?                                                */
-/* -------------------------------------------------------------------- */
-    if( bLaunderColumnNames )
-    {
-        char    *pszSafeName = OGRPGCommonLaunderName( oField.GetNameRef(), "PGDump" );
-
-        oField.SetName( pszSafeName );
-        CPLFree( pszSafeName );
-
-        if( EQUAL(oField.GetNameRef(),"oid") )
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Renaming field 'oid' to 'oid_' to avoid conflict with internal oid field." );
-            oField.SetName( "oid_" );
-        }
-    }
-
-    const char* pszOverrideType = CSLFetchNameValue(papszOverrideColumnTypes, oField.GetNameRef());
-    if( pszOverrideType != NULL )
-        osFieldType = pszOverrideType;
-    else
-    {
-        osFieldType = OGRPGCommonLayerGetType(oField, bPreservePrecision, bApproxOK);
-        if (osFieldType.size() == 0)
-            return OGRERR_FAILURE;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create the new field.                                           */
-/* -------------------------------------------------------------------- */
-    osCommand.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
-                      pszSqlTableName, OGRPGDumpEscapeColumnName(oField.GetNameRef()).c_str(),
-                      osFieldType.c_str() );
-    if( !oField.IsNullable() )
-        osCommand += " NOT NULL";
-    if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
-    {
-        osCommand += " DEFAULT ";
-        osCommand += OGRPGCommonLayerGetPGDefault(&oField);
-    }
-
-    poFeatureDefn->AddFieldDefn( &oField );
-
-    if( bAllowCreationOfFieldWithFIDName && pszFIDColumn != NULL &&
-        EQUAL( oField.GetNameRef(), pszFIDColumn ) )
-    {
-        iFIDAsRegularColumnIndex = poFeatureDefn->GetFieldCount() - 1;
-    }
-    else
-    {
-        if( bCreateTable )
-            poDS->Log(osCommand);
-    }
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                           CreateGeomField()                          */
-/************************************************************************/
-
-OGRErr OGRPGDumpLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
-                                        CPL_UNUSED int bApproxOK )
-{
-    OGRwkbGeometryType eType = poGeomFieldIn->GetType();
-    if( eType == wkbNone )
-    {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "Cannot create geometry field of type wkbNone");
-        return OGRERR_FAILURE;
-    }
-
-    // Check if GEOMETRY_NAME layer creation option was set, but no initial
-    // column was created in ICreateLayer()
-    CPLString osGeomFieldName = 
-        ( m_osFirstGeometryFieldName.size() ) ? m_osFirstGeometryFieldName :
-                                                CPLString(poGeomFieldIn->GetNameRef());
-    m_osFirstGeometryFieldName = ""; // reset for potential next geom columns
-
-    OGRGeomFieldDefn oTmpGeomFieldDefn( poGeomFieldIn );
-    oTmpGeomFieldDefn.SetName(osGeomFieldName);
-
-    CPLString               osCommand;
-    OGRPGDumpGeomFieldDefn *poGeomField =
-        new OGRPGDumpGeomFieldDefn( &oTmpGeomFieldDefn );
-
-/* -------------------------------------------------------------------- */
-/*      Do we want to "launder" the column names into Postgres          */
-/*      friendly format?                                                */
-/* -------------------------------------------------------------------- */
-    if( bLaunderColumnNames )
-    {
-        char    *pszSafeName = OGRPGCommonLaunderName( poGeomField->GetNameRef(), "PGDump" );
-
-        poGeomField->SetName( pszSafeName );
-        CPLFree( pszSafeName );
-    }
-    
-    OGRSpatialReference* poSRS = poGeomField->GetSpatialRef();
-    int nSRSId = nUnknownSRSId;
-    if( nForcedSRSId != -2 )
-        nSRSId = nForcedSRSId;
-    else if( poSRS != NULL )
-    {
-        const char* pszAuthorityName = poSRS->GetAuthorityName(NULL);
-        if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
-        {
-            /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */
-            nSRSId = atoi( poSRS->GetAuthorityCode(NULL) );
-        }
-        else
-        {
-            const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS");
-            if (pszGeogCSName != NULL && EQUAL(pszGeogCSName, "GCS_WGS_1984"))
-                nSRSId = 4326;
-        }
-    }
-
-    poGeomField->nSRSId = nSRSId;
-
-    int GeometryTypeFlags = 0;
-    if( OGR_GT_HasZ((OGRwkbGeometryType)eType) )
-        GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
-    if( OGR_GT_HasM((OGRwkbGeometryType)eType) )
-        GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
-    if( nForcedGeometryTypeFlags >= 0 )
-    {
-        GeometryTypeFlags = nForcedGeometryTypeFlags;
-        eType = OGR_GT_SetModifier(eType, 
-                                   GeometryTypeFlags & OGRGeometry::OGR_G_3D, 
-                                   GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
-    }
-    poGeomField->SetType(eType);
-    poGeomField->GeometryTypeFlags = GeometryTypeFlags;
-
-/* -------------------------------------------------------------------- */
-/*      Create the new field.                                           */
-/* -------------------------------------------------------------------- */
-    if (bCreateTable)
-    {
-        const char *suffix = "";
-        int dim = 2;
-        if( (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D) && (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
-            dim = 4;
-        else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED )
-        {
-            if( wkbFlatten(poGeomField->GetType()) != wkbUnknown )
-                suffix = "M";
-            dim = 3;
-        }
-        else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D )
-            dim = 3;
-
-        const char *pszGeometryType = OGRToOGCGeomType(poGeomField->GetType());
-        osCommand.Printf(
-                "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s%s',%d)",
-                OGRPGDumpEscapeString(pszSchemaName).c_str(),
-                OGRPGDumpEscapeString(poFeatureDefn->GetName()).c_str(),
-                OGRPGDumpEscapeString(poGeomField->GetNameRef()).c_str(),
-                nSRSId, pszGeometryType, suffix, dim );
-        
-        poDS->Log(osCommand);
-
-        if( !poGeomField->IsNullable() )
-        {
-            osCommand.Printf( "ALTER TABLE %s ALTER COLUMN %s SET NOT NULL",
-                              OGRPGDumpEscapeColumnName(poFeatureDefn->GetName()).c_str(),
-                              OGRPGDumpEscapeColumnName(poGeomField->GetNameRef()).c_str() );
-
-            poDS->Log(osCommand);
-        }
-
-        if( bCreateSpatialIndexFlag )
-        {
-            osCommand.Printf("CREATE INDEX %s ON %s USING GIST (%s)",
-                            OGRPGDumpEscapeColumnName(
-                                CPLSPrintf("%s_%s_geom_idx", GetName(), poGeomField->GetNameRef())).c_str(),
-                            pszSqlTableName,
-                            OGRPGDumpEscapeColumnName(poGeomField->GetNameRef()).c_str());
-
-            poDS->Log(osCommand);
-        }
-    }
-
-    poFeatureDefn->AddGeomFieldDefn( poGeomField, FALSE );
-    
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
-/*                        SetOverrideColumnTypes()                      */
-/************************************************************************/
-
-void OGRPGDumpLayer::SetOverrideColumnTypes( const char* pszOverrideColumnTypes )
-{
-    if( pszOverrideColumnTypes == NULL )
-        return;
-
-    const char* pszIter = pszOverrideColumnTypes;
-    CPLString osCur;
-    while(*pszIter != '\0')
-    {
-        if( *pszIter == '(' )
-        {
-            /* Ignore commas inside ( ) pair */
-            while(*pszIter != '\0')
-            {
-                if( *pszIter == ')' )
-                {
-                    osCur += *pszIter;
-                    pszIter ++;
-                    break;
-                }
-                osCur += *pszIter;
-                pszIter ++;
-            }
-            if( *pszIter == '\0')
-                break;
-        }
-
-        if( *pszIter == ',' )
-        {
-            papszOverrideColumnTypes = CSLAddString(papszOverrideColumnTypes, osCur);
-            osCur = "";
-        }
-        else
-            osCur += *pszIter;
-        pszIter ++;
-    }
-    if( osCur.size() )
-        papszOverrideColumnTypes = CSLAddString(papszOverrideColumnTypes, osCur);
-}
-
-/************************************************************************/
-/*                              SetMetadata()                           */
-/************************************************************************/
-
-CPLErr OGRPGDumpLayer::SetMetadata(char** papszMD, const char* pszDomain)
-{
-    OGRLayer::SetMetadata(papszMD, pszDomain);
-    if( osForcedDescription.size() != 0 &&
-        (pszDomain == NULL || EQUAL(pszDomain, "")) )
-    {
-        OGRLayer::SetMetadataItem("DESCRIPTION", osForcedDescription);
-    }
-
-    if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
-        osForcedDescription.size() == 0 )
-    {
-        const char* l_pszDescription = OGRLayer::GetMetadataItem("DESCRIPTION");
-        CPLString osCommand;
-
-        osCommand.Printf( "COMMENT ON TABLE %s IS %s",
-                           pszSqlTableName,
-                           l_pszDescription && l_pszDescription[0] != '\0' ?
-                              OGRPGDumpEscapeString(l_pszDescription).c_str() : "NULL" );
-        poDS->Log( osCommand );
-    }
-
-    return CE_None;
-}
-
-/************************************************************************/
-/*                            SetMetadataItem()                         */
-/************************************************************************/
-
-CPLErr OGRPGDumpLayer::SetMetadataItem(const char* pszName, const char* pszValue,
-                                       const char* pszDomain)
-{
-    if( (pszDomain == NULL || EQUAL(pszDomain, "")) && pszName != NULL &&
-        EQUAL(pszName, "DESCRIPTION") && osForcedDescription.size() )
-    {
-        return CE_None;
-    }
-    OGRLayer::SetMetadataItem(pszName, pszValue, pszDomain);
-    if( (pszDomain == NULL || EQUAL(pszDomain, "")) && pszName != NULL &&
-        EQUAL(pszName, "DESCRIPTION") )
-    {
-        SetMetadata( GetMetadata() );
-    }
-    return CE_None;
-}
-
-/************************************************************************/
-/*                      SetForcedDescription()                          */
-/************************************************************************/
-
-void OGRPGDumpLayer::SetForcedDescription( const char* pszDescriptionIn )
-{
-    osForcedDescription = pszDescriptionIn;
-    OGRLayer::SetMetadataItem("DESCRIPTION", osForcedDescription);
-
-    if( pszDescriptionIn[0] != '\0' )
-    {
-        CPLString osCommand;
-        osCommand.Printf( "COMMENT ON TABLE %s IS %s",
-                            pszSqlTableName,
-                            OGRPGDumpEscapeString(pszDescriptionIn).c_str() );
-        poDS->Log( osCommand );
-    }
-}
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements OGRPGDumpLayer class
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_pgdump.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_p.h"
+
+CPL_CVSID("$Id: ogrpgdumplayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
+static const int USE_COPY_UNSET = -1;
+
+static CPLString OGRPGDumpEscapeStringList(
+    char** papszItems, bool bForInsertOrUpdate,
+    OGRPGCommonEscapeStringCbk pfnEscapeString,
+    void* userdata );
+
+static CPLString OGRPGDumpEscapeStringWithUserData(
+    CPL_UNUSED void* user_data,
+    const char* pszStrValue, int nMaxLength,
+    CPL_UNUSED const char* pszLayerName,
+    const char* pszFieldName )
+{
+    return OGRPGDumpEscapeString(pszStrValue, nMaxLength, pszFieldName);
+}
+
+/************************************************************************/
+/*                        OGRPGDumpLayer()                              */
+/************************************************************************/
+
+OGRPGDumpLayer::OGRPGDumpLayer( OGRPGDumpDataSource* poDSIn,
+                                const char* pszSchemaNameIn,
+                                const char* pszTableName,
+                                const char *pszFIDColumnIn,
+                                int bWriteAsHexIn,
+                                int bCreateTableIn ) :
+    pszSchemaName(CPLStrdup(pszSchemaNameIn)),
+    pszSqlTableName(CPLStrdup(
+        CPLString().Printf("%s.%s",
+                           OGRPGDumpEscapeColumnName(pszSchemaName).c_str(),
+                           OGRPGDumpEscapeColumnName(pszTableName).c_str()))),
+    pszFIDColumn(CPLStrdup(pszFIDColumnIn)),
+    poFeatureDefn(new OGRFeatureDefn(pszTableName)),
+    poDS(poDSIn),
+    bLaunderColumnNames(true),
+    bPreservePrecision(true),
+    bUseCopy(USE_COPY_UNSET),
+    bWriteAsHex(CPL_TO_BOOL(bWriteAsHexIn)),
+    bCopyActive(false),
+    bFIDColumnInCopyFields(false),
+    bCreateTable(bCreateTableIn),
+    nUnknownSRSId(-1),
+    nForcedSRSId(-2),
+    nForcedGeometryTypeFlags(-1),
+    bCreateSpatialIndexFlag(true),
+    nPostGISMajor(1),
+    nPostGISMinor(2),
+    iNextShapeId(0),
+    iFIDAsRegularColumnIndex(-1),
+    bAutoFIDOnCreateViaCopy(true),
+    bCopyStatementWithFID(false),
+    papszOverrideColumnTypes(NULL)
+{
+    SetDescription( poFeatureDefn->GetName() );
+    poFeatureDefn->SetGeomType(wkbNone);
+    poFeatureDefn->Reference();
+}
+
+/************************************************************************/
+/*                          ~OGRPGDumpLayer()                           */
+/************************************************************************/
+
+OGRPGDumpLayer::~OGRPGDumpLayer()
+{
+    EndCopy();
+
+    poFeatureDefn->Release();
+    CPLFree(pszSchemaName);
+    CPLFree(pszSqlTableName);
+    CPLFree(pszFIDColumn);
+    CSLDestroy(papszOverrideColumnTypes);
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRPGDumpLayer::GetNextFeature()
+{
+    CPLError(CE_Failure, CPLE_NotSupported, "PGDump driver is write only");
+    return NULL;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+int OGRPGDumpLayer::TestCapability( const char * pszCap )
+{
+    if( EQUAL(pszCap,OLCSequentialWrite) ||
+        EQUAL(pszCap,OLCCreateField) ||
+        EQUAL(pszCap,OLCCreateGeomField) ||
+        EQUAL(pszCap,OLCCurveGeometries) ||
+        EQUAL(pszCap,OLCMeasuredGeometries) )
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRErr OGRPGDumpLayer::ICreateFeature( OGRFeature *poFeature )
+{
+    if( NULL == poFeature )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "NULL pointer to OGRFeature passed to CreateFeature()." );
+        return OGRERR_FAILURE;
+    }
+
+    /* In case the FID column has also been created as a regular field */
+    if( iFIDAsRegularColumnIndex >= 0 )
+    {
+        if( poFeature->GetFID() == OGRNullFID )
+        {
+            if( poFeature->IsFieldSetAndNotNull( iFIDAsRegularColumnIndex ) )
+            {
+                poFeature->SetFID(
+                    poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex));
+            }
+        }
+        else
+        {
+            if( !poFeature->IsFieldSetAndNotNull( iFIDAsRegularColumnIndex ) ||
+                poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex) != poFeature->GetFID() )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Inconsistent values of FID and field of same name");
+                return OGRERR_FAILURE;
+            }
+        }
+    }
+
+    if( !poFeature->Validate((OGR_F_VAL_ALL & ~OGR_F_VAL_WIDTH) |
+                             OGR_F_VAL_ALLOW_DIFFERENT_GEOM_DIM, TRUE ) )
+        return OGRERR_FAILURE;
+
+    // We avoid testing the config option too often.
+    if( bUseCopy == USE_COPY_UNSET )
+        bUseCopy = CPLTestBool( CPLGetConfigOption( "PG_USE_COPY", "NO") );
+
+    OGRErr eErr;
+    if( !bUseCopy )
+    {
+        eErr = CreateFeatureViaInsert( poFeature );
+    }
+    else
+    {
+        // If there's a unset field with a default value, then we must use a
+        // specific INSERT statement to avoid unset fields to be bound to NULL.
+        bool bHasDefaultValue = false;
+        const int nFieldCount = poFeatureDefn->GetFieldCount();
+        for( int iField = 0; iField < nFieldCount; iField++ )
+        {
+            if( !poFeature->IsFieldSetAndNotNull( iField ) &&
+                poFeature->GetFieldDefnRef(iField)->GetDefault() != NULL )
+            {
+                bHasDefaultValue = true;
+                break;
+            }
+        }
+        if( bHasDefaultValue )
+        {
+            EndCopy();
+            eErr = CreateFeatureViaInsert( poFeature );
+        }
+        else
+        {
+            const bool bFIDSet = poFeature->GetFID() != OGRNullFID;
+            if( bCopyActive && bFIDSet != bCopyStatementWithFID )
+            {
+                EndCopy();
+                eErr = CreateFeatureViaInsert( poFeature );
+            }
+            else
+            {
+                if ( !bCopyActive )
+                {
+                    // This is a heuristics. If the first feature to be copied
+                    // has a FID set (and that a FID column has been
+                    // identified), then we will try to copy FID values from
+                    // features. Otherwise, we will not do and assume that the
+                    // FID column is an autoincremented column.
+                    StartCopy(bFIDSet);
+                    bCopyStatementWithFID = bFIDSet;
+                }
+
+                eErr = CreateFeatureViaCopy( poFeature );
+                if( bFIDSet )
+                    bAutoFIDOnCreateViaCopy = false;
+                if( eErr == OGRERR_NONE && bAutoFIDOnCreateViaCopy )
+                {
+                    poFeature->SetFID( ++iNextShapeId );
+                }
+            }
+        }
+    }
+
+    if( eErr == OGRERR_NONE && iFIDAsRegularColumnIndex >= 0 )
+    {
+        poFeature->SetField(iFIDAsRegularColumnIndex, poFeature->GetFID());
+    }
+    return eErr;
+}
+
+/************************************************************************/
+/*                       CreateFeatureViaInsert()                       */
+/************************************************************************/
+
+OGRErr OGRPGDumpLayer::CreateFeatureViaInsert( OGRFeature *poFeature )
+
+{
+    OGRErr eErr = OGRERR_FAILURE;
+
+    if( NULL == poFeature )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "NULL pointer to OGRFeature passed to CreateFeatureViaInsert()." );
+        return eErr;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Form the INSERT command.                                        */
+/* -------------------------------------------------------------------- */
+    CPLString osCommand;
+    osCommand.Printf( "INSERT INTO %s (", pszSqlTableName );
+
+    bool bNeedComma = false;
+
+    for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+    {
+        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeom != NULL )
+        {
+            if( bNeedComma )
+                osCommand += ", ";
+
+            OGRGeomFieldDefn* poGFldDefn = poFeature->GetGeomFieldDefnRef(i);
+            osCommand = osCommand + OGRPGDumpEscapeColumnName(poGFldDefn->GetNameRef()) + " ";
+            bNeedComma = true;
+        }
+    }
+
+    if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
+    {
+        if( bNeedComma )
+            osCommand += ", ";
+
+        osCommand = osCommand + OGRPGDumpEscapeColumnName(pszFIDColumn) + " ";
+        bNeedComma = true;
+    }
+
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    {
+        if( i == iFIDAsRegularColumnIndex )
+            continue;
+        if( !poFeature->IsFieldSet( i ) )
+            continue;
+
+        if( !bNeedComma )
+            bNeedComma = true;
+        else
+            osCommand += ", ";
+
+        osCommand = osCommand
+            + OGRPGDumpEscapeColumnName(poFeatureDefn->GetFieldDefn(i)->GetNameRef());
+    }
+
+    const bool bEmptyInsert = !bNeedComma;
+
+    osCommand += ") VALUES (";
+
+    /* Set the geometry */
+    bNeedComma = false;
+    for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+    {
+        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
+        if( poGeom != NULL )
+        {
+            char *pszWKT = NULL;
+
+            OGRPGDumpGeomFieldDefn* poGFldDefn =
+                (OGRPGDumpGeomFieldDefn*) poFeature->GetGeomFieldDefnRef(i);
+
+            poGeom->closeRings();
+            poGeom->set3D(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D);
+            poGeom->setMeasured(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
+
+            if( bNeedComma )
+                osCommand += ", ";
+
+            if( bWriteAsHex )
+            {
+                char* pszHex = OGRGeometryToHexEWKB( poGeom, poGFldDefn->nSRSId,
+                                                     nPostGISMajor,
+                                                     nPostGISMinor );
+                osCommand += "'";
+                if (pszHex)
+                    osCommand += pszHex;
+                osCommand += "'";
+                CPLFree(pszHex);
+            }
+            else
+            {
+                poGeom->exportToWkt( &pszWKT );
+
+                if( pszWKT != NULL )
+                {
+                    osCommand +=
+                        CPLString().Printf(
+                            "GeomFromEWKT('SRID=%d;%s'::TEXT) ", poGFldDefn->nSRSId, pszWKT );
+                    CPLFree( pszWKT );
+                }
+                else
+                    osCommand += "''";
+            }
+
+            bNeedComma = true;
+        }
+    }
+
+    /* Set the FID */
+    if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
+    {
+        if( bNeedComma )
+            osCommand += ", ";
+        osCommand += CPLString().Printf( CPL_FRMT_GIB, poFeature->GetFID() );
+        bNeedComma = true;
+    }
+
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    {
+        if( i == iFIDAsRegularColumnIndex )
+            continue;
+        if( !poFeature->IsFieldSet( i ) )
+            continue;
+
+        if( bNeedComma )
+            osCommand += ", ";
+        else
+            bNeedComma = true;
+
+        OGRPGCommonAppendFieldValue(osCommand, poFeature, i,
+                                    OGRPGDumpEscapeStringWithUserData, NULL);
+    }
+
+    osCommand += ")";
+
+    if( bEmptyInsert )
+        osCommand.Printf( "INSERT INTO %s DEFAULT VALUES", pszSqlTableName );
+
+/* -------------------------------------------------------------------- */
+/*      Execute the insert.                                             */
+/* -------------------------------------------------------------------- */
+    poDS->Log(osCommand);
+
+    if( poFeature->GetFID() == OGRNullFID )
+        poFeature->SetFID( ++iNextShapeId );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        CreateFeatureViaCopy()                        */
+/************************************************************************/
+
+OGRErr OGRPGDumpLayer::CreateFeatureViaCopy( OGRFeature *poFeature )
+{
+    CPLString            osCommand;
+
+    /* First process geometry */
+    for( int i = 0; i < poFeature->GetGeomFieldCount(); i++ )
+    {
+        OGRGeometry *poGeometry = poFeature->GetGeomFieldRef(i);
+        char *pszGeom = NULL;
+        if ( NULL != poGeometry /* && (bHasWkb || bHasPostGISGeometry || bHasPostGISGeography) */)
+        {
+            OGRPGDumpGeomFieldDefn* poGFldDefn =
+                (OGRPGDumpGeomFieldDefn*) poFeature->GetGeomFieldDefnRef(i);
+
+            poGeometry->closeRings();
+            poGeometry->set3D(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_3D);
+            poGeometry->setMeasured(poGFldDefn->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
+
+            //CheckGeomTypeCompatibility(poGeometry);
+
+            /*if (bHasWkb)
+                pszGeom = GeometryToBYTEA( poGeometry );
+            else*/
+                pszGeom = OGRGeometryToHexEWKB( poGeometry, poGFldDefn->nSRSId,
+                                                nPostGISMajor,
+                                                nPostGISMinor );
+        }
+
+        if (!osCommand.empty())
+            osCommand += "\t";
+        if ( pszGeom )
+        {
+            osCommand += pszGeom;
+            CPLFree( pszGeom );
+        }
+        else
+        {
+            osCommand += "\\N";
+        }
+    }
+
+    OGRPGCommonAppendCopyFieldsExceptGeom(osCommand,
+                                          poFeature,
+                                          pszFIDColumn,
+                                          bFIDColumnInCopyFields,
+                                          OGRPGDumpEscapeStringWithUserData,
+                                          NULL);
+
+    /* Add end of line marker */
+    // osCommand += "\n";
+
+    /* ------------------------------------------------------------ */
+    /*      Execute the copy.                                       */
+    /* ------------------------------------------------------------ */
+
+    OGRErr result = OGRERR_NONE;
+
+    poDS->Log(osCommand, false);
+
+    return result;
+}
+
+/************************************************************************/
+/*                OGRPGCommonAppendCopyFieldsExceptGeom()               */
+/************************************************************************/
+
+void OGRPGCommonAppendCopyFieldsExceptGeom(
+    CPLString& osCommand,
+    OGRFeature* poFeature,
+    const char* pszFIDColumn,
+    bool bFIDColumnInCopyFields,
+    OGRPGCommonEscapeStringCbk pfnEscapeString,
+    void* userdata )
+{
+    OGRFeatureDefn* poFeatureDefn = poFeature->GetDefnRef();
+
+    /* Next process the field id column */
+    int nFIDIndex = -1;
+    if( bFIDColumnInCopyFields )
+    {
+        if (!osCommand.empty())
+            osCommand += "\t";
+
+        nFIDIndex = poFeatureDefn->GetFieldIndex( pszFIDColumn );
+
+        /* Set the FID */
+        if( poFeature->GetFID() != OGRNullFID )
+        {
+            osCommand += CPLString().Printf( CPL_FRMT_GIB, poFeature->GetFID());
+        }
+        else
+        {
+            osCommand += "\\N" ;
+        }
+    }
+
+    /* Now process the remaining fields */
+
+    int nFieldCount = poFeatureDefn->GetFieldCount();
+    bool bAddTab = !osCommand.empty();
+
+    for( int i = 0; i < nFieldCount;  i++ )
+    {
+        if (i == nFIDIndex)
+            continue;
+
+        const char *pszStrValue = poFeature->GetFieldAsString(i);
+        char *pszNeedToFree = NULL;
+
+        if( bAddTab )
+            osCommand += "\t";
+        bAddTab = true;
+
+        if( !poFeature->IsFieldSetAndNotNull( i ) )
+        {
+            osCommand += "\\N" ;
+
+            continue;
+        }
+
+        const int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
+
+        // We need special formatting for integer list values.
+        if( nOGRFieldType == OFTIntegerList )
+        {
+            int nCount, nOff = 0;
+            const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);
+
+            const size_t nLen = nCount * 13 + 10;
+            pszNeedToFree = (char *) CPLMalloc(nLen);
+            strcpy( pszNeedToFree, "{" );
+            for( int j = 0; j < nCount; j++ )
+            {
+                if( j != 0 )
+                    strcat( pszNeedToFree+nOff, "," );
+
+                nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+                snprintf( pszNeedToFree+nOff, nLen-nOff, "%d", panItems[j] );
+            }
+            strcat( pszNeedToFree+nOff, "}" );
+            pszStrValue = pszNeedToFree;
+        }
+
+        else if( nOGRFieldType == OFTInteger64List )
+        {
+            int nCount, nOff = 0;
+            const GIntBig *panItems = poFeature->GetFieldAsInteger64List(i,&nCount);
+
+            const size_t nLen = nCount * 26 + 10;
+            pszNeedToFree = (char *) CPLMalloc(nLen);
+            strcpy( pszNeedToFree, "{" );
+            for( int j = 0; j < nCount; j++ )
+            {
+                if( j != 0 )
+                    strcat( pszNeedToFree+nOff, "," );
+
+                nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+                snprintf( pszNeedToFree+nOff, nLen-nOff, CPL_FRMT_GIB, panItems[j] );
+            }
+            strcat( pszNeedToFree+nOff, "}" );
+            pszStrValue = pszNeedToFree;
+        }
+
+        // We need special formatting for real list values.
+        else if( nOGRFieldType == OFTRealList )
+        {
+            int nOff = 0;
+            int nCount = 0;
+            const double *padfItems =
+                poFeature->GetFieldAsDoubleList(i,&nCount);
+
+            const size_t nLen = nCount * 40 + 10;
+            pszNeedToFree = (char *) CPLMalloc(nLen);
+            strcpy( pszNeedToFree, "{" );
+            for( int j = 0; j < nCount; j++ )
+            {
+                if( j != 0 )
+                    strcat( pszNeedToFree+nOff, "," );
+
+                nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+                //Check for special values. They need to be quoted.
+                if( CPLIsNan(padfItems[j]) )
+                    snprintf( pszNeedToFree+nOff, nLen-nOff, "NaN" );
+                else if( CPLIsInf(padfItems[j]) )
+                    snprintf( pszNeedToFree+nOff, nLen-nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
+                else
+                    CPLsnprintf( pszNeedToFree+nOff, nLen-nOff, "%.16g", padfItems[j] );
+            }
+            strcat( pszNeedToFree+nOff, "}" );
+            pszStrValue = pszNeedToFree;
+        }
+
+        // We need special formatting for string list values.
+        else if( nOGRFieldType == OFTStringList )
+        {
+            CPLString osStr;
+            char **papszItems = poFeature->GetFieldAsStringList(i);
+
+            pszStrValue = pszNeedToFree = CPLStrdup(
+                OGRPGDumpEscapeStringList(papszItems, false,
+                                          pfnEscapeString, userdata));
+        }
+
+        // Binary formatting
+        else if( nOGRFieldType == OFTBinary )
+        {
+            int nLen = 0;
+            GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );
+            char* pszBytea = OGRPGDumpLayer::GByteArrayToBYTEA( pabyData, nLen);
+
+            pszStrValue = pszNeedToFree = pszBytea;
+        }
+
+        else if( nOGRFieldType == OFTReal )
+        {
+            //Check for special values. They need to be quoted.
+            double dfVal = poFeature->GetFieldAsDouble(i);
+            if( CPLIsNan(dfVal) )
+                pszStrValue = "NaN";
+            else if( CPLIsInf(dfVal) )
+                pszStrValue = (dfVal > 0) ? "Infinity" : "-Infinity";
+        }
+
+        if( nOGRFieldType != OFTIntegerList &&
+            nOGRFieldType != OFTInteger64List &&
+            nOGRFieldType != OFTRealList &&
+            nOGRFieldType != OFTInteger &&
+            nOGRFieldType != OFTInteger64 &&
+            nOGRFieldType != OFTReal &&
+            nOGRFieldType != OFTBinary )
+        {
+            int iUTFChar = 0;
+            const int nMaxWidth = poFeatureDefn->GetFieldDefn(i)->GetWidth();
+
+            for( int iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
+            {
+                //count of utf chars
+                if (nOGRFieldType != OFTStringList && (pszStrValue[iChar] & 0xc0) != 0x80)
+                {
+                    if( nMaxWidth > 0 && iUTFChar == nMaxWidth )
+                    {
+                        CPLDebug( "PG",
+                                "Truncated %s field value, it was too long.",
+                                poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
+                        break;
+                    }
+                    iUTFChar++;
+                }
+
+                /* Escape embedded \, \t, \n, \r since they will cause COPY
+                   to misinterpret a line of text and thus abort */
+                if( pszStrValue[iChar] == '\\' ||
+                    pszStrValue[iChar] == '\t' ||
+                    pszStrValue[iChar] == '\r' ||
+                    pszStrValue[iChar] == '\n'   )
+                {
+                    osCommand += '\\';
+                }
+
+                osCommand += pszStrValue[iChar];
+            }
+        }
+        else
+        {
+            osCommand += pszStrValue;
+        }
+
+        if( pszNeedToFree )
+            CPLFree( pszNeedToFree );
+    }
+}
+
+/************************************************************************/
+/*                             StartCopy()                              */
+/************************************************************************/
+
+OGRErr OGRPGDumpLayer::StartCopy( int bSetFID )
+
+{
+    /* Tell the datasource we are now planning to copy data */
+    poDS->StartCopy( this );
+
+    CPLString osFields = BuildCopyFields(bSetFID);
+
+    size_t size = osFields.size() +  strlen(pszSqlTableName) + 100;
+    char *pszCommand = (char *) CPLMalloc(size);
+
+    snprintf( pszCommand, size,
+             "COPY %s (%s) FROM STDIN",
+             pszSqlTableName, osFields.c_str() );
+
+    poDS->Log(pszCommand);
+    bCopyActive = true;
+
+    CPLFree( pszCommand );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                              EndCopy()                               */
+/************************************************************************/
+
+OGRErr OGRPGDumpLayer::EndCopy()
+
+{
+    if( !bCopyActive )
+        return OGRERR_NONE;
+
+    bCopyActive = false;
+
+    poDS->Log("\\.", false);
+    poDS->Log("END");
+
+    bUseCopy = USE_COPY_UNSET;
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                          BuildCopyFields()                           */
+/************************************************************************/
+
+CPLString OGRPGDumpLayer::BuildCopyFields( int bSetFID )
+{
+    CPLString osFieldList;
+
+    for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+    {
+        if( !osFieldList.empty() )
+            osFieldList += ", ";
+
+        OGRGeomFieldDefn* poGFldDefn = poFeatureDefn->GetGeomFieldDefn(i);
+
+        osFieldList += OGRPGDumpEscapeColumnName(poGFldDefn->GetNameRef());
+    }
+
+    int nFIDIndex = -1;
+    bFIDColumnInCopyFields = pszFIDColumn != NULL && bSetFID;
+    if( bFIDColumnInCopyFields )
+    {
+        if( !osFieldList.empty() )
+            osFieldList += ", ";
+
+        nFIDIndex = poFeatureDefn->GetFieldIndex( pszFIDColumn );
+
+        osFieldList += OGRPGDumpEscapeColumnName(pszFIDColumn);
+    }
+
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    {
+        if (i == nFIDIndex)
+            continue;
+
+        const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
+
+       if( !osFieldList.empty() )
+            osFieldList += ", ";
+
+        osFieldList += OGRPGDumpEscapeColumnName(pszName);
+    }
+
+    return osFieldList;
+}
+
+/************************************************************************/
+/*                       OGRPGDumpEscapeColumnName( )                   */
+/************************************************************************/
+
+CPLString OGRPGDumpEscapeColumnName(const char* pszColumnName)
+{
+    CPLString osStr = "\"";
+
+    char ch = '\0';
+    for( int i = 0; (ch = pszColumnName[i]) != '\0'; i++ )
+    {
+        if (ch == '"')
+            osStr.append(1, ch);
+        osStr.append(1, ch);
+    }
+
+    osStr += "\"";
+
+    return osStr;
+}
+
+/************************************************************************/
+/*                             EscapeString( )                          */
+/************************************************************************/
+
+CPLString OGRPGDumpEscapeString( const char* pszStrValue, int nMaxLength,
+                                 const char* pszFieldName )
+{
+    CPLString osCommand;
+
+    /* We need to quote and escape string fields. */
+    osCommand += "'";
+
+    int nSrcLen = static_cast<int>(strlen(pszStrValue));
+    const int nSrcLenUTF = CPLStrlenUTF8(pszStrValue);
+
+    if (nMaxLength > 0 && nSrcLenUTF > nMaxLength)
+    {
+        CPLDebug( "PG",
+                  "Truncated %s field value, it was too long.",
+                  pszFieldName );
+
+        int iUTF8Char = 0;
+        for(int iChar = 0; iChar < nSrcLen; iChar++ )
+        {
+            if( (((unsigned char *) pszStrValue)[iChar] & 0xc0) != 0x80 )
+            {
+                if( iUTF8Char == nMaxLength )
+                {
+                    nSrcLen = iChar;
+                    break;
+                }
+                iUTF8Char ++;
+            }
+        }
+    }
+
+    char* pszDestStr = (char*)CPLMalloc(2 * nSrcLen + 1);
+
+    /* -------------------------------------------------------------------- */
+    /*  PQescapeStringConn was introduced in PostgreSQL security releases   */
+    /*  8.1.4, 8.0.8, 7.4.13, 7.3.15                                        */
+    /*  PG_HAS_PQESCAPESTRINGCONN is added by a test in 'configure'         */
+    /*  so it is not set by default when building OGR for Win32             */
+    /* -------------------------------------------------------------------- */
+#if defined(PG_HAS_PQESCAPESTRINGCONN)
+    int nError = 0;
+    PQescapeStringConn (hPGConn, pszDestStr, pszStrValue, nSrcLen, &nError);
+    if (nError == 0)
+        osCommand += pszDestStr;
+    else
+        CPLError(CE_Warning, CPLE_AppDefined,
+                 "PQescapeString(): %s\n"
+                 "  input: '%s'\n"
+                 "    got: '%s'\n",
+                 PQerrorMessage( hPGConn ),
+                 pszStrValue, pszDestStr );
+#else
+    //PQescapeString(pszDestStr, pszStrValue, nSrcLen);
+
+    int j = 0;  // Used after for.
+    for( int i = 0; i < nSrcLen; i++)
+    {
+        if (pszStrValue[i] == '\'')
+        {
+            pszDestStr[j++] = '\'';
+            pszDestStr[j++] = '\'';
+        }
+        // FIXME: at some point (when we drop PostgreSQL < 9.1 support, remove
+        // the escaping of backslash and remove
+        //   'SET standard_conforming_strings = OFF'
+        //  in ICreateLayer().
+        else if (pszStrValue[i] == '\\')
+        {
+            pszDestStr[j++] = '\\';
+            pszDestStr[j++] = '\\';
+        }
+        else
+        {
+            pszDestStr[j++] = pszStrValue[i];
+        }
+    }
+    pszDestStr[j] = 0;
+
+    osCommand += pszDestStr;
+#endif
+    CPLFree(pszDestStr);
+
+    osCommand += "'";
+
+    return osCommand;
+}
+
+/************************************************************************/
+/*                    OGRPGDumpEscapeStringList( )                      */
+/************************************************************************/
+
+static CPLString OGRPGDumpEscapeStringList(
+    char** papszItems, bool bForInsertOrUpdate,
+    OGRPGCommonEscapeStringCbk pfnEscapeString,
+    void* userdata)
+{
+    bool bFirstItem = true;
+    CPLString osStr;
+    if (bForInsertOrUpdate)
+        osStr += "ARRAY[";
+    else
+        osStr += "{";
+    while(papszItems && *papszItems)
+    {
+        if( !bFirstItem )
+        {
+            osStr += ',';
+        }
+
+        char* pszStr = *papszItems;
+        if (*pszStr != '\0')
+        {
+            if (bForInsertOrUpdate)
+                osStr += pfnEscapeString(userdata, pszStr, 0, "", "");
+            else
+            {
+                osStr += '"';
+
+                while(*pszStr)
+                {
+                    if (*pszStr == '"' )
+                        osStr += "\\";
+                    osStr += *pszStr;
+                    pszStr++;
+                }
+
+                osStr += '"';
+            }
+        }
+        else
+            osStr += "NULL";
+
+        bFirstItem = false;
+
+        papszItems++;
+    }
+    if (bForInsertOrUpdate)
+    {
+        osStr += "]";
+        if( papszItems == NULL )
+            osStr += "::varchar[]";
+    }
+    else
+        osStr += "}";
+    return osStr;
+}
+
+/************************************************************************/
+/*                          AppendFieldValue()                          */
+/*                                                                      */
+/* Used by CreateFeatureViaInsert() and SetFeature() to format a        */
+/* non-empty field value                                                */
+/************************************************************************/
+
+void OGRPGCommonAppendFieldValue(CPLString& osCommand,
+                                 OGRFeature* poFeature, int i,
+                                 OGRPGCommonEscapeStringCbk pfnEscapeString,
+                                 void* userdata)
+{
+    if( poFeature->IsFieldNull(i) )
+    {
+        osCommand += "NULL";
+        return;
+    }
+
+    OGRFeatureDefn* poFeatureDefn = poFeature->GetDefnRef();
+    OGRFieldType nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
+    OGRFieldSubType eSubType = poFeatureDefn->GetFieldDefn(i)->GetSubType();
+
+    // We need special formatting for integer list values.
+    if(  nOGRFieldType == OFTIntegerList )
+    {
+        int nCount, nOff = 0, j;
+        const int *panItems = poFeature->GetFieldAsIntegerList(i,&nCount);
+        char *pszNeedToFree = NULL;
+
+        const size_t nLen = nCount * 13 + 10;
+        pszNeedToFree = (char *) CPLMalloc(nLen);
+        strcpy( pszNeedToFree, "'{" );
+        for( j = 0; j < nCount; j++ )
+        {
+            if( j != 0 )
+                strcat( pszNeedToFree+nOff, "," );
+
+            nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+            snprintf( pszNeedToFree+nOff, nLen-nOff, "%d", panItems[j] );
+        }
+        strcat( pszNeedToFree+nOff, "}'" );
+
+        osCommand += pszNeedToFree;
+        CPLFree(pszNeedToFree);
+
+        return;
+    }
+
+    else if(  nOGRFieldType == OFTInteger64List )
+    {
+        int nCount, nOff = 0, j;
+        const GIntBig *panItems = poFeature->GetFieldAsInteger64List(i,&nCount);
+        char *pszNeedToFree = NULL;
+
+        const size_t nLen = nCount * 26 + 10;
+        pszNeedToFree = (char *) CPLMalloc(nLen);
+        strcpy( pszNeedToFree, "'{" );
+        for( j = 0; j < nCount; j++ )
+        {
+            if( j != 0 )
+                strcat( pszNeedToFree+nOff, "," );
+
+            nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+            snprintf( pszNeedToFree+nOff, nLen-nOff, CPL_FRMT_GIB, panItems[j] );
+        }
+        strcat( pszNeedToFree+nOff, "}'" );
+
+        osCommand += pszNeedToFree;
+        CPLFree(pszNeedToFree);
+
+        return;
+    }
+
+    // We need special formatting for real list values.
+    else if( nOGRFieldType == OFTRealList )
+    {
+        int nCount = 0;
+        int nOff = 0;
+        const double *padfItems = poFeature->GetFieldAsDoubleList(i,&nCount);
+        char *pszNeedToFree = NULL;
+
+        const size_t nLen = nCount * 40 + 10;
+        pszNeedToFree = (char *) CPLMalloc(nLen);
+        strcpy( pszNeedToFree, "'{" );
+        for( int j = 0; j < nCount; j++ )
+        {
+            if( j != 0 )
+                strcat( pszNeedToFree+nOff, "," );
+
+            nOff += static_cast<int>(strlen(pszNeedToFree+nOff));
+            //Check for special values. They need to be quoted.
+            if( CPLIsNan(padfItems[j]) )
+                snprintf( pszNeedToFree+nOff, nLen-nOff, "NaN" );
+            else if( CPLIsInf(padfItems[j]) )
+                snprintf( pszNeedToFree+nOff, nLen-nOff, (padfItems[j] > 0) ? "Infinity" : "-Infinity" );
+            else
+                CPLsnprintf( pszNeedToFree+nOff, nLen-nOff, "%.16g", padfItems[j] );
+        }
+        strcat( pszNeedToFree+nOff, "}'" );
+
+        osCommand += pszNeedToFree;
+        CPLFree(pszNeedToFree);
+
+        return;
+    }
+
+    // We need special formatting for string list values.
+    else if( nOGRFieldType == OFTStringList )
+    {
+        char **papszItems = poFeature->GetFieldAsStringList(i);
+
+        osCommand += OGRPGDumpEscapeStringList(papszItems, true,
+                                               pfnEscapeString, userdata);
+
+        return;
+    }
+
+    // Binary formatting
+    else if( nOGRFieldType == OFTBinary )
+    {
+        osCommand += "E'";
+
+        int nLen = 0;
+        GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );
+        char* pszBytea = OGRPGDumpLayer::GByteArrayToBYTEA( pabyData, nLen);
+
+        osCommand += pszBytea;
+
+        CPLFree(pszBytea);
+        osCommand += "'";
+
+        return;
+    }
+
+    // Flag indicating NULL or not-a-date date value
+    // e.g. 0000-00-00 - there is no year 0
+    bool bIsDateNull = false;
+
+    const char *pszStrValue = poFeature->GetFieldAsString(i);
+
+    // Check if date is NULL: 0000-00-00
+    if( nOGRFieldType == OFTDate )
+    {
+        if( STARTS_WITH_CI(pszStrValue, "0000") )
+        {
+            pszStrValue = "NULL";
+            bIsDateNull = true;
+        }
+    }
+    else if ( nOGRFieldType == OFTReal )
+    {
+        //Check for special values. They need to be quoted.
+        double dfVal = poFeature->GetFieldAsDouble(i);
+        if( CPLIsNan(dfVal) )
+            pszStrValue = "'NaN'";
+        else if( CPLIsInf(dfVal) )
+            pszStrValue = (dfVal > 0) ? "'Infinity'" : "'-Infinity'";
+    }
+    else if ( (nOGRFieldType == OFTInteger ||
+               nOGRFieldType == OFTInteger64) && eSubType == OFSTBoolean )
+        pszStrValue = poFeature->GetFieldAsInteger(i) ? "'t'" : "'f'";
+
+    if( nOGRFieldType != OFTInteger && nOGRFieldType != OFTInteger64 &&
+        nOGRFieldType != OFTReal && nOGRFieldType != OFTStringList
+        && !bIsDateNull )
+    {
+        osCommand += pfnEscapeString( userdata, pszStrValue,
+                                      poFeatureDefn->GetFieldDefn(i)->GetWidth(),
+                                      poFeatureDefn->GetName(),
+                                      poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
+    }
+    else
+    {
+        osCommand += pszStrValue;
+    }
+}
+
+/************************************************************************/
+/*                        GByteArrayToBYTEA()                           */
+/************************************************************************/
+
+char* OGRPGDumpLayer::GByteArrayToBYTEA( const GByte* pabyData, int nLen)
+{
+    const size_t nTextBufLen = nLen * 5 + 1;
+    char* pszTextBuf;
+    pszTextBuf = (char *) CPLMalloc(nTextBufLen);
+
+    int iDst = 0;
+
+    for( int iSrc = 0; iSrc < nLen; iSrc++ )
+    {
+        if( pabyData[iSrc] < 40 || pabyData[iSrc] > 126
+            || pabyData[iSrc] == '\\' )
+        {
+            snprintf( pszTextBuf+iDst, nTextBufLen - iDst, "\\\\%03o", pabyData[iSrc] );
+            iDst += 5;
+        }
+        else
+            pszTextBuf[iDst++] = pabyData[iSrc];
+    }
+    pszTextBuf[iDst] = '\0';
+
+    return pszTextBuf;
+}
+
+/************************************************************************/
+/*                       OGRPGCommonLayerGetType()                      */
+/************************************************************************/
+
+CPLString OGRPGCommonLayerGetType( OGRFieldDefn& oField,
+                                   bool bPreservePrecision,
+                                   bool bApproxOK )
+{
+    char szFieldType[256];
+
+/* -------------------------------------------------------------------- */
+/*      Work out the PostgreSQL type.                                   */
+/* -------------------------------------------------------------------- */
+    if( oField.GetType() == OFTInteger )
+    {
+        if( oField.GetSubType() == OFSTBoolean )
+            strcpy( szFieldType, "BOOLEAN" );
+        else if( oField.GetSubType() == OFSTInt16 )
+            strcpy( szFieldType, "SMALLINT" );
+        else if( oField.GetWidth() > 0 && bPreservePrecision )
+            snprintf( szFieldType, sizeof(szFieldType), "NUMERIC(%d,0)", oField.GetWidth() );
+        else
+            strcpy( szFieldType, "INTEGER" );
+    }
+    else if( oField.GetType() == OFTInteger64 )
+    {
+        if( oField.GetWidth() > 0 && bPreservePrecision )
+            snprintf( szFieldType, sizeof(szFieldType), "NUMERIC(%d,0)", oField.GetWidth() );
+        else
+            strcpy( szFieldType, "INT8" );
+    }
+    else if( oField.GetType() == OFTReal )
+    {
+        if( oField.GetSubType() == OFSTFloat32 )
+            strcpy( szFieldType, "REAL" );
+        else if( oField.GetWidth() > 0 &&
+                 oField.GetPrecision() > 0 &&
+                 bPreservePrecision )
+            snprintf( szFieldType, sizeof(szFieldType), "NUMERIC(%d,%d)",
+                     oField.GetWidth(), oField.GetPrecision() );
+        else
+            strcpy( szFieldType, "FLOAT8" );
+    }
+    else if( oField.GetType() == OFTString )
+    {
+        if (oField.GetWidth() > 0 &&  bPreservePrecision )
+            snprintf( szFieldType, sizeof(szFieldType), "VARCHAR(%d)",  oField.GetWidth() );
+        else
+            strcpy( szFieldType, "VARCHAR");
+    }
+    else if( oField.GetType() == OFTIntegerList )
+    {
+        if( oField.GetSubType() == OFSTBoolean )
+            strcpy( szFieldType, "BOOLEAN[]" );
+        else if( oField.GetSubType() == OFSTInt16 )
+            strcpy( szFieldType, "INT2[]" );
+        else
+            strcpy( szFieldType, "INTEGER[]" );
+    }
+    else if( oField.GetType() == OFTInteger64List )
+    {
+        strcpy( szFieldType, "INT8[]" );
+    }
+    else if( oField.GetType() == OFTRealList )
+    {
+        if( oField.GetSubType() == OFSTFloat32 )
+            strcpy( szFieldType, "REAL[]" );
+        else
+            strcpy( szFieldType, "FLOAT8[]" );
+    }
+    else if( oField.GetType() == OFTStringList )
+    {
+        strcpy( szFieldType, "varchar[]" );
+    }
+    else if( oField.GetType() == OFTDate )
+    {
+        strcpy( szFieldType, "date" );
+    }
+    else if( oField.GetType() == OFTTime )
+    {
+        strcpy( szFieldType, "time" );
+    }
+    else if( oField.GetType() == OFTDateTime )
+    {
+        strcpy( szFieldType, "timestamp with time zone" );
+    }
+    else if( oField.GetType() == OFTBinary )
+    {
+        strcpy( szFieldType, "bytea" );
+    }
+    else if( bApproxOK )
+    {
+        CPLError( CE_Warning, CPLE_NotSupported,
+                  "Can't create field %s with type %s on PostgreSQL layers.  Creating as VARCHAR.",
+                  oField.GetNameRef(),
+                  OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
+        strcpy( szFieldType, "VARCHAR" );
+    }
+    else
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Can't create field %s with type %s on PostgreSQL layers.",
+                  oField.GetNameRef(),
+                  OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
+        strcpy( szFieldType, "");
+    }
+
+    return szFieldType;
+}
+
+/************************************************************************/
+/*                         OGRPGCommonLayerSetType()                    */
+/************************************************************************/
+
+bool OGRPGCommonLayerSetType( OGRFieldDefn& oField,
+                              const char* pszType,
+                              const char* pszFormatType,
+                              int nWidth )
+{
+    if( EQUAL(pszType,"text") )
+    {
+        oField.SetType( OFTString );
+    }
+    else if( EQUAL(pszType,"_bpchar") ||
+            EQUAL(pszType,"_varchar") ||
+            EQUAL(pszType,"_text"))
+    {
+        oField.SetType( OFTStringList );
+    }
+    else if( EQUAL(pszType,"bpchar") || EQUAL(pszType,"varchar") )
+    {
+        if( nWidth == -1 )
+        {
+            if( STARTS_WITH_CI(pszFormatType, "character(") )
+                nWidth = atoi(pszFormatType+10);
+            else if( STARTS_WITH_CI(pszFormatType, "character varying(") )
+                nWidth = atoi(pszFormatType+18);
+            else
+                nWidth = 0;
+        }
+        oField.SetType( OFTString );
+        oField.SetWidth( nWidth );
+    }
+    else if( EQUAL(pszType,"bool") )
+    {
+        oField.SetType( OFTInteger );
+        oField.SetSubType( OFSTBoolean );
+        oField.SetWidth( 1 );
+    }
+    else if( EQUAL(pszType,"_numeric") )
+    {
+        if( EQUAL(pszFormatType, "numeric[]") )
+            oField.SetType( OFTRealList );
+        else
+        {
+            const char *pszPrecision = strstr(pszFormatType,",");
+            int    nPrecision = 0;
+
+            nWidth = atoi(pszFormatType + 8);
+            if( pszPrecision != NULL )
+                nPrecision = atoi(pszPrecision+1);
+
+            if( nPrecision == 0 )
+            {
+                if( nWidth >= 10 )
+                    oField.SetType( OFTInteger64List );
+                else
+                    oField.SetType( OFTIntegerList );
+            }
+            else
+                oField.SetType( OFTRealList );
+
+            oField.SetWidth( nWidth );
+            oField.SetPrecision( nPrecision );
+        }
+    }
+    else if( EQUAL(pszType,"numeric") )
+    {
+        if( EQUAL(pszFormatType, "numeric") )
+            oField.SetType( OFTReal );
+        else
+        {
+            const char *pszPrecision = strstr(pszFormatType,",");
+            int    nPrecision = 0;
+
+            nWidth = atoi(pszFormatType + 8);
+            if( pszPrecision != NULL )
+                nPrecision = atoi(pszPrecision+1);
+
+            if( nPrecision == 0 )
+            {
+                if( nWidth >= 10 )
+                    oField.SetType( OFTInteger64 );
+                else
+                    oField.SetType( OFTInteger );
+            }
+            else
+                oField.SetType( OFTReal );
+
+            oField.SetWidth( nWidth );
+            oField.SetPrecision( nPrecision );
+        }
+    }
+    else if( EQUAL(pszFormatType,"integer[]") )
+    {
+        oField.SetType( OFTIntegerList );
+    }
+    else if( EQUAL(pszFormatType,"smallint[]") )
+    {
+        oField.SetType( OFTIntegerList );
+        oField.SetSubType( OFSTInt16 );
+    }
+    else if( EQUAL(pszFormatType,"boolean[]") )
+    {
+        oField.SetType( OFTIntegerList );
+        oField.SetSubType( OFSTBoolean );
+    }
+    else if( EQUAL(pszFormatType, "float[]") ||
+            EQUAL(pszFormatType, "real[]") )
+    {
+        oField.SetType( OFTRealList );
+        oField.SetSubType( OFSTFloat32 );
+    }
+    else if( EQUAL(pszFormatType, "double precision[]") )
+    {
+        oField.SetType( OFTRealList );
+    }
+    else if( EQUAL(pszType,"int2") )
+    {
+        oField.SetType( OFTInteger );
+        oField.SetSubType( OFSTInt16 );
+        oField.SetWidth( 5 );
+    }
+    else if( EQUAL(pszType,"int8") )
+    {
+        oField.SetType( OFTInteger64 );
+    }
+    else if( EQUAL(pszFormatType,"bigint[]") )
+    {
+        oField.SetType( OFTInteger64List );
+    }
+    else if( STARTS_WITH_CI(pszType, "int") )
+    {
+        oField.SetType( OFTInteger );
+    }
+    else if( EQUAL(pszType,"float4")  )
+    {
+        oField.SetType( OFTReal );
+        oField.SetSubType( OFSTFloat32 );
+    }
+    else if( STARTS_WITH_CI(pszType, "float") ||
+            STARTS_WITH_CI(pszType, "double") ||
+            EQUAL(pszType,"real") )
+    {
+        oField.SetType( OFTReal );
+    }
+    else if( STARTS_WITH_CI(pszType, "timestamp") )
+    {
+        oField.SetType( OFTDateTime );
+    }
+    else if( STARTS_WITH_CI(pszType, "date") )
+    {
+        oField.SetType( OFTDate );
+    }
+    else if( STARTS_WITH_CI(pszType, "time") )
+    {
+        oField.SetType( OFTTime );
+    }
+    else if( EQUAL(pszType,"bytea") )
+    {
+        oField.SetType( OFTBinary );
+    }
+    else
+    {
+        CPLDebug( "PGCommon", "Field %s is of unknown format type %s (type=%s).",
+                oField.GetNameRef(), pszFormatType, pszType );
+        return false;
+    }
+    return true;
+}
+
+/************************************************************************/
+/*                  OGRPGCommonLayerNormalizeDefault()                  */
+/************************************************************************/
+
+void OGRPGCommonLayerNormalizeDefault(OGRFieldDefn* poFieldDefn,
+                                      const char* pszDefault)
+{
+    if(pszDefault==NULL)
+        return;
+    CPLString osDefault(pszDefault);
+    size_t nPos = osDefault.find("::character varying");
+    if( nPos != std::string::npos )
+        osDefault.resize(nPos);
+    else if( strcmp(osDefault, "now()") == 0 )
+        osDefault = "CURRENT_TIMESTAMP";
+    else if( strcmp(osDefault, "('now'::text)::date") == 0 )
+        osDefault = "CURRENT_DATE";
+    else if( strcmp(osDefault, "('now'::text)::time with time zone") == 0 )
+        osDefault = "CURRENT_TIME";
+    else
+    {
+        nPos = osDefault.find("::timestamp with time zone");
+        if( poFieldDefn->GetType() == OFTDateTime && nPos != std::string::npos )
+        {
+            osDefault.resize(nPos);
+            nPos = osDefault.find("'+");
+            if( nPos != std::string::npos )
+            {
+                osDefault.resize(nPos);
+                osDefault += "'";
+            }
+            int nYear = 0;
+            int nMonth = 0;
+            int nDay = 0;
+            int nHour = 0;
+            int nMinute = 0;
+            float fSecond = 0.0f;
+            if( sscanf(osDefault, "'%d-%d-%d %d:%d:%f'", &nYear, &nMonth, &nDay,
+                                &nHour, &nMinute, &fSecond) == 6 ||
+                sscanf(osDefault, "'%d-%d-%d %d:%d:%f+00'", &nYear, &nMonth, &nDay,
+                                &nHour, &nMinute, &fSecond) == 6)
+            {
+                if( osDefault.find('.') == std::string::npos )
+                    osDefault = CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%02d'",
+                                            nYear, nMonth, nDay, nHour, nMinute, (int)(fSecond+0.5));
+                else
+                    osDefault = CPLSPrintf("'%04d/%02d/%02d %02d:%02d:%06.3f'",
+                                                    nYear, nMonth, nDay, nHour, nMinute, fSecond);
+            }
+        }
+    }
+    poFieldDefn->SetDefault(osDefault);
+}
+
+/************************************************************************/
+/*                     OGRPGCommonLayerGetPGDefault()                   */
+/************************************************************************/
+
+CPLString OGRPGCommonLayerGetPGDefault(OGRFieldDefn* poFieldDefn)
+{
+    CPLString osRet = poFieldDefn->GetDefault();
+    int nYear = 0;
+    int nMonth = 0;
+    int nDay = 0;
+    int nHour = 0;
+    int nMinute = 0;
+    float fSecond = 0.0f;
+    if( sscanf(osRet, "'%d/%d/%d %d:%d:%f'",
+                &nYear, &nMonth, &nDay,
+                &nHour, &nMinute, &fSecond) == 6 )
+    {
+        osRet.resize(osRet.size()-1);
+        osRet += "+00'::timestamp with time zone";
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRErr OGRPGDumpLayer::CreateField( OGRFieldDefn *poFieldIn,
+                                    int bApproxOK )
+{
+    CPLString osFieldType;
+    OGRFieldDefn oField( poFieldIn );
+
+    // Can be set to NO to test ogr2ogr default behaviour
+    const bool bAllowCreationOfFieldWithFIDName =
+        CPLTestBool(CPLGetConfigOption(
+            "PGDUMP_DEBUG_ALLOW_CREATION_FIELD_WITH_FID_NAME", "YES"));
+
+    if( bAllowCreationOfFieldWithFIDName && pszFIDColumn != NULL &&
+        EQUAL( oField.GetNameRef(), pszFIDColumn ) &&
+        oField.GetType() != OFTInteger &&
+        oField.GetType() != OFTInteger64 )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Wrong field type for %s",
+                 oField.GetNameRef());
+        return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we want to "launder" the column names into Postgres          */
+/*      friendly format?                                                */
+/* -------------------------------------------------------------------- */
+    if( bLaunderColumnNames )
+    {
+        char *pszSafeName =
+            OGRPGCommonLaunderName( oField.GetNameRef(), "PGDump" );
+
+        oField.SetName( pszSafeName );
+        CPLFree( pszSafeName );
+
+        if( EQUAL(oField.GetNameRef(),"oid") )
+        {
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Renaming field 'oid' to 'oid_' to avoid conflict with "
+                      "internal oid field." );
+            oField.SetName( "oid_" );
+        }
+    }
+
+    const char* pszOverrideType =
+        CSLFetchNameValue(papszOverrideColumnTypes, oField.GetNameRef());
+    if( pszOverrideType != NULL )
+    {
+        osFieldType = pszOverrideType;
+    }
+    else
+    {
+        osFieldType =
+            OGRPGCommonLayerGetType(oField, bPreservePrecision,
+                                    CPL_TO_BOOL(bApproxOK));
+        if (osFieldType.empty())
+            return OGRERR_FAILURE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create the new field.                                           */
+/* -------------------------------------------------------------------- */
+    CPLString osCommand;
+    osCommand.Printf( "ALTER TABLE %s ADD COLUMN %s %s",
+                      pszSqlTableName,
+                      OGRPGDumpEscapeColumnName(oField.GetNameRef()).c_str(),
+                      osFieldType.c_str() );
+    if( !oField.IsNullable() )
+        osCommand += " NOT NULL";
+    if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
+    {
+        osCommand += " DEFAULT ";
+        osCommand += OGRPGCommonLayerGetPGDefault(&oField);
+    }
+
+    poFeatureDefn->AddFieldDefn( &oField );
+
+    if( bAllowCreationOfFieldWithFIDName && pszFIDColumn != NULL &&
+        EQUAL( oField.GetNameRef(), pszFIDColumn ) )
+    {
+        iFIDAsRegularColumnIndex = poFeatureDefn->GetFieldCount() - 1;
+    }
+    else
+    {
+        if( bCreateTable )
+            poDS->Log(osCommand);
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                           CreateGeomField()                          */
+/************************************************************************/
+
+OGRErr OGRPGDumpLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
+                                        int /* bApproxOK */ )
+{
+    OGRwkbGeometryType eType = poGeomFieldIn->GetType();
+    if( eType == wkbNone )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot create geometry field of type wkbNone");
+        return OGRERR_FAILURE;
+    }
+
+    // Check if GEOMETRY_NAME layer creation option was set, but no initial
+    // column was created in ICreateLayer()
+    const CPLString osGeomFieldName =
+        !m_osFirstGeometryFieldName.empty()
+        ? m_osFirstGeometryFieldName
+        : CPLString(poGeomFieldIn->GetNameRef());
+
+    m_osFirstGeometryFieldName = ""; // reset for potential next geom columns
+
+    OGRGeomFieldDefn oTmpGeomFieldDefn( poGeomFieldIn );
+    oTmpGeomFieldDefn.SetName(osGeomFieldName);
+
+    CPLString               osCommand;
+    OGRPGDumpGeomFieldDefn *poGeomField =
+        new OGRPGDumpGeomFieldDefn( &oTmpGeomFieldDefn );
+
+/* -------------------------------------------------------------------- */
+/*      Do we want to "launder" the column names into Postgres          */
+/*      friendly format?                                                */
+/* -------------------------------------------------------------------- */
+    if( bLaunderColumnNames )
+    {
+        char *pszSafeName =
+            OGRPGCommonLaunderName( poGeomField->GetNameRef(), "PGDump" );
+
+        poGeomField->SetName( pszSafeName );
+        CPLFree( pszSafeName );
+    }
+
+    OGRSpatialReference* poSRS = poGeomField->GetSpatialRef();
+    int nSRSId = nUnknownSRSId;
+    if( nForcedSRSId != -2 )
+        nSRSId = nForcedSRSId;
+    else if( poSRS != NULL )
+    {
+        const char* pszAuthorityName = poSRS->GetAuthorityName(NULL);
+        if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
+        {
+            /* Assume the EPSG Id is the SRS ID. Might be a wrong guess ! */
+            nSRSId = atoi( poSRS->GetAuthorityCode(NULL) );
+        }
+        else
+        {
+            const char* pszGeogCSName = poSRS->GetAttrValue("GEOGCS");
+            if (pszGeogCSName != NULL && EQUAL(pszGeogCSName, "GCS_WGS_1984"))
+                nSRSId = 4326;
+        }
+    }
+
+    poGeomField->nSRSId = nSRSId;
+
+    int GeometryTypeFlags = 0;
+    if( OGR_GT_HasZ((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_3D;
+    if( OGR_GT_HasM((OGRwkbGeometryType)eType) )
+        GeometryTypeFlags |= OGRGeometry::OGR_G_MEASURED;
+    if( nForcedGeometryTypeFlags >= 0 )
+    {
+        GeometryTypeFlags = nForcedGeometryTypeFlags;
+        eType = OGR_GT_SetModifier(eType,
+                                   GeometryTypeFlags & OGRGeometry::OGR_G_3D,
+                                   GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED);
+    }
+    poGeomField->SetType(eType);
+    poGeomField->GeometryTypeFlags = GeometryTypeFlags;
+
+/* -------------------------------------------------------------------- */
+/*      Create the new field.                                           */
+/* -------------------------------------------------------------------- */
+    if (bCreateTable)
+    {
+        const char *suffix = "";
+        int dim = 2;
+        if( (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D) && (poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED) )
+            dim = 4;
+        else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_MEASURED )
+        {
+            if( wkbFlatten(poGeomField->GetType()) != wkbUnknown )
+                suffix = "M";
+            dim = 3;
+        }
+        else if( poGeomField->GeometryTypeFlags & OGRGeometry::OGR_G_3D )
+            dim = 3;
+
+        const char *pszGeometryType = OGRToOGCGeomType(poGeomField->GetType());
+        osCommand.Printf(
+                "SELECT AddGeometryColumn(%s,%s,%s,%d,'%s%s',%d)",
+                OGRPGDumpEscapeString(pszSchemaName).c_str(),
+                OGRPGDumpEscapeString(poFeatureDefn->GetName()).c_str(),
+                OGRPGDumpEscapeString(poGeomField->GetNameRef()).c_str(),
+                nSRSId, pszGeometryType, suffix, dim );
+
+        poDS->Log(osCommand);
+
+        if( !poGeomField->IsNullable() )
+        {
+            osCommand.Printf( "ALTER TABLE %s ALTER COLUMN %s SET NOT NULL",
+                              OGRPGDumpEscapeColumnName(poFeatureDefn->GetName()).c_str(),
+                              OGRPGDumpEscapeColumnName(poGeomField->GetNameRef()).c_str() );
+
+            poDS->Log(osCommand);
+        }
+
+        if( bCreateSpatialIndexFlag )
+        {
+            osCommand.Printf("CREATE INDEX %s ON %s USING GIST (%s)",
+                            OGRPGDumpEscapeColumnName(
+                                CPLSPrintf("%s_%s_geom_idx", GetName(), poGeomField->GetNameRef())).c_str(),
+                            pszSqlTableName,
+                            OGRPGDumpEscapeColumnName(poGeomField->GetNameRef()).c_str());
+
+            poDS->Log(osCommand);
+        }
+    }
+
+    poFeatureDefn->AddGeomFieldDefn( poGeomField, FALSE );
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                        SetOverrideColumnTypes()                      */
+/************************************************************************/
+
+void OGRPGDumpLayer::SetOverrideColumnTypes( const char* pszOverrideColumnTypes )
+{
+    if( pszOverrideColumnTypes == NULL )
+        return;
+
+    const char* pszIter = pszOverrideColumnTypes;
+    CPLString osCur;
+    while(*pszIter != '\0')
+    {
+        if( *pszIter == '(' )
+        {
+            /* Ignore commas inside ( ) pair */
+            while(*pszIter != '\0')
+            {
+                if( *pszIter == ')' )
+                {
+                    osCur += *pszIter;
+                    pszIter ++;
+                    break;
+                }
+                osCur += *pszIter;
+                pszIter ++;
+            }
+            if( *pszIter == '\0')
+                break;
+        }
+
+        if( *pszIter == ',' )
+        {
+            papszOverrideColumnTypes = CSLAddString(papszOverrideColumnTypes, osCur);
+            osCur = "";
+        }
+        else
+            osCur += *pszIter;
+        pszIter ++;
+    }
+    if( !osCur.empty() )
+        papszOverrideColumnTypes = CSLAddString(papszOverrideColumnTypes, osCur);
+}
+
+/************************************************************************/
+/*                              SetMetadata()                           */
+/************************************************************************/
+
+CPLErr OGRPGDumpLayer::SetMetadata(char** papszMD, const char* pszDomain)
+{
+    OGRLayer::SetMetadata(papszMD, pszDomain);
+    if( !osForcedDescription.empty() &&
+        (pszDomain == NULL || EQUAL(pszDomain, "")) )
+    {
+        OGRLayer::SetMetadataItem("DESCRIPTION", osForcedDescription);
+    }
+
+    if( (pszDomain == NULL || EQUAL(pszDomain, "")) &&
+        osForcedDescription.empty() )
+    {
+        const char* l_pszDescription = OGRLayer::GetMetadataItem("DESCRIPTION");
+        CPLString osCommand;
+
+        osCommand.Printf( "COMMENT ON TABLE %s IS %s",
+                           pszSqlTableName,
+                           l_pszDescription && l_pszDescription[0] != '\0' ?
+                              OGRPGDumpEscapeString(l_pszDescription).c_str() : "NULL" );
+        poDS->Log( osCommand );
+    }
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            SetMetadataItem()                         */
+/************************************************************************/
+
+CPLErr OGRPGDumpLayer::SetMetadataItem(const char* pszName, const char* pszValue,
+                                       const char* pszDomain)
+{
+    if( (pszDomain == NULL || EQUAL(pszDomain, "")) && pszName != NULL &&
+        EQUAL(pszName, "DESCRIPTION") && !osForcedDescription.empty() )
+    {
+        return CE_None;
+    }
+    OGRLayer::SetMetadataItem(pszName, pszValue, pszDomain);
+    if( (pszDomain == NULL || EQUAL(pszDomain, "")) && pszName != NULL &&
+        EQUAL(pszName, "DESCRIPTION") )
+    {
+        SetMetadata( GetMetadata() );
+    }
+    return CE_None;
+}
+
+/************************************************************************/
+/*                      SetForcedDescription()                          */
+/************************************************************************/
+
+void OGRPGDumpLayer::SetForcedDescription( const char* pszDescriptionIn )
+{
+    osForcedDescription = pszDescriptionIn;
+    OGRLayer::SetMetadataItem("DESCRIPTION", osForcedDescription);
+
+    if( pszDescriptionIn[0] != '\0' )
+    {
+        CPLString osCommand;
+        osCommand.Printf( "COMMENT ON TABLE %s IS %s",
+                            pszSqlTableName,
+                            OGRPGDumpEscapeString(pszDescriptionIn).c_str() );
+        poDS->Log( osCommand );
+    }
+}
diff --git a/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h b/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
index 2dfa353..9ec8d36 100644
--- a/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
+++ b/ogr/ogrsf_frmts/pgeo/ogr_pgeo.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_pgeo.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_pgeo.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for Personal Geodatabase driver.
@@ -72,18 +72,18 @@ class OGRPGeoLayer : public OGRLayer
                         OGRPGeoLayer();
     virtual             ~OGRPGeoLayer();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
     virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual const char *GetFIDColumn();
-    virtual const char *GetGeometryColumn();
+    virtual const char *GetFIDColumn() override;
+    virtual const char *GetGeometryColumn() override;
 };
 
 /************************************************************************/
@@ -92,20 +92,18 @@ class OGRPGeoLayer : public OGRLayer
 
 class OGRPGeoTableLayer : public OGRPGeoLayer
 {
-    int                 bUpdateAccess;
-
     char                *pszQuery;
 
-    void		ClearStatement();
+    void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *  GetStatement() override;
 
     OGREnvelope         sExtent;
 
   public:
-                        OGRPGeoTableLayer( OGRPGeoDataSource * );
-                        ~OGRPGeoTableLayer();
+    explicit            OGRPGeoTableLayer( OGRPGeoDataSource * );
+                        virtual ~OGRPGeoTableLayer();
 
     CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol,
@@ -117,16 +115,16 @@ class OGRPGeoTableLayer : public OGRPGeoLayer
                                     int nSRID,
                                     int bHasZ );
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
@@ -138,22 +136,22 @@ class OGRPGeoSelectLayer : public OGRPGeoLayer
 {
     char                *pszBaseStatement;
 
-    void		ClearStatement();
+    void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *  GetStatement() override;
 
   public:
                         OGRPGeoSelectLayer( OGRPGeoDataSource *,
                                            CPLODBCStatement * );
-                        ~OGRPGeoSelectLayer();
+                        virtual ~OGRPGeoSelectLayer();
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -172,23 +170,23 @@ class OGRPGeoDataSource : public OGRDataSource
 
   public:
                         OGRPGeoDataSource();
-                        ~OGRPGeoDataSource();
+                        virtual ~OGRPGeoDataSource();
 
     int                 Open( const char *, int bUpdate, int bTestOpen );
     int                 OpenTable( const char *pszTableName,
                                    const char *pszGeomCol,
                                    int bUpdate );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     // Internal use
     CPLODBCSession     *GetSession() { return &oSession; }
@@ -202,7 +200,7 @@ class OGRODBCMDBDriver : public OGRSFDriver
 {
 #ifndef WIN32
     CPLString   osDriverFile;
-    bool        LibraryExists( const char* pszLibPath );
+    static bool        LibraryExists( const char* pszLibPath );
     bool        FindDriverLib();
     CPLString   FindDefaultLib(const char* pszLibName);
 #endif
@@ -222,10 +220,10 @@ class OGRPGeoDriver : public OGRODBCMDBDriver
   public:
                 ~OGRPGeoDriver();
 
-    const char  *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char  *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
-    int          TestCapability( const char * );
+    int          TestCapability( const char * ) override;
 };
 
 #endif /* ndef _OGR_PGeo_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp
index 2d054f9..3931cb2 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeodatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgeodatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoDataSource class.
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include <vector>
 
-CPL_CVSID("$Id: ogrpgeodatasource.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrpgeodatasource.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                         OGRPGeoDataSource()                          */
@@ -44,7 +43,7 @@ OGRPGeoDataSource::OGRPGeoDataSource() :
     nLayers(0),
     pszName(NULL),
     bDSUpdate(FALSE)
-{ }
+{}
 
 /************************************************************************/
 /*                         ~OGRPGeoDataSource()                         */
@@ -106,7 +105,7 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
 /*      get the DSN.                                                    */
 /*                                                                      */
 /* -------------------------------------------------------------------- */
-    char *pszDSN;
+    char *pszDSN = NULL;
     const char* pszOptionName = "";
     const char* pszDSNStringTemplate = NULL;
     if( STARTS_WITH_CI(pszNewName, "PGEO:") )
@@ -210,9 +209,7 @@ int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
     for( iTable = 0; iTable < apapszGeomColumns.size(); iTable++ )
     {
         char **papszRecord = apapszGeomColumns[iTable];
-        OGRPGeoTableLayer  *poLayer;
-
-        poLayer = new OGRPGeoTableLayer( this );
+        OGRPGeoTableLayer  *poLayer = new OGRPGeoTableLayer( this );
 
         if( poLayer->Initialize( papszRecord[0],         // TableName
                                  papszRecord[1],         // FieldName
@@ -258,7 +255,6 @@ OGRLayer *OGRPGeoDataSource::GetLayer( int iLayer )
         return papoLayers[iLayer];
 }
 
-
 /************************************************************************/
 /*                             ExecuteSQL()                             */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
index 9cdc983..abf0c32 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeodriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgeodriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Personal Geodatabase driver.
@@ -31,7 +30,7 @@
 #include "ogr_pgeo.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrpgeodriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrpgeodriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                            ~OGRODBCDriver()                            */
@@ -60,8 +59,6 @@ OGRDataSource *OGRPGeoDriver::Open( const char * pszFilename,
                                     int bUpdate )
 
 {
-    OGRPGeoDataSource     *poDS;
-
     if( STARTS_WITH_CI(pszFilename, "WALK:") )
         return NULL;
 
@@ -132,7 +129,7 @@ OGRDataSource *OGRPGeoDriver::Open( const char * pszFilename,
 #endif /* ndef WIN32 */
 
     // Open data source
-    poDS = new OGRPGeoDataSource();
+    OGRPGeoDataSource *poDS = new OGRPGeoDataSource();
 
     if( !poDS->Open( pszFilename, bUpdate, TRUE ) )
     {
@@ -152,7 +149,6 @@ int OGRPGeoDriver::TestCapability( CPL_UNUSED const char * pszCap )
     return FALSE;
 }
 
-
 /*
  * START OF UNIX-only features.
  */
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
index eb9fe46..f07ba00 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeolayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgeolayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoLayer class, code shared between
@@ -34,29 +33,25 @@
 #include "cpl_string.h"
 #include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: ogrpgeolayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrpgeolayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                            OGRPGeoLayer()                            */
 /************************************************************************/
 
-OGRPGeoLayer::OGRPGeoLayer()
-
-{
-    poDS = NULL;
-
-    pszGeomColumn = NULL;
-    pszFIDColumn = NULL;
-
-    poStmt = NULL;
-
-    iNextShapeId = 0;
-
-    poSRS = NULL;
-    nSRSId = -2; // we haven't even queried the database for it yet.
-    poFeatureDefn = NULL;
-    panFieldOrdinals = NULL;
-}
+OGRPGeoLayer::OGRPGeoLayer() :
+    poFeatureDefn(NULL),
+    poStmt(NULL),
+    poSRS(NULL),
+    nSRSId(-2), // we haven't even queried the database for it yet.
+    iNextShapeId(0),
+    poDS(NULL),
+    pszGeomColumn(NULL),
+    pszFIDColumn(NULL),
+    panFieldOrdinals(NULL)
+{}
 
 /************************************************************************/
 /*                            ~OGRPGeoLayer()                             */
@@ -68,7 +63,7 @@ OGRPGeoLayer::~OGRPGeoLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "PGeo", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead,
+                  static_cast<int>(m_nFeaturesRead),
                   poFeatureDefn->GetName() );
     }
 
@@ -119,7 +114,8 @@ CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName,
     {
         OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
 
-        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
+        oField.SetWidth(
+            std::max(static_cast<short>(0), poStmtIn->GetColSize( iCol )));
 
         if( pszGeomColumn != NULL
             && EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )
@@ -189,7 +185,6 @@ CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName,
     return CE_None;
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -209,9 +204,7 @@ OGRFeature *OGRPGeoLayer::GetNextFeature()
 {
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -270,7 +263,7 @@ OGRFeature *OGRPGeoLayer::GetNextRawFeature()
         const char *pszValue = poStmt->GetColData( iSrcField );
 
         if( pszValue == NULL )
-            /* no value */;
+            poFeature->SetFieldNull( iField );
         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
             poFeature->SetField( iField,
                                  poStmt->GetColDataLength(iSrcField),
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp
index db4defb..8afdde5 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeoselectlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgeoselectlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoSelectLayer class, layer access to the results
@@ -32,15 +31,15 @@
 #include "cpl_conv.h"
 #include "ogr_pgeo.h"
 
-CPL_CVSID("$Id: ogrpgeoselectlayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+CPL_CVSID("$Id: ogrpgeoselectlayer.cpp 35198 2016-08-24 19:34:58Z goatbar $");
 
 /************************************************************************/
 /*                          OGRPGeoSelectLayer()                        */
 /************************************************************************/
 
 OGRPGeoSelectLayer::OGRPGeoSelectLayer( OGRPGeoDataSource *poDSIn,
-                                        CPLODBCStatement * poStmtIn )
-
+                                        CPLODBCStatement * poStmtIn ) :
+    pszBaseStatement(CPLStrdup(poStmtIn->GetCommand()))
 {
     poDS = poDSIn;
 
@@ -49,10 +48,9 @@ OGRPGeoSelectLayer::OGRPGeoSelectLayer( OGRPGeoDataSource *poDSIn,
     poFeatureDefn = NULL;
 
     poStmt = poStmtIn;
-    pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
 
-    /* Just to make test_ogrsf happy, but would/could need be extended to */
-    /* other cases */
+    // Just to make test_ogrsf happy, but would/could need be extended to
+    // other cases.
     if( STARTS_WITH_CI(pszBaseStatement, "SELECT * FROM ") )
     {
 
diff --git a/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp b/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
index 2239479..be6b794 100644
--- a/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
+++ b/ogr/ogrsf_frmts/pgeo/ogrpgeotablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrpgeotablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRPGeoTableLayer class, access to an existing table.
@@ -32,18 +31,16 @@
 #include "ogr_pgeo.h"
 #include "ogrpgeogeometry.h"
 
-CPL_CVSID("$Id: ogrpgeotablelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrpgeotablelayer.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                          OGRPGeoTableLayer()                         */
 /************************************************************************/
 
-OGRPGeoTableLayer::OGRPGeoTableLayer( OGRPGeoDataSource *poDSIn )
-
+OGRPGeoTableLayer::OGRPGeoTableLayer( OGRPGeoDataSource *poDSIn ) :
+    pszQuery(NULL)
 {
     poDS = poDSIn;
-    pszQuery = NULL;
-    bUpdateAccess = TRUE;
     iNextShapeId = 0;
     nSRSId = -1;
     poFeatureDefn = NULL;
@@ -305,20 +302,19 @@ OGRErr OGRPGeoTableLayer::SetAttributeFilter( const char *pszQueryIn )
     CPLFree(m_pszAttrQueryString);
     m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
 
-    if( (pszQueryIn == NULL && this->pszQuery == NULL)
-        || (pszQueryIn != NULL && this->pszQuery != NULL
-            && EQUAL(pszQueryIn,this->pszQuery)) )
+    if( (pszQueryIn == NULL && pszQuery == NULL)
+        || (pszQueryIn != NULL && pszQuery != NULL
+            && EQUAL(pszQueryIn, pszQuery)) )
         return OGRERR_NONE;
 
-    CPLFree( this->pszQuery );
-    this->pszQuery = pszQueryIn ? CPLStrdup( pszQueryIn ) : NULL;
+    CPLFree( pszQuery );
+    pszQuery = pszQueryIn ? CPLStrdup( pszQueryIn ) : NULL;
 
     ClearStatement();
 
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/plscenes/GNUmakefile b/ogr/ogrsf_frmts/plscenes/GNUmakefile
index fc911e9..b5923b5 100644
--- a/ogr/ogrsf_frmts/plscenes/GNUmakefile
+++ b/ogr/ogrsf_frmts/plscenes/GNUmakefile
@@ -2,7 +2,8 @@
 
 include ../../../GDALmake.opt
 
-OBJ	=	ogrplscenesdriver.o ogrplscenesdataset.o ogrplscenesv1dataset.o ogrplsceneslayer.o ogrplscenesv1layer.o
+OBJ	=	ogrplscenesdriver.o ogrplscenesdataset.o ogrplscenesv1dataset.o ogrplsceneslayer.o ogrplscenesv1layer.o \
+		ogrplscenesdatav1layer.o ogrplscenesdatav1dataset.o
 
 CPPFLAGS	:=	$(JSON_INCLUDE) -I.. -I../.. -I../geojson  $(CPPFLAGS)
 
diff --git a/ogr/ogrsf_frmts/plscenes/drv_plscenes.html b/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
index 45fb2f2..13f3cb4 100644
--- a/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
+++ b/ogr/ogrsf_frmts/plscenes/drv_plscenes.html
@@ -7,516 +7,24 @@
 
 <h1>PLScenes (Planet Labs Scenes/Catalog API)</h1>
 
-(GDAL/OGR >= 2.0 for v0 API, and GDAL/OGR >= 2.1 for v1 API)<p>
+(GDAL/OGR >= 2.0 for V0 API,  GDAL/OGR >= 2.1 for V1 API,  GDAL/OGR >= 2.2 for Data V1 API)<p>
 
-This driver can connect to Planet Labs Scenes v0/Catalog v1 API.
+This driver can connect to Planet Labs Scenes v0/Catalog v1/Data V1 API.
 GDAL/OGR must be built with Curl support in order for the
 PLScenes driver to be compiled.<p>
 
-The driver supports read-only operations to list scenes and their metadata
-as a vector layer per scene type/catalog ("ortho" for example). It can also access raster scenes.<p>
-
-<h2>Dataset name syntax</h2>
-
-The minimal syntax to open a datasource is : <pre>PLScenes:[options]</pre><p>
-
-Additionnal optional parameters can be specified after the ':' sign.
-Currently the following one is supported :<p>
-
-<ul>
-<li> <b>version</b>=v0/v1: To specify the API version to request. Defaults to v0.</li>
-<li> <b>api_key</b>=value: To specify the Planet API KEY. It is mandatory, unless
-it is supplied through the open option API_KEY, or the configuration option PL_API_KEY.</li>
-<li><b>follow_links</b>=YES/NO: Whether assets links should be followed for each scene (API v1 only, vector).
-Getting assets links require a HTTP request per scene, which might be costly when
-enumerating through a lot of products. Defaults to NO.</li>
-<li> <b>scene</b>=scene_id: To specify the scene ID, when accessing raster data.
-Optional for vector layer access.</li>
-<li> <b>catalog</b>=name: To specify the catalog name.
-Optional for vector layer access. Mandatory for raster access with v1 API.</li>
-<li> <b>product_type</b>=value: To specify the product type: 'visual', 'analytic' or 'thumb'
-(for raster fetching). Default is "visual". Optional for vector layer access. For V1 API,
-if the option is not specified and the 'visual' asset category does not exist for the scene
-(or if the value is set to 'list'), the returned dataset will have subdatasets
-for the available asset categories.</li>
-<li> <b>filter</b>=string (API v1 only): To specify an additional filter on the request URL (/items endpoint)
-that will be only evaluated on server-side. Can be convenient for conditions that are not
-easily expressed in OGR SQL. For example, to restrict to scenes whose visual asset
-can be downloaded, use '_permissions=assets.visual:download'. It can also be a more
-complex query expressed as a JSon filter to be evaluated by the Quick Search API(/quick-search endpoint)</li>
-</ul>
-
-If several parameters are specified, they must be separated by a comma.<p>
-
-<h2>Open options</h2>
-
-The following open options are available :
-<ul>
-<li><b>VERSION</b>=v0/v1: To specify the API version to request. Defaults to v0.</li>
-<li><b>API_KEY</b>=value: To specify the Planet API KEY.</li>
-<li><b>FOLLOW_LINKS</b>=YES/NO: Whether assets links should be followed for each scene (API v1 only, vector).
-Getting assets links require a HTTP request per scene, which might be costly when
-enumerating through a lot of products. Defaults to NO.</li>
-<li><b>SCENE</b>=scene_id: To specify the scene ID, when accessing raster data.
-Optional for vector layer access.</li>
-<li><b>PRODUCT_TYPE</b>=value: To specify the product type: 'visual', 'analytic' or 'thumb'
-(for raster fetching). Default is "visual". Optional for vector layer access. For V1 API,
-if the option is not specified and the 'visual' asset category does not exist for the scene
-(or if the value is set to 'list'), the returned dataset will have subdatasets
-for the available asset categories.</li>
-<li> <b>CATALOG</b>=name: To specify the catalog name.
-Optional for vector layer access. Mandatory for raster access with v1 API.</li>
-<li><b>RANDOM_ACCESS</b>=YES/NO: Whether raster should be accessed in random access mode
-(but with potentially not optimal throughput). If NO, in-memory ingestion is done.
-Default is YES.</li>
-<li><b>ACTIVATION_TIMEOUT</b>=int: Number of seconds during which to wait for
-asset activation (API v1 only, raster). Default is 3600.</li>
-<li> <b>FILTER</b>=string (API v1 only): To specify an additional filter on the request URL (/items endpoint)
-that will be only evaluated on server-side. Can be convenient for conditions that are not
-easily expressed in OGR SQL. For example, to restrict to scenes whose visual asset
-can be downloaded, use '_permissions=assets.visual:download'. It can also be a more
-complex query expressed as a JSon filter to be evaluated by the Quick Search API(/quick-search endpoint)</li>
-</ul>
-
-<h2>Configuration options</h2>
-
-The following configuration options are available :
-<ul>
-<li><b>PL_API_KEY</b>=value: To specify the Planet API KEY.</li>
-</ul>
-
-<h2>Attributes</h2>
-
-<h3>v0 API</h3>
-
-The <a href="https://www.planet.com/docs/v0/scenes/#metadata">scene metadata</a>
-are retrieved into the following feature fields for the "ortho" layer :<p>
-
-<table border="1">
-<tr><th>Name</th><th>Type</th><th>Description</th></tr>
-
-<tr><td>id</td><td>String</td><td>Scene unique identifier.</td></tr>
-<tr><td>acquired</td><td>DateTime</td><td>The time that image was taken in UTC.</td></tr>
-<tr><td>camera.bit_depth</td><td>Integer</td><td>Bit depth with which the image was taken onboard the satellite. Currently 8 or 12.</td></tr>
-<tr><td>camera.color_mode</td><td>String</td><td>The color mode of the image as taken by the satellite. Currently "RGB" or "Monochromatic".</td></tr>
-<tr><td>camera.exposure_time</td><td>Integer</td><td>The exposure time in microseconds.</td></tr>
-<tr><td>camera.gain</td><td>Integer</td><td>The analog gain with which the image was taken.</td></tr>
-<tr><td>camera.tdi_pulses</td><td>Integer</td><td>The number of pulses used for time delay and integration on the CCD. Currently 0 (if TDI was not used), 4, 6, or 12.</td></tr>
-<tr><td>cloud_cover.estimated</td><td>Real</td><td>The estimated percentage of the image covered by clouds. Decimal 0-100.</td></tr>
-<tr><td>data.products.analytic.full</td><td>String</td><td>URL to download scene GeoTIFF of the "analytic" product.</td></tr>
-<tr><td>data.products.visual.full</td><td>String</td><td>URL to download scene GeoTIFF of the "visual" product.</td></tr>
-<tr><td>file_size</td><td>Integer</td><td>The size of the full image in bytes.</td></tr>
-<tr><td>image_statistics.gsd</td><td>Real</td><td>The ground sample distance (distance between pixel centers measured on the ground) of the image in meters.</td></tr>
-<tr><td>image_statistics.image_quality</td><td>String</td><td>Image quality category for scene. One of 'test', 'standard', or 'target'.</td></tr>
-<tr><td>image_statistics.snr</td><td>Real</td><td>The estimated signal to noise ratio. Decimal > 0. Values greater than or equal to 50 are considered excellent quality. Values less than 50 and greater than or equal to 20 are considered adequate quality. Values less than 20 are considered poor quality.</td></tr>
-<tr><td>links.full</td><td>String</td><td>URL to download scene GeoTIFF (same content as data.products.visual.full currently)</td></tr>
-<tr><td>links.self</td><td>String</td><td>URL to scene information</td></tr>
-<tr><td>links.square_thumbnail</td><td>String</td><td>URL to image thumbnail</td></tr>
-<tr><td>links.thumbnail</td><td>String</td><td>Link to image square thumbnail</td></tr>
-<tr><td>sat.alt</td><td>Real</td><td>The altitude of the satellite when the image was taken in kilometers.</td></tr>
-<tr><td>sat.id</td><td>String</td><td>A unique identifier for the satellite that captured this image.</td></tr>
-<tr><td>sat.lat</td><td>Real</td><td>The latitude of the satellite when the image was taken in degrees.</td></tr>
-<tr><td>sat.lng</td><td>Real</td><td>The longitude of the satellite when the image was taken in degrees.</td></tr>
-<tr><td>sat.off_nadir</td><td>Real</td><td>The angle off nadir in degrees at which the image was taken.</td></tr>
-<tr><td>strip_id</td><td>Real</td><td>A unique float identifier for the set of images taken sequentially be the same satellite.</td></tr>
-<tr><td>sun.altitude</td><td>Real</td><td>The altitude (angle above horizon) of the sun from the imaged location at the time of capture in degrees.</td></tr>
-<tr><td>sun.azimuth</td><td>Real</td><td>The azimuth (angle clockwise from north) of the sun from the imaged location at the time of capture in degrees.</td></tr>
-<tr><td>sun.local_time_of_day</td><td>Real</td><td>The local sun time at the imaged location at the time of capture (0-24).</td></tr>
-</table>
-
-For other layers / scene types, additional attributes may be retrieved.<p>
-
-<h3>v1 API</h3>
-
-<p>For the v1 API, the layer field definition is built dynamically from the catalog
-specification. The links to downloadable products are
-in <i>asset_XXXXX_product_link</i> attributes where XXXXX is the asset category id,
-when they are active. Otherwise they should be activated by sending a POST request to
-the URL in the <i>asset_XXXXX_activate_link</i> attribute (what the raster driver
-does automatically)</p>
-
-<p>The details about the layer field description are given in the FIELDS_DESCRIPTION
-metadata item as a JSon serialized object. The keys are the OGR field names, and
-the value is an object that contains the definition of each field, with the following
-attributes :
+Please consult the dedicated pages for each version of the API:
 <ul>
-<li><i>description</i>: string with human readable description of the filed</li>
-<li><i>type</i>: e.g: string, number or integer</li>
-<li><i>format</i> (optional): e.g. date-time, float, int32, ...</li>
-<li><i>server_queryable</i>: true if filters on the property are forwarded to the server.
-Otherwise the filter is evaluated on client side.</li>
-<li><i>src_field</i>: path to the property from the root of the JSon Feature object.</li>
+<li><a href="drv_plscenes_v0.html">V0 API</a> (deprecated)</li>
+<li><a href="drv_plscenes_v1.html">V1 API</a> (deprecated)</li>
+<li><a href="drv_plscenes_data_v1.html">Data V1 API</a> (current)</li>
 </ul>
-For example:</p>
-<pre>
-{
-  "id":{
-    "description":"Identifier of this Item.",
-    "type":"string",
-    "src_field":"id",
-    "server_queryable":true
-  },
-  "self_link":{
-    "description":"RFC 3986 URI representing the canonical location of this object.",
-    "type":"string",
-    "src_field":"_links._self",
-    "server_queryable":false
-  },
-  "assets_link":{
-    "description":"RFC 3986 URI representing the canonical location of the Assets subcollection.",
-    "type":"string",
-    "src_field":"_links.assets",
-    "server_queryable":false
-  },
-  "published":{
-    "description":"The RFC 3339 timestamp at which this Item was added to the Catalog.",
-    "format":"date-time",
-    "type":"string",
-    "src_field":"properties.published",
-    "server_queryable":true
-  },
-  "acquired":{
-    "description":"The RFC 3339 acquisition time of underlying image.",
-    "format":"date-time",
-    "type":"string",
-    "src_field":"properties.catalog::acquired",
-    "server_queryable":true
-  },
-  "black_fill":{
-    "description":"Ratio of image containing artificial black fill due to clipping to actual data.",
-    "format":"float",
-    "maximum":1.000000,
-    "minimum":0.000000,
-    "type":"number",
-    "src_field":"properties.catalog::black_fill",
-    "server_queryable":true
-  },
-  "cloud_cover":{
-    "description":"Ratio of the image covered by clouds to that which is uncovered.",
-    "format":"float",
-    "maximum":1.000000,
-    "minimum":0.000000,
-    "type":"number",
-    "src_field":"properties.catalog::cloud_cover",
-    "server_queryable":true
-  },
-  "grid_cell":{
-    "description":"The grid cell identifier of the gridded Item.",
-    "type":"string",
-    "src_field":"properties.catalog::grid_cell",
-    "server_queryable":true
-  },
-  "provider":{
-    "description":"Name of the imagery provider.",
-    "enum":[
-      "planetscope",
-      "rapideye",
-      "landsat",
-      "sentinel"
-    ],
-    "type":"string",
-    "src_field":"properties.catalog::provider",
-    "server_queryable":true
-  },
-  "resolution":{
-    "description":"Pixel resolution of the Item image(s) in meters.",
-    "format":"float",
-    "minimum":0.000000,
-    "type":"number",
-    "src_field":"properties.catalog::resolution",
-    "server_queryable":true
-  },
-  "satellite_id":{
-    "description":"Globally unique identifier of the satellite that acquired the underlying image.",
-    "type":"string",
-    "src_field":"properties.catalog::satellite_id",
-    "server_queryable":true
-  },
-  "strip_id":{
-    "description":"Identifier of the Item's parent strip.",
-    "type":"string",
-    "src_field":"properties.catalog::strip_id",
-    "server_queryable":true
-  },
-  "sun_azimuth":{
-    "description":"Angle from the True North to the Sun Vector projected on the horizontal plane in degrees.",
-    "format":"float",
-    "maximum":360.000000,
-    "minimum":0.000000,
-    "type":"number",
-    "src_field":"properties.catalog::sun_azimuth",
-    "server_queryable":true
-  },
-  "sun_elevation":{
-    "description":"Elevation angle of the sun in degrees.",
-    "format":"float",
-    "maximum":90.000000,
-    "minimum":0.000000,
-    "type":"number",
-    "src_field":"properties.catalog::sun_elevation",
-    "server_queryable":true
-  },
-  "usable_data":{
-    "description":"Ratio of the usable to unusable portion of the image due to cloud cover or black fill.",
-    "format":"float",
-    "maximum":1.000000,
-    "minimum":0.000000,
-    "type":"number",
-    "src_field":"properties.catalog::usable_data",
-    "server_queryable":true
-  },
-  "view_angle":{
-    "description":"Spacecraft across-track off-nadir viewing angle used for imaging, in degrees with \"+\" being East and \"-\" being West.",
-    "format":"float",
-    "maximum":25.000000,
-    "minimum":-25.000000,
-    "type":"number",
-    "src_field":"properties.catalog::view_angle",
-    "server_queryable":true
-  },
-  "asset_visual_self_link":{
-    "description":"RFC 3986 URI representing the canonical location of this asset.",
-    "type":"string",
-    "src_field":"\/assets.visual._links._self",
-    "server_queryable":false
-  },
-  "asset_visual_permissions":{
-    "items":{
-      "enum":[
-        "download"
-      ],
-      "type":"string"
-    },
-    "type":"array",
-    "uniqueItems":true,
-    "src_field":"\/assets.visual._permissions",
-    "server_queryable":false
-  },
-  "asset_visual_activate_link":{
-    "description":"If present, RFC 3986 URI indicating where an authenticated user may trigger activation of this AssetFile via a POST request. A 202 response indicates the activation request has been accepted. A 204 response indicates the AssetFile is already active. After successful activation, this AssetFile will have a non-empty location.",
-    "type":"string",
-    "src_field":"\/assets.visual.files._links.activate",
-    "server_queryable":false
-  },
-  "asset_visual_expires_at":{
-    "description":"If present, RFC 3339 timestamp indicating when this AssetFile will become inactive and will require reactivation.",
-    "format":"date-time",
-    "type":"string",
-    "src_field":"\/assets.visual.files.expires_at",
-    "server_queryable":false
-  },
-  "asset_visual_product_link":{
-    "description":"If present, RFC 3986 URI that indicates a location that will yield image data. Consult the documentation of the AssetFile type to understand how to use this URI.",
-    "type":"string",
-    "src_field":"\/assets.visual.files.location",
-    "server_queryable":false
-  },
-  "asset_visual_product_link_status":{
-    "description":"Current status of the AssetFile. \"inactive\" indicates that the AssetFile is not currently available for download, but may be after activation. \"activating\" indicates the AssetFile is currently undergoing activation, and may be available for download shortly. \"active\" indicates the AssetFile has been activated, and may currently be available for download if the authentication context permits.",
-    "enum":[
-      "inactive",
-      "activating",
-      "active"
-    ],
-    "type":"string",
-    "src_field":"\/assets.visual.files.status",
-    "server_queryable":false
-  },
-  "asset_visual_mimetype":{
-    "description":"The MIME type of the underlying asset file.",
-    "type":"string",
-    "src_field":"\/assets.visual.mimetype",
-    "server_queryable":false
-  },
-  "asset_analytic_self_link":{
-    "description":"RFC 3986 URI representing the canonical location of this asset.",
-    "type":"string",
-    "src_field":"\/assets.analytic._links._self",
-    "server_queryable":false
-  },
-  "asset_analytic_permissions":{
-    "items":{
-      "enum":[
-        "download"
-      ],
-      "type":"string"
-    },
-    "type":"array",
-    "uniqueItems":true,
-    "src_field":"\/assets.analytic._permissions",
-    "server_queryable":false
-  },
-  "asset_analytic_activate_link":{
-    "description":"If present, RFC 3986 URI indicating where an authenticated user may trigger activation of this AssetFile via a POST request. A 202 response indicates the activation request has been accepted. A 204 response indicates the AssetFile is already active. After successful activation, this AssetFile will have a non-empty location.",
-    "type":"string",
-    "src_field":"\/assets.analytic.files._links.activate",
-    "server_queryable":false
-  },
-  "asset_analytic_expires_at":{
-    "description":"If present, RFC 3339 timestamp indicating when this AssetFile will become inactive and will require reactivation.",
-    "format":"date-time",
-    "type":"string",
-    "src_field":"\/assets.analytic.files.expires_at",
-    "server_queryable":false
-  },
-  "asset_analytic_product_link":{
-    "description":"If present, RFC 3986 URI that indicates a location that will yield image data. Consult the documentation of the AssetFile type to understand how to use this URI.",
-    "type":"string",
-    "src_field":"\/assets.analytic.files.location",
-    "server_queryable":false
-  },
-  "asset_analytic_product_link_status":{
-    "description":"Current status of the AssetFile. \"inactive\" indicates that the AssetFile is not currently available for download, but may be after activation. \"activating\" indicates the AssetFile is currently undergoing activation, and may be available for download shortly. \"active\" indicates the AssetFile has been activated, and may currently be available for download if the authentication context permits.",
-    "enum":[
-      "inactive",
-      "activating",
-      "active"
-    ],
-    "type":"string",
-    "src_field":"\/assets.analytic.files.status",
-    "server_queryable":false
-  },
-  "asset_analytic_mimetype":{
-    "description":"The MIME type of the underlying asset file.",
-    "type":"string",
-    "src_field":"\/assets.analytic.mimetype",
-    "server_queryable":false
-  }
-}
-</pre>
-
-<h3>Geometry</h3>
-
-The footprint of each scene is reported as a MultiPolygon with a longitude/latitude
-WGS84 coordinate system (EPSG:4326).
-
-<h3>Filtering</h3>
-
-The driver will forward any spatial filter set with SetSpatialFilter() to
-the server. It also makes the same for simple attribute filters set with
-SetAttributeFilter(). Note that not all attributes support all comparison
-operators. Refer to comparator column in <a href="https://www.planet.com/docs/v0/scenes/#metadata">Metadata properties</a> <p>
-
-<h3>Paging</h3>
-
-Features are retrieved from the server by chunks of 1000 by default (and this
-is the maximum value accepted by the server).
-This number can be altered with the PLSCENES_PAGE_SIZE
-configuration option.<p>
-
-<h3>Vector layer (scene metadata) examples</h3>
-
-<li>
-Listing all scenes available (with the rights of the account) :
-<pre>
-ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value
-</pre>
-or
-<pre>
-ogrinfo -ro -al "PLScenes:api_key=some_value"
-</pre>
-or
-<pre>
-ogrinfo -ro -al "PLScenes:" --config PL_API_KEY some_value
-</pre>
-<p>
-
-<li>
-Listing all scenes available under a point of (lat,lon)=(40,-100) :
-<pre>
-ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -spat -100,40,-100,40
-</pre>
-<p>
-
-<li>
-Listing all scenes available within a bounding box (lat,lon)=(40,-100) to (lat,lon)=(39,-99)
-<pre>
-ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -spat -100,40,-99,39
-</pre>
-<p>
-
-<li>
-Listing all scenes available matching criteria :
-<pre>
-ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -where "acquired >= '2015/03/26 00:00:00' AND \"cloud_cover.estimated\" < 10"
-</pre>
-<p>
-
-<li>
-List all downloadable scenes (API v1):
-<pre>
-ogrinfo -ro -al -q "PLScenes:" -oo VERSION=v1 -oo API_KEY=some_value -oo FILTER='_permissions=assets:download'
-</pre>
-
-<li>
-List scenes matching a filter using Quick Search API (API v1):
-<pre>
-ogrinfo -ro -al -q "PLScenes:" -oo VERSION=v1 -oo API_KEY=some_value -oo FILTER='{
-  "filter": {
-    "type": "OrFilter",
-    "config": [
-      {
-        "field_name": "published",
-        "config": {
-          "gte": "2015-10-01T00:00:00Z"
-        },
-        "type": "DateRangeFilter"
-      }
-    ]
-  }
-}'
-</pre>
-<p>
-
-
-<h2>Raster access</h2>
-
-<p>Scenes and their thumbnails can be accessed as raster datasets, provided
-that the scene ID is specified with the 'scene' parameter / SCENE open option.
-The product type (visual, analytic or thumb) can be specified with the
-'product_type' parameter / PRODUCT_TYPE open option. The scene id is the
-content of the value of the 'id' field of the features of the 'ortho' vector layer.</p>
-
-<p>This functionality is a convenience wrapper of the
-<a href="https://www.planet.com/docs/v0/scenes/#get-scene-full">API for fetching the scene GeoTIFF</a>
-</p>
-
-<p>For API v1, the CATALOG open option must be specified. If the product is not
-already generated on the server, it will be activated, and the driver will wait
-for it to be available. The length of this retry can be configured with the
-ACTIVATION_TIMEOUT open option.</p>
-
-<h3>Raster access examples</h3>
-
-<li>
-Displaying raster metadata :
-
-<pre>
-gdalinfo "PLScenes:scene=scene_id,product_type=analytic" -oo API_KEY=some_value
-</pre>
-or
-<pre>
-gdalinfo "PLScenes:" -oo API_KEY=some_value -oo SCENE=scene_id -oo PRODUCT_TYPE=analytic
-</pre>
-or with V1 API:
-<pre>
-gdalinfo "PLScenes:" -oo API_KEY=some_value -oo VERSION=v1 -oo CATALOG=catalog_name -oo SCENE=scene_id -oo PRODUCT_TYPE=analytic
-</pre>
-
-<li>
-Converting/downloading a whole file:
-
-<pre>
-gdal_translate "PLScenes:" -oo API_KEY=some_value -oo SCENE=scene_id \
-                -oo PRODUCT_TYPE=analytic -oo RANDOM_ACCESS=NO out.tif
-</pre>
 
 <h2>See Also</h2>
 
 <ul>
-<li> <a href="https://www.planet.com/docs/v0/scenes/">Documentation of Planet Scenes API v0</a><p>
-<li> <a href="https://www.planet.com/docs/v0/general-concepts/#authentication">API Authentication in API v0</a><p>
-<li> <a href="https://www.planet.com/docs/v1/">Documentation of Planet Scenes API v1</a><p>
+<li> <a href="https://www.planet.com/docs/reference/v0/">Documentation of Planet Scenes API V0</a><p>
+<li> <a href="https://www.planet.com/docs/reference/data-api/">Documentation of Planet Scenes Data API V1</a><p>
 <li> <a href="frmt_plmosaic.html">Raster PLMosaic / Planet Mosaics API driver</a><p>
 </ul>
 
diff --git a/ogr/ogrsf_frmts/plscenes/drv_plscenes_data_v1.html b/ogr/ogrsf_frmts/plscenes/drv_plscenes_data_v1.html
new file mode 100644
index 0000000..34a687e
--- /dev/null
+++ b/ogr/ogrsf_frmts/plscenes/drv_plscenes_data_v1.html
@@ -0,0 +1,199 @@
+<html>
+<head>
+<title>PLScenes (Planet Labs Scenes), Data V1 API</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>PLScenes (Planet Labs Scenes), Data V1 API</h1>
+
+GDAL/OGR >= 2.2<p>
+
+The driver supports read-only operations to list scenes and their metadata
+as a vector layer per item-types:
+"PSOrthoTile", "REOrthoTile", "PSScene3Band", "PSScene4Band", "REScene", "Landsat8L1G", "Sentinel2L1C".
+It can also access raster scenes.<p>
+
+<h2>Dataset name syntax</h2>
+
+The minimal syntax to open a datasource is : <pre>PLScenes:[options]</pre><p>
+
+Additional optional parameters can be specified after the ':' sign.
+Currently the following one is supported :<p>
+
+<ul>
+<li> <b>version</b>=data_v1: To specify the API version to request.</li>
+<li> <b>api_key</b>=value: To specify the Planet API KEY. It is mandatory, unless
+it is supplied through the open option API_KEY, or the configuration option PL_API_KEY.</li>
+<li><b>follow_links</b>=YES/NO: Whether assets links should be followed for each scene (vector).
+Getting assets links require a HTTP request per scene, which might be costly when
+enumerating through a lot of products. Defaults to NO.</li>
+<li> <b>scene</b>=scene_id: To specify the scene ID, when accessing raster data.
+Optional for vector layer access.</li>
+<li> <b>itemtypes</b>=name: To specify the item types name.
+Optional for vector layer access. Mandatory for raster accessI.</li>
+<li> <b>asset</b>=value: To specify the asset type
+(for raster fetching). Default is "visual". Optional for vector layer access.
+If the option is not specified and the 'visual' asset category does not exist for the scene
+(or if the value is set to 'list'), the returned dataset will have subdatasets
+for the available asset categories.</li>
+<li> <b>medata</b>=YES/NO: (Raster only) Whether scene metadata should be
+fetch from the API and attached to the raster dataset. Defaults to YES.</li>
+</ul>
+
+If several parameters are specified, they must be separated by a comma.<p>
+
+<h2>Open options</h2>
+
+The following open options are available :
+<ul>
+<li><b>VERSION</b>=data_v1: To specify the API version to request.</li>
+<li><b>API_KEY</b>=value: To specify the Planet API KEY.</li>
+<li><b>FOLLOW_LINKS</b>=YES/NO: Whether assets links should be followed for each scene (vector).
+Getting assets links require a HTTP request per scene, which might be costly when
+enumerating through a lot of products. Defaults to NO.</li>
+<li><b>SCENE</b>=scene_id: To specify the scene ID, when accessing raster data.
+Optional for vector layer access.</li>
+<li> <b>ITEMTYPES</b>=name: To specify the item types name.
+Optional for vector layer access. Mandatory for raster access.</li>
+<li> <b>ASSET</b>=value: To specify the asset type
+(for raster fetching). Default is "visual". Optional for vector layer access.
+If the option is not specified and the 'visual' asset category does not exist for the scene
+(or if the value is set to 'list'), the returned dataset will have subdatasets
+for the available asset categories.</li>
+<li><b>RANDOM_ACCESS</b>=YES/NO: Whether raster should be accessed in random access mode
+(but with potentially not optimal throughput). If NO, in-memory ingestion is done.
+Default is YES.</li>
+<li><b>ACTIVATION_TIMEOUT</b>=int: Number of seconds during which to wait for
+asset activation (raster). Default is 3600.</li>
+<li> <b>METADATA</b>=YES/NO: (Raster only) Whether scene metadata should be
+fetched from the API and attached to the raster dataset. Defaults to YES.</li>
+</ul>
+
+<h2>Configuration options</h2>
+
+The following configuration options are available :
+<ul>
+<li><b>PL_API_KEY</b>=value: To specify the Planet API KEY.</li>
+</ul>
+
+<h2>Attributes</h2>
+
+<p>The layer field definition is built from the "plscensconf.json"
+file in the GDAL configuration. The links to downloadable products are
+in <i>asset_XXXXX_location</i> attributes where XXXXX is the asset category id,
+when they are active. Otherwise they should be activated by sending a POST request to
+the URL in the <i>asset_XXXXX_activate_link</i> attribute (what the raster driver
+does automatically)</p>
+
+<h3>Geometry</h3>
+
+The footprint of each scene is reported as a MultiPolygon with a longitude/latitude
+WGS84 coordinate system (EPSG:4326).
+
+<h3>Filtering</h3>
+
+The driver will forward any spatial filter set with SetSpatialFilter() to
+the server. It also makes the same for simple attribute filters set with
+SetAttributeFilter(). Note that not all attributes support all comparison
+operators. Refer to comparator column in <a href="https://www.planet.com/docs/v0/scenes/#metadata">Metadata properties</a> <p>
+
+<h3>Paging</h3>
+
+Features are retrieved from the server by chunks of 250 by default (and this
+is the maximum value accepted by the server).
+This number can be altered with the PLSCENES_PAGE_SIZE
+configuration option.<p>
+
+<h3>Vector layer (scene metadata) examples</h3>
+
+<li>
+Listing all scenes available (with the rights of the account) :
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value
+</pre>
+or
+<pre>
+ogrinfo -ro -al "PLScenes:api_key=some_value"
+</pre>
+or
+<pre>
+ogrinfo -ro -al "PLScenes:" --config PL_API_KEY some_value
+</pre>
+<p>
+
+<li>
+Listing all scenes available on PSOrthoTile item types, under a point of (lat,lon)=(40,-100) :
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value PSOrthoTile -spat -100 40 -100 40
+</pre>
+<p>
+
+<li>
+Listing all scenes available within a bounding box (lat,lon)=(40,-100) to (lat,lon)=(39,-99)
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -spat -100 40 -99 39
+</pre>
+<p>
+
+<li>
+Listing all scenes available matching criteria :
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value PSOrthoTile -where "acquired >= '2015/03/26 00:00:00' AND cloud_cover < 10"
+</pre>
+<p>
+
+<li>
+List all downloadable scenes:
+<pre>
+ogrinfo -ro -al -q "PLScenes:" -oo API_KEY=some_value PSOrthoTile -where="permissions='assets:download'"
+</pre>
+
+<p>
+
+
+<h2>Raster access</h2>
+
+<p>Scenes can be accessed as raster datasets, provided
+that the scene ID is specified with the 'scene' parameter / SCENE open option.
+The 'itemtypes' parameter / ITEMTYPES open option must also be specified. 
+The asset type (visual, analytic, ...) can be specified with the
+'asset' parameter / ASSET open option. The scene id is the
+content of the value of the 'id' field of the features.</p>
+
+<p>If the product is not
+already generated on the server, it will be activated, and the driver will wait
+for it to be available. The length of this retry can be configured with the
+ACTIVATION_TIMEOUT open option.</p>
+
+<h3>Raster access examples</h3>
+
+<li>
+Displaying raster metadata :
+
+<pre>
+gdalinfo "PLScenes:scene=scene_id,itemtypes=itemypes,asset=analytic" -oo API_KEY=some_value
+</pre>
+or
+<pre>
+gdalinfo "PLScenes:" -oo API_KEY=some_value -oo ITEMTYPES=itemtypes -oo SCENE=scene_id -oo ASSET=analytic
+</pre>
+
+<li>
+Converting/downloading a whole file:
+
+<pre>
+gdal_translate "PLScenes:" -oo API_KEY=some_value -oo SCENE=scene_id \
+                -oo ITEMTYPES=itemtypes -oo ASSET=analytic -oo RANDOM_ACCESS=NO out.tif
+</pre>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="drv_plscenes.html">General documentation page for PLScenes driver</a><p>
+<li> <a href="https://www.planet.com/docs/reference/data-api/">Documentation of Planet Scenes Data API v1</a><p>
+<li> <a href="frmt_plmosaic.html">Raster PLMosaic / Planet Mosaics API driver</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/plscenes/drv_plscenes_v0.html b/ogr/ogrsf_frmts/plscenes/drv_plscenes_v0.html
new file mode 100644
index 0000000..2e9b9dd
--- /dev/null
+++ b/ogr/ogrsf_frmts/plscenes/drv_plscenes_v0.html
@@ -0,0 +1,202 @@
+<html>
+<head>
+<title>PLScenes (Planet Labs Scenes/Catalog API), V0 API</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>PLScenes (Planet Labs Scenes/Catalog API), V0 API</h1>
+
+GDAL/OGR >= 2.0<p>
+
+Note: this version of the API is deprecated. Please migrate to the
+<a href="drv_plscenes_data_v1.html">Data V1 API</a>.<p>
+
+The driver supports read-only operations to list scenes and their metadata
+as a vector layer per scene type, "ortho" for example.
+It can also access raster scenes.<p>
+
+<h2>Dataset name syntax</h2>
+
+The minimal syntax to open a datasource is : <pre>PLScenes:[options]</pre><p>
+
+Additional optional parameters can be specified after the ':' sign.
+Currently the following one is supported :<p>
+
+<ul>
+<li> <b>version</b>=v0: To specify the API version to request. Defaults to data_v1 starting with GDAL 2.2 (v0 for older versions).</li>
+<li> <b>api_key</b>=value: To specify the Planet API KEY. It is mandatory, unless
+it is supplied through the open option API_KEY, or the configuration option PL_API_KEY.</li>
+<li> <b>scene</b>=scene_id: To specify the scene ID, when accessing raster data.
+Optional for vector layer access.</li>
+<li> <b>catalog</b>=name: To specify the item types name.
+Optional for vector layer access.</li>
+<li> <b>product_type</b>=value: To specify the asset type
+(for raster fetching). Default is "visual". Optional for vector layer access.</li>
+</ul>
+
+If several parameters are specified, they must be separated by a comma.<p>
+
+<h2>Open options</h2>
+
+The following open options are available :
+<ul>
+<li><b>VERSION</b>=v0: To specify the API version to request. Defaults to data_v1 starting with GDAL 2.2 (v0 for older versions).</li>
+<li><b>API_KEY</b>=value: To specify the Planet API KEY.</li>
+<li><b>SCENE</b>=scene_id: To specify the scene ID, when accessing raster data.
+Optional for vector layer access.</li>
+<li><b>CATALOG</b>=name: To specify the item types name.
+Optional for vector layer access.</li>
+<li><b>PRODUCT_TYPE</b>=value: To specify the asset type
+(for raster fetching). Default is "visual". Optional for vector layer access.</li>
+<li><b>RANDOM_ACCESS</b>=YES/NO: Whether raster should be accessed in random access mode
+(but with potentially not optimal throughput). If NO, in-memory ingestion is done.
+Default is YES.</li>
+</ul>
+
+<h2>Configuration options</h2>
+
+The following configuration options are available :
+<ul>
+<li><b>PL_API_KEY</b>=value: To specify the Planet API KEY.</li>
+</ul>
+
+<h2>Attributes</h2>
+
+The <a href="https://www.planet.com/docs/v0/scenes/#metadata">scene metadata</a>
+are retrieved into the following feature fields for the "ortho" layer :<p>
+
+<table border="1">
+<tr><th>Name</th><th>Type</th><th>Description</th></tr>
+
+<tr><td>id</td><td>String</td><td>Scene unique identifier.</td></tr>
+<tr><td>acquired</td><td>DateTime</td><td>The time that image was taken in UTC.</td></tr>
+<tr><td>camera.bit_depth</td><td>Integer</td><td>Bit depth with which the image was taken onboard the satellite. Currently 8 or 12.</td></tr>
+<tr><td>camera.color_mode</td><td>String</td><td>The color mode of the image as taken by the satellite. Currently "RGB" or "Monochromatic".</td></tr>
+<tr><td>camera.exposure_time</td><td>Integer</td><td>The exposure time in microseconds.</td></tr>
+<tr><td>camera.gain</td><td>Integer</td><td>The analog gain with which the image was taken.</td></tr>
+<tr><td>camera.tdi_pulses</td><td>Integer</td><td>The number of pulses used for time delay and integration on the CCD. Currently 0 (if TDI was not used), 4, 6, or 12.</td></tr>
+<tr><td>cloud_cover.estimated</td><td>Real</td><td>The estimated percentage of the image covered by clouds. Decimal 0-100.</td></tr>
+<tr><td>data.products.analytic.full</td><td>String</td><td>URL to download scene GeoTIFF of the "analytic" product.</td></tr>
+<tr><td>data.products.visual.full</td><td>String</td><td>URL to download scene GeoTIFF of the "visual" product.</td></tr>
+<tr><td>file_size</td><td>Integer</td><td>The size of the full image in bytes.</td></tr>
+<tr><td>image_statistics.gsd</td><td>Real</td><td>The ground sample distance (distance between pixel centers measured on the ground) of the image in meters.</td></tr>
+<tr><td>image_statistics.image_quality</td><td>String</td><td>Image quality category for scene. One of 'test', 'standard', or 'target'.</td></tr>
+<tr><td>image_statistics.snr</td><td>Real</td><td>The estimated signal to noise ratio. Decimal > 0. Values greater than or equal to 50 are considered excellent quality. Values less than 50 and greater than or equal to 20 are considered adequate quality. Values less than 20 are considered poor quality.</td></tr>
+<tr><td>links.full</td><td>String</td><td>URL to download scene GeoTIFF (same content as data.products.visual.full currently)</td></tr>
+<tr><td>links.self</td><td>String</td><td>URL to scene information</td></tr>
+<tr><td>links.square_thumbnail</td><td>String</td><td>URL to image thumbnail</td></tr>
+<tr><td>links.thumbnail</td><td>String</td><td>Link to image square thumbnail</td></tr>
+<tr><td>sat.alt</td><td>Real</td><td>The altitude of the satellite when the image was taken in kilometers.</td></tr>
+<tr><td>sat.id</td><td>String</td><td>A unique identifier for the satellite that captured this image.</td></tr>
+<tr><td>sat.lat</td><td>Real</td><td>The latitude of the satellite when the image was taken in degrees.</td></tr>
+<tr><td>sat.lng</td><td>Real</td><td>The longitude of the satellite when the image was taken in degrees.</td></tr>
+<tr><td>sat.off_nadir</td><td>Real</td><td>The angle off nadir in degrees at which the image was taken.</td></tr>
+<tr><td>strip_id</td><td>Real</td><td>A unique float identifier for the set of images taken sequentially be the same satellite.</td></tr>
+<tr><td>sun.altitude</td><td>Real</td><td>The altitude (angle above horizon) of the sun from the imaged location at the time of capture in degrees.</td></tr>
+<tr><td>sun.azimuth</td><td>Real</td><td>The azimuth (angle clockwise from north) of the sun from the imaged location at the time of capture in degrees.</td></tr>
+<tr><td>sun.local_time_of_day</td><td>Real</td><td>The local sun time at the imaged location at the time of capture (0-24).</td></tr>
+</table>
+
+For other layers / scene types, additional attributes may be retrieved.<p>
+
+<h3>Geometry</h3>
+
+The footprint of each scene is reported as a MultiPolygon with a longitude/latitude
+WGS84 coordinate system (EPSG:4326).
+
+<h3>Filtering</h3>
+
+The driver will forward any spatial filter set with SetSpatialFilter() to
+the server. It also makes the same for simple attribute filters set with
+SetAttributeFilter(). Note that not all attributes support all comparison
+operators. Refer to comparator column in <a href="https://www.planet.com/docs/v0/scenes/#metadata">Metadata properties</a> <p>
+
+<h3>Paging</h3>
+
+Features are retrieved from the server by chunks of 1000 by default (and this
+is the maximum value accepted by the server).
+This number can be altered with the PLSCENES_PAGE_SIZE
+configuration option.<p>
+
+<h3>Vector layer (scene metadata) examples</h3>
+
+<li>
+Listing all scenes available (with the rights of the account) :
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value
+</pre>
+or
+<pre>
+ogrinfo -ro -al "PLScenes:api_key=some_value"
+</pre>
+or
+<pre>
+ogrinfo -ro -al "PLScenes:" --config PL_API_KEY some_value
+</pre>
+<p>
+
+<li>
+Listing all scenes available under a point of (lat,lon)=(40,-100) :
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -spat -100,40,-100,40
+</pre>
+<p>
+
+<li>
+Listing all scenes available within a bounding box (lat,lon)=(40,-100) to (lat,lon)=(39,-99)
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -spat -100,40,-99,39
+</pre>
+<p>
+
+<li>
+Listing all scenes available matching criteria :
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo API_KEY=some_value -where "acquired >= '2015/03/26 00:00:00' AND \"cloud_cover.estimated\" < 10"
+</pre>
+<p>
+
+<h2>Raster access</h2>
+
+<p>Scenes and their thumbnails can be accessed as raster datasets, provided
+that the scene ID is specified with the 'scene' parameter / SCENE open option.
+The product type (visual, analytic or thumb) can be specified with the
+'product_type' parameter / PRODUCT_TYPE open option. The scene id is the
+content of the value of the 'id' field of the features of the 'ortho' vector layer.</p>
+
+<p>This functionality is a convenience wrapper of the
+<a href="https://www.planet.com/docs/reference/v0/scenes/#api-endpoints">API for fetching the scene GeoTIFF</a>
+</p>
+
+<h3>Raster access examples</h3>
+
+<li>
+Displaying raster metadata :
+
+<pre>
+gdalinfo "PLScenes:scene=scene_id,product_type=analytic" -oo API_KEY=some_value
+</pre>
+or
+<pre>
+gdalinfo "PLScenes:" -oo API_KEY=some_value -oo SCENE=scene_id -oo PRODUCT_TYPE=analytic
+</pre>
+
+<li>
+Converting/downloading a whole file:
+
+<pre>
+gdal_translate "PLScenes:" -oo API_KEY=some_value -oo SCENE=scene_id \
+                -oo PRODUCT_TYPE=analytic -oo RANDOM_ACCESS=NO out.tif
+</pre>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="drv_plscenes.html">General documentation page for PLScenes driver</a><p>
+<li> <a href="https://www.planet.com/docs/reference/v0/">Documentation of Planet Scenes API v0</a><p>
+<li> <a href="frmt_plmosaic.html">Raster PLMosaic / Planet Mosaics API driver</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/plscenes/drv_plscenes_v1.html b/ogr/ogrsf_frmts/plscenes/drv_plscenes_v1.html
new file mode 100644
index 0000000..0837d80
--- /dev/null
+++ b/ogr/ogrsf_frmts/plscenes/drv_plscenes_v1.html
@@ -0,0 +1,469 @@
+<html>
+<head>
+<title>PLScenes (Planet Labs Scenes/Catalog API), V1 API</title>
+</head>
+
+<body bgcolor="#ffffff">
+
+<h1>PLScenes (Planet Labs Scenes/Catalog API), V1 API</h1>
+
+GDAL/OGR >= 2.1 for v1 API<p>
+
+Note: this version of the API is deprecated. Please migrate to the
+<a href="drv_plscenes_data_v1.html">Data V1 API</a>.<p>
+
+The driver supports read-only operations to list scenes and their metadata
+as a vector layer per scene catalog.
+It can also access raster scenes.<p>
+
+<h2>Dataset name syntax</h2>
+
+The minimal syntax to open a datasource is : <pre>PLScenes:[options]</pre><p>
+
+Additional optional parameters can be specified after the ':' sign.
+Currently the following one is supported :<p>
+
+<ul>
+<li> <b>version</b>=v1: To specify the API version to request. Defaults to data_v1 starting with GDAL 2.2 (v0 for older versions).</li>
+<li> <b>api_key</b>=value: To specify the Planet API KEY. It is mandatory, unless
+it is supplied through the open option API_KEY, or the configuration option PL_API_KEY.</li>
+<li><b>follow_links</b>=YES/NO: Whether assets links should be followed for each scene (vector).
+Getting assets links require a HTTP request per scene, which might be costly when
+enumerating through a lot of products. Defaults to NO.</li>
+<li> <b>scene</b>=scene_id: To specify the scene ID, when accessing raster data.
+Optional for vector layer access.</li>
+<li> <b>catalog</b>=name: To specify the item types name.
+Optional for vector layer access. Mandatory for raster access.</li>
+<li> <b>product_type</b>=value: To specify the asset type
+(for raster fetching). Default is "visual". Optional for vector layer access.
+If the option is not specified and the 'visual' asset category does not exist for the scene
+(or if the value is set to 'list'), the returned dataset will have subdatasets
+for the available asset categories.</li>
+<li> <b>filter</b>=string: To specify an additional filter on the request URL (/items endpoint)
+that will be only evaluated on server-side. Can be convenient for conditions that are not
+easily expressed in OGR SQL. For example, to restrict to scenes whose visual asset
+can be downloaded, use '_permissions=assets.visual:download'. It can also be a more
+complex query expressed as a JSon filter to be evaluated by the Quick Search API(/quick-search endpoint)</li>
+</ul>
+
+If several parameters are specified, they must be separated by a comma.<p>
+
+<h2>Open options</h2>
+
+The following open options are available :
+<ul>
+<li><b>VERSION</b>=v1: To specify the API version to request. Defaults to data_v1 starting with GDAL 2.2 (v0 for older versions).</li>
+<li><b>API_KEY</b>=value: To specify the Planet API KEY.</li>
+<li><b>FOLLOW_LINKS</b>=YES/NO: Whether assets links should be followed for each scene (API v1 and data v1 only, vector).
+Getting assets links require a HTTP request per scene, which might be costly when
+enumerating through a lot of products. Defaults to NO.</li>
+<li><b>SCENE</b>=scene_id: To specify the scene ID, when accessing raster data.
+Optional for vector layer access.</li>
+<li> <b>CATALOG</b>=name: To specify the item types name.
+Optional for vector layer access. Mandatory for raster access with v1 API.</li>
+<li> <b>PRODUCT_TYPE</b>=value: To specify the asset type
+(for raster fetching). Default is "visual". Optional for vector layer access.
+If the option is not specified and the 'visual' asset category does not exist for the scene
+(or if the value is set to 'list'), the returned dataset will have subdatasets
+for the available asset categories.</li>
+<li><b>RANDOM_ACCESS</b>=YES/NO: Whether raster should be accessed in random access mode
+(but with potentially not optimal throughput). If NO, in-memory ingestion is done.
+Default is YES.</li>
+<li><b>ACTIVATION_TIMEOUT</b>=int: Number of seconds during which to wait for
+asset activation (raster). Default is 3600.</li>
+<li> <b>FILTER</b>=string: To specify an additional filter on the request URL (/items endpoint)
+that will be only evaluated on server-side. Can be convenient for conditions that are not
+easily expressed in OGR SQL. For example, to restrict to scenes whose visual asset
+can be downloaded, use '_permissions=assets.visual:download'. It can also be a more
+complex query expressed as a JSon filter to be evaluated by the Quick Search API(/quick-search endpoint)</li>
+</ul>
+
+<h2>Configuration options</h2>
+
+The following configuration options are available :
+<ul>
+<li><b>PL_API_KEY</b>=value: To specify the Planet API KEY.</li>
+</ul>
+
+<h2>Attributes</h2>
+
+<p>The layer field definition is built dynamically from the catalog
+specification. The links to downloadable products are
+in <i>asset_XXXXX_product_link</i> attributes where XXXXX is the asset category id,
+when they are active. Otherwise they should be activated by sending a POST request to
+the URL in the <i>asset_XXXXX_activate_link</i> attribute (what the raster driver
+does automatically)</p>
+
+<p>The details about the layer field description are given in the FIELDS_DESCRIPTION
+metadata item as a JSon serialized object. The keys are the OGR field names, and
+the value is an object that contains the definition of each field, with the following
+attributes :
+<ul>
+<li><i>description</i>: string with human readable description of the filed</li>
+<li><i>type</i>: e.g: string, number or integer</li>
+<li><i>format</i> (optional): e.g. date-time, float, int32, ...</li>
+<li><i>server_queryable</i>: true if filters on the property are forwarded to the server.
+Otherwise the filter is evaluated on client side.</li>
+<li><i>src_field</i>: path to the property from the root of the JSon Feature object.</li>
+</ul>
+For example:</p>
+<pre>
+{
+  "id":{
+    "description":"Identifier of this Item.",
+    "type":"string",
+    "src_field":"id",
+    "server_queryable":true
+  },
+  "self_link":{
+    "description":"RFC 3986 URI representing the canonical location of this object.",
+    "type":"string",
+    "src_field":"_links._self",
+    "server_queryable":false
+  },
+  "assets_link":{
+    "description":"RFC 3986 URI representing the canonical location of the Assets subcollection.",
+    "type":"string",
+    "src_field":"_links.assets",
+    "server_queryable":false
+  },
+  "published":{
+    "description":"The RFC 3339 timestamp at which this Item was added to the Catalog.",
+    "format":"date-time",
+    "type":"string",
+    "src_field":"properties.published",
+    "server_queryable":true
+  },
+  "acquired":{
+    "description":"The RFC 3339 acquisition time of underlying image.",
+    "format":"date-time",
+    "type":"string",
+    "src_field":"properties.catalog::acquired",
+    "server_queryable":true
+  },
+  "black_fill":{
+    "description":"Ratio of image containing artificial black fill due to clipping to actual data.",
+    "format":"float",
+    "maximum":1.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::black_fill",
+    "server_queryable":true
+  },
+  "cloud_cover":{
+    "description":"Ratio of the image covered by clouds to that which is uncovered.",
+    "format":"float",
+    "maximum":1.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::cloud_cover",
+    "server_queryable":true
+  },
+  "grid_cell":{
+    "description":"The grid cell identifier of the gridded Item.",
+    "type":"string",
+    "src_field":"properties.catalog::grid_cell",
+    "server_queryable":true
+  },
+  "provider":{
+    "description":"Name of the imagery provider.",
+    "enum":[
+      "planetscope",
+      "rapideye",
+      "landsat",
+      "sentinel"
+    ],
+    "type":"string",
+    "src_field":"properties.catalog::provider",
+    "server_queryable":true
+  },
+  "resolution":{
+    "description":"Pixel resolution of the Item image(s) in meters.",
+    "format":"float",
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::resolution",
+    "server_queryable":true
+  },
+  "satellite_id":{
+    "description":"Globally unique identifier of the satellite that acquired the underlying image.",
+    "type":"string",
+    "src_field":"properties.catalog::satellite_id",
+    "server_queryable":true
+  },
+  "strip_id":{
+    "description":"Identifier of the Item's parent strip.",
+    "type":"string",
+    "src_field":"properties.catalog::strip_id",
+    "server_queryable":true
+  },
+  "sun_azimuth":{
+    "description":"Angle from the True North to the Sun Vector projected on the horizontal plane in degrees.",
+    "format":"float",
+    "maximum":360.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::sun_azimuth",
+    "server_queryable":true
+  },
+  "sun_elevation":{
+    "description":"Elevation angle of the sun in degrees.",
+    "format":"float",
+    "maximum":90.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::sun_elevation",
+    "server_queryable":true
+  },
+  "usable_data":{
+    "description":"Ratio of the usable to unusable portion of the image due to cloud cover or black fill.",
+    "format":"float",
+    "maximum":1.000000,
+    "minimum":0.000000,
+    "type":"number",
+    "src_field":"properties.catalog::usable_data",
+    "server_queryable":true
+  },
+  "view_angle":{
+    "description":"Spacecraft across-track off-nadir viewing angle used for imaging, in degrees with \"+\" being East and \"-\" being West.",
+    "format":"float",
+    "maximum":25.000000,
+    "minimum":-25.000000,
+    "type":"number",
+    "src_field":"properties.catalog::view_angle",
+    "server_queryable":true
+  },
+  "asset_visual_self_link":{
+    "description":"RFC 3986 URI representing the canonical location of this asset.",
+    "type":"string",
+    "src_field":"\/assets.visual._links._self",
+    "server_queryable":false
+  },
+  "asset_visual_permissions":{
+    "items":{
+      "enum":[
+        "download"
+      ],
+      "type":"string"
+    },
+    "type":"array",
+    "uniqueItems":true,
+    "src_field":"\/assets.visual._permissions",
+    "server_queryable":false
+  },
+  "asset_visual_activate_link":{
+    "description":"If present, RFC 3986 URI indicating where an authenticated user may trigger activation of this AssetFile via a POST request. A 202 response indicates the activation request has been accepted. A 204 response indicates the AssetFile is already active. After successful activation, this AssetFile will have a non-empty location.",
+    "type":"string",
+    "src_field":"\/assets.visual.files._links.activate",
+    "server_queryable":false
+  },
+  "asset_visual_expires_at":{
+    "description":"If present, RFC 3339 timestamp indicating when this AssetFile will become inactive and will require reactivation.",
+    "format":"date-time",
+    "type":"string",
+    "src_field":"\/assets.visual.files.expires_at",
+    "server_queryable":false
+  },
+  "asset_visual_product_link":{
+    "description":"If present, RFC 3986 URI that indicates a location that will yield image data. Consult the documentation of the AssetFile type to understand how to use this URI.",
+    "type":"string",
+    "src_field":"\/assets.visual.files.location",
+    "server_queryable":false
+  },
+  "asset_visual_product_link_status":{
+    "description":"Current status of the AssetFile. \"inactive\" indicates that the AssetFile is not currently available for download, but may be after activation. \"activating\" indicates the AssetFile is currently undergoing activation, and may be available for download shortly. \"active\" indicates the AssetFile has been activated, and may currently be available for download if the authentication context permits.",
+    "enum":[
+      "inactive",
+      "activating",
+      "active"
+    ],
+    "type":"string",
+    "src_field":"\/assets.visual.files.status",
+    "server_queryable":false
+  },
+  "asset_visual_mimetype":{
+    "description":"The MIME type of the underlying asset file.",
+    "type":"string",
+    "src_field":"\/assets.visual.mimetype",
+    "server_queryable":false
+  },
+  "asset_analytic_self_link":{
+    "description":"RFC 3986 URI representing the canonical location of this asset.",
+    "type":"string",
+    "src_field":"\/assets.analytic._links._self",
+    "server_queryable":false
+  },
+  "asset_analytic_permissions":{
+    "items":{
+      "enum":[
+        "download"
+      ],
+      "type":"string"
+    },
+    "type":"array",
+    "uniqueItems":true,
+    "src_field":"\/assets.analytic._permissions",
+    "server_queryable":false
+  },
+  "asset_analytic_activate_link":{
+    "description":"If present, RFC 3986 URI indicating where an authenticated user may trigger activation of this AssetFile via a POST request. A 202 response indicates the activation request has been accepted. A 204 response indicates the AssetFile is already active. After successful activation, this AssetFile will have a non-empty location.",
+    "type":"string",
+    "src_field":"\/assets.analytic.files._links.activate",
+    "server_queryable":false
+  },
+  "asset_analytic_expires_at":{
+    "description":"If present, RFC 3339 timestamp indicating when this AssetFile will become inactive and will require reactivation.",
+    "format":"date-time",
+    "type":"string",
+    "src_field":"\/assets.analytic.files.expires_at",
+    "server_queryable":false
+  },
+  "asset_analytic_product_link":{
+    "description":"If present, RFC 3986 URI that indicates a location that will yield image data. Consult the documentation of the AssetFile type to understand how to use this URI.",
+    "type":"string",
+    "src_field":"\/assets.analytic.files.location",
+    "server_queryable":false
+  },
+  "asset_analytic_product_link_status":{
+    "description":"Current status of the AssetFile. \"inactive\" indicates that the AssetFile is not currently available for download, but may be after activation. \"activating\" indicates the AssetFile is currently undergoing activation, and may be available for download shortly. \"active\" indicates the AssetFile has been activated, and may currently be available for download if the authentication context permits.",
+    "enum":[
+      "inactive",
+      "activating",
+      "active"
+    ],
+    "type":"string",
+    "src_field":"\/assets.analytic.files.status",
+    "server_queryable":false
+  },
+  "asset_analytic_mimetype":{
+    "description":"The MIME type of the underlying asset file.",
+    "type":"string",
+    "src_field":"\/assets.analytic.mimetype",
+    "server_queryable":false
+  }
+}
+</pre>
+
+<h3>Geometry</h3>
+
+The footprint of each scene is reported as a MultiPolygon with a longitude/latitude
+WGS84 coordinate system (EPSG:4326).
+
+<h3>Filtering</h3>
+
+The driver will forward any spatial filter set with SetSpatialFilter() to
+the server. It also makes the same for simple attribute filters set with
+SetAttributeFilter(). Note that not all attributes support all comparison
+operators. Refer to comparator column in <a href="https://www.planet.com/docs/v0/scenes/#metadata">Metadata properties</a> <p>
+
+<h3>Paging</h3>
+
+Features are retrieved from the server by chunks of 250 by default (and this
+is the maximum value accepted by the server).
+This number can be altered with the PLSCENES_PAGE_SIZE
+configuration option.<p>
+
+<h3>Vector layer (scene metadata) examples</h3>
+
+<li>
+Listing all scenes available (with the rights of the account) :
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo VERSION=V1 -oo API_KEY=some_value
+</pre>
+or
+<pre>
+ogrinfo -ro -al "PLScenes:api_key=some_value"
+</pre>
+or
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo VERSION=V1 --config PL_API_KEY some_value
+</pre>
+<p>
+
+<li>
+Listing all scenes available under a point of (lat,lon)=(40,-100) :
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo VERSION=V1 -oo API_KEY=some_value -spat -100,40,-100,40
+</pre>
+<p>
+
+<li>
+Listing all scenes available within a bounding box (lat,lon)=(40,-100) to (lat,lon)=(39,-99)
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo VERSION=V1 -oo API_KEY=some_value -spat -100,40,-99,39
+</pre>
+<p>
+
+<li>
+Listing all scenes available matching criteria :
+<pre>
+ogrinfo -ro -al "PLScenes:" -oo VERSION=V1 -oo API_KEY=some_value -where "acquired >= '2015/03/26 00:00:00' AND \"cloud_cover.estimated\" < 10"
+</pre>
+<p>
+
+<li>
+List all downloadable scenes:
+<pre>
+ogrinfo -ro -al -q "PLScenes:" -oo VERSION=v1 -oo API_KEY=some_value -oo FILTER='_permissions=assets:download'
+</pre>
+
+<li>
+List scenes matching a filter using Quick Search API:
+<pre>
+ogrinfo -ro -al -q "PLScenes:" -oo VERSION=v1 -oo API_KEY=some_value -oo FILTER='{
+  "filter": {
+    "type": "OrFilter",
+    "config": [
+      {
+        "field_name": "published",
+        "config": {
+          "gte": "2015-10-01T00:00:00Z"
+        },
+        "type": "DateRangeFilter"
+      }
+    ]
+  }
+}'
+</pre>
+<p>
+
+
+<h2>Raster access</h2>
+
+<p>Scenes can be accessed as raster datasets, provided
+that the scene ID is specified with the 'scene' parameter / SCENE open option.
+The product type (visual, analytic, ...) can be specified with the
+'product_type' parameter / PRODUCT_TYPE open option. The scene id is the
+content of the value of the 'id' field of the features.</p>
+
+<p>The CATALOG open option must be specified. If the product is not
+already generated on the server, it will be activated, and the driver will wait
+for it to be available. The length of this retry can be configured with the
+ACTIVATION_TIMEOUT open option.</p>
+
+<h3>Raster access examples</h3>
+
+<li>
+Displaying raster metadata :
+
+<pre>
+gdalinfo "PLScenes:" -oo API_KEY=some_value -oo VERSION=v1 -oo CATALOG=catalog_name -oo SCENE=scene_id -oo PRODUCT_TYPE=analytic
+</pre>
+
+<li>
+Converting/downloading a whole file:
+
+<pre>
+gdal_translate "PLScenes:" -oo VERSION=v1 -oo API_KEY=some_value -oo SCENE=scene_id \
+                 -oo CATALOG=catalog_name -oo PRODUCT_TYPE=analytic -oo RANDOM_ACCESS=NO out.tif
+</pre>
+
+<h2>See Also</h2>
+
+<ul>
+<li> <a href="drv_plscenes.html">General documentation page for PLScenes driver</a><p>
+<li> <a href="frmt_plmosaic.html">Raster PLMosaic / Planet Mosaics API driver</a><p>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/plscenes/makefile.vc b/ogr/ogrsf_frmts/plscenes/makefile.vc
index 41a9cd4..03c40e0 100644
--- a/ogr/ogrsf_frmts/plscenes/makefile.vc
+++ b/ogr/ogrsf_frmts/plscenes/makefile.vc
@@ -1,5 +1,7 @@
 
-OBJ	=	ogrplscenesdriver.obj ogrplscenesdataset.obj ogrplscenesv1dataset.obj ogrplsceneslayer.obj ogrplscenesv1layer.obj
+OBJ	=	ogrplscenesdriver.obj ogrplscenesdataset.obj ogrplscenesv1dataset.obj ogrplsceneslayer.obj ogrplscenesv1layer.obj \
+		ogrplscenesdatav1layer.obj ogrplscenesdatav1dataset.obj
+
 EXTRAFLAGS =	-I.. -I..\..  -I..\geojson -I..\geojson\libjson
 
 GDAL_ROOT	=	..\..\..
diff --git a/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h b/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
index 1d7f475..4fabc7b 100644
--- a/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
+++ b/ogr/ogrsf_frmts/plscenes/ogr_plscenes.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_plscenes.h 33915 2016-04-07 19:38:55Z rouault $
+ * $Id: ogr_plscenes.h 37271 2017-02-02 13:34:26Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  PLScenes driver interface
@@ -34,7 +34,6 @@
 #include "ogrsf_frmts.h"
 #include "ogr_srs_api.h"
 #include "cpl_http.h"
-#include <json.h>
 #include "ogr_geojson.h"
 #include "ogrgeojsonreader.h"
 #include "swq.h"
@@ -43,9 +42,10 @@
 #include <vector>
 
 class OGRPLScenesLayer;
+
 class OGRPLScenesDataset: public GDALDataset
 {
-        int             bMustCleanPersistent;
+        bool            bMustCleanPersistent;
         CPLString       osBaseURL;
         CPLString       osAPIKey;
 
@@ -60,15 +60,15 @@ class OGRPLScenesDataset: public GDALDataset
 
     public:
                             OGRPLScenesDataset();
-                           ~OGRPLScenesDataset();
+                           virtual ~OGRPLScenesDataset();
 
-        virtual int         GetLayerCount() { return nLayers; }
-        virtual OGRLayer   *GetLayer(int idx);
-        virtual OGRLayer   *GetLayerByName(const char* pszName);
+        virtual int         GetLayerCount() override { return nLayers; }
+        virtual OGRLayer   *GetLayer(int idx) override;
+        virtual OGRLayer   *GetLayerByName(const char* pszName) override;
         virtual OGRLayer   *ExecuteSQL( const char *pszSQLCommand,
                                         OGRGeometry *poSpatialFilter,
-                                        const char *pszDialect );
-        virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                        const char *pszDialect ) override;
+        virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
         json_object        *RunRequest(const char* pszURL,
                                        int bQuiet404Error = FALSE);
@@ -84,7 +84,7 @@ class OGRPLScenesLayer: public OGRLayer
             CPLString       osBaseURL;
             OGRFeatureDefn* poFeatureDefn;
             OGRSpatialReference* poSRS;
-            int             bEOF;
+            bool            bEOF;
             GIntBig         nNextFID;
             GIntBig         nFeatureCount;
             CPLString       osNextURL;
@@ -97,10 +97,10 @@ class OGRPLScenesLayer: public OGRLayer
             OGRGeometry    *poMainFilter;
 
             int             nPageSize;
-            int             bStillInFirstPage;
+            bool            bStillInFirstPage;
             int             bAcquiredAscending;
 
-            int             bFilterMustBeClientSideEvaluated;
+            bool            bFilterMustBeClientSideEvaluated;
             CPLString       osFilterURLPart;
 
             OGRFeature     *GetNextRawFeature();
@@ -113,22 +113,22 @@ class OGRPLScenesLayer: public OGRLayer
                                              const char* pszName,
                                              const char* pszBaseURL,
                                              json_object* poObjCount10 = NULL);
-                           ~OGRPLScenesLayer();
+                           virtual ~OGRPLScenesLayer();
 
-        virtual void            ResetReading();
-        virtual GIntBig         GetFeatureCount(int bForce = FALSE);
-        virtual OGRFeature     *GetNextFeature();
-        virtual int             TestCapability(const char*);
-        virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
+        virtual void            ResetReading() override;
+        virtual GIntBig         GetFeatureCount(int bForce = FALSE) override;
+        virtual OGRFeature     *GetNextFeature() override;
+        virtual int             TestCapability(const char*) override;
+        virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
 
-        virtual void        SetSpatialFilter( OGRGeometry *poGeom );
-        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+        virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override;
+        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-        virtual OGRErr      SetAttributeFilter( const char * );
+        virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
-        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
+        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
         void                SetMainFilterRect(double dfMinX, double dfMinY,
@@ -164,11 +164,11 @@ class OGRPLScenesV1Dataset: public GDALDataset
 
     public:
                             OGRPLScenesV1Dataset();
-                           ~OGRPLScenesV1Dataset();
+                           virtual ~OGRPLScenesV1Dataset();
 
-        virtual int         GetLayerCount();
-        virtual OGRLayer   *GetLayer(int idx);
-        virtual OGRLayer   *GetLayerByName(const char* pszName);
+        virtual int         GetLayerCount() override;
+        virtual OGRLayer   *GetLayer(int idx) override;
+        virtual OGRLayer   *GetLayerByName(const char* pszName) override;
 
         json_object        *RunRequest(const char* pszURL,
                                        int bQuiet404Error = FALSE,
@@ -193,7 +193,7 @@ class OGRPLScenesV1FeatureDefn: public OGRFeatureDefn
                             OGRFeatureDefn(pszName), m_poLayer(poLayer) {}
        ~OGRPLScenesV1FeatureDefn() {}
 
-       virtual int GetFieldCount();
+       virtual int GetFieldCount() override;
 
        void DropRefToLayer() { m_poLayer = NULL; }
 };
@@ -266,27 +266,158 @@ class OGRPLScenesV1Layer: public OGRLayer
                                                const char* pszSpecURL,
                                                const char* pszItemsURL,
                                                GIntBig nCount);
-                           ~OGRPLScenesV1Layer();
+                           virtual ~OGRPLScenesV1Layer();
 
-        virtual void            ResetReading();
-        virtual OGRFeature     *GetNextFeature();
-        virtual int             TestCapability(const char*);
-        virtual OGRFeatureDefn *GetLayerDefn();
-        virtual GIntBig         GetFeatureCount(int bForce = FALSE);
+        virtual void            ResetReading() override;
+        virtual OGRFeature     *GetNextFeature() override;
+        virtual int             TestCapability(const char*) override;
+        virtual OGRFeatureDefn *GetLayerDefn() override;
+        virtual GIntBig         GetFeatureCount(int bForce = FALSE) override;
 
-        virtual char      **GetMetadata( const char * pszDomain = "" );
-        virtual const char *GetMetadataItem( const char * pszName, const char* pszDomain = "" );
+        virtual char      **GetMetadata( const char * pszDomain = "" ) override;
+        virtual const char *GetMetadataItem( const char * pszName, const char* pszDomain = "" ) override;
 
-        virtual void        SetSpatialFilter( OGRGeometry *poGeom );
-        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+        virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override;
+        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-        virtual OGRErr      SetAttributeFilter( const char * );
+        virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
-        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
+        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
+};
+
+
+class OGRPLScenesDataV1Layer;
+class OGRPLScenesDataV1Dataset: public GDALDataset
+{
+        bool            m_bLayerListInitialized;
+        bool            m_bMustCleanPersistent;
+        CPLString       m_osBaseURL;
+        CPLString       m_osAPIKey;
+        CPLString       m_osNextItemTypesPageURL;
+        CPLString       m_osFilter;
+
+        int                   m_nLayers;
+        OGRPLScenesDataV1Layer  **m_papoLayers;
+
+        bool            m_bFollowLinks;
+
+        char              **GetBaseHTTPOptions();
+        OGRLayer           *ParseItemType(json_object* poItemType);
+        bool                ParseItemTypes(json_object* poObj,
+                                              CPLString& osNext);
+        void                EstablishLayerList();
+        GDALDataset       *OpenRasterScene(GDALOpenInfo* poOpenInfo,
+                                           CPLString osScene,
+                                           char** papszOptions);
+        CPLString           InsertAPIKeyInURL(CPLString osURL);
+
+    public:
+                            OGRPLScenesDataV1Dataset();
+                           virtual ~OGRPLScenesDataV1Dataset();
+
+        virtual int         GetLayerCount() override;
+        virtual OGRLayer   *GetLayer(int idx) override;
+        virtual OGRLayer   *GetLayerByName(const char* pszName) override;
+
+        json_object        *RunRequest(const char* pszURL,
+                                       int bQuiet404Error = FALSE,
+                                       const char* pszHTTPVerb = "GET",
+                                       bool bExpectJSonReturn = true,
+                                       const char* pszPostContent = NULL);
+
+        bool                DoesFollowLinks() const { return m_bFollowLinks; }
+        const CPLString&    GetFilter() const { return m_osFilter; }
+        const CPLString&    GetBaseURL() const { return m_osBaseURL; }
+
+        static GDALDataset* Open(GDALOpenInfo* poOpenInfo);
+};
+
+class OGRPLScenesDataV1FeatureDefn: public OGRFeatureDefn
+{
+            OGRPLScenesDataV1Layer* m_poLayer;
+
+    public:
+        OGRPLScenesDataV1FeatureDefn(OGRPLScenesDataV1Layer* poLayer,
+                                 const char* pszName):
+                            OGRFeatureDefn(pszName), m_poLayer(poLayer) {}
+       ~OGRPLScenesDataV1FeatureDefn() {}
+
+       virtual int GetFieldCount() override;
 
+       void DropRefToLayer() { m_poLayer = NULL; }
+};
+
+class OGRPLScenesDataV1Layer: public OGRLayer
+{
+            friend class OGRPLScenesDataV1Dataset;
+            friend class OGRPLScenesDataV1FeatureDefn;
+
+            OGRPLScenesDataV1Dataset* m_poDS;
+            bool                  m_bFeatureDefnEstablished;
+            OGRPLScenesDataV1FeatureDefn* m_poFeatureDefn;
+            OGRSpatialReference*  m_poSRS;
+            GIntBig               m_nTotalFeatures;
+            std::map<CPLString, int> m_oMapPrefixedJSonFieldNameToFieldIdx;
+            std::map<int,CPLString>  m_oMapFieldIdxToQueriableJSonFieldName;
+
+            GIntBig               m_nNextFID;
+            bool                  m_bEOF;
+            bool                  m_bStillInFirstPage;
+            CPLString             m_osNextURL;
+            CPLString             m_osRequestURL;
+            int                   m_nPageSize;
+            bool                  m_bInFeatureCountOrGetExtent;
+
+            json_object          *m_poPageObj;
+            json_object          *m_poFeatures;
+            int                   m_nFeatureIdx;
+
+            json_object*          m_poAttributeFilter;
+            bool                  m_bFilterMustBeClientSideEvaluated;
+
+            std::set<CPLString>   m_oSetAssets;
+            std::set<CPLString>   m_oSetUnregisteredAssets;
+            std::set<CPLString>   m_oSetUnregisteredFields;
+
+            OGRFeature           *GetNextRawFeature();
+            bool                  SetFieldFromPrefixedJSonFieldName(
+                                        OGRFeature* poFeature,
+                                        const CPLString& osPrefixedJSonFieldName,
+                                        json_object* poVal );
+            void                  EstablishLayerDefn();
+            void                  RegisterField(OGRFieldDefn* poFieldDefn,
+                                                const char* pszQueriableJSonName,
+                                                const char* pszPrefixedJSonName);
+            bool                  GetNextPage();
+            json_object*          BuildFilter(swq_expr_node* poNode);
+            bool                  IsSimpleComparison(const swq_expr_node* poNode);
+
+    public:
+                            OGRPLScenesDataV1Layer(OGRPLScenesDataV1Dataset* poDS,
+                                                   const char* pszName);
+                           virtual ~OGRPLScenesDataV1Layer();
+
+        virtual void            ResetReading() override;
+        virtual OGRFeature     *GetNextFeature() override;
+        virtual int             TestCapability(const char*) override;
+        virtual OGRFeatureDefn *GetLayerDefn() override;
+        virtual GIntBig         GetFeatureCount(int bForce = FALSE) override;
+
+        virtual char      **GetMetadata( const char * pszDomain = "" ) override;
+        virtual const char *GetMetadataItem( const char * pszName, const char* pszDomain = "" ) override;
+
+        virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override;
+        virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
+                { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
+
+        virtual OGRErr      SetAttributeFilter( const char * ) override;
+
+        virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
+        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
+                { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
 #endif /* ndef OGR_PLSCENES_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
index 203e3d8..32d9485 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesdataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrplscenesdataset.cpp 35828 2016-10-19 23:23:39Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesDataset
@@ -28,19 +27,19 @@
  ****************************************************************************/
 
 #include "ogr_plscenes.h"
+#include "ogrgeojsonreader.h"
 
-CPL_CVSID("$Id: ogrplscenesdataset.cpp 35828 2016-10-19 23:23:39Z rouault $");
+CPL_CVSID("$Id: ogrplscenesdataset.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGRPLScenesDataset()                         */
 /************************************************************************/
 
-OGRPLScenesDataset::OGRPLScenesDataset()
-{
-    bMustCleanPersistent = FALSE;
-    nLayers = 0;
-    papoLayers = NULL;
-}
+OGRPLScenesDataset::OGRPLScenesDataset() :
+    bMustCleanPersistent(false),
+    nLayers(0),
+    papoLayers(NULL)
+{}
 
 /************************************************************************/
 /*                         ~OGRPLScenesDataset()                        */
@@ -48,14 +47,15 @@ OGRPLScenesDataset::OGRPLScenesDataset()
 
 OGRPLScenesDataset::~OGRPLScenesDataset()
 {
-    for(int i=0;i<nLayers;i++)
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
     CPLFree(papoLayers);
 
-    if (bMustCleanPersistent)
+    if( bMustCleanPersistent )
     {
-        char** papszOptions = NULL;
-        papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("PLSCENES:%p", this));
+        char **papszOptions =
+            CSLSetNameValue(NULL, "CLOSE_PERSISTENT",
+                            CPLSPrintf("PLSCENES:%p", this));
         CPLHTTPDestroyResult(CPLHTTPFetch(osBaseURL, papszOptions));
         CSLDestroy(papszOptions);
     }
@@ -65,7 +65,7 @@ OGRPLScenesDataset::~OGRPLScenesDataset()
 /*                              GetLayer()                              */
 /************************************************************************/
 
-OGRLayer *OGRPLScenesDataset::GetLayer(int idx)
+OGRLayer *OGRPLScenesDataset::GetLayer( int idx )
 {
     if( idx < 0 || idx >= nLayers )
         return NULL;
@@ -129,9 +129,8 @@ OGRLayer* OGRPLScenesDataset::ExecuteSQL( const char *pszSQLCommand,
             oSelect.table_count == 1 && oSelect.order_specs == 1 &&
             strcmp(oSelect.order_defs[0].field_name, "acquired") == 0 )
         {
-            int idx;
             OGRPLScenesLayer* poLayer = NULL;
-            for(idx = 0; idx < nLayers; idx ++ )
+            for( int idx = 0; idx < nLayers; idx++ )
             {
                 if( strcmp( papoLayers[idx]->GetName(),
                             oSelect.table_defs[0].table_name) == 0 )
@@ -179,11 +178,15 @@ void OGRPLScenesDataset::ReleaseResultSet( OGRLayer * poResultsSet )
 
 char** OGRPLScenesDataset::GetBaseHTTPOptions()
 {
-    bMustCleanPersistent = TRUE;
+    bMustCleanPersistent = true;
 
     char** papszOptions = NULL;
-    papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=PLSCENES:%p", this));
-    papszOptions = CSLAddString(papszOptions, CPLSPrintf("HEADERS=Authorization: api-key %s", osAPIKey.c_str()));
+    papszOptions =
+        CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=PLSCENES:%p", this));
+    papszOptions =
+        CSLAddString(papszOptions,
+                     CPLSPrintf("HEADERS=Authorization: api-key %s",
+                                osAPIKey.c_str()));
     return papszOptions;
 }
 
@@ -295,7 +298,7 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
 
     for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
     {
-        char* pszKey;
+        char* pszKey = NULL;
         const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
         if( pszValue != NULL )
         {
@@ -323,7 +326,7 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
     json_object* poObj = RunRequest( osRasterURL );
     if( poObj == NULL )
         return NULL;
-    json_object* poProperties = json_object_object_get(poObj, "properties");
+    json_object* poProperties = CPL_json_object_object_get(poObj, "properties");
     if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find properties object");
@@ -334,26 +337,26 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
     const char* pszLink = NULL;
     if( EQUAL(pszProductType, "thumb") )
     {
-        json_object* poLinks = json_object_object_get(poProperties, "links");
+        json_object* poLinks = CPL_json_object_object_get(poProperties, "links");
         if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object )
         {
-            json_object* poThumbnail = json_object_object_get(poLinks, "thumbnail");
+            json_object* poThumbnail = CPL_json_object_object_get(poLinks, "thumbnail");
             if( poThumbnail && json_object_get_type(poThumbnail) == json_type_string )
                 pszLink = json_object_get_string(poThumbnail);
         }
     }
     else
     {
-        json_object* poData = json_object_object_get(poProperties, "data");
+        json_object* poData = CPL_json_object_object_get(poProperties, "data");
         if( poData != NULL && json_object_get_type(poData) == json_type_object )
         {
-            json_object* poProducts = json_object_object_get(poData, "products");
+            json_object* poProducts = CPL_json_object_object_get(poData, "products");
             if( poProducts != NULL && json_object_get_type(poProducts) == json_type_object )
             {
-                json_object* poProduct = json_object_object_get(poProducts, pszProductType);
+                json_object* poProduct = CPL_json_object_object_get(poProducts, pszProductType);
                 if( poProduct != NULL && json_object_get_type(poProduct) == json_type_object )
                 {
-                    json_object* poFull = json_object_object_get(poProduct, "full");
+                    json_object* poFull = CPL_json_object_object_get(poProduct, "full");
                     if( poFull && json_object_get_type(poFull) == json_type_string )
                         pszLink = json_object_get_string(poFull);
                 }
@@ -362,7 +365,7 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
     }
     osRasterURL = pszLink ? pszLink : "";
     json_object_put(poObj);
-    if( osRasterURL.size() == 0 )
+    if( osRasterURL.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link to scene %s",
                  osScene.c_str());
@@ -381,7 +384,8 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
     CPLString osOldHead(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", ""));
     CPLString osOldAllowedFilename(CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME", ""));
 
-    int bUseVSICURL = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", TRUE);
+    const bool bUseVSICURL =
+        CPLFetchBool(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", true);
     if( bUseVSICURL && !(STARTS_WITH(osBaseURL, "/vsimem/")) )
     {
         CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", "NO");
@@ -400,7 +404,14 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
         }
     }
 
-    GDALDataset* poOutDS = (GDALDataset*) GDALOpen(osRasterURL, GA_ReadOnly);
+    char** papszAllowedDrivers = NULL;
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "HTTP");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "GTiff");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "PNG");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "JPEG");
+    GDALDataset* poOutDS = (GDALDataset*) GDALOpenEx(osRasterURL, GDAL_OF_RASTER,
+                                                     papszAllowedDrivers, NULL, NULL);
+    CSLDestroy(papszAllowedDrivers);
     if( poOutDS )
     {
         if( !EQUAL(pszProductType, "thumb") )
@@ -422,7 +433,7 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
             {
                 for(int i=0;i<poFeat->GetFieldCount();i++)
                 {
-                    if( poFeat->IsFieldSet(i) )
+                    if( poFeat->IsFieldSetAndNotNull(i) )
                     {
                         const char* pszKey = poFeat->GetFieldDefnRef(i)->GetNameRef();
                         const char* pszVal = poFeat->GetFieldAsString(i);
@@ -444,15 +455,15 @@ GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
 
         CPLErrorReset();
         poOutDS->SetDescription(poOpenInfo->pszFilename);
-        CSLDestroy(poOutDS->GetFileList()); /* so as to probe all auxiliary files before reseting the allowed extensions */
+        CSLDestroy(poOutDS->GetFileList()); /* so as to probe all auxiliary files before resetting the allowed extensions */
     }
 
     if( bUseVSICURL )
     {
         CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD",
-                                    osOldHead.size() ? osOldHead.c_str(): NULL);
+                                    !osOldHead.empty() ? osOldHead.c_str(): NULL);
         CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME",
-                                    osOldAllowedFilename.size() ? osOldAllowedFilename.c_str(): NULL);
+                                    !osOldAllowedFilename.empty() ? osOldAllowedFilename.c_str(): NULL);
     }
 
     return poOutDS;
@@ -469,12 +480,12 @@ GDALDataset* OGRPLScenesDataset::Open(GDALOpenInfo* poOpenInfo)
     poDS->osBaseURL = CPLGetConfigOption("PL_URL", "https://api.planet.com/v0/scenes/");
 
     char** papszOptions = CSLTokenizeStringComplex(
-            poOpenInfo->pszFilename+strlen("PLScenes:"), ",", TRUE, FALSE );
+        poOpenInfo->pszFilename+strlen("PLScenes:"), ",", TRUE, FALSE );
 
     poDS->osAPIKey = CSLFetchNameValueDef(papszOptions, "api_key",
         CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "API_KEY",
                                 CPLGetConfigOption("PL_API_KEY","")) );
-    if( poDS->osAPIKey.size() == 0 )
+    if( poDS->osAPIKey.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Missing PL_API_KEY configuration option or API_KEY open option");
@@ -496,7 +507,7 @@ GDALDataset* OGRPLScenesDataset::Open(GDALOpenInfo* poOpenInfo)
 
     for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
     {
-        char* pszKey;
+        char* pszKey = NULL;
         const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
         if( pszValue != NULL )
         {
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1dataset.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1dataset.cpp
new file mode 100644
index 0000000..e2872f9
--- /dev/null
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1dataset.cpp
@@ -0,0 +1,812 @@
+/******************************************************************************
+ *
+ * Project:  PlanetLabs scene driver
+ * Purpose:  Implements OGRPLScenesDataV1Dataset
+ * Author:   Even Rouault, even dot rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Planet Labs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_plscenes.h"
+#include "ogrgeojsonreader.h"
+#include <time.h>
+
+CPL_CVSID("$Id: ogrplscenesdatav1dataset.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
+/************************************************************************/
+/*                       OGRPLScenesDataV1Dataset()                     */
+/************************************************************************/
+
+OGRPLScenesDataV1Dataset::OGRPLScenesDataV1Dataset() :
+    m_bLayerListInitialized(false),
+    m_bMustCleanPersistent(false),
+    m_nLayers(0),
+    m_papoLayers(NULL),
+    m_bFollowLinks(false)
+{}
+
+/************************************************************************/
+/*                       ~OGRPLScenesDataV1Dataset()                    */
+/************************************************************************/
+
+OGRPLScenesDataV1Dataset::~OGRPLScenesDataV1Dataset()
+{
+    for( int i = 0; i < m_nLayers; i++ )
+        delete m_papoLayers[i];
+    CPLFree(m_papoLayers);
+
+    if( m_bMustCleanPersistent )
+    {
+        char **papszOptions =
+            CSLSetNameValue(
+                NULL, "CLOSE_PERSISTENT", CPLSPrintf("PLSCENES:%p", this));
+        CPLHTTPDestroyResult(CPLHTTPFetch(m_osBaseURL, papszOptions));
+        CSLDestroy(papszOptions);
+    }
+}
+
+/************************************************************************/
+/*                              GetLayer()                              */
+/************************************************************************/
+
+OGRLayer *OGRPLScenesDataV1Dataset::GetLayer(int idx)
+{
+    if( idx < 0 || idx >= GetLayerCount() )
+        return NULL;
+    return m_papoLayers[idx];
+}
+
+/************************************************************************/
+/*                           GetLayerCount()                            */
+/************************************************************************/
+
+int OGRPLScenesDataV1Dataset::GetLayerCount()
+{
+    if( !m_bLayerListInitialized )
+    {
+        m_bLayerListInitialized = true;
+        EstablishLayerList();
+    }
+    return m_nLayers;
+}
+
+/************************************************************************/
+/*                          ParseItemType()                             */
+/************************************************************************/
+
+OGRLayer* OGRPLScenesDataV1Dataset::ParseItemType(json_object* poItemType)
+{
+    if( poItemType == NULL || json_object_get_type(poItemType) != json_type_object )
+        return NULL;
+    json_object* poId = CPL_json_object_object_get(poItemType, "id");
+    if( poId == NULL || json_object_get_type(poId) != json_type_string )
+        return NULL;
+
+    CPLString osDisplayDescription;
+    json_object* poDisplayDescription = CPL_json_object_object_get(poItemType, "display_description");
+    if( poDisplayDescription != NULL && json_object_get_type(poDisplayDescription) == json_type_string )
+        osDisplayDescription = json_object_get_string(poDisplayDescription);
+    CPLString osDisplayName;
+    json_object* poDisplayName = CPL_json_object_object_get(poItemType, "display_name");
+    if( poDisplayName != NULL && json_object_get_type(poDisplayName) == json_type_string )
+        osDisplayName = json_object_get_string(poDisplayName);
+
+    const char* pszId = json_object_get_string(poId);
+
+    // The layer might already exist if GetLayerByName() is called before
+    // GetLayer()/GetLayerCount() is
+
+    // Prevent GetLayerCount() from calling EstablishLayerList()
+    bool bLayerListInitializedBackup = m_bLayerListInitialized;
+    m_bLayerListInitialized = true;
+    OGRLayer* poExistingLayer = GDALDataset::GetLayerByName(pszId);
+    m_bLayerListInitialized = bLayerListInitializedBackup;
+    if( poExistingLayer != NULL )
+        return poExistingLayer;
+
+    OGRPLScenesDataV1Layer* poPLLayer = new OGRPLScenesDataV1Layer(
+                                                                this, pszId);
+    if( !osDisplayName.empty() )
+        poPLLayer->SetMetadataItem("SHORT_DESCRIPTION", osDisplayName.c_str());
+    if( !osDisplayDescription.empty() )
+        poPLLayer->SetMetadataItem("DESCRIPTION", osDisplayDescription.c_str());
+    m_papoLayers = (OGRPLScenesDataV1Layer**) CPLRealloc(m_papoLayers,
+                                sizeof(OGRPLScenesDataV1Layer*) * (m_nLayers + 1));
+    m_papoLayers[m_nLayers ++] = poPLLayer;
+    return poPLLayer;
+}
+
+/************************************************************************/
+/*                          ParseItemTypes()                         */
+/************************************************************************/
+
+bool OGRPLScenesDataV1Dataset::ParseItemTypes(json_object* poObj,
+                                             CPLString& osNext)
+{
+    json_object* poItemTypes = CPL_json_object_object_get(poObj, "item_types");
+    if( poItemTypes == NULL || json_object_get_type(poItemTypes) != json_type_array )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                "Missing item_types object, or not of type array");
+        return false;
+    }
+    const int nCatalogsLength = json_object_array_length(poItemTypes);
+    for( int i=0; i<nCatalogsLength; i++ )
+    {
+        json_object* poItemType = json_object_array_get_idx(poItemTypes, i);
+        ParseItemType(poItemType);
+    }
+
+    // Is there a next page ?
+    osNext = "";
+    json_object* poLinks = CPL_json_object_object_get(poObj, "_links");
+    if( poLinks && json_object_get_type(poLinks) == json_type_object )
+    {
+        json_object* poNext = CPL_json_object_object_get(poLinks, "_next");
+        if( poNext && json_object_get_type(poNext) == json_type_string )
+        {
+            osNext = json_object_get_string(poNext);
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                          EstablishLayerList()                        */
+/************************************************************************/
+
+void OGRPLScenesDataV1Dataset::EstablishLayerList()
+{
+    CPLString osURL(m_osNextItemTypesPageURL);
+    m_osNextItemTypesPageURL = "";
+
+    while( !osURL.empty() )
+    {
+        json_object* poObj = RunRequest(osURL);
+        if( poObj == NULL )
+            break;
+        if( !ParseItemTypes( poObj, osURL ) )
+        {
+            json_object_put(poObj);
+            break;
+        }
+        json_object_put(poObj);
+    }
+}
+
+/************************************************************************/
+/*                          GetLayerByName()                            */
+/************************************************************************/
+
+OGRLayer *OGRPLScenesDataV1Dataset::GetLayerByName(const char* pszName)
+{
+    // Prevent GetLayerCount() from calling EstablishLayerList()
+    bool bLayerListInitializedBackup = m_bLayerListInitialized;
+    m_bLayerListInitialized = true;
+    OGRLayer* poRet = GDALDataset::GetLayerByName(pszName);
+    m_bLayerListInitialized = bLayerListInitializedBackup;
+    if( poRet != NULL )
+        return poRet;
+
+    CPLString osURL(m_osBaseURL + "item-types/" + pszName);
+    json_object* poObj = RunRequest(osURL);
+    if( poObj == NULL )
+        return NULL;
+    poRet = ParseItemType(poObj);
+    json_object_put(poObj);
+    return poRet;
+}
+
+/************************************************************************/
+/*                          GetBaseHTTPOptions()                         */
+/************************************************************************/
+
+char** OGRPLScenesDataV1Dataset::GetBaseHTTPOptions()
+{
+    m_bMustCleanPersistent = true;
+
+    char** papszOptions = NULL;
+    papszOptions =
+        CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=PLSCENES:%p", this));
+    papszOptions =
+        CSLAddString(papszOptions,
+                     CPLSPrintf("HEADERS=Authorization: api-key %s",
+                                m_osAPIKey.c_str()));
+
+    return papszOptions;
+}
+
+/************************************************************************/
+/*                               RunRequest()                           */
+/************************************************************************/
+
+json_object* OGRPLScenesDataV1Dataset::RunRequest(const char* pszURL,
+                                              int bQuiet404Error,
+                                              const char* pszHTTPVerb,
+                                              bool bExpectJSonReturn,
+                                              const char* pszPostContent)
+{
+    char** papszOptions = CSLAddString(GetBaseHTTPOptions(), NULL);
+    // We need to set it each time as CURL would reuse the previous value
+    // if reusing the same connection
+    papszOptions = CSLSetNameValue(papszOptions, "CUSTOMREQUEST", pszHTTPVerb);
+    if( pszPostContent != NULL )
+    {
+        CPLString osHeaders = CSLFetchNameValueDef(papszOptions, "HEADERS", "");
+        if( !osHeaders.empty() )
+            osHeaders += "\r\n";
+        osHeaders += "Content-Type: application/json";
+        papszOptions = CSLSetNameValue(papszOptions, "HEADERS", osHeaders);
+        papszOptions = CSLSetNameValue(papszOptions, "POSTFIELDS", pszPostContent);
+    }
+    papszOptions = CSLSetNameValue(papszOptions, "MAX_RETRY", "3");
+    CPLHTTPResult *psResult = NULL;
+    if( STARTS_WITH(m_osBaseURL, "/vsimem/") &&
+        STARTS_WITH(pszURL, "/vsimem/") )
+    {
+        psResult = (CPLHTTPResult*) CPLCalloc(1, sizeof(CPLHTTPResult));
+        vsi_l_offset nDataLengthLarge = 0;
+        CPLString osURL(pszURL);
+        if( osURL[osURL.size()-1 ] == '/' )
+            osURL.resize(osURL.size()-1);
+        if( pszPostContent != NULL )
+        {
+            osURL += "&POSTFIELDS=";
+            osURL += pszPostContent;
+        }
+        CPLDebug("PLSCENES", "Fetching %s", osURL.c_str());
+        GByte* pabyBuf = VSIGetMemFileBuffer(osURL, &nDataLengthLarge, FALSE);
+        size_t nDataLength = static_cast<size_t>(nDataLengthLarge);
+        if( pabyBuf )
+        {
+            psResult->pabyData = (GByte*) VSI_MALLOC_VERBOSE(1 + nDataLength);
+            if( psResult->pabyData )
+            {
+                memcpy(psResult->pabyData, pabyBuf, nDataLength);
+                psResult->pabyData[nDataLength] = 0;
+            }
+        }
+        else
+        {
+            psResult->pszErrBuf =
+                CPLStrdup(CPLSPrintf("Error 404. Cannot find %s", osURL.c_str()));
+        }
+    }
+    else
+    {
+        if( bQuiet404Error )
+            CPLPushErrorHandler(CPLQuietErrorHandler);
+        psResult = CPLHTTPFetch( pszURL, papszOptions);
+        if( bQuiet404Error )
+            CPLPopErrorHandler();
+    }
+    CSLDestroy(papszOptions);
+
+    if( pszPostContent != NULL && m_bMustCleanPersistent )
+    {
+        papszOptions = CSLSetNameValue(NULL, "CLOSE_PERSISTENT", CPLSPrintf("PLSCENES:%p", this));
+        CPLHTTPDestroyResult(CPLHTTPFetch(m_osBaseURL, papszOptions));
+        CSLDestroy(papszOptions);
+        m_bMustCleanPersistent = false;
+    }
+
+    if( psResult->pszErrBuf != NULL )
+    {
+        if( !(bQuiet404Error && strstr(psResult->pszErrBuf, "404")) )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "%s",
+                    psResult->pabyData ? (const char*) psResult->pabyData :
+                    psResult->pszErrBuf);
+        }
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    if( !bExpectJSonReturn && (psResult->pabyData == NULL || psResult->nDataLen == 0) )
+    {
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    if( psResult->pabyData == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Empty content returned by server");
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+
+    json_tokener* jstok = NULL;
+    json_object* poObj = NULL;
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("PLScenes", "%s", (const char*) psResult->pabyData);
+#endif
+
+    jstok = json_tokener_new();
+    poObj = json_tokener_parse_ex(jstok, (const char*) psResult->pabyData, -1);
+    if( jstok->err != json_tokener_success)
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                    "JSON parsing error: %s (at offset %d)",
+                    json_tokener_error_desc(jstok->err), jstok->char_offset);
+        json_tokener_free(jstok);
+        CPLHTTPDestroyResult(psResult);
+        return NULL;
+    }
+    json_tokener_free(jstok);
+
+    CPLHTTPDestroyResult(psResult);
+
+    if( json_object_get_type(poObj) != json_type_object )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "Return is not a JSON dictionary");
+        json_object_put(poObj);
+        poObj = NULL;
+    }
+
+    return poObj;
+}
+
+/************************************************************************/
+/*                           InsertAPIKeyInURL()                        */
+/************************************************************************/
+
+CPLString OGRPLScenesDataV1Dataset::InsertAPIKeyInURL(CPLString osURL)
+{
+    if( STARTS_WITH(osURL, "http://") )
+    {
+        osURL = "http://" + m_osAPIKey + ":@" + osURL.substr(strlen("http://"));
+    }
+    else if( STARTS_WITH(osURL, "https://") )
+    {
+        osURL = "https://" + m_osAPIKey + ":@" + osURL.substr(strlen("https://"));
+    }
+    return osURL;
+}
+
+/************************************************************************/
+/*                            OpenRasterScene()                         */
+/************************************************************************/
+
+GDALDataset* OGRPLScenesDataV1Dataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
+                                                 CPLString osScene,
+                                                 char** papszOptions)
+{
+    if( !(poOpenInfo->nOpenFlags & GDAL_OF_RASTER) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "The scene option must only be used with vector access");
+        return NULL;
+    }
+
+    int nActivationTimeout = atoi(CSLFetchNameValueDef(poOpenInfo->papszOpenOptions,
+                                                      "ACTIVATION_TIMEOUT", "3600"));
+
+    for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
+    {
+        char* pszKey = NULL;
+        const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
+        if( pszValue != NULL )
+        {
+            if( !EQUAL(pszKey, "api_key") &&
+                !EQUAL(pszKey, "scene") &&
+                !EQUAL(pszKey, "product_type") &&
+                !EQUAL(pszKey, "asset") &&
+                !EQUAL(pszKey, "catalog") &&
+                !EQUAL(pszKey, "itemtypes") &&
+                !EQUAL(pszKey, "version") &&
+                !EQUAL(pszKey, "follow_links") &&
+                !EQUAL(pszKey, "metadata"))
+            {
+                CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option %s", pszKey);
+                CPLFree(pszKey);
+                return NULL;
+            }
+            CPLFree(pszKey);
+        }
+    }
+
+    const char* pszCatalog =
+        CSLFetchNameValueDef(papszOptions, "itemtypes",
+        CSLFetchNameValueDef(papszOptions, "catalog",
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "ITEMTYPES",
+        CSLFetchNameValue(poOpenInfo->papszOpenOptions, "CATALOG"))));
+    if( pszCatalog == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Missing catalog");
+        return NULL;
+    }
+
+    const char* pszProductType =
+        CSLFetchNameValueDef(papszOptions, "asset",
+        CSLFetchNameValueDef(papszOptions, "product_type",
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "ASSET",
+        CSLFetchNameValue(poOpenInfo->papszOpenOptions, "PRODUCT_TYPE"))));
+
+    CPLString osRasterURL;
+    osRasterURL = m_osBaseURL;
+    osRasterURL += "item-types/";
+    osRasterURL += pszCatalog;
+    osRasterURL += "/items/";
+    osRasterURL += osScene;
+    osRasterURL += "/assets/";
+
+    time_t nStartTime = time(NULL);
+retry:
+    time_t nCurrentTime = time(NULL);
+    if( nCurrentTime - nStartTime > nActivationTimeout )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Activation timeout reached");
+        return NULL;
+    }
+    json_object* poObj = RunRequest( osRasterURL );
+    if( poObj == NULL )
+        return NULL;
+
+    json_object* poSubObj = NULL;
+    if( pszProductType != NULL &&
+        (poSubObj = CPL_json_object_object_get(poObj, pszProductType)) != NULL )
+    {
+       /* do nothing */
+    }
+    else if( pszProductType != NULL && !EQUAL(pszProductType, "LIST") &&
+        (poSubObj = CPL_json_object_object_get(poObj, pszProductType)) == NULL )
+    {
+       CPLError(CE_Failure, CPLE_AppDefined, "Cannot find asset %s", pszProductType);
+       json_object_put(poObj);
+       return NULL;
+    }
+    else if( pszProductType == NULL &&
+             (poSubObj = CPL_json_object_object_get(poObj, "visual")) != NULL )
+    {
+        /* do nothing */
+    }
+    else
+    {
+        json_object_iter it;
+        it.key = NULL;
+        it.val = NULL;
+        it.entry = NULL;
+        char** papszSubdatasets = NULL;
+        int nSubDataset = 0;
+        json_object_object_foreachC( poObj, it )
+        {
+            ++nSubDataset;
+            papszSubdatasets = CSLSetNameValue(papszSubdatasets,
+                    CPLSPrintf("SUBDATASET_%d_NAME", nSubDataset),
+                    CPLSPrintf("Scene=%s of item types %s, asset %s",
+                               osScene.c_str(), pszCatalog, it.key));
+            papszSubdatasets = CSLSetNameValue(papszSubdatasets,
+                    CPLSPrintf("SUBDATASET_%d_DESC", nSubDataset),
+                    CPLSPrintf("PLScenes:version=Data_V1,itemtypes=%s,scene=%s,asset=%s",
+                               pszCatalog, osScene.c_str(), it.key));
+        }
+        json_object_put(poObj);
+        if( nSubDataset != 0 )
+        {
+            GDALDataset* poDS = new OGRPLScenesDataV1Dataset();
+            poDS->SetMetadata(papszSubdatasets, "SUBDATASETS");
+            CSLDestroy(papszSubdatasets);
+            return poDS;
+        }
+        return NULL;
+    }
+    if( json_object_get_type(poSubObj) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link");
+        json_object_put(poObj);
+        return NULL;
+    }
+
+    json_object* poPermissions = CPL_json_object_object_get(poSubObj, "_permissions");
+    if( poPermissions != NULL )
+    {
+        const char* pszPermissions = json_object_to_json_string_ext( poPermissions, 0 );
+        if( pszPermissions && strstr(pszPermissions, "download") == NULL )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "You don't have download permissions for this product");
+        }
+    }
+
+    json_object* poLocation = CPL_json_object_object_get(poSubObj, "location");
+    json_object* poStatus = CPL_json_object_object_get(poSubObj, "status");
+    bool bActive = false;
+    if( poStatus != NULL && json_object_get_type(poStatus) == json_type_string )
+    {
+        const char* pszStatus = json_object_get_string(poStatus);
+        if( EQUAL( pszStatus, "activating" ) )
+        {
+            CPLDebug("PLScenes", "The product is in activation. Retrying...");
+            CPLSleep( nActivationTimeout == 1 ? 0.5 : 1.0);
+            poLocation = NULL;
+            json_object_put(poObj);
+            goto retry;
+        }
+        bActive = EQUAL( pszStatus, "active" );
+    }
+    if( poLocation == NULL || json_object_get_type(poLocation) != json_type_string ||
+        !bActive )
+    {
+        CPLDebug("PLScenes", "The product isn't activated yet. Activating it");
+        json_object* poActivate = json_ex_get_object_by_path(poSubObj, "_links.activate");
+        if( poActivate == NULL || json_object_get_type(poActivate) != json_type_string )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link to activate scene %s",
+                      osScene.c_str());
+            json_object_put(poObj);
+            return NULL;
+        }
+        CPLString osActivate = json_object_get_string(poActivate);
+        poLocation = NULL;
+        json_object_put(poObj);
+        poObj = RunRequest( osActivate, FALSE, "POST", false );
+        if( poObj != NULL )
+            json_object_put(poObj);
+        poObj = NULL;
+        CPLSleep(nActivationTimeout == 1 ? 0.5 : 1.0);
+        goto retry;
+    }
+
+    const char* pszLink = json_object_get_string(poLocation);
+
+    osRasterURL = pszLink ? pszLink : "";
+    json_object_put(poObj);
+    if( osRasterURL.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link to scene %s",
+                 osScene.c_str());
+        return NULL;
+    }
+
+    osRasterURL = InsertAPIKeyInURL(osRasterURL);
+
+    CPLString osOldHead(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", ""));
+    CPLString osOldAllowedFilename(CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME", ""));
+
+    const bool bUseVSICURL =
+        CPLFetchBool(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", true);
+    if( bUseVSICURL && !(STARTS_WITH(m_osBaseURL, "/vsimem/")) )
+    {
+        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", "NO");
+        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME",
+                                      ("/vsicurl/" + osRasterURL).c_str());
+
+        VSIStatBufL sStat;
+        if( VSIStatL(("/vsicurl/" + osRasterURL).c_str(), &sStat) == 0 &&
+            sStat.st_size > 0 )
+        {
+            osRasterURL = "/vsicurl/" + osRasterURL;
+        }
+        else
+        {
+            CPLDebug("PLSCENES", "Cannot use random access for that file");
+        }
+    }
+
+    char** papszAllowedDrivers = NULL;
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "HTTP");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "GTiff");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "PNG");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "JPEG");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "NITF");
+    GDALDataset* poOutDS = (GDALDataset*) GDALOpenEx(osRasterURL, GDAL_OF_RASTER,
+                                                     papszAllowedDrivers, NULL, NULL);
+    CSLDestroy(papszAllowedDrivers);
+    if( poOutDS )
+    {
+        if( CPLFetchBool(papszOptions, "metadata",
+                CPLFetchBool(poOpenInfo->papszOpenOptions, "METADATA", true)) )
+        {
+            OGRLayer* poLayer = GetLayerByName(pszCatalog);
+            if( poLayer != NULL )
+            {
+                // Set a dummy name so that PAM goes here
+                CPLPushErrorHandler(CPLQuietErrorHandler);
+                poOutDS->SetDescription("/vsimem/tmp/ogrplscenesDataV1");
+
+                /* Attach scene metadata. */
+                poLayer->SetAttributeFilter(CPLSPrintf("id = '%s'", osScene.c_str()));
+                OGRFeature* poFeat = poLayer->GetNextFeature();
+                if( poFeat )
+                {
+                    for(int i=0;i<poFeat->GetFieldCount();i++)
+                    {
+                        if( poFeat->IsFieldSetAndNotNull(i) )
+                        {
+                            const char* pszKey = poFeat->GetFieldDefnRef(i)->GetNameRef();
+                            const char* pszVal = poFeat->GetFieldAsString(i);
+                            if( strncmp(pszKey, "asset_", strlen("asset_")) == 0 ||
+                                strstr(pszVal, "https://") != NULL ||
+                                strcmp(pszKey, "columns") == 0 ||
+                                strcmp(pszKey, "rows") == 0 ||
+                                strcmp(pszKey, "epsg_code") == 0 ||
+                                strcmp(pszKey, "origin_x") == 0 ||
+                                strcmp(pszKey, "origin_y") == 0 ||
+                                strcmp(pszKey, "permissions") == 0 ||
+                                strcmp(pszKey, "acquired") == 0 // Redundant with TIFFTAG_DATETIME
+                            )
+                            {
+                                continue;
+                            }
+                            poOutDS->SetMetadataItem(pszKey, pszVal);
+                        }
+                    }
+                }
+                delete poFeat;
+
+                poOutDS->FlushCache();
+                VSIUnlink("/vsimem/tmp/ogrplscenesDataV1");
+                VSIUnlink("/vsimem/tmp/ogrplscenesDataV1.aux.xml");
+                CPLPopErrorHandler();
+            }
+        }
+
+        CPLErrorReset();
+        poOutDS->SetDescription(poOpenInfo->pszFilename);
+        CSLDestroy(poOutDS->GetFileList()); /* so as to probe all auxiliary files before resetting the allowed extensions */
+    }
+    else if( CPLGetLastErrorType() == CE_None )
+    {
+        poObj = RunRequest( osRasterURL );
+        if( poObj == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "The generation of the product is in progress. Retry later");
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "%s", json_object_to_json_string_ext( poObj, JSON_C_TO_STRING_PRETTY ));
+            json_object_put(poObj);
+        }
+    }
+
+    if( bUseVSICURL )
+    {
+        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD",
+                                    !osOldHead.empty() ? osOldHead.c_str(): NULL);
+        CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME",
+                                    !osOldAllowedFilename.empty() ? osOldAllowedFilename.c_str(): NULL);
+    }
+
+    return poOutDS;
+}
+
+/************************************************************************/
+/*                                Open()                                */
+/************************************************************************/
+
+GDALDataset* OGRPLScenesDataV1Dataset::Open(GDALOpenInfo* poOpenInfo)
+{
+    OGRPLScenesDataV1Dataset* poDS = new OGRPLScenesDataV1Dataset();
+
+    poDS->m_osBaseURL = CPLGetConfigOption("PL_URL", "https://api.planet.com/data/v1/");
+
+    char** papszOptions = CSLTokenizeStringComplex(
+            poOpenInfo->pszFilename+strlen("PLScenes:"), ",", TRUE, FALSE );
+
+    poDS->m_osAPIKey = CSLFetchNameValueDef(papszOptions, "api_key",
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "API_KEY",
+                                CPLGetConfigOption("PL_API_KEY","")) );
+    if( poDS->m_osAPIKey.empty() )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Missing PL_API_KEY configuration option or API_KEY open option");
+        delete poDS;
+        CSLDestroy(papszOptions);
+        return NULL;
+    }
+
+    poDS->m_bFollowLinks = CPLTestBool( CSLFetchNameValueDef(papszOptions, "follow_links",
+                CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "FOLLOW_LINKS", "FALSE")) );
+
+    poDS->m_osFilter = CSLFetchNameValueDef(papszOptions, "filter",
+                CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "FILTER", ""));
+    poDS->m_osFilter.Trim();
+
+    const char* pszScene = CSLFetchNameValueDef(papszOptions, "scene",
+                CSLFetchNameValue(poOpenInfo->papszOpenOptions, "SCENE"));
+    if( pszScene )
+    {
+        GDALDataset* poRasterDS = poDS->OpenRasterScene(poOpenInfo, pszScene,
+                                                        papszOptions);
+        delete poDS;
+        CSLDestroy(papszOptions);
+        return poRasterDS;
+    }
+    else if( (poOpenInfo->nOpenFlags & GDAL_OF_RASTER) &&
+             !(poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Missing scene");
+        delete poDS;
+        CSLDestroy(papszOptions);
+        return NULL;
+    }
+
+    for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
+    {
+        char* pszKey = NULL;
+        const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
+        if( pszValue != NULL )
+        {
+            if( !EQUAL(pszKey, "api_key") &&
+                !EQUAL(pszKey, "version") &&
+                !EQUAL(pszKey, "catalog") &&
+                !EQUAL(pszKey, "itemtypes") &&
+                !EQUAL(pszKey, "follow_links") &&
+                !EQUAL(pszKey, "filter") )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option '%s'", pszKey);
+                CPLFree(pszKey);
+                delete poDS;
+                CSLDestroy(papszOptions);
+                return NULL;
+            }
+            CPLFree(pszKey);
+        }
+    }
+
+    json_object* poObj = poDS->RunRequest((poDS->m_osBaseURL + "item-types/").c_str());
+    if( poObj == NULL )
+    {
+        delete poDS;
+        CSLDestroy(papszOptions);
+        return NULL;
+    }
+
+    const char* pszCatalog =
+        CSLFetchNameValueDef(papszOptions, "itemtypes",
+        CSLFetchNameValueDef(papszOptions, "catalog",
+        CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "ITEMTYPES",
+        CSLFetchNameValue(poOpenInfo->papszOpenOptions, "CATALOG"))));
+    if( pszCatalog == NULL )
+    {
+        // Establish (partial if there are other pages) layer list.
+        if( !poDS->ParseItemTypes( poObj, poDS->m_osNextItemTypesPageURL) )
+        {
+            delete poDS;
+            poDS = NULL;
+        }
+    }
+    else
+    {
+        if( poDS->GetLayerByName( pszCatalog ) == NULL )
+        {
+            delete poDS;
+            poDS = NULL;
+        }
+    }
+
+    json_object_put(poObj);
+
+    CSLDestroy(papszOptions);
+
+    if( !(poOpenInfo->nOpenFlags & GDAL_OF_VECTOR) )
+    {
+        delete poDS;
+        return NULL;
+    }
+
+    return poDS;
+}
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1layer.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1layer.cpp
new file mode 100644
index 0000000..8f6ab99
--- /dev/null
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesdatav1layer.cpp
@@ -0,0 +1,1319 @@
+/******************************************************************************
+ *
+ * Project:  PlanetLabs scene driver
+ * Purpose:  Implements OGRPLScenesDataV1Layer
+ * Author:   Even Rouault, even dot rouault at spatialys.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Planet Labs
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_plscenes.h"
+#include "ogrgeojsonreader.h"
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrplscenesdatav1layer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
+/************************************************************************/
+/*                           GetFieldCount()                            */
+/************************************************************************/
+
+int OGRPLScenesDataV1FeatureDefn::GetFieldCount()
+{
+    if( nFieldCount == 0 && m_poLayer != NULL )
+        m_poLayer->EstablishLayerDefn();
+    return nFieldCount;
+}
+
+/************************************************************************/
+/*                        OGRPLScenesDataV1Layer()                      */
+/************************************************************************/
+
+OGRPLScenesDataV1Layer::OGRPLScenesDataV1Layer( OGRPLScenesDataV1Dataset* poDS,
+                                                const char* pszName ) :
+    m_poDS(poDS),
+    m_bFeatureDefnEstablished(false),
+    m_poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
+    m_nTotalFeatures(-1),
+    m_nNextFID(1),
+    m_bEOF(false),
+    m_bStillInFirstPage(true),
+    m_nPageSize(atoi(CPLGetConfigOption("PLSCENES_PAGE_SIZE", "250"))),
+    m_bInFeatureCountOrGetExtent(false),
+    m_poPageObj(NULL),
+    m_poFeatures(NULL),
+    m_nFeatureIdx(0),
+    m_poAttributeFilter(NULL),
+    m_bFilterMustBeClientSideEvaluated(false)
+{
+    // Cannot be moved to initializer list because of use of this, which MSVC 2008 doesn't like
+    m_poFeatureDefn = new OGRPLScenesDataV1FeatureDefn(this, pszName);
+
+    SetDescription(pszName);
+    m_poFeatureDefn->SetGeomType(wkbMultiPolygon);
+    m_poFeatureDefn->Reference();
+    m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poSRS);
+    ResetReading();
+}
+
+/************************************************************************/
+/*                      ~OGRPLScenesDataV1Layer()                       */
+/************************************************************************/
+
+OGRPLScenesDataV1Layer::~OGRPLScenesDataV1Layer()
+{
+    m_poFeatureDefn->DropRefToLayer();
+    m_poFeatureDefn->Release();
+    m_poSRS->Release();
+    if( m_poPageObj != NULL )
+        json_object_put(m_poPageObj);
+    if( m_poAttributeFilter != NULL )
+        json_object_put(m_poAttributeFilter);
+}
+
+/************************************************************************/
+/*                             GetLayerDefn()                           */
+/************************************************************************/
+
+OGRFeatureDefn* OGRPLScenesDataV1Layer::GetLayerDefn()
+{
+    return m_poFeatureDefn;
+}
+
+/************************************************************************/
+/*                          RegisterField()                             */
+/************************************************************************/
+
+void OGRPLScenesDataV1Layer::RegisterField(OGRFieldDefn* poFieldDefn,
+                                       const char* pszQueriableJSonName,
+                                       const char* pszPrefixedJSonName)
+{
+    const int nIdx = m_poFeatureDefn->GetFieldCount();
+    m_oMapPrefixedJSonFieldNameToFieldIdx[pszPrefixedJSonName] = nIdx;
+    if( pszQueriableJSonName )
+    {
+        m_oMapFieldIdxToQueriableJSonFieldName[nIdx] = pszQueriableJSonName;
+    }
+    m_poFeatureDefn->AddFieldDefn(poFieldDefn);
+}
+
+/************************************************************************/
+/*                         EstablishLayerDefn()                         */
+/************************************************************************/
+
+void OGRPLScenesDataV1Layer::EstablishLayerDefn()
+{
+    if( m_bFeatureDefnEstablished )
+        return;
+    m_bFeatureDefnEstablished = true;
+
+    const char* pszConfFile = CPLFindFile("gdal", "plscenesconf.json");
+    if( pszConfFile == NULL )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find plscenesconf.json");
+        return;
+    }
+
+    GByte* pabyRet = NULL;
+    if( !VSIIngestFile( NULL, pszConfFile, &pabyRet, NULL, -1 ) )
+    {
+        return;
+    }
+
+    json_object* poRoot = NULL;
+    const char* pzText = reinterpret_cast<char*>(pabyRet);
+    if( !OGRJSonParse( pzText, &poRoot ) )
+    {
+        VSIFree(pabyRet);
+        return;
+    }
+    VSIFree(pabyRet);
+
+    json_object* poV1Data = CPL_json_object_object_get(poRoot, "v1_data");
+    if( poV1Data == NULL || json_object_get_type(poV1Data) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find v1_data object in plscenesconf.json");
+        json_object_put(poRoot);
+        return;
+    }
+
+    json_object* poItemType = CPL_json_object_object_get(poV1Data,
+                                                         GetDescription());
+    if( poItemType == NULL ||
+        json_object_get_type(poItemType) != json_type_object )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find v1_data.%s object in plscenesconf.json",
+                 GetDescription());
+        json_object_put(poRoot);
+        return;
+    }
+
+    json_object* poFields = CPL_json_object_object_get(poItemType, "fields");
+    if( poFields == NULL ||
+        json_object_get_type(poFields) != json_type_array )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Cannot find v1_data.%s.fields object in plscenesconf.json",
+                 GetDescription());
+        json_object_put(poRoot);
+        return;
+    }
+
+    {
+        OGRFieldDefn oFieldDefn("id", OFTString);
+        RegisterField(&oFieldDefn, "id", "id");
+    }
+    const int nFields = json_object_array_length(poFields);
+    for( int i=0; i<nFields; i++ )
+    {
+        json_object* poField = json_object_array_get_idx(poFields, i);
+        if( poField && json_object_get_type(poField) == json_type_object )
+        {
+            json_object* poName = CPL_json_object_object_get(poField, "name");
+            json_object* poType = CPL_json_object_object_get(poField, "type");
+            if( poName && json_object_get_type(poName) == json_type_string &&
+                poType && json_object_get_type(poType) == json_type_string )
+            {
+                const char* pszName = json_object_get_string(poName);
+                const char* pszType = json_object_get_string(poType);
+                OGRFieldType eType(OFTString);
+                if( EQUAL(pszType, "datetime") )
+                    eType = OFTDateTime;
+                else if( EQUAL(pszType, "double") )
+                    eType = OFTReal;
+                else if( EQUAL(pszType, "int") )
+                    eType = OFTInteger;
+                else if( EQUAL(pszType, "string") )
+                    eType = OFTString;
+                else
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                             "Unrecognized field type %s for field %s",
+                             pszType, pszName);
+                }
+                OGRFieldDefn oFieldDefn(pszName, eType);
+                RegisterField(&oFieldDefn, pszName,
+                              (CPLString("properties.") + pszName).c_str());
+            }
+        }
+    }
+
+    {
+        OGRFieldDefn oFieldDefn("self_link", OFTString);
+        RegisterField(&oFieldDefn, NULL, "_links._self");
+    }
+
+    {
+        OGRFieldDefn oFieldDefn("assets_link", OFTString);
+        RegisterField(&oFieldDefn, NULL, "_links.assets");
+    }
+
+    {
+        OGRFieldDefn oFieldDefn("permissions", OFTStringList);
+        RegisterField(&oFieldDefn, NULL, "_permissions");
+    }
+
+    if( m_poDS->DoesFollowLinks() )
+    {
+        json_object* poAssets = CPL_json_object_object_get(poItemType, "assets");
+        if( poAssets == NULL ||
+            json_object_get_type(poAssets) != json_type_array )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "Cannot find v1_data.%s.assets object in plscenesconf.json",
+                    GetDescription());
+            json_object_put(poRoot);
+            return;
+        }
+
+        const int nAssets = json_object_array_length(poAssets);
+        for( int i=0; i<nAssets; i++ )
+        {
+            json_object* poAsset = json_object_array_get_idx(poAssets, i);
+            if( poAsset && json_object_get_type(poAsset) == json_type_string )
+            {
+                const char* pszAsset = json_object_get_string(poAsset);
+                m_oSetAssets.insert(pszAsset);
+
+                {
+                    CPLString osName("asset_");
+                    osName += pszAsset;
+                    osName += "_self_link";
+                    OGRFieldDefn oFieldDefn(osName, OFTString);
+                    RegisterField(&oFieldDefn, NULL,
+                                  CPLSPrintf("/assets.%s._links._self", pszAsset));
+                }
+                {
+                    CPLString osName("asset_");
+                    osName += pszAsset;
+                    osName += "_activate_link";
+                    OGRFieldDefn oFieldDefn(osName, OFTString);
+                    RegisterField(&oFieldDefn, NULL,
+                                  CPLSPrintf("/assets.%s._links.activate", pszAsset));
+                }
+                {
+                    CPLString osName("asset_");
+                    osName += pszAsset;
+                    osName += "_permissions";
+                    OGRFieldDefn oFieldDefn(osName, OFTStringList);
+                    RegisterField(&oFieldDefn, NULL,
+                                  CPLSPrintf("/assets.%s._permissions", pszAsset));
+                }
+                {
+                    CPLString osName("asset_");
+                    osName += pszAsset;
+                    osName += "_expires_at";
+                    OGRFieldDefn oFieldDefn(osName, OFTDateTime);
+                    RegisterField(&oFieldDefn, NULL,
+                                  CPLSPrintf("/assets.%s.expires_at", pszAsset));
+                }
+                {
+                    CPLString osName("asset_");
+                    osName += pszAsset;
+                    osName += "_location";
+                    OGRFieldDefn oFieldDefn(osName, OFTString);
+                    RegisterField(&oFieldDefn, NULL,
+                                  CPLSPrintf("/assets.%s.location", pszAsset));
+                }
+                {
+                    CPLString osName("asset_");
+                    osName += pszAsset;
+                    osName += "_status";
+                    OGRFieldDefn oFieldDefn(osName, OFTString);
+                    RegisterField(&oFieldDefn, NULL,
+                                  CPLSPrintf("/assets.%s.status", pszAsset));
+                }
+            }
+        }
+    }
+
+    json_object_put(poRoot);
+}
+
+/************************************************************************/
+/*                             GetMetadata()                            */
+/************************************************************************/
+
+char **OGRPLScenesDataV1Layer::GetMetadata( const char * pszDomain  )
+{
+    if( pszDomain == NULL || EQUAL(pszDomain, "") )
+    {
+        EstablishLayerDefn();
+    }
+    return OGRLayer::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                           GetMetadataItem()                          */
+/************************************************************************/
+
+const char *OGRPLScenesDataV1Layer::GetMetadataItem( const char * pszName, const char* pszDomain )
+{
+    if( pszDomain == NULL || EQUAL(pszDomain, "") )
+    {
+        EstablishLayerDefn();
+    }
+    return OGRLayer::GetMetadataItem(pszName, pszDomain);
+}
+
+/************************************************************************/
+/*                              GetNextPage()                           */
+/************************************************************************/
+
+bool OGRPLScenesDataV1Layer::GetNextPage()
+{
+    if( m_poPageObj != NULL )
+        json_object_put(m_poPageObj);
+    m_poPageObj = NULL;
+    m_poFeatures = NULL;
+    m_nFeatureIdx = 0;
+
+    if( m_osRequestURL.empty() )
+    {
+        m_bEOF = true;
+        return false;
+    }
+
+    json_object* poObj;
+    if (m_osRequestURL.find(m_poDS->GetBaseURL() + "quick-search?_page_size") == 0 )
+    {
+        CPLString osFilter(m_poDS->GetFilter());
+        if( osFilter.empty() )
+        {
+            json_object* poFilterRoot = json_object_new_object();
+            json_object* poItemTypes = json_object_new_array();
+            json_object_array_add(poItemTypes,
+                                  json_object_new_string(GetName()));
+            json_object_object_add(poFilterRoot, "item_types", poItemTypes);
+            json_object* poFilter = json_object_new_object();
+            json_object_object_add(poFilterRoot, "filter", poFilter);
+            json_object_object_add(poFilter, "type",
+                                   json_object_new_string("AndFilter"));
+            json_object* poConfig = json_object_new_array();
+            json_object_object_add(poFilter, "config", poConfig);
+
+            if( m_poFilterGeom != NULL )
+            {
+                json_object* poGeomFilter = json_object_new_object();
+                json_object_array_add(poConfig, poGeomFilter);
+                json_object_object_add(poGeomFilter, "type",
+                                   json_object_new_string("GeometryFilter"));
+                json_object_object_add(poGeomFilter, "field_name",
+                                   json_object_new_string("geometry"));
+                OGRGeoJSONWriteOptions oOptions;
+                json_object* poGeoJSONGeom =
+                            OGRGeoJSONWriteGeometry( m_poFilterGeom, oOptions );
+                json_object_object_add(poGeomFilter, "config",
+                                       poGeoJSONGeom);
+            }
+            if( m_poAttributeFilter != NULL )
+            {
+                json_object_get(m_poAttributeFilter);
+                json_object_array_add(poConfig, m_poAttributeFilter);
+            }
+
+            osFilter = json_object_to_json_string_ext(poFilterRoot, 0);
+            json_object_put(poFilterRoot);
+        }
+        poObj = m_poDS->RunRequest(m_osRequestURL, FALSE, "POST", true,
+                                   osFilter);
+    }
+    else
+    {
+        poObj = m_poDS->RunRequest(m_osRequestURL);
+    }
+    if( poObj == NULL )
+    {
+        m_bEOF = true;
+        return false;
+    }
+
+    json_object* poFeatures = CPL_json_object_object_get(poObj, "features");
+    if( poFeatures == NULL ||
+        json_object_get_type(poFeatures) != json_type_array ||
+        json_object_array_length(poFeatures) == 0 )
+    {
+        // If this is a single item, then wrap it in a features array
+        json_object* poProperties = CPL_json_object_object_get(poObj, "properties");
+        if( poProperties != NULL )
+        {
+            m_poPageObj = json_object_new_object();
+            poFeatures = json_object_new_array();
+            json_object_array_add(poFeatures, poObj);
+            json_object_object_add(m_poPageObj, "features", poFeatures);
+            poObj = m_poPageObj;
+        }
+        else
+        {
+            json_object_put(poObj);
+            m_bEOF = true;
+            return false;
+        }
+    }
+
+    m_poPageObj = poObj;
+    m_poFeatures = poFeatures;
+
+    // Get URL of next page
+    m_osNextURL = "";
+    json_object* poLinks = CPL_json_object_object_get(poObj, "_links");
+    if( poLinks && json_object_get_type(poLinks) == json_type_object )
+    {
+        json_object* poNext = CPL_json_object_object_get(poLinks, "_next");
+        if( poNext && json_object_get_type(poNext) == json_type_string )
+        {
+            m_osNextURL = json_object_get_string(poNext);
+        }
+    }
+
+    return true;
+}
+
+/************************************************************************/
+/*                             ResetReading()                           */
+/************************************************************************/
+
+void OGRPLScenesDataV1Layer::ResetReading()
+{
+    m_bEOF = false;
+
+    if( m_poFeatures != NULL && m_bStillInFirstPage )
+        m_nFeatureIdx = 0;
+    else
+        m_poFeatures = NULL;
+    m_nNextFID = 1;
+    m_bStillInFirstPage = true;
+    m_osRequestURL = m_poDS->GetBaseURL() +
+                        CPLSPrintf("quick-search?_page_size=%d", m_nPageSize);
+}
+
+/************************************************************************/
+/*                          SetSpatialFilter()                          */
+/************************************************************************/
+
+void OGRPLScenesDataV1Layer::SetSpatialFilter(  OGRGeometry *poGeomIn )
+{
+    m_poFeatures = NULL;
+
+    if( poGeomIn )
+    {
+        OGREnvelope sEnvelope;
+        poGeomIn->getEnvelope(&sEnvelope);
+        if( sEnvelope.MinX == sEnvelope.MaxX && sEnvelope.MinY == sEnvelope.MaxY )
+        {
+            OGRPoint p(sEnvelope.MinX, sEnvelope.MinY);
+            InstallFilter(&p);
+        }
+        else
+            InstallFilter( poGeomIn );
+    }
+    else
+        InstallFilter( poGeomIn );
+
+    ResetReading();
+}
+
+/************************************************************************/
+/*                      OGRPLScenesDataV1ParseDateTime()                    */
+/************************************************************************/
+
+static bool OGRPLScenesDataV1ParseDateTime(const char* pszValue,
+                                       int& nYear, int &nMonth, int &nDay,
+                                       int& nHour, int &nMinute, int &nSecond)
+{
+    return ( sscanf(pszValue,"%04d/%02d/%02d %02d:%02d:%02d",
+                    &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond) >= 3 ||
+             sscanf(pszValue,"%04d-%02d-%02dT%02d:%02d:%02d",
+                    &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond) >= 3 );
+}
+
+/************************************************************************/
+/*                          IsSimpleComparison()                        */
+/************************************************************************/
+
+bool OGRPLScenesDataV1Layer::IsSimpleComparison(const swq_expr_node* poNode)
+{
+    return  poNode->eNodeType == SNT_OPERATION &&
+            (poNode->nOperation == SWQ_EQ ||
+             poNode->nOperation == SWQ_NE ||
+             poNode->nOperation == SWQ_LT ||
+             poNode->nOperation == SWQ_LE ||
+             poNode->nOperation == SWQ_GT ||
+             poNode->nOperation == SWQ_GE) &&
+             poNode->nSubExprCount == 2 &&
+             poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+             poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+             m_oMapFieldIdxToQueriableJSonFieldName.find(
+                                    poNode->papoSubExpr[0]->field_index) !=
+                                m_oMapFieldIdxToQueriableJSonFieldName.end();
+}
+
+/************************************************************************/
+/*                             GetOperatorText()                        */
+/************************************************************************/
+
+static const char* GetOperatorText(int nOp)
+{
+    if( nOp == SWQ_LT )
+        return "lt";
+    if( nOp == SWQ_LE )
+            return "lte";
+    if( nOp == SWQ_GT )
+            return "gt";
+    if( nOp == SWQ_GE )
+            return "gte";
+    CPLAssert(false);
+    return "";
+}
+
+/************************************************************************/
+/*                             BuildFilter()                            */
+/************************************************************************/
+
+json_object* OGRPLScenesDataV1Layer::BuildFilter(swq_expr_node* poNode)
+{
+    if( poNode->eNodeType == SNT_OPERATION &&
+        poNode->nOperation == SWQ_AND && poNode->nSubExprCount == 2 )
+    {
+         // For AND, we can deal with a failure in one of the branch
+        // since client-side will do that extra filtering
+        json_object* poFilter1 = BuildFilter(poNode->papoSubExpr[0]);
+        json_object* poFilter2 = BuildFilter(poNode->papoSubExpr[1]);
+        if( poFilter1 && poFilter2 )
+        {
+            json_object* poFilter = json_object_new_object();
+            json_object_object_add(poFilter, "type",
+                                   json_object_new_string("AndFilter"));
+            json_object* poConfig = json_object_new_array();
+            json_object_object_add(poFilter, "config", poConfig);
+            json_object_array_add(poConfig, poFilter1);
+            json_object_array_add(poConfig, poFilter2);
+            return poFilter;
+        }
+        else if( poFilter1 )
+            return poFilter1;
+        else
+            return poFilter2;
+    }
+    else if( poNode->eNodeType == SNT_OPERATION &&
+             poNode->nOperation == SWQ_OR && poNode->nSubExprCount == 2 )
+    {
+         // For OR, we need both members to be valid
+        json_object* poFilter1 = BuildFilter(poNode->papoSubExpr[0]);
+        json_object* poFilter2 = BuildFilter(poNode->papoSubExpr[1]);
+        if( poFilter1 && poFilter2 )
+        {
+            json_object* poFilter = json_object_new_object();
+            json_object_object_add(poFilter, "type",
+                                   json_object_new_string("OrFilter"));
+            json_object* poConfig = json_object_new_array();
+            json_object_object_add(poFilter, "config", poConfig);
+            json_object_array_add(poConfig, poFilter1);
+            json_object_array_add(poConfig, poFilter2);
+            return poFilter;
+        }
+        else
+        {
+            if( poFilter1 )
+                json_object_put(poFilter1);
+            if( poFilter2 )
+                json_object_put(poFilter2);
+            return NULL;
+        }
+    }
+    else if( poNode->eNodeType == SNT_OPERATION &&
+             poNode->nOperation == SWQ_NOT && poNode->nSubExprCount == 1 )
+    {
+        json_object* poFilter1 = BuildFilter(poNode->papoSubExpr[0]);
+        if( poFilter1 )
+        {
+            json_object* poFilter = json_object_new_object();
+            json_object_object_add(poFilter, "type",
+                                   json_object_new_string("NotFilter"));
+            json_object_object_add(poFilter, "config", poFilter1);
+            return poFilter;
+        }
+        else
+        {
+            return NULL;
+        }
+    }
+    else if( IsSimpleComparison(poNode) )
+    {
+        int nYear = 0, nMonth = 0, nDay = 0, nHour = 0, nMinute = 0, nSecond = 0;
+        const int nFieldIdx = poNode->papoSubExpr[0]->field_index;
+        if( poNode->nOperation == SWQ_NE )
+        {
+            poNode->nOperation = SWQ_EQ;
+            json_object* poFilter1 = BuildFilter(poNode);
+            poNode->nOperation = SWQ_NE;
+            if( poFilter1 )
+            {
+                json_object* poFilter = json_object_new_object();
+                json_object_object_add(poFilter, "type",
+                                       json_object_new_string("NotFilter"));
+                json_object_object_add(poFilter, "config", poFilter1);
+                return poFilter;
+            }
+            else
+            {
+                return NULL;
+            }
+        }
+        else if( poNode->nOperation == SWQ_EQ &&
+                 (m_poFeatureDefn->GetFieldDefn(nFieldIdx)->GetType() == OFTInteger ||
+                  m_poFeatureDefn->GetFieldDefn(nFieldIdx)->GetType() == OFTReal) &&
+                 (poNode->papoSubExpr[1]->field_type == SWQ_INTEGER ||
+                  poNode->papoSubExpr[1]->field_type == SWQ_FLOAT) )
+        {
+            json_object* poFilter = json_object_new_object();
+            if( m_poFeatureDefn->GetFieldDefn(nFieldIdx)->GetType() == OFTReal )
+            {
+                json_object_object_add(poFilter, "type",
+                                    json_object_new_string("RangeFilter"));
+                json_object_object_add(poFilter, "field_name",
+                                    json_object_new_string(
+                                        m_oMapFieldIdxToQueriableJSonFieldName[nFieldIdx]));
+                json_object* poConfig = json_object_new_object();
+                const double EPS = 1e-8;
+                json_object_object_add(poConfig, "gte",
+                    (poNode->papoSubExpr[1]->field_type == SWQ_INTEGER) ?
+                        json_object_new_double(poNode->papoSubExpr[1]->int_value - EPS) :
+                        json_object_new_double(poNode->papoSubExpr[1]->float_value - EPS));
+                json_object_object_add(poConfig, "lte",
+                    (poNode->papoSubExpr[1]->field_type == SWQ_INTEGER) ?
+                        json_object_new_double(poNode->papoSubExpr[1]->int_value + EPS) :
+                        json_object_new_double(poNode->papoSubExpr[1]->float_value + EPS));
+                json_object_object_add(poFilter, "config", poConfig);
+            }
+            else
+            {
+                json_object_object_add(poFilter, "type",
+                                    json_object_new_string("NumberInFilter"));
+                json_object_object_add(poFilter, "field_name",
+                                    json_object_new_string(
+                                        m_oMapFieldIdxToQueriableJSonFieldName[nFieldIdx]));
+                json_object* poConfig = json_object_new_array();
+                json_object_array_add(poConfig,
+                    (poNode->papoSubExpr[1]->field_type == SWQ_INTEGER) ?
+                        json_object_new_int64(poNode->papoSubExpr[1]->int_value) :
+                        json_object_new_double(poNode->papoSubExpr[1]->float_value));
+                json_object_object_add(poFilter, "config", poConfig);
+            }
+            return poFilter;
+        }
+        else if( poNode->nOperation == SWQ_EQ &&
+                 m_poFeatureDefn->GetFieldDefn(nFieldIdx)->GetType() == OFTString &&
+                 poNode->papoSubExpr[1]->field_type == SWQ_STRING )
+        {
+            json_object* poFilter = json_object_new_object();
+            json_object_object_add(poFilter, "type",
+                                json_object_new_string("StringInFilter"));
+            json_object_object_add(poFilter, "field_name",
+                        json_object_new_string(
+                            m_oMapFieldIdxToQueriableJSonFieldName[nFieldIdx]));
+            json_object* poConfig = json_object_new_array();
+            json_object_array_add(poConfig,
+                json_object_new_string(poNode->papoSubExpr[1]->string_value));
+            json_object_object_add(poFilter, "config", poConfig);
+            return poFilter;
+        }
+        else if( (poNode->nOperation == SWQ_LT ||
+                  poNode->nOperation == SWQ_LE ||
+                  poNode->nOperation == SWQ_GT ||
+                  poNode->nOperation == SWQ_GE) &&
+                 (m_poFeatureDefn->GetFieldDefn(nFieldIdx)->GetType() == OFTInteger ||
+                  m_poFeatureDefn->GetFieldDefn(nFieldIdx)->GetType() == OFTReal) &&
+                 (poNode->papoSubExpr[1]->field_type == SWQ_INTEGER ||
+                  poNode->papoSubExpr[1]->field_type == SWQ_FLOAT) )
+        {
+            json_object* poFilter = json_object_new_object();
+            json_object_object_add(poFilter, "type",
+                                   json_object_new_string("RangeFilter"));
+            json_object_object_add(poFilter, "field_name",
+                                   json_object_new_string(
+                                       m_oMapFieldIdxToQueriableJSonFieldName[nFieldIdx]));
+            json_object* poConfig = json_object_new_object();
+            json_object_object_add(poConfig,
+                GetOperatorText(poNode->nOperation),
+                (poNode->papoSubExpr[1]->field_type == SWQ_INTEGER) ?
+                    json_object_new_int64(poNode->papoSubExpr[1]->int_value) :
+                    json_object_new_double(poNode->papoSubExpr[1]->float_value));
+            json_object_object_add(poFilter, "config", poConfig);
+            return poFilter;
+        }
+        else if( (poNode->nOperation == SWQ_LT ||
+                  poNode->nOperation == SWQ_LE ||
+                  poNode->nOperation == SWQ_GT ||
+                  poNode->nOperation == SWQ_GE) &&
+                 m_poFeatureDefn->GetFieldDefn(nFieldIdx)->GetType() == OFTDateTime &&
+                 poNode->papoSubExpr[1]->field_type == SWQ_TIMESTAMP &&
+                 OGRPLScenesDataV1ParseDateTime(poNode->papoSubExpr[1]->string_value,
+                    nYear, nMonth, nDay, nHour, nMinute, nSecond) )
+        {
+            json_object* poFilter = json_object_new_object();
+            json_object_object_add(poFilter, "type",
+                                   json_object_new_string("DateRangeFilter"));
+            json_object_object_add(poFilter, "field_name",
+                    json_object_new_string(
+                        m_oMapFieldIdxToQueriableJSonFieldName[nFieldIdx]));
+            json_object* poConfig = json_object_new_object();
+            json_object_object_add(poConfig,
+                GetOperatorText(poNode->nOperation),
+                json_object_new_string(
+                    CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ",
+                                nYear, nMonth, nDay, nHour, nMinute, nSecond)));
+            json_object_object_add(poFilter, "config", poConfig);
+            return poFilter;
+        }
+    }
+    else if ( poNode->eNodeType == SNT_OPERATION &&
+              poNode->nOperation == SWQ_IN &&
+              poNode->nSubExprCount >= 2 &&
+              poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+              m_oMapFieldIdxToQueriableJSonFieldName.find(
+                                    poNode->papoSubExpr[0]->field_index) !=
+                                m_oMapFieldIdxToQueriableJSonFieldName.end() )
+    {
+        const int nFieldIdx = poNode->papoSubExpr[0]->field_index;
+        if( m_poFeatureDefn->GetFieldDefn(nFieldIdx)->GetType() == OFTString )
+        {
+            json_object* poFilter = json_object_new_object();
+            json_object_object_add(poFilter, "type",
+                                json_object_new_string("StringInFilter"));
+            json_object_object_add(poFilter, "field_name",
+                        json_object_new_string(
+                            m_oMapFieldIdxToQueriableJSonFieldName[nFieldIdx]));
+            json_object* poConfig = json_object_new_array();
+            json_object_object_add(poFilter, "config", poConfig);
+            for( int i=1; i<poNode->nSubExprCount;i++)
+            {
+                if( poNode->papoSubExpr[i]->eNodeType != SNT_CONSTANT ||
+                    poNode->papoSubExpr[i]->field_type != SWQ_STRING )
+                {
+                    json_object_put(poFilter);
+                    m_bFilterMustBeClientSideEvaluated = true;
+                    return NULL;
+                }
+                json_object_array_add(poConfig, json_object_new_string(
+                                    poNode->papoSubExpr[i]->string_value));
+            }
+            return poFilter;
+        }
+        else if( m_poFeatureDefn->GetFieldDefn(nFieldIdx)->GetType() == OFTInteger )
+        {
+            json_object* poFilter = json_object_new_object();
+            json_object_object_add(poFilter, "type",
+                                json_object_new_string("NumberInFilter"));
+            json_object_object_add(poFilter, "field_name",
+                        json_object_new_string(
+                            m_oMapFieldIdxToQueriableJSonFieldName[nFieldIdx]));
+            json_object* poConfig = json_object_new_array();
+            json_object_object_add(poFilter, "config", poConfig);
+            for( int i=1; i<poNode->nSubExprCount;i++)
+            {
+                if( poNode->papoSubExpr[i]->eNodeType != SNT_CONSTANT ||
+                    poNode->papoSubExpr[i]->field_type != SWQ_INTEGER )
+                {
+                    json_object_put(poFilter);
+                    m_bFilterMustBeClientSideEvaluated = true;
+                    return NULL;
+                }
+                json_object_array_add(poConfig, json_object_new_int64(
+                                    poNode->papoSubExpr[i]->int_value));
+            }
+            return poFilter;
+        }
+    }
+    else if( poNode->eNodeType == SNT_OPERATION &&
+             poNode->nOperation == SWQ_EQ &&
+             poNode->nSubExprCount == 2 &&
+             poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+             poNode->papoSubExpr[1]->eNodeType == SNT_CONSTANT &&
+             poNode->papoSubExpr[0]->field_index ==
+                           m_poFeatureDefn->GetFieldIndex("permissions") &&
+             poNode->papoSubExpr[1]->field_type == SWQ_STRING )
+    {
+        json_object* poFilter = json_object_new_object();
+        json_object_object_add(poFilter, "type",
+                            json_object_new_string("PermissionFilter"));
+        json_object* poConfig = json_object_new_array();
+        json_object_object_add(poFilter, "config", poConfig);
+        json_object_array_add(poConfig, json_object_new_string(
+                                poNode->papoSubExpr[1]->string_value));
+        return poFilter;
+    }
+    else if( poNode->eNodeType == SNT_OPERATION &&
+             poNode->nOperation == SWQ_IN &&
+             poNode->nSubExprCount >= 2 &&
+             poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
+             poNode->papoSubExpr[0]->field_index ==
+                            m_poFeatureDefn->GetFieldIndex("permissions") )
+    {
+        json_object* poFilter = json_object_new_object();
+        json_object_object_add(poFilter, "type",
+                            json_object_new_string("PermissionFilter"));
+        json_object* poConfig = json_object_new_array();
+        json_object_object_add(poFilter, "config", poConfig);
+        for( int i=1; i<poNode->nSubExprCount;i++)
+        {
+            if( poNode->papoSubExpr[i]->eNodeType != SNT_CONSTANT ||
+                poNode->papoSubExpr[i]->field_type != SWQ_STRING )
+            {
+                json_object_put(poFilter);
+                m_bFilterMustBeClientSideEvaluated = true;
+                return NULL;
+            }
+            json_object_array_add(poConfig, json_object_new_string(
+                                    poNode->papoSubExpr[i]->string_value));
+        }
+        return poFilter;
+    }
+
+    m_bFilterMustBeClientSideEvaluated = true;
+    return NULL;
+}
+
+/************************************************************************/
+/*                         SetAttributeFilter()                         */
+/************************************************************************/
+
+OGRErr OGRPLScenesDataV1Layer::SetAttributeFilter( const char *pszQuery )
+
+{
+    m_poFeatures = NULL;
+
+    OGRErr eErr = OGRLayer::SetAttributeFilter(pszQuery);
+
+    if( m_poAttributeFilter )
+        json_object_put(m_poAttributeFilter);
+    m_poAttributeFilter = NULL;
+    m_bFilterMustBeClientSideEvaluated = false;
+    if( m_poAttrQuery != NULL )
+    {
+        swq_expr_node* poNode = (swq_expr_node*) m_poAttrQuery->GetSWQExpr();
+
+        poNode->ReplaceBetweenByGEAndLERecurse();
+
+        m_poAttributeFilter = BuildFilter(poNode);
+        if( m_poAttributeFilter == NULL )
+        {
+            CPLDebug("PLSCENES",
+                        "Full filter will be evaluated on client side.");
+        }
+        else if( m_bFilterMustBeClientSideEvaluated )
+        {
+            CPLDebug("PLSCENES",
+                "Only part of the filter will be evaluated on server side.");
+        }
+    }
+
+    ResetReading();
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                           GetNextFeature()                           */
+/************************************************************************/
+
+OGRFeature *OGRPLScenesDataV1Layer::GetNextFeature()
+{
+    while( true )
+    {
+        OGRFeature  *poFeature = GetNextRawFeature();
+        if (poFeature == NULL)
+            return NULL;
+
+        if( m_poAttrQuery == NULL ||
+            !m_bFilterMustBeClientSideEvaluated ||
+            m_poAttrQuery->Evaluate( poFeature ) )
+        {
+            return poFeature;
+        }
+        else
+        {
+            delete poFeature;
+        }
+    }
+}
+
+/************************************************************************/
+/*                            GetNextRawFeature()                       */
+/************************************************************************/
+
+OGRFeature* OGRPLScenesDataV1Layer::GetNextRawFeature()
+{
+    EstablishLayerDefn();
+    if( m_bEOF )
+        return NULL;
+
+    if( m_poFeatures == NULL )
+    {
+        if( !GetNextPage() )
+            return NULL;
+    }
+
+    if( m_nFeatureIdx == json_object_array_length(m_poFeatures) )
+    {
+        if( m_nFeatureIdx < m_nPageSize &&
+            m_poDS->GetBaseURL().find("/vsimem/") != 0  )
+        {
+            return NULL;
+        }
+        m_osRequestURL = m_osNextURL;
+        m_bStillInFirstPage = false;
+        if( !GetNextPage() )
+            return NULL;
+    }
+    json_object* poJSonFeature = json_object_array_get_idx(m_poFeatures, m_nFeatureIdx);
+    m_nFeatureIdx ++;
+    if( poJSonFeature == NULL || json_object_get_type(poJSonFeature) != json_type_object )
+    {
+        m_bEOF = true;
+        return NULL;
+    }
+
+    OGRFeature* poFeature = new OGRFeature(m_poFeatureDefn);
+    poFeature->SetFID(m_nNextFID++);
+
+    json_object* poJSonGeom = CPL_json_object_object_get(poJSonFeature, "geometry");
+    if( poJSonGeom != NULL && json_object_get_type(poJSonGeom) == json_type_object )
+    {
+        OGRGeometry* poGeom = OGRGeoJSONReadGeometry(poJSonGeom);
+        if( poGeom != NULL )
+        {
+            if( poGeom->getGeometryType() == wkbPolygon )
+            {
+                OGRMultiPolygon* poMP = new OGRMultiPolygon();
+                poMP->addGeometryDirectly(poGeom);
+                poGeom = poMP;
+            }
+            poGeom->assignSpatialReference(m_poSRS);
+            poFeature->SetGeometryDirectly(poGeom);
+        }
+    }
+
+    json_object* poId = CPL_json_object_object_get(poJSonFeature, "id");
+    if( poId != NULL && json_object_get_type(poId) == json_type_string )
+    {
+        std::map<CPLString, int>::const_iterator oIter =
+            m_oMapPrefixedJSonFieldNameToFieldIdx.find("id");
+        if( oIter != m_oMapPrefixedJSonFieldNameToFieldIdx.end() )
+        {
+            const int iField = oIter->second;
+            poFeature->SetField(iField, json_object_get_string(poId));
+        }
+    }
+
+    json_object* poPermissions =
+        CPL_json_object_object_get(poJSonFeature, "_permissions");
+    if( poPermissions != NULL &&
+        json_object_get_type(poPermissions) == json_type_array )
+    {
+        std::map<CPLString, int>::const_iterator oIter =
+                m_oMapPrefixedJSonFieldNameToFieldIdx.find("_permissions");
+        if( oIter != m_oMapPrefixedJSonFieldNameToFieldIdx.end() )
+        {
+            const int iField = oIter->second;
+            const int nStrings = json_object_array_length(poPermissions);
+            char** papszPermissions =
+                static_cast<char**>(CPLCalloc(nStrings+1, sizeof(char*)));
+            for(int i=0, j=0;i<nStrings;i++)
+            {
+                json_object* poPerm = json_object_array_get_idx(poPermissions,i);
+                if( poPerm && json_object_get_type(poPerm) == json_type_string )
+                {
+                    papszPermissions[j++] =
+                        CPLStrdup(json_object_get_string(poPerm));
+                }
+            }
+            poFeature->SetField(iField, papszPermissions);
+            CSLDestroy(papszPermissions);
+        }
+    }
+
+    for(int i=0;i<2;i++)
+    {
+        const char* pszFeaturePart = (i == 0) ? "properties": "_links";
+        json_object* poProperties =
+                CPL_json_object_object_get(poJSonFeature, pszFeaturePart);
+        if( poProperties != NULL &&
+            json_object_get_type(poProperties) == json_type_object )
+        {
+            json_object_iter it;
+            it.key = NULL;
+            it.val = NULL;
+            it.entry = NULL;
+            json_object_object_foreachC( poProperties, it )
+            {
+                CPLString osPrefixedJSonFieldName(pszFeaturePart);
+                osPrefixedJSonFieldName += ".";
+                osPrefixedJSonFieldName += it.key;
+                if( !SetFieldFromPrefixedJSonFieldName(
+                        poFeature, osPrefixedJSonFieldName, it.val) )
+                {
+                    if( i == 0 &&
+                        m_oSetUnregisteredFields.find(osPrefixedJSonFieldName)
+                            == m_oSetUnregisteredFields.end() )
+                    {
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "Field %s found in data but not "
+                                 "in configuration",
+                                 osPrefixedJSonFieldName.c_str());
+                        m_oSetUnregisteredFields.insert(
+                                                osPrefixedJSonFieldName);
+                    }
+                }
+            }
+        }
+    }
+
+    json_object* poAssets = NULL;
+    if( m_poDS->DoesFollowLinks() &&
+        (!m_bInFeatureCountOrGetExtent || m_poAttrQuery != NULL)  )
+    {
+        std::map<CPLString, int>::const_iterator oIter =
+                m_oMapPrefixedJSonFieldNameToFieldIdx.find("_links.assets");
+        if( oIter != m_oMapPrefixedJSonFieldNameToFieldIdx.end() )
+        {
+            const int iField = oIter->second;
+            if( poFeature->IsFieldSetAndNotNull( iField ) )
+            {
+                const char* pszAssetURL = poFeature->GetFieldAsString( iField );
+                poAssets = m_poDS->RunRequest(pszAssetURL);
+            }
+        }
+    }
+    if( poAssets != NULL )
+    {
+        json_object_iter itAsset;
+        itAsset.key = NULL;
+        itAsset.val = NULL;
+        itAsset.entry = NULL;
+        json_object_object_foreachC( poAssets, itAsset )
+        {
+            if( m_oSetAssets.find(itAsset.key) == m_oSetAssets.end() )
+            {
+                if( m_oSetUnregisteredAssets.find(itAsset.key) ==
+                                    m_oSetUnregisteredAssets.end() )
+                {
+                    CPLError(CE_Warning, CPLE_AppDefined,
+                                "Asset %s found in data but "
+                                "not in configuration",
+                                itAsset.key);
+                    m_oSetUnregisteredAssets.insert(itAsset.key);
+                }
+                continue;
+            }
+
+            json_object* poAsset = itAsset.val;
+            if( poAsset != NULL &&
+                json_object_get_type(poAsset) == json_type_object )
+            {
+                json_object_iter it;
+                it.key = NULL;
+                it.val = NULL;
+                it.entry = NULL;
+                json_object_object_foreachC( poAsset, it )
+                {
+                    if( it.val == NULL ) continue;
+                    CPLString osPrefixedJSonFieldName(
+                                    "/assets." + CPLString(itAsset.key));
+                    osPrefixedJSonFieldName += "." + CPLString(it.key);
+                    if( strcmp(it.key, "_links") == 0 &&
+                        json_object_get_type(it.val) == json_type_object )
+                    {
+                        if( CPL_json_object_object_get(it.val, "_self") != NULL )
+                        {
+                            CPLString osPrefixedJSonFieldNameNew(
+                                osPrefixedJSonFieldName + "._self");
+                            SetFieldFromPrefixedJSonFieldName(
+                                poFeature, osPrefixedJSonFieldNameNew,
+                                CPL_json_object_object_get(it.val, "_self"));
+                        }
+                        if( CPL_json_object_object_get(it.val, "activate") != NULL )
+                        {
+                            CPLString osPrefixedJSonFieldNameNew(
+                                osPrefixedJSonFieldName + ".activate");
+                            SetFieldFromPrefixedJSonFieldName(
+                                poFeature, osPrefixedJSonFieldNameNew,
+                                CPL_json_object_object_get(it.val, "activate"));
+                        }
+                    }
+                    else
+                    {
+                        SetFieldFromPrefixedJSonFieldName(
+                            poFeature, osPrefixedJSonFieldName, it.val);
+                    }
+                }
+            }
+        }
+        json_object_put(poAssets);
+    }
+
+    return poFeature;
+}
+
+/************************************************************************/
+/*                    SetFieldFromPrefixedJSonFieldName()               */
+/************************************************************************/
+
+bool OGRPLScenesDataV1Layer::SetFieldFromPrefixedJSonFieldName(
+                                  OGRFeature* poFeature,
+                                  const CPLString& osPrefixedJSonFieldName,
+                                  json_object* poVal )
+{
+    std::map<CPLString, int>::const_iterator oIter =
+        m_oMapPrefixedJSonFieldNameToFieldIdx.find(osPrefixedJSonFieldName);
+    if( poVal != NULL && oIter != m_oMapPrefixedJSonFieldNameToFieldIdx.end() )
+    {
+        const int iField = oIter->second;
+        json_type eJSonType = json_object_get_type(poVal);
+        if( eJSonType == json_type_int )
+        {
+            poFeature->SetField(iField,
+                    static_cast<GIntBig>(json_object_get_int64(poVal)));
+        }
+        else if( eJSonType == json_type_double )
+        {
+            poFeature->SetField(iField, json_object_get_double(poVal));
+        }
+        else if( eJSonType == json_type_string )
+        {
+            poFeature->SetField(iField, json_object_get_string(poVal));
+        }
+        else
+        {
+            poFeature->SetField(iField, json_object_to_json_string_ext( poVal, 0 ));
+        }
+        return true;
+    }
+    return false;
+}
+
+/************************************************************************/
+/*                          GetFeatureCount()                           */
+/************************************************************************/
+
+GIntBig OGRPLScenesDataV1Layer::GetFeatureCount(int bForce)
+{
+    if( m_poDS->GetFilter().empty() )
+    {
+        if( m_nTotalFeatures >= 0 &&
+            m_poFilterGeom == NULL && m_poAttrQuery == NULL )
+        {
+            return m_nTotalFeatures;
+        }
+
+        json_object* poFilterRoot = json_object_new_object();
+        json_object* poItemTypes = json_object_new_array();
+        json_object_array_add(poItemTypes,
+                                json_object_new_string(GetName()));
+        json_object_object_add(poFilterRoot, "interval",
+                                json_object_new_string("year"));
+        json_object_object_add(poFilterRoot, "item_types", poItemTypes);
+        json_object* poFilter = json_object_new_object();
+        json_object_object_add(poFilterRoot, "filter", poFilter);
+        json_object_object_add(poFilter, "type",
+                                json_object_new_string("AndFilter"));
+        json_object* poConfig = json_object_new_array();
+        json_object_object_add(poFilter, "config", poConfig);
+
+        // We need to put a dummy filter
+        if( m_poFilterGeom == NULL && m_poAttributeFilter == NULL )
+        {
+            json_object* poRangeFilter = json_object_new_object();
+            json_object_array_add(poConfig, poRangeFilter);
+            json_object_object_add(poRangeFilter, "type",
+                                json_object_new_string("RangeFilter"));
+            json_object_object_add(poRangeFilter, "field_name",
+                                json_object_new_string("cloud_cover"));
+            json_object* poRangeFilterConfig = json_object_new_object();
+            json_object_object_add(poRangeFilterConfig, "gte",
+                                   json_object_new_double(0.0));
+            json_object_object_add(poRangeFilter, "config",
+                                   poRangeFilterConfig);
+        }
+
+        if( m_poFilterGeom != NULL )
+        {
+            json_object* poGeomFilter = json_object_new_object();
+            json_object_array_add(poConfig, poGeomFilter);
+            json_object_object_add(poGeomFilter, "type",
+                                json_object_new_string("GeometryFilter"));
+            json_object_object_add(poGeomFilter, "field_name",
+                                json_object_new_string("geometry"));
+            OGRGeoJSONWriteOptions oOptions;
+            json_object* poGeoJSONGeom =
+                        OGRGeoJSONWriteGeometry( m_poFilterGeom, oOptions );
+            json_object_object_add(poGeomFilter, "config",
+                                    poGeoJSONGeom);
+        }
+        if( m_poAttributeFilter != NULL )
+        {
+            json_object_get(m_poAttributeFilter);
+            json_object_array_add(poConfig, m_poAttributeFilter);
+        }
+
+        CPLString osFilter = json_object_to_json_string_ext(poFilterRoot, 0);
+        json_object_put(poFilterRoot);
+
+        json_object* poObj = m_poDS->RunRequest(
+                                   (m_poDS->GetBaseURL() + "stats").c_str(),
+                                   FALSE, "POST", true,
+                                   osFilter);
+        if( poObj != NULL )
+        {
+            json_object* poBuckets =
+                                CPL_json_object_object_get(poObj, "buckets");
+            if( poBuckets && json_object_get_type(poBuckets) ==
+                                                            json_type_array )
+            {
+                GIntBig nRes = 0;
+                const int nBuckets = json_object_array_length(poBuckets);
+                for( int i=0; i<nBuckets;i++ )
+                {
+                    json_object* poBucket =
+                                json_object_array_get_idx(poBuckets, i);
+                    if( poBucket && json_object_get_type(poBucket) ==
+                                                            json_type_object )
+                    {
+                        json_object* poCount =
+                            CPL_json_object_object_get(poBucket, "count");
+                        if( poCount && json_object_get_type(poCount) ==
+                                                            json_type_int )
+                        {
+                            nRes += json_object_get_int64(poCount);
+                        }
+                    }
+                }
+                if( m_poFilterGeom == NULL && m_poAttrQuery == NULL )
+                    m_nTotalFeatures = nRes;
+
+                json_object_put(poObj);
+                return nRes;
+            }
+            json_object_put(poObj);
+        }
+    }
+
+    m_bInFeatureCountOrGetExtent = true;
+    GIntBig nRes = OGRLayer::GetFeatureCount(bForce);
+    m_bInFeatureCountOrGetExtent = false;
+    return nRes;
+}
+
+/************************************************************************/
+/*                                GetExtent()                           */
+/************************************************************************/
+
+OGRErr OGRPLScenesDataV1Layer::GetExtent( OGREnvelope *psExtent, int bForce )
+{
+    if( m_poFilterGeom != NULL )
+    {
+        m_bInFeatureCountOrGetExtent = true;
+        OGRErr eErr = OGRLayer::GetExtentInternal(0, psExtent, bForce);
+        m_bInFeatureCountOrGetExtent = false;
+        return eErr;
+    }
+
+    psExtent->MinX = -180;
+    psExtent->MinY = -90;
+    psExtent->MaxX = 180;
+    psExtent->MaxY = 90;
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
+/*                              TestCapability()                        */
+/************************************************************************/
+
+int OGRPLScenesDataV1Layer::TestCapability(const char* pszCap)
+{
+    if( EQUAL(pszCap, OLCFastFeatureCount) )
+        return !m_bFilterMustBeClientSideEvaluated;
+    if( EQUAL(pszCap, OLCStringsAsUTF8) )
+        return TRUE;
+    return FALSE;
+}
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp
index 9226d97..c6217d8 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrplscenesdriver.cpp 33915 2016-04-07 19:38:55Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  PlanetLabs scene driver
@@ -29,6 +28,8 @@
 
 #include "ogr_plscenes.h"
 
+CPL_CVSID("$Id: ogrplscenesdriver.cpp 37289 2017-02-03 18:42:21Z rouault $");
+
 /************************************************************************/
 /*                         OGRPLScenesIdentify()                        */
 /************************************************************************/
@@ -38,7 +39,6 @@ static int OGRPLScenesIdentify(GDALOpenInfo* poOpenInfo)
     return STARTS_WITH_CI(poOpenInfo->pszFilename, "PLSCENES:");
 }
 
-
 /************************************************************************/
 /*                            OGRPLScenesOpen()                         */
 /************************************************************************/
@@ -53,10 +53,12 @@ static GDALDataset* OGRPLScenesOpen(GDALOpenInfo* poOpenInfo)
     CPLString osVersion = CSLFetchNameValueDef(papszOptions, "version",
                 CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "VERSION", ""));
     CSLDestroy(papszOptions);
-    if( EQUAL(osVersion, "v0") || EQUAL(osVersion, "") )
+    if( EQUAL(osVersion, "v0"))
         return OGRPLScenesDataset::Open(poOpenInfo);
     if( EQUAL(osVersion, "v1") )
         return OGRPLScenesV1Dataset::Open(poOpenInfo);
+    if( EQUAL(osVersion, "data_v1") || EQUAL(osVersion, "")  )
+        return OGRPLScenesDataV1Dataset::Open(poOpenInfo);
     CPLError(CE_Failure, CPLE_AppDefined,
              "Unhandled API version: %s", osVersion.c_str());
     return NULL;
@@ -82,18 +84,20 @@ void RegisterOGRPLSCENES()
     poDriver->SetMetadataItem( GDAL_DMD_CONNECTION_PREFIX, "PLSCENES:" );
     poDriver->SetMetadataItem( GDAL_DMD_OPENOPTIONLIST,
 "<OpenOptionList>"
-"  <Option name='VERSION' type='string-select' description='API version' default='V0'>"
+"  <Option name='VERSION' type='string-select' description='API version' default='DATA_V1'>"
 "    <Value>V0</Value>"
 "    <Value>V1</Value>"
+"    <Value>DATA_V1</Value>"
 "  </Option>"
 "  <Option name='API_KEY' type='string' description='Account API key' required='true'/>"
-"  <Option name='FOLLOW_LINKS' type='boolean' description='Whether assets links should be followed for each scene (API v1 only)' default='NO'/>"
+"  <Option name='FOLLOW_LINKS' type='boolean' description='Whether assets links should be followed for each scene (API v1 / data v1 only)' default='NO'/>"
 "  <Option name='SCENE' type='string' description='Scene id (for raster fetching)'/>"
-"  <Option name='CATALOG' type='string' description='Catalog id (API v1 only, mandatory for raster fetching)'/>"
-"  <Option name='PRODUCT_TYPE' type='string' description='Product type/asset category. For v0 API: visual, analytic or thumb (for raster fetching)' default='visual'/>"
+"  <Option name='ITEMTYPES' alias='CATALOG' type='string' description='Catalog id (API v1 / data v1 only, mandatory for raster fetching)'/>"
+"  <Option name='ASSET' alias='PRODUCT_TYPE' type='string' description='Asset category/Product type. For v0 API: visual, analytic or thumb (for raster fetching)' default='visual'/>"
 "  <Option name='RANDOM_ACCESS' type='boolean' description='Whether raster should be accessed in random access mode (but with potentially not optimal throughput). If no, in-memory ingestion is done' default='YES'/>"
-"  <Option name='ACTIVATION_TIMEOUT' type='int' description='Number of seconds during which to wait for asset activation (API v1 only, raster)' default='3600'/>"
-"  <Option name='FILTER' type='string' description='Custom filter (API v1 only)'/>"
+"  <Option name='ACTIVATION_TIMEOUT' type='int' description='Number of seconds during which to wait for asset activation (API v1 / data v1 only, raster)' default='3600'/>"
+"  <Option name='FILTER' type='string' description='Custom filter (API v1 / data v1 only)'/>"
+"  <Option name='METADATA' type='boolean' description='(Raster only, API Data V1) Whether scene metadata should be fetched from the API and attached to the raster dataset' default='YES'/>"
 "</OpenOptionList>");
 
     poDriver->pfnOpen = OGRPLScenesOpen;
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp b/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
index c1889fb..021b596 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplsceneslayer.cpp
@@ -1,6 +1,4 @@
 /******************************************************************************
-ry
- * $Id: ogrplsceneslayer.cpp 35490 2016-09-19 12:24:14Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesLayer
@@ -29,9 +27,10 @@ ry
  ****************************************************************************/
 
 #include "ogr_plscenes.h"
+#include "ogrgeojsonreader.h"
 #include <algorithm>
 
-CPL_CVSID("$Id: ogrplsceneslayer.cpp 35490 2016-09-19 12:24:14Z rouault $");
+CPL_CVSID("$Id: ogrplsceneslayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 typedef struct
 {
@@ -90,41 +89,45 @@ static bool OGRPLScenesLayerFieldNameComparator(const CPLString& osFirst,
 /*                           OGRPLScenesLayer()                         */
 /************************************************************************/
 
-OGRPLScenesLayer::OGRPLScenesLayer(OGRPLScenesDataset* poDSIn,
-                                   const char* pszName,
-                                   const char* pszBaseURL,
-                                   json_object* poObjCount10)
+OGRPLScenesLayer::OGRPLScenesLayer( OGRPLScenesDataset* poDSIn,
+                                    const char* pszName,
+                                    const char* pszBaseURL,
+                                    json_object* poObjCount10 ) :
+    poDS(poDSIn),
+    osBaseURL(pszBaseURL),
+    poFeatureDefn(new OGRFeatureDefn(pszName)),
+    poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
+    bEOF(false),
+    nNextFID(1),
+    nFeatureCount(-1),
+    poGeoJSONDS(NULL),
+    poGeoJSONLayer(NULL),
+    poMainFilter(NULL),
+    nPageSize(atoi(CPLGetConfigOption("PLSCENES_PAGE_SIZE", "1000"))),
+    bStillInFirstPage(false),
+    bAcquiredAscending(-1),
+    bFilterMustBeClientSideEvaluated(false)
 {
-    this->poDS = poDSIn;
-    osBaseURL = pszBaseURL;
     SetDescription(pszName);
-    poFeatureDefn = new OGRFeatureDefn(pszName);
     poFeatureDefn->SetGeomType(wkbMultiPolygon);
-    for(int i = 0; i < (int)sizeof(apsAttrs) / (int)sizeof(apsAttrs[0]); i++)
+    for( int i = 0;
+         i < static_cast<int>(sizeof(apsAttrs)) /
+             static_cast<int>(sizeof(apsAttrs[0]));
+         i++ )
     {
         OGRFieldDefn oField(apsAttrs[i].pszName, apsAttrs[i].eType);
         poFeatureDefn->AddFieldDefn(&oField);
     }
     poFeatureDefn->Reference();
-    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
-    bEOF = FALSE;
-    nFeatureCount = -1;
-    nNextFID = 1;
-    poGeoJSONDS = NULL;
-    poGeoJSONLayer = NULL;
-    poMainFilter = NULL;
-    nPageSize = atoi(CPLGetConfigOption("PLSCENES_PAGE_SIZE", "1000"));
-    bStillInFirstPage = FALSE;
-    bAcquiredAscending = -1;
-    bFilterMustBeClientSideEvaluated = FALSE;
     ResetReading();
 
     if( poObjCount10 != NULL )
     {
-        json_object* poCount = json_object_object_get(poObjCount10, "count");
+        json_object* poCount = CPL_json_object_object_get(poObjCount10, "count");
         if( poCount != NULL )
-            nFeatureCount = MAX(0, json_object_get_int64(poCount));
+          nFeatureCount = std::max(static_cast<int64_t>(0),
+                                   json_object_get_int64(poCount));
 
         OGRGeoJSONDataSource* poTmpDS = new OGRGeoJSONDataSource();
         OGRGeoJSONReader oReader;
@@ -177,9 +180,9 @@ CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
             // since client-side will do that extra filtering
             CPLString osFilter1 = BuildFilter(poNode->papoSubExpr[0]);
             CPLString osFilter2 = BuildFilter(poNode->papoSubExpr[1]);
-            if( osFilter1.size() && osFilter2.size() )
+            if( !osFilter1.empty() && !osFilter2.empty() )
                 return osFilter1 + "&" + osFilter2;
-            else if( osFilter1.size() )
+            else if( !osFilter1.empty() )
                 return osFilter1;
             else
                 return osFilter2;
@@ -217,7 +220,7 @@ CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
                 {
                     if( !bFilterMustBeClientSideEvaluated )
                     {
-                        bFilterMustBeClientSideEvaluated = TRUE;
+                        bFilterMustBeClientSideEvaluated = true;
                         CPLDebug("PLSCENES",
                                  "Part or full filter will have to be "
                                  "evaluated on client side.");
@@ -228,15 +231,20 @@ CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
 
             CPLString osFilter(poFieldDefn->GetNameRef());
 
-            int bDateTimeParsed = FALSE;
-            int nYear = 0, nMonth = 0, nDay = 0, nHour = 0, nMinute = 0, nSecond = 0;
+            bool bDateTimeParsed = false;
+            int nYear = 0;
+            int nMonth = 0;
+            int nDay = 0;
+            int nHour = 0;
+            int nMinute = 0;
+            int nSecond = 0;
             if( poNode->papoSubExpr[1]->field_type == SWQ_TIMESTAMP )
             {
                 if( sscanf(poNode->papoSubExpr[1]->string_value,"%04d/%02d/%02d %02d:%02d:%02d",
                            &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond) >= 3 ||
                     sscanf(poNode->papoSubExpr[1]->string_value,"%04d-%02d-%02dT%02d:%02d:%02d",
                            &nYear, &nMonth, &nDay, &nHour, &nMinute, &nSecond) >= 3 )
-                    bDateTimeParsed = TRUE;
+                    bDateTimeParsed = true;
             }
 
             osFilter += ".";
@@ -293,7 +301,7 @@ CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
     }
     if( !bFilterMustBeClientSideEvaluated )
     {
-        bFilterMustBeClientSideEvaluated = TRUE;
+        bFilterMustBeClientSideEvaluated = true;
         CPLDebug("PLSCENES",
                  "Part or full filter will have to be evaluated on client side.");
     }
@@ -306,13 +314,13 @@ CPLString OGRPLScenesLayer::BuildFilter(swq_expr_node* poNode)
 
 void OGRPLScenesLayer::ResetReading()
 {
-    bEOF = FALSE;
+    bEOF = false;
     if( poGeoJSONLayer && bStillInFirstPage )
         poGeoJSONLayer->ResetReading();
     else
         poGeoJSONLayer = NULL;
     nNextFID = 1;
-    bStillInFirstPage = TRUE;
+    bStillInFirstPage = true;
     osRequestURL = BuildURL(nPageSize);
 }
 
@@ -371,7 +379,7 @@ CPLString OGRPLScenesLayer::BuildURL(int nFeatures)
             delete poIntersection;
     }
 
-    if( osFilterURLPart.size() )
+    if( !osFilterURLPart.empty() )
     {
         if( osFilterURLPart[0] == '&' )
             osURL += osFilterURLPart;
@@ -392,9 +400,9 @@ int OGRPLScenesLayer::GetNextPage()
     poGeoJSONLayer = NULL;
     poGeoJSONDS = NULL;
 
-    if( osRequestURL.size() == 0 )
+    if( osRequestURL.empty() )
     {
-        bEOF = TRUE;
+        bEOF = true;
         if( !bFilterMustBeClientSideEvaluated && nFeatureCount < 0 )
             nFeatureCount = 0;
         return FALSE;
@@ -405,7 +413,7 @@ int OGRPLScenesLayer::GetNextPage()
     json_object* poObj = poDS->RunRequest(osRequestURL, bQuiet404Error);
     if( poObj == NULL )
     {
-        bEOF = TRUE;
+        bEOF = true;
         if( !bFilterMustBeClientSideEvaluated && nFeatureCount < 0 )
             nFeatureCount = 0;
         return FALSE;
@@ -413,7 +421,7 @@ int OGRPLScenesLayer::GetNextPage()
 
     if( !bFilterMustBeClientSideEvaluated && nFeatureCount < 0 )
     {
-        json_object* poType = json_object_object_get(poObj, "type");
+        json_object* poType = CPL_json_object_object_get(poObj, "type");
         if( poType && json_object_get_type(poType) == json_type_string &&
             strcmp(json_object_get_string(poType), "Feature") == 0 )
         {
@@ -421,15 +429,16 @@ int OGRPLScenesLayer::GetNextPage()
         }
         else
         {
-            json_object* poCount = json_object_object_get(poObj, "count");
+            json_object* poCount = CPL_json_object_object_get(poObj, "count");
             if( poCount == NULL )
             {
                 json_object_put(poObj);
-                bEOF = TRUE;
+                bEOF = true;
                 nFeatureCount = 0;
                 return FALSE;
             }
-            nFeatureCount = MAX(0, json_object_get_int64(poCount));
+            nFeatureCount = std::max(static_cast<int64_t>(0),
+                                     json_object_get_int64(poCount));
         }
     }
 
@@ -444,10 +453,10 @@ int OGRPLScenesLayer::GetNextPage()
     osNextURL = "";
     if( poGeoJSONLayer )
     {
-        json_object* poLinks = json_object_object_get(poObj, "links");
+        json_object* poLinks = CPL_json_object_object_get(poObj, "links");
         if( poLinks && json_object_get_type(poLinks) == json_type_object )
         {
-            json_object* poNext = json_object_object_get(poLinks, "next");
+            json_object* poNext = CPL_json_object_object_get(poLinks, "next");
             if( poNext && json_object_get_type(poNext) == json_type_string )
             {
                 osNextURL = json_object_get_string(poNext);
@@ -504,7 +513,7 @@ OGRErr OGRPLScenesLayer::SetAttributeFilter( const char *pszQuery )
     OGRErr eErr = OGRLayer::SetAttributeFilter(pszQuery);
 
     osFilterURLPart = "";
-    bFilterMustBeClientSideEvaluated = FALSE;
+    bFilterMustBeClientSideEvaluated = false;
     if( m_poAttrQuery != NULL )
     {
         swq_expr_node* poNode = (swq_expr_node*) m_poAttrQuery->GetSWQExpr();
@@ -523,7 +532,7 @@ OGRErr OGRPLScenesLayer::SetAttributeFilter( const char *pszQuery )
         else
         {
             CPLString osFilter = BuildFilter(poNode);
-            if( osFilter.size() )
+            if( !osFilter.empty() )
             {
                 osFilterURLPart = "&";
                 osFilterURLPart += osFilter;
@@ -545,10 +554,9 @@ OGRFeature *OGRPLScenesLayer::GetNextFeature()
     if( !bFilterMustBeClientSideEvaluated )
         return GetNextRawFeature();
 
-    OGRFeature  *poFeature;
-
     while( true )
     {
+        OGRFeature *poFeature = NULL;
         poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
@@ -572,7 +580,9 @@ OGRFeature *OGRPLScenesLayer::GetNextFeature()
 OGRFeature* OGRPLScenesLayer::GetNextRawFeature()
 {
     if( bEOF ||
-        (!bFilterMustBeClientSideEvaluated && nFeatureCount >= 0 && nNextFID > nFeatureCount) )
+        (!bFilterMustBeClientSideEvaluated &&
+         nFeatureCount >= 0 &&
+         nNextFID > nFeatureCount) )
         return NULL;
 
     if( poGeoJSONLayer == NULL )
@@ -585,10 +595,10 @@ OGRFeature* OGRPLScenesLayer::GetNextRawFeature()
     if( CPLTestBool(CPLGetConfigOption("OGR_LIMIT_TOO_MANY_FEATURES", "FALSE")) &&
         nFeatureCount > nPageSize )
     {
-        bEOF = TRUE;
+        bEOF = true;
         OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
-        OGRGeometry* poGeom;
         const char* pszWKT = "MULTIPOLYGON(((-180 90,180 90,180 -90,-180 -90,-180 90)))";
+        OGRGeometry* poGeom = NULL;
         OGRGeometryFactory::createFromWkt((char**)&pszWKT, poSRS, &poGeom);
         poFeature->SetGeometryDirectly(poGeom);
         return poFeature;
@@ -599,13 +609,13 @@ OGRFeature* OGRPLScenesLayer::GetNextRawFeature()
     if( poGeoJSONFeature == NULL )
     {
         osRequestURL = osNextURL;
-        bStillInFirstPage = FALSE;
+        bStillInFirstPage = false;
         if( !GetNextPage() )
             return NULL;
         poGeoJSONFeature = poGeoJSONLayer->GetNextFeature();
         if( poGeoJSONFeature == NULL )
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
     }
@@ -630,7 +640,7 @@ OGRFeature* OGRPLScenesLayer::GetNextRawFeature()
         OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
         OGRFieldType eType = poFieldDefn->GetType();
         int iSrcField = poGeoJSONFeature->GetFieldIndex(poFieldDefn->GetNameRef());
-        if( iSrcField >= 0 && poGeoJSONFeature->IsFieldSet(iSrcField) )
+        if( iSrcField >= 0 && poGeoJSONFeature->IsFieldSetAndNotNull(iSrcField) )
         {
             if( eType == OFTInteger )
                 poFeature->SetField(i,
@@ -674,9 +684,10 @@ GIntBig OGRPLScenesLayer::GetFeatureCount(int bForce)
             json_object* poObj = poDS->RunRequest(osURL);
             if( poObj != NULL )
             {
-                json_object* poCount = json_object_object_get(poObj, "count");
+                json_object* poCount = CPL_json_object_object_get(poObj, "count");
                 if( poCount != NULL )
-                    nFeatureCount = MAX(0, json_object_get_int64(poCount));
+                    nFeatureCount = std::max(static_cast<int64_t>(0),
+                                             json_object_get_int64(poCount));
 
                 // Small optimization, if the feature count is actually 1
                 // then we can fetch it as the full layer
@@ -720,8 +731,8 @@ OGRErr OGRPLScenesLayer::GetExtent( OGREnvelope *psExtent, int bForce )
 /*                              SetMainFilterRect()                     */
 /************************************************************************/
 
-void OGRPLScenesLayer::SetMainFilterRect(double dfMinX, double dfMinY,
-                                        double dfMaxX, double dfMaxY)
+void OGRPLScenesLayer::SetMainFilterRect( double dfMinX, double dfMinY,
+                                          double dfMaxX, double dfMaxY )
 {
     delete poMainFilter;
     if( dfMinX == dfMaxX && dfMinY == dfMaxY )
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp
index 07492ba..f74fbd6 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1dataset.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrplscenesv1dataset.cpp 35828 2016-10-19 23:23:39Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesV1Dataset
@@ -28,22 +27,22 @@
  ****************************************************************************/
 
 #include "ogr_plscenes.h"
+#include "ogrgeojsonreader.h"
 #include <time.h>
 
-CPL_CVSID("$Id: ogrplscenesv1dataset.cpp 35828 2016-10-19 23:23:39Z rouault $");
+CPL_CVSID("$Id: ogrplscenesv1dataset.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                         OGRPLScenesV1Dataset()                       */
 /************************************************************************/
 
-OGRPLScenesV1Dataset::OGRPLScenesV1Dataset()
-{
-    m_bLayerListInitialized = false;
-    m_bMustCleanPersistent = false;
-    m_nLayers = 0;
-    m_papoLayers = NULL;
-    m_bFollowLinks = false;
-}
+OGRPLScenesV1Dataset::OGRPLScenesV1Dataset() :
+    m_bLayerListInitialized(false),
+    m_bMustCleanPersistent(false),
+    m_nLayers(0),
+    m_papoLayers(NULL),
+    m_bFollowLinks(false)
+{}
 
 /************************************************************************/
 /*                         ~OGRPLScenesV1Dataset()                      */
@@ -51,14 +50,15 @@ OGRPLScenesV1Dataset::OGRPLScenesV1Dataset()
 
 OGRPLScenesV1Dataset::~OGRPLScenesV1Dataset()
 {
-    for(int i=0;i<m_nLayers;i++)
+    for( int i = 0; i < m_nLayers; i++ )
         delete m_papoLayers[i];
     CPLFree(m_papoLayers);
 
-    if (m_bMustCleanPersistent)
+    if( m_bMustCleanPersistent )
     {
-        char** papszOptions = NULL;
-        papszOptions = CSLSetNameValue(papszOptions, "CLOSE_PERSISTENT", CPLSPrintf("PLSCENES:%p", this));
+        char **papszOptions =
+            CSLSetNameValue(
+                NULL, "CLOSE_PERSISTENT", CPLSPrintf("PLSCENES:%p", this));
         CPLHTTPDestroyResult(CPLHTTPFetch(m_osBaseURL, papszOptions));
         CSLDestroy(papszOptions);
     }
@@ -97,30 +97,30 @@ OGRLayer* OGRPLScenesV1Dataset::ParseCatalog(json_object* poCatalog)
 {
     if( poCatalog == NULL || json_object_get_type(poCatalog) != json_type_object )
         return NULL;
-    json_object* poId = json_object_object_get(poCatalog, "id");
+    json_object* poId = CPL_json_object_object_get(poCatalog, "id");
     if( poId == NULL || json_object_get_type(poId) != json_type_string )
         return NULL;
-    json_object* poLinks = json_object_object_get(poCatalog, "_links");
+    json_object* poLinks = CPL_json_object_object_get(poCatalog, "_links");
     if( poLinks == NULL || json_object_get_type(poLinks) != json_type_object )
         return NULL;
-    json_object* poSpec = json_object_object_get(poLinks, "spec");
+    json_object* poSpec = CPL_json_object_object_get(poLinks, "spec");
     if( poSpec == NULL || json_object_get_type(poSpec) != json_type_string )
         return NULL;
-    json_object* poItems = json_object_object_get(poLinks, "items");
+    json_object* poItems = CPL_json_object_object_get(poLinks, "items");
     if( poItems == NULL || json_object_get_type(poItems) != json_type_string )
         return NULL;
-    json_object* poCount = json_object_object_get(poCatalog, "item_count");
+    json_object* poCount = CPL_json_object_object_get(poCatalog, "item_count");
     GIntBig nCount = -1;
     if( poCount != NULL && json_object_get_type(poCount) == json_type_int )
     {
         nCount = json_object_get_int64(poCount);
     }
     CPLString osDisplayDescription;
-    json_object* poDisplayDescription = json_object_object_get(poCatalog, "display_description");
+    json_object* poDisplayDescription = CPL_json_object_object_get(poCatalog, "display_description");
     if( poDisplayDescription != NULL && json_object_get_type(poDisplayDescription) == json_type_string )
         osDisplayDescription = json_object_get_string(poDisplayDescription);
     CPLString osDisplayName;
-    json_object* poDisplayName = json_object_object_get(poCatalog, "display_name");
+    json_object* poDisplayName = CPL_json_object_object_get(poCatalog, "display_name");
     if( poDisplayName != NULL && json_object_get_type(poDisplayName) == json_type_string )
         osDisplayName = json_object_get_string(poDisplayName);
 
@@ -141,9 +141,9 @@ OGRLayer* OGRPLScenesV1Dataset::ParseCatalog(json_object* poCatalog)
 
     OGRPLScenesV1Layer* poPLLayer = new OGRPLScenesV1Layer(
                             this, pszId, pszSpecURL, pszItemsURL, nCount);
-    if( osDisplayName.size() )
+    if( !osDisplayName.empty() )
         poPLLayer->SetMetadataItem("SHORT_DESCRIPTION", osDisplayName.c_str());
-    if( osDisplayDescription.size() )
+    if( !osDisplayDescription.empty() )
         poPLLayer->SetMetadataItem("DESCRIPTION", osDisplayDescription.c_str());
     m_papoLayers = (OGRPLScenesV1Layer**) CPLRealloc(m_papoLayers,
                                 sizeof(OGRPLScenesV1Layer*) * (m_nLayers + 1));
@@ -151,7 +151,6 @@ OGRLayer* OGRPLScenesV1Dataset::ParseCatalog(json_object* poCatalog)
     return poPLLayer;
 }
 
-
 /************************************************************************/
 /*                          ParseCatalogsPage()                         */
 /************************************************************************/
@@ -159,7 +158,7 @@ OGRLayer* OGRPLScenesV1Dataset::ParseCatalog(json_object* poCatalog)
 bool OGRPLScenesV1Dataset::ParseCatalogsPage(json_object* poObj,
                                              CPLString& osNext)
 {
-    json_object* poCatalogs = json_object_object_get(poObj, "catalogs");
+    json_object* poCatalogs = CPL_json_object_object_get(poObj, "catalogs");
     if( poCatalogs == NULL || json_object_get_type(poCatalogs) != json_type_array )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -175,10 +174,10 @@ bool OGRPLScenesV1Dataset::ParseCatalogsPage(json_object* poObj,
 
     // Is there a next page ?
     osNext = "";
-    json_object* poLinks = json_object_object_get(poObj, "_links");
+    json_object* poLinks = CPL_json_object_object_get(poObj, "_links");
     if( poLinks && json_object_get_type(poLinks) == json_type_object )
     {
-        json_object* poNext = json_object_object_get(poLinks, "_next");
+        json_object* poNext = CPL_json_object_object_get(poLinks, "_next");
         if( poNext && json_object_get_type(poNext) == json_type_string )
         {
             osNext = json_object_get_string(poNext);
@@ -197,7 +196,7 @@ void OGRPLScenesV1Dataset::EstablishLayerList()
     CPLString osURL(m_osNextCatalogPageURL);
     m_osNextCatalogPageURL = "";
 
-    while( osURL.size() != 0 )
+    while( !osURL.empty() )
     {
         json_object* poObj = RunRequest(osURL);
         if( poObj == NULL )
@@ -243,8 +242,12 @@ char** OGRPLScenesV1Dataset::GetBaseHTTPOptions()
     m_bMustCleanPersistent = true;
 
     char** papszOptions = NULL;
-    papszOptions = CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=PLSCENES:%p", this));
-    papszOptions = CSLAddString(papszOptions, CPLSPrintf("HEADERS=Authorization: api-key %s", m_osAPIKey.c_str()));
+    papszOptions =
+        CSLAddString(papszOptions, CPLSPrintf("PERSISTENT=PLSCENES:%p", this));
+    papszOptions =
+        CSLAddString(papszOptions,
+                     CPLSPrintf("HEADERS=Authorization: api-key %s",
+                                m_osAPIKey.c_str()));
     return papszOptions;
 }
 
@@ -271,11 +274,10 @@ json_object* OGRPLScenesV1Dataset::RunRequest(const char* pszURL,
         papszOptions = CSLSetNameValue(papszOptions, "POSTFIELDS", pszPostContent);
     }
     papszOptions = CSLSetNameValue(papszOptions, "MAX_RETRY", "3");
-    CPLHTTPResult * psResult;
+    CPLHTTPResult *psResult = NULL;
     if( STARTS_WITH(m_osBaseURL, "/vsimem/") &&
         STARTS_WITH(pszURL, "/vsimem/") )
     {
-        CPLDebug("PLSCENES", "Fetching %s", pszURL);
         psResult = (CPLHTTPResult*) CPLCalloc(1, sizeof(CPLHTTPResult));
         vsi_l_offset nDataLengthLarge = 0;
         CPLString osURL(pszURL);
@@ -286,6 +288,7 @@ json_object* OGRPLScenesV1Dataset::RunRequest(const char* pszURL,
             osURL += "&POSTFIELDS=";
             osURL += pszPostContent;
         }
+        CPLDebug("PLSCENES", "Fetching %s", osURL.c_str());
         GByte* pabyBuf = VSIGetMemFileBuffer(osURL, &nDataLengthLarge, FALSE);
         size_t nDataLength = static_cast<size_t>(nDataLengthLarge);
         if( pabyBuf )
@@ -312,8 +315,8 @@ json_object* OGRPLScenesV1Dataset::RunRequest(const char* pszURL,
             CPLPopErrorHandler();
     }
     CSLDestroy(papszOptions);
-    
-    if ( pszPostContent != NULL && m_bMustCleanPersistent)
+
+    if( pszPostContent != NULL && m_bMustCleanPersistent )
     {
         papszOptions = CSLSetNameValue(NULL, "CLOSE_PERSISTENT", CPLSPrintf("PLSCENES:%p", this));
         CPLHTTPDestroyResult(CPLHTTPFetch(m_osBaseURL, papszOptions));
@@ -415,7 +418,7 @@ GDALDataset* OGRPLScenesV1Dataset::OpenRasterScene(GDALOpenInfo* poOpenInfo,
 
     for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
     {
-        char* pszKey;
+        char* pszKey = NULL;
         const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
         if( pszValue != NULL )
         {
@@ -466,19 +469,19 @@ retry:
 
     json_object* poSubObj = NULL;
     if( pszProductType != NULL &&
-        (poSubObj = json_object_object_get(poObj, pszProductType)) != NULL )
+        (poSubObj = CPL_json_object_object_get(poObj, pszProductType)) != NULL )
     {
        /* do nothing */
     }
     else if( pszProductType != NULL && !EQUAL(pszProductType, "LIST") &&
-        (poSubObj = json_object_object_get(poObj, pszProductType)) == NULL )
+        (poSubObj = CPL_json_object_object_get(poObj, pszProductType)) == NULL )
     {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find asset %s", pszProductType);
        json_object_put(poObj);
        return NULL;
     }
     else if( pszProductType == NULL &&
-             (poSubObj = json_object_object_get(poObj, "visual")) != NULL )
+             (poSubObj = CPL_json_object_object_get(poObj, "visual")) != NULL )
     {
         /* do nothing */
     }
@@ -519,7 +522,7 @@ retry:
         return NULL;
     }
 
-    json_object* poPermissions = json_object_object_get(poSubObj, "_permissions");
+    json_object* poPermissions = CPL_json_object_object_get(poSubObj, "_permissions");
     if( poPermissions != NULL )
     {
         const char* pszPermissions = json_object_to_json_string_ext( poPermissions, 0 );
@@ -537,8 +540,8 @@ retry:
         json_object_put(poObj);
         return NULL;
     }
-    json_object* poLocation = json_object_object_get(poHTTP, "location");
-    json_object* poStatus = json_object_object_get(poHTTP, "status");
+    json_object* poLocation = CPL_json_object_object_get(poHTTP, "location");
+    json_object* poStatus = CPL_json_object_object_get(poHTTP, "status");
     bool bActive = false;
     if( poStatus != NULL && json_object_get_type(poStatus) == json_type_string )
     {
@@ -580,7 +583,7 @@ retry:
 
     osRasterURL = pszLink ? pszLink : "";
     json_object_put(poObj);
-    if( osRasterURL.size() == 0 )
+    if( osRasterURL.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link to scene %s",
                  osScene.c_str());
@@ -592,7 +595,8 @@ retry:
     CPLString osOldHead(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", ""));
     CPLString osOldAllowedFilename(CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME", ""));
 
-    int bUseVSICURL = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", TRUE);
+    const bool bUseVSICURL =
+        CPLFetchBool(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", true);
     if( bUseVSICURL && !(STARTS_WITH(m_osBaseURL, "/vsimem/")) )
     {
         CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", "NO");
@@ -611,7 +615,14 @@ retry:
         }
     }
 
-    GDALDataset* poOutDS = (GDALDataset*) GDALOpenEx(osRasterURL, GDAL_OF_RASTER, NULL, NULL, NULL);
+    char** papszAllowedDrivers = NULL;
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "HTTP");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "GTiff");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "PNG");
+    papszAllowedDrivers = CSLAddString(papszAllowedDrivers, "JPEG");
+    GDALDataset* poOutDS = (GDALDataset*) GDALOpenEx(osRasterURL, GDAL_OF_RASTER,
+                                                     papszAllowedDrivers, NULL, NULL);
+    CSLDestroy(papszAllowedDrivers);
     if( poOutDS )
     {
         OGRLayer* poLayer = GetLayerByName(pszCatalog);
@@ -628,7 +639,7 @@ retry:
             {
                 for(int i=0;i<poFeat->GetFieldCount();i++)
                 {
-                    if( poFeat->IsFieldSet(i) )
+                    if( poFeat->IsFieldSetAndNotNull(i) )
                     {
                         const char* pszKey = poFeat->GetFieldDefnRef(i)->GetNameRef();
                         const char* pszVal = poFeat->GetFieldAsString(i);
@@ -651,7 +662,7 @@ retry:
 
         CPLErrorReset();
         poOutDS->SetDescription(poOpenInfo->pszFilename);
-        CSLDestroy(poOutDS->GetFileList()); /* so as to probe all auxiliary files before reseting the allowed extensions */
+        CSLDestroy(poOutDS->GetFileList()); /* so as to probe all auxiliary files before resetting the allowed extensions */
     }
     else if( CPLGetLastErrorType() == CE_None )
     {
@@ -672,9 +683,9 @@ retry:
     if( bUseVSICURL )
     {
         CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD",
-                                    osOldHead.size() ? osOldHead.c_str(): NULL);
+                                    !osOldHead.empty() ? osOldHead.c_str(): NULL);
         CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME",
-                                    osOldAllowedFilename.size() ? osOldAllowedFilename.c_str(): NULL);
+                                    !osOldAllowedFilename.empty() ? osOldAllowedFilename.c_str(): NULL);
     }
 
     return poOutDS;
@@ -696,7 +707,7 @@ GDALDataset* OGRPLScenesV1Dataset::Open(GDALOpenInfo* poOpenInfo)
     poDS->m_osAPIKey = CSLFetchNameValueDef(papszOptions, "api_key",
         CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "API_KEY",
                                 CPLGetConfigOption("PL_API_KEY","")) );
-    if( poDS->m_osAPIKey.size() == 0 )
+    if( poDS->m_osAPIKey.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Missing PL_API_KEY configuration option or API_KEY open option");
@@ -733,7 +744,7 @@ GDALDataset* OGRPLScenesV1Dataset::Open(GDALOpenInfo* poOpenInfo)
 
     for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ )
     {
-        char* pszKey;
+        char* pszKey = NULL;
         const char* pszValue = CPLParseNameValue(*papszIter, &pszKey);
         if( pszValue != NULL )
         {
diff --git a/ogr/ogrsf_frmts/plscenes/ogrplscenesv1layer.cpp b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1layer.cpp
index ad4d0a6..3eddaa1 100644
--- a/ogr/ogrsf_frmts/plscenes/ogrplscenesv1layer.cpp
+++ b/ogr/ogrsf_frmts/plscenes/ogrplscenesv1layer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrplscenesv1layer.cpp 33915 2016-04-07 19:38:55Z rouault $
  *
  * Project:  PlanetLabs scene driver
  * Purpose:  Implements OGRPLScenesV1Layer
@@ -28,9 +27,10 @@
  ****************************************************************************/
 
 #include "ogr_plscenes.h"
+#include "ogrgeojsonreader.h"
 #include <algorithm>
 
-CPL_CVSID("$Id: ogrplscenesv1layer.cpp 33915 2016-04-07 19:38:55Z rouault $");
+CPL_CVSID("$Id: ogrplscenesv1layer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                           GetFieldCount()                            */
@@ -47,32 +47,34 @@ int OGRPLScenesV1FeatureDefn::GetFieldCount()
 /*                          OGRPLScenesV1Layer()                        */
 /************************************************************************/
 
-OGRPLScenesV1Layer::OGRPLScenesV1Layer(OGRPLScenesV1Dataset* poDS,
-                                       const char* pszName,
-                                       const char* pszSpecURL,
-                                       const char* pszItemsURL,
-                                       GIntBig nCount)
+OGRPLScenesV1Layer::OGRPLScenesV1Layer( OGRPLScenesV1Dataset* poDS,
+                                        const char* pszName,
+                                        const char* pszSpecURL,
+                                        const char* pszItemsURL,
+                                        GIntBig nCount ) :
+    m_poDS(poDS),
+    m_bFeatureDefnEstablished(false),
+    m_poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
+    m_osSpecURL(pszSpecURL),
+    m_osItemsURL(pszItemsURL),
+    m_nTotalFeatures(nCount),
+    m_nNextFID(1),
+    m_bEOF(false),
+    m_bStillInFirstPage(true),
+    m_nPageSize(atoi(CPLGetConfigOption("PLSCENES_PAGE_SIZE", "250"))),
+    m_bInFeatureCountOrGetExtent(false),
+    m_poPageObj(NULL),
+    m_poFeatures(NULL),
+    m_nFeatureIdx(0),
+    m_bFilterMustBeClientSideEvaluated(false)
 {
-    m_poDS = poDS;
-    SetDescription(pszName);
-    m_bFeatureDefnEstablished = false;
+    // Cannot be moved to initializer list because of use of this, which MSVC 2008 doesn't like
     m_poFeatureDefn = new OGRPLScenesV1FeatureDefn(this, pszName);
+
+    SetDescription(pszName);
     m_poFeatureDefn->SetGeomType(wkbMultiPolygon);
     m_poFeatureDefn->Reference();
-    m_poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
     m_poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(m_poSRS);
-    m_osSpecURL = pszSpecURL;
-    m_osItemsURL = pszItemsURL;
-    m_nTotalFeatures = nCount;
-    m_nNextFID = 1;
-    m_bEOF = false;
-    m_bStillInFirstPage = true;
-    m_poPageObj = NULL;
-    m_poFeatures = NULL;
-    m_nFeatureIdx = 0;
-    m_nPageSize = atoi(CPLGetConfigOption("PLSCENES_PAGE_SIZE", "250"));
-    m_bFilterMustBeClientSideEvaluated = false;
-    m_bInFeatureCountOrGetExtent = false;
     ResetReading();
 }
 
@@ -105,7 +107,7 @@ OGRFeatureDefn* OGRPLScenesV1Layer::GetLayerDefn()
 json_object* OGRPLScenesV1Layer::ResolveRefIfNecessary(json_object* poObj,
                                                       json_object* poMain)
 {
-    json_object* poRef = json_object_object_get(poObj, "$ref");
+    json_object* poRef = CPL_json_object_object_get(poObj, "$ref");
     if( poRef == NULL )
         return poObj;
     if( json_object_get_type(poRef) != json_type_string )
@@ -121,7 +123,7 @@ json_object* OGRPLScenesV1Layer::ResolveRefIfNecessary(json_object* poObj,
     json_object* poCurNode = poMain;
     for(int i=0; papszPath != NULL && papszPath[i] != NULL; i++)
     {
-        poCurNode = json_object_object_get(poCurNode, papszPath[i]);
+        poCurNode = CPL_json_object_object_get(poCurNode, papszPath[i]);
         if( poCurNode == NULL || json_object_get_type(poCurNode) != json_type_object )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot find object '%s' of '%s'",
@@ -179,7 +181,7 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
         }
     }
 
-    json_object* poPaths = json_object_object_get(poSpec, "paths");
+    json_object* poPaths = CPL_json_object_object_get(poSpec, "paths");
     if( poPaths == NULL || json_object_get_type(poPaths) != json_type_object )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find paths");
@@ -269,10 +271,10 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
       ]
     }
 */
-    json_object* poProperties = json_object_object_get(poSchema, "properties");
+    json_object* poProperties = CPL_json_object_object_get(poSchema, "properties");
     if( poProperties == NULL )
     {
-        json_object* poAllOf = json_object_object_get(poSchema, "allOf");
+        json_object* poAllOf = CPL_json_object_object_get(poSchema, "allOf");
         if( poAllOf == NULL || json_object_get_type(poAllOf) != json_type_array )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -287,7 +289,7 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
             json_object* poAllOfItem = json_object_array_get_idx(poAllOf, i);
             if( poAllOfItem != NULL && json_object_get_type(poAllOfItem) == json_type_object )
             {
-                poProperties = json_object_object_get(poAllOfItem, "properties");
+                poProperties = CPL_json_object_object_get(poAllOfItem, "properties");
                 if( poProperties != NULL )
                     break;
             }
@@ -317,7 +319,6 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
         return;
     }
 
-
     // Look for parameters (fields that can be queried)
     json_object* poParameters = json_ex_get_object_by_path(poItemsDef, "get.parameters");
     if( poParameters == NULL || json_object_get_type(poParameters) != json_type_array )
@@ -335,11 +336,11 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
             poParameter = ResolveRefIfNecessary(poParameter, poSpec);
             if( poParameter == NULL )
                 continue;
-            json_object* poName = json_object_object_get(poParameter, "name");
+            json_object* poName = CPL_json_object_object_get(poParameter, "name");
             if( poName == NULL || json_object_get_type(poName) != json_type_string )
                 continue;
             const char* pszName = json_object_get_string(poName);
-            json_object* poIn = json_object_object_get(poParameter, "in");
+            json_object* poIn = CPL_json_object_object_get(poParameter, "in");
             if( poIn == NULL || json_object_get_type(poIn) != json_type_string )
                 continue;
             const char* pszIn = json_object_get_string(poIn);
@@ -356,7 +357,6 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
         }
     }
 
-
 /* Parse:
     "Item": {
       "type": "object",
@@ -391,10 +391,10 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
     },
 */
 
-    poProperties = json_object_object_get(poItems, "properties");
+    poProperties = CPL_json_object_object_get(poItems, "properties");
     if( poProperties == NULL )
     {
-        json_object* poAllOf = json_object_object_get(poItems, "allOf");
+        json_object* poAllOf = CPL_json_object_object_get(poItems, "allOf");
         if( poAllOf == NULL || json_object_get_type(poAllOf) != json_type_array )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -409,7 +409,7 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
             json_object* poAllOfItem = json_object_array_get_idx(poAllOf, i);
             if( poAllOfItem != NULL && json_object_get_type(poAllOfItem) == json_type_object )
             {
-                poProperties = json_object_object_get(poAllOfItem, "properties");
+                poProperties = CPL_json_object_object_get(poAllOfItem, "properties");
                 if( poProperties != NULL )
                     break;
             }
@@ -426,7 +426,7 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
 
     CPLString osPropertiesDesc = "{";
 
-    json_object* poId = json_object_object_get(poProperties, "id");
+    json_object* poId = CPL_json_object_object_get(poProperties, "id");
     if( poId != NULL )
     {
         json_object_object_add(poId, "src_field", json_object_new_string("id") );
@@ -440,7 +440,7 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
         RegisterField(&oFieldDefn, NULL, "id");
     }
 
-    json_object* poLinks = json_object_object_get(poProperties, "_links");
+    json_object* poLinks = CPL_json_object_object_get(poProperties, "_links");
     if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object )
         poLinks = ResolveRefIfNecessary(poLinks, poSpec);
     else
@@ -450,7 +450,7 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
         ParseProperties(poLinks, poSpec, osPropertiesDesc, "_links");
     }
 
-    poProperties = json_object_object_get(poProperties, "properties");
+    poProperties = CPL_json_object_object_get(poProperties, "properties");
     if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -507,7 +507,7 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
             json_object* poAllOfItem = json_object_array_get_idx(poPermissionFilterAllOf, i);
             if( poAllOfItem != NULL && json_object_get_type(poAllOfItem) == json_type_object )
             {
-                poProperties = json_object_object_get(poAllOfItem, "properties");
+                poProperties = CPL_json_object_object_get(poAllOfItem, "properties");
                 if( poProperties != NULL )
                     break;
             }
@@ -537,7 +537,7 @@ void OGRPLScenesV1Layer::EstablishLayerDefn()
         }
     }
 
-    if( m_poDS->DoesFollowLinks() && m_aoAssetCategories.size() )
+    if( m_poDS->DoesFollowLinks() && !m_aoAssetCategories.empty() )
     {
         ParseAssetProperties( poSpec, osPropertiesDesc );
     }
@@ -592,7 +592,7 @@ const char *OGRPLScenesV1Layer::GetMetadataItem( const char * pszName, const cha
 static OGRFieldType OGRPLScenesV1LayerGetFieldType(json_object* poObj,
                                                    const char* pszJSonFieldName )
 {
-    json_object* poType = json_object_object_get(poObj, "type");
+    json_object* poType = CPL_json_object_object_get(poObj, "type");
     OGRFieldType eType = OFTString;
     if( poType != NULL && json_object_get_type(poType) == json_type_string )
     {
@@ -610,7 +610,7 @@ static OGRFieldType OGRPLScenesV1LayerGetFieldType(json_object* poObj,
             CPLDebug("PLSCENES", "Unknown type '%s' for '%s'",
                       pszType, pszJSonFieldName);
         }
-        json_object* poFormat = json_object_object_get(poObj, "format");
+        json_object* poFormat = CPL_json_object_object_get(poObj, "format");
         if( poFormat != NULL && json_object_get_type(poFormat) == json_type_string )
         {
             const char* pszFormat = json_object_get_string(poFormat);
@@ -641,7 +641,7 @@ void OGRPLScenesV1Layer::ParseProperties(json_object* poProperties,
                                          CPLString& osPropertiesDesc,
                                          const char* pszCategory)
 {
-    json_object* poAllOf = json_object_object_get(poProperties, "allOf");
+    json_object* poAllOf = CPL_json_object_object_get(poProperties, "allOf");
     if( poAllOf != NULL && json_object_get_type(poAllOf) == json_type_array )
     {
         const int nAllOfSize = json_object_array_length(poAllOf);
@@ -658,7 +658,7 @@ void OGRPLScenesV1Layer::ParseProperties(json_object* poProperties,
         return;
     }
 
-    poProperties = json_object_object_get(poProperties, "properties");
+    poProperties = CPL_json_object_object_get(poProperties, "properties");
     if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object )
         return;
 
@@ -792,12 +792,12 @@ void OGRPLScenesV1Layer::ParseAssetProperties(json_object* poSpec,
                     continue;
                 }
 
-                const char* pszOGRFieldName;
+                const char* pszOGRFieldName = NULL;
                 CPLString osSrcField(CPLString("/assets.") + m_aoAssetCategories[i] + CPLString("."));
                 json_object* poLinksRef = NULL;
                 if( EQUAL(pszJSonFieldName, "_links") &&
                     (bFoundLinks ||
-                     ((poLinksRef = json_object_object_get( it.val, "$ref" )) != NULL &&
+                     ((poLinksRef = CPL_json_object_object_get( it.val, "$ref" )) != NULL &&
                      json_object_get_type(poLinksRef) == json_type_string &&
                      strcmp(json_object_get_string(poLinksRef), "#/definitions/SelfLink") == 0)) )
                 {
@@ -916,7 +916,7 @@ void OGRPLScenesV1Layer::ProcessAssetFileProperties( json_object* poPropertiesAs
             if( strcmp(pszJSonFieldName, "type") == 0 )
                 continue; // "http" not really interesting
 
-            const char* pszOGRFieldName;
+            const char* pszOGRFieldName = NULL;
             CPLString osSrcField(CPLString("/assets.") + osAssetCategory + CPLString(".files."));
             if( EQUAL(pszJSonFieldName, "_links") )
             {
@@ -974,30 +974,30 @@ bool OGRPLScenesV1Layer::GetNextPage()
     m_poFeatures = NULL;
     m_nFeatureIdx = 0;
 
-    if( m_osRequestURL.size() == 0 )
+    if( m_osRequestURL.empty() )
     {
         m_bEOF = true;
         return false;
     }
 
-    json_object* poObj;
-    if( m_osRequestURL == m_poDS->GetBaseURL() + GetName() + "/quick-search" )
-        poObj = m_poDS->RunRequest(m_osRequestURL, FALSE, "POST", true, m_poDS->GetFilter());
-    else
-        poObj = m_poDS->RunRequest(m_osRequestURL);
+    json_object* poObj =
+        m_osRequestURL == m_poDS->GetBaseURL() + GetName() + "/quick-search"
+        ? m_poDS->RunRequest(m_osRequestURL, FALSE, "POST", true,
+                             m_poDS->GetFilter())
+        : m_poDS->RunRequest(m_osRequestURL);
     if( poObj == NULL )
     {
         m_bEOF = true;
         return false;
     }
 
-    json_object* poFeatures = json_object_object_get(poObj, "features");
+    json_object* poFeatures = CPL_json_object_object_get(poObj, "features");
     if( poFeatures == NULL ||
         json_object_get_type(poFeatures) != json_type_array ||
         json_object_array_length(poFeatures) == 0 )
     {
         // If this is a single item, then wrap it in a features array
-        json_object* poProperties = json_object_object_get(poObj, "properties");
+        json_object* poProperties = CPL_json_object_object_get(poObj, "properties");
         if( poProperties != NULL )
         {
             m_poPageObj = json_object_new_object();
@@ -1019,10 +1019,10 @@ bool OGRPLScenesV1Layer::GetNextPage()
 
     // Get URL of next page
     m_osNextURL = "";
-    json_object* poLinks = json_object_object_get(poObj, "_links");
+    json_object* poLinks = CPL_json_object_object_get(poObj, "_links");
     if( poLinks && json_object_get_type(poLinks) == json_type_object )
     {
-        json_object* poNext = json_object_object_get(poLinks, "_next");
+        json_object* poNext = CPL_json_object_object_get(poLinks, "_next");
         if( poNext && json_object_get_type(poNext) == json_type_string )
         {
             m_osNextURL = json_object_get_string(poNext);
@@ -1056,7 +1056,7 @@ void OGRPLScenesV1Layer::ResetReading()
 CPLString OGRPLScenesV1Layer::BuildRequestURL()
 {
     const CPLString& osFilter = m_poDS->GetFilter();
-    if( osFilter.size() && osFilter[0] == '{' && osFilter[osFilter.size()-1] == '}' )
+    if( !osFilter.empty() && osFilter[0] == '{' && osFilter.back() == '}' )
     {
         // Quick search
         return m_poDS->GetBaseURL() + GetName() + "/quick-search";
@@ -1064,7 +1064,7 @@ CPLString OGRPLScenesV1Layer::BuildRequestURL()
 
     CPLString osURL = m_osItemsURL;
     osURL += CPLSPrintf("?_page_size=%d", m_nPageSize);
-    if( osFilter.size() )
+    if( !osFilter.empty() )
         osURL += "&" + osFilter;
 
     if( m_poFilterGeom != NULL )
@@ -1091,7 +1091,7 @@ CPLString OGRPLScenesV1Layer::BuildRequestURL()
         }
     }
 
-    if( m_osFilterURLPart.size() )
+    if( !m_osFilterURLPart.empty() )
     {
         if( m_osFilterURLPart[0] == '&' )
             osURL += m_osFilterURLPart;
@@ -1226,7 +1226,7 @@ struct OGRPLScenesV1LayerExprComparator
 {
     OGRPLScenesV1Layer* m_poLayer;
 
-    OGRPLScenesV1LayerExprComparator(OGRPLScenesV1Layer* poLayer) :
+    explicit OGRPLScenesV1LayerExprComparator(OGRPLScenesV1Layer* poLayer) :
                 m_poLayer(poLayer) {}
 
     bool operator() (const swq_expr_node* poNode1,
@@ -1298,7 +1298,7 @@ CPLString OGRPLScenesV1Layer::BuildFilter(swq_expr_node* poNode)
                 continue;
             }
 
-            if( osFilter.size() )
+            if( !osFilter.empty() )
                 osFilter += "&";
 
             osFilter += osJSonName;
@@ -1312,7 +1312,7 @@ CPLString OGRPLScenesV1Layer::BuildFilter(swq_expr_node* poNode)
         }
         else if( oVector[i]->nOperation == SWQ_EQ )
         {
-            if( osFilter.size() )
+            if( !osFilter.empty() )
                 osFilter += "&";
 
             osFilter += osJSonName;
@@ -1341,7 +1341,7 @@ CPLString OGRPLScenesV1Layer::BuildFilter(swq_expr_node* poNode)
         }
         else if( oVector[i]->nOperation == SWQ_GT || oVector[i]->nOperation == SWQ_GE )
         {
-            if( osFilter.size() )
+            if( !osFilter.empty() )
                 osFilter += "&";
 
             osFilter += osJSonName;
@@ -1351,7 +1351,7 @@ CPLString OGRPLScenesV1Layer::BuildFilter(swq_expr_node* poNode)
         }
         else if( oVector[i]->nOperation == SWQ_LT || oVector[i]->nOperation == SWQ_LE )
         {
-            if( osFilter.size() )
+            if( !osFilter.empty() )
                 osFilter += "&";
 
             osFilter += osJSonName;
@@ -1368,7 +1368,7 @@ CPLString OGRPLScenesV1Layer::BuildFilter(swq_expr_node* poNode)
         }
     }
 
-    if( osFilter.size() == 0 && !m_bFilterMustBeClientSideEvaluated )
+    if( osFilter.empty() && !m_bFilterMustBeClientSideEvaluated )
     {
         m_bFilterMustBeClientSideEvaluated = true;
         CPLDebug("PLSCENES",
@@ -1415,7 +1415,7 @@ OGRErr OGRPLScenesV1Layer::SetAttributeFilter( const char *pszQuery )
         else
         {
             CPLString osFilter = BuildFilter(poNode);
-            if( osFilter.size() )
+            if( !osFilter.empty() )
             {
                 m_osFilterURLPart = "&";
                 m_osFilterURLPart += osFilter;
@@ -1434,11 +1434,9 @@ OGRErr OGRPLScenesV1Layer::SetAttributeFilter( const char *pszQuery )
 
 OGRFeature *OGRPLScenesV1Layer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
     while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature  *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -1488,7 +1486,7 @@ OGRFeature* OGRPLScenesV1Layer::GetNextRawFeature()
     OGRFeature* poFeature = new OGRFeature(m_poFeatureDefn);
     poFeature->SetFID(m_nNextFID++);
 
-    json_object* poJSonGeom = json_object_object_get(poJSonFeature, "geometry");
+    json_object* poJSonGeom = CPL_json_object_object_get(poJSonFeature, "geometry");
     if( poJSonGeom != NULL && json_object_get_type(poJSonGeom) == json_type_object )
     {
         OGRGeometry* poGeom = OGRGeoJSONReadGeometry(poJSonGeom);
@@ -1505,7 +1503,7 @@ OGRFeature* OGRPLScenesV1Layer::GetNextRawFeature()
         }
     }
 
-    json_object* poId = json_object_object_get(poJSonFeature, "id");
+    json_object* poId = CPL_json_object_object_get(poJSonFeature, "id");
     if( poId != NULL && json_object_get_type(poId) == json_type_string )
     {
         std::map<CPLString, int>::iterator oIter = m_oMapPrefixedJSonFieldNameToFieldIdx.find("id");
@@ -1519,7 +1517,7 @@ OGRFeature* OGRPLScenesV1Layer::GetNextRawFeature()
     for(int i=0;i<2;i++)
     {
         const char* pszFeaturePart = (i == 0) ? "properties": "_links";
-        json_object* poProperties = json_object_object_get(poJSonFeature, pszFeaturePart);
+        json_object* poProperties = CPL_json_object_object_get(poJSonFeature, pszFeaturePart);
         if( poProperties != NULL && json_object_get_type(poProperties) == json_type_object )
         {
             json_object_iter it;
@@ -1543,7 +1541,7 @@ OGRFeature* OGRPLScenesV1Layer::GetNextRawFeature()
         if( oIter != m_oMapPrefixedJSonFieldNameToFieldIdx.end() )
         {
             const int iField = oIter->second;
-            if( poFeature->IsFieldSet( iField ) )
+            if( poFeature->IsFieldSetAndNotNull( iField ) )
             {
                 const char* pszAssetURL = poFeature->GetFieldAsString( iField );
                 poAssets = m_poDS->RunRequest(pszAssetURL);
@@ -1573,15 +1571,15 @@ OGRFeature* OGRPLScenesV1Layer::GetNextRawFeature()
                     json_object* poHTTP = NULL;
                     if( strcmp(it.key, "_links") == 0 &&
                         json_object_get_type(it.val) == json_type_object &&
-                        json_object_object_get(it.val, "_self") != NULL )
+                        CPL_json_object_object_get(it.val, "_self") != NULL )
                     {
                         osPrefixedJSonFieldName += "._self";
                         SetFieldFromPrefixedJSonFieldName(
-                            poFeature, osPrefixedJSonFieldName, json_object_object_get(it.val, "_self"));
+                            poFeature, osPrefixedJSonFieldName, CPL_json_object_object_get(it.val, "_self"));
                     }
                     else if( strcmp(it.key, "files") == 0 &&
                              json_object_get_type(it.val) == json_type_object &&
-                             (poHTTP = json_object_object_get(it.val, "http")) != NULL &&
+                             (poHTTP = CPL_json_object_object_get(it.val, "http")) != NULL &&
                              json_object_get_type(poHTTP) == json_type_object )
                     {
                         json_object_iter itFiles;
@@ -1593,7 +1591,7 @@ OGRFeature* OGRPLScenesV1Layer::GetNextRawFeature()
                             json_object* poActivate = NULL;
                             if( strcmp(itFiles.key, "_links") == 0 &&
                                 json_object_get_type(itFiles.val) == json_type_object &&
-                                (poActivate = json_object_object_get(itFiles.val, "activate")) != NULL )
+                                (poActivate = CPL_json_object_object_get(itFiles.val, "activate")) != NULL )
                             {
                                 SetFieldFromPrefixedJSonFieldName(
                                   poFeature, osPrefixedJSonFieldName + "._links.activate", poActivate);
diff --git a/ogr/ogrsf_frmts/rec/ll_recio.cpp b/ogr/ogrsf_frmts/rec/ll_recio.cpp
index 5de8242..bac1cc5 100644
--- a/ogr/ogrsf_frmts/rec/ll_recio.cpp
+++ b/ogr/ogrsf_frmts/rec/ll_recio.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ll_recio.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  EPIInfo .REC Reader
  * Purpose:  Implements low level REC reading API.
@@ -31,7 +30,7 @@
 #include "cpl_string.h"
 #include "ogr_rec.h"
 
-CPL_CVSID("$Id: ll_recio.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ll_recio.cpp 36547 2016-11-28 22:27:56Z goatbar $");
 
 static int nNextRecLine = 0;
 
@@ -77,7 +76,9 @@ int RECGetFieldDefinition( FILE *fp, char *pszFieldname,
     // Is this an real, integer or string field?  Default to string.
     int nTypeCode = atoi(RECGetField(pszLine,33,4));
     if( nTypeCode == 0 )
+    {
         eFType = OFTInteger;
+    }
     else if( nTypeCode > 100 && nTypeCode < 120 )
     {
         eFType = OFTReal;
@@ -90,15 +91,19 @@ int RECGetFieldDefinition( FILE *fp, char *pszFieldname,
             eFType = OFTReal;
     }
     else
-        eFType = OFTString;
+    {
+      eFType = OFTString;
+    }
 
-    *pnType = (int) eFType;
+    *pnType = static_cast<int>(eFType);
 
     strcpy( pszFieldname, RECGetField( pszLine, 2, 10 ) );
     *pnPrecision = 0;
 
     if( nTypeCode > 100 && nTypeCode < 120 )
-        *pnPrecision = nTypeCode - 100;
+    {
+      *pnPrecision = nTypeCode - 100;
+    }
     else if( eFType == OFTReal )
     {
         *pnPrecision = *pnWidth - 1;
@@ -116,13 +121,12 @@ int RECGetFieldDefinition( FILE *fp, char *pszFieldname,
 const char *RECGetField( const char *pszSrc, int nStart, int nWidth )
 
 {
-    static char szWorkField[128];
-    int         i;
+    static char szWorkField[128] = {};
 
-    strncpy( szWorkField, pszSrc+nStart-1, nWidth );
+    strncpy( szWorkField, pszSrc + nStart - 1, nWidth );
     szWorkField[nWidth] = '\0';
 
-    i = (int)strlen(szWorkField)-1;
+    int i = static_cast<int>(strlen(szWorkField)) - 1;
 
     while( i >= 0 && szWorkField[i] == ' ' )
         szWorkField[i--] = '\0';
@@ -137,12 +141,11 @@ const char *RECGetField( const char *pszSrc, int nStart, int nWidth )
 int RECReadRecord( FILE *fp, char *pszRecord, int nRecordLength )
 
 {
-    int        nDataLen = 0;
+    int nDataLen = 0;
 
     while( nDataLen < nRecordLength )
     {
         const char *pszLine = CPLReadLine( fp );
-        int         iSegLen;
 
         nNextRecLine++;
 
@@ -153,7 +156,7 @@ int RECReadRecord( FILE *fp, char *pszRecord, int nRecordLength )
             return FALSE;
 
         // If the end-of-line markers is '?' the record is deleted.
-        iSegLen = (int)strlen(pszLine);
+        int iSegLen = (int)strlen(pszLine);
         if( pszLine[iSegLen-1] == '?' )
         {
             pszRecord[0] = '\0';
diff --git a/ogr/ogrsf_frmts/rec/ogr_rec.h b/ogr/ogrsf_frmts/rec/ogr_rec.h
index ff90da5..bd119d9 100644
--- a/ogr/ogrsf_frmts/rec/ogr_rec.h
+++ b/ogr/ogrsf_frmts/rec/ogr_rec.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_rec.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_rec.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  Epi .REC Translator
  * Purpose:  Definition of classes for OGR .REC support.
@@ -42,7 +42,6 @@ int CPL_DLL RECReadRecord( FILE *fp, char *pszRecBuf, int nRecordLength  );
 const char CPL_DLL *RECGetField( const char *pszSrc, int nStart, int nWidth );
 CPL_C_END
 
-
 /************************************************************************/
 /*                             OGRRECLayer                              */
 /************************************************************************/
@@ -69,15 +68,14 @@ class OGRRECLayer : public OGRLayer
                                      int nFieldCount );
                         ~OGRRECLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     int                 IsValid() { return bIsValid; }
-
 };
 
 /************************************************************************/
@@ -96,10 +94,10 @@ class OGRRECDataSource : public OGRDataSource
 
     int                 Open( const char * pszFilename );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return 1; }
-    OGRLayer            *GetLayer( int );
-    int                 TestCapability( const char * );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return 1; }
+    OGRLayer            *GetLayer( int ) override;
+    int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_REC_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp b/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
index 0fb2841..d76495d 100644
--- a/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
+++ b/ogr/ogrsf_frmts/rec/ogrrecdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrrecdatasource.cpp 33089 2016-01-22 15:02:53Z goatbar $
  *
  * Project:  Epiinfo .REC Translator
  * Purpose:  Implements OGRRECDataSource class
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrrecdatasource.cpp 33089 2016-01-22 15:02:53Z goatbar $");
+CPL_CVSID("$Id: ogrrecdatasource.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                          OGRRECDataSource()                          */
diff --git a/ogr/ogrsf_frmts/rec/ogrrecdriver.cpp b/ogr/ogrsf_frmts/rec/ogrrecdriver.cpp
index 06baa14..a8b75b4 100644
--- a/ogr/ogrsf_frmts/rec/ogrrecdriver.cpp
+++ b/ogr/ogrsf_frmts/rec/ogrrecdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrrecdriver.cpp 33089 2016-01-22 15:02:53Z goatbar $
  *
  * Project:  REC Translator
  * Purpose:  Implements EpiInfo .REC driver.
@@ -30,7 +29,7 @@
 #include "ogr_rec.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrrecdriver.cpp 33089 2016-01-22 15:02:53Z goatbar $");
+CPL_CVSID("$Id: ogrrecdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -84,4 +83,3 @@ void RegisterOGRREC()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/rec/ogrreclayer.cpp b/ogr/ogrsf_frmts/rec/ogrreclayer.cpp
index 1952a08..3b5a623 100644
--- a/ogr/ogrsf_frmts/rec/ogrreclayer.cpp
+++ b/ogr/ogrsf_frmts/rec/ogrreclayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrreclayer.cpp 33089 2016-01-22 15:02:53Z goatbar $
  *
  * Project:  EPIInfo .REC Reader
  * Purpose:  Implements OGRRECLayer class.
@@ -31,7 +30,7 @@
 #include "cpl_string.h"
 #include "ogr_rec.h"
 
-CPL_CVSID("$Id: ogrreclayer.cpp 33089 2016-01-22 15:02:53Z goatbar $");
+CPL_CVSID("$Id: ogrreclayer.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                            OGRRECLayer()                             */
@@ -42,7 +41,7 @@ CPL_CVSID("$Id: ogrreclayer.cpp 33089 2016-01-22 15:02:53Z goatbar $");
 
 OGRRECLayer::OGRRECLayer( const char *pszLayerNameIn,
                           FILE * fp, int nFieldCountIn ) :
-  poFeatureDefn(new OGRFeatureDefn( pszLayerNameIn )),
+    poFeatureDefn(new OGRFeatureDefn( pszLayerNameIn )),
     fpREC(fp),
     nStartOfData(0),
     bIsValid(FALSE),
@@ -261,7 +260,6 @@ OGRFeature * OGRRECLayer::GetNextUnfilteredFeature()
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/s57/ddfrecordindex.cpp b/ogr/ogrsf_frmts/s57/ddfrecordindex.cpp
index a24d378..eae9269 100644
--- a/ogr/ogrsf_frmts/s57/ddfrecordindex.cpp
+++ b/ogr/ogrsf_frmts/s57/ddfrecordindex.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ddfrecordindex.cpp 33271 2016-01-30 16:01:55Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements DDFRecordIndex class.  This class is used to cache
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "s57.h"
 
-CPL_CVSID("$Id: ddfrecordindex.cpp 33271 2016-01-30 16:01:55Z goatbar $");
+CPL_CVSID("$Id: ddfrecordindex.cpp 35542 2016-09-29 14:10:37Z goatbar $");
 
 /************************************************************************/
 /*                           DDFRecordIndex()                           */
@@ -191,7 +190,7 @@ DDFRecord * DDFRecordIndex::FindRecordByObjl( int nObjl )
 /*                            RemoveRecord()                            */
 /************************************************************************/
 
-int DDFRecordIndex::RemoveRecord( int nKey )
+bool DDFRecordIndex::RemoveRecord( int nKey )
 
 {
     if( !bSorted )
@@ -217,7 +216,7 @@ int DDFRecordIndex::RemoveRecord( int nKey )
     }
 
     if( nMinIndex > nMaxIndex )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Delete this record.                                             */
@@ -234,7 +233,7 @@ int DDFRecordIndex::RemoveRecord( int nKey )
 
     nRecordCount--;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/s57/ogr_s57.h b/ogr/ogrsf_frmts/s57/ogr_s57.h
index 8e30622..f133bae 100644
--- a/ogr/ogrsf_frmts/s57/ogr_s57.h
+++ b/ogr/ogrsf_frmts/s57/ogr_s57.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_s57.h 32433 2015-12-23 23:48:56Z goatbar $
+ * $Id: ogr_s57.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Declarations for classes binding S57 support onto OGRLayer,
@@ -60,20 +60,20 @@ class OGRS57Layer : public OGRLayer
                                      int nOBJL = -1 );
     virtual             ~OGRS57Layer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
     OGRFeature *        GetNextUnfilteredFeature();
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    int                 TestCapability( const char * );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -102,7 +102,7 @@ class OGRS57DataSource : public OGRDataSource
     OGREnvelope         oExtents;
 
   public:
-                        OGRS57DataSource(char** papszOpenOptions = NULL);
+    explicit            OGRS57DataSource(char** papszOpenOptions = NULL);
                         ~OGRS57DataSource();
 
     void                SetOptionList( char ** );
@@ -111,11 +111,11 @@ class OGRS57DataSource : public OGRDataSource
     int                 Open( const char * pszName );
     int                 Create( const char *pszName, char **papszOptions );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
     void                AddLayer( OGRS57Layer * );
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     OGRSpatialReference *GetSpatialRef() { return poSpatialRef; }
 
diff --git a/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp b/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
index ee87d11..da2f865 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57datasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrs57datasource.cpp 34800 2016-07-27 16:52:35Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57DataSource class
@@ -32,7 +31,10 @@
 #include "cpl_string.h"
 #include "ogr_s57.h"
 
-CPL_CVSID("$Id: ogrs57datasource.cpp 34800 2016-07-27 16:52:35Z rouault $");
+#include <algorithm>
+#include <set>
+
+CPL_CVSID("$Id: ogrs57datasource.cpp 36017 2016-10-29 04:27:08Z goatbar $");
 
 /************************************************************************/
 /*                          OGRS57DataSource()                          */
@@ -84,7 +86,6 @@ OGRS57DataSource::OGRS57DataSource(char** papszOpenOptionsIn) :
         }
         CPLFree(pszKey);
     }
-
 }
 
 /************************************************************************/
@@ -211,7 +212,7 @@ int OGRS57DataSource::Open( const char * pszFilename )
                              GetOption(S57O_RECODE_BY_DSSI) );
 
     S57Reader *poModule = new S57Reader( pszFilename );
-    int bRet = poModule->SetOptions( papszReaderOptions );
+    bool bRet = poModule->SetOptions( papszReaderOptions );
     CSLDestroy( papszReaderOptions );
 
     if( !bRet )
@@ -440,10 +441,10 @@ OGRErr OGRS57DataSource::GetDSExtent( OGREnvelope *psExtent, int bForce )
             oExtents = oModuleEnvelope;
         else
         {
-            oExtents.MinX = MIN(oExtents.MinX,oModuleEnvelope.MinX);
-            oExtents.MaxX = MAX(oExtents.MaxX,oModuleEnvelope.MaxX);
-            oExtents.MinY = MIN(oExtents.MinY,oModuleEnvelope.MinY);
-            oExtents.MaxX = MAX(oExtents.MaxY,oModuleEnvelope.MaxY);
+            oExtents.MinX = std::min(oExtents.MinX, oModuleEnvelope.MinX);
+            oExtents.MaxX = std::max(oExtents.MaxX, oModuleEnvelope.MaxX);
+            oExtents.MinY = std::min(oExtents.MinY, oModuleEnvelope.MinY);
+            oExtents.MaxX = std::max(oExtents.MaxY, oModuleEnvelope.MaxY);
         }
     }
 
@@ -509,16 +510,24 @@ int OGRS57DataSource::Create( const char *pszFilename,
 /*      Initialize a feature definition for each object class.          */
 /* -------------------------------------------------------------------- */
     poClassContentExplorer->Rewind();
+    std::set<int> aoSetOBJL;
     while( poClassContentExplorer->NextClass() )
     {
+        const int nOBJL = poClassContentExplorer->GetOBJL();
+        // Detect potential duplicates in the classes
+        if( aoSetOBJL.find(nOBJL) != aoSetOBJL.end() )
+        {
+            CPLDebug("S57", "OBJL %d already registered!", nOBJL);
+            continue;
+        }
+        aoSetOBJL.insert(nOBJL);
         poDefn =
             S57GenerateObjectClassDefn( OGRS57Driver::GetS57Registrar(),
                                         poClassContentExplorer,
-                                        poClassContentExplorer->GetOBJL(),
+                                        nOBJL,
                                         nOptionFlags );
 
-        AddLayer( new OGRS57Layer( this, poDefn, 0,
-                                   poClassContentExplorer->GetOBJL() ) );
+        AddLayer( new OGRS57Layer( this, poDefn, 0, nOBJL ) );
     }
 
 /* -------------------------------------------------------------------- */
diff --git a/ogr/ogrsf_frmts/s57/ogrs57driver.cpp b/ogr/ogrsf_frmts/s57/ogrs57driver.cpp
index 79b2980..6547bf5 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57driver.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57driver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrs57driver.cpp 32433 2015-12-23 23:48:56Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57Driver
@@ -32,7 +31,7 @@
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrs57driver.cpp 32433 2015-12-23 23:48:56Z goatbar $");
+CPL_CVSID("$Id: ogrs57driver.cpp 35542 2016-09-29 14:10:37Z goatbar $");
 
 S57ClassRegistrar *OGRS57Driver::poRegistrar = NULL;
 static CPLMutex* hS57RegistrarMutex = NULL;
@@ -147,7 +146,7 @@ S57ClassRegistrar *OGRS57Driver::GetS57Registrar()
     {
         poRegistrar = new S57ClassRegistrar();
 
-        if( !poRegistrar->LoadInfo( NULL, NULL, FALSE ) )
+        if( !poRegistrar->LoadInfo( NULL, NULL, false ) )
         {
             delete poRegistrar;
             poRegistrar = NULL;
diff --git a/ogr/ogrsf_frmts/s57/ogrs57layer.cpp b/ogr/ogrsf_frmts/s57/ogrs57layer.cpp
index c6d7016..d5a0d7d 100644
--- a/ogr/ogrsf_frmts/s57/ogrs57layer.cpp
+++ b/ogr/ogrsf_frmts/s57/ogrs57layer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrs57layer.cpp 33271 2016-01-30 16:01:55Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements OGRS57Layer class.
@@ -32,7 +31,7 @@
 #include "cpl_string.h"
 #include "ogr_s57.h"
 
-CPL_CVSID("$Id: ogrs57layer.cpp 33271 2016-01-30 16:01:55Z goatbar $");
+CPL_CVSID("$Id: ogrs57layer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                            OGRS57Layer()                             */
@@ -283,7 +282,7 @@ OGRErr OGRS57Layer::ICreateFeature( OGRFeature *poFeature )
 
     if( iRCNMFld != -1 )
     {
-        if( !poFeature->IsFieldSet( iRCNMFld ) )
+        if( !poFeature->IsFieldSetAndNotNull( iRCNMFld ) )
             poFeature->SetField( iRCNMFld, nRCNM );
         else
         {
@@ -298,7 +297,7 @@ OGRErr OGRS57Layer::ICreateFeature( OGRFeature *poFeature )
     {
         const int iOBJLFld = poFeature->GetFieldIndex( "OBJL" );
 
-        if( !poFeature->IsFieldSet( iOBJLFld ) )
+        if( !poFeature->IsFieldSetAndNotNull( iOBJLFld ) )
             poFeature->SetField( iOBJLFld, nOBJL );
         else
         {
diff --git a/ogr/ogrsf_frmts/s57/s57.h b/ogr/ogrsf_frmts/s57/s57.h
index 3095faf..ea89dbd 100644
--- a/ogr/ogrsf_frmts/s57/s57.h
+++ b/ogr/ogrsf_frmts/s57/s57.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: s57.h 36427 2016-11-22 12:56:01Z rouault $
  *
  * Project:  S-57 Translator
  * Purpose:  Declarations for S-57 translator not including the
@@ -120,8 +120,8 @@ class CPL_DLL S57ClassRegistrar
     std::vector<S57AttrInfo*> aoAttrInfos;
     std::vector<int> anAttrIndex; // sorted by acronym.
 
-    int         FindFile( const char *pszTarget, const char *pszDirectory,
-                          int bReportErr, VSILFILE **fp );
+    static bool        FindFile( const char *pszTarget, const char *pszDirectory,
+                          bool bReportErr, VSILFILE **fp );
 
     const char *ReadLine( VSILFILE * fp );
     char      **papszNextLine;
@@ -130,11 +130,11 @@ public:
                 S57ClassRegistrar();
                ~S57ClassRegistrar();
 
-    int         LoadInfo( const char *, const char *, int );
+    bool        LoadInfo( const char *, const char *, bool );
 
     // attribute table methods.
     //int         GetMaxAttrIndex() { return nAttrMax; }
-    const S57AttrInfo *GetAttrInfo(int i);
+    const S57AttrInfo *GetAttrInfo( int i );
     const char *GetAttrName( int i )
     { return GetAttrInfo(i) == NULL ? NULL : aoAttrInfos[i]->osName.c_str(); }
     const char *GetAttrAcronym( int i )
@@ -151,7 +151,6 @@ public:
     char        GetAttrClass( int i )
     { return GetAttrInfo(i) == NULL ? '\0' : aoAttrInfos[i]->chClass; }
     int         FindAttrByAcronym( const char * );
-
 };
 
 /************************************************************************/
@@ -171,15 +170,15 @@ class S57ClassContentExplorer
     char      **papszTempResult;
 
     public:
-        S57ClassContentExplorer(S57ClassRegistrar* poRegistrar);
+    explicit    S57ClassContentExplorer(S57ClassRegistrar* poRegistrar);
        ~S57ClassContentExplorer();
 
-    int         SelectClassByIndex( int );
-    int         SelectClass( int );
-    int         SelectClass( const char * );
+    bool        SelectClassByIndex( int );
+    bool        SelectClass( int );
+    bool        SelectClass( const char * );
 
-    int         Rewind() { return SelectClassByIndex(0); }
-    int         NextClass() { return SelectClassByIndex(iCurrentClass+1); }
+    bool        Rewind() { return SelectClassByIndex(0); }
+    bool        NextClass() { return SelectClassByIndex(iCurrentClass+1); }
 
     int         GetOBJL();
     const char *GetDescription() const;
@@ -223,7 +222,7 @@ public:
                ~DDFRecordIndex();
 
     void        AddRecord( int nKey, DDFRecord * );
-    int         RemoveRecord( int nKey );
+    bool        RemoveRecord( int nKey );
 
     DDFRecord  *FindRecord( int nKey );
 
@@ -296,32 +295,35 @@ class CPL_DLL S57Reader
     OGRFeature         *AssembleFeature( DDFRecord  *, OGRFeatureDefn * );
 
     void                ApplyObjectClassAttributes( DDFRecord *, OGRFeature *);
+    // cppcheck-suppress functionStatic
     void                GenerateLNAMAndRefs( DDFRecord *, OGRFeature * );
     void                GenerateFSPTAttributes( DDFRecord *, OGRFeature * );
 
     void                AssembleSoundingGeometry( DDFRecord *, OGRFeature * );
+    // cppcheck-suppress functionStatic
     void                AssemblePointGeometry( DDFRecord *, OGRFeature * );
     void                AssembleLineGeometry( DDFRecord *, OGRFeature * );
     void                AssembleAreaGeometry( DDFRecord *, OGRFeature * );
 
-    int                 FetchPoint( int, int,
+    bool                FetchPoint( int, int,
                                     double *, double *, double * = NULL );
-    int                 FetchLine( DDFRecord *, int, int, OGRLineString * );
+    bool                FetchLine( DDFRecord *, int, int, OGRLineString * );
 
     OGRFeatureDefn     *FindFDefn( DDFRecord * );
     int                 ParseName( DDFField *, int = 0, int * = NULL );
 
-    int                 ApplyRecordUpdate( DDFRecord *, DDFRecord * );
+    // cppcheck-suppress functionStatic
+    bool                ApplyRecordUpdate( DDFRecord *, DDFRecord * );
 
     bool                bMissingWarningIssued;
     bool                bAttrWarningIssued;
 
   public:
-                        S57Reader( const char * );
+    explicit            S57Reader( const char * );
                        ~S57Reader();
 
     void                SetClassBased( S57ClassRegistrar *, S57ClassContentExplorer* );
-    int                 SetOptions( char ** );
+    bool                SetOptions( char ** );
     int                 GetOptionFlags() { return nOptionFlags; }
 
     int                 Open( int bTestOpen );
@@ -329,27 +331,26 @@ class CPL_DLL S57Reader
     DDFModule           *GetModule() { return poModule; }
     const char          *GetDSNM() { return pszDSNM; }
 
-    int                 Ingest();
-    int                 ApplyUpdates( DDFModule * );
-    int                 FindAndApplyUpdates( const char *pszPath=NULL );
+    bool                Ingest();
+    bool                ApplyUpdates( DDFModule * );
+    bool                FindAndApplyUpdates( const char *pszPath=NULL );
 
     void                Rewind();
     OGRFeature          *ReadNextFeature( OGRFeatureDefn * = NULL );
     OGRFeature          *ReadFeature( int nFID, OGRFeatureDefn * = NULL );
     OGRFeature          *ReadVector( int nFID, int nRCNM );
-    OGRFeature          *ReadDSID( void );
+    OGRFeature          *ReadDSID();
 
     int                 GetNextFEIndex( int nRCNM = 100 );
     void                SetNextFEIndex( int nNewIndex, int nRCNM = 100 );
 
     void                AddFeatureDefn( OGRFeatureDefn * );
 
-    int                 CollectClassList(std::vector<int> &anClassCount);
+    bool                CollectClassList(std::vector<int> &anClassCount);
 
     OGRErr              GetExtent( OGREnvelope *psExtent, int bForce );
 
     char               *RecodeByDSSI(const char *SourceString, bool LookAtAALL_NALL);
-
  };
 
 /************************************************************************/
@@ -363,15 +364,15 @@ public:
                         ~S57Writer();
 
     void                SetClassBased( S57ClassRegistrar *, S57ClassContentExplorer* );
-    int                 CreateS57File( const char *pszFilename );
-    int                 Close();
+    bool                CreateS57File( const char *pszFilename );
+    bool                Close();
 
-    int                 WriteGeometry( DDFRecord *, int, double *, double *,
+    bool                WriteGeometry( DDFRecord *, int, double *, double *,
                                        double * );
-    int                 WriteATTF( DDFRecord *, OGRFeature * );
-    int                 WritePrimitive( OGRFeature *poFeature );
-    int                 WriteCompleteFeature( OGRFeature *poFeature );
-    int                 WriteDSID( int nEXPP = 1,
+    bool                WriteATTF( DDFRecord *, OGRFeature * );
+    bool                WritePrimitive( OGRFeature *poFeature );
+    bool                WriteCompleteFeature( OGRFeature *poFeature );
+    bool                WriteDSID( int nEXPP = 1,
                                    int nINTU = 4,
                                    const char *pszDSNM = NULL,
                                    const char *pszEDTN = NULL,
@@ -383,9 +384,8 @@ public:
                                    const char *pszCOMT = NULL,
                                    int nNOMR = 0, int nNOGR = 0,
                                    int nNOLR = 0, int nNOIN = 0,
-                                   int nNOCN = 0, int nNOED = 0
-                                 );
-    int                 WriteDSPM( int nHDAT = 0,
+                                   int nNOCN = 0, int nNOED = 0 );
+    bool                WriteDSPM( int nHDAT = 0,
                                    int nVDAT = 0,
                                    int nSDAT = 0,
                                    int nCSCL = 0 );
diff --git a/ogr/ogrsf_frmts/s57/s57classregistrar.cpp b/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
index 91b558c..87703c4 100644
--- a/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
+++ b/ogr/ogrsf_frmts/s57/s57classregistrar.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: s57classregistrar.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57ClassRegistrar class for keeping track of
@@ -33,8 +32,7 @@
 #include "cpl_string.h"
 #include "s57.h"
 
-CPL_CVSID("$Id: s57classregistrar.cpp 33714 2016-03-13 05:42:13Z goatbar $");
-
+CPL_CVSID("$Id: s57classregistrar.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 #ifdef S57_BUILTIN_CLASSES
 #include "s57tables.h"
@@ -48,7 +46,7 @@ S57ClassRegistrar::S57ClassRegistrar() :
     nClasses(0),
     nAttrCount(0),
     papszNextLine(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                         ~S57ClassRegistrar()                         */
@@ -58,7 +56,7 @@ S57ClassRegistrar::~S57ClassRegistrar()
 
 {
     nClasses = 0;
-    for(size_t i=0;i<aoAttrInfos.size();i++)
+    for( size_t i = 0; i < aoAttrInfos.size(); i++ )
         delete aoAttrInfos[i];
     aoAttrInfos.resize(0);
     nAttrCount = 0;
@@ -68,15 +66,14 @@ S57ClassRegistrar::~S57ClassRegistrar()
 /*                        S57ClassContentExplorer()                     */
 /************************************************************************/
 
-S57ClassContentExplorer::S57ClassContentExplorer(S57ClassRegistrar* poRegistrarIn):
-    poRegistrar(poRegistrarIn)
-{
-    iCurrentClass = -1;
-
-    papszCurrentFields = NULL;
-    papapszClassesFields = NULL;
-    papszTempResult = NULL;
-}
+S57ClassContentExplorer::S57ClassContentExplorer(
+    S57ClassRegistrar* poRegistrarIn ) :
+    poRegistrar(poRegistrarIn),
+    papapszClassesFields(NULL),
+    iCurrentClass(-1),
+    papszCurrentFields(NULL),
+    papszTempResult(NULL)
+{}
 
 /************************************************************************/
 /*                        ~S57ClassContentExplorer()                    */
@@ -98,13 +95,13 @@ S57ClassContentExplorer::~S57ClassContentExplorer()
 /*                              FindFile()                              */
 /************************************************************************/
 
-int S57ClassRegistrar::FindFile( const char *pszTarget,
-                                 const char *pszDirectory,
-                                 int bReportErr,
-                                 VSILFILE **pfp )
+bool S57ClassRegistrar::FindFile( const char *pszTarget,
+                                  const char *pszDirectory,
+                                  bool bReportErr,
+                                  VSILFILE **pfp )
 
 {
-    const char *pszFilename;
+    const char *pszFilename = NULL;
 
     if( pszDirectory == NULL )
     {
@@ -162,17 +159,17 @@ const char *S57ClassRegistrar::ReadLine( VSILFILE * fp )
         papszNextLine = NULL;
         return NULL;
     }
-    else
-        return *(papszNextLine++);
+
+    return *(papszNextLine++);
 }
 
 /************************************************************************/
 /*                              LoadInfo()                              */
 /************************************************************************/
 
-int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
-                                 const char * pszProfile,
-                                 int bReportErr )
+bool S57ClassRegistrar::LoadInfo( const char * pszDirectory,
+                                  const char * pszProfile,
+                                  bool bReportErr )
 
 {
     if( pszDirectory == NULL )
@@ -187,10 +184,12 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     char szTargetFile[1024];  // TODO: Get this off of the stack.
     if( EQUAL(pszProfile, "Additional_Military_Layers") )
     {
+        // Has been suppressed in GDAL data/
        snprintf( szTargetFile, sizeof(szTargetFile), "s57objectclasses_%s.csv", "aml" );
     }
     else if ( EQUAL(pszProfile, "Inland_Waterways") )
     {
+        // Has been suppressed in GDAL data/
        snprintf( szTargetFile, sizeof(szTargetFile), "s57objectclasses_%s.csv", "iw" );
     }
     else if( strlen(pszProfile) > 0 )
@@ -204,7 +203,16 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
 
     VSILFILE *fp = NULL;
     if( !FindFile( szTargetFile, pszDirectory, bReportErr, &fp ) )
-        return FALSE;
+    {
+        if( EQUAL(pszProfile, "Additional_Military_Layers") ||
+            EQUAL(pszProfile, "Inland_Waterways") )
+        {
+            strcpy( szTargetFile, "s57objectclasses.csv" );
+            if( !FindFile( szTargetFile, pszDirectory, bReportErr, &fp ) )
+                return false;
+        }
+        return false;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Skip the line defining the column titles.                       */
@@ -219,7 +227,7 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
                   "s57objectclasses columns don't match expected format!\n" );
         if( fp != NULL )
             VSIFCloseL( fp );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -228,6 +236,8 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     apszClassesInfo.Clear();
     while( (pszLine = ReadLine(fp)) != NULL )
     {
+        if( strstr(pszLine, "###") != NULL )
+            continue;
         apszClassesInfo.AddString(pszLine);
     }
 
@@ -239,7 +249,7 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
 
     nClasses = apszClassesInfo.size();
     if( nClasses == 0 )
-        return FALSE;
+        return false;
 
 /* ==================================================================== */
 /*      Read the attributes list.                                       */
@@ -247,10 +257,12 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
 
     if( EQUAL(pszProfile, "Additional_Military_Layers") )
     {
+        // Has been suppressed in GDAL data/
       snprintf( szTargetFile, sizeof(szTargetFile), "s57attributes_%s.csv", "aml" );
     }
     else if ( EQUAL(pszProfile, "Inland_Waterways") )
     {
+        // Has been suppressed in GDAL data/
        snprintf( szTargetFile, sizeof(szTargetFile),"s57attributes_%s.csv", "iw" );
     }
     else if( strlen(pszProfile) > 0 )
@@ -263,7 +275,16 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
     }
 
     if( !FindFile( szTargetFile, pszDirectory, bReportErr, &fp ) )
-        return FALSE;
+    {
+        if( EQUAL(pszProfile, "Additional_Military_Layers") ||
+            EQUAL(pszProfile, "Inland_Waterways") )
+        {
+            strcpy( szTargetFile, "s57attributes.csv" );
+            if( !FindFile( szTargetFile, pszDirectory, bReportErr, &fp ) )
+                return false;
+        }
+        return false;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Skip the line defining the column titles.                       */
@@ -277,7 +298,7 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
                   "s57attributes columns don't match expected format!\n" );
         if( fp != NULL )
             VSIFCloseL( fp );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -285,12 +306,15 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
 /* -------------------------------------------------------------------- */
     while( (pszLine = ReadLine(fp)) != NULL )
     {
+        if( strstr(pszLine, "###") != NULL )
+            continue;
+
         char    **papszTokens = CSLTokenizeStringComplex( pszLine, ",",
                                                           TRUE, TRUE );
 
         if( CSLCount(papszTokens) < 5 )
         {
-            CPLAssert( FALSE );
+            CSLDestroy(papszTokens);
             continue;
         }
 
@@ -341,18 +365,18 @@ int S57ClassRegistrar::LoadInfo( const char * pszDirectory,
         }
     } while( bModified );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                         SelectClassByIndex()                         */
 /************************************************************************/
 
-int S57ClassContentExplorer::SelectClassByIndex( int nNewIndex )
+bool S57ClassContentExplorer::SelectClassByIndex( int nNewIndex )
 
 {
     if( nNewIndex < 0 || nNewIndex >= poRegistrar->nClasses )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Do we have our cache of class information field lists?          */
@@ -374,14 +398,14 @@ int S57ClassContentExplorer::SelectClassByIndex( int nNewIndex )
 
     iCurrentClass = nNewIndex;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                             SelectClass()                            */
 /************************************************************************/
 
-int S57ClassContentExplorer::SelectClass( int nOBJL )
+bool S57ClassContentExplorer::SelectClass( int nOBJL )
 
 {
     for( int i = 0; i < poRegistrar->nClasses; i++ )
@@ -397,7 +421,7 @@ int S57ClassContentExplorer::SelectClass( int nOBJL )
 /*                            SelectClass()                             */
 /************************************************************************/
 
-int S57ClassContentExplorer::SelectClass( const char *pszAcronym )
+bool S57ClassContentExplorer::SelectClass( const char *pszAcronym )
 
 {
     for( int i = 0; i < poRegistrar->nClasses; i++ )
@@ -405,11 +429,12 @@ int S57ClassContentExplorer::SelectClass( const char *pszAcronym )
         if( !SelectClassByIndex( i ) )
             continue;
 
-        if( strcmp(GetAcronym(),pszAcronym) == 0 )
-            return TRUE;
+        const char* pszClassAcronym = GetAcronym();
+        if( pszClassAcronym != NULL && strcmp(pszClassAcronym,pszAcronym) == 0 )
+            return true;
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/s57/s57dump.cpp b/ogr/ogrsf_frmts/s57/s57dump.cpp
index 5f8c8af..e821554 100644
--- a/ogr/ogrsf_frmts/s57/s57dump.cpp
+++ b/ogr/ogrsf_frmts/s57/s57dump.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: s57dump.cpp 32445 2015-12-25 01:28:55Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Simple client for viewing S57 driver data.
@@ -31,7 +30,7 @@
 #include "cpl_string.h"
 #include "s57.h"
 
-CPL_CVSID("$Id: s57dump.cpp 32445 2015-12-25 01:28:55Z goatbar $");
+CPL_CVSID("$Id: s57dump.cpp 35147 2016-08-18 17:36:16Z goatbar $");
 
 /************************************************************************/
 /*                                main()                                */
@@ -189,8 +188,8 @@ int main( int nArgc, char ** papszArgv )
 
         oReader.AddFeatureDefn( S57GenerateDSIDFeatureDefn() );
 
-        OGRFeature      *poFeature;
-        int             nFeatures = 0;
+        OGRFeature *poFeature = NULL;
+        int nFeatures = 0;
 
         while( (poFeature = oReader.ReadNextFeature()) != NULL )
         {
@@ -204,4 +203,3 @@ int main( int nArgc, char ** papszArgv )
 
     return 0;
 }
-
diff --git a/ogr/ogrsf_frmts/s57/s57featuredefns.cpp b/ogr/ogrsf_frmts/s57/s57featuredefns.cpp
index acdc18f..82ea96c 100644
--- a/ogr/ogrsf_frmts/s57/s57featuredefns.cpp
+++ b/ogr/ogrsf_frmts/s57/s57featuredefns.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: s57featuredefns.cpp 33271 2016-01-30 16:01:55Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements methods to create OGRFeatureDefns for various
@@ -33,8 +32,7 @@
 #include "ogr_api.h"
 #include "s57.h"
 
-CPL_CVSID("$Id: s57featuredefns.cpp 33271 2016-01-30 16:01:55Z goatbar $");
-
+CPL_CVSID("$Id: s57featuredefns.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                     S57GenerateGeomFeatureDefn()                     */
@@ -424,7 +422,8 @@ OGRFeatureDefn *S57GenerateObjectClassDefn(
 /* -------------------------------------------------------------------- */
 /*      Do we need to add DEPTH attributes to soundings?                */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(poClassContentExplorer->GetAcronym(), "SOUNDG")
+    const char* pszClassAcronym = poClassContentExplorer->GetAcronym();
+    if( pszClassAcronym != NULL && EQUAL(pszClassAcronym, "SOUNDG")
         && (nOptionFlags & S57M_ADD_SOUNDG_DEPTH) )
     {
         OGRFieldDefn oField( "DEPTH", OFTReal );
diff --git a/ogr/ogrsf_frmts/s57/s57filecollector.cpp b/ogr/ogrsf_frmts/s57/s57filecollector.cpp
index 61115fd..fc9350d 100644
--- a/ogr/ogrsf_frmts/s57/s57filecollector.cpp
+++ b/ogr/ogrsf_frmts/s57/s57filecollector.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: s57filecollector.cpp 33712 2016-03-12 10:51:56Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57FileCollector() function.  This function collects
@@ -33,7 +32,7 @@
 #include "cpl_string.h"
 #include "s57.h"
 
-CPL_CVSID("$Id: s57filecollector.cpp 33712 2016-03-12 10:51:56Z goatbar $");
+CPL_CVSID("$Id: s57filecollector.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                          S57FileCollector()                          */
@@ -114,7 +113,6 @@ char **S57FileCollector( const char *pszDataset )
         return papszRetList;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      We presumably have a catalog.  It contains paths to files       */
 /*      that generally lack the ENC_ROOT component.  Try to find the    */
diff --git a/ogr/ogrsf_frmts/s57/s57reader.cpp b/ogr/ogrsf_frmts/s57/s57reader.cpp
index 4f51182..f2db12d 100644
--- a/ogr/ogrsf_frmts/s57/s57reader.cpp
+++ b/ogr/ogrsf_frmts/s57/s57reader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: s57reader.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57Reader class.
@@ -33,18 +32,21 @@
 #include "ogr_api.h"
 #include "s57.h"
 
+#include <cmath>
+
+#include <algorithm>
 #include <string>
 
-CPL_CVSID("$Id: s57reader.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: s57reader.cpp 36948 2016-12-18 13:32:14Z rouault $");
 
-/******************************************************************************
+/**
 * Recode the given string from a source encoding to UTF-8 encoding.  The source
 * encoding is established by inspecting the AALL and NALL fields of the S57
 * DSSI record. If first time, the DSSI is read to setup appropriate
 * variables. Main scope of this function is to have the strings of all
 * attributes encoded/recoded to the same codepage in the final Shapefiles .DBF.
 *
-* @param[in] SourceString: source string to be recoded to UTF-8.
+* @param[in] SourceString source string to be recoded to UTF-8.
 *     LookAtAALL-NALL: flag indicating if the string becomes from an
 *     international attribute (e.g.  INFORM, OBJNAM) or national attribute (e.g
 *     NINFOM, NOBJNM). The type of encoding is contained in two different
@@ -56,9 +58,9 @@ CPL_CVSID("$Id: s57reader.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 *     0: the type of endoding is for international attributes
 *     1: the type of endoding is for national attributes
 *
-* @param[out]
+* @param[in] LookAtAALL_NALL to be documented
 *
-* @return: the output string recoded to UTF-8 or left unchanged if no valid
+* @return the output string recoded to UTF-8 or left unchanged if no valid
 *     recoding applicable. The recodinf relies on GDAL functions appropriately
 *     called, which allocate themselves the necessary memory to hold the
 *     recoded string.
@@ -139,7 +141,7 @@ char *S57Reader::RecodeByDSSI(const char *SourceString, bool LookAtAALL_NALL)
     if( RecodedString == NULL )
         RecodedString = CPLStrdup(SourceString);
 
-    return(RecodedString);
+    return RecodedString;
 }
 
 /************************************************************************/
@@ -340,7 +342,7 @@ OGRFeature *S57Reader::NextPendingMultiPoint()
 /*                             SetOptions()                             */
 /************************************************************************/
 
-int S57Reader::SetOptions( char ** papszOptionsIn )
+bool S57Reader::SetOptions( char ** papszOptionsIn )
 
 {
     CSLDestroy( papszOptions );
@@ -365,7 +367,7 @@ int S57Reader::SetOptions( char ** papszOptionsIn )
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Inconsistent options : ADD_SOUNDG_DEPTH should only be "
                  "enabled if SPLIT_MULTIPOINT is also enabled");
-        return FALSE;
+        return false;
     }
 
     pszOptionValue = CSLFetchNameValue( papszOptions, S57O_LNAM_REFS );
@@ -413,7 +415,7 @@ int S57Reader::SetOptions( char ** papszOptionsIn )
     else
         nOptionFlags &= ~S57M_RECODE_BY_DSSI;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -451,23 +453,23 @@ void S57Reader::Rewind()
 /*      indexes.                                                        */
 /************************************************************************/
 
-int S57Reader::Ingest()
+bool S57Reader::Ingest()
 
 {
     if( poModule == NULL || bFileIngested )
-        return TRUE;
+        return true;
 
 /* -------------------------------------------------------------------- */
 /*      Read all the records in the module, and place them in           */
 /*      appropriate indexes.                                            */
 /* -------------------------------------------------------------------- */
     CPLErrorReset();
-    DDFRecord *poRecord;
+    DDFRecord *poRecord = NULL;
     while( (poRecord = poModule->ReadRecord()) != NULL )
     {
-        DDFField        *poKeyField = poRecord->GetField(1);
+        DDFField *poKeyField = poRecord->GetField(1);
         if (poKeyField == NULL)
-            return FALSE;
+            return false;
 
         if( EQUAL(poKeyField->GetFieldDefn()->GetName(),"VRID") )
         {
@@ -523,8 +525,8 @@ int S57Reader::Ingest()
 
         else if( EQUAL(poKeyField->GetFieldDefn()->GetName(),"DSPM") )
         {
-            nCOMF = MAX(1,poRecord->GetIntSubfield( "DSPM",0, "COMF",0));
-            nSOMF = MAX(1,poRecord->GetIntSubfield( "DSPM",0, "SOMF",0));
+            nCOMF = std::max(1, poRecord->GetIntSubfield( "DSPM",0, "COMF",0));
+            nSOMF = std::max(1, poRecord->GetIntSubfield( "DSPM",0, "SOMF",0));
 
             if( nOptionFlags & S57M_RETURN_DSID )
             {
@@ -538,13 +540,13 @@ int S57Reader::Ingest()
         else
         {
             CPLDebug( "S57",
-                      "Skipping %s record in S57Reader::Ingest().\n",
+                      "Skipping %s record in S57Reader::Ingest().",
                       poKeyField->GetFieldDefn()->GetName() );
         }
     }
 
     if( CPLGetLastErrorType() == CE_Failure )
-        return FALSE;
+        return false;
 
     bFileIngested = true;
 
@@ -554,7 +556,7 @@ int S57Reader::Ingest()
     if( nOptionFlags & S57M_UPDATES )
         return FindAndApplyUpdates();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -776,7 +778,6 @@ OGRFeature *S57Reader::ReadFeature( int nFeatureId, OGRFeatureDefn *poTarget )
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                          AssembleFeature()                           */
 /*                                                                      */
@@ -900,7 +901,7 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
         {
             if( !bAttrWarningIssued )
             {
-                bAttrWarningIssued = TRUE;
+                bAttrWarningIssued = true;
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Illegal feature attribute id (ATTF:ATTL[%d]) of %d\n"
                           "on feature FIDN=%d, FIDS=%d.\n"
@@ -932,7 +933,7 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
         {
             if( !bMissingWarningIssued )
             {
-                bMissingWarningIssued = TRUE;
+                bMissingWarningIssued = true;
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Attributes %s ignored, not in expected schema.\n"
                           "No more warnings will be issued for this dataset.",
@@ -983,7 +984,7 @@ void S57Reader::ApplyObjectClassAttributes( DDFRecord * poRecord,
         {
             if( !bAttrWarningIssued )
             {
-                bAttrWarningIssued = TRUE;
+                bAttrWarningIssued = true;
                 CPLError( CE_Warning, CPLE_AppDefined,
                           "Illegal feature attribute id (NATF:ATTL[%d]) of %d\n"
                           "on feature FIDN=%d, FIDS=%d.\n"
@@ -1176,7 +1177,7 @@ OGRFeature *S57Reader::ReadDSID()
 
     if( poFDefn == NULL )
     {
-        //CPLAssert( FALSE );
+        // CPLAssert( false );
         return NULL;
     }
 
@@ -1284,7 +1285,6 @@ OGRFeature *S57Reader::ReadDSID()
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                             ReadVector()                             */
 /*                                                                      */
@@ -1324,7 +1324,7 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
         break;
 
       default:
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return NULL;
     }
 
@@ -1349,7 +1349,7 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
 
     if( poFDefn == NULL )
     {
-        //CPLAssert( FALSE );
+        // CPLAssert( false );
         return NULL;
     }
 
@@ -1414,7 +1414,6 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
                 poFeature->SetGeometryDirectly( poMP );
             }
         }
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -1517,8 +1516,8 @@ OGRFeature *S57Reader::ReadVector( int nFeatureId, int nRCNM )
 /*      Fetch the location of a spatial point object.                   */
 /************************************************************************/
 
-int S57Reader::FetchPoint( int nRCNM, int nRCID,
-                           double * pdfX, double * pdfY, double * pdfZ )
+bool S57Reader::FetchPoint( int nRCNM, int nRCID,
+                            double *pdfX, double *pdfY, double *pdfZ )
 
 {
     DDFRecord *poSRecord = NULL;
@@ -1529,7 +1528,7 @@ int S57Reader::FetchPoint( int nRCNM, int nRCID,
         poSRecord = oVC_Index.FindRecord( nRCID );
 
     if( poSRecord == NULL )
-        return FALSE;
+        return false;
 
     double dfX = 0.0;
     double dfY = 0.0;
@@ -1552,7 +1551,7 @@ int S57Reader::FetchPoint( int nRCNM, int nRCID,
             / static_cast<double>( nSOMF );
     }
     else
-        return FALSE;
+        return false;
 
     if( pdfX != NULL )
         *pdfX = dfX;
@@ -1561,7 +1560,7 @@ int S57Reader::FetchPoint( int nRCNM, int nRCID,
     if( pdfZ != NULL )
         *pdfZ = dfZ;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1577,7 +1576,7 @@ S57StrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
 {
     OGRLineString * const poLine = new OGRLineString;
 
-    nVertexCount = MAX(2,nVertexCount);
+    nVertexCount = std::max(2, nVertexCount);
     const double dfSlice = (dfEndAngle-dfStartAngle)/(nVertexCount-1);
 
     poLine->setNumPoints( nVertexCount );
@@ -1595,7 +1594,6 @@ S57StrokeArcToOGRGeometry_Angles( double dfCenterX, double dfCenterY,
     return poLine;
 }
 
-
 /************************************************************************/
 /*                  S57StrokeArcToOGRGeometry_Points()                  */
 /************************************************************************/
@@ -1607,14 +1605,13 @@ S57StrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
                                   int nVertexCount )
 
 {
-    double      dfStartAngle;
-    double      dfEndAngle;
-    double      dfRadius;
+    double dfStartAngle = 0.0;
+    double dfEndAngle = 360.0;
 
     if( dfStartX == dfEndX && dfStartY == dfEndY )
     {
-        dfStartAngle = 0.0;
-        dfEndAngle = 360.0;
+        // dfStartAngle = 0.0;
+        // dfEndAngle = 360.0;
     }
     else
     {
@@ -1657,8 +1654,9 @@ S57StrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
         }
     }
 
-    dfRadius = sqrt( (dfCenterX - dfStartX) * (dfCenterX - dfStartX)
-                     + (dfCenterY - dfStartY) * (dfCenterY - dfStartY) );
+    const double dfRadius =
+        sqrt( (dfCenterX - dfStartX) * (dfCenterX - dfStartX)
+              + (dfCenterY - dfStartY) * (dfCenterY - dfStartY) );
 
     return S57StrokeArcToOGRGeometry_Angles( dfCenterX, dfCenterY,
                                              dfRadius,
@@ -1670,7 +1668,7 @@ S57StrokeArcToOGRGeometry_Points( double dfStartX, double dfStartY,
 /*                             FetchLine()                              */
 /************************************************************************/
 
-int S57Reader::FetchLine( DDFRecord *poSRecord,
+bool S57Reader::FetchLine( DDFRecord *poSRecord,
                           int iStartVertex, int iDirection,
                           OGRLineString *poLine )
 
@@ -1716,7 +1714,7 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
         if( poXCOO == NULL || poYCOO == NULL )
         {
             CPLDebug( "S57", "XCOO or YCOO are NULL" );
-            return FALSE;
+            return false;
         }
 
         const int nVCount = poSG2D->GetRepeatCount();
@@ -1766,12 +1764,12 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
         {
             int nBytesRemaining = 0;
 
-            const char *pachData
-                = poSG2D->GetSubfieldData( poYCOO,&nBytesRemaining, 0 );
+            const char *pachData =
+                poSG2D->GetSubfieldData( poYCOO, &nBytesRemaining, 0 );
 
             for( int i = 0; i < nVCount; i++ )
             {
-                GInt32      nYCOO;
+                GInt32 nYCOO = 0;
                 memcpy( &nYCOO, pachData, 4 );
                 pachData += 4;
 
@@ -1850,7 +1848,7 @@ int S57Reader::FetchLine( DDFRecord *poSRecord,
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1871,7 +1869,7 @@ void S57Reader::AssemblePointGeometry( DDFRecord * poFRecord,
     if( poFSPT->GetRepeatCount() != 1 )
     {
 #ifdef DEBUG
-        fprintf( stderr,
+        fprintf( stderr, /*ok*/
                  "Point features with other than one spatial linkage.\n" );
         poFRecord->Dump( stderr );
 #endif
@@ -1922,11 +1920,9 @@ void S57Reader::AssembleSoundingGeometry( DDFRecord * poFRecord,
     int nRCNM = 0;
     const int nRCID = ParseName( poFSPT, 0, &nRCNM );
 
-    DDFRecord *poSRecord;
-    if( nRCNM == RCNM_VI )
-        poSRecord = oVI_Index.FindRecord( nRCID );
-    else
-        poSRecord = oVC_Index.FindRecord( nRCID );
+    DDFRecord *poSRecord = nRCNM == RCNM_VI
+        ? oVI_Index.FindRecord( nRCID )
+        : oVC_Index.FindRecord( nRCID );
 
     if( poSRecord == NULL )
         return;
@@ -1965,7 +1961,7 @@ void S57Reader::AssembleSoundingGeometry( DDFRecord * poFRecord,
 
     for( int i = 0; i < nPointCount; i++ )
     {
-        int nBytesConsumed;
+        int nBytesConsumed = 0;
 
         const double dfY = poYCOO->ExtractIntData( pachData, nBytesLeft,
                                                    &nBytesConsumed )
@@ -2019,7 +2015,7 @@ GetIntSubfield( DDFField *poField,
                                 &nBytesRemaining,
                                 iSubfieldIndex );
 
-    return( poSFDefn->ExtractIntData( pachData, nBytesRemaining, NULL ) );
+    return poSFDefn->ExtractIntData( pachData, nBytesRemaining, NULL );
 }
 
 /************************************************************************/
@@ -2163,8 +2159,8 @@ void S57Reader::AssembleLineGeometry( DDFRecord * poFRecord,
             {
                 poLine->addPoint( dfX, dfY );
             }
-            else if( ABS(dlastfX - dfX) > 0.00000001 ||
-                ABS(dlastfY - dfY) > 0.00000001 )
+            else if( std::abs(dlastfX - dfX) > 0.00000001 ||
+                std::abs(dlastfY - dfY) > 0.00000001 )
             {
                 // we need to start a new linestring.
                 poMLS->addGeometryDirectly( poLine );
@@ -2354,7 +2350,8 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
             if( poVRPT != NULL )
             {
                 int nVC_RCID = ParseName( poVRPT );
-                double dfX, dfY;
+                double dfX = 0.0;
+                double dfY = 0.0;
 
                 if( nVC_RCID != -1
                     && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
@@ -2376,8 +2373,8 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
             if( poVRPT != NULL && poVRPT->GetRepeatCount() > 1 )
             {
                 const int nVC_RCID = ParseName( poVRPT, 1 );
-                double dfX;
-                double dfY;
+                double dfX = 0.0;
+                double dfY = 0.0;
 
                 if( nVC_RCID != -1
                     && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
@@ -2386,8 +2383,8 @@ void S57Reader::AssembleAreaGeometry( DDFRecord * poFRecord,
             else if( (poVRPT = poSRecord->FindField( "VRPT", 1 )) != NULL )
             {
                 const int nVC_RCID = ParseName( poVRPT );
-                double dfX;
-                double dfY;
+                double dfX = 0.0;
+                double dfY = 0.0;
 
                 if( nVC_RCID != -1
                     && FetchPoint( RCNM_VC, nVC_RCID, &dfX, &dfY ) )
@@ -2452,8 +2449,10 @@ OGRFeatureDefn * S57Reader::FindFDefn( DDFRecord * poRecord )
 
         for( int i = 0; i < nFDefnCount; i++ )
         {
-            if( EQUAL(papoFDefnList[i]->GetName(),
-                      poClassContentExplorer->GetAcronym()) )
+            const char* pszAcronym = poClassContentExplorer->GetAcronym();
+            if( pszAcronym != NULL &&
+                EQUAL(papoFDefnList[i]->GetName(),
+                      pszAcronym) )
                 return papoFDefnList[i];
         }
 
@@ -2506,7 +2505,7 @@ int S57Reader::ParseName( DDFField * poField, int nIndex, int * pnRCNM )
     if( poName == NULL )
         return -1;
 
-    int nMaxBytes;
+    int nMaxBytes = 0;
     unsigned char *pabyData = reinterpret_cast<unsigned char *>(
         const_cast<char *>(
             poField->GetSubfieldData( poName, &nMaxBytes, nIndex ) ) );
@@ -2557,11 +2556,11 @@ void S57Reader::AddFeatureDefn( OGRFeatureDefn * poFDefn )
 /*      occur in this dataset.                                          */
 /************************************************************************/
 
-int S57Reader::CollectClassList(std::vector<int> &anClassCount)
+bool S57Reader::CollectClassList(std::vector<int> &anClassCount)
 
 {
     if( !bFileIngested && !Ingest() )
-        return FALSE;
+        return false;
 
     bool bSuccess = true;
 
@@ -2578,7 +2577,6 @@ int S57Reader::CollectClassList(std::vector<int> &anClassCount)
                 anClassCount.resize(nOBJL+1);
             anClassCount[nOBJL]++;
         }
-
     }
 
     return bSuccess;
@@ -2591,7 +2589,7 @@ int S57Reader::CollectClassList(std::vector<int> &anClassCount)
 /*      (RUIN=3).                                                       */
 /************************************************************************/
 
-int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
+bool S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 
 {
     const char *pszKey = poUpdate->GetField(1)->GetFieldDefn()->GetName();
@@ -2607,8 +2605,8 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                   poTarget->GetIntSubfield( pszKey, 0, "RCNM", 0 ),
                   poTarget->GetIntSubfield( pszKey, 0, "RCID", 0 ) );
 
-        // CPLAssert( FALSE );
-        return FALSE;
+        // CPLAssert( false );
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -2618,14 +2616,14 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 
     if( poKey == NULL )
     {
-        // CPLAssert( FALSE );
-        return FALSE;
+        // CPLAssert( false );
+        return false;
     }
 
     DDFSubfieldDefn *poRVER_SFD
         = poKey->GetFieldDefn()->FindSubfieldDefn( "RVER" );
     if( poRVER_SFD == NULL )
-        return FALSE;
+        return false;
 
     unsigned char *pnRVER
         = (unsigned char *) poKey->GetSubfieldData( poRVER_SFD, NULL, 0 );
@@ -2644,8 +2642,8 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 
         if( (poSrcFSPT == NULL && nFSUI != 2) || poDstFSPT == NULL )
         {
-            // CPLAssert( FALSE );
-            return FALSE;
+            // CPLAssert( false );
+            return false;
         }
 
         const int nFSIX = poUpdate->GetIntSubfield( "FSPC", 0, "FSIX", 0 );
@@ -2662,7 +2660,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                 CPLDebug( "S57", "Not enough bytes in source FSPT field. "
                           "Has %d, requires %d",
                           poSrcFSPT->GetDataSize(), nInsertionBytes );
-                return FALSE;
+                return false;
             }
 
             char *pachInsertion
@@ -2682,7 +2680,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                               "Has %d, requires %d",
                               poDstFSPT->GetDataSize(), nPtrSize * nFSIX );
                     CPLFree( pachInsertion );
-                    return FALSE;
+                    return false;
                 }
 
                 memcpy( pachInsertion + nInsertionBytes,
@@ -2710,7 +2708,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             {
                 CPLDebug("S57", "Not enough bytes in source FSPT field. Has %d, requires %d",
                          poSrcFSPT->GetDataSize(), nNSPT * nPtrSize );
-                return FALSE;
+                return false;
             }
 
             for( int i = 0; i < nNSPT; i++ )
@@ -2734,8 +2732,8 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 
         if( (poSrcVRPT == NULL && nVPUI != 2) || poDstVRPT == NULL )
         {
-            //CPLAssert( FALSE );
-            return FALSE;
+            // CPLAssert( false );
+            return false;
         }
 
         const int nVPIX = poUpdate->GetIntSubfield( "VRPC", 0, "VPIX", 0 );
@@ -2751,7 +2749,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             {
                 CPLDebug("S57", "Not enough bytes in source VRPT field. Has %d, requires %d",
                          poSrcVRPT->GetDataSize(), nInsertionBytes );
-                return FALSE;
+                return false;
             }
 
             char *pachInsertion
@@ -2770,7 +2768,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                     CPLDebug("S57", "Not enough bytes in dest VRPT field. Has %d, requires %d",
                          poDstVRPT->GetDataSize(), nPtrSize * nVPIX );
                     CPLFree( pachInsertion );
-                    return FALSE;
+                    return false;
                 }
 
                 memcpy( pachInsertion + nInsertionBytes,
@@ -2798,7 +2796,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                 CPLDebug( "S57", "Not enough bytes in source VRPT field. "
                           "Has %d, requires %d",
                           poSrcVRPT->GetDataSize(), nNVPT * nPtrSize );
-                return FALSE;
+                return false;
             }
 
             /* copy over each ptr */
@@ -2835,8 +2833,8 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
         if( (poSrcSG2D == NULL && nCCUI != 2)
             || (poDstSG2D == NULL && nCCUI != 1) )
         {
-            //CPLAssert( FALSE );
-            return FALSE;
+            // CPLAssert( false );
+            return false;
         }
 
         if (poDstSG2D == NULL)
@@ -2844,8 +2842,8 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             poTarget->AddField(poTarget->GetModule()->FindFieldDefn("SG2D"));
             poDstSG2D = poTarget->FindField("SG2D");
             if (poDstSG2D == NULL) {
-                //CPLAssert( FALSE );
-                return FALSE;
+                // CPLAssert( false );
+                return false;
             }
 
             // Delete null default data that was created
@@ -2865,7 +2863,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                 CPLDebug( "S57", "Not enough bytes in source SG2D field. "
                           "Has %d, requires %d",
                           poSrcSG2D->GetDataSize(), nInsertionBytes );
-                return FALSE;
+                return false;
             }
 
             char *pachInsertion
@@ -2886,7 +2884,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                               "Has %d, requires %d",
                               poDstSG2D->GetDataSize(), nCoordSize * nCCIX );
                     CPLFree( pachInsertion );
-                    return FALSE;
+                    return false;
                 }
 
                 memcpy( pachInsertion + nInsertionBytes,
@@ -2914,7 +2912,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                 CPLDebug( "S57", "Not enough bytes in source SG2D field. "
                           "Has %d, requires %d",
                           poSrcSG2D->GetDataSize(), nCCNC * nCoordSize );
-                return FALSE;
+                return false;
             }
 
             /* copy over each ptr */
@@ -2942,8 +2940,8 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             || (poDstFFPT == NULL && nFFUI != 1) )
         {
             CPLDebug( "S57", "Missing source or target FFPT applying update.");
-            //CPLAssert( FALSE );
-            return FALSE;
+            // CPLAssert( false );
+            return false;
         }
 
         // Create FFPT field on target record, if it does not yet exist.
@@ -2953,8 +2951,8 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             poTarget->AddField(poTarget->GetModule()->FindFieldDefn("FFPT"));
             poDstFFPT = poTarget->FindField("FFPT");
             if (poDstFFPT == NULL) {
-                //CPLAssert( FALSE );
-                return FALSE;
+                // CPLAssert( false );
+                return false;
             }
 
             // Delete null default data that was created
@@ -2982,7 +2980,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                 CPLDebug( "S57", "Not enough bytes in source FFPT field. "
                           "Has %d, requires %d",
                           poSrcFFPT->GetDataSize(), nInsertionBytes );
-                return FALSE;
+                return false;
             }
 
             char *pachInsertion
@@ -3002,7 +3000,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                               "Has %d, requires %d",
                               poDstFFPT->GetDataSize(), nFFPTSize * nFFIX );
                     CPLFree( pachInsertion );
-                    return FALSE;
+                    return false;
                 }
 
                 memcpy( pachInsertion + nInsertionBytes,
@@ -3033,7 +3031,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
                 CPLDebug( "S57", "Not enough bytes in source FFPT field. "
                           "Has %d, requires %d",
                           poSrcFFPT->GetDataSize(), nNFPT * nFFPTSize );
-                return FALSE;
+                return false;
             }
 
             /* copy over each ptr */
@@ -3059,7 +3057,7 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Unable to apply ATTF change to target record without "
                       "an ATTF field (see GDAL/OGR Bug #1648)" );
-            return FALSE;
+            return false;
         }
 
         DDFField *poSrcATTF = poUpdate->FindField( "ATTF" );
@@ -3069,9 +3067,9 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
         {
             const int nATTL
                 = poUpdate->GetIntSubfield( "ATTF", 0, "ATTL", iAtt );
-            int iTAtt;
+            int iTAtt = poDstATTF->GetRepeatCount() - 1;  // Used after for.
 
-            for( iTAtt = poDstATTF->GetRepeatCount()-1; iTAtt >= 0; iTAtt-- )
+            for( ; iTAtt >= 0; iTAtt-- )
             {
                 if( poTarget->GetIntSubfield( "ATTF", 0, "ATTL", iTAtt )
                     == nATTL )
@@ -3080,9 +3078,9 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
             if( iTAtt == -1 )
                 iTAtt = poDstATTF->GetRepeatCount();
 
-            int nDataBytes;
-            const char *pszRawData
-                = poSrcATTF->GetInstanceData( iAtt, &nDataBytes );
+            int nDataBytes = 0;
+            const char *pszRawData =
+                poSrcATTF->GetInstanceData( iAtt, &nDataBytes );
             if( pszRawData[2] == 0x7f /* delete marker */ )
             {
                 poTarget->SetFieldRaw( poDstATTF, iTAtt, NULL, 0 );
@@ -3095,10 +3093,9 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
         }
     }
 
-    return TRUE;
+    return true;
 }
 
-
 /************************************************************************/
 /*                            ApplyUpdates()                            */
 /*                                                                      */
@@ -3106,27 +3103,27 @@ int S57Reader::ApplyRecordUpdate( DDFRecord *poTarget, DDFRecord *poUpdate )
 /*      currently loaded index of features.                             */
 /************************************************************************/
 
-int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
+bool S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Ensure base file is loaded.                                     */
 /* -------------------------------------------------------------------- */
     if( !bFileIngested && !Ingest() )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Read records, and apply as updates.                             */
 /* -------------------------------------------------------------------- */
     CPLErrorReset();
 
-    DDFRecord *poRecord;
+    DDFRecord *poRecord = NULL;
 
     while( (poRecord = poUpdateModule->ReadRecord()) != NULL )
     {
         DDFField *poKeyField = poRecord->GetField(1);
         if( poKeyField == NULL )
-            return FALSE;
+            return false;
 
         const char *pszKey = poKeyField->GetFieldDefn()->GetName();
 
@@ -3159,8 +3156,8 @@ int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
                     break;
 
                   default:
-                    //CPLAssert( FALSE );
-                    return FALSE;
+                    // CPLAssert( false );
+                    return false;
                     break;
                 }
             }
@@ -3248,7 +3245,7 @@ int S57Reader::ApplyUpdates( DDFModule *poUpdateModule )
 /*      base file.                                                      */
 /************************************************************************/
 
-int S57Reader::FindAndApplyUpdates( const char * pszPath )
+bool S57Reader::FindAndApplyUpdates( const char * pszPath )
 
 {
     if( pszPath == NULL )
@@ -3259,7 +3256,7 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Can't apply updates to a base file with a different\n"
                   "extension than .000.\n" );
-        return FALSE;
+        return false;
     }
 
     bool bSuccess = true;
@@ -3269,10 +3266,11 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
         //Creaing file extension
         CPLString extension;
         CPLString dirname;
+
         if( 1 <= iUpdate &&  iUpdate < 10 )
         {
             char buf[2];
-            snprintf( buf, sizeof(buf), "%i", iUpdate );
+            CPLsnprintf( buf, sizeof(buf), "%i", iUpdate );
             extension.append("00");
             extension.append(buf);
             dirname.append(buf);
@@ -3280,7 +3278,7 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
         else if( 10 <= iUpdate && iUpdate < 100 )
         {
             char buf[3];
-            snprintf( buf, sizeof(buf), "%i", iUpdate );
+            CPLsnprintf( buf, sizeof(buf), "%i", iUpdate );
             extension.append("0");
             extension.append(buf);
             dirname.append(buf);
@@ -3288,7 +3286,7 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
         else if( 100 <= iUpdate && iUpdate < 1000 )
         {
             char buf[4];
-            snprintf( buf, sizeof(buf), "%i", iUpdate );
+            CPLsnprintf( buf, sizeof(buf), "%i", iUpdate );
             extension.append(buf);
             dirname.append(buf);
         }
@@ -3310,7 +3308,7 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
                 CPLDebug( "S57", "Applying feature updates from %s.",
                           pszUpdateFilename );
                 if( !ApplyUpdates( &oUpdateModule ) )
-                    return FALSE;
+                    return false;
             }
         }
         else // File is store on Primar generated CD.
@@ -3336,13 +3334,13 @@ int S57Reader::FindAndApplyUpdates( const char * pszPath )
             if( bSuccess )
             {
                 if( !ApplyUpdates( &oUpdateModule ) )
-                    return FALSE;
+                    return false;
             }
         }//end for if-else
         CPLFree( pszUpdateFilename );
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -3403,15 +3401,15 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
 
                 for( int i = 0; i < nVCount; i++ )
                 {
-                    GInt32 nX = CPL_LSBINT32PTR(pabyData + 4*(i*3+1));
-                    GInt32 nY = CPL_LSBINT32PTR(pabyData + 4*(i*3+0));
+                    GInt32 nX = CPL_LSBSINT32PTR(pabyData + 4*(i*3+1));
+                    GInt32 nY = CPL_LSBSINT32PTR(pabyData + 4*(i*3+0));
 
                     if( bGotExtents )
                     {
-                        nXMin = MIN(nXMin,nX);
-                        nXMax = MAX(nXMax,nX);
-                        nYMin = MIN(nYMin,nY);
-                        nYMax = MAX(nYMax,nY);
+                        nXMin = std::min(nXMin, nX);
+                        nXMax = std::max(nXMax, nX);
+                        nYMin = std::min(nYMin, nY);
+                        nYMax = std::max(nYMax, nY);
                     }
                     else
                     {
@@ -3419,31 +3417,30 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
                         nXMax = nX;
                         nYMin = nY;
                         nYMax = nY;
-                        bGotExtents = TRUE;
+                        bGotExtents = true;
                     }
                 }
             }
             else if( poSG2D != NULL )
             {
-                int     i, nVCount = poSG2D->GetRepeatCount();
-                GInt32  nX, nY;
-                const GByte   *pabyData;
+                const int nVCount = poSG2D->GetRepeatCount();
 
-                pabyData = (const GByte*)poSG2D->GetData();
                 if( poSG2D->GetDataSize() < 2 * nVCount * (int)sizeof(int) )
                     return OGRERR_FAILURE;
 
-                for( i = 0; i < nVCount; i++ )
+                const GByte *pabyData = (const GByte*)poSG2D->GetData();
+
+                for( int i = 0; i < nVCount; i++ )
                 {
-                    nX = CPL_LSBINT32PTR(pabyData + 4*(i*2+1));
-                    nY = CPL_LSBINT32PTR(pabyData + 4*(i*2+0));
+                    const GInt32 nX = CPL_LSBSINT32PTR(pabyData + 4*(i*2+1));
+                    const GInt32 nY = CPL_LSBSINT32PTR(pabyData + 4*(i*2+0));
 
                     if( bGotExtents )
                     {
-                        nXMin = MIN(nXMin,nX);
-                        nXMax = MAX(nXMax,nX);
-                        nYMin = MIN(nYMin,nY);
-                        nYMax = MAX(nYMax,nY);
+                        nXMin = std::min(nXMin, nX);
+                        nXMax = std::max(nXMax, nX);
+                        nYMin = std::min(nYMin, nY);
+                        nYMax = std::max(nYMax, nY);
                     }
                     else
                     {
@@ -3451,7 +3448,7 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
                         nXMax = nX;
                         nYMin = nY;
                         nYMax = nY;
-                        bGotExtents = TRUE;
+                        bGotExtents = true;
                     }
                 }
             }
@@ -3459,7 +3456,9 @@ OGRErr S57Reader::GetExtent( OGREnvelope *psExtent, int bForce )
     }
 
     if( !bGotExtents )
+    {
         return OGRERR_FAILURE;
+    }
     else
     {
         psExtent->MinX = nXMin / static_cast<double>( nCOMF );
diff --git a/ogr/ogrsf_frmts/s57/s57tables.h b/ogr/ogrsf_frmts/s57/s57tables.h
index 0048aed..c6a9034 100644
--- a/ogr/ogrsf_frmts/s57/s57tables.h
+++ b/ogr/ogrsf_frmts/s57/s57tables.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: s57tables.h 32444 2015-12-25 01:14:58Z goatbar $
+ * $Id: s57tables.h 34524 2016-07-03 02:47:25Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Inline tables.
diff --git a/ogr/ogrsf_frmts/s57/s57writer.cpp b/ogr/ogrsf_frmts/s57/s57writer.cpp
index 02e3eed..0bb48f9 100644
--- a/ogr/ogrsf_frmts/s57/s57writer.cpp
+++ b/ogr/ogrsf_frmts/s57/s57writer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: s57writer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  S-57 Translator
  * Purpose:  Implements S57Writer class.
@@ -33,7 +32,7 @@
 #include "ogr_api.h"
 #include "s57.h"
 
-CPL_CVSID("$Id: s57writer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: s57writer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                             S57Writer()                              */
@@ -46,7 +45,7 @@ S57Writer::S57Writer() :
     poClassContentExplorer(NULL),
     nCOMF(10000000),
     nSOMF(10)
-{ }
+{}
 
 /************************************************************************/
 /*                             ~S57Writer()                             */
@@ -64,7 +63,7 @@ S57Writer::~S57Writer()
 /*      Close the current S-57 dataset.                                 */
 /************************************************************************/
 
-int S57Writer::Close()
+bool S57Writer::Close()
 
 {
     if( poModule != NULL )
@@ -73,7 +72,7 @@ int S57Writer::Close()
         delete poModule;
         poModule = NULL;
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -83,7 +82,7 @@ int S57Writer::Close()
 /*      definitions.                                                    */
 /************************************************************************/
 
-int S57Writer::CreateS57File( const char *pszFilename )
+bool S57Writer::CreateS57File( const char *pszFilename )
 
 {
     // TODO: What was oModule for if it was unused?
@@ -422,23 +421,23 @@ int S57Writer::CreateS57File( const char *pszFilename )
     {
         delete poModule;
         poModule = NULL;
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                             WriteDSID()                              */
 /************************************************************************/
 
-int S57Writer::WriteDSID( int nEXPP /*1*/, int nINTU /*4*/,
-                          const char *pszDSNM, const char *pszEDTN,
-                          const char *pszUPDN, const char *pszUADT,
-                          const char *pszISDT, const char *pszSTED,
-                          int nAGEN, const char *pszCOMT,
-                          int nNOMR, int nNOGR, int nNOLR, int nNOIN,
-                          int nNOCN, int nNOED )
+bool S57Writer::WriteDSID( int nEXPP /*1*/, int nINTU /*4*/,
+                           const char *pszDSNM, const char *pszEDTN,
+                           const char *pszUPDN, const char *pszUADT,
+                           const char *pszISDT, const char *pszSTED,
+                           int nAGEN, const char *pszCOMT,
+                           int nNOMR, int nNOGR, int nNOLR, int nNOIN,
+                           int nNOCN, int nNOED )
 
 {
 /* -------------------------------------------------------------------- */
@@ -463,9 +462,9 @@ int S57Writer::WriteDSID( int nEXPP /*1*/, int nINTU /*4*/,
 /*      Add the DSID field.                                             */
 /* -------------------------------------------------------------------- */
     DDFRecord *poRec = MakeRecord();
-    /* DDFField *poField; */
 
-    /* poField = */ poRec->AddField( poModule->FindFieldDefn( "DSID" ) );
+    // DDFField *poField =
+    poRec->AddField( poModule->FindFieldDefn( "DSID" ) );
 
     poRec->SetIntSubfield   ( "DSID", 0, "RCNM", 0, 10 );
     poRec->SetIntSubfield   ( "DSID", 0, "RCID", 0, 1 );
@@ -513,14 +512,14 @@ int S57Writer::WriteDSID( int nEXPP /*1*/, int nINTU /*4*/,
     poRec->Write();
     delete poRec;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                             WriteDSPM()                              */
 /************************************************************************/
 
-int S57Writer::WriteDSPM( int nHDAT, int nVDAT, int nSDAT, int nCSCL )
+bool S57Writer::WriteDSPM( int nHDAT, int nVDAT, int nSDAT, int nCSCL )
 
 {
     if( nHDAT == 0 )
@@ -536,9 +535,9 @@ int S57Writer::WriteDSPM( int nHDAT, int nVDAT, int nSDAT, int nCSCL )
 /*      Add the DSID field.                                             */
 /* -------------------------------------------------------------------- */
     DDFRecord *poRec = MakeRecord();
-    /* DDFField *poField; */
 
-    /* poField = */ poRec->AddField( poModule->FindFieldDefn( "DSPM" ) );
+    // DDFField *poField =
+    poRec->AddField( poModule->FindFieldDefn( "DSPM" ) );
 
     poRec->SetIntSubfield   ( "DSPM", 0, "RCNM", 0, 20 );
     poRec->SetIntSubfield   ( "DSPM", 0, "RCID", 0, 1 );
@@ -560,7 +559,7 @@ int S57Writer::WriteDSPM( int nHDAT, int nVDAT, int nSDAT, int nCSCL )
     poRec->Write();
     delete poRec;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -591,8 +590,8 @@ DDFRecord *S57Writer::MakeRecord()
 /*                           WriteGeometry()                            */
 /************************************************************************/
 
-int S57Writer::WriteGeometry( DDFRecord *poRec, int nVertCount,
-                              double *padfX, double *padfY, double *padfZ )
+bool S57Writer::WriteGeometry( DDFRecord *poRec, int nVertCount,
+                               double *padfX, double *padfY, double *padfZ )
 
 {
     const char *pszFieldName = "SG2D";
@@ -600,17 +599,15 @@ int S57Writer::WriteGeometry( DDFRecord *poRec, int nVertCount,
     if( padfZ != NULL )
         pszFieldName = "SG3D";
 
-    DDFField *poField
-        = poRec->AddField( poModule->FindFieldDefn( pszFieldName ) );
+    DDFField *poField =
+        poRec->AddField( poModule->FindFieldDefn( pszFieldName ) );
 
-    int nRawDataSize;
-    if( padfZ )
-        nRawDataSize = 12 * nVertCount;
-    else
-        nRawDataSize = 8 * nVertCount;
+    const int nRawDataSize = padfZ
+        ? 12 * nVertCount :
+        8 * nVertCount;
 
-    unsigned char *pabyRawData
-        = static_cast<unsigned char *>( CPLMalloc(nRawDataSize) );
+    unsigned char *pabyRawData =
+        static_cast<unsigned char *>( CPLMalloc(nRawDataSize) );
 
     for( int i = 0; i < nVertCount; i++ )
     {
@@ -634,9 +631,9 @@ int S57Writer::WriteGeometry( DDFRecord *poRec, int nVertCount,
         }
     }
 
-    int nSuccess = poRec->SetFieldRaw(
+    const bool nSuccess = CPL_TO_BOOL(poRec->SetFieldRaw(
         poField, 0,
-        reinterpret_cast<const char *>( pabyRawData ), nRawDataSize );
+        reinterpret_cast<const char *>( pabyRawData ), nRawDataSize ));
 
     CPLFree( pabyRawData );
 
@@ -647,18 +644,18 @@ int S57Writer::WriteGeometry( DDFRecord *poRec, int nVertCount,
 /*                           WritePrimitive()                           */
 /************************************************************************/
 
-int S57Writer::WritePrimitive( OGRFeature *poFeature )
+bool S57Writer::WritePrimitive( OGRFeature *poFeature )
 
 {
     DDFRecord *poRec = MakeRecord();
-    /* DDFField *poField; */
     OGRGeometry *poGeom = poFeature->GetGeometryRef();
 
 /* -------------------------------------------------------------------- */
 /*      Add the VRID field.                                             */
 /* -------------------------------------------------------------------- */
 
-    /* poField = */ poRec->AddField( poModule->FindFieldDefn( "VRID" ) );
+    // DDFField *poField =
+    poRec->AddField( poModule->FindFieldDefn( "VRID" ) );
 
     poRec->SetIntSubfield   ( "VRID", 0, "RCNM", 0,
                               poFeature->GetFieldAsInteger( "RCNM") );
@@ -672,15 +669,14 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
     {
-        double dfX, dfY, dfZ;
         OGRPoint *poPoint = (OGRPoint *) poGeom;
 
         CPLAssert( poFeature->GetFieldAsInteger( "RCNM") == RCNM_VI
                    || poFeature->GetFieldAsInteger( "RCNM") == RCNM_VC );
 
-        dfX = poPoint->getX();
-        dfY = poPoint->getY();
-        dfZ = poPoint->getZ();
+        double dfX = poPoint->getX();
+        double dfY = poPoint->getY();
+        double dfZ = poPoint->getZ();
 
         if( dfZ == 0.0 )
             WriteGeometry( poRec, 1, &dfX, &dfY, NULL );
@@ -695,17 +691,16 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
              && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint )
     {
         OGRMultiPoint *poMP = (OGRMultiPoint *) poGeom;
-        int i, nVCount = poMP->getNumGeometries();
-        double *padfX, *padfY, *padfZ;
+        const int nVCount = poMP->getNumGeometries();
 
         CPLAssert( poFeature->GetFieldAsInteger( "RCNM") == RCNM_VI
                    || poFeature->GetFieldAsInteger( "RCNM") == RCNM_VC );
 
-        padfX = (double *) CPLMalloc(sizeof(double) * nVCount);
-        padfY = (double *) CPLMalloc(sizeof(double) * nVCount);
-        padfZ = (double *) CPLMalloc(sizeof(double) * nVCount);
+        double *padfX = (double *) CPLMalloc(sizeof(double) * nVCount);
+        double *padfY = (double *) CPLMalloc(sizeof(double) * nVCount);
+        double *padfZ = (double *) CPLMalloc(sizeof(double) * nVCount);
 
-        for( i = 0; i < nVCount; i++ )
+        for( int i = 0; i < nVCount; i++ )
         {
             OGRPoint *poPoint = (OGRPoint *) poMP->getGeometryRef( i );
             padfX[i] = poPoint->getX();
@@ -727,15 +722,14 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
              && wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
     {
         OGRLineString *poLS = (OGRLineString *) poGeom;
-        int i, nVCount = poLS->getNumPoints();
-        double *padfX, *padfY;
+        const int nVCount = poLS->getNumPoints();
 
         CPLAssert( poFeature->GetFieldAsInteger( "RCNM") == RCNM_VE );
 
-        padfX = (double *) CPLMalloc(sizeof(double) * nVCount);
-        padfY = (double *) CPLMalloc(sizeof(double) * nVCount);
+        double *padfX = (double *) CPLMalloc(sizeof(double) * nVCount);
+        double *padfY = (double *) CPLMalloc(sizeof(double) * nVCount);
 
-        for( i = 0; i < nVCount; i++ )
+        for( int i = 0; i < nVCount; i++ )
         {
             padfX[i] = poLS->getX(i);
             padfY[i] = poLS->getY(i);
@@ -746,7 +740,6 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
 
         CPLFree( padfX );
         CPLFree( padfY );
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -754,22 +747,21 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
     if( poFeature->GetDefnRef()->GetFieldIndex( "NAME_RCNM_0" ) >= 0 )
     {
-        /* DDFField *poField; */
-        char     szName[5];
-        int      nRCID;
-
         CPLAssert( poFeature->GetFieldAsInteger( "NAME_RCNM_0") == RCNM_VC );
 
-        /* poField = */ poRec->AddField( poModule->FindFieldDefn( "VRPT" ) );
+        // DDFField *poField =
+        poRec->AddField( poModule->FindFieldDefn( "VRPT" ) );
 
-        nRCID = poFeature->GetFieldAsInteger( "NAME_RCID_0");
-        szName[0] = RCNM_VC;
-        szName[1] = nRCID & 0xff;
-        szName[2] = (char) ((nRCID & 0xff00) >> 8);
-        szName[3] = (char) ((nRCID & 0xff0000) >> 16);
-        szName[4] = (char) ((nRCID & 0xff000000) >> 24);
+        const int nRCID0 = poFeature->GetFieldAsInteger( "NAME_RCID_0");
+        char szName0[5] = {
+            RCNM_VC,
+            static_cast<char>(nRCID0 & 0xff),
+            static_cast<char>((nRCID0 & 0xff00) >> 8),
+            static_cast<char>((nRCID0 & 0xff0000) >> 16),
+            static_cast<char>((nRCID0 & 0xff000000) >> 24)
+        };
 
-        poRec->SetStringSubfield( "VRPT", 0, "NAME", 0, szName, 5 );
+        poRec->SetStringSubfield( "VRPT", 0, "NAME", 0, szName0, 5 );
         poRec->SetIntSubfield   ( "VRPT", 0, "ORNT", 0,
                                   poFeature->GetFieldAsInteger( "ORNT_0") );
         poRec->SetIntSubfield   ( "VRPT", 0, "USAG", 0,
@@ -779,14 +771,16 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
         poRec->SetIntSubfield   ( "VRPT", 0, "MASK", 0,
                                   poFeature->GetFieldAsInteger( "MASK_0") );
 
-        nRCID = poFeature->GetFieldAsInteger( "NAME_RCID_1");
-        szName[0] = RCNM_VC;
-        szName[1] = nRCID & 0xff;
-        szName[2] = (char) ((nRCID & 0xff00) >> 8);
-        szName[3] = (char) ((nRCID & 0xff0000) >> 16);
-        szName[4] = (char) ((nRCID & 0xff000000) >> 24);
+        const int nRCID1 = poFeature->GetFieldAsInteger( "NAME_RCID_1");
+        const char szName1[5] = {
+            RCNM_VC,
+            static_cast<char>(nRCID1 & 0xff),
+            static_cast<char>((nRCID1 & 0xff00) >> 8),
+            static_cast<char>((nRCID1 & 0xff0000) >> 16),
+            static_cast<char>((nRCID1 & 0xff000000) >> 24)
+        };
 
-        poRec->SetStringSubfield( "VRPT", 0, "NAME", 1, szName, 5 );
+        poRec->SetStringSubfield( "VRPT", 0, "NAME", 1, szName1, 5 );
         poRec->SetIntSubfield   ( "VRPT", 0, "ORNT", 1,
                                   poFeature->GetFieldAsInteger( "ORNT_1") );
         poRec->SetIntSubfield   ( "VRPT", 0, "USAG", 1,
@@ -803,7 +797,7 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
     poRec->Write();
     delete poRec;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -813,11 +807,11 @@ int S57Writer::WritePrimitive( OGRFeature *poFeature )
 static char GetHEXChar( const char *pszSrcHEXString )
 
 {
-    int nResult = 0;
-
     if( pszSrcHEXString[0] == '\0' || pszSrcHEXString[1] == '\0' )
         return (char) 0;
 
+    int nResult = 0;
+
     if( pszSrcHEXString[0] >= '0' && pszSrcHEXString[0] <= '9' )
         nResult += (pszSrcHEXString[0] - '0') * 16;
     else if( pszSrcHEXString[0] >= 'a' && pszSrcHEXString[0] <= 'f' )
@@ -839,7 +833,7 @@ static char GetHEXChar( const char *pszSrcHEXString )
 /*                        WriteCompleteFeature()                        */
 /************************************************************************/
 
-int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
+bool S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
 
 {
     OGRFeatureDefn *poFDefn = poFeature->GetDefnRef();
@@ -860,9 +854,8 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Add the FRID.                                                   */
 /* -------------------------------------------------------------------- */
-    /*DDFField *poField;*/
-
-    /*poField = */poRec->AddField( poModule->FindFieldDefn( "FRID" ) );
+    // DDFField *poField =
+    poRec->AddField( poModule->FindFieldDefn( "FRID" ) );
 
     poRec->SetIntSubfield   ( "FRID", 0, "RCNM", 0, 100 );
     poRec->SetIntSubfield   ( "FRID", 0, "RCID", 0,
@@ -897,31 +890,34 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
         && !WriteATTF( poRec, poFeature ) )
     {
         delete poRec;
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Add the FSPT if needed.                                         */
 /* -------------------------------------------------------------------- */
-    if( poFeature->IsFieldSet( poFeature->GetFieldIndex("NAME_RCNM") ) )
+    if( poFeature->IsFieldSetAndNotNull( poFeature->GetFieldIndex("NAME_RCNM") ) )
     {
-        int nItemCount, i;
-        const int *panRCNM, *panRCID, *panORNT, *panUSAG, *panMASK;
-        unsigned char *pabyRawData;
-        int nRawDataSize;
-
-        panRCNM = poFeature->GetFieldAsIntegerList( "NAME_RCNM", &nItemCount );
-        panRCID = poFeature->GetFieldAsIntegerList( "NAME_RCID", &nItemCount );
-        panORNT = poFeature->GetFieldAsIntegerList( "ORNT", &nItemCount );
-        panUSAG = poFeature->GetFieldAsIntegerList( "USAG", &nItemCount );
-        panMASK = poFeature->GetFieldAsIntegerList( "MASK", &nItemCount );
-
+        int nItemCount = 0;
+
+        const int *panRCNM =
+            poFeature->GetFieldAsIntegerList( "NAME_RCNM", &nItemCount );
+        const int *panRCID =
+            poFeature->GetFieldAsIntegerList( "NAME_RCID", &nItemCount );
+        const int *panORNT =
+            poFeature->GetFieldAsIntegerList( "ORNT", &nItemCount );
+        const int *panUSAG =
+            poFeature->GetFieldAsIntegerList( "USAG", &nItemCount );
+        const int *panMASK =
+            poFeature->GetFieldAsIntegerList( "MASK", &nItemCount );
+
+        // cppcheck-suppress duplicateExpression
         CPLAssert( sizeof(int) == sizeof(GInt32) );
 
-        nRawDataSize = nItemCount * 8;
-        pabyRawData = (unsigned char *) CPLMalloc(nRawDataSize);
+        const int nRawDataSize = nItemCount * 8;
+        unsigned char *pabyRawData = (unsigned char *) CPLMalloc(nRawDataSize);
 
-        for( i = 0; i < nItemCount; i++ )
+        for( int i = 0; i < nItemCount; i++ )
         {
             GInt32 nRCID = CPL_LSBWORD32(panRCID[i]);
 
@@ -987,7 +983,7 @@ int S57Writer::WriteCompleteFeature( OGRFeature *poFeature )
     poRec->Write();
     delete poRec;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -1006,44 +1002,41 @@ void S57Writer::SetClassBased( S57ClassRegistrar * poReg,
 /*                             WriteATTF()                              */
 /************************************************************************/
 
-int S57Writer::WriteATTF( DDFRecord *poRec, OGRFeature *poFeature )
+bool S57Writer::WriteATTF( DDFRecord *poRec, OGRFeature *poFeature )
 {
-    int nRawSize=0, nACount = 0;
-    char achRawData[5000];
-    char **papszAttrList;
-
     CPLAssert( poRegistrar != NULL );
 
 /* -------------------------------------------------------------------- */
 /*      Loop over all attributes.                                       */
 /* -------------------------------------------------------------------- */
-    papszAttrList = poClassContentExplorer->GetAttributeList(NULL);
+    int nRawSize = 0;
+    int nACount = 0;
+    char achRawData[5000] = {};
+
+    char **papszAttrList = poClassContentExplorer->GetAttributeList(NULL);
 
     for( int iAttr = 0; papszAttrList[iAttr] != NULL; iAttr++ )
     {
-        int iField = poFeature->GetFieldIndex( papszAttrList[iAttr] );
+        const int iField = poFeature->GetFieldIndex( papszAttrList[iAttr] );
         OGRFieldType eFldType =
             poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType();
-        int nATTLInt;
-        GUInt16 nATTL;
-        const char *pszATVL;
 
         if( iField < 0 )
             continue;
 
-        if( !poFeature->IsFieldSet( iField ) )
+        if( !poFeature->IsFieldSetAndNotNull( iField ) )
             continue;
 
-        nATTLInt = poRegistrar->FindAttrByAcronym( papszAttrList[iAttr] );
+        const int nATTLInt = poRegistrar->FindAttrByAcronym( papszAttrList[iAttr] );
         if( nATTLInt == -1 )
             continue;
 
-        nATTL = (GUInt16)nATTLInt;
-        nATTL = CPL_LSBWORD16( nATTL );
+        GUInt16 nATTL = (GUInt16)nATTLInt;
+        CPL_LSBPTR16( &nATTL );
         memcpy( achRawData + nRawSize, &nATTL, 2 );
         nRawSize += 2;
 
-        pszATVL = poFeature->GetFieldAsString( iField );
+        const char *pszATVL = poFeature->GetFieldAsString( iField );
 
         // Special hack to handle special "empty" marker in integer fields.
         if( atoi(pszATVL) == EMPTY_NUMBER_MARKER
@@ -1055,7 +1048,7 @@ int S57Writer::WriteATTF( DDFRecord *poRec, OGRFeature *poFeature )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Too much ATTF data for fixed buffer size." );
-            return FALSE;
+            return false;
         }
 
         // copy data into record buffer.
@@ -1070,14 +1063,12 @@ int S57Writer::WriteATTF( DDFRecord *poRec, OGRFeature *poFeature )
 /*      If we got no attributes, return without adding ATTF.            */
 /* -------------------------------------------------------------------- */
     if( nACount == 0 )
-        return TRUE;
+        return true;
 
 /* -------------------------------------------------------------------- */
 /*      Write the new field value.                                      */
 /* -------------------------------------------------------------------- */
-    DDFField *poField;
-
-    poField = poRec->AddField( poModule->FindFieldDefn( "ATTF" ) );
+    DDFField *poField = poRec->AddField( poModule->FindFieldDefn( "ATTF" ) );
 
-    return poRec->SetFieldRaw( poField, 0, achRawData, nRawSize );
+    return CPL_TO_BOOL(poRec->SetFieldRaw( poField, 0, achRawData, nRawSize ));
 }
diff --git a/ogr/ogrsf_frmts/sde/ogr_sde.h b/ogr/ogrsf_frmts/sde/ogr_sde.h
index 2694a83..f591076 100644
--- a/ogr/ogrsf_frmts/sde/ogr_sde.h
+++ b/ogr/ogrsf_frmts/sde/ogr_sde.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sde.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogr_sde.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR SDE driver.
@@ -49,7 +49,6 @@
 /*                            OGRSDELayer                                */
 /************************************************************************/
 
-
 class OGRSDEDataSource;
 
 class OGRSDELayer : public OGRLayer
@@ -90,7 +89,6 @@ class OGRSDELayer : public OGRLayer
 
     int                 bUseNSTRING;
 
-
     char              **papszAllColumns;
     std::vector<int>    anFieldMap;     // SDE index of OGR field.
     std::vector<int>    anFieldTypeMap; // SDE type
@@ -118,30 +116,30 @@ class OGRSDELayer : public OGRLayer
 
     int                 Initialize( const char *, const char *, const char * );
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
     OGRErr              ResetStream();
 
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
-    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce );
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-    virtual GIntBig     GetFeatureCount( int bForce );
+    virtual GIntBig     GetFeatureCount( int bForce ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char *pszQuery );
+    virtual OGRErr      SetAttributeFilter( const char *pszQuery ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poFieldIn,
-                                     int bApproxOK );
+                                     int bApproxOK ) override;
 
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     // The following methods are not base class overrides
     //void                SetOptions( char ** );
@@ -183,18 +181,18 @@ class OGRSDEDataSource : public OGRDataSource
                                    const char *pszShapeColumn,
                                    LONG nFIDColumnType );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
     virtual OGRLayer    *ICreateLayer( const char *,
                                       OGRSpatialReference * = NULL,
                                       OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+                                      char ** = NULL ) override;
 
-    virtual OGRErr      DeleteLayer( int );
+    virtual OGRErr      DeleteLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     SE_CONNECTION       GetConnection() { return hConnection; }
     LONG                GetState() {return nState; }
@@ -223,15 +221,14 @@ class OGRSDEDataSource : public OGRDataSource
 class OGRSDEDriver : public OGRSFDriver
 {
   public:
-                ~OGRSDEDriver();
+    virtual ~OGRSDEDriver();
 
-    const char *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
     virtual OGRDataSource *CreateDataSource( const char *pszName,
-                                             char ** = NULL);
+                                             char ** = NULL) override;
 };
 
-
 #endif /* ndef _OGR_PG_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp b/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
index f888cf3..921f985 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdedatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsdedatasource.cpp 36090 2016-11-03 14:22:30Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDEDataSource class.
@@ -34,7 +33,7 @@
 #include "cpl_string.h"
 #include "gdal.h"
 
-CPL_CVSID("$Id: ogrsdedatasource.cpp 36090 2016-11-03 14:22:30Z rouault $");
+CPL_CVSID("$Id: ogrsdedatasource.cpp 36332 2016-11-20 15:19:39Z rouault $");
 
 /************************************************************************/
 /*                          OGRSDEDataSource()                           */
@@ -68,7 +67,6 @@ OGRSDEDataSource::~OGRSDEDataSource()
     LONG        nSDEErr;
     char       pszVersionName[SE_MAX_VERSION_LEN];
 
-
     // Commit our transactions if we were opened for update
     if (bDSUpdate && bDSUseVersionEdits && (nNextState != -2 && nState != SE_DEFAULT_STATE_ID )  ) {
         CPLDebug("OGR_SDE", "Moving states from %ld to %ld",
@@ -209,7 +207,7 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
         CPLError( CE_Failure, CPLE_OpenFailed,
                   "SDE connect string had wrong number of arguments.\n"
                   "Expected 'SDE:server,instance,database,username,password,layer'\n"
-		          "The layer name value is optional.\n"
+                  "The layer name value is optional.\n"
                   "Got '%s'",
                   pszNewName );
         return FALSE;
@@ -218,7 +216,7 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
 /* -------------------------------------------------------------------- */
 /*      Try to establish connection.                                    */
 /* -------------------------------------------------------------------- */
-    int 	nSDEErr;
+    int nSDEErr;
     SE_ERROR    sSDEErrorInfo;
 
     nSDEErr = SE_connection_create( papszTokens[0],
@@ -248,7 +246,6 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
         bDSUseVersionEdits = FALSE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Set unprotected concurrency policy, suitable for single         */
 /*      threaded access.                                                */
@@ -271,7 +268,6 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
         OpenSpatialTable( papszTokens[5] );
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Create a new version from the parent version if we were given   */
 /*      both the child and parent version values                        */
@@ -326,7 +322,6 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
 
         const char* pszVersionName= CPLSPrintf( "%s.%s", username, papszTokens[7]);
 
-
         CPLDebug("OGR_SDE", "Setting version to %s", pszVersionName);
         CPLDebug("OGR_SDE", "Opening layer %s", papszTokens[5]);
         OpenSpatialTable( papszTokens[5] );
@@ -356,7 +351,6 @@ int OGRSDEDataSource::Open( const char * pszNewName, int bUpdate )
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                             CreateVersion()                          */
 /************************************************************************/
@@ -429,8 +423,9 @@ int OGRSDEDataSource::CreateVersion( const char* pszParentVersion, const char* p
                            "  Your client/server versions must not match or "
                            "you have some other major configuration problem");
             return FALSE;
-
-        } else {
+        }
+        else
+        {
             IssueSDEError( nSDEErr, "SE_version_get_info parent" );
             return FALSE;
         }
@@ -645,12 +640,10 @@ int OGRSDEDataSource::SetVersionState( const char* pszVersionName ) {
         SE_stateinfo_free(hDummyStateInfo);
         SE_stateinfo_free(hCurrentStateInfo);
         SE_stateinfo_free(hNextStateInfo);
-
     }
     return TRUE;
-
-
 }
+
 /************************************************************************/
 /*                             OpenTable()                              */
 /************************************************************************/
@@ -783,7 +776,6 @@ OGRErr OGRSDEDataSource::DeleteLayer( int iLayer )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                            CleanupLayerCreation()                    */
 /************************************************************************/
@@ -792,7 +784,6 @@ void OGRSDEDataSource::CleanupLayerCreation(const char* pszLayerName)
 
     LONG nSDEErr;
 
-
     nSDEErr = SE_registration_delete( hConnection, pszLayerName );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -807,7 +798,6 @@ void OGRSDEDataSource::CleanupLayerCreation(const char* pszLayerName)
     }
 
     CPLDebug( "OGR_SDE", "CleanupLayerCreation(%s) successful", pszLayerName );
-
 }
 
 /************************************************************************/
@@ -842,7 +832,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
             || EQUAL(pszLayerName,
                      papoLayers[iLayer]->GetLayerDefn()->GetName()) )
         {
-            if( CSLFetchBoolean( papszOptions, "OVERWRITE", FALSE ) )
+            if( CPLFetchBool( papszOptions, "OVERWRITE", false ) )
             {
                 DeleteLayer( iLayer );
             }
@@ -883,7 +873,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         if( EQUAL(szTableName,pszLayerName)
             || EQUAL(szTableName,osFullName) )
         {
-            if( !CSLFetchBoolean( papszOptions, "OVERWRITE", FALSE ) )
+            if( !CPLFetchBool( papszOptions, "OVERWRITE", false ) )
             {
                 CPLError(
                     CE_Failure, CPLE_AppDefined,
@@ -914,12 +904,10 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
     const char         *pszDbtuneKeyword;
     const char         *pszLayerDescription;
 
-
     pszGeometryName = CSLFetchNameValue( papszOptions, "GEOMETRY_NAME" );
     if( pszGeometryName == NULL )
         pszGeometryName = "SHAPE";
 
-
     pszExpectedFIDName = CPLGetConfigOption( "SDE_FID", "OBJECTID" );
 
     pszDbtuneKeyword = CSLFetchNameValue( papszOptions, "SDE_KEYWORD" );
@@ -957,7 +945,6 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Convert the OGRSpatialReference to a SDE coordref object        */
 /* -------------------------------------------------------------------- */
@@ -973,7 +960,6 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Construct the layer info necessary to spatially enable          */
 /*      the table.                                                      */
@@ -1041,7 +1027,6 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
 
-
     // Set geometry column name
     nSDEErr = SE_layerinfo_set_spatial_column( hLayerInfo, pszLayerName,
                                                pszGeometryName );
@@ -1097,7 +1082,6 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
 
-
     nSDEErr = SE_layerinfo_set_description( hLayerInfo, pszLayerDescription );
     if( nSDEErr != SE_SUCCESS )
     {
@@ -1107,7 +1091,6 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
         return NULL;
     }
 
-
     // Set grid size
     nSDEErr = SE_layerinfo_set_grid_sizes( hLayerInfo,
                                            OGR_SDE_LAYER_CO_GRID1,
@@ -1194,7 +1177,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
      * If the layer creation option 'MULTIVERSION' is set, enable
      * multi-versioning for this layer
      */
-    if( CSLFetchBoolean( papszOptions, "SDE_MULTIVERSION", TRUE ) )
+    if( CPLFetchBool( papszOptions, "SDE_MULTIVERSION", true ) )
     {
         CPLDebug("OGR_SDE","Setting multiversion to true");
         nSDEErr = SE_reginfo_set_multiversion( hRegInfo, TRUE );
@@ -1252,7 +1235,7 @@ OGRSDEDataSource::ICreateLayer( const char * pszLayerName,
     poLayer->SetFIDColType( SE_REGISTRATION_ROW_ID_COLUMN_TYPE_SDE );
 
     poLayer->SetUseNSTRING(
-        CSLFetchBoolean( papszOptions, "USE_NSTRING", FALSE ) );
+        CPLFetchBool( papszOptions, "USE_NSTRING", false ) );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
@@ -1479,7 +1462,7 @@ OGRErr OGRSDEDataSource::ConvertOSRtoSDESpatRef( OGRSpatialReference *poSRS,
                   sGenericEnvelope.maxy );
     }
 
-    if( poSRS && poSRS->IsGeographic() )
+    if( poSRS->IsGeographic() )
     {
         LONG nSDEErr;
 
diff --git a/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp b/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp
index ac7a540..8f61ddc 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdedriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsdedriver.cpp 36090 2016-11-03 14:22:30Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDEDriver class.
@@ -32,7 +31,7 @@
 #include "ogr_sde.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsdedriver.cpp 36090 2016-11-03 14:22:30Z rouault $");
+CPL_CVSID("$Id: ogrsdedriver.cpp 36089 2016-11-03 14:22:21Z rouault $");
 
 /************************************************************************/
 /*                            ~OGRSDEDriver()                            */
diff --git a/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp b/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
index 7a3e79b..0a0523d 100644
--- a/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
+++ b/ogr/ogrsf_frmts/sde/ogrsdelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsdelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSDELayer class.
@@ -33,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsdelayer.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsdelayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                            OGRSDELayer()                             */
@@ -61,6 +60,11 @@ OGRSDELayer::OGRSDELayer( OGRSDEDataSource *poDSIn, int bUpdate )
     papszAllColumns = NULL;
     bHaveLayerInfo = FALSE;
     bUseNSTRING = FALSE;
+
+    pszOwnerName = NULL;
+    pszDbTableName = NULL;
+    bVersioned = FALSE;
+    bQueryActive = FALSE;
 }
 
 /************************************************************************/
@@ -351,8 +355,15 @@ int OGRSDELayer::NeedLayerInfo()
 
         LFLOAT falsex, falsey, xyunits;
         nSDEErr = SE_coordref_get_xy( hCoordRef, &falsex, &falsey, &xyunits );
-        CPLDebug( "SDE", "SE_coordref_get_xy(%s) = %g/%g/%g",
-                  pszDbTableName, falsex, falsey, xyunits );
+        if( nSDEErr != SE_SUCCESS )
+        {
+            poDS->IssueSDEError( nSDEErr, "SE_coordref_get_xy" );
+        }
+        else
+        {
+            CPLDebug( "SDE", "SE_coordref_get_xy(%s) = %g/%g/%g",
+                    pszDbTableName, falsex, falsey, xyunits );
+        }
     }
 
     return TRUE;
@@ -384,7 +395,7 @@ OGRwkbGeometryType OGRSDELayer::DiscoverLayerType()
         return wkbUnknown;
     }
 
-    int bIsMultipart = ( nShapeTypeMask & SE_MULTIPART_TYPE_MASK ? 1 : 0);
+    int bIsMultipart = (nShapeTypeMask & SE_MULTIPART_TYPE_MASK) ? 1 : 0;
     nShapeTypeMask &= ~SE_MULTIPART_TYPE_MASK;
 
     // Since we assume that all layers can bear a NULL geometry,
@@ -625,7 +636,7 @@ int OGRSDELayer::InstallQuery( int bCountingOnly )
         SE_SHAPE hRectShape;
         SHORT nSearchOrder = SE_SPATIAL_FIRST;
 
-        if( osAttributeFilter.size() > 0 )
+        if( !osAttributeFilter.empty() )
         {
             const char *pszOrder = CPLGetConfigOption( "OGR_SDE_SEARCHORDER",
                                                        "ATTRIBUTE_FIRST" );
@@ -802,7 +813,7 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
     {
         OGRFieldDefn   *poFieldDefn = poFeatureDefn->GetFieldDefn(i);
 
-        if( !poFeature->IsFieldSet(i) )
+        if( !poFeature->IsFieldSetAndNotNull(i) )
             continue;
 
         // Skip FID and Geometry columns
@@ -881,7 +892,6 @@ OGRErr OGRSDELayer::TranslateOGRRecord( OGRFeature *poFeature,
         return OGRERR_FAILURE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Set the feature attributes                                      */
 /* -------------------------------------------------------------------- */
@@ -1190,6 +1200,7 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
                 poDS->IssueSDEError( nSDEErr, "SE_shape_make_nil" );
                 return OGRERR_FAILURE;
             }
+            return OGRERR_NONE;
         }
 
         // Get total number of points in polygon
@@ -1283,7 +1294,6 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
         if( b3D )
             panfZcoords = (LFLOAT *) CPLMalloc( sizeof(LFLOAT) * nPoints );
 
-
         // Build arrays of points and part offsets
         for( i=0; i < nParts; i++ )
         {
@@ -1344,7 +1354,6 @@ OGRErr OGRSDELayer::TranslateOGRGeometry( OGRGeometry *poGeom,
         }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Translate LINESTRING/MULTILINESTRING type.                      */
 /* -------------------------------------------------------------------- */
@@ -1592,7 +1601,7 @@ OGRGeometry *OGRSDELayer::TranslateSDEGeometry( SE_SHAPE hShape )
       case SG_MULTI_SIMPLE_LINE_SHAPE:
       {
           OGRMultiLineString *poMLS = new OGRMultiLineString();
-	  int iPart;
+          int iPart;
 
           CPLAssert( nPartCount == nSubPartCount );
 
@@ -1833,7 +1842,6 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
 
                   poFeat->SetField( i, pszUTF8 );
                   CPLFree( pszUTF8 );
-
               }
               else if( nSDEErr != SE_NULL_VALUE )
               {
@@ -1899,7 +1907,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
                   /* the returned string is not null-terminated */
                   char* sClobstring = (char*)CPLMalloc(sizeof(char)*(sClobVal.clob_length+1));
                   memcpy(sClobstring, sClobVal.clob_buffer, sClobVal.clob_length);
-				  sClobstring[sClobVal.clob_length] = '\0';
+                  sClobstring[sClobVal.clob_length] = '\0';
 
                   poFeat->SetField( i, sClobstring );
                   SE_clob_free( &sClobVal );
@@ -1928,7 +1936,7 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
                   /* the returned string is not null-terminated */
                   SE_WCHAR* sNclobstring = (SE_WCHAR*)CPLMalloc(sizeof(char)*(sNclobVal.nclob_length+2));
                   memcpy(sNclobstring, sNclobVal.nclob_buffer, sNclobVal.nclob_length);
-				  sNclobstring[sNclobVal.nclob_length / 2] = '\0';
+                  sNclobstring[sNclobVal.nclob_length / 2] = '\0';
 
                   char* pszUTF8 = CPLRecodeFromWChar((const wchar_t*)sNclobstring, CPL_ENC_UTF16, CPL_ENC_UTF8);
 
@@ -1955,9 +1963,9 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
               nSDEErr = SE_stream_get_date( hStream, anFieldMap[i]+1,
                                             &sDateVal );
               if( nSDEErr == SE_SUCCESS )
-			  {
-			      poFeat->SetField( i, sDateVal.tm_year + 1900, sDateVal.tm_mon + 1, sDateVal.tm_mday,
-					  sDateVal.tm_hour, sDateVal.tm_min, sDateVal.tm_sec, (sDateVal.tm_isdst > 0));
+              {
+                poFeat->SetField( i, sDateVal.tm_year + 1900, sDateVal.tm_mon + 1, sDateVal.tm_mday,
+                                  sDateVal.tm_hour, sDateVal.tm_min, sDateVal.tm_sec, (sDateVal.tm_isdst > 0));
               }
               else if( nSDEErr != SE_NULL_VALUE )
               {
@@ -1966,7 +1974,6 @@ OGRFeature *OGRSDELayer::TranslateSDERecord()
               }
           }
           break;
-
         }
     }
 
@@ -2102,7 +2109,6 @@ OGRFeature *OGRSDELayer::GetFeature( GIntBig nFeatureId )
     return TranslateSDERecord();
 }
 
-
 /************************************************************************/
 /*                          ResetStream()                               */
 /*                                                                      */
@@ -2350,7 +2356,6 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
         return OGRERR_FAILURE;
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Set field width and precision                                   */
 /* -------------------------------------------------------------------- */
@@ -2383,7 +2388,6 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
         }
     }
 
-
 /* -------------------------------------------------------------------- */
 /*      Create the new field                                            */
 /* -------------------------------------------------------------------- */
@@ -2402,7 +2406,6 @@ OGRErr OGRSDELayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           ISetFeature()                               */
 /************************************************************************/
@@ -2548,7 +2551,6 @@ OGRErr OGRSDELayer::DeleteFeature( GIntBig nFID )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/sdts/GNUmakefile b/ogr/ogrsf_frmts/sdts/GNUmakefile
index bd21ccc..3024477 100644
--- a/ogr/ogrsf_frmts/sdts/GNUmakefile
+++ b/ogr/ogrsf_frmts/sdts/GNUmakefile
@@ -32,6 +32,6 @@ sdtslib-marker:	$(SDTSLIB)
 	./install-libs.sh $(SDTSLIB) $(FRMTSLIB)
 	touch sdtslib-marker
 
-libs:	
+libs:
 	(cd ../../../frmts/iso8211; $(MAKE))
 	(cd ../../../frmts/sdts; $(MAKE))
diff --git a/ogr/ogrsf_frmts/sdts/ogr_sdts.h b/ogr/ogrsf_frmts/sdts/ogr_sdts.h
index 1c3df5c..c1ffe1d 100644
--- a/ogr/ogrsf_frmts/sdts/ogr_sdts.h
+++ b/ogr/ogrsf_frmts/sdts/ogr_sdts.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sdts.h 32177 2015-12-14 07:25:30Z goatbar $
+ * $Id: ogr_sdts.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  STS Translator
  * Purpose:  Definition of classes finding SDTS support into OGRDriver
@@ -52,23 +52,16 @@ class OGRSDTSLayer : public OGRLayer
 
     OGRFeature         *GetNextUnfilteredFeature();
 
-    void                BuildPolygons();
-    int                 bPolygonsBuilt;
-
   public:
                         OGRSDTSLayer( SDTSTransfer *, int, OGRSDTSDataSource*);
                         ~OGRSDTSLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
-
-//    OGRFeature         *GetFeature( GIntBig nFeatureId );
-
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
 
-//    GIntBig             GetFeatureCount( int );
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -91,10 +84,10 @@ class OGRSDTSDataSource : public OGRDataSource
 
     int                 Open( const char * pszFilename, int bTestOpen );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
-    int                 TestCapability( const char * );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
+    int                 TestCapability( const char * ) override;
 
     OGRSpatialReference *GetSpatialRef() { return poSRS; }
 };
diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp
index d22bf87..ab73fb3 100644
--- a/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp
+++ b/ogr/ogrsf_frmts/sdts/ogrsdtsdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsdtsdatasource.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implements OGRSDTSDataSource class
@@ -31,23 +30,19 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsdtsdatasource.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+CPL_CVSID("$Id: ogrsdtsdatasource.cpp 36332 2016-11-20 15:19:39Z rouault $");
 
 /************************************************************************/
 /*                          OGRSDTSDataSource()                          */
 /************************************************************************/
 
-OGRSDTSDataSource::OGRSDTSDataSource()
-
-{
-    nLayers = 0;
-    papoLayers = NULL;
-
-    pszName = NULL;
-    poSRS = NULL;
-
-    poTransfer = NULL;
-}
+OGRSDTSDataSource::OGRSDTSDataSource() :
+    poTransfer(NULL),
+    pszName(NULL),
+    nLayers(0),
+    papoLayers(NULL),
+    poSRS(NULL)
+{}
 
 /************************************************************************/
 /*                         ~OGRSDTSDataSource()                          */
@@ -56,9 +51,7 @@ OGRSDTSDataSource::OGRSDTSDataSource()
 OGRSDTSDataSource::~OGRSDTSDataSource()
 
 {
-    int         i;
-
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
 
     CPLFree( papoLayers );
@@ -117,13 +110,11 @@ int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )
 /* -------------------------------------------------------------------- */
     if( bTestOpen )
     {
-        FILE    *fp;
-        char    pachLeader[10];
-
-        fp = VSIFOpen( pszFilename, "rb" );
+        FILE *fp = VSIFOpen( pszFilename, "rb" );
         if( fp == NULL )
             return FALSE;
 
+        char pachLeader[10] = {};
         if( VSIFRead( pachLeader, 1, 10, fp ) != 10
             || (pachLeader[5] != '1' && pachLeader[5] != '2'
                 && pachLeader[5] != '3' )
@@ -173,11 +164,7 @@ int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )
     else if( EQUAL(poXREF->pszDatum,"WGC") )
         poSRS->SetGeogCS("WGS 72", "WGS_1972", "NWL 10D", 6378135, 298.26 );
 
-    else if( EQUAL(poXREF->pszDatum,"WGE") )
-        poSRS->SetGeogCS("WGS 84", "WGS_1984",
-                         "WGS 84", 6378137, 298.257223563 );
-
-    else
+    else /* if( EQUAL(poXREF->pszDatum,"WGE") ) or default case */
         poSRS->SetGeogCS("WGS 84", "WGS_1984",
                          "WGS 84", 6378137, 298.257223563 );
 
@@ -188,12 +175,11 @@ int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )
 /* -------------------------------------------------------------------- */
     for( int iLayer = 0; iLayer < poTransfer->GetLayerCount(); iLayer++ )
     {
-        SDTSIndexedReader       *poReader;
-
         if( poTransfer->GetLayerType( iLayer ) == SLTRaster )
             continue;
 
-        poReader = poTransfer->GetLayerIndexedReader( iLayer );
+        SDTSIndexedReader *poReader =
+            poTransfer->GetLayerIndexedReader( iLayer );
         if( poReader == NULL )
             continue;
 
@@ -204,4 +190,3 @@ int OGRSDTSDataSource::Open( const char * pszFilename, int bTestOpen )
 
     return TRUE;
 }
-
diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp
index 0ad918e..5a6c7d2 100644
--- a/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp
+++ b/ogr/ogrsf_frmts/sdts/ogrsdtsdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsdtsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  SDTS Translator
  * Purpose:  Implements OGRSDTSDriver
@@ -30,7 +29,7 @@
 #include "ogr_sdts.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsdtsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrsdtsdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
diff --git a/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp b/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp
index 5158f17..8c92463 100644
--- a/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp
+++ b/ogr/ogrsf_frmts/sdts/ogrsdtslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsdtslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  SDTSReader
  * Purpose:  Implements OGRSDTSLayer class.
@@ -31,7 +30,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsdtslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrsdtslayer.cpp 36332 2016-11-20 15:19:39Z rouault $");
 
 /************************************************************************/
 /*                            OGRSDTSLayer()                            */
@@ -42,19 +41,16 @@ CPL_CVSID("$Id: ogrsdtslayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
                             OGRSDTSDataSource * poDSIn ) :
-    bPolygonsBuilt(FALSE)
+    poFeatureDefn(NULL),
+    poTransfer(poTransferIn),
+    iLayer(iLayerIn),
+    poReader(poTransferIn->GetLayerIndexedReader( iLayerIn )),
+    poDS(poDSIn)
 {
-    poDS = poDSIn;
-
-    poTransfer = poTransferIn;
-    iLayer = iLayerIn;
-
-    poReader = poTransfer->GetLayerIndexedReader( iLayer );
-
 /* -------------------------------------------------------------------- */
 /*      Define the feature.                                             */
 /* -------------------------------------------------------------------- */
-    int         iCATDEntry = poTransfer->GetLayerCATDEntry( iLayer );
+    const int iCATDEntry = poTransfer->GetLayerCATDEntry( iLayer );
 
     poFeatureDefn =
         new OGRFeatureDefn(poTransfer->GetCATD()->GetEntryModule(iCATDEntry));
@@ -91,7 +87,7 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
 /* -------------------------------------------------------------------- */
 /*      Add schema from referenced attribute records.                   */
 /* -------------------------------------------------------------------- */
-    char        **papszATIDRefs = NULL;
+    char **papszATIDRefs = NULL;
 
     if( poTransfer->GetLayerType(iLayer) != SLTAttr )
         papszATIDRefs = poReader->ScanModuleReferences();
@@ -103,23 +99,21 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
          papszATIDRefs != NULL && papszATIDRefs[iTable] != NULL;
          iTable++ )
     {
-        SDTSAttrReader  *poAttrReader;
-        DDFFieldDefn    *poFDefn;
-
 /* -------------------------------------------------------------------- */
 /*      Get the attribute table reader, and the associated user         */
 /*      attribute field.                                                */
 /* -------------------------------------------------------------------- */
-        int nLayerIdx = poTransfer->FindLayer( papszATIDRefs[iTable] );
+        const int nLayerIdx = poTransfer->FindLayer( papszATIDRefs[iTable] );
         if( nLayerIdx < 0 )
             continue;
-        poAttrReader = (SDTSAttrReader *)
+        SDTSAttrReader *poAttrReader = (SDTSAttrReader *)
             poTransfer->GetLayerIndexedReader(nLayerIdx);
 
         if( poAttrReader == NULL )
             continue;
 
-        poFDefn = poAttrReader->GetModule()->FindFieldDefn( "ATTP" );
+        DDFFieldDefn *poFDefn =
+            poAttrReader->GetModule()->FindFieldDefn( "ATTP" );
         if( poFDefn == NULL )
             poFDefn = poAttrReader->GetModule()->FindFieldDefn( "ATTS" );
         if( poFDefn == NULL )
@@ -129,18 +123,17 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
 /*      Process each user subfield on the attribute table into an       */
 /*      OGR field definition.                                           */
 /* -------------------------------------------------------------------- */
-        for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
+        for( int iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
         {
-            DDFSubfieldDefn     *poSFDefn = poFDefn->GetSubfield( iSF );
-            int                 nWidth = poSFDefn->GetWidth();
-            char                *pszFieldName;
+            DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield( iSF );
+            const int nWidth = poSFDefn->GetWidth();
 
-            if( poFeatureDefn->GetFieldIndex( poSFDefn->GetName() ) != -1 )
-                pszFieldName = CPLStrdup( CPLSPrintf( "%s_%s",
-                                                      papszATIDRefs[iTable],
-                                                      poSFDefn->GetName() ) );
-            else
-                pszFieldName = CPLStrdup( poSFDefn->GetName() );
+            char *pszFieldName =
+                poFeatureDefn->GetFieldIndex( poSFDefn->GetName() ) != -1
+                ? CPLStrdup( CPLSPrintf( "%s_%s",
+                                         papszATIDRefs[iTable],
+                                         poSFDefn->GetName() ) )
+                : CPLStrdup( poSFDefn->GetName() );
 
             switch( poSFDefn->GetType() )
             {
@@ -183,7 +176,6 @@ OGRSDTSLayer::OGRSDTSLayer( SDTSTransfer * poTransferIn, int iLayerIn,
             }
 
             CPLFree( pszFieldName );
-
         } /* next iSF (subfield) */
     } /* next iTable */
     CSLDestroy( papszATIDRefs );
@@ -199,7 +191,7 @@ OGRSDTSLayer::~OGRSDTSLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "SDTS", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead,
+                  static_cast<int>(m_nFeaturesRead),
                   poFeatureDefn->GetName() );
     }
 
@@ -231,17 +223,15 @@ AssignAttrRecordToFeature( OGRFeature * poFeature,
 /* -------------------------------------------------------------------- */
     DDFFieldDefn        *poFDefn = poSR->GetFieldDefn();
 
-    for( int iSF=0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
+    for( int iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++ )
     {
         DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield( iSF );
-        int                     iField;
-        int                     nMaxBytes;
-        const char *    pachData = poSR->GetSubfieldData(poSFDefn,
-                                                         &nMaxBytes);
+        int nMaxBytes = 0;
+        const char *pachData = poSR->GetSubfieldData(poSFDefn, &nMaxBytes);
 /* -------------------------------------------------------------------- */
-/*      Indentify this field on the feature.                            */
+/*      Identify this field on the feature.                            */
 /* -------------------------------------------------------------------- */
-        iField = poFeature->GetFieldIndex( poSFDefn->GetName() );
+        const int iField = poFeature->GetFieldIndex( poSFDefn->GetName() );
 
 /* -------------------------------------------------------------------- */
 /*      Handle each of the types.                                       */
@@ -249,34 +239,31 @@ AssignAttrRecordToFeature( OGRFeature * poFeature,
         switch( poSFDefn->GetType() )
         {
           case DDFString:
-            const char  *pszValue;
-
-            pszValue = poSFDefn->ExtractStringData(pachData, nMaxBytes,
-                                                   NULL);
+          {
+            const char  *pszValue =
+                poSFDefn->ExtractStringData(pachData, nMaxBytes, NULL);
 
             if( iField != -1 )
                 poFeature->SetField( iField, pszValue );
             break;
-
+          }
           case DDFFloat:
-            double      dfValue;
-
-            dfValue = poSFDefn->ExtractFloatData(pachData, nMaxBytes,
-                                                 NULL);
+          {
+            double dfValue =
+                poSFDefn->ExtractFloatData(pachData, nMaxBytes, NULL);
 
             if( iField != -1 )
                 poFeature->SetField( iField, dfValue );
             break;
-
+          }
           case DDFInt:
-            int         nValue;
-
-            nValue = poSFDefn->ExtractIntData(pachData, nMaxBytes, NULL);
+          {
+            int nValue = poSFDefn->ExtractIntData(pachData, nMaxBytes, NULL);
 
             if( iField != -1 )
                 poFeature->SetField( iField, nValue );
             break;
-
+          }
           default:
             break;
         }
@@ -303,7 +290,6 @@ OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
 /*      Fetch the next sdts style feature object from the reader.       */
 /* -------------------------------------------------------------------- */
     SDTSFeature *poSDTSFeature = poReader->GetNextFeature();
-    OGRFeature  *poFeature;
 
     if( poSDTSFeature == NULL )
         return NULL;
@@ -311,7 +297,7 @@ OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
 /* -------------------------------------------------------------------- */
 /*      Create the OGR feature.                                         */
 /* -------------------------------------------------------------------- */
-    poFeature = new OGRFeature( poFeatureDefn );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     m_nFeaturesRead++;
 
@@ -357,13 +343,11 @@ OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
           for( int iRing = 0; iRing < poPoly->nRings; iRing++ )
           {
               OGRLinearRing *poRing = new OGRLinearRing();
-              int           nVertices;
-
-              if( iRing == poPoly->nRings - 1 )
-                  nVertices = poPoly->nVertices - poPoly->panRingStart[iRing];
-              else
-                  nVertices = poPoly->panRingStart[iRing+1]
-                            - poPoly->panRingStart[iRing];
+              const int nVertices =
+                  iRing == poPoly->nRings - 1
+                  ? poPoly->nVertices - poPoly->panRingStart[iRing]
+                  : (poPoly->panRingStart[iRing+1]
+                     - poPoly->panRingStart[iRing]);
 
               poRing->setPoints( nVertices,
                                  poPoly->padfX + poPoly->panRingStart[iRing],
@@ -384,15 +368,12 @@ OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
 /* -------------------------------------------------------------------- */
 /*      Set attributes for any indicated attribute records.             */
 /* -------------------------------------------------------------------- */
-    int         iAttrRecord;
-
-    for( iAttrRecord = 0;
+    for( int iAttrRecord = 0;
          iAttrRecord < poSDTSFeature->nAttributes;
          iAttrRecord++)
     {
-        DDFField        *poSR;
-
-        poSR = poTransfer->GetAttr( poSDTSFeature->paoATID+iAttrRecord );
+        DDFField *poSR =
+            poTransfer->GetAttr( poSDTSFeature->paoATID+iAttrRecord );
         if( poSR != NULL )
             AssignAttrRecordToFeature( poFeature, poTransfer, poSR );
     }
@@ -422,7 +403,6 @@ OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature()
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -458,22 +438,8 @@ OGRFeature *OGRSDTSLayer::GetNextFeature()
 /*                           TestCapability()                           */
 /************************************************************************/
 
-int OGRSDTSLayer::TestCapability( const char * pszCap )
+int OGRSDTSLayer::TestCapability( const char * /* pszCap */ )
 
 {
-    if( EQUAL(pszCap,OLCRandomRead) )
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCSequentialWrite)
-             || EQUAL(pszCap,OLCRandomWrite) )
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCFastFeatureCount) )
-        return FALSE;
-
-    else if( EQUAL(pszCap,OLCFastSpatialFilter) )
-        return FALSE;
-
-    else
-        return FALSE;
+    return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h b/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
index c00352d..49db3ee 100644
--- a/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
+++ b/ogr/ogrsf_frmts/segukooa/ogr_segukooa.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_segukooa.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogr_segukooa.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Definition of classes for OGR SEG-P1 / UKOOA P1-90 driver.
@@ -40,17 +40,17 @@ class OGRSEGUKOOABaseLayer : public OGRLayer
 {
   protected:
     OGRFeatureDefn*    poFeatureDefn;
-    int                bEOF;
+    bool               bEOF;
     int                nNextFID;
 
     virtual OGRFeature *       GetNextRawFeature() = 0;
 
   public:
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int                 TestCapability( const char * ) { return FALSE; }
+    virtual int                 TestCapability( const char * ) override { return FALSE; }
 };
 
 /************************************************************************/
@@ -68,15 +68,14 @@ class OGRUKOOAP190Layer : public OGRSEGUKOOABaseLayer
     void               ParseHeaders();
 
   protected:
-    OGRFeature *       GetNextRawFeature();
+    OGRFeature *       GetNextRawFeature() override;
 
   public:
                         OGRUKOOAP190Layer(const char* pszFilename,
                                          VSILFILE* fp);
-                        ~OGRUKOOAP190Layer();
+                        virtual ~OGRUKOOAP190Layer();
 
-
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 };
 
 /************************************************************************/
@@ -89,17 +88,16 @@ class OGRSEGUKOOALineLayer : public OGRSEGUKOOABaseLayer
     OGRFeature        *poNextBaseFeature;
 
   protected:
-    OGRFeature *       GetNextRawFeature();
+    OGRFeature *       GetNextRawFeature() override;
 
   public:
                         OGRSEGUKOOALineLayer(const char* pszFilename,
                                              OGRLayer *poBaseLayer);
-                        ~OGRSEGUKOOALineLayer();
+                        virtual ~OGRSEGUKOOALineLayer();
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 };
 
-
 /************************************************************************/
 /*                         OGRSEGP1Layer                                */
 /************************************************************************/
@@ -114,15 +112,15 @@ class OGRSEGP1Layer: public OGRSEGUKOOABaseLayer
     int                bUseEastingNorthingAsGeometry;
 
   protected:
-    OGRFeature *       GetNextRawFeature();
+    OGRFeature *       GetNextRawFeature() override;
 
   public:
                         OGRSEGP1Layer(const char* pszFilename,
                                       VSILFILE* fp,
                                       int nLatitudeCol);
-                        ~OGRSEGP1Layer();
+                        virtual ~OGRSEGP1Layer();
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 
 public:
     static char* ExpandTabs(const char* pszLine);
@@ -142,16 +140,16 @@ class OGRSEGUKOOADataSource : public OGRDataSource
 
   public:
                         OGRSEGUKOOADataSource();
-                        ~OGRSEGUKOOADataSource();
+                        virtual ~OGRSEGUKOOADataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_SEGUKOOA_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
index 330e577..422b823 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooadatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsegukooadatasource.cpp 31122 2015-10-25 09:28:57Z rouault $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Implements OGRSEGUKOOADataSource class
@@ -31,20 +30,17 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsegukooadatasource.cpp 31122 2015-10-25 09:28:57Z rouault $");
+CPL_CVSID("$Id: ogrsegukooadatasource.cpp 35199 2016-08-24 21:14:08Z goatbar $");
 
 /************************************************************************/
 /*                        OGRSEGUKOOADataSource()                       */
 /************************************************************************/
 
-OGRSEGUKOOADataSource::OGRSEGUKOOADataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-}
+OGRSEGUKOOADataSource::OGRSEGUKOOADataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0)
+{}
 
 /************************************************************************/
 /*                       ~OGRSEGUKOOADataSource()                       */
@@ -95,9 +91,8 @@ int OGRSEGUKOOADataSource::Open( const char * pszFilename )
     if (fp == NULL)
         return FALSE;
 
-    const char* pszLine;
     CPLPushErrorHandler(CPLQuietErrorHandler);
-    pszLine = CPLReadLine2L(fp,81,NULL);
+    const char* pszLine = CPLReadLine2L(fp,81,NULL);
     CPLPopErrorHandler();
     CPLErrorReset();
 
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
index 9bd5268..91e77b7 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooadriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsegukooadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Implements OGRSEGUKOOADriver.
@@ -30,7 +29,7 @@
 #include "ogr_segukooa.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsegukooadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrsegukooadriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 extern "C" void RegisterOGRSEGUKOOA();
 
@@ -80,4 +79,3 @@ void RegisterOGRSEGUKOOA()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
index db888cd..c148324 100644
--- a/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
+++ b/ogr/ogrsf_frmts/segukooa/ogrsegukooalayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsegukooalayer.cpp 32982 2016-01-14 16:53:57Z goatbar $
  *
  * Project:  SEG-P1 / UKOOA P1-90 Translator
  * Purpose:  Implements OGRUKOOAP190Layer class.
@@ -33,7 +32,7 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsegukooalayer.cpp 32982 2016-01-14 16:53:57Z goatbar $");
+CPL_CVSID("$Id: ogrsegukooalayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                            ExtractField()                            */
@@ -51,11 +50,9 @@ static void ExtractField(char* szField, const char* pszLine, int nOffset, int nL
 
 OGRFeature *OGRSEGUKOOABaseLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
     while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -100,45 +97,46 @@ static const FieldDesc UKOOAP190Fields[] =
     { "DATETIME", OFTDateTime }
 };
 
-#define FIELD_LINENAME      0
-#define FIELD_VESSEL_ID     1
-#define FIELD_SOURCE_ID     2
-#define FIELD_OTHER_ID      3
-#define FIELD_POINTNUMBER   4
-#define FIELD_LONGITUDE     5
-#define FIELD_LATITUDE      6
-#define FIELD_EASTING       7
-#define FIELD_NORTHING      8
-#define FIELD_DEPTH         9
-#define FIELD_DAYOFYEAR     10
-#define FIELD_TIME          11
-#define FIELD_DATETIME      12
+static const int FIELD_LINENAME    = 0;
+static const int FIELD_VESSEL_ID   = 1;
+static const int FIELD_SOURCE_ID   = 2;
+static const int FIELD_OTHER_ID    = 3;
+// static const int FIELD_POINTNUMBER = 4;
+static const int FIELD_LONGITUDE   = 5;
+static const int FIELD_LATITUDE    = 6;
+static const int FIELD_EASTING     = 7;
+static const int FIELD_NORTHING    = 8;
+static const int FIELD_DEPTH       = 9;
+static const int FIELD_DAYOFYEAR   = 10;
+static const int FIELD_TIME        = 11;
+static const int FIELD_DATETIME    = 12;
 
 OGRUKOOAP190Layer::OGRUKOOAP190Layer( const char* pszFilename,
-                                      VSILFILE* fpIn )
-
+                                      VSILFILE* fpIn ) :
+    poSRS(NULL),
+    fp(fpIn),
+    bUseEastingNorthingAsGeometry(CPLTestBool(
+        CPLGetConfigOption("UKOOAP190_USE_EASTING_NORTHING", "NO"))),
+    nYear(0)
 {
-    this->fp = fpIn;
     nNextFID = 0;
-    bEOF = FALSE;
-    poSRS = NULL;
-    nYear = 0;
+    bEOF = false;
 
     poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPoint );
 
-    for(int i=0;i<(int)(sizeof(UKOOAP190Fields)/sizeof(UKOOAP190Fields[0]));i++)
+    for( int i = 0;
+         i < static_cast<int>(sizeof(UKOOAP190Fields) /
+                              sizeof(UKOOAP190Fields[0]));
+         i++ )
     {
         OGRFieldDefn    oField( UKOOAP190Fields[i].pszName,
                                 UKOOAP190Fields[i].eType );
         poFeatureDefn->AddFieldDefn( &oField );
     }
 
-    bUseEastingNorthingAsGeometry =
-        CPLTestBool(CPLGetConfigOption("UKOOAP190_USE_EASTING_NORTHING", "NO"));
-
     ParseHeaders();
 
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
@@ -206,8 +204,7 @@ void OGRUKOOAP190Layer::ParseHeaders()
         {
             char aszParams[6][6+1];
             char szZ[10+1];
-            int i;
-            for(i=0;i<6;i++)
+            for( int i = 0; i < 6; i++ )
             {
                 ExtractField(aszParams[i], pszLine, 33 - 1 + i * 6, 6);
             }
@@ -230,7 +227,7 @@ void OGRUKOOAP190Layer::ParseHeaders()
                     int nVal = atoi(papszTokens[i]);
                     if (nVal >= 1900)
                     {
-                        if (nYear != 0 && nYear != nVal)
+                        if( nYear != 0 && nYear != nVal )
                         {
                             CPLDebug("SEGUKOOA",
                                      "Several years found in H0200. Ignoring them!");
@@ -255,7 +252,7 @@ void OGRUKOOAP190Layer::ResetReading()
 
 {
     nNextFID = 0;
-    bEOF = FALSE;
+    bEOF = false;
     VSIFSeekL( fp, 0, SEEK_SET );
 }
 
@@ -263,19 +260,25 @@ void OGRUKOOAP190Layer::ResetReading()
 /*                         GetNextRawFeature()                          */
 /************************************************************************/
 
+static bool isleap( int y)
+{
+    return
+      (y % 4 == 0 &&
+       y % 100 != 0)
+      || y % 400 == 0;
+}
+
 OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
 {
-    if (bEOF)
+    if( bEOF )
         return NULL;
 
-    const char* pszLine;
-
     while( true )
     {
-        pszLine = CPLReadLine2L(fp,81,NULL);
+        const char* pszLine = CPLReadLine2L(fp, 81, NULL);
         if (pszLine == NULL || STARTS_WITH_CI(pszLine, "EOF"))
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
 
@@ -405,31 +408,34 @@ OGRFeature *OGRUKOOAP190Layer::GetNextRawFeature()
             ExtractField(szS, pszLine, 74-1+2+2, 2);
             poFeature->SetField(FIELD_TIME, 0, 0, 0, atoi(szH), atoi(szM), static_cast<float>(atoi(szS)) );
 
-            if (nYear != 0)
+            if( nYear != 0 )
             {
-                #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
                 static const int mon_lengths[2][12] = {
                     {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
                     {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
                 } ;
-                int bIsLeap = isleap(nYear);
+                const bool bIsLeap = isleap(nYear);
                 int nMonth = 0;
                 int nDays = 0;
                 if ((bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 366) ||
                     (!bIsLeap && nDayOfYear >= 1 && nDayOfYear <= 365))
                 {
-                    while(nDayOfYear > nDays + mon_lengths[bIsLeap][nMonth])
+                    static const int leap_offset = bIsLeap ? 0 : 1;
+                    while( nDayOfYear >
+                           nDays +
+                           mon_lengths[leap_offset][nMonth] )
                     {
-                        nDays += mon_lengths[bIsLeap][nMonth];
+                        nDays += mon_lengths[leap_offset][nMonth];
                         nMonth ++;
                     }
-                    int nDayOfMonth = nDayOfYear - nDays;
-                    nMonth ++;
+                    const int nDayOfMonth = nDayOfYear - nDays;
+                    nMonth++;
 
-                    poFeature->SetField(FIELD_DATETIME, nYear, nMonth, nDayOfMonth,
-                                        atoi(szH), atoi(szM), static_cast<float>(atoi(szS)) );
+                    poFeature->SetField(FIELD_DATETIME,
+                                        nYear, nMonth, nDayOfMonth,
+                                        atoi(szH), atoi(szM),
+                                        static_cast<float>(atoi(szS)) );
                 }
-
             }
         }
 
@@ -459,28 +465,29 @@ static const FieldDesc SEGP1Fields[] =
 #endif
 };
 
-#define SEGP1_FIELD_LINENAME      0
-#define SEGP1_FIELD_POINTNUMBER   1
-#define SEGP1_FIELD_RESHOOTCODE   2
-#define SEGP1_FIELD_LONGITUDE     3
-#define SEGP1_FIELD_LATITUDE      4
-#define SEGP1_FIELD_EASTING       5
-#define SEGP1_FIELD_NORTHING      6
-#define SEGP1_FIELD_DEPTH         7
-#define SEGP1_FIELD_DAYOFYEAR     8
-#define SEGP1_FIELD_TIME          9
-#define SEGP1_FIELD_DATETIME      10
+static const int SEGP1_FIELD_LINENAME    = 0;
+static const int SEGP1_FIELD_POINTNUMBER = 1;
+static const int SEGP1_FIELD_RESHOOTCODE = 2;
+static const int SEGP1_FIELD_LONGITUDE   = 3;
+static const int SEGP1_FIELD_LATITUDE    = 4;
+static const int SEGP1_FIELD_EASTING     = 5;
+static const int SEGP1_FIELD_NORTHING    = 6;
+static const int SEGP1_FIELD_DEPTH       = 7;
+// static const int SEGP1_FIELD_DAYOFYEAR   = 8;
+// static const int SEGP1_FIELD_TIME        = 9;
+// static const int SEGP1_FIELD_DATETIME    = 10;
 
 OGRSEGP1Layer::OGRSEGP1Layer( const char* pszFilename,
                               VSILFILE* fpIn,
-                              int nLatitudeColIn )
-
+                              int nLatitudeColIn ) :
+    poSRS(NULL),
+    fp(fpIn),
+    nLatitudeCol(nLatitudeColIn),
+    bUseEastingNorthingAsGeometry(CPLTestBool(
+        CPLGetConfigOption("SEGP1_USE_EASTING_NORTHING", "NO")))
 {
-    this->fp = fpIn;
-    this->nLatitudeCol = nLatitudeColIn;
     nNextFID = 0;
-    bEOF = FALSE;
-    poSRS = NULL;
+    bEOF = false;
 
     poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
     SetDescription( poFeatureDefn->GetName() );
@@ -494,9 +501,6 @@ OGRSEGP1Layer::OGRSEGP1Layer( const char* pszFilename,
         poFeatureDefn->AddFieldDefn( &oField );
     }
 
-    bUseEastingNorthingAsGeometry =
-        CPLTestBool(CPLGetConfigOption("SEGP1_USE_EASTING_NORTHING", "NO"));
-
     ResetReading();
 }
 
@@ -523,7 +527,7 @@ void OGRSEGP1Layer::ResetReading()
 
 {
     nNextFID = 0;
-    bEOF = FALSE;
+    bEOF = false;
     VSIFSeekL( fp, 0, SEEK_SET );
 
     /* Skip first 20 header lines */
@@ -533,7 +537,7 @@ void OGRSEGP1Layer::ResetReading()
         pszLine = CPLReadLine2L(fp,81,NULL);
         if (pszLine == NULL)
         {
-            bEOF = TRUE;
+            bEOF = true;
             break;
         }
     }
@@ -545,7 +549,7 @@ void OGRSEGP1Layer::ResetReading()
 
 OGRFeature *OGRSEGP1Layer::GetNextRawFeature()
 {
-    if (bEOF)
+    if( bEOF )
         return NULL;
 
     const char* pszLine = NULL;
@@ -554,7 +558,7 @@ OGRFeature *OGRSEGP1Layer::GetNextRawFeature()
         pszLine = CPLReadLine2L(fp,81,NULL);
         if (pszLine == NULL || STARTS_WITH_CI(pszLine, "EOF"))
         {
-            bEOF = TRUE;
+            bEOF = true;
             return NULL;
         }
 
@@ -715,28 +719,28 @@ int OGRSEGP1Layer::DetectLatitudeColumn(const char* pszLine)
     return 0;
 }
 
-
 /************************************************************************/
 /*                        OGRSEGUKOOALineLayer()                        */
 /************************************************************************/
 
-OGRSEGUKOOALineLayer::OGRSEGUKOOALineLayer(const char* pszFilename,
-                                           OGRLayer *poBaseLayerIn)
+OGRSEGUKOOALineLayer::OGRSEGUKOOALineLayer( const char* pszFilename,
+                                            OGRLayer *poBaseLayerIn ) :
+    poBaseLayer(poBaseLayerIn),
+    poNextBaseFeature(NULL)
 {
     nNextFID = 0;
-    bEOF = FALSE;
-    this->poBaseLayer = poBaseLayerIn;
+    bEOF = false;
 
-    poFeatureDefn = new OGRFeatureDefn( CPLSPrintf("%s_lines",
-                                                   CPLGetBasename(pszFilename)) );
+    poFeatureDefn = new OGRFeatureDefn(
+        CPLSPrintf("%s_lines",
+                   CPLGetBasename(pszFilename)) );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbLineString );
-    poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poBaseLayer->GetSpatialRef());
+    poFeatureDefn->GetGeomFieldDefn(0)->
+        SetSpatialRef(poBaseLayer->GetSpatialRef());
 
-    OGRFieldDefn    oField( "LINENAME", OFTString );
+    OGRFieldDefn oField( "LINENAME", OFTString );
     poFeatureDefn->AddFieldDefn( &oField );
-
-    poNextBaseFeature = NULL;
 }
 
 /************************************************************************/
@@ -759,7 +763,7 @@ void OGRSEGUKOOALineLayer::ResetReading()
 
 {
     nNextFID = 0;
-    bEOF = FALSE;
+    bEOF = false;
     delete poNextBaseFeature;
     poNextBaseFeature = NULL;
     poBaseLayer->ResetReading();
@@ -771,7 +775,7 @@ void OGRSEGUKOOALineLayer::ResetReading()
 
 OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
 {
-    if (bEOF)
+    if( bEOF )
         return NULL;
 
     /* Merge points of base layer that have same value for attribute(0) */
@@ -785,7 +789,7 @@ OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
 
     while(poNextBaseFeature != NULL)
     {
-        if (poNextBaseFeature->IsFieldSet(0) &&
+        if (poNextBaseFeature->IsFieldSetAndNotNull(0) &&
             poNextBaseFeature->GetFieldAsString(0)[0] != '\0')
         {
             if (poFeature != NULL &&
@@ -820,7 +824,7 @@ OGRFeature *OGRSEGUKOOALineLayer::GetNextRawFeature()
         poNextBaseFeature = poBaseLayer->GetNextFeature();
     }
 
-    bEOF = TRUE;
+    bEOF = true;
     if( poFeature )
         poFeature->SetGeometryDirectly(poLS);
     return poFeature;
diff --git a/ogr/ogrsf_frmts/segy/ogr_segy.h b/ogr/ogrsf_frmts/segy/ogr_segy.h
index 97981f7..6e9e1b1 100644
--- a/ogr/ogrsf_frmts/segy/ogr_segy.h
+++ b/ogr/ogrsf_frmts/segy/ogr_segy.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_segy.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogr_segy.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Definition of classes for OGR SEG-Y driver.
@@ -77,7 +77,7 @@ typedef struct
 class OGRSEGYLayer: public OGRLayer
 {
     OGRFeatureDefn*    poFeatureDefn;
-    int                bEOF;
+    bool               bEOF;
     int                nNextFID;
     VSILFILE*          fp;
 
@@ -87,18 +87,18 @@ class OGRSEGYLayer: public OGRLayer
     OGRFeature *       GetNextRawFeature();
 
   public:
-                        OGRSEGYLayer(const char* pszFilename,
-                                     VSILFILE* fp,
-                                     SEGYBinaryFileHeader* psBFH);
-                        ~OGRSEGYLayer();
+                        OGRSEGYLayer( const char* pszFilename,
+                                      VSILFILE* fp,
+                                      SEGYBinaryFileHeader* psBFH );
+                        virtual ~OGRSEGYLayer();
 
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int                 TestCapability( const char * ) { return FALSE; }
+    virtual int                 TestCapability( const char * ) override { return FALSE; }
 };
 
 /************************************************************************/
@@ -108,7 +108,7 @@ class OGRSEGYLayer: public OGRLayer
 class OGRSEGYHeaderLayer: public OGRLayer
 {
     OGRFeatureDefn*    poFeatureDefn;
-    int                bEOF;
+    bool               bEOF;
 
     SEGYBinaryFileHeader sBFH;
     char*                pszHeaderText;
@@ -116,18 +116,18 @@ class OGRSEGYHeaderLayer: public OGRLayer
     OGRFeature *       GetNextRawFeature();
 
   public:
-                        OGRSEGYHeaderLayer(const char* pszLayerName,
-                                           SEGYBinaryFileHeader* psBFH,
-                                           const char* pszHeaderText);
-                        ~OGRSEGYHeaderLayer();
+                        OGRSEGYHeaderLayer( const char* pszLayerName,
+                                            SEGYBinaryFileHeader* psBFH,
+                                            const char* pszHeaderText );
+                        virtual ~OGRSEGYHeaderLayer();
 
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual void                ResetReading();
+    virtual void                ResetReading() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual int                 TestCapability( const char * ) { return FALSE; }
+    virtual int                 TestCapability( const char * ) override { return FALSE; }
 };
 
 /************************************************************************/
@@ -143,16 +143,16 @@ class OGRSEGYDataSource : public OGRDataSource
 
   public:
                         OGRSEGYDataSource();
-                        ~OGRSEGYDataSource();
+                        virtual ~OGRSEGYDataSource();
 
     int                 Open( const char * pszFilename, const char* pszHeaderText );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_SEGY_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp b/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp
index 2f759d1..5b0daf8 100644
--- a/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp
+++ b/ogr/ogrsf_frmts/segy/ogrsegydatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsegydatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Implements OGRSEGYDataSource class.
@@ -31,20 +30,17 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsegydatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrsegydatasource.cpp 35627 2016-10-06 15:20:13Z goatbar $");
 
 /************************************************************************/
 /*                        OGRSEGYDataSource()                       */
 /************************************************************************/
 
-OGRSEGYDataSource::OGRSEGYDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-}
+OGRSEGYDataSource::OGRSEGYDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0)
+{}
 
 /************************************************************************/
 /*                       ~OGRSEGYDataSource()                       */
@@ -88,7 +84,7 @@ OGRLayer *OGRSEGYDataSource::GetLayer( int iLayer )
 
 GInt16 SEGYReadMSBInt16(const GByte* pabyVal)
 {
-    GInt16 nVal;
+    GInt16 nVal = 0;
     memcpy(&nVal, pabyVal, 2);
     CPL_MSBPTR16(&nVal);
     return nVal;
@@ -100,7 +96,7 @@ GInt16 SEGYReadMSBInt16(const GByte* pabyVal)
 
 GInt32 SEGYReadMSBInt32(const GByte* pabyVal)
 {
-    GInt32 nVal;
+    GInt32 nVal = 0;
     memcpy(&nVal, pabyVal, 4);
     CPL_MSBPTR32(&nVal);
     return nVal;
@@ -110,13 +106,14 @@ GInt32 SEGYReadMSBInt32(const GByte* pabyVal)
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRSEGYDataSource::Open( const char * pszFilename, const char* pszASCIITextHeader)
+int OGRSEGYDataSource::Open( const char *pszFilename,
+                             const char *pszASCIITextHeader )
 
 {
     pszName = CPLStrdup( pszFilename );
 
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
-    if (fp == NULL)
+    if( fp == NULL )
         return FALSE;
 
     VSIFSeekL(fp, 3200, SEEK_SET);
@@ -127,7 +124,7 @@ int OGRSEGYDataSource::Open( const char * pszFilename, const char* pszASCIITextH
 // --------------------------------------------------------------------
 
     GByte abyFileHeader[400];
-    if ((int)VSIFReadL(abyFileHeader, 1, 400, fp) != 400)
+    if( static_cast<int>(VSIFReadL(abyFileHeader, 1, 400, fp)) != 400 )
     {
         VSIFCloseL(fp);
         return FALSE;
@@ -167,48 +164,52 @@ int OGRSEGYDataSource::Open( const char * pszFilename, const char* pszASCIITextH
     sBFH.nFixedLengthTraceFlag = SEGYReadMSBInt16(abyFileHeader + 302);
     sBFH.nNumberOfExtendedTextualFileHeader = SEGYReadMSBInt16(abyFileHeader + 304);
 
-#if 0
-    CPLDebug("SIGY", "nJobIdNumber = %d", sBFH.nJobIdNumber);
-    CPLDebug("SIGY", "nLineNumber = %d", sBFH.nLineNumber);
-    CPLDebug("SIGY", "nReelNumber = %d", sBFH.nReelNumber);
-    CPLDebug("SIGY", "nDataTracesPerEnsemble = %d", sBFH.nDataTracesPerEnsemble);
-    CPLDebug("SIGY", "nAuxTracesPerEnsemble = %d", sBFH.nAuxTracesPerEnsemble);
-    CPLDebug("SIGY", "nSampleInterval = %d", sBFH.nSampleInterval);
-    CPLDebug("SIGY", "nSampleIntervalOriginal = %d", sBFH.nSampleIntervalOriginal);
-    CPLDebug("SIGY", "nSamplesPerDataTrace = %d", sBFH.nSamplesPerDataTrace);
-    CPLDebug("SIGY", "nSamplesPerDataTraceOriginal = %d", sBFH.nSamplesPerDataTraceOriginal);
-    CPLDebug("SIGY", "nDataSampleType = %d", sBFH.nDataSampleType);
-    CPLDebug("SIGY", "nEnsembleFold = %d", sBFH.nEnsembleFold);
-    CPLDebug("SIGY", "nTraceSortingCode = %d", sBFH.nTraceSortingCode);
-    CPLDebug("SIGY", "nVerticalSumCode = %d", sBFH.nVerticalSumCode);
-    CPLDebug("SIGY", "nSweepFrequencyAtStart = %d", sBFH.nSweepFrequencyAtStart);
-    CPLDebug("SIGY", "nSweepFrequencyAtEnd = %d", sBFH.nSweepFrequencyAtEnd);
-    CPLDebug("SIGY", "nSweepLength = %d", sBFH.nSweepLength);
-    CPLDebug("SIGY", "nSweepType = %d", sBFH.nSweepType);
-    CPLDebug("SIGY", "nTraceNumberOfSweepChannel = %d", sBFH.nTraceNumberOfSweepChannel);
-    CPLDebug("SIGY", "nSweepTraceTaperLengthAtStart = %d", sBFH.nSweepTraceTaperLengthAtStart);
-    CPLDebug("SIGY", "nSweepTraceTaperLengthAtEnd = %d", sBFH.nSweepTraceTaperLengthAtEnd);
-    CPLDebug("SIGY", "nTaperType = %d", sBFH.nTaperType);
-    CPLDebug("SIGY", "nCorrelated = %d", sBFH.nCorrelated);
-    CPLDebug("SIGY", "nBinaryGainRecovered = %d", sBFH.nBinaryGainRecovered);
-    CPLDebug("SIGY", "nAmplitudeRecoveryMethod = %d", sBFH.nAmplitudeRecoveryMethod);
-    CPLDebug("SIGY", "nMeasurementSystem = %d", sBFH.nMeasurementSystem);
-    CPLDebug("SIGY", "nImpulseSignalPolarity = %d", sBFH.nImpulseSignalPolarity);
-    CPLDebug("SIGY", "nVibratoryPolaryCode = %d", sBFH.nVibratoryPolaryCode);
-    CPLDebug("SIGY", "nSEGYRevisionNumber = %d", sBFH.nSEGYRevisionNumber);
-    CPLDebug("SIGY", "dfSEGYRevisionNumber = %f", sBFH.dfSEGYRevisionNumber);
-    CPLDebug("SIGY", "nFixedLengthTraceFlag = %d", sBFH.nFixedLengthTraceFlag);
-    CPLDebug("SIGY", "nNumberOfExtendedTextualFileHeader = %d", sBFH.nNumberOfExtendedTextualFileHeader);
-#endif
+#if DEBUG_VERBOSE
+    CPLDebug("SEGY", "nJobIdNumber = %d", sBFH.nJobIdNumber);
+    CPLDebug("SEGY", "nLineNumber = %d", sBFH.nLineNumber);
+    CPLDebug("SEGY", "nReelNumber = %d", sBFH.nReelNumber);
+    CPLDebug("SEGY", "nDataTracesPerEnsemble = %d", sBFH.nDataTracesPerEnsemble);
+    CPLDebug("SEGY", "nAuxTracesPerEnsemble = %d", sBFH.nAuxTracesPerEnsemble);
+    CPLDebug("SEGY", "nSampleInterval = %d", sBFH.nSampleInterval);
+    CPLDebug("SEGY", "nSampleIntervalOriginal = %d", sBFH.nSampleIntervalOriginal);
+    CPLDebug("SEGY", "nSamplesPerDataTrace = %d", sBFH.nSamplesPerDataTrace);
+    CPLDebug("SEGY", "nSamplesPerDataTraceOriginal = %d", sBFH.nSamplesPerDataTraceOriginal);
+    CPLDebug("SEGY", "nDataSampleType = %d", sBFH.nDataSampleType);
+    CPLDebug("SEGY", "nEnsembleFold = %d", sBFH.nEnsembleFold);
+    CPLDebug("SEGY", "nTraceSortingCode = %d", sBFH.nTraceSortingCode);
+    CPLDebug("SEGY", "nVerticalSumCode = %d", sBFH.nVerticalSumCode);
+    CPLDebug("SEGY", "nSweepFrequencyAtStart = %d", sBFH.nSweepFrequencyAtStart);
+    CPLDebug("SEGY", "nSweepFrequencyAtEnd = %d", sBFH.nSweepFrequencyAtEnd);
+    CPLDebug("SEGY", "nSweepLength = %d", sBFH.nSweepLength);
+    CPLDebug("SEGY", "nSweepType = %d", sBFH.nSweepType);
+    CPLDebug("SEGY", "nTraceNumberOfSweepChannel = %d", sBFH.nTraceNumberOfSweepChannel);
+    CPLDebug("SEGY", "nSweepTraceTaperLengthAtStart = %d", sBFH.nSweepTraceTaperLengthAtStart);
+    CPLDebug("SEGY", "nSweepTraceTaperLengthAtEnd = %d", sBFH.nSweepTraceTaperLengthAtEnd);
+    CPLDebug("SEGY", "nTaperType = %d", sBFH.nTaperType);
+    CPLDebug("SEGY", "nCorrelated = %d", sBFH.nCorrelated);
+    CPLDebug("SEGY", "nBinaryGainRecovered = %d", sBFH.nBinaryGainRecovered);
+    CPLDebug("SEGY", "nAmplitudeRecoveryMethod = %d", sBFH.nAmplitudeRecoveryMethod);
+    CPLDebug("SEGY", "nMeasurementSystem = %d", sBFH.nMeasurementSystem);
+    CPLDebug("SEGY", "nImpulseSignalPolarity = %d", sBFH.nImpulseSignalPolarity);
+    CPLDebug("SEGY", "nVibratoryPolaryCode = %d", sBFH.nVibratoryPolaryCode);
+    CPLDebug("SEGY", "nSEGYRevisionNumber = %d", sBFH.nSEGYRevisionNumber);
+    CPLDebug("SEGY", "dfSEGYRevisionNumber = %f", sBFH.dfSEGYRevisionNumber);
+    CPLDebug("SEGY", "nFixedLengthTraceFlag = %d", sBFH.nFixedLengthTraceFlag);
+    CPLDebug("SEGY", "nNumberOfExtendedTextualFileHeader = %d", sBFH.nNumberOfExtendedTextualFileHeader);
+#endif  // DEBUG_VERBOSE
 
 // --------------------------------------------------------------------
 //      Create layer
 // --------------------------------------------------------------------
 
     nLayers = 2;
-    papoLayers = (OGRLayer**) CPLMalloc(nLayers * sizeof(OGRLayer*));
+    papoLayers = static_cast<OGRLayer **>(
+        CPLMalloc(nLayers * sizeof(OGRLayer*)));
     papoLayers[0] = new OGRSEGYLayer(pszName, fp, &sBFH);
-    papoLayers[1] = new OGRSEGYHeaderLayer(CPLSPrintf("%s_header", CPLGetBasename(pszName)), &sBFH, pszASCIITextHeader);
+    papoLayers[1] =
+        new OGRSEGYHeaderLayer(
+            CPLSPrintf("%s_header", CPLGetBasename(pszName)),
+                       &sBFH, pszASCIITextHeader);
 
     return TRUE;
 }
diff --git a/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp b/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
index e819a91..1b1339a 100644
--- a/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
+++ b/ogr/ogrsf_frmts/segy/ogrsegydriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsegydriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Implements OGRSEGYDriver class.
@@ -30,7 +29,7 @@
 #include "ogr_segy.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsegydriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsegydriver.cpp 35674 2016-10-10 04:46:23Z goatbar $");
 
 /************************************************************************/
 /*                           EBCDICToASCII                              */
@@ -38,22 +37,28 @@ CPL_CVSID("$Id: ogrsegydriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 
 static const GByte EBCDICToASCII[] =
 {
-0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, 0x97, 0x8D, 0x8E, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
-0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F,
-0x80, 0x81, 0x82, 0x83, 0x84, 0x0A, 0x17, 0x1B, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
-0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9A, 0x9B, 0x14, 0x15, 0x9E, 0x1A,
-0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
-0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
-0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
-0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x5C, 0x00, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F,
+    0x00, 0x01, 0x02, 0x03, 0x9C, 0x09, 0x86, 0x7F, 0x97, 0x8D, 0x8E, 0x0B,
+    0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x9D, 0x85, 0x08, 0x87,
+    0x18, 0x19, 0x92, 0x8F, 0x1C, 0x1D, 0x1E, 0x1F, 0x80, 0x81, 0x82, 0x83,
+    0x84, 0x0A, 0x17, 0x1B, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x05, 0x06, 0x07,
+    0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9A, 0x9B,
+    0x14, 0x15, 0x9E, 0x1A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0xA2, 0x2E, 0x3C, 0x28, 0x2B, 0x7C, 0x26, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAC,
+    0x2D, 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA6, 0x2C,
+    0x25, 0x5F, 0x3E, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22, 0x00, 0x61, 0x62, 0x63,
+    0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+    0x79, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+    0x51, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x53, 0x54,
+    0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x9F,
 };
 
 /************************************************************************/
@@ -78,36 +83,43 @@ static GDALDataset *OGRSEGYDriverOpen( GDALOpenInfo* poOpenInfo )
 //      Try to decode the header encoded as EBCDIC and then ASCII
 // --------------------------------------------------------------------
 
-    int i, j, k;
     const GByte* pabyTextHeader = poOpenInfo->pabyHeader;
-    GByte* pabyASCIITextHeader = (GByte*) CPLMalloc(3200 + 40 + 1);
-    for( k=0; k<2; k++)
+    GByte* pabyASCIITextHeader = static_cast<GByte *>(CPLMalloc(3200 + 40 + 1));
+    for( int k = 0; k < 2; k++ )
     {
-        for( i=0, j=0;i<3200;i++)
+        int i = 0;  // Used after for.
+        int j = 0;  // Used after for.
+        for( ; i < 3200; i++ )
         {
             GByte chASCII = (k == 0) ? EBCDICToASCII[pabyTextHeader[i]] :
                                        pabyTextHeader[i];
-            if (chASCII < 32 && chASCII != '\t' &&
-                chASCII != '\n' && chASCII != '\r')
+            if( chASCII < 32 && chASCII != '\t' &&
+                chASCII != '\n' && chASCII != '\r' )
             {
-                break;
+                // Nuls are okay in an ASCII header if after the first "C1".
+                if( !(i > 2 && chASCII == '\0') )
+                {
+                    break;
+                }
             }
             pabyASCIITextHeader[j++] = chASCII;
-            if (chASCII != '\n' && ((i + 1) % 80) == 0)
+            if( chASCII != '\n' && ((i + 1) % 80) == 0 )
                 pabyASCIITextHeader[j++] = '\n';
         }
         pabyASCIITextHeader[j] = '\0';
 
-        if (i == 3200)
+        if( i == 3200 )
             break;
-        if (k == 1)
+        if( k == 1 )
         {
             CPLFree(pabyASCIITextHeader);
             return NULL;
         }
     }
 
-    CPLDebug("SIGY", "Header = \n%s", pabyASCIITextHeader);
+#if DEBUG_VERBOSE
+    CPLDebug("SEGY", "Header = \n%s", pabyASCIITextHeader);
+#endif
     CPLFree(pabyASCIITextHeader);
     pabyASCIITextHeader = NULL;
 
@@ -121,30 +133,32 @@ static GDALDataset *OGRSEGYDriverOpen( GDALOpenInfo* poOpenInfo )
 // --------------------------------------------------------------------
 //      First check that this binary header is not EBCDIC nor ASCII
 // --------------------------------------------------------------------
-    for( k=0;k<2;k++ )
+    for( int k = 0; k < 2; k++ )
     {
-        for( i=0;i<400;i++)
+        int i = 0;  // Used after for.
+        for( ; i < 400; i++ )
         {
             GByte chASCII = (k == 0) ? abyFileHeader[i] :
                                        EBCDICToASCII[abyFileHeader[i]];
-            /* A translated 0 value, when source value is not 0, means an invalid */
-            /* EBCDIC value. Bail out also for control characters */
-            if (chASCII < 32 && chASCII != '\t' &&
-                chASCII != '\n' && chASCII != '\r')
+            // A translated 0 value, when source value is not 0, means an
+            // invalid EBCDIC value. Bail out also for control characters.
+            if( chASCII < 32 && chASCII != '\t' &&
+                chASCII != '\n' && chASCII != '\r' )
             {
                 break;
             }
         }
-        if (i == 400)
+        if( i == 400 )
         {
             CPLFree(pabyASCIITextHeader);
             return NULL;
         }
     }
 
-    OGRSEGYDataSource   *poDS = new OGRSEGYDataSource();
+    OGRSEGYDataSource *poDS = new OGRSEGYDataSource();
 
-    if( !poDS->Open( poOpenInfo->pszFilename, (const char*)pabyASCIITextHeader ) )
+    if( !poDS->Open( poOpenInfo->pszFilename,
+                     (const char*)pabyASCIITextHeader ) )
     {
         CPLFree(pabyASCIITextHeader);
         delete poDS;
diff --git a/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp b/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
index e4ebbb7..065fbad 100644
--- a/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
+++ b/ogr/ogrsf_frmts/segy/ogrsegylayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsegylayer.cpp 32011 2015-12-06 10:19:18Z rouault $
  *
  * Project:  SEG-Y Translator
  * Purpose:  Implements OGRSEGYLayer class.
@@ -33,14 +32,16 @@
 #include "ogr_p.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsegylayer.cpp 32011 2015-12-06 10:19:18Z rouault $");
+CPL_CVSID("$Id: ogrsegylayer.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
-#define DT_IBM_4BYTES_FP         1
-#define DT_4BYTES_INT            2
-#define DT_2BYTES_INT            3
-#define DT_4BYTES_FP_WITH_GAIN   4
-#define DT_IEEE_4BYTES_FP        5
-#define DT_1BYTE_INT             8
+// #define SEGY_EXTENSIONS
+
+static const int DT_IBM_4BYTES_FP       = 1;
+static const int DT_4BYTES_INT          = 2;
+static const int DT_2BYTES_INT          = 3;
+static const int DT_4BYTES_FP_WITH_GAIN = 4;
+static const int DT_IEEE_4BYTES_FP      = 5;
+static const int DT_1BYTE_INT           = 8;
 
 typedef struct
 {
@@ -131,89 +132,89 @@ static const FieldDesc SEGYFields10[] =
     { "SHOTPOINT_SCALAR", OFTInteger },
 };
 
-#define TRACE_NUMBER_WITHIN_LINE 0
-#define TRACE_NUMBER_WITHIN_FILE 1
-#define ORIGINAL_FIELD_RECORD_NUMBER 2
-#define TRACE_NUMBER_WITHIN_ORIGINAL_FIELD_RECORD 3
-#define TRACE_IDENTIFICATION_CODE 4
-#define ENSEMBLE_NUMBER 5
-#define TRACE_NUMBER_WITHIN_ENSEMBLE 6
-#define NUMBER_VERTICAL_SUMMED_TRACES 7
-#define NUMBER_HORIZONTAL_STACKED_TRACES 8
-#define DATA_USE 9
-#define DISTANCE_SOURCE_GROUP 10
-#define RECEIVER_GROUP_ELEVATION 11
-#define SURFACE_ELEVATION_AT_SOURCE 12
-#define SOURCE_DEPTH_BELOW_SURFACE 13
-#define DATUM_ELEVATION_AT_RECEIVER_GROUP 14
-#define DATUM_ELEVATION_AT_SOURCE 15
-#define WATER_DEPTH_AT_SOURCE 16
-#define WATER_DEPTH_AT_GROUP 17
-#define VERTICAL_SCALAR 18
-#define HORIZONTAL_SCALAR 19
-#define SOURCE_X 20
-#define SOURCE_Y 21
-#define GROUP_X 22
-#define GROUP_Y 23
-#define COORDINATE_UNITS 24
-#define WEATHERING_VELOCITY 25
-#define SUB_WEATHERING_VELOCITY 26
-#define UPHOLE_TIME_AT_SOURCE 27
-#define UPHOLE_TIME_AT_GROUP 28
-#define SOURCE_STATIC_CORRECTION 29
-#define GROUP_STATIC_CORRECTION 30
-#define TOTAL_STATIC_CORRECTION 31
-#define LAG_TIME_A 32
-#define LAG_TIME_B 33
-#define DELAY_RECORDING_TIME 34
-#define MUTE_TIME_START 35
-#define MUTE_TIME_END 36
-#define SAMPLES 37
-#define SAMPLE_INTERVAL 38
-#define GAIN_TYPE 39
-#define INSTRUMENT_GAIN_CONSTANT 40
-#define INSTRUMENT_INITIAL_GAIN 41
-#define CORRELATED 42
-#define SWEEP_FREQUENCY_AT_START 43
-#define SWEEP_FREQUENCY_AT_END 44
-#define SWEEP_LENGTH 45
-#define SWEEP_TYPE 46
-#define SWEEP_TRACE_TAPER_LENGTH_AT_START 47
-#define SWEEP_TRACE_TAPER_LENGTH_AT_END 48
-#define TAPER_TYPE 49
-#define ALIAS_FILTER_FREQUENCY 50
-#define ALIAS_FILTER_SLOPE 51
-#define NOTCH_FILTER_FREQUENCY 52
-#define NOTCH_FILTER_SLOPE 53
-#define LOW_CUT_FREQUENCY 54
-#define HIGH_CUT_FREQUENCY 55
-#define LOW_CUT_SLOPE 56
-#define HIGH_CUT_SLOPE 57
-#define YEAR 58
-#define DAY_OF_YEAR 59
-#define HOUR 60
-#define MINUTE 61
-#define SECOND 62
-#define TIME_BASIC_CODE 63
-#define TRACE_WEIGHTING_FACTOR 64
-#define GEOPHONE_GROUP_NUMBER_OF_ROLL_SWITH 65
-#define GEOPHONE_GROUP_NUMBER_OF_TRACE_NUMBER_ONE 66
-#define GEOPHONE_GROUP_NUMBER_OF_LAST_TRACE 67
-#define GAP_SIZE 68
-#define OVER_TRAVEL 69
-#define INLINE_NUMBER 70
-#define CROSSLINE_NUMBER 71
-#define SHOTPOINT_NUMBER 72
-#define SHOTPOINT_SCALAR 73
-
-#if 0
+static const int TRACE_NUMBER_WITHIN_LINE = 0;
+static const int TRACE_NUMBER_WITHIN_FILE = 1;
+static const int ORIGINAL_FIELD_RECORD_NUMBER = 2;
+static const int TRACE_NUMBER_WITHIN_ORIGINAL_FIELD_RECORD = 3;
+static const int TRACE_IDENTIFICATION_CODE = 4;
+static const int ENSEMBLE_NUMBER = 5;
+static const int TRACE_NUMBER_WITHIN_ENSEMBLE = 6;
+static const int NUMBER_VERTICAL_SUMMED_TRACES = 7;
+static const int NUMBER_HORIZONTAL_STACKED_TRACES = 8;
+static const int DATA_USE = 9;
+static const int DISTANCE_SOURCE_GROUP = 10;
+static const int RECEIVER_GROUP_ELEVATION = 11;
+static const int SURFACE_ELEVATION_AT_SOURCE = 12;
+static const int SOURCE_DEPTH_BELOW_SURFACE = 13;
+static const int DATUM_ELEVATION_AT_RECEIVER_GROUP = 14;
+static const int DATUM_ELEVATION_AT_SOURCE = 15;
+static const int WATER_DEPTH_AT_SOURCE = 16;
+static const int WATER_DEPTH_AT_GROUP = 17;
+static const int VERTICAL_SCALAR = 18;
+static const int HORIZONTAL_SCALAR = 19;
+static const int SOURCE_X = 20;
+static const int SOURCE_Y = 21;
+static const int GROUP_X = 22;
+static const int GROUP_Y = 23;
+static const int COORDINATE_UNITS = 24;
+static const int WEATHERING_VELOCITY = 25;
+static const int SUB_WEATHERING_VELOCITY = 26;
+static const int UPHOLE_TIME_AT_SOURCE = 27;
+static const int UPHOLE_TIME_AT_GROUP = 28;
+static const int SOURCE_STATIC_CORRECTION = 29;
+static const int GROUP_STATIC_CORRECTION = 30;
+static const int TOTAL_STATIC_CORRECTION = 31;
+static const int LAG_TIME_A = 32;
+static const int LAG_TIME_B = 33;
+static const int DELAY_RECORDING_TIME = 34;
+static const int MUTE_TIME_START = 35;
+static const int MUTE_TIME_END = 36;
+static const int SAMPLES = 37;
+static const int SAMPLE_INTERVAL = 38;
+static const int GAIN_TYPE = 39;
+static const int INSTRUMENT_GAIN_CONSTANT = 40;
+static const int INSTRUMENT_INITIAL_GAIN = 41;
+static const int CORRELATED = 42;
+static const int SWEEP_FREQUENCY_AT_START = 43;
+static const int SWEEP_FREQUENCY_AT_END = 44;
+static const int SWEEP_LENGTH = 45;
+static const int SWEEP_TYPE = 46;
+static const int SWEEP_TRACE_TAPER_LENGTH_AT_START = 47;
+static const int SWEEP_TRACE_TAPER_LENGTH_AT_END = 48;
+static const int TAPER_TYPE = 49;
+static const int ALIAS_FILTER_FREQUENCY = 50;
+static const int ALIAS_FILTER_SLOPE = 51;
+static const int NOTCH_FILTER_FREQUENCY = 52;
+static const int NOTCH_FILTER_SLOPE = 53;
+static const int LOW_CUT_FREQUENCY = 54;
+static const int HIGH_CUT_FREQUENCY = 55;
+static const int LOW_CUT_SLOPE = 56;
+static const int HIGH_CUT_SLOPE = 57;
+static const int YEAR = 58;
+static const int DAY_OF_YEAR = 59;
+static const int HOUR = 60;
+static const int MINUTE = 61;
+static const int SECOND = 62;
+static const int TIME_BASIC_CODE = 63;
+static const int TRACE_WEIGHTING_FACTOR = 64;
+static const int GEOPHONE_GROUP_NUMBER_OF_ROLL_SWITH = 65;
+static const int GEOPHONE_GROUP_NUMBER_OF_TRACE_NUMBER_ONE = 66;
+static const int GEOPHONE_GROUP_NUMBER_OF_LAST_TRACE = 67;
+static const int GAP_SIZE = 68;
+static const int OVER_TRAVEL = 69;
+static const int INLINE_NUMBER = 70;
+static const int CROSSLINE_NUMBER = 71;
+static const int SHOTPOINT_NUMBER = 72;
+static const int SHOTPOINT_SCALAR = 73;
+
 /************************************************************************/
 /*                       SEGYReadMSBFloat32()                           */
 /************************************************************************/
 
+#ifdef SEGY_EXTENSIONS
 static float SEGYReadMSBFloat32(const GByte* pabyVal)
 {
-    float fVal;
+    float fVal = 0.0f;
     memcpy(&fVal, pabyVal, 4);
     CPL_MSBPTR32(&fVal);
     return fVal;
@@ -224,19 +225,18 @@ static float SEGYReadMSBFloat32(const GByte* pabyVal)
 /*                           OGRSEGYLayer()                            */
 /************************************************************************/
 
-
 OGRSEGYLayer::OGRSEGYLayer( const char* pszFilename,
                             VSILFILE* fpIn,
-                            SEGYBinaryFileHeader* psBFH )
-
+                            SEGYBinaryFileHeader* psBFH ) :
+    poFeatureDefn(new OGRFeatureDefn(CPLGetBasename(pszFilename))),
+    bEOF(false),
+    nNextFID(0),
+    fp(fpIn),
+    nDataSize(0)
 {
-    this->fp = fpIn;
-    nNextFID = 0;
-    bEOF = FALSE;
     memcpy(&sBFH, psBFH, sizeof(sBFH));
 
-    nDataSize = 0;
-    switch (sBFH.nDataSampleType)
+    switch( sBFH.nDataSampleType )
     {
         case DT_IBM_4BYTES_FP: nDataSize = 4; break;
         case DT_4BYTES_INT: nDataSize = 4; break;
@@ -247,24 +247,27 @@ OGRSEGYLayer::OGRSEGYLayer( const char* pszFilename,
         default: break;
     }
 
-    poFeatureDefn = new OGRFeatureDefn( CPLGetBasename(pszFilename) );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPoint );
 
-    int i;
-    for(i=0;i<(int)(sizeof(SEGYFields)/sizeof(SEGYFields[0]));i++)
+    for( int i = 0; i < static_cast<int>(sizeof(SEGYFields) /
+                                         sizeof(SEGYFields[0]));
+         i++ )
     {
-        OGRFieldDefn    oField( SEGYFields[i].pszName,
-                                SEGYFields[i].eType );
+        OGRFieldDefn oField( SEGYFields[i].pszName,
+                             SEGYFields[i].eType );
         poFeatureDefn->AddFieldDefn( &oField );
     }
 
-    if (sBFH.dfSEGYRevisionNumber >= 1.0)
+    if( sBFH.dfSEGYRevisionNumber >= 1.0 )
     {
-        for(i=0;i<(int)(sizeof(SEGYFields10)/sizeof(SEGYFields10[0]));i++)
+        for( int i = 0;
+             i < static_cast<int>(sizeof(SEGYFields10) /
+                                  sizeof(SEGYFields10[0]));
+             i++ )
         {
-            OGRFieldDefn    oField( SEGYFields10[i].pszName,
-                                    SEGYFields10[i].eType );
+            OGRFieldDefn oField( SEGYFields10[i].pszName,
+                                 SEGYFields10[i].eType );
             poFeatureDefn->AddFieldDefn( &oField );
         }
     }
@@ -295,7 +298,7 @@ void OGRSEGYLayer::ResetReading()
 
 {
     nNextFID = 0;
-    bEOF = FALSE;
+    bEOF = false;
 
     VSIFSeekL( fp, 3200 + 400 + 3200 * sBFH.nNumberOfExtendedTextualFileHeader,
                SEEK_SET );
@@ -307,23 +310,21 @@ void OGRSEGYLayer::ResetReading()
 
 OGRFeature *OGRSEGYLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
     while( true )
     {
-        poFeature = GetNextRawFeature();
-        if (poFeature == NULL)
+        OGRFeature *poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
             return NULL;
 
-        if((m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
-        && (m_poAttrQuery == NULL
-            || m_poAttrQuery->Evaluate( poFeature )) )
+        if( (m_poFilterGeom == NULL
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
         {
             return poFeature;
         }
-        else
-            delete poFeature;
+
+        delete poFeature;
     }
 }
 
@@ -333,261 +334,273 @@ OGRFeature *OGRSEGYLayer::GetNextFeature()
 
 static float GetIBMFloat(const GByte* pabyData)
 {
-    int nVal;
+    int nVal = 0;
     memcpy(&nVal, pabyData, 4);
     CPL_MSBPTR32(&nVal);
-    int nSign = 1 - 2 * ((nVal >> 31) & 0x01);
-    int nExp = (nVal >> 24) & 0x7f;
-    int nMant = nVal & 0xffffff;
+    const int nSign = 1 - 2 * ((nVal >> 31) & 0x01);
+    const int nExp = (nVal >> 24) & 0x7f;
+    const int nMant = nVal & 0xffffff;
 
-    if (nExp == 0x7f)
+    if( nExp == 0x7f )
     {
         nVal = (nVal & 0x80000000) | (0xff << 23) | (nMant >> 1);
-        float fVal;
+        float fVal = 0;
         memcpy(&fVal, &nVal, 4);
         return fVal;
     }
 
-    return (float)((double)nSign * nMant * pow(2.0, 4 * (nExp - 64) - 24));
+    return
+        static_cast<float>(
+            static_cast<double>(nSign) *
+            nMant *
+            pow(2.0, 4 * (nExp - 64) - 24));
 }
+
 /************************************************************************/
 /*                         GetNextRawFeature()                          */
 /************************************************************************/
 
 OGRFeature *OGRSEGYLayer::GetNextRawFeature()
 {
-    if (bEOF)
+    if( bEOF )
         return NULL;
 
     GByte abyTraceHeader[240];
 
-    if ((int)VSIFReadL(abyTraceHeader, 1, 240, fp) != 240)
+    if( (int)VSIFReadL(abyTraceHeader, 1, 240, fp) != 240 )
     {
-        bEOF = TRUE;
+        bEOF = true;
         return NULL;
     }
 
-    int nTraceNumberWithinLine = SEGYReadMSBInt32(abyTraceHeader + 0);
-    int nTraceNumberWithinFile = SEGYReadMSBInt32(abyTraceHeader + 4);
-    int nOriginalFieldRecordNumber = SEGYReadMSBInt32(abyTraceHeader + 8);
-    int nTraceNumberWithinOriginalFieldRecord = SEGYReadMSBInt32(abyTraceHeader + 12);
-    int nEnsembleNumber = SEGYReadMSBInt32(abyTraceHeader + 20);
-    int nTraceNumberWithinEnsemble = SEGYReadMSBInt32(abyTraceHeader + 24);
-    int nTraceIdentificationCode = SEGYReadMSBInt16(abyTraceHeader + 28);
-    int nNumberVerticalSummedTraces = SEGYReadMSBInt16(abyTraceHeader + 30);
-    int nNumberHorizontalStackedTraces = SEGYReadMSBInt16(abyTraceHeader + 32);
-    int nDataUse = SEGYReadMSBInt16(abyTraceHeader + 34);
-    int nDistanceSourceGroup = SEGYReadMSBInt32(abyTraceHeader + 36);
-    int nReceiverGroupElevation = SEGYReadMSBInt32(abyTraceHeader + 40);
-    int nSurfaceElevationAtSource = SEGYReadMSBInt32(abyTraceHeader + 44);
-    int nSourceDepthBelowSurface = SEGYReadMSBInt32(abyTraceHeader + 48);
-    int nDatumElevationAtReceiverGroup = SEGYReadMSBInt32(abyTraceHeader + 52);
-    int nDatumElevationAtSource = SEGYReadMSBInt32(abyTraceHeader + 56);
-    int nWaterDepthAtSource = SEGYReadMSBInt32(abyTraceHeader + 60);
-    int nWaterDepthAtGroup = SEGYReadMSBInt32(abyTraceHeader + 64);
-    int nVerticalScalar = SEGYReadMSBInt16(abyTraceHeader + 68);
-    int nHorizontalScalar = SEGYReadMSBInt16(abyTraceHeader + 70);
-    int nSourceX = SEGYReadMSBInt32(abyTraceHeader + 72);
-    int nSourceY = SEGYReadMSBInt32(abyTraceHeader + 76);
-    int nGroupX = SEGYReadMSBInt32(abyTraceHeader + 80);
-    int nGroupY = SEGYReadMSBInt32(abyTraceHeader + 84);
-    int nCoordinateUnits = SEGYReadMSBInt16(abyTraceHeader + 88);
-    int nWeatheringVelocity = SEGYReadMSBInt16(abyTraceHeader + 90);
-    int nSubWeatheringVelocity = SEGYReadMSBInt16(abyTraceHeader + 92);
-
-    int nUpholeTimeAtSource = SEGYReadMSBInt16(abyTraceHeader + 94);
-    int nUpholeTimeAtGroup = SEGYReadMSBInt16(abyTraceHeader + 96);
-    int nSourceStaticCorrection = SEGYReadMSBInt16(abyTraceHeader + 98);
-    int nGroupStaticCorrection = SEGYReadMSBInt16(abyTraceHeader + 100);
-    int nTotalStaticCorrection = SEGYReadMSBInt16(abyTraceHeader + 102);
-    int nLagTimeA = SEGYReadMSBInt16(abyTraceHeader + 104);
-    int nLagTimeB = SEGYReadMSBInt16(abyTraceHeader + 106);
-    int nDelayRecordingTime = SEGYReadMSBInt16(abyTraceHeader + 108);
-    int nMuteTimeStart = SEGYReadMSBInt16(abyTraceHeader + 110);
-    int nMuteTimeEnd = SEGYReadMSBInt16(abyTraceHeader + 112);
+    const int nTraceNumberWithinLine = SEGYReadMSBInt32(abyTraceHeader + 0);
+    const int nTraceNumberWithinFile = SEGYReadMSBInt32(abyTraceHeader + 4);
+    const int nOriginalFieldRecordNumber = SEGYReadMSBInt32(abyTraceHeader + 8);
+    const int nTraceNumberWithinOriginalFieldRecord = SEGYReadMSBInt32(abyTraceHeader + 12);
+    const int nEnsembleNumber = SEGYReadMSBInt32(abyTraceHeader + 20);
+    const int nTraceNumberWithinEnsemble = SEGYReadMSBInt32(abyTraceHeader + 24);
+    const int nTraceIdentificationCode = SEGYReadMSBInt16(abyTraceHeader + 28);
+    const int nNumberVerticalSummedTraces = SEGYReadMSBInt16(abyTraceHeader + 30);
+    const int nNumberHorizontalStackedTraces = SEGYReadMSBInt16(abyTraceHeader + 32);
+    const int nDataUse = SEGYReadMSBInt16(abyTraceHeader + 34);
+    const int nDistanceSourceGroup = SEGYReadMSBInt32(abyTraceHeader + 36);
+    const int nReceiverGroupElevation = SEGYReadMSBInt32(abyTraceHeader + 40);
+    const int nSurfaceElevationAtSource = SEGYReadMSBInt32(abyTraceHeader + 44);
+    const int nSourceDepthBelowSurface = SEGYReadMSBInt32(abyTraceHeader + 48);
+    const int nDatumElevationAtReceiverGroup = SEGYReadMSBInt32(abyTraceHeader + 52);
+    const int nDatumElevationAtSource = SEGYReadMSBInt32(abyTraceHeader + 56);
+    const int nWaterDepthAtSource = SEGYReadMSBInt32(abyTraceHeader + 60);
+    const int nWaterDepthAtGroup = SEGYReadMSBInt32(abyTraceHeader + 64);
+    const int nVerticalScalar = SEGYReadMSBInt16(abyTraceHeader + 68);
+    const int nHorizontalScalar = SEGYReadMSBInt16(abyTraceHeader + 70);
+    const int nSourceX = SEGYReadMSBInt32(abyTraceHeader + 72);
+    const int nSourceY = SEGYReadMSBInt32(abyTraceHeader + 76);
+    const int nGroupX = SEGYReadMSBInt32(abyTraceHeader + 80);
+    const int nGroupY = SEGYReadMSBInt32(abyTraceHeader + 84);
+    const int nCoordinateUnits = SEGYReadMSBInt16(abyTraceHeader + 88);
+    const int nWeatheringVelocity = SEGYReadMSBInt16(abyTraceHeader + 90);
+    const int nSubWeatheringVelocity = SEGYReadMSBInt16(abyTraceHeader + 92);
+
+    const int nUpholeTimeAtSource = SEGYReadMSBInt16(abyTraceHeader + 94);
+    const int nUpholeTimeAtGroup = SEGYReadMSBInt16(abyTraceHeader + 96);
+    const int nSourceStaticCorrection = SEGYReadMSBInt16(abyTraceHeader + 98);
+    const int nGroupStaticCorrection = SEGYReadMSBInt16(abyTraceHeader + 100);
+    const int nTotalStaticCorrection = SEGYReadMSBInt16(abyTraceHeader + 102);
+    const int nLagTimeA = SEGYReadMSBInt16(abyTraceHeader + 104);
+    const int nLagTimeB = SEGYReadMSBInt16(abyTraceHeader + 106);
+    const int nDelayRecordingTime = SEGYReadMSBInt16(abyTraceHeader + 108);
+    const int nMuteTimeStart = SEGYReadMSBInt16(abyTraceHeader + 110);
+    const int nMuteTimeEnd = SEGYReadMSBInt16(abyTraceHeader + 112);
 
     int nSamples = SEGYReadMSBInt16(abyTraceHeader + 114);
-    if (nSamples == 0) /* Happens with ftp://software.seg.org/pub/datasets/2D/Hess_VTI/timodel_c11.segy.gz */
+    // Happens with
+    // ftp://software.seg.org/pub/datasets/2D/Hess_VTI/timodel_c11.segy.gz
+    if( nSamples == 0 )
         nSamples = sBFH.nSamplesPerDataTrace;
 
-    if (nSamples < 0)
+    if( nSamples < 0 )
     {
-        bEOF = TRUE;
+        bEOF = true;
         return NULL;
     }
-    int nSampleInterval = SEGYReadMSBInt16(abyTraceHeader + 116);
-
-    int nGainType = SEGYReadMSBInt16(abyTraceHeader + 118);
-    int nInstrumentGainConstant = SEGYReadMSBInt16(abyTraceHeader + 120);
-    int nInstrumentInitialGain = SEGYReadMSBInt16(abyTraceHeader + 122);
-    int nCorrelated = SEGYReadMSBInt16(abyTraceHeader + 124);
-    int nSweepFrequencyAtStart = SEGYReadMSBInt16(abyTraceHeader + 126);
-    int nSweepFrequencyAtEnd = SEGYReadMSBInt16(abyTraceHeader + 128);
-    int nSweepLength = SEGYReadMSBInt16(abyTraceHeader + 130);
-    int nSweepType = SEGYReadMSBInt16(abyTraceHeader + 132);
-    int nSweepTraceTaperLengthAtStart = SEGYReadMSBInt16(abyTraceHeader + 134);
-    int nSweepTraceTaperLengthAtEnd = SEGYReadMSBInt16(abyTraceHeader + 136);
-    int nTaperType = SEGYReadMSBInt16(abyTraceHeader + 138);
-    int nAliasFilterFrequency = SEGYReadMSBInt16(abyTraceHeader + 140);
-    int nAliasFilterSlope = SEGYReadMSBInt16(abyTraceHeader + 142);
-    int nNotchFilterFrequency = SEGYReadMSBInt16(abyTraceHeader + 144);
-    int nNotchFilterSlope = SEGYReadMSBInt16(abyTraceHeader + 146);
-    int nLowCutFrequency = SEGYReadMSBInt16(abyTraceHeader + 148);
-    int nHighCutFrequency = SEGYReadMSBInt16(abyTraceHeader + 150);
-    int nLowCutSlope = SEGYReadMSBInt16(abyTraceHeader + 152);
-    int nHighCutSlope = SEGYReadMSBInt16(abyTraceHeader + 154);
-
-    int nYear = SEGYReadMSBInt16(abyTraceHeader + 156);
-    int nDayOfYear = SEGYReadMSBInt16(abyTraceHeader + 158);
-    int nHour = SEGYReadMSBInt16(abyTraceHeader + 160);
-    int nMinute = SEGYReadMSBInt16(abyTraceHeader + 162);
-    int nSecond = SEGYReadMSBInt16(abyTraceHeader + 164);
-    int nTimeBasicCode = SEGYReadMSBInt16(abyTraceHeader + 166);
-
-    int nTraceWeightingFactor = SEGYReadMSBInt16(abyTraceHeader + 168);
-    int nGeophoneGroupNumberOfRollSwith = SEGYReadMSBInt16(abyTraceHeader + 170);
-    int nGeophoneGroupNumberOfTraceNumberOne = SEGYReadMSBInt16(abyTraceHeader + 172);
-    int nGeophoneGroupNumberOfLastTrace = SEGYReadMSBInt16(abyTraceHeader + 174);
-    int nGapSize = SEGYReadMSBInt16(abyTraceHeader + 176);
-    int nOverTravel = SEGYReadMSBInt16(abyTraceHeader + 178);
-
-    int nInlineNumber = SEGYReadMSBInt32(abyTraceHeader + 188);
-    int nCrosslineNumber = SEGYReadMSBInt32(abyTraceHeader + 192);
-    int nShotpointNumber = SEGYReadMSBInt32(abyTraceHeader + 196);
-    int nShotpointScalar = SEGYReadMSBInt16(abyTraceHeader + 200);
-
-#if 0
-    /* Extensions of http://sioseis.ucsd.edu/segy.header.html */
-    float fDeepWaterDelay = SEGYReadMSBFloat32(abyTraceHeader + 180);
-    float fStartMuteTime  = SEGYReadMSBFloat32(abyTraceHeader + 184);
-    float fEndMuteTime  = SEGYReadMSBFloat32(abyTraceHeader + 188);
-    float fSampleInterval  = SEGYReadMSBFloat32(abyTraceHeader + 192);
-    float fWaterBottomTime  = SEGYReadMSBFloat32(abyTraceHeader + 196);
-    int nEndOfRp = SEGYReadMSBInt16(abyTraceHeader + 200);
-    CPLDebug("SIGY", "fDeepWaterDelay = %f", fDeepWaterDelay);
-    CPLDebug("SIGY", "fStartMuteTime = %f", fStartMuteTime);
-    CPLDebug("SIGY", "fEndMuteTime = %f", fEndMuteTime);
-    CPLDebug("SIGY", "fSampleInterval = %f", fSampleInterval);
-    CPLDebug("SIGY", "fWaterBottomTime = %f", fWaterBottomTime);
-    CPLDebug("SIGY", "nEndOfRp = %d", nEndOfRp);
-#endif
-
-    double dfHorizontalScale = (nHorizontalScalar > 0) ? nHorizontalScalar :
-                               (nHorizontalScalar < 0) ? 1.0 / -nHorizontalScalar : 1.0;
-    if (nCoordinateUnits == 2)
+    const int nSampleInterval = SEGYReadMSBInt16(abyTraceHeader + 116);
+
+    const int nGainType = SEGYReadMSBInt16(abyTraceHeader + 118);
+    const int nInstrumentGainConstant = SEGYReadMSBInt16(abyTraceHeader + 120);
+    const int nInstrumentInitialGain = SEGYReadMSBInt16(abyTraceHeader + 122);
+    const int nCorrelated = SEGYReadMSBInt16(abyTraceHeader + 124);
+    const int nSweepFrequencyAtStart = SEGYReadMSBInt16(abyTraceHeader + 126);
+    const int nSweepFrequencyAtEnd = SEGYReadMSBInt16(abyTraceHeader + 128);
+    const int nSweepLength = SEGYReadMSBInt16(abyTraceHeader + 130);
+    const int nSweepType = SEGYReadMSBInt16(abyTraceHeader + 132);
+    const int nSweepTraceTaperLengthAtStart = SEGYReadMSBInt16(abyTraceHeader + 134);
+    const int nSweepTraceTaperLengthAtEnd = SEGYReadMSBInt16(abyTraceHeader + 136);
+    const int nTaperType = SEGYReadMSBInt16(abyTraceHeader + 138);
+    const int nAliasFilterFrequency = SEGYReadMSBInt16(abyTraceHeader + 140);
+    const int nAliasFilterSlope = SEGYReadMSBInt16(abyTraceHeader + 142);
+    const int nNotchFilterFrequency = SEGYReadMSBInt16(abyTraceHeader + 144);
+    const int nNotchFilterSlope = SEGYReadMSBInt16(abyTraceHeader + 146);
+    const int nLowCutFrequency = SEGYReadMSBInt16(abyTraceHeader + 148);
+    const int nHighCutFrequency = SEGYReadMSBInt16(abyTraceHeader + 150);
+    const int nLowCutSlope = SEGYReadMSBInt16(abyTraceHeader + 152);
+    const int nHighCutSlope = SEGYReadMSBInt16(abyTraceHeader + 154);
+
+    const int nYear = SEGYReadMSBInt16(abyTraceHeader + 156);
+    const int nDayOfYear = SEGYReadMSBInt16(abyTraceHeader + 158);
+    const int nHour = SEGYReadMSBInt16(abyTraceHeader + 160);
+    const int nMinute = SEGYReadMSBInt16(abyTraceHeader + 162);
+    const int nSecond = SEGYReadMSBInt16(abyTraceHeader + 164);
+    const int nTimeBasicCode = SEGYReadMSBInt16(abyTraceHeader + 166);
+
+    const int nTraceWeightingFactor = SEGYReadMSBInt16(abyTraceHeader + 168);
+    const int nGeophoneGroupNumberOfRollSwith = SEGYReadMSBInt16(abyTraceHeader + 170);
+    const int nGeophoneGroupNumberOfTraceNumberOne = SEGYReadMSBInt16(abyTraceHeader + 172);
+    const int nGeophoneGroupNumberOfLastTrace = SEGYReadMSBInt16(abyTraceHeader + 174);
+    const int nGapSize = SEGYReadMSBInt16(abyTraceHeader + 176);
+    const int nOverTravel = SEGYReadMSBInt16(abyTraceHeader + 178);
+
+    const int nInlineNumber = SEGYReadMSBInt32(abyTraceHeader + 188);
+    const int nCrosslineNumber = SEGYReadMSBInt32(abyTraceHeader + 192);
+    const int nShotpointNumber = SEGYReadMSBInt32(abyTraceHeader + 196);
+    const int nShotpointScalar = SEGYReadMSBInt16(abyTraceHeader + 200);
+
+#ifdef SEGY_EXTENSIONS
+#if DEBUG_VERBOSE
+    // Extensions of http://sioseis.ucsd.edu/segy.header.html
+    const float fDeepWaterDelay = SEGYReadMSBFloat32(abyTraceHeader + 180);
+    const float fStartMuteTime  = SEGYReadMSBFloat32(abyTraceHeader + 184);
+    const float fEndMuteTime  = SEGYReadMSBFloat32(abyTraceHeader + 188);
+    const float fSampleInterval  = SEGYReadMSBFloat32(abyTraceHeader + 192);
+    const float fWaterBottomTime  = SEGYReadMSBFloat32(abyTraceHeader + 196);
+    const int nEndOfRp = SEGYReadMSBInt16(abyTraceHeader + 200);
+    // TODO(schwehr): Use the extension vars and move DEBUG_VERBOSE here.
+    CPLDebug("SEGY", "fDeepWaterDelay = %f", fDeepWaterDelay);
+    CPLDebug("SEGY", "fStartMuteTime = %f", fStartMuteTime);
+    CPLDebug("SEGY", "fEndMuteTime = %f", fEndMuteTime);
+    CPLDebug("SEGY", "fSampleInterval = %f", fSampleInterval);
+    CPLDebug("SEGY", "fWaterBottomTime = %f", fWaterBottomTime);
+    CPLDebug("SEGY", "nEndOfRp = %d", nEndOfRp);
+#endif  // DEBUG_VERBOSE
+#endif  // SEGY_EXTENSIONS
+
+    double dfHorizontalScale =
+        (nHorizontalScalar > 0) ? nHorizontalScalar :
+        (nHorizontalScalar < 0) ? 1.0 / -nHorizontalScalar : 1.0;
+    if( nCoordinateUnits == 2 )
         dfHorizontalScale /= 3600;
 
-    double dfGroupX = nGroupX * dfHorizontalScale;
-    double dfGroupY = nGroupY * dfHorizontalScale;
-
-#if 0
-    double dfSourceX = nSourceX * dfHorizontalScale;
-    double dfSourceY = nSourceY * dfHorizontalScale;
-#endif
-
-#if 0
-    CPLDebug("SIGY", "nTraceNumberWithinLine = %d", nTraceNumberWithinLine);
-    CPLDebug("SIGY", "nTraceNumberWithinFile = %d", nTraceNumberWithinFile);
-    CPLDebug("SIGY", "nOriginalFieldRecordNumber = %d", nOriginalFieldRecordNumber);
-    CPLDebug("SIGY", "nTraceNumberWithinOriginalFieldRecord = %d", nTraceNumberWithinOriginalFieldRecord);
-    CPLDebug("SIGY", "nTraceIdentificationCode = %d", nTraceIdentificationCode);
-    CPLDebug("SIGY", "nEnsembleNumber = %d", nEnsembleNumber);
-    CPLDebug("SIGY", "nTraceNumberWithinEnsemble = %d", nTraceNumberWithinEnsemble);
-    CPLDebug("SIGY", "nNumberVerticalSummedTraces = %d", nNumberVerticalSummedTraces);
-    CPLDebug("SIGY", "nNumberHorizontalStackedTraces = %d", nNumberHorizontalStackedTraces);
-    CPLDebug("SIGY", "nDataUse = %d", nDataUse);
-    CPLDebug("SIGY", "nDistanceSourceGroup = %d", nDistanceSourceGroup);
-    CPLDebug("SIGY", "nReceiverGroupElevation = %d", nReceiverGroupElevation);
-    CPLDebug("SIGY", "nSurfaceElevationAtSource = %d", nSurfaceElevationAtSource);
-    CPLDebug("SIGY", "nSourceDepthBelowSurface = %d", nSourceDepthBelowSurface);
-    CPLDebug("SIGY", "nDatumElevationAtReceiverGroup = %d", nDatumElevationAtReceiverGroup);
-    CPLDebug("SIGY", "nDatumElevationAtSource = %d", nDatumElevationAtSource);
-    CPLDebug("SIGY", "nWaterDepthAtSource = %d", nWaterDepthAtSource);
-    CPLDebug("SIGY", "nWaterDepthAtGroup = %d", nWaterDepthAtGroup);
-    CPLDebug("SIGY", "nVerticalScalar = %d", nVerticalScalar);
-    CPLDebug("SIGY", "nHorizontalScalar = %d", nHorizontalScalar);
-    CPLDebug("SIGY", "nSourceX = %d", nSourceX);
-    CPLDebug("SIGY", "nSourceY = %d", nSourceY);
-    CPLDebug("SIGY", "dfSourceX = %f", dfSourceX);
-    CPLDebug("SIGY", "dfSourceY = %f", dfSourceY);
-    CPLDebug("SIGY", "nGroupX = %d", nGroupX);
-    CPLDebug("SIGY", "nGroupY = %d", nGroupY);
-    CPLDebug("SIGY", "dfGroupX = %f", dfGroupX);
-    CPLDebug("SIGY", "dfGroupY = %f", dfGroupY);
-    CPLDebug("SIGY", "nCoordinateUnits = %d", nCoordinateUnits);
-
-    CPLDebug("SIGY", "nWeatheringVelocity = %d", nWeatheringVelocity);
-    CPLDebug("SIGY", "nSubWeatheringVelocity = %d", nSubWeatheringVelocity);
-    CPLDebug("SIGY", "nUpholeTimeAtSource = %d", nUpholeTimeAtSource);
-    CPLDebug("SIGY", "nUpholeTimeAtGroup = %d", nUpholeTimeAtGroup);
-    CPLDebug("SIGY", "nSourceStaticCorrection = %d", nSourceStaticCorrection);
-    CPLDebug("SIGY", "nGroupStaticCorrection = %d", nGroupStaticCorrection);
-    CPLDebug("SIGY", "nTotalStaticCorrection = %d", nTotalStaticCorrection);
-    CPLDebug("SIGY", "nLagTimeA = %d", nLagTimeA);
-    CPLDebug("SIGY", "nLagTimeB = %d", nLagTimeB);
-    CPLDebug("SIGY", "nDelayRecordingTime = %d", nDelayRecordingTime);
-    CPLDebug("SIGY", "nMuteTimeStart = %d", nMuteTimeStart);
-    CPLDebug("SIGY", "nMuteTimeEnd = %d", nMuteTimeEnd);
-
-    CPLDebug("SIGY", "nSamples = %d", nSamples);
-    CPLDebug("SIGY", "nSampleInterval = %d", nSampleInterval);
-
-    CPLDebug("SIGY", "nGainType = %d", nGainType);
-    CPLDebug("SIGY", "nInstrumentGainConstant = %d", nInstrumentGainConstant);
-    CPLDebug("SIGY", "nInstrumentInitialGain = %d", nInstrumentInitialGain);
-    CPLDebug("SIGY", "nCorrelated = %d", nCorrelated);
-    CPLDebug("SIGY", "nSweepFrequencyAtStart = %d", nSweepFrequencyAtStart);
-    CPLDebug("SIGY", "nSweepFrequencyAtEnd = %d", nSweepFrequencyAtEnd);
-    CPLDebug("SIGY", "nSweepLength = %d", nSweepLength);
-    CPLDebug("SIGY", "nSweepType = %d", nSweepType);
-    CPLDebug("SIGY", "nSweepTraceTaperLengthAtStart = %d", nSweepTraceTaperLengthAtStart);
-    CPLDebug("SIGY", "nSweepTraceTaperLengthAtEnd = %d", nSweepTraceTaperLengthAtEnd);
-    CPLDebug("SIGY", "nTaperType = %d", nTaperType);
-    CPLDebug("SIGY", "nAliasFilterFrequency = %d", nAliasFilterFrequency);
-    CPLDebug("SIGY", "nAliasFilterSlope = %d", nAliasFilterSlope);
-    CPLDebug("SIGY", "nNotchFilterFrequency = %d", nNotchFilterFrequency);
-    CPLDebug("SIGY", "nNotchFilterSlope = %d", nNotchFilterSlope);
-    CPLDebug("SIGY", "nLowCutFrequency = %d", nLowCutFrequency);
-    CPLDebug("SIGY", "nHighCutFrequency = %d", nHighCutFrequency);
-    CPLDebug("SIGY", "nLowCutSlope = %d", nLowCutSlope);
-    CPLDebug("SIGY", "nHighCutSlope = %d", nHighCutSlope);
-    CPLDebug("SIGY", "nYear = %d", nYear);
-    CPLDebug("SIGY", "nDayOfYear = %d", nDayOfYear);
-    CPLDebug("SIGY", "nHour = %d", nHour);
-    CPLDebug("SIGY", "nMinute = %d", nMinute);
-    CPLDebug("SIGY", "nSecond = %d", nSecond);
-    CPLDebug("SIGY", "nTimeBasicCode = %d", nTimeBasicCode);
-    CPLDebug("SIGY", "nTraceWeightingFactor = %d", nTraceWeightingFactor);
-    CPLDebug("SIGY", "nGeophoneGroupNumberOfRollSwith = %d", nGeophoneGroupNumberOfRollSwith);
-    CPLDebug("SIGY", "nGeophoneGroupNumberOfTraceNumberOne = %d", nGeophoneGroupNumberOfTraceNumberOne);
-    CPLDebug("SIGY", "nGeophoneGroupNumberOfLastTrace = %d", nGeophoneGroupNumberOfLastTrace);
-    CPLDebug("SIGY", "nGapSize = %d", nGapSize);
-    CPLDebug("SIGY", "nOverTravel = %d", nOverTravel);
-
-    if (sBFH.dfSEGYRevisionNumber >= 1.0)
+    const double dfGroupX = nGroupX * dfHorizontalScale;
+    const double dfGroupY = nGroupY * dfHorizontalScale;
+
+#if DEBUG_VERBOSE
+    const double dfSourceX = nSourceX * dfHorizontalScale;
+    const double dfSourceY = nSourceY * dfHorizontalScale;
+
+    CPLDebug("SEGY", "nTraceNumberWithinLine = %d", nTraceNumberWithinLine);
+    CPLDebug("SEGY", "nTraceNumberWithinFile = %d", nTraceNumberWithinFile);
+    CPLDebug("SEGY", "nOriginalFieldRecordNumber = %d", nOriginalFieldRecordNumber);
+    CPLDebug("SEGY", "nTraceNumberWithinOriginalFieldRecord = %d", nTraceNumberWithinOriginalFieldRecord);
+    CPLDebug("SEGY", "nTraceIdentificationCode = %d", nTraceIdentificationCode);
+    CPLDebug("SEGY", "nEnsembleNumber = %d", nEnsembleNumber);
+    CPLDebug("SEGY", "nTraceNumberWithinEnsemble = %d", nTraceNumberWithinEnsemble);
+    CPLDebug("SEGY", "nNumberVerticalSummedTraces = %d", nNumberVerticalSummedTraces);
+    CPLDebug("SEGY", "nNumberHorizontalStackedTraces = %d", nNumberHorizontalStackedTraces);
+    CPLDebug("SEGY", "nDataUse = %d", nDataUse);
+    CPLDebug("SEGY", "nDistanceSourceGroup = %d", nDistanceSourceGroup);
+    CPLDebug("SEGY", "nReceiverGroupElevation = %d", nReceiverGroupElevation);
+    CPLDebug("SEGY", "nSurfaceElevationAtSource = %d", nSurfaceElevationAtSource);
+    CPLDebug("SEGY", "nSourceDepthBelowSurface = %d", nSourceDepthBelowSurface);
+    CPLDebug("SEGY", "nDatumElevationAtReceiverGroup = %d", nDatumElevationAtReceiverGroup);
+    CPLDebug("SEGY", "nDatumElevationAtSource = %d", nDatumElevationAtSource);
+    CPLDebug("SEGY", "nWaterDepthAtSource = %d", nWaterDepthAtSource);
+    CPLDebug("SEGY", "nWaterDepthAtGroup = %d", nWaterDepthAtGroup);
+    CPLDebug("SEGY", "nVerticalScalar = %d", nVerticalScalar);
+    CPLDebug("SEGY", "nHorizontalScalar = %d", nHorizontalScalar);
+    CPLDebug("SEGY", "nSourceX = %d", nSourceX);
+    CPLDebug("SEGY", "nSourceY = %d", nSourceY);
+    CPLDebug("SEGY", "dfSourceX = %f", dfSourceX);
+    CPLDebug("SEGY", "dfSourceY = %f", dfSourceY);
+    CPLDebug("SEGY", "nGroupX = %d", nGroupX);
+    CPLDebug("SEGY", "nGroupY = %d", nGroupY);
+    CPLDebug("SEGY", "dfGroupX = %f", dfGroupX);
+    CPLDebug("SEGY", "dfGroupY = %f", dfGroupY);
+    CPLDebug("SEGY", "nCoordinateUnits = %d", nCoordinateUnits);
+
+    CPLDebug("SEGY", "nWeatheringVelocity = %d", nWeatheringVelocity);
+    CPLDebug("SEGY", "nSubWeatheringVelocity = %d", nSubWeatheringVelocity);
+    CPLDebug("SEGY", "nUpholeTimeAtSource = %d", nUpholeTimeAtSource);
+    CPLDebug("SEGY", "nUpholeTimeAtGroup = %d", nUpholeTimeAtGroup);
+    CPLDebug("SEGY", "nSourceStaticCorrection = %d", nSourceStaticCorrection);
+    CPLDebug("SEGY", "nGroupStaticCorrection = %d", nGroupStaticCorrection);
+    CPLDebug("SEGY", "nTotalStaticCorrection = %d", nTotalStaticCorrection);
+    CPLDebug("SEGY", "nLagTimeA = %d", nLagTimeA);
+    CPLDebug("SEGY", "nLagTimeB = %d", nLagTimeB);
+    CPLDebug("SEGY", "nDelayRecordingTime = %d", nDelayRecordingTime);
+    CPLDebug("SEGY", "nMuteTimeStart = %d", nMuteTimeStart);
+    CPLDebug("SEGY", "nMuteTimeEnd = %d", nMuteTimeEnd);
+
+    CPLDebug("SEGY", "nSamples = %d", nSamples);
+    CPLDebug("SEGY", "nSampleInterval = %d", nSampleInterval);
+
+    CPLDebug("SEGY", "nGainType = %d", nGainType);
+    CPLDebug("SEGY", "nInstrumentGainConstant = %d", nInstrumentGainConstant);
+    CPLDebug("SEGY", "nInstrumentInitialGain = %d", nInstrumentInitialGain);
+    CPLDebug("SEGY", "nCorrelated = %d", nCorrelated);
+    CPLDebug("SEGY", "nSweepFrequencyAtStart = %d", nSweepFrequencyAtStart);
+    CPLDebug("SEGY", "nSweepFrequencyAtEnd = %d", nSweepFrequencyAtEnd);
+    CPLDebug("SEGY", "nSweepLength = %d", nSweepLength);
+    CPLDebug("SEGY", "nSweepType = %d", nSweepType);
+    CPLDebug("SEGY", "nSweepTraceTaperLengthAtStart = %d", nSweepTraceTaperLengthAtStart);
+    CPLDebug("SEGY", "nSweepTraceTaperLengthAtEnd = %d", nSweepTraceTaperLengthAtEnd);
+    CPLDebug("SEGY", "nTaperType = %d", nTaperType);
+    CPLDebug("SEGY", "nAliasFilterFrequency = %d", nAliasFilterFrequency);
+    CPLDebug("SEGY", "nAliasFilterSlope = %d", nAliasFilterSlope);
+    CPLDebug("SEGY", "nNotchFilterFrequency = %d", nNotchFilterFrequency);
+    CPLDebug("SEGY", "nNotchFilterSlope = %d", nNotchFilterSlope);
+    CPLDebug("SEGY", "nLowCutFrequency = %d", nLowCutFrequency);
+    CPLDebug("SEGY", "nHighCutFrequency = %d", nHighCutFrequency);
+    CPLDebug("SEGY", "nLowCutSlope = %d", nLowCutSlope);
+    CPLDebug("SEGY", "nHighCutSlope = %d", nHighCutSlope);
+    CPLDebug("SEGY", "nYear = %d", nYear);
+    CPLDebug("SEGY", "nDayOfYear = %d", nDayOfYear);
+    CPLDebug("SEGY", "nHour = %d", nHour);
+    CPLDebug("SEGY", "nMinute = %d", nMinute);
+    CPLDebug("SEGY", "nSecond = %d", nSecond);
+    CPLDebug("SEGY", "nTimeBasicCode = %d", nTimeBasicCode);
+    CPLDebug("SEGY", "nTraceWeightingFactor = %d", nTraceWeightingFactor);
+    CPLDebug("SEGY", "nGeophoneGroupNumberOfRollSwith = %d", nGeophoneGroupNumberOfRollSwith);
+    CPLDebug("SEGY", "nGeophoneGroupNumberOfTraceNumberOne = %d", nGeophoneGroupNumberOfTraceNumberOne);
+    CPLDebug("SEGY", "nGeophoneGroupNumberOfLastTrace = %d", nGeophoneGroupNumberOfLastTrace);
+    CPLDebug("SEGY", "nGapSize = %d", nGapSize);
+    CPLDebug("SEGY", "nOverTravel = %d", nOverTravel);
+
+    if( sBFH.dfSEGYRevisionNumber >= 1.0 )
     {
-        CPLDebug("SIGY", "nInlineNumber = %d", nInlineNumber);
-        CPLDebug("SIGY", "nCrosslineNumber = %d", nCrosslineNumber);
-        CPLDebug("SIGY", "nShotpointNumber = %d", nShotpointNumber);
-        CPLDebug("SIGY", "nShotpointScalar = %d", nShotpointScalar);
+        CPLDebug("SEGY", "nInlineNumber = %d", nInlineNumber);
+        CPLDebug("SEGY", "nCrosslineNumber = %d", nCrosslineNumber);
+        CPLDebug("SEGY", "nShotpointNumber = %d", nShotpointNumber);
+        CPLDebug("SEGY", "nShotpointScalar = %d", nShotpointScalar);
     }
 #endif
 
-    GByte* pabyData = (GByte*) VSI_MALLOC_VERBOSE( nDataSize * nSamples );
-    double* padfValues = (double*) VSI_CALLOC_VERBOSE( nSamples, sizeof(double) );
-    if (pabyData == NULL || padfValues == NULL)
+    GByte* pabyData = static_cast<GByte *>(
+        VSI_MALLOC_VERBOSE(nDataSize * nSamples));
+    double* padfValues = static_cast<double *>(
+        VSI_CALLOC_VERBOSE(nSamples, sizeof(double)));
+    if( pabyData == NULL || padfValues == NULL )
     {
         VSIFSeekL( fp, nDataSize * nSamples, SEEK_CUR );
     }
     else
     {
-        if ((int)VSIFReadL(pabyData, nDataSize, nSamples, fp) != nSamples)
+        if( static_cast<int>(VSIFReadL(pabyData, nDataSize,
+                                       nSamples, fp)) != nSamples )
         {
-            bEOF = TRUE;
+            bEOF = true;
         }
-        for(int i=0;i<nSamples;i++)
+        for( int i = 0; i < nSamples; i++ )
         {
-            switch (sBFH.nDataSampleType)
+            switch( sBFH.nDataSampleType )
             {
                 case DT_IBM_4BYTES_FP:
                 {
@@ -597,7 +610,7 @@ OGRFeature *OGRSEGYLayer::GetNextRawFeature()
 
                 case DT_4BYTES_INT:
                 {
-                    int nVal;
+                    int nVal = 0;
                     memcpy(&nVal, pabyData + i * 4, 4);
                     CPL_MSBPTR32(&nVal);
                     padfValues[i] = nVal;
@@ -606,7 +619,7 @@ OGRFeature *OGRSEGYLayer::GetNextRawFeature()
 
                 case DT_2BYTES_INT:
                 {
-                    GInt16 nVal;
+                    GInt16 nVal = 0;
                     memcpy(&nVal, pabyData + i * 2, 2);
                     CPL_MSBPTR16(&nVal);
                     padfValues[i] = nVal;
@@ -615,7 +628,7 @@ OGRFeature *OGRSEGYLayer::GetNextRawFeature()
 
                 case DT_IEEE_4BYTES_FP:
                 {
-                    float fVal;
+                    float fVal = 0.0f;
                     memcpy(&fVal, pabyData + i * 4, 4);
                     CPL_MSBPTR32(&fVal);
                     padfValues[i] = fVal;
@@ -637,7 +650,7 @@ OGRFeature *OGRSEGYLayer::GetNextRawFeature()
 
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
     poFeature->SetFID(nNextFID ++);
-    if (dfGroupX != 0.0 || dfGroupY != 0.0)
+    if( dfGroupX != 0.0 || dfGroupY != 0.0 )
         poFeature->SetGeometryDirectly(new OGRPoint(dfGroupX, dfGroupY));
 
     poFeature->SetField(TRACE_NUMBER_WITHIN_LINE, nTraceNumberWithinLine);
@@ -711,7 +724,7 @@ OGRFeature *OGRSEGYLayer::GetNextRawFeature()
     poFeature->SetField(GAP_SIZE, nGapSize);
     poFeature->SetField(OVER_TRAVEL, nOverTravel);
 
-    if (sBFH.dfSEGYRevisionNumber >= 1.0)
+    if( sBFH.dfSEGYRevisionNumber >= 1.0 )
     {
         poFeature->SetField(INLINE_NUMBER, nInlineNumber);
         poFeature->SetField(CROSSLINE_NUMBER, nCrosslineNumber);
@@ -719,15 +732,14 @@ OGRFeature *OGRSEGYLayer::GetNextRawFeature()
         poFeature->SetField(SHOTPOINT_SCALAR, nShotpointScalar);
     }
 
-    if (nSamples > 0 && padfValues != NULL)
-        poFeature->SetField(poFeature->GetFieldCount() - 1, nSamples, padfValues);
+    if( nSamples > 0 && padfValues != NULL )
+        poFeature->SetField(poFeature->GetFieldCount() - 1,
+                            nSamples, padfValues);
 
     CPLFree(padfValues);
     return poFeature;
 }
 
-
-
 static const FieldDesc SEGYHeaderFields[] =
 {
     { "TEXT_HEADER", OFTString },
@@ -764,64 +776,63 @@ static const FieldDesc SEGYHeaderFields[] =
     { "NUMBER_OF_EXTENDED_TEXTUAL_FILE_HEADER", OFTInteger },
 };
 
-#define HEADER_TEXT_HEADER 0
-#define HEADER_JOB_ID_NUMBER 1
-#define HEADER_LINE_NUMBER 2
-#define HEADER_REEL_NUMBER 3
-#define HEADER_DATA_TRACES_PER_ENSEMBLE 4
-#define HEADER_AUX_TRACES_PER_ENSEMBLE 5
-#define HEADER_SAMPLE_INTERVAL 6
-#define HEADER_SAMPLE_INTERVAL_ORIGINAL 7
-#define HEADER_SAMPLES_PER_DATA_TRACE 8
-#define HEADER_SAMPLES_PER_DATA_TRACE_ORIGINAL 9
-#define HEADER_DATA_SAMPLE_TYPE 10
-#define HEADER_ENSEMBLE_FOLD 11
-#define HEADER_TRACE_SORTING_CODE 12
-#define HEADER_VERTICAL_SUM_CODE 13
-#define HEADER_SWEEP_FREQUENCY_AT_START 14
-#define HEADER_SWEEP_FREQUENCY_AT_END 15
-#define HEADER_SWEEP_LENGTH 16
-#define HEADER_SWEEP_TYPE 17
-#define HEADER_TRACE_NUMBER_OF_SWEEP_CHANNEL 18
-#define HEADER_SWEEP_TRACE_TAPER_LENGTH_AT_START 19
-#define HEADER_SWEEP_TRACE_TAPER_LENGTH_AT_END 20
-#define HEADER_TAPER_TYPE 21
-#define HEADER_CORRELATED 22
-#define HEADER_BINARY_GAIN_RECOVERED 23
-#define HEADER_AMPLITUDE_RECOVERY_METHOD 24
-#define HEADER_MEASUREMENT_SYSTEM 25
-#define HEADER_IMPULSE_SIGNAL_POLARITY 26
-#define HEADER_VIBRATORY_POLARY_CODE 27
-#define HEADER_SEGY_REVISION_NUMBER 28
-#define HEADER_FLOAT_SEGY_REVISION_NUMBER 29
-#define HEADER_FIXED_LENGTH_TRACE_FLAG 30
-#define HEADER_NUMBER_OF_EXTENDED_TEXTUAL_FILE_HEADER 31
-
+static const int HEADER_TEXT_HEADER = 0;
+static const int HEADER_JOB_ID_NUMBER = 1;
+static const int HEADER_LINE_NUMBER = 2;
+static const int HEADER_REEL_NUMBER = 3;
+static const int HEADER_DATA_TRACES_PER_ENSEMBLE = 4;
+static const int HEADER_AUX_TRACES_PER_ENSEMBLE = 5;
+static const int HEADER_SAMPLE_INTERVAL = 6;
+static const int HEADER_SAMPLE_INTERVAL_ORIGINAL = 7;
+static const int HEADER_SAMPLES_PER_DATA_TRACE = 8;
+static const int HEADER_SAMPLES_PER_DATA_TRACE_ORIGINAL = 9;
+static const int HEADER_DATA_SAMPLE_TYPE = 10;
+static const int HEADER_ENSEMBLE_FOLD = 11;
+static const int HEADER_TRACE_SORTING_CODE = 12;
+static const int HEADER_VERTICAL_SUM_CODE = 13;
+static const int HEADER_SWEEP_FREQUENCY_AT_START = 14;
+static const int HEADER_SWEEP_FREQUENCY_AT_END = 15;
+static const int HEADER_SWEEP_LENGTH = 16;
+static const int HEADER_SWEEP_TYPE = 17;
+static const int HEADER_TRACE_NUMBER_OF_SWEEP_CHANNEL = 18;
+static const int HEADER_SWEEP_TRACE_TAPER_LENGTH_AT_START = 19;
+static const int HEADER_SWEEP_TRACE_TAPER_LENGTH_AT_END = 20;
+static const int HEADER_TAPER_TYPE = 21;
+static const int HEADER_CORRELATED = 22;
+static const int HEADER_BINARY_GAIN_RECOVERED = 23;
+static const int HEADER_AMPLITUDE_RECOVERY_METHOD = 24;
+static const int HEADER_MEASUREMENT_SYSTEM = 25;
+static const int HEADER_IMPULSE_SIGNAL_POLARITY = 26;
+static const int HEADER_VIBRATORY_POLARY_CODE = 27;
+static const int HEADER_SEGY_REVISION_NUMBER = 28;
+static const int HEADER_FLOAT_SEGY_REVISION_NUMBER = 29;
+static const int HEADER_FIXED_LENGTH_TRACE_FLAG = 30;
+static const int HEADER_NUMBER_OF_EXTENDED_TEXTUAL_FILE_HEADER = 31;
 
 /************************************************************************/
 /*                         OGRSEGYHeaderLayer()                         */
 /************************************************************************/
 
-
 OGRSEGYHeaderLayer::OGRSEGYHeaderLayer( const char* pszLayerName,
                                         SEGYBinaryFileHeader* psBFH,
-                                        const char* pszHeaderTextIn )
-
+                                        const char* pszHeaderTextIn ) :
+    poFeatureDefn(new OGRFeatureDefn(pszLayerName)),
+    bEOF(false),
+    pszHeaderText(CPLStrdup(pszHeaderTextIn))
 {
-    bEOF = FALSE;
     memcpy(&sBFH, psBFH, sizeof(sBFH));
-    pszHeaderText = CPLStrdup(pszHeaderTextIn);
 
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-    int i;
-    for(i=0;i<(int)(sizeof(SEGYHeaderFields)/sizeof(SEGYHeaderFields[0]));i++)
+    for( int i = 0;
+         i < static_cast<int>(sizeof(SEGYHeaderFields)/
+                              sizeof(SEGYHeaderFields[0]));
+         i++ )
     {
-        OGRFieldDefn    oField( SEGYHeaderFields[i].pszName,
-                                SEGYHeaderFields[i].eType );
+        OGRFieldDefn oField( SEGYHeaderFields[i].pszName,
+                             SEGYHeaderFields[i].eType );
         poFeatureDefn->AddFieldDefn( &oField );
     }
 
@@ -846,7 +857,7 @@ OGRSEGYHeaderLayer::~OGRSEGYHeaderLayer()
 void OGRSEGYHeaderLayer::ResetReading()
 
 {
-    bEOF = FALSE;
+    bEOF = false;
 }
 
 /************************************************************************/
@@ -855,23 +866,23 @@ void OGRSEGYHeaderLayer::ResetReading()
 
 OGRFeature *OGRSEGYHeaderLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
     while( true )
     {
-        poFeature = GetNextRawFeature();
-        if (poFeature == NULL)
+        OGRFeature *poFeature = GetNextRawFeature();
+        if( poFeature == NULL )
             return NULL;
 
-        if((m_poFilterGeom == NULL
-            || FilterGeometry( poFeature->GetGeometryRef() ) )
-        && (m_poAttrQuery == NULL
-            || m_poAttrQuery->Evaluate( poFeature )) )
+        if( (m_poFilterGeom == NULL
+             || FilterGeometry( poFeature->GetGeometryRef() ) )
+            && (m_poAttrQuery == NULL
+                || m_poAttrQuery->Evaluate( poFeature )) )
         {
             return poFeature;
         }
         else
+        {
             delete poFeature;
+        }
     }
 }
 
@@ -881,10 +892,10 @@ OGRFeature *OGRSEGYHeaderLayer::GetNextFeature()
 
 OGRFeature *OGRSEGYHeaderLayer::GetNextRawFeature()
 {
-    if (bEOF)
+    if( bEOF )
         return NULL;
 
-    bEOF = TRUE;
+    bEOF = true;
 
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
     poFeature->SetFID(0);
diff --git a/ogr/ogrsf_frmts/selafin/GNUmakefile b/ogr/ogrsf_frmts/selafin/GNUmakefile
index 23b4f57..e03c3ae 100644
--- a/ogr/ogrsf_frmts/selafin/GNUmakefile
+++ b/ogr/ogrsf_frmts/selafin/GNUmakefile
@@ -4,7 +4,7 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrselafindriver.o ogrselafindatasource.o ogrselafinlayer.o io_selafin.o
 
-CPPFLAGS	:=	-I.. -I../..  $(CPPFLAGS) 
+CPPFLAGS	:=	-I.. -I../..  $(CPPFLAGS)
 
 # To pass -Wextra -Werror, enable this next line:
 # CPPFLAGS += -Wno-missing-field-initializers
diff --git a/ogr/ogrsf_frmts/selafin/io_selafin.cpp b/ogr/ogrsf_frmts/selafin/io_selafin.cpp
index dff01a3..55f66de 100644
--- a/ogr/ogrsf_frmts/selafin/io_selafin.cpp
+++ b/ogr/ogrsf_frmts/selafin/io_selafin.cpp
@@ -32,6 +32,8 @@
 #include "cpl_error.h"
 #include "cpl_quad_tree.h"
 
+CPL_CVSID("$Id: io_selafin.cpp 36347 2016-11-20 20:43:39Z rouault $");
+
 namespace Selafin {
 
     const char SELAFIN_ERROR_MESSAGE[]="Error when reading Selafin file\n";
@@ -41,7 +43,8 @@ namespace Selafin {
         const Header *poHeader;
     };
 
-    static void GetBoundsFunc(const void *hFeature,CPLRectObj *poBounds) {
+    static void GetBoundsFunc( const void *hFeature,CPLRectObj *poBounds )
+    {
         const Point *poPoint=(const Point*)hFeature;
         poBounds->minx=poPoint->poHeader->paadfCoords[0][poPoint->nIndex];
         poBounds->maxx=poPoint->poHeader->paadfCoords[0][poPoint->nIndex];
@@ -49,14 +52,14 @@ namespace Selafin {
         poBounds->maxy=poPoint->poHeader->paadfCoords[1][poPoint->nIndex];
     }
 
-    static int DumpFeatures(void *pElt,
-                     CPL_UNUSED void *pUserData) {
+    static int DumpFeatures( void *pElt,
+                             void * /* pUserData */ )
+    {
         Point *poPoint=(Point*)pElt;
         delete poPoint;
         return TRUE;
     }
 
-
     /****************************************************************/
     /*                         Header                               */
     /****************************************************************/
@@ -81,28 +84,33 @@ namespace Selafin {
         panBorder(NULL),
         panStartDate(NULL),
         nSteps(0),
-        nEpsg(0) {
-        paadfCoords[0]=NULL;
-        paadfCoords[1]=NULL;
-        for (size_t i=0;i<7;++i) anUnused[i]=0;
+        nEpsg(0)
+    {
+        paadfCoords[0] = NULL;
+        paadfCoords[1] = NULL;
+        for( size_t i = 0; i < 7; ++i ) anUnused[i] = 0;
+        adfOrigin[0] = 0.0;
+        adfOrigin[1] = 0.0;
     }
 
     Header::~Header() {
         CPLFree(pszFilename);
         CPLFree(pszTitle);
-        if (papszVariables!=NULL) {
-            for (int i=0;i<nVar;++i) CPLFree(papszVariables[i]);
+        if( papszVariables!=NULL )
+        {
+            for( int i = 0; i < nVar; ++i ) CPLFree(papszVariables[i]);
             CPLFree(papszVariables);
         }
         CPLFree(panConnectivity);
         CPLFree(panBorder);
-        if (poTree!=NULL) {
+        if( poTree!=NULL )
+        {
             CPLQuadTreeForeach(poTree,DumpFeatures,NULL);
             CPLQuadTreeDestroy(poTree);
         }
         CPLFree(panStartDate);
-        for (size_t i=0;i<2;++i) CPLFree(paadfCoords[i]);
-        if (fp!=NULL) VSIFCloseL(fp);
+        for( size_t i = 0; i < 2; ++i ) CPLFree(paadfCoords[i]);
+        if( fp != NULL ) VSIFCloseL(fp);
     }
 
     void Header::setUpdated() {
@@ -138,7 +146,9 @@ namespace Selafin {
         }
     }
 
-    int Header::getClosestPoint(const double &dfx,const double &dfy,const double &dfMax) {
+    int Header::getClosestPoint( const double &dfx, const double &dfy,
+                                 const double &dfMax)
+    {
         // If there is no quad-tree of the points, build it now
         if (bTreeUpdateNeeded) {
             if (poTree!=NULL) {
@@ -160,25 +170,26 @@ namespace Selafin {
             }
         }
         // Now we can look for the nearest neighbour using this tree
-        int nIndex=-1;
-        double dfMin;
+        int nIndex = -1;
         CPLRectObj poObj;
-        poObj.minx=dfx-dfMax;
-        poObj.maxx=dfx+dfMax;
+        poObj.minx = dfx-dfMax;
+        poObj.maxx = dfx+dfMax;
         poObj.miny=dfy-dfMax;
         poObj.maxy=dfy+dfMax;
-        int nFeatureCount;
-        void **phResults=CPLQuadTreeSearch(poTree,&poObj,&nFeatureCount);
-        if (nFeatureCount<=0) return -1;
-        double dfa,dfb,dfc;
-        dfMin=dfMax*dfMax;
-        for (int i=0;i<nFeatureCount;++i) {
+        int nFeatureCount = 0;
+        void **phResults = CPLQuadTreeSearch(poTree, &poObj, &nFeatureCount);
+        if( nFeatureCount <=0 ) return -1;
+        double dfMin = dfMax * dfMax;
+        for( int i=0;i<nFeatureCount;++i )
+        {
             Point *poPoint=(Point*)(phResults[i]);
-            dfa=dfx-poPoint->poHeader->paadfCoords[0][poPoint->nIndex];
-            dfa*=dfa;
+            double dfa =
+                dfx-poPoint->poHeader->paadfCoords[0][poPoint->nIndex];
+            dfa *= dfa;
             if (dfa>=dfMin) continue;
-            dfb=dfy-poPoint->poHeader->paadfCoords[1][poPoint->nIndex];
-            dfc=dfa+dfb*dfb;
+            const double dfb =
+                dfy-poPoint->poHeader->paadfCoords[1][poPoint->nIndex];
+            const double dfc = dfa + dfb * dfb;
             if (dfc<dfMin) {
                 dfMin=dfc;
                 nIndex=poPoint->nIndex;
@@ -219,8 +230,8 @@ namespace Selafin {
         // We must also remove all the elements referencing the deleted feature, otherwise the file will not be consistent any inter
         int nOldElements=nElements;
         for (int i=0;i<nElements;++i) {
-            bool bReferencing=false;
-            int *panTemp=panConnectivity+i*nPointsPerElement;
+            bool bReferencing = false;
+            int *panTemp = panConnectivity + i * nPointsPerElement;
             for (int j=0;j<nPointsPerElement;++j) bReferencing |= (panTemp[j]==nIndex+1);
             if (bReferencing) {
                 nElements--;
@@ -260,7 +271,9 @@ namespace Selafin {
     /****************************************************************/
     /*                         TimeStep                             */
     /****************************************************************/
-    TimeStep::TimeStep(int nRecordsP,int nFieldsP):nFields(nFieldsP) {
+    TimeStep::TimeStep( int nRecordsP, int nFieldsP ) :
+        nFields(nFieldsP)
+    {
         papadfData=(double**)VSI_MALLOC2_VERBOSE(sizeof(double*),nFieldsP);
         for (int i=0;i<nFieldsP;++i) papadfData[i]=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),nRecordsP);
     }
@@ -275,12 +288,12 @@ namespace Selafin {
     /****************************************************************/
     TimeStepList::~TimeStepList() {
         TimeStepList *poFirst=this;
-        TimeStepList *poTmp;
-        while (poFirst!=0) {
-            poTmp=poFirst->poNext;
+        while( poFirst != 0 )
+        {
+            TimeStepList *poTmp = poFirst->poNext;
             delete poFirst->poStep;
             delete poFirst;
-            poFirst=poTmp;
+            poFirst = poTmp;
         }
     }
 #endif
@@ -397,8 +410,9 @@ namespace Selafin {
         return 1;
     }
 
-    int read_float(VSILFILE *fp,double &dfData,bool bDiscard) {
-        float dfVal;
+    int read_float(VSILFILE *fp, double &dfData, bool bDiscard)
+    {
+        float dfVal = 0.0;
         if (VSIFReadL(&dfVal,1,4,fp)<4) {
             CPLError(CE_Failure,CPLE_FileIO,"%s",SELAFIN_ERROR_MESSAGE);
             return 0;
@@ -410,7 +424,7 @@ namespace Selafin {
         return 1;
     }
 
-    int write_float(VSILFILE *fp,double dfData) {
+    int write_float(VSILFILE *fp, double dfData) {
         float dfVal=(float)dfData;
         CPL_MSBPTR32(&dfVal);
         if (VSIFWriteL(&dfVal,1,4,fp)<4) {
@@ -466,18 +480,16 @@ namespace Selafin {
 
     Header *read_header(VSILFILE *fp,const char *pszFilename) {
         // Get the total file size (used later to estimate the number of time steps)
-        int nFileSize;
         VSIFSeekL(fp,0,SEEK_END);
-        nFileSize=(int)VSIFTellL(fp);
+        int nFileSize = (int)VSIFTellL(fp);
         VSIRewindL(fp);
         // Save the filename
-        int nLength;
         Header *poHeader=new Header();
         poHeader->fp=fp;
         poHeader->pszFilename=CPLStrdup(pszFilename);
         int *panTemp = NULL;
         // Read the title
-        nLength=read_string(fp,poHeader->pszTitle);
+        int nLength = read_string(fp,poHeader->pszTitle);
         if (nLength==0) {
             delete poHeader;
             return NULL;
@@ -608,8 +620,8 @@ namespace Selafin {
         if (write_intarray(fp,anTemp,4)==0) return 0;
         if (write_intarray(fp,poHeader->panConnectivity,poHeader->nElements*poHeader->nPointsPerElement)==0) return 0;
         if (write_intarray(fp,poHeader->panBorder,poHeader->nPoints)==0) return 0;
-        double *dfVals;
-        dfVals=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),poHeader->nPoints);
+        double *dfVals = (double*)
+            VSI_MALLOC2_VERBOSE(sizeof(double),poHeader->nPoints);
         if (poHeader->nPoints>0 && dfVals==NULL) return 0;
         for (size_t i=0;i<2;++i) {
             for (int j=0;j<poHeader->nPoints;++j) dfVals[j]=poHeader->paadfCoords[i][j]-poHeader->adfOrigin[i];
@@ -625,7 +637,7 @@ namespace Selafin {
 #ifdef notdef
     int read_step(VSILFILE *fp,const Header *poHeader,TimeStep *&poStep) {
         poStep=new TimeStep(poHeader->nPoints,poHeader->nVar);
-        int nLength;
+        int nLength = 0;
         if (read_integer(fp,nLength)==0 || nLength!=1) {
             delete poStep;
             return 0;
@@ -648,7 +660,6 @@ namespace Selafin {
         return 1;
     }
 
-
     int write_step(VSILFILE *fp,const Header *poHeader,const TimeStep *poStep) {
         if (write_integer(fp,1)==0) return 0;
         if (write_float(fp,poStep->dfDate)==0) return 0;
diff --git a/ogr/ogrsf_frmts/selafin/io_selafin.h b/ogr/ogrsf_frmts/selafin/io_selafin.h
index 29415b8..193b00a 100644
--- a/ogr/ogrsf_frmts/selafin/io_selafin.h
+++ b/ogr/ogrsf_frmts/selafin/io_selafin.h
@@ -25,334 +25,332 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-
 #ifndef  IO_SELAFIN_H_INC
 #define  IO_SELAFIN_H_INC
 
-#include "cpl_vsi.h"
 #include "cpl_quad_tree.h"
+#include "cpl_vsi.h"
 
 namespace Selafin {
     /**
      * \brief Data structure holding general information about a Selafin file
      */
-    class Header {
-        private:
-            int nHeaderSize; //!< Size (in bytes) of the header of the file (seeking to this location brings to the first "feature")
-            int nStepSize;    //!< Size (in bytes) of one feature in the file
-            int nMinxIndex;    //!< Index of the point at the western border of the bounding box
-            int nMaxxIndex;    //!< Index of the point at the eastern border of the bounding box
-            int nMinyIndex;    //!< Index of the point at the southern border of the bounding box
-            int nMaxyIndex;    //!< Index of the point at the northern border of the bounding box
-            bool bTreeUpdateNeeded;  //!< Tell if the quad tree has to be updated
-        public:
-            //size_t nRefCount;   //!< Number of references to this object
-            VSILFILE *fp;   //!< Pointer to the file with the layers
-            char *pszFilename;  //!< Name of the Selafin file
-            char *pszTitle; //!< Title of the simulation
-            int nVar;   //!< Number of variables
-            char **papszVariables;  //!< Name of the variables
-            int nPoints;    //!< Total number of points
-            int nElements;  //!< Total number of elements
-            int nPointsPerElement;  //!< Number of points per element
-            int *panConnectivity;   //!< Connectivity table of elements: first nPointsPerElement elements are the indices of the points making the first element, and so on. In the Selafin file, the first point has index 1.
-            double *paadfCoords[2]; //!< Table of coordinates of points: x then y
-            CPLQuadTree *poTree;    //!< Quad-tree for spatially indexing points in the array paadfCoords. The tree will mostly contain a Null value, until a request is made to find a closest neighbour, in which case it will be built and maintained
-            double adfOrigin[2];  //!< Table of coordinates of the origin of the axis
-            int *panBorder;    //!< Array of integers defining border points (0 for an inner point, and the index of the border point otherwise). This table is not used by the driver but stored to allow to rewrite the header if needed
-            int *panStartDate;    //!< Table with the starting date of the simulation (may be 0 if date is not defined). Date is registered as a set of six elements: year, month, day, hour, minute, second.
-            int nSteps;    //!< Number of steps in the Selafin file
-            int nEpsg; //!< EPSG of the file
-            int anUnused[7];   //!< Array of integers for storing the eight values read from the header but not actually used by the driver. These values are merely saved to rewrite them in the file if it is changed.
-
-            Header(); //!< Standard constructor
-            ~Header();  //!< Destructor of structure
-
-            /**
-             * \brief Return the position of a particular data in the Selafin file
-             *
-             * This function returns the position in the Selafin file of a particular element, characterized by the number of the time step, the index of the feature and the index of the attribute. If both nFeature and nAttribute are equal to -1 (default value), the function returns the position of the start of this time step. If nFeature is -1 but nAttribute is greater than 0, the function returns the position of the table for the given attribute (compatible with Selafin::read_floatarray)
-             * \param nStep Number of the time step, starting with 0
-             * \param nFeature Index of the feature (point), starting with 0
-             * \param nAttribute Index of the attribute, starting with 0
-             * \return Position (in bytes) from the start of the file
-             */
-            int getPosition(int nStep,int nFeature=-1,int nAttribute=-1) const; // {return nHeaderSize+nStep*nStepSize+(nFeature!=-1)?(12+nAttribute*(nPoints+2)*4+4+nFeature*4):0;}
-
-            /**
-             * \brief Return the bounding box of the points
-             *
-             * This function returns the bounding box of the set of points. The bounding box is stored in memory for quicker access.
-             * \return Pointer to the bounding box. The calling program is responsible for destroying it
-             */
-            CPLRectObj *getBoundingBox() const;
-
-            /**
-             * \brief Update the bounding box of the points
-             *
-             * This function calculates the bounding box of the set of points and stores it in the class.
-             */
-            void updateBoundingBox();
-
-            /**
-             * \brief Return the index of the point closest to the given coordinates
-             *
-             * This function searches the point in the array which is the closest to the one given by the user in arguments, but no farther than distance dfMax.
-             * \param dfx x-coordinate of the reference point
-             * \param dfy y-coordinate of the reference point
-             * \param dfMax Maximum distance allowed to the point
-             * \return Index of the closest point in the array, -1 if there was no point at all in the array closer than distance dfMax
-             */
-            int getClosestPoint(const double &dfx,const double &dfy,const double &dfMax);
-
-            /**
-             * \brief Tells that the header has been changed
-             *
-             * This function must be used whenever one of the member of the structure was changed. It forces the recalculation of some variables (header size and step size).
-             */
-            void setUpdated();
-
-            /**
-             * \brief Add a new point at the end of point list
-             *
-             * This function add a new point at the end of the array. If the arrays of coordinates are too small, they may be resized. The bounding box is updated.
-             * \param dfx x-coordinate of the new point
-             * \param dfy y-coordinate of the new point
-             */
-            void addPoint(const double &dfx,const double &dfy);
-
-            /**
-             * \brief Remove a point from the point list
-             *
-             * This function removes a point at position nIndex from the array of points. The bounding box is updated. All the elements which referenced this point are also removed.
-             * \param nIndex Index of the point which has to be removed
-             */
-            void removePoint(int nIndex);
-
-    };
+class Header {
+    private:
+        int nHeaderSize; //!< Size (in bytes) of the header of the file (seeking to this location brings to the first "feature")
+        int nStepSize;    //!< Size (in bytes) of one feature in the file
+        int nMinxIndex;    //!< Index of the point at the western border of the bounding box
+        int nMaxxIndex;    //!< Index of the point at the eastern border of the bounding box
+        int nMinyIndex;    //!< Index of the point at the southern border of the bounding box
+        int nMaxyIndex;    //!< Index of the point at the northern border of the bounding box
+        bool bTreeUpdateNeeded;  //!< Tell if the quad tree has to be updated
+    public:
+        //size_t nRefCount;   //!< Number of references to this object
+        VSILFILE *fp;   //!< Pointer to the file with the layers
+        char *pszFilename;  //!< Name of the Selafin file
+        char *pszTitle; //!< Title of the simulation
+        int nVar;   //!< Number of variables
+        char **papszVariables;  //!< Name of the variables
+        int nPoints;    //!< Total number of points
+        int nElements;  //!< Total number of elements
+        int nPointsPerElement;  //!< Number of points per element
+        int *panConnectivity;   //!< Connectivity table of elements: first nPointsPerElement elements are the indices of the points making the first element, and so on. In the Selafin file, the first point has index 1.
+        double *paadfCoords[2]; //!< Table of coordinates of points: x then y
+        CPLQuadTree *poTree;    //!< Quad-tree for spatially indexing points in the array paadfCoords. The tree will mostly contain a Null value, until a request is made to find a closest neighbour, in which case it will be built and maintained
+        double adfOrigin[2];  //!< Table of coordinates of the origin of the axis
+        int *panBorder;    //!< Array of integers defining border points (0 for an inner point, and the index of the border point otherwise). This table is not used by the driver but stored to allow to rewrite the header if needed
+        int *panStartDate;    //!< Table with the starting date of the simulation (may be 0 if date is not defined). Date is registered as a set of six elements: year, month, day, hour, minute, second.
+        int nSteps;    //!< Number of steps in the Selafin file
+        int nEpsg; //!< EPSG of the file
+        int anUnused[7];   //!< Array of integers for storing the eight values read from the header but not actually used by the driver. These values are merely saved to rewrite them in the file if it is changed.
+
+        Header(); //!< Standard constructor
+        ~Header();  //!< Destructor of structure
+
+        /**
+         * \brief Return the position of a particular data in the Selafin file
+         *
+         * This function returns the position in the Selafin file of a particular element, characterized by the number of the time step, the index of the feature and the index of the attribute. If both nFeature and nAttribute are equal to -1 (default value), the function returns the position of the start of this time step. If nFeature is -1 but nAttribute is greater than 0, the function returns the position of the table for the given attribute (compatible with Selafin::read_floatarray)
+         * \param nStep Number of the time step, starting with 0
+         * \param nFeature Index of the feature (point), starting with 0
+         * \param nAttribute Index of the attribute, starting with 0
+         * \return Position (in bytes) from the start of the file
+         */
+        int getPosition(int nStep,int nFeature=-1,int nAttribute=-1) const; // {return nHeaderSize+nStep*nStepSize+(nFeature!=-1)?(12+nAttribute*(nPoints+2)*4+4+nFeature*4):0;}
+
+        /**
+         * \brief Return the bounding box of the points
+         *
+         * This function returns the bounding box of the set of points. The bounding box is stored in memory for quicker access.
+         * \return Pointer to the bounding box. The calling program is responsible for destroying it
+         */
+        CPLRectObj *getBoundingBox() const;
+
+        /**
+         * \brief Update the bounding box of the points
+         *
+         * This function calculates the bounding box of the set of points and stores it in the class.
+         */
+        void updateBoundingBox();
+
+        /**
+         * \brief Return the index of the point closest to the given coordinates
+         *
+         * This function searches the point in the array which is the closest to the one given by the user in arguments, but no farther than distance dfMax.
+         * \param dfx x-coordinate of the reference point
+         * \param dfy y-coordinate of the reference point
+         * \param dfMax Maximum distance allowed to the point
+         * \return Index of the closest point in the array, -1 if there was no point at all in the array closer than distance dfMax
+         */
+        int getClosestPoint(const double &dfx,const double &dfy,const double &dfMax);
+
+        /**
+         * \brief Tells that the header has been changed
+         *
+         * This function must be used whenever one of the member of the structure was changed. It forces the recalculation of some variables (header size and step size).
+         */
+        void setUpdated();
+
+        /**
+         * \brief Add a new point at the end of point list
+         *
+         * This function add a new point at the end of the array. If the arrays of coordinates are too small, they may be resized. The bounding box is updated.
+         * \param dfx x-coordinate of the new point
+         * \param dfy y-coordinate of the new point
+         */
+        void addPoint(const double &dfx,const double &dfy);
+
+        /**
+         * \brief Remove a point from the point list
+         *
+         * This function removes a point at position nIndex from the array of points. The bounding box is updated. All the elements which referenced this point are also removed.
+         * \param nIndex Index of the point which has to be removed
+         */
+        void removePoint(int nIndex);
+};
 
 #ifdef notdef
-    /**
-     * \brief Data structure holding the attributes of all nodes for one time step
-     */
-    class TimeStep {
-        private:
-            //int nRecords;  //!< Number of records (first index) in the TimeStep::papadfData array, which should correspond to the number of features (either points or elements) in a Selafin layer
-            int nFields;   //!< Number of fields for each record (second index) in the TimeStep::papadfData array, which should correspond to the number of attributes in a Selafin layer
-        public:
-            double dfDate;  //!< Date of the time step (usually in seconds after the starting date)
-            double **papadfData;    //!< Double-indexed array with values of all attributes for all features. The first index is the number of the attribute, the second is the number of the feature.
-
-            /**
-             * \brief Constructor of the structure
-             *
-             * This function allocates the TimeStep::papadfData array based on the dimensions provided in argument.
-             * \param nRecords Number of records (first index) in the TimeStep::papadfData array, which should correspond to the number of features (either points or elements) in a Selafin layer
-             * \param nFields Number of fields for each record (second index) in the TimeStep::papadfData array, which should correspond to the number of attributes in a Selafin layer
-             */
-            TimeStep(int nRecordsP,int nFieldsP);
-
-            ~TimeStep();    //!< Standard destructor
-    };
-
-    /**
-     * \brief Structure holding a chained list of time steps (of class TimeStep)
-     */
-    class TimeStepList {
-        public:
-            TimeStep *poStep;   //!< Pointer to the time step structure
-            TimeStepList *poNext;   //!< Pointer to the next element in the list
-
-            TimeStepList(TimeStep *poStepP,TimeStepList *poNextP):poStep(poStepP),poNext(poNextP) {}    //!< Standard constructor
-            ~TimeStepList();    //!< Standard destructor
-    };
+/**
+ * \brief Data structure holding the attributes of all nodes for one time step
+ */
+class TimeStep {
+    private:
+        //int nRecords;  //!< Number of records (first index) in the TimeStep::papadfData array, which should correspond to the number of features (either points or elements) in a Selafin layer
+        int nFields;   //!< Number of fields for each record (second index) in the TimeStep::papadfData array, which should correspond to the number of attributes in a Selafin layer
+    public:
+        double dfDate;  //!< Date of the time step (usually in seconds after the starting date)
+        double **papadfData;    //!< Double-indexed array with values of all attributes for all features. The first index is the number of the attribute, the second is the number of the feature.
+
+        /**
+         * \brief Constructor of the structure
+         *
+         * This function allocates the TimeStep::papadfData array based on the dimensions provided in argument.
+         * \param nRecords Number of records (first index) in the TimeStep::papadfData array, which should correspond to the number of features (either points or elements) in a Selafin layer
+         * \param nFields Number of fields for each record (second index) in the TimeStep::papadfData array, which should correspond to the number of attributes in a Selafin layer
+         */
+        TimeStep(int nRecordsP,int nFieldsP);
+
+        ~TimeStep();    //!< Standard destructor
+};
+
+/**
+ * \brief Structure holding a chained list of time steps (of class TimeStep)
+ */
+class TimeStepList {
+    public:
+        TimeStep *poStep;   //!< Pointer to the time step structure
+        TimeStepList *poNext;   //!< Pointer to the next element in the list
+
+        TimeStepList(TimeStep *poStepP,TimeStepList *poNextP):poStep(poStepP),poNext(poNextP) {}    //!< Standard constructor
+        ~TimeStepList();    //!< Standard destructor
+};
 #endif
 
-    /**
-     * \brief Read an integer from a Selafin file
-     *
-     * This function reads an integer from an opened file. In Selafin files, integers are stored on 4 bytes in big-endian format (most significant byte first).
-     * \param fp Pointer to an open file
-     * \param nData After the execution, contains the value read
-     * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
-     * \return 1 if the integer was successfully read, 0 otherwise
-     */
-    int read_integer(VSILFILE *fp,int &nData,bool bDiscard=false);
-
-    /**
-     * \brief Write an integer to a Selafin file
-     *
-     * This function writes an integer to an opened file. See also Selafin::read_integer for additional information about how integers are stored in a Selafin file.
-     * \param fp Pointer to an open file
-     * \param nData Value to be written to the file
-     * \return 1 if the integer was successfully written, 0 otherwise
-     */
-    int write_integer(VSILFILE *fp,int nData);
-
-    /**
-     * \brief Read a string from a Selafin file
-     *
-     * This function reads a string from an opened file. In Selafin files, strings are stored in three parts:
-     *   - an integer \a n (therefore on 4 bytes) with the length of the string
-     *   - the \a n bytes of the string, preferably in ASCII format
-     *   - once again the integer \a n (on 4 bytes)
-     * The function does not check if the last integer is the same as the first one.
-     * \param fp Pointer to an open file
-     * \param pszData After the execution, contains the value read. The structure is allocated by the function.
-     * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
-     * \return Number of characters in string read
-     */
-    int read_string(VSILFILE *fp,char *&pszData,bool bDiscard=false);
-
-    /**
-     * \brief Write a string to a Selafin file
-     *
-     * This function writes a string to an opened file. See also Selafin::read_string for additional information about how strings are stored in a Selafin file.
-     * \param fp Pointer to an open file
-     * \param pszData String to be written to the file
-     * \param nLength Length of the string. If the value is 0, the length is automatically calculated. It is recommended to provide this value to avoid an additional strlen call. However, providing a value larger than the actual size of the string will result in an overflow read access and most likely in a segmentation fault.
-     * \return 1 if the string was successfully written, 0 otherwise
-     */
-    int write_string(VSILFILE *fp,char *pszData,size_t nLength=0);
-
-    /**
-     * \brief Read an array of integers from a Selafin file
-     *
-     * This function reads an array of integers from an opened file. In Selafin files, arrays of integers are stored in three parts:
-     *   - an integer \a n with the \e size of the array (therefore 4 times the number of elements)
-     *   - the \f$ \frac{n}{4} \f$ elements of the array, each on 4 bytes
-     *   - once again the integer \a n (on 4 bytes)
-     * The function does not check if the last integer is the same as the first one.
-     * \param fp Pointer to an open file
-     * \param panData After the execution, contains the array read. The structure is allocated by the function.
-     * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
-     * \return Number of elements in array read, -1 if an error occurred
-     */
-    int read_intarray(VSILFILE *fp,int *&panData,bool bDiscard=false);
-
-    /**
-     * \brief Write an array of integers to a Selafin file
-     *
-     * This function writes an array of integers to an opened file. See also Selafin::read_intarray for additional information about how arrays of integers are stored in a Selafin file.
-     * \param fp Pointer to an open file
-     * \param panData Array to be written to the file
-     * \param nLength Number of elements in the array
-     * \return 1 if the array was successfully written, 0 otherwise
-     */
-    int write_intarray(VSILFILE *fp,int *panData,size_t nLength);
-
-    /**
-     * \brief Read a floating point number from a Selafin file
-     *
-     * This function reads a floating point value from an opened file. In Selafin files, floats are stored on 4 bytes in big-endian format (most significant byte first).
-     * \param fp Pointer to an open file
-     * \param dfData After the execution, contains the value read
-     * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
-     * \return 1 if the floating point number was successfully read, 0 otherwise
-     */
-    int read_float(VSILFILE *fp,double &dfData,bool bDiscard=false);
-
-    /**
-     * \brief Write a floating point number to a Selafin file
-     *
-     * This function writes a floating point value from an opened file. See also Selafin::read_float for additional information about how floating point numbers are stored in a Selafin file.
-     * \param fp Pointer to an open file
-     * \param dfData Floating point number to be written to the file
-     * \return 1 if the floating point number was successfully written, 0 otherwise
-     */
-    int write_float(VSILFILE *fp,double dfData);
-
-    /**
-     * \brief Read an array of floats from a Selafin file
-     *
-     * This function reads an array of floats from an opened file. In Selafin files, arrays of floats are stored in three parts:
-     *   - an integer \a n with the \e size of the array (therefore 4 times the number of elements)
-     *   - the \f$ \frac{n}{4} \f$ elements of the array, each on 4 bytes
-     *   - once again the integer \a n (on 4 bytes)
-     * The function does not check if the last integer is the same as the first one.
-     * \param fp Pointer to an open file
-     * \param papadfData After the execution, contains the array read. The structure is allocated by the function.
-     * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
-     * \return Number of elements in array read, -1 if an error occurred
-     */
-    int read_floatarray(VSILFILE *fp,double **papadfData,bool bDiscard=false);
-
-    /**
-     * \brief Write an array of floats to a Selafin file
-     *
-     * This function writes an array of floats from an opened file. See also Selafin::read_floatarray for additional information about how arrays of floating point numbers are stored in a Selafin file.
-     * \param fp Pointer to an open file
-     * \param padfData Pointer to the array of floating point numbers to be written to the file
-     * \param nLength Number of elements in the array
-     * \return 1 if the array was successfully written, 0 otherwise
-     */
-    int write_floatarray(VSILFILE *fp,double *padfData,size_t nLength);
-
-    /**
-     * \brief Read the header of a Selafin file
-     *
-     * This function reads the whole header of a Selafin file (that is everything before the first time step) and stores it in a Selafin::Header structure. The file pointer is moved at the beginning of the file before reading.
-     * \param fp Pointer to an open file
-     * \param pszFilename Name of the file
-     * \return Pointer to a newly-allocated header structure, 0 if the function failed to read the whole header
-     */
-    Header *read_header(VSILFILE *fp,const char* pszFilename);
-
-    /**
-     * \brief Write the header to a file
-     *
-     * This function writes the header to an opened file. The file pointer is moved at the beginning of the file and the content is overwritten.
-     * \param fp Pointer to an open file with write access
-     * \return 1 if the header was successfully written, 0 otherwise
-     */
-    int write_header(VSILFILE *fp,Header *poHeader);
+/**
+ * \brief Read an integer from a Selafin file
+ *
+ * This function reads an integer from an opened file. In Selafin files, integers are stored on 4 bytes in big-endian format (most significant byte first).
+ * \param fp Pointer to an open file
+ * \param nData After the execution, contains the value read
+ * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
+ * \return 1 if the integer was successfully read, 0 otherwise
+ */
+int read_integer(VSILFILE *fp,int &nData,bool bDiscard=false);
+
+/**
+ * \brief Write an integer to a Selafin file
+ *
+ * This function writes an integer to an opened file. See also Selafin::read_integer for additional information about how integers are stored in a Selafin file.
+ * \param fp Pointer to an open file
+ * \param nData Value to be written to the file
+ * \return 1 if the integer was successfully written, 0 otherwise
+ */
+int write_integer(VSILFILE *fp,int nData);
+
+/**
+ * \brief Read a string from a Selafin file
+ *
+ * This function reads a string from an opened file. In Selafin files, strings are stored in three parts:
+ *   - an integer \a n (therefore on 4 bytes) with the length of the string
+ *   - the \a n bytes of the string, preferably in ASCII format
+ *   - once again the integer \a n (on 4 bytes)
+ * The function does not check if the last integer is the same as the first one.
+ * \param fp Pointer to an open file
+ * \param pszData After the execution, contains the value read. The structure is allocated by the function.
+ * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
+ * \return Number of characters in string read
+ */
+int read_string(VSILFILE *fp,char *&pszData,bool bDiscard=false);
+
+/**
+ * \brief Write a string to a Selafin file
+ *
+ * This function writes a string to an opened file. See also Selafin::read_string for additional information about how strings are stored in a Selafin file.
+ * \param fp Pointer to an open file
+ * \param pszData String to be written to the file
+ * \param nLength Length of the string. If the value is 0, the length is automatically calculated. It is recommended to provide this value to avoid an additional strlen call. However, providing a value larger than the actual size of the string will result in an overflow read access and most likely in a segmentation fault.
+ * \return 1 if the string was successfully written, 0 otherwise
+ */
+int write_string(VSILFILE *fp,char *pszData,size_t nLength=0);
+
+/**
+ * \brief Read an array of integers from a Selafin file
+ *
+ * This function reads an array of integers from an opened file. In Selafin files, arrays of integers are stored in three parts:
+ *   - an integer \a n with the \e size of the array (therefore 4 times the number of elements)
+ *   - the \f$ \frac{n}{4} \f$ elements of the array, each on 4 bytes
+ *   - once again the integer \a n (on 4 bytes)
+ * The function does not check if the last integer is the same as the first one.
+ * \param fp Pointer to an open file
+ * \param panData After the execution, contains the array read. The structure is allocated by the function.
+ * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
+ * \return Number of elements in array read, -1 if an error occurred
+ */
+int read_intarray(VSILFILE *fp,int *&panData,bool bDiscard=false);
+
+/**
+ * \brief Write an array of integers to a Selafin file
+ *
+ * This function writes an array of integers to an opened file. See also Selafin::read_intarray for additional information about how arrays of integers are stored in a Selafin file.
+ * \param fp Pointer to an open file
+ * \param panData Array to be written to the file
+ * \param nLength Number of elements in the array
+ * \return 1 if the array was successfully written, 0 otherwise
+ */
+int write_intarray(VSILFILE *fp,int *panData,size_t nLength);
+
+/**
+ * \brief Read a floating point number from a Selafin file
+ *
+ * This function reads a floating point value from an opened file. In Selafin files, floats are stored on 4 bytes in big-endian format (most significant byte first).
+ * \param fp Pointer to an open file
+ * \param dfData After the execution, contains the value read
+ * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
+ * \return 1 if the floating point number was successfully read, 0 otherwise
+ */
+int read_float(VSILFILE *fp,double &dfData,bool bDiscard=false);
+
+/**
+ * \brief Write a floating point number to a Selafin file
+ *
+ * This function writes a floating point value from an opened file. See also Selafin::read_float for additional information about how floating point numbers are stored in a Selafin file.
+ * \param fp Pointer to an open file
+ * \param dfData Floating point number to be written to the file
+ * \return 1 if the floating point number was successfully written, 0 otherwise
+ */
+int write_float(VSILFILE *fp,double dfData);
+
+/**
+ * \brief Read an array of floats from a Selafin file
+ *
+ * This function reads an array of floats from an opened file. In Selafin files, arrays of floats are stored in three parts:
+ *   - an integer \a n with the \e size of the array (therefore 4 times the number of elements)
+ *   - the \f$ \frac{n}{4} \f$ elements of the array, each on 4 bytes
+ *   - once again the integer \a n (on 4 bytes)
+ * The function does not check if the last integer is the same as the first one.
+ * \param fp Pointer to an open file
+ * \param papadfData After the execution, contains the array read. The structure is allocated by the function.
+ * \param bDiscard If true, the function does not attempt to save the value read in the variable nData, but only advances in the file as it should. Default value is false.
+ * \return Number of elements in array read, -1 if an error occurred
+ */
+int read_floatarray(VSILFILE *fp,double **papadfData,bool bDiscard=false);
+
+/**
+ * \brief Write an array of floats to a Selafin file
+ *
+ * This function writes an array of floats from an opened file. See also Selafin::read_floatarray for additional information about how arrays of floating point numbers are stored in a Selafin file.
+ * \param fp Pointer to an open file
+ * \param padfData Pointer to the array of floating point numbers to be written to the file
+ * \param nLength Number of elements in the array
+ * \return 1 if the array was successfully written, 0 otherwise
+ */
+int write_floatarray(VSILFILE *fp,double *padfData,size_t nLength);
+
+/**
+ * \brief Read the header of a Selafin file
+ *
+ * This function reads the whole header of a Selafin file (that is everything before the first time step) and stores it in a Selafin::Header structure. The file pointer is moved at the beginning of the file before reading.
+ * \param fp Pointer to an open file
+ * \param pszFilename Name of the file
+ * \return Pointer to a newly-allocated header structure, 0 if the function failed to read the whole header
+ */
+Header *read_header(VSILFILE *fp,const char* pszFilename);
+
+/**
+ * \brief Write the header to a file
+ *
+ * This function writes the header to an opened file. The file pointer is moved at the beginning of the file and the content is overwritten.
+ * \param fp Pointer to an open file with write access
+ * \return 1 if the header was successfully written, 0 otherwise
+ */
+int write_header(VSILFILE *fp,Header *poHeader);
 
 #ifdef notdef
-    /**
-     * \brief Read one time step from a Selafin file
-     *
-     * This function reads a single time step, with all the field values, from an open Selafin file at the current position.
-     * \param fp Pointer to an open file
-     * \param poHeader Pointer to the header structure. This should be read before the call to the function because some of its members are used to determine the format of the time step.
-     * \param poStep After the execution, holds the data for the current step. The variable is allocated by the function
-     * \return 1 if the time step was successfully read, 0 otherwise
-     */
-    int read_step(VSILFILE *fp,const Header *poHeader,TimeStep *&poStep);
-
-    /**
-     * \brief Write one time step to a Selafin file
-     *
-     * This function writes a single time step, with all the field values, to an open Selafin file at the current position.
-     * \param fp Pointer to an open file with write access
-     * \param poHeader Pointer to the header structure. This should be read before the call to the function because some of its members are used to determine the format of the time step.
-     * \param poStep Data of current step
-     * \return 1 if the time step was successfully written, 0 otherwise
-     */
-    int write_step(VSILFILE *fp,const Header *poHeader,const TimeStep *poStep);
-
-    /**
-     * \brief Read all time steps from a Selafin file
-     *
-     * This function reads all time steps, with all the field values, from an open Selafin file at the current position.
-     * \param fp Pointer to an open file
-     * \param poHeader Pointer to the header structure. This should be read before the call to the function because some of its members are used to determine the format of the time step.
-     * \param poSteps After the execution, holds the list of time steps. The variable is allocated by the function
-     * \return 1 if the time steps were successfully read, 0 otherwise
-     */
-    int read_steps(VSILFILE *fp,const Header *poHeader,TimeStepList *&poSteps);
-
-    /**
-     * \brief Write one time step to a Selafin file
-     *
-     * This function writes a single time step, with all the field values, to an open Selafin file at the current position.
-     * \param fp Pointer to an open file with write access
-     * \param poHeader Pointer to the header structure. This should be read before the call to the function because some of its members are used to determine the format of the time step.
-     * \param poSteps List of all steps
-     * \return 1 if the time steps were successfully written, 0 otherwise
-     */
-    int write_steps(VSILFILE *fp,const Header *poHeader,const TimeStepList *poSteps);
+/**
+ * \brief Read one time step from a Selafin file
+ *
+ * This function reads a single time step, with all the field values, from an open Selafin file at the current position.
+ * \param fp Pointer to an open file
+ * \param poHeader Pointer to the header structure. This should be read before the call to the function because some of its members are used to determine the format of the time step.
+ * \param poStep After the execution, holds the data for the current step. The variable is allocated by the function
+ * \return 1 if the time step was successfully read, 0 otherwise
+ */
+int read_step(VSILFILE *fp,const Header *poHeader,TimeStep *&poStep);
+
+/**
+ * \brief Write one time step to a Selafin file
+ *
+ * This function writes a single time step, with all the field values, to an open Selafin file at the current position.
+ * \param fp Pointer to an open file with write access
+ * \param poHeader Pointer to the header structure. This should be read before the call to the function because some of its members are used to determine the format of the time step.
+ * \param poStep Data of current step
+ * \return 1 if the time step was successfully written, 0 otherwise
+ */
+int write_step(VSILFILE *fp,const Header *poHeader,const TimeStep *poStep);
+
+/**
+ * \brief Read all time steps from a Selafin file
+ *
+ * This function reads all time steps, with all the field values, from an open Selafin file at the current position.
+ * \param fp Pointer to an open file
+ * \param poHeader Pointer to the header structure. This should be read before the call to the function because some of its members are used to determine the format of the time step.
+ * \param poSteps After the execution, holds the list of time steps. The variable is allocated by the function
+ * \return 1 if the time steps were successfully read, 0 otherwise
+ */
+int read_steps(VSILFILE *fp,const Header *poHeader,TimeStepList *&poSteps);
+
+/**
+ * \brief Write one time step to a Selafin file
+ *
+ * This function writes a single time step, with all the field values, to an open Selafin file at the current position.
+ * \param fp Pointer to an open file with write access
+ * \param poHeader Pointer to the header structure. This should be read before the call to the function because some of its members are used to determine the format of the time step.
+ * \param poSteps List of all steps
+ * \return 1 if the time steps were successfully written, 0 otherwise
+ */
+int write_steps(VSILFILE *fp,const Header *poHeader,const TimeStepList *poSteps);
 #endif
 
-}
+}  // namespace Selafin
 
 #endif   /* ----- #ifndef IO_SELAFIN_H_INC  ----- */
diff --git a/ogr/ogrsf_frmts/selafin/ogr_selafin.h b/ogr/ogrsf_frmts/selafin/ogr_selafin.h
index 6468ffe..6499f65 100644
--- a/ogr/ogrsf_frmts/selafin/ogr_selafin.h
+++ b/ogr/ogrsf_frmts/selafin/ogr_selafin.h
@@ -44,7 +44,7 @@ class Range {
             SelafinTypeDef eType;
             int nMin,nMax;
             List *poNext;
-            List():poNext(NULL) {}
+            List():eType(POINTS),nMin(0),nMax(0),poNext(NULL) {}
             List(SelafinTypeDef eTypeP,int nMinP,int nMaxP,List *poNextP):eType(eTypeP),nMin(nMinP),nMax(nMaxP),poNext(poNextP) {}
         } List;
         List *poVals,*poActual;
@@ -60,7 +60,6 @@ class Range {
         size_t getSize() const;
 };
 
-
 /************************************************************************/
 /*                             OGRSelafinLayer                          */
 /************************************************************************/
@@ -68,34 +67,37 @@ class Range {
 class OGRSelafinLayer : public OGRLayer {
     private:
         SelafinTypeDef eType;
-        int bUpdate;
+        bool bUpdate;
         int nStepNumber;
         Selafin::Header *poHeader;
         OGRFeatureDefn *poFeatureDefn;
         OGRSpatialReference *poSpatialRef;
         GIntBig nCurrentId;
     public:
-        OGRSelafinLayer( const char *pszLayerNameP, int bUpdateP,OGRSpatialReference *poSpatialRefP,Selafin::Header *poHeaderP,int nStepNumberP,SelafinTypeDef eTypeP);
+        OGRSelafinLayer( const char *pszLayerNameP, int bUpdateP,
+                         OGRSpatialReference *poSpatialRefP,
+                         Selafin::Header *poHeaderP, int nStepNumberP,
+                         SelafinTypeDef eTypeP );
         ~OGRSelafinLayer();
-        OGRSpatialReference *GetSpatialRef() {return poSpatialRef;}
+        OGRSpatialReference *GetSpatialRef() override {return poSpatialRef;}
         int GetStepNumber() {return nStepNumber;}
-        OGRFeature *GetNextFeature();
-        OGRFeature *GetFeature(GIntBig nFID);
-        void ResetReading();
-        OGRErr SetNextByIndex(GIntBig nIndex);
-        OGRFeatureDefn *GetLayerDefn() {return poFeatureDefn;}
-        int TestCapability(const char *pszCap);
-        GIntBig GetFeatureCount(int bForce=TRUE);
-        OGRErr GetExtent(OGREnvelope *psExtent,int bForce=TRUE);
-        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+        OGRFeature *GetNextFeature() override;
+        OGRFeature *GetFeature(GIntBig nFID) override;
+        void ResetReading() override;
+        OGRErr SetNextByIndex(GIntBig nIndex) override;
+        OGRFeatureDefn *GetLayerDefn() override {return poFeatureDefn;}
+        int TestCapability(const char *pszCap) override;
+        GIntBig GetFeatureCount( int bForce = TRUE ) override;
+        OGRErr GetExtent( OGREnvelope *psExtent, int bForce = TRUE ) override;
+        virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-        OGRErr ISetFeature(OGRFeature *poFeature);
-        OGRErr ICreateFeature(OGRFeature *poFeature);
-        OGRErr CreateField(OGRFieldDefn *poField,int bApproxOK=TRUE);
-        OGRErr DeleteField(int iField);
-        OGRErr ReorderFields(int *panMap);
-        OGRErr AlterFieldDefn(int iField,OGRFieldDefn *poNewFieldDefn,int nFlags);
-        OGRErr DeleteFeature(GIntBig nFID);
+        OGRErr ISetFeature(OGRFeature *poFeature) override;
+        OGRErr ICreateFeature(OGRFeature *poFeature) override;
+        OGRErr CreateField( OGRFieldDefn *poField, int bApproxOK = TRUE ) override;
+        OGRErr DeleteField(int iField) override;
+        OGRErr ReorderFields(int *panMap) override;
+        OGRErr AlterFieldDefn(int iField,OGRFieldDefn *poNewFieldDefn,int nFlags) override;
+        OGRErr DeleteFeature(GIntBig nFID) override;
 };
 
 /************************************************************************/
@@ -109,7 +111,7 @@ class OGRSelafinDataSource : public OGRDataSource {
         OGRSelafinLayer **papoLayers;
         Range poRange;
         int nLayers;
-        int bUpdate;
+        bool bUpdate;
         Selafin::Header *poHeader;
         CPLString osDefaultSelafinName;
         OGRSpatialReference *poSpatialRef;
@@ -117,15 +119,15 @@ class OGRSelafinDataSource : public OGRDataSource {
         void ReleaseLock();
     public:
         OGRSelafinDataSource();
-        ~OGRSelafinDataSource();
+        virtual ~OGRSelafinDataSource();
         int Open(const char * pszFilename, int bUpdate, int bCreate);
         int OpenTable(const char * pszFilename);
-        const char *GetName() { return pszName; }
-        int GetLayerCount() { return nLayers; }
-        OGRLayer *GetLayer( int );
-        virtual OGRLayer *ICreateLayer( const char *pszName, OGRSpatialReference *poSpatialRefP = NULL, OGRwkbGeometryType eGType = wkbUnknown, char ** papszOptions = NULL );
-        virtual OGRErr DeleteLayer(int);
-        int TestCapability( const char * );
+        const char *GetName() override { return pszName; }
+        int GetLayerCount() override { return nLayers; }
+        OGRLayer *GetLayer( int ) override;
+        virtual OGRLayer *ICreateLayer( const char *pszName, OGRSpatialReference *poSpatialRefP = NULL, OGRwkbGeometryType eGType = wkbUnknown, char ** papszOptions = NULL ) override;
+        virtual OGRErr DeleteLayer(int) override;
+        int TestCapability( const char * ) override;
         void SetDefaultSelafinName( const char *pszNameIn ) { osDefaultSelafinName = pszNameIn; }
 };
 
diff --git a/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp b/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp
index 6fc1130..30714a4 100644
--- a/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp
+++ b/ogr/ogrsf_frmts/selafin/ogrselafindatasource.cpp
@@ -34,6 +34,8 @@
 
 #include <ctime>
 
+CPL_CVSID("$Id: ogrselafindatasource.cpp 35562 2016-09-30 19:16:16Z goatbar $");
+
 /************************************************************************/
 /*                          Range                                       */
 /************************************************************************/
@@ -62,8 +64,9 @@ void Range::setRange(const char *pszStr) {
         return;
     }
     const char *pszc=pszStr;
-    char *psze;
-    int nMin,nMax;
+    char *psze = NULL;
+    int nMin = 0;
+    int nMax = 0;
     SelafinTypeDef eType;
     while (*pszc!=0 && *pszc!=']') {
         pszc++;
@@ -101,7 +104,7 @@ void Range::setRange(const char *pszStr) {
                 pszc=psze;
             }
         } else nMax=nMin;
-        Range::List *poNew;
+        Range::List *poNew = NULL;
         if (eType!=ALL) poNew=new Range::List(eType,nMin,nMax,NULL); else poNew=new Range::List(POINTS,nMin,nMax,new Range::List(ELEMENTS,nMin,nMax,NULL));
         if (poVals==NULL) {
             poVals=poNew;
@@ -217,17 +220,19 @@ OGRSelafinDataSource::OGRSelafinDataSource() :
     pszLockName(NULL),
     papoLayers(NULL),
     nLayers(0),
-    bUpdate(FALSE),
+    bUpdate(false),
     poHeader(NULL),
     poSpatialRef(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                         ~OGRSelafinDataSource()                      */
 /************************************************************************/
 
 OGRSelafinDataSource::~OGRSelafinDataSource() {
-    //CPLDebug("Selafin","~OGRSelafinDataSource(%s)",pszName);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("Selafin", "~OGRSelafinDataSource(%s)", pszName);
+#endif
     for( int i = 0; i < nLayers; i++ ) delete papoLayers[i];
     CPLFree( papoLayers );
     CPLFree( pszName );
@@ -259,9 +264,11 @@ OGRLayer *OGRSelafinDataSource::GetLayer( int iLayer ) {
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
-int OGRSelafinDataSource::Open(const char * pszFilename, int bUpdateIn, int bCreate) {
-    // Check if a range is set and extract it and the filename
-    const char *pszc=pszFilename;
+int OGRSelafinDataSource::Open( const char * pszFilename, int bUpdateIn,
+                                int bCreate )
+{
+    // Check if a range is set and extract it and the filename.
+    const char *pszc = pszFilename;
     if (*pszFilename==0) return FALSE;
     while (*pszc) ++pszc;
     if (*(pszc-1)==']') {
@@ -272,7 +279,7 @@ int OGRSelafinDataSource::Open(const char * pszFilename, int bUpdateIn, int bCre
     }
     pszName = CPLStrdup( pszFilename );
     pszName[pszc-pszFilename]=0;
-    bUpdate = bUpdateIn;
+    bUpdate = CPL_TO_BOOL(bUpdateIn);
     if (bCreate && EQUAL(pszName, "/vsistdout/")) return TRUE;
     /* For writable /vsizip/, do nothing more */
     if (bCreate && STARTS_WITH(pszName, "/vsizip/")) return TRUE;
@@ -337,12 +344,11 @@ int OGRSelafinDataSource::TakeLock(CPL_UNUSED const char *pszFilename) {
     // For now, this procedure is deactivated and a warning message is issued when a datasource is opened in update mode.
     //CPLDebug("Selafin","TakeLock(%s)",pszFilename);
     if (pszLockName!=0) CPLFree(pszLockName);
-    VSILFILE *fpLock;
     size_t nLen=strlen(pszFilename)+4;
     pszLockName=(char*)CPLMalloc(sizeof(char)*nLen);
     CPLStrlcpy(pszLockName,pszFilename,nLen-3);
     CPLStrlcat(pszLockName,"~~~",nLen);
-    fpLock=VSIFOpenL(pszLockName,"rb+");
+    VSILFILE *fpLock = VSIFOpenL(pszLockName, "rb+");
     // This is not thread-safe but I'm not quite sure how to open a file in exclusive mode and in a portable way
     if (fpLock!=NULL) {
         VSIFCloseL(fpLock);
@@ -369,18 +375,32 @@ void OGRSelafinDataSource::ReleaseLock() {
 /*                              OpenTable()                             */
 /************************************************************************/
 int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
-    //CPLDebug("Selafin","OpenTable(%s,%i)",pszFilename,bUpdate);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("Selafin", "OpenTable(%s,%i)",
+             pszFilename, static_cast<int>(bUpdate));
+#endif
     // Open the file
-    VSILFILE * fp;
-    if( bUpdate ) {
-        // We have to implement this locking feature for write access because the same file may hold several layers, and some programs (like QGIS) open each layer in a single datasource,
-        // so the same file might be opened several times for write access
+    VSILFILE *fp = NULL;
+    if( bUpdate )
+    {
+        // We have to implement this locking feature for write access because
+        // the same file may hold several layers, and some programs (like QGIS)
+        // open each layer in a single datasource, so the same file might be
+        // opened several times for write access.
         if (TakeLock(pszFilename)==0) {
-            CPLError(CE_Failure,CPLE_OpenFailed,"Failed to open %s for write access, lock file found %s.",pszFilename,pszLockName);
+            CPLError(CE_Failure, CPLE_OpenFailed,
+                     "Failed to open %s for write access, "
+                     "lock file found %s.",
+                     pszFilename, pszLockName);
             return FALSE;
         }
         fp = VSIFOpenL( pszFilename, "rb+" );
-    } else fp = VSIFOpenL( pszFilename, "rb" );
+    }
+    else
+    {
+        fp = VSIFOpenL( pszFilename, "rb" );
+    }
+
     if( fp == NULL ) {
         CPLError( CE_Warning, CPLE_OpenFailed, "Failed to open %s, %s.", pszFilename, VSIStrerror( errno ) );
         return FALSE;
@@ -438,9 +458,8 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
     }
 
     // Create two layers for each selected time step: one for points, the other for elements
-    int nNewLayers;
     poRange.setMaxValue(poHeader->nSteps);
-    nNewLayers=static_cast<int>(poRange.getSize());
+    const int nNewLayers = static_cast<int>(poRange.getSize());
     if (EQUAL(pszFilename, "/vsistdin/")) osBaseLayerName = "layer";
     CPLString osLayerName;
     papoLayers = (OGRSelafinLayer **) CPLRealloc(papoLayers, sizeof(void*) * (nLayers+nNewLayers));
@@ -449,8 +468,10 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
         for (int i=0;i<poHeader->nSteps;++i) {
             if (poRange.contains(eType,i)) {
                 char szTemp[30];
-                double dfTime;
-                if (VSIFSeekL(fp,poHeader->getPosition(i)+4,SEEK_SET)!=0 || Selafin::read_float(fp,dfTime)==0) {
+                double dfTime = 0.0;
+                if( VSIFSeekL(fp, poHeader->getPosition(i)+4, SEEK_SET)!=0 ||
+                    Selafin::read_float(fp, dfTime)==0 )
+                {
                     VSIFCloseL(fp);
                     CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open %s, wrong format.\n", pszFilename);
                     return FALSE;
@@ -468,7 +489,9 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
                     strftime(szTemp,29,"%Y_%m_%d_%H_%M_%S",&sDate);
                 }
                 if (eType==POINTS) osLayerName=osBaseLayerName+"_p"+szTemp; else osLayerName=osBaseLayerName+"_e"+szTemp;
-                papoLayers[nLayers++] = new OGRSelafinLayer( osLayerName, bUpdate, poSpatialRef, poHeader,i,eType);
+                papoLayers[nLayers++] =
+                    new OGRSelafinLayer( osLayerName, bUpdate, poSpatialRef,
+                                         poHeader, i, eType);
                 //poHeader->nRefCount++;
             }
         }
@@ -485,19 +508,23 @@ int OGRSelafinDataSource::OpenTable(const char * pszFilename) {
 OGRLayer *OGRSelafinDataSource::ICreateLayer( const char *pszLayerName, OGRSpatialReference *poSpatialRefP, OGRwkbGeometryType eGType, char ** papszOptions  ) {
     CPLDebug("Selafin","CreateLayer(%s,%s)",pszLayerName,(eGType==wkbPoint)?"wkbPoint":"wkbPolygon");
     // Verify we are in update mode.
-    if (!bUpdate) {
-        CPLError( CE_Failure, CPLE_NoWriteAccess, "Data source %s opened read-only.\n" "New layer %s cannot be created.\n", pszName, pszLayerName );
+    if ( !bUpdate )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Data source %s opened read-only.  "
+                  "New layer %s cannot be created.",
+                  pszName, pszLayerName );
         return NULL;
     }
     // Check that new layer is a point or polygon layer
-    if (eGType!=wkbPoint) {
+    if( eGType != wkbPoint )
+    {
         CPLError( CE_Failure, CPLE_NoWriteAccess, "Selafin format can only handle %s layers whereas input is %s\n.", OGRGeometryTypeToName(wkbPoint),OGRGeometryTypeToName(eGType));
         return NULL;
     }
     // Parse options
-    double dfDate;
     const char *pszTemp=CSLFetchNameValue(papszOptions,"DATE");
-    if (pszTemp!=NULL) dfDate=CPLAtof(pszTemp); else dfDate=0.0;
+    const double dfDate = pszTemp != NULL ? CPLAtof(pszTemp) : 0.0;
     // Set the SRS of the datasource if this is the first layer
     if (nLayers==0 && poSpatialRefP!=NULL) {
         poSpatialRef=poSpatialRefP;
@@ -542,9 +569,13 @@ OGRLayer *OGRSelafinDataSource::ICreateLayer( const char *pszLayerName, OGRSpati
     papoLayers = (OGRSelafinLayer **) CPLRealloc(papoLayers, sizeof(void*) * nLayers);
     CPLString szName=pszLayerName;
     CPLString szNewLayerName=szName+"_p";
-    papoLayers[nLayers-2] = new OGRSelafinLayer( szNewLayerName, bUpdate, poSpatialRef, poHeader,poHeader->nSteps-1,POINTS);
+    papoLayers[nLayers-2] =
+        new OGRSelafinLayer( szNewLayerName, bUpdate, poSpatialRef, poHeader,
+                             poHeader->nSteps-1, POINTS );
     szNewLayerName=szName+"_e";
-    papoLayers[nLayers-1] = new OGRSelafinLayer( szNewLayerName, bUpdate, poSpatialRef, poHeader,poHeader->nSteps-1,ELEMENTS);
+    papoLayers[nLayers-1] =
+        new OGRSelafinLayer( szNewLayerName, bUpdate, poSpatialRef, poHeader,
+                             poHeader->nSteps-1, ELEMENTS );
     return papoLayers[nLayers-2];
 }
 
@@ -553,8 +584,11 @@ OGRLayer *OGRSelafinDataSource::ICreateLayer( const char *pszLayerName, OGRSpati
 /************************************************************************/
 OGRErr OGRSelafinDataSource::DeleteLayer( int iLayer ) {
     // Verify we are in update mode.
-    if( !bUpdate ) {
-        CPLError( CE_Failure, CPLE_NoWriteAccess, "Data source %s opened read-only.\n" "Layer %d cannot be deleted.\n", pszName, iLayer );
+    if( !bUpdate )
+    {
+        CPLError( CE_Failure, CPLE_NoWriteAccess,
+                  "Data source %s opened read-only.  "
+                  "Layer %d cannot be deleted.\n", pszName, iLayer );
         return OGRERR_FAILURE;
     }
     if( iLayer < 0 || iLayer >= nLayers ) {
@@ -562,19 +596,22 @@ OGRErr OGRSelafinDataSource::DeleteLayer( int iLayer ) {
         return OGRERR_FAILURE;
     }
     // Delete layer in file. Here we don't need to create a copy of the file because we only update values and it can't get corrupted even if the system crashes during the operation
-    int nNum=papoLayers[iLayer]->GetStepNumber();
-    double dfTime;
+    const int nNum = papoLayers[iLayer]->GetStepNumber();
     double *dfValues=NULL;
-    int nTemp;
-    for (int i=nNum;i<poHeader->nSteps-1;++i) {
+    for( int i = nNum; i < poHeader->nSteps - 1; ++i )
+    {
+        double dfTime = 0.0;
         if (VSIFSeekL(poHeader->fp,poHeader->getPosition(i+1)+4,SEEK_SET)!=0 ||
-            Selafin::read_float(poHeader->fp,dfTime)==0 ||
+            Selafin::read_float(poHeader->fp, dfTime) == 0 ||
             VSIFSeekL(poHeader->fp,poHeader->getPosition(i)+4,SEEK_SET)!=0 ||
-            Selafin::write_float(poHeader->fp,dfTime)==0) {
+            Selafin::write_float(poHeader->fp, dfTime) == 0)
+        {
             CPLError( CE_Failure, CPLE_FileIO, "Could not update Selafin file %s.\n",pszName);
             return OGRERR_FAILURE;
         }
-        for (int j=0;j<poHeader->nVar;++j) {
+        for (int j=0;j<poHeader->nVar;++j)
+        {
+            int nTemp = 0;
             if (VSIFSeekL(poHeader->fp,poHeader->getPosition(i+1)+12,SEEK_SET)!=0 ||
                 (nTemp=Selafin::read_floatarray(poHeader->fp,&dfValues)) !=poHeader->nPoints ||
                 VSIFSeekL(poHeader->fp,poHeader->getPosition(i)+12,SEEK_SET)!=0 ||
diff --git a/ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp b/ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp
index 2ee2e29..9444b8b 100644
--- a/ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp
+++ b/ogr/ogrsf_frmts/selafin/ogrselafindriver.cpp
@@ -30,12 +30,14 @@
 #include "cpl_string.h"
 #include "io_selafin.h"
 
+CPL_CVSID("$Id: ogrselafindriver.cpp 35562 2016-09-30 19:16:16Z goatbar $");
+
 /************************************************************************/
 /*                     OGRSelafinDriverIdentify()                       */
 /************************************************************************/
 
-static int OGRSelafinDriverIdentify( GDALOpenInfo* poOpenInfo ) {
-
+static int OGRSelafinDriverIdentify( GDALOpenInfo* poOpenInfo )
+{
     if( poOpenInfo->fpL != NULL )
     {
         if( poOpenInfo->nHeaderBytes < 84 + 8 )
@@ -65,7 +67,9 @@ static GDALDataset *OGRSelafinDriverOpen( GDALOpenInfo* poOpenInfo ) {
         return NULL;
 
     OGRSelafinDataSource *poDS = new OGRSelafinDataSource();
-    if( !poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update, FALSE) ) {
+    if( !poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update,
+                    FALSE) )
+    {
         delete poDS;
         poDS = NULL;
     }
@@ -147,7 +151,8 @@ static GDALDataset *OGRSelafinDriverCreate( const char * pszName,
     }
     // Force it to open as a datasource
     OGRSelafinDataSource *poDS = new OGRSelafinDataSource();
-    if( !poDS->Open( pszName, TRUE, TRUE ) ) {
+    if( !poDS->Open( pszName, TRUE, TRUE ) )
+    {
         delete poDS;
         return NULL;
     }
diff --git a/ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp b/ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp
index a5a5dc8..85c4ea7 100644
--- a/ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp
+++ b/ogr/ogrsf_frmts/selafin/ogrselafinlayer.cpp
@@ -34,6 +34,8 @@
 #include "cpl_error.h"
 #include "cpl_quad_tree.h"
 
+CPL_CVSID("$Id: ogrselafinlayer.cpp 35933 2016-10-25 16:46:26Z goatbar $");
+
 /************************************************************************/
 /*                           Utilities functions                        */
 /************************************************************************/
@@ -56,28 +58,42 @@ static void MoveOverwrite(VSILFILE *fpDest,VSILFILE *fpSource) {
 /*       Note that no operation on OGRSelafinLayer is thread-safe       */
 /************************************************************************/
 
-OGRSelafinLayer::OGRSelafinLayer( const char *pszLayerNameP, int bUpdateP,OGRSpatialReference *poSpatialRefP,Selafin::Header *poHeaderP,int nStepNumberP,SelafinTypeDef eTypeP):eType(eTypeP),bUpdate(bUpdateP),nStepNumber(nStepNumberP),poHeader(poHeaderP),poSpatialRef(poSpatialRefP),nCurrentId(-1) {
-    //CPLDebug("Selafin","Opening layer %s",pszLayerNameP);
-    poFeatureDefn = new OGRFeatureDefn( CPLGetBasename( pszLayerNameP ) );
+OGRSelafinLayer::OGRSelafinLayer(
+    const char *pszLayerNameP, int bUpdateP, OGRSpatialReference *poSpatialRefP,
+    Selafin::Header *poHeaderP, int nStepNumberP, SelafinTypeDef eTypeP ) :
+    eType(eTypeP),
+    bUpdate(CPL_TO_BOOL(bUpdateP)),
+    nStepNumber(nStepNumberP),
+    poHeader(poHeaderP),
+    poFeatureDefn(new OGRFeatureDefn(CPLGetBasename(pszLayerNameP))),
+    poSpatialRef(poSpatialRefP),
+    nCurrentId(-1)
+{
+#ifdef DEBUG_VERBOSE
+    CPLDebug("Selafin", "Opening layer %s", pszLayerNameP);
+#endif
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
-    if (eType==POINTS) poFeatureDefn->SetGeomType( wkbPoint );
+    if( eType == POINTS ) poFeatureDefn->SetGeomType( wkbPoint );
     else poFeatureDefn->SetGeomType(wkbPolygon);
-    for (int i=0;i<poHeader->nVar;++i) {
+    for( int i = 0; i < poHeader->nVar; ++i )
+    {
         OGRFieldDefn oFieldDefn(poHeader->papszVariables[i],OFTReal);
         poFeatureDefn->AddFieldDefn(&oFieldDefn);
     }
 }
 
-
 /************************************************************************/
 /*                           ~OGRSelafinLayer()                         */
 /************************************************************************/
-OGRSelafinLayer::~OGRSelafinLayer() {
-    //CPLDebug("Selafin","Closing layer %s",GetName());
+OGRSelafinLayer::~OGRSelafinLayer()
+{
+#ifdef DEBUG_VERBOSE
+    CPLDebug("Selafin", "Closing layer %s", GetName());
+#endif
     poFeatureDefn->Release();
-    //poHeader->nRefCount--;
-    //if (poHeader->nRefCount==0) delete poHeader;
+    // poHeader->nRefCount--;
+    // if (poHeader->nRefCount==0) delete poHeader;
 }
 
 /************************************************************************/
@@ -117,18 +133,18 @@ OGRErr OGRSelafinLayer::SetNextByIndex(GIntBig nIndex) {
 int OGRSelafinLayer::TestCapability(const char *pszCap) {
     //CPLDebug("Selafin","TestCapability(%s)",pszCap);
     if (EQUAL(pszCap,OLCRandomRead)) return TRUE;
-    if (EQUAL(pszCap,OLCSequentialWrite)) return (bUpdate);
-    if (EQUAL(pszCap,OLCRandomWrite)) return (bUpdate);
+    if (EQUAL(pszCap,OLCSequentialWrite)) return bUpdate;
+    if (EQUAL(pszCap,OLCRandomWrite)) return bUpdate;
     if (EQUAL(pszCap,OLCFastSpatialFilter)) return FALSE;
     if (EQUAL(pszCap,OLCFastFeatureCount)) return TRUE;
     if (EQUAL(pszCap,OLCFastGetExtent)) return TRUE;
     if (EQUAL(pszCap,OLCFastSetNextByIndex)) return TRUE;
-    if (EQUAL(pszCap,OLCCreateField)) return (bUpdate);
+    if (EQUAL(pszCap,OLCCreateField)) return bUpdate;
     if (EQUAL(pszCap,OLCCreateGeomField)) return FALSE;
-    if (EQUAL(pszCap,OLCDeleteField)) return (bUpdate);
-    if (EQUAL(pszCap,OLCReorderFields)) return (bUpdate);
-    if (EQUAL(pszCap,OLCAlterFieldDefn)) return (bUpdate);
-    if (EQUAL(pszCap,OLCDeleteFeature)) return (bUpdate);
+    if (EQUAL(pszCap,OLCDeleteField)) return bUpdate;
+    if (EQUAL(pszCap,OLCReorderFields)) return bUpdate;
+    if (EQUAL(pszCap,OLCAlterFieldDefn)) return bUpdate;
+    if (EQUAL(pszCap,OLCDeleteFeature)) return bUpdate;
     if (EQUAL(pszCap,OLCStringsAsUTF8)) return FALSE;
     if (EQUAL(pszCap,OLCTransactions)) return FALSE;
     if (EQUAL(pszCap,OLCIgnoreFields)) return FALSE;
@@ -143,22 +159,22 @@ OGRFeature* OGRSelafinLayer::GetFeature(GIntBig nFID) {
     if (nFID<0) return NULL;
     if (eType==POINTS) {
         if (nFID>=poHeader->nPoints) return NULL;
-        double nData;
         OGRFeature *poFeature=new OGRFeature(poFeatureDefn);
         poFeature->SetGeometryDirectly(new OGRPoint(poHeader->paadfCoords[0][nFID],poHeader->paadfCoords[1][nFID]));
         poFeature->SetFID(nFID);
         for (int i=0;i<poHeader->nVar;++i) {
             VSIFSeekL(poHeader->fp,poHeader->getPosition(nStepNumber,(int)nFID,i),SEEK_SET);
-            if (Selafin::read_float(poHeader->fp,nData)==1) poFeature->SetField(i,nData);
+            double nData = 0.0;
+            if( Selafin::read_float(poHeader->fp,nData) == 1 )
+                poFeature->SetField(i,nData);
         }
         return poFeature;
     } else {
         if (nFID>=poHeader->nElements) return NULL;
-        double *anData;
-        anData=(double*)VSI_MALLOC2_VERBOSE(sizeof(double),poHeader->nVar);
+        double *anData = (double*)
+            VSI_MALLOC2_VERBOSE(sizeof(double),poHeader->nVar);
         if (poHeader->nVar>0 && anData==NULL) return NULL;
         for (int i=0;i<poHeader->nVar;++i) anData[i]=0;
-        double nData;
         OGRFeature *poFeature=new OGRFeature(poFeatureDefn);
         poFeature->SetFID(nFID);
         OGRPolygon *poPolygon=new OGRPolygon();
@@ -168,6 +184,7 @@ OGRFeature* OGRSelafinLayer::GetFeature(GIntBig nFID) {
             poLinearRing->addPoint(poHeader->paadfCoords[0][nPointNum],poHeader->paadfCoords[1][nPointNum]);
             for (int i=0;i<poHeader->nVar;++i) {
                 VSIFSeekL(poHeader->fp,poHeader->getPosition(nStepNumber,nPointNum,i),SEEK_SET);
+                double nData = 0.0;
                 if (Selafin::read_float(poHeader->fp,nData)==1) anData[i]+=nData;
             }
         }
@@ -180,17 +197,16 @@ OGRFeature* OGRSelafinLayer::GetFeature(GIntBig nFID) {
     }
 }
 
-
 /************************************************************************/
 /*                           GetFeatureCount()                          */
 /************************************************************************/
 GIntBig OGRSelafinLayer::GetFeatureCount(int bForce) {
     //CPLDebug("Selafin","GetFeatureCount(%i)",bForce);
     if (m_poFilterGeom==NULL && m_poAttrQuery==NULL) return (eType==POINTS)?poHeader->nPoints:poHeader->nElements;
-    if (bForce==FALSE) return -1;
-    int i=0;
-    int nFeatureCount=0;
-    int nMax=(eType==POINTS)?poHeader->nPoints:poHeader->nElements;
+    if( !bForce ) return -1;
+    int i = 0;
+    int nFeatureCount = 0;
+    const int nMax = eType == POINTS ? poHeader->nPoints : poHeader->nElements;
     while (i<nMax) {
         OGRFeature *poFeature=GetFeature(i++);
         if( (m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) ) ++nFeatureCount;
@@ -327,8 +343,8 @@ OGRErr OGRSelafinLayer::ICreateFeature(OGRFeature *poFeature) {
         }
 
         // Now we look for vertices that are already referenced as points in the file
-        int *anMap;
-        anMap=(int*)VSI_MALLOC2_VERBOSE(sizeof(int),poHeader->nPointsPerElement);
+        int *anMap = (int*)
+            VSI_MALLOC2_VERBOSE(sizeof(int), poHeader->nPointsPerElement);
         if (anMap==NULL) {
             return OGRERR_FAILURE;
         }
@@ -355,13 +371,11 @@ OGRErr OGRSelafinLayer::ICreateFeature(OGRFeature *poFeature) {
         }
         poHeader->setUpdated();
         CPLFree(anMap);
-
     }
 
     // Now comes the real insertion. Since values have to be inserted nearly everywhere in the file and we don't want to store everything in memory to overwrite it, we create a new copy of it where we write the new values
-    VSILFILE *fpNew;
     const char *pszTempfile=CPLGenerateTempFilename(NULL);
-    fpNew=VSIFOpenL(pszTempfile,"wb+");
+    VSILFILE *fpNew = VSIFOpenL(pszTempfile, "wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
@@ -371,10 +385,10 @@ OGRErr OGRSelafinLayer::ICreateFeature(OGRFeature *poFeature) {
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    int nLen;
-    double dfDate;
-    double *padfValues;
-    for (int i=0;i<poHeader->nSteps;++i) {
+    for (int i=0;i<poHeader->nSteps;++i)
+    {
+        int nLen = 0;
+        double dfDate = 0.0;
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -385,13 +399,16 @@ OGRErr OGRSelafinLayer::ICreateFeature(OGRFeature *poFeature) {
             VSIUnlink(pszTempfile);
             return OGRERR_FAILURE;
         }
-        for (int j=0;j<poHeader->nVar;++j) {
+        for( int j = 0; j < poHeader->nVar; ++j )
+        {
+            double *padfValues = NULL;
             if (Selafin::read_floatarray(poHeader->fp,&padfValues)==-1) {
                 VSIFCloseL(fpNew);
                 VSIUnlink(pszTempfile);
                 return OGRERR_FAILURE;
             }
-            padfValues=(double*)CPLRealloc(padfValues,sizeof(double)*poHeader->nPoints);
+            padfValues = (double*)
+                CPLRealloc(padfValues, sizeof(double)*poHeader->nPoints);
             if (padfValues==NULL) {
                 VSIFCloseL(fpNew);
                 VSIUnlink(pszTempfile);
@@ -445,9 +462,8 @@ OGRErr OGRSelafinLayer::CreateField(OGRFieldDefn *poField,
     poFeatureDefn->AddFieldDefn(poField);
 
     // Now comes the real insertion. Since values have to be inserted nearly everywhere in the file and we don't want to store everything in memory to overwrite it, we create a new copy of it where we write the new values
-    VSILFILE *fpNew;
     const char *pszTempfile=CPLGenerateTempFilename(NULL);
-    fpNew=VSIFOpenL(pszTempfile,"wb+");
+    VSILFILE *fpNew = VSIFOpenL(pszTempfile, "wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
@@ -457,10 +473,9 @@ OGRErr OGRSelafinLayer::CreateField(OGRFieldDefn *poField,
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    int nLen;
-    double dfDate;
-    double *padfValues;
     for (int i=0;i<poHeader->nSteps;++i) {
+        int nLen = 0;
+        double dfDate = 0.0;
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -471,6 +486,7 @@ OGRErr OGRSelafinLayer::CreateField(OGRFieldDefn *poField,
             VSIUnlink(pszTempfile);
             return OGRERR_FAILURE;
         }
+        double *padfValues = NULL;
         for (int j=0;j<poHeader->nVar-1;++j) {
             if (Selafin::read_floatarray(poHeader->fp,&padfValues)==-1) {
                 VSIFCloseL(fpNew);
@@ -515,9 +531,8 @@ OGRErr OGRSelafinLayer::DeleteField(int iField) {
     poFeatureDefn->DeleteFieldDefn(iField);
 
     // Now comes the real deletion. Since values have to be deleted nearly everywhere in the file and we don't want to store everything in memory to overwrite it, we create a new copy of it where we write the new values
-    VSILFILE *fpNew;
     const char *pszTempfile=CPLGenerateTempFilename(NULL);
-    fpNew=VSIFOpenL(pszTempfile,"wb+");
+    VSILFILE *fpNew = VSIFOpenL(pszTempfile, "wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
@@ -527,10 +542,9 @@ OGRErr OGRSelafinLayer::DeleteField(int iField) {
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    int nLen;
-    double dfDate;
-    double *padfValues;
     for (int i=0;i<poHeader->nSteps;++i) {
+        int nLen = 0;
+        double dfDate = 0.0;
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -542,6 +556,7 @@ OGRErr OGRSelafinLayer::DeleteField(int iField) {
             return OGRERR_FAILURE;
         }
         for (int j=0;j<poHeader->nVar;++j) {
+            double *padfValues = NULL;
             if (Selafin::read_floatarray(poHeader->fp,&padfValues)==-1) {
                 VSIFCloseL(fpNew);
                 VSIUnlink(pszTempfile);
@@ -577,9 +592,8 @@ OGRErr OGRSelafinLayer::ReorderFields(int *panMap) {
     poFeatureDefn->ReorderFieldDefns(panMap);
 
     // Now comes the real change.
-    VSILFILE *fpNew;
     const char *pszTempfile=CPLGenerateTempFilename(NULL);
-    fpNew=VSIFOpenL(pszTempfile,"wb+");
+    VSILFILE *fpNew = VSIFOpenL(pszTempfile, "wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
@@ -589,10 +603,10 @@ OGRErr OGRSelafinLayer::ReorderFields(int *panMap) {
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    int nLen;
-    double dfDate;
     double *padfValues=NULL;
     for (int i=0;i<poHeader->nSteps;++i) {
+        int nLen = 0;
+        double dfDate = 0.0;
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -665,9 +679,8 @@ OGRErr OGRSelafinLayer::DeleteFeature(GIntBig nFID) {
     }
 
     // Now we perform the deletion by creating a new temporary layer
-    VSILFILE *fpNew;
     const char *pszTempfile=CPLGenerateTempFilename(NULL);
-    fpNew=VSIFOpenL(pszTempfile,"wb+");
+    VSILFILE *fpNew = VSIFOpenL(pszTempfile, "wb+");
     if( fpNew == NULL ) {
         CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open temporary file %s with write access, %s.",pszTempfile, VSIStrerror( errno ) );
         return OGRERR_FAILURE;
@@ -677,10 +690,9 @@ OGRErr OGRSelafinLayer::DeleteFeature(GIntBig nFID) {
         VSIUnlink(pszTempfile);
         return OGRERR_FAILURE;
     }
-    int nLen;
-    double dfDate;
-    double *padfValues;
     for (int i=0;i<poHeader->nSteps;++i) {
+        int nLen = 0;
+        double dfDate = 0.0;
         if (Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
                 Selafin::read_float(poHeader->fp,dfDate)==0 ||
                 Selafin::read_integer(poHeader->fp,nLen,true)==0 ||
@@ -692,6 +704,7 @@ OGRErr OGRSelafinLayer::DeleteFeature(GIntBig nFID) {
             return OGRERR_FAILURE;
         }
         for (int j=0;j<poHeader->nVar;++j) {
+            double *padfValues = NULL;
             if (Selafin::read_floatarray(poHeader->fp,&padfValues)==-1) {
                 VSIFCloseL(fpNew);
                 VSIUnlink(pszTempfile);
diff --git a/ogr/ogrsf_frmts/shape/LICENSE.LGPL b/ogr/ogrsf_frmts/shape/COPYING
similarity index 100%
rename from ogr/ogrsf_frmts/shape/LICENSE.LGPL
rename to ogr/ogrsf_frmts/shape/COPYING
diff --git a/ogr/ogrsf_frmts/shape/dbfopen.c b/ogr/ogrsf_frmts/shape/dbfopen.c
index 9f8edd0..68d1172 100644
--- a/ogr/ogrsf_frmts/shape/dbfopen.c
+++ b/ogr/ogrsf_frmts/shape/dbfopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: dbfopen.c,v 1.89 2011-07-24 05:59:25 fwarmerdam Exp $
+ * $Id: dbfopen.c 37046 2016-12-31 09:59:57Z rouault $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of .dbf access API documented in dbf_api.html.
@@ -10,7 +10,7 @@
  * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * or at the option of the licensee under the LGPL (see COPYING).  This
  * option is discussed in more detail in shapelib.html.
  *
  * --
@@ -35,6 +35,33 @@
  ******************************************************************************
  *
  * $Log: dbfopen.c,v $
+ * Revision 1.92  2016-12-05 18:44:08  erouault
+ * * dbfopen.c, shapefil.h: write DBF end-of-file character 0x1A by default.
+ * This behaviour can be controlled with the DBFSetWriteEndOfFileChar()
+ * function.
+ *
+ * Revision 1.91  2016-12-05 12:44:05  erouault
+ * * Major overhaul of Makefile build system to use autoconf/automake.
+ *
+ * * Warning fixes in contrib/
+ *
+ * Revision 1.90  2016-12-04 15:30:15  erouault
+ * * shpopen.c, dbfopen.c, shptree.c, shapefil.h: resync with
+ * GDAL Shapefile driver. Mostly cleanups. SHPObject and DBFInfo
+ * structures extended with new members. New functions:
+ * DBFSetLastModifiedDate, SHPOpenLLEx, SHPRestoreSHX,
+ * SHPSetFastModeReadObject
+ *
+ * * sbnsearch.c: new file to implement original ESRI .sbn spatial
+ * index reading. (no write support). New functions:
+ * SBNOpenDiskTree, SBNCloseDiskTree, SBNSearchDiskTree,
+ * SBNSearchDiskTreeInteger, SBNSearchFreeIds
+ *
+ * * Makefile, makefile.vc, CMakeLists.txt, shapelib.def: updates
+ * with new file and symbols.
+ *
+ * * commit: helper script to cvs commit
+ *
  * Revision 1.89  2011-07-24 05:59:25  fwarmerdam
  * minimize use of CPLError in favor of SAHooks.Error()
  *
@@ -167,17 +194,41 @@
 #ifdef USE_CPL
 #include "cpl_string.h"
 #else
+
+#if defined(_MSC_VER)
+# if _MSC_VER < 1900
+#     define snprintf _snprintf
+# endif
+#elif defined(WIN32) || defined(_WIN32)
+#  ifndef snprintf
+#     define snprintf _snprintf
+#  endif
+#endif
+
 #define CPLsprintf sprintf
+#define CPLsnprintf snprintf
 #endif
 
-SHP_CVSID("$Id: dbfopen.c,v 1.89 2011-07-24 05:59:25 fwarmerdam Exp $")
+SHP_CVSID("$Id: dbfopen.c 37046 2016-12-31 09:59:57Z rouault $")
 
 #ifndef FALSE
 #  define FALSE		0
 #  define TRUE		1
 #endif
 
+/* File header size */
+#define XBASE_FILEHDR_SZ         32
+
+#define HEADER_RECORD_TERMINATOR 0x0D
+
+/* See http://www.manmrk.net/tutorials/database/xbase/dbf.html */
+#define END_OF_FILE_CHARACTER    0x1A
+
+#ifdef USE_CPL
 CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
+#else
+#define CPL_IGNORE_RET_VAL_INT(x) x
+#endif
 
 /************************************************************************/
 /*                             SfRealloc()                              */
@@ -207,8 +258,7 @@ static void * SfRealloc( void * pMem, int nNewSize )
 static void DBFWriteHeader(DBFHandle psDBF)
 
 {
-    unsigned char	abyHeader[XBASE_FLDHDR_SZ];
-    int		i;
+    unsigned char	abyHeader[XBASE_FILEHDR_SZ] = { 0 };
 
     if( !psDBF->bNoHeader )
         return;
@@ -218,9 +268,6 @@ static void DBFWriteHeader(DBFHandle psDBF)
 /* -------------------------------------------------------------------- */
 /*	Initialize the file header information.				*/
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
-        abyHeader[i] = 0;
-
     abyHeader[0] = 0x03;		/* memo field? - just copying 	*/
 
     /* write out update date */
@@ -243,20 +290,31 @@ static void DBFWriteHeader(DBFHandle psDBF)
 /*      descriptions.                                     		*/
 /* -------------------------------------------------------------------- */
     psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
-    psDBF->sHooks.FWrite( abyHeader, XBASE_FLDHDR_SZ, 1, psDBF->fp );
+    psDBF->sHooks.FWrite( abyHeader, XBASE_FILEHDR_SZ, 1, psDBF->fp );
     psDBF->sHooks.FWrite( psDBF->pszHeader, XBASE_FLDHDR_SZ, psDBF->nFields,
                           psDBF->fp );
 
 /* -------------------------------------------------------------------- */
 /*      Write out the newline character if there is room for it.        */
 /* -------------------------------------------------------------------- */
-    if( psDBF->nHeaderLength > 32*psDBF->nFields + 32 )
+    if( psDBF->nHeaderLength > XBASE_FLDHDR_SZ*psDBF->nFields +
+                               XBASE_FLDHDR_SZ )
     {
         char	cNewline;
 
-        cNewline = 0x0d;
+        cNewline = HEADER_RECORD_TERMINATOR;
         psDBF->sHooks.FWrite( &cNewline, 1, 1, psDBF->fp );
     }
+
+/* -------------------------------------------------------------------- */
+/*      If the file is new, add a EOF character.                        */
+/* -------------------------------------------------------------------- */
+    if( psDBF->nRecords == 0 && psDBF->bWriteEndOfFileChar )
+    {
+        char ch = END_OF_FILE_CHARACTER;
+
+        psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+    }
 }
 
 /************************************************************************/
@@ -289,6 +347,15 @@ static int DBFFlushRecord( DBFHandle psDBF )
             psDBF->sHooks.Error( szMessage );
             return FALSE;
         }
+
+        if( psDBF->nCurrentRecord == psDBF->nRecords - 1 )
+        {
+            if( psDBF->bWriteEndOfFileChar )
+            {
+                char ch = END_OF_FILE_CHARACTER;
+                psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+            }
+        }
     }
 
     return TRUE;
@@ -314,7 +381,7 @@ static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
 	if( psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, SEEK_SET ) != 0 )
         {
             char szMessage[128];
-            snprintf( szMessage, sizeof(szMessage), "fseek(%ld) failed on DBF file.\n",
+            snprintf( szMessage, sizeof(szMessage), "fseek(%ld) failed on DBF file.",
                      (long) nRecordOffset );
             psDBF->sHooks.Error( szMessage );
             return FALSE;
@@ -324,7 +391,7 @@ static int DBFLoadRecord( DBFHandle psDBF, int iRecord )
                                  psDBF->nRecordLength, 1, psDBF->fp ) != 1 )
         {
             char szMessage[128];
-            snprintf( szMessage, sizeof(szMessage), "fread(%d) failed on DBF file.\n",
+            snprintf( szMessage, sizeof(szMessage), "fread(%d) failed on DBF file.",
                      psDBF->nRecordLength );
             psDBF->sHooks.Error( szMessage );
             return FALSE;
@@ -344,7 +411,7 @@ void SHPAPI_CALL
 DBFUpdateHeader( DBFHandle psDBF )
 
 {
-    unsigned char		abyFileHeader[32];
+    unsigned char		abyFileHeader[XBASE_FILEHDR_SZ];
 
     if( psDBF->bNoHeader )
         DBFWriteHeader( psDBF );
@@ -353,18 +420,18 @@ DBFUpdateHeader( DBFHandle psDBF )
         return;
 
     psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
-    psDBF->sHooks.FRead( abyFileHeader, 32, 1, psDBF->fp );
+    psDBF->sHooks.FRead( abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp );
 
     abyFileHeader[1] = (unsigned char) psDBF->nUpdateYearSince1900;
     abyFileHeader[2] = (unsigned char) psDBF->nUpdateMonth;
     abyFileHeader[3] = (unsigned char) psDBF->nUpdateDay;
-    abyFileHeader[4] = (unsigned char) (psDBF->nRecords % 256);
-    abyFileHeader[5] = (unsigned char) ((psDBF->nRecords/256) % 256);
-    abyFileHeader[6] = (unsigned char) ((psDBF->nRecords/(256*256)) % 256);
-    abyFileHeader[7] = (unsigned char) ((psDBF->nRecords/(256*256*256)) % 256);
+    abyFileHeader[4] = (unsigned char) (psDBF->nRecords & 0xFF);
+    abyFileHeader[5] = (unsigned char) ((psDBF->nRecords>>8) & 0xFF);
+    abyFileHeader[6] = (unsigned char) ((psDBF->nRecords>>16) & 0xFF);
+    abyFileHeader[7] = (unsigned char) ((psDBF->nRecords>>24) & 0xFF);
 
     psDBF->sHooks.FSeek( psDBF->fp, 0, 0 );
-    psDBF->sHooks.FWrite( abyFileHeader, 32, 1, psDBF->fp );
+    psDBF->sHooks.FWrite( abyFileHeader, sizeof(abyFileHeader), 1, psDBF->fp );
 
     psDBF->sHooks.FFlush( psDBF->fp );
 }
@@ -484,7 +551,7 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 /*  Read Table Header info                                              */
 /* -------------------------------------------------------------------- */
     pabyBuf = (unsigned char *) malloc(nBufSize);
-    if( psDBF->sHooks.FRead( pabyBuf, 32, 1, psDBF->fp ) != 1 )
+    if( psDBF->sHooks.FRead( pabyBuf, XBASE_FILEHDR_SZ, 1, psDBF->fp ) != 1 )
     {
         psDBF->sHooks.FClose( psDBF->fp );
         if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
@@ -496,13 +563,13 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     DBFSetLastModifiedDate(psDBF, pabyBuf[1], pabyBuf[2], pabyBuf[3]);
 
     psDBF->nRecords =
-     pabyBuf[4] + pabyBuf[5]*256 + pabyBuf[6]*256*256 + (pabyBuf[7] & 0x7f) *256*256*256;
+     pabyBuf[4]|(pabyBuf[5]<<8)|(pabyBuf[6]<<16)|((pabyBuf[7]&0x7f)<<24);
 
-    psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
-    psDBF->nRecordLength = pabyBuf[10] + pabyBuf[11]*256;
+    psDBF->nHeaderLength = nHeadLen = pabyBuf[8]|(pabyBuf[9]<<8);
+    psDBF->nRecordLength = pabyBuf[10]|(pabyBuf[11]<<8);
     psDBF->iLanguageDriver = pabyBuf[29];
 
-    if (psDBF->nRecordLength == 0 || nHeadLen < 32)
+    if (psDBF->nRecordLength == 0 || nHeadLen < XBASE_FILEHDR_SZ)
     {
         psDBF->sHooks.FClose( psDBF->fp );
         if( pfCPG ) psDBF->sHooks.FClose( pfCPG );
@@ -511,8 +578,9 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
         return NULL;
     }
 
-    psDBF->nFields = nFields = (nHeadLen - 32) / 32;
+    psDBF->nFields = nFields = (nHeadLen - XBASE_FILEHDR_SZ) / XBASE_FLDHDR_SZ;
 
+    /* coverity[tainted_data] */
     psDBF->pszCurrentRecord = (char *) malloc(psDBF->nRecordLength);
 
 /* -------------------------------------------------------------------- */
@@ -548,8 +616,9 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     pabyBuf = (unsigned char *) SfRealloc(pabyBuf,nHeadLen);
     psDBF->pszHeader = (char *) pabyBuf;
 
-    psDBF->sHooks.FSeek( psDBF->fp, 32, 0 );
-    if( psDBF->sHooks.FRead( pabyBuf, nHeadLen-32, 1, psDBF->fp ) != 1 )
+    psDBF->sHooks.FSeek( psDBF->fp, XBASE_FILEHDR_SZ, 0 );
+    if( psDBF->sHooks.FRead( pabyBuf, nHeadLen-XBASE_FILEHDR_SZ, 1,
+                             psDBF->fp ) != 1 )
     {
         psDBF->sHooks.FClose( psDBF->fp );
         free( pabyBuf );
@@ -567,7 +636,12 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
     {
 	unsigned char		*pabyFInfo;
 
-	pabyFInfo = pabyBuf+iField*32;
+	pabyFInfo = pabyBuf+iField*XBASE_FLDHDR_SZ;
+        if( pabyFInfo[0] == HEADER_RECORD_TERMINATOR )
+        {
+            psDBF->nFields = iField;
+            break;
+        }
 
 	if( pabyFInfo[11] == 'N' || pabyFInfo[11] == 'F' )
 	{
@@ -597,6 +671,8 @@ DBFOpenLL( const char * pszFilename, const char * pszAccess, SAHooks *psHooks )
 	      psDBF->panFieldOffset[iField-1] + psDBF->panFieldSize[iField-1];
     }
 
+    DBFSetWriteEndOfFileChar( psDBF, TRUE );
+
     return( psDBF );
 }
 
@@ -769,7 +845,7 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
     psDBF->nRecords = 0;
     psDBF->nFields = 0;
     psDBF->nRecordLength = 1;
-    psDBF->nHeaderLength = 33;
+    psDBF->nHeaderLength = XBASE_FILEHDR_SZ + 1; /* + 1 for HEADER_RECORD_TERMINATOR */
 
     psDBF->panFieldOffset = NULL;
     psDBF->panFieldSize = NULL;
@@ -792,6 +868,8 @@ DBFCreateLL( const char * pszFilename, const char * pszCodePage, SAHooks *psHook
     }
     DBFSetLastModifiedDate(psDBF, 95, 7, 26); /* dummy date */
 
+    DBFSetWriteEndOfFileChar(psDBF, TRUE);
+
     return( psDBF );
 }
 
@@ -862,14 +940,36 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
     if( !DBFFlushRecord( psDBF ) )
         return -1;
 
+    if( psDBF->nHeaderLength + XBASE_FLDHDR_SZ > 65535 )
+    {
+        char szMessage[128];
+        snprintf( szMessage, sizeof(szMessage),
+                  "Cannot add field %s. Header length limit reached "
+                  "(max 65535 bytes, 2046 fields).",
+                  pszFieldName );
+        psDBF->sHooks.Error( szMessage );
+        return -1;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Do some checking to ensure we can add records to this file.     */
 /* -------------------------------------------------------------------- */
     if( nWidth < 1 )
         return -1;
 
-    if( nWidth > 255 )
-        nWidth = 255;
+    if( nWidth > XBASE_FLD_MAX_WIDTH )
+        nWidth = XBASE_FLD_MAX_WIDTH;
+
+    if( psDBF->nRecordLength + nWidth > 65535 )
+    {
+        char szMessage[128];
+        snprintf( szMessage, sizeof(szMessage),
+                  "Cannot add field %s. Record length limit reached "
+                  "(max 65535 bytes).",
+                  pszFieldName );
+        psDBF->sHooks.Error( szMessage );
+        return -1;
+    }
 
     nOldRecordLength = psDBF->nRecordLength;
     nOldHeaderLength = psDBF->nHeaderLength;
@@ -904,20 +1004,18 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
 /* -------------------------------------------------------------------- */
 /*      Extend the required header information.                         */
 /* -------------------------------------------------------------------- */
-    psDBF->nHeaderLength += 32;
+    psDBF->nHeaderLength += XBASE_FLDHDR_SZ;
     psDBF->bUpdated = FALSE;
 
-    psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
+    psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,
+                                          psDBF->nFields*XBASE_FLDHDR_SZ);
 
-    pszFInfo = psDBF->pszHeader + 32 * (psDBF->nFields-1);
+    pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * (psDBF->nFields-1);
 
-    for( i = 0; i < 32; i++ )
+    for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
         pszFInfo[i] = '\0';
 
-    if( (int) strlen(pszFieldName) < 10 )
-        strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
-    else
-        strncpy( pszFInfo, pszFieldName, 10);
+    strncpy( pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE );
 
     pszFInfo[11] = psDBF->pachFieldType[psDBF->nFields-1];
 
@@ -969,6 +1067,17 @@ DBFAddNativeFieldType(DBFHandle psDBF, const char * pszFieldName,
         psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
     }
 
+    if( psDBF->bWriteEndOfFileChar )
+    {
+        char ch = END_OF_FILE_CHARACTER;
+
+        nRecordOffset =
+            psDBF->nRecordLength * (SAOffset) psDBF->nRecords + psDBF->nHeaderLength;
+
+        psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+        psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+    }
+
     /* free record */
     free(pszRecord);
 
@@ -1241,6 +1350,8 @@ DBFGetRecordCount( DBFHandle psDBF )
 /*                          DBFGetFieldInfo()                           */
 /*                                                                      */
 /*      Return any requested information about the field.               */
+/*      pszFieldName must be at least XBASE_FLDNAME_LEN_READ+1 (=12)    */
+/*      bytes long.                                                     */
 /************************************************************************/
 
 DBFFieldType SHPAPI_CALL
@@ -1261,9 +1372,10 @@ DBFGetFieldInfo( DBFHandle psDBF, int iField, char * pszFieldName,
     {
 	int	i;
 
-	strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*32, 11 );
-	pszFieldName[11] = '\0';
-	for( i = 10; i > 0 && pszFieldName[i] == ' '; i-- )
+	strncpy( pszFieldName, (char *) psDBF->pszHeader+iField*XBASE_FLDHDR_SZ,
+                 XBASE_FLDNAME_LEN_READ );
+	pszFieldName[XBASE_FLDNAME_LEN_READ] = '\0';
+	for( i = XBASE_FLDNAME_LEN_READ - 1; i > 0 && pszFieldName[i] == ' '; i-- )
 	    pszFieldName[i] = '\0';
     }
 
@@ -1297,7 +1409,7 @@ static int DBFWriteAttribute(DBFHandle psDBF, int hEntity, int iField,
 {
     int	       	i, j, nRetResult = TRUE;
     unsigned char	*pabyRec;
-    char	szSField[400], szFormat[20];
+    char	szSField[XBASE_FLD_MAX_WIDTH+1], szFormat[20];
 
 /* -------------------------------------------------------------------- */
 /*	Is this a valid record?						*/
@@ -1652,11 +1764,13 @@ DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename )
 
    newDBF->bNoHeader = TRUE;
    newDBF->bUpdated = TRUE;
+   newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
 
    DBFWriteHeader ( newDBF );
    DBFClose ( newDBF );
 
    newDBF = DBFOpen ( pszFilename, "rb+" );
+   newDBF->bWriteEndOfFileChar = psDBF->bWriteEndOfFileChar;
 
    return ( newDBF );
 }
@@ -1710,20 +1824,23 @@ int SHPAPI_CALL
 DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName)
 
 {
-    char          name[12], name1[12], name2[12];
+    char          name[XBASE_FLDNAME_LEN_READ+1],
+                  name1[XBASE_FLDNAME_LEN_READ+1],
+                  name2[XBASE_FLDNAME_LEN_READ+1];
     int           i;
 
-    strncpy(name1, pszFieldName,11);
-    name1[11] = '\0';
+    strncpy(name1, pszFieldName,XBASE_FLDNAME_LEN_READ);
+    name1[XBASE_FLDNAME_LEN_READ] = '\0';
     str_to_upper(name1);
 
     for( i = 0; i < DBFGetFieldCount(psDBF); i++ )
     {
         DBFGetFieldInfo( psDBF, i, name, NULL, NULL );
-        strncpy(name2,name,11);
+        strncpy(name2,name,XBASE_FLDNAME_LEN_READ);
+        name2[XBASE_FLDNAME_LEN_READ] = '\0';
         str_to_upper(name2);
 
-        if(!strncmp(name1,name2,10))
+        if(!strcmp(name1,name2))
             return(i);
     }
     return(-1);
@@ -1863,15 +1980,16 @@ DBFDeleteField(DBFHandle psDBF, int iField)
         SfRealloc( psDBF->pachFieldType, sizeof(char) * psDBF->nFields );
 
     /* update header information */
-    psDBF->nHeaderLength -= 32;
+    psDBF->nHeaderLength -= XBASE_FLDHDR_SZ;
     psDBF->nRecordLength -= nDeletedFieldSize;
 
     /* overwrite field information in header */
-    memmove(psDBF->pszHeader + iField*32,
-           psDBF->pszHeader + (iField+1)*32,
-           sizeof(char) * (psDBF->nFields - iField)*32);
+    memmove(psDBF->pszHeader + iField*XBASE_FLDHDR_SZ,
+           psDBF->pszHeader + (iField+1)*XBASE_FLDHDR_SZ,
+           sizeof(char) * (psDBF->nFields - iField)*XBASE_FLDHDR_SZ);
 
-    psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,psDBF->nFields*32);
+    psDBF->pszHeader = (char *) SfRealloc(psDBF->pszHeader,
+                                          psDBF->nFields*XBASE_FLDHDR_SZ);
 
     /* update size of current record appropriately */
     psDBF->pszCurrentRecord = (char *) SfRealloc(psDBF->pszCurrentRecord,
@@ -1910,6 +2028,12 @@ DBFDeleteField(DBFHandle psDBF, int iField)
 
     }
 
+    if( psDBF->bWriteEndOfFileChar )
+    {
+        char ch = END_OF_FILE_CHARACTER;
+        psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+    }
+
     /* TODO: truncate file */
 
     /* free record */
@@ -1954,10 +2078,11 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
 
     /* a simple malloc() would be enough, but calloc() helps clang static analyzer */
     panFieldOffsetNew = (int *) calloc(sizeof(int), psDBF->nFields);
-    panFieldSizeNew = (int *) malloc(sizeof(int) *  psDBF->nFields);
-    panFieldDecimalsNew = (int *) malloc(sizeof(int) *  psDBF->nFields);
-    pachFieldTypeNew = (char *) malloc(sizeof(char) *  psDBF->nFields);
-    pszHeaderNew = (char*) malloc(sizeof(char) * 32 *  psDBF->nFields);
+    panFieldSizeNew = (int *) calloc(sizeof(int),  psDBF->nFields);
+    panFieldDecimalsNew = (int *) calloc(sizeof(int), psDBF->nFields);
+    pachFieldTypeNew = (char *) calloc(sizeof(char), psDBF->nFields);
+    pszHeaderNew = (char*) malloc(sizeof(char) * XBASE_FLDHDR_SZ * 
+                                  psDBF->nFields);
 
     /* shuffle fields definitions */
     for(i=0; i < psDBF->nFields; i++)
@@ -1965,8 +2090,8 @@ DBFReorderFields( DBFHandle psDBF, int* panMap )
         panFieldSizeNew[i] = psDBF->panFieldSize[panMap[i]];
         panFieldDecimalsNew[i] = psDBF->panFieldDecimals[panMap[i]];
         pachFieldTypeNew[i] = psDBF->pachFieldType[panMap[i]];
-        memcpy(pszHeaderNew + i * 32,
-               psDBF->pszHeader + panMap[i] * 32, 32);
+        memcpy(pszHeaderNew + i * XBASE_FLDHDR_SZ,
+               psDBF->pszHeader + panMap[i] * XBASE_FLDHDR_SZ, XBASE_FLDHDR_SZ);
     }
     panFieldOffsetNew[0] = 1;
     for(i=1; i < psDBF->nFields; i++)
@@ -2076,8 +2201,8 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
     if( nWidth < 1 )
         return -1;
 
-    if( nWidth > 255 )
-        nWidth = 255;
+    if( nWidth > XBASE_FLD_MAX_WIDTH )
+        nWidth = XBASE_FLD_MAX_WIDTH;
 
 /* -------------------------------------------------------------------- */
 /*      Assign the new field information fields.                        */
@@ -2089,15 +2214,12 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
 /* -------------------------------------------------------------------- */
 /*      Update the header information.                                  */
 /* -------------------------------------------------------------------- */
-    pszFInfo = psDBF->pszHeader + 32 * iField;
+    pszFInfo = psDBF->pszHeader + XBASE_FLDHDR_SZ * iField;
 
-    for( i = 0; i < 32; i++ )
+    for( i = 0; i < XBASE_FLDHDR_SZ; i++ )
         pszFInfo[i] = '\0';
 
-    if( (int) strlen(pszFieldName) < 10 )
-        strncpy( pszFInfo, pszFieldName, strlen(pszFieldName));
-    else
-        strncpy( pszFInfo, pszFieldName, 10);
+    strncpy( pszFInfo, pszFieldName, XBASE_FLDNAME_LEN_WRITE );
 
     pszFInfo[11] = psDBF->pachFieldType[iField];
 
@@ -2138,6 +2260,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
         char* pszRecord = (char *) malloc(sizeof(char) * nOldRecordLength);
         char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
 
+        /* cppcheck-suppress uninitdata */
         pszOldField[nOldWidth] = 0;
 
         /* move records to their new positions */
@@ -2184,6 +2307,18 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
             psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
         }
 
+        if( psDBF->bWriteEndOfFileChar )
+        {
+            char ch = END_OF_FILE_CHARACTER;
+
+            nRecordOffset =
+                psDBF->nRecordLength * (SAOffset) psDBF->nRecords + psDBF->nHeaderLength;
+
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+        }
+        /* TODO: truncate file */
+
         free(pszRecord);
         free(pszOldField);
     }
@@ -2192,6 +2327,7 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
         char* pszRecord = (char *) malloc(sizeof(char) * psDBF->nRecordLength);
         char* pszOldField = (char *) malloc(sizeof(char) * (nOldWidth + 1));
 
+        /* cppcheck-suppress uninitdata */
         pszOldField[nOldWidth] = 0;
 
         /* move records to their new positions */
@@ -2243,6 +2379,17 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
             psDBF->sHooks.FWrite( pszRecord, psDBF->nRecordLength, 1, psDBF->fp );
         }
 
+        if( psDBF->bWriteEndOfFileChar )
+        {
+            char ch = END_OF_FILE_CHARACTER;
+
+            nRecordOffset =
+                psDBF->nRecordLength * (SAOffset) psDBF->nRecords + psDBF->nHeaderLength;
+
+            psDBF->sHooks.FSeek( psDBF->fp, nRecordOffset, 0 );
+            psDBF->sHooks.FWrite( &ch, 1, 1, psDBF->fp );
+        }
+
         free(pszRecord);
         free(pszOldField);
     }
@@ -2253,3 +2400,12 @@ DBFAlterFieldDefn( DBFHandle psDBF, int iField, const char * pszFieldName,
 
     return TRUE;
 }
+
+/************************************************************************/
+/*                    DBFSetWriteEndOfFileChar()                        */
+/************************************************************************/
+
+void SHPAPI_CALL DBFSetWriteEndOfFileChar( DBFHandle psDBF, int bWriteFlag )
+{
+    psDBF->bWriteEndOfFileChar = bWriteFlag;
+}
diff --git a/ogr/ogrsf_frmts/shape/drv_shapefile.html b/ogr/ogrsf_frmts/shape/drv_shapefile.html
index 2165b23..c011877 100644
--- a/ogr/ogrsf_frmts/shape/drv_shapefile.html
+++ b/ogr/ogrsf_frmts/shape/drv_shapefile.html
@@ -51,7 +51,8 @@ analysis based on topological relationships of the parts of the polygons so
 that the resulting polygons are correctly
 defined in the OGC Simple Feature convention. </p>
 
-<p>An attempt is made to read the LDID/codepage setting from the .dbf file
+<p>An attempt is made to read the code page setting in the .cpg file, or as a
+fallback in the LDID/codepage setting from the .dbf file,
 and use it to translate string fields to UTF-8 on read, and back when writing.
 LDID "87 / 0x57" is treated as ISO8859_1 which may not be appropriate.
 The SHAPE_ENCODING <a href="http://trac.osgeo.org/gdal/wiki/ConfigOptions">
@@ -82,6 +83,15 @@ the driver will look at the first shape and if it has M values it will expose th
 layer as having a M dimension. By specifying
 ALL_SHAPES, the driver will iterate over features until a shape with a valid
 M value is found to decide the appropriate layer type.</li>
+
+<li> <b>AUTO_REPACK=</b><i>YES/NO</i>: (OGR >= 2.2) Default to YES in GDAL 2.2.
+Whether the shapefile should be automatically repacked when needed, at dataset
+closing or at FlushCache()/SyncToDisk() time.</li>
+
+<li> <b>DBF_EOF_CHAR=</b><i>YES/NO</i>: (OGR >= 2.2) Default to YES in GDAL 2.2.
+Whether the .DBF should be terminated by a 0x1A end-of-file character, as in the
+DBF spec and done by other software vendors. Previous GDAL versions did not write one.</li>
+
 </ul>
 
 <h2>Spatial and Attribute Indexing</h2>
@@ -194,6 +204,9 @@ the datasource ExecuteSQL() method.</p>
 <p>Starting with GDAL 2.0, REPACK will also result in .shp being rewritten if
 a feature geometry has been modified with SetFeature() and resulted in a change
 of the size the binary encoding of the geometry in the .shp file.</p>
+<p>Starting with GDAL 2.2, REPACK is also done automatically at file closing,
+or at FlushCache()/SyncToDisk() time, since shapefiles with holes can cause
+interoperability issues with other software.</p>
 
 <h2>Field sizes</h2>
 
@@ -245,11 +258,11 @@ emitted when the 2GB limit is reached.</p>
 
 <li><b>SHPT=type</b>: Override the type of shapefile created.  Can be
 one of NULL for a simple .dbf file with no .shp file, POINT, ARC,
-POLYGON or MULTIPOINT for 2D; POINTZ, ARCZ, POLYGONZ or MULTIPOINTZ
+POLYGON or MULTIPOINT for 2D; POINTZ, ARCZ, POLYGONZ, MULTIPOINTZ or MULTIPATCH
 for 3D; POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries;
 and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured
 geometries. The measure support was added in GDAL 2.1. MULTIPATCH
-files are not supported.</li>
+files are supported since GDAL 2.2.</li>
 
 <li> <b>ENCODING=</b><i>value</i>: set the encoding value in the DBF file. The
 default value is "LDID/87".  It is not clear what other values may be
@@ -267,6 +280,14 @@ for .SHP or .DBF files. Defaults to NO.</li>
 date to write in DBF header with year-month-day format. If not specified, current date is used.
 Note: behaviour of past GDAL releases was to write 1995-07-26</li>
 
+<li> <b>AUTO_REPACK=</b><i>YES/NO</i>: (OGR >= 2.2) Default to YES in GDAL 2.2.
+Whether the shapefile should be automatically repacked when needed, at dataset
+closing or at FlushCache()/SyncToDisk() time.</li>
+
+<li> <b>DBF_EOF_CHAR=</b><i>YES/NO</i>: (OGR >= 2.2) Default to YES in GDAL 2.2.
+Whether the .DBF should be terminated by a 0x1A end-of-file character, as in the
+DBF spec and done by other software vendors. Previous GDAL versions did not write one.</li>
+
 </ul>
 
 <h3>VSI Virtual File System API support</h3>
diff --git a/ogr/ogrsf_frmts/shape/ogrshape.h b/ogr/ogrsf_frmts/shape/ogrshape.h
index 0d926cb..31712a7 100644
--- a/ogr/ogrsf_frmts/shape/ogrshape.h
+++ b/ogr/ogrsf_frmts/shape/ogrshape.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrshape.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogrshape.h 36704 2016-12-05 16:33:06Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions within the Shapefile driver to implement
@@ -58,8 +58,8 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
 OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                            OGRFeatureDefn *poFeatureDefn,
                            OGRFeature *poFeature, const char *pszSHPEncoding,
-                           int* pbTruncationWarningEmitted,
-                           int bRewind );
+                           bool* pbTruncationWarningEmitted,
+                           bool bRewind );
 
 /************************************************************************/
 /*                         OGRShapeGeomFieldDefn                        */
@@ -68,24 +68,25 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 class OGRShapeGeomFieldDefn CPL_FINAL: public OGRGeomFieldDefn
 {
     char* pszFullName;
-    int   bSRSSet;
+    bool  bSRSSet;
     CPLString osPrjFile;
 
     public:
-        OGRShapeGeomFieldDefn(const char* pszFullNameIn, OGRwkbGeometryType eType,
-                              int bSRSSetIn, OGRSpatialReference *poSRSIn) :
+        OGRShapeGeomFieldDefn( const char* pszFullNameIn,
+                               OGRwkbGeometryType eType,
+                               int bSRSSetIn, OGRSpatialReference *poSRSIn) :
             OGRGeomFieldDefn("", eType),
             pszFullName(CPLStrdup(pszFullNameIn)),
-            bSRSSet(bSRSSetIn)
+            bSRSSet(CPL_TO_BOOL(bSRSSetIn))
         {
             poSRS = poSRSIn;
         }
 
         virtual ~OGRShapeGeomFieldDefn() { CPLFree(pszFullName); }
 
-        virtual OGRSpatialReference* GetSpatialRef();
+        virtual OGRSpatialReference* GetSpatialRef() override;
 
-        const CPLString& GetPrjFilename() { return osPrjFile; }
+        const CPLString& GetPrjFilename() const { return osPrjFile; }
 };
 
 /************************************************************************/
@@ -107,12 +108,12 @@ class OGRShapeLayer CPL_FINAL: public OGRAbstractProxiedLayer
     SHPHandle           hSHP;
     DBFHandle           hDBF;
 
-    int                 bUpdateAccess;
+    bool                bUpdateAccess;
 
     OGRwkbGeometryType  eRequestedGeomType;
     int                 ResetGeomType( int nNewType );
 
-    int                 ScanIndices();
+    bool                ScanIndices();
 
     GIntBig            *panMatchingFIDs;
     int                 iMatchingFID;
@@ -123,44 +124,61 @@ class OGRShapeLayer CPL_FINAL: public OGRAbstractProxiedLayer
     int                *panSpatialFIDs;
     void                ClearSpatialFIDs();
 
-    int                 bHeaderDirty;
-    int                 bSHPNeedsRepack;
-
-    int                 bCheckedForQIX;
+    bool                bHeaderDirty;
+    bool                bSHPNeedsRepack;
+    bool                bCheckedForQIX;
     SHPTreeDiskHandle   hQIX;
-    int                 CheckForQIX();
+    bool                CheckForQIX();
 
-    int                 bCheckedForSBN;
+    bool                bCheckedForSBN;
     SBNSearchHandle     hSBN;
-    int                 CheckForSBN();
+    bool                CheckForSBN();
 
-    int                 bSbnSbxDeleted;
+    bool                bSbnSbxDeleted;
 
     CPLString           ConvertCodePage( const char * );
     CPLString           osEncoding;
 
-    int                 bTruncationWarningEmitted;
+    bool                bTruncationWarningEmitted;
+
+    bool                bHSHPWasNonNULL; // Must try to reopen a .shp?
+    bool                bHDBFWasNonNULL; // Must try to reopen a .dbf
+    // Current state of opening of file descriptor to .shp and .dbf.
+
+    typedef enum
+    {
+        FD_OPENED,
+        FD_CLOSED,
+        FD_CANNOT_REOPEN
+    } FileDescriptorState;
+    FileDescriptorState eFileDescriptorsState;
 
-    int                 bHSHPWasNonNULL; /* to know if we must try to reopen a .shp */
-    int                 bHDBFWasNonNULL; /* to know if we must try to reopen a .dbf */
-    int                 eFileDescriptorsState; /* current state of opening of file descriptor to .shp and .dbf */
-    int                 TouchLayer();
-    int                 ReopenFileDescriptors();
+    bool                TouchLayer();
+    bool                ReopenFileDescriptors();
 
-    int                 bResizeAtClose;
+    bool                bResizeAtClose;
 
     void                TruncateDBF();
 
-    int                 bCreateSpatialIndexAtClose;
-    int                 bRewindOnWrite;
+    bool                bCreateSpatialIndexAtClose;
+    bool                bRewindOnWrite;
+
+    bool                m_bAutoRepack;
+    typedef enum
+    {
+        YES,
+        NO,
+        MAYBE
+    } NormandyState; /* French joke. "Peut'et' ben que oui, peut'et' ben que non." Sorry :-) */
+    NormandyState       m_eNeedRepack;
 
   protected:
 
-    virtual void        CloseUnderlyingLayer();
+    virtual void        CloseUnderlyingLayer() override;
 
-/* WARNING: each of the below public methods should start with a call to */
-/* TouchLayer() and test its return value, so as to make sure that */
-/* the layer is properly re-opened if necessary */
+// WARNING: Each of the below public methods should start with a call to
+// TouchLayer() and test its return value, so as to make sure that
+// the layer is properly re-opened if necessary.
 
   public:
     OGRErr              CreateSpatialIndex( int nMaxDepth );
@@ -169,56 +187,63 @@ class OGRShapeLayer CPL_FINAL: public OGRAbstractProxiedLayer
     OGRErr              RecomputeExtent();
     OGRErr              ResizeDBF();
 
-    void                SetResizeAtClose( int bFlag ) { bResizeAtClose = bFlag; }
+    void                SetResizeAtClose( bool bFlag )
+        { bResizeAtClose = bFlag; }
 
     const char         *GetFullName() { return pszFullName; }
 
-    OGRFeature *        FetchShape(int iShapeId);
+    OGRFeature *        FetchShape( int iShapeId );
     int                 GetFeatureCountWithSpatialFilterOnly();
 
   public:
                         OGRShapeLayer( OGRShapeDataSource* poDSIn,
                                        const char * pszName,
                                        SHPHandle hSHP, DBFHandle hDBF,
-                                       OGRSpatialReference *poSRS, int bSRSSet,
-                                       int bUpdate,
+                                       OGRSpatialReference *poSRS, bool bSRSSet,
+                                       bool bUpdate,
                                        OGRwkbGeometryType eReqType,
                                        char ** papszCreateOptions = NULL);
-                        ~OGRShapeLayer();
+    virtual            ~OGRShapeLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
 
-    OGRFeature         *GetFeature( GIntBig nFeatureId );
-    OGRErr              ISetFeature( OGRFeature *poFeature );
-    OGRErr              DeleteFeature( GIntBig nFID );
-    OGRErr              ICreateFeature( OGRFeature *poFeature );
-    OGRErr              SyncToDisk();
+    OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
+    OGRErr              ISetFeature( OGRFeature *poFeature ) override;
+    OGRErr              DeleteFeature( GIntBig nFID ) override;
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override;
+    OGRErr              SyncToDisk() override;
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    GIntBig             GetFeatureCount( int );
-    OGRErr              GetExtent(OGREnvelope *psExtent, int bForce);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    GIntBig             GetFeatureCount( int ) override;
+    OGRErr              GetExtent( OGREnvelope *psExtent, int bForce ) override;
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent,
+                                   int bForce ) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
-
-    virtual int         TestCapability( const char * );
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+                                     int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    virtual OGRErr      AlterFieldDefn( int iField,
+                                        OGRFieldDefn* poNewFieldDefn,
+                                        int nFlags ) override;
+
+    virtual int         TestCapability( const char * ) override;
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
     void                AddToFileList( CPLStringList& oFileList );
-    void                CreateSpatialIndexAtClose( int bFlag ) { bCreateSpatialIndexAtClose = bFlag; }
-    void                SetModificationDate(const char* pszStr);
+    void                CreateSpatialIndexAtClose( int bFlag )
+        { bCreateSpatialIndexAtClose = CPL_TO_BOOL(bFlag); }
+    void                SetModificationDate( const char* pszStr );
+    void                SetAutoRepack(bool b) { m_bAutoRepack = b; }
+    void                SetWriteDBFEOFChar(bool b);
 };
 
 /************************************************************************/
@@ -229,58 +254,55 @@ class OGRShapeDataSource CPL_FINAL: public OGRDataSource
 {
     OGRShapeLayer     **papoLayers;
     int                 nLayers;
-
     char                *pszName;
+    bool                bDSUpdate;
+    bool                bSingleFileDataSource;
+    OGRLayerPool       *poPool;
 
-    int                 bDSUpdate;
-
-    int                 bSingleFileDataSource;
-
-    OGRLayerPool*       poPool;
-
-    void                AddLayer(OGRShapeLayer* poLayer);
+    void                AddLayer( OGRShapeLayer* poLayer );
 
     std::vector<CPLString> oVectorLayerName;
 
-    int                 b2GBLimit;
-
+    bool                b2GBLimit;
     char              **papszOpenOptions;
 
   public:
                         OGRShapeDataSource();
-                        ~OGRShapeDataSource();
+    virtual            ~OGRShapeDataSource();
 
     OGRLayerPool       *GetPool() { return poPool; }
 
-    int                 Open( GDALOpenInfo* poOpenInfo, int bTestOpen,
-                              int bForceSingleFileDataSource = FALSE );
-    int                 OpenFile( const char *, int bUpdate, int bTestOpen );
+    bool                Open( GDALOpenInfo* poOpenInfo, bool bTestOpen,
+                              bool bForceSingleFileDataSource = false );
+    bool                OpenFile( const char *, bool bUpdate );
 
-    virtual const char  *GetName() { return pszName; }
+    virtual const char  *GetName() override { return pszName; }
 
-    virtual int          GetLayerCount();
-    virtual OGRLayer    *GetLayer( int );
-    virtual OGRLayer    *GetLayerByName(const char *);
+    virtual int          GetLayerCount() override;
+    virtual OGRLayer    *GetLayer( int ) override;
+    virtual OGRLayer    *GetLayerByName( const char * ) override;
 
     virtual OGRLayer    *ICreateLayer( const char *,
-                                      OGRSpatialReference * = NULL,
-                                      OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+                                       OGRSpatialReference * = NULL,
+                                       OGRwkbGeometryType = wkbUnknown,
+                                       char ** = NULL ) override;
 
     virtual OGRLayer    *ExecuteSQL( const char *pszStatement,
                                      OGRGeometry *poSpatialFilter,
-                                     const char *pszDialect );
+                                     const char *pszDialect ) override;
 
-    virtual int          TestCapability( const char * );
-    virtual OGRErr       DeleteLayer( int iLayer );
+    virtual int          TestCapability( const char * ) override;
+    virtual OGRErr       DeleteLayer( int iLayer ) override;
 
-    virtual char      **GetFileList(void);
+    virtual char      **GetFileList() override;
 
     void                 SetLastUsedLayer( OGRShapeLayer* poLayer );
     void                 UnchainLayer( OGRShapeLayer* poLayer );
 
-    SHPHandle            DS_SHPOpen( const char * pszShapeFile, const char * pszAccess );
-    DBFHandle            DS_DBFOpen( const char * pszDBFFile, const char * pszAccess );
+    SHPHandle            DS_SHPOpen( const char * pszShapeFile,
+                                     const char * pszAccess );
+    DBFHandle            DS_DBFOpen( const char * pszDBFFile,
+                                     const char * pszAccess );
     char               **GetOpenOptions() { return papszOpenOptions; }
 };
 
diff --git a/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp b/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
index 4cb71b4..2fa4e61 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapedatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrshapedatasource.cpp 34069 2016-04-23 17:59:00Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeDataSource class.
@@ -33,25 +32,29 @@
 #include "cpl_string.h"
 #include <set>
 
-//#define IMMEDIATE_OPENING 1
+// #define IMMEDIATE_OPENING 1
 
-CPL_CVSID("$Id: ogrshapedatasource.cpp 34069 2016-04-23 17:59:00Z rouault $");
+CPL_CVSID("$Id: ogrshapedatasource.cpp 37091 2017-01-10 17:25:57Z rouault $");
 
 /************************************************************************/
 /*                          DS_SHPOpen()                                */
 /************************************************************************/
 
-SHPHandle OGRShapeDataSource::DS_SHPOpen( const char * pszShapeFile, const char * pszAccess )
+SHPHandle OGRShapeDataSource::DS_SHPOpen( const char * pszShapeFile,
+                                          const char * pszAccess )
 {
-    /* Do lazy shx loading for /vsicurl/ */
+    // Do lazy shx loading for /vsicurl/
     if( STARTS_WITH(pszShapeFile, "/vsicurl/") &&
         strcmp(pszAccess, "r") == 0 )
         pszAccess = "rl";
 
-    int bRestoreSHX = CPLTestBool( CPLGetConfigOption("SHAPE_RESTORE_SHX", "FALSE") );
-    SHPHandle hSHP = SHPOpenLLEx( pszShapeFile, pszAccess, (SAHooks*) VSI_SHP_GetHook(b2GBLimit),
-                                  bRestoreSHX );
-    
+    const bool bRestoreSHX =
+        CPLTestBool( CPLGetConfigOption("SHAPE_RESTORE_SHX", "FALSE") );
+    SHPHandle hSHP =
+        SHPOpenLLEx( pszShapeFile, pszAccess,
+                     const_cast<SAHooks *>(VSI_SHP_GetHook(b2GBLimit)),
+                     bRestoreSHX );
+
     if( hSHP != NULL )
         SHPSetFastModeReadObject( hSHP, TRUE );
     return hSHP;
@@ -61,9 +64,12 @@ SHPHandle OGRShapeDataSource::DS_SHPOpen( const char * pszShapeFile, const char
 /*                           DS_DBFOpen()                               */
 /************************************************************************/
 
-DBFHandle OGRShapeDataSource::DS_DBFOpen( const char * pszDBFFile, const char * pszAccess )
+DBFHandle OGRShapeDataSource::DS_DBFOpen( const char * pszDBFFile,
+                                          const char * pszAccess )
 {
-    DBFHandle hDBF = DBFOpenLL( pszDBFFile, pszAccess, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
+    DBFHandle hDBF =
+        DBFOpenLL( pszDBFFile, pszAccess,
+                   const_cast<SAHooks *>(VSI_SHP_GetHook(b2GBLimit)) );
     return hDBF;
 }
 
@@ -75,14 +81,12 @@ OGRShapeDataSource::OGRShapeDataSource() :
     papoLayers(NULL),
     nLayers(0),
     pszName(NULL),
-    bDSUpdate(FALSE),
-    bSingleFileDataSource(FALSE),
+    bDSUpdate(false),
+    bSingleFileDataSource(false),
+    poPool(new OGRLayerPool()),
+    b2GBLimit(CPLTestBool(CPLGetConfigOption("SHAPE_2GB_LIMIT", "FALSE"))),
     papszOpenOptions(NULL)
-{
-    poPool = new OGRLayerPool();
-    b2GBLimit = CPLTestBool(CPLGetConfigOption("SHAPE_2GB_LIMIT", "FALSE"));
-}
-
+{}
 
 /************************************************************************/
 /*                        ~OGRShapeDataSource()                         */
@@ -110,21 +114,21 @@ OGRShapeDataSource::~OGRShapeDataSource()
 /*                                Open()                                */
 /************************************************************************/
 
-int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
-                              int bTestOpen, int bForceSingleFileDataSource )
+bool OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
+                              bool bTestOpen, bool bForceSingleFileDataSource )
 
 {
     CPLAssert( nLayers == 0 );
 
     const char * pszNewName = poOpenInfo->pszFilename;
-    int bUpdate = poOpenInfo->eAccess == GA_Update;
+    const bool bUpdate = poOpenInfo->eAccess == GA_Update;
     papszOpenOptions = CSLDuplicate( poOpenInfo->papszOpenOptions );
 
     pszName = CPLStrdup( pszNewName );
 
     bDSUpdate = bUpdate;
 
-    bSingleFileDataSource = bForceSingleFileDataSource;
+    bSingleFileDataSource = CPL_TO_BOOL(bForceSingleFileDataSource);
 
 /* -------------------------------------------------------------------- */
 /*      If bSingleFileDataSource is TRUE we don't try to do anything    */
@@ -135,7 +139,7 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
 /*      file by calling ICreateLayer().                                 */
 /* -------------------------------------------------------------------- */
     if( bSingleFileDataSource )
-        return TRUE;
+        return true;
 
 /* -------------------------------------------------------------------- */
 /*      Is the given path a directory or a regular file?                */
@@ -144,10 +148,10 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
     {
         if( !bTestOpen )
             CPLError( CE_Failure, CPLE_AppDefined,
-                   "%s is neither a file or directory, Shape access failed.\n",
+                      "%s is neither a file or directory, Shape access failed.",
                       pszNewName );
 
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -155,63 +159,66 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
 /* -------------------------------------------------------------------- */
     if( !poOpenInfo->bIsDirectory )
     {
-        if( !OpenFile( pszNewName, bUpdate, bTestOpen ) )
+        if( !OpenFile( pszNewName, bUpdate ) )
         {
             if( !bTestOpen )
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                          "Failed to open shapefile %s.\n"
-                          "It may be corrupt or read-only file accessed in update mode.\n",
-                          pszNewName );
-
-            return FALSE;
+                CPLError(
+                    CE_Failure, CPLE_OpenFailed,
+                    "Failed to open shapefile %s.  "
+                    "It may be corrupt or read-only file accessed in "
+                    "update mode.",
+                    pszNewName );
+
+            return false;
         }
 
-        bSingleFileDataSource = TRUE;
+        bSingleFileDataSource = true;
 
-        return TRUE;
+        return true;
     }
     else
     {
-        char      **papszCandidates = VSIReadDir( pszNewName );
-        int       iCan, nCandidateCount = CSLCount( papszCandidates );
-        int       bMightBeOldCoverage = FALSE;
+        char **papszCandidates = VSIReadDir( pszNewName );
+        const int nCandidateCount = CSLCount( papszCandidates );
+        bool bMightBeOldCoverage = false;
         std::set<CPLString> osLayerNameSet;
 
-        for( iCan = 0; iCan < nCandidateCount; iCan++ )
+        for( int iCan = 0; iCan < nCandidateCount; iCan++ )
         {
-            char        *pszFilename;
-            const char  *pszCandidate = papszCandidates[iCan];
-            const char  *pszLayerName = CPLGetBasename(pszCandidate);
+            const char *pszCandidate = papszCandidates[iCan];
+            const char *pszLayerName = CPLGetBasename(pszCandidate);
             CPLString osLayerName(pszLayerName);
 #ifdef WIN32
-            /* On Windows, as filenames are case insensitive, a shapefile layer can be made of */
-            /* foo.shp and FOO.DBF, so to detect unique layer names, put them */
-            /* upper case in the unique set used for detection */
+            // On Windows, as filenames are case insensitive, a shapefile layer
+            // can be made of foo.shp and FOO.DBF, so to detect unique layer
+            // names, put them upper case in the unique set used for detection.
             osLayerName.toupper();
 #endif
 
             if( EQUAL(pszCandidate,"ARC") )
-                bMightBeOldCoverage = TRUE;
+                bMightBeOldCoverage = true;
 
             if( strlen(pszCandidate) < 4
                 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".shp") )
                 continue;
 
-            pszFilename =
+            char *pszFilename =
                 CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL));
 
             osLayerNameSet.insert(osLayerName);
 #ifdef IMMEDIATE_OPENING
-            if( !OpenFile( pszFilename, bUpdate, bTestOpen )
+            if( !OpenFile( pszFilename, bUpdate )
                 && !bTestOpen )
             {
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                          "Failed to open shapefile %s.\n"
-                          "It may be corrupt or read-only file accessed in update mode.\n",
-                          pszFilename );
+                CPLError(
+                    CE_Failure, CPLE_OpenFailed,
+                    "Failed to open shapefile %s.  "
+                    "It may be corrupt or read-only file accessed in "
+                    "update mode.",
+                    pszFilename );
                 CPLFree( pszFilename );
                 CSLDestroy( papszCandidates );
-                return FALSE;
+                return false;
             }
 #else
             oVectorLayerName.push_back(pszFilename);
@@ -220,9 +227,8 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
         }
 
         // Try and .dbf files without apparent associated shapefiles.
-        for( iCan = 0; iCan < nCandidateCount; iCan++ )
+        for( int iCan = 0; iCan < nCandidateCount; iCan++ )
         {
-            char        *pszFilename;
             const char  *pszCandidate = papszCandidates[iCan];
             const char  *pszLayerName = CPLGetBasename(pszCandidate);
             CPLString osLayerName(pszLayerName);
@@ -233,11 +239,11 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
             // We don't consume .dbf files in a directory that looks like
             // an old style Arc/Info (for PC?) that unless we found at least
             // some shapefiles.  See Bug 493.
-            if( bMightBeOldCoverage && osLayerNameSet.size() == 0 )
+            if( bMightBeOldCoverage && osLayerNameSet.empty() )
                 continue;
 
             if( strlen(pszCandidate) < 4
-                || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".dbf") )
+                || !EQUAL(pszCandidate+strlen(pszCandidate)-4, ".dbf") )
                 continue;
 
             if( osLayerNameSet.find(osLayerName) != osLayerNameSet.end() )
@@ -245,35 +251,37 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
 
             // We don't want to access .dbf files with an associated .tab
             // file, or it will never get recognised as a mapinfo dataset.
-            int  iCan2, bFoundTAB = FALSE;
-            for( iCan2 = 0; iCan2 < nCandidateCount; iCan2++ )
+            bool bFoundTAB = false;
+            for( int iCan2 = 0; iCan2 < nCandidateCount; iCan2++ )
             {
                 const char *pszCandidate2 = papszCandidates[iCan2];
 
-                if( EQUALN(pszCandidate2,pszLayerName,strlen(pszLayerName))
+                if( EQUALN(pszCandidate2, pszLayerName, strlen(pszLayerName))
                     && EQUAL(pszCandidate2 + strlen(pszLayerName), ".tab") )
-                    bFoundTAB = TRUE;
+                    bFoundTAB = true;
             }
 
             if( bFoundTAB )
                 continue;
 
-            pszFilename =
+            char *pszFilename =
                 CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL));
 
             osLayerNameSet.insert(osLayerName);
 
 #ifdef IMMEDIATE_OPENING
-            if( !OpenFile( pszFilename, bUpdate, bTestOpen )
+            if( !OpenFile( pszFilename, bUpdate )
                 && !bTestOpen )
             {
-                CPLError( CE_Failure, CPLE_OpenFailed,
-                          "Failed to open dbf file %s.\n"
-                          "It may be corrupt or read-only file accessed in update mode.\n",
-                          pszFilename );
+                CPLError(
+                    CE_Failure, CPLE_OpenFailed,
+                    "Failed to open dbf file %s.  "
+                    "It may be corrupt or read-only file accessed in "
+                    "update mode.",
+                    pszFilename );
                 CPLFree( pszFilename );
                 CSLDestroy( papszCandidates );
-                return FALSE;
+                return false;
             }
 #else
             oVectorLayerName.push_back(pszFilename);
@@ -284,9 +292,9 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
         CSLDestroy( papszCandidates );
 
 #ifdef IMMEDIATE_OPENING
-        int nDirLayers = nLayers;
+        const int nDirLayers = nLayers;
 #else
-        int nDirLayers = static_cast<int>(oVectorLayerName.size());
+        const int nDirLayers = static_cast<int>(oVectorLayerName.size());
 #endif
 
         CPLErrorReset();
@@ -299,19 +307,14 @@ int OGRShapeDataSource::Open( GDALOpenInfo* poOpenInfo,
 /*                              OpenFile()                              */
 /************************************************************************/
 
-int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
-                                  int bTestOpen )
+bool OGRShapeDataSource::OpenFile( const char *pszNewName, bool bUpdate )
 
 {
-    SHPHandle   hSHP;
-    DBFHandle   hDBF;
     const char *pszExtension = CPLGetExtension( pszNewName );
 
-    (void) bTestOpen;
-
     if( !EQUAL(pszExtension,"shp") && !EQUAL(pszExtension,"shx")
         && !EQUAL(pszExtension,"dbf") )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      SHPOpen() should include better (CPL based) error reporting,    */
@@ -324,10 +327,9 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
 /*      we think it is appropriate.                                     */
 /* -------------------------------------------------------------------- */
     CPLPushErrorHandler( CPLQuietErrorHandler );
-    if( bUpdate )
-        hSHP = DS_SHPOpen( pszNewName, "r+" );
-    else
-        hSHP = DS_SHPOpen( pszNewName, "r" );
+    SHPHandle hSHP = bUpdate ?
+        DS_SHPOpen( pszNewName, "r+" ) :
+        DS_SHPOpen( pszNewName, "r" );
     CPLPopErrorHandler();
 
     if( hSHP == NULL
@@ -338,7 +340,7 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
 
         CPLError( CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str() );
 
-        return FALSE;
+        return false;
     }
     CPLErrorReset();
 
@@ -347,29 +349,34 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
 /*      filename has to either refer to a successfully opened shp       */
 /*      file or has to refer to the actual .dbf file.                   */
 /* -------------------------------------------------------------------- */
-    if( hSHP != NULL || EQUAL(CPLGetExtension(pszNewName),"dbf") )
+    DBFHandle hDBF = NULL;
+    if( hSHP != NULL || EQUAL(CPLGetExtension(pszNewName), "dbf") )
     {
         if( bUpdate )
         {
             hDBF = DS_DBFOpen( pszNewName, "r+" );
             if( hSHP != NULL && hDBF == NULL )
             {
-                for(int i=0;i<2;i++)
+                for( int i = 0; i < 2; i++ )
                 {
                     VSIStatBufL sStat;
-                    const char* pszDBFName = CPLResetExtension(pszNewName,
-                                                    (i == 0 ) ? "dbf" : "DBF");
+                    const char* pszDBFName =
+                        CPLResetExtension(pszNewName,
+                                          (i == 0 ) ? "dbf" : "DBF");
                     VSILFILE* fp = NULL;
-                    if( VSIStatExL( pszDBFName, &sStat, VSI_STAT_EXISTS_FLAG) == 0 )
+                    if( VSIStatExL( pszDBFName, &sStat,
+                                    VSI_STAT_EXISTS_FLAG) == 0 )
                     {
                         fp = VSIFOpenL(pszDBFName, "r+");
-                        if (fp == NULL)
+                        if( fp == NULL )
                         {
-                            CPLError( CE_Failure, CPLE_OpenFailed,
-                                    "%s exists, but cannot be opened in update mode",
-                                    pszDBFName );
+                            CPLError(
+                                CE_Failure, CPLE_OpenFailed,
+                                "%s exists, "
+                                "but cannot be opened in update mode",
+                                pszDBFName );
                             SHPClose(hSHP);
-                            return FALSE;
+                            return false;
                         }
                         VSIFCloseL(fp);
                         break;
@@ -378,51 +385,58 @@ int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate,
             }
         }
         else
+        {
             hDBF = DS_DBFOpen( pszNewName, "r" );
+        }
     }
     else
+    {
         hDBF = NULL;
+    }
 
     if( hDBF == NULL && hSHP == NULL )
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRShapeLayer       *poLayer;
-
-    poLayer = new OGRShapeLayer( this, pszNewName, hSHP, hDBF, NULL, FALSE, bUpdate,
-                                 wkbNone );
+    OGRShapeLayer *poLayer =
+        new OGRShapeLayer( this, pszNewName, hSHP, hDBF, NULL, false, bUpdate,
+                           wkbNone );
     poLayer->SetModificationDate(
-            CSLFetchNameValue( papszOpenOptions, "DBF_DATE_LAST_UPDATE" ) );
+        CSLFetchNameValue( papszOpenOptions, "DBF_DATE_LAST_UPDATE" ) );
+    poLayer->SetAutoRepack(
+        CPLFetchBool( papszOpenOptions, "AUTO_REPACK", true ) );
+    poLayer->SetWriteDBFEOFChar(
+        CPLFetchBool( papszOpenOptions, "DBF_EOF_CHAR", true ) );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
 /* -------------------------------------------------------------------- */
     AddLayer(poLayer);
 
-    return TRUE;
+    return true;
 }
 
-
 /************************************************************************/
 /*                             AddLayer()                               */
 /************************************************************************/
 
-void OGRShapeDataSource::AddLayer(OGRShapeLayer* poLayer)
+void OGRShapeDataSource::AddLayer( OGRShapeLayer* poLayer )
 {
-    papoLayers = (OGRShapeLayer **)
-        CPLRealloc( papoLayers,  sizeof(OGRShapeLayer *) * (nLayers+1) );
+    papoLayers = reinterpret_cast<OGRShapeLayer **>(
+        CPLRealloc( papoLayers,  sizeof(OGRShapeLayer *) * (nLayers+1) ) );
     papoLayers[nLayers++] = poLayer;
 
-    /* If we reach the limit, then register all the already opened layers */
-    /* Technically this code would not be necessary if there was not the */
-    /* following initial test in SetLastUsedLayer() : */
-    /*      if (nLayers < MAX_SIMULTANEOUSLY_OPENED_LAYERS) */
-    /*         return; */
-    if (nLayers == poPool->GetMaxSimultaneouslyOpened() && poPool->GetSize() == 0)
+    // If we reach the limit, then register all the already opened layers
+    // Technically this code would not be necessary if there was not the
+    // following initial test in SetLastUsedLayer() :
+    //      if (nLayers < MAX_SIMULTANEOUSLY_OPENED_LAYERS)
+    //         return;
+    if( nLayers == poPool->GetMaxSimultaneouslyOpened() &&
+        poPool->GetSize() == 0 )
     {
-        for(int i=0;i<nLayers;i++)
+        for( int i = 0; i < nLayers; i++ )
             poPool->SetLastUsedLayer(papoLayers[i]);
     }
 }
@@ -433,16 +447,12 @@ void OGRShapeDataSource::AddLayer(OGRShapeLayer* poLayer)
 
 OGRLayer *
 OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
-                                 OGRSpatialReference *poSRS,
-                                 OGRwkbGeometryType eType,
-                                 char ** papszOptions )
+                                  OGRSpatialReference *poSRS,
+                                  OGRwkbGeometryType eType,
+                                  char ** papszOptions )
 
 {
-    SHPHandle   hSHP;
-    DBFHandle   hDBF;
-    int         nShapeType;
-
-    /* To ensure that existing layers are created */
+    // To ensure that existing layers are created.
     GetLayerCount();
 
 /* -------------------------------------------------------------------- */
@@ -451,7 +461,7 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
     if (GetLayerByName(pszLayerName) != NULL)
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Layer '%s' already exists",
-                    pszLayerName);
+                  pszLayerName);
         return NULL;
     }
 
@@ -461,8 +471,8 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
     if( !bDSUpdate )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
-                  "Data source %s opened read-only.\n"
-                  "New layer %s cannot be created.\n",
+                  "Data source %s opened read-only.  "
+                  "New layer %s cannot be created.",
                   pszName, pszLayerName );
 
         return NULL;
@@ -471,11 +481,13 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Figure out what type of layer we need.                          */
 /* -------------------------------------------------------------------- */
+    int nShapeType = -1;
+
     if( wkbFlatten(eType) == wkbUnknown || eType == wkbLineString )
         nShapeType = SHPT_ARC;
     else if( eType == wkbPoint )
         nShapeType = SHPT_POINT;
-    else if( eType == wkbPolygon )
+    else if( eType == wkbPolygon || eType == wkbTriangle )
         nShapeType = SHPT_POLYGON;
     else if( eType == wkbMultiPoint )
         nShapeType = SHPT_MULTIPOINT;
@@ -499,11 +511,11 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
         nShapeType = SHPT_ARCM;
     else if( eType == wkbMultiLineStringZM )
         nShapeType = SHPT_ARCZ;
-    else if( eType == wkbPolygon25D )
+    else if( eType == wkbPolygon25D || eType == wkbTriangleZ )
         nShapeType = SHPT_POLYGONZ;
-    else if( eType == wkbPolygonM )
+    else if( eType == wkbPolygonM || eType == wkbTriangleM )
         nShapeType = SHPT_POLYGONM;
-    else if( eType == wkbPolygonZM )
+    else if( eType == wkbPolygonZM || eType == wkbTriangleZM )
         nShapeType = SHPT_POLYGONZ;
     else if( eType == wkbMultiPolygon )
         nShapeType = SHPT_POLYGON;
@@ -519,10 +531,11 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
         nShapeType = SHPT_MULTIPOINTM;
     else if( eType == wkbMultiPointZM )
         nShapeType = SHPT_MULTIPOINTZ;
+    else if( wkbFlatten(eType) == wkbTIN ||
+             wkbFlatten(eType) == wkbPolyhedralSurface )
+        nShapeType = SHPT_MULTIPATCH;
     else if( eType == wkbNone )
         nShapeType = SHPT_NULL;
-    else
-        nShapeType = -1;
 
 /* -------------------------------------------------------------------- */
 /*      Has the application overridden this with a special creation     */
@@ -531,7 +544,9 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
     const char *pszOverride = CSLFetchNameValue( papszOptions, "SHPT" );
 
     if( pszOverride == NULL )
+    {
         /* ignore */;
+    }
     else if( EQUAL(pszOverride,"POINT") )
     {
         nShapeType = SHPT_POINT;
@@ -612,6 +627,11 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
         nShapeType = SHPT_MULTIPOINTZ;
         eType = wkbMultiPointZM;
     }
+    else if( EQUAL(pszOverride,"MULTIPATCH") )
+    {
+        nShapeType = SHPT_MULTIPATCH;
+        eType = wkbUnknown; // not ideal...
+    }
     else if( EQUAL(pszOverride,"NONE") || EQUAL(pszOverride,"NULL") )
     {
         nShapeType = SHPT_NULL;
@@ -620,8 +640,8 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
     else
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Unknown SHPT value of `%s' passed to Shapefile layer\n"
-                  "creation.  Creation aborted.\n",
+                  "Unknown SHPT value of `%s' passed to Shapefile layer"
+                  "creation.  Creation aborted.",
                   pszOverride );
 
         return NULL;
@@ -630,9 +650,10 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
     if( nShapeType == -1 )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Geometry type of `%s' not supported in shapefiles.\n"
-                  "Type can be overridden with a layer creation option\n"
-                  "of SHPT=POINT/ARC/POLYGON/MULTIPOINT/POINTZ/ARCZ/POLYGONZ/MULTIPOINTZ.\n",
+                  "Geometry type of `%s' not supported in shapefiles.  "
+                  "Type can be overridden with a layer creation option "
+                  "of SHPT=POINT/ARC/POLYGON/MULTIPOINT/POINTZ/ARCZ/POLYGONZ/"
+                  "MULTIPOINTZ/MULTIPATCH.",
                   OGRGeometryTypeToName(eType) );
         return NULL;
     }
@@ -640,51 +661,57 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      What filename do we use, excluding the extension?               */
 /* -------------------------------------------------------------------- */
-    char *pszFilenameWithoutExt;
+    char *pszFilenameWithoutExt = NULL;
 
-    if(  bSingleFileDataSource && nLayers == 0 )
+    if( bSingleFileDataSource && nLayers == 0 )
     {
         char *pszPath = CPLStrdup(CPLGetPath(pszName));
         char *pszFBasename = CPLStrdup(CPLGetBasename(pszName));
 
-        pszFilenameWithoutExt = CPLStrdup(CPLFormFilename(pszPath, pszFBasename, NULL));
+        pszFilenameWithoutExt =
+            CPLStrdup(CPLFormFilename(pszPath, pszFBasename, NULL));
 
         CPLFree( pszFBasename );
         CPLFree( pszPath );
     }
-    else if(  bSingleFileDataSource )
+    else if( bSingleFileDataSource )
     {
-        /* This is a very weird use case : the user creates/open a datasource */
-        /* made of a single shapefile 'foo.shp' and wants to add a new layer */
-        /* to it, 'bar'. So we create a new shapefile 'bar.shp' in the same */
-        /* directory as 'foo.shp' */
-        /* So technically, we will not be any longer a single file */
-        /* datasource ... Ahem ahem */
+        // This is a very weird use case : the user creates/open a datasource
+        // made of a single shapefile 'foo.shp' and wants to add a new layer
+        // to it, 'bar'. So we create a new shapefile 'bar.shp' in the same
+        // directory as 'foo.shp'
+        // So technically, we will not be any longer a single file
+        // datasource ... Ahem ahem.
         char *pszPath = CPLStrdup(CPLGetPath(pszName));
-        pszFilenameWithoutExt = CPLStrdup(CPLFormFilename(pszPath,pszLayerName,NULL));
+        pszFilenameWithoutExt =
+            CPLStrdup(CPLFormFilename(pszPath, pszLayerName, NULL));
         CPLFree( pszPath );
     }
     else
-        pszFilenameWithoutExt = CPLStrdup(CPLFormFilename(pszName,pszLayerName,NULL));
+    {
+        pszFilenameWithoutExt =
+            CPLStrdup(CPLFormFilename(pszName, pszLayerName, NULL));
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Create the shapefile.                                           */
 /* -------------------------------------------------------------------- */
-    char        *pszFilename;
+    const bool l_b2GBLimit =
+        CPLTestBool(CSLFetchNameValueDef( papszOptions, "2GB_LIMIT", "FALSE" ));
 
-    int l_b2GBLimit = CPLTestBool(CSLFetchNameValueDef( papszOptions, "2GB_LIMIT", "FALSE" ));
+    SHPHandle hSHP = NULL;
 
     if( nShapeType != SHPT_NULL )
     {
-        pszFilename = CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "shp" ));
+        char *pszFilename =
+            CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "shp" ));
 
-        hSHP = SHPCreateLL( pszFilename, nShapeType, (SAHooks*) VSI_SHP_GetHook(l_b2GBLimit) );
+        hSHP = SHPCreateLL(
+            pszFilename, nShapeType,
+            const_cast<SAHooks *>(VSI_SHP_GetHook(l_b2GBLimit)) );
 
         if( hSHP == NULL )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Failed to open Shapefile `%s'.\n",
-                      pszFilename );
             CPLFree( pszFilename );
             CPLFree( pszFilenameWithoutExt );
             return NULL;
@@ -694,8 +721,6 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
 
         CPLFree( pszFilename );
     }
-    else
-        hSHP = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Has a specific LDID been specified by the caller?               */
@@ -705,17 +730,17 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Create a DBF file.                                              */
 /* -------------------------------------------------------------------- */
-    pszFilename = CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "dbf" ));
+    char *pszFilename =
+        CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "dbf" ));
 
-    if( pszLDID != NULL )
-        hDBF = DBFCreateLL( pszFilename, pszLDID, (SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
-    else
-        hDBF = DBFCreateLL( pszFilename, "LDID/87",(SAHooks*) VSI_SHP_GetHook(b2GBLimit) );
+    DBFHandle hDBF =
+        DBFCreateLL( pszFilename, (pszLDID != NULL) ? pszLDID : "LDID/87",
+                     const_cast<SAHooks *>(VSI_SHP_GetHook(b2GBLimit)) );
 
     if( hDBF == NULL )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
-                  "Failed to open Shape DBF file `%s'.\n",
+                  "Failed to open Shape DBF file `%s'.",
                   pszFilename );
         CPLFree( pszFilename );
         CPLFree( pszFilenameWithoutExt );
@@ -730,14 +755,15 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
     if( poSRS != NULL )
     {
-        char    *pszWKT = NULL;
-        CPLString osPrjFile = CPLFormFilename( NULL, pszFilenameWithoutExt, "prj");
-        VSILFILE    *fp;
+        CPLString osPrjFile =
+            CPLFormFilename( NULL, pszFilenameWithoutExt, "prj");
 
-        /* the shape layer needs it's own copy */
+        // The shape layer needs its own copy.
         poSRS = poSRS->Clone();
         poSRS->morphToESRI();
 
+        char *pszWKT = NULL;
+        VSILFILE *fp = NULL;
         if( poSRS->exportToWkt( &pszWKT ) == OGRERR_NONE
             && (fp = VSIFOpenL( osPrjFile, "wt" )) != NULL )
         {
@@ -753,23 +779,29 @@ OGRShapeDataSource::ICreateLayer( const char * pszLayerName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRShapeLayer       *poLayer;
+    // OGRShapeLayer constructor expects a filename with an extension (that
+    // could be random actually), otherwise this is going to cause problems with
+    // layer names that have a dot (not speaking about the one before the shp)
+    pszFilename =
+        CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "shp" ));
 
-    /* OGRShapeLayer constructor expects a filename with an extension (that could be */
-    /* random actually), otherwise this is going to cause problems with layer */
-    /* names that have a dot (not speaking about the one before the shp) */
-    pszFilename = CPLStrdup(CPLFormFilename( NULL, pszFilenameWithoutExt, "shp" ));
-
-    poLayer = new OGRShapeLayer( this, pszFilename, hSHP, hDBF, poSRS, TRUE, TRUE,
-                                 eType );
+    OGRShapeLayer *poLayer =
+        new OGRShapeLayer( this, pszFilename, hSHP, hDBF, poSRS,
+                           true, true, eType );
 
     CPLFree( pszFilenameWithoutExt );
     CPLFree( pszFilename );
 
-    poLayer->SetResizeAtClose( CSLFetchBoolean( papszOptions, "RESIZE", FALSE ) );
-    poLayer->CreateSpatialIndexAtClose( CSLFetchBoolean( papszOptions, "SPATIAL_INDEX", FALSE ) );
+    poLayer->SetResizeAtClose(
+        CPLFetchBool( papszOptions, "RESIZE", false ) );
+    poLayer->CreateSpatialIndexAtClose(
+        CPLFetchBool( papszOptions, "SPATIAL_INDEX", false ) );
     poLayer->SetModificationDate(
         CSLFetchNameValue( papszOptions, "DBF_DATE_LAST_UPDATE" ) );
+    poLayer->SetAutoRepack(
+        CPLFetchBool( papszOptions, "AUTO_REPACK", true ) );
+    poLayer->SetWriteDBFEOFChar(
+        CPLFetchBool( papszOptions, "DBF_EOF_CHAR", true ) );
 
 /* -------------------------------------------------------------------- */
 /*      Add layer to data source layer list.                            */
@@ -788,12 +820,14 @@ int OGRShapeDataSource::TestCapability( const char * pszCap )
 {
     if( EQUAL(pszCap,ODsCCreateLayer) )
         return bDSUpdate;
-    else if( EQUAL(pszCap,ODsCDeleteLayer) )
+    if( EQUAL(pszCap,ODsCDeleteLayer) )
         return bDSUpdate;
-    else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
+    if( EQUAL(pszCap,ODsCMeasuredGeometries) )
         return TRUE;
-    else
-        return FALSE;
+    if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return bDSUpdate;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -804,27 +838,28 @@ int OGRShapeDataSource::GetLayerCount()
 
 {
 #ifndef IMMEDIATE_OPENING
-    if (oVectorLayerName.size() != 0)
+    if( !oVectorLayerName.empty() )
     {
-        for(size_t i = 0; i < oVectorLayerName.size(); i++)
+        for( size_t i = 0; i < oVectorLayerName.size(); i++ )
         {
             const char* pszFilename = oVectorLayerName[i].c_str();
             const char* pszLayerName = CPLGetBasename(pszFilename);
 
-            int j;
-            for(j=0;j<nLayers;j++)
+            int j = 0;  // Used after for.
+            for( ; j < nLayers; j++ )
             {
-                if (strcmp(papoLayers[j]->GetName(), pszLayerName) == 0)
+                if( strcmp(papoLayers[j]->GetName(), pszLayerName) == 0 )
                     break;
             }
-            if (j < nLayers)
+            if( j < nLayers )
                 continue;
 
-            if( !OpenFile( pszFilename, bDSUpdate, TRUE ) )
+            if( !OpenFile( pszFilename, bDSUpdate ) )
             {
                 CPLError( CE_Failure, CPLE_OpenFailed,
-                          "Failed to open file %s.\n"
-                          "It may be corrupt or read-only file accessed in update mode.\n",
+                          "Failed to open file %s."
+                          "It may be corrupt or read-only file accessed in "
+                          "update mode.",
                           pszFilename );
             }
         }
@@ -842,26 +877,25 @@ int OGRShapeDataSource::GetLayerCount()
 OGRLayer *OGRShapeDataSource::GetLayer( int iLayer )
 
 {
-    /* To ensure that existing layers are created */
+    // To ensure that existing layers are created.
     GetLayerCount();
 
     if( iLayer < 0 || iLayer >= nLayers )
         return NULL;
-    else
-        return papoLayers[iLayer];
+
+    return papoLayers[iLayer];
 }
 
 /************************************************************************/
 /*                           GetLayerByName()                           */
 /************************************************************************/
 
-OGRLayer *OGRShapeDataSource::GetLayerByName(const char * pszLayerNameIn)
+OGRLayer *OGRShapeDataSource::GetLayerByName( const char * pszLayerNameIn )
 {
 #ifndef IMMEDIATE_OPENING
-    if (oVectorLayerName.size() != 0)
+    if( !oVectorLayerName.empty() )
     {
-        int j;
-        for(j=0;j<nLayers;j++)
+        for( int j = 0; j < nLayers; j++ )
         {
             if (strcmp(papoLayers[j]->GetName(), pszLayerNameIn) == 0)
             {
@@ -869,37 +903,35 @@ OGRLayer *OGRShapeDataSource::GetLayerByName(const char * pszLayerNameIn)
             }
         }
 
-        size_t i;
-        for(j = 0; j < 2; j++)
+        for( int j = 0; j < 2; j++ )
         {
-            for(i = 0; i < oVectorLayerName.size(); i++)
+            for( size_t i = 0; i < oVectorLayerName.size(); i++ )
             {
                 const char* pszFilename = oVectorLayerName[i].c_str();
                 const char* pszLayerName = CPLGetBasename(pszFilename);
 
-                if (j == 0)
+                if( j == 0 )
                 {
-                    if (strcmp(pszLayerName, pszLayerNameIn) != 0)
+                    if(strcmp(pszLayerName, pszLayerNameIn) != 0)
                         continue;
                 }
                 else
                 {
-                    if ( !EQUAL(pszLayerName, pszLayerNameIn) )
+                    if( !EQUAL(pszLayerName, pszLayerNameIn) )
                         continue;
                 }
 
-                if( !OpenFile( pszFilename, bDSUpdate, TRUE ) )
+                if( !OpenFile( pszFilename, bDSUpdate ) )
                 {
                     CPLError( CE_Failure, CPLE_OpenFailed,
-                            "Failed to open file %s.\n"
-                            "It may be corrupt or read-only file accessed in update mode.\n",
-                            pszFilename );
+                              "Failed to open file %s.  "
+                              "It may be corrupt or read-only file accessed in "
+                              "update mode.",
+                              pszFilename );
                     return NULL;
                 }
-                else
-                {
-                    return papoLayers[nLayers - 1];
-                }
+
+                return papoLayers[nLayers - 1];
             }
         }
 
@@ -932,8 +964,8 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /* ==================================================================== */
     if( STARTS_WITH_CI(pszStatement, "REPACK ") )
     {
-        OGRShapeLayer *poLayer = (OGRShapeLayer *)
-            GetLayerByName( pszStatement + 7 );
+        OGRShapeLayer *poLayer = dynamic_cast<OGRShapeLayer *>(
+            GetLayerByName( pszStatement + 7 ));
 
         if( poLayer != NULL )
         {
@@ -958,11 +990,13 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /* ==================================================================== */
     if( STARTS_WITH_CI(pszStatement, "RESIZE ") )
     {
-        OGRShapeLayer *poLayer = (OGRShapeLayer *)
-            GetLayerByName( pszStatement + 7 );
+        OGRShapeLayer *poLayer = dynamic_cast<OGRShapeLayer *>(
+            GetLayerByName( pszStatement + 7 ));
 
         if( poLayer != NULL )
+        {
             poLayer->ResizeDBF();
+        }
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -977,11 +1011,13 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /* ==================================================================== */
     if( STARTS_WITH_CI(pszStatement, "RECOMPUTE EXTENT ON ") )
     {
-        OGRShapeLayer *poLayer = (OGRShapeLayer *)
-            GetLayerByName( pszStatement + 20 );
+        OGRShapeLayer *poLayer = dynamic_cast<OGRShapeLayer *>(
+            GetLayerByName( pszStatement + 20 ));
 
         if( poLayer != NULL )
+        {
             poLayer->RecomputeExtent();
+        }
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -996,11 +1032,13 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /* ==================================================================== */
     if( STARTS_WITH_CI(pszStatement, "DROP SPATIAL INDEX ON ") )
     {
-        OGRShapeLayer *poLayer = (OGRShapeLayer *)
-            GetLayerByName( pszStatement + 22 );
+        OGRShapeLayer *poLayer = dynamic_cast<OGRShapeLayer *>(
+            GetLayerByName( pszStatement + 22 ));
 
         if( poLayer != NULL )
+        {
             poLayer->DropSpatialIndex();
+        }
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -1021,8 +1059,9 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
             && EQUAL(papszTokens[1],"INDEX")
             && EQUAL(papszTokens[2],"ON") )
         {
-            OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[3]);
-            if (poLayer != NULL)
+            OGRShapeLayer *poLayer = dynamic_cast<OGRShapeLayer *>(
+                GetLayerByName(papszTokens[3]));
+            if( poLayer != NULL )
                 poLayer->InitializeIndexSupport( poLayer->GetFullName() );
         }
         CSLDestroy( papszTokens );
@@ -1057,14 +1096,14 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
 /* -------------------------------------------------------------------- */
 /*      Get depth if provided.                                          */
 /* -------------------------------------------------------------------- */
-    int nDepth = 0;
-    if( CSLCount(papszTokens) == 7 )
-        nDepth = atoi(papszTokens[6]);
+    const int nDepth =
+        CSLCount(papszTokens) == 7 ? atoi(papszTokens[6]) : 0;
 
 /* -------------------------------------------------------------------- */
 /*      What layer are we operating on.                                 */
 /* -------------------------------------------------------------------- */
-    OGRShapeLayer *poLayer = (OGRShapeLayer *) GetLayerByName(papszTokens[4]);
+    OGRShapeLayer *poLayer = dynamic_cast<OGRShapeLayer *>(
+        GetLayerByName(papszTokens[4]));
 
     if( poLayer == NULL )
     {
@@ -1081,7 +1120,6 @@ OGRLayer * OGRShapeDataSource::ExecuteSQL( const char *pszStatement,
     return NULL;
 }
 
-
 /************************************************************************/
 /*                            DeleteLayer()                             */
 /************************************************************************/
@@ -1095,7 +1133,7 @@ OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
     if( !bDSUpdate )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
-                  "Data source %s opened read-only.\n"
+                  "Data source %s opened read-only.  "
                   "Layer %d cannot be deleted.",
                   pszName, iLayer );
 
@@ -1110,9 +1148,9 @@ OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
         return OGRERR_FAILURE;
     }
 
-    OGRShapeLayer* poLayerToDelete = (OGRShapeLayer*) papoLayers[iLayer];
+    OGRShapeLayer* poLayerToDelete = papoLayers[iLayer];
 
-    char *pszFilename = CPLStrdup(poLayerToDelete->GetFullName());
+    char * const pszFilename = CPLStrdup(poLayerToDelete->GetFullName());
 
     delete poLayerToDelete;
 
@@ -1141,20 +1179,20 @@ OGRErr OGRShapeDataSource::DeleteLayer( int iLayer )
 
 void OGRShapeDataSource::SetLastUsedLayer( OGRShapeLayer* poLayer )
 {
-    /* We could remove that check and things would still work in */
-    /* 99.99% cases */
-    /* The only rationale for that test is to avoid breaking applications */
-    /* that would deal with layers of the same datasource in different */
-    /* threads. In GDAL < 1.9.0, this would work in most cases I can */
-    /* imagine as shapefile layers are pretty much independent from each */
-    /* others (although it has never been guaranteed to be a valid use case, */
-    /* and the shape driver is likely more the exception than the rule in */
-    /* permitting accessing layers from different threads !) */
-    /* Anyway the LRU list mechanism leaves the door open to concurrent accesses to it */
-    /* so when the datasource has not many layers, we don't try to build the */
-    /* LRU list to avoid concurrency issues. I haven't bothered making the analysis */
-    /* of how a mutex could be used to protect that (my intuition is that it would */
-    /* need to be placed at the beginning of OGRShapeLayer::TouchLayer() ) */
+    // We could remove that check and things would still work in
+    // 99.99% cases.
+    // The only rationale for that test is to avoid breaking applications that
+    // would deal with layers of the same datasource in different threads. In
+    // GDAL < 1.9.0, this would work in most cases I can imagine as shapefile
+    // layers are pretty much independent from each others (although it has
+    // never been guaranteed to be a valid use case, and the shape driver is
+    // likely more the exception than the rule in permitting accessing layers
+    // from different threads !)  Anyway the LRU list mechanism leaves the door
+    // open to concurrent accesses to it so when the datasource has not many
+    // layers, we don't try to build the LRU list to avoid concurrency issues. I
+    // haven't bothered making the analysis of how a mutex could be used to
+    // protect that (my intuition is that it would need to be placed at the
+    // beginning of OGRShapeLayer::TouchLayer() ).
     if (nLayers < poPool->GetMaxSimultaneouslyOpened())
         return;
 
@@ -1162,14 +1200,14 @@ void OGRShapeDataSource::SetLastUsedLayer( OGRShapeLayer* poLayer )
 }
 
 /************************************************************************/
-/*                            GetFileList()                             */
+//                            GetFileList()                             */
 /************************************************************************/
 
 char** OGRShapeDataSource::GetFileList()
 {
-    CPLStringList       oFileList;
+    CPLStringList oFileList;
     GetLayerCount();
-    for(int i=0;i<nLayers;i++)
+    for( int i = 0; i < nLayers; i++ )
     {
         OGRShapeLayer* poLayer = papoLayers[i];
         poLayer->AddToFileList(oFileList);
diff --git a/ogr/ogrsf_frmts/shape/ogrshapedriver.cpp b/ogr/ogrsf_frmts/shape/ogrshapedriver.cpp
index 10b35f4..1e18093 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapedriver.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapedriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrshapedriver.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeDriver class.
@@ -28,10 +27,12 @@
  ****************************************************************************/
 
 #include "ogrshape.h"
+
 #include "cpl_conv.h"
 #include "cpl_string.h"
+#include "ogrsf_frmts.h"
 
-CPL_CVSID("$Id: ogrshapedriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrshapedriver.cpp 36883 2016-12-15 13:31:12Z rouault $");
 
 /************************************************************************/
 /*                              Identify()                              */
@@ -39,11 +40,11 @@ CPL_CVSID("$Id: ogrshapedriver.cpp 33713 2016-03-12 17:41:57Z goatbar $");
 
 static int OGRShapeDriverIdentify( GDALOpenInfo* poOpenInfo )
 {
-    /* Files not ending with .shp, .shx or .dbf are not handled by this driver */
+    // Files not ending with .shp, .shx or .dbf are not handled by this driver.
     if( !poOpenInfo->bStatOK )
         return FALSE;
     if( poOpenInfo->bIsDirectory )
-        return -1; /* unsure */
+        return -1;  // Unsure.
     if( poOpenInfo->fpL == NULL )
     {
         return FALSE;
@@ -59,23 +60,23 @@ static int OGRShapeDriverIdentify( GDALOpenInfo* poOpenInfo )
         if( poOpenInfo->nHeaderBytes < 32 )
             return FALSE;
         const GByte* pabyBuf = poOpenInfo->pabyHeader;
-        unsigned int nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
-        unsigned int nRecordLength = pabyBuf[10] + pabyBuf[11]*256;
+        const unsigned int nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
+        const unsigned int nRecordLength = pabyBuf[10] + pabyBuf[11]*256;
         if( nHeadLen < 32 )
             return FALSE;
         // The header length of some .dbf files can be a non-multiple of 32
         // See https://trac.osgeo.org/gdal/ticket/6035
         // Hopefully there are not so many .dbf files around that are not real
         // DBFs
-        //if( (nHeadLen % 32) != 0 && (nHeadLen % 32) != 1 )
-        //    return FALSE;
-        unsigned int nFields = (nHeadLen - 32) / 32;
+        // if( (nHeadLen % 32) != 0 && (nHeadLen % 32) != 1 )
+        //     return FALSE;
+        const unsigned int nFields = (nHeadLen - 32) / 32;
         if( nRecordLength < nFields )
             return FALSE;
         return TRUE;
     }
 #ifdef DEBUG
-    /* For AFL, so that .cur_input is detected as the archive filename */
+    // For AFL, so that .cur_input is detected as the archive filename.
     if( !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
         EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") )
     {
@@ -92,33 +93,32 @@ static int OGRShapeDriverIdentify( GDALOpenInfo* poOpenInfo )
 static GDALDataset *OGRShapeDriverOpen( GDALOpenInfo* poOpenInfo )
 
 {
-    OGRShapeDataSource  *poDS;
-
     if( OGRShapeDriverIdentify(poOpenInfo) == FALSE )
         return NULL;
 
 #ifdef DEBUG
-    /* For AFL, so that .cur_input is detected as the archive filename */
+    // For AFL, so that .cur_input is detected as the archive filename.
     if( poOpenInfo->fpL != NULL &&
         !STARTS_WITH(poOpenInfo->pszFilename, "/vsitar/") &&
         EQUAL(CPLGetFilename(poOpenInfo->pszFilename), ".cur_input") )
     {
-        GDALOpenInfo oOpenInfo( (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
-                                poOpenInfo->nOpenFlags );
+        GDALOpenInfo oOpenInfo(
+            (CPLString("/vsitar/") + poOpenInfo->pszFilename).c_str(),
+            poOpenInfo->nOpenFlags );
         oOpenInfo.papszOpenOptions = poOpenInfo->papszOpenOptions;
         return OGRShapeDriverOpen(&oOpenInfo);
     }
 #endif
 
-    poDS = new OGRShapeDataSource();
+    OGRShapeDataSource *poDS = new OGRShapeDataSource();
 
-    if( !poDS->Open( poOpenInfo, TRUE ) )
+    if( !poDS->Open( poOpenInfo, true ) )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -126,24 +126,24 @@ static GDALDataset *OGRShapeDriverOpen( GDALOpenInfo* poOpenInfo )
 /************************************************************************/
 
 static GDALDataset *OGRShapeDriverCreate( const char * pszName,
-                                          CPL_UNUSED int nBands,
-                                          CPL_UNUSED int nXSize,
-                                          CPL_UNUSED int nYSize,
-                                          CPL_UNUSED GDALDataType eDT,
-                                          CPL_UNUSED char **papszOptions )
+                                           int /* nBands */,
+                                           int /* nXSize */,
+                                           int /* nYSize */,
+                                           GDALDataType /* eDT */,
+                                           char ** /* papszOptions */ )
 {
-    VSIStatBuf  stat;
-    int         bSingleNewFile = FALSE;
+    bool bSingleNewFile = false;
 
 /* -------------------------------------------------------------------- */
 /*      Is the target a valid existing directory?                       */
 /* -------------------------------------------------------------------- */
+    VSIStatBuf stat;
     if( CPLStat( pszName, &stat ) == 0 )
     {
         if( !VSI_ISDIR(stat.st_mode) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "%s is not a directory.\n",
+                      "%s is not a directory.",
                       pszName );
 
             return NULL;
@@ -154,10 +154,10 @@ static GDALDataset *OGRShapeDriverCreate( const char * pszName,
 /*      Does it end in the extension .shp indicating the user likely    */
 /*      wants to create a single file set?                              */
 /* -------------------------------------------------------------------- */
-    else if( EQUAL(CPLGetExtension(pszName),"shp")
-             || EQUAL(CPLGetExtension(pszName),"dbf") )
+    else if( EQUAL(CPLGetExtension(pszName), "shp")
+             || EQUAL(CPLGetExtension(pszName), "dbf") )
     {
-        bSingleNewFile = TRUE;
+        bSingleNewFile = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -168,8 +168,8 @@ static GDALDataset *OGRShapeDriverCreate( const char * pszName,
         if( VSIMkdir( pszName, 0755 ) != 0 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Failed to create directory %s\n"
-                      "for shapefile datastore.\n",
+                      "Failed to create directory %s "
+                      "for shapefile datastore.",
                       pszName );
 
             return NULL;
@@ -179,18 +179,16 @@ static GDALDataset *OGRShapeDriverCreate( const char * pszName,
 /* -------------------------------------------------------------------- */
 /*      Return a new OGRDataSource()                                    */
 /* -------------------------------------------------------------------- */
-    OGRShapeDataSource  *poDS = NULL;
-
-    poDS = new OGRShapeDataSource();
+    OGRShapeDataSource  *poDS = new OGRShapeDataSource();
 
     GDALOpenInfo oOpenInfo( pszName, GA_Update );
-    if( !poDS->Open( &oOpenInfo, FALSE, bSingleNewFile ) )
+    if( !poDS->Open( &oOpenInfo, false, bSingleNewFile ) )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -200,11 +198,7 @@ static GDALDataset *OGRShapeDriverCreate( const char * pszName,
 static CPLErr OGRShapeDriverDelete( const char *pszDataSource )
 
 {
-    int iExt;
     VSIStatBufL sStatBuf;
-    static const char * const apszExtensions[] =
-        { "shp", "shx", "dbf", "sbn", "sbx", "prj", "idm", "ind",
-          "qix", "cpg", NULL };
 
     if( VSIStatL( pszDataSource, &sStatBuf ) != 0 )
     {
@@ -215,15 +209,19 @@ static CPLErr OGRShapeDriverDelete( const char *pszDataSource )
         return CE_Failure;
     }
 
+    static const char * const apszExtensions[] =
+        { "shp", "shx", "dbf", "sbn", "sbx", "prj", "idm", "ind",
+          "qix", "cpg", NULL };
+
     if( VSI_ISREG(sStatBuf.st_mode)
-        && (EQUAL(CPLGetExtension(pszDataSource),"shp")
-            || EQUAL(CPLGetExtension(pszDataSource),"shx")
-            || EQUAL(CPLGetExtension(pszDataSource),"dbf")) )
+        && (EQUAL(CPLGetExtension(pszDataSource), "shp")
+            || EQUAL(CPLGetExtension(pszDataSource), "shx")
+            || EQUAL(CPLGetExtension(pszDataSource), "dbf")) )
     {
-        for( iExt=0; apszExtensions[iExt] != NULL; iExt++ )
+        for( int iExt = 0; apszExtensions[iExt] != NULL; iExt++ )
         {
             const char *pszFile = CPLResetExtension(pszDataSource,
-                                                    apszExtensions[iExt] );
+                                                    apszExtensions[iExt]);
             if( VSIStatL( pszFile, &sStatBuf ) == 0 )
                 VSIUnlink( pszFile );
         }
@@ -231,13 +229,12 @@ static CPLErr OGRShapeDriverDelete( const char *pszDataSource )
     else if( VSI_ISDIR(sStatBuf.st_mode) )
     {
         char **papszDirEntries = VSIReadDir( pszDataSource );
-        int  iFile;
 
-        for( iFile = 0;
+        for( int iFile = 0;
              papszDirEntries != NULL && papszDirEntries[iFile] != NULL;
              iFile++ )
         {
-            if( CSLFindString( (char **) apszExtensions,
+            if( CSLFindString( apszExtensions,
                                CPLGetExtension(papszDirEntries[iFile])) != -1)
             {
                 VSIUnlink( CPLFormFilename( pszDataSource,
@@ -283,6 +280,8 @@ void RegisterOGRShape()
 "    <Value>FIRST_SHAPE</Value>"
 "    <Value>ALL_SHAPES</Value>"
 "  </Option>"
+"  <Option name='AUTO_REPACK' type='boolean' description='Whether the shapefile should be automatically repacked when needed' default='YES'/>"
+"  <Option name='DBF_EOF_CHAR' type='boolean' description='Whether to write the 0x1A end-of-file character in DBF files' default='YES'/>"
 "</OpenOptionList>");
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
@@ -306,6 +305,7 @@ void RegisterOGRShape()
 "    <Value>ARCZM</Value>"
 "    <Value>POLYGONZM</Value>"
 "    <Value>MULTIPOINTZM</Value>"
+"    <Value>MULTIPATCH</Value>"
 "    <Value>NONE</Value>"
 "    <Value>NULL</Value>"
 "  </Option>"
@@ -314,6 +314,8 @@ void RegisterOGRShape()
 "  <Option name='RESIZE' type='boolean' description='To resize fields to their optimal size.' default='NO'/>"
 "  <Option name='SPATIAL_INDEX' type='boolean' description='To create a spatial index.' default='NO'/>"
 "  <Option name='DBF_DATE_LAST_UPDATE' type='string' description='Modification date to write in DBF header with YYYY-MM-DD format'/>"
+"  <Option name='AUTO_REPACK' type='boolean' description='Whether the shapefile should be automatically repacked when needed' default='YES'/>"
+"  <Option name='DBF_EOF_CHAR' type='boolean' description='Whether to write the 0x1A end-of-file character in DBF files' default='YES'/>"
 "</LayerCreationOptionList>");
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
diff --git a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
index 749331d..4c8fa16 100644
--- a/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
+++ b/ogr/ogrsf_frmts/shape/ogrshapelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrshapelayer.cpp 35625 2016-10-06 13:59:48Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRShapeLayer class.
@@ -29,18 +28,18 @@
  ****************************************************************************/
 
 #include "ogrshape.h"
+
 #include "cpl_conv.h"
 #include "cpl_string.h"
-#include "ogr_p.h"
 #include "cpl_time.h"
+#include "ogr_p.h"
 
-#define FD_OPENED           0
-#define FD_CLOSED           1
-#define FD_CANNOT_REOPEN    2
+#include <algorithm>
 
-#define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
+static const char UNSUPPORTED_OP_READ_ONLY[] =
+    "%s : unsupported operation on a read-only datasource.";
 
-CPL_CVSID("$Id: ogrshapelayer.cpp 35625 2016-10-06 13:59:48Z rouault $");
+CPL_CVSID("$Id: ogrshapelayer.cpp 36883 2016-12-15 13:31:12Z rouault $");
 
 /************************************************************************/
 /*                           OGRShapeLayer()                            */
@@ -49,13 +48,15 @@ CPL_CVSID("$Id: ogrshapelayer.cpp 35625 2016-10-06 13:59:48Z rouault $");
 OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
                               const char * pszFullNameIn,
                               SHPHandle hSHPIn, DBFHandle hDBFIn,
-                              OGRSpatialReference *poSRSIn, int bSRSSetIn,
-                              int bUpdate,
+                              OGRSpatialReference *poSRSIn, bool bSRSSetIn,
+                              bool bUpdate,
                               OGRwkbGeometryType eReqType,
                               char ** papszCreateOptions ) :
     OGRAbstractProxiedLayer(poDSIn->GetPool()),
     poDS(poDSIn),
     iNextShapeId(0),
+    nTotalShapeCount(0),
+    pszFullName(CPLStrdup(pszFullNameIn)),
     hSHP(hSHPIn),
     hDBF(hDBFIn),
     bUpdateAccess(bUpdate),
@@ -65,35 +66,47 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
     m_poFilterGeomLastValid(NULL),
     nSpatialFIDCount(0),
     panSpatialFIDs(NULL),
-    bHeaderDirty(FALSE),
-    bSHPNeedsRepack(FALSE),
-    bCheckedForQIX(FALSE),
+    bHeaderDirty(false),
+    bSHPNeedsRepack(false),
+    bCheckedForQIX(false),
     hQIX(NULL),
-    bCheckedForSBN(FALSE),
+    bCheckedForSBN(false),
     hSBN(NULL),
-    bSbnSbxDeleted(FALSE),
-    bTruncationWarningEmitted(FALSE),
+    bSbnSbxDeleted(false),
+    bTruncationWarningEmitted(false),
+    bHSHPWasNonNULL(hSHPIn != NULL),
+    bHDBFWasNonNULL(hDBFIn != NULL),
     eFileDescriptorsState(FD_OPENED),
-    bResizeAtClose(FALSE),
-    bCreateSpatialIndexAtClose(FALSE)
+    bResizeAtClose(false),
+    bCreateSpatialIndexAtClose(false),
+    bRewindOnWrite(false),
+    m_bAutoRepack(false),
+    m_eNeedRepack(MAYBE)
 {
-    pszFullName = CPLStrdup(pszFullNameIn);
-
     if( hSHP != NULL )
     {
         nTotalShapeCount = hSHP->nRecords;
         if( hDBF != NULL && hDBF->nRecords != nTotalShapeCount )
         {
-            CPLDebug("Shape", "Inconsistent record number in .shp (%d) and in .dbf (%d)",
-                     hSHP->nRecords, hDBF->nRecords);
+            CPLDebug(
+                "Shape",
+                "Inconsistent record number in .shp (%d) and in .dbf (%d)",
+                hSHP->nRecords, hDBF->nRecords);
         }
     }
-    else
+    else if( hDBF != NULL )
+    {
         nTotalShapeCount = hDBF->nRecords;
+    }
+#ifdef DEBUG
+    else
+    {
+        CPLError(CE_Fatal, CPLE_AssertionFailed,
+                 "Should not happen: Both hSHP and hDBF are nullptrs");
+    }
+#endif
 
-    bHSHPWasNonNULL = hSHPIn != NULL;
-    bHDBFWasNonNULL = hDBFIn != NULL;
-    if (!TouchLayer())
+    if( !TouchLayer() )
     {
         CPLDebug("Shape", "TouchLayer in shape ctor failed. ");
     }
@@ -113,9 +126,11 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
               hDBF->nUpdateMonth == 7 &&
               hDBF->nUpdateDay == 26) )
         {
-            SetMetadataItem( "DBF_DATE_LAST_UPDATE", CPLSPrintf("%04d-%02d-%02d",
-                            hDBF->nUpdateYearSince1900 + 1900,
-                            hDBF->nUpdateMonth, hDBF->nUpdateDay) );
+            SetMetadataItem(
+                "DBF_DATE_LAST_UPDATE",
+                CPLSPrintf("%04d-%02d-%02d",
+                           hDBF->nUpdateYearSince1900 + 1900,
+                           hDBF->nUpdateMonth, hDBF->nUpdateDay) );
         }
         struct tm tm;
         CPLUnixTimeToYMDHMS(time(NULL), &tm);
@@ -136,49 +151,51 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
     {
         CPLDebug( "Shape", "Treating as encoding '%s'.", osEncoding.c_str() );
 
-        if (!TestCapability(OLCStringsAsUTF8))
+        if( !TestCapability(OLCStringsAsUTF8) )
         {
-            CPLDebug( "Shape", "Cannot recode from '%s'. Disabling recoding", osEncoding.c_str() );
+            CPLDebug( "Shape", "Cannot recode from '%s'. Disabling recoding",
+                      osEncoding.c_str() );
             osEncoding = "";
         }
     }
 
-    poFeatureDefn = SHPReadOGRFeatureDefn( CPLGetBasename(pszFullName),
-                                           hSHP, hDBF, osEncoding,
-               CSLFetchBoolean(poDS->GetOpenOptions(), "ADJUST_TYPE", FALSE) );
+    poFeatureDefn = SHPReadOGRFeatureDefn(
+        CPLGetBasename(pszFullName),
+        hSHP, hDBF, osEncoding,
+        CPLFetchBool(poDS->GetOpenOptions(), "ADJUST_TYPE", false) );
 
-    /* To make sure that GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef() == GetSpatialRef() */
+    // To make sure that
+    //  GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef() == GetSpatialRef()
     OGRwkbGeometryType eGeomType = poFeatureDefn->GetGeomType();
     if( eGeomType != wkbNone )
     {
-        OGRwkbGeometryType eType;
+        OGRwkbGeometryType eType = wkbUnknown;
 
         if( eRequestedGeomType == wkbNone )
         {
             eType = eGeomType;
 
             const char* pszAdjustGeomType = CSLFetchNameValueDef(
-                            poDS->GetOpenOptions(), "ADJUST_GEOM_TYPE", "FIRST_SHAPE");
+                poDS->GetOpenOptions(), "ADJUST_GEOM_TYPE", "FIRST_SHAPE");
             const bool bFirstShape = EQUAL(pszAdjustGeomType, "FIRST_SHAPE");
             const bool bAllShapes  = EQUAL(pszAdjustGeomType, "ALL_SHAPES");
             if( (hSHP != NULL) && (hSHP->nRecords > 0) && wkbHasM(eType) &&
                 (bFirstShape || bAllShapes) )
             {
                 bool bMIsUsed = false;
-                for(int iShape=0; iShape < hSHP->nRecords; iShape++)
+                for( int iShape=0; iShape < hSHP->nRecords; iShape++ )
                 {
-                    SHPObject   *psShape = SHPReadObject( hSHP, iShape );
+                    SHPObject *psShape = SHPReadObject( hSHP, iShape );
                     if( psShape )
                     {
                         if( psShape->bMeasureIsUsed &&
                             psShape->nVertices > 0 &&
                             psShape->padfM != NULL )
                         {
-                            for(int i=0;i<psShape->nVertices;i++)
+                            for( int i = 0; i < psShape->nVertices; i++ )
                             {
-                                /* Per the spec, if the M value is smaller than -1e38,
-                                 * it is a nodata value
-                                 */
+                                // Per the spec, if the M value is smaller than
+                                // -1e38, it is a nodata value.
                                 if( psShape->padfM[i] > -1e38 )
                                 {
                                     bMIsUsed = true;
@@ -197,18 +214,22 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
             }
         }
         else
+        {
             eType = eRequestedGeomType;
+        }
 
         OGRShapeGeomFieldDefn* poGeomFieldDefn =
-            //new OGRShapeGeomFieldDefn(pszFullName, eGeomType, bSRSSetIn, poSRSIn);
             new OGRShapeGeomFieldDefn(pszFullName, eType, bSRSSetIn, poSRSIn);
         poFeatureDefn->SetGeomType(wkbNone);
         poFeatureDefn->AddGeomFieldDefn(poGeomFieldDefn, FALSE);
     }
     else if( bSRSSetIn && poSRSIn != NULL )
+    {
         poSRSIn->Release();
+    }
     SetDescription( poFeatureDefn->GetName() );
-    bRewindOnWrite = CPLTestBool(CPLGetConfigOption( "SHAPE_REWIND_ON_WRITE", "YES" ));
+    bRewindOnWrite =
+        CPLTestBool(CPLGetConfigOption( "SHAPE_REWIND_ON_WRITE", "YES" ));
 }
 
 /************************************************************************/
@@ -218,6 +239,9 @@ OGRShapeLayer::OGRShapeLayer( OGRShapeDataSource* poDSIn,
 OGRShapeLayer::~OGRShapeLayer()
 
 {
+    if( m_eNeedRepack == YES && m_bAutoRepack )
+        Repack();
+
     if( bResizeAtClose && hDBF != NULL )
     {
         ResizeDBF();
@@ -230,7 +254,7 @@ OGRShapeLayer::~OGRShapeLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "Shape", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead,
+                  static_cast<int>(m_nFeaturesRead),
                   poFeatureDefn->GetName() );
     }
 
@@ -255,20 +279,21 @@ OGRShapeLayer::~OGRShapeLayer()
         SBNCloseDiskTree( hSBN );
 }
 
-
 /************************************************************************/
 /*                       SetModificationDate()                          */
 /************************************************************************/
 
-void OGRShapeLayer::SetModificationDate(const char* pszStr)
+void OGRShapeLayer::SetModificationDate( const char* pszStr )
 {
     if( hDBF && pszStr )
     {
-        int year, month, day;
-        if ((sscanf(pszStr, "%04d-%02d-%02d", &year, &month, &day) == 3 ||
+        int year = 0;
+        int month = 0;
+        int day = 0;
+        if( (sscanf(pszStr, "%04d-%02d-%02d", &year, &month, &day) == 3 ||
              sscanf(pszStr, "%04d/%02d/%02d", &year, &month, &day) == 3) &&
             (year >= 1900 && year <= 1900 + 255 && month >= 1 && month <= 12 &&
-             day >= 1 && day <= 31))
+             day >= 1 && day <= 31) )
         {
             DBFSetLastModifiedDate( hDBF, year - 1900, month, day );
         }
@@ -276,6 +301,18 @@ void OGRShapeLayer::SetModificationDate(const char* pszStr)
 }
 
 /************************************************************************/
+/*                       SetWriteDBFEOFChar()                           */
+/************************************************************************/
+
+void OGRShapeLayer::SetWriteDBFEOFChar( bool b )
+{
+    if( hDBF )
+    {
+        DBFSetWriteEndOfFileChar( hDBF, b );
+    }
+}
+
+/************************************************************************/
 /*                          ConvertCodePage()                           */
 /************************************************************************/
 
@@ -289,9 +326,9 @@ CPLString OGRShapeLayer::ConvertCodePage( const char *pszCodePage )
 
     if( STARTS_WITH_CI(pszCodePage, "LDID/") )
     {
-        int nCP = -1; // windows code page.
+        int nCP = -1;  // Windows code page.
 
-        //http://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTM
+        // http://www.autopark.ru/ASBProgrammerGuide/DBFSTRUC.HTM
         switch( atoi(pszCodePage+5) )
         {
           case 1: nCP = 437;      break;
@@ -387,7 +424,7 @@ CPLString OGRShapeLayer::ConvertCodePage( const char *pszCodePage )
     if( STARTS_WITH_CI(pszCodePage, "UTF-8") )
         return CPL_ENC_UTF8;
 
-    // try just using the CPG value directly.  Works for stuff like Big5.
+    // Try just using the CPG value directly.  Works for stuff like Big5.
     return pszCodePage;
 }
 
@@ -395,19 +432,17 @@ CPLString OGRShapeLayer::ConvertCodePage( const char *pszCodePage )
 /*                            CheckForQIX()                             */
 /************************************************************************/
 
-int OGRShapeLayer::CheckForQIX()
+bool OGRShapeLayer::CheckForQIX()
 
 {
-    const char *pszQIXFilename;
-
     if( bCheckedForQIX )
         return hQIX != NULL;
 
-    pszQIXFilename = CPLResetExtension( pszFullName, "qix" );
+    const char *pszQIXFilename = CPLResetExtension( pszFullName, "qix" );
 
     hQIX = SHPOpenDiskTree( pszQIXFilename, NULL );
 
-    bCheckedForQIX = TRUE;
+    bCheckedForQIX = true;
 
     return hQIX != NULL;
 }
@@ -416,19 +451,17 @@ int OGRShapeLayer::CheckForQIX()
 /*                            CheckForSBN()                             */
 /************************************************************************/
 
-int OGRShapeLayer::CheckForSBN()
+bool OGRShapeLayer::CheckForSBN()
 
 {
-    const char *pszSBNFilename;
-
     if( bCheckedForSBN )
         return hSBN != NULL;
 
-    pszSBNFilename = CPLResetExtension( pszFullName, "sbn" );
+    const char *pszSBNFilename = CPLResetExtension( pszFullName, "sbn" );
 
     hSBN = SBNOpenDiskTree( pszSBNFilename, NULL );
 
-    bCheckedForSBN = TRUE;
+    bCheckedForSBN = true;
 
     return hSBN != NULL;
 }
@@ -440,7 +473,7 @@ int OGRShapeLayer::CheckForSBN()
 /*      available.                                                      */
 /************************************************************************/
 
-int OGRShapeLayer::ScanIndices()
+bool OGRShapeLayer::ScanIndices()
 
 {
     iMatchingFID = 0;
@@ -454,8 +487,8 @@ int OGRShapeLayer::ScanIndices()
 
         InitializeIndexSupport( pszFullName );
 
-        panMatchingFIDs = m_poAttrQuery->EvaluateAgainstIndices( this,
-                                                                 NULL );
+        panMatchingFIDs =
+            m_poAttrQuery->EvaluateAgainstIndices( this, NULL );
     }
 
 /* -------------------------------------------------------------------- */
@@ -463,29 +496,30 @@ int OGRShapeLayer::ScanIndices()
 /* -------------------------------------------------------------------- */
 
     if( m_poFilterGeom == NULL || hSHP == NULL )
-        return TRUE;
+        return true;
 
     OGREnvelope oSpatialFilterEnvelope;
-    int bTryQIXorSBN = TRUE;
+    bool bTryQIXorSBN = true;
 
     m_poFilterGeom->getEnvelope( &oSpatialFilterEnvelope );
 
     OGREnvelope oLayerExtent;
-    if (GetExtent(&oLayerExtent, TRUE) == OGRERR_NONE)
+    if( GetExtent(&oLayerExtent, TRUE) == OGRERR_NONE )
     {
-        if (oSpatialFilterEnvelope.Contains(oLayerExtent))
+        if( oSpatialFilterEnvelope.Contains(oLayerExtent) )
         {
-            // The spatial filter is larger than the layer extent. No use of .qix file for now
-            return TRUE;
+            // The spatial filter is larger than the layer extent. No use of
+            // .qix file for now.
+            return true;
         }
-        else if (!oSpatialFilterEnvelope.Intersects(oLayerExtent))
+        else if( !oSpatialFilterEnvelope.Intersects(oLayerExtent) )
         {
-            /* No intersection : no need to check for .qix or .sbn */
-            bTryQIXorSBN = FALSE;
+            // No intersection : no need to check for .qix or .sbn.
+            bTryQIXorSBN = false;
 
-            /* Set an empty result for spatial FIDs */
+            // Set an empty result for spatial FIDs.
             free(panSpatialFIDs);
-            panSpatialFIDs = (int*) calloc(1, sizeof(int));
+            panSpatialFIDs = static_cast<int *>(calloc(1, sizeof(int)));
             nSpatialFIDCount = 0;
 
             delete m_poFilterGeomLastValid;
@@ -504,18 +538,19 @@ int OGRShapeLayer::ScanIndices()
 /* -------------------------------------------------------------------- */
 /*      Compute spatial index if appropriate.                           */
 /* -------------------------------------------------------------------- */
-    if( bTryQIXorSBN && (hQIX != NULL || hSBN != NULL) && panSpatialFIDs == NULL )
+    if( bTryQIXorSBN && (hQIX != NULL || hSBN != NULL) &&
+        panSpatialFIDs == NULL )
     {
-        double adfBoundsMin[4], adfBoundsMax[4];
-
-        adfBoundsMin[0] = oSpatialFilterEnvelope.MinX;
-        adfBoundsMin[1] = oSpatialFilterEnvelope.MinY;
-        adfBoundsMin[2] = 0.0;
-        adfBoundsMin[3] = 0.0;
-        adfBoundsMax[0] = oSpatialFilterEnvelope.MaxX;
-        adfBoundsMax[1] = oSpatialFilterEnvelope.MaxY;
-        adfBoundsMax[2] = 0.0;
-        adfBoundsMax[3] = 0.0;
+        double adfBoundsMin[4] = {
+            oSpatialFilterEnvelope.MinX,
+            oSpatialFilterEnvelope.MinY,
+            0.0,
+            0.0 };
+        double adfBoundsMax[4] = {
+            oSpatialFilterEnvelope.MaxX,
+            oSpatialFilterEnvelope.MaxY,
+            0.0,
+            0.0 };
 
         if( hQIX != NULL )
             panSpatialFIDs = SHPSearchDiskTreeEx( hQIX,
@@ -540,26 +575,23 @@ int OGRShapeLayer::ScanIndices()
     {
         // Use resulting list as matching FID list (but reallocate and
         // terminate with OGRNullFID).
-
         if( panMatchingFIDs == NULL )
         {
-            int i;
-
-            panMatchingFIDs = (GIntBig *)
-                CPLMalloc(sizeof(GIntBig) * (nSpatialFIDCount+1) );
-            for( i = 0; i < nSpatialFIDCount; i++ )
-                panMatchingFIDs[i] = (GIntBig) panSpatialFIDs[i];
+            panMatchingFIDs = static_cast<GIntBig *>(
+                CPLMalloc(sizeof(GIntBig) * (nSpatialFIDCount+1) ));
+            for( int i = 0; i < nSpatialFIDCount; i++ )
+              panMatchingFIDs[i] = static_cast<GIntBig>( panSpatialFIDs[i] );
             panMatchingFIDs[nSpatialFIDCount] = OGRNullFID;
         }
-
         // Cull attribute index matches based on those in the spatial index
         // result set.  We assume that the attribute results are in sorted
         // order.
         else
         {
-            int iRead, iWrite=0, iSpatial=0;
+            int iWrite = 0;
+            int iSpatial = 0;
 
-            for( iRead = 0; panMatchingFIDs[iRead] != OGRNullFID; iRead++ )
+            for( int iRead = 0; panMatchingFIDs[iRead] != OGRNullFID; iRead++ )
             {
                 while( iSpatial < nSpatialFIDCount
                        && panSpatialFIDs[iSpatial] < panMatchingFIDs[iRead] )
@@ -574,13 +606,13 @@ int OGRShapeLayer::ScanIndices()
             panMatchingFIDs[iWrite] = OGRNullFID;
         }
 
-        if (nSpatialFIDCount > 100000)
+        if( nSpatialFIDCount > 100000 )
         {
             ClearSpatialFIDs();
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -590,7 +622,7 @@ int OGRShapeLayer::ScanIndices()
 void OGRShapeLayer::ResetReading()
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return;
 
     iMatchingFID = 0;
@@ -620,7 +652,7 @@ void OGRShapeLayer::ClearMatchingFIDs()
 
 void OGRShapeLayer::ClearSpatialFIDs()
 {
-    if ( panSpatialFIDs != NULL )
+    if( panSpatialFIDs != NULL )
     {
         CPLDebug("SHAPE", "Clear panSpatialFIDs");
         free( panSpatialFIDs );
@@ -642,22 +674,21 @@ void OGRShapeLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
 
     if( poGeomIn == NULL )
     {
-        /* Do nothing */
+        // Do nothing.
     }
-    else if ( m_poFilterGeomLastValid != NULL &&
-              m_poFilterGeomLastValid->Equals(poGeomIn) )
+    else if( m_poFilterGeomLastValid != NULL &&
+             m_poFilterGeomLastValid->Equals(poGeomIn) )
     {
-        /* Do nothing */
+        // Do nothing.
     }
-    else if ( panSpatialFIDs != NULL )
+    else if( panSpatialFIDs != NULL )
     {
-        /* We clear the spatialFIDs only if we have a new non-NULL */
-        /* spatial filter, otherwise we keep the previous result */
-        /* cached. This can be useful when several SQL layers */
-        /* rely on the same table layer, and use the same spatial */
-        /* filters. But as there is in the destructor of OGRGenSQLResultsLayer */
-        /* a clearing of the spatial filter of the table layer, we */
-        /* need this trick. */
+        // We clear the spatialFIDs only if we have a new non-NULL spatial
+        // filter, otherwise we keep the previous result cached. This can be
+        // useful when several SQL layers rely on the same table layer, and use
+        // the same spatial filters. But as there is in the destructor of
+        // OGRGenSQLResultsLayer a clearing of the spatial filter of the table
+        // layer, we need this trick.
         ClearSpatialFIDs();
     }
 
@@ -685,7 +716,7 @@ OGRErr OGRShapeLayer::SetAttributeFilter( const char * pszAttributeFilter )
 OGRErr OGRShapeLayer::SetNextByIndex( GIntBig nIndex )
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( nIndex < 0 || nIndex > INT_MAX )
@@ -696,7 +727,7 @@ OGRErr OGRShapeLayer::SetNextByIndex( GIntBig nIndex )
     if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )
         return OGRLayer::SetNextByIndex( nIndex );
 
-    iNextShapeId = (int)nIndex;
+    iNextShapeId = static_cast<int>(nIndex);
 
     return OGRERR_NONE;
 }
@@ -708,16 +739,14 @@ OGRErr OGRShapeLayer::SetNextByIndex( GIntBig nIndex )
 /*      if the shapeid bbox intersects the geometry.                    */
 /************************************************************************/
 
-OGRFeature *OGRShapeLayer::FetchShape(int iShapeId /*, OGREnvelope* psShapeExtent */)
+OGRFeature *OGRShapeLayer::FetchShape( int iShapeId )
 
 {
-    OGRFeature *poFeature;
+    OGRFeature *poFeature = NULL;
 
-    if (m_poFilterGeom != NULL && hSHP != NULL )
+    if( m_poFilterGeom != NULL && hSHP != NULL )
     {
-        SHPObject   *psShape;
-
-        psShape = SHPReadObject( hSHP, iShapeId );
+        SHPObject *psShape = SHPReadObject( hSHP, iShapeId );
 
         // do not trust degenerate bounds on non-point geometries
         // or bounds on null shapes.
@@ -726,7 +755,7 @@ OGRFeature *OGRShapeLayer::FetchShape(int iShapeId /*, OGREnvelope* psShapeExten
                 && psShape->nSHPType != SHPT_POINTZ
                 && psShape->nSHPType != SHPT_POINTM
                 && (psShape->dfXMin == psShape->dfXMax
-                 || psShape->dfYMin == psShape->dfYMax))
+                    || psShape->dfYMin == psShape->dfYMax))
             || psShape->nSHPType == SHPT_NULL )
         {
             poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn,
@@ -742,10 +771,6 @@ OGRFeature *OGRShapeLayer::FetchShape(int iShapeId /*, OGREnvelope* psShapeExten
         }
         else
         {
-            /*psShapeExtent->MinX = psShape->dfXMin;
-            psShapeExtent->MinY = psShape->dfYMin;
-            psShapeExtent->MaxX = psShape->dfXMax;
-            psShapeExtent->MaxY = psShape->dfYMax;*/
             poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn,
                                            iShapeId, psShape, osEncoding );
         }
@@ -766,11 +791,9 @@ OGRFeature *OGRShapeLayer::FetchShape(int iShapeId /*, OGREnvelope* psShapeExten
 OGRFeature *OGRShapeLayer::GetNextFeature()
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return NULL;
 
-    OGRFeature  *poFeature = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Collect a matching list if we have attribute or spatial         */
 /*      indices.  Only do this on the first request for a given pass    */
@@ -785,10 +808,10 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
 /* -------------------------------------------------------------------- */
 /*      Loop till we find a feature matching our criteria.              */
 /* -------------------------------------------------------------------- */
+    OGRFeature *poFeature = NULL;
+
     while( true )
     {
-        //OGREnvelope oShapeExtent;
-
         if( panMatchingFIDs != NULL )
         {
             if( panMatchingFIDs[iMatchingFID] == OGRNullFID )
@@ -798,10 +821,10 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
 
             // Check the shape object's geometry, and if it matches
             // any spatial filter, return it.
-            poFeature = FetchShape((int)panMatchingFIDs[iMatchingFID] /*, &oShapeExtent*/);
+            poFeature =
+                FetchShape(static_cast<int>(panMatchingFIDs[iMatchingFID]));
 
             iMatchingFID++;
-
         }
         else
         {
@@ -812,15 +835,15 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
 
             if( hDBF )
             {
-                if (DBFIsRecordDeleted( hDBF, iNextShapeId ))
+                if( DBFIsRecordDeleted( hDBF, iNextShapeId ) )
                     poFeature = NULL;
                 else if( VSIFEofL(VSI_SHP_GetVSIL(hDBF->fp)) )
-                    return NULL; /* There's an I/O error */
+                    return NULL;  //* I/O error.
                 else
-                    poFeature = FetchShape(iNextShapeId /*, &oShapeExtent */);
+                    poFeature = FetchShape(iNextShapeId);
             }
             else
-                poFeature = FetchShape(iNextShapeId /*, &oShapeExtent */);
+                poFeature = FetchShape(iNextShapeId);
 
             iNextShapeId++;
         }
@@ -835,8 +858,9 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
 
             m_nFeaturesRead++;
 
-            if( (m_poFilterGeom == NULL || FilterGeometry( poGeom /*, &oShapeExtent*/ ) )
-                && (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) )
+            if( (m_poFilterGeom == NULL || FilterGeometry( poGeom ) )
+                && (m_poAttrQuery == NULL ||
+                    m_poAttrQuery->Evaluate( poFeature )) )
             {
                 return poFeature;
             }
@@ -853,29 +877,27 @@ OGRFeature *OGRShapeLayer::GetNextFeature()
 OGRFeature *OGRShapeLayer::GetFeature( GIntBig nFeatureId )
 
 {
-    if (!TouchLayer() || nFeatureId > INT_MAX )
+    if( !TouchLayer() || nFeatureId > INT_MAX )
         return NULL;
 
-    OGRFeature *poFeature = NULL;
-    poFeature = SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn, (int)nFeatureId, NULL,
-                                   osEncoding );
-
-    if( poFeature != NULL )
-    {
-        if( poFeature->GetGeometryRef() != NULL )
-        {
-            poFeature->GetGeometryRef()->assignSpatialReference( GetSpatialRef() );
-        }
+    OGRFeature *poFeature =
+        SHPReadOGRFeature( hSHP, hDBF, poFeatureDefn,
+                           static_cast<int>(nFeatureId), NULL,
+                           osEncoding );
 
-        m_nFeaturesRead++;
+    if( poFeature == NULL ) {
+        // Reading shape feature failed.
+        return NULL;
+    }
 
-        return poFeature;
+    if( poFeature->GetGeometryRef() != NULL )
+    {
+        poFeature->GetGeometryRef()->assignSpatialReference( GetSpatialRef() );
     }
 
-    /*
-     * Reading shape feature failed.
-     */
-    return NULL;
+    m_nFeaturesRead++;
+
+    return poFeature;
 }
 
 /************************************************************************/
@@ -885,7 +907,7 @@ OGRFeature *OGRShapeLayer::GetFeature( GIntBig nFeatureId )
 OGRErr OGRShapeLayer::ISetFeature( OGRFeature *poFeature )
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( !bUpdateAccess )
@@ -904,7 +926,7 @@ OGRErr OGRShapeLayer::ISetFeature( OGRFeature *poFeature )
         return OGRERR_NON_EXISTING_FEATURE;
     }
 
-    bHeaderDirty = TRUE;
+    bHeaderDirty = true;
     if( CheckForQIX() || CheckForSBN() )
         DropSpatialIndex();
 
@@ -925,7 +947,8 @@ OGRErr OGRShapeLayer::ISetFeature( OGRFeature *poFeature )
         if( nOffset != hSHP->panRecOffset[nFID] ||
             nSize != hSHP->panRecSize[nFID] )
         {
-            bSHPNeedsRepack = TRUE;
+            bSHPNeedsRepack = true;
+            m_eNeedRepack = YES;
         }
     }
 
@@ -939,7 +962,7 @@ OGRErr OGRShapeLayer::ISetFeature( OGRFeature *poFeature )
 OGRErr OGRShapeLayer::DeleteFeature( GIntBig nFID )
 
 {
-    if (!TouchLayer() || nFID > INT_MAX )
+    if( !TouchLayer() || nFID > INT_MAX )
         return OGRERR_FAILURE;
 
     if( !bUpdateAccess )
@@ -960,23 +983,24 @@ OGRErr OGRShapeLayer::DeleteFeature( GIntBig nFID )
     if( !hDBF )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to delete shape in shapefile with no .dbf file.\n"
-                  "Deletion is done by marking record deleted in dbf\n"
+                  "Attempt to delete shape in shapefile with no .dbf file.  "
+                  "Deletion is done by marking record deleted in dbf "
                   "and is not supported without a .dbf file." );
         return OGRERR_FAILURE;
     }
 
-    if( DBFIsRecordDeleted( hDBF, (int)nFID ) )
+    if( DBFIsRecordDeleted( hDBF, static_cast<int>(nFID) ) )
     {
         return OGRERR_NON_EXISTING_FEATURE;
     }
 
-    if( !DBFMarkRecordDeleted( hDBF, (int)nFID, TRUE ) )
+    if( !DBFMarkRecordDeleted( hDBF, static_cast<int>(nFID), TRUE ) )
         return OGRERR_FAILURE;
 
-    bHeaderDirty = TRUE;
+    bHeaderDirty = true;
     if( CheckForQIX() || CheckForSBN() )
         DropSpatialIndex();
+    m_eNeedRepack = YES;
 
     return OGRERR_NONE;
 }
@@ -988,9 +1012,7 @@ OGRErr OGRShapeLayer::DeleteFeature( GIntBig nFID )
 OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
 
 {
-    OGRErr eErr;
-
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( !bUpdateAccess )
@@ -1007,7 +1029,7 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    bHeaderDirty = TRUE;
+    bHeaderDirty = true;
     if( CheckForQIX() || CheckForSBN() )
         DropSpatialIndex();
 
@@ -1015,10 +1037,12 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
 
     if( nTotalShapeCount == 0
         && wkbFlatten(eRequestedGeomType) == wkbUnknown
+        && hSHP != NULL
+        && hSHP->nShapeType != SHPT_MULTIPATCH
         && poFeature->GetGeometryRef() != NULL )
     {
-        OGRGeometry     *poGeom = poFeature->GetGeometryRef();
-        int             nShapeType;
+        OGRGeometry *poGeom = poFeature->GetGeometryRef();
+        int nShapeType = -1;
 
         switch( poGeom->getGeometryType() )
         {
@@ -1088,24 +1112,28 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
 
           case wkbPolygon:
           case wkbMultiPolygon:
+          case wkbTriangle:
             nShapeType = SHPT_POLYGON;
             eRequestedGeomType = wkbPolygon;
             break;
 
           case wkbPolygon25D:
           case wkbMultiPolygon25D:
+          case wkbTriangleZ:
             nShapeType = SHPT_POLYGONZ;
             eRequestedGeomType = wkbPolygon25D;
             break;
 
           case wkbPolygonM:
           case wkbMultiPolygonM:
+          case wkbTriangleM:
             nShapeType = SHPT_POLYGONM;
             eRequestedGeomType = wkbPolygonM;
             break;
 
           case wkbPolygonZM:
           case wkbMultiPolygonZM:
+          case wkbTriangleZM:
             nShapeType = SHPT_POLYGONZ;
             eRequestedGeomType = wkbPolygonZM;
             break;
@@ -1115,6 +1143,41 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
             break;
         }
 
+        if( wkbFlatten(poGeom->getGeometryType()) == wkbTIN ||
+            wkbFlatten(poGeom->getGeometryType()) == wkbPolyhedralSurface )
+        {
+            nShapeType = SHPT_MULTIPATCH;
+            eRequestedGeomType = wkbUnknown;
+        }
+
+        if( wkbFlatten(poGeom->getGeometryType()) == wkbGeometryCollection )
+        {
+            OGRGeometryCollection *poGC =
+                            dynamic_cast<OGRGeometryCollection *>(poGeom);
+            bool bIsMultiPatchCompatible = false;
+            for( int iGeom = 0; poGC != NULL &&
+                                iGeom < poGC->getNumGeometries(); iGeom++ )
+            {
+                OGRwkbGeometryType eSubGeomType =
+                    wkbFlatten(poGC->getGeometryRef(iGeom)->getGeometryType());
+                if( eSubGeomType == wkbTIN ||
+                    eSubGeomType == wkbPolyhedralSurface )
+                {
+                    bIsMultiPatchCompatible = true;
+                }
+                else if( eSubGeomType != wkbMultiPolygon )
+                {
+                    bIsMultiPatchCompatible = false;
+                    break;
+                }
+            }
+            if( bIsMultiPatchCompatible )
+            {
+                nShapeType = SHPT_MULTIPATCH;
+                eRequestedGeomType = wkbUnknown;
+            }
+        }
+
         if( nShapeType != -1 )
         {
             poFeatureDefn->SetGeomType(eRequestedGeomType);
@@ -1122,14 +1185,20 @@ OGRErr OGRShapeLayer::ICreateFeature( OGRFeature *poFeature )
         }
     }
 
-    eErr = SHPWriteOGRFeature( hSHP, hDBF, poFeatureDefn, poFeature,
-                               osEncoding, &bTruncationWarningEmitted,
-                               bRewindOnWrite );
+    const OGRErr eErr =
+        SHPWriteOGRFeature( hSHP, hDBF, poFeatureDefn, poFeature,
+                            osEncoding, &bTruncationWarningEmitted,
+                            bRewindOnWrite );
 
     if( hSHP != NULL )
         nTotalShapeCount = hSHP->nRecords;
-    else
+    else if( hDBF != NULL )
         nTotalShapeCount = hDBF->nRecords;
+#ifdef DEBUG
+    else  // Silence coverity.
+        CPLError(CE_Fatal, CPLE_AssertionFailed,
+                 "Should not happen: Both hSHP and hDBF are nullptrs");
+#endif
 
     return eErr;
 }
@@ -1157,10 +1226,10 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
     int nFeatureCount = 0;
     int iLocalMatchingFID = 0;
     int iLocalNextShapeId = 0;
-    int bExpectPoints = FALSE;
+    bool bExpectPoints = false;
 
-    if (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbPoint)
-        bExpectPoints = TRUE;
+    if( wkbFlatten(poFeatureDefn->GetGeomType()) == wkbPoint )
+        bExpectPoints = true;
 
 /* -------------------------------------------------------------------- */
 /*      Loop till we find a feature matching our criteria.              */
@@ -1171,12 +1240,11 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
 
     while( true )
     {
-        SHPObject* psShape = NULL;
         int iShape = -1;
 
         if( panMatchingFIDs != NULL )
         {
-            iShape = (int)panMatchingFIDs[iLocalMatchingFID];
+            iShape = static_cast<int>(panMatchingFIDs[iLocalMatchingFID]);
             if( iShape == OGRNullFID )
                 break;
             iLocalMatchingFID++;
@@ -1185,20 +1253,21 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
         {
             if( iLocalNextShapeId >= nTotalShapeCount )
                 break;
-            iShape = iLocalNextShapeId ++;
+            iShape = iLocalNextShapeId++;
 
             if( hDBF )
             {
-                if (DBFIsRecordDeleted( hDBF, iShape ))
+                if( DBFIsRecordDeleted( hDBF, iShape ) )
                     continue;
 
-                if (VSIFEofL(VSI_SHP_GetVSIL(hDBF->fp)))
+                if( VSIFEofL(VSI_SHP_GetVSIL(hDBF->fp)) )
                     break;
             }
         }
 
-        /* Read full shape for point layers */
-        if (bExpectPoints ||
+        // Read full shape for point layers.
+        SHPObject* psShape = NULL;
+        if( bExpectPoints ||
             hSHP->panRecOffset[iShape] == 0 /* lazy shx loading case */ )
             psShape = SHPReadObject( hSHP, iShape);
 
@@ -1207,19 +1276,21 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
 /*      inconclusive tests on bounding box only, we will read the full  */
 /*      shape later.                                                    */
 /* -------------------------------------------------------------------- */
-        else if (iShape >= 0 && iShape < hSHP->nRecords &&
-                    hSHP->panRecSize[iShape] > 4 + 8 * 4 )
+        else if( iShape >= 0 && iShape < hSHP->nRecords &&
+                 hSHP->panRecSize[iShape] > 4 + 8 * 4 )
         {
-            GByte abyBuf[4 + 8 * 4];
-            if( hSHP->sHooks.FSeek( hSHP->fpSHP, hSHP->panRecOffset[iShape] + 8, 0 ) == 0 &&
-                hSHP->sHooks.FRead( abyBuf, sizeof(abyBuf), 1, hSHP->fpSHP ) == 1 )
+            GByte abyBuf[4 + 8 * 4] = {};
+            if( hSHP->sHooks.FSeek( hSHP->fpSHP,
+                                    hSHP->panRecOffset[iShape] + 8, 0 ) == 0 &&
+                hSHP->sHooks.FRead( abyBuf, sizeof(abyBuf),
+                                    1, hSHP->fpSHP ) == 1 )
             {
                 memcpy(&(sShape.nSHPType), abyBuf, 4);
                 CPL_LSBPTR32(&(sShape.nSHPType));
-                if ( sShape.nSHPType != SHPT_NULL &&
-                        sShape.nSHPType != SHPT_POINT &&
-                        sShape.nSHPType != SHPT_POINTM &&
-                        sShape.nSHPType != SHPT_POINTZ)
+                if( sShape.nSHPType != SHPT_NULL &&
+                    sShape.nSHPType != SHPT_POINT &&
+                    sShape.nSHPType != SHPT_POINTM &&
+                    sShape.nSHPType != SHPT_POINTZ )
                 {
                     psShape = &sShape;
                     memcpy(&(sShape.dfXMin), abyBuf + 4, 8);
@@ -1242,18 +1313,18 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
         {
             OGRGeometry* poGeometry = NULL;
             OGREnvelope sGeomEnv;
-            /* Test if we have a degenerated bounding box */
-            if (psShape->nSHPType != SHPT_POINT
+            // Test if we have a degenerated bounding box.
+            if( psShape->nSHPType != SHPT_POINT
                 && psShape->nSHPType != SHPT_POINTZ
                 && psShape->nSHPType != SHPT_POINTM
                 && (psShape->dfXMin == psShape->dfXMax
-                    || psShape->dfYMin == psShape->dfYMax))
+                    || psShape->dfYMin == psShape->dfYMax) )
             {
-                /* We need to read the full geometry */
-                /* to compute the envelope */
-                if (psShape == &sShape)
+                // Need to read the full geometry to compute the envelope.
+                if( psShape == &sShape )
                     psShape = SHPReadObject( hSHP, iShape);
-                if (psShape)
+
+                if( psShape )
                 {
                     poGeometry = SHPReadOGRObject( hSHP, iShape, psShape );
                     poGeometry->getEnvelope( &sGeomEnv );
@@ -1262,7 +1333,7 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
             }
             else
             {
-                /* Trust the shape bounding box as the shape envelope */
+                // Trust the shape bounding box as the shape envelope.
                 sGeomEnv.MinX = psShape->dfXMin;
                 sGeomEnv.MinY = psShape->dfYMin;
                 sGeomEnv.MaxX = psShape->dfXMax;
@@ -1278,8 +1349,7 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
                 || sGeomEnv.MaxY < m_sFilterEnvelope.MinY
                 || m_sFilterEnvelope.MaxX < sGeomEnv.MinX
                 || m_sFilterEnvelope.MaxY < sGeomEnv.MinY )
-            {
-            }
+            {}
 /* -------------------------------------------------------------------- */
 /*      If the filter geometry is its own envelope and if the           */
 /*      envelope of the geometry is inside the filter geometry,         */
@@ -1291,7 +1361,7 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
                 sGeomEnv.MaxX <= m_sFilterEnvelope.MaxX &&
                 sGeomEnv.MaxY <= m_sFilterEnvelope.MaxY)
             {
-                nFeatureCount ++;
+                nFeatureCount++;
             }
             else
             {
@@ -1301,12 +1371,12 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
 /* -------------------------------------------------------------------- */
                 if( OGRGeometryFactory::haveGEOS() )
                 {
-                    /* We need to read the full geometry */
-                    if (poGeometry == NULL)
+                    // Read the full geometry.
+                    if( poGeometry == NULL )
                     {
-                        if (psShape == &sShape)
+                        if( psShape == &sShape )
                             psShape = SHPReadObject( hSHP, iShape);
-                        if (psShape)
+                        if( psShape )
                         {
                             poGeometry =
                                 SHPReadOGRObject( hSHP, iShape, psShape );
@@ -1314,28 +1384,34 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
                         }
                     }
                     if( poGeometry == NULL )
-                        nFeatureCount ++;
-                    else if ( m_pPreparedFilterGeom != NULL )
+                    {
+                        nFeatureCount++;
+                    }
+                    else if( m_pPreparedFilterGeom != NULL )
                     {
                         if( OGRPreparedGeometryIntersects(m_pPreparedFilterGeom,
                                                           poGeometry) )
                         {
-                            nFeatureCount ++;
+                            nFeatureCount++;
                         }
                     }
                     else if( m_poFilterGeom->Intersects( poGeometry ) )
-                        nFeatureCount ++;
+                        nFeatureCount++;
                 }
                 else
-                    nFeatureCount ++;
+                {
+                    nFeatureCount++;
+                }
             }
 
             delete poGeometry;
         }
         else
-            nFeatureCount ++;
+        {
+            nFeatureCount++;
+        }
 
-        if (psShape && psShape != &sShape)
+        if( psShape && psShape != &sShape )
             SHPDestroyObject( psShape );
     }
 
@@ -1349,48 +1425,54 @@ int OGRShapeLayer::GetFeatureCountWithSpatialFilterOnly()
 GIntBig OGRShapeLayer::GetFeatureCount( int bForce )
 
 {
-    /* Check if the spatial filter is non-trivial */
-    int bHasTrivialSpatialFilter;
-    if (m_poFilterGeom != NULL)
+    // Check if the spatial filter is non-trivial.
+    bool bHasTrivialSpatialFilter = false;
+    if( m_poFilterGeom != NULL )
     {
         OGREnvelope oSpatialFilterEnvelope;
         m_poFilterGeom->getEnvelope( &oSpatialFilterEnvelope );
 
         OGREnvelope oLayerExtent;
-        if (GetExtent(&oLayerExtent, TRUE) == OGRERR_NONE)
+        if( GetExtent(&oLayerExtent, TRUE) == OGRERR_NONE )
         {
-            if (oSpatialFilterEnvelope.Contains(oLayerExtent))
+            if( oSpatialFilterEnvelope.Contains(oLayerExtent) )
             {
-                bHasTrivialSpatialFilter = TRUE;
+                bHasTrivialSpatialFilter = true;
             }
             else
-                bHasTrivialSpatialFilter = FALSE;
+            {
+                bHasTrivialSpatialFilter = false;
+            }
         }
         else
-            bHasTrivialSpatialFilter = FALSE;
+        {
+            bHasTrivialSpatialFilter = false;
+        }
     }
     else
-        bHasTrivialSpatialFilter = TRUE;
-
+    {
+        bHasTrivialSpatialFilter = true;
+    }
 
     if( bHasTrivialSpatialFilter && m_poAttrQuery == NULL )
         return nTotalShapeCount;
 
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return 0;
 
-    /* Spatial filter only */
+    // Spatial filter only.
     if( m_poAttrQuery == NULL && hSHP != NULL )
     {
         return GetFeatureCountWithSpatialFilterOnly();
     }
 
-    /* Attribute filter only */
+    // Attribute filter only.
     if( m_poAttrQuery != NULL )
     {
-        /* Let's see if we can ignore reading geometries */
-        int bSaveGeometryIgnored = poFeatureDefn->IsGeometryIgnored();
-        if (!AttributeFilterEvaluationNeedsGeometry())
+        // See if we can ignore reading geometries.
+        const bool bSaveGeometryIgnored =
+            CPL_TO_BOOL(poFeatureDefn->IsGeometryIgnored());
+        if( !AttributeFilterEvaluationNeedsGeometry() )
             poFeatureDefn->SetGeometryIgnored(TRUE);
 
         GIntBig nRet = OGRLayer::GetFeatureCount( bForce );
@@ -1412,19 +1494,18 @@ GIntBig OGRShapeLayer::GetFeatureCount( int bForce )
 /*      Returns OGRERR_NONE/OGRRERR_FAILURE.                            */
 /************************************************************************/
 
-OGRErr OGRShapeLayer::GetExtent (OGREnvelope *psExtent, int bForce)
+OGRErr OGRShapeLayer::GetExtent( OGREnvelope *psExtent, int bForce )
 
 {
-    UNREFERENCED_PARAM( bForce );
-
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
-    double adMin[4], adMax[4];
-
     if( hSHP == NULL )
         return OGRERR_FAILURE;
 
+    double adMin[4] = { 0.0, 0.0, 0.0, 0.0 };
+    double adMax[4] = { 0.0, 0.0, 0.0, 0.0 };
+
     SHPGetInfo(hSHP, NULL, NULL, adMin, adMax);
 
     psExtent->MinX = adMin[0];
@@ -1436,16 +1517,15 @@ OGRErr OGRShapeLayer::GetExtent (OGREnvelope *psExtent, int bForce)
         CPLIsNan(adMax[0]) || CPLIsNan(adMax[1]) )
     {
         CPLDebug("SHAPE", "Invalid extent in shape header");
-        OGRErr eErr;
 
-        /* Disable filters to avoid infinite recursion in GetNextFeature() */
-        /* that calls ScanIndices() that call GetExtent... */
+        // Disable filters to avoid infinite recursion in GetNextFeature()
+        // that calls ScanIndices() that call GetExtent.
         OGRFeatureQuery* poAttrQuery = m_poAttrQuery;
         m_poAttrQuery = NULL;
         OGRGeometry* poFilterGeom = m_poFilterGeom;
         m_poFilterGeom = NULL;
 
-        eErr = OGRLayer::GetExtent(psExtent, bForce);
+        const OGRErr eErr = OGRLayer::GetExtent(psExtent, bForce);
 
         m_poAttrQuery = poAttrQuery;
         m_poFilterGeom = poFilterGeom;
@@ -1462,17 +1542,17 @@ OGRErr OGRShapeLayer::GetExtent (OGREnvelope *psExtent, int bForce)
 int OGRShapeLayer::TestCapability( const char * pszCap )
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return FALSE;
 
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCSequentialWrite)
+    if( EQUAL(pszCap,OLCSequentialWrite)
              || EQUAL(pszCap,OLCRandomWrite) )
         return bUpdateAccess;
 
-    else if( EQUAL(pszCap,OLCFastFeatureCount) )
+    if( EQUAL(pszCap,OLCFastFeatureCount) )
     {
         if( !(m_poFilterGeom == NULL || CheckForQIX() || CheckForSBN()) )
             return FALSE;
@@ -1485,37 +1565,37 @@ int OGRShapeLayer::TestCapability( const char * pszCap )
         return TRUE;
     }
 
-    else if( EQUAL(pszCap,OLCDeleteFeature) )
+    if( EQUAL(pszCap,OLCDeleteFeature) )
         return bUpdateAccess;
 
-    else if( EQUAL(pszCap,OLCFastSpatialFilter) )
+    if( EQUAL(pszCap,OLCFastSpatialFilter) )
         return CheckForQIX() || CheckForSBN();
 
-    else if( EQUAL(pszCap,OLCFastGetExtent) )
+    if( EQUAL(pszCap,OLCFastGetExtent) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCFastSetNextByIndex) )
+    if( EQUAL(pszCap,OLCFastSetNextByIndex) )
         return m_poFilterGeom == NULL && m_poAttrQuery == NULL;
 
-    else if( EQUAL(pszCap,OLCCreateField) )
+    if( EQUAL(pszCap,OLCCreateField) )
         return bUpdateAccess;
 
-    else if( EQUAL(pszCap,OLCDeleteField) )
+    if( EQUAL(pszCap,OLCDeleteField) )
         return bUpdateAccess;
 
-    else if( EQUAL(pszCap,OLCReorderFields) )
+    if( EQUAL(pszCap,OLCReorderFields) )
         return bUpdateAccess;
 
-    else if( EQUAL(pszCap,OLCAlterFieldDefn) )
+    if( EQUAL(pszCap,OLCAlterFieldDefn) )
         return bUpdateAccess;
 
-    else if( EQUAL(pszCap,OLCIgnoreFields) )
+    if( EQUAL(pszCap,OLCIgnoreFields) )
         return TRUE;
 
-    else if( EQUAL(pszCap,OLCStringsAsUTF8) )
+    if( EQUAL(pszCap,OLCStringsAsUTF8) )
     {
-        /* No encoding defined : we don't know */
-        if( osEncoding.size() == 0)
+        // No encoding defined: we don't know.
+        if( osEncoding.empty())
             return FALSE;
 
         if( hDBF == NULL || DBFGetFieldCount( hDBF ) == 0 )
@@ -1523,24 +1603,24 @@ int OGRShapeLayer::TestCapability( const char * pszCap )
 
         CPLClearRecodeWarningFlags();
 
-        /* Otherwise test that we can re-encode field names to UTF-8 */
-        int nFieldCount = DBFGetFieldCount( hDBF );
-        for(int i=0;i<nFieldCount;i++)
+        // Otherwise test that we can re-encode field names to UTF-8.
+        const int nFieldCount = DBFGetFieldCount( hDBF );
+        for( int i = 0; i < nFieldCount; i++ )
         {
-            char            szFieldName[20];
-            int             nWidth, nPrecision;
+            char szFieldName[XBASE_FLDNAME_LEN_READ+1] = {};
+            int nWidth = 0;
+            int nPrecision = 0;
 
-            DBFGetFieldInfo( hDBF, i, szFieldName,
-                            &nWidth, &nPrecision );
+            DBFGetFieldInfo( hDBF, i, szFieldName, &nWidth, &nPrecision );
 
             CPLErrorReset();
             CPLPushErrorHandler(CPLQuietErrorHandler);
-            char *pszUTF8Field = CPLRecode( szFieldName,
-                                            osEncoding, CPL_ENC_UTF8);
+            char * const pszUTF8Field =
+                CPLRecode( szFieldName, osEncoding, CPL_ENC_UTF8);
             CPLPopErrorHandler();
             CPLFree( pszUTF8Field );
 
-            if (CPLGetLastErrorType() != 0)
+            if( CPLGetLastErrorType() != 0 )
             {
                 return FALSE;
             }
@@ -1549,11 +1629,10 @@ int OGRShapeLayer::TestCapability( const char * pszCap )
         return TRUE;
     }
 
-    else if( EQUAL(pszCap,OLCMeasuredGeometries) )
+    if( EQUAL(pszCap,OLCMeasuredGeometries) )
         return TRUE;
 
-    else
-        return FALSE;
+    return FALSE;
 }
 
 /************************************************************************/
@@ -1563,87 +1642,77 @@ int OGRShapeLayer::TestCapability( const char * pszCap )
 OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     CPLAssert( NULL != poFieldDefn );
 
-    int         iNewField;
-
     if( !bUpdateAccess )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  UNSUPPORTED_OP_READ_ONLY,
-                  "CreateField");
+                  UNSUPPORTED_OP_READ_ONLY, "CreateField" );
         return OGRERR_FAILURE;
-
     }
 
-    int bDBFJustCreated = FALSE;
+    bool bDBFJustCreated = false;
     if( hDBF == NULL )
     {
-        CPLString osFilename = CPLResetExtension( pszFullName, "dbf" );
+        const CPLString osFilename = CPLResetExtension( pszFullName, "dbf" );
         hDBF = DBFCreate( osFilename );
 
         if( hDBF == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
-                      "Failed to create DBF file `%s'.\n",
+                      "Failed to create DBF file `%s'.",
                       osFilename.c_str() );
             return OGRERR_FAILURE;
         }
 
-        bDBFJustCreated = TRUE;
+        bDBFJustCreated = true;
     }
 
     CPLErrorReset();
 
-    if ( poFeatureDefn->GetFieldCount() == 255 )
+    if( poFeatureDefn->GetFieldCount() == 255 )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
-                  "Creating a 256th field, but some DBF readers might only support 255 fields" );
-    }
-    if ( hDBF->nHeaderLength + 32 > 65535 )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Cannot add more fields in DBF file.");
-        return OGRERR_FAILURE;
+                  "Creating a 256th field, "
+                  "but some DBF readers might only support 255 fields" );
     }
 
 /* -------------------------------------------------------------------- */
 /*      Normalize field name                                            */
 /* -------------------------------------------------------------------- */
-
-    char szNewFieldName[10 + 1];
-    char * pszTmp = NULL;
-    int nRenameNum = 1;
-
     CPLString osFieldName;
-    if( osEncoding.size() )
+    if( !osEncoding.empty() )
     {
         CPLClearRecodeWarningFlags();
         CPLPushErrorHandler(CPLQuietErrorHandler);
         CPLErr eLastErr = CPLGetLastErrorType();
-        char* pszRecoded = CPLRecode( poFieldDefn->GetNameRef(), CPL_ENC_UTF8, osEncoding);
+        char* const pszRecoded =
+            CPLRecode( poFieldDefn->GetNameRef(), CPL_ENC_UTF8, osEncoding);
         CPLPopErrorHandler();
         osFieldName = pszRecoded;
         CPLFree(pszRecoded);
         if( CPLGetLastErrorType() != eLastErr )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Failed to create field name '%s' : cannot convert to %s",
+                     "Failed to create field name '%s': cannot convert to %s",
                      poFieldDefn->GetNameRef(), osEncoding.c_str());
             return OGRERR_FAILURE;
         }
     }
     else
+    {
         osFieldName = poFieldDefn->GetNameRef();
+    }
 
-    int nNameSize = static_cast<int>(osFieldName.size());
-    pszTmp = CPLScanString( osFieldName,
-                            MIN( nNameSize, 10) , TRUE, TRUE);
-    strncpy(szNewFieldName, pszTmp, 10);
-    szNewFieldName[10] = '\0';
+    const int nNameSize = static_cast<int>(osFieldName.size());
+    char * pszTmp =
+        CPLScanString( osFieldName, std::min( nNameSize, XBASE_FLDNAME_LEN_WRITE) , TRUE, TRUE);
+    char szNewFieldName[XBASE_FLDNAME_LEN_WRITE + 1];
+    strncpy(szNewFieldName, pszTmp, sizeof(szNewFieldName)-1);
+    szNewFieldName[sizeof(szNewFieldName)-1] = '\0';
 
     if( !bApproxOK &&
         ( DBFGetFieldIndex( hDBF, szNewFieldName ) >= 0 ||
@@ -1657,20 +1726,28 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
         return OGRERR_FAILURE;
     }
 
+    int nRenameNum = 1;
     while( DBFGetFieldIndex( hDBF, szNewFieldName ) >= 0 && nRenameNum < 10 )
-        snprintf( szNewFieldName, sizeof(szNewFieldName), "%.8s_%.1d", pszTmp, nRenameNum++ );
+    {
+        CPLsnprintf( szNewFieldName, sizeof(szNewFieldName),
+                  "%.8s_%.1d", pszTmp, nRenameNum );
+        nRenameNum ++;
+    }
     while( DBFGetFieldIndex( hDBF, szNewFieldName ) >= 0 && nRenameNum < 100 )
-        snprintf( szNewFieldName, sizeof(szNewFieldName), "%.8s%.2d", pszTmp, nRenameNum++ );
+        CPLsnprintf( szNewFieldName, sizeof(szNewFieldName),
+                  "%.8s%.2d", pszTmp, nRenameNum++ );
 
     CPLFree( pszTmp );
     pszTmp = NULL;
 
     if( DBFGetFieldIndex( hDBF, szNewFieldName ) >= 0 )
     {
+        // One hundred similar field names!!?
         CPLError( CE_Failure, CPLE_NotSupported,
-                  "Too many field names like '%s' when truncated to 10 letters "
+                  "Too many field names like '%s' when truncated to %d letters "
                   "for Shapefile format.",
-                  poFieldDefn->GetNameRef() );//One hundred similar field names!!?
+                  poFieldDefn->GetNameRef(),
+                  XBASE_FLDNAME_LEN_WRITE );
     }
 
     OGRFieldDefn oModFieldDefn(poFieldDefn);
@@ -1682,14 +1759,13 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
                   poFieldDefn->GetNameRef(),
                   szNewFieldName );
 
-        // Set field name with normalized value
+        // Set field name with normalized value.
         oModFieldDefn.SetName(szNewFieldName);
     }
 
 /* -------------------------------------------------------------------- */
 /*      Add field to layer                                              */
 /* -------------------------------------------------------------------- */
-
     char chType = 'C';
     int nWidth = 0;
     int nDecimals = 0;
@@ -1699,20 +1775,20 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
         case OFTInteger:
             chType = 'N';
             nWidth = oModFieldDefn.GetWidth();
-            if (nWidth == 0) nWidth = 9;
+            if( nWidth == 0 ) nWidth = 9;
             break;
 
         case OFTInteger64:
             chType = 'N';
             nWidth = oModFieldDefn.GetWidth();
-            if (nWidth == 0) nWidth = 18;
+            if( nWidth == 0 ) nWidth = 18;
             break;
 
         case OFTReal:
             chType = 'N';
             nWidth = oModFieldDefn.GetWidth();
             nDecimals = oModFieldDefn.GetPrecision();
-            if (nWidth == 0)
+            if( nWidth == 0 )
             {
                 nWidth = 24;
                 nDecimals = 15;
@@ -1722,12 +1798,12 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
         case OFTString:
             chType = 'C';
             nWidth = oModFieldDefn.GetWidth();
-            if (nWidth == 0) nWidth = 80;
-            else if (nWidth > OGR_DBF_MAX_FIELD_WIDTH)
+            if( nWidth == 0 ) nWidth = 80;
+            else if( nWidth > OGR_DBF_MAX_FIELD_WIDTH )
             {
                 CPLError( CE_Warning, CPLE_AppDefined,
-                        "Field %s of width %d truncated to %d.",
-                        szNewFieldName, nWidth, OGR_DBF_MAX_FIELD_WIDTH );
+                          "Field %s of width %d truncated to %d.",
+                          szNewFieldName, nWidth, OGR_DBF_MAX_FIELD_WIDTH );
                 nWidth = OGR_DBF_MAX_FIELD_WIDTH;
             }
             break;
@@ -1738,9 +1814,10 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
             break;
 
         case OFTDateTime:
-            CPLError( CE_Warning, CPLE_NotSupported,
-                    "Field %s create as date field, though DateTime requested.",
-                    szNewFieldName );
+            CPLError(
+                CE_Warning, CPLE_NotSupported,
+                "Field %s create as date field, though DateTime requested.",
+                szNewFieldName );
             chType = 'D';
             nWidth = 8;
             oModFieldDefn.SetType( OFTDate );
@@ -1748,8 +1825,8 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 
         default:
             CPLError( CE_Failure, CPLE_NotSupported,
-                    "Can't create fields of type %s on shapefile layers.",
-                    OGRFieldDefn::GetFieldTypeName(oModFieldDefn.GetType()) );
+                      "Can't create fields of type %s on shapefile layers.",
+                      OGRFieldDefn::GetFieldTypeName(oModFieldDefn.GetType()) );
 
             return OGRERR_FAILURE;
             break;
@@ -1758,22 +1835,13 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
     oModFieldDefn.SetWidth( nWidth );
     oModFieldDefn.SetPrecision( nDecimals );
 
-    if ( hDBF->nRecordLength + nWidth > 65535 )
-    {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Can't create field %s in Shape DBF file. "
-                  "Maximum record length reached.",
-                  szNewFieldName );
-        return OGRERR_FAILURE;
-    }
-
-    /* Suppress the dummy FID field if we have created it just before */
+    // Suppress the dummy FID field if we have created it just before.
     if( DBFGetFieldCount( hDBF ) == 1 && poFeatureDefn->GetFieldCount() == 0 )
     {
         DBFDeleteField( hDBF, 0 );
     }
 
-    iNewField =
+    const int iNewField =
         DBFAddNativeFieldType( hDBF, szNewFieldName,
                                chType, nWidth, nDecimals );
 
@@ -1783,7 +1851,7 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 
         if( bDBFJustCreated )
         {
-            for(int i=0;i<nTotalShapeCount;i++)
+            for( int i = 0; i < nTotalShapeCount; i++ )
             {
                 DBFWriteNULLAttribute( hDBF, i, 0 );
             }
@@ -1791,14 +1859,12 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 
         return OGRERR_NONE;
     }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Can't create field %s in Shape DBF file, reason unknown.",
-                  szNewFieldName );
 
-        return OGRERR_FAILURE;
-    }
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "Can't create field %s in Shape DBF file, reason unknown.",
+              szNewFieldName );
+
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -1807,7 +1873,7 @@ OGRErr OGRShapeLayer::CreateField( OGRFieldDefn *poFieldDefn, int bApproxOK )
 
 OGRErr OGRShapeLayer::DeleteField( int iField )
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( !bUpdateAccess )
@@ -1818,21 +1884,21 @@ OGRErr OGRShapeLayer::DeleteField( int iField )
         return OGRERR_FAILURE;
     }
 
-    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    if( iField < 0 || iField >= poFeatureDefn->GetFieldCount() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid field index");
         return OGRERR_FAILURE;
     }
 
-    if ( DBFDeleteField( hDBF, iField ) )
+    if( DBFDeleteField( hDBF, iField ) )
     {
         TruncateDBF();
 
         return poFeatureDefn->DeleteFieldDefn( iField );
     }
-    else
-        return OGRERR_FAILURE;
+
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -1841,7 +1907,7 @@ OGRErr OGRShapeLayer::DeleteField( int iField )
 
 OGRErr OGRShapeLayer::ReorderFields( int* panMap )
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( !bUpdateAccess )
@@ -1852,28 +1918,29 @@ OGRErr OGRShapeLayer::ReorderFields( int* panMap )
         return OGRERR_FAILURE;
     }
 
-    if (poFeatureDefn->GetFieldCount() == 0)
+    if( poFeatureDefn->GetFieldCount() == 0 )
         return OGRERR_NONE;
 
     OGRErr eErr = OGRCheckPermutation(panMap, poFeatureDefn->GetFieldCount());
-    if (eErr != OGRERR_NONE)
+    if( eErr != OGRERR_NONE )
         return eErr;
 
-    if ( DBFReorderFields( hDBF, panMap ) )
+    if( DBFReorderFields( hDBF, panMap ) )
     {
         return poFeatureDefn->ReorderFieldDefns( panMap );
     }
-    else
-        return OGRERR_FAILURE;
+
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
 /*                           AlterFieldDefn()                           */
 /************************************************************************/
 
-OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
+OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
+                                      int nFlagsIn )
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( !bUpdateAccess )
@@ -1884,7 +1951,7 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
         return OGRERR_FAILURE;
     }
 
-    if (iField < 0 || iField >= poFeatureDefn->GetFieldCount())
+    if( iField < 0 || iField >= poFeatureDefn->GetFieldCount() )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "Invalid field index");
@@ -1892,28 +1959,27 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
     }
 
     OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
+    OGRFieldType eType = poFieldDefn->GetType();
 
-    char chNativeType;
-    char            szFieldName[20];
-    int             nWidth, nPrecision;
-    OGRFieldType    eType = poFieldDefn->GetType();
-    /* DBFFieldType    eDBFType; */
-
-    chNativeType = DBFGetNativeFieldType( hDBF, iField );
-    /* eDBFType = */ DBFGetFieldInfo( hDBF, iField, szFieldName,
-                                      &nWidth, &nPrecision );
+    // On reading we support up to 11 characters
+    char szFieldName[XBASE_FLDNAME_LEN_READ+1] = {};
+    int nWidth = 0;
+    int nPrecision = 0;
+    DBFGetFieldInfo( hDBF, iField, szFieldName, &nWidth, &nPrecision );
+    char chNativeType = DBFGetNativeFieldType( hDBF, iField );
 
-    if ((nFlagsIn & ALTER_TYPE_FLAG) &&
-        poNewFieldDefn->GetType() != poFieldDefn->GetType())
+    if( (nFlagsIn & ALTER_TYPE_FLAG) &&
+        poNewFieldDefn->GetType() != poFieldDefn->GetType() )
     {
-        if (poNewFieldDefn->GetType() == OFTInteger64 && poFieldDefn->GetType() == OFTInteger )
+        if( poNewFieldDefn->GetType() == OFTInteger64 &&
+            poFieldDefn->GetType() == OFTInteger )
         {
             eType = poNewFieldDefn->GetType();
         }
-        else if (poNewFieldDefn->GetType() != OFTString)
+        else if( poNewFieldDefn->GetType() != OFTString )
         {
             CPLError( CE_Failure, CPLE_NotSupported,
-                      "Can only convert to OFTString");
+                      "Can only convert to OFTString" );
             return OGRERR_FAILURE;
         }
         else
@@ -1923,46 +1989,52 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
         }
     }
 
-    if (nFlagsIn & ALTER_NAME_FLAG)
+    if( nFlagsIn & ALTER_NAME_FLAG )
     {
         CPLString osFieldName;
-        if( osEncoding.size() )
+        if( !osEncoding.empty() )
         {
             CPLClearRecodeWarningFlags();
             CPLErrorReset();
             CPLPushErrorHandler(CPLQuietErrorHandler);
-            char* pszRecoded = CPLRecode( poNewFieldDefn->GetNameRef(), CPL_ENC_UTF8, osEncoding);
+            char* pszRecoded =
+                CPLRecode( poNewFieldDefn->GetNameRef(),
+                           CPL_ENC_UTF8, osEncoding);
             CPLPopErrorHandler();
             osFieldName = pszRecoded;
             CPLFree(pszRecoded);
             if( CPLGetLastErrorType() != 0 )
             {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Failed to rename field name to '%s' : cannot convert to %s",
-                        poNewFieldDefn->GetNameRef(), osEncoding.c_str());
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Failed to rename field name to '%s': "
+                    "cannot convert to %s",
+                    poNewFieldDefn->GetNameRef(), osEncoding.c_str());
                 return OGRERR_FAILURE;
             }
         }
         else
+        {
             osFieldName = poNewFieldDefn->GetNameRef();
+        }
 
-        strncpy(szFieldName, osFieldName, 10);
-        szFieldName[10] = '\0';
+        strncpy(szFieldName, osFieldName, sizeof(szFieldName)-1);
+        szFieldName[sizeof(szFieldName)-1] = '\0';
     }
-    if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
+    if( nFlagsIn & ALTER_WIDTH_PRECISION_FLAG )
     {
         nWidth = poNewFieldDefn->GetWidth();
         nPrecision = poNewFieldDefn->GetPrecision();
     }
 
-    if ( DBFAlterFieldDefn( hDBF, iField, szFieldName,
-                            chNativeType, nWidth, nPrecision) )
+    if( DBFAlterFieldDefn( hDBF, iField, szFieldName,
+                           chNativeType, nWidth, nPrecision) )
     {
-        if (nFlagsIn & ALTER_TYPE_FLAG)
+        if( nFlagsIn & ALTER_TYPE_FLAG )
             poFieldDefn->SetType(eType);
-        if (nFlagsIn & ALTER_NAME_FLAG)
+        if( nFlagsIn & ALTER_NAME_FLAG )
             poFieldDefn->SetName(poNewFieldDefn->GetNameRef());
-        if (nFlagsIn & ALTER_WIDTH_PRECISION_FLAG)
+        if( nFlagsIn & ALTER_WIDTH_PRECISION_FLAG )
         {
             poFieldDefn->SetWidth(nWidth);
             poFieldDefn->SetPrecision(nPrecision);
@@ -1971,8 +2043,8 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
         }
         return OGRERR_NONE;
     }
-    else
-        return OGRERR_FAILURE;
+
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -1982,20 +2054,20 @@ OGRErr OGRShapeLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
 OGRSpatialReference *OGRShapeGeomFieldDefn::GetSpatialRef()
 
 {
-    if (bSRSSet)
+    if( bSRSSet )
         return poSRS;
 
-    bSRSSet = TRUE;
+    bSRSSet = true;
 
 /* -------------------------------------------------------------------- */
 /*      Is there an associated .prj file we can read?                   */
 /* -------------------------------------------------------------------- */
     const char  *pszPrjFile = CPLResetExtension( pszFullName, "prj" );
-    char    **papszLines;
 
-    char* apszOptions[] = { (char*)"EMIT_ERROR_IF_CANNOT_OPEN_FILE=FALSE", NULL };
-    papszLines = CSLLoad2( pszPrjFile, -1, -1, apszOptions );
-    if (papszLines == NULL)
+    char *apszOptions[] = {
+        const_cast<char *>("EMIT_ERROR_IF_CANNOT_OPEN_FILE=FALSE"), NULL };
+    char **papszLines = CSLLoad2( pszPrjFile, -1, -1, apszOptions );
+    if( papszLines == NULL )
     {
         pszPrjFile = CPLResetExtension( pszFullName, "PRJ" );
         papszLines = CSLLoad2( pszPrjFile, -1, -1, apszOptions );
@@ -2006,13 +2078,15 @@ OGRSpatialReference *OGRShapeGeomFieldDefn::GetSpatialRef()
         osPrjFile = pszPrjFile;
 
         poSRS = new OGRSpatialReference();
-        /* Remove UTF-8 BOM if found */
-        /* http://lists.osgeo.org/pipermail/gdal-dev/2014-July/039527.html */
-        if( ((unsigned char)papszLines[0][0] == 0xEF) &&
-            ((unsigned char)papszLines[0][1] == 0xBB) &&
-            ((unsigned char)papszLines[0][2] == 0xBF) )
+        // Remove UTF-8 BOM if found
+        // http://lists.osgeo.org/pipermail/gdal-dev/2014-July/039527.html
+        if( static_cast<unsigned char>(papszLines[0][0]) == 0xEF &&
+            static_cast<unsigned char>(papszLines[0][1]) == 0xBB &&
+            static_cast<unsigned char>(papszLines[0][2]) == 0xBF )
         {
-            memmove(papszLines[0], papszLines[0] + 3, strlen(papszLines[0] + 3) + 1);
+            memmove(papszLines[0],
+                    papszLines[0] + 3,
+                    strlen(papszLines[0] + 3) + 1);
         }
         if( poSRS->importFromESRI( papszLines ) != OGRERR_NONE )
         {
@@ -2020,6 +2094,36 @@ OGRSpatialReference *OGRShapeGeomFieldDefn::GetSpatialRef()
             poSRS = NULL;
         }
         CSLDestroy( papszLines );
+
+        // Some new? shapefiles have  EPSG authority nodes (#6485) Use
+        // them  to  'import'  TOWGS84  from EPSG  definition,  if  no
+        // TOWGS84 is present in the  .prj (which should be the case).
+        // We  could  potentially import  more,  or  just replace  the
+        // entire definition
+        const char* pszAuthorityName = NULL;
+        const char* pszAuthorityCode = NULL;
+        double adfTOWGS84[7] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+        if( poSRS != NULL &&
+            poSRS->GetTOWGS84(adfTOWGS84, 7) == OGRERR_FAILURE &&
+            (pszAuthorityName = poSRS->GetAuthorityName(NULL)) != NULL &&
+            EQUAL(pszAuthorityName, "EPSG") &&
+            (pszAuthorityCode = poSRS->GetAuthorityCode(NULL)) != NULL )
+        {
+            const int nEPSGCode = atoi(pszAuthorityCode);
+            OGRSpatialReference oSRS;
+            if( oSRS.importFromEPSG(nEPSGCode) == OGRERR_NONE &&
+                oSRS.GetTOWGS84(adfTOWGS84, 7) == OGRERR_NONE )
+            {
+                CPLDebug(
+                    "Shape", "Importing TOWGS84 node from EPSG definition");
+                poSRS->SetTOWGS84(adfTOWGS84[0], adfTOWGS84[1], adfTOWGS84[2],
+                                  adfTOWGS84[3], adfTOWGS84[4], adfTOWGS84[5],
+                                  adfTOWGS84[6]);
+            }
+        }
+
+        if( poSRS )
+            poSRS->AutoIdentifyEPSG();
     }
 
     return poSRS;
@@ -2037,24 +2141,22 @@ OGRSpatialReference *OGRShapeGeomFieldDefn::GetSpatialRef()
 int OGRShapeLayer::ResetGeomType( int nNewGeomType )
 
 {
-    char        abyHeader[100];
-    int         nStartPos;
-
     if( nTotalShapeCount > 0 )
         return FALSE;
 
     if( hSHP->fpSHX == NULL)
     {
         CPLError( CE_Failure, CPLE_NotSupported,
-                  " OGRShapeLayer::ResetGeomType failed : SHX file is closed");
+                  "OGRShapeLayer::ResetGeomType failed: SHX file is closed");
         return FALSE;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Update .shp header.                                             */
 /* -------------------------------------------------------------------- */
-    nStartPos = (int)( hSHP->sHooks.FTell( hSHP->fpSHP ) );
+    int nStartPos = static_cast<int>( hSHP->sHooks.FTell( hSHP->fpSHP ) );
 
+    char abyHeader[100] = {};
     if( hSHP->sHooks.FSeek( hSHP->fpSHP, 0, SEEK_SET ) != 0
         || hSHP->sHooks.FRead( abyHeader, 100, 1, hSHP->fpSHP ) != 1 )
         return FALSE;
@@ -2071,7 +2173,7 @@ int OGRShapeLayer::ResetGeomType( int nNewGeomType )
 /* -------------------------------------------------------------------- */
 /*      Update .shx header.                                             */
 /* -------------------------------------------------------------------- */
-    nStartPos = (int)( hSHP->sHooks.FTell( hSHP->fpSHX ) );
+    nStartPos = static_cast<int>( hSHP->sHooks.FTell( hSHP->fpSHX ) );
 
     if( hSHP->sHooks.FSeek( hSHP->fpSHX, 0, SEEK_SET ) != 0
         || hSHP->sHooks.FRead( abyHeader, 100, 1, hSHP->fpSHX ) != 1 )
@@ -2101,7 +2203,7 @@ int OGRShapeLayer::ResetGeomType( int nNewGeomType )
 OGRErr OGRShapeLayer::SyncToDisk()
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( bHeaderDirty )
@@ -2112,7 +2214,7 @@ OGRErr OGRShapeLayer::SyncToDisk()
         if( hDBF != NULL )
             DBFUpdateHeader( hDBF );
 
-        bHeaderDirty = FALSE;
+        bHeaderDirty = false;
     }
 
     if( hSHP != NULL )
@@ -2127,6 +2229,9 @@ OGRErr OGRShapeLayer::SyncToDisk()
         hDBF->sHooks.FFlush( hDBF->fp );
     }
 
+    if( m_eNeedRepack == YES && m_bAutoRepack )
+        Repack();
+
     return OGRERR_NONE;
 }
 
@@ -2137,7 +2242,7 @@ OGRErr OGRShapeLayer::SyncToDisk()
 OGRErr OGRShapeLayer::DropSpatialIndex()
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( !CheckForQIX() && !CheckForSBN() )
@@ -2148,41 +2253,40 @@ OGRErr OGRShapeLayer::DropSpatialIndex()
         return OGRERR_FAILURE;
     }
 
-    int bHadQIX = hQIX != NULL;
+    const bool bHadQIX = hQIX != NULL;
 
     SHPCloseDiskTree( hQIX );
     hQIX = NULL;
-    bCheckedForQIX = FALSE;
+    bCheckedForQIX = false;
 
     SBNCloseDiskTree( hSBN );
     hSBN = NULL;
-    bCheckedForSBN = FALSE;
+    bCheckedForSBN = false;
 
     if( bHadQIX )
     {
-        const char *pszQIXFilename;
-
-        pszQIXFilename = CPLResetExtension( pszFullName, "qix" );
+        const char *pszQIXFilename =
+            CPLResetExtension( pszFullName, "qix" );
         CPLDebug( "SHAPE", "Unlinking index file %s", pszQIXFilename );
 
         if( VSIUnlink( pszQIXFilename ) != 0 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "Failed to delete file %s.\n%s",
-                    pszQIXFilename, VSIStrerror( errno ) );
+                      "Failed to delete file %s.\n%s",
+                      pszQIXFilename, VSIStrerror( errno ) );
             return OGRERR_FAILURE;
         }
     }
 
     if( !bSbnSbxDeleted )
     {
-        const char *pszIndexFilename;
         const char papszExt[2][4] = { "sbn", "sbx" };
-        int i;
-        for( i = 0; i < 2; i++ )
+        for( int i = 0; i < 2; i++ )
         {
-            pszIndexFilename = CPLResetExtension( pszFullName, papszExt[i] );
-            CPLDebug( "SHAPE", "Trying to unlink index file %s", pszIndexFilename );
+            const char *pszIndexFilename =
+                CPLResetExtension( pszFullName, papszExt[i] );
+            CPLDebug(
+                "SHAPE", "Trying to unlink index file %s", pszIndexFilename );
 
             if( VSIUnlink( pszIndexFilename ) != 0 )
             {
@@ -2192,7 +2296,7 @@ OGRErr OGRShapeLayer::DropSpatialIndex()
             }
         }
     }
-    bSbnSbxDeleted = TRUE;
+    bSbnSbxDeleted = true;
 
     ClearSpatialFIDs();
 
@@ -2206,7 +2310,7 @@ OGRErr OGRShapeLayer::DropSpatialIndex()
 OGRErr OGRShapeLayer::CreateSpatialIndex( int nMaxDepth )
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
 /* -------------------------------------------------------------------- */
@@ -2215,20 +2319,17 @@ OGRErr OGRShapeLayer::CreateSpatialIndex( int nMaxDepth )
     if( CheckForQIX() )
         DropSpatialIndex();
 
-    bCheckedForQIX = FALSE;
+    bCheckedForQIX = false;
 
 /* -------------------------------------------------------------------- */
 /*      Build a quadtree structure for this file.                       */
 /* -------------------------------------------------------------------- */
-    SHPTree	*psTree;
-
     SyncToDisk();
-    psTree = SHPCreateTree( hSHP, 2, nMaxDepth, NULL, NULL );
+    SHPTree *psTree = SHPCreateTree( hSHP, 2, nMaxDepth, NULL, NULL );
 
     if( NULL == psTree )
     {
-        // TODO - mloskot: Is it better to return OGRERR_NOT_ENOUGH_MEMORY?
-
+        // TODO(mloskot): Is it better to return OGRERR_NOT_ENOUGH_MEMORY?
         CPLDebug( "SHAPE",
                   "Index creation failure. Likely, memory allocation error." );
 
@@ -2243,16 +2344,13 @@ OGRErr OGRShapeLayer::CreateSpatialIndex( int nMaxDepth )
 /* -------------------------------------------------------------------- */
 /*      Dump tree to .qix file.                                         */
 /* -------------------------------------------------------------------- */
-    char *pszQIXFilename;
-
-    pszQIXFilename = CPLStrdup(CPLResetExtension( pszFullName, "qix" ));
+    char *pszQIXFilename = CPLStrdup(CPLResetExtension( pszFullName, "qix" ));
 
     CPLDebug( "SHAPE", "Creating index file %s", pszQIXFilename );
 
     SHPWriteTree( psTree, pszQIXFilename );
     CPLFree( pszQIXFilename );
 
-
 /* -------------------------------------------------------------------- */
 /*      cleanup                                                         */
 /* -------------------------------------------------------------------- */
@@ -2357,6 +2455,12 @@ static void ForceDeleteFile( const CPLString& osFilename )
 OGRErr OGRShapeLayer::Repack()
 
 {
+    if( m_eNeedRepack == NO )
+    {
+        CPLDebug("Shape", "REPACK: nothing to do. Was done previously");
+        return OGRERR_NONE;
+    }
+
     if( !TouchLayer() )
         return OGRERR_FAILURE;
 
@@ -2376,6 +2480,8 @@ OGRErr OGRShapeLayer::Repack()
     int nDeleteCountAlloc = 128;
     OGRErr eErr = OGRERR_NONE;
 
+    CPLDebug("Shape", "REPACK: Checking if features have been deleted");
+
     if( hDBF != NULL )
     {
         for( int iShape = 0; iShape < nTotalShapeCount; iShape++ )
@@ -2424,6 +2530,7 @@ OGRErr OGRShapeLayer::Repack()
 /* -------------------------------------------------------------------- */
     if( nDeleteCount == 0 && !bSHPNeedsRepack )
     {
+        CPLDebug("Shape", "REPACK: nothing to do");
         CPLFree( panRecordsToDelete );
         return OGRERR_NONE;
     }
@@ -2474,7 +2581,7 @@ OGRErr OGRShapeLayer::Repack()
     CSLDestroy(papszCandidates);
     papszCandidates = NULL;
 
-    if( hDBF != NULL && osDBFName.size() == 0 )
+    if( hDBF != NULL && osDBFName.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find the filename of the DBF file, but we managed to "
@@ -2484,7 +2591,7 @@ OGRErr OGRShapeLayer::Repack()
         return OGRERR_FAILURE;
     }
 
-    if( hSHP != NULL && osSHPName.size() == 0 )
+    if( hSHP != NULL && osSHPName.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find the filename of the SHP file, but we managed to "
@@ -2494,7 +2601,7 @@ OGRErr OGRShapeLayer::Repack()
         return OGRERR_FAILURE;
     }
 
-    if( hSHP != NULL && osSHXName.size() == 0 )
+    if( hSHP != NULL && osSHXName.empty() )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find the filename of the SHX file, but we managed to "
@@ -2520,6 +2627,7 @@ OGRErr OGRShapeLayer::Repack()
 
     if( hDBF != NULL && nDeleteCount > 0 )
     {
+        CPLDebug("Shape", "REPACK: repacking .dbf");
         bMustReopenDBF = true;
 
         oTempFileDBF = CPLFormFilename(osDirname, osBasename, NULL);
@@ -2537,7 +2645,7 @@ OGRErr OGRShapeLayer::Repack()
         }
 
         // Delete temporary .cpg file if existing.
-        if( osCPGName.size() )
+        if( !osCPGName.empty() )
         {
             CPLString oCPGTempFile =
                 CPLFormFilename(osDirname, osBasename, NULL);
@@ -2609,6 +2717,8 @@ OGRErr OGRShapeLayer::Repack()
 
     if( hSHP != NULL )
     {
+        CPLDebug("Shape", "REPACK: repacking .shp + .shx");
+
         oTempFileSHP = CPLFormFilename(osDirname, osBasename, NULL);
         oTempFileSHP += "_packed.shp";
         oTempFileSHX = CPLFormFilename(osDirname, osBasename, NULL);
@@ -2705,8 +2815,8 @@ OGRErr OGRShapeLayer::Repack()
         {
             if( !CopyInPlace( VSI_SHP_GetVSIL(hDBF->fp), oTempFileDBF ) )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
-                        "An error occured while copying the content of %s on top of %s. "
+                CPLError( CE_Failure, CPLE_FileIO,
+                        "An error occurred while copying the content of %s on top of %s. "
                         "The non corrupted version is in the _packed.dbf, "
                         "_packed.shp and _packed.shx files that you should rename "
                         "on top of the main ones.",
@@ -2734,8 +2844,8 @@ OGRErr OGRShapeLayer::Repack()
         {
             if( !CopyInPlace( VSI_SHP_GetVSIL(hSHP->fpSHP), oTempFileSHP ) )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
-                        "An error occured while copying the content of %s on top of %s. "
+                CPLError( CE_Failure, CPLE_FileIO,
+                        "An error occurred while copying the content of %s on top of %s. "
                         "The non corrupted version is in the _packed.dbf, "
                         "_packed.shp and _packed.shx files that you should rename "
                         "on top of the main ones.",
@@ -2756,8 +2866,8 @@ OGRErr OGRShapeLayer::Repack()
             }
             if( !CopyInPlace( VSI_SHP_GetVSIL(hSHP->fpSHX), oTempFileSHX ) )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
-                        "An error occured while copying the content of %s on top of %s. "
+                CPLError( CE_Failure, CPLE_FileIO,
+                        "An error occurred while copying the content of %s on top of %s. "
                         "The non corrupted version is in the _packed.dbf, "
                         "_packed.shp and _packed.shx files that you should rename "
                         "on top of the main ones.",
@@ -2821,7 +2931,7 @@ OGRErr OGRShapeLayer::Repack()
 
             if( VSIUnlink( osDBFName ) != 0 )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
+                CPLError( CE_Failure, CPLE_FileIO,
                         "Failed to delete old DBF file: %s",
                         VSIStrerror( errno ) );
 
@@ -2834,7 +2944,7 @@ OGRErr OGRShapeLayer::Repack()
 
             if( VSIRename( oTempFileDBF, osDBFName ) != 0 )
             {
-                CPLError( CE_Failure, CPLE_FileIO, 
+                CPLError( CE_Failure, CPLE_FileIO,
                         "Can not rename new DBF file: %s",
                         VSIStrerror( errno ) );
                 return OGRERR_FAILURE;
@@ -2909,7 +3019,8 @@ OGRErr OGRShapeLayer::Repack()
 /* -------------------------------------------------------------------- */
     if( hDBF != NULL )
         nTotalShapeCount = hDBF->nRecords;
-    bSHPNeedsRepack = FALSE;
+    bSHPNeedsRepack = false;
+    m_eNeedRepack = NO;
 
     return OGRERR_NONE;
 }
@@ -2924,7 +3035,7 @@ OGRErr OGRShapeLayer::Repack()
 OGRErr OGRShapeLayer::ResizeDBF()
 
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( !bUpdateAccess )
@@ -2937,18 +3048,19 @@ OGRErr OGRShapeLayer::ResizeDBF()
 
     if( hDBF == NULL )
     {
-        CPLError( CE_Failure, CPLE_NotSupported,
-                  "Attempt to RESIZE a shapefile with no .dbf file not supported.");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "Attempt to RESIZE a shapefile with no .dbf file not supported.");
         return OGRERR_FAILURE;
     }
 
-    int i, j;
-
     /* Look which columns must be examined */
-    int* panColMap = (int*) CPLMalloc(poFeatureDefn->GetFieldCount() * sizeof(int));
-    int* panBestWidth = (int*) CPLMalloc(poFeatureDefn->GetFieldCount() * sizeof(int));
+    int *panColMap = static_cast<int *>(
+        CPLMalloc(poFeatureDefn->GetFieldCount() * sizeof(int)));
+    int *panBestWidth = static_cast<int *>(
+        CPLMalloc(poFeatureDefn->GetFieldCount() * sizeof(int)));
     int nStringCols = 0;
-    for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         if( poFeatureDefn->GetFieldDefn(i)->GetType() == OFTString ||
             poFeatureDefn->GetFieldDefn(i)->GetType() == OFTInteger ||
@@ -2956,13 +3068,13 @@ OGRErr OGRShapeLayer::ResizeDBF()
         {
             panColMap[nStringCols] = i;
             panBestWidth[nStringCols] = 1;
-            nStringCols ++;
+            nStringCols++;
         }
     }
 
-    if (nStringCols == 0)
+    if( nStringCols == 0 )
     {
-        /* Nothing to do */
+        // Nothing to do.
         CPLFree(panColMap);
         CPLFree(panBestWidth);
         return OGRERR_NONE;
@@ -2970,55 +3082,59 @@ OGRErr OGRShapeLayer::ResizeDBF()
 
     CPLDebug("SHAPE", "Computing optimal column size...");
 
-    int bAlreadyWarned = FALSE;
-    for( i = 0; i < hDBF->nRecords; i++ )
+    bool bAlreadyWarned = false;
+    for( int i = 0; i < hDBF->nRecords; i++ )
     {
         if( !DBFIsRecordDeleted( hDBF, i ) )
         {
-            for( j = 0; j < nStringCols; j ++)
+            for( int j = 0; j < nStringCols; j++ )
             {
-                if (DBFIsAttributeNULL(hDBF, i, panColMap[j]))
+                if( DBFIsAttributeNULL(hDBF, i, panColMap[j]) )
                     continue;
 
-                const char* pszVal = DBFReadStringAttribute(hDBF, i, panColMap[j]);
-                int nLen =  static_cast<int>(strlen(pszVal));
-                if (nLen > panBestWidth[j])
+                const char *pszVal =
+                    DBFReadStringAttribute(hDBF, i, panColMap[j]);
+                const int nLen =  static_cast<int>(strlen(pszVal));
+                if( nLen > panBestWidth[j] )
                     panBestWidth[j] = nLen;
             }
         }
-        else if (!bAlreadyWarned)
+        else if( !bAlreadyWarned )
         {
-            bAlreadyWarned = TRUE;
-            CPLDebug("SHAPE",
-                     "DBF file would also need a REPACK due to deleted records");
+            bAlreadyWarned = true;
+            CPLDebug(
+                "SHAPE",
+                "DBF file would also need a REPACK due to deleted records");
         }
     }
 
-    for( j = 0; j < nStringCols; j ++)
+    for( int j = 0; j < nStringCols; j++ )
     {
-        int             iField = panColMap[j];
-        OGRFieldDefn*   poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
-
-        char            szFieldName[20];
-        int             nOriWidth, nPrecision;
-        char            chNativeType;
-        /* DBFFieldType    eDBFType; */
+        const int iField = panColMap[j];
+        OGRFieldDefn* const poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
 
-        chNativeType = DBFGetNativeFieldType( hDBF, iField );
-        /* eDBFType = */ DBFGetFieldInfo( hDBF, iField, szFieldName,
-                                          &nOriWidth, &nPrecision );
+        const char chNativeType = DBFGetNativeFieldType( hDBF, iField );
+        char szFieldName[XBASE_FLDNAME_LEN_READ+1] = {};
+        int nOriWidth = 0;
+        int nPrecision = 0;
+        DBFGetFieldInfo( hDBF, iField, szFieldName,
+                         &nOriWidth, &nPrecision );
 
-        if (panBestWidth[j] < nOriWidth)
+        if( panBestWidth[j] < nOriWidth )
         {
-            CPLDebug("SHAPE", "Shrinking field %d (%s) from %d to %d characters",
-                        iField, poFieldDefn->GetNameRef(), nOriWidth, panBestWidth[j]);
+            CPLDebug(
+                "SHAPE", "Shrinking field %d (%s) from %d to %d characters",
+                iField, poFieldDefn->GetNameRef(), nOriWidth, panBestWidth[j]);
 
-            if (!DBFAlterFieldDefn( hDBF, iField, szFieldName,
-                                    chNativeType, panBestWidth[j], nPrecision ))
+            if( !DBFAlterFieldDefn( hDBF, iField, szFieldName,
+                                    chNativeType, panBestWidth[j],
+                                    nPrecision ) )
             {
-                CPLError(CE_Failure, CPLE_AppDefined,
-                        "Shrinking field %d (%s) from %d to %d characters failed",
-                        iField, poFieldDefn->GetNameRef(), nOriWidth, panBestWidth[j]);
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Shrinking field %d (%s) from %d to %d characters failed",
+                    iField, poFieldDefn->GetNameRef(), nOriWidth,
+                    panBestWidth[j]);
 
                 CPLFree(panColMap);
                 CPLFree(panBestWidth);
@@ -3046,18 +3162,23 @@ OGRErr OGRShapeLayer::ResizeDBF()
 
 void OGRShapeLayer::TruncateDBF()
 {
-    if (hDBF == NULL)
+    if( hDBF == NULL )
         return;
 
     hDBF->sHooks.FSeek(hDBF->fp, 0, SEEK_END);
     vsi_l_offset nOldSize = hDBF->sHooks.FTell(hDBF->fp);
-    vsi_l_offset nNewSize = hDBF->nRecordLength * (SAOffset) hDBF->nRecords
-                            + hDBF->nHeaderLength;
-    if (nNewSize < nOldSize)
-    {
-        CPLDebug("SHAPE",
-                 "Truncating DBF file from " CPL_FRMT_GUIB " to " CPL_FRMT_GUIB " bytes",
-                 nOldSize, nNewSize);
+    vsi_l_offset nNewSize =
+        hDBF->nRecordLength * static_cast<SAOffset>(hDBF->nRecords)
+        + hDBF->nHeaderLength;
+    if( hDBF->bWriteEndOfFileChar )
+        nNewSize ++;
+    if( nNewSize < nOldSize )
+    {
+        CPLDebug(
+            "SHAPE",
+            "Truncating DBF file from " CPL_FRMT_GUIB " to " CPL_FRMT_GUIB
+            " bytes",
+            nOldSize, nNewSize);
         VSIFTruncateL(VSI_SHP_GetVSIL(hDBF->fp), nNewSize);
     }
     hDBF->sHooks.FSeek(hDBF->fp, 0, SEEK_SET);
@@ -3071,7 +3192,7 @@ void OGRShapeLayer::TruncateDBF()
 
 OGRErr OGRShapeLayer::RecomputeExtent()
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return OGRERR_FAILURE;
 
     if( !bUpdateAccess )
@@ -3084,15 +3205,17 @@ OGRErr OGRShapeLayer::RecomputeExtent()
 
     if( hSHP == NULL )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "The RECOMPUTE EXTENT operation is not permitted on a layer without .SHP file." );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "The RECOMPUTE EXTENT operation is not permitted on a layer "
+            "without .SHP file." );
         return OGRERR_FAILURE;
     }
 
     double adBoundsMin[4] = { 0.0, 0.0, 0.0, 0.0 };
     double adBoundsMax[4] = { 0.0, 0.0, 0.0, 0.0 };
 
-    int bHasBeenInit = FALSE;
+    bool bHasBeenInit = false;
 
     for( int iShape = 0;
          iShape < nTotalShapeCount;
@@ -3101,36 +3224,46 @@ OGRErr OGRShapeLayer::RecomputeExtent()
         if( hDBF == NULL || !DBFIsRecordDeleted( hDBF, iShape ) )
         {
             SHPObject *psObject = SHPReadObject( hSHP, iShape );
-            if ( psObject != NULL &&
-                 psObject->nSHPType != SHPT_NULL &&
-                 psObject->nVertices != 0 )
+            if( psObject != NULL &&
+                psObject->nSHPType != SHPT_NULL &&
+                psObject->nVertices != 0 )
             {
                 if( !bHasBeenInit )
                 {
-                    bHasBeenInit = TRUE;
-                    adBoundsMin[0] = adBoundsMax[0] = psObject->padfX[0];
-                    adBoundsMin[1] = adBoundsMax[1] = psObject->padfY[0];
+                    bHasBeenInit = true;
+                    adBoundsMin[0] = psObject->padfX[0];
+                    adBoundsMax[0] = psObject->padfX[0];
+                    adBoundsMin[1] = psObject->padfY[0];
+                    adBoundsMax[1] = psObject->padfY[0];
                     if( psObject->padfZ )
-                        adBoundsMin[2] = adBoundsMax[2] = psObject->padfZ[0];
+                    {
+                        adBoundsMin[2] = psObject->padfZ[0];
+                        adBoundsMax[2] = psObject->padfZ[0];
+                    }
                     if( psObject->padfM )
-                        adBoundsMin[3] = adBoundsMax[3] = psObject->padfM[0];
+                    {
+                        adBoundsMin[3] = psObject->padfM[0];
+                        adBoundsMax[3] = psObject->padfM[0];
+                    }
                 }
 
                 for( int i = 0; i < psObject->nVertices; i++ )
                 {
-                    adBoundsMin[0] = MIN(adBoundsMin[0],psObject->padfX[i]);
-                    adBoundsMin[1] = MIN(adBoundsMin[1],psObject->padfY[i]);
-                    adBoundsMax[0] = MAX(adBoundsMax[0],psObject->padfX[i]);
-                    adBoundsMax[1] = MAX(adBoundsMax[1],psObject->padfY[i]);
+                    adBoundsMin[0] = std::min(adBoundsMin[0], psObject->padfX[i]);
+                    adBoundsMin[1] = std::min(adBoundsMin[1], psObject->padfY[i]);
+                    adBoundsMax[0] = std::max(adBoundsMax[0], psObject->padfX[i]);
+                    adBoundsMax[1] = std::max(adBoundsMax[1], psObject->padfY[i]);
                     if( psObject->padfZ )
                     {
-                        adBoundsMin[2] = MIN(adBoundsMin[2],psObject->padfZ[i]);
-                        adBoundsMax[2] = MAX(adBoundsMax[2],psObject->padfZ[i]);
+                        adBoundsMin[2] = std::min(adBoundsMin[2],
+                                                  psObject->padfZ[i]);
+                        adBoundsMax[2] = std::max(adBoundsMax[2], psObject->padfZ[i]);
                     }
                     if( psObject->padfM )
                     {
-                        adBoundsMax[3] = MAX(adBoundsMax[3],psObject->padfM[i]);
-                        adBoundsMin[3] = MIN(adBoundsMin[3],psObject->padfM[i]);
+                        adBoundsMax[3] = std::max(adBoundsMax[3], psObject->padfM[i]);
+                        adBoundsMin[3] = std::min(adBoundsMin[3],
+                                                  psObject->padfM[i]);
                     }
                 }
             }
@@ -3141,7 +3274,7 @@ OGRErr OGRShapeLayer::RecomputeExtent()
     if( memcmp(hSHP->adBoundsMin, adBoundsMin, 4*sizeof(double)) != 0 ||
         memcmp(hSHP->adBoundsMax, adBoundsMax, 4*sizeof(double)) != 0 )
     {
-        bHeaderDirty = TRUE;
+        bHeaderDirty = true;
         hSHP->bUpdated = TRUE;
         memcpy(hSHP->adBoundsMin, adBoundsMin, 4*sizeof(double));
         memcpy(hSHP->adBoundsMax, adBoundsMax, 4*sizeof(double));
@@ -3150,64 +3283,57 @@ OGRErr OGRShapeLayer::RecomputeExtent()
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                              TouchLayer()                            */
 /************************************************************************/
 
-int OGRShapeLayer::TouchLayer()
+bool OGRShapeLayer::TouchLayer()
 {
     poDS->SetLastUsedLayer(this);
 
-    if (eFileDescriptorsState == FD_OPENED)
-        return TRUE;
-    else if (eFileDescriptorsState == FD_CANNOT_REOPEN)
-        return FALSE;
-    else
-        return ReopenFileDescriptors();
+    if( eFileDescriptorsState == FD_OPENED )
+        return true;
+    if( eFileDescriptorsState == FD_CANNOT_REOPEN )
+        return false;
+
+    return ReopenFileDescriptors();
 }
 
 /************************************************************************/
 /*                        ReopenFileDescriptors()                       */
 /************************************************************************/
 
-int OGRShapeLayer::ReopenFileDescriptors()
+bool OGRShapeLayer::ReopenFileDescriptors()
 {
     CPLDebug("SHAPE", "ReopenFileDescriptors(%s)", pszFullName);
 
     if( bHSHPWasNonNULL )
     {
-        if( bUpdateAccess )
-            hSHP = poDS->DS_SHPOpen( pszFullName, "r+" );
-        else
-            hSHP = poDS->DS_SHPOpen( pszFullName, "r" );
+        hSHP = poDS->DS_SHPOpen( pszFullName, bUpdateAccess ? "r+" : "r" );
 
-        if (hSHP == NULL)
+        if( hSHP == NULL )
         {
             eFileDescriptorsState = FD_CANNOT_REOPEN;
-            return FALSE;
+            return false;
         }
     }
 
     if( bHDBFWasNonNULL )
     {
-        if( bUpdateAccess )
-            hDBF = poDS->DS_DBFOpen( pszFullName, "r+" );
-        else
-            hDBF = poDS->DS_DBFOpen( pszFullName, "r" );
+        hDBF = poDS->DS_DBFOpen( pszFullName, bUpdateAccess ? "r+" : "r" );
 
-        if (hDBF == NULL)
+        if( hDBF == NULL )
         {
             CPLError(CE_Failure, CPLE_OpenFailed,
                      "Cannot reopen %s", CPLResetExtension(pszFullName, "dbf"));
             eFileDescriptorsState = FD_CANNOT_REOPEN;
-            return FALSE;
+            return false;
         }
     }
 
     eFileDescriptorsState = FD_OPENED;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -3226,17 +3352,17 @@ void OGRShapeLayer::CloseUnderlyingLayer()
         SHPClose( hSHP );
     hSHP = NULL;
 
-    /* We close QIX and reset the check flag, so that CheckForQIX() */
-    /* will retry opening it if necessary when the layer is active again */
+    // We close QIX and reset the check flag, so that CheckForQIX()
+    // will retry opening it if necessary when the layer is active again.
     if( hQIX != NULL )
         SHPCloseDiskTree( hQIX );
     hQIX = NULL;
-    bCheckedForQIX = FALSE;
+    bCheckedForQIX = false;
 
     if( hSBN != NULL )
         SBNCloseDiskTree( hSBN );
     hSBN = NULL;
-    bCheckedForSBN = FALSE;
+    bCheckedForSBN = false;
 
     eFileDescriptorsState = FD_CLOSED;
 }
@@ -3247,17 +3373,20 @@ void OGRShapeLayer::CloseUnderlyingLayer()
 
 void OGRShapeLayer::AddToFileList( CPLStringList& oFileList )
 {
-    if (!TouchLayer())
+    if( !TouchLayer() )
         return;
+
     if( hSHP )
     {
         const char* pszSHPFilename = VSI_SHP_GetFilename( hSHP->fpSHP );
         oFileList.AddString(pszSHPFilename);
         const char* pszSHPExt = CPLGetExtension(pszSHPFilename);
-        const char* pszSHXFilename = CPLResetExtension( pszSHPFilename,
-                                        (pszSHPExt[0] == 's') ? "shx" : "SHX" );
+        const char* pszSHXFilename = CPLResetExtension(
+            pszSHPFilename,
+            (pszSHPExt[0] == 's') ? "shx" : "SHX" );
         oFileList.AddString(pszSHXFilename);
     }
+
     if( hDBF )
     {
         const char* pszDBFFilename = VSI_SHP_GetFilename( hDBF->fp );
@@ -3265,11 +3394,13 @@ void OGRShapeLayer::AddToFileList( CPLStringList& oFileList )
         if( hDBF->pszCodePage != NULL && hDBF->iLanguageDriver == 0 )
         {
             const char* pszDBFExt = CPLGetExtension(pszDBFFilename);
-            const char* pszCPGFilename = CPLResetExtension( pszDBFFilename,
-                                       (pszDBFExt[0] == 'd') ? "cpg" : "CPG"  );
+            const char* pszCPGFilename = CPLResetExtension(
+                pszDBFFilename,
+                (pszDBFExt[0] == 'd') ? "cpg" : "CPG" );
             oFileList.AddString(pszCPGFilename);
         }
     }
+
     if( hSHP )
     {
         if( GetSpatialRef() != NULL )
@@ -3280,14 +3411,17 @@ void OGRShapeLayer::AddToFileList( CPLStringList& oFileList )
         }
         if( CheckForQIX() )
         {
-            const char* pszQIXFilename = CPLResetExtension( pszFullName, "qix" );
+            const char* pszQIXFilename =
+                CPLResetExtension( pszFullName, "qix" );
             oFileList.AddString(pszQIXFilename);
         }
         else if( CheckForSBN() )
         {
-            const char* pszSBNFilename = CPLResetExtension( pszFullName, "sbn" );
+            const char* pszSBNFilename =
+                CPLResetExtension( pszFullName, "sbn" );
             oFileList.AddString(pszSBNFilename);
-            const char* pszSBXFilename = CPLResetExtension( pszFullName, "sbx" );
+            const char* pszSBXFilename =
+                CPLResetExtension( pszFullName, "sbx" );
             oFileList.AddString(pszSBXFilename);
         }
     }
diff --git a/ogr/ogrsf_frmts/shape/sbnsearch.c b/ogr/ogrsf_frmts/shape/sbnsearch.c
index 8ad4317..11272b4 100644
--- a/ogr/ogrsf_frmts/shape/sbnsearch.c
+++ b/ogr/ogrsf_frmts/shape/sbnsearch.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: sbnsearch.c 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: sbnsearch.c 36763 2016-12-09 22:10:55Z rouault $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of search in ESRI SBN spatial index.
@@ -9,7 +9,7 @@
  * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * or at the option of the licensee under the LGPL (see COPYING).  This
  * option is discussed in more detail in shapelib.html.
  *
  * --
@@ -40,13 +40,25 @@
 #include <stdlib.h>
 #include <string.h>
 
-SHP_CVSID("$Id: sbnsearch.c 33713 2016-03-12 17:41:57Z goatbar $")
+SHP_CVSID("$Id: sbnsearch.c 36763 2016-12-09 22:10:55Z rouault $")
 
 #ifndef TRUE
 #  define TRUE 1
 #  define FALSE 0
 #endif
 
+#ifndef USE_CPL
+#if defined(_MSC_VER)
+# if _MSC_VER < 1900
+#     define snprintf _snprintf
+# endif
+#elif defined(WIN32) || defined(_WIN32)
+#  ifndef snprintf
+#     define snprintf _snprintf
+#  endif
+#endif
+#endif
+
 #define READ_MSB_INT(ptr) \
         (((ptr)[0] << 24) | ((ptr)[1] << 16) | ((ptr)[2] << 8) | (ptr)[3])
 
@@ -700,8 +712,8 @@ static int SBNSearchDiskInternal( SearchStruct* psSearch,
                         bMaxX < bNodeMinX || bMaxY < bNodeMinY ||
                         bMinX > bNodeMaxX || bMinY > bNodeMaxY )
                     {
-                        /*printf("shape %d %d %d %d\n", bMinX, bMinY, bMaxX, bMaxY);
-                        printf("node  %d %d %d %d\n", bNodeMinX, bNodeMinY, bNodeMaxX, bNodeMaxY);*/
+                        /* printf("shape %d %d %d %d\n", bMinX, bMinY, bMaxX, bMaxY);*/
+                        /* printf("node  %d %d %d %d\n", bNodeMinX, bNodeMinY, bNodeMaxX, bNodeMaxY);*/
                         hSBN->sHooks.Error(
                             "Invalid shape bounding box in bin" );
                         free(psNode->pabyShapeDesc);
@@ -918,7 +930,7 @@ int* SBNSearchDiskTreeInteger( SBNSearchHandle hSBN,
     if( bMinX > bMaxX || bMinY > bMaxY )
         return NULL;
 
-    if( bMaxX < 0 || bMaxY < 0 || bMinX > 255 || bMinX > 255 )
+    if( bMaxX < 0 || bMaxY < 0 || bMinX > 255 || bMinY > 255 )
         return NULL;
 
     if( hSBN->nShapeCount == 0 )
@@ -926,6 +938,7 @@ int* SBNSearchDiskTreeInteger( SBNSearchHandle hSBN,
 /* -------------------------------------------------------------------- */
 /*      Run the search.                                                 */
 /* -------------------------------------------------------------------- */
+    memset( &sSearch, 0, sizeof(sSearch) );
     sSearch.hSBN = hSBN;
     sSearch.bMinX = (coord) (bMinX >= 0 ? bMinX : 0);
     sSearch.bMinY = (coord) (bMinY >= 0 ? bMinY : 0);
diff --git a/ogr/ogrsf_frmts/shape/shape2ogr.cpp b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
index 29b4b38..5f97d90 100644
--- a/ogr/ogrsf_frmts/shape/shape2ogr.cpp
+++ b/ogr/ogrsf_frmts/shape/shape2ogr.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: shape2ogr.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements translation of Shapefile shapes into OGR
@@ -30,67 +29,72 @@
  ****************************************************************************/
 
 #include "ogrshape.h"
+
 #include "cpl_conv.h"
+#include "ogrpgeogeometry.h"
+
+#include <algorithm>
 #include <limits>
 
-CPL_CVSID("$Id: shape2ogr.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: shape2ogr.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                        RingStartEnd                                  */
-/*        set first and last vertex for given ring                      */
+/*        Set first and last vertex for given ring.                     */
 /************************************************************************/
-static void RingStartEnd ( SHPObject *psShape, int ring, int *start, int *end )
+static void RingStartEnd( SHPObject *psShape, int ring, int *start, int *end )
 {
     if( psShape->panPartStart == NULL )
     {
-	    *start = 0;
+        *start = 0;
         *end = psShape->nVertices - 1;
     }
     else
     {
+        *start = psShape->panPartStart[ring];
+
         if( ring == psShape->nParts - 1 )
             *end = psShape->nVertices - 1;
         else
             *end = psShape->panPartStart[ring+1] - 1;
-
-        *start = psShape->panPartStart[ring];
     }
 }
 
 /************************************************************************/
 /*                        CreateLinearRing                              */
-/*                                                                      */
 /************************************************************************/
-static OGRLinearRing * CreateLinearRing ( SHPObject *psShape, int ring, int bHasZ, int bHasM )
+static OGRLinearRing * CreateLinearRing(
+    SHPObject *psShape, int ring, bool bHasZ, bool bHasM )
 {
-    OGRLinearRing *poRing;
-    int nRingStart, nRingEnd, nRingPoints;
-
-    poRing = new OGRLinearRing();
-
-    RingStartEnd ( psShape, ring, &nRingStart, &nRingEnd );
-    if( nRingEnd >= nRingStart )
-    {
-        nRingPoints = nRingEnd - nRingStart + 1;
-
-        if (bHasZ && bHasM)
-            poRing->setPoints( nRingPoints, psShape->padfX + nRingStart,
-                            psShape->padfY + nRingStart,
-                            psShape->padfZ + nRingStart,
-                               psShape->padfM ? psShape->padfM + nRingStart : NULL );
-        else if (bHasM)
-            poRing->setPointsM( nRingPoints, psShape->padfX + nRingStart,
-                            psShape->padfY + nRingStart,
-                                psShape->padfM ? psShape->padfM + nRingStart :NULL );
-        else
-            poRing->setPoints( nRingPoints, psShape->padfX + nRingStart,
-                            psShape->padfY + nRingStart );
-    }
+    int nRingStart = 0;
+    int nRingEnd = 0;
+    RingStartEnd( psShape, ring, &nRingStart, &nRingEnd );
+
+    OGRLinearRing * const poRing = new OGRLinearRing();
+    if( !(nRingEnd >= nRingStart) )
+        return poRing;
+
+    const int nRingPoints = nRingEnd - nRingStart + 1;
+
+    if( bHasZ && bHasM )
+        poRing->setPoints(
+            nRingPoints, psShape->padfX + nRingStart,
+            psShape->padfY + nRingStart,
+            psShape->padfZ + nRingStart,
+            psShape->padfM ? psShape->padfM + nRingStart : NULL );
+    else if( bHasM )
+        poRing->setPointsM(
+            nRingPoints, psShape->padfX + nRingStart,
+            psShape->padfY + nRingStart,
+            psShape->padfM ? psShape->padfM + nRingStart :NULL );
+    else
+        poRing->setPoints(
+            nRingPoints, psShape->padfX + nRingStart,
+            psShape->padfY + nRingStart );
 
-    return ( poRing );
+    return poRing;
 }
 
-
 /************************************************************************/
 /*                          SHPReadOGRObject()                          */
 /*                                                                      */
@@ -100,9 +104,9 @@ static OGRLinearRing * CreateLinearRing ( SHPObject *psShape, int ring, int bHas
 
 OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
 {
-    // CPLDebug( "Shape", "SHPReadOGRObject( iShape=%d )\n", iShape );
-
-    OGRGeometry *poOGR = NULL;
+#if DEBUG_VERBOSE
+    CPLDebug( "Shape", "SHPReadOGRObject( iShape=%d )", iShape );
+#endif
 
     if( psShape == NULL )
         psShape = SHPReadObject( hSHP, iShape );
@@ -112,10 +116,12 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
         return NULL;
     }
 
+    OGRGeometry *poOGR = NULL;
+
 /* -------------------------------------------------------------------- */
 /*      Point.                                                          */
 /* -------------------------------------------------------------------- */
-    else if( psShape->nSHPType == SHPT_POINT )
+    if( psShape->nSHPType == SHPT_POINT )
     {
         poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0] );
     }
@@ -132,7 +138,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                                   psShape->padfZ[0] );
         }
     }
-    else if(psShape->nSHPType == SHPT_POINTM )
+    else if( psShape->nSHPType == SHPT_POINTM )
     {
         poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0],
                               0.0, psShape->padfM[0] );
@@ -145,40 +151,44 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
              || psShape->nSHPType == SHPT_MULTIPOINTM
              || psShape->nSHPType == SHPT_MULTIPOINTZ )
     {
-        if (psShape->nVertices == 0)
+        if( psShape->nVertices == 0 )
         {
             poOGR = NULL;
         }
         else
         {
             OGRMultiPoint *poOGRMPoint = new OGRMultiPoint();
-            int             i;
 
-            for( i = 0; i < psShape->nVertices; i++ )
+            for( int i = 0; i < psShape->nVertices; i++ )
             {
-                OGRPoint    *poPoint;
+                OGRPoint *poPoint = NULL;
 
                 if( psShape->nSHPType == SHPT_MULTIPOINTZ )
                 {
                     if( psShape->padfM )
                     {
-                        poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i],
-                                                psShape->padfZ[i], psShape->padfM[i] );
+                        poPoint = new OGRPoint(
+                            psShape->padfX[i], psShape->padfY[i],
+                            psShape->padfZ[i], psShape->padfM[i] );
                     }
                     else
                     {
-                        poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i],
-                                                psShape->padfZ[i] );
+                        poPoint = new OGRPoint(
+                            psShape->padfX[i], psShape->padfY[i],
+                            psShape->padfZ[i] );
                     }
                 }
                 else if( psShape->nSHPType == SHPT_MULTIPOINTM )
                 {
-                    poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i],
-                                            0.0, psShape->padfM[i] );
+                    poPoint = new OGRPoint(psShape->padfX[i], psShape->padfY[i],
+                                           0.0, psShape->padfM[i]);
                     poPoint->set3D(FALSE);
                 }
                 else
-                    poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i] );
+                {
+                    poPoint =
+                        new OGRPoint( psShape->padfX[i], psShape->padfY[i] );
+                }
 
                 poOGRMPoint->addGeometry( poPoint );
 
@@ -192,7 +202,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
 /* -------------------------------------------------------------------- */
 /*      Arc (LineString)                                                */
 /*                                                                      */
-/*      I am ignoring parts though they can apply to arcs as well.      */
+/*      Ignoring parts though they can apply to arcs as well.           */
 /* -------------------------------------------------------------------- */
     else if( psShape->nSHPType == SHPT_ARC
              || psShape->nSHPType == SHPT_ARCM
@@ -205,33 +215,31 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
         else if( psShape->nParts == 1 )
         {
             OGRLineString *poOGRLine = new OGRLineString();
+            poOGR = poOGRLine;
 
             if( psShape->nSHPType == SHPT_ARCZ )
                 poOGRLine->setPoints( psShape->nVertices,
-                                      psShape->padfX, psShape->padfY, psShape->padfZ, psShape->padfM );
+                                      psShape->padfX, psShape->padfY,
+                                      psShape->padfZ, psShape->padfM );
             else if( psShape->nSHPType == SHPT_ARCM )
                 poOGRLine->setPointsM( psShape->nVertices,
-                                       psShape->padfX, psShape->padfY, psShape->padfM );
+                                       psShape->padfX, psShape->padfY,
+                                       psShape->padfM );
             else
                 poOGRLine->setPoints( psShape->nVertices,
                                       psShape->padfX, psShape->padfY );
-
-            poOGR = poOGRLine;
         }
         else
         {
-            int iRing;
-            OGRMultiLineString *poOGRMulti;
-
-            poOGR = poOGRMulti = new OGRMultiLineString();
+            OGRMultiLineString *poOGRMulti = new OGRMultiLineString();
+            poOGR = poOGRMulti;
 
-            for( iRing = 0; iRing < psShape->nParts; iRing++ )
+            for( int iRing = 0; iRing < psShape->nParts; iRing++ )
             {
-                OGRLineString   *poLine;
-                int     nRingPoints;
-                int     nRingStart;
+                int nRingPoints = 0;
+                int nRingStart = 0;
 
-                poLine = new OGRLineString();
+                OGRLineString *poLine = new OGRLineString();
 
                 if( psShape->panPartStart == NULL )
                 {
@@ -240,7 +248,6 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                 }
                 else
                 {
-
                     if( iRing == psShape->nParts - 1 )
                         nRingPoints =
                             psShape->nVertices - psShape->panPartStart[iRing];
@@ -251,20 +258,22 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
                 }
 
                 if( psShape->nSHPType == SHPT_ARCZ )
-                    poLine->setPoints( nRingPoints,
-                                    psShape->padfX + nRingStart,
-                                    psShape->padfY + nRingStart,
-                                    psShape->padfZ + nRingStart,
-                                    psShape->padfM ? psShape->padfM + nRingStart : NULL );
-                else if( psShape->nSHPType == SHPT_ARCM && psShape->padfM != NULL )
+                    poLine->setPoints(
+                        nRingPoints,
+                        psShape->padfX + nRingStart,
+                        psShape->padfY + nRingStart,
+                        psShape->padfZ + nRingStart,
+                        psShape->padfM ? psShape->padfM + nRingStart : NULL );
+                else if( psShape->nSHPType == SHPT_ARCM &&
+                         psShape->padfM != NULL )
                     poLine->setPointsM( nRingPoints,
-                                    psShape->padfX + nRingStart,
-                                    psShape->padfY + nRingStart,
-                                    psShape->padfM + nRingStart );
+                                        psShape->padfX + nRingStart,
+                                        psShape->padfY + nRingStart,
+                                        psShape->padfM + nRingStart );
                 else
                     poLine->setPoints( nRingPoints,
-                                    psShape->padfX + nRingStart,
-                                    psShape->padfY + nRingStart );
+                                       psShape->padfX + nRingStart,
+                                       psShape->padfY + nRingStart );
 
                 poOGRMulti->addGeometryDirectly( poLine );
             }
@@ -280,47 +289,53 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
              || psShape->nSHPType == SHPT_POLYGONM
              || psShape->nSHPType == SHPT_POLYGONZ )
     {
-        int iRing;
-        int bHasZ = ( psShape->nSHPType == SHPT_POLYGONZ );
-        int bHasM = ( bHasZ || (psShape->nSHPType == SHPT_POLYGONM) );
+        const bool bHasZ = psShape->nSHPType == SHPT_POLYGONZ;
+        const bool bHasM = bHasZ || psShape->nSHPType == SHPT_POLYGONM;
 
-        //CPLDebug( "Shape", "Shape type: polygon with nParts=%d \n", psShape->nParts );
+#if DEBUG_VERBOSE
+        CPLDebug( "Shape", "Shape type: polygon with nParts=%d",
+                  psShape->nParts );
+#endif
 
-        if ( psShape->nParts == 0 )
+        if( psShape->nParts == 0 )
         {
             poOGR = NULL;
         }
-        else if ( psShape->nParts == 1 )
+        else if( psShape->nParts == 1 )
         {
-            /* Surely outer ring */
-            OGRPolygon *poOGRPoly = NULL;
-            OGRLinearRing *poRing = NULL;
+            // Surely outer ring.
+            OGRPolygon *poOGRPoly = new OGRPolygon();
+            poOGR = poOGRPoly;
 
-            poOGR = poOGRPoly = new OGRPolygon();
-            poRing = CreateLinearRing ( psShape, 0, bHasZ, bHasM );
+            OGRLinearRing *poRing =
+                CreateLinearRing( psShape, 0, bHasZ, bHasM );
             poOGRPoly->addRingDirectly( poRing );
         }
-
         else
         {
             OGRPolygon** tabPolygons = new OGRPolygon*[psShape->nParts];
-            for( iRing = 0; iRing < psShape->nParts; iRing++ )
+            for( int iRing = 0; iRing < psShape->nParts; iRing++ )
             {
                 tabPolygons[iRing] = new OGRPolygon();
-                tabPolygons[iRing]->addRingDirectly(CreateLinearRing ( psShape, iRing, bHasZ, bHasM ));
+                tabPolygons[iRing]->addRingDirectly(
+                    CreateLinearRing( psShape, iRing, bHasZ, bHasM ));
             }
 
-            int isValidGeometry;
+            int isValidGeometry = FALSE;
             const char* papszOptions[] = { "METHOD=ONLY_CCW", NULL };
+            OGRGeometry **tabGeom =
+                reinterpret_cast<OGRGeometry**>(tabPolygons);
             poOGR = OGRGeometryFactory::organizePolygons(
-                (OGRGeometry**)tabPolygons, psShape->nParts, &isValidGeometry, papszOptions );
+                tabGeom, psShape->nParts, &isValidGeometry, papszOptions );
 
-            if (!isValidGeometry)
+            if( !isValidGeometry )
             {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                        "Geometry of polygon of fid %d cannot be translated to Simple Geometry. "
-                        "All polygons will be contained in a multipolygon.\n",
-                        iShape);
+                CPLError(
+                    CE_Warning, CPLE_AppDefined,
+                    "Geometry of polygon of fid %d cannot be translated to "
+                    "Simple Geometry. "
+                    "All polygons will be contained in a multipolygon.",
+                    iShape);
             }
 
             delete[] tabPolygons;
@@ -332,139 +347,13 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
 /* -------------------------------------------------------------------- */
     else if( psShape->nSHPType == SHPT_MULTIPATCH )
     {
-        OGRMultiPolygon *poMP = new OGRMultiPolygon();
-        int iPart;
-        OGRPolygon *poLastPoly = NULL;
-
-        for( iPart = 0; iPart < psShape->nParts; iPart++ )
-        {
-            int nPartPoints, nPartStart;
-
-            // Figure out details about this part's vertex list.
-            if( psShape->panPartStart == NULL )
-            {
-                nPartPoints = psShape->nVertices;
-                nPartStart = 0;
-            }
-            else
-            {
-
-                if( iPart == psShape->nParts - 1 )
-                    nPartPoints =
-                        psShape->nVertices - psShape->panPartStart[iPart];
-                else
-                    nPartPoints = psShape->panPartStart[iPart+1]
-                        - psShape->panPartStart[iPart];
-                nPartStart = psShape->panPartStart[iPart];
-            }
-
-            if( psShape->panPartType[iPart] == SHPP_TRISTRIP )
-            {
-                int iBaseVert;
-
-                if( poLastPoly != NULL )
-                {
-                    poMP->addGeometryDirectly( poLastPoly );
-                    poLastPoly = NULL;
-                }
-
-                for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
-                {
-                    OGRPolygon *poPoly = new OGRPolygon();
-                    OGRLinearRing *poRing = new OGRLinearRing();
-                    int iSrcVert = iBaseVert + nPartStart;
-
-                    poRing->setPoint( 0,
-                                      psShape->padfX[iSrcVert],
-                                      psShape->padfY[iSrcVert],
-                                      psShape->padfZ[iSrcVert] );
-                    poRing->setPoint( 1,
-                                      psShape->padfX[iSrcVert+1],
-                                      psShape->padfY[iSrcVert+1],
-                                      psShape->padfZ[iSrcVert+1] );
-
-                    poRing->setPoint( 2,
-                                      psShape->padfX[iSrcVert+2],
-                                      psShape->padfY[iSrcVert+2],
-                                      psShape->padfZ[iSrcVert+2] );
-                    poRing->setPoint( 3,
-                                      psShape->padfX[iSrcVert],
-                                      psShape->padfY[iSrcVert],
-                                      psShape->padfZ[iSrcVert] );
-
-                    poPoly->addRingDirectly( poRing );
-                    poMP->addGeometryDirectly( poPoly );
-                }
-            }
-            else if( psShape->panPartType[iPart] == SHPP_TRIFAN )
-            {
-                int iBaseVert;
-
-                if( poLastPoly != NULL )
-                {
-                    poMP->addGeometryDirectly( poLastPoly );
-                    poLastPoly = NULL;
-                }
-
-                for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
-                {
-                    OGRPolygon *poPoly = new OGRPolygon();
-                    OGRLinearRing *poRing = new OGRLinearRing();
-                    int iSrcVert = iBaseVert + nPartStart;
-
-                    poRing->setPoint( 0,
-                                      psShape->padfX[nPartStart],
-                                      psShape->padfY[nPartStart],
-                                      psShape->padfZ[nPartStart] );
-                    poRing->setPoint( 1,
-                                      psShape->padfX[iSrcVert+1],
-                                      psShape->padfY[iSrcVert+1],
-                                      psShape->padfZ[iSrcVert+1] );
-
-                    poRing->setPoint( 2,
-                                      psShape->padfX[iSrcVert+2],
-                                      psShape->padfY[iSrcVert+2],
-                                      psShape->padfZ[iSrcVert+2] );
-                    poRing->setPoint( 3,
-                                      psShape->padfX[nPartStart],
-                                      psShape->padfY[nPartStart],
-                                      psShape->padfZ[nPartStart] );
-
-                    poPoly->addRingDirectly( poRing );
-                    poMP->addGeometryDirectly( poPoly );
-                }
-            }
-            else if( psShape->panPartType[iPart] == SHPP_OUTERRING
-                     || psShape->panPartType[iPart] == SHPP_INNERRING
-                     || psShape->panPartType[iPart] == SHPP_FIRSTRING
-                     || psShape->panPartType[iPart] == SHPP_RING )
-            {
-                if( poLastPoly != NULL
-                    && (psShape->panPartType[iPart] == SHPP_OUTERRING
-                        || psShape->panPartType[iPart] == SHPP_FIRSTRING) )
-                {
-                    poMP->addGeometryDirectly( poLastPoly );
-                    poLastPoly = NULL;
-                }
-
-                if( poLastPoly == NULL )
-                    poLastPoly = new OGRPolygon();
-
-                poLastPoly->addRingDirectly(
-                    CreateLinearRing( psShape, iPart, TRUE, TRUE ) );
-            }
-            else
-                CPLDebug( "OGR", "Unrecognized parttype %d, ignored.",
-                          psShape->panPartType[iPart] );
-        }
-
-        if( poLastPoly != NULL )
-        {
-            poMP->addGeometryDirectly( poLastPoly );
-            poLastPoly = NULL;
-        }
-
-        poOGR = poMP;
+        poOGR = OGRCreateFromMultiPatch( psShape->nParts,
+                                         psShape->panPartStart,
+                                         psShape->panPartType,
+                                         psShape->nVertices,
+                                         psShape->padfX,
+                                         psShape->padfY,
+                                         psShape->padfZ );
     }
 
 /* -------------------------------------------------------------------- */
@@ -477,7 +366,7 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
             CPLDebug( "OGR", "Unsupported shape type in SHPReadOGRObject()" );
         }
 
-        /* nothing returned */
+        // Nothing returned.
     }
 
 /* -------------------------------------------------------------------- */
@@ -493,23 +382,22 @@ OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
 /************************************************************************/
 static
 OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
-                          int bRewind, OGRwkbGeometryType eLayerGeomType )
+                          bool bRewind, OGRwkbGeometryType eLayerGeomType )
 
 {
-    int nReturnedShapeID;
 /* ==================================================================== */
 /*      Write "shape" with no geometry or with empty geometry           */
 /* ==================================================================== */
     if( poGeom == NULL || poGeom->IsEmpty() )
     {
-        SHPObject       *psShape;
-
-        psShape = SHPCreateObject( SHPT_NULL, -1, 0, NULL, NULL, 0, NULL, NULL, NULL, NULL );
-        nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
+        SHPObject *psShape =
+            SHPCreateObject( SHPT_NULL, -1, 0, NULL, NULL, 0,
+                             NULL, NULL, NULL, NULL );
+        const int nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
         if( nReturnedShapeID == -1 )
         {
-            //Assuming error is reported by SHPWriteObject()
+            // Assuming error is reported by SHPWriteObject().
             return OGRERR_FAILURE;
         }
     }
@@ -521,10 +409,6 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
              || hSHP->nShapeType == SHPT_POINTM
              || hSHP->nShapeType == SHPT_POINTZ )
     {
-        SHPObject       *psShape;
-        double          dfX, dfY, dfZ, dfM;
-        double          *pdfM;
-
         if( wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -535,11 +419,22 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
         }
 
-        OGRPoint        *poPoint = (OGRPoint *) poGeom;
-        dfX = poPoint->getX();
-        dfY = poPoint->getY();
-        dfZ = poPoint->getZ();
-        if( wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_POINTM || hSHP->nShapeType == SHPT_POINTZ) )
+        OGRPoint *poPoint = dynamic_cast<OGRPoint *>( poGeom );
+        if( poPoint == NULL )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                     "dynamic_cast failed.  Expected a point." );
+            return OGRERR_FAILURE;
+        }
+
+        const double dfX = poPoint->getX();
+        const double dfY = poPoint->getY();
+        const double dfZ = poPoint->getZ();
+        double dfM = 0.0;
+        double *pdfM = NULL;
+        if( wkbHasM(eLayerGeomType) &&
+            (hSHP->nShapeType == SHPT_POINTM ||
+             hSHP->nShapeType == SHPT_POINTZ) )
         {
             if( poGeom->IsMeasured() )
                 dfM = poPoint->getM();
@@ -547,12 +442,11 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
                 dfM = -std::numeric_limits<double>::max();
             pdfM = &dfM;
         }
-        else
-            pdfM = NULL;
 
-        psShape = SHPCreateObject( hSHP->nShapeType, -1, 0, NULL, NULL, 1,
-                                   &dfX, &dfY, &dfZ, pdfM );
-        nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
+        SHPObject *psShape =
+            SHPCreateObject( hSHP->nShapeType, -1, 0, NULL, NULL, 1,
+                             &dfX, &dfY, &dfZ, pdfM );
+        const int nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
         if( nReturnedShapeID == -1 )
             return OGRERR_FAILURE;
@@ -564,10 +458,6 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
              || hSHP->nShapeType == SHPT_MULTIPOINTM
              || hSHP->nShapeType == SHPT_MULTIPOINTZ )
     {
-        double          *padfX, *padfY, *padfZ, *padfM;
-        int             iPoint;
-        SHPObject       *psShape;
-
         if( wkbFlatten(poGeom->getGeometryType()) != wkbMultiPoint )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -579,21 +469,39 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
         }
 
         OGRMultiPoint   *poMP = (OGRMultiPoint *) poGeom;
-        padfX = (double *) CPLMalloc(sizeof(double)*poMP->getNumGeometries());
-        padfY = (double *) CPLMalloc(sizeof(double)*poMP->getNumGeometries());
-        padfZ = (double *) CPLCalloc(sizeof(double),poMP->getNumGeometries());
-        if( wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_MULTIPOINTM || hSHP->nShapeType == SHPT_MULTIPOINTZ) )
-            padfM = (double *) CPLCalloc(sizeof(double),poMP->getNumGeometries());
-        else
-            padfM = NULL;
+        double *padfX = static_cast<double *>(
+            CPLMalloc(sizeof(double) * poMP->getNumGeometries()));
+        double *padfY = static_cast<double *>(
+            CPLMalloc(sizeof(double) * poMP->getNumGeometries()));
+        // TODO(schwehr): Why a calloc for padfZ?
+        double *padfZ = static_cast<double *>(
+            CPLCalloc(sizeof(double), poMP->getNumGeometries()));
+        double *padfM = NULL;
+        if( wkbHasM(eLayerGeomType) &&
+            (hSHP->nShapeType == SHPT_MULTIPOINTM ||
+             hSHP->nShapeType == SHPT_MULTIPOINTZ) )
+            padfM = static_cast<double *>(
+                CPLCalloc(sizeof(double), poMP->getNumGeometries()));
 
         int iDstPoints = 0;
-        for( iPoint = 0; iPoint < poMP->getNumGeometries(); iPoint++ )
+        for( int iPoint = 0; iPoint < poMP->getNumGeometries(); iPoint++ )
         {
-            OGRPoint    *poPoint = (OGRPoint *) poMP->getGeometryRef(iPoint);
+            OGRPoint *poPoint =
+                dynamic_cast<OGRPoint *>(poMP->getGeometryRef(iPoint));
+            if( poPoint == NULL )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "dynamic_cast failed.  "
+                          "Expected point within multi-point." );
+                CPLFree( padfX );
+                CPLFree( padfY );
+                CPLFree( padfZ );
+                CPLFree( padfM );
+                return OGRERR_FAILURE;
+            }
 
-            /* Ignore POINT EMPTY */
-            if (poPoint->IsEmpty() == FALSE)
+            // Ignore POINT EMPTY.
+            if( !poPoint->IsEmpty() )
             {
                 padfX[iDstPoints] = poPoint->getX();
                 padfY[iDstPoints] = poPoint->getY();
@@ -605,17 +513,22 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
                     else
                         padfM[iDstPoints] = -std::numeric_limits<double>::max();
                 }
-                iDstPoints ++;
+                iDstPoints++;
             }
             else
-                CPLDebug( "OGR",
-                              "Ignore POINT EMPTY inside MULTIPOINT in shapefile writer." );
+            {
+                CPLDebug(
+                    "OGR",
+                    "Ignored POINT EMPTY inside MULTIPOINT in shapefile "
+                    "writer." );
+            }
         }
 
-        psShape = SHPCreateObject( hSHP->nShapeType, -1, 0, NULL, NULL,
-                                   iDstPoints,
-                                   padfX, padfY, padfZ, padfM );
-        nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
+        SHPObject *psShape =
+            SHPCreateObject( hSHP->nShapeType, -1, 0, NULL, NULL,
+                             iDstPoints,
+                             padfX, padfY, padfZ, padfM );
+        const int nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
 
         CPLFree( padfX );
@@ -634,20 +547,28 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
               || hSHP->nShapeType == SHPT_ARCZ)
              && wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
     {
-        OGRLineString   *poArc = (OGRLineString *) poGeom;
-        double          *padfX, *padfY, *padfZ, *padfM;
-        int             iPoint;
-        SHPObject       *psShape;
-
-        padfX = (double *) CPLMalloc(sizeof(double)*poArc->getNumPoints());
-        padfY = (double *) CPLMalloc(sizeof(double)*poArc->getNumPoints());
-        padfZ = (double *) CPLCalloc(sizeof(double),poArc->getNumPoints());
-        if( wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_ARCM || hSHP->nShapeType == SHPT_ARCZ) )
-            padfM = (double *) CPLCalloc(sizeof(double),poArc->getNumPoints());
-        else
-            padfM = NULL;
+        OGRLineString *poArc = dynamic_cast<OGRLineString *>(poGeom);
+        if( poArc == NULL )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "dynamic_cast failed.  Expected line string for arc." );
+            return OGRERR_FAILURE;
+        }
 
-        for( iPoint = 0; iPoint < poArc->getNumPoints(); iPoint++ )
+        double *padfX = static_cast<double *>(
+            CPLMalloc(sizeof(double) * poArc->getNumPoints()));
+        double *padfY = static_cast<double *>(
+            CPLMalloc(sizeof(double)*poArc->getNumPoints()));
+        double *padfZ = static_cast<double *>(
+            CPLCalloc(sizeof(double), poArc->getNumPoints()));
+        double *padfM = NULL;
+        if( wkbHasM(eLayerGeomType) &&
+            (hSHP->nShapeType == SHPT_ARCM ||
+             hSHP->nShapeType == SHPT_ARCZ) )
+            padfM = static_cast<double *>(
+                CPLCalloc(sizeof(double),poArc->getNumPoints()));
+
+        for( int iPoint = 0; iPoint < poArc->getNumPoints(); iPoint++ )
         {
             padfX[iPoint] = poArc->getX( iPoint );
             padfY[iPoint] = poArc->getY( iPoint );
@@ -661,10 +582,11 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
             }
         }
 
-        psShape = SHPCreateObject( hSHP->nShapeType, -1, 0, NULL, NULL,
-                                   poArc->getNumPoints(),
-                                   padfX, padfY, padfZ, padfM );
-        nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
+        SHPObject *psShape =
+            SHPCreateObject( hSHP->nShapeType, -1, 0, NULL, NULL,
+                             poArc->getNumPoints(),
+                             padfX, padfY, padfZ, padfM );
+        const int nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
 
         CPLFree( padfX );
@@ -681,17 +603,8 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
              || hSHP->nShapeType == SHPT_ARCM
              || hSHP->nShapeType == SHPT_ARCZ )
     {
-        OGRGeometry     *poForcedGeom;
-        double          *padfX=NULL, *padfY=NULL, *padfZ=NULL, *padfM=NULL;
-        int             iGeom, iPoint, nPointCount = 0;
-        SHPObject       *psShape;
-        int             *panRingStart;
-        int             nParts = 0;
-        const bool       bSupportMeasures =
-            wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_ARCM ||
-                                            hSHP->nShapeType == SHPT_ARCZ);
-
-        poForcedGeom = OGRGeometryFactory::forceToMultiLineString( poGeom->clone() );
+        OGRGeometry *poForcedGeom =
+            OGRGeometryFactory::forceToMultiLineString( poGeom->clone() );
 
         if( wkbFlatten(poForcedGeom->getGeometryType()) != wkbMultiLineString )
         {
@@ -703,58 +616,86 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
 
             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
         }
-        OGRMultiLineString *poML = (OGRMultiLineString *)poForcedGeom;
+        OGRMultiLineString *poML =
+            dynamic_cast<OGRMultiLineString *>(poForcedGeom);
+        if( poML == NULL )
+        {
+            delete poForcedGeom;
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "dynamic_cast failed.  Expected multi-line string." );
+            return OGRERR_FAILURE;
+        }
+
+        int *panRingStart = static_cast<int *>(
+            CPLMalloc(sizeof(int) * poML->getNumGeometries()) );
 
-        panRingStart = (int *)
-            CPLMalloc(sizeof(int) * poML->getNumGeometries());
+        double *padfX = NULL;
+        double *padfY = NULL;
+        double *padfZ = NULL;
+        double *padfM = NULL;
+        int nPointCount = 0;
+        int nParts = 0;
+        const bool bSupportMeasures =
+            wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_ARCM ||
+                                            hSHP->nShapeType == SHPT_ARCZ);
 
-        for( iGeom = 0; iGeom < poML->getNumGeometries(); iGeom++ )
+        for( int iGeom = 0; iGeom < poML->getNumGeometries(); iGeom++ )
         {
-            OGRLineString *poArc = (OGRLineString *)
-                poML->getGeometryRef(iGeom);
-            int nNewPoints = poArc->getNumPoints();
+            OGRLineString *poArc = dynamic_cast<OGRLineString *>(
+                poML->getGeometryRef(iGeom));
+            if( poArc == NULL )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined,
+                          "dynamic_cast failed. Expected line string for arc.");
+                continue;
+            }
+            const int nNewPoints = poArc->getNumPoints();
 
-            /* Ignore LINESTRING EMPTY */
-            if (nNewPoints == 0)
+            // Ignore LINESTRING EMPTY.
+            if( nNewPoints == 0 )
             {
-                CPLDebug( "OGR",
-                          "Ignore LINESTRING EMPTY inside MULTILINESTRING in shapefile writer." );
+                CPLDebug(
+                    "OGR",
+                    "Ignore LINESTRING EMPTY inside MULTILINESTRING in "
+                    "shapefile writer." );
                 continue;
             }
 
-            panRingStart[nParts ++] = nPointCount;
+            panRingStart[nParts++] = nPointCount;
 
-            padfX = (double *)
-                CPLRealloc( padfX, sizeof(double)*(nNewPoints+nPointCount) );
-            padfY = (double *)
-                CPLRealloc( padfY, sizeof(double)*(nNewPoints+nPointCount) );
-            padfZ = (double *)
-                CPLRealloc( padfZ, sizeof(double)*(nNewPoints+nPointCount) );
+            padfX = static_cast<double *>(
+                CPLRealloc( padfX, sizeof(double)*(nNewPoints+nPointCount) ));
+            padfY = static_cast<double *>(
+                CPLRealloc( padfY, sizeof(double)*(nNewPoints+nPointCount) ));
+            padfZ = static_cast<double *>(
+                CPLRealloc( padfZ, sizeof(double)*(nNewPoints+nPointCount) ));
             if( bSupportMeasures )
             {
-                padfM = (double *)
-                    CPLRealloc( padfM, sizeof(double)*(nNewPoints+nPointCount) );
+                padfM = static_cast<double *>(
+                    CPLRealloc(padfM, sizeof(double)*(nNewPoints+nPointCount)));
             }
 
-            for( iPoint = 0; iPoint < nNewPoints; iPoint++ )
+            for( int iPoint = 0; iPoint < nNewPoints; iPoint++ )
             {
                 padfX[nPointCount] = poArc->getX( iPoint );
                 padfY[nPointCount] = poArc->getY( iPoint );
                 padfZ[nPointCount] = poArc->getZ( iPoint );
                 if( bSupportMeasures )
                     padfM[nPointCount] = poGeom->IsMeasured() ?
-                        poArc->getM( iPoint ) : -std::numeric_limits<double>::max();
+                        poArc->getM( iPoint ) :
+                        -std::numeric_limits<double>::max();
                 nPointCount++;
             }
         }
 
         CPLAssert(nParts != 0);
 
-        psShape = SHPCreateObject( hSHP->nShapeType, iShape,
-                                    nParts,
-                                    panRingStart, NULL,
-                                    nPointCount, padfX, padfY, padfZ, padfM);
-        nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
+        SHPObject *psShape =
+            SHPCreateObject( hSHP->nShapeType, iShape,
+                             nParts,
+                             panRingStart, NULL,
+                             nPointCount, padfX, padfY, padfZ, padfM );
+        const int nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
 
         CPLFree( panRingStart );
@@ -775,53 +716,66 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
              || hSHP->nShapeType == SHPT_POLYGONM
              || hSHP->nShapeType == SHPT_POLYGONZ )
     {
-        OGRLinearRing   *poRing, **papoRings=NULL;
-        double          *padfX=NULL, *padfY=NULL, *padfZ=NULL, *padfM=NULL;
-        int             iPoint, iRing, nRings, nVertex=0, *panRingStart;
+        OGRLinearRing **papoRings = NULL;
+        int nRings = 0;
+        const OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
+        OGRGeometry* poGeomToDelete = NULL;
 
-        /* Collect list of rings */
-
-        if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon )
+        if( eType == wkbPolygon || eType == wkbTriangle )
         {
-            OGRPolygon* poPoly =  (OGRPolygon *) poGeom;
+            OGRPolygon* poPoly = (OGRPolygon *) poGeom;
 
             if( poPoly->getExteriorRing() == NULL ||
                 poPoly->getExteriorRing()->IsEmpty() )
             {
                 CPLDebug( "OGR",
                           "Ignore POLYGON EMPTY in shapefile writer." );
-                nRings = 0;
             }
             else
             {
-                int nSrcRings = poPoly->getNumInteriorRings()+1;
-                nRings = 0;
-                papoRings = (OGRLinearRing **) CPLMalloc(sizeof(void*)*nSrcRings);
-                for( iRing = 0; iRing < nSrcRings; iRing++ )
+                const int nSrcRings = poPoly->getNumInteriorRings()+1;
+                papoRings = static_cast<OGRLinearRing **>(
+                    CPLMalloc(sizeof(void*)*nSrcRings));
+                for( int iRing = 0; iRing < nSrcRings; iRing++ )
                 {
                     if( iRing == 0 )
                         papoRings[nRings] = poPoly->getExteriorRing();
                     else
                         papoRings[nRings] = poPoly->getInteriorRing( iRing-1 );
 
-                    /* Ignore LINEARRING EMPTY */
-                    if (papoRings[nRings]->getNumPoints() != 0)
-                        nRings ++;
+                    // Ignore LINEARRING EMPTY.
+                    if( papoRings[nRings]->getNumPoints() != 0 )
+                        nRings++;
                     else
-                        CPLDebug( "OGR",
-                                "Ignore LINEARRING EMPTY inside POLYGON in shapefile writer." );
+                        CPLDebug(
+                            "OGR",
+                            "Ignore LINEARRING EMPTY inside POLYGON in "
+                            "shapefile writer." );
                 }
             }
         }
-        else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon
-                 || wkbFlatten(poGeom->getGeometryType())
-                                                == wkbGeometryCollection )
+        else if( eType == wkbMultiPolygon ||
+                 eType == wkbGeometryCollection ||
+                 eType == wkbPolyhedralSurface ||
+                 eType == wkbTIN)
         {
-            OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
-            int         iGeom;
+            OGRMultiPolygon *poMultiPolygon = NULL;
+            OGRGeometryCollection *poGC;
+            // for PolyhedralSurface and TIN
+            if (eType == wkbPolyhedralSurface || eType == wkbTIN)
+            {
+                poGeomToDelete = OGRGeometryFactory::forceTo(poGeom->clone(),
+                                                             wkbMultiPolygon,
+                                                             NULL);
+                poMultiPolygon = dynamic_cast<OGRMultiPolygon*>(poGeomToDelete);
+                poGC = poMultiPolygon;
+            }
+
+            else
+                poGC = (OGRGeometryCollection *) poGeom;
 
-            nRings = 0;
-            for( iGeom=0; iGeom < poGC->getNumGeometries(); iGeom++ )
+            for( int iGeom=0; poGC != NULL &&
+                              iGeom < poGC->getNumGeometries(); iGeom++ )
             {
                 OGRGeometry* poSubGeom = poGC->getGeometryRef( iGeom );
 
@@ -837,18 +791,22 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
                 }
                 OGRPolygon* poPoly =  (OGRPolygon *) poSubGeom;
 
-                /* Ignore POLYGON EMPTY */
+                // Ignore POLYGON EMPTY.
                 if( poPoly->getExteriorRing() == NULL ||
                     poPoly->getExteriorRing()->IsEmpty() )
                 {
-                    CPLDebug( "OGR",
-                              "Ignore POLYGON EMPTY inside MULTIPOLYGON in shapefile writer." );
+                    CPLDebug(
+                        "OGR",
+                        "Ignore POLYGON EMPTY inside MULTIPOLYGON in "
+                        "shapefile writer." );
                     continue;
                 }
 
-                papoRings = (OGRLinearRing **) CPLRealloc(papoRings,
-                     sizeof(void*) * (nRings+poPoly->getNumInteriorRings()+1));
-                for( iRing = 0;
+                papoRings = static_cast<OGRLinearRing **>(
+                    CPLRealloc(papoRings,
+                               sizeof(void*) *
+                               (nRings+poPoly->getNumInteriorRings() + 1)) );
+                for( int iRing = 0;
                      iRing < poPoly->getNumInteriorRings()+1;
                      iRing++ )
                 {
@@ -856,14 +814,16 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
                         papoRings[nRings] = poPoly->getExteriorRing();
                     else
                         papoRings[nRings] =
-                            poPoly->getInteriorRing( iRing-1 );
+                            poPoly->getInteriorRing( iRing - 1 );
 
-                    /* Ignore LINEARRING EMPTY */
-                    if (papoRings[nRings]->getNumPoints() != 0)
-                        nRings ++;
+                    // Ignore LINEARRING EMPTY.
+                    if( papoRings[nRings]->getNumPoints() != 0 )
+                        nRings++;
                     else
-                        CPLDebug( "OGR",
-                              "Ignore LINEARRING EMPTY inside POLYGON in shapefile writer." );
+                        CPLDebug(
+                            "OGR",
+                            "Ignore LINEARRING EMPTY inside POLYGON in "
+                            "shapefile writer." );
                 }
             }
         }
@@ -883,38 +843,50 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
 /* -------------------------------------------------------------------- */
         if( nRings == 0 )
         {
-            SHPObject       *psShape;
-
-            psShape = SHPCreateObject( SHPT_NULL, -1, 0, NULL, NULL, 0, NULL, NULL, NULL, NULL );
-            nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
+            SHPObject *psShape =
+                SHPCreateObject( SHPT_NULL, -1, 0, NULL, NULL,
+                                 0, NULL, NULL, NULL, NULL );
+            const int nReturnedShapeID =
+                SHPWriteObject( hSHP, iShape, psShape );
             SHPDestroyObject( psShape );
 
+            delete poGeomToDelete;
+
             if( nReturnedShapeID == -1 )
                 return OGRERR_FAILURE;
 
             return OGRERR_NONE;
         }
 
-        /* count vertices */
-        nVertex = 0;
-        for( iRing = 0; iRing < nRings; iRing++ )
+        // Count vertices.
+        int nVertex = 0;
+        for( int iRing = 0; iRing < nRings; iRing++ )
             nVertex += papoRings[iRing]->getNumPoints();
 
-        panRingStart = (int *) CPLMalloc(sizeof(int) * nRings);
-        padfX = (double *) CPLMalloc(sizeof(double)*nVertex);
-        padfY = (double *) CPLMalloc(sizeof(double)*nVertex);
-        padfZ = (double *) CPLMalloc(sizeof(double)*nVertex);
-        if( wkbHasM(eLayerGeomType) && (hSHP->nShapeType == SHPT_POLYGONM || hSHP->nShapeType == SHPT_POLYGONZ) )
-            padfM = (double *) CPLMalloc(sizeof(double)*nVertex);
-
-        /* collect vertices */
+        int *panRingStart =
+            static_cast<int *>( CPLMalloc(sizeof(int) * nRings) );
+        double *padfX =
+            static_cast<double *>( CPLMalloc(sizeof(double) * nVertex) );
+        double *padfY =
+            static_cast<double *>( CPLMalloc(sizeof(double) * nVertex) );
+        double *padfZ =
+            static_cast<double *>( CPLMalloc(sizeof(double) * nVertex) );
+
+        double *padfM = NULL;
+        if( wkbHasM(eLayerGeomType) &&
+            (hSHP->nShapeType == SHPT_POLYGONM ||
+             hSHP->nShapeType == SHPT_POLYGONZ) )
+            padfM = static_cast<double *>(
+                CPLMalloc(sizeof(double) * nVertex));
+
+        // Collect vertices.
         nVertex = 0;
-        for( iRing = 0; iRing < nRings; iRing++ )
+        for( int iRing = 0; iRing < nRings; iRing++ )
         {
-            poRing = papoRings[iRing];
+            OGRLinearRing *poRing = papoRings[iRing];
             panRingStart[iRing] = nVertex;
 
-            for( iPoint = 0; iPoint < poRing->getNumPoints(); iPoint++ )
+            for( int iPoint = 0; iPoint < poRing->getNumPoints(); iPoint++ )
             {
                 padfX[nVertex] = poRing->getX( iPoint );
                 padfY[nVertex] = poRing->getY( iPoint );
@@ -922,18 +894,19 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
                 if( padfM )
                 {
                     padfM[nVertex] = poGeom->IsMeasured() ?
-                        poRing->getM( iPoint ) : -std::numeric_limits<double>::max();
+                        poRing->getM( iPoint ) :
+                        -std::numeric_limits<double>::max();
                 }
                 nVertex++;
             }
         }
 
-        SHPObject* psShape = SHPCreateObject( hSHP->nShapeType, iShape, nRings,
-                                   panRingStart, NULL,
-                                   nVertex, padfX, padfY, padfZ, padfM );
+        SHPObject* psShape =
+            SHPCreateObject( hSHP->nShapeType, iShape, nRings, panRingStart,
+                             NULL, nVertex, padfX, padfY, padfZ, padfM );
         if( bRewind )
             SHPRewindObject( hSHP, psShape );
-        nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
+        const int nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
         SHPDestroyObject( psShape );
 
         CPLFree( papoRings );
@@ -942,12 +915,66 @@ OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom,
         CPLFree( padfY );
         CPLFree( padfZ );
         CPLFree( padfM );
+
+        delete poGeomToDelete;
+
+        if( nReturnedShapeID == -1 )
+            return OGRERR_FAILURE;
+    }
+
+/* ==================================================================== */
+/*      Multipatch                                                      */
+/* ==================================================================== */
+    else if( hSHP->nShapeType == SHPT_MULTIPATCH )
+    {
+        int nParts = 0;
+        int* panPartStart = NULL;
+        int* panPartType = NULL;
+        int nPoints = 0;
+        OGRRawPoint* poPoints = NULL;
+        double* padfZ = NULL;
+        OGRErr eErr = OGRCreateMultiPatch( poGeom,
+                                           FALSE, // no SHPP_TRIANGLES
+                                           nParts,
+                                           panPartStart,
+                                           panPartType,
+                                           nPoints,
+                                           poPoints,
+                                           padfZ );
+        if( eErr != OGRERR_NONE )
+            return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+
+        double *padfX =
+            static_cast<double *>( CPLMalloc(sizeof(double) * nPoints) );
+        double *padfY =
+            static_cast<double *>( CPLMalloc(sizeof(double) * nPoints) );
+        for( int i = 0; i < nPoints; ++i )
+        {
+            padfX[i] = poPoints[i].x;
+            padfY[i] = poPoints[i].y;
+        }
+        CPLFree(poPoints);
+
+        SHPObject* psShape =
+            SHPCreateObject( hSHP->nShapeType, iShape, nParts, panPartStart,
+                             panPartType, nPoints, padfX, padfY, padfZ, NULL );
+        if( bRewind )
+            SHPRewindObject( hSHP, psShape );
+        const int nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
+        SHPDestroyObject( psShape );
+
+        CPLFree(panPartStart);
+        CPLFree(panPartType);
+        CPLFree(padfX);
+        CPLFree(padfY);
+        CPLFree(padfZ);
+
         if( nReturnedShapeID == -1 )
             return OGRERR_FAILURE;
     }
+
     else
     {
-        /* do nothing for multipatch */
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     }
 
@@ -964,48 +991,50 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
                                        int bAdjustType )
 
 {
-    OGRFeatureDefn      *poDefn = new OGRFeatureDefn( pszName );
-    int                 iField;
-    int                 nAdjustableFields = 0;
-    int                 nFieldCount = (hDBF) ? DBFGetFieldCount(hDBF) : 0;
+    int nAdjustableFields = 0;
+    const int nFieldCount = hDBF ? DBFGetFieldCount(hDBF) : 0;
 
+    OGRFeatureDefn * const poDefn = new OGRFeatureDefn( pszName );
     poDefn->Reference();
 
-    for( iField = 0; iField < nFieldCount; iField++ )
+    for( int iField = 0; iField < nFieldCount; iField++ )
     {
-        char            szFieldName[12] = {};
-        int             nWidth, nPrecision;
-        DBFFieldType    eDBFType;
-        OGRFieldDefn    oField("", OFTInteger);
-        char            chNativeType;
-
-        chNativeType = DBFGetNativeFieldType( hDBF, iField );
-        eDBFType = DBFGetFieldInfo( hDBF, iField, szFieldName,
-                                    &nWidth, &nPrecision );
-
+        // On reading we support up to 11 characters
+        char szFieldName[XBASE_FLDNAME_LEN_READ+1] = {};
+        int nWidth = 0;
+        int nPrecision = 0;
+        DBFFieldType eDBFType =
+            DBFGetFieldInfo( hDBF, iField, szFieldName, &nWidth, &nPrecision );
+
+        OGRFieldDefn oField("", OFTInteger);
         if( strlen(pszSHPEncoding) > 0 )
         {
-            char *pszUTF8Field = CPLRecode( szFieldName,
-                                            pszSHPEncoding, CPL_ENC_UTF8);
+            char * const pszUTF8Field =
+                CPLRecode( szFieldName, pszSHPEncoding, CPL_ENC_UTF8);
             oField.SetName( pszUTF8Field );
             CPLFree( pszUTF8Field );
         }
         else
+        {
             oField.SetName( szFieldName );
+        }
 
         oField.SetWidth( nWidth );
         oField.SetPrecision( nPrecision );
 
+        const char chNativeType = DBFGetNativeFieldType( hDBF, iField );
         if( chNativeType == 'D' )
         {
-            /* XXX - mloskot:
-             * Shapefile date has following 8-chars long format: 20060101.
-             * OGR splits it as YYYY/MM/DD, so 2 additional characters are
-             * required.
-             * Is this a correct assumption? What about time part of date?
-             * Should this format look as datetime: YYYY/MM/DD HH:MM:SS
-             * with 4 additional characters?
-             */
+            // TODO(mloskot): Shapefile date has following 8-chars long format:
+            //
+            //     20060101.
+            //
+            // Split as YYYY/MM/DD, so 2 additional characters are required.
+            //
+            // Is this a correct assumption? What about time part of date?
+            // Should this format look as datetime: YYYY/MM/DD HH:MM:SS with 4
+            // additional characters?
+
             oField.SetWidth( nWidth + 2 );
             oField.SetType( OFTDate );
         }
@@ -1025,12 +1054,13 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
         poDefn->AddFieldDefn( &oField );
     }
 
-    /* Do an optional past if requested and needed to demote Integer64->Integer */
-    /* or Real->Integer64/Integer */
+    // Do an optional past if requested and needed to demote Integer64->Integer
+    // or Real->Integer64/Integer.
     if( nAdjustableFields && bAdjustType )
     {
-        int* panAdjustableField = (int*)CPLCalloc(sizeof(int), nFieldCount);
-        for( iField = 0; iField < nFieldCount; iField++ )
+        int *panAdjustableField = static_cast<int *>(
+            CPLCalloc(sizeof(int), nFieldCount));
+        for( int iField = 0; iField < nFieldCount; iField++ )
         {
             OGRFieldType eType = poDefn->GetFieldDefn(iField)->GetType();
             if( poDefn->GetFieldDefn(iField)->GetPrecision() == 0 &&
@@ -1038,36 +1068,29 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
             {
                 panAdjustableField[iField] = TRUE;
                 poDefn->GetFieldDefn(iField)->SetType(OFTInteger);
-                //poDefn->GetFieldDefn(iField)->SetWidth(0);
             }
         }
 
-        int nRowCount = DBFGetRecordCount(hDBF);
-        for( int iRow = 0; iRow < nRowCount && nAdjustableFields; iRow ++ )
+        const int nRowCount = DBFGetRecordCount(hDBF);
+        for( int iRow = 0; iRow < nRowCount && nAdjustableFields; iRow++ )
         {
-           for( iField = 0; iField < nFieldCount; iField++ )
+           for( int iField = 0; iField < nFieldCount; iField++ )
            {
                if( panAdjustableField[iField] )
                {
-                   const char* pszValue = DBFReadStringAttribute( hDBF, iRow, iField );
-                   int nValueLength = (int)strlen(pszValue);
-                   //if( nValueLength >= poDefn->GetFieldDefn(iField)->GetWidth())
-                   //    poDefn->GetFieldDefn(iField)->SetWidth(nValueLength);
+                   const char* pszValue =
+                       DBFReadStringAttribute( hDBF, iRow, iField );
+                   const int nValueLength = static_cast<int>(strlen(pszValue));
                    if( nValueLength >= 10 )
                    {
-                       int bOverflow;
-                       GIntBig nVal = CPLAtoGIntBigEx(pszValue, FALSE, &bOverflow);
+                       int bOverflow = FALSE;
+                       const GIntBig nVal =
+                           CPLAtoGIntBigEx(pszValue, FALSE, &bOverflow);
                        if( bOverflow )
                        {
                            poDefn->GetFieldDefn(iField)->SetType(OFTReal);
                            panAdjustableField[iField] = FALSE;
-                           nAdjustableFields --;
-
-                           /*char            szFieldName[12] = {};
-                           int             nWidth, nPrecision;
-                           DBFGetFieldInfo( hDBF, iField, szFieldName,
-                                            &nWidth, &nPrecision );
-                           poDefn->GetFieldDefn(iField)->SetWidth(nWidth);*/
+                           nAdjustableFields--;
                        }
                        else if( !CPL_INT64_FITS_ON_INT32(nVal) )
                        {
@@ -1075,13 +1098,7 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
                            if( poDefn->GetFieldDefn(iField)->GetWidth() <= 18 )
                            {
                                panAdjustableField[iField] = FALSE;
-                               nAdjustableFields --;
-
-                               /*char            szFieldName[12] = {};
-                               int             nWidth, nPrecision;
-                               DBFGetFieldInfo( hDBF, iField, szFieldName,
-                                                &nWidth, &nPrecision );
-                               poDefn->GetFieldDefn(iField)->SetWidth(nWidth);*/
+                               nAdjustableFields--;
                            }
                        }
                    }
@@ -1093,7 +1110,9 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
     }
 
     if( hSHP == NULL )
+    {
         poDefn->SetGeomType( wkbNone );
+    }
     else
     {
         switch( hSHP->nShapeType )
@@ -1146,6 +1165,9 @@ OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
             poDefn->SetGeomType( wkbPolygonM );
             break;
 
+          case SHPT_MULTIPATCH:
+            poDefn->SetGeomType( wkbUnknown ); // not ideal
+            break;
         }
     }
 
@@ -1174,7 +1196,8 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
     if( hDBF && DBFIsRecordDeleted( hDBF, iShape ) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to read shape with feature id (%d), but it is marked deleted.",
+                  "Attempt to read shape with feature id (%d), "
+                  "but it is marked deleted.",
                   iShape );
         if( psShape != NULL )
             SHPDestroyObject(psShape);
@@ -1193,23 +1216,24 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
             OGRGeometry* poGeometry = NULL;
             poGeometry = SHPReadOGRObject( hSHP, iShape, psShape );
 
-            /*
-            * NOTE - mloskot:
-            * Two possibilities are expected here (both are tested by GDAL Autotests):
-            * 1. Read valid geometry and assign it directly.
-            * 2. Read and assign null geometry if it can not be read correctly from a shapefile
-            *
-            * It's NOT required here to test poGeometry == NULL.
-            */
+            // Two possibilities are expected here (both are tested by
+            // GDAL Autotests):
+            //   1. Read valid geometry and assign it directly.
+            //   2. Read and assign null geometry if it can not be read
+            //      correctly from a shapefile.
+            //
+            // It is NOT required here to test poGeometry == NULL.
 
-            if (poGeometry)
+            if( poGeometry )
             {
-                /* Set/unset flags. */
-                OGRwkbGeometryType eMyGeomType = poFeature->GetDefnRef()->GetGeomFieldDefn(0)->GetType();
+                // Set/unset flags.
+                const OGRwkbGeometryType eMyGeomType =
+                    poFeature->GetDefnRef()->GetGeomFieldDefn(0)->GetType();
 
                 if( eMyGeomType != wkbUnknown )
                 {
-                    OGRwkbGeometryType eGeomInType = poGeometry->getGeometryType();
+                    OGRwkbGeometryType eGeomInType =
+                        poGeometry->getGeometryType();
                     if( wkbHasZ(eMyGeomType) && !wkbHasZ(eGeomInType) )
                     {
                         poGeometry->set3D(TRUE);
@@ -1241,72 +1265,87 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 /*      Fetch feature attributes to OGRFeature fields.                  */
 /* -------------------------------------------------------------------- */
 
-    for( int iField = 0; hDBF != NULL && iField < poDefn->GetFieldCount(); iField++ )
+    for( int iField = 0;
+         hDBF != NULL && iField < poDefn->GetFieldCount();
+         iField++ )
     {
-        OGRFieldDefn* poFieldDefn = poDefn->GetFieldDefn(iField);
-        if (poFieldDefn->IsIgnored() )
+        const OGRFieldDefn * const poFieldDefn = poDefn->GetFieldDefn(iField);
+        if( poFieldDefn->IsIgnored() )
             continue;
 
         switch( poFieldDefn->GetType() )
         {
           case OFTString:
           {
-              const char *pszFieldVal =
+              const char * const pszFieldVal =
                   DBFReadStringAttribute( hDBF, iShape, iField );
               if( pszFieldVal != NULL && pszFieldVal[0] != '\0' )
               {
                 if( pszSHPEncoding[0] != '\0' )
                 {
-                    char *pszUTF8Field = CPLRecode( pszFieldVal,
-                                                    pszSHPEncoding, CPL_ENC_UTF8);
+                    char * const pszUTF8Field =
+                        CPLRecode( pszFieldVal, pszSHPEncoding, CPL_ENC_UTF8);
                     poFeature->SetField( iField, pszUTF8Field );
                     CPLFree( pszUTF8Field );
                 }
                 else
                     poFeature->SetField( iField, pszFieldVal );
               }
+              else
+              {
+                  poFeature->SetFieldNull(iField);
+              }
+              break;
           }
-          break;
-
           case OFTInteger:
           case OFTInteger64:
           case OFTReal:
-            if( !DBFIsAttributeNULL( hDBF, iShape, iField ) )
-                poFeature->SetField( iField,
-                                    DBFReadStringAttribute( hDBF, iShape,
-                                                            iField ) );
-            break;
-
+          {
+              if( DBFIsAttributeNULL( hDBF, iShape, iField ) )
+              {
+                  poFeature->SetFieldNull(iField);
+              }
+              else
+              {
+                  poFeature->SetField(
+                      iField,
+                      DBFReadStringAttribute( hDBF, iShape, iField ) );
+              }
+              break;
+          }
           case OFTDate:
           {
-              OGRField sFld;
               if( DBFIsAttributeNULL( hDBF, iShape, iField ) )
+              {
+                  poFeature->SetFieldNull(iField);
                   continue;
+              }
 
-              const char* pszDateValue =
+              const char* const pszDateValue =
                   DBFReadStringAttribute(hDBF,iShape,iField);
 
-              /* Some DBF files have fields filled with spaces */
-              /* (trimmed by DBFReadStringAttribute) to indicate null */
-              /* values for dates (#4265) */
-              if (pszDateValue[0] == '\0')
+              // Some DBF files have fields filled with spaces
+              // (trimmed by DBFReadStringAttribute) to indicate null
+              // values for dates (#4265).
+              if( pszDateValue[0] == '\0' )
                   continue;
 
+              OGRField sFld;
               memset( &sFld, 0, sizeof(sFld) );
 
               if( strlen(pszDateValue) >= 10 &&
                   pszDateValue[2] == '/' && pszDateValue[5] == '/' )
               {
-                  sFld.Date.Month = (GByte)atoi(pszDateValue+0);
-                  sFld.Date.Day   = (GByte)atoi(pszDateValue+3);
-                  sFld.Date.Year  = (GInt16)atoi(pszDateValue+6);
+                  sFld.Date.Month = static_cast<GByte>(atoi(pszDateValue + 0));
+                  sFld.Date.Day   = static_cast<GByte>(atoi(pszDateValue + 3));
+                  sFld.Date.Year  = static_cast<GInt16>(atoi(pszDateValue + 6));
               }
               else
               {
-                  int nFullDate = atoi(pszDateValue);
-                  sFld.Date.Year = (GInt16)(nFullDate / 10000);
-                  sFld.Date.Month = (GByte)((nFullDate / 100) % 100);
-                  sFld.Date.Day = (GByte)(nFullDate % 100);
+                  const int nFullDate = atoi(pszDateValue);
+                  sFld.Date.Year = static_cast<GInt16>(nFullDate / 10000);
+                  sFld.Date.Month = static_cast<GByte>((nFullDate / 100) % 100);
+                  sFld.Date.Day = static_cast<GByte>(nFullDate % 100);
               }
 
               poFeature->SetField( iField, &sFld );
@@ -1314,48 +1353,43 @@ OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
           break;
 
           default:
-            CPLAssert( FALSE );
+            CPLAssert( false );
         }
     }
 
     if( poFeature != NULL )
         poFeature->SetFID( iShape );
 
-    return( poFeature );
+    return poFeature;
 }
 
 /************************************************************************/
 /*                             GrowField()                              */
 /************************************************************************/
 
-static OGRErr GrowField(DBFHandle hDBF, int iField, OGRFieldDefn* poFieldDefn,
-                        int nNewSize)
+static OGRErr GrowField( DBFHandle hDBF, int iField, OGRFieldDefn* poFieldDefn,
+                         int nNewSize )
 {
-    char            szFieldName[20] = {};
-    int             nOriWidth, nPrecision;
-    char            chNativeType;
-    /* DBFFieldType    eDBFType; */
-
-    chNativeType = DBFGetNativeFieldType( hDBF, iField );
-    /* eDBFType = */ DBFGetFieldInfo( hDBF, iField, szFieldName,
-                                      &nOriWidth, &nPrecision );
+    char szFieldName[20] = {};
+    int nOriWidth = 0;
+    int nPrecision = 0;
+    DBFGetFieldInfo( hDBF, iField, szFieldName, &nOriWidth, &nPrecision );
 
     CPLDebug("SHAPE", "Extending field %d (%s) from %d to %d characters",
-                iField, poFieldDefn->GetNameRef(), nOriWidth, nNewSize);
+             iField, poFieldDefn->GetNameRef(), nOriWidth, nNewSize);
 
-    if ( !DBFAlterFieldDefn( hDBF, iField, szFieldName,
-                             chNativeType, nNewSize, nPrecision ) )
+    const char chNativeType = DBFGetNativeFieldType( hDBF, iField );
+    if( !DBFAlterFieldDefn( hDBF, iField, szFieldName,
+                            chNativeType, nNewSize, nPrecision ) )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                    "Extending field %d (%s) from %d to %d characters failed",
-                    iField, poFieldDefn->GetNameRef(), nOriWidth, nNewSize);
+                 "Extending field %d (%s) from %d to %d characters failed",
+                 iField, poFieldDefn->GetNameRef(), nOriWidth, nNewSize);
         return OGRERR_FAILURE;
     }
-    else
-    {
-        poFieldDefn->SetWidth(nNewSize);
-        return OGRERR_NONE;
-    }
+
+    poFieldDefn->SetWidth(nNewSize);
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -1369,19 +1403,19 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                            OGRFeatureDefn * poDefn,
                            OGRFeature * poFeature,
                            const char *pszSHPEncoding,
-                           int* pbTruncationWarningEmitted,
-                           int bRewind )
+                           bool* pbTruncationWarningEmitted,
+                           bool bRewind )
 
 {
-#ifdef notdef
+#if DEBUG_VERBOSE
 /* -------------------------------------------------------------------- */
 /*      Don't write objects with missing geometry.                      */
 /* -------------------------------------------------------------------- */
     if( poFeature->GetGeometryRef() == NULL && hSHP != NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to write feature without geometry not supported"
-                  " for shapefile driver." );
+                  "Attempt to write feature without geometry not supported "
+                  "for shapefile driver." );
 
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     }
@@ -1390,13 +1424,13 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 /* -------------------------------------------------------------------- */
 /*      Write the geometry.                                             */
 /* -------------------------------------------------------------------- */
-    OGRErr      eErr;
-
     if( hSHP != NULL )
     {
-        eErr = SHPWriteOGRObject( hSHP, (int)poFeature->GetFID(),
-                                  poFeature->GetGeometryRef(), bRewind,
-                                  poDefn->GetGeomType() );
+        const OGRErr eErr =
+            SHPWriteOGRObject( hSHP, static_cast<int>(poFeature->GetFID()),
+                               poFeature->GetGeometryRef(),
+                               bRewind,
+                               poDefn->GetGeomType() );
         if( eErr != OGRERR_NONE )
             return eErr;
     }
@@ -1429,8 +1463,9 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 /* -------------------------------------------------------------------- */
     if( DBFGetRecordCount( hDBF ) == 0 && DBFGetFieldCount( hDBF ) == 0 )
     {
-        CPLDebug( "OGR",
-               "Created dummy FID field for shapefile since schema is empty.");
+        CPLDebug(
+            "OGR",
+            "Created dummy FID field for shapefile since schema is empty.");
         DBFAddField( hDBF, "FID", FTInteger, 11, 0 );
     }
 
@@ -1439,8 +1474,9 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 /* -------------------------------------------------------------------- */
     if( DBFGetFieldCount( hDBF ) == 1 && poDefn->GetFieldCount() == 0 )
     {
-        DBFWriteIntegerAttribute( hDBF, (int)poFeature->GetFID(), 0,
-                                  (int)poFeature->GetFID() );
+        DBFWriteIntegerAttribute(
+            hDBF, static_cast<int>(poFeature->GetFID()), 0,
+            static_cast<int>(poFeature->GetFID()) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1448,13 +1484,14 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
 /* -------------------------------------------------------------------- */
     for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
     {
-        if( !poFeature->IsFieldSet( iField ) )
+        if( !poFeature->IsFieldSetAndNotNull( iField ) )
         {
-            DBFWriteNULLAttribute( hDBF, (int)poFeature->GetFID(), iField );
+            DBFWriteNULLAttribute(
+                hDBF, static_cast<int>(poFeature->GetFID()), iField );
             continue;
         }
 
-        OGRFieldDefn* poFieldDefn = poDefn->GetFieldDefn(iField);
+        OGRFieldDefn * const poFieldDefn = poDefn->GetFieldDefn(iField);
 
         switch( poFieldDefn->GetType() )
         {
@@ -1469,137 +1506,154 @@ OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
                   pszStr = pszEncoded;
               }
 
-              int nStrLen = (int) strlen(pszStr);
-              if (nStrLen > OGR_DBF_MAX_FIELD_WIDTH)
+              int nStrLen = static_cast<int>(strlen(pszStr));
+              if( nStrLen > OGR_DBF_MAX_FIELD_WIDTH )
               {
-                if (!(*pbTruncationWarningEmitted))
-                {
-                    *pbTruncationWarningEmitted = TRUE;
-                    CPLError(CE_Warning, CPLE_AppDefined,
-                            "Value '%s' of field %s has been truncated to %d characters.\n"
-                            "This warning will not be emitted any more for that layer.",
-                            poFeature->GetFieldAsString(iField),
-                            poFieldDefn->GetNameRef(),
-                            OGR_DBF_MAX_FIELD_WIDTH);
-                }
-
-                nStrLen = OGR_DBF_MAX_FIELD_WIDTH;
+                  if( !(*pbTruncationWarningEmitted) )
+                  {
+                      *pbTruncationWarningEmitted = true;
+                      CPLError(
+                          CE_Warning, CPLE_AppDefined,
+                          "Value '%s' of field %s has been truncated to %d "
+                          "characters.  This warning will not be emitted any "
+                          "more for that layer.",
+                          poFeature->GetFieldAsString(iField),
+                          poFieldDefn->GetNameRef(),
+                          OGR_DBF_MAX_FIELD_WIDTH);
+                  }
 
-                if(pszEncoded != NULL && /* to please Coverity */
-                   EQUAL(pszSHPEncoding, CPL_ENC_UTF8))
-                {
-                    const char *p = pszStr + nStrLen;
-                    int byteCount = nStrLen;
-                    while(byteCount > 0)
-                    {
-                        if( (*p & 0xc0) != 0x80 )
-                        {
-                            nStrLen = byteCount;
-                            break;
-                        }
-
-                        byteCount--;
-                        p--;
-                    }
+                  nStrLen = OGR_DBF_MAX_FIELD_WIDTH;
 
-                    pszEncoded[nStrLen] = 0;
-                }
+                  if( pszEncoded != NULL &&  // For Coverity.
+                      EQUAL(pszSHPEncoding, CPL_ENC_UTF8))
+                  {
+                      // TODO(schwehr): Provide a comment about what this does.
+                      const char *p = pszStr + nStrLen;
+                      int byteCount = nStrLen;
+                      while( byteCount > 0 )
+                      {
+                          if( (*p & 0xc0) != 0x80 )
+                          {
+                              nStrLen = byteCount;
+                              break;
+                          }
+
+                          byteCount--;
+                          p--;
+                      }
+
+                      pszEncoded[nStrLen] = 0;
+                  }
               }
 
-              if ( nStrLen > poFieldDefn->GetWidth() )
+              if( nStrLen > poFieldDefn->GetWidth() )
               {
-                  if (GrowField(hDBF, iField, poFieldDefn, nStrLen) != OGRERR_NONE)
+                  if( GrowField(hDBF, iField, poFieldDefn, nStrLen) !=
+                          OGRERR_NONE )
                   {
                       CPLFree( pszEncoded );
                       return OGRERR_FAILURE;
                   }
               }
 
-              DBFWriteStringAttribute( hDBF, (int)poFeature->GetFID(), iField,
-                                              pszStr );
+              DBFWriteStringAttribute(
+                  hDBF, static_cast<int>(poFeature->GetFID()), iField, pszStr );
 
               CPLFree( pszEncoded );
+              break;
           }
-          break;
-
           case OFTInteger:
           case OFTInteger64:
           {
-              char szFormat[20];
-              char szValue[32];
+              char szFormat[20] = {};
+              char szValue[32] = {};
               int nFieldWidth = poFieldDefn->GetWidth();
-              snprintf(szFormat, sizeof(szFormat), "%%%d" CPL_FRMT_GB_WITHOUT_PREFIX "d", MIN(nFieldWidth, (int)sizeof(szValue)-1));
-              snprintf(szValue, sizeof(szValue), szFormat, poFeature->GetFieldAsInteger64(iField) );
-              int nStrLen = static_cast<int>(strlen(szValue));
+              snprintf(szFormat, sizeof(szFormat),
+                       "%%%d" CPL_FRMT_GB_WITHOUT_PREFIX "d",
+                       std::min(nFieldWidth, static_cast<int>(sizeof(szValue)) - 1));
+              snprintf(szValue, sizeof(szValue), szFormat,
+                       poFeature->GetFieldAsInteger64(iField));
+
+              const int nStrLen = static_cast<int>(strlen(szValue));
               if( nStrLen > nFieldWidth )
               {
-                  if (GrowField(hDBF, iField, poFieldDefn, nStrLen) != OGRERR_NONE)
+                  if( GrowField(hDBF, iField, poFieldDefn, nStrLen) !=
+                          OGRERR_NONE )
                   {
                       return OGRERR_FAILURE;
                   }
               }
 
-              DBFWriteAttributeDirectly( hDBF, (int)poFeature->GetFID(), iField,
-                                         szValue );
+              DBFWriteAttributeDirectly(
+                  hDBF, static_cast<int>(poFeature->GetFID()),
+                  iField, szValue );
 
               break;
           }
 
           case OFTReal:
           {
-            double dfVal = poFeature->GetFieldAsDouble(iField);
-            /* IEEE754 doubles can store exact values of all integers below 2^53 */
-            if( poFieldDefn->GetPrecision() == 0 && fabs(dfVal) > ((GIntBig)1 << 53) )
-            {
-                static int nCounter = 0;
-                if( nCounter <= 10 )
-                {
-                    CPLError( CE_Warning, CPLE_AppDefined,
-                              "Value %.18g of field %s with 0 decimal of "
-                              "feature " CPL_FRMT_GIB " is bigger than 2^53. "
-                              "Precision loss likely occurred or going to "
-                              "happen.%s",
-                              dfVal, poFieldDefn->GetNameRef(),
-                              poFeature->GetFID(),
-                              (nCounter == 10) ? " This warning will not be "
-                              "emitted anymore." : "");
-                    nCounter ++;
-                }
-            }
-            int ret = DBFWriteDoubleAttribute( hDBF, (int)poFeature->GetFID(), iField,
-                                               dfVal );
-            if( !ret )
-            {
-                CPLError(CE_Warning, CPLE_AppDefined,
-                         "Value %.18g of field %s of feature " CPL_FRMT_GIB " not successfully written. "
-                         "Possibly due to too larger number with respect to field width",
-                         dfVal, poFieldDefn->GetNameRef(), poFeature->GetFID());
-            }
-            break;
+              const double dfVal = poFeature->GetFieldAsDouble(iField);
+              // IEEE754 doubles can store exact values of all integers
+              // below 2^53.
+              if( poFieldDefn->GetPrecision() == 0 &&
+                  fabs(dfVal) > (static_cast<GIntBig>(1) << 53) )
+              {
+                  static int nCounter = 0;
+                  if( nCounter <= 10 )
+                  {
+                      CPLError(
+                          CE_Warning, CPLE_AppDefined,
+                          "Value %.18g of field %s with 0 decimal of feature "
+                          CPL_FRMT_GIB " is bigger than 2^53. "
+                          "Precision loss likely occurred or going to happen.%s",
+                          dfVal, poFieldDefn->GetNameRef(),
+                          poFeature->GetFID(),
+                          (nCounter == 10) ? " This warning will not be "
+                          "emitted anymore." : "");
+                      nCounter++;
+                  }
+              }
+              int ret = DBFWriteDoubleAttribute(
+                  hDBF, static_cast<int>(poFeature->GetFID()), iField, dfVal );
+              if( !ret )
+              {
+                  CPLError(
+                      CE_Warning, CPLE_AppDefined,
+                      "Value %.18g of field %s of feature " CPL_FRMT_GIB " not "
+                      "successfully written. Possibly due to too larger number "
+                      "with respect to field width",
+                      dfVal, poFieldDefn->GetNameRef(), poFeature->GetFID());
+              }
+              break;
           }
-
           case OFTDate:
           {
-              const OGRField* psField = poFeature->GetRawFieldRef(iField);
+              const OGRField * const psField =
+                  poFeature->GetRawFieldRef(iField);
 
               if( psField->Date.Year < 0 || psField->Date.Year > 9999 )
               {
-                  CPLError(CE_Warning, CPLE_NotSupported,
-                          "Year < 0 or > 9999 is not a valid date for shapefile");
+                  CPLError(
+                      CE_Warning, CPLE_NotSupported,
+                      "Year < 0 or > 9999 is not a valid date for shapefile");
               }
               else
-                  DBFWriteIntegerAttribute( hDBF, (int)poFeature->GetFID(), iField,
-                                            psField->Date.Year*10000 + psField->Date.Month*100 + psField->Date.Day );
+              {
+                  DBFWriteIntegerAttribute(
+                      hDBF, static_cast<int>(poFeature->GetFID()), iField,
+                      psField->Date.Year*10000 + psField->Date.Month*100 +
+                      psField->Date.Day);
+              }
           }
           break;
 
           default:
           {
-              /* Ignore fields of other types */
+              // Ignore fields of other types.
               break;
           }
         }
-
     }
 
     return OGRERR_NONE;
diff --git a/ogr/ogrsf_frmts/shape/shapefil.h b/ogr/ogrsf_frmts/shape/shapefil.h
index d7569ac..848a4f8 100644
--- a/ogr/ogrsf_frmts/shape/shapefil.h
+++ b/ogr/ogrsf_frmts/shape/shapefil.h
@@ -2,7 +2,7 @@
 #define SHAPEFILE_H_INCLUDED
 
 /******************************************************************************
- * $Id: shapefil.h 33889 2016-04-04 09:16:07Z rouault $
+ * $Id: shapefil.h 36727 2016-12-06 20:04:22Z rouault $
  *
  * Project:  Shapelib
  * Purpose:  Primary include file for Shapelib.
@@ -10,10 +10,10 @@
  *
  ******************************************************************************
  * Copyright (c) 1999, Frank Warmerdam
- * Copyright (c) 2012-2013, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2012-2016, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * or at the option of the licensee under the LGPL (see COPYING).  This
  * option is discussed in more detail in shapelib.html.
  *
  * --
@@ -36,109 +36,6 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  * DEALINGS IN THE SOFTWARE.
  ******************************************************************************
- *
- * $Log: shapefil.h,v $
- * Revision 1.52  2011-12-11 22:26:46  fwarmerdam
- * upgrade .qix access code to use SAHooks (gdal #3365)
- *
- * Revision 1.51  2011-07-24 05:59:25  fwarmerdam
- * minimize use of CPLError in favor of SAHooks.Error()
- *
- * Revision 1.50  2011-05-13 17:35:17  fwarmerdam
- * added DBFReorderFields() and DBFAlterFields() functions (from Even)
- *
- * Revision 1.49  2011-04-16 14:38:21  fwarmerdam
- * avoid warnings with gcc on SHP_CVSID
- *
- * Revision 1.48  2010-08-27 23:42:52  fwarmerdam
- * add SHPAPI_CALL attribute in code
- *
- * Revision 1.47  2010-01-28 11:34:34  fwarmerdam
- * handle the shape file length limits more gracefully (#3236)
- *
- * Revision 1.46  2008-11-12 14:28:15  fwarmerdam
- * DBFCreateField() now works on files with records
- *
- * Revision 1.45  2008/11/11 17:47:10  fwarmerdam
- * added DBFDeleteField() function
- *
- * Revision 1.44  2008/01/16 20:05:19  bram
- * Add file hooks that accept UTF-8 encoded filenames on some platforms.  Use SASetupUtf8Hooks
- *  tosetup the hooks and check SHPAPI_UTF8_HOOKS for its availability.  Currently, this
- *  is only available on the Windows platform that decodes the UTF-8 filenames to wide
- *  character strings and feeds them to _wfopen and _wremove.
- *
- * Revision 1.43  2008/01/10 16:35:30  fwarmerdam
- * avoid _ prefix on #defined symbols (bug 1840)
- *
- * Revision 1.42  2007/12/18 18:28:14  bram
- * - create hook for client specific atof (bugzilla ticket 1615)
- * - check for NULL handle before closing cpCPG file, and close after reading.
- *
- * Revision 1.41  2007/12/15 20:25:32  bram
- * dbfopen.c now reads the Code Page information from the DBF file, and exports
- * this information as a string through the DBFGetCodePage function.  This is
- * either the number from the LDID header field ("LDID/<number>") or as the
- * content of an accompanying .CPG file.  When creating a DBF file, the code can
- * be set using DBFCreateEx.
- *
- * Revision 1.40  2007/12/06 07:00:25  fwarmerdam
- * dbfopen now using SAHooks for fileio
- *
- * Revision 1.39  2007/12/04 20:37:56  fwarmerdam
- * preliminary implementation of hooks api for io and errors
- *
- * Revision 1.38  2007/11/21 22:39:56  fwarmerdam
- * close shx file in readonly mode (GDAL #1956)
- *
- * Revision 1.37  2007/10/27 03:31:14  fwarmerdam
- * limit default depth of tree to 12 levels (gdal ticket #1594)
- *
- * Revision 1.36  2007/09/10 23:33:15  fwarmerdam
- * Upstreamed support for visibility flag in SHPAPI_CALL for the needs
- * of GDAL (gdal ticket #1810).
- *
- * Revision 1.35  2007/09/03 19:48:10  fwarmerdam
- * move DBFReadAttribute() static dDoubleField into dbfinfo
- *
- * Revision 1.34  2006/06/17 15:33:32  fwarmerdam
- * added pszWorkField - bug 1202 (rso)
- *
- * Revision 1.33  2006/02/15 01:14:30  fwarmerdam
- * added DBFAddNativeFieldType
- *
- * Revision 1.32  2006/01/26 15:07:32  fwarmerdam
- * add bMeasureIsUsed flag from Craig Bruce: Bug 1249
- *
- * Revision 1.31  2006/01/05 01:27:27  fwarmerdam
- * added dbf deletion mark/fetch
- *
- * Revision 1.30  2005/01/03 22:30:13  fwarmerdam
- * added support for saved quadtrees
- *
- * Revision 1.29  2004/09/26 20:09:35  fwarmerdam
- * avoid rcsid warnings
- *
- * Revision 1.28  2003/12/29 06:02:18  fwarmerdam
- * added cpl_error.h option
- *
- * Revision 1.27  2003/04/21 18:30:37  warmerda
- * added header write/update public methods
- *
- * Revision 1.26  2002/09/29 00:00:08  warmerda
- * added FTLogical and logical attribute read/write calls
- *
- * Revision 1.25  2002/05/07 13:46:30  warmerda
- * added DBFWriteAttributeDirectly().
- *
- * Revision 1.24  2002/04/10 16:59:54  warmerda
- * added SHPRewindObject
- *
- * Revision 1.23  2002/01/15 14:36:07  warmerda
- * updated email address
- *
- * Revision 1.22  2002/01/15 14:32:00  warmerda
- * try to improve SHPAPI_CALL docs
  */
 
 #include <stdio.h>
@@ -239,8 +136,8 @@ static const char *cvsid_aw() { return( cvsid_aw() ? NULL : cpl_cvsid ); }
 /*      UTF-8 encoded filenames Unicode filenames                       */
 /* -------------------------------------------------------------------- */
 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
-#	define SHPAPI_WINDOWS
-#	define SHPAPI_UTF8_HOOKS
+#  define SHPAPI_WINDOWS
+#  define SHPAPI_UTF8_HOOKS
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -281,21 +178,21 @@ typedef struct
     SAHooks sHooks;
 
     SAFile      fpSHP;
-    SAFile 	fpSHX;
+    SAFile      fpSHX;
 
-    int		nShapeType;				/* SHPT_* */
+    int         nShapeType;  /* SHPT_* */
 
-    unsigned int 	nFileSize;				/* SHP file */
+    unsigned int nFileSize;  /* SHP file */
 
     int         nRecords;
-    int		nMaxRecords;
-    unsigned int		*panRecOffset;
-    unsigned int		*panRecSize;
+    int         nMaxRecords;
+    unsigned int*panRecOffset;
+    unsigned int *panRecSize;
 
-    double	adBoundsMin[4];
-    double	adBoundsMax[4];
+    double      adBoundsMin[4];
+    double      adBoundsMax[4];
 
-    int		bUpdated;
+    int         bUpdated;
 
     unsigned char *pabyRec;
     int         nBufSize;
@@ -311,33 +208,32 @@ typedef SHPInfo * SHPHandle;
 /* -------------------------------------------------------------------- */
 /*      Shape types (nSHPType)                                          */
 /* -------------------------------------------------------------------- */
-#define SHPT_NULL	0
-#define SHPT_POINT	1
-#define SHPT_ARC	3
-#define SHPT_POLYGON	5
-#define SHPT_MULTIPOINT	8
-#define SHPT_POINTZ	11
-#define SHPT_ARCZ	13
-#define SHPT_POLYGONZ	15
+#define SHPT_NULL       0
+#define SHPT_POINT      1
+#define SHPT_ARC        3
+#define SHPT_POLYGON    5
+#define SHPT_MULTIPOINT 8
+#define SHPT_POINTZ     11
+#define SHPT_ARCZ       13
+#define SHPT_POLYGONZ   15
 #define SHPT_MULTIPOINTZ 18
-#define SHPT_POINTM	21
-#define SHPT_ARCM	23
-#define SHPT_POLYGONM	25
+#define SHPT_POINTM     21
+#define SHPT_ARCM       23
+#define SHPT_POLYGONM   25
 #define SHPT_MULTIPOINTM 28
 #define SHPT_MULTIPATCH 31
 
-
 /* -------------------------------------------------------------------- */
 /*      Part types - everything but SHPT_MULTIPATCH just uses           */
 /*      SHPP_RING.                                                      */
 /* -------------------------------------------------------------------- */
 
-#define SHPP_TRISTRIP	0
-#define SHPP_TRIFAN	1
-#define SHPP_OUTERRING	2
-#define SHPP_INNERRING	3
-#define SHPP_FIRSTRING	4
-#define SHPP_RING	5
+#define SHPP_TRISTRIP   0
+#define SHPP_TRIFAN     1
+#define SHPP_OUTERRING  2
+#define SHPP_INNERRING  3
+#define SHPP_FIRSTRING  4
+#define SHPP_RING       5
 
 /* -------------------------------------------------------------------- */
 /*      SHPObject - represents on shape (without attributes) read       */
@@ -345,32 +241,32 @@ typedef SHPInfo * SHPHandle;
 /* -------------------------------------------------------------------- */
 struct tagSHPObject
 {
-    int		nSHPType;
+    int    nSHPType;
 
-    int		nShapeId; /* -1 is unknown/unassigned */
+    int    nShapeId;  /* -1 is unknown/unassigned */
 
-    int		nParts;
-    int		*panPartStart;
-    int		*panPartType;
+    int    nParts;
+    int    *panPartStart;
+    int    *panPartType;
 
-    int		nVertices;
-    double	*padfX;
-    double	*padfY;
-    double	*padfZ;
-    double	*padfM;
+    int    nVertices;
+    double *padfX;
+    double *padfY;
+    double *padfZ;
+    double *padfM;
 
-    double	dfXMin;
-    double	dfYMin;
-    double	dfZMin;
-    double	dfMMin;
+    double dfXMin;
+    double dfYMin;
+    double dfZMin;
+    double dfMMin;
 
-    double	dfXMax;
-    double	dfYMax;
-    double	dfZMax;
-    double	dfMMax;
+    double dfXMax;
+    double dfYMax;
+    double dfZMax;
+    double dfMMax;
 
-    int		bMeasureIsUsed;
-    int     bFastModeReadObject;
+    int    bMeasureIsUsed;
+    int    bFastModeReadObject;
 };
 
 /* -------------------------------------------------------------------- */
@@ -388,7 +284,7 @@ SHPHandle SHPAPI_CALL
       SHPOpenLLEx( const char *pszShapeFile, const char *pszAccess,
                   SAHooks *psHooks, int bRestoreSHX );
 
-int       SHPAPI_CALL
+int SHPAPI_CALL
       SHPRestoreSHX( const char *pszShapeFile, const char *pszAccess,
                   SAHooks *psHooks );
 
@@ -444,7 +340,7 @@ const char SHPAPI_CALL1(*)
 /* -------------------------------------------------------------------- */
 
 /* this can be two or four for binary or quad tree */
-#define MAX_SUBNODE	4
+#define MAX_SUBNODE 4
 
 /* upper limit of tree levels for automatic estimation */
 #define MAX_DEFAULT_TREE_DEPTH 12
@@ -452,16 +348,16 @@ const char SHPAPI_CALL1(*)
 typedef struct shape_tree_node
 {
     /* region covered by this node */
-    double	adfBoundsMin[4];
-    double	adfBoundsMax[4];
+    double      adfBoundsMin[4];
+    double      adfBoundsMax[4];
 
     /* list of shapes stored at this node.  The papsShapeObj pointers
        or the whole list can be NULL */
-    int		nShapeCount;
-    int		*panShapeIds;
+    int         nShapeCount;
+    int         *panShapeIds;
     SHPObject   **papsShapeObj;
 
-    int		nSubNodes;
+    int         nSubNodes;
     struct shape_tree_node *apsSubNode[MAX_SUBNODE];
 
 } SHPTreeNode;
@@ -470,36 +366,36 @@ typedef struct
 {
     SHPHandle   hSHP;
 
-    int		nMaxDepth;
-    int		nDimension;
+    int         nMaxDepth;
+    int         nDimension;
     int         nTotalCount;
 
-    SHPTreeNode	*psRoot;
+    SHPTreeNode *psRoot;
 } SHPTree;
 
 SHPTree SHPAPI_CALL1(*)
       SHPCreateTree( SHPHandle hSHP, int nDimension, int nMaxDepth,
                      double *padfBoundsMin, double *padfBoundsMax );
-void    SHPAPI_CALL
+void SHPAPI_CALL
       SHPDestroyTree( SHPTree * hTree );
 
-int	SHPAPI_CALL
+int SHPAPI_CALL
       SHPWriteTree( SHPTree *hTree, const char * pszFilename );
 
-int	SHPAPI_CALL
+int SHPAPI_CALL
       SHPTreeAddShapeId( SHPTree * hTree, SHPObject * psObject );
-int	SHPAPI_CALL
+int SHPAPI_CALL
       SHPTreeRemoveShapeId( SHPTree * hTree, int nShapeId );
 
-void 	SHPAPI_CALL
+void SHPAPI_CALL
       SHPTreeTrimExtraNodes( SHPTree * hTree );
 
-int    SHPAPI_CALL1(*)
+int SHPAPI_CALL1(*)
       SHPTreeFindLikelyShapes( SHPTree * hTree,
                                double * padfBoundsMin,
                                double * padfBoundsMax,
                                int * );
-int     SHPAPI_CALL
+int SHPAPI_CALL
       SHPCheckBoundsOverlap( double *, double *, double *, double *, int );
 
 int SHPAPI_CALL1(*)
@@ -507,7 +403,6 @@ SHPSearchDiskTree( FILE *fp,
                    double *padfBoundsMin, double *padfBoundsMax,
                    int *pnShapeCount );
 
-
 typedef struct SHPDiskTreeInfo* SHPTreeDiskHandle;
 
 SHPTreeDiskHandle SHPAPI_CALL
@@ -519,13 +414,12 @@ void SHPAPI_CALL
 
 int SHPAPI_CALL1(*)
 SHPSearchDiskTreeEx( SHPTreeDiskHandle hDiskTree,
-                   double *padfBoundsMin, double *padfBoundsMax,
-                   int *pnShapeCount );
+                     double *padfBoundsMin, double *padfBoundsMax,
+                     int *pnShapeCount );
 
 int SHPAPI_CALL
     SHPWriteTreeLL(SHPTree *hTree, const char *pszFilename, SAHooks *psHooks );
 
-
 /* -------------------------------------------------------------------- */
 /*      SBN Search API                                                  */
 /* -------------------------------------------------------------------- */
@@ -554,33 +448,35 @@ void SHPAPI_CALL SBNSearchFreeIds( int* panShapeId );
 /************************************************************************/
 /*                             DBF Support.                             */
 /************************************************************************/
-typedef	struct
+typedef struct
 {
     SAHooks sHooks;
 
-    SAFile	fp;
+    SAFile      fp;
 
     int         nRecords;
 
-    int		nRecordLength;
-    int		nHeaderLength;
-    int		nFields;
-    int		*panFieldOffset;
-    int		*panFieldSize;
-    int		*panFieldDecimals;
-    char	*pachFieldType;
+    int         nRecordLength; /* Must fit on uint16 */
+    int         nHeaderLength; /* File header length (32) + field
+                                  descriptor length + spare space.
+                                  Must fit on uint16 */
+    int         nFields;
+    int         *panFieldOffset;
+    int         *panFieldSize;
+    int         *panFieldDecimals;
+    char        *pachFieldType;
 
-    char	*pszHeader;
+    char        *pszHeader; /* Field descriptors */
 
-    int		nCurrentRecord;
-    int		bCurrentRecordModified;
-    char	*pszCurrentRecord;
+    int         nCurrentRecord;
+    int         bCurrentRecordModified;
+    char        *pszCurrentRecord;
 
     int         nWorkFieldLength;
     char        *pszWorkField;
 
-    int		bNoHeader;
-    int		bUpdated;
+    int         bNoHeader;
+    int         bUpdated;
 
     union
     {
@@ -594,6 +490,8 @@ typedef	struct
     int         nUpdateYearSince1900; /* 0-255 */
     int         nUpdateMonth; /* 1-12 */
     int         nUpdateDay; /* 1-31 */
+
+    int         bWriteEndOfFileChar; /* defaults to TRUE */
 } DBFInfo;
 
 typedef DBFInfo * DBFHandle;
@@ -606,8 +504,14 @@ typedef enum {
   FTInvalid
 } DBFFieldType;
 
-#define XBASE_FLDHDR_SZ       32
-
+/* Field descriptor/header size */
+#define XBASE_FLDHDR_SZ         32
+/* Shapelib read up to 11 characters, even if only 10 should normally be used */
+#define XBASE_FLDNAME_LEN_READ  11
+/* On writing, we limit to 10 characters */
+#define XBASE_FLDNAME_LEN_WRITE 10
+/* Normally only 254 characters should be used. We tolerate 255 historically */
+#define XBASE_FLD_MAX_WIDTH     255
 
 DBFHandle SHPAPI_CALL
       DBFOpen( const char * pszDBFFile, const char * pszAccess );
@@ -621,19 +525,19 @@ DBFHandle SHPAPI_CALL
 DBFHandle SHPAPI_CALL
       DBFCreateLL( const char * pszDBFFile, const char * pszCodePage, SAHooks *psHooks );
 
-int	SHPAPI_CALL
+int SHPAPI_CALL
       DBFGetFieldCount( DBFHandle psDBF );
-int	SHPAPI_CALL
+int SHPAPI_CALL
       DBFGetRecordCount( DBFHandle psDBF );
-int	SHPAPI_CALL
+int SHPAPI_CALL
       DBFAddField( DBFHandle hDBF, const char * pszFieldName,
                    DBFFieldType eType, int nWidth, int nDecimals );
 
-int	SHPAPI_CALL
+int SHPAPI_CALL
       DBFAddNativeFieldType( DBFHandle hDBF, const char * pszFieldName,
                              char chType, int nWidth, int nDecimals );
 
-int	SHPAPI_CALL
+int SHPAPI_CALL
       DBFDeleteField( DBFHandle hDBF, int iField );
 
 int SHPAPI_CALL
@@ -650,15 +554,15 @@ DBFFieldType SHPAPI_CALL
 int SHPAPI_CALL
       DBFGetFieldIndex(DBFHandle psDBF, const char *pszFieldName);
 
-int 	SHPAPI_CALL
+int SHPAPI_CALL
       DBFReadIntegerAttribute( DBFHandle hDBF, int iShape, int iField );
-double 	SHPAPI_CALL
+double SHPAPI_CALL
       DBFReadDoubleAttribute( DBFHandle hDBF, int iShape, int iField );
 const char SHPAPI_CALL1(*)
       DBFReadStringAttribute( DBFHandle hDBF, int iShape, int iField );
 const char SHPAPI_CALL1(*)
       DBFReadLogicalAttribute( DBFHandle hDBF, int iShape, int iField );
-int     SHPAPI_CALL
+int SHPAPI_CALL
       DBFIsAttributeNULL( DBFHandle hDBF, int iShape, int iField );
 
 int SHPAPI_CALL
@@ -675,7 +579,7 @@ int SHPAPI_CALL
 
 int SHPAPI_CALL
      DBFWriteLogicalAttribute( DBFHandle hDBF, int iShape, int iField,
-			       const char lFieldValue);
+                               const char lFieldValue);
 int SHPAPI_CALL
      DBFWriteAttributeDirectly(DBFHandle psDBF, int hEntity, int iField,
                                void * pValue );
@@ -691,11 +595,11 @@ int SHPAPI_CALL DBFMarkRecordDeleted( DBFHandle psDBF, int iShape,
 DBFHandle SHPAPI_CALL
       DBFCloneEmpty(DBFHandle psDBF, const char * pszFilename );
 
-void	SHPAPI_CALL
+void SHPAPI_CALL
       DBFClose( DBFHandle hDBF );
 void    SHPAPI_CALL
       DBFUpdateHeader( DBFHandle hDBF );
-char    SHPAPI_CALL
+char SHPAPI_CALL
       DBFGetNativeFieldType( DBFHandle hDBF, int iField );
 
 const char SHPAPI_CALL1(*)
@@ -704,6 +608,8 @@ const char SHPAPI_CALL1(*)
 void SHPAPI_CALL
     DBFSetLastModifiedDate( DBFHandle psDBF, int nYYSince1900, int nMM, int nDD );
 
+void SHPAPI_CALL DBFSetWriteEndOfFileChar( DBFHandle psDBF, int bWriteFlag );
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/ogr/ogrsf_frmts/shape/shp_vsi.c b/ogr/ogrsf_frmts/shape/shp_vsi.c
index 8af56f8..904ceaa 100644
--- a/ogr/ogrsf_frmts/shape/shp_vsi.c
+++ b/ogr/ogrsf_frmts/shape/shp_vsi.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shp_vsi.c 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: shp_vsi.c 37091 2017-01-10 17:25:57Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  IO Redirection via VSI services for shp/dbf io.
@@ -31,8 +31,9 @@
 #include "shp_vsi.h"
 #include "cpl_error.h"
 #include "cpl_conv.h"
+#include "cpl_vsi_error.h"
 
-CPL_CVSID("$Id: shp_vsi.c 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: shp_vsi.c 37091 2017-01-10 17:25:57Z rouault $");
 
 typedef struct
 {
@@ -73,7 +74,7 @@ SAFile VSI_SHP_OpenInternal( const char *pszFilename, const char *pszAccess,
 
 {
     OGRSHPDBFFile* pFile;
-    VSILFILE* fp = VSIFOpenL( pszFilename, pszAccess );
+    VSILFILE* fp = VSIFOpenExL( pszFilename, pszAccess, TRUE );
     if( fp == NULL )
         return NULL;
     pFile = (OGRSHPDBFFile* )CPLCalloc(1,sizeof(OGRSHPDBFFile));
diff --git a/ogr/ogrsf_frmts/shape/shpopen.c b/ogr/ogrsf_frmts/shape/shpopen.c
index 6b257a5..701db8a 100644
--- a/ogr/ogrsf_frmts/shape/shpopen.c
+++ b/ogr/ogrsf_frmts/shape/shpopen.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shpopen.c,v 1.73 2012-01-24 22:33:01 fwarmerdam Exp $
+ * $Id: shpopen.c 37185 2017-01-19 13:36:59Z rouault $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of core Shapefile read/write functions.
@@ -10,7 +10,7 @@
  * Copyright (c) 2011-2013, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * or at the option of the licensee under the LGPL (see COPYING).  This
  * option is discussed in more detail in shapelib.html.
  *
  * --
@@ -35,6 +35,28 @@
  ******************************************************************************
  *
  * $Log: shpopen.c,v $
+ * Revision 1.75  2016-12-05 12:44:05  erouault
+ * * Major overhaul of Makefile build system to use autoconf/automake.
+ *
+ * * Warning fixes in contrib/
+ *
+ * Revision 1.74  2016-12-04 15:30:15  erouault
+ * * shpopen.c, dbfopen.c, shptree.c, shapefil.h: resync with
+ * GDAL Shapefile driver. Mostly cleanups. SHPObject and DBFInfo
+ * structures extended with new members. New functions:
+ * DBFSetLastModifiedDate, SHPOpenLLEx, SHPRestoreSHX,
+ * SHPSetFastModeReadObject
+ *
+ * * sbnsearch.c: new file to implement original ESRI .sbn spatial
+ * index reading. (no write support). New functions:
+ * SBNOpenDiskTree, SBNCloseDiskTree, SBNSearchDiskTree,
+ * SBNSearchDiskTreeInteger, SBNSearchFreeIds
+ *
+ * * Makefile, makefile.vc, CMakeLists.txt, shapelib.def: updates
+ * with new file and symbols.
+ *
+ * * commit: helper script to cvs commit
+ *
  * Revision 1.73  2012-01-24 22:33:01  fwarmerdam
  * fix memory leak on failure to open .shp (gdal #4410)
  *
@@ -145,7 +167,7 @@
  * avoid c++ comments
  *
  * Revision 1.38  2002/05/07 16:43:39  warmerda
- * Removed debugging printf.
+ * Removed debugging printf()
  *
  * Revision 1.37  2002/04/10 17:35:22  warmerda
  * fixed bug in ring reversal code
@@ -273,8 +295,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <errno.h>
 
-SHP_CVSID("$Id: shpopen.c,v 1.73 2012-01-24 22:33:01 fwarmerdam Exp $")
+SHP_CVSID("$Id: shpopen.c 37185 2017-01-19 13:36:59Z rouault $")
 
 typedef unsigned char uchar;
 
@@ -295,11 +318,25 @@ typedef unsigned int	      int32;
 #  define MAX(a,b)      ((a>b) ? a : b)
 #endif
 
-#if defined(WIN32) || defined(_WIN32)
+#ifndef USE_CPL
+#if defined(_MSC_VER)
+# if _MSC_VER < 1900
+#     define snprintf _snprintf
+# endif
+#elif defined(WIN32) || defined(_WIN32)
 #  ifndef snprintf
 #     define snprintf _snprintf
 #  endif
 #endif
+#endif
+
+#ifndef CPL_UNUSED
+#if defined(__GNUC__) && __GNUC__ >= 4
+#  define CPL_UNUSED __attribute((__unused__))
+#else
+#  define CPL_UNUSED
+#endif
+#endif  
 
 #if defined(CPL_LSB)
 #define bBigEndian FALSE
@@ -355,7 +392,7 @@ static void * SfRealloc( void * pMem, int nNewSize )
 void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
 
 {
-    uchar     	abyHeader[100];
+    uchar     	abyHeader[100] = { 0 };
     int		i;
     int32	i32;
     double	dValue;
@@ -370,8 +407,6 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
 /* -------------------------------------------------------------------- */
 /*      Prepare header block for .shp file.                             */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < 100; i++ )
-        abyHeader[i] = 0;
 
     abyHeader[2] = 0x27;				/* magic cookie */
     abyHeader[3] = 0x0a;
@@ -426,7 +461,11 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
     if( psSHP->sHooks.FSeek( psSHP->fpSHP, 0, 0 ) != 0
         || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHP ) != 1 )
     {
-        psSHP->sHooks.Error( "Failure writing .shp header" );
+        char szError[200];
+
+        snprintf( szError, sizeof(szError),
+                 "Failure writing .shp header: %s", strerror(errno) );
+        psSHP->sHooks.Error( szError );
         return;
     }
 
@@ -440,7 +479,12 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
     if( psSHP->sHooks.FSeek( psSHP->fpSHX, 0, 0 ) != 0
         || psSHP->sHooks.FWrite( abyHeader, 100, 1, psSHP->fpSHX ) != 1 )
     {
-        psSHP->sHooks.Error( "Failure writing .shx header" );
+        char szError[200];
+
+        snprintf( szError, sizeof(szError),
+                 "Failure writing .shx header: %s", strerror(errno) );
+        psSHP->sHooks.Error( szError );
+
         return;
     }
 
@@ -465,7 +509,11 @@ void SHPAPI_CALL SHPWriteHeader( SHPHandle psSHP )
     if( (int)psSHP->sHooks.FWrite( panSHX, sizeof(int32)*2, psSHP->nRecords, psSHP->fpSHX )
         != psSHP->nRecords )
     {
-        psSHP->sHooks.Error( "Failure writing .shx contents" );
+        char szError[200];
+
+        snprintf( szError, sizeof(szError),
+                 "Failure writing .shx contents: %s", strerror(errno) );
+        psSHP->sHooks.Error( szError );
     }
 
     free( panSHX );
@@ -623,10 +671,8 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
     pabyBuf = (uchar *) malloc(100);
     psSHP->sHooks.FRead( pabyBuf, 100, 1, psSHP->fpSHP );
 
-    psSHP->nFileSize = ((unsigned int)pabyBuf[24] * 256 * 256 * 256
-                        + (unsigned int)pabyBuf[25] * 256 * 256
-                        + (unsigned int)pabyBuf[26] * 256
-                        + (unsigned int)pabyBuf[27]);
+    psSHP->nFileSize = ((unsigned int)pabyBuf[24]<<24)|(pabyBuf[25]<<16)|
+                        (pabyBuf[26]<<8)|pabyBuf[27];
     if( psSHP->nFileSize < 0xFFFFFFFFU / 2 )
         psSHP->nFileSize *= 2;
     else
@@ -649,8 +695,8 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         return( NULL );
     }
 
-    psSHP->nRecords = pabyBuf[27] + pabyBuf[26] * 256
-        + pabyBuf[25] * 256 * 256 + (pabyBuf[24] & 0x7F) * 256 * 256 * 256;
+    psSHP->nRecords = pabyBuf[27]|(pabyBuf[26]<<8)|(pabyBuf[25]<<16)|
+                      ((pabyBuf[24] & 0x7F)<<24);
     psSHP->nRecords = (psSHP->nRecords - 50) / 4;
 
     psSHP->nShapeType = pabyBuf[32];
@@ -772,8 +818,8 @@ SHPOpenLL( const char * pszLayer, const char * pszAccess, SAHooks *psHooks )
         char szError[200];
 
         snprintf( szError, sizeof(szError),
-                 "Failed to read all values for %d records in .shx file.",
-                 psSHP->nRecords );
+                 "Failed to read all values for %d records in .shx file: %s.",
+                 psSHP->nRecords, strerror(errno) );
         psSHP->sHooks.Error( szError );
 
         /* SHX is short or unreadable for some reason. */
@@ -966,10 +1012,8 @@ SHPRestoreSHX ( const char * pszLayer, const char * pszAccess, SAHooks *psHooks
     pabyBuf = (uchar *) malloc(100);
     psHooks->FRead( pabyBuf, 100, 1, fpSHP );
 
-    nSHPFilesize = ((unsigned int)pabyBuf[24] * 256 * 256 * 256
-                        + (unsigned int)pabyBuf[25] * 256 * 256
-                        + (unsigned int)pabyBuf[26] * 256
-                        + (unsigned int)pabyBuf[27]);
+    nSHPFilesize = ((unsigned int)pabyBuf[24]<<24)|(pabyBuf[25]<<16)|
+                   (pabyBuf[26]<<8)|pabyBuf[27];
     if( nSHPFilesize < 0xFFFFFFFFU / 2 )
         nSHPFilesize *= 2;
     else
@@ -1229,7 +1273,12 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     fpSHP = psHooks->FOpen(pszFullname, "wb" );
     if( fpSHP == NULL )
     {
-        psHooks->Error( "Failed to create file .shp file." );
+        char szError[200];
+        snprintf( szError, sizeof(szError),
+                 "Failed to create file %s: %s",
+                  pszFullname, strerror(errno) );
+        psHooks->Error( szError );
+
         goto error;
     }
 
@@ -1237,7 +1286,11 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
     fpSHX = psHooks->FOpen(pszFullname, "wb" );
     if( fpSHX == NULL )
     {
-        psHooks->Error( "Failed to create file .shx file." );
+        char szError[200];
+        snprintf( szError, sizeof(szError),
+                 "Failed to create file %s: %s",
+                  pszFullname, strerror(errno) );
+        psHooks->Error( szError );
         goto error;
     }
 
@@ -1247,8 +1300,7 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
 /*      Prepare header block for .shp file.                             */
 /* -------------------------------------------------------------------- */
-    for( i = 0; i < 100; i++ )
-        abyHeader[i] = 0;
+    memset( abyHeader, 0, sizeof(abyHeader) );
 
     abyHeader[2] = 0x27;				/* magic cookie */
     abyHeader[3] = 0x0a;
@@ -1276,7 +1328,12 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 /* -------------------------------------------------------------------- */
     if( psHooks->FWrite( abyHeader, 100, 1, fpSHP ) != 1 )
     {
-        psHooks->Error( "Failed to write .shp header." );
+        char szError[200];
+
+        snprintf( szError, sizeof(szError),
+                 "Failed to write .shp header: %s", strerror(errno) );
+        psHooks->Error( szError );
+
         goto error;
     }
 
@@ -1289,7 +1346,12 @@ SHPCreateLL( const char * pszLayer, int nShapeType, SAHooks *psHooks )
 
     if( psHooks->FWrite( abyHeader, 100, 1, fpSHX ) != 1 )
     {
-        psHooks->Error( "Failed to write .shx header." );
+        char szError[200];
+
+        snprintf( szError, sizeof(szError),
+                 "Failure writing .shx header: %s", strerror(errno) );
+        psHooks->Error( szError );
+
         goto error;
     }
 
@@ -1458,24 +1520,26 @@ SHPCreateObject( int nSHPType, int nShapeId, int nParts,
 /* -------------------------------------------------------------------- */
     if( nVertices > 0 )
     {
-        psObject->padfX = (double *) calloc(sizeof(double),nVertices);
-        psObject->padfY = (double *) calloc(sizeof(double),nVertices);
-        psObject->padfZ = (double *) calloc(sizeof(double),nVertices);
-        psObject->padfM = (double *) calloc(sizeof(double),nVertices);
-
-        for( i = 0; i < nVertices; i++ )
-        {
-            if( padfX != NULL )
-                psObject->padfX[i] = padfX[i];
-            if( padfY != NULL )
-                psObject->padfY[i] = padfY[i];
-            if( padfZ != NULL && bHasZ )
-                psObject->padfZ[i] = padfZ[i];
-            if( padfM != NULL && bHasM )
-                psObject->padfM[i] = padfM[i];
-        }
+        size_t nSize = sizeof(double) * nVertices;
+        psObject->padfX = (double *) padfX ? malloc(nSize) :
+                                             calloc(sizeof(double),nVertices);
+        psObject->padfY = (double *) padfY ? malloc(nSize) :
+                                             calloc(sizeof(double),nVertices);
+        psObject->padfZ = (double *) padfZ && bHasZ ? malloc(nSize) :
+                                             calloc(sizeof(double),nVertices);
+        psObject->padfM = (double *) padfM && bHasM ? malloc(nSize) :
+                                             calloc(sizeof(double),nVertices);
+        if( padfX != NULL )
+            memcpy(psObject->padfX, padfX, nSize);
+        if( padfY != NULL )
+            memcpy(psObject->padfY, padfY, nSize);
+        if( padfZ != NULL && bHasZ )
+            memcpy(psObject->padfZ, padfZ, nSize);
         if( padfM != NULL && bHasM )
+        {
+            memcpy(psObject->padfM, padfM, nSize);
             psObject->bMeasureIsUsed = TRUE;
+        }
     }
 
 /* -------------------------------------------------------------------- */
@@ -1859,13 +1923,25 @@ SHPWriteObject(SHPHandle psSHP, int nShapeId, SHPObject * psObject )
 /* -------------------------------------------------------------------- */
     if( psSHP->sHooks.FSeek( psSHP->fpSHP, nRecordOffset, 0 ) != 0 )
     {
-        psSHP->sHooks.Error( "Error in psSHP->sHooks.FSeek() while writing object to .shp file." );
+        char szError[200];
+
+        snprintf( szError, sizeof(szError),
+                 "Error in psSHP->sHooks.FSeek() while writing object to .shp file: %s",
+                  strerror(errno) );
+        psSHP->sHooks.Error( szError );
+
         free( pabyRec );
         return -1;
     }
     if( psSHP->sHooks.FWrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
     {
-        psSHP->sHooks.Error( "Error in psSHP->sHooks.Fwrite() while writing object to .shp file." );
+        char szError[200];
+
+        snprintf( szError, sizeof(szError),
+                 "Error in psSHP->sHooks.FWrite() while writing object of %u bytes to .shp file: %s",
+                  nRecordSize, strerror(errno) );
+        psSHP->sHooks.Error( szError );
+
         free( pabyRec );
         return -1;
     }
@@ -2072,7 +2148,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             {
                 char str[128];
                 snprintf( str, sizeof(str),
-                         "Error in fread() reading object of size %u at offset %u from .shp file",
+                         "Error in fread() reading object of size %d at offset %u from .shp file",
                          nEntitySize, psSHP->panRecOffset[hEntity] );
 
                 psSHP->sHooks.Error( str );
@@ -2156,7 +2232,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
          */
         char str[128];
         snprintf( str, sizeof(str),
-                 "Error in fread() reading object of size %u at offset %u from .shp file",
+                 "Error in fread() reading object of size %d at offset %u from .shp file",
                  nEntitySize, psSHP->panRecOffset[hEntity] );
 
         psSHP->sHooks.Error( str );
@@ -2249,7 +2325,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d.",
+                     "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u.",
                      hEntity, nPoints, nParts);
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
@@ -2273,7 +2349,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         if (nRequiredSize > nEntitySize)
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Corrupted .shp file : shape %d, nPoints=%d, nParts=%d, nEntitySize=%d.",
+                     "Corrupted .shp file : shape %d, nPoints=%u, nParts=%u, nEntitySize=%d.",
                      hEntity, nPoints, nParts, nEntitySize);
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
@@ -2305,8 +2381,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             psShape->panPartType == NULL)
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                    "Not enough memory to allocate requested memory (nPoints=%d, nParts=%d) for shape %d. "
-                    "Probably broken SHP file", hEntity, nPoints, nParts );
+                    "Not enough memory to allocate requested memory (nPoints=%u, nParts=%u) for shape %d. "
+                    "Probably broken SHP file", nPoints, nParts, hEntity );
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
@@ -2466,7 +2542,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         if (/* nPoints < 0 || */ nPoints > 50 * 1000 * 1000)
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Corrupted .shp file : shape %d : nPoints = %d",
+                     "Corrupted .shp file : shape %d : nPoints = %u",
                      hEntity, nPoints);
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
@@ -2481,7 +2557,7 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
         if (nRequiredSize > nEntitySize)
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Corrupted .shp file : shape %d : nPoints = %d, nEntitySize = %d",
+                     "Corrupted .shp file : shape %d : nPoints = %u, nEntitySize = %d",
                      hEntity, nPoints, nEntitySize);
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
@@ -2508,8 +2584,8 @@ SHPReadObject( SHPHandle psSHP, int hEntity )
             psShape->padfM == NULL)
         {
             snprintf(szErrorMsg, sizeof(szErrorMsg),
-                     "Not enough memory to allocate requested memory (nPoints=%d) for shape %d. "
-                     "Probably broken SHP file", hEntity, nPoints );
+                     "Not enough memory to allocate requested memory (nPoints=%u) for shape %d. "
+                     "Probably broken SHP file", nPoints, hEntity );
             psSHP->sHooks.Error( szErrorMsg );
             SHPDestroyObject(psShape);
             return NULL;
diff --git a/ogr/ogrsf_frmts/shape/shptree.c b/ogr/ogrsf_frmts/shape/shptree.c
index b6f1b85..c8915df 100644
--- a/ogr/ogrsf_frmts/shape/shptree.c
+++ b/ogr/ogrsf_frmts/shape/shptree.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: shptree.c,v 1.17 2012-01-27 21:09:26 fwarmerdam Exp $
+ * $Id: shptree.c 36727 2016-12-06 20:04:22Z rouault $
  *
  * Project:  Shapelib
  * Purpose:  Implementation of quadtree building and searching functions.
@@ -10,7 +10,7 @@
  * Copyright (c) 2012, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * This software is available under the following "MIT Style" license,
- * or at the option of the licensee under the LGPL (see LICENSE.LGPL).  This
+ * or at the option of the licensee under the LGPL (see COPYING).  This
  * option is discussed in more detail in shapelib.html.
  *
  * --
@@ -40,12 +40,13 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 
 #ifdef USE_CPL
 #include "cpl_error.h"
 #endif
 
-SHP_CVSID("$Id: shptree.c,v 1.17 2012-01-27 21:09:26 fwarmerdam Exp $")
+SHP_CVSID("$Id: shptree.c 36727 2016-12-06 20:04:22Z rouault $")
 
 #ifndef TRUE
 #  define TRUE 1
diff --git a/ogr/ogrsf_frmts/sosi/GNUmakefile b/ogr/ogrsf_frmts/sosi/GNUmakefile
index acd1bd8..0a33b21 100644
--- a/ogr/ogrsf_frmts/sosi/GNUmakefile
+++ b/ogr/ogrsf_frmts/sosi/GNUmakefile
@@ -2,7 +2,7 @@
 
 include ../../../GDALmake.opt
 
-OBJ	=	ogrsosidriver.o ogrsosidatasource.o ogrsosilayer.o ogrsosidatatypes.o 
+OBJ	=	ogrsosidriver.o ogrsosidatasource.o ogrsosilayer.o ogrsosidatatypes.o
 
 CPPFLAGS	:=-DLINUX -DUNIX -I.. -I../..  $(SOSI_INC) $(CPPFLAGS)
 
diff --git a/ogr/ogrsf_frmts/sosi/fyba_melding.cpp b/ogr/ogrsf_frmts/sosi/fyba_melding.cpp
index ba2b30c..54e251e 100644
--- a/ogr/ogrsf_frmts/sosi/fyba_melding.cpp
+++ b/ogr/ogrsf_frmts/sosi/fyba_melding.cpp
@@ -1,72 +1,63 @@
-/******************************************************************************
- * $Id: fyba_melding.cpp 33128 2016-01-23 20:05:32Z rouault $
- *
- * Project:  FYBA Callbacks
- * Purpose:  Needed by FYBA - however we do not want to display most messages
- * Author:   Thomas Hirsch, <thomas.hirsch statkart no>
- *
- ******************************************************************************
- * Copyright (c) 2010, Thomas Hirsch
- * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include <windows.h>
-#include "fyba.h"
-
-static short sProsent;
-
-void LC_Error(short feil_nr, const char *logtx, const char *vartx)
-{
-   char szErrMsg[260];
-   short strategi;
-   char *pszFeilmelding;
-
-
-   // Translate all to English.
-   // Egen enkel implementasjon av feilhandtering
-   /* Hent feilmeldingstekst og strategi */
-   strategi = LC_StrError(feil_nr,&pszFeilmelding);
-   switch(strategi) {
-      case 2:  sprintf(szErrMsg,"%s","Observer følgende! \n\n");break;
-      case 3:  sprintf(szErrMsg,"%s","Det er oppstått en feil! \n\n");break;
-      case 4:  sprintf(szErrMsg,"%s","Alvorlig feil avslutt programmet! \n\n");break;
-      default: szErrMsg[0]='\0';
-   }
-}
-
-
-void LC_StartMessage(const char *pszFilnavn)
-{
-}
-
-void LC_ShowMessage(double prosent) // TODO: prosent?
-{
-}
-
-void LC_EndMessage(void)
-{
-}
-
-short LC_Cancel(void)
-{
-      /* Not supported */
-      return FALSE;
-}
+/******************************************************************************
+ *
+ * Project:  FYBA Callbacks
+ * Purpose:  Needed by FYBA - however we do not want to display most messages
+ * Author:   Thomas Hirsch, <thomas.hirsch statkart no>
+ *
+ ******************************************************************************
+ * Copyright (c) 2010, Thomas Hirsch
+ * Copyright (c) 2010, Even Rouault <even dot rouault at mines-paris dot org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <windows.h>
+#include "fyba.h"
+
+static short sProsent;
+
+void LC_Error(short feil_nr, const char *logtx, const char *vartx)
+{
+    char szErrMsg[260] = {};
+    char *pszFeilmelding = NULL;
+
+    // Translate all to English.
+    // Egen enkel implementasjon av feilhandtering
+    /* Hent feilmeldingstekst og strategi */
+    const short strategi = LC_StrError(feil_nr,&pszFeilmelding);
+    switch(strategi) {
+      case 2:  sprintf(szErrMsg,"%s","Observer følgende! \n\n");break;
+      case 3:  sprintf(szErrMsg,"%s","Det er oppstått en feil! \n\n");break;
+      case 4:  sprintf(szErrMsg,"%s","Alvorlig feil avslutt programmet! \n\n");break;
+      default: /*szErrMsg[0]='\0';*/ break;
+   }
+}
+
+void LC_StartMessage(const char *pszFilnavn) {}
+
+void LC_ShowMessage(double prosent) // TODO: prosent?
+{}
+
+void LC_EndMessage(void) {}
+
+short LC_Cancel(void)
+{
+      // Not supported.
+      return FALSE;
+}
diff --git a/ogr/ogrsf_frmts/sosi/ogr_sosi.h b/ogr/ogrsf_frmts/sosi/ogr_sosi.h
index 1542475..a03fd0d 100644
--- a/ogr/ogrsf_frmts/sosi/ogr_sosi.h
+++ b/ogr/ogrsf_frmts/sosi/ogr_sosi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sosi.h 34420 2016-06-24 21:06:03Z rouault $
+ * $Id: ogr_sosi.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSIDriver.
@@ -70,14 +70,14 @@ public:
     OGRSOSILayer( OGRSOSIDataSource *poPar, OGRFeatureDefn *poFeatDefn, LC_FILADM *poFil, S2I *poHeadDefn);
     ~OGRSOSILayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
-    OGRFeatureDefn *    GetLayerDefn();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    OGRFeatureDefn *    GetLayerDefn() override;
 #ifdef WRITE_SUPPORT
     OGRErr              CreateField(OGRFieldDefn *poField, int bApproxOK=TRUE);
     OGRErr              ICreateFeature(OGRFeature *poFeature);
 #endif
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************
@@ -122,20 +122,19 @@ public:
 #ifdef WRITE_SUPPORT
     int                 Create( const char * pszFilename );
 #endif
-    const char          *GetName() {
+    const char          *GetName() override {
         return pszName;
     }
-    int                 GetLayerCount() {
+    int                 GetLayerCount() override {
         return nLayers;
     }
-    OGRLayer            *GetLayer( int );
+    OGRLayer            *GetLayer( int ) override;
 #ifdef WRITE_SUPPORT
     OGRLayer            *ICreateLayer( const char *pszName, OGRSpatialReference  *poSpatialRef=NULL, OGRwkbGeometryType eGType=wkbUnknown, char **papszOptions=NULL);
 #endif
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 };
 
-
 /************************************************************************
  *                           OGRSOSIDataTypes                           *
  * OGRSOSIDataTypes provides the correct data types for some of the     *
@@ -143,7 +142,7 @@ public:
  ************************************************************************/
 
 class OGRSOSISimpleDataType {
-    const char          *pszName; 
+    const char          *pszName;
     OGRFieldType        nType;
 
 public:
@@ -158,14 +157,22 @@ public:
     OGRFieldType        GetType() {
         return nType;
     };
-
 };
 
 class OGRSOSIDataType {
+    // cppcheck is right here. The disgn of this class is disputable
+    // cppcheck-suppress unsafeClassCanLeak
     OGRSOSISimpleDataType* poElements;
     int                    nElementCount;
+
 public:
-    OGRSOSIDataType (int nSize);
+    explicit OGRSOSIDataType (int nSize);
+
+    OGRSOSIDataType( const OGRSOSIDataType& oSrc ) :
+            // cppcheck-suppress copyCtorPointerCopying
+            poElements( oSrc.poElements ),
+            nElementCount( oSrc.nElementCount ) {}
+
     ~OGRSOSIDataType();
 
     void setElement(int nIndex, const char *name, OGRFieldType type);
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp b/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp
index c6d32f1..8226e00 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosidatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsosidatasource.cpp 34420 2016-06-24 21:06:03Z rouault $
  *
  * Project:  SOSI Data Source
  * Purpose:  Provide SOSI Data to OGR.
@@ -32,13 +31,14 @@
 #include <map>
 #include <math.h>
 
+CPL_CVSID("$Id: ogrsosidatasource.cpp 36457 2016-11-23 00:18:37Z rouault $");
+
 /* This is the most common encoding for SOSI files. Let's at least try if
  * it is supported, or generate a meaningful error message.               */
 #ifndef CPL_ENC_ISO8859_10
 #  define CPL_ENC_ISO8859_10 "ISO8859-10"
 #endif
 
-
 #ifdef WRITE_SUPPORT
 /************************************************************************/
 /*                              utility methods                         */
@@ -155,9 +155,10 @@ OGRSOSIDataSource::OGRSOSIDataSource() {
     poCurveHeaders = NULL;
 
     pszEncoding = CPL_ENC_UTF8;
-    
+    nNumFeatures = 0;
+
     SOSIInitTypes();
-    
+
     nMode = MODE_READING;
 }
 
@@ -209,7 +210,7 @@ OGRFeatureDefn *defineLayer(const char *szName, OGRwkbGeometryType szType, S2I *
     poFeatureDefn->SetGeomType( szType );
     S2I* poHeadersNew  = *ppoHeadersNew;
 
-    for (S2I::iterator i=poHeaders->begin(); i!=poHeaders->end(); i++) {
+    for (S2I::iterator i=poHeaders->begin(); i!=poHeaders->end(); ++i) {
                 OGRSOSIDataType* poType = SOSIGetType(i->first);
                 OGRSOSISimpleDataType* poElements = poType->getElements();
                 for (int k=0; k<poType->getElementCount(); k++) {
@@ -274,7 +275,7 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
 
     /* --------------------------------------------------------------------*
      *      Prefetch all the information needed to determine layers        *
-     * 	    and prebuild LineString features for later assembly.           *
+     *      and prebuild LineString features for later assembly.           *
      * --------------------------------------------------------------------*/
 
     /* allocate room for one pointer per feature */
@@ -291,9 +292,9 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
     short          nName, nNumLines;
     long           nNumCoo;
     unsigned short nInfo;
-    LC_SNR_ADM	   oSnradm;
-    LC_BGR		   oNextSerial;
-    LC_BGR		  *poNextSerial;
+    LC_SNR_ADM oSnradm;
+    LC_BGR   oNextSerial;
+    LC_BGR  *poNextSerial;
     poNextSerial =&oNextSerial;
 
     bool bPointLayer = FALSE; /* Initialize four layers for the different geometry types */
@@ -339,8 +340,8 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
                     }
                     break;
                 }
-                case L_KURVE:  
-                case L_LINJE:  
+                case L_KURVE:
+                case L_LINJE:
                 case L_BUEP:  {    /* FIXME: maybe not use the same headers for both */
                     if (poCurveHeaders->find(osKey) == poCurveHeaders->end()) {
                         iH = static_cast<int>(poCurveHeaders->size());
@@ -348,7 +349,7 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
                     }
                     break;
                 }
-                case L_PUNKT: 
+                case L_PUNKT:
                 case L_SYMBOL: {
                     if (poPointHeaders->find(osKey) == poPointHeaders->end()) {
                         iH = static_cast<int>(poPointHeaders->size());
@@ -382,7 +383,7 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
             /* cannot build geometries that reference others yet */
             break;
         }
-        case L_KURVE: 
+        case L_KURVE:
         case L_LINJE: {
             /* Pre-build a line feature. Activate line/curve layer. */
             bCurveLayer = TRUE;
@@ -416,8 +417,8 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
             /* Get coordinate system from SOSI header. */
             int nEPSG = sosi2epsg(oTrans.sKoordsys);
             if (poSRS->importFromEPSG(nEPSG) != OGRERR_NONE) {
-				CPLError( CE_Failure, CPLE_OpenFailed,
-                          "OGR could not load coordinate system definition EPSG:%i.", nEPSG);
+              CPLError( CE_Failure, CPLE_OpenFailed,
+                        "OGR could not load coordinate system definition EPSG:%i.", nEPSG);
                 return FALSE;
             }
 
@@ -461,10 +462,9 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
 
     /* Define each layer, using a proper feature definition, geometry type,
      * and adding every SOSI header encountered in the file as field. */
-    S2I::iterator i;
     if (bPolyLayer) {
         S2I * poHeadersNew = new S2I();
-		OGRFeatureDefn *poFeatureDefn = defineLayer("polygons", wkbPolygon, poPolyHeaders, &poHeadersNew);
+        OGRFeatureDefn *poFeatureDefn = defineLayer("polygons", wkbPolygon, poPolyHeaders, &poHeadersNew);
         delete poPolyHeaders;
         poPolyHeaders = poHeadersNew;
         poFeatureDefn->Reference();
@@ -515,8 +515,8 @@ int  OGRSOSIDataSource::Open( const char *pszFilename, int bUpdate ) {
 /************************************************************************/
 
 int  OGRSOSIDataSource::Create( const char *pszFilename ) {
-	short nStatus;
-	short nDetStatus;
+    short nStatus;
+    short nDetStatus;
 
     poBaseadm = LC_OpenBase(LC_KLADD);
     nStatus   = LC_OpenSos(pszFilename, LC_SEKV_SKRIV, LC_NY_IDX, LC_INGEN_STATUS,
@@ -575,8 +575,9 @@ OGRLayer *OGRSOSIDataSource::ICreateLayer( const char *pszNameIn,
             }
         }
         LC_WsGr(poFileadm); /* Writing the header here! */
-
-    } else {
+    }
+    else
+    {
         if (!poSRS->IsSame(poSpatialRef)) {
           CPLError( CE_Failure, CPLE_AppDefined,
                     "SOSI driver does not support different spatial reference systems in one file.");
@@ -611,7 +612,8 @@ void OGRSOSIDataSource::buildOGRMultiPoint(int nNumCoo, long iSerial) {
     OGRMultiPoint *poMP = new OGRMultiPoint();
 
     long i;
-    double dfEast = 0, dfNorth = 0;
+    double dfEast = 0.0;
+    double dfNorth = 0.0;
     for (i=(nNumCoo>1)?2:1; i<=nNumCoo; i++) {
         LC_GetTK(i, &dfEast, &dfNorth);
         OGRPoint poP = OGRPoint(dfEast, dfNorth);
@@ -637,7 +639,7 @@ void OGRSOSIDataSource::buildOGRLineString(int nNumCoo, long iSerial) {
     papoBuiltGeometries[iSerial] = poLS;
 }
 
-static double sqr(double x) { return x * x; } 
+static double sqr(double x) { return x * x; }
 
 void OGRSOSIDataSource::buildOGRLineStringFromArc(long iSerial) {
     if (papoBuiltGeometries[iSerial] != NULL) {
@@ -645,7 +647,7 @@ void OGRSOSIDataSource::buildOGRLineStringFromArc(long iSerial) {
     }
 
     OGRLineString *poLS = new OGRLineString();
-   
+
     /* fetch reference points on circle (easting, northing) */
     double e1 = 0, e2 = 0, e3 = 0;
     double n1 = 0, n2 = 0, n3 = 0;
@@ -663,8 +665,8 @@ void OGRSOSIDataSource::buildOGRLineStringFromArc(long iSerial) {
     double dN13 = n1 - n3;
 
     /* center of the circle */
-    double cE = (dN13 * p12 - dN12 * p13) / (dE12 * dN13 - dN12 * dE13) ; 
-    double cN = (dE13 * p12 - dE12 * p13) / (dN12 * dE13 - dE12 * dN13) ;
+    double cE = (dN13 * p12 - dN12 * p13) / (dE12 * dN13 - dN12 * dE13);
+    double cN = (dE13 * p12 - dE12 * p13) / (dN12 * dE13 - dE12 * dN13);
 
     /* radius of the circle */
     double r = sqrt(sqr(e1 - cE) + sqr(n1 - cN));
@@ -676,7 +678,7 @@ void OGRSOSIDataSource::buildOGRLineStringFromArc(long iSerial) {
     /* interpolation step in radians */
     double dth = th3 - th1;
     if (dth < 0) {dth  += 2 * M_PI;}
-    if (dth > M_PI) { 
+    if (dth > M_PI) {
       dth = - 2*M_PI + dth;
     }
     int    npt = (int)(ARC_INTERPOLATION_FULL_CIRCLE * dth / 2*M_PI);
@@ -685,21 +687,19 @@ void OGRSOSIDataSource::buildOGRLineStringFromArc(long iSerial) {
     poLS->setNumPoints(npt);
     dth = dth / (npt-1);
 
-    long i;
+    int i;
     double dfEast = 0, dfNorth = 0;
-    
+
     for (i=0; i<npt; i++) {
         dfEast  = cE + r * cos(th1 + dth * i);
         dfNorth = cN + r * sin(th1 + dth * i);
         if (dfEast != dfEast) { /* which is a wonderful property of nans */
           CPLError( CE_Warning, CPLE_AppDefined,
-                    "Calculated %lf for point %li of %i in curve %li.", dfEast, i, npt, iSerial);
+                    "Calculated %lf for point %d of %d in curve %li.", dfEast, i, npt, iSerial);
         }
         poLS->setPoint(i, dfEast, dfNorth);
     }
     papoBuiltGeometries[iSerial] = poLS;
-     
-    
 }
 
 void OGRSOSIDataSource::buildOGRPoint(long iSerial) {
@@ -718,5 +718,5 @@ int OGRSOSIDataSource::TestCapability( CPL_UNUSED const char * pszCap ) {
         return TRUE;
     }
 #endif
-	return FALSE;
+    return FALSE;
 }
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosidatatypes.cpp b/ogr/ogrsf_frmts/sosi/ogrsosidatatypes.cpp
index 04ad39d..6c1bbbc 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosidatatypes.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosidatatypes.cpp
@@ -1,6 +1,8 @@
 #include <map>
 #include "ogr_sosi.h"
 
+CPL_CVSID("$Id: ogrsosidatatypes.cpp 36347 2016-11-20 20:43:39Z rouault $");
+
 C2F oTypes;
 C2F::iterator iTypes;
 
@@ -17,7 +19,11 @@ void OGRSOSIDataType::setElement(int nIndex, const char *name, OGRFieldType type
     poElements[nIndex].setType(name, type);
 }
 
-OGRSOSISimpleDataType::OGRSOSISimpleDataType () {}
+OGRSOSISimpleDataType::OGRSOSISimpleDataType ():
+    pszName(""),
+    nType(OFTString)
+{}
+
 OGRSOSISimpleDataType::OGRSOSISimpleDataType (const char *name, OGRFieldType type) {
     setType(name, type);
 }
@@ -27,7 +33,6 @@ void OGRSOSISimpleDataType::setType (const char *name, OGRFieldType type) {
 }
 OGRSOSISimpleDataType::~OGRSOSISimpleDataType () {}
 
-
 /*** utility methods ***/
 
 static void addType(C2F* map, const char *key, OGRSOSIDataType *type) {
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosidatatypes.h b/ogr/ogrsf_frmts/sosi/ogrsosidatatypes.h
index 323c26d..bdca74d 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosidatatypes.h
+++ b/ogr/ogrsf_frmts/sosi/ogrsosidatatypes.h
@@ -1,3560 +1,3558 @@
 
       addSimpleType(&oTypes, "ADM_GRENSE", "administrativGrense", OFTString);
-    
+
       addSimpleType(&oTypes, "ADRESSE", "adresse", OFTString);
-    
+
       addSimpleType(&oTypes, "ADRESSEREFKODE", "adresseReferansekode", OFTString);
-    
+
       addSimpleType(&oTypes, "AJOURFØRTAV", "ajourførtAv", OFTString);
-    
+
       addSimpleType(&oTypes, "AJOURFØRTDATO", "ajourførtDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "AKGEOLTEMA", "annetKvTema", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AKVA_ART", "akvaArt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AKVA_ENHET", "akvaEnhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AKVA_KONSTR", "akvaKonstruksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AKVA_NR", "akvaKonsesjonsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AKVA_STATUS", "akvaKonsesjonsstatus", OFTString);
-    
+
       addSimpleType(&oTypes, "AKVA_TYPE", "akvaKonsesjonstype", OFTString);
-    
+
       addSimpleType(&oTypes, "AKVAKONSESJONSFORMÅL", "akvaKonsesjonsformål", OFTString);
-    
+
       addSimpleType(&oTypes, "AKVATEMP", "akvaTemperatur", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AKVSYMBOL", "andreKvSymbol", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ALDERBESKRIVELSE", "alderBeskrivelse", OFTString);
-    
+
       addSimpleType(&oTypes, "ALGE_KONS", "algeKonsentrasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ALGE_TYP", "algeType", OFTString);
-    
+
       addSimpleType(&oTypes, "ALM-TYP", "allmenningtype", OFTString);
-    
+
       addSimpleType(&oTypes, "ALT_AREALBYGNING", "alternativtArealBygning", OFTReal);
-    
+
       addSimpleType(&oTypes, "ALTERN_FNR", "altForekomstNr", OFTString);
-    
+
       addSimpleType(&oTypes, "ALTERNATIVTNAVN", "alternativtNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "ANBELINTYP", "annenBergartLinjetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANDREKILDERBELASTNING", "andrekilderBelastning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANKRINGSBRUK", "ankringsbruk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANKRTYP", "ankringstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANLEGGNØDSTRØM", "anleggNødstrøm", OFTString);
-    
+
       addSimpleType(&oTypes, "ANLEGGSNUMMER", "anleggsnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "ANNEN_VANNB_ELEK", "annenVannbehandlingAvhElektrisitet", OFTString);
-    
+
       addSimpleType(&oTypes, "ANNENLUFTHAVN", "annenLufthavn", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANNENMATRENHET", "annenMatrEnhet", OFTString);
-    
+
       addSimpleType(&oTypes, "ANT_ANALYS", "antallAnalyser", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANT_ANS", "antallAnsatte", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANT_ÅRSV", "antallÅrsverk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALL_BAD", "antallBad", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALL_BOENHETER", "antallBoenheter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALL_ETASJER", "antall etasjer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALL_ROM", "antallRom", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALL_RØKLØP", "antallRøkløp", OFTReal);
-    
+
       addSimpleType(&oTypes, "ANTALL_WC", "antallWC", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALLFASTBOENDE", "antallFastboende", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALLFRITIDSBOLIGER", "antallFritidsboliger", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALLIDENTISKELYS", "antallIdentiskeLys", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALLSKISPOR", "antallSkispor", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTALLSKORSTEINER", "antallSkorsteiner", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ANTDRIFT", "landbruksregAntBedrifter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ARAVGRTYPE", "arealressursAvgrensingType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ARDYRKING", "arealressursDyrkbarjord", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AREAL", "areal", OFTReal);
-    
+
       addSimpleType(&oTypes, "AREALBRUK_RESTR", "arealbrukRestriksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AREALENHET", "arealenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "AREALINNSJØ", "arealInnsjø", OFTReal);
-    
+
       addSimpleType(&oTypes, "AREALKILDE", "arealkilde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AREALMERKNAD", "arealmerknad", OFTString);
-    
+
       addSimpleType(&oTypes, "AREALNEDBØRFELT", "arealNedbørfelt", OFTString);
-    
+
       addSimpleType(&oTypes, "AREALREGINE", "arealRegine", OFTReal);
-    
+
       addSimpleType(&oTypes, "AREALST", "arealbruksstatus", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AREALVERDI_IND", "arealverdiindikator", OFTString);
-    
+
       addSimpleType(&oTypes, "ARENKEL", "arealressursGruppertEnkel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ARGRUNNF", "arealressursGrunnforhold", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ARKARTSTD", "arealressursKartstandard", OFTString);
-    
+
       addSimpleType(&oTypes, "ARNFJBRUK", "arealressursNaturgrunnlagForJordbruk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ARSKOGBON", "arealressursSkogbonitet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ART_ENGELSK", "engelskArtsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "ART_LATIN", "vitenskapeligArtsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "ART_NORSK", "norskArtsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "ART_TAKSONOMI", "taksonomiskKode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ARTRESLAG", "arealressursTreslag", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ARTYPE", "arealressursArealtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ARUTETYPE", "annenRutetype", OFTString);
-    
+
       addSimpleType(&oTypes, "ARVANLIG", "arealressursGruppertVanlig", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ARVEGET", "arealressursVegetasjonsdekke", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ASKOG", "potensiellSkogbonitet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ATIL", "arealtilstand", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AVFALLSDEP", "avfallDeponiEgnethet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AVFALLTYPE", "avfallType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AVGIFTSBELAGT", "avgiftsbelagt", OFTString);
-    
+
       addSimpleType(&oTypes, "AVGJDATO", "avgjørelsesdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "AVGRENSNINGSTYPE", "avgrensningstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AVKJ", "avkjørselsbestemmelse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AVKLARTEIERE", "avklartEiere", OFTString);
-    
+
       addSimpleType(&oTypes, "AVLØP", "avløp", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AVLØP_TILKNYTNING", "tilknyttetKommunaltAvløp", OFTString);
-    
+
       addSimpleType(&oTypes, "AVLØPINNSJØ", "avløpInnsjø", OFTReal);
-    
+
       addSimpleType(&oTypes, "AVLØPRENSEPRINSIPP", "avløpRenseprinsipp", OFTString);
-    
+
       addSimpleType(&oTypes, "AVLØPSANLEGGEIERFORM", "avløpsanleggEierform", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AVLØPSANLEGGTYPE", "avløpsanleggtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AVSETNING", "avsetningstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AVSETNRATE", "avsetnRate", OFTString);
-    
+
       addSimpleType(&oTypes, "BAKKEOPPLØSNING", "bakkeoppløsning", OFTReal);
-    
+
       addSimpleType(&oTypes, "BARMARKSLØYPETYPE", "barmarksløypeType", OFTString);
-    
+
       addSimpleType(&oTypes, "BEALDERBST", "bergartAlderBestemmelse", OFTString);
-    
+
       addSimpleType(&oTypes, "BEBYGD_AREAL", "bebygdAreal", OFTReal);
-    
+
       addSimpleType(&oTypes, "BEFARGEKO", "cmykFargekode", OFTString);
-    
+
       addSimpleType(&oTypes, "BEHSTAT", "behandlingsstatus", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BEITEBRUKERID", "reinbeitebrukerID", OFTString);
-    
+
       addSimpleType(&oTypes, "BEITETID", "beitetid", OFTString);
-    
+
       addSimpleType(&oTypes, "BEITETIDVEDTAK", "beitetidVedtak", OFTString);
-    
+
       addSimpleType(&oTypes, "BEKJSAMSET", "bergartKjemiskSammensetning", OFTString);
-    
+
       addSimpleType(&oTypes, "BEKORNSTR", "bergartKornstørrelse", OFTString);
-    
+
       addSimpleType(&oTypes, "BELIGG", "omgivelsetypeTraséseksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BELIGGENHET", "beliggenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "BELYSNING", "belysning", OFTString);
-    
+
       addSimpleType(&oTypes, "BEREGNET", "beregningsDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "BEREGNETÅR", "beregnetÅr", OFTString);
-    
+
       addSimpleType(&oTypes, "BERGFARGE", "bergartFarge", OFTString);
-    
+
       addSimpleType(&oTypes, "BERGGRENSETYPE", "berggrunnGrensetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BESK_ELEMENT", "beskrivelseElement", OFTString);
-    
+
       addSimpleType(&oTypes, "BESKRIV", "tiltaksbeskrivelse", OFTString);
-    
+
       addSimpleType(&oTypes, "BESKRIVELSE", "beskrivelse", OFTString);
-    
+
       addSimpleType(&oTypes, "BESTEMMELSEOMRNAVN", "bestemmelseOmrådeNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "BESTRUKTUR", "bergartStruktur", OFTString);
-    
+
       addSimpleType(&oTypes, "BESYMBOLTY", "bergartSymbol", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BETEKSTUR", "bergartTekstur", OFTString);
-    
+
       addSimpleType(&oTypes, "BETJENINGSGRAD", "betjeningsgrad", OFTString);
-    
+
       addSimpleType(&oTypes, "BILDE-BIT-PIXEL", "bitsPerPixel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BILDE-FIL", "bildeFil", OFTString);
-    
+
       addSimpleType(&oTypes, "PLANPÅSKRIFTTYPE", "planpåskriftype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BILDEKATEGORI", "bildekategori", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BILDEMÅLESTOKK", "bildemålestokk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BILDENUMMER", "bildenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BILDE-SYS", "bildeSystem", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BILDE-TYPE", "bildeType", OFTString);
-    
+
       addSimpleType(&oTypes, "BILDE-UNDERTYPE", "bildeUndertype", OFTString);
-    
+
       addSimpleType(&oTypes, "BISPENUMMER", "bispenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BKLASSIFIK", "berggrunnKlassifikasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BLOKK", "steinOgBlokk", OFTString);
-    
+
       addSimpleType(&oTypes, "BLOKKAREAL", "blokkareal", OFTReal);
-    
+
       addSimpleType(&oTypes, "BMANDEL", "bmAndel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BMANTALL", "bmAntall", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BMARSTID", "bmÅrstid", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BMART", "bmArt", OFTString);
-    
+
       addSimpleType(&oTypes, "BMENHET", "bmEnhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BMFUNK", "bmOmrådefunksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BMFUNKVAL", "bmFunksjonskvalitet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BMKILDTYP", "bmKildetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BMKILDVURD", "bmKildevurdering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BMNATYP", "bmNaturtype", OFTString);
-    
+
       addSimpleType(&oTypes, "BMNATYPMARIN", "bmNaturtypeMarin", OFTString);
-    
+
       addSimpleType(&oTypes, "BMNATYPMARINUTF", "bmNaturtypeMarinUtforming", OFTString);
-    
+
       addSimpleType(&oTypes, "BMNATYPUTF", "bmNaturtypeUtforming", OFTString);
-    
+
       addSimpleType(&oTypes, "BMREGDATO", "bmRegistreringsdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "BMTRUETKAT", "bmTruethetskategori", OFTString);
-    
+
       addSimpleType(&oTypes, "BMVERDI", "bmVerdi", OFTString);
-    
+
       addSimpleType(&oTypes, "BMVILTVEKT", "bmViltvekt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BNR", "bruksnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BOKST", "bokstav", OFTString);
-    
+
       addSimpleType(&oTypes, "BOLTTYPE", "boltType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BOREDAGER", "antallBoredager", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BOREDATO", "boredato", OFTDate);
-    
+
       addSimpleType(&oTypes, "BOREDYP", "boredyp", OFTReal);
-    
+
       addSimpleType(&oTypes, "BOREFIRMA", "borefirma", OFTString);
-    
+
       addSimpleType(&oTypes, "BOREINNRETN", "boreinnretningsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "BORESLUTT", "boreslutt", OFTDate);
-    
+
       addSimpleType(&oTypes, "BORESTART", "borestart", OFTDate);
-    
+
       addSimpleType(&oTypes, "BORETYPE", "boringType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BORHELNING", "gfborehHelning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BORHULLNR", "borhullNummer", OFTString);
-    
+
       addSimpleType(&oTypes, "BORLENGDE", "gfborehLengde", OFTReal);
-    
+
       addSimpleType(&oTypes, "BORRETNING", "gfborehRetning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BOT_OK_INT", "botaniskØkologiskInteresse", OFTString);
-    
+
       addSimpleType(&oTypes, "BRANSJE", "bransje", OFTString);
-    
+
       addSimpleType(&oTypes, "BREDDE", "trasébredde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BRENNVIDDE", "brennvidde", OFTReal);
-    
+
       addSimpleType(&oTypes, "BRENSELTANKNEDGR", "brenseltankNedgravd", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BRETYPE", "bretype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BRUDDLENGDE", "bruddlengde", OFTReal);
-    
+
       addSimpleType(&oTypes, "BRUEIER", "brueier", OFTString);
-    
+
       addSimpleType(&oTypes, "BRUK_GRAD", "kulturlandskapBrukGrad", OFTString);
-    
+
       addSimpleType(&oTypes, "BRUKONSTRTYPE", "brukonstruksjonstype", OFTString);
-    
+
       addSimpleType(&oTypes, "BRUKSAREAL", "bruksareal", OFTReal);
-    
+
       addSimpleType(&oTypes, "BRUKSAREALANNET", "bruksarealTilAnnet", OFTReal);
-    
+
       addSimpleType(&oTypes, "BRUKSAREALBOLIG", "bruksarealTilBolig", OFTReal);
-    
+
       addSimpleType(&oTypes, "BRUKSAREALTOTALT", "bruksarealTotalt", OFTReal);
-    
+
       addSimpleType(&oTypes, "BRUKSENHETSTYPE", "bruksenhetstype", OFTString);
-    
+
       addSimpleType(&oTypes, "BRUKSFREKVENS", "friluftsområdeBruksfrekvens", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BRUKSNAVN", "bruksnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "BRUMATERIAL", "brumaterial", OFTString);
-    
+
       addSimpleType(&oTypes, "BRUOVERBRU", "bruOverBru", OFTString);
-    
+
       addSimpleType(&oTypes, "BRUTRAFIKKTYPE", "brutrafikktype", OFTString);
-    
+
       addSimpleType(&oTypes, "BRUÅPNING", "bruåpningsmåte", OFTString);
-    
+
       addSimpleType(&oTypes, "BRØNN_REGNR", "brønnRegNr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BRØNN_RESULTAT", "brønnresultat", OFTString);
-    
+
       addSimpleType(&oTypes, "BRØNNKLASSE", "petroleumsbrønnklasse", OFTString);
-    
+
       addSimpleType(&oTypes, "BRØNNTYPE", "petroleumsbrønntype", OFTString);
-    
+
       addSimpleType(&oTypes, "BRØYTEAREALTILGANG", "brøytearealtilgang", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BRØYTEAREALTYPE", "brøytearealtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BRØYTEBREDDE", "brøytebredde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BRØYTEPRIORITET", "brøyteprioritet", OFTString);
-    
+
       addSimpleType(&oTypes, "BRØYTERESTRIKSJON", "brøyterestriksjon", OFTString);
-    
+
       addSimpleType(&oTypes, "BRØYTESIDE", "brøyteside", OFTString);
-    
+
       addSimpleType(&oTypes, "BRØYTETYPE", "brøytetype", OFTString);
-    
+
       addSimpleType(&oTypes, "BUNNTYP", "bunntype", OFTString);
-    
+
       addSimpleType(&oTypes, "BUNNTYPE", "bunntype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BYDELSNAVN", "bydelsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "BYDELSNUMMER", "bydelsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BYGGHØYDEIMETER", "bygghøydeIMeter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BYGGNR", "bygningsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BYGGSTAT", "bygningsstatus", OFTString);
-    
+
       addSimpleType(&oTypes, "BYGGTYP_NBR", "bygningstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BYGGVERK", "byggverkbestemmelse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BYGN_ENDR_KODE", "bygningsendringskode", OFTString);
-    
+
       addSimpleType(&oTypes, "BYGN_ENDR_LØPENR", "endringsløpenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BYGN_HIST_DATO", "bygningshistorikkDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "BYGN_REF_TYPE", "bygningReferansetype", OFTString);
-    
+
       addSimpleType(&oTypes, "BYGN_SAKSNR", "bygnSaksnr", OFTString);
-    
+
       addSimpleType(&oTypes, "BYGNINGSFUNKSJON", "bygningsfunksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BÆREEVNEBENEVNELSE", "bæreevnebenevnelse", OFTString);
-    
+
       addSimpleType(&oTypes, "BØYE_FORM", "bøyeform", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BÅNDLAGTFREMTIL", "båndlagtFremTil", OFTDate);
-    
+
       addSimpleType(&oTypes, "CLEIER", "CL_Eier", OFTString);
-    
+
       addSimpleType(&oTypes, "D", "dybde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DA_ANNET", "landbruksregArealAnnet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DA_JORD_D", "landbruksregArealJordIDrift", OFTReal);
-    
+
       addSimpleType(&oTypes, "DA_JORD_E", "landbruksregArealJordbruk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DA_SKOG", "landbruksregArealSkog", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DAMFORMÅL", "damFormål", OFTString);
-    
+
       addSimpleType(&oTypes, "DAMFUNKSJON", "damFunksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DAMLENGDE", "damLengde", OFTReal);
-    
+
       addSimpleType(&oTypes, "DAMTYPE", "damType", OFTString);
-    
+
       addSimpleType(&oTypes, "DATAFANGSTDATO", "datafangstdato", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "DATAUTTAKSDATO", "datauttaksdato", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "DATERMETOD", "dateringMetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DATUM", "datum", OFTString);
-    
+
       addSimpleType(&oTypes, "DEFORMASJONFASE", "deformasjonFase", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DEKKENAVN", "dekkeEnhetNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "DEKKETYPE", "dekketype", OFTString);
-    
+
       addSimpleType(&oTypes, "DEKNINGSNUMMER", "dekningsnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "DEL_BRED", "posisjonBredde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DEL_DYBD", "posisjonDybde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DELOMRÅDENAVN", "delområdenavn", OFTString);
-    
+
       addSimpleType(&oTypes, "DELOMRÅDENUMMER", "delområdenummer", OFTString);
-    
+
       addSimpleType(&oTypes, "DELSTREKNINGSNUMMER", "delstrekningsnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "DEPONISTATUS", "deponistatus", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DEPONITYPE", "deponitype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DESINFANLAVHELEK", "desinfAnleggAvhElektrisitet", OFTString);
-    
+
       addSimpleType(&oTypes, "DIGITALISERINGSMÅLESTOKK", "digitaliseringsmålestokk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DIM-BREDDE", "tekstTegnBredde", OFTReal);
-    
+
       addSimpleType(&oTypes, "DIM-HØYDE", "tekstTegnHøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "DISTKODE", "reinbeitedistriktID", OFTString);
-    
+
       addSimpleType(&oTypes, "DK_MANDEL", "dyrkningspotensialMandel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DK_MANDEL_A", "nedklassifiseringMandel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DK_NEDBOR", "nedbørsbasert", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DK_NEDBOR_A", "nedklassifiseringNedbør", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DK_VANN", "vanningsbasert", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DK_VANN_A", "nedklassifiseringVanning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DOKUMENTASJONSTYPE", "dokumentasjonType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "D-REF-INT", "vertikalReferanseInternasjonalDybde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DRIFTFHOLD", "driftForhold", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DRIFTMETOD", "driftMetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DRSENTER", "jordregisterDriftssenter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DYBDE", "dybde", OFTReal);
-    
+
       addSimpleType(&oTypes, "DYBDE_MAX", "maximumsdybde", OFTReal);
-    
+
       addSimpleType(&oTypes, "DYBDE_MIN", "minimumsdybde", OFTReal);
-    
+
       addSimpleType(&oTypes, "DYBDEFJELL", "dybdeTilFjell", OFTReal);
-    
+
       addSimpleType(&oTypes, "DYBDEKVIKKLEIRE", "dybdeTilKvikkleire", OFTReal);
-    
+
       addSimpleType(&oTypes, "DYBDEMÅLEMETODE", "dybemålemetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DYBDE-REF", "dybdeReferanse", OFTString);
-    
+
       addSimpleType(&oTypes, "DYBDETYPE", "dybdetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DYPMIDDEL", "dypMiddel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "DYPSTØRSTMÅLT", "dypStørstMålt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SERIENUMMER", "serienummer", OFTString);
-    
+
       addSimpleType(&oTypes, "DYRKING", "jordregisterDyrkingsjord", OFTString);
-    
+
       addSimpleType(&oTypes, "EIER", "geodataeier", OFTString);
-    
+
       addSimpleType(&oTypes, "EIERFORHOLD", "eierforhold", OFTString);
-    
+
       addSimpleType(&oTypes, "EIERFORM", "eierformType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "EKOORD-H", "jordregisterKoordinatHøyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "EKOORD-N", "jordregisterKoordinatNord", OFTInteger);
-    
+
       addSimpleType(&oTypes, "EKOORD-Ø", "jordregisterKoordinatØst", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ENDRET_TID", "tidspunktEndring", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "ENDRET_TYPE", "typeEndring", OFTString);
-    
+
       addSimpleType(&oTypes, "ENDRINGSGRAD", "endringsgrad", OFTString);
-    
+
       addSimpleType(&oTypes, "ENERGIKILDE", "energikilde", OFTString);
-    
+
       addSimpleType(&oTypes, "ENHET", "enhet", OFTReal);
-    
+
       addSimpleType(&oTypes, "ENHET-D", "enhetDybde", OFTReal);
-    
+
       addSimpleType(&oTypes, "ENHET-H", "enhetHøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "EROSJONGS", "erosjonsrisikoGrasdekke", OFTInteger);
-    
+
       addSimpleType(&oTypes, "EROSJONHP", "erosjonsrisikoHøstpløying", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ETABLERINGSDATO", "etableringsdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "ETABLERT", "fastmerkeEtableringsdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "ETASJENUMMER", "etasjenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ETASJEPLAN", "etasjeplan", OFTString);
-    
+
       addSimpleType(&oTypes, "ETASJETALL", "etasjetall", OFTString);
-    
+
       addSimpleType(&oTypes, "ETAT", "etat", OFTString);
-    
+
       addSimpleType(&oTypes, "F_TYPE", "fiskeType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FAGOMRÅD", "ledningsfagområde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FALLHØYDE", "fallHøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "FAO_KODE", "faoKode", OFTString);
-    
+
       addSimpleType(&oTypes, "FARTØY_ID", "fartøyIdentifikasjon", OFTString);
-    
+
       addSimpleType(&oTypes, "FASADE", "fasade", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FBNAVN", "fiskebedriftsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "FBNR", "fiskebruksnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FBNR_FYLK", "fiskebruksnummerFylke", OFTString);
-    
+
       addSimpleType(&oTypes, "FELTNAVN", "feltbetegnelse", OFTString);
-    
+
       addSimpleType(&oTypes, "FELTREGISTRERTAV", "feltegistrertAv", OFTString);
-    
+
       addSimpleType(&oTypes, "FIGF_ID", "figurFørSkifteIdent", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FILM", "film", OFTString);
-    
+
       addSimpleType(&oTypes, "FIRMA", "firmanavn", OFTString);
-    
+
       addSimpleType(&oTypes, "FISK_KODE", "artskode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKE_BEDR_ANDEL", "fiskebedriftsandel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKE_BEDR_EIER", "fiskebedriftseier", OFTString);
-    
+
       addSimpleType(&oTypes, "FISKE_BEDR_OMR", "fiskebedriftsområde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKE_BEDR_PROD", "fiskebedriftsprodukt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKE_BEDR_SERVICE", "fiskebedriftservice", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKE_KAP_ENH", "fiskekapasitetEnhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKE_KAPASITET", "fiskekapasitet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKE_TYPE", "fisketype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKERI_BRUK_TYPE", "fiskeribrukstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKERI_RESS_TYPE", "fiskeriressursOmrådetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKERIREDSKAP_GEN_AKTIV", "fiskeriredskapGenAktiv", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKERIREDSKAP_GEN_PASSIV", "fiskeriredskapGenPassiv", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKERIREDSKAP_SPES_AKTIV", "fiskeriredskapSpesAktiv", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FISKERIREDSKAP_SPES_PASSIV", "fiskeriredskapSpesPassiv", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FJELL", "fjellblotninger", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FJORDID", "fjordidentifikasjon", OFTString);
-    
+
       addSimpleType(&oTypes, "FLODBOLGEHOYDE", "flodbolgehoyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FLOMLAVPUNKT", "flomLavPunkt", OFTReal);
-    
+
       addSimpleType(&oTypes, "FLYFIRMA", "flyfirma", OFTString);
-    
+
       addSimpleType(&oTypes, "FLYHØYDE", "flyhøyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FLYRESTR", "flyRestriksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FMADKOMST", "fastmerkeAdkomst", OFTString);
-    
+
       addSimpleType(&oTypes, "FMDIM", "fastmerkeDiameter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FMHREF", "fastmerkeHøyderef", OFTString);
-    
+
       addSimpleType(&oTypes, "FMIDDATO", "fastmerkeIdDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "FMIDGML", "fastmerkeIdGammel", OFTString);
-    
+
       addSimpleType(&oTypes, "FMINST", "fastmerkeInstitusjon", OFTString);
-    
+
       addSimpleType(&oTypes, "FMKOMM", "fastmerkeKommune", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FMMERK", "fastmerkeMerknader", OFTString);
-    
+
       addSimpleType(&oTypes, "FMNAVN", "fastmerkeNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "FMNUMMER", "fastmerkeNummer", OFTString);
-    
+
       addSimpleType(&oTypes, "FMREFBER", "fastmerkeRefGrunnrisBeregning", OFTString);
-    
+
       addSimpleType(&oTypes, "FMREFHBER", "fastmerkeRefHøydeBeregning", OFTString);
-    
+
       addSimpleType(&oTypes, "FMRESTR", "fastmerkeRestriksjon", OFTString);
-    
+
       addSimpleType(&oTypes, "FMSREF", "fastmerkeSentrumRef", OFTString);
-    
+
       addSimpleType(&oTypes, "FNR", "festenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FONTENE_TYPE", "fontenetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FOREKNAVN", "navnRastoffobj", OFTString);
-    
+
       addSimpleType(&oTypes, "FOREKOM_ID", "identRastoffobj", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FORHOLDANDREHUS", "forholdAndreHus", OFTString);
-    
+
       addSimpleType(&oTypes, "FORHÅNDSTALL", "forhåndstall", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FORLENGET_DATO", "forlengetDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "FORMASJON", "formasjonTotalDyp", OFTString);
-    
+
       addSimpleType(&oTypes, "FORMELFLATE", "kvFormFlatetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FORMELLIN", "kvFormLinjetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FORMELPKT", "kvFormPunkttype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FORMÅLSEKSJON", "formålSeksjonKode", OFTString);
-    
+
       addSimpleType(&oTypes, "FORUR_AREAL", "forurensetAreal", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FORUR_GRUNNTYPE", "forurensetGrunnType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FORUR_HOVEDGRUPPE", "forurensningHovedgruppe", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FORV_MYND", "forvaltningMyndighet", OFTString);
-    
+
       addSimpleType(&oTypes, "FORV_PLAN", "forvaltningPlan", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FOSSILTYPE", "fossilNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "FOTODATO", "fotodato", OFTDate);
-    
+
       addSimpleType(&oTypes, "FOTOGRAF", "fotograf", OFTString);
-    
+
       addSimpleType(&oTypes, "FOTRUTETYPE", "fotrutetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FRASPORNODEKILOMETER", "fraSpornodeKilometer", OFTReal);
-    
+
       addSimpleType(&oTypes, "FRASPORNODETEKST", "fraSpornodeTekst", OFTString);
-    
+
       addSimpleType(&oTypes, "FRASPORNODETYPE", "fraSpornodeType", OFTString);
-    
+
       addSimpleType(&oTypes, "F-REF-INT", "friseilingReferanseInternasjonal", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FREG", "jordregisterFreg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FRIDRIFTSTILSYN", "friluftslivsområdeDriftstilsyn", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FRIEGNETHET", "friluftslivsområdeEgnethet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FRIPLANST", "friluftslivsområdePlanStatus", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FRISEILHØYDE", "friseilingshøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "FRISEIL-REF", "frilseilingReferanse", OFTString);
-    
+
       addSimpleType(&oTypes, "FRISIKRING", "friluftslivSikring", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FRISPERR", "frisperring", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FRISTMATRIKKELFØRINGSKRAV", "fristMatrikkelføringskrav", OFTDate);
-    
+
       addSimpleType(&oTypes, "FRISTOPPMÅLING", "fristOppmåling", OFTDate);
-    
+
       addSimpleType(&oTypes, "FRITILRETTELEGGING", "friluftslivsområdeTilrettelegging", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FRITYPE", "friluftslivsområdeType", OFTString);
-    
+
       addSimpleType(&oTypes, "FRIVERDI", "friluftslivsområdeVerdi", OFTString);
-    
+
       addSimpleType(&oTypes, "F-STRENG", "formatertStreng", OFTString);
-    
+
       addSimpleType(&oTypes, "FUNDAMENTERING", "fundamentering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FYDELTEMA", "fylkesdeltema", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FYLKESNR", "fylkesnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FYRLISTEKARAKTER", "fyrlisteKarakter", OFTString);
-    
+
       addSimpleType(&oTypes, "FYRLISTENUMMER", "fyrlistenummer", OFTString);
-    
+
       addSimpleType(&oTypes, "FYSENHET", "fysiskEnhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FYSISKMILJØ", "fysiskMiljø", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FYSPARAM", "fysiskParameter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FYSSTR", "fysiskStorrelse", OFTReal);
-    
+
       addSimpleType(&oTypes, "FØLGER_TERRENGDET", "følgerTerrengdetalj", OFTString);
-    
+
       addSimpleType(&oTypes, "FØRSTEDATAFANGSTDATO", "førsteDatafangstdato", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "FØRSTEDIGITALISERINGSDATO", "førsteDigitaliseringsdato", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "GARDIDNR", "landbruksregProdusentId", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GATENAVN", "gatenavn", OFTString);
-    
+
       addSimpleType(&oTypes, "GATENR", "gatenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GENRESTR", "generellrestriksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOALDER", "geolAlder", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOALDER_FRA", "geolMaksAlder", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOALDER_TIL", "geolMinAlder", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOBESK", "geolBeskrivelse", OFTString);
-    
+
       addSimpleType(&oTypes, "GEO-DATUM", "geoDatumInternasjonal", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOFELTNR", "geologFeltnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "GEOFORMASJ", "geolFormasjonNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "GEOGRUPPE", "geolGruppeNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "GEOHOVERDI", "geolHorisontalverdi", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOKARTNR", "geolKartnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOKOORD", "geoKoordinatverdiEnhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOLOKNR", "geolLokalitetnummer", OFTReal);
-    
+
       addSimpleType(&oTypes, "GEO-PROJ", "geoProjeksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOPÅVISNINGTYPE", "geolPavisningtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOSITENO", "geositeNummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEO-SONE", "geoSoneProjeksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOVERDIVURD", "geolVerdivurdering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GEOVEVERDI", "geolVertikalverdi", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFANOMALI", "geofAnomali", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFDYPSTR", "geofDyp", OFTReal);
-    
+
       addSimpleType(&oTypes, "GFDYPTYPE", "geofDyptype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFFALLBREGMET", "geofFallBeregnMetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFFALLSTR", "geofFallstorrelse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFFLATE", "geofFlate", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFL_INFO", "geofLinjeInfo", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFLINJE", "geofTolkLinjetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFMETODE", "geofMetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFP_INFO", "geofPunktInfo", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFSTROK", "geofStrokretning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFTOLK", "geofTolkMetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFUTLLEN", "geofLengdeUtlegg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFUTLRETN", "geofRetningUtlegg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GFUTLTYPE", "geofTypeUtlegg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GJENNOMFØRINGSFRIST", "gjennomføringsfrist", OFTDate);
-    
+
       addSimpleType(&oTypes, "GJENTAKSINTERVAL", "gjentaksInterval", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GJERDETYPE", "sikringGjerdetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GKEKSTRAKT", "geokEkstrakt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GKENHET", "geokEnhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GKFRADYP", "geokFraDyp", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GKFRAKSJON", "geokFraksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GKHORISONT", "geokHorisont", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GKHOVMEDIUM", "geokHovedmedium", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GKMEDIUM", "geokMedium", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GKRETSNAVN", "grunnkretsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "GKTILDYP", "geokTilDyp", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GKVARIABEL", "geokVariabel", OFTString);
-    
+
       addSimpleType(&oTypes, "GNR", "gårdsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GR_TYPE", "grensetypeSjø", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRAVERT", "gravertTekst", OFTString);
-    
+
       addSimpleType(&oTypes, "GRDANNELSE", "grotteDannelse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRDIMSJOND", "grotteDimDiameter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRDIMSJONH", "grotteDimHoyre", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRDIMSJONO", "grotteDimOver", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRDIMSJONU", "grotteDimUnder", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRDIMSJONV", "grotteDimVenstre", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRENSEMERKENEDSATTI", "grensemerkeNedsasttI", OFTString);
-    
+
       addSimpleType(&oTypes, "GRENSEPUNKTNUMMER", "grensepunktnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "GRENSEPUNKTTYPE", "grensepunkttype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRENSEVEDTAK", "grenseVedtak", OFTString);
-    
+
       addSimpleType(&oTypes, "GRFORMELM", "grotteFormElement", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRGANGFORM", "grotteGaForm", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRGANGTYPE", "grotteGaType", OFTString);
-    
+
       addSimpleType(&oTypes, "GRHOYDE", "grotteHoyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRLINTYPE", "grotteLinjetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GROTLEGEME", "grotteLegeme", OFTString);
-    
+
       addSimpleType(&oTypes, "GROTNOYAKT", "grotteNoyaktighet", OFTString);
-    
+
       addSimpleType(&oTypes, "GROTTELAST", "grotteLast", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GROTTENAVN", "grotteNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "GROTTEPLAN", "grottePlan", OFTString);
-    
+
       addSimpleType(&oTypes, "GROTTLENKE", "grotteLenke", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRPKTTYPE", "grottePktType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRPUNKTNR", "grottePktNummer", OFTString);
-    
+
       addSimpleType(&oTypes, "GRUNNBORINGREF", "grunnBoringReferanse", OFTString);
-    
+
       addSimpleType(&oTypes, "GRUNNFHOLD", "losmGrunnforhold", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRUNNGASS", "grunnGass", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRUNNKRETS", "grunnkretsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRUNNLINJENAVN", "grunnlinjepunktnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "GRUNNLINJENUMMER", "grunnlinjepunktnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "GRUNNRISSREFERANSESPOR", "grunnrissreferanseSpor", OFTString);
-    
+
       addSimpleType(&oTypes, "GRUNNVANN", "grunnvannPotensiale", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GRUNNVERDI", "grunnVerdi", OFTReal);
-    
+
       addSimpleType(&oTypes, "GRVARSEL", "grotteVarsel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GVAKT_PROS", "geoVernAktivProsess", OFTString);
-    
+
       addSimpleType(&oTypes, "GVAREAL", "geoVernAreal", OFTString);
-    
+
       addSimpleType(&oTypes, "GVDLIKEHOLD", "geoVernVedlikehold", OFTString);
-    
+
       addSimpleType(&oTypes, "GVERNE_ID", "geoVernObjektId", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GVERNETYPE", "geoVernTematype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GVERNHTYPE", "geoVernHovedtype", OFTString);
-    
+
       addSimpleType(&oTypes, "GVERNKRT_A", "geoVernAKriterie", OFTString);
-    
+
       addSimpleType(&oTypes, "GVERNKRT_B", "geoVernBKriterie", OFTString);
-    
+
       addSimpleType(&oTypes, "GVERNKRT_C", "geoVernCKriterie", OFTString);
-    
+
       addSimpleType(&oTypes, "GVERNVERDI", "geoVernVerdi", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GVGRENSETY", "geoVernGrensetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GVHINNHLD", "geoVernHovInnhold", OFTString);
-    
+
       addSimpleType(&oTypes, "GVINNGREP", "geoVernInngrep", OFTString);
-    
+
       addSimpleType(&oTypes, "GVLITTRTUR", "geoVernLitteratur", OFTString);
-    
+
       addSimpleType(&oTypes, "GVOFFNTLGJ", "geoVernOffentliggjoring", OFTString);
-    
+
       addSimpleType(&oTypes, "GVOMR_NAVN", "geoVernOmrNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "GVPROALDER", "geoVernProsessalder", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GVSAKSTATUS", "geoVernSakStatus", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GVSTATUS", "geoVernType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "GVSYSTEM", "geoVernSystem", OFTString);
-    
+
       addSimpleType(&oTypes, "GVTINNHLD", "geoVernTilleggInnhold", OFTString);
-    
+
       addSimpleType(&oTypes, "GVVKT_PROS", "geoVernViktigProsess", OFTString);
-    
+
       addSimpleType(&oTypes, "GYLDIGFRA", "gyldigFra", OFTDate);
-    
+
       addSimpleType(&oTypes, "GYLDIGTIL", "gyldigTil", OFTDate);
-    
+
       addSimpleType(&oTypes, "H", "høyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "H_EUREF89", "høydeOverEuref89", OFTReal);
-    
+
       addSimpleType(&oTypes, "H_KAT_LANDSK", "hovedkategoriLandskap", OFTString);
-    
+
       addSimpleType(&oTypes, "HAR_HEIS", "harHeis", OFTString);
-    
+
       addSimpleType(&oTypes, "HASTIGHETSENHET", "hastighetsenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "HAVNE_D_ADM", "havnedistriktadministrasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HAVNE_ID", "havneidentifikasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HAVNEAVSNITTNUMMER", "havneavsnittnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HAVNEAVSNITTSTATUS", "havneavsnittstatus", OFTString);
-    
+
       addSimpleType(&oTypes, "HAVNEAVSNITTTYPE", "havneavsnitttype", OFTString);
-    
+
       addSimpleType(&oTypes, "HAVNETERMINALISPSNUMMER", "havneterminalISPSnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HAVNETERMINALNUMMER", "havneterminalnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HAVNETERMINALSTATUS", "havneterminalstatus", OFTString);
-    
+
       addSimpleType(&oTypes, "HAVNETERMINALTYPE", "havneterminaltype", OFTString);
-    
+
       addSimpleType(&oTypes, "HBERGKODE", "hovedBergKode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HELLING", "helling", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HENDELSE", "trasénodeHendelsestype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HENSYNSONENAVN", "hensynSonenavn", OFTString);
-    
+
       addSimpleType(&oTypes, "HFLOM", "vannstandRegHøyestRegistrerte", OFTReal);
-    
+
       addSimpleType(&oTypes, "HINDERFLATE_TYPE", "hinderFlateType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HINDERFLATEPENETRERINGSTYPE", "hinderflatepenetreringstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HJELPELINJETYPE", "hjelpelinjetype", OFTString);
-    
+
       addSimpleType(&oTypes, "HJEMMELSGRUNNLAG", "hjemmelsgrunnlag", OFTString);
-    
+
       addSimpleType(&oTypes, "HJULTRYKK", "hjultrykk", OFTString);
-    
+
       addSimpleType(&oTypes, "H-MÅLEMETODE", "målemetodeHøyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "H-NØYAKTIGHET", "nøyaktighetHøyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HOB", "høydeOverBakken", OFTReal);
-    
+
       addSimpleType(&oTypes, "HOLDNINGSKLASSE", "holdningsklasse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HOR_BÆREKONSTR", "horisontalBærekonstr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HOVEDPARSELL", "hovedParsell", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HOVEDTEIG", "hovedteig", OFTString);
-    
+
       addSimpleType(&oTypes, "HREF", "høydereferanse", OFTString);
-    
+
       addSimpleType(&oTypes, "H-REF-INT", "høydeReferanseInternasjonal", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HRV", "vannstandHøyesteRegulert", OFTReal);
-    
+
       addSimpleType(&oTypes, "HUSHOLDBELASTNING", "husholdBelastning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HUSLØPENR", "husLøpenr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HUSNR", "husNr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HVANN", "vannstandHøyestRegistrert", OFTReal);
-    
+
       addSimpleType(&oTypes, "HYTTE_ID", "hytteId", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HYTTEEIER", "hytteeier", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HØYDE", "høyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "HØYDE_TIL_NAV", "høydeTilNavet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "HØYDE-REF", "høyde-Referanse", OFTString);
-    
+
       addSimpleType(&oTypes, "HØYDEREFERANSESPOR", "høydereferanseSpor", OFTString);
-    
+
       addSimpleType(&oTypes, "HØYDE-TYPE", "høydeType", OFTString);
-    
+
       addSimpleType(&oTypes, "ID", "identifikasjon", OFTString);
-    
+
       addSimpleType(&oTypes, "IKRAFT", "ikrafttredelsesdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "IMOTOPPMERKETYPE", "imoToppmerketype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "IMP", "impedimentprosentSkog", OFTInteger);
-    
+
       addSimpleType(&oTypes, "INDEKSMIN", "indeksMineral", OFTString);
-    
+
       addSimpleType(&oTypes, "INDIKATOR", "indikatorFastmerkenummer", OFTString);
-    
+
       addSimpleType(&oTypes, "INDUSTRIBELASTNING", "industriBelastning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "INFILT", "infiltrasjonEvne", OFTInteger);
-    
+
       addSimpleType(&oTypes, "INFORMASJON", "informasjon", OFTString);
-    
+
       addSimpleType(&oTypes, "FAGOMRÅDEGRUPPE", "fagområdegruppe", OFTString);
-    
+
       addSimpleType(&oTypes, "FAGOMRÅDE_FULLT_NAVN", "fagområdets fulle navn", OFTString);
-    
+
       addSimpleType(&oTypes, "INON_AVS", "inngrepsfriSoneAvstand", OFTReal);
-    
+
       addSimpleType(&oTypes, "INONSONE", "inngrepsfrieNaturområderINorgeSone", OFTString);
-    
+
       addSimpleType(&oTypes, "INRT_FUNKSJON", "innretningsfunksjon", OFTString);
-    
+
       addSimpleType(&oTypes, "INRT_HOVEDTYPE", "innretningshovedtype", OFTString);
-    
+
       addSimpleType(&oTypes, "INRT_MATR", "innretningsmaterialtype", OFTString);
-    
+
       addSimpleType(&oTypes, "INRT_NAVN", "innretningsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "INRT_TYPE", "innretningstype", OFTString);
-    
+
       addSimpleType(&oTypes, "INST_EFFEKT", "installertEffekt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "INSTALLASJONSBØYEKATEGORI", "installasjonsbøyekategori", OFTInteger);
-    
+
       addSimpleType(&oTypes, "INSTALLERT_ÅR", "installertÅr", OFTDate);
-    
+
       addSimpleType(&oTypes, "INT_STAT", "internasjonalStatus", OFTInteger);
-    
+
       addSimpleType(&oTypes, "J_LREG", "jordregisterLreg", OFTString);
-    
+
       addSimpleType(&oTypes, "JERNBANEEIER", "jernbaneeier", OFTString);
-    
+
       addSimpleType(&oTypes, "JERNBANETYPE", "jernbanetype", OFTString);
-    
+
       addSimpleType(&oTypes, "JORD", "jordklassifikasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "JORDARB", "anbefaltJordarbeiding", OFTInteger);
-    
+
       addSimpleType(&oTypes, "JORDART", "losmassetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "JREGAREAL", "jordregisterAreal", OFTReal);
-    
+
       addSimpleType(&oTypes, "JREGEKODE", "jordregisterStatusEiendom", OFTInteger);
-    
+
       addSimpleType(&oTypes, "JRFIGNR", "jordregisterFigurnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "JSR_AREAL", "jordskifteArealtilstand", OFTInteger);
-    
+
       addSimpleType(&oTypes, "JSVSAK", "jordskifterettenSaksnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "JXAREAL", "annetareal", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KABELTYPE", "kabeltype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KAI_DYBDE", "kaiDybde", OFTReal);
-    
+
       addSimpleType(&oTypes, "KAI_TYPE", "kaiTypeInformasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KALIBRERINGSRAPPORT", "kalibreringsrapport", OFTString);
-    
+
       addSimpleType(&oTypes, "KAMERATYPE", "kameratype", OFTString);
-    
+
       addSimpleType(&oTypes, "KAPASITETLANGEKJØRETØY", "kapasitetLangekjøretøy", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KAPASITETPERSONBILER", "kapasitetPersonbiler", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KAPASITETPERSONEKVIVALENTER", "kapasitetPersonekvivalenter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KARDINALMERKETYPE", "kardinalmerketype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KARTID", "kartbladindeks", OFTString);
-    
+
       addSimpleType(&oTypes, "KARTLEGGINGSETAPPE", "kartleggingsetappe", OFTString);
-    
+
       addSimpleType(&oTypes, "KARTREG", "kartregistrering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KARTSIGNATUR", "kartsignatur", OFTString);
-    
+
       addSimpleType(&oTypes, "KARTTYPE", "karttype", OFTString);
-    
+
       addSimpleType(&oTypes, "KBISPENR", "bispedømmenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KILDEPRIVATVANNF", "kildePrivatVannforsyning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KJELLER", "kjeller", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KJERNEOMRÅDESTATUS", "kjerneområdestatus", OFTString);
-    
+
       addSimpleType(&oTypes, "KJØKKENTILGANG", "kjøkkentilgang", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KLASSIFISERING", "kulturlandskapKlassifisering", OFTString);
-    
+
       addSimpleType(&oTypes, "KLOR_FØR_FORBRUK", "klorKontakttidFørForbruk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KLORO_MAKS", "klorofyllMaksimum", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KLOTPAR", "klotoideParameter", OFTReal);
-    
+
       addSimpleType(&oTypes, "KLOTRAD1", "klotoideRadius 1", OFTReal);
-    
+
       addSimpleType(&oTypes, "KLOTRAD2", "klotoideRadius 2", OFTReal);
-    
+
       addSimpleType(&oTypes, "RUTEVANSKELIGHETSGRAD", "rutevanskelighetsgrad", OFTString);
-    
+
       addSimpleType(&oTypes, "RWY_BÆREEVNE_BEN", "bæreevnebenevnelse", OFTString);
-    
+
       addSimpleType(&oTypes, "RWY_TYPE", "rullebaneType", OFTString);
-    
+
       addSimpleType(&oTypes, "RWYMERK", "rullebaneoppmerking", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RYDDEBREDDE", "ryddebredde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RØR_ENDE_PKT", "ledningsendepunkt", OFTString);
-    
+
       addSimpleType(&oTypes, "RØR_START_PKT", "ledningsstartpunkt", OFTString);
-    
+
       addSimpleType(&oTypes, "RØRLEDNINGSTYPE", "rørledningstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SAK_AVSLUTT", "sakAvsluttet", OFTString);
-    
+
       addSimpleType(&oTypes, "SAKSNR", "saksnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SAKSOMF", "saksomfang", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SAKSTYPE", "sakstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SALINITET", "salinitet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SAT_KOM_ID", "satellittkommunikasjonsId", OFTString);
-    
+
       addSimpleType(&oTypes, "SCANNEROPPLØSNING", "scanneroppløsning", OFTReal);
-    
+
       addSimpleType(&oTypes, "SEDDYBDEME", "sedDybdeMeter", OFTReal);
-    
+
       addSimpleType(&oTypes, "SEDDYBDEMS", "sedDybdeMillisekund", OFTReal);
-    
+
       addSimpleType(&oTypes, "SEDKORNSTR", "sedKornstorrelse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SEDMEKTME", "sedMektighetMeter", OFTReal);
-    
+
       addSimpleType(&oTypes, "SEDMEKTMS", "sedMektighetMillisekund", OFTReal);
-    
+
       addSimpleType(&oTypes, "SEFRAK_FUNK_KODE", "sefrakFunksjonsKode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SEFRAK_FUNK_STAT", "sefrakFunksjonsstatus", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_ANTALL", "kulturminneAntall", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KM_BETEGN", "kulturminneBetegnelse", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_DAT", "kulturminneDatering", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_DATKVAL", "kulturminneDateringKvalitet", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_FUNK_NÅ", "kulturminneNåværendeFunksjon", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_FUNK_OP", "kulturminneOpprinneligFunksjon", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_HOVEDGRUPPE", "kulturminneHovedgruppe", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_KATEGORI", "kulturminneKategori", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_MAT", "kulturminneHovedMateriale", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_SYNLIG", "kulturminneSynlig", OFTString);
-    
+
       addSimpleType(&oTypes, "KM_VERNEVERDI", "kulturminneVerneverdi", OFTString);
-    
+
       addSimpleType(&oTypes, "KODDRIFT", "landbruksregBedriftskode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KOM_KALLSIGNAL", "komKallSignal", OFTString);
-    
+
       addSimpleType(&oTypes, "KOM_KANAL", "komKanal", OFTString);
-    
+
       addSimpleType(&oTypes, "KOMM", "kommunenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KOMM_ALT_AREAL", "kommAlternativtAreal", OFTReal);
-    
+
       addSimpleType(&oTypes, "KOMM_ALT_AREAL2", "kommAlternativtAreal2", OFTReal);
-    
+
       addSimpleType(&oTypes, "KOMMENTAR", "kommentar", OFTString);
-    
+
       addSimpleType(&oTypes, "KOMMENTAR_TYPE", "kommentarType", OFTString);
-    
+
       addSimpleType(&oTypes, "KOMMSEK", "kommuneSekundær", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KOMPONENT", "komponent", OFTString);
-    
+
       addSimpleType(&oTypes, "KONSTA1", "konstantA1", OFTReal);
-    
+
       addSimpleType(&oTypes, "KONSTA2", "konstantA2", OFTReal);
-    
+
       addSimpleType(&oTypes, "KONSTB1", "konstantB1", OFTReal);
-    
+
       addSimpleType(&oTypes, "KONSTB2", "konstantB2", OFTReal);
-    
+
       addSimpleType(&oTypes, "KONSTC1", "konstantC1", OFTReal);
-    
+
       addSimpleType(&oTypes, "KONSTC2", "konstantC2", OFTReal);
-    
+
       addSimpleType(&oTypes, "KONTAKTPERSON", "kontaktperson", OFTString);
-    
+
       addSimpleType(&oTypes, "KOORDKVALKODE", "koordinatkvalitetKode", OFTString);
-    
+
       addSimpleType(&oTypes, "KOPIDATO", "kopidato", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "KOPL_BRU", "koplingBruksområde", OFTString);
-    
+
       addSimpleType(&oTypes, "KOPL_KAT", "koplingskategori", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KOPL_NAV", "koplingsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "KOPL_TYP", "koplingstype", OFTString);
-    
+
       addSimpleType(&oTypes, "KORTNAVN", "kortnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "KOSTHOLDART", "kostholdArt", OFTString);
-    
+
       addSimpleType(&oTypes, "KOSTHOLDSRÅDTYPE", "kostholdsrådType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KP", "knutePunkt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPANGITTHENSYN", "angittHensyn", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPAREALFORMÅL", "arealformål", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPBÅNDLEGGING", "båndlegging", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPDETALJERING", "detaljering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPFARE", "fare", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPGJENNOMFØRING", "gjennomføring", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPINFRASTRUKTUR", "infrastruktur", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPINFRASTRUKTURLINJE", "infrastrukturLinje", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPJURLINJE", "juridisklinje", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPRESTENAVN", "prestegjeldnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "KPRESTENR", "prestegjeldnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPROSTINAVN", "prostinavn", OFTString);
-    
+
       addSimpleType(&oTypes, "KPROSTINR", "prostinummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPSIKRING", "sikring", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KPSTØY", "støy", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KRAFTVERKTYP", "kraftverktype", OFTString);
-    
+
       addSimpleType(&oTypes, "KRETSNAVN", "kretsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "KRETSNUMMER", "kretsnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "KRETSTYPEKODE", "kretstypekode", OFTString);
-    
+
       addSimpleType(&oTypes, "KRETSTYPENAVN", "kretstypenavn", OFTString);
-    
+
       addSimpleType(&oTypes, "KULT_HIST_INT", "kulturhistoriskInteresse", OFTString);
-    
+
       addSimpleType(&oTypes, "KVIKKLEIRESVURD", "stabilitetVurderingKvikkleire", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KYSTKONSTRUKSJONSTYPE", "kystkonstruksjonstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KYSTREF", "kystreferanse", OFTString);
-    
+
       addSimpleType(&oTypes, "KYSTTYP", "kysttype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KYSTVERKSDISTRIKT", "kystverksdistrikt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LAGRET_DATO", "lagretDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "LAND1", "førsteLand", OFTString);
-    
+
       addSimpleType(&oTypes, "LAND2", "annetLand", OFTString);
-    
+
       addSimpleType(&oTypes, "LANDEMERKEKATEGORI", "landeberkekategori", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LANDKODE", "landkode", OFTString);
-    
+
       addSimpleType(&oTypes, "LATERALMERKETYPE", "lateralmerketype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LDEL", "landsdelområde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LEDN_BRU", "ledningbruksområde", OFTString);
-    
+
       addSimpleType(&oTypes, "LEDN_NAV", "ledningsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "LEDN_TYP", "ledningstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LEDNINGSEIER", "ledningseier", OFTString);
-    
+
       addSimpleType(&oTypes, "LEKEREKRTYPE", "lekeRekreasjonstype", OFTString);
-    
+
       addSimpleType(&oTypes, "LENGDE", "lengde", OFTReal);
-    
+
       addSimpleType(&oTypes, "LENGDEENHET", "lengdeenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "LENGDEOVERLAPP", "lengdeoverlapp", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LENGDESEKTORLINJE1", "lengdeSektorlinje1", OFTReal);
-    
+
       addSimpleType(&oTypes, "LENGDESEKTORLINJE2", "lengdeSektorlinje2", OFTReal);
-    
+
       addSimpleType(&oTypes, "LETE_AREAL", "leteareal", OFTReal);
-    
+
       addSimpleType(&oTypes, "LH_BEREDSKAP", "lufthavnBeredskapskode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHAREAL", "lufthavnArealer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHDISTTYPE", "lufthavndistansetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHELEV", "lufthavnelevasjon", OFTReal);
-    
+
       addSimpleType(&oTypes, "LHFDET", "lufthavnForsvarsObjektDetalj", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHFM_TYPE", "lufthavnFastmerketype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHINST_TYPE", "lufthavnInstrumenteringType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHLYS_OPPHØYD_NEDFELT", "lufthavnLysOpphøydNedfelt", OFTString);
-    
+
       addSimpleType(&oTypes, "LHLYSFARGE", "lufthavnlysFarge", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHLYSRETN", "lufhavnLysretning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHLYSTYPE", "lufthavnlystype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHSKILTKATEGORI", "lufthavnskiltkatagori", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LHSKILTLYS", "lufthavnskiltlys", OFTString);
-    
+
       addSimpleType(&oTypes, "LHSKILTTYPE", "lufthavnskilttype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LINEAMENTTYPE", "lineamentType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LINK", "link", OFTString);
-    
+
       addSimpleType(&oTypes, "LJORDKL", "lokalJordressurs", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LJORDKL_A", "nedklassifiseringLokalJordressurs", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LOK_NAVN", "lokalitetsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "LOK_NR", "lokalitetsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LOSLIGHET", "loslighetGrad", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LOSMKORNSTR", "losmKornstorrelse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LOSMOVERFLATETYPE", "losmOverflateType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LOVDISP", "dispensasjonType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LOVREFBESKRIVELSE", "lovreferanseBeskrivelse", OFTString);
-    
+
       addSimpleType(&oTypes, "LOVREFERANSE", "lovreferanseType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LR_AKTIV", "landbruksregAktiv", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LR_TYPE", "landbruksregType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "LRV", "vannstandLavestRegulert", OFTReal);
-    
+
       addSimpleType(&oTypes, "LUFTHAVNHINDERTREGRUPPE", "lufthavnhinderTregruppe", OFTString);
-    
+
       addSimpleType(&oTypes, "LVANN", "vannstandLavestRegistrert", OFTReal);
-    
+
       addSimpleType(&oTypes, "LYSHØYDE", "lyshøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "LØPENR", "bruksenhetLøpenr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MAGASINNR", "magasinNr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MAKSHØYDE", "makshøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "MAKSIMALREKKEVIDDE", "maksimalRekkevidde", OFTReal);
-    
+
       addSimpleType(&oTypes, "MAKSSNØHØYDE", "maksSnøhøyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MANGELMATRIKKELFØRINGSKRAV", "mangelMatrikkelføringskrav", OFTString);
-    
+
       addSimpleType(&oTypes, "MARKID", "jordregisterMarkslagKobling", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MARKSLAGAVGRTYPE", "markslagAvgrensingType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MASSEENHET", "masseenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "MATERIALE", "materialeBolt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MATERIALE_YTTERV", "materialeYttervegg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MATR_KODE", "materiellkode", OFTString);
-    
+
       addSimpleType(&oTypes, "MATRIKKELKOMMUNE", "matrikkelkommune", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MATRTYPE", "materialType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MATRUNTYPE", "materialUndertype", OFTString);
-    
+
       addSimpleType(&oTypes, "MAX_ELEMENT_PKT", "maksAntallPunktGeometritype1", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MAX_OBJEKT_PKT", "maksAntallPunktGeometritype2", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MAX_REF_OBJEKT", "maksAntallGeometriReferanse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MAX-AVVIK", "maksimaltAvvik", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MAX-N", "maksimumNord", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MAX-Ø", "maksimumØst", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MEDIUM", "medium", OFTString);
-    
+
       addSimpleType(&oTypes, "MEKT50", "mektighetFemtiProsent", OFTReal);
-    
+
       addSimpleType(&oTypes, "MERKEFORM", "merkeform", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MERKELISTENUMMER", "merkelistenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MERKEMØNSTER", "merkemønster", OFTInteger);
-    
+
       addSimpleType(&oTypes, "METADATALINK", "metadatalink", OFTString);
-    
+
       addSimpleType(&oTypes, "METALINTYP", "metamorfLinjetype", OFTString);
-    
+
       addSimpleType(&oTypes, "METAMOGRAD", "metamorfGrad", OFTInteger);
-    
+
       addSimpleType(&oTypes, "METER-FRA", "veglenkeMeterFra", OFTInteger);
-    
+
       addSimpleType(&oTypes, "METER-TIL", "veglenkeMeterTil", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MGENHETBESKRIV", "mgEnhetBeskrivelse", OFTString);
-    
+
       addSimpleType(&oTypes, "MGENHETOPPLOSN", "mgEnhetOpplosning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MGINSTRUMENT", "mgInstrument", OFTString);
-    
+
       addSimpleType(&oTypes, "MGLINJENR", "mgLinjenummer", OFTString);
-    
+
       addSimpleType(&oTypes, "MGPOSNR", "mgPosisjonnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MGTOKTNR", "mgToktnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "MILITÆRØVELSETYPE", "militærøvelsetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MILJOTIL", "miljøtiltak", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MINHØYDE", "minhøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "MIN-N", "minimumNord", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MIN-Ø", "minimumØst", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MYNDIGHET", "vedtaksmyndighet", OFTString);
-    
+
       addSimpleType(&oTypes, "MYR", "myrklassifikasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MÅLEMETODE", "målemetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MÅLESTOKK", "målestokk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "MÅLTALL", "måltall", OFTReal);
-    
+
       addSimpleType(&oTypes, "NASJONALTOPPMERKETYPE", "nasjonalToppmerketype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "NASJVIKTIG", "rastoffViktighetOmfang", OFTString);
-    
+
       addSimpleType(&oTypes, "NAVIGASJONSINSTALLASJONSEIER", "navigasjonsinstallasjonseier", OFTString);
-    
+
       addSimpleType(&oTypes, "NAVLYS_KARAKTER", "navigasjonslyskarakter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "NAVLYSTYPE", "navlysType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "NAVN", "navn", OFTString);
-    
+
       addSimpleType(&oTypes, "NAVNTYPE", "navnetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "NEDSENKETKANTSTEIN", "nedsenketKantstein", OFTString);
-    
+
       addSimpleType(&oTypes, "NEDSTENGT_DATO", "nedstengtDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "NETT_NIV", "ledningsnettNivå", OFTString);
-    
+
       addSimpleType(&oTypes, "NEVNER", "nevner", OFTReal);
-    
+
       addSimpleType(&oTypes, "NOMINELLREKKEVIDDE", "nominellRekkevidde", OFTReal);
-    
+
       addSimpleType(&oTypes, "NORD", "nord", OFTInteger);
-    
+
       addSimpleType(&oTypes, "NYMATRIKULERT", "nymatrikulert", OFTString);
-    
+
       addSimpleType(&oTypes, "NÆRINGSGRUPPE", "næringsgruppe", OFTString);
-    
+
       addSimpleType(&oTypes, "NØYAKTIGHET", "nøyaktighet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "NØYAKTIGHETSKLASSE", "nøyaktighetsklasse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "NÅVÆRENDE_AREAL", "nåværendeAreal", OFTReal);
-    
+
       addSimpleType(&oTypes, "OBJTYPE", "objekttypenavn", OFTString);
-    
+
       addSimpleType(&oTypes, "OBSERVERTFLOM", "observertFlom", OFTReal);
-    
+
       addSimpleType(&oTypes, "OBSLINID", "obsLinId", OFTString);
-    
+
       addSimpleType(&oTypes, "OMKRETSINNSJØ", "omkretsInnsjø", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OMRKODE", "reinbeiteområdeID", OFTString);
-    
+
       addSimpleType(&oTypes, "OMRNAVN", "områdenavn", OFTString);
-    
+
       addSimpleType(&oTypes, "OMRTYPE", "dumpefelttype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OMRÅDEID", "områdeid", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OMTVISTET", "omtvistet", OFTString);
-    
+
       addSimpleType(&oTypes, "OPAREALAVGRTYPE", "operativArealavgrensningtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OPERATØR", "petroleumsoperatør", OFTString);
-    
+
       addSimpleType(&oTypes, "OPLAREAL", "arealbruk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OPLAREALUTDYP", "arealbruksutdyping", OFTString);
-    
+
       addSimpleType(&oTypes, "OPLRESTR", "arealbruksrestriksjoner", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OPLRETNL", "arealbruksretningslinjer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OPPARBEIDING", "opparbeiding", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OPPDATERINGSDATO", "oppdateringsdato", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "OPPDRAGSGIVER", "oppdragsgiver", OFTString);
-    
+
       addSimpleType(&oTypes, "OPPGITTAREAL", "oppgittAreal", OFTReal);
-    
+
       addSimpleType(&oTypes, "OPPHAV", "opphav", OFTString);
-    
+
       addSimpleType(&oTypes, "OPPMÅLINGIKKEFULLFØRT", "oppmålingIkkeFullført", OFTString);
-    
+
       addSimpleType(&oTypes, "OPPMÅLTKOTE", "oppmåltKote", OFTReal);
-    
+
       addSimpleType(&oTypes, "OPPMÅLTÅR", "oppmåltÅr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OPPRETTET_AAR", "opprettetÅr", OFTDate);
-    
+
       addSimpleType(&oTypes, "OPPRINNELIGBILDEFORMAT", "bildeType", OFTString);
-    
+
       addSimpleType(&oTypes, "OPPRINNELIGBILDESYS", "BildeSystem", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OPPRINNELIGSOSIALTMILJØ", "opprinneligSosialtMiljø", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OPPRINNELSE", "opprinnelse", OFTString);
-    
+
       addSimpleType(&oTypes, "OPPSTARTSÅR", "oppstartsår", OFTDate);
-    
+
       addSimpleType(&oTypes, "OPPTAKSMETODE", "opptaksmetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OPPVARMING", "oppvarming", OFTString);
-    
+
       addSimpleType(&oTypes, "ORGANISK", "organiskAndel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ORGNR", "organsisasjonsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ORIENTERINGSDATA", "orienteringsdata", OFTString);
-    
+
       addSimpleType(&oTypes, "ORIENTERINGSMETODE", "orienteringsmetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ORIGINALDATAVERT", "originalDatavert", OFTString);
-    
+
       addSimpleType(&oTypes, "ORIGO-N", "origoNord", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ORIGO-Ø", "origoØst", OFTInteger);
-    
+
       addSimpleType(&oTypes, "OVERGRUPPE", "overgruppeNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "PBTILTAK", "tiltakstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PETLITOKODE", "petrofLitologi", OFTString);
-    
+
       addSimpleType(&oTypes, "PETMETAKODE", "petrofMetamorfose", OFTString);
-    
+
       addSimpleType(&oTypes, "PETROLEUM_KOORD_STATUS", "petroleumKoordinatstatus", OFTString);
-    
+
       addSimpleType(&oTypes, "PETROLEUMLEDNINGFUNKSJON", "petroleumsledningsfunksjon", OFTString);
-    
+
       addSimpleType(&oTypes, "PETROLEUMLEDNINGTYPE", "petroleumsledningstype", OFTString);
-    
+
       addSimpleType(&oTypes, "PETROLEUMSANDEL", "petroleumsandel", OFTReal);
-    
+
       addSimpleType(&oTypes, "PETROLEUMSDATAKILDE", "petroleumsdatakilde", OFTString);
-    
+
       addSimpleType(&oTypes, "PETROLEUMSFELTNAVN", "petroleumsfeltnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "PETROLEUMSFELTTYPE", "petroleumsfelttype", OFTString);
-    
+
       addSimpleType(&oTypes, "PETROLEUMSPARTNERE", "petroleumspartnere", OFTString);
-    
+
       addSimpleType(&oTypes, "PETSTRATKODE", "petrofStratigrafi", OFTString);
-    
+
       addSimpleType(&oTypes, "PILARKATEGORI", "pilarkategori", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PIXEL-STØRR", "pixelstørrelse", OFTReal);
-    
+
       addSimpleType(&oTypes, "PLANBEST", "planbestemmelse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PLANERING", "planeringsgrad", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PLANID", "planidentifikasjon", OFTString);
-    
+
       addSimpleType(&oTypes, "PLANNAVN", "plannavn", OFTString);
-    
+
       addSimpleType(&oTypes, "FORSLAGSSTILLERTYPE", "forslagsstillerType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PLANSTAT", "planstatus", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PLANTYPE", "plantype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PLASS", "plasseringskode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PLFMERK", "oppstillingplattformmerking", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PLOGSJIKTTEKSTUR", "plogsjiktTekstur", OFTInteger);
-    
+
       addSimpleType(&oTypes, "POBS", "observasjonstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "POLITIDISTRIKTID", "politidistriktId", OFTInteger);
-    
+
       addSimpleType(&oTypes, "POS_KVAL", "posisjonKvalitet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "POS_TYPE", "posisjonType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BITS_PR_PIXEL", "bitsPrPixel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "POSTNAVN", "poststedsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "POSTNR", "postnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PREPARERING", "løypepreparering", OFTString);
-    
+
       addSimpleType(&oTypes, "PRIMÆRSTREKNINGSNUMMER", "primærstrekningsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PRIOMR", "prioritetområde", OFTString);
-    
+
       addSimpleType(&oTypes, "PRIORITET", "kulturlandskapPrioritet", OFTString);
-    
+
       addSimpleType(&oTypes, "PRIVAT_KLOAKKR", "privatKloakkRensing", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PRODUKT", "produkt", OFTString);
-    
+
       addSimpleType(&oTypes, "PRODUKT_FULLT_NAVN", "produktFullstendigNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "PRODUKTGRUPPE", "produktgruppe", OFTString);
-    
+
       addSimpleType(&oTypes, "PRODUSENT", "geodataprodusent", OFTString);
-    
+
       addSimpleType(&oTypes, "PROJEK", "projeksjon", OFTString);
-    
+
       addSimpleType(&oTypes, "PROSELV", "prosentElv", OFTReal);
-    
+
       addSimpleType(&oTypes, "PROSESS_HISTORIE", "prosesshistorie", OFTString);
-    
+
       addSimpleType(&oTypes, "PROSHAV", "prosentHav", OFTReal);
-    
+
       addSimpleType(&oTypes, "PROSINNSJØ", "prosentInnsjø", OFTReal);
-    
+
       addSimpleType(&oTypes, "PROSJEKTNAVN", "prosjektnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "PROSJEKTSTART", "prosjektstartår", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PROSLAND", "prosentLand", OFTReal);
-    
+
       addSimpleType(&oTypes, "PROSTINUMMER", "prostinummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PROVEMATR", "proveMaterial", OFTString);
-    
+
       addSimpleType(&oTypes, "PTYPE", "punktType", OFTString);
-    
+
       addSimpleType(&oTypes, "PUKKVERKTYPE", "pukkverktype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PUMPER_NØDSTR", "pumperNødstrøm", OFTString);
-    
+
       addSimpleType(&oTypes, "PUMPES_VANNET", "pumperVannet", OFTString);
-    
+
       addSimpleType(&oTypes, "PUNKTBESKR", "punktBeskrivelse", OFTString);
-    
+
       addSimpleType(&oTypes, "PUNKTFESTE", "punktfeste", OFTString);
-    
+
       addSimpleType(&oTypes, "PÅVIRKNINGSGRAD", "påvirkningsgrad", OFTInteger);
-    
+
       addSimpleType(&oTypes, "R_FNR", "forekomstNummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "R_LNR", "lokalNummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "R_ONR", "omrNummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "R_PNR", "proveNummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "R_RESERVER", "rastoffReserver", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RACONFREKVENSBÅND", "raconFrekvensbånd", OFTString);
-    
+
       addSimpleType(&oTypes, "RACONKARAKTER", "raconkarakter", OFTString);
-    
+
       addSimpleType(&oTypes, "RACONMORSETEGN", "raconmorsetegn", OFTString);
-    
+
       addSimpleType(&oTypes, "RACONRESPONSINTERVALL", "raconresponsintervall", OFTString);
-    
+
       addSimpleType(&oTypes, "RACONTYPE", "racontype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RADAR_FYR_TYPE", "radarfyrtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RADARREFLEKTOR", "radarReflektor", OFTString);
-    
+
       addSimpleType(&oTypes, "RADARSTASJONSTYPE", "radarstasjonstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RADIO_FYR_TYPE", "radiofyrtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RADIOAKTIV", "radioaktivitetNiva", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RADIOFYRMODULASJON", "radiofyrmodulasjon", OFTString);
-    
+
       addSimpleType(&oTypes, "RADIUS", "radius", OFTReal);
-    
+
       addSimpleType(&oTypes, "RADRISKOMR", "naturlRadioaktivStraling", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RAPPORTERINGSÅR", "rapporteringsår", OFTDate);
-    
+
       addSimpleType(&oTypes, "REFERANSE", "referanse", OFTString);
-    
+
       addSimpleType(&oTypes, "REFERANSENUMMER", "referansenummer", OFTString);
-    
+
       addSimpleType(&oTypes, "REGFORM", "reguleringsformål", OFTInteger);
-    
+
       addSimpleType(&oTypes, "REGFORMUTDYP", "reguleringsformålsutdyping", OFTString);
-    
+
       addSimpleType(&oTypes, "REGISTRERINGKRETSNR", "registreringKretsnr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "REGISTRERT_DATO", "registrertDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "REGMETOD", "registreringsmetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "REGULERTHØYDE", "regulertHøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "REINDRIFTANLTYP", "reindriftsanleggstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "REINDRIFTKONNAVN", "reindriftKonvensjonsområdenavn", OFTString);
-    
+
       addSimpleType(&oTypes, "REKKEVIDDEGRØNN", "rekkeviddeGrønn", OFTReal);
-    
+
       addSimpleType(&oTypes, "REKKEVIDDEGUL", "rekkeviddeGul", OFTReal);
-    
+
       addSimpleType(&oTypes, "REKKEVIDDEHVIT", "rekkeviddeHvit", OFTReal);
-    
+
       addSimpleType(&oTypes, "REKKEVIDDERØD", "rekkeviddeRød", OFTReal);
-    
+
       addSimpleType(&oTypes, "RENHET", "retningsenhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RENOVASJON", "renovasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RESIPIENTTYPE", "resipienttype", OFTString);
-    
+
       addSimpleType(&oTypes, "RESTR_OMR", "restriksjonsområde", OFTString);
-    
+
       addSimpleType(&oTypes, "RESTRIKSJONSTYPE", "restriksjonstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RET_SYS", "retningsreferanse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RETN", "retningsverdi", OFTReal);
-    
+
       addSimpleType(&oTypes, "RETNINGSEKTORLINJE1", "retningSektorlinje1", OFTReal);
-    
+
       addSimpleType(&oTypes, "RETNINGSEKTORLINJE2", "retningSektorlinje2", OFTReal);
-    
+
       addSimpleType(&oTypes, "RISIKOVURDERING", "risikovurdering", OFTString);
-    
+
       addSimpleType(&oTypes, "RKB", "rkb", OFTReal);
-    
+
       addSimpleType(&oTypes, "RKB_TD", "rkbTotaltDyp", OFTReal);
-    
+
       addSimpleType(&oTypes, "ROTASJON", "rotasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPANGITTHENSYN", "angitthensyn", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPAREALFORMÅL", "arealformål", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPBÅNDLEGGING", "båndlegging", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPDETALJERING", "detaljering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPFARE", "fare", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPGJENNOMFØRING", "gjennomføring", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPINFRASTRUKTUR", "infrastruktur", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPJURLINJE", "juridisklinje", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPJURPUNKT", "juridiskpunkt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPPÅSKRIFTTYPE", "påskriftType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPSIKRING", "sikring", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPSTØY", "støy", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RSL_JREG", "referansesystemForLandskapJordbruksregioner", OFTString);
-    
+
       addSimpleType(&oTypes, "RSL_REG", "referansesystemForLandskapRegioner", OFTString);
-    
+
       addSimpleType(&oTypes, "RSL_UREG", "referansesystemForLandskapUReg", OFTString);
-    
+
       addSimpleType(&oTypes, "RTALLHØY", "reintallHøyeste", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RTALLVEDTAK", "reintallVedtak", OFTString);
-    
+
       addSimpleType(&oTypes, "RULLEBANEDISTANSETYPE", "rullebanedistansetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RULLEBANERETNING", "rullebaneretning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RUTEBREDDE", "rutebredde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RUTEFØLGER", "ruteFølger", OFTString);
-    
+
       addSimpleType(&oTypes, "RUTEMERKING", "ruteMerking", OFTString);
-    
+
       addSimpleType(&oTypes, "RUTENETTYPE", "rutenettype", OFTString);
-    
+
       addSimpleType(&oTypes, "RUTENR", "rutenummer", OFTString);
-    
+
       addSimpleType(&oTypes, "SEFRAK_TILTAK", "sefrakTiltak", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SEFRAKBREDDE", "sefrakbredde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SEFRAKKOMMUNE", "sefrakKommune", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SEFRAKLENGDE", "sefraklengde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SEIL_BREDDE", "seilingsbredde", OFTReal);
-    
+
       addSimpleType(&oTypes, "SEIL_DYBDE", "seilingsdybde", OFTReal);
-    
+
       addSimpleType(&oTypes, "SEKSJONERT", "seksjonert", OFTString);
-    
+
       addSimpleType(&oTypes, "SEKTORTEKST", "sektortekst", OFTString);
-    
+
       addSimpleType(&oTypes, "SEKUNDÆRSTREKNINGSNUMMER", "sekundærstrekningsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SENTRUMSSONENAVN", "sentrumssonenavn", OFTString);
-    
+
       addSimpleType(&oTypes, "SENTRUMSSONENUMMER", "sentrumssonenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SEPTIKTANK", "septiktank", OFTString);
-    
+
       addSimpleType(&oTypes, "SERIEKODE1", "serie1", OFTString);
-    
+
       addSimpleType(&oTypes, "SERIEKODE2", "serie2", OFTString);
-    
+
       addSimpleType(&oTypes, "SERIEKODE3", "serie3", OFTString);
-    
+
       addSimpleType(&oTypes, "SERVMERK", "servituttMerknad", OFTString);
-    
+
       addSimpleType(&oTypes, "SERVTYPE", "servituttType", OFTString);
-    
+
       addSimpleType(&oTypes, "SESOMR", "reindriftSesongområde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SFOTRUTETYPE", "spesialFotrutetype", OFTString);
-    
+
       addSimpleType(&oTypes, "SIDEOVERLAPP", "sideoverlapp", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SIGNALGRUPPE", "signalgruppe", OFTString);
-    
+
       addSimpleType(&oTypes, "SIGNALNR", "signalnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "SIGNALPERIODE", "signalperiode", OFTString);
-    
+
       addSimpleType(&oTypes, "SIGNALSEKVENS", "signalsekvens", OFTString);
-    
+
       addSimpleType(&oTypes, "SIGNH", "signalHøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "SIGNHREF", "signalHøydeRef", OFTString);
-    
+
       addSimpleType(&oTypes, "SIGNTYPE", "signalType", OFTString);
-    
+
       addSimpleType(&oTypes, "SIKKERÅR", "ledningsalderReferanse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SIKTEDYP", "sikteDyp", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SIST_VURDERT_AAR", "sistVurdertÅr", OFTDate);
-    
+
       addSimpleType(&oTypes, "SISTBEFART", "sisteBefaringsdato", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SJØ_RESTRIKSJON", "sjørestriksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SJØ_SIGFRQ", "sjøsignalfrekvens", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SJØ_STATUS", "sjøstatus", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SJØ_TRAFIKK", "sjøtrafikk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SJØMERKEFARGE", "sjømerkefarge", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SJØMERKESYSTEM", "sjømerkesystem", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKAL_AVGR_BYGN", "skalAvgrenseBygning", OFTString);
-    
+
       addSimpleType(&oTypes, "SKALAENHET", "skalaenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "SKILTGRUPPE", "skiltgruppe", OFTString);
-    
+
       addSimpleType(&oTypes, "SKILØYPETYPE", "skiløypetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKJERMINGFUNK", "skjermingsfunksjon", OFTString);
-    
+
       addSimpleType(&oTypes, "SKOG", "jordregisterSkogtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKOGREIS", "jordregisterSkogreisningsmark", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKOLEKRETSTYPE", "skolekretsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "SKREDALDERBEST", "skredAlderBestemmelse", OFTString);
-    
+
       addSimpleType(&oTypes, "SKREDBESKRIVELSE", "skredBeskrivelse", OFTString);
-    
+
       addSimpleType(&oTypes, "SKREDBREDDE", "skredBredde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDEVAKUERING", "skredEvakuering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDFALLHØYDE", "skredFallhoyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDFAREGR_KL", "skredFaregradKlasse", OFTString);
-    
+
       addSimpleType(&oTypes, "SKREDFAREGRADSCORE", "skredFaregradScore", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDFAREVURD", "snoSteinSkredfareVurdering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDKONSSCORE", "skredSkadKonsekvensScore", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDKVALKARTLEGGING", "skredKvalKartlegging", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDLENGDE", "skredLengde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDMALEMETODE", "skredMalemetode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDOBSGUID", "skredObservasjonGUID", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDOMKOMNE", "skredAntallOmkomne", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDOMRID", "skredOmrID", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDOMRNAVN", "skredOmrNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "SKREDREDNING", "skredRedning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDRISIKO_KL", "skredRisikoKvikkleireKlasse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDSKADEANNEN", "skredSkadeAnnen", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDSKADEOBJEKTER", "skredSkadeObjekter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDSKADESAMFERDSEL", "skredSkadeSamferdsel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDSKADETYPE", "skredSkadType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDSKADKONS_KL", "skredSkadeKonsekvensKlasse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDSTATSANN", "skredStatistikkSannsynlighet", OFTString);
-    
+
       addSimpleType(&oTypes, "SKREDTIDHENDELSE", "skredTidspunktHendelse", OFTString);
-    
+
       addSimpleType(&oTypes, "SKREDTIDUSIKKERH", "skredTidUsikkerhet", OFTString);
-    
+
       addSimpleType(&oTypes, "SKREDTYPE", "skredtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDUTLOMRHELNING", "skredUtlosningOmrHelning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDUTLOPOMRTYPE", "skredUtlopOmrType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDUTLOSNINGOMRTYPE", "skredUtlosningOmrType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKREDVOLUM", "skredVolum", OFTString);
-    
+
       addSimpleType(&oTypes, "SKRETSNAVN", "skolekretsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "SKRETSNR", "skolekretsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKRIFTKODE", "presentasjonskode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SKYLD", "skyld", OFTReal);
-    
+
       addSimpleType(&oTypes, "SKYVGRINDL", "skyvegrenseInndeling", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SLUSETYP", "sluseType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SMÅBÅTHAVNFASILITET", "småbåthavnfasilitet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SNAVN", "stedsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "SNDATO", "statusdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "SNITT_HØ", "snitthøyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SNKILDE", "stedsnavnkilde", OFTString);
-    
+
       addSimpleType(&oTypes, "SNLØPENR", "arkivløpenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SNMERK", "stedsnavnmerknad", OFTString);
-    
+
       addSimpleType(&oTypes, "SNMYND", "stedsnavnVedtaksmyndighet", OFTString);
-    
+
       addSimpleType(&oTypes, "SNR", "seksjonsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SNREGDATO", "stedsnavnRegistreringsdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "SNSAKSNR", "arkivsaksnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SNSKRSTAT", "stedsnavnSkrivemåtestatus", OFTString);
-    
+
       addSimpleType(&oTypes, "SNSPRÅK", "språk", OFTString);
-    
+
       addSimpleType(&oTypes, "SNTYSTAT", "stedsnavnTypestatus", OFTString);
-    
+
       addSimpleType(&oTypes, "SNØSCOOTERLØYPETYPE", "snøscooterløypeType", OFTString);
-    
+
       addSimpleType(&oTypes, "SOGNNUMMER", "sognnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SONENAUT", "soneNautisk", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SONETYPE", "sonetype", OFTString);
-    
+
       addSimpleType(&oTypes, "SOSIELEMENT", "sosiElementnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "SOSI-NIVÅ", "sosiKompleksitetNivå", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SOSI-VERSJON", "sosiVersjon", OFTString);
-    
+
       addSimpleType(&oTypes, "SP_ABONTRE", "skogbrplanKlassAktueltTreslag", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_AGJBON", "skogbrplanKlassAktSnittBon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_ALDER", "skogbrplanBeskrivBestandAlder", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_ANDEREG", "skogbrplanTreslagAntTreDaaEReg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_ANDFREG", "skogbrplanTreslagAntTreDaaFReg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_AVOLPRDA", "skogbrplanGrunnlagVolumDaaFelt", OFTReal);
-    
+
       addSimpleType(&oTypes, "SP_AVOLTOT", "skogbrplanGrunnlagVolumBestFelt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_BAREAL", "skogbrplanBeskrivBestandDaa", OFTReal);
-    
+
       addSimpleType(&oTypes, "SP_BERTYPE", "skogbrplanGrunnlagBerType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_BESTDELNR", "skogbrplanBestandDelNr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_BESTNR", "skogbrplanBestandNr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_BEVNE", "skogbrplanTerrengBæreevneBestand", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_BMIDDIAM", "skogbrplanBeskrivBestSnittDiam", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_BMIDGRFL", "skogbrplanBeskrivBestandSnittM2", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_BMIDHO", "skogbrplanBeskrivBestandSnittH", OFTReal);
-    
+
       addSimpleType(&oTypes, "SP_BRATT", "skogbrplanTerrengBestandBratthet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_BTILVPRDA", "skogbrplanTilvekstBeregnDaa", OFTReal);
-    
+
       addSimpleType(&oTypes, "SP_BTILVPROS", "skogbrplanTilvekstBeregnProsent", OFTReal);
-    
+
       addSimpleType(&oTypes, "SP_BVOLPRDA", "skogbrplanTilvekstBeregnM3", OFTReal);
-    
+
       addSimpleType(&oTypes, "SP_DENDR", "skogbrplanAdmDatoEndring", OFTDate);
-    
+
       addSimpleType(&oTypes, "SP_DREG", "skogbrplanAdmDatoEtablering", OFTDate);
-    
+
       addSimpleType(&oTypes, "SP_ELEMTYPE", "skogbrplanFlerKoderElementtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_FARAND", "skogbrplanFlerKoderArealProsent", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_FAREAL", "skogbrplanFlerKoderArealDaa", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_FRAND", "skogbrplanFlerKoderSpesBehPros", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_FRAREAL", "skogbrplanFlerKoderSpesBehDaa", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_GREND", "skogbrplanTeigGrend", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_GRFL", "skogbrplanTetthetGrunnflatesum", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_HBAR", "skogbrplanBeskrivBarHøydehkl2", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_HKL", "skogbrplanBeskrivHogstklasse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_HLAUV", "skogbrplanBeskrivLauvHøydehkl2", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_HOVEDGR", "skogbrplanGrunnlagHovedgruppe", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_HOYDE", "skogbrplanTetthetMHøyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_IMPANDEL", "skogbrplanKlassImpProsent", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_IMPTYPE", "skogbrplanKlassImpType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_LILEN", "skogbrplanTerrengLiLengde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_MINTRSP", "skogbrplanTerrengMinTranspUtst", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_PBONTRE", "skogbrplanKlassPotTreslag", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_PGJBON", "skogbrplanKlassPotSnittBon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_PRIO", "skogbrplanTiltakProritet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_REG", "skogbrplanGrunnlagRegion", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_SJIKT", "skogbrplanBeskrivSjiktning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_SKOGTYP", "skogbrplanBeskrivSkogtype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_SUNNH", "skogbrplanBeskrivSunnhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_SVPROS", "skogbrplanGrunnlagSvinnProsent", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TAKSTTYPE", "skogbrplanGrunnlagTaksttype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TARAND", "skogbrplanTiltakProsent", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TAREAL", "skogbrplanTiltakAreal", OFTReal);
-    
+
       addSimpleType(&oTypes, "SP_TEIGNR", "skogbrplanTeigNr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TERJEVN", "skogbrplanTerrengJevnhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TILT", "skogbrplanTiltakBestand", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TILVKOR", "skogbrplanGrunnlagTilvekstkorr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TNAVN", "skogbrplanTeigNavn", OFTString);
-    
+
       addSimpleType(&oTypes, "SP_TOTVOL", "skogbrplanTilvekstVolumBestand", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TREEREG", "skogbrplanBeskrivTreERegulering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TREFREG", "skogbrplanBeskrivTreFRegulering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TRESLAG", "skogbrplanTreslag", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_TRESLHO", "skogbrplanTreslagHøyde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_VOLAND", "skogbrplanTreslagProsent", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_VOLKORR", "skogbrplanTreslagKorrVolumUBark", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_VOLSALG", "skogbrplanTreslagSalgsvolumUBark", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_VOLUKORR", "skogbrplanTreslagUkorrVolumUBark", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SP_AAR", "skogbrplanTiltakÅr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SPERRING", "sperring", OFTString);
-    
+
       addSimpleType(&oTypes, "SPES_SKILØYPETYPE", "spesialSkiløypetype", OFTString);
-    
+
       addSimpleType(&oTypes, "SPESIALMERKETYPE", "spesialmerketype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SPESIALSYKKELRUTETYPE", "spesialsykkelrutetype", OFTString);
-    
+
       addSimpleType(&oTypes, "SPOR_HASTIGHET", "sporhastighet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SPORANTALL", "sporantall", OFTString);
-    
+
       addSimpleType(&oTypes, "SPORAVGRENINGSNR", "sporavgreningsnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "SPORAVGRENINGSPUNKTNR", "sporavgreningspunktnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "SPORAVGRENINGSPUNKTTYPE", "sporavgreningspunkttype", OFTString);
-    
+
       addSimpleType(&oTypes, "SPORAVGRENINGSTYPE", "sporavgreningstype", OFTString);
-    
+
       addSimpleType(&oTypes, "SPORKM", "sporKilometer", OFTReal);
-    
+
       addSimpleType(&oTypes, "SPORNUMMER", "spornummer", OFTString);
-    
+
       addSimpleType(&oTypes, "SPORPUNKTNUMMER", "sporpunktnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "SPORPUNKTTYPE", "sporpunkttype", OFTString);
-    
+
       addSimpleType(&oTypes, "SPORTYPE", "sportype", OFTString);
-    
+
       addSimpleType(&oTypes, "SSR-ID", "ssrId", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SSR-OBJID", "objId", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STANDARDENHET", "standardenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "STASJONSFORMÅL", "stasjonsformål", OFTString);
-    
+
       addSimpleType(&oTypes, "STASJONSNR", "stasjonsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STASJONSPARAMETER", "stasjonsparameter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STASJONSTYPE", "stasjonstype", OFTString);
-    
+
       addSimpleType(&oTypes, "STASJONTYP", "stasjonstype", OFTString);
-    
+
       addSimpleType(&oTypes, "STAT", "typeStatus", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STATUS", "status", OFTString);
-    
+
       addSimpleType(&oTypes, "STED", "sted", OFTString);
-    
+
       addSimpleType(&oTypes, "STED_VERIF", "stedfestingVerifisert", OFTString);
-    
+
       addSimpleType(&oTypes, "STENGESDATO", "stengesDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "STORBUE", "storbue", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STREKNINGSNUMMER", "strekningsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STRENG", "generellTekststreng", OFTString);
-    
+
       addSimpleType(&oTypes, "STRIPENUMMER", "stripenummer", OFTString);
-    
+
       addSimpleType(&oTypes, "STRUKTUROVERBIKKET", "strukturOverbikket", OFTString);
-    
+
       addSimpleType(&oTypes, "STRUKTURPUNKTTYPE", "strukturPunkttype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STRØMHAST", "strømhastighet", OFTReal);
-    
+
       addSimpleType(&oTypes, "STRØMRETN", "strømretning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STØYENHET", "støyenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "STØYINTERVALL", "støyintervall", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STØYKILDE", "støykilde", OFTString);
-    
+
       addSimpleType(&oTypes, "STØYKILDEIDENTIFIKASJON", "Støykildeidentifikasjon", OFTString);
-    
+
       addSimpleType(&oTypes, "STØYKILDENAVN", "støykildenavn", OFTString);
-    
+
       addSimpleType(&oTypes, "STØYMETODE", "støymetode", OFTString);
-    
+
       addSimpleType(&oTypes, "STØYNIVÅ", "støynivå", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STØYSONEKATEGORI", "støysonekategori", OFTString);
-    
+
       addSimpleType(&oTypes, "SUM_ALT_AREAL", "sumAlternativtAreal", OFTReal);
-    
+
       addSimpleType(&oTypes, "SUM_ALT_AREAL2", "sumAlternativtAreal2", OFTReal);
-    
+
       addSimpleType(&oTypes, "SUM_ANTALLBOENH", "sumAntallBoenheter", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SUM_BRUKSARTOT", "sumBruksarealTotalt", OFTReal);
-    
+
       addSimpleType(&oTypes, "SUM_BRUKSTILANN", "sumBruksarealTilAnnet", OFTReal);
-    
+
       addSimpleType(&oTypes, "SUM_BRUKSTILBOL", "sumBruksarealTilBolig", OFTReal);
-    
+
       addSimpleType(&oTypes, "SYKKELRUTETYPE", "sykkelrutetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SYNBARHET", "synbarhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SYSKODE", "referansesystemKode", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TAKFORM", "takform", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TAKSKJEGG", "takskjegg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TAKTEKKING", "taktekking", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TDIM-BREDDE", "tekstTegnbredde", OFTReal);
-    
+
       addSimpleType(&oTypes, "TDIM-HØYDE", "tekstTegnhøyde", OFTReal);
-    
+
       addSimpleType(&oTypes, "TEGNFORKL", "tegnforklaring", OFTString);
-    
+
       addSimpleType(&oTypes, "TEGNSETT", "tegnsett", OFTString);
-    
+
       addSimpleType(&oTypes, "TEIGE_ID", "teigEtterSkifteIdent", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TEIGF_ID", "teigFørSkitfeIdent", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TEIGFLEREMATRSAMMEEIER", "teigFlereMatrSammeEier", OFTString);
-    
+
       addSimpleType(&oTypes, "TEIGMEDFLEREMATRENHETER", "teigMedFlereMatrikkelenheter", OFTString);
-    
+
       addSimpleType(&oTypes, "TEIGNR", "jordregisterEiendomTeigNummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TEKSTURKODE1", "teksturkode", OFTString);
-    
+
       addSimpleType(&oTypes, "TEKSTURKODE2", "teksturkode2", OFTString);
-    
+
       addSimpleType(&oTypes, "TEKSTURKODE3", "teksturkode3", OFTString);
-    
+
       addSimpleType(&oTypes, "TELEFAXNR", "telefaxnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TELEFONNR", "telefonnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TELLER", "teller", OFTReal);
-    
+
       addSimpleType(&oTypes, "TEMAJUST", "geolTemajustering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TEMAKVAL", "temaKvalitet", OFTString);
-    
+
       addSimpleType(&oTypes, "TERSKELFUNKSJON", "terskelFunksjon", OFTString);
-    
+
       addSimpleType(&oTypes, "TERSKELTYP", "terskelType", OFTString);
-    
+
       addSimpleType(&oTypes, "TETTSTEDNAVN", "tettstednavn", OFTString);
-    
+
       addSimpleType(&oTypes, "TIDOPPHOLDVANN", "tidOppholdVann", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TIDREF", "tidreferanse", OFTString);
-    
+
       addSimpleType(&oTypes, "TIDSANGIVELSE", "tidsangivelse", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TIDSENHET", "tidsenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "TIDSLUTT", "periodeSlutt", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "TIDSPUNKT", "tidspunkt", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "TIDSTART", "periodeStart", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "TILDELT_AREAL", "tildeltAreal", OFTReal);
-    
+
       addSimpleType(&oTypes, "TILDELT_DATO", "tilldeltDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "TILGJENGELIGHETSVURDERING", "tilgjengelighetsvurdering", OFTString);
-    
+
       addSimpleType(&oTypes, "TILLEGG", "flatetillegg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TILLEGGSAREAL", "tilleggsareal", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TILSPORNODEKILOMETER", "tilSpornodeKilometer", OFTReal);
-    
+
       addSimpleType(&oTypes, "TILSPORNODETEKST", "tilSpornodeTekst", OFTString);
-    
+
       addSimpleType(&oTypes, "TILSPORNODETYPE", "tilSpornodeType", OFTString);
-    
+
       addSimpleType(&oTypes, "TILSYS", "tilKoordinatsystem", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TILTAKNR", "tiltaksnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TINGLYST", "tinglyst", OFTString);
-    
+
       addSimpleType(&oTypes, "TIPPVOLUM", "deponitippVolum", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TOKTID", "toktId", OFTString);
-    
+
       addSimpleType(&oTypes, "TOT_PROD", "totalProduksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TOTALAREALKM2", "totalarealKm2", OFTReal);
-    
+
       addSimpleType(&oTypes, "TOTALBELASTNING", "totalBelastning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TRAFIKKBELASTNING", "trafikkbelastning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TRAFIKKFARE", "trafikkfare", OFTString);
-    
+
       addSimpleType(&oTypes, "TRE_D_NIVÅ", "treDNivå", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TRE_TYP", "treType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TRNORD", "tekstReferansePunktNord", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TRØST", "tekstReferansePunktØst", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TSKOG", "tilleggsopplysningerSkog", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TSKYV", "tekstForskyvning", OFTReal);
-    
+
       addSimpleType(&oTypes, "TSTED", "tettstednummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TVIST", "tvist", OFTString);
-    
+
       addSimpleType(&oTypes, "TWYMERK", "taksebaneoppmerking", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TYPE_BR", "trasebreddetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TYPE_VANNFOR_ANL", "typeVannforsyningsanlegg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TYPEDUMPEOMRÅDE", "typeDumpeområde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TYPEINNSJØ", "typeInnsjø", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TYPESAMFLINJE", "samferdselslinjeType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "TYPESAMFPUNKT", "samferdselspunkt", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UB_ANL_TYP", "utmarkbeiteAnleggstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UB_DYRESL", "utmarkbeiteDyreslag", OFTString);
-    
+
       addSimpleType(&oTypes, "UFULLSTENDIGAREAL", "ufullstendigAreal", OFTString);
-    
+
       addSimpleType(&oTypes, "UNDERBYGNINGKONSTR", "underbygningKonstr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UNDERGRUNN", "undergrunn", OFTString);
-    
+
       addSimpleType(&oTypes, "UNDERLAG", "fastmerkeUnderlag", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UNDERLAGSTYPE", "underlagstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UNDERSAMMENFØYNINGSKALBESTÅ", "underSammenføyningSkalBestå", OFTString);
-    
+
       addSimpleType(&oTypes, "UNDERSAMMENFØYNINGSKALUTGÅ", "underSammenføyningSkalUtgå", OFTString);
-    
+
       addSimpleType(&oTypes, "UNDERSOKELSENR", "undersokelseNummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UNDERTYPE", "undertypeVersjon", OFTString);
-    
+
       addSimpleType(&oTypes, "UNR", "underNr", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UREGJORDSAMEIE", "uregistrertJordsameie", OFTString);
-    
+
       addSimpleType(&oTypes, "UTEAREAL", "uteoppholdsareal", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UTGÅR_DATO", "utgårDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "UTGÅTT", "utgått", OFTString);
-    
+
       addSimpleType(&oTypes, "UTNTALL", "utnyttingstall", OFTReal);
-    
+
       addSimpleType(&oTypes, "UTNTYP", "utnyttingstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UTNYTTBAR_KAP", "utnyttbarMagasinkapasitet", OFTReal);
-    
+
       addSimpleType(&oTypes, "UTSLIPPTYPE", "utslipptype", OFTString);
-    
+
       addSimpleType(&oTypes, "UTV_TILL_NR", "tillatelsesnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "UTV_TILL_TYPE", "utvinningstillatelsestype", OFTString);
-    
+
       addSimpleType(&oTypes, "UTVALGSAK", "utvalgssaksnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UTVALGSMET", "utvalgMetode", OFTString);
-    
+
       addSimpleType(&oTypes, "UUFASILITET", "universellutformingFasilitet", OFTString);
-    
+
       addSimpleType(&oTypes, "VALUTAENHET", "valutaenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "VANNBR", "vannbredde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VANNFORSYNING", "vannforsyning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VANNFØRINGMIDLERE", "vannføringMidlere", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VANNFØRINGMINSTE", "vannføringMinste", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VANNFØRINGSTØRST", "vannføringStørst", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VANNLAGR", "vannlagringsevne", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VASSDRAGNAVN", "vassdragsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "VASSDRAGSNR", "vassdragsnummer", OFTString);
-    
+
       addSimpleType(&oTypes, "VATNLNR", "vatnLøpenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "V-DELTA-MAX", "vertikaltDeltaMaksimum", OFTInteger);
-    
+
       addSimpleType(&oTypes, "V-DELTA-MIN", "vertikaltDeltaMinimum", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VEDLIKEH", "vedlikeholdsansvarlig", OFTString);
-    
+
       addSimpleType(&oTypes, "VEDTAK", "vedtakstype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VEDTAKSDATO", "vedtaksdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "VEGKATEGORI", "vegkategori", OFTString);
-    
+
       addSimpleType(&oTypes, "VEGNUMMER", "vegnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VEGOVERVEG", "vegOverVeg", OFTString);
-    
+
       addSimpleType(&oTypes, "VEGREKKVERKTYPE", "vegrekkverkType", OFTString);
-    
+
       addSimpleType(&oTypes, "VEGSPERRINGTYPE", "vegsperringtype", OFTString);
-    
+
       addSimpleType(&oTypes, "VEGSTATUS", "vegstatus", OFTString);
-    
+
       addSimpleType(&oTypes, "VERDI", "verdi", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VERDI1", "verdi", OFTString);
-    
+
       addSimpleType(&oTypes, "VERDI2", "tilVerdi", OFTString);
-    
+
       addSimpleType(&oTypes, "VERDIANNA", "verdiAnnenUtnyttelseGrunn", OFTReal);
-    
+
       addSimpleType(&oTypes, "VERDIBEITE", "verdiBeiterett", OFTReal);
-    
+
       addSimpleType(&oTypes, "VERDIGRUNN", "verdiGrunn", OFTReal);
-    
+
       addSimpleType(&oTypes, "VERDIJAKT", "verdiJaktrett", OFTReal);
-    
+
       addSimpleType(&oTypes, "VERDISKOG", "verdiSkogProduksjon", OFTReal);
-    
+
       addSimpleType(&oTypes, "VERIFISERINGSDATO", "verifiseringsdato", OFTDateTime);
-    
+
       addSimpleType(&oTypes, "VERN_FORMAL", "verneFormål", OFTString);
-    
+
       addSimpleType(&oTypes, "VERN_LOV", "vernelov", OFTString);
-    
+
       addSimpleType(&oTypes, "VERN_MOT", "vernskogType", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VERN_PARA", "verneparagraf", OFTString);
-    
+
       addSimpleType(&oTypes, "VERNEDATO", "vernedato", OFTDate);
-    
+
       addSimpleType(&oTypes, "VERNEFORM", "verneform", OFTString);
-    
+
       addSimpleType(&oTypes, "VERNEPLAN", "verneplan", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VERNTEMA", "verneTema", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VERNTYPE", "vernetype", OFTString);
-    
+
       addSimpleType(&oTypes, "VERSJON", "versjon", OFTString);
-    
+
       addSimpleType(&oTypes, "VERT_BÆREKONSTR", "vertikalBærekonstruksjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VERTNIV", "vertikalnivå", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VFLATE", "delteigKlassifisering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VFRADATO", "veglenkeFraDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "VIKTIG", "viktighet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VINDRETN", "vindretning", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VINKELENHET", "vinkelenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "VIRKSOMHET", "typeRastoffVirksomhet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VISUELLTYDELIGHET", "visuellTydelighet", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VKJORFLT", "feltoversikt", OFTString);
-    
+
       addSimpleType(&oTypes, "VKRETSNAVN", "valgkretsnavn", OFTString);
-    
+
       addSimpleType(&oTypes, "VKRETSNR", "valgkretsnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VLENKEID", "veglenkeIdentifikasjon", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VOLUM_M3", "rastoffVolum", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VOLUMENHET", "volumenhet", OFTString);
-    
+
       addSimpleType(&oTypes, "VOLUMINNSJØ", "volumInnsjø", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VRAKTYP", "vraktype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "VTILDATO", "veglenkeTilDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "VURDERING", "vurdering", OFTString);
-    
+
       addSimpleType(&oTypes, "VURDERTDATO", "vurdertDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "VÆSKETYPE", "petroleumsvæsketype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "WRBKODE", "WRBgruppe", OFTString);
-    
+
       addSimpleType(&oTypes, "YTTERVEGG", "yttervegg", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ØST", "øst", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ÅPNESDATO", "åpnesDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "ÅR", "årstall", OFTInteger);
-    
+
       addSimpleType(&oTypes, "ÅRSTIDBRUK", "årstidbruk", OFTString);
-    
+
       addSimpleType(&oTypes, "VEDTAKENDELIGPLANDATO", "vedtakEndeligPlanDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "KUNNGJØRINGSDATO", "kunngjøringsdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "KPBESTEMMELSEHJEMMEL", "kpBestemmelseHjemmel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "RPBESTEMMELSEHJEMMEL", "rpBestemmelseHjemmel", OFTInteger);
-    
+
       addSimpleType(&oTypes, "CCDBRIKKELENGDE", "ccdBrikkelengde", OFTInteger);
-    
+
       addSimpleType(&oTypes, "CCDBRIKKESIDE", "ccdBrikkeside", OFTInteger);
-    
+
       addSimpleType(&oTypes, "BILDEOPPLØSNING", "bildeoppløsning", OFTReal);
-    
+
       addSimpleType(&oTypes, "BILDEFILFORMAT", "bildefilformat", OFTInteger);
-    
+
       addSimpleType(&oTypes, "STATLIGNR", "statlignummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "AEROTRIANGULERING", "aerotriangulering", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PROSJEKTRAPPORTLINK", "prosjektrapportlink", OFTString);
-    
+
       addSimpleType(&oTypes, "BILDEFILIR", "bildefilIr", OFTString);
-    
+
       addSimpleType(&oTypes, "BILDEFILPAN", "bildefilPan", OFTString);
-    
+
       addSimpleType(&oTypes, "BILDEFILRGB", "bildefilRGB", OFTString);
-    
+
       addSimpleType(&oTypes, "BILDEFILMULTI", "bildefilMulti", OFTString);
-    
+
       addSimpleType(&oTypes, "ORTOFOTOTYPE", "ortofototype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "KAMERALØPENUMMER", "løpenummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "PRODUKSJONSRAPPORTLINK", "produksjonsrapportlink", OFTString);
-    
+
       addSimpleType(&oTypes, "PRODUKTSPESIFIKASJONSLINK", "produktspesifikasjonslink", OFTString);
-    
+
       addSimpleType(&oTypes, "SAKSÅR", "saksår", OFTInteger);
-    
+
       addSimpleType(&oTypes, "SEKVENSNUMMER", "sekvensnummer", OFTInteger);
-    
+
       addSimpleType(&oTypes, "UTNTALL_MIN", "utnyttingstall_minimum", OFTReal);
-    
+
       addSimpleType(&oTypes, "GYLDIGTILDATO", "gyldigTilDato", OFTDate);
-    
+
       addSimpleType(&oTypes, "PIXELSTØRRELSE", "pixelstørrelse", OFTReal);
-    
+
       addSimpleType(&oTypes, "HENDELSESDATO", "Hendelsesdato", OFTDate);
-    
+
       addSimpleType(&oTypes, "NPPLANBESTEMMELSETYPE", "planbestemmelsetype", OFTInteger);
-    
+
       addSimpleType(&oTypes, "NPPLANTEMA", "planTema", OFTInteger);
-    
+
       addSimpleType(&oTypes, "FAGOMRÅDE_LINK", "link til fagområde", OFTString);
-    
+
       addSimpleType(&oTypes, "PRODUKT_LINK", "produktLink", OFTString);
-    
 
 OGRSOSIDataType ADRESSEBRUKSENHETType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType ADRESSEKOMMENTARType = OGRSOSIDataType(5);
-     
+
 OGRSOSIDataType ADRESSEREFERANSEType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType ADRESSETILLEGGType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType AIDType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType AJOURFOeRINGType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType AKVA_KONS_INFOType = OGRSOSIDataType(7);
-     
+
 OGRSOSIDataType AKVA_PROeVE_INFOType = OGRSOSIDataType(9);
-     
+
 OGRSOSIDataType ANDELType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType AREALFORDELINGType = OGRSOSIDataType(5);
-     
+
 OGRSOSIDataType BELASTNINGBOF5Type = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType BELASTNINGFOSFORType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType BEREGNETAREALType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType BILDEINFORMASJONType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType BMARTOBSType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType BMARTREGType = OGRSOSIDataType(8);
-     
+
 OGRSOSIDataType BMKILDEType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType BMNATYPTILLEGGType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType BRUKSENHETType = OGRSOSIDataType(10);
-     
+
 OGRSOSIDataType BYDELIDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType BYGG_KOMMENTARERType = OGRSOSIDataType(5);
-     
+
 OGRSOSIDataType BYGN_STAT_HISTType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType BYGNING_TILLEGGType = OGRSOSIDataType(15);
-     
+
 OGRSOSIDataType BYGNINGSREFType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType DELOMRAaDEIDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType DPOT_GRASType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType DPOT_KORNType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType DPOT_POTETType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType EKOORDType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType ENDRINGSFLAGGType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType ENDRINGSVURDERINGType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType ETASJEType = OGRSOSIDataType(8);
-     
+
 OGRSOSIDataType ETASJEDATAType = OGRSOSIDataType(6);
-     
+
 OGRSOSIDataType FELTREGISTRERTType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType FIRMA_EIERType = OGRSOSIDataType(7);
-     
+
 OGRSOSIDataType FISKE_BEDR_IDType = OGRSOSIDataType(6);
-     
+
 OGRSOSIDataType FISKE_BEDR_INFOType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType FISKE_BEDR_MARKEDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType FISKE_BEDR_TJENESTEType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType FISKERI_REDSKAPType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType FISKERI_RESS_ARTType = OGRSOSIDataType(6);
-     
+
 OGRSOSIDataType FISKERI_RESSURSType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType FMDATOType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType FMIDNYType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType FMSIGNType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType FMSTATUSType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType FMTYPEType = OGRSOSIDataType(5);
-     
+
 OGRSOSIDataType FORUR_GRUNN_EIENDOMType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType GRENSE_MELLOMType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType GRUNNKRETSIDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType HAVNE_D_INFOType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType HOVEDMAaLRUBRIKKType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType HOVEDNRType = OGRSOSIDataType(2); // Note: fixed manually by E.Rouault. Was 1 initially, but Valgrind complained
-     
+
 OGRSOSIDataType HYTTEINFORMASJONType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType JORDTYPEType = OGRSOSIDataType(6);
-     
+
 OGRSOSIDataType JREGMARKType = OGRSOSIDataType(10);
-     
+
 OGRSOSIDataType JREGTEIGType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType KAI_INFOType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType KAMERAINFORMASJONType = OGRSOSIDataType(9);
-     
+
 OGRSOSIDataType KM_DAT_INFOType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType KM_DATERINGType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType KOMMUNALKRETSType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType KOPIDATAType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType KOPLINGType = OGRSOSIDataType(8);
-     
+
 OGRSOSIDataType KURSLINJE_INFOType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType KVALITETType = OGRSOSIDataType(6);
-     
+
 OGRSOSIDataType LEDNINGType = OGRSOSIDataType(8);
-     
+
 OGRSOSIDataType LEGGEAaRType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType LGIDType = OGRSOSIDataType(8);
-     
+
 OGRSOSIDataType MATRIKKELADRESSEIDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType MATRIKKELNUMMERType = OGRSOSIDataType(5);
-     
+
 OGRSOSIDataType OVERLAPPType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType POSTType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType REGISTRERINGSVERSJONType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType RESIPIENTType = OGRSOSIDataType(5);
-     
+
 OGRSOSIDataType RETNINGType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType ROeR_DIMENSJONType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType SAKType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType SEFRAK_IDType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType SEFRAKFUNKSJONType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType SENTRUMSSONEIDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType SERVType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType SKRETSIDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType SP_ADMType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType SP_AKLASSType = OGRSOSIDataType(6);
-     
+
 OGRSOSIDataType SP_BESTANDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType SP_BSKRIVType = OGRSOSIDataType(13);
-     
+
 OGRSOSIDataType SP_FLBRELEMType = OGRSOSIDataType(5);
-     
+
 OGRSOSIDataType SP_GRLVOLType = OGRSOSIDataType(8);
-     
+
 OGRSOSIDataType SP_TEIGType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType SP_TERKLASSType = OGRSOSIDataType(5);
-     
+
 OGRSOSIDataType SP_TETTHOYDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType SP_TILTAKType = OGRSOSIDataType(5);
-     
+
 OGRSOSIDataType SP_TILVVOLType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType SP_TRESLType = OGRSOSIDataType(8);
-     
+
 OGRSOSIDataType TETTSTEDIDType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType UNIVERSELLUTFORMINGType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType UTNYTTType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType UTSLIPPType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType UTV_TILL_PARTType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType VERNType = OGRSOSIDataType(4);
-     
+
 OGRSOSIDataType VKRETSType = OGRSOSIDataType(2);
-     
+
 OGRSOSIDataType VNRType = OGRSOSIDataType(3);
-     
+
 OGRSOSIDataType VPAType = OGRSOSIDataType(3);
-     ADRESSEBRUKSENHETType.setElement(1, "etasjenummer", OFTInteger); 
-   ADRESSEBRUKSENHETType.setElement(2, "etasjeplan", OFTString); 
-   ADRESSEBRUKSENHETType.setElement(0, "bruksenhetLøpenr", OFTInteger); 
-   ADRESSEKOMMENTARType.setElement(0, "etat", OFTString); 
-   ADRESSEKOMMENTARType.setElement(2, "kommentar", OFTString); 
-   ADRESSEKOMMENTARType.setElement(1, "kommentarType", OFTString); 
-   ADRESSEKOMMENTARType.setElement(4, "lagretDato", OFTDate); 
-   ADRESSEKOMMENTARType.setElement(3, "saksnummer", OFTInteger); 
-   ADRESSEREFERANSEType.setElement(1, "adresseReferansekode", OFTString); 
-   ADRESSEREFERANSEType.setElement(0, "referanse", OFTString); 
-   ADRESSETILLEGGType.setElement(1, "adresseKommentar", OFTString); 
-   ADRESSETILLEGGType.setElement(2, "adresseReferanse", OFTString); 
-   ADRESSETILLEGGType.setElement(0, "kartbladindeks", OFTString); 
-   AIDType.setElement(2, "bokstav", OFTString); 
-   AIDType.setElement(0, "gatenummer", OFTInteger); 
-   AIDType.setElement(1, "husnummer", OFTInteger); 
-   AJOURFOeRINGType.setElement(1, "ajourførtAv", OFTString); 
-   AJOURFOeRINGType.setElement(0, "ajourførtDato", OFTDate); 
-   AKVA_KONS_INFOType.setElement(1, "akvaKonsesjonsnummer", OFTInteger); 
-   AKVA_KONS_INFOType.setElement(4, "konsesjonsstatus", OFTString); 
-   AKVA_KONS_INFOType.setElement(6, "konsesjonstype", OFTString); 
-   AKVA_KONS_INFOType.setElement(5, "konsesjonsformål", OFTString); 
-   AKVA_KONS_INFOType.setElement(0, "fiskebruksnummerFylke", OFTString); 
-   AKVA_KONS_INFOType.setElement(2, "lokalitetsnavn", OFTString); 
-   AKVA_KONS_INFOType.setElement(3, "lokalitetsnummer", OFTInteger); 
-   AKVA_PROeVE_INFOType.setElement(7, "akvaTemperatur", OFTInteger); 
-   AKVA_PROeVE_INFOType.setElement(1, "algekonsentrasjon", OFTInteger); 
-   AKVA_PROeVE_INFOType.setElement(0, "algetype", OFTString); 
-   AKVA_PROeVE_INFOType.setElement(5, "klorofyllMaksimum", OFTInteger); 
-   AKVA_PROeVE_INFOType.setElement(8, "salinitet", OFTInteger); 
-   AKVA_PROeVE_INFOType.setElement(6, "sikteDyp", OFTInteger); 
-   AKVA_PROeVE_INFOType.setElement(2, "strømretning", OFTInteger); 
-   AKVA_PROeVE_INFOType.setElement(4, "vindretning", OFTInteger); 
-   ANDELType.setElement(1, "nevner", OFTReal); 
-   ANDELType.setElement(0, "teller", OFTReal); 
-   AREALFORDELINGType.setElement(4, "prosentElv", OFTReal); 
-   AREALFORDELINGType.setElement(2, "prosentHav", OFTReal); 
-   AREALFORDELINGType.setElement(3, "prosentInnsjø", OFTReal); 
-   AREALFORDELINGType.setElement(1, "prosentLand", OFTReal); 
-   AREALFORDELINGType.setElement(0, "totalarealKm2", OFTReal); 
-   BELASTNINGBOF5Type.setElement(2, "andrekilderBelastning", OFTInteger); 
-   BELASTNINGBOF5Type.setElement(0, "husholdBelastning", OFTInteger); 
-   BELASTNINGBOF5Type.setElement(1, "industriBelastning", OFTInteger); 
-   BELASTNINGBOF5Type.setElement(3, "totalbelastning", OFTInteger); 
-   BELASTNINGFOSFORType.setElement(2, "andrekilderBelastning", OFTInteger); 
-   BELASTNINGFOSFORType.setElement(0, "husholdBelastning", OFTInteger); 
-   BELASTNINGFOSFORType.setElement(1, "industriBelastning", OFTInteger); 
-   BELASTNINGFOSFORType.setElement(3, "totalbelastning", OFTInteger); 
-   BEREGNETAREALType.setElement(0, "areal", OFTReal); 
-   BEREGNETAREALType.setElement(1, "arealmerknad", OFTString); 
-   BILDEINFORMASJONType.setElement(1, "brennvidde", OFTReal); 
-   BILDEINFORMASJONType.setElement(2, "fotograf", OFTString); 
-   BILDEINFORMASJONType.setElement(0, "kameratype", OFTString); 
-   BMARTOBSType.setElement(1, "bmAntall", OFTInteger); 
-   BMARTOBSType.setElement(0, "bmArt", OFTString); 
-   BMARTOBSType.setElement(2, "bmEnhet", OFTInteger); 
-   BMARTOBSType.setElement(3, "bmRegistreringsdato", OFTDate); 
-   BMARTREGType.setElement(6, "bmÅrstid", OFTInteger); 
-   BMARTREGType.setElement(0, "bmArt", OFTString); 
-   BMARTREGType.setElement(2, "bmOmrådefunksjon", OFTInteger); 
-   BMARTREGType.setElement(5, "bmFunksjonskvalitet", OFTInteger); 
-   BMARTREGType.setElement(7, "bmKilde", OFTString); 
-   BMARTREGType.setElement(1, "bmRegistreringsdato", OFTDate); 
-   BMARTREGType.setElement(3, "bmTruethetskategori", OFTString); 
-   BMARTREGType.setElement(4, "bmViltvekt", OFTInteger); 
-   BMKILDEType.setElement(1, "bmKildetype", OFTInteger); 
-   BMKILDEType.setElement(0, "bmKildevurdering", OFTInteger); 
-   BMNATYPTILLEGGType.setElement(1, "bmAndel", OFTInteger); 
-   BMNATYPTILLEGGType.setElement(0, "bmNaturtype", OFTString); 
-   BRUKSENHETType.setElement(7, "antallBad", OFTInteger); 
-   BRUKSENHETType.setElement(6, "antallRom", OFTInteger); 
-   BRUKSENHETType.setElement(8, "antallWC", OFTInteger); 
-   BRUKSENHETType.setElement(5, "bruksareal", OFTReal); 
-   BRUKSENHETType.setElement(4, "bruksenhetstype", OFTString); 
-   BRUKSENHETType.setElement(2, "etasjenummer", OFTInteger); 
-   BRUKSENHETType.setElement(1, "etasjeplan", OFTString); 
-   BRUKSENHETType.setElement(9, "kjøkkenTilgang", OFTInteger); 
-   BRUKSENHETType.setElement(3, "bruksenhetLøpenr", OFTInteger); 
-   BRUKSENHETType.setElement(0, "matrikkelnummer", OFTString); 
-   BYDELIDType.setElement(0, "bydelsnavn", OFTString); 
-   BYDELIDType.setElement(1, "bydelsnummer", OFTInteger); 
-   BYGG_KOMMENTARERType.setElement(3, "bygnSaksnr", OFTString); 
-   BYGG_KOMMENTARERType.setElement(0, "etat", OFTString); 
-   BYGG_KOMMENTARERType.setElement(2, "kommentar", OFTString); 
-   BYGG_KOMMENTARERType.setElement(1, "kommentarType", OFTString); 
-   BYGG_KOMMENTARERType.setElement(4, "lagretDato", OFTDate); 
-   BYGN_STAT_HISTType.setElement(0, "bygningsstatus", OFTString); 
-   BYGN_STAT_HISTType.setElement(1, "bygningshistorikkDato", OFTDate); 
-   BYGN_STAT_HISTType.setElement(2, "registrertDato", OFTDate); 
-   BYGNING_TILLEGGType.setElement(0, "alternativtArealBygning", OFTReal); 
-   BYGNING_TILLEGGType.setElement(1, "antallEtasjer", OFTInteger); 
-   BYGNING_TILLEGGType.setElement(2, "antallRøkløp", OFTReal); 
-   BYGNING_TILLEGGType.setElement(3, "brenseltankNedgravd", OFTInteger); 
-   BYGNING_TILLEGGType.setElement(14, "bygningKommentar", OFTString); 
-   BYGNING_TILLEGGType.setElement(13, "bygningsreferanse", OFTString); 
-   BYGNING_TILLEGGType.setElement(9, "fundamentering", OFTInteger); 
-   BYGNING_TILLEGGType.setElement(12, "horisontalBærekonstr", OFTInteger); 
-   BYGNING_TILLEGGType.setElement(5, "kartbladindeks", OFTString); 
-   BYGNING_TILLEGGType.setElement(6, "kildePrivatVannforsyning", OFTInteger); 
-   BYGNING_TILLEGGType.setElement(10, "materialeIYttervegg", OFTInteger); 
-   BYGNING_TILLEGGType.setElement(7, "privatKloakkRensing", OFTInteger); 
-   BYGNING_TILLEGGType.setElement(8, "renovasjon", OFTInteger); 
-   BYGNING_TILLEGGType.setElement(4, "septiktank", OFTString); 
-   BYGNING_TILLEGGType.setElement(11, "vertikalBærekonstr", OFTInteger); 
-   BYGNINGSREFType.setElement(1, "bygningReferansetype", OFTString); 
-   BYGNINGSREFType.setElement(0, "referanse", OFTString); 
-   DELOMRAaDEIDType.setElement(0, "delområdenavn", OFTString); 
-   DELOMRAaDEIDType.setElement(1, "delområdenummer", OFTString); 
-   DPOT_GRASType.setElement(2, "nedbørsbasert", OFTInteger); 
-   DPOT_GRASType.setElement(3, "nedklassifiseringNedbør", OFTInteger); 
-   DPOT_GRASType.setElement(0, "vanningsbasert", OFTInteger); 
-   DPOT_GRASType.setElement(1, "nedklassifiseringVanning", OFTInteger); 
-   DPOT_KORNType.setElement(2, "nedbørsbasert", OFTInteger); 
-   DPOT_KORNType.setElement(3, "nedklassifiseringNedbør", OFTInteger); 
-   DPOT_KORNType.setElement(0, "vanningsbasert", OFTInteger); 
-   DPOT_KORNType.setElement(1, "nedklassifiseringVanning", OFTInteger); 
-   DPOT_POTETType.setElement(2, "nedbørsbasert", OFTInteger); 
-   DPOT_POTETType.setElement(3, "nedklassifiseringNedbør", OFTInteger); 
-   DPOT_POTETType.setElement(0, "vanningsbasert", OFTInteger); 
-   DPOT_POTETType.setElement(1, "nedklassifiseringVanning", OFTInteger); 
-   EKOORDType.setElement(2, "jordregisterKoordinatHøyde", OFTInteger); 
-   EKOORDType.setElement(0, "jordregisterKoordinatNord", OFTInteger); 
-   EKOORDType.setElement(1, "jordregisterKoordinatØst", OFTInteger); 
-   ENDRINGSFLAGGType.setElement(1, "tidspunktEndring", OFTDateTime); 
-   ENDRINGSFLAGGType.setElement(0, "typeEndring", OFTString); 
-   ENDRINGSVURDERINGType.setElement(0, "endringsgrad", OFTString); 
-   ENDRINGSVURDERINGType.setElement(1, "vurdertDato", OFTDate); 
-   ETASJEType.setElement(2, "antallBoenheter", OFTInteger); 
-   ETASJEType.setElement(4, "bruksarealTilAnnet", OFTReal); 
-   ETASJEType.setElement(3, "bruksarealTilBolig", OFTReal); 
-   ETASJEType.setElement(5, "bruksarealTotalt", OFTReal); 
-   ETASJEType.setElement(1, "etasjenummer", OFTInteger); 
-   ETASJEType.setElement(0, "etasjeplan", OFTString); 
-   ETASJEType.setElement(6, "kommAlternativtAreal", OFTReal); 
-   ETASJEType.setElement(7, "kommAlternativtAreal2", OFTReal); 
-   ETASJEDATAType.setElement(4, "sumAlternativtAreal", OFTReal); 
-   ETASJEDATAType.setElement(5, "sumAlternativtAreal2", OFTReal); 
-   ETASJEDATAType.setElement(0, "sumAntallBoenheter", OFTInteger); 
-   ETASJEDATAType.setElement(3, "sumBruksarealTotalt", OFTReal); 
-   ETASJEDATAType.setElement(2, "sumBruksarealTilAnnet", OFTReal); 
-   ETASJEDATAType.setElement(1, "sumBruksarealTilBolig", OFTReal); 
-   FELTREGISTRERTType.setElement(2, "ajourføring", OFTString); 
-   FELTREGISTRERTType.setElement(1, "datafangstdato", OFTDateTime); 
-   FELTREGISTRERTType.setElement(0, "feltregistrertAv", OFTString); 
-   FIRMA_EIERType.setElement(2, "adresse", OFTString); 
-   FIRMA_EIERType.setElement(0, "firmanavn", OFTString); 
-   FIRMA_EIERType.setElement(1, "bedriftseier", OFTString); 
-   FIRMA_EIERType.setElement(6, "kontaktperson", OFTString); 
-   FIRMA_EIERType.setElement(3, "postnummer", OFTInteger); 
-   FIRMA_EIERType.setElement(5, "telefaxnummer", OFTInteger); 
-   FIRMA_EIERType.setElement(4, "telefonnummer", OFTInteger); 
-   FISKE_BEDR_IDType.setElement(4, "antallAnsatte", OFTInteger); 
-   FISKE_BEDR_IDType.setElement(5, "antallÅrsverk", OFTInteger); 
-   FISKE_BEDR_IDType.setElement(0, "fiskebedriftsnavn", OFTString); 
-   FISKE_BEDR_IDType.setElement(2, "fiskebruksnummer", OFTInteger); 
-   FISKE_BEDR_IDType.setElement(1, "fiskebruksnummerFylke", OFTString); 
-   FISKE_BEDR_IDType.setElement(3, "firmaeier", OFTString); 
-   FISKE_BEDR_INFOType.setElement(1, "artskode", OFTInteger); 
-   FISKE_BEDR_INFOType.setElement(0, "fisketype", OFTInteger); 
-   FISKE_BEDR_MARKEDType.setElement(0, "fiskebedriftsandel", OFTInteger); 
-   FISKE_BEDR_MARKEDType.setElement(1, "fiskebedriftsområde", OFTInteger); 
-   FISKE_BEDR_TJENESTEType.setElement(2, "fiskebedriftservice", OFTInteger); 
-   FISKE_BEDR_TJENESTEType.setElement(1, "fiskekapasitetEnhet", OFTInteger); 
-   FISKE_BEDR_TJENESTEType.setElement(0, "fiskekapasitet", OFTInteger); 
-   FISKERI_REDSKAPType.setElement(0, "fiskeriredskapGenAktiv", OFTInteger); 
-   FISKERI_REDSKAPType.setElement(1, "fiskeriredskapGenPassiv", OFTInteger); 
-   FISKERI_REDSKAPType.setElement(2, "fiskeriredskapSpesAktiv", OFTInteger); 
-   FISKERI_REDSKAPType.setElement(3, "fiskeriredskapSpesPassiv", OFTInteger); 
-   FISKERI_RESS_ARTType.setElement(3, "engelskArtsnavn", OFTString); 
-   FISKERI_RESS_ARTType.setElement(2, "vitenskapeligArtsnavn", OFTString); 
-   FISKERI_RESS_ARTType.setElement(1, "norskArtsnavn", OFTString); 
-   FISKERI_RESS_ARTType.setElement(0, "taksonomiskKode", OFTInteger); 
-   FISKERI_RESS_ARTType.setElement(4, "faoKode", OFTString); 
-   FISKERI_RESS_ARTType.setElement(5, "artskode", OFTInteger); 
-   FISKERI_RESSURSType.setElement(0, "fiskeriressursområdeArt", OFTString); 
-   FISKERI_RESSURSType.setElement(1, "periode", OFTString); 
-   FMDATOType.setElement(1, "beregningsDato", OFTDate); 
-   FMDATOType.setElement(0, "fastmerkeEtableringsdato", OFTDate); 
-   FMIDNYType.setElement(1, "fastmerkeInstitusjon", OFTString); 
-   FMIDNYType.setElement(0, "fastmerkeKommune", OFTInteger); 
-   FMIDNYType.setElement(2, "fastmerkeNummer", OFTString); 
-   FMIDNYType.setElement(3, "indikatorFastmerkenummer", OFTString); 
-   FMSIGNType.setElement(1, "signalHøyde", OFTReal); 
-   FMSIGNType.setElement(0, "signalType", OFTString); 
-   FMSTATUSType.setElement(1, "typeStatus", OFTInteger); 
-   FMSTATUSType.setElement(0, "verifiseringsdato", OFTDateTime); 
-   FMTYPEType.setElement(0, "boltType", OFTInteger); 
-   FMTYPEType.setElement(3, "fastmerkeDiameter", OFTInteger); 
-   FMTYPEType.setElement(4, "gravertTekst", OFTString); 
-   FMTYPEType.setElement(1, "materialeBolt", OFTInteger); 
-   FMTYPEType.setElement(2, "fastmerkeUnderlag", OFTInteger); 
-   FORUR_GRUNN_EIENDOMType.setElement(1, "arealbrukRestriksjon", OFTInteger); 
-   FORUR_GRUNN_EIENDOMType.setElement(0, "matrikkelnummer", OFTString); 
-   GRENSE_MELLOMType.setElement(0, "førsteLand", OFTString); 
-   GRENSE_MELLOMType.setElement(1, "annetLand", OFTString); 
-   GRUNNKRETSIDType.setElement(1, "grunnkretsnavn", OFTString); 
-   GRUNNKRETSIDType.setElement(0, "grunnkretsnummer", OFTInteger); 
-   HAVNE_D_INFOType.setElement(1, "havnedistriktAdministrasjon", OFTInteger); 
-   HAVNE_D_INFOType.setElement(0, "kommune", OFTInteger); 
-   HOVEDMAaLRUBRIKKType.setElement(1, "bredde", OFTInteger); 
-   HOVEDMAaLRUBRIKKType.setElement(0, "lengde", OFTInteger); 
-   HOVEDNRType.setElement(1, " kommunenummer", OFTInteger); 
-   HOVEDNRType.setElement(0, "matrikkelnummer", OFTString); 
-   HYTTEINFORMASJONType.setElement(1, "betjeningsgrad", OFTString); 
-   HYTTEINFORMASJONType.setElement(0, "hytteId", OFTInteger); 
-   HYTTEINFORMASJONType.setElement(2, "hytteeier", OFTInteger); 
-   JORDTYPEType.setElement(0, "serie1", OFTString); 
-   JORDTYPEType.setElement(2, "serie2", OFTString); 
-   JORDTYPEType.setElement(4, "serie3", OFTString); 
-   JORDTYPEType.setElement(1, "tekstur1", OFTString); 
-   JORDTYPEType.setElement(3, "tekstur2", OFTString); 
-   JORDTYPEType.setElement(5, "tekstur3", OFTString); 
-   JREGMARKType.setElement(1, "potensiellSkogbonitetOmkodet", OFTInteger); 
-   JREGMARKType.setElement(0, "arealtilstand", OFTInteger); 
-   JREGMARKType.setElement(7, "jordregisterDyrkingsjord", OFTString); 
-   JREGMARKType.setElement(6, "jordregisterFreg", OFTInteger); 
-   JREGMARKType.setElement(5, "jordregisterLreg", OFTString); 
-   JREGMARKType.setElement(3, "jordklassifikasjon", OFTInteger); 
-   JREGMARKType.setElement(4, "myrklassifikasjon", OFTInteger); 
-   JREGMARKType.setElement(8, "jordregisterSkogtype", OFTInteger); 
-   JREGMARKType.setElement(9, "jordregisterSkogreisningsmark", OFTInteger); 
-   JREGMARKType.setElement(2, "tilleggsopplysningerSkog", OFTInteger); 
-   JREGTEIGType.setElement(2, "jordregisterDriftssenter", OFTInteger); 
-   JREGTEIGType.setElement(3, "jordregisterStatusEiendom", OFTInteger); 
-   JREGTEIGType.setElement(0, "matrikkelnummer", OFTString); 
-   JREGTEIGType.setElement(1, "jordregisterEiendomTeigNummer", OFTInteger); 
-   KAI_INFOType.setElement(1, "kaiDybde", OFTReal); 
-   KAI_INFOType.setElement(0, "kaiType", OFTInteger); 
-   KAI_INFOType.setElement(2, "kommunenummer", OFTInteger); 
-   KAMERAINFORMASJONType.setElement(4, "bildekategori", OFTInteger); 
-   KAMERAINFORMASJONType.setElement(3, "brennvidde", OFTReal); 
-   KAMERAINFORMASJONType.setElement(7, "film", OFTString); 
-   KAMERAINFORMASJONType.setElement(8, "kalibreringsrapport", OFTString); 
-   KAMERAINFORMASJONType.setElement(1, "kameratype", OFTString); 
-   KAMERAINFORMASJONType.setElement(0, "opptaksmetode", OFTInteger); 
-   KM_DAT_INFOType.setElement(0, "sefrakTiltak", OFTInteger); 
-   KM_DAT_INFOType.setElement(1, "tidsangivelse", OFTInteger); 
-   KM_DATERINGType.setElement(0, "kulturminneDatering", OFTString); 
-   KM_DATERINGType.setElement(1, "kulturminneDateringKvalitet", OFTString); 
-   KOMMUNALKRETSType.setElement(3, "kretsnavn", OFTString); 
-   KOMMUNALKRETSType.setElement(2, "kretsnummer", OFTString); 
-   KOMMUNALKRETSType.setElement(0, "kretstypekode", OFTString); 
-   KOMMUNALKRETSType.setElement(1, "kretstypenavn", OFTString); 
-   KOPIDATAType.setElement(2, "kopidato", OFTDateTime); 
-   KOPIDATAType.setElement(0, "områdeId", OFTInteger); 
-   KOPIDATAType.setElement(1, "originalDatavert", OFTString); 
-   KOPLINGType.setElement(1, "fagområde", OFTInteger); 
-   KOPLINGType.setElement(4, "bruksområde", OFTString); 
-   KOPLINGType.setElement(2, "koplingskategori", OFTInteger); 
-   KOPLINGType.setElement(0, "koplingsnavn", OFTString); 
-   KOPLINGType.setElement(3, "koplingstype", OFTString); 
-   KOPLINGType.setElement(7, "bildelink", OFTString); 
-   KOPLINGType.setElement(5, "materiellkode", OFTString); 
-   KOPLINGType.setElement(6, "verdi", OFTInteger); 
-   KURSLINJE_INFOType.setElement(0, "fartøyIdentifikasjon", OFTString); 
-   KURSLINJE_INFOType.setElement(1, "satellittkommunikasjonsId", OFTString); 
-   KURSLINJE_INFOType.setElement(3, "sporhastighet", OFTInteger); 
-   KURSLINJE_INFOType.setElement(2, "tidspunkt", OFTDateTime); 
-   KVALITETType.setElement(3, "målemetodeHøyde", OFTInteger); 
-   KVALITETType.setElement(4, "nøyaktighetHøyde", OFTInteger); 
-   KVALITETType.setElement(5, "maksimaltAvvik", OFTInteger); 
-   KVALITETType.setElement(0, "målemetode", OFTInteger); 
-   KVALITETType.setElement(1, "nøyaktighet", OFTInteger); 
-   KVALITETType.setElement(2, "synbarhet", OFTInteger); 
-   LEDNINGType.setElement(1, "fagområde", OFTInteger); 
-   LEDNINGType.setElement(3, "bruksområde", OFTString); 
-   LEDNINGType.setElement(0, "ledningsnavn", OFTString); 
-   LEDNINGType.setElement(2, "ledningstype", OFTInteger); 
-   LEDNINGType.setElement(7, "leggeår", OFTString); 
-   LEDNINGType.setElement(6, "lengde", OFTReal); 
-   LEDNINGType.setElement(5, "materiellkode", OFTString); 
-   LEDNINGType.setElement(4, "nettnivå", OFTString); 
-   LEGGEAaRType.setElement(0, "alderReferanse", OFTInteger); 
-   LEGGEAaRType.setElement(1, "årstall", OFTInteger); 
-   LGIDType.setElement(7, "landbruksregAktiv", OFTInteger); 
-   LGIDType.setElement(6, "landbruksregType", OFTInteger); 
-   LGIDType.setElement(0, "matrikkelnummer", OFTString); 
-   MATRIKKELADRESSEIDType.setElement(0, "matrikkelnummer", OFTString); 
-   MATRIKKELADRESSEIDType.setElement(1, "undernr", OFTInteger); 
-   MATRIKKELNUMMERType.setElement(2, "bruksnummer", OFTInteger); 
-   MATRIKKELNUMMERType.setElement(3, "festenummer", OFTInteger); 
-   MATRIKKELNUMMERType.setElement(1, "gårdsnummer", OFTInteger); 
-   MATRIKKELNUMMERType.setElement(0, "matrikkelkommune", OFTInteger); 
-   MATRIKKELNUMMERType.setElement(4, "seksjonsnummer", OFTInteger); 
-   OVERLAPPType.setElement(0, "lengdeoverlapp", OFTInteger); 
-   OVERLAPPType.setElement(1, "sideoverlapp", OFTInteger); 
-   POSTType.setElement(1, "poststedsnavn", OFTString); 
-   POSTType.setElement(0, "postnummer", OFTInteger); 
-   REGISTRERINGSVERSJONType.setElement(0, "produkt", OFTString); 
-   REGISTRERINGSVERSJONType.setElement(1, "versjon", OFTString); 
-   RESIPIENTType.setElement(2, "fjordId", OFTString); 
-   RESIPIENTType.setElement(0, "resipientnavn", OFTString); 
-   RESIPIENTType.setElement(4, "resipienttype", OFTString); 
-   RESIPIENTType.setElement(1, "vassdragsnummer", OFTString); 
-   RESIPIENTType.setElement(3, "vatnLøpenummer", OFTInteger); 
-   RETNINGType.setElement(1, "retningsenhet", OFTInteger); 
-   RETNINGType.setElement(2, "retningsreferanse", OFTInteger); 
-   RETNINGType.setElement(0, "retningsverdi", OFTReal); 
-   ROeR_DIMENSJONType.setElement(1, "lengdeenhet", OFTString); 
-   ROeR_DIMENSJONType.setElement(0, "måltall", OFTReal); 
-   SAKType.setElement(3, "vedtaksmyndighet", OFTString); 
-   SAKType.setElement(0, "saksnummer", OFTInteger); 
-   SAKType.setElement(2, "utvalgssaksnummer", OFTInteger); 
-   SAKType.setElement(1, "vedtaksdato", OFTDate); 
-   SEFRAK_IDType.setElement(2, "husLøpenr", OFTInteger); 
-   SEFRAK_IDType.setElement(1, "registreringKretsnr", OFTInteger); 
-   SEFRAK_IDType.setElement(0, "SEFRAKkommune", OFTInteger); 
-   SEFRAKFUNKSJONType.setElement(0, "sefrakFunksjonskode", OFTInteger); 
-   SEFRAKFUNKSJONType.setElement(1, "sefrakFunksjonsstatus", OFTString); 
-   SENTRUMSSONEIDType.setElement(1, "sentrumssonenavn", OFTString); 
-   SENTRUMSSONEIDType.setElement(0, "sentrumssonenummer", OFTInteger); 
-   SERVType.setElement(2, "informasjon", OFTString); 
-   SERVType.setElement(0, "matrikkelnummer", OFTString); 
-   SERVType.setElement(1, "servituttType", OFTString); 
-   SKRETSIDType.setElement(1, "skolekretsnavn", OFTString); 
-   SKRETSIDType.setElement(0, "skolekretsnummer", OFTInteger); 
-   SP_ADMType.setElement(0, "skogbrplanAdmDatoEndring", OFTDate); 
-   SP_ADMType.setElement(1, "skogbrplanAdmDatoEtablering", OFTDate); 
-   SP_AKLASSType.setElement(0, "skogbrplanKlassAktueltTreslag", OFTInteger); 
-   SP_AKLASSType.setElement(1, "skogbrplanKlassAktSnittBon", OFTInteger); 
-   SP_AKLASSType.setElement(3, "skogbrplanKlassImpProsent", OFTInteger); 
-   SP_AKLASSType.setElement(2, "skogbrplanKlassImpType", OFTInteger); 
-   SP_AKLASSType.setElement(4, "skogbrplanKlassPotTreslag", OFTInteger); 
-   SP_AKLASSType.setElement(5, "skogbrplanKlassPotSnittBon", OFTInteger); 
-   SP_BESTANDType.setElement(1, "skogbrplanBestandDelNr", OFTInteger); 
-   SP_BESTANDType.setElement(0, "skogbrplanBestandNr", OFTInteger); 
-   SP_BSKRIVType.setElement(2, "skogbrplanBeskrivBestandAlder", OFTInteger); 
-   SP_BSKRIVType.setElement(3, "skogbrplanBeskrivBestandDaa", OFTReal); 
-   SP_BSKRIVType.setElement(6, "skogbrplanBeskrivBestSnittDiam", OFTInteger); 
-   SP_BSKRIVType.setElement(4, "skogbrplanBeskrivBestandSnittM2", OFTInteger); 
-   SP_BSKRIVType.setElement(5, "skogbrplanBeskrivBestandSnittH", OFTReal); 
-   SP_BSKRIVType.setElement(7, "skogbrplanBeskrivBarHøydehkl2", OFTInteger); 
-   SP_BSKRIVType.setElement(0, "skogbrplanBeskrivHogstklasse", OFTInteger); 
-   SP_BSKRIVType.setElement(8, "skogbrplanBeskrivLauvHøydehkl2", OFTInteger); 
-   SP_BSKRIVType.setElement(9, "skogbrplanBeskrivSjiktning", OFTInteger); 
-   SP_BSKRIVType.setElement(1, "skogbrplanBeskrivSkogtype", OFTInteger); 
-   SP_BSKRIVType.setElement(10, "skogbrplanBeskrivSunnhet", OFTInteger); 
-   SP_BSKRIVType.setElement(11, "skogbrplanBeskrivTreERegulering", OFTInteger); 
-   SP_BSKRIVType.setElement(12, "skogbrplanBeskrivTreFRegulering", OFTInteger); 
-   SP_FLBRELEMType.setElement(0, "skogbrplanFlerKoderElementtype", OFTInteger); 
-   SP_FLBRELEMType.setElement(1, "skogbrplanFlerKoderArealProsent", OFTInteger); 
-   SP_FLBRELEMType.setElement(2, "skogbrplanFlerKoderArealDaa", OFTInteger); 
-   SP_FLBRELEMType.setElement(3, "skogbrplanFlerKoderSpesBehPros", OFTInteger); 
-   SP_FLBRELEMType.setElement(4, "skogbrplanFlerKoderSpesBehDaa", OFTInteger); 
-   SP_GRLVOLType.setElement(3, "skogbrplanGrunnlagVolumDaaFelt", OFTReal); 
-   SP_GRLVOLType.setElement(4, "skogbrplanGrunnlagVolumBestFelt", OFTInteger); 
-   SP_GRLVOLType.setElement(0, "skogbrplanGrunnlagBerType", OFTInteger); 
-   SP_GRLVOLType.setElement(2, "skogbrplanGrunnlagHovedgruppe", OFTInteger); 
-   SP_GRLVOLType.setElement(6, "skogbrplanGrunnlagRegion", OFTInteger); 
-   SP_GRLVOLType.setElement(5, "skogbrplanGrunnlagSvinnProsent", OFTInteger); 
-   SP_GRLVOLType.setElement(1, "skogbrplanGrunnlagTaksttype", OFTInteger); 
-   SP_GRLVOLType.setElement(7, "skogbrplanGrunnlagTilvekstkorr", OFTInteger); 
-   SP_TEIGType.setElement(3, "matrikkelnummer", OFTString); 
-   SP_TEIGType.setElement(2, "skogbrplanTeigGrend", OFTInteger); 
-   SP_TEIGType.setElement(0, "skogbrplanTeigNr", OFTInteger); 
-   SP_TEIGType.setElement(1, "skogbrplanTeigNavn", OFTString); 
-   SP_TERKLASSType.setElement(0, "skogbrplanTerrengBæreevneBestand", OFTInteger); 
-   SP_TERKLASSType.setElement(1, "skogbrplanTerrengBestandBratthet", OFTInteger); 
-   SP_TERKLASSType.setElement(2, "skogbrplanTerrengLiLengde", OFTInteger); 
-   SP_TERKLASSType.setElement(3, "skogbrplanTerrengMinTranspUtst", OFTInteger); 
-   SP_TERKLASSType.setElement(4, "skogbrplanTerrengJevnhet", OFTInteger); 
-   SP_TETTHOYDType.setElement(0, "skogbrplanTetthetGrunnflatesum", OFTInteger); 
-   SP_TETTHOYDType.setElement(1, "skogbrplanTetthetMHøyde", OFTInteger); 
-   SP_TILTAKType.setElement(3, "skogbrplanTiltakProritet", OFTInteger); 
-   SP_TILTAKType.setElement(1, "skogbrplanTiltakProsent", OFTInteger); 
-   SP_TILTAKType.setElement(4, "skogbrplanTiltakAreal", OFTReal); 
-   SP_TILTAKType.setElement(0, "skogbrplanTiltakBestand", OFTInteger); 
-   SP_TILTAKType.setElement(2, "skogbrplanTiltakÅr", OFTInteger); 
-   SP_TILVVOLType.setElement(0, "skogbrplanTilvekstBeregnDaa", OFTReal); 
-   SP_TILVVOLType.setElement(1, "skogbrplanTilvekstBeregnProsent", OFTReal); 
-   SP_TILVVOLType.setElement(2, "skogbrplanTilvekstBeregnM3", OFTReal); 
-   SP_TILVVOLType.setElement(3, "skogbrplanTilvekstVolumBestand", OFTInteger); 
-   SP_TRESLType.setElement(4, "skogbrplanTreslagAntTreDaaEReg", OFTInteger); 
-   SP_TRESLType.setElement(3, "skogbrplanTreslagAntTreDaaFReg", OFTInteger); 
-   SP_TRESLType.setElement(0, "skogbrplanTreslag", OFTInteger); 
-   SP_TRESLType.setElement(1, "skogbrplanTreslagHøyde", OFTInteger); 
-   SP_TRESLType.setElement(2, "skogbrplanTreslagProsent", OFTInteger); 
-   SP_TRESLType.setElement(5, "skogbrplanTreslagKorrVolumUBark", OFTInteger); 
-   SP_TRESLType.setElement(7, "skogbrplanTreslagSalgsvolumUBark", OFTInteger); 
-   SP_TRESLType.setElement(6, "skogbrplanTreslagUkorrVolumUBark", OFTInteger); 
-   TETTSTEDIDType.setElement(1, "tettstednavn", OFTString); 
-   TETTSTEDIDType.setElement(0, "tettstednummer", OFTInteger); 
-   UNIVERSELLUTFORMINGType.setElement(2, "informasjon", OFTString); 
-   UNIVERSELLUTFORMINGType.setElement(0, "tilgjengelighetsvurdering", OFTString); 
-   UNIVERSELLUTFORMINGType.setElement(1, "universellutformingFasilitet", OFTString); 
-   UTNYTTType.setElement(1, "utnyttingstall", OFTReal); 
-   UTNYTTType.setElement(0, "utnyttingstype", OFTInteger); 
-   UTSLIPPType.setElement(0, "komponent", OFTString); 
-   UTSLIPPType.setElement(1, "massestørrelse", OFTString); 
-   UTSLIPPType.setElement(2, "utslippType", OFTString); 
-   UTV_TILL_PARTType.setElement(1, "petroleumsandel", OFTReal); 
-   UTV_TILL_PARTType.setElement(0, "petroleumspartnere", OFTString); 
-   VERNType.setElement(0, "vernelov", OFTString); 
-   VERNType.setElement(1, "verneparagraf", OFTString); 
-   VERNType.setElement(3, "vernedato", OFTDate); 
-   VERNType.setElement(2, "vernetype", OFTString); 
-   VKRETSType.setElement(1, "valgkretsnavn", OFTString); 
-   VKRETSType.setElement(0, "valgkretsnummer", OFTInteger); 
-   VNRType.setElement(0, "vegkategori", OFTString); 
-   VNRType.setElement(2, "vegnummer", OFTInteger); 
-   VNRType.setElement(1, "vegstatus", OFTString); 
-   VPAType.setElement(0, "hovedParsell", OFTInteger); 
-   VPAType.setElement(1, "veglenkeMeterFra", OFTInteger); 
-   VPAType.setElement(2, "veglenkeMeterTil", OFTInteger); 
-   
+   ADRESSEBRUKSENHETType.setElement(1, "etasjenummer", OFTInteger);
+   ADRESSEBRUKSENHETType.setElement(2, "etasjeplan", OFTString);
+   ADRESSEBRUKSENHETType.setElement(0, "bruksenhetLøpenr", OFTInteger);
+   ADRESSEKOMMENTARType.setElement(0, "etat", OFTString);
+   ADRESSEKOMMENTARType.setElement(2, "kommentar", OFTString);
+   ADRESSEKOMMENTARType.setElement(1, "kommentarType", OFTString);
+   ADRESSEKOMMENTARType.setElement(4, "lagretDato", OFTDate);
+   ADRESSEKOMMENTARType.setElement(3, "saksnummer", OFTInteger);
+   ADRESSEREFERANSEType.setElement(1, "adresseReferansekode", OFTString);
+   ADRESSEREFERANSEType.setElement(0, "referanse", OFTString);
+   ADRESSETILLEGGType.setElement(1, "adresseKommentar", OFTString);
+   ADRESSETILLEGGType.setElement(2, "adresseReferanse", OFTString);
+   ADRESSETILLEGGType.setElement(0, "kartbladindeks", OFTString);
+   AIDType.setElement(2, "bokstav", OFTString);
+   AIDType.setElement(0, "gatenummer", OFTInteger);
+   AIDType.setElement(1, "husnummer", OFTInteger);
+   AJOURFOeRINGType.setElement(1, "ajourførtAv", OFTString);
+   AJOURFOeRINGType.setElement(0, "ajourførtDato", OFTDate);
+   AKVA_KONS_INFOType.setElement(1, "akvaKonsesjonsnummer", OFTInteger);
+   AKVA_KONS_INFOType.setElement(4, "konsesjonsstatus", OFTString);
+   AKVA_KONS_INFOType.setElement(6, "konsesjonstype", OFTString);
+   AKVA_KONS_INFOType.setElement(5, "konsesjonsformål", OFTString);
+   AKVA_KONS_INFOType.setElement(0, "fiskebruksnummerFylke", OFTString);
+   AKVA_KONS_INFOType.setElement(2, "lokalitetsnavn", OFTString);
+   AKVA_KONS_INFOType.setElement(3, "lokalitetsnummer", OFTInteger);
+   AKVA_PROeVE_INFOType.setElement(7, "akvaTemperatur", OFTInteger);
+   AKVA_PROeVE_INFOType.setElement(1, "algekonsentrasjon", OFTInteger);
+   AKVA_PROeVE_INFOType.setElement(0, "algetype", OFTString);
+   AKVA_PROeVE_INFOType.setElement(5, "klorofyllMaksimum", OFTInteger);
+   AKVA_PROeVE_INFOType.setElement(8, "salinitet", OFTInteger);
+   AKVA_PROeVE_INFOType.setElement(6, "sikteDyp", OFTInteger);
+   AKVA_PROeVE_INFOType.setElement(2, "strømretning", OFTInteger);
+   AKVA_PROeVE_INFOType.setElement(4, "vindretning", OFTInteger);
+   ANDELType.setElement(1, "nevner", OFTReal);
+   ANDELType.setElement(0, "teller", OFTReal);
+   AREALFORDELINGType.setElement(4, "prosentElv", OFTReal);
+   AREALFORDELINGType.setElement(2, "prosentHav", OFTReal);
+   AREALFORDELINGType.setElement(3, "prosentInnsjø", OFTReal);
+   AREALFORDELINGType.setElement(1, "prosentLand", OFTReal);
+   AREALFORDELINGType.setElement(0, "totalarealKm2", OFTReal);
+   BELASTNINGBOF5Type.setElement(2, "andrekilderBelastning", OFTInteger);
+   BELASTNINGBOF5Type.setElement(0, "husholdBelastning", OFTInteger);
+   BELASTNINGBOF5Type.setElement(1, "industriBelastning", OFTInteger);
+   BELASTNINGBOF5Type.setElement(3, "totalbelastning", OFTInteger);
+   BELASTNINGFOSFORType.setElement(2, "andrekilderBelastning", OFTInteger);
+   BELASTNINGFOSFORType.setElement(0, "husholdBelastning", OFTInteger);
+   BELASTNINGFOSFORType.setElement(1, "industriBelastning", OFTInteger);
+   BELASTNINGFOSFORType.setElement(3, "totalbelastning", OFTInteger);
+   BEREGNETAREALType.setElement(0, "areal", OFTReal);
+   BEREGNETAREALType.setElement(1, "arealmerknad", OFTString);
+   BILDEINFORMASJONType.setElement(1, "brennvidde", OFTReal);
+   BILDEINFORMASJONType.setElement(2, "fotograf", OFTString);
+   BILDEINFORMASJONType.setElement(0, "kameratype", OFTString);
+   BMARTOBSType.setElement(1, "bmAntall", OFTInteger);
+   BMARTOBSType.setElement(0, "bmArt", OFTString);
+   BMARTOBSType.setElement(2, "bmEnhet", OFTInteger);
+   BMARTOBSType.setElement(3, "bmRegistreringsdato", OFTDate);
+   BMARTREGType.setElement(6, "bmÅrstid", OFTInteger);
+   BMARTREGType.setElement(0, "bmArt", OFTString);
+   BMARTREGType.setElement(2, "bmOmrådefunksjon", OFTInteger);
+   BMARTREGType.setElement(5, "bmFunksjonskvalitet", OFTInteger);
+   BMARTREGType.setElement(7, "bmKilde", OFTString);
+   BMARTREGType.setElement(1, "bmRegistreringsdato", OFTDate);
+   BMARTREGType.setElement(3, "bmTruethetskategori", OFTString);
+   BMARTREGType.setElement(4, "bmViltvekt", OFTInteger);
+   BMKILDEType.setElement(1, "bmKildetype", OFTInteger);
+   BMKILDEType.setElement(0, "bmKildevurdering", OFTInteger);
+   BMNATYPTILLEGGType.setElement(1, "bmAndel", OFTInteger);
+   BMNATYPTILLEGGType.setElement(0, "bmNaturtype", OFTString);
+   BRUKSENHETType.setElement(7, "antallBad", OFTInteger);
+   BRUKSENHETType.setElement(6, "antallRom", OFTInteger);
+   BRUKSENHETType.setElement(8, "antallWC", OFTInteger);
+   BRUKSENHETType.setElement(5, "bruksareal", OFTReal);
+   BRUKSENHETType.setElement(4, "bruksenhetstype", OFTString);
+   BRUKSENHETType.setElement(2, "etasjenummer", OFTInteger);
+   BRUKSENHETType.setElement(1, "etasjeplan", OFTString);
+   BRUKSENHETType.setElement(9, "kjøkkenTilgang", OFTInteger);
+   BRUKSENHETType.setElement(3, "bruksenhetLøpenr", OFTInteger);
+   BRUKSENHETType.setElement(0, "matrikkelnummer", OFTString);
+   BYDELIDType.setElement(0, "bydelsnavn", OFTString);
+   BYDELIDType.setElement(1, "bydelsnummer", OFTInteger);
+   BYGG_KOMMENTARERType.setElement(3, "bygnSaksnr", OFTString);
+   BYGG_KOMMENTARERType.setElement(0, "etat", OFTString);
+   BYGG_KOMMENTARERType.setElement(2, "kommentar", OFTString);
+   BYGG_KOMMENTARERType.setElement(1, "kommentarType", OFTString);
+   BYGG_KOMMENTARERType.setElement(4, "lagretDato", OFTDate);
+   BYGN_STAT_HISTType.setElement(0, "bygningsstatus", OFTString);
+   BYGN_STAT_HISTType.setElement(1, "bygningshistorikkDato", OFTDate);
+   BYGN_STAT_HISTType.setElement(2, "registrertDato", OFTDate);
+   BYGNING_TILLEGGType.setElement(0, "alternativtArealBygning", OFTReal);
+   BYGNING_TILLEGGType.setElement(1, "antallEtasjer", OFTInteger);
+   BYGNING_TILLEGGType.setElement(2, "antallRøkløp", OFTReal);
+   BYGNING_TILLEGGType.setElement(3, "brenseltankNedgravd", OFTInteger);
+   BYGNING_TILLEGGType.setElement(14, "bygningKommentar", OFTString);
+   BYGNING_TILLEGGType.setElement(13, "bygningsreferanse", OFTString);
+   BYGNING_TILLEGGType.setElement(9, "fundamentering", OFTInteger);
+   BYGNING_TILLEGGType.setElement(12, "horisontalBærekonstr", OFTInteger);
+   BYGNING_TILLEGGType.setElement(5, "kartbladindeks", OFTString);
+   BYGNING_TILLEGGType.setElement(6, "kildePrivatVannforsyning", OFTInteger);
+   BYGNING_TILLEGGType.setElement(10, "materialeIYttervegg", OFTInteger);
+   BYGNING_TILLEGGType.setElement(7, "privatKloakkRensing", OFTInteger);
+   BYGNING_TILLEGGType.setElement(8, "renovasjon", OFTInteger);
+   BYGNING_TILLEGGType.setElement(4, "septiktank", OFTString);
+   BYGNING_TILLEGGType.setElement(11, "vertikalBærekonstr", OFTInteger);
+   BYGNINGSREFType.setElement(1, "bygningReferansetype", OFTString);
+   BYGNINGSREFType.setElement(0, "referanse", OFTString);
+   DELOMRAaDEIDType.setElement(0, "delområdenavn", OFTString);
+   DELOMRAaDEIDType.setElement(1, "delområdenummer", OFTString);
+   DPOT_GRASType.setElement(2, "nedbørsbasert", OFTInteger);
+   DPOT_GRASType.setElement(3, "nedklassifiseringNedbør", OFTInteger);
+   DPOT_GRASType.setElement(0, "vanningsbasert", OFTInteger);
+   DPOT_GRASType.setElement(1, "nedklassifiseringVanning", OFTInteger);
+   DPOT_KORNType.setElement(2, "nedbørsbasert", OFTInteger);
+   DPOT_KORNType.setElement(3, "nedklassifiseringNedbør", OFTInteger);
+   DPOT_KORNType.setElement(0, "vanningsbasert", OFTInteger);
+   DPOT_KORNType.setElement(1, "nedklassifiseringVanning", OFTInteger);
+   DPOT_POTETType.setElement(2, "nedbørsbasert", OFTInteger);
+   DPOT_POTETType.setElement(3, "nedklassifiseringNedbør", OFTInteger);
+   DPOT_POTETType.setElement(0, "vanningsbasert", OFTInteger);
+   DPOT_POTETType.setElement(1, "nedklassifiseringVanning", OFTInteger);
+   EKOORDType.setElement(2, "jordregisterKoordinatHøyde", OFTInteger);
+   EKOORDType.setElement(0, "jordregisterKoordinatNord", OFTInteger);
+   EKOORDType.setElement(1, "jordregisterKoordinatØst", OFTInteger);
+   ENDRINGSFLAGGType.setElement(1, "tidspunktEndring", OFTDateTime);
+   ENDRINGSFLAGGType.setElement(0, "typeEndring", OFTString);
+   ENDRINGSVURDERINGType.setElement(0, "endringsgrad", OFTString);
+   ENDRINGSVURDERINGType.setElement(1, "vurdertDato", OFTDate);
+   ETASJEType.setElement(2, "antallBoenheter", OFTInteger);
+   ETASJEType.setElement(4, "bruksarealTilAnnet", OFTReal);
+   ETASJEType.setElement(3, "bruksarealTilBolig", OFTReal);
+   ETASJEType.setElement(5, "bruksarealTotalt", OFTReal);
+   ETASJEType.setElement(1, "etasjenummer", OFTInteger);
+   ETASJEType.setElement(0, "etasjeplan", OFTString);
+   ETASJEType.setElement(6, "kommAlternativtAreal", OFTReal);
+   ETASJEType.setElement(7, "kommAlternativtAreal2", OFTReal);
+   ETASJEDATAType.setElement(4, "sumAlternativtAreal", OFTReal);
+   ETASJEDATAType.setElement(5, "sumAlternativtAreal2", OFTReal);
+   ETASJEDATAType.setElement(0, "sumAntallBoenheter", OFTInteger);
+   ETASJEDATAType.setElement(3, "sumBruksarealTotalt", OFTReal);
+   ETASJEDATAType.setElement(2, "sumBruksarealTilAnnet", OFTReal);
+   ETASJEDATAType.setElement(1, "sumBruksarealTilBolig", OFTReal);
+   FELTREGISTRERTType.setElement(2, "ajourføring", OFTString);
+   FELTREGISTRERTType.setElement(1, "datafangstdato", OFTDateTime);
+   FELTREGISTRERTType.setElement(0, "feltregistrertAv", OFTString);
+   FIRMA_EIERType.setElement(2, "adresse", OFTString);
+   FIRMA_EIERType.setElement(0, "firmanavn", OFTString);
+   FIRMA_EIERType.setElement(1, "bedriftseier", OFTString);
+   FIRMA_EIERType.setElement(6, "kontaktperson", OFTString);
+   FIRMA_EIERType.setElement(3, "postnummer", OFTInteger);
+   FIRMA_EIERType.setElement(5, "telefaxnummer", OFTInteger);
+   FIRMA_EIERType.setElement(4, "telefonnummer", OFTInteger);
+   FISKE_BEDR_IDType.setElement(4, "antallAnsatte", OFTInteger);
+   FISKE_BEDR_IDType.setElement(5, "antallÅrsverk", OFTInteger);
+   FISKE_BEDR_IDType.setElement(0, "fiskebedriftsnavn", OFTString);
+   FISKE_BEDR_IDType.setElement(2, "fiskebruksnummer", OFTInteger);
+   FISKE_BEDR_IDType.setElement(1, "fiskebruksnummerFylke", OFTString);
+   FISKE_BEDR_IDType.setElement(3, "firmaeier", OFTString);
+   FISKE_BEDR_INFOType.setElement(1, "artskode", OFTInteger);
+   FISKE_BEDR_INFOType.setElement(0, "fisketype", OFTInteger);
+   FISKE_BEDR_MARKEDType.setElement(0, "fiskebedriftsandel", OFTInteger);
+   FISKE_BEDR_MARKEDType.setElement(1, "fiskebedriftsområde", OFTInteger);
+   FISKE_BEDR_TJENESTEType.setElement(2, "fiskebedriftservice", OFTInteger);
+   FISKE_BEDR_TJENESTEType.setElement(1, "fiskekapasitetEnhet", OFTInteger);
+   FISKE_BEDR_TJENESTEType.setElement(0, "fiskekapasitet", OFTInteger);
+   FISKERI_REDSKAPType.setElement(0, "fiskeriredskapGenAktiv", OFTInteger);
+   FISKERI_REDSKAPType.setElement(1, "fiskeriredskapGenPassiv", OFTInteger);
+   FISKERI_REDSKAPType.setElement(2, "fiskeriredskapSpesAktiv", OFTInteger);
+   FISKERI_REDSKAPType.setElement(3, "fiskeriredskapSpesPassiv", OFTInteger);
+   FISKERI_RESS_ARTType.setElement(3, "engelskArtsnavn", OFTString);
+   FISKERI_RESS_ARTType.setElement(2, "vitenskapeligArtsnavn", OFTString);
+   FISKERI_RESS_ARTType.setElement(1, "norskArtsnavn", OFTString);
+   FISKERI_RESS_ARTType.setElement(0, "taksonomiskKode", OFTInteger);
+   FISKERI_RESS_ARTType.setElement(4, "faoKode", OFTString);
+   FISKERI_RESS_ARTType.setElement(5, "artskode", OFTInteger);
+   FISKERI_RESSURSType.setElement(0, "fiskeriressursområdeArt", OFTString);
+   FISKERI_RESSURSType.setElement(1, "periode", OFTString);
+   FMDATOType.setElement(1, "beregningsDato", OFTDate);
+   FMDATOType.setElement(0, "fastmerkeEtableringsdato", OFTDate);
+   FMIDNYType.setElement(1, "fastmerkeInstitusjon", OFTString);
+   FMIDNYType.setElement(0, "fastmerkeKommune", OFTInteger);
+   FMIDNYType.setElement(2, "fastmerkeNummer", OFTString);
+   FMIDNYType.setElement(3, "indikatorFastmerkenummer", OFTString);
+   FMSIGNType.setElement(1, "signalHøyde", OFTReal);
+   FMSIGNType.setElement(0, "signalType", OFTString);
+   FMSTATUSType.setElement(1, "typeStatus", OFTInteger);
+   FMSTATUSType.setElement(0, "verifiseringsdato", OFTDateTime);
+   FMTYPEType.setElement(0, "boltType", OFTInteger);
+   FMTYPEType.setElement(3, "fastmerkeDiameter", OFTInteger);
+   FMTYPEType.setElement(4, "gravertTekst", OFTString);
+   FMTYPEType.setElement(1, "materialeBolt", OFTInteger);
+   FMTYPEType.setElement(2, "fastmerkeUnderlag", OFTInteger);
+   FORUR_GRUNN_EIENDOMType.setElement(1, "arealbrukRestriksjon", OFTInteger);
+   FORUR_GRUNN_EIENDOMType.setElement(0, "matrikkelnummer", OFTString);
+   GRENSE_MELLOMType.setElement(0, "førsteLand", OFTString);
+   GRENSE_MELLOMType.setElement(1, "annetLand", OFTString);
+   GRUNNKRETSIDType.setElement(1, "grunnkretsnavn", OFTString);
+   GRUNNKRETSIDType.setElement(0, "grunnkretsnummer", OFTInteger);
+   HAVNE_D_INFOType.setElement(1, "havnedistriktAdministrasjon", OFTInteger);
+   HAVNE_D_INFOType.setElement(0, "kommune", OFTInteger);
+   HOVEDMAaLRUBRIKKType.setElement(1, "bredde", OFTInteger);
+   HOVEDMAaLRUBRIKKType.setElement(0, "lengde", OFTInteger);
+   HOVEDNRType.setElement(1, " kommunenummer", OFTInteger);
+   HOVEDNRType.setElement(0, "matrikkelnummer", OFTString);
+   HYTTEINFORMASJONType.setElement(1, "betjeningsgrad", OFTString);
+   HYTTEINFORMASJONType.setElement(0, "hytteId", OFTInteger);
+   HYTTEINFORMASJONType.setElement(2, "hytteeier", OFTInteger);
+   JORDTYPEType.setElement(0, "serie1", OFTString);
+   JORDTYPEType.setElement(2, "serie2", OFTString);
+   JORDTYPEType.setElement(4, "serie3", OFTString);
+   JORDTYPEType.setElement(1, "tekstur1", OFTString);
+   JORDTYPEType.setElement(3, "tekstur2", OFTString);
+   JORDTYPEType.setElement(5, "tekstur3", OFTString);
+   JREGMARKType.setElement(1, "potensiellSkogbonitetOmkodet", OFTInteger);
+   JREGMARKType.setElement(0, "arealtilstand", OFTInteger);
+   JREGMARKType.setElement(7, "jordregisterDyrkingsjord", OFTString);
+   JREGMARKType.setElement(6, "jordregisterFreg", OFTInteger);
+   JREGMARKType.setElement(5, "jordregisterLreg", OFTString);
+   JREGMARKType.setElement(3, "jordklassifikasjon", OFTInteger);
+   JREGMARKType.setElement(4, "myrklassifikasjon", OFTInteger);
+   JREGMARKType.setElement(8, "jordregisterSkogtype", OFTInteger);
+   JREGMARKType.setElement(9, "jordregisterSkogreisningsmark", OFTInteger);
+   JREGMARKType.setElement(2, "tilleggsopplysningerSkog", OFTInteger);
+   JREGTEIGType.setElement(2, "jordregisterDriftssenter", OFTInteger);
+   JREGTEIGType.setElement(3, "jordregisterStatusEiendom", OFTInteger);
+   JREGTEIGType.setElement(0, "matrikkelnummer", OFTString);
+   JREGTEIGType.setElement(1, "jordregisterEiendomTeigNummer", OFTInteger);
+   KAI_INFOType.setElement(1, "kaiDybde", OFTReal);
+   KAI_INFOType.setElement(0, "kaiType", OFTInteger);
+   KAI_INFOType.setElement(2, "kommunenummer", OFTInteger);
+   KAMERAINFORMASJONType.setElement(4, "bildekategori", OFTInteger);
+   KAMERAINFORMASJONType.setElement(3, "brennvidde", OFTReal);
+   KAMERAINFORMASJONType.setElement(7, "film", OFTString);
+   KAMERAINFORMASJONType.setElement(8, "kalibreringsrapport", OFTString);
+   KAMERAINFORMASJONType.setElement(1, "kameratype", OFTString);
+   KAMERAINFORMASJONType.setElement(0, "opptaksmetode", OFTInteger);
+   KM_DAT_INFOType.setElement(0, "sefrakTiltak", OFTInteger);
+   KM_DAT_INFOType.setElement(1, "tidsangivelse", OFTInteger);
+   KM_DATERINGType.setElement(0, "kulturminneDatering", OFTString);
+   KM_DATERINGType.setElement(1, "kulturminneDateringKvalitet", OFTString);
+   KOMMUNALKRETSType.setElement(3, "kretsnavn", OFTString);
+   KOMMUNALKRETSType.setElement(2, "kretsnummer", OFTString);
+   KOMMUNALKRETSType.setElement(0, "kretstypekode", OFTString);
+   KOMMUNALKRETSType.setElement(1, "kretstypenavn", OFTString);
+   KOPIDATAType.setElement(2, "kopidato", OFTDateTime);
+   KOPIDATAType.setElement(0, "områdeId", OFTInteger);
+   KOPIDATAType.setElement(1, "originalDatavert", OFTString);
+   KOPLINGType.setElement(1, "fagområde", OFTInteger);
+   KOPLINGType.setElement(4, "bruksområde", OFTString);
+   KOPLINGType.setElement(2, "koplingskategori", OFTInteger);
+   KOPLINGType.setElement(0, "koplingsnavn", OFTString);
+   KOPLINGType.setElement(3, "koplingstype", OFTString);
+   KOPLINGType.setElement(7, "bildelink", OFTString);
+   KOPLINGType.setElement(5, "materiellkode", OFTString);
+   KOPLINGType.setElement(6, "verdi", OFTInteger);
+   KURSLINJE_INFOType.setElement(0, "fartøyIdentifikasjon", OFTString);
+   KURSLINJE_INFOType.setElement(1, "satellittkommunikasjonsId", OFTString);
+   KURSLINJE_INFOType.setElement(3, "sporhastighet", OFTInteger);
+   KURSLINJE_INFOType.setElement(2, "tidspunkt", OFTDateTime);
+   KVALITETType.setElement(3, "målemetodeHøyde", OFTInteger);
+   KVALITETType.setElement(4, "nøyaktighetHøyde", OFTInteger);
+   KVALITETType.setElement(5, "maksimaltAvvik", OFTInteger);
+   KVALITETType.setElement(0, "målemetode", OFTInteger);
+   KVALITETType.setElement(1, "nøyaktighet", OFTInteger);
+   KVALITETType.setElement(2, "synbarhet", OFTInteger);
+   LEDNINGType.setElement(1, "fagområde", OFTInteger);
+   LEDNINGType.setElement(3, "bruksområde", OFTString);
+   LEDNINGType.setElement(0, "ledningsnavn", OFTString);
+   LEDNINGType.setElement(2, "ledningstype", OFTInteger);
+   LEDNINGType.setElement(7, "leggeår", OFTString);
+   LEDNINGType.setElement(6, "lengde", OFTReal);
+   LEDNINGType.setElement(5, "materiellkode", OFTString);
+   LEDNINGType.setElement(4, "nettnivå", OFTString);
+   LEGGEAaRType.setElement(0, "alderReferanse", OFTInteger);
+   LEGGEAaRType.setElement(1, "årstall", OFTInteger);
+   LGIDType.setElement(7, "landbruksregAktiv", OFTInteger);
+   LGIDType.setElement(6, "landbruksregType", OFTInteger);
+   LGIDType.setElement(0, "matrikkelnummer", OFTString);
+   MATRIKKELADRESSEIDType.setElement(0, "matrikkelnummer", OFTString);
+   MATRIKKELADRESSEIDType.setElement(1, "undernr", OFTInteger);
+   MATRIKKELNUMMERType.setElement(2, "bruksnummer", OFTInteger);
+   MATRIKKELNUMMERType.setElement(3, "festenummer", OFTInteger);
+   MATRIKKELNUMMERType.setElement(1, "gårdsnummer", OFTInteger);
+   MATRIKKELNUMMERType.setElement(0, "matrikkelkommune", OFTInteger);
+   MATRIKKELNUMMERType.setElement(4, "seksjonsnummer", OFTInteger);
+   OVERLAPPType.setElement(0, "lengdeoverlapp", OFTInteger);
+   OVERLAPPType.setElement(1, "sideoverlapp", OFTInteger);
+   POSTType.setElement(1, "poststedsnavn", OFTString);
+   POSTType.setElement(0, "postnummer", OFTInteger);
+   REGISTRERINGSVERSJONType.setElement(0, "produkt", OFTString);
+   REGISTRERINGSVERSJONType.setElement(1, "versjon", OFTString);
+   RESIPIENTType.setElement(2, "fjordId", OFTString);
+   RESIPIENTType.setElement(0, "resipientnavn", OFTString);
+   RESIPIENTType.setElement(4, "resipienttype", OFTString);
+   RESIPIENTType.setElement(1, "vassdragsnummer", OFTString);
+   RESIPIENTType.setElement(3, "vatnLøpenummer", OFTInteger);
+   RETNINGType.setElement(1, "retningsenhet", OFTInteger);
+   RETNINGType.setElement(2, "retningsreferanse", OFTInteger);
+   RETNINGType.setElement(0, "retningsverdi", OFTReal);
+   ROeR_DIMENSJONType.setElement(1, "lengdeenhet", OFTString);
+   ROeR_DIMENSJONType.setElement(0, "måltall", OFTReal);
+   SAKType.setElement(3, "vedtaksmyndighet", OFTString);
+   SAKType.setElement(0, "saksnummer", OFTInteger);
+   SAKType.setElement(2, "utvalgssaksnummer", OFTInteger);
+   SAKType.setElement(1, "vedtaksdato", OFTDate);
+   SEFRAK_IDType.setElement(2, "husLøpenr", OFTInteger);
+   SEFRAK_IDType.setElement(1, "registreringKretsnr", OFTInteger);
+   SEFRAK_IDType.setElement(0, "SEFRAKkommune", OFTInteger);
+   SEFRAKFUNKSJONType.setElement(0, "sefrakFunksjonskode", OFTInteger);
+   SEFRAKFUNKSJONType.setElement(1, "sefrakFunksjonsstatus", OFTString);
+   SENTRUMSSONEIDType.setElement(1, "sentrumssonenavn", OFTString);
+   SENTRUMSSONEIDType.setElement(0, "sentrumssonenummer", OFTInteger);
+   SERVType.setElement(2, "informasjon", OFTString);
+   SERVType.setElement(0, "matrikkelnummer", OFTString);
+   SERVType.setElement(1, "servituttType", OFTString);
+   SKRETSIDType.setElement(1, "skolekretsnavn", OFTString);
+   SKRETSIDType.setElement(0, "skolekretsnummer", OFTInteger);
+   SP_ADMType.setElement(0, "skogbrplanAdmDatoEndring", OFTDate);
+   SP_ADMType.setElement(1, "skogbrplanAdmDatoEtablering", OFTDate);
+   SP_AKLASSType.setElement(0, "skogbrplanKlassAktueltTreslag", OFTInteger);
+   SP_AKLASSType.setElement(1, "skogbrplanKlassAktSnittBon", OFTInteger);
+   SP_AKLASSType.setElement(3, "skogbrplanKlassImpProsent", OFTInteger);
+   SP_AKLASSType.setElement(2, "skogbrplanKlassImpType", OFTInteger);
+   SP_AKLASSType.setElement(4, "skogbrplanKlassPotTreslag", OFTInteger);
+   SP_AKLASSType.setElement(5, "skogbrplanKlassPotSnittBon", OFTInteger);
+   SP_BESTANDType.setElement(1, "skogbrplanBestandDelNr", OFTInteger);
+   SP_BESTANDType.setElement(0, "skogbrplanBestandNr", OFTInteger);
+   SP_BSKRIVType.setElement(2, "skogbrplanBeskrivBestandAlder", OFTInteger);
+   SP_BSKRIVType.setElement(3, "skogbrplanBeskrivBestandDaa", OFTReal);
+   SP_BSKRIVType.setElement(6, "skogbrplanBeskrivBestSnittDiam", OFTInteger);
+   SP_BSKRIVType.setElement(4, "skogbrplanBeskrivBestandSnittM2", OFTInteger);
+   SP_BSKRIVType.setElement(5, "skogbrplanBeskrivBestandSnittH", OFTReal);
+   SP_BSKRIVType.setElement(7, "skogbrplanBeskrivBarHøydehkl2", OFTInteger);
+   SP_BSKRIVType.setElement(0, "skogbrplanBeskrivHogstklasse", OFTInteger);
+   SP_BSKRIVType.setElement(8, "skogbrplanBeskrivLauvHøydehkl2", OFTInteger);
+   SP_BSKRIVType.setElement(9, "skogbrplanBeskrivSjiktning", OFTInteger);
+   SP_BSKRIVType.setElement(1, "skogbrplanBeskrivSkogtype", OFTInteger);
+   SP_BSKRIVType.setElement(10, "skogbrplanBeskrivSunnhet", OFTInteger);
+   SP_BSKRIVType.setElement(11, "skogbrplanBeskrivTreERegulering", OFTInteger);
+   SP_BSKRIVType.setElement(12, "skogbrplanBeskrivTreFRegulering", OFTInteger);
+   SP_FLBRELEMType.setElement(0, "skogbrplanFlerKoderElementtype", OFTInteger);
+   SP_FLBRELEMType.setElement(1, "skogbrplanFlerKoderArealProsent", OFTInteger);
+   SP_FLBRELEMType.setElement(2, "skogbrplanFlerKoderArealDaa", OFTInteger);
+   SP_FLBRELEMType.setElement(3, "skogbrplanFlerKoderSpesBehPros", OFTInteger);
+   SP_FLBRELEMType.setElement(4, "skogbrplanFlerKoderSpesBehDaa", OFTInteger);
+   SP_GRLVOLType.setElement(3, "skogbrplanGrunnlagVolumDaaFelt", OFTReal);
+   SP_GRLVOLType.setElement(4, "skogbrplanGrunnlagVolumBestFelt", OFTInteger);
+   SP_GRLVOLType.setElement(0, "skogbrplanGrunnlagBerType", OFTInteger);
+   SP_GRLVOLType.setElement(2, "skogbrplanGrunnlagHovedgruppe", OFTInteger);
+   SP_GRLVOLType.setElement(6, "skogbrplanGrunnlagRegion", OFTInteger);
+   SP_GRLVOLType.setElement(5, "skogbrplanGrunnlagSvinnProsent", OFTInteger);
+   SP_GRLVOLType.setElement(1, "skogbrplanGrunnlagTaksttype", OFTInteger);
+   SP_GRLVOLType.setElement(7, "skogbrplanGrunnlagTilvekstkorr", OFTInteger);
+   SP_TEIGType.setElement(3, "matrikkelnummer", OFTString);
+   SP_TEIGType.setElement(2, "skogbrplanTeigGrend", OFTInteger);
+   SP_TEIGType.setElement(0, "skogbrplanTeigNr", OFTInteger);
+   SP_TEIGType.setElement(1, "skogbrplanTeigNavn", OFTString);
+   SP_TERKLASSType.setElement(0, "skogbrplanTerrengBæreevneBestand", OFTInteger);
+   SP_TERKLASSType.setElement(1, "skogbrplanTerrengBestandBratthet", OFTInteger);
+   SP_TERKLASSType.setElement(2, "skogbrplanTerrengLiLengde", OFTInteger);
+   SP_TERKLASSType.setElement(3, "skogbrplanTerrengMinTranspUtst", OFTInteger);
+   SP_TERKLASSType.setElement(4, "skogbrplanTerrengJevnhet", OFTInteger);
+   SP_TETTHOYDType.setElement(0, "skogbrplanTetthetGrunnflatesum", OFTInteger);
+   SP_TETTHOYDType.setElement(1, "skogbrplanTetthetMHøyde", OFTInteger);
+   SP_TILTAKType.setElement(3, "skogbrplanTiltakProritet", OFTInteger);
+   SP_TILTAKType.setElement(1, "skogbrplanTiltakProsent", OFTInteger);
+   SP_TILTAKType.setElement(4, "skogbrplanTiltakAreal", OFTReal);
+   SP_TILTAKType.setElement(0, "skogbrplanTiltakBestand", OFTInteger);
+   SP_TILTAKType.setElement(2, "skogbrplanTiltakÅr", OFTInteger);
+   SP_TILVVOLType.setElement(0, "skogbrplanTilvekstBeregnDaa", OFTReal);
+   SP_TILVVOLType.setElement(1, "skogbrplanTilvekstBeregnProsent", OFTReal);
+   SP_TILVVOLType.setElement(2, "skogbrplanTilvekstBeregnM3", OFTReal);
+   SP_TILVVOLType.setElement(3, "skogbrplanTilvekstVolumBestand", OFTInteger);
+   SP_TRESLType.setElement(4, "skogbrplanTreslagAntTreDaaEReg", OFTInteger);
+   SP_TRESLType.setElement(3, "skogbrplanTreslagAntTreDaaFReg", OFTInteger);
+   SP_TRESLType.setElement(0, "skogbrplanTreslag", OFTInteger);
+   SP_TRESLType.setElement(1, "skogbrplanTreslagHøyde", OFTInteger);
+   SP_TRESLType.setElement(2, "skogbrplanTreslagProsent", OFTInteger);
+   SP_TRESLType.setElement(5, "skogbrplanTreslagKorrVolumUBark", OFTInteger);
+   SP_TRESLType.setElement(7, "skogbrplanTreslagSalgsvolumUBark", OFTInteger);
+   SP_TRESLType.setElement(6, "skogbrplanTreslagUkorrVolumUBark", OFTInteger);
+   TETTSTEDIDType.setElement(1, "tettstednavn", OFTString);
+   TETTSTEDIDType.setElement(0, "tettstednummer", OFTInteger);
+   UNIVERSELLUTFORMINGType.setElement(2, "informasjon", OFTString);
+   UNIVERSELLUTFORMINGType.setElement(0, "tilgjengelighetsvurdering", OFTString);
+   UNIVERSELLUTFORMINGType.setElement(1, "universellutformingFasilitet", OFTString);
+   UTNYTTType.setElement(1, "utnyttingstall", OFTReal);
+   UTNYTTType.setElement(0, "utnyttingstype", OFTInteger);
+   UTSLIPPType.setElement(0, "komponent", OFTString);
+   UTSLIPPType.setElement(1, "massestørrelse", OFTString);
+   UTSLIPPType.setElement(2, "utslippType", OFTString);
+   UTV_TILL_PARTType.setElement(1, "petroleumsandel", OFTReal);
+   UTV_TILL_PARTType.setElement(0, "petroleumspartnere", OFTString);
+   VERNType.setElement(0, "vernelov", OFTString);
+   VERNType.setElement(1, "verneparagraf", OFTString);
+   VERNType.setElement(3, "vernedato", OFTDate);
+   VERNType.setElement(2, "vernetype", OFTString);
+   VKRETSType.setElement(1, "valgkretsnavn", OFTString);
+   VKRETSType.setElement(0, "valgkretsnummer", OFTInteger);
+   VNRType.setElement(0, "vegkategori", OFTString);
+   VNRType.setElement(2, "vegnummer", OFTInteger);
+   VNRType.setElement(1, "vegstatus", OFTString);
+   VPAType.setElement(0, "hovedParsell", OFTInteger);
+   VPAType.setElement(1, "veglenkeMeterFra", OFTInteger);
+   VPAType.setElement(2, "veglenkeMeterTil", OFTInteger);
+
 addType(&oTypes, "ADRESSEBRUKSENHET", &ADRESSEBRUKSENHETType);
-     
+
 addType(&oTypes, "ADRESSEKOMMENTAR", &ADRESSEKOMMENTARType);
-     
+
 addType(&oTypes, "ADRESSEREFERANSE", &ADRESSEREFERANSEType);
-     
+
 addType(&oTypes, "ADRESSETILLEGG", &ADRESSETILLEGGType);
-     
+
 addType(&oTypes, "AID", &AIDType);
-     
+
 addType(&oTypes, "AJOURFØRING", &AJOURFOeRINGType);
-     
+
 addType(&oTypes, "AKVA_KONS_INFO", &AKVA_KONS_INFOType);
-     
+
 addType(&oTypes, "AKVA_PRØVE_INFO", &AKVA_PROeVE_INFOType);
-     
+
 addType(&oTypes, "ANDEL", &ANDELType);
-     
+
 addType(&oTypes, "AREALFORDELING", &AREALFORDELINGType);
-     
+
 addType(&oTypes, "BELASTNINGBOF5", &BELASTNINGBOF5Type);
-     
+
 addType(&oTypes, "BELASTNINGFOSFOR", &BELASTNINGFOSFORType);
-     
+
 addType(&oTypes, "BEREGNETAREAL", &BEREGNETAREALType);
-     
+
 addType(&oTypes, "BILDEINFORMASJON", &BILDEINFORMASJONType);
-     
+
 addType(&oTypes, "BMARTOBS", &BMARTOBSType);
-     
+
 addType(&oTypes, "BMARTREG", &BMARTREGType);
-     
+
 addType(&oTypes, "BMKILDE", &BMKILDEType);
-     
+
 addType(&oTypes, "BMNATYPTILLEGG", &BMNATYPTILLEGGType);
-     
+
 addType(&oTypes, "BRUKSENHET", &BRUKSENHETType);
-     
+
 addType(&oTypes, "BYDELID", &BYDELIDType);
-     
+
 addType(&oTypes, "BYGG_KOMMENTARER", &BYGG_KOMMENTARERType);
-     
+
 addType(&oTypes, "BYGN_STAT_HIST", &BYGN_STAT_HISTType);
-     
+
 addType(&oTypes, "BYGNING_TILLEGG", &BYGNING_TILLEGGType);
-     
+
 addType(&oTypes, "BYGNINGSREF", &BYGNINGSREFType);
-     
+
 addType(&oTypes, "DELOMRÅDEID", &DELOMRAaDEIDType);
-     
+
 addType(&oTypes, "DPOT_GRAS", &DPOT_GRASType);
-     
+
 addType(&oTypes, "DPOT_KORN", &DPOT_KORNType);
-     
+
 addType(&oTypes, "DPOT_POTET", &DPOT_POTETType);
-     
+
 addType(&oTypes, "EKOORD", &EKOORDType);
-     
+
 addType(&oTypes, "ENDRINGSFLAGG", &ENDRINGSFLAGGType);
-     
+
 addType(&oTypes, "ENDRINGSVURDERING", &ENDRINGSVURDERINGType);
-     
+
 addType(&oTypes, "ETASJE", &ETASJEType);
-     
+
 addType(&oTypes, "ETASJEDATA", &ETASJEDATAType);
-     
+
 addType(&oTypes, "FELTREGISTRERT", &FELTREGISTRERTType);
-     
+
 addType(&oTypes, "FIRMA_EIER", &FIRMA_EIERType);
-     
+
 addType(&oTypes, "FISKE_BEDR_ID", &FISKE_BEDR_IDType);
-     
+
 addType(&oTypes, "FISKE_BEDR_INFO", &FISKE_BEDR_INFOType);
-     
+
 addType(&oTypes, "FISKE_BEDR_MARKED", &FISKE_BEDR_MARKEDType);
-     
+
 addType(&oTypes, "FISKE_BEDR_TJENESTE", &FISKE_BEDR_TJENESTEType);
-     
+
 addType(&oTypes, "FISKERI_REDSKAP", &FISKERI_REDSKAPType);
-     
+
 addType(&oTypes, "FISKERI_RESS_ART", &FISKERI_RESS_ARTType);
-     
+
 addType(&oTypes, "FISKERI_RESSURS", &FISKERI_RESSURSType);
-     
+
 addType(&oTypes, "FMDATO", &FMDATOType);
-     
+
 addType(&oTypes, "FMIDNY", &FMIDNYType);
-     
+
 addType(&oTypes, "FMSIGN", &FMSIGNType);
-     
+
 addType(&oTypes, "FMSTATUS", &FMSTATUSType);
-     
+
 addType(&oTypes, "FMTYPE", &FMTYPEType);
-     
+
 addType(&oTypes, "FORUR_GRUNN_EIENDOM", &FORUR_GRUNN_EIENDOMType);
-     
+
 addType(&oTypes, "GRENSE_MELLOM", &GRENSE_MELLOMType);
-     
+
 addType(&oTypes, "GRUNNKRETSID", &GRUNNKRETSIDType);
-     
+
 addType(&oTypes, "HAVNE_D_INFO", &HAVNE_D_INFOType);
-     
+
 addType(&oTypes, "HOVEDMÅLRUBRIKK", &HOVEDMAaLRUBRIKKType);
-     
+
 addType(&oTypes, "HOVEDNR", &HOVEDNRType);
-     
+
 addType(&oTypes, "HYTTEINFORMASJON", &HYTTEINFORMASJONType);
-     
+
 addType(&oTypes, "JORDTYPE", &JORDTYPEType);
-     
+
 addType(&oTypes, "JREGMARK", &JREGMARKType);
-     
+
 addType(&oTypes, "JREGTEIG", &JREGTEIGType);
-     
+
 addType(&oTypes, "KAI_INFO", &KAI_INFOType);
-     
+
 addType(&oTypes, "KAMERAINFORMASJON", &KAMERAINFORMASJONType);
-     
+
 addType(&oTypes, "KM_DAT_INFO", &KM_DAT_INFOType);
-     
+
 addType(&oTypes, "KM_DATERING", &KM_DATERINGType);
-     
+
 addType(&oTypes, "KOMMUNALKRETS", &KOMMUNALKRETSType);
-     
+
 addType(&oTypes, "KOPIDATA", &KOPIDATAType);
-     
+
 addType(&oTypes, "KOPLING", &KOPLINGType);
-     
+
 addType(&oTypes, "KURSLINJE_INFO", &KURSLINJE_INFOType);
-     
+
 addType(&oTypes, "KVALITET", &KVALITETType);
-     
+
 addType(&oTypes, "LEDNING", &LEDNINGType);
-     
+
 addType(&oTypes, "LEGGEÅR", &LEGGEAaRType);
-     
+
 addType(&oTypes, "LGID", &LGIDType);
-     
+
 addType(&oTypes, "MATRIKKELADRESSEID", &MATRIKKELADRESSEIDType);
-     
+
 addType(&oTypes, "MATRIKKELNUMMER", &MATRIKKELNUMMERType);
-     
+
 addType(&oTypes, "OVERLAPP", &OVERLAPPType);
-     
+
 addType(&oTypes, "POST", &POSTType);
-     
+
 addType(&oTypes, "REGISTRERINGSVERSJON", &REGISTRERINGSVERSJONType);
-     
+
 addType(&oTypes, "RESIPIENT", &RESIPIENTType);
-     
+
 addType(&oTypes, "RETNING", &RETNINGType);
-     
+
 addType(&oTypes, "RØR_DIMENSJON", &ROeR_DIMENSJONType);
-     
+
 addType(&oTypes, "SAK", &SAKType);
-     
+
 addType(&oTypes, "SEFRAK_ID", &SEFRAK_IDType);
-     
+
 addType(&oTypes, "SEFRAKFUNKSJON", &SEFRAKFUNKSJONType);
-     
+
 addType(&oTypes, "SENTRUMSSONEID", &SENTRUMSSONEIDType);
-     
+
 addType(&oTypes, "SERV", &SERVType);
-     
+
 addType(&oTypes, "SKRETSID", &SKRETSIDType);
-     
+
 addType(&oTypes, "SP_ADM", &SP_ADMType);
-     
+
 addType(&oTypes, "SP_AKLASS", &SP_AKLASSType);
-     
+
 addType(&oTypes, "SP_BESTAND", &SP_BESTANDType);
-     
+
 addType(&oTypes, "SP_BSKRIV", &SP_BSKRIVType);
-     
+
 addType(&oTypes, "SP_FLBRELEM", &SP_FLBRELEMType);
-     
+
 addType(&oTypes, "SP_GRLVOL", &SP_GRLVOLType);
-     
+
 addType(&oTypes, "SP_TEIG", &SP_TEIGType);
-     
+
 addType(&oTypes, "SP_TERKLASS", &SP_TERKLASSType);
-     
+
 addType(&oTypes, "SP_TETTHOYD", &SP_TETTHOYDType);
-     
+
 addType(&oTypes, "SP_TILTAK", &SP_TILTAKType);
-     
+
 addType(&oTypes, "SP_TILVVOL", &SP_TILVVOLType);
-     
+
 addType(&oTypes, "SP_TRESL", &SP_TRESLType);
-     
+
 addType(&oTypes, "TETTSTEDID", &TETTSTEDIDType);
-     
+
 addType(&oTypes, "UNIVERSELLUTFORMING", &UNIVERSELLUTFORMINGType);
-     
+
 addType(&oTypes, "UTNYTT", &UTNYTTType);
-     
+
 addType(&oTypes, "UTSLIPP", &UTSLIPPType);
-     
+
 addType(&oTypes, "UTV_TILL_PART", &UTV_TILL_PARTType);
-     
+
 addType(&oTypes, "VERN", &VERNType);
-     
+
 addType(&oTypes, "VKRETS", &VKRETSType);
-     
+
 addType(&oTypes, "VNR", &VNRType);
-     
+
 addType(&oTypes, "VPA", &VPAType);
-     
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp b/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp
index dd30802..fcfc25b 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosidriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsosidriver.cpp 34420 2016-06-24 21:06:03Z rouault $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSIDriver.
@@ -30,6 +29,8 @@
 
 #include "ogr_sosi.h"
 
+CPL_CVSID("$Id: ogrsosidriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+
 static int bFYBAInit = FALSE;
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp b/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
index aabc72a..d930e2d 100644
--- a/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
+++ b/ogr/ogrsf_frmts/sosi/ogrsosilayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsosilayer.cpp 34420 2016-06-24 21:06:03Z rouault $
  *
  * Project:  SOSI Translator
  * Purpose:  Implements OGRSOSILayer.
@@ -31,6 +30,8 @@
 #include "ogr_sosi.h"
 #include <map>
 
+CPL_CVSID("$Id: ogrsosilayer.cpp 36418 2016-11-21 22:58:41Z rouault $");
+
 /************************************************************************/
 /*                           OGRSOSILayer()                             */
 /************************************************************************/
@@ -54,7 +55,7 @@ OGRSOSILayer::OGRSOSILayer( OGRSOSIDataSource *poPar, OGRFeatureDefn *poFeatDefn
 /*                           ~OGRSOSILayer()                            */
 /************************************************************************/
 OGRSOSILayer::~OGRSOSILayer() {
-	poFeatureDefn->Release();
+    poFeatureDefn->Release();
 }
 
 /************************************************************************/
@@ -104,14 +105,14 @@ OGRErr OGRSOSILayer::ICreateFeature(OGRFeature *poFeature) {
     /* PutGI for all headers */
     char pszGi[255];
     for (int i=0;i<poFeature->GetFieldCount();i++) {
-		int n = snprintf (pszGi, 255, "%s", poFeature->GetFieldDefnRef(i)->GetNameRef());
-		if (n<255) {
-			/*int m = */snprintf (pszGi + (n-1), 255-n, "%s", poFeature->GetFieldAsString(i));
-			/* check overflow */
-		}
-		LC_PutGi(i+2, pszGi); /* should add headers too */
-	}
-	//LC_OppdaterEndret(0);
+        int n = snprintf (pszGi, 255, "%s", poFeature->GetFieldDefnRef(i)->GetNameRef());
+        if (n<255) {
+            /*int m = */snprintf (pszGi + (n-1), 255-n, "%s", poFeature->GetFieldAsString(i));
+          /* check overflow */
+        }
+        LC_PutGi(i+2, pszGi); /* should add headers too */
+    }
+    // LC_OppdaterEndret(0);
     /* PutTK for all coords */
     /* ... */
     /* === /WIP - Work in progress === */
@@ -267,6 +268,7 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
         }
         case L_SYMBOL: {
             //CPLError( CE_Warning, CPLE_OpenFailed, "Geometry of type SYMBOL treated as point (PUNKT).");
+            CPL_FALLTHROUGH
         }
         case L_PUNKT: {  /* point */
             oGType = wkbPoint;
@@ -297,7 +299,7 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
         OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
         /* set all headers found in this group - we export everything, just in case */
-        for (iHeaders = oHeaders.begin(); iHeaders != oHeaders.end(); iHeaders++) {
+        for (iHeaders = oHeaders.begin(); iHeaders != oHeaders.end(); ++iHeaders) {
             OGRSOSIDataType *poType = SOSIGetType(iHeaders->first);
             OGRSOSISimpleDataType *poElements = poType->getElements();
 
@@ -310,9 +312,9 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
                 if (strcmp(poElements[k].GetName(),"")==0) continue;
                 int iHNr = poHeaderDefn->find(poElements[k].GetName())->second;
                 if (iHNr == -1) {
-	    			CPLError( CE_Warning, CPLE_AppDefined, "Could not find field definition for %s.", poElements[k].GetName());
+                    CPLError( CE_Warning, CPLE_AppDefined, "Could not find field definition for %s.", poElements[k].GetName());
                     continue;
-    			}
+                }
                 OGRFieldType nType = poElements[k].GetType();
                 switch (nType) {
                   case OFTInteger: {
@@ -328,7 +330,7 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
                   case OFTDateTime: {
                     int date[6];
                     SOSITypeToDateTime(tokens[k], date);
-                    if (date[0]>0) 
+                    if (date[0]>0)
                       poFeature->SetField( iHNr, date[0], date[1], date[2], date[3], date[4], static_cast<float>(date[5]), 1);
                     break;
                   }
@@ -336,9 +338,9 @@ OGRFeature *OGRSOSILayer::GetNextFeature() {
                     poFeature->SetField( iHNr, SOSITypeToReal(tokens[k]));
                     break;
                   }
-                  default: { 
+                  default: {
                     if ((k==0)&&((pszLine[0] == '\'')||(pszLine[0] == '\"'))) { /* If the value is quoted, ignore these */
-                        int nLen = strlen(pszLine);
+                        int nLen = static_cast<int>(strlen(pszLine));
                         char *pszNline = (char*)CPLMalloc(nLen-1);
                         strncpy(pszNline, pszLine+1, nLen-2);
                         pszNline[nLen-2] = '\0';
diff --git a/ogr/ogrsf_frmts/sosi/tools/README b/ogr/ogrsf_frmts/sosi/tools/README
index e3fa1eb..4fa13ee 100644
--- a/ogr/ogrsf_frmts/sosi/tools/README
+++ b/ogr/ogrsf_frmts/sosi/tools/README
@@ -2,6 +2,6 @@ Use this script to create a valid "ogrsosidatatypes.h" include file based on the
 
 http://www.primar.org/statkart.ny.no/nor/SOSI/SOSI-std/SOSI-db_versjoner/SOSI-db+-+SOSI+standarden+i+en+Access-database.d25-SwBDU1O.ips
 
-Note: to avoid too big files to be kept in SVN,  Elementdefinisjoner.xml and 
+Note: to avoid too big files to be kept in SVN,  Elementdefinisjoner.xml and
 Gruppeelement_sammensetning.xml have been put in http://download.osgeo.org/gdal/tools/sosi/
 Download them locally before running the script.
diff --git a/ogr/ogrsf_frmts/sosi/tools/groupelements.xslt b/ogr/ogrsf_frmts/sosi/tools/groupelements.xslt
index efbb88b..6ea7632 100644
--- a/ogr/ogrsf_frmts/sosi/tools/groupelements.xslt
+++ b/ogr/ogrsf_frmts/sosi/tools/groupelements.xslt
@@ -31,7 +31,7 @@ OGRSOSIDataType <xsl:value-of select="$dtnsafe" />Type = OGRSOSIDataType(<xsl:va
    <xsl:variable name="oft">
     <xsl:for-each select="//Elementdefinisjoner[elementnavn=$elemtyp]">
       <xsl:choose>
-        <xsl:when test="verditype='T'">OFTString</xsl:when> 
+        <xsl:when test="verditype='T'">OFTString</xsl:when>
         <xsl:when test="verditype='H'">OFTInteger</xsl:when>
         <xsl:when test="verditype='D'">OFTReal</xsl:when>
         <xsl:when test="verditype='DATO'">OFTDate</xsl:when>
@@ -43,7 +43,7 @@ OGRSOSIDataType <xsl:value-of select="$dtnsafe" />Type = OGRSOSIDataType(<xsl:va
    </xsl:variable>
 
    <xsl:if test="./datatypenavn">
-<xsl:value-of select="$dtnsafe" />Type.setElement(<xsl:value-of select="rekkefølge -1" />, "<xsl:value-of select="egenskapsnavn" />", <xsl:value-of select="$oft" />); 
+<xsl:value-of select="$dtnsafe" />Type.setElement(<xsl:value-of select="rekkefølge -1" />, "<xsl:value-of select="egenskapsnavn" />", <xsl:value-of select="$oft" />);
    </xsl:if>
   </xsl:for-each>
 
diff --git a/ogr/ogrsf_frmts/sqlite/GNUmakefile b/ogr/ogrsf_frmts/sqlite/GNUmakefile
index c30042a..f08d975 100644
--- a/ogr/ogrsf_frmts/sqlite/GNUmakefile
+++ b/ogr/ogrsf_frmts/sqlite/GNUmakefile
@@ -4,7 +4,8 @@ include ../../../GDALmake.opt
 
 OBJ	=	ogrsqlitedatasource.o ogrsqlitelayer.o ogrsqlitedriver.o \
 		ogrsqlitetablelayer.o ogrsqliteviewlayer.o ogrsqliteselectlayer.o ogrsqlitesinglefeaturelayer.o \
-		ogrsqlitevfs.o ogrsqlitevirtualogr.o ogrsqliteexecutesql.o ogrsqliteapiroutines.o
+		ogrsqlitevfs.o ogrsqlitevirtualogr.o ogrsqliteexecutesql.o ogrsqliteapiroutines.o \
+		rasterlite2.o ogrsqliteutility.o
 
 ifeq ($(HAVE_SPATIALITE),yes)
 CPPFLAGS +=  -DHAVE_SPATIALITE
@@ -30,6 +31,10 @@ ifeq ($(SQLITE_HAS_COLUMN_METADATA),yes)
 CPPFLAGS +=  -DSQLITE_HAS_COLUMN_METADATA
 endif
 
+ifeq ($(HAVE_RASTERLITE2),yes)
+CPPFLAGS +=  -DHAVE_RASTERLITE2 $(RASTERLITE2_CFLAGS)
+endif
+
 CPPFLAGS	:=	-I..  $(SQLITE_INC) $(SPATIALITE_INC) $(CPPFLAGS)
 
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
diff --git a/ogr/ogrsf_frmts/sqlite/drv_sqlite.html b/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
index ac3794c..ffc6a74 100644
--- a/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
+++ b/ogr/ogrsf_frmts/sqlite/drv_sqlite.html
@@ -12,14 +12,25 @@ database files.  SQLite is a "light weight" single file based RDBMS engine
 with fairly complete SQL semantics and respectable performance.</p>
 
 <p>The driver can handle "regular" SQLite databases, as well as Spatialite
-databases (spatial enabled SQLite databases).</p>
+databases (spatial enabled SQLite databases). The type of an existing database
+can be checked from the SQLITE debug info value "OGR style SQLite DB found/
+SpatiaLite DB found/SpatiaLite v4 DB found" obtained by running
+<strong>"ogrinfo db.sqlite --debug on"</strong>
+</p>
+
+<p>Starting with GDAL 2.20, the SQLite driver can also read databases with
+<a href="frmt_rasterlite2.html">RasterLite2 raster coverages</a>.</p>
 
 <p>The SQLite database is essentially typeless, but the SQLite driver will
 attempt to classify attributes field as text, integer or floating point
-based on the contents of the first record in a table.  None of the list
-attribute field types existing in SQLite. Starting with OGR 1.10, datetime
+based on the contents of the first record in a table.  Starting with OGR 1.10, datetime
 field types are also handled.</p>
 
+<p>Starting with GDAL 2.2, the "JSonStringList", "JSonIntegerList", "JSonInteger64List"
+and "JSonRealList" SQLite declaration types are used to map the corresponding OGR StringList,
+IntegerList, Integer64List and RealList types. The field values are then encoded as
+JSon arrays, with proper CSV escaping.</p>
+
 <p>SQLite databases often due not work well over NFS, or some other networked
 file system protocols due to the poor support for locking.  It is safest
 to operate only on SQLite files on a physical disk of the local system.</p>
@@ -230,7 +241,7 @@ potential safety issues.<p>
 geometry_columns and spatial_ref_sys tables in a new database.  By default
 these metadata tables are created when a new database is created.</p></li>
 
-<li><p><b>SPATIALITE=YES/NO</b>: (Starting with GDAL 1.7.0) Create the SpatiaLite flavour of the metadata
+<li><p><b>SPATIALITE=YES/NO</b>: (Starting with GDAL 1.7.0) Create the SpatiaLite flavor of the metadata
 tables, which are a bit differ from the metadata used by this OGR driver and
 from OGC specifications. Implies <b>METADATA=YES</b>.<br>
 Please note: (Starting with GDAL 1.9.0) OGR must be linked against <i>libspatialite</i> in order to support
@@ -271,11 +282,11 @@ case and some special characters(' - #) will be changed to underscores. Default
 to YES.</p></li>
 
 <li><p><b>SPATIAL_INDEX=YES/NO</b>: (Starting with GDAL 1.7.0) If the database is
-of the SpatiaLite flavour, and if OGR is linked against libspatialite, this option
+of the SpatiaLite flavor, and if OGR is linked against libspatialite, this option
 can be used to control if a spatial index must be created. Default to YES.</p></li>
 
 <li><p><b>COMPRESS_GEOM=YES/NO</b>: (Starting with GDAL 1.9.0) If the format of the
-geometry BLOB is of the SpatiaLite flavour, this option can be used to control
+geometry BLOB is of the SpatiaLite flavor, this option can be used to control
 if the compressed format for geometries (LINESTRINGs, POLYGONs) must be used. This
 format is understood by Spatialite v2.4 (or any subsequent version). Default to NO.
 Note: when updating an existing Spatialite DB, the COMPRESS_GEOM configuration option
@@ -362,6 +373,7 @@ If a database has gone through editing operations, it might be useful to run a
 <li><a href="http://www.sqlite.org/">http://www.sqlite.org</a>: Main SQLite page.
 <li> <a href="http://www.gaia-gis.it/spatialite/">http://www.gaia-gis.it/spatialite/</a>: SpatiaLite extension to SQLite.
 <li> <A href="http://trac.osgeo.org/fdo/wiki/FDORfc16">FDO RFC 16</a>: FDO Provider for SQLite</li>
+<li><a href="frmt_rasterlite2.html">RasterLite2 driver</a></li>
 </ul>
 
 </body>
diff --git a/ogr/ogrsf_frmts/sqlite/frmt_rasterlite2.html b/ogr/ogrsf_frmts/sqlite/frmt_rasterlite2.html
new file mode 100644
index 0000000..6ff15b8
--- /dev/null
+++ b/ogr/ogrsf_frmts/sqlite/frmt_rasterlite2.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>RasterLite2 - Rasters in SQLite DB</title>
+</head>
+
+<body>
+
+<h1>RasterLite2 - Rasters in SQLite DB</h1>
+
+<p>Starting with GDAL 2.2, the SQLite driver allows reading and writing SQLite
+databases containing RasterLite2 coverages.</p>
+<p>
+  Those databases can be produced by the utilities of the
+  <a href="https://www.gaia-gis.it/fossil/librasterlite2/home">RasterLite2</a> distribution,
+  such as rl2tools.<br>
+  The driver supports reading grayscale, paletted, RGB, multispectral images stored as tiles in the many compressed formats supported by libRasterLite2.
+  The driver also supports reading overviews/pyramids, spatial reference system and spatial extent.
+</p>
+
+<p>GDAL/OGR must be compiled with sqlite support and against librasterlite2 and libspatialite.</p>
+
+<p>The driver is implemented a unified SQLite / SpatiaLite / RasterLite2
+vector and raster capable driver./p>
+
+<h2>Opening syntax</h2>
+
+<p>A RasterLite2 filename can be specified as the connection string. If the
+file contains a single RasterLite2 coverage, this one will be exposed as the
+GDAL dataset. If the file contains multiple coverages, each one will be exposed
+as a subdataset with the syntax RASTERLITE2:filename:coverage_name. See
+<a href="https://www.gaia-gis.it/fossil/librasterlite2/wiki?name=basic_concepts">the
+basic concepts of RasterLite2</a>.</p>
+
+<p>If a coverage is made of several sections, they will be listed as subdatasets
+of the coverage dataset, so as to be accessed individually. By default, they
+will be exposed as a unified dataset. The syntax of section-based dataset is
+RASTERLITE2:filename:coverage_name:section_id:section_name.</p>
+
+<h2>Creation</h2>
+
+The driver supports creating new databases from scratch, adding new coverages to
+an existing database and adding sections to an existing coverage.
+
+<h2>Creation options</h2>
+
+<ul>
+<li> <b>APPEND_SUBDATASET</b>=YES/NO: Whether to add the raster to the existing
+file. If set to YES, COVERAGE must be specified. Default is NO (ie overwrite
+existing file)</li>
+<li> <b>COVERAGE</b>=string: Coverage name. If not specified, the basename of
+the output file is used.</li>
+<li> <b>SECTION</b>=string: Section name. If not specified, the basename of
+the output file is used.</li>
+<li> <b>COMPRESS</b>=NONE/DEFLATE/LZMA/PNG/CCITTFAX4/JPEG/WEBP/CHARS/JPEG2000:
+Compression method. Default is NONE. See the
+<a href="https://www.gaia-gis.it/fossil/librasterlite2/wiki?name=codecs">
+information about supported codecs</a>. Note that some codecs may not be
+available depending on how librasterlite2 has been built.</li>
+<li> <b>QUALITY</b>=0 to 100: Image quality for JPEG, WEBP and JPEG2000
+compressions. Exact meaning depends on the compression method. For WEBP and
+JPEG2000, the value 100 triggers the use of their lossless variants.</li>
+<li> <b>PIXEL_TYPE</b>=MONOCHROME/PALETTE/GRAYSCALE/RGB/MULTIBAND/DATAGRID:
+Raster pixel type. Determines the photometric interpretation. See the
+<a href="https://www.gaia-gis.it/fossil/librasterlite2/wiki?name=reference_table">
+information about supported pixel types</a>. The driver will
+automatically determine an appropriate pixel type given the band characteristics.
+</li>
+<li> <b>BLOCKXSIZE</b>=int_value. Block width. Defaults to 512.</li>
+<li> <b>BLOCKYSIZE</b>=int_value. Block height. Defaults to 512.</li>
+<li> <b>NBITS</b>=1/2/4. Force bit width. This will be by default gotten from
+the NBITS metadata item in the IMAGE_STRUCTURE metadata domain of the source
+raster band.</li>
+<li> <b>PYRAMIDIZE</b>=YES/NO. Whether to build automatically build relevant
+pyramids/overviews. Defaults to NO. Pyramids can be built with the BuildOverviews() /
+gdaladdo.
+</ul>
+
+<h2>Examples</h2>
+
+<ul>
+
+<li>Reading a RasterLite2 database with a single coverage:
+
+<pre>
+gdalinfo my.rl2
+</pre>
+
+<li>Listing the subdatasets corresponding to the coverages of a RasterLite2
+database with several coverages:
+
+<pre>
+gdalinfo multiple_coverages.rl2
+</pre>
+
+<li>Reading a subdataset corresponding to a coverage:
+
+<pre>
+gdalinfo RASTERLITE2:multiple_coverages.rl2:my_coverage
+</pre>
+
+<li>Creating a RasterLite2 dataset from a grayscale image:
+
+<pre>
+gdal_translate -f SQLite byte.tif byte.rl2
+</pre>
+
+<li>Creating a RasterLite2 dataset from a RGB image, and using JPEG compression:
+
+<pre>
+gdal_translate -f SQLite rgb.tif rgb.rl2 -co COMPRESS=JPEG
+</pre>
+
+<li>Adding a RasterLite2 coverage to an existing SpatiaLite/RasterLite2 database:
+
+<pre>
+gdal_translate -f SQLite rgb.tif rgb.rl2 -co APPEND_SUBDATASET=YES -co COVERAGE=rgb
+</pre>
+
+<li>Adding pyramids to a coverage:
+
+<pre>
+gdaladdo rgb.rl2 2 4 8 16
+</pre>
+
+</ul>
+
+<p>See Also:</p>
+
+<ul>
+<li><a href="https://www.gaia-gis.it/fossil/libRasterLite2/home">Rasterlite2 home page</a></li>
+<li><a href="drv_sqlite.html">OGR SQLite driver</a></li>
+</ul>
+
+</body>
+</html>
diff --git a/ogr/ogrsf_frmts/sqlite/makefile.vc b/ogr/ogrsf_frmts/sqlite/makefile.vc
index 4b5d5f2..8ee054c 100644
--- a/ogr/ogrsf_frmts/sqlite/makefile.vc
+++ b/ogr/ogrsf_frmts/sqlite/makefile.vc
@@ -2,7 +2,8 @@
 OBJ	=	ogrsqlitedriver.obj ogrsqlitedatasource.obj \
 		ogrsqlitelayer.obj ogrsqlitetablelayer.obj ogrsqliteviewlayer.obj  \
 		ogrsqliteselectlayer.obj ogrsqlitesinglefeaturelayer.obj \
-		ogrsqlitevfs.obj ogrsqlitevirtualogr.obj ogrsqliteexecutesql.obj
+		ogrsqlitevfs.obj ogrsqlitevirtualogr.obj ogrsqliteexecutesql.obj \
+		rasterlite2.obj ogrsqliteutility.obj
 
 GDAL_ROOT	=	..\..\..
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h b/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
index d1ddae4..d20c570 100644
--- a/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
+++ b/ogr/ogrsf_frmts/sqlite/ogr_sqlite.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sqlite.h 36600 2016-12-01 13:59:11Z rouault $
+ * $Id: ogr_sqlite.h 37810 2017-03-20 16:23:30Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/SQLite driver.
@@ -61,10 +61,7 @@
 #include "sqlite3.h"
 #endif
 
-#if SQLITE_VERSION_NUMBER >= 3006000
-#define HAVE_SQLITE_VFS
-#define HAVE_SQLITE3_PREPARE_V2
-#endif
+#include "rasterlite2_header.h"
 
 #ifndef DO_NOT_INCLUDE_SQLITE_CLASSES
 
@@ -184,7 +181,7 @@ class OGRSQLiteGeomFieldDefn CPL_FINAL : public OGRGeomFieldDefn
 class OGRSQLiteFeatureDefn CPL_FINAL : public OGRFeatureDefn
 {
     public:
-        OGRSQLiteFeatureDefn( const char * pszName = NULL ) :
+        explicit OGRSQLiteFeatureDefn( const char * pszName = NULL ) :
             OGRFeatureDefn(pszName)
         {
             SetGeomType(wkbNone);
@@ -272,36 +269,38 @@ class OGRSQLiteLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
 
     int                 bAllowMultipleGeomFields;
 
+    static
     CPLString           FormatSpatialFilterFromRTree(OGRGeometry* poFilterGeom,
                                                        const char* pszRowIDName,
                                                        const char* pszEscapedTable,
                                                        const char* pszEscapedGeomCol);
+
+    static
     CPLString           FormatSpatialFilterFromMBR(OGRGeometry* poFilterGeom,
                                                    const char* pszEscapedGeomColName);
 
-
   public:
                         OGRSQLiteLayer();
     virtual             ~OGRSQLiteLayer();
 
     virtual void        Finalize();
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
     virtual OGRFeature *GetNextRawFeature();
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRFeatureDefn *GetLayerDefn() { return poFeatureDefn; }
+    virtual OGRFeatureDefn *GetLayerDefn() override { return poFeatureDefn; }
     virtual OGRSQLiteFeatureDefn *myGetLayerDefn() { return poFeatureDefn; }
 
-    virtual const char *GetFIDColumn();
+    virtual const char *GetFIDColumn() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRErr       StartTransaction();
-    virtual OGRErr       CommitTransaction();
-    virtual OGRErr       RollbackTransaction();
+    virtual OGRErr       StartTransaction() override;
+    virtual OGRErr       CommitTransaction() override;
+    virtual OGRErr       RollbackTransaction() override;
 
     virtual void        InvalidateCachedFeatureCountAndExtent() { }
 
@@ -309,10 +308,19 @@ class OGRSQLiteLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
 
     virtual int          HasSpatialIndex(CPL_UNUSED int iGeomField) { return FALSE; }
 
-    virtual int           HasFastSpatialFilter(CPL_UNUSED int iGeomCol) { return FALSE; }
+    virtual int           HasFastSpatialFilter(CPL_UNUSED int iGeomCol) override { return FALSE; }
     virtual CPLString     GetSpatialWhere(CPL_UNUSED int iGeomCol,
-                                          CPL_UNUSED OGRGeometry* poFilterGeom) { return ""; }
-
+                                          CPL_UNUSED OGRGeometry* poFilterGeom) override { return ""; }
+
+    static OGRErr       GetSpatialiteGeometryHeader( const GByte *pabyData,
+                                                    int nBytes,
+                                                    int* pnSRID,
+                                                    OGRwkbGeometryType* peType,
+                                                    bool* pbIsEmpty,
+                                                    double* pdfMinX,
+                                                    double* pdfMinY,
+                                                    double* pdfMaxX,
+                                                    double* pdfMaxY );
     static OGRErr       ImportSpatiaLiteGeometry( const GByte *, int,
                                                   OGRGeometry ** );
     static OGRErr       ImportSpatiaLiteGeometry( const GByte *, int,
@@ -320,7 +328,6 @@ class OGRSQLiteLayer : public OGRLayer, public IOGRSQLiteGetSpatialWhere
     static OGRErr       ExportSpatiaLiteGeometry( const OGRGeometry *,
                                                   GInt32, OGRwkbByteOrder,
                                                   int, int bUseComprGeom, GByte **, int * );
-
 };
 
 /************************************************************************/
@@ -345,16 +352,16 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
     CPLString           osLastInsertStmt;
 
     int                 bHasCheckedTriggers;
+    bool                m_bHasTriedDetectingFID64;
 
     void                ClearInsertStmt();
 
-    void                BuildWhere(void);
+    void                BuildWhere();
 
-    virtual OGRErr      ResetStatement();
+    virtual OGRErr      ResetStatement() override;
 
     OGRErr              RecomputeOrdinals();
 
-    OGRErr              AddColumnAncientMethod( OGRFieldDefn& oField);
     void                AddColumnDef(char* pszNewFieldList, size_t nBufLen,
                                      OGRFieldDefn* poFldDefn);
 
@@ -366,8 +373,8 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
                                       const char* pszNewFieldList,
                                       const char* pszGenericErrorMessage);
     OGRErr              BindValues( OGRFeature *poFeature,
-                                        sqlite3_stmt* hStmt,
-                                        int bBindNullValues );
+                                    sqlite3_stmt* hStmt,
+                                    bool bBindUnsetAsNull );
 
     int                 CheckSpatialIndexTable(int iGeomCol);
 
@@ -389,8 +396,8 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
     int                 iFIDAsRegularColumnIndex;
 
   public:
-                        OGRSQLiteTableLayer( OGRSQLiteDataSource * );
-                        ~OGRSQLiteTableLayer();
+    explicit            OGRSQLiteTableLayer( OGRSQLiteDataSource * );
+                        virtual ~OGRSQLiteTableLayer();
 
     CPLErr              Initialize( const char *pszTableName,
                                     int bIsVirtualShapeIn,
@@ -401,38 +408,38 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
                                                const char *pszGeometryName,
                                                OGRSpatialReference *poSRS,
                                                int nSRSId );
-    virtual const char* GetName();
+    virtual const char* GetName() override;
 
-    virtual GIntBig     GetFeatureCount( int );
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce);
+    virtual GIntBig     GetFeatureCount( int ) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override;
 
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual OGRFeatureDefn *GetLayerDefn() override;
     int                 HasLayerDefnError() { GetLayerDefn(); return bLayerDefnError; }
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
-    virtual OGRErr      SetAttributeFilter( const char * );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
-                                         int bApproxOK = TRUE );
-    virtual OGRErr      DeleteField( int iField );
-    virtual OGRErr      ReorderFields( int* panMap );
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags );
+                                         int bApproxOK = TRUE ) override;
+    virtual OGRErr      DeleteField( int iField ) override;
+    virtual OGRErr      ReorderFields( int* panMap ) override;
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
 
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual char      **GetMetadata( const char * pszDomain = "" );
+    virtual char      **GetMetadata( const char * pszDomain = "" ) override;
     virtual const char *GetMetadataItem( const char * pszName,
-                                         const char * pszDomain = "" );
+                                         const char * pszDomain = "" ) override;
 
     // follow methods are not base class overrides
     void                SetLaunderFlag( int bFlag )
@@ -453,14 +460,14 @@ class OGRSQLiteTableLayer : public OGRSQLiteLayer
     int                 AreStatisticsValid();
     int                 SaveStatistics();
 
-    virtual void        InvalidateCachedFeatureCountAndExtent();
+    virtual void        InvalidateCachedFeatureCountAndExtent() override;
 
-    virtual int          IsTableLayer() { return TRUE; }
+    virtual int          IsTableLayer() override { return TRUE; }
 
-    virtual int          HasSpatialIndex(int iGeomField);
-    virtual int          HasFastSpatialFilter(int iGeomCol);
+    virtual int          HasSpatialIndex(int iGeomField) override;
+    virtual int          HasFastSpatialFilter(int iGeomCol) override;
     virtual CPLString    GetSpatialWhere(int iGeomCol,
-                                         OGRGeometry* poFilterGeom);
+                                         OGRGeometry* poFilterGeom) override;
 
     OGRErr               RunDeferredCreationIfNecessary();
 };
@@ -491,18 +498,18 @@ class OGRSQLiteViewLayer : public OGRSQLiteLayer
     OGRSQLiteLayer     *poUnderlyingLayer;
     OGRSQLiteLayer     *GetUnderlyingLayer();
 
-    void                BuildWhere(void);
+    void                BuildWhere();
 
-    virtual OGRErr      ResetStatement();
+    virtual OGRErr      ResetStatement() override;
 
     CPLErr              EstablishFeatureDefn();
 
   public:
-                        OGRSQLiteViewLayer( OGRSQLiteDataSource * );
-                        ~OGRSQLiteViewLayer();
+    explicit            OGRSQLiteViewLayer( OGRSQLiteDataSource * );
+                        virtual ~OGRSQLiteViewLayer();
 
-    virtual const char* GetName() { return pszViewName; }
-    virtual OGRwkbGeometryType GetGeomType();
+    virtual const char* GetName() override { return pszViewName; }
+    virtual OGRwkbGeometryType GetGeomType() override;
 
     CPLErr              Initialize( const char *pszViewName,
                                     const char *pszViewGeometry,
@@ -510,24 +517,24 @@ class OGRSQLiteViewLayer : public OGRSQLiteLayer
                                     const char *pszTableName,
                                     const char *pszGeometryColumn);
 
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual OGRFeatureDefn *GetLayerDefn() override;
     int                 HasLayerDefnError() { GetLayerDefn(); return bLayerDefnError; }
 
-    virtual OGRFeature *GetNextFeature();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual OGRFeature *GetNextFeature() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRSQLiteLayer::SetSpatialFilter(iGeomField, poGeom); }
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual int          HasSpatialIndex(CPL_UNUSED int iGeomField) { return bHasSpatialIndex; }
+    virtual int          HasSpatialIndex(CPL_UNUSED int iGeomField) override { return bHasSpatialIndex; }
     virtual CPLString    GetSpatialWhere(int iGeomCol,
-                                         OGRGeometry* poFilterGeom);
+                                         OGRGeometry* poFilterGeom) override;
 };
 
 /************************************************************************/
@@ -601,7 +608,7 @@ class OGRSQLiteSelectLayer : public OGRSQLiteLayer, public IOGRSQLiteSelectLayer
 {
     OGRSQLiteSelectLayerCommonBehaviour* poBehaviour;
 
-    virtual OGRErr      ResetStatement();
+    virtual OGRErr      ResetStatement() override;
 
   public:
                         OGRSQLiteSelectLayer( OGRSQLiteDataSource *,
@@ -610,37 +617,37 @@ class OGRSQLiteSelectLayer : public OGRSQLiteLayer, public IOGRSQLiteSelectLayer
                                               int bUseStatementForGetNextFeature,
                                               int bEmptyLayer,
                                               int bAllowMultipleGeomFields );
-                       ~OGRSQLiteSelectLayer();
-
-    virtual void        ResetReading();
-
-    virtual OGRFeature *GetNextFeature();
-    virtual GIntBig     GetFeatureCount( int );
-
-    virtual void        SetSpatialFilter( OGRGeometry * poGeom ) { SetSpatialFilter(0, poGeom); }
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * );
-    virtual OGRErr      SetAttributeFilter( const char * );
-
-    virtual int         TestCapability( const char * );
-
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) { return GetExtent(0, psExtent, bForce); }
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE);
-
-    virtual OGRFeatureDefn *     GetLayerDefn() { return OGRSQLiteLayer::GetLayerDefn(); }
-    virtual char*&               GetAttrQueryString() { return m_pszAttrQueryString; }
-    virtual OGRFeatureQuery*&    GetFeatureQuery() { return m_poAttrQuery; }
-    virtual OGRGeometry*&        GetFilterGeom() { return m_poFilterGeom; }
-    virtual int&                 GetIGeomFieldFilter() { return m_iGeomFieldFilter; }
-    virtual OGRSpatialReference* GetSpatialRef() { return OGRSQLiteLayer::GetSpatialRef(); }
-    virtual int                  InstallFilter( OGRGeometry * poGeomIn ) { return OGRSQLiteLayer::InstallFilter(poGeomIn); }
-    virtual int                  HasReadFeature() { return iNextShapeId > 0; }
-    virtual void                 BaseResetReading() { OGRSQLiteLayer::ResetReading(); }
-    virtual OGRFeature          *BaseGetNextFeature() { return OGRSQLiteLayer::GetNextFeature(); }
-    virtual OGRErr               BaseSetAttributeFilter(const char* pszQuery) { return OGRSQLiteLayer::SetAttributeFilter(pszQuery); }
-    virtual GIntBig              BaseGetFeatureCount(int bForce) { return OGRSQLiteLayer::GetFeatureCount(bForce); }
-    virtual int                  BaseTestCapability( const char *pszCap ) { return OGRSQLiteLayer::TestCapability(pszCap); }
-    virtual OGRErr               BaseGetExtent(OGREnvelope *psExtent, int bForce) { return OGRSQLiteLayer::GetExtent(psExtent, bForce); }
-    virtual OGRErr               BaseGetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) { return OGRSQLiteLayer::GetExtent(iGeomField, psExtent, bForce); }
+                       virtual ~OGRSQLiteSelectLayer();
+
+    virtual void        ResetReading() override;
+
+    virtual OGRFeature *GetNextFeature() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
+
+    virtual void        SetSpatialFilter( OGRGeometry * poGeom ) override { SetSpatialFilter(0, poGeom); }
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * ) override;
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
+
+    virtual int         TestCapability( const char * ) override;
+
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override { return GetExtent(0, psExtent, bForce); }
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce = TRUE) override;
+
+    virtual OGRFeatureDefn *     GetLayerDefn() override { return OGRSQLiteLayer::GetLayerDefn(); }
+    virtual char*&               GetAttrQueryString() override { return m_pszAttrQueryString; }
+    virtual OGRFeatureQuery*&    GetFeatureQuery() override { return m_poAttrQuery; }
+    virtual OGRGeometry*&        GetFilterGeom() override { return m_poFilterGeom; }
+    virtual int&                 GetIGeomFieldFilter() override { return m_iGeomFieldFilter; }
+    virtual OGRSpatialReference* GetSpatialRef() override { return OGRSQLiteLayer::GetSpatialRef(); }
+    virtual int                  InstallFilter( OGRGeometry * poGeomIn ) override { return OGRSQLiteLayer::InstallFilter(poGeomIn); }
+    virtual int                  HasReadFeature() override { return iNextShapeId > 0; }
+    virtual void                 BaseResetReading() override { OGRSQLiteLayer::ResetReading(); }
+    virtual OGRFeature          *BaseGetNextFeature() override { return OGRSQLiteLayer::GetNextFeature(); }
+    virtual OGRErr               BaseSetAttributeFilter(const char* pszQuery) override { return OGRSQLiteLayer::SetAttributeFilter(pszQuery); }
+    virtual GIntBig              BaseGetFeatureCount(int bForce) override { return OGRSQLiteLayer::GetFeatureCount(bForce); }
+    virtual int                  BaseTestCapability( const char *pszCap ) override { return OGRSQLiteLayer::TestCapability(pszCap); }
+    virtual OGRErr               BaseGetExtent(OGREnvelope *psExtent, int bForce) override { return OGRSQLiteLayer::GetExtent(psExtent, bForce); }
+    virtual OGRErr               BaseGetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override { return OGRSQLiteLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
 /************************************************************************/
@@ -660,12 +667,12 @@ class OGRSQLiteSingleFeatureLayer CPL_FINAL : public OGRLayer
                                                      int nVal );
                         OGRSQLiteSingleFeatureLayer( const char* pszLayerName,
                                                      const char *pszVal );
-                        ~OGRSQLiteSingleFeatureLayer();
+                        virtual ~OGRSQLiteSingleFeatureLayer();
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
-    virtual OGRFeatureDefn *GetLayerDefn();
-    virtual int         TestCapability( const char * );
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
+    virtual OGRFeatureDefn *GetLayerDefn() override;
+    virtual int         TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -681,16 +688,14 @@ class OGRSQLiteBaseDataSource : public GDALPamDataset
     sqlite3             *hDB;
     int                 bUpdate;
 
-#ifdef HAVE_SQLITE_VFS
     sqlite3_vfs*        pMyVFS;
-#endif
 
     VSILFILE*           fpMainFile; /* Set by the VFS layer when it opens the DB */
                                     /* Must *NOT* be closed by the datasource explicitly. */
 
     int                 OpenOrCreateDB(int flags, int bRegisterOGR2SQLiteExtensions);
-    int                 SetSynchronous();
-    int                 SetCacheSize();
+    bool                SetSynchronous();
+    bool                SetCacheSize();
 
     void                CloseDB();
 
@@ -701,6 +706,11 @@ class OGRSQLiteBaseDataSource : public GDALPamDataset
     bool                InitNewSpatialite();
     void                FinishNewSpatialite();
 #endif
+#ifdef HAVE_RASTERLITE2
+    void               *m_hRL2Ctxt;
+    bool                InitRasterLite2();
+    void                FinishRasterLite2();
+#endif
 
     int                 bUserTransactionActive;
     int                 nSoftTransactionLevel;
@@ -709,7 +719,7 @@ class OGRSQLiteBaseDataSource : public GDALPamDataset
 
   public:
                         OGRSQLiteBaseDataSource();
-                        ~OGRSQLiteBaseDataSource();
+                        virtual ~OGRSQLiteBaseDataSource();
 
     sqlite3            *GetDB() { return hDB; }
     int                 GetUpdate() const { return bUpdate; }
@@ -722,13 +732,13 @@ class OGRSQLiteBaseDataSource : public GDALPamDataset
 
     virtual std::pair<OGRLayer*, IOGRSQLiteGetSpatialWhere*> GetLayerWithGetSpatialWhereByName( const char* pszName ) = 0;
 
-    virtual OGRErr      StartTransaction(int bForce = FALSE);
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction(int bForce = FALSE) override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual void *GetInternalHandle( const char * );
+    virtual void *GetInternalHandle( const char * ) override;
 
     OGRErr              SoftStartTransaction();
     OGRErr              SoftCommitTransaction();
@@ -777,11 +787,34 @@ class OGRSQLiteDataSource CPL_FINAL : public OGRSQLiteBaseDataSource
 
     std::vector<OGRLayer*> apoInvisibleLayers;
 
+#ifdef HAVE_RASTERLITE2
+    CPLString           m_osCoverageName;
+    GIntBig             m_nSectionId;
+    rl2CoveragePtr      m_pRL2Coverage;
+    bool                m_bRL2MixedResolutions;
+#endif
+    CPLStringList       m_aosSubDatasets;
+    bool                m_bGeoTransformValid;
+    double              m_adfGeoTransform[6];
+    CPLString           m_osProjection;
+    bool                m_bPromote1BitAs8Bit;
+    bool                OpenRaster();
+    bool                OpenRasterSubDataset(const char* pszConnectionId);
+    OGRSQLiteDataSource* m_poParentDS;
+    std::vector<OGRSQLiteDataSource*> m_apoOverviewDS;
+
+#ifdef HAVE_RASTERLITE2
+    void                ListOverviews();
+    void                CreateRL2OverviewDatasetIfNeeded(double dfXRes,
+                                                      double dfYRes);
+#endif
+
   public:
                         OGRSQLiteDataSource();
-                        ~OGRSQLiteDataSource();
+                        virtual ~OGRSQLiteDataSource();
 
-    int                 Open( const char *, int bUpdateIn, char** papszOpenOptions );
+    int                 Open( const char *, int bUpdateIn,
+                              char** papszOpenOptions, int nOpenFlags );
     int                 Create( const char *, char **papszOptions );
 
     int                 OpenTable( const char *pszTableName,
@@ -792,29 +825,34 @@ class OGRSQLiteDataSource CPL_FINAL : public OGRSQLiteBaseDataSource
                                    const char *pszTableName,
                                    const char *pszGeometryColumn);
 
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer   *GetLayer( int );
-    virtual OGRLayer   *GetLayerByName( const char* );
+    virtual int         GetLayerCount() override { return nLayers; }
+    virtual OGRLayer   *GetLayer( int ) override;
+    virtual OGRLayer   *GetLayerByName( const char* ) override;
     OGRLayer           *GetLayerByNameNotVisible( const char* );
-    virtual std::pair<OGRLayer*, IOGRSQLiteGetSpatialWhere*> GetLayerWithGetSpatialWhereByName( const char* pszName );
+    virtual std::pair<OGRLayer*, IOGRSQLiteGetSpatialWhere*> GetLayerWithGetSpatialWhereByName( const char* pszName ) override;
 
     virtual OGRLayer    *ICreateLayer( const char *pszLayerName,
                                       OGRSpatialReference *poSRS,
                                       OGRwkbGeometryType eType,
-                                      char **papszOptions );
-    virtual OGRErr      DeleteLayer(int);
+                                      char **papszOptions ) override;
+    virtual OGRErr      DeleteLayer(int) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+                                    const char *pszDialect ) override;
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
-    virtual void        FlushCache();
+    virtual void        FlushCache() override;
 
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
+
+    virtual char**      GetMetadata(const char* pszDomain = "") override;
+
+    virtual CPLErr      GetGeoTransform( double* padfGeoTransform ) override;
+    virtual const char* GetProjectionRef() override;
 
     char               *LaunderName( const char * );
     int                 FetchSRSId( OGRSpatialReference * poSRS );
@@ -839,17 +877,62 @@ class OGRSQLiteDataSource CPL_FINAL : public OGRSQLiteBaseDataSource
     int                 HasGeometryColumns() const { return bHaveGeometryColumns; }
 
     void                ReloadLayers();
+
+#ifdef HAVE_RASTERLITE2
+    rl2CoveragePtr      GetRL2CoveragePtr() const { return m_pRL2Coverage; }
+    GIntBig             GetSectionId() const { return m_nSectionId; }
+    const double*       GetGeoTransform() const { return m_adfGeoTransform; }
+    bool                IsRL2MixedResolutions() const { return m_bRL2MixedResolutions; }
+
+    virtual CPLErr IBuildOverviews( const char *, int, int *,
+                                    int, int *, GDALProgressFunc, void * ) override;
+
+#endif
+    OGRSQLiteDataSource* GetParentDS() const { return m_poParentDS; }
+    const std::vector<OGRSQLiteDataSource*>& GetOverviews() const { return m_apoOverviewDS; }
+    bool                 HasPromote1BitAS8Bit() const { return m_bPromote1BitAs8Bit; }
 };
 
-#endif /* DO_NOT_INCLUDE_SQLITE_CLASSES */
+#ifdef HAVE_RASTERLITE2
+/************************************************************************/
+/*                           RL2RasterBand                              */
+/************************************************************************/
 
-/* To escape literals. The returned string doesn't contain the surrounding single quotes */
-CPLString OGRSQLiteEscape( const char *pszLiteral );
+class RL2RasterBand CPL_FINAL: public GDALPamRasterBand
+{
+    bool            m_bHasNoData;
+    double          m_dfNoDataValue;
+    GDALColorInterp m_eColorInterp;
+    GDALColorTable* m_poCT;
 
-/* To escape table or field names. The returned string doesn't contain the surrounding double quotes */
-CPLString OGRSQLiteEscapeName( const char* pszName );
+    public:
+                            RL2RasterBand( int nBandIn,
+                                           int nPixelType,
+                                           GDALDataType eDT,
+                                           int nBits,
+                                           bool bPromote1BitAs8Bit,
+                                           bool bSigned,
+                                           int nBlockXSizeIn,
+                                           int nBlockYSizeIn,
+                                           bool bHasNoDataIn,
+                                           double dfNoDataValueIn );
+                            RL2RasterBand( const RL2RasterBand* poOther );
+
+        virtual            ~RL2RasterBand();
+
+    protected:
+
+        virtual CPLErr      IReadBlock( int, int, void* ) override;
+        virtual GDALColorInterp GetColorInterpretation() override
+                                                    { return m_eColorInterp; }
+        virtual double      GetNoDataValue( int* pbSuccess = NULL ) override;
+        virtual GDALColorTable* GetColorTable() override;
+        virtual int         GetOverviewCount() override;
+        virtual GDALRasterBand* GetOverview(int) override;
+};
+#endif // HAVE_RASTERLITE2
 
-CPLString OGRSQLiteParamsUnquote(const char* pszVal);
+#endif /* DO_NOT_INCLUDE_SQLITE_CLASSES */
 
 CPLString OGRSQLiteFieldDefnToSQliteFieldDefn( OGRFieldDefn* poFieldDefn,
                                                int bSQLiteDialectInternalUse );
@@ -857,13 +940,18 @@ CPLString OGRSQLiteFieldDefnToSQliteFieldDefn( OGRFieldDefn* poFieldDefn,
 int OGRSQLITEStringToDateTimeField( OGRFeature* poFeature, int iField,
                                     const char* pszValue );
 
-#ifdef HAVE_SQLITE_VFS
 typedef void (*pfnNotifyFileOpenedType)(void* pfnUserData, const char* pszFilename, VSILFILE* fp);
 sqlite3_vfs* OGRSQLiteCreateVFS(pfnNotifyFileOpenedType pfn, void* pfnUserData);
-#endif
 
 void OGRSQLiteRegisterInflateDeflate(sqlite3* hDB);
 
 void OGRSQLiteDriverUnload(GDALDriver*);
 
+#ifdef HAVE_RASTERLITE2
+GDALDataset *OGRSQLiteDriverCreateCopy( const char *, GDALDataset *,
+                                        int, char **,
+                                        GDALProgressFunc pfnProgress,
+                                        void * pProgressData );
+#endif
+
 #endif /* ndef OGR_SQLITE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h b/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h
index ea51a81..f2d4efe 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlite3ext.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlite3ext.h 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrsqlite3ext.h 34524 2016-07-03 02:47:25Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Custom version of sqlite3ext.h to workaround issues with Spatialite amalgamation
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c b/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c
index 76a2a70..8aa79c2 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteapiroutines.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteapiroutines.c 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: ogrsqliteapiroutines.c 37534 2017-03-01 16:50:58Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Static registration of sqlite3 entry points
@@ -54,11 +54,6 @@
 #include "sqlite3.h"
 #endif
 
-#if SQLITE_VERSION_NUMBER >= 3006000
-#define HAVE_SQLITE_VFS
-#define HAVE_SQLITE3_PREPARE_V2
-#endif
-
 #define DONT_UNDEF_SQLITE3_MACROS
 #ifndef SQLITE_CORE
 #define SQLITE_CORE
@@ -189,17 +184,11 @@ const struct sqlite3_api_routines OGRSQLITE_static_routines =
   /* Added ??? */
  NULL, /*sqlite3_overload_function,*/
   /* Added by 3.3.13 */
-#ifdef HAVE_SQLITE3_PREPARE_V2
  sqlite3_prepare_v2, /* YES */
-#else
- NULL,
-#endif
  NULL, /*sqlite3_prepare16_v2,*/
  NULL, /*sqlite3_clear_bindings,*/
   /* Added by 3.4.1 */
-#ifdef HAVE_SQLITE_VFS
  sqlite3_create_module_v2,
-#endif
   /* Added by 3.5.0 */
  NULL, /*sqlite3_bind_zeroblob,*/
  NULL, /*sqlite3_blob_bytes,*/
@@ -216,25 +205,15 @@ const struct sqlite3_api_routines OGRSQLITE_static_routines =
   NULL, /*sqlite3_mutex_free,*/
   NULL, /*sqlite3_mutex_leave,*/
  NULL, /*sqlite3_mutex_try,*/
-#ifdef HAVE_SQLITE_VFS
  sqlite3_open_v2, /* YES */
-#else
- NULL,
-#endif
  NULL, /*sqlite3_release_memory,*/
   NULL, /*sqlite3_result_error_nomem,*/
   NULL, /*sqlite3_result_error_toobig,*/
  NULL, /*sqlite3_sleep,*/
   NULL, /*sqlite3_soft_heap_limit,*/
-#ifdef HAVE_SQLITE_VFS
-  sqlite3_vfs_find, /* YES */
+ sqlite3_vfs_find, /* YES */
  sqlite3_vfs_register, /* YES */
  sqlite3_vfs_unregister, /* YES */
-#else
- NULL,
- NULL,
- NULL,
-#endif
  NULL, /*sqlite3_threadsafe,*/
   NULL, /*sqlite3_result_zeroblob,*/
   NULL, /*sqlite3_result_error_code,*/
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
index 2b30658..454ebc1 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqlitedatasource.cpp 37124 2017-01-12 16:25:54Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDataSource class.
@@ -42,16 +41,27 @@
 #include "cpl_csv.h"
 #include "cpl_multiproc.h"
 #include "ogrsqlitevirtualogr.h"
+#include "ogrsqliteutility.h"
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
 
 #if defined(HAVE_SPATIALITE) && !defined(SPATIALITE_DLOPEN)
 #include "spatialite.h"
 #endif
 
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
 #ifndef SPATIALITE_412_OR_LATER
 static int bSpatialiteGlobalLoaded = FALSE;
 #endif
 
-CPL_CVSID("$Id: ogrsqlitedatasource.cpp 37124 2017-01-12 16:25:54Z rouault $");
+CPL_CVSID("$Id: ogrsqlitedatasource.cpp 37818 2017-03-21 07:53:27Z rouault $");
 
 /************************************************************************/
 /*                      OGRSQLiteInitOldSpatialite()                    */
@@ -86,7 +96,7 @@ void OGRSQLiteDriverUnload(GDALDriver*)
 {
 }
 
-#else
+#else // defined(SPATIALITE_412_OR_LATER)
 
 #ifdef SPATIALITE_DLOPEN
 static CPLMutex* hMutexLoadSpatialiteSymbols = NULL;
@@ -208,7 +218,40 @@ void OGRSQLiteBaseDataSource::FinishNewSpatialite()
     }
 }
 
-#endif
+#endif // defined(SPATIALITE_412_OR_LATER)
+
+#ifdef HAVE_RASTERLITE2
+
+/************************************************************************/
+/*                          InitRasterLite2()                           */
+/************************************************************************/
+
+bool OGRSQLiteBaseDataSource::InitRasterLite2()
+{
+    CPLAssert(m_hRL2Ctxt == NULL);
+    m_hRL2Ctxt = rl2_alloc_private();
+    if( m_hRL2Ctxt != NULL )
+    {
+        rl2_init (hDB, m_hRL2Ctxt, 0);
+    }
+    return m_hRL2Ctxt != NULL;
+}
+
+/************************************************************************/
+/*                         FinishRasterLite2()                          */
+/************************************************************************/
+
+void OGRSQLiteBaseDataSource::FinishRasterLite2()
+{
+    if( m_hRL2Ctxt != NULL )
+    {
+        rl2_cleanup_private(m_hRL2Ctxt);
+        m_hRL2Ctxt = NULL;
+    }
+}
+
+#endif // HAVE_RASTERLITE2
+
 
 /************************************************************************/
 /*                          IsSpatialiteLoaded()                        */
@@ -243,26 +286,21 @@ int OGRSQLiteDataSource::GetSpatialiteVersionNumber()
 /*                       OGRSQLiteBaseDataSource()                      */
 /************************************************************************/
 
-OGRSQLiteBaseDataSource::OGRSQLiteBaseDataSource()
-
-{
-    m_pszFilename = NULL;
-    hDB = NULL;
-    bUpdate = FALSE;
-
-#ifdef HAVE_SQLITE_VFS
-    pMyVFS = NULL;
-#endif
-
-    fpMainFile = NULL; /* Do not close ! The VFS layer will do it for us */
-
+OGRSQLiteBaseDataSource::OGRSQLiteBaseDataSource() :
+    m_pszFilename(NULL),
+    hDB(NULL),
+    bUpdate(FALSE),
+    pMyVFS(NULL),
+    fpMainFile(NULL),  // Do not close. The VFS layer will do it for us.
 #ifdef SPATIALITE_412_OR_LATER
-    hSpatialiteCtxt = NULL;
+    hSpatialiteCtxt(NULL),
 #endif
-
-    bUserTransactionActive = FALSE;
-    nSoftTransactionLevel = 0;
-}
+#ifdef HAVE_RASTERLITE2
+    m_hRL2Ctxt(NULL),
+#endif
+    bUserTransactionActive(FALSE),
+    nSoftTransactionLevel(0)
+{}
 
 /************************************************************************/
 /*                      ~OGRSQLiteBaseDataSource()                      */
@@ -274,7 +312,9 @@ OGRSQLiteBaseDataSource::~OGRSQLiteBaseDataSource()
 #ifdef SPATIALITE_412_OR_LATER
     FinishNewSpatialite();
 #endif
-
+#ifdef HAVE_RASTERLITE2
+    FinishRasterLite2();
+#endif
     CloseDB();
     CPLFree(m_pszFilename);
 }
@@ -295,6 +335,9 @@ void OGRSQLiteBaseDataSource::CloseDB()
         // read-write
         VSIStatBufL sStat;
         if( eAccess == GA_ReadOnly &&
+            !(STARTS_WITH(m_pszFilename, "/vsicurl/") ||
+              STARTS_WITH(m_pszFilename, "/vsitar/") ||
+              STARTS_WITH(m_pszFilename, "/vsizip/")) &&
             VSIStatL( CPLSPrintf("%s-wal", m_pszFilename), &sStat) == 0 )
         {
             CPL_IGNORE_RET_VAL( sqlite3_open( m_pszFilename, &hDB ) );
@@ -316,7 +359,6 @@ void OGRSQLiteBaseDataSource::CloseDB()
 
     }
 
-#ifdef HAVE_SQLITE_VFS
     if (pMyVFS)
     {
         sqlite3_vfs_unregister(pMyVFS);
@@ -324,32 +366,40 @@ void OGRSQLiteBaseDataSource::CloseDB()
         CPLFree(pMyVFS);
         pMyVFS = NULL;
     }
-#endif
 }
 
 /************************************************************************/
 /*                        OGRSQLiteDataSource()                         */
 /************************************************************************/
 
-OGRSQLiteDataSource::OGRSQLiteDataSource()
-
+OGRSQLiteDataSource::OGRSQLiteDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    nKnownSRID(0),
+    panSRID(NULL),
+    papoSRS(NULL),
+    papszOpenOptions(NULL),
+    bHaveGeometryColumns(FALSE),
+    bIsSpatiaLiteDB(FALSE),
+    bSpatialite4Layout(FALSE),
+    nUndefinedSRID(-1),  // Will be set to 0 if Spatialite >= 4.0 detected.
+    nFileTimestamp(0),
+    bLastSQLCommandIsUpdateLayerStatistics(FALSE),
+#ifdef HAVE_RASTERLITE2
+    m_nSectionId(-1),
+    m_pRL2Coverage(NULL),
+    m_bRL2MixedResolutions(false),
+#endif
+    m_bGeoTransformValid(false),
+    m_bPromote1BitAs8Bit(false),
+    m_poParentDS(NULL)
 {
-    papoLayers = NULL;
-    nLayers = 0;
-
-    nKnownSRID = 0;
-    panSRID = NULL;
-    papoSRS = NULL;
-
-    bHaveGeometryColumns = FALSE;
-    bIsSpatiaLiteDB = FALSE;
-    bSpatialite4Layout = FALSE;
-
-    nUndefinedSRID = -1; /* will be changed to 0 if Spatialite >= 4.0 detected */
-
-    nFileTimestamp = 0;
-    bLastSQLCommandIsUpdateLayerStatistics = FALSE;
-    papszOpenOptions = NULL;
+    m_adfGeoTransform[0] = 0.0;
+    m_adfGeoTransform[1] = 1.0;
+    m_adfGeoTransform[2] = 0.0;
+    m_adfGeoTransform[3] = 0.0;
+    m_adfGeoTransform[4] = 0.0;
+    m_adfGeoTransform[5] = 1.0;
 }
 
 /************************************************************************/
@@ -359,14 +409,40 @@ OGRSQLiteDataSource::OGRSQLiteDataSource()
 OGRSQLiteDataSource::~OGRSQLiteDataSource()
 
 {
-    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
+#ifdef HAVE_RASTERLITE2
+    if( m_pRL2Coverage != NULL )
     {
-        if( papoLayers[iLayer]->IsTableLayer() )
+        rl2_destroy_coverage( m_pRL2Coverage );
+    }
+#endif
+    for( size_t i=0; i < m_apoOverviewDS.size(); ++i )
+    {
+        delete m_apoOverviewDS[i];
+    }
+
+    if( nLayers > 0 || !apoInvisibleLayers.empty() )
+    {
+        // Close any remaining iterator
+        for( int i = 0; i < nLayers; i++ )
+            papoLayers[i]->ResetReading();
+        for( size_t i = 0; i < apoInvisibleLayers.size(); i++ )
+            apoInvisibleLayers[i]->ResetReading();
+
+        // Create spatial indices in a transaction for faster execution
+        if( hDB )
+            SoftStartTransaction();
+        for( int iLayer = 0; iLayer < nLayers; iLayer++ )
         {
-            OGRSQLiteTableLayer* poLayer = (OGRSQLiteTableLayer*) papoLayers[iLayer];
-            poLayer->RunDeferredCreationIfNecessary();
-            poLayer->CreateSpatialIndexIfNecessary();
+            if( papoLayers[iLayer]->IsTableLayer() )
+            {
+                OGRSQLiteTableLayer* poLayer =
+                    (OGRSQLiteTableLayer*) papoLayers[iLayer];
+                poLayer->RunDeferredCreationIfNecessary();
+                poLayer->CreateSpatialIndexIfNecessary();
+            }
         }
+        if( hDB )
+            SoftCommitTransaction();
     }
 
     SaveStatistics();
@@ -394,13 +470,13 @@ OGRSQLiteDataSource::~OGRSQLiteDataSource()
 
 void OGRSQLiteDataSource::SaveStatistics()
 {
-    int i;
-    int nSavedAllLayersCacheData = -1;
-
-    if( !bIsSpatiaLiteDB || !IsSpatialiteLoaded() || bLastSQLCommandIsUpdateLayerStatistics )
+    if( !bIsSpatiaLiteDB || !IsSpatialiteLoaded() ||
+        bLastSQLCommandIsUpdateLayerStatistics || !bUpdate )
         return;
 
-    for( i = 0; i < nLayers; i++ )
+    int nSavedAllLayersCacheData = -1;
+
+    for( int i = 0; i < nLayers; i++ )
     {
         if( papoLayers[i]->IsTableLayer() )
         {
@@ -418,25 +494,20 @@ void OGRSQLiteDataSource::SaveStatistics()
 
     if( hDB && nSavedAllLayersCacheData == TRUE )
     {
-        char* pszErrMsg = NULL;
-
-        int nRowCount = 0, nColCount = 0;
-        char **papszResult = NULL;
+        SQLResult oResult;
         int nReplaceEventId = -1;
 
-        sqlite3_get_table( hDB,
-                           "SELECT event_id, table_name, geometry_column, event "
-                           "FROM spatialite_history ORDER BY event_id DESC LIMIT 1",
-                           &papszResult,
-                           &nRowCount, &nColCount, &pszErrMsg );
+        CPL_IGNORE_RET_VAL( SQLQuery( hDB,
+                  "SELECT event_id, table_name, geometry_column, event "
+                  "FROM spatialite_history ORDER BY event_id DESC LIMIT 1",
+                  &oResult ) );
 
-        if( nRowCount == 1 )
+        if( oResult.nRowCount == 1 )
         {
-            char **papszRow = papszResult + 4;
-            const char* pszEventId = papszRow[0];
-            const char* pszTableName = papszRow[1];
-            const char* pszGeomCol = papszRow[2];
-            const char* pszEvent = papszRow[3];
+            const char* pszEventId = SQLResultGetValue(&oResult, 0, 0);
+            const char* pszTableName = SQLResultGetValue(&oResult, 1, 0);
+            const char* pszGeomCol = SQLResultGetValue(&oResult, 2, 0);
+            const char* pszEvent = SQLResultGetValue(&oResult, 3, 0);
 
             if( pszEventId != NULL && pszTableName != NULL &&
                 pszGeomCol != NULL && pszEvent != NULL &&
@@ -447,37 +518,29 @@ void OGRSQLiteDataSource::SaveStatistics()
                 nReplaceEventId = atoi(pszEventId);
             }
         }
-        if( pszErrMsg )
-            sqlite3_free( pszErrMsg );
-        pszErrMsg = NULL;
-
-        sqlite3_free_table( papszResult );
-
-        int rc;
+        SQLResultFree(&oResult);
 
+        const char* pszNow = HasSpatialite4Layout() ?
+            "strftime('%Y-%m-%dT%H:%M:%fZ','now')" : "DateTime('now')";
+        const char* pszSQL;
         if( nReplaceEventId >= 0 )
         {
-            rc = sqlite3_exec( hDB,
-                               CPLSPrintf("UPDATE spatialite_history SET "
-                                          "timestamp = DateTime('now') "
-                                          "WHERE event_id = %d", nReplaceEventId),
-                               NULL, NULL, &pszErrMsg );
+            pszSQL = CPLSPrintf("UPDATE spatialite_history SET "
+                                          "timestamp = %s "
+                                          "WHERE event_id = %d",
+                                          pszNow,
+                                          nReplaceEventId);
         }
         else
         {
-            rc = sqlite3_exec( hDB,
-                "INSERT INTO spatialite_history (table_name, geometry_column, "
+            pszSQL =
+                CPLSPrintf( "INSERT INTO spatialite_history (table_name, geometry_column, "
                 "event, timestamp, ver_sqlite, ver_splite) VALUES ("
                 "'ALL-TABLES', 'ALL-GEOMETRY-COLUMNS', 'UpdateLayerStatistics', "
-                "DateTime('now'), sqlite_version(), spatialite_version())",
-                NULL, NULL, &pszErrMsg );
+                "%s, sqlite_version(), spatialite_version())", pszNow);
         }
 
-        if( rc != SQLITE_OK )
-        {
-            CPLDebug("SQLITE", "Error %s", pszErrMsg ? pszErrMsg : "unknown");
-            sqlite3_free( pszErrMsg );
-        }
+        SQLCommand( hDB, pszSQL) ;
     }
 }
 
@@ -485,98 +548,56 @@ void OGRSQLiteDataSource::SaveStatistics()
 /*                              SetSynchronous()                        */
 /************************************************************************/
 
-int OGRSQLiteBaseDataSource::SetSynchronous()
+bool OGRSQLiteBaseDataSource::SetSynchronous()
 {
-    int rc;
     const char* pszSqliteSync = CPLGetConfigOption("OGR_SQLITE_SYNCHRONOUS", NULL);
     if (pszSqliteSync != NULL)
     {
-        char* pszErrMsg = NULL;
+        const char* pszSQL = NULL;
         if (EQUAL(pszSqliteSync, "OFF") || EQUAL(pszSqliteSync, "0") ||
             EQUAL(pszSqliteSync, "FALSE"))
-            rc = sqlite3_exec( hDB, "PRAGMA synchronous = OFF", NULL, NULL, &pszErrMsg );
+            pszSQL = "PRAGMA synchronous = OFF";
         else if (EQUAL(pszSqliteSync, "NORMAL") || EQUAL(pszSqliteSync, "1"))
-            rc = sqlite3_exec( hDB, "PRAGMA synchronous = NORMAL", NULL, NULL, &pszErrMsg );
+            pszSQL =  "PRAGMA synchronous = NORMAL";
         else if (EQUAL(pszSqliteSync, "ON") || EQUAL(pszSqliteSync, "FULL") ||
             EQUAL(pszSqliteSync, "2") || EQUAL(pszSqliteSync, "TRUE"))
-            rc = sqlite3_exec( hDB, "PRAGMA synchronous = FULL", NULL, NULL, &pszErrMsg );
+            pszSQL = "PRAGMA synchronous = FULL";
         else
-        {
-            CPLError( CE_Warning, CPLE_AppDefined, "Unrecognized value for OGR_SQLITE_SYNCHRONOUS : %s",
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Unrecognized value for OGR_SQLITE_SYNCHRONOUS : %s",
                       pszSqliteSync);
-            rc = SQLITE_OK;
-        }
 
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to run PRAGMA synchronous : %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            return FALSE;
-        }
+        return pszSQL != NULL && SQLCommand(hDB, pszSQL) == OGRERR_NONE;
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                              SetCacheSize()                          */
 /************************************************************************/
 
-int OGRSQLiteBaseDataSource::SetCacheSize()
+bool OGRSQLiteBaseDataSource::SetCacheSize()
 {
-    int rc;
     const char* pszSqliteCacheMB = CPLGetConfigOption("OGR_SQLITE_CACHE", NULL);
     if (pszSqliteCacheMB != NULL)
     {
-        char* pszErrMsg = NULL;
-        char **papszResult;
-        int nRowCount, nColCount;
-        int iSqliteCachePages;
-        int iSqlitePageSize = -1;
-        int iSqliteCacheBytes = atoi( pszSqliteCacheMB ) * 1024 * 1024;
+        const GIntBig iSqliteCacheBytes = 
+            static_cast<GIntBig>(atoi( pszSqliteCacheMB )) * 1024 * 1024;
 
         /* querying the current PageSize */
-        rc = sqlite3_get_table( hDB, "PRAGMA page_size",
-                                &papszResult, &nRowCount, &nColCount,
-                                &pszErrMsg );
-        if( rc == SQLITE_OK )
-        {
-            int iRow;
-            for (iRow = 1; iRow <= nRowCount; iRow++)
-            {
-                iSqlitePageSize = atoi( papszResult[(iRow * nColCount) + 0] );
-            }
-            sqlite3_free_table(papszResult);
-        }
-        if( iSqlitePageSize < 0 )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to run PRAGMA page_size : %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            return TRUE;
-        }
-
+        int iSqlitePageSize = SQLGetInteger(hDB, "PRAGMA page_size", NULL);
+        if( iSqlitePageSize <= 0 )
+            return false;
         /* computing the CacheSize as #Pages */
-        if( iSqlitePageSize == 0 )
-            return TRUE;
-        iSqliteCachePages = iSqliteCacheBytes / iSqlitePageSize;
+        const int iSqliteCachePages =
+                static_cast<int>(iSqliteCacheBytes / iSqlitePageSize);
         if( iSqliteCachePages <= 0)
-            return TRUE;
+            return false;
 
-        rc = sqlite3_exec( hDB, CPLSPrintf( "PRAGMA cache_size = %d",
-                                            iSqliteCachePages ),
-                           NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Unrecognized value for PRAGMA cache_size : %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-        }
+        return SQLCommand( hDB, CPLSPrintf( "PRAGMA cache_size = %d",
+                                        iSqliteCachePages ) ) == OGRERR_NONE;
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -591,7 +612,6 @@ void OGRSQLiteBaseDataSourceNotifyFileOpened (void* pfnUserData,
     ((OGRSQLiteBaseDataSource*)pfnUserData)->NotifyFileOpened(pszFilename, fp);
 }
 
-
 /************************************************************************/
 /*                          NotifyFileOpened()                          */
 /************************************************************************/
@@ -608,7 +628,7 @@ void OGRSQLiteBaseDataSource::NotifyFileOpened(const char* pszFilename,
 #ifdef USE_SQLITE_DEBUG_MEMALLOC
 
 /* DMA9 */
-#define DMA_SIGNATURE 0x444D4139
+static const int DMA_SIGNATURE = 0x444D4139;
 
 static void* OGRSQLiteDMA_Malloc(int size)
 {
@@ -682,18 +702,17 @@ const struct sqlite3_mem_methods sDebugMemAlloc =
 
 int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, int bRegisterOGR2SQLiteExtensions)
 {
-    int rc;
-
 #ifdef USE_SQLITE_DEBUG_MEMALLOC
     if( CPLTestBool(CPLGetConfigOption("USE_SQLITE_DEBUG_MEMALLOC", "NO")) )
         sqlite3_config(SQLITE_CONFIG_MALLOC, &sDebugMemAlloc);
 #endif
 
-#ifdef HAVE_SQLITE_VFS
     if( bRegisterOGR2SQLiteExtensions )
         OGR2SQLITE_Register();
 
-    int flags = flagsIn;
+    // No mutex since OGR objects are not supposed to be used concurrently
+    // from multiple threads.
+    int flags = flagsIn | SQLITE_OPEN_NOMUTEX;
 #ifdef SQLITE_OPEN_URI
     // This code enables support for named memory databases in SQLite.
     // SQLITE_USE_URI is checked only to enable backward compatibility, in
@@ -705,7 +724,10 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, int bRegisterOGR2SQLite
     }
 #endif
 
-    int bUseOGRVFS = CPLTestBool(CPLGetConfigOption("SQLITE_USE_OGR_VFS", "NO"));
+    int rc = SQLITE_OK;
+
+    const bool bUseOGRVFS =
+        CPLTestBool(CPLGetConfigOption("SQLITE_USE_OGR_VFS", "NO"));
     if (bUseOGRVFS || STARTS_WITH(m_pszFilename, "/vsi"))
     {
         pMyVFS = OGRSQLiteCreateVFS(OGRSQLiteBaseDataSourceNotifyFileOpened, this);
@@ -713,10 +735,10 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, int bRegisterOGR2SQLite
         rc = sqlite3_open_v2( m_pszFilename, &hDB, flags, pMyVFS->zName );
     }
     else
+    {
         rc = sqlite3_open_v2( m_pszFilename, &hDB, flags, NULL );
-#else
-    rc = sqlite3_open( m_pszFilename, &hDB );
-#endif
+    }
+
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -725,111 +747,131 @@ int OGRSQLiteBaseDataSource::OpenOrCreateDB(int flagsIn, int bRegisterOGR2SQLite
         return FALSE;
     }
 
-    int nRowCount = 0, nColCount = 0;
-    char** papszResult = NULL;
-    char* pszErrMsg = NULL;
-    rc = sqlite3_get_table( hDB,
-                       "SELECT name, sql FROM sqlite_master "
-                       "WHERE (type = 'trigger' OR type = 'view') AND ("
-                       "sql LIKE '%%ogr_geocode%%' OR "
-                       "sql LIKE '%%ogr_datasource_load_layers%%' OR "
-                       "sql LIKE '%%ogr_GetConfigOption%%' OR "
-                       "sql LIKE '%%ogr_SetConfigOption%%' )",
-                       &papszResult, &nRowCount, &nColCount,
-                       &pszErrMsg );
-    if( rc != SQLITE_OK )
+    if( (flagsIn & SQLITE_OPEN_CREATE) == 0 )
     {
-        bool bIsWAL = false;
-        VSILFILE* fp = VSIFOpenL(m_pszFilename, "rb");
-        if( fp != NULL )
+        if( CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_READ", "NO")) )
         {
-            GByte byVal = 0;
-            VSIFSeekL(fp, 18, SEEK_SET);
-            VSIFReadL(&byVal, 1, 1, fp);
-            bIsWAL = byVal == 2;
+            if( SQLGetInteger( hDB,
+                               "SELECT 1 FROM sqlite_master "
+                               "WHERE type = 'table' AND name = 'vfk_tables'",
+                               NULL ) )
+                return FALSE;  /* DB is valid VFK datasource */
         }
-        if( bIsWAL )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                "%s: this file is a WAL-enabled database. It cannot be opened "
-                "because it is presumably read-only or in a read-only directory.",
-                pszErrMsg);
-        }
-        else
-        {
-            CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrMsg);
-        }
-        sqlite3_free( pszErrMsg );
-        return FALSE;
-    }
 
-    sqlite3_free_table(papszResult);
-    papszResult = NULL;
-
-    if( nRowCount > 0 )
-    {
-        if( !CPLTestBool(CPLGetConfigOption("ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW", "NO")) )
+        int nRowCount = 0, nColCount = 0;
+        char** papszResult = NULL;
+        char* pszErrMsg = NULL;
+        rc = sqlite3_get_table( hDB,
+                        "SELECT 1 FROM sqlite_master "
+                        "WHERE (type = 'trigger' OR type = 'view') AND ("
+                        "sql LIKE '%%ogr_geocode%%' OR "
+                        "sql LIKE '%%ogr_datasource_load_layers%%' OR "
+                        "sql LIKE '%%ogr_GetConfigOption%%' OR "
+                        "sql LIKE '%%ogr_SetConfigOption%%' ) "
+                        "LIMIT 1",
+                        &papszResult, &nRowCount, &nColCount,
+                        &pszErrMsg );
+        if( rc != SQLITE_OK )
         {
-            CPLError( CE_Failure, CPLE_OpenFailed, "%s",
-                "A trigger and/or view calls a OGR extension SQL function that could be used to "
-                "steal data, or use network bandwidth, without your consent.\n"
-                "The database will not be opened unless the ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW "
-                "configuration option to YES.");
+            bool bIsWAL = false;
+            VSILFILE* fp = VSIFOpenL(m_pszFilename, "rb");
+            if( fp != NULL )
+            {
+                GByte byVal = 0;
+                VSIFSeekL(fp, 18, SEEK_SET);
+                VSIFReadL(&byVal, 1, 1, fp);
+                bIsWAL = byVal == 2;
+                VSIFCloseL(fp);
+            }
+            if( bIsWAL )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                    "%s: this file is a WAL-enabled database. "
+                    "It cannot be opened "
+                    "because it is presumably read-only or in a "
+                    "read-only directory.",
+                    pszErrMsg);
+            }
+            else
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "%s", pszErrMsg);
+            }
+            sqlite3_free( pszErrMsg );
             return FALSE;
         }
-    }
 
-    const char* pszSqliteJournal = CPLGetConfigOption("OGR_SQLITE_JOURNAL", NULL);
-    if (pszSqliteJournal != NULL)
-    {
-        pszErrMsg = NULL;
-
-        const char* pszSQL = CPLSPrintf("PRAGMA journal_mode = %s",
-                                        pszSqliteJournal);
+        sqlite3_free_table(papszResult);
 
-        rc = sqlite3_get_table( hDB, pszSQL,
-                                &papszResult, &nRowCount, &nColCount,
-                                &pszErrMsg );
-        if( rc == SQLITE_OK )
-        {
-            sqlite3_free_table(papszResult);
-        }
-        else
+        if( nRowCount > 0 )
         {
-            sqlite3_free( pszErrMsg );
+            if( !CPLTestBool(CPLGetConfigOption(
+                "ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW", "NO")) )
+            {
+                CPLError( CE_Failure, CPLE_OpenFailed, "%s",
+                    "A trigger and/or view calls a OGR extension SQL "
+                    "function that could be used to "
+                    "steal data, or use network bandwidth, without your consent.\n"
+                    "The database will not be opened unless the "
+                    "ALLOW_OGR_SQL_FUNCTIONS_FROM_TRIGGER_AND_VIEW "
+                    "configuration option to YES.");
+                return FALSE;
+            }
         }
     }
 
-    const char* pszSqlitePragma = CPLGetConfigOption("OGR_SQLITE_PRAGMA", NULL);
+    const char* pszSqlitePragma =
+                            CPLGetConfigOption("OGR_SQLITE_PRAGMA", NULL);
+    CPLString osJournalMode =
+                        CPLGetConfigOption("OGR_SQLITE_JOURNAL", "");
+
+    bool bPageSizeFound = false;
     if (pszSqlitePragma != NULL)
     {
-        char** papszTokens = CSLTokenizeString2( pszSqlitePragma, ",", CSLT_HONOURSTRINGS );
+        char** papszTokens = CSLTokenizeString2( pszSqlitePragma, ",",
+                                                 CSLT_HONOURSTRINGS );
         for(int i=0; papszTokens[i] != NULL; i++ )
         {
-            pszErrMsg = NULL;
+            if( STARTS_WITH_CI(papszTokens[i], "PAGE_SIZE") )
+                bPageSizeFound = true;
+            if( STARTS_WITH_CI(papszTokens[i], "JOURNAL_MODE") )
+            {
+                const char* pszEqual = strchr(papszTokens[i], '=');
+                if( pszEqual )
+                {
+                    osJournalMode = pszEqual + 1;
+                    osJournalMode.Trim();
+                    break;
+                }
+            }
 
             const char* pszSQL = CPLSPrintf("PRAGMA %s", papszTokens[i]);
 
-            rc = sqlite3_get_table( hDB, pszSQL,
-                                    &papszResult, &nRowCount, &nColCount,
-                                    &pszErrMsg );
-            if( rc == SQLITE_OK )
-            {
-                sqlite3_free_table(papszResult);
-            }
-            else
-            {
-                sqlite3_free( pszErrMsg );
-            }
+            CPL_IGNORE_RET_VAL(
+                sqlite3_exec( hDB, pszSQL, NULL, NULL, NULL ) );
         }
         CSLDestroy(papszTokens);
     }
 
-    if (!SetCacheSize())
-        return FALSE;
+    if( !bPageSizeFound && (flagsIn & SQLITE_OPEN_CREATE) != 0 )
+    {
+        // Since sqlite 3.12 the default page_size is now 4096. But we
+        // can use that even with older versions.
+        CPL_IGNORE_RET_VAL(
+            sqlite3_exec( hDB, "PRAGMA page_size = 4096", NULL, NULL, NULL ) );
+    }
 
-    if (!SetSynchronous())
-        return FALSE;
+    // journal_mode = WAL must be done *AFTER* changing page size.
+    if (!osJournalMode.empty())
+    {
+        const char* pszSQL = CPLSPrintf("PRAGMA journal_mode = %s",
+                                        osJournalMode.c_str());
+
+        CPL_IGNORE_RET_VAL(
+            sqlite3_exec( hDB, pszSQL, NULL, NULL, NULL ) );
+    }
+
+    SetCacheSize();
+    SetSynchronous();
 
     return TRUE;
 }
@@ -852,9 +894,7 @@ void *OGRSQLiteBaseDataSource::GetInternalHandle( const char * pszKey )
 
 int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
 {
-    int rc;
     CPLString osCommand;
-    char *pszErrMsg = NULL;
 
     m_pszFilename = CPLStrdup( pszNameIn );
 
@@ -862,10 +902,10 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
 /*      Check that spatialite extensions are loaded if required to      */
 /*      create a spatialite database                                    */
 /* -------------------------------------------------------------------- */
-    int bSpatialite = CSLFetchBoolean( papszOptions, "SPATIALITE", FALSE );
-    int bMetadata = CSLFetchBoolean( papszOptions, "METADATA", TRUE );
+    bool bSpatialite = CPLFetchBool( papszOptions, "SPATIALITE", false );
+    int bMetadata = CPLFetchBool( papszOptions, "METADATA", true );
 
-    if (bSpatialite == TRUE)
+    if( bSpatialite )
     {
 #ifdef HAVE_SPATIALITE
 #ifndef SPATIALITE_412_OR_LATER
@@ -907,6 +947,9 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
             return FALSE;
         }
 #endif
+#ifdef HAVE_RASTERLITE2
+        InitRasterLite2();
+#endif
 
         /*
         / SpatiaLite full support: calling InitSpatialMetadata()
@@ -918,27 +961,28 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
         */
 
         const char* pszVal = CSLFetchNameValue( papszOptions, "INIT_WITH_EPSG" );
+        const int nSpatialiteVersionNumber = GetSpatialiteVersionNumber();
         if( pszVal != NULL && !CPLTestBool(pszVal) &&
-            GetSpatialiteVersionNumber() >= 40 )
-            osCommand =  "SELECT InitSpatialMetadata('NONE')";
+            nSpatialiteVersionNumber >= 40 )
+        {
+            if( nSpatialiteVersionNumber >= 41 )
+                osCommand =  "SELECT InitSpatialMetadata(1, 'NONE')";
+            else
+                osCommand =  "SELECT InitSpatialMetadata('NONE')";
+        }
         else
         {
             /* Since spatialite 4.1, InitSpatialMetadata() is no longer run */
             /* into a transaction, which makes population of spatial_ref_sys */
             /* from EPSG awfully slow. We have to use InitSpatialMetadata(1) */
             /* to run within a transaction */
-            if( GetSpatialiteVersionNumber() >= 41 )
+            if( nSpatialiteVersionNumber >= 41 )
                 osCommand =  "SELECT InitSpatialMetadata(1)";
             else
                 osCommand =  "SELECT InitSpatialMetadata()";
         }
-        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
+        if( SQLCommand( hDB, osCommand ) != OGRERR_NONE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                "Unable to Initialize SpatiaLite Metadata: %s",
-                    pszErrMsg );
-            sqlite3_free( pszErrMsg );
             return FALSE;
         }
     }
@@ -948,37 +992,21 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
 /* -------------------------------------------------------------------- */
     else if( bMetadata )
     {
-        osCommand =
+        if( SQLCommand( hDB,
             "CREATE TABLE geometry_columns ("
             "     f_table_name VARCHAR, "
             "     f_geometry_column VARCHAR, "
             "     geometry_type INTEGER, "
             "     coord_dimension INTEGER, "
             "     srid INTEGER,"
-            "     geometry_format VARCHAR )";
-        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to create table geometry_columns: %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
-            return FALSE;
-        }
-
-        osCommand =
+            "     geometry_format VARCHAR )"
+            ";"
             "CREATE TABLE spatial_ref_sys        ("
             "     srid INTEGER UNIQUE,"
             "     auth_name TEXT,"
             "     auth_srid TEXT,"
-            "     srtext TEXT)";
-        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
+            "     srtext TEXT)") != OGRERR_NONE )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to create table spatial_ref_sys: %s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
             return FALSE;
         }
     }
@@ -988,13 +1016,13 @@ int OGRSQLiteDataSource::Create( const char * pszNameIn, char **papszOptions )
 /*      with the EPSG database                                          */
 /* -------------------------------------------------------------------- */
     if ( (bSpatialite || bMetadata) &&
-         CSLFetchBoolean( papszOptions, "INIT_WITH_EPSG", FALSE ) )
+         CPLFetchBool( papszOptions, "INIT_WITH_EPSG", false ) )
     {
         if (!InitWithEPSG())
             return FALSE;
     }
 
-    return Open(m_pszFilename, TRUE, NULL);
+    return Open(m_pszFilename, TRUE, NULL, GDAL_OF_VECTOR);
 }
 
 /************************************************************************/
@@ -1019,14 +1047,12 @@ int OGRSQLiteDataSource::InitWithEPSG()
     if( SoftStartTransaction() != OGRERR_NONE )
         return FALSE;
 
-    FILE* fp;
-    int i;
     int rc = SQLITE_OK;
-    for(i=0;i<2 && rc == SQLITE_OK;i++)
+    for( int i = 0; i < 2 && rc == SQLITE_OK; i++ )
     {
         const char* pszFilename = (i == 0) ? "gcs.csv" : "pcs.csv";
-        fp = VSIFOpen(CSVFilename(pszFilename), "rt");
-        if (fp == NULL)
+        FILE *fp = VSIFOpen(CSVFilename(pszFilename), "rt");
+        if( fp == NULL )
         {
             CPLError( CE_Failure, CPLE_OpenFailed,
                 "Unable to open EPSG support file %s.\n"
@@ -1038,8 +1064,9 @@ int OGRSQLiteDataSource::InitWithEPSG()
         }
 
         OGRSpatialReference oSRS;
-        char** papszTokens;
         CSLDestroy(CSVReadParseLine( fp ));
+
+        char **papszTokens = NULL;
         while ( (papszTokens = CSVReadParseLine( fp )) != NULL && rc == SQLITE_OK)
         {
             int nSRSId = atoi(papszTokens[0]);
@@ -1105,7 +1132,7 @@ int OGRSQLiteDataSource::InitWithEPSG()
                     }
 
                     sqlite3_stmt *hInsertStmt = NULL;
-                    rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
+                    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hInsertStmt, NULL );
 
                     if ( pszProjCS )
                     {
@@ -1167,7 +1194,7 @@ int OGRSQLiteDataSource::InitWithEPSG()
                         nSRSId, nSRSId );
 
                     sqlite3_stmt *hInsertStmt = NULL;
-                    rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
+                    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hInsertStmt, NULL );
 
                     if( rc == SQLITE_OK)
                         rc = sqlite3_bind_text( hInsertStmt, 1, pszWKT, -1, SQLITE_STATIC );
@@ -1222,7 +1249,7 @@ void OGRSQLiteDataSource::ReloadLayers()
     papoLayers = NULL;
     nLayers = 0;
 
-    Open(m_pszFilename, bUpdate, NULL);
+    Open(m_pszFilename, bUpdate, NULL, GDAL_OF_VECTOR);
 }
 
 /************************************************************************/
@@ -1230,15 +1257,37 @@ void OGRSQLiteDataSource::ReloadLayers()
 /************************************************************************/
 
 int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
-                               char** papszOpenOptionsIn)
+                               char** papszOpenOptionsIn, int nOpenFlagsIn)
 
 {
     CPLAssert( nLayers == 0 );
+    bUpdate = bUpdateIn;
+    nOpenFlags = nOpenFlagsIn;
+    SetDescription(pszNewName);
 
     if (m_pszFilename == NULL)
-        m_pszFilename = CPLStrdup( pszNewName );
-    SetDescription(m_pszFilename);
-    bUpdate = bUpdateIn;
+    {
+#ifdef HAVE_RASTERLITE2
+        if( STARTS_WITH_CI(pszNewName, "RASTERLITE2:") &&
+            (nOpenFlags & GDAL_OF_RASTER) != 0 )
+        {
+            char** papszTokens =
+                CSLTokenizeString2( pszNewName, ":", CSLT_HONOURSTRINGS );
+            if( CSLCount(papszTokens) < 2 )
+            {
+                CSLDestroy(papszTokens);
+                return FALSE;
+            }
+            m_pszFilename = CPLStrdup( SQLUnescape( papszTokens[1] ) );
+            CSLDestroy(papszTokens);
+        }
+        else
+#endif
+        {
+            m_pszFilename = CPLStrdup( pszNewName );
+        }
+    }
+    SetPhysicalFilename(m_pszFilename);
 
     VSIStatBufL sStat;
     if( VSIStatL( m_pszFilename, &sStat ) == 0 )
@@ -1252,16 +1301,20 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
         papszOpenOptions = CSLDuplicate(papszOpenOptionsIn);
     }
 
-    int bListAllTables = CPLTestBool(CSLFetchNameValueDef(
-        papszOpenOptions, "LIST_ALL_TABLES",
-        CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "NO")));
+    bool bListVectorLayers = (nOpenFlags & GDAL_OF_VECTOR) != 0;
+
+    bool bListAllTables = bListVectorLayers &&
+        CPLTestBool(CSLFetchNameValueDef(
+            papszOpenOptions, "LIST_ALL_TABLES",
+            CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "NO")));
 
     // Don't list by default: there might be some security implications
     // if a user is provided with a file and doesn't know that there are
     // virtual OGR tables in it.
-    int bListVirtualOGRLayers = CPLTestBool(CSLFetchNameValueDef(
-        papszOpenOptions, "LIST_VIRTUAL_OGR",
-        CPLGetConfigOption("OGR_SQLITE_LIST_VIRTUAL_OGR", "NO")));
+    bool bListVirtualOGRLayers = bListVectorLayers &&
+        CPLTestBool(CSLFetchNameValueDef(
+            papszOpenOptions, "LIST_VIRTUAL_OGR",
+            CPLGetConfigOption("OGR_SQLITE_LIST_VIRTUAL_OGR", "NO")));
 
 /* -------------------------------------------------------------------- */
 /*      Try to open the sqlite database properly now.                   */
@@ -1278,23 +1331,35 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
 #ifdef SPATIALITE_412_OR_LATER
         InitNewSpatialite();
 #endif
+#ifdef HAVE_RASTERLITE2
+        InitRasterLite2();
+#endif
     }
 
+#ifdef HAVE_RASTERLITE2
+    if( STARTS_WITH_CI(pszNewName, "RASTERLITE2:") &&
+        (nOpenFlags & GDAL_OF_RASTER) != 0 )
+    {
+        return OpenRasterSubDataset( pszNewName );
+    }
+#endif
+
 /* -------------------------------------------------------------------- */
 /*      If we have a GEOMETRY_COLUMNS tables, initialize on the basis   */
 /*      of that.                                                        */
 /* -------------------------------------------------------------------- */
-    int rc;
-    char *pszErrMsg = NULL;
-    char **papszResult;
-    int nRowCount, iRow, nColCount;
-
     CPLHashSet* hSet = CPLHashSetNew(CPLHashSetHashStr, CPLHashSetEqualStr, CPLFree);
 
-    rc = sqlite3_get_table(
+    char **papszResult = NULL;
+    char *pszErrMsg = NULL;
+    int nRowCount = 0;
+    int nColCount = 0;
+    int rc = sqlite3_get_table(
         hDB,
-        "SELECT f_table_name, f_geometry_column, geometry_type, coord_dimension, geometry_format, srid"
-        " FROM geometry_columns",
+        "SELECT f_table_name, f_geometry_column, geometry_type, "
+        "coord_dimension, geometry_format, srid"
+        " FROM geometry_columns "
+        "LIMIT 10000",
         &papszResult, &nRowCount, &nColCount, &pszErrMsg );
 
     if( rc == SQLITE_OK )
@@ -1303,7 +1368,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
 
         bHaveGeometryColumns = TRUE;
 
-        for ( iRow = 0; iRow < nRowCount; iRow++ )
+        for ( int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++ )
         {
             char **papszRow = papszResult + iRow * 6 + 6;
             const char* pszTableName = papszRow[0];
@@ -1315,7 +1380,7 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
             aoMapTableToSetOfGeomCols[pszTableName].insert(CPLString(pszGeomCol).tolower());
         }
 
-        for( iRow = 0; iRow < nRowCount; iRow++ )
+        for( int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++ )
         {
             char **papszRow = papszResult + iRow * 6 + 6;
             const char* pszTableName = papszRow[0];
@@ -1338,13 +1403,15 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
         if( bListVirtualOGRLayers )
         {
             rc = sqlite3_get_table( hDB,
-                                "SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE %'",
+                                "SELECT name, sql FROM sqlite_master "
+                                "WHERE sql LIKE 'CREATE VIRTUAL TABLE %' "
+                                "LIMIT 10000",
                                 &papszResult, &nRowCount,
                                 &nColCount, &pszErrMsg );
 
             if ( rc == SQLITE_OK )
             {
-                for( iRow = 0; iRow < nRowCount; iRow++ )
+                for( int iRow = 0; iRow < nRowCount; iRow++ )
                 {
                     char **papszRow = papszResult + iRow * 2 + 2;
                     const char *pszName = papszRow[0];
@@ -1377,6 +1444,13 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
 
         CPLHashSetDestroy(hSet);
 
+        if( nOpenFlags & GDAL_OF_RASTER )
+        {
+            bool bRet = OpenRaster();
+            if( !bRet && !(nOpenFlags & GDAL_OF_VECTOR))
+                return FALSE;
+        }
+
         return TRUE;
     }
 
@@ -1387,7 +1461,8 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
     rc = sqlite3_get_table( hDB,
                             "SELECT f_table_name, f_geometry_column, "
                             "type, coord_dimension, srid, "
-                            "spatial_index_enabled FROM geometry_columns",
+                            "spatial_index_enabled FROM geometry_columns "
+                            "LIMIT 10000",
                             &papszResult, &nRowCount,
                             &nColCount, &pszErrMsg );
     if (rc != SQLITE_OK )
@@ -1397,7 +1472,8 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
         rc = sqlite3_get_table( hDB,
                                 "SELECT f_table_name, f_geometry_column, "
                                 "geometry_type, coord_dimension, srid, "
-                                "spatial_index_enabled FROM geometry_columns",
+                                "spatial_index_enabled FROM geometry_columns "
+                                "LIMIT 10000",
                                 &papszResult, &nRowCount,
                                 &nColCount, &pszErrMsg );
         if ( rc == SQLITE_OK )
@@ -1444,7 +1520,48 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
                      (bSpatialite4Layout) ? " v4" : "");
         }
 
-        for ( iRow = 0; iRow < nRowCount; iRow++ )
+        // List RasterLite2 coverages, so as to avoid listing corresponding
+        // technical tables
+        std::set<CPLString> aoSetTablesToIgnore;
+        if( bSpatialite4Layout )
+        {
+            char** papszResults2 = NULL;
+            int nRowCount2 = 0, nColCount2 = 0;
+            rc = sqlite3_get_table( hDB,
+                                "SELECT name FROM sqlite_master WHERE "
+                                "type = 'table' AND name = 'raster_coverages'",
+                                &papszResults2, &nRowCount2,
+                                &nColCount2, NULL );
+            sqlite3_free_table(papszResults2);
+            if( rc == SQLITE_OK && nRowCount2 == 1 )
+            {
+                papszResults2 = NULL;
+                nRowCount2 = 0;
+                nColCount2 = 0;
+                rc = sqlite3_get_table( hDB,
+                                "SELECT coverage_name FROM raster_coverages "
+                                "LIMIT 10000",
+                                &papszResults2, &nRowCount2,
+                                &nColCount2, NULL );
+                if( rc == SQLITE_OK )
+                {
+                    for(int i=0;i<nRowCount2;++i)
+                    {
+                        const char * const* papszRow = papszResults2 + i*1 + 1;
+                        if( papszRow[0] != NULL )
+                        {
+                            aoSetTablesToIgnore.insert(
+                                    CPLString(papszRow[0]) + "_sections" );
+                            aoSetTablesToIgnore.insert(
+                                    CPLString(papszRow[0]) + "_tiles" );
+                        }
+                    }
+                }
+                sqlite3_free_table(papszResults2);
+            }
+        }
+
+        for ( int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++ )
         {
             char **papszRow = papszResult + iRow * 6 + 6;
             const char* pszTableName = papszRow[0];
@@ -1452,17 +1569,29 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
 
             if( pszTableName == NULL || pszGeomCol == NULL )
                 continue;
+            if( !bListAllTables &&
+                aoSetTablesToIgnore.find(pszTableName) !=
+                                                aoSetTablesToIgnore.end() )
+            {
+                continue;
+            }
 
             aoMapTableToSetOfGeomCols[pszTableName].insert(CPLString(pszGeomCol).tolower());
         }
 
-        for ( iRow = 0; iRow < nRowCount; iRow++ )
+        for ( int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++ )
         {
             char **papszRow = papszResult + iRow * 6 + 6;
             const char* pszTableName = papszRow[0];
 
             if (pszTableName == NULL )
                 continue;
+            if( !bListAllTables &&
+                aoSetTablesToIgnore.find(pszTableName) !=
+                                                aoSetTablesToIgnore.end() )
+            {
+                continue;
+            }
 
             if( GDALDataset::GetLayerByName(pszTableName) == NULL )
                 OpenTable( pszTableName);
@@ -1477,13 +1606,15 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
 /*      Detect VirtualShape, VirtualXL and VirtualOGR layers            */
 /* -------------------------------------------------------------------- */
         rc = sqlite3_get_table( hDB,
-                            "SELECT name, sql FROM sqlite_master WHERE sql LIKE 'CREATE VIRTUAL TABLE %'",
+                            "SELECT name, sql FROM sqlite_master "
+                            "WHERE sql LIKE 'CREATE VIRTUAL TABLE %' "
+                            "LIMIT 10000",
                             &papszResult, &nRowCount,
                             &nColCount, &pszErrMsg );
 
         if ( rc == SQLITE_OK )
         {
-            for( iRow = 0; iRow < nRowCount; iRow++ )
+            for( int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++ )
             {
                 char **papszRow = papszResult + iRow * 2 + 2;
                 const char *pszName = papszRow[0];
@@ -1518,12 +1649,15 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
 /* -------------------------------------------------------------------- */
 
         rc = sqlite3_get_table( hDB,
-                                "SELECT view_name, view_geometry, view_rowid, f_table_name, f_geometry_column FROM views_geometry_columns",
+                                "SELECT view_name, view_geometry, view_rowid, "
+                                "f_table_name, f_geometry_column "
+                                "FROM views_geometry_columns "
+                                "LIMIT 10000",
                                 &papszResult, &nRowCount,
                                 &nColCount, NULL );
         if ( rc == SQLITE_OK )
         {
-            for( iRow = 0; iRow < nRowCount; iRow++ )
+            for( int iRow = 0; bListVectorLayers && iRow < nRowCount; iRow++ )
             {
                 char **papszRow = papszResult + iRow * 5 + 5;
                 const char* pszViewName = papszRow[0];
@@ -1548,12 +1682,18 @@ int OGRSQLiteDataSource::Open( const char * pszNewName, int bUpdateIn,
             sqlite3_free_table(papszResult);
         }
 
-
         if (bListAllTables)
             goto all_tables;
 
         CPLHashSetDestroy(hSet);
 
+        if( nOpenFlags & GDAL_OF_RASTER )
+        {
+            bool bRet = OpenRaster();
+            if( !bRet && !(nOpenFlags & GDAL_OF_VECTOR))
+                return FALSE;
+        }
+
         return TRUE;
     }
 
@@ -1570,7 +1710,8 @@ all_tables:
                             "UNION ALL "
                             "SELECT name FROM sqlite_temp_master "
                             "WHERE type IN ('table','view') "
-                            "ORDER BY 1",
+                            "ORDER BY 1 "
+                            "LIMIT 10000",
                             &papszResult, &nRowCount,
                             &nColCount, &pszErrMsg );
 
@@ -1584,7 +1725,7 @@ all_tables:
         return FALSE;
     }
 
-    for( iRow = 0; iRow < nRowCount; iRow++ )
+    for( int iRow = 0; iRow < nRowCount; iRow++ )
     {
         const char* pszTableName = papszResult[iRow+1];
         if( pszTableName != NULL && CPLHashSetLookup(hSet, pszTableName) == NULL )
@@ -1594,6 +1735,13 @@ all_tables:
     sqlite3_free_table(papszResult);
     CPLHashSetDestroy(hSet);
 
+    if( nOpenFlags & GDAL_OF_RASTER )
+    {
+        bool bRet = OpenRaster();
+        if( !bRet && !(nOpenFlags & GDAL_OF_VECTOR))
+            return FALSE;
+    }
+
     return TRUE;
 }
 
@@ -1662,9 +1810,7 @@ int OGRSQLiteDataSource::OpenTable( const char *pszTableName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRSQLiteTableLayer  *poLayer;
-
-    poLayer = new OGRSQLiteTableLayer( this );
+    OGRSQLiteTableLayer *poLayer = new OGRSQLiteTableLayer( this );
     if( poLayer->Initialize( pszTableName, bIsVirtualShapeIn, FALSE) != CE_None )
     {
         delete poLayer;
@@ -1695,9 +1841,7 @@ int OGRSQLiteDataSource::OpenView( const char *pszViewName,
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRSQLiteViewLayer  *poLayer;
-
-    poLayer = new OGRSQLiteViewLayer( this );
+    OGRSQLiteViewLayer *poLayer = new OGRSQLiteViewLayer( this );
 
     if( poLayer->Initialize( pszViewName, pszViewGeometry,
                              pszViewRowid, pszTableName, pszGeometryColumn ) != CE_None )
@@ -1731,7 +1875,9 @@ int OGRSQLiteDataSource::TestCapability( const char * pszCap )
         return !bIsSpatiaLiteDB;
     else if( EQUAL(pszCap,ODsCMeasuredGeometries) )
         return TRUE;
-    else if EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer)
+    else if( EQUAL(pszCap,ODsCCreateGeomFieldAfterCreateLayer) )
+        return bUpdate;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
         return bUpdate;
     else
         return OGRSQLiteBaseDataSource::TestCapability(pszCap);
@@ -1743,7 +1889,7 @@ int OGRSQLiteDataSource::TestCapability( const char * pszCap )
 
 int OGRSQLiteBaseDataSource::TestCapability( const char * pszCap )
 {
-    if EQUAL(pszCap,ODsCTransactions)
+    if( EQUAL(pszCap,ODsCTransactions) )
         return TRUE;
     else
         return GDALPamDataset::TestCapability(pszCap);
@@ -1955,8 +2101,7 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
     if( EQUAL(pszSQLCommand, "VACUUM") )
     {
         int bNeedRefresh = -1;
-        int i;
-        for( i = 0; i < nLayers; i++ )
+        for( int i = 0; i < nLayers; i++ )
         {
             if( papoLayers[i]->IsTableLayer() )
             {
@@ -1973,7 +2118,7 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
         }
         if( bNeedRefresh == TRUE )
         {
-            for( i = 0; i < nLayers; i++ )
+            for( int i = 0; i < nLayers; i++ )
             {
                 if( papoLayers[i]->IsTableLayer() )
                 {
@@ -1997,7 +2142,6 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
 /*      Prepare statement.                                              */
 /* -------------------------------------------------------------------- */
-    int rc;
     sqlite3_stmt *hSQLStmt = NULL;
 
     CPLString osSQLCommand = pszSQLCommand;
@@ -2009,6 +2153,7 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
     int bEmptyLayer = FALSE;
 
     if( osSQLCommand.ifind("SELECT ") == 0 &&
+        CPLString(osSQLCommand.substr(1)).ifind("SELECT ") == std::string::npos &&
         osSQLCommand.ifind(" UNION ") == std::string::npos &&
         osSQLCommand.ifind(" INTERSECT ") == std::string::npos &&
         osSQLCommand.ifind(" EXCEPT ") == std::string::npos )
@@ -2021,15 +2166,15 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
         }
     }
 
-    rc = sqlite3_prepare( GetDB(), osSQLCommand.c_str(),
-                          static_cast<int>(osSQLCommand.size()),
-                          &hSQLStmt, NULL );
+    int rc = sqlite3_prepare_v2( GetDB(), osSQLCommand.c_str(),
+                              static_cast<int>(osSQLCommand.size()),
+                              &hSQLStmt, NULL );
 
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
-                pszSQLCommand, sqlite3_errmsg(GetDB()) );
+                  "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n  %s",
+                  osSQLCommand.c_str(), sqlite3_errmsg(GetDB()) );
 
         if( hSQLStmt != NULL )
         {
@@ -2049,7 +2194,7 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                   "In ExecuteSQL(): sqlite3_step(%s):\n  %s",
-                  pszSQLCommand, sqlite3_errmsg(GetDB()) );
+                  osSQLCommand.c_str(), sqlite3_errmsg(GetDB()) );
 
             sqlite3_finalize( hSQLStmt );
             return NULL;
@@ -2086,9 +2231,10 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
 /* -------------------------------------------------------------------- */
     if( STARTS_WITH_CI(pszSQLCommand, "SELECT ") )
     {
-        unsigned int i;
-        for(i=0;i<sizeof(apszFuncsWithSideEffects)/
-                  sizeof(apszFuncsWithSideEffects[0]);i++)
+        for( unsigned int i=0;
+             i < sizeof(apszFuncsWithSideEffects) /
+                 sizeof(apszFuncsWithSideEffects[0]);
+             i++ )
         {
             if( EQUALN(apszFuncsWithSideEffects[i], pszSQLCommand + 7,
                        strlen(apszFuncsWithSideEffects[i])) )
@@ -2096,7 +2242,7 @@ OGRLayer * OGRSQLiteDataSource::ExecuteSQL( const char *pszSQLCommand,
                 if (sqlite3_column_count( hSQLStmt ) == 1 &&
                     sqlite3_column_type( hSQLStmt, 0 ) == SQLITE_INTEGER )
                 {
-                    int ret = sqlite3_column_int( hSQLStmt, 0 );
+                    const int ret = sqlite3_column_int( hSQLStmt, 0 );
 
                     sqlite3_finalize( hSQLStmt );
 
@@ -2143,14 +2289,10 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
                                   char ** papszOptions )
 
 {
-    char                *pszLayerName;
-    const char          *pszGeomFormat;
-    int                  bImmediateSpatialIndexCreation = FALSE;
-    int                  bDeferredSpatialIndexCreation = FALSE;
-
 /* -------------------------------------------------------------------- */
 /*      Verify we are in update mode.                                   */
 /* -------------------------------------------------------------------- */
+    char *pszLayerName = NULL;
     if( !bUpdate )
     {
         CPLError( CE_Failure, CPLE_NoWriteAccess,
@@ -2186,7 +2328,7 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
 
     CPLString osFIDColumnName;
     const char* pszFIDColumnNameIn = CSLFetchNameValueDef(papszOptions, "FID", "OGC_FID");
-    if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+    if( CPLFetchBool(papszOptions, "LAUNDER", true) )
     {
         char* pszFIDColumnName = LaunderName(pszFIDColumnNameIn);
         osFIDColumnName = pszFIDColumnName;
@@ -2195,12 +2337,12 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
     else
         osFIDColumnName = pszFIDColumnNameIn;
 
-    if( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) )
+    if( CPLFetchBool(papszOptions, "LAUNDER", true) )
         pszLayerName = LaunderName( pszLayerNameIn );
     else
         pszLayerName = CPLStrdup( pszLayerNameIn );
 
-    pszGeomFormat = CSLFetchNameValue( papszOptions, "FORMAT" );
+    const char *pszGeomFormat = CSLFetchNameValue( papszOptions, "FORMAT" );
     if( pszGeomFormat == NULL )
     {
         if ( !bIsSpatiaLiteDB )
@@ -2228,7 +2370,7 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
     }
     else
     {
-        if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
+        if( CPLFetchBool(papszOptions,"LAUNDER", true) )
         {
             char* pszGeometryName = LaunderName(pszGeometryNameIn);
             osGeometryName = pszGeometryName;
@@ -2262,9 +2404,7 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
-    int iLayer;
-
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
         {
@@ -2310,6 +2450,9 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
     else if( poSRS != NULL )
         nSRSId = FetchSRSId( poSRS );
 
+    bool bImmediateSpatialIndexCreation = false;
+    bool bDeferredSpatialIndexCreation = false;
+
     const char* pszSI = CSLFetchNameValue( papszOptions, "SPATIAL_INDEX" );
     if( bHaveGeometryColumns && eType != wkbNone )
     {
@@ -2329,11 +2472,11 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
         {
             if( pszSI != NULL && EQUAL(pszSI, "IMMEDIATE") )
             {
-                bImmediateSpatialIndexCreation = TRUE;
+                bImmediateSpatialIndexCreation = true;
             }
             else if( pszSI == NULL || CPLTestBool(pszSI) )
             {
-                bDeferredSpatialIndexCreation = TRUE;
+                bDeferredSpatialIndexCreation = true;
             }
         }
     }
@@ -2341,16 +2484,14 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
     {
 #ifdef HAVE_SPATIALITE
         if( bIsSpatiaLiteDB && IsSpatialiteLoaded() && (pszSI == NULL || CPLTestBool(pszSI)) )
-            bDeferredSpatialIndexCreation = TRUE;
+            bDeferredSpatialIndexCreation = true;
 #endif
     }
 
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
 /* -------------------------------------------------------------------- */
-    OGRSQLiteTableLayer     *poLayer;
-
-    poLayer = new OGRSQLiteTableLayer( this );
+    OGRSQLiteTableLayer *poLayer = new OGRSQLiteTableLayer( this );
 
     poLayer->Initialize( pszLayerName, FALSE, TRUE ) ;
     poLayer->SetCreationParameters( osFIDColumnName, eType, pszGeomFormat,
@@ -2365,8 +2506,8 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
     papoLayers[nLayers++] = poLayer;
 
     poLayer->InitFeatureCount();
-    poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
-    if ( CSLFetchBoolean(papszOptions,"COMPRESS_GEOM",FALSE) )
+    poLayer->SetLaunderFlag( CPLFetchBool(papszOptions, "LAUNDER", true) );
+    if( CPLFetchBool(papszOptions, "COMPRESS_GEOM", false) )
         poLayer->SetUseCompressGeom( TRUE );
     if( bImmediateSpatialIndexCreation )
         poLayer->CreateSpatialIndex(0);
@@ -2386,10 +2527,8 @@ OGRSQLiteDataSource::ICreateLayer( const char * pszLayerNameIn,
 char *OGRSQLiteDataSource::LaunderName( const char *pszSrcName )
 
 {
-    char    *pszSafeName = CPLStrdup( pszSrcName );
-    int     i;
-
-    for( i = 0; pszSafeName[i] != '\0'; i++ )
+    char *pszSafeName = CPLStrdup( pszSrcName );
+    for( int i = 0; pszSafeName[i] != '\0'; i++ )
     {
         pszSafeName[i] = (char) tolower( pszSafeName[i] );
         if( pszSafeName[i] == '\'' || pszSafeName[i] == '-' || pszSafeName[i] == '#' )
@@ -2400,75 +2539,12 @@ char *OGRSQLiteDataSource::LaunderName( const char *pszSrcName )
 }
 
 /************************************************************************/
-/*                       OGRSQLiteParamsUnquote()                       */
-/************************************************************************/
-
-CPLString OGRSQLiteParamsUnquote(const char* pszVal)
-{
-    char chQuoteChar = pszVal[0];
-    if( chQuoteChar != '\'' && chQuoteChar != '"' )
-        return pszVal;
-
-    CPLString osRet;
-    pszVal ++;
-    while( *pszVal != '\0' )
-    {
-        if( *pszVal == chQuoteChar )
-        {
-            if( pszVal[1] == chQuoteChar )
-                pszVal ++;
-            else
-                break;
-        }
-        osRet += *pszVal;
-        pszVal ++;
-    }
-    return osRet;
-}
-
-/************************************************************************/
-/*                          OGRSQLiteEscape()                           */
-/************************************************************************/
-
-CPLString OGRSQLiteEscape( const char *pszLiteral )
-{
-    CPLString osVal;
-    for( int i = 0; pszLiteral[i] != '\0'; i++ )
-    {
-        if ( pszLiteral[i] == '\'' )
-            osVal += '\'';
-        osVal += pszLiteral[i];
-    }
-    return osVal;
-}
-
-/************************************************************************/
-/*                        OGRSQLiteEscapeName()                         */
-/************************************************************************/
-
-CPLString OGRSQLiteEscapeName(const char* pszName)
-{
-    CPLString osRet;
-    while( *pszName != '\0' )
-    {
-        if( *pszName == '"' )
-            osRet += "\"\"";
-        else
-            osRet += *pszName;
-        pszName ++;
-    }
-    return osRet;
-}
-
-/************************************************************************/
 /*                            DeleteLayer()                             */
 /************************************************************************/
 
 void OGRSQLiteDataSource::DeleteLayer( const char *pszLayerName )
 
 {
-    int iLayer;
-
 /* -------------------------------------------------------------------- */
 /*      Verify we are in update mode.                                   */
 /* -------------------------------------------------------------------- */
@@ -2485,7 +2561,9 @@ void OGRSQLiteDataSource::DeleteLayer( const char *pszLayerName )
 /* -------------------------------------------------------------------- */
 /*      Try to find layer.                                              */
 /* -------------------------------------------------------------------- */
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    int iLayer = 0;  // Used after for.
+
+    for( ; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetLayerDefn()->GetName()) )
             break;
@@ -2533,21 +2611,14 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
 /* -------------------------------------------------------------------- */
 /*      Remove from the database.                                       */
 /* -------------------------------------------------------------------- */
-    int rc;
-    char *pszErrMsg;
-
-    CPLString osEscapedLayerName = OGRSQLiteEscape(osLayerName);
+    CPLString osEscapedLayerName = SQLEscapeLiteral(osLayerName);
     const char* pszEscapedLayerName = osEscapedLayerName.c_str();
     const char* pszGeometryColumn = osGeometryColumn.size() ? osGeometryColumn.c_str() : NULL;
 
-    rc = sqlite3_exec( hDB, CPLSPrintf( "DROP TABLE '%s'", pszEscapedLayerName ),
-                       NULL, NULL, &pszErrMsg );
-    if( rc != SQLITE_OK )
+    if( SQLCommand( hDB,
+                    CPLSPrintf( "DROP TABLE '%s'", pszEscapedLayerName ) )
+                                                            != OGRERR_NONE )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to drop table %s: %s",
-                  osLayerName.c_str(), pszErrMsg );
-        sqlite3_free( pszErrMsg );
         return OGRERR_FAILURE;
     }
 
@@ -2562,13 +2633,8 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
             "DELETE FROM geometry_columns WHERE f_table_name = '%s'",
             pszEscapedLayerName );
 
-        rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
+        if( SQLCommand( hDB, osCommand ) != OGRERR_NONE )
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                      "Removal from geometry_columns failed.\n%s: %s",
-                      osCommand.c_str(), pszErrMsg );
-            sqlite3_free( pszErrMsg );
             return OGRERR_FAILURE;
         }
 
@@ -2578,26 +2644,25 @@ OGRErr OGRSQLiteDataSource::DeleteLayer(int iLayer)
         if( bIsSpatiaLiteDB && pszGeometryColumn )
         {
             osCommand.Printf( "DROP TABLE 'idx_%s_%s'", pszEscapedLayerName,
-                              OGRSQLiteEscape(pszGeometryColumn).c_str());
+                              SQLEscapeLiteral(pszGeometryColumn).c_str());
             CPL_IGNORE_RET_VAL(sqlite3_exec( hDB, osCommand, NULL, NULL, NULL ));
 
             osCommand.Printf( "DROP TABLE 'idx_%s_%s_node'", pszEscapedLayerName,
-                              OGRSQLiteEscape(pszGeometryColumn).c_str());
+                              SQLEscapeLiteral(pszGeometryColumn).c_str());
             CPL_IGNORE_RET_VAL(sqlite3_exec( hDB, osCommand, NULL, NULL, NULL ));
 
             osCommand.Printf( "DROP TABLE 'idx_%s_%s_parent'", pszEscapedLayerName,
-                              OGRSQLiteEscape(pszGeometryColumn).c_str());
+                              SQLEscapeLiteral(pszGeometryColumn).c_str());
             CPL_IGNORE_RET_VAL(sqlite3_exec( hDB, osCommand, NULL, NULL, NULL ));
 
             osCommand.Printf( "DROP TABLE 'idx_%s_%s_rowid'", pszEscapedLayerName,
-                              OGRSQLiteEscape(pszGeometryColumn).c_str());
+                              SQLEscapeLiteral(pszGeometryColumn).c_str());
             CPL_IGNORE_RET_VAL(sqlite3_exec( hDB, osCommand, NULL, NULL, NULL ));
         }
     }
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                         StartTransaction()                           */
 /*                                                                      */
@@ -2743,7 +2808,7 @@ OGRErr OGRSQLiteBaseDataSource::SoftCommitTransaction()
 
     if( nSoftTransactionLevel <= 0 )
     {
-        CPLAssert(FALSE);
+        CPLAssert(false);
         return OGRERR_FAILURE;
     }
 
@@ -2772,7 +2837,7 @@ OGRErr OGRSQLiteBaseDataSource::SoftRollbackTransaction()
 
     if( nSoftTransactionLevel <= 0 )
     {
-        CPLAssert(FALSE);
+        CPLAssert(false);
         return OGRERR_FAILURE;
     }
 
@@ -2793,24 +2858,11 @@ OGRErr OGRSQLiteBaseDataSource::SoftRollbackTransaction()
 OGRErr OGRSQLiteBaseDataSource::DoTransactionCommand(const char* pszCommand)
 
 {
-    int rc;
-    char *pszErrMsg;
-
 #ifdef DEBUG
     CPLDebug( "OGR_SQLITE", "%s Transaction", pszCommand );
 #endif
 
-    rc = sqlite3_exec( hDB, pszCommand, NULL, NULL, &pszErrMsg );
-    if( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "%s transaction failed: %s",
-                  pszCommand, pszErrMsg );
-        sqlite3_free( pszErrMsg );
-        return OGRERR_FAILURE;
-    }
-
-    return OGRERR_NONE;
+    return SQLCommand( hDB, pszCommand );
 }
 
 /************************************************************************/
@@ -2822,23 +2874,24 @@ const char* OGRSQLiteDataSource::GetSRTEXTColName()
     if( !bIsSpatiaLiteDB || bSpatialite4Layout )
         return "srtext";
 
-/* testing for SRS_WKT column presence */
-    int bHasSrsWkt = FALSE;
-    char **papszResult;
-    int nRowCount, nColCount;
+    // Testing for SRS_WKT column presence.
+    bool bHasSrsWkt = false;
+    char **papszResult = NULL;
+    int nRowCount = 0;
+    int nColCount = 0;
     char *pszErrMsg = NULL;
-    int rc = sqlite3_get_table( hDB, "PRAGMA table_info(spatial_ref_sys)",
-                            &papszResult, &nRowCount, &nColCount,
-                            &pszErrMsg );
+    const int rc =
+        sqlite3_get_table( hDB, "PRAGMA table_info(spatial_ref_sys)",
+                           &papszResult, &nRowCount, &nColCount,
+                           &pszErrMsg );
 
     if( rc == SQLITE_OK )
     {
-        int iRow;
-        for (iRow = 1; iRow <= nRowCount; iRow++)
+        for( int iRow = 1; iRow <= nRowCount; iRow++ )
         {
             if (EQUAL("srs_wkt",
                         papszResult[(iRow * nColCount) + 1]))
-                bHasSrsWkt = TRUE;
+                bHasSrsWkt = true;
         }
         sqlite3_free_table(papszResult);
     }
@@ -2880,28 +2933,19 @@ void OGRSQLiteDataSource::AddSRIDToCache(int nId, OGRSpatialReference * poSRS )
 int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 
 {
-    int                 nSRSId = nUndefinedSRID;
-    const char          *pszAuthorityName, *pszAuthorityCode = NULL;
-    CPLString           osCommand;
-    char *pszErrMsg;
-    int   rc;
-    char **papszResult;
-    int nRowCount, nColCount;
-
+    int nSRSId = nUndefinedSRID;
     if( poSRS == NULL )
         return nSRSId;
 
 /* -------------------------------------------------------------------- */
 /*      First, we look through our SRID cache, is it there?             */
 /* -------------------------------------------------------------------- */
-    int  i;
-
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( papoSRS[i] == poSRS )
             return panSRID[i];
     }
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( papoSRS[i] != NULL && papoSRS[i]->IsSame(poSRS) )
             return panSRID[i];
@@ -2913,7 +2957,8 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     OGRSpatialReference oSRS(*poSRS);
     poSRS = NULL;
 
-    pszAuthorityName = oSRS.GetAuthorityName(NULL);
+    const char *pszAuthorityName = oSRS.GetAuthorityName(NULL);
+    const char *pszAuthorityCode = NULL;
 
     if( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
     {
@@ -2941,6 +2986,12 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*      Check whether the EPSG authority code is already mapped to a    */
 /*      SRS ID.                                                         */
 /* -------------------------------------------------------------------- */
+    char *pszErrMsg = NULL;
+    CPLString osCommand;
+    char **papszResult = NULL;
+    int nRowCount = 0;
+    int nColCount = 0;
+
     if( pszAuthorityName != NULL && strlen(pszAuthorityName) > 0 )
     {
         pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
@@ -2952,11 +3003,12 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
             // the driver uses 'EPSG' in upper case, but SpatiaLite extension
             // uses 'epsg' in lower case.
             osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE "
-                              "auth_name = '%s' COLLATE NOCASE AND auth_srid = '%s'",
+                              "auth_name = '%s' COLLATE NOCASE AND auth_srid = '%s' "
+                              "LIMIT 2",
                               pszAuthorityName, pszAuthorityCode );
 
-            rc = sqlite3_get_table( hDB, osCommand, &papszResult,
-                                    &nRowCount, &nColCount, &pszErrMsg );
+            int rc = sqlite3_get_table( hDB, osCommand, &papszResult,
+                                        &nRowCount, &nColCount, &pszErrMsg );
             if( rc != SQLITE_OK )
             {
                 /* Retry without COLLATE NOCASE which may not be understood by older sqlite3 */
@@ -2981,7 +3033,8 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
                     sqlite3_free_table(papszResult);
 
                     osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE "
-                                      "auth_name = 'epsg' AND auth_srid = '%s'",
+                                      "auth_name = 'epsg' AND auth_srid = '%s' "
+                                      "LIMIT 2",
                                       pszAuthorityCode );
 
                     rc = sqlite3_get_table( hDB, osCommand, &papszResult,
@@ -3012,12 +3065,13 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*      Search for existing record using either WKT definition or       */
 /*      PROJ.4 string (SpatiaLite variant).                             */
 /* -------------------------------------------------------------------- */
-    CPLString   osWKT, osProj4;
+    CPLString osWKT;
+    CPLString osProj4;
 
 /* -------------------------------------------------------------------- */
 /*      Translate SRS to WKT.                                           */
 /* -------------------------------------------------------------------- */
-    char    *pszWKT = NULL;
+    char *pszWKT = NULL;
 
     if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
     {
@@ -3036,12 +3090,13 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
 /*      Try to find based on the WKT match.                             */
 /* -------------------------------------------------------------------- */
-        osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE \"%s\" = ?",
-                          OGRSQLiteEscapeName(pszSRTEXTColName).c_str());
+        osCommand.Printf( "SELECT srid FROM spatial_ref_sys WHERE \"%s\" = ? "
+                          "LIMIT 2",
+                          SQLEscapeName(pszSRTEXTColName).c_str());
     }
 
 /* -------------------------------------------------------------------- */
-/*      Handle SpatiaLite (< 4) flavour of the spatial_ref_sys.         */
+/*      Handle SpatiaLite (< 4) flavor of the spatial_ref_sys.         */
 /* -------------------------------------------------------------------- */
     else
     {
@@ -3064,11 +3119,11 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /*      Try to find based on the PROJ.4 match.                          */
 /* -------------------------------------------------------------------- */
         osCommand.Printf(
-            "SELECT srid FROM spatial_ref_sys WHERE proj4text = ?");
+            "SELECT srid FROM spatial_ref_sys WHERE proj4text = ? LIMIT 2");
     }
 
     sqlite3_stmt *hSelectStmt = NULL;
-    rc = sqlite3_prepare( hDB, osCommand, -1, &hSelectStmt, NULL );
+    int rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hSelectStmt, NULL );
 
     if( rc == SQLITE_OK)
         rc = sqlite3_bind_text( hSelectStmt, 1,
@@ -3108,7 +3163,7 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
 /*      Translate SRS to PROJ.4 string (if not already done)            */
 /* -------------------------------------------------------------------- */
-    if( osProj4.size() == 0 )
+    if( osProj4.empty() )
     {
         char* pszProj4 = NULL;
         if( oSRS.exportToProj4( &pszProj4 ) == OGRERR_NONE )
@@ -3125,8 +3180,9 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
 /* -------------------------------------------------------------------- */
     if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
     {
-        osCommand.Printf( "SELECT * FROM spatial_ref_sys WHERE auth_srid='%s'",
-                          OGRSQLiteEscape(pszAuthorityCode).c_str() );
+        osCommand.Printf( "SELECT * FROM spatial_ref_sys WHERE auth_srid='%s' "
+                          "LIMIT 2",
+                          SQLEscapeLiteral(pszAuthorityCode).c_str() );
         rc = sqlite3_get_table( hDB, osCommand, &papszResult,
                                 &nRowCount, &nColCount, &pszErrMsg );
 
@@ -3281,9 +3337,9 @@ int OGRSQLiteDataSource::FetchSRSId( OGRSpatialReference * poSRS )
     }
 
     sqlite3_stmt *hInsertStmt = NULL;
-    rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
+    rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hInsertStmt, NULL );
 
-    for(i=0;apszToInsert[i]!=NULL;i++)
+    for( int i = 0; apszToInsert[i] != NULL; i++ )
     {
         if( rc == SQLITE_OK)
             rc = sqlite3_bind_text( hInsertStmt, i+1, apszToInsert[i], -1, SQLITE_STATIC );
@@ -3327,9 +3383,7 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
 /* -------------------------------------------------------------------- */
 /*      First, we look through our SRID cache, is it there?             */
 /* -------------------------------------------------------------------- */
-    int  i;
-
-    for( i = 0; i < nKnownSRID; i++ )
+    for( int i = 0; i < nKnownSRID; i++ )
     {
         if( panSRID[i] == nId )
             return papoSRS[i];
@@ -3338,17 +3392,20 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
 /* -------------------------------------------------------------------- */
 /*      Try looking up in spatial_ref_sys table.                        */
 /* -------------------------------------------------------------------- */
-    char *pszErrMsg;
-    int   rc;
-    char **papszResult;
-    int nRowCount, nColCount;
-    CPLString osCommand;
+    char *pszErrMsg = NULL;
+    char **papszResult = NULL;
+    int nRowCount = 0;
+    int nColCount = 0;
     OGRSpatialReference *poSRS = NULL;
 
-    osCommand.Printf( "SELECT srtext FROM spatial_ref_sys WHERE srid = %d",
+    CPLString osCommand;
+    osCommand.Printf( "SELECT srtext FROM spatial_ref_sys WHERE srid = %d "
+                      "LIMIT 2",
                       nId );
-    rc = sqlite3_get_table( hDB, osCommand,
-                            &papszResult, &nRowCount, &nColCount, &pszErrMsg );
+    int rc =
+        sqlite3_get_table(
+            hDB, osCommand,
+            &papszResult, &nRowCount, &nColCount, &pszErrMsg );
 
     if ( rc == SQLITE_OK )
     {
@@ -3380,7 +3437,7 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
     }
 
 /* -------------------------------------------------------------------- */
-/*      Next try SpatiaLite flavour. SpatiaLite uses PROJ.4 strings     */
+/*      Next try SpatiaLite flavor. SpatiaLite uses PROJ.4 strings     */
 /*      in 'proj4text' column instead of WKT in 'srtext'. Note: recent  */
 /*      versions of spatialite have a srs_wkt column too                */
 /* -------------------------------------------------------------------- */
@@ -3395,7 +3452,8 @@ OGRSpatialReference *OGRSQLiteDataSource::FetchSRS( int nId )
             osSRTEXTColNameWithCommaBefore.Printf(", %s", pszSRTEXTColName);
 
         osCommand.Printf(
-            "SELECT proj4text, auth_name, auth_srid%s FROM spatial_ref_sys WHERE srid = %d",
+            "SELECT proj4text, auth_name, auth_srid%s FROM spatial_ref_sys "
+            "WHERE srid = %d LIMIT 2",
             (pszSRTEXTColName != NULL) ? osSRTEXTColNameWithCommaBefore.c_str() : "", nId );
         rc = sqlite3_get_table( hDB, osCommand,
                                 &papszResult, &nRowCount,
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
index 1074d30..00cf65c 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitedriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqlitedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteDriver class.
@@ -38,7 +37,7 @@
 #include "ogr_sqlite.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsqlitedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
+CPL_CVSID("$Id: ogrsqlitedriver.cpp 37599 2017-03-04 18:10:23Z rouault $");
 
 /************************************************************************/
 /*                     OGRSQLiteDriverIdentify()                        */
@@ -47,13 +46,23 @@ CPL_CVSID("$Id: ogrsqlitedriver.cpp 33714 2016-03-13 05:42:13Z goatbar $");
 static int OGRSQLiteDriverIdentify( GDALOpenInfo* poOpenInfo )
 
 {
-    int nLen = (int) strlen(poOpenInfo->pszFilename);
+    CPLString osExt(CPLGetExtension(poOpenInfo->pszFilename));
+    if( EQUAL(osExt, "gpkg") && GDALGetDriverByName("GPKG") != NULL )
+    {
+        return FALSE;
+    }
+
     if (STARTS_WITH_CI(poOpenInfo->pszFilename, "VirtualShape:") &&
-        nLen > 4 && EQUAL(poOpenInfo->pszFilename + nLen - 4, ".SHP"))
+        EQUAL(osExt, "shp"))
     {
         return TRUE;
     }
 
+#ifdef HAVE_RASTERLITE2
+    if( STARTS_WITH_CI(poOpenInfo->pszFilename, "RASTERLITE2:") )
+        return poOpenInfo->nOpenFlags & GDAL_OF_RASTER;
+#endif
+
     if( EQUAL(poOpenInfo->pszFilename, ":memory:") )
         return TRUE;
 
@@ -79,12 +88,21 @@ static int OGRSQLiteDriverIdentify( GDALOpenInfo* poOpenInfo )
 /*      Verify that the target is a real file, and has an               */
 /*      appropriate magic string at the beginning.                      */
 /* -------------------------------------------------------------------- */
-    if( poOpenInfo->nHeaderBytes < 16 )
+    if( poOpenInfo->nHeaderBytes < 100 )
         return FALSE;
 
     if( !STARTS_WITH((const char*)poOpenInfo->pabyHeader, "SQLite format 3") )
         return FALSE;
 
+    // In case we are opening /vsizip/foo.zip with a .gpkg inside
+    if( (memcmp(poOpenInfo->pabyHeader + 68, "GP10", 4) == 0 ||
+         memcmp(poOpenInfo->pabyHeader + 68, "GP11", 4) == 0 ||
+         memcmp(poOpenInfo->pabyHeader + 68, "GPKG", 4) == 0) &&
+        GDALGetDriverByName("GPKG") != NULL )
+    {
+        return FALSE;
+    }
+
     // Could be a Rasterlite file as well
     return -1;
 }
@@ -106,9 +124,7 @@ static GDALDataset *OGRSQLiteDriverOpen( GDALOpenInfo* poOpenInfo )
     if (STARTS_WITH_CI(poOpenInfo->pszFilename, "VirtualShape:") &&
         nLen > 4 && EQUAL(poOpenInfo->pszFilename + nLen - 4, ".SHP"))
     {
-        OGRSQLiteDataSource     *poDS;
-
-        poDS = new OGRSQLiteDataSource();
+        OGRSQLiteDataSource *poDS = new OGRSQLiteDataSource();
 
         char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
         int nRet = poDS->Create( ":memory:", papszOptions );
@@ -150,12 +166,10 @@ static GDALDataset *OGRSQLiteDriverOpen( GDALOpenInfo* poOpenInfo )
 /*      We think this is really an SQLite database, go ahead and try    */
 /*      and open it.                                                    */
 /* -------------------------------------------------------------------- */
-    OGRSQLiteDataSource     *poDS;
-
-    poDS = new OGRSQLiteDataSource();
+    OGRSQLiteDataSource *poDS = new OGRSQLiteDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update,
-                     poOpenInfo->papszOpenOptions ) )
+                     poOpenInfo->papszOpenOptions, poOpenInfo->nOpenFlags ) )
     {
         delete poDS;
         return NULL;
@@ -192,17 +206,15 @@ static GDALDataset *OGRSQLiteDriverCreate( const char * pszName,
 /* -------------------------------------------------------------------- */
 /*      Try to create datasource.                                       */
 /* -------------------------------------------------------------------- */
-    OGRSQLiteDataSource     *poDS;
-
-    poDS = new OGRSQLiteDataSource();
+    OGRSQLiteDataSource *poDS = new OGRSQLiteDataSource();
 
     if( !poDS->Create( pszName, papszOptions ) )
     {
         delete poDS;
         return NULL;
     }
-    else
-        return poDS;
+
+    return poDS;
 }
 
 /************************************************************************/
@@ -234,7 +246,12 @@ void RegisterOGRSQLite()
 
     poDriver->SetDescription( "SQLite" );
     poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+#ifdef HAVE_RASTERLITE2
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SQLite / Spatialite / RasterLite2" );
+#else
     poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "SQLite / Spatialite" );
+#endif
     poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drv_sqlite.html" );
     poDriver->SetMetadataItem( GDAL_DMD_EXTENSIONS, "sqlite db" );
 
@@ -242,16 +259,62 @@ void RegisterOGRSQLite()
 "<OpenOptionList>"
 "  <Option name='LIST_ALL_TABLES' type='boolean' description='Whether all tables, including non-spatial ones, should be listed' default='NO'/>"
 "  <Option name='LIST_VIRTUAL_OGR' type='boolean' description='Whether VirtualOGR virtual tables should be listed. Should only be enabled on trusted datasources to avoid potential safety issues' default='NO'/>"
+"  <Option name='1BIT_AS_8BIT' type='boolean' description='Whether to promote 1-bit monochrome raster as 8-bit, so as to have higher quality overviews' default='YES'/>"
 "</OpenOptionList>");
 
-    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
+    CPLString osCreationOptions(
 "<CreationOptionList>"
 #ifdef HAVE_SPATIALITE
 "  <Option name='SPATIALITE' type='boolean' description='Whether to create a Spatialite database' default='NO'/>"
 #endif
 "  <Option name='METADATA' type='boolean' description='Whether to create the geometry_columns and spatial_ref_sys tables' default='YES'/>"
 "  <Option name='INIT_WITH_EPSG' type='boolean' description='Whether to insert the content of the EPSG CSV files into the spatial_ref_sys table ' default='NO'/>"
-"</CreationOptionList>");
+#ifdef HAVE_RASTERLITE2
+"  <Option name='APPEND_SUBDATASET' scope='raster' type='boolean' description='Whether to add the raster to the existing file' default='NO'/>"
+"  <Option name='COVERAGE' scope='raster' type='string' description='Coverage name'/>"
+"  <Option name='SECTION' scope='raster' type='string' description='Section name'/>"
+"  <Option name='COMPRESS' scope='raster' type='string-select' description='Raster compression' default='NONE'>"
+"    <Value>NONE</Value>"
+#endif
+    );
+#ifdef HAVE_RASTERLITE2
+    if( rl2_is_supported_codec( RL2_COMPRESSION_DEFLATE ) )
+        osCreationOptions += "    <Value>DEFLATE</Value>";
+    if( rl2_is_supported_codec( RL2_COMPRESSION_LZMA ) )
+        osCreationOptions += "    <Value>LZMA</Value>";
+    if( rl2_is_supported_codec( RL2_COMPRESSION_PNG ) )
+        osCreationOptions += "    <Value>PNG</Value>";
+    if( rl2_is_supported_codec( RL2_COMPRESSION_CCITTFAX4 ) )
+        osCreationOptions += "    <Value>CCITTFAX4</Value>";
+    if( rl2_is_supported_codec( RL2_COMPRESSION_JPEG ) )
+        osCreationOptions += "    <Value>JPEG</Value>";
+    if( rl2_is_supported_codec( RL2_COMPRESSION_LOSSY_WEBP ) )
+        osCreationOptions += "    <Value>WEBP</Value>";
+    if( rl2_is_supported_codec( RL2_COMPRESSION_CHARLS ) )
+        osCreationOptions += "    <Value>CHARLS</Value>";
+    if( rl2_is_supported_codec( RL2_COMPRESSION_LOSSY_JP2 ) )
+        osCreationOptions += "    <Value>JPEG2000</Value>";
+#endif
+    osCreationOptions +=
+#ifdef HAVE_RASTERLITE2
+"  </Option>"
+"  <Option name='QUALITY' scope='raster' type='int' description='Image quality for JPEG, WEBP and JPEG2000 compressions'/>"
+"  <Option name='PIXEL_TYPE' scope='raster' type='string-select' description='Raster pixel type. Determines photometric interpretation'>"
+"    <Value>MONOCHROME</Value>"
+"    <Value>PALETTE</Value>"
+"    <Value>GRAYSCALE</Value>"
+"    <Value>RGB</Value>"
+"    <Value>MULTIBAND</Value>"
+"    <Value>DATAGRID</Value>"
+"  </Option>"
+"  <Option name='BLOCKXSIZE' scope='raster' type='int' description='Block width' default='512'/>"
+"  <Option name='BLOCKYSIZE' scope='raster' type='int' description='Block height' default='512'/>"
+"  <Option name='NBITS' scope='raster' type='int' description='Force bit width. 1, 2 or 4 are supported'/>"
+"  <Option name='PYRAMIDIZE' scope='raster' type='boolean' description='Whether to automatically build relevant pyramids/overviews' default='NO'/>"
+#endif
+"</CreationOptionList>";
+
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST, osCreationOptions);
 
     poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
 "<LayerCreationOptionList>"
@@ -276,7 +339,13 @@ void RegisterOGRSQLite()
 
     poDriver->SetMetadataItem( GDAL_DMD_CREATIONFIELDDATATYPES,
                                "Integer Integer64 Real String Date DateTime "
-                               "Time Binary" );
+                               "Time Binary IntegerList Integer64List "
+                               "RealList StringList" );
+#ifdef HAVE_RASTERLITE2
+    poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
+                               "Byte UInt16 Int16 UInt32 Int32 Float32 "
+                               "Float64" );
+#endif
     poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_FIELDS, "YES" );
     poDriver->SetMetadataItem( GDAL_DCAP_DEFAULT_FIELDS, "YES" );
     poDriver->SetMetadataItem( GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES" );
@@ -285,6 +354,9 @@ void RegisterOGRSQLite()
     poDriver->pfnOpen = OGRSQLiteDriverOpen;
     poDriver->pfnIdentify = OGRSQLiteDriverIdentify;
     poDriver->pfnCreate = OGRSQLiteDriverCreate;
+#ifdef HAVE_RASTERLITE2
+    poDriver->pfnCreateCopy = OGRSQLiteDriverCreateCopy;
+#endif
     poDriver->pfnDelete = OGRSQLiteDriverDelete;
     poDriver->pfnUnloadDriver = OGRSQLiteDriverUnload;
 
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
index 045c871..1dde949 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqliteexecutesql.cpp 34082 2016-04-24 22:10:13Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Run SQL requests with SQLite SQL engine
@@ -31,9 +30,10 @@
 #include "ogr_api.h"
 #include "ogrsqlitevirtualogr.h"
 #include "ogrsqliteexecutesql.h"
+#include "ogrsqliteutility.h"
 #include "cpl_multiproc.h"
 
-#ifdef HAVE_SQLITE_VFS
+CPL_CVSID("$Id: ogrsqliteexecutesql.cpp 37809 2017-03-20 15:28:41Z rouault $");
 
 /************************************************************************/
 /*                       OGRSQLiteExecuteSQLLayer                       */
@@ -41,35 +41,34 @@
 
 class OGRSQLiteExecuteSQLLayer: public OGRSQLiteSelectLayer
 {
-        char             *pszTmpDBName;
-
-    public:
-        OGRSQLiteExecuteSQLLayer(char* pszTmpDBName,
-                                 OGRSQLiteDataSource* poDS,
-                                 CPLString osSQL,
-                                 sqlite3_stmt * hStmt,
-                                 int bUseStatementForGetNextFeature,
-                                 int bEmptyLayer );
-        virtual ~OGRSQLiteExecuteSQLLayer();
+    char             *pszTmpDBName;
+
+  public:
+    OGRSQLiteExecuteSQLLayer( char* pszTmpDBName,
+                              OGRSQLiteDataSource* poDS,
+                              CPLString osSQL,
+                              sqlite3_stmt * hStmt,
+                              int bUseStatementForGetNextFeature,
+                              int bEmptyLayer );
+    virtual ~OGRSQLiteExecuteSQLLayer();
 };
 
 /************************************************************************/
 /*                         OGRSQLiteExecuteSQLLayer()                   */
 /************************************************************************/
 
-OGRSQLiteExecuteSQLLayer::OGRSQLiteExecuteSQLLayer(char* pszTmpDBNameIn,
-                                                   OGRSQLiteDataSource* poDSIn,
-                                                   CPLString osSQL,
-                                                   sqlite3_stmt * hStmtIn,
-                                                   int bUseStatementForGetNextFeature,
-                                                   int bEmptyLayer ) :
-
-                               OGRSQLiteSelectLayer(poDSIn, osSQL, hStmtIn,
-                                                    bUseStatementForGetNextFeature,
-                                                    bEmptyLayer, TRUE)
-{
-    this->pszTmpDBName = pszTmpDBNameIn;
-}
+OGRSQLiteExecuteSQLLayer::OGRSQLiteExecuteSQLLayer(
+    char* pszTmpDBNameIn,
+    OGRSQLiteDataSource* poDSIn,
+    CPLString osSQL,
+    sqlite3_stmt * hStmtIn,
+    int bUseStatementForGetNextFeature,
+    int bEmptyLayer ) :
+    OGRSQLiteSelectLayer(poDSIn, osSQL, hStmtIn,
+                         bUseStatementForGetNextFeature,
+                         bEmptyLayer, TRUE),
+    pszTmpDBName(pszTmpDBNameIn)
+{}
 
 /************************************************************************/
 /*                        ~OGRSQLiteExecuteSQLLayer()                   */
@@ -77,10 +76,10 @@ OGRSQLiteExecuteSQLLayer::OGRSQLiteExecuteSQLLayer(char* pszTmpDBNameIn,
 
 OGRSQLiteExecuteSQLLayer::~OGRSQLiteExecuteSQLLayer()
 {
-    /* This is a bit peculiar: we must "finalize" the OGRLayer, since */
-    /* it has objects that depend on the datasource, that we are just */
-    /* going to destroy afterwards. The issue here is that we destroy */
-    /* our own datasource ! */
+    // This is a bit peculiar: we must "finalize" the OGRLayer, since
+    // it has objects that depend on the datasource, that we are just
+    // going to destroy afterwards. The issue here is that we destroy
+    // our own datasource,
     Finalize();
 
     delete poDS;
@@ -187,7 +186,7 @@ static void OGR2SQLITEAddLayer( const char*& pszStart, int& nNum,
     pszStart = pszSQLCommand;
     LayerDesc oLayerDesc = OGR2SQLITEExtractLayerDesc(&pszSQLCommand);
     int bInsert = TRUE;
-    if( oLayerDesc.osDSName.size() == 0 )
+    if( oLayerDesc.osDSName.empty() )
     {
         osTruncated = pszStart;
         osTruncated.resize(pszSQLCommand - pszStart);
@@ -226,8 +225,7 @@ static const char* const apszKeywords[] =  {
 
 static int StartsAsSQLITEKeyWord(const char* pszStr)
 {
-    int i;
-    for(i=0;i<(int)(sizeof(apszKeywords) / sizeof(char*));i++)
+    for( int i = 0; i < (int)(sizeof(apszKeywords) / sizeof(char*)); i++ )
     {
         if( EQUALN(pszStr, apszKeywords[i], strlen(apszKeywords[i])) )
             return TRUE;
@@ -247,7 +245,7 @@ static void OGR2SQLITEGetPotentialLayerNamesInternal(const char **ppszSQLCommand
 {
     const char *pszSQLCommand = *ppszSQLCommand;
     const char* pszStart = pszSQLCommand;
-    char ch;
+    char ch = '\0';
     int nParenthesisLevel = 0;
     int bLookforFTableName = FALSE;
 
@@ -484,7 +482,6 @@ void OGR2SQLITE_IgnoreAllFieldsExceptGeometry(OGRLayer* poLayer)
 }
 #endif
 
-
 /************************************************************************/
 /*                  OGR2SQLITEDealWithSpatialColumn()                   */
 /************************************************************************/
@@ -517,15 +514,15 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
         osGeomColRaw = poGeomField->GetNameRef();
     const char* pszGeomColRaw = osGeomColRaw.c_str();
 
-    CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw));
+    CPLString osGeomColEscaped(SQLEscapeLiteral(pszGeomColRaw));
     const char* pszGeomColEscaped = osGeomColEscaped.c_str();
 
-    CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName));
+    CPLString osLayerNameEscaped(SQLEscapeLiteral(osTableName));
     const char* pszLayerNameEscaped = osLayerNameEscaped.c_str();
 
     CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s",
                     oLayerDesc.osLayerName.c_str(), pszGeomColRaw));
-    CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw));
+    CPLString osIdxNameEscaped(SQLEscapeName(osIdxNameRaw));
 
     /* Make sure that the SRS is injected in spatial_ref_sys */
     OGRSpatialReference* poSRS = poGeomField->GetSpatialRef();
@@ -645,7 +642,7 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
                     "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)",
                     osIdxNameEscaped.c_str(),
                     nExtraDS,
-                    OGRSQLiteEscape(oLayerDesc.osLayerName).c_str());
+                    SQLEscapeLiteral(oLayerDesc.osLayerName).c_str());
 
     rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
     if( rc != SQLITE_OK )
@@ -670,14 +667,14 @@ int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
         const char* pszInsertInto = CPLSPrintf(
             "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) "
             "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str());
-        rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL);
+        rc = sqlite3_prepare_v2(hDB, pszInsertInto, -1, &hStmt, NULL);
     }
 
-    OGRFeature* poFeature;
-    OGREnvelope sEnvelope;
     OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer);
     poLayer->ResetReading();
 
+    OGRFeature* poFeature = NULL;
+    OGREnvelope sEnvelope;
     while( rc == SQLITE_OK &&
             (poFeature = poLayer->GetNextFeature()) != NULL )
     {
@@ -728,10 +725,10 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
                                 CPL_UNUSED const char *pszDialect )
 {
     char* pszTmpDBName = (char*) CPLMalloc(256);
-    snprintf(pszTmpDBName, 256, "/vsimem/ogr2sqlite/temp_%p.db", pszTmpDBName);
+    void* ptr = pszTmpDBName;
+    snprintf(pszTmpDBName, 256, "/vsimem/ogr2sqlite/temp_%p.db", ptr);
 
     OGRSQLiteDataSource* poSQLiteDS = NULL;
-    int nRet;
     int bSpatialiteDB = FALSE;
 
     CPLString osOldVal;
@@ -765,11 +762,12 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
         {
             bTried = TRUE;
             char* pszCachedFilename = (char*) CPLMalloc(256);
+            void* ptrCached = pszCachedFilename;
             snprintf(pszCachedFilename, 256, "/vsimem/ogr2sqlite/reference_%p.db",
-                    pszCachedFilename);
+                     ptrCached);
             char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
             OGRSQLiteDataSource* poCachedDS = new OGRSQLiteDataSource();
-            nRet = poCachedDS->Create( pszCachedFilename, papszOptions );
+            const int nRet = poCachedDS->Create( pszCachedFilename, papszOptions );
             CSLDestroy(papszOptions);
             papszOptions = NULL;
             delete poCachedDS;
@@ -799,7 +797,7 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
 
         poSQLiteDS = new OGRSQLiteDataSource();
         CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO");
-        nRet = poSQLiteDS->Open( pszTmpDBName, TRUE, NULL );
+        const int nRet = poSQLiteDS->Open( pszTmpDBName, TRUE, NULL, GDAL_OF_VECTOR );
         CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal);
         if( !nRet )
         {
@@ -816,7 +814,7 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
     poSQLiteDS = new OGRSQLiteDataSource();
     char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
     CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO");
-    nRet = poSQLiteDS->Create( pszTmpDBName, papszOptions );
+    const int nRet = poSQLiteDS->Create( pszTmpDBName, papszOptions );
     CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal);
     CSLDestroy(papszOptions);
     papszOptions = NULL;
@@ -834,9 +832,11 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
     if( true )
     {
 #endif // HAVE_SPATIALITE
+
+        // cppcheck-suppress redundantAssignment
         poSQLiteDS = new OGRSQLiteDataSource();
         CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO");
-        nRet = poSQLiteDS->Create( pszTmpDBName, NULL );
+        const int nRet = poSQLiteDS->Create( pszTmpDBName, NULL );
         CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal);
         if( !nRet )
         {
@@ -885,8 +885,8 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
         CPLString osSQL;
         OGRLayer* poLayer = NULL;
         CPLString osTableName;
-        int nExtraDS;
-        if( oLayerDesc.osDSName.size() == 0 )
+        int nExtraDS = -1;
+        if( oLayerDesc.osDSName.empty() )
         {
             poLayer = poDS->GetLayerByName(oLayerDesc.osLayerName);
             /* Might be a false positive (unlikely) */
@@ -894,8 +894,6 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
                 continue;
 
             osTableName = oLayerDesc.osLayerName;
-
-            nExtraDS = -1;
         }
         else
         {
@@ -935,9 +933,9 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
             poSingleSrcLayer = poLayer;
 
         osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d,%d)",
-                OGRSQLiteEscapeName(osTableName).c_str(),
+                SQLEscapeName(osTableName).c_str(),
                 nExtraDS,
-                OGRSQLiteEscape(oLayerDesc.osLayerName).c_str(),
+                SQLEscapeLiteral(oLayerDesc.osLayerName).c_str(),
                 bFoundOGRStyle,
                 TRUE/*bExposeOGRNativeData*/);
 
@@ -977,14 +975,14 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
     int bEmptyLayer = FALSE;
 
     sqlite3_stmt *hSQLStmt = NULL;
-    int rc = sqlite3_prepare( hDB,
+    int rc = sqlite3_prepare_v2( hDB,
                               pszStatement, -1,
                               &hSQLStmt, NULL );
 
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
+                "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n  %s",
                 pszStatement, sqlite3_errmsg(hDB) );
 
         if( hSQLStmt != NULL )
@@ -1072,31 +1070,3 @@ std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char* pszStatement)
 
     return oSetLayers;
 }
-
-#else // HAVE_SQLITE_VFS
-
-/************************************************************************/
-/*                          OGRSQLiteExecuteSQL()                       */
-/************************************************************************/
-
-OGRLayer * OGRSQLiteExecuteSQL( OGRDataSource* poDS,
-                                const char *pszStatement,
-                                OGRGeometry *poSpatialFilter,
-                                const char *pszDialect )
-{
-    CPLError(CE_Failure, CPLE_NotSupported,
-                "The SQLite version is to old to support the SQLite SQL dialect");
-    return NULL;
-}
-
-/************************************************************************/
-/*                   OGRSQLiteGetReferencedLayers()                     */
-/************************************************************************/
-
-std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char* pszStatement)
-{
-     std::set<LayerDesc> oSetLayers;
-     return oSetLayers;
-}
-
-#endif // HAVE_SQLITE_VFS
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h
index 4cdb798..5fd130d 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteexecutesql.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqliteexecutesql.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogrsqliteexecutesql.h 35911 2016-10-24 15:03:26Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Run SQL requests with SQLite SQL engine
@@ -39,7 +39,6 @@ OGRLayer * OGRSQLiteExecuteSQL( GDALDataset* poDS,
                                 OGRGeometry *poSpatialFilter,
                                 const char *pszDialect );
 
-
 /************************************************************************/
 /*                               LayerDesc                              */
 /************************************************************************/
@@ -64,4 +63,3 @@ std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char* pszStatement);
 
 #endif /* ndef OGR_SQLITE_EXECUTE_SQL_H_INCLUDED */
 
-
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
index 87a67d5..9831e35 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqlitelayer.cpp 35899 2016-10-24 11:56:25Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteLayer class, code shared between
@@ -40,40 +39,31 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_sqlite.h"
+#include "ogrsqliteutility.h"
 #include <cassert>
 
-CPL_CVSID("$Id: ogrsqlitelayer.cpp 35899 2016-10-24 11:56:25Z rouault $");
+CPL_CVSID("$Id: ogrsqlitelayer.cpp 37809 2017-03-20 15:28:41Z rouault $");
 
 /************************************************************************/
 /*                           OGRSQLiteLayer()                           */
 /************************************************************************/
 
-OGRSQLiteLayer::OGRSQLiteLayer()
-
-{
-    poDS = NULL;
-
-    pszFIDColumn = NULL;
-
-    hStmt = NULL;
-    bDoStep = TRUE;
-
-    poFeatureDefn = NULL;
-    iNextShapeId = 0;
-
-    panFieldOrdinals = NULL;
-    iFIDCol = -1;
-    iOGRNativeDataCol = -1;
-    iOGRNativeMediaTypeCol = -1;
-
-    bIsVirtualShape = FALSE;
-
-    bUseComprGeom = CPLTestBool(CPLGetConfigOption("COMPRESS_GEOM", "FALSE"));
-
-    papszCompressedColumns = NULL;
-
-    bAllowMultipleGeomFields = FALSE;
-}
+OGRSQLiteLayer::OGRSQLiteLayer() :
+    poFeatureDefn(NULL),
+    iNextShapeId(0),
+    hStmt(NULL),
+    bDoStep(TRUE),
+    poDS(NULL),
+    pszFIDColumn(NULL),
+    panFieldOrdinals(NULL),
+    iFIDCol(-1),
+    iOGRNativeDataCol(-1),
+    iOGRNativeMediaTypeCol(-1),
+    bIsVirtualShape(FALSE),
+    bUseComprGeom(CPLTestBool(CPLGetConfigOption("COMPRESS_GEOM", "FALSE"))),
+    papszCompressedColumns(NULL),
+    bAllowMultipleGeomFields(FALSE)
+{}
 
 /************************************************************************/
 /*                          ~OGRSQLiteLayer()                           */
@@ -135,24 +125,26 @@ int OGRIsBinaryGeomCol( sqlite3_stmt *hStmt,
 {
     OGRGeometry* poGeometry = NULL;
     const int nBytes = sqlite3_column_bytes( hStmt, iCol );
+    // coverity[tainted_data_return]
+    GByte* pabyBlob = (GByte*)sqlite3_column_blob( hStmt, iCol );
     int nBytesConsumed = 0;
     CPLPushErrorHandler(CPLQuietErrorHandler);
     /* Try as spatialite first since createFromWkb() can sometimes */
     /* interpret spatialite blobs as WKB for certain SRID values */
     if( OGRSQLiteLayer::ImportSpatiaLiteGeometry(
-            (GByte*)sqlite3_column_blob( hStmt, iCol ), nBytes,
+            pabyBlob, nBytes,
             &poGeometry ) == OGRERR_NONE )
     {
         eGeomFormat = OSGF_SpatiaLite;
     }
     else if( OGRGeometryFactory::createFromWkb(
-            (GByte*)sqlite3_column_blob( hStmt, iCol ),
+            pabyBlob,
             NULL, &poGeometry, nBytes ) == OGRERR_NONE )
     {
         eGeomFormat = OSGF_WKB;
     }
     else if( OGRGeometryFactory::createFromFgf(
-            (GByte*)sqlite3_column_blob( hStmt, iCol ),
+            pabyBlob,
             NULL, &poGeometry, nBytes, &nBytesConsumed ) == OGRERR_NONE &&
              nBytes == nBytesConsumed )
     {
@@ -185,14 +177,13 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
     poFeatureDefn->SetGeomType(wkbNone);
     poFeatureDefn->Reference();
 
-    int    nRawColumns = sqlite3_column_count( hStmtIn );
+    const int nRawColumns = sqlite3_column_count( hStmtIn );
 
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
 
-    int iCol;
-    for( iCol = 0; iCol < nRawColumns; iCol++ )
+    for( int iCol = 0; iCol < nRawColumns; iCol++ )
     {
-        OGRFieldDefn    oField( OGRSQLiteParamsUnquote(sqlite3_column_name( hStmtIn, iCol )),
+        OGRFieldDefn    oField( SQLUnescape(sqlite3_column_name( hStmtIn, iCol )),
                                 OFTString );
 
         // In some cases, particularly when there is a real name for
@@ -224,7 +215,7 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
         if( pszFIDColumn != NULL && EQUAL(pszFIDColumn, oField.GetNameRef()))
             continue;
 
-        //oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
+        // oField.SetWidth( std::max(0,poStmt->GetColSize( iCol )) );
 
         if( aosIgnoredCols.find( CPLString(oField.GetNameRef()).tolower() ) != aosIgnoredCols.end() )
         {
@@ -283,19 +274,19 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
                 oField.SetType(OFTInteger);
                 oField.SetSubType(OFSTInt16);
             }
-            else if (EQUAL(pszDeclType, "INTEGERLIST"))
+            else if (EQUAL(pszDeclType, "JSONINTEGERLIST"))
             {
                 oField.SetType(OFTIntegerList);
             }
-            else if (EQUAL(pszDeclType, "INTEGER64LIST"))
+            else if (EQUAL(pszDeclType, "JSONINTEGER64LIST"))
             {
                 oField.SetType(OFTInteger64List);
             }
-            else if (EQUAL(pszDeclType, "REALLIST"))
+            else if (EQUAL(pszDeclType, "JSONREALLIST"))
             {
                 oField.SetType(OFTRealList);
             }
-            else if (EQUAL(pszDeclType, "STRINGLIST"))
+            else if (EQUAL(pszDeclType, "JSONSTRINGLIST"))
             {
                 oField.SetType(OFTStringList);
             }
@@ -524,9 +515,9 @@ void OGRSQLiteLayer::BuildFeatureDefn( const char *pszLayerName,
 
     if( pszFIDColumn != NULL )
     {
-        for( iCol = 0; iCol < nRawColumns; iCol++ )
+        for( int iCol = 0; iCol < nRawColumns; iCol++ )
         {
-            if( EQUAL(OGRSQLiteParamsUnquote(sqlite3_column_name(hStmtIn,iCol)).c_str(),
+            if( EQUAL(SQLUnescape(sqlite3_column_name(hStmtIn,iCol)).c_str(),
                       pszFIDColumn) )
             {
                 iFIDCol = iCol;
@@ -570,9 +561,7 @@ OGRFeature *OGRSQLiteLayer::GetNextFeature()
 {
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -605,9 +594,7 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
     if( bDoStep )
     {
-        int rc;
-
-        rc = sqlite3_step( hStmt );
+        const int rc = sqlite3_step( hStmt );
         if( rc != SQLITE_ROW )
         {
             if ( rc != SQLITE_DONE )
@@ -624,12 +611,13 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
         }
     }
     else
+    {
         bDoStep = TRUE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Create a feature from the current result.                       */
 /* -------------------------------------------------------------------- */
-    int         iField;
     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
 /* -------------------------------------------------------------------- */
@@ -647,7 +635,7 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      Process Geometry if we have a column.                           */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; iField < poFeatureDefn->GetGeomFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetGeomFieldCount(); iField++ )
     {
         OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
             poFeatureDefn->myGetGeomFieldDefn(iField);
@@ -673,8 +661,9 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
                 {
                     /* If the layer is the result of a sql select, we cannot be sure if it is */
                     /* WKB or SpatialLite format */
-                    if( ImportSpatiaLiteGeometry(
-                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ), nBytes,
+                    // coverity[tainted_data_return]
+                    GByte* pabyBlob = (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol );
+                    if( ImportSpatiaLiteGeometry( pabyBlob, nBytes,
                         &poGeometry ) == OGRERR_NONE )
                     {
                         poGeomFieldDefn->eGeomFormat = OSGF_SpatiaLite;
@@ -684,26 +673,27 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
 
                 if( poGeomFieldDefn->eGeomFormat == OSGF_WKB )
                 {
+                    // coverity[tainted_data_return]
+                    GByte* pabyBlob = (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol );
                     CPL_IGNORE_RET_VAL(OGRGeometryFactory::createFromWkb(
-                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ),
-                        NULL, &poGeometry, nBytes ));
+                        pabyBlob, NULL, &poGeometry, nBytes ));
                 }
             }
             else if ( poGeomFieldDefn->eGeomFormat == OSGF_FGF )
             {
                 const int nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol );
-
-                OGRGeometryFactory::createFromFgf(
-                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ),
+                // coverity[tainted_data_return]
+                GByte* pabyBlob = (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol );
+                OGRGeometryFactory::createFromFgf( pabyBlob,
                         NULL, &poGeometry, nBytes, NULL );
             }
             else if ( poGeomFieldDefn->eGeomFormat == OSGF_SpatiaLite )
             {
                 const int nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol );
-
+                // coverity[tainted_data_return]
+                GByte* pabyBlob = (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol );
                 CPL_IGNORE_RET_VAL(ImportSpatiaLiteGeometry(
-                        (GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol ), nBytes,
-                        &poGeometry ));
+                        pabyBlob, nBytes, &poGeometry ));
             }
 
             if (poGeometry != NULL )
@@ -718,7 +708,7 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
 /* -------------------------------------------------------------------- */
 /*      set the fields.                                                 */
 /* -------------------------------------------------------------------- */
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );
         if ( poFieldDefn->IsIgnored() )
@@ -728,7 +718,10 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
 
         int nSQLite3Type = sqlite3_column_type( hStmt, iRawField );
         if( nSQLite3Type == SQLITE_NULL )
+        {
+            poFeature->SetFieldNull( iField );
             continue;
+        }
 
         switch( poFieldDefn->GetType() )
         {
@@ -760,9 +753,11 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
         case OFTBinary:
             {
                 const int nBytes = sqlite3_column_bytes( hStmt, iRawField );
-
+                // coverity[tainted_data_return]
+                const GByte* pabyData = reinterpret_cast<const GByte*>(
+                    sqlite3_column_blob( hStmt, iRawField ) );
                 poFeature->SetField( iField, nBytes,
-                    (GByte*)sqlite3_column_blob( hStmt, iRawField ) );
+                                     const_cast<GByte*>(pabyData) );
             }
             break;
 
@@ -776,6 +771,7 @@ OGRFeature *OGRSQLiteLayer::GetNextRawFeature()
                               poFeatureDefn->GetFieldDefn(iField)->GetNameRef()) >= 0 )
             {
                 const int nBytes = sqlite3_column_bytes( hStmt, iRawField );
+                // coverity[tainted_data_return]
                 GByte* pabyBlob = (GByte*)sqlite3_column_blob( hStmt, iRawField );
 
                 void* pOut = CPLZLibInflate( pabyBlob, nBytes, NULL, 0, NULL );
@@ -859,7 +855,6 @@ OGRFeature *OGRSQLiteLayer::GetFeature( GIntBig nFeatureId )
     return OGRLayer::GetFeature( nFeatureId );
 }
 
-
 /************************************************************************/
 /*                     createFromSpatialiteInternal()                   */
 /************************************************************************/
@@ -875,7 +870,6 @@ OGRFeature *OGRSQLiteLayer::GetFeature( GIntBig nFeatureId )
 #define NEED_SWAP_SPATIALITE()  (eByteOrder == wkbNDR)
 #endif
 
-
 OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                                                     OGRGeometry **ppoReturn,
                                                     int nBytes,
@@ -883,10 +877,6 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                                                     int* pnBytesConsumed,
                                                     int nRecLevel)
 {
-    OGRGeometry *poGeom = NULL;
-    GInt32       nGType;
-    GInt32       compressedSize;
-
     *ppoReturn = NULL;
 
     /* Arbitrary value, but certainly large enough for reasonable usages ! */
@@ -905,8 +895,9 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
 /*      Decode the geometry type.                                       */
 /* -------------------------------------------------------------------- */
+    GInt32 nGType = 0;
     memcpy( &nGType, pabyData, 4 );
-    if (NEED_SWAP_SPATIALITE())
+    if( NEED_SWAP_SPATIALITE() )
         CPL_SWAP32PTR( &nGType );
 
     if( ( nGType >= OGRSplitePointXY &&
@@ -932,13 +923,16 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
 /*      Point [XY]                                                      */
 /* -------------------------------------------------------------------- */
+    OGRGeometry *poGeom = NULL;
+    GInt32 compressedSize = 0;
+
     if( nGType == OGRSplitePointXY )
     {
-        double  adfTuple[2];
-
         if( nBytes < 4 + 2 * 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        double adfTuple[2] = { 0.0, 0.0 };
+
         memcpy( adfTuple, pabyData + 4, 2*8 );
         if (NEED_SWAP_SPATIALITE())
         {
@@ -956,11 +950,11 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSplitePointXYZ )
     {
-        double  adfTuple[3];
-
         if( nBytes < 4 + 3 * 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        double adfTuple[3] = { 0.0, 0.0, 0.0 };
+
         memcpy( adfTuple, pabyData + 4, 3*8 );
         if (NEED_SWAP_SPATIALITE())
         {
@@ -980,11 +974,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSplitePointXYM )
     {
-        double  adfTuple[3];
-
         if( nBytes < 4 + 3 * 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        double adfTuple[3] = { 0.0, 0.0, 0.0 };
         memcpy( adfTuple, pabyData + 4, 3*8 );
         if (NEED_SWAP_SPATIALITE())
         {
@@ -1006,11 +999,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSplitePointXYZM )
     {
-        double  adfTuple[4];
-
         if( nBytes < 4 + 4 * 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        double  adfTuple[4];
         memcpy( adfTuple, pabyData + 4, 4*8 );
         if (NEED_SWAP_SPATIALITE())
         {
@@ -1031,14 +1023,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteLineStringXY )
     {
-        double adfTuple[2];
-        GInt32 nPointCount;
-        int    iPoint;
-        OGRLineString *poLS;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nPointCount = 0;
         memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nPointCount );
@@ -1049,7 +1037,8 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < 2 * 8 * nPointCount )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        poGeom = poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
+        poGeom = poLS;
         if( !NEED_SWAP_SPATIALITE() )
         {
             poLS->setPoints( nPointCount, (OGRRawPoint*)(pabyData + 8), NULL );
@@ -1057,8 +1046,9 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         else
         {
             poLS->setNumPoints( nPointCount, FALSE );
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                double adfTuple[2] = { 0.0, 0.0 };
                 memcpy( adfTuple, pabyData + 8 + 2*8*iPoint, 2*8 );
                 CPL_SWAP64PTR( adfTuple );
                 CPL_SWAP64PTR( adfTuple + 1 );
@@ -1075,14 +1065,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteLineStringXYZ )
     {
-        double adfTuple[3];
-        GInt32 nPointCount;
-        int    iPoint;
-        OGRLineString *poLS;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nPointCount = 0;
         memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nPointCount );
@@ -1093,11 +1079,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < 3 * 8 * nPointCount )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        poGeom = poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
+        poGeom = poLS;
         poLS->setNumPoints( nPointCount );
 
-        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
+            double adfTuple[3] = { 0.0, 0.0, 0.0 };
             memcpy( adfTuple, pabyData + 8 + 3*8*iPoint, 3*8 );
             if (NEED_SWAP_SPATIALITE())
             {
@@ -1118,14 +1106,11 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteLineStringXYM )
     {
-        double adfTuple[3];
-        GInt32 nPointCount;
-        int    iPoint;
-        OGRLineString *poLS;
 
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nPointCount = 0;
         memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nPointCount );
@@ -1136,11 +1121,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < 3 * 8 * nPointCount )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        poGeom = poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
+        poGeom = poLS;
         poLS->setNumPoints( nPointCount );
 
-        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
+            double adfTuple[3] = { 0.0, 0.0, 0.0 };
             memcpy( adfTuple, pabyData + 8 + 3*8*iPoint, 3*8 );
             if (NEED_SWAP_SPATIALITE())
             {
@@ -1161,14 +1148,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteLineStringXYZM )
     {
-        double adfTuple[4];
-        GInt32 nPointCount;
-        int    iPoint;
-        OGRLineString *poLS;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nPointCount = 0;
         memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nPointCount );
@@ -1179,11 +1162,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < 4 * 8 * nPointCount )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        poGeom = poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
+        poGeom = poLS;
         poLS->setNumPoints( nPointCount );
 
-        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
+            double adfTuple[4] = { 0.0, 0.0, 0.0, 0.0 };
             memcpy( adfTuple, pabyData + 8 + 4*8*iPoint, 4*8 );
             if (NEED_SWAP_SPATIALITE())
             {
@@ -1205,17 +1190,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprLineStringXY )
     {
-        double adfTuple[2];
-        double adfTupleBase[2];
-        float asfTuple[2];
-        GInt32 nPointCount;
-        int    iPoint;
-        OGRLineString *poLS;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nPointCount = 0;
         memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nPointCount );
@@ -1229,15 +1207,17 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < compressedSize )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        poGeom = poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
+        poGeom = poLS;
         poLS->setNumPoints( nPointCount );
 
-        nNextByte = 8;
-        adfTupleBase[0] = 0.0;
-        adfTupleBase[1] = 0.0;
+        int nNextByte = 8;
+        double adfTupleBase[2] = { 0.0, 0.0 };
 
-        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
+            double adfTuple[2] = { 0.0, 0.0 };
+
             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
             {
                 // first and last Points are uncompressed
@@ -1253,6 +1233,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             else
             {
                 // any other intermediate Point is compressed
+                float asfTuple[2] = { 0.0f, 0.0f };
                 memcpy( asfTuple, pabyData + nNextByte, 2*4 );
                 nNextByte += 2 * 4;
 
@@ -1279,17 +1260,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprLineStringXYZ )
     {
-        double adfTuple[3];
-        double adfTupleBase[3];
-        float asfTuple[3];
-        GInt32 nPointCount;
-        int    iPoint;
-        OGRLineString *poLS;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nPointCount = 0;
         memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nPointCount );
@@ -1303,16 +1277,17 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < compressedSize )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        poGeom = poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
+        poGeom = poLS;
         poLS->setNumPoints( nPointCount );
 
-        nNextByte = 8;
-        adfTupleBase[0] = 0.0;
-        adfTupleBase[1] = 0.0;
-        adfTupleBase[2] = 0.0;
+        int nNextByte = 8;
+        double adfTupleBase[3] = { 0.0, 0.0, 0.0 };
 
-        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
+            double adfTuple[3] = { 0.0, 0.0, 0.0 };
+
             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
             {
                 // first and last Points are uncompressed
@@ -1329,6 +1304,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             else
             {
                 // any other intermediate Point is compressed
+                float asfTuple[3] = { 0.0f, 0.0f, 0.0f };
                 memcpy( asfTuple, pabyData + nNextByte, 3*4 );
                 nNextByte += 3 * 4;
 
@@ -1358,17 +1334,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprLineStringXYM )
     {
-        double adfTuple[3];
-        double adfTupleBase[2];
-        float asfTuple[2];
-        GInt32 nPointCount;
-        int    iPoint;
-        OGRLineString *poLS;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nPointCount = 0;
         memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nPointCount );
@@ -1382,15 +1351,16 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < compressedSize )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        poGeom = poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
+        poGeom = poLS;
         poLS->setNumPoints( nPointCount );
 
-        nNextByte = 8;
-        adfTupleBase[0] = 0.0;
-        adfTupleBase[1] = 0.0;
+        int nNextByte = 8;
+        double adfTupleBase[2] = { 0.0, 0.0 };
 
-        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
+            double adfTuple[3] = { 0.0, 0.0, 0.0 };
             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
             {
                 // first and last Points are uncompressed
@@ -1407,6 +1377,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             else
             {
                 // any other intermediate Point is compressed
+                float asfTuple[2] = { 0.0f, 0.0f };
                 memcpy( asfTuple, pabyData + nNextByte, 2*4 );
                 memcpy( adfTuple + 2, pabyData + nNextByte + 2*4, 8 );
                 nNextByte += 2 * 4 + 8;
@@ -1435,17 +1406,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprLineStringXYZM )
     {
-        double adfTuple[4];
-        double adfTupleBase[3];
-        float asfTuple[3];
-        GInt32 nPointCount;
-        int    iPoint;
-        OGRLineString *poLS;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nPointCount = 0;
         memcpy( &nPointCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nPointCount );
@@ -1460,16 +1424,17 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < compressedSize )
             return OGRERR_NOT_ENOUGH_DATA;
 
-        poGeom = poLS = new OGRLineString();
+        OGRLineString *poLS = new OGRLineString();
+        poGeom = poLS;
         poLS->setNumPoints( nPointCount );
 
-        nNextByte = 8;
-        adfTupleBase[0] = 0.0;
-        adfTupleBase[1] = 0.0;
-        adfTupleBase[2] = 0.0;
+        int nNextByte = 8;
+        double adfTupleBase[3] = { 0.0, 0.0, 0.0 };
 
-        for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+        for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
         {
+            double adfTuple[4] = { 0.0, 0.0, 0.0, 0.0 };
+
             if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
             {
                 // first and last Points are uncompressed
@@ -1487,6 +1452,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             else
             {
                 // any other intermediate Point is compressed
+                float asfTuple[3] = { 0.0f, 0.0f, 0.0f };
                 memcpy( asfTuple, pabyData + nNextByte, 3*4 );
                 memcpy( adfTuple + 3, pabyData + nNextByte + 3*4, 8 );
                 nNextByte += 3 * 4 + 8;
@@ -1518,17 +1484,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSplitePolygonXY )
     {
-        double adfTuple[2];
-        GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nRingCount = 0;
         memcpy( &nRingCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nRingCount );
@@ -1540,11 +1499,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 8;
+        int nNextByte = 8;
 
-        poGeom = poPoly = new OGRPolygon();
+        OGRPolygon *poPoly = new OGRPolygon();
+        poGeom = poPoly;
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( int iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
             {
@@ -1552,6 +1512,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
+            GInt32 nPointCount = 0;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
@@ -1570,7 +1531,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            poLR = new OGRLinearRing();
+            OGRLinearRing *poLR = new OGRLinearRing();
             if( !NEED_SWAP_SPATIALITE() )
             {
                 poLR->setPoints( nPointCount, (OGRRawPoint*)(pabyData + nNextByte), NULL );
@@ -1579,8 +1540,9 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             else
             {
                 poLR->setNumPoints( nPointCount, FALSE );
-                for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+                for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
                 {
+                    double adfTuple[2] = { 0.0, 0.0 };
                     memcpy( adfTuple, pabyData + nNextByte, 2*8 );
                     nNextByte += 2 * 8;
                     CPL_SWAP64PTR( adfTuple );
@@ -1601,17 +1563,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSplitePolygonXYZ )
     {
-        double adfTuple[3];
-        GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nRingCount = 0;
         memcpy( &nRingCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nRingCount );
@@ -1623,11 +1578,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 8;
+        int nNextByte = 8;
 
-        poGeom = poPoly = new OGRPolygon();
+        OGRPolygon *poPoly = new OGRPolygon();
+        poGeom = poPoly;
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( int iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
             {
@@ -1635,6 +1591,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
+            GInt32 nPointCount = 0;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
@@ -1653,11 +1610,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            poLR = new OGRLinearRing();
+            OGRLinearRing *poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
 
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                double adfTuple[3] = { 0.0, 0.0, 0.0 };
                 memcpy( adfTuple, pabyData + nNextByte, 3*8 );
                 nNextByte += 3 * 8;
 
@@ -1683,17 +1641,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSplitePolygonXYM )
     {
-        double adfTuple[3];
-        GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nRingCount = 0;
         memcpy( &nRingCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nRingCount );
@@ -1705,11 +1656,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 8;
+        int nNextByte = 8;
 
-        poGeom = poPoly = new OGRPolygon();
+        OGRPolygon *poPoly = new OGRPolygon();
+        poGeom = poPoly;
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( int iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
             {
@@ -1717,6 +1669,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
+            GInt32 nPointCount = 0;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
@@ -1735,11 +1688,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            poLR = new OGRLinearRing();
+            OGRLinearRing *poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
 
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                double adfTuple[3] = { 0.0, 0.0, 0.0 };
                 memcpy( adfTuple, pabyData + nNextByte, 3*8 );
                 nNextByte += 3 * 8;
 
@@ -1765,17 +1719,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSplitePolygonXYZM )
     {
-        double adfTuple[4];
-        GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nRingCount = 0;
         memcpy( &nRingCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nRingCount );
@@ -1787,11 +1734,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 8;
+        int nNextByte = 8;
 
-        poGeom = poPoly = new OGRPolygon();
+        OGRPolygon *poPoly = new OGRPolygon();
+        poGeom = poPoly;
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( int iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
             {
@@ -1799,6 +1747,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
+            GInt32 nPointCount = 0;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
@@ -1817,11 +1766,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            poLR = new OGRLinearRing();
+            OGRLinearRing *poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
 
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                double adfTuple[4] = { 0.0, 0.0, 0.0, 0.0 };
+
                 memcpy( adfTuple, pabyData + nNextByte, 4*8 );
                 nNextByte += 4 * 8;
 
@@ -1848,19 +1799,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprPolygonXY  )
     {
-        double adfTuple[2];
-        double adfTupleBase[2];
-        float asfTuple[2];
-        GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nRingCount = 0;
         memcpy( &nRingCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nRingCount );
@@ -1872,11 +1814,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 8;
+        int nNextByte = 8;
 
-        poGeom = poPoly = new OGRPolygon();
+        OGRPolygon *poPoly = new OGRPolygon();
+        poGeom = poPoly;
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( int iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
             {
@@ -1884,6 +1827,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
+            GInt32 nPointCount = 0;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
@@ -1898,8 +1842,6 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             compressedSize += 8 * (nPointCount - 2);  // intermediate Points
 
             nNextByte += 4;
-            adfTupleBase[0] = 0.0;
-            adfTupleBase[1] = 0.0;
 
             if (nBytes - nNextByte < compressedSize )
             {
@@ -1907,11 +1849,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            poLR = new OGRLinearRing();
+            double adfTupleBase[2] = { 0.0, 0.0 };
+            OGRLinearRing *poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
 
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                double adfTuple[2] = { 0.0, 0.0 };
                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
                 {
                     // first and last Points are uncompressed
@@ -1927,6 +1871,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 else
                 {
                     // any other intermediate Point is compressed
+                    float asfTuple[2]  = { 0.0f, 0.0f };
                     memcpy( asfTuple, pabyData + nNextByte, 2*4 );
                     nNextByte += 2 * 4;
 
@@ -1956,19 +1901,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprPolygonXYZ )
     {
-        double adfTuple[3];
-        double adfTupleBase[3];
-        float asfTuple[3];
-        GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nRingCount = 0;
         memcpy( &nRingCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nRingCount );
@@ -1980,11 +1916,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 8;
+        int nNextByte = 8;
 
-        poGeom = poPoly = new OGRPolygon();
+        OGRPolygon *poPoly = new OGRPolygon();
+        poGeom = poPoly;
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( int iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
             {
@@ -1992,6 +1929,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
+            GInt32 nPointCount = 0;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
@@ -2002,25 +1940,24 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_CORRUPT_DATA;
             }
 
-            compressedSize = 24 * 2;                  	// first and last Points
+            compressedSize = 24 * 2;  // first and last Points
             compressedSize += 12 * (nPointCount - 2);  // intermediate Points
 
             nNextByte += 4;
-            adfTupleBase[0] = 0.0;
-            adfTupleBase[1] = 0.0;
-            adfTupleBase[2] = 0.0;
 
-            if (nBytes - nNextByte < compressedSize )
+            if( nBytes - nNextByte < compressedSize )
             {
                 delete poPoly;
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            poLR = new OGRLinearRing();
+            double adfTupleBase[3] = { 0.0, 0.0, 0.0 };
+            OGRLinearRing *poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
 
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                double adfTuple[3] = { 0.0, 0.0, 0.0 };
                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
                 {
                     // first and last Points are uncompressed
@@ -2037,6 +1974,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 else
                 {
                     // any other intermediate Point is compressed
+                    float asfTuple[3] = { 0.0, 0.0, 0.0 };
                     memcpy( asfTuple, pabyData + nNextByte, 3*4 );
                     nNextByte += 3 * 4;
 
@@ -2069,19 +2007,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprPolygonXYM )
     {
-        double adfTuple[3];
-        double adfTupleBase[2];
-        float asfTuple[2];
-        GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nRingCount = 0;
         memcpy( &nRingCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nRingCount );
@@ -2093,11 +2022,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 8;
+        int nNextByte = 8;
 
-        poGeom = poPoly = new OGRPolygon();
+        OGRPolygon *poPoly = new OGRPolygon();
+        poGeom = poPoly;
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( int iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
             {
@@ -2105,11 +2035,11 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
+            GInt32 nPointCount = 0;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
 
-
             if( nPointCount < 0 || nPointCount - 2 > (INT_MAX - 24 * 2) / 16)
             {
                 delete poPoly;
@@ -2120,8 +2050,6 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             compressedSize += 16 * (nPointCount - 2);  // intermediate Points
 
             nNextByte += 4;
-			adfTupleBase[0] = 0.0;
-			adfTupleBase[1] = 0.0;
 
             if (nBytes - nNextByte < compressedSize )
             {
@@ -2129,11 +2057,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            poLR = new OGRLinearRing();
+            double adfTupleBase[2] = { 0.0, 0.0 };
+            OGRLinearRing *poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
 
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                double adfTuple[3] = { 0.0, 0.0, 0.0 };
                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
                 {
                     // first and last Points are uncompressed
@@ -2150,6 +2080,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 else
                 {
                     // any other intermediate Point is compressed
+                    float asfTuple[2] = { 0.0f, 0.0f };
                     memcpy( asfTuple, pabyData + nNextByte, 2*4 );
                     memcpy( adfTuple + 2, pabyData + nNextByte + 2*4, 8 );
                     nNextByte += 2 * 4 + 8;
@@ -2181,19 +2112,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     else if( nGType == OGRSpliteComprPolygonXYZM )
     {
-        double adfTuple[4];
-        double adfTupleBase[3];
-        float asfTuple[3];
-        GInt32 nPointCount;
-        GInt32 nRingCount;
-        int    iPoint, iRing;
-        OGRLinearRing *poLR;
-        OGRPolygon *poPoly;
-        int    nNextByte;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nRingCount = 0;
         memcpy( &nRingCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nRingCount );
@@ -2205,11 +2127,12 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
         if (nBytes - 8 < nRingCount * 4)
             return OGRERR_NOT_ENOUGH_DATA;
 
-        nNextByte = 8;
+        int nNextByte = 8;
 
-        poGeom = poPoly = new OGRPolygon();
+        OGRPolygon *poPoly = new OGRPolygon();
+        poGeom = poPoly;
 
-        for( iRing = 0; iRing < nRingCount; iRing++ )
+        for( int iRing = 0; iRing < nRingCount; iRing++ )
         {
             if( nBytes - nNextByte < 4 )
             {
@@ -2217,6 +2140,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
+            GInt32 nPointCount = 0;
             memcpy( &nPointCount, pabyData + nNextByte, 4 );
             if (NEED_SWAP_SPATIALITE())
                 CPL_SWAP32PTR( &nPointCount );
@@ -2232,9 +2156,6 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             compressedSize += 20 * (nPointCount - 2);  // intermediate Points
 
             nNextByte += 4;
-            adfTupleBase[0] = 0.0;
-            adfTupleBase[1] = 0.0;
-            adfTupleBase[2] = 0.0;
 
             if (nBytes - nNextByte < compressedSize )
             {
@@ -2242,11 +2163,13 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_NOT_ENOUGH_DATA;
             }
 
-            poLR = new OGRLinearRing();
+            double adfTupleBase[3] = { 0.0, 0.0, 0.0 };
+            OGRLinearRing *poLR = new OGRLinearRing();
             poLR->setNumPoints( nPointCount, FALSE );
 
-            for( iPoint = 0; iPoint < nPointCount; iPoint++ )
+            for( int iPoint = 0; iPoint < nPointCount; iPoint++ )
             {
+                double adfTuple[4] = { 0.0, 0.0, 0.0, 0.0 };
                 if ( iPoint == 0 || iPoint == (nPointCount - 1 ) )
                 {
                     // first and last Points are uncompressed
@@ -2264,6 +2187,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 else
                 {
                     // any other intermediate Point is compressed
+                  float asfTuple[3] = { 0.0f, 0.0f, 0.0f };
                     memcpy( asfTuple, pabyData + nNextByte, 3*4 );
                     memcpy( adfTuple + 3, pabyData + nNextByte + 3*4, 8 );
                     nNextByte += 3 * 4 + 8;
@@ -2313,13 +2237,10 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
              ( nGType >= OGRSpliteComprMultiLineStringXYZM &&
                nGType <= OGRSpliteComprGeometryCollectionXYZM ) ) // XYZM compressed
     {
-        OGRGeometryCollection *poGC = NULL;
-        GInt32 nGeomCount = 0;
-        int iGeom = 0;
-
         if( nBytes < 8 )
             return OGRERR_NOT_ENOUGH_DATA;
 
+        GInt32 nGeomCount = 0;
         memcpy( &nGeomCount, pabyData + 4, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nGeomCount );
@@ -2332,6 +2253,7 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
             return OGRERR_NOT_ENOUGH_DATA;
 
         int nBytesUsed = 8;
+        OGRGeometryCollection *poGC = NULL;
 
         switch ( nGType )
         {
@@ -2375,9 +2297,8 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 
         assert(NULL != poGC);
 
-        for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
+        for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
         {
-            int nThisGeomSize;
             OGRGeometry *poThisGeom = NULL;
 
             if (nBytes - nBytesUsed < 5)
@@ -2392,11 +2313,14 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
                 return OGRERR_CORRUPT_DATA;
             }
 
-            nBytesUsed ++;
+            nBytesUsed++;
 
-            OGRErr eErr = createFromSpatialiteInternal( pabyData + nBytesUsed,
-                                                 &poThisGeom, nBytes - nBytesUsed,
-                                                 eByteOrder, &nThisGeomSize, nRecLevel + 1);
+            int nThisGeomSize = 0;
+            OGRErr eErr =
+                createFromSpatialiteInternal( pabyData + nBytesUsed,
+                                              &poThisGeom, nBytes - nBytesUsed,
+                                              eByteOrder, &nThisGeomSize,
+                                              nRecLevel + 1);
             if( eErr != OGRERR_NONE )
             {
                 delete poGC;
@@ -2430,6 +2354,167 @@ OGRErr OGRSQLiteLayer::createFromSpatialiteInternal(const GByte *pabyData,
 }
 
 /************************************************************************/
+/*                     GetSpatialiteGeometryHeader()                    */
+/************************************************************************/
+typedef struct
+{
+    int                nSpliteType;
+    OGRwkbGeometryType eGType;
+} SpliteOGRGeometryTypeTuple;
+
+static const SpliteOGRGeometryTypeTuple anTypesMap[] = {
+{ OGRSplitePointXY, wkbPoint },
+{ OGRSplitePointXYZ, wkbPoint25D },
+{ OGRSplitePointXYM, wkbPointM },
+{ OGRSplitePointXYZM, wkbPointZM },
+{ OGRSpliteLineStringXY, wkbLineString },
+{ OGRSpliteLineStringXYZ, wkbLineString25D },
+{ OGRSpliteLineStringXYM, wkbLineStringM },
+{ OGRSpliteLineStringXYZM, wkbLineStringZM },
+{ OGRSpliteComprLineStringXY, wkbLineString },
+{ OGRSpliteComprLineStringXYZ, wkbLineString25D },
+{ OGRSpliteComprLineStringXYM, wkbLineStringM },
+{ OGRSpliteComprLineStringXYZM, wkbLineStringZM },
+{ OGRSplitePolygonXY, wkbPolygon },
+{ OGRSplitePolygonXYZ, wkbPolygon25D },
+{ OGRSplitePolygonXYM, wkbPolygonM },
+{ OGRSplitePolygonXYZM, wkbPolygonZM },
+{ OGRSpliteComprPolygonXY, wkbPolygon },
+{ OGRSpliteComprPolygonXYZ, wkbPolygon25D },
+{ OGRSpliteComprPolygonXYM, wkbPolygonM },
+{ OGRSpliteComprPolygonXYZM, wkbPolygonZM },
+
+{ OGRSpliteMultiPointXY, wkbMultiPoint },
+{ OGRSpliteMultiPointXYZ, wkbMultiPoint25D },
+{ OGRSpliteMultiPointXYM, wkbMultiPointM },
+{ OGRSpliteMultiPointXYZM, wkbMultiPointZM },
+{ OGRSpliteMultiLineStringXY, wkbMultiLineString },
+{ OGRSpliteMultiLineStringXYZ, wkbMultiLineString25D },
+{ OGRSpliteMultiLineStringXYM, wkbMultiLineStringM },
+{ OGRSpliteMultiLineStringXYZM, wkbMultiLineStringZM },
+{ OGRSpliteComprMultiLineStringXY, wkbMultiLineString },
+{ OGRSpliteComprMultiLineStringXYZ, wkbMultiLineString25D },
+{ OGRSpliteComprMultiLineStringXYM, wkbMultiLineStringM },
+{ OGRSpliteComprMultiLineStringXYZM, wkbMultiLineStringZM },
+{ OGRSpliteMultiPolygonXY, wkbMultiPolygon },
+{ OGRSpliteMultiPolygonXYZ, wkbMultiPolygon25D },
+{ OGRSpliteMultiPolygonXYM, wkbMultiPolygonM },
+{ OGRSpliteMultiPolygonXYZM, wkbMultiPolygonZM },
+{ OGRSpliteComprMultiPolygonXY, wkbMultiPolygon },
+{ OGRSpliteComprMultiPolygonXYZ, wkbMultiPolygon25D },
+{ OGRSpliteComprMultiPolygonXYM, wkbMultiPolygonM },
+{ OGRSpliteComprMultiPolygonXYZM, wkbMultiPolygonZM },
+
+{ OGRSpliteGeometryCollectionXY, wkbGeometryCollection },
+{ OGRSpliteGeometryCollectionXYZ, wkbGeometryCollection25D },
+{ OGRSpliteGeometryCollectionXYM, wkbGeometryCollectionM },
+{ OGRSpliteGeometryCollectionXYZM, wkbGeometryCollectionZM },
+{ OGRSpliteComprGeometryCollectionXY, wkbGeometryCollection },
+{ OGRSpliteComprGeometryCollectionXYZ, wkbGeometryCollection25D },
+{ OGRSpliteComprGeometryCollectionXYM, wkbGeometryCollectionM },
+{ OGRSpliteComprGeometryCollectionXYZM, wkbGeometryCollectionZM },
+};
+
+OGRErr OGRSQLiteLayer::GetSpatialiteGeometryHeader( const GByte *pabyData,
+                                                    int nBytes,
+                                                    int* pnSRID,
+                                                    OGRwkbGeometryType* peType,
+                                                    bool* pbIsEmpty,
+                                                    double* pdfMinX,
+                                                    double* pdfMinY,
+                                                    double* pdfMaxX,
+                                                    double* pdfMaxY )
+{
+    if( nBytes < 44
+        || pabyData[0] != 0
+        || pabyData[38] != 0x7C
+        || pabyData[nBytes-1] != 0xFE )
+        return OGRERR_CORRUPT_DATA;
+
+    OGRwkbByteOrder eByteOrder = (OGRwkbByteOrder) pabyData[1];
+
+    if( pnSRID != NULL )
+    {
+        int nSRID = 0;
+        memcpy( &nSRID, pabyData + 2, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nSRID );
+        *pnSRID = nSRID;
+    }
+
+    if( peType != NULL || pbIsEmpty != NULL )
+    {
+        OGRwkbGeometryType eGType = wkbUnknown;
+        int nSpliteType = 0;
+        memcpy( &nSpliteType, pabyData + 39, 4 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP32PTR( &nSpliteType );
+        for( size_t i = 0; i < CPL_ARRAYSIZE(anTypesMap); ++i )
+        {
+            if( anTypesMap[i].nSpliteType == nSpliteType )
+            {
+                eGType = anTypesMap[i].eGType;
+                break;
+            }
+        }
+        if( peType != NULL )
+            *peType = eGType;
+        if( pbIsEmpty != NULL )
+        {
+            *pbIsEmpty = false;
+            if ( wkbFlatten(eGType) != wkbPoint &&
+                 nBytes >= 44 + 4 )
+            {
+                int nCount = 0;
+                memcpy( &nSpliteType, pabyData + 43, 4 );
+                if (NEED_SWAP_SPATIALITE())
+                    CPL_SWAP32PTR( &nCount );
+                *pbIsEmpty = (nCount == 0);
+            }
+        }
+    }
+
+    if( pdfMinX != NULL )
+    {
+        double dfMinX = 0.0;
+        memcpy( &dfMinX, pabyData + 6, 8 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP64PTR( &dfMinX );
+        *pdfMinX = dfMinX;
+    }
+
+    if( pdfMinY != NULL )
+    {
+        double dfMinY = 0.0;
+        memcpy( &dfMinY, pabyData + 14, 8 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP64PTR( &dfMinY );
+        *pdfMinY = dfMinY;
+    }
+
+
+    if( pdfMaxX != NULL )
+    {
+        double dfMaxX = 0.0;
+        memcpy( &dfMaxX, pabyData + 22, 8 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP64PTR( &dfMaxX );
+        *pdfMaxX = dfMaxX;
+    }
+
+    if( pdfMaxY != NULL )
+    {
+        double dfMaxY = 0.0;
+        memcpy( &dfMaxY, pabyData + 30, 8 );
+        if (NEED_SWAP_SPATIALITE())
+            CPL_SWAP64PTR( &dfMaxY );
+        *pdfMaxY = dfMaxY;
+    }
+
+    return OGRERR_NONE;
+}
+
+/************************************************************************/
 /*                      ImportSpatiaLiteGeometry()                      */
 /************************************************************************/
 
@@ -2468,7 +2553,7 @@ OGRErr OGRSQLiteLayer::ImportSpatiaLiteGeometry( const GByte *pabyData,
 /* -------------------------------------------------------------------- */
     if( pnSRID != NULL )
     {
-        int nSRID;
+        int nSRID = 0;
         memcpy( &nSRID, pabyData + 2, 4 );
         if (NEED_SWAP_SPATIALITE())
             CPL_SWAP32PTR( &nSRID );
@@ -2576,13 +2661,13 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
         case wkbLinearRing:
         {
             int nPoints = ((OGRLineString*)poGeometry)->getNumPoints();
-            int nDimension;
+            int nDimension = 2;
             int nPointsDouble = nPoints;
             int nPointsFloat = 0;
             bool bHasM = CPL_TO_BOOL(poGeometry->IsMeasured());
             if ( bSpatialite2D == TRUE )
             {
-                nDimension = 2;
+                // nDimension = 2;
                 bHasM = false;
             }
             else
@@ -2594,7 +2679,10 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
                 }
                 nDimension = poGeometry->Is3D() ? 3 : 2;
             }
-            return 4 + nDimension * (8 * nPointsDouble + 4 * nPointsFloat) + ((bHasM) ? nPoints * 8 : 0);
+            return
+                4 +
+                nDimension * (8 * nPointsDouble + 4 * nPointsFloat) +
+                (bHasM ? nPoints * 8 : 0);
         }
 
         case wkbPolygon:
@@ -2630,8 +2718,12 @@ int OGRSQLiteLayer::ComputeSpatiaLiteGeometrySize(const OGRGeometry *poGeometry,
         }
 
         default:
-            CPLError(CE_Failure, CPLE_AppDefined, "Unexpected geometry type");
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Unexpected geometry type: %s",
+                     OGRToOGCGeomType(poGeometry->getGeometryType()));
             return 0;
+        }
     }
 }
 
@@ -2774,7 +2866,6 @@ int OGRSQLiteLayer::GetSpatialiteGeometryCode(const OGRGeometry *poGeometry,
             }
             break;
 
-
         case wkbGeometryCollection:
             if ( bSpatialite2D == TRUE )
                 return OGRSpliteGeometryCollectionXY;
@@ -3042,7 +3133,6 @@ int OGRSQLiteLayer::ExportSpatiaLiteGeometryInternal(const OGRGeometry *poGeomet
     }
 }
 
-
 OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
                                                  GInt32 nSRID,
                                                  OGRwkbByteOrder eByteOrder,
@@ -3053,17 +3143,22 @@ OGRErr OGRSQLiteLayer::ExportSpatiaLiteGeometry( const OGRGeometry *poGeometry,
 
 {
     /* Spatialite does not support curve geometries */
-    const OGRGeometry* poWorkGeom;
-    if( poGeometry->hasCurveGeometry() )
-        poWorkGeom = poGeometry->getLinearGeometry();
-    else
-        poWorkGeom = poGeometry;
+    const OGRGeometry* poWorkGeom = poGeometry->hasCurveGeometry()
+        ? poGeometry->getLinearGeometry()
+        :  poGeometry;
 
     bUseComprGeom = bUseComprGeom && !bSpatialite2D && CanBeCompressedSpatialiteGeometry(poWorkGeom);
 
-    int     nDataLen = 44 + ComputeSpatiaLiteGeometrySize( poWorkGeom,
-                                                           bSpatialite2D,
-                                                           bUseComprGeom );
+    const int nGeomSize = ComputeSpatiaLiteGeometrySize( poWorkGeom,
+                                                         bSpatialite2D,
+                                                         bUseComprGeom );
+    if( nGeomSize == 0 )
+    {
+        *ppabyData = NULL;
+        *pnDataLength = 0;
+        return OGRERR_FAILURE;
+    }
+    const int nDataLen = 44 + nGeomSize;
     OGREnvelope sEnvelope;
 
     *ppabyData =  (GByte *) CPLMalloc( nDataLen );
@@ -3193,7 +3288,9 @@ void OGRSQLiteLayer::ClearStatement()
 {
     if( hStmt != NULL )
     {
+#ifdef DEBUG_VERBOSE
         CPLDebug( "OGR_SQLITE", "finalize %p", hStmt );
+#endif
         sqlite3_finalize( hStmt );
         hStmt = NULL;
     }
@@ -3296,15 +3393,14 @@ CPLString OGRSQLiteLayer::FormatSpatialFilterFromRTree(OGRGeometry* poFilterGeom
         return "";
 
     osSpatialWHERE.Printf("%s IN ( SELECT pkid FROM 'idx_%s_%s' WHERE "
-                    "xmax >= %s AND xmin <= %s AND ymax >= %s AND ymin <= %s)",
+                    "xmax >= %.12f AND xmin <= %.12f AND ymax >= %.12f AND ymin <= %.12f)",
                     pszRowIDName,
                     pszEscapedTable,
                     pszEscapedGeomCol,
-                    // Insure that only Decimal.Points are used, never local settings such as Decimal.Comma.
-                    CPLString().FormatC(sEnvelope.MinX - 1e-11,"%.12f").c_str(),
-                    CPLString().FormatC(sEnvelope.MaxX + 1e-11,"%.12f").c_str(),
-                    CPLString().FormatC(sEnvelope.MinY - 1e-11,"%.12f").c_str(),
-                    CPLString().FormatC(sEnvelope.MaxY + 1e-11,"%.12f").c_str());
+                    sEnvelope.MinX - 1e-11,
+                    sEnvelope.MaxX + 1e-11,
+                    sEnvelope.MinY - 1e-11,
+                    sEnvelope.MaxY + 1e-11);
 
     return osSpatialWHERE;
 }
@@ -3328,13 +3424,13 @@ CPLString OGRSQLiteLayer::FormatSpatialFilterFromMBR(OGRGeometry* poFilterGeom,
         return "";
 
     /* A bit inefficient but still faster than OGR filtering */
-    osSpatialWHERE.Printf("MBRIntersects(\"%s\", BuildMBR(%s, %s, %s, %s))",
+    osSpatialWHERE.Printf("MBRIntersects(\"%s\", BuildMBR(%.12f, %.12f, %.12f, %.12f))",
                     pszEscapedGeomColName,
                     // Insure that only Decimal.Points are used, never local settings such as Decimal.Comma.
-                    CPLString().FormatC(sEnvelope.MinX - 1e-11,"%.12f").c_str(),
-                    CPLString().FormatC(sEnvelope.MinY - 1e-11,"%.12f").c_str(),
-                    CPLString().FormatC(sEnvelope.MaxX + 1e-11,"%.12f").c_str(),
-                    CPLString().FormatC(sEnvelope.MaxY + 1e-11,"%.12f").c_str());
+                    sEnvelope.MinX - 1e-11,
+                    sEnvelope.MinY - 1e-11,
+                    sEnvelope.MaxX + 1e-11,
+                    sEnvelope.MaxY + 1e-11);
 
     return osSpatialWHERE;
 }
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp
index 76632ff..3d2af28 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteregexp.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqliteregexp.cpp 32982 2016-01-14 16:53:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite REGEXP function
@@ -46,7 +45,6 @@
  * commercial or non-commercial, and by any means.
  */
 
-
 #include "ogrsqliteregexp.h"
 
 #ifdef HAVE_PCRE
@@ -59,24 +57,19 @@ typedef struct {
     pcre_extra *e;
 } cache_entry;
 
-#ifndef CACHE_SIZE
-#define CACHE_SIZE 16
-#endif
+static const int CACHE_SIZE = 16;
 
 /************************************************************************/
 /*                         OGRSQLiteREGEXPFunction()                    */
 /************************************************************************/
 
 static
-void OGRSQLiteREGEXPFunction(sqlite3_context *ctx, CPL_UNUSED int argc, sqlite3_value **argv)
+void OGRSQLiteREGEXPFunction( sqlite3_context *ctx,
+                              CPL_UNUSED int argc, sqlite3_value **argv )
 {
-    const char *re, *str;
-    pcre *p;
-    pcre_extra *e;
-
     CPLAssert(argc == 2);
 
-    re = (const char *) sqlite3_value_text(argv[0]);
+    const char *re = (const char *) sqlite3_value_text(argv[0]);
     if (!re) {
         sqlite3_result_error(ctx, "no regexp", -1);
         return;
@@ -88,30 +81,29 @@ void OGRSQLiteREGEXPFunction(sqlite3_context *ctx, CPL_UNUSED int argc, sqlite3_
         return;
     }
 
-    str = (const char *) sqlite3_value_text(argv[1]);
+    const char *str = (const char *) sqlite3_value_text(argv[1]);
     if (!str) {
         sqlite3_result_error(ctx, "no string", -1);
         return;
     }
 
     /* simple LRU cache */
-    int i;
-    int found = 0;
     cache_entry *cache = (cache_entry*) sqlite3_user_data(ctx);
-
     CPLAssert(cache);
 
-    for (i = 0; i < CACHE_SIZE && cache[i].s; i++)
+    bool found = false;
+    int i = 0;  // Used after for.
+    for( ; i < CACHE_SIZE && cache[i].s; i++ )
     {
         if (strcmp(re, cache[i].s) == 0) {
-            found = 1;
+            found = true;
             break;
         }
     }
 
-    if (found)
+    if( found )
     {
-        if (i > 0)
+        if( i > 0 )
         {
             cache_entry c = cache[i];
             memmove(cache + 1, cache, i * sizeof(cache_entry));
@@ -121,8 +113,8 @@ void OGRSQLiteREGEXPFunction(sqlite3_context *ctx, CPL_UNUSED int argc, sqlite3_
     else
     {
         cache_entry c;
-        const char *err;
-        int pos;
+        const char *err = NULL;
+        int pos = 0;
         c.p = pcre_compile(re, 0, &err, &pos, NULL);
         if (!c.p)
         {
@@ -151,12 +143,11 @@ void OGRSQLiteREGEXPFunction(sqlite3_context *ctx, CPL_UNUSED int argc, sqlite3_
         memmove(cache + 1, cache, i * sizeof(cache_entry));
         cache[0] = c;
     }
-    p = cache[0].p;
-    e = cache[0].e;
-
-    int rc;
+    pcre *p = cache[0].p;
     CPLAssert(p);
-    rc = pcre_exec(p, e, str, static_cast<int>(strlen(str)), 0, 0, NULL, 0);
+    pcre_extra *e = cache[0].e;
+
+    int rc = pcre_exec(p, e, str, static_cast<int>(strlen(str)), 0, 0, NULL, 0);
     sqlite3_result_int(ctx, rc >= 0);
 }
 
@@ -216,8 +207,7 @@ void OGRSQLiteFreeRegExpCache(void*
         return;
 
     cache_entry *cache = (cache_entry*) hRegExpCache;
-    int i;
-    for (i = 0; i < CACHE_SIZE && cache[i].s; i++)
+    for( int i = 0; i < CACHE_SIZE && cache[i].s; i++ )
     {
         CPLFree(cache[i].s);
         CPLAssert(cache[i].p);
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
index a1ce301..8cf673e 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteselectlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqliteselectlayer.cpp 35899 2016-10-24 11:56:25Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteSelectLayer class, layer access to the results
@@ -34,22 +33,25 @@
 #include "swq.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrsqliteselectlayer.cpp 35899 2016-10-24 11:56:25Z rouault $");
+CPL_CVSID("$Id: ogrsqliteselectlayer.cpp 37534 2017-03-01 16:50:58Z rouault $");
 
 /************************************************************************/
 /*                   OGRSQLiteSelectLayerCommonBehaviour()              */
 /************************************************************************/
 
-OGRSQLiteSelectLayerCommonBehaviour::OGRSQLiteSelectLayerCommonBehaviour(OGRSQLiteBaseDataSource* poDSIn,
-                                            IOGRSQLiteSelectLayer* poLayerIn,
-                                            CPLString osSQLIn,
-                                            int bEmptyLayerIn) :
-            poDS(poDSIn), poLayer(poLayerIn), osSQLBase(osSQLIn),
-            bEmptyLayer(bEmptyLayerIn), osSQLCurrent(osSQLIn)
-{
-    bAllowResetReadingEvenIfIndexAtZero = FALSE;
-    bSpatialFilterInSQL = TRUE;
-}
+OGRSQLiteSelectLayerCommonBehaviour::OGRSQLiteSelectLayerCommonBehaviour(
+    OGRSQLiteBaseDataSource* poDSIn,
+    IOGRSQLiteSelectLayer* poLayerIn,
+    CPLString osSQLIn,
+    int bEmptyLayerIn) :
+    poDS(poDSIn),
+    poLayer(poLayerIn),
+    osSQLBase(osSQLIn),
+    bEmptyLayer(bEmptyLayerIn),
+    bAllowResetReadingEvenIfIndexAtZero(FALSE),
+    bSpatialFilterInSQL(TRUE),
+    osSQLCurrent(osSQLIn)
+{}
 
 /************************************************************************/
 /*                        OGRSQLiteSelectLayer()                        */
@@ -61,12 +63,13 @@ OGRSQLiteSelectLayer::OGRSQLiteSelectLayer( OGRSQLiteDataSource *poDSIn,
                                             int bUseStatementForGetNextFeature,
                                             int bEmptyLayer,
                                             int bAllowMultipleGeomFieldsIn )
-
 {
-    poBehaviour = new OGRSQLiteSelectLayerCommonBehaviour(poDSIn, this, osSQLIn, bEmptyLayer);
     poDS = poDSIn;
+    // Cannot be moved to initializer list because of use of this, which MSVC 2008 doesn't like
+    poBehaviour = new OGRSQLiteSelectLayerCommonBehaviour(poDSIn, this, osSQLIn,
+                                                          bEmptyLayer);
 
-    this->bAllowMultipleGeomFields = bAllowMultipleGeomFieldsIn;
+    bAllowMultipleGeomFields = bAllowMultipleGeomFieldsIn;
 
     std::set<CPLString> aosEmpty;
     BuildFeatureDefn( "SELECT", hStmtIn, NULL, aosEmpty );
@@ -87,9 +90,8 @@ OGRSQLiteSelectLayer::OGRSQLiteSelectLayer( OGRSQLiteDataSource *poDSIn,
             if( wkbFlatten(poGeomFieldDefn->GetType()) != wkbUnknown )
                 continue;
 
-            int nBytes;
             if( sqlite3_column_type( hStmt, poGeomFieldDefn->iCol ) == SQLITE_BLOB &&
-                (nBytes = sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol )) > 39 )
+                sqlite3_column_bytes( hStmt, poGeomFieldDefn->iCol ) > 39 )
             {
                 const GByte* pabyBlob = (const GByte*)sqlite3_column_blob( hStmt, poGeomFieldDefn->iCol );
                 int eByteOrder = pabyBlob[1];
@@ -97,7 +99,7 @@ OGRSQLiteSelectLayer::OGRSQLiteSelectLayer( OGRSQLiteDataSource *poDSIn,
                     (eByteOrder == wkbNDR || eByteOrder == wkbXDR) &&
                     pabyBlob[38] == 0x7C )
                 {
-                    int nSRSId;
+                    int nSRSId = 0;
                     memcpy(&nSRSId, pabyBlob + 2, 4);
 #ifdef CPL_LSB
                     if( eByteOrder != wkbNDR)
@@ -286,8 +288,9 @@ GIntBig OGRSQLiteSelectLayerCommonBehaviour::GetFeatureCount( int bForce )
 /*      Execute.                                                        */
 /* -------------------------------------------------------------------- */
     char *pszErrMsg = NULL;
-    char **papszResult;
-    int nRowCount, nColCount;
+    char **papszResult = NULL;
+    int nRowCount = 0;
+    int nColCount = 0;
     int nResult = -1;
 
     if( sqlite3_get_table( poDS->GetDB(), osFeatureCountSQL, &papszResult,
@@ -315,33 +318,28 @@ GIntBig OGRSQLiteSelectLayerCommonBehaviour::GetFeatureCount( int bForce )
 OGRErr OGRSQLiteSelectLayer::ResetStatement()
 
 {
-    int rc;
-
     ClearStatement();
 
     iNextShapeId = 0;
     bDoStep = TRUE;
 
 #ifdef DEBUG
-    CPLDebug( "OGR_SQLITE", "prepare(%s)", poBehaviour->osSQLCurrent.c_str() );
+    CPLDebug( "OGR_SQLITE", "prepare_v2(%s)", poBehaviour->osSQLCurrent.c_str() );
 #endif
 
-    rc = sqlite3_prepare( poDS->GetDB(), poBehaviour->osSQLCurrent,
-                          static_cast<int>(poBehaviour->osSQLCurrent.size()),
-                          &hStmt, NULL );
+    const int rc =
+        sqlite3_prepare_v2( poDS->GetDB(), poBehaviour->osSQLCurrent,
+                         static_cast<int>(poBehaviour->osSQLCurrent.size()),
+                         &hStmt, NULL );
 
     if( rc == SQLITE_OK )
-    {
         return OGRERR_NONE;
-    }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s",
-                  poBehaviour->osSQLCurrent.c_str(), sqlite3_errmsg(poDS->GetDB()) );
-        hStmt = NULL;
-        return OGRERR_FAILURE;
-    }
+
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "In ResetStatement(): sqlite3_prepare_v2(%s):\n  %s",
+              poBehaviour->osSQLCurrent.c_str(), sqlite3_errmsg(poDS->GetDB()) );
+    hStmt = NULL;
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -506,7 +504,7 @@ int OGRSQLiteSelectLayerCommonBehaviour::BuildSQL()
         else
         {
             osSpatialWhere = oPair.second->GetSpatialWhere(nIdx, poLayer->GetFilterGeom());
-            if (osSpatialWhere.size() == 0)
+            if (osSpatialWhere.empty())
             {
                 CPLDebug("SQLITE", "Cannot get spatial where clause");
                 bSpatialFilterInSQL = FALSE;
@@ -515,21 +513,21 @@ int OGRSQLiteSelectLayerCommonBehaviour::BuildSQL()
     }
 
     CPLString osCustomWhere;
-    if( osSpatialWhere.size() != 0 )
+    if( !osSpatialWhere.empty() )
     {
         osCustomWhere = osSpatialWhere;
     }
     if( poLayer->GetAttrQueryString() != NULL && poLayer->GetAttrQueryString()[0] != '\0' )
     {
-        if( osSpatialWhere.size() != 0)
+        if( !osSpatialWhere.empty())
             osCustomWhere += " AND (";
         osCustomWhere += poLayer->GetAttrQueryString();
-        if( osSpatialWhere.size() != 0)
+        if( !osSpatialWhere.empty())
             osCustomWhere += ")";
     }
 
     /* Nothing to do */
-    if( osCustomWhere.size() == 0 )
+    if( osCustomWhere.empty() )
         return TRUE;
 
     while (i < osSQLBase.size() && osSQLBase[i] == ' ')
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp
index 71873ae..4d1c5f7 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitesinglefeaturelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqlitesinglefeaturelayer.cpp 32011 2015-12-06 10:19:18Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteSingleFeatureLayer class.
@@ -31,25 +30,24 @@
 #include "cpl_string.h"
 #include "ogr_sqlite.h"
 
-CPL_CVSID("$Id: ogrsqlitesinglefeaturelayer.cpp 32011 2015-12-06 10:19:18Z rouault $");
+CPL_CVSID("$Id: ogrsqlitesinglefeaturelayer.cpp 35201 2016-08-25 13:48:52Z goatbar $");
 
 /************************************************************************/
 /*                    OGRSQLiteSingleFeatureLayer()                     */
 /************************************************************************/
 
 OGRSQLiteSingleFeatureLayer::OGRSQLiteSingleFeatureLayer(
-                                                     const char* pszLayerName,
-                                                     int nValIn )
+    const char* pszLayerName,
+    int nValIn ) :
+    nVal(nValIn),
+    pszVal(NULL),
+    poFeatureDefn(new OGRFeatureDefn( "SELECT" )),
+    iNextShapeId(0)
 {
-    poFeatureDefn = new OGRFeatureDefn( "SELECT" );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     OGRFieldDefn oField( pszLayerName, OFTInteger );
     poFeatureDefn->AddFieldDefn( &oField );
-
-    iNextShapeId = 0;
-    this->nVal = nValIn;
-    pszVal = NULL;
 }
 
 /************************************************************************/
@@ -57,17 +55,16 @@ OGRSQLiteSingleFeatureLayer::OGRSQLiteSingleFeatureLayer(
 /************************************************************************/
 
 OGRSQLiteSingleFeatureLayer::OGRSQLiteSingleFeatureLayer(
-                                                     const char* pszLayerName,
-                                                     const char *pszValIn )
+    const char* pszLayerName,
+    const char *pszValIn ) :
+    nVal(0),
+    pszVal(CPLStrdup(pszValIn)),
+    poFeatureDefn(new OGRFeatureDefn( "SELECT" )),
+    iNextShapeId(0)
 {
-    poFeatureDefn = new OGRFeatureDefn( "SELECT" );
     poFeatureDefn->Reference();
     OGRFieldDefn oField( pszLayerName, OFTString );
     poFeatureDefn->AddFieldDefn( &oField );
-
-    iNextShapeId = 0;
-    nVal = 0;
-    this->pszVal = CPLStrdup(pszValIn);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp
index 241ffa6..eacc331 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitesqlfunctions.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqlitesqlfunctions.cpp 33714 2016-03-13 05:42:13Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Extension SQL functions
@@ -39,6 +38,8 @@
 #include "ogrsqliteregexp.cpp" /* yes the .cpp file, to make it work on Windows with load_extension('gdalXX.dll') */
 #include "swq.h"
 
+CPL_CVSID("$Id: ogrsqlitesqlfunctions.cpp 37810 2017-03-20 16:23:30Z rouault $");
+
 #ifndef HAVE_SPATIALITE
 #define MINIMAL_SPATIAL_FUNCTIONS
 #endif
@@ -55,7 +56,7 @@ class OGRSQLiteExtensionData
     OGRGeocodingSessionH hGeocodingSession;
 
   public:
-                                 OGRSQLiteExtensionData(sqlite3* hDB);
+    explicit                     OGRSQLiteExtensionData(sqlite3* hDB);
                                 ~OGRSQLiteExtensionData();
 
     OGRCoordinateTransformation* GetTransform(int nSrcSRSId, int nDstSRSId);
@@ -71,12 +72,12 @@ class OGRSQLiteExtensionData
 /************************************************************************/
 
 OGRSQLiteExtensionData::OGRSQLiteExtensionData(CPL_UNUSED sqlite3* hDB) :
-        hRegExpCache(NULL), hGeocodingSession(NULL)
-{
 #ifdef DEBUG
-    pDummy = CPLMalloc(1);
+    pDummy(CPLMalloc(1)),
 #endif
-}
+    hRegExpCache(NULL),
+    hGeocodingSession(NULL)
+{}
 
 /************************************************************************/
 /*                       ~OGRSQLiteExtensionData()                      */
@@ -234,7 +235,7 @@ void OGR2SQLITE_ogr_deflate(sqlite3_context* pContext,
     }
 
     size_t nOutBytes = 0;
-    void* pOut;
+    void* pOut = NULL;
     if( sqlite3_value_type (argv[0]) == SQLITE_TEXT )
     {
         const char* pszVal = (const char*)sqlite3_value_text(argv[0]);
@@ -274,11 +275,10 @@ void OGR2SQLITE_ogr_inflate(sqlite3_context* pContext,
     }
 
     size_t nOutBytes = 0;
-    void* pOut;
 
     const void* pSrc = sqlite3_value_blob (argv[0]);
     int nLen = sqlite3_value_bytes (argv[0]);
-    pOut = CPLZLibInflate( pSrc, nLen, NULL, 0, &nOutBytes);
+    void* pOut = CPLZLibInflate( pSrc, nLen, NULL, 0, &nOutBytes);
 
     if( pOut != NULL )
     {
@@ -329,7 +329,7 @@ void OGR2SQLITE_ogr_geocode_set_result(sqlite3_context* pContext,
             }
         }
         else if( (nIdx = poFDefn->GetFieldIndex(pszField)) >= 0 &&
-                 poFeature->IsFieldSet(nIdx) )
+                 poFeature->IsFieldSetAndNotNull(nIdx) )
         {
             OGRFieldType eType = poFDefn->GetFieldDefn(nIdx)->GetType();
             if( eType == OFTInteger )
@@ -377,9 +377,8 @@ void OGR2SQLITE_ogr_geocode(sqlite3_context* pContext,
         osField = (const char*)sqlite3_value_text(argv[1]);
     }
 
-    int i;
     char** papszOptions = NULL;
-    for(i = 2; i < argc; i++)
+    for( int i = 2; i < argc; i++ )
     {
         if( sqlite3_value_type (argv[i]) == SQLITE_TEXT )
         {
@@ -477,9 +476,11 @@ void OGR2SQLITE_ogr_geocode_reverse(sqlite3_context* pContext,
     OGRSQLiteExtensionData* poModule =
                     (OGRSQLiteExtensionData*) sqlite3_user_data(pContext);
 
-    double dfLon = 0.0, dfLat = 0.0;
+    double dfLon = 0.0;
+    double dfLat = 0.0;
     int iAfterGeomIdx = 0;
-    int bGotLon = FALSE, bGotLat = FALSE;
+    int bGotLon = FALSE;
+    int bGotLat = FALSE;
 
     if( argc >= 2 )
     {
@@ -520,9 +521,8 @@ void OGR2SQLITE_ogr_geocode_reverse(sqlite3_context* pContext,
 
     const char* pszField = (const char*)sqlite3_value_text(argv[iAfterGeomIdx]);
 
-    int i;
     char** papszOptions = NULL;
-    for(i = iAfterGeomIdx + 1; i < argc; i++)
+    for( int i = iAfterGeomIdx + 1; i < argc; i++ )
     {
         if( sqlite3_value_type (argv[i]) == SQLITE_TEXT )
         {
@@ -603,37 +603,29 @@ void OGR2SQLITE_ogr_datasource_load_layers(sqlite3_context* pContext,
         return;
     }
 
-    CPLString osEscapedDataSource = OGRSQLiteEscape(pszDataSource);
+    CPLString osEscapedDataSource = SQLEscapeLiteral(pszDataSource);
     for(int i=0;i<poDS->GetLayerCount();i++)
     {
         const char* pszLayerName = poDS->GetLayer(i)->GetName();
-        CPLString osEscapedLayerName = OGRSQLiteEscape(pszLayerName);
+        CPLString osEscapedLayerName = SQLEscapeLiteral(pszLayerName);
         CPLString osTableName;
         if( pszPrefix != NULL )
         {
             osTableName = pszPrefix;
             osTableName += "_";
-            osTableName += OGRSQLiteEscapeName(pszLayerName);
+            osTableName += SQLEscapeName(pszLayerName);
         }
         else
         {
-            osTableName = OGRSQLiteEscapeName(pszLayerName);
+            osTableName = SQLEscapeName(pszLayerName);
         }
 
-        char* pszErrMsg = NULL;
-        if( sqlite3_exec(hDB, CPLSPrintf(
+        SQLCommand(hDB, CPLSPrintf(
             "CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR('%s', %d, '%s')",
                 osTableName.c_str(),
                 osEscapedDataSource.c_str(),
                 bUpdate,
-                osEscapedLayerName.c_str()),
-            NULL, NULL, &pszErrMsg) != SQLITE_OK )
-        {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Cannot create table \"%s\" : %s",
-                     osTableName.c_str(), pszErrMsg);
-            sqlite3_free(pszErrMsg);
-        }
+                osEscapedLayerName.c_str()));
     }
 
     poDS->Release();
@@ -997,7 +989,7 @@ void OGR2SQLITE_ST_Buffer(sqlite3_context* pContext,
 {
     int nSRSId = -1;
     OGRGeometry* poGeom = OGR2SQLITE_GetGeom(pContext, argc, argv, &nSRSId);
-    int bGotVal;
+    int bGotVal = FALSE;
     double dfDist = OGR2SQLITE_GetValAsDouble(argv[1], &bGotVal);
     if( poGeom != NULL && bGotVal )
         OGR2SQLITE_SetGeom_AndDestroy(pContext, poGeom->Buffer(dfDist), nSRSId);
@@ -1014,9 +1006,9 @@ static
 void OGR2SQLITE_ST_MakePoint(sqlite3_context* pContext,
                              int argc, sqlite3_value** argv)
 {
-    double dfX, dfY = 0.0;
-    int bGotVal;
-    dfX = OGR2SQLITE_GetValAsDouble(argv[0], &bGotVal);
+    double dfY = 0.0;
+    int bGotVal = FALSE;
+    const double dfX = OGR2SQLITE_GetValAsDouble(argv[0], &bGotVal);
     if( bGotVal )
         dfY = OGR2SQLITE_GetValAsDouble(argv[1], &bGotVal);
     if( !bGotVal )
@@ -1025,7 +1017,7 @@ void OGR2SQLITE_ST_MakePoint(sqlite3_context* pContext,
         return;
     }
 
-    OGRPoint* poPoint;
+    OGRPoint* poPoint = NULL;
     if( argc == 3 )
     {
         double dfZ = OGR2SQLITE_GetValAsDouble(argv[2], &bGotVal);
@@ -1038,14 +1030,15 @@ void OGR2SQLITE_ST_MakePoint(sqlite3_context* pContext,
         poPoint = new OGRPoint(dfX, dfY, dfZ);
     }
     else
+    {
         poPoint = new OGRPoint(dfX, dfY);
+    }
 
     OGR2SQLITE_SetGeom_AndDestroy(pContext, poPoint, -1);
 }
 
 #endif // #ifdef MINIMAL_SPATIAL_FUNCTIONS
 
-
 /************************************************************************/
 /*                     OGRSQLITE_hstore_get_value()                     */
 /************************************************************************/
@@ -1075,55 +1068,73 @@ void OGRSQLITE_hstore_get_value(sqlite3_context* pContext,
 /*                   OGRSQLiteRegisterSQLFunctions()                    */
 /************************************************************************/
 
+#ifndef SQLITE_DETERMINISTIC
+#define SQLITE_DETERMINISTIC 0
+#endif
+
 static
 void* OGRSQLiteRegisterSQLFunctions(sqlite3* hDB)
 {
     OGRSQLiteExtensionData* pData = new OGRSQLiteExtensionData(hDB);
 
-    sqlite3_create_function(hDB, "ogr_version", 0, SQLITE_ANY, NULL,
-                           OGR2SQLITE_ogr_version, NULL, NULL);
+    sqlite3_create_function(hDB, "ogr_version", 0,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
+                            OGR2SQLITE_ogr_version, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_version", 1, SQLITE_ANY, NULL,
-                           OGR2SQLITE_ogr_version, NULL, NULL);
+    sqlite3_create_function(hDB, "ogr_version", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
+                            OGR2SQLITE_ogr_version, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_deflate", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ogr_deflate", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGR2SQLITE_ogr_deflate, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_deflate", 2, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ogr_deflate", 2,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGR2SQLITE_ogr_deflate, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_inflate", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ogr_inflate", 1,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGR2SQLITE_ogr_inflate, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_geocode", -1, SQLITE_ANY, pData,
+    sqlite3_create_function(hDB, "ogr_geocode", -1,
+                            SQLITE_UTF8, pData,
                             OGR2SQLITE_ogr_geocode, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_geocode_reverse", -1, SQLITE_ANY, pData,
+    sqlite3_create_function(hDB, "ogr_geocode_reverse", -1,
+                            SQLITE_UTF8, pData,
                             OGR2SQLITE_ogr_geocode_reverse, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_datasource_load_layers", 1, SQLITE_ANY, hDB,
+    sqlite3_create_function(hDB, "ogr_datasource_load_layers", 1,
+                            SQLITE_UTF8, hDB,
                             OGR2SQLITE_ogr_datasource_load_layers, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_datasource_load_layers", 2, SQLITE_ANY, hDB,
+    sqlite3_create_function(hDB, "ogr_datasource_load_layers", 2,
+                            SQLITE_UTF8, hDB,
                             OGR2SQLITE_ogr_datasource_load_layers, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_datasource_load_layers", 3, SQLITE_ANY, hDB,
+    sqlite3_create_function(hDB, "ogr_datasource_load_layers", 3,
+                            SQLITE_UTF8, hDB,
                             OGR2SQLITE_ogr_datasource_load_layers, NULL, NULL);
 
 #if notdef
-    sqlite3_create_function(hDB, "ogr_GetConfigOption", 1, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ogr_GetConfigOption", 1,
+                            SQLITE_UTF8, NULL,
                             OGR2SQLITE_ogr_GetConfigOption, NULL, NULL);
 
-    sqlite3_create_function(hDB, "ogr_SetConfigOption", 2, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "ogr_SetConfigOption", 2,
+                            SQLITE_UTF8, NULL,
                             OGR2SQLITE_ogr_SetConfigOption, NULL, NULL);
 #endif
 
     // Custom and undocumented function, not sure I'll keep it.
-    sqlite3_create_function(hDB, "Transform3", 3, SQLITE_ANY, pData,
+    sqlite3_create_function(hDB, "Transform3", 3,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, pData,
                             OGR2SQLITE_Transform, NULL, NULL);
 
     // HSTORE functions
-    sqlite3_create_function(hDB, "hstore_get_value", 2, SQLITE_ANY, NULL,
+    sqlite3_create_function(hDB, "hstore_get_value", 2,
+                            SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL,
                             OGRSQLITE_hstore_get_value, NULL, NULL);
 
 #ifdef MINIMAL_SPATIAL_FUNCTIONS
@@ -1140,9 +1151,11 @@ void* OGRSQLiteRegisterSQLFunctions(sqlite3* hDB)
                  "Spatialite not available. Implementing a few functions");
 
 #define REGISTER_ST_op(argc, op) \
-        sqlite3_create_function(hDB, #op, argc, SQLITE_ANY, NULL, \
+        sqlite3_create_function(hDB, #op, argc, \
+                                SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL, \
                                 OGR2SQLITE_ST_##op, NULL, NULL); \
-        sqlite3_create_function(hDB, "ST_" #op, argc, SQLITE_ANY, NULL, \
+        sqlite3_create_function(hDB, "ST_" #op, argc, \
+                                SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL, \
                                 OGR2SQLITE_ST_##op, NULL, NULL);
 
         REGISTER_ST_op(1, AsText);
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
index a665b88..159d9bc 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitetablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqlitetablelayer.cpp 35908 2016-10-24 12:31:58Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteTableLayer class, access to an existing table.
@@ -33,50 +32,41 @@
 #include "ogr_sqlite.h"
 #include "ogr_p.h"
 #include "cpl_time.h"
+#include "ogrsqliteutility.h"
 #include <string>
 
-#define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
+static const char UNSUPPORTED_OP_READ_ONLY[] =
+  "%s : unsupported operation on a read-only datasource.";
 
-CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 35908 2016-10-24 12:31:58Z rouault $");
+CPL_CVSID("$Id: ogrsqlitetablelayer.cpp 37810 2017-03-20 16:23:30Z rouault $");
 
 /************************************************************************/
 /*                        OGRSQLiteTableLayer()                         */
 /************************************************************************/
 
-OGRSQLiteTableLayer::OGRSQLiteTableLayer( OGRSQLiteDataSource *poDSIn )
-
+OGRSQLiteTableLayer::OGRSQLiteTableLayer( OGRSQLiteDataSource *poDSIn ) :
+    bLaunderColumnNames(TRUE),
+    // SpatiaLite v.2.4.0 (or any subsequent) is required
+    // to support 2.5D: if an obsolete version of the library
+    // is found we'll unconditionally activate 2D casting mode.
+    bSpatialite2D(poDSIn->GetSpatialiteVersionNumber() < 24),
+    bDeferredSpatialIndexCreation(FALSE),
+    pszTableName(NULL),
+    pszEscapedTableName(NULL),
+    bLayerDefnError(FALSE),
+    hInsertStmt(NULL),
+    bHasCheckedTriggers(!CPLTestBool(
+        CPLGetConfigOption("OGR_SQLITE_DISABLE_INSERT_TRIGGERS", "YES"))),
+    m_bHasTriedDetectingFID64(false),
+    bStatisticsNeedsToBeFlushed(FALSE),
+    nFeatureCount(-1),
+    bDeferredCreation(FALSE),
+    pszCreationGeomFormat(NULL),
+    iFIDAsRegularColumnIndex(-1)
 {
     poDS = poDSIn;
-
-    bLaunderColumnNames = TRUE;
-
-    /* SpatiaLite v.2.4.0 (or any subsequent) is required
-       to support 2.5D: if an obsolete version of the library
-       is found we'll unconditionally activate 2D casting mode.
-    */
-    bSpatialite2D = poDS->GetSpatialiteVersionNumber() < 24;
-
     iNextShapeId = 0;
-
     poFeatureDefn = NULL;
-    pszTableName = NULL;
-    pszEscapedTableName = NULL;
-
-    bDeferredSpatialIndexCreation = FALSE;
-
-    hInsertStmt = NULL;
-
-    bLayerDefnError = FALSE;
-
-    bStatisticsNeedsToBeFlushed = FALSE;
-    nFeatureCount = -1;
-
-    int bDisableInsertTriggers = CPLTestBool(CPLGetConfigOption(
-                            "OGR_SQLITE_DISABLE_INSERT_TRIGGERS", "YES"));
-    bHasCheckedTriggers = !bDisableInsertTriggers;
-    bDeferredCreation = FALSE;
-    pszCreationGeomFormat = NULL;
-    iFIDAsRegularColumnIndex = -1;
 }
 
 /************************************************************************/
@@ -89,31 +79,26 @@ OGRSQLiteTableLayer::~OGRSQLiteTableLayer()
     ClearStatement();
     ClearInsertStmt();
 
-    int nGeomFieldCount = (poFeatureDefn) ? poFeatureDefn->GetGeomFieldCount() : 0;
-    for(int i=0;i<nGeomFieldCount; i++)
+    const int nGeomFieldCount =
+        poFeatureDefn ? poFeatureDefn->GetGeomFieldCount() : 0;
+    for( int i = 0; i < nGeomFieldCount; i++ )
     {
-        OGRSQLiteGeomFieldDefn* poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(i);
-        // Restore temporarily disabled triggers
-        for(int j = 0; j < (int)poGeomFieldDefn->aosDisabledTriggers.size(); j++ )
+        OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
+            poFeatureDefn->myGetGeomFieldDefn(i);
+        // Restore temporarily disabled triggers.
+        for( int j = 0;
+             j < static_cast<int>(poGeomFieldDefn->aosDisabledTriggers.size());
+             j++ )
         {
             CPLDebug("SQLite", "Restoring trigger %s",
                      poGeomFieldDefn->aosDisabledTriggers[j].first.c_str());
             // This may fail since CreateSpatialIndex() reinstalls triggers, so
-            // don't check result
-            CPL_IGNORE_RET_VAL(sqlite3_exec( poDS->GetDB(),
-                          poGeomFieldDefn->aosDisabledTriggers[j].second.c_str(),
-                          NULL, NULL, NULL ));
-        }
-
-        // Update geometry_columns_time
-        if( poGeomFieldDefn->aosDisabledTriggers.size() != 0 )
-        {
-            char* pszSQL3 = sqlite3_mprintf(
-                "UPDATE geometry_columns_time SET last_insert = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now') "
-                "WHERE Lower(f_table_name) = Lower('%q') AND Lower(f_geometry_column) = Lower('%q')",
-                pszTableName, poGeomFieldDefn->GetNameRef());
-            CPL_IGNORE_RET_VAL(sqlite3_exec( poDS->GetDB(), pszSQL3, NULL, NULL, NULL ));
-            sqlite3_free( pszSQL3 );
+            // don't check result.
+            CPL_IGNORE_RET_VAL(
+                sqlite3_exec(
+                    poDS->GetDB(),
+                    poGeomFieldDefn->aosDisabledTriggers[j].second.c_str(),
+                    NULL, NULL, NULL ));
         }
     }
 
@@ -160,10 +145,10 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableNameIn,
 {
     SetDescription( pszTableNameIn );
 
-    this->bIsVirtualShape = bIsVirtualShapeIn;
-    this->pszTableName = CPLStrdup(pszTableNameIn);
-    this->bDeferredCreation = bDeferredCreationIn;
-    pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszTableName));
+    bIsVirtualShape = bIsVirtualShapeIn;
+    pszTableName = CPLStrdup(pszTableNameIn);
+    bDeferredCreation = bDeferredCreationIn;
+    pszEscapedTableName = CPLStrdup(SQLEscapeLiteral(pszTableName));
 
     if( strchr(pszTableName, '(') != NULL &&
         pszTableName[strlen(pszTableName)-1] == ')' )
@@ -185,9 +170,9 @@ CPLErr OGRSQLiteTableLayer::Initialize( const char *pszTableNameIn,
         {
             char* pszGeomCol = CPLStrdup(strchr(pszTableName, '(')+1);
             pszGeomCol[strlen(pszGeomCol)-1] = 0;
-            *strchr(this->pszTableName, '(') = 0;
-            CPLFree(pszEscapedTableName),
-            pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszTableName));
+            *strchr(pszTableName, '(') = 0;
+            CPLFree(pszEscapedTableName);
+            pszEscapedTableName = CPLStrdup(SQLEscapeLiteral(pszTableName));
             EstablishFeatureDefn(pszGeomCol);
             CPLFree(pszGeomCol);
             if( poFeatureDefn == NULL || poFeatureDefn->GetGeomFieldCount() == 0 )
@@ -261,24 +246,57 @@ const char* OGRSQLiteTableLayer::GetName()
 }
 
 /************************************************************************/
-/*                             GetMetadata()                            */
+/*                            GetMetadata()                             */
 /************************************************************************/
 
-char** OGRSQLiteTableLayer::GetMetadata( const char * pszDomain )
+char **OGRSQLiteTableLayer::GetMetadata( const char *pszDomain )
+
 {
     GetLayerDefn();
+    if( !m_bHasTriedDetectingFID64 && pszFIDColumn != NULL )
+    {
+        m_bHasTriedDetectingFID64 = true;
+
+/* -------------------------------------------------------------------- */
+/*      Find if the FID holds 64bit values                              */
+/* -------------------------------------------------------------------- */
+
+        // Normally the fid should be AUTOINCREMENT, so check sqlite_sequence
+        OGRErr err = OGRERR_NONE;
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT seq FROM sqlite_sequence WHERE name = '%q'",
+            pszTableName);
+        CPLPushErrorHandler(CPLQuietErrorHandler);
+        GIntBig nMaxId = SQLGetInteger64( poDS->GetDB(), pszSQL, &err);
+        CPLPopErrorHandler();
+        sqlite3_free(pszSQL);
+        if( err != OGRERR_NONE )
+        {
+            CPLErrorReset();
+
+            // In case of error, fallback to taking the MAX of the FID
+            pszSQL = sqlite3_mprintf("SELECT MAX(\"%w\") FROM \"%w\"",
+                                        pszFIDColumn,
+                                        pszTableName);
+
+            nMaxId = SQLGetInteger64( poDS->GetDB(), pszSQL, NULL);
+            sqlite3_free(pszSQL);
+        }
+        if( nMaxId > INT_MAX )
+            OGRLayer::SetMetadataItem(OLMD_FID64, "YES");
+    }
+
     return OGRSQLiteLayer::GetMetadata(pszDomain);
 }
 
 /************************************************************************/
-/*                           GetMetadataItem()                          */
+/*                          GetMetadataItem()                           */
 /************************************************************************/
 
-const char * OGRSQLiteTableLayer::GetMetadataItem( const char * pszName,
-                                                   const char * pszDomain )
+const char *OGRSQLiteTableLayer::GetMetadataItem( const char * pszName,
+                                                  const char * pszDomain )
 {
-    GetLayerDefn();
-    return OGRSQLiteLayer::GetMetadataItem(pszName, pszDomain);
+    return CSLFetchNameValue( GetMetadata(pszDomain), pszName );
 }
 
 /************************************************************************/
@@ -288,18 +306,16 @@ const char * OGRSQLiteTableLayer::GetMetadataItem( const char * pszName,
 CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
 {
     sqlite3 *hDB = poDS->GetDB();
-    int rc;
-    const char *pszSQL;
-    sqlite3_stmt *hColStmt = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Get the column definitions for this table.                      */
 /* -------------------------------------------------------------------- */
 
-    pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
-                                     pszEscapedTableName );
+    const char *pszSQL =
+        CPLSPrintf("SELECT _rowid_, * FROM '%s' LIMIT 1", pszEscapedTableName);
 
-    rc = sqlite3_prepare( hDB, pszSQL, -1, &hColStmt, NULL );
+    sqlite3_stmt *hColStmt = NULL;
+    int rc = sqlite3_prepare_v2( hDB, pszSQL, -1, &hColStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -330,7 +346,7 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
 /*      column.                                                         */
 /* -------------------------------------------------------------------- */
     CPLFree( pszFIDColumn );
-    pszFIDColumn = CPLStrdup(OGRSQLiteParamsUnquote(sqlite3_column_name( hColStmt, 0 )));
+    pszFIDColumn = CPLStrdup(SQLUnescape(sqlite3_column_name( hColStmt, 0 )));
 
 /* -------------------------------------------------------------------- */
 /*      Collect the rest of the fields.                                 */
@@ -353,26 +369,6 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
     sqlite3_finalize( hColStmt );
 
 /* -------------------------------------------------------------------- */
-/*      Find if the FID holds 64bit values                              */
-/* -------------------------------------------------------------------- */
-    pszSQL = CPLSPrintf("SELECT MAX(%s) FROM '%s'",
-                        OGRSQLiteEscape(pszFIDColumn).c_str(),
-                        pszEscapedTableName);
-    hColStmt = NULL;
-    rc = sqlite3_prepare( hDB, pszSQL, -1, &hColStmt, NULL );
-    if( rc == SQLITE_OK )
-    {
-        rc = sqlite3_step( hColStmt );
-        if( rc == SQLITE_ROW )
-        {
-            GIntBig nMaxId = sqlite3_column_int64( hColStmt, 0 );
-            if( nMaxId > INT_MAX )
-                SetMetadataItem(OLMD_FID64, "YES");
-        }
-    }
-    sqlite3_finalize( hColStmt );
-
-/* -------------------------------------------------------------------- */
 /*      Set the properties of the geometry column.                      */
 /* -------------------------------------------------------------------- */
     int bHasSpatialiteCol = FALSE;
@@ -388,20 +384,20 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
             {
                 pszSQL = CPLSPrintf("SELECT srid, geometry_type, coord_dimension, spatial_index_enabled FROM geometry_columns WHERE lower(f_table_name) = lower('%s') AND lower(f_geometry_column) = lower('%s')",
                                     pszEscapedTableName,
-                                    OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str());
+                                    SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str());
             }
             else
             {
                 pszSQL = CPLSPrintf("SELECT srid, type, coord_dimension, spatial_index_enabled FROM geometry_columns WHERE lower(f_table_name) = lower('%s') AND lower(f_geometry_column) = lower('%s')",
                                     pszEscapedTableName,
-                                    OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str());
+                                    SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str());
             }
         }
         else
         {
             pszSQL = CPLSPrintf("SELECT srid, geometry_type, coord_dimension, geometry_format FROM geometry_columns WHERE lower(f_table_name) = lower('%s') AND lower(f_geometry_column) = lower('%s')",
                                 pszEscapedTableName,
-                                OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str());
+                                SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str());
         }
         char* pszErrMsg = NULL;
         int nRowCount = 0, nColCount = 0;
@@ -500,8 +496,9 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
 /*      Check if there are default values and nullable status           */
 /* -------------------------------------------------------------------- */
 
-    char **papszResult;
-    int nRowCount, nColCount;
+    char **papszResult = NULL;
+    int nRowCount = 0;
+    int nColCount = 0;
     char *pszErrMsg = NULL;
     /*  #|name|type|notnull|default|pk */
     char* pszSQL3 = sqlite3_mprintf("PRAGMA table_info('%q')", pszTableName);
@@ -586,17 +583,15 @@ CPLErr OGRSQLiteTableLayer::EstablishFeatureDefn(const char* pszGeomCol)
 OGRErr OGRSQLiteTableLayer::RecomputeOrdinals()
 {
     sqlite3 *hDB = poDS->GetDB();
-    int rc;
-    const char *pszSQL;
     sqlite3_stmt *hColStmt = NULL;
 /* -------------------------------------------------------------------- */
 /*      Get the column definitions for this table.                      */
 /* -------------------------------------------------------------------- */
 
-    pszSQL = CPLSPrintf( "SELECT _rowid_, * FROM '%s' LIMIT 1",
-                                     pszEscapedTableName );
+    const char *pszSQL =
+        CPLSPrintf("SELECT _rowid_, * FROM '%s' LIMIT 1", pszEscapedTableName);
 
-    rc = sqlite3_prepare( hDB, pszSQL, -1, &hColStmt, NULL );
+    int rc = sqlite3_prepare_v2( hDB, pszSQL, -1, &hColStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -616,7 +611,7 @@ OGRErr OGRSQLiteTableLayer::RecomputeOrdinals()
         return OGRERR_FAILURE;
     }
 
-    int    nRawColumns = sqlite3_column_count( hColStmt );
+    int nRawColumns = sqlite3_column_count( hColStmt );
 
     CPLFree(panFieldOrdinals);
     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * poFeatureDefn->GetFieldCount() );
@@ -624,11 +619,10 @@ OGRErr OGRSQLiteTableLayer::RecomputeOrdinals()
     int nCountGeomFieldOrdinals = 0;
     iFIDCol = -1;
 
-    int iCol;
-    for( iCol = 0; iCol < nRawColumns; iCol++ )
+    for( int iCol = 0; iCol < nRawColumns; iCol++ )
     {
         CPLString osName =
-            OGRSQLiteParamsUnquote(sqlite3_column_name( hColStmt, iCol ));
+            SQLUnescape(sqlite3_column_name( hColStmt, iCol ));
         int nIdx = poFeatureDefn->GetFieldIndex(osName);
         if( pszFIDColumn != NULL && strcmp(osName, pszFIDColumn) == 0 )
         {
@@ -636,14 +630,14 @@ OGRErr OGRSQLiteTableLayer::RecomputeOrdinals()
             {
                 iFIDCol = iCol;
                 if( nIdx >= 0 ) /* in case it has also been created as a regular field */
-                    nCountFieldOrdinals ++;
+                    nCountFieldOrdinals++;
             }
             continue;
         }
         if( nIdx >= 0 )
         {
             panFieldOrdinals[nIdx] = iCol;
-            nCountFieldOrdinals ++;
+            nCountFieldOrdinals++;
         }
         else
         {
@@ -653,7 +647,7 @@ OGRErr OGRSQLiteTableLayer::RecomputeOrdinals()
                 OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                     poFeatureDefn->myGetGeomFieldDefn(nIdx);
                 poGeomFieldDefn->iCol = iCol;
-                nCountGeomFieldOrdinals ++;
+                nCountGeomFieldOrdinals++;
             }
         }
     }
@@ -697,7 +691,6 @@ OGRFeatureDefn* OGRSQLiteTableLayer::GetLayerDefn()
 OGRErr OGRSQLiteTableLayer::ResetStatement()
 
 {
-    int rc;
     CPLString osSQL;
 
     if( bDeferredCreation ) RunDeferredCreationIfNecessary();
@@ -709,27 +702,21 @@ OGRErr OGRSQLiteTableLayer::ResetStatement()
     osSQL.Printf( "SELECT _rowid_, * FROM '%s' %s",
                     pszEscapedTableName,
                     osWHERE.c_str() );
+#ifdef DEBUG_VERBOSE
+    CPLDebug("SQLite", "%s", osSQL.c_str());
+#endif
 
-
-//#ifdef HAVE_SQLITE3_PREPARE_V2
-//    rc = sqlite3_prepare_v2( poDS->GetDB(), osSQL, osSQL.size(),
-//                  &hStmt, NULL );
-//#else
-    rc = sqlite3_prepare( poDS->GetDB(), osSQL, -1, &hStmt, NULL );
-//#endif
-
+    const int rc = sqlite3_prepare_v2( poDS->GetDB(), osSQL, -1, &hStmt, NULL );
     if( rc == SQLITE_OK )
     {
-	return OGRERR_NONE;
-    }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s",
-                  osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
-        hStmt = NULL;
-        return OGRERR_FAILURE;
+        return OGRERR_NONE;
     }
+
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "In ResetStatement(): sqlite3_prepare_v2(%s):\n  %s",
+              osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
+    hStmt = NULL;
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -777,7 +764,6 @@ OGRFeature *OGRSQLiteTableLayer::GetFeature( GIntBig nFeatureId )
 /*      Setup explicit query statement to fetch the record we want.     */
 /* -------------------------------------------------------------------- */
     CPLString osSQL;
-    int rc;
 
     ClearStatement();
 
@@ -785,17 +771,17 @@ OGRFeature *OGRSQLiteTableLayer::GetFeature( GIntBig nFeatureId )
 
     osSQL.Printf( "SELECT _rowid_, * FROM '%s' WHERE \"%s\" = " CPL_FRMT_GIB,
                   pszEscapedTableName,
-                  OGRSQLiteEscape(pszFIDColumn).c_str(), nFeatureId );
+                  SQLEscapeLiteral(pszFIDColumn).c_str(), nFeatureId );
 
     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
 
-    rc = sqlite3_prepare( poDS->GetDB(), osSQL,
-                          static_cast<int>(osSQL.size()),
-                          &hStmt, NULL );
+    const int rc = sqlite3_prepare_v2( poDS->GetDB(), osSQL,
+                                    static_cast<int>(osSQL.size()),
+                                    &hStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "In GetFeature(): sqlite3_prepare(%s):\n  %s",
+                  "In GetFeature(): sqlite3_prepare_v2(%s):\n  %s",
                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
 
         return NULL;
@@ -834,7 +820,6 @@ OGRErr OGRSQLiteTableLayer::SetAttributeFilter( const char *pszQuery )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
@@ -884,15 +869,16 @@ int OGRSQLiteTableLayer::CheckSpatialIndexTable(int iGeomCol)
     if (HasSpatialIndex(iGeomCol) && !poGeomFieldDefn->bHasCheckedSpatialIndexTable)
     {
         poGeomFieldDefn->bHasCheckedSpatialIndexTable = TRUE;
-        char **papszResult;
-        int nRowCount, nColCount;
+        char **papszResult = NULL;
+        int nRowCount = 0;
+        int nColCount = 0;
         char *pszErrMsg = NULL;
 
         CPLString osSQL;
 
         /* This will ensure that RTree support is available */
         osSQL.Printf("SELECT pkid FROM 'idx_%s_%s' WHERE xmax > 0 AND xmin < 0 AND ymax > 0 AND ymin < 0",
-                     pszEscapedTableName, OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str());
+                     pszEscapedTableName, SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str());
 
         int  rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
                                     &papszResult, &nRowCount,
@@ -943,14 +929,14 @@ CPLString OGRSQLiteTableLayer::GetSpatialWhere(int iGeomCol,
     {
         return FormatSpatialFilterFromRTree(poFilterGeom, "ROWID",
             pszEscapedTableName,
-            OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str());
+            SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str());
     }
 
     if( poFilterGeom != NULL &&
         poDS->IsSpatialiteLoaded() && !poGeomFieldDefn->bHasSpatialIndex )
     {
         return FormatSpatialFilterFromMBR(poFilterGeom,
-            OGRSQLiteEscapeName(poGeomFieldDefn->GetNameRef()).c_str());
+            SQLEscapeName(poGeomFieldDefn->GetNameRef()).c_str());
     }
 
     return "";
@@ -970,15 +956,15 @@ void OGRSQLiteTableLayer::BuildWhere()
 
     CPLString osSpatialWHERE = GetSpatialWhere(m_iGeomFieldFilter,
                                                m_poFilterGeom);
-    if (osSpatialWHERE.size() != 0)
+    if (!osSpatialWHERE.empty())
     {
         osWHERE = "WHERE ";
         osWHERE += osSpatialWHERE;
     }
 
-    if( osQuery.size() > 0 )
+    if( !osQuery.empty() )
     {
-        if( osWHERE.size() == 0 )
+        if( osWHERE.empty() )
         {
             osWHERE = "WHERE ";
             osWHERE += osQuery;
@@ -1061,7 +1047,7 @@ GIntBig OGRSQLiteTableLayer::GetFeatureCount( int bForce )
         return OGRSQLiteLayer::GetFeatureCount( bForce );
 
     if (nFeatureCount >= 0 && m_poFilterGeom == NULL &&
-        osQuery.size() == 0 )
+        osQuery.empty() )
     {
         return nFeatureCount;
     }
@@ -1069,10 +1055,10 @@ GIntBig OGRSQLiteTableLayer::GetFeatureCount( int bForce )
 /* -------------------------------------------------------------------- */
 /*      Form count SQL.                                                 */
 /* -------------------------------------------------------------------- */
-    const char *pszSQL;
+    const char *pszSQL = NULL;
 
     if (m_poFilterGeom != NULL && CheckSpatialIndexTable(m_iGeomFieldFilter) &&
-        strlen(osQuery) == 0)
+        osQuery.empty())
     {
         OGREnvelope  sEnvelope;
 
@@ -1080,7 +1066,7 @@ GIntBig OGRSQLiteTableLayer::GetFeatureCount( int bForce )
         const char* pszGeomCol = poFeatureDefn->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef();
         pszSQL = CPLSPrintf("SELECT count(*) FROM 'idx_%s_%s' WHERE "
                             "xmax >= %.12f AND xmin <= %.12f AND ymax >= %.12f AND ymin <= %.12f",
-                            pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str(),
+                            pszEscapedTableName, SQLEscapeLiteral(pszGeomCol).c_str(),
                             sEnvelope.MinX - 1e-11,
                             sEnvelope.MaxX + 1e-11,
                             sEnvelope.MinY - 1e-11,
@@ -1097,27 +1083,22 @@ GIntBig OGRSQLiteTableLayer::GetFeatureCount( int bForce )
 /* -------------------------------------------------------------------- */
 /*      Execute.                                                        */
 /* -------------------------------------------------------------------- */
-    char **papszResult, *pszErrMsg;
-    int nRowCount, nColCount;
-    GIntBig nResult = -1;
-
-    if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult,
-                           &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
-        return -1;
-
-    if( nRowCount == 1 && nColCount == 1 )
+    OGRErr eErr = OGRERR_NONE;
+    GIntBig nResult = SQLGetInteger64( poDS->GetDB(), pszSQL, &eErr);
+    if( eErr == OGRERR_FAILURE )
     {
-        nResult = CPLAtoGIntBig(papszResult[1]);
-
-        if( m_poFilterGeom == NULL && osQuery.size() == 0 )
+        nResult = -1;
+    }
+    else
+    {
+        if( m_poFilterGeom == NULL && osQuery.empty() )
         {
             nFeatureCount = nResult;
-            bStatisticsNeedsToBeFlushed = TRUE;
+            if( poDS->GetUpdate() )
+                bStatisticsNeedsToBeFlushed = TRUE;
         }
     }
 
-    sqlite3_free_table( papszResult );
-
     return nResult;
 }
 
@@ -1160,18 +1141,22 @@ OGRErr OGRSQLiteTableLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int
     if (CheckSpatialIndexTable(iGeomField) &&
         !CPLTestBool(CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO")))
     {
-        const char* pszSQL;
-
-        pszSQL = CPLSPrintf("SELECT MIN(xmin), MIN(ymin), MAX(xmax), MAX(ymax) FROM 'idx_%s_%s'",
-                            pszEscapedTableName, OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str());
+        const char* pszSQL =
+            CPLSPrintf(
+                "SELECT MIN(xmin), MIN(ymin), "
+                "MAX(xmax), MAX(ymax) FROM 'idx_%s_%s'",
+                pszEscapedTableName,
+                SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str());
 
         CPLDebug("SQLITE", "Running %s", pszSQL);
 
 /* -------------------------------------------------------------------- */
 /*      Execute.                                                        */
 /* -------------------------------------------------------------------- */
-        char **papszResult, *pszErrMsg;
-        int nRowCount, nColCount;
+        char **papszResult = NULL;
+        char *pszErrMsg;
+        int nRowCount = 0;
+        int nColCount = 0;
 
         if( sqlite3_get_table( poDS->GetDB(), pszSQL, &papszResult,
                                &nRowCount, &nColCount, &pszErrMsg ) != SQLITE_OK )
@@ -1191,10 +1176,11 @@ OGRErr OGRSQLiteTableLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int
             psExtent->MaxY = CPLAtof(papszResult[4+3]);
             eErr = OGRERR_NONE;
 
-            if( m_poFilterGeom == NULL && osQuery.size() == 0 )
+            if( m_poFilterGeom == NULL && osQuery.empty() )
             {
                 poGeomFieldDefn->bCachedExtentIsValid = TRUE;
-                bStatisticsNeedsToBeFlushed = TRUE;
+                if( poDS->GetUpdate() )
+                    bStatisticsNeedsToBeFlushed = TRUE;
                 memcpy(&poGeomFieldDefn->oCachedExtent, psExtent, sizeof(poGeomFieldDefn->oCachedExtent));
             }
         }
@@ -1210,7 +1196,7 @@ OGRErr OGRSQLiteTableLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int
         eErr = OGRSQLiteLayer::GetExtent(psExtent, bForce);
     else
         eErr = OGRSQLiteLayer::GetExtent(iGeomField, psExtent, bForce);
-    if( eErr == OGRERR_NONE && m_poFilterGeom == NULL && osQuery.size() == 0 )
+    if( eErr == OGRERR_NONE && m_poFilterGeom == NULL && osQuery.empty() )
     {
         poGeomFieldDefn->bCachedExtentIsValid = TRUE;
         bStatisticsNeedsToBeFlushed = TRUE;
@@ -1257,28 +1243,16 @@ CPLString OGRSQLiteFieldDefnToSQliteFieldDefn( OGRFieldDefn* poFieldDefn,
         case OFTDate    : return "DATE"; break;
         case OFTTime    : return "TIME"; break;
         case OFTIntegerList:
-            if (bSQLiteDialectInternalUse )
-                return "INTEGERLIST";
-            else
-                return "VARCHAR";
+            return "JSONINTEGERLIST";
             break;
         case OFTInteger64List:
-            if (bSQLiteDialectInternalUse )
-                return "INTEGER64LIST";
-            else
-                return "VARCHAR";
+            return "JSONINTEGER64LIST";
             break;
         case OFTRealList:
-            if (bSQLiteDialectInternalUse )
-                return "REALLIST";
-            else
-                return "VARCHAR";
+            return "JSONREALLIST";
             break;
         case OFTStringList:
-            if (bSQLiteDialectInternalUse )
-                return "STRINGLIST";
-            else
-                return "VARCHAR";
+            return "JSONSTRINGLIST";
             break;
         default         : return "VARCHAR"; break;
     }
@@ -1330,7 +1304,8 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 
     ClearInsertStmt();
 
-    if( poDS->IsSpatialiteDB() && EQUAL( oField.GetNameRef(), "ROWID") )
+    if( poDS->IsSpatialiteDB() && EQUAL( oField.GetNameRef(), "ROWID") &&
+        !(pszFIDColumn != NULL && EQUAL( oField.GetNameRef(), pszFIDColumn )) )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "In a Spatialite DB, a 'ROWID' column that is not the integer "
@@ -1350,7 +1325,6 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
         CPLFree( pszSafeName );
     }
 
-
     if( (oField.GetType() == OFTTime || oField.GetType() == OFTDate ||
          oField.GetType() == OFTDateTime) &&
         !(CPLTestBool(
@@ -1361,59 +1335,37 @@ OGRErr OGRSQLiteTableLayer::CreateField( OGRFieldDefn *poFieldIn,
 
     if( !bDeferredCreation )
     {
-        /* ADD COLUMN only available since SQLite 3.1.3 */
-        if (CPLTestBool(CPLGetConfigOption("OGR_SQLITE_USE_ADD_COLUMN", "YES")) &&
-            sqlite3_libversion_number() > 3 * 1000000 + 1 * 1000 + 3)
-        {
-            int rc;
-            char *pszErrMsg = NULL;
-            sqlite3 *hDB = poDS->GetDB();
-            CPLString osCommand;
-
-            CPLString osFieldType(FieldDefnToSQliteFieldDefn(&oField));
-            osCommand.Printf("ALTER TABLE '%s' ADD COLUMN '%s' %s",
-                            pszEscapedTableName,
-                            OGRSQLiteEscape(oField.GetNameRef()).c_str(),
-                            osFieldType.c_str());
-            if( !oField.IsNullable() )
-            {
-                osCommand += " NOT NULL";
-            }
-            if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
-            {
-                osCommand += " DEFAULT ";
-                osCommand += oField.GetDefault();
-            }
-            else if( !oField.IsNullable() )
-            {
-                // This is kind of dumb, but SQLite mandates a DEFAULT value
-                // when adding a NOT NULL column in an ALTER TABLE ADD COLUMN
-                // statement, which defeats the purpose of NOT NULL,
-                // whereas it doesn't in CREATE TABLE
-                osCommand += " DEFAULT ''";
-            }
-
-        #ifdef DEBUG
-            CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
-        #endif
+        CPLString osCommand;
 
-            rc = sqlite3_exec( hDB, osCommand, NULL, NULL, &pszErrMsg );
-            if( rc != SQLITE_OK )
-            {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Failed to add field %s to table %s:\n %s",
-                        oField.GetNameRef(), poFeatureDefn->GetName(),
-                        pszErrMsg );
-                sqlite3_free( pszErrMsg );
-                return OGRERR_FAILURE;
-            }
+        CPLString osFieldType(FieldDefnToSQliteFieldDefn(&oField));
+        osCommand.Printf("ALTER TABLE '%s' ADD COLUMN '%s' %s",
+                        pszEscapedTableName,
+                        SQLEscapeLiteral(oField.GetNameRef()).c_str(),
+                        osFieldType.c_str());
+        if( !oField.IsNullable() )
+        {
+            osCommand += " NOT NULL";
         }
-        else
+        if( oField.GetDefault() != NULL && !oField.IsDefaultDriverSpecific() )
+        {
+            osCommand += " DEFAULT ";
+            osCommand += oField.GetDefault();
+        }
+        else if( !oField.IsNullable() )
         {
-            OGRErr eErr = AddColumnAncientMethod(oField);
-            if (eErr != OGRERR_NONE)
-                return eErr;
+            // This is kind of dumb, but SQLite mandates a DEFAULT value
+            // when adding a NOT NULL column in an ALTER TABLE ADD COLUMN
+            // statement, which defeats the purpose of NOT NULL,
+            // whereas it doesn't in CREATE TABLE
+            osCommand += " DEFAULT ''";
         }
+
+    #ifdef DEBUG
+        CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
+    #endif
+
+        if( SQLCommand( poDS->GetDB(), osCommand ) != OGRERR_NONE )
+            return OGRERR_FAILURE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -1529,30 +1481,24 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
                                                   int bAddColumnsForNonSpatialite )
 {
     OGRwkbGeometryType eType = poGeomFieldDefn->GetType();
-    int nCoordDim;
     const char* pszGeomCol = poGeomFieldDefn->GetNameRef();
     int nSRSId = poGeomFieldDefn->nSRSId;
-    CPLString osCommand;
-    char* pszErrMsg = NULL;
 
-    if( eType == wkbFlatten(eType) )
-        nCoordDim = 2;
-    else
-        nCoordDim = 3;
+    const int nCoordDim = eType == wkbFlatten(eType) ? 2 : 3;
 
     if( bAddColumnsForNonSpatialite && !poDS->IsSpatialiteDB() )
     {
-        osCommand = CPLSPrintf("ALTER TABLE '%s' ADD COLUMN ",
-                               pszEscapedTableName );
+        CPLString osCommand = CPLSPrintf("ALTER TABLE '%s' ADD COLUMN ",
+                                         pszEscapedTableName );
         if( poGeomFieldDefn->eGeomFormat == OSGF_WKT )
         {
             osCommand += CPLSPrintf(" '%s' VARCHAR",
-                OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str() );
+                SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str() );
         }
         else
         {
             osCommand += CPLSPrintf(" '%s' BLOB",
-                OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str() );
+                SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str() );
         }
         if( !poGeomFieldDefn->IsNullable() )
             osCommand += " NOT NULL DEFAULT ''";
@@ -1561,17 +1507,12 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
         CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
 #endif
 
-        int rc = sqlite3_exec( poDS->GetDB(), osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Unable to geometry field:\n%s",
-                      pszErrMsg );
-            sqlite3_free( pszErrMsg );
+        if( SQLCommand( poDS->GetDB(), osCommand ) != OGRERR_NONE )
             return OGRERR_FAILURE;
-        }
     }
 
+    CPLString osCommand;
+
     if ( poDS->IsSpatialiteDB() )
     {
         /*
@@ -1608,7 +1549,7 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
         osCommand.Printf( "SELECT AddGeometryColumn("
                         "'%s', '%s', %d, '%s', %s",
                         pszEscapedTableName,
-                        OGRSQLiteEscape(pszGeomCol).c_str(), nSRSId,
+                        SQLEscapeLiteral(pszGeomCol).c_str(), nSRSId,
                         pszType, pszCoordDim );
         if( iSpatialiteVersion >= 30 && !poGeomFieldDefn->IsNullable() )
             osCommand += ", 1";
@@ -1629,7 +1570,7 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
                 "geometry_type, coord_dimension, srid) VALUES "
                 "('%s','%s','%s', %d, %d, %d)",
                 pszEscapedTableName,
-                OGRSQLiteEscape(pszGeomCol).c_str(), pszGeomFormat,
+                SQLEscapeLiteral(pszGeomCol).c_str(), pszGeomFormat,
                 (int) wkbFlatten(eType), nCoordDim, nSRSId );
         }
         else
@@ -1640,7 +1581,7 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
                 "geometry_type, coord_dimension) VALUES "
                 "('%s','%s','%s', %d, %d)",
                 pszEscapedTableName,
-                OGRSQLiteEscape(pszGeomCol).c_str(), pszGeomFormat,
+                SQLEscapeLiteral(pszGeomCol).c_str(), pszGeomFormat,
                 (int) wkbFlatten(eType), nCoordDim );
         }
     }
@@ -1649,17 +1590,7 @@ OGRErr OGRSQLiteTableLayer::RunAddGeometryColumn( OGRSQLiteGeomFieldDefn *poGeom
     CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
 #endif
 
-    int rc = sqlite3_exec( poDS->GetDB(), osCommand, NULL, NULL, &pszErrMsg );
-    if( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to geometry field:\n%s",
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
-        return OGRERR_FAILURE;
-    }
-
-    return OGRERR_NONE;
+    return SQLCommand( poDS->GetDB(), osCommand );
 }
 
 /************************************************************************/
@@ -1671,10 +1602,9 @@ void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
                                                     size_t& nBufLenOut,
                                                     int nExtraSpace)
 {
-    int iField;
     size_t nFieldListLen = 100 + 2 * nExtraSpace;
 
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
         nFieldListLen +=
@@ -1684,7 +1614,7 @@ void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
     }
 
     nFieldListLen += 50 + (pszFIDColumn ? 2 * strlen(pszFIDColumn) : strlen("OGC_FID"));
-    for( iField = 0; iField < poFeatureDefn->GetGeomFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetGeomFieldCount(); iField++ )
     {
         nFieldListLen += 70 + 2 * strlen(poFeatureDefn->GetGeomFieldDefn(iField)->GetNameRef());
     }
@@ -1696,21 +1626,21 @@ void OGRSQLiteTableLayer::InitFieldListForRecrerate(char* & pszNewFieldList,
 /* -------------------------------------------------------------------- */
 /*      Build list of old fields, and the list of new fields.           */
 /* -------------------------------------------------------------------- */
-    snprintf( pszFieldListForSelect, nFieldListLen, "\"%s\"", pszFIDColumn ? OGRSQLiteEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
-    snprintf( pszNewFieldList, nFieldListLen, "\"%s\" INTEGER PRIMARY KEY",pszFIDColumn ? OGRSQLiteEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
+    snprintf( pszFieldListForSelect, nFieldListLen, "\"%s\"", pszFIDColumn ? SQLEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
+    snprintf( pszNewFieldList, nFieldListLen, "\"%s\" INTEGER PRIMARY KEY",pszFIDColumn ? SQLEscapeName(pszFIDColumn).c_str() : "OGC_FID" );
 
-    for( iField = 0; iField < poFeatureDefn->GetGeomFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetGeomFieldCount(); iField++ )
     {
         OGRSQLiteGeomFieldDefn* poGeomFieldDefn = poFeatureDefn->myGetGeomFieldDefn(iField);
         strcat( pszFieldListForSelect, "," );
         strcat( pszNewFieldList, "," );
 
         strcat( pszFieldListForSelect, "\"");
-        strcat( pszFieldListForSelect, OGRSQLiteEscapeName(poGeomFieldDefn->GetNameRef()) );
+        strcat( pszFieldListForSelect, SQLEscapeName(poGeomFieldDefn->GetNameRef()) );
         strcat( pszFieldListForSelect, "\"");
 
         strcat( pszNewFieldList, "\"");
-        strcat( pszNewFieldList, OGRSQLiteEscapeName(poGeomFieldDefn->GetNameRef()) );
+        strcat( pszNewFieldList, SQLEscapeName(poGeomFieldDefn->GetNameRef()) );
         strcat( pszNewFieldList, "\"");
 
         if ( poGeomFieldDefn->eGeomFormat == OSGF_WKT )
@@ -1730,7 +1660,7 @@ void OGRSQLiteTableLayer::AddColumnDef(char* pszNewFieldList, size_t nBufLen,
                                        OGRFieldDefn* poFldDefn)
 {
     snprintf( pszNewFieldList+strlen(pszNewFieldList), nBufLen-strlen(pszNewFieldList),
-             ", '%s' %s", OGRSQLiteEscape(poFldDefn->GetNameRef()).c_str(),
+             ", '%s' %s", SQLEscapeLiteral(poFldDefn->GetNameRef()).c_str(),
              FieldDefnToSQliteFieldDefn(poFldDefn).c_str() );
     if( !poFldDefn->IsNullable() )
         snprintf( pszNewFieldList+strlen(pszNewFieldList),
@@ -1744,184 +1674,6 @@ void OGRSQLiteTableLayer::AddColumnDef(char* pszNewFieldList, size_t nBufLen,
 }
 
 /************************************************************************/
-/*                       AddColumnAncientMethod()                       */
-/************************************************************************/
-
-OGRErr OGRSQLiteTableLayer::AddColumnAncientMethod( OGRFieldDefn& oField)
-{
-
-/* -------------------------------------------------------------------- */
-/*      How much space do we need for the list of fields.               */
-/* -------------------------------------------------------------------- */
-    int iField;
-    char *pszOldFieldList, *pszNewFieldList;
-    size_t nBufLen = 0;
-
-    InitFieldListForRecrerate(pszNewFieldList, pszOldFieldList,nBufLen,
-                              static_cast<int>(strlen( oField.GetNameRef() )));
-
-/* -------------------------------------------------------------------- */
-/*      Build list of old fields, and the list of new fields.           */
-/* -------------------------------------------------------------------- */
-
-    int iNextOrdinal = 3; /* _rowid_ is 1, OGC_FID is 2 */
-
-    iNextOrdinal += poFeatureDefn->GetGeomFieldCount();
-
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
-    {
-        OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
-
-        // we already added OGC_FID so don't do it again
-        if( EQUAL(poFldDefn->GetNameRef(),pszFIDColumn ? pszFIDColumn : "OGC_FID") )
-            continue;
-
-        snprintf( pszOldFieldList+strlen(pszOldFieldList), nBufLen-strlen(pszOldFieldList),
-                 ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
-
-        AddColumnDef(pszNewFieldList, nBufLen, poFldDefn);
-
-        iNextOrdinal++;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Add the new field.                                              */
-/* -------------------------------------------------------------------- */
-    AddColumnDef(pszNewFieldList, nBufLen, &oField);
-
-/* ==================================================================== */
-/*      Backup, destroy, recreate and repopulate the table.  SQLite     */
-/*      has no ALTER TABLE so we have to do all this to add a           */
-/*      column.                                                         */
-/* ==================================================================== */
-
-/* -------------------------------------------------------------------- */
-/*      Do this all in a transaction.                                   */
-/* -------------------------------------------------------------------- */
-    poDS->SoftStartTransaction();
-
-/* -------------------------------------------------------------------- */
-/*      Save existing related triggers and index                        */
-/* -------------------------------------------------------------------- */
-    int rc;
-    char *pszErrMsg = NULL;
-    sqlite3 *hDB = poDS->GetDB();
-    CPLString osSQL;
-
-    osSQL.Printf( "SELECT sql FROM sqlite_master WHERE type IN ('trigger','index') AND tbl_name='%s'",
-                   pszEscapedTableName );
-
-    int nRowTriggerIndexCount, nColTriggerIndexCount;
-    char **papszTriggerIndexResult = NULL;
-    rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult,
-                            &nRowTriggerIndexCount, &nColTriggerIndexCount, &pszErrMsg );
-
-/* -------------------------------------------------------------------- */
-/*      Make a backup of the table.                                     */
-/* -------------------------------------------------------------------- */
-
-    if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB,
-                       CPLSPrintf( "CREATE TEMPORARY TABLE t1_back(%s)",
-                                   pszOldFieldList ),
-                       NULL, NULL, &pszErrMsg );
-
-    if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB,
-                           CPLSPrintf( "INSERT INTO t1_back SELECT %s FROM '%s'",
-                                       pszOldFieldList,
-                                       pszEscapedTableName ),
-                           NULL, NULL, &pszErrMsg );
-
-
-/* -------------------------------------------------------------------- */
-/*      Drop the original table, and recreate with new field.           */
-/* -------------------------------------------------------------------- */
-    if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB,
-                           CPLSPrintf( "DROP TABLE '%s'",
-                                       pszEscapedTableName ),
-                           NULL, NULL, &pszErrMsg );
-
-    if( rc == SQLITE_OK )
-    {
-        const char *pszCmd =
-            CPLSPrintf( "CREATE TABLE '%s' (%s)",
-                        pszEscapedTableName,
-                        pszNewFieldList );
-        rc = sqlite3_exec( hDB, pszCmd,
-                           NULL, NULL, &pszErrMsg );
-
-        CPLDebug( "OGR_SQLITE", "exec(%s)", pszCmd );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Copy backup field values into new table.                        */
-/* -------------------------------------------------------------------- */
-
-    if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB,
-                           CPLSPrintf( "INSERT INTO '%s' SELECT %s, NULL FROM t1_back",
-                                       pszEscapedTableName,
-                                       pszOldFieldList ),
-                           NULL, NULL, &pszErrMsg );
-
-    CPLFree( pszOldFieldList );
-    CPLFree( pszNewFieldList );
-
-/* -------------------------------------------------------------------- */
-/*      Cleanup backup table.                                           */
-/* -------------------------------------------------------------------- */
-
-    if( rc == SQLITE_OK )
-        rc = sqlite3_exec( hDB,
-                           CPLSPrintf( "DROP TABLE t1_back" ),
-                           NULL, NULL, &pszErrMsg );
-
-/* -------------------------------------------------------------------- */
-/*      Recreate existing related tables, triggers and index            */
-/* -------------------------------------------------------------------- */
-
-    if( rc == SQLITE_OK )
-    {
-        int i;
-
-        for(i = 1; i <= nRowTriggerIndexCount && nColTriggerIndexCount == 1 && rc == SQLITE_OK; i++)
-        {
-            if (papszTriggerIndexResult[i] != NULL && papszTriggerIndexResult[i][0] != '\0')
-                rc = sqlite3_exec( hDB,
-                            papszTriggerIndexResult[i],
-                            NULL, NULL, &pszErrMsg );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      COMMIT on success or ROLLBACK on failure.                       */
-/* -------------------------------------------------------------------- */
-
-    sqlite3_free_table( papszTriggerIndexResult );
-
-    if( rc == SQLITE_OK )
-    {
-        poDS->SoftCommitTransaction();
-    }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Failed to add field %s to table %s:\n %s",
-                  oField.GetNameRef(), poFeatureDefn->GetName(),
-                  pszErrMsg );
-        sqlite3_free( pszErrMsg );
-
-        poDS->SoftRollbackTransaction();
-
-        return OGRERR_FAILURE;
-    }
-
-    return OGRERR_NONE;
-}
-
-/************************************************************************/
 /*                           RecreateTable()                            */
 /************************************************************************/
 
@@ -1937,7 +1689,6 @@ OGRErr OGRSQLiteTableLayer::RecreateTable(const char* pszFieldListForSelect,
 /* -------------------------------------------------------------------- */
 /*      Save existing related triggers and index                        */
 /* -------------------------------------------------------------------- */
-    int rc;
     char *pszErrMsg = NULL;
     sqlite3 *hDB = poDS->GetDB();
     CPLString osSQL;
@@ -1947,8 +1698,10 @@ OGRErr OGRSQLiteTableLayer::RecreateTable(const char* pszFieldListForSelect,
 
     int nRowTriggerIndexCount, nColTriggerIndexCount;
     char **papszTriggerIndexResult = NULL;
-    rc = sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult,
-                            &nRowTriggerIndexCount, &nColTriggerIndexCount, &pszErrMsg );
+    int rc =
+        sqlite3_get_table( hDB, osSQL.c_str(), &papszTriggerIndexResult,
+                           &nRowTriggerIndexCount, &nColTriggerIndexCount,
+                           &pszErrMsg );
 
 /* -------------------------------------------------------------------- */
 /*      Make a backup of the table.                                     */
@@ -1967,7 +1720,6 @@ OGRErr OGRSQLiteTableLayer::RecreateTable(const char* pszFieldListForSelect,
                                        pszEscapedTableName ),
                            NULL, NULL, &pszErrMsg );
 
-
 /* -------------------------------------------------------------------- */
 /*      Drop the original table                                         */
 /* -------------------------------------------------------------------- */
@@ -1995,9 +1747,11 @@ OGRErr OGRSQLiteTableLayer::RecreateTable(const char* pszFieldListForSelect,
 
     if( rc == SQLITE_OK )
     {
-        int i;
-
-        for(i = 1; i <= nRowTriggerIndexCount && nColTriggerIndexCount == 1 && rc == SQLITE_OK; i++)
+        for( int i = 1;
+             i <= nRowTriggerIndexCount &&
+             nColTriggerIndexCount == 1 &&
+             rc == SQLITE_OK;
+             i++)
         {
             if (papszTriggerIndexResult[i] != NULL && papszTriggerIndexResult[i][0] != '\0')
                 rc = sqlite3_exec( hDB,
@@ -2061,13 +1815,13 @@ OGRErr OGRSQLiteTableLayer::DeleteField( int iFieldToDelete )
 /* -------------------------------------------------------------------- */
 /*      Build list of old fields, and the list of new fields.           */
 /* -------------------------------------------------------------------- */
-    int iField;
-    char *pszNewFieldList, *pszFieldListForSelect;
+    char *pszNewFieldList = NULL;
+    char *pszFieldListForSelect = NULL;
     size_t nBufLen = 0;
 
     InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect, nBufLen);
 
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
 
@@ -2076,7 +1830,7 @@ OGRErr OGRSQLiteTableLayer::DeleteField( int iFieldToDelete )
 
         snprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
                   nBufLen-strlen(pszFieldListForSelect),
-                 ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
+                 ", \"%s\"", SQLEscapeName(poFldDefn->GetNameRef()).c_str() );
 
         AddColumnDef(pszNewFieldList, nBufLen, poFldDefn);
     }
@@ -2139,8 +1893,8 @@ OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poN
 /* -------------------------------------------------------------------- */
 /*      Build list of old fields, and the list of new fields.           */
 /* -------------------------------------------------------------------- */
-    int iField;
-    char *pszNewFieldList, *pszFieldListForSelect;
+    char *pszNewFieldList = NULL;
+    char *pszFieldListForSelect = NULL;
     size_t nBufLen = 0;
 
     InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect,
@@ -2150,13 +1904,13 @@ OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poN
                               (poNewFieldDefn->GetDefault() ? static_cast<int>(strlen(poNewFieldDefn->GetDefault())) : 0)
                               );
 
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(iField);
 
         snprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
                  nBufLen-strlen(pszFieldListForSelect),
-                 ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
+                 ", \"%s\"", SQLEscapeName(poFldDefn->GetNameRef()).c_str() );
 
         if (iField == iFieldToAlter)
         {
@@ -2186,7 +1940,7 @@ OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poN
             snprintf( pszNewFieldList+strlen(pszNewFieldList),
                       nBufLen-strlen(pszNewFieldList),
                     ", '%s' %s",
-                    OGRSQLiteEscape(oTmpFieldDefn.GetNameRef()).c_str(),
+                    SQLEscapeLiteral(oTmpFieldDefn.GetNameRef()).c_str(),
                     FieldDefnToSQliteFieldDefn(&oTmpFieldDefn).c_str() );
             if ( (nFlagsIn & ALTER_NAME_FLAG) &&
                  oTmpFieldDefn.GetType() == OFTString &&
@@ -2237,7 +1991,7 @@ OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poN
 
     if (nFlagsIn & ALTER_TYPE_FLAG)
     {
-        int iIdx;
+        int iIdx = 0;
         if( poNewFieldDefn->GetType() != OFTString &&
             (iIdx = CSLFindString(papszCompressedColumns,
                                   poFieldDefn->GetNameRef())) >= 0 )
@@ -2251,9 +2005,9 @@ OGRErr OGRSQLiteTableLayer::AlterFieldDefn( int iFieldToAlter, OGRFieldDefn* poN
     }
     if (nFlagsIn & ALTER_NAME_FLAG)
     {
-        int iIdx;
-        if( (iIdx = CSLFindString(papszCompressedColumns,
-                                  poFieldDefn->GetNameRef())) >= 0 )
+        const int iIdx = CSLFindString(papszCompressedColumns,
+                                       poFieldDefn->GetNameRef());
+        if( iIdx >= 0 )
         {
             CPLFree(papszCompressedColumns[iIdx]);
             papszCompressedColumns[iIdx] =
@@ -2304,19 +2058,19 @@ OGRErr OGRSQLiteTableLayer::ReorderFields( int* panMap )
 /* -------------------------------------------------------------------- */
 /*      Build list of old fields, and the list of new fields.           */
 /* -------------------------------------------------------------------- */
-    int iField;
-    char *pszNewFieldList, *pszFieldListForSelect;
-    size_t nBufLen;
+    char *pszNewFieldList = NULL;
+    char *pszFieldListForSelect = NULL;
+    size_t nBufLen = 0;
 
     InitFieldListForRecrerate(pszNewFieldList, pszFieldListForSelect, nBufLen);
 
-    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
+    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     {
         OGRFieldDefn *poFldDefn = poFeatureDefn->GetFieldDefn(panMap[iField]);
 
         snprintf( pszFieldListForSelect+strlen(pszFieldListForSelect),
                   nBufLen - strlen(pszFieldListForSelect),
-                 ", \"%s\"", OGRSQLiteEscapeName(poFldDefn->GetNameRef()).c_str() );
+                 ", \"%s\"", SQLEscapeName(poFldDefn->GetNameRef()).c_str() );
 
         AddColumnDef(pszNewFieldList, nBufLen, poFldDefn);
     }
@@ -2358,18 +2112,16 @@ OGRErr OGRSQLiteTableLayer::ReorderFields( int* panMap )
 
 OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                                         sqlite3_stmt* hStmtIn,
-                                        int bBindNullValues )
+                                        bool bBindUnsetAsNull )
 {
-    int rc;
     sqlite3 *hDB = poDS->GetDB();
 
 /* -------------------------------------------------------------------- */
 /*      Bind the geometry                                               */
 /* -------------------------------------------------------------------- */
     int nBindField = 1;
-    int iField;
     int nFieldCount = poFeatureDefn->GetGeomFieldCount();
-    for( iField = 0; iField < nFieldCount; iField++ )
+    for( int iField = 0; iField < nFieldCount; iField++ )
     {
         OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
             poFeatureDefn->myGetGeomFieldDefn(iField);
@@ -2377,6 +2129,7 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
         if( eGeomFormat == OSGF_FGF )
             continue;
         OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iField);
+        int rc = SQLITE_OK;
         if ( poGeom != NULL )
         {
             if ( eGeomFormat == OSGF_WKT )
@@ -2395,12 +2148,14 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
             }
             else if ( eGeomFormat == OSGF_SpatiaLite )
             {
-                int     nBLOBLen;
-                GByte   *pabySLBLOB;
-
-                int nSRSId = poGeomFieldDefn->nSRSId;
-                CPL_IGNORE_RET_VAL(ExportSpatiaLiteGeometry( poGeom, nSRSId, wkbNDR,
-                                        bSpatialite2D, bUseComprGeom, &pabySLBLOB, &nBLOBLen ));
+                int nBLOBLen = 0;
+                GByte *pabySLBLOB = NULL;
+
+                const int nSRSId = poGeomFieldDefn->nSRSId;
+                CPL_IGNORE_RET_VAL(
+                    ExportSpatiaLiteGeometry(
+                        poGeom, nSRSId, wkbNDR,
+                        bSpatialite2D, bUseComprGeom, &pabySLBLOB, &nBLOBLen ));
                 rc = sqlite3_bind_blob( hStmtIn, nBindField++, pabySLBLOB,
                                         nBLOBLen, CPLFree );
             }
@@ -2408,15 +2163,12 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
             {
                 rc = SQLITE_OK;
                 CPL_IGNORE_RET_VAL(rc);
-                CPLAssert(0);
+                CPLAssert(false);
             }
         }
         else
         {
-            if (bBindNullValues)
-                rc = sqlite3_bind_null( hStmtIn, nBindField++ );
-            else
-                rc = SQLITE_OK;
+            rc = sqlite3_bind_null( hStmtIn, nBindField++ );
         }
 
         if( rc != SQLITE_OK )
@@ -2432,18 +2184,19 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
 /*      Bind field values.                                              */
 /* -------------------------------------------------------------------- */
     nFieldCount = poFeatureDefn->GetFieldCount();
-    for( iField = 0; iField < nFieldCount; iField++ )
+    for( int iField = 0; iField < nFieldCount; iField++ )
     {
-        const char *pszRawValue;
         if( iField == iFIDAsRegularColumnIndex )
             continue;
+        if( !bBindUnsetAsNull && !poFeature->IsFieldSet(iField) )
+            continue;
+
+        int rc = SQLITE_OK;
 
-        if( !poFeature->IsFieldSet( iField ) )
+        if( (bBindUnsetAsNull && !poFeature->IsFieldSet(iField)) ||
+            poFeature->IsFieldNull( iField ) )
         {
-            if (bBindNullValues)
-                rc = sqlite3_bind_null( hStmtIn, nBindField++ );
-            else
-                rc = SQLITE_OK;
+            rc = sqlite3_bind_null( hStmtIn, nBindField++ );
         }
         else
         {
@@ -2492,7 +2245,13 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
 
                 case OFTDate:
                 {
-                    int nYear, nMonth, nDay, nHour, nMinute, nSecond, nTZ;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMinute = 0;
+                    int nSecond = 0;
+                    int nTZ = 0;
                     poFeature->GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
                                                 &nHour, &nMinute, &nSecond, &nTZ);
                     char szBuffer[64];
@@ -2504,8 +2263,13 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
 
                 case OFTTime:
                 {
-                    int nYear, nMonth, nDay, nHour, nMinute, nTZ;
-                    float fSecond;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMinute = 0;
+                    int nTZ = 0;
+                    float fSecond = 0.0f;
                     poFeature->GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
                                                 &nHour, &nMinute, &fSecond, &nTZ );
                     char szBuffer[64];
@@ -2519,25 +2283,21 @@ OGRErr OGRSQLiteTableLayer::BindValues( OGRFeature *poFeature,
                 }
 
                 case OFTStringList:
+                case OFTIntegerList:
+                case OFTInteger64List:
+                case OFTRealList:
                 {
-                    char** papszValues = poFeature->GetFieldAsStringList( iField );
-                    CPLString osValue;
-                    osValue += CPLSPrintf("(%d:", CSLCount(papszValues));
-                    for(int i=0; papszValues[i] != NULL; i++)
-                    {
-                        if( i != 0 )
-                            osValue += ",";
-                        osValue += papszValues[i];
-                    }
-                    osValue += ")";
+                    char* pszJSon = poFeature->GetFieldAsSerializedJSon(iField);
                     rc = sqlite3_bind_text(hStmtIn, nBindField++,
-                                               osValue.c_str(), -1, SQLITE_TRANSIENT);
+                                               pszJSon, -1, SQLITE_TRANSIENT);
+                    CPLFree(pszJSon);
                     break;
                 }
 
                 default:
                 {
-                    pszRawValue = poFeature->GetFieldAsString( iField );
+                    const char *pszRawValue =
+                        poFeature->GetFieldAsString( iField );
                     if( CSLFindString(papszCompressedColumns,
                                       poFeatureDefn->GetFieldDefn(iField)->GetNameRef()) >= 0 )
                     {
@@ -2614,7 +2374,7 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
     /* In case the FID column has also been created as a regular field */
     if( iFIDAsRegularColumnIndex >= 0 )
     {
-        if( !poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) ||
+        if( !poFeature->IsFieldSetAndNotNull( iFIDAsRegularColumnIndex ) ||
             poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex) != poFeature->GetFID() )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -2627,7 +2387,6 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
 
     sqlite3 *hDB = poDS->GetDB();
-    CPLString      osCommand;
     int            bNeedComma = FALSE;
 
     ResetReading();
@@ -2635,14 +2394,13 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Form the UPDATE command.                                        */
 /* -------------------------------------------------------------------- */
-    osCommand += CPLSPrintf( "UPDATE '%s' SET ", pszEscapedTableName );
+    CPLString osCommand = CPLSPrintf( "UPDATE '%s' SET ", pszEscapedTableName );
 
 /* -------------------------------------------------------------------- */
 /*      Add geometry field name.                                        */
 /* -------------------------------------------------------------------- */
-    int iField;
     int nFieldCount = poFeatureDefn->GetGeomFieldCount();
-    for( iField = 0; iField < nFieldCount; iField++ )
+    for( int iField = 0; iField < nFieldCount; iField++ )
     {
         OGRSQLiteGeomFormat eGeomFormat =
             poFeatureDefn->myGetGeomFieldDefn(iField)->eGeomFormat;
@@ -2652,7 +2410,7 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
             osCommand += ",";
 
         osCommand += "\"";
-        osCommand += OGRSQLiteEscapeName( poFeatureDefn->GetGeomFieldDefn(iField)->GetNameRef());
+        osCommand += SQLEscapeName( poFeatureDefn->GetGeomFieldDefn(iField)->GetNameRef());
         osCommand += "\" = ?";
 
         bNeedComma = TRUE;
@@ -2662,15 +2420,17 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
 /*      Add field names.                                                */
 /* -------------------------------------------------------------------- */
     nFieldCount = poFeatureDefn->GetFieldCount();
-    for( iField = 0; iField < nFieldCount; iField++ )
+    for( int iField = 0; iField < nFieldCount; iField++ )
     {
         if( iField == iFIDAsRegularColumnIndex )
             continue;
+        if( !poFeature->IsFieldSet(iField) )
+            continue;
         if( bNeedComma )
             osCommand += ",";
 
         osCommand += "\"";
-        osCommand += OGRSQLiteEscapeName(poFeatureDefn->GetFieldDefn(iField)->GetNameRef());
+        osCommand += SQLEscapeName(poFeatureDefn->GetFieldDefn(iField)->GetNameRef());
         osCommand += "\" = ?";
 
         bNeedComma = TRUE;
@@ -2683,24 +2443,23 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
 /*      Merge final command.                                            */
 /* -------------------------------------------------------------------- */
     osCommand += " WHERE \"";
-    osCommand += OGRSQLiteEscapeName(pszFIDColumn);
+    osCommand += SQLEscapeName(pszFIDColumn);
     osCommand += CPLSPrintf("\" = " CPL_FRMT_GIB, poFeature->GetFID());
 
 /* -------------------------------------------------------------------- */
 /*      Prepare the statement.                                          */
 /* -------------------------------------------------------------------- */
-    int rc;
-    sqlite3_stmt *hUpdateStmt;
-
 #ifdef DEBUG
-    CPLDebug( "OGR_SQLITE", "prepare(%s)", osCommand.c_str() );
+    CPLDebug( "OGR_SQLITE", "prepare_v2(%s)", osCommand.c_str() );
 #endif
 
-    rc = sqlite3_prepare( hDB, osCommand, -1, &hUpdateStmt, NULL );
+    sqlite3_stmt *hUpdateStmt = NULL;
+    int rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hUpdateStmt, NULL );
+
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "In SetFeature(): sqlite3_prepare(%s):\n  %s",
+                  "In SetFeature(): sqlite3_prepare_v2(%s):\n  %s",
                   osCommand.c_str(), sqlite3_errmsg(hDB) );
 
         return OGRERR_FAILURE;
@@ -2709,7 +2468,7 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Bind values.                                                   */
 /* -------------------------------------------------------------------- */
-    OGRErr eErr = BindValues( poFeature, hUpdateStmt, TRUE );
+    OGRErr eErr = BindValues( poFeature, hUpdateStmt, false );
     if (eErr != OGRERR_NONE)
     {
         sqlite3_finalize( hUpdateStmt );
@@ -2737,7 +2496,7 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
     if( eErr == OGRERR_NONE )
     {
         nFieldCount = poFeatureDefn->GetGeomFieldCount();
-        for( iField = 0; iField < nFieldCount; iField++ )
+        for( int iField = 0; iField < nFieldCount; iField++ )
         {
             OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                 poFeatureDefn->myGetGeomFieldDefn(iField);
@@ -2763,8 +2522,8 @@ OGRErr OGRSQLiteTableLayer::ISetFeature( OGRFeature *poFeature )
 static int AreTriggersSimilar(const char* pszExpectedTrigger,
                               const char* pszTriggerSQL)
 {
-    int i;
-    for(i=0; pszTriggerSQL[i] != '\0' && pszExpectedTrigger[i] != '\0'; i++)
+    int i = 0;  // Used after for.
+    for( ; pszTriggerSQL[i] != '\0' && pszExpectedTrigger[i] != '\0'; i++ )
     {
         if( pszTriggerSQL[i] == pszExpectedTrigger[i] )
             continue;
@@ -2929,7 +2688,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
         OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                                         poFeatureDefn->myGetGeomFieldDefn(j);
         OGRGeometry *poGeom = poFeature->GetGeomFieldRef(j);
-        if( poGeomFieldDefn->aosDisabledTriggers.size() != 0  && poGeom != NULL )
+        if( !poGeomFieldDefn->aosDisabledTriggers.empty()  && poGeom != NULL )
         {
             OGRwkbGeometryType eGeomType = poGeomFieldDefn->GetType();
             if( eGeomType != wkbUnknown && poGeom->getGeometryType() != eGeomType )
@@ -2950,15 +2709,14 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
 
     /* If there's a unset field with a default value, then we must create */
     /* a specific INSERT statement to avoid unset fields to be bound to NULL */
-    int bHasDefaultValue = FALSE;
-    int iField;
+    bool bHasDefaultValue = false;
     int nFieldCount = poFeatureDefn->GetFieldCount();
-    for( iField = 0; iField < nFieldCount; iField++ )
+    for( int iField = 0; iField < nFieldCount; iField++ )
     {
         if( !poFeature->IsFieldSet( iField ) &&
             poFeature->GetFieldDefnRef(iField)->GetDefault() != NULL )
         {
-            bHasDefaultValue = TRUE;
+            bHasDefaultValue = true;
             break;
         }
     }
@@ -2968,7 +2726,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
     {
         if( poFeature->GetFID() == OGRNullFID )
         {
-            if( poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) )
+            if( poFeature->IsFieldSetAndNotNull( iFIDAsRegularColumnIndex ) )
             {
                 poFeature->SetFID(
                     poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex));
@@ -2976,7 +2734,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
         }
         else
         {
-            if( !poFeature->IsFieldSet( iFIDAsRegularColumnIndex ) ||
+            if( !poFeature->IsFieldSetAndNotNull( iFIDAsRegularColumnIndex ) ||
                 poFeature->GetFieldAsInteger64(iFIDAsRegularColumnIndex) != poFeature->GetFID() )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
@@ -3003,7 +2761,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
             && poFeature->GetFID() != OGRNullFID )
         {
             osCommand += "\"";
-            osCommand += OGRSQLiteEscapeName(pszFIDColumn);
+            osCommand += SQLEscapeName(pszFIDColumn);
             osCommand += "\"";
 
             osValues += CPLSPrintf( CPL_FRMT_GIB, poFeature->GetFID() );
@@ -3014,7 +2772,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
 /*      Add geometry.                                                   */
 /* -------------------------------------------------------------------- */
         nFieldCount = poFeatureDefn->GetGeomFieldCount();
-        for( iField = 0; iField < nFieldCount; iField++ )
+        for( int iField = 0; iField < nFieldCount; iField++ )
         {
             OGRSQLiteGeomFormat eGeomFormat =
                 poFeatureDefn->myGetGeomFieldDefn(iField)->eGeomFormat;
@@ -3029,7 +2787,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
             }
 
             osCommand += "\"";
-            osCommand += OGRSQLiteEscapeName(poFeatureDefn->GetGeomFieldDefn(iField)->GetNameRef());
+            osCommand += SQLEscapeName(poFeatureDefn->GetGeomFieldDefn(iField)->GetNameRef());
             osCommand += "\"";
 
             osValues += "?";
@@ -3041,7 +2799,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
 /*      Add field values.                                               */
 /* -------------------------------------------------------------------- */
         nFieldCount = poFeatureDefn->GetFieldCount();
-        for( iField = 0; iField < nFieldCount; iField++ )
+        for( int iField = 0; iField < nFieldCount; iField++ )
         {
             if( iField == iFIDAsRegularColumnIndex )
                 continue;
@@ -3055,7 +2813,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
             }
 
             osCommand += "\"";
-            osCommand += OGRSQLiteEscapeName(poFeatureDefn->GetFieldDefn(iField)->GetNameRef());
+            osCommand += SQLEscapeName(poFeatureDefn->GetFieldDefn(iField)->GetNameRef());
             osCommand += "\"";
 
             osValues += "?";
@@ -3074,32 +2832,28 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
             osCommand = CPLSPrintf( "INSERT INTO '%s' DEFAULT VALUES", pszEscapedTableName );
     }
     else
+    {
         bReuseStmt = TRUE;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Prepare the statement.                                          */
 /* -------------------------------------------------------------------- */
-    int rc;
-
     if( !bReuseStmt && (hInsertStmt == NULL || osCommand != osLastInsertStmt) )
     {
     #ifdef DEBUG
-        CPLDebug( "OGR_SQLITE", "prepare(%s)", osCommand.c_str() );
+        CPLDebug( "OGR_SQLITE", "prepare_v2(%s)", osCommand.c_str() );
     #endif
 
         ClearInsertStmt();
         if( poFeature->GetFID() == OGRNullFID )
             osLastInsertStmt = osCommand;
 
-#ifdef HAVE_SQLITE3_PREPARE_V2
-        rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hInsertStmt, NULL );
-#else
-        rc = sqlite3_prepare( hDB, osCommand, -1, &hInsertStmt, NULL );
-#endif
+        const int rc = sqlite3_prepare_v2( hDB, osCommand, -1, &hInsertStmt, NULL );
         if( rc != SQLITE_OK )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "In CreateFeature(): sqlite3_prepare(%s):\n  %s",
+                    "In CreateFeature(): sqlite3_prepare_v2(%s):\n  %s",
                     osCommand.c_str(), sqlite3_errmsg(hDB) );
 
             ClearInsertStmt();
@@ -3120,7 +2874,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
 /* -------------------------------------------------------------------- */
 /*      Execute the insert.                                             */
 /* -------------------------------------------------------------------- */
-    rc = sqlite3_step( hInsertStmt );
+    const int rc = sqlite3_step( hInsertStmt );
 
     if( rc != SQLITE_OK && rc != SQLITE_DONE )
     {
@@ -3149,7 +2903,7 @@ OGRErr OGRSQLiteTableLayer::ICreateFeature( OGRFeature *poFeature )
         ClearInsertStmt();
 
     nFieldCount = poFeatureDefn->GetGeomFieldCount();
-    for( iField = 0; iField < nFieldCount; iField++ )
+    for( int iField = 0; iField < nFieldCount; iField++ )
     {
         OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
             poFeatureDefn->myGetGeomFieldDefn(iField);
@@ -3183,8 +2937,6 @@ OGRErr OGRSQLiteTableLayer::DeleteFeature( GIntBig nFID )
 
 {
     CPLString      osSQL;
-    int            rc;
-    char          *pszErrMsg = NULL;
 
     if (HasLayerDefnError())
         return OGRERR_FAILURE;
@@ -3211,19 +2963,12 @@ OGRErr OGRSQLiteTableLayer::DeleteFeature( GIntBig nFID )
 
     osSQL.Printf( "DELETE FROM '%s' WHERE \"%s\" = " CPL_FRMT_GIB,
                   pszEscapedTableName,
-                  OGRSQLiteEscapeName(pszFIDColumn).c_str(), nFID );
+                  SQLEscapeName(pszFIDColumn).c_str(), nFID );
 
     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
 
-    rc = sqlite3_exec( poDS->GetDB(), osSQL, NULL, NULL, &pszErrMsg );
-    if( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                    "In DeleteFeature(): sqlite3_exec(%s):\n  %s",
-                    osSQL.c_str(), pszErrMsg );
-        sqlite3_free( pszErrMsg );
+    if( SQLCommand( poDS->GetDB(), osSQL ) != OGRERR_NONE )
         return OGRERR_FAILURE;
-    }
 
     OGRErr eErr = (sqlite3_changes(poDS->GetDB()) > 0) ? OGRERR_NONE : OGRERR_NON_EXISTING_FEATURE;
     if( eErr == OGRERR_NONE )
@@ -3257,7 +3002,7 @@ int OGRSQLiteTableLayer::CreateSpatialIndex(int iGeomCol)
 
     osCommand.Printf("SELECT CreateSpatialIndex('%s', '%s')",
                      pszEscapedTableName,
-                     OGRSQLiteEscape(poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef()).c_str());
+                     SQLEscapeLiteral(poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef()).c_str());
 
     char* pszErrMsg = NULL;
     sqlite3 *hDB = poDS->GetDB();
@@ -3277,7 +3022,6 @@ int OGRSQLiteTableLayer::CreateSpatialIndex(int iGeomCol)
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                      RunDeferredCreationIfNecessary()                */
 /************************************************************************/
@@ -3288,20 +3032,15 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
         return OGRERR_NONE;
     bDeferredCreation = FALSE;
 
-    const char* pszLayerName = poFeatureDefn->GetName();
-
-    int rc;
-    char *pszErrMsg;
     CPLString osCommand;
 
-    osCommand.Printf( "CREATE TABLE '%s' ( %s INTEGER PRIMARY KEY",
+    osCommand.Printf( "CREATE TABLE '%s' ( %s INTEGER PRIMARY KEY AUTOINCREMENT",
                       pszEscapedTableName,
                       pszFIDColumn );
 
-    int i;
     if ( !poDS->IsSpatialiteDB() )
     {
-        for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+        for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
         {
             OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                 poFeatureDefn->myGetGeomFieldDefn(i);
@@ -3309,12 +3048,12 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
             if( poGeomFieldDefn->eGeomFormat == OSGF_WKT )
             {
                 osCommand += CPLSPrintf(", '%s' VARCHAR",
-                    OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str() );
+                    SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str() );
             }
             else
             {
                 osCommand += CPLSPrintf(", '%s' BLOB",
-                    OGRSQLiteEscape(poGeomFieldDefn->GetNameRef()).c_str() );
+                    SQLEscapeLiteral(poGeomFieldDefn->GetNameRef()).c_str() );
             }
             if( !poGeomFieldDefn->IsNullable() )
             {
@@ -3323,14 +3062,14 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
         }
     }
 
-    for(i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
+    for( int i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     {
         OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
         if( i == iFIDAsRegularColumnIndex )
             continue;
         CPLString osFieldType(FieldDefnToSQliteFieldDefn(poFieldDefn));
         osCommand += CPLSPrintf(", '%s' %s",
-                        OGRSQLiteEscape(poFieldDefn->GetNameRef()).c_str(),
+                        SQLEscapeLiteral(poFieldDefn->GetNameRef()).c_str(),
                         osFieldType.c_str());
         if( !poFieldDefn->IsNullable() )
         {
@@ -3353,15 +3092,8 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
     CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
 #endif
 
-    rc = sqlite3_exec( poDS->GetDB(), osCommand, NULL, NULL, &pszErrMsg );
-    if( rc != SQLITE_OK )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to create table %s: %s",
-                  pszLayerName, pszErrMsg );
-        sqlite3_free( pszErrMsg );
+    if( SQLCommand( poDS->GetDB(), osCommand ) != OGRERR_NONE )
         return OGRERR_FAILURE;
-    }
 
 /* -------------------------------------------------------------------- */
 /*      Eventually we should be adding this table to a table of         */
@@ -3381,18 +3113,10 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
 #ifdef DEBUG
         CPLDebug( "OGR_SQLITE", "exec(%s)", osCommand.c_str() );
 #endif
-
-        rc = sqlite3_exec( poDS->GetDB(), osCommand, NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to run %s: %s",
-                  osCommand.c_str(), pszErrMsg );
-            sqlite3_free( pszErrMsg );
+        if( SQLCommand( poDS->GetDB(), osCommand ) != OGRERR_NONE )
             return OGRERR_FAILURE;
-        }
 
-        for(i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+        for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
         {
             OGRSQLiteGeomFieldDefn* poGeomFieldDefn =
                 poFeatureDefn->myGetGeomFieldDefn(i);
@@ -3407,15 +3131,9 @@ OGRErr OGRSQLiteTableLayer::RunDeferredCreationIfNecessary()
     if( poDS->IsSpatialiteDB() && poDS->GetLayerCount() == 1)
     {
         /* To create the layer_statistics and spatialite_history tables */
-        rc = sqlite3_exec( poDS->GetDB(), "SELECT UpdateLayerStatistics()", NULL, NULL, &pszErrMsg );
-        if( rc != SQLITE_OK )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to run %s: %s",
-                  osCommand.c_str(), pszErrMsg );
-            sqlite3_free( pszErrMsg );
+        if( SQLCommand( poDS->GetDB(), "SELECT UpdateLayerStatistics()" )
+                                                            != OGRERR_NONE )
             return OGRERR_FAILURE;
-        }
     }
 
     return OGRERR_NONE;
@@ -3502,25 +3220,31 @@ void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
         CPLString osSQL;
         CPLString osLastEvtDate;
         osSQL.Printf("SELECT MAX(last_insert, last_update, last_delete) FROM geometry_columns_time WHERE "
-                    "(f_table_name = '%s' AND f_geometry_column = '%s')"
+                    "(f_table_name = lower('%s') AND f_geometry_column = lower('%s'))"
 #ifdef WORKAROUND_SQLITE3_BUGS
                     " OR 0"
 #endif
-                    ,pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
+                    ,pszEscapedTableName, SQLEscapeLiteral(pszGeomCol).c_str());
 
         sqlite3 *hDB = poDS->GetDB();
-        int nRowCount = 0, nColCount = 0;
+        int nRowCount = 0;
+        int nColCount = 0;
         char **papszResult = NULL;
 
         sqlite3_get_table( hDB, osSQL.c_str(), &papszResult,
                         &nRowCount, &nColCount, NULL );
 
         /* Make it a Unix timestamp */
-        int nYear, nMonth, nDay, nHour, nMinute;
-        float fSecond;
+        int nYear = 0;
+        int nMonth = 0;
+        int nDay = 0;
+        char chSep = 0;
+        int nHour = 0;
+        int nMinute = 0;
+        float fSecond = 0.0f;
         if( nRowCount == 1 && nColCount == 1 && papszResult[1] != NULL &&
-            sscanf( papszResult[1], "%04d-%02d-%02dT%02d:%02d:%f",
-                    &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond ) == 6 )
+            sscanf( papszResult[1], "%04d-%02d-%02d%c%02d:%02d:%f",
+                    &nYear, &nMonth, &nDay, &chSep, &nHour, &nMinute, &fSecond ) == 7 )
         {
             osLastEvtDate = papszResult[1];
         }
@@ -3528,16 +3252,16 @@ void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
         sqlite3_free_table( papszResult );
         papszResult = NULL;
 
-        if( osLastEvtDate.size() == 0 )
+        if( osLastEvtDate.empty() )
             return;
 
         osSQL.Printf("SELECT last_verified, row_count, extent_min_x, extent_min_y, "
                     "extent_max_x, extent_max_y FROM geometry_columns_statistics WHERE "
-                    "(f_table_name = '%s' AND f_geometry_column = '%s')"
+                    "(f_table_name = lower('%s') AND f_geometry_column = lower('%s'))"
 #ifdef WORKAROUND_SQLITE3_BUGS
                     " OR 0"
 #endif
-                    ,pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
+                    ,pszEscapedTableName, SQLEscapeLiteral(pszGeomCol).c_str());
 
         nRowCount = 0;
         nColCount = 0;
@@ -3545,8 +3269,8 @@ void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
                         &nRowCount, &nColCount, NULL );
 
         if( nRowCount == 1 && nColCount == 6 && papszResult[6] != NULL &&
-            sscanf( papszResult[6], "%04d-%02d-%02dT%02d:%02d:%f",
-                    &nYear, &nMonth, &nDay, &nHour, &nMinute, &fSecond ) == 6 )
+            sscanf( papszResult[6], "%04d-%02d-%02d%c%02d:%02d:%f",
+                    &nYear, &nMonth, &nDay, &chSep, &nHour, &nMinute, &fSecond ) == 7 )
         {
             CPLString osLastVerified(papszResult[6]);
 
@@ -3574,7 +3298,7 @@ void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
                     }
                     else
                     {
-                        CPLDebug("SQLite", "Layer %s feature count : " CPL_FRMT_GIB,
+                        CPLDebug("SQLITE", "Layer %s feature count : " CPL_FRMT_GIB,
                                     pszTableName, nFeatureCount);
                     }
                 }
@@ -3587,10 +3311,15 @@ void OGRSQLiteTableLayer::LoadStatisticsSpatialite4DB()
                     poGeomFieldDefn->oCachedExtent.MinY = CPLAtof(pszMinY);
                     poGeomFieldDefn->oCachedExtent.MaxX = CPLAtof(pszMaxX);
                     poGeomFieldDefn->oCachedExtent.MaxY = CPLAtof(pszMaxY);
-                    CPLDebug("SQLite", "Layer %s extent : %s,%s,%s,%s",
+                    CPLDebug("SQLITE", "Layer %s extent : %s,%s,%s,%s",
                                 pszTableName, pszMinX,pszMinY,pszMaxX,pszMaxY);
                 }
             }
+            else
+            {
+                CPLDebug("SQLite", "Statistics in %s is not up-to-date",
+                         pszTableName);
+            }
         }
 
         sqlite3_free_table( papszResult );
@@ -3628,7 +3357,7 @@ void OGRSQLiteTableLayer::LoadStatistics()
                  "((table_name = '%s' AND geometry_column = '%s') OR "
                  "(table_name = 'ALL-TABLES' AND geometry_column = 'ALL-GEOMETRY-COLUMNS')) AND "
                  "event = 'UpdateLayerStatistics'",
-                 pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
+                 pszEscapedTableName, SQLEscapeLiteral(pszGeomCol).c_str());
 
     sqlite3 *hDB = poDS->GetDB();
     int nRowCount = 0, nColCount = 0;
@@ -3661,7 +3390,7 @@ void OGRSQLiteTableLayer::LoadStatistics()
     {
         osSQL.Printf("SELECT row_count, extent_min_x, extent_min_y, extent_max_x, extent_max_y "
                         "FROM layer_statistics WHERE table_name = '%s' AND geometry_column = '%s'",
-                        pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
+                        pszEscapedTableName, SQLEscapeLiteral(pszGeomCol).c_str());
 
         sqlite3_free_table( papszResult );
         papszResult = NULL;
@@ -3684,7 +3413,7 @@ void OGRSQLiteTableLayer::LoadStatistics()
             if( pszRowCount != NULL )
             {
                 nFeatureCount = CPLAtoGIntBig( pszRowCount );
-                CPLDebug("SQLite", "Layer %s feature count : " CPL_FRMT_GIB,
+                CPLDebug("SQLITE", "Layer %s feature count : " CPL_FRMT_GIB,
                             pszTableName, nFeatureCount);
             }
 
@@ -3697,7 +3426,7 @@ void OGRSQLiteTableLayer::LoadStatistics()
                 poGeomFieldDefn->oCachedExtent.MinY = CPLAtof(pszMinY);
                 poGeomFieldDefn->oCachedExtent.MaxX = CPLAtof(pszMaxX);
                 poGeomFieldDefn->oCachedExtent.MaxY = CPLAtof(pszMaxY);
-                CPLDebug("SQLite", "Layer %s extent : %s,%s,%s,%s",
+                CPLDebug("SQLITE", "Layer %s extent : %s,%s,%s,%s",
                             pszTableName, pszMinX,pszMinY,pszMaxX,pszMaxY);
             }
         }
@@ -3716,7 +3445,7 @@ void OGRSQLiteTableLayer::LoadStatistics()
 int OGRSQLiteTableLayer::SaveStatistics()
 {
     if( !bStatisticsNeedsToBeFlushed || !poDS->IsSpatialiteDB()  ||
-        !poDS->IsSpatialiteLoaded() || poDS->HasSpatialite4Layout() )
+        !poDS->IsSpatialiteLoaded() || !poDS->GetUpdate() )
         return -1;
     if( GetLayerDefn()->GetGeomFieldCount() != 1 )
         return -1;
@@ -3727,51 +3456,106 @@ int OGRSQLiteTableLayer::SaveStatistics()
     sqlite3 *hDB = poDS->GetDB();
     char* pszErrMsg = NULL;
 
+    // Update geometry_columns_time.
+    if( !poGeomFieldDefn->aosDisabledTriggers.empty() )
+    {
+        char* pszSQL3 = sqlite3_mprintf(
+            "UPDATE geometry_columns_time "
+            "SET last_insert = strftime('%%Y-%%m-%%dT%%H:%%M:%%fZ', 'now') "
+            "WHERE Lower(f_table_name) = Lower('%q') AND "
+            "Lower(f_geometry_column) = Lower('%q')",
+            pszTableName, poGeomFieldDefn->GetNameRef());
+        if( sqlite3_exec( poDS->GetDB(), pszSQL3, NULL, NULL, &pszErrMsg) != SQLITE_OK )
+        {
+            CPLDebug("SQLITE", "%s: error %s",
+                     pszSQL3, pszErrMsg ? pszErrMsg : "unknown");
+            sqlite3_free( pszErrMsg );
+            pszErrMsg = NULL;
+        }
+        sqlite3_free( pszSQL3 );
+    }
+
+    const char* pszStatTableName =
+        poDS->HasSpatialite4Layout() ? "geometry_columns_statistics":
+                                       "layer_statistics";
+    if( SQLGetInteger( poDS->GetDB(),
+            CPLSPrintf("SELECT 1 FROM sqlite_master WHERE type IN "
+                       "('view', 'table') AND name = '%s'",
+                       pszStatTableName), NULL ) == 0 )
+    {
+        return TRUE;
+    }
+    const char* pszFTableName =
+        poDS->HasSpatialite4Layout() ? "f_table_name" : "table_name";
+    const char* pszFGeometryColumn =
+        poDS->HasSpatialite4Layout() ? "f_geometry_column" : "geometry_column";
+    CPLString osTableName(pszTableName);
+    CPLString osGeomCol(pszGeomCol);
+    const char* pszNowValue = "";
+    if( poDS->HasSpatialite4Layout() )
+    {
+        osTableName = osTableName.tolower();
+        osGeomCol = osGeomCol.tolower();
+        pszNowValue = ", strftime('%Y-%m-%dT%H:%M:%fZ','now')";
+    }
     if( nFeatureCount >= 0 )
     {
         /* Update or add entry in the layer_statistics table */
         if( poGeomFieldDefn->bCachedExtentIsValid )
         {
-            osSQL.Printf("INSERT OR REPLACE INTO layer_statistics (raster_layer, "
-                            "table_name, geometry_column, row_count, extent_min_x, "
-                            "extent_min_y, extent_max_x, extent_max_y) VALUES ("
-                            "0, '%s', '%s', " CPL_FRMT_GIB ", %s, %s, %s, %s)",
-                            pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str(),
+            osSQL.Printf("INSERT OR REPLACE INTO %s (%s"
+                            "%s, %s, row_count, extent_min_x, "
+                            "extent_min_y, extent_max_x, extent_max_y%s) VALUES ("
+                            "%s'%s', '%s', " CPL_FRMT_GIB ", %.18g, %.18g, %.18g, %.18g%s)",
+                            pszStatTableName,
+                            poDS->HasSpatialite4Layout() ? "" : "raster_layer, ",
+                            pszFTableName,
+                            pszFGeometryColumn,
+                            poDS->HasSpatialite4Layout() ? ", last_verified": "",
+                            poDS->HasSpatialite4Layout() ? "" : "0 ,",
+                            SQLEscapeLiteral(osTableName).c_str(),
+                            SQLEscapeLiteral(osGeomCol).c_str(),
                             nFeatureCount,
-                            // Insure that only Decimal.Points are used, never local settings such as Decimal.Comma.
-                            CPLString().FormatC(poGeomFieldDefn->oCachedExtent.MinX,"%.18g").c_str(),
-                            CPLString().FormatC(poGeomFieldDefn->oCachedExtent.MinY,"%.18g").c_str(),
-                            CPLString().FormatC(poGeomFieldDefn->oCachedExtent.MaxX,"%.18g").c_str(),
-                            CPLString().FormatC(poGeomFieldDefn->oCachedExtent.MaxY,"%.18g").c_str());
+                            poGeomFieldDefn->oCachedExtent.MinX,
+                            poGeomFieldDefn->oCachedExtent.MinY,
+                            poGeomFieldDefn->oCachedExtent.MaxX,
+                            poGeomFieldDefn->oCachedExtent.MaxY,
+                            pszNowValue
+                        );
         }
         else
         {
-            osSQL.Printf("INSERT OR REPLACE INTO layer_statistics (raster_layer, "
-                            "table_name, geometry_column, row_count, extent_min_x, "
-                            "extent_min_y, extent_max_x, extent_max_y) VALUES ("
-                            "0, '%s', '%s', " CPL_FRMT_GIB ", NULL, NULL, NULL, NULL)",
-                            pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str(),
-                            nFeatureCount);
+            osSQL.Printf("INSERT OR REPLACE INTO %s (%s"
+                            "%s, %s, row_count, extent_min_x, "
+                            "extent_min_y, extent_max_x, extent_max_y%s) VALUES ("
+                            "%s'%s', '%s', " CPL_FRMT_GIB ", NULL, NULL, NULL, NULL%s)",
+                            pszStatTableName,
+                            poDS->HasSpatialite4Layout() ? "" : "raster_layer, ",
+                            pszFTableName,
+                            pszFGeometryColumn,
+                            poDS->HasSpatialite4Layout() ? ", last_verified": "",
+                            poDS->HasSpatialite4Layout() ? "" : "0 ,",
+                            SQLEscapeLiteral(osTableName).c_str(),
+                            SQLEscapeLiteral(osGeomCol).c_str(),
+                            nFeatureCount,
+                            pszNowValue
+                        );
         }
     }
     else
     {
         /* Remove any existing entry in layer_statistics if for some reason */
         /* we know that it will out-of-sync */
-        osSQL.Printf("DELETE FROM layer_statistics WHERE "
-                     "table_name = '%s' AND geometry_column = '%s'",
-                     pszEscapedTableName, OGRSQLiteEscape(pszGeomCol).c_str());
+        osSQL.Printf("DELETE FROM %s WHERE "
+                     "%s = '%s' AND %s = '%s'",
+                     pszStatTableName,
+                     pszFTableName,
+                     SQLEscapeLiteral(osTableName).c_str(),
+                     pszFGeometryColumn,
+                     SQLEscapeLiteral(osGeomCol).c_str());
     }
 
-    int rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, &pszErrMsg );
-    if( rc != SQLITE_OK )
-    {
-        CPLDebug("SQLITE", "Error %s", pszErrMsg ? pszErrMsg : "unknown");
-        sqlite3_free( pszErrMsg );
-        return FALSE;
-    }
-    else
-        return TRUE;
+    return SQLCommand( hDB, osSQL) == OGRERR_NONE;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteutility.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteutility.cpp
new file mode 100644
index 0000000..f64fab7
--- /dev/null
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteutility.cpp
@@ -0,0 +1,332 @@
+/******************************************************************************
+ *
+ * Project:  GeoPackage Translator
+ * Purpose:  Utility functions for OGR GeoPackage driver.
+ * Author:   Paul Ramsey, pramsey at boundlessgeo.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Paul Ramsey <pramsey at boundlessgeo.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrsqliteutility.h"
+#include "ogr_p.h"
+
+CPL_CVSID("$Id: ogrsqliteutility.cpp 37809 2017-03-20 15:28:41Z rouault $");
+
+/* Runs a SQL command and ignores the result (good for INSERT/UPDATE/CREATE) */
+OGRErr SQLCommand(sqlite3 * poDb, const char * pszSQL)
+{
+    CPLAssert( poDb != NULL );
+    CPLAssert( pszSQL != NULL );
+
+    char *pszErrMsg = NULL;
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GPKG", "exec(%s)", pszSQL);
+#endif
+    int rc = sqlite3_exec(poDb, pszSQL, NULL, NULL, &pszErrMsg);
+
+    if ( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "sqlite3_exec(%s) failed: %s",
+                  pszSQL, pszErrMsg ? pszErrMsg : "" );
+        sqlite3_free( pszErrMsg );
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+OGRErr SQLResultInit(SQLResult * poResult)
+{
+    poResult->papszResult = NULL;
+    poResult->pszErrMsg = NULL;
+    poResult->nRowCount = 0;
+    poResult->nColCount = 0;
+    poResult->rc = 0;
+    return OGRERR_NONE;
+}
+
+OGRErr SQLQuery(sqlite3 * poDb, const char * pszSQL, SQLResult * poResult)
+{
+    CPLAssert( poDb != NULL );
+    CPLAssert( pszSQL != NULL );
+    CPLAssert( poResult != NULL );
+
+    SQLResultInit(poResult);
+
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GPKG", "get_table(%s)", pszSQL);
+#endif
+    poResult->rc = sqlite3_get_table(
+        poDb, pszSQL,
+        &(poResult->papszResult),
+        &(poResult->nRowCount),
+        &(poResult->nColCount),
+        &(poResult->pszErrMsg) );
+
+    if( poResult->rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "sqlite3_get_table(%s) failed: %s", pszSQL, poResult->pszErrMsg );
+        return OGRERR_FAILURE;
+    }
+
+    return OGRERR_NONE;
+}
+
+OGRErr SQLResultFree(SQLResult * poResult)
+{
+    if ( poResult->papszResult )
+        sqlite3_free_table(poResult->papszResult);
+
+    if ( poResult->pszErrMsg )
+        sqlite3_free(poResult->pszErrMsg);
+
+    return OGRERR_NONE;
+}
+
+const char* SQLResultGetValue(const SQLResult * poResult, int iColNum, int iRowNum)
+{
+    CPLAssert( poResult != NULL );
+
+    const int nCols = poResult->nColCount;
+#ifdef DEBUG
+    const int nRows = poResult->nRowCount;
+
+    CPLAssert( iColNum >= 0 && iColNum < nCols );
+    CPLAssert( iRowNum >= 0 && iRowNum < nRows );
+#endif
+    return poResult->papszResult[ nCols + iRowNum * nCols + iColNum ];
+}
+
+int SQLResultGetValueAsInteger(const SQLResult * poResult, int iColNum, int iRowNum)
+{
+    const char *pszValue = SQLResultGetValue(poResult, iColNum, iRowNum);
+    if ( ! pszValue )
+        return 0;
+
+    return atoi(pszValue);
+}
+
+/* Returns the first row of first column of SQL as integer */
+GIntBig SQLGetInteger64(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
+{
+    CPLAssert( poDb != NULL );
+
+    sqlite3_stmt *poStmt = NULL;
+
+    /* Prepare the SQL */
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GPKG", "get(%s)", pszSQL);
+#endif
+    int rc = sqlite3_prepare_v2(poDb, pszSQL, -1, &poStmt, NULL);
+    if ( rc != SQLITE_OK )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined, "sqlite3_prepare_v2(%s) failed: %s",
+                  pszSQL, sqlite3_errmsg( poDb ) );
+        if ( err ) *err = OGRERR_FAILURE;
+        return 0;
+    }
+
+    /* Execute and fetch first row */
+    rc = sqlite3_step(poStmt);
+    if ( rc != SQLITE_ROW )
+    {
+        if ( err ) *err = OGRERR_FAILURE;
+        sqlite3_finalize(poStmt);
+        return 0;
+    }
+
+    /* Read the integer from the row */
+    GIntBig i = sqlite3_column_int64(poStmt, 0);
+    sqlite3_finalize(poStmt);
+
+    if ( err ) *err = OGRERR_NONE;
+    return i;
+}
+
+int SQLGetInteger(sqlite3 * poDb, const char * pszSQL, OGRErr *err)
+{
+    return static_cast<int>(SQLGetInteger64(poDb, pszSQL, err));
+}
+
+int SQLiteFieldFromOGR(OGRFieldType eType)
+{
+    switch(eType)
+    {
+        case OFTInteger:
+            return SQLITE_INTEGER;
+        case OFTReal:
+            return SQLITE_FLOAT;
+        case OFTString:
+            return SQLITE_TEXT;
+        case OFTBinary:
+            return SQLITE_BLOB;
+        case OFTDate:
+            return SQLITE_TEXT;
+        case OFTDateTime:
+            return SQLITE_TEXT;
+        default:
+            return 0;
+    }
+}
+
+/************************************************************************/
+/*                             SQLUnescape()                            */
+/************************************************************************/
+
+CPLString SQLUnescape(const char* pszVal)
+{
+    char chQuoteChar = pszVal[0];
+    if( chQuoteChar != '\'' && chQuoteChar != '"' )
+        return pszVal;
+
+    CPLString osRet;
+    pszVal ++;
+    while( *pszVal != '\0' )
+    {
+        if( *pszVal == chQuoteChar )
+        {
+            if( pszVal[1] == chQuoteChar )
+                pszVal ++;
+            else
+                break;
+        }
+        osRet += *pszVal;
+        pszVal ++;
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                          SQLEscapeLiteral()                          */
+/************************************************************************/
+
+CPLString SQLEscapeLiteral( const char *pszLiteral )
+{
+    CPLString osVal;
+    for( int i = 0; pszLiteral[i] != '\0'; i++ )
+    {
+        if ( pszLiteral[i] == '\'' )
+            osVal += '\'';
+        osVal += pszLiteral[i];
+    }
+    return osVal;
+}
+
+/************************************************************************/
+/*                           SQLEscapeName()                            */
+/************************************************************************/
+
+CPLString SQLEscapeName(const char* pszName)
+{
+    CPLString osRet;
+    while( *pszName != '\0' )
+    {
+        if( *pszName == '"' )
+            osRet += "\"\"";
+        else
+            osRet += *pszName;
+        pszName ++;
+    }
+    return osRet;
+}
+
+/************************************************************************/
+/*                             SQLTokenize()                            */
+/************************************************************************/
+
+char** SQLTokenize( const char* pszStr )
+{
+    char** papszTokens = NULL;
+    bool bInQuote = false;
+    char chQuoteChar = '\0';
+    bool bInSpace = true;
+    CPLString osCurrentToken;
+    while( *pszStr != '\0' )
+    {
+        if( *pszStr == ' ' && !bInQuote )
+        {
+            if( !bInSpace )
+            {
+                papszTokens = CSLAddString(papszTokens, osCurrentToken);
+                osCurrentToken.clear();
+            }
+            bInSpace = true;
+        }
+        else if( (*pszStr == '(' || *pszStr == ')' || *pszStr == ',')  && !bInQuote )
+        {
+            if( !bInSpace )
+            {
+                papszTokens = CSLAddString(papszTokens, osCurrentToken);
+                osCurrentToken.clear();
+            }
+            osCurrentToken.clear();
+            osCurrentToken += *pszStr;
+            papszTokens = CSLAddString(papszTokens, osCurrentToken);
+            osCurrentToken.clear();
+            bInSpace = true;
+        }
+        else if( *pszStr == '"' || *pszStr == '\'' )
+        {
+            if( bInQuote && *pszStr == chQuoteChar && pszStr[1] == chQuoteChar )
+            {
+                osCurrentToken += *pszStr;
+                osCurrentToken += *pszStr;
+                pszStr += 2;
+                continue;
+            }
+            else if( bInQuote && *pszStr == chQuoteChar )
+            {
+                osCurrentToken += *pszStr;
+                papszTokens = CSLAddString(papszTokens, osCurrentToken);
+                osCurrentToken.clear();
+                bInSpace = true;
+                bInQuote = false;
+                chQuoteChar = '\0';
+            }
+            else if( bInQuote )
+            {
+                osCurrentToken += *pszStr;
+            }
+            else
+            {
+                chQuoteChar = *pszStr;
+                osCurrentToken.clear();
+                osCurrentToken += chQuoteChar;
+                bInQuote = true;
+                bInSpace = false;
+            }
+        }
+        else
+        {
+            osCurrentToken += *pszStr;
+            bInSpace = false;
+        }
+        pszStr ++;
+    }
+
+    if( !osCurrentToken.empty() )
+        papszTokens = CSLAddString(papszTokens, osCurrentToken);
+
+    return papszTokens;
+}
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteutility.h b/ogr/ogrsf_frmts/sqlite/ogrsqliteutility.h
new file mode 100644
index 0000000..afa4ef8
--- /dev/null
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteutility.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ * $Id: ogrsqliteutility.h 37809 2017-03-20 15:28:41Z rouault $
+ *
+ * Project:  GeoPackage Translator
+ * Purpose:  Utility header for OGR GeoPackage driver.
+ * Author:   Paul Ramsey, pramsey at boundlessgeo.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2013, Paul Ramsey <pramsey at boundlessgeo.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef OGR_SQLITEUTILITY_H_INCLUDED
+#define OGR_SQLITEUTILITY_H_INCLUDED
+
+#include "ogr_core.h"
+#include "cpl_string.h"
+#include "sqlite3.h"
+
+typedef struct
+{
+    char** papszResult;
+    int nRowCount;
+    int nColCount;
+    char *pszErrMsg;
+    int rc;
+} SQLResult;
+
+
+OGRErr              SQLCommand(sqlite3 *poDb, const char * pszSQL);
+int                 SQLGetInteger(sqlite3 * poDb, const char * pszSQL, OGRErr *err);
+GIntBig             SQLGetInteger64(sqlite3 * poDb, const char * pszSQL, OGRErr *err);
+
+OGRErr              SQLResultInit(SQLResult * poResult);
+OGRErr              SQLQuery(sqlite3 *poDb, const char * pszSQL, SQLResult * poResult);
+const char*         SQLResultGetValue(const SQLResult * poResult, int iColumnNum, int iRowNum);
+int                 SQLResultGetValueAsInteger(const SQLResult * poResult, int iColNum, int iRowNum);
+OGRErr              SQLResultFree(SQLResult * poResult);
+
+int                 SQLiteFieldFromOGR(OGRFieldType eType);
+
+/* To escape literals. The returned string doesn't contain the surrounding single quotes */
+CPLString           SQLEscapeLiteral( const char *pszLiteral );
+
+/* To escape table or field names. The returned string doesn't contain the surrounding double quotes */
+CPLString           SQLEscapeName( const char* pszName );
+
+/* Remove leading ' or " and unescape in that case. Or return string unmodified */
+CPLString           SQLUnescape(const char* pszVal);
+
+char**              SQLTokenize( const char* pszSQL );
+
+#endif // OGR_SQLITEUTILITY_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
index cda99f7..fe64a5c 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevfs.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqlitevfs.cpp 33884 2016-04-03 18:50:15Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements SQLite VFS
@@ -30,7 +29,7 @@
 #include "cpl_atomic_ops.h"
 #include "ogr_sqlite.h"
 
-CPL_CVSID("$Id: ogrsqlitevfs.cpp 33884 2016-04-03 18:50:15Z rouault $");
+CPL_CVSID("$Id: ogrsqlitevfs.cpp 37594 2017-03-04 15:52:52Z rouault $");
 
 #ifdef DEBUG_IO
 # define DEBUG_ONLY
@@ -40,8 +39,6 @@ CPL_CVSID("$Id: ogrsqlitevfs.cpp 33884 2016-04-03 18:50:15Z rouault $");
 
 //#define DEBUG_IO 1
 
-#ifdef HAVE_SQLITE_VFS
-
 typedef struct
 {
     char                       szVFSName[64];
@@ -215,7 +212,7 @@ static const sqlite3_io_methods OGRSQLiteIOMethods =
     NULL,  // xShmLock
     NULL,  // xShmBarrier
     NULL,  // xShmUnmap
-#if SQLITE_VERSION_NUMBER >= 3008002L /* perhaps older too ? */
+#if SQLITE_VERSION_NUMBER >= 3007017L /* perhaps older too ? */
     NULL,  // xFetch
     NULL,  // xUnfetch
 #endif
@@ -295,11 +292,13 @@ static int OGRSQLiteVFSAccess (DEBUG_ONLY sqlite3_vfs* pVFS,
     CPLDebug("SQLITE", "OGRSQLiteVFSAccess(%s, %d)", zName, flags);
 #endif
     VSIStatBufL sStatBufL;
-    int nRet;
+    int nRet;  // TODO(schwehr): Cleanup nRet and pResOut.  bools?
     if (flags == SQLITE_ACCESS_EXISTS)
     {
         /* Do not try to check the presence of a journal or a wal on /vsicurl ! */
-        if ( STARTS_WITH(zName, "/vsicurl/") &&
+        if ( (STARTS_WITH(zName, "/vsicurl/") ||
+              STARTS_WITH(zName, "/vsitar/") ||
+              STARTS_WITH(zName, "/vsizip/")) &&
              ((strlen(zName) > strlen("-journal") &&
                strcmp(zName + strlen(zName) - strlen("-journal"), "-journal") == 0) ||
               (strlen(zName) > strlen("-wal") &&
@@ -308,7 +307,9 @@ static int OGRSQLiteVFSAccess (DEBUG_ONLY sqlite3_vfs* pVFS,
             nRet = -1;
         }
         else
+        {
             nRet = VSIStatExL(zName, &sStatBufL, VSI_STAT_EXISTS_FLAG);
+        }
     }
     else if (flags == SQLITE_ACCESS_READ)
     {
@@ -325,7 +326,9 @@ static int OGRSQLiteVFSAccess (DEBUG_ONLY sqlite3_vfs* pVFS,
             VSIFCloseL(fp);
     }
     else
+    {
         nRet = -1;
+    }
     *pResOut = (nRet == 0);
     return SQLITE_OK;
 }
@@ -500,5 +503,3 @@ sqlite3_vfs* OGRSQLiteCreateVFS(pfnNotifyFileOpenedType pfn, void* pfnUserData)
 
     return pMyVFS;
 }
-
-#endif // HAVE_SQLITE_VFS
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
index 881727d..8143fb9 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqliteviewlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqliteviewlayer.cpp 36600 2016-12-01 13:59:11Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRSQLiteViewLayer class, access to an existing spatialite view.
@@ -30,32 +29,28 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_sqlite.h"
+#include "ogrsqliteutility.h"
 #include <string>
 
-CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 36600 2016-12-01 13:59:11Z rouault $");
+CPL_CVSID("$Id: ogrsqliteviewlayer.cpp 37809 2017-03-20 15:28:41Z rouault $");
 
 /************************************************************************/
 /*                        OGRSQLiteViewLayer()                         */
 /************************************************************************/
 
-OGRSQLiteViewLayer::OGRSQLiteViewLayer( OGRSQLiteDataSource *poDSIn )
-
+OGRSQLiteViewLayer::OGRSQLiteViewLayer( OGRSQLiteDataSource *poDSIn ) :
+    bHasCheckedSpatialIndexTable(FALSE),
+    eGeomFormat(OSGF_None),
+    bHasSpatialIndex(FALSE),
+    pszViewName(NULL),
+    pszEscapedTableName(NULL),
+    pszEscapedUnderlyingTableName(NULL),
+    bLayerDefnError(FALSE),
+    poUnderlyingLayer(NULL)
 {
     poDS = poDSIn;
-
     iNextShapeId = 0;
-
     poFeatureDefn = NULL;
-    pszViewName = NULL;
-    pszEscapedTableName = NULL;
-    pszEscapedUnderlyingTableName = NULL;
-    bHasSpatialIndex = FALSE;
-
-    bHasCheckedSpatialIndexTable = FALSE;
-
-    bLayerDefnError = FALSE;
-    eGeomFormat = OSGF_None;
-    poUnderlyingLayer = NULL;
 }
 
 /************************************************************************/
@@ -82,7 +77,7 @@ CPLErr OGRSQLiteViewLayer::Initialize( const char *pszViewNameIn,
                                        const char *pszUnderlyingGeometryColumn)
 
 {
-    this->pszViewName = CPLStrdup(pszViewNameIn);
+    pszViewName = CPLStrdup(pszViewNameIn);
     SetDescription( pszViewName );
 
     osGeomColumn = pszViewGeometry;
@@ -95,10 +90,8 @@ CPLErr OGRSQLiteViewLayer::Initialize( const char *pszViewNameIn,
     osUnderlyingGeometryColumn = pszUnderlyingGeometryColumn;
     poUnderlyingLayer = NULL;
 
-    //this->bHasM = bHasM;
-
-    pszEscapedTableName = CPLStrdup(OGRSQLiteEscape(pszViewName));
-    pszEscapedUnderlyingTableName = CPLStrdup(OGRSQLiteEscape(pszUnderlyingTableName));
+    pszEscapedTableName = CPLStrdup(SQLEscapeLiteral(pszViewName));
+    pszEscapedUnderlyingTableName = CPLStrdup(SQLEscapeLiteral(pszUnderlyingTableName));
 
     return CE_None;
 }
@@ -171,10 +164,8 @@ OGRwkbGeometryType OGRSQLiteViewLayer::GetGeomType()
 
 CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
 {
-    int rc;
     sqlite3 *hDB = poDS->GetDB();
     sqlite3_stmt *hColStmt = NULL;
-    const char *pszSQL;
 
     OGRSQLiteLayer* l_poUnderlyingLayer = GetUnderlyingLayer();
     if (l_poUnderlyingLayer == NULL)
@@ -203,17 +194,19 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
         return CE_Failure;
     }
 
-    this->bHasSpatialIndex = l_poUnderlyingLayer->HasSpatialIndex(nUnderlyingLayerGeomFieldIndex);
+    bHasSpatialIndex =
+        l_poUnderlyingLayer->HasSpatialIndex(nUnderlyingLayerGeomFieldIndex);
 
 /* -------------------------------------------------------------------- */
 /*      Get the column definitions for this table.                      */
 /* -------------------------------------------------------------------- */
     hColStmt = NULL;
-    pszSQL = CPLSPrintf( "SELECT \"%s\", * FROM '%s' LIMIT 1",
-                         OGRSQLiteEscapeName(pszFIDColumn).c_str(),
-                         pszEscapedTableName );
+    const char *pszSQL =
+        CPLSPrintf( "SELECT \"%s\", * FROM '%s' LIMIT 1",
+                    SQLEscapeName(pszFIDColumn).c_str(),
+                    pszEscapedTableName );
 
-    rc = sqlite3_prepare( hDB, pszSQL, -1, &hColStmt, NULL );
+    int rc = sqlite3_prepare_v2( hDB, pszSQL, -1, &hColStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -268,7 +261,6 @@ CPLErr OGRSQLiteViewLayer::EstablishFeatureDefn()
 OGRErr OGRSQLiteViewLayer::ResetStatement()
 
 {
-    int rc;
     CPLString osSQL;
 
     ClearStatement();
@@ -276,25 +268,24 @@ OGRErr OGRSQLiteViewLayer::ResetStatement()
     iNextShapeId = 0;
 
     osSQL.Printf( "SELECT \"%s\", * FROM '%s' %s",
-                  OGRSQLiteEscapeName(pszFIDColumn).c_str(),
+                  SQLEscapeName(pszFIDColumn).c_str(),
                   pszEscapedTableName,
                   osWHERE.c_str() );
 
-    rc = sqlite3_prepare( poDS->GetDB(), osSQL, static_cast<int>(osSQL.size()),
-		          &hStmt, NULL );
+    const int rc =
+        sqlite3_prepare_v2( poDS->GetDB(), osSQL, static_cast<int>(osSQL.size()),
+                         &hStmt, NULL );
 
     if( rc == SQLITE_OK )
     {
-	return OGRERR_NONE;
-    }
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "In ResetStatement(): sqlite3_prepare(%s):\n  %s",
-                  osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
-        hStmt = NULL;
-        return OGRERR_FAILURE;
+        return OGRERR_NONE;
     }
+
+    CPLError( CE_Failure, CPLE_AppDefined,
+              "In ResetStatement(): sqlite3_prepare_v2(%s):\n  %s",
+              osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
+    hStmt = NULL;
+    return OGRERR_FAILURE;
 }
 
 /************************************************************************/
@@ -331,26 +322,26 @@ OGRFeature *OGRSQLiteViewLayer::GetFeature( GIntBig nFeatureId )
 /*      Setup explicit query statement to fetch the record we want.     */
 /* -------------------------------------------------------------------- */
     CPLString osSQL;
-    int rc;
 
     ClearStatement();
 
     iNextShapeId = nFeatureId;
 
     osSQL.Printf( "SELECT \"%s\", * FROM '%s' WHERE \"%s\" = %d",
-                  OGRSQLiteEscapeName(pszFIDColumn).c_str(),
+                  SQLEscapeName(pszFIDColumn).c_str(),
                   pszEscapedTableName,
-                  OGRSQLiteEscapeName(pszFIDColumn).c_str(),
+                  SQLEscapeName(pszFIDColumn).c_str(),
                   (int) nFeatureId );
 
     CPLDebug( "OGR_SQLITE", "exec(%s)", osSQL.c_str() );
 
-    rc = sqlite3_prepare( poDS->GetDB(), osSQL, static_cast<int>(osSQL.size()),
-                          &hStmt, NULL );
+    const int rc =
+        sqlite3_prepare_v2( poDS->GetDB(), osSQL, static_cast<int>(osSQL.size()),
+                         &hStmt, NULL );
     if( rc != SQLITE_OK )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "In GetFeature(): sqlite3_prepare(%s):\n  %s",
+                  "In GetFeature(): sqlite3_prepare_v2(%s):\n  %s",
                   osSQL.c_str(), sqlite3_errmsg(poDS->GetDB()) );
 
         return NULL;
@@ -386,7 +377,6 @@ OGRErr OGRSQLiteViewLayer::SetAttributeFilter( const char *pszQuery )
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
@@ -423,15 +413,16 @@ CPLString OGRSQLiteViewLayer::GetSpatialWhere(int iGeomCol,
         if (!bHasCheckedSpatialIndexTable)
         {
             bHasCheckedSpatialIndexTable = TRUE;
-            char **papszResult;
-            int nRowCount, nColCount;
+            char **papszResult = NULL;
+            int nRowCount = 0;
+            int nColCount = 0;
             char *pszErrMsg = NULL;
 
             CPLString osSQL;
             osSQL.Printf("SELECT name FROM sqlite_master "
                         "WHERE name='idx_%s_%s'",
                         pszEscapedUnderlyingTableName,
-                        OGRSQLiteEscape(osUnderlyingGeometryColumn).c_str());
+                        SQLEscapeLiteral(osUnderlyingGeometryColumn).c_str());
 
             int  rc = sqlite3_get_table( poDS->GetDB(), osSQL.c_str(),
                                         &papszResult, &nRowCount,
@@ -458,22 +449,21 @@ CPLString OGRSQLiteViewLayer::GetSpatialWhere(int iGeomCol,
         if (bHasSpatialIndex)
         {
             return FormatSpatialFilterFromRTree(poFilterGeom,
-                CPLSPrintf("\"%s\"", OGRSQLiteEscapeName(pszFIDColumn).c_str()),
+                CPLSPrintf("\"%s\"", SQLEscapeName(pszFIDColumn).c_str()),
                 pszEscapedUnderlyingTableName,
-                OGRSQLiteEscape(osUnderlyingGeometryColumn).c_str());
+                SQLEscapeLiteral(osUnderlyingGeometryColumn).c_str());
         }
         else
         {
             CPLDebug("SQLITE", "Count not find idx_%s_%s layer. Disabling spatial index",
                      pszEscapedUnderlyingTableName, osUnderlyingGeometryColumn.c_str());
         }
-
     }
 
     if( poFilterGeom != NULL && poDS->IsSpatialiteLoaded() )
     {
         return FormatSpatialFilterFromMBR(poFilterGeom,
-            OGRSQLiteEscapeName(poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef()).c_str());
+            SQLEscapeName(poFeatureDefn->GetGeomFieldDefn(iGeomCol)->GetNameRef()).c_str());
     }
 
     return "";
@@ -493,15 +483,15 @@ void OGRSQLiteViewLayer::BuildWhere()
 
     CPLString osSpatialWHERE = GetSpatialWhere(m_iGeomFieldFilter,
                                                m_poFilterGeom);
-    if (osSpatialWHERE.size() != 0)
+    if (!osSpatialWHERE.empty())
     {
         osWHERE = "WHERE ";
         osWHERE += osSpatialWHERE;
     }
 
-    if( osQuery.size() > 0 )
+    if( !osQuery.empty() )
     {
-        if( osWHERE.size() == 0 )
+        if( osWHERE.empty() )
         {
             osWHERE = "WHERE ";
             osWHERE += osQuery;
@@ -526,7 +516,7 @@ int OGRSQLiteViewLayer::TestCapability( const char * pszCap )
         return FALSE;
 
     if (EQUAL(pszCap,OLCFastFeatureCount))
-        return m_poFilterGeom == NULL || osGeomColumn.size() == 0 ||
+        return m_poFilterGeom == NULL || osGeomColumn.empty() ||
                bHasSpatialIndex;
 
     else if (EQUAL(pszCap,OLCFastSpatialFilter))
@@ -557,10 +547,9 @@ GIntBig OGRSQLiteViewLayer::GetFeatureCount( int bForce )
 /* -------------------------------------------------------------------- */
 /*      Form count SQL.                                                 */
 /* -------------------------------------------------------------------- */
-    const char *pszSQL;
-
-    pszSQL = CPLSPrintf( "SELECT count(*) FROM '%s' %s",
-                          pszEscapedTableName, osWHERE.c_str() );
+    const char *pszSQL =
+        CPLSPrintf( "SELECT count(*) FROM '%s' %s",
+                    pszEscapedTableName, osWHERE.c_str() );
 
 /* -------------------------------------------------------------------- */
 /*      Execute.                                                        */
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
index 1953c24..f5353cd 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsqlitevirtualogr.cpp 33554 2016-02-25 16:00:10Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite Virtual Table module using OGR layers
@@ -31,11 +30,10 @@
 #include "ogr_api.h"
 #include "swq.h"
 #include "ogr_p.h"
+#include "ogrsqliteutility.h"
 #include <map>
 #include <vector>
 
-#ifdef HAVE_SQLITE_VFS
-
 /************************************************************************/
 /*                           OGR2SQLITE_Register()                      */
 /************************************************************************/
@@ -122,12 +120,14 @@ class OGR2SQLITEModule
 /************************************************************************/
 
 OGR2SQLITEModule::OGR2SQLITEModule() :
-    hDB(NULL), poDS(NULL), poSQLiteDS(NULL), hHandleSQLFunctions(NULL)
-{
 #ifdef DEBUG
-    pDummy = CPLMalloc(1);
+    pDummy(CPLMalloc(1)),
 #endif
-}
+    hDB(NULL),
+    poDS(NULL),
+    poSQLiteDS(NULL),
+    hHandleSQLFunctions(NULL)
+{}
 
 /************************************************************************/
 /*                          ~OGR2SQLITEModule                           */
@@ -139,7 +139,7 @@ OGR2SQLITEModule::~OGR2SQLITEModule()
     CPLFree(pDummy);
 #endif
 
-    for(int i=0;i<(int)apoExtraDS.size();i++)
+    for( int i = 0; i < static_cast<int>(apoExtraDS.size()); i++ )
         delete apoExtraDS[i];
 
     OGRSQLiteUnregisterSQLFunctions(hHandleSQLFunctions);
@@ -195,9 +195,10 @@ int OGR2SQLITEModule::Setup(GDALDataset* poDSIn,
 /*                            FetchSRSId()                              */
 /************************************************************************/
 
-int OGR2SQLITEModule::FetchSRSId(OGRSpatialReference* poSRS)
+// TODO(schwehr): Refactor FetchSRSId to be much simpler.
+int OGR2SQLITEModule::FetchSRSId( OGRSpatialReference* poSRS )
 {
-    int nSRSId;
+    int nSRSId = -1;
 
     if( poSQLiteDS != NULL )
     {
@@ -207,7 +208,6 @@ int OGR2SQLITEModule::FetchSRSId(OGRSpatialReference* poSRS)
     }
     else
     {
-        nSRSId = -1;
         if( poSRS != NULL )
         {
             const char* pszAuthorityName = poSRS->GetAuthorityName(NULL);
@@ -262,7 +262,7 @@ OGRLayer* OGR2SQLITEModule::GetLayerForVTable(const char* pszVTableName)
         /* table since we know that we have managed to create it before */
         if( sqlite3_exec(hDB,
                      CPLSPrintf("PRAGMA table_info(\"%s\")",
-                                OGRSQLiteEscapeName(pszVTableName).c_str()),
+                                SQLEscapeName(pszVTableName).c_str()),
                      NULL, NULL, NULL) == SQLITE_OK )
         {
             poLayer = oMapVTableToOGRLayer[pszVTableName];
@@ -321,7 +321,6 @@ typedef struct
     int            nGeomBLOBLen;
 } OGR2SQLITE_vtab_cursor;
 
-
 /************************************************************************/
 /*                  OGR2SQLITE_GetNameForGeometryColumn()               */
 /************************************************************************/
@@ -356,21 +355,20 @@ static int OGR2SQLITEDetectSuspiciousUsage(sqlite3* hDB,
                                            char**pzErr)
 {
     char **papszResult = NULL;
-    int nRowCount = 0, nColCount = 0;
-    int i;
-
-    std::vector<CPLString> aosDatabaseNames;
+    int nRowCount = 0;
+    int nColCount = 0;
 
     /* Collect database names */
     sqlite3_get_table( hDB, "PRAGMA database_list",
                        &papszResult, &nRowCount, &nColCount, NULL );
 
-    for(i = 1; i <= nRowCount; i++)
+    std::vector<CPLString> aosDatabaseNames;
+    for( int i = 1; i <= nRowCount; i++ )
     {
         const char* pszUnescapedName = papszResult[i * nColCount + 1];
         aosDatabaseNames.push_back(
             CPLSPrintf("\"%s\".sqlite_master",
-                       OGRSQLiteEscapeName(pszUnescapedName).c_str()));
+                       SQLEscapeName(pszUnescapedName).c_str()));
     }
 
     /* Add special database (just in case, not sure it is really needed) */
@@ -380,20 +378,19 @@ static int OGR2SQLITEDetectSuspiciousUsage(sqlite3* hDB,
     papszResult = NULL;
 
     /* Check the triggers of each database */
-    for(i = 0; i < (int)aosDatabaseNames.size(); i++ )
+    for( int i = 0; i < (int)aosDatabaseNames.size(); i++ )
     {
         nRowCount = 0; nColCount = 0;
 
-        const char* pszSQL;
-
-        pszSQL = CPLSPrintf("SELECT name, sql FROM %s "
-                            "WHERE (type = 'trigger' OR type = 'view') AND ("
-                            "sql LIKE '%%%s%%' OR "
-                            "sql LIKE '%%\"%s\"%%' OR "
-                            "sql LIKE '%%ogr_layer_%%' )",
-                            aosDatabaseNames[i].c_str(),
-                            pszVirtualTableName,
-                            OGRSQLiteEscapeName(pszVirtualTableName).c_str());
+        const char* pszSQL =
+            CPLSPrintf("SELECT name, sql FROM %s "
+                       "WHERE (type = 'trigger' OR type = 'view') AND ("
+                       "sql LIKE '%%%s%%' OR "
+                       "sql LIKE '%%\"%s\"%%' OR "
+                       "sql LIKE '%%ogr_layer_%%' )",
+                       aosDatabaseNames[i].c_str(),
+                       pszVirtualTableName,
+                       SQLEscapeName(pszVirtualTableName).c_str());
 
         sqlite3_get_table( hDB, pszSQL, &papszResult, &nRowCount, &nColCount,
                            NULL );
@@ -433,26 +430,21 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
                              int argc, const char *const*argv,
                              sqlite3_vtab **ppVTab, char**pzErr)
 {
+#ifdef DEBUG_OGR2SQLITE
+    CPLDebug("OGR2SQLITE", "ConnectCreate(%s)", argv[2]);
+#endif
+
     OGR2SQLITEModule* poModule = (OGR2SQLITEModule*) pAux;
     OGRLayer* poLayer = NULL;
-    GDALDataset* poDS = NULL;
     int bExposeOGR_STYLE = FALSE;
     int bCloseDS = FALSE;
     int bInternalUse = FALSE;
     int bExposeOGRNativeData = FALSE;
-    int i;
-
-#ifdef DEBUG_OGR2SQLITE
-    CPLDebug("OGR2SQLITE", "ConnectCreate(%s)", argv[2]);
-#endif
-
-    /*for(i=0;i<argc;i++)
-        printf("[%d] %s\n", i, argv[i]);*/
 
 /* -------------------------------------------------------------------- */
 /*      If called from ogrexecutesql.cpp                                */
 /* -------------------------------------------------------------------- */
-    poDS = poModule->GetDS();
+    GDALDataset* poDS = poModule->GetDS();
     if( poDS != NULL && (argc == 6 || argc == 7) &&
         CPLGetValueType(argv[3]) == CPL_VALUE_INTEGER )
     {
@@ -468,7 +460,7 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
                 return SQLITE_ERROR;
             }
         }
-        CPLString osLayerName(OGRSQLiteParamsUnquote(argv[4]));
+        CPLString osLayerName(SQLUnescape(argv[4]));
 
         poLayer = poDS->GetLayerByName(osLayerName);
         if( poLayer == NULL )
@@ -478,8 +470,8 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
             return SQLITE_ERROR;
         }
 
-        bExposeOGR_STYLE = atoi(OGRSQLiteParamsUnquote(argv[5]));
-        bExposeOGRNativeData = (argc == 7) ? atoi(OGRSQLiteParamsUnquote(argv[6])) : FALSE;
+        bExposeOGR_STYLE = atoi(SQLUnescape(argv[5]));
+        bExposeOGRNativeData = (argc == 7) ? atoi(SQLUnescape(argv[6])) : FALSE;
     }
 #ifdef VIRTUAL_OGR_DYNAMIC_EXTENSION_ENABLED
 /* -------------------------------------------------------------------- */
@@ -500,8 +492,8 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
             return SQLITE_ERROR;
         }
 
-        CPLString osDSName(OGRSQLiteParamsUnquote(argv[3]));
-        CPLString osUpdate(OGRSQLiteParamsUnquote((argc >= 5) ? argv[4] : "0"));
+        CPLString osDSName(SQLUnescape(argv[3]));
+        CPLString osUpdate(SQLUnescape((argc >= 5) ? argv[4] : "0"));
 
         if( !EQUAL(osUpdate, "1") && !EQUAL(osUpdate, "0") )
         {
@@ -522,7 +514,7 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
         CPLString osLayerName;
         if( argc >= 6 )
         {
-            osLayerName = OGRSQLiteParamsUnquote(argv[5]);
+            osLayerName = SQLUnescape(argv[5]);
             poLayer = poDS->GetLayerByName(osLayerName);
         }
         else
@@ -556,11 +548,11 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
 
         if( argc >= 7 )
         {
-            bExposeOGR_STYLE = atoi(OGRSQLiteParamsUnquote(argv[6]));
+            bExposeOGR_STYLE = atoi(SQLUnescape(argv[6]));
         }
         if( argc >= 8 )
         {
-            bExposeOGRNativeData = atoi(OGRSQLiteParamsUnquote(argv[7]));
+            bExposeOGRNativeData = atoi(SQLUnescape(argv[7]));
         }
 
         bCloseDS = TRUE;
@@ -569,7 +561,7 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
     OGR2SQLITE_vtab* vtab =
                 (OGR2SQLITE_vtab*) CPLCalloc(1, sizeof(OGR2SQLITE_vtab));
     /* We do not need to fill the non-extended fields */
-    vtab->pszVTableName = CPLStrdup(OGRSQLiteEscapeName(argv[2]));
+    vtab->pszVTableName = CPLStrdup(SQLEscapeName(argv[2]));
     vtab->poModule = poModule;
     vtab->poDS = poDS;
     vtab->bCloseDS = bCloseDS;
@@ -583,23 +575,23 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
     CPLString osSQL;
     osSQL = "CREATE TABLE ";
     osSQL += "\"";
-    osSQL += OGRSQLiteEscapeName(argv[2]);
+    osSQL += SQLEscapeName(argv[2]);
     osSQL += "\"";
     osSQL += "(";
 
-    int bAddComma = FALSE;
+    bool bAddComma = false;
 
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
-    for(i=0;i<poFDefn->GetFieldCount();i++)
+    for( int i = 0; i < poFDefn->GetFieldCount(); i++ )
     {
         if( bAddComma )
             osSQL += ",";
-        bAddComma = TRUE;
+        bAddComma = true;
 
         OGRFieldDefn* poFieldDefn = poFDefn->GetFieldDefn(i);
 
         osSQL += "\"";
-        osSQL += OGRSQLiteEscapeName(poFieldDefn->GetNameRef());
+        osSQL += SQLEscapeName(poFieldDefn->GetNameRef());
         osSQL += "\"";
         osSQL += " ";
         osSQL += OGRSQLiteFieldDefnToSQliteFieldDefn(poFieldDefn,
@@ -608,24 +600,24 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
 
     if( bAddComma )
         osSQL += ",";
-    bAddComma = TRUE;
+    bAddComma = true;
     osSQL += "OGR_STYLE VARCHAR";
     if( !bExposeOGR_STYLE )
      osSQL += " HIDDEN";
 
-    for(i=0;i<poFDefn->GetGeomFieldCount();i++)
+    for( int i = 0; i < poFDefn->GetGeomFieldCount(); i++ )
     {
         if( bAddComma )
             osSQL += ",";
-        bAddComma = TRUE;
+        bAddComma = true;
 
         OGRGeomFieldDefn* poFieldDefn = poFDefn->GetGeomFieldDefn(i);
 
         osSQL += "\"";
         if( i == 0 )
-            osSQL += OGRSQLiteEscapeName(OGR2SQLITE_GetNameForGeometryColumn(poLayer));
+            osSQL += SQLEscapeName(OGR2SQLITE_GetNameForGeometryColumn(poLayer));
         else
-            osSQL += OGRSQLiteEscapeName(poFieldDefn->GetNameRef());
+            osSQL += SQLEscapeName(poFieldDefn->GetNameRef());
         osSQL += "\"";
         osSQL += " BLOB";
 
@@ -681,16 +673,15 @@ int OGR2SQLITE_ConnectCreate(sqlite3* hDB, void *pAux,
 static
 int OGR2SQLITE_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pIndex)
 {
-    int i;
     OGR2SQLITE_vtab* pMyVTab = (OGR2SQLITE_vtab*) pVTab;
     OGRFeatureDefn* poFDefn = pMyVTab->poLayer->GetLayerDefn();
 
 #ifdef DEBUG_OGR2SQLITE
     CPLString osQueryPatternUsable, osQueryPatternNotUsable;
-    for (i = 0; i < pIndex->nConstraint; i++)
+    for( int i = 0; i < pIndex->nConstraint; i++ )
     {
         int iCol = pIndex->aConstraint[i].iColumn;
-        const char* pszFieldName;
+        const char* pszFieldName = NULL;
         if( iCol == -1 )
             pszFieldName = "FID";
         else if( iCol >= 0 && iCol < poFDefn->GetFieldCount() )
@@ -698,7 +689,7 @@ int OGR2SQLITE_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pIndex)
         else
             pszFieldName = "unknown_field";
 
-        const char* pszOp;
+        const char* pszOp = NULL;
         switch(pIndex->aConstraint[i].op)
         {
             case SQLITE_INDEX_CONSTRAINT_EQ: pszOp = " = "; break;
@@ -712,14 +703,14 @@ int OGR2SQLITE_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pIndex)
 
         if (pIndex->aConstraint[i].usable)
         {
-            if (osQueryPatternUsable.size()) osQueryPatternUsable += " AND ";
+            if (!osQueryPatternUsable.empty() ) osQueryPatternUsable += " AND ";
             osQueryPatternUsable += pszFieldName;
             osQueryPatternUsable += pszOp;
             osQueryPatternUsable += "?";
         }
         else
         {
-            if (osQueryPatternNotUsable.size()) osQueryPatternNotUsable += " AND ";
+            if (!osQueryPatternNotUsable.empty() ) osQueryPatternNotUsable += " AND ";
             osQueryPatternNotUsable += pszFieldName;
             osQueryPatternNotUsable += pszOp;
             osQueryPatternNotUsable += "?";
@@ -730,7 +721,7 @@ int OGR2SQLITE_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pIndex)
 #endif
 
     int nConstraints = 0;
-    for (i = 0; i < pIndex->nConstraint; i++)
+    for( int i = 0; i < pIndex->nConstraint; i++ )
     {
         int iCol = pIndex->aConstraint[i].iColumn;
         if (pIndex->aConstraint[i].usable &&
@@ -760,7 +751,7 @@ int OGR2SQLITE_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pIndex)
 
         nConstraints = 0;
 
-        for (i = 0; i < pIndex->nConstraint; i++)
+        for( int i = 0; i < pIndex->nConstraint; i++ )
         {
             if (pIndex->aConstraintUsage[i].omit)
             {
@@ -769,7 +760,7 @@ int OGR2SQLITE_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pIndex)
                 panConstraints[2 * nConstraints + 2] =
                                             pIndex->aConstraint[i].op;
 
-                nConstraints ++;
+                nConstraints++;
             }
         }
     }
@@ -926,8 +917,7 @@ int OGR2SQLITE_Filter(sqlite3_vtab_cursor* pCursor,
 
     OGRFeatureDefn* poFDefn = pMyCursor->poLayer->GetLayerDefn();
 
-    int i;
-    for (i = 0; i < argc; i++)
+    for( int i = 0; i < argc; i++ )
     {
         int nCol = panConstraints[2 * i + 1];
         OGRFieldDefn* poFieldDefn = NULL;
@@ -944,7 +934,7 @@ int OGR2SQLITE_Filter(sqlite3_vtab_cursor* pCursor,
         if( poFieldDefn != NULL )
         {
             const char* pszFieldName = poFieldDefn->GetNameRef();
-            char ch;
+            char ch = '\0';
             int bNeedsQuoting = swq_is_reserved_keyword(pszFieldName);
             for(int j = 0; !bNeedsQuoting &&
                            (ch = pszFieldName[j]) != '\0'; j++ )
@@ -956,7 +946,7 @@ int OGR2SQLITE_Filter(sqlite3_vtab_cursor* pCursor,
             if( bNeedsQuoting )
             {
                 osAttributeFilter += '"';
-                osAttributeFilter += OGRSQLiteEscapeName(pszFieldName);
+                osAttributeFilter += SQLEscapeName(pszFieldName);
                 osAttributeFilter += '"';
             }
             else
@@ -965,7 +955,9 @@ int OGR2SQLITE_Filter(sqlite3_vtab_cursor* pCursor,
             }
         }
         else
+        {
             osAttributeFilter += "FID";
+        }
 
         switch(panConstraints[2 * i + 2])
         {
@@ -997,7 +989,7 @@ int OGR2SQLITE_Filter(sqlite3_vtab_cursor* pCursor,
         else if (sqlite3_value_type (argv[i]) == SQLITE_TEXT)
         {
             osAttributeFilter += "'";
-            osAttributeFilter += OGRSQLiteEscape((const char*) sqlite3_value_text (argv[i]));
+            osAttributeFilter += SQLEscapeLiteral((const char*) sqlite3_value_text (argv[i]));
             osAttributeFilter += "'";
         }
         else
@@ -1015,7 +1007,7 @@ int OGR2SQLITE_Filter(sqlite3_vtab_cursor* pCursor,
              osAttributeFilter.c_str());
 #endif
 
-    if( pMyCursor->poLayer->SetAttributeFilter( osAttributeFilter.size() ?
+    if( pMyCursor->poLayer->SetAttributeFilter( !osAttributeFilter.empty() ?
                             osAttributeFilter.c_str() : NULL) != OGRERR_NONE )
     {
         sqlite3_free(pMyCursor->pVTab->zErrMsg);
@@ -1092,11 +1084,11 @@ int OGR2SQLITE_Eof(sqlite3_vtab_cursor* pCursor)
 
     if( pMyCursor->nFeatureCount < 0 )
     {
-        return (pMyCursor->poFeature == NULL);
+        return pMyCursor->poFeature == NULL;
     }
     else
     {
-        return ( pMyCursor->nNextWishedIndex >= pMyCursor->nFeatureCount );
+        return pMyCursor->nNextWishedIndex >= pMyCursor->nFeatureCount;
     }
 }
 
@@ -1168,15 +1160,15 @@ static
 int OGR2SQLITE_Column(sqlite3_vtab_cursor* pCursor,
                       sqlite3_context* pContext, int nCol)
 {
-    OGR2SQLITE_vtab_cursor* pMyCursor = (OGR2SQLITE_vtab_cursor*) pCursor;
-    OGRFeature* poFeature;
 #ifdef DEBUG_OGR2SQLITE
     CPLDebug("OGR2SQLITE", "Column %d", nCol);
 #endif
 
+    OGR2SQLITE_vtab_cursor* pMyCursor = (OGR2SQLITE_vtab_cursor*) pCursor;
+
     OGR2SQLITE_GoToWishedIndex(pMyCursor);
 
-    poFeature = pMyCursor->poFeature;
+    OGRFeature* poFeature = pMyCursor->poFeature;
     if( poFeature == NULL)
         return SQLITE_ERROR;
 
@@ -1276,7 +1268,7 @@ int OGR2SQLITE_Column(sqlite3_vtab_cursor* pCursor,
     {
         return SQLITE_ERROR;
     }
-    else if( !poFeature->IsFieldSet(nCol) )
+    else if( !poFeature->IsFieldSetAndNotNull(nCol) )
     {
         sqlite3_result_null(pContext);
         return SQLITE_OK;
@@ -1301,7 +1293,7 @@ int OGR2SQLITE_Column(sqlite3_vtab_cursor* pCursor,
 
         case OFTBinary:
         {
-            int nSize;
+            int nSize = 0;
             GByte* pBlob = poFeature->GetFieldAsBinary(nCol, &nSize);
             sqlite3_result_blob(pContext, pBlob, nSize, SQLITE_TRANSIENT);
             break;
@@ -1330,8 +1322,13 @@ int OGR2SQLITE_Column(sqlite3_vtab_cursor* pCursor,
 
         case OFTTime:
         {
-            int nYear, nMonth, nDay, nHour, nMinute, nTZ;
-            float fSecond;
+            int nYear = 0;
+            int nMonth = 0;
+            int nDay = 0;
+            int nHour = 0;
+            int nMinute = 0;
+            int nTZ = 0;
+            float fSecond = 0.0f;
             poFeature->GetFieldAsDateTime(nCol, &nYear, &nMonth, &nDay,
                                         &nHour, &nMinute, &fSecond, &nTZ );
             char szBuffer[64];
@@ -1415,8 +1412,8 @@ static OGRFeature* OGR2SQLITE_FeatureFromArgs(OGRLayer* poLayer,
                                               sqlite3_value **argv)
 {
     OGRFeatureDefn* poLayerDefn = poLayer->GetLayerDefn();
-    int nFieldCount = poLayerDefn->GetFieldCount();
-    int nGeomFieldCount = poLayerDefn->GetGeomFieldCount();
+    const int nFieldCount = poLayerDefn->GetFieldCount();
+    const int nGeomFieldCount = poLayerDefn->GetGeomFieldCount();
     if( argc != 2 + nFieldCount + 1 + nGeomFieldCount + 2)
     {
         CPLDebug("OGR2SQLITE", "Did not get expect argument count : %d, %d", argc,
@@ -1425,11 +1422,13 @@ static OGRFeature* OGR2SQLITE_FeatureFromArgs(OGRLayer* poLayer,
     }
 
     OGRFeature* poFeature = new OGRFeature(poLayerDefn);
-    int i;
-    for(i = 0; i < nFieldCount; i++)
+    for( int i = 0; i < nFieldCount; i++ )
     {
         switch( sqlite3_value_type(argv[2 + i]) )
         {
+            case SQLITE_NULL:
+                poFeature->SetFieldNull(i);
+                break;
             case SQLITE_INTEGER:
                 poFeature->SetField(i, sqlite3_value_int64(argv[2 + i]));
                 break;
@@ -1474,9 +1473,9 @@ static OGRFeature* OGR2SQLITE_FeatureFromArgs(OGRLayer* poLayer,
         poFeature->SetStyleString((const char*) sqlite3_value_text(argv[nStyleIdx]));
     }
 
-    for(i = 0; i < nGeomFieldCount; i++)
+    for( int i = 0; i < nGeomFieldCount; i++ )
     {
-        int nGeomFieldIdx = 2 + nFieldCount + 1 + i;
+        const int nGeomFieldIdx = 2 + nFieldCount + 1 + i;
         if( sqlite3_value_type(argv[nGeomFieldIdx]) == SQLITE_BLOB )
         {
             GByte* pabyBlob = (GByte *) sqlite3_value_blob (argv[nGeomFieldIdx]);
@@ -1644,7 +1643,7 @@ OGRLayer* OGR2SQLITE_GetLayer(const char* pszFuncName,
     OGR2SQLITEModule* poModule =
                     (OGR2SQLITEModule*) sqlite3_user_data(pContext);
 
-    OGRLayer* poLayer = poModule->GetLayerForVTable(OGRSQLiteParamsUnquote(pszVTableName));
+    OGRLayer* poLayer = poModule->GetLayerForVTable(SQLUnescape(pszVTableName));
     if( poLayer == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -1834,7 +1833,10 @@ typedef struct
     OGRLayer      *poLayer;
     OGRFeature    *poFeature;
     int            bHasSetBounds;
-    double         dfMinX, dfMinY, dfMaxX, dfMaxY;
+    double         dfMinX;
+    double         dfMinY;
+    double         dfMaxX;
+    double         dfMaxY;
 } OGR2SQLITESpatialIndex_vtab_cursor;
 
 /************************************************************************/
@@ -1846,23 +1848,16 @@ int OGR2SQLITESpatialIndex_ConnectCreate(sqlite3* hDB, void *pAux,
                              int argc, const char *const*argv,
                              sqlite3_vtab **ppVTab, char**pzErr)
 {
-    OGR2SQLITEModule* poModule = (OGR2SQLITEModule*) pAux;
-    OGRLayer* poLayer = NULL;
-    OGRDataSource* poDS = NULL;
-    int bCloseDS = FALSE;
-    int i;
-
 #ifdef DEBUG_OGR2SQLITE
     CPLDebug("OGR2SQLITE", "ConnectCreate(%s)", argv[2]);
 #endif
 
-    /*for(i=0;i<argc;i++)
-        printf("[%d] %s\n", i, argv[i]);*/
+    OGR2SQLITEModule* poModule = (OGR2SQLITEModule*) pAux;
 
 /* -------------------------------------------------------------------- */
 /*      If called from ogrexecutesql.cpp                                */
 /* -------------------------------------------------------------------- */
-    poDS = poModule->GetDS();
+    OGRDataSource* poDS = poModule->GetDS();
     if( poDS == NULL )
         return SQLITE_ERROR;
 
@@ -1890,11 +1885,10 @@ int OGR2SQLITESpatialIndex_ConnectCreate(sqlite3* hDB, void *pAux,
     {
         return SQLITE_ERROR;
     }
-    bCloseDS = TRUE;
 
-    CPLString osLayerName(OGRSQLiteParamsUnquote(argv[4]));
+    CPLString osLayerName(SQLUnescape(argv[4]));
 
-    poLayer = poDS->GetLayerByName(osLayerName);
+    OGRLayer* poLayer = poDS->GetLayerByName(osLayerName);
     if( poLayer == NULL )
     {
         *pzErr = sqlite3_mprintf( "Cannot find layer '%s' in '%s'",
@@ -1905,10 +1899,10 @@ int OGR2SQLITESpatialIndex_ConnectCreate(sqlite3* hDB, void *pAux,
     OGR2SQLITESpatialIndex_vtab* vtab =
                 (OGR2SQLITESpatialIndex_vtab*) CPLCalloc(1, sizeof(OGR2SQLITESpatialIndex_vtab));
     // We do not need to fill the non-extended fields.
-    vtab->pszVTableName = CPLStrdup(OGRSQLiteEscapeName(argv[2]));
+    vtab->pszVTableName = CPLStrdup(SQLEscapeName(argv[2]));
     vtab->poModule = poModule;
     vtab->poDS = poDS;
-    vtab->bCloseDS = bCloseDS;
+    vtab->bCloseDS = TRUE;
     vtab->poLayer = poLayer;
     vtab->nMyRef = 0;
 
@@ -1917,20 +1911,20 @@ int OGR2SQLITESpatialIndex_ConnectCreate(sqlite3* hDB, void *pAux,
     CPLString osSQL;
     osSQL = "CREATE TABLE ";
     osSQL += "\"";
-    osSQL += OGRSQLiteEscapeName(argv[2]);
+    osSQL += SQLEscapeName(argv[2]);
     osSQL += "\"";
     osSQL += "(";
 
-    int bAddComma = FALSE;
+    bool bAddComma = false;
 
     for(i=0;i<5;i++)
     {
         if( bAddComma )
             osSQL += ",";
-        bAddComma = TRUE;
+        bAddComma = true;
 
         osSQL += "\"";
-        osSQL += OGRSQLiteEscapeName(OGRSQLiteParamsUnquote(argv[5+i]));
+        osSQL += SQLEscapeName(SQLUnescape(argv[5+i]));
         osSQL += "\"";
         osSQL += " ";
         osSQL += (i == 0) ? "INTEGER" : "FLOAT";
@@ -1960,33 +1954,34 @@ int OGR2SQLITESpatialIndex_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pI
     CPLDebug("OGR2SQLITE", "BestIndex");
 #endif
 
-    int i;
-
-    int bMinX = FALSE, bMinY = FALSE, bMaxX = FALSE, bMaxY = FALSE;
+    bool bMinX = false;
+    bool bMinY = false;
+    bool bMaxX = false;
+    bool bMaxY = false;
 
-    for (i = 0; i < pIndex->nConstraint; i++)
+    for( int i = 0; i < pIndex->nConstraint; i++ )
     {
         int iCol = pIndex->aConstraint[i].iColumn;
         /* MinX */
         if( !bMinX && iCol == 1 && pIndex->aConstraint[i].usable &&
             (pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_LE ||
                 pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_LT) )
-            bMinX = TRUE;
+            bMinX = true;
         /* MaxX */
         else if( !bMaxX && iCol == 2 && pIndex->aConstraint[i].usable &&
             (pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_GE ||
                 pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_GT) )
-            bMaxX = TRUE;
+            bMaxX = true;
         /* MinY */
         else if( !bMinY && iCol == 3 && pIndex->aConstraint[i].usable &&
             (pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_LE ||
                 pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_LT) )
-            bMinY = TRUE;
+            bMinY = true;
         /* MaxY */
         else if( !bMaxY && iCol == 4 && pIndex->aConstraint[i].usable &&
             (pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_GE ||
                 pIndex->aConstraint[i].op == SQLITE_INDEX_CONSTRAINT_GT) )
-            bMaxY = TRUE;
+            bMaxY = true;
         else
             break;
     }
@@ -1996,7 +1991,7 @@ int OGR2SQLITESpatialIndex_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pI
         CPLAssert( pIndex->nConstraint == 4 );
 
         int nConstraints = 0;
-        for (i = 0; i < pIndex->nConstraint; i++)
+        for( int i = 0; i < pIndex->nConstraint; i++ )
         {
             pIndex->aConstraintUsage[i].argvIndex = nConstraints + 1;
             pIndex->aConstraintUsage[i].omit = TRUE;
@@ -2010,7 +2005,7 @@ int OGR2SQLITESpatialIndex_BestIndex(sqlite3_vtab *pVTab, sqlite3_index_info* pI
 
         nConstraints = 0;
 
-        for (i = 0; i < pIndex->nConstraint; i++)
+        for( int i = 0; i < pIndex->nConstraint; i++ )
         {
             if (pIndex->aConstraintUsage[i].omit)
             {
@@ -2168,15 +2163,17 @@ int OGR2SQLITESpatialIndex_Filter(sqlite3_vtab_cursor* pCursor,
     if( nConstraints != argc )
         return SQLITE_ERROR;
 
-    int i;
-    double dfMinX = 0, dfMaxX = 0, dfMinY = 0, dfMaxY = 0;
-    for (i = 0; i < argc; i++)
+    double dfMinX = 0.0;
+    double dfMaxX = 0.0;
+    double dfMinY = 0.0;
+    double dfMaxY = 0.0;
+    for( int i = 0; i < argc; i++ )
     {
-        int nCol = panConstraints[2 * i + 1];
+        const int nCol = panConstraints[2 * i + 1];
         if( nCol < 0 )
             return SQLITE_ERROR;
 
-        double dfVal;
+        double dfVal = 0.0;
         if (sqlite3_value_type (argv[i]) == SQLITE_INTEGER)
             dfVal = sqlite3_value_int64 (argv[i]);
         else if (sqlite3_value_type (argv[i]) == SQLITE_FLOAT)
@@ -2241,7 +2238,7 @@ int OGR2SQLITESpatialIndex_Eof(sqlite3_vtab_cursor* pCursor)
     CPLDebug("OGR2SQLITE", "Eof");
 #endif
 
-    return (pMyCursor->poFeature == NULL);
+    return pMyCursor->poFeature == NULL;
 }
 
 /************************************************************************/
@@ -2252,13 +2249,13 @@ static
 int OGR2SQLITESpatialIndex_Column(sqlite3_vtab_cursor* pCursor,
                       sqlite3_context* pContext, int nCol)
 {
-    OGR2SQLITESpatialIndex_vtab_cursor* pMyCursor = (OGR2SQLITESpatialIndex_vtab_cursor*) pCursor;
-    OGRFeature* poFeature;
 #ifdef DEBUG_OGR2SQLITE
     CPLDebug("OGR2SQLITE", "Column %d", nCol);
 #endif
 
-    poFeature = pMyCursor->poFeature;
+    OGR2SQLITESpatialIndex_vtab_cursor* pMyCursor = (OGR2SQLITESpatialIndex_vtab_cursor*) pCursor;
+
+    OGRFeature* poFeature = pMyCursor->poFeature;
     if( poFeature == NULL)
         return SQLITE_ERROR;
 
@@ -2373,12 +2370,11 @@ static const struct sqlite3_module sOGR2SQLITESpatialIndex =
 
 int OGR2SQLITEModule::Setup(sqlite3* hDBIn)
 {
-    int rc;
+    hDB = hDBIn;
 
-    this->hDB = hDBIn;
-
-    rc = sqlite3_create_module_v2(hDB, "VirtualOGR", &sOGR2SQLITEModule, this,
-                                  OGR2SQLITEDestroyModule);
+    int rc =
+        sqlite3_create_module_v2(hDB, "VirtualOGR", &sOGR2SQLITEModule, this,
+                                 OGR2SQLITEDestroyModule);
     if( rc != SQLITE_OK )
         return FALSE;
 
@@ -2515,5 +2511,3 @@ int OGR2SQLITE_static_register (sqlite3 * hDB, char **pzErrMsg, void * _pApi)
 
     return SQLITE_OK;
 }
-
-#endif // HAVE_SQLITE_VFS
diff --git a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h
index 1c1b95f..e64f438 100644
--- a/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h
+++ b/ogr/ogrsf_frmts/sqlite/ogrsqlitevirtualogr.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrsqlitevirtualogr.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogrsqlitevirtualogr.h 37534 2017-03-01 16:50:58Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  SQLite Virtual Table module using OGR layers
@@ -32,8 +32,6 @@
 
 #include "ogr_sqlite.h"
 
-#ifdef HAVE_SQLITE_VFS
-
 class OGR2SQLITEModule;
 
 OGR2SQLITEModule* OGR2SQLITE_Setup(GDALDataset* poDS,
@@ -45,6 +43,4 @@ void OGR2SQLITE_Register();
 
 CPLString OGR2SQLITE_GetNameForGeometryColumn(OGRLayer* poLayer);
 
-#endif // HAVE_SQLITE_VFS
-
 #endif // OGR_SQLITE_VIRTUAL_OGR_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/sqlite/rasterlite2.cpp b/ogr/ogrsf_frmts/sqlite/rasterlite2.cpp
new file mode 100644
index 0000000..2bb8225
--- /dev/null
+++ b/ogr/ogrsf_frmts/sqlite/rasterlite2.cpp
@@ -0,0 +1,2464 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements RasterLite2 support class.
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ *
+ * CREDITS: The RasterLite2 module has been completely funded by:
+ * Regione Toscana - Settore Sistema Informativo Territoriale ed
+ * Ambientale (GDAL/RasterLite2 driver)
+ * CIG: 644544015A
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_sqlite.h"
+#include "ogrsqliteutility.h"
+#include "rasterlite2_header.h"
+
+#include <algorithm>
+
+#ifdef HAVE_RASTERLITE2
+
+static CPLString EscapeNameAndQuoteIfNeeded(const char* pszName)
+{
+    if( strchr(pszName, '"') == NULL && strchr(pszName, ':') == NULL )
+        return pszName;
+    return '"' + SQLEscapeName(pszName) + '"';
+}
+
+#endif
+
+/************************************************************************/
+/*                            OpenRaster()                              */
+/************************************************************************/
+
+bool OGRSQLiteDataSource::OpenRaster()
+{
+#ifdef HAVE_RASTERLITE2
+/* -------------------------------------------------------------------- */
+/*      Detect RasterLite2 coverages.                                   */
+/* -------------------------------------------------------------------- */
+    char** papszResults = NULL;
+    int nRowCount = 0, nColCount = 0;
+    int rc = sqlite3_get_table( hDB,
+                           "SELECT name FROM sqlite_master WHERE "
+                           "type = 'table' AND name = 'raster_coverages'",
+                           &papszResults, &nRowCount,
+                           &nColCount, NULL );
+    sqlite3_free_table(papszResults);
+    if( !(rc == SQLITE_OK && nRowCount == 1) )
+    {
+        return false;
+    }
+
+    papszResults = NULL;
+    nRowCount = 0;
+    nColCount = 0;
+    rc = sqlite3_get_table( hDB,
+                           "SELECT coverage_name, title, abstract "
+                           "FROM raster_coverages "
+                           "LIMIT 10000",
+                           &papszResults, &nRowCount,
+                           &nColCount, NULL );
+    if( !(rc == SQLITE_OK && nRowCount > 0) )
+    {
+        sqlite3_free_table(papszResults);
+        return false;
+    }
+    for(int i=0;i<nRowCount;++i)
+    {
+        const char * const* papszRow = papszResults + i * 3 + 3;
+        const char* pszCoverageName = papszRow[0];
+        const char* pszTitle = papszRow[1];
+        const char* pszAbstract = papszRow[2];
+        if( pszCoverageName != NULL )
+        {
+            rl2CoveragePtr cvg = rl2_create_coverage_from_dbms( 
+                                                            hDB,
+                                                            NULL,
+                                                            pszCoverageName );
+            if( cvg != NULL )
+            {
+                const int nIdx = m_aosSubDatasets.size() / 2 + 1;
+                m_aosSubDatasets.AddNameValue(
+                    CPLSPrintf("SUBDATASET_%d_NAME", nIdx),
+                    CPLSPrintf("RASTERLITE2:%s:%s",
+                        EscapeNameAndQuoteIfNeeded(m_pszFilename).c_str(),
+                        EscapeNameAndQuoteIfNeeded(pszCoverageName).c_str()));
+                CPLString osDesc("Coverage ");
+                osDesc += pszCoverageName;
+                if( pszTitle != NULL && pszTitle[0] != '\0' &&
+                    !EQUAL(pszTitle, "*** missing Title ***") )
+                {
+                    osDesc += ", title = ";
+                    osDesc += pszTitle;
+                }
+                if( pszAbstract != NULL && pszAbstract[0] != '\0' &&
+                    !EQUAL(pszAbstract, "*** missing Abstract ***") )
+                {
+                    osDesc += ", abstract = ";
+                    osDesc += pszAbstract;
+                }
+                m_aosSubDatasets.AddNameValue(
+                    CPLSPrintf("SUBDATASET_%d_DESC", nIdx), osDesc.c_str());
+
+                rl2_destroy_coverage(cvg);
+            }
+        }
+    }
+    sqlite3_free_table(papszResults);
+
+    if( m_aosSubDatasets.size() == 2 )
+    {
+        return OpenRasterSubDataset(
+                    m_aosSubDatasets.FetchNameValue( "SUBDATASET_1_NAME" ));
+    }
+
+    return !m_aosSubDatasets.empty();
+#else
+    return false;
+#endif
+}
+
+/************************************************************************/
+/*                        OpenRasterSubDataset()                        */
+/************************************************************************/
+
+bool OGRSQLiteDataSource::OpenRasterSubDataset(CPL_UNUSED
+                                               const char* pszConnectionId)
+{
+#ifdef HAVE_RASTERLITE2
+    if( !STARTS_WITH_CI( pszConnectionId, "RASTERLITE2:" ) )
+        return false;
+
+    char** papszTokens =
+        CSLTokenizeString2( pszConnectionId, ":", CSLT_HONOURSTRINGS );
+    if( CSLCount(papszTokens) < 3 )
+    {
+        CSLDestroy(papszTokens);
+        return false;
+    }
+
+    m_aosSubDatasets.Clear();
+
+    m_osCoverageName = SQLUnescape( papszTokens[2] );
+    m_nSectionId =
+        (CSLCount(papszTokens) >= 4) ? CPLAtoGIntBig( papszTokens[3] ) : -1;
+
+    CSLDestroy(papszTokens);
+
+    m_pRL2Coverage = rl2_create_coverage_from_dbms( hDB,
+                                                    NULL,
+                                                    m_osCoverageName );
+    if( m_pRL2Coverage == NULL )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Invalid coverage: %s", m_osCoverageName.c_str() );
+        return false;
+    }
+
+    bool bSingleSection = false;
+    if( m_nSectionId < 0 )
+    {
+        CPLString osSectionTableName( CPLSPrintf("%s_sections",
+                                                 m_osCoverageName.c_str()) );
+        int nRowCount2 = 0;
+        int nColCount2 = 0;
+        char** papszResults2 = NULL;
+        char* pszSQL = sqlite3_mprintf(
+                "SELECT section_id, section_name FROM \"%w\" "
+                "ORDER BY section_id "
+                "LIMIT 1000000",
+                osSectionTableName.c_str());
+        int rc = sqlite3_get_table( hDB,
+                pszSQL,
+                &papszResults2, &nRowCount2,
+                &nColCount2, NULL );
+        sqlite3_free(pszSQL);
+        if( rc == SQLITE_OK )
+        {
+            for( int j=0; j<nRowCount2; ++j )
+            {
+                const char * const* papszRow2 = papszResults2 + j * 2 + 2;
+                const char* pszSectionId = papszRow2[0];
+                const char* pszSectionName = papszRow2[1];
+                if( pszSectionName != NULL && pszSectionId != NULL )
+                {
+                    if( nRowCount2 > 1 )
+                    {
+                        const int nIdx = m_aosSubDatasets.size() / 2 + 1;
+                        m_aosSubDatasets.AddNameValue(
+                          CPLSPrintf("SUBDATASET_%d_NAME", nIdx),
+                          CPLSPrintf("RASTERLITE2:%s:%s:%s:%s",
+                            EscapeNameAndQuoteIfNeeded(m_pszFilename).c_str(),
+                            EscapeNameAndQuoteIfNeeded(m_osCoverageName).
+                                                                      c_str(),
+                            pszSectionId,
+                            EscapeNameAndQuoteIfNeeded(pszSectionName).
+                                                                     c_str()));
+                        m_aosSubDatasets.AddNameValue(
+                            CPLSPrintf("SUBDATASET_%d_DESC", nIdx),
+                            CPLSPrintf("Coverage %s, section %s / %s",
+                                    m_osCoverageName.c_str(),
+                                    pszSectionName,
+                                    pszSectionId));
+                    }
+                    else
+                    {
+                        m_nSectionId = CPLAtoGIntBig( pszSectionId );
+                        bSingleSection = true;
+                    }
+                }
+            }
+        }
+        sqlite3_free_table(papszResults2);
+    }
+
+    double dfXRes = 0.0;
+    double dfYRes = 0.0;
+
+    double dfMinX = 0.0;
+    double dfMinY = 0.0;
+    double dfMaxX = 0.0;
+    double dfMaxY = 0.0;
+    unsigned int nWidth = 0;
+    unsigned int nHeight = 0;
+
+    // Get extent and resolution
+    if( m_nSectionId >= 0 )
+    {
+        int ret = rl2_resolve_base_resolution_from_dbms(hDB,
+                                                        NULL,
+                                                        m_osCoverageName,
+                                                        TRUE, // by_section
+                                                        m_nSectionId,
+                                                        &dfXRes,
+                                                        &dfYRes );
+        if( ret != RL2_OK )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "rl2_resolve_base_resolution_from_dbms() failed / "
+                    "Invalid section: " CPL_FRMT_GIB, m_nSectionId );
+            return false;
+        }
+
+
+        ret = rl2_resolve_full_section_from_dbms( hDB,
+                                                  NULL,
+                                                  m_osCoverageName,
+                                                  m_nSectionId,
+                                                  dfXRes, dfYRes,
+                                                  &dfMinX, &dfMinY,
+                                                  &dfMaxX, &dfMaxY,
+                                                  &nWidth, &nHeight );
+        if( ret != RL2_OK || nWidth == 0 || nWidth > INT_MAX ||
+            nHeight == 0 || nHeight > INT_MAX )
+        {
+            CPLError( CE_Failure, CPLE_AppDefined,
+                    "rl2_resolve_full_section_from_dbms() failed / "
+                    "Invalid section: " CPL_FRMT_GIB, m_nSectionId );
+            return false;
+        }
+    }
+    else
+    {
+        rl2_get_coverage_resolution (m_pRL2Coverage, &dfXRes, &dfYRes);
+
+        char* pszSQL = sqlite3_mprintf(
+            "SELECT extent_minx, extent_miny, extent_maxx, extent_maxy "
+            "FROM raster_coverages WHERE "
+            "Lower(coverage_name) = Lower('%q') "
+            "LIMIT 1", m_osCoverageName.c_str() );
+        char** papszResults = NULL;
+        int nRowCount = 0;
+        int nColCount = 0;
+        int rc = sqlite3_get_table( hDB, pszSQL,
+                                    &papszResults, &nRowCount,
+                                    &nColCount, NULL );
+        sqlite3_free( pszSQL );
+        if( rc == SQLITE_OK )
+        {
+            if( nRowCount ==  1 )
+            {
+                const char* pszMinX = papszResults[4 + 0];
+                const char* pszMinY = papszResults[4 + 1];
+                const char* pszMaxX = papszResults[4 + 2];
+                const char* pszMaxY = papszResults[4 + 3];
+                if( pszMinX != NULL && pszMinY != NULL && pszMaxX != NULL &&
+                    pszMaxY != NULL )
+                {
+                    dfMinX = CPLAtof(pszMinX);
+                    dfMinY = CPLAtof(pszMinY);
+                    dfMaxX = CPLAtof(pszMaxX);
+                    dfMaxY = CPLAtof(pszMaxY);
+                }
+            }
+            sqlite3_free_table(papszResults);
+        }
+        double dfWidth = 0.5 + (dfMaxX - dfMinX) / dfXRes;
+        double dfHeight = 0.5 + (dfMaxY - dfMinY) / dfYRes;
+        if( dfWidth <= 0.5 || dfHeight <= 0.5 || dfWidth > INT_MAX ||
+            dfHeight > INT_MAX )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Invalid dimensions");
+            return false;
+        }
+        nWidth = static_cast<int>(dfWidth);
+        nHeight = static_cast<int>(dfHeight);
+    }
+
+    // Compute dimension and geotransform
+    nRasterXSize = static_cast<int>(nWidth);
+    nRasterYSize = static_cast<int>(nHeight);
+    m_bGeoTransformValid = true;
+    m_adfGeoTransform[0] = dfMinX;
+    m_adfGeoTransform[1] = (dfMaxX - dfMinX) / nRasterXSize;
+    m_adfGeoTransform[2] = 0.0;
+    m_adfGeoTransform[3] = dfMaxY;
+    m_adfGeoTransform[4] = 0.0;
+    m_adfGeoTransform[5] = -(dfMaxY - dfMinY) / nRasterYSize;
+
+    // Get SRS
+    int nSRID = 0;
+    if( rl2_get_coverage_srid(m_pRL2Coverage, &nSRID) == RL2_OK )
+    {
+        OGRSpatialReference* poSRS = FetchSRS( nSRID );
+        if( poSRS != NULL )
+        {
+            OGRSpatialReference oSRS(*poSRS);
+            char* pszWKT = NULL;
+            if( oSRS.EPSGTreatsAsLatLong() ||
+                oSRS.EPSGTreatsAsNorthingEasting() )
+            {
+                oSRS.GetRoot()->StripNodes( "AXIS" );
+            }
+            if( oSRS.exportToWkt( &pszWKT ) == OGRERR_NONE )
+            {
+                m_osProjection = pszWKT;
+                CPLFree(pszWKT);
+            }
+        }
+    }
+
+    // Get pixel information and number of bands
+    unsigned char nSampleType = 0;
+    unsigned char nPixelType = 0;
+    unsigned char l_nBands = 0;
+    rl2_get_coverage_type (m_pRL2Coverage,
+                           &nSampleType, &nPixelType, &l_nBands);
+    if( !GDALCheckBandCount(l_nBands, FALSE) )
+        return false;
+    int nBits = 0;
+    GDALDataType eDT = GDT_Unknown;
+    bool bSigned = false;
+    switch( nSampleType )
+    {
+        default:
+        case RL2_SAMPLE_UNKNOWN:
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Unknown sample type");
+            return false;
+        }
+        case RL2_SAMPLE_1_BIT:
+        {
+            if( nPixelType == RL2_PIXEL_MONOCHROME )
+            {
+                m_bPromote1BitAs8Bit = CPLFetchBool( papszOpenOptions,
+                                                     "1BIT_AS_8BIT", true );
+            }
+            nBits = 1;
+            eDT = GDT_Byte;
+            break;
+        }
+        case RL2_SAMPLE_2_BIT:
+        {
+            nBits = 2;
+            eDT = GDT_Byte;
+            break;
+        }
+        case RL2_SAMPLE_4_BIT:
+        {
+            nBits = 4;
+            eDT = GDT_Byte;
+            break;
+        }
+        case RL2_SAMPLE_INT8:
+        {
+            nBits = 8;
+            eDT = GDT_Byte;
+            bSigned = true;
+            break;
+        }
+        case RL2_SAMPLE_UINT8:
+        {
+            nBits = 8;
+            eDT = GDT_Byte;
+            bSigned = false;
+            break;
+        }
+        case RL2_SAMPLE_INT16:
+        {
+            nBits = 16;
+            eDT = GDT_Int16;
+            bSigned = true;
+            break;
+        }
+        case RL2_SAMPLE_UINT16:
+        {
+            nBits = 16;
+            eDT = GDT_UInt16;
+            bSigned = false;
+            break;
+        }
+        case RL2_SAMPLE_INT32:
+        {
+            nBits = 32;
+            eDT = GDT_Int32;
+            bSigned = true;
+            break;
+        }
+        case RL2_SAMPLE_UINT32:
+        {
+            nBits = 32;
+            eDT = GDT_UInt32;
+            bSigned = false;
+            break;
+        }
+        case RL2_SAMPLE_FLOAT:
+        {
+            nBits = 32;
+            eDT = GDT_Float32;
+            bSigned = true;
+            break;
+        }
+        case RL2_SAMPLE_DOUBLE:
+        {
+            nBits = 64;
+            eDT = GDT_Float64;
+            bSigned = true;
+            break;
+        }
+    }
+
+    // Get information about compression (informative)
+    unsigned char nCompression = 0;
+    int nQuality = 0;
+    rl2_get_coverage_compression (m_pRL2Coverage, &nCompression, &nQuality );
+    const char* pszCompression = NULL;
+    switch( nCompression )
+    {
+        case RL2_COMPRESSION_DEFLATE:
+        case RL2_COMPRESSION_DEFLATE_NO:
+            pszCompression = "DEFLATE";
+            break;
+        case RL2_COMPRESSION_LZMA:
+        case RL2_COMPRESSION_LZMA_NO:
+            pszCompression = "LZMA";
+            break;
+        case RL2_COMPRESSION_GIF:
+            pszCompression = "GIF";
+            break;
+        case RL2_COMPRESSION_JPEG:
+            pszCompression = "JPEG";
+            break;
+        case RL2_COMPRESSION_PNG:
+            pszCompression = "PNG";
+            break;
+        case RL2_COMPRESSION_LOSSY_WEBP:
+            pszCompression = "WEBP";
+            break;
+        case RL2_COMPRESSION_LOSSLESS_WEBP:
+            pszCompression = "WEBP_LOSSLESS";
+            break;
+        case RL2_COMPRESSION_CCITTFAX3:
+            pszCompression = "CCITTFAX3";
+            break;
+        case RL2_COMPRESSION_CCITTFAX4:
+            pszCompression = "CCITTFAX4";
+            break;
+        case RL2_COMPRESSION_LZW:
+            pszCompression = "LZW";
+            break;
+        case RL2_COMPRESSION_CHARLS:
+            pszCompression = "CHARLS";
+            break;
+        case RL2_COMPRESSION_LOSSY_JP2:
+            pszCompression = "JPEG2000";
+            break;
+        case RL2_COMPRESSION_LOSSLESS_JP2:
+            pszCompression = "JPEG2000_LOSSLESS";
+            break;
+        default:
+            break;
+    }
+
+    if( pszCompression != NULL )
+    {
+        GDALDataset::SetMetadataItem( "COMPRESSION", pszCompression,
+                                      "IMAGE_STRUCTURE" );
+    }
+
+    if( nQuality != 0 &&
+        (nCompression == RL2_COMPRESSION_JPEG ||
+         nCompression == RL2_COMPRESSION_LOSSY_WEBP||
+         nCompression == RL2_COMPRESSION_LOSSY_JP2 ) )
+    {
+        GDALDataset::SetMetadataItem( "QUALITY",
+                                      CPLSPrintf("%d", nQuality),
+                                      "IMAGE_STRUCTURE" );
+    }
+
+    // Get tile dimensions
+    unsigned int nTileWidth = 0;
+    unsigned int nTileHeight = 0;
+    rl2_get_coverage_tile_size (m_pRL2Coverage, &nTileWidth, &nTileHeight);
+    if( nTileWidth == 0 || nTileHeight == 0 || nTileWidth > INT_MAX ||
+        nTileHeight > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Invalid block size");
+        return false;
+    }
+    const int nBlockXSize = static_cast<int>(nTileWidth);
+    const int nBlockYSize = static_cast<int>(nTileHeight);
+
+    // Fetch nodata values
+    std::vector<double> adfNoDataValues;
+    rl2PixelPtr noDataPtr = rl2_get_coverage_no_data (m_pRL2Coverage);
+    if( noDataPtr != NULL )
+    {
+        unsigned char noDataSampleType = 0;
+        unsigned char noDataPixelType = 0;
+        unsigned char noDataBands = 0;
+        if( rl2_get_pixel_type( noDataPtr, &noDataSampleType,
+                                &noDataPixelType,
+                                &noDataBands ) == RL2_OK &&
+            noDataSampleType == nSampleType &&
+            noDataPixelType == nPixelType &&
+            noDataBands == l_nBands )
+        {
+            for( int i = 0; i < l_nBands; ++i )
+            {
+                double dfNoDataValue = 0.0;
+                switch( nSampleType )
+                {
+                    default:
+                    {
+                        break;
+                    }
+                    case RL2_SAMPLE_1_BIT:
+                    {
+                        unsigned char nVal = 0;
+                        rl2_get_pixel_sample_1bit( noDataPtr, &nVal );
+                        dfNoDataValue = nVal;
+                        break;
+                    }
+                    case RL2_SAMPLE_2_BIT:
+                    {
+                        unsigned char nVal = 0;
+                        rl2_get_pixel_sample_2bit( noDataPtr, &nVal );
+                        dfNoDataValue = nVal;
+                        break;
+                    }
+                    case RL2_SAMPLE_4_BIT:
+                    {
+                        unsigned char nVal = 0;
+                        rl2_get_pixel_sample_4bit( noDataPtr, &nVal );
+                        dfNoDataValue = nVal;
+                        break;
+
+                    }
+                    case RL2_SAMPLE_INT8:
+                    {
+                        char nVal = 0;
+                        rl2_get_pixel_sample_int8( noDataPtr, &nVal );
+                        dfNoDataValue = nVal;
+                        break;
+                    }
+                    case RL2_SAMPLE_UINT8:
+                    {
+                        unsigned char nVal = 0;
+                        rl2_get_pixel_sample_uint8( noDataPtr, i, &nVal );
+                        dfNoDataValue = nVal;
+                        break;
+                    }
+                    case RL2_SAMPLE_INT16:
+                    {
+                        short nVal = 0;
+                        rl2_get_pixel_sample_int16( noDataPtr, &nVal );
+                        dfNoDataValue = nVal;
+                        break;
+                    }
+                    case RL2_SAMPLE_UINT16:
+                    {
+                        unsigned short nVal = 0;
+                        rl2_get_pixel_sample_uint16( noDataPtr, i, &nVal );
+                        dfNoDataValue = nVal;
+                        break;
+                    }
+                    case RL2_SAMPLE_INT32:
+                    {
+                        int nVal = 0;
+                        rl2_get_pixel_sample_int32( noDataPtr, &nVal );
+                        dfNoDataValue = nVal;
+                        break;
+                    }
+                    case RL2_SAMPLE_UINT32:
+                    {
+                        unsigned int nVal = 0;
+                        rl2_get_pixel_sample_uint32( noDataPtr, &nVal );
+                        dfNoDataValue = nVal;
+                        break;
+                    }
+                    case RL2_SAMPLE_FLOAT:
+                    {
+                        float fVal = 0.0f;
+                        rl2_get_pixel_sample_float( noDataPtr, &fVal );
+                        dfNoDataValue = fVal;
+                        break;
+                    }
+                    case RL2_SAMPLE_DOUBLE:
+                    {
+                        double dfVal = 0.0;
+                        rl2_get_pixel_sample_double( noDataPtr, &dfVal );
+                        dfNoDataValue = dfVal;
+                        break;
+                    }
+                }
+
+                adfNoDataValues.push_back( dfNoDataValue );
+            }
+
+        }
+
+        // Do not destroy noDataPtr. It belongs to m_pRL2Coverage
+    }
+
+    // The nodata concept in RasterLite2 is equivalent to the NODATA_VALUES
+    // one of GDAL: the nodata value must be matched simultaneously on all
+    // bands.
+    if( adfNoDataValues.size() == l_nBands && l_nBands > 1 )
+    {
+        CPLString osNoDataValues;
+        for( int i = 0; i < l_nBands; i++ )
+        {
+            if( !osNoDataValues.empty() )
+                osNoDataValues += " ";
+            osNoDataValues += CPLSPrintf("%g", adfNoDataValues[i]);
+        }
+        GDALDataset::SetMetadataItem( "NODATA_VALUES", osNoDataValues.c_str() );
+    }
+
+    for( int iBand = 1; iBand <= l_nBands; ++iBand )
+    {
+        const bool bHasNoData = adfNoDataValues.size() == 1 && l_nBands == 1;
+        const double dfNoDataValue = bHasNoData ? adfNoDataValues[0] : 0.0;
+        SetBand( iBand,
+                 new RL2RasterBand( iBand, nPixelType,
+                                    eDT, nBits, m_bPromote1BitAs8Bit,
+                                    bSigned,
+                                    nBlockXSize, nBlockYSize,
+                                    bHasNoData,
+                                    dfNoDataValue ) );
+    }
+
+    // Fetch statistics
+    if( m_nSectionId < 0 || bSingleSection )
+    {
+        rl2RasterStatisticsPtr pStatistics =
+            rl2_create_raster_statistics_from_dbms( hDB,
+                                                    NULL,
+                                                    m_osCoverageName );
+        if( pStatistics != NULL )
+        {
+            for( int iBand = 1; iBand <= l_nBands; ++iBand )
+            {
+                GDALRasterBand* poBand = GetRasterBand(iBand);
+                double dfMin = 0.0;
+                double dfMax = 0.0;
+                double dfMean = 0.0;
+                double dfVariance = 0.0;
+                double dfStdDev = 0.0;
+                if( !(nBits == 1 && m_bPromote1BitAs8Bit) &&
+                    rl2_get_band_statistics( pStatistics,
+                                             static_cast<unsigned char>
+                                                             (iBand - 1),
+                                             &dfMin, &dfMax, &dfMean,
+                                             &dfVariance,
+                                             &dfStdDev ) == RL2_OK )
+                {
+                    poBand->GDALRasterBand::SetMetadataItem(
+                        "STATISTICS_MINIMUM", CPLSPrintf("%.16g", dfMin) );
+                    poBand->GDALRasterBand::SetMetadataItem(
+                        "STATISTICS_MAXIMUM", CPLSPrintf("%.16g", dfMax) );
+                    poBand->GDALRasterBand::SetMetadataItem(
+                        "STATISTICS_MEAN", CPLSPrintf("%.16g", dfMean) );
+                    poBand->GDALRasterBand::SetMetadataItem(
+                        "STATISTICS_STDDEV", CPLSPrintf("%.16g", dfStdDev) );
+                }
+            }
+            rl2_destroy_raster_statistics(pStatistics);
+        }
+    }
+
+    // Fetch other metadata
+    char* pszSQL = sqlite3_mprintf(
+        "SELECT title, abstract FROM raster_coverages WHERE "
+        "Lower(coverage_name) = Lower('%q') LIMIT 1",
+        m_osCoverageName.c_str() );
+    char** papszResults = NULL;
+    int nRowCount = 0;
+    int nColCount = 0;
+    int rc = sqlite3_get_table( hDB, pszSQL,
+                                &papszResults, &nRowCount,
+                                &nColCount, NULL );
+    sqlite3_free( pszSQL );
+    if( rc == SQLITE_OK )
+    {
+        if( nRowCount ==  1 )
+        {
+            const char* pszTitle = papszResults[2 + 0];
+            const char* pszAbstract = papszResults[2 + 1];
+            if( pszTitle != NULL && pszTitle[0] != '\0' &&
+                !EQUAL(pszTitle, "*** missing Title ***") )
+            {
+                GDALDataset::SetMetadataItem( "COVERAGE_TITLE", pszTitle );
+            }
+            if( pszAbstract != NULL && pszAbstract[0] != '\0' &&
+                !EQUAL(pszAbstract, "*** missing Abstract ***") )
+            {
+                GDALDataset::SetMetadataItem( "COVERAGE_ABSTRACT",
+                                              pszAbstract );
+            }
+        }
+        sqlite3_free_table(papszResults);
+    }
+
+    if( m_nSectionId >= 0 )
+    {
+        papszResults = NULL;
+        nRowCount = 0;
+        nColCount = 0;
+        pszSQL = sqlite3_mprintf(
+            "SELECT summary FROM \"%w\" WHERE "
+            "section_id = %d LIMIT 1",
+            CPLSPrintf( "%s_sections", m_osCoverageName.c_str() ),
+            static_cast<int>(m_nSectionId) );
+        rc = sqlite3_get_table( hDB, pszSQL,
+                                    &papszResults, &nRowCount,
+                                    &nColCount, NULL );
+        sqlite3_free( pszSQL );
+        if( rc == SQLITE_OK )
+        {
+            if( nRowCount ==  1 )
+            {
+                const char* pszSummary = papszResults[1 + 0];
+                if( pszSummary != NULL && pszSummary[0] != '\0' )
+                {
+                    GDALDataset::SetMetadataItem( "SECTION_SUMMARY",
+                                                  pszSummary );
+                }
+            }
+            sqlite3_free_table(papszResults);
+        }
+    }
+
+    // Instantiate overviews
+    int nStrictResolution = 0;
+    int nMixedResolutions = 0;
+    int nSectionPaths = 0;
+    int nSectionMD5 = 0;
+    int nSectionSummary = 0;
+    rl2_get_coverage_policies (m_pRL2Coverage,
+                               &nStrictResolution,
+                               &nMixedResolutions,
+                               &nSectionPaths,
+                               &nSectionMD5,
+                               &nSectionSummary);
+    m_bRL2MixedResolutions = CPL_TO_BOOL(nMixedResolutions);
+
+    ListOverviews();
+
+    return true;
+#else // !defined(HAVE_RASTERLITE2)
+    return false;
+#endif // HAVE_RASTERLITE2
+}
+
+#ifdef HAVE_RASTERLITE2
+
+/************************************************************************/
+/*                          ListOverviews()                             */
+/************************************************************************/
+
+void OGRSQLiteDataSource::ListOverviews()
+{
+    if( !m_bRL2MixedResolutions || m_nSectionId >= 0 )
+    {
+        char* pszSQL;
+        if( !m_bRL2MixedResolutions )
+        {
+            pszSQL = sqlite3_mprintf(
+                "SELECT x_resolution_1_1, y_resolution_1_1, "
+                "x_resolution_1_2, y_resolution_1_2, "
+                "x_resolution_1_4, y_resolution_1_4,"
+                "x_resolution_1_8, y_resolution_1_8 "
+                "FROM \"%w\" ORDER BY pyramid_level "
+                "LIMIT 1000",
+                CPLSPrintf( "%s_levels", m_osCoverageName.c_str() ) );
+        }
+        else
+        {
+            pszSQL = sqlite3_mprintf(
+                "SELECT x_resolution_1_1, y_resolution_1_1, "
+                "x_resolution_1_2, y_resolution_1_2, "
+                "x_resolution_1_4, y_resolution_1_4,"
+                "x_resolution_1_8, y_resolution_1_8 "
+                "FROM \"%w\" WHERE section_id = %d "
+                "ORDER BY pyramid_level "
+                "LIMIT 1000",
+                CPLSPrintf( "%s_section_levels", m_osCoverageName.c_str() ),
+                static_cast<int>(m_nSectionId) );
+        }
+        char** papszResults = NULL;
+        int nRowCount = 0;
+        int nColCount = 0;
+        char* pszErrMsg = NULL;
+        int rc = sqlite3_get_table( hDB, pszSQL,
+                                &papszResults, &nRowCount,
+                                &nColCount, &pszErrMsg );
+        sqlite3_free( pszSQL );
+        if( pszErrMsg )
+            CPLDebug( "SQLite", "%s", pszErrMsg);
+        sqlite3_free(pszErrMsg);
+        if( rc == SQLITE_OK )
+        {
+            for( int i=0; i<nRowCount; ++i )
+            {
+                const char* const* papszRow = papszResults + i * 8 + 8;
+                const char* pszXRes1 = papszRow[0];
+                const char* pszYRes1 = papszRow[1];
+                const char* pszXRes2 = papszRow[2];
+                const char* pszYRes2 = papszRow[3];
+                const char* pszXRes4 = papszRow[4];
+                const char* pszYRes4 = papszRow[5];
+                const char* pszXRes8 = papszRow[6];
+                const char* pszYRes8 = papszRow[7];
+                if( pszXRes1 != NULL && pszYRes1 != NULL )
+                {
+                    CreateRL2OverviewDatasetIfNeeded( CPLAtof(pszXRes1),
+                                                      CPLAtof(pszYRes1) );
+                }
+                if( pszXRes2 != NULL && pszYRes2 != NULL )
+                {
+                    CreateRL2OverviewDatasetIfNeeded( CPLAtof(pszXRes2),
+                                                      CPLAtof(pszYRes2) );
+                }
+                if( pszXRes4 != NULL && pszYRes4 != NULL )
+                {
+                    CreateRL2OverviewDatasetIfNeeded( CPLAtof(pszXRes4),
+                                                      CPLAtof(pszYRes4) );
+                }
+                if( pszXRes8 != NULL && pszYRes8 != NULL )
+                {
+                    CreateRL2OverviewDatasetIfNeeded( CPLAtof(pszXRes8),
+                                                      CPLAtof(pszYRes8) );
+                }
+            }
+            sqlite3_free_table(papszResults);
+        }
+    }
+}
+
+/************************************************************************/
+/*                    CreateRL2OverviewDatasetIfNeeded()                   */
+/************************************************************************/
+
+void OGRSQLiteDataSource::CreateRL2OverviewDatasetIfNeeded( double dfXRes,
+                                                            double dfYRes )
+{
+    if( fabs( dfXRes - m_adfGeoTransform[1] ) < 1e-5 * m_adfGeoTransform[1] )
+        return;
+
+    for( size_t i=0; i<m_apoOverviewDS.size(); ++i )
+    {
+        if( fabs( dfXRes - m_apoOverviewDS[i]->m_adfGeoTransform[1] ) <
+                1e-5 * m_apoOverviewDS[i]->m_adfGeoTransform[1] )
+        {
+            return;
+        }
+    }
+
+    OGRSQLiteDataSource* poOvrDS = new OGRSQLiteDataSource();
+    poOvrDS->bIsInternal = true;
+    poOvrDS->m_poParentDS = this;
+    poOvrDS->m_osCoverageName = m_osCoverageName;
+    poOvrDS->m_nSectionId = m_nSectionId;
+    poOvrDS->m_bPromote1BitAs8Bit = m_bPromote1BitAs8Bit;
+    poOvrDS->m_bRL2MixedResolutions = m_bRL2MixedResolutions;
+    poOvrDS->m_adfGeoTransform[0] = m_adfGeoTransform[0];
+    poOvrDS->m_adfGeoTransform[1] = dfXRes;
+    poOvrDS->m_adfGeoTransform[3] = m_adfGeoTransform[3];
+    poOvrDS->m_adfGeoTransform[5] = -dfYRes;
+    const double dfMinX = m_adfGeoTransform[0];
+    const double dfMaxX = dfMinX + m_adfGeoTransform[1] * nRasterXSize;
+    const double dfMaxY = m_adfGeoTransform[3];
+    const double dfMinY = dfMaxY + m_adfGeoTransform[5] * nRasterYSize;
+    poOvrDS->nRasterXSize = static_cast<int>(0.5 + (dfMaxX - dfMinX) / dfXRes);
+    poOvrDS->nRasterYSize = static_cast<int>(0.5 + (dfMaxY - dfMinY) / dfYRes);
+    if( poOvrDS->nRasterXSize <= 1 || poOvrDS->nRasterYSize <= 1 ||
+        (poOvrDS->nRasterXSize < 64 && poOvrDS->nRasterYSize < 64 &&
+        !CPLTestBool(CPLGetConfigOption("RL2_SHOW_ALL_PYRAMID_LEVELS", "NO"))) )
+    {
+        delete poOvrDS;
+        return;
+    }
+    for( int iBand = 1; iBand <= nBands; ++iBand )
+    {
+        poOvrDS->SetBand( iBand,
+                 new RL2RasterBand(
+                     reinterpret_cast<RL2RasterBand*>(GetRasterBand(iBand)) ) );
+    }
+    m_apoOverviewDS.push_back(poOvrDS);
+}
+
+/************************************************************************/
+/*                            RL2RasterBand()                           */
+/************************************************************************/
+
+RL2RasterBand::RL2RasterBand( int nBandIn,
+                              int nPixelType,
+                              GDALDataType eDT,
+                              int nBits,
+                              bool bPromote1BitAs8Bit,
+                              bool bSigned,
+                              int nBlockXSizeIn,
+                              int nBlockYSizeIn,
+                              bool bHasNoDataIn,
+                              double dfNoDataValueIn ) :
+    m_bHasNoData( bHasNoDataIn ),
+    m_dfNoDataValue( dfNoDataValueIn ),
+    m_eColorInterp( GCI_Undefined ),
+    m_poCT( NULL )
+{
+    eDataType = eDT;
+    nBlockXSize = nBlockXSizeIn;
+    nBlockYSize = nBlockYSizeIn;
+    if( (nBits % 8) != 0 )
+    {
+        GDALRasterBand::SetMetadataItem( (nBits == 1 && bPromote1BitAs8Bit) ?
+                                                    "SOURCE_NBITS" : "NBITS",
+                                         CPLSPrintf("%d", nBits),
+                                         "IMAGE_STRUCTURE" );
+    }
+    if( nBits == 8 && bSigned )
+    {
+        GDALRasterBand::SetMetadataItem( "PIXELTYPE",
+                                         "SIGNEDBYTE",
+                                         "IMAGE_STRUCTURE" );
+    }
+
+    if( nPixelType == RL2_PIXEL_MONOCHROME ||
+        nPixelType == RL2_PIXEL_GRAYSCALE )
+    {
+        m_eColorInterp = GCI_GrayIndex;
+    }
+    else if( nPixelType == RL2_PIXEL_PALETTE )
+    {
+        m_eColorInterp = GCI_PaletteIndex;
+    }
+    else if( nPixelType == RL2_PIXEL_RGB )
+    {
+        m_eColorInterp = static_cast<GDALColorInterp>(
+                                                GCI_RedBand + nBandIn - 1 );
+    }
+}
+
+/************************************************************************/
+/*                            RL2RasterBand()                           */
+/************************************************************************/
+
+RL2RasterBand::RL2RasterBand(const RL2RasterBand* poOther)
+{
+    eDataType = poOther->eDataType;
+    nBlockXSize = poOther->nBlockXSize;
+    nBlockYSize = poOther->nBlockYSize;
+    GDALRasterBand::SetMetadataItem( "NBITS",
+        const_cast<RL2RasterBand*>(poOther)->
+                    GetMetadataItem("NBITS", "IMAGE_STRUCTURE"),
+        "IMAGE_STRUCTURE" );
+    GDALRasterBand::SetMetadataItem( "PIXELTYPE",
+        const_cast<RL2RasterBand*>(poOther)->
+                    GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE"),
+        "IMAGE_STRUCTURE" );
+    m_eColorInterp = poOther->m_eColorInterp;
+    m_bHasNoData = poOther->m_bHasNoData;
+    m_dfNoDataValue = poOther->m_dfNoDataValue;
+    m_poCT = NULL;
+}
+
+/************************************************************************/
+/*                           ~RL2RasterBand()                           */
+/************************************************************************/
+
+RL2RasterBand::~RL2RasterBand()
+{
+    delete m_poCT;
+}
+
+/************************************************************************/
+/*                          GetColorTable()                             */
+/************************************************************************/
+
+GDALColorTable* RL2RasterBand::GetColorTable()
+{
+    OGRSQLiteDataSource* poGDS = reinterpret_cast<OGRSQLiteDataSource*>(poDS);
+    if( m_poCT == NULL && m_eColorInterp == GCI_PaletteIndex )
+    {
+        rl2PalettePtr palettePtr =
+            rl2_get_dbms_palette(
+                            poGDS->GetDB(),
+                            NULL,
+                            rl2_get_coverage_name(poGDS->GetRL2CoveragePtr()) );
+        if( palettePtr )
+        {
+            m_poCT = new GDALColorTable();
+            unsigned short nEntries = 0;
+            unsigned char* pabyR = NULL;
+            unsigned char* pabyG = NULL;
+            unsigned char* pabyB = NULL;
+            if( rl2_get_palette_colors( palettePtr, &nEntries,
+                                        &pabyR, &pabyG, &pabyB ) == RL2_OK )
+            {
+                for( int i=0; i < nEntries; ++ i )
+                {
+                    GDALColorEntry sEntry;
+                    sEntry.c1 = pabyR[i];
+                    sEntry.c2 = pabyG[i];
+                    sEntry.c3 = pabyB[i];
+                    sEntry.c4 =
+                            (m_bHasNoData && i == m_dfNoDataValue) ? 0 : 255;
+                    m_poCT->SetColorEntry( i, &sEntry );
+                }
+                rl2_free(pabyR);
+                rl2_free(pabyG);
+                rl2_free(pabyB);
+            }
+            rl2_destroy_palette( palettePtr );
+        }
+    }
+    return m_poCT;
+}
+
+/************************************************************************/
+/*                          GetOverviewCount()                          */
+/************************************************************************/
+
+int RL2RasterBand::GetOverviewCount()
+{
+    OGRSQLiteDataSource* poGDS = reinterpret_cast<OGRSQLiteDataSource*>(poDS);
+    int nRet = static_cast<int>(poGDS->GetOverviews().size());
+    if( nRet > 0 )
+        return nRet;
+    return GDALPamRasterBand::GetOverviewCount();
+}
+
+/************************************************************************/
+/*                           GetOverview()                              */
+/************************************************************************/
+
+GDALRasterBand* RL2RasterBand::GetOverview(int nIdx)
+{
+    OGRSQLiteDataSource* poGDS = reinterpret_cast<OGRSQLiteDataSource*>(poDS);
+    int nOvr = static_cast<int>(poGDS->GetOverviews().size());
+    if( nOvr > 0 )
+    {
+        if( nIdx < 0 || nIdx >= nOvr )
+            return NULL;
+        return poGDS->GetOverviews()[nIdx]->GetRasterBand(nBand);
+    }
+    return GDALPamRasterBand::GetOverview(nIdx);
+}
+
+/************************************************************************/
+/*                          GetNoDataValue()                            */
+/************************************************************************/
+
+double RL2RasterBand::GetNoDataValue( int* pbSuccess )
+{
+    if( m_bHasNoData )
+    {
+        if( pbSuccess )
+            *pbSuccess = TRUE;
+        return m_dfNoDataValue;
+    }
+    return GDALPamRasterBand::GetNoDataValue( pbSuccess );
+}
+
+/************************************************************************/
+/*                             IReadBlock()                             */
+/************************************************************************/
+
+CPLErr RL2RasterBand::IReadBlock( int nBlockXOff, int nBlockYOff, void* pData)
+{
+    OGRSQLiteDataSource* poGDS = reinterpret_cast<OGRSQLiteDataSource*>(poDS);
+#ifdef DEBUG_VERBOSE
+    CPLDebug("SQLite", "IReadBlock(ds=%p, band=%d, x=%d, y=%d)",
+             poGDS, nBand, nBlockXOff, nBlockYOff);
+#endif
+
+    const int nMaxThreads = 1;
+    const double* padfGeoTransform = poGDS->GetGeoTransform();
+    const double dfMinX = padfGeoTransform[0] +
+                          nBlockXOff * nBlockXSize * padfGeoTransform[1];
+    const double dfMaxX = dfMinX + nBlockXSize * padfGeoTransform[1];
+    const double dfMaxY = padfGeoTransform[3] +
+                          nBlockYOff * nBlockYSize * padfGeoTransform[5];
+    const double dfMinY = dfMaxY + nBlockYSize * padfGeoTransform[5];
+    unsigned char* pBuffer = NULL;
+    int nBufSize = 0;
+
+    sqlite3* hDB = poGDS->GetParentDS() ? poGDS->GetParentDS()->GetDB() :
+                                          poGDS->GetDB();
+    rl2CoveragePtr cov = poGDS->GetParentDS() ?
+                                    poGDS->GetParentDS()->GetRL2CoveragePtr():
+                                    poGDS->GetRL2CoveragePtr();
+    unsigned char nSampleType = 0;
+    unsigned char nPixelType = 0;
+    unsigned char l_nBands = 0;
+    rl2_get_coverage_type (cov,
+                           &nSampleType, &nPixelType, &l_nBands);
+
+    unsigned char nOutPixel = nPixelType;
+    if( nPixelType == RL2_PIXEL_MONOCHROME &&
+        nSampleType == RL2_SAMPLE_1_BIT )
+    {
+        nOutPixel = RL2_PIXEL_GRAYSCALE;
+    }
+
+    const GIntBig nSectionId = poGDS->GetSectionId();
+    if( nSectionId >= 0 &&
+        (poGDS->IsRL2MixedResolutions() || poGDS->GetParentDS() == NULL) )
+    {
+        int ret = rl2_get_section_raw_raster_data( hDB,
+                                                nMaxThreads,
+                                                cov,
+                                                nSectionId,
+                                                nBlockXSize,
+                                                nBlockYSize,
+                                                dfMinX,
+                                                dfMinY,
+                                                dfMaxX,
+                                                dfMaxY,
+                                                padfGeoTransform[1],
+                                                fabs(padfGeoTransform[5]),
+                                                &pBuffer,
+                                                &nBufSize,
+                                                NULL, // palette
+                                                nOutPixel );
+        if( ret != RL2_OK )
+            return CE_Failure;
+    }
+    else
+    {
+        int ret = rl2_get_raw_raster_data( hDB,
+                                                nMaxThreads,
+                                                cov,
+                                                nBlockXSize,
+                                                nBlockYSize,
+                                                dfMinX,
+                                                dfMinY,
+                                                dfMaxX,
+                                                dfMaxY,
+                                                padfGeoTransform[1],
+                                                fabs(padfGeoTransform[5]),
+                                                &pBuffer,
+                                                &nBufSize,
+                                                NULL, // palette
+                                                nOutPixel );
+        if( ret != RL2_OK )
+            return CE_Failure;
+    }
+
+    const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
+    const int nExpectedBytesOnBand = nBlockXSize * nBlockYSize * nDTSize;
+    const int nBands = poGDS->GetRasterCount();
+    const int nExpectedBytesAllBands = nExpectedBytesOnBand * nBands;
+    if( nBufSize != nExpectedBytesAllBands )
+    {
+        CPLDebug("SQLite", "Got %d bytes instead of %d",
+                 nBufSize, nExpectedBytesAllBands);
+        rl2_free( pBuffer);
+        return CE_Failure;
+    }
+
+    if( nPixelType == RL2_PIXEL_MONOCHROME &&
+        nSampleType == RL2_SAMPLE_1_BIT &&
+        !poGDS->HasPromote1BitAS8Bit() && poGDS->GetParentDS() != NULL )
+    {
+        GByte* pabyDstData = static_cast<GByte*>(pData);
+        for( int i = 0; i < nExpectedBytesAllBands; i++ )
+        {
+            pabyDstData[i] = ( pBuffer[i] > 127 ) ? 1 : 0;
+        }
+    }
+    else
+    {
+        GDALCopyWords( pBuffer + (nBand - 1) * nDTSize,
+                       eDataType, nDTSize * nBands,
+                       pData, eDataType, nDTSize,
+                       nBlockXSize * nBlockYSize );
+    }
+
+    if( nBands > 1 )
+    {
+        for( int iBand = 1; iBand <= nBands; ++iBand )
+        {
+            if( iBand == nBand )
+                continue;
+
+            GDALRasterBlock* poBlock = reinterpret_cast<RL2RasterBand*>(
+                poGDS->GetRasterBand(iBand))->
+                    TryGetLockedBlockRef( nBlockXOff, nBlockYOff );
+            if( poBlock != NULL )
+            {
+                poBlock->DropLock();
+                continue;
+            }
+            poBlock = reinterpret_cast<RL2RasterBand*>(
+                poGDS->GetRasterBand(iBand))->
+                    GetLockedBlockRef( nBlockXOff, nBlockYOff, TRUE );
+            if( poBlock == NULL )
+                continue;
+            void* pDest = poBlock->GetDataRef();
+            GDALCopyWords( pBuffer + (iBand - 1) * nDTSize,
+                           eDataType, nDTSize * nBands,
+                           pDest, eDataType, nDTSize,
+                           nBlockXSize * nBlockYSize );
+
+            poBlock->DropLock();
+        }
+    }
+
+    rl2_free( pBuffer);
+
+    return CE_None;
+}
+
+/************************************************************************/
+/*                          GetNoDataValue()                            */
+/************************************************************************/
+
+template<class T> static T GetNoDataValue( GDALDataset* poSrcDS,
+                                           int nBand,
+                                           T nDefault )
+{
+    int bHasNoData = FALSE;
+    double dfNoData =
+            poSrcDS->GetRasterBand(nBand)->GetNoDataValue(&bHasNoData);
+    if( bHasNoData )
+        return static_cast<T>(dfNoData);
+    return static_cast<T>(nDefault);
+}
+
+/************************************************************************/
+/*                          CreateNoData()                              */
+/************************************************************************/
+
+static rl2PixelPtr CreateNoData ( unsigned char nSampleType,
+                                  unsigned char nPixelType,
+                                  unsigned char nBandCount,
+                                  GDALDataset* poSrcDS )
+{
+    // creating a default NO-DATA value
+    rl2PixelPtr pxl = rl2_create_pixel (nSampleType, nPixelType, nBandCount);
+    if (pxl == NULL)
+        return NULL;
+    switch (nPixelType)
+    {
+        case RL2_PIXEL_MONOCHROME:
+            rl2_set_pixel_sample_1bit (pxl,
+                                       GetNoDataValue<GByte>(poSrcDS, 1, 0));
+            break;
+        case RL2_PIXEL_PALETTE:
+            switch (nSampleType)
+            {
+                case RL2_SAMPLE_1_BIT:
+                    rl2_set_pixel_sample_1bit (pxl,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_2_BIT:
+                    rl2_set_pixel_sample_2bit (pxl,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_4_BIT:
+                    rl2_set_pixel_sample_4bit (pxl,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_UINT8:
+                    rl2_set_pixel_sample_uint8 (pxl, 0,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 0));
+                    break;
+                default:
+                    CPLAssert(false);
+                    break;
+            }
+            break;
+        case RL2_PIXEL_GRAYSCALE:
+            switch (nSampleType)
+            {
+                case RL2_SAMPLE_1_BIT:
+                    rl2_set_pixel_sample_1bit (pxl,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 1));
+                    break;
+                case RL2_SAMPLE_2_BIT:
+                    rl2_set_pixel_sample_2bit (pxl,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 3));
+                    break;
+                case RL2_SAMPLE_4_BIT:
+                    rl2_set_pixel_sample_4bit (pxl,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 15));
+                    break;
+                case RL2_SAMPLE_UINT8:
+                    rl2_set_pixel_sample_uint8 (pxl, 0,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 255));
+                    break;
+                case RL2_SAMPLE_UINT16:
+                    rl2_set_pixel_sample_uint16 (pxl, 0,
+                                      GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
+                    break;
+                default:
+                    CPLAssert(false);
+                    break;
+            }
+            break;
+        case RL2_PIXEL_RGB:
+            switch (nSampleType)
+            {
+                case RL2_SAMPLE_UINT8:
+                    rl2_set_pixel_sample_uint8 (pxl, 0,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 255));
+                    rl2_set_pixel_sample_uint8 (pxl, 1,
+                                        GetNoDataValue<GByte>(poSrcDS, 2, 255));
+                    rl2_set_pixel_sample_uint8 (pxl, 2,
+                                        GetNoDataValue<GByte>(poSrcDS, 3, 255));
+                    break;
+                case RL2_SAMPLE_UINT16:
+                    rl2_set_pixel_sample_uint16 (pxl, 0,
+                                        GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
+                    rl2_set_pixel_sample_uint16 (pxl, 1,
+                                        GetNoDataValue<GUInt16>(poSrcDS, 2, 0));
+                    rl2_set_pixel_sample_uint16 (pxl, 2,
+                                        GetNoDataValue<GUInt16>(poSrcDS, 3, 0));
+                    break;
+                default:
+                    CPLAssert(false);
+                    break;
+            }
+            break;
+        case RL2_PIXEL_DATAGRID:
+            switch (nSampleType)
+            {
+                case RL2_SAMPLE_INT8:
+                    rl2_set_pixel_sample_int8 (pxl,
+                                        GetNoDataValue<char>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_UINT8:
+                    rl2_set_pixel_sample_uint8 (pxl, 0,
+                                        GetNoDataValue<GByte>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_INT16:
+                    rl2_set_pixel_sample_int16 (pxl,
+                                        GetNoDataValue<GInt16>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_UINT16:
+                    rl2_set_pixel_sample_uint16 (pxl, 0,
+                                        GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_INT32:
+                    rl2_set_pixel_sample_int32 (pxl,
+                                        GetNoDataValue<GInt32>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_UINT32:
+                    rl2_set_pixel_sample_uint32 (pxl,
+                                        GetNoDataValue<GUInt32>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_FLOAT:
+                    rl2_set_pixel_sample_float (pxl,
+                                        GetNoDataValue<float>(poSrcDS, 1, 0));
+                    break;
+                case RL2_SAMPLE_DOUBLE:
+                    rl2_set_pixel_sample_double (pxl,
+                                        GetNoDataValue<double>(poSrcDS, 1, 0));
+                    break;
+                default:
+                    CPLAssert(false);
+                    break;
+            }
+            break;
+        case RL2_PIXEL_MULTIBAND:
+            switch (nSampleType)
+            {
+                case RL2_SAMPLE_UINT8:
+                    for (unsigned int nb = 0; nb < nBandCount; nb++)
+                        rl2_set_pixel_sample_uint8 (pxl, nb,
+                            GetNoDataValue<GByte>(poSrcDS, nb+1, 255));
+                    break;
+                case RL2_SAMPLE_UINT16:
+                    for (unsigned int nb = 0; nb < nBandCount; nb++)
+                        rl2_set_pixel_sample_uint16 (pxl, nb,
+                            GetNoDataValue<GUInt16>(poSrcDS, nb+1, 0));
+                    break;
+                default:
+                    CPLAssert(false);
+                    break;
+            }
+            break;
+        default:
+            CPLAssert(false);
+            break;
+    }
+    return pxl;
+}
+
+/************************************************************************/
+/*                       RasterLite2Callback()                          */
+/************************************************************************/
+
+typedef struct
+{
+    GDALDataset* poSrcDS;
+    unsigned char nPixelType;
+    unsigned char nSampleType;
+    rl2PalettePtr pPalette;
+    GDALProgressFunc pfnProgress;
+    void * pProgressData;
+    double adfGeoTransform[6];
+} RasterLite2CallbackData;
+
+static int RasterLite2Callback( void *data,
+                                double dfTileMinX,
+                                double dfTileMinY,
+                                double dfTileMaxX,
+                                double dfTileMaxY,
+                                unsigned char *pabyBuffer,
+                                rl2PalettePtr* pOutPalette )
+{
+#ifdef DEBUG_VERBOSE
+    CPLDebug("SQLite", "RasterLite2Callback(%f %f %f %f)",
+             dfTileMinX, dfTileMinY, dfTileMaxX, dfTileMaxY);
+#endif
+    RasterLite2CallbackData* pCbkData =
+                            static_cast<RasterLite2CallbackData*>(data);
+    if( pOutPalette )
+    {
+        if( pCbkData->pPalette )
+            *pOutPalette = rl2_clone_palette( pCbkData->pPalette );
+        else
+            *pOutPalette = NULL;
+    }
+    int nXOff = static_cast<int>(0.5 +
+        (dfTileMinX - pCbkData->adfGeoTransform[0]) /
+                                pCbkData->adfGeoTransform[1]);
+    int nXOff2 = static_cast<int>(0.5 +
+        (dfTileMaxX - pCbkData->adfGeoTransform[0]) /
+                                pCbkData->adfGeoTransform[1]);
+    int nYOff = static_cast<int>(0.5 +
+        (dfTileMaxY - pCbkData->adfGeoTransform[3]) /
+                                pCbkData->adfGeoTransform[5]);
+    int nYOff2 = static_cast<int>(0.5 +
+        (dfTileMinY - pCbkData->adfGeoTransform[3]) /
+                                pCbkData->adfGeoTransform[5]);
+    int nReqXSize = nXOff2 - nXOff;
+    bool bZeroInitialize = false;
+    if( nXOff2 > pCbkData->poSrcDS->GetRasterXSize() )
+    {
+        bZeroInitialize = true;
+        nReqXSize = pCbkData->poSrcDS->GetRasterXSize() - nXOff;
+    }
+    int nReqYSize = nYOff2 - nYOff;
+    if( nYOff2 > pCbkData->poSrcDS->GetRasterYSize() )
+    {
+        bZeroInitialize = true;
+        nReqYSize = pCbkData->poSrcDS->GetRasterYSize() - nYOff;
+    }
+
+    GDALDataType eDT = pCbkData->poSrcDS->GetRasterBand(1)->GetRasterDataType();
+    int nDTSize = GDALGetDataTypeSizeBytes(eDT);
+    int nBands = pCbkData->poSrcDS->GetRasterCount();
+    if( bZeroInitialize )
+    {
+        memset( pabyBuffer, 0,
+                static_cast<size_t>(nXOff2 - nXOff) *
+                                   (nYOff2 - nYOff) * nBands * nDTSize );
+    }
+
+    const GSpacing nPixelSpacing = static_cast<GSpacing>(nDTSize) * nBands;
+    const GSpacing nLineSpacing = nPixelSpacing * (nXOff2 - nXOff);
+    CPLErr eErr = pCbkData->poSrcDS->RasterIO( GF_Read,
+                                               nXOff, nYOff,
+                                               nReqXSize, nReqYSize,
+                                               pabyBuffer,
+                                               nReqXSize, nReqYSize,
+                                               eDT,
+                                               nBands,
+                                               NULL,
+                                               nPixelSpacing,
+                                               nLineSpacing,
+                                               nDTSize,
+                                               NULL );
+    if( eErr != CE_None )
+        return FALSE;
+
+    if( pCbkData->pfnProgress &&
+        !pCbkData->pfnProgress(static_cast<double>(nYOff + nReqYSize) /
+                                    pCbkData->poSrcDS->GetRasterYSize(),
+                               "", pCbkData->pProgressData) )
+    {
+        return FALSE;
+    }
+
+    int nMaxVal = 0;
+    if( pCbkData->nSampleType == RL2_SAMPLE_1_BIT )
+    {
+        nMaxVal = 1;
+    }
+    else if( pCbkData->nSampleType == RL2_SAMPLE_2_BIT )
+    {
+        nMaxVal = 3;
+    }
+    else if( pCbkData->nSampleType == RL2_SAMPLE_4_BIT )
+    {
+        nMaxVal = 7;
+    }
+    if( nMaxVal != 0 )
+    {
+        bool bClamped = false;
+        for( int iY = 0; iY < nReqYSize; ++iY )
+        {
+            for( int iX = 0; iX < nReqXSize; ++iX )
+            {
+                GByte* pbyVal = pabyBuffer +
+                        static_cast<size_t>(iY) * (nXOff2 - nXOff) + iX;
+                if( *pbyVal > nMaxVal )
+                {
+                    if( !bClamped )
+                    {
+                        bClamped = true;
+                        CPLError(CE_Warning, CPLE_AppDefined,
+                                 "One or several values above %d have "
+                                 "been clamped",
+                                 nMaxVal);
+                    }
+                    *pbyVal = nMaxVal;
+                }
+            }
+        }
+    }
+
+    return TRUE;
+}
+
+/************************************************************************/
+/*                    OGRSQLiteDriverCreateCopy()                       */
+/************************************************************************/
+
+GDALDataset *OGRSQLiteDriverCreateCopy( const char* pszName,
+                                        GDALDataset* poSrcDS,
+                                        int /* bStrict */,
+                                        char ** papszOptions,
+                                        GDALProgressFunc pfnProgress,
+                                        void * pProgressData )
+{
+    if( poSrcDS->GetRasterCount() == 0 ||
+        poSrcDS->GetRasterCount() > 255 )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported band count");
+        return NULL;
+    }
+
+    double adfGeoTransform[6];
+    if( poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None &&
+        (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0) )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Raster with rotation/shearing geotransform terms "
+                 "are not supported");
+        return NULL;
+    }
+
+    if( CSLFetchNameValue(papszOptions, "APPEND_SUBDATASET") &&
+        !CSLFetchNameValue(papszOptions, "COVERAGE") )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "COVERAGE must be specified with APPEND_SUBDATASET=YES");
+        return NULL;
+    }
+
+    GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
+
+    unsigned char nSampleType = RL2_SAMPLE_UINT8;
+    unsigned char nPixelType = RL2_PIXEL_GRAYSCALE;
+    unsigned char nBandCount = static_cast<unsigned char>(
+                                            poSrcDS->GetRasterCount());
+
+    const char* pszPixelType = CSLFetchNameValue(papszOptions, "PIXEL_TYPE");
+    if( pszPixelType )
+    {
+        if( EQUAL(pszPixelType, "MONOCHROME") )
+            nPixelType = RL2_PIXEL_MONOCHROME;
+        else if( EQUAL(pszPixelType, "PALETTE") )
+            nPixelType = RL2_PIXEL_PALETTE;
+        else if( EQUAL(pszPixelType, "GRAYSCALE") )
+            nPixelType = RL2_PIXEL_GRAYSCALE;
+        else if( EQUAL(pszPixelType, "RGB") )
+            nPixelType = RL2_PIXEL_RGB;
+        else if( EQUAL(pszPixelType, "MULTIBAND") )
+            nPixelType = RL2_PIXEL_MULTIBAND;
+        else if( EQUAL(pszPixelType, "DATAGRID") )
+            nPixelType = RL2_PIXEL_DATAGRID;
+    }
+    else
+    {
+        // Guess a reasonable pixel type from band characteristics
+        if( nBandCount == 1 &&
+            poSrcDS->GetRasterBand(1)->GetColorTable() != NULL )
+        {
+            nPixelType = RL2_PIXEL_PALETTE;
+        }
+        else if( nBandCount == 3 && (eDT == GDT_Byte || eDT == GDT_UInt16) &&
+                 poSrcDS->GetRasterBand(1)->GetColorInterpretation() ==
+                                                            GCI_RedBand &&
+                 poSrcDS->GetRasterBand(2)->GetColorInterpretation() ==
+                                                            GCI_GreenBand &&
+                 poSrcDS->GetRasterBand(3)->GetColorInterpretation() ==
+                                                            GCI_BlueBand )
+        {
+            nPixelType = RL2_PIXEL_RGB;
+        }
+        else if( nBandCount > 1 && (eDT == GDT_Byte || eDT == GDT_UInt16) )
+        {
+            nPixelType = RL2_PIXEL_MULTIBAND;
+        }
+        else if( nBandCount == 1 && eDT != GDT_Byte )
+        {
+            nPixelType = RL2_PIXEL_DATAGRID;
+        }
+    }
+
+    // Deal with NBITS
+    const char* pszNBITS = CSLFetchNameValue(papszOptions, "NBITS");
+    int nBITS = 0;
+    if( pszNBITS != NULL )
+    {
+        nBITS = atoi(pszNBITS);
+        if( nBITS != 1 && nBITS != 2 && nBITS != 4 && nBITS != 8 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported NBITS value");
+            return NULL;
+        }
+    }
+    else
+    {
+        pszNBITS = poSrcDS->GetRasterBand(1)->GetMetadataItem(
+                                                "NBITS", "IMAGE_STRUCTURE");
+        if( pszNBITS != NULL )
+        {
+            nBITS = atoi(pszNBITS);
+        }
+    }
+
+    if( nBITS > 0 && nBITS <= 8 && eDT != GDT_Byte )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "NBITS <= 8 only compatible with Byte data type");
+        return NULL;
+    }
+
+    if( nBITS == 1 )
+    {
+        nSampleType = RL2_SAMPLE_1_BIT;
+        if( nPixelType != RL2_PIXEL_PALETTE && pszPixelType == NULL )
+            nPixelType = RL2_PIXEL_MONOCHROME;
+    }
+    else if( nBITS == 2 )
+    {
+        nSampleType = RL2_SAMPLE_2_BIT;
+        if( nPixelType != RL2_PIXEL_PALETTE && pszPixelType == NULL )
+            nPixelType = RL2_PIXEL_GRAYSCALE;
+    }
+    else if( nBITS == 4 )
+    {
+        nSampleType = RL2_SAMPLE_4_BIT;
+        if( nPixelType != RL2_PIXEL_PALETTE && pszPixelType == NULL )
+            nPixelType = RL2_PIXEL_GRAYSCALE;
+    }
+
+    if( nPixelType == RL2_PIXEL_MONOCHROME )
+    {
+        if( eDT != GDT_Byte )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Incompatible data type for MONOCHROME");
+            return NULL;
+        }
+        // Force 1 bit
+        nSampleType = RL2_SAMPLE_1_BIT;
+    }
+
+    // Guess sample type in other cases
+    if( eDT == GDT_UInt16 )
+        nSampleType = RL2_SAMPLE_UINT16;
+    else if( eDT == GDT_Int16 )
+        nSampleType = RL2_SAMPLE_INT16;
+    else if( eDT == GDT_UInt32 )
+        nSampleType = RL2_SAMPLE_UINT32;
+    else if( eDT == GDT_Int32 )
+        nSampleType = RL2_SAMPLE_INT32;
+    else if( eDT == GDT_Float32 )
+        nSampleType = RL2_SAMPLE_FLOAT;
+    else if( eDT == GDT_Float64 )
+        nSampleType = RL2_SAMPLE_DOUBLE;
+    else if( eDT != GDT_Byte )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported data type");
+        return NULL;
+    }
+
+    unsigned char nCompression = RL2_COMPRESSION_NONE;
+    int nQuality = 100;
+    const char* pszCompression = CSLFetchNameValue( papszOptions, "COMPRESS" );
+    if( pszCompression )
+    {
+        if( EQUAL( pszCompression, "NONE") )
+            nCompression = RL2_COMPRESSION_NONE;
+        else if( EQUAL( pszCompression, "DEFLATE") )
+            nCompression = RL2_COMPRESSION_DEFLATE;
+        else if( EQUAL( pszCompression, "LZMA") )
+            nCompression = RL2_COMPRESSION_LZMA;
+        else if( EQUAL( pszCompression, "PNG") )
+            nCompression = RL2_COMPRESSION_PNG;
+        else if( EQUAL( pszCompression, "CCITTFAX4") )
+            nCompression = RL2_COMPRESSION_CCITTFAX4;
+        else if( EQUAL( pszCompression, "JPEG") )
+        {
+            nCompression = RL2_COMPRESSION_JPEG;
+            nQuality = 75;
+        }
+        else if( EQUAL( pszCompression, "WEBP") )
+        {
+            nCompression = RL2_COMPRESSION_LOSSY_WEBP;
+            nQuality = 75;
+        }
+        else if( EQUAL( pszCompression, "CHARLS") )
+            nCompression = RL2_COMPRESSION_CHARLS;
+        else if( EQUAL( pszCompression, "JPEG2000") )
+        {
+            nCompression = RL2_COMPRESSION_LOSSY_JP2;
+            nQuality = 20;
+        }
+        else
+        {
+            CPLError(CE_Failure, CPLE_NotSupported, "Unsupported compression");
+            return NULL;
+        }
+        if( !rl2_is_supported_codec(nCompression) )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "librasterlite2 is not built with support for "
+                     "this compression method.");
+            return NULL;
+        }
+    }
+
+    // Compatibility checks:
+    // see https://www.gaia-gis.it/fossil/librasterlite2/wiki?name=reference_table
+    if( nPixelType == RL2_PIXEL_MONOCHROME )
+    {
+        if( nBandCount != 1 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported band count with MONOCHROME");
+            return NULL;
+        }
+        CPLAssert( nSampleType == RL2_SAMPLE_1_BIT );
+    }
+    else if( nPixelType == RL2_PIXEL_PALETTE )
+    {
+        if( nBandCount != 1 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported band count with PALETTE");
+            return NULL;
+        }
+        if( nSampleType != RL2_SAMPLE_1_BIT &&
+            nSampleType != RL2_SAMPLE_2_BIT &&
+            nSampleType != RL2_SAMPLE_4_BIT &&
+            nSampleType != RL2_SAMPLE_UINT8 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported sample type with PALETTE");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_GRAYSCALE )
+    {
+        if( nBandCount != 1 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported band count with GRAYSCALE");
+            return NULL;
+        }
+        if( nSampleType != RL2_SAMPLE_2_BIT &&
+            nSampleType != RL2_SAMPLE_4_BIT &&
+            nSampleType != RL2_SAMPLE_UINT8 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported sample type with GRAYSCALE");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_RGB )
+    {
+        if( nBandCount != 3 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported band count with RGB");
+            return NULL;
+        }
+        if( nSampleType != RL2_SAMPLE_UINT8 &&
+            nSampleType != RL2_SAMPLE_UINT16 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported sample type with RGB");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_MULTIBAND )
+    {
+        if( nBandCount == 1 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported band count with MULTIBAND");
+            return NULL;
+        }
+        if( nSampleType != RL2_SAMPLE_UINT8 &&
+            nSampleType != RL2_SAMPLE_UINT16 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported sample type with MULTIBAND");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_DATAGRID )
+    {
+        if( nBandCount != 1 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported band count with DATAGRID");
+            return NULL;
+        }
+        if( nSampleType != RL2_SAMPLE_INT8 &&
+            nSampleType != RL2_SAMPLE_UINT8 &&
+            nSampleType != RL2_SAMPLE_INT16 &&
+            nSampleType != RL2_SAMPLE_UINT16 &&
+            nSampleType != RL2_SAMPLE_INT32 &&
+            nSampleType != RL2_SAMPLE_UINT32 &&
+            nSampleType != RL2_SAMPLE_FLOAT &&
+            nSampleType != RL2_SAMPLE_DOUBLE )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported sample type with DATAGRID");
+            return NULL;
+        }
+    }
+
+    // Other compatibility checks based on compression
+    if( nPixelType == RL2_PIXEL_MONOCHROME )
+    {
+        if( nCompression != RL2_COMPRESSION_NONE &&
+            nCompression != RL2_COMPRESSION_DEFLATE &&
+            nCompression != RL2_COMPRESSION_DEFLATE_NO &&
+            nCompression != RL2_COMPRESSION_LZMA &&
+            nCompression != RL2_COMPRESSION_LZMA_NO &&
+            nCompression != RL2_COMPRESSION_CCITTFAX4 &&
+            nCompression != RL2_COMPRESSION_PNG )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with MONOCHROME");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_PALETTE )
+    {
+        if( nCompression != RL2_COMPRESSION_NONE &&
+            nCompression != RL2_COMPRESSION_DEFLATE &&
+            nCompression != RL2_COMPRESSION_DEFLATE_NO &&
+            nCompression != RL2_COMPRESSION_LZMA &&
+            nCompression != RL2_COMPRESSION_LZMA_NO &&
+            nCompression != RL2_COMPRESSION_PNG )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with PALETTE");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_GRAYSCALE )
+    {
+        if( nCompression == RL2_COMPRESSION_CCITTFAX4 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with GRAYSCALE");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_RGB && nSampleType == RL2_SAMPLE_UINT8 )
+    {
+        if( nCompression == RL2_COMPRESSION_CCITTFAX4 )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with RGB UINT8");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_RGB && nSampleType == RL2_SAMPLE_UINT16 )
+    {
+        if( nCompression == RL2_COMPRESSION_CCITTFAX4 ||
+            nCompression == RL2_COMPRESSION_JPEG ||
+            nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
+            nCompression == RL2_COMPRESSION_LOSSLESS_WEBP )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with RGB UINT16");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_MULTIBAND &&
+             nSampleType == RL2_SAMPLE_UINT8 &&
+             (nBandCount == 3 || nBandCount == 4) )
+    {
+        if( nCompression == RL2_COMPRESSION_CCITTFAX4 ||
+            nCompression == RL2_COMPRESSION_JPEG  )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with MULTIBAND UINT8 %d bands",
+                     nBandCount);
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_MULTIBAND &&
+             nSampleType == RL2_SAMPLE_UINT16 &&
+             (nBandCount == 3 || nBandCount == 4) )
+    {
+        if( nCompression == RL2_COMPRESSION_CCITTFAX4 ||
+            nCompression == RL2_COMPRESSION_JPEG ||
+            nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
+            nCompression == RL2_COMPRESSION_LOSSLESS_WEBP  )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with MULTIBAND UINT16 %d bands",
+                     nBandCount);
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_MULTIBAND )
+    {
+        if( nCompression != RL2_COMPRESSION_NONE &&
+            nCompression != RL2_COMPRESSION_DEFLATE &&
+            nCompression != RL2_COMPRESSION_DEFLATE_NO &&
+            nCompression != RL2_COMPRESSION_LZMA &&
+            nCompression != RL2_COMPRESSION_LZMA_NO )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with MULTIBAND %s %d bands",
+                     (nSampleType == RL2_SAMPLE_UINT8) ? "UINT8" : "UINT16",
+                     nBandCount);
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_DATAGRID &&
+             (nSampleType == RL2_SAMPLE_UINT8 ||
+              nSampleType == RL2_SAMPLE_UINT16) )
+    {
+        if( nCompression == RL2_COMPRESSION_CCITTFAX4 ||
+            nCompression == RL2_COMPRESSION_JPEG ||
+            nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
+            nCompression == RL2_COMPRESSION_LOSSLESS_WEBP  )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with DATAGRID %s",
+                     (nSampleType == RL2_SAMPLE_UINT8) ? "UINT8" : "UINT16");
+            return NULL;
+        }
+    }
+    else if( nPixelType == RL2_PIXEL_DATAGRID &&
+             nSampleType != RL2_SAMPLE_UINT8 &&
+             nSampleType != RL2_SAMPLE_UINT16 )
+    {
+        if( nCompression != RL2_COMPRESSION_NONE &&
+            nCompression != RL2_COMPRESSION_DEFLATE &&
+            nCompression != RL2_COMPRESSION_DEFLATE_NO &&
+            nCompression != RL2_COMPRESSION_LZMA &&
+            nCompression != RL2_COMPRESSION_LZMA_NO )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Unsupported compression with DATAGRID %s",
+                     GDALGetDataTypeName(eDT));
+            return NULL;
+        }
+    }
+
+    const char* pszQuality = CSLFetchNameValue( papszOptions, "QUALITY" );
+    if( pszQuality )
+    {
+        nQuality = atoi(pszQuality);
+        if( nQuality == 100 && nCompression == RL2_COMPRESSION_LOSSY_JP2 )
+            nCompression = RL2_COMPRESSION_LOSSLESS_JP2;
+        else if( nQuality == 100 && nCompression == RL2_COMPRESSION_LOSSY_WEBP )
+            nCompression = RL2_COMPRESSION_LOSSLESS_WEBP;
+    }
+
+    unsigned int nTileWidth = atoi( CSLFetchNameValueDef(papszOptions,
+                                                         "BLOCKXSIZE",
+                                                         "512") );
+    unsigned int nTileHeight = atoi( CSLFetchNameValueDef(papszOptions,
+                                                         "BLOCKYSIZE",
+                                                         "512") );
+
+/* -------------------------------------------------------------------- */
+/*      Try to create datasource.                                       */
+/* -------------------------------------------------------------------- */
+    OGRSQLiteDataSource *poDS = new OGRSQLiteDataSource();
+
+    if( CSLFetchNameValue(papszOptions, "APPEND_SUBDATASET") )
+    {
+        if( !poDS->Open( pszName, TRUE, NULL, GDAL_OF_RASTER |
+                                              GDAL_OF_VECTOR ) )
+        {
+            delete poDS;
+            return NULL;
+        }
+    }
+    else
+    {
+        char** papszNewOptions = CSLDuplicate(papszOptions);
+        papszNewOptions = CSLSetNameValue(papszNewOptions, "SPATIALITE", "YES");
+        if( !poDS->Create( pszName, papszNewOptions ) )
+        {
+            CSLDestroy(papszNewOptions);
+            delete poDS;
+            return NULL;
+        }
+        CSLDestroy(papszNewOptions);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try to get the SRS Id of this spatial reference system,         */
+/*      adding to the srs table if needed.                              */
+/* -------------------------------------------------------------------- */
+    int nSRSId = 0;
+    const char* pszSRID = CSLFetchNameValue(papszOptions, "SRID");
+
+    if( pszSRID != NULL )
+    {
+        nSRSId = atoi(pszSRID);
+        if( nSRSId > 0 )
+        {
+            OGRSpatialReference* poSRSFetched = poDS->FetchSRS( nSRSId );
+            if( poSRSFetched == NULL )
+            {
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "SRID %d will be used, but no matching SRS is "
+                         "defined in spatial_ref_sys",
+                         nSRSId);
+            }
+        }
+    }
+    else
+    {
+        const char* pszProjectionRef = poSrcDS->GetProjectionRef();
+        if( pszProjectionRef != NULL && !EQUAL(pszProjectionRef, "") )
+        {
+            OGRSpatialReference oSRS;
+            char* pszTmp = const_cast<char*>(pszProjectionRef);
+            if( oSRS.importFromWkt(&pszTmp) == OGRERR_NONE )
+            {
+                nSRSId = poDS->FetchSRSId( &oSRS );
+            }
+        }
+    }
+
+    poDS->StartTransaction();
+
+    char** papszResults = NULL;
+    int nRowCount = 0;
+    int nColCount = 0;
+    sqlite3_get_table( poDS->GetDB(),
+                  "SELECT * FROM sqlite_master WHERE "
+                  "name = 'raster_coverages' AND type = 'table'",
+                   &papszResults, &nRowCount,
+                   &nColCount, NULL );
+    sqlite3_free_table(papszResults);
+    if( nRowCount == 0 )
+    {
+        char* pszErrMsg = NULL;
+        int ret = sqlite3_exec (poDS->GetDB(),
+                                "SELECT CreateRasterCoveragesTable()", NULL,
+                                NULL, &pszErrMsg);
+        if (ret != SQLITE_OK)
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "CreateRasterCoveragesTable() failed: %s", pszErrMsg);
+            sqlite3_free(pszErrMsg);
+            delete poDS;
+            return NULL;
+        }
+    }
+
+    CPLString osCoverageName( CSLFetchNameValueDef(papszOptions,
+                                                   "COVERAGE",
+                                                   CPLGetBasename(pszName)) );
+    // Check if the coverage already exists
+    rl2CoveragePtr cvg = NULL;
+    char* pszSQL = sqlite3_mprintf(
+            "SELECT coverage_name "
+            "FROM raster_coverages WHERE coverage_name = '%q' LIMIT 1",
+            osCoverageName.c_str());
+    sqlite3_get_table( poDS->GetDB(), pszSQL,  &papszResults, &nRowCount,
+                       &nColCount, NULL );
+    sqlite3_free(pszSQL);
+    sqlite3_free_table(papszResults);
+    if( nRowCount == 1 )
+    {
+        cvg = rl2_create_coverage_from_dbms( poDS->GetDB(),
+                                             NULL,
+                                             osCoverageName );
+        if( cvg == NULL )
+        {
+            delete poDS;
+            return NULL;
+        }
+    }
+
+    rl2PalettePtr pPalette = NULL;
+    if( nPixelType == RL2_PIXEL_PALETTE )
+    {
+        GDALColorTable* poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
+        if( poCT == NULL )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined, "Missing color table");
+            delete poDS;
+            return NULL;
+        }
+
+        const int nColors = poCT->GetColorEntryCount();
+        pPalette = rl2_create_palette( nColors );
+        for( int i=0; i<nColors; ++i )
+        {
+            const GDALColorEntry* poCE = poCT->GetColorEntry(i);
+            rl2_set_palette_color (pPalette, i,
+                                    static_cast<GByte>(poCE->c1),
+                                    static_cast<GByte>(poCE->c2),
+                                    static_cast<GByte>(poCE->c3));
+        }
+    }
+
+    if( cvg == NULL )
+    {
+        const double dfXRes = adfGeoTransform[1];
+        const double dfYRes = fabs(adfGeoTransform[5]);
+        const bool bStrictResolution = true;
+        const bool bMixedResolutions = false;
+        const bool bSectionPaths = false;
+        const bool bSectionMD5 = false;
+        const bool bSectionSummary = false;
+        const bool bIsQueryable = false;
+
+        rl2PixelPtr pNoData =
+            CreateNoData( nSampleType, nPixelType, nBandCount, poSrcDS );
+        if( pNoData == NULL )
+        {
+            delete poDS;
+            if( pPalette )
+                rl2_destroy_palette(pPalette);
+            return NULL;
+        }
+
+        if( rl2_create_dbms_coverage(poDS->GetDB(),
+                                    osCoverageName,
+                                    nSampleType,
+                                    nPixelType,
+                                    nBandCount,
+                                    nCompression,
+                                    nQuality,
+                                    nTileWidth,
+                                    nTileHeight,
+                                    nSRSId,
+                                    dfXRes,
+                                    dfYRes,
+                                    pNoData,
+                                    pPalette,
+                                    bStrictResolution,
+                                    bMixedResolutions,
+                                    bSectionPaths,
+                                    bSectionMD5,
+                                    bSectionSummary,
+                                    bIsQueryable) != RL2_OK )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                    "rl2_create_dbms_coverage() failed");
+            rl2_destroy_pixel (pNoData);
+            if( pPalette )
+                rl2_destroy_palette(pPalette);
+            delete poDS;
+            return NULL;
+        }
+
+        rl2_destroy_pixel (pNoData);
+    }
+
+    if( cvg == NULL )
+    {
+        cvg = rl2_create_coverage_from_dbms( poDS->GetDB(),
+                                             NULL,
+                                             osCoverageName );
+        if (cvg == NULL)
+        {
+            if( pPalette )
+                rl2_destroy_palette(pPalette);
+            delete poDS;
+            return NULL;
+        }
+    }
+
+    if( adfGeoTransform[5] > 0 )
+        adfGeoTransform[5] = -adfGeoTransform[5];
+    double dfXMin = adfGeoTransform[0];
+    double dfXMax = dfXMin + adfGeoTransform[1] * poSrcDS->GetRasterXSize();
+    double dfYMax = adfGeoTransform[3];
+    double dfYMin = dfYMax + adfGeoTransform[5] * poSrcDS->GetRasterYSize();
+
+    CPLString osSectionName( CSLFetchNameValueDef(papszOptions,
+                                                  "SECTION",
+                                                  CPLGetBasename(pszName)) );
+    const bool bPyramidize = CPLFetchBool( papszOptions, "PYRAMIDIZE", false );
+    RasterLite2CallbackData cbk_data;
+    cbk_data.poSrcDS = poSrcDS;
+    cbk_data.nPixelType = nPixelType;
+    cbk_data.nSampleType = nSampleType;
+    cbk_data.pPalette = pPalette;
+    cbk_data.pfnProgress = pfnProgress;
+    cbk_data.pProgressData = pProgressData;
+    memcpy( &cbk_data.adfGeoTransform, adfGeoTransform,
+            sizeof(adfGeoTransform) );
+
+    if( rl2_load_raw_tiles_into_dbms(poDS->GetDB(), cvg,
+                                     osSectionName,
+                                     poSrcDS->GetRasterXSize(),
+                                     poSrcDS->GetRasterYSize(),
+                                     nSRSId,
+                                     dfXMin, dfYMin, dfXMax, dfYMax,
+                                     RasterLite2Callback,
+                                     &cbk_data,
+                                     bPyramidize) != RL2_OK )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "rl2_load_raw_tiles_into_dbms() failed");
+        delete poDS;
+        rl2_destroy_coverage (cvg);
+        if( pPalette )
+            rl2_destroy_palette(pPalette);
+        return NULL;
+    }
+
+    rl2_destroy_coverage (cvg);
+    if( pPalette )
+        rl2_destroy_palette(pPalette);
+
+    poDS->CommitTransaction();
+
+    delete poDS;
+
+    poDS = new OGRSQLiteDataSource();
+    poDS->Open( CPLSPrintf("RASTERLITE2:%s:%s",
+                           EscapeNameAndQuoteIfNeeded(pszName).c_str(),
+                           EscapeNameAndQuoteIfNeeded(osCoverageName).c_str()),
+                TRUE, NULL, GDAL_OF_RASTER );
+    return poDS;
+}
+
+/************************************************************************/
+/*                            IsPowerOfTwo()                            */
+/************************************************************************/
+
+static bool IsPowerOfTwo( unsigned int i )
+{
+    int nBitSet = 0;
+    while(i != 0)
+    {
+        if( i & 1 )
+            ++nBitSet;
+        i >>= 1;
+    }
+    return nBitSet == 1;
+}
+
+/************************************************************************/
+/*                          IBuildOverviews()                           */
+/************************************************************************/
+
+CPLErr OGRSQLiteDataSource::IBuildOverviews(
+    const char * pszResampling,
+    int nOverviews, int * panOverviewList,
+    int nBandsIn, int * /*panBandList */,
+    GDALProgressFunc /*pfnProgress*/, void * /*pProgressData*/ )
+
+{
+    if( nBandsIn != nBands )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Only build of all bands is supported");
+    }
+
+    if( nOverviews == 0 )
+    {
+        int ret;
+        if( m_bRL2MixedResolutions && m_nSectionId >= 0 )
+        {
+            ret = rl2_delete_section_pyramid (hDB, m_osCoverageName,
+                                              m_nSectionId);
+        }
+        else
+        {
+            ret = rl2_delete_all_pyramids (hDB, m_osCoverageName);
+        }
+        if( ret != RL2_OK )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Deletion of pyramids failed");
+            return CE_Failure;
+        }
+    }
+    else
+    {
+        if( !STARTS_WITH_CI(pszResampling, "NEAR") )
+        {
+            CPLError(CE_Warning, CPLE_AppDefined,
+                "Resampling method is ignored. Using librasterlite2 own method");
+        }
+        for( int i = 0; i < nOverviews; ++i )
+        {
+            if( !IsPowerOfTwo(panOverviewList[i]) )
+            {
+                CPLError(CE_Failure, CPLE_NotSupported,
+                         "Only power-of-two overview factors are supported");
+                return CE_Failure;
+            }
+        }
+
+        const int nMaxThreads = 1;
+        const int bForcedRebuild = 1;
+        const int bVerbose = 0;
+        const int bVirtualLevels = 1;
+        int ret;
+        if( m_bRL2MixedResolutions )
+        {
+            if( m_nSectionId >= 0 )
+            {
+                ret = rl2_build_section_pyramid( hDB, nMaxThreads,
+                                           m_osCoverageName, m_nSectionId,
+                                           bForcedRebuild, bVerbose);
+            }
+            else
+            {
+                ret = rl2_build_monolithic_pyramid (hDB, m_osCoverageName,
+                                                    bVirtualLevels,
+                                                    bVerbose);
+
+            }
+        }
+        else
+        {
+            ret = rl2_build_monolithic_pyramid (hDB, m_osCoverageName,
+                                                bVirtualLevels,
+                                                bVerbose);
+        }
+        if( ret != RL2_OK )
+        {
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Build of pyramids failed");
+            return CE_Failure;
+        }
+    }
+
+    for(size_t i=0;i<m_apoOverviewDS.size();++i)
+        delete m_apoOverviewDS[i];
+    m_apoOverviewDS.clear();
+    ListOverviews();
+
+    return CE_None;
+}
+
+#endif // HAVE_RASTERLITE2
+
+/************************************************************************/
+/*                             GetMetadata()                            */
+/************************************************************************/
+
+char** OGRSQLiteDataSource::GetMetadata(const char* pszDomain)
+{
+    if( pszDomain != NULL && EQUAL( pszDomain, "SUBDATASETS" ) &&
+        m_aosSubDatasets.size() > 2 )
+    {
+        return m_aosSubDatasets.List();
+    }
+    return GDALPamDataset::GetMetadata(pszDomain);
+}
+
+/************************************************************************/
+/*                           GetGeoTransform()                          */
+/************************************************************************/
+
+CPLErr OGRSQLiteDataSource::GetGeoTransform( double* padfGeoTransform )
+{
+    if( m_bGeoTransformValid )
+    {
+        memcpy( padfGeoTransform, m_adfGeoTransform, 6 * sizeof(double) );
+        return CE_None;
+    }
+    return GDALPamDataset::GetGeoTransform(padfGeoTransform);
+}
+
+/************************************************************************/
+/*                           GetProjectionRef()                         */
+/************************************************************************/
+
+const char* OGRSQLiteDataSource::GetProjectionRef()
+{
+    if( !m_osProjection.empty() )
+        return m_osProjection.c_str();
+    return GDALPamDataset::GetProjectionRef();
+}
diff --git a/ogr/ogrsf_frmts/sqlite/rasterlite2_header.h b/ogr/ogrsf_frmts/sqlite/rasterlite2_header.h
new file mode 100644
index 0000000..45ca5ad
--- /dev/null
+++ b/ogr/ogrsf_frmts/sqlite/rasterlite2_header.h
@@ -0,0 +1,49 @@
+/******************************************************************************
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Implements RasterLite2 support class.
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ ******************************************************************************
+ *
+ * CREDITS: The RasterLite2 module has been completely funded by:
+ * Regione Toscana - Settore Sistema Informativo Territoriale ed
+ * Ambientale (GDAL/RasterLite2 driver)
+ * CIG: 644544015A
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef RASTERLITE_HEADER_H
+#define RASTERLITE_HEADER_H
+
+#include "cpl_port.h"
+
+#if ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && !defined(_MSC_VER))
+#pragma GCC system_header
+#endif
+
+#ifdef HAVE_RASTERLITE2
+#include "rasterlite2/rasterlite2.h"
+#endif
+
+#endif // RASTERLITE_HEADER_H
diff --git a/ogr/ogrsf_frmts/sua/ogr_sua.h b/ogr/ogrsf_frmts/sua/ogr_sua.h
index b0c384d..29f9e0a 100644
--- a/ogr/ogrsf_frmts/sua/ogr_sua.h
+++ b/ogr/ogrsf_frmts/sua/ogr_sua.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sua.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogr_sua.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  SUA Translator
  * Purpose:  Definition of classes for OGR .sua driver.
@@ -42,8 +42,8 @@ class OGRSUALayer : public OGRLayer
     OGRSpatialReference *poSRS;
 
     VSILFILE*          fpSUA;
-    int                bEOF;
-    int                bHasLastLine;
+    bool               bEOF;
+    bool               bHasLastLine;
     CPLString          osLastLine;
 
     int                nNextFID;
@@ -51,16 +51,15 @@ class OGRSUALayer : public OGRLayer
     OGRFeature *       GetNextRawFeature();
 
   public:
-                        OGRSUALayer(VSILFILE* fp);
-                        ~OGRSUALayer();
+    explicit            OGRSUALayer(VSILFILE* fp);
+                        virtual ~OGRSUALayer();
 
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
-
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 /************************************************************************/
@@ -76,16 +75,16 @@ class OGRSUADataSource : public OGRDataSource
 
   public:
                         OGRSUADataSource();
-                        ~OGRSUADataSource();
+                        virtual ~OGRSUADataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
 #endif /* ndef OGR_SUA_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp b/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp
index 2425836..4a6a6d4 100644
--- a/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsuadatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsuadatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUADataSource class
@@ -31,20 +30,17 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrsuadatasource.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: ogrsuadatasource.cpp 35202 2016-08-25 15:43:35Z goatbar $");
 
 /************************************************************************/
 /*                          OGRSUADataSource()                          */
 /************************************************************************/
 
-OGRSUADataSource::OGRSUADataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-}
+OGRSUADataSource::OGRSUADataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0)
+{}
 
 /************************************************************************/
 /*                         ~OGRSUADataSource()                          */
diff --git a/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp b/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp
index 13953c4..c84eb17 100644
--- a/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsuadriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsuadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUADriver.
@@ -30,7 +29,7 @@
 #include "ogr_sua.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsuadriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrsuadriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 extern "C" void RegisterOGRSUA();
 
@@ -125,4 +124,3 @@ void RegisterOGRSUA()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/sua/ogrsualayer.cpp b/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
index f27486f..d0255d2 100644
--- a/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
+++ b/ogr/ogrsf_frmts/sua/ogrsualayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsualayer.cpp 31478 2015-11-14 19:13:16Z goatbar $
  *
  * Project:  SUA Translator
  * Purpose:  Implements OGRSUALayer class.
@@ -34,37 +33,34 @@
 #include "ogr_xplane_geo_utils.h"
 #include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrsualayer.cpp 31478 2015-11-14 19:13:16Z goatbar $");
+CPL_CVSID("$Id: ogrsualayer.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                            OGRSUALayer()                             */
 /************************************************************************/
 
-OGRSUALayer::OGRSUALayer( VSILFILE* fp )
-
+OGRSUALayer::OGRSUALayer( VSILFILE* fp ) :
+    poFeatureDefn(new OGRFeatureDefn( "layer" )),
+    poSRS(new OGRSpatialReference(SRS_WKT_WGS84)),
+    fpSUA(fp),
+    bEOF(false),
+    bHasLastLine(false),
+    nNextFID(0)
 {
-    fpSUA = fp;
-    nNextFID = 0;
-    bEOF = FALSE;
-    bHasLastLine = FALSE;
-
-    poSRS = new OGRSpatialReference(SRS_WKT_WGS84);
-
-    poFeatureDefn = new OGRFeatureDefn( "layer" );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbPolygon );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
-    OGRFieldDefn    oField1( "TYPE", OFTString);
+    OGRFieldDefn oField1( "TYPE", OFTString);
     poFeatureDefn->AddFieldDefn( &oField1 );
-    OGRFieldDefn    oField2( "CLASS", OFTString);
+    OGRFieldDefn oField2( "CLASS", OFTString);
     poFeatureDefn->AddFieldDefn( &oField2 );
-    OGRFieldDefn    oField3( "TITLE", OFTString);
+    OGRFieldDefn oField3( "TITLE", OFTString);
     poFeatureDefn->AddFieldDefn( &oField3 );
-    OGRFieldDefn    oField4( "TOPS", OFTString);
+    OGRFieldDefn oField4( "TOPS", OFTString);
     poFeatureDefn->AddFieldDefn( &oField4 );
-    OGRFieldDefn    oField5( "BASE", OFTString);
+    OGRFieldDefn oField5( "BASE", OFTString);
     poFeatureDefn->AddFieldDefn( &oField5 );
 }
 
@@ -83,7 +79,6 @@ OGRSUALayer::~OGRSUALayer()
     VSIFCloseL( fpSUA );
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -92,23 +87,20 @@ void OGRSUALayer::ResetReading()
 
 {
     nNextFID = 0;
-    bEOF = FALSE;
-    bHasLastLine = FALSE;
+    bEOF = false;
+    bHasLastLine = false;
     VSIFSeekL( fpSUA, 0, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
 
 OGRFeature *OGRSUALayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
-
     while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -124,20 +116,18 @@ OGRFeature *OGRSUALayer::GetNextFeature()
     }
 }
 
-
-
 /************************************************************************/
 /*                              GetLatLon()                             */
 /************************************************************************/
 
-static int GetLatLon(const char* pszStr, double& dfLat, double& dfLon)
+static bool GetLatLon( const char* pszStr, double& dfLat, double& dfLon )
 {
     if (pszStr[7] != ' ')
-        return FALSE;
+        return false;
     if (pszStr[0] != 'N' && pszStr[0] != 'S')
-        return FALSE;
+        return false;
     if (pszStr[8] != 'E' && pszStr[8] != 'W')
-        return FALSE;
+        return false;
 
     char szDeg[4], szMin[3], szSec[3];
     szDeg[0] = pszStr[1];
@@ -169,7 +159,7 @@ static int GetLatLon(const char* pszStr, double& dfLat, double& dfLon)
     if (pszStr[8] == 'W')
         dfLon = -dfLon;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -178,34 +168,39 @@ static int GetLatLon(const char* pszStr, double& dfLat, double& dfLon)
 
 OGRFeature *OGRSUALayer::GetNextRawFeature()
 {
-    const char* pszLine;
-    CPLString osTYPE, osCLASS, osTITLE, osTOPS, osBASE;
-    OGRLinearRing oLR;
-    double dfLastLat = 0, dfLastLon = 0;
-    int bFirst = TRUE;
-
-    if (bEOF)
+    if( bEOF )
         return NULL;
 
+    CPLString osTYPE;
+    CPLString osCLASS;
+    CPLString osTITLE;
+    CPLString osTOPS;
+    CPLString osBASE;
+    OGRLinearRing oLR;
+    double dfLastLat = 0.0;
+    double dfLastLon = 0.0;
+    bool bFirst = true;
+
     while( true )
     {
-        if (bFirst && bHasLastLine)
+        const char* pszLine = NULL;
+        if( bFirst && bHasLastLine )
         {
             pszLine = osLastLine.c_str();
-            bFirst = FALSE;
+            bFirst = false;
         }
         else
         {
             pszLine = CPLReadLine2L(fpSUA, 1024, NULL);
             if (pszLine == NULL)
             {
-                bEOF = TRUE;
+                bEOF = true;
                 if (oLR.getNumPoints() == 0)
                     return NULL;
                 break;
             }
             osLastLine = pszLine;
-            bHasLastLine = TRUE;
+            bHasLastLine = true;
         }
 
         if (pszLine[0] == '#' || pszLine[0] == '\0')
@@ -213,19 +208,19 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
 
         if (STARTS_WITH_CI(pszLine, "TYPE="))
         {
-            if (osTYPE.size() != 0)
+            if (!osTYPE.empty())
                 break;
             osTYPE = pszLine + 5;
         }
         else if (STARTS_WITH_CI(pszLine, "CLASS="))
         {
-            if (osCLASS.size() != 0)
+            if (!osCLASS.empty())
                 break;
             osCLASS = pszLine + 6;
         }
         else if (STARTS_WITH_CI(pszLine, "TITLE="))
         {
-            if (osTITLE.size() != 0)
+            if (!osTITLE.empty())
                 break;
             osTITLE = pszLine + 6;
         }
@@ -239,7 +234,8 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
             if (strlen(pszLine) != 16)
                 continue;
 
-            double dfLat, dfLon;
+            double dfLat = 0.0;
+            double dfLon = 0.0;
             if (!GetLatLon(pszLine, dfLat, dfLon))
                 continue;
 
@@ -265,7 +261,8 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
             pszCENTRE += 7;
             if (strlen(pszCENTRE) < 17 || pszCENTRE[16] != ' ')
                 continue;
-            double dfCenterLat, dfCenterLon;
+            double dfCenterLat = 0.0;
+            double dfCenterLon = 0.0;
             if (!GetLatLon(pszCENTRE, dfCenterLat, dfCenterLon))
                 continue;
 
@@ -275,26 +272,34 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
             pszTO += 3;
             if (strlen(pszTO) != 16)
                 continue;
-            double dfToLat, dfToLon;
+            double dfToLat = 0.0;
+            double dfToLon = 0.0;
             if (!GetLatLon(pszTO, dfToLat, dfToLon))
                 continue;
 
-            double dfStartDistance = OGRXPlane_Distance(dfCenterLat, dfCenterLon, dfLastLat, dfLastLon);
-            double dfEndDistance = OGRXPlane_Distance(dfCenterLat, dfCenterLon, dfToLat, dfToLon);
-            double dfStartAngle = OGRXPlane_Track(dfCenterLat, dfCenterLon, dfLastLat, dfLastLon);
-            double dfEndAngle = OGRXPlane_Track(dfCenterLat, dfCenterLon, dfToLat, dfToLon);
-            if (bClockWise && dfEndAngle < dfStartAngle)
+            const double dfStartDistance =
+                OGRXPlane_Distance(dfCenterLat, dfCenterLon, dfLastLat, dfLastLon);
+            const double dfEndDistance =
+                OGRXPlane_Distance(dfCenterLat, dfCenterLon, dfToLat, dfToLon);
+            const double dfStartAngle =
+                OGRXPlane_Track(dfCenterLat, dfCenterLon, dfLastLat, dfLastLon);
+            double dfEndAngle =
+                OGRXPlane_Track(dfCenterLat, dfCenterLon, dfToLat, dfToLon);
+
+            if( bClockWise && dfEndAngle < dfStartAngle )
                 dfEndAngle += 360;
             else if (!bClockWise && dfStartAngle < dfEndAngle)
                 dfEndAngle -= 360;
 
             int nSign = (bClockWise) ? 1 : -1;
-            double dfAngle;
-            for(dfAngle = dfStartAngle; (dfAngle - dfEndAngle) * nSign < 0; dfAngle += nSign)
+            for( double dfAngle = dfStartAngle;
+                 (dfAngle - dfEndAngle) * nSign < 0;
+                 dfAngle += nSign )
             {
-                double dfLat, dfLon;
-                double pct = (dfAngle - dfStartAngle) / (dfEndAngle - dfStartAngle);
-                double dfDist = dfStartDistance * (1-pct) + dfEndDistance * pct;
+                const double pct = (dfAngle - dfStartAngle) / (dfEndAngle - dfStartAngle);
+                const double dfDist = dfStartDistance * (1-pct) + dfEndDistance * pct;
+                double dfLat = 0.0;
+                double dfLon = 0.0;
                 OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon, dfDist, dfAngle, &dfLat, &dfLon);
                 oLR.addPoint(dfLon, dfLat);
             }
@@ -316,13 +321,14 @@ OGRFeature *OGRSUALayer::GetNextRawFeature()
             pszCENTRE += 7;
             if (strlen(pszCENTRE) != 16)
                 continue;
-            double dfCenterLat, dfCenterLon;
+            double dfCenterLat = 0.0;
+            double dfCenterLon = 0.0;
             if (!GetLatLon(pszCENTRE, dfCenterLat, dfCenterLon))
                 continue;
 
-            double dfAngle;
-            double dfLat, dfLon;
-            for(dfAngle = 0; dfAngle < 360; dfAngle += 1)
+            double dfLat = 0.0;
+            double dfLon = 0.0;
+            for( double dfAngle = 0; dfAngle < 360; dfAngle += 1 )
             {
                 OGRXPlane_ExtendPosition(dfCenterLat, dfCenterLon, dfRADIUS, dfAngle, &dfLat, &dfLon);
                 oLR.addPoint(dfLon, dfLat);
diff --git a/ogr/ogrsf_frmts/svg/ogr_svg.h b/ogr/ogrsf_frmts/svg/ogr_svg.h
index 0c89ace..88eb210 100644
--- a/ogr/ogrsf_frmts/svg/ogr_svg.h
+++ b/ogr/ogrsf_frmts/svg/ogr_svg.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_svg.h 32177 2015-12-14 07:25:30Z goatbar $
+ * $Id: ogr_svg.h 36569 2016-11-30 13:04:32Z goatbar $
  *
  * Project:  SVG Translator
  * Purpose:  Definition of classes for OGR .svg driver.
@@ -53,14 +53,16 @@ class OGRSVGLayer : public OGRLayer
 {
     OGRFeatureDefn*    poFeatureDefn;
     OGRSpatialReference *poSRS;
+#ifdef HAVE_EXPAT
     OGRSVGDataSource*  poDS;
+#endif
     CPLString          osLayerName;
 
     SVGGeometryType    svgGeomType;
 
     int                nTotalFeatures;
     int                nNextFID;
-    VSILFILE*          fpSVG; /* Large file API */
+    VSILFILE*          fpSVG;  // Large file API.
 
 #ifdef HAVE_EXPAT
     XML_Parser         oParser;
@@ -77,9 +79,9 @@ class OGRSVGLayer : public OGRLayer
 
     int                depthLevel;
     int                interestingDepthLevel;
-    int                inInterestingElement;
+    bool               inInterestingElement;
 
-    int                bStopParsing;
+    bool               bStopParsing;
 #ifdef HAVE_EXPAT
     int                nWithoutEventCounter;
     int                nDataHandlerCounter;
@@ -95,19 +97,19 @@ class OGRSVGLayer : public OGRLayer
                                     const char* layerName,
                                     SVGGeometryType svgGeomType,
                                     OGRSVGDataSource* poDS);
-                        ~OGRSVGLayer();
+                        virtual ~OGRSVGLayer();
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual const char*         GetName() { return osLayerName.c_str(); }
-    virtual OGRwkbGeometryType  GetGeomType();
+    virtual const char*         GetName() override { return osLayerName.c_str(); }
+    virtual OGRwkbGeometryType  GetGeomType() override;
 
-    virtual GIntBig             GetFeatureCount( int bForce = TRUE );
+    virtual GIntBig             GetFeatureCount( int bForce = TRUE ) override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
 #ifdef HAVE_EXPAT
     void                startElementCbk(const char *pszName, const char **ppszAttr);
@@ -147,17 +149,16 @@ class OGRSVGDataSource : public OGRDataSource
 
   public:
                         OGRSVGDataSource();
-                        ~OGRSVGDataSource();
+                        virtual ~OGRSVGDataSource();
 
     int                 Open( const char * pszFilename );
 
-    virtual const char*         GetName() { return pszName; }
-
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
+    virtual int                 TestCapability( const char * ) override;
 
 #ifdef HAVE_EXPAT
     void                startElementValidateCbk(const char *pszName, const char **ppszAttr);
diff --git a/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp b/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
index 3bbb727..7ecc262 100644
--- a/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
+++ b/ogr/ogrsf_frmts/svg/ogrsvgdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsvgdatasource.cpp 32011 2015-12-06 10:19:18Z rouault $
  *
  * Project:  SVG Translator
  * Purpose:  Implements OGRSVGDataSource class
@@ -30,7 +29,7 @@
 #include "ogr_svg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsvgdatasource.cpp 32011 2015-12-06 10:19:18Z rouault $");
+CPL_CVSID("$Id: ogrsvgdatasource.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                          OGRSVGDataSource()                          */
@@ -47,8 +46,7 @@ OGRSVGDataSource::OGRSVGDataSource() :
     oCurrentParser(NULL),
     nDataHandlerCounter(0)
 #endif
-{
-}
+{}
 
 /************************************************************************/
 /*                         ~OGRSVGDataSource()                          */
@@ -89,9 +87,8 @@ void OGRSVGDataSource::startElementValidateCbk(const char *pszNameIn,
     {
         if (strcmp(pszNameIn, "svg") == 0)
         {
-            int i;
             eValidity = SVG_VALIDITY_VALID;
-            for(i=0; ppszAttr[i] != NULL; i+= 2)
+            for( int i = 0; ppszAttr[i] != NULL; i += 2 )
             {
                 if (strcmp(ppszAttr[i], "xmlns:cm") == 0 &&
                     strcmp(ppszAttr[i+1], "http://cloudmade.com/") == 0)
@@ -108,7 +105,6 @@ void OGRSVGDataSource::startElementValidateCbk(const char *pszNameIn,
     }
 }
 
-
 /************************************************************************/
 /*                      dataHandlerValidateCbk()                        */
 /************************************************************************/
@@ -125,7 +121,6 @@ void OGRSVGDataSource::dataHandlerValidateCbk(CPL_UNUSED const char *data,
     }
 }
 
-
 static void XMLCALL startElementValidateCbk(void *pUserData,
                                             const char *pszName, const char **ppszAttr)
 {
@@ -174,8 +169,8 @@ int OGRSVGDataSource::Open( const char * pszFilename )
     XML_SetCharacterDataHandler(oParser, ::dataHandlerValidateCbk);
 
     char aBuf[BUFSIZ];
-    int nDone;
-    unsigned int nLen;
+    int nDone = 0;
+    unsigned int nLen = 0;
     int nCount = 0;
 
     /* Begin to parse the file and look for the <svg> element */
@@ -245,7 +240,7 @@ int OGRSVGDataSource::Open( const char * pszFilename )
         }
     }
 
-    return (nLayers > 0);
+    return nLayers > 0;
 #else
     char aBuf[256];
     VSILFILE* fp = VSIFOpenL(pszFilename, "r");
diff --git a/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp b/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
index 516b2c4..e5af554 100644
--- a/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
+++ b/ogr/ogrsf_frmts/svg/ogrsvgdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsvgdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  SVG Translator
  * Purpose:  Implements OGRSVGDriver.
@@ -30,7 +29,7 @@
 #include "ogr_svg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsvgdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrsvgdriver.cpp 36569 2016-11-30 13:04:32Z goatbar $");
 
 CPL_C_START
 void RegisterOGRSVG();
@@ -51,7 +50,7 @@ static GDALDataset *OGRSVGDriverOpen( GDALOpenInfo* poOpenInfo )
     if( strstr((const char*)poOpenInfo->pabyHeader, "<svg") == NULL )
         return NULL;
 
-    OGRSVGDataSource   *poDS = new OGRSVGDataSource();
+    OGRSVGDataSource *poDS = new OGRSVGDataSource();
 
     if( !poDS->Open( poOpenInfo->pszFilename ) )
     {
@@ -88,4 +87,3 @@ void RegisterOGRSVG()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp b/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
index 5760dbe..76f810c 100644
--- a/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
+++ b/ogr/ogrsf_frmts/svg/ogrsvglayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsvglayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  SVG Translator
  * Purpose:  Implements OGRSVGLayer class.
@@ -30,7 +29,7 @@
 #include "ogr_svg.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrsvglayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+CPL_CVSID("$Id: ogrsvglayer.cpp 36569 2016-11-30 13:04:32Z goatbar $");
 
 /************************************************************************/
 /*                            OGRSVGLayer()                             */
@@ -39,10 +38,17 @@ CPL_CVSID("$Id: ogrsvglayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
 OGRSVGLayer::OGRSVGLayer( const char* pszFilename,
                           const char* pszLayerName,
                           SVGGeometryType svgGeomTypeIn,
-                          OGRSVGDataSource* poDSIn) :
+#ifndef HAVE_EXPAT
+                          CPL_UNUSED
+#endif
+                          OGRSVGDataSource* poDSIn ) :
     poFeatureDefn(NULL),
     poSRS(NULL),
-    poDS(NULL),
+#ifdef HAVE_EXPAT
+    poDS(poDSIn),
+#endif
+    osLayerName(pszLayerName),
+    svgGeomType(svgGeomTypeIn),
     nTotalFeatures(0),
     nNextFID(0),
     fpSVG(NULL),
@@ -59,8 +65,8 @@ OGRSVGLayer::OGRSVGLayer( const char* pszFilename,
     nFeatureTabIndex(0),
     depthLevel(0),
     interestingDepthLevel(0),
-    inInterestingElement(FALSE),
-    bStopParsing(FALSE)
+    inInterestingElement(false),
+    bStopParsing(false)
 #ifdef HAVE_EXPAT
         ,
     nWithoutEventCounter(0),
@@ -69,9 +75,6 @@ OGRSVGLayer::OGRSVGLayer( const char* pszFilename,
 #endif
 
 {
-    this->poDS = poDSIn;
-    this->svgGeomType = svgGeomTypeIn;
-    osLayerName = pszLayerName;
     SetDescription( pszLayerName );
 
     poSRS = new OGRSpatialReference("PROJCS[\"WGS 84 / Pseudo-Mercator\","
@@ -126,8 +129,7 @@ OGRSVGLayer::~OGRSVGLayer()
 
     CPLFree(pszSubElementValue);
 
-    int i;
-    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+    for( int i = nFeatureTabIndex;i<nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
 
@@ -185,8 +187,7 @@ void OGRSVGLayer::ResetReading()
     nSubElementValueLen = 0;
     iCurrentField = -1;
 
-    int i;
-    for(i=nFeatureTabIndex;i<nFeatureTabLength;i++)
+    for( int i = nFeatureTabIndex; i < nFeatureTabLength; i++ )
         delete ppoFeatureTab[i];
     CPLFree(ppoFeatureTab);
     nFeatureTabIndex = 0;
@@ -198,7 +199,7 @@ void OGRSVGLayer::ResetReading()
 
     depthLevel = 0;
     interestingDepthLevel = 0;
-    inInterestingElement = FALSE;
+    inInterestingElement = false;
 }
 
 #ifdef HAVE_EXPAT
@@ -228,15 +229,15 @@ static void OGRSVGParseD(OGRLineString* poLS, const char* pszD)
     char szBuffer[32];
     int iBuffer = 0;
     const char* pszIter = pszD;
-    char ch;
     int iNumber = 0;
-    double dfPrevNumber = 0;
-    int bRelativeLineto = FALSE;
-    double dfX = 0, dfY = 0;
+    double dfPrevNumber = 0.0;
+    bool bRelativeLineto = false;
+    double dfX = 0.0;
+    double dfY = 0.0;
     int nPointCount = 0;
     while( true )
     {
-        ch = *(pszIter ++);
+        const char ch = *(pszIter ++);
 
         if (ch == 'M' || ch == 'm')
         {
@@ -248,7 +249,7 @@ static void OGRSVGParseD(OGRLineString* poLS, const char* pszD)
         }
         else if (ch == 'L')
         {
-            bRelativeLineto = FALSE;
+            bRelativeLineto = false;
         }
         else if (ch == 'l')
         {
@@ -257,7 +258,7 @@ static void OGRSVGParseD(OGRLineString* poLS, const char* pszD)
                 CPLDebug("SVG", "Relative lineto at the beginning of the line");
                 return;
             }
-            bRelativeLineto = TRUE;
+            bRelativeLineto = true;
         }
         else if (ch == 'z' || ch == 'Z')
         {
@@ -281,10 +282,10 @@ static void OGRSVGParseD(OGRLineString* poLS, const char* pszD)
                 szBuffer[iBuffer] = 0;
                 if (iNumber == 1)
                 {
-                    /* Cloudmade --> negate y */
-                    double dfNumber = -CPLAtof(szBuffer);
+                    // Cloudmade --> negate y.
+                    const double dfNumber = -CPLAtof(szBuffer);
 
-                    if (bRelativeLineto)
+                    if( bRelativeLineto )
                     {
                         dfX += dfPrevNumber;
                         dfY += dfNumber;
@@ -319,9 +320,7 @@ static void OGRSVGParseD(OGRLineString* poLS, const char* pszD)
 
 void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
 {
-    int i;
-
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
 
@@ -329,18 +328,20 @@ void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         strcmp(pszName, "circle") == 0 &&
         strcmp(OGRSVGGetClass(ppszAttr), "point") == 0)
     {
-        int bHasFoundX = FALSE, bHasFoundY = FALSE;
-        double dfX = 0, dfY = 0;
-        for (i = 0; ppszAttr[i]; i += 2)
+        bool bHasFoundX = false;
+        bool bHasFoundY = false;
+        double dfX = 0.0;
+        double dfY = 0.0;
+        for( int i = 0; ppszAttr[i]; i += 2 )
         {
             if (strcmp(ppszAttr[i], "cx") == 0)
             {
-                bHasFoundX = TRUE;
+                bHasFoundX = true;
                 dfX = CPLAtof(ppszAttr[i + 1]);
             }
             else if (strcmp(ppszAttr[i], "cy") == 0)
             {
-                bHasFoundY = TRUE;
+                bHasFoundY = true;
                 /* Cloudmade --> negate y */
                 dfY = - CPLAtof(ppszAttr[i + 1]);
             }
@@ -348,7 +349,7 @@ void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         if (bHasFoundX && bHasFoundY)
         {
             interestingDepthLevel = depthLevel;
-            inInterestingElement = TRUE;
+            inInterestingElement = true;
 
             if (poFeature)
                 delete poFeature;
@@ -366,7 +367,7 @@ void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
              strcmp(OGRSVGGetClass(ppszAttr), "line") == 0)
     {
         const char* pszD = NULL;
-        for (i = 0; ppszAttr[i]; i += 2)
+        for( int i = 0; ppszAttr[i]; i += 2 )
         {
             if (strcmp(ppszAttr[i], "d") == 0)
             {
@@ -377,7 +378,7 @@ void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         if (pszD)
         {
             interestingDepthLevel = depthLevel;
-            inInterestingElement = TRUE;
+            inInterestingElement = true;
 
             if (poFeature)
                 delete poFeature;
@@ -396,7 +397,7 @@ void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
              strcmp(OGRSVGGetClass(ppszAttr), "polygon") == 0)
     {
         const char* pszD = NULL;
-        for (i = 0; ppszAttr[i]; i += 2)
+        for( int i = 0; ppszAttr[i]; i += 2 )
         {
             if (strcmp(ppszAttr[i], "d") == 0)
             {
@@ -407,7 +408,7 @@ void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
         if (pszD)
         {
             interestingDepthLevel = depthLevel;
-            inInterestingElement = TRUE;
+            inInterestingElement = true;
 
             if (poFeature)
                 delete poFeature;
@@ -423,9 +424,9 @@ void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
             poFeature->SetGeometryDirectly( poPolygon );
         }
     }
-    else if (inInterestingElement &&
+    else if( inInterestingElement &&
              depthLevel == interestingDepthLevel + 1 &&
-             STARTS_WITH(pszName, "cm:"))
+             STARTS_WITH(pszName, "cm:") )
     {
         iCurrentField = poFeatureDefn->GetFieldIndex(pszName + 3);
     }
@@ -439,17 +440,17 @@ void OGRSVGLayer::startElementCbk(const char *pszName, const char **ppszAttr)
 
 void OGRSVGLayer::endElementCbk(CPL_UNUSED const char *pszName)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
 
     depthLevel--;
 
-    if (inInterestingElement)
+    if( inInterestingElement )
     {
         if (depthLevel == interestingDepthLevel)
         {
-            inInterestingElement = FALSE;
+            inInterestingElement = false;
 
             if( (m_poFilterGeom == NULL
                     || FilterGeometry( poFeature->GetGeometryRef() ) )
@@ -490,7 +491,7 @@ void OGRSVGLayer::endElementCbk(CPL_UNUSED const char *pszName)
 
 void OGRSVGLayer::dataHandlerCbk(const char *data, int nLen)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nDataHandlerCounter ++;
     if (nDataHandlerCounter >= BUFSIZ)
@@ -498,7 +499,7 @@ void OGRSVGLayer::dataHandlerCbk(const char *data, int nLen)
         CPLError(CE_Failure, CPLE_AppDefined,
                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
@@ -511,7 +512,7 @@ void OGRSVGLayer::dataHandlerCbk(const char *data, int nLen)
         if (pszNewSubElementValue == NULL)
         {
             XML_StopParser(oParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
             return;
         }
         pszSubElementValue = pszNewSubElementValue;
@@ -522,7 +523,7 @@ void OGRSVGLayer::dataHandlerCbk(const char *data, int nLen)
             CPLError(CE_Failure, CPLE_AppDefined,
                      "Too much data inside one element. File probably corrupted");
             XML_StopParser(oParser, XML_FALSE);
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
     }
 }
@@ -539,7 +540,7 @@ OGRFeature *OGRSVGLayer::GetNextFeature()
     if (fpSVG == NULL)
         return NULL;
 
-    if (bStopParsing)
+    if( bStopParsing )
         return NULL;
 
 #ifdef HAVE_EXPAT
@@ -560,7 +561,7 @@ OGRFeature *OGRSVGLayer::GetNextFeature()
     nWithoutEventCounter = 0;
     iCurrentField = -1;
 
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -574,18 +575,18 @@ OGRFeature *OGRSVGLayer::GetNextFeature()
                      XML_ErrorString(XML_GetErrorCode(oParser)),
                      (int)XML_GetCurrentLineNumber(oParser),
                      (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
             break;
         }
         nWithoutEventCounter ++;
-    } while (!nDone && nFeatureTabLength == 0 && !bStopParsing &&
-             nWithoutEventCounter < 1000);
+    } while( !nDone && nFeatureTabLength == 0 && !bStopParsing &&
+             nWithoutEventCounter < 1000 );
 
     if (nWithoutEventCounter == 1000)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
 
     return (nFeatureTabLength) ? ppoFeatureTab[nFeatureTabIndex++] : NULL;
@@ -612,7 +613,6 @@ int OGRSVGLayer::TestCapability( const char * pszCap )
         return FALSE;
 }
 
-
 /************************************************************************/
 /*                       LoadSchema()                         */
 /************************************************************************/
@@ -637,7 +637,6 @@ static void XMLCALL dataHandlerLoadSchemaCbk(void *pUserData,
     ((OGRSVGLayer*)pUserData)->dataHandlerLoadSchemaCbk(data, nLen);
 }
 
-
 /** This function parses the whole file to build the schema */
 void OGRSVGLayer::LoadSchema()
 {
@@ -663,13 +662,13 @@ void OGRSVGLayer::LoadSchema()
 
     VSIFSeekL( fpSVG, 0, SEEK_SET );
 
-    inInterestingElement = FALSE;
+    inInterestingElement = false;
     depthLevel = 0;
     nWithoutEventCounter = 0;
-    bStopParsing = FALSE;
+    bStopParsing = false;
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -683,17 +682,17 @@ void OGRSVGLayer::LoadSchema()
                      XML_ErrorString(XML_GetErrorCode(oSchemaParser)),
                      (int)XML_GetCurrentLineNumber(oSchemaParser),
                      (int)XML_GetCurrentColumnNumber(oSchemaParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
             break;
         }
         nWithoutEventCounter ++;
-    } while (!nDone && !bStopParsing && nWithoutEventCounter < 1000);
+    } while( !nDone && !bStopParsing && nWithoutEventCounter < 1000 );
 
     if (nWithoutEventCounter == 1000)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
 
     XML_ParserFree(oSchemaParser);
@@ -702,7 +701,6 @@ void OGRSVGLayer::LoadSchema()
     VSIFSeekL( fpSVG, 0, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                  startElementLoadSchemaCbk()                         */
 /************************************************************************/
@@ -710,7 +708,7 @@ void OGRSVGLayer::LoadSchema()
 void OGRSVGLayer::startElementLoadSchemaCbk(const char *pszName,
                                             const char **ppszAttr)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
 
@@ -719,7 +717,7 @@ void OGRSVGLayer::startElementLoadSchemaCbk(const char *pszName,
     {
         poCurLayer = (OGRSVGLayer*)poDS->GetLayer(0);
         poCurLayer->nTotalFeatures ++;
-        inInterestingElement = TRUE;
+        inInterestingElement = true;
         interestingDepthLevel = depthLevel;
     }
     else if (strcmp(pszName, "path") == 0 &&
@@ -727,7 +725,7 @@ void OGRSVGLayer::startElementLoadSchemaCbk(const char *pszName,
     {
         poCurLayer = (OGRSVGLayer*)poDS->GetLayer(1);
         poCurLayer->nTotalFeatures ++;
-        inInterestingElement = TRUE;
+        inInterestingElement = true;
         interestingDepthLevel = depthLevel;
     }
     else if (strcmp(pszName, "path") == 0 &&
@@ -735,10 +733,10 @@ void OGRSVGLayer::startElementLoadSchemaCbk(const char *pszName,
     {
         poCurLayer = (OGRSVGLayer*)poDS->GetLayer(2);
         poCurLayer->nTotalFeatures ++;
-        inInterestingElement = TRUE;
+        inInterestingElement = true;
         interestingDepthLevel = depthLevel;
     }
-    else if (inInterestingElement)
+    else if( inInterestingElement )
     {
         if (depthLevel == interestingDepthLevel + 1 &&
             STARTS_WITH(pszName, "cm:"))
@@ -768,16 +766,16 @@ void OGRSVGLayer::startElementLoadSchemaCbk(const char *pszName,
 
 void OGRSVGLayer::endElementLoadSchemaCbk(CPL_UNUSED const char *pszName)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
 
     depthLevel--;
 
-    if (inInterestingElement &&
-        depthLevel == interestingDepthLevel)
+    if( inInterestingElement &&
+        depthLevel == interestingDepthLevel )
     {
-        inInterestingElement = FALSE;
+        inInterestingElement = false;
     }
 }
 
@@ -788,7 +786,7 @@ void OGRSVGLayer::endElementLoadSchemaCbk(CPL_UNUSED const char *pszName)
 void OGRSVGLayer::dataHandlerLoadSchemaCbk(CPL_UNUSED const char *data,
                                            CPL_UNUSED int nLen)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nDataHandlerCounter ++;
     if (nDataHandlerCounter >= BUFSIZ)
@@ -796,7 +794,7 @@ void OGRSVGLayer::dataHandlerLoadSchemaCbk(CPL_UNUSED const char *data,
         CPLError(CE_Failure, CPLE_AppDefined,
                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(oSchemaParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
diff --git a/ogr/ogrsf_frmts/sxf/ogr_sxf.h b/ogr/ogrsf_frmts/sxf/ogr_sxf.h
index 97ebd85..0a3081a 100644
--- a/ogr/ogrsf_frmts/sxf/ogr_sxf.h
+++ b/ogr/ogrsf_frmts/sxf/ogr_sxf.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_sxf.h  $
+ * $Id: ogr_sxf.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  SXF Translator
  * Purpose:  Include file defining classes for OGR SXF driver, datasource and layers.
@@ -51,7 +51,7 @@ class OGRSXFLayer : public OGRLayer
 {
 protected:
     OGRFeatureDefn*    poFeatureDefn;
-	VSILFILE*          fpSXF;
+    VSILFILE*          fpSXF;
     GByte              nLayerID;
     std::map<unsigned, CPLString> mnClassificators;
     std::map<long, vsi_l_offset> mnRecordDesc;
@@ -68,7 +68,6 @@ protected:
                          const char *psBuff, GUInt32 nBufLen,
                          double *dfX, double *dfY, double *dfH = NULL);
 
-
     OGRFeature *TranslatePoint(const SXFRecordDescription& certifInfo, const char * psRecordBuf, GUInt32 nBufLen);
     OGRFeature *TranslateText(const SXFRecordDescription& certifInfo, const char * psBuff, GUInt32 nBufLen);
     OGRFeature *TranslatePolygon(const SXFRecordDescription& certifInfo, const char * psBuff, GUInt32 nBufLen);
@@ -76,29 +75,30 @@ protected:
     OGRFeature *TranslateVetorAngle(const SXFRecordDescription& certifInfo, const char * psBuff, GUInt32 nBufLen);
 public:
     OGRSXFLayer(VSILFILE* fp, CPLMutex** hIOMutex, GByte nID, const char* pszLayerName, int nVer, const SXFMapDescription&  sxfMapDesc);
-    ~OGRSXFLayer();
+    virtual ~OGRSXFLayer();
 
-	virtual void                ResetReading();
-    virtual OGRFeature         *GetNextFeature();
-    virtual OGRErr              SetNextByIndex(GIntBig nIndex);
-    virtual OGRFeature         *GetFeature(GIntBig nFID);
-    virtual OGRFeatureDefn     *GetLayerDefn() { return poFeatureDefn;}
+    virtual void                ResetReading() override;
+    virtual OGRFeature         *GetNextFeature() override;
+    virtual OGRErr              SetNextByIndex(GIntBig nIndex) override;
+    virtual OGRFeature         *GetFeature(GIntBig nFID) override;
+    virtual OGRFeatureDefn     *GetLayerDefn() override { return poFeatureDefn;}
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
-    virtual GIntBig     GetFeatureCount(int bForce = TRUE);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual GIntBig     GetFeatureCount(int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
-    virtual OGRSpatialReference *GetSpatialRef();
-    virtual const char* GetFIDColumn();
+    virtual OGRSpatialReference *GetSpatialRef() override;
+    virtual const char* GetFIDColumn() override;
 
     virtual GByte GetId() const { return nLayerID; };
     virtual void AddClassifyCode(unsigned nClassCode, const char *szName = NULL);
-    virtual int AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset, bool bHasSemantic, size_t nSemanticsSize);
+    virtual bool AddRecord( long nFID, unsigned nClassCode,
+                            vsi_l_offset nOffset, bool bHasSemantic,
+                            size_t nSemanticsSize );
 };
 
-
 /************************************************************************/
 /*                        OGRSXFDataSource                       */
 /************************************************************************/
@@ -114,27 +114,27 @@ class OGRSXFDataSource : public OGRDataSource
 
     VSILFILE* fpSXF;
     CPLMutex  *hIOMutex;
-    void FillLayers(void);
+    void FillLayers();
     void CreateLayers();
     void CreateLayers(VSILFILE* fpRSC);
-    OGRErr ReadSXFInformationFlags(VSILFILE* fpSXF, SXFPassport& passport);
+    static OGRErr ReadSXFInformationFlags(VSILFILE* fpSXF, SXFPassport& passport);
     OGRErr ReadSXFDescription(VSILFILE* fpSXF, SXFPassport& passport);
-    void SetVertCS(const long iVCS, SXFPassport& passport);
-    OGRErr ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& passport);
+    static void SetVertCS(const long iVCS, SXFPassport& passport);
+    static OGRErr ReadSXFMapDescription(VSILFILE* fpSXF, SXFPassport& passport);
     OGRSXFLayer*       GetLayerById(GByte);
 public:
                         OGRSXFDataSource();
-                        ~OGRSXFDataSource();
+                        virtual ~OGRSXFDataSource();
 
     int                 Open( const char * pszFilename,
                               int bUpdate );
 
-    virtual const char*     GetName() { return pszName; }
+    virtual const char*     GetName() override { return pszName; }
 
-    virtual int             GetLayerCount() { return static_cast<int>(nLayers); }
-    virtual OGRLayer*       GetLayer( int );
+    virtual int             GetLayerCount() override { return static_cast<int>(nLayers); }
+    virtual OGRLayer*       GetLayer( int ) override;
 
-    virtual int             TestCapability( const char * );
+    virtual int             TestCapability( const char * ) override;
     void                    CloseFile();
 };
 
@@ -147,10 +147,10 @@ class OGRSXFDriver : public OGRSFDriver
   public:
                 ~OGRSXFDriver();
 
-    const char*     GetName();
-    OGRDataSource*  Open( const char *, int );
-    OGRErr          DeleteDataSource(const char* pszName);
-    int             TestCapability(const char *);
+    const char*     GetName() override;
+    OGRDataSource*  Open( const char *, int ) override;
+    OGRErr          DeleteDataSource(const char* pszName) override;
+    int             TestCapability(const char *) override;
 };
 
 #endif
diff --git a/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp b/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp
index 0c30140..494f188 100644
--- a/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp
+++ b/ogr/ogrsf_frmts/sxf/ogrsxfdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_sxfdatasource.cpp  $
  *
  * Project:  SXF Translator
  * Purpose:  Definition of classes for OGR SXF Datasource.
@@ -40,7 +39,7 @@
 #include <map>
 #include <string>
 
-CPL_CVSID("$Id: ogrsxfdatasource.cpp  $");
+CPL_CVSID("$Id: ogrsxfdatasource.cpp 36457 2016-11-23 00:18:37Z rouault $");
 
 static const long aoVCS[] =
 {
@@ -76,19 +75,20 @@ static const long aoVCS[] =
 
 #define NUMBER_OF_VERTICALCS    (sizeof(aoVCS)/sizeof(aoVCS[0]))
 
+// EPSG code range http://gis.stackexchange.com/a/18676/9904
+static const int MIN_EPSG = 1000;
+static const int MAX_EPSG = 3768;
+
 /************************************************************************/
 /*                         OGRSXFDataSource()                           */
 /************************************************************************/
 
-OGRSXFDataSource::OGRSXFDataSource()
-
+OGRSXFDataSource::OGRSXFDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    fpSXF(NULL),
+    hIOMutex(NULL)
 {
-    papoLayers = NULL;
-    nLayers = 0;
-
-    fpSXF = NULL;
-    hIOMutex = NULL;
-
     oSXFPassport.stMapDescription.pSpatRef = NULL;
 }
 
@@ -157,10 +157,7 @@ OGRLayer *OGRSXFDataSource::GetLayer( int iLayer )
 
 int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
 {
-    size_t nObjectsRead;
-    int nFileHeaderSize;
-
-    if (bUpdateIn)
+    if( bUpdateIn )
     {
         return FALSE;
     }
@@ -175,15 +172,16 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
     }
 
     //read header
-    nFileHeaderSize = sizeof(SXFHeader);
+    const int nFileHeaderSize = sizeof(SXFHeader);
     SXFHeader stSXFFileHeader;
-    nObjectsRead = VSIFReadL(&stSXFFileHeader, nFileHeaderSize, 1, fpSXF);
+    const size_t nObjectsRead =
+        VSIFReadL(&stSXFFileHeader, nFileHeaderSize, 1, fpSXF);
 
     if (nObjectsRead != 1)
     {
         CPLError(CE_Failure, CPLE_None, "SXF head read failed");
         CloseFile();
-		return FALSE;
+        return FALSE;
     }
 
     //check version
@@ -212,7 +210,6 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
         return FALSE;
     }
 
-
     //read flags
     if (ReadSXFInformationFlags(fpSXF, oSXFPassport) != OGRERR_NONE)
     {
@@ -221,7 +218,8 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
         return FALSE;
     }
 
-    if (oSXFPassport.informationFlags.bProjectionDataCompliance == false)
+    if(oSXFPassport.version == 3 &&
+               oSXFPassport.informationFlags.bProjectionDataCompliance == false)
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   "SXF. Data does not correspond to the projection." );
@@ -270,8 +268,21 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
         }
     }
 
+    // 1. Create layers from RSC file or create default set of layers from
+    // gdal_data/default.rsc.
 
-    //1. Create layers from RSC file or create default set of layers from osm.rsc
+    if(soRSCRileName.empty())
+    {
+        pszRSCRileName = CPLFindFile( "gdal", "default.rsc" );
+        if (NULL != pszRSCRileName)
+        {
+            soRSCRileName = pszRSCRileName;
+        }
+        else
+        {
+            CPLDebug( "OGRSXFDataSource", "Default RSC file not found" );
+        }
+    }
 
     if (soRSCRileName.empty())
     {
@@ -279,9 +290,7 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
     }
     else
     {
-        VSILFILE* fpRSC;
-
-        fpRSC = VSIFOpenL(soRSCRileName, "rb");
+        VSILFILE* fpRSC = VSIFOpenL(soRSCRileName, "rb");
         if (fpRSC == NULL)
         {
             CPLError(CE_Warning, CPLE_OpenFailed, "RSC file %s open failed",
@@ -308,7 +317,7 @@ int OGRSXFDataSource::Open( const char * pszFilename, int bUpdateIn)
 
 OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXFIn, SXFPassport& passport)
 {
-    /* int nObjectsRead; */
+    // int nObjectsRead = 0;
 
     if (passport.version == 3)
     {
@@ -335,19 +344,19 @@ OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXFIn, SXFPassport& pass
 
         char szName[26] = { 0 };
         memcpy(szName, buff + 8, 24);
-        char* pszRecoded = CPLRecode(szName + 2, "CP1251", CPL_ENC_UTF8);
+        szName[ sizeof(szName) - 1 ] = '\0';
+        char* pszRecoded = CPLRecode(szName, "CP1251", CPL_ENC_UTF8);// szName + 2
         passport.sMapSheet = pszRecoded; //TODO: check the encoding in SXF created in Linux
         CPLFree(pszRecoded);
 
         memcpy(&passport.nScale, buff + 32, 4);
         CPL_LSBPTR32(&passport.nScale);
 
-        memset(szName, 0, 26);
         memcpy(szName, buff + 36, 26);
+        szName[ sizeof(szName) - 1 ] = '\0';
         pszRecoded = CPLRecode(szName, "CP866", CPL_ENC_UTF8);
         passport.sMapSheetName = pszRecoded; //TODO: check the encoding in SXF created in Linux
         CPLFree(pszRecoded);
-
     }
     else if (passport.version == 4)
     {
@@ -360,8 +369,8 @@ OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXFIn, SXFPassport& pass
         memcpy(date, buff, 4);
         passport.dtCrateDate.nYear = static_cast<GUInt16>(atoi(date));
 
-        memset(date, 0, 5);
         memcpy(date, buff + 4, 2);
+        memset(date+2, 0, 3);
 
         passport.dtCrateDate.nMonth = static_cast<GUInt16>(atoi(date));
 
@@ -371,15 +380,16 @@ OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXFIn, SXFPassport& pass
 
         char szName[32] = { 0 };
         memcpy(szName, buff + 12, 32);
-        char* pszRecoded = CPLRecode(szName + 2, "CP1251", CPL_ENC_UTF8);
+        szName[ sizeof(szName) - 1 ] = '\0';
+        char* pszRecoded = CPLRecode(szName, "CP1251", CPL_ENC_UTF8); //szName + 2
         passport.sMapSheet = pszRecoded; //TODO: check the encoding in SXF created in Linux
         CPLFree(pszRecoded);
 
         memcpy(&passport.nScale, buff + 44, 4);
         CPL_LSBPTR32(&passport.nScale);
 
-        memset(szName, 0, 32);
         memcpy(szName, buff + 48, 32);
+        szName[ sizeof(szName) - 1 ] = '\0';
         pszRecoded = CPLRecode(szName, "CP1251", CPL_ENC_UTF8);
         passport.sMapSheetName = pszRecoded; //TODO: check the encoding in SXF created in Linux
         CPLFree(pszRecoded);
@@ -399,16 +409,16 @@ OGRErr OGRSXFDataSource::ReadSXFDescription(VSILFILE* fpSXFIn, SXFPassport& pass
 
 OGRErr OGRSXFDataSource::ReadSXFInformationFlags(VSILFILE* fpSXFIn, SXFPassport& passport)
 {
-    /* int nObjectsRead; */
+    // int nObjectsRead = 0;
     GByte val[4];
     /* nObjectsRead = */ VSIFReadL(&val, 4, 1, fpSXFIn);
 
-    if (!(CHECK_BIT(val[0], 0) && CHECK_BIT(val[0], 1)))
+    if (!(CHECK_BIT(val[0], 0) && CHECK_BIT(val[0], 1))) // xxxxxx11
     {
         return OGRERR_UNSUPPORTED_OPERATION;
     }
 
-    if (CHECK_BIT(val[0], 2))
+    if (CHECK_BIT(val[0], 2)) // xxxxx0xx or xxxxx1xx
     {
         passport.informationFlags.bProjectionDataCompliance = true;
     }
@@ -485,7 +495,7 @@ void OGRSXFDataSource::SetVertCS(const long iVCS, SXFPassport& passport)
 
     const int nEPSG = static_cast<int>(aoVCS[iVCS]);
 
-    if (nEPSG == 0)
+    if (nEPSG < MIN_EPSG || nEPSG > MAX_EPSG)
     {
         CPLError(CE_Warning, CPLE_NotSupported, "SXF. Vertical coordinate system (SXF index %ld) not supported", iVCS);
         return;
@@ -515,8 +525,7 @@ void OGRSXFDataSource::SetVertCS(const long iVCS, SXFPassport& passport)
 }
 OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& passport)
 {
-    /* int nObjectsRead;*/
-    int i;
+    // int nObjectsRead = 0;
     passport.stMapDescription.Env.MaxX = -100000000;
     passport.stMapDescription.Env.MinX = 100000000;
     passport.stMapDescription.Env.MaxY = -100000000;
@@ -538,7 +547,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
         //get projected corner coords
         /* nObjectsRead = */ VSIFReadL(&nCorners, 32, 1, fpSXFIn);
 
-        for (i = 0; i < 8; i++)
+        for( int i = 0; i < 8; i++ )
         {
             passport.stMapDescription.stProjCoords[i] = double(nCorners[i]) / 10.0;
             if (bIsX) //X
@@ -560,17 +569,17 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
         //get geographic corner coords
         /* nObjectsRead = */ VSIFReadL(&nCorners, 32, 1, fpSXFIn);
 
-        for (i = 0; i < 8; i++)
+        for( int i = 0; i < 8; i++ )
         {
             passport.stMapDescription.stGeoCoords[i] = double(nCorners[i]) * 0.00000057295779513082; //from radians to degree * 100 000 000
         }
     }
     else if (passport.version == 4)
     {
-        int nEPSG;
+        int nEPSG = 0;
         /* nObjectsRead = */ VSIFReadL(&nEPSG, 4, 1, fpSXFIn);
 
-        if (nEPSG != 0)
+        if (nEPSG >= MIN_EPSG && nEPSG <= MAX_EPSG) //TODO: check epsg valid range
         {
             passport.stMapDescription.pSpatRef = new OGRSpatialReference();
             passport.stMapDescription.pSpatRef->importFromEPSG(nEPSG);
@@ -579,7 +588,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
         double dfCorners[8];
         /* nObjectsRead = */ VSIFReadL(&dfCorners, 64, 1, fpSXFIn);
 
-        for (i = 0; i < 8; i++)
+        for( int i = 0; i < 8; i++ )
         {
             passport.stMapDescription.stProjCoords[i] = dfCorners[i];
             if (bIsX) //X
@@ -597,16 +606,14 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
                     passport.stMapDescription.Env.MinX = passport.stMapDescription.stProjCoords[i];
             }
             bIsX = !bIsX;
-
         }
         //get geographic corner coords
         /* nObjectsRead = */ VSIFReadL(&dfCorners, 64, 1, fpSXFIn);
 
-        for (i = 0; i < 8; i++)
+        for( int i = 0; i < 8; i++ )
         {
             passport.stMapDescription.stGeoCoords[i] = dfCorners[i] * TO_DEGREES; // to degree
         }
-
     }
 
     if (NULL != passport.stMapDescription.pSpatRef)
@@ -648,17 +655,17 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
             break;
         }
 
-
         VSIFSeekL(fpSXFIn, 212, SEEK_SET);
         struct _buff{
             GUInt32 nRes;
             GInt16 anFrame[8];
+            // cppcheck-suppress unusedStructMember
             GUInt32 nFrameCode;
         } buff;
         /* nObjectsRead = */ VSIFReadL(&buff, 20, 1, fpSXFIn);
         passport.stMapDescription.nResolution = buff.nRes; //resolution
 
-        for (i = 0; i < 8; i++)
+        for( int i = 0; i < 8; i++ )
             passport.stMapDescription.stFrameCoords[i] = buff.anFrame[i];
 
         int anParams[5];
@@ -680,7 +687,6 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
         passport.stMapDescription.dfFalseNorthing = 0;
         passport.stMapDescription.dfFalseEasting = 0;
 
-
         //adfPrjParams[0] = double(anParams[0]) / 100000000.0; // to radians
         //adfPrjParams[1] = double(anParams[1]) / 100000000.0;
         //adfPrjParams[2] = double(anParams[2]) / 100000000.0;
@@ -689,7 +695,6 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
         //adfPrjParams[5] = 0;//?
         //adfPrjParams[6] = 0;//?
         //adfPrjParams[7] = 0;// importFromPanorama calc it by itself
-
     }
     else if (passport.version == 4)
     {
@@ -711,10 +716,10 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
         /* nObjectsRead = */ VSIFReadL(&buff, 40, 1, fpSXFIn);
 
         passport.stMapDescription.nResolution = buff[0]; //resolution
-        for (i = 0; i < 8; i++)
+        for( int i = 0; i < 8; i++ )
             passport.stMapDescription.stFrameCoords[i] = buff[1 + i];
 
-        double adfParams[6];
+        double adfParams[6] = {};
         /* nObjectsRead = */ VSIFReadL(&adfParams, 48, 1, fpSXFIn);
 
         if (adfParams[1] != -1)
@@ -755,7 +760,7 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
     }
 
     //normalize some coordintatessystems
-    if (iEllips == 1 && iProjSys == 1) // Pulkovo 1942 / Gauss-Kruger
+    if ((iEllips == 1 || iEllips == 0 ) && iProjSys == 1) // Pulkovo 1942 / Gauss-Kruger
     {
         double dfCenterLongEnv = passport.stMapDescription.stGeoCoords[1] + fabs(passport.stMapDescription.stGeoCoords[5] - passport.stMapDescription.stGeoCoords[1]) / 2;
 
@@ -787,8 +792,8 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
         double dfCenterLongEnv = passport.stMapDescription.stGeoCoords[1] + fabs(passport.stMapDescription.stGeoCoords[5] - passport.stMapDescription.stGeoCoords[1]) / 2;
         int nZoneEnv = (int)(30 + (dfCenterLongEnv + 3.0) / 6.0 + 0.5);
         bool bNorth = passport.stMapDescription.stGeoCoords[6] + (passport.stMapDescription.stGeoCoords[2] - passport.stMapDescription.stGeoCoords[6]) / 2 < 0;
-        int nEPSG;
-        if (bNorth)
+        int nEPSG = 0;
+        if( bNorth )
         {
             nEPSG = 32600 + nZoneEnv;
         }
@@ -801,10 +806,17 @@ OGRErr OGRSXFDataSource::ReadSXFMapDescription(VSILFILE* fpSXFIn, SXFPassport& p
         SetVertCS(iVCS, passport);
         return eErr;
     }
-   else if (iEllips == 45 && iProjSys == 35) //Mercator 3395 on sphere wgs84
+    else if (iEllips == 45 && iProjSys == 35) //Mercator 3857 on sphere wgs84
     {
-        passport.stMapDescription.pSpatRef = new OGRSpatialReference("PROJCS[\"WGS_1984_Web_Mercator\",GEOGCS[\"GCS_WGS_1984_Major_Auxiliary_Sphere\",DATUM[\"WGS_1984_Major_Auxiliary_Sphere\",SPHEROID[\"WGS_1984_Major_Auxiliary_Sphere\",6378137.0,0.0]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"False_Easting\",0.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",0.0],PARAMETER[\"latitude_of_origin\",0.0],UNIT[\ [...]
-        OGRErr eErr = OGRERR_NONE; //passport.stMapDescription.pSpatRef->importFromEPSG(3395);
+        passport.stMapDescription.pSpatRef = new OGRSpatialReference("PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0],PARAMETER[\"scale_factor\",1],PARAME [...]
+        OGRErr eErr = OGRERR_NONE; //passport.stMapDescription.pSpatRef->importFromEPSG(3857);
+        SetVertCS(iVCS, passport);
+        return eErr;
+    }
+    else if (iEllips == 9 && iProjSys == 35) //Mercator 3395 on ellips wgs84
+    {
+        passport.stMapDescription.pSpatRef = new OGRSpatialReference();
+        OGRErr eErr = passport.stMapDescription.pSpatRef->importFromEPSG(3395);
         SetVertCS(iVCS, passport);
         return eErr;
     }
@@ -854,11 +866,8 @@ void OGRSXFDataSource::FillLayers()
     CPLDebug("SXF","Create layers");
 
     //2. Read all records (only classify code and offset) and add this to correspondence layer
-    GUInt32 nFID;
     int nObjectsRead = 0;
-    size_t i;
-    vsi_l_offset nOffset = 0, nOffsetSemantic;
-    size_t nDeletedLayerIndex;
+    vsi_l_offset nOffset = 0;
 
     //get record count
     GUInt32 nRecordCountMax = 0;
@@ -884,7 +893,7 @@ void OGRSXFDataSource::FillLayers()
 
     VSIFSeekL(fpSXF, nOffset, SEEK_SET);
 
-    for (nFID = 0; nFID < nRecordCountMax; nFID++)
+    for( GUInt32 nFID = 0; nFID < nRecordCountMax; nFID++ )
     {
         GInt32 buff[6];
         nObjectsRead = static_cast<int>(VSIFReadL(&buff, 24, 1, fpSXF));
@@ -899,7 +908,7 @@ void OGRSXFDataSource::FillLayers()
         if (bHasSemantic) //check has attributes
         {
             //we have already 24 byte readed
-            nOffsetSemantic = 8 + buff[2];
+            vsi_l_offset nOffsetSemantic = 8 + buff[2];
             VSIFSeekL(fpSXF, nOffsetSemantic, SEEK_CUR);
         }
 
@@ -909,7 +918,8 @@ void OGRSXFDataSource::FillLayers()
             CPLError(CE_Failure, CPLE_AppDefined, "Invalid value");
             break;
         }
-        for (i = 0; i < nLayers; i++)
+
+        for( size_t i = 0; i < nLayers; i++ )
         {
             OGRSXFLayer* pOGRSXFLayer = (OGRSXFLayer*)papoLayers[i];
             if (pOGRSXFLayer && pOGRSXFLayer->AddRecord(nFID, buff[3], nOffset, bHasSemantic, nSemanticSize) == TRUE)
@@ -920,15 +930,14 @@ void OGRSXFDataSource::FillLayers()
         nOffset += buff[1];
         VSIFSeekL(fpSXF, nOffset, SEEK_SET);
     }
-
     //3. delete empty layers
-    for (i = 0; i < nLayers; i++)
+    for( size_t i = 0; i < nLayers; i++ )
     {
         OGRSXFLayer* pOGRSXFLayer = (OGRSXFLayer*)papoLayers[i];
         if (pOGRSXFLayer && pOGRSXFLayer->GetFeatureCount() == 0)
         {
             delete pOGRSXFLayer;
-            nDeletedLayerIndex = i;
+            size_t nDeletedLayerIndex = i;
             while (nDeletedLayerIndex < nLayers - 1)
             {
                 papoLayers[nDeletedLayerIndex] = papoLayers[nDeletedLayerIndex + 1];
@@ -957,8 +966,6 @@ OGRSXFLayer* OGRSXFDataSource::GetLayerById(GByte nID)
 
 void OGRSXFDataSource::CreateLayers()
 {
-    //codes get from OSM.rsc http://gistoolkit.ru/download/classifiers/osm.zip
-
     //default layers set
     papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
     OGRSXFLayer* pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 0, CPLString("SYSTEM"), oSXFPassport.version, oSXFPassport.stMapDescription);
@@ -973,246 +980,8 @@ void OGRSXFDataSource::CreateLayers()
     pLayer->AddClassifyCode(91000000);
 
     papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 1, CPLString("boundary"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(81110000);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 2, CPLString("water"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(31410000);
-    pLayer->AddClassifyCode(31120000);
-    pLayer->AddClassifyCode(31710000);
-    pLayer->AddClassifyCode(72310000);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 3, CPLString("city"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(41100000);
-    pLayer->AddClassifyCode(91100001);
-    pLayer->AddClassifyCode(91100002);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 4, CPLString("poi"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(123);
-    pLayer->AddClassifyCode(32410000);
-    pLayer->AddClassifyCode(44200000);
-    pLayer->AddClassifyCode(44200010);
-    pLayer->AddClassifyCode(47140000);
-    pLayer->AddClassifyCode(51121000);
-    pLayer->AddClassifyCode(51130000);
-    pLayer->AddClassifyCode(51410000);
-    pLayer->AddClassifyCode(51410001);
-    pLayer->AddClassifyCode(51420000);
-    pLayer->AddClassifyCode(53110000);
-    pLayer->AddClassifyCode(53311400);
-    pLayer->AddClassifyCode(53421000);
-    pLayer->AddClassifyCode(53510000);
-    pLayer->AddClassifyCode(53612000);
-    pLayer->AddClassifyCode(53612100);
-    pLayer->AddClassifyCode(53612101);
-    pLayer->AddClassifyCode(53612102);
-    pLayer->AddClassifyCode(53612103);
-    pLayer->AddClassifyCode(53612104);
-    pLayer->AddClassifyCode(53612105);
-    pLayer->AddClassifyCode(53612106);
-    pLayer->AddClassifyCode(53612107);
-    pLayer->AddClassifyCode(53612200);
-    pLayer->AddClassifyCode(53612201);
-    pLayer->AddClassifyCode(53612202);
-    pLayer->AddClassifyCode(53612203);
-    pLayer->AddClassifyCode(53612204);
-    pLayer->AddClassifyCode(53612205);
-    pLayer->AddClassifyCode(53612211);
-    pLayer->AddClassifyCode(53612300);
-    pLayer->AddClassifyCode(53612301);
-    pLayer->AddClassifyCode(53612302);
-    pLayer->AddClassifyCode(53612303);
-    pLayer->AddClassifyCode(53612304);
-    pLayer->AddClassifyCode(53612400);
-    pLayer->AddClassifyCode(53612401);
-    pLayer->AddClassifyCode(53612402);
-    pLayer->AddClassifyCode(53612403);
-    pLayer->AddClassifyCode(53612404);
-    pLayer->AddClassifyCode(53623000);
-    pLayer->AddClassifyCode(53623100);
-    pLayer->AddClassifyCode(53623110);
-    pLayer->AddClassifyCode(53623200);
-    pLayer->AddClassifyCode(53623300);
-    pLayer->AddClassifyCode(53623400);
-    pLayer->AddClassifyCode(53623500);
-    pLayer->AddClassifyCode(53623600);
-    pLayer->AddClassifyCode(53624000);
-    pLayer->AddClassifyCode(53624001);
-    pLayer->AddClassifyCode(53624002);
-    pLayer->AddClassifyCode(53624003);
-    pLayer->AddClassifyCode(53624004);
-    pLayer->AddClassifyCode(53624005);
-    pLayer->AddClassifyCode(53630000);
-    pLayer->AddClassifyCode(53631000);
-    pLayer->AddClassifyCode(53632101);
-    pLayer->AddClassifyCode(53632102);
-    pLayer->AddClassifyCode(53632103);
-    pLayer->AddClassifyCode(53632104);
-    pLayer->AddClassifyCode(53632105);
-    pLayer->AddClassifyCode(53632106);
-    pLayer->AddClassifyCode(53633001);
-    pLayer->AddClassifyCode(53633101);
-    pLayer->AddClassifyCode(53633102);
-    pLayer->AddClassifyCode(53633112);
-    pLayer->AddClassifyCode(53633114);
-    pLayer->AddClassifyCode(53635000);
-    pLayer->AddClassifyCode(53640000);
-    pLayer->AddClassifyCode(53641000);
-    pLayer->AddClassifyCode(53642000);
-    pLayer->AddClassifyCode(53643000);
-    pLayer->AddClassifyCode(53644000);
-    pLayer->AddClassifyCode(53646011);
-    pLayer->AddClassifyCode(53646013);
-    pLayer->AddClassifyCode(53646014);
-    pLayer->AddClassifyCode(53650000);
-    pLayer->AddClassifyCode(53650001);
-    pLayer->AddClassifyCode(53650002);
-    pLayer->AddClassifyCode(53650003);
-    pLayer->AddClassifyCode(53650004);
-    pLayer->AddClassifyCode(53650006);
-    pLayer->AddClassifyCode(53660000);
-    pLayer->AddClassifyCode(53661001);
-    pLayer->AddClassifyCode(53661002);
-    pLayer->AddClassifyCode(53661003);
-    pLayer->AddClassifyCode(53661004);
-    pLayer->AddClassifyCode(53661005);
-    pLayer->AddClassifyCode(53661006);
-    pLayer->AddClassifyCode(53661007);
-    pLayer->AddClassifyCode(53661008);
-    pLayer->AddClassifyCode(53661009);
-    pLayer->AddClassifyCode(53661010);
-    pLayer->AddClassifyCode(53661021);
-    pLayer->AddClassifyCode(53661100);
-    pLayer->AddClassifyCode(53662001);
-    pLayer->AddClassifyCode(53662002);
-    pLayer->AddClassifyCode(53662003);
-    pLayer->AddClassifyCode(53662004);
-    pLayer->AddClassifyCode(53672600);
-    pLayer->AddClassifyCode(53673300);
-    pLayer->AddClassifyCode(53700000);
-    pLayer->AddClassifyCode(53710000);
-    pLayer->AddClassifyCode(53720100);
-    pLayer->AddClassifyCode(53720200);
-    pLayer->AddClassifyCode(53720300);
-    pLayer->AddClassifyCode(53720301);
-    pLayer->AddClassifyCode(53720400);
-    pLayer->AddClassifyCode(53720500);
-    pLayer->AddClassifyCode(53720510);
-    pLayer->AddClassifyCode(53720520);
-    pLayer->AddClassifyCode(53720970);
-    pLayer->AddClassifyCode(53890000);
-
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 5, CPLString("highway"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(10715);
-    pLayer->AddClassifyCode(11118);
-    pLayer->AddClassifyCode(2000253);
-    pLayer->AddClassifyCode(2000727);
-    pLayer->AddClassifyCode(51133200);
-    pLayer->AddClassifyCode(51220000);
-    pLayer->AddClassifyCode(61230000);
-    pLayer->AddClassifyCode(61230000);
-    pLayer->AddClassifyCode(62132000);
-    pLayer->AddClassifyCode(62213100);
-    pLayer->AddClassifyCode(62213101);
-    pLayer->AddClassifyCode(62213102);
-    pLayer->AddClassifyCode(62223000);
-    pLayer->AddClassifyCode(62331000);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 6, CPLString("railway"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(61111000);
-    pLayer->AddClassifyCode(61121100);
-    pLayer->AddClassifyCode(61121200);
-    pLayer->AddClassifyCode(61122000);
-    pLayer->AddClassifyCode(62131000);
-
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 7, CPLString("building"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(44100000);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 8, CPLString("landuse"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(97);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 9, CPLString("vegetation"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(71111111);
-    pLayer->AddClassifyCode(71325000);
-    pLayer->AddClassifyCode(53890000);
-    pLayer->AddClassifyCode(22700000);
-    pLayer->AddClassifyCode(32282000);
-    pLayer->AddClassifyCode(71211000);
-    pLayer->AddClassifyCode(72120000);
-    pLayer->AddClassifyCode(71314000);
-    pLayer->AddClassifyCode(71312000);
-
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 10, CPLString("fire"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(96);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 11, CPLString("roaddesign"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(60000000);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 13, CPLString("RoadStructure"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(62315000);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
-    pLayer = new OGRSXFLayer(fpSXF, &hIOMutex, 14, CPLString("signature"), oSXFPassport.version, oSXFPassport.stMapDescription);
-    papoLayers[nLayers] = pLayer;
-    nLayers++;
-
-    pLayer->AddClassifyCode(91100000);
-    pLayer->AddClassifyCode(91200000);
-
-    papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
     papoLayers[nLayers] = new OGRSXFLayer(fpSXF, &hIOMutex, 255, CPLString("Not_Classified"), oSXFPassport.version, oSXFPassport.stMapDescription);
     nLayers++;
-
 }
 
 void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
@@ -1234,11 +1003,12 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
         char szName[32];
         char szShortName[16];
         GByte nNo;
+        // cppcheck-suppress unusedStructMember
         GByte nPos;
+        // cppcheck-suppress unusedStructMember
         GUInt16 nSemanticCount;
     };
 
-    GUInt32 i;
     size_t nLayerStructSize = sizeof(_layer);
 
     VSIFSeekL(fpRSC, stRSCFileHeader.Layers.nOffset - sizeof(szLayersID), SEEK_SET);
@@ -1246,14 +1016,14 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
     vsi_l_offset nOffset = stRSCFileHeader.Layers.nOffset;
     _layer LAYER;
 
-    for (i = 0; i < stRSCFileHeader.Layers.nRecordCount; ++i)
+    for( GUInt32 i = 0; i < stRSCFileHeader.Layers.nRecordCount; ++i )
     {
         VSIFReadL(&LAYER, nLayerStructSize, 1, fpRSC);
 
         papoLayers = (OGRLayer**)CPLRealloc(papoLayers, sizeof(OGRLayer*)* (nLayers + 1));
         bool bLayerFullName = CPLTestBool(CPLGetConfigOption("SXF_LAYER_FULLNAME", "NO"));
 
-        char* pszRecoded;
+        char* pszRecoded = NULL;
         if (bLayerFullName)
         {
             if(LAYER.szName[0] == 0)
@@ -1291,17 +1061,20 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
     papoLayers[nLayers] = new OGRSXFLayer(fpSXF, &hIOMutex, 255, CPLString("Not_Classified"), oSXFPassport.version, oSXFPassport.stMapDescription);
     nLayers++;
 
-
     char szObjectsID[4];
     struct _object{
         unsigned nLength;
         unsigned nClassifyCode;
+        // cppcheck-suppress unusedStructMember
         unsigned nObjectNumber;
+        // cppcheck-suppress unusedStructMember
         unsigned nObjectCode;
         char szShortName[32];
         char szName[32];
+        // cppcheck-suppress unusedStructMember
         char szGeomType;
         char szLayernNo;
+        // cppcheck-suppress unusedStructMember
         char szUnimportantSeg[14];
     };
 
@@ -1310,14 +1083,14 @@ void OGRSXFDataSource::CreateLayers(VSILFILE* fpRSC)
     nOffset = stRSCFileHeader.Objects.nOffset;
     _object OBJECT;
 
-    for (unsigned j = 0; j < stRSCFileHeader.Objects.nRecordCount; ++j)
+    for( GUInt32 i = 0; i < stRSCFileHeader.Objects.nRecordCount; ++i )
     {
         VSIFReadL(&OBJECT, sizeof(_object), 1, fpRSC);
 
         OGRSXFLayer* pLayer = GetLayerById(OBJECT.szLayernNo);
         if (NULL != pLayer)
         {
-            char* pszRecoded;
+            char* pszRecoded = NULL;
             if(OBJECT.szName[0] == 0)
                 pszRecoded = CPLStrdup("Unnamed");
             else if (stRSCFileHeader.nFontEnc == 125)
diff --git a/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp b/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp
index 79c31b2..2d5d706 100644
--- a/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp
+++ b/ogr/ogrsf_frmts/sxf/ogrsxfdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_sxfdriver.cpp  $
  *
  * Project:  SXF Translator
  * Purpose:  Definition of classes for OGR SXF driver.
@@ -33,8 +32,7 @@
 #include "cpl_conv.h"
 #include "ogr_sxf.h"
 
-CPL_CVSID("$Id: ogrsxfdriver.cpp  $");
-
+CPL_CVSID("$Id: ogrsxfdriver.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 extern "C" void RegisterOGRSXF();
 
@@ -90,7 +88,6 @@ OGRDataSource *OGRSXFDriver::Open( const char * pszFilename, int bUpdate )
 
 OGRErr OGRSXFDriver::DeleteDataSource(const char* pszName)
 {
-    int iExt;
     //TODO: add more extensions if aplicable
     static const char * const apszExtensions[] = { "szf", "rsc", "SZF", "RSC", NULL };
 
@@ -104,7 +101,7 @@ OGRErr OGRSXFDriver::DeleteDataSource(const char* pszName)
         return OGRERR_FAILURE;
     }
 
-    for (iExt = 0; apszExtensions[iExt] != NULL; iExt++)
+    for( int iExt = 0; apszExtensions[iExt] != NULL; iExt++ )
     {
         const char *pszFile = CPLResetExtension(pszName,
             apszExtensions[iExt]);
@@ -124,8 +121,8 @@ int OGRSXFDriver::TestCapability( const char * pszCap )
 {
     if (EQUAL(pszCap, ODrCDeleteDataSource))
         return TRUE;
-    else
-        return FALSE;
+
+    return FALSE;
 }
 
 /************************************************************************/
@@ -142,6 +139,3 @@ void RegisterOGRSXF()
 
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(poDriver);
 }
-
-
-
diff --git a/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp b/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp
index 36a9f76..1a4541b 100644
--- a/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp
+++ b/ogr/ogrsf_frmts/sxf/ogrsxflayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_sxflayer.cpp  $
  *
  * Project:  SXF Translator
  * Purpose:  Definition of classes for OGR SXF Layers.
@@ -38,34 +37,34 @@
 #include "ogr_srs_api.h"
 #include "cpl_multiproc.h"
 
-CPL_CVSID("$Id: ogrsxflayer.cpp $");
+CPL_CVSID("$Id: ogrsxflayer.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 /************************************************************************/
 /*                        OGRSXFLayer()                                 */
 /************************************************************************/
 
-OGRSXFLayer::OGRSXFLayer(VSILFILE* fp, CPLMutex** hIOMutex, GByte nID, const char* pszLayerName, int nVer, const SXFMapDescription&  sxfMapDesc) : OGRLayer()
+OGRSXFLayer::OGRSXFLayer(
+    VSILFILE* fp, CPLMutex** hIOMutex, GByte nID, const char* pszLayerName,
+    int nVer, const SXFMapDescription&  sxfMapDesc) :
+    OGRLayer(),
+    poFeatureDefn(new OGRFeatureDefn(pszLayerName)),
+    fpSXF(fp),
+    nLayerID(nID),
+    stSXFMapDescription(sxfMapDesc),
+    m_nSXFFormatVer(nVer),
+    sFIDColumn_("ogc_fid"),
+    m_hIOMutex(hIOMutex),
+    m_dfCoeff(sxfMapDesc.dfScale / sxfMapDesc.nResolution)
 {
-    sFIDColumn_ = "ogc_fid";
-    fpSXF = fp;
-    nLayerID = nID;
-    stSXFMapDescription = sxfMapDesc;
     stSXFMapDescription.pSpatRef->Reference();
-    m_nSXFFormatVer = nVer;
     oNextIt = mnRecordDesc.begin();
-    m_hIOMutex = hIOMutex;
-    m_dfCoeff = stSXFMapDescription.dfScale / stSXFMapDescription.nResolution;
-    poFeatureDefn = new OGRFeatureDefn(pszLayerName);
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
 
     poFeatureDefn->SetGeomType(wkbUnknown);
     if (poFeatureDefn->GetGeomFieldCount() != 0)
-        poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(stSXFMapDescription.pSpatRef);
-
-    //OGRGeomFieldDefn oGeomFieldDefn("Shape", wkbGeometryCollection);
-    //oGeomFieldDefn.SetSpatialRef(stSXFMapDescription.pSpatRef);
-    //poFeatureDefn->AddGeomFieldDefn(&oGeomFieldDefn);
+        poFeatureDefn->GetGeomFieldDefn(0)->
+            SetSpatialRef(stSXFMapDescription.pSpatRef);
 
     OGRFieldDefn oFIDField(sFIDColumn_, OFTInteger);
     poFeatureDefn->AddFieldDefn(&oFIDField);
@@ -121,12 +120,14 @@ void OGRSXFLayer::AddClassifyCode(unsigned nClassCode, const char *szName)
 }
 
 /************************************************************************/
-/*                         AddRecord()                               */
+/*                           AddRecord()                                */
 /************************************************************************/
 
-int OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset, bool bHasSemantic, size_t nSemanticsSize)
+bool OGRSXFLayer::AddRecord( long nFID, unsigned nClassCode, vsi_l_offset nOffset,
+                             bool bHasSemantic, size_t nSemanticsSize )
 {
-    if (mnClassificators.empty() || mnClassificators.find(nClassCode) != mnClassificators.end())
+    if( mnClassificators.find(nClassCode) != mnClassificators.end() ||
+        EQUAL(GetName(), "Not_Classified") )
     {
         mnRecordDesc[nFID] = nOffset;
         // Add additional semantics (attribute fields).
@@ -154,7 +155,6 @@ int OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset,
 
                     offset += 4;
 
-
                     switch (eType) //TODO: set field type form RSC as here sometimes we have the codes and string values can be get from RSC by this code
                     {
                     case SXF_RAT_ASCIIZ_DOS:
@@ -247,7 +247,7 @@ int OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset,
                             oField.SetWidth(1024);
                             poFeatureDefn->AddFieldDefn(&oField);
                         }
-                        GUInt32 scale2;
+                        GUInt32 scale2 = 0;
                         VSIFReadL(&scale2, sizeof(GUInt32), 1, fpSXF);
                         CPL_LSBPTR32(&scale2);
 
@@ -264,10 +264,10 @@ int OGRSXFLayer::AddRecord(long nFID, unsigned nClassCode, vsi_l_offset nOffset,
                 VSIFSeekL(fpSXF, nCurrOff, SEEK_CUR);
             }
         }
-        return TRUE;
+        return true;
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -358,7 +358,6 @@ void OGRSXFLayer::ResetReading()
     oNextIt = mnRecordDesc.begin();
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -424,11 +423,11 @@ int OGRSXFLayer::TestCapability( const char * pszCap )
  * coordinate, the vector format, etc.
  */
 
-GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
-                                  const char *psBuff, GUInt32 nBufLen,
-                          double *dfX, double *dfY, double *dfH)
+GUInt32 OGRSXFLayer::TranslateXYH( const SXFRecordDescription& certifInfo,
+                                   const char *psBuff, GUInt32 nBufLen,
+                                   double *dfX, double *dfY, double *dfH )
 {
-    //Xp, Yp(м) = Xo, Yo(м) + (Xd, Yd / R * S), (1)
+    // Xp, Yp(м) = Xo, Yo(м) + (Xd, Yd / R * S), (1)
 
     int offset = 0;
     switch (certifInfo.eValType)
@@ -437,7 +436,8 @@ GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
     {
         if( nBufLen < 4 )
             return 0;
-        GInt16 x, y;
+        GInt16 x = 0;
+        GInt16 y = 0;
         memcpy(&y, psBuff, 2);
         CPL_LSBPTR16(&y);
         memcpy(&x, psBuff + 2, 2);
@@ -469,7 +469,7 @@ GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
         {
             if( nBufLen < 4 + 4 )
                 return 0;
-            float h;
+            float h = 0.0f;
             memcpy(&h, psBuff + 4, 4); // H always in float
             CPL_LSBPTR32(&h);
             *dfH = (double)h;
@@ -482,9 +482,10 @@ GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
     {
         if( nBufLen < 8 )
             return 0;
-        float x, y;
+        float y = 0.0f;
         memcpy(&y, psBuff, 4);
         CPL_LSBPTR32(&y);
+        float x = 0.0f;
         memcpy(&x, psBuff + 4, 4);
         CPL_LSBPTR32(&x);
 
@@ -505,7 +506,7 @@ GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
         {
             if( nBufLen < 8 + 4 )
                 return 0;
-            float h;
+            float h = 0.0f;
             memcpy(&h, psBuff + 8, 4); // H always in float
             CPL_LSBPTR32(&h);
             *dfH = (double)h;
@@ -549,7 +550,7 @@ GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
         {
             if( nBufLen < 8 + 4 )
                 return 0;
-            float h;
+            float h = 0.0f;
             memcpy(&h, psBuff + 8, 4); // H always in float
             CPL_LSBPTR32(&h);
             *dfH = (double)h;
@@ -562,7 +563,8 @@ GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
     {
         if( nBufLen < 16 )
             return 0;
-        double x, y;
+        double x = 0.0;
+        double y = 0.0;
         memcpy(&y, psBuff, 8);
         CPL_LSBPTR64(&y);
         memcpy(&x, psBuff + 8, 8);
@@ -585,7 +587,7 @@ GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
         {
             if( nBufLen < 16 + 8 )
                 return 0;
-            double h;
+            double h = 0.0;
             memcpy(&h, psBuff + 16, 8); // H in double
             CPL_LSBPTR64(&h);
             *dfH = (double)h;
@@ -606,9 +608,8 @@ GUInt32 OGRSXFLayer::TranslateXYH(const SXFRecordDescription& certifInfo,
 OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
 {
     SXFRecordHeader stRecordHeader;
-    int nObjectRead;
-
-    nObjectRead = static_cast<int>(VSIFReadL(&stRecordHeader, sizeof(SXFRecordHeader), 1, fpSXF));
+    int nObjectRead = static_cast<int>(
+        VSIFReadL(&stRecordHeader, sizeof(SXFRecordHeader), 1, fpSXF));
 
     if (nObjectRead != 1 || stRecordHeader.nID != IDSXFOBJ)
     {
@@ -730,7 +731,7 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
     }
     // Else trouble.
 
-    if (b3D) //xххххх1х
+    if (b3D) //xxxxxx1x
         stCertInfo.bDim = 1;
     else
         stCertInfo.bDim = 0;
@@ -758,7 +759,6 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
         }
     }
 
-
     stCertInfo.bFormat = CHECK_BIT(stRecordHeader.nRef[2], 0);
     stCertInfo.eGeomType = eGeomType;
 
@@ -904,12 +904,12 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
                 }
                 case SXF_RAT_ONEBYTE:
                 {
-                    GByte nTmpVal;
                     if( offset + sizeof(GByte) > nSemanticsSize )
                     {
                         nSemanticsSize = 0;
                         break;
                     }
+                    GByte nTmpVal = 0;
                     memcpy(&nTmpVal, psSemanticsdBuf + offset, sizeof(GByte));
                     nVal = double(nTmpVal) * pow(10.0, (double)stAttInfo.nScale);
 
@@ -919,12 +919,12 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
                 }
                 case SXF_RAT_TWOBYTE:
                 {
-                    GInt16 nTmpVal;
                     if( offset + sizeof(GInt16) > nSemanticsSize )
                     {
                         nSemanticsSize = 0;
                         break;
                     }
+                    GInt16 nTmpVal = 0;
                     memcpy(&nTmpVal, psSemanticsdBuf + offset, sizeof(GInt16));
                     nVal = double(CPL_LSBWORD16(nTmpVal)) * pow(10.0, (double)stAttInfo.nScale);
 
@@ -934,12 +934,12 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
                 }
                 case SXF_RAT_FOURBYTE:
                 {
-                    GInt32 nTmpVal;
                     if( offset + sizeof(GInt32) > nSemanticsSize )
                     {
                         nSemanticsSize = 0;
                         break;
                     }
+                    GInt32 nTmpVal = 0;
                     memcpy(&nTmpVal, psSemanticsdBuf + offset, sizeof(GInt32));
                     nVal = double(CPL_LSBWORD32(nTmpVal)) * pow(10.0, (double)stAttInfo.nScale);
 
@@ -949,15 +949,16 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
                 }
                 case SXF_RAT_EIGHTBYTE:
                 {
-                    double dfTmpVal;
                     if( offset + sizeof(double) > nSemanticsSize )
                     {
                         nSemanticsSize = 0;
                         break;
                     }
+                    double dfTmpVal = 0.0;
                     memcpy(&dfTmpVal, psSemanticsdBuf + offset, sizeof(double));
                     CPL_LSBPTR64(&dfTmpVal);
-                    double d = dfTmpVal * pow(10.0, (double)stAttInfo.nScale);
+                    const double d =
+                        dfTmpVal * pow(10.0, (double)stAttInfo.nScale);
 
                     poFeature->SetField(oFieldName, d);
 
@@ -1021,12 +1022,12 @@ OGRFeature *OGRSXFLayer::GetNextRawFeature(long nFID)
                 }
                 case SXF_RAT_BIGTEXT:
                 {
-                    GUInt32 scale2;
                     if( offset + sizeof(GUInt32) > nSemanticsSize )
                     {
                         nSemanticsSize = 0;
                         break;
                     }
+                    GUInt32 scale2 = 0;
                     memcpy(&scale2, psSemanticsdBuf + offset, sizeof(GUInt32));
                     CPL_LSBPTR32(&scale2);
                     /* FIXME add ?: offset += sizeof(GUInt32); */
@@ -1106,17 +1107,17 @@ OGRFeature *OGRSXFLayer::TranslatePoint(const SXFRecordDescription& certifInfo,
         if( nOffset + 4 > nBufLen )
             break;
 
-        GUInt16 nSubObj;
+        GUInt16 nSubObj = 0;
         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
         CPL_LSBPTR16(&nSubObj);
 
-        GUInt16 nCoords;
+        GUInt16 nCoords = 0;
         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
         CPL_LSBPTR16(&nCoords);
 
         nOffset +=4;
 
-        for (int i=0; i < nCoords ; i++)
+        for( int i=0; i < nCoords ; i++ )
         {
             const char * psCoords = psRecordBuf + nOffset ;
 
@@ -1198,24 +1199,24 @@ OGRFeature *OGRSXFLayer::TranslateLine(const SXFRecordDescription& certifInfo,
 
 /*---------------------- Reading Sub Lines --------------------------------*/
 
-    for(int count=0 ; count <  certifInfo.nSubObjectCount ; count++)
+    for(GUInt16 count=0 ; count <  certifInfo.nSubObjectCount ; count++)
     {
         poLS->empty();
 
         if( nOffset + 4 > nBufLen )
             break;
 
-        GUInt16 nSubObj;
+        GUInt16 nSubObj = 0;
         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
         CPL_LSBPTR16(&nSubObj);
 
-        GUInt16 nCoords;
+        GUInt16 nCoords = 0;
         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
         CPL_LSBPTR16(&nCoords);
 
         nOffset +=4;
 
-        for (int i=0; i < nCoords ; i++)
+        for (GUInt16 i=0; i < nCoords ; i++)
         {
             const char * psCoords = psRecordBuf + nOffset ;
             if (certifInfo.bDim == 1)
@@ -1264,11 +1265,7 @@ OGRFeature *OGRSXFLayer::TranslateVetorAngle(const SXFRecordDescription& certifI
         return NULL;
     }
 
-    double dfX = 1.0;
-    double dfY = 1.0;
-    double dfZ = 0.0;
     GUInt32 nOffset = 0;
-    GUInt32 count;
     GUInt32 nDelta = 0;
 
     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
@@ -1278,10 +1275,13 @@ OGRFeature *OGRSXFLayer::TranslateVetorAngle(const SXFRecordDescription& certifI
 
     OGRLineString* poLS = new OGRLineString();
 
-    for (count = 0; count < certifInfo.nPointCount; count++)
+    for( GUInt32 count = 0; count < certifInfo.nPointCount; count++ )
     {
         const char * psCoords = psRecordBuf + nOffset;
 
+        double dfX = 1.0;
+        double dfY = 1.0;
+        double dfZ = 0.0;
         if (certifInfo.bDim == 1)
         {
             nDelta = TranslateXYH( certifInfo, psCoords, nBufLen - nOffset, &dfX, &dfY, &dfZ );
@@ -1303,8 +1303,8 @@ OGRFeature *OGRSXFLayer::TranslateVetorAngle(const SXFRecordDescription& certifI
     OGRPoint *poAngPT = new OGRPoint();
     poLS->EndPoint(poAngPT);
 
-    double xDiff = poPT->getX() - poAngPT->getX();
-    double yDiff = poPT->getY() - poAngPT->getY();
+    const double xDiff = poPT->getX() - poAngPT->getX();
+    const double yDiff = poPT->getY() - poAngPT->getY();
     double dfAngle = atan2(xDiff, yDiff) * TO_DEGREES - 90;
     if (dfAngle < 0)
         dfAngle += 360;
@@ -1318,7 +1318,6 @@ OGRFeature *OGRSXFLayer::TranslateVetorAngle(const SXFRecordDescription& certifI
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                         TranslatePolygon ()                          */
 /************************************************************************/
@@ -1354,8 +1353,7 @@ OGRFeature *OGRSXFLayer::TranslatePolygon(const SXFRecordDescription& certifInfo
             break;
         nOffset += nDelta;
         poLS->addPoint( dfX, dfY, dfZ );
-
-    }    // for
+    }  // for
 
     OGRLinearRing *poLR = new OGRLinearRing();
     poLR->addSubLineString( poLS, 0 );
@@ -1371,11 +1369,11 @@ OGRFeature *OGRSXFLayer::TranslatePolygon(const SXFRecordDescription& certifInfo
         if( nOffset + 4 > nBufLen )
             break;
 
-        GUInt16 nSubObj;
+        GUInt16 nSubObj = 0;
         memcpy(&nSubObj, psRecordBuf + nOffset, 2);
         CPL_LSBPTR16(&nSubObj);
 
-        GUInt16 nCoords;
+        GUInt16 nCoords = 0;
         memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
         CPL_LSBPTR16(&nCoords);
 
@@ -1441,39 +1439,44 @@ OGRFeature *OGRSXFLayer::TranslateText(const SXFRecordDescription& certifInfo,
     double dfY = 1.0;
     double dfZ = 0.0;
     GUInt32 nOffset = 0;
-    GUInt32 count;
     GUInt32 nDelta = 0;
-	//OGRFeatureDefn *fd = poFeatureDefn->Clone();
-	//fd->SetGeomType( wkbLineString );
- //   OGRFeature *poFeature = new OGRFeature(fd);
 
     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
+    OGRMultiLineString *poMLS = new  OGRMultiLineString ();
+
+/*---------------------- Reading Primary Line --------------------------------*/
+
     OGRLineString* poLS = new OGRLineString();
 
-    for(count=0 ; count <  certifInfo.nPointCount ; count++)
+    for(GUInt32 count=0 ; count <  certifInfo.nPointCount ; count++)
     {
-        const char * psBuf = psRecordBuf + nOffset;
+        const char * psCoords = psRecordBuf + nOffset ;
+
         if (certifInfo.bDim == 1)
         {
-            nDelta = TranslateXYH( certifInfo, psBuf, nBufLen - nOffset, &dfX, &dfY, &dfZ );
+            nDelta = TranslateXYH( certifInfo, psCoords, nBufLen - nOffset,
+                                   &dfX, &dfY, &dfZ );
         }
         else
         {
             dfZ = 0.0;
-            nDelta = TranslateXYH( certifInfo, psBuf, nBufLen - nOffset, &dfX, &dfY );
+            nDelta = TranslateXYH( certifInfo, psCoords, nBufLen - nOffset,
+                                   &dfX, &dfY );
         }
+
         if( nDelta == 0 )
             break;
-
         nOffset += nDelta;
+
         poLS->addPoint( dfX, dfY, dfZ );
     }
 
-    poFeature->SetGeometryDirectly( poLS );
+    poMLS->addGeometry( poLS );
 
-/*------------------     READING TEXT VALUE   ---------------------------------------*/
+/*------------------     READING TEXT VALUE   --------------------------------*/
+    CPLString soText;
 
-    if ( certifInfo.nSubObjectCount == 0 && certifInfo.bHasTextSign )
+    if ( certifInfo.bHasTextSign )
     {
         if( nOffset + 1 > nBufLen )
             return poFeature;
@@ -1489,19 +1492,84 @@ OGRFeature *OGRSXFLayer::TranslateText(const SXFRecordDescription& certifInfo,
 
         //TODO: Check encoding from sxf
         char* pszRecoded = CPLRecode(pszTextBuf, "CP1251", CPL_ENC_UTF8);
-        poFeature->SetField("TEXT", pszRecoded);
+        soText += pszRecoded;
         CPLFree(pszRecoded);
 
         CPLFree( pszTextBuf );
+
+        nOffset += nTextL+2;
     }
 
+/*---------------------- Reading Sub Lines --------------------------------*/
 
-/*****
- * TODO :
- *          - Translate graphics
- *          - Translate 3D vector
- */
+    for(int count=0 ; count <  certifInfo.nSubObjectCount ; count++)
+    {
+        poLS->empty();
+
+        if( nOffset + 4 > nBufLen )
+            break;
+
+        GUInt16 nSubObj = 0;
+        memcpy(&nSubObj, psRecordBuf + nOffset, 2);
+        CPL_LSBPTR16(&nSubObj);
+
+        GUInt16 nCoords = 0;
+        memcpy(&nCoords, psRecordBuf + nOffset + 2, 2);
+        CPL_LSBPTR16(&nCoords);
+
+        nOffset +=4;
+
+        for (int i=0; i < nCoords ; i++)
+        {
+            const char * psCoords = psRecordBuf + nOffset ;
+            if (certifInfo.bDim == 1)
+            {
+                nDelta = TranslateXYH( certifInfo, psCoords, nBufLen - nOffset, &dfX, &dfY, &dfZ );
+            }
+            else
+            {
+                dfZ = 0.0;
+                nDelta = TranslateXYH( certifInfo, psCoords, nBufLen - nOffset, &dfX, &dfY );
+            }
+
+            if( nDelta == 0 )
+                break;
+            nOffset += nDelta;
+
+            poLS->addPoint( dfX, dfY, dfZ );
+        }
+
+        poMLS->addGeometry( poLS );
+
+        if ( certifInfo.bHasTextSign )
+        {
+            if( nOffset + 1 > nBufLen )
+                return poFeature;
+            const char * pszTxt = psRecordBuf + nOffset;
+            GByte nTextL = (GByte) *pszTxt;
+            if( nOffset + 1 + nTextL > nBufLen )
+                return poFeature;
+
+            char * pszTextBuf = (char *)CPLMalloc( nTextL+1 );
+
+            strncpy(pszTextBuf, (pszTxt+1),    nTextL);
+            pszTextBuf[nTextL] = '\0';
+
+            //TODO: Check encoding from sxf
+            char* pszRecoded = CPLRecode(pszTextBuf, "CP1251", CPL_ENC_UTF8);
+            soText += " " + CPLString(pszRecoded);
+            CPLFree(pszRecoded);
+
+            CPLFree( pszTextBuf );
+
+            nOffset += nTextL+2;
+        }
+    }  // for
+
+    delete poLS;
+    poFeature->SetGeometryDirectly( poMLS );
 
+    poFeature->SetField("TEXT", soText);
     return poFeature;
 }
 
diff --git a/ogr/ogrsf_frmts/sxf/org_sxf_defs.h b/ogr/ogrsf_frmts/sxf/org_sxf_defs.h
index 9f2ea5b..f5a0f36 100644
--- a/ogr/ogrsf_frmts/sxf/org_sxf_defs.h
+++ b/ogr/ogrsf_frmts/sxf/org_sxf_defs.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: org_sxf_defs.h  $
+ * $Id: org_sxf_defs.h 35911 2016-10-24 15:03:26Z goatbar $
  *
  * Project:  SXF Translator
  * Purpose:  Include file defining Records Structures for file reading and
@@ -214,14 +214,12 @@ typedef struct
 
 } SXFMapDescription;
 
-
 enum SXFCoordinateType
 {
     SXF_CT_RECTANGULAR = 0,
     SXF_CT_GEODETIC
 };
 
-
 /*
  * List of SXF file format geometry types.
  */
@@ -317,7 +315,6 @@ typedef struct
     GUInt32 nCheckSum; //check sum
 }  SXFHeader;
 
-
 /************************************************************************/
 /*                         RSCInfo                                      */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/tiger/GNUmakefile b/ogr/ogrsf_frmts/tiger/GNUmakefile
index a8c43b0..32657d8 100644
--- a/ogr/ogrsf_frmts/tiger/GNUmakefile
+++ b/ogr/ogrsf_frmts/tiger/GNUmakefile
@@ -1,5 +1,3 @@
-
-
 include ../../../GDALmake.opt
 
 OBJ     =  ogrtigerdriver.o           \
@@ -27,19 +25,13 @@ OBJ     =  ogrtigerdriver.o           \
 	   tigerzipplus4.o	      \
 	   tigerpoint.o
 
-
-
 CPPFLAGS	:=	-I.. -I../..  $(CPPFLAGS)
 
 LIBS	:=	$(GDAL_LIB) $(LIBS)
 
-
 default:	$(O_OBJ:.o=.$(OBJ_EXT))
 
 $(O_OBJ): ogr_tiger.h
 
 clean:
 	rm -f *.o $(O_OBJ)
-
-tigerinfo$(EXE):	tigerinfo.$(OBJ_EXT)
-	$(LD) $(LDFLAGS) tigerinfo.$(OBJ_EXT) $(CONFIG_LIBS) -o tigerinfo$(EXE)
diff --git a/ogr/ogrsf_frmts/tiger/ogr_tiger.h b/ogr/ogrsf_frmts/tiger/ogr_tiger.h
index 118259b..cb6b9bb 100644
--- a/ogr/ogrsf_frmts/tiger/ogr_tiger.h
+++ b/ogr/ogrsf_frmts/tiger/ogr_tiger.h
@@ -1,6 +1,6 @@
 /*-*-C++-*-*/
 /******************************************************************************
- * $Id: ogr_tiger.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogr_tiger.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Main declarations for Tiger translator.
@@ -160,7 +160,7 @@ public:
 
   virtual const char *GetShortModule() { return pszShortModule; }
   virtual const char *GetModule() { return pszModule; }
-  virtual int         SetWriteModule( const char *, int, OGRFeature * );
+  virtual bool        SetWriteModule( const char *, int, OGRFeature * );
 
   virtual int         GetFeatureCount() { return nFeatures; }
 
@@ -170,31 +170,29 @@ public:
   static void         SetField( OGRFeature *, const char *, const char *,
                                 int, int );
 
-  int                 WriteField( OGRFeature *, const char *, char *,
+  static bool                WriteField( OGRFeature *, const char *, char *,
                                   int, int, char, char );
-  int                 WriteRecord( char *pachRecord, int nRecLen,
+  bool                WriteRecord( char *pachRecord, int nRecLen,
                                    const char *pszType, VSILFILE *fp = NULL );
-  int                 WritePoint( char *pachRecord, int nStart,
+  static bool                WritePoint( char *pachRecord, int nStart,
                                   double dfX, double dfY );
 
-  virtual int         SetModule( const char * pszModule );
+  virtual bool        SetModule( const char * pszModule );
   virtual OGRFeature *GetFeature( int nRecordId );
   virtual OGRErr      CreateFeature( OGRFeature *poFeature );
 
  protected:
-  void                WriteFields(const TigerRecordInfo *psRTInfo,
+  static void                WriteFields(const TigerRecordInfo *psRTInfo,
                                   OGRFeature      *poFeature,
                                   char            *szRecord);
 
-  void                AddFieldDefns(const TigerRecordInfo *psRTInfo,
+  static void                AddFieldDefns(const TigerRecordInfo *psRTInfo,
                                     OGRFeatureDefn  *poFeatureDefn);
 
-
-  void                SetFields(const TigerRecordInfo *psRTInfo,
+  static void                SetFields(const TigerRecordInfo *psRTInfo,
                                 OGRFeature      *poFeature,
                                 char            *achRecord);
 
-
   const TigerRecordInfo *psRTInfo;
   const char            *m_pszFileCode;
 };
@@ -208,12 +206,12 @@ class TigerCompleteChain : public TigerFileBase
   VSILFILE           *fpShape;
   int                *panShapeRecordId;
 
-  VSILFILE               *fpRT3;
-  int                 bUsingRT3;
+  VSILFILE           *fpRT3;
+  bool                bUsingRT3;
   int                 nRT1RecOffset;
 
   int                 GetShapeRecordId( int, int );
-  int                 AddShapePoints( int, int, OGRLineString *, int );
+  bool                AddShapePoints( int, int, OGRLineString *, int );
 
   void                AddFieldDefnsPre2002();
   OGRFeature         *GetFeaturePre2002( int );
@@ -232,13 +230,13 @@ public:
                                           const char * );
   virtual            ~TigerCompleteChain();
 
-  virtual int         SetModule( const char * );
+  virtual bool        SetModule( const char * ) override;
 
-  virtual OGRFeature *GetFeature( int );
+  virtual OGRFeature *GetFeature( int ) override;
 
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+  virtual OGRErr      CreateFeature( OGRFeature *poFeature ) override;
 
-  virtual int         SetWriteModule( const char *, int, OGRFeature * );
+  virtual bool        SetWriteModule( const char *, int, OGRFeature * ) override;
 };
 
 /************************************************************************/
@@ -249,11 +247,11 @@ class TigerAltName : public TigerFileBase
 {
  public:
                       TigerAltName( OGRTigerDataSource *,
-                                          const char * );
+                                    const char * );
 
-  virtual OGRFeature *GetFeature( int );
+  virtual OGRFeature *GetFeature( int ) override;
 
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+  virtual OGRErr      CreateFeature( OGRFeature *poFeature ) override;
 };
 
 /************************************************************************/
@@ -302,16 +300,14 @@ class TigerPoint : public TigerFileBase
  int                  bRequireGeom;
 
  public:
-  virtual OGRFeature *GetFeature( int nFID) { return TigerFileBase::GetFeature(nFID); } /* to avoid -Woverloaded-virtual warnings */
+  virtual OGRFeature *GetFeature( int nFID) override { return TigerFileBase::GetFeature(nFID); } /* to avoid -Woverloaded-virtual warnings */
   OGRFeature *GetFeature( int              nRecordId,
                                   int nX0, int nX1,
                                   int nY0, int nY1 );
 
-
-  virtual OGRErr CreateFeature( OGRFeature      *poFeature) { return TigerFileBase::CreateFeature(poFeature); } /* to avoid -Woverloaded-virtual warnings */
+  virtual OGRErr CreateFeature( OGRFeature      *poFeature) override { return TigerFileBase::CreateFeature(poFeature); } /* to avoid -Woverloaded-virtual warnings */
   OGRErr CreateFeature( OGRFeature      *poFeature,
                                 int nIndex );
-
 };
 
 /************************************************************************/
@@ -323,9 +319,9 @@ class TigerLandmarks : public TigerPoint
  public:
                       TigerLandmarks( OGRTigerDataSource *, const char * );
 
-  virtual OGRFeature *GetFeature( int );
+  virtual OGRFeature *GetFeature( int ) override;
 
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+  virtual OGRErr      CreateFeature( OGRFeature *poFeature ) override;
 };
 
 /************************************************************************/
@@ -359,19 +355,19 @@ class TigerPolygon : public TigerFileBase
   const TigerRecordInfo    *psRTSInfo;
 
   VSILFILE               *fpRTS;
-  int                 bUsingRTS;
+  bool                bUsingRTS;
   int                 nRTSRecLen;
 
 public:
                       TigerPolygon( OGRTigerDataSource *, const char * );
   virtual            ~TigerPolygon();
 
-  virtual int         SetModule( const char * );
+  virtual bool        SetModule( const char * ) override;
 
-  virtual OGRFeature *GetFeature( int );
+  virtual OGRFeature *GetFeature( int ) override;
 
-  virtual int         SetWriteModule( const char *, int, OGRFeature * );
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+  virtual bool        SetWriteModule( const char *, int, OGRFeature * ) override;
+  virtual OGRErr      CreateFeature( OGRFeature *poFeature ) override;
 };
 
 /************************************************************************/
@@ -402,7 +398,6 @@ class TigerPolygonEconomic : public TigerFileBase
 {
 public:
                       TigerPolygonEconomic( OGRTigerDataSource *, const char * );
-
 };
 
 /************************************************************************/
@@ -444,9 +439,9 @@ class TigerPIP : public TigerPoint
 public:
                       TigerPIP( OGRTigerDataSource *, const char * );
 
-  virtual OGRFeature *GetFeature( int );
+  virtual OGRFeature *GetFeature( int ) override;
 
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+  virtual OGRErr      CreateFeature( OGRFeature *poFeature ) override;
 };
 
 /************************************************************************/
@@ -478,9 +473,9 @@ class TigerOverUnder : public TigerPoint
 public:
                       TigerOverUnder( OGRTigerDataSource *, const char * );
 
-  virtual OGRFeature *GetFeature( int );
+  virtual OGRFeature *GetFeature( int ) override;
 
-  virtual OGRErr      CreateFeature( OGRFeature *poFeature );
+  virtual OGRErr      CreateFeature( OGRFeature *poFeature ) override;
 };
 
 /************************************************************************/
@@ -515,19 +510,19 @@ class OGRTigerLayer : public OGRLayer
                                        TigerFileBase * );
     virtual             ~OGRTigerLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
-    OGRFeature         *GetFeature( GIntBig nFeatureId );
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
+    OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
 
-    OGRFeatureDefn *    GetLayerDefn();
+    OGRFeatureDefn *    GetLayerDefn() override;
 
-    GIntBig             GetFeatureCount( int );
+    GIntBig             GetFeatureCount( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
 };
 
 /************************************************************************/
@@ -553,18 +548,18 @@ class OGRTigerDataSource : public OGRDataSource
     int                 nVersionCode;
     TigerVersion        nVersion;
 
-    int                 bWriteMode;
+    bool                bWriteMode;
 
     TigerVersion        TigerCheckVersion( TigerVersion, const char * );
 
   public:
                         OGRTigerDataSource();
-                        ~OGRTigerDataSource();
+                        virtual ~OGRTigerDataSource();
 
-    int                 GetWriteMode() { return bWriteMode; }
+    bool                GetWriteMode() const { return bWriteMode; }
 
-    TigerVersion        GetVersion() { return nVersion; }
-    int                 GetVersionCode() { return nVersionCode; }
+    TigerVersion        GetVersion() const { return nVersion; }
+    int                 GetVersionCode() const { return nVersionCode; }
 
     void                SetOptionList( char ** );
     const char         *GetOption( const char * );
@@ -574,13 +569,13 @@ class OGRTigerDataSource : public OGRDataSource
 
     int                 Create( const char *pszName, char **papszOptions );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount();
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override;
+    OGRLayer            *GetLayer( int ) override;
     OGRLayer            *GetLayer( const char *pszLayerName );
 
     void                AddLayer( OGRTigerLayer * );
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
     OGRSpatialReference *GetSpatialRef() { return poSpatialRef; }
 
@@ -588,18 +583,17 @@ class OGRTigerDataSource : public OGRDataSource
     char                *BuildFilename( const char * pszModule,
                                         const char * pszExtension );
 
-
-    int                 GetModuleCount() { return nModules; }
+    int                 GetModuleCount() const { return nModules; }
     const char         *GetModule( int );
-    int                 CheckModule( const char *pszModule );
+    bool                CheckModule( const char *pszModule );
     void                AddModule( const char *pszModule );
 
     void                DeleteModuleFiles( const char *pszModule );
 
     virtual OGRLayer    *ICreateLayer( const char *,
-                                      OGRSpatialReference * = NULL,
-                                      OGRwkbGeometryType = wkbUnknown,
-                                      char ** = NULL );
+                                       OGRSpatialReference * = NULL,
+                                       OGRwkbGeometryType = wkbUnknown,
+                                       char ** = NULL ) override;
 };
 
 #endif /* ndef OGR_TIGER_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
index 5380385..1414146 100644
--- a/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
+++ b/ogr/ogrsf_frmts/tiger/ogrtigerdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrtigerdatasource.cpp 33710 2016-03-12 06:28:29Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements OGRTigerDataSource class
@@ -32,8 +31,9 @@
 #include "ogr_tiger.h"
 
 #include <cctype>
+#include <algorithm>
 
-CPL_CVSID("$Id: ogrtigerdatasource.cpp 33710 2016-03-12 06:28:29Z goatbar $");
+CPL_CVSID("$Id: ogrtigerdatasource.cpp 36017 2016-10-29 04:27:08Z goatbar $");
 
 /************************************************************************/
 /*                        TigerClassifyVersion()                        */
@@ -194,19 +194,18 @@ OGRTigerDataSource::OGRTigerDataSource() :
     pszName(NULL),
     nLayers(0),
     papoLayers(NULL),
+    poSpatialRef(new OGRSpatialReference(
+        "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\","
+        "SPHEROID[\"GRS 1980\",6378137,298.257222101]],PRIMEM[\"Greenwich\",0],"
+        "UNIT[\"degree\",0.0174532925199433]]")),
     papszOptions(NULL),
     pszPath(NULL),
     nModules(0),
     papszModules(NULL),
     nVersionCode(0),
     nVersion(TIGER_Unknown),
-    bWriteMode(FALSE)
-{
-    poSpatialRef = new OGRSpatialReference(
-        "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\","
-        "SPHEROID[\"GRS 1980\",6378137,298.257222101]],PRIMEM[\"Greenwich\",0],"
-        "UNIT[\"degree\",0.0174532925199433]]" );
-}
+    bWriteMode(false)
+{}
 
 /************************************************************************/
 /*                        ~OGRTigerDataSource()                         */
@@ -395,20 +394,15 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
     {
         if( bTestOpen || i == 0 )
         {
-            char        szHeader[500];
-            VSILFILE    *fp;
-            char        *pszRecStart = NULL;
-            int         bIsGDT = FALSE;
-            char       *l_pszFilename;
-
-            l_pszFilename = BuildFilename( papszFileList[i], "1" );
+            char *l_pszFilename = BuildFilename( papszFileList[i], "1" );
 
-            fp = VSIFOpenL( l_pszFilename, "rb" );
+            VSILFILE *fp = VSIFOpenL( l_pszFilename, "rb" );
             CPLFree( l_pszFilename );
 
             if( fp == NULL )
                 continue;
 
+            char szHeader[500] = {};
             if( VSIFReadL( szHeader, sizeof(szHeader)-1, 1, fp ) < 1 )
             {
                 VSIFCloseL( fp );
@@ -417,13 +411,15 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
 
             VSIFCloseL( fp );
 
-            pszRecStart = szHeader;
+            char *pszRecStart = szHeader;
             szHeader[sizeof(szHeader)-1] = '\0';
 
+            bool bIsGDT = false;
+
             if( STARTS_WITH_CI(pszRecStart, "Copyright (C)")
                 && strstr(pszRecStart,"Geographic Data Tech") != NULL )
             {
-                bIsGDT = TRUE;
+                bIsGDT = true;
 
                 while( *pszRecStart != '\0'
                        && *pszRecStart != 10
@@ -490,16 +486,16 @@ int OGRTigerDataSource::Open( const char * pszFilename, int bTestOpen,
 /* -------------------------------------------------------------------- */
 /*      Do we have a user provided version override?                    */
 /* -------------------------------------------------------------------- */
-    if( CPLGetConfigOption( "TIGER_VERSION", NULL ) != NULL )
-    {
-        const char *pszRequestedVersion =
+    const char *pszRequestedVersion =
             CPLGetConfigOption( "TIGER_VERSION", NULL );
+    if( pszRequestedVersion != NULL )
+    {
 
         if( STARTS_WITH_CI(pszRequestedVersion, "TIGER_") )
         {
-            int iCode;
+            int iCode = 1;  // Used after for.
 
-            for( iCode = 1; iCode < TIGER_Unknown; iCode++ )
+            for( ; iCode < TIGER_Unknown; iCode++ )
             {
                 if( EQUAL(TigerVersionString((TigerVersion)iCode),
                           pszRequestedVersion) )
@@ -683,17 +679,15 @@ const char *OGRTigerDataSource::GetModule( int iModule )
 /*      written to before.                                              */
 /************************************************************************/
 
-int OGRTigerDataSource::CheckModule( const char *pszModule )
+bool OGRTigerDataSource::CheckModule( const char *pszModule )
 
 {
-    int         i;
-
-    for( i = 0; i < nModules; i++ )
+    for( int i = 0; i < nModules; i++ )
     {
-        if( EQUAL(pszModule,papszModules[i]) )
-            return TRUE;
+        if( EQUAL(pszModule, papszModules[i]) )
+            return true;
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -715,16 +709,14 @@ void OGRTigerDataSource::AddModule( const char *pszModule )
 /************************************************************************/
 
 char *OGRTigerDataSource::BuildFilename( const char *pszModuleName,
-                                    const char *pszExtension )
+                                         const char *pszExtension )
 
 {
-    char        *pszFilename;
-    char        szLCExtension[3];
-
 /* -------------------------------------------------------------------- */
 /*      Force the record type to lower case if the filename appears     */
 /*      to be in lower case.                                            */
 /* -------------------------------------------------------------------- */
+    char szLCExtension[3] = {};
     if( *pszExtension >= 'A' && *pszExtension <= 'Z' && *pszModuleName == 't' )
     {
         szLCExtension[0] = (*pszExtension) + 'a' - 'A';
@@ -735,10 +727,11 @@ char *OGRTigerDataSource::BuildFilename( const char *pszModuleName,
 /* -------------------------------------------------------------------- */
 /*      Build the filename.                                             */
 /* -------------------------------------------------------------------- */
-    const size_t nFilenameLen = strlen(GetDirPath())
-                                     + strlen(pszModuleName)
-                                     + strlen(pszExtension) + 10;
-    pszFilename = (char *) CPLMalloc(nFilenameLen);
+    const size_t nFilenameLen =
+        strlen(GetDirPath())
+        + strlen(pszModuleName)
+        + strlen(pszExtension) + 10;
+    char *pszFilename = (char *) CPLMalloc(nFilenameLen);
 
     if( strlen(GetDirPath()) == 0 )
         snprintf( pszFilename, nFilenameLen, "%s%s",
@@ -793,7 +786,7 @@ int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptionsIn )
 /* -------------------------------------------------------------------- */
     pszPath = CPLStrdup( pszNameIn );
     pszName = CPLStrdup( pszNameIn );
-    bWriteMode = TRUE;
+    bWriteMode = true;
 
     SetOptionList( papszOptionsIn );
 
@@ -806,7 +799,7 @@ int OGRTigerDataSource::Create( const char *pszNameIn, char **papszOptionsIn )
     if( GetOption("VERSION") != NULL )
     {
         nVersionCode = atoi(GetOption("VERSION"));
-        nVersionCode = MAX(0,MIN(9999,nVersionCode));
+        nVersionCode = std::max(0, std::min(9999, nVersionCode));
     }
     nVersion = TigerClassifyVersion(nVersionCode);
 
@@ -957,16 +950,14 @@ OGRLayer *OGRTigerDataSource::ICreateLayer( const char *pszLayerName,
 void OGRTigerDataSource::DeleteModuleFiles( const char *pszModule )
 
 {
-    char        **papszDirFiles = VSIReadDir( GetDirPath() );
-    int         i, nCount = CSLCount(papszDirFiles);
+    char **papszDirFiles = VSIReadDir( GetDirPath() );
+    const int nCount = CSLCount(papszDirFiles);
 
-    for( i = 0; i < nCount; i++ )
+    for( int i = 0; i < nCount; i++ )
     {
         if( EQUALN(pszModule,papszDirFiles[i],strlen(pszModule)) )
         {
-            const char  *pszFilename;
-
-            pszFilename = CPLFormFilename( GetDirPath(),
+            const char *pszFilename = CPLFormFilename( GetDirPath(),
                                            papszDirFiles[i],
                                            NULL );
             if( VSIUnlink( pszFilename ) != 0 )
diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp
index 7fb0e8b..f2ded88 100644
--- a/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp
+++ b/ogr/ogrsf_frmts/tiger/ogrtigerdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrtigerdriver.cpp 33105 2016-01-23 15:27:32Z rouault $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements OGRTigerDriver
@@ -30,7 +29,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrtigerdriver.cpp 33105 2016-01-23 15:27:32Z rouault $");
+CPL_CVSID("$Id: ogrtigerdriver.cpp 35466 2016-09-16 05:03:52Z goatbar $");
 
 /************************************************************************/
 /*                                Open()                                */
@@ -44,16 +43,15 @@ static GDALDataset *OGRTigerDriverOpen( GDALOpenInfo* poOpenInfo )
     char** papszSiblingFiles = poOpenInfo->GetSiblingFiles();
     if( papszSiblingFiles != NULL )
     {
-        int i;
-        int bFoundCompatibleFile = FALSE;
-        for( i = 0; papszSiblingFiles[i] != NULL; i++ )
+        bool bFoundCompatibleFile = false;
+        for( int i = 0; papszSiblingFiles[i] != NULL; i++ )
         {
             int nLen = (int)strlen(papszSiblingFiles[i]);
             if( nLen > 4 &&
                 papszSiblingFiles[i][nLen-4] == '.' &&
                 papszSiblingFiles[i][nLen-1] == '1' )
             {
-                bFoundCompatibleFile = TRUE;
+                bFoundCompatibleFile = true;
                 break;
             }
         }
@@ -91,9 +89,7 @@ static GDALDataset *OGRTigerDriverCreate( const char * pszName,
                                           CPL_UNUSED GDALDataType eDT,
                                           char **papszOptions )
 {
-    OGRTigerDataSource *poDS;
-
-    poDS = new OGRTigerDataSource();
+    OGRTigerDataSource *poDS = new OGRTigerDataSource();
 
     if( poDS->Create( pszName, papszOptions ) )
         return poDS;
diff --git a/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp b/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp
index ab71f12..43abd8e 100644
--- a/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp
+++ b/ogr/ogrsf_frmts/tiger/ogrtigerlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrtigerlayer.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements OGRTigerLayer class.
@@ -29,7 +28,7 @@
 
 #include "ogr_tiger.h"
 
-CPL_CVSID("$Id: ogrtigerlayer.cpp 33706 2016-03-11 13:33:27Z goatbar $");
+CPL_CVSID("$Id: ogrtigerlayer.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                           OGRTigerLayer()                            */
@@ -39,19 +38,15 @@ CPL_CVSID("$Id: ogrtigerlayer.cpp 33706 2016-03-11 13:33:27Z goatbar $");
 /************************************************************************/
 
 OGRTigerLayer::OGRTigerLayer( OGRTigerDataSource *poDSIn,
-                              TigerFileBase * poReaderIn )
-
+                              TigerFileBase * poReaderIn ) :
+    poReader(poReaderIn),
+    poDS(poDSIn),
+    nFeatureCount(0),
+    panModuleFCount(NULL),
+    panModuleOffset(NULL),
+    iLastFeatureId(0),
+    iLastModule(-1)
 {
-    poDS = poDSIn;
-    poReader = poReaderIn;
-
-    iLastFeatureId = 0;
-    iLastModule = -1;
-
-    nFeatureCount = 0;
-    panModuleFCount = NULL;
-    panModuleOffset = NULL;
-
 /* -------------------------------------------------------------------- */
 /*      Setup module feature counts.                                    */
 /* -------------------------------------------------------------------- */
@@ -146,9 +141,7 @@ OGRFeature *OGRTigerLayer::GetFeature( GIntBig nFeatureId )
 /* -------------------------------------------------------------------- */
 /*      Fetch the feature associated with the record.                   */
 /* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature;
-
-    poFeature =
+    OGRFeature  *poFeature =
         poReader->GetFeature( (int)nFeatureId-panModuleOffset[iLastModule]-1 );
 
     if( poFeature != NULL )
@@ -167,7 +160,6 @@ OGRFeature *OGRTigerLayer::GetFeature( GIntBig nFeatureId )
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp b/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
index f5dac78..131db0a 100644
--- a/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigeraltname.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigeraltname.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerAltName, providing access to RT4 files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigeraltname.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+CPL_CVSID("$Id: tigeraltname.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
-#define FILE_CODE "4"
+static const char FILE_CODE[] = "4";
 
 static const TigerFieldInfo rt4_fields[] = {
   // fieldname    fmt  type  OFTType         beg  end  len  bDefine bSet bWrite
@@ -52,7 +51,6 @@ static const TigerRecordInfo rt4_info =
     58
   };
 
-
 /************************************************************************/
 /*                            TigerAltName()                            */
 /************************************************************************/
@@ -126,9 +124,8 @@ OGRFeature *TigerAltName::GetFeature( int nRecordId )
 
     for( int iFeat = 0; iFeat < 5; iFeat++ )
     {
-        const char *    pszFieldText;
-
-        pszFieldText = GetField( achRecord, 19 + iFeat*8, 26 + iFeat*8 );
+        const char *pszFieldText =
+            GetField( achRecord, 19 + iFeat*8, 26 + iFeat*8 );
 
         if( *pszFieldText != '\0' )
             anFeatList[nFeatCount++] = atoi(pszFieldText);
@@ -146,21 +143,21 @@ OGRFeature *TigerAltName::GetFeature( int nRecordId )
 OGRErr TigerAltName::CreateFeature( OGRFeature *poFeature )
 
 {
-  char        szRecord[OGR_TIGER_RECBUF_LEN];
-    const int   *panValue;
-    int         nValueCount = 0;
 
     if( !SetWriteModule( FILE_CODE, psRTInfo->nRecordLength+2, poFeature ) )
         return OGRERR_FAILURE;
 
+    char szRecord[OGR_TIGER_RECBUF_LEN] = {};
     memset( szRecord, ' ', psRTInfo->nRecordLength );
 
     WriteFields( psRTInfo, poFeature, szRecord );
 
-    panValue = poFeature->GetFieldAsIntegerList( "FEAT", &nValueCount );
+    int nValueCount = 0;
+    const int *panValue =
+        poFeature->GetFieldAsIntegerList( "FEAT", &nValueCount );
     for( int i = 0; i < nValueCount; i++ )
     {
-        char    szWork[9];
+        char szWork[9] = {};
 
         snprintf( szWork, sizeof(szWork), "%8d", panValue[i] );
         strncpy( szRecord + 18 + 8 * i, szWork, 8 );
diff --git a/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp b/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp
index a071697..c1bef78 100644
--- a/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerarealandmarks.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerarealandmarks.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerAreaLandmarks, providing access to .RT8 files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerarealandmarks.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerarealandmarks.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
-#define FILE_CODE "8"
+static const char FILE_CODE[] = "8";
 
 static const TigerFieldInfo rt8_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -70,5 +69,4 @@ TigerAreaLandmarks::TigerAreaLandmarks( OGRTigerDataSource * poDSIn,
     /* -------------------------------------------------------------------- */
 
     AddFieldDefns( psRTInfo, poFeatureDefn );
-
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp b/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
index 4387ba2..d5b9563 100644
--- a/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigercompletechain.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigercompletechain.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerCompleteChain, providing access to RT1 and
@@ -31,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigercompletechain.cpp 33706 2016-03-11 13:33:27Z goatbar $");
+CPL_CVSID("$Id: tigercompletechain.cpp 36472 2016-11-23 16:38:20Z rouault $");
 
 static const TigerFieldInfo rt1_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -140,7 +139,6 @@ static const TigerRecordInfo rt2_info =
     208         // <--- nRecordLength
   };
 
-
 static const TigerFieldInfo rt3_2000_Redistricting_fields[] = {
   // fieldname    fmt  type OFTType       beg  end  len  bDefine bSet bWrite
   { "TLID",       'R', 'N', OFTInteger,     6,  15,  10,       0,   0,     1 },
@@ -201,8 +199,8 @@ static const TigerFieldInfo rt3_fields[] = {
 
   { "VTDL",       'L', 'A', OFTString,    104, 107,   4,       1,   1,     1 },
   { "VTDR",       'L', 'A', OFTString,    108, 111,   4,       1,   1,     1 }
-
 };
+
 static const TigerRecordInfo rt3_info =
   {
     rt3_fields,
@@ -214,21 +212,28 @@ static const TigerRecordInfo rt3_info =
 /*                         TigerCompleteChain()                         */
 /************************************************************************/
 
-TigerCompleteChain::TigerCompleteChain( OGRTigerDataSource * poDSIn,
-                                        CPL_UNUSED const char * pszPrototypeModule )
+TigerCompleteChain::TigerCompleteChain(
+    OGRTigerDataSource * poDSIn,
+    const char * /* pszPrototypeModule */ ) :
+    fpShape(NULL),
+    panShapeRecordId(NULL),
+    fpRT3(NULL),
+    bUsingRT3(false),
+    psRT1Info(NULL),
+    psRT2Info(NULL),
+    psRT3Info(NULL)
 {
     poDS = poDSIn;
     poFeatureDefn = new OGRFeatureDefn( "CompleteChain" );
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbLineString );
 
-
     if (poDS->GetVersion() >= TIGER_2002) {
       psRT1Info = &rt1_2002_info;
-      bUsingRT3 = FALSE;
+      // bUsingRT3 = false;
     } else {
       psRT1Info = &rt1_info;
-      bUsingRT3 = TRUE;
+      bUsingRT3 = true;
     }
 
     psRT2Info = &rt2_info;
@@ -241,11 +246,6 @@ TigerCompleteChain::TigerCompleteChain( OGRTigerDataSource * poDSIn,
       psRT3Info = &rt3_info;
     }
 
-    fpRT3 = NULL;
-
-    panShapeRecordId = NULL;
-    fpShape = NULL;
-
     /* -------------------------------------------------------------------- */
     /*      Fields from type 1 record.                                      */
     /* -------------------------------------------------------------------- */
@@ -256,7 +256,8 @@ TigerCompleteChain::TigerCompleteChain( OGRTigerDataSource * poDSIn,
     /*      Fields from type 3 record.  Eventually we should verify that    */
     /*      a .RT3 file is available before adding these fields.            */
     /* -------------------------------------------------------------------- */
-    if( bUsingRT3 ) {
+    if( bUsingRT3 )
+    {
       AddFieldDefns( psRT3Info, poFeatureDefn );
     }
 }
@@ -281,11 +282,11 @@ TigerCompleteChain::~TigerCompleteChain()
 /*                             SetModule()                              */
 /************************************************************************/
 
-int TigerCompleteChain::SetModule( const char * pszModuleIn )
+bool TigerCompleteChain::SetModule( const char * pszModuleIn )
 
 {
     if( !OpenFile( pszModuleIn, "1" ) )
-        return FALSE;
+        return false;
 
     EstablishFeatureCount();
 
@@ -322,9 +323,7 @@ int TigerCompleteChain::SetModule( const char * pszModuleIn )
 
         if( pszModuleIn )
         {
-            char        *pszFilename;
-
-            pszFilename = poDS->BuildFilename( pszModuleIn, "3" );
+            char *pszFilename = poDS->BuildFilename( pszModuleIn, "3" );
 
             fpRT3 = VSIFOpenL( pszFilename, "rb" );
 
@@ -350,9 +349,7 @@ int TigerCompleteChain::SetModule( const char * pszModuleIn )
 /* -------------------------------------------------------------------- */
     if( pszModuleIn != NULL )
     {
-        char    *pszFilename;
-
-        pszFilename = poDS->BuildFilename( pszModuleIn, "2" );
+        char *pszFilename = poDS->BuildFilename( pszModuleIn, "2" );
 
         fpShape = VSIFOpenL( pszFilename, "rb" );
 
@@ -369,7 +366,7 @@ int TigerCompleteChain::SetModule( const char * pszModuleIn )
         CPLFree( pszFilename );
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -447,7 +444,6 @@ OGRFeature *TigerCompleteChain::GetFeature( int nRecordId )
         }
 
         SetFields( psRT3Info, poFeature, achRT3Rec );
-
     }
 
 /* -------------------------------------------------------------------- */
@@ -481,27 +477,26 @@ OGRFeature *TigerCompleteChain::GetFeature( int nRecordId )
 /*      and add the points to the passed line geometry.                 */
 /************************************************************************/
 
-int TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
+bool TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
                                         OGRLineString * poLine,
                                         CPL_UNUSED int nSeqNum )
 {
-    int         nShapeRecId;
-
-    nShapeRecId = GetShapeRecordId( nRecordId, nTLID );
+    int nShapeRecId = GetShapeRecordId( nRecordId, nTLID );
 
     // -2 means an error occurred.
     if( nShapeRecId == -2 )
-        return FALSE;
+        return false;
 
     // -1 means there are no extra shape vertices, but things worked fine.
     if( nShapeRecId == -1 )
-        return TRUE;
+        return true;
 
 /* -------------------------------------------------------------------- */
 /*      Read all the sequential records with the same TLID.             */
 /* -------------------------------------------------------------------- */
-    char        achShapeRec[OGR_TIGER_RECBUF_LEN];
-    int         nShapeRecLen = psRT2Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength;
+    char achShapeRec[OGR_TIGER_RECBUF_LEN];
+    const int nShapeRecLen =
+        psRT2Info->nRecordLength + nRecordLength - psRT1Info->nRecordLength;
 
     for( ; true; nShapeRecId++ )
     {
@@ -513,7 +508,7 @@ int TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
             CPLError( CE_Failure, CPLE_FileIO,
                       "Failed to seek to %d of %s2",
                       (nShapeRecId-1) * nShapeRecLen, pszModule );
-            return FALSE;
+            return false;
         }
 
         nBytesRead = static_cast<int>(VSIFReadL( achShapeRec, 1, psRT2Info->nRecordLength,
@@ -534,7 +529,7 @@ int TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
                       "Failed to read %d bytes of record %d of %s2 at offset %d",
                       psRT2Info->nRecordLength, nShapeRecId, pszModule,
                       (nShapeRecId-1) * nShapeRecLen );
-            return FALSE;
+            return false;
         }
 
         if( atoi(GetField(achShapeRec,6,15)) != nTLID )
@@ -543,13 +538,13 @@ int TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
 /* -------------------------------------------------------------------- */
 /*      Translate the locations into OGRLineString vertices.            */
 /* -------------------------------------------------------------------- */
-        int     iVertex;
+        int iVertex = 0;  // Used after for.
 
-        for( iVertex = 0; iVertex < 10; iVertex++ )
+        for( ; iVertex < 10; iVertex++ )
         {
-            int         iStart = 19 + 19*iVertex;
-            int         nX = atoi(GetField(achShapeRec,iStart,iStart+9));
-            int         nY = atoi(GetField(achShapeRec,iStart+10,iStart+18));
+            const int iStart = 19 + 19*iVertex;
+            const int nX = atoi(GetField(achShapeRec,iStart,iStart+9));
+            const int nY = atoi(GetField(achShapeRec,iStart+10,iStart+18));
 
             if( nX == 0 && nY == 0 )
                 break;
@@ -564,7 +559,7 @@ int TigerCompleteChain::AddShapePoints( int nTLID, int nRecordId,
             break;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -673,13 +668,12 @@ int TigerCompleteChain::GetShapeRecordId( int nChainId, int nTLID )
 /************************************************************************/
 /*                           SetWriteModule()                           */
 /************************************************************************/
-int TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen,
-                                        OGRFeature *poFeature )
+bool TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen,
+                                         OGRFeature *poFeature )
 
 {
-    int bSuccess;
-
-    bSuccess = TigerFileBase::SetWriteModule( pszFileCode, nRecLen, poFeature);
+    const bool bSuccess =
+        TigerFileBase::SetWriteModule( pszFileCode, nRecLen, poFeature);
     if( !bSuccess )
         return bSuccess;
 
@@ -696,9 +690,7 @@ int TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen,
 
         if( pszModule )
         {
-            char        *pszFilename;
-
-            pszFilename = poDS->BuildFilename( pszModule, "3" );
+            char *pszFilename = poDS->BuildFilename( pszModule, "3" );
 
             fpRT3 = VSIFOpenL( pszFilename, "ab" );
 
@@ -718,16 +710,14 @@ int TigerCompleteChain::SetWriteModule( const char *pszFileCode, int nRecLen,
 
     if( pszModule )
     {
-        char        *pszFilename;
-
-        pszFilename = poDS->BuildFilename( pszModule, "2" );
+        char *pszFilename = poDS->BuildFilename( pszModule, "2" );
 
         fpShape = VSIFOpenL( pszFilename, "ab" );
 
         CPLFree( pszFilename );
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -761,7 +751,8 @@ OGRErr TigerCompleteChain::CreateFeature( OGRFeature *poFeature )
     /* -------------------------------------------------------------------- */
     /*      Write geographic entity codes (RT3)                             */
     /* -------------------------------------------------------------------- */
-    if (bUsingRT3) {
+    if( bUsingRT3 )
+    {
       memset( szRecord, ' ', psRT3Info->nRecordLength );
       WriteFields( psRT3Info, poFeature, szRecord );
       WriteRecord( szRecord, psRT3Info->nRecordLength, "3", fpRT3 );
@@ -772,22 +763,20 @@ OGRErr TigerCompleteChain::CreateFeature( OGRFeature *poFeature )
     /* -------------------------------------------------------------------- */
     if( poLine->getNumPoints() > 2 )
     {
-        int     nPoints = poLine->getNumPoints();
-        int     iPoint, nRTSQ = 1;
+        const int nPoints = poLine->getNumPoints();
 
-        for( iPoint = 1; iPoint < nPoints-1; )
+        for( int iPoint = 1, nRTSQ = 1; iPoint < nPoints-1; )
         {
-            int         i;
-            char        szTemp[5];
+            char szTemp[5] = {};
 
             memset( szRecord, ' ', psRT2Info->nRecordLength );
 
             WriteField( poFeature, "TLID", szRecord, 6, 15, 'R', 'N' );
 
-            snprintf( szTemp, sizeof(szTemp), "%3d", nRTSQ );
+            CPLsnprintf( szTemp, sizeof(szTemp), "%3d", nRTSQ );
             strncpy( ((char *)szRecord) + 15, szTemp, 4 );
 
-            for( i = 0; i < 10; i++ )
+            for( int i = 0; i < 10; i++ )
             {
                 if( iPoint < nPoints-1 )
                     WritePoint( szRecord, 19+19*i,
diff --git a/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp b/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp
index b818547..739d492 100644
--- a/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerentitynames.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerentitynames.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerEntityNames, providing access to .RTC files.
@@ -31,9 +30,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerentitynames.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerentitynames.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
-#define FILE_CODE "C"
+static const char FILE_CODE[] = "C";
 
 static const TigerFieldInfo rtC_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -114,7 +113,6 @@ static const TigerRecordInfo rtC_info =
     112
   };
 
-
 /************************************************************************/
 /*                          TigerEntityNames()                          */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp b/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp
index 8a4550e..310a5bf 100644
--- a/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerfeatureids.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerfeatureids.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerFeatureIds, providing access to .RT5 files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerfeatureids.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerfeatureids.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE "5"
+static const char FILE_CODE[] = "5";
 
 static const TigerFieldInfo rt5_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
diff --git a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
index 5bb96e6..9cc501a 100644
--- a/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerfilebase.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerfilebase.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerBaseFile class, providing common services to all
@@ -34,14 +33,14 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: tigerfilebase.cpp 33706 2016-03-11 13:33:27Z goatbar $");
+CPL_CVSID("$Id: tigerfilebase.cpp 37987 2017-04-14 07:42:50Z rouault $");
 
 /************************************************************************/
 /*                           TigerFileBase()                            */
 /************************************************************************/
 
 TigerFileBase::TigerFileBase( const TigerRecordInfo *psRTInfoIn,
-                              const char            *m_pszFileCodeIn ) :
+                              const char *m_pszFileCodeIn ) :
     poDS(NULL),
     pszModule(NULL),
     pszShortModule(NULL),
@@ -53,7 +52,7 @@ TigerFileBase::TigerFileBase( const TigerRecordInfo *psRTInfoIn,
     nVersion(TIGER_Unknown),
     psRTInfo(psRTInfoIn),
     m_pszFileCode(m_pszFileCodeIn)
-{ }
+{}
 
 /************************************************************************/
 /*                           ~TigerFileBase()                           */
@@ -86,7 +85,6 @@ int TigerFileBase::OpenFile( const char * pszModuleToOpen,
                              const char *pszExtension )
 
 {
-    char        *pszFilename;
 
     CPLFree( pszModule );
     pszModule = NULL;
@@ -102,28 +100,26 @@ int TigerFileBase::OpenFile( const char * pszModuleToOpen,
     if( pszModuleToOpen == NULL )
         return TRUE;
 
-    pszFilename = poDS->BuildFilename( pszModuleToOpen, pszExtension );
+    char *pszFilename = poDS->BuildFilename( pszModuleToOpen, pszExtension );
 
     fpPrimary = VSIFOpenL( pszFilename, "rb" );
 
     CPLFree( pszFilename );
 
-    if( fpPrimary != NULL )
+    if( fpPrimary == NULL )
+        return FALSE;
+
+    pszModule = CPLStrdup(pszModuleToOpen);
+    pszShortModule = CPLStrdup(pszModuleToOpen);
+    for( int i = 0; pszShortModule[i] != '\0'; i++ )
     {
-        pszModule = CPLStrdup(pszModuleToOpen);
-        pszShortModule = CPLStrdup(pszModuleToOpen);
-        for( int i = 0; pszShortModule[i] != '\0'; i++ )
-        {
-            if( pszShortModule[i] == '.' )
-                pszShortModule[i] = '\0';
-        }
+        if( pszShortModule[i] == '.' )
+            pszShortModule[i] = '\0';
+    }
 
-        SetupVersion();
+    SetupVersion();
 
-        return TRUE;
-    }
-    else
-        return FALSE;
+    return TRUE;
 }
 
 /************************************************************************/
@@ -151,16 +147,14 @@ void TigerFileBase::SetupVersion()
 int TigerFileBase::EstablishRecordLength( VSILFILE * fp )
 
 {
-    char        chCurrent;
-    int         nRecLen = 0;
-
     if( fp == NULL || VSIFSeekL( fp, 0, SEEK_SET ) != 0 )
         return -1;
 
 /* -------------------------------------------------------------------- */
 /*      Read through to the end of line.                                */
 /* -------------------------------------------------------------------- */
-    chCurrent = '\0';
+    int nRecLen = 0;
+    char chCurrent = '\0';
     while( VSIFReadL( &chCurrent, 1, 1, fp ) == 1
            && chCurrent != 10
            && chCurrent != 13 )
@@ -217,10 +211,9 @@ void TigerFileBase::EstablishFeatureCount()
 /*      (including line terminators).  Get the total file size, and     */
 /*      divide by this length to get the presumed number of records.    */
 /* -------------------------------------------------------------------- */
-    vsi_l_offset        nFileSize;
 
     VSIFSeekL( fpPrimary, 0, SEEK_END );
-    nFileSize = VSIFTellL( fpPrimary );
+    const vsi_l_offset nFileSize = VSIFTellL( fpPrimary );
 
     if( (nFileSize % (vsi_l_offset)nRecordLength) != 0 )
     {
@@ -284,19 +277,20 @@ void TigerFileBase::SetField( OGRFeature *poFeature, const char *pszField,
 /*      formatting, or leave blank if not found.                        */
 /************************************************************************/
 
-int TigerFileBase::WriteField( OGRFeature *poFeature, const char *pszField,
-                               char *pachRecord, int nStart, int nEnd,
-                               char chFormat, char chType )
+bool TigerFileBase::WriteField( OGRFeature *poFeature, const char *pszField,
+                                char *pachRecord, int nStart, int nEnd,
+                                char chFormat, char chType )
 
 {
-    int         iField = poFeature->GetFieldIndex( pszField );
-    char        szValue[512], szFormat[32];
+    const int iField = poFeature->GetFieldIndex( pszField );
+    char szValue[512];
 
     CPLAssert( nEnd - nStart + 1 < (int) sizeof(szValue)-1 );
 
-    if( iField < 0 || !poFeature->IsFieldSet( iField ) )
-        return FALSE;
+    if( iField < 0 || !poFeature->IsFieldSetAndNotNull( iField ) )
+        return false;
 
+    char szFormat[32];
     if( chType == 'N' && chFormat == 'L' )
     {
         snprintf( szFormat, sizeof(szFormat), "%%0%dd", nEnd - nStart + 1 );
@@ -323,46 +317,45 @@ int TigerFileBase::WriteField( OGRFeature *poFeature, const char *pszField,
     }
     else
     {
-        CPLAssert( FALSE );
-        return FALSE;
+        CPLAssert( false );
+        return false;
     }
 
     strncpy( pachRecord + nStart - 1, szValue, nEnd - nStart + 1 );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                             WritePoint()                             */
 /************************************************************************/
 
-int TigerFileBase::WritePoint( char *pachRecord, int nStart,
-                               double dfX, double dfY )
+bool TigerFileBase::WritePoint( char *pachRecord, int nStart,
+                                double dfX, double dfY )
 
 {
-    char        szTemp[20];
-
     if( dfX == 0.0 && dfY == 0.0 )
     {
         memcpy( pachRecord + nStart - 1, "+000000000+00000000", 19 );
     }
     else
     {
+        char szTemp[20];
         snprintf( szTemp, sizeof(szTemp), "%+10d%+9d",
                  (int) floor(dfX * 1000000 + 0.5),
                  (int) floor(dfY * 1000000 + 0.5) );
         strncpy( pachRecord + nStart - 1, szTemp, 19 );
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                            WriteRecord()                             */
 /************************************************************************/
 
-int TigerFileBase::WriteRecord( char *pachRecord, int nRecLen,
-                                const char *pszType, VSILFILE * fp )
+bool TigerFileBase::WriteRecord( char *pachRecord, int nRecLen,
+                                 const char *pszType, VSILFILE * fp )
 
 {
     if( fp == NULL )
@@ -370,16 +363,15 @@ int TigerFileBase::WriteRecord( char *pachRecord, int nRecLen,
 
     pachRecord[0] = *pszType;
 
-
     /*
      * Prior to TIGER_2002, type 5 files lacked the version.  So write
-     * the version in the record iff we're using TIGER_2002 or higher,
+     * the version in the record if we're using TIGER_2002 or higher,
      * or if this is not type "5"
      */
     if ( (poDS->GetVersion() >= TIGER_2002) ||
          (!EQUAL(pszType, "5")) )
     {
-        char    szVersion[5];
+        char szVersion[5];
         snprintf( szVersion, sizeof(szVersion), "%04d", poDS->GetVersionCode() );
         strncpy( pachRecord + 1, szVersion, 4 );
     }
@@ -387,7 +379,7 @@ int TigerFileBase::WriteRecord( char *pachRecord, int nRecLen,
     VSIFWriteL( pachRecord, nRecLen, 1, fp );
     VSIFWriteL( (void *) "\r\n", 2, 1, fp );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -396,29 +388,29 @@ int TigerFileBase::WriteRecord( char *pachRecord, int nRecLen,
 /*      Setup our access to be to the module indicated in the feature.  */
 /************************************************************************/
 
-int TigerFileBase::SetWriteModule( const char *pszExtension,
-                                   CPL_UNUSED int nRecLen,
-                                   OGRFeature *poFeature )
+bool TigerFileBase::SetWriteModule( const char *pszExtension,
+                                    CPL_UNUSED int nRecLen,
+                                    OGRFeature *poFeature )
 {
 /* -------------------------------------------------------------------- */
 /*      Work out what module we should be writing to.                   */
 /* -------------------------------------------------------------------- */
     const char *pszTargetModule = poFeature->GetFieldAsString( "MODULE" );
-    char        szFullModule[30];
 
     /* TODO/notdef: eventually more logic based on FILE and STATE/COUNTY can
        be inserted here. */
 
     if( pszTargetModule == NULL )
-        return FALSE;
+        return false;
 
+    char szFullModule[30];
     snprintf( szFullModule, sizeof(szFullModule), "%s.RT", pszTargetModule );
 
 /* -------------------------------------------------------------------- */
 /*      Is this our current module?                                     */
 /* -------------------------------------------------------------------- */
     if( pszModule != NULL && EQUAL(szFullModule,pszModule) )
-        return TRUE;
+        return true;
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup the previous file, if any.                              */
@@ -448,18 +440,16 @@ int TigerFileBase::SetWriteModule( const char *pszExtension,
 /* -------------------------------------------------------------------- */
 /*      Does this file already exist?                                   */
 /* -------------------------------------------------------------------- */
-    char *pszFilename;
-
-    pszFilename = poDS->BuildFilename( szFullModule, pszExtension );
+    char *pszFilename = poDS->BuildFilename( szFullModule, pszExtension );
 
     fpPrimary = VSIFOpenL( pszFilename, "ab" );
     CPLFree(pszFilename);
     if( fpPrimary == NULL )
-        return FALSE;
+        return false;
 
     pszModule = CPLStrdup( szFullModule );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -498,8 +488,8 @@ void TigerFileBase::SetFields(const TigerRecordInfo *psRTInfoIn,
                               OGRFeature      *poFeature,
                               char            *achRecord)
 {
-  int i;
-  for (i=0; i<psRTInfoIn->nFieldCount; ++i) {
+  for( int i = 0; i < psRTInfoIn->nFieldCount; ++i )
+  {
     if (psRTInfoIn->pasFields[i].bSet) {
       SetField( poFeature,
                 psRTInfoIn->pasFields[i].pszFieldName,
@@ -517,8 +507,8 @@ void TigerFileBase::WriteFields(const TigerRecordInfo *psRTInfoIn,
                                 OGRFeature      *poFeature,
                                 char            *szRecord)
 {
-  int i;
-  for (i=0; i<psRTInfoIn->nFieldCount; ++i) {
+  for( int i = 0; i < psRTInfoIn->nFieldCount; ++i )
+  {
     if (psRTInfoIn->pasFields[i].bWrite) {
       WriteField( poFeature,
                   psRTInfoIn->pasFields[i].pszFieldName,
@@ -531,24 +521,22 @@ void TigerFileBase::WriteFields(const TigerRecordInfo *psRTInfoIn,
   }
 }
 
-
-
 /************************************************************************/
 /*                             SetModule()                              */
 /************************************************************************/
 
-int TigerFileBase::SetModule( const char * pszModuleIn )
+bool TigerFileBase::SetModule( const char * pszModuleIn )
 
 {
-    if (m_pszFileCode == NULL)
-        return FALSE;
+    if( m_pszFileCode == NULL )
+        return false;
 
     if( !OpenFile( pszModuleIn, m_pszFileCode ) )
-        return FALSE;
+        return false;
 
     EstablishFeatureCount();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp b/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp
index cf87a5b..f53e340 100644
--- a/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigeridhistory.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigeridhistory.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerIDHistory, providing access to .RTH files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigeridhistory.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigeridhistory.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE "H"
+static const char FILE_CODE[] = "H";
 
 static const TigerFieldInfo rtH_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
diff --git a/ogr/ogrsf_frmts/tiger/tigerinfo.cpp b/ogr/ogrsf_frmts/tiger/tigerinfo.cpp
deleted file mode 100644
index 1e149b4..0000000
--- a/ogr/ogrsf_frmts/tiger/tigerinfo.cpp
+++ /dev/null
@@ -1,235 +0,0 @@
-/******************************************************************************
- * $Id: tigerinfo.cpp 33706 2016-03-11 13:33:27Z goatbar $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Simple client for viewing OGR driver data.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 1999, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include "ogrsf_frmts.h"
-#include "cpl_conv.h"
-#include "cpl_string.h"
-
-#include "ogr_tiger.h"
-
-CPL_CVSID("$Id: tigerinfo.cpp 33706 2016-03-11 13:33:27Z goatbar $");
-
-int     bReadOnly = FALSE;
-int     bVerbose = TRUE;
-
-static void Usage();
-
-static void ReportOnLayer( OGRLayer * );
-
-/************************************************************************/
-/*                                main()                                */
-/************************************************************************/
-
-int main( int nArgc, char ** papszArgv )
-
-{
-    const char  *pszDataSource = NULL;
-    char        **papszLayers = NULL;
-
-/* -------------------------------------------------------------------- */
-/*      Register format(s).                                             */
-/* -------------------------------------------------------------------- */
-    RegisterOGRTiger();
-
-/* -------------------------------------------------------------------- */
-/*      Processing command line arguments.                              */
-/* -------------------------------------------------------------------- */
-    for( int iArg = 1; iArg < nArgc; iArg++ )
-    {
-        if( EQUAL(papszArgv[iArg],"-ro") )
-            bReadOnly = TRUE;
-        else if( EQUAL(papszArgv[iArg],"-q") )
-            bVerbose = FALSE;
-        else if( papszArgv[iArg][0] == '-' )
-        {
-            Usage();
-        }
-        else if( pszDataSource == NULL )
-            pszDataSource = papszArgv[iArg];
-        else
-            papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
-    }
-
-    if( pszDataSource == NULL )
-        Usage();
-
-/* -------------------------------------------------------------------- */
-/*      Open data source.                                               */
-/* -------------------------------------------------------------------- */
-    OGRDataSource       *poDS;
-    OGRSFDriver         *poDriver;
-
-    poDS = OGRSFDriverRegistrar::Open( pszDataSource, !bReadOnly, &poDriver );
-    if( poDS == NULL && !bReadOnly )
-    {
-        poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE, &poDriver );
-        if( poDS != NULL && bVerbose )
-        {
-            printf( "Had to open data source read-only.\n" );
-            bReadOnly = TRUE;
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Report failure                                                  */
-/* -------------------------------------------------------------------- */
-    if( poDS == NULL )
-    {
-        OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
-
-        printf( "FAILURE:\n"
-                "Unable to open datasource `%s' with the following drivers.\n",
-                pszDataSource );
-
-        for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
-        {
-            printf( "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
-        }
-
-        exit( 1 );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Some information messages.                                      */
-/* -------------------------------------------------------------------- */
-    if( bVerbose )
-    {
-        printf( "INFO: Open of `%s'\n"
-                "using driver `%s' successful.\n",
-                pszDataSource, poDriver->GetName() );
-        printf("Tiger Version: %s\n",
-               TigerVersionString(((OGRTigerDataSource*)poDS)->GetVersion()));
-    }
-
-    if( bVerbose && !EQUAL(pszDataSource,poDS->GetName()) )
-    {
-        printf( "INFO: Internal data source name `%s'\n"
-                "      different from user name `%s'.\n",
-                poDS->GetName(), pszDataSource );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Process each data source layer.                                 */
-/* -------------------------------------------------------------------- */
-    for( int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
-    {
-        OGRLayer        *poLayer = poDS->GetLayer(iLayer);
-
-        if( poLayer == NULL )
-        {
-            printf( "FAILURE: Couldn't fetch advertised layer %d!\n",
-                    iLayer );
-            exit( 1 );
-        }
-
-        if( CSLCount(papszLayers) == 0 )
-        {
-            printf( "%d: %s\n",
-                    iLayer+1,
-                    poLayer->GetLayerDefn()->GetName() );
-        }
-        else if( CSLFindString( papszLayers,
-                                poLayer->GetLayerDefn()->GetName() ) != -1 )
-        {
-            ReportOnLayer( poLayer );
-        }
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Close down.                                                     */
-/* -------------------------------------------------------------------- */
-    delete poDS;
-
-#ifdef DBMALLOC
-    malloc_dump(1);
-#endif
-
-    return 0;
-}
-
-/************************************************************************/
-/*                               Usage()                                */
-/************************************************************************/
-
-static void Usage()
-
-{
-    printf( "Usage: ogrinfo [-ro] [-q] datasource_name [layer [layer ...]]\n");
-    exit( 1 );
-}
-
-/************************************************************************/
-/*                           ReportOnLayer()                            */
-/************************************************************************/
-
-static void ReportOnLayer( OGRLayer * poLayer )
-
-{
-    OGRFeatureDefn      *poDefn = poLayer->GetLayerDefn();
-
-    printf( "\n" );
-
-    printf( "Layer name: %s\n", poDefn->GetName() );
-
-    printf( "Feature Count: %d\n", poLayer->GetFeatureCount() );
-
-    if( bVerbose )
-    {
-        char    *pszWKT;
-
-        if( poLayer->GetSpatialRef() == NULL )
-            pszWKT = CPLStrdup( "(NULL)" );
-        else
-            poLayer->GetSpatialRef()->exportToWkt( &pszWKT );
-
-        printf( "Layer SRS WKT: %s\n", pszWKT );
-        CPLFree( pszWKT );
-    }
-
-    for( int iAttr = 0; iAttr < poDefn->GetFieldCount(); iAttr++ )
-    {
-        OGRFieldDefn    *poField = poDefn->GetFieldDefn( iAttr );
-
-        printf( "%s: %s (%d.%d)\n",
-                poField->GetNameRef(),
-                poField->GetFieldTypeName( poField->GetType() ),
-                poField->GetWidth(),
-                poField->GetPrecision() );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Read, and dump features.                                        */
-/* -------------------------------------------------------------------- */
-    OGRFeature  *poFeature;
-    while( (poFeature = poLayer->GetNextFeature()) != NULL )
-    {
-        poFeature->DumpReadable( stdout );
-        delete poFeature;
-    }
-}
diff --git a/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp b/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp
index 50fe037..222b041 100644
--- a/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerkeyfeatures.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerkeyfeatures.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerKeyFeatures, providing access to .RT9 files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerkeyfeatures.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerkeyfeatures.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE "9"
+static const char FILE_CODE[] = "9";
 
 static const TigerFieldInfo rt9_fields[] = {
   // fieldname    fmt  type  OFTType      beg  end  len  bDefine bSet bWrite
@@ -76,5 +75,4 @@ TigerKeyFeatures::TigerKeyFeatures( OGRTigerDataSource * poDSIn,
     /* -------------------------------------------------------------------- */
 
     AddFieldDefns( psRTInfo, poFeatureDefn );
-
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp b/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp
index 1a4e6e9..a1f9af7 100644
--- a/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerlandmarks.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerlandmarks.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerLandmarks, providing access to .RT7 files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerlandmarks.cpp 33706 2016-03-11 13:33:27Z goatbar $");
+CPL_CVSID("$Id: tigerlandmarks.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE "7"
+static const char FILE_CODE[] = "7";
 
 static const TigerFieldInfo rt7_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
diff --git a/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp b/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp
index b28c7fa..d0d4699 100644
--- a/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigeroverunder.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigeroverunder.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerOverUnder, providing access to .RTU files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigeroverunder.cpp 33706 2016-03-11 13:33:27Z goatbar $");
+CPL_CVSID("$Id: tigeroverunder.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
-#define FILE_CODE       "U"
+static const char FILE_CODE[] = "U";
 
 static const TigerFieldInfo rtU_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -54,7 +53,6 @@ static const TigerRecordInfo rtU_info =
     80
   };
 
-
 /************************************************************************/
 /*                           TigerOverUnder()                           */
 /************************************************************************/
@@ -69,7 +67,6 @@ TigerOverUnder::TigerOverUnder( OGRTigerDataSource * poDSIn,
     poFeatureDefn->SetGeomType( wkbNone );
 
     AddFieldDefns( psRTInfo, poFeatureDefn );
-
 }
 
 OGRFeature *TigerOverUnder::GetFeature( int nRecordId )
diff --git a/ogr/ogrsf_frmts/tiger/tigerpip.cpp b/ogr/ogrsf_frmts/tiger/tigerpip.cpp
index 1855a4e..86152d7 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpip.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpip.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerpip.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPIP, providing access to .RTP files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpip.cpp 33706 2016-03-11 13:33:27Z goatbar $");
+CPL_CVSID("$Id: tigerpip.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
-#define FILE_CODE "P"
+static const char FILE_CODE[] = "P";
 
 static const TigerFieldInfo rtP_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -67,7 +66,6 @@ static const TigerRecordInfo rtP_info =
     44
   };
 
-
 /************************************************************************/
 /*                              TigerPIP()                              */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp b/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
index b6705b4..57e6f09 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpoint.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerpoint.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPoint class.
@@ -30,16 +29,16 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpoint.cpp 33706 2016-03-11 13:33:27Z goatbar $");
+CPL_CVSID("$Id: tigerpoint.cpp 35609 2016-10-04 14:16:24Z goatbar $");
 
 /************************************************************************/
 /*                             TigerPoint()                             */
 /************************************************************************/
 TigerPoint::TigerPoint( int bRequireGeomIn, const TigerRecordInfo *psRTInfoIn,
-                        const char            *m_pszFileCodeIn ) : TigerFileBase(psRTInfoIn, m_pszFileCodeIn)
-{
-    this->bRequireGeom = bRequireGeomIn;
-}
+                        const char *m_pszFileCodeIn ) :
+    TigerFileBase(psRTInfoIn, m_pszFileCodeIn),
+    bRequireGeom(bRequireGeomIn)
+{}
 
 /************************************************************************/
 /*                             GetFeature()                             */
@@ -82,7 +81,7 @@ OGRFeature *TigerPoint::GetFeature( int nRecordId,
     /*      Set fields.                                                     */
     /* -------------------------------------------------------------------- */
 
-    OGRFeature  *poFeature = new OGRFeature( poFeatureDefn );
+    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
 
     SetFields( psRTInfo, poFeature, achRecord);
 
@@ -90,10 +89,8 @@ OGRFeature *TigerPoint::GetFeature( int nRecordId,
     /*      Set geometry                                                    */
     /* -------------------------------------------------------------------- */
 
-    double      dfX, dfY;
-
-    dfX = atoi(GetField(achRecord, nX0, nX1)) / 1000000.0;
-    dfY = atoi(GetField(achRecord, nY0, nY1)) / 1000000.0;
+    const double dfX = atoi(GetField(achRecord, nX0, nX1)) / 1000000.0;
+    const double dfY = atoi(GetField(achRecord, nY0, nY1)) / 1000000.0;
 
     if( dfX != 0.0 || dfY != 0.0 ) {
         poFeature->SetGeometryDirectly( new OGRPoint( dfX, dfY ) );
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp b/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp
index 4992025..a85bb9b 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolychainlink.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerpolychainlink.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolyChainLink, providing access to .RTI files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolychainlink.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerpolychainlink.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
-#define FILE_CODE "I"
+static const char FILE_CODE[] = "I";
 
 static const TigerFieldInfo rtI_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -78,7 +77,6 @@ static const TigerRecordInfo rtI_info =
     52
   };
 
-
 /************************************************************************/
 /*                         TigerPolyChainLink()                         */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
index ff32180..265cb90 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygon.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerpolygon.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolygon, providing access to .RTA files.
@@ -31,7 +30,7 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygon.cpp 33706 2016-03-11 13:33:27Z goatbar $");
+CPL_CVSID("$Id: tigerpolygon.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
 static const TigerFieldInfo rtA_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -90,7 +89,6 @@ static const TigerRecordInfo rtA_2002_info =
     210
   };
 
-
 static const TigerFieldInfo rtA_2003_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
@@ -150,7 +148,6 @@ static const TigerRecordInfo rtA_2003_info =
     210
   };
 
-
 static const TigerFieldInfo rtA_2004_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
@@ -210,7 +207,6 @@ static const TigerRecordInfo rtA_2004_info =
     210
   };
 
-
 static const TigerFieldInfo rtA_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "MODULE",     ' ', ' ', OFTString,     0,   0,   8,       1,   0,     0 },
@@ -245,7 +241,6 @@ static const TigerRecordInfo rtA_info =
     98
   };
 
-
 static const TigerFieldInfo rtS_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
   { "FILE",       'L', 'N', OFTInteger,    6,  10,   5,       0,   0,     1 },
@@ -296,7 +291,6 @@ static const TigerRecordInfo rtS_2002_info =
     168
   };
 
-
 static const TigerFieldInfo rtS_2000_Redistricting_fields[] = {
   { "FILE",       'L', 'N', OFTString,     6,  10,   5,       0,   0,     1 },
   { "STATE",      'L', 'N', OFTInteger,    6,   7,   2,       0,   0,     1 },
@@ -331,7 +325,6 @@ static const TigerFieldInfo rtS_2000_Redistricting_fields[] = {
   { "BLOCKCOL",   'R', 'N', OFTInteger,  108, 112,   5,       1,   1,     1 },
   { "BLKSUFCOL",  'L', 'A', OFTString,   113, 113,   1,       1,   1,     1 },
   { "ZCTA5",      'L', 'A', OFTString,   114, 118,   5,       1,   1,     1 }
-
 };
 
 static const TigerRecordInfo rtS_2000_Redistricting_info =
@@ -382,9 +375,11 @@ static const TigerRecordInfo rtS_info =
 /************************************************************************/
 
 TigerPolygon::TigerPolygon( OGRTigerDataSource * poDSIn,
-                            CPL_UNUSED const char * pszPrototypeModule ) :
+                            const char * /* pszPrototypeModule */ ) :
+    psRTAInfo(NULL),
+    psRTSInfo(NULL),
     fpRTS(NULL),
-    bUsingRTS(TRUE),
+    bUsingRTS(true),
     nRTSRecLen(0)
 {
     poDS = poDSIn;
@@ -392,7 +387,6 @@ TigerPolygon::TigerPolygon( OGRTigerDataSource * poDSIn,
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType( wkbNone );
 
-
     if( poDS->GetVersion() >= TIGER_2004 ) {
         psRTAInfo = &rtA_2004_info;
     } else if( poDS->GetVersion() >= TIGER_2003 ) {
@@ -414,13 +408,11 @@ TigerPolygon::TigerPolygon( OGRTigerDataSource * poDSIn,
     /* -------------------------------------------------------------------- */
     /*      Fields from type A record.                                      */
     /* -------------------------------------------------------------------- */
-
     AddFieldDefns(psRTAInfo, poFeatureDefn);
 
     /* -------------------------------------------------------------------- */
     /*      Add the RTS records if it is available.                         */
     /* -------------------------------------------------------------------- */
-
     if( bUsingRTS ) {
       AddFieldDefns(psRTSInfo, poFeatureDefn);
     }
@@ -441,11 +433,11 @@ TigerPolygon::~TigerPolygon()
 /*                             SetModule()                              */
 /************************************************************************/
 
-int TigerPolygon::SetModule( const char * pszModuleIn )
+bool TigerPolygon::SetModule( const char * pszModuleIn )
 
 {
     if( !OpenFile( pszModuleIn, "A" ) )
-        return FALSE;
+        return false;
 
     EstablishFeatureCount();
 
@@ -462,9 +454,7 @@ int TigerPolygon::SetModule( const char * pszModuleIn )
 
         if( pszModuleIn )
         {
-            char        *pszFilename;
-
-            pszFilename = poDS->BuildFilename( pszModuleIn, "S" );
+            char *pszFilename = poDS->BuildFilename( pszModuleIn, "S" );
 
             fpRTS = VSIFOpenL( pszFilename, "rb" );
 
@@ -474,7 +464,7 @@ int TigerPolygon::SetModule( const char * pszModuleIn )
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -549,7 +539,6 @@ OGRFeature *TigerPolygon::GetFeature( int nRecordId )
         }
 
         SetFields( psRTSInfo, poFeature, achRTSRec );
-
     }
 
     return poFeature;
@@ -559,13 +548,12 @@ OGRFeature *TigerPolygon::GetFeature( int nRecordId )
 /*                           SetWriteModule()                           */
 /************************************************************************/
 
-int TigerPolygon::SetWriteModule( const char *pszFileCode, int nRecLen,
-                                  OGRFeature *poFeature )
+bool TigerPolygon::SetWriteModule( const char *pszFileCode, int nRecLen,
+                                   OGRFeature *poFeature )
 
 {
-    int bSuccess;
-
-    bSuccess = TigerFileBase::SetWriteModule( pszFileCode, nRecLen, poFeature);
+    const bool bSuccess =
+        TigerFileBase::SetWriteModule( pszFileCode, nRecLen, poFeature);
     if( !bSuccess )
         return bSuccess;
 
@@ -582,9 +570,7 @@ int TigerPolygon::SetWriteModule( const char *pszFileCode, int nRecLen,
 
         if( pszModule )
         {
-            char        *pszFilename;
-
-            pszFilename = poDS->BuildFilename( pszModule, "S" );
+            char *pszFilename = poDS->BuildFilename( pszModule, "S" );
 
             fpRTS = VSIFOpenL( pszFilename, "ab" );
 
@@ -592,7 +578,7 @@ int TigerPolygon::SetWriteModule( const char *pszFileCode, int nRecLen,
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -625,6 +611,5 @@ OGRErr TigerPolygon::CreateFeature( OGRFeature *poFeature )
     WriteFields( psRTSInfo, poFeature, szRecord );
     WriteRecord( szRecord, psRTSInfo->nRecordLength, "S", fpRTS );
 
-
     return OGRERR_NONE;
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp
index ca82341..f69a52b 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygoncorrections.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerpolygoncorrections.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolygonCorrections, providing access to .RTB files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygoncorrections.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerpolygoncorrections.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE       "B"
+static const char FILE_CODE[] = "B";
 
 static const TigerFieldInfo rtB_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -69,8 +68,9 @@ static const TigerRecordInfo rtB_info =
 /*                     TigerPolygonCorrections()                        */
 /************************************************************************/
 
-TigerPolygonCorrections::TigerPolygonCorrections( OGRTigerDataSource * poDSIn,
-                                                  CPL_UNUSED const char * pszPrototypeModule ) :
+TigerPolygonCorrections::TigerPolygonCorrections(
+    OGRTigerDataSource * poDSIn,
+    const char * /* pszPrototypeModule */ ) :
     TigerFileBase(&rtB_info, FILE_CODE)
 {
     OGRFieldDefn        oField("",OFTInteger);
@@ -83,6 +83,5 @@ TigerPolygonCorrections::TigerPolygonCorrections( OGRTigerDataSource * poDSIn,
     /* -------------------------------------------------------------------- */
     /*      Fields from type B record.                                      */
     /* -------------------------------------------------------------------- */
-
     AddFieldDefns( psRTInfo, poFeatureDefn );
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp b/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp
index 8bba92b..1cf26d4 100644
--- a/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerpolygoneconomic.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerpolygoneconomic.cpp 33706 2016-03-11 13:33:27Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerPolygonEconomic, providing access to .RTE files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerpolygoneconomic.cpp 33706 2016-03-11 13:33:27Z goatbar $");
+CPL_CVSID("$Id: tigerpolygoneconomic.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE       "E"
+static const char FILE_CODE[] = "E";
 
 /* I think this was the expected RTE format, but was never deployed, leaving
    it in the code in case I am missing something.
diff --git a/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp b/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp
index d917c52..5fe83af 100644
--- a/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerspatialmetadata.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerspatialmetadata.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerSpatialMetadata, providing access to .RTM files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerspatialmetadata.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerspatialmetadata.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE "M"
+static const char FILE_CODE[] = "M";
 
 static const TigerFieldInfo rtM_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
diff --git a/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp b/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp
index 86e74cd..903fa98 100644
--- a/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigertlidrange.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigertlidrange.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerTLIDRange, providing access to .RTR files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigertlidrange.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigertlidrange.cpp 35933 2016-10-25 16:46:26Z goatbar $");
 
-#define FILE_CODE "R"
+static const char FILE_CODE[] = "R";
 
 static const TigerFieldInfo rtR_2002_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -97,5 +96,4 @@ TigerTLIDRange::TigerTLIDRange( OGRTigerDataSource * poDSIn,
     /* -------------------------------------------------------------------- */
 
     AddFieldDefns( psRTInfo, poFeatureDefn );
-
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp b/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp
index a96d055..6a2562b 100644
--- a/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerzerocellid.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerzerocellid.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerZeroCellID, providing access to .RTT files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerzerocellid.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerzerocellid.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE       "T"
+static const char FILE_CODE[] = "T";
 
 static const TigerFieldInfo rtT_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -67,5 +66,4 @@ TigerZeroCellID::TigerZeroCellID( OGRTigerDataSource * poDSIn,
 /* -------------------------------------------------------------------- */
 
     AddFieldDefns( psRTInfo, poFeatureDefn );
-
 }
diff --git a/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp b/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp
index face12a..80abdd0 100644
--- a/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerzipcodes.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerzipcodes.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerZipCodes, providing access to .RT6 files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerzipcodes.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerzipcodes.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE "6"
+static const char FILE_CODE[] = "6";
 
 static const TigerFieldInfo rt6_fields[] = {
   // fieldname    fmt  type OFTType     beg  end  len  bDefine bSet bWrite
diff --git a/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp b/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp
index c180513..538a12d 100644
--- a/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp
+++ b/ogr/ogrsf_frmts/tiger/tigerzipplus4.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: tigerzipplus4.cpp 27745 2014-09-27 16:38:57Z goatbar $
  *
  * Project:  TIGER/Line Translator
  * Purpose:  Implements TigerZipPlus4, providing access to .RTZ files.
@@ -30,9 +29,9 @@
 #include "ogr_tiger.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: tigerzipplus4.cpp 27745 2014-09-27 16:38:57Z goatbar $");
+CPL_CVSID("$Id: tigerzipplus4.cpp 35629 2016-10-06 23:39:06Z goatbar $");
 
-#define FILE_CODE       "Z"
+static const char FILE_CODE[] = "Z";
 
 static const TigerFieldInfo rtZ_fields[] = {
   // fieldname    fmt  type OFTType      beg  end  len  bDefine bSet bWrite
@@ -65,7 +64,5 @@ TigerZipPlus4::TigerZipPlus4( OGRTigerDataSource * poDSIn,
     /* -------------------------------------------------------------------- */
     /*      Fields from type Z record.                                      */
     /* -------------------------------------------------------------------- */
-
     AddFieldDefns( psRTInfo, poFeatureDefn );
-
 }
diff --git a/ogr/ogrsf_frmts/vdv/ogr_vdv.h b/ogr/ogrsf_frmts/vdv/ogr_vdv.h
index 157737b..8ca5e18 100644
--- a/ogr/ogrsf_frmts/vdv/ogr_vdv.h
+++ b/ogr/ogrsf_frmts/vdv/ogr_vdv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_vdv.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: ogr_vdv.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  VDV Translator
  * Purpose:  Implements OGRVDVDriver.
@@ -49,11 +49,11 @@ class OGRIDFDataSource : public GDALDataset
     void                Parse();
 
   public:
-                        OGRIDFDataSource(VSILFILE* fpL);
-                        ~OGRIDFDataSource();
+    explicit            OGRIDFDataSource(VSILFILE* fpL);
+                        virtual ~OGRIDFDataSource();
 
-    virtual int                 GetLayerCount();
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override;
+    virtual OGRLayer*           GetLayer( int ) override;
 };
 
 /************************************************************************/
@@ -80,19 +80,18 @@ class OGRVDVLayer: public OGRLayer
                                     bool bOwnFP,
                                     bool bRecodeFromLatin1,
                                     vsi_l_offset nStartOffset);
-                        ~OGRVDVLayer();
+                        virtual ~OGRVDVLayer();
 
-        virtual void            ResetReading();
-        virtual OGRFeature     *GetNextFeature();
-        virtual GIntBig         GetFeatureCount(int bForce);
-        virtual OGRFeatureDefn *GetLayerDefn() { return m_poFeatureDefn; }
-        virtual int             TestCapability(const char* pszCap);
+        virtual void            ResetReading() override;
+        virtual OGRFeature     *GetNextFeature() override;
+        virtual GIntBig         GetFeatureCount(int bForce) override;
+        virtual OGRFeatureDefn *GetLayerDefn() override { return m_poFeatureDefn; }
+        virtual int             TestCapability(const char* pszCap) override;
 
         void                    SetFeatureCount(GIntBig nTotalFeatureCount)
                             { m_nTotalFeatureCount = nTotalFeatureCount; }
 };
 
-
 class OGRVDV452Field
 {
     public:
@@ -156,15 +155,15 @@ class OGRVDVWriterLayer: public OGRLayer
                                           const CPLString& osVDV452Lang = "",
                                           bool bProfileStrict = false
                                           );
-                        ~OGRVDVWriterLayer();
+                        virtual ~OGRVDVWriterLayer();
 
-        virtual void            ResetReading();
-        virtual OGRFeature     *GetNextFeature();
-        virtual OGRFeatureDefn *GetLayerDefn() { return m_poFeatureDefn; }
-        virtual int             TestCapability(const char* pszCap);
-        virtual OGRErr          CreateField(OGRFieldDefn* poFieldDefn, int bApproxOK = TRUE);
-        virtual OGRErr          ICreateFeature(OGRFeature* poFeature);
-        virtual GIntBig         GetFeatureCount(int bForce = TRUE);
+        virtual void            ResetReading() override;
+        virtual OGRFeature     *GetNextFeature() override;
+        virtual OGRFeatureDefn *GetLayerDefn() override { return m_poFeatureDefn; }
+        virtual int             TestCapability(const char* pszCap) override;
+        virtual OGRErr          CreateField(OGRFieldDefn* poFieldDefn, int bApproxOK = TRUE) override;
+        virtual OGRErr          ICreateFeature(OGRFeature* poFeature) override;
+        virtual GIntBig         GetFeatureCount(int bForce = TRUE) override;
 
         void                    StopAsCurrentLayer();
 };
@@ -196,15 +195,15 @@ class OGRVDVDataSource : public GDALDataset
                                          bool bUpdate,
                                          bool bSingleFile,
                                          bool bNew);
-                        ~OGRVDVDataSource();
+                        virtual ~OGRVDVDataSource();
 
-    virtual int                 GetLayerCount();
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override;
+    virtual OGRLayer*           GetLayer( int ) override;
     virtual OGRLayer*           ICreateLayer( const char *pszLayerName,
                                       OGRSpatialReference * /*poSpatialRef*/,
                                       OGRwkbGeometryType /*eGType*/,
-                                      char ** papszOptions  );
-    virtual int                 TestCapability( const char * pszCap );
+                                      char ** papszOptions  ) override;
+    virtual int                 TestCapability( const char * pszCap ) override;
 
     void                        SetCurrentWriterLayer(OGRVDVWriterLayer* poLayer);
 
@@ -215,5 +214,4 @@ class OGRVDVDataSource : public GDALDataset
                                         char ** papszOptions );
 };
 
-
 #endif /* ndef OGR_VDV_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/vdv/ogrvdvdatasource.cpp b/ogr/ogrsf_frmts/vdv/ogrvdvdatasource.cpp
index 1ae7c8b..23b6ce8 100644
--- a/ogr/ogrsf_frmts/vdv/ogrvdvdatasource.cpp
+++ b/ogr/ogrsf_frmts/vdv/ogrvdvdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrvdvdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VDV Translator
  * Purpose:  Implements OGRVDVFDriver.
@@ -32,7 +31,7 @@
 #include "cpl_time.h"
 #include <map>
 
-CPL_CVSID("$Id: ogrvdvdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrvdvdatasource.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 #ifndef STARTS_WITH_CI
 #define STARTS_WITH(a,b)               (strncmp(a,b,strlen(b)) == 0)
@@ -126,11 +125,11 @@ static void OGRVDVParseAtrFrm(OGRFeatureDefn* poFeatureDefn,
 /*                           OGRIDFDataSource()                         */
 /************************************************************************/
 
-OGRIDFDataSource::OGRIDFDataSource(VSILFILE* fpLIn) : m_fpL(fpLIn)
-{
-    m_bHasParsed = false;
-    m_poMemDS = NULL;
-}
+OGRIDFDataSource::OGRIDFDataSource(VSILFILE* fpLIn) :
+    m_fpL(fpLIn),
+    m_bHasParsed(false),
+    m_poMemDS(NULL)
+{}
 
 /************************************************************************/
 /*                          ~OGRIDFDataSource()                         */
@@ -163,7 +162,6 @@ void OGRIDFDataSource::Parse()
     bool bRecodeFromLatin1 = false;
     int iNodeID = -1;
     int iLinkID = -1;
-    int iCount = -1;
     int iFromNode = -1;
     int iToNode = -1;
     IDFLayerType eLayerType = LAYER_OTHER;
@@ -187,7 +185,7 @@ void OGRIDFDataSource::Parse()
             osTablename = pszLine + 4;
             osAtr = "";
             osFrm = "";
-            iX = iY = iNodeID = iLinkID = iCount = iFromNode = iToNode = -1;
+            iX = iY = iNodeID = iLinkID = iFromNode = iToNode = -1;
             eLayerType = LAYER_OTHER;
         }
         else if( STARTS_WITH(pszLine, "atr;") )
@@ -234,7 +232,7 @@ void OGRIDFDataSource::Parse()
                 }
                 else if( EQUAL(osTablename, "LinkCoordinate") &&
                         (iLinkID = CSLFindString(papszAtr, "LINK_ID")) >= 0 &&
-                        (iCount = CSLFindString(papszAtr, "COUNT")) >= 0 &&
+                        CSLFindString(papszAtr, "COUNT") >= 0 &&
                         (iX = CSLFindString(papszAtr, "X")) >= 0 &&
                         (iY = CSLFindString(papszAtr, "Y")) >= 0 )
                 {
@@ -248,7 +246,7 @@ void OGRIDFDataSource::Parse()
                     poCurLayer = m_poMemDS->CreateLayer(osTablename, NULL, wkbNone, apszOptions);
                 }
 
-                if( osAtr.size() && CSLCount(papszAtr) == CSLCount(papszFrm) )
+                if( !osAtr.empty() && CSLCount(papszAtr) == CSLCount(papszFrm) )
                 {
                     /* Note: we use AddFieldDefn() directly on the layer defn */
                     /* This works with the current implementation of the MEM driver */
@@ -263,7 +261,7 @@ void OGRIDFDataSource::Parse()
             char** papszTokens = CSLTokenizeStringComplex(pszLine + 4,";",TRUE,TRUE);
             OGRFeatureDefn* poFDefn = poCurLayer->GetLayerDefn();
             OGRFeature* poFeature = new OGRFeature(poFDefn);
-            for(int i=0; papszTokens[i] != NULL && i < poFDefn->GetFieldCount();i++)
+            for(int i=0; i < poFDefn->GetFieldCount() && papszTokens[i] != NULL ;i++)
             {
                 if( papszTokens[i][0] )
                 {
@@ -282,7 +280,7 @@ void OGRIDFDataSource::Parse()
                 }
             }
 
-            if( eLayerType == LAYER_NODE )
+            if( eLayerType == LAYER_NODE && iX >= 0 && iY >= 0 && iNodeID >= 0 )
             {
                 double dfX = poFeature->GetFieldAsDouble(iX);
                 double dfY = poFeature->GetFieldAsDouble(iY);
@@ -292,7 +290,8 @@ void OGRIDFDataSource::Parse()
                 poGeom->assignSpatialReference(poFDefn->GetGeomFieldDefn(0)->GetSpatialRef());
                 poFeature->SetGeometryDirectly(poGeom);
             }
-            else if( eLayerType == LAYER_LINK )
+            else if( eLayerType == LAYER_LINK && iFromNode >= 0 &&
+                     iToNode >= 0 )
             {
                 GIntBig nFromNode = poFeature->GetFieldAsInteger64(iFromNode);
                 GIntBig nToNode = poFeature->GetFieldAsInteger64(iToNode);
@@ -309,7 +308,8 @@ void OGRIDFDataSource::Parse()
                     poFeature->SetGeometryDirectly(poLS);
                 }
             }
-            else if( eLayerType == LAYER_LINKCOORDINATE )
+            else if( eLayerType == LAYER_LINKCOORDINATE &&
+                     iX >= 0 && iY >= 0 && iLinkID >= 0 )
             {
                 double dfX = poFeature->GetFieldAsDouble(iX);
                 double dfY = poFeature->GetFieldAsDouble(iY);
@@ -345,13 +345,13 @@ void OGRIDFDataSource::Parse()
     OGRLayer* poLinkLyr = m_poMemDS->GetLayerByName("Link");
     if( poLinkLyr )
     {
-        OGRFeature* poFeat;
         iLinkID = poLinkLyr->GetLayerDefn()->GetFieldIndex("LINK_ID");
         if( iLinkID >= 0 )
         {
             poLinkLyr->ResetReading();
             OGRSpatialReference* poSRS =
                 poLinkLyr->GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef();
+            OGRFeature* poFeat = NULL;
             while( (poFeat = poLinkLyr->GetNextFeature()) != NULL )
             {
                 GIntBig nLinkID = poFeat->GetFieldAsInteger64(iLinkID);
@@ -431,8 +431,7 @@ OGRVDVDataSource::OGRVDVDataSource(const char* pszFilename,
     m_poCurrentWriterLayer(NULL),
     m_bMustWriteEof(false),
     m_bVDV452Loaded(false)
-{
-}
+{}
 
 /************************************************************************/
 /*                          ~OGRVDVDataSource()                         */
@@ -673,7 +672,7 @@ OGRVDVLayer::OGRVDVLayer(const CPLString& osTableName,
         {
             CPLString osChs(pszLine+4);
             osChs.Trim();
-            if( osChs.size() >= 2 && osChs[0] == '"' && osChs[osChs.size()-1] == '"' )
+            if( osChs.size() >= 2 && osChs[0] == '"' && osChs.back() == '"' )
                 osChs = osChs.substr(1, osChs.size()-2);
             m_bRecodeFromLatin1 = EQUAL(osChs, "ISO8859-1") ||
                                   EQUAL(osChs, "ISO_LATIN_1");
@@ -703,7 +702,7 @@ OGRVDVLayer::OGRVDVLayer(const CPLString& osTableName,
         CPLDebug("VDV", "Didn't find tbl; line");
 
     VSIFSeekL(m_fpL, nCurOffset, SEEK_SET);
-    if( osAtr.size() && osFrm.size() )
+    if( !osAtr.empty() && !osFrm.empty() )
     {
         char** papszAtr = CSLTokenizeString2(osAtr,";",
                     CSLT_ALLOWEMPTYTOKENS|CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
@@ -812,8 +811,8 @@ OGRFeature* OGRVDVLayer::GetNextFeature()
                 CSLT_ALLOWEMPTYTOKENS | CSLT_STRIPLEADSPACES| CSLT_STRIPENDSPACES);
         poFeature = new OGRFeature(m_poFeatureDefn);
         poFeature->SetFID( m_nFID ++ );
-        for(int i=0; papszTokens[i] != NULL &&
-                     i < m_poFeatureDefn->GetFieldCount();i++)
+        for(int i=0; i < m_poFeatureDefn->GetFieldCount() &&
+                     papszTokens[i] != NULL ;i++)
         {
             if( papszTokens[i][0] && !EQUAL(papszTokens[i], "NULL") )
             {
@@ -828,7 +827,7 @@ OGRFeature* OGRVDVLayer::GetNextFeature()
                 else
                     osToken = papszTokens[i];
                 // Strip trailing spaces
-                while( osToken.size() && osToken[osToken.size()-1] == ' ' )
+                while( !osToken.empty() && osToken.back() == ' ' )
                     osToken.resize(osToken.size()-1);
                 OGRFieldType eFieldType = m_poFeatureDefn->GetFieldDefn(i)->GetType();
                 if( m_bRecodeFromLatin1 && eFieldType == OFTString )
@@ -1070,6 +1069,7 @@ OGRVDVWriterLayer::OGRVDVWriterLayer( OGRVDVDataSource *poDS,
                                       const CPLString& osVDV452Lang,
                                       bool bProfileStrict):
     m_poDS(poDS),
+    m_poFeatureDefn(new OGRFeatureDefn(pszName)),
     m_bWritePossible(true),
     m_fpL(fpL),
     m_bOwnFP(bOwnFP),
@@ -1080,7 +1080,6 @@ OGRVDVWriterLayer::OGRVDVWriterLayer( OGRVDVDataSource *poDS,
     m_iLongitudeVDV452(-1),
     m_iLatitudeVDV452(-1)
 {
-    m_poFeatureDefn = new OGRFeatureDefn(pszName);
     m_poFeatureDefn->SetGeomType(wkbNone);
     m_poFeatureDefn->Reference();
     SetDescription(pszName);
@@ -1196,7 +1195,6 @@ bool OGRVDVWriterLayer::WriteSchemaIfNeeded()
                     bOK &= VSIFPrintfL(m_fpL, "char[%d]", nWidth) > 0;
                     break;
             }
-
         }
         bOK &= VSIFPrintfL(m_fpL, "\n") > 0;
 
@@ -1230,7 +1228,7 @@ OGRErr OGRVDVWriterLayer::ICreateFeature(OGRFeature* poFeature)
     {
         if( i > 0)
             bOK &= VSIFPrintfL(m_fpL, "; ") > 0;
-        if( poFeature->IsFieldSet(i) )
+        if( poFeature->IsFieldSetAndNotNull(i) )
         {
             const OGRFieldType eType = m_poFeatureDefn->GetFieldDefn(i)->GetType();
             if( eType == OFTInteger || eType == OFTInteger64 )
@@ -1398,7 +1396,7 @@ static bool OGRVDVWriteHeader(VSILFILE* fpL, char** papszOptions)
 {
     bool bRet = true;
     const bool bStandardHeader =
-            CSLFetchBoolean(papszOptions, "STANDARD_HEADER", TRUE) != FALSE;
+            CPLFetchBool(papszOptions, "STANDARD_HEADER", true);
 
     struct tm tm;
     CPLUnixTimeToYMDHMS(time(NULL), &tm);
@@ -1433,7 +1431,6 @@ static bool OGRVDVWriteHeader(VSILFILE* fpL, char** papszOptions)
         bRet &= VSIFPrintfL(fpL, "fft; \"%s\"\n", OGRVDVEscapeString(pszFft).c_str()) > 0;
     }
 
-
     for(char** papszIter = papszOptions;
                papszIter != NULL && *papszIter != NULL;
                papszIter++)
@@ -1533,9 +1530,9 @@ OGRVDVDataSource::ICreateLayer( const char *pszLayerName,
         OGRVDVLoadVDV452Tables(m_oVDV452Tables);
     }
     const bool bProfileStrict =
-        CSLFetchBoolean(papszOptions, "PROFILE_STRICT", FALSE) != FALSE;
+        CPLFetchBool(papszOptions, "PROFILE_STRICT", false);
     const bool bCreateAllFields =
-        CSLFetchBoolean(papszOptions, "CREATE_ALL_FIELDS", TRUE) != FALSE;
+        CPLFetchBool(papszOptions, "CREATE_ALL_FIELDS", true);
 
     CPLString osUpperLayerName(pszLayerName);
     osUpperLayerName.toupper();
@@ -1597,7 +1594,7 @@ OGRVDVDataSource::ICreateLayer( const char *pszLayerName,
             return NULL;
     }
 
-    VSILFILE* fpL;
+    VSILFILE* fpL = NULL;
     if( m_bSingleFile )
     {
         fpL = m_fpL;
@@ -1611,7 +1608,7 @@ OGRVDVDataSource::ICreateLayer( const char *pszLayerName,
             while( nOffset > 0 )
             {
                 VSIFSeekL(fpL, nOffset - 1, SEEK_SET);
-                char ch;
+                char ch = '\0';
                 VSIFReadL(&ch, 1, 1, fpL);
                 if( bTerminatingEOL )
                 {
@@ -1639,7 +1636,7 @@ OGRVDVDataSource::ICreateLayer( const char *pszLayerName,
             {
                 // Otherwise make sure the file ends with an eol character
                 VSIFSeekL(fpL, nFileSize - 1, SEEK_SET);
-                char ch;
+                char ch = '\0';
                 VSIFReadL(&ch, 1, 1, fpL);
                 VSIFSeekL(fpL, nFileSize, SEEK_SET);
                 if( !(ch == '\r' || ch == '\n') )
@@ -1776,7 +1773,7 @@ GDALDataset* OGRVDVDataSource::Create( const char * pszName,
         return NULL;
     }
 
-    bool bSingleFile = CPL_TO_BOOL(CSLFetchBoolean(papszOptions, "SINGLE_FILE", TRUE));
+    const bool bSingleFile = CPLFetchBool(papszOptions, "SINGLE_FILE", true);
     if( !bSingleFile )
     {
         if( VSIMkdir( pszName, 0755 ) != 0 )
diff --git a/ogr/ogrsf_frmts/vfk/drv_vfk.html b/ogr/ogrsf_frmts/vfk/drv_vfk.html
index bf00491..19c3b17 100644
--- a/ogr/ogrsf_frmts/vfk/drv_vfk.html
+++ b/ogr/ogrsf_frmts/vfk/drv_vfk.html
@@ -8,53 +8,54 @@
 <h1>VFK - Czech Cadastral Exchange Data Format</h1>
 
 This driver reads VFK files, i.e. data in the <em>Czech cadastral
-exchange data format</em>. The VFK file is recognized as an OGR
-datasource with zero or more OGR layers.
+exchange data format</em>. The VFK file is recognized as an datasource
+with zero or more layers.
 
 <p>
-Note: starting with OGR 1.10, the driver is compiled only if GDAL
+Note: starting with GDAL 1.10, the driver is compiled only if GDAL
 is <em>built with SQLite support</em>.
 
 <p>
 Points are represented as wkbPoints, lines and boundaries as
-wkbLineStrings and areas as wkbPolygons. wkbMulti* primitives are not
+wkbLineStrings and areas as wkbPolygons. wkbMulti* features are not
 used. Feature types cannot be mixed in one layer.
 
 <h3>Configuration</h3>
 
-Starting with OGR 1.9, the driver reads and writes VFK data from/to
-internal SQLite database. Default name for the database is
-"input_vfk_file.db". Since OGR 1.10, you can define an
-alternative DB name with <b>OGR_VFK_DB_NAME</b> configuration
-option. If <b>OGR_VFK_DB_OVERWRITE=YES</b> configuration option is
-given, than the driver overwrites existing SQLite database and reads
-data from original input VFK file into newly created DB. Since OGR
-1.11, if <b>OGR_VFK_DB_DELETE=YES</b> configuration option is given
-than the driver deletes the internal SQLite database when closing the
-data source.
+Starting with GDAL 1.9, the driver uses SQLite as a backend database
+when reading VFK data. By default, SQLite database is created in a
+directory of input VFK file (with file extension '.db'). Since GDAL
+1.10, the user can define DB name with <b>OGR_VFK_DB_NAME</b>
+configuration option. If <b>OGR_VFK_DB_OVERWRITE=YES</b> configuration
+option is given, the driver overwrites existing SQLite database and
+stores data read from input VFK file into newly created DB. Since GDAL
+1.11, if <b>OGR_VFK_DB_DELETE=YES</b> configuration option is given,
+the driver deletes backend SQLite database when closing the
+datasource.
 
 <p>
-Starting with OGR 1.10, resolved geometries are stored also in SQLite
-database. It means that geometries are resolved only once when
-building SQLite database from original VFK data. Geometries are stored
-in WKB format. Note that GDAL doesn't need to be built with SpatiaLite
-support. Geometries are not stored in DB
+Starting with GDAL 1.10, resolved geometries are stored also in
+backend SQLite database. It means that geometries are resolved only
+once when building SQLite database from VFK data. Geometries are
+stored in WKB format. Note that GDAL doesn't need to be built with
+SpatiaLite support. Geometries are not stored in DB
 when <b>OGR_VFK_DB_SPATIAL=NO</b> configuration option is given. In
-this case the geometries are resolved from DB.
+this case geometries are resolved when reading data from DB on the
+fly.
 
 <h3>Internal working and performance tweaking</h3>
 
-Since OGR 1.9, the driver uses an internal SQLite database to resolve
-geometries. By default, this file will be written in the same
-directory as input VFK file. If SQLite database already exists then
-the driver reads VFK features directly from the database (and not from
-original VFK file).
+If backend SQLite database already exists then the driver reads
+features directly from the database and not from input VFK file given
+as an input datasource. This causes significant performance gain when
+reading features by the driver.
 
 <p>
-Since OGR 1.11, the driver reads by default all data blocks. When
-configuration option <b>OGR_VFK_DB_READ_ALL_BLOCKS=NO</b> is given
-than the driver reads only data blocks which are requested by the
-user.
+Since GDAL 1.11, the driver reads by default all data blocks from VFK
+file when building backend SQLite database. When configuration
+option <b>OGR_VFK_DB_READ_ALL_BLOCKS=NO</b> is given, the driver reads
+only data blocks which are requested by the user. This can be useful
+when the user want to process only part of VFK data.
 
 <h2>Datasource name</h2>
 
@@ -64,6 +65,12 @@ Datasource name is a full path to the VFK file.
 System API, which include "regular" files, as well as files in the
 /vsizip/, /vsigzip/, and /vsicurl/ read-only domains.
 
+<p>
+Since GDAL 2.2 also a full path to the backend SQLite database can be
+used as an datasource. By default, such datasource is read by SQLite
+driver. If configuration option <b>OGR_VFK_DB_READ=YES</b> is given,
+such datasource is open by VFK driver instead.
+  
 <h2>Layer names</h2>
 
 VFK data blocks are used as layer names.
@@ -72,7 +79,7 @@ VFK data blocks are used as layer names.
 
 <h3>Attribute filter</h3>
 
-OGR internal SQL engine is used to evaluate the expression. Evaluation
+An internal SQL engine is used to evaluate the expression. Evaluation
 is done once when the attribute filter is set.
 
 <h3>Spatial filter</h3>
diff --git a/ogr/ogrsf_frmts/vfk/ogr_vfk.h b/ogr/ogrsf_frmts/vfk/ogr_vfk.h
index 91b6cd3..6789226 100644
--- a/ogr/ogrsf_frmts/vfk/ogr_vfk.h
+++ b/ogr/ogrsf_frmts/vfk/ogr_vfk.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_vfk.h 32177 2015-12-14 07:25:30Z goatbar $
+ * $Id: ogr_vfk.h 37757 2017-03-18 14:03:33Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/VFK driver.
@@ -53,9 +53,6 @@ private:
     /* feature definition */
     OGRFeatureDefn      *poFeatureDefn;
 
-    /* OGR data source */
-    OGRVFKDataSource    *poDS;
-
     /* VFK data block */
     IVFKDataBlock       *poDataBlock;
 
@@ -71,16 +68,16 @@ public:
                 OGRwkbGeometryType, OGRVFKDataSource *);
     ~OGRVFKLayer();
 
-    OGRFeature          *GetNextFeature();
-    OGRFeature          *GetFeature(GIntBig);
+    OGRFeature          *GetNextFeature() override;
+    OGRFeature          *GetFeature(GIntBig) override;
 
-    OGRFeatureDefn      *GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn      *GetLayerDefn() override { return poFeatureDefn; }
 
-    void                 ResetReading();
+    void                 ResetReading() override;
 
-    int                  TestCapability(const char *);
+    int                  TestCapability(const char *) override;
 
-    GIntBig              GetFeatureCount(int = TRUE);
+    GIntBig              GetFeatureCount(int = TRUE) override;
 };
 
 /************************************************************************/
@@ -105,14 +102,14 @@ public:
     OGRVFKDataSource();
     ~OGRVFKDataSource();
 
-    int            Open(const char *, int);
+    int            Open(GDALOpenInfo* poOpenInfo);
 
-    const char    *GetName() { return pszName; }
+    const char    *GetName() override { return pszName; }
 
-    int            GetLayerCount() { return nLayers; }
-    OGRLayer      *GetLayer(int);
+    int            GetLayerCount() override { return nLayers; }
+    OGRLayer      *GetLayer(int) override;
 
-    int            TestCapability(const char *);
+    int            TestCapability(const char *) override;
 
     IVFKReader    *GetReader() const { return poReader; }
 };
diff --git a/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp b/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
index c05b6ec..799aff9 100644
--- a/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
+++ b/ogr/ogrsf_frmts/vfk/ogrvfkdatasource.cpp
@@ -1,12 +1,11 @@
 /******************************************************************************
- * $Id: ogrvfkdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVFKDatasource class.
  * Author:   Martin Landa, landa.martin gmail.com
  *
  ******************************************************************************
- * Copyright (c) 2009-2010, 2013 Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2009-2010, 2013-2016 Martin Landa <landa.martin gmail.com>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -33,20 +32,17 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrvfkdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrvfkdatasource.cpp 37757 2017-03-18 14:03:33Z rouault $");
 
 /*!
   \brief OGRVFKDataSource constructor
 */
-OGRVFKDataSource::OGRVFKDataSource()
-{
-    pszName    = NULL;
-
-    poReader   = NULL;
-
-    papoLayers = NULL;
-    nLayers    = 0;
-}
+OGRVFKDataSource::OGRVFKDataSource() :
+    papoLayers(NULL),
+    nLayers(0),
+    pszName(NULL),
+    poReader(NULL)
+{}
 
 /*!
   \brief OGRVFKDataSource destructor
@@ -55,10 +51,10 @@ OGRVFKDataSource::~OGRVFKDataSource()
 {
     CPLFree(pszName);
 
-    if (poReader)
+    if( poReader )
         delete poReader;
 
-    for(int i = 0; i < nLayers; i++)
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
 
     CPLFree(papoLayers);
@@ -67,56 +63,23 @@ OGRVFKDataSource::~OGRVFKDataSource()
 /*!
   \brief Open VFK datasource
 
-  \param pszNewName datasource name
-  \param bTestOpen True to test if datasource is possible to open
+  \param poOpenInfo open info
 
   \return TRUE on success or FALSE on failure
 */
-int OGRVFKDataSource::Open(const char *pszNewName, int bTestOpen)
+int OGRVFKDataSource::Open(GDALOpenInfo* poOpenInfo)
 {
-    FILE * fp;
-    char   szHeader[1000];
-
-    /* open the source file */
-    fp = VSIFOpen(pszNewName, "r");
-    if (fp == NULL) {
-        if (!bTestOpen)
-            CPLError(CE_Failure, CPLE_OpenFailed,
-                     "Failed to open VFK file `%s'",
-                     pszNewName);
-
-        return FALSE;
-    }
-
-   /* If we aren't sure it is VFK, load a header chunk and check
-      for signs it is VFK */
-    if (bTestOpen) {
-        size_t nRead = VSIFRead(szHeader, 1, sizeof(szHeader), fp);
-        if (nRead <= 0) {
-            VSIFClose(fp);
-            return FALSE;
-        }
-        szHeader[MIN(nRead, sizeof(szHeader))-1] = '\0';
+    pszName = CPLStrdup(poOpenInfo->pszFilename);
 
-        // TODO: improve check
-        if (!STARTS_WITH(szHeader, "&H")) {
-            VSIFClose(fp);
-            return FALSE;
-        }
-    }
-
-    /* We assume now that it is VFK. Close and instantiate a
-       VFKReader on it. */
-    VSIFClose(fp);
-
-    pszName = CPLStrdup(pszNewName);
-
-    poReader = CreateVFKReader(pszNewName);
-    if (poReader == NULL) {
+    /* create VFK reader */
+    poReader = CreateVFKReader(poOpenInfo->pszFilename);
+    if (poReader == NULL || !poReader->IsValid()) {
+        /*
         CPLError(CE_Failure, CPLE_AppDefined,
                  "File %s appears to be VFK but the VFK reader can't"
                  "be instantiated",
-                 pszNewName);
+                     pszFileName);
+        */
         return FALSE;
     }
 
@@ -126,15 +89,22 @@ int OGRVFKDataSource::Open(const char *pszNewName, int bTestOpen)
     /* get list of layers */
     papoLayers = (OGRVFKLayer **) CPLCalloc(sizeof(OGRVFKLayer *), poReader->GetDataBlockCount());
 
+    /* create layers from VFK blocks */
     for (int iLayer = 0; iLayer < poReader->GetDataBlockCount(); iLayer++) {
         papoLayers[iLayer] = CreateLayerFromBlock(poReader->GetDataBlock(iLayer));
         nLayers++;
     }
 
-    /* read data records if required */
-    if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_READ_ALL_BLOCKS", "YES")))
+    if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_READ_ALL_BLOCKS", "YES"))) {
+        /* read data records if requested */
         poReader->ReadDataRecords();
 
+        for (int iLayer = 0; iLayer < poReader->GetDataBlockCount(); iLayer++) {
+            /* load geometry */
+            poReader->GetDataBlock(iLayer)->LoadGeometry();
+        }
+    }
+
     return TRUE;
 }
 
@@ -179,13 +149,10 @@ int OGRVFKDataSource::TestCapability(const char * pszCap)
 */
 OGRVFKLayer *OGRVFKDataSource::CreateLayerFromBlock(const IVFKDataBlock *poDataBlock)
 {
-    OGRVFKLayer *poLayer;
-
-    poLayer = NULL;
-
     /* create an empty layer */
-    poLayer = new OGRVFKLayer(poDataBlock->GetName(), NULL,
-                              poDataBlock->GetGeometryType(), this);
+    OGRVFKLayer *poLayer =
+        new OGRVFKLayer(poDataBlock->GetName(), NULL,
+                        poDataBlock->GetGeometryType(), this);
 
     /* define attributes (properties) */
     for (int iField = 0; iField < poDataBlock->GetPropertyCount(); iField++) {
diff --git a/ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp b/ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp
index 145ba51..393f96e 100644
--- a/ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp
+++ b/ogr/ogrsf_frmts/vfk/ogrvfkdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrvfkdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVFKDriver class.
@@ -33,13 +32,31 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrvfkdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrvfkdriver.cpp 37757 2017-03-18 14:03:33Z rouault $");
 
 static int OGRVFKDriverIdentify(GDALOpenInfo* poOpenInfo)
 {
-    return ( poOpenInfo->fpL != NULL &&
-             poOpenInfo->nHeaderBytes >= 2 &&
-             STARTS_WITH((const char*)poOpenInfo->pabyHeader, "&H") );
+    if( poOpenInfo->fpL == NULL )
+        return FALSE;
+
+    if( poOpenInfo->nHeaderBytes >= 2 &&
+        STARTS_WITH((const char*)poOpenInfo->pabyHeader, "&H") )
+        return TRUE;
+
+    /* valid datasource can be also SQLite DB previously created by
+       VFK driver, the real check is done by VFKReaderSQLite */
+    if ( poOpenInfo->nHeaderBytes >= 100 &&
+         STARTS_WITH((const char*)poOpenInfo->pabyHeader, "SQLite format 3") )
+    {
+        VSIStatBuf sStat;
+        if (CPLStat(poOpenInfo->pszFilename, &sStat) == 0 &&
+            VSI_ISREG(sStat.st_mode))
+        {
+            return GDAL_IDENTIFY_UNKNOWN;
+        }
+    }
+
+    return FALSE;
 }
 
 /*
@@ -48,15 +65,15 @@ static int OGRVFKDriverIdentify(GDALOpenInfo* poOpenInfo)
 */
 static GDALDataset *OGRVFKDriverOpen(GDALOpenInfo* poOpenInfo)
 {
-    OGRVFKDataSource *poDS;
-
     if( poOpenInfo->eAccess == GA_Update ||
         !OGRVFKDriverIdentify(poOpenInfo) )
         return NULL;
 
-    poDS = new OGRVFKDataSource();
+    OGRVFKDataSource *poDS = new OGRVFKDataSource();
 
-    if(!poDS->Open(poOpenInfo->pszFilename, TRUE) || poDS->GetLayerCount() == 0) {
+    if( !poDS->Open(poOpenInfo) ||
+        poDS->GetLayerCount() == 0 )
+    {
         delete poDS;
         return NULL;
     }
@@ -64,7 +81,6 @@ static GDALDataset *OGRVFKDriverOpen(GDALOpenInfo* poOpenInfo)
         return poDS;
 }
 
-
 /*!
   \brief Register VFK driver
 */
diff --git a/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp b/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp
index fdc6e8f..74ae3ea 100644
--- a/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp
+++ b/ogr/ogrsf_frmts/vfk/ogrvfklayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrvfklayer.cpp 32177 2015-12-14 07:25:30Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVFKLayer class.
@@ -33,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrvfklayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
+CPL_CVSID("$Id: ogrvfklayer.cpp 35466 2016-09-16 05:03:52Z goatbar $");
 
 /*!
   \brief OGRVFKLayer constructor
@@ -43,36 +42,29 @@ CPL_CVSID("$Id: ogrvfklayer.cpp 32177 2015-12-14 07:25:30Z goatbar $");
   \param eReqType WKB geometry type
   \param poDSIn  data source where to register OGR layer
 */
-OGRVFKLayer::OGRVFKLayer(const char *pszName,
-                         OGRSpatialReference *poSRSIn,
-                         OGRwkbGeometryType eReqType,
-                         OGRVFKDataSource *poDSIn) :
-    poDS(poDSIn),
+OGRVFKLayer::OGRVFKLayer( const char *pszName,
+                          OGRSpatialReference *poSRSIn,
+                          OGRwkbGeometryType eReqType,
+                          OGRVFKDataSource *poDSIn ) :
+    poSRS(poSRSIn == NULL ? new OGRSpatialReference() : poSRSIn->Clone()),
+    poFeatureDefn(new OGRFeatureDefn(pszName)),
+    poDataBlock(poDSIn->GetReader()->GetDataBlock(pszName)),
     m_iNextFeature(0)
 {
-    /* set spatial reference */
     if( poSRSIn == NULL ) {
-        /* default is S-JTSK (EPSG: 5514) */
-        poSRS = new OGRSpatialReference();
-        if (poSRS->importFromEPSG(5514) != OGRERR_NONE) {
+        // Default is S-JTSK (EPSG: 5514).
+        if( poSRS->importFromEPSG(5514) != OGRERR_NONE )
+        {
             delete poSRS;
             poSRS = NULL;
         }
     }
-    else {
-        poSRS = poSRSIn->Clone();
-    }
 
-    /* feature definition */
-    poFeatureDefn = new OGRFeatureDefn(pszName);
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
 
     poFeatureDefn->Reference();
     poFeatureDefn->SetGeomType(eReqType);
-
-    /* data block reference */
-    poDataBlock = poDS->GetReader()->GetDataBlock(pszName);
 }
 
 /*!
@@ -80,10 +72,10 @@ OGRVFKLayer::OGRVFKLayer(const char *pszName,
 */
 OGRVFKLayer::~OGRVFKLayer()
 {
-    if(poFeatureDefn)
+    if( poFeatureDefn )
         poFeatureDefn->Release();
 
-    if(poSRS)
+    if( poSRS )
         poSRS->Release();
 }
 
@@ -135,11 +127,10 @@ OGRGeometry *OGRVFKLayer::CreateGeometry(IVFKFeature * poVfkFeature)
 */
 GIntBig OGRVFKLayer::GetFeatureCount(CPL_UNUSED int bForce)
 {
-    int nfeatures;
-
     /* note that 'nfeatures' is 0 when data are not read from DB */
-    nfeatures = (int)poDataBlock->GetFeatureCount();
-    if (m_poFilterGeom || m_poAttrQuery || nfeatures < 1) {
+    int nfeatures = (int)poDataBlock->GetFeatureCount();
+    if( m_poFilterGeom || m_poAttrQuery || nfeatures < 1 )
+    {
         /* force real feature count */
         nfeatures = (int)OGRLayer::GetFeatureCount();
     }
@@ -184,9 +175,7 @@ OGRFeature *OGRVFKLayer::GetNextFeature()
 */
 OGRFeature *OGRVFKLayer::GetFeature(GIntBig nFID)
 {
-    IVFKFeature *poVFKFeature;
-
-    poVFKFeature = poDataBlock->GetFeature(nFID);
+    IVFKFeature *poVFKFeature = poDataBlock->GetFeature(nFID);
 
     if (!poVFKFeature)
         return NULL;
@@ -204,14 +193,12 @@ OGRFeature *OGRVFKLayer::GetFeature(GIntBig nFID)
 */
 OGRFeature *OGRVFKLayer::GetFeature(IVFKFeature *poVFKFeature)
 {
-    OGRGeometry *poGeom;
-
     /* skip feature with unknown geometry type */
     if (poVFKFeature->GetGeometryType() == wkbUnknown)
         return NULL;
 
     /* get features geometry */
-    poGeom = CreateGeometry(poVFKFeature);
+    OGRGeometry *poGeom = CreateGeometry(poVFKFeature);
     if (poGeom != NULL)
         poGeom->assignSpatialReference(poSRS);
 
diff --git a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
index d2aa7ae..8e4bd80 100644
--- a/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkdatablock.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vfkdatablock.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Data block definition
  * Purpose:  Implements VFKDataBlock class.
@@ -38,28 +37,28 @@
 #include "cpl_conv.h"
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: vfkdatablock.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
 /*!
   \brief VFK Data Block constructor
 
   \param pszName data block name
 */
-IVFKDataBlock::IVFKDataBlock(const char *pszName, const IVFKReader *poReader) :
+IVFKDataBlock::IVFKDataBlock( const char *pszName, const IVFKReader *poReader ) :
+    m_papoFeature(NULL),
     m_nPropertyCount(0),
     m_papoProperty(NULL),
-    m_bGeometry(false),   // geometry is not loaded by default
+    m_pszName(CPLStrdup(pszName)),
+    m_bGeometry(false),   // Geometry is not loaded by default.
     m_nGeometryType(wkbUnknown),
-    m_bGeometryPerBlock(true),    // load geometry per block/feature
-    m_nFeatureCount(-1),  // Load data on first request
+    m_bGeometryPerBlock(true),    // Load geometry per block/feature.
+    m_nFeatureCount(-1),  // Load data on first request.
     m_iNextFeature(-1),
     m_poReader(const_cast<IVFKReader *>(poReader))
 {
-    m_pszName        = CPLStrdup(pszName);
-
-    m_papoFeature    = NULL;
-
-    m_nRecordCount[RecordValid]      = 0L;  /* number of valid records */
-    m_nRecordCount[RecordSkipped]    = 0L;  /* number of skipped (invalid) records */
-    m_nRecordCount[RecordDuplicated] = 0L;  /* number of duplicated records */
+    m_nRecordCount[RecordValid] = 0L;  // Number of valid records.
+    m_nRecordCount[RecordSkipped] = 0L;  // Number of skipped (invalid) records.
+    m_nRecordCount[RecordDuplicated] = 0L;  // Number of duplicated records.
 }
 
 /*!
@@ -69,14 +68,16 @@ IVFKDataBlock::~IVFKDataBlock()
 {
     CPLFree(m_pszName);
 
-    for (int i = 0; i < m_nPropertyCount; i++) {
-        if (m_papoProperty[i])
+    for( int i = 0; i < m_nPropertyCount; i++ )
+    {
+        if( m_papoProperty[i] )
             delete m_papoProperty[i];
     }
     CPLFree(m_papoProperty);
 
-    for (int i = 0; i < m_nFeatureCount; i++) {
-        if (m_papoFeature[i])
+    for( int i = 0; i < m_nFeatureCount; i++ )
+    {
+        if( m_papoFeature[i] )
             delete m_papoFeature[i];
     }
     CPLFree(m_papoFeature);
@@ -104,7 +105,7 @@ VFKPropertyDefn *IVFKDataBlock::GetProperty(int iIndex) const
 */
 void IVFKDataBlock::SetProperties(const char *poLine)
 {
-    const char *poChar;
+    const char *poChar = NULL;
 
     /* skip data block name */
     for (poChar = poLine; *poChar != '0' && *poChar != ';'; poChar++)
@@ -183,13 +184,17 @@ int IVFKDataBlock::AddProperty(const char *pszName, const char *pszType)
 /*!
   \brief Get number of features for given data block
 
+  \param bForce true to force reading VFK data blocks if needed
+
   \return number of features
 */
-GIntBig IVFKDataBlock::GetFeatureCount()
+GIntBig IVFKDataBlock::GetFeatureCount( bool bForce )
 {
-    if (m_nFeatureCount < 0) {
+    if( bForce && m_nFeatureCount == -1 )
+    {
         m_poReader->ReadDataRecords(this); /* read VFK data records */
-        if (m_bGeometryPerBlock && !m_bGeometry) {
+        if( m_bGeometryPerBlock && !m_bGeometry )
+        {
             LoadGeometry(); /* get real number of features */
         }
     }
@@ -422,11 +427,11 @@ IVFKFeature *IVFKDataBlock::GetFeature(GIntBig nFID)
 */
 int IVFKDataBlock::LoadGeometry()
 {
-    if (m_bGeometry)
+    if( m_bGeometry )
         return 0;
 
+    m_bGeometry = true;
     int nInvalid = 0;
-    m_bGeometry = TRUE;
 
 #ifdef DEBUG_TIMING
     const clock_t start       = clock();
@@ -483,18 +488,19 @@ int IVFKDataBlock::LoadGeometry()
   \param[in,out] papoRing list of rings
   \param poLine pointer to linestring to be added to a ring
   \param bNewRing  create new ring
-  \param bBackword allow backward direction
+  \param bBackward allow backward direction
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool IVFKDataBlock::AppendLineToRing(PointListArray *papoRing, const OGRLineString *poLine,
                                      bool bNewRing, bool bBackward)
 {
-    OGRPoint  pt;
     PointList poList;
 
     /* OGRLineString -> PointList */
-    for (int i = 0; i < poLine->getNumPoints(); i++) {
+    for( int i = 0; i < poLine->getNumPoints(); i++ )
+    {
+        OGRPoint pt;
         poLine->getPoint(i, &pt);
         poList.push_back(pt);
     }
@@ -502,7 +508,7 @@ bool IVFKDataBlock::AppendLineToRing(PointListArray *papoRing, const OGRLineStri
     /* create new ring */
     if (bNewRing) {
         papoRing->push_back(new PointList(poList));
-        return TRUE;
+        return true;
     }
 
     OGRPoint *poFirstNew = &(poList.front());
@@ -516,34 +522,34 @@ bool IVFKDataBlock::AppendLineToRing(PointListArray *papoRing, const OGRLineStri
         poFirst = &(ring->front());
         poLast  = &(ring->back());
         if (!poFirst || !poLast || poLine->getNumPoints() < 2)
-            return FALSE;
+            return false;
 
         if (poFirstNew->Equals(poLast)) {
             /* forward, skip first point */
             ring->insert(ring->end(), poList.begin()+1, poList.end());
-            return TRUE;
+            return true;
         }
 
         if (bBackward && poFirstNew->Equals(poFirst)) {
             /* backward, skip last point */
             ring->insert(ring->begin(), poList.rbegin(), poList.rend()-1);
-            return TRUE;
+            return true;
         }
 
         if (poLastNew->Equals(poLast)) {
             /* backward, skip first point */
             ring->insert(ring->end(), poList.rbegin()+1, poList.rend());
-            return TRUE;
+            return true;
         }
 
         if (bBackward && poLastNew->Equals(poFirst)) {
             /* forward, skip last point */
             ring->insert(ring->begin(), poList.begin(), poList.end()-1);
-            return TRUE;
+            return true;
         }
     }
 
-    return FALSE;
+    return false;
 }
 
 /*!
@@ -614,24 +620,27 @@ void IVFKDataBlock::SetIncRecordCount(RecordType iRec)
 */
 VFKFeature *VFKDataBlock::GetFeature(int idx, GUIntBig value, VFKFeatureList *poList)
 {
-    GUIntBig    iPropertyValue;
-    VFKFeature *poVfkFeature;
-
     if (poList) {
-        for (VFKFeatureList::iterator i = poList->begin(), e = poList->end();
-             i != e; ++i) {
-            poVfkFeature = *i;
-            iPropertyValue = strtoul(poVfkFeature->GetProperty(idx)->GetValueS(), NULL, 0);
+        for( VFKFeatureList::iterator i = poList->begin(), e = poList->end();
+             i != e;
+             ++i )
+        {
+            VFKFeature *poVfkFeature = *i;
+            const GUIntBig iPropertyValue =
+                strtoul(poVfkFeature->GetProperty(idx)->GetValueS(), NULL, 0);
             if (iPropertyValue == value) {
                 poList->erase(i); /* ??? */
                 return poVfkFeature;
             }
         }
     }
-    else {
-        for (int i = 0; i < m_nFeatureCount; i++) {
-            poVfkFeature = (VFKFeature *) GetFeatureByIndex(i);
-            iPropertyValue = strtoul(poVfkFeature->GetProperty(idx)->GetValueS(), NULL, 0);
+    else
+    {
+        for( int i = 0; i < m_nFeatureCount; i++ )
+        {
+            VFKFeature *poVfkFeature = (VFKFeature *) GetFeatureByIndex(i);
+            const GUIntBig iPropertyValue =
+                strtoul(poVfkFeature->GetProperty(idx)->GetValueS(), NULL, 0);
             if (iPropertyValue == value) {
                 m_iNextFeature = i + 1;
                 return poVfkFeature;
@@ -652,13 +661,12 @@ VFKFeature *VFKDataBlock::GetFeature(int idx, GUIntBig value, VFKFeatureList *po
 */
 VFKFeatureList VFKDataBlock::GetFeatures(int idx, GUIntBig value)
 {
-    GUIntBig    iPropertyValue;
-    VFKFeature *poVfkFeature;
     std::vector<VFKFeature *> poResult;
 
     for (int i = 0; i < m_nFeatureCount; i++) {
-        poVfkFeature = (VFKFeature *) GetFeatureByIndex(i);
-        iPropertyValue = strtoul(poVfkFeature->GetProperty(idx)->GetValueS(), NULL, 0);
+        VFKFeature *poVfkFeature = (VFKFeature *) GetFeatureByIndex(i);
+        const GUIntBig iPropertyValue =
+            strtoul(poVfkFeature->GetProperty(idx)->GetValueS(), NULL, 0);
         if (iPropertyValue == value) {
             poResult.push_back(poVfkFeature);
         }
@@ -678,20 +686,22 @@ VFKFeatureList VFKDataBlock::GetFeatures(int idx, GUIntBig value)
 */
 VFKFeatureList VFKDataBlock::GetFeatures(int idx1, int idx2, GUIntBig value)
 {
-    GUIntBig    iPropertyValue1, iPropertyValue2;
-    VFKFeature *poVfkFeature;
     std::vector<VFKFeature *> poResult;
 
-    for (int i = 0; i < m_nFeatureCount; i++) {
-        poVfkFeature = (VFKFeature *) GetFeatureByIndex(i);
-        iPropertyValue1 = strtoul(poVfkFeature->GetProperty(idx1)->GetValueS(), NULL, 0);
+    for( int i = 0; i < m_nFeatureCount; i++ )
+    {
+        VFKFeature *poVfkFeature = (VFKFeature *) GetFeatureByIndex(i);
+        const GUIntBig iPropertyValue1 =
+            strtoul(poVfkFeature->GetProperty(idx1)->GetValueS(), NULL, 0);
         if (idx2 < 0) {
             if (iPropertyValue1 == value) {
                 poResult.push_back(poVfkFeature);
             }
         }
-        else {
-            iPropertyValue2 = strtoul(poVfkFeature->GetProperty(idx2)->GetValueS(), NULL, 0);
+        else
+        {
+            const GUIntBig iPropertyValue2 =
+                strtoul(poVfkFeature->GetProperty(idx2)->GetValueS(), NULL, 0);
             if (iPropertyValue1 == value || iPropertyValue2 == value) {
                 poResult.push_back(poVfkFeature);
             }
@@ -711,14 +721,14 @@ VFKFeatureList VFKDataBlock::GetFeatures(int idx1, int idx2, GUIntBig value)
 */
 GIntBig VFKDataBlock::GetFeatureCount(const char *pszName, const char *pszValue)
 {
-    int propIdx = GetPropertyIndex(pszName);
+    const int propIdx = GetPropertyIndex(pszName);
     if (propIdx < 0)
         return -1;
 
     int nfeatures = 0;
-    VFKFeature *poVFKFeature;
     for (int i = 0; i < ((IVFKDataBlock *) this)->GetFeatureCount(); i++) {
-        poVFKFeature = (VFKFeature *) ((IVFKDataBlock *) this)->GetFeature(i);
+        VFKFeature *poVFKFeature =
+            (VFKFeature *) ((IVFKDataBlock *) this)->GetFeature(i);
         if (!poVFKFeature)
             return -1;
         if (EQUAL (poVFKFeature->GetProperty(propIdx)->GetValueS(), pszValue))
@@ -838,21 +848,18 @@ int VFKDataBlock::LoadGeometryLineStringHP()
     }
 
     poDataBlockLines->LoadGeometry();
-    int idxId = GetPropertyIndex("ID");
-    int idxMy_Id;
-    if (EQUAL (m_pszName, "HP"))
-        idxMy_Id = poDataBlockLines->GetPropertyIndex("HP_ID");
-    else
-        idxMy_Id = poDataBlockLines->GetPropertyIndex("DPM_ID");
-    int idxPCB   = poDataBlockLines->GetPropertyIndex("PORADOVE_CISLO_BODU");
+    const int idxId = GetPropertyIndex("ID");
+    const int idxMy_Id = poDataBlockLines->GetPropertyIndex(
+        EQUAL(m_pszName, "HP") ? "HP_ID" : "DPM_ID");
+    const int idxPCB = poDataBlockLines->GetPropertyIndex("PORADOVE_CISLO_BODU");
     if (idxId < 0 || idxMy_Id < 0 || idxPCB < 0) {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Corrupted data (%s).\n", m_pszName);
         return nInvalid;
     }
 
-    VFKFeatureList poLineList
-        = poDataBlockLines->GetFeatures(idxPCB, 1); // reduce to first segment
+    // Reduce to first segment.
+    VFKFeatureList poLineList = poDataBlockLines->GetFeatures(idxPCB, 1);
     for (int i = 0; i < ((IVFKDataBlock *) this)->GetFeatureCount(); i++) {
         VFKFeature *poFeature = (VFKFeature *) GetFeatureByIndex(i);
         CPLAssert(NULL != poFeature);
@@ -876,27 +883,22 @@ int VFKDataBlock::LoadGeometryLineStringHP()
 */
 int VFKDataBlock::LoadGeometryPolygon()
 {
-    int nInvalid = 0;
+    VFKDataBlock *poDataBlockLines1 = NULL;
+    VFKDataBlock *poDataBlockLines2 = NULL;
 
-    GUIntBig id;
-    int idxBud = 0;
-    int idxOb = 0;
-    int idxIdOb = 0;
-
-    VFKFeature   *poFeature;
-    VFKDataBlock *poDataBlockLines1, *poDataBlockLines2;
-
-    bool bIsPar;
+    bool bIsPar = false;
     if (EQUAL (m_pszName, "PAR")) {
         poDataBlockLines1 = (VFKDataBlock *) m_poReader->GetDataBlock("HP");
         poDataBlockLines2 = poDataBlockLines1;
-        bIsPar = TRUE;
+        bIsPar = true;
     }
     else {
         poDataBlockLines1 = (VFKDataBlock *) m_poReader->GetDataBlock("OB");
         poDataBlockLines2 = (VFKDataBlock *) m_poReader->GetDataBlock("SBP");
-        bIsPar = FALSE;
+        bIsPar = false;
     }
+
+    int nInvalid = 0;
     if (NULL == poDataBlockLines1 || NULL == poDataBlockLines2) {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Data block %s not found.\n", m_pszName);
@@ -912,9 +914,13 @@ int VFKDataBlock::LoadGeometryPolygon()
         return nInvalid;
     }
 
+    int idxBud = 0;
+    int idxOb = 0;
+    int idxIdOb = 0;
     int idxPar1 = 0;
     int idxPar2 = 0;
-    if (bIsPar) {
+    if( bIsPar )
+    {
         idxPar1 = poDataBlockLines1->GetPropertyIndex("PAR_ID_1");
         idxPar2 = poDataBlockLines1->GetPropertyIndex("PAR_ID_2");
         if (idxPar1 < 0 || idxPar2 < 0) {
@@ -939,10 +945,12 @@ int VFKDataBlock::LoadGeometryPolygon()
     OGRLinearRing ogrRing;
     OGRPolygon ogrPolygon;
 
-    for (int i = 0; i < ((IVFKDataBlock *) this)->GetFeatureCount(); i++) {
-        poFeature = (VFKFeature *) GetFeatureByIndex(i);
+    for( int i = 0; i < ((IVFKDataBlock *) this)->GetFeatureCount(); i++ )
+    {
+        VFKFeature *poFeature = (VFKFeature *) GetFeatureByIndex(i);
         CPLAssert(NULL != poFeature);
-        id = strtoul(poFeature->GetProperty(idxId)->GetValueS(), NULL, 0);
+        const GUIntBig id =
+            strtoul(poFeature->GetProperty(idxId)->GetValueS(), NULL, 0);
         if (bIsPar) {
             poLineList = poDataBlockLines1->GetFeatures(idxPar1, idxPar2, id);
         }
@@ -970,14 +978,14 @@ int VFKDataBlock::LoadGeometryPolygon()
         bool bFound = false;
         int nCount = 0;
         int nCountMax = static_cast<int>(poLineList.size()) * 2;
-        while (poLineList.size() > 0 && nCount < nCountMax) {
+        while (!poLineList.empty() && nCount < nCountMax) {
             bool bNewRing = !bFound;
             bFound = false;
             for (VFKFeatureList::iterator iHp = poLineList.begin(), eHp = poLineList.end();
                  iHp != eHp; ++iHp) {
                 const OGRLineString *pLine = (OGRLineString *) (*iHp)->GetGeometry();
                 if (pLine && AppendLineToRing(&poRingList, pLine, bNewRing)) {
-                    bFound = TRUE;
+                    bFound = true;
                     poLineList.erase(iHp);
                     break;
                 }
diff --git a/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp b/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp
index fd24c6c..b0482c2 100644
--- a/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkdatablocksqlite.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vfkdatablocksqlite.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Data block definition (SQLite)
  * Purpose:  Implements VFKDataBlockSQLite
@@ -38,6 +37,8 @@
 #include "cpl_conv.h"
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: vfkdatablocksqlite.cpp 37472 2017-02-26 02:47:45Z goatbar $");
+
 /*!
   \brief Load geometry (point layers)
 
@@ -45,61 +46,55 @@
 */
 int VFKDataBlockSQLite::LoadGeometryPoint()
 {
-    int   nInvalid, rowId, nGeometries;
-    bool  bSkipInvalid;
-    /* long iFID; */
-    double x, y;
-
-    CPLString     osSQL;
-    sqlite3_stmt *hStmt;
-
-    VFKFeatureSQLite *poFeature;
-    VFKReaderSQLite  *poReader;
-
-    nInvalid  = nGeometries = 0;
-    poReader  = (VFKReaderSQLite*) m_poReader;
-
     if (LoadGeometryFromDB()) /* try to load geometry from DB */
-	return 0;
+        return 0;
 
-    bSkipInvalid = EQUAL(m_pszName, "OB") || EQUAL(m_pszName, "OP") || EQUAL(m_pszName, "OBBP");
+    const bool bSkipInvalid =
+        EQUAL(m_pszName, "OB") || EQUAL(m_pszName, "OP") ||
+        EQUAL(m_pszName, "OBBP");
+
+    CPLString osSQL;
     osSQL.Printf("SELECT SOURADNICE_Y,SOURADNICE_X,%s,rowid FROM %s",
                  FID_COLUMN, m_pszName);
-    hStmt = poReader->PrepareStatement(osSQL.c_str());
+
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
+    sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());
 
     if (poReader->IsSpatial())
-	poReader->ExecuteSQL("BEGIN");
+        poReader->ExecuteSQL("BEGIN");
 
+    int nGeometries = 0;
+    int nInvalid = 0;
     while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
         /* read values */
-        x = -1.0 * sqlite3_column_double(hStmt, 0); /* S-JTSK coordinate system expected */
-        y = -1.0 * sqlite3_column_double(hStmt, 1);
+        const double x = -1.0 * sqlite3_column_double(hStmt, 0); /* S-JTSK coordinate system expected */
+        const double y = -1.0 * sqlite3_column_double(hStmt, 1);
 #ifdef DEBUG
-	const GIntBig iFID = sqlite3_column_int64(hStmt, 2);
+        const GIntBig iFID = sqlite3_column_int64(hStmt, 2);
 #endif
-	rowId = sqlite3_column_int(hStmt, 3);
+        const int rowId = sqlite3_column_int(hStmt, 3);
 
-        poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
+        VFKFeatureSQLite *poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
         CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);
 
         /* create geometry */
-	OGRPoint pt(x, y);
+        OGRPoint pt(x, y);
         if (!poFeature->SetGeometry(&pt)) {
             nInvalid++;
             continue;
         }
 
-	/* store also geometry in DB */
-	if (poReader->IsSpatial() &&
-	    SaveGeometryToDB(&pt, rowId) != OGRERR_FAILURE)
-	    nGeometries++;
+        /* store also geometry in DB */
+        if (poReader->IsSpatial() &&
+            SaveGeometryToDB(&pt, rowId) != OGRERR_FAILURE)
+            nGeometries++;
     }
 
     /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
 
     if (poReader->IsSpatial())
-	poReader->ExecuteSQL("COMMIT");
+        poReader->ExecuteSQL("COMMIT");
 
     return bSkipInvalid ? 0 : nInvalid;
 }
@@ -109,7 +104,7 @@ int VFKDataBlockSQLite::LoadGeometryPoint()
 
   \param poLine VFK feature
   \param oOGRLine line geometry
-  \param[in,out] bValid TRUE when feature's geometry is valid
+  \param[in,out] bValid true when feature's geometry is valid
   \param[in,out] rowIdFeat list of row ids which forms linestring
   \param[in,out] nGeometries number of features with valid geometry
 */
@@ -117,15 +112,13 @@ bool VFKDataBlockSQLite::SetGeometryLineString(VFKFeatureSQLite *poLine, OGRLine
                                                bool& bValid, const char *ftype,
                                                std::vector<int>& rowIdFeat, int& nGeometries)
 {
-    int              npoints;
-    VFKReaderSQLite *poReader;
-
-    poReader  = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
     oOGRLine->setCoordinateDimension(2); /* force 2D */
 
     /* check also VFK validity */
-    if (bValid) {
+    if( bValid )
+    {
         /* Feature types
 
            - '3'    - line       (2 points)
@@ -136,37 +129,37 @@ bool VFKDataBlockSQLite::SetGeometryLineString(VFKFeatureSQLite *poLine, OGRLine
            - '16'   - arc        (3 points)
         */
 
-        npoints = oOGRLine->getNumPoints();
+        const int npoints = oOGRLine->getNumPoints();
         if (EQUAL(ftype, "3") && npoints > 2) {
             /* be less pedantic, just inform user about data
              * inconsistency
 
-               bValid = FALSE;
+               bValid = false;
             */
             CPLDebug("OGR-VFK",
                      "Line (fid=" CPL_FRMT_GIB ") defined by more than two vertices",
                      poLine->GetFID());
         }
         else if (EQUAL(ftype, "11") && npoints < 2) {
-            bValid = FALSE;
+            bValid = false;
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Curve (fid=" CPL_FRMT_GIB ") defined by less than two vertices",
                      poLine->GetFID());
         }
         else if (EQUAL(ftype, "15") && npoints != 3) {
-            bValid = FALSE;
+            bValid = false;
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Circle (fid=" CPL_FRMT_GIB ") defined by invalid number of vertices (%d)",
                      poLine->GetFID(), oOGRLine->getNumPoints());
         }
         else if (strlen(ftype) > 2 && STARTS_WITH_CI(ftype, "15") && npoints != 1) {
-            bValid = FALSE;
+            bValid = false;
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Circle (fid=" CPL_FRMT_GIB ") defined by invalid number of vertices (%d)",
                      poLine->GetFID(), oOGRLine->getNumPoints());
         }
         else if (EQUAL(ftype, "16") && npoints != 3) {
-            bValid = FALSE;
+            bValid = false;
             CPLError(CE_Warning, CPLE_AppDefined,
                      "Arc (fid=" CPL_FRMT_GIB ") defined by invalid number of vertices (%d)",
                      poLine->GetFID(), oOGRLine->getNumPoints());
@@ -174,12 +167,14 @@ bool VFKDataBlockSQLite::SetGeometryLineString(VFKFeatureSQLite *poLine, OGRLine
     }
 
     /* set geometry (NULL for invalid features) */
-    if (bValid) {
+    if( bValid )
+    {
         if (!poLine->SetGeometry(oOGRLine, ftype)) {
-            bValid = FALSE;
+            bValid = false;
         }
     }
-    else {
+    else
+    {
         poLine->SetGeometry(NULL);
     }
 
@@ -187,11 +182,13 @@ bool VFKDataBlockSQLite::SetGeometryLineString(VFKFeatureSQLite *poLine, OGRLine
     UpdateFID(poLine->GetFID(), rowIdFeat);
 
     /* store also geometry in DB */
-    CPLAssert(0 != rowIdFeat.size());
-    if (bValid && poReader->IsSpatial() &&
+    CPLAssert( !rowIdFeat.empty() );
+    if( bValid && poReader->IsSpatial() &&
         SaveGeometryToDB(bValid ? poLine->GetGeometry() : NULL,
-                         rowIdFeat[0]) != OGRERR_FAILURE)
+                         rowIdFeat[0]) != OGRERR_FAILURE )
+    {
         nGeometries++;
+    }
 
     rowIdFeat.clear();
     oOGRLine->empty(); /* restore line */
@@ -206,46 +203,37 @@ bool VFKDataBlockSQLite::SetGeometryLineString(VFKFeatureSQLite *poLine, OGRLine
 */
 int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
 {
-    int       nInvalid, nGeometries, rowId, iIdx;
-    CPLString szFType, szFTypeLine;
-
-    GUIntBig id, ipcb;
-    bool     bValid;
-
-    std::vector<int> rowIdFeat;
-    CPLString     osSQL;
-    sqlite3_stmt *hStmt;
+    int nInvalid = 0;
 
-    VFKReaderSQLite    *poReader;
-    VFKDataBlockSQLite *poDataBlockPoints;
-    VFKFeatureSQLite   *poFeature, *poPoint, *poLine;
-
-    OGRLineString oOGRLine;
-
-    nInvalid  = nGeometries = 0;
-    poReader  = (VFKReaderSQLite*) m_poReader;
-    poLine    = NULL;
-
-    poDataBlockPoints = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SOBR");
+    VFKDataBlockSQLite *poDataBlockPoints =
+        (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SOBR");
     if (NULL == poDataBlockPoints) {
         CPLError(CE_Failure, CPLE_FileIO,
                  "Data block %s not found.\n", m_pszName);
         return nInvalid;
     }
 
+    int nGeometries = 0;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
+
     poDataBlockPoints->LoadGeometry();
 
     if (LoadGeometryFromDB()) /* try to load geometry from DB */
-	return 0;
+        return 0;
 
+    CPLString osSQL;
     osSQL.Printf("UPDATE %s SET %s = -1", m_pszName, FID_COLUMN);
     poReader->ExecuteSQL(osSQL.c_str());
-    bValid = TRUE;
-    iIdx = 0;
-    for (int i = 0; i < 2; i++) {
-	/* first collect linestrings related to HP, OB or DPM
-	   then collect rest of linestrings */
-        if (i == 0)
+    bool bValid = true;
+    int iIdx = 0;
+
+    VFKFeatureSQLite *poLine = NULL;
+
+    for( int i = 0; i < 2; i++ )
+    {
+        /* first collect linestrings related to HP, OB or DPM
+           then collect rest of linestrings */
+        if( i == 0 )
             osSQL.Printf("SELECT BP_ID,PORADOVE_CISLO_BODU,PARAMETRY_SPOJENI,_rowid_ FROM '%s' WHERE "
                          "HP_ID IS NOT NULL OR OB_ID IS NOT NULL OR DPM_ID IS NOT NULL "
                          "ORDER BY HP_ID,OB_ID,DPM_ID,PORADOVE_CISLO_BODU", m_pszName);
@@ -254,71 +242,88 @@ int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
                          "OB_ID IS NULL AND HP_ID IS NULL AND DPM_ID IS NULL "
                          "ORDER BY ID,PORADOVE_CISLO_BODU", m_pszName);
 
-        hStmt = poReader->PrepareStatement(osSQL.c_str());
+        sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());
+
+        if (poReader->IsSpatial())
+            poReader->ExecuteSQL("BEGIN");
 
-	if (poReader->IsSpatial())
-	    poReader->ExecuteSQL("BEGIN");
+        std::vector<int> rowIdFeat;
+        CPLString szFType;
+        OGRLineString oOGRLine;
 
         while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
             // read values
-            id    = sqlite3_column_int64(hStmt, 0);
-            ipcb  = sqlite3_column_int64(hStmt, 1);
+            const GUIntBig id = sqlite3_column_int64(hStmt, 0);
+            const GUIntBig ipcb  = sqlite3_column_int64(hStmt, 1);
             szFType = (char *) sqlite3_column_text(hStmt, 2);
-            rowId = sqlite3_column_int(hStmt, 3);
+            int rowId = sqlite3_column_int(hStmt, 3);
 
             if (ipcb == 1) {
-                poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(iIdx);
+                VFKFeatureSQLite *poFeature =
+                    (VFKFeatureSQLite *) GetFeatureByIndex(iIdx);
                 if( poFeature == NULL )
                 {
-                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot retrieve feature %d", iIdx);
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Cannot retrieve feature %d", iIdx);
                     break;
                 }
                 poFeature->SetRowId(rowId);
 
                 /* set geometry & reset */
-                if (poLine && !SetGeometryLineString(poLine, &oOGRLine,
-                                                     bValid, szFTypeLine, rowIdFeat, nGeometries)) {
+                CPLString szFTypeLine;
+                if( poLine &&
+                    !SetGeometryLineString(
+                        poLine, &oOGRLine,
+                        bValid, szFTypeLine, rowIdFeat, nGeometries) )
+                {
                     nInvalid++;
                 }
 
-		bValid = TRUE;
+                bValid = true;
                 poLine = poFeature;
                 szFTypeLine = szFType;
                 iIdx++;
             }
 
-            poPoint = (VFKFeatureSQLite *) poDataBlockPoints->GetFeature("ID", id);
-	    if (poPoint) {
-		OGRPoint *pt = (OGRPoint *) poPoint->GetGeometry();
-		if (pt) {
-		    oOGRLine.addPoint(pt);
-		}
-		else {
-		    CPLDebug("OGR-VFK",
-			     "Geometry (point ID = " CPL_FRMT_GUIB ") not valid", id);
-		    bValid = FALSE;
-		}
-	    }
-	    else {
+            VFKFeatureSQLite *poPoint =
+                (VFKFeatureSQLite *) poDataBlockPoints->GetFeature("ID", id);
+            if( poPoint )
+            {
+                OGRPoint *pt = (OGRPoint *) poPoint->GetGeometry();
+                if (pt) {
+                    oOGRLine.addPoint(pt);
+                }
+                else
+                {
+                    CPLDebug("OGR-VFK",
+                             "Geometry (point ID = " CPL_FRMT_GUIB ") not valid", id);
+                    bValid = false;
+                }
+            }
+            else
+            {
                 CPLDebug("OGR-VFK",
                          "Point ID = " CPL_FRMT_GUIB " not found (rowid = %d)",
                          id, rowId);
-		bValid = FALSE;
+                bValid = false;
             }
 
-	    /* add vertex to the linestring */
-	    rowIdFeat.push_back(rowId);
+            /* add vertex to the linestring */
+            rowIdFeat.push_back(rowId);
         }
 
         /* add last line */
-        if (poLine && !SetGeometryLineString(poLine, &oOGRLine,
-                                             bValid, szFType.c_str(), rowIdFeat, nGeometries)) {
+        if( poLine &&
+            !SetGeometryLineString(
+                poLine, &oOGRLine,
+                bValid, szFType.c_str(), rowIdFeat, nGeometries) )
+        {
             nInvalid++;
         }
-	poLine = NULL;
+        poLine = NULL;
 
-	if (poReader->IsSpatial())
-	    poReader->ExecuteSQL("COMMIT");
+        if (poReader->IsSpatial())
+            poReader->ExecuteSQL("COMMIT");
     }
 
     /* update number of geometries in VFK_DB_TABLE table */
@@ -334,86 +339,86 @@ int VFKDataBlockSQLite::LoadGeometryLineStringSBP()
 */
 int VFKDataBlockSQLite::LoadGeometryLineStringHP()
 {
-    int          nInvalid, nGeometries;
-    int          rowId;
-    long         iFID;
-
-    CPLString    osColumn, osSQL;
-    const char  *vrColumn[2];
-    GUIntBig     vrValue[2];
-
-    sqlite3_stmt *hStmt;
+    int nInvalid = 0;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
-    OGRGeometry        *poOgrGeometry;
-    VFKReaderSQLite    *poReader;
-    VFKDataBlockSQLite *poDataBlockLines;
-    VFKFeatureSQLite   *poFeature, *poLine;
-
-    nInvalid = nGeometries = 0;
-    poReader  = (VFKReaderSQLite*) m_poReader;
-
-    poDataBlockLines = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SBP");
+    VFKDataBlockSQLite *poDataBlockLines =
+        (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SBP");
     if (NULL == poDataBlockLines) {
         CPLError(CE_Failure, CPLE_FileIO,
-                 "Data block %s not found", m_pszName);
+                 "Data block %s not found.", m_pszName);
         return nInvalid;
     }
 
     poDataBlockLines->LoadGeometry();
 
     if (LoadGeometryFromDB()) /* try to load geometry from DB */
-	return 0;
+        return 0;
 
+    CPLString osColumn;
     osColumn.Printf("%s_ID", m_pszName);
-    vrColumn[0] = osColumn.c_str();
-    vrColumn[1] = "PORADOVE_CISLO_BODU";
-    vrValue[1]  = 1; /* reduce to first segment */
+    const char *vrColumn[2] = {
+        osColumn.c_str(),
+        "PORADOVE_CISLO_BODU"
+    };
+
+    GUIntBig vrValue[2] = { 0, 1 }; // Reduce to first segment.
 
+    CPLString osSQL;
     osSQL.Printf("SELECT ID,%s,rowid FROM %s", FID_COLUMN, m_pszName);
     /* TODO: handle points in DPM */
     if (EQUAL(m_pszName, "DPM"))
         osSQL += " WHERE SOURADNICE_X IS NULL";
-    hStmt = poReader->PrepareStatement(osSQL.c_str());
+    sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());
 
     if (poReader->IsSpatial())
-	poReader->ExecuteSQL("BEGIN");
+        poReader->ExecuteSQL("BEGIN");
 
-    while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
+    int nGeometries = 0;
+
+    while( poReader->ExecuteSQL(hStmt) == OGRERR_NONE )
+    {
         /* read values */
         vrValue[0] = sqlite3_column_int64(hStmt, 0);
-        iFID       = static_cast<long>(sqlite3_column_int64(hStmt, 1));
-        rowId      = sqlite3_column_int(hStmt, 2);
+        const long iFID = static_cast<long>(sqlite3_column_int64(hStmt, 1));
+        const int rowId = sqlite3_column_int(hStmt, 2);
 
-        poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
+        VFKFeatureSQLite *poFeature =
+            (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
         CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);
 
-        poLine = poDataBlockLines->GetFeature(vrColumn, vrValue, 2, TRUE);
-	if (!poLine) {
-	    poOgrGeometry = NULL;
-	}
-	else {
-	    poOgrGeometry = poLine->GetGeometry();
-	}
-	if (!poOgrGeometry || !poFeature->SetGeometry(poOgrGeometry)) {
+        VFKFeatureSQLite *poLine =
+            poDataBlockLines->GetFeature(vrColumn, vrValue, 2, TRUE);
+
+        OGRGeometry *poOgrGeometry = NULL;
+        if( !poLine )
+        {
+            poOgrGeometry = NULL;
+        }
+        else
+        {
+            poOgrGeometry = poLine->GetGeometry();
+        }
+        if (!poOgrGeometry || !poFeature->SetGeometry(poOgrGeometry)) {
             CPLDebug("OGR-VFK", "VFKDataBlockSQLite::LoadGeometryLineStringHP(): name=%s fid=%ld "
                      "id=" CPL_FRMT_GUIB " -> %s geometry", m_pszName, iFID, vrValue[0],
                      poOgrGeometry ? "invalid" : "empty");
-	    nInvalid++;
+            nInvalid++;
             continue;
         }
 
-	/* store also geometry in DB */
-	if (poReader->IsSpatial() &&
-	    SaveGeometryToDB(poOgrGeometry, rowId) != OGRERR_FAILURE &&
-	    poOgrGeometry)
-	    nGeometries++;
+        /* store also geometry in DB */
+        if (poReader->IsSpatial() &&
+            SaveGeometryToDB(poOgrGeometry, rowId) != OGRERR_FAILURE &&
+            poOgrGeometry)
+            nGeometries++;
     }
 
     /* update number of geometries in VFK_DB_TABLE table */
     UpdateVfkBlocks(nGeometries);
 
     if (poReader->IsSpatial())
-	poReader->ExecuteSQL("COMMIT");
+        poReader->ExecuteSQL("COMMIT");
 
     return nInvalid;
 }
@@ -425,56 +430,44 @@ int VFKDataBlockSQLite::LoadGeometryLineStringHP()
 */
 int VFKDataBlockSQLite::LoadGeometryPolygon()
 {
-    int  nInvalidNoLines, nInvalidNoRings, nGeometries, nBridges;
-    int  rowId, nCount, nCountMax;
-    size_t nLines;
-    long iFID;
-    bool bIsPar, bNewRing, bFound;
-
-    CPLString    osSQL;
-    const char  *vrColumn[2];
-    GUIntBig     vrValue[2];
-    GUIntBig     id, idOb;
-
-    sqlite3_stmt *hStmt;
-
-    VFKReaderSQLite    *poReader;
-    VFKDataBlockSQLite *poDataBlockLines1, *poDataBlockLines2;
-    VFKFeatureSQLite   *poFeature;
-
-    VFKFeatureSQLiteList  poLineList;
-    /* first is to be considered as exterior */
-    PointListArray        poRingList;
-
-    std::vector<OGRLinearRing *> poLinearRingList;
-    OGRPolygon     ogrPolygon;
-    OGRLinearRing *poOgrRing;
-
-    nInvalidNoLines = nInvalidNoRings = nGeometries = 0;
-    poReader  = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
+    VFKDataBlockSQLite *poDataBlockLines1 = NULL;
+    VFKDataBlockSQLite *poDataBlockLines2 = NULL;
+    bool bIsPar = false;
     if (EQUAL (m_pszName, "PAR")) {
         poDataBlockLines1 = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("HP");
         poDataBlockLines2 = poDataBlockLines1;
-        bIsPar = TRUE;
+        bIsPar = true;
     }
     else {
         poDataBlockLines1 = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("OB");
         poDataBlockLines2 = (VFKDataBlockSQLite *) m_poReader->GetDataBlock("SBP");
-        bIsPar = FALSE;
+        bIsPar = false;
     }
-    if (NULL == poDataBlockLines1 || NULL == poDataBlockLines2) {
-        CPLError(CE_Failure, CPLE_FileIO,
-                 "Data block %s not found", m_pszName);
+    if( NULL == poDataBlockLines1 )
+    {
+        CPLError(CE_Warning, CPLE_FileIO,
+                 "Data block %s not found. Unable to build geometry for %s.",
+                 bIsPar ? "HP" : "OB", m_pszName);
+        return -1;
+    }
+    if( NULL == poDataBlockLines2 )
+    {
+        CPLError(CE_Warning, CPLE_FileIO,
+                 "Data block %s not found. Unable to build geometry for %s.",
+                 "SBP", m_pszName);
         return -1;
     }
 
     poDataBlockLines1->LoadGeometry();
     poDataBlockLines2->LoadGeometry();
 
-    if (LoadGeometryFromDB()) /* try to load geometry from DB */
-	return 0;
+    if( LoadGeometryFromDB() )  // Try to load geometry from DB.
+        return 0;
 
+    const char *vrColumn[2] = { NULL, NULL };
+    GUIntBig vrValue[2] = { 0, 0 };
     if (bIsPar) {
         vrColumn[0] = "PAR_ID_1";
         vrColumn[1] = "PAR_ID_2";
@@ -485,31 +478,40 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
         vrValue[1]  = 1;
     }
 
+    CPLString osSQL;
     osSQL.Printf("SELECT ID,%s,rowid FROM %s", FID_COLUMN, m_pszName);
-    hStmt = poReader->PrepareStatement(osSQL.c_str());
+    sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());
 
     if (poReader->IsSpatial())
-	poReader->ExecuteSQL("BEGIN");
+        poReader->ExecuteSQL("BEGIN");
 
-    while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
-        nBridges = 0;
+    VFKFeatureSQLiteList poLineList;
+    /* first is to be considered as exterior */
+    PointListArray poRingList;
+    std::vector<OGRLinearRing *> poLinearRingList;
+    OGRPolygon ogrPolygon;
+    int nInvalidNoLines = 0;
+    int nInvalidNoRings = 0;
+    int nGeometries = 0;
 
+    while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
         /* read values */
-        id        = sqlite3_column_int64(hStmt, 0);
-        iFID      = static_cast<long>(sqlite3_column_int64(hStmt, 1));
-        rowId     = sqlite3_column_int(hStmt, 2);
+        const GUIntBig id = sqlite3_column_int64(hStmt, 0);
+        const long iFID = static_cast<long>(sqlite3_column_int64(hStmt, 1));
+        const int rowId = sqlite3_column_int(hStmt, 2);
 
-        poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
+        VFKFeatureSQLite *poFeature =
+            (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
         CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);
 
-        if (bIsPar) {
+        if( bIsPar )
+        {
             vrValue[0] = vrValue[1] = id;
             poLineList = poDataBlockLines1->GetFeatures(vrColumn, vrValue, 2);
         }
-        else {
-            VFKFeatureSQLite *poLineSbp;
-            std::vector<VFKFeatureSQLite *> poLineListOb;
-            sqlite3_stmt *hStmtOb;
+        else
+        {
+            // std::vector<VFKFeatureSQLite *> poLineListOb;
 
             osSQL.Printf("SELECT ID FROM %s WHERE BUD_ID = " CPL_FRMT_GUIB,
                          poDataBlockLines1->GetName(), id);
@@ -519,17 +521,18 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
                 osColumn.Printf(" AND %s IS NULL", GEOM_COLUMN);
                 osSQL += osColumn;
             }
-            hStmtOb = poReader->PrepareStatement(osSQL.c_str());
+            sqlite3_stmt *hStmtOb = poReader->PrepareStatement(osSQL.c_str());
 
             while(poReader->ExecuteSQL(hStmtOb) == OGRERR_NONE) {
-                idOb = sqlite3_column_int64(hStmtOb, 0);
+                const GUIntBig idOb = sqlite3_column_int64(hStmtOb, 0);
                 vrValue[0] = idOb;
-                poLineSbp = poDataBlockLines2->GetFeature(vrColumn, vrValue, 2);
+                VFKFeatureSQLite *poLineSbp =
+                    poDataBlockLines2->GetFeature(vrColumn, vrValue, 2);
                 if (poLineSbp)
                     poLineList.push_back(poLineSbp);
             }
         }
-        nLines = poLineList.size();
+        size_t nLines = poLineList.size();
         if (nLines < 1) {
             CPLDebug("OGR-VFK",
                      "%s: unable to collect rings for polygon fid = %ld (no lines)",
@@ -543,18 +546,19 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
         poRingList.clear();
 
         /* collect rings from lines */
-        bFound = FALSE;
-        nCount = 0;
-        nCountMax = static_cast<int>(nLines) * 2;
-	while (poLineList.size() > 0 && nCount < nCountMax) {
-            bNewRing = !bFound ? TRUE : FALSE;
-            bFound = FALSE;
+        bool bFound = false;
+        int nCount = 0;
+        const int nCountMax = static_cast<int>(nLines) * 2;
+        while( !poLineList.empty() && nCount < nCountMax )
+        {
+            bool bNewRing = !bFound;
+            bFound = false;
             int i = 1;
             for (VFKFeatureSQLiteList::iterator iHp = poLineList.begin(), eHp = poLineList.end();
                  iHp != eHp; ++iHp, ++i) {
                 const OGRLineString *pLine = (OGRLineString *) (*iHp)->GetGeometry();
                 if (pLine && AppendLineToRing(&poRingList, pLine, bNewRing)) {
-                    bFound = TRUE;
+                    bFound = true;
                     poLineList.erase(iHp);
                     break;
                 }
@@ -564,7 +568,7 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
         CPLDebug("OGR-VFK", "%s: fid = %ld nlines = %d -> nrings = %d", m_pszName,
                  iFID, (int)nLines, (int)poRingList.size());
 
-        if (poLineList.size() > 0) {
+        if (!poLineList.empty()) {
             CPLDebug("OGR-VFK",
                      "%s: unable to collect rings for polygon fid = %ld",
                      m_pszName, iFID);
@@ -573,59 +577,74 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
         }
 
         /* build rings */
-	poLinearRingList.clear();
-	int i = 1;
-        for (PointListArray::const_iterator iRing = poRingList.begin(), eRing = poRingList.end();
-             iRing != eRing; ++iRing) {
-	    OGRPoint *poPoint;
+        poLinearRingList.clear();
+        OGRLinearRing *poOgrRing = NULL;
+        int i = 1;
+        for( PointListArray::const_iterator iRing = poRingList.begin(),
+                 eRing = poRingList.end();
+             iRing != eRing;
+             ++iRing)
+        {
             PointList *poList = *iRing;
 
             poLinearRingList.push_back(new OGRLinearRing());
-	    poOgrRing = poLinearRingList.back();
-	    CPLAssert(NULL != poOgrRing);
-
-            for (PointList::iterator iPoint = poList->begin(), ePoint = poList->end();
-                 iPoint != ePoint; ++iPoint) {
-		poPoint = &(*iPoint);
+            poOgrRing = poLinearRingList.back();
+            CPLAssert(NULL != poOgrRing);
+
+            for( PointList::iterator iPoint = poList->begin(),
+                     ePoint = poList->end();
+                 iPoint != ePoint;
+                 ++iPoint)
+            {
+                OGRPoint *poPoint = &(*iPoint);
                 poOgrRing->addPoint(poPoint);
             }
-	    i++;
-	}
-
-	/* find exterior ring */
-	if (poLinearRingList.size() > 1) {
-	    double dArea, dMaxArea;
-	    std::vector<OGRLinearRing *>::iterator exteriorRing;
-
-	    exteriorRing = poLinearRingList.begin();
-	    dMaxArea = -1.;
-	    for (std::vector<OGRLinearRing *>::iterator iRing = poLinearRingList.begin(),
-		     eRing = poLinearRingList.end(); iRing != eRing; ++iRing) {
-		poOgrRing = *iRing;
-		if (!IsRingClosed(poOgrRing))
-		    continue; /* skip unclosed rings */
-
-		dArea = poOgrRing->get_Area();
-		if (dArea > dMaxArea) {
-		    dMaxArea = dArea;
-		    exteriorRing = iRing;
-		}
-	    }
-	    if (exteriorRing != poLinearRingList.begin()) {
-		std::swap(*poLinearRingList.begin(), *exteriorRing);
-	    }
-	}
-
-	/* build polygon from rings */
-        for (std::vector<OGRLinearRing *>::iterator iRing = poLinearRingList.begin(),
-		 eRing = poLinearRingList.end(); iRing != eRing; ++iRing) {
-	    poOgrRing = *iRing;
-
-	    /* check if ring is closed */
-	    if (IsRingClosed(poOgrRing)) {
-		ogrPolygon.addRing(poOgrRing);
+            i++;
+        }
+
+        /* find exterior ring */
+        if( poLinearRingList.size() > 1 )
+        {
+            std::vector<OGRLinearRing *>::iterator exteriorRing;
+
+            exteriorRing = poLinearRingList.begin();
+            double dMaxArea = -1.0;
+            for( std::vector<OGRLinearRing *>::iterator iRing =
+                     poLinearRingList.begin(),
+                     eRing = poLinearRingList.end();
+                 iRing != eRing;
+                 ++iRing )
+            {
+                poOgrRing = *iRing;
+                if (!IsRingClosed(poOgrRing))
+                    continue; /* skip unclosed rings */
+
+                const double dArea = poOgrRing->get_Area();
+                if (dArea > dMaxArea) {
+                    dMaxArea = dArea;
+                    exteriorRing = iRing;
+                }
+            }
+            if (exteriorRing != poLinearRingList.begin()) {
+                std::swap(*poLinearRingList.begin(), *exteriorRing);
+            }
+        }
+
+        /* build polygon from rings */
+        int nBridges = 0;
+        for( std::vector<OGRLinearRing *>::iterator iRing =
+                 poLinearRingList.begin(),
+                 eRing = poLinearRingList.end();
+             iRing != eRing;
+             ++iRing )
+        {
+            poOgrRing = *iRing;
+
+            /* check if ring is closed */
+            if (IsRingClosed(poOgrRing)) {
+                ogrPolygon.addRing(poOgrRing);
             }
-	    else {
+            else {
                 if (poOgrRing->getNumPoints() == 2) {
                     CPLDebug("OGR-VFK", "%s: Polygon (fid = %ld) bridge removed",
                              m_pszName, iFID);
@@ -637,7 +656,7 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
                              m_pszName, iFID);
                 }
             }
-	    delete poOgrRing;
+            delete poOgrRing;
             *iRing = NULL;
         }
 
@@ -651,7 +670,7 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
 
         /* store also geometry in DB */
         if (poReader->IsSpatial() &&
-	    SaveGeometryToDB(&ogrPolygon, rowId) != OGRERR_FAILURE)
+            SaveGeometryToDB(&ogrPolygon, rowId) != OGRERR_FAILURE)
             nGeometries++;
     }
 
@@ -669,7 +688,7 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
     UpdateVfkBlocks(nGeometries);
 
     if (poReader->IsSpatial())
-	poReader->ExecuteSQL("COMMIT");
+        poReader->ExecuteSQL("COMMIT");
 
     return nInvalidNoLines + nInvalidNoRings;
 }
@@ -685,12 +704,6 @@ int VFKDataBlockSQLite::LoadGeometryPolygon()
 */
 IVFKFeature *VFKDataBlockSQLite::GetFeature(GIntBig nFID)
 {
-    int rowId;
-    CPLString osSQL;
-    VFKReaderSQLite  *poReader;
-
-    sqlite3_stmt *hStmt;
-
     if (m_nFeatureCount < 0) {
         m_poReader->ReadDataRecords(this);
     }
@@ -698,20 +711,22 @@ IVFKFeature *VFKDataBlockSQLite::GetFeature(GIntBig nFID)
     if (nFID < 1 || nFID > m_nFeatureCount)
         return NULL;
 
-    if (m_bGeometryPerBlock && !m_bGeometry) {
+    if( m_bGeometryPerBlock && !m_bGeometry )
+    {
         LoadGeometry();
     }
 
-    poReader = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
+    CPLString osSQL;
     osSQL.Printf("SELECT rowid FROM %s WHERE %s = " CPL_FRMT_GIB,
                  m_pszName, FID_COLUMN, nFID);
     if (EQUAL(m_pszName, "SBP")) {
         osSQL += " AND PORADOVE_CISLO_BODU = 1";
     }
-    hStmt = poReader->PrepareStatement(osSQL.c_str());
+    sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());
 
-    rowId = -1;
+    int rowId = -1;
     if (poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
         rowId = sqlite3_column_int(hStmt, 0);
     }
@@ -732,28 +747,24 @@ IVFKFeature *VFKDataBlockSQLite::GetFeature(GIntBig nFID)
 VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char *column, GUIntBig value,
                                                  bool bGeom)
 {
-    int idx;
-    CPLString osSQL;
-    VFKReaderSQLite  *poReader;
-
-    sqlite3_stmt *hStmt;
-
-    poReader = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
+    CPLString osSQL;
     osSQL.Printf("SELECT %s from %s WHERE %s = " CPL_FRMT_GUIB,
                  FID_COLUMN, m_pszName, column, value);
-    if (bGeom) {
+    if( bGeom )
+    {
         CPLString osColumn;
 
         osColumn.Printf(" AND %s IS NOT NULL", GEOM_COLUMN);
         osSQL += osColumn;
     }
 
-    hStmt = poReader->PrepareStatement(osSQL.c_str());
+    sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());
     if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE)
         return NULL;
 
-    idx = sqlite3_column_int(hStmt, 0) - 1;
+    const int idx = sqlite3_column_int(hStmt, 0) - 1;
     sqlite3_finalize(hStmt);
 
     if (idx < 0 || idx >= m_nFeatureCount) // ? assert
@@ -775,32 +786,31 @@ VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char *column, GUIntBig va
 VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char **column, GUIntBig *value, int num,
                                                  bool bGeom)
 {
-    int idx;
-    CPLString osSQL, osItem;
-    VFKReaderSQLite  *poReader;
-
-    sqlite3_stmt *hStmt;
-
-    poReader = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
+    CPLString osSQL;
     osSQL.Printf("SELECT %s FROM %s WHERE ", FID_COLUMN, m_pszName);
-    for (int i = 0; i < num; i++) {
+
+    CPLString osItem;
+    for( int i = 0; i < num; i++ )
+    {
         if (i > 0)
             osItem.Printf(" AND %s = " CPL_FRMT_GUIB, column[i], value[i]);
         else
             osItem.Printf("%s = " CPL_FRMT_GUIB, column[i], value[i]);
         osSQL += osItem;
     }
-    if (bGeom) {
+    if( bGeom )
+    {
         osItem.Printf(" AND %s IS NOT NULL", GEOM_COLUMN);
         osSQL += osItem;
     }
 
-    hStmt = poReader->PrepareStatement(osSQL.c_str());
+    sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());
     if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE)
         return NULL;
 
-    idx = sqlite3_column_int(hStmt, 0) - 1; /* rowid starts at 1 */
+    int idx = sqlite3_column_int(hStmt, 0) - 1; /* rowid starts at 1 */
     sqlite3_finalize(hStmt);
 
     if (idx < 0 || idx >= m_nFeatureCount) // ? assert
@@ -820,16 +830,10 @@ VFKFeatureSQLite *VFKDataBlockSQLite::GetFeature(const char **column, GUIntBig *
 */
 VFKFeatureSQLiteList VFKDataBlockSQLite::GetFeatures(const char **column, GUIntBig *value, int num)
 {
-    int iRowId;
-    CPLString osSQL, osItem;
-
-    VFKReaderSQLite     *poReader;
-    VFKFeatureSQLiteList fList;
-
-    sqlite3_stmt *hStmt;
-
-    poReader = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
+    CPLString osItem;
+    CPLString osSQL;
     osSQL.Printf("SELECT rowid from %s WHERE ", m_pszName);
     for (int i = 0; i < num; i++) {
         if (i > 0)
@@ -841,9 +845,11 @@ VFKFeatureSQLiteList VFKDataBlockSQLite::GetFeatures(const char **column, GUIntB
     osSQL += " ORDER BY ";
     osSQL += FID_COLUMN;
 
-    hStmt = poReader->PrepareStatement(osSQL.c_str());
+    VFKFeatureSQLiteList fList;
+
+    sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());
     while (poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
-        iRowId = sqlite3_column_int(hStmt, 0);
+        const int iRowId = sqlite3_column_int(hStmt, 0);
         fList.push_back((VFKFeatureSQLite *)GetFeatureByIndex(iRowId - 1));
     }
 
@@ -861,36 +867,33 @@ VFKFeatureSQLiteList VFKDataBlockSQLite::GetFeatures(const char **column, GUIntB
 OGRErr VFKDataBlockSQLite::SaveGeometryToDB(const OGRGeometry *poGeom, int iRowId)
 {
     int        rc, nWKBLen;
-    GByte     *pabyWKB;
     CPLString  osSQL;
 
-    sqlite3_stmt *hStmt;
-
-    VFKReaderSQLite  *poReader;
+    sqlite3_stmt *hStmt = NULL;
 
-    poReader  = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
     if (poGeom) {
-	nWKBLen = poGeom->WkbSize();
-	pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
-	poGeom->exportToWkb(wkbNDR, pabyWKB);
-
-	osSQL.Printf("UPDATE %s SET %s = ? WHERE rowid = %d",
-		     m_pszName, GEOM_COLUMN, iRowId);
-	hStmt = poReader->PrepareStatement(osSQL.c_str());
-
-	rc = sqlite3_bind_blob(hStmt, 1, pabyWKB, nWKBLen, CPLFree);
-	if (rc != SQLITE_OK) {
-	    sqlite3_finalize(hStmt);
-	    CPLError(CE_Failure, CPLE_AppDefined,
-		     "Storing geometry in DB failed");
-	    return OGRERR_FAILURE;
-	}
+        nWKBLen = poGeom->WkbSize();
+        GByte *pabyWKB = (GByte *) CPLMalloc(nWKBLen + 1);
+        poGeom->exportToWkb(wkbNDR, pabyWKB);
+
+        osSQL.Printf("UPDATE %s SET %s = ? WHERE rowid = %d",
+                     m_pszName, GEOM_COLUMN, iRowId);
+        hStmt = poReader->PrepareStatement(osSQL.c_str());
+
+        rc = sqlite3_bind_blob(hStmt, 1, pabyWKB, nWKBLen, CPLFree);
+        if (rc != SQLITE_OK) {
+            sqlite3_finalize(hStmt);
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Storing geometry in DB failed");
+            return OGRERR_FAILURE;
+        }
     }
     else { /* invalid */
-	osSQL.Printf("UPDATE %s SET %s = NULL WHERE rowid = %d",
-		     m_pszName, GEOM_COLUMN, iRowId);
-	hStmt = poReader->PrepareStatement(osSQL.c_str());
+        osSQL.Printf("UPDATE %s SET %s = NULL WHERE rowid = %d",
+                     m_pszName, GEOM_COLUMN, iRowId);
+        hStmt = poReader->PrepareStatement(osSQL.c_str());
     }
 
     return poReader->ExecuteSQL(hStmt); /* calls sqlite3_finalize() */
@@ -899,95 +902,87 @@ OGRErr VFKDataBlockSQLite::SaveGeometryToDB(const OGRGeometry *poGeom, int iRowI
 /*!
   \brief Load geometry from DB
 
-  \return TRUE geometry successfully loaded otherwise FALSE
+  \return true if geometry successfully loaded otherwise false
 */
 bool VFKDataBlockSQLite::LoadGeometryFromDB()
 {
-    int nInvalid, nGeometries, nGeometriesCount, nBytes, rowId;
-#ifdef DEBUG
-    GIntBig iFID;
-#endif
-    bool bSkipInvalid;
-
-    CPLString osSQL;
-
-    OGRGeometry      *poGeometry;
-
-    VFKFeatureSQLite *poFeature;
-    VFKReaderSQLite  *poReader;
-
-    sqlite3_stmt *hStmt;
-
-    poReader = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
     if (!poReader->IsSpatial())   /* check if DB is spatial */
-	return FALSE;
+        return false;
 
+    CPLString osSQL;
     osSQL.Printf("SELECT num_geometries FROM %s WHERE table_name = '%s'",
-		 VFK_DB_TABLE, m_pszName);
-    hStmt = poReader->PrepareStatement(osSQL.c_str());
+                 VFK_DB_TABLE, m_pszName);
+    sqlite3_stmt *hStmt = poReader->PrepareStatement(osSQL.c_str());
     if (poReader->ExecuteSQL(hStmt) != OGRERR_NONE)
-        return FALSE;
-    nGeometries = sqlite3_column_int(hStmt, 0);
+        return false;
+    const int nGeometries = sqlite3_column_int(hStmt, 0);
     sqlite3_finalize(hStmt);
 
-    if (nGeometries < 1)
-	return FALSE;
+    if( nGeometries < 1 )
+        return false;
 
-    bSkipInvalid = EQUAL(m_pszName, "OB") || EQUAL(m_pszName, "OP") || EQUAL(m_pszName, "OBBP");
+    const bool bSkipInvalid =
+        EQUAL(m_pszName, "OB") ||
+        EQUAL(m_pszName, "OP") ||
+        EQUAL(m_pszName, "OBBP");
 
     /* load geometry from DB */
-    nInvalid = nGeometriesCount = 0;
     osSQL.Printf("SELECT %s,rowid,%s FROM %s ",
-		 GEOM_COLUMN, FID_COLUMN, m_pszName);
+                 GEOM_COLUMN, FID_COLUMN, m_pszName);
     if (EQUAL(m_pszName, "SBP"))
-	osSQL += "WHERE PORADOVE_CISLO_BODU = 1 ";
+        osSQL += "WHERE PORADOVE_CISLO_BODU = 1 ";
     osSQL += "ORDER BY ";
     osSQL += FID_COLUMN;
     hStmt = poReader->PrepareStatement(osSQL.c_str());
 
-    rowId = 0;
+    int rowId = 0;
+    int nInvalid = 0;
+    int nGeometriesCount = 0;
+
     while(poReader->ExecuteSQL(hStmt) == OGRERR_NONE) {
         rowId++; // =sqlite3_column_int(hStmt, 1);
 #ifdef DEBUG
-        iFID = sqlite3_column_int64(hStmt, 2);
+        const GIntBig iFID = sqlite3_column_int64(hStmt, 2);
 #endif
 
-        poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
+        VFKFeatureSQLite *poFeature = (VFKFeatureSQLite *) GetFeatureByIndex(rowId - 1);
         CPLAssert(NULL != poFeature && poFeature->GetFID() == iFID);
 
         // read geometry from DB
-	nBytes = sqlite3_column_bytes(hStmt, 0);
-	if (nBytes > 0 &&
-	    OGRGeometryFactory::createFromWkb((GByte*) sqlite3_column_blob(hStmt, 0),
-					      NULL, &poGeometry, nBytes) == OGRERR_NONE) {
-	    nGeometriesCount++;
-	    if (!poFeature->SetGeometry(poGeometry)) {
-		nInvalid++;
-	    }
-	    delete poGeometry;
-	}
-	else {
-	    nInvalid++;
-	}
+        const int nBytes = sqlite3_column_bytes(hStmt, 0);
+        OGRGeometry *poGeometry = NULL;
+        if (nBytes > 0 &&
+            OGRGeometryFactory::createFromWkb((GByte*) sqlite3_column_blob(hStmt, 0),
+                                              NULL, &poGeometry, nBytes) == OGRERR_NONE) {
+            nGeometriesCount++;
+            if (!poFeature->SetGeometry(poGeometry)) {
+                nInvalid++;
+            }
+            delete poGeometry;
+        }
+        else {
+            nInvalid++;
+        }
     }
 
     CPLDebug("OGR-VFK", "%s: %d geometries loaded from DB",
-	     m_pszName, nGeometriesCount);
+             m_pszName, nGeometriesCount);
 
     if (nGeometriesCount != nGeometries) {
-	CPLError(CE_Warning, CPLE_AppDefined,
+        CPLError(CE_Warning, CPLE_AppDefined,
                  "%s: %d geometries loaded (should be %d)",
-		 m_pszName, nGeometriesCount, nGeometries);
+                 m_pszName, nGeometriesCount, nGeometries);
     }
 
     if (nInvalid > 0 && !bSkipInvalid) {
-	CPLError(CE_Warning, CPLE_AppDefined,
+        CPLError(CE_Warning, CPLE_AppDefined,
                  "%s: %d features with invalid or empty geometry",
-		 m_pszName, nInvalid);
+                 m_pszName, nInvalid);
     }
 
-    return TRUE;
+    return true;
 }
 
 /*!
@@ -996,15 +991,12 @@ bool VFKDataBlockSQLite::LoadGeometryFromDB()
   \param nGeometries number of geometries to update
 */
 void VFKDataBlockSQLite::UpdateVfkBlocks(int nGeometries) {
-    int nFeatCount;
     CPLString osSQL;
 
-    VFKReaderSQLite  *poReader;
-
-    poReader = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
     /* update number of features in VFK_DB_TABLE table */
-    nFeatCount = (int)GetFeatureCount();
+    const int nFeatCount = (int)GetFeatureCount();
     if (nFeatCount > 0) {
         osSQL.Printf("UPDATE %s SET num_features = %d WHERE table_name = '%s'",
                      VFK_DB_TABLE, nFeatCount, m_pszName);
@@ -1017,9 +1009,9 @@ void VFKDataBlockSQLite::UpdateVfkBlocks(int nGeometries) {
                  "VFKDataBlockSQLite::UpdateVfkBlocks(): name=%s -> "
                  "%d geometries saved to internal DB", m_pszName, nGeometries);
 
-	osSQL.Printf("UPDATE %s SET num_geometries = %d WHERE table_name = '%s'",
-		     VFK_DB_TABLE, nGeometries, m_pszName);
-	poReader->ExecuteSQL(osSQL.c_str());
+        osSQL.Printf("UPDATE %s SET num_geometries = %d WHERE table_name = '%s'",
+                     VFK_DB_TABLE, nGeometries, m_pszName);
+        poReader->ExecuteSQL(osSQL.c_str());
     }
 }
 
@@ -1032,19 +1024,17 @@ void VFKDataBlockSQLite::UpdateVfkBlocks(int nGeometries) {
 void VFKDataBlockSQLite::UpdateFID(GIntBig iFID, std::vector<int> rowId)
 {
     CPLString osSQL, osValue;
-    VFKReaderSQLite  *poReader;
-
-    poReader = (VFKReaderSQLite*) m_poReader;
+    VFKReaderSQLite *poReader = (VFKReaderSQLite*) m_poReader;
 
     /* update number of geometries in VFK_DB_TABLE table */
     osSQL.Printf("UPDATE %s SET %s = " CPL_FRMT_GIB " WHERE rowid IN (",
                  m_pszName, FID_COLUMN, iFID);
     for (size_t i = 0; i < rowId.size(); i++) {
-	if (i > 0)
-	    osValue.Printf(",%d", rowId[i]);
-	else
-	    osValue.Printf("%d", rowId[i]);
-	osSQL += osValue;
+        if (i > 0)
+            osValue.Printf(",%d", rowId[i]);
+        else
+            osValue.Printf("%d", rowId[i]);
+        osSQL += osValue;
     }
     osSQL += ")";
 
@@ -1056,21 +1046,19 @@ void VFKDataBlockSQLite::UpdateFID(GIntBig iFID, std::vector<int> rowId)
 
   \param poRing pointer to OGRLinearRing to check
 
-  \return TRUE if closed otherwise FALSE
+  \return true if closed otherwise false
 */
-bool VFKDataBlockSQLite::IsRingClosed(const OGRLinearRing *poRing)
+bool VFKDataBlockSQLite::IsRingClosed( const OGRLinearRing *poRing )
 {
-    int nPoints;
-
-    nPoints = poRing->getNumPoints();
+    const int nPoints = poRing->getNumPoints();
     if (nPoints < 3)
-	return FALSE;
+        return false;
 
     if (poRing->getX(0) == poRing->getX(nPoints-1) &&
-	poRing->getY(0) == poRing->getY(nPoints-1))
-	return TRUE;
+        poRing->getY(0) == poRing->getY(nPoints-1))
+        return true;
 
-    return FALSE;
+    return false;
 }
 
 /*!
@@ -1080,15 +1068,30 @@ bool VFKDataBlockSQLite::IsRingClosed(const OGRLinearRing *poRing)
 */
 const char *VFKDataBlockSQLite::GetKey() const
 {
-    const char *pszKey;
-    const VFKPropertyDefn *poPropDefn;
-
-    if (GetPropertyCount() > 1) {
-        poPropDefn = GetProperty(0);
-        pszKey = poPropDefn->GetName();
-        if (EQUAL(pszKey, "ID"))
+    if( GetPropertyCount() > 1 )
+    {
+        const VFKPropertyDefn *poPropDefn = GetProperty(0);
+        const char *pszKey = poPropDefn->GetName();
+        if( EQUAL(pszKey, "ID") )
             return pszKey;
     }
 
     return NULL;
 }
+
+/*!
+  \brief Get geometry SQL type (for geometry_columns table)
+
+  \return geometry_type as integer
+*/
+int VFKDataBlockSQLite::GetGeometrySQLType() const
+{
+    if (m_nGeometryType == wkbPolygon)
+        return 3;
+    else if (m_nGeometryType == wkbLineString)
+        return 2;
+    else if (m_nGeometryType == wkbPoint)
+        return 1;
+
+    return 0; /* unknown geometry type */
+}
diff --git a/ogr/ogrsf_frmts/vfk/vfkfeature.cpp b/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
index 555d20a..5aed794 100644
--- a/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkfeature.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vfkfeature.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Feature definition
  * Purpose:  Implements IVFKFeature/VFKFeature class.
@@ -36,21 +35,22 @@
 #include "cpl_conv.h"
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: vfkfeature.cpp 37796 2017-03-19 19:18:10Z martinl $");
+
 /*!
   \brief IVFKFeature constructor
 
   \param poDataBlock pointer to VFKDataBlock instance
 */
-IVFKFeature::IVFKFeature(IVFKDataBlock *poDataBlock)
+IVFKFeature::IVFKFeature( IVFKDataBlock *poDataBlock ) :
+    m_poDataBlock(poDataBlock),
+    m_nFID(-1),
+    m_nGeometryType(poDataBlock->GetGeometryType()),
+    m_bGeometry(false),
+    m_bValid(false),
+    m_paGeom(NULL)
 {
     CPLAssert(NULL != poDataBlock);
-    m_poDataBlock   = poDataBlock;
-
-    m_nFID          = -1;
-    m_nGeometryType = poDataBlock->GetGeometryType();
-    m_bGeometry     = FALSE;
-    m_bValid        = FALSE;
-    m_paGeom        = NULL;
 }
 
 /*!
@@ -58,7 +58,7 @@ IVFKFeature::IVFKFeature(IVFKDataBlock *poDataBlock)
 */
 IVFKFeature::~IVFKFeature()
 {
-    if (m_paGeom)
+    if( m_paGeom )
         delete m_paGeom;
 
     m_poDataBlock = NULL;
@@ -97,18 +97,18 @@ void IVFKFeature::SetFID(GIntBig nFID)
   \param poGeom pointer to OGRGeometry
   \param ftype geometry VFK type
 
-  \return TRUE on valid feature or otherwise FALSE
+  \return true on valid feature or otherwise false
 */
-bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
+bool IVFKFeature::SetGeometry( OGRGeometry *poGeom, const char *ftype )
 {
-    m_bGeometry = TRUE;
+    m_bGeometry = true;
 
     delete m_paGeom;
     m_paGeom = NULL;
-    m_bValid = TRUE;
+    m_bValid = true;
 
     if (!poGeom) {
-	return m_bValid;
+        return m_bValid;
     }
 
     /* check empty geometries */
@@ -116,42 +116,41 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
             CPLError(CE_Warning, CPLE_AppDefined,
                      "%s: empty geometry fid = " CPL_FRMT_GIB,
                      m_poDataBlock->GetName(), m_nFID);
-        m_bValid = FALSE;
+        m_bValid = false;
     }
 
     /* check coordinates */
     if (m_nGeometryType == wkbPoint) {
-        double x, y;
-        x = ((OGRPoint *) poGeom)->getX();
-        y = ((OGRPoint *) poGeom)->getY();
+        const double x = ((OGRPoint *) poGeom)->getX();
+        const double y = ((OGRPoint *) poGeom)->getY();
         if (x > -430000 || x < -910000 ||
             y > -930000 || y < -1230000) {
             CPLDebug("OGR-VFK", "%s: invalid point fid = " CPL_FRMT_GIB,
                      m_poDataBlock->GetName(), m_nFID);
-            m_bValid = FALSE;
+            m_bValid = false;
         }
     }
 
     /* check degenerated polygons */
     if (m_nGeometryType == wkbPolygon) {
-        OGRLinearRing *poRing;
-        poRing = ((OGRPolygon *) poGeom)->getExteriorRing();
+        OGRLinearRing *poRing = ((OGRPolygon *) poGeom)->getExteriorRing();
         if (!poRing || poRing->getNumPoints() < 3) {
-	    CPLDebug("OGR-VFK", "%s: invalid polygon fid = " CPL_FRMT_GIB,
-		     m_poDataBlock->GetName(), m_nFID);
-            m_bValid = FALSE;
-	}
+            CPLDebug("OGR-VFK", "%s: invalid polygon fid = " CPL_FRMT_GIB,
+                     m_poDataBlock->GetName(), m_nFID);
+            m_bValid = false;
+        }
     }
 
-    if (m_bValid) {
-        if (ftype) {
+    if( m_bValid )
+    {
+        if( ftype )
+        {
             OGRPoint pt;
-            OGRGeometry *poGeomCurved;
             OGRCircularString poGeomString;
 
-            poGeomCurved = NULL;
+            OGRGeometry *poGeomCurved = NULL;
             if (EQUAL(ftype, "15") || EQUAL(ftype, "16")) {         /* -> circle or arc */
-                int npoints = ((OGRLineString *) poGeom)->getNumPoints();
+                const int npoints = ((OGRLineString *) poGeom)->getNumPoints();
                 for (int i = 0; i < npoints; i++) {
                     ((OGRLineString *) poGeom)->getPoint(i, &pt);
                     poGeomString.addPoint(&pt);
@@ -165,35 +164,38 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
                         CPLError(CE_Warning, CPLE_AppDefined,
                                  "npoints is %d.  Will overflow buffers.  "
                                  "Cannot continue.", npoints);
-                        m_bValid = FALSE;
+                        m_bValid = false;
                         return false;
                     }
 
                     /* compute center and radius of a circle */
                     double x[3] = { 0.0, 0.0, 0.0 };
                     double y[3] = { 0.0, 0.0, 0.0 };
-                    double m1, n1, m2, n2, c1, c2, mx;
-                    double c_x, c_y;
 
-                    for (int i = 0; i < npoints; i++) {
+                    for( int i = 0; i < npoints; i++ )
+                    {
                         ((OGRLineString *) poGeom)->getPoint(i, &pt);
                         x[i] = pt.getX();
                         y[i] = pt.getY();
                     }
 
-                    m1 = (x[0] + x[1]) / 2.0;
-                    n1 = (y[0] + y[1]) / 2.0;
+                    const double m1 = (x[0] + x[1]) / 2.0;
+                    const double n1 = (y[0] + y[1]) / 2.0;
 
-                    m2 = (x[0] + x[2]) / 2.0;
-                    n2 = (y[0] + y[2]) / 2.0;
+                    const double m2 = (x[0] + x[2]) / 2.0;
+                    const double n2 = (y[0] + y[2]) / 2.0;
 
-                    c1 = (x[1] - x[0]) * m1 + (y[1] - y[0]) * n1;
-                    c2 = (x[2] - x[0]) * m2 + (y[2] - y[0]) * n2;
+                    const double c1 = (x[1] - x[0]) * m1 + (y[1] - y[0]) * n1;
+                    const double c2 = (x[2] - x[0]) * m2 + (y[2] - y[0]) * n2;
 
-                    mx = (x[1] - x[0]) * (y[2] - y[0]) + (y[1] - y[0]) * (x[0] - x[2]);
+                    const double mx =
+                        (x[1] - x[0]) * (y[2] - y[0]) +
+                        (y[1] - y[0]) * (x[0] - x[2]);
 
-                    c_x = (c1 * (y[2] - y[0]) + c2 * (y[0] - y[1])) / mx;
-                    c_y = (c1 * (x[0] - x[2]) + c2 * (x[1] - x[0])) / mx;
+                    const double c_x =
+                        (c1 * (y[2] - y[0]) + c2 * (y[0] - y[1])) / mx;
+                    const double c_y =
+                        (c1 * (x[0] - x[2]) + c2 * (x[1] - x[0])) / mx;
 
                     /* compute a new intermediate point */
                     pt.setX(c_x - (x[1] - c_x));
@@ -203,25 +205,22 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
                     /* add last point */
                     ((OGRLineString *) poGeom)->getPoint(0, &pt);
                     poGeomString.addPoint(&pt);
-
                 }
             }
             else if (strlen(ftype) > 2 && STARTS_WITH_CI(ftype, "15")) { /* -> circle with radius */
-                float r;
-                char s[3]; /* 15 */
+                char s[3] = {}; /* 15 */
 
-                r = 0;
-                if (2 != sscanf(ftype, "%s %f", s, &r) || r < 0) {
+                float r = 0.0f;
+                if (2 != sscanf(ftype, "%2s %f", s, &r) || r < 0) {
                     CPLDebug("OGR-VFK", "%s: invalid circle (unknown or negative radius) "
                              "fid = " CPL_FRMT_GIB, m_poDataBlock->GetName(), m_nFID);
-                    m_bValid = FALSE;
+                    m_bValid = false;
                 }
-                else {
-                    double c_x, c_y;
-
+                else
+                {
                     ((OGRLineString *) poGeom)->getPoint(0, &pt);
-                    c_x = pt.getX();
-                    c_y = pt.getY();
+                    const double c_x = pt.getX();
+                    const double c_y = pt.getY();
 
                     /* define first point on a circle */
                     pt.setX(c_x + r);
@@ -248,12 +247,9 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
                     pt.setY(c_y);
                     poGeomString.addPoint(&pt);
                 }
-
             }
             else if (EQUAL(ftype, "11")) {                          /* curve */
-                int npoints;
-
-                npoints = ((OGRLineString *) poGeom)->getNumPoints();
+                const int npoints = ((OGRLineString *) poGeom)->getNumPoints();
                 if (npoints > 2) { /* circular otherwise line string */
                     for (int i = 0; i < npoints; i++) {
                         ((OGRLineString *) poGeom)->getPoint(i, &pt);
@@ -266,9 +262,8 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
                 poGeomCurved = poGeomString.CurveToLine();
 
             if (poGeomCurved) {
-                int npoints;
-
-                npoints = ((OGRLineString *) poGeomCurved)->getNumPoints();
+                const int npoints =
+                    ((OGRLineString *) poGeomCurved)->getNumPoints();
                 CPLDebug("OGR-VFK", "%s: curve (type=%s) to linestring (npoints=%d) fid = " CPL_FRMT_GIB,
                          m_poDataBlock->GetName(), ftype,
                          npoints, m_nFID);
@@ -281,18 +276,16 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
         if (!m_paGeom) {
             /* check degenerated linestrings */
             if (m_nGeometryType == wkbLineString) {
-                int npoints;
-
-                npoints = ((OGRLineString *) poGeom)->getNumPoints();
+                const int npoints = ((OGRLineString *) poGeom)->getNumPoints();
                 if (npoints < 2) {
                     CPLError(CE_Warning, CPLE_AppDefined,
                              "%s: invalid linestring (%d vertices) fid = " CPL_FRMT_GIB,
                              m_poDataBlock->GetName(), npoints, m_nFID);
-                    m_bValid = FALSE;
+                    m_bValid = false;
                 }
             }
 
-            if (m_bValid)
+            if( m_bValid )
                 m_paGeom = (OGRGeometry *) poGeom->clone(); /* make copy */
         }
     }
@@ -307,26 +300,23 @@ bool IVFKFeature::SetGeometry(OGRGeometry *poGeom, const char *ftype)
 */
 OGRGeometry *IVFKFeature::GetGeometry()
 {
-    if (m_nGeometryType != wkbNone && !m_bGeometry)
+    if( m_nGeometryType != wkbNone && !m_bGeometry )
         LoadGeometry();
 
     return m_paGeom;
 }
 
-
 /*!
   \brief Load geometry
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool IVFKFeature::LoadGeometry()
 {
-    const char *pszName;
-
-    if (m_bGeometry)
-        return TRUE;
+    if( m_bGeometry )
+        return true;
 
-    pszName  = m_poDataBlock->GetName();
+    const char *pszName = m_poDataBlock->GetName();
 
     if (EQUAL (pszName, "SOBR") ||
         EQUAL (pszName, "OBBP") ||
@@ -353,7 +343,7 @@ bool IVFKFeature::LoadGeometry()
         return LoadGeometryPolygon();
     }
 
-    return FALSE;
+    return false;
 }
 
 /*!
@@ -361,11 +351,13 @@ bool IVFKFeature::LoadGeometry()
 
   \param poDataBlock pointer to VFKDataBlock instance
 */
-VFKFeature::VFKFeature(IVFKDataBlock *poDataBlock, GIntBig iFID) : IVFKFeature(poDataBlock)
+VFKFeature::VFKFeature( IVFKDataBlock *poDataBlock, GIntBig iFID ) :
+    IVFKFeature(poDataBlock)
 {
     m_nFID = iFID;
     m_propertyList.assign(poDataBlock->GetPropertyCount(), VFKProperty());
-    CPLAssert(size_t (poDataBlock->GetPropertyCount()) == m_propertyList.size());
+    CPLAssert(
+        size_t (poDataBlock->GetPropertyCount()) == m_propertyList.size());
 }
 
 /*!
@@ -373,41 +365,37 @@ VFKFeature::VFKFeature(IVFKDataBlock *poDataBlock, GIntBig iFID) : IVFKFeature(p
 
   \param pszLine pointer to line containing feature definition
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool VFKFeature::SetProperties(const char *pszLine)
 {
-    unsigned int iIndex, nLength;
-    const char *poChar, *poProp;
-    char* pszProp;
-    bool inString;
-
-    std::vector<CPLString> oPropList;
-
-    pszProp = NULL;
-
-    for (poChar = pszLine; *poChar != '\0' && *poChar != ';'; poChar++)
+    const char *poChar = pszLine;  // Used after for.
+    for( ; *poChar != '\0' && *poChar != ';'; poChar++ )
         /* skip data block name */
         ;
-    if (*poChar == '\0')
-        return FALSE; /* nothing to read */
+    if( *poChar == '\0' )
+        return false; /* nothing to read */
 
     poChar++; /* skip ';' after data block name*/
 
     /* read properties into the list */
-    poProp = poChar;
-    iIndex = nLength = 0;
-    inString = FALSE;
-    while(*poChar != '\0') {
+    const char *poProp = poChar;
+    unsigned int iIndex = 0;
+    unsigned int nLength = 0;
+    bool inString = false;
+    char* pszProp = NULL;
+    std::vector<CPLString> oPropList;
+    while( *poChar != '\0' )
+    {
         if (*poChar == '"' &&
             (*(poChar-1) == ';' || *(poChar+1) == ';' || *(poChar+1) == '\0')) {
             poChar++; /* skip '"' */
-            inString = inString ? FALSE : TRUE;
+            inString = !inString;
             if (inString) {
                 poProp = poChar;
                 if (*poChar == '"' && (*(poChar+1) == ';' || *(poChar+1) == '\0')) {
                     poChar++;
-                    inString = FALSE;
+                    inString = false;
                 }
             }
             if (*poChar == '\0')
@@ -444,26 +432,23 @@ bool VFKFeature::SetProperties(const char *pszLine)
         CPLError(CE_Warning, CPLE_AppDefined,
                  "%s: invalid number of properties %d should be %d",
                  m_poDataBlock->GetName(),
-		 (int) oPropList.size(), m_poDataBlock->GetPropertyCount());
+                 (int) oPropList.size(), m_poDataBlock->GetPropertyCount());
         CPLFree(pszProp);
-        return FALSE;
+        return false;
    }
     iIndex = 0;
     for (std::vector<CPLString>::iterator ip = oPropList.begin();
-	 ip != oPropList.end(); ++ip) {
-	SetProperty(iIndex++, (*ip).c_str());
+         ip != oPropList.end(); ++ip) {
+        SetProperty(iIndex++, (*ip).c_str());
     }
 
-    // TODO(martinl): What was this block disabled?
+    // TODO(martinl): Why was this block disabled?
     /* set fid
     if (EQUAL(m_poDataBlock->GetName(), "SBP")) {
-        GUIntBig id;
-        const VFKProperty *poVfkProperty;
-
-        poVfkProperty = GetProperty("PORADOVE_CISLO_BODU");
+        const VFKProperty *poVfkProperty = GetProperty("PORADOVE_CISLO_BODU");
         if (poVfkProperty)
         {
-            id = strtoul(poVfkProperty->GetValueS(), NULL, 0);
+            GUIntBig id = strtoul(poVfkProperty->GetValueS(), NULL, 0);
             if (id == 1)
                 SetFID(0);
             else
@@ -476,7 +461,7 @@ bool VFKFeature::SetProperties(const char *pszLine)
     */
     CPLFree(pszProp);
 
-    return TRUE;
+    return true;
 }
 
 /*!
@@ -485,46 +470,49 @@ bool VFKFeature::SetProperties(const char *pszLine)
   \param iIndex property index
   \param pszValue property value
 
-  \return TRUE on success
-  \return FALSE on failure
+  \return true on success, false on failure
 */
-bool VFKFeature::SetProperty(int iIndex, const char *pszValue)
+bool VFKFeature::SetProperty( int iIndex, const char *pszValue )
 {
     if (iIndex < 0 || iIndex >= m_poDataBlock->GetPropertyCount() ||
-	size_t(iIndex) >= m_propertyList.size())
-        return FALSE;
+        size_t(iIndex) >= m_propertyList.size())
+        return false;
 
     if (strlen(pszValue) < 1)
+    {
         m_propertyList[iIndex] = VFKProperty();
-    else {
-        OGRFieldType fType;
-
-        const char *pszEncoding;
-        char       *pszValueEnc;
+        return true;
+    }
 
-        fType = m_poDataBlock->GetProperty(iIndex)->GetType();
-        switch (fType) {
-        case OFTInteger:
-            m_propertyList[iIndex] = VFKProperty(atoi(pszValue));
-            break;
-        case OFTReal:
-            m_propertyList[iIndex] = VFKProperty(CPLAtof(pszValue));
-            break;
-        default:
-            pszEncoding = m_poDataBlock->GetProperty(iIndex)->GetEncoding();
-            if (pszEncoding) {
-                pszValueEnc = CPLRecode(pszValue, pszEncoding,
-                                        CPL_ENC_UTF8);
-                m_propertyList[iIndex] = VFKProperty(pszValueEnc);
-                CPLFree(pszValueEnc);
-            }
-            else {
-                m_propertyList[iIndex] = VFKProperty(pszValue);
-            }
-            break;
+    const OGRFieldType fType =
+        m_poDataBlock->GetProperty(iIndex)->GetType();
+
+    switch (fType) {
+    case OFTInteger:
+        m_propertyList[iIndex] = VFKProperty(atoi(pszValue));
+        break;
+    case OFTInteger64:
+        m_propertyList[iIndex] = VFKProperty(CPLAtoGIntBig(pszValue));
+        break;
+    case OFTReal:
+        m_propertyList[iIndex] = VFKProperty(CPLAtof(pszValue));
+        break;
+    default:
+        const char *pszEncoding =
+            m_poDataBlock->GetProperty(iIndex)->GetEncoding();
+        if (pszEncoding) {
+            char *pszValueEnc =
+                CPLRecode(pszValue, pszEncoding, CPL_ENC_UTF8);
+            m_propertyList[iIndex] = VFKProperty(pszValueEnc);
+            CPLFree(pszValueEnc);
         }
+        else {
+            m_propertyList[iIndex] = VFKProperty(pszValue);
+        }
+        break;
     }
-    return TRUE;
+
+    return true;
 }
 
 /*!
@@ -532,13 +520,12 @@ bool VFKFeature::SetProperty(int iIndex, const char *pszValue)
 
   \param iIndex property index
 
-  \return property value
-  \return NULL on error
+  \return property value, NULL on error
 */
 const VFKProperty *VFKFeature::GetProperty(int iIndex) const
 {
     if (iIndex < 0 || iIndex >= m_poDataBlock->GetPropertyCount() ||
-	size_t(iIndex) >= m_propertyList.size())
+        size_t(iIndex) >= m_propertyList.size())
         return NULL;
 
     const VFKProperty* poProperty = &m_propertyList[iIndex];
@@ -550,8 +537,7 @@ const VFKProperty *VFKFeature::GetProperty(int iIndex) const
 
   \param pszName property name
 
-  \return property value
-  \return NULL on error
+  \return property value, NULL on error
 */
 const VFKProperty *VFKFeature::GetProperty(const char *pszName) const
 {
@@ -563,25 +549,21 @@ const VFKProperty *VFKFeature::GetProperty(const char *pszName) const
 
   \todo Really needed?
 
-  \return TRUE on success
-  \return FALSE on failure
+  \return true on success, false on failure
 */
 bool VFKFeature::LoadGeometryPoint()
 {
-    double x, y;
-    int i_idxX, i_idxY;
-
-    i_idxY = m_poDataBlock->GetPropertyIndex("SOURADNICE_Y");
-    i_idxX = m_poDataBlock->GetPropertyIndex("SOURADNICE_X");
+    const int i_idxY = m_poDataBlock->GetPropertyIndex("SOURADNICE_Y");
+    const int i_idxX = m_poDataBlock->GetPropertyIndex("SOURADNICE_X");
     if (i_idxY < 0 || i_idxX < 0)
-        return FALSE;
+        return false;
 
-    x = -1.0 * GetProperty(i_idxY)->GetValueD();
-    y = -1.0 * GetProperty(i_idxX)->GetValueD();
+    const double x = -1.0 * GetProperty(i_idxY)->GetValueD();
+    const double y = -1.0 * GetProperty(i_idxX)->GetValueD();
     OGRPoint pt(x, y);
     SetGeometry(&pt);
 
-    return TRUE;
+    return true;
 }
 
 /*!
@@ -589,39 +571,34 @@ bool VFKFeature::LoadGeometryPoint()
 
   \todo Really needed?
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool VFKFeature::LoadGeometryLineStringSBP()
 {
-    int id, idxId, idxBp_Id, idxPCB, ipcb;
-
-    VFKDataBlock *poDataBlockPoints;
-    VFKFeature   *poPoint, *poLine;
-
-    OGRLineString OGRLine;
-
-    poDataBlockPoints = (VFKDataBlock *) m_poDataBlock->GetReader()->GetDataBlock("SOBR");
+    VFKDataBlock *poDataBlockPoints =
+        (VFKDataBlock *) m_poDataBlock->GetReader()->GetDataBlock("SOBR");
     if (!poDataBlockPoints)
-        return FALSE;
+        return false;
 
-    idxId    = poDataBlockPoints->GetPropertyIndex("ID");
-    idxBp_Id = m_poDataBlock->GetPropertyIndex("BP_ID");
-    idxPCB   = m_poDataBlock->GetPropertyIndex("PORADOVE_CISLO_BODU");
+    const int idxId = poDataBlockPoints->GetPropertyIndex("ID");
+    const int idxBp_Id = m_poDataBlock->GetPropertyIndex("BP_ID");
+    const int idxPCB = m_poDataBlock->GetPropertyIndex("PORADOVE_CISLO_BODU");
     if (idxId < 0 || idxBp_Id < 0 || idxPCB < 0)
         return false;
 
-    poLine = this;
+    VFKFeature *poLine = this;
+    OGRLineString OGRLine;
     while( true )
     {
-        id   = poLine->GetProperty(idxBp_Id)->GetValueI();
-        ipcb = poLine->GetProperty(idxPCB)->GetValueI();
+        const int id = poLine->GetProperty(idxBp_Id)->GetValueI();
+        const int ipcb = poLine->GetProperty(idxPCB)->GetValueI();
         if (OGRLine.getNumPoints() > 0 && ipcb == 1)
         {
             m_poDataBlock->GetPreviousFeature(); /* push back */
             break;
         }
 
-        poPoint = poDataBlockPoints->GetFeature(idxId, id);
+        VFKFeature *poPoint = poDataBlockPoints->GetFeature(idxId, id);
         if (!poPoint)
         {
             continue;
@@ -640,7 +617,7 @@ bool VFKFeature::LoadGeometryLineStringSBP()
     /* reset reading */
     poDataBlockPoints->ResetReading();
 
-    return TRUE;
+    return true;
 }
 
 /*!
@@ -648,32 +625,29 @@ bool VFKFeature::LoadGeometryLineStringSBP()
 
   \todo Really needed?
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool VFKFeature::LoadGeometryLineStringHP()
 {
-    int           id, idxId, idxHp_Id;
-    VFKDataBlock *poDataBlockLines;
-    VFKFeature   *poLine;
-
-    poDataBlockLines = (VFKDataBlock *) m_poDataBlock->GetReader()->GetDataBlock("SBP");
+    VFKDataBlock *poDataBlockLines =
+        (VFKDataBlock *) m_poDataBlock->GetReader()->GetDataBlock("SBP");
     if (!poDataBlockLines)
-        return FALSE;
+        return false;
 
-    idxId    = m_poDataBlock->GetPropertyIndex("ID");
-    idxHp_Id = poDataBlockLines->GetPropertyIndex("HP_ID");
+    const int idxId = m_poDataBlock->GetPropertyIndex("ID");
+    const int idxHp_Id = poDataBlockLines->GetPropertyIndex("HP_ID");
     if (idxId < 0 || idxHp_Id < 0)
-        return FALSE;
+        return false;
 
-    id = GetProperty(idxId)->GetValueI();
-    poLine = poDataBlockLines->GetFeature(idxHp_Id, id);
+    const int id = GetProperty(idxId)->GetValueI();
+    VFKFeature *poLine = poDataBlockLines->GetFeature(idxHp_Id, id);
     if (!poLine || !poLine->GetGeometry())
-        return FALSE;
+        return false;
 
     SetGeometry(poLine->GetGeometry());
     poDataBlockLines->ResetReading();
 
-    return TRUE;
+    return true;
 }
 
 /*!
@@ -681,17 +655,20 @@ bool VFKFeature::LoadGeometryLineStringHP()
 
   \todo Implement (really needed?)
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool VFKFeature::LoadGeometryPolygon()
 {
-    return FALSE;
+    return false;
 }
-OGRErr VFKFeature::LoadProperties(OGRFeature *poFeature)
+
+OGRErr VFKFeature::LoadProperties( OGRFeature *poFeature )
 {
-    for (int iField = 0; iField < m_poDataBlock->GetPropertyCount(); iField++) {
-        if (GetProperty(iField)->IsNull())
+    for( int iField = 0; iField < m_poDataBlock->GetPropertyCount(); iField++ )
+    {
+        if( GetProperty(iField)->IsNull() )
             continue;
+
         OGRFieldType fType = poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType();
         if (fType == OFTInteger)
             poFeature->SetField(iField,
diff --git a/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp b/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
index 4b4cd21..1053c00 100644
--- a/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkfeaturesqlite.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vfkfeaturesqlite.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Feature definition (SQLite)
  * Purpose:  Implements VFKFeatureSQLite class.
@@ -35,6 +34,8 @@
 #include "cpl_conv.h"
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: vfkfeaturesqlite.cpp 37796 2017-03-19 19:18:10Z martinl $");
+
 /*!
   \brief VFKFeatureSQLite constructor (from DB)
 
@@ -42,13 +43,14 @@
 
   \param poDataBlock pointer to related IVFKDataBlock
 */
-VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock) : IVFKFeature(poDataBlock)
+VFKFeatureSQLite::VFKFeatureSQLite( IVFKDataBlock *poDataBlock ) :
+    IVFKFeature(poDataBlock),
+    // Starts at 1.
+    m_iRowId(static_cast<int>(poDataBlock->GetFeatureCount() + 1)),
+    m_hStmt(NULL)
 {
-    m_hStmt  = NULL;
-    m_iRowId = (int)m_poDataBlock->GetFeatureCount() + 1; /* starts at 1 */
-
-    /* set FID from DB */
-    SetFIDFromDB(); /* -> m_nFID */
+    // Set FID from DB.
+    SetFIDFromDB();  // -> m_nFID
 }
 
 /*!
@@ -58,11 +60,13 @@ VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock) : IVFKFeature(poD
   \param iRowId feature DB rowid (starts at 1)
   \param nFID feature id
 */
-VFKFeatureSQLite::VFKFeatureSQLite(IVFKDataBlock *poDataBlock, int iRowId, GIntBig nFID) : IVFKFeature(poDataBlock)
+VFKFeatureSQLite::VFKFeatureSQLite( IVFKDataBlock *poDataBlock, int iRowId,
+                                    GIntBig nFID) :
+    IVFKFeature(poDataBlock),
+    m_iRowId(iRowId),
+    m_hStmt(NULL)
 {
-    m_hStmt  = NULL;
-    m_iRowId = iRowId;
-    m_nFID   = nFID;
+    m_nFID = nFID;
 }
 
 /*!
@@ -112,18 +116,14 @@ void VFKFeatureSQLite::FinalizeSQL()
 */
 OGRErr VFKFeatureSQLite::ExecuteSQL(const char *pszSQLCommand)
 {
-    int rc;
-
-    sqlite3  *poDB;
-
     VFKReaderSQLite *poReader = (VFKReaderSQLite *) m_poDataBlock->GetReader();
-    poDB = poReader->m_poDB;
+    sqlite3  *poDB = poReader->m_poDB;
 
-    rc = sqlite3_prepare(poDB, pszSQLCommand, -1,
+    int rc = sqlite3_prepare_v2(poDB, pszSQLCommand, -1,
                          &m_hStmt, NULL);
     if (rc != SQLITE_OK) {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
+                 "In ExecuteSQL(): sqlite3_prepare_v2(%s):\n  %s",
                  pszSQLCommand, sqlite3_errmsg(poDB));
 
         if(m_hStmt != NULL) {
@@ -152,11 +152,14 @@ OGRErr VFKFeatureSQLite::ExecuteSQL(const char *pszSQLCommand)
 
   Read VFK feature from VFK file and insert it into DB
 */
-VFKFeatureSQLite::VFKFeatureSQLite(const VFKFeature *poVFKFeature) : IVFKFeature(poVFKFeature->m_poDataBlock)
+VFKFeatureSQLite::VFKFeatureSQLite( const VFKFeature *poVFKFeature ) :
+    IVFKFeature(poVFKFeature->m_poDataBlock),
+    // Starts at 1.
+    m_iRowId(static_cast<int>(
+        poVFKFeature->m_poDataBlock->GetFeatureCount() + 1)),
+    m_hStmt(NULL)
 {
-    m_nFID   = poVFKFeature->m_nFID;
-    m_hStmt  = NULL;
-    m_iRowId = (int)m_poDataBlock->GetFeatureCount() + 1; /* starts at 1 */
+    m_nFID = poVFKFeature->m_nFID;
 }
 
 /*!
@@ -164,11 +167,11 @@ VFKFeatureSQLite::VFKFeatureSQLite(const VFKFeature *poVFKFeature) : IVFKFeature
 
   \todo Implement (really needed?)
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool VFKFeatureSQLite::LoadGeometryPoint()
 {
-    return FALSE;
+    return false;
 }
 
 /*!
@@ -176,11 +179,11 @@ bool VFKFeatureSQLite::LoadGeometryPoint()
 
   \todo Implement (really needed?)
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool VFKFeatureSQLite::LoadGeometryLineStringSBP()
 {
-    return FALSE;
+    return false;
 }
 
 /*!
@@ -188,11 +191,11 @@ bool VFKFeatureSQLite::LoadGeometryLineStringSBP()
 
   \todo Implement (really needed?)
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool VFKFeatureSQLite::LoadGeometryLineStringHP()
 {
-    return FALSE;
+    return false;
 }
 
 /*!
@@ -200,11 +203,11 @@ bool VFKFeatureSQLite::LoadGeometryLineStringHP()
 
   \todo Implement (really needed?)
 
-  \return TRUE on success or FALSE on failure
+  \return true on success or false on failure
 */
 bool VFKFeatureSQLite::LoadGeometryPolygon()
 {
-    return FALSE;
+    return false;
 }
 
 /*!
@@ -224,18 +227,27 @@ OGRErr VFKFeatureSQLite::LoadProperties(OGRFeature *poFeature)
         return OGRERR_FAILURE;
 
     for (int iField = 0; iField < m_poDataBlock->GetPropertyCount(); iField++) {
-	if (sqlite3_column_type(m_hStmt, iField) == SQLITE_NULL) /* skip null values */
+        if (sqlite3_column_type(m_hStmt, iField) == SQLITE_NULL) /* skip null values */
             continue;
         OGRFieldType fType = poFeature->GetDefnRef()->GetFieldDefn(iField)->GetType();
-        if (fType == OFTInteger)
+        switch (fType) {
+        case OFTInteger:
             poFeature->SetField(iField,
                                 sqlite3_column_int(m_hStmt, iField));
-        else if (fType == OFTReal)
+            break;
+        case OFTInteger64:
+            poFeature->SetField(iField,
+                                sqlite3_column_int64(m_hStmt, iField));
+            break;
+        case OFTReal:
             poFeature->SetField(iField,
                                 sqlite3_column_double(m_hStmt, iField));
-        else
+            break;
+        default:
             poFeature->SetField(iField,
                                 (const char *) sqlite3_column_text(m_hStmt, iField));
+            break;
+        }
     }
 
     FinalizeSQL();
diff --git a/ogr/ogrsf_frmts/vfk/vfkproperty.cpp b/ogr/ogrsf_frmts/vfk/vfkproperty.cpp
index 159d9bd..b877c40 100644
--- a/ogr/ogrsf_frmts/vfk/vfkproperty.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkproperty.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vfkproperty.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Property definition
  * Purpose:  Implements VFKProperty class.
@@ -35,70 +34,87 @@
 #include "cpl_conv.h"
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: vfkproperty.cpp 37796 2017-03-19 19:18:10Z martinl $");
+
 /*!
   \brief Set VFK property (null)
 */
-VFKProperty::VFKProperty()
-    : m_bIsNull(TRUE), m_nValue(0), m_dValue(0.0)
-{
-}
+VFKProperty::VFKProperty() :
+    m_bIsNull(true),
+    m_iValue(0),
+    m_dValue(0.0)
+{}
 
 /*!
   \brief Set VFK property (integer)
 */
-VFKProperty::VFKProperty(int iValue)
-    : m_bIsNull(FALSE), m_nValue(iValue), m_dValue(0.0)
-{
-}
+VFKProperty::VFKProperty( int iValue ) :
+    m_bIsNull(false),
+    m_iValue(iValue),
+    m_dValue(0.0)
+{}
+
+/*!
+  \brief Set VFK property (big integer)
+*/
+VFKProperty::VFKProperty( GIntBig iValue ) :
+    m_bIsNull(false),
+    m_iValue(iValue),
+    m_dValue(0.0)
+{}
 
 /*!
   \brief Set VFK property (double)
 */
-VFKProperty::VFKProperty(double dValue)
-    : m_bIsNull(FALSE), m_nValue(0), m_dValue(dValue)
-{
-}
+VFKProperty::VFKProperty( double dValue ) :
+    m_bIsNull(false),
+    m_iValue(0),
+    m_dValue(dValue)
+{}
 
 /*!
   \brief Set VFK property (string)
 */
-VFKProperty::VFKProperty(const char *pszValue)
-    : m_bIsNull(FALSE), m_nValue(0), m_dValue(0.0), m_strValue(NULL != pszValue ? pszValue : "")
-{
-}
+VFKProperty::VFKProperty( const char *pszValue ) :
+    m_bIsNull(false),
+    m_iValue(0),
+    m_dValue(0.0),
+    m_strValue(NULL != pszValue ? pszValue : "")
+{}
 
 /*!
   \brief Set VFK property (string)
 */
-VFKProperty::VFKProperty(CPLString const& strValue)
-    : m_bIsNull(FALSE), m_nValue(0), m_dValue(0.0), m_strValue(strValue)
-{
-}
+VFKProperty::VFKProperty( CPLString const& strValue ) :
+    m_bIsNull(false),
+    m_iValue(0),
+    m_dValue(0.0),
+    m_strValue(strValue)
+{}
 
 /*!
   \brief VFK property destructor
 */
-VFKProperty::~VFKProperty()
-{
-}
+VFKProperty::~VFKProperty() {}
 
 /*!
   \brief Copy constructor.
 */
-VFKProperty::VFKProperty(VFKProperty const& other)
-    : m_bIsNull(other.m_bIsNull),
-      m_nValue(other.m_nValue), m_dValue(other.m_dValue), m_strValue(other.m_strValue)
-{
-}
+VFKProperty::VFKProperty( VFKProperty const& other ) :
+    m_bIsNull(other.m_bIsNull),
+    m_iValue(other.m_iValue),
+    m_dValue(other.m_dValue),
+    m_strValue(other.m_strValue)
+{}
 
 /*!
   \brief Assignment operator.
 */
-VFKProperty& VFKProperty::operator=(VFKProperty const& other)
+VFKProperty& VFKProperty::operator=( VFKProperty const& other )
 {
     if (&other != this) {
         m_bIsNull = other.m_bIsNull;
-        m_nValue = other.m_nValue;
+        m_iValue = other.m_iValue;
         m_dValue = other.m_dValue;
         m_strValue = other.m_strValue;
     }
@@ -108,19 +124,17 @@ VFKProperty& VFKProperty::operator=(VFKProperty const& other)
 /*!
   \brief Get string property
 
-  \param escape TRUE to escape characters for SQL
+  \param escape true to escape characters for SQL
 
   \return string buffer
 */
-const char *VFKProperty::GetValueS(bool escape) const
+const char *VFKProperty::GetValueS( bool escape ) const
 {
-    size_t ipos;
-
-    if (!escape)
+    if( !escape )
         return m_strValue.c_str();
 
     CPLString strValue(m_strValue);
-    ipos = 0;
+    size_t ipos = 0;
     while (std::string::npos != (ipos = strValue.find("'", ipos))) {
         strValue.replace(ipos, 1, "\'\'", 2);
         ipos += 2;
diff --git a/ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp b/ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp
index 8f35f4f..f0a8f9c 100644
--- a/ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkpropertydefn.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vfkpropertydefn.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader - Data block property definition
  * Purpose:  Implements VFKPropertyDefn class.
@@ -35,39 +34,37 @@
 #include "cpl_conv.h"
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: vfkpropertydefn.cpp 37796 2017-03-19 19:18:10Z martinl $");
+
 /*!
   \brief VFKPropertyDefn constructor
 
   \param pszName property name
   \param pszType property type (original, string)
-  \param bLatin2 TRUE for "ISO-8859-2" otherwise "WINDOWS-1250" is used (only for "text" type)
+  \param bLatin2 true for "ISO-8859-2" otherwise "WINDOWS-1250" is used (only for "text" type)
 */
-VFKPropertyDefn::VFKPropertyDefn(const char *pszName, const char *pszType,
-                                 bool bLatin2)
+VFKPropertyDefn::VFKPropertyDefn( const char *pszName, const char *pszType,
+                                  bool bLatin2 ) :
+    m_pszName(CPLStrdup(pszName)),
+    m_pszType(CPLStrdup(pszType)),
+    m_pszEncoding(NULL),
+    m_nWidth(0),
+    m_nPrecision(0)
 {
-    char *poChar, *poWidth, *pszWidth;
-    int   nLength;
-
-    m_pszName = CPLStrdup(pszName);
-    m_pszType = CPLStrdup(pszType);
-
-    poWidth = poChar = m_pszType + 1;
-    for (nLength = 0; *poChar && *poChar != '.'; nLength++, poChar++)
+    char *poWidth = m_pszType + 1;
+    char *poChar = m_pszType + 1;
+    int nLength = 0;  // Used after for.
+    for( ; *poChar && *poChar != '.'; nLength++, poChar++)
         ;
 
-    /* width */
-    pszWidth = (char *) CPLMalloc(nLength+1);
+    char *pszWidth = static_cast<char *>(CPLMalloc(nLength + 1));
     strncpy(pszWidth, poWidth, nLength);
     pszWidth[nLength] = '\0';
 
-    m_nWidth  = atoi(pszWidth);
+    m_nWidth = atoi(pszWidth);
     CPLFree(pszWidth);
 
-    /* precision */
-    m_nPrecision = 0;
-
-    /* type */
-    m_pszEncoding = NULL;
+    // Type.
     if (*m_pszType == 'N') {
         if (*poChar == '.') {
             m_eFType = OFTReal;
@@ -77,23 +74,23 @@ VFKPropertyDefn::VFKPropertyDefn(const char *pszName, const char *pszType,
             if (m_nWidth < 10)
                 m_eFType = OFTInteger;
             else {
-                m_eFType  = OFTString;
+                m_eFType = OFTInteger64;
             }
         }
     }
     else if (*m_pszType == 'T') {
-        /* string */
+        // String.
         m_eFType = OFTString;
         m_pszEncoding = bLatin2 ? CPLStrdup("ISO-8859-2") : CPLStrdup("WINDOWS-1250");
     }
     else if (*m_pszType == 'D') {
-        /* date */
-        /* m_eFType = OFTDateTime; */
+        // Date.
+        // m_eFType = OFTDateTime;
         m_eFType = OFTString;
         m_nWidth = 25;
     }
     else {
-        /* unknown - string */
+        // Unknown - string.
         m_eFType = OFTString;
         m_pszEncoding = bLatin2 ? CPLStrdup("ISO-8859-2") : CPLStrdup("WINDOWS-1250");
     }
@@ -106,7 +103,7 @@ VFKPropertyDefn::~VFKPropertyDefn()
 {
     CPLFree(m_pszName);
     CPLFree(m_pszType);
-    if (m_pszEncoding)
+    if( m_pszEncoding )
         CPLFree(m_pszEncoding);
 }
 
@@ -120,13 +117,12 @@ CPLString VFKPropertyDefn::GetTypeSQL() const
     switch(m_eFType) {
     case OFTInteger:
         return CPLString("integer");
+    case OFTInteger64:
+        return CPLString("bigint");
     case OFTReal:
         return CPLString("real");
     case OFTString:
-        if (m_pszType[0] == 'N')
-            return CPLString("integer");
-        else
-            return CPLString("text");
+        return CPLString("text");
     default:
         return CPLString("text");
     }
diff --git a/ogr/ogrsf_frmts/vfk/vfkreader.cpp b/ogr/ogrsf_frmts/vfk/vfkreader.cpp
index 2429e80..f6376d6 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreader.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkreader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vfkreader.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  VFK Reader
  * Purpose:  Implements VFKReader class.
@@ -30,6 +29,8 @@
  * SOFTWARE.
  ****************************************************************************/
 
+#include <sys/stat.h>
+
 #include "vfkreader.h"
 #include "vfkreaderp.h"
 
@@ -37,11 +38,9 @@
 #include "cpl_error.h"
 #include "cpl_string.h"
 
-#define SUPPORT_GEOMETRY
+#include "ogr_geometry.h"
 
-#ifdef SUPPORT_GEOMETRY
-#  include "ogr_geometry.h"
-#endif
+CPL_CVSID("$Id: vfkreader.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 static char *GetDataBlockName(const char *);
 
@@ -65,16 +64,26 @@ IVFKReader *CreateVFKReader(const char *pszFilename)
 /*!
   \brief VFKReader constructor
 */
-VFKReader::VFKReader(const char *pszFilename)
+VFKReader::VFKReader( const char *pszFilename ) :
+    m_bLatin2(true),  // Encoding ISO-8859-2 or WINDOWS-1250.
+    m_poFD(NULL),
+    m_pszFilename(CPLStrdup(pszFilename)),
+    m_poFStat((VSIStatBuf*) CPLMalloc(sizeof(VSIStatBuf))),
+    // VFK are provided in two forms - stative and amendment data.
+    m_bAmendment(false),
+    m_nDataBlockCount(0),
+    m_papoDataBlock(NULL)
 {
-    m_nDataBlockCount = 0;
-    m_papoDataBlock   = NULL;
-    m_bLatin2         = TRUE; /* encoding ISO-8859-2 or WINDOWS-1250 */
-
-    /* open VFK file for reading */
+    // Open VFK file for reading.
     CPLAssert(NULL != pszFilename);
-    m_pszFilename = CPLStrdup(pszFilename);
-    m_poFD = VSIFOpen(m_pszFilename, "rb");
+
+    if (CPLStat(pszFilename, m_poFStat) != 0 ||
+        !VSI_ISREG(m_poFStat->st_mode)) {
+      CPLError(CE_Failure, CPLE_OpenFailed,
+               "%s is not a regular file.", m_pszFilename);
+    }
+
+    m_poFD = VSIFOpenL(m_pszFilename, "rb");
     if (m_poFD == NULL) {
         CPLError(CE_Failure, CPLE_OpenFailed,
                  "Failed to open file %s.", m_pszFilename);
@@ -89,7 +98,8 @@ VFKReader::~VFKReader()
     CPLFree(m_pszFilename);
 
     if (m_poFD)
-        VSIFClose(m_poFD);
+        VSIFCloseL(m_poFD);
+    CPLFree(m_poFStat);
 
     /* clear data blocks */
     for (int i = 0; i < m_nDataBlockCount; i++)
@@ -99,17 +109,16 @@ VFKReader::~VFKReader()
 
 char *GetDataBlockName(const char *pszLine)
 {
-    int         n;
-    const char *pszLineChar;
-    char       *pszBlockName;
+    int n = 0; // Used after for.
+    const char *pszLineChar = pszLine + 2;
 
-    for (pszLineChar = pszLine + 2, n = 0; *pszLineChar != '\0' && *pszLineChar != ';'; pszLineChar++, n++)
+    for( ; *pszLineChar != '\0' && *pszLineChar != ';'; pszLineChar++, n++)
         ;
 
-    if (*pszLineChar == '\0')
+    if( *pszLineChar == '\0' )
         return NULL;
 
-    pszBlockName = (char *) CPLMalloc(n + 1);
+    char *pszBlockName = (char *) CPLMalloc(n + 1);
     strncpy(pszBlockName, pszLine + 2, n);
     pszBlockName[n] = '\0';
 
@@ -123,23 +132,20 @@ char *GetDataBlockName(const char *pszLine)
 
   \return a NULL terminated string which should be freed with CPLFree().
 */
-char *VFKReader::ReadLine(bool bRecode)
+char *VFKReader::ReadLine( bool bRecode )
 {
-    const char *pszRawLine;
-    char *pszLine;
-
-    pszRawLine = CPLReadLine(m_poFD);
+    const char *pszRawLine = CPLReadLine2L(m_poFD, 100 * 1024, NULL);
     if (pszRawLine == NULL)
         return NULL;
 
-    if (bRecode)
-        pszLine = CPLRecode(pszRawLine,
-                            m_bLatin2 ? "ISO-8859-2" : "WINDOWS-1250",
-                            CPL_ENC_UTF8);
-    else {
-        pszLine = (char *) CPLMalloc(strlen(pszRawLine) + 1);
-        strcpy(pszLine, pszRawLine);
-    }
+    if( bRecode )
+        return CPLRecode(pszRawLine,
+                         m_bLatin2 ? "ISO-8859-2" : "WINDOWS-1250",
+                         CPL_ENC_UTF8);
+
+    const size_t nLineLen = strlen(pszRawLine);
+    char *pszLine = (char *) CPLMalloc(nLineLen + 1);
+    memcpy(pszLine, pszRawLine, nLineLen + 1);
 
     return pszLine;
 }
@@ -153,15 +159,11 @@ char *VFKReader::ReadLine(bool bRecode)
 */
 int VFKReader::ReadDataBlocks()
 {
-    char       *pszLine, *pszBlockName;
-    bool        bInHeader;
-
-    IVFKDataBlock *poNewDataBlock;
-
     CPLAssert(NULL != m_pszFilename);
 
-    VSIFSeek(m_poFD, 0, SEEK_SET);
-    bInHeader = TRUE;
+    VSIFSeekL(m_poFD, 0, SEEK_SET);
+    bool bInHeader = true;
+    char *pszLine = NULL;
     while ((pszLine = ReadLine()) != NULL) {
         if (strlen(pszLine) < 2 || pszLine[0] != '&') {
             CPLFree(pszLine);
@@ -169,23 +171,34 @@ int VFKReader::ReadDataBlocks()
         }
 
         if (pszLine[1] == 'B') {
-            if (bInHeader)
-                bInHeader = FALSE; /* 'B' record closes the header section */
+            if( bInHeader )
+                bInHeader = false; /* 'B' record closes the header section */
 
-            pszBlockName = GetDataBlockName(pszLine);
+            char *pszBlockName = GetDataBlockName(pszLine);
             if (pszBlockName == NULL) {
                 CPLError(CE_Failure, CPLE_NotSupported,
                          "Corrupted data - line\n%s\n", pszLine);
                 CPLFree(pszLine);
                 return -1;
             }
-            poNewDataBlock = (IVFKDataBlock *) CreateDataBlock(pszBlockName);
+
+            /* skip duplicated data blocks (when reading multiple files into single DB)  */
+            if( !GetDataBlock(pszBlockName) )
+            {
+                IVFKDataBlock *poNewDataBlock =
+                    (IVFKDataBlock *) CreateDataBlock(pszBlockName);
+                poNewDataBlock->SetGeometryType();
+                poNewDataBlock->SetProperties(pszLine); /* TODO: check consistency on property level */
+                AddDataBlock(poNewDataBlock, pszLine);
+            }
             CPLFree(pszBlockName);
-            poNewDataBlock->SetGeometryType();
-            poNewDataBlock->SetProperties(pszLine);
-            AddDataBlock(poNewDataBlock, pszLine);
         }
         else if (pszLine[1] == 'H') {
+            /* check for amendment file */
+            if (EQUAL(pszLine, "&HZMENY;1")) {
+                m_bAmendment = true;
+            }
+
             /* header - metadata */
             AddInfo(pszLine);
         }
@@ -194,7 +207,8 @@ int VFKReader::ReadDataBlocks()
             CPLFree(pszLine);
             break;
         }
-        else if (bInHeader && pszLine[1] == 'D') {
+        else if( bInHeader && pszLine[1] == 'D' )
+        {
             /* process 'D' records in the header section */
             AddInfo(pszLine);
         }
@@ -205,7 +219,6 @@ int VFKReader::ReadDataBlocks()
     return m_nDataBlockCount;
 }
 
-
 /*!
   \brief Load data records (&D)
 
@@ -222,18 +235,20 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
 
     if (poDataBlock) {  /* read only given data block */
         poDataBlockCurrent = poDataBlock;
-        poDataBlockCurrent->SetFeatureCount(0);
+        if (poDataBlockCurrent->GetFeatureCount(FALSE) < 0)
+            poDataBlockCurrent->SetFeatureCount(0);
         pszName = poDataBlockCurrent->GetName();
     }
     else {              /* read all data blocks */
         for (int iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
             poDataBlockCurrent = GetDataBlock(iDataBlock);
-            poDataBlockCurrent->SetFeatureCount(0);
+            if (poDataBlockCurrent->GetFeatureCount(FALSE) < 0)
+                poDataBlockCurrent->SetFeatureCount(0);
         }
         poDataBlockCurrent = NULL;
     }
 
-    VSIFSeek(m_poFD, 0, SEEK_SET);
+    VSIFSeekL(m_poFD, 0, SEEK_SET);
 
     int iLine = 0;
     int nSkipped = 0;
@@ -241,11 +256,11 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
     int nRecords = 0;
     bool bInHeader = true;
     CPLString osBlockNameLast;
-    char *pszLine;
+    char *pszLine = NULL;
 
     while ((pszLine = ReadLine()) != NULL) {
         iLine++;
-        int nLength = static_cast<int>(strlen(pszLine));
+        size_t nLength = strlen(pszLine);
         if (nLength < 2) {
             CPLFree(pszLine);
             continue;
@@ -285,12 +300,22 @@ int VFKReader::ReadDataRecords(IVFKDataBlock *poDataBlock)
                         osMultiLine.erase(osMultiLine.size() - 1);
 
                         CPLFree(pszLine);
+                        if( osMultiLine.size() > 100U * 1024U * 1024U )
+                        {
+                            CPLFree(pszBlockName);
+                            return -1;
+                        }
                     }
                     if( pszLine )
                         osMultiLine += pszLine;
                     CPLFree(pszLine);
 
-                    nLength = static_cast<int>(osMultiLine.size());
+                    nLength = osMultiLine.size();
+                    if( nLength > 100U * 1024U * 1024U )
+                    {
+                        CPLFree(pszBlockName);
+                        return -1;
+                    }
                     pszLine = (char *) CPLMalloc(nLength + 1);
                     strncpy(pszLine, osMultiLine.c_str(), nLength);
                     pszLine[nLength] = '\0';
@@ -439,9 +464,7 @@ IVFKDataBlock *VFKReader::GetDataBlock(const char *pszName) const
 */
 int VFKReader::LoadGeometry()
 {
-    long int nfeatures;
-
-    nfeatures = 0;
+    long int nfeatures = 0;
     for (int i = 0; i < m_nDataBlockCount; i++) {
         nfeatures += m_papoDataBlock[i]->LoadGeometry();
     }
@@ -458,11 +481,7 @@ int VFKReader::LoadGeometry()
 */
 void VFKReader::AddInfo(const char *pszLine)
 {
-    int         nOffset;
-    if (pszLine[1] == 'H')
-        nOffset = 2;
-    else
-        nOffset = 1; /* &DKATUZE */
+    const int nOffset = pszLine[1] == 'H' ? 2 : 1;  // &DKATUZE
 
     const char *poKey = pszLine + nOffset; /* &H */
     const char *poChar = poKey;
@@ -507,7 +526,7 @@ void VFKReader::AddInfo(const char *pszLine)
     /* recode values, assuming Latin2 */
     if (EQUAL(pszKey, "CODEPAGE")) {
         if (!EQUAL(pszValue, "WE8ISO8859P2"))
-            m_bLatin2 = FALSE;
+            m_bLatin2 = false;
     }
 
     char *pszValueEnc = CPLRecode(pszValue,
diff --git a/ogr/ogrsf_frmts/vfk/vfkreader.h b/ogr/ogrsf_frmts/vfk/vfkreader.h
index 648294a..c8d6079 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreader.h
+++ b/ogr/ogrsf_frmts/vfk/vfkreader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkreader.h 32177 2015-12-14 07:25:30Z goatbar $
+ * $Id: vfkreader.h 37796 2017-03-19 19:18:10Z martinl $
  *
  * Project:  VFK Reader
  * Purpose:  Public Declarations for OGR free VFK Reader code.
@@ -54,9 +54,10 @@ typedef std::vector<VFKFeatureSQLite *> VFKFeatureSQLiteList;
 #define FID_COLUMN   "ogr_fid"
 #define GEOM_COLUMN  "geometry"
 
-#define VFK_DB_HEADER   "vfk_header"
-#define VFK_DB_TABLE    "vfk_tables"
-
+#define VFK_DB_HEADER_TABLE      "vfk_header"
+#define VFK_DB_TABLE             "vfk_tables"
+#define VFK_DB_GEOMETRY_TABLE    "geometry_columns"
+#define VFK_DB_SPATIAL_REF_TABLE "spatial_ref_sys"
 
 enum RecordType { RecordValid, RecordSkipped, RecordDuplicated };
 
@@ -68,13 +69,14 @@ class VFKProperty
 private:
     bool                    m_bIsNull;
 
-    int                     m_nValue;
+    GIntBig                 m_iValue;
     double                  m_dValue;
     CPLString               m_strValue;
 
 public:
     VFKProperty();
     explicit VFKProperty(int);
+    explicit VFKProperty(GIntBig);
     explicit VFKProperty(double);
     explicit VFKProperty(const char*);
     explicit VFKProperty(CPLString const&);
@@ -83,10 +85,11 @@ public:
     VFKProperty(VFKProperty const& other);
     VFKProperty& operator=(VFKProperty const& other);
 
-    bool                    IsNull()    const { return m_bIsNull; }
-    int                     GetValueI() const { return m_nValue; }
-    double                  GetValueD() const { return m_dValue; }
-    const char             *GetValueS(bool = FALSE) const;
+    bool                    IsNull()      const { return m_bIsNull; }
+    int                     GetValueI()   const { return static_cast<int> (m_iValue); }
+    GIntBig                 GetValueI64() const { return m_iValue; }
+    double                  GetValueD()   const { return m_dValue; }
+    const char             *GetValueS( bool = false ) const;
 };
 
 /************************************************************************/
@@ -108,7 +111,7 @@ protected:
     virtual bool         LoadGeometryPolygon() = 0;
 
 public:
-    IVFKFeature(IVFKDataBlock *);
+    explicit IVFKFeature(IVFKDataBlock *);
     virtual ~IVFKFeature();
 
     GIntBig              GetFID() const { return m_nFID; }
@@ -140,10 +143,10 @@ private:
 
     friend class         VFKFeatureSQLite;
 
-    bool                 LoadGeometryPoint();
-    bool                 LoadGeometryLineStringSBP();
-    bool                 LoadGeometryLineStringHP();
-    bool                 LoadGeometryPolygon();
+    bool                 LoadGeometryPoint() override;
+    bool                 LoadGeometryLineStringSBP() override;
+    bool                 LoadGeometryLineStringHP() override;
+    bool                 LoadGeometryPolygon() override;
 
 public:
     VFKFeature(IVFKDataBlock *, GIntBig);
@@ -152,7 +155,7 @@ public:
     const VFKProperty   *GetProperty(int) const;
     const VFKProperty   *GetProperty(const char *) const;
 
-    OGRErr               LoadProperties(OGRFeature *);
+    OGRErr               LoadProperties(OGRFeature *) override;
 
     bool                 AppendLineToRing(int, const OGRLineString *);
 };
@@ -166,21 +169,21 @@ private:
     int                  m_iRowId;           /* rowid in DB */
     sqlite3_stmt        *m_hStmt;
 
-    bool                 LoadGeometryPoint();
-    bool                 LoadGeometryLineStringSBP();
-    bool                 LoadGeometryLineStringHP();
-    bool                 LoadGeometryPolygon();
+    bool                 LoadGeometryPoint() override;
+    bool                 LoadGeometryLineStringSBP() override;
+    bool                 LoadGeometryLineStringHP() override;
+    bool                 LoadGeometryPolygon() override;
 
     OGRErr               SetFIDFromDB();
     OGRErr               ExecuteSQL(const char *);
     void                 FinalizeSQL();
 
 public:
-    VFKFeatureSQLite(IVFKDataBlock *);
+    explicit VFKFeatureSQLite(IVFKDataBlock *);
     VFKFeatureSQLite(IVFKDataBlock *, int, GIntBig);
-    VFKFeatureSQLite(const VFKFeature *);
+    explicit VFKFeatureSQLite(const VFKFeature *);
 
-    OGRErr               LoadProperties(OGRFeature *);
+    OGRErr               LoadProperties(OGRFeature *) override;
     void                 SetRowId(int);
 };
 
@@ -208,7 +211,6 @@ public:
     int               GetPrecision() const { return m_nPrecision;  }
     OGRFieldType      GetType() const  { return m_eFType;  }
     CPLString         GetTypeSQL() const;
-    GBool             IsIntBig() const { return m_pszType[0] == 'N'; }
     const char       *GetEncoding() const { return  m_pszEncoding; }
 };
 
@@ -243,7 +245,9 @@ protected:
 
     GIntBig            m_nRecordCount[3];
 
-    bool               AppendLineToRing(PointListArray *, const OGRLineString *, bool, bool = FALSE);
+    bool               AppendLineToRing( PointListArray *,
+                                         const OGRLineString *,
+                                         bool, bool = false );
     int                LoadData();
 
     virtual int        LoadGeometryPoint() = 0;
@@ -262,8 +266,8 @@ public:
     void               SetProperties(const char *);
     int                GetPropertyIndex(const char *) const;
 
-    GIntBig            GetFeatureCount();
-    void               SetFeatureCount(int, bool = FALSE);
+    GIntBig            GetFeatureCount( bool = true);
+    void               SetFeatureCount( int, bool = false );
     IVFKFeature       *GetFeatureByIndex(int) const;
     IVFKFeature       *GetFeature(GIntBig);
     void               AddFeature(IVFKFeature *);
@@ -291,10 +295,10 @@ public:
 class VFKDataBlock : public IVFKDataBlock
 {
 private:
-    int                LoadGeometryPoint();
-    int                LoadGeometryLineStringSBP();
-    int                LoadGeometryLineStringHP();
-    int                LoadGeometryPolygon();
+    int                LoadGeometryPoint() override;
+    int                LoadGeometryLineStringSBP() override;
+    int                LoadGeometryLineStringHP() override;
+    int                LoadGeometryPolygon() override;
 
 public:
     VFKDataBlock(const char *pszName, const IVFKReader *poReader) : IVFKDataBlock(pszName, poReader) {}
@@ -316,15 +320,15 @@ private:
                                                bool&, const char *,
                                                std::vector<int>&, int&);
 
-    int                  LoadGeometryPoint();
-    int                  LoadGeometryLineStringSBP();
-    int                  LoadGeometryLineStringHP();
-    int                  LoadGeometryPolygon();
+    int                  LoadGeometryPoint() override;
+    int                  LoadGeometryLineStringSBP() override;
+    int                  LoadGeometryLineStringHP() override;
+    int                  LoadGeometryPolygon() override;
 
     bool                 LoadGeometryFromDB();
     OGRErr               SaveGeometryToDB(const OGRGeometry *, int);
 
-    bool                 IsRingClosed(const OGRLinearRing *);
+    static bool                 IsRingClosed(const OGRLinearRing *);
     void                 UpdateVfkBlocks(int);
     void                 UpdateFID(GIntBig, std::vector<int>);
 
@@ -333,9 +337,13 @@ public:
 
     const char          *GetKey() const;
     IVFKFeature         *GetFeature(GIntBig);
-    VFKFeatureSQLite    *GetFeature(const char *, GUIntBig, bool = FALSE);
-    VFKFeatureSQLite    *GetFeature(const char **, GUIntBig *, int, bool = FALSE);
+    VFKFeatureSQLite    *GetFeature( const char *, GUIntBig, bool = false );
+    VFKFeatureSQLite    *GetFeature( const char **, GUIntBig *, int,
+                                     bool = false);
     VFKFeatureSQLiteList GetFeatures(const char **, GUIntBig *, int);
+
+    int                  GetGeometrySQLType() const;
+
 };
 
 /************************************************************************/
@@ -357,6 +365,7 @@ public:
     virtual bool           IsLatin2() const = 0;
     virtual bool           IsSpatial() const = 0;
     virtual bool           IsPreProcessed() const = 0;
+    virtual bool           IsValid() const = 0;
     virtual int            ReadDataBlocks() = 0;
     virtual int            ReadDataRecords(IVFKDataBlock * = NULL) = 0;
     virtual int            LoadGeometry() = 0;
diff --git a/ogr/ogrsf_frmts/vfk/vfkreaderp.h b/ogr/ogrsf_frmts/vfk/vfkreaderp.h
index 632a96f..bfadf26 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreaderp.h
+++ b/ogr/ogrsf_frmts/vfk/vfkreaderp.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: vfkreaderp.h 33713 2016-03-12 17:41:57Z goatbar $
+ * $Id: vfkreaderp.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  VFK Reader
  * Purpose:  Private Declarations for OGR free VFK Reader code.
@@ -50,39 +50,42 @@ class VFKReader : public IVFKReader
 private:
     bool           m_bLatin2;
 
-    FILE          *m_poFD;
-    char          *ReadLine(bool = FALSE);
+    VSILFILE      *m_poFD;
+    char          *ReadLine( bool = false );
 
-    void          AddInfo(const char *);
+    void          AddInfo(const char *) override;
 
 protected:
     char           *m_pszFilename;
+    VSIStatBuf     *m_poFStat;
+    bool            m_bAmendment;
     int             m_nDataBlockCount;
     IVFKDataBlock **m_papoDataBlock;
 
-    IVFKDataBlock  *CreateDataBlock(const char *);
-    void            AddDataBlock(IVFKDataBlock *, const char *);
-    OGRErr          AddFeature(IVFKDataBlock *, VFKFeature *);
+    IVFKDataBlock  *CreateDataBlock(const char *) override;
+    void            AddDataBlock(IVFKDataBlock *, const char *) override;
+    virtual OGRErr          AddFeature(IVFKDataBlock *, VFKFeature *) override;
 
-    /* metadata */
+    // Metadata.
     std::map<CPLString, CPLString> poInfo;
 
 public:
-    VFKReader(const char *);
+    explicit VFKReader( const char *pszFilename );
     virtual ~VFKReader();
 
-    bool           IsLatin2() const { return m_bLatin2; }
-    bool           IsSpatial() const { return FALSE; }
-    bool           IsPreProcessed() const { return FALSE; }
-    int            ReadDataBlocks();
-    int            ReadDataRecords(IVFKDataBlock * = NULL);
-    int            LoadGeometry();
+    bool           IsLatin2() const override { return m_bLatin2; }
+    bool           IsSpatial() const override { return false; }
+    bool           IsPreProcessed() const override { return false; }
+    bool           IsValid() const override { return true; }
+    int            ReadDataBlocks() override;
+    int            ReadDataRecords(IVFKDataBlock * = NULL) override;
+    int            LoadGeometry() override;
 
-    int            GetDataBlockCount() const { return m_nDataBlockCount; }
-    IVFKDataBlock *GetDataBlock(int) const;
-    IVFKDataBlock *GetDataBlock(const char *) const;
+    int            GetDataBlockCount() const override { return m_nDataBlockCount; }
+    IVFKDataBlock *GetDataBlock(int) const override;
+    IVFKDataBlock *GetDataBlock(const char *) const override;
 
-    const char    *GetInfo(const char *);
+    const char    *GetInfo(const char *) override;
 };
 
 /************************************************************************/
@@ -96,27 +99,29 @@ private:
     sqlite3       *m_poDB;
     bool           m_bSpatial;
     bool           m_bNewDb;
+    bool           m_bDbSource;
 
-    IVFKDataBlock *CreateDataBlock(const char *);
-    void           AddDataBlock(IVFKDataBlock *, const char *);
-    OGRErr         AddFeature(IVFKDataBlock *, VFKFeature *);
+    IVFKDataBlock *CreateDataBlock(const char *) override;
+    void           AddDataBlock(IVFKDataBlock *, const char *) override;
+    OGRErr         AddFeature(IVFKDataBlock *, VFKFeature *) override;
 
     void           StoreInfo2DB();
 
-    void           CreateIndex(const char *, const char *, const char *, bool = TRUE);
+    void           CreateIndex(const char *, const char *, const char *, bool = true);
 
     friend class   VFKFeatureSQLite;
 public:
-    VFKReaderSQLite(const char *);
+    explicit VFKReaderSQLite(const char *);
     virtual ~VFKReaderSQLite();
 
-    bool          IsSpatial() const { return m_bSpatial; }
-    bool          IsPreProcessed() const { return !m_bNewDb; }
-    int           ReadDataBlocks();
-    int           ReadDataRecords(IVFKDataBlock * = NULL);
+    bool          IsSpatial() const override { return m_bSpatial; }
+    bool          IsPreProcessed() const override { return !m_bNewDb; }
+    bool          IsValid() const override { return m_poDB != NULL; }
+    int           ReadDataBlocks() override;
+    int           ReadDataRecords(IVFKDataBlock * = NULL) override;
 
     sqlite3_stmt *PrepareStatement(const char *);
-    OGRErr        ExecuteSQL(const char *, bool = FALSE);
+    OGRErr        ExecuteSQL( const char *, bool = false );
     OGRErr        ExecuteSQL(sqlite3_stmt *);
 };
 
diff --git a/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp b/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp
index e72a5b2..9be44ce 100644
--- a/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp
+++ b/ogr/ogrsf_frmts/vfk/vfkreadersqlite.cpp
@@ -1,13 +1,12 @@
 /******************************************************************************
- * $Id: vfkreadersqlite.cpp 34258 2016-05-23 11:49:11Z martinl $
  *
  * Project:  VFK Reader (SQLite)
  * Purpose:  Implements VFKReaderSQLite class.
  * Author:   Martin Landa, landa.martin gmail.com
  *
  ******************************************************************************
- * Copyright (c) 2012-2014, Martin Landa <landa.martin gmail.com>
- * Copyright (c) 2012-2014, Even Rouault <even dot rouault at mines-paris dot org>
+ * Copyright (c) 2012-2016, Martin Landa <landa.martin gmail.com>
+ * Copyright (c) 2012-2016, Even Rouault <even dot rouault at mines-paris dot org>
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -40,95 +39,136 @@
 
 #include <cstring>
 
-#define SUPPORT_GEOMETRY
+#include "ogr_geometry.h"
 
-#ifdef SUPPORT_GEOMETRY
-#  include "ogr_geometry.h"
-#endif
+CPL_CVSID("$Id: vfkreadersqlite.cpp 37796 2017-03-19 19:18:10Z martinl $");
 
 /*!
   \brief VFKReaderSQLite constructor
 */
-VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilename)
+VFKReaderSQLite::VFKReaderSQLite( const char *pszFileName ) :
+    VFKReader(pszFileName),
+    m_pszDBname(NULL),
+    m_poDB(NULL),
+    // True - build geometry from DB
+    // False - store also geometry in DB
+    m_bSpatial(CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_SPATIAL", "YES"))),
+    m_bNewDb(false),
+    m_bDbSource(false)
 {
-    const char *pszDbNameConf;
-    CPLString   osDbName;
-    CPLString   osCommand;
-    VSIStatBufL sStatBufDb, sStatBufVfk;
-
-    /* open tmp SQLite DB (re-use DB file if already exists) */
-    pszDbNameConf = CPLGetConfigOption("OGR_VFK_DB_NAME", NULL);
-    if (pszDbNameConf) {
-	osDbName = pszDbNameConf;
+    size_t nLen = 0;
+    VSIStatBufL sStatBufDb;
+    {
+        GDALOpenInfo *poOpenInfo = new GDALOpenInfo(pszFileName, GA_ReadOnly);
+        m_bDbSource = poOpenInfo->nHeaderBytes >= 16 &&
+            STARTS_WITH((const char*)poOpenInfo->pabyHeader, "SQLite format 3");
+        delete poOpenInfo;
     }
-    else {
-	osDbName = CPLResetExtension(m_pszFilename, "db");
+
+    const char *pszDbNameConf = CPLGetConfigOption("OGR_VFK_DB_NAME", NULL);
+    CPLString osDbName;
+
+    if( !m_bDbSource )
+    {
+        m_bNewDb = true;
+
+        /* open tmp SQLite DB (re-use DB file if already exists) */
+        if (pszDbNameConf) {
+            osDbName = pszDbNameConf;
+        }
+        else
+        {
+            osDbName = CPLResetExtension(m_pszFilename, "db");
+        }
+        nLen = osDbName.length();
+        if( nLen > 2048 )
+        {
+            nLen = 2048;
+            osDbName.resize(nLen);
+        }
     }
-    size_t nLen = osDbName.length();
-    if( nLen > 2048 )
+    else
     {
-        nLen = 2048;
-        osDbName.resize(nLen);
+        // m_bNewDb = false;
+        nLen = strlen(pszFileName);
+        osDbName = pszFileName;
     }
+
     m_pszDBname = new char [nLen+1];
     std::strncpy(m_pszDBname, osDbName.c_str(), nLen);
     m_pszDBname[nLen] = 0;
+
     CPLDebug("OGR-VFK", "Using internal DB: %s",
              m_pszDBname);
 
-    if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_SPATIAL", "YES")))
-	m_bSpatial = TRUE;    /* build geometry from DB */
-    else
-	m_bSpatial = FALSE;   /* store also geometry in DB */
-
-    m_bNewDb = TRUE;
-    if (VSIStatL(osDbName, &sStatBufDb) == 0) {
-	if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_OVERWRITE", "NO"))) {
-	    m_bNewDb = TRUE;     /* overwrite existing DB */
+    if( !m_bDbSource && VSIStatL(osDbName, &sStatBufDb) == 0 )
+    {
+        /* Internal DB exists */
+        if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_OVERWRITE", "NO"))) {
+            m_bNewDb = true;     // Overwrite existing DB.
             CPLDebug("OGR-VFK", "Internal DB (%s) already exists and will be overwritten",
                      m_pszDBname);
-	    VSIUnlink(osDbName);
+            VSIUnlink(osDbName);
         }
-        else {
-            if (VSIStatL(pszFilename, &sStatBufVfk) == 0 &&
-                sStatBufVfk.st_mtime > sStatBufDb.st_mtime) {
+        else
+        {
+            if (pszDbNameConf == NULL &&
+                m_poFStat->st_mtime > sStatBufDb.st_mtime) {
                 CPLDebug("OGR-VFK",
                          "Found %s but ignoring because it appears\n"
                          "be older than the associated VFK file.",
                          osDbName.c_str());
-                m_bNewDb = TRUE;
+                m_bNewDb = true;
                 VSIUnlink(osDbName);
             }
-            else {
-                m_bNewDb = FALSE;    /* re-use existing DB */
+            else
+            {
+                m_bNewDb = false;    /* re-use existing DB */
             }
         }
     }
 
-    /*
-    if (m_bNewDb) {
-      CPLError(CE_Warning, CPLE_AppDefined,
-               "INFO: No internal SQLite DB found. Reading VFK data may take some time...");
-    }
-    */
-
     CPLDebug("OGR-VFK", "New DB: %s Spatial: %s",
              m_bNewDb ? "yes" : "no", m_bSpatial ? "yes" : "no");
 
-    char* pszErrMsg;
     if (SQLITE_OK != sqlite3_open(osDbName, &m_poDB)) {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Creating SQLite DB failed: %s",
                  sqlite3_errmsg(m_poDB));
     }
 
-    if (!m_bNewDb) {
-        char** papszResult;
-        int nRowCount, nColCount;
-        
+    int nRowCount = 0;
+    int nColCount = 0;
+    CPLString osCommand;
+    if( m_bDbSource )
+    {
+        /* check if it's really VFK DB datasource */
+        char* pszErrMsg = NULL;
+        char** papszResult = NULL;
+        nRowCount = nColCount = 0;
+
+        osCommand.Printf("SELECT * FROM sqlite_master WHERE type='table' AND name='%s'",
+                         VFK_DB_TABLE);
+        sqlite3_get_table(m_poDB,
+                          osCommand.c_str(),
+                          &papszResult,
+                          &nRowCount, &nColCount, &pszErrMsg);
+        sqlite3_free_table(papszResult);
+        sqlite3_free(pszErrMsg);
+
+        if (nRowCount != 1) {
+            /* DB is not valid VFK datasource */
+            sqlite3_close(m_poDB);
+            m_poDB = NULL;
+            return;
+        }
+    }
+
+    if( !m_bNewDb )
+    {
         /* check if DB is up-to-date datasource */
-        pszErrMsg = NULL;
-        papszResult = NULL;
+        char* pszErrMsg = NULL;
+        char** papszResult = NULL;
         nRowCount = nColCount = 0;
         osCommand.Printf("SELECT * FROM %s LIMIT 1", VFK_DB_TABLE);
         sqlite3_get_table(m_poDB,
@@ -137,11 +177,16 @@ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilenam
                           &nRowCount, &nColCount, &pszErrMsg);
         sqlite3_free_table(papszResult);
         sqlite3_free(pszErrMsg);
-        pszErrMsg = NULL;
-        
-        if (nColCount != 6) {
+
+        if (nColCount != 7) {
             /* it seems that DB is outdated, let's create new DB from
              * scratch */
+            if( m_bDbSource )
+            {
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Invalid VFK DB datasource");
+            }
+
             if (SQLITE_OK != sqlite3_close(m_poDB)) {
                 CPLError(CE_Failure, CPLE_AppDefined,
                          "Closing SQLite DB failed: %s",
@@ -156,25 +201,58 @@ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilenam
             CPLDebug("OGR-VFK", "Internal DB (%s) is invalid - will be re-created",
                      m_pszDBname);
 
-            m_bNewDb = TRUE;
+            m_bNewDb = true;
         }
     }
 
-    pszErrMsg = NULL;
+    char* pszErrMsg = NULL;
     CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "PRAGMA synchronous = OFF",
                                     NULL, NULL, &pszErrMsg));
     sqlite3_free(pszErrMsg);
-    
-    if (m_bNewDb) {
+
+    if( m_bNewDb )
+    {
+        OGRSpatialReference *poSRS;
+
         /* new DB, create support metadata tables */
-        osCommand.Printf("CREATE TABLE %s (file_name text, table_name text, num_records integer, "
-                         "num_features integer, num_geometries integer, table_defn text)",
-                         VFK_DB_TABLE);
+        osCommand.Printf(
+            "CREATE TABLE %s (file_name text, file_size integer, "
+            "table_name text, num_records integer, "
+            "num_features integer, num_geometries integer, table_defn text)",
+            VFK_DB_TABLE);
         ExecuteSQL(osCommand.c_str());
 
         /* header table */
-        osCommand.Printf("CREATE TABLE %s (key text, value text)", VFK_DB_HEADER);
+        osCommand.Printf(
+            "CREATE TABLE %s (key text, value text)", VFK_DB_HEADER_TABLE);
         ExecuteSQL(osCommand.c_str());
+
+        /* geometry_columns */
+        osCommand.Printf(
+            "CREATE TABLE %s (f_table_name text, f_geometry_column text, "
+            "geometry_type integer, coord_dimension integer, "
+            "srid integer, geometry_format text)", VFK_DB_GEOMETRY_TABLE);
+        ExecuteSQL(osCommand.c_str());
+
+        /* spatial_ref_sys */
+        osCommand.Printf(
+            "CREATE TABLE %s (srid interer, auth_name text, auth_srid text, "
+            "srtext text)", VFK_DB_SPATIAL_REF_TABLE);
+        ExecuteSQL(osCommand.c_str());
+
+        /* insert S-JTSK into spatial_ref_sys table */
+        poSRS = new OGRSpatialReference();
+        if (poSRS->importFromEPSG(5514) != OGRERR_FAILURE)
+        {
+            char *pszWKT = NULL;
+            poSRS->exportToWkt(&pszWKT);
+            osCommand.Printf("INSERT INTO %s (srid, auth_name, auth_srid, "
+                             "srtext) VALUES (5514, 'EPSG', 5514, '%s')",
+                             VFK_DB_SPATIAL_REF_TABLE, pszWKT);
+            ExecuteSQL(osCommand.c_str());
+            CPLFree(pszWKT);
+        }
+        delete poSRS;
     }
 }
 
@@ -183,19 +261,19 @@ VFKReaderSQLite::VFKReaderSQLite(const char *pszFilename) : VFKReader(pszFilenam
 */
 VFKReaderSQLite::~VFKReaderSQLite()
 {
-    /* close tmp SQLite DB */
-    if (SQLITE_OK != sqlite3_close(m_poDB)) {
+    // Close tmp SQLite DB.
+    if( SQLITE_OK != sqlite3_close(m_poDB) )
+    {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Closing SQLite DB failed: %s",
                  sqlite3_errmsg(m_poDB));
     }
-    CPLDebug("OGR-VFK", "Internal DB (%s) closed",
-             m_pszDBname);
+    CPLDebug("OGR-VFK", "Internal DB (%s) closed", m_pszDBname);
 
     /* delete tmp SQLite DB if requested */
-    if (CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_DELETE", "NO"))) {
-        CPLDebug("OGR-VFK", "Internal DB (%s) deleted",
-                 m_pszDBname);
+    if( CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_DELETE", "NO")) )
+    {
+        CPLDebug("OGR-VFK", "Internal DB (%s) deleted", m_pszDBname);
         VSIUnlink(m_pszDBname);
     }
     delete[] m_pszDBname;
@@ -210,32 +288,23 @@ VFKReaderSQLite::~VFKReaderSQLite()
 */
 int VFKReaderSQLite::ReadDataBlocks()
 {
-    int  nDataBlocks = -1;
     CPLString osSQL;
-    const char *pszName, *pszDefn;
-    IVFKDataBlock *poNewDataBlock;
-
-    sqlite3_stmt *hStmt;
-
     osSQL.Printf("SELECT table_name, table_defn FROM %s", VFK_DB_TABLE);
-    hStmt = PrepareStatement(osSQL.c_str());
+    sqlite3_stmt *hStmt = PrepareStatement(osSQL.c_str());
     while(ExecuteSQL(hStmt) == OGRERR_NONE) {
-        pszName = (const char*) sqlite3_column_text(hStmt, 0);
-        pszDefn = (const char*) sqlite3_column_text(hStmt, 1);
-        poNewDataBlock = (IVFKDataBlock *) CreateDataBlock(pszName);
+        const char *pszName = (const char*) sqlite3_column_text(hStmt, 0);
+        const char *pszDefn = (const char*) sqlite3_column_text(hStmt, 1);
+        IVFKDataBlock *poNewDataBlock =
+            (IVFKDataBlock *) CreateDataBlock(pszName);
         poNewDataBlock->SetGeometryType();
         poNewDataBlock->SetProperties(pszDefn);
         VFKReader::AddDataBlock(poNewDataBlock, NULL);
     }
 
-    if (m_nDataBlockCount == 0) {
-        CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "BEGIN", NULL, NULL, NULL));
-        /* CREATE TABLE ... */
-        nDataBlocks = VFKReader::ReadDataBlocks();
-        CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "COMMIT", NULL, NULL, NULL));
-
-        StoreInfo2DB();
-    }
+    CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "BEGIN", NULL, NULL, NULL));
+    /* Read data from VFK file */
+    const int nDataBlocks = VFKReader::ReadDataBlocks();
+    CPL_IGNORE_RET_VAL(sqlite3_exec(m_poDB, "COMMIT", NULL, NULL, NULL));
 
     return nDataBlocks;
 }
@@ -251,16 +320,13 @@ int VFKReaderSQLite::ReadDataBlocks()
 */
 int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
 {
-    int         nDataRecords;
-    int         iDataBlock;
-    const char *pszName;
     CPLString   osSQL;
-
-    IVFKDataBlock *poDataBlockCurrent;
-
-    sqlite3_stmt *hStmt;
-
-    pszName = NULL;
+    IVFKDataBlock *poDataBlockCurrent = NULL;
+    sqlite3_stmt *hStmt = NULL;
+    const char *pszName = NULL;
+    int nDataRecords = 0;
+    bool bReadVfk = !m_bDbSource;
+    bool bReadDb = false;
 
     if (poDataBlock) { /* read records only for selected data block */
         /* table name */
@@ -271,35 +337,50 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
                      "table_name = '%s'",
                      VFK_DB_TABLE, pszName);
         hStmt = PrepareStatement(osSQL.c_str());
-        nDataRecords = -1;
         if (ExecuteSQL(hStmt) == OGRERR_NONE) {
             nDataRecords = sqlite3_column_int(hStmt, 0);
+            if (nDataRecords > 0)
+                bReadDb = true; /* -> read from DB */
+            else
+                nDataRecords = 0;
         }
         sqlite3_finalize(hStmt);
     }
-    else {
-                      /* read all data blocks */
-
+    else
+    {                     /* read all data blocks */
         /* check for existing records (re-use already inserted data) */
-        osSQL.Printf("SELECT COUNT(*) FROM %s WHERE num_records = -1", VFK_DB_TABLE);
+        osSQL.Printf("SELECT COUNT(*) FROM %s WHERE num_records > 0", VFK_DB_TABLE);
         hStmt = PrepareStatement(osSQL.c_str());
         if (ExecuteSQL(hStmt) == OGRERR_NONE &&
-            sqlite3_column_int(hStmt, 0) == 0)
-            nDataRecords = 0;     /* -> read from DB */
-        else
-            nDataRecords = -1;    /* -> read from VFK file */
+            sqlite3_column_int(hStmt, 0) != 0)
+            bReadDb = true;     /* -> read from DB */
+        sqlite3_finalize(hStmt);
 
+        /* check if file is already registered in DB (requires file_size column) */
+        osSQL.Printf("SELECT COUNT(*) FROM %s WHERE file_name = '%s' AND "
+                     "file_size = " CPL_FRMT_GUIB " AND num_records > 0",
+                     VFK_DB_TABLE, CPLGetFilename(m_pszFilename),
+                     (GUIntBig) m_poFStat->st_size);
+        hStmt = PrepareStatement(osSQL.c_str());
+        if (ExecuteSQL(hStmt) == OGRERR_NONE &&
+            sqlite3_column_int(hStmt, 0) > 0) {
+            /* -> file already registered (filename & size is the same) */
+            CPLDebug("OGR-VFK", "VFK file %s already loaded in DB", m_pszFilename);
+            bReadVfk = false;
+        }
         sqlite3_finalize(hStmt);
     }
 
-    if (nDataRecords > -1) {        /* read records from DB */
+    if( bReadDb )
+    {  /* read records from DB */
         /* read from  DB */
-        long iFID;
-        int  iRowId;
         VFKFeatureSQLite *poNewFeature = NULL;
 
         poDataBlockCurrent = NULL;
-        for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
+        for( int iDataBlock = 0;
+             iDataBlock < GetDataBlockCount();
+             iDataBlock++ )
+        {
             poDataBlockCurrent = GetDataBlock(iDataBlock);
 
             if (poDataBlock && poDataBlock != poDataBlockCurrent)
@@ -319,8 +400,8 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
             hStmt = PrepareStatement(osSQL.c_str());
             nDataRecords = 0;
             while (ExecuteSQL(hStmt) == OGRERR_NONE) {
-                iFID = sqlite3_column_int(hStmt, 0);
-                iRowId = sqlite3_column_int(hStmt, 1);
+                const long iFID = sqlite3_column_int(hStmt, 0);
+                int iRowId = sqlite3_column_int(hStmt, 1);
                 poNewFeature = new VFKFeatureSQLite(poDataBlockCurrent, iRowId, iFID);
                 poDataBlockCurrent->AddFeature(poNewFeature);
                 nDataRecords++;
@@ -331,9 +412,7 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
                          VFK_DB_TABLE, pszName);
             hStmt = PrepareStatement(osSQL.c_str());
             if (ExecuteSQL(hStmt) == OGRERR_NONE) {
-                int nFeatDB;
-
-                nFeatDB = sqlite3_column_int(hStmt, 0);
+                const int nFeatDB = sqlite3_column_int(hStmt, 0);
                 if (nFeatDB > 0 && nFeatDB != poDataBlockCurrent->GetFeatureCount())
                     CPLError(CE_Failure, CPLE_AppDefined,
                              "%s: Invalid number of features " CPL_FRMT_GIB " (should be %d)",
@@ -342,16 +421,24 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
             sqlite3_finalize(hStmt);
         }
     }
-    else {                          /* read from VFK file and insert records into DB */
+
+    if( bReadVfk )
+    {  /* read from VFK file and insert records into DB */
         /* begin transaction */
         ExecuteSQL("BEGIN");
 
-        /* INSERT ... */
-        nDataRecords = VFKReader::ReadDataRecords(poDataBlock);
+        /* Store VFK header to DB */
+        StoreInfo2DB();
+
+        /* Insert VFK data records into DB */
+        nDataRecords += VFKReader::ReadDataRecords(poDataBlock);
 
         /* update VFK_DB_TABLE table */
         poDataBlockCurrent = NULL;
-        for (iDataBlock = 0; iDataBlock < GetDataBlockCount(); iDataBlock++) {
+        for( int iDataBlock = 0;
+             iDataBlock < GetDataBlockCount();
+             iDataBlock++)
+        {
             poDataBlockCurrent = GetDataBlock(iDataBlock);
 
             if (poDataBlock && poDataBlock != poDataBlockCurrent)
@@ -377,18 +464,16 @@ int VFKReaderSQLite::ReadDataRecords(IVFKDataBlock *poDataBlock)
 */
 void VFKReaderSQLite::StoreInfo2DB()
 {
-    CPLString osSQL;
-    const char *value;
-    char q;
-
-    for(std::map<CPLString, CPLString>::iterator i = poInfo.begin();
-        i != poInfo.end(); ++i) {
-        value = i->second.c_str();
+    for( std::map<CPLString, CPLString>::iterator i = poInfo.begin();
+         i != poInfo.end(); ++i )
+    {
+        const char *value = i->second.c_str();
 
-        q = (value[0] == '"') ? ' ' : '"';
+        const char q = (value[0] == '"') ? ' ' : '"';
 
+        CPLString osSQL;
         osSQL.Printf("INSERT INTO %s VALUES(\"%s\", %c%s%c)",
-                     VFK_DB_HEADER, i->first.c_str(),
+                     VFK_DB_HEADER_TABLE, i->first.c_str(),
                      q, value, q);
         ExecuteSQL(osSQL);
     }
@@ -402,7 +487,7 @@ void VFKReaderSQLite::StoreInfo2DB()
   \param name index name
   \param table table name
   \param column column(s) name
-  \param unique TRUE to create unique index
+  \param unique true to create unique index
 */
 void VFKReaderSQLite::CreateIndex(const char *name, const char *table, const char *column,
                                   bool unique)
@@ -442,31 +527,23 @@ IVFKDataBlock *VFKReaderSQLite::CreateDataBlock(const char *pszBlockName)
 */
 void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDefn)
 {
-    const char *pszBlockName;
-    const char *pszKey;
-    CPLString   osCommand, osColumn;
-    bool        bUnique;
-
-    VFKPropertyDefn *poPropertyDefn;
+    CPLString osColumn;
 
-    sqlite3_stmt *hStmt;
-
-    bUnique = !CPLTestBool(CPLGetConfigOption("OGR_VFK_DB_IGNORE_DUPLICATES", "NO"));
-
-    pszBlockName = poDataBlock->GetName();
+    const char *pszBlockName = poDataBlock->GetName();
 
     /* register table in VFK_DB_TABLE */
+    CPLString osCommand;
     osCommand.Printf("SELECT COUNT(*) FROM %s WHERE "
                      "table_name = '%s'",
                      VFK_DB_TABLE, pszBlockName);
-    hStmt = PrepareStatement(osCommand.c_str());
+    sqlite3_stmt *hStmt = PrepareStatement(osCommand.c_str());
 
     if (ExecuteSQL(hStmt) == OGRERR_NONE &&
         sqlite3_column_int(hStmt, 0) == 0) {
 
-        osCommand.Printf("CREATE TABLE '%s' (", pszBlockName);
+        osCommand.Printf("CREATE TABLE IF NOT EXISTS '%s' (", pszBlockName);
         for (int i = 0; i < poDataBlock->GetPropertyCount(); i++) {
-            poPropertyDefn = poDataBlock->GetProperty(i);
+            VFKPropertyDefn *poPropertyDefn = poDataBlock->GetProperty(i);
             if (i > 0)
                 osCommand += ",";
             osColumn.Printf("%s %s", poPropertyDefn->GetName(),
@@ -474,12 +551,12 @@ void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDe
             osCommand += osColumn;
         }
         osColumn.Printf(",%s integer", FID_COLUMN);
-	osCommand += osColumn;
-	if (poDataBlock->GetGeometryType() != wkbNone) {
-	    osColumn.Printf(",%s blob", GEOM_COLUMN);
+        osCommand += osColumn;
+        if (poDataBlock->GetGeometryType() != wkbNone) {
+            osColumn.Printf(",%s blob", GEOM_COLUMN);
             osCommand += osColumn;
-	}
-	osCommand += ")";
+        }
+        osCommand += ")";
         ExecuteSQL(osCommand.c_str()); /* CREATE TABLE */
 
         /* create indices */
@@ -487,38 +564,47 @@ void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDe
         CreateIndex(osCommand.c_str(), pszBlockName, FID_COLUMN,
                     !EQUAL(pszBlockName, "SBP"));
 
-        pszKey = ((VFKDataBlockSQLite *) poDataBlock)->GetKey();
+        const char *pszKey = ((VFKDataBlockSQLite *) poDataBlock)->GetKey();
         if (pszKey) {
             osCommand.Printf("%s_%s", pszBlockName, pszKey);
-            CreateIndex(osCommand.c_str(), pszBlockName, pszKey, bUnique);
+            CreateIndex(osCommand.c_str(), pszBlockName, pszKey, !m_bAmendment);
         }
 
         if (EQUAL(pszBlockName, "SBP")) {
             /* create extra indices for SBP */
-            CreateIndex("SBP_OB",        pszBlockName, "OB_ID", FALSE);
-            CreateIndex("SBP_HP",        pszBlockName, "HP_ID", FALSE);
-            CreateIndex("SBP_DPM",       pszBlockName, "DPM_ID", FALSE);
-            CreateIndex("SBP_OB_HP_DPM", pszBlockName, "OB_ID,HP_ID,DPM_ID", bUnique);
-            CreateIndex("SBP_OB_POR",    pszBlockName, "OB_ID,PORADOVE_CISLO_BODU", FALSE);
-            CreateIndex("SBP_HP_POR",    pszBlockName, "HP_ID,PORADOVE_CISLO_BODU", FALSE);
-            CreateIndex("SBP_DPM_POR",   pszBlockName, "DPM_ID,PORADOVE_CISLO_BODU", FALSE);
+            CreateIndex("SBP_OB",        pszBlockName, "OB_ID", false);
+            CreateIndex("SBP_HP",        pszBlockName, "HP_ID", false);
+            CreateIndex("SBP_DPM",       pszBlockName, "DPM_ID", false);
+            CreateIndex("SBP_OB_HP_DPM", pszBlockName, "OB_ID,HP_ID,DPM_ID", true);
+            CreateIndex("SBP_OB_POR",    pszBlockName, "OB_ID,PORADOVE_CISLO_BODU", false);
+            CreateIndex("SBP_HP_POR",    pszBlockName, "HP_ID,PORADOVE_CISLO_BODU", false);
+            CreateIndex("SBP_DPM_POR",   pszBlockName, "DPM_ID,PORADOVE_CISLO_BODU", false);
         }
         else if (EQUAL(pszBlockName, "HP")) {
             /* create extra indices for HP */
-            CreateIndex("HP_PAR1",        pszBlockName, "PAR_ID_1", FALSE);
-            CreateIndex("HP_PAR2",        pszBlockName, "PAR_ID_2", FALSE);
+            CreateIndex("HP_PAR1",        pszBlockName, "PAR_ID_1", false);
+            CreateIndex("HP_PAR2",        pszBlockName, "PAR_ID_2", false);
         }
         else if (EQUAL(pszBlockName, "OB")) {
             /* create extra indices for OP */
-            CreateIndex("OB_BUD",        pszBlockName, "BUD_ID", FALSE);
+            CreateIndex("OB_BUD",        pszBlockName, "BUD_ID", false);
         }
 
         /* update VFK_DB_TABLE meta-table */
-        osCommand.Printf("INSERT INTO %s (file_name, table_name, "
+        osCommand.Printf("INSERT INTO %s (file_name, file_size, table_name, "
                          "num_records, num_features, num_geometries, table_defn) VALUES "
-			 "('%s', '%s', -1, 0, 0, '%s')",
-			 VFK_DB_TABLE, m_pszFilename, pszBlockName, pszDefn);
+                         "('%s', " CPL_FRMT_GUIB ", '%s', -1, 0, 0, '%s')",
+                         VFK_DB_TABLE, CPLGetFilename(m_pszFilename),
+                         (GUIntBig) m_poFStat->st_size,
+                         pszBlockName, pszDefn);
+        ExecuteSQL(osCommand.c_str());
 
+        int geom_type = ((VFKDataBlockSQLite *) poDataBlock)->GetGeometrySQLType();
+        /* update VFK_DB_GEOMETRY_TABLE */
+        osCommand.Printf("INSERT INTO %s (f_table_name, f_geometry_column, geometry_type, "
+                         "coord_dimension, srid, geometry_format) VALUES "
+                         "('%s', '%s', %d, 2, 5514, 'WKB')",
+                         VFK_DB_GEOMETRY_TABLE, pszBlockName, GEOM_COLUMN, geom_type);
         ExecuteSQL(osCommand.c_str());
 
         sqlite3_finalize(hStmt);
@@ -536,17 +622,17 @@ void VFKReaderSQLite::AddDataBlock(IVFKDataBlock *poDataBlock, const char *pszDe
 */
 sqlite3_stmt *VFKReaderSQLite::PrepareStatement(const char *pszSQLCommand)
 {
-    int rc;
-    sqlite3_stmt *hStmt = NULL;
-
     CPLDebug("OGR-VFK", "VFKReaderSQLite::PrepareStatement(): %s", pszSQLCommand);
 
-    rc = sqlite3_prepare(m_poDB, pszSQLCommand, -1,
-                         &hStmt, NULL);
+    sqlite3_stmt *hStmt = NULL;
+    const int rc = sqlite3_prepare_v2(m_poDB, pszSQLCommand, -1,
+                                   &hStmt, NULL);
 
-    if (rc != SQLITE_OK) {
+    // TODO(schwehr): if( rc == SQLITE_OK ) return NULL;
+    if (rc != SQLITE_OK)
+    {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "In PrepareStatement(): sqlite3_prepare(%s):\n  %s",
+                 "In PrepareStatement(): sqlite3_prepare_v2(%s):\n  %s",
                  pszSQLCommand, sqlite3_errmsg(m_poDB));
 
         if(hStmt != NULL) {
@@ -568,11 +654,7 @@ sqlite3_stmt *VFKReaderSQLite::PrepareStatement(const char *pszSQLCommand)
 */
 OGRErr VFKReaderSQLite::ExecuteSQL(sqlite3_stmt *hStmt)
 {
-    int rc;
-
-    // assert
-
-    rc = sqlite3_step(hStmt);
+    const int rc = sqlite3_step(hStmt);
     if (rc != SQLITE_ROW) {
         if (rc == SQLITE_DONE) {
             sqlite3_finalize(hStmt);
@@ -588,22 +670,23 @@ OGRErr VFKReaderSQLite::ExecuteSQL(sqlite3_stmt *hStmt)
     }
 
     return OGRERR_NONE;
-
 }
 
 /*!
   \brief Execute SQL statement (SQLITE only)
 
   \param pszSQLCommand SQL command to execute
-  \param bQuiet TRUE to print debug message on failure instead of error message
+  \param bQuiet true to print debug message on failure instead of error message
 
   \return OGRERR_NONE on success or OGRERR_FAILURE on failure
 */
-OGRErr VFKReaderSQLite::ExecuteSQL(const char *pszSQLCommand, bool bQuiet)
+OGRErr VFKReaderSQLite::ExecuteSQL( const char *pszSQLCommand, bool bQuiet )
 {
     char *pszErrMsg = NULL;
 
-    if (SQLITE_OK != sqlite3_exec(m_poDB, pszSQLCommand, NULL, NULL, &pszErrMsg)) {
+    if( SQLITE_OK != sqlite3_exec(m_poDB, pszSQLCommand,
+                                  NULL, NULL, &pszErrMsg) )
+    {
         if (!bQuiet)
             CPLError(CE_Failure, CPLE_AppDefined,
                      "In ExecuteSQL(%s): %s",
@@ -625,45 +708,45 @@ OGRErr VFKReaderSQLite::ExecuteSQL(const char *pszSQLCommand, bool bQuiet)
   \param poDataBlock pointer to VFKDataBlock instance
   \param poFeature pointer to VFKFeature instance
 */
-OGRErr VFKReaderSQLite::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFeature)
+OGRErr VFKReaderSQLite::AddFeature( IVFKDataBlock *poDataBlock,
+                                    VFKFeature *poFeature )
 {
-    CPLString     osCommand;
-    CPLString     osValue;
-
-    const char   *pszBlockName;
+    CPLString osValue;
 
-    OGRFieldType  ftype;
+    const VFKProperty *poProperty = NULL;
 
-    const VFKProperty *poProperty;
-
-    VFKFeatureSQLite *poNewFeature;
-
-    pszBlockName = poDataBlock->GetName();
+    const char *pszBlockName = poDataBlock->GetName();
+    CPLString osCommand;
     osCommand.Printf("INSERT INTO '%s' VALUES(", pszBlockName);
 
-    for (int i = 0; i < poDataBlock->GetPropertyCount(); i++) {
-        ftype = poDataBlock->GetProperty(i)->GetType();
+    for( int i = 0; i < poDataBlock->GetPropertyCount(); i++ )
+    {
+        const OGRFieldType ftype = poDataBlock->GetProperty(i)->GetType();
         poProperty = poFeature->GetProperty(i);
         if (i > 0)
             osCommand += ",";
-        if (poProperty->IsNull())
+
+        if( poProperty->IsNull() )
+        {
             osValue.Printf("NULL");
-        else {
+        }
+        else
+        {
             switch (ftype) {
             case OFTInteger:
                 osValue.Printf("%d", poProperty->GetValueI());
                 break;
+            case OFTInteger64:
+                osValue.Printf(CPL_FRMT_GIB, poProperty->GetValueI64());
+                break;
             case OFTReal:
                 osValue.Printf("%f", poProperty->GetValueD());
                 break;
             case OFTString:
-                if (poDataBlock->GetProperty(i)->IsIntBig())
-		    osValue.Printf("%s", poProperty->GetValueS());
-                else
-                    osValue.Printf("'%s'", poProperty->GetValueS(TRUE));
+                osValue.Printf("'%s'", poProperty->GetValueS(true));
                 break;
             default:
-                osValue.Printf("'%s'", poProperty->GetValueS());
+                osValue.Printf("'%s'", poProperty->GetValueS(true));
                 break;
             }
         }
@@ -671,12 +754,12 @@ OGRErr VFKReaderSQLite::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFea
     }
     osValue.Printf("," CPL_FRMT_GIB, poFeature->GetFID());
     if (poDataBlock->GetGeometryType() != wkbNone) {
-	osValue += ",NULL";
+        osValue += ",NULL";
     }
     osValue += ")";
     osCommand += osValue;
 
-    if (ExecuteSQL(osCommand.c_str(), TRUE) != OGRERR_NONE)
+    if( ExecuteSQL(osCommand.c_str(), true) != OGRERR_NONE )
         return OGRERR_FAILURE;
 
     if (EQUAL(pszBlockName, "SBP")) {
@@ -686,12 +769,14 @@ OGRErr VFKReaderSQLite::AddFeature(IVFKDataBlock *poDataBlock, VFKFeature *poFea
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot find property PORADOVE_CISLO_BODU");
             return OGRERR_FAILURE;
         }
-        if (!EQUAL(poProperty->GetValueS(), "1"))
+        if (poProperty->GetValueI64() != 1)
             return OGRERR_NONE;
     }
 
-    poNewFeature = new VFKFeatureSQLite(poDataBlock, poDataBlock->GetRecordCount(RecordValid) + 1,
-                                        poFeature->GetFID());
+    VFKFeatureSQLite *poNewFeature =
+        new VFKFeatureSQLite(poDataBlock,
+                             poDataBlock->GetRecordCount(RecordValid) + 1,
+                             poFeature->GetFID());
     poDataBlock->AddFeature(poNewFeature);
 
     return OGRERR_NONE;
diff --git a/ogr/ogrsf_frmts/vrt/ogr_vrt.h b/ogr/ogrsf_frmts/vrt/ogr_vrt.h
index dfaa632..9ed9c0c 100644
--- a/ogr/ogrsf_frmts/vrt/ogr_vrt.h
+++ b/ogr/ogrsf_frmts/vrt/ogr_vrt.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_vrt.h 34203 2016-05-10 14:06:35Z rouault $
+ * $Id: ogr_vrt.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Private definitions for OGR/VRT driver.
@@ -31,14 +31,14 @@
 #ifndef OGR_VRT_H_INCLUDED
 #define OGR_VRT_H_INCLUDED
 
-#include "ogrsf_frmts.h"
 #include "cpl_error.h"
 #include "cpl_minixml.h"
 #include "ogrlayerpool.h"
+#include "ogrsf_frmts.h"
 
-#include <vector>
-#include <string>
 #include <set>
+#include <string>
+#include <vector>
 
 typedef enum {
     VGS_None,
@@ -56,28 +56,31 @@ typedef enum {
 class OGRVRTGeomFieldProps
 {
     public:
-        CPLString           osName;         /* Name of the VRT geometry field */
+        CPLString           osName;  // Name of the VRT geometry field */
         OGRwkbGeometryType  eGeomType;
         OGRSpatialReference *poSRS;
 
-        int                 bSrcClip;
+        bool                bSrcClip;
         OGRGeometry         *poSrcRegion;
 
         // Geometry interpretation related.
         OGRVRTGeometryStyle eGeometryStyle;
 
-        /* points to a OGRField for VGS_WKT, VGS_WKB, VGS_Shape and OGRGeomField for VGS_Direct */
+        // Points to a OGRField for VGS_WKT, VGS_WKB, VGS_Shape and OGRGeomField
+        // for VGS_Direct.
         int                 iGeomField;
 
-                            // VGS_PointFromColumn
-        int                 iGeomXField, iGeomYField, iGeomZField, iGeomMField;
-        int                 bReportSrcColumn;
-        int                 bUseSpatialSubquery;
+        // VGS_PointFromColumn
+        int                 iGeomXField;
+        int                 iGeomYField;
+        int                 iGeomZField;
+        int                 iGeomMField;
+        bool                bReportSrcColumn;
+        bool                bUseSpatialSubquery;
+        bool                bNullable;
 
         OGREnvelope         sStaticEnvelope;
 
-        int                 bNullable;
-
                         OGRVRTGeomFieldProps();
                        ~OGRVRTGeomFieldProps();
 };
@@ -94,7 +97,7 @@ class OGRVRTLayer : public OGRLayer
     OGRVRTDataSource*   poDS;
     std::vector<OGRVRTGeomFieldProps*> apoGeomFieldProps;
 
-    int                 bHasFullInitialized;
+    bool                bHasFullInitialized;
     CPLString           osName;
     CPLXMLNode         *psLTree;
     CPLString           osVRTDirectory;
@@ -104,96 +107,97 @@ class OGRVRTLayer : public OGRLayer
     GDALDataset         *poSrcDS;
     OGRLayer            *poSrcLayer;
     OGRFeatureDefn      *poSrcFeatureDefn;
-    int                 bNeedReset;
-    int                 bSrcLayerFromSQL;
-    int                 bSrcDSShared;
-    int                 bAttrFilterPassThrough;
+    bool                bNeedReset;
+    bool                bSrcLayerFromSQL;
+    bool                bSrcDSShared;
+    bool                bAttrFilterPassThrough;
 
     char                *pszAttrFilter;
 
-    int                 iFIDField; // -1 means pass through.
+    int                 iFIDField;  // -1 means pass through.
     CPLString           osFIDFieldName;
-    int                 iStyleField; // -1 means pass through.
+    int                 iStyleField;  // -1 means pass through.
 
-    // Attribute Mapping
+    // Attribute mapping.
     std::vector<int>    anSrcField;
     std::vector<int>    abDirectCopy;
 
-    int                 bUpdate;
+    bool                bUpdate;
 
     OGRFeature         *TranslateFeature( OGRFeature*& , int bUseSrcRegion );
     OGRFeature         *TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeature);
 
-    int                 ResetSourceReading();
+    bool                ResetSourceReading();
 
-    int                 FullInitialize();
+    bool                FullInitialize();
 
     OGRFeatureDefn     *GetSrcLayerDefn();
     void                ClipAndAssignSRS(OGRFeature* poFeature);
 
     GIntBig             nFeatureCount;
 
-    int                 bError;
+    bool                bError;
 
-    int                 ParseGeometryField(CPLXMLNode* psNode,
-                                           CPLXMLNode* psNodeParent,
-                                           OGRVRTGeomFieldProps* poProps);
+    bool                ParseGeometryField( CPLXMLNode* psNode,
+                                            CPLXMLNode* psNodeParent,
+                                            OGRVRTGeomFieldProps* poProps );
 
   public:
-                        OGRVRTLayer(OGRVRTDataSource* poDSIn);
+    explicit             OGRVRTLayer( OGRVRTDataSource* poDSIn );
     virtual             ~OGRVRTLayer();
 
-    int                FastInitialize( CPLXMLNode *psLTree,
-                                    const char *pszVRTDirectory,
-                                    int bUpdate);
+    bool               FastInitialize( CPLXMLNode *psLTree,
+                                       const char *pszVRTDirectory,
+                                       int bUpdate );
 
-    virtual const char  *GetName() { return osName.c_str(); }
-    virtual OGRwkbGeometryType GetGeomType();
+    virtual const char  *GetName() override { return osName.c_str(); }
+    virtual OGRwkbGeometryType GetGeomType() override;
 
 /* -------------------------------------------------------------------- */
 /*      Caution : all the below methods should care of calling          */
 /*      FullInitialize() if not already done                            */
 /* -------------------------------------------------------------------- */
 
-    virtual void        ResetReading();
-    virtual OGRFeature *GetNextFeature();
+    virtual void        ResetReading() override;
+    virtual OGRFeature *GetNextFeature() override;
 
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex );
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
 
-    virtual OGRFeatureDefn *GetLayerDefn();
+    virtual OGRFeatureDefn *GetLayerDefn() override;
 
-    virtual OGRSpatialReference *GetSpatialRef();
+    virtual OGRSpatialReference *GetSpatialRef() override;
 
-    virtual GIntBig     GetFeatureCount( int );
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent,
-                                  int bForce = TRUE);
+    virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce = TRUE ) override;
+    virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent,
+                                   int bForce = TRUE ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry * poGeomIn );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn );
+    virtual void        SetSpatialFilter( OGRGeometry *poGeomIn ) override;
+    virtual void        SetSpatialFilter( int iGeomField,
+                                          OGRGeometry *poGeomIn ) override;
 
-    virtual OGRErr      ICreateFeature( OGRFeature* poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
 
-    virtual OGRErr      ISetFeature( OGRFeature* poFeature );
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
 
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 
-    virtual const char *GetFIDColumn();
+    virtual const char *GetFIDColumn() override;
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction() override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
-    virtual OGRErr      SetIgnoredFields( const char **papszFields );
+    virtual OGRErr      SetIgnoredFields( const char **papszFields ) override;
 
     GDALDataset*        GetSrcDataset();
 };
@@ -223,62 +227,65 @@ class OGRVRTDataSource : public OGRDataSource
 
     std::set<std::string> aosOtherDSNameSet;
 
-    OGRLayer*           InstantiateWarpedLayer(CPLXMLNode *psLTree,
-                                               const char *pszVRTDirectory,
-                                               int bUpdate,
-                                               int nRecLevel);
-    OGRLayer*           InstantiateUnionLayer(CPLXMLNode *psLTree,
+    OGRLayer*           InstantiateWarpedLayer( CPLXMLNode *psLTree,
+                                                const char *pszVRTDirectory,
+                                                int bUpdate,
+                                                int nRecLevel );
+    OGRLayer*           InstantiateUnionLayer( CPLXMLNode *psLTree,
                                                const char *pszVRTDirectory,
                                                int bUpdate,
-                                               int nRecLevel);
+                                               int nRecLevel );
 
     OGRLayerPool*       poLayerPool;
 
     OGRVRTDataSource   *poParentDS;
-    int                 bRecursionDetected;
+    bool                bRecursionDetected;
 
   public:
-                        OGRVRTDataSource(GDALDriver* poDriver);
-                        ~OGRVRTDataSource();
+    explicit            OGRVRTDataSource( GDALDriver *poDriver );
+                        virtual ~OGRVRTDataSource();
 
-    virtual int         CloseDependentDatasets();
+    virtual int         CloseDependentDatasets() override;
 
-    OGRLayer*           InstantiateLayer(CPLXMLNode *psLTree,
-                                    const char *pszVRTDirectory,
-                                    int bUpdate,
-                                    int nRecLevel = 0);
+    OGRLayer*           InstantiateLayer( CPLXMLNode *psLTree,
+                                          const char *pszVRTDirectory,
+                                          int bUpdate,
+                                          int nRecLevel = 0 );
 
-    OGRLayer*           InstantiateLayerInternal(CPLXMLNode *psLTree,
-                                            const char *pszVRTDirectory,
-                                            int bUpdate,
-                                            int nRecLevel);
+    OGRLayer*           InstantiateLayerInternal( CPLXMLNode *psLTree,
+                                                  const char *pszVRTDirectory,
+                                                  int bUpdate,
+                                                  int nRecLevel );
 
-    int                 Initialize( CPLXMLNode *psXML, const char *pszName,
+    bool                Initialize( CPLXMLNode *psXML, const char *pszName,
                                     int bUpdate );
 
-    const char          *GetName() { return pszName; }
-    int                 GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char          *GetName() override { return pszName; }
+    int                 GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                 TestCapability( const char * );
+    int                 TestCapability( const char * ) override;
 
-    virtual char      **GetFileList();
+    virtual char      **GetFileList() override;
 
-    /* Anti-recursion mechanism for standard Open */
-    void                SetCallLevel(int nCallLevelIn) { nCallLevel = nCallLevelIn; }
+    // Anti-recursion mechanism for standard Open.
+    void                SetCallLevel(int nCallLevelIn)
+        { nCallLevel = nCallLevelIn; }
     int                 GetCallLevel() { return nCallLevel; }
 
-    void                SetParentDS(OGRVRTDataSource* poParentDSIn) { poParentDS = poParentDSIn; }
+    void                SetParentDS( OGRVRTDataSource* poParentDSIn )
+        { poParentDS = poParentDSIn; }
     OGRVRTDataSource*   GetParentDS() { return poParentDS; }
 
-    void                SetRecursionDetected() { bRecursionDetected = TRUE; }
-    int                 GetRecursionDetected() { return bRecursionDetected; }
+    void                SetRecursionDetected() { bRecursionDetected = true; }
+    bool                GetRecursionDetected() const
+        { return bRecursionDetected; }
 
-    /* Anti-recursion mechanism for shared Open */
-    void                AddForbiddenNames(const char* pszOtherDSName);
-    int                 IsInForbiddenNames(const char* pszOtherDSName);
+    // Anti-recursion mechanism for shared Open.
+    void                AddForbiddenNames( const char* pszOtherDSName );
+    bool                IsInForbiddenNames( const char* pszOtherDSName ) const;
 };
 
 OGRwkbGeometryType OGRVRTGetGeometryType(const char* pszGType, int* pbError);
 
-#endif /* ndef OGR_VRT_H_INCLUDED */
+#endif  // ndef OGR_VRT_H_INCLUDED
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
index b29bad9..f80b22d 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrvrtdatasource.cpp 34048 2016-04-21 18:14:02Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTDataSource class.
@@ -34,7 +33,7 @@
 #include "ogrwarpedlayer.h"
 #include "ogrunionlayer.h"
 
-CPL_CVSID("$Id: ogrvrtdatasource.cpp 34048 2016-04-21 18:14:02Z rouault $");
+CPL_CVSID("$Id: ogrvrtdatasource.cpp 36883 2016-12-15 13:31:12Z rouault $");
 
 /************************************************************************/
 /*                       OGRVRTGetGeometryType()                        */
@@ -62,19 +61,22 @@ static const OGRGeomTypeName asGeomTypeNames[] = { /* 25D versions are implicit
     { wkbMultiSurface, "wkbMultiSurface" },
     { wkbCurve, "wkbCurve" },
     { wkbSurface, "wkbSurface" },
+    { wkbPolyhedralSurface, "wkbPolyhedralSurface" },
+    { wkbTIN, "wkbTIN" },
+    { wkbTriangle, "wkbTriangle" },
     { wkbNone, "wkbNone" },
     { wkbNone, NULL }
 };
 
-OGRwkbGeometryType OGRVRTGetGeometryType(const char* pszGType, int* pbError)
+OGRwkbGeometryType OGRVRTGetGeometryType( const char* pszGType, int* pbError )
 {
-    if (pbError)
+    if( pbError )
         *pbError = FALSE;
 
     OGRwkbGeometryType eGeomType = wkbUnknown;
-    int iType;
+    int iType = 0;  // Used after for.
 
-    for( iType = 0; asGeomTypeNames[iType].pszName != NULL; iType++ )
+    for( ; asGeomTypeNames[iType].pszName != NULL; iType++ )
     {
         if( EQUALN(pszGType, asGeomTypeNames[iType].pszName,
                 strlen(asGeomTypeNames[iType].pszName)) )
@@ -91,7 +93,7 @@ OGRwkbGeometryType OGRVRTGetGeometryType(const char* pszGType, int* pbError)
 
     if( asGeomTypeNames[iType].pszName == NULL )
     {
-        if (pbError)
+        if( pbError )
             *pbError = TRUE;
     }
 
@@ -102,7 +104,7 @@ OGRwkbGeometryType OGRVRTGetGeometryType(const char* pszGType, int* pbError)
 /*                          OGRVRTDataSource()                          */
 /************************************************************************/
 
-OGRVRTDataSource::OGRVRTDataSource(GDALDriver* poDriverIn) :
+OGRVRTDataSource::OGRVRTDataSource( GDALDriver* poDriverIn ) :
     papoLayers(NULL),
     paeLayerType(NULL),
     nLayers(0),
@@ -111,9 +113,9 @@ OGRVRTDataSource::OGRVRTDataSource(GDALDriver* poDriverIn) :
     nCallLevel(0),
     poLayerPool(NULL),
     poParentDS(NULL),
-    bRecursionDetected(FALSE)
+    bRecursionDetected(false)
 {
-    this->poDriver = poDriverIn;
+    poDriver = poDriverIn;
 }
 
 /************************************************************************/
@@ -157,10 +159,10 @@ int OGRVRTDataSource::CloseDependentDatasets()
 /************************************************************************/
 
 OGRLayer*  OGRVRTDataSource::InstantiateWarpedLayer(
-                                        CPLXMLNode *psLTree,
-                                        const char *pszVRTDirectory,
-                                        int bUpdate,
-                                        int nRecLevel)
+    CPLXMLNode *psLTree,
+    const char *pszVRTDirectory,
+    int bUpdate,
+    int nRecLevel)
 {
     if( !EQUAL(psLTree->pszValue,"OGRVRTWarpedLayer") )
         return NULL;
@@ -175,7 +177,7 @@ OGRLayer*  OGRVRTDataSource::InstantiateWarpedLayer(
             continue;
 
         poSrcLayer = InstantiateLayer(psSubNode, pszVRTDirectory,
-                                 bUpdate, nRecLevel + 1);
+                                      bUpdate, nRecLevel + 1);
         if( poSrcLayer != NULL )
             break;
     }
@@ -308,10 +310,10 @@ OGRLayer*  OGRVRTDataSource::InstantiateWarpedLayer(
 /************************************************************************/
 
 OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
-                                        CPLXMLNode *psLTree,
-                                        const char *pszVRTDirectory,
-                                        int bUpdate,
-                                        int nRecLevel)
+    CPLXMLNode *psLTree,
+    const char *pszVRTDirectory,
+    int bUpdate,
+    int nRecLevel)
 {
     if( !EQUAL(psLTree->pszValue,"OGRVRTUnionLayer") )
         return NULL;
@@ -333,12 +335,12 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
 /*      source layer.                                                   */
 /* -------------------------------------------------------------------- */
     const char* pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
-    int bGlobalGeomTypeSet = FALSE;
+    bool bGlobalGeomTypeSet = false;
     OGRwkbGeometryType eGlobalGeomType = wkbUnknown;
     if( pszGType != NULL )
     {
-        int bError;
-        bGlobalGeomTypeSet = TRUE;
+        bGlobalGeomTypeSet = true;
+        int bError = FALSE;
         eGlobalGeomType = OGRVRTGetGeometryType(pszGType, &bError);
         if( bError )
         {
@@ -354,10 +356,10 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
 /* -------------------------------------------------------------------- */
      const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
      OGRSpatialReference* poGlobalSRS = NULL;
-     int bGlobalSRSSet = FALSE;
+     bool bGlobalSRSSet = false;
      if( pszLayerSRS != NULL )
      {
-         bGlobalSRSSet = TRUE;
+         bGlobalSRSSet = true;
          if( !EQUAL(pszLayerSRS,"NULL") )
          {
              OGRSpatialReference oSRS;
@@ -380,8 +382,7 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
     OGRUnionLayerGeomFieldDefn** papoGeomFields = NULL;
     int nGeomFields = 0;
 
-    CPLXMLNode *psSubNode;
-    for( psSubNode=psLTree->psChild;
+    for( CPLXMLNode *psSubNode = psLTree->psChild;
          psSubNode != NULL;
          psSubNode=psSubNode->psNext )
     {
@@ -410,9 +411,9 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
 
              if( pszArg != NULL )
              {
-                 int iType;
+                 int iType = 0;  // Used after for.
 
-                 for( iType = 0; iType <= (int) OFTMaxType; iType++ )
+                 for( ; iType <= (int) OFTMaxType; iType++ )
                  {
                      if( EQUAL(pszArg,OGRFieldDefn::GetFieldTypeName(
                                    (OGRFieldType)iType)) )
@@ -475,12 +476,12 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
              if( pszGType == NULL && nGeomFields == 0 )
                  pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
              OGRwkbGeometryType eGeomType = wkbUnknown;
-             int bGeomTypeSet = FALSE;
+             bool bGeomTypeSet = false;
              if( pszGType != NULL )
              {
-                int bError;
+                int bError = FALSE;
                 eGeomType = OGRVRTGetGeometryType(pszGType, &bError);
-                bGeomTypeSet = TRUE;
+                bGeomTypeSet = true;
                 if( bError || eGeomType == wkbNone )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
@@ -494,10 +495,10 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
              if( pszSRS == NULL && nGeomFields == 0 )
                  pszSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
              OGRSpatialReference* poSRS = NULL;
-             int bSRSSet = FALSE;
+             bool bSRSSet = false;
              if( pszSRS != NULL )
              {
-                 bSRSSet = TRUE;
+                 bSRSSet = true;
                  if( !EQUAL(pszSRS,"NULL") )
                  {
                     OGRSpatialReference oSRS;
@@ -592,7 +593,7 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
     int nSrcLayers = 0;
     OGRLayer** papoSrcLayers = NULL;
 
-    for( psSubNode=psLTree->psChild;
+    for( CPLXMLNode *psSubNode = psLTree->psChild;
          psSubNode != NULL;
          psSubNode=psSubNode->psNext )
     {
@@ -600,7 +601,7 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
             continue;
 
         OGRLayer* poSrcLayer = InstantiateLayer(psSubNode, pszVRTDirectory,
-                                           bUpdate, nRecLevel + 1);
+                                                bUpdate, nRecLevel + 1);
         if( poSrcLayer != NULL )
         {
             papoSrcLayers = (OGRLayer**)
@@ -614,11 +615,10 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Cannot find source layers" );
-        int iField;
-        for(iField = 0; iField < nFields; iField++)
+        for( int iField = 0; iField < nFields; iField++ )
             delete papoFields[iField];
         CPLFree(papoFields);
-        for(iField = 0; iField < nGeomFields; iField++)
+        for( int iField = 0; iField < nGeomFields; iField++ )
             delete papoGeomFields[iField];
         CPLFree(papoGeomFields);
         return NULL;
@@ -642,7 +642,7 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
 /* -------------------------------------------------------------------- */
 /*      Set the PreserveSrcFID attribute.                               */
 /* -------------------------------------------------------------------- */
-    int bPreserveSrcFID = FALSE;
+    bool bPreserveSrcFID = false;
     const char* pszPreserveFID = CPLGetXMLValue( psLTree, "PreserveSrcFID", NULL );
     if( pszPreserveFID != NULL )
         bPreserveSrcFID = CPLTestBool(pszPreserveFID);
@@ -702,10 +702,11 @@ OGRLayer*  OGRVRTDataSource::InstantiateUnionLayer(
 /*                     InstantiateLayerInternal()                       */
 /************************************************************************/
 
-OGRLayer* OGRVRTDataSource::InstantiateLayerInternal(CPLXMLNode *psLTree,
-                                                const char *pszVRTDirectory,
-                                                int bUpdate,
-                                                int nRecLevel)
+OGRLayer* OGRVRTDataSource::InstantiateLayerInternal(
+    CPLXMLNode *psLTree,
+    const char *pszVRTDirectory,
+    int bUpdate,
+    int nRecLevel )
 {
 /* -------------------------------------------------------------------- */
 /*      Create the layer object.                                        */
@@ -745,16 +746,17 @@ typedef struct
     OGRVRTDataSource* poDS;
     CPLXMLNode *psNode;
     char       *pszVRTDirectory;
-    int         bUpdate;
+    bool        bUpdate;
 } PooledInitData;
 
 static OGRLayer* OGRVRTOpenProxiedLayer(void* pUserData)
 {
     PooledInitData* pData = (PooledInitData*) pUserData;
-    return pData->poDS->InstantiateLayerInternal(pData->psNode,
-                                            pData->pszVRTDirectory,
-                                            pData->bUpdate,
-                                            0);
+    return pData->poDS->InstantiateLayerInternal(
+        pData->psNode,
+        pData->pszVRTDirectory,
+        pData->bUpdate,
+        0);
 }
 
 /************************************************************************/
@@ -772,10 +774,11 @@ static void OGRVRTFreeProxiedLayerUserData(void* pUserData)
 /*                          InstantiateLayer()                          */
 /************************************************************************/
 
-OGRLayer* OGRVRTDataSource::InstantiateLayer(CPLXMLNode *psLTree,
-                                        const char *pszVRTDirectory,
-                                        int bUpdate,
-                                        int nRecLevel)
+OGRLayer* OGRVRTDataSource::InstantiateLayer(
+    CPLXMLNode *psLTree,
+    const char *pszVRTDirectory,
+    int bUpdate,
+    int nRecLevel )
 {
     if( poLayerPool != NULL && EQUAL(psLTree->pszValue,"OGRVRTLayer"))
     {
@@ -783,7 +786,7 @@ OGRLayer* OGRVRTDataSource::InstantiateLayer(CPLXMLNode *psLTree,
         pData->poDS = this;
         pData->psNode = psLTree;
         pData->pszVRTDirectory = CPLStrdup(pszVRTDirectory);
-        pData->bUpdate = bUpdate;
+        pData->bUpdate = CPL_TO_BOOL(bUpdate);
         return new OGRProxiedLayer(poLayerPool,
                                     OGRVRTOpenProxiedLayer,
                                     OGRVRTFreeProxiedLayerUserData,
@@ -819,13 +822,13 @@ static int CountOGRVRTLayers(CPLXMLNode *psTree)
 /*                             Initialize()                             */
 /************************************************************************/
 
-int OGRVRTDataSource::Initialize( CPLXMLNode *psTreeIn, const char *pszNewName,
-                                  int bUpdate )
+bool OGRVRTDataSource::Initialize( CPLXMLNode *psTreeIn, const char *pszNewName,
+                                   int bUpdate )
 
 {
     CPLAssert( nLayers == 0 );
 
-    this->psTree = psTreeIn;
+    psTree = psTreeIn;
 
 /* -------------------------------------------------------------------- */
 /*      Set name, and capture the directory path so we can use it       */
@@ -845,7 +848,7 @@ int OGRVRTDataSource::Initialize( CPLXMLNode *psTreeIn, const char *pszNewName,
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Did not find the <OGRVRTDataSource> node in the root of the document,\n"
                   "this is not really an OGR VRT." );
-        return FALSE;
+        return false;
     }
 
 /* -------------------------------------------------------------------- */
@@ -904,7 +907,7 @@ int OGRVRTDataSource::Initialize( CPLXMLNode *psTreeIn, const char *pszNewName,
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -944,7 +947,7 @@ void OGRVRTDataSource::AddForbiddenNames(const char* pszOtherDSName)
 /*                         IsInForbiddenNames()                         */
 /************************************************************************/
 
-int OGRVRTDataSource::IsInForbiddenNames(const char* pszOtherDSName)
+bool OGRVRTDataSource::IsInForbiddenNames( const char* pszOtherDSName ) const
 {
     return aosOtherDSNameSet.find(pszOtherDSName) != aosOtherDSNameSet.end();
 }
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
index 546031a..73c53c1 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrvrtdriver.cpp 32982 2016-01-14 16:53:57Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTDriver class.
@@ -31,7 +30,7 @@
 #include "ogr_vrt.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrvrtdriver.cpp 32982 2016-01-14 16:53:57Z goatbar $");
+CPL_CVSID("$Id: ogrvrtdriver.cpp 36682 2016-12-04 20:34:45Z rouault $");
 
 /************************************************************************/
 /*                           OGRVRTErrorHandler()                       */
@@ -153,7 +152,7 @@ static GDALDataset *OGRVRTDriverOpen( GDALOpenInfo* poOpenInfo )
             CPLPopErrorHandler();
             if( !bRet )
             {
-                if( aosErrors.size() > 0 &&
+                if( !aosErrors.empty() &&
                     strstr(aosErrors[0].c_str(), "missing libxml2 support") == NULL )
                 {
                     for(size_t i = 0; i < aosErrors.size(); i++)
diff --git a/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp b/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
index 69b3355..681141d 100644
--- a/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
+++ b/ogr/ogrsf_frmts/vrt/ogrvrtlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrvrtlayer.cpp 34203 2016-05-10 14:06:35Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRVRTLayer class.
@@ -34,11 +33,10 @@
 #include "ogrpgeogeometry.h"
 #include <string>
 
-CPL_CVSID("$Id: ogrvrtlayer.cpp 34203 2016-05-10 14:06:35Z rouault $");
+CPL_CVSID("$Id: ogrvrtlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 #define UNSUPPORTED_OP_READ_ONLY "%s : unsupported operation on a read-only datasource."
 
-
 /************************************************************************/
 /*                       OGRVRTGeomFieldProps()                         */
 /************************************************************************/
@@ -46,7 +44,7 @@ CPL_CVSID("$Id: ogrvrtlayer.cpp 34203 2016-05-10 14:06:35Z rouault $");
 OGRVRTGeomFieldProps::OGRVRTGeomFieldProps() :
     eGeomType(wkbUnknown),
     poSRS(NULL),
-    bSrcClip(FALSE),
+    bSrcClip(false),
     poSrcRegion(NULL),
     eGeometryStyle(VGS_Direct),
     iGeomField(-1),
@@ -54,10 +52,10 @@ OGRVRTGeomFieldProps::OGRVRTGeomFieldProps() :
     iGeomYField(-1),
     iGeomZField(-1),
     iGeomMField(-1),
-    bReportSrcColumn(TRUE),
-    bUseSpatialSubquery(FALSE),
-    bNullable(TRUE)
-{ }
+    bReportSrcColumn(true),
+    bUseSpatialSubquery(false),
+    bNullable(true)
+{}
 
 /************************************************************************/
 /*                      ~OGRVRTGeomFieldProps()                         */
@@ -75,25 +73,25 @@ OGRVRTGeomFieldProps::~OGRVRTGeomFieldProps()
 /*                            OGRVRTLayer()                             */
 /************************************************************************/
 
-OGRVRTLayer::OGRVRTLayer(OGRVRTDataSource* poDSIn) :
+OGRVRTLayer::OGRVRTLayer( OGRVRTDataSource* poDSIn ) :
     poDS(poDSIn),
-    bHasFullInitialized(FALSE),
+    bHasFullInitialized(false),
     psLTree(NULL),
     poFeatureDefn(NULL),
     poSrcDS(NULL),
     poSrcLayer(NULL),
     poSrcFeatureDefn(NULL),
-    bNeedReset(TRUE),
-    bSrcLayerFromSQL(FALSE),
-    bSrcDSShared(FALSE),
-    bAttrFilterPassThrough(FALSE),
+    bNeedReset(true),
+    bSrcLayerFromSQL(false),
+    bSrcDSShared(false),
+    bAttrFilterPassThrough(false),
     pszAttrFilter(NULL),
     iFIDField(-1),  // -1 means pass through.
     iStyleField(-1),  // -1 means pass through.
-    bUpdate(FALSE),
+    bUpdate(false),
     nFeatureCount(-1),
-    bError(FALSE)
-{ }
+    bError(false)
+{}
 
 /************************************************************************/
 /*                            ~OGRVRTLayer()                            */
@@ -152,12 +150,13 @@ OGRFeatureDefn* OGRVRTLayer::GetSrcLayerDefn()
 /*                         FastInitialize()                             */
 /************************************************************************/
 
-int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTreeIn, const char *pszVRTDirectory,
-                             int bUpdateIn)
+bool OGRVRTLayer::FastInitialize( CPLXMLNode *psLTreeIn,
+                                  const char *pszVRTDirectory,
+                                  int bUpdateIn )
 
 {
-    this->psLTree = psLTreeIn;
-    this->bUpdate = bUpdateIn;
+    psLTree = psLTreeIn;
+    bUpdate = CPL_TO_BOOL(bUpdateIn);
     osVRTDirectory = pszVRTDirectory;
 
     if( !EQUAL(psLTree->pszValue,"OGRVRTLayer") )
@@ -187,8 +186,9 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTreeIn, const char *pszVRTDirect
          pszGType = CPLGetXMLValue( psGeometryFieldNode, "GeometryType", NULL );
      if( pszGType != NULL )
      {
-         int l_bError;
-         OGRwkbGeometryType eGeomType = OGRVRTGetGeometryType(pszGType, &l_bError);
+         int l_bError = FALSE;
+         OGRwkbGeometryType eGeomType =
+             OGRVRTGetGeometryType(pszGType, &l_bError);
          if( l_bError )
          {
              CPLError( CE_Failure, CPLE_AppDefined,
@@ -211,8 +211,10 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTreeIn, const char *pszVRTDirect
          pszLayerSRS = CPLGetXMLValue( psGeometryFieldNode, "SRS", NULL );
      if( pszLayerSRS != NULL )
      {
-         if( apoGeomFieldProps.size() == 0 )
+         if( apoGeomFieldProps.empty() )
+         {
              apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
+         }
          if( !(EQUAL(pszLayerSRS,"NULL")) )
          {
              OGRSpatialReference oSRS;
@@ -253,8 +255,10 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTreeIn, const char *pszVRTDirect
      if( pszExtentXMin != NULL && pszExtentYMin != NULL &&
          pszExtentXMax != NULL && pszExtentYMax != NULL )
      {
-         if( apoGeomFieldProps.size() == 0 )
+         if( apoGeomFieldProps.empty() )
+         {
              apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
+         }
          apoGeomFieldProps[0]->sStaticEnvelope.MinX = CPLAtof(pszExtentXMin);
          apoGeomFieldProps[0]->sStaticEnvelope.MinY = CPLAtof(pszExtentYMin);
          apoGeomFieldProps[0]->sStaticEnvelope.MaxX = CPLAtof(pszExtentXMax);
@@ -268,9 +272,9 @@ int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTreeIn, const char *pszVRTDirect
 /*                       ParseGeometryField()                           */
 /************************************************************************/
 
-int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
-                                    CPLXMLNode* psNodeParent,
-                                    OGRVRTGeomFieldProps* poProps)
+bool OGRVRTLayer::ParseGeometryField( CPLXMLNode* psNode,
+                                      CPLXMLNode* psNodeParent,
+                                      OGRVRTGeomFieldProps* poProps )
 {
     const char* pszName = CPLGetXMLValue( psNode, "name", NULL);
     poProps->osName = (pszName ) ? pszName : "";
@@ -289,14 +293,14 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
         pszGType = CPLGetXMLValue( psNodeParent, "GeometryType", NULL );
     if( pszGType != NULL )
     {
-        int l_bError;
+        int l_bError = FALSE;
         poProps->eGeomType = OGRVRTGetGeometryType(pszGType, &l_bError);
         if( l_bError )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                      "GeometryType %s not recognised.",
                       pszGType );
-            return FALSE;
+            return false;
         }
     }
 
@@ -337,7 +341,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to identify source X or Y field for PointFromColumns encoding." );
-            return FALSE;
+            return false;
         }
 
         if( pszGType == NULL )
@@ -353,7 +357,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                 "encoding=\"%s\" not recognised.", pszEncoding );
-        return FALSE;
+        return false;
     }
 
     if( poProps->eGeometryStyle == VGS_WKT
@@ -370,7 +374,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
             CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to identify source field '%s' for geometry.",
                     pszFieldName );
-            return FALSE;
+            return false;
         }
     }
     else if( poProps->eGeometryStyle == VGS_Direct )
@@ -389,7 +393,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Unable to identify source geometry field '%s' for geometry.",
                         pszFieldName );
-                return FALSE;
+                return false;
             }
         }
         else if( GetSrcLayerDefn()->GetGeomFieldCount() == 1 )
@@ -400,7 +404,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                     "Unable to identify source geometry field." );
-            return FALSE;
+            return false;
         }
     }
 
@@ -454,7 +458,7 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
              {
                  CPLError( CE_Failure, CPLE_AppDefined,
                            "Failed to import SRS `%s'.", pszSRS );
-                 return FALSE;
+                 return false;
              }
              poProps->poSRS = oSRS.Clone();
          }
@@ -498,14 +502,14 @@ int OGRVRTLayer::ParseGeometryField(CPLXMLNode* psNode,
 
     poProps->bNullable = CPLTestBool(CPLGetXMLValue( psNode, "nullable", "TRUE" ));
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                         FullInitialize()                             */
 /************************************************************************/
 
-int OGRVRTLayer::FullInitialize()
+bool OGRVRTLayer::FullInitialize()
 
 {
     const char *pszSharedSetting = NULL;
@@ -513,18 +517,18 @@ int OGRVRTLayer::FullInitialize()
     const char *pszSrcFIDFieldName = NULL;
     const char *pszStyleFieldName = NULL;
     CPLXMLNode *psChild = NULL;
-    int bFoundGeometryField = FALSE;
+    bool bFoundGeometryField = false;
 
-    if (bHasFullInitialized)
-        return TRUE;
+    if( bHasFullInitialized )
+        return true;
 
-    bHasFullInitialized = TRUE;
+    bHasFullInitialized = true;
 
     poFeatureDefn = new OGRFeatureDefn( osName );
     poFeatureDefn->Reference();
 
     if (poDS->GetRecursionDetected())
-        return FALSE;
+        return false;
 
 /* -------------------------------------------------------------------- */
 /*      Figure out the data source name.  It may be treated relative    */
@@ -543,7 +547,7 @@ int OGRVRTLayer::FullInitialize()
                                        "0")) )
     {
         static const char* const apszPrefixes[] = { "CSV:", "GPSBABEL:" };
-        int bDone = FALSE;
+        bool bDone = false;
         for( size_t i = 0; i < sizeof(apszPrefixes) / sizeof(apszPrefixes[0]); i ++)
         {
             const char* pszPrefix = apszPrefixes[i];
@@ -558,7 +562,7 @@ int OGRVRTLayer::FullInitialize()
                 osPrefix.resize(pszLastPart - pszSrcDSName);
                 pszSrcDSName = CPLStrdup( (osPrefix +
                     CPLProjectRelativeFilename( osVRTDirectory, pszLastPart )).c_str() );
-                bDone = TRUE;
+                bDone = true;
                 break;
             }
         }
@@ -594,7 +598,7 @@ int OGRVRTLayer::FullInitialize()
 
     // update mode doesn't make sense if we have a SrcSQL element
     if (CPLGetXMLValue( psLTree, "SrcSQL", NULL ) != NULL)
-        bUpdate = FALSE;
+        bUpdate = false;
 
 /* -------------------------------------------------------------------- */
 /*      Try to access the datasource.                                   */
@@ -612,7 +616,7 @@ try_again:
     }
     else if( bSrcDSShared )
     {
-        if (poDS->IsInForbiddenNames(pszSrcDSName))
+        if( poDS->IsInForbiddenNames(pszSrcDSName) )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cyclic VRT opening detected !");
             poDS->SetRecursionDetected();
@@ -669,12 +673,12 @@ try_again:
 
     if( poSrcDS == NULL )
     {
-        if (bUpdate)
+        if( bUpdate )
         {
             CPLError( CE_Warning, CPLE_AppDefined,
                       "Cannot open datasource `%s' in update mode. Trying again in read-only mode",
                        pszSrcDSName );
-            bUpdate = FALSE;
+            bUpdate = false;
             goto try_again;
         }
         if( strlen(CPLGetLastErrorMsg()) == 0 )
@@ -707,7 +711,7 @@ try_again:
                       pszSQL );
             goto error;
         }
-        bSrcLayerFromSQL = TRUE;
+        bSrcLayerFromSQL = true;
     }
 
 /* -------------------------------------------------------------------- */
@@ -744,9 +748,10 @@ try_again:
         {
             if( !bFoundGeometryField )
             {
-                bFoundGeometryField = TRUE;
+                bFoundGeometryField = true;
 
-                // Recreate the first one if already taken into account in FastInitialize()
+                // Recreate the first one if already taken into account in
+                // FastInitialize().
                 if( apoGeomFieldProps.size() == 1 )
                 {
                     delete apoGeomFieldProps[0];
@@ -756,7 +761,7 @@ try_again:
 
             apoGeomFieldProps.push_back(new OGRVRTGeomFieldProps());
             if( !ParseGeometryField(psChild, psLTree,
-                                    apoGeomFieldProps[apoGeomFieldProps.size()-1] ) )
+                                    apoGeomFieldProps.back() ) )
             {
                 goto error;
             }
@@ -776,7 +781,7 @@ try_again:
             goto error;
     }
 
-    if( apoGeomFieldProps.size() == 0 &&
+    if( apoGeomFieldProps.empty() &&
         CPLGetXMLValue( psLTree, "GeometryType", NULL ) == NULL )
     {
         /* If no GeometryField is found but source geometry fields */
@@ -785,8 +790,7 @@ try_again:
                 iGeomField < GetSrcLayerDefn()->GetGeomFieldCount();
                 iGeomField++ )
         {
-            OGRVRTGeomFieldProps* poProps;
-            poProps = new OGRVRTGeomFieldProps();
+            OGRVRTGeomFieldProps* poProps = new OGRVRTGeomFieldProps();
             apoGeomFieldProps.push_back(poProps);
             OGRGeomFieldDefn* poFDefn =
                 GetSrcLayerDefn()->GetGeomFieldDefn(iGeomField);
@@ -795,7 +799,7 @@ try_again:
             if( poFDefn->GetSpatialRef() != NULL )
             poProps->poSRS = poFDefn->GetSpatialRef()->Clone();
             poProps->iGeomField = iGeomField;
-            poProps->bNullable = poFDefn->IsNullable();
+            poProps->bNullable = CPL_TO_BOOL(poFDefn->IsNullable());
         }
     }
 
@@ -813,7 +817,7 @@ try_again:
 /* -------------------------------------------------------------------- */
 /*      Figure out what should be used as an FID.                       */
 /* -------------------------------------------------------------------- */
-     bAttrFilterPassThrough = TRUE;
+     bAttrFilterPassThrough = true;
      pszSrcFIDFieldName = CPLGetXMLValue( psLTree, "FID", NULL );
 
      if( pszSrcFIDFieldName != NULL )
@@ -829,11 +833,13 @@ try_again:
          }
 
          // User facing FID column name. If not defined we will report the
-         // source FID column name only if it is exposed as a field too (#4637)
+         // source FID column name only if it is exposed as a field too (#4637).
          osFIDFieldName = CPLGetXMLValue( psLTree, "FID.name", "" );
 
          if( !EQUAL(pszSrcFIDFieldName, poSrcLayer->GetFIDColumn()) )
-             bAttrFilterPassThrough = FALSE;
+         {
+             bAttrFilterPassThrough = false;
+         }
      }
 
 /* -------------------------------------------------------------------- */
@@ -854,7 +860,9 @@ try_again:
          }
 
          if( !EQUAL(pszStyleFieldName, "OGR_STYLE") )
-             bAttrFilterPassThrough = FALSE;
+         {
+             bAttrFilterPassThrough = false;
+         }
      }
 
 /* ==================================================================== */
@@ -884,9 +892,9 @@ try_again:
 
              if( pszArg != NULL )
              {
-                 int iType;
+                 int iType = 0;  // Used after for.
 
-                 for( iType = 0; iType <= (int) OFTMaxType; iType++ )
+                 for( ; iType <= (int) OFTMaxType; iType++ )
                  {
                      if( EQUAL(pszArg,OGRFieldDefn::GetFieldTypeName(
                                    (OGRFieldType)iType)) )
@@ -911,9 +919,9 @@ try_again:
              pszArg = CPLGetXMLValue( psChild, "subtype", NULL );
              if( pszArg != NULL )
              {
-                 int iType;
                  OGRFieldSubType eSubType = OFSTNone;
 
+                 int iType = 0;  // Used after for.
                  for( iType = 0; iType <= (int) OFSTMaxSubType; iType++ )
                  {
                      if( EQUAL(pszArg,OGRFieldDefn::GetFieldSubTypeName(
@@ -969,7 +977,8 @@ try_again:
 /* -------------------------------------------------------------------- */
 /*      Nullable attribute.                                             */
 /* -------------------------------------------------------------------- */
-             int bNullable = CPLTestBool(CPLGetXMLValue( psChild, "nullable", "true" ));
+             const bool bNullable =
+                 CPLTestBool(CPLGetXMLValue( psChild, "nullable", "true" ));
              oFieldDefn.SetNullable(bNullable);
 
 /* -------------------------------------------------------------------- */
@@ -1006,12 +1015,12 @@ try_again:
              }
 
              if (iSrcField < 0 || (pszArg != NULL && strcmp(pszArg, pszName) != 0))
-                 bAttrFilterPassThrough = FALSE;
+                 bAttrFilterPassThrough = false;
              else
              {
                  OGRFieldDefn* poSrcFieldDefn = GetSrcLayerDefn()->GetFieldDefn(iSrcField);
                  if (poSrcFieldDefn->GetType() != oFieldDefn.GetType())
-                     bAttrFilterPassThrough = FALSE;
+                     bAttrFilterPassThrough = false;
              }
 
              anSrcField.push_back( iSrcField );
@@ -1025,15 +1034,14 @@ try_again:
 /* -------------------------------------------------------------------- */
      if( poFeatureDefn->GetFieldCount() == 0 )
      {
-         int iSrcField;
          int nSrcFieldCount = GetSrcLayerDefn()->GetFieldCount();
 
-         for( iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++ )
+         for( int iSrcField = 0; iSrcField < nSrcFieldCount; iSrcField++ )
          {
-             int bSkip = FALSE;
+             bool bSkip = false;
              for( size_t iGF = 0; iGF < apoGeomFieldProps.size(); iGF++ )
              {
-                if( apoGeomFieldProps[iGF]->bReportSrcColumn == FALSE &&
+                if( !apoGeomFieldProps[iGF]->bReportSrcColumn &&
                     (iSrcField == apoGeomFieldProps[iGF]->iGeomXField ||
                      iSrcField == apoGeomFieldProps[iGF]->iGeomYField ||
                      iSrcField == apoGeomFieldProps[iGF]->iGeomZField ||
@@ -1041,7 +1049,7 @@ try_again:
                      (apoGeomFieldProps[iGF]->eGeometryStyle != VGS_Direct &&
                       iSrcField == apoGeomFieldProps[iGF]->iGeomField)) )
                 {
-                    bSkip = TRUE;
+                    bSkip = true;
                     break;
                 }
              }
@@ -1053,7 +1061,7 @@ try_again:
              abDirectCopy.push_back( TRUE );
          }
 
-         bAttrFilterPassThrough = TRUE;
+         bAttrFilterPassThrough = true;
      }
 
 /* -------------------------------------------------------------------- */
@@ -1063,13 +1071,13 @@ try_again:
      if (poSrcFeatureDefn != NULL && iFIDField == -1 && iStyleField == -1 &&
          poSrcFeatureDefn->IsSame(poFeatureDefn))
      {
-        int bSame = TRUE;
+        bool bSame = true;
         for(size_t i = 0; i < apoGeomFieldProps.size(); i++ )
         {
             if( apoGeomFieldProps[i]->eGeometryStyle != VGS_Direct ||
                 apoGeomFieldProps[i]->iGeomField != (int)i )
             {
-                bSame = FALSE;
+                bSame = false;
                 break;
             }
         }
@@ -1104,15 +1112,15 @@ try_again:
 
      SetIgnoredFields(NULL);
 
-     return TRUE;
+     return true;
 
 error:
-    bError = TRUE;
+    bError = true;
     CPLFree( pszSrcDSName );
     poFeatureDefn->Release();
     poFeatureDefn = new OGRFeatureDefn( osName );
     poFeatureDefn->Reference();
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -1122,17 +1130,17 @@ error:
 void OGRVRTLayer::ResetReading()
 
 {
-    bNeedReset = TRUE;
+    bNeedReset = true;
 }
 
 /************************************************************************/
 /*                         ResetSourceReading()                         */
 /************************************************************************/
 
-int OGRVRTLayer::ResetSourceReading()
+bool OGRVRTLayer::ResetSourceReading()
 
 {
-    int bSuccess = TRUE;
+    bool bSuccess = true;
 
 /* -------------------------------------------------------------------- */
 /*      Do we want to let source layer do spatial restriction?          */
@@ -1150,7 +1158,7 @@ int OGRVRTLayer::ResetSourceReading()
 
             pszXField = poXField->GetNameRef();
             pszYField = poYField->GetNameRef();
-            if (apoGeomFieldProps[i]->bUseSpatialSubquery)
+            if( apoGeomFieldProps[i]->bUseSpatialSubquery )
             {
                 OGRFieldType xType = poXField->GetType();
                 OGRFieldType yType = poYField->GetType();
@@ -1161,10 +1169,10 @@ int OGRVRTLayer::ResetSourceReading()
                             "The '%s' and/or '%s' fields of the source layer are not declared as numeric fields,\n"
                             "so the spatial filter cannot be turned into an attribute filter on them",
                             pszXField, pszYField);
-                    apoGeomFieldProps[i]->bUseSpatialSubquery = FALSE;
+                    apoGeomFieldProps[i]->bUseSpatialSubquery = false;
                 }
             }
-            if (apoGeomFieldProps[i]->bUseSpatialSubquery)
+            if( apoGeomFieldProps[i]->bUseSpatialSubquery )
             {
                 OGREnvelope sEnvelope;
                 CPLString osFilter;
@@ -1201,38 +1209,38 @@ int OGRVRTLayer::ResetSourceReading()
 
                 if( !CPLIsInf(sEnvelope.MaxX) )
                 {
-                    if( osFilter.size() ) osFilter += " AND ";
+                    if( !osFilter.empty() ) osFilter += " AND ";
                     osFilter += CPLSPrintf("%s < %.15g", pszXField, sEnvelope.MaxX);
                 }
                 else if( sEnvelope.MaxX < 0 )
                 {
-                    if( osFilter.size() ) osFilter += " AND ";
+                    if( !osFilter.empty() ) osFilter += " AND ";
                     osFilter += "0 = 1";
                 }
 
                 if( !CPLIsInf(sEnvelope.MinY) )
                 {
-                    if( osFilter.size() ) osFilter += " AND ";
+                    if( !osFilter.empty() ) osFilter += " AND ";
                     osFilter += CPLSPrintf("%s > %.15g", pszYField, sEnvelope.MinY);
                 }
                 else if( sEnvelope.MinY > 0 )
                 {
-                    if( osFilter.size() ) osFilter += " AND ";
+                    if( !osFilter.empty() ) osFilter += " AND ";
                     osFilter += "0 = 1";
                 }
 
                 if( !CPLIsInf(sEnvelope.MaxY) )
                 {
-                    if( osFilter.size() ) osFilter += " AND ";
+                    if( !osFilter.empty() ) osFilter += " AND ";
                     osFilter += CPLSPrintf("%s < %.15g", pszYField, sEnvelope.MaxY);
                 }
                 else if( sEnvelope.MaxY < 0 )
                 {
-                    if( osFilter.size() ) osFilter += " AND ";
+                    if( !osFilter.empty() ) osFilter += " AND ";
                     osFilter += "0 = 1";
                 }
 
-                if( osFilter.size() != 0 )
+                if( !osFilter.empty() )
                 {
                     pszFilter = CPLStrdup(osFilter);
                 }
@@ -1294,7 +1302,7 @@ int OGRVRTLayer::ResetSourceReading()
             }
             else
             {
-                int bDoIntersection = TRUE;
+                bool bDoIntersection = true;
                 if( m_bFilterIsEnvelope )
                 {
                     OGREnvelope sEnvelope;
@@ -1302,10 +1310,10 @@ int OGRVRTLayer::ResetSourceReading()
                     if( CPLIsInf(sEnvelope.MinX) && CPLIsInf(sEnvelope.MinY) &&
                         CPLIsInf(sEnvelope.MaxX) && CPLIsInf(sEnvelope.MaxY) &&
                         sEnvelope.MinX < 0 && sEnvelope.MinY < 0 &&
-                        sEnvelope.MaxY > 0 && sEnvelope.MaxY > 0 )
+                        sEnvelope.MaxX > 0 && sEnvelope.MaxY > 0 )
                     {
                         poSpatialGeom = poSrcRegion;
-                        bDoIntersection = FALSE;
+                        bDoIntersection = false;
                     }
                 }
                 if( bDoIntersection )
@@ -1321,9 +1329,11 @@ int OGRVRTLayer::ResetSourceReading()
             delete poSpatialGeom;
     }
     else
+    {
         poSrcLayer->SetSpatialFilter( NULL );
+    }
     poSrcLayer->ResetReading();
-    bNeedReset = FALSE;
+    bNeedReset = false;
 
     return bSuccess;
 }
@@ -1335,7 +1345,7 @@ int OGRVRTLayer::ResetSourceReading()
 OGRFeature *OGRVRTLayer::GetNextFeature()
 
 {
-    if (!bHasFullInitialized)
+    if( !bHasFullInitialized )
         FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected())
         return NULL;
@@ -1354,7 +1364,7 @@ OGRFeature *OGRVRTLayer::GetNextFeature()
         if( poSrcFeature == NULL )
             return NULL;
 
-        OGRFeature *poFeature;
+        OGRFeature *poFeature = NULL;
         if (poFeatureDefn == poSrcFeatureDefn)
         {
             poFeature = poSrcFeature;
@@ -1433,7 +1443,7 @@ retry:
 /* -------------------------------------------------------------------- */
     if( iStyleField != -1 )
     {
-        if( poSrcFeat->IsFieldSet(iStyleField) )
+        if( poSrcFeat->IsFieldSetAndNotNull(iStyleField) )
             poDstFeat->SetStyleString(
                 poSrcFeat->GetFieldAsString(iStyleField) );
     }
@@ -1475,8 +1485,8 @@ retry:
         }
         else if( eGeometryStyle == VGS_WKB && iGeomField != -1 )
         {
-            int nBytes;
-            GByte *pabyWKB;
+            int nBytes = 0;
+            GByte *pabyWKB = NULL;
             bool bNeedFree = false;
 
             if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
@@ -1505,9 +1515,9 @@ retry:
         }
         else if( eGeometryStyle == VGS_Shape && iGeomField != -1 )
         {
-            int nBytes;
-            GByte *pabyWKB;
-            int bNeedFree = FALSE;
+            int nBytes = 0;
+            GByte *pabyWKB = NULL;
+            bool bNeedFree = false;
 
             if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
             {
@@ -1518,7 +1528,7 @@ retry:
                 const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
 
                 pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
-                bNeedFree = TRUE;
+                bNeedFree = true;
             }
 
             if( pabyWKB != NULL )
@@ -1538,7 +1548,7 @@ retry:
         }
         else if( eGeometryStyle == VGS_PointFromColumns )
         {
-            OGRPoint* poPoint;
+            OGRPoint* poPoint = NULL;
             if( apoGeomFieldProps[i]->iGeomZField != -1 )
             {
                 poPoint = new OGRPoint( poSrcFeat->GetFieldAsDouble( apoGeomFieldProps[i]->iGeomXField ),
@@ -1588,9 +1598,7 @@ retry:
 /* -------------------------------------------------------------------- */
 /*      Copy fields.                                                    */
 /* -------------------------------------------------------------------- */
-    int iVRTField;
-
-    for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
+    for( int iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
     {
         if( anSrcField[iVRTField] == -1 )
             continue;
@@ -1598,7 +1606,7 @@ retry:
         OGRFieldDefn *poDstDefn = poFeatureDefn->GetFieldDefn( iVRTField );
         OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
 
-        if( !poSrcFeat->IsFieldSet( anSrcField[iVRTField] ) || poDstDefn->IsIgnored() )
+        if( !poSrcFeat->IsFieldSetAndNotNull( anSrcField[iVRTField] ) || poDstDefn->IsIgnored() )
             continue;
 
         if( abDirectCopy[iVRTField]
@@ -1623,7 +1631,6 @@ retry:
     return poDstFeat;
 }
 
-
 /************************************************************************/
 /*                             GetFeature()                             */
 /************************************************************************/
@@ -1631,10 +1638,10 @@ retry:
 OGRFeature *OGRVRTLayer::GetFeature( GIntBig nFeatureId )
 
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return NULL;
 
-    bNeedReset = TRUE;
+    bNeedReset = true;
 
 /* -------------------------------------------------------------------- */
 /*      If the FID is directly mapped, we can do a simple               */
@@ -1687,7 +1694,7 @@ OGRFeature *OGRVRTLayer::GetFeature( GIntBig nFeatureId )
 
 OGRErr OGRVRTLayer::SetNextByIndex( GIntBig nIndex )
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
 
     if( bNeedReset )
@@ -1827,13 +1834,10 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
 /* -------------------------------------------------------------------- */
 /*      Copy fields.                                                    */
 /* -------------------------------------------------------------------- */
-
-    int iVRTField;
-
-    for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
+    for( int iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
     {
-        int bSkip = FALSE;
-        for(int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
+        bool bSkip = false;
+        for( int i = 0; i < poFeatureDefn->GetGeomFieldCount(); i++ )
         {
             /* Do not set source geometry columns. Have been set just above */
             if ((apoGeomFieldProps[i]->eGeometryStyle != VGS_Direct &&
@@ -1843,7 +1847,7 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
                 anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomZField ||
                 anSrcField[iVRTField] == apoGeomFieldProps[i]->iGeomMField)
             {
-                bSkip = TRUE;
+                bSkip = true;
                 break;
             }
         }
@@ -1877,10 +1881,10 @@ OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeatu
 
 OGRErr OGRVRTLayer::ICreateFeature( OGRFeature* poVRTFeature )
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
 
-    if(!bUpdate)
+    if( !bUpdate )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   UNSUPPORTED_OP_READ_ONLY,
@@ -1915,10 +1919,10 @@ OGRErr OGRVRTLayer::ICreateFeature( OGRFeature* poVRTFeature )
 
 OGRErr OGRVRTLayer::ISetFeature( OGRFeature* poVRTFeature )
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
 
-    if(!bUpdate)
+    if( !bUpdate )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   UNSUPPORTED_OP_READ_ONLY,
@@ -1949,10 +1953,10 @@ OGRErr OGRVRTLayer::ISetFeature( OGRFeature* poVRTFeature )
 OGRErr OGRVRTLayer::DeleteFeature( GIntBig nFID )
 
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
 
-    if(!bUpdate )
+    if( !bUpdate )
     {
         CPLError( CE_Failure, CPLE_NotSupported,
                   UNSUPPORTED_OP_READ_ONLY,
@@ -1977,7 +1981,7 @@ OGRErr OGRVRTLayer::DeleteFeature( GIntBig nFID )
 OGRErr OGRVRTLayer::SetAttributeFilter( const char *pszNewQuery )
 
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
 
     if( bAttrFilterPassThrough )
@@ -2015,7 +2019,7 @@ int OGRVRTLayer::TestCapability( const char * pszCap )
          apoGeomFieldProps[0]->sStaticEnvelope.IsInit() )
         return TRUE;
 
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return FALSE;
 
     if ( EQUAL(pszCap,OLCFastFeatureCount) ||
@@ -2023,13 +2027,13 @@ int OGRVRTLayer::TestCapability( const char * pszCap )
     {
         if( m_poAttrQuery == NULL )
         {
-            int bForward = TRUE;
+            bool bForward = true;
             for( size_t i=0; i<apoGeomFieldProps.size();i++ )
             {
                 if( !(apoGeomFieldProps[i]->eGeometryStyle == VGS_Direct ||
                     (apoGeomFieldProps[i]->poSrcRegion == NULL && m_poFilterGeom == NULL)) )
                 {
-                    bForward = FALSE;
+                    bForward = false;
                     break;
                 }
             }
@@ -2089,7 +2093,7 @@ OGRSpatialReference *OGRVRTLayer::GetSpatialRef()
         apoGeomFieldProps.size() >= 1)
         return apoGeomFieldProps[0]->poSRS;
 
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return NULL;
 
     if( apoGeomFieldProps.size() >= 1 )
@@ -2119,7 +2123,7 @@ OGRErr OGRVRTLayer::GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce
         return OGRERR_NONE;
     }
 
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
 
     if ( apoGeomFieldProps[iGeomField]->eGeometryStyle == VGS_Direct &&
@@ -2158,7 +2162,7 @@ GIntBig OGRVRTLayer::GetFeatureCount( int bForce )
         return nFeatureCount;
     }
 
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return 0;
 
     if (TestCapability(OLCFastFeatureCount))
@@ -2172,7 +2176,6 @@ GIntBig OGRVRTLayer::GetFeatureCount( int bForce )
     return OGRLayer::GetFeatureCount( bForce );
 }
 
-
 /************************************************************************/
 /*                          SetSpatialFilter()                          */
 /************************************************************************/
@@ -2194,11 +2197,11 @@ void OGRVRTLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
         return;
     }
 
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return;
 
     if( apoGeomFieldProps[iGeomField]->eGeometryStyle == VGS_Direct)
-        bNeedReset = TRUE;
+        bNeedReset = true;
 
     m_iGeomFieldFilter = iGeomField;
     if( InstallFilter( poGeomIn ) )
@@ -2211,7 +2214,7 @@ void OGRVRTLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
 
 OGRErr OGRVRTLayer::SyncToDisk()
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
 
     return poSrcLayer->SyncToDisk();
@@ -2223,7 +2226,7 @@ OGRErr OGRVRTLayer::SyncToDisk()
 
 OGRFeatureDefn *OGRVRTLayer::GetLayerDefn()
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
 
     return poFeatureDefn;
 }
@@ -2251,13 +2254,13 @@ OGRwkbGeometryType OGRVRTLayer::GetGeomType()
 
 const char * OGRVRTLayer::GetFIDColumn()
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return "";
 
-    if( osFIDFieldName.size() )
+    if( !osFIDFieldName.empty() )
         return osFIDFieldName;
 
-    const char* pszFIDColumn;
+    const char* pszFIDColumn = NULL;
     if (iFIDField == -1)
     {
         /* If pass-through, then query the source layer FID column */
@@ -2285,8 +2288,9 @@ const char * OGRVRTLayer::GetFIDColumn()
 
 OGRErr OGRVRTLayer::StartTransaction()
 {
-    if (!bHasFullInitialized) FullInitialize();
-    if (!poSrcLayer || !bUpdate || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
+    if( !bHasFullInitialized ) FullInitialize();
+    if( !poSrcLayer || !bUpdate || poDS->GetRecursionDetected() )
+        return OGRERR_FAILURE;
 
     return poSrcLayer->StartTransaction();
 }
@@ -2297,8 +2301,9 @@ OGRErr OGRVRTLayer::StartTransaction()
 
 OGRErr OGRVRTLayer::CommitTransaction()
 {
-    if (!bHasFullInitialized) FullInitialize();
-    if (!poSrcLayer || !bUpdate || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
+    if( !bHasFullInitialized ) FullInitialize();
+    if( !poSrcLayer || !bUpdate || poDS->GetRecursionDetected() )
+        return OGRERR_FAILURE;
 
     return poSrcLayer->CommitTransaction();
 }
@@ -2309,8 +2314,9 @@ OGRErr OGRVRTLayer::CommitTransaction()
 
 OGRErr OGRVRTLayer::RollbackTransaction()
 {
-    if (!bHasFullInitialized) FullInitialize();
-    if (!poSrcLayer || !bUpdate || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
+    if( !bHasFullInitialized ) FullInitialize();
+    if( !poSrcLayer || !bUpdate || poDS->GetRecursionDetected() )
+        return OGRERR_FAILURE;
 
     return poSrcLayer->RollbackTransaction();
 }
@@ -2321,7 +2327,7 @@ OGRErr OGRVRTLayer::RollbackTransaction()
 
 OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return OGRERR_FAILURE;
 
     if( !poSrcLayer->TestCapability(OLCIgnoreFields) )
@@ -2353,10 +2359,10 @@ OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
                 int iSrcField = anSrcField[iVRTField];
                 if (iSrcField >= 0)
                 {
-                    /* If we are asked to ignore x or y for a VGS_PointFromColumns */
-                    /* geometry field, we must NOT pass that order to the underlying */
-                    /* layer */
-                    int bOKToIgnore = TRUE;
+                    // If we are asked to ignore x or y for a
+                    // VGS_PointFromColumns geometry field, we must NOT pass
+                    // that order to the underlying layer.
+                    bool bOKToIgnore = true;
                     for(int iGeomVRTField = 0;
                             iGeomVRTField < GetLayerDefn()->GetGeomFieldCount(); iGeomVRTField++)
                     {
@@ -2365,7 +2371,7 @@ OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
                              iSrcField == apoGeomFieldProps[iGeomVRTField]->iGeomZField ||
                              iSrcField == apoGeomFieldProps[iGeomVRTField]->iGeomMField) )
                         {
-                            bOKToIgnore = FALSE;
+                            bOKToIgnore = false;
                             break;
                         }
                     }
@@ -2487,7 +2493,7 @@ OGRErr OGRVRTLayer::SetIgnoredFields( const char **papszFields )
 
 GDALDataset* OGRVRTLayer::GetSrcDataset()
 {
-    if (!bHasFullInitialized) FullInitialize();
+    if( !bHasFullInitialized ) FullInitialize();
     if (!poSrcLayer || poDS->GetRecursionDetected()) return NULL;
     return poSrcDS;
 }
diff --git a/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h b/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h
index a56b57e..f26cbd3 100644
--- a/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h
+++ b/ogr/ogrsf_frmts/walk/ogis_geometry_wkb_struct.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogis_geometry_wkb_struct.h
+ * $Id: ogis_geometry_wkb_struct.h$
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Definition of GeometryWkb Structs
@@ -56,6 +56,8 @@
 #define CPL_LSBPTRPOINTS(p,n)
 #endif
 
+namespace OGRWALK {
+
 struct Point3D {
     double x;
     double y;
@@ -87,7 +89,7 @@ typedef Point Vector;        //Space Vector    {dx, dy, dz}
 /* is not allowed.                                                        */
 /**************************************************************************/
 
-enum wkLineType {
+typedef enum {
     wkLineTypePoint        =0,   // Point
     wkLineTypeStraight    =1,    // Straightline
     wkLineTypeBezier    =2,      // Bezier
@@ -99,7 +101,7 @@ enum wkLineType {
     wkLineTypeRectCircle=8,      // Rectangular Circle; 2 points
     wkLineTypeBCurve    =9,      // B Curve
     wkLineTypeStrainCurve =10,   // Strain Curve
-};
+} wkLineType;
 
 struct CurveSegment {
     GUInt32 lineType;
@@ -229,4 +231,20 @@ public:
     WKBGeometry () { wkbType=wkbUnknown; }
 };
 
+} /* namespace OGRWALK */
+
+using OGRWALK::wkLineType;
+using OGRWALK::Point;
+using OGRWALK::CurveSegment;
+using OGRWALK::LineString;
+using OGRWALK::WKBSimpleGeometry;
+using OGRWALK::WKBPoint;
+using OGRWALK::WKBLineString;
+using OGRWALK::WKBPolygon;
+using OGRWALK::WKBMultiPoint;
+using OGRWALK::WKBMultiLineString;
+using OGRWALK::WKBMultiPolygon;
+using OGRWALK::WKBGeometryCollection;
+using OGRWALK::WKBGeometry;
+
 #endif /* ndef OGIS_GEOMETRY_WKB_STRUCT_H */
diff --git a/ogr/ogrsf_frmts/walk/ogrwalk.h b/ogr/ogrsf_frmts/walk/ogrwalk.h
index 4c076c4..fcce28b 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalk.h
+++ b/ogr/ogrsf_frmts/walk/ogrwalk.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrwalk.h
+ * $Id: ogrwalk.h$
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Definition of classes for OGR Walk driver.
@@ -64,7 +64,7 @@ protected:
 
     OGRWalkDataSource    *poDS;
 
-    int                bGeomColumnWKB;
+    bool               bGeomColumnWKB;
     char               *pszGeomColumn;
     char               *pszFIDColumn;
 
@@ -78,18 +78,18 @@ protected:
 
 public:
                         OGRWalkLayer();
-                        ~OGRWalkLayer();
+                        virtual ~OGRWalkLayer();
 
-    void                ResetReading();
-    OGRFeature *        GetNextFeature();
+    void                ResetReading() override;
+    OGRFeature *        GetNextFeature() override;
     OGRFeature *        GetNextRawFeature();
 
-    OGRFeatureDefn *    GetLayerDefn() { return poFeatureDefn; }
+    OGRFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
 
-    int         TestCapability( const char * ) { return FALSE; }
+    int         TestCapability( const char * ) override { return FALSE; }
 
-    virtual const char * GetFIDColumn ();
-    virtual const char * GetGeometryColumn ();
+    virtual const char * GetFIDColumn () override;
+    virtual const char * GetGeometryColumn () override;
 };
 
 /************************************************************************/
@@ -103,13 +103,13 @@ class OGRWalkTableLayer : public OGRWalkLayer
     void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *  GetStatement() override;
 
     OGREnvelope         sExtent;
 
 public:
-                        OGRWalkTableLayer( OGRWalkDataSource * );
-                        ~OGRWalkTableLayer();
+    explicit            OGRWalkTableLayer( OGRWalkDataSource * );
+                        virtual ~OGRWalkTableLayer();
 
     CPLErr              Initialize( const char *pszTableName,
                                     const char *pszGeomCol,
@@ -119,16 +119,16 @@ public:
                                     double maxN,
                                     const char *pszMemo );
 
-    virtual void        ResetReading();
-    virtual GIntBig     GetFeatureCount( int );
+    virtual void        ResetReading() override;
+    virtual GIntBig     GetFeatureCount( int ) override;
 
-    virtual OGRErr      SetAttributeFilter( const char * );
-    virtual OGRFeature *GetFeature( GIntBig nFeatureId );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
+    virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
 
-    virtual int         TestCapability( const char * );
+    virtual int         TestCapability( const char * ) override;
 
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
@@ -143,16 +143,16 @@ class OGRWalkSelectLayer : public OGRWalkLayer
     void                ClearStatement();
     OGRErr              ResetStatement();
 
-    virtual CPLODBCStatement *  GetStatement();
+    virtual CPLODBCStatement *  GetStatement() override;
 
   public:
                         OGRWalkSelectLayer( OGRWalkDataSource *,
                                            CPLODBCStatement * );
-                        ~OGRWalkSelectLayer();
+                        virtual ~OGRWalkSelectLayer();
 
-    virtual void        ResetReading();
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual void        ResetReading() override;
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 };
 
@@ -166,30 +166,28 @@ class OGRWalkDataSource : public OGRDataSource
     OGRWalkLayer        **papoLayers;
     int                 nLayers;
 
-    int                 bDSUpdate;
     CPLODBCSession      oSession;
 
 public:
                         OGRWalkDataSource();
-                        ~OGRWalkDataSource();
+                        virtual ~OGRWalkDataSource();
 
     int                 Open( const char * , int );
 
-    const char            *GetName() { return pszName; }
-    int                    GetLayerCount() { return nLayers; }
-    OGRLayer            *GetLayer( int );
+    const char            *GetName() override { return pszName; }
+    int                    GetLayerCount() override { return nLayers; }
+    OGRLayer            *GetLayer( int ) override;
 
-    int                    TestCapability( const char * ) { return FALSE; }
+    int                    TestCapability( const char * ) override { return FALSE; }
 
     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
                                     OGRGeometry *poSpatialFilter,
-                                    const char *pszDialect );
+                                    const char *pszDialect ) override;
 
-    virtual void        ReleaseResultSet( OGRLayer * poLayer );
+    virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
 
     // For Internal Use
     CPLODBCSession     *GetSession() { return &oSession; }
-
 };
 
 /************************************************************************/
@@ -201,12 +199,12 @@ class OGRWalkDriver : public OGRODBCMDBDriver
 public:
                 ~OGRWalkDriver();
 
-    const char    *GetName();
-    OGRDataSource *Open( const char *, int );
+    const char    *GetName() override;
+    OGRDataSource *Open( const char *, int ) override;
 
-    OGRDataSource *CreateDataSource( const char *, char ** );
+    OGRDataSource *CreateDataSource( const char *, char ** ) override;
 
-    int            TestCapability( const char * );
+    int            TestCapability( const char * ) override;
 };
 
 void RegisterOGRWalk();
diff --git a/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp b/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp
index fdf5eaf..30de8ba 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalkdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwalkdatasource.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRWalkDatasource class.
@@ -30,6 +29,8 @@
 #include "ogrwalk.h"
 #include <vector>
 
+CPL_CVSID("$Id: ogrwalkdatasource.cpp 35577 2016-09-30 23:30:37Z goatbar $");
+
 /************************************************************************/
 /*                         OGRWalkDataSource()                          */
 /************************************************************************/
@@ -37,9 +38,8 @@
 OGRWalkDataSource::OGRWalkDataSource() :
     pszName(NULL),
     papoLayers(NULL),
-    nLayers(0),
-    bDSUpdate(FALSE)
-{ }
+    nLayers(0)
+{}
 
 /************************************************************************/
 /*                        ~OGRWalkDataSource()                          */
@@ -63,17 +63,19 @@ OGRWalkDataSource::~OGRWalkDataSource()
 /*                              Open()                                  */
 /************************************************************************/
 
-int OGRWalkDataSource::Open( const char * pszNewName, int bUpdate )
+int OGRWalkDataSource::Open( const char * pszNewName, int /* bUpdate */ )
 {
 /* -------------------------------------------------------------------- */
 /*      If this is the name of an MDB file, then construct the          */
 /*      appropriate connection string.  Otherwise clip of WALK: to      */
 /*      get the DSN.                                                    */
 /* -------------------------------------------------------------------- */
-    char *pszDSN;
+    char *pszDSN = NULL;
 
     if( STARTS_WITH_CI(pszNewName, "WALK:") )
+    {
         pszDSN = CPLStrdup( pszNewName + 5 );
+    }
     else
     {
         const char *pszDSNStringTemplate = "DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s";
@@ -102,8 +104,6 @@ int OGRWalkDataSource::Open( const char * pszNewName, int bUpdate )
 
     pszName = CPLStrdup( pszNewName );
 
-    bDSUpdate = bUpdate;
-
 /* -------------------------------------------------------------------- */
 /*      Collect list of layers and their attributes.                    */
 /* -------------------------------------------------------------------- */
@@ -135,12 +135,10 @@ int OGRWalkDataSource::Open( const char * pszNewName, int bUpdate )
 /* -------------------------------------------------------------------- */
 /*      Create a layer for each spatial table.                          */
 /* -------------------------------------------------------------------- */
-    unsigned int iTable;
-
     papoLayers = (OGRWalkLayer **) CPLCalloc(apapszGeomColumns.size(),
                                              sizeof( void * ));
 
-    for( iTable = 0; iTable < apapszGeomColumns.size(); iTable++ )
+    for( unsigned int iTable = 0; iTable < apapszGeomColumns.size(); iTable++ )
     {
         char **papszRecord = apapszGeomColumns[iTable];
 
diff --git a/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp b/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp
index f72098d..ca42868 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalkdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwalkdriver.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRWalkDriver class.
@@ -30,6 +29,8 @@
 
 #include "ogrwalk.h"
 
+CPL_CVSID("$Id: ogrwalkdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+
 /************************************************************************/
 /*                          ~OGRWalkDriver()                            */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp b/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp
index d7c7a3f..73cad7b 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalklayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwalklayer.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRWalkLayer class.
@@ -29,27 +28,25 @@
 
 #include "ogrwalk.h"
 
+#include <algorithm>
+
+CPL_CVSID("$Id: ogrwalklayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
 /************************************************************************/
 /*                            OGRWalkLayer()                            */
 /************************************************************************/
 
-OGRWalkLayer::OGRWalkLayer( )
-
-{
-    poDS = NULL;
-
-    bGeomColumnWKB = FALSE;
-    pszGeomColumn = NULL;
-    pszFIDColumn = NULL;
-    panFieldOrdinals = NULL;
-
-    poStmt = NULL;
-
-    poFeatureDefn = NULL;
-    iNextShapeId = 0;
-
-    poSRS = NULL;
-}
+OGRWalkLayer::OGRWalkLayer() :
+    poFeatureDefn(NULL),
+    poStmt(NULL),
+    poSRS(NULL),
+    iNextShapeId(0),
+    poDS(NULL),
+    bGeomColumnWKB(false),
+    pszGeomColumn(NULL),
+    pszFIDColumn(NULL),
+    panFieldOrdinals(NULL)
+{}
 
 /************************************************************************/
 /*                           ~OGRWalkLayer()                            */
@@ -61,7 +58,7 @@ OGRWalkLayer::~OGRWalkLayer()
     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     {
         CPLDebug( "Walk", "%d features read on layer '%s'.",
-                  (int) m_nFeaturesRead,
+                  static_cast<int>(m_nFeaturesRead),
                   poFeatureDefn->GetName() );
     }
 
@@ -99,7 +96,8 @@ CPLErr OGRWalkLayer::BuildFeatureDefn( const char *pszLayerName,
     {
         OGRFieldDefn    oField( poStmtIn->GetColName(iCol), OFTString );
 
-        oField.SetWidth( MAX(0,poStmtIn->GetColSize( iCol )) );
+        oField.SetWidth(
+            std::max(static_cast<short>(0), poStmtIn->GetColSize( iCol )));
 
         if( pszGeomColumn != NULL
             && EQUAL(poStmtIn->GetColName(iCol),pszGeomColumn) )    //If Geometry Column, continue to next field
@@ -185,7 +183,6 @@ void OGRWalkLayer::ResetReading()
     iNextShapeId = 0;
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -195,9 +192,7 @@ OGRFeature *OGRWalkLayer::GetNextFeature()
 {
     while( true )
     {
-        OGRFeature      *poFeature;
-
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if( poFeature == NULL )
             return NULL;
 
@@ -250,7 +245,7 @@ OGRFeature *OGRWalkLayer::GetNextRawFeature()
         const char *pszValue = poStmt->GetColData( iSrcField );
 
         if( pszValue == NULL )
-            /* no value */;
+            poFeature->SetFieldNull( iField );
         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
             poFeature->SetField( iField,
                                  poStmt->GetColDataLength(iSrcField),
@@ -287,7 +282,7 @@ OGRFeature *OGRWalkLayer::GetNextRawFeature()
 
         if ( eErr != OGRERR_NONE )
         {
-            const char *pszMessage;
+            const char *pszMessage = NULL;
 
             switch ( eErr )
             {
diff --git a/ogr/ogrsf_frmts/walk/ogrwalkselectlayer.cpp b/ogr/ogrsf_frmts/walk/ogrwalkselectlayer.cpp
index a7bc6e2..64aa645 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalkselectlayer.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalkselectlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwalkselectlayer.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRWalkSelectLayer class, layer access to the results
@@ -31,13 +30,15 @@
 #include "cpl_conv.h"
 #include "ogrwalk.h"
 
+CPL_CVSID("$Id: ogrwalkselectlayer.cpp 35203 2016-08-25 17:56:54Z goatbar $");
+
 /************************************************************************/
 /*                          OGRWalkSelectLayer()                        */
 /************************************************************************/
 
 OGRWalkSelectLayer::OGRWalkSelectLayer( OGRWalkDataSource *poDSIn,
-                                        CPLODBCStatement * poStmtIn )
-
+                                        CPLODBCStatement * poStmtIn ) :
+    pszBaseStatement(CPLStrdup(poStmtIn->GetCommand()))
 {
     poDS = poDSIn;
 
@@ -45,8 +46,6 @@ OGRWalkSelectLayer::OGRWalkSelectLayer( OGRWalkDataSource *poDSIn,
     poFeatureDefn = NULL;
 
     poStmt = poStmtIn;
-    pszBaseStatement = CPLStrdup( poStmtIn->GetCommand() );
-
     BuildFeatureDefn( "SELECT", poStmt );
 }
 
diff --git a/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp b/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp
index 2d18c2e..10b5e48 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalktablelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwalktablelayer.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements OGRWalkTableLayer class, access to an existing table.
@@ -30,17 +29,17 @@
 #include "ogrwalk.h"
 #include "cpl_conv.h"
 
+CPL_CVSID("$Id: ogrwalktablelayer.cpp 35911 2016-10-24 15:03:26Z goatbar $");
+
 /************************************************************************/
 /*                          OGRWalkTableLayer()                         */
 /************************************************************************/
 
-OGRWalkTableLayer::OGRWalkTableLayer( OGRWalkDataSource *poDSIn )
-
+OGRWalkTableLayer::OGRWalkTableLayer( OGRWalkDataSource *poDSIn ) :
+    pszQuery(NULL)
 {
     poDS = poDSIn;
 
-    pszQuery = NULL;
-
     iNextShapeId = 0;
     poFeatureDefn = NULL;
 
@@ -171,7 +170,7 @@ CPLErr OGRWalkTableLayer::Initialize( const char *pszLayerName,
         {
             if( CPLODBCStatement::GetTypeMapping(
                     oGetCol.GetColType( iColumn )) == SQL_C_BINARY )
-                bGeomColumnWKB = TRUE;
+                bGeomColumnWKB = true;
         }
     }
 
@@ -287,22 +286,21 @@ OGRErr OGRWalkTableLayer::SetAttributeFilter( const char *pszQueryIn )
 
 {
     CPLFree(m_pszAttrQueryString);
-    m_pszAttrQueryString = (pszQueryIn) ? CPLStrdup(pszQueryIn) : NULL;
+    m_pszAttrQueryString = pszQueryIn ? CPLStrdup(pszQueryIn) : NULL;
 
-    if( (pszQueryIn == NULL && this->pszQuery == NULL)
-        || (pszQueryIn != NULL && this->pszQuery != NULL
-            && EQUAL(pszQueryIn,this->pszQuery)) )
+    if( (pszQueryIn == NULL && pszQuery == NULL)
+        || (pszQueryIn != NULL && pszQuery != NULL
+            && EQUAL(pszQueryIn, pszQuery)) )
         return OGRERR_NONE;
 
-    CPLFree( this->pszQuery );
-    this->pszQuery = (pszQueryIn != NULL ) ? CPLStrdup( pszQueryIn ) : NULL;
+    CPLFree( pszQuery );
+    pszQuery = pszQueryIn != NULL ? CPLStrdup( pszQueryIn ) : NULL;
 
     ClearStatement();
 
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           TestCapability()                           */
 /************************************************************************/
@@ -313,8 +311,7 @@ int OGRWalkTableLayer::TestCapability( const char * pszCap )
     if( EQUAL(pszCap,OLCRandomRead) )
         return TRUE;
 
-    else
-        return OGRWalkLayer::TestCapability( pszCap );
+    return OGRWalkLayer::TestCapability( pszCap );
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/walk/ogrwalktool.cpp b/ogr/ogrsf_frmts/walk/ogrwalktool.cpp
index 8682ed2..7fa76cf 100644
--- a/ogr/ogrsf_frmts/walk/ogrwalktool.cpp
+++ b/ogr/ogrsf_frmts/walk/ogrwalktool.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwalktool.cpp
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Implements Walk Binary Data to Walk Geometry and OGC WKB
@@ -29,17 +28,19 @@
 
 #include "ogrwalk.h"
 
+CPL_CVSID("$Id: ogrwalktool.cpp 36474 2016-11-24 00:40:09Z rouault $");
+
 /************************************************************************/
 /*                   OGRWalkArcCenterFromEdgePoints()                   */
 /*                                                                      */
 /*      Compute the center of an arc/circle from three edge points.     */
 /************************************************************************/
 
-static int
+static bool
 OGRWalkArcCenterFromEdgePoints( double x_c0, double y_c0,
-                               double x_c1, double y_c1,
-                               double x_c2, double y_c2,
-                               double *x_center, double *y_center )
+                                double x_c1, double y_c1,
+                                double x_c2, double y_c2,
+                                double *x_center, double *y_center )
 
 {
 /* -------------------------------------------------------------------- */
@@ -47,65 +48,55 @@ OGRWalkArcCenterFromEdgePoints( double x_c0, double y_c0,
 /*      second points.  Also compute the center point of the two        */
 /*      points ... the point our crossing line will go through.          */
 /* -------------------------------------------------------------------- */
-    double m1, x1, y1;
-
-    if( (y_c1 - y_c0) != 0.0 )
-        m1 = (x_c0 - x_c1) / (y_c1 - y_c0);
-    else
-        m1 = 1e+10;
+    const double m1 = (y_c1 - y_c0) != 0.0
+        ? ((x_c0 - x_c1) / (y_c1 - y_c0))
+        : 1e+10;
 
-    x1 = (x_c0 + x_c1) * 0.5;
-    y1 = (y_c0 + y_c1) * 0.5;
+    const double x1 = (x_c0 + x_c1) * 0.5;
+    const double y1 = (y_c0 + y_c1) * 0.5;
 
 /* -------------------------------------------------------------------- */
 /*      Compute the same for the second point compared to the third     */
 /*      point.                                                          */
 /* -------------------------------------------------------------------- */
-    double m2, x2, y2;
-
-    if( (y_c2 - y_c1) != 0.0 )
-        m2 = (x_c1 - x_c2) / (y_c2 - y_c1);
-    else
-        m2 = 1e+10;
+    const double m2 = (y_c2 - y_c1) != 0.0
+        ? ((x_c1 - x_c2) / (y_c2 - y_c1))
+        : 1e+10;
 
-    x2 = (x_c1 + x_c2) * 0.5;
-    y2 = (y_c1 + y_c2) * 0.5;
+    const double x2 = (x_c1 + x_c2) * 0.5;
+    const double y2 = (y_c1 + y_c2) * 0.5;
 
 /* -------------------------------------------------------------------- */
 /*      Turn these into the Ax+By+C = 0 form of the lines.              */
 /* -------------------------------------------------------------------- */
-    double      a1, a2, b1, b2, c1, c2;
+    const double a1 = m1;
+    const double a2 = m2;
 
-    a1 = m1;
-    a2 = m2;
+    const double b1 = -1.0;
+    const double b2 = -1.0;
 
-    b1 = -1.0;
-    b2 = -1.0;
-
-    c1 = (y1 - m1*x1);
-    c2 = (y2 - m2*x2);
+    const double c1 = (y1 - m1*x1);
+    const double c2 = (y2 - m2*x2);
 
 /* -------------------------------------------------------------------- */
 /*      Compute the intersection of the two lines through the center    */
 /*      of the circle, using Kramers rule.                              */
 /* -------------------------------------------------------------------- */
-    double      det_inv;
-
     if( a1*b2 - a2*b1 == 0.0 )
-        return FALSE;
+        return false;
 
-    det_inv = 1 / (a1*b2 - a2*b1);
+    const double det_inv = 1 / (a1*b2 - a2*b1);
 
     *x_center = (b1*c2 - b2*c1) * det_inv;
     *y_center = (a2*c1 - a1*c2) * det_inv;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                       OGRWalkArcToLineString()                       */
 /************************************************************************/
-static int
+static bool
 OGRWalkArcToLineString( double dfStartX, double dfStartY,
                         double dfAlongX, double dfAlongY,
                         double dfEndX, double dfEndY,
@@ -113,25 +104,20 @@ OGRWalkArcToLineString( double dfStartX, double dfStartY,
                         double dfCenterZ, double dfRadius,
                         int nNumPoints, OGRLineString *poLS )
 {
-    double dfStartAngle, dfEndAngle, dfAlongAngle;
-    double dfDeltaX, dfDeltaY;
-
-    dfDeltaX = dfStartX - dfCenterX;
-    dfDeltaY = dfStartY - dfCenterY;
-    dfStartAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
+    double dfDeltaX = dfStartX - dfCenterX;
+    double dfDeltaY = dfStartY - dfCenterY;
+    const double dfStartAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
 
     dfDeltaX = dfAlongX - dfCenterX;
     dfDeltaY = dfAlongY - dfCenterY;
-    dfAlongAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
-
-    dfDeltaX = dfEndX - dfCenterX;
-    dfDeltaY = dfEndY - dfCenterY;
-    dfEndAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
-
+    double dfAlongAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
     // Try positive (clockwise?) winding.
     while( dfAlongAngle < dfStartAngle )
         dfAlongAngle += 360.0;
 
+    dfDeltaX = dfEndX - dfCenterX;
+    dfDeltaY = dfEndY - dfCenterY;
+    double dfEndAngle = -1 * atan2(dfDeltaY,dfDeltaX) * 180.0 / M_PI;
     while( dfEndAngle < dfAlongAngle )
         dfEndAngle += 360.0;
 
@@ -156,7 +142,9 @@ OGRWalkArcToLineString( double dfStartX, double dfStartY,
             dfEndAngle = dfStartAngle + 360.0;
     }
     else
-        return FALSE;
+    {
+        return false;
+    }
 
     OGRLineString* poArcpoLS =
         (OGRLineString*)OGRGeometryFactory::approximateArcAngles(
@@ -165,12 +153,12 @@ OGRWalkArcToLineString( double dfStartX, double dfStartY,
             dfStartAngle, dfEndAngle, 0.0 );
 
     if( poArcpoLS == NULL )
-        return FALSE;
+        return false;
 
     poLS->addSubLineString(poArcpoLS);
     delete poArcpoLS;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -351,8 +339,6 @@ static OGRErr Binary2WkbMGeom(unsigned char *& p, WKBGeometry* geom, int nBytes)
 /************************************************************************/
 OGRErr Binary2WkbGeom(unsigned char *p, WKBGeometry* geom, int nBytes)
 {
-    GUInt32 i;
-
     if( nBytes < 28 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -381,7 +367,7 @@ OGRErr Binary2WkbGeom(unsigned char *p, WKBGeometry* geom, int nBytes)
         geom->mgeometries.WKBGeometries =
             new WKBSimpleGeometry[geom->mgeometries.num_wkbSGeometries];
 
-        for(i = 0; i < geom->mgeometries.num_wkbSGeometries; i++)
+        for( GUInt32 i = 0; i < geom->mgeometries.num_wkbSGeometries; i++ )
             Binary2WkbMGeom(p, (WKBGeometry*)(&geom->mgeometries.WKBGeometries[i]), nBytes-8);
         break;
     default:
@@ -394,37 +380,40 @@ OGRErr Binary2WkbGeom(unsigned char *p, WKBGeometry* geom, int nBytes)
 /************************************************************************/
 /*                       TranslateWalkPoint()                           */
 /************************************************************************/
-static OGRBoolean TranslateWalkPoint(OGRPoint *poPoint, WKBPoint* pWalkWkbPoint)
+static bool TranslateWalkPoint(OGRPoint *poPoint, WKBPoint* pWalkWkbPoint)
 {
     if ( poPoint == NULL || pWalkWkbPoint == NULL )
-        return FALSE;
+        return false;
 
     poPoint->setX(pWalkWkbPoint->x);
     poPoint->setY(pWalkWkbPoint->y);
     poPoint->setZ(pWalkWkbPoint->z);
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                    TranslateCurveSegment()                           */
 /************************************************************************/
-static OGRBoolean TranslateCurveSegment(OGRLineString *poLS, CurveSegment* pSegment)
+static bool TranslateCurveSegment(OGRLineString *poLS, CurveSegment* pSegment)
 {
     if ( poLS == NULL || pSegment == NULL )
-        return FALSE;
+        return false;
 
     switch(pSegment->lineType)
     {
-    case wkLineType3PArc:
-    case wkLineType3PCircle:
+    case OGRWALK::wkLineType3PArc:
+    case OGRWALK::wkLineType3PCircle:
         {
-            double      dfCenterX, dfCenterY, dfCenterZ, dfRadius;
+            double dfCenterX;
+            double dfCenterY;
+            double dfCenterZ;
+            double dfRadius;
 
             if ( !OGRWalkArcCenterFromEdgePoints( pSegment->points[0].x, pSegment->points[0].y,
                                            pSegment->points[1].x, pSegment->points[1].y,
                                            pSegment->points[2].x, pSegment->points[2].y,
                                            &dfCenterX, &dfCenterY ) )
-                return FALSE;
+                return false;
 
             //Use Z value of the first point
             dfCenterZ = pSegment->points[0].z;
@@ -436,10 +425,10 @@ static OGRBoolean TranslateCurveSegment(OGRLineString *poLS, CurveSegment* pSegm
                         pSegment->points[2].x, pSegment->points[2].y,
                         dfCenterX, dfCenterY, dfCenterZ, dfRadius,
                         pSegment->numPoints, poLS ) )
-                return FALSE;
+                return false;
         }
         break;
-    case wkLineTypeStraight:
+    case OGRWALK::wkLineTypeStraight:
     default:
         {
             for (GUInt32 i = 0; i < pSegment->numPoints; ++i)
@@ -451,49 +440,52 @@ static OGRBoolean TranslateCurveSegment(OGRLineString *poLS, CurveSegment* pSegm
         break;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                    TranslateWalkLineString()                         */
 /************************************************************************/
-static OGRBoolean TranslateWalkLineString(OGRLineString *poLS, LineString* pLineString)
+static bool TranslateWalkLineString( OGRLineString *poLS,
+                                     LineString* pLineString )
 {
-    if ( poLS == NULL || pLineString == NULL )
-        return FALSE;
+    if( poLS == NULL || pLineString == NULL )
+        return false;
 
-    for (GUInt32 i = 0; i < pLineString->numSegments; ++i)
+    for( GUInt32 i = 0; i < pLineString->numSegments; ++i )
     {
         if ( !TranslateCurveSegment(poLS, &pLineString->segments[i]) )
-            return FALSE;
+            return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                    TranslateWalkLinearring()                         */
 /************************************************************************/
-static OGRBoolean TranslateWalkLinearring(OGRLinearRing *poRing, LineString* pLineString)
+static bool TranslateWalkLinearring( OGRLinearRing *poRing,
+                                     LineString* pLineString )
 {
-    if ( poRing == NULL || pLineString == NULL )
-        return FALSE;
+    if( poRing == NULL || pLineString == NULL )
+        return false;
 
-    for(GUInt32 i = 0; i < pLineString->numSegments; i++)
+    for( GUInt32 i = 0; i < pLineString->numSegments; i++ )
         TranslateCurveSegment(poRing, &pLineString->segments[i]);
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                    TranslateWalkPolygon()                            */
 /************************************************************************/
-static OGRBoolean TranslateWalkPolygon(OGRPolygon *poPolygon, WKBPolygon* pWalkWkbPolgon)
+static bool TranslateWalkPolygon( OGRPolygon *poPolygon,
+                                  WKBPolygon* pWalkWkbPolgon )
 {
     if ( poPolygon == NULL || pWalkWkbPolgon == NULL )
-        return FALSE;
+        return false;
 
-    for (GUInt32 i = 0; i < pWalkWkbPolgon->numRings; ++i)
+    for( GUInt32 i = 0; i < pWalkWkbPolgon->numRings; ++i )
     {
         OGRLinearRing* poRing = new OGRLinearRing();
         LineString* lineString = &pWalkWkbPolgon->rings[i];
@@ -501,7 +493,7 @@ static OGRBoolean TranslateWalkPolygon(OGRPolygon *poPolygon, WKBPolygon* pWalkW
         poPolygon->addRingDirectly(poRing);
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -522,7 +514,7 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
     {
     case wkbPoint:
         {
-            if (!TranslateWalkPoint((OGRPoint *)poGeom, &geom->point))
+            if( !TranslateWalkPoint((OGRPoint *)poGeom, &geom->point) )
             {
                 delete poGeom;
                 return OGRERR_CORRUPT_DATA;
@@ -552,7 +544,7 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
             for (GUInt32 i = 0; i < geom->mpoint.num_wkbPoints; ++i)
             {
                 OGRPoint* poPoint = new OGRPoint();
-                if (!TranslateWalkPoint(poPoint, &geom->mpoint.WKBPoints[i]))
+                if( !TranslateWalkPoint(poPoint, &geom->mpoint.WKBPoints[i]) )
                 {
                     delete poPoint;
                     delete poGeom;
@@ -602,7 +594,7 @@ OGRErr TranslateWalkGeom(OGRGeometry **ppoGeom, WKBGeometry* geom)
                     case wkbPoint:
                         {
                             OGRPoint* poPoint = new OGRPoint();
-                            if (!TranslateWalkPoint(poPoint, &sg->point))
+                            if( !TranslateWalkPoint(poPoint, &sg->point) )
                             {
                                 delete poPoint;
                                 delete poGeom;
diff --git a/ogr/ogrsf_frmts/wasp/ogrwasp.h b/ogr/ogrsf_frmts/wasp/ogrwasp.h
index 9a773af..f97f44b 100644
--- a/ogr/ogrsf_frmts/wasp/ogrwasp.h
+++ b/ogr/ogrsf_frmts/wasp/ogrwasp.h
@@ -149,25 +149,25 @@ class OGRWAsPLayer : public OGRLayer
                                       VSILFILE * hFile,
                                       OGRSpatialReference * poSpatialRef );
 
-                        ~OGRWAsPLayer();
+                        virtual ~OGRWAsPLayer();
 
-    virtual OGRFeatureDefn *    GetLayerDefn() { return poLayerDefn; }
+    virtual OGRFeatureDefn *    GetLayerDefn() override { return poLayerDefn; }
 
-    virtual void        ResetReading();
-    virtual int         TestCapability( const char * );
+    virtual void        ResetReading() override;
+    virtual int         TestCapability( const char * ) override;
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE );
+                                     int bApproxOK = TRUE ) override;
     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
-                                         int bApproxOK = TRUE );
+                                         int bApproxOK = TRUE ) override;
 
-    virtual OGRErr      ICreateFeature( OGRFeature * poFeature );
+    virtual OGRErr      ICreateFeature( OGRFeature * poFeature ) override;
 
-    virtual OGRFeature *GetNextFeature();
+    virtual OGRFeature *GetNextFeature() override;
     OGRFeature *GetNextRawFeature();
-    virtual OGRwkbGeometryType  GetGeomType() { return wkbLineString25D; }
-    virtual OGRSpatialReference *GetSpatialRef() { return poSpatialReference; }
-    virtual const char *GetName() { return sName.c_str(); }
+    virtual OGRwkbGeometryType  GetGeomType() override { return wkbLineString25D; }
+    virtual OGRSpatialReference *GetSpatialRef() override { return poSpatialReference; }
+    virtual const char *GetName() override { return sName.c_str(); }
 };
 
 /************************************************************************/
@@ -188,19 +188,19 @@ class OGRWAsPDataSource : public OGRDataSource
                         /** @note takes ownership of hFile (i.e. responsibility for closing) */
                         OGRWAsPDataSource( const char * pszName,
                                            VSILFILE * hFile );
-                        ~OGRWAsPDataSource();
+                        virtual ~OGRWAsPDataSource();
 
-    virtual const char *GetName() { return sFilename.c_str(); }
-    virtual int         GetLayerCount() { return oLayer.get() ? 1 : 0; }
-    virtual OGRLayer   *GetLayer( int );
-    virtual OGRLayer   *GetLayerByName( const char * );
+    virtual const char *GetName() override { return sFilename.c_str(); }
+    virtual int         GetLayerCount() override { return oLayer.get() ? 1 : 0; }
+    virtual OGRLayer   *GetLayer( int ) override;
+    virtual OGRLayer   *GetLayerByName( const char * ) override;
 
     virtual OGRLayer   *ICreateLayer( const char *pszName,
                                      OGRSpatialReference *poSpatialRef = NULL,
                                      OGRwkbGeometryType eGType = wkbUnknown,
-                                     char ** papszOptions = NULL );
+                                     char ** papszOptions = NULL ) override;
 
-    virtual int        TestCapability( const char * );
+    virtual int        TestCapability( const char * ) override;
     OGRErr             Load( bool bSilent = false );
 };
 
@@ -214,16 +214,15 @@ class OGRWAsPDriver : public OGRSFDriver
   public:
                                 ~OGRWAsPDriver() {}
 
-    virtual const char*         GetName() { return "WAsP"; }
-    virtual OGRDataSource*      Open( const char *, int );
+    virtual const char*         GetName() override { return "WAsP"; }
+    virtual OGRDataSource*      Open( const char *, int ) override;
 
     virtual OGRDataSource       *CreateDataSource( const char *pszName,
-                                                   char ** = NULL );
+                                                   char ** = NULL ) override;
 
-    virtual OGRErr 	        DeleteDataSource (const char *pszName);
+    virtual OGRErr              DeleteDataSource (const char *pszName) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 };
 
-
 #endif /* ndef OGR_WASP_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp b/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp
index 7e5b563..d0f2a75 100644
--- a/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp
+++ b/ogr/ogrsf_frmts/wasp/ogrwaspdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwaspdatasource.cpp 25307 2012-12-15 09:04:40Z rouault $
  *
  * Project:  WAsP Translator
  * Purpose:  Implements OGRWAsPDataSource class
@@ -34,17 +33,17 @@
 #include <cassert>
 #include <sstream>
 
+CPL_CVSID("$Id: ogrwaspdatasource.cpp 36481 2016-11-24 03:55:49Z goatbar $");
+
 /************************************************************************/
 /*                          OGRWAsPDataSource()                          */
 /************************************************************************/
 
 OGRWAsPDataSource::OGRWAsPDataSource( const char * pszName,
-                                      VSILFILE * hFileHandle )
-    : sFilename( pszName )
-    , hFile( hFileHandle )
-
-{
-}
+                                      VSILFILE * hFileHandle ) :
+    sFilename(pszName),
+    hFile(hFileHandle)
+{}
 
 /************************************************************************/
 /*                         ~OGRWAsPDataSource()                          */
@@ -167,14 +166,12 @@ OGRErr OGRWAsPDataSource::Load(bool bSilent)
 /*                              GetLayer()                              */
 /************************************************************************/
 
-
 OGRLayer *OGRWAsPDataSource::GetLayer( int iLayer )
 
 {
     return ( iLayer == 0 ) ? oLayer.get() : NULL;
 }
 
-
 /************************************************************************/
 /*                             ICreateLayer()                           */
 /************************************************************************/
@@ -316,7 +313,7 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
 
     char * ppszWktSpatialRef = NULL ;
     if ( poSpatialRef
-            && poSpatialRef->exportToProj4( &ppszWktSpatialRef ) == OGRERR_NONE )
+         && poSpatialRef->exportToProj4( &ppszWktSpatialRef ) == OGRERR_NONE )
     {
         VSIFPrintfL( hFile, "%s\n", ppszWktSpatialRef );
     }
@@ -324,7 +321,7 @@ OGRLayer *OGRWAsPDataSource::ICreateLayer(const char *pszName,
     {
         VSIFPrintfL( hFile, "no spatial ref sys\n" );
     }
-    OGRFree( ppszWktSpatialRef );
+    CPLFree( ppszWktSpatialRef );
 
     VSIFPrintfL( hFile, "  0.0 0.0 0.0 0.0\n" );
     VSIFPrintfL( hFile, "  1.0 0.0 1.0 0.0\n" );
diff --git a/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp b/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp
index 668e886..1cf79c7 100644
--- a/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp
+++ b/ogr/ogrsf_frmts/wasp/ogrwaspdriver.cpp
@@ -30,6 +30,8 @@
 #include "cpl_conv.h"
 #include <cassert>
 
+CPL_CVSID("$Id: ogrwaspdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
+
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp b/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp
index fed9974..fbb794e 100644
--- a/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp
+++ b/ogr/ogrsf_frmts/wasp/ogrwasplayer.cpp
@@ -35,32 +35,33 @@
 #include <map>
 #include <sstream>
 
+CPL_CVSID("$Id: ogrwasplayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
+
 /************************************************************************/
 /*                            OGRWAsPLayer()                             */
 /************************************************************************/
 
 OGRWAsPLayer::OGRWAsPLayer( const char * pszName,
                             VSILFILE * hFileHandle,
-                            OGRSpatialReference * poSpatialRef )
-    : bMerge( false )
-    , iFeatureCount(0)
-    , sName( pszName )
-    , hFile( hFileHandle )
-    , iFirstFieldIdx( 0 )
-    , iSecondFieldIdx( 1 )
-    , iGeomFieldIdx( 0 )
-    , poLayerDefn( new OGRFeatureDefn( pszName ) )
-    , poSpatialReference( poSpatialRef )
-    , iOffsetFeatureBegin( VSIFTellL( hFile ) )
-    , eMode( READ_ONLY )
-
+                            OGRSpatialReference * poSpatialRef ) :
+    bMerge(false),
+    iFeatureCount(0),
+    sName(pszName),
+    hFile(hFileHandle),
+    iFirstFieldIdx(0),
+    iSecondFieldIdx(1),
+    iGeomFieldIdx(0),
+    poLayerDefn(new OGRFeatureDefn(pszName)),
+    poSpatialReference(poSpatialRef),
+    iOffsetFeatureBegin(VSIFTellL(hFile)),
+    eMode(READ_ONLY)
 {
     SetDescription( poLayerDefn->GetName() );
     poLayerDefn->Reference();
     poLayerDefn->SetGeomType( wkbLineString25D );
     poLayerDefn->GetGeomFieldDefn(0)->SetType( wkbLineString25D );
     poLayerDefn->GetGeomFieldDefn(0)->SetSpatialRef( poSpatialReference );
-    if (poSpatialReference) poSpatialReference->Reference();
+    if( poSpatialReference ) poSpatialReference->Reference();
 }
 
 OGRWAsPLayer::OGRWAsPLayer( const char * pszName,
@@ -72,24 +73,24 @@ OGRWAsPLayer::OGRWAsPLayer( const char * pszName,
                             bool bMergeParam,
                             double * pdfToleranceParam,
                             double * pdfAdjacentPointToleranceParam,
-                            double * pdfPointToCircleRadiusParam )
-    : bMerge( bMergeParam )
-    , iFeatureCount(0)
-    , sName( pszName )
-    , hFile( hFileHandle )
-    , sFirstField( sFirstFieldParam )
-    , sSecondField( sSecondFieldParam )
-    , sGeomField( sGeomFieldParam )
-    , iFirstFieldIdx( -1 )
-    , iSecondFieldIdx( -1 )
-    , iGeomFieldIdx( sGeomFieldParam.empty() ? 0 : -1 )
-    , poLayerDefn( new OGRFeatureDefn( pszName ) )
-    , poSpatialReference( poSpatialRef )
-    , iOffsetFeatureBegin( VSIFTellL( hFile ) ) /* avoids coverity warning */
-    , eMode( WRITE_ONLY )
-    , pdfTolerance( pdfToleranceParam )
-    , pdfAdjacentPointTolerance( pdfAdjacentPointToleranceParam )
-    , pdfPointToCircleRadius( pdfPointToCircleRadiusParam )
+                            double * pdfPointToCircleRadiusParam ) :
+    bMerge(bMergeParam),
+    iFeatureCount(0),
+    sName(pszName),
+    hFile(hFileHandle),
+    sFirstField(sFirstFieldParam),
+    sSecondField(sSecondFieldParam),
+    sGeomField(sGeomFieldParam),
+    iFirstFieldIdx(-1),
+    iSecondFieldIdx(-1),
+    iGeomFieldIdx(sGeomFieldParam.empty() ? 0 : -1),
+    poLayerDefn(new OGRFeatureDefn(pszName)),
+    poSpatialReference(poSpatialRef),
+    iOffsetFeatureBegin(VSIFTellL(hFile)),  // Avoids coverity warning.
+    eMode(WRITE_ONLY),
+    pdfTolerance(pdfToleranceParam),
+    pdfAdjacentPointTolerance(pdfAdjacentPointToleranceParam),
+    pdfPointToCircleRadius(pdfPointToCircleRadiusParam)
 {
     poLayerDefn->Reference();
     if (poSpatialReference) poSpatialReference->Reference();
@@ -128,7 +129,7 @@ OGRWAsPLayer::~OGRWAsPLayer()
 
         std::vector<int> endNeighbors( oBoundaries.size(), -1 );
         std::vector<int> startNeighbors( oBoundaries.size(), -1 );
-        for ( PointMap::const_iterator it = oMap.begin(); it != oMap.end(); it++ )
+        for ( PointMap::const_iterator it = oMap.begin(); it != oMap.end(); ++it )
         {
             if ( it->second.size() != 2 ) continue;
             int i = it->second[0];
@@ -286,7 +287,6 @@ OGRLineString * OGRWAsPLayer::Simplify( const OGRLineString & line ) const
         poLine->StartPoint( &pt );
         newLine->addPoint( &pt );
         const int iNumPoints= poLine->getNumPoints();
-        unsigned rem = 0;
         for (int v=1; v<iNumPoints; v++)
         {
             if ( fabs(poLine->getX(v) - pt.getX()) > dist ||
@@ -295,10 +295,6 @@ OGRLineString * OGRWAsPLayer::Simplify( const OGRLineString & line ) const
                 poLine->getPoint( v, &pt );
                 newLine->addPoint( &pt );
             }
-            else
-            {
-                ++rem;
-            }
         }
 
         /* force closed loop if initially closed */
@@ -362,7 +358,6 @@ OGRLineString * OGRWAsPLayer::Simplify( const OGRLineString & line ) const
                         cy + radius*sin((v%nbPt)*(2*M_PI/nbPt)) );
             }
         }
-
     }
 
     return poLine.release();
@@ -422,12 +417,10 @@ OGRErr OGRWAsPLayer::WriteElevation( OGRGeometry * poGeom, const double & dfZ )
     return OGRERR_FAILURE; /* avoid visual warning */
 }
 
-
 /************************************************************************/
 /*                            WriteRoughness()                          */
 /************************************************************************/
 
-
 OGRErr OGRWAsPLayer::WriteRoughness( OGRPolygon * poGeom, const double & dfZ )
 
 {
@@ -496,7 +489,7 @@ OGRErr OGRWAsPLayer::WriteRoughness( OGRPolygon * poGeom, const double & dfZ )
                             OGREnvelope oErrorRegion = oZones[i].oEnvelope;
                             oErrorRegion.Intersect( oEnvelope );
                             CPLError(CE_Failure, CPLE_NotSupported,
-                                    "Overlaping polygons in rectangle (%.16g %.16g, %.16g %.16g))",
+                                    "Overlapping polygons in rectangle (%.16g %.16g, %.16g %.16g))",
                                     oErrorRegion.MinX,
                                     oErrorRegion.MinY,
                                     oErrorRegion.MaxX,
@@ -516,7 +509,7 @@ OGRErr OGRWAsPLayer::WriteRoughness( OGRPolygon * poGeom, const double & dfZ )
                             OGREnvelope oErrorRegion = oZones[i].oEnvelope;
                             oErrorRegion.Intersect( oEnvelope );
                             CPLError(CE_Failure, CPLE_NotSupported,
-                                    "Overlaping polygons in rectangle (%.16g %.16g, %.16g %.16g))",
+                                    "Overlapping polygons in rectangle (%.16g %.16g, %.16g %.16g))",
                                     oErrorRegion.MinX,
                                     oErrorRegion.MinY,
                                     oErrorRegion.MaxX,
@@ -635,17 +628,16 @@ OGRErr OGRWAsPLayer::ICreateFeature( OGRFeature * poFeature )
     if ( !geom ) return OGRERR_NONE; /* null geom, nothing to do */
 
     const OGRwkbGeometryType geomType = geom->getGeometryType();
-    const double bPolygon = (geomType == wkbPolygon)
+    const bool bPolygon = (geomType == wkbPolygon)
                          || (geomType == wkbPolygon25D)
                          || (geomType == wkbMultiPolygon)
                          || (geomType == wkbMultiPolygon25D);
     const bool bRoughness = (-1 != iSecondFieldIdx) || bPolygon ;
 
-
-    double z1;
+    double z1 = 0.0;
     if ( -1 != iFirstFieldIdx )
     {
-        if (!poFeature->IsFieldSet(iFirstFieldIdx))
+        if (!poFeature->IsFieldSetAndNotNull(iFirstFieldIdx))
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Field %d %s is NULL", iFirstFieldIdx, sFirstField.c_str() );
             return OGRERR_FAILURE;
@@ -665,10 +657,10 @@ OGRErr OGRWAsPLayer::ICreateFeature( OGRFeature * poFeature )
         z1 = AvgZ( geom );
     }
 
-    double z2;
+    double z2 = 0.0;
     if ( -1 != iSecondFieldIdx )
     {
-        if (!poFeature->IsFieldSet(iSecondFieldIdx))
+        if (!poFeature->IsFieldSetAndNotNull(iSecondFieldIdx))
         {
             CPLError(CE_Failure, CPLE_NotSupported, "Field %d %s is NULL", iSecondFieldIdx, sSecondField.c_str() );
             return OGRERR_FAILURE;
@@ -681,7 +673,9 @@ OGRErr OGRWAsPLayer::ICreateFeature( OGRFeature * poFeature )
         return OGRERR_FAILURE;
     }
 
-    return bRoughness ? WriteRoughness( geom, z1, z2 ) : WriteElevation( geom, z1 );
+    return bRoughness
+        ? WriteRoughness( geom, z1, z2 )
+        : WriteElevation( geom, z1 );
 }
 
 /************************************************************************/
@@ -720,7 +714,6 @@ OGRErr OGRWAsPLayer::CreateGeomField( OGRGeomFieldDefn *poGeomFieldIn,
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                           GetNextFeature()                           */
 /************************************************************************/
@@ -733,13 +726,11 @@ OGRFeature *OGRWAsPLayer::GetNextFeature()
         return NULL;
     }
 
-    OGRFeature  *poFeature;
-
     GetLayerDefn();
 
     while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -838,7 +829,6 @@ void OGRWAsPLayer::ResetReading()
     VSIFSeekL( hFile, iOffsetFeatureBegin, SEEK_SET );
 }
 
-
 /************************************************************************/
 /*                           AvgZ()                                     */
 /************************************************************************/
@@ -891,8 +881,6 @@ double OGRWAsPLayer::AvgZ( OGRGeometry * poGeom )
     return 0; /* avoid warning */
 }
 
-
-
 /************************************************************************/
 /*                           DouglasPeucker()                           */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/wfs/drv_wfs.html b/ogr/ogrsf_frmts/wfs/drv_wfs.html
index 02f7fe3..5131cc8 100644
--- a/ogr/ogrsf_frmts/wfs/drv_wfs.html
+++ b/ogr/ogrsf_frmts/wfs/drv_wfs.html
@@ -20,7 +20,7 @@ The driver supports read-only services, as well as Transactionnal ones (WFS-T).<
 
 The minimal syntax to open a WFS datasource is : <i>WFS:http://path/to/WFS/service</i> or <i>http://path/to/WFS/service?SERVICE=WFS</i><p>
 
-Additionnal optional parameters can be specified such as <i>TYPENAME</i>, <i>VERSION</i>, <i>MAXFEATURES</i> as specified in WFS specification.<p>
+Additional optional parameters can be specified such as <i>TYPENAME</i>, <i>VERSION</i>, <i>MAXFEATURES</i> as specified in WFS specification.<p>
 
 The name provided to the TYPENAME parameter must be exactly the layer name reported by OGR,
 in particular with its namespace prefix when its exists. Note: starting with GDAL 1.10, several type names can be provided and separated by comma.<p>
@@ -50,7 +50,7 @@ userid and password to the remote server.
 <li> <b>Version</b>:  Set a specific WFS version to use (either 1.0.0 or 1.1.0).
 <li> <b>PagingAllowed</b>: Set to ON if paging must be enabled. See "Request paging" section.
 <li> <b>PageSize</b>: Page size when paging is enabled. See "Request paging" section.
-<li> <b>BaseStartIndex</b>: (OGR >= 1.10) Base start index when paging is enabled. See "Request paging" section.
+<li> <b>BaseStartIndex</b>: (OGR >= 1.10) Base of the start index when paging is enabled (0 or 1). See "Request paging" section.
 <li> <b>COOKIE</b>: HTTP cookies that are passed in HTTP requests, formatted as COOKIE1=VALUE1; COOKIE2=VALUE2
 </ul>
 
@@ -58,11 +58,12 @@ userid and password to the remote server.
 
 Before OGR 1.10, when reading the first feature from a layer, the whole layer content will be fetched from the server.<p>
 
-Some servers (such as MapServer >= 6.0) support a vendor specific option, STARTINDEX, that allow to do the requests per "page",
-and thus to avoid downloading the whole content of the layer in a single request. The OGR WFS client will use paging when the OGR_WFS_PAGING_ALLOWED
-configuration option is set to ON. The page size (number of features fetched in a single request) is limited to 100 by default.
-It can be changed by setting the OGR_WFS_PAGE_SIZE configuration option.<br>
-WFS 1.1 specification has clarified that the first feature in paging is at index 0. But some server implementations of WFS 1.1
+Some servers (such as MapServer >= 6.0) support the use of STARTINDEX that allows to do the requests per "page",
+and thus to avoid downloading the whole content of the layer in a single request. Paging was introduced in WFS 2.0.0 but
+servers may support it as an vendor specific option also with WFS 1.0.0 and 1.1.0. The OGR WFS client will use paging when the
+OGR_WFS_PAGING_ALLOWED configuration option is set to ON. The page size (number of features fetched in a single request)
+is limited to 100 by default. It can be changed by setting the OGR_WFS_PAGE_SIZE configuration option.<br>
+WFS 2.0.2 specification has clarified that the first feature in paging is at index 0. But some server implementations of WFS paging
 have considered that it was at index 1 (including MapServer <= 6.2). Starting with OGR 1.10, the default base start index is 0,
 as mandated by the specification. The OGR_WFS_BASE_START_INDEX configuration option can however be set to 1 to be compatible
 with the server implementations that considered the first feature to be at index 1.<br>
diff --git a/ogr/ogrsf_frmts/wfs/ogr_wfs.h b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
index fd4cb0f..59b30f4 100644
--- a/ogr/ogrsf_frmts/wfs/ogr_wfs.h
+++ b/ogr/ogrsf_frmts/wfs/ogr_wfs.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_wfs.h 34401 2016-06-24 12:34:12Z rouault $
+ * $Id: ogr_wfs.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Definition of classes for OGR WFS driver.
@@ -63,10 +63,14 @@ class OGRWFSSortDesc
 {
     public:
         CPLString osColumn;
-        int       bAsc;
-
-        OGRWFSSortDesc(const CPLString& osColumnIn, int bAscIn) : osColumn(osColumnIn), bAsc(bAscIn) {}
-        OGRWFSSortDesc(const OGRWFSSortDesc& other) : osColumn(other.osColumn), bAsc(other.bAsc) {}
+        bool      bAsc;
+
+        OGRWFSSortDesc( const CPLString& osColumnIn, int bAscIn ) :
+            osColumn(osColumnIn),
+            bAsc(CPL_TO_BOOL(bAscIn)) {}
+        OGRWFSSortDesc(const OGRWFSSortDesc& other) :
+            osColumn(other.osColumn),
+            bAsc(other.bAsc) {}
 };
 
 /************************************************************************/
@@ -80,10 +84,10 @@ class OGRWFSLayer : public OGRLayer
     OGRWFSDataSource*   poDS;
 
     OGRFeatureDefn*     poFeatureDefn;
-    int                 bGotApproximateLayerDefn;
+    bool                bGotApproximateLayerDefn;
     GMLFeatureClass*    poGMLFeatureClass;
 
-    int                  bAxisOrderAlreadyInverted;
+    int                 bAxisOrderAlreadyInverted;
     OGRSpatialReference *poSRS;
 
     char*               pszBaseURL;
@@ -91,27 +95,30 @@ class OGRWFSLayer : public OGRLayer
     char*               pszNS;
     char*               pszNSVal;
 
-    int                 bStreamingDS;
+    bool                bStreamingDS;
     GDALDataset        *poBaseDS;
     OGRLayer           *poBaseLayer;
-    int                 bHasFetched;
-    int                 bReloadNeeded;
+    bool                bHasFetched;
+    bool                bReloadNeeded;
 
     CPLString           osGeometryColumnName;
     OGRwkbGeometryType  eGeomType;
     GIntBig             nFeatures;
-    int                 bCountFeaturesInGetNextFeature;
+    bool                bCountFeaturesInGetNextFeature;
 
     int                 CanRunGetFeatureCountAndGetExtentTogether();
 
     CPLString           MakeGetFeatureURL(int nMaxFeatures, int bRequestHits);
-    int                 MustRetryIfNonCompliantServer(const char* pszServerAnswer);
+    bool                MustRetryIfNonCompliantServer( const char* pszServerAnswer );
     GDALDataset*        FetchGetFeature(int nMaxFeatures);
     OGRFeatureDefn*     DescribeFeatureType();
     GIntBig             ExecuteGetFeatureResultTypeHits();
 
-    double              dfMinX, dfMinY, dfMaxX, dfMaxY;
-    int                 bHasExtents;
+    double              dfMinX;
+    double              dfMinY;
+    double              dfMaxX;
+    double              dfMaxY;
+    bool                bHasExtents;
 
     OGRGeometry        *poFetchedFilterGeom;
 
@@ -125,13 +132,13 @@ class OGRWFSLayer : public OGRLayer
     CPLString           osGlobalInsert;
     std::vector<CPLString> aosFIDList;
 
-    int                 bInTransaction;
+    bool                bInTransaction;
 
     CPLString           GetPostHeader();
 
-    int                 bUseFeatureIdAtLayerLevel;
+    bool                bUseFeatureIdAtLayerLevel;
 
-    int                 bPagingActive;
+    bool                bPagingActive;
     int                 nPagingStartIndex;
     int                 nFeatureRead;
     int                 nFeatureCountRequested;
@@ -151,43 +158,42 @@ class OGRWFSLayer : public OGRLayer
                                     const char* pszNS,
                                     const char* pszNSVal);
 
-                        ~OGRWFSLayer();
+                        virtual ~OGRWFSLayer();
 
     OGRWFSLayer*                Clone();
 
+    const char                 *GetName() override { return pszName; }
 
-    const char                 *GetName() { return pszName; }
-
-    virtual void                ResetReading();
-    virtual OGRFeature*         GetNextFeature();
-    virtual OGRFeature*         GetFeature(GIntBig nFID);
+    virtual void                ResetReading() override;
+    virtual OGRFeature*         GetNextFeature() override;
+    virtual OGRFeature*         GetFeature(GIntBig nFID) override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 
-    virtual GIntBig     GetFeatureCount( int bForce = TRUE );
+    virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override;
 
     void                SetExtents(double dfMinX, double dfMinY, double dfMaxX, double dfMaxY);
-    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE);
-    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
+    virtual OGRErr      GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
+    virtual OGRErr      GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce) override
                 { return OGRLayer::GetExtent(iGeomField, psExtent, bForce); }
 
-    virtual OGRErr      ICreateFeature( OGRFeature *poFeature );
-    virtual OGRErr      ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr      DeleteFeature( GIntBig nFID );
+    virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
 
-    virtual OGRErr      StartTransaction();
-    virtual OGRErr      CommitTransaction();
-    virtual OGRErr      RollbackTransaction();
+    virtual OGRErr      StartTransaction() override;
+    virtual OGRErr      CommitTransaction() override;
+    virtual OGRErr      RollbackTransaction() override;
 
-    virtual OGRErr      SetIgnoredFields( const char **papszFields );
+    virtual OGRErr      SetIgnoredFields( const char **papszFields ) override;
 
     int                 HasLayerDefn() { return poFeatureDefn != NULL; }
 
@@ -205,7 +211,7 @@ class OGRWFSLayer : public OGRLayer
     const char         *GetRequiredOutputFormat() { return pszRequiredOutputFormat; };
 
     void                SetOrderBy(const std::vector<OGRWFSSortDesc>& aoSortColumnsIn);
-    int                 HasGotApproximateLayerDefn() { GetLayerDefn(); return bGotApproximateLayerDefn; }
+    bool                HasGotApproximateLayerDefn() { GetLayerDefn(); return bGotApproximateLayerDefn; }
 
     const char*         GetNamespacePrefix() { return pszNS; }
     const char*         GetNamespaceName() { return pszNSVal; }
@@ -229,15 +235,16 @@ class OGRWFSJoinLayer : public OGRLayer
 
     GDALDataset        *poBaseDS;
     OGRLayer           *poBaseLayer;
-    int                 bReloadNeeded;
-    int                 bHasFetched;
+    bool                bReloadNeeded;
+    bool                bHasFetched;
 
-    int                 bPagingActive;
+    bool                bPagingActive;
     int                 nPagingStartIndex;
     int                 nFeatureRead;
     int                 nFeatureCountRequested;
 
-    std::vector<CPLString> aoSrcFieldNames, aoSrcGeomFieldNames;
+    std::vector<CPLString> aoSrcFieldNames;
+    std::vector<CPLString> aoSrcGeomFieldNames;
 
     CPLString           osFeatureTypes;
 
@@ -252,22 +259,22 @@ class OGRWFSJoinLayer : public OGRLayer
 
     static OGRWFSJoinLayer* Build(OGRWFSDataSource* poDS,
                                   const swq_select* psSelectInfo);
-                       ~OGRWFSJoinLayer();
+                       virtual ~OGRWFSJoinLayer();
 
-    virtual void                ResetReading();
-    virtual OGRFeature*         GetNextFeature();
+    virtual void                ResetReading() override;
+    virtual OGRFeature*         GetNextFeature() override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
-    virtual GIntBig             GetFeatureCount( int bForce = TRUE );
+    virtual GIntBig             GetFeatureCount( int bForce = TRUE ) override;
 
-    virtual void        SetSpatialFilter( OGRGeometry * );
-    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
+    virtual void        SetSpatialFilter( OGRGeometry * ) override;
+    virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override
                 { OGRLayer::SetSpatialFilter(iGeomField, poGeom); }
 
-    virtual OGRErr      SetAttributeFilter( const char * );
+    virtual OGRErr      SetAttributeFilter( const char * ) override;
 };
 
 /************************************************************************/
@@ -277,48 +284,48 @@ class OGRWFSJoinLayer : public OGRLayer
 class OGRWFSDataSource : public OGRDataSource
 {
     char*               pszName;
-    int                 bRewriteFile;
+    bool                bRewriteFile;
     CPLXMLNode*         psFileXML;
 
     OGRWFSLayer**       papoLayers;
     int                 nLayers;
     std::map<OGRLayer*, OGRLayer*> oMap;
 
-    int                 bUpdate;
+    bool                bUpdate;
 
-    int                 bGetFeatureSupportHits;
+    bool                bGetFeatureSupportHits;
     CPLString           osVersion;
-    int                 bNeedNAMESPACE;
-    int                 bHasMinOperators;
-    int                 bHasNullCheck;
-    int                 bPropertyIsNotEqualToSupported;
-    int                 bUseFeatureId;
-    int                 bGmlObjectIdNeedsGMLPrefix;
-    int                 bRequiresEnvelopeSpatialFilter;
-    int                 DetectRequiresEnvelopeSpatialFilter(CPLXMLNode* psRoot);
-
-    int                 bTransactionSupport;
+    bool                bNeedNAMESPACE;
+    bool                bHasMinOperators;
+    bool                bHasNullCheck;
+    bool                bPropertyIsNotEqualToSupported;
+    bool                bUseFeatureId;
+    bool                bGmlObjectIdNeedsGMLPrefix;
+    bool                bRequiresEnvelopeSpatialFilter;
+    static bool                DetectRequiresEnvelopeSpatialFilter( CPLXMLNode* psRoot );
+
+    bool                bTransactionSupport;
     char**              papszIdGenMethods;
-    int                 DetectTransactionSupport(CPLXMLNode* psRoot);
+    bool                DetectTransactionSupport( CPLXMLNode* psRoot );
 
     CPLString           osBaseURL;
     CPLString           osPostTransactionURL;
 
     CPLXMLNode*         LoadFromFile( const char * pszFilename );
 
-    int                 bUseHttp10;
+    bool                bUseHttp10;
 
     char**              papszHttpOptions;
 
-    int                 bPagingAllowed;
+    bool                bPagingAllowed;
     int                 nPageSize;
     int                 nBaseStartIndex;
-    int                 DetectSupportPagingWFS2(CPLXMLNode* psRoot);
+    bool                DetectSupportPagingWFS2(CPLXMLNode* psRoot);
 
-    int                 bStandardJoinsWFS2;
-    int                 DetectSupportStandardJoinsWFS2(CPLXMLNode* psRoot);
+    bool                bStandardJoinsWFS2;
+    bool                DetectSupportStandardJoinsWFS2( CPLXMLNode* psRoot );
 
-    int                 bLoadMultipleLayerDefn;
+    bool                bLoadMultipleLayerDefn;
     std::set<CPLString> aoSetAlreadyTriedLayers;
 
     CPLString           osLayerMetadataCSV;
@@ -331,13 +338,13 @@ class OGRWFSDataSource : public OGRDataSource
     GDALDataset        *poLayerGetCapabilitiesDS;
     OGRLayer           *poLayerGetCapabilitiesLayer;
 
-    int                 bKeepLayerNamePrefix;
+    bool                bKeepLayerNamePrefix;
 
-    int                 bEmptyAsNull;
+    bool                bEmptyAsNull;
 
-    int                 bInvertAxisOrderIfLatLong;
+    bool                bInvertAxisOrderIfLatLong;
     CPLString           osConsiderEPSGAsURN;
-    int                 bExposeGMLId;
+    bool                bExposeGMLId;
 
     CPLHTTPResult*      SendGetCapabilities(const char* pszBaseURL,
                                             CPLString& osTypeName);
@@ -346,42 +353,47 @@ class OGRWFSDataSource : public OGRDataSource
 
   public:
                         OGRWFSDataSource();
-                        ~OGRWFSDataSource();
+                        virtual ~OGRWFSDataSource();
 
     int                 Open( const char * pszFilename,
                               int bUpdate,
                               char** papszOpenOptions );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
-    virtual OGRLayer*           GetLayerByName(const char* pszLayerName);
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
+    virtual OGRLayer*           GetLayerByName(const char* pszLayerName) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     virtual OGRLayer *          ExecuteSQL( const char *pszSQLCommand,
                                         OGRGeometry *poSpatialFilter,
-                                        const char *pszDialect );
-    virtual void                ReleaseResultSet( OGRLayer * poResultsSet );
-
-    int                         UpdateMode() { return bUpdate; }
-    int                         SupportTransactions() { return bTransactionSupport; }
-    void                        DisableSupportHits() { bGetFeatureSupportHits = FALSE; }
-    int                         GetFeatureSupportHits() { return bGetFeatureSupportHits; }
+                                        const char *pszDialect ) override;
+    virtual void                ReleaseResultSet( OGRLayer * poResultsSet ) override;
+
+    bool                        UpdateMode() const { return bUpdate; }
+    bool                        SupportTransactions() const
+        { return bTransactionSupport; }
+    void                        DisableSupportHits() { bGetFeatureSupportHits = false; }
+    bool                        GetFeatureSupportHits() const
+        { return bGetFeatureSupportHits; }
     const char                 *GetVersion() { return osVersion.c_str(); }
 
-    int                         IsOldDeegree(const char* pszErrorString);
-    int                         GetNeedNAMESPACE() { return bNeedNAMESPACE; }
-    int                         HasMinOperators() { return bHasMinOperators; }
-    int                         HasNullCheck() { return bHasNullCheck; }
-    int                         UseFeatureId() { return bUseFeatureId; }
-    int                         RequiresEnvelopeSpatialFilter() { return bRequiresEnvelopeSpatialFilter; }
-    void                        SetGmlObjectIdNeedsGMLPrefix() { bGmlObjectIdNeedsGMLPrefix = TRUE; }
-    int                         DoesGmlObjectIdNeedGMLPrefix() { return bGmlObjectIdNeedsGMLPrefix; }
-
-    void                        SetPropertyIsNotEqualToUnSupported() { bPropertyIsNotEqualToSupported = FALSE; }
-    int                         PropertyIsNotEqualToSupported() { return bPropertyIsNotEqualToSupported; }
+    bool                        IsOldDeegree( const char* pszErrorString );
+    bool                        GetNeedNAMESPACE() const { return bNeedNAMESPACE; }
+    bool                        HasMinOperators() const { return bHasMinOperators; }
+    bool                        HasNullCheck() const { return bHasNullCheck; }
+    bool                        UseFeatureId() const { return bUseFeatureId; }
+    bool                        RequiresEnvelopeSpatialFilter() const
+        { return bRequiresEnvelopeSpatialFilter; }
+    void                        SetGmlObjectIdNeedsGMLPrefix() { bGmlObjectIdNeedsGMLPrefix = true; }
+    int                         DoesGmlObjectIdNeedGMLPrefix() const
+        { return bGmlObjectIdNeedsGMLPrefix; }
+
+    void                        SetPropertyIsNotEqualToUnSupported() { bPropertyIsNotEqualToSupported = false; }
+    bool                        PropertyIsNotEqualToSupported() const
+        { return bPropertyIsNotEqualToSupported; }
 
     CPLString                   GetPostTransactionURL();
 
@@ -389,24 +401,27 @@ class OGRWFSDataSource : public OGRDataSource
 
     CPLHTTPResult*              HTTPFetch( const char* pszURL, char** papszOptions );
 
-    int                         IsPagingAllowed() const { return bPagingAllowed; }
+    bool                        IsPagingAllowed() const { return bPagingAllowed; }
     int                         GetPageSize() const { return nPageSize; }
     int                         GetBaseStartIndex() const { return nBaseStartIndex; }
 
     void                        LoadMultipleLayerDefn(const char* pszLayerName,
                                                       char* pszNS, char* pszNSVal);
 
-    int                         GetKeepLayerNamePrefix() { return bKeepLayerNamePrefix; }
+    bool                        GetKeepLayerNamePrefix() const
+        { return bKeepLayerNamePrefix; }
     const CPLString&            GetBaseURL() { return osBaseURL; }
 
-    int                         IsEmptyAsNull() const { return bEmptyAsNull; }
-    int                         InvertAxisOrderIfLatLong() const { return bInvertAxisOrderIfLatLong; }
+    bool                        IsEmptyAsNull() const
+        { return bEmptyAsNull; }
+    bool                        InvertAxisOrderIfLatLong() const
+        { return bInvertAxisOrderIfLatLong; }
     const CPLString&            GetConsiderEPSGAsURN() const { return osConsiderEPSGAsURN; }
 
-    int                         ExposeGMLId() const { return bExposeGMLId; }
+    bool                        ExposeGMLId() const { return bExposeGMLId; }
 
-    virtual char**              GetMetadataDomainList();
-    virtual char**              GetMetadata( const char * pszDomain = "" );
+    virtual char**              GetMetadataDomainList() override;
+    virtual char**              GetMetadata( const char * pszDomain = "" ) override;
 };
 
 #endif /* ndef OGR_WFS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
index 4394aef..23417ca 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwfsdatasource.cpp 34572 2016-07-06 18:31:02Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSDataSource class
@@ -37,10 +36,12 @@
 #include "swq.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrwfsdatasource.cpp 34572 2016-07-06 18:31:02Z rouault $");
+#include <algorithm>
 
-#define DEFAULT_BASE_START_INDEX     0
-#define DEFAULT_PAGE_SIZE            100
+CPL_CVSID("$Id: ogrwfsdatasource.cpp 36682 2016-12-04 20:34:45Z rouault $");
+
+static const int DEFAULT_BASE_START_INDEX = 0;
+static const int DEFAULT_PAGE_SIZE = 100;
 
 typedef struct
 {
@@ -50,18 +51,18 @@ typedef struct
 
 static const MetadataItem asMetadata[] =
 {
-    {  "Service.Title", "TITLE" }, /*1.0 */
-    {  "ServiceIdentification.Title", "TITLE" }, /* 1.1 or 2.0 */
-    {  "Service.Abstract", "ABSTRACT" }, /* 1.0 */
-    {  "ServiceIdentification.Abstract", "ABSTRACT" }, /* 1.1 or 2.0 */
-    {  "ServiceProvider.ProviderName", "PROVIDER_NAME" }, /* 1.1 or 2.0 */
+    { "Service.Title", "TITLE" }, /*1.0 */
+    { "ServiceIdentification.Title", "TITLE" }, /* 1.1 or 2.0 */
+    { "Service.Abstract", "ABSTRACT" }, /* 1.0 */
+    { "ServiceIdentification.Abstract", "ABSTRACT" }, /* 1.1 or 2.0 */
+    { "ServiceProvider.ProviderName", "PROVIDER_NAME" }, /* 1.1 or 2.0 */
 };
 
 /************************************************************************/
 /*                            WFSFindNode()                             */
 /************************************************************************/
 
-CPLXMLNode* WFSFindNode(CPLXMLNode* psXML, const char* pszRootName)
+CPLXMLNode* WFSFindNode( CPLXMLNode* psXML, const char* pszRootName )
 {
     CPLXMLNode* psIter = psXML;
     do
@@ -106,67 +107,70 @@ CPLXMLNode* WFSFindNode(CPLXMLNode* psXML, const char* pszRootName)
 class OGRWFSWrappedResultLayer : public OGRLayer
 {
     GDALDataset *poDS;
-    OGRLayer      *poLayer;
+    OGRLayer    *poLayer;
 
     public:
-        OGRWFSWrappedResultLayer(GDALDataset* poDSIn, OGRLayer* poLayerIn)
-        {
-            this->poDS = poDSIn;
-            this->poLayer = poLayerIn;
-        }
+        OGRWFSWrappedResultLayer( GDALDataset* poDSIn, OGRLayer* poLayerIn ) :
+            poDS(poDSIn),
+            poLayer(poLayerIn)
+        {}
         ~OGRWFSWrappedResultLayer()
         {
             delete poDS;
         }
 
-        virtual void        ResetReading() { poLayer->ResetReading(); }
-        virtual OGRFeature *GetNextFeature() { return poLayer->GetNextFeature(); }
-        virtual OGRErr      SetNextByIndex( GIntBig nIndex ) { return poLayer->SetNextByIndex(nIndex); }
-        virtual OGRFeature *GetFeature( GIntBig nFID ) { return poLayer->GetFeature(nFID); }
-        virtual OGRFeatureDefn *GetLayerDefn() { return poLayer->GetLayerDefn(); }
-        virtual GIntBig     GetFeatureCount( int bForce = TRUE ) { return poLayer->GetFeatureCount(bForce); }
-        virtual int         TestCapability( const char * pszCap )  { return poLayer->TestCapability(pszCap); }
+        virtual void        ResetReading() override { poLayer->ResetReading(); }
+        virtual OGRFeature *GetNextFeature() override { return poLayer->GetNextFeature(); }
+        virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override { return poLayer->SetNextByIndex(nIndex); }
+        virtual OGRFeature *GetFeature( GIntBig nFID ) override { return poLayer->GetFeature(nFID); }
+        virtual OGRFeatureDefn *GetLayerDefn() override { return poLayer->GetLayerDefn(); }
+        virtual GIntBig     GetFeatureCount( int bForce = TRUE ) override { return poLayer->GetFeatureCount(bForce); }
+        virtual int         TestCapability( const char * pszCap ) override  { return poLayer->TestCapability(pszCap); }
 };
 
-
 /************************************************************************/
 /*                          OGRWFSDataSource()                          */
 /************************************************************************/
 
-OGRWFSDataSource::OGRWFSDataSource()
-
+OGRWFSDataSource::OGRWFSDataSource() :
+    pszName(NULL),
+    bRewriteFile(false),
+    psFileXML(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    bUpdate(false),
+    bGetFeatureSupportHits(false),
+    bNeedNAMESPACE(false),
+    bHasMinOperators(false),
+    bHasNullCheck(false),
+    // Advertized by deegree but not implemented.
+    bPropertyIsNotEqualToSupported(true),
+    bUseFeatureId(false),  // CubeWerx doesn't like GmlObjectId.
+    bGmlObjectIdNeedsGMLPrefix(false),
+    bRequiresEnvelopeSpatialFilter(false),
+    bTransactionSupport(false),
+    papszIdGenMethods(NULL),
+    bUseHttp10(false),
+    papszHttpOptions(NULL),
+    bPagingAllowed(CPLTestBool(
+        CPLGetConfigOption("OGR_WFS_PAGING_ALLOWED", "OFF"))),
+    nPageSize(DEFAULT_PAGE_SIZE),
+    nBaseStartIndex(DEFAULT_BASE_START_INDEX),
+    bStandardJoinsWFS2(false),
+    bLoadMultipleLayerDefn(CPLTestBool(
+        CPLGetConfigOption("OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN", "TRUE"))),
+    poLayerMetadataDS(NULL),
+    poLayerMetadataLayer(NULL),
+    poLayerGetCapabilitiesDS(NULL),
+    poLayerGetCapabilitiesLayer(NULL),
+    bKeepLayerNamePrefix(false),
+    bEmptyAsNull(true),
+    bInvertAxisOrderIfLatLong(true),
+    bExposeGMLId(true)
 {
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-
-    bUpdate = FALSE;
-    bGetFeatureSupportHits = FALSE;
-    bNeedNAMESPACE = FALSE;
-    bHasMinOperators = FALSE;
-    bHasNullCheck = FALSE;
-    bPropertyIsNotEqualToSupported = TRUE; /* advertized by deegree but not implemented */
-    bTransactionSupport = FALSE;
-    papszIdGenMethods = NULL;
-    bUseFeatureId = FALSE; /* CubeWerx doesn't like GmlObjectId */
-    bGmlObjectIdNeedsGMLPrefix = FALSE;
-    bRequiresEnvelopeSpatialFilter = FALSE;
-
-    bRewriteFile = FALSE;
-    psFileXML = NULL;
-
-    bUseHttp10 = FALSE;
-    papszHttpOptions = NULL;
-
-    bPagingAllowed = CPLTestBool(CPLGetConfigOption("OGR_WFS_PAGING_ALLOWED", "OFF"));
-    nPageSize = DEFAULT_PAGE_SIZE;
-    nBaseStartIndex = DEFAULT_BASE_START_INDEX;
-    if (bPagingAllowed)
+    if( bPagingAllowed )
     {
-        const char* pszOption;
-
-        pszOption = CPLGetConfigOption("OGR_WFS_PAGE_SIZE", NULL);
+        const char* pszOption = CPLGetConfigOption("OGR_WFS_PAGE_SIZE", NULL);
         if( pszOption != NULL )
         {
             nPageSize = atoi(pszOption);
@@ -179,23 +183,8 @@ OGRWFSDataSource::OGRWFSDataSource()
             nBaseStartIndex = atoi(pszOption);
     }
 
-    bStandardJoinsWFS2 = FALSE;
-
-    bLoadMultipleLayerDefn = CPLTestBool(CPLGetConfigOption("OGR_WFS_LOAD_MULTIPLE_LAYER_DEFN", "TRUE"));
-
-    poLayerMetadataDS = NULL;
-    poLayerMetadataLayer = NULL;
-
-    poLayerGetCapabilitiesDS = NULL;
-    poLayerGetCapabilitiesLayer = NULL;
-
-    bKeepLayerNamePrefix = FALSE;
     apszGetCapabilities[0] = NULL;
     apszGetCapabilities[1] = NULL;
-    bEmptyAsNull = TRUE;
-
-    bInvertAxisOrderIfLatLong = TRUE;
-    bExposeGMLId = TRUE;
 }
 
 /************************************************************************/
@@ -205,9 +194,9 @@ OGRWFSDataSource::OGRWFSDataSource()
 OGRWFSDataSource::~OGRWFSDataSource()
 
 {
-    if (psFileXML)
+    if( psFileXML )
     {
-        if (bRewriteFile)
+        if( bRewriteFile )
         {
             CPLSerializeXMLTreeToFile(psFileXML, pszName);
         }
@@ -215,12 +204,11 @@ OGRWFSDataSource::~OGRWFSDataSource()
         CPLDestroyXMLNode(psFileXML);
     }
 
-    int i;
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
     CPLFree( papoLayers );
 
-    if (osLayerMetadataTmpFileName.size() != 0)
+    if (!osLayerMetadataTmpFileName.empty())
         VSIUnlink(osLayerMetadataTmpFileName);
     delete poLayerMetadataDS;
     delete poLayerGetCapabilitiesDS;
@@ -263,7 +251,7 @@ OGRLayer* OGRWFSDataSource::GetLayerByName(const char* pszNameIn)
 
     if (EQUAL(pszNameIn, "WFSLayerMetadata"))
     {
-        if (osLayerMetadataTmpFileName.size() != 0)
+        if (!osLayerMetadataTmpFileName.empty())
             return poLayerMetadataLayer;
 
         osLayerMetadataTmpFileName = CPLSPrintf("/vsimem/tempwfs_%p/WFSLayerMetadata.csv", this);
@@ -318,7 +306,6 @@ char** OGRWFSDataSource::GetMetadataDomainList()
     return BuildMetadataDomainList(GDALDataset::GetMetadataDomainList(),
                                    TRUE,
                                    "", "xml:capabilities", NULL);
-
 }
 
 /************************************************************************/
@@ -342,22 +329,21 @@ char** OGRWFSDataSource::GetMetadata( const char * pszDomain )
 
 int OGRWFSDataSource::GetLayerIndex(const char* pszNameIn)
 {
-    int i;
-    int  bHasFoundLayerWithColon = FALSE;
+    bool bHasFoundLayerWithColon = false;
 
     /* first a case sensitive check */
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
     {
         OGRWFSLayer *poLayer = papoLayers[i];
 
         if( strcmp( pszNameIn, poLayer->GetName() ) == 0 )
             return i;
 
-        bHasFoundLayerWithColon |= (strchr( poLayer->GetName(), ':') != NULL);
+        bHasFoundLayerWithColon |= strchr( poLayer->GetName(), ':') != NULL;
     }
 
     /* then case insensitive */
-    for( i = 0; i < nLayers; i++ )
+    for( int i = 0; i < nLayers; i++ )
     {
         OGRWFSLayer *poLayer = papoLayers[i];
 
@@ -366,9 +352,11 @@ int OGRWFSDataSource::GetLayerIndex(const char* pszNameIn)
     }
 
     /* now try looking after the colon character */
-    if (!bKeepLayerNamePrefix && bHasFoundLayerWithColon && strchr(pszNameIn, ':') == NULL)
+    if( !bKeepLayerNamePrefix &&
+        bHasFoundLayerWithColon &&
+        strchr(pszNameIn, ':') == NULL )
     {
-        for( i = 0; i < nLayers; i++ )
+        for( int i = 0; i < nLayers; i++ )
         {
             OGRWFSLayer *poLayer = papoLayers[i];
 
@@ -398,14 +386,14 @@ const char* FindSubStringInsensitive(const char* pszStr,
 /*                 DetectIfGetFeatureSupportHits()                      */
 /************************************************************************/
 
-static int DetectIfGetFeatureSupportHits(CPLXMLNode* psRoot)
+static bool DetectIfGetFeatureSupportHits( CPLXMLNode* psRoot )
 {
     CPLXMLNode* psOperationsMetadata =
         CPLGetXMLNode(psRoot, "OperationsMetadata");
     if (!psOperationsMetadata)
     {
         CPLDebug("WFS", "Could not find <OperationsMetadata>");
-        return FALSE;
+        return false;
     }
 
     CPLXMLNode* psChild = psOperationsMetadata->psChild;
@@ -422,7 +410,7 @@ static int DetectIfGetFeatureSupportHits(CPLXMLNode* psRoot)
     if (!psChild)
     {
         CPLDebug("WFS", "Could not find <Operation name=\"GetFeature\">");
-        return FALSE;
+        return false;
     }
 
     psChild = psChild->psChild;
@@ -439,7 +427,7 @@ static int DetectIfGetFeatureSupportHits(CPLXMLNode* psRoot)
    if (!psChild)
     {
         CPLDebug("WFS", "Could not find <Parameter name=\"resultType\">");
-        return FALSE;
+        return false;
     }
 
     psChild = psChild->psChild;
@@ -455,7 +443,7 @@ static int DetectIfGetFeatureSupportHits(CPLXMLNode* psRoot)
                     strcmp(psChild2->pszValue, "hits") == 0)
                 {
                     CPLDebug("WFS", "GetFeature operation supports hits");
-                    return TRUE;
+                    return true;
                 }
                 psChild2 = psChild2->psNext;
             }
@@ -463,40 +451,39 @@ static int DetectIfGetFeatureSupportHits(CPLXMLNode* psRoot)
         psChild = psChild->psNext;
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
 /*                   DetectRequiresEnvelopeSpatialFilter()              */
 /************************************************************************/
 
-int OGRWFSDataSource::DetectRequiresEnvelopeSpatialFilter(CPLXMLNode* psRoot)
+bool OGRWFSDataSource::DetectRequiresEnvelopeSpatialFilter( CPLXMLNode* psRoot )
 {
-    /* This is a heuristic to detect Deegree 3 servers, such as */
-    /* http://deegree3-demo.deegree.org:80/deegree-utah-demo/services */
-    /* that are very GML3 strict, and don't like <gml:Box> in a <Filter><BBOX> */
-    /* request, but requires instead <gml:Envelope>, but some servers (such as MapServer) */
-    /* don't like <gml:Envelope> so we are obliged to detect the kind of server */
-
-    int nCount;
-    CPLXMLNode* psChild;
+    // This is a heuristic to detect Deegree 3 servers, such as
+    // http://deegree3-demo.deegree.org:80/deegree-utah-demo/services that are
+    // very GML3 strict, and don't like <gml:Box> in a <Filter><BBOX> request,
+    // but requires instead <gml:Envelope>, but some servers (such as MapServer)
+    // don't like <gml:Envelope> so we are obliged to detect the kind of server.
 
     CPLXMLNode* psGeometryOperands =
-        CPLGetXMLNode(psRoot, "Filter_Capabilities.Spatial_Capabilities.GeometryOperands");
+        CPLGetXMLNode(
+            psRoot,
+            "Filter_Capabilities.Spatial_Capabilities.GeometryOperands");
     if (!psGeometryOperands)
     {
-        return FALSE;
+        return false;
     }
 
-    nCount = 0;
-    psChild = psGeometryOperands->psChild;
-    while(psChild)
+    int nCount = 0;
+    CPLXMLNode* psChild = psGeometryOperands->psChild;
+    while( psChild )
     {
-        nCount ++;
+        nCount++;
         psChild = psChild->psNext;
     }
-    /* Magic number... Might be fragile */
-    return (nCount == 19);
+    // Magic number... Might be fragile.
+    return nCount == 19;
 }
 
 /************************************************************************/
@@ -505,7 +492,7 @@ int OGRWFSDataSource::DetectRequiresEnvelopeSpatialFilter(CPLXMLNode* psRoot)
 
 CPLString OGRWFSDataSource::GetPostTransactionURL()
 {
-    if (osPostTransactionURL.size())
+    if (!osPostTransactionURL.empty() )
         return osPostTransactionURL;
 
     osPostTransactionURL = osBaseURL;
@@ -521,7 +508,7 @@ CPLString OGRWFSDataSource::GetPostTransactionURL()
 /*                    DetectTransactionSupport()                        */
 /************************************************************************/
 
-int OGRWFSDataSource::DetectTransactionSupport(CPLXMLNode* psRoot)
+bool OGRWFSDataSource::DetectTransactionSupport( CPLXMLNode* psRoot )
 {
     CPLXMLNode* psTransactionWFS100 =
         CPLGetXMLNode(psRoot, "Capability.Request.Transaction");
@@ -537,15 +524,15 @@ int OGRWFSDataSource::DetectTransactionSupport(CPLXMLNode* psRoot)
             }
         }
 
-        bTransactionSupport = TRUE;
-        return TRUE;
+        bTransactionSupport = true;
+        return true;
     }
 
     CPLXMLNode* psOperationsMetadata =
         CPLGetXMLNode(psRoot, "OperationsMetadata");
     if (!psOperationsMetadata)
     {
-        return FALSE;
+        return false;
     }
 
     CPLXMLNode* psChild = psOperationsMetadata->psChild;
@@ -562,13 +549,12 @@ int OGRWFSDataSource::DetectTransactionSupport(CPLXMLNode* psRoot)
     if (!psChild)
     {
         CPLDebug("WFS", "No transaction support");
-        return FALSE;
+        return false;
     }
 
-    bTransactionSupport = TRUE;
+    bTransactionSupport = true;
     CPLDebug("WFS", "Transaction support !");
 
-
     CPLXMLNode* psPostURL = CPLGetXMLNode(psChild, "DCP.HTTP.Post");
     if (psPostURL)
     {
@@ -591,7 +577,7 @@ int OGRWFSDataSource::DetectTransactionSupport(CPLXMLNode* psRoot)
    if (!psChild)
     {
         papszIdGenMethods = CSLAddString(NULL, "GenerateNew");
-        return TRUE;
+        return true;
     }
 
     psChild = psChild->psChild;
@@ -614,24 +600,24 @@ int OGRWFSDataSource::DetectTransactionSupport(CPLXMLNode* psRoot)
         psChild = psChild->psNext;
     }
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                    DetectSupportPagingWFS2()                         */
 /************************************************************************/
 
-int OGRWFSDataSource::DetectSupportPagingWFS2(CPLXMLNode* psRoot)
+bool OGRWFSDataSource::DetectSupportPagingWFS2( CPLXMLNode* psRoot )
 {
     const char* pszPagingAllowed = CPLGetConfigOption("OGR_WFS_PAGING_ALLOWED", NULL);
     if( pszPagingAllowed != NULL && !CPLTestBool(pszPagingAllowed) )
-        return FALSE;
+        return false;
 
     CPLXMLNode* psOperationsMetadata =
         CPLGetXMLNode(psRoot, "OperationsMetadata");
     if (!psOperationsMetadata)
     {
-        return FALSE;
+        return false;
     }
 
     CPLXMLNode* psChild = psOperationsMetadata->psChild;
@@ -653,7 +639,7 @@ int OGRWFSDataSource::DetectSupportPagingWFS2(CPLXMLNode* psRoot)
     if (!psChild)
     {
         CPLDebug("WFS", "No paging support");
-        return FALSE;
+        return false;
     }
 
     psChild = psOperationsMetadata->psChild;
@@ -694,22 +680,22 @@ int OGRWFSDataSource::DetectSupportPagingWFS2(CPLXMLNode* psRoot)
     }
 
     CPLDebug("WFS", "Paging support with page size %d", nPageSize);
-    bPagingAllowed = TRUE;
+    bPagingAllowed = true;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                   DetectSupportStandardJoinsWFS2()                   */
 /************************************************************************/
 
-int OGRWFSDataSource::DetectSupportStandardJoinsWFS2(CPLXMLNode* psRoot)
+bool OGRWFSDataSource::DetectSupportStandardJoinsWFS2(CPLXMLNode* psRoot)
 {
     CPLXMLNode* psOperationsMetadata =
         CPLGetXMLNode(psRoot, "OperationsMetadata");
-    if (!psOperationsMetadata)
+    if( !psOperationsMetadata )
     {
-        return FALSE;
+        return false;
     }
 
     CPLXMLNode* psChild = psOperationsMetadata->psChild;
@@ -731,17 +717,17 @@ int OGRWFSDataSource::DetectSupportStandardJoinsWFS2(CPLXMLNode* psRoot)
     if (!psChild)
     {
         CPLDebug("WFS", "No ImplementsStandardJoins support");
-        return FALSE;
+        return false;
     }
-    bStandardJoinsWFS2 = TRUE;
-    return TRUE;
+    bStandardJoinsWFS2 = true;
+    return true;
 }
 
 /************************************************************************/
 /*                      FindComparisonOperator()                        */
 /************************************************************************/
 
-static int FindComparisonOperator(CPLXMLNode* psNode, const char* pszVal)
+static bool FindComparisonOperator( CPLXMLNode* psNode, const char* pszVal )
 {
     CPLXMLNode* psChild = psNode->psChild;
     while(psChild)
@@ -750,17 +736,17 @@ static int FindComparisonOperator(CPLXMLNode* psNode, const char* pszVal)
             strcmp(psChild->pszValue, "ComparisonOperator") == 0)
         {
             if (strcmp(CPLGetXMLValue(psChild, NULL, ""), pszVal) == 0)
-                return TRUE;
+                return true;
 
             /* For WFS 2.0.0 */
             const char* pszName = CPLGetXMLValue(psChild, "name", NULL);
             if (pszName != NULL && STARTS_WITH(pszName, "PropertyIs") &&
                 strcmp(pszName + 10, pszVal) == 0)
-                return TRUE;
+                return true;
         }
         psChild = psChild->psNext;
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -769,21 +755,20 @@ static int FindComparisonOperator(CPLXMLNode* psNode, const char* pszVal)
 
 CPLXMLNode* OGRWFSDataSource::LoadFromFile( const char * pszFilename )
 {
-    VSILFILE *fp;
-    char achHeader[1024];
-
     VSIStatBufL sStatBuf;
     if (VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG ) != 0 ||
         VSI_ISDIR(sStatBuf.st_mode))
         return NULL;
 
-    fp = VSIFOpenL( pszFilename, "rb" );
+    VSILFILE *fp = VSIFOpenL( pszFilename, "rb" );
 
     if( fp == NULL )
         return NULL;
 
-    int nRead;
-    if( (nRead = static_cast<int>(VSIFReadL( achHeader, 1, sizeof(achHeader) - 1, fp ))) == 0 )
+    char achHeader[1024] = {};
+    const int nRead =
+        static_cast<int>(VSIFReadL( achHeader, 1, sizeof(achHeader) - 1, fp ));
+    if( nRead == 0 )
     {
         VSIFCloseL( fp );
         return NULL;
@@ -801,10 +786,8 @@ CPLXMLNode* OGRWFSDataSource::LoadFromFile( const char * pszFilename )
 /* -------------------------------------------------------------------- */
 /*      It is the right file, now load the full XML definition.         */
 /* -------------------------------------------------------------------- */
-    int nLen;
-
     VSIFSeekL( fp, 0, SEEK_END );
-    nLen = (int) VSIFTellL( fp );
+    const int nLen = (int) VSIFTellL( fp );
     VSIFSeekL( fp, 0, SEEK_SET );
 
     char* pszXML = (char *) VSI_MALLOC_VERBOSE(nLen+1);
@@ -826,11 +809,11 @@ CPLXMLNode* OGRWFSDataSource::LoadFromFile( const char * pszFilename )
     if (strstr(pszXML, "CubeWerx"))
     {
         /* At least true for CubeWerx Suite 4.15.1 */
-        bUseFeatureId = TRUE;
+        bUseFeatureId = true;
     }
     else if (strstr(pszXML, "deegree"))
     {
-        bGmlObjectIdNeedsGMLPrefix = TRUE;
+        bGmlObjectIdNeedsGMLPrefix = true;
     }
 
     CPLXMLNode* psXML = CPLParseXMLString( pszXML );
@@ -851,7 +834,7 @@ CPLHTTPResult* OGRWFSDataSource::SendGetCapabilities(const char* pszBaseURL,
     osURL = CPLURLAddKVP(osURL, "SERVICE", "WFS");
     osURL = CPLURLAddKVP(osURL, "REQUEST", "GetCapabilities");
     osTypeName = CPLURLGetValue(osURL, "TYPENAME");
-    if( osTypeName.size() == 0 )
+    if( osTypeName.empty() )
         osTypeName = CPLURLGetValue(osURL, "TYPENAMES");
     osURL = CPLURLAddKVP(osURL, "TYPENAME", NULL);
     osURL = CPLURLAddKVP(osURL, "TYPENAMES", NULL);
@@ -860,11 +843,9 @@ CPLHTTPResult* OGRWFSDataSource::SendGetCapabilities(const char* pszBaseURL,
     osURL = CPLURLAddKVP(osURL, "MAXFEATURES", NULL);
     osURL = CPLURLAddKVP(osURL, "OUTPUTFORMAT", NULL);
 
-    CPLHTTPResult* psResult;
-
     CPLDebug("WFS", "%s", osURL.c_str());
 
-    psResult = HTTPFetch( osURL, NULL);
+    CPLHTTPResult* psResult = HTTPFetch( osURL, NULL);
     if (psResult == NULL)
     {
         return NULL;
@@ -894,7 +875,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                             char** papszOpenOptionsIn )
 
 {
-    bUpdate = bUpdateIn;
+    bUpdate = CPL_TO_BOOL(bUpdateIn);
     CPLFree(pszName);
     pszName = CPLStrdup(pszFilename);
 
@@ -903,7 +884,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
     CPLString osTypeName;
     const char* pszBaseURL = NULL;
 
-    bEmptyAsNull = CSLFetchBoolean(papszOpenOptionsIn, "EMPTY_AS_NULL", TRUE);
+    bEmptyAsNull = CPLFetchBool(papszOpenOptionsIn, "EMPTY_AS_NULL", true);
 
     if (psXML == NULL)
     {
@@ -939,11 +920,11 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
         if (strstr((const char*) psResult->pabyData, "CubeWerx"))
         {
             /* At least true for CubeWerx Suite 4.15.1 */
-            bUseFeatureId = TRUE;
+            bUseFeatureId = true;
         }
         else if (strstr((const char*) psResult->pabyData, "deegree"))
         {
-            bGmlObjectIdNeedsGMLPrefix = TRUE;
+            bGmlObjectIdNeedsGMLPrefix = true;
         }
 
         psXML = CPLParseXMLString( (const char*) psResult->pabyData );
@@ -990,9 +971,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
 /* -------------------------------------------------------------------- */
 /*      Capture other parameters.                                       */
 /* -------------------------------------------------------------------- */
-        const char  *pszParm;
-
-        pszParm = CPLGetXMLValue( psRoot, "Timeout", NULL );
+        const char *pszParm = CPLGetXMLValue( psRoot, "Timeout", NULL );
         if( pszParm )
             papszHttpOptions =
                 CSLSetNameValue(papszHttpOptions,
@@ -1037,7 +1016,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
             nBaseStartIndex = atoi(pszParm);
 
         CPLString strOriginalTypeName = CPLURLGetValue(pszBaseURL, "TYPENAME");
-        if( strOriginalTypeName.size() == 0 )
+        if( strOriginalTypeName.empty() )
             strOriginalTypeName = CPLURLGetValue(pszBaseURL, "TYPENAMES");
         osTypeName = WFS_DecodeURL(strOriginalTypeName);
 
@@ -1077,15 +1056,16 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
 
             CPLAddXMLChild(psXML, CPLCloneXMLTree(psWFSCapabilities));
 
-            int bOK = CPLSerializeXMLTreeToFile(psXML, pszFilename);
+            const bool bOK =
+                CPL_TO_BOOL(CPLSerializeXMLTreeToFile(psXML, pszFilename));
 
             CPLDestroyXMLNode( psXML );
             CPLDestroyXMLNode( psXML2 );
 
-            if (bOK)
+            if( bOK )
                 return Open(pszFilename, bUpdate, papszOpenOptionsIn);
-            else
-                return FALSE;
+
+            return FALSE;
         }
         else
         {
@@ -1151,36 +1131,39 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
 
     pszBaseURL = NULL;
 
-    for(int i=0; i < (int)(sizeof(asMetadata) / sizeof(asMetadata[0])); i++ )
+    for( int i=0; i < (int)(sizeof(asMetadata) / sizeof(asMetadata[0])); i++ )
     {
         const char* pszVal = CPLGetXMLValue( psWFSCapabilities, asMetadata[i].pszPath, NULL );
         if( pszVal )
             SetMetadataItem(asMetadata[i].pszMDI, pszVal);
     }
 
-    if (osVersion.size() == 0)
+    if( osVersion.empty() )
         osVersion = CPLGetXMLValue(psWFSCapabilities, "version", "1.0.0");
-    if (strcmp(osVersion.c_str(), "1.0.0") == 0)
-        bUseFeatureId = TRUE;
+    if( strcmp(osVersion.c_str(), "1.0.0") == 0 )
+    {
+        bUseFeatureId = true;
+    }
     else
     {
         /* Some servers happen to support RESULTTYPE=hits in 1.0.0, but there */
         /* is no way to advertises this */
         if (atoi(osVersion) >= 2)
-            bGetFeatureSupportHits = TRUE;  /* WFS >= 2.0.0 supports hits */
+            bGetFeatureSupportHits = true;  /* WFS >= 2.0.0 supports hits */
         else
             bGetFeatureSupportHits = DetectIfGetFeatureSupportHits(psWFSCapabilities);
-        bRequiresEnvelopeSpatialFilter = DetectRequiresEnvelopeSpatialFilter(psWFSCapabilities);
+        bRequiresEnvelopeSpatialFilter =
+            DetectRequiresEnvelopeSpatialFilter(psWFSCapabilities);
     }
 
     if ( atoi(osVersion) >= 2 )
     {
         CPLString osMaxFeatures = CPLURLGetValue(osBaseURL, "COUNT" );
         /* Ok, people are used to MAXFEATURES, so be nice to recognize it if it is used for WFS 2.0 ... */
-        if (osMaxFeatures.size() == 0 )
+        if (osMaxFeatures.empty() )
         {
             osMaxFeatures = CPLURLGetValue(osBaseURL, "MAXFEATURES");
-            if( osMaxFeatures.size() != 0 &&
+            if( !osMaxFeatures.empty() &&
                 CPLTestBool(CPLGetConfigOption("OGR_WFS_FIX_MAXFEATURES", "YES")) )
             {
                 CPLDebug("WFS", "MAXFEATURES wrongly used for WFS 2.0. Using COUNT instead");
@@ -1195,7 +1178,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
 
     DetectTransactionSupport(psWFSCapabilities);
 
-    if (bUpdate && !bTransactionSupport)
+    if( bUpdate && !bTransactionSupport )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                     "Server is read-only WFS; no WFS-T feature advertized");
@@ -1207,8 +1190,9 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
     CPLXMLNode* psFilterCap = CPLGetXMLNode(psWFSCapabilities, "Filter_Capabilities.Scalar_Capabilities");
     if (psFilterCap)
     {
-        bHasMinOperators = CPLGetXMLNode(psFilterCap, "LogicalOperators") != NULL ||
-                           CPLGetXMLNode(psFilterCap, "Logical_Operators") != NULL;
+        bHasMinOperators =
+            CPLGetXMLNode(psFilterCap, "LogicalOperators") != NULL ||
+            CPLGetXMLNode(psFilterCap, "Logical_Operators") != NULL;
         if (CPLGetXMLNode(psFilterCap, "ComparisonOperators"))
             psFilterCap = CPLGetXMLNode(psFilterCap, "ComparisonOperators");
         else if (CPLGetXMLNode(psFilterCap, "Comparison_Operators"))
@@ -1246,7 +1230,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
         }
         else
         {
-            bHasMinOperators = FALSE;
+            bHasMinOperators = false;
         }
     }
 
@@ -1260,11 +1244,9 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
         return FALSE;
     }
 
-    CPLXMLNode* psChildIter;
-
     /* Check if there are layer names whose identical except their prefix */
     std::set<CPLString> aosSetLayerNames;
-    for(psChildIter = psChild->psChild;
+    for( CPLXMLNode* psChildIter = psChild->psChild;
         psChildIter != NULL;
         psChildIter = psChildIter->psNext)
     {
@@ -1279,8 +1261,11 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                     l_pszName = pszShortName + 1;
                 if (aosSetLayerNames.find(l_pszName) != aosSetLayerNames.end())
                 {
-                    bKeepLayerNamePrefix = TRUE;
-                    CPLDebug("WFS", "At least 2 layers have names that are only distinguishable by keeping the prefix");
+                    bKeepLayerNamePrefix = true;
+                    CPLDebug(
+                        "WFS",
+                        "At least 2 layers have names that are only "
+                        "distinguishable by keeping the prefix");
                     break;
                 }
                 aosSetLayerNames.insert(l_pszName);
@@ -1289,12 +1274,12 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
     }
 
     char** papszTypenames = NULL;
-    if (osTypeName.size() != 0)
+    if (!osTypeName.empty())
         papszTypenames = CSLTokenizeStringComplex( osTypeName, ",", FALSE, FALSE );
 
-    for(psChildIter = psChild->psChild;
-        psChildIter != NULL;
-        psChildIter = psChildIter->psNext)
+    for( CPLXMLNode* psChildIter = psChild->psChild;
+         psChildIter != NULL;
+         psChildIter = psChildIter->psNext )
     {
         if (psChildIter->eType == CXT_Element &&
             strcmp(psChildIter->pszValue, "FeatureType") == 0)
@@ -1344,31 +1329,31 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                         psOutputFormatIter = psOutputFormatIter->psNext;
                     }
 
-                    if (strcmp(osVersion.c_str(), "1.1.0") == 0 && osFormats.size() > 0)
+                    if (strcmp(osVersion.c_str(), "1.1.0") == 0 && !osFormats.empty())
                     {
-                        int bFoundGML31 = FALSE;
+                        bool bFoundGML31 = false;
                         for(size_t i=0;i<osFormats.size();i++)
                         {
                             if (strstr(osFormats[i].c_str(), "3.1") != NULL)
                             {
-                                bFoundGML31 = TRUE;
+                                bFoundGML31 = true;
                                 break;
                             }
                         }
 
                         /* If we didn't find any mention to GML 3.1, then arbitrarily */
                         /* use the first output format */
-                        if (!bFoundGML31)
+                        if( !bFoundGML31 )
                             osOutputFormat = osFormats[0].c_str();
                     }
                 }
 
                 OGRSpatialReference* poSRS = NULL;
-                int bAxisOrderAlreadyInverted = FALSE;
+                bool bAxisOrderAlreadyInverted = false;
 
                 /* If a SRSNAME parameter has been encoded in the URL, use it as the SRS */
                 CPLString osSRSName = CPLURLGetValue(osBaseURL, "SRSNAME");
-                if (osSRSName.size() != 0)
+                if (!osSRSName.empty())
                 {
                     pszDefaultSRS = osSRSName.c_str();
                 }
@@ -1379,10 +1364,10 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                     if (oSRS.SetFromUserInput(pszDefaultSRS) == OGRERR_NONE)
                     {
                         poSRS = oSRS.Clone();
-                        if (bInvertAxisOrderIfLatLong &&
-                            GML_IsSRSLatLongOrder(pszDefaultSRS))
+                        if( bInvertAxisOrderIfLatLong &&
+                            GML_IsSRSLatLongOrder(pszDefaultSRS) )
                         {
-                            bAxisOrderAlreadyInverted = TRUE;
+                            bAxisOrderAlreadyInverted = true;
 
                             OGR_SRSNode *poGEOGCS =
                                             poSRS->GetAttrNode( "GEOGCS" );
@@ -1398,8 +1383,11 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
 
                 CPLXMLNode* psBBox = NULL;
                 CPLXMLNode* psLatLongBBox = NULL;
-                /* int bFoundBBox = FALSE; */
-                double dfMinX = 0, dfMinY = 0, dfMaxX = 0, dfMaxY = 0;
+                /* bool bFoundBBox = false; */
+                double dfMinX = 0.0;
+                double dfMinY = 0.0;
+                double dfMaxX = 0.0;
+                double dfMaxY = 0.0;
                 if ((psBBox = CPLGetXMLNode(psChildIter, "WGS84BoundingBox")) != NULL)
                 {
                     const char* pszLC = CPLGetXMLValue(psBBox, "LowerCorner", NULL);
@@ -1409,12 +1397,11 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                         CPLString osConcat(pszLC);
                         osConcat += " ";
                         osConcat += pszUC;
-                        char** papszTokens;
-                        papszTokens = CSLTokenizeStringComplex(
-                                            osConcat, " ,", FALSE, FALSE );
+                        char **papszTokens = CSLTokenizeStringComplex(
+                            osConcat, " ,", FALSE, FALSE );
                         if (CSLCount(papszTokens) == 4)
                         {
-                            /* bFoundBBox = TRUE; */
+                            // bFoundBBox = true;
                             dfMinX = CPLAtof(papszTokens[0]);
                             dfMinY = CPLAtof(papszTokens[1]);
                             dfMaxX = CPLAtof(papszTokens[2]);
@@ -1437,7 +1424,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                     if (pszMinX != NULL && pszMinY != NULL &&
                         pszMaxX != NULL && pszMaxY != NULL)
                     {
-                        /* bFoundBBox = TRUE; */
+                        // bFoundBBox = true;
                         dfMinX = CPLAtof(pszMinX);
                         dfMinY = CPLAtof(pszMinY);
                         dfMaxX = CPLAtof(pszMaxX);
@@ -1445,9 +1432,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                     }
                 }
 
-                char* pszCSVEscaped;
-
-                pszCSVEscaped = CPLEscapeString(l_pszName, -1, CPLES_CSV);
+                char* pszCSVEscaped = CPLEscapeString(l_pszName, -1, CPLES_CSV);
                 osLayerMetadataCSV += pszCSVEscaped;
                 CPLFree(pszCSVEscaped);
 
@@ -1468,9 +1453,9 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                 osLayerMetadataCSV += "\n";
 
                 OGRWFSLayer* poLayer = new OGRWFSLayer(
-                            this, poSRS, bAxisOrderAlreadyInverted,
-                            osBaseURL, l_pszName, pszNS, pszNSVal);
-                if (osOutputFormat.size())
+                    this, poSRS, bAxisOrderAlreadyInverted,
+                    osBaseURL, l_pszName, pszNS, pszNSVal);
+                if (!osOutputFormat.empty() )
                     poLayer->SetRequiredOutputFormat(osOutputFormat);
 
                 if( pszTitle )
@@ -1504,9 +1489,13 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                     if (poSRS->exportToProj4(&pszProj4) == OGRERR_NONE)
                     {
                         /* See http://trac.osgeo.org/gdal/ticket/4041 */
-                        int bTrustBounds =
-                            CSLFetchBoolean(papszOpenOptionsIn, "TRUST_CAPABILITIES_BOUNDS",
-                                CPLTestBool(CPLGetConfigOption("OGR_WFS_TRUST_CAPABILITIES_BOUNDS", "FALSE")));
+                        const bool bTrustBounds =
+                            CPLFetchBool(
+                                papszOpenOptionsIn,
+                                "TRUST_CAPABILITIES_BOUNDS",
+                                CPLTestBool(CPLGetConfigOption(
+                                    "OGR_WFS_TRUST_CAPABILITIES_BOUNDS",
+                                    "FALSE")));
 
                         if (((bTrustBounds || (dfMinX == -180 && dfMinY == -90 && dfMaxX == 180 && dfMaxY == 90)) &&
                             (strcmp(pszProj4, "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ") == 0 ||
@@ -1520,10 +1509,11 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                         {
                             OGRSpatialReference oWGS84;
                             oWGS84.SetWellKnownGeogCS("WGS84");
-                            OGRCoordinateTransformation* poCT;
                             CPLPushErrorHandler(CPLQuietErrorHandler);
-                            poCT = OGRCreateCoordinateTransformation(&oWGS84, poSRS);
-                            if (poCT)
+                            OGRCoordinateTransformation* poCT =
+                                OGRCreateCoordinateTransformation(&oWGS84,
+                                                                  poSRS);
+                            if( poCT )
                             {
                                 double dfULX = dfMinX;
                                 double dfULY = dfMaxY;
@@ -1539,24 +1529,24 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                                     poCT->Transform(1, &dfLRX, &dfLRY, NULL))
                                 {
                                     dfMinX = dfULX;
-                                    dfMinX = MIN(dfMinX, dfURX);
-                                    dfMinX = MIN(dfMinX, dfLLX);
-                                    dfMinX = MIN(dfMinX, dfLRX);
+                                    dfMinX = std::min(dfMinX, dfURX);
+                                    dfMinX = std::min(dfMinX, dfLLX);
+                                    dfMinX = std::min(dfMinX, dfLRX);
 
                                     dfMinY = dfULY;
-                                    dfMinY = MIN(dfMinY, dfURY);
-                                    dfMinY = MIN(dfMinY, dfLLY);
-                                    dfMinY = MIN(dfMinY, dfLRY);
+                                    dfMinY = std::min(dfMinY, dfURY);
+                                    dfMinY = std::min(dfMinY, dfLLY);
+                                    dfMinY = std::min(dfMinY, dfLRY);
 
                                     dfMaxX = dfULX;
-                                    dfMaxX = MAX(dfMaxX, dfURX);
-                                    dfMaxX = MAX(dfMaxX, dfLLX);
-                                    dfMaxX = MAX(dfMaxX, dfLRX);
+                                    dfMaxX = std::max(dfMaxX, dfURX);
+                                    dfMaxX = std::max(dfMaxX, dfLLX);
+                                    dfMaxX = std::max(dfMaxX, dfLRX);
 
                                     dfMaxY = dfULY;
-                                    dfMaxY = MAX(dfMaxY, dfURY);
-                                    dfMaxY = MAX(dfMaxY, dfLLY);
-                                    dfMaxY = MAX(dfMaxY, dfLRY);
+                                    dfMaxY = std::max(dfMaxY, dfURY);
+                                    dfMaxY = std::max(dfMaxY, dfLLY);
+                                    dfMaxY = std::max(dfMaxY, dfLRY);
 
                                     poLayer->SetExtents(dfMinX, dfMinY, dfMaxX, dfMaxY);
                                 }
@@ -1565,7 +1555,6 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
                             CPLPopErrorHandler();
                             CPLErrorReset();
                         }
-
                     }
                     CPLFree(pszProj4);
                 }
@@ -1617,7 +1606,7 @@ int OGRWFSDataSource::Open( const char * pszFilename, int bUpdateIn,
 void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                                              char* pszNS, char* pszNSVal)
 {
-    if (!bLoadMultipleLayerDefn)
+    if( !bLoadMultipleLayerDefn )
         return;
 
     if (aoSetAlreadyTriedLayers.find(pszLayerName) != aoSetAlreadyTriedLayers.end())
@@ -1754,13 +1743,13 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
 
     if (psResult == NULL)
     {
-        bLoadMultipleLayerDefn = FALSE;
+        bLoadMultipleLayerDefn = false;
         return;
     }
 
     if (strstr((const char*)psResult->pabyData, "<ServiceExceptionReport") != NULL)
     {
-        if (IsOldDeegree((const char*)psResult->pabyData))
+        if( IsOldDeegree((const char*)psResult->pabyData) )
         {
             /* just silently forgive */
         }
@@ -1770,7 +1759,7 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                     psResult->pabyData);
         }
         CPLHTTPDestroyResult(psResult);
-        bLoadMultipleLayerDefn = FALSE;
+        bLoadMultipleLayerDefn = false;
         return;
     }
 
@@ -1780,7 +1769,7 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
         CPLError(CE_Failure, CPLE_AppDefined, "Invalid XML content : %s",
                 psResult->pabyData);
         CPLHTTPDestroyResult(psResult);
-        bLoadMultipleLayerDefn = FALSE;
+        bLoadMultipleLayerDefn = false;
         return;
     }
     CPLHTTPDestroyResult(psResult);
@@ -1790,7 +1779,7 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find <Schema>");
         CPLDestroyXMLNode( psXML );
-        bLoadMultipleLayerDefn = FALSE;
+        bLoadMultipleLayerDefn = false;
         return;
     }
 
@@ -1804,18 +1793,19 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
     GMLParseXSD( osTmpFileName, aosClasses, bFullyUnderstood );
 
     int nLayersFound = 0;
-    if ((int)aosClasses.size() > 0)
+    if (!(int)aosClasses.empty())
     {
         std::vector<GMLFeatureClass*>::const_iterator oIter = aosClasses.begin();
         std::vector<GMLFeatureClass*>::const_iterator oEndIter = aosClasses.end();
         while (oIter != oEndIter)
         {
             GMLFeatureClass* poClass = *oIter;
-            oIter ++;
+            ++oIter;
 
-            OGRWFSLayer* poLayer;
+            OGRWFSLayer* poLayer = NULL;
 
-            if (bKeepLayerNamePrefix && pszNS != NULL && strchr(poClass->GetName(), ':') == NULL)
+            if( bKeepLayerNamePrefix && pszNS != NULL &&
+                strchr(poClass->GetName(), ':') == NULL )
             {
                 CPLString osWithPrefix(pszNS);
                 osWithPrefix += ":";
@@ -1834,9 +1824,9 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                     CPLXMLNode* psSchemaForLayer = CPLCloneXMLTree(psSchema);
                     CPLStripXMLNamespace( psSchemaForLayer, NULL, TRUE );
                     CPLXMLNode* psIter = psSchemaForLayer->psChild;
-                    int bHasAlreadyImportedGML = FALSE;
-                    int bFoundComplexType = FALSE;
-                    int bFoundElement = FALSE;
+                    bool bHasAlreadyImportedGML = false;
+                    bool bFoundComplexType = false;
+                    bool bFoundElement = false;
                     while(psIter != NULL)
                     {
                         CPLXMLNode* psIterNext = psIter->psNext;
@@ -1852,7 +1842,7 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                                 strcmp(l_pszName, osExpectedName2) == 0 ||
                                 strcmp(l_pszName, poLayer->GetShortName()) == 0)
                             {
-                                bFoundComplexType = TRUE;
+                                bFoundComplexType = true;
                             }
                             else
                             {
@@ -1881,7 +1871,7 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                                  (strcmp(strchr(pszType, ':') + 1, osExpectedType) == 0 ||
                                   strcmp(strchr(pszType, ':') + 1, osExpectedType2) == 0)))
                             {
-                                bFoundElement = TRUE;
+                                bFoundElement = true;
                             }
                             else if (*pszType == '\0' &&
                                      CPLGetXMLNode(psIter, "complexType") != NULL &&
@@ -1889,8 +1879,8 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                                       strcmp(l_pszName, osExpectedName2) == 0 ||
                                       strcmp(l_pszName, poLayer->GetShortName()) == 0) )
                             {
-                                bFoundElement = TRUE;
-                                bFoundComplexType = TRUE;
+                                bFoundElement = true;
+                                bFoundComplexType = true;
                             }
                             else
                             {
@@ -1903,18 +1893,20 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
                                 strcmp(CPLGetXMLValue(psIter, "namespace", ""),
                                         "http://www.opengis.net/gml") == 0)
                         {
-                            if (bHasAlreadyImportedGML)
+                            if( bHasAlreadyImportedGML )
                             {
                                 CPLRemoveXMLChild( psSchemaForLayer, psIter );
                                 CPLDestroyXMLNode(psIter);
                             }
                             else
-                                bHasAlreadyImportedGML = TRUE;
+                            {
+                                bHasAlreadyImportedGML = true;
+                            }
                         }
                         psIter = psIterNext;
                     }
 
-                    if (bFoundComplexType && bFoundElement)
+                    if( bFoundComplexType && bFoundElement )
                     {
                         OGRFeatureDefn* poSrcFDefn
                             = poLayer->ParseSchema(psSchemaForLayer);
@@ -1945,7 +1937,7 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
         CPLDebug( "WFS",
                   "Turn off loading of multiple layer definitions at a "
                   "single time");
-        bLoadMultipleLayerDefn = FALSE;
+        bLoadMultipleLayerDefn = false;
     }
 
     VSIUnlink(osTmpFileName);
@@ -1957,12 +1949,14 @@ void OGRWFSDataSource::LoadMultipleLayerDefn(const char* pszLayerName,
 /*                         SaveLayerSchema()                            */
 /************************************************************************/
 
-void OGRWFSDataSource::SaveLayerSchema(const char* pszLayerName, CPLXMLNode* psSchema)
+void OGRWFSDataSource::SaveLayerSchema( const char* pszLayerName,
+                                        CPLXMLNode* psSchema )
 {
     if (psFileXML != NULL)
     {
-        bRewriteFile = TRUE;
-        CPLXMLNode* psLayerNode = CPLCreateXMLNode(NULL, CXT_Element, "OGRWFSLayer");
+        bRewriteFile = true;
+        CPLXMLNode* psLayerNode =
+            CPLCreateXMLNode(NULL, CXT_Element, "OGRWFSLayer");
         CPLSetXMLValue(psLayerNode, "#name", pszLayerName);
         CPLAddXMLChild(psLayerNode, CPLCloneXMLTree(psSchema));
         CPLAddXMLChild(psFileXML, psLayerNode);
@@ -1973,15 +1967,17 @@ void OGRWFSDataSource::SaveLayerSchema(const char* pszLayerName, CPLXMLNode* psS
 /*                           IsOldDeegree()                             */
 /************************************************************************/
 
-int OGRWFSDataSource::IsOldDeegree(const char* pszErrorString)
+bool OGRWFSDataSource::IsOldDeegree(const char* pszErrorString)
 {
-    if (!bNeedNAMESPACE &&
-        strstr(pszErrorString, "Invalid \"TYPENAME\" parameter. No binding for prefix") != NULL)
+    if( !bNeedNAMESPACE &&
+        strstr(pszErrorString,
+               "Invalid \"TYPENAME\" parameter. "
+               "No binding for prefix") != NULL )
     {
-        bNeedNAMESPACE = TRUE;
-        return TRUE;
+        bNeedNAMESPACE = true;
+        return true;
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -2025,23 +2021,22 @@ CPLString WFS_EscapeURL(const char* pszURL)
 CPLString WFS_DecodeURL(const CPLString &osSrc)
 {
     CPLString ret;
-    char ch;
-    int ii;
-    for (size_t i=0; i<osSrc.length(); i++)
+    for( size_t i=0; i<osSrc.length(); i++ )
     {
         if (osSrc[i]=='%' && i+2 < osSrc.length())
         {
+            unsigned int ii = 0;
             sscanf(osSrc.substr(i+1,2).c_str(), "%x", &ii);
-            ch=static_cast<char>(ii);
-            ret+=ch;
-            i=i+2;
+            char ch = static_cast<char>(ii);
+            ret += ch;
+            i = i + 2;
         }
         else
         {
             ret+=osSrc[i];
         }
     }
-    return (ret);
+    return ret;
 }
 
 /************************************************************************/
@@ -2051,7 +2046,7 @@ CPLString WFS_DecodeURL(const CPLString &osSrc)
 CPLHTTPResult* OGRWFSDataSource::HTTPFetch( const char* pszURL, char** papszOptions )
 {
     char** papszNewOptions = CSLDuplicate(papszOptions);
-    if (bUseHttp10)
+    if( bUseHttp10 )
         papszNewOptions = CSLAddNameValue(papszNewOptions, "HTTP_VERSION", "1.0");
     if (papszHttpOptions)
         papszNewOptions = CSLMerge(papszNewOptions, papszHttpOptions);
@@ -2068,13 +2063,13 @@ CPLHTTPResult* OGRWFSDataSource::HTTPFetch( const char* pszURL, char** papszOpti
         // remaining bytes value curl does not like this. Retry with
         // HTTP 1.0 protocol instead that does not support chunked
         // data.
-        if (psResult->pszErrBuf &&
+        if( psResult->pszErrBuf &&
             strstr(psResult->pszErrBuf,
                    "transfer closed with outstanding read data remaining") &&
-            !bUseHttp10)
+            !bUseHttp10 )
         {
             CPLDebug("WFS", "Probably buggy remote server. Retrying with HTTP 1.0 protocol");
-            bUseHttp10 = TRUE;
+            bUseHttp10 = true;
             CPLHTTPDestroyResult(psResult);
             return HTTPFetch(pszURL, papszOptions);
         }
@@ -2159,7 +2154,7 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
             poFeature->SetField(0, osFID);
             CPL_IGNORE_RET_VAL(poMEMLayer->CreateFeature(poFeature));
             delete poFeature;
-            oIter ++;
+            ++oIter;
         }
 
         OGRLayer* poResLayer = new OGRWFSWrappedResultLayer(poMEMDS, poMEMLayer);
@@ -2191,7 +2186,7 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
             return NULL;
         }
 
-        while(*pszIter && *pszIter == ' ')
+        while(*pszIter == ' ')
             pszIter ++;
         if (!STARTS_WITH_CI(pszIter, "WHERE "))
         {
@@ -2215,19 +2210,20 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
         int nVersion = (strcmp(GetVersion(),"1.0.0") == 0) ? 100 : 110;
         swq_expr_node* poNode = (swq_expr_node*) oQuery.GetSWQExpr();
         poNode->ReplaceBetweenByGEAndLERecurse();
-        CPLString osOGCFilter = WFS_TurnSQLFilterToOGCFilter(poNode,
-                                                             NULL,
-                                                             poLayer->GetLayerDefn(),
-                                                             nVersion,
-                                                             bPropertyIsNotEqualToSupported,
-                                                             bUseFeatureId,
-                                                             bGmlObjectIdNeedsGMLPrefix,
-                                                             "",
-                                                             &bNeedsNullCheck);
+        CPLString osOGCFilter = WFS_TurnSQLFilterToOGCFilter(
+            poNode,
+            NULL,
+            poLayer->GetLayerDefn(),
+            nVersion,
+            bPropertyIsNotEqualToSupported,
+            bUseFeatureId,
+            bGmlObjectIdNeedsGMLPrefix,
+            "",
+            &bNeedsNullCheck);
         if (bNeedsNullCheck && !HasNullCheck())
             osOGCFilter = "";
 
-        if (osOGCFilter.size() == 0)
+        if (osOGCFilter.empty())
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Cannot convert WHERE clause into a OGC filter");
             return NULL;
@@ -2249,7 +2245,7 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
             delete psSelectInfo;
             return NULL;
         }
-        int iLayer;
+        int iLayer = 0;
         if( strcmp(GetVersion(),"1.0.0") != 0 &&
             psSelectInfo->table_count == 1 &&
             psSelectInfo->table_defs[0].data_source == NULL &&
@@ -2260,8 +2256,8 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
         {
             OGRWFSLayer* poSrcLayer = papoLayers[iLayer];
             std::vector<OGRWFSSortDesc> aoSortColumns;
-            int i;
-            for(i=0;i<psSelectInfo->order_specs;i++)
+            int i = 0;  // Used after for.
+            for( ; i < psSelectInfo->order_specs; i++ )
             {
                 int nFieldIndex = poSrcLayer->GetLayerDefn()->GetFieldIndex(
                                         psSelectInfo->order_defs[i].field_name);
@@ -2328,7 +2324,7 @@ OGRLayer * OGRWFSDataSource::ExecuteSQL( const char *pszSQLCommand,
             oParseOptions.bAlwaysPrefixWithTableName = FALSE;
             oParseOptions.bAllowDistinctOnGeometryField = FALSE;
             oParseOptions.bAllowDistinctOnMultipleFields = FALSE;
-            int bOK = psParseInfo != NULL;
+            const bool bOK = psParseInfo != NULL;
             DestroyParseInfo(psParseInfo);
 
             OGRLayer* poResLayer = NULL;
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
index 3246046..49c4a17 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSDriver.
@@ -32,7 +31,7 @@
 
 // g++ -fPIC -g -Wall ogr/ogrsf_frmts/wfs/*.cpp -shared -o ogr_WFS.so -Iport -Igcore -Iogr -Iogr/ogrsf_frmts -Iogr/ogrsf_frmts/gml -Iogr/ogrsf_frmts/wfs -L. -lgdal
 
-CPL_CVSID("$Id: ogrwfsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrwfsdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 extern "C" void RegisterOGRWFS();
 
@@ -121,4 +120,3 @@ void RegisterOGRWFS()
 
     GetGDALDriverManager()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
index 65f779f..7b9980f 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsfilter.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwfsfilter.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGR SQL into OGC Filter translation.
@@ -30,12 +29,12 @@
 #include "ogr_wfs.h"
 #include "ogr_p.h"
 
-CPL_CVSID("$Id: ogrwfsfilter.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrwfsfilter.cpp 36501 2016-11-25 14:09:24Z rouault $");
 
 typedef struct
 {
     int nVersion;
-    int bPropertyIsNotEqualToSupported;
+    bool bPropertyIsNotEqualToSupported;
     int bOutNeedsNullCheck;
     OGRDataSource* poDS;
     OGRFeatureDefn* poFDefn;
@@ -48,11 +47,11 @@ typedef struct
 /*                WFS_ExprDumpGmlObjectIdFilter()                       */
 /************************************************************************/
 
-static int WFS_ExprDumpGmlObjectIdFilter(CPLString& osFilter,
-                                         const swq_expr_node* poExpr,
-                                         int bUseFeatureId,
-                                         int bGmlObjectIdNeedsGMLPrefix,
-                                         int nVersion)
+static bool WFS_ExprDumpGmlObjectIdFilter( CPLString& osFilter,
+                                           const swq_expr_node* poExpr,
+                                           int bUseFeatureId,
+                                           int bGmlObjectIdNeedsGMLPrefix,
+                                           int nVersion )
 {
     if (poExpr->eNodeType == SNT_OPERATION &&
         poExpr->nOperation == SWQ_EQ &&
@@ -61,46 +60,57 @@ static int WFS_ExprDumpGmlObjectIdFilter(CPLString& osFilter,
         strcmp(poExpr->papoSubExpr[0]->string_value, "gml_id") == 0 &&
         poExpr->papoSubExpr[1]->eNodeType == SNT_CONSTANT)
     {
-        if (bUseFeatureId)
+        if( bUseFeatureId )
             osFilter += "<FeatureId fid=\"";
-        else if (nVersion >= 200)
+        else if( nVersion >= 200 )
             osFilter += "<ResourceId rid=\"";
-        else if (!bGmlObjectIdNeedsGMLPrefix)
+        else if( !bGmlObjectIdNeedsGMLPrefix )
             osFilter += "<GmlObjectId id=\"";
         else
             osFilter += "<GmlObjectId gml:id=\"";
         if( poExpr->papoSubExpr[1]->field_type == SWQ_INTEGER ||
             poExpr->papoSubExpr[1]->field_type == SWQ_INTEGER64 )
-            osFilter += CPLSPrintf(CPL_FRMT_GIB, poExpr->papoSubExpr[1]->int_value);
+        {
+            osFilter += CPLSPrintf(CPL_FRMT_GIB,
+                                   poExpr->papoSubExpr[1]->int_value);
+        }
         else if( poExpr->papoSubExpr[1]->field_type == SWQ_STRING )
         {
-            char* pszXML = CPLEscapeString(poExpr->papoSubExpr[1]->string_value, -1, CPLES_XML);
+            char* pszXML =
+                CPLEscapeString(poExpr->papoSubExpr[1]->string_value,
+                                -1, CPLES_XML);
             osFilter += pszXML;
             CPLFree(pszXML);
         }
         else
-            return FALSE;
+        {
+            return false;
+        }
         osFilter += "\"/>";
-        return TRUE;
+        return true;
     }
     else if (poExpr->eNodeType == SNT_OPERATION &&
              poExpr->nOperation == SWQ_OR &&
              poExpr->nSubExprCount == 2 )
     {
-        return WFS_ExprDumpGmlObjectIdFilter(osFilter, poExpr->papoSubExpr[0],
-                                             bUseFeatureId, bGmlObjectIdNeedsGMLPrefix, nVersion) &&
-               WFS_ExprDumpGmlObjectIdFilter(osFilter, poExpr->papoSubExpr[1],
-                                             bUseFeatureId, bGmlObjectIdNeedsGMLPrefix, nVersion);
+        return
+          WFS_ExprDumpGmlObjectIdFilter(
+              osFilter, poExpr->papoSubExpr[0],
+              bUseFeatureId, bGmlObjectIdNeedsGMLPrefix, nVersion) &&
+          WFS_ExprDumpGmlObjectIdFilter(
+              osFilter, poExpr->papoSubExpr[1],
+              bUseFeatureId, bGmlObjectIdNeedsGMLPrefix, nVersion);
     }
-    return FALSE;
+
+    return false;
 }
 
 /************************************************************************/
 /*                     WFS_ExprDumpRawLitteral()                        */
 /************************************************************************/
 
-static int WFS_ExprDumpRawLitteral(CPLString& osFilter,
-                                   const swq_expr_node* poExpr)
+static bool WFS_ExprDumpRawLitteral( CPLString& osFilter,
+                                     const swq_expr_node* poExpr )
 {
     if( poExpr->field_type == SWQ_INTEGER ||
         poExpr->field_type == SWQ_INTEGER64 )
@@ -117,14 +127,16 @@ static int WFS_ExprDumpRawLitteral(CPLString& osFilter,
     {
         OGRField sDate;
         if( !OGRParseDate(poExpr->string_value, &sDate, 0) )
-            return FALSE;
+            return false;
         char* pszDate = OGRGetXMLDateTime(&sDate);
         osFilter += pszDate;
         CPLFree(pszDate);
     }
     else
-        return FALSE;
-    return TRUE;
+    {
+        return false;
+    }
+    return true;
 }
 
 /************************************************************************/
@@ -170,15 +182,15 @@ static const char* WFS_ExprGetSRSName( const swq_expr_node* poExpr,
 /*                     WFS_ExprDumpAsOGCFilter()                        */
 /************************************************************************/
 
-static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
-                                   const swq_expr_node* poExpr,
-                                   int bExpectBinary,
-                                   ExprDumpFilterOptions* psOptions)
+static bool WFS_ExprDumpAsOGCFilter( CPLString& osFilter,
+                                     const swq_expr_node* poExpr,
+                                     int bExpectBinary,
+                                     ExprDumpFilterOptions* psOptions )
 {
     if( poExpr->eNodeType == SNT_COLUMN )
     {
         if (bExpectBinary)
-            return FALSE;
+            return false;
 
         /* Special fields not understood by server */
         if (EQUAL(poExpr->string_value, "gml_id") ||
@@ -189,14 +201,15 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
             EQUAL(poExpr->string_value, "OGR_STYLE"))
         {
             CPLDebug("WFS", "Attribute refers to a OGR special field. Cannot use server-side filtering");
-            return FALSE;
+            return false;
         }
 
         const char* pszFieldname = NULL;
-        int nIndex;
-        int bSameTable = psOptions->poFDefn != NULL &&
-                         ( poExpr->table_name == NULL ||
-                           EQUAL(poExpr->table_name, psOptions->poFDefn->GetName()) );
+        int nIndex = 0;
+        const bool bSameTable =
+            psOptions->poFDefn != NULL &&
+            ( poExpr->table_name == NULL ||
+              EQUAL(poExpr->table_name, psOptions->poFDefn->GetName()) );
         if( bSameTable )
         {
             if( (nIndex = psOptions->poFDefn->GetFieldIndex(poExpr->string_value)) >= 0 )
@@ -240,7 +253,7 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
             else
                 CPLDebug("WFS", "Field \"%s\" unknown. Cannot use server-side filtering",
                          poExpr->string_value);
-            return FALSE;
+            return false;
         }
 
         if (psOptions->nVersion >= 200)
@@ -255,55 +268,53 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
         else
             osFilter += CPLSPrintf("</%sPropertyName>", psOptions->pszNSPrefix);
 
-        return TRUE;
+        return true;
     }
 
     if( poExpr->eNodeType == SNT_CONSTANT )
     {
         if (bExpectBinary)
-            return FALSE;
+            return false;
 
         osFilter += CPLSPrintf("<%sLiteral>", psOptions->pszNSPrefix);
         if( !WFS_ExprDumpRawLitteral(osFilter, poExpr) )
-            return FALSE;
+            return false;
         osFilter += CPLSPrintf("</%sLiteral>", psOptions->pszNSPrefix);
 
-        return TRUE;
+        return true;
     }
 
     if( poExpr->eNodeType != SNT_OPERATION )
-        return FALSE; // Should not happen.
+        return false; // Should not happen.
 
     if( poExpr->nOperation == SWQ_NOT )
     {
         osFilter +=  CPLSPrintf("<%sNot>", psOptions->pszNSPrefix);
         if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], TRUE, psOptions))
-            return FALSE;
+            return false;
         osFilter +=  CPLSPrintf("</%sNot>", psOptions->pszNSPrefix);
-        return TRUE;
+        return true;
     }
 
     if( poExpr->nOperation == SWQ_LIKE )
     {
         CPLString osVal;
-        char ch;
         char firstCh = 0;
-        int i;
         if (psOptions->nVersion == 100)
             osFilter += CPLSPrintf("<%sPropertyIsLike wildCard='*' singleChar='_' escape='!'>", psOptions->pszNSPrefix);
         else
             osFilter += CPLSPrintf("<%sPropertyIsLike wildCard='*' singleChar='_' escapeChar='!'>", psOptions->pszNSPrefix);
         if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], FALSE, psOptions))
-            return FALSE;
+            return false;
         if (poExpr->papoSubExpr[1]->eNodeType != SNT_CONSTANT &&
             poExpr->papoSubExpr[1]->field_type != SWQ_STRING)
-            return FALSE;
+            return false;
         osFilter += CPLSPrintf("<%sLiteral>", psOptions->pszNSPrefix);
 
         // Escape value according to above special characters.  For URL
         // compatibility reason, we remap the OGR SQL '%' wildcard into '*'.
-        i = 0;
-        ch = poExpr->papoSubExpr[1]->string_value[i];
+        int i = 0;
+        char ch = poExpr->papoSubExpr[1]->string_value[i];
         if (ch == '\'' || ch == '"')
         {
             firstCh = ch;
@@ -332,17 +343,17 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
         CPLFree(pszXML);
         osFilter += CPLSPrintf("</%sLiteral>", psOptions->pszNSPrefix);
         osFilter += CPLSPrintf("</%sPropertyIsLike>", psOptions->pszNSPrefix);
-        return TRUE;
+        return true;
     }
 
     if( poExpr->nOperation == SWQ_ISNULL )
     {
         osFilter += CPLSPrintf("<%sPropertyIsNull>", psOptions->pszNSPrefix);
         if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], FALSE, psOptions))
-            return FALSE;
+            return false;
         osFilter += CPLSPrintf("</%sPropertyIsNull>", psOptions->pszNSPrefix);
         psOptions->bOutNeedsNullCheck = TRUE;
-        return TRUE;
+        return true;
     }
 
     if( poExpr->nOperation == SWQ_EQ ||
@@ -353,12 +364,12 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
         poExpr->nOperation == SWQ_GT )
     {
         int nOperation = poExpr->nOperation;
-        int bAddClosingNot = FALSE;
-        if (!psOptions->bPropertyIsNotEqualToSupported && nOperation == SWQ_NE)
+        bool bAddClosingNot = false;
+        if( !psOptions->bPropertyIsNotEqualToSupported && nOperation == SWQ_NE )
         {
             osFilter += CPLSPrintf("<%sNot>", psOptions->pszNSPrefix);
             nOperation = SWQ_EQ;
-            bAddClosingNot = TRUE;
+            bAddClosingNot = true;
         }
 
         const char* pszName = NULL;
@@ -377,16 +388,16 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
         osFilter += pszName;
         osFilter += ">";
         if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], FALSE, psOptions))
-            return FALSE;
+            return false;
         if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[1], FALSE, psOptions))
-            return FALSE;
+            return false;
         osFilter += "</";
         osFilter += psOptions->pszNSPrefix;
         osFilter += pszName;
         osFilter += ">";
-        if (bAddClosingNot)
+        if( bAddClosingNot )
             osFilter += CPLSPrintf("</%sNot>", psOptions->pszNSPrefix);
-        return TRUE;
+        return true;
     }
 
     if( poExpr->nOperation == SWQ_AND ||
@@ -398,14 +409,14 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
         osFilter += pszName;
         osFilter += ">";
         if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[0], TRUE, psOptions))
-            return FALSE;
+            return false;
         if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[1], TRUE, psOptions))
-            return FALSE;
+            return false;
         osFilter += "</";
         osFilter += psOptions->pszNSPrefix;
         osFilter += pszName;
         osFilter += ">";
-        return TRUE;
+        return true;
     }
 
     if( poExpr->nOperation == SWQ_CUSTOM_FUNC &&
@@ -413,7 +424,7 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
     {
         OGRSpatialReference oSRS;
         const char* pszSRSName = WFS_ExprGetSRSName( poExpr, 4, psOptions, oSRS );
-        int bAxisSwap = FALSE;
+        bool bAxisSwap = false;
 
         osFilter += "<gml:Envelope";
         if( pszSRSName )
@@ -422,25 +433,25 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
             osFilter += pszSRSName;
             osFilter += "\"";
             if( oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting() )
-                bAxisSwap = TRUE;
+                bAxisSwap = true;
         }
         osFilter += ">";
         osFilter += "<gml:lowerCorner>";
-        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 1 : 0]))
-            return FALSE;
+        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[bAxisSwap ? 1 : 0]))
+            return false;
         osFilter += " ";
-        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 0 : 1]))
-            return FALSE;
+        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[bAxisSwap ? 0 : 1]))
+            return false;
         osFilter += "</gml:lowerCorner>";
         osFilter += "<gml:upperCorner>";
-        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 3 : 2]))
-            return FALSE;
+        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[bAxisSwap ? 3 : 2]))
+            return false;
         osFilter += " ";
-        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[(bAxisSwap) ? 2 : 3]))
-            return FALSE;
+        if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[bAxisSwap ? 2 : 3]))
+            return false;
         osFilter += "</gml:upperCorner>";
         osFilter += "</gml:Envelope>";
-        return TRUE;
+        return true;
     }
 
     if( poExpr->nOperation == SWQ_CUSTOM_FUNC &&
@@ -480,7 +491,7 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
         CSLDestroy(papszOptions);
         delete poGeom;
         CPLFree(pszGML);
-        return TRUE;
+        return true;
     }
 
     if( poExpr->nOperation == SWQ_CUSTOM_FUNC )
@@ -498,7 +509,7 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
             EQUAL(poExpr->string_value, "ST_Beyond") ? "Beyond" :
             NULL;
         if( pszName == NULL )
-            return FALSE;
+            return false;
         osFilter += "<";
         osFilter += psOptions->pszNSPrefix;
         osFilter += pszName;
@@ -516,8 +527,10 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
                                 EQUAL(poExpr->papoSubExpr[0]->table_name, psOptions->poFDefn->GetName()) );
                 if( bSameTable )
                 {
-                    int nIndex;
-                    if( (nIndex = psOptions->poFDefn->GetGeomFieldIndex(poExpr->papoSubExpr[0]->string_value)) >= 0 )
+                    const int nIndex =
+                        psOptions->poFDefn->
+                        GetGeomFieldIndex(poExpr->papoSubExpr[0]->string_value);
+                    if( nIndex  >= 0 )
                     {
                         psOptions->poSRS = psOptions->poFDefn->GetGeomFieldDefn(nIndex)->GetSpatialRef();
                     }
@@ -528,34 +541,38 @@ static int WFS_ExprDumpAsOGCFilter(CPLString& osFilter,
                     if( poLayer )
                     {
                         OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
-                        int nIndex;
-                        if( (nIndex = poFDefn->GetGeomFieldIndex(poExpr->papoSubExpr[0]->string_value)) >= 0 )
+                        const int nIndex =
+                            poFDefn->GetGeomFieldIndex(
+                                poExpr->papoSubExpr[0]->string_value);
+                        if( nIndex >= 0 )
                         {
                             psOptions->poSRS = poFDefn->GetGeomFieldDefn(nIndex)->GetSpatialRef();
                         }
                     }
                 }
             }
-            int bRet = WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[i], FALSE, psOptions);
+            const bool bRet =
+                WFS_ExprDumpAsOGCFilter(osFilter, poExpr->papoSubExpr[i],
+                                        FALSE, psOptions);
             psOptions->poSRS = NULL;
             if( !bRet )
-                return FALSE;
+                return false;
         }
         if( poExpr->nSubExprCount > 2 )
         {
             osFilter += CPLSPrintf("<%sDistance unit=\"m\">", psOptions->pszNSPrefix);
             if (!WFS_ExprDumpRawLitteral(osFilter, poExpr->papoSubExpr[2]) )
-                return FALSE;
+                return false;
             osFilter += CPLSPrintf("</%sDistance>", psOptions->pszNSPrefix);
         }
         osFilter += "</";
         osFilter += psOptions->pszNSPrefix;
         osFilter += pszName;
         osFilter += ">";
-        return TRUE;
+        return true;
     }
 
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -580,7 +597,8 @@ CPLString WFS_TurnSQLFilterToOGCFilter( const swq_expr_node* poExpr,
     {
         ExprDumpFilterOptions sOptions;
         sOptions.nVersion = nVersion;
-        sOptions.bPropertyIsNotEqualToSupported = bPropertyIsNotEqualToSupported;
+        sOptions.bPropertyIsNotEqualToSupported =
+            CPL_TO_BOOL(bPropertyIsNotEqualToSupported);
         sOptions.bOutNeedsNullCheck = FALSE;
         sOptions.poDS = poDS;
         sOptions.poFDefn = poFDefn;
@@ -588,7 +606,7 @@ CPLString WFS_TurnSQLFilterToOGCFilter( const swq_expr_node* poExpr,
         sOptions.poSRS = NULL;
         sOptions.pszNSPrefix = pszNSPrefix;
         osFilter = "";
-        if (!WFS_ExprDumpAsOGCFilter(osFilter, poExpr, TRUE, &sOptions))
+        if( !WFS_ExprDumpAsOGCFilter(osFilter, poExpr, TRUE, &sOptions) )
             osFilter = "";
         /*else
             CPLDebug("WFS", "Filter %s", osFilter.c_str());*/
@@ -627,7 +645,7 @@ static swq_field_type OGRWFSSpatialBooleanPredicateChecker( swq_expr_node *op,
 /*                           OGRWFSCheckSRIDArg()                       */
 /************************************************************************/
 
-static int OGRWFSCheckSRIDArg( swq_expr_node *op, int iSubArgIndex )
+static bool OGRWFSCheckSRIDArg( swq_expr_node *op, int iSubArgIndex )
 {
     if( op->papoSubExpr[iSubArgIndex]->field_type == SWQ_INTEGER )
     {
@@ -636,7 +654,7 @@ static int OGRWFSCheckSRIDArg( swq_expr_node *op, int iSubArgIndex )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Wrong value for argument %d of %s",
                      iSubArgIndex + 1, op->string_value);
-            return FALSE;
+            return false;
         }
     }
     else if( op->papoSubExpr[iSubArgIndex]->field_type == SWQ_STRING )
@@ -646,16 +664,16 @@ static int OGRWFSCheckSRIDArg( swq_expr_node *op, int iSubArgIndex )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Wrong value for argument %d of %s",
                      iSubArgIndex + 1, op->string_value);
-            return FALSE;
+            return false;
         }
     }
     else
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Wrong field type for argument %d of %s",
                  iSubArgIndex + 1, op->string_value);
-        return FALSE;
+        return false;
     }
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -767,7 +785,7 @@ class OGRWFSCustomFuncRegistrar: public swq_custom_func_registrar
 {
     public:
         OGRWFSCustomFuncRegistrar() {};
-        virtual const swq_operation *GetOperator( const char * ) ;
+        virtual const swq_operation *GetOperator( const char * ) override ;
 };
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp b/ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp
index 2b4d76f..7cf2491 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfsjoinlayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwfsjoinlayer.cpp 32983 2016-01-14 18:32:10Z goatbar $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSJoinLayer class.
@@ -30,35 +29,33 @@
 #include "ogr_wfs.h"
 #include "../../frmts/wms/md5.h"
 
-CPL_CVSID("$Id: ogrwfsjoinlayer.cpp 32983 2016-01-14 18:32:10Z goatbar $");
+CPL_CVSID("$Id: ogrwfsjoinlayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                          OGRWFSJoinLayer()                           */
 /************************************************************************/
 
-OGRWFSJoinLayer::OGRWFSJoinLayer(OGRWFSDataSource* poDSIn,
-                                 const swq_select* psSelectInfo,
-                                 const CPLString& osGlobalFilterIn)
+OGRWFSJoinLayer::OGRWFSJoinLayer( OGRWFSDataSource* poDSIn,
+                                  const swq_select* psSelectInfo,
+                                  const CPLString& osGlobalFilterIn ) :
+    poDS(poDSIn),
+    poFeatureDefn(NULL),
+    osGlobalFilter(osGlobalFilterIn),
+    bDistinct(psSelectInfo->query_mode == SWQM_DISTINCT_LIST),
+    poBaseDS(NULL),
+    poBaseLayer(NULL),
+    bReloadNeeded(false),
+    bHasFetched(false),
+    bPagingActive(false),
+    nPagingStartIndex(0),
+    nFeatureRead(0),
+    nFeatureCountRequested(0)
 {
-    this->poDS = poDSIn;
-    this->osGlobalFilter = osGlobalFilterIn;
-    poFeatureDefn = NULL;
-    bPagingActive = FALSE;
-    nPagingStartIndex = 0;
-    nFeatureRead = 0;
-    nFeatureCountRequested = 0;
-    poBaseDS = NULL;
-    poBaseLayer = NULL;
-    bReloadNeeded = FALSE;
-    bHasFetched = FALSE;
-    bDistinct = (psSelectInfo->query_mode == SWQM_DISTINCT_LIST);
-
     CPLString osName("join_");
-    CPLString osLayerName;
-    osLayerName = psSelectInfo->table_defs[0].table_name;
+    CPLString osLayerName = psSelectInfo->table_defs[0].table_name;
     apoLayers.push_back((OGRWFSLayer*)poDS->GetLayerByName(osLayerName));
     osName += osLayerName;
-    for(int i=0;i<psSelectInfo->join_count;i++)
+    for( int i = 0; i < psSelectInfo->join_count; i++ )
     {
         osName += "_";
         osLayerName = psSelectInfo->table_defs[
@@ -68,7 +65,7 @@ OGRWFSJoinLayer::OGRWFSJoinLayer(OGRWFSDataSource* poDSIn,
     }
 
     osFeatureTypes = "(";
-    for(int i=0;i<(int)apoLayers.size();i++)
+    for( int i = 0; i < (int)apoLayers.size(); i++ )
     {
         if( i > 0 )
             osFeatureTypes += ",";
@@ -85,7 +82,7 @@ OGRWFSJoinLayer::OGRWFSJoinLayer(OGRWFSDataSource* poDSIn,
     for( int i = 0; i < psSelectInfo->result_columns; i++ )
     {
         swq_col_def *def = psSelectInfo->column_defs + i;
-        int table_index;
+        int table_index = 0;
         if( def->table_index >= 0 )
             table_index = def->table_index;
         else
@@ -154,7 +151,7 @@ OGRWFSJoinLayer::OGRWFSJoinLayer(OGRWFSDataSource* poDSIn,
         /* Make sure to have the right case */
         const char* pszFieldName = apoLayers[0]->GetLayerDefn()->
             GetFieldDefn(nFieldIndex)->GetNameRef();
-        if( osSortBy.size() )
+        if( !osSortBy.empty() )
             osSortBy += ",";
         osSortBy += pszFieldName;
         if( !psSelectInfo->order_defs[i].ascending_flag )
@@ -174,8 +171,8 @@ OGRWFSJoinLayer::OGRWFSJoinLayer(OGRWFSDataSource* poDSIn,
             psGlobalSchema = NULL;
             break;
         }
-        CPLXMLNode* psIter;
-        for(psIter = psSchema->psChild; psIter != NULL; psIter = psIter->psNext )
+        CPLXMLNode* psIter = psSchema->psChild;  // Used after for.
+        for( ; psIter != NULL; psIter = psIter->psNext )
         {
             if( psIter->eType == CXT_Element )
                 break;
@@ -266,7 +263,7 @@ OGRWFSJoinLayer* OGRWFSJoinLayer::Build(OGRWFSDataSource* poDS,
     {
         OGRWFSRemoveReferenceToTableAlias(psSelectInfo->join_defs[i].poExpr,
                                           psSelectInfo);
-        int bOutNeedsNullCheck;
+        int bOutNeedsNullCheck = FALSE;
         CPLString osFilter = WFS_TurnSQLFilterToOGCFilter(
                                       psSelectInfo->join_defs[i].poExpr,
                                       poDS,
@@ -277,7 +274,7 @@ OGRWFSJoinLayer* OGRWFSJoinLayer::Build(OGRWFSDataSource* poDS,
                                       FALSE, /* bGmlObjectIdNeedsGMLPrefix */
                                       "",
                                       &bOutNeedsNullCheck);
-        if( osFilter.size() == 0 )
+        if( osFilter.empty() )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Unsupported JOIN clause");
@@ -289,7 +286,7 @@ OGRWFSJoinLayer* OGRWFSJoinLayer::Build(OGRWFSDataSource* poDS,
     {
         OGRWFSRemoveReferenceToTableAlias(psSelectInfo->where_expr,
                                           psSelectInfo);
-        int bOutNeedsNullCheck;
+        int bOutNeedsNullCheck = FALSE;
         CPLString osFilter = WFS_TurnSQLFilterToOGCFilter(
                                       psSelectInfo->where_expr,
                                       poDS,
@@ -300,7 +297,7 @@ OGRWFSJoinLayer* OGRWFSJoinLayer::Build(OGRWFSDataSource* poDS,
                                       FALSE, /* bGmlObjectIdNeedsGMLPrefix */
                                       "",
                                       &bOutNeedsNullCheck);
-        if( osFilter.size() == 0 )
+        if( osFilter.empty() )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Unsupported WHERE clause");
@@ -323,18 +320,18 @@ OGRWFSJoinLayer* OGRWFSJoinLayer::Build(OGRWFSDataSource* poDS,
 
 void OGRWFSJoinLayer::ResetReading()
 {
-    if (bPagingActive)
-        bReloadNeeded = TRUE;
+    if( bPagingActive )
+        bReloadNeeded = true;
     nPagingStartIndex = 0;
     nFeatureRead = 0;
     nFeatureCountRequested = 0;
-    if (bReloadNeeded)
+    if( bReloadNeeded )
     {
         GDALClose(poBaseDS);
         poBaseDS = NULL;
         poBaseLayer = NULL;
-        bHasFetched = FALSE;
-        bReloadNeeded = FALSE;
+        bHasFetched = false;
+        bReloadNeeded = false;
     }
     if (poBaseLayer)
         poBaseLayer->ResetReading();
@@ -355,14 +352,14 @@ CPLString OGRWFSJoinLayer::MakeGetFeatureURL(int bRequestHits)
 
     int nRequestMaxFeatures = 0;
     if (poDS->IsPagingAllowed() && !bRequestHits &&
-        CPLURLGetValue(osURL, "COUNT").size() == 0 )
+        CPLURLGetValue(osURL, "COUNT").empty() )
     {
         osURL = CPLURLAddKVP(osURL, "STARTINDEX",
             CPLSPrintf("%d", nPagingStartIndex +
                                 poDS->GetBaseStartIndex()));
         nRequestMaxFeatures = poDS->GetPageSize();
         nFeatureCountRequested = nRequestMaxFeatures;
-        bPagingActive = TRUE;
+        bPagingActive = true;
     }
 
     if (nRequestMaxFeatures)
@@ -402,7 +399,7 @@ CPLString OGRWFSJoinLayer::MakeGetFeatureURL(int bRequestHits)
     {
         osURL = CPLURLAddKVP(osURL, "RESULTTYPE", "hits");
     }
-    else if( osSortBy.size() )
+    else if( !osSortBy.empty() )
     {
         osURL = CPLURLAddKVP(osURL, "SORTBY", WFS_EscapeURL(osSortBy));
     }
@@ -445,7 +442,7 @@ GDALDataset* OGRWFSJoinLayer::FetchGetFeature()
                            apszOpenOptions, NULL);
         if (poGML_DS)
         {
-            //bStreamingDS = TRUE;
+            // bStreamingDS = true;
             return poGML_DS;
         }
 
@@ -473,7 +470,7 @@ GDALDataset* OGRWFSJoinLayer::FetchGetFeature()
         }
     }
 
-    //bStreamingDS = FALSE;
+    // bStreamingDS = false;
     psResult = poDS->HTTPFetch( osURL, NULL);
     if (psResult == NULL)
     {
@@ -509,9 +506,8 @@ GDALDataset* OGRWFSJoinLayer::FetchGetFeature()
 
     CPLHTTPDestroyResult(psResult);
 
-    OGRDataSource* l_poDS;
-
-    l_poDS = (OGRDataSource*) OGROpen(osTmpFileName, FALSE, NULL);
+    OGRDataSource* l_poDS =
+        (OGRDataSource*) OGROpen(osTmpFileName, FALSE, NULL);
     if (l_poDS == NULL)
     {
         if( strstr((const char*)pabyData, "<wfs:FeatureCollection") == NULL &&
@@ -543,22 +539,23 @@ OGRFeature* OGRWFSJoinLayer::GetNextFeature()
 {
     while( true )
     {
-        if (bPagingActive && nFeatureRead == nPagingStartIndex + nFeatureCountRequested)
+        if( bPagingActive &&
+            nFeatureRead == nPagingStartIndex + nFeatureCountRequested )
         {
-            bReloadNeeded = TRUE;
+            bReloadNeeded = true;
             nPagingStartIndex = nFeatureRead;
         }
-        if (bReloadNeeded)
+        if( bReloadNeeded )
         {
             GDALClose(poBaseDS);
             poBaseDS = NULL;
             poBaseLayer = NULL;
-            bHasFetched = FALSE;
-            bReloadNeeded = FALSE;
+            bHasFetched = false;
+            bReloadNeeded = false;
         }
-        if (poBaseDS == NULL && !bHasFetched)
+        if( poBaseDS == NULL && !bHasFetched )
         {
-            bHasFetched = TRUE;
+            bHasFetched = true;
             poBaseDS = FetchGetFeature();
             if (poBaseDS)
             {
@@ -583,7 +580,7 @@ OGRFeature* OGRWFSJoinLayer::GetNextFeature()
         for(int i=0;i<(int)aoSrcFieldNames.size();i++)
         {
             int iSrcField = poSrcFeature->GetFieldIndex(aoSrcFieldNames[i]);
-            if( iSrcField >= 0 && poSrcFeature->IsFieldSet(iSrcField) )
+            if( iSrcField >= 0 && poSrcFeature->IsFieldSetAndNotNull(iSrcField) )
             {
                 OGRFieldType eType = poFeatureDefn->GetFieldDefn(i)->GetType();
                 if( eType == poSrcFeature->GetFieldDefnRef(iSrcField)->GetType() )
@@ -744,16 +741,14 @@ GIntBig OGRWFSJoinLayer::ExecuteGetFeatureResultTypeHits()
 
 GIntBig OGRWFSJoinLayer::GetFeatureCount( int bForce )
 {
-    GIntBig nFeatures;
-
     if( !bDistinct )
     {
-        nFeatures = ExecuteGetFeatureResultTypeHits();
+        const GIntBig nFeatures = ExecuteGetFeatureResultTypeHits();
         if (nFeatures >= 0)
             return nFeatures;
     }
 
-    nFeatures = OGRLayer::GetFeatureCount(bForce);
+    const GIntBig nFeatures = OGRLayer::GetFeatureCount(bForce);
     return nFeatures;
 }
 
diff --git a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
index a070fae..953f7f6 100644
--- a/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
+++ b/ogr/ogrsf_frmts/wfs/ogrwfslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrwfslayer.cpp 36904 2016-12-16 10:09:27Z rouault $
  *
  * Project:  WFS Translator
  * Purpose:  Implements OGRWFSLayer class.
@@ -34,8 +33,7 @@
 #include "cpl_http.h"
 #include "parsexsd.h"
 
-CPL_CVSID("$Id: ogrwfslayer.cpp 36904 2016-12-16 10:09:27Z rouault $");
-
+CPL_CVSID("$Id: ogrwfslayer.cpp 37371 2017-02-13 11:41:59Z rouault $");
 
 /************************************************************************/
 /*                      OGRWFSRecursiveUnlink()                         */
@@ -44,12 +42,9 @@ CPL_CVSID("$Id: ogrwfslayer.cpp 36904 2016-12-16 10:09:27Z rouault $");
 void OGRWFSRecursiveUnlink( const char *pszName )
 
 {
-    char **papszFileList;
-    int i;
-
-    papszFileList = VSIReadDir( pszName );
+    char **papszFileList = VSIReadDir( pszName );
 
-    for( i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
+    for( int i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
     {
         VSIStatBufL  sStatBuf;
 
@@ -87,46 +82,41 @@ OGRWFSLayer::OGRWFSLayer( OGRWFSDataSource* poDSIn,
                           const char* pszBaseURLIn,
                           const char* pszNameIn,
                           const char* pszNSIn,
-                          const char* pszNSValIn )
-
+                          const char* pszNSValIn ) :
+    poDS(poDSIn),
+    poFeatureDefn(NULL),
+    bGotApproximateLayerDefn(false),
+    poGMLFeatureClass(NULL),
+    bAxisOrderAlreadyInverted(bAxisOrderAlreadyInvertedIn),
+    poSRS(poSRSIn),
+    pszBaseURL(CPLStrdup(pszBaseURLIn)),
+    pszName(CPLStrdup(pszNameIn)),
+    pszNS(pszNSIn ? CPLStrdup(pszNSIn) : NULL),
+    pszNSVal(pszNSValIn ? CPLStrdup(pszNSValIn) : NULL),
+    bStreamingDS(false),
+    poBaseDS(NULL),
+    poBaseLayer(NULL),
+    bHasFetched(false),
+    bReloadNeeded(false),
+    eGeomType(wkbUnknown),
+    nFeatures(-1),
+    bCountFeaturesInGetNextFeature(false),
+    dfMinX(0.0),
+    dfMinY(0.0),
+    dfMaxX(0.0),
+    dfMaxY(0.0),
+    bHasExtents(false),
+    poFetchedFilterGeom(NULL),
+    nExpectedInserts(0),
+    bInTransaction(false),
+    bUseFeatureIdAtLayerLevel(false),
+    bPagingActive(false),
+    nPagingStartIndex(0),
+    nFeatureRead(0),
+    nFeatureCountRequested(0),
+    pszRequiredOutputFormat(NULL)
 {
-    this->poDS = poDSIn;
-    this->poSRS = poSRSIn;
-    this->bAxisOrderAlreadyInverted = bAxisOrderAlreadyInvertedIn;
-    this->pszBaseURL = CPLStrdup(pszBaseURLIn);
-    this->pszName = CPLStrdup(pszNameIn);
-    this->pszNS = pszNSIn ? CPLStrdup(pszNSIn) : NULL;
-    this->pszNSVal = pszNSValIn ? CPLStrdup(pszNSValIn) : NULL;
-
     SetDescription( pszName );
-
-    poFeatureDefn = NULL;
-    poGMLFeatureClass = NULL;
-    bGotApproximateLayerDefn = FALSE;
-
-    bStreamingDS = FALSE;
-    poBaseDS = NULL;
-    poBaseLayer = NULL;
-    bReloadNeeded = FALSE;
-    bHasFetched = FALSE;
-    eGeomType = wkbUnknown;
-    nFeatures = -1;
-    bCountFeaturesInGetNextFeature = FALSE;
-
-    dfMinX = dfMinY = dfMaxX = dfMaxY = 0;
-    bHasExtents = FALSE;
-    poFetchedFilterGeom = NULL;
-
-    nExpectedInserts = 0;
-    bInTransaction = FALSE;
-    bUseFeatureIdAtLayerLevel = FALSE;
-
-    bPagingActive = FALSE;
-    nPagingStartIndex = 0;
-    nFeatureRead = 0;
-    nFeatureCountRequested = 0;
-
-    pszRequiredOutputFormat = NULL;
 }
 
 /************************************************************************/
@@ -160,13 +150,13 @@ OGRWFSLayer* OGRWFSLayer::Clone()
 OGRWFSLayer::~OGRWFSLayer()
 
 {
-    if (bInTransaction)
+    if( bInTransaction )
         CommitTransaction();
 
     if( poSRS != NULL )
         poSRS->Release();
 
-    if (poFeatureDefn != NULL)
+    if( poFeatureDefn != NULL )
         poFeatureDefn->Release();
     delete poGMLFeatureClass;
 
@@ -235,7 +225,7 @@ OGRFeatureDefn* OGRWFSLayer::DescribeFeatureType()
 
     if (strstr((const char*)psResult->pabyData, "<ServiceExceptionReport") != NULL)
     {
-        if (poDS->IsOldDeegree((const char*)psResult->pabyData))
+        if( poDS->IsOldDeegree((const char*)psResult->pabyData) )
         {
             CPLHTTPDestroyResult(psResult);
             return DescribeFeatureType();
@@ -302,7 +292,7 @@ OGRFeatureDefn* OGRWFSLayer::ParseSchema(CPLXMLNode* psSchema)
         while (oIter != oEndIter)
         {
             GMLFeatureClass* poClass = *oIter;
-            oIter ++;
+            ++oIter;
             delete poClass;
         }
     }
@@ -317,7 +307,7 @@ OGRFeatureDefn* OGRWFSLayer::ParseSchema(CPLXMLNode* psSchema)
 
 OGRFeatureDefn* OGRWFSLayer::BuildLayerDefnFromFeatureClass(GMLFeatureClass* poClass)
 {
-    this->poGMLFeatureClass = poClass;
+    poGMLFeatureClass = poClass;
 
     OGRFeatureDefn* poFDefn = new OGRFeatureDefn( pszName );
     poFDefn->SetGeomType(wkbNone);
@@ -428,7 +418,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
                                 poDS->GetBaseStartIndex()));
         nRequestMaxFeatures = poDS->GetPageSize();
         nFeatureCountRequested = nRequestMaxFeatures;
-        bPagingActive = TRUE;
+        bPagingActive = true;
     }
 
     if (nRequestMaxFeatures)
@@ -454,7 +444,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
 
     CPLString osGeomFilter;
 
-    if (m_poFilterGeom != NULL && osGeometryColumnName.size() > 0)
+    if (m_poFilterGeom != NULL && !osGeometryColumnName.empty())
     {
         OGREnvelope oEnvelope;
         m_poFilterGeom->getEnvelope(&oEnvelope);
@@ -482,7 +472,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
             osGeomFilter += "<gml:Envelope";
 
             CPLString osSRSName = CPLURLGetValue(pszBaseURL, "SRSNAME");
-            if( osSRSName.size() )
+            if( !osSRSName.empty() )
             {
                 osGeomFilter += " srsName=\"";
                 osGeomFilter += osSRSName;
@@ -537,7 +527,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
         osGeomFilter += "</BBOX>";
     }
 
-    if (osGeomFilter.size() != 0 || osWFSWhere.size() != 0)
+    if (!osGeomFilter.empty() || !osWFSWhere.empty())
     {
         CPLString osFilter;
         if (atoi(poDS->GetVersion()) >= 2)
@@ -556,11 +546,11 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
             osFilter += " xmlns:gml=\"http://www.opengis.net/gml/3.2\">";
         else
             osFilter += " xmlns:gml=\"http://www.opengis.net/gml\">";
-        if (osGeomFilter.size() != 0 && osWFSWhere.size() != 0)
+        if (!osGeomFilter.empty() && !osWFSWhere.empty())
             osFilter += "<And>";
         osFilter += osWFSWhere;
         osFilter += osGeomFilter;
-        if (osGeomFilter.size() != 0 && osWFSWhere.size() != 0)
+        if (!osGeomFilter.empty() && !osWFSWhere.empty())
             osFilter += "</And>";
         osFilter += "</Filter>";
 
@@ -571,7 +561,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
     {
         osURL = CPLURLAddKVP(osURL, "RESULTTYPE", "hits");
     }
-    else if (aoSortColumns.size() != 0)
+    else if (!aoSortColumns.empty())
     {
         CPLString osSortBy;
         for( int i=0; i < (int)aoSortColumns.size(); i++)
@@ -595,7 +585,7 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
     const char* pszPropertyName = osPropertyName.c_str();
     if (pszPropertyName[0] == 0 && poFeatureDefn != NULL)
     {
-        int bHasIgnoredField = FALSE;
+        bool bHasIgnoredField = false;
         osPropertyName.clear();
         for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
         {
@@ -605,30 +595,30 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
             }
             else if (poFeatureDefn->GetFieldDefn(iField)->IsIgnored())
             {
-                bHasIgnoredField = TRUE;
+                bHasIgnoredField = true;
             }
             else
             {
-                if (osPropertyName.size() != 0)
+                if (!osPropertyName.empty())
                     osPropertyName += ",";
                 osPropertyName += poFeatureDefn->GetFieldDefn(iField)->GetNameRef();
             }
         }
-        if (osGeometryColumnName.size() != 0)
+        if (!osGeometryColumnName.empty())
         {
             if (poFeatureDefn->IsGeometryIgnored())
             {
-                bHasIgnoredField = TRUE;
+                bHasIgnoredField = true;
             }
             else
             {
-                if (osPropertyName.size() != 0)
+                if (!osPropertyName.empty())
                     osPropertyName += ",";
                 osPropertyName += osGeometryColumnName;
             }
         }
 
-        if (bHasIgnoredField && osPropertyName.size())
+        if( bHasIgnoredField && !osPropertyName.empty() )
         {
             osPropertyName = "(" + osPropertyName + ")";
             osURL = CPLURLAddKVP(osURL, "PROPERTYNAME", WFS_EscapeURL(osPropertyName));
@@ -638,7 +628,6 @@ CPLString OGRWFSLayer::MakeGetFeatureURL(int nRequestMaxFeatures, int bRequestHi
     return osURL;
 }
 
-
 /************************************************************************/
 /*               OGRWFSFetchContentDispositionFilename()                */
 /************************************************************************/
@@ -672,41 +661,41 @@ static const char* OGRWFSFetchContentDispositionFilename(char** papszHeaders)
 /*                  MustRetryIfNonCompliantServer()                     */
 /************************************************************************/
 
-int OGRWFSLayer::MustRetryIfNonCompliantServer(const char* pszServerAnswer)
+bool OGRWFSLayer::MustRetryIfNonCompliantServer( const char* pszServerAnswer )
 {
-    int bRetry = FALSE;
+    bool bRetry = false;
 
     /* Deegree server does not support PropertyIsNotEqualTo */
     /* We have to turn it into <Not><PropertyIsEqualTo> */
-    if (osWFSWhere.size() != 0 && poDS->PropertyIsNotEqualToSupported() &&
+    if (!osWFSWhere.empty() && poDS->PropertyIsNotEqualToSupported() &&
         strstr(pszServerAnswer, "Unknown comparison operation: 'PropertyIsNotEqualTo'") != NULL)
     {
         poDS->SetPropertyIsNotEqualToUnSupported();
-        bRetry = TRUE;
+        bRetry = true;
     }
 
     /* Deegree server requires the gml: prefix in GmlObjectId element, but ESRI */
     /* doesn't like it at all ! Other servers don't care... */
-    if (osWFSWhere.size() != 0 && !poDS->DoesGmlObjectIdNeedGMLPrefix() &&
+    if (!osWFSWhere.empty() && !poDS->DoesGmlObjectIdNeedGMLPrefix() &&
         strstr(pszServerAnswer, "<GmlObjectId> requires 'gml:id'-attribute!") != NULL)
     {
         poDS->SetGmlObjectIdNeedsGMLPrefix();
-        bRetry = TRUE;
+        bRetry = true;
     }
 
     /* GeoServer can return the error 'Only FeatureIds are supported when encoding id filters to SDE' */
-    if (osWFSWhere.size() != 0 && !bUseFeatureIdAtLayerLevel &&
-        strstr(pszServerAnswer, "Only FeatureIds are supported") != NULL)
+    if( !osWFSWhere.empty() && !bUseFeatureIdAtLayerLevel &&
+        strstr(pszServerAnswer, "Only FeatureIds are supported") != NULL )
     {
-        bUseFeatureIdAtLayerLevel = TRUE;
-        bRetry = TRUE;
+        bUseFeatureIdAtLayerLevel = true;
+        bRetry = true;
     }
 
-    if (bRetry)
+    if( bRetry )
     {
         SetAttributeFilter(osSQLWhere);
-        bHasFetched = TRUE;
-        bReloadNeeded = FALSE;
+        bHasFetched = true;
+        bReloadNeeded = false;
     }
 
     return bRetry;
@@ -731,7 +720,7 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
     CPLString osXSDFileName = CPLSPrintf("/vsimem/tempwfs_%p/file.xsd", this);
     VSIStatBufL sBuf;
     if (CPLTestBool(CPLGetConfigOption("OGR_WFS_USE_STREAMING", "YES")) &&
-        (osOutputFormat.size() == 0 || osOutputFormat.ifind("GML") != std::string::npos) &&
+        (osOutputFormat.empty() || osOutputFormat.ifind("GML") != std::string::npos) &&
         VSIStatL(osXSDFileName, &sBuf) == 0 && GDALGetDriverByName("GML") != NULL)
     {
         const char* pszStreamingName = CPLSPrintf("/vsicurl_streaming/%s",
@@ -769,9 +758,9 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         GDALDataset* poGML_DS = (GDALDataset*)
                 GDALOpenEx(pszStreamingName, GDAL_OF_VECTOR, apszAllowedDrivers,
                            apszOpenOptions, NULL);
-        if (poGML_DS)
+        if( poGML_DS )
         {
-            bStreamingDS = TRUE;
+            bStreamingDS = true;
             return poGML_DS;
         }
 
@@ -789,25 +778,26 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
 
         if (nRead != 0)
         {
-            if (MustRetryIfNonCompliantServer(szBuffer))
+            if( MustRetryIfNonCompliantServer(szBuffer) )
                 return FetchGetFeature(nRequestMaxFeatures);
 
             if (strstr(szBuffer, "<ServiceExceptionReport") != NULL ||
                 strstr(szBuffer, "<ows:ExceptionReport") != NULL)
             {
-                if (poDS->IsOldDeegree(szBuffer))
+                if( poDS->IsOldDeegree(szBuffer) )
                 {
                     return FetchGetFeature(nRequestMaxFeatures);
                 }
 
-                CPLError(CE_Failure, CPLE_AppDefined, "Error returned by server : %s",
-                            szBuffer);
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "Error returned by server : %s",
+                         szBuffer);
                 return NULL;
             }
         }
     }
 
-    bStreamingDS = FALSE;
+    bStreamingDS = false;
     psResult = poDS->HTTPFetch( osURL, NULL);
     if (psResult == NULL)
     {
@@ -823,17 +813,16 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
 
     GByte *pabyData = psResult->pabyData;
     int    nDataLen = psResult->nDataLen;
-    int bIsMultiPart = FALSE;
+    bool bIsMultiPart = false;
     const char* pszAttachmentFilename = NULL;
 
     if(strstr(pszContentType,"multipart")
         && CPLHTTPParseMultipartMime(psResult) )
     {
-        int i;
-        bIsMultiPart = TRUE;
+        bIsMultiPart = true;
         OGRWFSRecursiveUnlink(osTmpDirName);
         VSIMkdir(osTmpDirName, 0);
-        for(i=0;i<psResult->nMimePartCount;i++)
+        for( int i = 0; i < psResult->nMimePartCount; i++ )
         {
             CPLString osTmpFileName = osTmpDirName + "/";
             pszAttachmentFilename =
@@ -861,45 +850,45 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
                 OGRWFSFetchContentDispositionFilename(
                     psResult->papszHeaders);
 
-    int bJSON = FALSE;
-    int bCSV = FALSE;
-    int bKML = FALSE;
-    int bKMZ = FALSE;
-    int bZIP = FALSE;
-    int bGZIP = FALSE;
+    bool bJSON = false;
+    bool bCSV = false;
+    bool bKML = false;
+    bool bKMZ = false;
+    bool bZIP = false;
+    bool bGZIP = false;
 
     const char* pszOutputFormat = osOutputFormat.c_str();
 
     if (FindSubStringInsensitive(pszContentType, "json") ||
         FindSubStringInsensitive(pszOutputFormat, "json"))
     {
-        bJSON = TRUE;
+        bJSON = true;
     }
     else if (FindSubStringInsensitive(pszContentType, "csv") ||
              FindSubStringInsensitive(pszOutputFormat, "csv"))
     {
-        bCSV = TRUE;
+        bCSV = true;
     }
     else if (FindSubStringInsensitive(pszContentType, "kml") ||
              FindSubStringInsensitive(pszOutputFormat, "kml"))
     {
-        bKML = TRUE;
+        bKML = true;
     }
     else if (FindSubStringInsensitive(pszContentType, "kmz") ||
              FindSubStringInsensitive(pszOutputFormat, "kmz"))
     {
-        bKMZ = TRUE;
+        bKMZ = true;
     }
     else if (strstr(pszContentType, "application/zip") != NULL)
     {
-        bZIP = TRUE;
+        bZIP = true;
     }
     else if (strstr(pszContentType, "application/gzip") != NULL)
     {
-        bGZIP = TRUE;
+        bGZIP = true;
     }
 
-    if (MustRetryIfNonCompliantServer((const char*)pabyData))
+    if( MustRetryIfNonCompliantServer((const char*)pabyData) )
     {
         CPLHTTPDestroyResult(psResult);
         return FetchGetFeature(nRequestMaxFeatures);
@@ -908,7 +897,7 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
     if (strstr((const char*)pabyData, "<ServiceExceptionReport") != NULL ||
         strstr((const char*)pabyData, "<ows:ExceptionReport") != NULL)
     {
-        if (poDS->IsOldDeegree((const char*)pabyData))
+        if( poDS->IsOldDeegree((const char*)pabyData) )
         {
             CPLHTTPDestroyResult(psResult);
             return FetchGetFeature(nRequestMaxFeatures);
@@ -922,17 +911,17 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
 
     CPLString osTmpFileName;
 
-    if (!bIsMultiPart)
+    if( !bIsMultiPart )
     {
-        if (bJSON)
+        if( bJSON )
             osTmpFileName = osTmpDirName + "/file.geojson";
-        else if (bZIP)
+        else if( bZIP )
             osTmpFileName = osTmpDirName + "/file.zip";
-        else if (bCSV)
+        else if( bCSV )
             osTmpFileName = osTmpDirName + "/file.csv";
-        else if (bKML)
+        else if( bKML )
             osTmpFileName = osTmpDirName + "/file.kml";
-        else if (bKMZ)
+        else if( bKMZ )
             osTmpFileName = osTmpDirName + "/file.kmz";
         /* GML is a special case. It needs the .xsd file that has been saved */
         /* as file.xsd, so we cannot used the attachment filename */
@@ -955,11 +944,11 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         VSIFCloseL(fp);
         psResult->pabyData = NULL;
 
-        if (bZIP)
+        if( bZIP )
         {
             osTmpFileName = "/vsizip/" + osTmpFileName;
         }
-        else if (bGZIP)
+        else if( bGZIP )
         {
             osTmpFileName = "/vsigzip/" + osTmpFileName;
         }
@@ -1001,14 +990,13 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
 
     GDALDataset* poPageDS = (GDALDataset*) GDALOpenEx(osTmpFileName,
                                 GDAL_OF_VECTOR, NULL, papszOpenOptions, NULL);
-    if (poPageDS == NULL && (bZIP || bIsMultiPart))
+    if( poPageDS == NULL && (bZIP || bIsMultiPart) )
     {
         char** papszFileList = VSIReadDir(osTmpFileName);
-        int i;
-        for( i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
+        for( int i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
         {
             CPLString osFullFilename =
-                    CPLFormFilename( osTmpFileName, papszFileList[i], NULL );
+                CPLFormFilename( osTmpFileName, papszFileList[i], NULL );
             hDrv = GDALIdentifyDriver(osFullFilename, NULL);
             if( hDrv != NULL && hDrv == GDALGetDriverByName("GML") )
                 papszOpenOptions = apszGMLOpenOptions;
@@ -1021,11 +1009,11 @@ GDALDataset* OGRWFSLayer::FetchGetFeature(int nRequestMaxFeatures)
         CSLDestroy( papszFileList );
     }
 
-    if (poPageDS == NULL)
+    if( poPageDS == NULL )
     {
-        if (pabyData != NULL && !bJSON && !bZIP &&
+        if( pabyData != NULL && !bJSON && !bZIP &&
             strstr((const char*)pabyData, "<wfs:FeatureCollection") == NULL &&
-            strstr((const char*)pabyData, "<gml:FeatureCollection") == NULL)
+            strstr((const char*)pabyData, "<gml:FeatureCollection") == NULL )
         {
             if (nDataLen > 1000)
                 pabyData[1000] = 0;
@@ -1068,7 +1056,7 @@ OGRFeatureDefn * OGRWFSLayer::GetLayerDefn()
 
 OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(OGRFeatureDefn* poSrcFDefn)
 {
-    int bUnsetWidthPrecision = FALSE;
+    bool bUnsetWidthPrecision = false;
 
     poFeatureDefn = new OGRFeatureDefn( pszName );
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
@@ -1091,19 +1079,18 @@ OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(OGRFeatureDefn* poSrcFDefn)
             return poFeatureDefn;
         }
         poSrcFDefn = l_poLayer->GetLayerDefn();
-        bGotApproximateLayerDefn = TRUE;
+        bGotApproximateLayerDefn = true;
         /* We cannot trust width and precision based on a single feature */
-        bUnsetWidthPrecision = TRUE;
+        bUnsetWidthPrecision = true;
     }
 
     CPLString osPropertyName = CPLURLGetValue(pszBaseURL, "PROPERTYNAME");
     const char* pszPropertyName = osPropertyName.c_str();
 
-    int i;
     poFeatureDefn->SetGeomType(poSrcFDefn->GetGeomType());
     if( poSrcFDefn->GetGeomFieldCount() > 0 )
         poFeatureDefn->GetGeomFieldDefn(0)->SetName(poSrcFDefn->GetGeomFieldDefn(0)->GetNameRef());
-    for(i=0;i<poSrcFDefn->GetFieldCount();i++)
+    for( int i = 0; i < poSrcFDefn->GetFieldCount(); i++ )
     {
         if (pszPropertyName[0] != 0)
         {
@@ -1111,12 +1098,12 @@ OGRFeatureDefn * OGRWFSLayer::BuildLayerDefn(OGRFeatureDefn* poSrcFDefn)
                        poSrcFDefn->GetFieldDefn(i)->GetNameRef()) != NULL)
                 poFeatureDefn->AddFieldDefn(poSrcFDefn->GetFieldDefn(i));
             else
-                bGotApproximateLayerDefn = TRUE;
+                bGotApproximateLayerDefn = true;
         }
         else
         {
             OGRFieldDefn oFieldDefn(poSrcFDefn->GetFieldDefn(i));
-            if (bUnsetWidthPrecision)
+            if( bUnsetWidthPrecision )
             {
                 oFieldDefn.SetWidth(0);
                 oFieldDefn.SetPrecision(0);
@@ -1141,18 +1128,18 @@ void OGRWFSLayer::ResetReading()
 
 {
     GetLayerDefn();
-    if (bPagingActive)
-        bReloadNeeded = TRUE;
+    if( bPagingActive )
+        bReloadNeeded = true;
     nPagingStartIndex = 0;
     nFeatureRead = 0;
     nFeatureCountRequested = 0;
-    if (bReloadNeeded)
+    if( bReloadNeeded )
     {
         GDALClose(poBaseDS);
         poBaseDS = NULL;
         poBaseLayer = NULL;
-        bHasFetched = FALSE;
-        bReloadNeeded = FALSE;
+        bHasFetched = false;
+        bReloadNeeded = false;
     }
     if (poBaseLayer)
         poBaseLayer->ResetReading();
@@ -1164,7 +1151,7 @@ void OGRWFSLayer::ResetReading()
 
 OGRErr OGRWFSLayer::SetIgnoredFields( const char **papszFields )
 {
-    bReloadNeeded = TRUE;
+    bReloadNeeded = true;
     ResetReading();
     return OGRLayer::SetIgnoredFields(papszFields);
 }
@@ -1179,22 +1166,23 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
 
     while( true )
     {
-        if (bPagingActive && nFeatureRead == nPagingStartIndex + nFeatureCountRequested)
+        if( bPagingActive &&
+            nFeatureRead == nPagingStartIndex + nFeatureCountRequested )
         {
-            bReloadNeeded = TRUE;
+            bReloadNeeded = true;
             nPagingStartIndex = nFeatureRead;
         }
-        if (bReloadNeeded)
+        if( bReloadNeeded )
         {
             GDALClose(poBaseDS);
             poBaseDS = NULL;
             poBaseLayer = NULL;
-            bHasFetched = FALSE;
-            bReloadNeeded = FALSE;
+            bHasFetched = false;
+            bReloadNeeded = false;
         }
-        if (poBaseDS == NULL && !bHasFetched)
+        if( poBaseDS == NULL && !bHasFetched )
         {
-            bHasFetched = TRUE;
+            bHasFetched = true;
             poBaseDS = FetchGetFeature(0);
             poBaseLayer = NULL;
             if (poBaseDS)
@@ -1207,18 +1195,19 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
                 /* Check that the layer field definition is consistent with the one */
                 /* we got in BuildLayerDefn() */
                 if (poFeatureDefn->GetFieldCount() != poBaseLayer->GetLayerDefn()->GetFieldCount())
-                    bGotApproximateLayerDefn = TRUE;
+                    bGotApproximateLayerDefn = true;
                 else
                 {
-                    int iField;
-                    for(iField = 0;iField < poFeatureDefn->GetFieldCount(); iField++)
+                    for( int iField = 0;
+                         iField < poFeatureDefn->GetFieldCount();
+                         iField++)
                     {
                         OGRFieldDefn* poFDefn1 = poFeatureDefn->GetFieldDefn(iField);
                         OGRFieldDefn* poFDefn2 = poBaseLayer->GetLayerDefn()->GetFieldDefn(iField);
                         if (strcmp(poFDefn1->GetNameRef(), poFDefn2->GetNameRef()) != 0 ||
                             poFDefn1->GetType() != poFDefn2->GetType())
                         {
-                            bGotApproximateLayerDefn = TRUE;
+                            bGotApproximateLayerDefn = true;
                             break;
                         }
                     }
@@ -1246,7 +1235,7 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
         /* Client-side attribute filtering with underlying layer defn */
         /* identical to exposed layer defn. */
         if( !bGotApproximateLayerDefn &&
-            osWFSWhere.size() == 0 &&
+            osWFSWhere.empty() &&
             m_poAttrQuery != NULL &&
             !m_poAttrQuery->Evaluate( poSrcFeature ) )
         {
@@ -1255,13 +1244,13 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
         }
 
         OGRFeature* poNewFeature = new OGRFeature(poFeatureDefn);
-        if (bGotApproximateLayerDefn)
+        if( bGotApproximateLayerDefn )
         {
             poNewFeature->SetFrom(poSrcFeature);
 
             /* Client-side attribute filtering. */
             if( m_poAttrQuery != NULL &&
-                osWFSWhere.size() == 0 &&
+                osWFSWhere.empty() &&
                 !m_poAttrQuery->Evaluate( poNewFeature ) )
             {
                 delete poSrcFeature;
@@ -1271,9 +1260,13 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
         }
         else
         {
-            int iField;
-            for(iField = 0;iField < poFeatureDefn->GetFieldCount(); iField++)
-                poNewFeature->SetField( iField, poSrcFeature->GetRawFieldRef(iField) );
+            for( int iField = 0;
+                 iField < poFeatureDefn->GetFieldCount();
+                 iField++ )
+            {
+                poNewFeature->SetField(
+                    iField, poSrcFeature->GetRawFieldRef(iField) );
+            }
             poNewFeature->SetStyleString(poSrcFeature->GetStyleString());
             poNewFeature->SetGeometryDirectly(poSrcFeature->StealGeometry());
         }
@@ -1304,14 +1297,16 @@ OGRFeature *OGRWFSLayer::GetNextFeature()
 
 void OGRWFSLayer::SetSpatialFilter( OGRGeometry * poGeom )
 {
-    if (bStreamingDS)
-        bReloadNeeded = TRUE;
-    else if (poFetchedFilterGeom == NULL && poBaseDS != NULL)
+    if( bStreamingDS )
+    {
+        bReloadNeeded = true;
+    }
+    else if( poFetchedFilterGeom == NULL && poBaseDS != NULL )
     {
         /* If there was no filter set, and that we set one */
         /* the new result set can only be a subset of the whole */
         /* so no need to reload from source */
-        bReloadNeeded = FALSE;
+        bReloadNeeded = false;
     }
     else if (poFetchedFilterGeom != NULL && poGeom != NULL && poBaseDS != NULL)
     {
@@ -1321,10 +1316,12 @@ void OGRWFSLayer::SetSpatialFilter( OGRGeometry * poGeom )
         /* Optimization : we don't need to request the server */
         /* if the new BBOX is inside the old BBOX as we have */
         /* already all the features */
-        bReloadNeeded = ! oOldEnvelope.Contains(oNewEnvelope);
+        bReloadNeeded = !oOldEnvelope.Contains(oNewEnvelope);
     }
     else
-        bReloadNeeded = TRUE;
+    {
+        bReloadNeeded = true;
+    }
     nFeatures = -1;
     OGRLayer::SetSpatialFilter(poGeom);
     ResetReading();
@@ -1372,22 +1369,23 @@ OGRErr OGRWFSLayer::SetAttributeFilter( const char * pszFilter )
         if( poNode->field_type != SWQ_BOOLEAN )
             osWFSWhere = "";
         else
-            osWFSWhere = WFS_TurnSQLFilterToOGCFilter(poNode,
-                                                      NULL,
-                                                  GetLayerDefn(),
-                                                  nVersion,
-                                                  poDS->PropertyIsNotEqualToSupported(),
-                                                  poDS->UseFeatureId() || bUseFeatureIdAtLayerLevel,
-                                                  poDS->DoesGmlObjectIdNeedGMLPrefix(),
-                                                  "",
-                                                  &bNeedsNullCheck);
+            osWFSWhere = WFS_TurnSQLFilterToOGCFilter(
+                poNode,
+                NULL,
+                GetLayerDefn(),
+                nVersion,
+                poDS->PropertyIsNotEqualToSupported(),
+                poDS->UseFeatureId() || bUseFeatureIdAtLayerLevel,
+                poDS->DoesGmlObjectIdNeedGMLPrefix(),
+                "",
+                &bNeedsNullCheck);
         if (bNeedsNullCheck && !poDS->HasNullCheck())
             osWFSWhere = "";
     }
     else
         osWFSWhere = "";
 
-    if (m_poAttrQuery != NULL && osWFSWhere.size() == 0)
+    if (m_poAttrQuery != NULL && osWFSWhere.empty())
     {
         CPLDebug("WFS", "Using client-side only mode for filter \"%s\"", pszFilter);
         OGRErr eErr = OGRLayer::SetAttributeFilter(pszFilter);
@@ -1399,9 +1397,9 @@ OGRErr OGRWFSLayer::SetAttributeFilter( const char * pszFilter )
     osSQLWhere = (pszFilter) ? pszFilter : "";
 
     if (osWFSWhere != osOldWFSWhere)
-        bReloadNeeded = TRUE;
+        bReloadNeeded = true;
     else
-        bReloadNeeded = FALSE;
+        bReloadNeeded = false;
     nFeatures = -1;
 
     return OGRERR_NONE;
@@ -1426,7 +1424,7 @@ int OGRWFSLayer::TestCapability( const char * pszCap )
 
     else if( EQUAL(pszCap,OLCFastGetExtent) )
     {
-        if (bHasExtents)
+        if( bHasExtents )
             return TRUE;
 
         return poBaseLayer != NULL &&
@@ -1531,7 +1529,7 @@ GIntBig OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
     if (strstr(pabyData, "<ServiceExceptionReport") != NULL ||
         strstr(pabyData, "<ows:ExceptionReport") != NULL)
     {
-        if (poDS->IsOldDeegree(pabyData))
+        if( poDS->IsOldDeegree(pabyData) )
         {
             CPLHTTPDestroyResult(psResult);
             return ExecuteGetFeatureResultTypeHits();
@@ -1582,7 +1580,7 @@ GIntBig OGRWFSLayer::ExecuteGetFeatureResultTypeHits()
     /* Hum, http://deegree3-testing.deegree.org:80/deegree-inspire-node/services?MAXFEATURES=10&SERVICE=WFS&VERSION=1.1.0&REQUEST=GetFeature&TYPENAME=ad:Address&OUTPUTFORMAT=text/xml;%20subtype=gml/3.2.1&RESULTTYPE=hits */
     /* returns more than MAXFEATURES features... So truncate to MAXFEATURES */
     CPLString osMaxFeatures = CPLURLGetValue(osURL, atoi(poDS->GetVersion()) >= 2 ? "COUNT" : "MAXFEATURES");
-    if (osMaxFeatures.size() != 0)
+    if (!osMaxFeatures.empty())
     {
         GIntBig nMaxFeatures = CPLAtoGIntBig(osMaxFeatures);
         if (l_nFeatures > nMaxFeatures)
@@ -1627,7 +1625,7 @@ GIntBig OGRWFSLayer::GetFeatureCount( int bForce )
     if (TestCapability(OLCFastFeatureCount))
         return poBaseLayer->GetFeatureCount(bForce);
 
-    if ((m_poAttrQuery == NULL || osWFSWhere.size() != 0) &&
+    if ((m_poAttrQuery == NULL || !osWFSWhere.empty()) &&
          poDS->GetFeatureSupportHits())
     {
         nFeatures = ExecuteGetFeatureResultTypeHits();
@@ -1664,27 +1662,27 @@ GIntBig OGRWFSLayer::GetFeatureCount( int bForce )
     return nFeatures;
 }
 
-
 /************************************************************************/
 /*                              SetExtent()                             */
 /************************************************************************/
 
-void OGRWFSLayer::SetExtents(double dfMinXIn, double dfMinYIn, double dfMaxXIn, double dfMaxYIn)
+void OGRWFSLayer::SetExtents( double dfMinXIn, double dfMinYIn,
+                              double dfMaxXIn, double dfMaxYIn )
 {
-    this->dfMinX = dfMinXIn;
-    this->dfMinY = dfMinYIn;
-    this->dfMaxX = dfMaxXIn;
-    this->dfMaxY = dfMaxYIn;
-    bHasExtents = TRUE;
+    dfMinX = dfMinXIn;
+    dfMinY = dfMinYIn;
+    dfMaxX = dfMaxXIn;
+    dfMaxY = dfMaxYIn;
+    bHasExtents = true;
 }
 
 /************************************************************************/
 /*                              GetExtent()                             */
 /************************************************************************/
 
-OGRErr OGRWFSLayer::GetExtent(OGREnvelope *psExtent, int bForce)
+OGRErr OGRWFSLayer::GetExtent( OGREnvelope *psExtent, int bForce )
 {
-    if (bHasExtents)
+    if( bHasExtents )
     {
         psExtent->MinX = dfMinX;
         psExtent->MinY = dfMinY;
@@ -1712,7 +1710,7 @@ OGRErr OGRWFSLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     /* and GetExtent() with the same data */
     if( CanRunGetFeatureCountAndGetExtentTogether() )
     {
-        bCountFeaturesInGetNextFeature = TRUE;
+        bCountFeaturesInGetNextFeature = true;
         nFeatures = 0;
     }
 
@@ -1726,13 +1724,13 @@ OGRErr OGRWFSLayer::GetExtent(OGREnvelope *psExtent, int bForce)
             dfMinY = psExtent->MinY;
             dfMaxX = psExtent->MaxX;
             dfMaxY = psExtent->MaxY;
-            bHasExtents = TRUE;
+            bHasExtents = true;
         }
         else
         {
             nFeatures = -1;
         }
-        bCountFeaturesInGetNextFeature = FALSE;
+        bCountFeaturesInGetNextFeature = false;
     }
 
     return eErr;
@@ -1752,7 +1750,6 @@ const char* OGRWFSLayer::GetShortName()
     return pszShortName;
 }
 
-
 /************************************************************************/
 /*                          GetPostHeader()                             */
 /************************************************************************/
@@ -1813,7 +1810,7 @@ OGRErr OGRWFSLayer::ICreateFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if (poFeature->IsFieldSet(0))
+    if (poFeature->IsFieldSetAndNotNull(0))
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot insert a feature when gml_id field is already set");
@@ -1824,7 +1821,7 @@ OGRErr OGRWFSLayer::ICreateFeature( OGRFeature *poFeature )
 
     const char* pszShortName = GetShortName();
 
-    if (!bInTransaction)
+    if( !bInTransaction )
     {
         osPost += GetPostHeader();
         osPost += "  <wfs:Insert>\n";
@@ -1832,18 +1829,17 @@ OGRErr OGRWFSLayer::ICreateFeature( OGRFeature *poFeature )
     osPost += "    <feature:"; osPost += pszShortName; osPost += " xmlns:feature=\"";
     osPost += osTargetNamespace; osPost += "\">\n";
 
-    int i;
-    for(i=1; i <= poFeature->GetFieldCount(); i++)
+    for( int i = 1; i <= poFeature->GetFieldCount(); i++ )
     {
         if (poGMLFeatureClass->GetGeometryPropertyCount() == 1 &&
             poGMLFeatureClass->GetGeometryProperty(0)->GetAttributeIndex() == i - 1)
         {
             OGRGeometry* poGeom = poFeature->GetGeometryRef();
-            if (poGeom != NULL && osGeometryColumnName.size() != 0)
+            if (poGeom != NULL && !osGeometryColumnName.empty())
             {
                 if (poGeom->getSpatialReference() == NULL)
                     poGeom->assignSpatialReference(poSRS);
-                char* pszGML;
+                char* pszGML = NULL;
                 if (strcmp(poDS->GetVersion(), "1.1.0") == 0)
                 {
                     char** papszOptions = CSLAddString(NULL, "FORMAT=GML3");
@@ -1861,7 +1857,17 @@ OGRErr OGRWFSLayer::ICreateFeature( OGRFeature *poFeature )
         if (i == poFeature->GetFieldCount())
             break;
 
-        if (poFeature->IsFieldSet(i))
+#ifdef notdef
+        if( poFeature->IsFieldNull(i) )
+        {
+            OGRFieldDefn* poFDefn = poFeature->GetFieldDefnRef(i);
+            osPost += "      <feature:";
+            osPost += poFDefn->GetNameRef();
+            osPost += " xsi:nil=\"true\" />\n";
+        }
+        else
+#endif
+        if (poFeature->IsFieldSet(i) && !poFeature->IsFieldNull(i) )
         {
             OGRFieldDefn* poFDefn = poFeature->GetFieldDefnRef(i);
             osPost += "      <feature:";
@@ -1884,12 +1890,11 @@ OGRErr OGRWFSLayer::ICreateFeature( OGRFeature *poFeature )
             osPost += poFDefn->GetNameRef();
             osPost += ">\n";
         }
-
     }
 
     osPost += "    </feature:"; osPost += pszShortName; osPost += ">\n";
 
-    if (!bInTransaction)
+    if( !bInTransaction )
     {
         osPost += "  </wfs:Insert>\n";
         osPost += "</wfs:Transaction>\n";
@@ -1939,13 +1944,13 @@ OGRErr OGRWFSLayer::ICreateFeature( OGRFeature *poFeature )
     }
 
     CPLStripXMLNamespace( psXML, NULL, TRUE );
-    int bUse100Schema = FALSE;
+    bool bUse100Schema = false;
     CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=TransactionResponse" );
     if (psRoot == NULL)
     {
         psRoot = CPLGetXMLNode( psXML, "=WFS_TransactionResponse" );
         if (psRoot)
-            bUse100Schema = TRUE;
+            bUse100Schema = true;
     }
 
     if (psRoot == NULL)
@@ -1959,7 +1964,7 @@ OGRErr OGRWFSLayer::ICreateFeature( OGRFeature *poFeature )
 
     CPLXMLNode* psFeatureID = NULL;
 
-    if (bUse100Schema)
+    if( bUse100Schema )
     {
         if (CPLGetXMLNode( psRoot, "TransactionResult.Status.FAILED" ))
         {
@@ -2022,14 +2027,13 @@ OGRErr OGRWFSLayer::ICreateFeature( OGRFeature *poFeature )
     CPLHTTPDestroyResult(psResult);
 
     /* Invalidate layer */
-    bReloadNeeded = TRUE;
+    bReloadNeeded = true;
     nFeatures = -1;
-    bHasExtents = FALSE;
+    bHasExtents = false;
 
     return OGRERR_NONE;
 }
 
-
 /************************************************************************/
 /*                             ISetFeature()                             */
 /************************************************************************/
@@ -2054,14 +2058,14 @@ OGRErr OGRWFSLayer::ISetFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if (poFeature->IsFieldSet(0) == FALSE)
+    if (poFeature->IsFieldSetAndNotNull(0) == FALSE)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot update a feature when gml_id field is not set");
         return OGRERR_FAILURE;
     }
 
-    if (bInTransaction)
+    if( bInTransaction )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "SetFeature() not yet dealt in transaction. Issued immediately");
@@ -2076,7 +2080,7 @@ OGRErr OGRWFSLayer::ISetFeature( OGRFeature *poFeature )
     osPost += osTargetNamespace; osPost += "\">\n";
 
     OGRGeometry* poGeom = poFeature->GetGeometryRef();
-    if ( osGeometryColumnName.size() != 0 )
+    if ( !osGeometryColumnName.empty() )
     {
         osPost += "    <wfs:Property>\n";
         osPost += "      <wfs:Name>"; osPost += osGeometryColumnName; osPost += "</wfs:Name>\n";
@@ -2084,7 +2088,7 @@ OGRErr OGRWFSLayer::ISetFeature( OGRFeature *poFeature )
         {
             if (poGeom->getSpatialReference() == NULL)
                 poGeom->assignSpatialReference(poSRS);
-            char* pszGML;
+            char* pszGML = NULL;
             if (strcmp(poDS->GetVersion(), "1.1.0") == 0)
             {
                 char** papszOptions = CSLAddString(NULL, "FORMAT=GML3");
@@ -2101,14 +2105,13 @@ OGRErr OGRWFSLayer::ISetFeature( OGRFeature *poFeature )
         osPost += "    </wfs:Property>\n";
     }
 
-    int i;
-    for(i=1; i < poFeature->GetFieldCount(); i++)
+    for( int i = 1; i < poFeature->GetFieldCount(); i++ )
     {
         OGRFieldDefn* poFDefn = poFeature->GetFieldDefnRef(i);
 
         osPost += "    <wfs:Property>\n";
         osPost += "      <wfs:Name>"; osPost += poFDefn->GetNameRef(); osPost += "</wfs:Name>\n";
-        if (poFeature->IsFieldSet(i))
+        if (poFeature->IsFieldSetAndNotNull(i))
         {
             osPost += "      <wfs:Value>";
             if (poFDefn->GetType() == OFTInteger)
@@ -2129,7 +2132,7 @@ OGRErr OGRWFSLayer::ISetFeature( OGRFeature *poFeature )
         osPost += "    </wfs:Property>\n";
     }
     osPost += "    <ogc:Filter>\n";
-    if (poDS->UseFeatureId() || bUseFeatureIdAtLayerLevel)
+    if( poDS->UseFeatureId() || bUseFeatureIdAtLayerLevel )
         osPost += "      <ogc:FeatureId fid=\"";
     else if (atoi(poDS->GetVersion()) >= 2)
         osPost += "      <ogc:ResourceId rid=\"";
@@ -2178,13 +2181,13 @@ OGRErr OGRWFSLayer::ISetFeature( OGRFeature *poFeature )
     }
 
     CPLStripXMLNamespace( psXML, NULL, TRUE );
-    int bUse100Schema = FALSE;
+    int bUse100Schema = false;
     CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=TransactionResponse" );
     if (psRoot == NULL)
     {
         psRoot = CPLGetXMLNode( psXML, "=WFS_TransactionResponse" );
         if (psRoot)
-            bUse100Schema = TRUE;
+            bUse100Schema = true;
     }
     if (psRoot == NULL)
     {
@@ -2195,7 +2198,7 @@ OGRErr OGRWFSLayer::ISetFeature( OGRFeature *poFeature )
         return OGRERR_FAILURE;
     }
 
-    if (bUse100Schema)
+    if( bUse100Schema )
     {
         if (CPLGetXMLNode( psRoot, "TransactionResult.Status.FAILED" ))
         {
@@ -2212,9 +2215,9 @@ OGRErr OGRWFSLayer::ISetFeature( OGRFeature *poFeature )
     CPLHTTPDestroyResult(psResult);
 
     /* Invalidate layer */
-    bReloadNeeded = TRUE;
+    bReloadNeeded = true;
     nFeatures = -1;
-    bHasExtents = FALSE;
+    bHasExtents = false;
 
     return OGRERR_NONE;
 }
@@ -2315,13 +2318,13 @@ OGRErr OGRWFSLayer::DeleteFromFilter( CPLString osOGCFilter )
     }
 
     CPLStripXMLNamespace( psXML, NULL, TRUE );
-    int bUse100Schema = FALSE;
+    bool bUse100Schema = false;
     CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=TransactionResponse" );
     if (psRoot == NULL)
     {
         psRoot = CPLGetXMLNode( psXML, "=WFS_TransactionResponse" );
         if (psRoot)
-            bUse100Schema = TRUE;
+            bUse100Schema = true;
     }
     if (psRoot == NULL)
     {
@@ -2331,7 +2334,7 @@ OGRErr OGRWFSLayer::DeleteFromFilter( CPLString osOGCFilter )
         return OGRERR_FAILURE;
     }
 
-    if (bUse100Schema)
+    if( bUse100Schema )
     {
         if (CPLGetXMLNode( psRoot, "TransactionResult.Status.FAILED" ))
         {
@@ -2348,9 +2351,9 @@ OGRErr OGRWFSLayer::DeleteFromFilter( CPLString osOGCFilter )
     CPLHTTPDestroyResult(psResult);
 
     /* Invalidate layer */
-    bReloadNeeded = TRUE;
+    bReloadNeeded = true;
     nFeatures = -1;
-    bHasExtents = FALSE;
+    bHasExtents = false;
 
     return OGRERR_NONE;
 }
@@ -2396,7 +2399,7 @@ OGRErr OGRWFSLayer::DeleteFeature( GIntBig nFID )
         return OGRERR_FAILURE;
     }
 
-    if (bInTransaction)
+    if( bInTransaction )
     {
         CPLError(CE_Warning, CPLE_AppDefined,
                  "DeleteFeature() not yet dealt in transaction. Issued immediately");
@@ -2412,7 +2415,6 @@ OGRErr OGRWFSLayer::DeleteFeature( GIntBig nFID )
     return DeleteFromFilter(osFilter);
 }
 
-
 /************************************************************************/
 /*                         StartTransaction()                           */
 /************************************************************************/
@@ -2430,14 +2432,14 @@ OGRErr OGRWFSLayer::StartTransaction()
         return OGRERR_FAILURE;
     }
 
-    if (bInTransaction)
+    if( bInTransaction )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                      "StartTransaction() has already been called");
         return OGRERR_FAILURE;
     }
 
-    bInTransaction = TRUE;
+    bInTransaction = true;
     osGlobalInsert = "";
     nExpectedInserts = 0;
     aosFIDList.resize(0);
@@ -2462,14 +2464,14 @@ OGRErr OGRWFSLayer::CommitTransaction()
         return OGRERR_FAILURE;
     }
 
-    if (!bInTransaction)
+    if( !bInTransaction )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                      "StartTransaction() has not yet been called");
         return OGRERR_FAILURE;
     }
 
-    if (osGlobalInsert.size() != 0)
+    if (!osGlobalInsert.empty())
     {
         CPLString osPost = GetPostHeader();
         osPost += "  <wfs:Insert>\n";
@@ -2477,10 +2479,10 @@ OGRErr OGRWFSLayer::CommitTransaction()
         osPost += "  </wfs:Insert>\n";
         osPost += "</wfs:Transaction>\n";
 
-        bInTransaction = FALSE;
+        bInTransaction = false;
         osGlobalInsert = "";
-        int l_nExpectedInserts = this->nExpectedInserts;
-        this->nExpectedInserts = 0;
+        int l_nExpectedInserts = nExpectedInserts;
+        nExpectedInserts = 0;
 
         CPLDebug("WFS", "Post : %s", osPost.c_str());
 
@@ -2520,13 +2522,13 @@ OGRErr OGRWFSLayer::CommitTransaction()
         }
 
         CPLStripXMLNamespace( psXML, NULL, TRUE );
-        int bUse100Schema = FALSE;
+        bool bUse100Schema = false;
         CPLXMLNode* psRoot = CPLGetXMLNode( psXML, "=TransactionResponse" );
         if (psRoot == NULL)
         {
             psRoot = CPLGetXMLNode( psXML, "=WFS_TransactionResponse" );
             if (psRoot)
-                bUse100Schema = TRUE;
+                bUse100Schema = true;
         }
 
         if (psRoot == NULL)
@@ -2538,7 +2540,7 @@ OGRErr OGRWFSLayer::CommitTransaction()
             return OGRERR_FAILURE;
         }
 
-        if (bUse100Schema)
+        if( bUse100Schema )
         {
             if (CPLGetXMLNode( psRoot, "TransactionResult.Status.FAILED" ))
             {
@@ -2608,7 +2610,7 @@ OGRErr OGRWFSLayer::CommitTransaction()
         CPLHTTPDestroyResult(psResult);
     }
 
-    bInTransaction = FALSE;
+    bInTransaction = false;
     osGlobalInsert = "";
     nExpectedInserts = 0;
 
@@ -2632,14 +2634,14 @@ OGRErr OGRWFSLayer::RollbackTransaction()
         return OGRERR_FAILURE;
     }
 
-    if (!bInTransaction)
+    if( !bInTransaction )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                      "StartTransaction() has not yet been called");
         return OGRERR_FAILURE;
     }
 
-    bInTransaction = FALSE;
+    bInTransaction = false;
     osGlobalInsert = "";
     nExpectedInserts = 0;
 
diff --git a/ogr/ogrsf_frmts/xls/ogr_xls.h b/ogr/ogrsf_frmts/xls/ogr_xls.h
index a5b3603..adb0469 100644
--- a/ogr/ogrsf_frmts/xls/ogr_xls.h
+++ b/ogr/ogrsf_frmts/xls/ogr_xls.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xls.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: ogr_xls.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  XLS Translator
  * Purpose:  Definition of classes for OGR .xls driver.
@@ -45,7 +45,7 @@ class OGRXLSLayer : public OGRLayer
 
     char              *pszName;
     int                iSheet;
-    int                bFirstLineIsHeaders;
+    bool               bFirstLineIsHeaders;
     int                nRows;
     unsigned short     nCols;
 
@@ -63,22 +63,20 @@ class OGRXLSLayer : public OGRLayer
                                     int iSheetIn,
                                     int nRowsIn,
                                     unsigned short nColsIn);
-                        ~OGRXLSLayer();
+                        virtual ~OGRXLSLayer();
 
+    virtual void                ResetReading() override;
+    virtual OGRFeature *        GetNextFeature() override;
 
-    virtual void                ResetReading();
-    virtual OGRFeature *        GetNextFeature();
+    virtual OGRFeatureDefn *    GetLayerDefn() override;
+    virtual GIntBig             GetFeatureCount( int bForce = TRUE ) override;
 
-    virtual OGRFeatureDefn *    GetLayerDefn();
-    virtual GIntBig             GetFeatureCount( int bForce = TRUE );
+    virtual const char         *GetName() override { return pszName; }
+    virtual OGRwkbGeometryType  GetGeomType() override { return wkbNone; }
 
-    virtual const char         *GetName() { return pszName; }
-    virtual OGRwkbGeometryType  GetGeomType() { return wkbNone; }
-
-    virtual int                 TestCapability( const char * );
-
-    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
+    virtual int                 TestCapability( const char * ) override;
 
+    virtual OGRSpatialReference *GetSpatialRef() override { return NULL; }
 };
 
 /************************************************************************/
@@ -96,17 +94,17 @@ class OGRXLSDataSource : public OGRDataSource
 
   public:
                         OGRXLSDataSource();
-                        ~OGRXLSDataSource();
+                        virtual ~OGRXLSDataSource();
 
     int                 Open( const char * pszFilename,
                               int bUpdate );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount() { return nLayers; }
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     const void                 *GetXLSHandle();
 };
@@ -118,12 +116,11 @@ class OGRXLSDataSource : public OGRDataSource
 class OGRXLSDriver : public OGRSFDriver
 {
   public:
-                ~OGRXLSDriver();
+                virtual ~OGRXLSDriver();
 
-    virtual const char*         GetName();
-    virtual OGRDataSource*      Open( const char *, int );
-    virtual int                 TestCapability( const char * );
+    virtual const char*         GetName() override;
+    virtual OGRDataSource*      Open( const char *, int ) override;
+    virtual int                 TestCapability( const char * ) override;
 };
 
-
 #endif /* ndef OGR_XLS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp b/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
index 5d6f59c..87ff45f 100644
--- a/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
+++ b/ogr/ogrsf_frmts/xls/ogrxlsdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrxlsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $
  *
  * Project:  XLS Translator
  * Purpose:  Implements OGRXLSDataSource class
@@ -37,22 +36,18 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrxlsdatasource.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrxlsdatasource.cpp 35205 2016-08-26 18:17:08Z goatbar $");
 
 /************************************************************************/
 /*                          OGRXLSDataSource()                          */
 /************************************************************************/
 
-OGRXLSDataSource::OGRXLSDataSource()
-
-{
-    papoLayers = NULL;
-    nLayers = 0;
-
-    pszName = NULL;
-
-    xlshandle = NULL;
-}
+OGRXLSDataSource::OGRXLSDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    xlshandle(NULL)
+{}
 
 /************************************************************************/
 /*                         ~OGRXLSDataSource()                          */
@@ -67,7 +62,7 @@ OGRXLSDataSource::~OGRXLSDataSource()
 
     CPLFree( pszName );
 
-    if (xlshandle)
+    if( xlshandle )
         freexl_close(xlshandle);
 }
 
diff --git a/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp b/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
index 8bb7ac0..5b42013 100644
--- a/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
+++ b/ogr/ogrsf_frmts/xls/ogrxlsdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrxlsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $
  *
  * Project:  XLS Translator
  * Purpose:  Implements OGRXLSDriver.
@@ -30,7 +29,7 @@
 #include "ogr_xls.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrxlsdriver.cpp 32110 2015-12-10 17:19:40Z goatbar $");
+CPL_CVSID("$Id: ogrxlsdriver.cpp 34819 2016-07-28 22:32:18Z goatbar $");
 
 /************************************************************************/
 /*                           ~OGRXLSDriver()                            */
@@ -104,4 +103,3 @@ void RegisterOGRXLS()
 
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp b/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
index 61883ba..f4ee972 100644
--- a/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
+++ b/ogr/ogrsf_frmts/xls/ogrxlslayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrxlslayer.cpp 31478 2015-11-14 19:13:16Z goatbar $
  *
  * Project:  XLS Translator
  * Purpose:  Implements OGRXLSLayer class.
@@ -33,7 +32,7 @@
 #include "cpl_conv.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: ogrxlslayer.cpp 31478 2015-11-14 19:13:16Z goatbar $");
+CPL_CVSID("$Id: ogrxlslayer.cpp 35580 2016-10-01 17:02:59Z goatbar $");
 
 /************************************************************************/
 /*                            OGRXLSLayer()                             */
@@ -43,17 +42,16 @@ OGRXLSLayer::OGRXLSLayer( OGRXLSDataSource* poDSIn,
                           const char* pszSheetname,
                           int iSheetIn,
                           int nRowsIn,
-                          unsigned short nColsIn )
-
+                          unsigned short nColsIn ) :
+    poDS(poDSIn),
+    poFeatureDefn(NULL),
+    pszName(CPLStrdup(pszSheetname)),
+    iSheet(iSheetIn),
+    bFirstLineIsHeaders(false),
+    nRows(nRowsIn),
+    nCols(nColsIn),
+    nNextFID(0)
 {
-    poDS = poDSIn;
-    iSheet = iSheetIn;
-    nNextFID = 0;
-    bFirstLineIsHeaders = FALSE;
-    poFeatureDefn = NULL;
-    pszName = CPLStrdup(pszSheetname);
-    nRows = nRowsIn;
-    nCols = nColsIn;
     SetDescription( pszName );
 }
 
@@ -65,7 +63,7 @@ OGRXLSLayer::~OGRXLSLayer()
 
 {
     CPLFree(pszName);
-    if (poFeatureDefn)
+    if( poFeatureDefn )
         poFeatureDefn->Release();
 }
 
@@ -89,10 +87,10 @@ void OGRXLSLayer::ResetReading()
 void OGRXLSLayer::DetectHeaderLine(const void* xlshandle)
 
 {
-    unsigned short i;
     FreeXL_CellValue sCellValue;
     int nCountTextOnSecondLine = 0;
-    for(i = 0; i < nCols && nRows >= 2; i ++)
+    unsigned short i = 0;  // Used after for.
+    for( ; i < nCols && nRows >= 2; i++ )
     {
         if (freexl_get_cell_value(xlshandle, 0, i, &sCellValue) == FREEXL_OK)
         {
@@ -117,12 +115,12 @@ void OGRXLSLayer::DetectHeaderLine(const void* xlshandle)
     }
 
     const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", "");
-    if (EQUAL(pszXLSHeaders, "FORCE"))
-        bFirstLineIsHeaders = TRUE;
-    else if (EQUAL(pszXLSHeaders, "DISABLE"))
-        bFirstLineIsHeaders = FALSE;
-    else if (i == nCols && nCountTextOnSecondLine != nCols)
-        bFirstLineIsHeaders = TRUE;
+    if( EQUAL(pszXLSHeaders, "FORCE") )
+        bFirstLineIsHeaders = true;
+    else if( EQUAL(pszXLSHeaders, "DISABLE") )
+        bFirstLineIsHeaders = false;
+    else if( i == nCols && nCountTextOnSecondLine != nCols )
+        bFirstLineIsHeaders = true;
 }
 
 /************************************************************************/
@@ -133,12 +131,10 @@ void OGRXLSLayer::DetectColumnTypes(const void* xlshandle,
                                     int* paeFieldTypes)
 
 {
-    int j;
-    unsigned short i;
     FreeXL_CellValue sCellValue;
-    for(j = bFirstLineIsHeaders ? 1 : 0; j < nRows; j ++)
+    for( int j = bFirstLineIsHeaders ? 1 : 0; j < nRows; j++ )
     {
-        for(i = 0; i < nCols; i ++)
+        for( unsigned short i = 0; i < nCols; i ++)
         {
             if (freexl_get_cell_value(xlshandle, j, i, &sCellValue) == FREEXL_OK)
             {
@@ -214,14 +210,14 @@ OGRFeatureDefn * OGRXLSLayer::GetLayerDefn()
 
     if (nRows > 0)
     {
-        unsigned short i;
+
         FreeXL_CellValue sCellValue;
 
         DetectHeaderLine(xlshandle);
 
         int* paeFieldTypes = (int* )
                             CPLMalloc(nCols * sizeof(int));
-        for(i = 0; i < nCols; i ++)
+        for( unsigned short i = 0; i < nCols; i++ )
         {
             paeFieldTypes[i] = -1;
         }
@@ -231,15 +227,16 @@ OGRFeatureDefn * OGRXLSLayer::GetLayerDefn()
         if (!EQUAL(pszXLSFieldTypes, "STRING"))
             DetectColumnTypes(xlshandle, paeFieldTypes);
 
-        for(i = 0; i < nCols; i ++)
+        for( unsigned short i = 0; i < nCols; i++ )
         {
             OGRFieldType eType = (OGRFieldType) paeFieldTypes[i];
             if (paeFieldTypes[i] < 0)
                 eType = OFTString;
-            if (bFirstLineIsHeaders &&
-                freexl_get_cell_value(xlshandle, 0, i, &sCellValue) == FREEXL_OK &&
+            if( bFirstLineIsHeaders &&
+                freexl_get_cell_value(xlshandle,
+                                      0, i, &sCellValue) == FREEXL_OK &&
                 (sCellValue.type == FREEXL_CELL_TEXT ||
-                 sCellValue.type == FREEXL_CELL_SST_TEXT))
+                 sCellValue.type == FREEXL_CELL_SST_TEXT) )
             {
                 OGRFieldDefn oField(sCellValue.value.text_value, eType);
                 poFeatureDefn->AddFieldDefn(&oField);
@@ -252,7 +249,6 @@ OGRFeatureDefn * OGRXLSLayer::GetLayerDefn()
         }
 
         CPLFree(paeFieldTypes);
-
     }
 
     ResetReading();
@@ -266,7 +262,7 @@ OGRFeatureDefn * OGRXLSLayer::GetLayerDefn()
 
 GIntBig OGRXLSLayer::GetFeatureCount( int bForce )
 {
-    if  ( m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */ )
+    if( m_poAttrQuery == NULL /* && m_poFilterGeom == NULL */ )
     {
         const char* pszXLSHeaders = CPLGetConfigOption("OGR_XLS_HEADERS", "");
         if(EQUAL(pszXLSHeaders, "DISABLE"))
@@ -287,11 +283,9 @@ OGRFeature *OGRXLSLayer::GetNextFeature()
 {
     GetLayerDefn();
 
-    OGRFeature  *poFeature;
-
     while( true )
     {
-        poFeature = GetNextRawFeature();
+        OGRFeature *poFeature = GetNextRawFeature();
         if (poFeature == NULL)
             return NULL;
 
@@ -373,4 +367,3 @@ int OGRXLSLayer::TestCapability( const char * pszCap )
 
     return FALSE;
 }
-
diff --git a/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h b/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
index d3c5885..8f70cc5 100644
--- a/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
+++ b/ogr/ogrsf_frmts/xlsx/ogr_xlsx.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xlsx.h 35710 2016-10-13 07:21:17Z rouault $
+ * $Id: ogr_xlsx.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Definition of classes for OGR OpenOfficeSpreadsheet .xlsx driver.
@@ -49,69 +49,69 @@ class OGRXLSXDataSource;
 
 class OGRXLSXLayer : public OGRMemLayer
 {
-    int                bInit;
+    bool               bInit;
     OGRXLSXDataSource* poDS;
     CPLString          osFilename;
     void               Init();
-    int                bUpdated;
-    int                bHasHeaderLine;
+    bool               bUpdated;
+    bool               bHasHeaderLine;
 
-    public:
+  public:
         OGRXLSXLayer( OGRXLSXDataSource* poDSIn,
                       const char * pszFilename,
                       const char * pszName,
                       int bUpdateIn = FALSE);
 
-    int                 HasBeenUpdated() { return bUpdated; }
-    void                SetUpdated(int bUpdatedIn = TRUE);
+    bool                HasBeenUpdated() const { return bUpdated; }
+    void                SetUpdated( bool bUpdatedIn = true );
 
-    int                 GetHasHeaderLine() { return bHasHeaderLine; }
-    void                SetHasHeaderLine(int bIn) { bHasHeaderLine = bIn; }
+    bool                GetHasHeaderLine() const { return bHasHeaderLine; }
+    void                SetHasHeaderLine( bool bIn ) { bHasHeaderLine = bIn; }
 
-    const char         *GetName() { return OGRMemLayer::GetLayerDefn()->GetName(); };
-    OGRwkbGeometryType  GetGeomType() { return wkbNone; }
-    virtual OGRSpatialReference *GetSpatialRef() { return NULL; }
+    const char         *GetName() override { return OGRMemLayer::GetLayerDefn()->GetName(); };
+    OGRwkbGeometryType  GetGeomType() override { return wkbNone; }
+    virtual OGRSpatialReference *GetSpatialRef() override { return NULL; }
 
-    void                ResetReading()
+    void                ResetReading() override
     { Init(); OGRMemLayer::ResetReading(); }
 
     const CPLString&    GetFilename() const { return osFilename; }
 
     /* For external usage. Mess with FID */
-    virtual OGRFeature *        GetNextFeature();
-    virtual OGRFeature         *GetFeature( GIntBig nFeatureId );
-    virtual OGRErr              ISetFeature( OGRFeature *poFeature );
-    virtual OGRErr              DeleteFeature( GIntBig nFID );
+    virtual OGRFeature *        GetNextFeature() override;
+    virtual OGRFeature         *GetFeature( GIntBig nFeatureId ) override;
+    virtual OGRErr              ISetFeature( OGRFeature *poFeature ) override;
+    virtual OGRErr              DeleteFeature( GIntBig nFID ) override;
 
-    virtual OGRErr      SetNextByIndex( GIntBig nIndex )
+    virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override
     { Init(); return OGRMemLayer::SetNextByIndex(nIndex); }
 
-    OGRErr              ICreateFeature( OGRFeature *poFeature )
+    OGRErr              ICreateFeature( OGRFeature *poFeature ) override
     { Init(); SetUpdated(); return OGRMemLayer::ICreateFeature(poFeature); }
 
-    OGRFeatureDefn *    GetLayerDefn()
+    OGRFeatureDefn *    GetLayerDefn() override
     { Init(); return OGRMemLayer::GetLayerDefn(); }
 
-    GIntBig                 GetFeatureCount( int bForce )
+    GIntBig                 GetFeatureCount( int bForce ) override
     { Init(); return OGRMemLayer::GetFeatureCount(bForce); }
 
     virtual OGRErr      CreateField( OGRFieldDefn *poField,
-                                     int bApproxOK = TRUE )
+                                     int bApproxOK = TRUE ) override
     { Init(); SetUpdated(); return OGRMemLayer::CreateField(poField, bApproxOK); }
 
-    virtual OGRErr      DeleteField( int iField )
+    virtual OGRErr      DeleteField( int iField ) override
     { Init(); SetUpdated(); return OGRMemLayer::DeleteField(iField); }
 
-    virtual OGRErr      ReorderFields( int* panMap )
+    virtual OGRErr      ReorderFields( int* panMap ) override
     { Init(); SetUpdated(); return OGRMemLayer::ReorderFields(panMap); }
 
-    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn )
+    virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlagsIn ) override
     { Init(); SetUpdated(); return OGRMemLayer::AlterFieldDefn(iField, poNewFieldDefn, nFlagsIn); }
 
-    int                 TestCapability( const char * pszCap )
+    int                 TestCapability( const char * pszCap ) override
     { Init(); return OGRMemLayer::TestCapability(pszCap); }
 
-    virtual OGRErr      SyncToDisk();
+    virtual OGRErr      SyncToDisk() override;
 };
 
 /************************************************************************/
@@ -143,19 +143,21 @@ class XLSXFieldTypeExtended
 {
 public:
     OGRFieldType      eType;
-    int               bHasMS;
+    bool              bHasMS;
 
-                    XLSXFieldTypeExtended() : eType(OFTMaxType), bHasMS(FALSE) {}
+                    XLSXFieldTypeExtended() :
+                        eType(OFTMaxType),
+                        bHasMS(false) {}
                     XLSXFieldTypeExtended(OGRFieldType eTypeIn,
-                                          int bHasMSIn = FALSE) :
+                                          bool bHasMSIn = false) :
                                     eType(eTypeIn), bHasMS(bHasMSIn) {}
 };
 
 class OGRXLSXDataSource : public OGRDataSource
 {
     char*               pszName;
-    int                 bUpdatable;
-    int                 bUpdated;
+    bool                bUpdatable;
+    bool                bUpdated;
 
     int                 nLayers;
     OGRLayer          **papoLayers;
@@ -169,11 +171,11 @@ class OGRXLSXDataSource : public OGRDataSource
     std::vector<std::string>  apoSharedStrings;
     std::string         osCurrentString;
 
-    int                 bFirstLineIsHeaders;
+    bool                bFirstLineIsHeaders;
     int                 bAutodetectTypes;
 
     XML_Parser          oParser;
-    int                 bStopParsing;
+    bool                bStopParsing;
     int                 nWithoutEventCounter;
     int                 nDataHandlerCounter;
     int                 nCurLine;
@@ -193,7 +195,7 @@ class OGRXLSXDataSource : public OGRDataSource
     std::vector<std::string>  apoCurLineValues;
     std::vector<std::string>  apoCurLineTypes;
 
-    int                        bInCellXFS;
+    bool                bInCellXFS;
     std::map<int,XLSXFieldTypeExtended> apoMapStyleFormats;
     std::vector<XLSXFieldTypeExtended>  apoStyles;
 
@@ -216,7 +218,7 @@ class OGRXLSXDataSource : public OGRDataSource
 
   public:
                         OGRXLSXDataSource();
-                        ~OGRXLSXDataSource();
+                        virtual ~OGRXLSXDataSource();
 
     int                 Open( const char * pszFilename,
                               VSILFILE* fpWorkbook,
@@ -226,20 +228,20 @@ class OGRXLSXDataSource : public OGRDataSource
                               int bUpdate );
     int                 Create( const char * pszName, char **papszOptions );
 
-    virtual const char*         GetName() { return pszName; }
+    virtual const char*         GetName() override { return pszName; }
 
-    virtual int                 GetLayerCount();
-    virtual OGRLayer*           GetLayer( int );
+    virtual int                 GetLayerCount() override;
+    virtual OGRLayer*           GetLayer( int ) override;
 
-    virtual int                 TestCapability( const char * );
+    virtual int                 TestCapability( const char * ) override;
 
     virtual OGRLayer* ICreateLayer( const char * pszLayerName,
                                 OGRSpatialReference *poSRS,
                                 OGRwkbGeometryType eType,
-                                char ** papszOptions );
-    virtual OGRErr      DeleteLayer(int iLayer);
+                                char ** papszOptions ) override;
+    virtual OGRErr      DeleteLayer(int iLayer) override;
 
-    virtual void        FlushCache();
+    virtual void        FlushCache() override;
 
     void                startElementCbk(const char *pszName, const char **ppszAttr);
     void                endElementCbk(const char *pszName);
@@ -258,8 +260,8 @@ class OGRXLSXDataSource : public OGRDataSource
 
     void                BuildLayer(OGRXLSXLayer* poLayer);
 
-    int                 GetUpdatable() { return bUpdatable; }
-    void                SetUpdated() { bUpdated = TRUE; }
+    bool                GetUpdatable() { return bUpdatable; }
+    void                SetUpdated() { bUpdated = true; }
 };
 
 } /* end of OGRXLSX namespace */
@@ -271,15 +273,15 @@ class OGRXLSXDataSource : public OGRDataSource
 class OGRXLSXDriver : public OGRSFDriver
 {
   public:
-                ~OGRXLSXDriver();
+                virtual ~OGRXLSXDriver();
 
-    virtual const char*         GetName();
-    virtual OGRDataSource*      Open( const char *, int );
-    virtual int                 TestCapability( const char * );
+    virtual const char*         GetName() override;
+    virtual OGRDataSource*      Open( const char *, int ) override;
+    virtual int                 TestCapability( const char * ) override;
 
     virtual OGRDataSource *CreateDataSource( const char *pszName,
-                                             char ** = NULL );
-    virtual OGRErr      DeleteDataSource( const char *pszName );
+                                             char ** = NULL ) override;
+    virtual OGRErr      DeleteDataSource( const char *pszName ) override;
 };
 
 #endif /* ndef OGR_XLSX_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
index 1e45270..340b97a 100644
--- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
+++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrxlsxdatasource.cpp 36555 2016-11-29 22:18:53Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Implements OGRXLSXDataSource class
@@ -31,11 +30,15 @@
 #include "ogr_p.h"
 #include "cpl_conv.h"
 #include "cpl_time.h"
+#include "cpl_vsi_error.h"
 
-CPL_CVSID("$Id: ogrxlsxdatasource.cpp 36555 2016-11-29 22:18:53Z rouault $");
+CPL_CVSID("$Id: ogrxlsxdatasource.cpp 37472 2017-02-26 02:47:45Z goatbar $");
 
 namespace OGRXLSX {
 
+static const int NUMBER_OF_DAYS_BETWEEN_1900_AND_1970 = 25569;
+static const int NUMBER_OF_SECONDS_PER_DAY = 86400;
+
 /************************************************************************/
 /*                            OGRXLSXLayer()                            */
 /************************************************************************/
@@ -43,15 +46,14 @@ namespace OGRXLSX {
 OGRXLSXLayer::OGRXLSXLayer( OGRXLSXDataSource* poDSIn,
                             const char * pszFilename,
                             const char * pszName,
-                            int bUpdatedIn) :
-                                OGRMemLayer(pszName, NULL, wkbNone)
-{
-    bInit = FALSE;
-    osFilename = pszFilename;
-    poDS = poDSIn;
-    bUpdated = bUpdatedIn;
-    bHasHeaderLine = FALSE;
-}
+                            int bUpdatedIn ) :
+    OGRMemLayer(pszName, NULL, wkbNone),
+    bInit(false),
+    poDS(poDSIn),
+    osFilename(pszFilename),
+    bUpdated(CPL_TO_BOOL(bUpdatedIn)),
+    bHasHeaderLine(false)
+{}
 
 /************************************************************************/
 /*                              Init()                                  */
@@ -59,9 +61,9 @@ OGRXLSXLayer::OGRXLSXLayer( OGRXLSXDataSource* poDSIn,
 
 void OGRXLSXLayer::Init()
 {
-    if (!bInit)
+    if( !bInit )
     {
-        bInit = TRUE;
+        bInit = true;
         CPLDebug("XLSX", "Init(%s)", GetName());
         poDS->BuildLayer(this);
     }
@@ -71,16 +73,16 @@ void OGRXLSXLayer::Init()
 /*                             Updated()                                */
 /************************************************************************/
 
-void OGRXLSXLayer::SetUpdated(int bUpdatedIn)
+void OGRXLSXLayer::SetUpdated( bool bUpdatedIn )
 {
     if (bUpdatedIn && !bUpdated && poDS->GetUpdatable())
     {
-        bUpdated = TRUE;
+        bUpdated = true;
         poDS->SetUpdated();
     }
-    else if (bUpdated && !bUpdatedIn)
+    else if( bUpdated && !bUpdatedIn )
     {
-        bUpdated = FALSE;
+        bUpdated = false;
     }
 }
 
@@ -103,7 +105,8 @@ OGRFeature* OGRXLSXLayer::GetNextFeature()
     Init();
     OGRFeature* poFeature = OGRMemLayer::GetNextFeature();
     if (poFeature)
-        poFeature->SetFID(poFeature->GetFID() + 1 + bHasHeaderLine);
+        poFeature->SetFID(poFeature->GetFID() +
+                          1 + static_cast<int>(bHasHeaderLine));
     return poFeature;
 }
 
@@ -114,7 +117,9 @@ OGRFeature* OGRXLSXLayer::GetNextFeature()
 OGRFeature* OGRXLSXLayer::GetFeature( GIntBig nFeatureId )
 {
     Init();
-    OGRFeature* poFeature = OGRMemLayer::GetFeature(nFeatureId - (1 + bHasHeaderLine));
+    OGRFeature* poFeature =
+        OGRMemLayer::GetFeature(nFeatureId -
+                                (1 + static_cast<int>(bHasHeaderLine)));
     if (poFeature)
         poFeature->SetFID(nFeatureId);
     return poFeature;
@@ -132,7 +137,7 @@ OGRErr OGRXLSXLayer::ISetFeature( OGRFeature *poFeature )
 
     GIntBig nFID = poFeature->GetFID();
     if (nFID != OGRNullFID)
-        poFeature->SetFID(nFID - (1 + bHasHeaderLine));
+        poFeature->SetFID(nFID - (1 + static_cast<int>(bHasHeaderLine)));
     SetUpdated();
     OGRErr eErr = OGRMemLayer::ISetFeature(poFeature);
     poFeature->SetFID(nFID);
@@ -147,42 +152,36 @@ OGRErr OGRXLSXLayer::DeleteFeature( GIntBig nFID )
 {
     Init();
     SetUpdated();
-    return OGRMemLayer::DeleteFeature(nFID - (1 + bHasHeaderLine));
+    return OGRMemLayer::DeleteFeature(nFID -
+                                      (1 + static_cast<int>(bHasHeaderLine)));
 }
 
 /************************************************************************/
 /*                          OGRXLSXDataSource()                         */
 /************************************************************************/
 
-OGRXLSXDataSource::OGRXLSXDataSource()
-
+OGRXLSXDataSource::OGRXLSXDataSource() :
+    pszName(NULL),
+    bUpdatable(false),
+    bUpdated(false),
+    nLayers(0),
+    papoLayers(NULL),
+    bFirstLineIsHeaders(false),
+    bAutodetectTypes(!EQUAL(CPLGetConfigOption("OGR_XLSX_FIELD_TYPES", ""),
+                            "STRING")),
+    oParser(NULL),
+    bStopParsing(false),
+    nWithoutEventCounter(0),
+    nDataHandlerCounter(0),
+    nCurLine(0),
+    nCurCol(0),
+    poCurLayer(NULL),
+    nStackDepth(0),
+    nDepth(0),
+    bInCellXFS(false)
 {
-    pszName = NULL;
-    bUpdatable = FALSE;
-    bUpdated = FALSE;
-
-    nLayers = 0;
-    papoLayers = NULL;
-
-    bFirstLineIsHeaders = FALSE;
-
-    oParser = NULL;
-    bStopParsing = FALSE;
-    nWithoutEventCounter = 0;
-    nDataHandlerCounter = 0;
-    nStackDepth = 0;
-    nDepth = 0;
-    nCurLine = 0;
-    nCurCol = 0;
     stateStack[0].eVal = STATE_DEFAULT;
     stateStack[0].nBeginDepth = 0;
-    bInCellXFS = FALSE;
-
-    poCurLayer = NULL;
-
-    const char* pszXLSXFieldTypes =
-                CPLGetConfigOption("OGR_XLSX_FIELD_TYPES", "");
-    bAutodetectTypes = !EQUAL(pszXLSXFieldTypes, "STRING");
 }
 
 /************************************************************************/
@@ -196,7 +195,7 @@ OGRXLSXDataSource::~OGRXLSXDataSource()
 
     CPLFree( pszName );
 
-    for(int i=0;i<nLayers;i++)
+    for( int i = 0; i < nLayers; i++ )
         delete papoLayers[i];
     CPLFree( papoLayers );
 }
@@ -212,6 +211,8 @@ int OGRXLSXDataSource::TestCapability( const char * pszCap )
         return bUpdatable;
     else if( EQUAL(pszCap,ODsCDeleteLayer) )
         return bUpdatable;
+    else if( EQUAL(pszCap,ODsCRandomLayerWrite) )
+        return bUpdatable;
     else
         return FALSE;
 }
@@ -250,7 +251,7 @@ int OGRXLSXDataSource::Open( const char * pszFilename,
                              int bUpdateIn )
 
 {
-    bUpdatable = bUpdateIn;
+    bUpdatable = CPL_TO_BOOL(bUpdateIn);
 
     pszName = CPLStrdup( pszFilename );
 
@@ -281,8 +282,8 @@ int OGRXLSXDataSource::Open( const char * pszFilename,
 int OGRXLSXDataSource::Create( const char * pszFilename,
                                CPL_UNUSED char **papszOptions )
 {
-    bUpdated = TRUE;
-    bUpdatable = TRUE;
+    bUpdated = true;
+    bUpdatable = true;
 
     pszName = CPLStrdup( pszFilename );
 
@@ -302,7 +303,7 @@ static void XMLCALL startElementCbk(void *pUserData, const char *pszNameIn,
 void OGRXLSXDataSource::startElementCbk(const char *pszNameIn,
                                        const char **ppszAttr)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
     switch(stateStack[nStackDepth].eVal)
@@ -328,7 +329,7 @@ static void XMLCALL endElementCbk(void *pUserData, const char *pszNameIn)
 
 void OGRXLSXDataSource::endElementCbk(const char *pszNameIn)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
 
@@ -358,15 +359,15 @@ static void XMLCALL dataHandlerCbk(void *pUserData, const char *data, int nLen)
 
 void OGRXLSXDataSource::dataHandlerCbk(const char *data, int nLen)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
-    nDataHandlerCounter ++;
-    if (nDataHandlerCounter >= BUFSIZ)
+    nDataHandlerCounter++;
+    if( nDataHandlerCounter >= BUFSIZ )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
@@ -378,7 +379,7 @@ void OGRXLSXDataSource::dataHandlerCbk(const char *data, int nLen)
         case STATE_SHEETDATA:   break;
         case STATE_ROW:     break;
         case STATE_CELL:    break;
-        case STATE_TEXTV:   dataHandlerTextV(data, nLen);
+        case STATE_TEXTV:   dataHandlerTextV(data, nLen); break;
         default:            break;
     }
 }
@@ -391,7 +392,7 @@ void OGRXLSXDataSource::PushState(HandlerStateEnum eVal)
 {
     if (nStackDepth + 1 == STACK_SIZE)
     {
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
     nStackDepth ++;
@@ -481,8 +482,6 @@ static void SetField(OGRFeature* poFeature,
     {
         struct tm sTm;
         double dfNumberOfDaysSince1900 = CPLAtof(pszValue);
-#define NUMBER_OF_DAYS_BETWEEN_1900_AND_1970        25569
-#define NUMBER_OF_SECONDS_PER_DAY                   86400
         GIntBig nUnixTime = (GIntBig)((dfNumberOfDaysSince1900 -
                                        NUMBER_OF_DAYS_BETWEEN_1900_AND_1970 )*
                                                 NUMBER_OF_SECONDS_PER_DAY);
@@ -525,22 +524,22 @@ static void SetField(OGRFeature* poFeature,
 void OGRXLSXDataSource::DetectHeaderLine()
 
 {
-    int bHeaderLineCandidate = TRUE;
-    size_t i;
-    for(i = 0; i < apoFirstLineTypes.size(); i++)
+    bool bHeaderLineCandidate = true;
+
+    for( size_t i = 0; i < apoFirstLineTypes.size(); i++ )
     {
         if (apoFirstLineTypes[i] != "string")
         {
             /* If the values in the first line are not text, then it is */
             /* not a header line */
-            bHeaderLineCandidate = FALSE;
+            bHeaderLineCandidate = false;
             break;
         }
     }
 
     size_t nCountTextOnCurLine = 0;
     size_t nCountNonEmptyOnCurLine = 0;
-    for(i = 0; bHeaderLineCandidate && i < apoCurLineTypes.size(); i++)
+    for( size_t i = 0; bHeaderLineCandidate && i < apoCurLineTypes.size(); i++ )
     {
         if (apoCurLineTypes[i] == "string")
         {
@@ -555,18 +554,18 @@ void OGRXLSXDataSource::DetectHeaderLine()
     }
 
     const char* pszXLSXHeaders = CPLGetConfigOption("OGR_XLSX_HEADERS", "");
-    bFirstLineIsHeaders = FALSE;
+    bFirstLineIsHeaders = false;
     if (EQUAL(pszXLSXHeaders, "FORCE"))
-        bFirstLineIsHeaders = TRUE;
+        bFirstLineIsHeaders = true;
     else if (EQUAL(pszXLSXHeaders, "DISABLE"))
-        bFirstLineIsHeaders = FALSE;
-    else if (bHeaderLineCandidate &&
-             apoFirstLineTypes.size() != 0 &&
+        bFirstLineIsHeaders = false;
+    else if( bHeaderLineCandidate &&
+             !apoFirstLineTypes.empty() &&
              apoFirstLineTypes.size() == apoCurLineTypes.size() &&
              nCountTextOnCurLine != apoFirstLineTypes.size() &&
-             nCountNonEmptyOnCurLine != 0)
+             nCountNonEmptyOnCurLine != 0 )
     {
-        bFirstLineIsHeaders = TRUE;
+        bFirstLineIsHeaders = true;
     }
     CPLDebug("XLSX", "%s %s",
              poCurLayer->GetName(),
@@ -626,15 +625,14 @@ void OGRXLSXDataSource::endElementTable(CPL_UNUSED const char *pszNameIn)
         CPLAssert(strcmp(pszNameIn, "sheetData") == 0);
 
         if (nCurLine == 0 ||
-            (nCurLine == 1 && apoFirstLineValues.size() == 0))
+            (nCurLine == 1 && apoFirstLineValues.empty()))
         {
             /* We could remove empty sheet, but too late now */
         }
         else if (nCurLine == 1)
         {
             /* If we have only one single line in the sheet */
-            size_t i;
-            for(i = 0; i < apoFirstLineValues.size(); i++)
+            for( size_t i = 0; i < apoFirstLineValues.size(); i++ )
             {
                 const char* pszFieldName = CPLSPrintf("Field%d", (int)i + 1);
                 OGRFieldType eType = GetOGRFieldType(apoFirstLineValues[i].c_str(),
@@ -644,7 +642,7 @@ void OGRXLSXDataSource::endElementTable(CPL_UNUSED const char *pszNameIn)
             }
 
             OGRFeature* poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
-            for(i = 0; i < apoFirstLineValues.size(); i++)
+            for( size_t i = 0; i < apoFirstLineValues.size(); i++ )
             {
                 SetField(poFeature, static_cast<int>(i), apoFirstLineValues[i].c_str(),
                          apoFirstLineTypes[i].c_str());
@@ -656,8 +654,8 @@ void OGRXLSXDataSource::endElementTable(CPL_UNUSED const char *pszNameIn)
         if (poCurLayer)
         {
             ((OGRMemLayer*)poCurLayer)->SetUpdatable(CPL_TO_BOOL(bUpdatable));
-            ((OGRMemLayer*)poCurLayer)->SetAdvertizeUTF8(TRUE);
-            ((OGRXLSXLayer*)poCurLayer)->SetUpdated(FALSE);
+            ((OGRMemLayer*)poCurLayer)->SetAdvertizeUTF8(true);
+            ((OGRXLSXLayer*)poCurLayer)->SetUpdated(false);
         }
 
         poCurLayer = NULL;
@@ -740,9 +738,6 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
     {
         CPLAssert(strcmp(pszNameIn, "row") == 0);
 
-        OGRFeature* poFeature;
-        size_t i;
-
         /* Backup first line values and types in special arrays */
         if (nCurLine == 0)
         {
@@ -750,7 +745,7 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
             apoFirstLineValues = apoCurLineValues;
 
     #if skip_leading_empty_rows
-            if (apoFirstLineTypes.size() == 0)
+            if (apoFirstLineTypes.empty())
             {
                 /* Skip leading empty rows */
                 apoFirstLineTypes.resize(0);
@@ -766,9 +761,9 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
 
             poCurLayer->SetHasHeaderLine(bFirstLineIsHeaders);
 
-            if (bFirstLineIsHeaders)
+            if( bFirstLineIsHeaders )
             {
-                for(i = 0; i < apoFirstLineValues.size(); i++)
+                for( size_t i = 0; i < apoFirstLineValues.size(); i++ )
                 {
                     const char* pszFieldName = apoFirstLineValues[i].c_str();
                     if (pszFieldName[0] == '\0')
@@ -785,7 +780,7 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
             }
             else
             {
-                for(i = 0; i < apoFirstLineValues.size(); i++)
+                for( size_t i = 0; i < apoFirstLineValues.size(); i++ )
                 {
                     const char* pszFieldName =
                         CPLSPrintf("Field%d", (int)i + 1);
@@ -796,8 +791,8 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
                     poCurLayer->CreateField(&oFieldDefn);
                 }
 
-                poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
-                for(i = 0; i < apoFirstLineValues.size(); i++)
+                OGRFeature* poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
+                for( size_t i = 0; i < apoFirstLineValues.size(); i++ )
                 {
                     SetField(poFeature, static_cast<int>(i), apoFirstLineValues[i].c_str(),
                              apoFirstLineTypes[i].c_str());
@@ -813,9 +808,9 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
             if (apoCurLineValues.size() >
                 (size_t)poCurLayer->GetLayerDefn()->GetFieldCount())
             {
-                for(i = (size_t)poCurLayer->GetLayerDefn()->GetFieldCount();
-                    i < apoCurLineValues.size();
-                    i++)
+                for( size_t i = (size_t)poCurLayer->GetLayerDefn()->GetFieldCount();
+                     i < apoCurLineValues.size();
+                     i++ )
                 {
                     const char* pszFieldName =
                         CPLSPrintf("Field%d", (int)i + 1);
@@ -830,9 +825,9 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
             /* Update field type if necessary */
             if (bAutodetectTypes)
             {
-                for(i = 0; i < apoCurLineValues.size(); i++)
+                for( size_t i = 0; i < apoCurLineValues.size(); i++ )
                 {
-                    if (apoCurLineValues[i].size())
+                    if (!apoCurLineValues[i].empty() )
                     {
                         OGRFieldType eValType = GetOGRFieldType(
                                                 apoCurLineValues[i].c_str(),
@@ -874,8 +869,8 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
             }
 
             /* Add feature for current line */
-            poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
-            for(i = 0; i < apoCurLineValues.size(); i++)
+            OGRFeature* poFeature = new OGRFeature(poCurLayer->GetLayerDefn());
+            for( size_t i = 0; i < apoCurLineValues.size(); i++ )
             {
                 SetField(poFeature, static_cast<int>(i), apoCurLineValues[i].c_str(),
                          apoCurLineTypes[i].c_str());
@@ -895,11 +890,11 @@ void OGRXLSXDataSource::endElementRow(CPL_UNUSED const char *pszNameIn)
 void OGRXLSXDataSource::startElementCell(const char *pszNameIn,
                                          CPL_UNUSED const char **ppszAttr)
 {
-    if (osValue.size() == 0 && strcmp(pszNameIn, "v") == 0)
+    if (osValue.empty() && strcmp(pszNameIn, "v") == 0)
     {
         PushState(STATE_TEXTV);
     }
-    else if (osValue.size() == 0 && strcmp(pszNameIn, "t") == 0)
+    else if (osValue.empty() && strcmp(pszNameIn, "t") == 0)
     {
         PushState(STATE_TEXTV);
     }
@@ -945,7 +940,7 @@ void OGRXLSXDataSource::dataHandlerTextV(const char *data, int nLen)
 /*                              BuildLayer()                            */
 /************************************************************************/
 
-void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer)
+void OGRXLSXDataSource::BuildLayer( OGRXLSXLayer* poLayer )
 {
     poCurLayer = poLayer;
 
@@ -958,7 +953,7 @@ void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer)
         return;
     }
 
-    int bUpdatedBackup = bUpdated;
+    const bool bUpdatedBackup = bUpdated;
 
     oParser = OGRCreateExpatXMLParser();
     XML_SetElementHandler(oParser, OGRXLSX::startElementCbk, OGRXLSX::endElementCbk);
@@ -967,7 +962,7 @@ void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer)
 
     VSIFSeekL( fp, 0, SEEK_SET );
 
-    bStopParsing = FALSE;
+    bStopParsing = false;
     nWithoutEventCounter = 0;
     nDataHandlerCounter = 0;
     nStackDepth = 0;
@@ -976,7 +971,7 @@ void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer)
     stateStack[0].nBeginDepth = 0;
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -991,10 +986,10 @@ void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer)
                      XML_ErrorString(XML_GetErrorCode(oParser)),
                      (int)XML_GetCurrentLineNumber(oParser),
                      (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
         nWithoutEventCounter ++;
-    } while (!nDone && !bStopParsing && nWithoutEventCounter < 10);
+    } while( !nDone && !bStopParsing && nWithoutEventCounter < 10 );
 
     XML_ParserFree(oParser);
     oParser = NULL;
@@ -1003,7 +998,7 @@ void OGRXLSXDataSource::BuildLayer(OGRXLSXLayer* poLayer)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
 
     VSIFCloseL(fp);
@@ -1024,7 +1019,7 @@ static void XMLCALL startElementSSCbk(void *pUserData, const char *pszNameIn,
 void OGRXLSXDataSource::startElementSSCbk(const char *pszNameIn,
                                           CPL_UNUSED const char **ppszAttr)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
     switch(stateStack[nStackDepth].eVal)
@@ -1055,7 +1050,7 @@ static void XMLCALL endElementSSCbk(void *pUserData, const char *pszNameIn)
 
 void OGRXLSXDataSource::endElementSSCbk(CPL_UNUSED const char *pszNameIn)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
 
@@ -1089,7 +1084,7 @@ static void XMLCALL dataHandlerSSCbk(void *pUserData, const char *data, int nLen
 
 void OGRXLSXDataSource::dataHandlerSSCbk(const char *data, int nLen)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nDataHandlerCounter ++;
     if (nDataHandlerCounter >= BUFSIZ)
@@ -1097,7 +1092,7 @@ void OGRXLSXDataSource::dataHandlerSSCbk(const char *data, int nLen)
         CPLError(CE_Failure, CPLE_AppDefined,
                  "File probably corrupted (million laugh pattern)");
         XML_StopParser(oParser, XML_FALSE);
-        bStopParsing = TRUE;
+        bStopParsing = true;
         return;
     }
 
@@ -1127,7 +1122,7 @@ void OGRXLSXDataSource::AnalyseSharedStrings(VSILFILE* fpSharedStrings)
 
     VSIFSeekL( fpSharedStrings, 0, SEEK_SET );
 
-    bStopParsing = FALSE;
+    bStopParsing = false;
     nWithoutEventCounter = 0;
     nDataHandlerCounter = 0;
     nStackDepth = 0;
@@ -1136,7 +1131,7 @@ void OGRXLSXDataSource::AnalyseSharedStrings(VSILFILE* fpSharedStrings)
     stateStack[0].nBeginDepth = 0;
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -1151,10 +1146,10 @@ void OGRXLSXDataSource::AnalyseSharedStrings(VSILFILE* fpSharedStrings)
                      XML_ErrorString(XML_GetErrorCode(oParser)),
                      (int)XML_GetCurrentLineNumber(oParser),
                      (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
         nWithoutEventCounter ++;
-    } while (!nDone && !bStopParsing && nWithoutEventCounter < 10);
+    } while( !nDone && !bStopParsing && nWithoutEventCounter < 10 );
 
     XML_ParserFree(oParser);
     oParser = NULL;
@@ -1163,14 +1158,12 @@ void OGRXLSXDataSource::AnalyseSharedStrings(VSILFILE* fpSharedStrings)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
 
     VSIFCloseL(fpSharedStrings);
-    fpSharedStrings = NULL;
 }
 
-
 /************************************************************************/
 /*                        startElementWBRelsCbk()                       */
 /************************************************************************/
@@ -1263,7 +1256,7 @@ static void XMLCALL startElementWBCbk(void *pUserData, const char *pszNameIn,
 void OGRXLSXDataSource::startElementWBCbk(const char *pszNameIn,
                                        const char **ppszAttr)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
     if (strcmp(pszNameIn,"sheet") == 0)
@@ -1278,7 +1271,7 @@ void OGRXLSXDataSource::startElementWBCbk(const char *pszNameIn,
             if( !oMapRelsIdToTarget[pszId].empty() &&
                 oMapRelsIdToTarget[pszId][0] == '/' )
             {
-                // Is it an "absolute" path ? 
+                // Is it an "absolute" path ?
                 osFilename = "/vsizip/" + CPLString(pszName) +
                              oMapRelsIdToTarget[pszId];
             }
@@ -1306,12 +1299,12 @@ void OGRXLSXDataSource::AnalyseWorkbook(VSILFILE* fpWorkbook)
 
     VSIFSeekL( fpWorkbook, 0, SEEK_SET );
 
-    bStopParsing = FALSE;
+    bStopParsing = false;
     nWithoutEventCounter = 0;
     nDataHandlerCounter = 0;
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -1326,10 +1319,10 @@ void OGRXLSXDataSource::AnalyseWorkbook(VSILFILE* fpWorkbook)
                      XML_ErrorString(XML_GetErrorCode(oParser)),
                      (int)XML_GetCurrentLineNumber(oParser),
                      (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
         nWithoutEventCounter ++;
-    } while (!nDone && !bStopParsing && nWithoutEventCounter < 10);
+    } while( !nDone && !bStopParsing && nWithoutEventCounter < 10 );
 
     XML_ParserFree(oParser);
     oParser = NULL;
@@ -1338,13 +1331,12 @@ void OGRXLSXDataSource::AnalyseWorkbook(VSILFILE* fpWorkbook)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
 
     VSIFCloseL(fpWorkbook);
 }
 
-
 /************************************************************************/
 /*                       startElementStylesCbk()                        */
 /************************************************************************/
@@ -1358,7 +1350,7 @@ static void XMLCALL startElementStylesCbk(void *pUserData, const char *pszNameIn
 void OGRXLSXDataSource::startElementStylesCbk(const char *pszNameIn,
                                        const char **ppszAttr)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
     if (strcmp(pszNameIn,"numFmt") == 0)
@@ -1382,11 +1374,11 @@ void OGRXLSXDataSource::startElementStylesCbk(const char *pszNameIn,
                 apoMapStyleFormats[nNumFmtId] = XLSXFieldTypeExtended(OFTReal);
         }
     }
-    else if (strcmp(pszNameIn,"cellXfs") == 0)
+    else if( strcmp(pszNameIn,"cellXfs") == 0 )
     {
-        bInCellXFS = TRUE;
+        bInCellXFS = true;
     }
-    else if (bInCellXFS && strcmp(pszNameIn,"xf") == 0)
+    else if( bInCellXFS && strcmp(pszNameIn,"xf") == 0 )
     {
         const char* pszNumFmtId = GetAttributeValue(ppszAttr, "numFmtId", "-1");
         int nNumFmtId = atoi(pszNumFmtId);
@@ -1412,7 +1404,10 @@ void OGRXLSXDataSource::startElementStylesCbk(const char *pszNameIn,
                     CPLDebug("XLSX", "Cannot find entry in <numFmts> with numFmtId=%d", nNumFmtId);
             }
         }
-        //printf("style[%d] = %d\n", apoStyles.size(), eType);
+#if DEBUG_VERBOSE
+        printf("style[%lu] = %d\n",/*ok*/
+               apoStyles.size(), static_cast<int>(eType.eType));
+#endif
 
         apoStyles.push_back(eType);
     }
@@ -1429,12 +1424,12 @@ static void XMLCALL endElementStylesCbk(void *pUserData, const char *pszNameIn)
 
 void OGRXLSXDataSource::endElementStylesCbk(const char *pszNameIn)
 {
-    if (bStopParsing) return;
+    if( bStopParsing ) return;
 
     nWithoutEventCounter = 0;
     if (strcmp(pszNameIn,"cellXfs") == 0)
     {
-        bInCellXFS = FALSE;
+        bInCellXFS = false;
     }
 }
 
@@ -1453,13 +1448,13 @@ void OGRXLSXDataSource::AnalyseStyles(VSILFILE* fpStyles)
 
     VSIFSeekL( fpStyles, 0, SEEK_SET );
 
-    bStopParsing = FALSE;
+    bStopParsing = false;
     nWithoutEventCounter = 0;
     nDataHandlerCounter = 0;
-    bInCellXFS = FALSE;
+    bInCellXFS = false;
 
     char aBuf[BUFSIZ];
-    int nDone;
+    int nDone = 0;
     do
     {
         nDataHandlerCounter = 0;
@@ -1474,10 +1469,10 @@ void OGRXLSXDataSource::AnalyseStyles(VSILFILE* fpStyles)
                      XML_ErrorString(XML_GetErrorCode(oParser)),
                      (int)XML_GetCurrentLineNumber(oParser),
                      (int)XML_GetCurrentColumnNumber(oParser));
-            bStopParsing = TRUE;
+            bStopParsing = true;
         }
         nWithoutEventCounter ++;
-    } while (!nDone && !bStopParsing && nWithoutEventCounter < 10);
+    } while( !nDone && !bStopParsing && nWithoutEventCounter < 10 );
 
     XML_ParserFree(oParser);
     oParser = NULL;
@@ -1486,7 +1481,7 @@ void OGRXLSXDataSource::AnalyseStyles(VSILFILE* fpStyles)
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Too much data inside one element. File probably corrupted");
-        bStopParsing = TRUE;
+        bStopParsing = true;
     }
 
     VSIFCloseL(fpStyles);
@@ -1520,9 +1515,7 @@ OGRXLSXDataSource::ICreateLayer( const char * pszLayerName,
 /*      Do we already have this layer?  If so, should we blow it        */
 /*      away?                                                           */
 /* -------------------------------------------------------------------- */
-    int iLayer;
-
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     {
         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetName()) )
         {
@@ -1554,7 +1547,7 @@ OGRXLSXDataSource::ICreateLayer( const char * pszLayerName,
     papoLayers[nLayers] = poLayer;
     nLayers ++;
 
-    bUpdated = TRUE;
+    bUpdated = true;
 
     return poLayer;
 }
@@ -1566,8 +1559,6 @@ OGRXLSXDataSource::ICreateLayer( const char * pszLayerName,
 void OGRXLSXDataSource::DeleteLayer( const char *pszLayerName )
 
 {
-    int iLayer;
-
 /* -------------------------------------------------------------------- */
 /*      Verify we are in update mode.                                   */
 /* -------------------------------------------------------------------- */
@@ -1584,9 +1575,10 @@ void OGRXLSXDataSource::DeleteLayer( const char *pszLayerName )
 /* -------------------------------------------------------------------- */
 /*      Try to find layer.                                              */
 /* -------------------------------------------------------------------- */
-    for( iLayer = 0; iLayer < nLayers; iLayer++ )
+    int iLayer = 0;
+    for( ; iLayer < nLayers; iLayer++ )
     {
-        if( EQUAL(pszLayerName,papoLayers[iLayer]->GetName()) )
+        if( EQUAL(pszLayerName, papoLayers[iLayer]->GetName()) )
             break;
     }
 
@@ -1625,7 +1617,7 @@ OGRErr OGRXLSXDataSource::DeleteLayer(int iLayer)
              sizeof(void *) * (nLayers - iLayer - 1) );
     nLayers--;
 
-    bUpdated = TRUE;
+    bUpdated = true;
 
     return OGRERR_NONE;
 }
@@ -1634,18 +1626,24 @@ OGRErr OGRXLSXDataSource::DeleteLayer(int iLayer)
 /*                            WriteOverride()                           */
 /************************************************************************/
 
-static void WriteOverride(VSILFILE* fp, const char* pszPartName, const char* pszContentType)
+static void WriteOverride( VSILFILE* fp, const char* pszPartName,
+                           const char* pszContentType )
 {
     VSIFPrintfL(fp, "<Override PartName=\"%s\" ContentType=\"%s\"/>\n",
                 pszPartName, pszContentType);
 }
 
-#define XML_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-#define MAIN_NS "xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\""
-#define SCHEMA_OD "http://schemas.openxmlformats.org/officeDocument/2006"
-#define SCHEMA_OD_RS "http://schemas.openxmlformats.org/officeDocument/2006/relationships"
-#define SCHEMA_PACKAGE "http://schemas.openxmlformats.org/package/2006"
-#define SCHEMA_PACKAGE_RS "http://schemas.openxmlformats.org/package/2006/relationships"
+static const char XML_HEADER[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+static const char MAIN_NS[] =
+    "xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"";
+static const char SCHEMA_OD[] =
+    "http://schemas.openxmlformats.org/officeDocument/2006";
+static const char SCHEMA_OD_RS[] =
+    "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
+static const char SCHEMA_PACKAGE[] =
+    "http://schemas.openxmlformats.org/package/2006";
+static const char SCHEMA_PACKAGE_RS[] =
+    "http://schemas.openxmlformats.org/package/2006/relationships";
 
 /************************************************************************/
 /*                           WriteContentTypes()                        */
@@ -1653,10 +1651,11 @@ static void WriteOverride(VSILFILE* fp, const char* pszPartName, const char* psz
 
 static void WriteContentTypes(const char* pszName, int nLayers)
 {
-    VSILFILE* fp;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/[Content_Types].xml", pszName), "wb");
-    VSIFPrintfL(fp, XML_HEADER);
+    VSILFILE* fp =
+        VSIFOpenL(CPLSPrintf("/vsizip/%s/[Content_Types].xml", pszName), "wb");
+    // TODO(schwehr): Convert all strlen(XML_HEADER) to constexpr with
+    // switch to C++11 or newer.
+    VSIFWriteL(XML_HEADER, strlen(XML_HEADER), 1, fp);
     VSIFPrintfL(fp, "<Types xmlns=\"%s/content-types\">\n", SCHEMA_PACKAGE);
     WriteOverride(fp, "/_rels/.rels", "application/vnd.openxmlformats-package.relationships+xml");
     WriteOverride(fp, "/docProps/core.xml", "application/vnd.openxmlformats-package.core-properties+xml");
@@ -1680,10 +1679,9 @@ static void WriteContentTypes(const char* pszName, int nLayers)
 
 static void WriteApp(const char* pszName)
 {
-    VSILFILE* fp;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/docProps/app.xml", pszName), "wb");
-    VSIFPrintfL(fp, XML_HEADER);
+    VSILFILE* fp =
+        VSIFOpenL(CPLSPrintf("/vsizip/%s/docProps/app.xml", pszName), "wb");
+    VSIFWriteL(XML_HEADER, strlen(XML_HEADER), 1, fp);
     VSIFPrintfL(fp, "<Properties xmlns=\"%s/extended-properties\" "
                     "xmlns:vt=\"%s/docPropsVTypes\">\n", SCHEMA_OD, SCHEMA_OD);
     VSIFPrintfL(fp, "<TotalTime>0</TotalTime>\n");
@@ -1697,10 +1695,9 @@ static void WriteApp(const char* pszName)
 
 static void WriteCore(const char* pszName)
 {
-    VSILFILE* fp;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/docProps/core.xml", pszName), "wb");
-    VSIFPrintfL(fp, XML_HEADER);
+    VSILFILE* fp =
+        VSIFOpenL(CPLSPrintf("/vsizip/%s/docProps/core.xml", pszName), "wb");
+    VSIFWriteL(XML_HEADER, strlen(XML_HEADER), 1, fp);
     VSIFPrintfL(fp, "<cp:coreProperties xmlns:cp=\"%s/metadata/core-properties\" "
                     "xmlns:dc=\"http://purl.org/dc/elements/1.1/\" "
                     "xmlns:dcmitype=\"http://purl.org/dc/dcmitype/\" "
@@ -1717,10 +1714,9 @@ static void WriteCore(const char* pszName)
 
 static void WriteWorkbook(const char* pszName, OGRDataSource* poDS)
 {
-    VSILFILE* fp;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/workbook.xml", pszName), "wb");
-    VSIFPrintfL(fp, XML_HEADER);
+    VSILFILE* fp =
+        VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/workbook.xml", pszName), "wb");
+    VSIFWriteL(XML_HEADER, strlen(XML_HEADER), 1, fp);
     VSIFPrintfL(fp, "<workbook %s xmlns:r=\"%s\">\n", MAIN_NS, SCHEMA_OD_RS);
     VSIFPrintfL(fp, "<fileVersion appName=\"Calc\"/>\n");
     /*
@@ -1784,11 +1780,10 @@ static void WriteLayer(const char* pszName, OGRLayer* poLayer, int iLayer,
                        std::map<std::string,int>& oStringMap,
                        std::vector<std::string>& oStringList)
 {
-    VSILFILE* fp;
-    int j;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/worksheets/sheet%d.xml", pszName, iLayer + 1), "wb");
-    VSIFPrintfL(fp, XML_HEADER);
+    VSILFILE* fp =
+        VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/worksheets/sheet%d.xml",
+                             pszName, iLayer + 1), "wb");
+    VSIFWriteL(XML_HEADER, strlen(XML_HEADER), 1, fp);
     VSIFPrintfL(fp, "<worksheet %s xmlns:r=\"%s\">\n", MAIN_NS, SCHEMA_OD_RS);
     /*
     VSIFPrintfL(fp, "<sheetViews>\n");
@@ -1803,11 +1798,11 @@ static void WriteLayer(const char* pszName, OGRLayer* poLayer, int iLayer,
     OGRFeature* poFeature = poLayer->GetNextFeature();
 
     OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();
-    int bHasHeaders = FALSE;
+    bool bHasHeaders = false;
     int iRow = 1;
 
     VSIFPrintfL(fp, "<cols>\n");
-    for(j=0;j<poFDefn->GetFieldCount();j++)
+    for( int j=0;j<poFDefn->GetFieldCount();j++)
     {
         int nWidth = 15;
         if (poFDefn->GetFieldDefn(j)->GetType() == OFTDateTime)
@@ -1817,20 +1812,20 @@ static void WriteLayer(const char* pszName, OGRLayer* poLayer, int iLayer,
 
         if (strcmp(poFDefn->GetFieldDefn(j)->GetNameRef(),
                     CPLSPrintf("Field%d", j+1)) != 0)
-            bHasHeaders = TRUE;
+            bHasHeaders = true;
     }
     VSIFPrintfL(fp, "</cols>\n");
 
     VSIFPrintfL(fp, "<sheetData>\n");
 
-    if (bHasHeaders && poFeature != NULL)
+    if( bHasHeaders && poFeature != NULL )
     {
         VSIFPrintfL(fp, "<row r=\"%d\">\n", iRow);
-        for(j=0;j<poFDefn->GetFieldCount();j++)
+        for( int j=0;j<poFDefn->GetFieldCount();j++)
         {
             const char* pszVal = poFDefn->GetFieldDefn(j)->GetNameRef();
             std::map<std::string,int>::iterator oIter = oStringMap.find(pszVal);
-            int nStringIndex;
+            int nStringIndex = 0;
             if (oIter != oStringMap.end())
                 nStringIndex = oIter->second;
             else
@@ -1855,9 +1850,9 @@ static void WriteLayer(const char* pszName, OGRLayer* poLayer, int iLayer,
     while(poFeature != NULL)
     {
         VSIFPrintfL(fp, "<row r=\"%d\">\n", iRow);
-        for(j=0;j<poFeature->GetFieldCount();j++)
+        for( int j=0;j<poFeature->GetFieldCount();j++)
         {
-            if (poFeature->IsFieldSet(j))
+            if (poFeature->IsFieldSetAndNotNull(j))
             {
                 char szCol[5];
                 BuildColString(szCol, j);
@@ -1884,8 +1879,13 @@ static void WriteLayer(const char* pszName, OGRLayer* poLayer, int iLayer,
                 }
                 else if (eType == OFTDate || eType == OFTDateTime || eType == OFTTime)
                 {
-                    int nYear, nMonth, nDay, nHour, nMinute, nTZFlag;
-                    float fSecond;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMinute = 0;
+                    int nTZFlag = 0;
+                    float fSecond = 0.0f;
                     poFeature->GetFieldAsDateTime(j, &nYear, &nMonth, &nDay,
                                                     &nHour, &nMinute, &fSecond, &nTZFlag );
                     struct tm brokendowntime;
@@ -1915,7 +1915,7 @@ static void WriteLayer(const char* pszName, OGRLayer* poLayer, int iLayer,
                 {
                     const char* pszVal = poFeature->GetFieldAsString(j);
                     std::map<std::string,int>::iterator oIter = oStringMap.find(pszVal);
-                    int nStringIndex;
+                    int nStringIndex = 0;
                     if (oIter != oStringMap.end())
                         nStringIndex = oIter->second;
                     else
@@ -1949,10 +1949,9 @@ static void WriteSharedStrings(const char* pszName,
                                CPL_UNUSED std::map<std::string,int>& oStringMap,
                                std::vector<std::string>& oStringList)
 {
-    VSILFILE* fp;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/sharedStrings.xml", pszName), "wb");
-    VSIFPrintfL(fp, XML_HEADER);
+    VSILFILE* fp =
+        VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/sharedStrings.xml", pszName), "wb");
+    VSIFWriteL(XML_HEADER, strlen(XML_HEADER), 1, fp);
     VSIFPrintfL(fp, "<sst %s uniqueCount=\"%d\">\n",
                 MAIN_NS,
                 (int)oStringList.size());
@@ -1974,10 +1973,9 @@ static void WriteSharedStrings(const char* pszName,
 
 static void WriteStyles(const char* pszName)
 {
-    VSILFILE* fp;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/styles.xml", pszName), "wb");
-    VSIFPrintfL(fp, XML_HEADER);
+    VSILFILE* fp =
+        VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/styles.xml", pszName), "wb");
+    VSIFWriteL(XML_HEADER, strlen(XML_HEADER), 1, fp);
     VSIFPrintfL(fp, "<styleSheet %s>\n", MAIN_NS);
     VSIFPrintfL(fp, "<numFmts count=\"4\">\n");
     VSIFPrintfL(fp, "<numFmt formatCode=\"GENERAL\" numFmtId=\"164\"/>\n");
@@ -2031,10 +2029,10 @@ static void WriteStyles(const char* pszName)
 
 static void WriteWorkbookRels(const char* pszName, int nLayers)
 {
-    VSILFILE* fp;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/_rels/workbook.xml.rels", pszName), "wb");
-    VSIFPrintfL(fp, XML_HEADER);
+    VSILFILE* fp =
+        VSIFOpenL(CPLSPrintf("/vsizip/%s/xl/_rels/workbook.xml.rels",
+                             pszName), "wb");
+    VSIFWriteL(XML_HEADER, strlen(XML_HEADER), 1, fp);
     VSIFPrintfL(fp, "<Relationships xmlns=\"%s\">\n", SCHEMA_PACKAGE_RS);
     VSIFPrintfL(fp, "<Relationship Id=\"rId1\" Type=\"%s/styles\" Target=\"styles.xml\"/>\n", SCHEMA_OD_RS);
     for(int i=0;i<nLayers;i++)
@@ -2054,10 +2052,9 @@ static void WriteWorkbookRels(const char* pszName, int nLayers)
 
 static void WriteDotRels(const char* pszName)
 {
-    VSILFILE* fp;
-
-    fp = VSIFOpenL(CPLSPrintf("/vsizip/%s/_rels/.rels", pszName), "wb");
-    VSIFPrintfL(fp, XML_HEADER);
+    VSILFILE* fp =
+        VSIFOpenL(CPLSPrintf("/vsizip/%s/_rels/.rels", pszName), "wb");
+    VSIFWriteL(XML_HEADER, strlen(XML_HEADER), 1, fp);
     VSIFPrintfL(fp, "<Relationships xmlns=\"%s\">\n", SCHEMA_PACKAGE_RS);
     VSIFPrintfL(fp, "<Relationship Id=\"rId1\" Type=\"%s/officeDocument\" Target=\"xl/workbook.xml\"/>\n", SCHEMA_OD_RS);
     VSIFPrintfL(fp, "<Relationship Id=\"rId2\" Type=\"%s/metadata/core-properties\" Target=\"docProps/core.xml\"/>\n", SCHEMA_PACKAGE_RS);
@@ -2072,7 +2069,7 @@ static void WriteDotRels(const char* pszName)
 
 void OGRXLSXDataSource::FlushCache()
 {
-    if (!bUpdated)
+    if( !bUpdated )
         return;
 
     VSIStatBufL sStat;
@@ -2093,11 +2090,11 @@ void OGRXLSXDataSource::FlushCache()
     }
 
     /* Maintain new ZIP files opened */
-    VSILFILE* fpZIP = VSIFOpenL(CPLSPrintf("/vsizip/%s", pszName), "wb");
+    VSILFILE* fpZIP = VSIFOpenExL(CPLSPrintf("/vsizip/%s", pszName), "wb", true);
     if (fpZIP == NULL)
     {
         CPLError(CE_Failure, CPLE_FileIO,
-                 "Cannot create %s", pszName);
+                 "Cannot create %s: %s", pszName, VSIGetLastErrorMsg());
         return;
     }
 
@@ -2132,10 +2129,10 @@ void OGRXLSXDataSource::FlushCache()
     VSIFCloseL(fpZIP);
 
     /* Reset updated flag at datasource and layer level */
-    bUpdated = FALSE;
-    for(int i = 0; i<nLayers; i++)
+    bUpdated = false;
+    for( int i = 0; i<nLayers; i++ )
     {
-        ((OGRXLSXLayer*)papoLayers[i])->SetUpdated(FALSE);
+        ((OGRXLSXLayer*)papoLayers[i])->SetUpdated(false);
     }
 
     return;
diff --git a/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp b/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
index a5eed58..5e75d2b 100644
--- a/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
+++ b/ogr/ogrsf_frmts/xlsx/ogrxlsxdriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrxlsxdriver.cpp 35710 2016-10-13 07:21:17Z rouault $
  *
  * Project:  XLSX Translator
  * Purpose:  Implements OGRXLSXDriver.
@@ -30,7 +29,7 @@
 #include "ogr_xlsx.h"
 #include "cpl_conv.h"
 
-CPL_CVSID("$Id: ogrxlsxdriver.cpp 35710 2016-10-13 07:21:17Z rouault $");
+CPL_CVSID("$Id: ogrxlsxdriver.cpp 35709 2016-10-13 07:21:06Z rouault $");
 
 extern "C" void RegisterOGRXLSX();
 
@@ -61,7 +60,8 @@ const char *OGRXLSXDriver::GetName()
 /*                                Open()                                */
 /************************************************************************/
 
-#define XLSX_MIMETYPE "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
+static const char XLSX_MIMETYPE[] =
+    "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
 
 OGRDataSource *OGRXLSXDriver::Open( const char * pszFilename, int bUpdate )
 
@@ -73,17 +73,17 @@ OGRDataSource *OGRXLSXDriver::Open( const char * pszFilename, int bUpdate )
     if (fp == NULL)
         return NULL;
 
-    int bOK = FALSE;
+    bool bOK = false;
     char szBuffer[2048];
     if (VSIFReadL(szBuffer, sizeof(szBuffer), 1, fp) == 1 &&
         memcmp(szBuffer, "PK", 2) == 0)
     {
-        bOK = TRUE;
+        bOK = true;
     }
 
     VSIFCloseL(fp);
 
-    if (!bOK)
+    if( !bOK )
         return NULL;
 
     VSILFILE* fpContent = VSIFOpenL(CPLSPrintf("/vsizip/%s/[Content_Types].xml", pszFilename), "rb");
@@ -154,9 +154,7 @@ OGRDataSource *OGRXLSXDriver::CreateDataSource( const char * pszName,
 /* -------------------------------------------------------------------- */
 /*      Try to create datasource.                                       */
 /* -------------------------------------------------------------------- */
-    OGRXLSXDataSource     *poDS;
-
-    poDS = new OGRXLSXDataSource();
+    OGRXLSXDataSource *poDS = new OGRXLSXDataSource();
 
     if( !poDS->Create( pszName, papszOptions ) )
     {
@@ -214,4 +212,3 @@ void RegisterOGRXLSX()
 
     OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( poDriver );
 }
-
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane.h b/ogr/ogrsf_frmts/xplane/ogr_xplane.h
index 517af57..b259d83 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xplane.h $
+ * $Id: ogr_xplane.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Definition of classes for OGR X-Plane aeronautical data driver.
@@ -55,7 +55,8 @@ class OGRXPlaneLayer : public OGRLayer
   protected:
     OGRXPlaneReader*   poReader;
     OGRFeatureDefn*    poFeatureDefn;
-                       OGRXPlaneLayer(const char* pszLayerName);
+
+    explicit           OGRXPlaneLayer(const char* pszLayerName);
 
     void               RegisterFeature(OGRFeature* poFeature);
 
@@ -68,17 +69,16 @@ class OGRXPlaneLayer : public OGRLayer
     int                       IsEmpty() { return nFeatureArraySize == 0; }
     void                      AutoAdjustColumnsWidth();
 
-    virtual void              ResetReading();
-    virtual OGRFeature *      GetNextFeature();
-    virtual OGRFeature *      GetFeature( GIntBig nFID );
-    virtual OGRErr            SetNextByIndex( GIntBig nIndex );
-    virtual GIntBig           GetFeatureCount( int bForce = TRUE );
+    virtual void              ResetReading() override;
+    virtual OGRFeature *      GetNextFeature() override;
+    virtual OGRFeature *      GetFeature( GIntBig nFID ) override;
+    virtual OGRErr            SetNextByIndex( GIntBig nIndex ) override;
+    virtual GIntBig           GetFeatureCount( int bForce = TRUE ) override;
 
-    virtual OGRFeatureDefn *  GetLayerDefn();
-    virtual int               TestCapability( const char * pszCap );
+    virtual OGRFeatureDefn *  GetLayerDefn() override;
+    virtual int               TestCapability( const char * pszCap ) override;
 };
 
-
 /************************************************************************/
 /*                           OGRXPlaneDataSource                        */
 /************************************************************************/
@@ -91,24 +91,24 @@ class OGRXPlaneDataSource : public OGRDataSource
     int                 nLayers;
 
     OGRXPlaneReader*    poReader;
-    int                 bReadWholeFile;
-    int                 bWholeFiledReadingDone;
+    bool                bReadWholeFile;
+    bool                bWholeFiledReadingDone;
 
     void                Reset();
 
   public:
                         OGRXPlaneDataSource();
-                        ~OGRXPlaneDataSource();
+                        virtual ~OGRXPlaneDataSource();
 
     int                 Open( const char * pszFilename, int bReadWholeFile = TRUE );
 
     void                RegisterLayer( OGRXPlaneLayer* poLayer );
 
-    virtual int         GetLayerCount() { return nLayers; }
-    virtual OGRLayer*   GetLayer( int );
-    virtual const char* GetName() { return pszName; }
+    virtual int         GetLayerCount() override { return nLayers; }
+    virtual OGRLayer*   GetLayer( int ) override;
+    virtual const char* GetName() override { return pszName; }
 
-    virtual int         TestCapability( const char * pszCap );
+    virtual int         TestCapability( const char * pszCap ) override;
 
     void                ReadWholeFileIfNecessary();
 };
@@ -121,11 +121,10 @@ class OGRXPlaneDriver : public OGRSFDriver
 {
   public:
 
-    virtual const char* GetName();
-    OGRDataSource*      Open( const char *, int );
+    virtual const char* GetName() override;
+    OGRDataSource*      Open( const char *, int ) override;
 
-    virtual int         TestCapability( const char * pszCap );
+    virtual int         TestCapability( const char * pszCap ) override;
 };
 
-
 #endif /* ndef OGR_XPLANE_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
index ffb55ab..59527d8 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_xplane_apt_reader.cpp
  *
  * Project:  X-Plane apt.dat file reader
  * Purpose:  Implements OGRXPlaneAptReader class
@@ -30,7 +29,7 @@
 #include "ogr_xplane_apt_reader.h"
 #include "ogr_xplane_geo_utils.h"
 
-CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 32430 2015-12-22 13:56:42Z goatbar $");
+CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 36061 2016-11-01 02:26:58Z goatbar $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateAptFileReader                       */
@@ -154,7 +153,7 @@ OGRXPlaneReader* OGRXPlaneAptReader::CloneForLayer(OGRXPlaneLayer* poLayer)
     SET_IF_INTEREST_LAYER(poVASI_PAPI_WIGWAG_Layer);
     SET_IF_INTEREST_LAYER(poTaxiLocationLayer);
 
-    if (pszFilename)
+    if( pszFilename )
     {
         poReader->pszFilename = CPLStrdup(pszFilename);
         poReader->fp = VSIFOpenL( pszFilename, "rb" );
@@ -184,25 +183,24 @@ void OGRXPlaneAptReader::Rewind()
     OGRXPlaneReader::Rewind();
 }
 
-
 /************************************************************************/
 /*                      IsRecognizedVersion()                           */
 /************************************************************************/
 
 int OGRXPlaneAptReader::IsRecognizedVersion( const char* pszVersionString)
 {
-    if (STARTS_WITH_CI(pszVersionString, "810 Version"))
+    if( STARTS_WITH_CI(pszVersionString, "810 Version") )
         nVersion = APT_V_810;
-    else if (STARTS_WITH_CI(pszVersionString, "850 Version"))
+    else if( STARTS_WITH_CI(pszVersionString, "850 Version") )
         nVersion = APT_V_850;
-    else if (STARTS_WITH_CI(pszVersionString, "1000 Version"))
+    else if( STARTS_WITH_CI(pszVersionString, "1000 Version") )
         nVersion = APT_V_1000;
     else
         nVersion = APT_V_UNKNOWN;
 
-    if (nVersion == APT_V_1000)
+    if( nVersion == APT_V_1000 )
     {
-        if (poDataSource)
+        if( poDataSource )
         {
             poTaxiLocationLayer = new OGRXPlaneTaxiLocationLayer();
             poDataSource->RegisterLayer(poTaxiLocationLayer);
@@ -218,16 +216,16 @@ int OGRXPlaneAptReader::IsRecognizedVersion( const char* pszVersionString)
 
 void OGRXPlaneAptReader::Read()
 {
-    if (!bResumeLine)
+    if( !bResumeLine )
     {
         CPLAssert(papszTokens == NULL);
     }
 
     const char* pszLine = NULL;
 
-    while(bResumeLine || (pszLine = CPLReadLineL(fp)) != NULL)
+    while( bResumeLine || (pszLine = CPLReadLineL(fp)) != NULL )
     {
-        if (!bResumeLine)
+        if( !bResumeLine )
         {
             papszTokens = CSLTokenizeString(pszLine);
             nTokens = CSLCount(papszTokens);
@@ -239,14 +237,14 @@ void OGRXPlaneAptReader::Read()
         {
             bResumeLine = false;
 
-            if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
+            if( nTokens == 1 && strcmp(papszTokens[0], "99") == 0 )
             {
                 CSLDestroy(papszTokens);
                 papszTokens = NULL;
                 bEOF = true;
-                if (bAptHeaderFound)
+                if( bAptHeaderFound )
                 {
-                    if (poAPTLayer)
+                    if( poAPTLayer )
                     {
                         poAPTLayer->AddFeature(
                             osAptICAO, osAptName, nAPTType, dfElevation,
@@ -258,7 +256,7 @@ void OGRXPlaneAptReader::Read()
                 }
                 return;
             }
-            else if (nTokens == 0 || assertMinCol(2) == FALSE)
+            else if( nTokens == 0 || !assertMinCol(2) )
             {
                 break;
             }
@@ -269,10 +267,10 @@ void OGRXPlaneAptReader::Read()
                 case APT_AIRPORT_HEADER:
                 case APT_SEAPLANE_HEADER:
                 case APT_HELIPORT_HEADER:
-                    if (bAptHeaderFound)
+                    if( bAptHeaderFound )
                     {
                         bAptHeaderFound = false;
-                        if (poAPTLayer)
+                        if( poAPTLayer )
                         {
                             poAPTLayer->AddFeature(
                                 osAptICAO, osAptName, nAPTType, dfElevation,
@@ -288,43 +286,43 @@ void OGRXPlaneAptReader::Read()
                     break;
 
                 case APT_RUNWAY_TAXIWAY_V_810:
-                    if (poAPTLayer ||
+                    if( poAPTLayer ||
                         poRunwayLayer || poRunwayThresholdLayer ||
                         poStopwayLayer ||
                         poHelipadLayer || poHelipadPolygonLayer ||
-                        poVASI_PAPI_WIGWAG_Layer || poTaxiwayRectangleLayer)
+                        poVASI_PAPI_WIGWAG_Layer || poTaxiwayRectangleLayer )
                     {
                         ParseRunwayTaxiwayV810Record();
                     }
                     break;
 
                 case APT_TOWER:
-                    if (poAPTLayer)
+                    if( poAPTLayer )
                         ParseTowerRecord();
                     break;
 
                 case APT_STARTUP_LOCATION:
-                    if (poStartupLocationLayer)
+                    if( poStartupLocationLayer )
                         ParseStartupLocationRecord();
                     break;
 
                 case APT_LIGHT_BEACONS:
-                    if (poAPTLightBeaconLayer)
+                    if( poAPTLightBeaconLayer )
                         ParseLightBeaconRecord();
                     break;
 
                 case APT_WINDSOCKS:
-                    if (poAPTWindsockLayer)
+                    if( poAPTWindsockLayer )
                         ParseWindsockRecord();
                     break;
 
                 case APT_TAXIWAY_SIGNS:
-                    if (poTaxiwaySignLayer)
+                    if( poTaxiwaySignLayer )
                         ParseTaxiwaySignRecord();
                     break;
 
                 case APT_VASI_PAPI_WIGWAG:
-                    if (poVASI_PAPI_WIGWAG_Layer)
+                    if( poVASI_PAPI_WIGWAG_Layer )
                         ParseVasiPapiWigWagRecord();
                     break;
 
@@ -335,33 +333,33 @@ void OGRXPlaneAptReader::Read()
                 case APT_ATC_TWR:
                 case APT_ATC_APP:
                 case APT_ATC_DEP:
-                    if (poATCFreqLayer)
+                    if( poATCFreqLayer )
                         ParseATCRecord(nType);
                     break;
 
                 case APT_RUNWAY:
-                    if (poAPTLayer || poRunwayLayer || poRunwayThresholdLayer
-                        || poStopwayLayer)
+                    if( poAPTLayer || poRunwayLayer || poRunwayThresholdLayer
+                        || poStopwayLayer )
                         ParseRunwayRecord();
                     break;
 
                 case APT_WATER_RUNWAY:
-                    if (poWaterRunwayLayer || poWaterRunwayThresholdLayer)
+                    if( poWaterRunwayLayer || poWaterRunwayThresholdLayer )
                         ParseWaterRunwayRecord();
                     break;
 
                 case APT_HELIPAD:
-                    if (poHelipadLayer || poHelipadPolygonLayer)
+                    if( poHelipadLayer || poHelipadPolygonLayer )
                         ParseHelipadRecord();
                     break;
 
                 case APT_PAVEMENT_HEADER:
-                    if (poPavementLayer)
+                    if( poPavementLayer )
                         ParsePavement();
                     break;
 
                 case APT_LINEAR_HEADER:
-                    if (poAPTLinearFeatureLayer)
+                    if( poAPTLinearFeatureLayer )
                         ParseAPTLinearFeature();
                     break;
 
@@ -380,19 +378,18 @@ void OGRXPlaneAptReader::Read()
                               nLineNumber, nType);
                     break;
             }
-        } while(bResumeLine);
+        } while( bResumeLine );
 
         CSLDestroy(papszTokens);
         papszTokens = NULL;
 
-        if (poInterestLayer && poInterestLayer->IsEmpty() == FALSE)
+        if( poInterestLayer && !poInterestLayer->IsEmpty() )
             return;
     }
 
     bEOF = true;
 }
 
-
 /************************************************************************/
 /*                         ParseAptHeaderRecord()                       */
 /************************************************************************/
@@ -420,19 +417,19 @@ void    OGRXPlaneAptReader::ParseAptHeaderRecord()
 /*                    ParseRunwayTaxiwayV810Record()                    */
 /************************************************************************/
 
-void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
+void OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
 {
-    // int aeVisualApproachLightingCode[2];
+    // int aeVisualApproachLightingCode[2] = { 0, 0 };
 
     RET_IF_FAIL(assertMinCol(15));
 
-    double dfLat;
-    double dfLon;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
     const char* pszRwyNum = papszTokens[3];
-    double dfTrueHeading;
+    double dfTrueHeading = 0.0;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 4));
-    double dfLength;
+    double dfLength = 0.0;
     RET_IF_FAIL(readDouble(&dfLength, 5, "length"));
     dfLength *= FEET_TO_METER;
     double adfDisplacedThresholdLength[2];
@@ -447,7 +444,7 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
         adfStopwayLength[1] = atoi(strchr(papszTokens[7], '.') + 1) * FEET_TO_METER;
     else
         adfStopwayLength[1] = 0;
-    double dfWidth;
+    double dfWidth = 0.0;
     RET_IF_FAIL(readDouble(&dfWidth, 8, "width"));
     dfWidth *= FEET_TO_METER;
     int aeRunwayLightingCode[2];
@@ -471,10 +468,10 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
     const int eSurfaceCode = atoi(papszTokens[10]);
     const int eShoulderCode = atoi(papszTokens[11]);
     const int eMarkings = atoi(papszTokens[12]);
-    double dfSmoothness;
+    double dfSmoothness = 0.0;
     RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 13, "runway smoothness", 0., 1.));
     bool bHasDistanceRemainingSigns = CPL_TO_BOOL(atoi(papszTokens[14]));
-    double adfVisualGlidePathAngle[2];
+    double adfVisualGlidePathAngle[2] = { 0.0, 0.0 };
     if (nTokens == 16)
     {
         adfVisualGlidePathAngle[0] = atoi(papszTokens[15]) / 100.;
@@ -483,11 +480,6 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
         else
             adfVisualGlidePathAngle[1] = 0;
     }
-    else
-    {
-        adfVisualGlidePathAngle[0] = 0;
-        adfVisualGlidePathAngle[1] = 0;
-    }
 
     if (strcmp(pszRwyNum, "xxx") == 000)
     {
@@ -552,7 +544,6 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
                             ( osAptICAO, aosRwyNum[i], adfLat[i], adfLon[i],
                               dfWidth, bBuoys );
                 }
-
             }
 
             if (poWaterRunwayThresholdLayer)
@@ -681,7 +672,6 @@ void    OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
         CPLDebug("XPlane", "Line %d : Unexpected runway number : %s",
                     nLineNumber, pszRwyNum);
     }
-
 }
 
 /************************************************************************/
@@ -692,28 +682,28 @@ void OGRXPlaneAptReader::ParseRunwayRecord()
 {
     RET_IF_FAIL(assertMinCol(8 + 9 + 9));
 
-    double dfWidth;
+    double dfWidth = 0.0;
     RET_IF_FAIL(readDouble(&dfWidth, 1, "runway width"));
 
     const int eSurfaceCode = atoi(papszTokens[2]);
     const int eShoulderCode = atoi(papszTokens[3]);
-    double dfSmoothness;
+    double dfSmoothness = 0.0;
     RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 4, "runway smoothness", 0., 1.));
 
     const bool bHasCenterLineLights = CPL_TO_BOOL(atoi(papszTokens[5]));
     const int eEdgeLighting = atoi(papszTokens[6]);
     const bool bHasDistanceRemainingSigns = CPL_TO_BOOL(atoi(papszTokens[7]));
-    double adfLat[2];
-    double adfLon[2];
+    double adfLat[2] = { 0.0, 0.0 };
+    double adfLon[2] = { 0.0, 0.0 };
     CPLString aosRunwayId[2];
-    double adfDisplacedThresholdLength[2];
-    double adfStopwayLength[2];
+    double adfDisplacedThresholdLength[2] = { 0.0, 0.0 };
+    double adfStopwayLength[2] = { 0.0, 0.0 };
 
-    for( int nRwy=0; nRwy<=1 ; nRwy++ )
+    for( int nRwy = 0; nRwy <= 1 ; nRwy++ )
     {
         aosRunwayId[nRwy] = papszTokens[8 + 9*nRwy + 0]; /* for example : 08, 24R, or xxx */
-        double dfLat;
-        double dfLon;
+        double dfLat = 0.0;
+        double dfLon = 0.0;
         RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 8 + 9*nRwy + 1));
         adfLat[nRwy] = dfLat;
         adfLon[nRwy] = dfLon;
@@ -724,7 +714,7 @@ void OGRXPlaneAptReader::ParseRunwayRecord()
                                  8 + 9*nRwy + 4,
                                  "stopway/blastpad/over-run length" ) );
 
-        if (!bRunwayFound)
+        if( !bRunwayFound )
         {
             dfLatFirstRwy = dfLat;
             dfLonFirstRwy = dfLon;
@@ -787,8 +777,9 @@ void OGRXPlaneAptReader::ParseRunwayRecord()
         {
             if (adfStopwayLength[i] != 0)
             {
-                double dfHeading = OGRXPlane_Track(adfLat[i], adfLon[i],
-                                                   adfLat[1-i], adfLon[1-i]);
+                const double dfHeading =
+                    OGRXPlane_Track(adfLat[i], adfLon[i],
+                                    adfLat[1-i], adfLon[1-i]);
                 poStopwayLayer->AddFeature(osAptICAO, aosRunwayId[i],
                     adfLat[i], adfLon[i], dfHeading, dfWidth, adfStopwayLength[i]);
             }
@@ -804,12 +795,12 @@ void OGRXPlaneAptReader::ParseWaterRunwayRecord()
 {
     RET_IF_FAIL(assertMinCol(9));
 
-    double dfWidth;
+    double dfWidth = 0.0;
     RET_IF_FAIL(readDouble(&dfWidth, 1, "runway width"));
 
     bool bBuoys = CPL_TO_BOOL(atoi(papszTokens[2]));
-    double adfLat[2];
-    double adfLon[2];
+    double adfLat[2] = { 0.0, 0.0 };
+    double adfLon[2] = { 0.0, 0.0 };
     CPLString aosRunwayId[2];
 
     for( int i=0; i < 2; i++ )
@@ -818,13 +809,13 @@ void OGRXPlaneAptReader::ParseWaterRunwayRecord()
         RET_IF_FAIL(readLatLon(&adfLat[i], &adfLon[i], 4 + 3*i));
     }
 
-    const double dfLength
-        = OGRXPlane_Distance(adfLat[0], adfLon[0], adfLat[1], adfLon[1]);
+    const double dfLength =
+        OGRXPlane_Distance(adfLat[0], adfLon[0], adfLat[1], adfLon[1]);
 
     if (poWaterRunwayThresholdLayer)
     {
         OGRFeature* apoWaterRunwayThreshold[2] = {NULL, NULL};
-        for( int i=0; i < 2; i++ )
+        for( int i = 0; i < 2; i++ )
         {
             apoWaterRunwayThreshold[i] =
                 poWaterRunwayThresholdLayer->AddFeature
@@ -854,23 +845,23 @@ void OGRXPlaneAptReader::ParseHelipadRecord()
     RET_IF_FAIL(assertMinCol(12));
 
     const char* pszHelipadName = papszTokens[1];
-    double dfLat;
-    double dfLon;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 2));
-    double dfTrueHeading;
+    double dfTrueHeading = 0.0;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 4));
-    double dfLength;
+    double dfLength = 0.0;
     RET_IF_FAIL(readDouble(&dfLength, 5, "length"));
-    double dfWidth;
+    double dfWidth = 0.0;
     RET_IF_FAIL(readDouble(&dfWidth, 6, "width"));
     const int eSurfaceCode = atoi(papszTokens[7]);
     const int eMarkings = atoi(papszTokens[8]);
     const int eShoulderCode = atoi(papszTokens[9]);
-    double dfSmoothness;
+    double dfSmoothness = 0.0;
     RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 10, "helipad smoothness", 0., 1.));
     const int eEdgeLighting = atoi(papszTokens[11]);
 
-    if (poHelipadLayer)
+    if( poHelipadLayer )
     {
         poHelipadLayer->AddFeature(osAptICAO, pszHelipadName, dfLat, dfLon,
                                 dfTrueHeading, dfLength, dfWidth,
@@ -893,33 +884,40 @@ void OGRXPlaneAptReader::ParseHelipadRecord()
     }
 }
 
-
-
 /************************************************************************/
 /*                          AddBezierCurve()                           */
 /************************************************************************/
 
-#define CUBIC_INTERPOL(A, B, C, D)  ((A)*(b*b*b) + 3*(B)*(b*b)*a + 3 *(C)*b*(a*a) + (D)*(a*a*a))
+static double CUBIC_INTERPOL( double a, double b,
+                              double A, double B, double C, double D )
+{
+    return A*b*b*b + 3*B*b*b*a + 3 *C*b*a*a + D*a*a*a;
+}
 
 void OGRXPlaneAptReader::AddBezierCurve(OGRLineString& lineString,
                                         double dfLatA, double dfLonA,
                                         double dfCtrPtLatA, double dfCtrPtLonA,
-                                        double dfSymCtrlPtLatB, double dfSymCtrlPtLonB,
+                                        double dfSymCtrlPtLatB,
+                                        double dfSymCtrlPtLonB,
                                         double dfLatB, double dfLonB)
 {
     for( int step = 0; step <= 10; step++ )
     {
-        const double a = step / 10.;
-        const double b = 1. - a;
+        const double a = step / 10.0;
+        const double b = 1.0 - a;
         const double dfCtrlPtLonB = dfLonB - (dfSymCtrlPtLonB - dfLonB);
         const double dfCtrlPtLatB = dfLatB - (dfSymCtrlPtLatB - dfLatB);
-        lineString.addPoint(CUBIC_INTERPOL(dfLonA, dfCtrPtLonA, dfCtrlPtLonB, dfLonB),
-                            CUBIC_INTERPOL(dfLatA, dfCtrPtLatA, dfCtrlPtLatB, dfLatB));
+        lineString.addPoint(
+            CUBIC_INTERPOL(a, b, dfLonA, dfCtrPtLonA, dfCtrlPtLonB, dfLonB),
+            CUBIC_INTERPOL(a, b, dfLatA, dfCtrPtLatA, dfCtrlPtLatB, dfLatB));
     }
 }
 
-
-#define QUADRATIC_INTERPOL(A, B, C)  ((A)*(b*b) + 2*(B)*b*a + (C)*(a*a))
+static double QUADRATIC_INTERPOL( double a, double b,
+                                  double A, double B, double C )
+{
+    return A*b*b + 2*B*b*a + C*a*a;
+}
 
 void OGRXPlaneAptReader::AddBezierCurve(OGRLineString& lineString,
                                         double dfLatA, double dfLonA,
@@ -928,10 +926,11 @@ void OGRXPlaneAptReader::AddBezierCurve(OGRLineString& lineString,
 {
     for( int step = 0; step <= 10; step++ )
     {
-        double a = step / 10.;
-        double b = 1. - a;
-        lineString.addPoint(QUADRATIC_INTERPOL(dfLonA, dfCtrPtLon, dfLonB),
-                            QUADRATIC_INTERPOL(dfLatA, dfCtrPtLat, dfLatB));
+        const double a = step / 10.0;
+        const double b = 1.0 - a;
+        lineString.addPoint(
+            QUADRATIC_INTERPOL(a, b, dfLonA, dfCtrPtLon, dfLonB),
+            QUADRATIC_INTERPOL(a, b, dfLatA, dfCtrPtLat, dfLatB));
     }
 }
 
@@ -948,9 +947,9 @@ static OGRGeometry* OGRXPlaneAptReaderSplitPolygon(OGRPolygon& polygon)
         papoPolygons[i+1]->addRing(polygon.getInteriorRing(i));
     }
 
-    int bIsValid;
-    OGRGeometry* poGeom
-        = OGRGeometryFactory::organizePolygons(
+    int bIsValid = FALSE;
+    OGRGeometry* poGeom =
+        OGRGeometryFactory::organizePolygons(
             reinterpret_cast<OGRGeometry**>( papoPolygons ),
             1 + polygon.getNumInteriorRings(),
             &bIsValid, NULL);
@@ -1005,7 +1004,7 @@ OGRGeometry* OGRXPlaneAptReader::FixPolygonTopology(OGRPolygon& polygon)
         {
             OGRPoint pt;
             poInternalRing->getPoint(j, &pt);
-            if (poExternalRing->isPointInRing(&pt) == FALSE)
+            if( !poExternalRing->isPointInRing(&pt) )
             {
                 nOutside++;
                 jOutside = j;
@@ -1063,30 +1062,36 @@ OGRGeometry* OGRXPlaneAptReader::FixPolygonTopology(OGRPolygon& polygon)
 /************************************************************************/
 
 /* This function will eat records until the end of the polygon */
-/* Return TRUE if the main parser must re-scan the current record */
+/* Return true if the main parser must re-scan the current record */
 
-#define RET_FALSE_IF_FAIL(x)      if (!(x)) return FALSE;
+#define RET_FALSE_IF_FAIL(x)      if (!(x)) return false;
 
-int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
+bool OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
 {
-    double dfLat, dfLon;
-    double dfFirstLat = 0., dfFirstLon = 0.;
-    double dfLastLat = 0., dfLastLon = 0.;
-    double dfLatBezier = 0., dfLonBezier = 0.;
-    double dfFirstLatBezier = 0., dfFirstLonBezier = 0.;
-    double dfLastLatBezier = 0., dfLastLonBezier = 0.;
+    double dfLat;
+    double dfLon;
+    double dfFirstLat = 0.0;
+    double dfFirstLon = 0.0;
+    double dfLastLat = 0.0;
+    double dfLastLon = 0.0;
+    double dfLatBezier = 0.0;
+    double dfLonBezier = 0.0;
+    double dfFirstLatBezier = 0.0;
+    double dfFirstLonBezier = 0.0;
+    double dfLastLatBezier = 0.0;
+    double dfLastLonBezier = 0.0;
     bool bIsFirst = true;
     bool bFirstIsBezier = true;
     // bool bLastIsValid = false;
     bool bLastIsBezier = false;
     bool bLastPartIsClosed = false;
-    const char* pszLine;
     OGRPolygon polygon;
 
     OGRLinearRing linearRing;
 
     *ppoGeom = NULL;
 
+    const char* pszLine = NULL;
     while((pszLine = CPLReadLineL(fp)) != NULL)
     {
         int nType = -1;
@@ -1097,10 +1102,12 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
 
         if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
         {
-            if (bLastPartIsClosed == FALSE)
+            if( !bLastPartIsClosed )
             {
-                CPLDebug("XPlane", "Line %d : Unexpected token when reading a polygon : %d",
-                        nLineNumber, nType);
+                CPLDebug(
+                    "XPlane",
+                    "Line %d : Unexpected token when reading a polygon : %d",
+                    nLineNumber, nType);
             }
             else
             {
@@ -1109,7 +1116,7 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
 
             return true;
         }
-        if (nTokens == 0 || assertMinCol(2) == FALSE)
+        if (nTokens == 0 || !assertMinCol(2) )
         {
             CSLDestroy(papszTokens);
             continue;
@@ -1245,15 +1252,19 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
             linearRing.empty();
 
             bLastPartIsClosed = true;
-            bLastIsBezier = false; /* we don't want to draw an arc between two parts */
+            // We do not want to draw an arc between two parts.
+            bLastIsBezier = false;
         }
         else
         {
-            if (nType == APT_NODE_END || nType == APT_NODE_END_WITH_BEZIER ||
-                bLastPartIsClosed == FALSE)
+            if( nType == APT_NODE_END ||
+                nType == APT_NODE_END_WITH_BEZIER ||
+                !bLastPartIsClosed )
             {
-                CPLDebug("XPlane", "Line %d : Unexpected token when reading a polygon : %d",
-                        nLineNumber, nType);
+                CPLDebug(
+                    "XPlane",
+                    "Line %d : Unexpected token when reading a polygon : %d",
+                    nLineNumber, nType);
             }
             else
             {
@@ -1280,14 +1291,13 @@ int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
         CSLDestroy(papszTokens);
     }
 
-    CPLAssert(0);
+    CPLAssert(false);
 
     papszTokens = NULL;
 
     return false;
 }
 
-
 /************************************************************************/
 /*                            ParsePavement()                           */
 /************************************************************************/
@@ -1298,10 +1308,10 @@ void OGRXPlaneAptReader::ParsePavement()
 
     const int eSurfaceCode = atoi(papszTokens[1]);
 
-    double dfSmoothness;
+    double dfSmoothness = 0.0;
     RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 2, "pavement smoothness", 0., 1.));
 
-    double dfTextureHeading;
+    double dfTextureHeading = 0.0;
     RET_IF_FAIL(readTrueHeading(&dfTextureHeading, 3, "texture heading"));
 
     const CPLString osPavementName = readStringUntilEnd(4);
@@ -1309,7 +1319,7 @@ void OGRXPlaneAptReader::ParsePavement()
     CSLDestroy(papszTokens);
     papszTokens = NULL;
 
-    OGRGeometry* poGeom;
+    OGRGeometry* poGeom = NULL;
     bResumeLine = ParsePolygonalGeometry(&poGeom);
     if (poGeom != NULL && poPavementLayer)
     {
@@ -1347,11 +1357,9 @@ void OGRXPlaneAptReader::ParsePavement()
 /************************************************************************/
 
 /* This function will eat records until the end of the boundary definition */
-/* Return TRUE if the main parser must re-scan the current record */
 
 void OGRXPlaneAptReader::ParseAPTBoundary()
 {
-
     RET_IF_FAIL(assertMinCol(2));
 
     const CPLString osBoundaryName = readStringUntilEnd(2);
@@ -1359,7 +1367,7 @@ void OGRXPlaneAptReader::ParseAPTBoundary()
     CSLDestroy(papszTokens);
     papszTokens = NULL;
 
-    OGRGeometry* poGeom;
+    OGRGeometry* poGeom = NULL;
     bResumeLine = ParsePolygonalGeometry(&poGeom);
     if (poGeom != NULL && poAPTBoundaryLayer)
     {
@@ -1389,31 +1397,37 @@ void OGRXPlaneAptReader::ParseAPTBoundary()
         delete poGeom;
 }
 
-
 /************************************************************************/
 /*                             ParseLinearGeometry()                    */
 /************************************************************************/
 
 /* This function will eat records until the end of the multilinestring */
-/* Return TRUE if the main parser must re-scan the current record */
+/* Return true if the main parser must re-scan the current record */
 
-int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring, int* pbIsValid)
+bool OGRXPlaneAptReader::ParseLinearGeometry(
+    OGRMultiLineString& multilinestring, int* pbIsValid )
 {
-    double dfLat, dfLon;
-    double dfFirstLat = 0., dfFirstLon = 0.;
-    double dfLastLat = 0., dfLastLon = 0.;
-    double dfLatBezier = 0., dfLonBezier = 0.;
-    double dfFirstLatBezier = 0., dfFirstLonBezier = 0.;
-    double dfLastLatBezier = 0., dfLastLonBezier = 0.;
+    double dfLat;
+    double dfLon;
+    double dfFirstLat = 0.0;
+    double dfFirstLon = 0.0;
+    double dfLastLat = 0.0;
+    double dfLastLon = 0.0;
+    double dfLatBezier = 0.0;
+    double dfLonBezier = 0.0;
+    double dfFirstLatBezier = 0.0;
+    double dfFirstLonBezier = 0.0;
+    double dfLastLatBezier = 0.0;
+    double dfLastLonBezier = 0.0;
     bool bIsFirst = true;
     bool bFirstIsBezier = true;
     // bool bLastIsValid = false;
     bool bLastIsBezier = false;
     bool bLastPartIsClosedOrEnded = false;
-    const char* pszLine;
 
     OGRLineString lineString;
 
+    const char* pszLine = NULL;
     while((pszLine = CPLReadLineL(fp)) != NULL)
     {
         int nType = -1;
@@ -1440,7 +1454,7 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
             }
             return true;
         }
-        if (nTokens == 0 || assertMinCol(2) == FALSE)
+        if( nTokens == 0 || !assertMinCol(2) )
         {
             CSLDestroy(papszTokens);
             continue;
@@ -1607,7 +1621,7 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
         }
         else
         {
-            if (bLastPartIsClosedOrEnded == FALSE)
+            if( !bLastPartIsClosedOrEnded )
             {
                 CPLDebug( "XPlane",
                           "Line %d : Unexpected token when reading a linear "
@@ -1644,7 +1658,7 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
         CSLDestroy(papszTokens);
     }
 
-    CPLAssert(0);
+    CPLAssert(false);
 
     papszTokens = NULL;
 
@@ -1656,7 +1670,6 @@ int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring,
 /************************************************************************/
 
 // This function will eat records until the end of the linear feature definition
-// Return TRUE if the main parser must re-scan the current record.
 
 void OGRXPlaneAptReader::ParseAPTLinearFeature()
 {
@@ -1698,7 +1711,6 @@ void OGRXPlaneAptReader::ParseTowerRecord()
     bTowerFound = true;
 }
 
-
 /************************************************************************/
 /*                            ParseATCRecord()                          */
 /************************************************************************/
@@ -1707,7 +1719,7 @@ void OGRXPlaneAptReader::ParseATCRecord(int nType)
 {
     RET_IF_FAIL(assertMinCol(2));
 
-    double dfFrequency;
+    double dfFrequency = 0.0;
     RET_IF_FAIL(readDouble(&dfFrequency, 1, "frequency"));
     dfFrequency /= 100.;
 
@@ -1727,7 +1739,6 @@ void OGRXPlaneAptReader::ParseATCRecord(int nType)
     }
 }
 
-
 /************************************************************************/
 /*                      ParseStartupLocationRecord()                    */
 /************************************************************************/
@@ -1736,9 +1747,11 @@ void OGRXPlaneAptReader::ParseStartupLocationRecord()
 {
     RET_IF_FAIL(assertMinCol(4));
 
-    double dfLat, dfLon, dfTrueHeading;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
 
+    double dfTrueHeading = 0.0;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 3));
 
     const CPLString osName = readStringUntilEnd(4);
@@ -1756,7 +1769,8 @@ void OGRXPlaneAptReader::ParseLightBeaconRecord()
 {
     RET_IF_FAIL(assertMinCol(4));
 
-    double dfLat, dfLon;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
     const int eColor = atoi(papszTokens[3]);
     const CPLString osName = readStringUntilEnd(4);
@@ -1775,7 +1789,8 @@ void OGRXPlaneAptReader::ParseWindsockRecord()
 {
     RET_IF_FAIL(assertMinCol(4));
 
-    double dfLat, dfLon;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
 
     const bool bIsIllumnited = CPL_TO_BOOL(atoi(papszTokens[3]));
@@ -1794,9 +1809,10 @@ void OGRXPlaneAptReader::ParseTaxiwaySignRecord()
 {
     RET_IF_FAIL(assertMinCol(7));
 
-    double dfLat, dfLon;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
-    double dfTrueHeading;
+    double dfTrueHeading = 0.0;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 3, "heading"));
     /* papszTokens[4] : ignored. Taxiway sign style */
     const int nSize = atoi(papszTokens[5]);
@@ -1815,18 +1831,19 @@ void OGRXPlaneAptReader::ParseVasiPapiWigWagRecord()
 {
     RET_IF_FAIL(assertMinCol(7));
 
-    double dfLat, dfLon;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
 
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
     const int eType = atoi(papszTokens[3]);
-    double dfTrueHeading;
+    double dfTrueHeading = 0.0;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 4, "heading"));
-    double dfVisualGlidePathAngle;
+    double dfVisualGlidePathAngle = 0.0;
     RET_IF_FAIL(readDoubleWithBounds(&dfVisualGlidePathAngle, 5, "visual glidepath angle", 0, 90));
     const char* pszRwyNum = papszTokens[6];
     /* papszTokens[7] : ignored. Type of lighting object represented */
 
-    if (poVASI_PAPI_WIGWAG_Layer)
+    if( poVASI_PAPI_WIGWAG_Layer )
         poVASI_PAPI_WIGWAG_Layer->AddFeature(
             osAptICAO, pszRwyNum, VASI_PAPI_WIGWAG_Enumeration.GetText(eType),
             dfLat, dfLon,
@@ -1841,9 +1858,10 @@ void OGRXPlaneAptReader::ParseTaxiLocation()
 {
     RET_IF_FAIL(assertMinCol(7));
 
-    double dfLat, dfLon;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
-    double dfTrueHeading;
+    double dfTrueHeading = 0.0;
     RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 3, "heading"));
     const CPLString osLocationType = papszTokens[4];
     const CPLString osAirplaneTypes = papszTokens[5];
@@ -1859,7 +1877,6 @@ void OGRXPlaneAptReader::ParseTaxiLocation()
 /*                         OGRXPlaneAPTLayer()                          */
 /************************************************************************/
 
-
 OGRXPlaneAPTLayer::OGRXPlaneAPTLayer() : OGRXPlaneLayer("APT")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
@@ -1897,17 +1914,17 @@ OGRXPlaneAPTLayer::OGRXPlaneAPTLayer() : OGRXPlaneLayer("APT")
 /*                           AddFeature()                               */
 /************************************************************************/
 
-OGRFeature*
-     OGRXPlaneAPTLayer::AddFeature(const char* pszAptICAO,
-                                   const char* pszAptName,
-                                   int nAPTType,
-                                   double dfElevation,
-                                   int bHasCoordinates,
-                                   double dfLat,
-                                   double dfLon,
-                                   int bHasTower,
-                                   double dfHeightTower,
-                                   const char* pszTowerName)
+OGRFeature *
+OGRXPlaneAPTLayer::AddFeature( const char* pszAptICAO,
+                               const char* pszAptName,
+                               int nAPTType,
+                               double dfElevation,
+                               bool bHasCoordinates,
+                               double dfLat,
+                               double dfLon,
+                               bool bHasTower,
+                               double dfHeightTower,
+                               const char* pszTowerName )
 {
     int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
@@ -1917,8 +1934,8 @@ OGRFeature*
                                    (nAPTType == APT_SEAPLANE_HEADER)   ? 1 :
                                  /*(nAPTType == APT_HELIPORT_HEADER)*/   2 );
     poFeature->SetField( nCount++, dfElevation );
-    poFeature->SetField( nCount++, bHasTower );
-    if (bHasCoordinates)
+    poFeature->SetField( nCount++, static_cast<int>(bHasTower) );
+    if( bHasCoordinates )
     {
         poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
     }
@@ -1926,7 +1943,7 @@ OGRFeature*
     {
         CPLDebug("XPlane", "Airport %s/%s has no coordinates", pszAptICAO, pszAptName);
     }
-    if (bHasTower)
+    if( bHasTower )
     {
         poFeature->SetField( nCount++, dfHeightTower );
         poFeature->SetField( nCount++, pszTowerName );
@@ -1941,7 +1958,6 @@ OGRFeature*
 /*               OGRXPlaneRunwayThresholdLayer()                        */
 /************************************************************************/
 
-
 OGRXPlaneRunwayThresholdLayer::OGRXPlaneRunwayThresholdLayer() : OGRXPlaneLayer("RunwayThreshold")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
@@ -2089,7 +2105,8 @@ OGRFeature* OGRXPlaneRunwayThresholdLayer::
     const double dfTrueHeading = poFeature->GetFieldAsDouble("true_heading_deg");
     poFeature->SetField("is_displaced", true);
     OGRPoint* poPoint = (OGRPoint*)poFeature->GetGeometryRef();
-    double dfLatDisplaced, dfLonDisplaced;
+    double dfLatDisplaced = 0.0;
+    double dfLonDisplaced = 0.0;
     OGRXPlane_ExtendPosition(poPoint->getY(), poPoint->getX(),
                              dfDisplacedThresholdLength, dfTrueHeading,
                              &dfLatDisplaced, &dfLonDisplaced);
@@ -2105,9 +2122,8 @@ OGRFeature* OGRXPlaneRunwayThresholdLayer::
 /*                       OGRXPlaneRunwayLayer()                         */
 /************************************************************************/
 
-
-
-OGRXPlaneRunwayLayer::OGRXPlaneRunwayLayer() : OGRXPlaneLayer("RunwayPolygon")
+OGRXPlaneRunwayLayer::OGRXPlaneRunwayLayer() :
+    OGRXPlaneLayer("RunwayPolygon")
 {
     poFeatureDefn->SetGeomType( wkbPolygon );
 
@@ -2163,7 +2179,6 @@ OGRXPlaneRunwayLayer::OGRXPlaneRunwayLayer() : OGRXPlaneLayer("RunwayPolygon")
 /*                           AddFeature()                               */
 /************************************************************************/
 
-
 OGRFeature*
      OGRXPlaneRunwayLayer::AddFeature  (const char* pszAptICAO,
                                         const char* pszRwyNum1,
@@ -2221,14 +2236,12 @@ OGRFeature*
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                      OGRXPlaneStopwayLayer()                         */
 /************************************************************************/
 
-
-
-OGRXPlaneStopwayLayer::OGRXPlaneStopwayLayer() : OGRXPlaneLayer("Stopway")
+OGRXPlaneStopwayLayer::OGRXPlaneStopwayLayer() :
+    OGRXPlaneLayer("Stopway")
 {
     poFeatureDefn->SetGeomType( wkbPolygon );
 
@@ -2253,7 +2266,6 @@ OGRXPlaneStopwayLayer::OGRXPlaneStopwayLayer() : OGRXPlaneLayer("Stopway")
 /*                           AddFeature()                               */
 /************************************************************************/
 
-
 OGRFeature*
      OGRXPlaneStopwayLayer::AddFeature(const char* pszAptICAO,
                                        const char* pszRwyNum,
@@ -2266,8 +2278,10 @@ OGRFeature*
     int nCount = 0;
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
-    double dfLat2, dfLon2;
-    double adfLat[4], adfLon[4];
+    double dfLat2 = 0.0;
+    double dfLon2 = 0.0;
+    double adfLat[4] = {};
+    double adfLon[4] = {};
 
     OGRXPlane_ExtendPosition( dfLatThreshold, dfLonThreshold, dfStopwayLength,
                               180 + dfRunwayHeading, &dfLat2, &dfLon2);
@@ -2304,7 +2318,6 @@ OGRFeature*
 /*               OGRXPlaneWaterRunwayThresholdLayer()                   */
 /************************************************************************/
 
-
 OGRXPlaneWaterRunwayThresholdLayer::OGRXPlaneWaterRunwayThresholdLayer() :
     OGRXPlaneLayer("WaterRunwayThreshold")
 {
@@ -2371,13 +2384,10 @@ void OGRXPlaneWaterRunwayThresholdLayer::SetRunwayLengthAndHeading(
     poFeature->SetField( nCount++, dfHeading );
 }
 
-
 /************************************************************************/
 /*                      OGRXPlaneWaterRunwayLayer()                     */
 /************************************************************************/
 
-
-
 OGRXPlaneWaterRunwayLayer::OGRXPlaneWaterRunwayLayer() :
     OGRXPlaneLayer("WaterRunwayPolygon")
 {
@@ -2433,7 +2443,8 @@ OGRFeature*
     const double dfLength = OGRXPlane_Distance(dfLat1, dfLon1, dfLat2, dfLon2);
     const double dfTrack12 = OGRXPlane_Track(dfLat1, dfLon1, dfLat2, dfLon2);
     const double dfTrack21 = OGRXPlane_Track(dfLat2, dfLon2, dfLat1, dfLon1);
-    double adfLat[4], adfLon[4];
+    double adfLat[4] = {};
+    double adfLon[4] = {};
 
     OGRXPlane_ExtendPosition( dfLat1, dfLon1, dfWidth / 2, dfTrack12 - 90,
                               &adfLat[0], &adfLon[0]);
@@ -2467,13 +2478,12 @@ OGRFeature*
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                     OGRXPlaneHelipadLayer()                          */
 /************************************************************************/
 
-
-OGRXPlaneHelipadLayer::OGRXPlaneHelipadLayer() : OGRXPlaneLayer("Helipad")
+OGRXPlaneHelipadLayer::OGRXPlaneHelipadLayer() :
+    OGRXPlaneLayer("Helipad")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -2514,7 +2524,6 @@ OGRXPlaneHelipadLayer::OGRXPlaneHelipadLayer() : OGRXPlaneLayer("Helipad")
 
     OGRFieldDefn oFieldEdgeLighting("edge_lighting", OFTString );
     poFeatureDefn->AddFieldDefn( &oFieldEdgeLighting );
-
 }
 
 /************************************************************************/
@@ -2558,7 +2567,6 @@ OGRFeature*
 /*                 OGRXPlaneHelipadPolygonLayer()                       */
 /************************************************************************/
 
-
 OGRXPlaneHelipadPolygonLayer::OGRXPlaneHelipadPolygonLayer() :
     OGRXPlaneLayer("HelipadPolygon")
 {
@@ -2601,7 +2609,6 @@ OGRXPlaneHelipadPolygonLayer::OGRXPlaneHelipadPolygonLayer() :
 
     OGRFieldDefn oFieldEdgeLighting("edge_lighting", OFTString );
     poFeatureDefn->AddFieldDefn( &oFieldEdgeLighting );
-
 }
 
 /************************************************************************/
@@ -2624,9 +2631,12 @@ OGRFeature*
 {
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
-    double dfBeforeLat, dfBeforeLon;
-    double dfAfterLat, dfAfterLon;
-    double adfLat[4], adfLon[4];
+    double dfBeforeLat = 0.0;
+    double dfBeforeLon = 0.0;
+    double dfAfterLat = 0.0;
+    double dfAfterLon = 0.0;
+    double adfLat[4] = {};
+    double adfLon[4] = {};
 
     OGRXPlane_ExtendPosition( dfLat, dfLon, dfLength / 2, dfTrueHeading + 180,
                               &dfBeforeLat, &dfBeforeLon);
@@ -2668,13 +2678,12 @@ OGRFeature*
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                 OGRXPlaneTaxiwayRectangleLayer()                     */
 /************************************************************************/
 
-
-OGRXPlaneTaxiwayRectangleLayer::OGRXPlaneTaxiwayRectangleLayer() : OGRXPlaneLayer("TaxiwayRectangle")
+OGRXPlaneTaxiwayRectangleLayer::OGRXPlaneTaxiwayRectangleLayer() :
+    OGRXPlaneLayer("TaxiwayRectangle")
 {
     poFeatureDefn->SetGeomType( wkbPolygon );
 
@@ -2706,7 +2715,6 @@ OGRXPlaneTaxiwayRectangleLayer::OGRXPlaneTaxiwayRectangleLayer() : OGRXPlaneLaye
     OGRFieldDefn oFieldBlueEdgeLighting("edge_lighting", OFTInteger );
     oFieldBlueEdgeLighting.SetWidth( 1 );
     poFeatureDefn->AddFieldDefn( &oFieldBlueEdgeLighting );
-
 }
 
 /************************************************************************/
@@ -2726,9 +2734,12 @@ OGRFeature*
 {
     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
 
-    double dfBeforeLat, dfBeforeLon;
-    double dfAfterLat, dfAfterLon;
-    double adfLat[4], adfLon[4];
+    double dfBeforeLat = 0.0;
+    double dfBeforeLon = 0.0;
+    double dfAfterLat = 0.0;
+    double dfAfterLon = 0.0;
+    double adfLat[4] = {};
+    double adfLon[4] = {};
 
     OGRXPlane_ExtendPosition( dfLat, dfLon, dfLength / 2, dfTrueHeading + 180,
                               &dfBeforeLat, &dfBeforeLon);
@@ -2767,13 +2778,12 @@ OGRFeature*
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                      OGRXPlanePavementLayer()                        */
 /************************************************************************/
 
-
-OGRXPlanePavementLayer::OGRXPlanePavementLayer() : OGRXPlaneLayer("Pavement")
+OGRXPlanePavementLayer::OGRXPlanePavementLayer() :
+    OGRXPlaneLayer("Pavement")
 {
     poFeatureDefn->SetGeomType( wkbPolygon );
 
@@ -2796,7 +2806,6 @@ OGRXPlanePavementLayer::OGRXPlanePavementLayer() : OGRXPlaneLayer("Pavement")
     oFieldTextureHeading.SetWidth( 6 );
     oFieldTextureHeading.SetPrecision( 2 );
     poFeatureDefn->AddFieldDefn( &oFieldTextureHeading );
-
 }
 
 /************************************************************************/
@@ -2827,13 +2836,10 @@ OGRFeature*
     return poFeature;
 }
 
-
-
 /************************************************************************/
 /*                   OGRXPlaneAPTBoundaryLayer()                        */
 /************************************************************************/
 
-
 OGRXPlaneAPTBoundaryLayer::OGRXPlaneAPTBoundaryLayer() :
     OGRXPlaneLayer("APTBoundary")
 {
@@ -2845,7 +2851,6 @@ OGRXPlaneAPTBoundaryLayer::OGRXPlaneAPTBoundaryLayer() :
 
     OGRFieldDefn oFieldName("name", OFTString );
     poFeatureDefn->AddFieldDefn( &oFieldName );
-
 }
 
 /************************************************************************/
@@ -2874,7 +2879,6 @@ OGRFeature*
 /*               OGRXPlaneAPTLinearFeatureLayer()                       */
 /************************************************************************/
 
-
 OGRXPlaneAPTLinearFeatureLayer::OGRXPlaneAPTLinearFeatureLayer() :
     OGRXPlaneLayer("APTLinearFeature")
 {
@@ -2886,7 +2890,6 @@ OGRXPlaneAPTLinearFeatureLayer::OGRXPlaneAPTLinearFeatureLayer() :
 
     OGRFieldDefn oFieldName("name", OFTString );
     poFeatureDefn->AddFieldDefn( &oFieldName );
-
 }
 
 /************************************************************************/
@@ -2916,8 +2919,8 @@ OGRFeature*
 /*                        OGRXPlaneATCFreqLayer()                       */
 /************************************************************************/
 
-
-OGRXPlaneATCFreqLayer::OGRXPlaneATCFreqLayer() : OGRXPlaneLayer("ATCFreq")
+OGRXPlaneATCFreqLayer::OGRXPlaneATCFreqLayer() :
+    OGRXPlaneLayer("ATCFreq")
 {
     poFeatureDefn->SetGeomType( wkbNone );
 
@@ -2960,7 +2963,6 @@ OGRFeature*
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                     OGRXPlaneStartupLocationLayer()                  */
 /************************************************************************/
@@ -3006,7 +3008,6 @@ OGRFeature*
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                      OGRXPlaneAPTLightBeaconLayer()                  */
 /************************************************************************/
@@ -3094,7 +3095,6 @@ OGRFeature*
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                        OGRXPlaneTaxiwaySignLayer()                   */
 /************************************************************************/
@@ -3146,7 +3146,6 @@ OGRFeature*
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                   OGRXPlane_VASI_PAPI_WIGWAG_Layer()                 */
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
index 0272247..e011bc0 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_apt_reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xplane_apt_reader.h
+ * $Id: ogr_xplane_apt_reader.h$
  *
  * Project:  X-Plane apt.dat file reader headers
  * Purpose:  Definition of classes for X-Plane apt.dat file reader
@@ -37,7 +37,6 @@
 /*                           OGRXPlaneAPTLayer                          */
 /************************************************************************/
 
-
 class OGRXPlaneAPTLayer : public OGRXPlaneLayer
 {
   public:
@@ -49,15 +48,14 @@ class OGRXPlaneAPTLayer : public OGRXPlaneLayer
                                    const char* pszAptName,
                                    int nAPTType,
                                    double dfElevation,
-                                   int bHasCoordinates = FALSE,
+                                   bool bHasCoordinates = false,
                                    double dfLat = 0,
                                    double dfLon = 0,
-                                   int bHasTower = FALSE,
+                                   bool bHasTower = false,
                                    double dfHeightTower = 0,
                                    const char* pszTowerName = NULL);
 };
 
-
 /************************************************************************/
 /*                   OGRXPlaneRunwayThresholdLayer                      */
 /************************************************************************/
@@ -183,7 +181,7 @@ class OGRXPlaneRunwayThresholdLayer : public OGRXPlaneLayer
                                    const char* pszREIL);
 
     /* Set a few computed values */
-    void                 SetRunwayLengthAndHeading(OGRFeature* poFeature,
+    static void                 SetRunwayLengthAndHeading(OGRFeature* poFeature,
                                                    double dfLength,
                                                    double dfHeading);
 
@@ -194,7 +192,6 @@ class OGRXPlaneRunwayThresholdLayer : public OGRXPlaneLayer
 /*                          OGRXPlaneRunwayLayer                        */
 /************************************************************************/
 
-
 class OGRXPlaneRunwayLayer : public OGRXPlaneLayer
 {
   public:
@@ -216,12 +213,10 @@ class OGRXPlaneRunwayLayer : public OGRXPlaneLayer
                                    int bHasDistanceRemainingSigns);
 };
 
-
 /************************************************************************/
 /*                        OGRXPlaneStopwayLayer                         */
 /************************************************************************/
 
-
 class OGRXPlaneStopwayLayer : public OGRXPlaneLayer
 {
   public:
@@ -240,7 +235,6 @@ class OGRXPlaneStopwayLayer : public OGRXPlaneLayer
 /*                   OGRXPlaneWaterRunwayThresholdLayer                 */
 /************************************************************************/
 
-
 class OGRXPlaneWaterRunwayThresholdLayer : public OGRXPlaneLayer
 {
   public:
@@ -254,12 +248,11 @@ class OGRXPlaneWaterRunwayThresholdLayer : public OGRXPlaneLayer
                                    int bBuoys);
 
     /* Set a few computed values */
-    void                 SetRunwayLengthAndHeading(OGRFeature* poFeature,
+    static void                 SetRunwayLengthAndHeading(OGRFeature* poFeature,
                                                    double dfLength,
                                                    double dfHeading);
 };
 
-
 /************************************************************************/
 /*                         OGRXPlaneWaterRunwayLayer                    */
 /************************************************************************/
@@ -282,7 +275,6 @@ class OGRXPlaneWaterRunwayLayer : public OGRXPlaneLayer
                                    int bBuoys);
 };
 
-
 /************************************************************************/
 /*                        OGRXPlaneHelipadLayer                         */
 /************************************************************************/
@@ -320,7 +312,6 @@ class OGRXPlaneHelipadLayer : public OGRXPlaneLayer
 /*                     OGRXPlaneHelipadPolygonLayer                     */
 /************************************************************************/
 
-
 class OGRXPlaneHelipadPolygonLayer : public OGRXPlaneLayer
 {
   public:
@@ -340,12 +331,10 @@ class OGRXPlaneHelipadPolygonLayer : public OGRXPlaneLayer
                                    const char* pszEdgeLighing);
 };
 
-
 /************************************************************************/
 /*                    OGRXPlaneTaxiwayRectangleLayer                    */
 /************************************************************************/
 
-
 class OGRXPlaneTaxiwayRectangleLayer : public OGRXPlaneLayer
 {
   public:
@@ -362,12 +351,10 @@ class OGRXPlaneTaxiwayRectangleLayer : public OGRXPlaneLayer
                                    int bBlueEdgeLights);
 };
 
-
 /************************************************************************/
 /*                          OGRXPlanePavementLayer                      */
 /************************************************************************/
 
-
 class OGRXPlanePavementLayer : public OGRXPlaneLayer
 {
   public:
@@ -385,7 +372,6 @@ class OGRXPlanePavementLayer : public OGRXPlaneLayer
 /*                       OGRXPlaneAPTBoundaryLayer                      */
 /************************************************************************/
 
-
 class OGRXPlaneAPTBoundaryLayer : public OGRXPlaneLayer
 {
   public:
@@ -396,12 +382,10 @@ class OGRXPlaneAPTBoundaryLayer : public OGRXPlaneLayer
                                    OGRPolygon* poPolygon);
 };
 
-
 /************************************************************************/
 /*                 OGRXPlaneAPTLinearFeatureLayer                       */
 /************************************************************************/
 
-
 class OGRXPlaneAPTLinearFeatureLayer : public OGRXPlaneLayer
 {
   public:
@@ -412,7 +396,6 @@ class OGRXPlaneAPTLinearFeatureLayer : public OGRXPlaneLayer
                                    OGRMultiLineString* poMultilineString);
 };
 
-
 /************************************************************************/
 /*                         OGRXPlaneATCFreqLayer                         */
 /************************************************************************/
@@ -428,7 +411,6 @@ class OGRXPlaneATCFreqLayer : public OGRXPlaneLayer
                                    double dfFrequency);
 };
 
-
 /************************************************************************/
 /*                     OGRXPlaneStartupLocationLayer                    */
 /************************************************************************/
@@ -449,7 +431,6 @@ class OGRXPlaneStartupLocationLayer : public OGRXPlaneLayer
 /*                     OGRXPlaneAPTLightBeaconLayer                     */
 /************************************************************************/
 
-
 static const sEnumerationElement APTLightBeaconColorType[] =
 {
     { 0, "None" },
@@ -489,7 +470,6 @@ class OGRXPlaneAPTWindsockLayer : public OGRXPlaneLayer
                                    int bIsIllumnited);
 };
 
-
 /************************************************************************/
 /*                       OGRXPlaneTaxiwaySignLayer                      */
 /************************************************************************/
@@ -597,8 +577,6 @@ enum
     APT_TAXI_LOCATION          = 1300, /* added in V_1000 */
 };
 
-
-
 /************************************************************************/
 /*                           OGRXPlaneAptReader                         */
 /************************************************************************/
@@ -637,15 +615,16 @@ class OGRXPlaneAptReader : public OGRXPlaneReader
         CPLString osAptName;
         int       nAPTType;
 
-        int       bTowerFound;
+        bool      bTowerFound;
         double    dfLatTower, dfLonTower;
         double    dfHeightTower;
         CPLString osTowerName;
 
-        int     bRunwayFound;
-        double  dfLatFirstRwy , dfLonFirstRwy;
+        bool    bRunwayFound;
+        double  dfLatFirstRwy;
+        double  dfLonFirstRwy;
 
-        int     bResumeLine;
+        bool    bResumeLine;
 
     private:
                 OGRXPlaneAptReader();
@@ -668,8 +647,9 @@ class OGRXPlaneAptReader : public OGRXPlaneReader
         void    ParseTaxiLocation();
 
         OGRGeometry* FixPolygonTopology(OGRPolygon& polygon);
-        int     ParsePolygonalGeometry(OGRGeometry** ppoGeom);
-        int     ParseLinearGeometry(OGRMultiLineString& multilinestring, int* pbIsValid);
+        bool    ParsePolygonalGeometry(OGRGeometry** ppoGeom);
+        bool    ParseLinearGeometry(
+                    OGRMultiLineString& multilinestring, int* pbIsValid );
 
         static void    AddBezierCurve (OGRLineString& lineString,
                                 double dfLatA, double dfLonA,
@@ -682,13 +662,13 @@ class OGRXPlaneAptReader : public OGRXPlaneReader
                                 double dfLatB, double dfLonB);
 
     protected:
-        virtual void             Read();
+        virtual void             Read() override;
 
     public:
-                                 OGRXPlaneAptReader( OGRXPlaneDataSource* poDataSource );
-        virtual OGRXPlaneReader* CloneForLayer(OGRXPlaneLayer* poLayer);
-        virtual int              IsRecognizedVersion( const char* pszVersionString);
-        virtual void             Rewind();
+        explicit                 OGRXPlaneAptReader( OGRXPlaneDataSource* poDataSource );
+        virtual OGRXPlaneReader* CloneForLayer(OGRXPlaneLayer* poLayer) override;
+        virtual int              IsRecognizedVersion( const char* pszVersionString) override;
+        virtual void             Rewind() override;
 };
 
 #endif
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
index dd0dc27..d3f42e5 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_xplane_awy_reader.cpp
  *
  * Project:  X-Plane awy.dat file reader
  * Purpose:  Implements OGRXPlaneAwyReader class
@@ -29,7 +28,7 @@
 
 #include "ogr_xplane_awy_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_awy_reader.cpp 32431 2015-12-22 14:06:59Z goatbar $");
+CPL_CVSID("$Id: ogr_xplane_awy_reader.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateAwyFileReader                       */
@@ -41,25 +40,22 @@ OGRXPlaneReader* OGRXPlaneCreateAwyFileReader( OGRXPlaneDataSource* poDataSource
     return poReader;
 }
 
-
 /************************************************************************/
 /*                         OGRXPlaneAwyReader()                         */
 /************************************************************************/
-OGRXPlaneAwyReader::OGRXPlaneAwyReader()
-{
-    poAirwaySegmentLayer = NULL;
-    poAirwayIntersectionLayer = NULL;
-}
+OGRXPlaneAwyReader::OGRXPlaneAwyReader() :
+    poAirwaySegmentLayer(NULL),
+    poAirwayIntersectionLayer(NULL)
+{}
 
 /************************************************************************/
 /*                          OGRXPlaneAwyReader()                        */
 /************************************************************************/
 
-OGRXPlaneAwyReader::OGRXPlaneAwyReader( OGRXPlaneDataSource* poDataSource )
+OGRXPlaneAwyReader::OGRXPlaneAwyReader( OGRXPlaneDataSource* poDataSource ) :
+    poAirwaySegmentLayer(new OGRXPlaneAirwaySegmentLayer()),
+    poAirwayIntersectionLayer(new OGRXPlaneAirwayIntersectionLayer())
 {
-    poAirwaySegmentLayer = new OGRXPlaneAirwaySegmentLayer();
-    poAirwayIntersectionLayer = new OGRXPlaneAirwayIntersectionLayer();
-
     poDataSource->RegisterLayer(poAirwaySegmentLayer);
     poDataSource->RegisterLayer(poAirwayIntersectionLayer);
 }
@@ -86,7 +82,6 @@ OGRXPlaneReader* OGRXPlaneAwyReader::CloneForLayer(OGRXPlaneLayer* poLayer)
     return poReader;
 }
 
-
 /************************************************************************/
 /*                       IsRecognizedVersion()                          */
 /************************************************************************/
@@ -96,14 +91,13 @@ int OGRXPlaneAwyReader::IsRecognizedVersion( const char* pszVersionString)
     return STARTS_WITH_CI(pszVersionString, "640 Version");
 }
 
-
 /************************************************************************/
 /*                                Read()                                */
 /************************************************************************/
 
 void OGRXPlaneAwyReader::Read()
 {
-    const char* pszLine;
+    const char* pszLine = NULL;
     while((pszLine = CPLReadLineL(fp)) != NULL)
     {
         papszTokens = CSLTokenizeString(pszLine);
@@ -115,10 +109,10 @@ void OGRXPlaneAwyReader::Read()
         {
             CSLDestroy(papszTokens);
             papszTokens = NULL;
-            bEOF = TRUE;
+            bEOF = true;
             return;
         }
-        else if (nTokens == 0 || assertMinCol(10) == FALSE)
+        else if( nTokens == 0 || !assertMinCol(10) )
         {
             CSLDestroy(papszTokens);
             papszTokens = NULL;
@@ -130,12 +124,12 @@ void OGRXPlaneAwyReader::Read()
         CSLDestroy(papszTokens);
         papszTokens = NULL;
 
-        if (poInterestLayer && poInterestLayer->IsEmpty() == FALSE)
+        if( poInterestLayer && !poInterestLayer->IsEmpty() )
             return;
     }
 
     papszTokens = NULL;
-    bEOF = TRUE;
+    bEOF = true;
 }
 
 /************************************************************************/
@@ -144,8 +138,10 @@ void OGRXPlaneAwyReader::Read()
 
 void OGRXPlaneAwyReader::ParseRecord()
 {
-    double dfLat1, dfLon1;
-    double dfLat2, dfLon2;
+    double dfLat1 = 0.0;
+    double dfLon1 = 0.0;
+    double dfLat2 = 0.0;
+    double dfLon2 = 0.0;
 
     const char* pszFirstPointName = papszTokens[0];
     RET_IF_FAIL(readLatLon(&dfLat1, &dfLon1, 1));
@@ -201,12 +197,12 @@ void OGRXPlaneAwyReader::ParseRecord()
     }
 }
 
-
 /************************************************************************/
 /*                       OGRXPlaneAirwaySegmentLayer()                  */
 /************************************************************************/
 
-OGRXPlaneAirwaySegmentLayer::OGRXPlaneAirwaySegmentLayer() : OGRXPlaneLayer("AirwaySegment")
+OGRXPlaneAirwaySegmentLayer::OGRXPlaneAirwaySegmentLayer() :
+    OGRXPlaneLayer("AirwaySegment")
 {
     poFeatureDefn->SetGeomType( wkbLineString );
 
@@ -262,17 +258,20 @@ OGRFeature*
         OGRMultiLineString* multiLineString = new OGRMultiLineString();
         OGRLineString* lineString1 = new OGRLineString();
         OGRLineString* lineString2 = new OGRLineString();
-        double dfLatInt;
         lineString1->addPoint(dfLon1, dfLat1);
         if (dfLon1 < dfLon2)
         {
-            dfLatInt = dfLat1 + (dfLat2 - dfLat1) * (-180 - dfLon1) / ((dfLon2 - 360) - dfLon1);
+            const double dfLatInt =
+                dfLat1 +
+                (dfLat2 - dfLat1) * (-180 - dfLon1) / ((dfLon2 - 360) - dfLon1);
             lineString1->addPoint(-180, dfLatInt);
             lineString2->addPoint(180, dfLatInt);
         }
         else
         {
-            dfLatInt = dfLat1 + (dfLat2 - dfLat1) * (180 - dfLon1) / ((dfLon2 + 360) - dfLon1);
+            const double dfLatInt =
+                dfLat1 +
+                (dfLat2 - dfLat1) * (180 - dfLon1) / ((dfLon2 + 360) - dfLon1);
             lineString1->addPoint(180, dfLatInt);
             lineString2->addPoint(-180, dfLatInt);
         }
@@ -299,20 +298,23 @@ OGRFeature*
 /*                 EqualAirwayIntersectionFeature                       */
 /************************************************************************/
 
-static int EqualAirwayIntersectionFeatureFunc(const void* _feature1, const void* _feature2)
+static int EqualAirwayIntersectionFeatureFunc(
+    const void* _feature1, const void* _feature2 )
 {
     OGRFeature* feature1 = (OGRFeature*)_feature1;
     OGRFeature* feature2 = (OGRFeature*)_feature2;
-    if (strcmp(feature1->GetFieldAsString(0), feature2->GetFieldAsString(0)) == 0)
+    if (strcmp(feature1->GetFieldAsString(0),
+               feature2->GetFieldAsString(0)) == 0)
     {
         OGRPoint* point1 = (OGRPoint*) feature1->GetGeometryRef();
         OGRPoint* point2 = (OGRPoint*) feature2->GetGeometryRef();
-        return (point1->getX() == point2->getX() && point1->getY() == point2->getY());
+        return
+            point1->getX() == point2->getX() &&
+            point1->getY() == point2->getY();
     }
-    return FALSE;
+    return false;
 }
 
-
 /************************************************************************/
 /*                      OGRXPlaneAirwayHashDouble()                     */
 /************************************************************************/
@@ -358,16 +360,16 @@ static void FreeAirwayIntersectionFeatureFunc(void* _feature)
 /*                 OGRXPlaneAirwayIntersectionLayer()                   */
 /************************************************************************/
 
-OGRXPlaneAirwayIntersectionLayer::OGRXPlaneAirwayIntersectionLayer() : OGRXPlaneLayer("AirwayIntersection")
+OGRXPlaneAirwayIntersectionLayer::OGRXPlaneAirwayIntersectionLayer() :
+    OGRXPlaneLayer("AirwayIntersection"),
+    poSet(CPLHashSetNew(HashAirwayIntersectionFeatureFunc,
+                        EqualAirwayIntersectionFeatureFunc,
+                        FreeAirwayIntersectionFeatureFunc))
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
     OGRFieldDefn oFieldName("name", OFTString );
     poFeatureDefn->AddFieldDefn( &oFieldName );
-
-    poSet = CPLHashSetNew(HashAirwayIntersectionFeatureFunc,
-                          EqualAirwayIntersectionFeatureFunc,
-                          FreeAirwayIntersectionFeatureFunc);
 }
 
 /************************************************************************/
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h
index 60089e6..257c780 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_awy_reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xplane_awy_reader.cpp
+ * $Id: ogr_xplane_awy_reader.cpp$
  *
  * Project:  X-Plane awy.dat file reader header
  * Purpose:  Definition of classes for X-Plane awy.dat file reader
@@ -39,7 +39,6 @@
 /*                   OGRXPlaneAirwaySegmentLayer                        */
 /************************************************************************/
 
-
 class OGRXPlaneAirwaySegmentLayer : public OGRXPlaneLayer
 {
   public:
@@ -67,13 +66,13 @@ class OGRXPlaneAirwayIntersectionLayer : public OGRXPlaneLayer
 
   public:
                         OGRXPlaneAirwayIntersectionLayer();
-                        ~OGRXPlaneAirwayIntersectionLayer();
+                        virtual ~OGRXPlaneAirwayIntersectionLayer();
 
     OGRFeature*         AddFeature(const char* pszIntersectionName,
                                    double dfLat,
                                    double dfLon);
 
-    virtual void        ResetReading();
+    virtual void        ResetReading() override;
 };
 
 /************************************************************************/
@@ -91,12 +90,12 @@ class OGRXPlaneAwyReader : public OGRXPlaneReader
         void                     ParseRecord();
 
     protected:
-        virtual void             Read();
+        virtual void             Read() override;
 
     public:
-                                 OGRXPlaneAwyReader( OGRXPlaneDataSource* poDataSource );
-        virtual OGRXPlaneReader* CloneForLayer(OGRXPlaneLayer* poLayer);
-        virtual int              IsRecognizedVersion( const char* pszVersionString);
+        explicit                 OGRXPlaneAwyReader( OGRXPlaneDataSource* poDataSource );
+        virtual OGRXPlaneReader* CloneForLayer(OGRXPlaneLayer* poLayer) override;
+        virtual int              IsRecognizedVersion( const char* pszVersionString) override;
 };
 
 #endif
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
index 4575d29..79177b1 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_xplane_fix_reader.cpp
  *
  * Project:  X-Plane fix.dat file reader
  * Purpose:  Implements OGRXPlaneFixReader class
@@ -29,7 +28,7 @@
 
 #include "ogr_xplane_fix_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_fix_reader.cpp 31120 2015-10-24 19:55:09Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_fix_reader.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateFixFileReader                       */
@@ -41,23 +40,20 @@ OGRXPlaneReader* OGRXPlaneCreateFixFileReader( OGRXPlaneDataSource* poDataSource
     return poReader;
 }
 
-
 /************************************************************************/
 /*                         OGRXPlaneFixReader()                         */
 /************************************************************************/
-OGRXPlaneFixReader::OGRXPlaneFixReader()
-{
-    poFIXLayer = NULL;
-}
+OGRXPlaneFixReader::OGRXPlaneFixReader() :
+    poFIXLayer(NULL)
+{}
 
 /************************************************************************/
 /*                          OGRXPlaneFixReader()                        */
 /************************************************************************/
 
-OGRXPlaneFixReader::OGRXPlaneFixReader( OGRXPlaneDataSource* poDataSource )
+OGRXPlaneFixReader::OGRXPlaneFixReader( OGRXPlaneDataSource* poDataSource ) :
+    poFIXLayer(new OGRXPlaneFIXLayer())
 {
-    poFIXLayer = new OGRXPlaneFIXLayer();
-
     poDataSource->RegisterLayer(poFIXLayer);
 }
 
@@ -97,7 +93,7 @@ int OGRXPlaneFixReader::IsRecognizedVersion( const char* pszVersionString)
 
 void OGRXPlaneFixReader::Read()
 {
-    const char* pszLine;
+    const char* pszLine = NULL;
     while((pszLine = CPLReadLineL(fp)) != NULL)
     {
         papszTokens = CSLTokenizeString(pszLine);
@@ -109,10 +105,10 @@ void OGRXPlaneFixReader::Read()
         {
             CSLDestroy(papszTokens);
             papszTokens = NULL;
-            bEOF = TRUE;
+            bEOF = true;
             return;
         }
-        else if (nTokens == 0 || assertMinCol(3) == FALSE)
+        else if( nTokens == 0 || !assertMinCol(3) )
         {
             CSLDestroy(papszTokens);
             papszTokens = NULL;
@@ -124,12 +120,12 @@ void OGRXPlaneFixReader::Read()
         CSLDestroy(papszTokens);
         papszTokens = NULL;
 
-        if (poInterestLayer && poInterestLayer->IsEmpty() == FALSE)
+        if( poInterestLayer && !poInterestLayer->IsEmpty() )
             return;
     }
 
     papszTokens = NULL;
-    bEOF = TRUE;
+    bEOF = true;
 }
 
 /************************************************************************/
@@ -138,7 +134,8 @@ void OGRXPlaneFixReader::Read()
 
 void    OGRXPlaneFixReader::ParseRecord()
 {
-    double dfLat, dfLon;
+    double dfLat = 0.0;
+    double dfLon = 0.0;
     CPLString osName;
 
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 0));
@@ -148,12 +145,12 @@ void    OGRXPlaneFixReader::ParseRecord()
         poFIXLayer->AddFeature(osName, dfLat, dfLon);
 }
 
-
 /************************************************************************/
 /*                           OGRXPlaneFIXLayer()                        */
 /************************************************************************/
 
-OGRXPlaneFIXLayer::OGRXPlaneFIXLayer() : OGRXPlaneLayer("FIX")
+OGRXPlaneFIXLayer::OGRXPlaneFIXLayer() :
+    OGRXPlaneLayer("FIX")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h
index 5d9ec3e..b677005 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_fix_reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xplane_fix_reader.cpp
+ * $Id: ogr_xplane_fix_reader.cpp$
  *
  * Project:  X-Plane fix.dat file reader header
  * Purpose:  Definition of classes for X-Plane fix.dat file reader
@@ -37,7 +37,6 @@
 /*                           OGRXPlaneFIXLayer                          */
 /************************************************************************/
 
-
 class OGRXPlaneFIXLayer : public OGRXPlaneLayer
 {
   public:
@@ -61,12 +60,12 @@ class OGRXPlaneFixReader : public OGRXPlaneReader
         void                     ParseRecord();
 
     protected:
-        virtual void             Read();
+        virtual void             Read() override;
 
     public:
-                                 OGRXPlaneFixReader( OGRXPlaneDataSource* poDataSource );
-        virtual OGRXPlaneReader* CloneForLayer(OGRXPlaneLayer* poLayer);
-        virtual int              IsRecognizedVersion( const char* pszVersionString);
+        explicit                 OGRXPlaneFixReader( OGRXPlaneDataSource* poDataSource );
+        virtual OGRXPlaneReader* CloneForLayer(OGRXPlaneLayer* poLayer) override;
+        virtual int              IsRecognizedVersion( const char* pszVersionString) override;
 };
 
 #endif
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp
index a9b9a82..1ae4102 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_xplane_geo_utils.cpp
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Geo-computations
@@ -30,20 +29,20 @@
 #include "ogr_xplane_geo_utils.h"
 #include "cpl_port.h"
 
-CPL_CVSID("$Id: ogr_xplane_geo_utils.cpp 30726 2015-09-27 17:25:12Z goatbar $");
+CPL_CVSID("$Id: ogr_xplane_geo_utils.cpp 35634 2016-10-07 15:07:10Z goatbar $");
 
-#define RAD2METER            ((180./M_PI)*60.*1852.)
-#define METER2RAD            (1/RAD2METER)
+static const double RAD2METER = (180.0 / M_PI) * 60.0 * 1852.0;
+static const double METER2RAD = 1.0 / RAD2METER;
 
-#define DEG2RAD              (M_PI/180.)
-#define RAD2DEG              (1/DEG2RAD)
+static const double DEG2RAD = M_PI / 180.0;
+static const double RAD2DEG = 1.0 / DEG2RAD;
 
 static
-double OGRXPlane_Safe_acos(double x)
+double OGRXPlane_Safe_acos( double x )
 {
-    if (x > 1)
+    if( x > 1 )
         x = 1;
-    else if (x < -1)
+    else if( x < -1 )
         x = -1;
     return acos(x);
 }
@@ -52,21 +51,17 @@ double OGRXPlane_Safe_acos(double x)
 /*                         OGRXPlane_Distance()                         */
 /************************************************************************/
 
-double OGRXPlane_Distance(double LatA_deg, double LonA_deg,
-                          double LatB_deg, double LonB_deg)
+double OGRXPlane_Distance( double LatA_deg, double LonA_deg,
+                           double LatB_deg, double LonB_deg )
 {
-    double LatA_rad, LatB_rad;
-    double cosa, cosb, sina, sinb, cosP;
-    double cos_angle;
-
-    cosP = cos((LonB_deg - LonA_deg) * DEG2RAD);
-    LatA_rad = LatA_deg * DEG2RAD;
-    LatB_rad = LatB_deg * DEG2RAD;
-    cosa = cos(LatA_rad);
-    sina = sin(LatA_rad);
-    cosb = cos(LatB_rad);
-    sinb = sin(LatB_rad);
-    cos_angle = sina*sinb + cosa*cosb*cosP;
+    const double cosP = cos((LonB_deg - LonA_deg) * DEG2RAD);
+    const double LatA_rad = LatA_deg * DEG2RAD;
+    const double LatB_rad = LatB_deg * DEG2RAD;
+    const double cosa = cos(LatA_rad);
+    const double sina = sin(LatA_rad);
+    const double cosb = cos(LatB_rad);
+    const double sinb = sin(LatB_rad);
+    const double cos_angle = sina*sinb + cosa*cosb*cosP;
     return OGRXPlane_Safe_acos(cos_angle) * RAD2METER;
 }
 
@@ -74,35 +69,32 @@ double OGRXPlane_Distance(double LatA_deg, double LonA_deg,
 /*                           OGRXPlane_Track()                          */
 /************************************************************************/
 
-double OGRXPlane_Track(double LatA_deg, double LonA_deg,
-                       double LatB_deg, double LonB_deg)
+double OGRXPlane_Track( double LatA_deg, double LonA_deg,
+                        double LatB_deg, double LonB_deg )
 {
-    if (fabs (LatA_deg - 90) < 1e-10 || fabs (LatB_deg + 90) < 1e-10)
+    if( fabs (LatA_deg - 90) < 1e-10 || fabs (LatB_deg + 90) < 1e-10 )
     {
         return 180;
     }
-    else  if (fabs (LatA_deg + 90) < 1e-10 || fabs (LatB_deg - 90) < 1e-10)
+    else if( fabs (LatA_deg + 90) < 1e-10 || fabs (LatB_deg - 90) < 1e-10 )
     {
         return 0;
     }
     else
     {
-        double cos_LatA, sin_LatA, diffG, cos_diffG, sin_diffG;
-        double denom;
-        double track;
-        double LatA_rad = LatA_deg * DEG2RAD;
-        double LatB_rad = LatB_deg * DEG2RAD;
+        const double LatA_rad = LatA_deg * DEG2RAD;
+        const double LatB_rad = LatB_deg * DEG2RAD;
 
-        cos_LatA = cos(LatA_rad);
-        sin_LatA = sin(LatA_rad);
+        const double cos_LatA = cos(LatA_rad);
+        const double sin_LatA = sin(LatA_rad);
 
-        diffG = (LonA_deg - LonB_deg) * DEG2RAD;
-        cos_diffG = cos(diffG);
-        sin_diffG = sin(diffG);
+        const double diffG = (LonA_deg - LonB_deg) * DEG2RAD;
+        const double cos_diffG = cos(diffG);
+        const double sin_diffG = sin(diffG);
 
-        denom = sin_LatA * cos_diffG - cos_LatA * tan(LatB_rad);
+        const double denom = sin_LatA * cos_diffG - cos_LatA * tan(LatB_rad);
 
-        track = atan (sin_diffG / denom) * RAD2DEG;
+        double track = atan (sin_diffG / denom) * RAD2DEG;
 
         if (denom > 0.0)
         {
@@ -125,34 +117,30 @@ int OGRXPlane_ExtendPosition(double dfLatA_deg, double dfLonA_deg,
                              double dfDistance, double dfHeading,
                              double* pdfLatB_deg, double* pdfLonB_deg)
 {
-    double dfHeadingRad, cos_Heading, sin_Heading;
-    double dfDistanceRad, cos_Distance, sin_Distance;
-    double dfLatA_rad, cos_complement_LatA, sin_complement_LatA;
-    double cos_complement_latB, complement_latB;
-    double Cos_dG, dG_deg;
+    const double dfHeadingRad = dfHeading * DEG2RAD;
+    const double cos_Heading = cos (dfHeadingRad);
+    const double sin_Heading = sin (dfHeadingRad);
 
-    dfHeadingRad = dfHeading * DEG2RAD;
-    cos_Heading = cos (dfHeadingRad);
-    sin_Heading = sin (dfHeadingRad);
+    const double dfDistanceRad = dfDistance * METER2RAD;
+    const double cos_Distance = cos (dfDistanceRad);
+    const double sin_Distance = sin (dfDistanceRad);
 
-    dfDistanceRad = dfDistance * METER2RAD;
-    cos_Distance = cos (dfDistanceRad);
-    sin_Distance = sin (dfDistanceRad);
+    const double dfLatA_rad = dfLatA_deg * DEG2RAD;
+    const double cos_complement_LatA = sin(dfLatA_rad);
+    const double sin_complement_LatA = cos(dfLatA_rad);
 
-    dfLatA_rad = dfLatA_deg * DEG2RAD;
-    cos_complement_LatA = sin(dfLatA_rad);
-    sin_complement_LatA = cos(dfLatA_rad);
+    const double cos_complement_latB =
+        cos_Distance * cos_complement_LatA +
+        sin_Distance * sin_complement_LatA * cos_Heading;
 
-    cos_complement_latB = cos_Distance * cos_complement_LatA +
-                          sin_Distance * sin_complement_LatA * cos_Heading;
+    const double complement_latB  = OGRXPlane_Safe_acos(cos_complement_latB);
 
-    complement_latB  = OGRXPlane_Safe_acos(cos_complement_latB);
-
-    Cos_dG = (cos_Distance - cos_complement_latB * cos_complement_LatA) /
-                    (sin(complement_latB) * sin_complement_LatA);
+    const double Cos_dG =
+        (cos_Distance - cos_complement_latB * cos_complement_LatA) /
+        (sin(complement_latB) * sin_complement_LatA);
     *pdfLatB_deg = 90 - complement_latB * RAD2DEG;
 
-    dG_deg  = OGRXPlane_Safe_acos(Cos_dG) * RAD2DEG;
+    const double dG_deg  = OGRXPlane_Safe_acos(Cos_dG) * RAD2DEG;
 
     if (sin_Heading < 0)
         *pdfLonB_deg = dfLonA_deg - dG_deg;
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h
index 620dd62..309164b 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_geo_utils.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xplane_geo_utils.h $
+ * $Id: ogr_xplane_geo_utils.h 35911 2016-10-24 15:03:26Z goatbar $
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Definition of geo-computation functions
@@ -40,5 +40,4 @@ int OGRXPlane_ExtendPosition(double dfLatA_deg, double dfLonA_deg,
                              double dfDistance, double dfHeading,
                              double* pdfLatB_deg, double* pdfLonB_deg);
 
-
 #endif /* ndef OGR_XPLANE_GEO_UTILS_H_INCLUDED */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
index 5422085..37b5b05 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_xplane_nav_reader.cpp
  *
  * Project:  X-Plane nav.dat file reader
  * Purpose:  Implements OGRXPlaneNavReader class
@@ -29,7 +28,7 @@
 
 #include "ogr_xplane_nav_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_nav_reader.cpp 31120 2015-10-24 19:55:09Z rouault $");
+CPL_CVSID("$Id: ogr_xplane_nav_reader.cpp 36061 2016-11-01 02:26:58Z goatbar $");
 
 /************************************************************************/
 /*                   OGRXPlaneCreateNavFileReader                       */
@@ -41,35 +40,32 @@ OGRXPlaneReader* OGRXPlaneCreateNavFileReader( OGRXPlaneDataSource* poDataSource
     return poReader;
 }
 
-
 /************************************************************************/
 /*                         OGRXPlaneNavReader()                         */
 /************************************************************************/
-OGRXPlaneNavReader::OGRXPlaneNavReader()
-{
-    poILSLayer = NULL;
-    poVORLayer = NULL;
-    poNDBLayer = NULL;
-    poGSLayer = NULL;
-    poMarkerLayer = NULL;
-    poDMELayer = NULL;
-    poDMEILSLayer = NULL;
-}
+OGRXPlaneNavReader::OGRXPlaneNavReader() :
+    poILSLayer(NULL),
+    poVORLayer(NULL),
+    poNDBLayer(NULL),
+    poGSLayer(NULL),
+    poMarkerLayer(NULL),
+    poDMELayer(NULL),
+    poDMEILSLayer(NULL)
+{}
 
 /************************************************************************/
 /*                          OGRXPlaneNavReader()                        */
 /************************************************************************/
 
-OGRXPlaneNavReader::OGRXPlaneNavReader( OGRXPlaneDataSource* poDataSource )
+OGRXPlaneNavReader::OGRXPlaneNavReader( OGRXPlaneDataSource* poDataSource ) :
+    poILSLayer(new OGRXPlaneILSLayer()),
+    poVORLayer(new OGRXPlaneVORLayer()),
+    poNDBLayer(new OGRXPlaneNDBLayer()),
+    poGSLayer(new OGRXPlaneGSLayer()),
+    poMarkerLayer(new OGRXPlaneMarkerLayer()),
+    poDMELayer(new OGRXPlaneDMELayer()),
+    poDMEILSLayer(new OGRXPlaneDMEILSLayer())
 {
-    poILSLayer = new OGRXPlaneILSLayer();
-    poVORLayer = new OGRXPlaneVORLayer();
-    poNDBLayer = new OGRXPlaneNDBLayer();
-    poGSLayer = new OGRXPlaneGSLayer();
-    poMarkerLayer = new OGRXPlaneMarkerLayer();
-    poDMELayer = new OGRXPlaneDMELayer();
-    poDMEILSLayer = new OGRXPlaneDMEILSLayer();
-
     poDataSource->RegisterLayer(poILSLayer);
     poDataSource->RegisterLayer(poVORLayer);
     poDataSource->RegisterLayer(poNDBLayer);
@@ -122,30 +118,29 @@ int OGRXPlaneNavReader::IsRecognizedVersion( const char* pszVersionString)
 
 void OGRXPlaneNavReader::Read()
 {
-    const char* pszLine;
-    while((pszLine = CPLReadLineL(fp)) != NULL)
+    const char* pszLine = NULL;
+    while( (pszLine = CPLReadLineL(fp)) != NULL )
     {
-        int nType;
         papszTokens = CSLTokenizeString(pszLine);
         nTokens = CSLCount(papszTokens);
 
-        nLineNumber ++;
+        nLineNumber++;
 
         if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
         {
             CSLDestroy(papszTokens);
             papszTokens = NULL;
-            bEOF = TRUE;
+            bEOF = true;
             return;
         }
-        else if (nTokens == 0 || assertMinCol(9) == FALSE)
+        else if( nTokens == 0 || !assertMinCol(9) )
         {
             CSLDestroy(papszTokens);
             papszTokens = NULL;
             continue;
         }
 
-        nType = atoi(papszTokens[0]);
+        const int nType = atoi(papszTokens[0]);
         if (!((nType >= NAVAID_NDB && nType <= NAVAID_IM) ||
                nType == NAVAID_DME_COLOC || nType == NAVAID_DME_STANDALONE))
         {
@@ -161,41 +156,44 @@ void OGRXPlaneNavReader::Read()
         CSLDestroy(papszTokens);
         papszTokens = NULL;
 
-        if (poInterestLayer && poInterestLayer->IsEmpty() == FALSE)
+        if( poInterestLayer && !poInterestLayer->IsEmpty() )
             return;
     }
 
     papszTokens = NULL;
-    bEOF = TRUE;
+    bEOF = true;
 }
 
 /************************************************************************/
 /*                            ParseRecord()                             */
 /************************************************************************/
 
-void    OGRXPlaneNavReader::ParseRecord(int nType)
+void OGRXPlaneNavReader::ParseRecord( int nType )
 {
-    double dfVal, dfLat, dfLon, dfElevation, dfFrequency, dfRange;
-    double dfSlavedVariation = 0, dfTrueHeading = 0,
-            dfDMEBias = 0, dfSlope = 0;
-    char* pszNavaidId;
+    double dfVal = 0.0;
+    double dfTrueHeading = 0.0;
 
+    double dfLat = 0.0;
+    double dfLon = 0.0;
     RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
 
+    double dfElevation = 0.0;
     /* feet to meter */
     RET_IF_FAIL(readDoubleWithBoundsAndConversion(&dfElevation, 3, "elevation", FEET_TO_METER, -1000., 10000.));
 
+    double dfFrequency = 0.0;
     RET_IF_FAIL(readDouble(&dfFrequency, 4, "frequency"));
     /* NDB frequencies are in kHz. Others must be divided by 100 */
     /* to get a frequency in MHz */
     if (nType != NAVAID_NDB)
         dfFrequency /= 100.;
 
+    double dfRange = 0.0;
     /* nautical miles to kilometer */
     RET_IF_FAIL(readDouble(&dfRange, 5, "range"));
     dfRange *= NM_TO_KM;
 
-    pszNavaidId = papszTokens[7];
+    char* pszNavaidId = papszTokens[7];
 
     if (nType == NAVAID_NDB)
     {
@@ -225,7 +223,9 @@ void    OGRXPlaneNavReader::ParseRecord(int nType)
         const char* pszSubType = "";
         CPLString osNavaidName;
 
-        RET_IF_FAIL(readDoubleWithBounds(&dfSlavedVariation, 6, "slaved variation", -180., 180.));
+        double dfSlavedVariation = 0.0;
+        RET_IF_FAIL(readDoubleWithBounds(&dfSlavedVariation, 6,
+                                         "slaved variation", -180., 180.));
 
         if (EQUAL(papszTokens[nTokens-1], "VOR") ||
             EQUAL(papszTokens[nTokens-1], "VORTAC") ||
@@ -236,27 +236,28 @@ void    OGRXPlaneNavReader::ParseRecord(int nType)
         }
         else
         {
-            CPLDebug("XPlane", "Unexpected VOR subtype : %s", papszTokens[nTokens-1]);
+            CPLDebug("XPlane", "Unexpected VOR subtype : %s",
+                     papszTokens[nTokens-1]);
         }
 
         osNavaidName = readStringUntilEnd(8);
 
         if (poVORLayer)
             poVORLayer->AddFeature(pszNavaidId, osNavaidName, pszSubType,
-                                    dfLat, dfLon,
-                                    dfElevation, dfFrequency, dfRange, dfSlavedVariation);
+                                   dfLat, dfLon,
+                                   dfElevation, dfFrequency,
+                                   dfRange, dfSlavedVariation);
     }
     else if (nType == NAVAID_LOC_ILS || nType == NAVAID_LOC_STANDALONE)
     {
-        const char* pszAptICAO, * pszRwyNum, * pszSubType;
-
-        RET_IF_FAIL(readDoubleWithBounds(&dfTrueHeading, 6, "true heading", 0., 360.));
+        RET_IF_FAIL(readDoubleWithBounds(&dfTrueHeading, 6, "true heading",
+                                         0.0, 360.));
 
         RET_IF_FAIL(assertMinCol(11));
 
-        pszAptICAO = papszTokens[8];
-        pszRwyNum = papszTokens[9];
-        pszSubType = papszTokens[10];
+        const char *pszAptICAO = papszTokens[8];
+        const char *pszRwyNum = papszTokens[9];
+        const char *pszSubType = papszTokens[10];
 
         if (EQUAL(pszSubType, "ILS-cat-I") ||
             EQUAL(pszSubType, "ILS-cat-II") ||
@@ -268,9 +269,11 @@ void    OGRXPlaneNavReader::ParseRecord(int nType)
             EQUAL(pszSubType, "LDA-GS"))
         {
             if (poILSLayer)
-                poILSLayer->AddFeature(pszNavaidId, pszAptICAO, pszRwyNum, pszSubType,
-                                        dfLat, dfLon,
-                                        dfElevation, dfFrequency, dfRange, dfTrueHeading);
+                poILSLayer->AddFeature(pszNavaidId, pszAptICAO,
+                                       pszRwyNum, pszSubType,
+                                       dfLat, dfLon,
+                                       dfElevation, dfFrequency,
+                                       dfRange, dfTrueHeading);
         }
         else
         {
@@ -281,10 +284,8 @@ void    OGRXPlaneNavReader::ParseRecord(int nType)
     }
     else if (nType == NAVAID_GS)
     {
-        const char* pszAptICAO, * pszRwyNum, * pszSubType;
-
         RET_IF_FAIL(readDouble(&dfVal, 6, "slope & heading"));
-        dfSlope = (int)(dfVal / 1000) / 100.;
+        const double dfSlope = (int)(dfVal / 1000) / 100.;
         dfTrueHeading = dfVal - dfSlope * 100000;
         if (dfTrueHeading < 0 || dfTrueHeading > 360)
         {
@@ -295,16 +296,17 @@ void    OGRXPlaneNavReader::ParseRecord(int nType)
 
         RET_IF_FAIL(assertMinCol(11));
 
-        pszAptICAO = papszTokens[8];
-        pszRwyNum = papszTokens[9];
-        pszSubType = papszTokens[10];
+        const char *pszAptICAO = papszTokens[8];
+        const char *pszRwyNum = papszTokens[9];
+        const char *pszSubType = papszTokens[10];
 
         if (EQUAL(pszSubType, "GS") )
         {
             if (poGSLayer)
                 poGSLayer->AddFeature(pszNavaidId, pszAptICAO, pszRwyNum,
-                                        dfLat, dfLon,
-                                        dfElevation, dfFrequency, dfRange, dfTrueHeading, dfSlope);
+                                      dfLat, dfLon,
+                                      dfElevation, dfFrequency, dfRange,
+                                      dfTrueHeading, dfSlope);
         }
         else
         {
@@ -317,7 +319,8 @@ void    OGRXPlaneNavReader::ParseRecord(int nType)
     {
         const char* pszAptICAO, * pszRwyNum, * pszSubType;
 
-        RET_IF_FAIL(readDoubleWithBounds(&dfTrueHeading, 6, "true heading", 0., 360.));
+        RET_IF_FAIL(readDoubleWithBounds(&dfTrueHeading, 6, "true heading",
+                                         0.0, 360.0));
 
         RET_IF_FAIL(assertMinCol(11));
 
@@ -336,8 +339,9 @@ void    OGRXPlaneNavReader::ParseRecord(int nType)
         }
         else
         {
-            CPLDebug("XPlane", "Line %d : invalid localizer marker subtype: '%s'",
-                    nLineNumber, pszSubType);
+            CPLDebug("XPlane",
+                     "Line %d : invalid localizer marker subtype: '%s'",
+                     nLineNumber, pszSubType);
             return;
         }
     }
@@ -346,6 +350,7 @@ void    OGRXPlaneNavReader::ParseRecord(int nType)
         const char* pszSubType = "";
         CPLString osNavaidName;
 
+        double dfDMEBias = 0.0;
         RET_IF_FAIL(readDouble(&dfDMEBias, 6, "DME bias"));
         dfDMEBias *= NM_TO_KM;
 
@@ -398,12 +403,10 @@ void    OGRXPlaneNavReader::ParseRecord(int nType)
     }
     else
     {
-        CPLAssert(0);
+        CPLAssert(false);
     }
-
 }
 
-
 /************************************************************************/
 /*                           OGRXPlaneILSLayer()                        */
 /************************************************************************/
@@ -486,7 +489,6 @@ OGRFeature*
 /*                           OGRXPlaneVORLayer()                        */
 /************************************************************************/
 
-
 OGRXPlaneVORLayer::OGRXPlaneVORLayer() : OGRXPlaneLayer("VOR")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
@@ -622,7 +624,8 @@ OGRFeature*
 /*                           OGRXPlaneGSLayer                          */
 /************************************************************************/
 
-OGRXPlaneGSLayer::OGRXPlaneGSLayer() : OGRXPlaneLayer("GS")
+OGRXPlaneGSLayer::OGRXPlaneGSLayer() :
+    OGRXPlaneLayer("GS")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -697,12 +700,12 @@ OGRFeature*
     return poFeature;
 }
 
-
 /************************************************************************/
 /*                         OGRXPlaneMarkerLayer                         */
 /************************************************************************/
 
-OGRXPlaneMarkerLayer::OGRXPlaneMarkerLayer() : OGRXPlaneLayer("Marker")
+OGRXPlaneMarkerLayer::OGRXPlaneMarkerLayer() :
+    OGRXPlaneLayer("Marker")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -760,7 +763,8 @@ OGRFeature*
 /*                           OGRXPlaneDMEILSLayer                          */
 /************************************************************************/
 
-OGRXPlaneDMEILSLayer::OGRXPlaneDMEILSLayer() : OGRXPlaneLayer("DMEILS")
+OGRXPlaneDMEILSLayer::OGRXPlaneDMEILSLayer() :
+    OGRXPlaneLayer("DMEILS")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
@@ -832,8 +836,8 @@ OGRFeature*
 /*                           OGRXPlaneDMELayer                          */
 /************************************************************************/
 
-
-OGRXPlaneDMELayer::OGRXPlaneDMELayer() : OGRXPlaneLayer("DME")
+OGRXPlaneDMELayer::OGRXPlaneDMELayer() :
+    OGRXPlaneLayer("DME")
 {
     poFeatureDefn->SetGeomType( wkbPoint );
 
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h
index affb42b..ba96369 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_nav_reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xplane_nav_reader.cpp
+ * $Id: ogr_xplane_nav_reader.cpp$
  *
  * Project:  X-Plane nav.dat file reader header
  * Purpose:  Definition of classes for X-Plane nav.dat file reader
@@ -37,7 +37,6 @@
 /*                           OGRXPlaneILSLayer                          */
 /************************************************************************/
 
-
 class OGRXPlaneILSLayer : public OGRXPlaneLayer
 {
   public:
@@ -58,7 +57,6 @@ class OGRXPlaneILSLayer : public OGRXPlaneLayer
 /*                           OGRXPlaneVORLayer                          */
 /************************************************************************/
 
-
 class OGRXPlaneVORLayer : public OGRXPlaneLayer
 {
   public:
@@ -78,7 +76,6 @@ class OGRXPlaneVORLayer : public OGRXPlaneLayer
 /*                           OGRXPlaneNDBLayer                          */
 /************************************************************************/
 
-
 class OGRXPlaneNDBLayer : public OGRXPlaneLayer
 {
   public:
@@ -97,7 +94,6 @@ class OGRXPlaneNDBLayer : public OGRXPlaneLayer
 /*                           OGRXPlaneGSLayer                          */
 /************************************************************************/
 
-
 class OGRXPlaneGSLayer : public OGRXPlaneLayer
 {
   public:
@@ -118,7 +114,6 @@ class OGRXPlaneGSLayer : public OGRXPlaneLayer
 /*                          OGRXPlaneMarkerLayer                        */
 /************************************************************************/
 
-
 class OGRXPlaneMarkerLayer : public OGRXPlaneLayer
 {
   public:
@@ -136,7 +131,6 @@ class OGRXPlaneMarkerLayer : public OGRXPlaneLayer
 /*                         OGRXPlaneDMEILSLayer                         */
 /************************************************************************/
 
-
 class OGRXPlaneDMEILSLayer : public OGRXPlaneLayer
 {
   public:
@@ -152,12 +146,10 @@ class OGRXPlaneDMEILSLayer : public OGRXPlaneLayer
                                    double dfDMEBias);
 };
 
-
 /************************************************************************/
 /*                           OGRXPlaneDMELayer                          */
 /************************************************************************/
 
-
 class OGRXPlaneDMELayer : public OGRXPlaneLayer
 {
   public:
@@ -173,7 +165,6 @@ class OGRXPlaneDMELayer : public OGRXPlaneLayer
                                    double dfDMEBias);
 };
 
-
 enum
 {
     NAVAID_NDB            = 2,
@@ -188,7 +179,6 @@ enum
     NAVAID_DME_STANDALONE = 13, /* DME (including the DME element of an NDB-DME) */
 };
 
-
 /************************************************************************/
 /*                           OGRXPlaneNavReader                         */
 /************************************************************************/
@@ -209,12 +199,12 @@ class OGRXPlaneNavReader : public OGRXPlaneReader
         void                     ParseRecord(int nType);
 
     protected:
-        virtual void             Read();
+        virtual void             Read() override;
 
     public:
-                                 OGRXPlaneNavReader( OGRXPlaneDataSource* poDataSource );
-        virtual OGRXPlaneReader* CloneForLayer(OGRXPlaneLayer* poLayer);
-        virtual int              IsRecognizedVersion( const char* pszVersionString);
+        explicit                 OGRXPlaneNavReader( OGRXPlaneDataSource* poDataSource );
+        virtual OGRXPlaneReader* CloneForLayer(OGRXPlaneLayer* poLayer) override;
+        virtual int              IsRecognizedVersion( const char* pszVersionString) override;
 };
 
 #endif
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
index 2bc03d3..c2c2172 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogr_xplane_reader.cpp 32381 2015-12-20 21:37:32Z goatbar $
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Definition of classes for OGR X-Plane aeronautical data driver.
@@ -31,22 +30,21 @@
 
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogr_xplane_reader.cpp 32381 2015-12-20 21:37:32Z goatbar $");
+CPL_CVSID("$Id: ogr_xplane_reader.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /***********************************************************************/
 /*                       OGRXPlaneReader()                             */
 /***********************************************************************/
 
-OGRXPlaneReader::OGRXPlaneReader()
-{
-    papszTokens = NULL;
-    fp = NULL;
-    pszFilename = NULL;
-    bEOF = FALSE;
-    nLineNumber = 0;
-    poInterestLayer = NULL;
-    nTokens = 0;
-}
+OGRXPlaneReader::OGRXPlaneReader() :
+    nLineNumber(0),
+    papszTokens(NULL),
+    nTokens(0),
+    fp(NULL),
+    pszFilename(NULL),
+    bEOF(false),
+    poInterestLayer(NULL)
+{}
 
 /***********************************************************************/
 /*                         ~OGRXPlaneReader()                          */
@@ -69,11 +67,11 @@ OGRXPlaneReader::~OGRXPlaneReader()
 /*                         StartParsing()                               */
 /************************************************************************/
 
-int OGRXPlaneReader::StartParsing( const char * pszFilenameIn )
+bool OGRXPlaneReader::StartParsing( const char * pszFilenameIn )
 {
     fp = VSIFOpenL( pszFilenameIn, "rb" );
     if (fp == NULL)
-        return FALSE;
+        return false;
 
     fp = (VSILFILE*) VSICreateBufferedReaderHandle ( (VSIVirtualHandle*) fp );
 
@@ -83,26 +81,26 @@ int OGRXPlaneReader::StartParsing( const char * pszFilenameIn )
     {
         VSIFCloseL(fp);
         fp = NULL;
-        return FALSE;
+        return false;
     }
 
     pszLine = CPLReadLineL(fp);
-    if (!pszLine || IsRecognizedVersion(pszLine) == FALSE)
+    if( !pszLine || !IsRecognizedVersion(pszLine) )
     {
         VSIFCloseL(fp);
         fp = NULL;
-        return FALSE;
+        return false;
     }
 
-    CPLFree(this->pszFilename);
-    this->pszFilename = CPLStrdup(pszFilenameIn);
+    CPLFree(pszFilename);
+    pszFilename = CPLStrdup(pszFilenameIn);
 
     nLineNumber = 2;
     CPLDebug("XPlane", "Version/Copyright : %s", pszLine);
 
     Rewind();
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -111,19 +109,19 @@ int OGRXPlaneReader::StartParsing( const char * pszFilenameIn )
 
 void OGRXPlaneReader::Rewind()
 {
-    if (fp != NULL)
-    {
-        VSIRewindL(fp);
-        CPLReadLineL(fp);
-        CPLReadLineL(fp);
+    if (fp == NULL)
+        return;
 
-        nLineNumber = 2;
+    VSIRewindL(fp);
+    CPLReadLineL(fp);
+    CPLReadLineL(fp);
 
-        CSLDestroy(papszTokens);
-        papszTokens = NULL;
+    nLineNumber = 2;
 
-        bEOF = FALSE;
-    }
+    CSLDestroy(papszTokens);
+    papszTokens = NULL;
+
+    bEOF = false;
 }
 
 /************************************************************************/
@@ -132,7 +130,7 @@ void OGRXPlaneReader::Rewind()
 
 int OGRXPlaneReader::GetNextFeature()
 {
-    if (fp == NULL || bEOF == TRUE || poInterestLayer == NULL)
+    if( fp == NULL || bEOF || poInterestLayer == NULL )
         return FALSE;
 
     Read();
@@ -143,59 +141,60 @@ int OGRXPlaneReader::GetNextFeature()
 /*                          ReadWholeFile()                             */
 /************************************************************************/
 
-int OGRXPlaneReader::ReadWholeFile()
+bool OGRXPlaneReader::ReadWholeFile()
 {
-    if (fp == NULL || bEOF == TRUE || nLineNumber != 2 || poInterestLayer != NULL)
-        return FALSE;
+    if( fp == NULL || bEOF || nLineNumber != 2 || poInterestLayer != NULL )
+        return false;
 
     Read();
-    return TRUE;
+    return true;
 }
 
-
 /***********************************************************************/
 /*                          assertMinCol()                             */
 /***********************************************************************/
 
-int OGRXPlaneReader::assertMinCol(int nMinColNum)
+bool OGRXPlaneReader::assertMinCol( int nMinColNum ) const
 {
     if (nTokens < nMinColNum)
     {
-        CPLDebug("XPlane", "Line %d : not enough columns : %d. %d is the minimum required",
-                nLineNumber, nTokens, nMinColNum);
-        return FALSE;
+        CPLDebug("XPlane",
+                 "Line %d : not enough columns : %d. "
+                 "%d is the minimum required",
+                 nLineNumber, nTokens, nMinColNum);
+        return false;
     }
-    return TRUE;
+    return true;
 }
 
-
 /***********************************************************************/
 /*                           readDouble()                              */
 /***********************************************************************/
 
-int OGRXPlaneReader::readDouble(double* pdfValue, int iToken, const char* pszTokenDesc)
+bool OGRXPlaneReader::readDouble( double* pdfValue, int iToken,
+                                  const char* pszTokenDesc ) const
 {
-    char* pszNext;
+    char* pszNext = NULL;
     *pdfValue = CPLStrtod(papszTokens[iToken], &pszNext);
     if (*pszNext != '\0' )
     {
         CPLDebug("XPlane", "Line %d : invalid %s '%s'",
                     nLineNumber, pszTokenDesc, papszTokens[iToken]);
-        return FALSE;
+        return false;
     }
-    return TRUE;
+    return true;
 }
 
 /***********************************************************************/
 /*                  readDoubleWithBoundsAndConversion()                */
 /***********************************************************************/
 
-int OGRXPlaneReader::readDoubleWithBoundsAndConversion(
-                double* pdfValue, int iToken, const char* pszTokenDesc,
-                double dfFactor, double dfLowerBound, double dfUpperBound)
+bool OGRXPlaneReader::readDoubleWithBoundsAndConversion(
+    double* pdfValue, int iToken, const char* pszTokenDesc,
+    double dfFactor, double dfLowerBound, double dfUpperBound ) const
 {
-    int bRet = readDouble(pdfValue, iToken, pszTokenDesc);
-    if (bRet)
+    const bool bRet = readDouble(pdfValue, iToken, pszTokenDesc);
+    if( bRet )
     {
         *pdfValue *= dfFactor;
         if (*pdfValue < dfLowerBound || *pdfValue > dfUpperBound)
@@ -203,7 +202,7 @@ int OGRXPlaneReader::readDoubleWithBoundsAndConversion(
             CPLDebug("XPlane", "Line %d : %s '%s' out of bounds [%f, %f]",
                      nLineNumber, pszTokenDesc, papszTokens[iToken],
                      dfLowerBound / dfFactor, dfUpperBound / dfFactor);
-            return FALSE;
+            return false;
         }
     }
     return bRet;
@@ -213,12 +212,12 @@ int OGRXPlaneReader::readDoubleWithBoundsAndConversion(
 /*                     readDoubleWithBounds()                          */
 /***********************************************************************/
 
-int OGRXPlaneReader::readDoubleWithBounds(
-                        double* pdfValue, int iToken, const char* pszTokenDesc,
-                        double dfLowerBound, double dfUpperBound)
+bool OGRXPlaneReader::readDoubleWithBounds(
+    double* pdfValue, int iToken, const char* pszTokenDesc,
+    double dfLowerBound, double dfUpperBound ) const
 {
     return readDoubleWithBoundsAndConversion(pdfValue, iToken, pszTokenDesc,
-                                             1., dfLowerBound, dfUpperBound);
+                                             1.0, dfLowerBound, dfUpperBound);
 }
 
 /***********************************************************************/
@@ -255,15 +254,15 @@ CPLString OGRXPlaneReader::readStringUntilEnd(int iFirstTokenIndice)
     return osResult;
 }
 
-
 /***********************************************************************/
 /*                             readLatLon()                            */
 /***********************************************************************/
 
-int OGRXPlaneReader::readLatLon(double* pdfLat, double* pdfLon, int iToken)
+bool OGRXPlaneReader::readLatLon( double* pdfLat, double* pdfLon, int iToken )
 {
-    int bRet = readDoubleWithBounds(pdfLat, iToken, "latitude", -90., 90.);
-    bRet    &= readDoubleWithBounds(pdfLon, iToken + 1, "longitude", -180., 180.);
+    bool bRet = readDoubleWithBounds(pdfLat, iToken, "latitude", -90., 90.);
+    bRet     &= readDoubleWithBounds(pdfLon, iToken + 1,
+                                     "longitude", -180., 180.);
     return bRet;
 }
 
@@ -271,32 +270,31 @@ int OGRXPlaneReader::readLatLon(double* pdfLat, double* pdfLon, int iToken)
 /*                             readTrueHeading()                       */
 /***********************************************************************/
 
-int OGRXPlaneReader::readTrueHeading(double* pdfTrueHeading, int iToken, const char* pszTokenDesc)
+bool OGRXPlaneReader::readTrueHeading( double* pdfTrueHeading, int iToken,
+                                       const char* pszTokenDesc )
 {
-    int bRet = readDoubleWithBounds(pdfTrueHeading, iToken, pszTokenDesc, -180., 360.);
-    if (bRet)
+    const bool bRet = readDoubleWithBounds(pdfTrueHeading, iToken, pszTokenDesc,
+                                           -180.0, 360.0);
+    if( bRet )
     {
-        if (*pdfTrueHeading < 0.)
+        if( *pdfTrueHeading < 0. )
             *pdfTrueHeading += 180.;
     }
     return bRet;
 }
 
-
-
 /***********************************************************************/
 /*                       OGRXPlaneEnumeration()                        */
 /***********************************************************************/
 
-
-OGRXPlaneEnumeration::OGRXPlaneEnumeration(const char *pszEnumerationName,
-                            const sEnumerationElement*  osElements,
-                            int nElements) :
-                                 m_pszEnumerationName(pszEnumerationName),
-                                 m_osElements(osElements),
-                                 m_nElements(nElements)
-{
-}
+OGRXPlaneEnumeration::OGRXPlaneEnumeration(
+    const char *pszEnumerationName,
+    const sEnumerationElement*  osElements,
+    int nElements ) :
+    m_pszEnumerationName(pszEnumerationName),
+    m_osElements(osElements),
+    m_nElements(nElements)
+{}
 
 /***********************************************************************/
 /*                              GetText()                              */
diff --git a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
index 2d42863..2b9b954 100644
--- a/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
+++ b/ogr/ogrsf_frmts/xplane/ogr_xplane_reader.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_xplane.h $
+ * $Id: ogr_xplane_reader.h 35911 2016-10-24 15:03:26Z goatbar $
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Definition of classes for OGR X-Plane aeronautical data reader.
@@ -55,7 +55,7 @@ class OGRXPlaneReader
         int             nTokens;
         VSILFILE*       fp;
         char*           pszFilename;
-        int             bEOF;
+        bool            bEOF;
         OGRXPlaneLayer* poInterestLayer;
 
                                  OGRXPlaneReader();
@@ -65,22 +65,26 @@ class OGRXPlaneReader
 
         virtual OGRXPlaneReader* CloneForLayer(OGRXPlaneLayer* poLayer) = 0;
         virtual int              IsRecognizedVersion( const char* pszVersionString) = 0;
-        virtual int              StartParsing( const char * pszFilename );
+        virtual bool             StartParsing( const char * pszFilename );
         virtual void             Read() = 0;
-        virtual int              ReadWholeFile();
+        virtual bool             ReadWholeFile();
         virtual int              GetNextFeature();
         virtual void             Rewind();
 
-        int         assertMinCol(int nMinColNum);
-        int         readDouble(double* pdfValue, int iToken, const char* pszTokenDesc);
-        int         readDoubleWithBounds(double* pdfValue, int iToken, const char* pszTokenDesc,
-                                         double dfLowerBound, double dfUpperBound);
-        int         readDoubleWithBoundsAndConversion(double* pdfValue, int iToken, const char* pszTokenDesc,
-                                                      double dfFactor, double dfLowerBound, double dfUpperBound);
+        bool        assertMinCol( int nMinColNum) const;
+        bool        readDouble( double* pdfValue, int iToken,
+                                const char* pszTokenDesc) const;
+        bool        readDoubleWithBounds(
+                        double* pdfValue, int iToken, const char* pszTokenDesc,
+                        double dfLowerBound, double dfUpperBound ) const;
+        bool        readDoubleWithBoundsAndConversion(
+                        double* pdfValue, int iToken, const char* pszTokenDesc,
+                        double dfFactor,
+                        double dfLowerBound, double dfUpperBound) const;
         CPLString   readStringUntilEnd(int iFirstToken);
 
-        int         readLatLon(double* pdfLat, double* pdfLon, int iToken);
-        int         readTrueHeading(double* pdfTrueHeading, int iToken, const char* pszTokenDesc = "true heading");
+        bool        readLatLon(double* pdfLat, double* pdfLon, int iToken);
+        bool        readTrueHeading(double* pdfTrueHeading, int iToken, const char* pszTokenDesc = "true heading");
 };
 
 /************************************************************************/
@@ -114,7 +118,6 @@ class OGRXPlaneEnumeration
 static OGRXPlaneEnumeration enumerationName( #enumerationName, enumerationValues, \
                     sizeof( enumerationValues ) / sizeof( enumerationValues[0] ) );
 
-
 /***********************************************************************/
 /*                 OGRXPlaneCreateAptFileReader                        */
 /***********************************************************************/
diff --git a/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp b/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp
index 59b102e..663da30 100644
--- a/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogrxplanedatasource.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrxplanedatasource.cpp
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Implements OGRXPlaneDataSource class
@@ -30,22 +29,20 @@
 #include "ogr_xplane.h"
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogrxplanedatasource.cpp 32371 2015-12-20 20:05:48Z goatbar $");
+CPL_CVSID("$Id: ogrxplanedatasource.cpp 35599 2016-10-02 15:49:33Z goatbar $");
 
 /************************************************************************/
 /*                          OGRXPlaneDataSource()                          */
 /************************************************************************/
 
-OGRXPlaneDataSource::OGRXPlaneDataSource()
-
-{
-    pszName = NULL;
-    papoLayers = NULL;
-    nLayers = 0;
-    poReader = NULL;
-    bReadWholeFile = TRUE;
-    bWholeFiledReadingDone = FALSE;
-}
+OGRXPlaneDataSource::OGRXPlaneDataSource() :
+    pszName(NULL),
+    papoLayers(NULL),
+    nLayers(0),
+    poReader(NULL),
+    bReadWholeFile(true),
+    bWholeFiledReadingDone(false)
+{}
 
 /************************************************************************/
 /*                         ~OGRXPlaneDataSource()                       */
@@ -114,7 +111,7 @@ int OGRXPlaneDataSource::Open( const char * pszFilename, int bReadWholeFileIn )
 {
     Reset();
 
-    this->bReadWholeFile = bReadWholeFileIn;
+    bReadWholeFile = CPL_TO_BOOL(bReadWholeFileIn);
 
     const char* pszShortFilename = CPLGetFilename(pszFilename);
     if (EQUAL(pszShortFilename, "nav.dat") ||
@@ -137,16 +134,16 @@ int OGRXPlaneDataSource::Open( const char * pszFilename, int bReadWholeFileIn )
         poReader = OGRXPlaneCreateAwyFileReader(this);
     }
 
-    if (poReader && poReader->StartParsing(pszFilename) == FALSE)
+    if( poReader && !poReader->StartParsing(pszFilename) )
     {
         delete poReader;
         poReader = NULL;
     }
-    if (poReader)
+    if( poReader )
     {
         pszName = CPLStrdup(pszFilename);
 
-        if ( !bReadWholeFile )
+        if( !bReadWholeFile )
         {
             for( int i = 0; i < nLayers; i++ )
                 papoLayers[i]->SetReader(poReader->CloneForLayer(papoLayers[i]));
@@ -172,11 +169,11 @@ int OGRXPlaneDataSource::TestCapability( CPL_UNUSED const char * pszCap )
 
 void OGRXPlaneDataSource::ReadWholeFileIfNecessary()
 {
-    if (bReadWholeFile && !bWholeFiledReadingDone)
+    if( bReadWholeFile && !bWholeFiledReadingDone )
     {
         poReader->ReadWholeFile();
         for( int i = 0; i < nLayers; i++ )
             papoLayers[i]->AutoAdjustColumnsWidth();
-        bWholeFiledReadingDone = TRUE;
+        bWholeFiledReadingDone = true;
     }
 }
diff --git a/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp b/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp
index 21e82cc..c521d14 100644
--- a/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogrxplanedriver.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrxplanedriver.cpp
  *
  * Project:  X-Plane aeronautical data reader
  * Purpose:  Implements OGRXPlaneDriver.
@@ -30,6 +29,8 @@
 #include "ogr_xplane.h"
 #include "cpl_conv.h"
 
+CPL_CVSID("$Id: ogrxplanedriver.cpp 35676 2016-10-10 05:14:51Z goatbar $");
+
 /************************************************************************/
 /*                              GetName()                               */
 /************************************************************************/
@@ -47,7 +48,7 @@ const char *OGRXPlaneDriver::GetName()
 OGRDataSource *OGRXPlaneDriver::Open( const char * pszFilename, int bUpdate )
 
 {
-    if ( bUpdate )
+    if( bUpdate )
     {
         return NULL;
     }
@@ -55,7 +56,7 @@ OGRDataSource *OGRXPlaneDriver::Open( const char * pszFilename, int bUpdate )
     if( !EQUAL(CPLGetExtension(pszFilename), "dat") )
         return NULL;
 
-    OGRXPlaneDataSource   *poDS = new OGRXPlaneDataSource();
+    OGRXPlaneDataSource *poDS = new OGRXPlaneDataSource();
 
     bool bReadWholeFile = CPLTestBool(
         CPLGetConfigOption("OGR_XPLANE_READ_WHOLE_FILE", "TRUE"));
diff --git a/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp b/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp
index bf8fb8a..f23b781 100644
--- a/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp
+++ b/ogr/ogrsf_frmts/xplane/ogrxplanelayer.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrxplanelayer.cpp
  *
  * Project:  XPlane Translator
  * Purpose:  Implements OGRXPlaneLayer class.
@@ -31,34 +30,30 @@
 #include "ogr_xplane_geo_utils.h"
 #include "ogr_xplane_reader.h"
 
-CPL_CVSID("$Id: ogrxplanelayer.cpp 33713 2016-03-12 17:41:57Z goatbar $");
+CPL_CVSID("$Id: ogrxplanelayer.cpp 35911 2016-10-24 15:03:26Z goatbar $");
 
 /************************************************************************/
 /*                            OGRXPlaneLayer()                          */
 /************************************************************************/
 
-OGRXPlaneLayer::OGRXPlaneLayer( const char* pszLayerName )
-
+OGRXPlaneLayer::OGRXPlaneLayer( const char* pszLayerName ) :
+    nFID(0),
+    nFeatureArraySize(0),
+    nFeatureArrayMaxSize(0),
+    nFeatureArrayIndex(0),
+    papoFeatures(NULL),
+    poSRS(new OGRSpatialReference()),
+    poDS(NULL),
+    poReader(NULL),
+    poFeatureDefn(new OGRFeatureDefn(pszLayerName))
 {
-    nFID = 0;
-    nFeatureArraySize = 0;
-    nFeatureArrayMaxSize = 0;
-    nFeatureArrayIndex = 0;
-    papoFeatures = NULL;
-    poDS = NULL;
-
-    poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     SetDescription( poFeatureDefn->GetName() );
     poFeatureDefn->Reference();
 
-    poSRS = new OGRSpatialReference();
     poSRS->SetWellKnownGeogCS("WGS84");
     poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poSRS);
-
-    poReader = NULL;
 }
 
-
 /************************************************************************/
 /*                            ~OGRXPlaneLayer()                            */
 /************************************************************************/
@@ -72,7 +67,7 @@ OGRXPlaneLayer::~OGRXPlaneLayer()
 
     for(int i=0;i<nFeatureArraySize;i++)
     {
-        if (papoFeatures[i])
+        if( papoFeatures[i] )
             delete papoFeatures[i];
     }
     nFeatureArraySize = 0;
@@ -80,14 +75,13 @@ OGRXPlaneLayer::~OGRXPlaneLayer()
     CPLFree(papoFeatures);
     papoFeatures = NULL;
 
-    if (poReader)
+    if( poReader )
     {
         delete poReader;
         poReader = NULL;
     }
 }
 
-
 /************************************************************************/
 /*                            ResetReading()                            */
 /************************************************************************/
@@ -95,11 +89,11 @@ OGRXPlaneLayer::~OGRXPlaneLayer()
 void OGRXPlaneLayer::ResetReading()
 
 {
-    if (poReader)
+    if( poReader )
     {
         for(int i=0;i<nFeatureArraySize;i++)
         {
-            if (papoFeatures[i])
+            if( papoFeatures[i] )
                 delete papoFeatures[i];
         }
         nFID = 0;
@@ -115,11 +109,11 @@ void OGRXPlaneLayer::ResetReading()
 
 void OGRXPlaneLayer::SetReader(OGRXPlaneReader* poReaderIn)
 {
-    if (this->poReader)
+    if( poReader )
     {
-        delete this->poReader;
+        delete poReader;
     }
-    this->poReader = poReaderIn;
+    poReader = poReaderIn;
 }
 
 /************************************************************************/
@@ -128,7 +122,7 @@ void OGRXPlaneLayer::SetReader(OGRXPlaneReader* poReaderIn)
 
 void  OGRXPlaneLayer::AutoAdjustColumnsWidth()
 {
-    if (poReader != NULL)
+    if( poReader != NULL )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "AutoAdjustColumnsWidth() only supported when reading the whole file");
@@ -138,16 +132,17 @@ void  OGRXPlaneLayer::AutoAdjustColumnsWidth()
     for(int col=0;col<poFeatureDefn->GetFieldCount();col++)
     {
         OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(col);
-        if (poFieldDefn->GetWidth() == 0)
+        if( poFieldDefn->GetWidth() == 0 )
         {
-            if (poFieldDefn->GetType() == OFTString ||
-                poFieldDefn->GetType() == OFTInteger)
+            if( poFieldDefn->GetType() == OFTString ||
+                poFieldDefn->GetType() == OFTInteger )
             {
                 int nMaxLen = 0;
-                for(int i=0;i<nFeatureArraySize;i++)
+                for( int i = 0; i < nFeatureArraySize; i++ )
                 {
-                    int nLen = static_cast<int>(strlen(papoFeatures[i]->GetFieldAsString(col)));
-                    if (nLen > nMaxLen)
+                    const int nLen = static_cast<int>(
+                        strlen(papoFeatures[i]->GetFieldAsString(col)));
+                    if( nLen > nMaxLen )
                         nMaxLen = nLen;
                 }
                 poFieldDefn->SetWidth(nMaxLen);
@@ -167,25 +162,24 @@ void  OGRXPlaneLayer::AutoAdjustColumnsWidth()
 
 OGRFeature *OGRXPlaneLayer::GetNextFeature()
 {
-    OGRFeature  *poFeature;
 
-    if (poReader)
+    if( poReader )
     {
         while( true )
         {
-            if ( nFeatureArrayIndex == nFeatureArraySize)
+            if( nFeatureArrayIndex == nFeatureArraySize )
             {
                 nFeatureArrayIndex = nFeatureArraySize = 0;
 
-                if (poReader->GetNextFeature() == FALSE)
+                if( !poReader->GetNextFeature() )
                     return NULL;
-                if (nFeatureArraySize == 0)
+                if( nFeatureArraySize == 0 )
                     return NULL;
             }
 
             do
             {
-                poFeature = papoFeatures[nFeatureArrayIndex];
+                OGRFeature *poFeature = papoFeatures[nFeatureArrayIndex];
                 papoFeatures[nFeatureArrayIndex] = NULL;
                 nFeatureArrayIndex++;
 
@@ -206,7 +200,7 @@ OGRFeature *OGRXPlaneLayer::GetNextFeature()
 
     while(nFeatureArrayIndex < nFeatureArraySize)
     {
-        poFeature = papoFeatures[nFeatureArrayIndex ++];
+        OGRFeature *poFeature = papoFeatures[nFeatureArrayIndex ++];
         CPLAssert (poFeature != NULL);
 
         if( (m_poFilterGeom == NULL
@@ -225,14 +219,14 @@ OGRFeature *OGRXPlaneLayer::GetNextFeature()
 /*                           GetFeature()                               */
 /************************************************************************/
 
-OGRFeature *  OGRXPlaneLayer::GetFeature( GIntBig nFIDIn )
+OGRFeature *OGRXPlaneLayer::GetFeature( GIntBig nFIDIn )
 {
-    if (poReader)
+    if( poReader )
         return OGRLayer::GetFeature(nFIDIn);
     else
         poDS->ReadWholeFileIfNecessary();
 
-    if (nFIDIn >= 0 && nFIDIn < nFeatureArraySize)
+    if(nFIDIn >= 0 && nFIDIn < nFeatureArraySize)
     {
         return papoFeatures[nFIDIn]->Clone();
     }
@@ -246,9 +240,9 @@ OGRFeature *  OGRXPlaneLayer::GetFeature( GIntBig nFIDIn )
 /*                      GetFeatureCount()                               */
 /************************************************************************/
 
-GIntBig  OGRXPlaneLayer::GetFeatureCount( int bForce )
+GIntBig OGRXPlaneLayer::GetFeatureCount( int bForce )
 {
-    if (poReader == NULL && m_poFilterGeom == NULL && m_poAttrQuery == NULL)
+    if( poReader == NULL && m_poFilterGeom == NULL && m_poAttrQuery == NULL )
     {
         poDS->ReadWholeFileIfNecessary();
         return nFeatureArraySize;
@@ -257,44 +251,44 @@ GIntBig  OGRXPlaneLayer::GetFeatureCount( int bForce )
         return OGRLayer::GetFeatureCount( bForce ) ;
 }
 
-
 /************************************************************************/
 /*                           SetNextByIndex()                           */
 /************************************************************************/
 
 OGRErr OGRXPlaneLayer::SetNextByIndex( GIntBig nIndex )
 {
-    if (poReader == NULL && m_poFilterGeom == NULL && m_poAttrQuery == NULL)
+    if( poReader == NULL && m_poFilterGeom == NULL && m_poAttrQuery == NULL )
     {
         poDS->ReadWholeFileIfNecessary();
-        if (nIndex < 0 || nIndex >= nFeatureArraySize)
+        if( nIndex < 0 || nIndex >= nFeatureArraySize )
             return OGRERR_FAILURE;
 
         nFeatureArrayIndex = (int)nIndex;
         return OGRERR_NONE;
     }
-    else
-        return OGRLayer::SetNextByIndex(nIndex);
+
+    return OGRLayer::SetNextByIndex(nIndex);
 }
 
 /************************************************************************/
 /*                       TestCapability()                               */
 /************************************************************************/
 
-int  OGRXPlaneLayer::TestCapability( const char * pszCap )
+int OGRXPlaneLayer::TestCapability( const char * pszCap )
 {
-    if (EQUAL(pszCap,OLCFastFeatureCount) ||
+    if( EQUAL(pszCap,OLCFastFeatureCount) ||
         EQUAL(pszCap,OLCRandomRead) ||
-        EQUAL(pszCap,OLCFastSetNextByIndex))
+        EQUAL(pszCap,OLCFastSetNextByIndex) )
     {
-        if (poReader == NULL && m_poFilterGeom == NULL && m_poAttrQuery == NULL)
+        if( poReader == NULL &&
+            m_poFilterGeom == NULL &&
+            m_poAttrQuery == NULL )
             return TRUE;
     }
 
     return FALSE;
 }
 
-
 /************************************************************************/
 /*                       RegisterFeature()                              */
 /************************************************************************/
@@ -304,10 +298,10 @@ void OGRXPlaneLayer::RegisterFeature( OGRFeature* poFeature )
     CPLAssert (poFeature != NULL);
 
     OGRGeometry* poGeom = poFeature->GetGeometryRef();
-    if (poGeom)
+    if( poGeom )
         poGeom->assignSpatialReference( poSRS );
 
-    if (nFeatureArraySize == nFeatureArrayMaxSize)
+    if( nFeatureArraySize == nFeatureArrayMaxSize )
     {
         nFeatureArrayMaxSize = 2 * nFeatureArrayMaxSize + 1;
         papoFeatures = (OGRFeature**)CPLRealloc(papoFeatures,
@@ -335,5 +329,5 @@ OGRFeatureDefn * OGRXPlaneLayer::GetLayerDefn()
 
 void OGRXPlaneLayer::SetDataSource(OGRXPlaneDataSource* poDSIn)
 {
-    this->poDS = poDSIn;
+    poDS = poDSIn;
 }
diff --git a/ogr/ogrsf_frmts/xplane/test_geo_utils.cpp b/ogr/ogrsf_frmts/xplane/test_geo_utils.cpp
index 85b9adc..6412fec 100644
--- a/ogr/ogrsf_frmts/xplane/test_geo_utils.cpp
+++ b/ogr/ogrsf_frmts/xplane/test_geo_utils.cpp
@@ -1,16 +1,17 @@
-#include <stdio.h>
+#include <cstdio>
 #include "ogr_xplane_geo_utils.h"
 
-int main(int argc, char* argv[])
+int main( int /* argc */ , char* /* argv */ [])
 {
-  double latA = 49, lonA = 2;
-  double latB = 49.1, lonB = 2.1;
-  double latC, lonC;
-  double heading;
-  double distance;
+  const double latA = 49;
+  const double lonA = 2;
+  const double latB = 49.1;
+  const double lonB = 2.1;
 
-  heading = OGRXPlane_Track(latA, lonA, latB, lonB);
-  distance = OGRXPlane_Distance(latA, lonA, latB, lonB);
+  double heading = OGRXPlane_Track(latA, lonA, latB, lonB);
+  double distance = OGRXPlane_Distance(latA, lonA, latB, lonB);
+  double latC = 0.0;
+  double lonC = 0.0;
   OGRXPlane_ExtendPosition(latA, lonA, distance, heading, &latC, &lonC);
   printf("heading=%f, distance=%f\n", heading, distance);
   printf("%.15f=%.15f, %.15f=%.15f\n", latB, latC, lonB, lonC);
diff --git a/ogr/ogrspatialreference.cpp b/ogr/ogrspatialreference.cpp
index d19030b..d0dd12d 100644
--- a/ogr/ogrspatialreference.cpp
+++ b/ogr/ogrspatialreference.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrspatialreference.cpp 33432 2016-02-12 01:11:41Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSpatialReference class.
@@ -28,14 +27,29 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "ogr_spatialref.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
 #include "cpl_atomic_ops.h"
+#include "cpl_conv.h"
 #include "cpl_csv.h"
+#include "cpl_error.h"
 #include "cpl_http.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "ogr_core.h"
 #include "ogr_p.h"
-#include "ogr_spatialref.h"
+#include "ogr_srs_api.h"
 
-CPL_CVSID("$Id: ogrspatialreference.cpp 33432 2016-02-12 01:11:41Z goatbar $");
+CPL_CVSID("$Id: ogrspatialreference.cpp 37774 2017-03-18 20:52:44Z rouault $");
 
 // The current opinion is that WKT longitudes like central meridian
 // should be relative to Greenwich, not the prime meridian in use.
@@ -59,8 +73,8 @@ void OGRsnPrintDouble( char * pszStrBuf, size_t size, double dfValue )
     // The following hack is intended to truncate some "precision" in cases
     // that appear to be roundoff error.
     if( nLen > 15
-        && (strcmp(pszStrBuf+nLen-6,"999999") == 0
-            || strcmp(pszStrBuf+nLen-6,"000001") == 0) )
+        && (strcmp(pszStrBuf+nLen-6, "999999") == 0
+            || strcmp(pszStrBuf+nLen-6, "000001") == 0) )
     {
         CPLsnprintf( pszStrBuf, size, "%.15g", dfValue );
     }
@@ -73,7 +87,6 @@ void OGRsnPrintDouble( char * pszStrBuf, size_t size, double dfValue )
     }
 }
 
-
 /************************************************************************/
 /*                        OGRSpatialReference()                         */
 /************************************************************************/
@@ -134,10 +147,11 @@ OGRSpatialReferenceH CPL_STDCALL OSRNewSpatialReference( const char *pszWKT )
 
 /************************************************************************/
 /*                        OGRSpatialReference()                         */
-/*                                                                      */
-/*      Simple copy constructor.  See also Clone().                     */
 /************************************************************************/
 
+/** Simple copy constructor. See also Clone().
+ * @param oOther other spatial reference
+ */
 OGRSpatialReference::OGRSpatialReference(const OGRSpatialReference &oOther) :
     dfFromGreenwich(0.0),
     dfToMeter(0.0),
@@ -166,8 +180,7 @@ OGRSpatialReference::OGRSpatialReference(const OGRSpatialReference &oOther) :
 OGRSpatialReference::~OGRSpatialReference()
 
 {
-    if( poRoot != NULL )
-        delete poRoot;
+    delete poRoot;
 }
 
 /************************************************************************/
@@ -226,9 +239,7 @@ void CPL_STDCALL OSRDestroySpatialReference( OGRSpatialReferenceH hSRS )
 void OGRSpatialReference::Clear()
 
 {
-    if( poRoot )
-        delete poRoot;
-
+    delete poRoot;
     poRoot = NULL;
 
     bNormInfoSet = FALSE;
@@ -241,14 +252,25 @@ void OGRSpatialReference::Clear()
 /*                             operator=()                              */
 /************************************************************************/
 
+/** Assignment operator.
+ * @param oSource SRS to assing to *this
+ * @return *this
+ */
 OGRSpatialReference &
 OGRSpatialReference::operator=(const OGRSpatialReference &oSource)
 
 {
-    Clear();
+    if( &oSource != this )
+    {
+        Clear();
+#ifdef CPPCHECK
+        // Otherwise cppcheck would protest that nRefCount isn't modified
+        nRefCount = (nRefCount + 1) - 1;
+#endif
 
-    if( oSource.poRoot != NULL )
-        poRoot = oSource.poRoot->Clone();
+        if( oSource.poRoot != NULL )
+            poRoot = oSource.poRoot->Clone();
+    }
 
     return *this;
 }
@@ -396,9 +418,7 @@ void OSRRelease( OGRSpatialReferenceH hSRS )
 void OGRSpatialReference::SetRoot( OGR_SRSNode * poNewRoot )
 
 {
-    if( poRoot != NULL )
-        delete poRoot;
-
+    delete poRoot;
     poRoot = poNewRoot;
 }
 
@@ -447,6 +467,24 @@ OGR_SRSNode *OGRSpatialReference::GetAttrNode( const char * pszNodePath )
     return poNode;
 }
 
+/**
+ * \brief Find named node in tree.
+ *
+ * This method does a pre-order traversal of the node tree searching for
+ * a node with this exact value (case insensitive), and returns it.  Leaf
+ * nodes are not considered, under the assumption that they are just
+ * attribute value nodes.
+ *
+ * If a node appears more than once in the tree (such as UNIT for instance),
+ * the first encountered will be returned.  Use GetNode() on a subtree to be
+ * more specific.
+ *
+ * @param pszNodePath the name of the node to search for.  May contain multiple
+ * components such as "GEOGCS|UNIT".
+ *
+ * @return a pointer to the node found, or NULL if none.
+ */
+
 const OGR_SRSNode *
 OGRSpatialReference::GetAttrNode( const char * pszNodePath ) const
 
@@ -553,17 +591,17 @@ OGRSpatialReferenceH CPL_STDCALL OSRClone( OGRSpatialReferenceH hSRS )
 
 /************************************************************************/
 /*                            dumpReadable()                            */
-/*                                                                      */
-/*      Dump pretty wkt to stdout, mostly for debugging.                */
 /************************************************************************/
 
+/** Dump pretty wkt to stdout, mostly for debugging.
+ */
 void OGRSpatialReference::dumpReadable()
 
 {
     char *pszPrettyWkt = NULL;
 
     exportToPrettyWkt( &pszPrettyWkt, FALSE );
-    printf( "%s\n", pszPrettyWkt );
+    printf( "%s\n", pszPrettyWkt );/*ok*/
     CPLFree( pszPrettyWkt );
 }
 
@@ -574,7 +612,7 @@ void OGRSpatialReference::dumpReadable()
 /**
  * Convert this SRS into a nicely formatted WKT string for display to a person.
  *
- * Note that the returned WKT string should be freed with OGRFree() or
+ * Note that the returned WKT string should be freed with
  * CPLFree() when no longer needed.  It is the responsibility of the caller.
  *
  * This method is the same as the C function OSRExportToPrettyWkt().
@@ -617,7 +655,6 @@ OGRErr OGRSpatialReference::exportToPrettyWkt( char ** ppszResult,
 /*                        OSRExportToPrettyWkt()                        */
 /************************************************************************/
 
-
 /**
  * \brief Convert this SRS into a nicely formatted WKT string for display to a
  * person.
@@ -644,7 +681,7 @@ OGRErr CPL_STDCALL OSRExportToPrettyWkt( OGRSpatialReferenceH hSRS, char ** ppsz
 /**
  * \brief Convert this SRS into WKT format.
  *
- * Note that the returned WKT string should be freed with OGRFree() or
+ * Note that the returned WKT string should be freed with
  * CPLFree() when no longer needed.  It is the responsibility of the caller.
  *
  * This method is the same as the C function OSRExportToWkt().
@@ -713,15 +750,15 @@ OGRErr CPL_STDCALL OSRExportToWkt( OGRSpatialReferenceH hSRS,
 OGRErr OGRSpatialReference::importFromWkt( char ** ppszInput )
 
 {
-    if ( !ppszInput || !*ppszInput )
+    if( !ppszInput || !*ppszInput )
         return OGRERR_FAILURE;
 
     Clear();
 
     poRoot = new OGR_SRSNode();
 
-    OGRErr eErr = poRoot->importFromWkt( ppszInput );
-    if (eErr != OGRERR_NONE)
+    const OGRErr eErr = poRoot->importFromWkt( ppszInput );
+    if( eErr != OGRERR_NONE )
         return eErr;
 
 /* -------------------------------------------------------------------- */
@@ -731,16 +768,16 @@ OGRErr OGRSpatialReference::importFromWkt( char ** ppszInput )
 /*      need to extend this somewhat to bring it into an acceptable     */
 /*      OGRSpatialReference organization at some point.                 */
 /* -------------------------------------------------------------------- */
-    if (strlen(*ppszInput) > 0 && strstr(*ppszInput, "VERTCS"))
+    if( strlen(*ppszInput) > 0 && strstr(*ppszInput, "VERTCS") )
     {
-        if(((*ppszInput)[0]) == ',')
+        if( ((*ppszInput)[0]) == ',' )
             (*ppszInput)++;
         OGR_SRSNode *poNewChild = new OGR_SRSNode();
         poRoot->AddChild( poNewChild );
         return poNewChild->importFromWkt( ppszInput );
     }
 
-    return eErr;
+    return OGRERR_NONE;
 }
 
 /************************************************************************/
@@ -758,7 +795,9 @@ OGRErr OSRImportFromWkt( OGRSpatialReferenceH hSRS, char **ppszInput )
 {
     VALIDATE_POINTER1( hSRS, "OSRImportFromWkt", OGRERR_FAILURE );
 
-    return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromWkt( ppszInput );
+    return
+        reinterpret_cast<OGRSpatialReference *>(hSRS)->
+            importFromWkt( ppszInput );
 }
 
 /************************************************************************/
@@ -797,7 +836,7 @@ OGRErr OGRSpatialReference::SetNode( const char * pszNodePath,
         return OGRERR_FAILURE;
     }
 
-    if( GetRoot() == NULL || !EQUAL(papszPathTokens[0],GetRoot()->GetValue()) )
+    if( GetRoot() == NULL || !EQUAL(papszPathTokens[0], GetRoot()->GetValue()) )
     {
         SetRoot( new OGR_SRSNode( papszPathTokens[0] ) );
     }
@@ -805,11 +844,11 @@ OGRErr OGRSpatialReference::SetNode( const char * pszNodePath,
     OGR_SRSNode *poNode = GetRoot();
     for( int i = 1; papszPathTokens[i] != NULL; i++ )
     {
-        int j;
+        int j = 0;  // Used after for.
 
-        for( j = 0; j < poNode->GetChildCount(); j++ )
+        for( ; j < poNode->GetChildCount(); j++ )
         {
-            if( EQUAL(poNode->GetChild( j )->GetValue(),papszPathTokens[i]) )
+            if( EQUAL(poNode->GetChild( j )->GetValue(), papszPathTokens[i]) )
             {
                 poNode = poNode->GetChild(j);
                 j = -1;
@@ -861,13 +900,30 @@ OGRErr CPL_STDCALL OSRSetAttrValue( OGRSpatialReferenceH hSRS,
 /*                              SetNode()                               */
 /************************************************************************/
 
+/**
+ * \brief Set attribute value in spatial reference.
+ *
+ * Missing intermediate nodes in the path will be created if not already
+ * in existence.  If the attribute has no children one will be created and
+ * assigned the value otherwise the zeroth child will be assigned the value.
+ *
+ * This method does the same as the C function OSRSetAttrValue().
+ *
+ * @param pszNodePath full path to attribute to be set.  For instance
+ * "PROJCS|GEOGCS|UNIT".
+ *
+ * @param dfValue value to be assigned to node.
+ *
+ * @return OGRERR_NONE on success.
+ */
+
 OGRErr OGRSpatialReference::SetNode( const char *pszNodePath,
                                      double dfValue )
 
 {
     char szValue[64] = { '\0' };
 
-    if( ABS(dfValue - static_cast<int>(dfValue)) == 0.0 )
+    if( std::abs(dfValue - static_cast<int>(dfValue)) == 0.0 )
         snprintf( szValue, sizeof(szValue), "%d", static_cast<int>(dfValue) );
     else
         OGRsnPrintDouble( szValue, sizeof(szValue), dfValue );
@@ -915,7 +971,7 @@ OGRErr OGRSpatialReference::SetAngularUnits( const char * pszUnitsName,
     if( poCS->FindChild( "UNIT" ) >= 0 )
     {
         poUnits = poCS->GetChild( poCS->FindChild( "UNIT" ) );
-        if (poUnits->GetChildCount() < 2)
+        if( poUnits->GetChildCount() < 2 )
             return OGRERR_FAILURE;
         poUnits->GetChild(0)->SetValue( pszUnitsName );
         poUnits->GetChild(1)->SetValue( szValue );
@@ -988,7 +1044,7 @@ double OGRSpatialReference::GetAngularUnits( char ** ppszName ) const
     {
         const OGR_SRSNode *poChild = poCS->GetChild(iChild);
 
-        if( EQUAL(poChild->GetValue(),"UNIT")
+        if( EQUAL(poChild->GetValue(), "UNIT")
             && poChild->GetChildCount() >= 2 )
         {
             if( ppszName != NULL )
@@ -1060,10 +1116,11 @@ OGRErr OGRSpatialReference::SetLinearUnitsAndUpdateParameters(
     {
         const OGR_SRSNode *poChild = poPROJCS->GetChild(iChild);
 
-        if( EQUAL(poChild->GetValue(),"PARAMETER")
+        if( EQUAL(poChild->GetValue(), "PARAMETER")
             && poChild->GetChildCount() > 1 )
         {
-            char * const pszParmName = CPLStrdup(poChild->GetChild(0)->GetValue());
+            char *const pszParmName =
+                CPLStrdup(poChild->GetChild(0)->GetValue());
 
             if( IsLinearParameter( pszParmName ) )
             {
@@ -1205,8 +1262,9 @@ OGRErr OGRSpatialReference::SetTargetLinearUnits( const char *pszTargetKey,
         return OGRERR_FAILURE;
 
     char szValue[128] = { '\0' };
-    if( dfInMeters == (int) dfInMeters )
-        snprintf( szValue, sizeof(szValue), "%d", static_cast<int>(dfInMeters) );
+    if( dfInMeters == static_cast<int>(dfInMeters) )
+        snprintf( szValue, sizeof(szValue),
+                  "%d", static_cast<int>(dfInMeters) );
     else
         OGRsnPrintDouble( szValue, sizeof(szValue), dfInMeters );
 
@@ -1214,7 +1272,7 @@ OGRErr OGRSpatialReference::SetTargetLinearUnits( const char *pszTargetKey,
     if( poCS->FindChild( "UNIT" ) >= 0 )
     {
         poUnits = poCS->GetChild( poCS->FindChild( "UNIT" ) );
-        if (poUnits->GetChildCount() < 2)
+        if( poUnits->GetChildCount() < 2 )
             return OGRERR_FAILURE;
         poUnits->GetChild(0)->SetValue( pszUnitsName );
         poUnits->GetChild(1)->SetValue( szValue );
@@ -1266,7 +1324,7 @@ OGRErr OSRSetTargetLinearUnits( OGRSpatialReferenceH hSRS,
  * This method only checks directly under the PROJCS, GEOCCS or LOCAL_CS node
  * for units.
  *
- * This method does the same thing as the C function OSRGetLinearUnits()/
+ * This method does the same thing as the C function OSRGetLinearUnits()
  *
  * @param ppszName a pointer to be updated with the pointer to the units name.
  * The returned value remains internal to the OGRSpatialReference and should
@@ -1309,13 +1367,15 @@ double OSRGetLinearUnits( OGRSpatialReferenceH hSRS, char ** ppszName )
  *
  * If no units are available, a value of "Meters" and 1.0 will be assumed.
  *
- * This method does the same thing as the C function OSRGetTargetLinearUnits()/
+ * This method does the same thing as the C function OSRGetTargetLinearUnits()
  *
- * @param pszTargetKey the key to look on. i.e. "PROJCS" or "VERT_CS".  @param
- * ppszName a pointer to be updated with the pointer to the units name.  The
- * returned value remains internal to the OGRSpatialReference and should not
+ * @param pszTargetKey the key to look on. i.e. "PROJCS" or "VERT_CS". Might be
+ * NULL, in which case PROJCS will be implied (and if not found, LOCAL_CS,
+ * GEOCCS and VERT_CS are looked up)
+ * @param ppszName a pointer to be updated with the pointer to the units name.
+ * The returned value remains internal to the OGRSpatialReference and should not
  * be freed, or modified.  It may be invalidated on the next
- * OGRSpatialReference call.
+ * OGRSpatialReference call. ppszName can be set to NULL.
  *
  * @return the value to multiply by linear distances to transform them to
  * meters.
@@ -1353,7 +1413,7 @@ double OGRSpatialReference::GetTargetLinearUnits( const char *pszTargetKey,
     {
         const OGR_SRSNode *poChild = poCS->GetChild(iChild);
 
-        if( EQUAL(poChild->GetValue(),"UNIT")
+        if( EQUAL(poChild->GetValue(), "UNIT")
             && poChild->GetChildCount() >= 2 )
         {
             if( ppszName != NULL )
@@ -1533,7 +1593,7 @@ OGRSpatialReference::SetGeogCS( const char * pszGeogName,
     {
         OGR_SRSNode *poCS = NULL;
 
-        if( EQUAL(GetRoot()->GetValue(),"GEOGCS") )
+        if( EQUAL(GetRoot()->GetValue(), "GEOGCS") )
             Clear();
         else if( (poCS = GetAttrNode( "PROJCS" )) != NULL
                  && poCS->FindChild( "GEOGCS" ) != -1 )
@@ -1575,7 +1635,7 @@ OGRSpatialReference::SetGeogCS( const char * pszGeogName,
     OGR_SRSNode *poSpheroid = new OGR_SRSNode( "SPHEROID" );
     poSpheroid->AddChild( new OGR_SRSNode( pszSpheroidName ) );
 
-    char szValue[128];
+    char szValue[128] = {};
     OGRsnPrintDouble( szValue, sizeof(szValue), dfSemiMajor );
     poSpheroid->AddChild( new OGR_SRSNode(szValue) );
 
@@ -1620,7 +1680,7 @@ OGRSpatialReference::SetGeogCS( const char * pszGeogName,
 /* -------------------------------------------------------------------- */
 /*      Attach below the PROJCS if there is one, or make this the root. */
 /* -------------------------------------------------------------------- */
-    if( GetRoot() != NULL && EQUAL(GetRoot()->GetValue(),"PROJCS") )
+    if( GetRoot() != NULL && EQUAL(GetRoot()->GetValue(), "PROJCS") )
         poRoot->InsertChild( poGeogCS, 1 );
     else
         SetRoot( poGeogCS );
@@ -1722,20 +1782,38 @@ OGRErr OGRSpatialReference::SetWellKnownGeogCS( const char * pszName )
 /* -------------------------------------------------------------------- */
     char *pszWKT = NULL;
 
-    if( EQUAL(pszName, "WGS84") || EQUAL(pszName,"CRS84") || EQUAL(pszName,"CRS:84") )
+    if( EQUAL(pszName, "WGS84") || EQUAL(pszName, "CRS84") ||
+        EQUAL(pszName, "CRS:84") )
         pszWKT = (char* ) SRS_WKT_WGS84;
 
     else if( EQUAL(pszName, "WGS72") )
         pszWKT = const_cast<char *>(
-            "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26,AUTHORITY[\"EPSG\",\"7043\"]],TOWGS84[0,0,4.5,0,0,0.554,0.2263],AUTHORITY[\"EPSG\",\"6322\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4322\"]]" );
-
-    else if( EQUAL(pszName, "NAD27") || EQUAL(pszName, "CRS27") || EQUAL(pszName,"CRS:27") )
-      pszWKT = const_cast<char *>(
-          "GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke 1866\",6378206.4,294.9786982138982,AUTHORITY[\"EPSG\",\"7008\"]],AUTHORITY[\"EPSG\",\"6267\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4267\"]]" );
-
-    else if( EQUAL(pszName, "NAD83") || EQUAL(pszName,"CRS83") || EQUAL(pszName,"CRS:83") )
-      pszWKT = const_cast<char *>(
-          "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]]" );
+            "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\","
+            "SPHEROID[\"WGS 72\",6378135,298.26,AUTHORITY[\"EPSG\",\"7043\"]],"
+            "TOWGS84[0,0,4.5,0,0,0.554,0.2263],AUTHORITY[\"EPSG\",\"6322\"]],"
+            "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],"
+            "UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],"
+            "AUTHORITY[\"EPSG\",\"4322\"]]" );
+
+    else if( EQUAL(pszName, "NAD27") || EQUAL(pszName, "CRS27") ||
+             EQUAL(pszName, "CRS:27") )
+        pszWKT = const_cast<char *>(
+            "GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\","
+            "SPHEROID[\"Clarke 1866\",6378206.4,294.9786982138982,"
+            "AUTHORITY[\"EPSG\",\"7008\"]],AUTHORITY[\"EPSG\",\"6267\"]],"
+            "PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],"
+            "UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],"
+            "AUTHORITY[\"EPSG\",\"4267\"]]" );
+
+    else if( EQUAL(pszName, "NAD83") || EQUAL(pszName, "CRS83") ||
+             EQUAL(pszName, "CRS:83") )
+        pszWKT = const_cast<char *>(
+            "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\","
+            "SPHEROID[\"GRS 1980\",6378137,298.257222101,"
+            "AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],"
+            "AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,"
+            "AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,"
+            "AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]]" );
 
     else
         return OGRERR_FAILURE;
@@ -1788,7 +1866,6 @@ OGRErr OSRSetWellKnownGeogCS( OGRSpatialReferenceH hSRS, const char *pszName )
  * @return OGRERR_NONE on success or an error code.
  */
 
-
 OGRErr OGRSpatialReference::CopyGeogCSFrom(
     const OGRSpatialReference * poSrcSRS )
 
@@ -1826,7 +1903,7 @@ OGRErr OGRSpatialReference::CopyGeogCSFrom(
     {
         OGR_SRSNode *poPROJCS = NULL;
 
-        if( EQUAL(GetRoot()->GetValue(),"GEOGCS") )
+        if( EQUAL(GetRoot()->GetValue(), "GEOGCS") )
             Clear();
         else if( (poPROJCS = GetAttrNode( "PROJCS" )) != NULL
                  && poPROJCS->FindChild( "GEOGCS" ) != -1 )
@@ -1838,14 +1915,14 @@ OGRErr OGRSpatialReference::CopyGeogCSFrom(
 /* -------------------------------------------------------------------- */
 /*      Find the GEOGCS node on the source.                             */
 /* -------------------------------------------------------------------- */
-    const OGR_SRSNode  *poGeogCS = poSrcSRS->GetAttrNode( "GEOGCS" );
+    const OGR_SRSNode *poGeogCS = poSrcSRS->GetAttrNode( "GEOGCS" );
     if( poGeogCS == NULL )
         return OGRERR_FAILURE;
 
 /* -------------------------------------------------------------------- */
 /*      Attach below the PROJCS if there is one, or make this the root. */
 /* -------------------------------------------------------------------- */
-    if( GetRoot() != NULL && EQUAL(GetRoot()->GetValue(),"PROJCS") )
+    if( GetRoot() != NULL && EQUAL(GetRoot()->GetValue(), "PROJCS") )
         poRoot->InsertChild( poGeogCS->Clone(), 1 );
     else
         SetRoot( poGeogCS->Clone() );
@@ -1953,7 +2030,7 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
         if( STARTS_WITH_CI(pszDefinition, "EPSG:") )
             eStatus = importFromEPSG( atoi(pszDefinition+5) );
 
-        else /* if( STARTS_WITH_CI(pszDefinition, "EPSGA:") ) */
+        else // if( STARTS_WITH_CI(pszDefinition, "EPSGA:") )
             eStatus = importFromEPSGA( atoi(pszDefinition+6) );
 
         // Do we want to turn this into a compound definition
@@ -1963,7 +2040,7 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
             OGRSpatialReference oVertSRS;
 
             eStatus = oVertSRS.importFromEPSG(
-                atoi(strchr(pszDefinition,'+')+1) );
+                atoi(strchr(pszDefinition, '+') + 1) );
             if( eStatus == OGRERR_NONE )
             {
                 OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
@@ -2006,10 +2083,10 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
         return SetWellKnownGeogCS( pszDefinition );
 
     if( STARTS_WITH_CI(pszDefinition, "DICT:")
-        && strstr(pszDefinition,",") )
+        && strstr(pszDefinition, ",") )
     {
         char *pszFile = CPLStrdup(pszDefinition+5);
-        char *pszCode = strstr(pszFile,",") + 1;
+        char *pszCode = strstr(pszFile, ",") + 1;
 
         pszCode[-1] = '\0';
 
@@ -2022,7 +2099,7 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
         return err;
     }
 
-    if( EQUAL(pszDefinition,"NAD27")
+    if( EQUAL(pszDefinition, "NAD27")
         || EQUAL(pszDefinition,"NAD83")
         || EQUAL(pszDefinition,"WGS84")
         || EQUAL(pszDefinition,"WGS72") )
@@ -2031,13 +2108,14 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
         return SetWellKnownGeogCS( pszDefinition );
     }
 
-    if( strstr(pszDefinition,"+proj") != NULL
-             || strstr(pszDefinition,"+init") != NULL )
+    if( strstr(pszDefinition, "+proj") != NULL
+             || strstr(pszDefinition, "+init") != NULL )
         return importFromProj4( pszDefinition );
 
     if( STARTS_WITH_CI(pszDefinition, "IGNF:") )
     {
-        char* pszProj4Str = (char*) CPLMalloc(6 + strlen(pszDefinition) + 1);
+        char* pszProj4Str =
+            static_cast<char *>(CPLMalloc(6 + strlen(pszDefinition) + 1));
         strcpy(pszProj4Str, "+init=");
         strcat(pszProj4Str, pszDefinition);
         const OGRErr err = importFromProj4( pszProj4Str );
@@ -2051,7 +2129,7 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
         return importFromUrl (pszDefinition);
     }
 
-    if( EQUAL(pszDefinition,"osgb:BNG") )
+    if( EQUAL(pszDefinition, "osgb:BNG") )
     {
         return importFromEPSG(27700);
     }
@@ -2071,8 +2149,8 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
     if( nBytes == nBufMax-1 )
     {
         CPLDebug( "OGR",
-                  "OGRSpatialReference::SetFromUserInput(%s), opened file\n"
-                  "but it is to large for our generous buffer.  Is it really\n"
+                  "OGRSpatialReference::SetFromUserInput(%s), opened file "
+                  "but it is to large for our generous buffer.  Is it really "
                   "just a WKT definition?", pszDefinition );
         CPLFree( pszBuffer );
         return OGRERR_FAILURE;
@@ -2087,10 +2165,10 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
     OGRErr err = OGRERR_NONE;
     if( pszBufPtr[0] == '<' )
         err = importFromXML( pszBufPtr );
-    else if( (strstr(pszBuffer,"+proj") != NULL
-              || strstr(pszBuffer,"+init") != NULL)
-             && (strstr(pszBuffer,"EXTENSION") == NULL
-                 && strstr(pszBuffer,"extension") == NULL) )
+    else if( (strstr(pszBuffer, "+proj") != NULL
+              || strstr(pszBuffer, "+init") != NULL)
+             && (strstr(pszBuffer, "EXTENSION") == NULL
+                 && strstr(pszBuffer, "extension") == NULL) )
         err = importFromProj4( pszBufPtr );
     else
     {
@@ -2100,7 +2178,7 @@ OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
             pszBufPtr += 6;
         }
 
-        /* coverity[tainted_data] */
+        // coverity[tainted_data]
         err = importFromWkt( &pszBufPtr );
         if( err == OGRERR_NONE && bESRI )
             err = morphFromESRI();
@@ -2129,7 +2207,6 @@ OGRErr CPL_STDCALL OSRSetFromUserInput( OGRSpatialReferenceH hSRS,
     return reinterpret_cast<OGRSpatialReference *>(hSRS)->SetFromUserInput( pszDef );
 }
 
-
 /************************************************************************/
 /*                          ImportFromUrl()                             */
 /************************************************************************/
@@ -2178,12 +2255,12 @@ OGRErr OGRSpatialReference::importFromUrl( const char * pszUrl )
 /*      Try to handle errors.                                           */
 /* -------------------------------------------------------------------- */
 
-    if ( psResult == NULL)
+    if( psResult == NULL )
         return OGRERR_FAILURE;
     if( psResult->nDataLen == 0
-        || CPLGetLastErrorNo() != 0 || psResult->pabyData == NULL  )
+        || CPLGetLastErrorNo() != 0 || psResult->pabyData == NULL )
     {
-        if (CPLGetLastErrorNo() == 0)
+        if( CPLGetLastErrorNo() == 0 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                     "No data was returned from the given URL" );
@@ -2192,10 +2269,11 @@ OGRErr OGRSpatialReference::importFromUrl( const char * pszUrl )
         return OGRERR_FAILURE;
     }
 
-    if (psResult->nStatus != 0)
+    if( psResult->nStatus != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Curl reports error: %d: %s", psResult->nStatus, psResult->pszErrBuf );
+                  "Curl reports error: %d: %s",
+                  psResult->nStatus, psResult->pszErrBuf );
         CPLHTTPDestroyResult( psResult );
         return OGRERR_FAILURE;
     }
@@ -2232,7 +2310,8 @@ OGRErr OSRImportFromUrl( OGRSpatialReferenceH hSRS, const char *pszUrl )
 {
     VALIDATE_POINTER1( hSRS, "OSRImportFromUrl", OGRERR_FAILURE );
 
-    return reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromUrl( pszUrl );
+    return
+        reinterpret_cast<OGRSpatialReference *>(hSRS)->importFromUrl( pszUrl );
 }
 
 /************************************************************************/
@@ -2244,7 +2323,7 @@ OGRErr OGRSpatialReference::importFromURNPart(const char* pszAuthority,
 {
 /* -------------------------------------------------------------------- */
 /*      Is this an EPSG code? Note that we import it with EPSG          */
-/*      preferred axis ordering for geographic coordinate systems!      */
+/*      preferred axis ordering for geographic coordinate systems.      */
 /* -------------------------------------------------------------------- */
     if( STARTS_WITH_CI(pszAuthority, "EPSG") )
         return importFromEPSGA( atoi(pszCode) );
@@ -2272,7 +2351,7 @@ OGRErr OGRSpatialReference::importFromURNPart(const char* pszAuthority,
         return SetWellKnownGeogCS( pszCode );
     else if( STARTS_WITH_CI(pszCode, "CRS27") )
         return SetWellKnownGeogCS( pszCode );
-    else if( STARTS_WITH_CI(pszCode, "84") ) /* urn:ogc:def:crs:OGC:2:84 */
+    else if( STARTS_WITH_CI(pszCode, "84") )  // urn:ogc:def:crs:OGC:2:84
         return SetWellKnownGeogCS( "CRS84" );
 
 /* -------------------------------------------------------------------- */
@@ -2281,13 +2360,12 @@ OGRErr OGRSpatialReference::importFromURNPart(const char* pszAuthority,
 /* -------------------------------------------------------------------- */
     else if( STARTS_WITH_CI(pszCode, "AUTO") )
     {
-      char szWMSAuto[100] = { '\0' };
+        char szWMSAuto[100] = { '\0' };
 
         if( strlen(pszCode) > sizeof(szWMSAuto)-2 )
             return OGRERR_FAILURE;
 
-        strcpy( szWMSAuto, "AUTO:" );
-        strcpy( szWMSAuto + 5, pszCode + 4 );
+        snprintf( szWMSAuto, sizeof(szWMSAuto), "AUTO:%s", pszCode + 4 );
         for( int i = 5; szWMSAuto[i] != '\0'; i++ )
         {
             if( szWMSAuto[i] == ':' )
@@ -2354,11 +2432,7 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
 /* -------------------------------------------------------------------- */
 /*      Clear any existing definition.                                  */
 /* -------------------------------------------------------------------- */
-    if( GetRoot() != NULL )
-    {
-        delete poRoot;
-        poRoot = NULL;
-    }
+    Clear();
 
 /* -------------------------------------------------------------------- */
 /*      Find code (ignoring version) out of string like:                */
@@ -2389,12 +2463,12 @@ OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
     const char *pszCode = pszCur;
 
     const char* pszComma = strchr(pszCur, ',');
-    if (pszComma == NULL)
+    if( pszComma == NULL )
         return importFromURNPart(pszAuthority, pszCode, pszURN);
 
-    /* There's a second part with the vertical SRS */
+    // There's a second part with the vertical SRS.
     pszCur = pszComma + 1;
-    if (!STARTS_WITH(pszCur, "crs:"))
+    if( !STARTS_WITH(pszCur, "crs:") )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
                   "URN %s not a supported format.", pszURN );
@@ -2500,11 +2574,7 @@ OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
 /* -------------------------------------------------------------------- */
 /*      Clear any existing definition.                                  */
 /* -------------------------------------------------------------------- */
-    if( GetRoot() != NULL )
-    {
-        delete poRoot;
-        poRoot = NULL;
-    }
+    Clear();
 
     if( STARTS_WITH_CI(pszCur, "-compound?1=") )
     {
@@ -2515,26 +2585,26 @@ OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
 /* -------------------------------------------------------------------- */
         pszCur += 12;
 
-        // extract each component CRS URL
+        // Extract each component CRS URL.
         int iComponentUrl = 2;
 
         CPLString osName = "";
         Clear();
 
-        while (iComponentUrl != -1)
+        while( iComponentUrl != -1 )
         {
-            char searchStr[5];
+            char searchStr[15] = {};
             snprintf(searchStr, sizeof(searchStr), "&%d=", iComponentUrl);
 
             const char* pszUrlEnd = strstr(pszCur, searchStr);
 
-            // figure out the next component URL
-            char* pszComponentUrl;
+            // Figure out the next component URL.
+            char* pszComponentUrl = NULL;
 
             if( pszUrlEnd )
             {
                 size_t nLen = pszUrlEnd - pszCur;
-                pszComponentUrl = (char*) CPLMalloc(nLen + 1);
+                pszComponentUrl = static_cast<char *>(CPLMalloc(nLen + 1));
                 strncpy(pszComponentUrl, pszCur, nLen);
                 pszComponentUrl[nLen] = '\0';
 
@@ -2655,7 +2725,6 @@ OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
         nUnitsId = 9001;
         dfRefLong = CPLAtof(papszTokens[1]);
         dfRefLat = CPLAtof(papszTokens[2]);
-
     }
     else if( CSLCount(papszTokens) == 2 && atoi(papszTokens[0]) == 42005 )
     {
@@ -2684,7 +2753,7 @@ OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
     switch( nProjId )
     {
       case 42001: // Auto UTM
-        SetUTM( (int) floor( (dfRefLong + 180.0) / 6.0 ) + 1,
+        SetUTM( static_cast<int>(floor( (dfRefLong + 180.0) / 6.0 )) + 1,
                 dfRefLat >= 0.0 );
         break;
 
@@ -2916,8 +2985,8 @@ OGRErr OGRSpatialReference::SetLocalCS( const char * pszName )
     if( poCS == NULL && GetRoot() != NULL )
     {
         CPLDebug( "OGR",
-                  "OGRSpatialReference::SetLocalCS(%s) failed.\n"
-                  "It appears an incompatible root node (%s) already exists.\n",
+                  "OGRSpatialReference::SetLocalCS(%s) failed.  "
+                  "It appears an incompatible root node (%s) already exists.",
                   pszName, GetRoot()->GetValue() );
         return OGRERR_FAILURE;
     }
@@ -2979,8 +3048,8 @@ OGRErr OGRSpatialReference::SetGeocCS( const char * pszName )
     if( poGeocCS == NULL && GetRoot() != NULL )
     {
         CPLDebug( "OGR",
-                  "OGRSpatialReference::SetGeocCS(%s) failed.\n"
-                  "It appears an incompatible root node (%s) already exists.\n",
+                  "OGRSpatialReference::SetGeocCS(%s) failed.  "
+                  "It appears an incompatible root node (%s) already exists.",
                   pszName, GetRoot()->GetValue() );
         return OGRERR_FAILURE;
     }
@@ -2991,7 +3060,7 @@ OGRErr OGRSpatialReference::SetGeocCS( const char * pszName )
     {
         OGR_SRSNode *poDatum = poGeogCS->GetNode( "DATUM" );
         OGR_SRSNode *poPRIMEM = poGeogCS->GetNode( "PRIMEM" );
-        if ( poRoot != NULL && poDatum != NULL && poPRIMEM != NULL )
+        if( poRoot != NULL && poDatum != NULL && poPRIMEM != NULL )
         {
             poRoot->InsertChild( poDatum->Clone(), 1 );
             poRoot->InsertChild( poPRIMEM->Clone(), 2 );
@@ -3079,7 +3148,7 @@ OGRErr OGRSpatialReference::SetVertCS( const char * pszVertCSName,
     else
     {
         poVertCS = new OGR_SRSNode( "VERT_CS" );
-        if( poRoot != NULL && EQUAL(poRoot->GetValue(),"COMPD_CS") )
+        if( poRoot != NULL && EQUAL(poRoot->GetValue(), "COMPD_CS") )
         {
             poRoot->AddChild( poVertCS );
         }
@@ -3243,7 +3312,7 @@ OGRErr OGRSpatialReference::SetProjCS( const char * pszName )
     OGR_SRSNode *poGeogCS = NULL;
     OGR_SRSNode *poProjCS = GetAttrNode( "PROJCS" );
 
-    if( poRoot != NULL && EQUAL(poRoot->GetValue(),"GEOGCS") )
+    if( poRoot != NULL && EQUAL(poRoot->GetValue(), "GEOGCS") )
     {
         poGeogCS = poRoot;
         poRoot = NULL;
@@ -3252,8 +3321,8 @@ OGRErr OGRSpatialReference::SetProjCS( const char * pszName )
     if( poProjCS == NULL && GetRoot() != NULL )
     {
         CPLDebug( "OGR",
-                  "OGRSpatialReference::SetProjCS(%s) failed.\n"
-                  "It appears an incompatible root node (%s) already exists.\n",
+                  "OGRSpatialReference::SetProjCS(%s) failed.  "
+                  "It appears an incompatible root node (%s) already exists.",
                   pszName, GetRoot()->GetValue() );
         return OGRERR_FAILURE;
     }
@@ -3303,7 +3372,7 @@ OGRErr OGRSpatialReference::SetProjection( const char * pszProjection )
 {
     OGR_SRSNode *poGeogCS = NULL;
 
-    if( poRoot != NULL && EQUAL(poRoot->GetValue(),"GEOGCS") )
+    if( poRoot != NULL && EQUAL(poRoot->GetValue(), "GEOGCS") )
     {
         poGeogCS = poRoot;
         poRoot = NULL;
@@ -3386,9 +3455,9 @@ OGRErr OGRSpatialReference::SetProjParm( const char * pszParmName,
     {
         poParm = poPROJCS->GetChild( iChild );
 
-        if( EQUAL(poParm->GetValue(),"PARAMETER")
+        if( EQUAL(poParm->GetValue(), "PARAMETER")
             && poParm->GetChildCount() == 2
-            && EQUAL(poParm->GetChild(0)->GetValue(),pszParmName) )
+            && EQUAL(poParm->GetChild(0)->GetValue(), pszParmName) )
         {
             poParm->GetChild(1)->SetValue( szValue );
             return OGRERR_NONE;
@@ -3457,7 +3526,7 @@ int OGRSpatialReference::FindProjParm( const char *pszParameter,
     {
         const OGR_SRSNode *poParameter = poPROJCS->GetChild(iChild);
 
-        if( EQUAL(poParameter->GetValue(),"PARAMETER")
+        if( EQUAL(poParameter->GetValue(), "PARAMETER")
             && poParameter->GetChildCount() == 2
             && EQUAL(poPROJCS->GetChild(iChild)->GetChild(0)->GetValue(),
                      pszParameter) )
@@ -3469,12 +3538,12 @@ int OGRSpatialReference::FindProjParm( const char *pszParameter,
 /* -------------------------------------------------------------------- */
 /*      Try similar names, for selected parameters.                     */
 /* -------------------------------------------------------------------- */
-    if( EQUAL(pszParameter,SRS_PP_LATITUDE_OF_ORIGIN) )
+    if( EQUAL(pszParameter, SRS_PP_LATITUDE_OF_ORIGIN) )
     {
         return FindProjParm( SRS_PP_LATITUDE_OF_CENTER, poPROJCS );
     }
 
-    if( EQUAL(pszParameter,SRS_PP_CENTRAL_MERIDIAN) )
+    if( EQUAL(pszParameter, SRS_PP_CENTRAL_MERIDIAN) )
     {
         int iChild = FindProjParm(SRS_PP_LONGITUDE_OF_CENTER, poPROJCS );
         if( iChild == -1 )
@@ -3519,7 +3588,7 @@ double OGRSpatialReference::GetProjParm( const char * pszName,
 /*      Find the desired parameter.                                     */
 /* -------------------------------------------------------------------- */
     const OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
-    if ( poPROJCS == NULL )
+    if( poPROJCS == NULL )
     {
         if( pnErr != NULL )
             *pnErr = OGRERR_FAILURE;
@@ -4107,7 +4176,7 @@ OGRErr OSRSetEC( OGRSpatialReferenceH hSRS,
 /*                             SetEckert()                              */
 /************************************************************************/
 
-OGRErr OGRSpatialReference::SetEckert( int nVariation /* 1-6 */,
+OGRErr OGRSpatialReference::SetEckert( int nVariation,  // 1-6.
                                        double dfCentralMeridian,
                                        double dfFalseEasting,
                                        double dfFalseNorthing )
@@ -4696,8 +4765,8 @@ OGRErr OGRSpatialReference::SetHOM2PNO( double dfCenterLat,
 /*                           OSRSetHOM2PNO()                            */
 /************************************************************************/
 /**
- * \brief  Set a Hotine Oblique Mercator projection using two points on projection
- *  centerline.
+ * \brief Set a Hotine Oblique Mercator projection using two points on
+ *  projection centerline.
  *
  * This is the same as the C++ method OGRSpatialReference::SetHOM2PNO()
  */
@@ -5502,14 +5571,16 @@ OGRErr OGRSpatialReference::SetUTM( int nZone, int bNorth )
     else
         SetNormProjParm( SRS_PP_FALSE_NORTHING, 10000000 );
 
-    if( EQUAL(GetAttrValue("PROJCS"),"unnamed") )
+    if( EQUAL(GetAttrValue("PROJCS"), "unnamed") )
     {
-        char    szUTMName[128];
+        char szUTMName[128] = {};
 
         if( bNorth )
-            snprintf( szUTMName, sizeof(szUTMName), "UTM Zone %d, Northern Hemisphere", nZone );
+            snprintf(szUTMName, sizeof(szUTMName),
+                     "UTM Zone %d, Northern Hemisphere", nZone);
         else
-            snprintf( szUTMName, sizeof(szUTMName), "UTM Zone %d, Southern Hemisphere", nZone );
+            snprintf(szUTMName, sizeof(szUTMName),
+                     "UTM Zone %d, Southern Hemisphere", nZone);
 
         SetNode( "PROJCS", szUTMName );
     }
@@ -5560,10 +5631,10 @@ OGRErr OSRSetUTM( OGRSpatialReferenceH hSRS, int nZone, int bNorth )
 int OGRSpatialReference::GetUTMZone( int * pbNorth ) const
 
 {
-    const char  *pszProjection = GetAttrValue( "PROJECTION" );
+    const char *pszProjection = GetAttrValue( "PROJECTION" );
 
     if( pszProjection == NULL
-        || !EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
+        || !EQUAL(pszProjection, SRS_PT_TRANSVERSE_MERCATOR) )
         return 0;
 
     if( GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) != 0.0 )
@@ -5575,7 +5646,7 @@ int OGRSpatialReference::GetUTMZone( int * pbNorth ) const
     if( fabs(GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 )-500000.0) > 0.001 )
         return 0;
 
-    double      dfFalseNorthing = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0);
+    const double dfFalseNorthing = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0);
 
     if( dfFalseNorthing != 0.0
         && fabs(dfFalseNorthing-10000000.0) > 0.001 )
@@ -5584,16 +5655,16 @@ int OGRSpatialReference::GetUTMZone( int * pbNorth ) const
     if( pbNorth != NULL )
         *pbNorth = (dfFalseNorthing == 0);
 
-    double      dfCentralMeridian = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
-                                                     0.0);
-    double      dfZone = ( dfCentralMeridian + 186.0 ) / 6.0;
+    const double dfCentralMeridian =
+        GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, 0.0);
+    const double dfZone = (dfCentralMeridian + 186.0) / 6.0;
 
-    if( ABS(dfZone - (int) dfZone - 0.5 ) > 0.00001
+    if( std::abs(dfZone - static_cast<int>(dfZone) - 0.5 ) > 0.00001
         || dfCentralMeridian < -177.00001
         || dfCentralMeridian > 177.000001 )
         return 0;
-    else
-        return (int) dfZone;
+
+    return static_cast<int>(dfZone);
 }
 
 /************************************************************************/
@@ -5617,7 +5688,7 @@ int OSRGetUTMZone( OGRSpatialReferenceH hSRS, int *pbNorth )
 /*                             SetWagner()                              */
 /************************************************************************/
 
-OGRErr OGRSpatialReference::SetWagner( int nVariation /* 1 -- 7 */,
+OGRErr OGRSpatialReference::SetWagner( int nVariation,  // 1--7.
                                        double dfCenterLat,
                                        double dfFalseEasting,
                                        double dfFalseNorthing )
@@ -5756,7 +5827,7 @@ OGRErr OGRSpatialReference::SetAuthority( const char *pszTargetKey,
 /* -------------------------------------------------------------------- */
 /*      Find the node below which the authority should be put.          */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode  *poNode = GetAttrNode( pszTargetKey );
+    OGR_SRSNode *poNode = GetAttrNode( pszTargetKey );
 
     if( poNode == NULL )
         return OGRERR_FAILURE;
@@ -5772,12 +5843,11 @@ OGRErr OGRSpatialReference::SetAuthority( const char *pszTargetKey,
 /* -------------------------------------------------------------------- */
 /*      Create a new authority node.                                    */
 /* -------------------------------------------------------------------- */
-    char   szCode[32];
-    OGR_SRSNode *poAuthNode;
+    char szCode[32] = {};
 
     snprintf( szCode, sizeof(szCode), "%d", nCode );
 
-    poAuthNode = new OGR_SRSNode( "AUTHORITY" );
+    OGR_SRSNode *poAuthNode = new OGR_SRSNode( "AUTHORITY" );
     poAuthNode->AddChild( new OGR_SRSNode( pszAuthority ) );
     poAuthNode->AddChild( new OGR_SRSNode( szCode ) );
 
@@ -5838,12 +5908,9 @@ OGRSpatialReference::GetAuthorityCode( const char *pszTargetKey ) const
 /* -------------------------------------------------------------------- */
 /*      Find the node below which the authority should be put.          */
 /* -------------------------------------------------------------------- */
-    const OGR_SRSNode  *poNode;
-
-    if( pszTargetKey == NULL )
-        poNode = poRoot;
-    else
-        poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
+    const OGR_SRSNode *poNode = pszTargetKey == NULL
+        ? poRoot
+        : GetAttrNode( pszTargetKey );
 
     if( poNode == NULL )
         return NULL;
@@ -5913,7 +5980,7 @@ OGRSpatialReference::GetAuthorityName( const char *pszTargetKey ) const
 /* -------------------------------------------------------------------- */
 /*      Find the node below which the authority should be put.          */
 /* -------------------------------------------------------------------- */
-    const OGR_SRSNode  *poNode = NULL;
+    const OGR_SRSNode *poNode = NULL;
 
     if( pszTargetKey == NULL )
         poNode = poRoot;
@@ -5980,7 +6047,7 @@ OGRErr OGRSpatialReference::StripVertical()
 
 {
     if( GetRoot() == NULL
-        || !EQUAL(GetRoot()->GetValue(),"COMPD_CS") )
+        || !EQUAL(GetRoot()->GetValue(), "COMPD_CS") )
         return OGRERR_NONE;
 
     OGR_SRSNode *poHorizontalCS = GetRoot()->GetChild( 1 );
@@ -6022,7 +6089,7 @@ OGRErr OGRSpatialReference::StripCTParms( OGR_SRSNode * poCurrent )
     if( poCurrent == NULL )
         return OGRERR_NONE;
 
-    if( poCurrent == GetRoot() && EQUAL(poCurrent->GetValue(),"LOCAL_CS") )
+    if( poCurrent == GetRoot() && EQUAL(poCurrent->GetValue(), "LOCAL_CS") )
     {
         delete poCurrent;
         poRoot = NULL;
@@ -6073,7 +6140,7 @@ int OGRSpatialReference::IsCompound() const
     if( poRoot == NULL )
         return FALSE;
 
-    return EQUAL(poRoot->GetValue(),"COMPD_CS");
+    return EQUAL(poRoot->GetValue(), "COMPD_CS");
 }
 
 /************************************************************************/
@@ -6112,9 +6179,10 @@ int OGRSpatialReference::IsProjected() const
     if( poRoot == NULL )
         return FALSE;
 
-    if( EQUAL(poRoot->GetValue(),"PROJCS") )
+
+    if( EQUAL(poRoot->GetValue(), "PROJCS") )
         return TRUE;
-    else if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
+    else if( EQUAL(poRoot->GetValue(), "COMPD_CS") )
         return GetAttrNode( "PROJCS" ) != NULL;
     else
         return FALSE;
@@ -6157,7 +6225,7 @@ int OGRSpatialReference::IsGeocentric() const
     if( poRoot == NULL )
         return FALSE;
 
-    if( EQUAL(poRoot->GetValue(),"GEOCCS") )
+    if( EQUAL(poRoot->GetValue(), "GEOCCS") )
         return TRUE;
 
     return FALSE;
@@ -6200,10 +6268,10 @@ int OGRSpatialReference::IsGeographic() const
     if( GetRoot() == NULL )
         return FALSE;
 
-    if( EQUAL(poRoot->GetValue(),"GEOGCS") )
+    if( EQUAL(poRoot->GetValue(), "GEOGCS") )
         return TRUE;
 
-    if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
+    if( EQUAL(poRoot->GetValue(), "COMPD_CS") )
         return GetAttrNode( "GEOGCS" ) != NULL
             && GetAttrNode( "PROJCS" ) == NULL;
 
@@ -6245,7 +6313,7 @@ int OGRSpatialReference::IsLocal() const
     if( GetRoot() == NULL )
         return FALSE;
 
-    return EQUAL(GetRoot()->GetValue(),"LOCAL_CS");
+    return EQUAL(GetRoot()->GetValue(), "LOCAL_CS");
 }
 
 /************************************************************************/
@@ -6285,10 +6353,10 @@ int OGRSpatialReference::IsVertical() const
     if( poRoot == NULL )
         return FALSE;
 
-    if( EQUAL(poRoot->GetValue(),"VERT_CS") )
+    if( EQUAL(poRoot->GetValue(), "VERT_CS") )
         return TRUE;
 
-    if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
+    if( EQUAL(poRoot->GetValue(), "COMPD_CS") )
         return GetAttrNode( "VERT_CS" ) != NULL;
 
     return FALSE;
@@ -6409,7 +6477,7 @@ int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) cons
     pszOtherValue = poOther->GetAttrValue( "DATUM" );
 
     if( pszThisValue != NULL && pszOtherValue != NULL
-        && !EQUAL(pszThisValue,pszOtherValue) )
+        && !EQUAL(pszThisValue, pszOtherValue) )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -6428,7 +6496,7 @@ int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) cons
     }
 
 /* -------------------------------------------------------------------- */
-/*      Do the prime meridians match?  If missing assume a value of zero.*/
+/*    Do the prime meridians match?  If missing assume a value of zero. */
 /* -------------------------------------------------------------------- */
     pszThisValue = this->GetAttrValue( "PRIMEM", 1 );
     if( pszThisValue == NULL )
@@ -6452,7 +6520,7 @@ int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) cons
     if( pszOtherValue == NULL )
         pszOtherValue = SRS_UA_DEGREE_CONV;
 
-    if( ABS(CPLAtof(pszOtherValue) - CPLAtof(pszThisValue)) > 0.00000001 )
+    if( std::abs(CPLAtof(pszOtherValue) - CPLAtof(pszThisValue)) > 0.00000001 )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -6462,13 +6530,13 @@ int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) cons
     pszThisValue = this->GetAttrValue( "SPHEROID", 1 );
     pszOtherValue = poOther->GetAttrValue( "SPHEROID", 1 );
     if( pszThisValue != NULL && pszOtherValue != NULL
-        && ABS(CPLAtof(pszThisValue) - CPLAtof(pszOtherValue)) > 0.01 )
+        && std::abs(CPLAtof(pszThisValue) - CPLAtof(pszOtherValue)) > 0.01 )
         return FALSE;
 
     pszThisValue = this->GetAttrValue( "SPHEROID", 2 );
     pszOtherValue = poOther->GetAttrValue( "SPHEROID", 2 );
     if( pszThisValue != NULL && pszOtherValue != NULL
-        && ABS(CPLAtof(pszThisValue) - CPLAtof(pszOtherValue)) > 0.0001 )
+        && std::abs(CPLAtof(pszThisValue) - CPLAtof(pszOtherValue)) > 0.0001 )
         return FALSE;
 
     return TRUE;
@@ -6531,7 +6599,7 @@ int OGRSpatialReference::IsSameVertCS( const OGRSpatialReference *poOther ) cons
     if( pszOtherValue == NULL )
         pszOtherValue = "1.0";
 
-    if( ABS(CPLAtof(pszOtherValue) - CPLAtof(pszThisValue)) > 0.00000001 )
+    if( std::abs(CPLAtof(pszOtherValue) - CPLAtof(pszThisValue)) > 0.00000001 )
         return FALSE;
 
     return TRUE;
@@ -6587,7 +6655,7 @@ int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
 /*      Do the have the same root types?  i.e. is one PROJCS and one    */
 /*      GEOGCS or perhaps LOCALCS?                                      */
 /* -------------------------------------------------------------------- */
-    if( !EQUAL(GetRoot()->GetValue(),poOtherSRS->GetRoot()->GetValue()) )
+    if( !EQUAL(GetRoot()->GetValue(), poOtherSRS->GetRoot()->GetValue()) )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
@@ -6599,17 +6667,17 @@ int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
         const char *pszValue1 = this->GetAttrValue( "PROJECTION" );
         const char *pszValue2 = poOtherSRS->GetAttrValue( "PROJECTION" );
         if( pszValue1 == NULL || pszValue2 == NULL
-            || !EQUAL(pszValue1,pszValue2) )
+            || !EQUAL(pszValue1, pszValue2) )
             return FALSE;
 
         for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
         {
             const OGR_SRSNode *poNode = poPROJCS->GetChild( iChild );
-            if( !EQUAL(poNode->GetValue(),"PARAMETER")
+            if( !EQUAL(poNode->GetValue(), "PARAMETER")
                 || poNode->GetChildCount() != 2 )
                 continue;
 
-            /* this this eventually test within some epsilon? */
+            // This this eventually test within some epsilon?
             if( this->GetProjParm( poNode->GetChild(0)->GetValue() )
                 != poOtherSRS->GetProjParm( poNode->GetChild(0)->GetValue() ) )
                 return FALSE;
@@ -6808,19 +6876,22 @@ OGRErr OSRGetTOWGS84( OGRSpatialReferenceH hSRS,
 
 /************************************************************************/
 /*                         IsAngularParameter()                         */
-/*                                                                      */
-/*      Is the passed projection parameter an angular one?              */
 /************************************************************************/
 
+/** Is the passed projection parameter an angular one?
+ *
+ * @return TRUE or FALSE
+ */
+
 int OGRSpatialReference::IsAngularParameter( const char *pszParameterName )
 
 {
     if( STARTS_WITH_CI(pszParameterName, "long")
         || STARTS_WITH_CI(pszParameterName, "lati")
-        || EQUAL(pszParameterName,SRS_PP_CENTRAL_MERIDIAN)
+        || EQUAL(pszParameterName, SRS_PP_CENTRAL_MERIDIAN)
         || STARTS_WITH_CI(pszParameterName, "standard_parallel")
-        || EQUAL(pszParameterName,SRS_PP_AZIMUTH)
-        || EQUAL(pszParameterName,SRS_PP_RECTIFIED_GRID_ANGLE) )
+        || EQUAL(pszParameterName, SRS_PP_AZIMUTH)
+        || EQUAL(pszParameterName, SRS_PP_RECTIFIED_GRID_ANGLE) )
         return TRUE;
 
     return FALSE;
@@ -6828,16 +6899,19 @@ int OGRSpatialReference::IsAngularParameter( const char *pszParameterName )
 
 /************************************************************************/
 /*                        IsLongitudeParameter()                        */
-/*                                                                      */
-/*      Is the passed projection parameter an angular longitude         */
-/*      (relative to a prime meridian)?                                 */
 /************************************************************************/
 
+/** Is the passed projection parameter an angular longitude
+ * (relative to a prime meridian)?
+ *
+ * @return TRUE or FALSE
+ */
+
 int OGRSpatialReference::IsLongitudeParameter( const char *pszParameterName )
 
 {
     if( STARTS_WITH_CI(pszParameterName, "long")
-        || EQUAL(pszParameterName,SRS_PP_CENTRAL_MERIDIAN) )
+        || EQUAL(pszParameterName, SRS_PP_CENTRAL_MERIDIAN) )
         return TRUE;
 
     return FALSE;
@@ -6845,16 +6919,18 @@ int OGRSpatialReference::IsLongitudeParameter( const char *pszParameterName )
 
 /************************************************************************/
 /*                         IsLinearParameter()                          */
-/*                                                                      */
-/*      Is the passed projection parameter an linear one measured in    */
-/*      meters or some similar linear measure.                          */
 /************************************************************************/
 
+/** Is the passed projection parameter an linear one measured in meters or
+ * some similar linear measure.
+ *
+ * @return TRUE or FALSE
+ */
 int OGRSpatialReference::IsLinearParameter( const char *pszParameterName )
 
 {
     if( STARTS_WITH_CI(pszParameterName, "false_")
-        || EQUAL(pszParameterName,SRS_PP_SATELLITE_HEIGHT) )
+        || EQUAL(pszParameterName, SRS_PP_SATELLITE_HEIGHT) )
         return TRUE;
 
     return FALSE;
@@ -7029,12 +7105,9 @@ const char *OGRSpatialReference::GetExtension( const char *pszTargetKey,
 /* -------------------------------------------------------------------- */
 /*      Find the target node.                                           */
 /* -------------------------------------------------------------------- */
-    const OGR_SRSNode  *poNode;
-
-    if( pszTargetKey == NULL )
-        poNode = poRoot;
-    else
-        poNode = const_cast<OGRSpatialReference *>(this)->GetAttrNode( pszTargetKey );
+    const OGR_SRSNode *poNode = pszTargetKey == NULL
+        ? poRoot
+        : const_cast<OGRSpatialReference *>(this)->GetAttrNode( pszTargetKey );
 
     if( poNode == NULL )
         return NULL;
@@ -7046,10 +7119,10 @@ const char *OGRSpatialReference::GetExtension( const char *pszTargetKey,
     {
         const OGR_SRSNode *poChild = poNode->GetChild(i);
 
-        if( EQUAL(poChild->GetValue(),"EXTENSION")
+        if( EQUAL(poChild->GetValue(), "EXTENSION")
             && poChild->GetChildCount() >= 2 )
         {
-            if( EQUAL(poChild->GetChild(0)->GetValue(),pszName) )
+            if( EQUAL(poChild->GetChild(0)->GetValue(), pszName) )
                 return poChild->GetChild(1)->GetValue();
         }
     }
@@ -7081,12 +7154,13 @@ OGRErr OGRSpatialReference::SetExtension( const char *pszTargetKey,
 /* -------------------------------------------------------------------- */
 /*      Find the target node.                                           */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode  *poNode = NULL;
+    OGR_SRSNode *poNode = NULL;
 
     if( pszTargetKey == NULL )
         poNode = poRoot;
     else
-        poNode = const_cast<OGRSpatialReference *>(this)->GetAttrNode( pszTargetKey );
+        poNode =
+            const_cast<OGRSpatialReference *>(this)->GetAttrNode(pszTargetKey);
 
     if( poNode == NULL )
         return OGRERR_FAILURE;
@@ -7098,10 +7172,10 @@ OGRErr OGRSpatialReference::SetExtension( const char *pszTargetKey,
     {
         OGR_SRSNode *poChild = poNode->GetChild(i);
 
-        if( EQUAL(poChild->GetValue(),"EXTENSION")
+        if( EQUAL(poChild->GetValue(), "EXTENSION")
             && poChild->GetChildCount() >= 2 )
         {
-            if( EQUAL(poChild->GetChild(0)->GetValue(),pszName) )
+            if( EQUAL(poChild->GetChild(0)->GetValue(), pszName) )
             {
                 poChild->GetChild(1)->SetValue( pszValue );
                 return OGRERR_NONE;
@@ -7178,12 +7252,13 @@ OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
 /* -------------------------------------------------------------------- */
 /*      Find the target node.                                           */
 /* -------------------------------------------------------------------- */
-    OGR_SRSNode  *poNode = NULL;
+    OGR_SRSNode *poNode = NULL;
 
     if( pszTargetKey == NULL )
         poNode = poRoot;
     else
-        poNode = const_cast<OGRSpatialReference *>(this)->GetAttrNode( pszTargetKey );
+        poNode =
+            const_cast<OGRSpatialReference *>(this)->GetAttrNode(pszTargetKey);
 
     if( poNode == NULL )
         return NULL;
@@ -7198,7 +7273,7 @@ OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
     {
         OGR_SRSNode *poChild = poNode->GetChild( iChild );
 
-        if( !EQUAL(poChild->GetValue(),"AXIS") )
+        if( !EQUAL(poChild->GetValue(), "AXIS") )
             continue;
 
         if( iAxis == 0 )
@@ -7222,19 +7297,19 @@ OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
     {
         const char *pszOrientation = poAxis->GetChild(1)->GetValue();
 
-        if( EQUAL(pszOrientation,"NORTH") )
+        if( EQUAL(pszOrientation, "NORTH") )
             *peOrientation = OAO_North;
-        else if( EQUAL(pszOrientation,"EAST") )
+        else if( EQUAL(pszOrientation, "EAST") )
             *peOrientation = OAO_East;
-        else if( EQUAL(pszOrientation,"SOUTH") )
+        else if( EQUAL(pszOrientation, "SOUTH") )
             *peOrientation = OAO_South;
-        else if( EQUAL(pszOrientation,"WEST") )
+        else if( EQUAL(pszOrientation, "WEST") )
             *peOrientation = OAO_West;
-        else if( EQUAL(pszOrientation,"UP") )
+        else if( EQUAL(pszOrientation, "UP") )
             *peOrientation = OAO_Up;
-        else if( EQUAL(pszOrientation,"DOWN") )
+        else if( EQUAL(pszOrientation, "DOWN") )
             *peOrientation = OAO_Down;
-        else if( EQUAL(pszOrientation,"OTHER") )
+        else if( EQUAL(pszOrientation, "OTHER") )
             *peOrientation = OAO_Other;
         else
         {
@@ -7421,7 +7496,7 @@ OGRErr OSRExportToMICoordSys( OGRSpatialReferenceH hSRS, char ** ppszReturn )
 /**
  * \brief Export coordinate system in Mapinfo style CoordSys format.
  *
- * Note that the returned WKT string should be freed with OGRFree() or
+ * Note that the returned WKT string should be freed with
  * CPLFree() when no longer needed.  It is the responsibility of the caller.
  *
  * This method is the same as the C function OSRExportToMICoordSys().
@@ -7429,7 +7504,7 @@ OGRErr OSRExportToMICoordSys( OGRSpatialReferenceH hSRS, char ** ppszReturn )
  * @param ppszResult pointer to which dynamically allocated Mapinfo CoordSys
  * definition will be assigned.
  *
- * @return  OGRERR_NONE on success, OGRERR_FAILURE on failure,
+ * @return OGRERR_NONE on success, OGRERR_FAILURE on failure,
  * OGRERR_UNSUPPORTED_OPERATION if MITAB library was not linked in.
  */
 
diff --git a/ogr/ogrsurface.cpp b/ogr/ogrsurface.cpp
index 9bbf4a9..f67dec8 100644
--- a/ogr/ogrsurface.cpp
+++ b/ogr/ogrsurface.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrsurface.cpp 33631 2016-03-04 06:28:09Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  The OGRSurface class.
@@ -27,9 +26,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "ogr_geometry.h"
 #include "ogr_p.h"
 
+CPL_CVSID("$Id: ogrsurface.cpp 36324 2016-11-20 02:28:41Z goatbar $");
+
 /**
  * \fn double OGRSurface::get_Area() const;
  *
@@ -47,7 +49,8 @@
 /**
  * \fn OGRErr OGRSurface::PointOnSurface( OGRPoint * poPoint ) const;
  *
- * \brief This method relates to the SFCOM ISurface::get_PointOnSurface() method.
+ * \brief This method relates to the SFCOM
+ * ISurface::get_PointOnSurface() method.
  *
  * NOTE: Only implemented when GEOS included in build.
  *
@@ -60,6 +63,7 @@
 /*                          CastToPolygon()                             */
 /************************************************************************/
 
+/*! @cond Doxygen_Suppress */
 /**
  * \brief Cast to polygon
  *
@@ -70,7 +74,7 @@
  * @return new geometry.
  */
 
-OGRPolygon* OGRSurface::CastToPolygon(OGRSurface* poSurface)
+OGRPolygon* OGRSurface::CastToPolygon( OGRSurface* poSurface )
 {
     OGRSurfaceCasterToPolygon pfn = poSurface->GetCasterToPolygon();
     return pfn(poSurface);
@@ -90,8 +94,9 @@ OGRPolygon* OGRSurface::CastToPolygon(OGRSurface* poSurface)
  * @return new geometry.
  */
 
-OGRCurvePolygon* OGRSurface::CastToCurvePolygon(OGRSurface* poSurface)
+OGRCurvePolygon* OGRSurface::CastToCurvePolygon( OGRSurface* poSurface )
 {
     OGRSurfaceCasterToCurvePolygon pfn = poSurface->GetCasterToCurvePolygon();
     return pfn(poSurface);
 }
+/*! @endcond */
diff --git a/ogr/ogrtriangle.cpp b/ogr/ogrtriangle.cpp
new file mode 100644
index 0000000..257ab0a
--- /dev/null
+++ b/ogr/ogrtriangle.cpp
@@ -0,0 +1,277 @@
+/******************************************************************************
+ * $Id: ogrtriangle.cpp 36959 2016-12-19 14:11:00Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  The OGRTriangle geometry class.
+ * Author:   Avyav Kumar Singh <avyavkumar at gmail dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Avyav Kumar Singh <avyavkumar at gmail dot com>
+ * Copyright (c) 2016, Even Rouault <even.roauult at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_geometry.h"
+#include "ogr_api.h"
+#include "cpl_error.h"
+
+CPL_CVSID("$Id: ogrtriangle.cpp 36959 2016-12-19 14:11:00Z rouault $");
+
+/************************************************************************/
+/*                             OGRTriangle()                            */
+/************************************************************************/
+
+/**
+ * \brief Constructor.
+ *
+ */
+
+OGRTriangle::OGRTriangle()
+{ }
+
+/************************************************************************/
+/*                             OGRTriangle()                            */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ */
+
+OGRTriangle::OGRTriangle(const OGRTriangle& other) :
+    OGRPolygon(other)
+{ }
+
+/************************************************************************/
+/*                             OGRTriangle()                            */
+/************************************************************************/
+
+/**
+ * \brief Constructs an OGRTriangle from a valid OGRPolygon. In case of error,
+ * NULL is returned.
+ *
+ * @param other the Polygon we wish to construct a triangle from
+ * @param eErr encapsulates an error code; contains OGRERR_NONE if the triangle
+ * is constructed successfully
+ */
+
+OGRTriangle::OGRTriangle(const OGRPolygon& other, OGRErr &eErr)
+{
+    // In case of Polygon, we have to check that it is a valid triangle -
+    // closed and contains one external ring of four points
+    // If not, then eErr will contain the error description
+    const OGRCurve *poCurve = other.getExteriorRingCurve();
+    if (other.getNumInteriorRings() == 0 &&
+        poCurve != NULL && poCurve->get_IsClosed() &&
+        poCurve->getNumPoints() == 4)
+    {
+        // everything is fine
+        eErr = addRing( const_cast<OGRCurve*>(poCurve) );
+        if (eErr != OGRERR_NONE)
+            CPLError( CE_Failure, CPLE_NotSupported, "Invalid Triangle");
+    }
+    assignSpatialReference( other.getSpatialReference() );
+}
+
+/************************************************************************/
+/*                             OGRTriangle()                            */
+/************************************************************************/
+
+/**
+ * \brief Construct a triangle from points
+ *
+ * @param p Point 1
+ * @param q Point 2
+ * @param r Point 3
+ */
+
+OGRTriangle::OGRTriangle(const OGRPoint &p, const OGRPoint &q,
+                         const OGRPoint &r)
+{
+    OGRLinearRing *poCurve = new OGRLinearRing();
+    poCurve->addPoint(&p);
+    poCurve->addPoint(&q);
+    poCurve->addPoint(&r);
+    poCurve->addPoint(&p);
+
+    oCC.addCurveDirectly(this, poCurve, TRUE);
+}
+
+/************************************************************************/
+/*                             ~OGRTriangle()                            */
+/************************************************************************/
+
+/**
+ * \brief Destructor
+ *
+ */
+
+OGRTriangle::~OGRTriangle()
+{
+}
+
+/************************************************************************/
+/*                    operator=( const OGRGeometry&)                    */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator
+ *
+ * @param other A triangle passed as a parameter
+ *
+ * @return OGRTriangle A copy of other
+ *
+ */
+
+OGRTriangle& OGRTriangle::operator=( const OGRTriangle& other )
+{
+    if( this != &other)
+    {
+        OGRPolygon::operator=( other );
+    }
+    return *this;
+}
+
+/************************************************************************/
+/*                          getGeometryName()                           */
+/************************************************************************/
+
+const char* OGRTriangle::getGeometryName() const
+{
+    return "TRIANGLE";
+}
+
+/************************************************************************/
+/*                          getGeometryType()                           */
+/************************************************************************/
+
+OGRwkbGeometryType OGRTriangle::getGeometryType() const
+{
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbTriangleZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbTriangleM;
+    else if( flags & OGR_G_3D )
+        return wkbTriangleZ;
+    else
+        return wkbTriangle;
+}
+
+/************************************************************************/
+/*                        quickValidityCheck()                          */
+/************************************************************************/
+
+bool OGRTriangle::quickValidityCheck() const
+{
+    return oCC.nCurveCount == 0 ||
+           (oCC.nCurveCount == 1 &&
+            oCC.papoCurves[0]->getNumPoints() == 4 &&
+            oCC.papoCurves[0]->get_IsClosed());
+}
+
+/************************************************************************/
+/*                           importFromWkb()                            */
+/************************************************************************/
+
+OGRErr OGRTriangle::importFromWkb( unsigned char *pabyData,
+                                  int nSize,
+                                  OGRwkbVariant eWkbVariant )
+{
+    OGRErr eErr = OGRPolygon::importFromWkb( pabyData, nSize, eWkbVariant );
+    if( eErr != OGRERR_NONE )
+        return eErr;
+
+    if ( !quickValidityCheck() )
+    {
+        CPLDebug("OGR", "Triangle is not made of a closed rings of 3 points");
+        empty();
+        return OGRERR_CORRUPT_DATA;
+    }
+
+    return OGRERR_NONE;
+}
+
+/*! @cond Doxygen_Suppress */
+/************************************************************************/
+/*                        importFromWKTListOnly()                       */
+/*                                                                      */
+/*      Instantiate from "((x y, x y, ...),(x y, ...),...)"             */
+/************************************************************************/
+
+OGRErr OGRTriangle::importFromWKTListOnly( char ** ppszInput,
+                                          int bHasZ, int bHasM,
+                                          OGRRawPoint*& paoPoints,
+                                          int& nMaxPoints,
+                                          double*& padfZ )
+
+{
+    OGRErr eErr = OGRPolygon::importFromWKTListOnly(ppszInput,
+                                                    bHasZ, bHasM,
+                                                    paoPoints,
+                                                    nMaxPoints,
+                                                    padfZ );
+    if( eErr == OGRERR_NONE )
+    {
+        if( !quickValidityCheck() )
+        {
+            CPLDebug("OGR",
+                     "Triangle is not made of a closed rings of 3 points");
+            empty();
+            eErr = OGRERR_CORRUPT_DATA;
+        }
+    }
+
+    return eErr;
+}
+/*! @endcond */
+
+/************************************************************************/
+/*                           addRingDirectly()                          */
+/************************************************************************/
+
+OGRErr OGRTriangle::addRingDirectly( OGRCurve * poNewRing )
+{
+    if (oCC.nCurveCount == 0)
+        return addRingDirectlyInternal( poNewRing, TRUE );
+    else
+        return OGRERR_FAILURE;
+}
+
+//! @cond Doxygen_Suppress
+/************************************************************************/
+/*                      GetCasterToPolygon()                            */
+/************************************************************************/
+
+OGRSurfaceCasterToPolygon OGRTriangle::GetCasterToPolygon() const {
+    return (OGRSurfaceCasterToPolygon) OGRTriangle::CastToPolygon;
+}
+
+/************************************************************************/
+/*                        CastToPolygon()                               */
+/************************************************************************/
+
+OGRGeometry* OGRTriangle::CastToPolygon(OGRGeometry* poGeom)
+{
+    OGRGeometry* poRet = new OGRPolygon( *(OGRPolygon*)poGeom );
+    delete poGeom;
+    return poRet;
+}
+//! @endcond
+
diff --git a/ogr/ogrtriangulatedsurface.cpp b/ogr/ogrtriangulatedsurface.cpp
new file mode 100644
index 0000000..69f5a8b
--- /dev/null
+++ b/ogr/ogrtriangulatedsurface.cpp
@@ -0,0 +1,276 @@
+/******************************************************************************
+ * $Id: ogrtriangulatedsurface.cpp 36962 2016-12-19 14:48:28Z rouault $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  The OGRTriangulatedSurface geometry class.
+ * Author:   Avyav Kumar Singh <avyavkumar at gmail dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Avyav Kumar Singh <avyavkumar at gmail dot com>
+ * Copyright (c) 2016, Even Rouault <even.roauult at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogr_geometry.h"
+#include "ogr_p.h"
+#include "ogr_api.h"
+
+CPL_CVSID("$Id: ogrtriangulatedsurface.cpp 36962 2016-12-19 14:48:28Z rouault $");
+
+/************************************************************************/
+/*                        OGRTriangulatedSurface()                      */
+/************************************************************************/
+
+/**
+ * \brief Constructor.
+ *
+ */
+
+OGRTriangulatedSurface::OGRTriangulatedSurface()
+
+{ }
+
+/************************************************************************/
+/*        OGRTriangulatedSurface( const OGRTriangulatedSurface& )       */
+/************************************************************************/
+
+/**
+ * \brief Copy constructor.
+ *
+ */
+
+OGRTriangulatedSurface::OGRTriangulatedSurface(
+                                        const OGRTriangulatedSurface& other ) :
+    OGRPolyhedralSurface()
+{
+    *this = other;
+}
+
+/************************************************************************/
+/*                        ~OGRTriangulatedSurface()                     */
+/************************************************************************/
+
+/**
+ * \brief Destructor
+ *
+ */
+
+OGRTriangulatedSurface::~OGRTriangulatedSurface()
+
+{ }
+
+/************************************************************************/
+/*                 operator=( const OGRTriangulatedSurface&)            */
+/************************************************************************/
+
+/**
+ * \brief Assignment operator.
+ *
+ */
+
+OGRTriangulatedSurface& OGRTriangulatedSurface::operator=(
+                                        const OGRTriangulatedSurface& other )
+{
+    if( this != &other)
+    {
+        // We need to do it manually. We cannot rely on the = operator
+        // of OGRPolyhedralSurface since it will be confused by a multipolygon
+        // of triangles.
+        OGRSurface::operator=( other );
+        empty();
+        set3D( other.Is3D() );
+        setMeasured( other.IsMeasured() );
+        assignSpatialReference( other.getSpatialReference() );
+        for(int i=0;i<other.oMP.nGeomCount;i++)
+        {
+            addGeometry( other.oMP.getGeometryRef(i) );
+        }
+    }
+    return *this;
+}
+
+/************************************************************************/
+/*                          getGeometryName()                           */
+/************************************************************************/
+
+/**
+ * \brief Returns the geometry name of the TriangulatedSurface
+ *
+ * @return "TIN"
+ *
+ */
+
+const char* OGRTriangulatedSurface::getGeometryName() const
+{
+    return "TIN" ;
+}
+
+/************************************************************************/
+/*                          getGeometryType()                           */
+/************************************************************************/
+
+/**
+ * \brief Returns the WKB Type of TriangulatedSurface
+ *
+ */
+
+OGRwkbGeometryType OGRTriangulatedSurface::getGeometryType() const
+{
+    if( (flags & OGR_G_3D) && (flags & OGR_G_MEASURED) )
+        return wkbTINZM;
+    else if( flags & OGR_G_MEASURED  )
+        return wkbTINM;
+    else if( flags & OGR_G_3D )
+        return wkbTINZ;
+    else
+        return wkbTIN;
+}
+
+/************************************************************************/
+/*                         isCompatibleSubType()                        */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRBoolean OGRTriangulatedSurface::isCompatibleSubType(
+                                        OGRwkbGeometryType eSubType ) const
+{
+    return wkbFlatten( eSubType ) == wkbTriangle;
+}
+//! @endcond
+
+/************************************************************************/
+/*                         getSubGeometryName()                         */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+const char* OGRTriangulatedSurface::getSubGeometryName() const
+{
+    return "TRIANGLE";
+}
+//! @endcond
+
+/************************************************************************/
+/*                         getSubGeometryType()                         */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRwkbGeometryType OGRTriangulatedSurface::getSubGeometryType() const
+{
+    return wkbTriangle;
+}
+//! @endcond
+
+/************************************************************************/
+/*                            addGeometry()                             */
+/************************************************************************/
+
+OGRErr OGRTriangulatedSurface::addGeometry (const OGRGeometry *poNewGeom)
+{
+    // If the geometry is a polygon, check if it can be cast as a triangle
+    if( EQUAL(poNewGeom->getGeometryName(),"POLYGON") )
+    {
+        OGRErr eErr = OGRERR_FAILURE;
+        OGRTriangle *poTriangle = new OGRTriangle(
+                    *(reinterpret_cast<const OGRPolygon *>(poNewGeom)), eErr);
+        if (poTriangle != NULL && eErr == OGRERR_NONE)
+        {
+            eErr = addGeometryDirectly(poTriangle);
+
+            if( eErr != OGRERR_NONE )
+                delete poTriangle;
+
+            return eErr;
+        }
+        else
+        {
+            delete poTriangle;
+            return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
+        }
+    }
+
+    return OGRPolyhedralSurface::addGeometry(poNewGeom);
+}
+
+/************************************************************************/
+/*                     GetCasterToMultiPolygon()                        */
+/************************************************************************/
+
+//! @cond Doxygen_Suppress
+OGRPolyhedralSurfaceCastToMultiPolygon
+                        OGRTriangulatedSurface::GetCasterToMultiPolygon() const
+{
+    return OGRTriangulatedSurface::CastToMultiPolygonImpl;
+}
+
+/************************************************************************/
+/*                         CastToMultiPolygon()                         */
+/************************************************************************/
+
+OGRMultiPolygon* OGRTriangulatedSurface::CastToMultiPolygonImpl(
+                                                    OGRPolyhedralSurface* poTS)
+{
+    OGRMultiPolygon *poMultiPolygon = new OGRMultiPolygon();
+    poMultiPolygon->assignSpatialReference(poTS->getSpatialReference());
+
+    for (int i = 0; i < poTS->oMP.nGeomCount; i++)
+    {
+        OGRTriangle *geom =
+            reinterpret_cast<OGRTriangle *>(poTS->oMP.papoGeoms[i]);
+        poTS->oMP.papoGeoms[i] = NULL;
+        OGRPolygon *poPolygon = OGRSurface::CastToPolygon(geom);
+        poMultiPolygon->addGeometryDirectly(poPolygon);
+    }
+    delete poTS;
+
+    return poMultiPolygon;
+}
+//! @endcond
+
+/************************************************************************/
+/*                     CastToPolyhedralSurface()                        */
+/************************************************************************/
+
+/**
+ * \brief Casts the OGRTriangulatedSurface to an OGRPolyhedralSurface
+ *
+ * The passed in geometry is consumed and a new one returned (or NULL in case
+ * of failure)
+ *
+ * @param poTS the input geometry - ownership is passed to the method.
+ * @return new geometry.
+ */
+
+
+OGRPolyhedralSurface* OGRTriangulatedSurface::CastToPolyhedralSurface(
+                                                OGRTriangulatedSurface* poTS)
+{
+    OGRPolyhedralSurface* poPS = new OGRPolyhedralSurface();
+    poPS->assignSpatialReference(poTS->getSpatialReference());
+    for (int i = 0; i < poTS->oMP.nGeomCount; i++)
+    {
+        OGRTriangle *geom =
+            reinterpret_cast<OGRTriangle *>(poTS->oMP.papoGeoms[i]);
+        poTS->oMP.papoGeoms[i] = NULL;
+        OGRPolygon *poPolygon = OGRSurface::CastToPolygon(geom);
+        poPS->oMP.addGeometryDirectly(poPolygon);
+    }
+    delete poTS;
+    return poPS;
+}
diff --git a/ogr/ogrutils.cpp b/ogr/ogrutils.cpp
index 32e6ad5..ac442ea 100644
--- a/ogr/ogrutils.cpp
+++ b/ogr/ogrutils.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: ogrutils.cpp 33956 2016-04-12 18:55:40Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Utility functions for OGR classes, including some related to
@@ -29,30 +28,46 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_conv.h"
-#include "cpl_vsi.h"
+#include "cpl_port.h"
+#include "ogr_p.h"
 
-#include <ctype.h>
+#include <cmath>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cctype>
+#include <limits>
 
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+#include "gdal.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
-#include "ogr_p.h"
+#include "ogrsf_frmts.h"
 
-# include "ogrsf_frmts.h"
+CPL_CVSID("$Id: ogrutils.cpp 37564 2017-03-03 09:09:26Z rouault $");
 
-CPL_CVSID("$Id: ogrutils.cpp 33956 2016-04-12 18:55:40Z rouault $");
+// Returns whether a double fits within an int.
+// Unable to put this in cpl_port.h as include limit breaks grib.
+inline bool CPLIsDoubleAnInt(double d)
+{
+    if (d > std::numeric_limits<int>::max()) return false;
+    if (d < std::numeric_limits<int>::min()) return false;
+    return d == static_cast<double>(static_cast<int>(d));
+}
 
 /************************************************************************/
 /*                        OGRFormatDouble()                             */
 /************************************************************************/
 
 void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
-                      char chDecimalSep, int nPrecision, char chConversionSpecifier )
+                      char chDecimalSep, int nPrecision,
+                      char chConversionSpecifier )
 {
-    int i;
-    int nTruncations = 0;
-    char szFormat[16];
-
-    // So to have identical cross platform representation
+    // So to have identical cross platform representation.
     if( CPLIsInf(dfVal) )
     {
         if( dfVal > 0 )
@@ -67,11 +82,14 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
         return;
     }
 
-    snprintf(szFormat, sizeof(szFormat), "%%.%d%c", nPrecision, chConversionSpecifier);
+    char szFormat[16] = {};
+    snprintf(szFormat, sizeof(szFormat),
+             "%%.%d%c", nPrecision, chConversionSpecifier);
 
     int ret = CPLsnprintf(pszBuffer, nBufferLen, szFormat, dfVal);
-    /* Windows CRT doesn't conform with C99 and return -1 when buffer is truncated */
-    if (ret >= nBufferLen || ret == -1)
+    // Windows CRT does not conform with C99 and returns -1 when buffer is
+    // truncated.
+    if( ret >= nBufferLen || ret == -1 )
     {
         CPLsnprintf(pszBuffer, nBufferLen, "%s", "too_big");
         return;
@@ -80,21 +98,22 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
     if( chConversionSpecifier == 'g' && strchr(pszBuffer, 'e') )
         return;
 
-    while(nPrecision > 0)
+    int nTruncations = 0;
+    while( nPrecision > 0 )
     {
-        i = 0;
+        int i = 0;
         int nCountBeforeDot = 0;
         int iDotPos = -1;
         while( pszBuffer[i] != '\0' )
         {
-            if (pszBuffer[i] == '.' && chDecimalSep != '\0')
+            if( pszBuffer[i] == '.' && chDecimalSep != '\0' )
             {
                 iDotPos = i;
                 pszBuffer[i] = chDecimalSep;
             }
-            else if (iDotPos < 0 && pszBuffer[i] != '-')
-                nCountBeforeDot ++;
-            i++;
+            else if( iDotPos < 0 && pszBuffer[i] != '-' )
+                ++nCountBeforeDot;
+            ++i;
         }
         if( iDotPos < 0 )
             break;
@@ -104,7 +123,7 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
     /* -------------------------------------------------------------------- */
         if( i > 10 )
         {
-            if (/* && pszBuffer[i-1] == '1' &&*/
+            if(  // && pszBuffer[i-1] == '1' &&
                 pszBuffer[i-2] == '0'
                 && pszBuffer[i-3] == '0'
                 && pszBuffer[i-4] == '0'
@@ -113,15 +132,15 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
             {
                 pszBuffer[--i] = '\0';
             }
-            else if( i - 8 > iDotPos && /* pszBuffer[i-1] == '1' */
-                  /* && pszBuffer[i-2] == '0' && */
-                    (nCountBeforeDot >= 4 || pszBuffer[i-3] == '0')
-                    && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '0')
-                    && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '0')
-                    && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '0')
-                    && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '0')
-                    && pszBuffer[i-8] == '0'
-                    && pszBuffer[i-9] == '0')
+            else if( i - 8 > iDotPos &&  // pszBuffer[i-1] == '1'
+                     // && pszBuffer[i-2] == '0' &&
+                     (nCountBeforeDot >= 4 || pszBuffer[i-3] == '0')
+                     && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '0')
+                     && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '0')
+                     && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '0')
+                     && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '0')
+                     && pszBuffer[i-8] == '0'
+                     && pszBuffer[i-9] == '0')
             {
                 i -= 8;
                 pszBuffer[i] = '\0';
@@ -142,34 +161,37 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
         if( i > 10 &&
             nPrecision + nTruncations >= 15)
         {
-            if (/*pszBuffer[i-1] == '9' && */
-                 pszBuffer[i-2] == '9'
+            if(  //pszBuffer[i-1] == '9' &&
+                pszBuffer[i-2] == '9'
                 && pszBuffer[i-3] == '9'
                 && pszBuffer[i-4] == '9'
                 && pszBuffer[i-5] == '9'
                 && pszBuffer[i-6] == '9' )
             {
-                nPrecision --;
-                nTruncations ++;
-                snprintf(szFormat, sizeof(szFormat), "%%.%d%c", nPrecision, chConversionSpecifier);
+                --nPrecision;
+                ++nTruncations;
+                snprintf(szFormat, sizeof(szFormat),
+                         "%%.%d%c", nPrecision, chConversionSpecifier);
                 CPLsnprintf(pszBuffer, nBufferLen, szFormat, dfVal);
                 if( chConversionSpecifier == 'g' && strchr(pszBuffer, 'e') )
                     return;
                 continue;
             }
-            else if (i - 9 > iDotPos && /*pszBuffer[i-1] == '9' && */
-                     /*pszBuffer[i-2] == '9' && */
+            else if( i - 9 > iDotPos &&
+                     // pszBuffer[i-1] == '9' &&
+                     //pszBuffer[i-2] == '9' &&
                     (nCountBeforeDot >= 4 || pszBuffer[i-3] == '9')
-                    && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '9')
-                    && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '9')
-                    && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '9')
-                    && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '9')
-                    && pszBuffer[i-8] == '9'
-                    && pszBuffer[i-9] == '9')
+                     && (nCountBeforeDot >= 5 || pszBuffer[i-4] == '9')
+                     && (nCountBeforeDot >= 6 || pszBuffer[i-5] == '9')
+                     && (nCountBeforeDot >= 7 || pszBuffer[i-6] == '9')
+                     && (nCountBeforeDot >= 8 || pszBuffer[i-7] == '9')
+                     && pszBuffer[i-8] == '9'
+                     && pszBuffer[i-9] == '9')
             {
-                nPrecision --;
-                nTruncations ++;
-                snprintf(szFormat, sizeof(szFormat), "%%.%d%c", nPrecision, chConversionSpecifier);
+                --nPrecision;
+                ++nTruncations;
+                snprintf(szFormat, sizeof(szFormat),
+                         "%%.%d%c", nPrecision, chConversionSpecifier);
                 CPLsnprintf(pszBuffer, nBufferLen, szFormat, dfVal);
                 if( chConversionSpecifier == 'g' && strchr(pszBuffer, 'e') )
                     return;
@@ -179,7 +201,6 @@ void OGRFormatDouble( char *pszBuffer, int nBufferLen, double dfVal,
 
         break;
     }
-
 }
 
 /************************************************************************/
@@ -198,32 +219,38 @@ void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
 
 {
     const size_t bufSize = 75;
-    const size_t maxTargetSize = 75; /* Assumed max length of the target buffer. */
+    // Assumed max length of the target buffer.
+    const size_t maxTargetSize = 75;
     const char chDecimalSep = '.';
-    const int nPrecision = 15;
+    static int nPrecision = -1;
+    if( nPrecision < 0 )
+        nPrecision = atoi(CPLGetConfigOption("OGR_WKT_PRECISION", "15"));
 
-    char szX[bufSize];
-    char szY[bufSize];
-    char szZ[bufSize];
+    char szX[bufSize] = {};
+    char szY[bufSize] = {};
+    char szZ[bufSize] = {};
 
     szZ[0] = '\0';
 
-    size_t nLenX, nLenY;
+    size_t nLenX = 0;
+    size_t nLenY = 0;
 
-    if( CPL_IS_DOUBLE_A_INT(x) && CPL_IS_DOUBLE_A_INT(y) )
+    if( CPLIsDoubleAnInt(x) && CPLIsDoubleAnInt(y) )
     {
-        snprintf( szX, bufSize, "%d", (int) x );
-        snprintf( szY, bufSize, "%d", (int) y );
+        snprintf( szX, bufSize, "%d", static_cast<int>(x) );
+        snprintf( szY, bufSize, "%d", static_cast<int>(y) );
     }
     else
     {
-        OGRFormatDouble( szX, bufSize, x, chDecimalSep, nPrecision, fabs(x) < 1 ? 'f' : 'g' );
+        OGRFormatDouble( szX, bufSize, x, chDecimalSep, nPrecision,
+                         fabs(x) < 1 ? 'f' : 'g' );
         if( CPLIsFinite(x) && strchr(szX, '.') == NULL &&
             strchr(szX, 'e') == NULL && strlen(szX) < bufSize - 2 )
         {
             strcat(szX, ".0");
         }
-        OGRFormatDouble( szY, bufSize, y, chDecimalSep, nPrecision, fabs(y) < 1 ? 'f' : 'g' );
+        OGRFormatDouble( szY, bufSize, y, chDecimalSep, nPrecision,
+                         fabs(y) < 1 ? 'f' : 'g' );
         if( CPLIsFinite(y) && strchr(szY, '.') == NULL &&
             strchr(szY, 'e') == NULL && strlen(szY) < bufSize - 2 )
         {
@@ -236,9 +263,9 @@ void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
 
     if( nDimension == 3 )
     {
-        if( CPL_IS_DOUBLE_A_INT(z) )
+        if( CPLIsDoubleAnInt(z) )
         {
-            snprintf( szZ, bufSize, "%d", (int) z );
+            snprintf( szZ, bufSize, "%d", static_cast<int>(z) );
         }
         else
         {
@@ -246,11 +273,12 @@ void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
         }
     }
 
-    if( nLenX + 1 + nLenY + ((nDimension == 3) ? (1 + strlen(szZ)) : 0) >= maxTargetSize )
+    if( nLenX + 1 + nLenY + ((nDimension == 3) ? (1 + strlen(szZ)) : 0) >=
+        maxTargetSize )
     {
 #ifdef DEBUG
         CPLDebug( "OGR",
-                  "Yow!  Got this big result in OGRMakeWktCoordinate()\n"
+                  "Yow!  Got this big result in OGRMakeWktCoordinate(): "
                   "%s %s %s",
                   szX, szY, szZ );
 #endif
@@ -264,7 +292,7 @@ void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
         memcpy( pszTarget, szX, nLenX );
         pszTarget[nLenX] = ' ';
         memcpy( pszTarget + nLenX + 1, szY, nLenY );
-        if (nDimension == 3)
+        if( nDimension == 3 )
         {
             pszTarget[nLenX + 1 + nLenY] = ' ';
             strcpy( pszTarget + nLenX + 1 + nLenY + 1, szZ );
@@ -287,39 +315,44 @@ void OGRMakeWktCoordinate( char *pszTarget, double x, double y, double z,
 /*      characters barring the X or Y value being extremely large.      */
 /************************************************************************/
 
-void OGRMakeWktCoordinateM( char *pszTarget, double x, double y, double z, double m,
+void OGRMakeWktCoordinateM( char *pszTarget,
+                            double x, double y, double z, double m,
                             OGRBoolean hasZ, OGRBoolean hasM )
 
 {
     const size_t bufSize = 75;
-    const size_t maxTargetSize = 75; /* Assumed max length of the target buffer. */
+    // Assumed max length of the target buffer.
+    const size_t maxTargetSize = 75;
     const char chDecimalSep = '.';
-    const int nPrecision = 15;
-
-    char szX[bufSize];
-    char szY[bufSize];
-    char szZ[bufSize];
-    char szM[bufSize];
+    static int nPrecision = -1;
+    if( nPrecision < 0 )
+        nPrecision = atoi(CPLGetConfigOption("OGR_WKT_PRECISION", "15"));
 
-    szZ[0] = '\0';
-    szM[0] = '\0';
+    char szX[bufSize] = {};
+    char szY[bufSize] = {};
+    char szZ[bufSize] = {};
+    char szM[bufSize] = {};
 
-    size_t nLen, nLenX, nLenY;
+    size_t nLen = 0;
+    size_t nLenX = 0;
+    size_t nLenY = 0;
 
-    if( CPL_IS_DOUBLE_A_INT(x) && CPL_IS_DOUBLE_A_INT(y) )
+    if( CPLIsDoubleAnInt(x) && CPLIsDoubleAnInt(y) )
     {
-        snprintf( szX, bufSize, "%d", (int) x );
-        snprintf( szY, bufSize, "%d", (int) y );
+        snprintf( szX, bufSize, "%d", static_cast<int>(x) );
+        snprintf( szY, bufSize, "%d", static_cast<int>(y) );
     }
     else
     {
-        OGRFormatDouble( szX, bufSize, x, chDecimalSep, nPrecision, fabs(x) < 1 ? 'f' : 'g' );
+        OGRFormatDouble( szX, bufSize, x, chDecimalSep, nPrecision,
+                         fabs(x) < 1 ? 'f' : 'g' );
         if( CPLIsFinite(x) && strchr(szX, '.') == NULL &&
             strchr(szX, 'e') == NULL && strlen(szX) < bufSize - 2 )
         {
             strcat(szX, ".0");
         }
-        OGRFormatDouble( szY, bufSize, y, chDecimalSep, nPrecision, fabs(y) < 1 ? 'f' : 'g' );
+        OGRFormatDouble( szY, bufSize, y, chDecimalSep, nPrecision,
+                         fabs(y) < 1 ? 'f' : 'g' );
         if( CPLIsFinite(y) && strchr(szY, '.') == NULL &&
             strchr(szY, 'e') == NULL && strlen(szY) < bufSize - 2 )
         {
@@ -333,9 +366,9 @@ void OGRMakeWktCoordinateM( char *pszTarget, double x, double y, double z, doubl
 
     if( hasZ )
     {
-        if( CPL_IS_DOUBLE_A_INT(z) )
+        if( CPLIsDoubleAnInt(z) )
         {
-            snprintf( szZ, bufSize, "%d", (int) z );
+            snprintf( szZ, bufSize, "%d", static_cast<int>(z) );
         }
         else
         {
@@ -346,9 +379,9 @@ void OGRMakeWktCoordinateM( char *pszTarget, double x, double y, double z, doubl
 
     if( hasM )
     {
-        if( CPL_IS_DOUBLE_A_INT(m) )
+        if( CPLIsDoubleAnInt(m) )
         {
-            snprintf( szM, bufSize, "%d", (int) m );
+            snprintf( szM, bufSize, "%d", static_cast<int>(m) );
         }
         else
         {
@@ -361,7 +394,7 @@ void OGRMakeWktCoordinateM( char *pszTarget, double x, double y, double z, doubl
     {
 #ifdef DEBUG
         CPLDebug( "OGR",
-                  "Yow!  Got this big result in OGRMakeWktCoordinate()\n"
+                  "Yow!  Got this big result in OGRMakeWktCoordinate(): "
                   "%s %s %s %s",
                   szX, szY, szZ, szM );
 #endif
@@ -378,20 +411,20 @@ void OGRMakeWktCoordinateM( char *pszTarget, double x, double y, double z, doubl
         strcpy( target, szX );
         target += nLenX;
         *target = ' ';
-        target++;
+        ++target;
         strcpy( target, szY );
         target += nLenY;
         if( hasZ )
         {
             *target = ' ';
-            target++;
+            ++target;
             strcpy( target, szZ );
             target += strlen(szZ);
         }
         if( hasM )
         {
             *target = ' ';
-            target++;
+            ++target;
             strcpy( target, szM );
             target += strlen(szM);
         }
@@ -416,7 +449,7 @@ const char *OGRWktReadToken( const char * pszInput, char * pszToken )
 /*      Swallow pre-white space.                                        */
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' || *pszInput == '\t' )
-        pszInput++;
+        ++pszInput;
 
 /* -------------------------------------------------------------------- */
 /*      If this is a delimiter, read just one character.                */
@@ -426,7 +459,7 @@ const char *OGRWktReadToken( const char * pszInput, char * pszToken )
         pszToken[0] = *pszInput;
         pszToken[1] = '\0';
 
-        pszInput++;
+        ++pszInput;
     }
 
 /* -------------------------------------------------------------------- */
@@ -435,7 +468,7 @@ const char *OGRWktReadToken( const char * pszInput, char * pszToken )
 /* -------------------------------------------------------------------- */
     else
     {
-        int             iChar = 0;
+        int iChar = 0;
 
         while( iChar < OGR_WKT_TOKEN_MAX-1
                && ((*pszInput >= 'a' && *pszInput <= 'z')
@@ -455,9 +488,9 @@ const char *OGRWktReadToken( const char * pszInput, char * pszToken )
 /*      Eat any trailing white space.                                   */
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' || *pszInput == '\t' )
-        pszInput++;
+        ++pszInput;
 
-    return( pszInput );
+    return pszInput;
 }
 
 /************************************************************************/
@@ -483,41 +516,42 @@ const char * OGRWktReadPoints( const char * pszInput,
 /*      Eat any leading white space.                                    */
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' || *pszInput == '\t' )
-        pszInput++;
+        ++pszInput;
 
 /* -------------------------------------------------------------------- */
-/*      If this isn't an opening bracket then we have a problem!        */
+/*      If this isn't an opening bracket then we have a problem.        */
 /* -------------------------------------------------------------------- */
     if( *pszInput != '(' )
     {
         CPLDebug( "OGR",
-                  "Expected '(', but got %s in OGRWktReadPoints().\n",
+                  "Expected '(', but got %s in OGRWktReadPoints().",
                   pszInput );
 
         return pszInput;
     }
 
-    pszInput++;
+    ++pszInput;
 
 /* ==================================================================== */
 /*      This loop reads a single point.  It will continue till we       */
 /*      run out of well formed points, or a closing bracket is          */
 /*      encountered.                                                    */
 /* ==================================================================== */
-    char        szDelim[OGR_WKT_TOKEN_MAX];
+    char szDelim[OGR_WKT_TOKEN_MAX] = {};
 
     do {
 /* -------------------------------------------------------------------- */
 /*      Read the X and Y values, verify they are numeric.               */
 /* -------------------------------------------------------------------- */
-        char    szTokenX[OGR_WKT_TOKEN_MAX];
-        char    szTokenY[OGR_WKT_TOKEN_MAX];
+        char szTokenX[OGR_WKT_TOKEN_MAX] = {};
+        char szTokenY[OGR_WKT_TOKEN_MAX] = {};
 
         pszInput = OGRWktReadToken( pszInput, szTokenX );
         pszInput = OGRWktReadToken( pszInput, szTokenY );
 
         if( (!isdigit(szTokenX[0]) && szTokenX[0] != '-' && szTokenX[0] != '.' )
-            || (!isdigit(szTokenY[0]) && szTokenY[0] != '-' && szTokenY[0] != '.') )
+            || (!isdigit(szTokenY[0]) && szTokenY[0] != '-' &&
+                szTokenY[0] != '.') )
             return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -526,13 +560,13 @@ const char * OGRWktReadPoints( const char * pszInput,
         if( *pnPointsRead == *pnMaxPoints )
         {
             *pnMaxPoints = *pnMaxPoints * 2 + 10;
-            *ppaoPoints = (OGRRawPoint *)
-                CPLRealloc(*ppaoPoints, sizeof(OGRRawPoint) * *pnMaxPoints);
+            *ppaoPoints = static_cast<OGRRawPoint *>(
+                CPLRealloc(*ppaoPoints, sizeof(OGRRawPoint) * *pnMaxPoints) );
 
             if( *ppadfZ != NULL )
             {
-                *ppadfZ = (double *)
-                    CPLRealloc(*ppadfZ, sizeof(double) * *pnMaxPoints);
+                *ppadfZ = static_cast<double *>(
+                    CPLRealloc(*ppadfZ, sizeof(double) * *pnMaxPoints) );
             }
         }
 
@@ -551,17 +585,20 @@ const char * OGRWktReadPoints( const char * pszInput,
         {
             if( *ppadfZ == NULL )
             {
-                *ppadfZ = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
+                *ppadfZ = static_cast<double *>(
+                    CPLCalloc(sizeof(double), *pnMaxPoints) );
             }
 
             (*ppadfZ)[*pnPointsRead] = CPLAtof(szDelim);
 
             pszInput = OGRWktReadToken( pszInput, szDelim );
         }
-        else if ( *ppadfZ != NULL )
+        else if( *ppadfZ != NULL )
+        {
             (*ppadfZ)[*pnPointsRead] = 0.0;
+        }
 
-        (*pnPointsRead)++;
+        ++(*pnPointsRead);
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a M coordinate?                                      */
@@ -579,12 +616,11 @@ const char * OGRWktReadPoints( const char * pszInput,
         if( szDelim[0] != ')' && szDelim[0] != ',' )
         {
             CPLDebug( "OGR",
-                      "Corrupt input in OGRWktReadPoints()\n"
-                      "Got `%s' when expecting `,' or `)', near `%s' in %s.\n",
+                      "Corrupt input in OGRWktReadPoints().  "
+                      "Got `%s' when expecting `,' or `)', near `%s' in %s.",
                       szDelim, pszInput, pszOrigInput );
             return NULL;
         }
-
     } while( szDelim[0] == ',' );
 
     return pszInput;
@@ -598,14 +634,17 @@ const char * OGRWktReadPoints( const char * pszInput,
 /************************************************************************/
 
 const char * OGRWktReadPointsM( const char * pszInput,
-                                OGRRawPoint ** ppaoPoints, double **ppadfZ, double **ppadfM,
+                                OGRRawPoint ** ppaoPoints,
+                                double **ppadfZ, double **ppadfM,
                                 int * flags,
                                 int * pnMaxPoints,
                                 int * pnPointsRead )
 
 {
     const char *pszOrigInput = pszInput;
-    int no_flags = !(*flags & OGRGeometry::OGR_G_3D) && !(*flags & OGRGeometry::OGR_G_MEASURED);
+    const bool bNoFlags =
+        !(*flags & OGRGeometry::OGR_G_3D) &&
+        !(*flags & OGRGeometry::OGR_G_MEASURED);
     *pnPointsRead = 0;
 
     if( pszInput == NULL )
@@ -615,41 +654,42 @@ const char * OGRWktReadPointsM( const char * pszInput,
 /*      Eat any leading white space.                                    */
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' || *pszInput == '\t' )
-        pszInput++;
+        ++pszInput;
 
 /* -------------------------------------------------------------------- */
-/*      If this isn't an opening bracket then we have a problem!        */
+/*      If this isn't an opening bracket then we have a problem.        */
 /* -------------------------------------------------------------------- */
     if( *pszInput != '(' )
     {
         CPLDebug( "OGR",
-                  "Expected '(', but got %s in OGRWktReadPointsM().\n",
+                  "Expected '(', but got %s in OGRWktReadPointsM().",
                   pszInput );
 
         return pszInput;
     }
 
-    pszInput++;
+    ++pszInput;
 
 /* ==================================================================== */
 /*      This loop reads a single point.  It will continue till we       */
 /*      run out of well formed points, or a closing bracket is          */
 /*      encountered.                                                    */
 /* ==================================================================== */
-    char        szDelim[OGR_WKT_TOKEN_MAX];
+    char szDelim[OGR_WKT_TOKEN_MAX] = {};
 
     do {
 /* -------------------------------------------------------------------- */
 /*      Read the X and Y values, verify they are numeric.               */
 /* -------------------------------------------------------------------- */
-        char    szTokenX[OGR_WKT_TOKEN_MAX];
-        char    szTokenY[OGR_WKT_TOKEN_MAX];
+        char szTokenX[OGR_WKT_TOKEN_MAX] = {};
+        char szTokenY[OGR_WKT_TOKEN_MAX] = {};
 
         pszInput = OGRWktReadToken( pszInput, szTokenX );
         pszInput = OGRWktReadToken( pszInput, szTokenY );
 
         if( (!isdigit(szTokenX[0]) && szTokenX[0] != '-' && szTokenX[0] != '.' )
-            || (!isdigit(szTokenY[0]) && szTokenY[0] != '-' && szTokenY[0] != '.') )
+            || (!isdigit(szTokenY[0]) && szTokenY[0] != '-' &&
+                szTokenY[0] != '.') )
             return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -658,19 +698,19 @@ const char * OGRWktReadPointsM( const char * pszInput,
         if( *pnPointsRead == *pnMaxPoints )
         {
             *pnMaxPoints = *pnMaxPoints * 2 + 10;
-            *ppaoPoints = (OGRRawPoint *)
-                CPLRealloc(*ppaoPoints, sizeof(OGRRawPoint) * *pnMaxPoints);
+            *ppaoPoints = static_cast<OGRRawPoint *>(
+                CPLRealloc(*ppaoPoints, sizeof(OGRRawPoint) * *pnMaxPoints) );
 
             if( *ppadfZ != NULL )
             {
-                *ppadfZ = (double *)
-                    CPLRealloc(*ppadfZ, sizeof(double) * *pnMaxPoints);
+                *ppadfZ = static_cast<double *>(
+                    CPLRealloc(*ppadfZ, sizeof(double) * *pnMaxPoints) );
             }
 
             if( *ppadfM != NULL )
             {
-                *ppadfM = (double *)
-                    CPLRealloc(*ppadfM, sizeof(double) * *pnMaxPoints);
+                *ppadfM = static_cast<double *>(
+                    CPLRealloc(*ppadfM, sizeof(double) * *pnMaxPoints) );
             }
         }
 
@@ -689,7 +729,8 @@ const char * OGRWktReadPointsM( const char * pszInput,
 /*      If there are unexpectedly more coordinates, they are Z.         */
 /* -------------------------------------------------------------------- */
 
-        if( !(*flags & OGRGeometry::OGR_G_3D) && !(*flags & OGRGeometry::OGR_G_MEASURED) &&
+        if( !(*flags & OGRGeometry::OGR_G_3D) &&
+            !(*flags & OGRGeometry::OGR_G_MEASURED) &&
             (isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' ))
         {
             *flags |= OGRGeometry::OGR_G_3D;
@@ -704,19 +745,23 @@ const char * OGRWktReadPointsM( const char * pszInput,
         {
             if( *ppadfZ == NULL )
             {
-                *ppadfZ = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
+                *ppadfZ = static_cast<double *>(
+                    CPLCalloc(sizeof(double), *pnMaxPoints) );
             }
             if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
             {
                 (*ppadfZ)[*pnPointsRead] = CPLAtof(szDelim);
                 pszInput = OGRWktReadToken( pszInput, szDelim );
             }
-            else {
+            else
+            {
                 (*ppadfZ)[*pnPointsRead] = 0.0;
             }
         }
-        else if ( *ppadfZ != NULL )
+        else if( *ppadfZ != NULL )
+        {
             (*ppadfZ)[*pnPointsRead] = 0.0;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      If there are unexpectedly even more coordinates,                */
@@ -727,7 +772,7 @@ const char * OGRWktReadPointsM( const char * pszInput,
         if( !(*flags & OGRGeometry::OGR_G_MEASURED) &&
             (isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' ) )
         {
-            if( no_flags )
+            if( bNoFlags )
             {
                 *flags |= OGRGeometry::OGR_G_MEASURED;
             }
@@ -746,19 +791,23 @@ const char * OGRWktReadPointsM( const char * pszInput,
         {
             if( *ppadfM == NULL )
             {
-                *ppadfM = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
+                *ppadfM = static_cast<double *>(
+                    CPLCalloc(sizeof(double), *pnMaxPoints) );
             }
             if( isdigit(szDelim[0]) || szDelim[0] == '-' || szDelim[0] == '.' )
             {
                 (*ppadfM)[*pnPointsRead] = CPLAtof(szDelim);
                 pszInput = OGRWktReadToken( pszInput, szDelim );
             }
-            else {
+            else
+            {
                 (*ppadfM)[*pnPointsRead] = 0.0;
             }
         }
-        else if ( *ppadfM != NULL )
+        else if( *ppadfM != NULL )
+        {
             (*ppadfM)[*pnPointsRead] = 0.0;
+        }
 
 /* -------------------------------------------------------------------- */
 /*      If there are still more coordinates and we do not have Z        */
@@ -772,7 +821,8 @@ const char * OGRWktReadPointsM( const char * pszInput,
             *flags |= OGRGeometry::OGR_G_3D;
             if( *ppadfZ == NULL )
             {
-                *ppadfZ = (double *) CPLCalloc(sizeof(double),*pnMaxPoints);
+                *ppadfZ = static_cast<double *>(
+                    CPLCalloc(sizeof(double), *pnMaxPoints) );
             }
             (*ppadfZ)[*pnPointsRead] = (*ppadfM)[*pnPointsRead];
             (*ppadfM)[*pnPointsRead] = CPLAtof(szDelim);
@@ -782,7 +832,7 @@ const char * OGRWktReadPointsM( const char * pszInput,
 /* -------------------------------------------------------------------- */
 /*      Increase points index.                                          */
 /* -------------------------------------------------------------------- */
-        (*pnPointsRead)++;
+        ++(*pnPointsRead);
 
 /* -------------------------------------------------------------------- */
 /*      The next delimiter should be a comma or an ending bracket.      */
@@ -790,12 +840,11 @@ const char * OGRWktReadPointsM( const char * pszInput,
         if( szDelim[0] != ')' && szDelim[0] != ',' )
         {
             CPLDebug( "OGR",
-                      "Corrupt input in OGRWktReadPointsM()\n"
-                      "Got `%s' when expecting `,' or `)', near `%s' in %s.\n",
+                      "Corrupt input in OGRWktReadPointsM()  "
+                      "Got `%s' when expecting `,' or `)', near `%s' in %s.",
                       szDelim, pszInput, pszOrigInput );
             return NULL;
         }
-
     } while( szDelim[0] == ',' );
 
     return pszInput;
@@ -819,7 +868,7 @@ void *OGRMalloc( size_t size )
 /*      Cover for CPLCalloc()                                           */
 /************************************************************************/
 
-void * OGRCalloc( size_t count, size_t size )
+void *OGRCalloc( size_t count, size_t size )
 
 {
     return CPLCalloc( count, size );
@@ -850,6 +899,7 @@ void OGRFree( void * pMemory )
 }
 
 /**
+ * \fn OGRGeneralCmdLineProcessor(int, char***, int)
  * General utility option processing.
  *
  * This function is intended to provide a variety of generic commandline
@@ -881,17 +931,18 @@ void OGRFree( void * pMemory )
  *        exit( -argc );
  *
  * @param nArgc number of values in the argument list.
- * @param ppapszArgv pointer to the argument list array (will be updated in place).
+ * @param ppapszArgv pointer to the argument list array (will be updated in
+ * place).
  * @param nOptions unused.
  *
  * @return updated nArgc argument count.  Return of 0 requests terminate
  * without error, return of -1 requests exit with error code.
  */
 
-int OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv, int nOptions )
+int OGRGeneralCmdLineProcessor( int nArgc, char ***ppapszArgv,
+                                CPL_UNUSED int nOptions )
 
 {
-    (void) nOptions;
     return GDALGeneralCmdLineProcessor( nArgc, ppapszArgv, GDAL_OF_VECTOR );
 }
 
@@ -934,8 +985,6 @@ int OGRParseDate( const char *pszInput,
                   OGRField *psField,
                   CPL_UNUSED int nOptions )
 {
-    bool bGotSomething = false;
-
     psField->Date.Year = 0;
     psField->Date.Month = 0;
     psField->Date.Day = 0;
@@ -949,22 +998,25 @@ int OGRParseDate( const char *pszInput,
 /*      Do we have a date?                                              */
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' )
-        pszInput++;
+        ++pszInput;
 
+    bool bGotSomething = false;
     if( strstr(pszInput,"-") != NULL || strstr(pszInput,"/") != NULL )
     {
-        if( !(*pszInput == '-' || *pszInput == '+' || (*pszInput >= '0' && *pszInput <= '9')) )
+        if( !(*pszInput == '-' || *pszInput == '+' ||
+              (*pszInput >= '0' && *pszInput <= '9')) )
             return FALSE;
         int nYear = atoi(pszInput);
-        if( nYear != (GInt16)nYear )
+        if( nYear != static_cast<GInt16>(nYear) )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Years < -32768 or > 32767 are not supported");
             return FALSE;
         }
-        psField->Date.Year = (GInt16)nYear;
+        psField->Date.Year = static_cast<GInt16>(nYear);
         if( (pszInput[1] == '-' || pszInput[1] == '/' ) ||
-            (pszInput[1] != '\0' && (pszInput[2] == '-' || pszInput[2] == '/' )) )
+            (pszInput[1] != '\0' &&
+             (pszInput[2] == '-' || pszInput[2] == '/' )) )
         {
             if( psField->Date.Year < 100 && psField->Date.Year >= 30 )
                 psField->Date.Year += 1900;
@@ -973,79 +1025,79 @@ int OGRParseDate( const char *pszInput,
         }
 
         if( *pszInput == '-' )
-            pszInput ++;
+            ++pszInput;
         while( *pszInput >= '0' && *pszInput <= '9' )
-            pszInput++;
+            ++pszInput;
         if( *pszInput != '-' && *pszInput != '/' )
             return FALSE;
         else
-            pszInput++;
+            ++pszInput;
 
-        psField->Date.Month = (GByte)atoi(pszInput);
-        if( psField->Date.Month <= 0 || psField->Date.Month > 12 )
+        psField->Date.Month = static_cast<GByte>(atoi(pszInput));
+        if( psField->Date.Month == 0 || psField->Date.Month > 12 )
             return FALSE;
 
         while( *pszInput >= '0' && *pszInput <= '9' )
-            pszInput++;
+            ++pszInput;
         if( *pszInput != '-' && *pszInput != '/' )
             return FALSE;
         else
-            pszInput++;
+            ++pszInput;
 
-        psField->Date.Day = (GByte)atoi(pszInput);
-        if( psField->Date.Day <= 0 || psField->Date.Day > 31 )
+        psField->Date.Day = static_cast<GByte>(atoi(pszInput));
+        if( psField->Date.Day == 0 || psField->Date.Day > 31 )
             return FALSE;
 
         while( *pszInput >= '0' && *pszInput <= '9' )
-            pszInput++;
+            ++pszInput;
 
         bGotSomething = true;
 
-        /* If ISO 8601 format */
+        // If ISO 8601 format.
         if( *pszInput == 'T' )
-            pszInput ++;
+            ++pszInput;
     }
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a time?                                              */
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' )
-        pszInput++;
+        ++pszInput;
 
-    if( strstr(pszInput,":") != NULL )
+    if( strstr(pszInput, ":") != NULL )
     {
-        psField->Date.Hour = (GByte)atoi(pszInput);
+        psField->Date.Hour = static_cast<GByte>(atoi(pszInput));
         if( psField->Date.Hour > 23 )
             return FALSE;
 
         while( *pszInput >= '0' && *pszInput <= '9' )
-            pszInput++;
+            ++pszInput;
         if( *pszInput != ':' )
             return FALSE;
         else
-            pszInput++;
+            ++pszInput;
 
-        psField->Date.Minute = (GByte)atoi(pszInput);
+        psField->Date.Minute = static_cast<GByte>(atoi(pszInput));
         if( psField->Date.Minute > 59 )
             return FALSE;
 
         while( *pszInput >= '0' && *pszInput <= '9' )
-            pszInput++;
+            ++pszInput;
         if( *pszInput == ':' )
         {
-            pszInput++;
+            ++pszInput;
 
-            psField->Date.Second = (float)CPLAtof(pszInput);
+            psField->Date.Second = static_cast<float>(CPLAtof(pszInput));
             if( psField->Date.Second > 61 )
                 return FALSE;
 
             while( (*pszInput >= '0' && *pszInput <= '9')
                 || *pszInput == '.' )
             {
-                pszInput++;
+                ++pszInput;
             }
 
-            /* If ISO 8601 format */
+            // If ISO 8601 format.
             if( *pszInput == 'Z' )
             {
                 psField->Date.TZFlag = 100;
@@ -1063,40 +1115,41 @@ int OGRParseDate( const char *pszInput,
 /*      Do we have a timezone?                                          */
 /* -------------------------------------------------------------------- */
     while( *pszInput == ' ' )
-        pszInput++;
+        ++pszInput;
 
     if( *pszInput == '-' || *pszInput == '+' )
     {
         // +HH integral offset
         if( strlen(pszInput) <= 3 )
-            psField->Date.TZFlag = (GByte)(100 + atoi(pszInput) * 4);
-
+        {
+            psField->Date.TZFlag = static_cast<GByte>(100 + atoi(pszInput) * 4);
+        }
         else if( pszInput[3] == ':'  // +HH:MM offset
-                 && atoi(pszInput+4) % 15 == 0 )
+                 && atoi(pszInput + 4) % 15 == 0 )
         {
             psField->Date.TZFlag = (GByte)(100
-                + atoi(pszInput+1) * 4
-                + (atoi(pszInput+4) / 15));
+                + atoi(pszInput + 1) * 4
+                + (atoi(pszInput + 4) / 15));
 
             if( pszInput[0] == '-' )
                 psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
         }
         else if( isdigit(pszInput[3]) && isdigit(pszInput[4])  // +HHMM offset
-                 && atoi(pszInput+3) % 15 == 0 )
+                 && atoi(pszInput + 3) % 15 == 0 )
         {
             psField->Date.TZFlag = (GByte)(100
-                + static_cast<GByte>(CPLScanLong(pszInput+1,2)) * 4
-                + (atoi(pszInput+3) / 15));
+                + static_cast<GByte>(CPLScanLong(pszInput + 1, 2)) * 4
+                + (atoi(pszInput + 3) / 15));
 
             if( pszInput[0] == '-' )
                 psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
         }
         else if( isdigit(pszInput[3]) && pszInput[4] == '\0'  // +HMM offset
-                 && atoi(pszInput+2) % 15 == 0 )
+                 && atoi(pszInput + 2) % 15 == 0 )
         {
             psField->Date.TZFlag = (GByte)(100
-                + static_cast<GByte>(CPLScanLong(pszInput+1,1)) * 4
-                + (atoi(pszInput+2) / 15));
+                + static_cast<GByte>(CPLScanLong(pszInput + 1, 1)) * 4
+                + (atoi(pszInput + 2) / 15));
 
             if( pszInput[0] == '-' )
                 psField->Date.TZFlag = -1 * (psField->Date.TZFlag - 100) + 100;
@@ -1107,7 +1160,6 @@ int OGRParseDate( const char *pszInput,
     return TRUE;
 }
 
-
 /************************************************************************/
 /*                           OGRParseXMLDateTime()                      */
 /************************************************************************/
@@ -1115,161 +1167,178 @@ int OGRParseDate( const char *pszInput,
 int OGRParseXMLDateTime( const char* pszXMLDateTime,
                          OGRField* psField)
 {
-    int year = 0, month = 0, day = 0, hour = 0, minute = 0, TZHour, TZMinute;
+    int year = 0;
+    int month = 0;
+    int day = 0;
+    int hour = 0;
+    int minute = 0;
+    int TZHour = 0;
+    int TZMinute = 0;
     float second = 0;
-    char c;
+    char c = '\0';
     int TZ = 0;
-    int bRet = FALSE;
+    bool bRet = false;
 
-    /* Date is expressed as a UTC date */
-    if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c",
-                &year, &month, &day, &hour, &minute, &second, &c) == 7 && c == 'Z')
+    // Date is expressed as a UTC date.
+    if( sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c",
+               &year, &month, &day, &hour, &minute, &second, &c) == 7 &&
+        c == 'Z' )
     {
         TZ = 100;
-        bRet = TRUE;
+        bRet = true;
     }
-    /* Date is expressed as a UTC date, with a timezone */
-    else if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c%02d:%02d",
-                &year, &month, &day, &hour, &minute, &second, &c, &TZHour, &TZMinute) == 9 &&
-                (c == '+' || c == '-'))
+    // Date is expressed as a UTC date, with a timezone.
+    else if( sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f%c%02d:%02d",
+                    &year, &month, &day, &hour, &minute, &second, &c,
+                    &TZHour, &TZMinute) == 9 &&
+             (c == '+' || c == '-') )
     {
         TZ = 100 + ((c == '+') ? 1 : -1) * ((TZHour * 60 + TZMinute) / 15);
-        bRet = TRUE;
+        bRet = true;
     }
-    /* Date is expressed into an unknown timezone */
-    else if (sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f",
-                    &year, &month, &day, &hour, &minute, &second) == 6)
+    // Date is expressed into an unknown timezone.
+    else if( sscanf(pszXMLDateTime, "%04d-%02d-%02dT%02d:%02d:%f",
+                    &year, &month, &day, &hour, &minute, &second) == 6 )
     {
         TZ = 0;
-        bRet = TRUE;
+        bRet = true;
     }
-    /* Date is expressed as a UTC date with only year:month:day */
-    else if (sscanf(pszXMLDateTime, "%04d-%02d-%02d", &year, &month, &day) == 3)
+    // Date is expressed as a UTC date with only year:month:day.
+    else if( sscanf(pszXMLDateTime, "%04d-%02d-%02d", &year, &month, &day) ==
+             3 )
     {
         TZ = 0;
-        bRet = TRUE;
+        bRet = true;
     }
 
-    if (bRet)
-    {
-        psField->Date.Year = (GInt16)year;
-        psField->Date.Month = (GByte)month;
-        psField->Date.Day = (GByte)day;
-        psField->Date.Hour = (GByte)hour;
-        psField->Date.Minute = (GByte)minute;
-        psField->Date.Second = second;
-        psField->Date.TZFlag = (GByte)TZ;
-        psField->Date.Reserved = 0;
-    }
+    if( !bRet )
+      return FALSE;
 
-    return bRet;
+    psField->Date.Year = static_cast<GInt16>(year);
+    psField->Date.Month = static_cast<GByte>(month);
+    psField->Date.Day = static_cast<GByte>(day);
+    psField->Date.Hour = static_cast<GByte>(hour);
+    psField->Date.Minute = static_cast<GByte>(minute);
+    psField->Date.Second = second;
+    psField->Date.TZFlag = static_cast<GByte>(TZ);
+    psField->Date.Reserved = 0;
+
+    return TRUE;
 }
 
 /************************************************************************/
 /*                      OGRParseRFC822DateTime()                        */
 /************************************************************************/
 
-static const char* const aszMonthStr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+static const char* const aszMonthStr[] = {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
 int OGRParseRFC822DateTime( const char* pszRFC822DateTime, OGRField* psField )
 {
-    /* Following http://asg.web.cmu.edu/rfc/rfc822.html#sec-5 : [Fri,] 28 Dec 2007 05:24[:17] GMT */
-    char** papszTokens = CSLTokenizeStringComplex( pszRFC822DateTime, " ,:", TRUE, FALSE );
+    // Following
+    // http://asg.web.cmu.edu/rfc/rfc822.html#sec-5 :
+    // [Fri,] 28 Dec 2007 05:24[:17] GMT
+    char** papszTokens =
+        CSLTokenizeStringComplex( pszRFC822DateTime, " ,:", TRUE, FALSE );
     char** papszVal = papszTokens;
-    int bRet = FALSE;
+    bool bRet = false;
     int nTokens = CSLCount(papszTokens);
-    if (nTokens >= 6)
+    if( nTokens < 6 )
     {
-        if ( ! ((*papszVal)[0] >= '0' && (*papszVal)[0] <= '9') )
-        {
-            /* Ignore day of week */
-            papszVal ++;
-        }
+        CSLDestroy(papszTokens);
+        return false;
+    }
 
-        int day = atoi(*papszVal);
-        papszVal ++;
+    if( !((*papszVal)[0] >= '0' && (*papszVal)[0] <= '9') )
+    {
+        // Ignore day of week.
+        ++papszVal;
+    }
 
-        int month = 0;
+    const int day = atoi(*papszVal);
+    ++papszVal;
 
-        for(int i = 0; i < 12; i++)
-        {
-            if (EQUAL(*papszVal, aszMonthStr[i]))
-                month = i + 1;
-        }
-        papszVal ++;
+    int month = 0;
+
+    for( int i = 0; i < 12; ++i )
+    {
+        if( EQUAL(*papszVal, aszMonthStr[i]) )
+            month = i + 1;
+    }
+    ++papszVal;
+
+    int year = atoi(*papszVal);
+    ++papszVal;
+    if( year < 100 && year >= 30 )
+        year += 1900;
+    else if( year < 30 && year >= 0 )
+        year += 2000;
 
-        int year = atoi(*papszVal);
-        papszVal ++;
-        if( year < 100 && year >= 30 )
-            year += 1900;
-        else if( year < 30 && year >= 0 )
-            year += 2000;
+    const int hour = atoi(*papszVal);
+    ++papszVal;
 
-        int hour = atoi(*papszVal);
-        papszVal ++;
+    const int minute = atoi(*papszVal);
+    ++papszVal;
 
-        int minute = atoi(*papszVal);
-        papszVal ++;
+    int second = 0;
+    if( *papszVal != NULL && (*papszVal)[0] >= '0' && (*papszVal)[0] <= '9' )
+    {
+        second = atoi(*papszVal);
+        ++papszVal;
+    }
+
+    if( month != 0 )
+    {
+        bRet = true;
+        int TZ = 0;
 
-        int second = 0;
-        if (*papszVal != NULL && (*papszVal)[0] >= '0' && (*papszVal)[0] <= '9')
+        if( *papszVal == NULL )
         {
-            second = atoi(*papszVal);
-            papszVal ++;
         }
-
-        if (month != 0)
+        else if( strlen(*papszVal) == 5 &&
+                 ((*papszVal)[0] == '+' || (*papszVal)[0] == '-') )
         {
-            bRet = TRUE;
-            int TZ = 0;
-
-            if (*papszVal == NULL)
-            {
-            }
-            else if (strlen(*papszVal) == 5 &&
-                     ((*papszVal)[0] == '+' || (*papszVal)[0] == '-'))
-            {
-                char szBuf[3];
-                szBuf[0] = (*papszVal)[1];
-                szBuf[1] = (*papszVal)[2];
-                szBuf[2] = 0;
-                int TZHour = atoi(szBuf);
-                szBuf[0] = (*papszVal)[3];
-                szBuf[1] = (*papszVal)[4];
-                szBuf[2] = 0;
-                int TZMinute = atoi(szBuf);
-                TZ = 100 + (((*papszVal)[0] == '+') ? 1 : -1) * ((TZHour * 60 + TZMinute) / 15);
-            }
-            else
+            char szBuf[3] = { (*papszVal)[1], (*papszVal)[2], 0 };
+            const int TZHour = atoi(szBuf);
+            szBuf[0] = (*papszVal)[3];
+            szBuf[1] = (*papszVal)[4];
+            szBuf[2] = 0;
+            const int TZMinute = atoi(szBuf);
+            TZ = 100 + (((*papszVal)[0] == '+') ? 1 : -1) *
+                        ((TZHour * 60 + TZMinute) / 15);
+        }
+        else
+        {
+            const char* aszTZStr[] = {
+                "GMT", "UT", "Z", "EST", "EDT", "CST", "CDT", "MST", "MDT",
+                "PST", "PDT"
+            };
+            int anTZVal[] = { 0, 0, 0, -5, -4, -6, -5, -7, -6, -8, -7 };
+            for( int i = 0; i < 11; ++i )
             {
-                const char* aszTZStr[] = { "GMT", "UT", "Z", "EST", "EDT", "CST", "CDT", "MST", "MDT", "PST", "PDT" };
-                int anTZVal[] = { 0, 0, 0, -5, -4, -6, -5, -7, -6, -8, -7 };
-                for(int i = 0; i < 11; i++)
+                if( EQUAL(*papszVal, aszTZStr[i]) )
                 {
-                    if (EQUAL(*papszVal, aszTZStr[i]))
-                    {
-                        TZ =  100 + anTZVal[i] * 4;
-                        break;
-                    }
+                    TZ = 100 + anTZVal[i] * 4;
+                    break;
                 }
             }
-
-            psField->Date.Year = (GInt16)year;
-            psField->Date.Month = (GByte)month;
-            psField->Date.Day = (GByte)day;
-            psField->Date.Hour = (GByte)hour;
-            psField->Date.Minute = (GByte)minute;
-            psField->Date.Second = static_cast<float>(second);
-            psField->Date.TZFlag = (GByte)TZ;
-            psField->Date.Reserved = 0;
         }
+
+        psField->Date.Year = static_cast<GInt16>(year);
+        psField->Date.Month = static_cast<GByte>(month);
+        psField->Date.Day = static_cast<GByte>(day);
+        psField->Date.Hour = static_cast<GByte>(hour);
+        psField->Date.Minute = static_cast<GByte>(minute);
+        psField->Date.Second = static_cast<float>(second);
+        psField->Date.TZFlag = static_cast<GByte>(TZ);
+        psField->Date.Reserved = 0;
     }
+
     CSLDestroy(papszTokens);
     return bRet;
 }
 
-
 /**
   * Returns the day of the week in Gregorian calendar
   *
@@ -1280,58 +1349,61 @@ int OGRParseRFC822DateTime( const char* pszRFC822DateTime, OGRField* psField )
   * @return day of the week : 0 for Monday, ... 6 for Sunday
   */
 
-int OGRGetDayOfWeek(int day, int month, int year)
+int OGRGetDayOfWeek( int day, int month, int year )
 {
-    /* Reference: Zeller's congruence */
-    int q = day;
-    int m;
-    if (month >=3)
-        m = month;
+    // Reference: Zeller's congruence.
+    const int q = day;
+    int m = month;
+    if( month >=3 )
+    {
+        // m = month;
+    }
     else
     {
         m = month + 12;
-        year --;
+        year--;
     }
-    int K = year % 100;
-    int J = year / 100;
-    int h = ( q + (((m+1)*26)/10) + K + K/4 + J/4 + 5 * J) % 7;
+    const int K = year % 100;
+    const int J = year / 100;
+    const int h = ( q + (((m+1)*26)/10) + K + K/4 + J/4 + 5 * J) % 7;
     return ( h + 5 ) % 7;
 }
 
-
 /************************************************************************/
 /*                         OGRGetRFC822DateTime()                       */
 /************************************************************************/
 
-char* OGRGetRFC822DateTime(const OGRField* psField)
+char* OGRGetRFC822DateTime( const OGRField* psField )
 {
     char* pszTZ = NULL;
-    const char* aszDayOfWeek[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
+    const char* aszDayOfWeek[] =
+        { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
 
     int dayofweek = OGRGetDayOfWeek(psField->Date.Day, psField->Date.Month,
                                     psField->Date.Year);
 
     int month = psField->Date.Month;
-    if (month < 1 || month > 12)
+    if( month < 1 || month > 12 )
         month = 1;
 
     int TZFlag = psField->Date.TZFlag;
-    if (TZFlag == 0 || TZFlag == 100)
+    if( TZFlag == 0 || TZFlag == 100 )
     {
         pszTZ = CPLStrdup("GMT");
     }
     else
     {
-        int TZOffset = ABS(TZFlag - 100) * 15;
+        int TZOffset = std::abs(TZFlag - 100) * 15;
         int TZHour = TZOffset / 60;
         int TZMinute = TZOffset - TZHour * 60;
         pszTZ = CPLStrdup(CPLSPrintf("%c%02d%02d", TZFlag > 100 ? '+' : '-',
                                         TZHour, TZMinute));
     }
-    char* pszRet = CPLStrdup(CPLSPrintf("%s, %02d %s %04d %02d:%02d:%02d %s",
-                     aszDayOfWeek[dayofweek], psField->Date.Day, aszMonthStr[month - 1],
-                     psField->Date.Year, psField->Date.Hour,
-                     psField->Date.Minute, (int)psField->Date.Second, pszTZ));
+    char* pszRet = CPLStrdup(CPLSPrintf(
+        "%s, %02d %s %04d %02d:%02d:%02d %s",
+        aszDayOfWeek[dayofweek], psField->Date.Day, aszMonthStr[month - 1],
+        psField->Date.Year, psField->Date.Hour,
+        psField->Date.Minute, static_cast<int>(psField->Date.Second), pszTZ));
     CPLFree(pszTZ);
     return pszRet;
 }
@@ -1342,36 +1414,43 @@ char* OGRGetRFC822DateTime(const OGRField* psField)
 
 char* OGRGetXMLDateTime(const OGRField* psField)
 {
-    char* pszRet;
-    int year = psField->Date.Year;
-    int month = psField->Date.Month;
-    int day = psField->Date.Day;
-    int hour = psField->Date.Hour;
-    int minute = psField->Date.Minute;
-    float second = psField->Date.Second;
-    int TZFlag = psField->Date.TZFlag;
-    if (TZFlag == 0 || TZFlag == 100)
+    const int year = psField->Date.Year;
+    const int month = psField->Date.Month;
+    const int day = psField->Date.Day;
+    const int hour = psField->Date.Hour;
+    const int minute = psField->Date.Minute;
+    const float second = psField->Date.Second;
+    const int TZFlag = psField->Date.TZFlag;
+
+    char* pszRet = NULL;
+
+    if( TZFlag == 0 || TZFlag == 100 )
     {
         if( OGR_GET_MS(second) )
-            pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%06.3fZ",
-                                    year, month, day, hour, minute, second));
+            pszRet = CPLStrdup(CPLSPrintf(
+                "%04d-%02d-%02dT%02d:%02d:%06.3fZ",
+                year, month, day, hour, minute, second));
         else
-            pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02dZ",
-                                    year, month, day, hour, minute, (int)second));
+            pszRet = CPLStrdup(CPLSPrintf(
+                "%04d-%02d-%02dT%02d:%02d:%02dZ",
+                year, month, day, hour, minute, static_cast<int>(second)));
     }
     else
     {
-        int TZOffset = ABS(TZFlag - 100) * 15;
-        int TZHour = TZOffset / 60;
-        int TZMinute = TZOffset - TZHour * 60;
+        const int TZOffset = std::abs(TZFlag - 100) * 15;
+        const int TZHour = TZOffset / 60;
+        const int TZMinute = TZOffset - TZHour * 60;
         if( OGR_GET_MS(second) )
-            pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%06.3f%c%02d:%02d",
-                           year, month, day, hour, minute, second,
-                           (TZFlag > 100) ? '+' : '-', TZHour, TZMinute));
+            pszRet = CPLStrdup(CPLSPrintf(
+                "%04d-%02d-%02dT%02d:%02d:%06.3f%c%02d:%02d",
+                year, month, day, hour, minute, second,
+                (TZFlag > 100) ? '+' : '-', TZHour, TZMinute));
         else
-            pszRet = CPLStrdup(CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
-                            year, month, day, hour, minute, (int)second,
-                            (TZFlag > 100) ? '+' : '-', TZHour, TZMinute));
+            pszRet = CPLStrdup(
+                CPLSPrintf("%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
+                           year, month, day, hour, minute,
+                           static_cast<int>(second),
+                           TZFlag > 100 ? '+' : '-', TZHour, TZMinute));
     }
     return pszRet;
 }
@@ -1382,24 +1461,26 @@ char* OGRGetXMLDateTime(const OGRField* psField)
 
 char* OGRGetXML_UTF8_EscapedString(const char* pszString)
 {
-    char *pszEscaped;
-    if (!CPLIsUTF8(pszString, -1) &&
-         CSLTestBoolean(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")))
+    char *pszEscaped = NULL;
+    if( !CPLIsUTF8(pszString, -1) &&
+         CPLTestBool(CPLGetConfigOption("OGR_FORCE_ASCII", "YES")) )
     {
         static bool bFirstTime = true;
-        if (bFirstTime)
+        if( bFirstTime )
         {
             bFirstTime = false;
             CPLError(CE_Warning, CPLE_AppDefined,
-                    "%s is not a valid UTF-8 string. Forcing it to ASCII.\n"
-                    "If you still want the original string and change the XML file encoding\n"
-                    "afterwards, you can define OGR_FORCE_ASCII=NO as configuration option.\n"
-                    "This warning won't be issued anymore", pszString);
+                     "%s is not a valid UTF-8 string. Forcing it to ASCII.  "
+                     "If you still want the original string and change the XML "
+                     "file encoding afterwards, you can define "
+                     "OGR_FORCE_ASCII=NO as configuration option.  "
+                     "This warning won't be issued anymore", pszString);
         }
         else
         {
-            CPLDebug("OGR", "%s is not a valid UTF-8 string. Forcing it to ASCII",
-                    pszString);
+            CPLDebug("OGR",
+                     "%s is not a valid UTF-8 string. Forcing it to ASCII",
+                     pszString);
         }
         char* pszTemp = CPLForceToASCII(pszString, -1, '?');
         pszEscaped = CPLEscapeString( pszTemp, -1, CPLES_XML );
@@ -1414,39 +1495,39 @@ char* OGRGetXML_UTF8_EscapedString(const char* pszString)
 /*                        OGRCompareDate()                              */
 /************************************************************************/
 
-int OGRCompareDate(   OGRField *psFirstTuple,
-                      OGRField *psSecondTuple )
+int OGRCompareDate( const OGRField *psFirstTuple,
+                    const OGRField *psSecondTuple )
 {
-    /* FIXME? : We ignore TZFlag */
+    // TODO: We ignore TZFlag.
 
-    if (psFirstTuple->Date.Year < psSecondTuple->Date.Year)
+    if( psFirstTuple->Date.Year < psSecondTuple->Date.Year )
         return -1;
-    else if (psFirstTuple->Date.Year > psSecondTuple->Date.Year)
+    else if( psFirstTuple->Date.Year > psSecondTuple->Date.Year )
         return 1;
 
-    if (psFirstTuple->Date.Month < psSecondTuple->Date.Month)
+    if( psFirstTuple->Date.Month < psSecondTuple->Date.Month )
         return -1;
-    else if (psFirstTuple->Date.Month > psSecondTuple->Date.Month)
+    else if( psFirstTuple->Date.Month > psSecondTuple->Date.Month )
         return 1;
 
-    if (psFirstTuple->Date.Day < psSecondTuple->Date.Day)
+    if( psFirstTuple->Date.Day < psSecondTuple->Date.Day )
         return -1;
-    else if (psFirstTuple->Date.Day > psSecondTuple->Date.Day)
+    else if( psFirstTuple->Date.Day > psSecondTuple->Date.Day )
         return 1;
 
-    if (psFirstTuple->Date.Hour < psSecondTuple->Date.Hour)
+    if( psFirstTuple->Date.Hour < psSecondTuple->Date.Hour )
         return -1;
-    else if (psFirstTuple->Date.Hour > psSecondTuple->Date.Hour)
+    else if( psFirstTuple->Date.Hour > psSecondTuple->Date.Hour )
         return 1;
 
-    if (psFirstTuple->Date.Minute < psSecondTuple->Date.Minute)
+    if( psFirstTuple->Date.Minute < psSecondTuple->Date.Minute )
         return -1;
-    else if (psFirstTuple->Date.Minute > psSecondTuple->Date.Minute)
+    else if( psFirstTuple->Date.Minute > psSecondTuple->Date.Minute )
         return 1;
 
-    if (psFirstTuple->Date.Second < psSecondTuple->Date.Second)
+    if( psFirstTuple->Date.Second < psSecondTuple->Date.Second )
         return -1;
-    else if (psFirstTuple->Date.Second > psSecondTuple->Date.Second)
+    else if( psFirstTuple->Date.Second > psSecondTuple->Date.Second )
         return 1;
 
     return 0;
@@ -1456,26 +1537,26 @@ int OGRCompareDate(   OGRField *psFirstTuple,
 /*                        OGRFastAtof()                                 */
 /************************************************************************/
 
-/* On Windows, CPLAtof() is very slow if the number */
-/* is followed by other long content. */
-/* So we just extract the number into a short string */
-/* before calling CPLAtof() on it */
+// On Windows, CPLAtof() is very slow if the number is followed by other long
+// content.  Just extract the number into a short string before calling
+// CPLAtof() on it.
 static
 double OGRCallAtofOnShortString(const char* pszStr)
 {
-    char szTemp[128];
-    int nCounter = 0;
     const char* p = pszStr;
-    while(*p == ' ' || *p == '\t')
-        p++;
-    while(*p == '+'  ||
-          *p == '-'  ||
-          (*p >= '0' && *p <= '9') ||
-          *p == '.'  ||
-          (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D'))
+    while( *p == ' ' || *p == '\t' )
+        ++p;
+
+    char szTemp[128] = {};
+    int nCounter = 0;
+    while( *p == '+' ||
+           *p == '-' ||
+           (*p >= '0' && *p <= '9') ||
+           *p == '.' ||
+           (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D') )
     {
         szTemp[nCounter++] = *(p++);
-        if (nCounter == 127)
+        if( nCounter == 127 )
             return CPLAtof(pszStr);
     }
     szTemp[nCounter] = '\0';
@@ -1502,30 +1583,30 @@ double OGRFastAtof(const char* pszStr)
         1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31
     };
 
-    while(*p == ' ' || *p == '\t')
-        p++;
+    while( *p == ' ' || *p == '\t' )
+        ++p;
 
-    if (*p == '+')
-        p++;
-    else if (*p == '-')
+    if( *p == '+' )
+        ++p;
+    else if( *p == '-' )
     {
         dfSign = -1.0;
-        p++;
+        ++p;
     }
 
     while( true )
     {
-        if (*p >= '0' && *p <= '9')
+        if( *p >= '0' && *p <= '9' )
         {
             dfVal = dfVal * 10.0 + (*p - '0');
-            p++;
+            ++p;
         }
-        else if (*p == '.')
+        else if( *p == '.' )
         {
-            p++;
+            ++p;
             break;
         }
-        else if (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D')
+        else if( *p == 'e' || *p == 'E' || *p == 'd' || *p == 'D' )
             return OGRCallAtofOnShortString(pszStr);
         else
             return dfSign * dfVal;
@@ -1534,17 +1615,17 @@ double OGRFastAtof(const char* pszStr)
     unsigned int countFractionnal = 0;
     while( true )
     {
-        if (*p >= '0' && *p <= '9')
+        if( *p >= '0' && *p <= '9' )
         {
             dfVal = dfVal * 10.0 + (*p - '0');
-            countFractionnal ++;
-            p++;
+            ++countFractionnal;
+            ++p;
         }
-        else if (*p == 'e' || *p == 'E' || *p == 'd' || *p == 'D')
+        else if( *p == 'e' || *p == 'E' || *p == 'd' || *p == 'D' )
             return OGRCallAtofOnShortString(pszStr);
         else
         {
-            if (countFractionnal < sizeof(adfTenPower) / sizeof(adfTenPower[0]))
+            if( countFractionnal < CPL_ARRAYSIZE(adfTenPower) )
                 return dfSign * (dfVal / adfTenPower[countFractionnal]);
             else
                 return OGRCallAtofOnShortString(pszStr);
@@ -1553,27 +1634,26 @@ double OGRFastAtof(const char* pszStr)
 }
 
 /**
- * Check that panPermutation is a permutation of [0,nSize-1].
+ * Check that panPermutation is a permutation of [0, nSize-1].
  * @param panPermutation an array of nSize elements.
  * @param nSize size of the array.
- * @return OGRERR_NONE if panPermutation is a permutation of [0,nSize-1].
+ * @return OGRERR_NONE if panPermutation is a permutation of [0, nSize - 1].
  * @since OGR 1.9.0
  */
-OGRErr OGRCheckPermutation(int* panPermutation, int nSize)
+OGRErr OGRCheckPermutation( int* panPermutation, int nSize )
 {
     OGRErr eErr = OGRERR_NONE;
-    int* panCheck = (int*)CPLCalloc(nSize, sizeof(int));
-    int i;
-    for(i=0;i<nSize;i++)
+    int* panCheck = static_cast<int *>(CPLCalloc(nSize, sizeof(int)));
+    for( int i = 0; i < nSize; ++i )
     {
-        if (panPermutation[i] < 0 || panPermutation[i] >= nSize)
+        if( panPermutation[i] < 0 || panPermutation[i] >= nSize )
         {
             CPLError(CE_Failure, CPLE_IllegalArg,
                      "Bad value for element %d", i);
             eErr = OGRERR_FAILURE;
             break;
         }
-        if (panCheck[panPermutation[i]] != 0)
+        if( panCheck[panPermutation[i]] != 0 )
         {
             CPLError(CE_Failure, CPLE_IllegalArg,
                      "Array is not a permutation of [0,%d]",
@@ -1587,139 +1667,139 @@ OGRErr OGRCheckPermutation(int* panPermutation, int nSize)
     return eErr;
 }
 
-
-OGRErr OGRReadWKBGeometryType( unsigned char * pabyData, OGRwkbVariant eWkbVariant,
+OGRErr OGRReadWKBGeometryType( unsigned char * pabyData,
+                               OGRwkbVariant eWkbVariant,
                                OGRwkbGeometryType *peGeometryType )
 {
-    if ( !peGeometryType )
+    if( !peGeometryType )
         return OGRERR_FAILURE;
 
 /* -------------------------------------------------------------------- */
 /*      Get the byte order byte.                                        */
 /* -------------------------------------------------------------------- */
     int nByteOrder = DB2_V72_FIX_BYTE_ORDER(*pabyData);
-    if (!( nByteOrder == wkbXDR || nByteOrder == wkbNDR ))
+    if( !( nByteOrder == wkbXDR || nByteOrder == wkbNDR ) )
         return OGRERR_CORRUPT_DATA;
     OGRwkbByteOrder eByteOrder = (OGRwkbByteOrder) nByteOrder;
 
 /* -------------------------------------------------------------------- */
 /*      Get the geometry type.                                          */
 /* -------------------------------------------------------------------- */
-    int bIs3D = FALSE;
-    int bIsMeasured = FALSE;
-    int iRawType;
+    bool bIs3D = false;
+    bool bIsMeasured = false;
+    int iRawType = 0;
 
     memcpy(&iRawType, pabyData + 1, 4);
-    if ( OGR_SWAP(eByteOrder))
+    if( OGR_SWAP(eByteOrder))
     {
         CPL_SWAP32PTR(&iRawType);
     }
 
-    /* Test for M bit in PostGIS WKB, see ogrgeometry.cpp:4956 */
-    if ( 0x40000000 & iRawType )
+    // Test for M bit in PostGIS WKB, see ogrgeometry.cpp:4956.
+    if( 0x40000000 & iRawType )
     {
         iRawType &= ~0x40000000;
-        bIsMeasured = TRUE;
+        bIsMeasured = true;
     }
-    /* Old-style OGC z-bit is flipped? Tests also Z bit in PostGIS WKB */
-    if ( wkb25DBitInternalUse & iRawType )
+    // Old-style OGC z-bit is flipped? Tests also Z bit in PostGIS WKB.
+    if( wkb25DBitInternalUse & iRawType )
     {
-        /* Clean off top 3 bytes */
+        // Clean off top 3 bytes.
         iRawType &= 0x000000FF;
-        bIs3D = TRUE;
+        bIs3D = true;
     }
 
-    /*  ISO SQL/MM Part3 draft -> Deprecated */
-    /* See http://jtc1sc32.org/doc/N1101-1150/32N1107-WD13249-3--spatial.pdf  */
-    if (iRawType == 1000001)
+    // ISO SQL/MM Part3 draft -> Deprecated.
+    // See http://jtc1sc32.org/doc/N1101-1150/32N1107-WD13249-3--spatial.pdf
+    if( iRawType == 1000001 )
         iRawType = wkbCircularString;
-    else if (iRawType == 1000002)
+    else if( iRawType == 1000002 )
         iRawType = wkbCompoundCurve;
-    else if (iRawType == 1000003)
+    else if( iRawType == 1000003 )
         iRawType = wkbCurvePolygon;
-    else if (iRawType == 1000004)
+    else if( iRawType == 1000004 )
         iRawType = wkbMultiCurve;
-    else if (iRawType == 1000005)
+    else if( iRawType == 1000005 )
         iRawType = wkbMultiSurface;
-    else if (iRawType == 2000001)
+    else if( iRawType == 2000001 )
         iRawType = wkbPointZM;
-    else if (iRawType == 2000002)
+    else if( iRawType == 2000002 )
         iRawType = wkbLineStringZM;
-    else if (iRawType == 2000003)
+    else if( iRawType == 2000003 )
         iRawType = wkbCircularStringZM;
-    else if (iRawType == 2000004)
+    else if( iRawType == 2000004 )
         iRawType = wkbCompoundCurveZM;
-    else if (iRawType == 2000005)
+    else if( iRawType == 2000005 )
         iRawType = wkbPolygonZM;
-    else if (iRawType == 2000006)
+    else if( iRawType == 2000006 )
         iRawType = wkbCurvePolygonZM;
-    else if (iRawType == 2000007)
+    else if( iRawType == 2000007 )
         iRawType = wkbMultiPointZM;
-    else if (iRawType == 2000008)
+    else if( iRawType == 2000008 )
         iRawType = wkbMultiCurveZM;
-    else if (iRawType == 2000009)
+    else if( iRawType == 2000009 )
         iRawType = wkbMultiLineStringZM;
-    else if (iRawType == 2000010)
+    else if( iRawType == 2000010 )
         iRawType = wkbMultiSurfaceZM;
-    else if (iRawType == 2000011)
+    else if( iRawType == 2000011 )
         iRawType = wkbMultiPolygonZM;
-    else if (iRawType == 2000012)
+    else if( iRawType == 2000012 )
         iRawType = wkbGeometryCollectionZM;
-    else if (iRawType == 3000001)
+    else if( iRawType == 3000001 )
         iRawType = wkbPoint25D;
-    else if (iRawType == 3000002)
+    else if( iRawType == 3000002 )
         iRawType = wkbLineString25D;
-    else if (iRawType == 3000003)
+    else if( iRawType == 3000003 )
         iRawType = wkbCircularStringZ;
-    else if (iRawType == 3000004)
+    else if( iRawType == 3000004 )
         iRawType = wkbCompoundCurveZ;
-    else if (iRawType == 3000005)
+    else if( iRawType == 3000005 )
         iRawType = wkbPolygon25D;
-    else if (iRawType == 3000006)
+    else if( iRawType == 3000006 )
         iRawType = wkbCurvePolygonZ;
-    else if (iRawType == 3000007)
+    else if( iRawType == 3000007 )
         iRawType = wkbMultiPoint25D;
-    else if (iRawType == 3000008)
+    else if( iRawType == 3000008 )
         iRawType = wkbMultiCurveZ;
-    else if (iRawType == 3000009)
+    else if( iRawType == 3000009 )
         iRawType = wkbMultiLineString25D;
-    else if (iRawType == 3000010)
+    else if( iRawType == 3000010 )
         iRawType = wkbMultiSurfaceZ;
-    else if (iRawType == 3000011)
+    else if( iRawType == 3000011 )
         iRawType = wkbMultiPolygon25D;
-    else if (iRawType == 3000012)
+    else if( iRawType == 3000012 )
         iRawType = wkbGeometryCollection25D;
-    else if (iRawType == 4000001)
+    else if( iRawType == 4000001 )
         iRawType = wkbPointM;
-    else if (iRawType == 4000002)
+    else if( iRawType == 4000002 )
         iRawType = wkbLineStringM;
-    else if (iRawType == 4000003)
+    else if( iRawType == 4000003 )
         iRawType = wkbCircularStringM;
-    else if (iRawType == 4000004)
+    else if( iRawType == 4000004 )
         iRawType = wkbCompoundCurveM;
-    else if (iRawType == 4000005)
+    else if( iRawType == 4000005 )
         iRawType = wkbPolygonM;
-    else if (iRawType == 4000006)
+    else if( iRawType == 4000006 )
         iRawType = wkbCurvePolygonM;
-    else if (iRawType == 4000007)
+    else if( iRawType == 4000007 )
         iRawType = wkbMultiPointM;
-    else if (iRawType == 4000008)
+    else if( iRawType == 4000008 )
         iRawType = wkbMultiCurveM;
-    else if (iRawType == 4000009)
+    else if( iRawType == 4000009 )
         iRawType = wkbMultiLineStringM;
-    else if (iRawType == 4000010)
+    else if( iRawType == 4000010 )
         iRawType = wkbMultiSurfaceM;
-    else if (iRawType == 4000011)
+    else if( iRawType == 4000011 )
         iRawType = wkbMultiPolygonM;
-    else if (iRawType == 4000012)
+    else if( iRawType == 4000012 )
         iRawType = wkbGeometryCollectionM;
 
-    /* Sometimes the Z flag is in the 2nd byte? */
-    if ( iRawType & (wkb25DBitInternalUse >> 16) )
+    // Sometimes the Z flag is in the 2nd byte?
+    if( iRawType & (wkb25DBitInternalUse >> 16) )
     {
-        /* Clean off top 3 bytes */
+        // Clean off top 3 bytes.
         iRawType &= 0x000000FF;
-        bIs3D = TRUE;
+        bIs3D = true;
     }
 
     if( eWkbVariant == wkbVariantPostGIS1 )
@@ -1741,24 +1821,26 @@ OGRErr OGRReadWKBGeometryType( unsigned char * pabyData, OGRwkbVariant eWkbVaria
         iRawType += 2000;
     }
 
-    /* ISO SQL/MM style types are between 1-16, 1001-1016, 2001-2016, and 3001-3016 */
-    if ( !((iRawType > 0 && iRawType <= 16) ||
-           (iRawType > 1000 && iRawType <= 1016) ||
-           (iRawType > 2000 && iRawType <= 2016) ||
-           (iRawType > 3000 && iRawType <= 3016)) )
+    // ISO SQL/MM style types are between 1-17, 1001-1017, 2001-2017, and
+    // 3001-3017.
+    if( !((iRawType > 0 && iRawType <= 17) ||
+           (iRawType > 1000 && iRawType <= 1017) ||
+           (iRawType > 2000 && iRawType <= 2017) ||
+           (iRawType > 3000 && iRawType <= 3017)) )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported WKB type %d", iRawType);
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Unsupported WKB type %d", iRawType);
         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     }
 
-    /* convert to OGRwkbGeometryType value */
+    // Convert to OGRwkbGeometryType value.
     if( iRawType >= 1001 && iRawType <= 1007 )
     {
         iRawType -= 1000;
         iRawType |= wkb25DBitInternalUse;
     }
 
-    *peGeometryType = (OGRwkbGeometryType)iRawType;
+    *peGeometryType = static_cast<OGRwkbGeometryType>(iRawType);
 
     return OGRERR_NONE;
 }
diff --git a/ogr/osr_cs_wkt.c b/ogr/osr_cs_wkt.c
index 8a4fe29..3d01e5d 100644
--- a/ogr/osr_cs_wkt.c
+++ b/ogr/osr_cs_wkt.c
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr_cs_wkt.c 33714 2016-03-13 05:42:13Z goatbar $
+ * $Id: osr_cs_wkt.c 35305 2016-09-03 14:40:17Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  CS WKT parser
@@ -27,16 +27,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include <stdio.h>
 #include <string.h>
 
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-
 #include "osr_cs_wkt.h"
 
-#include "cpl_port.h"
-
 /************************************************************************/
 /*                        osr_cs_wkt_error()                            */
 /************************************************************************/
diff --git a/ogr/osr_cs_wkt.h b/ogr/osr_cs_wkt.h
index d895c3c..eca12b1 100644
--- a/ogr/osr_cs_wkt.h
+++ b/ogr/osr_cs_wkt.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr_cs_wkt.h 31777 2015-11-26 14:14:41Z rouault $
+ * $Id: osr_cs_wkt.h 34921 2016-08-04 22:26:31Z rouault $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  CS WKT parser
@@ -30,6 +30,8 @@
 #ifndef OSR_CS_WKT_H_INCLUDED_
 #define OSR_CS_WKT_H_INCLUDED_
 
+#ifndef DOXYGEN_SKIP
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -52,4 +54,6 @@ int osr_cs_wkt_parse(osr_cs_wkt_parse_context *context);
 }
 #endif
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /*  OSR_CS_WKT_H_INCLUDED_ */
diff --git a/ogr/osr_cs_wkt_parser.h b/ogr/osr_cs_wkt_parser.h
index c467805..4b79ce7 100644
--- a/ogr/osr_cs_wkt_parser.h
+++ b/ogr/osr_cs_wkt_parser.h
@@ -82,8 +82,6 @@ typedef int YYSTYPE;
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
-
-
 int osr_cs_wkt_parse (osr_cs_wkt_parse_context *context);
 
 #endif /* !YY_OSR_CS_WKT_OSR_CS_WKT_PARSER_H_INCLUDED  */
diff --git a/ogr/osr_tutorial.dox b/ogr/osr_tutorial.dox
index 1df8380..0371294 100644
--- a/ogr/osr_tutorial.dox
+++ b/ogr/osr_tutorial.dox
@@ -4,18 +4,18 @@
 
 The OGRSpatialReference, and OGRCoordinateTransformation classes provide
 services to represent coordinate systems (projections and datums) and to
-transform between them.  These services are loosely modeled on the 
-OpenGIS Coordinate Transformations specification, and use the same 
-Well Known Text format for describing coordinate systems. 
+transform between them.  These services are loosely modeled on the
+OpenGIS Coordinate Transformations specification, and use the same
+Well Known Text format for describing coordinate systems.
 
 Some background on OpenGIS coordinate systems and services can be found
 in the Simple Features for COM, and Spatial Reference Systems Abstract Model
 documents available from the <a href="http://www.opengeospatial.org">Open Geospatial Consortium</a>.
 The <a href="http://www.remotesensing.org/geotiff/proj_list">GeoTIFF Projections Transform List</a>
-may also be of assistance in 
-understanding formulations of projections in WKT.  The 
-<a href="http://www.epsg.org">EPSG</a> 
-Geodesy web page is also a useful resource. 
+may also be of assistance in
+understanding formulations of projections in WKT.  The
+<a href="http://www.epsg.org">EPSG</a>
+Geodesy web page is also a useful resource.
 
 \section osr_tutorial_cs Defining a Geographic Coordinate System
 
@@ -23,42 +23,42 @@ Coordinate systems are encapsulated in the OGRSpatialReference class.  There
 are a number of ways of initializing an OGRSpatialReference object to a
 valid coordinate system.  There are two primary kinds of coordinate systems.
 The first is geographic (positions are measured in long/lat) and the second
-is projected (such as UTM - positions are measured in meters or feet).  
+is projected (such as UTM - positions are measured in meters or feet).
 
 A Geographic coordinate system contains information on the datum (which implies
-an spheroid described by a semi-major axis, and inverse flattening), prime 
-meridian (normally Greenwich), and an angular units type which is normally 
-degrees.  The following code initializes a geographic coordinate system 
+an spheroid described by a semi-major axis, and inverse flattening), prime
+meridian (normally Greenwich), and an angular units type which is normally
+degrees.  The following code initializes a geographic coordinate system
 on supplying all this information along with a user visible name for the
-geographic coordinate system. 
+geographic coordinate system.
 
 \code
 	OGRSpatialReference oSRS;
 
 	oSRS.SetGeogCS( "My geographic coordinate system",
-	                "WGS_1984", 
-			"My WGS84 Spheroid", 
-			SRS_WGS84_SEMIMAJOR, SRS_WGS84_INVFLATTENING, 
-			"Greenwich", 0.0, 
+	                "WGS_1984",
+			"My WGS84 Spheroid",
+			SRS_WGS84_SEMIMAJOR, SRS_WGS84_INVFLATTENING,
+			"Greenwich", 0.0,
 			"degree", SRS_UA_DEGREE_CONV );
 \endcode
 
-Of these values, the names "My geographic coordinate system", "My WGS84 
+Of these values, the names "My geographic coordinate system", "My WGS84
 Spheroid", "Greenwich" and "degree" are not keys, but are used for display
 to the user.  However, the datum name "WGS_1984" is used as a key to identify
 the datum, and there are rules on what values can be used.  NOTE: Prepare
-writeup somewhere on valid datums! 
+writeup somewhere on valid datums!
 
 The OGRSpatialReference has built in support for a few well known coordinate
 systems, which include "NAD27", "NAD83", "WGS72" and "WGS84" which can be
-defined in a single call to SetWellKnownGeogCS(). 
+defined in a single call to SetWellKnownGeogCS().
 
 \code
 	oSRS.SetWellKnownGeogCS( "WGS84" );
 \endcode
 
 Furthermore, any geographic coordinate system in the EPSG database can
-be set by it's GCS code number if the EPSG database is available. 
+be set by it's GCS code number if the EPSG database is available.
 
 \code
 	oSRS.SetWellKnownGeogCS( "EPSG:4326" );
@@ -103,16 +103,16 @@ GEOGCS["WGS 84",
     AUTHORITY["EPSG",4326]]
 </pre>
 
-The OGRSpatialReference::importFromWkt() method can be used to set an 
+The OGRSpatialReference::importFromWkt() method can be used to set an
 OGRSpatialReference from a WKT coordinate system definition.
 
 \section osr_tutorial_proj Defining a Projected Coordinate System
 
-A projected coordinate system (such as UTM, Lambert Conformal Conic, etc) 
+A projected coordinate system (such as UTM, Lambert Conformal Conic, etc)
 requires and underlying geographic coordinate system as well as a definition
 for the projection transform used to translate between linear positions
 (in meters or feet) and angular long/lat positions.  The following code
-defines a UTM zone 17 projected coordinate system with an underlying 
+defines a UTM zone 17 projected coordinate system with an underlying
 geographic coordinate system (datum) of WGS84.
 
 \code
@@ -126,15 +126,15 @@ geographic coordinate system (datum) of WGS84.
 Calling SetProjCS() sets a user
 name for the projected coordinate system and establishes that the system
 is projected.  The SetWellKnownGeogCS() associates a geographic coordinate
-system, and the SetUTM() call sets detailed projection transformation 
-parameters.  At this time the above order is important in order to 
+system, and the SetUTM() call sets detailed projection transformation
+parameters.  At this time the above order is important in order to
 create a valid definition, but in the future the object will automatically
 reorder the internal representation as needed to remain valid.  For now
 <b>be careful of the order of steps defining an OGRSpatialReference!</b>
 
 The above definition would give a WKT version that looks something like
-the following.  Note that the UTM 17 was expanded into the details 
-transverse mercator definition of the UTM zone.  
+the following.  Note that the UTM 17 was expanded into the details
+transverse mercator definition of the UTM zone.
 
 <pre>
 PROJCS["UTM 17 (WGS84) in northern hemisphere.",
@@ -163,26 +163,26 @@ Mercator), SetLCC() (Lambert Conformal Conic), and SetMercator().
 \section osr_tutorial_query Querying Coordinate System
 
 Once an OGRSpatialReference has been established, various information about
-it can be queried.  It can be established if it is a projected or 
-geographic coordinate system using the OGRSpatialReference::IsProjected() and 
-OGRSpatialReference::IsGeographic() methods.  The 
-OGRSpatialReference::GetSemiMajor(), OGRSpatialReference::GetSemiMinor() and 
-OGRSpatialReference::GetInvFlattening() methods can be used to get 
+it can be queried.  It can be established if it is a projected or
+geographic coordinate system using the OGRSpatialReference::IsProjected() and
+OGRSpatialReference::IsGeographic() methods.  The
+OGRSpatialReference::GetSemiMajor(), OGRSpatialReference::GetSemiMinor() and
+OGRSpatialReference::GetInvFlattening() methods can be used to get
 information about the spheroid.  The OGRSpatialReference::GetAttrValue()
 method can be used to get the PROJCS, GEOGCS, DATUM, SPHEROID, and PROJECTION
-names strings.  The OGRSpatialReference::GetProjParm() method can be used to 
-get the projection parameters.  The OGRSpatialReference::GetLinearUnits() 
+names strings.  The OGRSpatialReference::GetProjParm() method can be used to
+get the projection parameters.  The OGRSpatialReference::GetLinearUnits()
 method can be used to fetch the linear units type, and translation to meters.
 
 The following code (from ogr_srs_proj4.cpp) demonstrates use
 of GetAttrValue() to get the projection, and GetProjParm() to get projection
-parameters.  The GetAttrValue() method searches for the first "value" 
-node associated with the named entry in the WKT text representation.  
-The #define'ed constants for projection parameters (such as 
+parameters.  The GetAttrValue() method searches for the first "value"
+node associated with the named entry in the WKT text representation.
+The \#define'ed constants for projection parameters (such as
 SRS_PP_CENTRAL_MERIDIAN) should be used when fetching projection parameter
 with GetProjParm().   The code for the Set methods of the various projections
-in ogrspatialreference.cpp can be consulted to find which parameters apply to 
-which projections.  
+in ogrspatialreference.cpp can be consulted to find which parameters apply to
+which projections.
 
 \code
     const char *pszProjection = poSRS->GetAttrValue("PROJECTION");
@@ -218,52 +218,52 @@ points between coordinate systems.
         OGRSpatialReference oSourceSRS, oTargetSRS;
         OGRCoordinateTransformation *poCT;
         double			x, y;
-            
+
         oSourceSRS.importFromEPSG( atoi(papszArgv[i+1]) );
         oTargetSRS.importFromEPSG( atoi(papszArgv[i+2]) );
-            
+
         poCT = OGRCreateCoordinateTransformation( &oSourceSRS,
                                                   &oTargetSRS );
         x = atof( papszArgv[i+3] );
         y = atof( papszArgv[i+4] );
-            
+
         if( poCT == NULL || !poCT->Transform( 1, &x, &y ) )
             printf( "Transformation failed.\n" );
         else
-            printf( "(%f,%f) -> (%f,%f)\n", 
+            printf( "(%f,%f) -> (%f,%f)\n",
                     atof( papszArgv[i+3] ),
                     atof( papszArgv[i+4] ),
                     x, y );
 \endcode
 
 There are a couple of points at which transformations can
-fail.  First, OGRCreateCoordinateTransformation() may fail, 
+fail.  First, OGRCreateCoordinateTransformation() may fail,
 generally because the internals recognise that no transformation
 between the indicated systems can be established.  This might
-be due to use of a projection not supported by the internal 
+be due to use of a projection not supported by the internal
 PROJ.4 library, differing datums for which no relationship
 is known, or one of the coordinate systems being inadequately
 defined.  If OGRCreateCoordinateTransformation() fails it will
-return a NULL. 
+return a NULL.
 
 The OGRCoordinateTransformation::Transform() method itself can
 also fail.  This may be as a delayed result of one of the above
-problems, or as a result of an operation being numerically 
-undefined for one or more of the passed in points.  The 
-Transform() function will return TRUE on success, or FALSE 
-if any of the points fail to transform.  The point array is 
+problems, or as a result of an operation being numerically
+undefined for one or more of the passed in points.  The
+Transform() function will return TRUE on success, or FALSE
+if any of the points fail to transform.  The point array is
 left in an indeterminate state on error.
 
 Though not shown above, the coordinate transformation service can
 take 3D points, and will adjust elevations for elevation differences
-in spheroids, and datums.  At some point in the future shifts 
+in spheroids, and datums.  At some point in the future shifts
 between different vertical datums may also be applied.  If no Z is
-passed, it is assume that the point is on the geoid. 
+passed, it is assume that the point is on the geoid.
 
 The following example shows how to conveniently create a lat/long coordinate
 system using the same geographic coordinate system as a projected coordinate
 system, and using that to transform between projected coordinates and
-lat/long. 
+lat/long.
 
 \code
     OGRSpatialReference    oUTM, *poLatLong;
@@ -274,13 +274,13 @@ lat/long.
     oUTM.SetUTM( 17 );
 
     poLatLong = oUTM.CloneGeogCS();
-    
+
     poTransform = OGRCreateCoordinateTransformation( &oUTM, poLatLong );
     if( poTransform == NULL )
     {
         ...
     }
-    
+
     ...
 
     if( !poTransform->Transform( nPoints, x, y, z ) )
@@ -289,15 +289,15 @@ lat/long.
 
 \section osr_tutorial_apis Alternate Interfaces
 
-A C interface to the coordinate system services is defined in 
-ogr_srs_api.h, and Python bindings are available via the osr.py module. 
+A C interface to the coordinate system services is defined in
+ogr_srs_api.h, and Python bindings are available via the osr.py module.
 Methods are close analogs of the C++ methods but C and Python bindings
-are missing for some C++ methods. 
+are missing for some C++ methods.
 
 <h3>C Bindings</h3>
 
 \code
-typedef void *OGRSpatialReferenceH;                               
+typedef void *OGRSpatialReferenceH;
 typedef void *OGRCoordinateTransformationH;
 
 OGRSpatialReferenceH OSRNewSpatialReference( const char * );
@@ -347,7 +347,7 @@ OGRErr  OSRSetAuthority( OGRSpatialReferenceH hSRS,
                          int nCode );
 OGRErr  OSRSetProjParm( OGRSpatialReferenceH, const char *, double );
 double  OSRGetProjParm( OGRSpatialReferenceH hSRS,
-                        const char * pszParmName, 
+                        const char * pszParmName,
                         double dfDefault,
                         OGRErr * );
 
@@ -392,6 +392,6 @@ class CoordinateTransformation:
 
 The OGRCoordinateTransformation service is implemented on top of the
 <a href="http://www.remotesensing.org/proj">PROJ.4</a> library originally
-written by Gerald Evenden of the USGS.  
+written by Gerald Evenden of the USGS.
 
 */
diff --git a/ogr/swq.cpp b/ogr/swq.cpp
index cd7fa75..8f7ec2a 100644
--- a/ogr/swq.cpp
+++ b/ogr/swq.cpp
@@ -19,15 +19,28 @@
  * It is provided "as is" without express or implied warranty.
  ****************************************************************************/
 
-#include <ctype.h>
+#include "cpl_port.h"
+#include "swq.h"
+
+#include <cctype>
+#include <cmath>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+
+#include <algorithm>
+#include <limits>
+#include <string>
 
-#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
-#include "swq.h"
-#include "swq_parser.hpp"
 #include "cpl_time.h"
+#include "swq_parser.hpp"
+
+CPL_CVSID("$Id: swq.cpp 37581 2017-03-03 16:23:40Z rouault $");
 
-#define YYSTYPE  swq_expr_node*
+#define YYSTYPE swq_expr_node *
 
 /************************************************************************/
 /*                               swqlex()                               */
@@ -41,17 +54,18 @@ void swqerror( swq_parse_context *context, const char *msg )
 
     int n = static_cast<int>(context->pszLastValid - context->pszInput);
 
-    for( int i = MAX(0,n-40); i < n + 40 && context->pszInput[i] != '\0'; i ++ )
+    for( int i = std::max(0, n - 40);
+         i < n + 40 && context->pszInput[i] != '\0';
+         i++ )
         osMsg += context->pszInput[i];
     osMsg += "\n";
-    for( int i=0;i<MIN(n, 40);i++ )
+    for( int i = 0; i < std::min(n, 40); i++ )
         osMsg += " ";
     osMsg += "^";
 
     CPLError( CE_Failure, CPLE_AppDefined, "%s", osMsg.c_str() );
 }
 
-
 /************************************************************************/
 /*                               swqlex()                               */
 /*                                                                      */
@@ -94,8 +108,6 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
 /* -------------------------------------------------------------------- */
     if( *pszInput == '"' || *pszInput == '\'' )
     {
-        char *token;
-        int i_token;
         char chQuote = *pszInput;
         bool bFoundEndQuote = false;
 
@@ -103,16 +115,18 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
 
         pszInput++;
 
-        token = (char *) CPLMalloc(strlen(pszInput)+1);
-        i_token = 0;
+        char *token = static_cast<char *>(CPLMalloc(strlen(pszInput) + 1));
+        int i_token = 0;
 
         while( *pszInput != '\0' )
         {
             if( chQuote == '"' && *pszInput == '\\' && pszInput[1] == '"' )
                 pszInput++;
-            else if( chQuote == '\'' && *pszInput == '\\' && pszInput[1] == '\'' )
+            else if( chQuote == '\'' && *pszInput == '\\' &&
+                     pszInput[1] == '\'' )
                 pszInput++;
-            else if( chQuote == '\'' && *pszInput == '\'' && pszInput[1] == '\'' )
+            else if( chQuote == '\'' && *pszInput == '\'' &&
+                     pszInput[1] == '\'' )
                 pszInput++;
             else if( *pszInput == chQuote )
             {
@@ -175,9 +189,9 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
 
         context->pszNext = pszNext;
 
-        if( strstr(osToken,".")
-            || strstr(osToken,"e")
-            || strstr(osToken,"E") )
+        if( strstr(osToken, ".")
+            || strstr(osToken, "e")
+            || strstr(osToken, "E") )
         {
             *ppNode = new swq_expr_node( CPLAtof(osToken) );
             return SWQT_FLOAT_NUMBER;
@@ -186,7 +200,7 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
         {
             GIntBig nVal = CPLAtoGIntBig(osToken);
             if( CPL_INT64_FITS_ON_INT32(nVal) )
-                *ppNode = new swq_expr_node( (int)nVal );
+                *ppNode = new swq_expr_node( static_cast<int>(nVal) );
             else
                 *ppNode = new swq_expr_node( nVal );
             return SWQT_INTEGER_NUMBER;
@@ -211,61 +225,65 @@ int swqlex( YYSTYPE *ppNode, swq_parse_context *context )
 
         context->pszNext = pszNext;
 
-        if( EQUAL(osToken,"IN") )
+        if( EQUAL(osToken, "IN") )
             nReturn = SWQT_IN;
-        else if( EQUAL(osToken,"LIKE") )
+        else if( EQUAL(osToken, "LIKE") )
             nReturn = SWQT_LIKE;
-        else if( EQUAL(osToken,"ILIKE") )
+        else if( EQUAL(osToken, "ILIKE") )
             nReturn = SWQT_LIKE;
-        else if( EQUAL(osToken,"ESCAPE") )
+        else if( EQUAL(osToken, "ESCAPE") )
             nReturn = SWQT_ESCAPE;
-        else if( EQUAL(osToken,"NULL") )
+        else if( EQUAL(osToken, "NULL") )
             nReturn = SWQT_NULL;
-        else if( EQUAL(osToken,"IS") )
+        else if( EQUAL(osToken, "IS") )
             nReturn = SWQT_IS;
-        else if( EQUAL(osToken,"NOT") )
+        else if( EQUAL(osToken, "NOT") )
             nReturn = SWQT_NOT;
-        else if( EQUAL(osToken,"AND") )
+        else if( EQUAL(osToken, "AND") )
             nReturn = SWQT_AND;
-        else if( EQUAL(osToken,"OR") )
+        else if( EQUAL(osToken, "OR") )
             nReturn = SWQT_OR;
-        else if( EQUAL(osToken,"BETWEEN") )
+        else if( EQUAL(osToken, "BETWEEN") )
             nReturn = SWQT_BETWEEN;
-        else if( EQUAL(osToken,"SELECT") )
+        else if( EQUAL(osToken, "SELECT") )
             nReturn = SWQT_SELECT;
-        else if( EQUAL(osToken,"LEFT") )
+        else if( EQUAL(osToken, "LEFT") )
             nReturn = SWQT_LEFT;
-        else if( EQUAL(osToken,"JOIN") )
+        else if( EQUAL(osToken, "JOIN") )
             nReturn = SWQT_JOIN;
-        else if( EQUAL(osToken,"WHERE") )
+        else if( EQUAL(osToken, "WHERE") )
             nReturn = SWQT_WHERE;
-        else if( EQUAL(osToken,"ON") )
+        else if( EQUAL(osToken, "ON") )
             nReturn = SWQT_ON;
-        else if( EQUAL(osToken,"ORDER") )
+        else if( EQUAL(osToken, "ORDER") )
             nReturn = SWQT_ORDER;
-        else if( EQUAL(osToken,"BY") )
+        else if( EQUAL(osToken, "BY") )
             nReturn = SWQT_BY;
-        else if( EQUAL(osToken,"FROM") )
+        else if( EQUAL(osToken, "FROM") )
             nReturn = SWQT_FROM;
-        else if( EQUAL(osToken,"AS") )
+        else if( EQUAL(osToken, "AS") )
             nReturn = SWQT_AS;
-        else if( EQUAL(osToken,"ASC") )
+        else if( EQUAL(osToken, "ASC") )
             nReturn = SWQT_ASC;
-        else if( EQUAL(osToken,"DESC") )
+        else if( EQUAL(osToken, "DESC") )
             nReturn = SWQT_DESC;
-        else if( EQUAL(osToken,"DISTINCT") )
+        else if( EQUAL(osToken, "DISTINCT") )
             nReturn = SWQT_DISTINCT;
-        else if( EQUAL(osToken,"CAST") )
+        else if( EQUAL(osToken, "CAST") )
             nReturn = SWQT_CAST;
-        else if( EQUAL(osToken,"UNION") )
+        else if( EQUAL(osToken, "UNION") )
             nReturn = SWQT_UNION;
-        else if( EQUAL(osToken,"ALL") )
+        else if( EQUAL(osToken, "ALL") )
             nReturn = SWQT_ALL;
-
-        /* Unhandled by OGR SQL */
-        else if( EQUAL(osToken,"LIMIT") ||
-                 EQUAL(osToken,"OUTER") ||
-                 EQUAL(osToken,"INNER") )
+        else if( EQUAL(osToken, "LIMIT") )
+            nReturn = SWQT_LIMIT;
+        else if( EQUAL(osToken, "OFFSET") )
+            nReturn = SWQT_OFFSET;
+
+        // Unhandled by OGR SQL.
+        else if( EQUAL(osToken, "LIMIT") ||
+                 EQUAL(osToken, "OUTER") ||
+                 EQUAL(osToken, "INNER") )
             nReturn = SWQT_RESERVED_KEYWORD;
 
         else
@@ -297,7 +315,6 @@ swq_select_summarize( swq_select *select_info,
 
 {
     swq_col_def *def = select_info->column_defs + dest_column;
-    swq_summary *summary;
 
 /* -------------------------------------------------------------------- */
 /*      Do various checking.                                            */
@@ -311,65 +328,90 @@ swq_select_summarize( swq_select *select_info,
     if( def->col_func == SWQCF_NONE && !def->distinct_flag )
         return NULL;
 
+    if( select_info->query_mode == SWQM_DISTINCT_LIST &&
+        select_info->order_specs > 0 )
+    {
+        if( select_info->order_specs > 1 )
+            return "Can't ORDER BY a DISTINCT list by more than one key.";
+
+        if( select_info->order_defs[0].field_index !=
+            select_info->column_defs[0].field_index )
+            return "Only selected DISTINCT field can be used for ORDER BY.";
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Create the summary information if this is the first row         */
 /*      being processed.                                                */
 /* -------------------------------------------------------------------- */
-    if( select_info->column_summary == NULL )
+    if( select_info->column_summary.empty() )
     {
-        select_info->column_summary = (swq_summary *)
-            CPLMalloc(sizeof(swq_summary) * select_info->result_columns);
-        memset( select_info->column_summary, 0,
-                sizeof(swq_summary) * select_info->result_columns );
-
+        select_info->column_summary.resize(select_info->result_columns);
         for( int i = 0; i < select_info->result_columns; i++ )
         {
-            select_info->column_summary[i].min = 1e20;
-            select_info->column_summary[i].max = -1e20;
-            strcpy(select_info->column_summary[i].szMin, "9999/99/99 99:99:99");
-            strcpy(select_info->column_summary[i].szMax, "0000/00/00 00:00:00");
+            if( def->distinct_flag )
+            {
+                swq_summary::Comparator oComparator;
+                if( select_info->order_specs > 0 )
+                {
+                    CPLAssert( select_info->order_specs ==1 );
+                    CPLAssert( select_info->result_columns == 1 );
+                    oComparator.bSortAsc =
+                        CPL_TO_BOOL(select_info->order_defs[0].ascending_flag);
+                }
+                if( select_info->column_defs[i].field_type == SWQ_INTEGER ||
+-                   select_info->column_defs[i].field_type == SWQ_INTEGER64 )
+                {
+                    oComparator.eType = SWQ_INTEGER64;
+                }
+                else if( select_info->column_defs[i].field_type == SWQ_FLOAT )
+                {
+                    oComparator.eType = SWQ_FLOAT;
+                }
+                else
+                {
+                    oComparator.eType = SWQ_STRING;
+                }
+                select_info->column_summary[i].oSetDistinctValues =
+                    std::set<CPLString, swq_summary::Comparator>(oComparator);
+            }
+            select_info->column_summary[i].min =
+                std::numeric_limits<double>::infinity();
+            select_info->column_summary[i].max =
+                -std::numeric_limits<double>::infinity();
+            select_info->column_summary[i].osMin = "9999/99/99 99:99:99";
+            select_info->column_summary[i].osMax = "0000/00/00 00:00:00";
         }
     }
 
 /* -------------------------------------------------------------------- */
 /*      If distinct processing is on, process that now.                 */
 /* -------------------------------------------------------------------- */
-    summary = select_info->column_summary + dest_column;
+    swq_summary& summary = select_info->column_summary[dest_column];
 
     if( def->distinct_flag )
     {
-        GIntBig  i;
-
-        /* This should be implemented with a much more complicated
-           data structure to achieve any sort of efficiency. */
-        for( i = 0; i < summary->count; i++ )
+        if( value == NULL )
+            value = SZ_OGR_NULL;
+        try
         {
-            if( value == NULL )
+            if( summary.oSetDistinctValues.find(value) ==
+                    summary.oSetDistinctValues.end() )
             {
-                if (summary->distinct_list[i] == NULL)
-                    break;
+                summary.oSetDistinctValues.insert(value);
+                if( select_info->order_specs == 0 )
+                {
+                    // If not sorted, keep values in their original order
+                    summary.oVectorDistinctValues.push_back(value);
+                }
+                summary.count ++;
             }
-            else if( summary->distinct_list[i] != NULL &&
-                     strcmp(value,summary->distinct_list[i]) == 0 )
-                break;
         }
-
-        if( i == summary->count )
+        catch( std::bad_alloc& )
         {
-            char  **old_list = summary->distinct_list;
-
-            summary->distinct_list = (char **)
-                CPLMalloc(sizeof(char *) * (size_t)(summary->count+1));
-            if( summary->count )
-            {
-                memcpy( summary->distinct_list, old_list,
-                        sizeof(char *) * (size_t)summary->count );
-            }
-            summary->distinct_list[(summary->count)++] =
-                (value != NULL) ? CPLStrdup( value ) : NULL;
-
-            CPLFree(old_list);
+            return "Out of memory";
         }
+
+        return NULL;
     }
 
 /* -------------------------------------------------------------------- */
@@ -381,85 +423,81 @@ swq_select_summarize( swq_select *select_info,
       case SWQCF_MIN:
         if( value != NULL && value[0] != '\0' )
         {
-            if(def->field_type == SWQ_DATE ||
-               def->field_type == SWQ_TIME ||
-               def->field_type == SWQ_TIMESTAMP)
+            if( def->field_type == SWQ_DATE ||
+                def->field_type == SWQ_TIME ||
+                def->field_type == SWQ_TIMESTAMP )
             {
-                if( strcmp( value, summary->szMin ) < 0 )
+                if( strcmp( value, summary.osMin ) < 0 )
                 {
-                    strncpy( summary->szMin, value, sizeof(summary->szMin) );
-                    summary->szMin[sizeof(summary->szMin) - 1] = '\0';
+                    summary.osMin = value;
                 }
             }
             else
             {
                 double df_val = CPLAtof(value);
-                if( df_val < summary->min )
-                    summary->min = df_val;
+                if( df_val < summary.min )
+                    summary.min = df_val;
             }
-            summary->count++;
+            summary.count++;
         }
         break;
       case SWQCF_MAX:
         if( value != NULL && value[0] != '\0' )
         {
-            if(def->field_type == SWQ_DATE ||
-               def->field_type == SWQ_TIME ||
-               def->field_type == SWQ_TIMESTAMP)
+            if( def->field_type == SWQ_DATE ||
+                def->field_type == SWQ_TIME ||
+                def->field_type == SWQ_TIMESTAMP )
             {
-                if( strcmp( value, summary->szMax ) > 0 )
+                if( strcmp( value, summary.osMax ) > 0 )
                 {
-                    strncpy( summary->szMax, value, sizeof(summary->szMax) );
-                    summary->szMax[sizeof(summary->szMax) - 1] = '\0';
+                    summary.osMax = value;
                 }
             }
             else
             {
                 double df_val = CPLAtof(value);
-                if( df_val > summary->max )
-                    summary->max = df_val;
+                if( df_val > summary.max )
+                    summary.max = df_val;
             }
-            summary->count++;
+            summary.count++;
         }
         break;
       case SWQCF_AVG:
       case SWQCF_SUM:
         if( value != NULL && value[0] != '\0' )
         {
-            if(def->field_type == SWQ_DATE ||
-               def->field_type == SWQ_TIME ||
-               def->field_type == SWQ_TIMESTAMP)
+            if( def->field_type == SWQ_DATE ||
+                def->field_type == SWQ_TIME ||
+                def->field_type == SWQ_TIMESTAMP )
             {
-                int nYear, nMonth, nDay, nHour = 0, nMin = 0;
-                float fSec = 0 ;
-                if( sscanf(value, "%04d/%02d/%02d %02d:%02d:%f",
-                           &nYear, &nMonth, &nDay, &nHour, &nMin, &fSec) == 6 ||
-                    sscanf(value, "%04d/%02d/%02d",
-                           &nYear, &nMonth, &nDay) == 3 )
+                OGRField sField;
+                if( OGRParseDate( value, &sField, 0 ) )
                 {
                     struct tm brokendowntime;
-                    brokendowntime.tm_year = nYear - 1900;
-                    brokendowntime.tm_mon = nMonth - 1;
-                    brokendowntime.tm_mday = nDay;
-                    brokendowntime.tm_hour = nHour;
-                    brokendowntime.tm_min = nMin;
-                    brokendowntime.tm_sec = (int)fSec;
-                    summary->count++;
-                    summary->sum += CPLYMDHMSToUnixTime(&brokendowntime);
-                    summary->sum += fmod((double)fSec, 1);
+                    brokendowntime.tm_year = sField.Date.Year - 1900;
+                    brokendowntime.tm_mon = sField.Date.Month - 1;
+                    brokendowntime.tm_mday = sField.Date.Day;
+                    brokendowntime.tm_hour = sField.Date.Hour;
+                    brokendowntime.tm_min = sField.Date.Minute;
+                    brokendowntime.tm_sec =
+                        static_cast<int>(sField.Date.Second);
+                    summary.count++;
+                    summary.sum += CPLYMDHMSToUnixTime(&brokendowntime);
+                    summary.sum += fmod(static_cast<double>(
+                                                    sField.Date.Second), 1.0);
                 }
             }
             else
             {
-                summary->count++;
-                summary->sum += CPLAtof(value);
+                summary.count++;
+                summary.sum += CPLAtof(value);
             }
         }
         break;
 
       case SWQCF_COUNT:
-        if( value != NULL && !def->distinct_flag )
-            summary->count++;
+        if( value != NULL )
+            summary.count++;
         break;
 
       case SWQCF_NONE:
@@ -478,119 +516,50 @@ swq_select_summarize( swq_select *select_info,
 /*                      sort comparison functions.                      */
 /************************************************************************/
 
-static int FORCE_CDECL swq_compare_int( const void *item1, const void *item2 )
-{
-    const char* pszStr1 = *((const char **) item1);
-    const char* pszStr2 = *((const char **) item2);
-    if (pszStr1 == NULL)
-        return (pszStr2 == NULL) ? 0 : -1;
-    else if (pszStr2 == NULL)
-        return 1;
-
-    const GIntBig v1 = CPLAtoGIntBig(pszStr1);
-    const GIntBig v2 = CPLAtoGIntBig(pszStr2);
-
-    if( v1 < v2 )
-        return -1;
-    else if( v1 == v2 )
-        return 0;
-    else
-        return 1;
-}
-
-static int FORCE_CDECL swq_compare_real( const void *item1, const void *item2 )
+static bool Compare (swq_field_type eType,
+                     const CPLString& a,
+                     const CPLString& b)
 {
-    const char* pszStr1 = *((const char **) item1);
-    const char* pszStr2 = *((const char **) item2);
-    if (pszStr1 == NULL)
-        return (pszStr2 == NULL) ? 0 : -1;
-    else if (pszStr2 == NULL)
-        return 1;
-
-    const double v1 = CPLAtof(pszStr1);
-    const double v2 = CPLAtof(pszStr2);
-
-    if( v1 < v2 )
-        return -1;
-    else if( v1 == v2 )
-        return 0;
+    if( a == SZ_OGR_NULL )
+        return b != SZ_OGR_NULL;
+    else if( b == SZ_OGR_NULL )
+        return false;
     else
-        return 1;
+    {
+        if( eType == SWQ_INTEGER64 )
+            return CPLAtoGIntBig(a) < CPLAtoGIntBig(b);
+        else if( eType == SWQ_FLOAT )
+            return CPLAtof(a) < CPLAtof(b);
+        else if( eType == SWQ_STRING )
+            return a < b;
+        else
+        {
+            CPLAssert( false );
+            return false;
+        }
+    }
 }
 
-static int FORCE_CDECL swq_compare_string( const void *item1, const void *item2 )
+#ifndef DOXYGEN_SKIP
+bool swq_summary::Comparator::operator() (const CPLString& a,
+                                          const CPLString& b) const
 {
-    const char* pszStr1 = *((const char **) item1);
-    const char* pszStr2 = *((const char **) item2);
-    if (pszStr1 == NULL)
-        return (pszStr2 == NULL) ? 0 : -1;
-    else if (pszStr2 == NULL)
-        return 1;
-
-    return strcmp( pszStr1, pszStr2 );
-}
-
-/************************************************************************/
-/*                    swq_select_finish_summarize()                     */
-/*                                                                      */
-/*      Call to complete summarize work.  Does stuff like ordering      */
-/*      the distinct list for instance.                                 */
-/************************************************************************/
-
-const char *swq_select_finish_summarize( swq_select *select_info )
-
-{
-    int (FORCE_CDECL *compare_func)(const void *, const void*);
-    GIntBig count = 0;
-    char **distinct_list = NULL;
-
-    if( select_info->query_mode != SWQM_DISTINCT_LIST
-        || select_info->order_specs == 0 )
-        return NULL;
-
-    if( select_info->order_specs > 1 )
-        return "Can't ORDER BY a DISTINCT list by more than one key.";
-
-    if( select_info->order_defs[0].field_index !=
-        select_info->column_defs[0].field_index )
-        return "Only selected DISTINCT field can be used for ORDER BY.";
-
-    if( select_info->column_summary == NULL )
-        return NULL;
-
-    if( select_info->column_defs[0].field_type == SWQ_INTEGER ||
-        select_info->column_defs[0].field_type == SWQ_INTEGER64 )
-        compare_func = swq_compare_int;
-    else if( select_info->column_defs[0].field_type == SWQ_FLOAT )
-        compare_func = swq_compare_real;
+    if( bSortAsc )
+    {
+        return Compare(eType, a, b);
+    }
     else
-        compare_func = swq_compare_string;
-
-    distinct_list = select_info->column_summary[0].distinct_list;
-    count = select_info->column_summary[0].count;
-
-    qsort( distinct_list, (size_t)count, sizeof(char *), compare_func );
-
-/* -------------------------------------------------------------------- */
-/*      Do we want the list ascending in stead of descending?           */
-/* -------------------------------------------------------------------- */
-    if( !select_info->order_defs[0].ascending_flag )
     {
-        for( GIntBig i = 0; i < count/2; i++ )
-        {
-            char *saved = distinct_list[i];
-            distinct_list[i] = distinct_list[count-i-1];
-            distinct_list[count-i-1] = saved;
-        }
+        return Compare(eType, b, a);
     }
-
-    return NULL;
 }
+#endif
 
 /************************************************************************/
 /*                         swq_identify_field()                         */
 /************************************************************************/
-int swq_identify_field_internal( const char* table_name, const char *field_token,
+int swq_identify_field_internal( const char* table_name,
+                                 const char *field_token,
                                  swq_field_list *field_list,
                                  swq_field_type *this_type, int *table_id,
                                  int bOneMoreTimeOK );
@@ -604,7 +573,8 @@ int swq_identify_field( const char* table_name, const char *field_token,
                                        this_type, table_id, TRUE);
 }
 
-int swq_identify_field_internal( const char* table_name, const char *field_token,
+int swq_identify_field_internal( const char* table_name,
+                                 const char *field_token,
                                  swq_field_list *field_list,
                                  swq_field_type *this_type, int *table_id,
                                  int bOneMoreTimeOK )
@@ -625,26 +595,26 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
 /* -------------------------------------------------------------------- */
     for( int i = 0; i < field_list->count; i++ )
     {
-        int  t_id = 0;
-
         if( !EQUAL( field_list->names[i], field_token ) )
             continue;
 
-        /* Do the table specifications match? */
+        int t_id = 0;
+
+        // Do the table specifications match?/
         if( tables_enabled )
         {
             t_id = field_list->table_ids[i];
             if( table_name[0] != '\0'
-                && !EQUAL(table_name,field_list->table_defs[t_id].table_alias))
+                && !EQUAL(table_name, field_list->table_defs[t_id].table_alias))
                 continue;
 
-//            if( t_id != 0 && table_name[0] == '\0' )
-//                continue;
+            // if( t_id != 0 && table_name[0] == '\0' )
+            //     continue;
         }
         else if( table_name[0] != '\0' )
             break;
 
-        /* We have a match, return various information */
+        // We have a match, return various information.
         if( this_type != NULL )
         {
             if( field_list->types != NULL )
@@ -665,21 +635,24 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
 /* -------------------------------------------------------------------- */
 /*      When there is no ambiguity, try to accept quoting errors...     */
 /* -------------------------------------------------------------------- */
-    if( bOneMoreTimeOK && !CSLTestBoolean(CPLGetConfigOption("OGR_SQL_STRICT", "FALSE")) )
+    if( bOneMoreTimeOK &&
+        !CPLTestBool(CPLGetConfigOption("OGR_SQL_STRICT", "FALSE")) )
     {
         if( table_name[0] )
         {
-            CPLString osAggregatedName(CPLSPrintf("%s.%s", table_name, field_token));
+            CPLString osAggregatedName(
+                CPLSPrintf("%s.%s", table_name, field_token));
 
             // Check there's no table called table_name, or a field called with
-            // the aggregated name
-            int i;
-            for( i = 0; i < field_list->count; i++ )
+            // the aggregated name.
+            int i = 0;  // Used after for.
+            for( ; i < field_list->count; i++ )
             {
                 if( tables_enabled )
                 {
                     int t_id = field_list->table_ids[i];
-                    if( EQUAL(table_name,field_list->table_defs[t_id].table_alias) )
+                    if( EQUAL(table_name,
+                              field_list->table_defs[t_id].table_alias) )
                         break;
                 }
             }
@@ -692,9 +665,10 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
                 if( ret >= 0 )
                 {
                     CPLError(CE_Warning, CPLE_AppDefined,
-                            "Passed field name %s.%s should have been surrounded by double quotes. "
-                            "Accepted since there is no ambiguity...",
-                            table_name, field_token);
+                             "Passed field name %s.%s should have been "
+                             "surrounded by double quotes. "
+                             "Accepted since there is no ambiguity...",
+                             table_name, field_token);
                 }
                 return ret;
             }
@@ -702,8 +676,8 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
         else
         {
             // If the fieldname is a.b (and there's no . in b), then
-            // it might be an error in providing it as being quoted where it should
-            // not have been quoted.
+            // it might be an error in providing it as being quoted where it
+            // should not have been quoted.
             const char* pszDot = strchr(field_token, '.');
             if( pszDot && strchr(pszDot+1, '.') == NULL )
             {
@@ -718,7 +692,8 @@ int swq_identify_field_internal( const char* table_name, const char *field_token
                 if( ret >= 0 )
                 {
                     CPLError(CE_Warning, CPLE_AppDefined,
-                            "Passed field name %s should NOT have been surrounded by double quotes. "
+                            "Passed field name %s should NOT have been "
+                             "surrounded by double quotes. "
                             "Accepted since there is no ambiguity...",
                             field_token);
                 }
@@ -752,7 +727,7 @@ CPLErr swq_expr_compile( const char *where_clause,
                          swq_expr_node **expr_out )
 
 {
-    swq_field_list  field_list;
+    swq_field_list field_list;
 
     field_list.count = field_count;
     field_list.names = field_names;
@@ -767,7 +742,6 @@ CPLErr swq_expr_compile( const char *where_clause,
                               bCheck, poCustomFuncRegistrar, expr_out );
 }
 
-
 /************************************************************************/
 /*                         swq_expr_compile2()                          */
 /************************************************************************/
@@ -787,8 +761,10 @@ CPLErr swq_expr_compile2( const char *where_clause,
     context.nStartToken = SWQT_VALUE_START;
     context.bAcceptCustomFuncs = poCustomFuncRegistrar != NULL;
 
-    if( swqparse( &context ) == 0
-        && bCheck && context.poRoot->Check( field_list, FALSE, FALSE, poCustomFuncRegistrar ) != SWQ_ERROR )
+    if( swqparse( &context ) == 0 &&
+        bCheck &&
+        context.poRoot->Check( field_list, FALSE, FALSE,
+                               poCustomFuncRegistrar ) != SWQ_ERROR )
     {
         *expr_out = context.poRoot;
 
@@ -835,9 +811,11 @@ static const char* const apszSQLReservedKeywords[] = {
 
 int swq_is_reserved_keyword(const char* pszStr)
 {
-    for(int i = 0; i < (int)(sizeof(apszSQLReservedKeywords)/sizeof(char*)); i++)
+    for( int i = 0;
+         i < (int)(sizeof(apszSQLReservedKeywords) / sizeof(char*));
+         i++ )
     {
-        if (EQUAL(pszStr, apszSQLReservedKeywords[i]))
+        if( EQUAL(pszStr, apszSQLReservedKeywords[i]) )
             return TRUE;
     }
     return FALSE;
@@ -849,7 +827,7 @@ int swq_is_reserved_keyword(const char* pszStr)
 
 const char* SWQFieldTypeToString( swq_field_type field_type )
 {
-    switch(field_type)
+    switch( field_type )
     {
         case SWQ_INTEGER:   return "integer";
         case SWQ_INTEGER64: return "bigint";
diff --git a/ogr/swq.h b/ogr/swq.h
index e954865..4ba4d2f 100644
--- a/ogr/swq.h
+++ b/ogr/swq.h
@@ -21,14 +21,22 @@
 #ifndef SWQ_H_INCLUDED_
 #define SWQ_H_INCLUDED_
 
+#ifndef DOXYGEN_SKIP
+
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "ogr_core.h"
 
+#include <vector>
+#include <set>
+
 #if defined(_WIN32) && !defined(strcasecmp)
 #  define strcasecmp stricmp
 #endif
 
+// Used for swq_summary.oSetDistinctValues and oVectorDistinctValues
+#define SZ_OGR_NULL  "__OGR_NULL__"
+
 typedef enum {
     SWQ_OR,
     SWQ_AND,
@@ -84,7 +92,6 @@ typedef enum {
     SNT_OPERATION
 } swq_node_type;
 
-
 class swq_field_list;
 class swq_expr_node;
 class swq_select;
@@ -113,6 +120,7 @@ public:
     ~swq_expr_node();
 
     void           Initialize();
+    void           MarkAsTimestamp();
     CPLString      UnparseOperationFromUnparsedSubExpr(char** apszSubExpr);
     char          *Unparse( swq_field_list *, char chColumnQuote );
     void           Dump( FILE *fp, int depth );
@@ -174,7 +182,6 @@ class swq_custom_func_registrar
         virtual const swq_operation *GetOperator( const char * ) = 0;
 };
 
-
 typedef struct {
     char       *data_source;
     char       *table_name;
@@ -283,16 +290,30 @@ typedef struct {
     swq_expr_node *expr;
 } swq_col_def;
 
-typedef struct {
+class swq_summary {
+public:
+    struct Comparator
+    {
+        bool    bSortAsc;
+        swq_field_type eType;
+
+        Comparator() : bSortAsc(true), eType(SWQ_STRING) {}
+
+        bool    operator() (const CPLString&, const CPLString &) const;
+    };
+
     GIntBig     count;
 
-    char        **distinct_list; /* items of the list can be NULL */
+    std::vector<CPLString>          oVectorDistinctValues;
+    std::set<CPLString, Comparator> oSetDistinctValues;
     double      sum;
     double      min;
     double      max;
-    char        szMin[32];
-    char        szMax[32];
-} swq_summary;
+    CPLString   osMin;
+    CPLString   osMax;
+
+        swq_summary() : count(0), sum(0.0), min(0.0), max(0.0) {}
+};
 
 typedef struct {
     char *table_name;
@@ -341,7 +362,7 @@ public:
                            int distinct_flag = FALSE );
     int         result_columns;
     swq_col_def *column_defs;
-    swq_summary *column_summary;
+    std::vector<swq_summary> column_summary;
 
     int         PushTableDef( const char *pszDataSource,
                               const char *pszTableName,
@@ -359,6 +380,12 @@ public:
     int         order_specs;
     swq_order_def *order_defs;
 
+    void        SetLimit( GIntBig nLimit );
+    GIntBig     limit;
+
+    void        SetOffset( GIntBig nOffset );
+    GIntBig     offset;
+
     swq_select *poOtherSelect;
     void        PushUnionAll( swq_select* poOtherSelectIn );
 
@@ -377,7 +404,6 @@ CPLErr swq_select_parse( swq_select *select_info,
                          swq_field_list *field_list,
                          int parse_flags );
 
-const char *swq_select_finish_summarize( swq_select *select_info );
 const char *swq_select_summarize( swq_select *select_info,
                                   int dest_column,
                                   const char *value );
@@ -386,4 +412,6 @@ int swq_is_reserved_keyword(const char* pszStr);
 
 char* OGRHStoreGetValue(const char* pszHStore, const char* pszSearchedKey);
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* def SWQ_H_INCLUDED_ */
diff --git a/ogr/swq_expr_node.cpp b/ogr/swq_expr_node.cpp
index ab47891..5f9bc4c 100644
--- a/ogr/swq_expr_node.cpp
+++ b/ogr/swq_expr_node.cpp
@@ -28,11 +28,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
+#include "cpl_port.h"
+#include "swq.h"
+
+#include <cctype>
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <vector>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
-#include "swq.h"
+#include "cpl_string.h"
 #include "ogr_geometry.h"
-#include <vector>
+
+CPL_CVSID("$Id: swq_expr_node.cpp 37398 2017-02-17 10:21:00Z rouault $");
 
 /************************************************************************/
 /*                           swq_expr_node()                            */
@@ -121,7 +134,7 @@ swq_expr_node::swq_expr_node( swq_op eOp )
 
     eNodeType = SNT_OPERATION;
 
-    nOperation = (int) eOp;
+    nOperation = static_cast<int>(eOp);
     nSubExprCount = 0;
     papoSubExpr = NULL;
 }
@@ -167,6 +180,18 @@ swq_expr_node::~swq_expr_node()
 }
 
 /************************************************************************/
+/*                          MarkAsTimestamp()                           */
+/************************************************************************/
+
+void swq_expr_node::MarkAsTimestamp()
+
+{
+    CPLAssert( eNodeType == SNT_CONSTANT );
+    CPLAssert( field_type == SWQ_STRING );
+    field_type = SWQ_TIMESTAMP;
+}
+
+/************************************************************************/
 /*                         PushSubExpression()                          */
 /************************************************************************/
 
@@ -174,8 +199,8 @@ void swq_expr_node::PushSubExpression( swq_expr_node *child )
 
 {
     nSubExprCount++;
-    papoSubExpr = (swq_expr_node **)
-        CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount );
+    papoSubExpr = static_cast<swq_expr_node **>(
+        CPLRealloc( papoSubExpr, sizeof(void*) * nSubExprCount ));
 
     papoSubExpr[nSubExprCount-1] = child;
 }
@@ -189,11 +214,7 @@ void swq_expr_node::ReverseSubExpressions()
 {
     for( int i = 0; i < nSubExprCount / 2; i++ )
     {
-        swq_expr_node *temp;
-
-        temp = papoSubExpr[i];
-        papoSubExpr[i] = papoSubExpr[nSubExprCount - i - 1];
-        papoSubExpr[nSubExprCount - i - 1] = temp;
+        std::swap(papoSubExpr[i], papoSubExpr[nSubExprCount - i - 1]);
     }
 }
 
@@ -203,10 +224,11 @@ void swq_expr_node::ReverseSubExpressions()
 /*      Check argument types, etc.                                      */
 /************************************************************************/
 
-swq_field_type swq_expr_node::Check( swq_field_list *poFieldList,
-                                     int bAllowFieldsInSecondaryTables,
-                                     int bAllowMismatchTypeOnFieldComparison,
-                                     swq_custom_func_registrar* poCustomFuncRegistrar )
+swq_field_type
+swq_expr_node::Check( swq_field_list *poFieldList,
+                      int bAllowFieldsInSecondaryTables,
+                      int bAllowMismatchTypeOnFieldComparison,
+                      swq_custom_func_registrar* poCustomFuncRegistrar )
 
 {
 /* -------------------------------------------------------------------- */
@@ -241,9 +263,10 @@ swq_field_type swq_expr_node::Check( swq_field_list *poFieldList,
 
         if( !bAllowFieldsInSecondaryTables && table_index != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Cannot use field '%s' of a secondary table in this context",
-                      string_value );
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Cannot use field '%s' of a secondary table in this context",
+                string_value );
             return SWQ_ERROR;
         }
     }
@@ -298,10 +321,10 @@ swq_field_type swq_expr_node::Check( swq_field_list *poFieldList,
 void swq_expr_node::Dump( FILE * fp, int depth )
 
 {
-    char        spaces[60];
-    int         i;
+    char spaces[60] = {};
 
-    for( i = 0; i < depth*2 && i < (int) sizeof(spaces) - 1; i++ )
+    int i = 0;  // Used after for.
+    for( ; i < depth*2 && i < (int) sizeof(spaces) - 1; i++ )
         spaces[i] = ' ';
     spaces[i] = '\0';
 
@@ -348,14 +371,14 @@ void swq_expr_node::Dump( FILE * fp, int depth )
         papoSubExpr[i]->Dump( fp, depth+1 );
 }
 
-
 /************************************************************************/
 /*                       QuoteIfNecessary()                             */
 /*                                                                      */
 /*      Add quoting if necessary to unparse a string.                   */
 /************************************************************************/
 
-CPLString swq_expr_node::QuoteIfNecessary( const CPLString &osExpr, char chQuote )
+CPLString swq_expr_node::QuoteIfNecessary( const CPLString &osExpr,
+                                           char chQuote )
 
 {
     if( osExpr[0] == '_' )
@@ -363,16 +386,16 @@ CPLString swq_expr_node::QuoteIfNecessary( const CPLString &osExpr, char chQuote
     if( osExpr == "*" )
         return osExpr;
 
-    for( int i = 0; i < (int) osExpr.size(); i++ )
+    for( int i = 0; i < static_cast<int>(osExpr.size()); i++ )
     {
         char ch = osExpr[i];
-        if ((!(isalnum((int)ch) || ch == '_')) || ch == '.')
+        if( (!(isalnum(static_cast<int>(ch)) || ch == '_')) || ch == '.' )
         {
             return Quote(osExpr, chQuote);
         }
     }
 
-    if (swq_is_reserved_keyword(osExpr))
+    if( swq_is_reserved_keyword(osExpr) )
     {
         return Quote(osExpr, chQuote);
     }
@@ -393,7 +416,7 @@ CPLString swq_expr_node::Quote( const CPLString &osTarget, char chQuote )
 
     osNew += chQuote;
 
-    for( int i = 0; i < (int) osTarget.size(); i++ )
+    for( int i = 0; i < static_cast<int>(osTarget.size()); i++ )
     {
         if( osTarget[i] == chQuote )
         {
@@ -422,7 +445,7 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
 /* -------------------------------------------------------------------- */
     if( eNodeType == SNT_CONSTANT )
     {
-        if (is_null)
+        if( is_null )
             return CPLStrdup("NULL");
 
         if( field_type == SWQ_INTEGER || field_type == SWQ_INTEGER64 ||
@@ -431,10 +454,10 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
         else if( field_type == SWQ_FLOAT )
         {
             osExpr.Printf( "%.15g", float_value );
-            /* Make sure this is interpreted as a floating point value */
-            /* and not as an integer later */
-            if (strchr(osExpr, '.') == NULL && strchr(osExpr, 'e') == NULL  &&
-                strchr(osExpr, 'E') == NULL)
+            // Make sure this is interpreted as a floating point value
+            // and not as an integer later.
+            if( strchr(osExpr, '.') == NULL && strchr(osExpr, 'e') == NULL &&
+                strchr(osExpr, 'E') == NULL )
                 osExpr += '.';
         }
         else
@@ -453,18 +476,20 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
         if( field_list == NULL )
         {
             if( table_name )
-                osExpr.Printf( "%s.%s",
-                               QuoteIfNecessary(table_name, chColumnQuote).c_str(),
-                               QuoteIfNecessary(string_value, chColumnQuote).c_str() );
+                osExpr.Printf(
+                    "%s.%s",
+                    QuoteIfNecessary(table_name, chColumnQuote).c_str(),
+                    QuoteIfNecessary(string_value, chColumnQuote).c_str() );
             else
-                osExpr.Printf( "%s",
-                               QuoteIfNecessary(string_value, chColumnQuote).c_str() );
+                osExpr.Printf(
+                    "%s",
+                    QuoteIfNecessary(string_value, chColumnQuote).c_str() );
         }
         else if( field_index != -1
             && table_index < field_list->table_count
             && table_index > 0 )
         {
-            for(int i = 0; i < field_list->count; i++ )
+            for( int i = 0; i < field_list->count; i++ )
             {
                 if( field_list->table_ids[i] == table_index &&
                     field_list->ids[i] == field_index )
@@ -478,7 +503,7 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
         }
         else if( field_index != -1 )
         {
-            for(int i = 0; i < field_list->count; i++ )
+            for( int i = 0; i < field_list->count; i++ )
             {
                 if( field_list->table_ids[i] == table_index &&
                     field_list->ids[i] == field_index )
@@ -489,12 +514,13 @@ char *swq_expr_node::Unparse( swq_field_list *field_list, char chColumnQuote )
             }
         }
 
-        if( osExpr.size() == 0 )
+        if( osExpr.empty() )
         {
             return CPLStrdup(CPLSPrintf("%c%c", chColumnQuote, chColumnQuote));
         }
 
-        /* The string is just alphanum and not a reserved SQL keyword, no needs to quote and escape */
+        // The string is just alphanum and not a reserved SQL keyword,
+        // no needs to quote and escape.
         return CPLStrdup(osExpr.c_str());
     }
 
@@ -533,13 +559,13 @@ CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
 
     if( poOp == NULL && nOperation != SWQ_CUSTOM_FUNC )
     {
-        CPLAssert( FALSE );
+        CPLAssert( false );
         return osExpr;
     }
 
     switch( nOperation )
     {
-        // binary infix operators.
+      // Binary infix operators.
       case SWQ_OR:
       case SWQ_AND:
       case SWQ_EQ:
@@ -555,8 +581,8 @@ CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
       case SWQ_DIVIDE:
       case SWQ_MODULUS:
         CPLAssert( nSubExprCount >= 2 );
-        if (papoSubExpr[0]->eNodeType == SNT_COLUMN ||
-            papoSubExpr[0]->eNodeType == SNT_CONSTANT)
+        if( papoSubExpr[0]->eNodeType == SNT_COLUMN ||
+            papoSubExpr[0]->eNodeType == SNT_CONSTANT )
         {
             osExpr += apszSubExpr[0];
         }
@@ -569,8 +595,8 @@ CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
         osExpr += " ";
         osExpr += poOp->pszName;
         osExpr += " ";
-        if (papoSubExpr[1]->eNodeType == SNT_COLUMN ||
-            papoSubExpr[1]->eNodeType == SNT_CONSTANT)
+        if( papoSubExpr[1]->eNodeType == SNT_COLUMN ||
+            papoSubExpr[1]->eNodeType == SNT_CONSTANT )
         {
             osExpr += apszSubExpr[1];
         }
@@ -625,9 +651,10 @@ CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
             else if( i > 2 )
                 osExpr += ", ";
 
-            int nLen = (int)strlen(apszSubExpr[i]);
+            const int nLen = static_cast<int>(strlen(apszSubExpr[i]));
             if( (i == 1 &&
-                (apszSubExpr[i][0] == '\'' && nLen > 2 && apszSubExpr[i][nLen-1] == '\'')) ||
+                (apszSubExpr[i][0] == '\'' &&
+                 nLen > 2 && apszSubExpr[i][nLen-1] == '\'')) ||
                 (i == 2 && EQUAL(apszSubExpr[1], "'GEOMETRY")) )
             {
                 apszSubExpr[i][nLen-1] = '\0';
@@ -638,7 +665,7 @@ CPLString swq_expr_node::UnparseOperationFromUnparsedSubExpr(char** apszSubExpr)
 
             if( i == 1 && nSubExprCount > 2)
                 osExpr += "(";
-            else if (i > 1 && i == nSubExprCount - 1)
+            else if( i > 1 && i == nSubExprCount - 1 )
                 osExpr += ")";
         }
         osExpr += ")";
@@ -678,9 +705,9 @@ swq_expr_node *swq_expr_node::Clone()
     {
         poRetNode->nOperation = nOperation;
         poRetNode->nSubExprCount = nSubExprCount;
-        poRetNode->papoSubExpr = (swq_expr_node **)
-                CPLMalloc( sizeof(void*) * nSubExprCount );
-        for(int i=0;i<nSubExprCount;i++)
+        poRetNode->papoSubExpr = static_cast<swq_expr_node **>(
+                CPLMalloc( sizeof(void*) * nSubExprCount ));
+        for( int i = 0; i < nSubExprCount; i++ )
             poRetNode->papoSubExpr[i] = papoSubExpr[i]->Clone();
     }
     else if( eNodeType == SNT_COLUMN )
@@ -747,7 +774,8 @@ swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
         }
         else
         {
-            swq_expr_node* poSubExprVal = papoSubExpr[i]->Evaluate(pfnFetcher,pRecord);
+            swq_expr_node* poSubExprVal =
+                papoSubExpr[i]->Evaluate(pfnFetcher, pRecord);
             if( poSubExprVal == NULL )
                 bError = true;
             else
@@ -772,9 +800,10 @@ swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
                         "Evaluate(): Unable to find definition for operator %s.",
                         string_value );
             else
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "Evaluate(): Unable to find definition for operator %d.",
-                        nOperation );
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Evaluate(): Unable to find definition for operator %d.",
+                    nOperation );
             poRetNode = NULL;
         }
         else
@@ -784,7 +813,7 @@ swq_expr_node *swq_expr_node::Evaluate( swq_field_fetcher pfnFetcher,
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    for( int i = 0; i < (int) apoValues.size(); i++ )
+    for( int i = 0; i < static_cast<int>(apoValues.size()); i++ )
     {
         if( anValueNeedsFree[i] )
             delete apoValues[i];
@@ -804,7 +833,7 @@ void swq_expr_node::ReplaceBetweenByGEAndLERecurse()
 
     if( nOperation != SWQ_BETWEEN )
     {
-        for(int i=0;i<nSubExprCount;i++)
+        for( int i = 0; i < nSubExprCount; i++ )
             papoSubExpr[i]->ReplaceBetweenByGEAndLERecurse();
         return;
     }
@@ -825,3 +854,5 @@ void swq_expr_node::ReplaceBetweenByGEAndLERecurse()
     papoSubExpr[1]->PushSubExpression(poExpr0->Clone());
     papoSubExpr[1]->PushSubExpression(poExpr2);
 }
+
+#endif  // #ifndef DOXYGEN_SKIP
diff --git a/ogr/swq_op_general.cpp b/ogr/swq_op_general.cpp
index 5f0606b..9e3ee0e 100644
--- a/ogr/swq_op_general.cpp
+++ b/ogr/swq_op_general.cpp
@@ -29,9 +29,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_conv.h"
+#include "cpl_port.h"
 #include "swq.h"
+
+#include <cctype>
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
 #include "ogr_geometry.h"
+#include "ogr_p.h"
+
+CPL_CVSID("$Id: swq_op_general.cpp 37398 2017-02-17 10:21:00Z rouault $");
 
 /************************************************************************/
 /*                           swq_test_like()                            */
@@ -39,7 +52,8 @@
 /*      Does input match pattern?                                       */
 /************************************************************************/
 
-static int swq_test_like( const char *input, const char *pattern, char chEscape )
+static int swq_test_like( const char *input, const char *pattern,
+                          char chEscape )
 
 {
     if( input == NULL || pattern == NULL )
@@ -71,15 +85,13 @@ static int swq_test_like( const char *input, const char *pattern, char chEscape
         }
         else if( *pattern == '%' )
         {
-            int   eat;
-
             if( pattern[1] == '\0' )
                 return 1;
 
-            /* try eating varying amounts of the input till we get a positive*/
-            for( eat = 0; input[eat] != '\0'; eat++ )
+            // Try eating varying amounts of the input till we get a positive.
+            for( int eat = 0; input[eat] != '\0'; eat++ )
             {
-                if( swq_test_like(input+eat,pattern+1, chEscape) )
+                if( swq_test_like(input + eat, pattern + 1, chEscape) )
                     return 1;
             }
 
@@ -97,7 +109,7 @@ static int swq_test_like( const char *input, const char *pattern, char chEscape
         }
     }
 
-    if( *pattern != '\0' && strcmp(pattern,"%") != 0 )
+    if( *pattern != '\0' && strcmp(pattern, "%") != 0 )
         return 0;
     else
         return 1;
@@ -107,36 +119,48 @@ static int swq_test_like( const char *input, const char *pattern, char chEscape
 /*                        OGRHStoreGetValue()                           */
 /************************************************************************/
 
-static char* OGRHStoreCheckEnd(char* pszIter, int bIsKey)
+static char* OGRHStoreCheckEnd( char* pszIter, int bIsKey )
 {
-    pszIter ++;
+    pszIter++;
     for( ; *pszIter != '\0'; pszIter ++ )
     {
         if( bIsKey )
         {
             if( *pszIter == ' ' )
+            {
                 ;
+            }
             else if( *pszIter == '=' && pszIter[1] == '>' )
+            {
                 return pszIter + 2;
+            }
             else
+            {
                 return NULL;
+            }
         }
         else
         {
             if( *pszIter == ' ' )
+            {
                 ;
+            }
             else if( *pszIter == ',' )
+            {
                 return pszIter + 1;
+            }
             else
+            {
                 return NULL;
+            }
         }
     }
     return pszIter;
 }
 
-static char* OGRHStoreGetNextString(char* pszIter,
-                                    char** ppszOut,
-                                    int bIsKey)
+static char* OGRHStoreGetNextString( char* pszIter,
+                                     char** ppszOut,
+                                     int bIsKey )
 {
     char ch;
     bool bInString = false;
@@ -153,12 +177,12 @@ static char* OGRHStoreGetNextString(char* pszIter,
             }
             else if( ch == '\\')
             {
-                pszIter ++;
+                pszIter++;
                 if( (ch = *pszIter) == '\0' )
                     return NULL;
             }
             *pszOut = ch;
-            pszOut ++;
+            pszOut++;
         }
         else
         {
@@ -188,11 +212,15 @@ static char* OGRHStoreGetNextString(char* pszIter,
             }
             else if( ch == '"' )
             {
-                pszOut = *ppszOut = pszIter + 1;
+                pszOut = pszIter + 1;
+                *ppszOut = pszOut;
                 bInString = true;
             }
             else if( pszOut == NULL )
-                pszOut = *ppszOut = pszIter;
+            {
+                pszOut = pszIter;
+                *ppszOut = pszIter;
+            }
         }
     }
 
@@ -241,6 +269,26 @@ char* OGRHStoreGetValue(const char* pszHStore, const char* pszSearchedKey)
     return pszRet;
 }
 
+#ifdef DEBUG_VERBOSE
+/************************************************************************/
+/*                         OGRFormatDate()                              */
+/************************************************************************/
+
+static const char * OGRFormatDate(const OGRField *psField)
+{
+    CPLString osResult;
+
+    osResult.Printf("%04d/%02d/%02d %02d:%02d:%06.3f",
+                    psField->Date.Year,
+                    psField->Date.Month,
+                    psField->Date.Day,
+                    psField->Date.Hour,
+                    psField->Date.Minute,
+                    psField->Date.Second );
+    return CPLSPrintf(osResult);
+}
+#endif
+
 /************************************************************************/
 /*                        SWQGeneralEvaluator()                         */
 /************************************************************************/
@@ -262,10 +310,12 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
         poRet->field_type = node->field_type;
 
         if( SWQ_IS_INTEGER(sub_node_values[0]->field_type) )
-            sub_node_values[0]->float_value = (double) sub_node_values[0]->int_value;
+            sub_node_values[0]->float_value =
+                static_cast<double>(sub_node_values[0]->int_value);
         if( node->nSubExprCount > 1 &&
             SWQ_IS_INTEGER(sub_node_values[1]->field_type) )
-            sub_node_values[1]->float_value = (double)sub_node_values[1]->int_value;
+            sub_node_values[1]->float_value =
+                static_cast<double>(sub_node_values[1]->int_value);
 
         if( node->nOperation != SWQ_ISNULL )
         {
@@ -330,9 +380,8 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
 
           case SWQ_IN:
           {
-              int i;
               poRet->int_value = 0;
-              for( i = 1; i < node->nSubExprCount; i++ )
+              for( int i = 1; i < node->nSubExprCount; i++ )
               {
                   if( sub_node_values[0]->float_value
                       == sub_node_values[i]->float_value )
@@ -382,7 +431,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
           {
             GIntBig nRight = (GIntBig) sub_node_values[1]->float_value;
             poRet->field_type = SWQ_INTEGER;
-            if (nRight == 0)
+            if( nRight == 0 )
                 poRet->int_value = INT_MAX;
             else
                 poRet->int_value = ((GIntBig) sub_node_values[0]->float_value)
@@ -391,7 +440,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
           }
 
           default:
-            CPLAssert( FALSE );
+            CPLAssert( false );
             delete poRet;
             poRet = NULL;
             break;
@@ -531,7 +580,90 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
             break;
 
           default:
-            CPLAssert( FALSE );
+            CPLAssert( false );
+            delete poRet;
+            poRet = NULL;
+            break;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      datetime                                                        */
+/* -------------------------------------------------------------------- */
+    else if( sub_node_values[0]->field_type == SWQ_TIMESTAMP
+             && (node->nOperation == SWQ_EQ
+                 || node->nOperation == SWQ_GT
+                 || node->nOperation == SWQ_GE
+                 || node->nOperation == SWQ_LT
+                 || node->nOperation == SWQ_LE
+                 || node->nOperation == SWQ_BETWEEN) )
+    {
+        OGRField sField0, sField1;
+        poRet = new swq_expr_node(0);
+        poRet->field_type = node->field_type;
+
+        if( !OGRParseDate(sub_node_values[0]->string_value, &sField0, 0))
+        {
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Failed to parse date '%s' evaluating OGR WHERE expression",
+                sub_node_values[0]->string_value);
+            delete poRet;
+            return NULL;
+        }
+        if( !OGRParseDate(sub_node_values[1]->string_value, &sField1, 0))
+        {
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Failed to parse date '%s' evaluating OGR WHERE expression",
+                sub_node_values[1]->string_value);
+            delete poRet;
+            return NULL;
+        }
+
+        switch( (swq_op) node->nOperation )
+        {
+          case SWQ_GT:
+            poRet->int_value = OGRCompareDate(&sField0, &sField1) > 0;
+            break;
+
+          case SWQ_GE:
+            poRet->int_value = OGRCompareDate(&sField0, &sField1) >= 0;
+            break;
+
+          case SWQ_LT:
+            poRet->int_value = OGRCompareDate(&sField0, &sField1) < 0;
+            break;
+
+          case SWQ_LE:
+            poRet->int_value = OGRCompareDate(&sField0, &sField1) <= 0;
+            break;
+
+          case SWQ_EQ:
+            poRet->int_value = OGRCompareDate(&sField0, &sField1) == 0;
+            break;
+
+          case SWQ_BETWEEN:
+          {
+              OGRField sField2;
+              if( !OGRParseDate(sub_node_values[2]->string_value, &sField2, 0) )
+              {
+                  CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "Failed to parse date '%s' evaluating OGR WHERE expression",
+                    sub_node_values[2]->string_value);
+                  delete poRet;
+                  return NULL;
+              }
+
+              poRet->int_value =
+                  (OGRCompareDate(&sField0, &sField1) >= 0)
+                  && (OGRCompareDate(&sField0, &sField2) <= 0);
+          }
+          break;
+
+          default:
+            CPLAssert( false );
             delete poRet;
             poRet = NULL;
             break;
@@ -571,8 +703,8 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
         {
           case SWQ_EQ:
           {
-            /* When comparing timestamps, the +00 at the end might be discarded */
-            /* if the other member has no explicit timezone */
+            // When comparing timestamps, the +00 at the end might be discarded
+            // if the other member has no explicit timezone.
             if( (sub_node_values[0]->field_type == SWQ_TIMESTAMP ||
                  sub_node_values[0]->field_type == SWQ_STRING) &&
                 (sub_node_values[1]->field_type == SWQ_TIMESTAMP ||
@@ -593,7 +725,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
                       sub_node_values[1]->field_type == SWQ_STRING) &&
                      strlen(sub_node_values[0]->string_value) > 3 &&
                      strlen(sub_node_values[1]->string_value) > 3 &&
-                     (sub_node_values[0]->string_value[strlen(sub_node_values[0]->string_value)-3] == ':')  &&
+                     (sub_node_values[0]->string_value[strlen(sub_node_values[0]->string_value)-3] == ':') &&
                       strcmp(sub_node_values[1]->string_value + strlen(sub_node_values[1]->string_value)-3, "+00") == 0)
             {
                 poRet->int_value =
@@ -642,9 +774,8 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
 
           case SWQ_IN:
           {
-              int i;
               poRet->int_value = 0;
-              for( i = 1; i < node->nSubExprCount; i++ )
+              for( int i = 1; i < node->nSubExprCount; i++ )
               {
                   if( strcasecmp(sub_node_values[0]->string_value,
                                  sub_node_values[i]->string_value) == 0 )
@@ -694,34 +825,34 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
 
           case SWQ_SUBSTR:
           {
-              int nOffset, nSize;
               const char *pszSrcStr = sub_node_values[0]->string_value;
 
+              int nOffset = 0;
               if( SWQ_IS_INTEGER(sub_node_values[1]->field_type) )
-                  nOffset = (int)sub_node_values[1]->int_value;
+                  nOffset = static_cast<int>(sub_node_values[1]->int_value);
               else if( sub_node_values[1]->field_type == SWQ_FLOAT )
-                  nOffset = (int) sub_node_values[1]->float_value;
-              else
-                  nOffset = 0;
+                  nOffset = static_cast<int>(sub_node_values[1]->float_value);
+              // else
+              //     nOffset = 0;
 
+              int nSize = 0;
               if( node->nSubExprCount < 3 )
                   nSize = 100000;
               else if( SWQ_IS_INTEGER(sub_node_values[2]->field_type) )
-                  nSize = (int)sub_node_values[2]->int_value;
+                  nSize = static_cast<int>(sub_node_values[2]->int_value);
               else if( sub_node_values[2]->field_type == SWQ_FLOAT )
-                  nSize = (int) sub_node_values[2]->float_value;
-              else
-                  nSize = 0;
-
-              int nSrcStrLen = (int)strlen(pszSrcStr);
-
-
-              /* In SQL, the first character is at offset 1 */
-              /* And 0 is considered as 1 */
-              if (nOffset > 0)
-                  nOffset --;
-              /* Some implementations allow negative offsets, to start */
-              /* from the end of the string */
+                  nSize = static_cast<int>(sub_node_values[2]->float_value);
+              // else
+              //    nSize = 0;
+
+              const int nSrcStrLen = static_cast<int>(strlen(pszSrcStr));
+
+              // In SQL, the first character is at offset 1.
+              // 0 is considered as 1.
+              if( nOffset > 0 )
+                  nOffset--;
+              // Some implementations allow negative offsets, to start
+              // from the end of the string.
               else if( nOffset < 0 )
               {
                   if( nSrcStrLen + nOffset >= 0 )
@@ -739,7 +870,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
                   nSize = nSrcStrLen - nOffset;
 
               CPLString osResult = pszSrcStr + nOffset;
-              if( (int)osResult.size() > nSize )
+              if( static_cast<int>(osResult.size()) > nSize )
                   osResult.resize( nSize );
 
               poRet->string_value = CPLStrdup(osResult);
@@ -758,7 +889,7 @@ swq_expr_node *SWQGeneralEvaluator( swq_expr_node *node,
           }
 
           default:
-            CPLAssert( FALSE );
+            CPLAssert( false );
             delete poRet;
             poRet = NULL;
             break;
@@ -879,7 +1010,7 @@ static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
     {
         swq_expr_node *poSubNode = poNode->papoSubExpr[i];
 
-        /* identify the mixture of the argument type */
+        // Identify the mixture of the argument type.
         if( (eArgType == SWQ_STRING
             && (SWQ_IS_INTEGER(poSubNode->field_type)
                || poSubNode->field_type == SWQ_FLOAT)) ||
@@ -900,18 +1031,20 @@ static void SWQAutoConvertStringToNumeric( swq_expr_node *poNode )
         {
             if( poSubNode->eNodeType == SNT_CONSTANT )
             {
-                /* apply the string to numeric conversion */
+                // Apply the string to numeric conversion.
                 char* endPtr = NULL;
-                poSubNode->float_value = CPLStrtod(poSubNode->string_value, &endPtr);
-                if ( !(endPtr == NULL || *endPtr == '\0') )
+                poSubNode->float_value =
+                    CPLStrtod(poSubNode->string_value, &endPtr);
+                if( !(endPtr == NULL || *endPtr == '\0') )
                 {
                     CPLError(CE_Warning, CPLE_NotSupported,
-                             "Conversion failed when converting the string value '%s' to data type float.",
+                             "Conversion failed when converting the string "
+                             "value '%s' to data type float.",
                              poSubNode->string_value);
                     continue;
                 }
 
-                /* we should also fill the integer value in this case */
+                // Should also fill the integer value in this case.
                 poSubNode->int_value = (GIntBig)poSubNode->float_value;
                 poSubNode->field_type = SWQ_FLOAT;
             }
@@ -946,7 +1079,7 @@ static bool SWQCheckSubExprAreNotGeometries( swq_expr_node *poNode )
 /************************************************************************/
 
 swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
-                                  int bAllowMismatchTypeOnFieldComparison  )
+                                  int bAllowMismatchTypeOnFieldComparison )
 
 {
     swq_field_type eRetType = SWQ_ERROR;
@@ -1003,13 +1136,25 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
             return SWQ_ERROR;
         SWQAutoPromoteIntegerToInteger64OrFloat( poNode );
         if( poNode->papoSubExpr[0]->field_type == SWQ_STRING )
-            eRetType = eArgType = SWQ_STRING;
+        {
+            eRetType = SWQ_STRING;
+            eArgType = SWQ_STRING;
+        }
         else if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
-            eRetType = eArgType = SWQ_FLOAT;
+        {
+            eRetType = SWQ_FLOAT;
+            eArgType = SWQ_FLOAT;
+        }
         else if( poNode->papoSubExpr[0]->field_type == SWQ_INTEGER64 )
-            eRetType = eArgType = SWQ_INTEGER64;
+        {
+            eRetType = SWQ_INTEGER64;
+            eArgType = SWQ_INTEGER64;
+        }
         else
-            eRetType = eArgType = SWQ_INTEGER;
+        {
+            eRetType = SWQ_INTEGER;
+            eArgType = SWQ_INTEGER;
+        }
         break;
 
       case SWQ_SUBTRACT:
@@ -1019,11 +1164,20 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
             return SWQ_ERROR;
         SWQAutoPromoteIntegerToInteger64OrFloat( poNode );
         if( poNode->papoSubExpr[0]->field_type == SWQ_FLOAT )
-            eRetType = eArgType = SWQ_FLOAT;
+        {
+            eRetType = SWQ_FLOAT;
+            eArgType = SWQ_FLOAT;
+        }
         else if( poNode->papoSubExpr[0]->field_type == SWQ_INTEGER64 )
-            eRetType = eArgType = SWQ_INTEGER64;
+        {
+            eRetType = SWQ_INTEGER64;
+            eArgType = SWQ_INTEGER64;
+        }
         else
-            eRetType = eArgType = SWQ_INTEGER;
+        {
+            eRetType = SWQ_INTEGER;
+            eArgType = SWQ_INTEGER;
+        }
         break;
 
       case SWQ_CONCAT:
@@ -1049,8 +1203,9 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
             || (poNode->nSubExprCount > 2
                 && poNode->papoSubExpr[2]->field_type != SWQ_INTEGER) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Wrong argument type for SUBSTR(), expected SUBSTR(string,int,int) or SUBSTR(string,int)." );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Wrong argument type for SUBSTR(), "
+                     "expected SUBSTR(string,int,int) or SUBSTR(string,int).");
             return SWQ_ERROR;
         }
         break;
@@ -1070,7 +1225,8 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
             || poNode->papoSubExpr[1]->field_type != SWQ_STRING )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Wrong argument type for hstore_get_value(), expected hstore_get_value(string,string)." );
+                      "Wrong argument type for hstore_get_value(), "
+                      "expected hstore_get_value(string,string)." );
             return SWQ_ERROR;
         }
         break;
@@ -1097,13 +1253,13 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
         for( int i = 0; i < poNode->nSubExprCount; i++ )
         {
             swq_field_type eThisArgType = poNode->papoSubExpr[i]->field_type;
-            if( SWQ_IS_INTEGER(eThisArgType) ||  eThisArgType == SWQ_BOOLEAN )
+            if( SWQ_IS_INTEGER(eThisArgType) || eThisArgType == SWQ_BOOLEAN )
                 eThisArgType = SWQ_FLOAT;
 
             if( eArgType != eThisArgType )
             {
                 // Convenience for join. We allow comparing numeric columns
-                // and string columns, by casting string columns to numeric
+                // and string columns, by casting string columns to numeric.
                 if( bAllowMismatchTypeOnFieldComparison &&
                     poNode->nSubExprCount == 2 &&
                     poNode->nOperation == SWQ_EQ &&
@@ -1137,7 +1293,8 @@ swq_field_type SWQGeneralChecker( swq_expr_node *poNode,
                     swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
 
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "Type mismatch or improper type of arguments to %s operator.",
+                          "Type mismatch or improper type of arguments "
+                          "to %s operator.",
                           poOp->pszName );
                 return SWQ_ERROR;
             }
@@ -1193,12 +1350,15 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
                     break;
 
                 case SWQ_INTEGER64:
-                    // TODO: warn in case of overflow ?
-                    poRetNode->int_value = (int) poSrcNode->int_value;
+                    // TODO: Warn in case of overflow?
+                    poRetNode->int_value =
+                      static_cast<int>(poSrcNode->int_value);
                     break;
 
                 case SWQ_FLOAT:
-                    poRetNode->int_value = (int) poSrcNode->float_value;
+                    // TODO: Warn in case of overflow?
+                    poRetNode->int_value =
+                        static_cast<int>(poSrcNode->float_value);
                     break;
 
                 default:
@@ -1223,11 +1383,13 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
                     break;
 
                 case SWQ_FLOAT:
-                    poRetNode->int_value = (GIntBig) poSrcNode->float_value;
+                    poRetNode->int_value =
+                        static_cast<GIntBig>(poSrcNode->float_value);
                     break;
 
                 default:
-                    poRetNode->int_value = CPLAtoGIntBig(poSrcNode->string_value);
+                    poRetNode->int_value =
+                        CPLAtoGIntBig(poSrcNode->string_value);
                     break;
             }
         }
@@ -1243,7 +1405,8 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
                 case SWQ_INTEGER:
                 case SWQ_INTEGER64:
                 case SWQ_BOOLEAN:
-                    poRetNode->float_value = (double) poSrcNode->int_value;
+                    poRetNode->float_value =
+                        static_cast<double>(poSrcNode->int_value);
                     break;
 
                 case SWQ_FLOAT:
@@ -1289,7 +1452,7 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
             break;
         }
 
-        // everything else is a string.
+        // Everything else is a string.
         default:
         {
             CPLString osRet;
@@ -1310,7 +1473,7 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
                 {
                     if( poSrcNode->geometry_value != NULL )
                     {
-                        char* pszWKT;
+                        char* pszWKT = NULL;
                         poSrcNode->geometry_value->exportToWkt(&pszWKT);
                         osRet = pszWKT;
                         CPLFree(pszWKT);
@@ -1327,10 +1490,8 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
 
             if( node->nSubExprCount > 2 )
             {
-                int nWidth;
-
-                nWidth = (int) sub_node_values[2]->int_value;
-                if( nWidth > 0 && (int) strlen(osRet) > nWidth )
+                int nWidth = static_cast<int>(sub_node_values[2]->int_value);
+                if( nWidth > 0 && static_cast<int>(osRet.size()) > nWidth )
                     osRet.resize(nWidth);
             }
 
@@ -1347,30 +1508,35 @@ swq_expr_node *SWQCastEvaluator( swq_expr_node *node,
 /************************************************************************/
 
 swq_field_type SWQCastChecker( swq_expr_node *poNode,
-                               CPL_UNUSED int bAllowMismatchTypeOnFieldComparison )
+                               int /* bAllowMismatchTypeOnFieldComparison */ )
 
 {
     swq_field_type eType = SWQ_ERROR;
     const char *pszTypeName = poNode->papoSubExpr[1]->string_value;
 
     if( poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY &&
-        !(EQUAL(pszTypeName,"character") ||
-          EQUAL(pszTypeName,"geometry")) )
+        !(EQUAL(pszTypeName, "character") ||
+          EQUAL(pszTypeName, "geometry")) )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "Cannot cast geometry to %s",
                   pszTypeName );
     }
-
-    else if( EQUAL(pszTypeName,"boolean") )
+    else if( EQUAL(pszTypeName, "boolean") )
+    {
         eType = SWQ_BOOLEAN;
-    else if( EQUAL(pszTypeName,"character") )
+    }
+    else if( EQUAL(pszTypeName, "character") )
+    {
         eType = SWQ_STRING;
-    else if( EQUAL(pszTypeName,"integer") )
+    }
+    else if( EQUAL(pszTypeName, "integer") )
+    {
         eType = SWQ_INTEGER;
-    else if( EQUAL(pszTypeName,"bigint") )
+    }
+    else if( EQUAL(pszTypeName, "bigint") )
     {
-        // Handle CAST(fid AS bigint) by changing the field_type of fid to Integer64
-        // A bit of a hack
+        // Handle CAST(fid AS bigint) by changing the field_type of fid to
+        // Integer64.  A bit of a hack.
         if( poNode->papoSubExpr[0]->eNodeType == SNT_COLUMN &&
             poNode->papoSubExpr[0]->field_type == SWQ_INTEGER &&
             strcmp(poNode->papoSubExpr[0]->string_value, "fid") == 0 )
@@ -1379,25 +1545,37 @@ swq_field_type SWQCastChecker( swq_expr_node *poNode,
         }
         eType = SWQ_INTEGER64;
     }
-    else if( EQUAL(pszTypeName,"smallint") )
+    else if( EQUAL(pszTypeName, "smallint") )
+    {
         eType = SWQ_INTEGER;
-    else if( EQUAL(pszTypeName,"float") )
+    }
+    else if( EQUAL(pszTypeName, "float") )
+    {
         eType = SWQ_FLOAT;
-    else if( EQUAL(pszTypeName,"numeric") )
+    }
+    else if( EQUAL(pszTypeName, "numeric") )
+    {
         eType = SWQ_FLOAT;
-    else if( EQUAL(pszTypeName,"timestamp") )
+    }
+    else if( EQUAL(pszTypeName, "timestamp") )
+    {
         eType = SWQ_TIMESTAMP;
-    else if( EQUAL(pszTypeName,"date") )
+    }
+    else if( EQUAL(pszTypeName, "date") )
+    {
         eType = SWQ_DATE;
-    else if( EQUAL(pszTypeName,"time") )
+    }
+    else if( EQUAL(pszTypeName, "time") )
+    {
         eType = SWQ_TIME;
-    else if( EQUAL(pszTypeName,"geometry") )
+    }
+    else if( EQUAL(pszTypeName, "geometry") )
     {
         if( !(poNode->papoSubExpr[0]->field_type == SWQ_GEOMETRY ||
               poNode->papoSubExpr[0]->field_type == SWQ_STRING) )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "Cannot cast %s to geometry",
-                      SWQFieldTypeToString(poNode->papoSubExpr[0]->field_type) );
+            CPLError(CE_Failure, CPLE_AppDefined, "Cannot cast %s to geometry",
+                     SWQFieldTypeToString(poNode->papoSubExpr[0]->field_type));
         }
         else
             eType = SWQ_GEOMETRY;
@@ -1405,8 +1583,8 @@ swq_field_type SWQCastChecker( swq_expr_node *poNode,
     else
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                    "Unrecognized typename %s in CAST operator.",
-                    pszTypeName );
+                  "Unrecognized typename %s in CAST operator.",
+                  pszTypeName );
     }
 
     poNode->field_type = eType;
diff --git a/ogr/swq_op_registrar.cpp b/ogr/swq_op_registrar.cpp
index 57c57b0..983c338 100644
--- a/ogr/swq_op_registrar.cpp
+++ b/ogr/swq_op_registrar.cpp
@@ -28,11 +28,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_conv.h"
+#include "cpl_port.h"
 #include "swq.h"
 
-static swq_field_type SWQColumnFuncChecker( swq_expr_node *poNode,
-                                            int bAllowMismatchTypeOnFieldComparison );
+#include <cstddef>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+
+CPL_CVSID("$Id: swq_op_registrar.cpp 36323 2016-11-20 02:18:05Z goatbar $");
+
+//! @cond Doxygen_Suppress
+static swq_field_type SWQColumnFuncChecker(
+    swq_expr_node *poNode, int bAllowMismatchTypeOnFieldComparison );
 
 static const swq_operation swq_apsOperations[] =
 {
@@ -56,7 +64,8 @@ static const swq_operation swq_apsOperations[] =
     { "%", SWQ_MODULUS , SWQGeneralEvaluator, SWQGeneralChecker },
     { "CONCAT", SWQ_CONCAT , SWQGeneralEvaluator, SWQGeneralChecker },
     { "SUBSTR", SWQ_SUBSTR , SWQGeneralEvaluator, SWQGeneralChecker },
-    { "HSTORE_GET_VALUE", SWQ_HSTORE_GET_VALUE , SWQGeneralEvaluator, SWQGeneralChecker },
+    { "HSTORE_GET_VALUE", SWQ_HSTORE_GET_VALUE , SWQGeneralEvaluator,
+        SWQGeneralChecker },
 
     { "AVG", SWQ_AVG, SWQGeneralEvaluator, SWQColumnFuncChecker },
     { "MIN", SWQ_MIN, SWQGeneralEvaluator, SWQColumnFuncChecker },
@@ -76,10 +85,9 @@ static const swq_operation swq_apsOperations[] =
 const swq_operation *swq_op_registrar::GetOperator( const char *pszName )
 
 {
-    unsigned int i;
-    for( i = 0; i < N_OPERATIONS; i++ )
+    for( unsigned int i = 0; i < N_OPERATIONS; ++i )
     {
-        if( EQUAL(pszName,swq_apsOperations[i].pszName) )
+        if( EQUAL(pszName, swq_apsOperations[i].pszName) )
             return &(swq_apsOperations[i]);
     }
 
@@ -93,9 +101,7 @@ const swq_operation *swq_op_registrar::GetOperator( const char *pszName )
 const swq_operation *swq_op_registrar::GetOperator( swq_op eOperator )
 
 {
-    unsigned int i;
-
-    for( i = 0; i < N_OPERATIONS; i++ )
+    for( unsigned int i = 0; i < N_OPERATIONS; ++i )
     {
         if( eOperator == swq_apsOperations[i].eOperation )
             return &(swq_apsOperations[i]);
@@ -113,13 +119,14 @@ const swq_operation *swq_op_registrar::GetOperator( swq_op eOperator )
 /*      error if they are used in any other context.                    */
 /************************************************************************/
 
-static swq_field_type SWQColumnFuncChecker( swq_expr_node *poNode,
-                                            CPL_UNUSED int bAllowMismatchTypeOnFieldComparison )
+static swq_field_type SWQColumnFuncChecker(
+    swq_expr_node *poNode, int /* bAllowMismatchTypeOnFieldComparison */ )
 {
     const swq_operation *poOp =
-            swq_op_registrar::GetOperator((swq_op)poNode->nOperation);
+        swq_op_registrar::GetOperator(static_cast<swq_op>(poNode->nOperation));
     CPLError( CE_Failure, CPLE_AppDefined,
               "Column Summary Function '%s' found in an inappropriate context.",
-              (poOp) ? poOp->pszName : "" );
+              poOp != NULL ? poOp->pszName : "" );
     return SWQ_ERROR;
 }
+//! @endcond
diff --git a/ogr/swq_parser.cpp b/ogr/swq_parser.cpp
index bd100d1..74ebd9b 100644
--- a/ogr/swq_parser.cpp
+++ b/ogr/swq_parser.cpp
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison implementation for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "3.0"
+#define YYBISON_VERSION "3.0.4"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -99,14 +99,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "swq.h"
+
+#include <cstdlib>
+#include <cstring>
 
 #include "cpl_conv.h"
-#include "cpl_port.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
-#include "swq.h"
 
-#define YYSTYPE  swq_expr_node*
+CPL_CVSID("$Id: swq_parser.cpp 37361 2017-02-12 20:49:47Z rouault $");
+
+#define YYSTYPE swq_expr_node *
 
 /* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */
 /* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */
@@ -115,14 +122,13 @@
 /* it appears to be a non documented feature of Bison */
 #define YYSTYPE_IS_TRIVIAL 1
 
+#line 126 "swq_parser.cpp" /* yacc.c:339  */
 
-#line 119 "swq_parser.cpp" /* yacc.c:339  */
-
-# ifndef YY_NULL
+# ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULL nullptr
+#   define YY_NULLPTR nullptr
 #  else
-#   define YY_NULL 0
+#   define YY_NULLPTR 0
 #  endif
 # endif
 
@@ -177,13 +183,15 @@ extern int swqdebug;
     SWQT_CAST = 280,
     SWQT_UNION = 281,
     SWQT_ALL = 282,
-    SWQT_VALUE_START = 283,
-    SWQT_SELECT_START = 284,
-    SWQT_NOT = 285,
-    SWQT_OR = 286,
-    SWQT_AND = 287,
-    SWQT_UMINUS = 288,
-    SWQT_RESERVED_KEYWORD = 289
+    SWQT_LIMIT = 283,
+    SWQT_OFFSET = 284,
+    SWQT_VALUE_START = 285,
+    SWQT_SELECT_START = 286,
+    SWQT_NOT = 287,
+    SWQT_OR = 288,
+    SWQT_AND = 289,
+    SWQT_UMINUS = 290,
+    SWQT_RESERVED_KEYWORD = 291
   };
 #endif
 
@@ -202,7 +210,7 @@ int swqparse (swq_parse_context *context);
 
 /* Copy the second part of user declarations.  */
 
-#line 205 "swq_parser.cpp" /* yacc.c:358  */
+#line 214 "swq_parser.cpp" /* yacc.c:358  */
 
 #ifdef short
 # undef short
@@ -259,11 +267,30 @@ typedef short int yytype_int16;
 # endif
 #endif
 
-#ifndef __attribute__
-/* This feature is available in gcc versions 2.5 and later.  */
-# if (! defined __GNUC__ || __GNUC__ < 2 \
-      || (__GNUC__ == 2 && __GNUC_MINOR__ < 5))
-#  define __attribute__(Spec) /* empty */
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
 # endif
 #endif
 
@@ -425,21 +452,21 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  20
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   416
+#define YYLAST   400
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  48
+#define YYNTOKENS  50
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  20
+#define YYNNTS  22
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  87
+#define YYNRULES  91
 /* YYNSTATES -- Number of states.  */
-#define YYNSTATES  185
+#define YYNSTATES  193
 
 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
    by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   289
+#define YYMAXUTOK   291
 
 #define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -451,10 +478,10 @@ static const yytype_uint8 yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    36,     2,     2,     2,    41,     2,     2,
-      44,    45,    39,    37,    46,    38,    47,    40,     2,     2,
+       2,     2,     2,    38,     2,     2,     2,    43,     2,     2,
+      46,    47,    41,    39,    48,    40,    49,    42,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      34,    33,    35,     2,     2,     2,     2,     2,     2,     2,
+      36,    35,    37,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -476,22 +503,24 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    42,    43
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      44,    45
 };
 
 #if YYDEBUG
   /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   112,   112,   113,   118,   124,   129,   137,   145,   152,
-     160,   168,   176,   184,   192,   200,   208,   216,   224,   232,
-     245,   254,   268,   277,   292,   301,   315,   322,   336,   342,
-     349,   356,   368,   373,   378,   382,   387,   392,   397,   413,
-     420,   427,   434,   441,   448,   484,   492,   498,   505,   514,
-     532,   552,   553,   556,   561,   567,   568,   570,   578,   579,
-     582,   591,   602,   616,   638,   668,   702,   726,   755,   761,
-     764,   765,   770,   771,   777,   784,   785,   788,   789,   792,
-     798,   804,   812,   822,   833,   844,   857,   868
+       0,   121,   121,   122,   127,   133,   138,   146,   154,   161,
+     169,   177,   185,   193,   201,   209,   217,   225,   233,   241,
+     253,   262,   275,   284,   297,   306,   319,   326,   338,   344,
+     351,   359,   372,   377,   382,   386,   391,   396,   401,   417,
+     424,   431,   438,   445,   452,   488,   496,   502,   509,   518,
+     536,   556,   557,   560,   565,   571,   572,   574,   582,   583,
+     586,   595,   606,   621,   642,   673,   708,   733,   762,   768,
+     770,   771,   776,   777,   783,   790,   791,   794,   795,   798,
+     804,   810,   817,   818,   825,   826,   834,   844,   855,   866,
+     879,   890
 };
 #endif
 
@@ -505,15 +534,15 @@ static const char *const yytname[] =
   "\"LIKE\"", "\"ESCAPE\"", "\"BETWEEN\"", "\"NULL\"", "\"IS\"",
   "\"SELECT\"", "\"LEFT\"", "\"JOIN\"", "\"WHERE\"", "\"ON\"", "\"ORDER\"",
   "\"BY\"", "\"FROM\"", "\"AS\"", "\"ASC\"", "\"DESC\"", "\"DISTINCT\"",
-  "\"CAST\"", "\"UNION\"", "\"ALL\"", "SWQT_VALUE_START",
-  "SWQT_SELECT_START", "\"NOT\"", "\"OR\"", "\"AND\"", "'='", "'<'", "'>'",
-  "'!'", "'+'", "'-'", "'*'", "'/'", "'%'", "SWQT_UMINUS",
-  "\"reserved keyword\"", "'('", "')'", "','", "'.'", "$accept", "input",
-  "value_expr", "value_expr_list", "field_value", "value_expr_non_logical",
-  "type_def", "select_statement", "select_core", "opt_union_all",
-  "union_all", "select_field_list", "column_spec", "as_clause",
-  "opt_where", "opt_joins", "opt_order_by", "sort_spec_list", "sort_spec",
-  "table_def", YY_NULL
+  "\"CAST\"", "\"UNION\"", "\"ALL\"", "\"LIMIT\"", "\"OFFSET\"",
+  "SWQT_VALUE_START", "SWQT_SELECT_START", "\"NOT\"", "\"OR\"", "\"AND\"",
+  "'='", "'<'", "'>'", "'!'", "'+'", "'-'", "'*'", "'/'", "'%'",
+  "SWQT_UMINUS", "\"reserved keyword\"", "'('", "')'", "','", "'.'",
+  "$accept", "input", "value_expr", "value_expr_list", "field_value",
+  "value_expr_non_logical", "type_def", "select_statement", "select_core",
+  "opt_union_all", "union_all", "select_field_list", "column_spec",
+  "as_clause", "opt_where", "opt_joins", "opt_order_by", "sort_spec_list",
+  "sort_spec", "opt_limit", "opt_offset", "table_def", YY_NULLPTR
 };
 #endif
 
@@ -525,15 +554,15 @@ static const yytype_uint16 yytoknum[] =
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,    61,    60,    62,    33,    43,    45,    42,
-      47,    37,   288,   289,    40,    41,    44,    46
+     285,   286,   287,   288,   289,    61,    60,    62,    33,    43,
+      45,    42,    47,    37,   290,   291,    40,    41,    44,    46
 };
 # endif
 
-#define YYPACT_NINF -119
+#define YYPACT_NINF -126
 
 #define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-119)))
+  (!!((Yystate) == (-126)))
 
 #define YYTABLE_NINF -1
 
@@ -544,25 +573,26 @@ static const yytype_uint16 yytoknum[] =
      STATE-NUM.  */
 static const yytype_int16 yypact[] =
 {
-      -9,   204,    -6,    10,  -119,  -119,  -119,   -30,  -119,   -32,
-     204,   240,   204,   342,  -119,   356,    54,    12,  -119,     4,
-    -119,   204,    35,   204,   380,  -119,   263,    18,   204,   240,
-      50,    87,   204,   204,    97,   112,   158,    33,   240,   240,
-     240,   240,   240,   -23,   194,  -119,   297,    36,    28,    31,
-      56,  -119,    -6,   256,    42,  -119,   335,  -119,   204,    82,
-      72,  -119,    70,    55,   204,   240,   247,   350,   204,   204,
-    -119,   204,   204,  -119,   204,  -119,   204,    80,    80,  -119,
-    -119,  -119,   148,     0,    94,  -119,   118,  -119,    47,   194,
-       4,  -119,  -119,   204,  -119,   120,    85,   204,   240,  -119,
-     204,   124,   284,  -119,  -119,  -119,  -119,  -119,  -119,   130,
-      95,  -119,    47,  -119,    96,    -5,    75,  -119,  -119,  -119,
-     100,   101,  -119,  -119,   356,   103,   204,   240,   108,   115,
-       2,    75,   151,   159,  -119,   153,    47,   150,    23,  -119,
-    -119,  -119,   356,     2,  -119,   150,     2,     2,    47,   154,
-     204,   152,    61,    83,  -119,   152,  -119,  -119,   157,   204,
-     342,   156,  -119,  -119,   173,  -119,   174,  -119,   204,   305,
-     130,   134,   135,   305,  -119,   116,  -119,   136,  -119,  -119,
-    -119,  -119,  -119,   130,  -119
+      10,   181,    -9,    12,  -126,  -126,  -126,   -29,  -126,   -27,
+     181,   204,   181,   314,  -126,   183,    53,     8,  -126,    28,
+    -126,   181,    59,   181,   352,  -126,   230,    30,   181,   204,
+      -8,     6,   181,   181,    86,   104,   158,    63,   204,   204,
+     204,   204,   204,    20,   171,  -126,   266,    94,    58,    69,
+      92,  -126,    -9,   223,    70,  -126,   299,  -126,   181,   111,
+      61,  -126,   110,    78,   181,   204,   331,   346,   181,   181,
+    -126,   181,   181,  -126,   181,  -126,   181,   -13,   -13,  -126,
+    -126,  -126,   148,     1,   107,  -126,   122,  -126,    55,   171,
+      28,  -126,  -126,   181,  -126,   124,    84,   181,   204,  -126,
+     181,   126,   357,  -126,  -126,  -126,  -126,  -126,  -126,   127,
+      91,  -126,    55,  -126,    88,     4,    65,  -126,  -126,  -126,
+      96,    93,  -126,  -126,   183,    98,   181,   204,    97,   100,
+       2,    65,   137,   142,  -126,   140,    55,   141,    49,  -126,
+    -126,  -126,   183,     2,  -126,   141,     2,     2,    55,   143,
+     181,   138,    36,    39,  -126,   138,  -126,  -126,   149,   181,
+     314,   146,   150,  -126,   165,  -126,   167,   150,   181,   281,
+     127,   168,   152,   132,   144,   152,   281,  -126,    90,  -126,
+     147,  -126,   194,  -126,  -126,  -126,  -126,  -126,  -126,  -126,
+     127,  -126,  -126
 };
 
   /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -581,28 +611,31 @@ static const yytype_uint8 yydefact[] =
       42,    43,     0,     0,     0,    69,     0,    61,     0,     0,
       55,    57,    56,     0,    44,     0,     0,     0,     0,    27,
        0,    19,     0,    15,    16,    14,    10,    17,    11,     0,
-       0,    63,     0,    68,     0,    82,    72,    59,    52,    28,
+       0,    63,     0,    68,     0,    86,    72,    59,    52,    28,
       46,     0,    22,    20,    24,     0,     0,     0,    30,     0,
-      64,    72,     0,     0,    83,     0,     0,    70,     0,    45,
-      23,    21,    25,    66,    65,    70,    84,    86,     0,     0,
-       0,    75,     0,     0,    67,    75,    85,    87,     0,     0,
-      71,     0,    53,    47,     0,    49,     0,    54,     0,    72,
-       0,     0,     0,    72,    73,    79,    76,    78,    48,    50,
-      74,    80,    81,     0,    77
+      64,    72,     0,     0,    87,     0,     0,    70,     0,    45,
+      23,    21,    25,    66,    65,    70,    88,    90,     0,     0,
+       0,    75,     0,     0,    67,    75,    89,    91,     0,     0,
+      71,     0,    82,    47,     0,    49,     0,    82,     0,    72,
+       0,     0,    84,     0,     0,    84,    72,    73,    79,    76,
+      78,    83,     0,    53,    48,    50,    54,    74,    80,    81,
+       0,    85,    77
 };
 
   /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -119,  -119,    -1,   -56,  -106,     7,  -119,   129,   167,    99,
-    -119,   -39,  -119,   -61,    40,  -118,    38,    11,  -119,  -108
+    -126,  -126,    -1,   -19,  -108,     7,  -126,   153,   182,   112,
+    -126,   -39,  -126,   139,    56,  -125,    45,    24,  -126,    51,
+      41,  -110
 };
 
   /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
       -1,     3,    53,    54,    14,    15,   121,    18,    19,    51,
-      52,    47,    48,    87,   151,   137,   162,   176,   177,   116
+      52,    47,    48,    87,   151,   137,   162,   179,   180,   172,
+     183,   116
 };
 
   /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
@@ -610,133 +643,133 @@ static const yytype_int16 yydefgoto[] =
      number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_uint8 yytable[] =
 {
-      13,    85,    96,   129,   131,    84,    55,    16,    85,    24,
-      20,    26,    23,   145,    21,    46,    86,    22,    25,     1,
-       2,    82,    56,    86,    83,    16,   152,    59,   149,   153,
-      50,    66,    67,    70,    73,    75,    60,   119,    17,   111,
-     158,    55,   133,    46,   125,    77,    78,    79,    80,    81,
-     117,   174,   114,   115,   134,   180,    88,     4,     5,     6,
-      43,    61,    58,   101,   175,     8,    76,   103,   104,   144,
-     105,   106,   102,   107,    89,   108,    90,   175,    44,     9,
-      62,    99,   154,    91,    10,   156,   157,    94,    46,   135,
-     136,    97,    11,    45,    63,    64,   123,    65,    12,   100,
-       4,     5,     6,     7,    98,   124,   163,   164,     8,    38,
-      39,    40,    41,    42,   112,     4,     5,     6,     7,    40,
-      41,    42,     9,     8,   113,   141,   120,    10,   165,   166,
-     122,    68,    69,   126,   142,    11,   128,     9,   181,   182,
-     130,    12,    10,   132,   138,    71,   139,    72,   140,   160,
-      11,     4,     5,     6,     7,    22,    12,   146,   169,     8,
-     143,     4,     5,     6,     7,   147,   150,   173,   148,     8,
-     161,   159,   109,     9,   168,   170,   171,   172,    10,   178,
-     179,    92,   183,     9,    49,   155,    11,   110,    10,   118,
-       0,    74,    12,   167,   184,     0,    11,     4,     5,     6,
-      43,     0,    12,     0,     0,     8,     0,     4,     5,     6,
-       7,     0,     0,     0,     0,     8,     0,     0,     0,     9,
-       0,     0,     0,     0,    10,     0,     0,     0,     0,     9,
-       0,     0,    11,    45,    10,     0,     0,     0,    12,     0,
-       0,     0,    11,     4,     5,     6,     7,     0,    12,     0,
-       0,     8,     0,     0,    27,    28,     0,    29,     0,    30,
-       0,     0,     0,    27,    28,     9,    29,     0,    30,     0,
-      27,    28,     0,    29,     0,    30,     0,    31,    11,    33,
-      34,    35,    36,    37,    12,     0,    31,    32,    33,    34,
-      35,    36,    37,    31,    32,    33,    34,    35,    36,    37,
-       0,     0,    93,    85,    27,    28,     0,    29,    57,    30,
-       0,     0,    27,    28,     0,    29,   127,    30,    86,   135,
-     136,    38,    39,    40,    41,    42,     0,    31,    32,    33,
-      34,    35,    36,    37,     0,    31,    32,    33,    34,    35,
-      36,    37,    27,    28,     0,    29,     0,    30,     0,    27,
-      28,     0,    29,     0,    30,     0,    95,    27,    28,     0,
-      29,     0,    30,     0,     0,    31,    32,    33,    34,    35,
-      36,    37,    31,    32,    33,    34,    35,    36,    37,     0,
-      31,     0,     0,    34,    35,    36,    37,    27,    28,     0,
-      29,     0,    30,    38,    39,    40,    41,    42,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    34,    35,    36,    37
+      13,   129,   131,    61,    16,    84,   145,    55,    85,    24,
+      85,    26,    20,    63,    64,    46,    65,    21,    25,    23,
+      22,    16,    56,    86,    62,    86,   149,    59,    40,    41,
+      42,    66,    67,    70,    73,    75,    60,    17,   158,    96,
+       1,     2,   111,    46,   177,    77,    78,    79,    80,    81,
+     117,   187,   152,   133,    50,   153,     4,     5,     6,    43,
+     114,   115,   178,   101,     8,    55,    82,   103,   104,    83,
+     105,   106,   102,   107,   119,   108,    58,    44,     9,   135,
+     136,   125,   178,   163,   164,    10,   165,   166,    46,     4,
+       5,     6,     7,    11,    45,    98,   123,     8,    76,    12,
+      38,    39,    40,    41,    42,   124,    89,     4,     5,     6,
+       7,     9,   188,   189,    88,     8,    90,    94,    10,    91,
+      97,    99,    68,    69,   100,   141,    11,   112,   113,     9,
+     120,   122,    12,   128,   142,   126,    10,   132,   130,    71,
+     139,    72,   138,   146,    11,   140,    22,   143,   147,   160,
+      12,     4,     5,     6,     7,   148,   161,   150,   169,     8,
+     159,     4,     5,     6,     7,   170,   168,   176,   173,     8,
+     174,   181,   109,     9,     4,     5,     6,    43,   171,   184,
+      10,   182,     8,     9,     4,     5,     6,     7,    11,   110,
+      10,   185,     8,    74,    12,   190,     9,   191,    11,    49,
+     167,   155,   118,    10,    12,    92,     9,     4,     5,     6,
+       7,    11,    45,    10,   192,     8,   186,    12,   175,     0,
+       0,    11,    38,    39,    40,    41,    42,    12,     0,     9,
+      27,    28,     0,    29,     0,    30,     0,    27,    28,     0,
+      29,     0,    30,     0,    11,     0,     0,     0,     0,     0,
+      12,     0,     0,     0,   134,    31,    32,    33,    34,    35,
+      36,    37,    31,    32,    33,    34,    35,    36,    37,   144,
+       0,    93,    85,    27,    28,     0,    29,    57,    30,     0,
+       0,     0,   154,     0,     0,   156,   157,    86,    27,    28,
+       0,    29,     0,    30,     0,   135,   136,     0,    31,    32,
+      33,    34,    35,    36,    37,     0,    27,    28,     0,    29,
+       0,    30,     0,    31,    32,    33,    34,    35,    36,    37,
+      95,    27,    28,     0,    29,     0,    30,     0,     0,     0,
+       0,    31,    32,    33,    34,    35,    36,    37,    27,    28,
+       0,    29,     0,    30,     0,     0,    31,    32,    33,    34,
+      35,    36,    37,    27,    28,     0,    29,     0,    30,    27,
+      28,     0,    29,    31,    30,    33,    34,    35,    36,    37,
+       0,     0,     0,     0,     0,     0,     0,     0,    31,     0,
+       0,    34,    35,    36,    37,     0,     0,    34,    35,    36,
+      37,   127,     0,     0,     0,     0,    38,    39,    40,    41,
+      42
 };
 
 static const yytype_int16 yycheck[] =
 {
-       1,     6,    58,   109,   112,    44,     6,    13,     6,    10,
-       0,    12,    44,   131,    44,    16,    21,    47,    11,    28,
-      29,    44,    23,    21,    47,    13,     3,    28,   136,     6,
-      26,    32,    33,    34,    35,    36,    29,    93,    44,    39,
-     148,     6,    47,    44,   100,    38,    39,    40,    41,    42,
-      89,   169,     5,     6,   115,   173,    20,     3,     4,     5,
-       6,    11,    44,    64,   170,    11,    33,    68,    69,   130,
-      71,    72,    65,    74,    46,    76,    45,   183,    24,    25,
-      30,    11,   143,    27,    30,   146,   147,    45,    89,    14,
-      15,     9,    38,    39,     7,     8,    97,    10,    44,    44,
-       3,     4,     5,     6,    32,    98,    45,    46,    11,    37,
-      38,    39,    40,    41,    20,     3,     4,     5,     6,    39,
-      40,    41,    25,    11,     6,   126,     6,    30,    45,    46,
-      45,    34,    35,     9,   127,    38,     6,    25,    22,    23,
-      45,    44,    30,    47,    44,    33,    45,    35,    45,   150,
-      38,     3,     4,     5,     6,    47,    44,     6,   159,    11,
-      45,     3,     4,     5,     6,     6,    16,   168,    15,    11,
-      18,    17,    24,    25,    17,    19,     3,     3,    30,    45,
-      45,    52,    46,    25,    17,   145,    38,    39,    30,    90,
-      -1,    33,    44,   155,   183,    -1,    38,     3,     4,     5,
-       6,    -1,    44,    -1,    -1,    11,    -1,     3,     4,     5,
-       6,    -1,    -1,    -1,    -1,    11,    -1,    -1,    -1,    25,
-      -1,    -1,    -1,    -1,    30,    -1,    -1,    -1,    -1,    25,
-      -1,    -1,    38,    39,    30,    -1,    -1,    -1,    44,    -1,
-      -1,    -1,    38,     3,     4,     5,     6,    -1,    44,    -1,
-      -1,    11,    -1,    -1,     7,     8,    -1,    10,    -1,    12,
-      -1,    -1,    -1,     7,     8,    25,    10,    -1,    12,    -1,
-       7,     8,    -1,    10,    -1,    12,    -1,    30,    38,    32,
-      33,    34,    35,    36,    44,    -1,    30,    31,    32,    33,
-      34,    35,    36,    30,    31,    32,    33,    34,    35,    36,
-      -1,    -1,    46,     6,     7,     8,    -1,    10,    45,    12,
-      -1,    -1,     7,     8,    -1,    10,    32,    12,    21,    14,
-      15,    37,    38,    39,    40,    41,    -1,    30,    31,    32,
-      33,    34,    35,    36,    -1,    30,    31,    32,    33,    34,
-      35,    36,     7,     8,    -1,    10,    -1,    12,    -1,     7,
-       8,    -1,    10,    -1,    12,    -1,    21,     7,     8,    -1,
-      10,    -1,    12,    -1,    -1,    30,    31,    32,    33,    34,
-      35,    36,    30,    31,    32,    33,    34,    35,    36,    -1,
-      30,    -1,    -1,    33,    34,    35,    36,     7,     8,    -1,
-      10,    -1,    12,    37,    38,    39,    40,    41,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    33,    34,    35,    36
+       1,   109,   112,    11,    13,    44,   131,     6,     6,    10,
+       6,    12,     0,     7,     8,    16,    10,    46,    11,    46,
+      49,    13,    23,    21,    32,    21,   136,    28,    41,    42,
+      43,    32,    33,    34,    35,    36,    29,    46,   148,    58,
+      30,    31,    41,    44,   169,    38,    39,    40,    41,    42,
+      89,   176,     3,    49,    26,     6,     3,     4,     5,     6,
+       5,     6,   170,    64,    11,     6,    46,    68,    69,    49,
+      71,    72,    65,    74,    93,    76,    46,    24,    25,    14,
+      15,   100,   190,    47,    48,    32,    47,    48,    89,     3,
+       4,     5,     6,    40,    41,    34,    97,    11,    35,    46,
+      39,    40,    41,    42,    43,    98,    48,     3,     4,     5,
+       6,    25,    22,    23,    20,    11,    47,    47,    32,    27,
+       9,    11,    36,    37,    46,   126,    40,    20,     6,    25,
+       6,    47,    46,     6,   127,     9,    32,    49,    47,    35,
+      47,    37,    46,     6,    40,    47,    49,    47,     6,   150,
+      46,     3,     4,     5,     6,    15,    18,    16,   159,    11,
+      17,     3,     4,     5,     6,    19,    17,   168,     3,    11,
+       3,     3,    24,    25,     3,     4,     5,     6,    28,    47,
+      32,    29,    11,    25,     3,     4,     5,     6,    40,    41,
+      32,    47,    11,    35,    46,    48,    25,     3,    40,    17,
+     155,   145,    90,    32,    46,    52,    25,     3,     4,     5,
+       6,    40,    41,    32,   190,    11,   175,    46,   167,    -1,
+      -1,    40,    39,    40,    41,    42,    43,    46,    -1,    25,
+       7,     8,    -1,    10,    -1,    12,    -1,     7,     8,    -1,
+      10,    -1,    12,    -1,    40,    -1,    -1,    -1,    -1,    -1,
+      46,    -1,    -1,    -1,   115,    32,    33,    34,    35,    36,
+      37,    38,    32,    33,    34,    35,    36,    37,    38,   130,
+      -1,    48,     6,     7,     8,    -1,    10,    47,    12,    -1,
+      -1,    -1,   143,    -1,    -1,   146,   147,    21,     7,     8,
+      -1,    10,    -1,    12,    -1,    14,    15,    -1,    32,    33,
+      34,    35,    36,    37,    38,    -1,     7,     8,    -1,    10,
+      -1,    12,    -1,    32,    33,    34,    35,    36,    37,    38,
+      21,     7,     8,    -1,    10,    -1,    12,    -1,    -1,    -1,
+      -1,    32,    33,    34,    35,    36,    37,    38,     7,     8,
+      -1,    10,    -1,    12,    -1,    -1,    32,    33,    34,    35,
+      36,    37,    38,     7,     8,    -1,    10,    -1,    12,     7,
+       8,    -1,    10,    32,    12,    34,    35,    36,    37,    38,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    32,    -1,
+      -1,    35,    36,    37,    38,    -1,    -1,    35,    36,    37,
+      38,    34,    -1,    -1,    -1,    -1,    39,    40,    41,    42,
+      43
 };
 
   /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
      symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    28,    29,    49,     3,     4,     5,     6,    11,    25,
-      30,    38,    44,    50,    52,    53,    13,    44,    55,    56,
-       0,    44,    47,    44,    50,    53,    50,     7,     8,    10,
-      12,    30,    31,    32,    33,    34,    35,    36,    37,    38,
-      39,    40,    41,     6,    24,    39,    50,    59,    60,    56,
-      26,    57,    58,    50,    51,     6,    50,    45,    44,    50,
-      53,    11,    30,     7,     8,    10,    50,    50,    34,    35,
-      50,    33,    35,    50,    33,    50,    33,    53,    53,    53,
-      53,    53,    44,    47,    59,     6,    21,    61,    20,    46,
-      45,    27,    55,    46,    45,    21,    51,     9,    32,    11,
-      44,    50,    53,    50,    50,    50,    50,    50,    50,    24,
-      39,    39,    20,     6,     5,     6,    67,    59,    57,    51,
-       6,    54,    45,    50,    53,    51,     9,    32,     6,    52,
-      45,    67,    47,    47,    61,    14,    15,    63,    44,    45,
-      45,    50,    53,    45,    61,    63,     6,     6,    15,    67,
-      16,    62,     3,     6,    61,    62,    61,    61,    67,    17,
-      50,    18,    64,    45,    46,    45,    46,    64,    17,    50,
-      19,     3,     3,    50,    63,    52,    65,    66,    45,    45,
-      63,    22,    23,    46,    65
+       0,    30,    31,    51,     3,     4,     5,     6,    11,    25,
+      32,    40,    46,    52,    54,    55,    13,    46,    57,    58,
+       0,    46,    49,    46,    52,    55,    52,     7,     8,    10,
+      12,    32,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,     6,    24,    41,    52,    61,    62,    58,
+      26,    59,    60,    52,    53,     6,    52,    47,    46,    52,
+      55,    11,    32,     7,     8,    10,    52,    52,    36,    37,
+      52,    35,    37,    52,    35,    52,    35,    55,    55,    55,
+      55,    55,    46,    49,    61,     6,    21,    63,    20,    48,
+      47,    27,    57,    48,    47,    21,    53,     9,    34,    11,
+      46,    52,    55,    52,    52,    52,    52,    52,    52,    24,
+      41,    41,    20,     6,     5,     6,    71,    61,    59,    53,
+       6,    56,    47,    52,    55,    53,     9,    34,     6,    54,
+      47,    71,    49,    49,    63,    14,    15,    65,    46,    47,
+      47,    52,    55,    47,    63,    65,     6,     6,    15,    71,
+      16,    64,     3,     6,    63,    64,    63,    63,    71,    17,
+      52,    18,    66,    47,    48,    47,    48,    66,    17,    52,
+      19,    28,    69,     3,     3,    69,    52,    65,    54,    67,
+      68,     3,    29,    70,    47,    47,    70,    65,    22,    23,
+      48,     3,    67
 };
 
   /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    48,    49,    49,    49,    50,    50,    50,    50,    50,
-      50,    50,    50,    50,    50,    50,    50,    50,    50,    50,
-      50,    50,    50,    50,    50,    50,    50,    50,    51,    51,
-      52,    52,    53,    53,    53,    53,    53,    53,    53,    53,
-      53,    53,    53,    53,    53,    53,    54,    54,    54,    54,
-      54,    55,    55,    56,    56,    57,    57,    58,    59,    59,
-      60,    60,    60,    60,    60,    60,    60,    60,    61,    61,
-      62,    62,    63,    63,    63,    64,    64,    65,    65,    66,
-      66,    66,    67,    67,    67,    67,    67,    67
+       0,    50,    51,    51,    51,    52,    52,    52,    52,    52,
+      52,    52,    52,    52,    52,    52,    52,    52,    52,    52,
+      52,    52,    52,    52,    52,    52,    52,    52,    53,    53,
+      54,    54,    55,    55,    55,    55,    55,    55,    55,    55,
+      55,    55,    55,    55,    55,    55,    56,    56,    56,    56,
+      56,    57,    57,    58,    58,    59,    59,    60,    61,    61,
+      62,    62,    62,    62,    62,    62,    62,    62,    63,    63,
+      64,    64,    65,    65,    65,    66,    66,    67,    67,    68,
+      68,    68,    69,    69,    70,    70,    71,    71,    71,    71,
+      71,    71
 };
 
   /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
@@ -747,10 +780,11 @@ static const yytype_uint8 yyr2[] =
        5,     6,     5,     6,     5,     6,     3,     4,     3,     1,
        1,     3,     1,     1,     1,     1,     3,     1,     2,     3,
        3,     3,     3,     3,     4,     6,     1,     4,     6,     4,
-       6,     2,     4,     7,     8,     0,     2,     2,     1,     3,
+       6,     2,     4,     9,    10,     0,     2,     2,     1,     3,
        1,     2,     1,     3,     4,     5,     5,     6,     2,     1,
        0,     2,     0,     5,     6,     0,     3,     3,     1,     1,
-       2,     2,     1,     2,     3,     4,     3,     4
+       2,     2,     0,     2,     0,     2,     1,     2,     3,     4,
+       3,     4
 };
 
 
@@ -1001,8 +1035,7 @@ yytnamerr (char *yyres, const char *yystr)
           case '\\':
             if (*++yyp != '\\')
               goto do_not_strip_quotes;
-            /* Fall through.  */
-            // CPL_FALLTHROUGH
+            CPL_FALLTHROUGH
           default:
             if (yyres)
               yyres[yyn] = *yyp;
@@ -1036,11 +1069,11 @@ static int
 yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                 yytype_int16 *yyssp, int yytoken)
 {
-  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
   enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
   /* Internationalized format string. */
-  const char *yyformat = YY_NULL;
+  const char *yyformat = YY_NULLPTR;
   /* Arguments of yyformat. */
   char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
   /* Number of reported tokens (one for the "unexpected", one per
@@ -1097,7 +1130,7 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                   }
                 yyarg[yycount++] = yytname[yyx];
                 {
-                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
                   if (! (yysize <= yysize1
                          && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
                     return 2;
@@ -1177,63 +1210,63 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, swq_parse_context
   switch (yytype)
     {
           case 3: /* "integer number"  */
-#line 107 "swq_parser.y" /* yacc.c:1257  */
+#line 116 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1181 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1216 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
     case 4: /* "floating point number"  */
-#line 107 "swq_parser.y" /* yacc.c:1257  */
+#line 116 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1187 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1222 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
     case 5: /* "string"  */
-#line 107 "swq_parser.y" /* yacc.c:1257  */
+#line 116 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1193 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1228 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
     case 6: /* "identifier"  */
-#line 107 "swq_parser.y" /* yacc.c:1257  */
+#line 116 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1199 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1234 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
-    case 50: /* value_expr  */
-#line 108 "swq_parser.y" /* yacc.c:1257  */
+    case 52: /* value_expr  */
+#line 117 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1205 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1240 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
-    case 51: /* value_expr_list  */
-#line 108 "swq_parser.y" /* yacc.c:1257  */
+    case 53: /* value_expr_list  */
+#line 117 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1211 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1246 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
-    case 52: /* field_value  */
-#line 108 "swq_parser.y" /* yacc.c:1257  */
+    case 54: /* field_value  */
+#line 117 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1217 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1252 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
-    case 53: /* value_expr_non_logical  */
-#line 108 "swq_parser.y" /* yacc.c:1257  */
+    case 55: /* value_expr_non_logical  */
+#line 117 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1223 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1258 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
-    case 54: /* type_def  */
-#line 108 "swq_parser.y" /* yacc.c:1257  */
+    case 56: /* type_def  */
+#line 117 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1229 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1264 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
-    case 67: /* table_def  */
-#line 108 "swq_parser.y" /* yacc.c:1257  */
+    case 71: /* table_def  */
+#line 117 "swq_parser.y" /* yacc.c:1257  */
       { delete ((*yyvaluep)); }
-#line 1235 "swq_parser.cpp" /* yacc.c:1257  */
+#line 1270 "swq_parser.cpp" /* yacc.c:1257  */
         break;
 
 
@@ -1499,176 +1532,175 @@ yyreduce:
   switch (yyn)
     {
         case 3:
-#line 114 "swq_parser.y" /* yacc.c:1646  */
+#line 123 "swq_parser.y" /* yacc.c:1646  */
     {
             context->poRoot = (yyvsp[0]);
         }
-#line 1505 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1540 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 4:
-#line 119 "swq_parser.y" /* yacc.c:1646  */
+#line 128 "swq_parser.y" /* yacc.c:1646  */
     {
             context->poRoot = (yyvsp[0]);
         }
-#line 1513 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1548 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 5:
-#line 125 "swq_parser.y" /* yacc.c:1646  */
+#line 134 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[0]);
         }
-#line 1521 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1556 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 6:
-#line 130 "swq_parser.y" /* yacc.c:1646  */
+#line 139 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_AND );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1532 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1567 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 7:
-#line 138 "swq_parser.y" /* yacc.c:1646  */
+#line 147 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_OR );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1543 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1578 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 8:
-#line 146 "swq_parser.y" /* yacc.c:1646  */
+#line 155 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_NOT );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1553 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1588 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 9:
-#line 153 "swq_parser.y" /* yacc.c:1646  */
+#line 162 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_EQ );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1564 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1599 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 10:
-#line 161 "swq_parser.y" /* yacc.c:1646  */
+#line 170 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_NE );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-3]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1575 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1610 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 11:
-#line 169 "swq_parser.y" /* yacc.c:1646  */
+#line 178 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_NE );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-3]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1586 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1621 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 12:
-#line 177 "swq_parser.y" /* yacc.c:1646  */
+#line 186 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_LT );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1597 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1632 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 13:
-#line 185 "swq_parser.y" /* yacc.c:1646  */
+#line 194 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_GT );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1608 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1643 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 14:
-#line 193 "swq_parser.y" /* yacc.c:1646  */
+#line 202 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_LE );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-3]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1619 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1654 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 15:
-#line 201 "swq_parser.y" /* yacc.c:1646  */
+#line 210 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_LE );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-3]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1630 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1665 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 16:
-#line 209 "swq_parser.y" /* yacc.c:1646  */
+#line 218 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_LE );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-3]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1641 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1676 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 17:
-#line 217 "swq_parser.y" /* yacc.c:1646  */
+#line 226 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_GE );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-3]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1652 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1687 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 18:
-#line 225 "swq_parser.y" /* yacc.c:1646  */
+#line 234 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_LIKE );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1663 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1698 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 19:
-#line 233 "swq_parser.y" /* yacc.c:1646  */
+#line 242 "swq_parser.y" /* yacc.c:1646  */
     {
-            swq_expr_node *like;
-            like = new swq_expr_node( SWQ_LIKE );
+            swq_expr_node *like = new swq_expr_node( SWQ_LIKE );
             like->field_type = SWQ_BOOLEAN;
             like->PushSubExpression( (yyvsp[-3]) );
             like->PushSubExpression( (yyvsp[0]) );
@@ -1677,11 +1709,11 @@ yyreduce:
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( like );
         }
-#line 1679 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1713 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 20:
-#line 246 "swq_parser.y" /* yacc.c:1646  */
+#line 254 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_LIKE );
             (yyval)->field_type = SWQ_BOOLEAN;
@@ -1689,14 +1721,13 @@ yyreduce:
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1691 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1725 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 21:
-#line 255 "swq_parser.y" /* yacc.c:1646  */
+#line 263 "swq_parser.y" /* yacc.c:1646  */
     {
-            swq_expr_node *like;
-            like = new swq_expr_node( SWQ_LIKE );
+            swq_expr_node *like = new swq_expr_node( SWQ_LIKE );
             like->field_type = SWQ_BOOLEAN;
             like->PushSubExpression( (yyvsp[-5]) );
             like->PushSubExpression( (yyvsp[-2]) );
@@ -1706,11 +1737,11 @@ yyreduce:
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( like );
         }
-#line 1708 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1741 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 22:
-#line 269 "swq_parser.y" /* yacc.c:1646  */
+#line 276 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[-1]);
             (yyval)->field_type = SWQ_BOOLEAN;
@@ -1718,15 +1749,13 @@ yyreduce:
             (yyval)->PushSubExpression( (yyvsp[-4]) );
             (yyval)->ReverseSubExpressions();
         }
-#line 1720 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1753 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 23:
-#line 278 "swq_parser.y" /* yacc.c:1646  */
+#line 285 "swq_parser.y" /* yacc.c:1646  */
     {
-            swq_expr_node *in;
-
-            in = (yyvsp[-1]);
+            swq_expr_node *in = (yyvsp[-1]);
             in->field_type = SWQ_BOOLEAN;
             in->nOperation = SWQ_IN;
             in->PushSubExpression( (yyvsp[-5]) );
@@ -1736,11 +1765,11 @@ yyreduce:
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( in );
         }
-#line 1738 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1769 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 24:
-#line 293 "swq_parser.y" /* yacc.c:1646  */
+#line 298 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_BETWEEN );
             (yyval)->field_type = SWQ_BOOLEAN;
@@ -1748,14 +1777,13 @@ yyreduce:
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1750 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1781 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 25:
-#line 302 "swq_parser.y" /* yacc.c:1646  */
+#line 307 "swq_parser.y" /* yacc.c:1646  */
     {
-            swq_expr_node *between;
-            between = new swq_expr_node( SWQ_BETWEEN );
+            swq_expr_node *between = new swq_expr_node( SWQ_BETWEEN );
             between->field_type = SWQ_BOOLEAN;
             between->PushSubExpression( (yyvsp[-5]) );
             between->PushSubExpression( (yyvsp[-2]) );
@@ -1765,25 +1793,23 @@ yyreduce:
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( between );
         }
-#line 1767 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1797 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 26:
-#line 316 "swq_parser.y" /* yacc.c:1646  */
+#line 320 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_ISNULL );
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( (yyvsp[-2]) );
         }
-#line 1777 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1807 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 27:
-#line 323 "swq_parser.y" /* yacc.c:1646  */
+#line 327 "swq_parser.y" /* yacc.c:1646  */
     {
-        swq_expr_node *isnull;
-
-            isnull = new swq_expr_node( SWQ_ISNULL );
+            swq_expr_node *isnull = new swq_expr_node( SWQ_ISNULL );
             isnull->field_type = SWQ_BOOLEAN;
             isnull->PushSubExpression( (yyvsp[-3]) );
 
@@ -1791,101 +1817,103 @@ yyreduce:
             (yyval)->field_type = SWQ_BOOLEAN;
             (yyval)->PushSubExpression( isnull );
         }
-#line 1793 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1821 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 28:
-#line 337 "swq_parser.y" /* yacc.c:1646  */
+#line 339 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[0]);
             (yyvsp[0])->PushSubExpression( (yyvsp[-2]) );
         }
-#line 1802 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1830 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 29:
-#line 343 "swq_parser.y" /* yacc.c:1646  */
+#line 345 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_ARGUMENT_LIST ); /* temporary value */
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1811 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1839 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 30:
-#line 350 "swq_parser.y" /* yacc.c:1646  */
+#line 352 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[0]);  // validation deferred.
             (yyval)->eNodeType = SNT_COLUMN;
-            (yyval)->field_index = (yyval)->table_index = -1;
+            (yyval)->field_index = -1;
+            (yyval)->table_index = -1;
         }
-#line 1821 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1850 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 31:
-#line 357 "swq_parser.y" /* yacc.c:1646  */
+#line 360 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[-2]);  // validation deferred.
             (yyval)->eNodeType = SNT_COLUMN;
-            (yyval)->field_index = (yyval)->table_index = -1;
+            (yyval)->field_index = -1;
+            (yyval)->table_index = -1;
             (yyval)->table_name = (yyval)->string_value;
             (yyval)->string_value = CPLStrdup((yyvsp[0])->string_value);
             delete (yyvsp[0]);
             (yyvsp[0]) = NULL;
         }
-#line 1835 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1865 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 32:
-#line 369 "swq_parser.y" /* yacc.c:1646  */
+#line 373 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[0]);
         }
-#line 1843 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1873 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 33:
-#line 374 "swq_parser.y" /* yacc.c:1646  */
+#line 378 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[0]);
         }
-#line 1851 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1881 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 34:
-#line 379 "swq_parser.y" /* yacc.c:1646  */
+#line 383 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[0]);
         }
-#line 1859 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1889 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 35:
-#line 383 "swq_parser.y" /* yacc.c:1646  */
+#line 387 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[0]);
         }
-#line 1867 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1897 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 36:
-#line 388 "swq_parser.y" /* yacc.c:1646  */
+#line 392 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[-1]);
         }
-#line 1875 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1905 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 37:
-#line 393 "swq_parser.y" /* yacc.c:1646  */
+#line 397 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node((const char*)NULL);
         }
-#line 1883 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1913 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 38:
-#line 398 "swq_parser.y" /* yacc.c:1646  */
+#line 402 "swq_parser.y" /* yacc.c:1646  */
     {
             if ((yyvsp[0])->eNodeType == SNT_CONSTANT)
             {
@@ -1900,61 +1928,61 @@ yyreduce:
                 (yyval)->PushSubExpression( (yyvsp[0]) );
             }
         }
-#line 1902 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1932 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 39:
-#line 414 "swq_parser.y" /* yacc.c:1646  */
+#line 418 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_ADD );
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1912 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1942 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 40:
-#line 421 "swq_parser.y" /* yacc.c:1646  */
+#line 425 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_SUBTRACT );
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1922 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1952 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 41:
-#line 428 "swq_parser.y" /* yacc.c:1646  */
+#line 432 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_MULTIPLY );
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1932 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1962 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 42:
-#line 435 "swq_parser.y" /* yacc.c:1646  */
+#line 439 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_DIVIDE );
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1942 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1972 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 43:
-#line 442 "swq_parser.y" /* yacc.c:1646  */
+#line 446 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = new swq_expr_node( SWQ_MODULUS );
             (yyval)->PushSubExpression( (yyvsp[-2]) );
             (yyval)->PushSubExpression( (yyvsp[0]) );
         }
-#line 1952 "swq_parser.cpp" /* yacc.c:1646  */
+#line 1982 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 44:
-#line 449 "swq_parser.y" /* yacc.c:1646  */
+#line 453 "swq_parser.y" /* yacc.c:1646  */
     {
             const swq_operation *poOp =
                     swq_op_registrar::GetOperator( (yyvsp[-3])->string_value );
@@ -1989,54 +2017,54 @@ yyreduce:
                 delete (yyvsp[-3]);
             }
         }
-#line 1991 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2021 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 45:
-#line 485 "swq_parser.y" /* yacc.c:1646  */
+#line 489 "swq_parser.y" /* yacc.c:1646  */
     {
             (yyval) = (yyvsp[-1]);
             (yyval)->PushSubExpression( (yyvsp[-3]) );
             (yyval)->ReverseSubExpressions();
         }
-#line 2001 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2031 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 46:
-#line 493 "swq_parser.y" /* yacc.c:1646  */
+#line 497 "swq_parser.y" /* yacc.c:1646  */
     {
         (yyval) = new swq_expr_node( SWQ_CAST );
         (yyval)->PushSubExpression( (yyvsp[0]) );
     }
-#line 2010 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2040 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 47:
-#line 499 "swq_parser.y" /* yacc.c:1646  */
+#line 503 "swq_parser.y" /* yacc.c:1646  */
     {
         (yyval) = new swq_expr_node( SWQ_CAST );
         (yyval)->PushSubExpression( (yyvsp[-1]) );
         (yyval)->PushSubExpression( (yyvsp[-3]) );
     }
-#line 2020 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2050 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 48:
-#line 506 "swq_parser.y" /* yacc.c:1646  */
+#line 510 "swq_parser.y" /* yacc.c:1646  */
     {
         (yyval) = new swq_expr_node( SWQ_CAST );
         (yyval)->PushSubExpression( (yyvsp[-1]) );
         (yyval)->PushSubExpression( (yyvsp[-3]) );
         (yyval)->PushSubExpression( (yyvsp[-5]) );
     }
-#line 2031 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2061 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 49:
-#line 515 "swq_parser.y" /* yacc.c:1646  */
+#line 519 "swq_parser.y" /* yacc.c:1646  */
     {
         OGRwkbGeometryType eType = OGRFromOGCGeomType((yyvsp[-1])->string_value);
-        if( !EQUAL((yyvsp[-3])->string_value,"GEOMETRY") ||
+        if( !EQUAL((yyvsp[-3])->string_value, "GEOMETRY") ||
             (wkbFlatten(eType) == wkbUnknown &&
             !STARTS_WITH_CI((yyvsp[-1])->string_value, "GEOMETRY")) )
         {
@@ -2049,14 +2077,14 @@ yyreduce:
         (yyval)->PushSubExpression( (yyvsp[-1]) );
         (yyval)->PushSubExpression( (yyvsp[-3]) );
     }
-#line 2051 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2081 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 50:
-#line 533 "swq_parser.y" /* yacc.c:1646  */
+#line 537 "swq_parser.y" /* yacc.c:1646  */
     {
         OGRwkbGeometryType eType = OGRFromOGCGeomType((yyvsp[-3])->string_value);
-        if( !EQUAL((yyvsp[-5])->string_value,"GEOMETRY") ||
+        if( !EQUAL((yyvsp[-5])->string_value, "GEOMETRY") ||
             (wkbFlatten(eType) == wkbUnknown &&
             !STARTS_WITH_CI((yyvsp[-3])->string_value, "GEOMETRY")) )
         {
@@ -2071,38 +2099,38 @@ yyreduce:
         (yyval)->PushSubExpression( (yyvsp[-3]) );
         (yyval)->PushSubExpression( (yyvsp[-5]) );
     }
-#line 2073 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2103 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 53:
-#line 557 "swq_parser.y" /* yacc.c:1646  */
+#line 561 "swq_parser.y" /* yacc.c:1646  */
     {
-        delete (yyvsp[-3]);
+        delete (yyvsp[-5]);
     }
-#line 2081 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2111 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 54:
-#line 562 "swq_parser.y" /* yacc.c:1646  */
+#line 566 "swq_parser.y" /* yacc.c:1646  */
     {
         context->poCurSelect->query_mode = SWQM_DISTINCT_LIST;
-        delete (yyvsp[-3]);
+        delete (yyvsp[-5]);
     }
-#line 2090 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2120 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 57:
-#line 571 "swq_parser.y" /* yacc.c:1646  */
+#line 575 "swq_parser.y" /* yacc.c:1646  */
     {
         swq_select* poNewSelect = new swq_select();
         context->poCurSelect->PushUnionAll(poNewSelect);
         context->poCurSelect = poNewSelect;
     }
-#line 2100 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2130 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 60:
-#line 583 "swq_parser.y" /* yacc.c:1646  */
+#line 587 "swq_parser.y" /* yacc.c:1646  */
     {
             if( !context->poCurSelect->PushField( (yyvsp[0]) ) )
             {
@@ -2110,11 +2138,11 @@ yyreduce:
                 YYERROR;
             }
         }
-#line 2112 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2142 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 61:
-#line 592 "swq_parser.y" /* yacc.c:1646  */
+#line 596 "swq_parser.y" /* yacc.c:1646  */
     {
             if( !context->poCurSelect->PushField( (yyvsp[-1]), (yyvsp[0])->string_value ) )
             {
@@ -2124,16 +2152,17 @@ yyreduce:
             }
             delete (yyvsp[0]);
         }
-#line 2126 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2156 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 62:
-#line 603 "swq_parser.y" /* yacc.c:1646  */
+#line 607 "swq_parser.y" /* yacc.c:1646  */
     {
             swq_expr_node *poNode = new swq_expr_node();
             poNode->eNodeType = SNT_COLUMN;
             poNode->string_value = CPLStrdup( "*" );
-            poNode->table_index = poNode->field_index = -1;
+            poNode->table_index = -1;
+            poNode->field_index = -1;
 
             if( !context->poCurSelect->PushField( poNode ) )
             {
@@ -2141,15 +2170,13 @@ yyreduce:
                 YYERROR;
             }
         }
-#line 2143 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2174 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 63:
-#line 617 "swq_parser.y" /* yacc.c:1646  */
+#line 622 "swq_parser.y" /* yacc.c:1646  */
     {
-            CPLString osTableName;
-
-            osTableName = (yyvsp[-2])->string_value;
+            CPLString osTableName = (yyvsp[-2])->string_value;
 
             delete (yyvsp[-2]);
             (yyvsp[-2]) = NULL;
@@ -2158,7 +2185,8 @@ yyreduce:
             poNode->eNodeType = SNT_COLUMN;
             poNode->table_name = CPLStrdup(osTableName );
             poNode->string_value = CPLStrdup( "*" );
-            poNode->table_index = poNode->field_index = -1;
+            poNode->table_index = -1;
+            poNode->field_index = -1;
 
             if( !context->poCurSelect->PushField( poNode ) )
             {
@@ -2166,14 +2194,14 @@ yyreduce:
                 YYERROR;
             }
         }
-#line 2168 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2198 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 64:
-#line 639 "swq_parser.y" /* yacc.c:1646  */
+#line 643 "swq_parser.y" /* yacc.c:1646  */
     {
                 // special case for COUNT(*), confirm it.
-            if( !EQUAL((yyvsp[-3])->string_value,"COUNT") )
+            if( !EQUAL((yyvsp[-3])->string_value, "COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Syntax Error with %s(*).",
@@ -2188,7 +2216,8 @@ yyreduce:
             swq_expr_node *poNode = new swq_expr_node();
             poNode->eNodeType = SNT_COLUMN;
             poNode->string_value = CPLStrdup( "*" );
-            poNode->table_index = poNode->field_index = -1;
+            poNode->table_index = -1;
+            poNode->field_index = -1;
 
             swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
             count->PushSubExpression( poNode );
@@ -2199,14 +2228,14 @@ yyreduce:
                 YYERROR;
             }
         }
-#line 2201 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2232 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 65:
-#line 669 "swq_parser.y" /* yacc.c:1646  */
+#line 674 "swq_parser.y" /* yacc.c:1646  */
     {
                 // special case for COUNT(*), confirm it.
-            if( !EQUAL((yyvsp[-4])->string_value,"COUNT") )
+            if( !EQUAL((yyvsp[-4])->string_value, "COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Syntax Error with %s(*).",
@@ -2222,7 +2251,8 @@ yyreduce:
             swq_expr_node *poNode = new swq_expr_node();
             poNode->eNodeType = SNT_COLUMN;
             poNode->string_value = CPLStrdup( "*" );
-            poNode->table_index = poNode->field_index = -1;
+            poNode->table_index = -1;
+            poNode->field_index = -1;
 
             swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
             count->PushSubExpression( poNode );
@@ -2236,17 +2266,18 @@ yyreduce:
 
             delete (yyvsp[0]);
         }
-#line 2238 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2270 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 66:
-#line 703 "swq_parser.y" /* yacc.c:1646  */
+#line 709 "swq_parser.y" /* yacc.c:1646  */
     {
                 // special case for COUNT(DISTINCT x), confirm it.
-            if( !EQUAL((yyvsp[-4])->string_value,"COUNT") )
+            if( !EQUAL((yyvsp[-4])->string_value, "COUNT") )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "DISTINCT keyword can only be used in COUNT() operator." );
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "DISTINCT keyword can only be used in COUNT() operator." );
                 delete (yyvsp[-4]);
                 delete (yyvsp[-1]);
                     YYERROR;
@@ -2263,14 +2294,14 @@ yyreduce:
                 YYERROR;
             }
         }
-#line 2265 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2298 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 67:
-#line 727 "swq_parser.y" /* yacc.c:1646  */
+#line 734 "swq_parser.y" /* yacc.c:1646  */
     {
             // special case for COUNT(DISTINCT x), confirm it.
-            if( !EQUAL((yyvsp[-5])->string_value,"COUNT") )
+            if( !EQUAL((yyvsp[-5])->string_value, "COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "DISTINCT keyword can only be used in COUNT() operator." );
@@ -2294,165 +2325,185 @@ yyreduce:
             delete (yyvsp[-5]);
             delete (yyvsp[0]);
         }
-#line 2296 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2329 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 68:
-#line 756 "swq_parser.y" /* yacc.c:1646  */
+#line 763 "swq_parser.y" /* yacc.c:1646  */
     {
             delete (yyvsp[-1]);
             (yyval) = (yyvsp[0]);
         }
-#line 2305 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2338 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 71:
-#line 766 "swq_parser.y" /* yacc.c:1646  */
+#line 772 "swq_parser.y" /* yacc.c:1646  */
     {
             context->poCurSelect->where_expr = (yyvsp[0]);
         }
-#line 2313 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2346 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 73:
-#line 772 "swq_parser.y" /* yacc.c:1646  */
+#line 778 "swq_parser.y" /* yacc.c:1646  */
     {
             context->poCurSelect->PushJoin( static_cast<int>((yyvsp[-3])->int_value),
                                             (yyvsp[-1]) );
             delete (yyvsp[-3]);
         }
-#line 2323 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2356 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 74:
-#line 778 "swq_parser.y" /* yacc.c:1646  */
+#line 784 "swq_parser.y" /* yacc.c:1646  */
     {
             context->poCurSelect->PushJoin( static_cast<int>((yyvsp[-3])->int_value),
                                             (yyvsp[-1]) );
             delete (yyvsp[-3]);
-	    }
-#line 2333 "swq_parser.cpp" /* yacc.c:1646  */
+        }
+#line 2366 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 79:
-#line 793 "swq_parser.y" /* yacc.c:1646  */
+#line 799 "swq_parser.y" /* yacc.c:1646  */
     {
             context->poCurSelect->PushOrderBy( (yyvsp[0])->table_name, (yyvsp[0])->string_value, TRUE );
             delete (yyvsp[0]);
             (yyvsp[0]) = NULL;
         }
-#line 2343 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2376 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 80:
-#line 799 "swq_parser.y" /* yacc.c:1646  */
+#line 805 "swq_parser.y" /* yacc.c:1646  */
     {
             context->poCurSelect->PushOrderBy( (yyvsp[-1])->table_name, (yyvsp[-1])->string_value, TRUE );
             delete (yyvsp[-1]);
             (yyvsp[-1]) = NULL;
         }
-#line 2353 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2386 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
   case 81:
-#line 805 "swq_parser.y" /* yacc.c:1646  */
+#line 811 "swq_parser.y" /* yacc.c:1646  */
     {
             context->poCurSelect->PushOrderBy( (yyvsp[-1])->table_name, (yyvsp[-1])->string_value, FALSE );
             delete (yyvsp[-1]);
             (yyvsp[-1]) = NULL;
         }
-#line 2363 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2396 "swq_parser.cpp" /* yacc.c:1646  */
+    break;
+
+  case 83:
+#line 819 "swq_parser.y" /* yacc.c:1646  */
+    {
+        context->poCurSelect->SetLimit( (yyvsp[0])->int_value );
+        delete (yyvsp[0]);
+        (yyvsp[0]) = NULL;
+    }
+#line 2406 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 82:
-#line 813 "swq_parser.y" /* yacc.c:1646  */
+  case 85:
+#line 827 "swq_parser.y" /* yacc.c:1646  */
+    {
+        context->poCurSelect->SetOffset( (yyvsp[0])->int_value );
+        delete (yyvsp[0]);
+        (yyvsp[0]) = NULL;
+    }
+#line 2416 "swq_parser.cpp" /* yacc.c:1646  */
+    break;
+
+  case 86:
+#line 835 "swq_parser.y" /* yacc.c:1646  */
     {
-        int iTable;
-        iTable =context->poCurSelect->PushTableDef( NULL, (yyvsp[0])->string_value,
-                                                    NULL );
+        const int iTable =
+            context->poCurSelect->PushTableDef( NULL, (yyvsp[0])->string_value,
+                                                NULL );
         delete (yyvsp[0]);
 
         (yyval) = new swq_expr_node( iTable );
     }
-#line 2376 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2429 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 83:
-#line 823 "swq_parser.y" /* yacc.c:1646  */
+  case 87:
+#line 845 "swq_parser.y" /* yacc.c:1646  */
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( NULL, (yyvsp[-1])->string_value,
-                                                     (yyvsp[0])->string_value );
+        const int iTable =
+            context->poCurSelect->PushTableDef( NULL, (yyvsp[-1])->string_value,
+                                                (yyvsp[0])->string_value );
         delete (yyvsp[-1]);
         delete (yyvsp[0]);
 
         (yyval) = new swq_expr_node( iTable );
     }
-#line 2390 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2443 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 84:
-#line 834 "swq_parser.y" /* yacc.c:1646  */
+  case 88:
+#line 856 "swq_parser.y" /* yacc.c:1646  */
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( (yyvsp[-2])->string_value,
-                                                     (yyvsp[0])->string_value, NULL );
+        const int iTable =
+            context->poCurSelect->PushTableDef( (yyvsp[-2])->string_value,
+                                                (yyvsp[0])->string_value, NULL );
         delete (yyvsp[-2]);
         delete (yyvsp[0]);
 
         (yyval) = new swq_expr_node( iTable );
     }
-#line 2404 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2457 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 85:
-#line 845 "swq_parser.y" /* yacc.c:1646  */
+  case 89:
+#line 867 "swq_parser.y" /* yacc.c:1646  */
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( (yyvsp[-3])->string_value,
-                                                     (yyvsp[-1])->string_value,
-                                                     (yyvsp[0])->string_value );
+        const int iTable =
+            context->poCurSelect->PushTableDef( (yyvsp[-3])->string_value,
+                                                (yyvsp[-1])->string_value,
+                                                (yyvsp[0])->string_value );
         delete (yyvsp[-3]);
         delete (yyvsp[-1]);
         delete (yyvsp[0]);
 
         (yyval) = new swq_expr_node( iTable );
     }
-#line 2420 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2473 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 86:
-#line 858 "swq_parser.y" /* yacc.c:1646  */
+  case 90:
+#line 880 "swq_parser.y" /* yacc.c:1646  */
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( (yyvsp[-2])->string_value,
-                                                     (yyvsp[0])->string_value, NULL );
+        const int iTable =
+            context->poCurSelect->PushTableDef( (yyvsp[-2])->string_value,
+                                                (yyvsp[0])->string_value, NULL );
         delete (yyvsp[-2]);
         delete (yyvsp[0]);
 
         (yyval) = new swq_expr_node( iTable );
     }
-#line 2434 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2487 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
-  case 87:
-#line 869 "swq_parser.y" /* yacc.c:1646  */
+  case 91:
+#line 891 "swq_parser.y" /* yacc.c:1646  */
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( (yyvsp[-3])->string_value,
-                                                     (yyvsp[-1])->string_value,
-                                                     (yyvsp[0])->string_value );
+        const int iTable =
+            context->poCurSelect->PushTableDef( (yyvsp[-3])->string_value,
+                                                (yyvsp[-1])->string_value,
+                                                (yyvsp[0])->string_value );
         delete (yyvsp[-3]);
         delete (yyvsp[-1]);
         delete (yyvsp[0]);
 
         (yyval) = new swq_expr_node( iTable );
     }
-#line 2450 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2503 "swq_parser.cpp" /* yacc.c:1646  */
     break;
 
 
-#line 2454 "swq_parser.cpp" /* yacc.c:1646  */
+#line 2507 "swq_parser.cpp" /* yacc.c:1646  */
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
diff --git a/ogr/swq_parser.hpp b/ogr/swq_parser.hpp
index 80f43c2..3256c07 100644
--- a/ogr/swq_parser.hpp
+++ b/ogr/swq_parser.hpp
@@ -1,8 +1,8 @@
-/* A Bison parser, made by GNU Bison 3.0.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison interface for Yacc-like parsers in C
 
-   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -71,13 +71,15 @@ extern int swqdebug;
     SWQT_CAST = 280,
     SWQT_UNION = 281,
     SWQT_ALL = 282,
-    SWQT_VALUE_START = 283,
-    SWQT_SELECT_START = 284,
-    SWQT_NOT = 285,
-    SWQT_OR = 286,
-    SWQT_AND = 287,
-    SWQT_UMINUS = 288,
-    SWQT_RESERVED_KEYWORD = 289
+    SWQT_LIMIT = 283,
+    SWQT_OFFSET = 284,
+    SWQT_VALUE_START = 285,
+    SWQT_SELECT_START = 286,
+    SWQT_NOT = 287,
+    SWQT_OR = 288,
+    SWQT_AND = 289,
+    SWQT_UMINUS = 290,
+    SWQT_RESERVED_KEYWORD = 291
   };
 #endif
 
diff --git a/ogr/swq_parser.y b/ogr/swq_parser.y
index f970f65..2b00aa2 100644
--- a/ogr/swq_parser.y
+++ b/ogr/swq_parser.y
@@ -28,13 +28,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "swq.h"
+
+#include <cstdlib>
+#include <cstring>
 
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
-#include "swq.h"
 
-#define YYSTYPE  swq_expr_node*
+CPL_CVSID("$Id: swq_parser.y 37361 2017-02-12 20:49:47Z rouault $");
+
+#define YYSTYPE swq_expr_node *
 
 /* Defining YYSTYPE_IS_TRIVIAL is needed because the parser is generated as a C++ file. */
 /* See http://www.gnu.org/s/bison/manual/html_node/Memory-Management.html that suggests */
@@ -42,7 +50,6 @@
 /* Setting YYSTYPE_IS_TRIVIAL overcomes this limitation, but might be fragile because */
 /* it appears to be a non documented feature of Bison */
 #define YYSTYPE_IS_TRIVIAL 1
-
 %}
 
 %define api.pure
@@ -79,6 +86,8 @@
 %token SWQT_CAST                "CAST"
 %token SWQT_UNION               "UNION"
 %token SWQT_ALL                 "ALL"
+%token SWQT_LIMIT               "LIMIT"
+%token SWQT_OFFSET              "OFFSET"
 
 %token SWQT_VALUE_START
 %token SWQT_SELECT_START
@@ -93,7 +102,7 @@
 %left SWQT_AND
 %left SWQT_NOT
 
-%left '=' '<' '>' '!'  SWQT_BETWEEN SWQT_IN SWQT_LIKE SWQT_IS
+%left '=' '<' '>' '!' SWQT_BETWEEN SWQT_IN SWQT_LIKE SWQT_IS
 %left SWQT_ESCAPE
 
 %left '+' '-'
@@ -102,7 +111,7 @@
 
 %token SWQT_RESERVED_KEYWORD    "reserved keyword"
 
-/* Any grammar rule that does $$ =  must be listed afterwards */
+/* Any grammar rule that does $$ = must be listed afterwards */
 /* as well as SWQT_INTEGER_NUMBER SWQT_FLOAT_NUMBER SWQT_STRING SWQT_IDENTIFIER that are allocated by swqlex() */
 %destructor { delete $$; } SWQT_INTEGER_NUMBER SWQT_FLOAT_NUMBER SWQT_STRING SWQT_IDENTIFIER
 %destructor { delete $$; } value_expr_list field_value value_expr value_expr_non_logical type_def table_def
@@ -231,8 +240,7 @@ value_expr:
 
     | value_expr SWQT_NOT SWQT_LIKE value_expr
         {
-            swq_expr_node *like;
-            like = new swq_expr_node( SWQ_LIKE );
+            swq_expr_node *like = new swq_expr_node( SWQ_LIKE );
             like->field_type = SWQ_BOOLEAN;
             like->PushSubExpression( $1 );
             like->PushSubExpression( $4 );
@@ -253,8 +261,7 @@ value_expr:
 
     | value_expr SWQT_NOT SWQT_LIKE value_expr SWQT_ESCAPE value_expr
         {
-            swq_expr_node *like;
-            like = new swq_expr_node( SWQ_LIKE );
+            swq_expr_node *like = new swq_expr_node( SWQ_LIKE );
             like->field_type = SWQ_BOOLEAN;
             like->PushSubExpression( $1 );
             like->PushSubExpression( $4 );
@@ -276,9 +283,7 @@ value_expr:
 
     | value_expr SWQT_NOT SWQT_IN '(' value_expr_list ')'
         {
-            swq_expr_node *in;
-
-            in = $5;
+            swq_expr_node *in = $5;
             in->field_type = SWQ_BOOLEAN;
             in->nOperation = SWQ_IN;
             in->PushSubExpression( $1 );
@@ -300,8 +305,7 @@ value_expr:
 
     | value_expr SWQT_NOT SWQT_BETWEEN value_expr_non_logical SWQT_AND value_expr_non_logical
         {
-            swq_expr_node *between;
-            between = new swq_expr_node( SWQ_BETWEEN );
+            swq_expr_node *between = new swq_expr_node( SWQ_BETWEEN );
             between->field_type = SWQ_BOOLEAN;
             between->PushSubExpression( $1 );
             between->PushSubExpression( $4 );
@@ -321,9 +325,7 @@ value_expr:
 
     | value_expr SWQT_IS SWQT_NOT SWQT_NULL
         {
-        swq_expr_node *isnull;
-
-            isnull = new swq_expr_node( SWQ_ISNULL );
+            swq_expr_node *isnull = new swq_expr_node( SWQ_ISNULL );
             isnull->field_type = SWQ_BOOLEAN;
             isnull->PushSubExpression( $1 );
 
@@ -350,14 +352,16 @@ field_value:
         {
             $$ = $1;  // validation deferred.
             $$->eNodeType = SNT_COLUMN;
-            $$->field_index = $$->table_index = -1;
+            $$->field_index = -1;
+            $$->table_index = -1;
         }
 
     | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER
         {
             $$ = $1;  // validation deferred.
             $$->eNodeType = SNT_COLUMN;
-            $$->field_index = $$->table_index = -1;
+            $$->field_index = -1;
+            $$->table_index = -1;
             $$->table_name = $$->string_value;
             $$->string_value = CPLStrdup($3->string_value);
             delete $3;
@@ -514,7 +518,7 @@ type_def:
     | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ')'
     {
         OGRwkbGeometryType eType = OGRFromOGCGeomType($3->string_value);
-        if( !EQUAL($1->string_value,"GEOMETRY") ||
+        if( !EQUAL($1->string_value, "GEOMETRY") ||
             (wkbFlatten(eType) == wkbUnknown &&
             !STARTS_WITH_CI($3->string_value, "GEOMETRY")) )
         {
@@ -532,7 +536,7 @@ type_def:
     | SWQT_IDENTIFIER '(' SWQT_IDENTIFIER ',' SWQT_INTEGER_NUMBER ')'
     {
         OGRwkbGeometryType eType = OGRFromOGCGeomType($3->string_value);
-        if( !EQUAL($1->string_value,"GEOMETRY") ||
+        if( !EQUAL($1->string_value, "GEOMETRY") ||
             (wkbFlatten(eType) == wkbUnknown &&
             !STARTS_WITH_CI($3->string_value, "GEOMETRY")) )
         {
@@ -553,12 +557,12 @@ select_statement:
     | '(' select_core ')' opt_union_all
 
 select_core:
-    SWQT_SELECT select_field_list SWQT_FROM table_def opt_joins opt_where opt_order_by
+    SWQT_SELECT select_field_list SWQT_FROM table_def opt_joins opt_where opt_order_by opt_limit opt_offset
     {
         delete $4;
     }
 
-    | SWQT_SELECT SWQT_DISTINCT select_field_list SWQT_FROM table_def opt_joins opt_where opt_order_by
+    | SWQT_SELECT SWQT_DISTINCT select_field_list SWQT_FROM table_def opt_joins opt_where opt_order_by opt_limit opt_offset
     {
         context->poCurSelect->query_mode = SWQM_DISTINCT_LIST;
         delete $5;
@@ -604,7 +608,8 @@ column_spec:
             swq_expr_node *poNode = new swq_expr_node();
             poNode->eNodeType = SNT_COLUMN;
             poNode->string_value = CPLStrdup( "*" );
-            poNode->table_index = poNode->field_index = -1;
+            poNode->table_index = -1;
+            poNode->field_index = -1;
 
             if( !context->poCurSelect->PushField( poNode ) )
             {
@@ -615,9 +620,7 @@ column_spec:
 
     | SWQT_IDENTIFIER '.' '*'
         {
-            CPLString osTableName;
-
-            osTableName = $1->string_value;
+            CPLString osTableName = $1->string_value;
 
             delete $1;
             $1 = NULL;
@@ -626,7 +629,8 @@ column_spec:
             poNode->eNodeType = SNT_COLUMN;
             poNode->table_name = CPLStrdup(osTableName );
             poNode->string_value = CPLStrdup( "*" );
-            poNode->table_index = poNode->field_index = -1;
+            poNode->table_index = -1;
+            poNode->field_index = -1;
 
             if( !context->poCurSelect->PushField( poNode ) )
             {
@@ -638,7 +642,7 @@ column_spec:
     | SWQT_IDENTIFIER '(' '*' ')'
         {
                 // special case for COUNT(*), confirm it.
-            if( !EQUAL($1->string_value,"COUNT") )
+            if( !EQUAL($1->string_value, "COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Syntax Error with %s(*).",
@@ -653,7 +657,8 @@ column_spec:
             swq_expr_node *poNode = new swq_expr_node();
             poNode->eNodeType = SNT_COLUMN;
             poNode->string_value = CPLStrdup( "*" );
-            poNode->table_index = poNode->field_index = -1;
+            poNode->table_index = -1;
+            poNode->field_index = -1;
 
             swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
             count->PushSubExpression( poNode );
@@ -668,7 +673,7 @@ column_spec:
     | SWQT_IDENTIFIER '(' '*' ')' as_clause
         {
                 // special case for COUNT(*), confirm it.
-            if( !EQUAL($1->string_value,"COUNT") )
+            if( !EQUAL($1->string_value, "COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "Syntax Error with %s(*).",
@@ -684,7 +689,8 @@ column_spec:
             swq_expr_node *poNode = new swq_expr_node();
             poNode->eNodeType = SNT_COLUMN;
             poNode->string_value = CPLStrdup( "*" );
-            poNode->table_index = poNode->field_index = -1;
+            poNode->table_index = -1;
+            poNode->field_index = -1;
 
             swq_expr_node *count = new swq_expr_node( (swq_op)SWQ_COUNT );
             count->PushSubExpression( poNode );
@@ -702,10 +708,11 @@ column_spec:
     | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')'
         {
                 // special case for COUNT(DISTINCT x), confirm it.
-            if( !EQUAL($1->string_value,"COUNT") )
+            if( !EQUAL($1->string_value, "COUNT") )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                        "DISTINCT keyword can only be used in COUNT() operator." );
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "DISTINCT keyword can only be used in COUNT() operator." );
                 delete $1;
                 delete $4;
                     YYERROR;
@@ -726,7 +733,7 @@ column_spec:
     | SWQT_IDENTIFIER '(' SWQT_DISTINCT field_value ')' as_clause
         {
             // special case for COUNT(DISTINCT x), confirm it.
-            if( !EQUAL($1->string_value,"COUNT") )
+            if( !EQUAL($1->string_value, "COUNT") )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                         "DISTINCT keyword can only be used in COUNT() operator." );
@@ -760,7 +767,6 @@ as_clause:
 
     | SWQT_IDENTIFIER
 
-
 opt_where:
     | SWQT_WHERE value_expr
         {
@@ -779,7 +785,7 @@ opt_joins:
             context->poCurSelect->PushJoin( static_cast<int>($3->int_value),
                                             $5 );
             delete $3;
-	    }
+        }
 
 opt_order_by:
     | SWQT_ORDER SWQT_BY sort_spec_list
@@ -808,12 +814,28 @@ sort_spec:
             $1 = NULL;
         }
 
+opt_limit:
+    | SWQT_LIMIT SWQT_INTEGER_NUMBER
+    {
+        context->poCurSelect->SetLimit( $2->int_value );
+        delete $2;
+        $2 = NULL;
+    }
+
+opt_offset:
+    | SWQT_OFFSET SWQT_INTEGER_NUMBER
+    {
+        context->poCurSelect->SetOffset( $2->int_value );
+        delete $2;
+        $2 = NULL;
+    }
+
 table_def:
     SWQT_IDENTIFIER
     {
-        int iTable;
-        iTable =context->poCurSelect->PushTableDef( NULL, $1->string_value,
-                                                    NULL );
+        const int iTable =
+            context->poCurSelect->PushTableDef( NULL, $1->string_value,
+                                                NULL );
         delete $1;
 
         $$ = new swq_expr_node( iTable );
@@ -821,9 +843,9 @@ table_def:
 
     | SWQT_IDENTIFIER as_clause
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( NULL, $1->string_value,
-                                                     $2->string_value );
+        const int iTable =
+            context->poCurSelect->PushTableDef( NULL, $1->string_value,
+                                                $2->string_value );
         delete $1;
         delete $2;
 
@@ -832,9 +854,9 @@ table_def:
 
     | SWQT_STRING '.' SWQT_IDENTIFIER
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( $1->string_value,
-                                                     $3->string_value, NULL );
+        const int iTable =
+            context->poCurSelect->PushTableDef( $1->string_value,
+                                                $3->string_value, NULL );
         delete $1;
         delete $3;
 
@@ -843,10 +865,10 @@ table_def:
 
     | SWQT_STRING '.' SWQT_IDENTIFIER as_clause
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( $1->string_value,
-                                                     $3->string_value,
-                                                     $4->string_value );
+        const int iTable =
+            context->poCurSelect->PushTableDef( $1->string_value,
+                                                $3->string_value,
+                                                $4->string_value );
         delete $1;
         delete $3;
         delete $4;
@@ -856,9 +878,9 @@ table_def:
 
     | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( $1->string_value,
-                                                     $3->string_value, NULL );
+        const int iTable =
+            context->poCurSelect->PushTableDef( $1->string_value,
+                                                $3->string_value, NULL );
         delete $1;
         delete $3;
 
@@ -867,10 +889,10 @@ table_def:
 
     | SWQT_IDENTIFIER '.' SWQT_IDENTIFIER as_clause
     {
-        int iTable;
-        iTable = context->poCurSelect->PushTableDef( $1->string_value,
-                                                     $3->string_value,
-                                                     $4->string_value );
+        const int iTable =
+            context->poCurSelect->PushTableDef( $1->string_value,
+                                                $3->string_value,
+                                                $4->string_value );
         delete $1;
         delete $3;
         delete $4;
diff --git a/ogr/swq_select.cpp b/ogr/swq_select.cpp
index df3606a..b3689f7 100644
--- a/ogr/swq_select.cpp
+++ b/ogr/swq_select.cpp
@@ -27,10 +27,23 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "swq.h"
-#include "swq_parser.hpp"
+
+#include <cstdio>
+#include <cstring>
+#include <string>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+#include "ogr_core.h"
 #include "ogr_geometry.h"
+#include "swq_parser.hpp"
 
+CPL_CVSID("$Id: swq_select.cpp 37576 2017-03-03 14:29:55Z rouault $");
+
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                             swq_select()                             */
 /************************************************************************/
@@ -40,7 +53,6 @@ swq_select::swq_select() :
     raw_select(NULL),
     result_columns(0),
     column_defs(NULL),
-    column_summary(NULL),
     table_count(0),
     table_defs(NULL),
     join_count(0),
@@ -48,8 +60,10 @@ swq_select::swq_select() :
     where_expr(NULL),
     order_specs(0),
     order_defs(NULL),
+    limit(-1),
+    offset(0),
     poOtherSelect(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                            ~swq_select()                             */
@@ -69,8 +83,7 @@ swq_select::~swq_select()
         CPLFree( table_def->table_name );
         CPLFree( table_def->table_alias );
     }
-    if( table_defs != NULL )
-        CPLFree( table_defs );
+    CPLFree( table_defs );
 
     for( int i = 0; i < result_columns; i++ )
     {
@@ -79,21 +92,10 @@ swq_select::~swq_select()
         CPLFree( column_defs[i].field_alias );
 
         delete column_defs[i].expr;
-
-        if( column_summary != NULL
-            && column_summary[i].distinct_list != NULL )
-        {
-            for( int j = 0; j < column_summary[i].count; j++ )
-                CPLFree( column_summary[i].distinct_list[j] );
-
-            CPLFree( column_summary[i].distinct_list );
-        }
     }
 
     CPLFree( column_defs );
 
-    CPLFree( column_summary );
-
     for( int i = 0; i < order_specs; i++ )
     {
         CPLFree( order_defs[i].table_name );
@@ -157,16 +159,18 @@ void swq_select::postpreparse()
 /* -------------------------------------------------------------------- */
 /*      Reorder the joins in the order they appear in the SQL string.   */
 /* -------------------------------------------------------------------- */
-    for(int i = 0; i < join_count / 2; i++)
+    for( int i = 0; i < join_count / 2; i++ )
     {
         swq_join_def sTmp;
         memcpy(&sTmp, &join_defs[i], sizeof(swq_join_def));
-        memcpy(&join_defs[i], &join_defs[join_count - 1 - i], sizeof(swq_join_def));
+        memcpy(&join_defs[i],
+               &join_defs[join_count - 1 - i],
+               sizeof(swq_join_def));
         memcpy(&join_defs[join_count - 1 - i], &sTmp, sizeof(swq_join_def));
     }
 
-    /* We make that strong assumption in ogr_gensql */
-    for(int i = 0; i < join_count; i++)
+    // We make that strong assumption in ogr_gensql.
+    for( int i = 0; i < join_count; i++ )
     {
         CPLAssert(join_defs[i].secondary_table == i + 1);
     }
@@ -340,7 +344,8 @@ char* swq_select::Unparse()
             if( (def->field_alias == NULL || table_count > 1) &&
                 def->table_name != NULL && def->table_name[0] != '\0' )
             {
-                osSelect += swq_expr_node::QuoteIfNecessary(def->table_name, '"');
+                osSelect +=
+                    swq_expr_node::QuoteIfNecessary(def->table_name, '"');
                 osSelect += ".";
             }
             osSelect += swq_expr_node::QuoteIfNecessary(def->field_name, '"');
@@ -369,7 +374,8 @@ char* swq_select::Unparse()
         strcmp(table_defs[0].table_name, table_defs[0].table_alias) != 0 )
     {
         osSelect += " AS ";
-        osSelect += swq_expr_node::QuoteIfNecessary(table_defs[0].table_alias, '"');
+        osSelect +=
+            swq_expr_node::QuoteIfNecessary(table_defs[0].table_alias, '"');
     }
 
     for( int i = 0; i < join_count; i++ )
@@ -382,12 +388,15 @@ char* swq_select::Unparse()
             osSelect += table_defs[iTable].data_source;
             osSelect += "'.";
         }
-        osSelect += swq_expr_node::QuoteIfNecessary(table_defs[iTable].table_name, '"');
+        osSelect +=
+            swq_expr_node::QuoteIfNecessary(table_defs[iTable].table_name, '"');
         if( table_defs[iTable].table_alias != NULL &&
-            strcmp(table_defs[iTable].table_name, table_defs[iTable].table_alias) != 0 )
+            strcmp(table_defs[iTable].table_name,
+                   table_defs[iTable].table_alias) != 0 )
         {
             osSelect += " AS ";
-            osSelect += swq_expr_node::QuoteIfNecessary(table_defs[iTable].table_alias, '"');
+            osSelect += swq_expr_node::QuoteIfNecessary(
+                table_defs[iTable].table_alias, '"');
         }
         osSelect += " ON ";
         char* pszTmp = join_defs[i].poExpr->Unparse(NULL, '"');
@@ -406,7 +415,8 @@ char* swq_select::Unparse()
     for( int i = 0; i < order_specs; i++ )
     {
         osSelect += " ORDER BY ";
-        osSelect += swq_expr_node::QuoteIfNecessary(order_defs[i].field_name, '"');
+        osSelect +=
+            swq_expr_node::QuoteIfNecessary(order_defs[i].field_name, '"');
         if( !order_defs[i].ascending_flag )
             osSelect += " DESC";
     }
@@ -426,7 +436,9 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
 {
     if( query_mode == SWQM_DISTINCT_LIST && distinct_flag )
     {
-        CPLError(CE_Failure, CPLE_NotSupported, "SELECT DISTINCT and COUNT(DISTINCT...) not supported together");
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "SELECT DISTINCT and COUNT(DISTINCT...) "
+                 "not supported together");
         return FALSE;
     }
 
@@ -435,8 +447,8 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
 /* -------------------------------------------------------------------- */
     result_columns++;
 
-    column_defs = (swq_col_def *)
-        CPLRealloc( column_defs, sizeof(swq_col_def) * result_columns );
+    column_defs = static_cast<swq_col_def *>(
+        CPLRealloc(column_defs, sizeof(swq_col_def) * result_columns));
 
     swq_col_def *col_def = column_defs + result_columns - 1;
 
@@ -507,50 +519,50 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
         const char *pszTypeName = poExpr->papoSubExpr[1]->string_value;
         int parse_precision = 0;
 
-        if( EQUAL(pszTypeName,"character") )
+        if( EQUAL(pszTypeName, "character") )
         {
             col_def->target_type = SWQ_STRING;
             col_def->field_length = 1;
         }
-        else if( strcasecmp(pszTypeName,"boolean") == 0 )
+        else if( strcasecmp(pszTypeName, "boolean") == 0 )
         {
             col_def->target_type = SWQ_BOOLEAN;
         }
-        else if( strcasecmp(pszTypeName,"integer") == 0 )
+        else if( strcasecmp(pszTypeName, "integer") == 0 )
         {
             col_def->target_type = SWQ_INTEGER;
         }
-        else if( strcasecmp(pszTypeName,"bigint") == 0 )
+        else if( strcasecmp(pszTypeName, "bigint") == 0 )
         {
             col_def->target_type = SWQ_INTEGER64;
         }
-        else if( strcasecmp(pszTypeName,"smallint") == 0 )
+        else if( strcasecmp(pszTypeName, "smallint") == 0 )
         {
             col_def->target_type = SWQ_INTEGER;
             col_def->target_subtype = OFSTInt16;
         }
-        else if( strcasecmp(pszTypeName,"float") == 0 )
+        else if( strcasecmp(pszTypeName, "float") == 0 )
         {
             col_def->target_type = SWQ_FLOAT;
         }
-        else if( strcasecmp(pszTypeName,"numeric") == 0 )
+        else if( strcasecmp(pszTypeName, "numeric") == 0 )
         {
             col_def->target_type = SWQ_FLOAT;
             parse_precision = 1;
         }
-        else if( strcasecmp(pszTypeName,"timestamp") == 0 )
+        else if( strcasecmp(pszTypeName, "timestamp") == 0 )
         {
             col_def->target_type = SWQ_TIMESTAMP;
         }
-        else if( strcasecmp(pszTypeName,"date") == 0 )
+        else if( strcasecmp(pszTypeName, "date") == 0 )
         {
             col_def->target_type = SWQ_DATE;
         }
-        else if( strcasecmp(pszTypeName,"time") == 0 )
+        else if( strcasecmp(pszTypeName, "time") == 0 )
         {
             col_def->target_type = SWQ_TIME;
         }
-        else if( strcasecmp(pszTypeName,"geometry") == 0 )
+        else if( strcasecmp(pszTypeName, "geometry") == 0 )
         {
             col_def->target_type = SWQ_GEOMETRY;
         }
@@ -575,8 +587,9 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
             {
                 if( poExpr->papoSubExpr[2]->field_type != SWQ_STRING )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                      "First argument of CAST operator should be an geometry type identifier." );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "First argument of CAST operator should be "
+                             "a geometry type identifier.");
                     CPLFree(col_def->table_name);
                     col_def->table_name = NULL;
                     CPLFree(col_def->field_name);
@@ -593,7 +606,8 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
                 // SRID
                 if( poExpr->nSubExprCount > 3 )
                 {
-                    col_def->nSRID = (int)poExpr->papoSubExpr[3]->int_value;
+                    col_def->nSRID =
+                        static_cast<int>(poExpr->papoSubExpr[3]->int_value);
                 }
             }
         }
@@ -604,8 +618,9 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
             {
                 if( poExpr->papoSubExpr[2]->field_type != SWQ_INTEGER )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                      "First argument of CAST operator should be of integer type." );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "First argument of CAST operator should be of "
+                             "integer type." );
                     CPLFree(col_def->table_name);
                     col_def->table_name = NULL;
                     CPLFree(col_def->field_name);
@@ -615,13 +630,15 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
                     result_columns--;
                     return FALSE;
                 }
-                col_def->field_length = (int)poExpr->papoSubExpr[2]->int_value;
+                col_def->field_length =
+                    static_cast<int>(poExpr->papoSubExpr[2]->int_value);
             }
 
             // field width.
             if( poExpr->nSubExprCount > 3 && parse_precision )
             {
-                col_def->field_precision = (int)poExpr->papoSubExpr[3]->int_value;
+                col_def->field_precision =
+                    static_cast<int>(poExpr->papoSubExpr[3]->int_value);
                 if( col_def->field_precision == 0 )
                 {
                     if( col_def->field_length < 10 )
@@ -644,9 +661,10 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
         {
             const swq_operation *poOp =
                     swq_op_registrar::GetOperator( (swq_op)poExpr->nOperation );
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Column Summary Function '%s' has wrong number of arguments.",
-                      poOp->pszName );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Column Summary Function '%s' has "
+                     "wrong number of arguments.",
+                     poOp->pszName);
             CPLFree(col_def->table_name);
             col_def->table_name = NULL;
             CPLFree(col_def->field_name);
@@ -660,9 +678,10 @@ int swq_select::PushField( swq_expr_node *poExpr, const char *pszAlias,
         {
             const swq_operation *poOp =
                     swq_op_registrar::GetOperator( (swq_op)poExpr->nOperation );
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Argument of column Summary Function '%s' should be a column.",
-                      poOp->pszName );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Argument of column Summary Function '%s' "
+                     "should be a column.",
+                     poOp->pszName);
             CPLFree(col_def->table_name);
             col_def->table_name = NULL;
             CPLFree(col_def->field_name);
@@ -703,8 +722,8 @@ int swq_select::PushTableDef( const char *pszDataSource,
 {
     table_count++;
 
-    table_defs = (swq_table_def *)
-        CPLRealloc( table_defs, sizeof(swq_table_def) * table_count );
+    table_defs = static_cast<swq_table_def *>(
+        CPLRealloc(table_defs, sizeof(swq_table_def) * table_count));
 
     if( pszDataSource != NULL )
         table_defs[table_count-1].data_source = CPLStrdup(pszDataSource);
@@ -725,14 +744,16 @@ int swq_select::PushTableDef( const char *pszDataSource,
 /*                            PushOrderBy()                             */
 /************************************************************************/
 
-void swq_select::PushOrderBy( const char* pszTableName, const char *pszFieldName, int bAscending )
+void swq_select::PushOrderBy( const char* pszTableName,
+                              const char *pszFieldName, int bAscending )
 
 {
     order_specs++;
-    order_defs = (swq_order_def *)
-        CPLRealloc( order_defs, sizeof(swq_order_def) * order_specs );
+    order_defs = static_cast<swq_order_def *>(
+        CPLRealloc(order_defs, sizeof(swq_order_def) * order_specs));
 
-    order_defs[order_specs-1].table_name = CPLStrdup(pszTableName ? pszTableName : "");
+    order_defs[order_specs-1].table_name =
+        CPLStrdup(pszTableName ? pszTableName : "");
     order_defs[order_specs-1].field_name = CPLStrdup(pszFieldName);
     order_defs[order_specs-1].table_index = -1;
     order_defs[order_specs-1].field_index = -1;
@@ -747,8 +768,8 @@ void swq_select::PushJoin( int iSecondaryTable, swq_expr_node* poExpr )
 
 {
     join_count++;
-    join_defs = (swq_join_def *)
-        CPLRealloc( join_defs, sizeof(swq_join_def) * join_count );
+    join_defs = static_cast<swq_join_def *>(
+        CPLRealloc(join_defs, sizeof(swq_join_def) * join_count));
 
     join_defs[join_count-1].secondary_table = iSecondaryTable;
     join_defs[join_count-1].poExpr = poExpr;
@@ -765,6 +786,26 @@ void swq_select::PushUnionAll( swq_select* poOtherSelectIn )
 }
 
 /************************************************************************/
+/*                             SetLimit()                               */
+/************************************************************************/
+
+void swq_select::SetLimit( GIntBig nLimit )
+
+{
+    limit = nLimit;
+}
+
+/************************************************************************/
+/*                            SetOffset()                               */
+/************************************************************************/
+
+void swq_select::SetOffset( GIntBig nOffset )
+
+{
+    offset = nOffset;
+}
+
+/************************************************************************/
 /*                          expand_wildcard()                           */
 /*                                                                      */
 /*      This function replaces the '*' in a "SELECT *" with the list    */
@@ -791,7 +832,7 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
             || src_fieldname[strlen(src_fieldname)-1] != '*' )
             continue;
 
-        /* We don't want to expand COUNT(*) */
+        // Don't want to expand COUNT(*).
         if( column_defs[isrc].col_func == SWQCF_COUNT )
             continue;
 
@@ -821,7 +862,7 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
                 return CE_Failure;
             }
 
-            /* count the number of fields in this table. */
+            // Count the number of fields in this table.
             new_fields = 0;
             for( int i = 0; i < field_list->count; i++ )
             {
@@ -830,7 +871,7 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
             }
         }
 
-        if (new_fields > 0)
+        if( new_fields > 0 )
         {
 /* -------------------------------------------------------------------- */
 /*      Reallocate the column list larger.                              */
@@ -839,16 +880,16 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
             CPLFree( column_defs[isrc].field_name );
             delete column_defs[isrc].expr;
 
-            column_defs = (swq_col_def *)
-                CPLRealloc( column_defs,
-                            sizeof(swq_col_def) *
-                            (result_columns + new_fields - 1 ) );
+            column_defs = static_cast<swq_col_def *>(
+                CPLRealloc(column_defs,
+                           sizeof(swq_col_def) *
+                           (result_columns + new_fields - 1)));
 
 /* -------------------------------------------------------------------- */
 /*      Push the old definitions that came after the one to be          */
 /*      replaced further up in the array.                               */
 /* -------------------------------------------------------------------- */
-            if (new_fields != 1)
+            if( new_fields != 1 )
             {
                 for( int i = result_columns-1; i > isrc; i-- )
                 {
@@ -879,7 +920,7 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
                      column_defs + isrc + 1,
                      sizeof( swq_col_def ) * (result_columns-1-isrc) );
 
-            result_columns --;
+            result_columns--;
         }
 
 /* -------------------------------------------------------------------- */
@@ -892,17 +933,17 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
             swq_col_def *def;
             int compose = (itable != -1) || bAlwaysPrefixWithTableName;
 
-            /* skip this field if it isn't in the target table.  */
+            // Skip this field if it isn't in the target table.
             if( itable != -1 && itable != field_list->table_ids[i] )
                 continue;
 
-            /* set up some default values. */
+            // Set up some default values.
             def = column_defs + iout;
             def->field_precision = -1;
             def->target_type = SWQ_OTHER;
             def->target_subtype = OFSTNone;
 
-            /* does this field duplicate an earlier one? */
+            // Does this field duplicate an earlier one?
             if( field_list->table_ids[i] != 0
                 && !compose )
             {
@@ -931,15 +972,15 @@ CPLErr swq_select::expand_wildcard( swq_field_list *field_list,
 
             iout++;
 
-            /* All the other table info will be provided by the later
-               parse operation. */
+            // All the other table info will be provided by the later
+            // parse operation.
         }
 
-        /* If there are several occurrences of '*', go on, but stay on the */
-        /* same index in case '*' is expanded to nothing */
-        /* (the -- is to compensate the fact that isrc will be incremented in */
-        /*  the after statement of the for loop) */
-        isrc --;
+        // If there are several occurrences of '*', go on, but stay on the
+        // same index in case '*' is expanded to nothing.
+        // The -- is to compensate the fact that isrc will be incremented in
+        // the after statement of the for loop.
+        isrc--;
     }
 
     return CE_None;
@@ -964,13 +1005,15 @@ static bool CheckCompatibleJoinExpr( swq_expr_node* poExpr,
         {
             if( poExpr->table_name )
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "Field %s.%s in JOIN clause does not correspond to the primary table nor the joint (secondary) table.",
-                        poExpr->table_name,
-                        poExpr->string_value );
+                          "Field %s.%s in JOIN clause does not correspond to "
+                          "the primary table nor the joint (secondary) table.",
+                          poExpr->table_name,
+                          poExpr->string_value );
             else
                 CPLError( CE_Failure, CPLE_AppDefined,
-                        "Field %s in JOIN clause does not correspond to the primary table nor the joint (secondary) table.",
-                        poExpr->string_value );
+                          "Field %s in JOIN clause does not correspond to the "
+                          "primary table nor the joint (secondary) table.",
+                          poExpr->string_value );
             return false;
         }
 
@@ -979,7 +1022,7 @@ static bool CheckCompatibleJoinExpr( swq_expr_node* poExpr,
 
     if( poExpr->eNodeType == SNT_OPERATION )
     {
-        for(int i=0;i<poExpr->nSubExprCount;i++)
+        for( int i = 0; i < poExpr->nSubExprCount; i++ )
         {
             if( !CheckCompatibleJoinExpr( poExpr->papoSubExpr[i],
                                           secondary_table,
@@ -1023,22 +1066,23 @@ CPLErr swq_select::parse( swq_field_list *field_list,
             def->field_index = -1;
             def->table_index = -1;
 
-            if( def->expr->Check( field_list, TRUE, FALSE, poCustomFuncRegistrar ) == SWQ_ERROR )
+            if( def->expr->Check( field_list, TRUE, FALSE,
+                                  poCustomFuncRegistrar ) == SWQ_ERROR )
                 return CE_Failure;
 
             def->field_type = def->expr->field_type;
         }
         else
         {
-            swq_field_type  this_type;
+            swq_field_type this_type;
 
-            /* identify field */
+            // Identify field.
             def->field_index = swq_identify_field( def->table_name,
                                                    def->field_name, field_list,
                                                    &this_type,
                                                    &(def->table_index) );
 
-            /* record field type */
+            // Record field type.
             def->field_type = this_type;
 
             if( def->field_index == -1 && def->col_func != SWQCF_COUNT )
@@ -1052,7 +1096,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
             }
         }
 
-        /* identify column function if present */
+        // Identify column function if present.
         if( (def->col_func == SWQCF_MIN
              || def->col_func == SWQCF_MAX
              || def->col_func == SWQCF_AVG
@@ -1060,7 +1104,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
             && (def->field_type == SWQ_STRING ||
                 def->field_type == SWQ_GEOMETRY) )
         {
-            // possibly this is already enforced by the checker?
+            // Possibly this is already enforced by the checker?
             const swq_operation *op = swq_op_registrar::GetOperator(
                 (swq_op) def->col_func );
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -1093,10 +1137,11 @@ CPLErr swq_select::parse( swq_field_list *field_list,
         swq_col_def *def = column_defs + i;
         int this_indicator = -1;
 
-        if( query_mode == SWQM_DISTINCT_LIST && def->field_type == SWQ_GEOMETRY )
+        if( query_mode == SWQM_DISTINCT_LIST &&
+            def->field_type == SWQ_GEOMETRY )
         {
-            int bAllowDistinctOnGeometryField = (
-                    poParseOptions && poParseOptions->bAllowDistinctOnGeometryField );
+            const bool bAllowDistinctOnGeometryField =
+                poParseOptions && poParseOptions->bAllowDistinctOnGeometryField;
             if( !bAllowDistinctOnGeometryField )
             {
                 CPLError( CE_Failure, CPLE_NotSupported,
@@ -1116,8 +1161,8 @@ CPLErr swq_select::parse( swq_field_list *field_list,
                 def->distinct_flag &&
                 def->field_type == SWQ_GEOMETRY )
             {
-                CPLError( CE_Failure, CPLE_AppDefined,
-                          "SELECT COUNT DISTINCT on a geometry not supported." );
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "SELECT COUNT DISTINCT on a geometry not supported.");
                 return CE_Failure;
             }
         }
@@ -1136,8 +1181,9 @@ CPLErr swq_select::parse( swq_field_list *field_list,
              && this_indicator != -1
             && query_mode != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Field list implies mixture of regular recordset mode, summary mode or distinct field list mode." );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Field list implies mixture of regular recordset mode, "
+                     "summary mode or distinct field list mode.");
             return CE_Failure;
         }
 
@@ -1145,7 +1191,7 @@ CPLErr swq_select::parse( swq_field_list *field_list,
             query_mode = this_indicator;
     }
 
-    if (result_columns == 0)
+    if( result_columns == 0 )
     {
         query_mode = SWQM_RECORDSET;
     }
@@ -1156,9 +1202,11 @@ CPLErr swq_select::parse( swq_field_list *field_list,
     for( int i = 0; i < join_count; i++ )
     {
         swq_join_def *def = join_defs + i;
-        if( def->poExpr->Check( field_list, TRUE, TRUE, poCustomFuncRegistrar ) == SWQ_ERROR )
+        if( def->poExpr->Check(field_list, TRUE, TRUE,
+                               poCustomFuncRegistrar) == SWQ_ERROR )
             return CE_Failure;
-        if( !CheckCompatibleJoinExpr( def->poExpr, def->secondary_table, field_list ) )
+        if( !CheckCompatibleJoinExpr(def->poExpr, def->secondary_table,
+                                     field_list) )
             return CE_Failure;
     }
 
@@ -1169,11 +1217,11 @@ CPLErr swq_select::parse( swq_field_list *field_list,
     {
         swq_order_def *def = order_defs + i;
 
-        /* identify field */
+        // Identify field.
         swq_field_type field_type;
-        def->field_index = swq_identify_field( def->table_name,
-                                               def->field_name, field_list,
-                                               &field_type, &(def->table_index) );
+        def->field_index = swq_identify_field(def->table_name,
+                                              def->field_name, field_list,
+                                              &field_type, &(def->table_index));
         if( def->field_index == -1 )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
@@ -1186,16 +1234,17 @@ CPLErr swq_select::parse( swq_field_list *field_list,
 
         if( def->table_index != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Cannot use field '%s' of a secondary table in a ORDER BY clause",
-                      def->field_name );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot use field '%s' of a secondary table in "
+                     "an ORDER BY clause",
+                     def->field_name );
             return CE_Failure;
         }
 
         if( field_type == SWQ_GEOMETRY )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Cannot use geometry field '%s' in a ORDER BY clause",
+                      "Cannot use geometry field '%s' in an ORDER BY clause",
                       def->field_name );
             return CE_Failure;
         }
@@ -1207,12 +1256,15 @@ CPLErr swq_select::parse( swq_field_list *field_list,
 /* -------------------------------------------------------------------- */
     int bAllowFieldsInSecondaryTablesInWhere = FALSE;
     if( poParseOptions != NULL )
-        bAllowFieldsInSecondaryTablesInWhere = poParseOptions->bAllowFieldsInSecondaryTablesInWhere;
+        bAllowFieldsInSecondaryTablesInWhere =
+            poParseOptions->bAllowFieldsInSecondaryTablesInWhere;
     if( where_expr != NULL
-        && where_expr->Check( field_list, bAllowFieldsInSecondaryTablesInWhere, FALSE, poCustomFuncRegistrar ) == SWQ_ERROR )
+        && where_expr->Check(field_list, bAllowFieldsInSecondaryTablesInWhere,
+                             FALSE, poCustomFuncRegistrar) == SWQ_ERROR )
     {
         return CE_Failure;
     }
 
     return CE_None;
 }
+//! @endcond
diff --git a/port/GNUmakefile b/port/GNUmakefile
index 53f10b8..4496639 100644
--- a/port/GNUmakefile
+++ b/port/GNUmakefile
@@ -13,7 +13,7 @@ else
 XTRA_OPT =
 endif
 
-CPPFLAGS	:= $(CPPFLAGS)	$(CURL_INC) $(XTRA_OPT)
+CPPFLAGS	:= $(CPPFLAGS)	$(CURL_INC) $(XTRA_OPT) -DINST_DATA=\"$(INST_DATA)\"
 
 OBJ =	cpl_conv.o cpl_error.o cpl_string.o cplgetsymbol.o cplstringlist.o \
 	cpl_strtod.o cpl_path.o cpl_csv.o cpl_findfile.o cpl_minixml.o \
@@ -27,7 +27,8 @@ OBJ =	cpl_conv.o cpl_error.o cpl_string.o cplgetsymbol.o cplstringlist.o \
 	cpl_base64.o cpl_vsil_curl.o cpl_vsil_curl_streaming.o \
 	cpl_vsil_cache.o cpl_xml_validate.o cpl_spawn.o \
 	cpl_google_oauth2.o cpl_progress.o cpl_virtualmem.o cpl_worker_thread_pool.o \
-	cpl_vsil_crypt.o cpl_sha256.o cpl_aws.o cpl_vsi_error.o
+	cpl_vsil_crypt.o cpl_sha1.o cpl_sha256.o cpl_aws.o cpl_vsi_error.o cpl_cpu_features.o \
+	cpl_google_cloud.o
 
 ifeq ($(ODBC_SETTING),yes)
 OBJ	:= 	$(OBJ) cpl_odbc.o
diff --git a/port/cpl_atomic_ops.cpp b/port/cpl_atomic_ops.cpp
index 089d1a6..5221144 100644
--- a/port/cpl_atomic_ops.cpp
+++ b/port/cpl_atomic_ops.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_atomic_ops.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Name:     cpl_atomic_ops.cpp
  * Project:  CPL - Common Portability Library
@@ -30,23 +29,27 @@
 
 #include "cpl_atomic_ops.h"
 
+#include "cpl_config.h"
+
 // TODO: If C++11, use #include <atomic>.
 
+CPL_CVSID("$Id: cpl_atomic_ops.cpp 36840 2016-12-13 05:21:52Z goatbar $");
+
 #if defined(__MACH__) && defined(__APPLE__)
 
 #include <libkern/OSAtomic.h>
 
 int CPLAtomicAdd(volatile int* ptr, int increment)
 {
-  return OSAtomicAdd32(increment, (int*)(ptr));
+    return OSAtomicAdd32(increment, (int*)(ptr));
 }
 
 int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
 {
-  return OSAtomicCompareAndSwap32(oldval, newval, (int*)(ptr));
+    return OSAtomicCompareAndSwap32(oldval, newval, (int*)(ptr));
 }
 
-#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+#elif defined(_MSC_VER)
 
 #include <windows.h>
 
@@ -55,13 +58,15 @@ int CPLAtomicAdd(volatile int* ptr, int increment)
 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
   return InterlockedExchangeAdd((LONG*)(ptr), (LONG)(increment)) + increment;
 #else
-  return InterlockedExchangeAdd((volatile LONG*)(ptr), (LONG)(increment)) + increment;
+  return InterlockedExchangeAdd((volatile LONG*)(ptr),
+                                (LONG)(increment)) + increment;
 #endif
 }
 
 int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
 {
-  return (LONG)InterlockedCompareExchange((volatile LONG*)(ptr), (LONG)newval, (LONG)oldval) == (LONG)oldval;
+  return (LONG)InterlockedCompareExchange((volatile LONG*)(ptr), (LONG)newval,
+                                          (LONG)oldval) == (LONG)oldval;
 }
 
 #elif defined(__MINGW32__) && defined(__i386__)
@@ -75,7 +80,8 @@ int CPLAtomicAdd(volatile int* ptr, int increment)
 
 int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
 {
-  return (LONG)InterlockedCompareExchange((LONG*)(ptr), (LONG)newval, (LONG)oldval) == (LONG)oldval;
+  return (LONG)InterlockedCompareExchange((LONG*)(ptr), (LONG)newval,
+                                          (LONG)oldval) == (LONG)oldval;
 }
 
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
@@ -100,24 +106,25 @@ int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
     : "r" (newval), "m" (*ptr), "a" (oldval)
     : "memory");
 
-    return (int) ret;
+    return static_cast<int>(ret);
 }
 
 #elif defined(HAVE_GCC_ATOMIC_BUILTINS)
-/* Starting with GCC 4.1.0, built-in functions for atomic memory access are provided. */
-/* see http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html */
-/* We use a ./configure test to determine whether this builtins are available */
-/* as it appears that the GCC 4.1 version used on debian etch is broken when linking */
-/* such instructions... */
-int CPLAtomicAdd(volatile int* ptr, int increment)
+// Starting with GCC 4.1.0, built-in functions for atomic memory access are
+// provided.  See:
+//   http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html
+// We use a ./configure test to determine whether this builtins are available.
+// as it appears that the GCC 4.1 version used on debian etch is broken when
+// linking such instructions.
+int CPLAtomicAdd( volatile int* ptr, int increment )
 {
-  if (increment > 0)
+  if( increment > 0 )
     return __sync_add_and_fetch(ptr, increment);
 
   return __sync_sub_and_fetch(ptr, -increment);
 }
 
-int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
+int CPLAtomicCompareAndExchange( volatile int* ptr, int oldval, int newval )
 {
     return __sync_bool_compare_and_swap (ptr, oldval, newval);
 }
@@ -125,14 +132,14 @@ int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
 #elif !defined(CPL_MULTIPROC_PTHREAD)
 #warning "Needs real lock API to implement properly atomic increment"
 
-/* Dummy implementation */
+// Dummy implementation.
 int CPLAtomicAdd(volatile int* ptr, int increment)
 {
     (*ptr) += increment;
     return *ptr;
 }
 
-int CPLAtomicCompareAndExchange(volatile int* ptr, int oldval, int newval)
+int CPLAtomicCompareAndExchange( volatile int* ptr, int oldval, int newval )
 {
     if( *ptr == oldval )
     {
diff --git a/port/cpl_atomic_ops.h b/port/cpl_atomic_ops.h
index 6a07d2c..6899926 100644
--- a/port/cpl_atomic_ops.h
+++ b/port/cpl_atomic_ops.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_atomic_ops.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cpl_atomic_ops.h 35921 2016-10-25 02:28:29Z goatbar $
  *
  * Name:     cpl_atomic_ops.h
  * Project:  CPL - Common Portability Library
@@ -51,7 +51,7 @@ CPL_C_START
   * supported by GCC 4.1 or higher. For other platforms supporting
   * the pthread library, and when GDAL is configured with thread-support,
   * the atomicity will be done with a mutex, but with
-  * reduced efficiently. For the remaining platforms, a simple addition
+  * reduced efficiency. For the remaining platforms, a simple addition
   * with no locking will be done...
   *
   * @param ptr a pointer to an integer to increment
@@ -82,7 +82,6 @@ int CPL_DLL CPLAtomicAdd(volatile int* ptr, int increment);
   */
 #define CPLAtomicDec(ptr) CPLAtomicAdd(ptr, -1)
 
-
 /** Compares *ptr with oldval. If *ptr == oldval, then *ptr is assigned
   * newval and TRUE is returned. Otherwise nothing is done, and FALSE is returned.
   *
@@ -91,8 +90,8 @@ int CPL_DLL CPLAtomicAdd(volatile int* ptr, int increment);
   * supported by GCC 4.1 or higher. For other platforms supporting
   * the pthread library, and when GDAL is configured with thread-support,
   * the atomicity will be done with a mutex, but with
-  * reduced efficiently. For the remaining platforms, a simple addition
-  * with no locking will be done...
+  * reduced efficiency. For the remaining platforms, a simple compare and
+  * exchange with no locking will be done...
   *
   * @param ptr a pointer to an integer (aligned on 32bit boundary).
   * @param oldval old value
diff --git a/port/cpl_aws.cpp b/port/cpl_aws.cpp
index 75e203d..e66a61b 100644
--- a/port/cpl_aws.cpp
+++ b/port/cpl_aws.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_aws.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Name:     cpl_aws.cpp
  * Project:  CPL - Common Portability Library
@@ -28,6 +27,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+//! @cond Doxygen_Suppress
+
 #include "cpl_aws.h"
 #include "cpl_vsi_error.h"
 #include "cpl_sha256.h"
@@ -35,9 +36,9 @@
 #include "cpl_minixml.h"
 #include <algorithm>
 
-CPL_CVSID("$Id: cpl_aws.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: cpl_aws.cpp 37174 2017-01-18 20:00:36Z rouault $");
 
-//#define DEBUG_VERBOSE 1
+// #define DEBUG_VERBOSE 1
 
 /************************************************************************/
 /*                         CPLGetLowerCaseHex()                         */
@@ -69,8 +70,8 @@ static CPLString CPLGetLowerCaseHex( const GByte *pabyData, size_t nBytes )
 
 CPLString CPLGetLowerCaseHexSHA256( const void *pabyData, size_t nBytes )
 {
-    GByte hash[CPL_SHA256_HASH_SIZE];
-    CPL_SHA256((const GByte*)pabyData, nBytes, hash);
+    GByte hash[CPL_SHA256_HASH_SIZE] = {};
+    CPL_SHA256(static_cast<const GByte *>(pabyData), nBytes, hash);
     return CPLGetLowerCaseHex(hash, CPL_SHA256_HASH_SIZE);
 }
 
@@ -87,18 +88,19 @@ CPLString CPLGetLowerCaseHexSHA256( const CPLString& osStr )
 /*                       CPLAWSURLEncode()                              */
 /************************************************************************/
 
-CPLString CPLAWSURLEncode(const CPLString& osURL, bool bEncodeSlash)
+CPLString CPLAWSURLEncode( const CPLString& osURL, bool bEncodeSlash )
 {
     CPLString osRet;
     for( size_t i = 0; i < osURL.size(); i++ )
     {
         char ch = osURL[i];
-        if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
-            (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.')
+        if( (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') ||
+            (ch >= '0' && ch <= '9') ||
+            ch == '_' || ch == '-' || ch == '~' || ch == '.' )
         {
             osRet += ch;
         }
-        else if (ch == '/')
+        else if( ch == '/' )
         {
             if( bEncodeSlash )
                 osRet += "%2F";
@@ -117,40 +119,42 @@ CPLString CPLAWSURLEncode(const CPLString& osURL, bool bEncodeSlash)
 /*                CPLGetAWS_SIGN4_Authorization()                       */
 /************************************************************************/
 
-/* See http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html */
-CPLString CPLGetAWS_SIGN4_Authorization(const CPLString& osSecretAccessKey,
-                                           const CPLString& osAccessKeyId,
-                                           const CPLString& osAccessToken,
-                                           const CPLString& osAWSRegion,
-                                           const CPLString& osService,
-                                           const CPLString& osVerb,
-                                           const CPLString& osHost,
-                                           const CPLString& osCanonicalURI,
-                                           const CPLString& osCanonicalQueryString,
-                                           const CPLString& osXAMZContentSHA256,
-                                           const CPLString& osTimestamp)
+// See:
+// http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
+CPLString
+CPLGetAWS_SIGN4_Authorization( const CPLString& osSecretAccessKey,
+                               const CPLString& osAccessKeyId,
+                               const CPLString& osAccessToken,
+                               const CPLString& osAWSRegion,
+                               const CPLString& osRequestPayer,
+                               const CPLString& osService,
+                               const CPLString& osVerb,
+                               const CPLString& osHost,
+                               const CPLString& osCanonicalURI,
+                               const CPLString& osCanonicalQueryString,
+                               const CPLString& osXAMZContentSHA256,
+                               const CPLString& osTimestamp )
 {
 /* -------------------------------------------------------------------- */
 /*      Compute canonical request string.                               */
 /* -------------------------------------------------------------------- */
-    CPLString osCanonicalRequest;
-    osCanonicalRequest = osVerb + "\n";
+    CPLString osCanonicalRequest = osVerb + "\n";
 
     osCanonicalRequest += osCanonicalURI + "\n";
 
     osCanonicalRequest += osCanonicalQueryString + "\n";
 
-    CPLString osCanonicalHeaders;
-    osCanonicalHeaders += "host:";
-    osCanonicalHeaders += osHost;
-    osCanonicalHeaders += "\n";
-    osCanonicalHeaders += "x-amz-content-sha256:";
-    osCanonicalHeaders += osXAMZContentSHA256;
-    osCanonicalHeaders += "\n";
-    osCanonicalHeaders += "x-amz-date:";
-    osCanonicalHeaders += osTimestamp;
-    osCanonicalHeaders += "\n";
-    if( osAccessToken.size() )
+    CPLString osCanonicalHeaders =
+        "host:" + osHost + "\n" +
+        "x-amz-content-sha256:" + osXAMZContentSHA256 + "\n" +
+        "x-amz-date:" + osTimestamp + "\n";
+    if( !osRequestPayer.empty() )
+    {
+        osCanonicalHeaders += "x-amz-request-payer:";
+        osCanonicalHeaders += osRequestPayer;
+        osCanonicalHeaders += "\n";
+    }
+    if( !osAccessToken.empty() )
     {
         osCanonicalHeaders += "x-amz-security-token:";
         osCanonicalHeaders += osAccessToken;
@@ -160,14 +164,16 @@ CPLString CPLGetAWS_SIGN4_Authorization(const CPLString& osSecretAccessKey,
     osCanonicalRequest += osCanonicalHeaders + "\n";
 
     CPLString osSignedHeaders = "host;x-amz-content-sha256;x-amz-date";
-    if( osAccessToken.size() )
+    if( !osRequestPayer.empty() )
+        osSignedHeaders += ";x-amz-request-payer";
+    if( !osAccessToken.empty() )
         osSignedHeaders += ";x-amz-security-token";
     osCanonicalRequest += osSignedHeaders + "\n";
 
     osCanonicalRequest += osXAMZContentSHA256;
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("S3", "osCanonicalRequest='%s'\n", osCanonicalRequest.c_str());
+    CPLDebug("S3", "osCanonicalRequest='%s'", osCanonicalRequest.c_str());
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -188,14 +194,14 @@ CPLString CPLGetAWS_SIGN4_Authorization(const CPLString& osSecretAccessKey,
     osStringToSign += CPLGetLowerCaseHexSHA256(osCanonicalRequest);
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("S3", "osStringToSign='%s'\n", osStringToSign.c_str());
+    CPLDebug("S3", "osStringToSign='%s'", osStringToSign.c_str());
 #endif
 
 /* -------------------------------------------------------------------- */
 /*      Compute signing key.                                            */
 /* -------------------------------------------------------------------- */
-    GByte abySigningKeyIn[CPL_SHA256_HASH_SIZE];
-    GByte abySigningKeyOut[CPL_SHA256_HASH_SIZE];
+    GByte abySigningKeyIn[CPL_SHA256_HASH_SIZE] = {};
+    GByte abySigningKeyOut[CPL_SHA256_HASH_SIZE] = {};
 
     CPLString osFirstKey(CPLString("AWS4") + osSecretAccessKey);
     CPL_HMAC_SHA256( osFirstKey.c_str(), osFirstKey.size(),
@@ -219,21 +225,23 @@ CPLString CPLGetAWS_SIGN4_Authorization(const CPLString& osSecretAccessKey,
     memcpy(abySigningKeyIn, abySigningKeyOut, CPL_SHA256_HASH_SIZE);
 
 #ifdef DEBUG_VERBOSE
-    CPLString osSigningKey(CPLGetLowerCaseHex(abySigningKeyIn, CPL_SHA256_HASH_SIZE));
-    CPLDebug("S3", "osSigningKey='%s'\n", osSigningKey.c_str());
+    CPLString osSigningKey(CPLGetLowerCaseHex(abySigningKeyIn,
+                                              CPL_SHA256_HASH_SIZE));
+    CPLDebug("S3", "osSigningKey='%s'", osSigningKey.c_str());
 #endif
 
 /* -------------------------------------------------------------------- */
 /*      Compute signature.                                              */
 /* -------------------------------------------------------------------- */
-    GByte abySignature[CPL_SHA256_HASH_SIZE];
+    GByte abySignature[CPL_SHA256_HASH_SIZE] = {};
     CPL_HMAC_SHA256( abySigningKeyIn, CPL_SHA256_HASH_SIZE,
                      osStringToSign, osStringToSign.size(),
                      abySignature);
-    CPLString osSignature(CPLGetLowerCaseHex(abySignature, CPL_SHA256_HASH_SIZE));
+    CPLString osSignature(CPLGetLowerCaseHex(abySignature,
+                                             CPL_SHA256_HASH_SIZE));
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("S3", "osSignature='%s'\n", osSignature.c_str());
+    CPLDebug("S3", "osSignature='%s'", osSignature.c_str());
 #endif
 
 /* -------------------------------------------------------------------- */
@@ -258,7 +266,7 @@ CPLString CPLGetAWS_SIGN4_Authorization(const CPLString& osSecretAccessKey,
     osAuthorization += osSignature;
 
 #ifdef DEBUG_VERBOSE
-    CPLDebug("S3", "osAuthorization='%s'\n", osAuthorization.c_str());
+    CPLDebug("S3", "osAuthorization='%s'", osAuthorization.c_str());
 #endif
 
     return osAuthorization;
@@ -273,7 +281,7 @@ CPLString CPLGetAWS_SIGN4_Timestamp()
     struct tm brokenDown;
     CPLUnixTimeToYMDHMS(time(NULL), &brokenDown);
 
-    char szTimeStamp[4+2+2+1+2+2+2+1+1];
+    char szTimeStamp[4+2+2+1+2+2+2+1+1] = {};
     snprintf(szTimeStamp, sizeof(szTimeStamp), "%04d%02d%02dT%02d%02d%02dZ",
             brokenDown.tm_year + 1900,
             brokenDown.tm_mon + 1,
@@ -289,27 +297,29 @@ CPLString CPLGetAWS_SIGN4_Timestamp()
 /************************************************************************/
 /*                         VSIS3HandleHelper()                          */
 /************************************************************************/
-
-VSIS3HandleHelper::VSIS3HandleHelper(   const CPLString& osSecretAccessKey,
-                                        const CPLString& osAccessKeyId,
-                                        const CPLString& osSessionToken,
-                                        const CPLString& osAWSS3Endpoint,
-                                        const CPLString& osAWSRegion,
-                                        const CPLString& osBucket,
-                                        const CPLString& osObjectKey,
-                                        bool bUseHTTPS, bool bUseVirtualHosting) :
-        m_osURL(BuildURL(osAWSS3Endpoint, osBucket, osObjectKey, bUseHTTPS, bUseVirtualHosting)),
-        m_osSecretAccessKey(osSecretAccessKey),
-        m_osAccessKeyId(osAccessKeyId),
-        m_osSessionToken(osSessionToken),
-        m_osAWSS3Endpoint(osAWSS3Endpoint),
-        m_osAWSRegion(osAWSRegion),
-        m_osBucket(osBucket),
-        m_osObjectKey(osObjectKey),
-        m_bUseHTTPS(bUseHTTPS),
-        m_bUseVirtualHosting(bUseVirtualHosting)
-{
-}
+VSIS3HandleHelper::VSIS3HandleHelper( const CPLString& osSecretAccessKey,
+                                      const CPLString& osAccessKeyId,
+                                      const CPLString& osSessionToken,
+                                      const CPLString& osAWSS3Endpoint,
+                                      const CPLString& osAWSRegion,
+                                      const CPLString& osRequestPayer,
+                                      const CPLString& osBucket,
+                                      const CPLString& osObjectKey,
+                                      bool bUseHTTPS,
+                                      bool bUseVirtualHosting ) :
+    m_osURL(BuildURL(osAWSS3Endpoint, osBucket, osObjectKey, bUseHTTPS,
+                     bUseVirtualHosting)),
+    m_osSecretAccessKey(osSecretAccessKey),
+    m_osAccessKeyId(osAccessKeyId),
+    m_osSessionToken(osSessionToken),
+    m_osAWSS3Endpoint(osAWSS3Endpoint),
+    m_osAWSRegion(osAWSRegion),
+    m_osRequestPayer(osRequestPayer),
+    m_osBucket(osBucket),
+    m_osObjectKey(osObjectKey),
+    m_bUseHTTPS(bUseHTTPS),
+    m_bUseVirtualHosting(bUseVirtualHosting)
+{}
 
 /************************************************************************/
 /*                        ~VSIS3HandleHelper()                          */
@@ -317,7 +327,7 @@ VSIS3HandleHelper::VSIS3HandleHelper(   const CPLString& osSecretAccessKey,
 
 VSIS3HandleHelper::~VSIS3HandleHelper()
 {
-    for(size_t i=0;i<m_osSecretAccessKey.size();i++)
+    for( size_t i = 0; i < m_osSecretAccessKey.size(); i++ )
         m_osSecretAccessKey[i] = 0;
 }
 
@@ -348,8 +358,10 @@ CPLString VSIS3HandleHelper::BuildURL(const CPLString& osAWSS3Endpoint,
 
 void VSIS3HandleHelper::RebuildURL()
 {
-    m_osURL = BuildURL(m_osAWSS3Endpoint, m_osBucket, m_osObjectKey, m_bUseHTTPS, m_bUseVirtualHosting);
-    std::map<CPLString, CPLString>::iterator oIter = m_oMapQueryParameters.begin();
+    m_osURL = BuildURL(m_osAWSS3Endpoint, m_osBucket, m_osObjectKey,
+                       m_bUseHTTPS, m_bUseVirtualHosting);
+    std::map<CPLString, CPLString>::iterator oIter =
+        m_oMapQueryParameters.begin();
     for( ; oIter != m_oMapQueryParameters.end(); ++oIter )
     {
         if( oIter == m_oMapQueryParameters.begin() )
@@ -357,7 +369,7 @@ void VSIS3HandleHelper::RebuildURL()
         else
             m_osURL += "&";
         m_osURL += oIter->first;
-        if( oIter->second.size() )
+        if( !oIter->second.empty() )
         {
             m_osURL += "=";
             m_osURL += oIter->second;
@@ -369,12 +381,14 @@ void VSIS3HandleHelper::RebuildURL()
 /*                        GetBucketAndObjectKey()                       */
 /************************************************************************/
 
-bool VSIS3HandleHelper::GetBucketAndObjectKey(const char* pszURI, const char* pszFSPrefix,
-                                              bool bAllowNoObject,
-                                              CPLString &osBucket, CPLString &osObjectKey)
+bool VSIS3HandleHelper::GetBucketAndObjectKey( const char* pszURI,
+                                               const char* pszFSPrefix,
+                                               bool bAllowNoObject,
+                                               CPLString &osBucket,
+                                               CPLString &osObjectKey )
 {
     osBucket = pszURI;
-    if( osBucket.size() == 0 )
+    if( osBucket.empty() )
     {
         return false;
     }
@@ -399,40 +413,51 @@ bool VSIS3HandleHelper::GetBucketAndObjectKey(const char* pszURI, const char* ps
 /*                          BuildFromURI()                              */
 /************************************************************************/
 
-VSIS3HandleHelper* VSIS3HandleHelper::BuildFromURI(const char* pszURI,
-                                                   const char* pszFSPrefix,
-                                                   bool bAllowNoObject)
+VSIS3HandleHelper* VSIS3HandleHelper::BuildFromURI( const char* pszURI,
+                                                    const char* pszFSPrefix,
+                                                    bool bAllowNoObject )
 {
-    CPLString osSecretAccessKey = CPLGetConfigOption("AWS_SECRET_ACCESS_KEY", "");
-    if( osSecretAccessKey.size() == 0 )
+    const CPLString osSecretAccessKey =
+        CPLGetConfigOption("AWS_SECRET_ACCESS_KEY", "");
+    if( osSecretAccessKey.empty() )
     {
         VSIError(VSIE_AWSInvalidCredentials,
                  "AWS_SECRET_ACCESS_KEY configuration option not defined");
         return NULL;
     }
-    CPLString osAccessKeyId = CPLGetConfigOption("AWS_ACCESS_KEY_ID", "");
-    if( osAccessKeyId.size() == 0 )
+    const CPLString osAccessKeyId = CPLGetConfigOption("AWS_ACCESS_KEY_ID", "");
+    if( osAccessKeyId.empty() )
     {
         VSIError(VSIE_AWSInvalidCredentials,
                  "AWS_ACCESS_KEY_ID configuration option not defined");
         return NULL;
     }
-    CPLString osSessionToken = CPLGetConfigOption("AWS_SESSION_TOKEN", "");
-    CPLString osAWSS3Endpoint = CPLGetConfigOption("AWS_S3_ENDPOINT", "s3.amazonaws.com");
-    CPLString osAWSRegion = CPLGetConfigOption("AWS_REGION", "us-east-1");
-    CPLString osBucket, osObjectKey;
-    if( !GetBucketAndObjectKey(pszURI, pszFSPrefix, bAllowNoObject, osBucket, osObjectKey) )
+    const CPLString osSessionToken =
+        CPLGetConfigOption("AWS_SESSION_TOKEN", "");
+    const CPLString osAWSS3Endpoint =
+        CPLGetConfigOption("AWS_S3_ENDPOINT", "s3.amazonaws.com");
+    const CPLString osAWSRegion = CPLGetConfigOption("AWS_REGION", "us-east-1");
+    const CPLString osRequestPayer =
+        CPLGetConfigOption("AWS_REQUEST_PAYER", "");
+    CPLString osBucket;
+    CPLString osObjectKey;
+    if( !GetBucketAndObjectKey(pszURI, pszFSPrefix, bAllowNoObject,
+                               osBucket, osObjectKey) )
     {
         return NULL;
     }
-    bool bUseHTTPS = CPL_TO_BOOL(CSLTestBoolean(CPLGetConfigOption("AWS_HTTPS", "YES")));
-    bool bIsValidNameForVirtualHosting = (osBucket.find('.') == std::string::npos);
-    bool bUseVirtualHosting = CPL_TO_BOOL(CSLTestBoolean(
-            CPLGetConfigOption("AWS_VIRTUAL_HOSTING",
-                               bIsValidNameForVirtualHosting ? "TRUE" : "FALSE")));
-    return new VSIS3HandleHelper(osSecretAccessKey, osAccessKeyId, osSessionToken,
-                                    osAWSS3Endpoint, osAWSRegion,
-                                    osBucket, osObjectKey, bUseHTTPS, bUseVirtualHosting);
+    const bool bUseHTTPS = CPLTestBool(CPLGetConfigOption("AWS_HTTPS", "YES"));
+    const bool bIsValidNameForVirtualHosting =
+        osBucket.find('.') == std::string::npos;
+    const bool bUseVirtualHosting = CPLTestBool(
+        CPLGetConfigOption("AWS_VIRTUAL_HOSTING",
+                           bIsValidNameForVirtualHosting ? "TRUE" : "FALSE"));
+    return new VSIS3HandleHelper(osSecretAccessKey, osAccessKeyId,
+                                 osSessionToken,
+                                 osAWSS3Endpoint, osAWSRegion,
+                                 osRequestPayer,
+                                 osBucket, osObjectKey, bUseHTTPS,
+                                 bUseVirtualHosting);
 }
 
 /************************************************************************/
@@ -449,7 +474,8 @@ void VSIS3HandleHelper::ResetQueryParameters()
 /*                         AddQueryParameter()                          */
 /************************************************************************/
 
-void VSIS3HandleHelper::AddQueryParameter(const CPLString& osKey, const CPLString& osValue)
+void VSIS3HandleHelper::AddQueryParameter( const CPLString& osKey,
+                                           const CPLString& osValue )
 {
     m_oMapQueryParameters[osKey] = osValue;
     RebuildURL();
@@ -459,50 +485,64 @@ void VSIS3HandleHelper::AddQueryParameter(const CPLString& osKey, const CPLStrin
 /*                           GetCurlHeaders()                           */
 /************************************************************************/
 
-struct curl_slist* VSIS3HandleHelper::GetCurlHeaders(const CPLString& osVerb,
-                                                     const void *pabyDataContent,
-                                                     size_t nBytesContent)
+struct curl_slist *
+VSIS3HandleHelper::GetCurlHeaders( const CPLString& osVerb,
+                                   const void *pabyDataContent,
+                                   size_t nBytesContent )
 {
     CPLString osXAMZDate = CPLGetConfigOption("AWS_TIMESTAMP", "");
-    if( osXAMZDate.size() == 0 )
+    if( osXAMZDate.empty() )
         osXAMZDate = CPLGetAWS_SIGN4_Timestamp();
 
-    CPLString osXAMZContentSHA256 = CPLGetLowerCaseHexSHA256(pabyDataContent, nBytesContent);
+    const CPLString osXAMZContentSHA256 =
+        CPLGetLowerCaseHexSHA256(pabyDataContent, nBytesContent);
 
     CPLString osCanonicalQueryString;
-    std::map<CPLString, CPLString>::iterator oIter = m_oMapQueryParameters.begin();
+    std::map<CPLString, CPLString>::iterator oIter =
+        m_oMapQueryParameters.begin();
     for( ; oIter != m_oMapQueryParameters.end(); ++oIter )
     {
-        if( osCanonicalQueryString.size() )
+        if( !osCanonicalQueryString.empty() )
             osCanonicalQueryString += "&";
         osCanonicalQueryString += oIter->first;
         osCanonicalQueryString += "=";
         osCanonicalQueryString += CPLAWSURLEncode(oIter->second);
     }
 
-    CPLString osAuthorization = CPLGetAWS_SIGN4_Authorization(
-            m_osSecretAccessKey,
-            m_osAccessKeyId,
-            m_osSessionToken,
-            m_osAWSRegion,
-            "s3",
-            osVerb,
-            (m_bUseVirtualHosting) ? m_osBucket + "." + m_osAWSS3Endpoint : m_osAWSS3Endpoint,
-            (m_bUseVirtualHosting) ? ("/" + m_osObjectKey).c_str() : ("/" + m_osBucket + "/" + m_osObjectKey).c_str(),
-            osCanonicalQueryString,
-            osXAMZContentSHA256,
-            osXAMZDate);
+    const CPLString osHost(m_bUseVirtualHosting
+        ? CPLString(m_osBucket + "." + m_osAWSS3Endpoint) : m_osAWSS3Endpoint);
+    const CPLString osAuthorization = CPLGetAWS_SIGN4_Authorization(
+        m_osSecretAccessKey,
+        m_osAccessKeyId,
+        m_osSessionToken,
+        m_osAWSRegion,
+        m_osRequestPayer,
+        "s3",
+        osVerb,
+        osHost,
+        m_bUseVirtualHosting
+        ? ("/" + m_osObjectKey).c_str() :
+        ("/" + m_osBucket + "/" + m_osObjectKey).c_str(),
+        osCanonicalQueryString,
+        osXAMZContentSHA256,
+        osXAMZDate);
 
     struct curl_slist *headers=NULL;
-    headers = curl_slist_append(headers,
-                                CPLSPrintf("x-amz-date: %s", osXAMZDate.c_str()));
-    headers = curl_slist_append(headers,
-                                CPLSPrintf("x-amz-content-sha256: %s", osXAMZContentSHA256.c_str()));
-    if( m_osSessionToken.size() )
-        headers = curl_slist_append(headers,
-                                CPLSPrintf("X-Amz-Security-Token: %s", m_osSessionToken.c_str()));
-    headers = curl_slist_append(headers,
-                                CPLSPrintf("Authorization: %s", osAuthorization.c_str()));
+    headers = curl_slist_append(
+        headers, CPLSPrintf("x-amz-date: %s", osXAMZDate.c_str()));
+    headers = curl_slist_append(
+        headers, CPLSPrintf("x-amz-content-sha256: %s",
+                            osXAMZContentSHA256.c_str()));
+    if( !m_osSessionToken.empty() )
+        headers = curl_slist_append(
+            headers,
+            CPLSPrintf("X-Amz-Security-Token: %s", m_osSessionToken.c_str()));
+    if( !m_osRequestPayer.empty() )
+        headers = curl_slist_append(
+            headers,
+            CPLSPrintf("x-amz-request-payer: %s", m_osRequestPayer.c_str()));
+    headers = curl_slist_append(
+        headers, CPLSPrintf("Authorization: %s", osAuthorization.c_str()));
     return headers;
 }
 
@@ -510,7 +550,8 @@ struct curl_slist* VSIS3HandleHelper::GetCurlHeaders(const CPLString& osVerb,
 /*                          CanRestartOnError()                         */
 /************************************************************************/
 
-bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg, bool bSetError)
+bool VSIS3HandleHelper::CanRestartOnError( const char* pszErrorMsg,
+                                           bool bSetError )
 {
 #ifdef DEBUG_VERBOSE
     CPLDebug("S3", "%s", pszErrorMsg);
@@ -518,14 +559,21 @@ bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg, bool bSetErro
 
     if( !STARTS_WITH(pszErrorMsg, "<?xml") )
     {
-        if(bSetError) { VSIError(VSIE_AWSError, "Invalid AWS response: %s", pszErrorMsg); }
+        if( bSetError )
+        {
+            VSIError(VSIE_AWSError, "Invalid AWS response: %s", pszErrorMsg);
+        }
         return false;
     }
 
     CPLXMLNode* psTree = CPLParseXMLString(pszErrorMsg);
     if( psTree == NULL )
     {
-        if(bSetError) { VSIError(VSIE_AWSError, "Malformed AWS XML repsonse: %s", pszErrorMsg); }
+        if( bSetError )
+        {
+            VSIError(VSIE_AWSError,
+                     "Malformed AWS XML response: %s", pszErrorMsg);
+        }
         return false;
     }
 
@@ -533,7 +581,11 @@ bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg, bool bSetErro
     if( pszCode == NULL )
     {
         CPLDestroyXMLNode(psTree);
-        if(bSetError) { VSIError(VSIE_AWSError, "Malformed AWS XML repsonse: %s", pszErrorMsg); }
+        if( bSetError )
+        {
+            VSIError(VSIE_AWSError,
+                     "Malformed AWS XML response: %s", pszErrorMsg);
+        }
         return false;
     }
 
@@ -543,7 +595,11 @@ bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg, bool bSetErro
         if( pszRegion == NULL )
         {
             CPLDestroyXMLNode(psTree);
-            if(bSetError) { VSIError(VSIE_AWSError, "Malformed AWS XML repsonse: %s", pszErrorMsg); }
+            if( bSetError )
+            {
+                VSIError(VSIE_AWSError,
+                         "Malformed AWS XML response: %s", pszErrorMsg);
+            }
             return false;
         }
         SetAWSRegion(pszRegion);
@@ -554,13 +610,20 @@ bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg, bool bSetErro
 
     if( EQUAL(pszCode, "PermanentRedirect") )
     {
-        const char* pszEndpoint = CPLGetXMLValue(psTree, "=Error.Endpoint", NULL);
+        const char* pszEndpoint =
+            CPLGetXMLValue(psTree, "=Error.Endpoint", NULL);
         if( pszEndpoint == NULL ||
-            (m_bUseVirtualHosting && (strncmp(pszEndpoint, m_osBucket.c_str(), m_osBucket.size()) != 0 ||
-                                    pszEndpoint[m_osBucket.size()] != '.')) )
+            (m_bUseVirtualHosting &&
+             (strncmp(pszEndpoint, m_osBucket.c_str(),
+                      m_osBucket.size()) != 0 ||
+              pszEndpoint[m_osBucket.size()] != '.')) )
         {
             CPLDestroyXMLNode(psTree);
-            if(bSetError) { VSIError(VSIE_AWSError, "Malformed AWS XML repsonse: %s", pszErrorMsg); }
+            if( bSetError )
+            {
+                VSIError(VSIE_AWSError,
+                         "Malformed AWS XML response: %s", pszErrorMsg);
+            }
             return false;
         }
         if( !m_bUseVirtualHosting &&
@@ -570,16 +633,18 @@ bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg, bool bSetErro
             m_bUseVirtualHosting = true;
             CPLDebug("S3", "Switching to virtual hosting");
         }
-        SetAWSS3Endpoint((m_bUseVirtualHosting) ? pszEndpoint + m_osBucket.size() + 1 : pszEndpoint);
+        SetAWSS3Endpoint(
+            m_bUseVirtualHosting
+            ? pszEndpoint + m_osBucket.size() + 1
+            : pszEndpoint);
         CPLDebug("S3", "Switching to endpoint %s", m_osAWSS3Endpoint.c_str());
         CPLDestroyXMLNode(psTree);
         return true;
     }
 
-    if(bSetError) {
-        /*
-         * Translate AWS errors into VSI errors
-         */
+    if( bSetError )
+    {
+        // Translate AWS errors into VSI errors.
         const char* pszMessage = CPLGetXMLValue(psTree, "=Error.Message", NULL);
 
         if( pszMessage == NULL ) {
@@ -606,7 +671,7 @@ bool VSIS3HandleHelper::CanRestartOnError(const char* pszErrorMsg, bool bSetErro
 /*                          SetAWSS3Endpoint()                          */
 /************************************************************************/
 
-void VSIS3HandleHelper::SetAWSS3Endpoint(const CPLString &osStr)
+void VSIS3HandleHelper::SetAWSS3Endpoint( const CPLString &osStr )
 {
     m_osAWSS3Endpoint = osStr;
     RebuildURL();
@@ -616,15 +681,25 @@ void VSIS3HandleHelper::SetAWSS3Endpoint(const CPLString &osStr)
 /*                           SetAWSRegion()                             */
 /************************************************************************/
 
-void VSIS3HandleHelper::SetAWSRegion(const CPLString &osStr)
+void VSIS3HandleHelper::SetAWSRegion( const CPLString &osStr )
 {
     m_osAWSRegion = osStr;
 }
+
+/************************************************************************/
+/*                           SetRequestPayer()                          */
+/************************************************************************/
+
+void VSIS3HandleHelper::SetRequestPayer( const CPLString &osStr )
+{
+    m_osRequestPayer = osStr;
+}
+
 /************************************************************************/
 /*                         SetVirtualHosting()                          */
 /************************************************************************/
 
-void VSIS3HandleHelper::SetVirtualHosting(bool b)
+void VSIS3HandleHelper::SetVirtualHosting( bool b )
 {
     m_bUseVirtualHosting = b;
     RebuildURL();
@@ -634,10 +709,12 @@ void VSIS3HandleHelper::SetVirtualHosting(bool b)
 /*                           SetObjectKey()                             */
 /************************************************************************/
 
-void VSIS3HandleHelper::SetObjectKey(const CPLString &osStr)
+void VSIS3HandleHelper::SetObjectKey( const CPLString &osStr )
 {
     m_osObjectKey = osStr;
     RebuildURL();
 }
 
 #endif
+
+//! @endcond
diff --git a/port/cpl_aws.h b/port/cpl_aws.h
index 854ada6..88ea61e 100644
--- a/port/cpl_aws.h
+++ b/port/cpl_aws.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_aws.h 33758 2016-03-21 09:06:22Z rouault $
+ * $Id: cpl_aws.h 37174 2017-01-18 20:00:36Z rouault $
  *
  * Name:     cpl_aws.h
  * Project:  CPL - Common Portability Library
@@ -31,12 +31,17 @@
 #ifndef CPL_AWS_INCLUDED_H
 #define CPL_AWS_INCLUDED_H
 
+#ifndef DOXYGEN_SKIP
+
+#include <cstddef>
+
 #include "cpl_string.h"
 
 CPLString CPLGetAWS_SIGN4_Authorization(const CPLString& osSecretAccessKey,
                                         const CPLString& osAccessKeyId,
                                         const CPLString& osAccessToken,
                                         const CPLString& osAWSRegion,
+                                        const CPLString& osRequestPayer,
                                         const CPLString& osService,
                                         const CPLString& osVerb,
                                         const CPLString& osHost,
@@ -65,6 +70,7 @@ class VSIS3HandleHelper
         CPLString m_osSessionToken;
         CPLString m_osAWSS3Endpoint;
         CPLString m_osAWSRegion;
+        CPLString m_osRequestPayer;
         CPLString m_osBucket;
         CPLString m_osObjectKey;
         bool m_bUseHTTPS;
@@ -84,6 +90,7 @@ class VSIS3HandleHelper
                     const CPLString& osSessionToken,
                     const CPLString& osAWSS3Endpoint,
                     const CPLString& osAWSRegion,
+                    const CPLString& osRequestPayer,
                     const CPLString& osBucket,
                     const CPLString& osObjectKey,
                     bool bUseHTTPS, bool bUseVirtualHosting);
@@ -109,9 +116,11 @@ class VSIS3HandleHelper
         const CPLString& GetObjectKey() const { return m_osObjectKey; }
         const CPLString& GetAWSS3Endpoint()const  { return m_osAWSS3Endpoint; }
         const CPLString& GetAWSRegion() const { return m_osAWSRegion; }
+        const CPLString& GetRequestPayer() const { return m_osRequestPayer; }
         bool GetVirtualHosting() const { return m_bUseVirtualHosting; }
         void SetAWSS3Endpoint(const CPLString &osStr);
         void SetAWSRegion(const CPLString &osStr);
+        void SetRequestPayer(const CPLString &osStr);
         void SetVirtualHosting(bool b);
         void SetObjectKey(const CPLString &osStr);
 };
@@ -121,16 +130,21 @@ class VSIS3UpdateParams
     public:
         CPLString m_osAWSRegion;
         CPLString m_osAWSS3Endpoint;
+        CPLString m_osRequestPayer;
         bool m_bUseVirtualHosting;
 
         VSIS3UpdateParams(const CPLString& osAWSRegion = "",
                           const CPLString& osAWSS3Endpoint = "",
+                          const CPLString& osRequestPayer = "",
                           bool bUseVirtualHosting = false) :
             m_osAWSRegion(osAWSRegion),
             m_osAWSS3Endpoint(osAWSS3Endpoint),
+            m_osRequestPayer(osRequestPayer),
             m_bUseVirtualHosting(bUseVirtualHosting) {}
 };
 
 #endif /* HAVE_CURL */
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* CPL_AWS_INCLUDED_H */
diff --git a/port/cpl_base64.cpp b/port/cpl_base64.cpp
index 5969997..378bc3b 100644
--- a/port/cpl_base64.cpp
+++ b/port/cpl_base64.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_base64.cpp 31561 2015-11-17 15:51:25Z goatbar $
  *
  * Project:  Common Portability Library
  * Purpose:  Encoding/Decoding Base64 strings
@@ -34,40 +33,45 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_base64.cpp 31561 2015-11-17 15:51:25Z goatbar $");
+#include <string>
 
-/* Derived from MapServer's mappostgis.c */
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: cpl_base64.cpp 36993 2016-12-22 00:21:24Z goatbar $");
+
+// Derived from MapServer's mappostgis.c.
 
 /*
 ** Decode a base64 character.
 */
 static const unsigned char CPLBase64DecodeChar[256] = {
-    /* not Base64 characters */
+    // Not Base64 characters.
     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
     64,64,64,64,64,64,64,64,64,64,64,
-    /*  +  */
+    // +
     62,
-    /* not Base64 characters */
+    // Not Base64 characters.
     64,64,64,
-    /*  /  */
+    //  /
     63,
-    /* 0-9 */
+    // 0-9
     52,53,54,55,56,57,58,59,60,61,
-    /* not Base64 characters */
+    // Not Base64 characters.
     64,64,64,64,64,64,64,
-    /* A-Z */
+    // A-Z
     0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,
-    /* not Base64 characters */
+    // Not Base64 characters.
     64,64,64,64,64,64,
-    /* a-z */
+    // a-z
     26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,
     51,
-    /* not Base64 characters */
+    // Not Base64 characters.
     64,64,64,64,64,
-    /* not Base64 characters (upper 128 characters) */
+    // Not Base64 characters (upper 128 characters).
     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
@@ -80,59 +84,70 @@ static const unsigned char CPLBase64DecodeChar[256] = {
 
 /************************************************************************/
 /*                       CPLBase64DecodeInPlace()                       */
-/*                                                                      */
-/*      Decode base64 string "pszBase64" (null terminated) in place     */
-/*      Returns length of decoded array or 0 on failure.                */
 /************************************************************************/
 
-int CPLBase64DecodeInPlace(GByte* pszBase64)
+/** Decode base64 string "pszBase64" (null terminated) in place.
+ *
+ * Returns length of decoded array or 0 on failure.
+ */
+int CPLBase64DecodeInPlace( GByte* pszBase64 )
 {
-    if (pszBase64 && *pszBase64) {
+    if( pszBase64 && *pszBase64 )
+    {
         unsigned char *p = pszBase64;
         int offset_1 = 0;
         int offset_2 = 0;
 
-        /* Drop illegal chars first */
-        for ( ; pszBase64[offset_1]; ++offset_1) {
+        // Drop illegal chars first.
+        for( ; pszBase64[offset_1]; ++offset_1 )
+        {
             unsigned char c = pszBase64[offset_1];
-            if ( (CPLBase64DecodeChar[c] != 64) || (c == '=') ) {
+            if( (CPLBase64DecodeChar[c] != 64) || (c == '=') )
+            {
                 pszBase64[offset_2++] = c;
             }
         }
 
-        for (int idx = 0; idx < offset_2; idx += 4) {
+        for( int idx = 0; idx < offset_2; idx += 4 )
+        {
             unsigned char b1 = CPLBase64DecodeChar[pszBase64[idx]];
             unsigned char b2 = 0;
             unsigned char c3 = 'A';
             unsigned char c4 = 'A';
 
-            if (idx + 3 < offset_2) {
+            if( idx + 3 < offset_2 )
+            {
                 b2 = CPLBase64DecodeChar[pszBase64[idx+1]];
                 c3 = pszBase64[idx+2];
                 c4 = pszBase64[idx+3];
-            } else if (idx + 2 < offset_2) {
+            }
+            else if( idx + 2 < offset_2 )
+            {
                 b2 = CPLBase64DecodeChar[pszBase64[idx+1]];
                 c3 = pszBase64[idx+2];
-            } else if (idx + 1 < offset_2) {
+            }
+            else if( idx + 1 < offset_2 )
+            {
                 b2 = CPLBase64DecodeChar[pszBase64[idx+1]];
-                c3 = 'A';
+                // c3 = 'A';
             }  // Else: Use the default values.
 
-
             const unsigned char b3 = CPLBase64DecodeChar[c3];
             const unsigned char b4 = CPLBase64DecodeChar[c4];
 
             *p++ = ( (b1 << 2) | (b2 >> 4) );
-            if (p - pszBase64 == offset_1)
+            if( p - pszBase64 == offset_1 )
                 break;
-            if (c3 != '=') {
+            if( c3 != '=' )
+            {
                 *p++ = ( ((b2 & 0xf) << 4) | (b3 >> 2) );
-                if (p - pszBase64 == offset_1)
+                if( p - pszBase64 == offset_1 )
                     break;
             }
-            if (c4 != '=') {
+            if( c4 != '=' )
+            {
                 *p++ = ( ((b3 & 0x3) << 6) | b4);
-                if (p - pszBase64 == offset_1)
+                if( p - pszBase64 == offset_1 )
                     break;
             }
         }
@@ -179,30 +194,36 @@ int CPLBase64DecodeInPlace(GByte* pszBase64)
 /*                          CPLBase64Encode()                           */
 /************************************************************************/
 
-char *CPLBase64Encode(int nDataLen, const GByte *pabyBytesToEncode) {
+/** Base64 encode a buffer. */
+
+char *CPLBase64Encode(int nDataLen, const GByte *pabyBytesToEncode)
+{
     static const char base64Chars[] =
         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
     const int kCharArray3Size = 3;
     const int kCharArray4Size = 4;
-    unsigned char charArray3[kCharArray3Size];
+    unsigned char charArray3[kCharArray3Size] = {};
 
     std::string result("");
     int array3_idx = 0;
-    while (nDataLen--) {
+    while( nDataLen-- )
+    {
         charArray3[array3_idx++] = *(pabyBytesToEncode++);
 
-        if (array3_idx == kCharArray3Size) {
-            unsigned char charArray4[kCharArray4Size];
-
-            charArray4[0] = (charArray3[0] & 0xfc) >> 2;
-            charArray4[1] = ((charArray3[0] & 0x03) << 4)
-                + ((charArray3[1] & 0xf0) >> 4);
-            charArray4[2] = ((charArray3[1] & 0x0f) << 2)
-                + ((charArray3[2] & 0xc0) >> 6);
-            charArray4[3] = charArray3[2] & 0x3f;
+        if( array3_idx == kCharArray3Size )
+        {
+            const unsigned char charArray4[kCharArray4Size] = {
+                static_cast<unsigned char>( (charArray3[0] & 0xfc) >> 2),
+                static_cast<unsigned char>(((charArray3[0] & 0x03) << 4) +
+                                           ((charArray3[1] & 0xf0) >> 4)),
+                static_cast<unsigned char>(((charArray3[1] & 0x0f) << 2) +
+                                           ((charArray3[2] & 0xc0) >> 6)),
+                static_cast<unsigned char>(  charArray3[2] & 0x3f)
+            };
 
-            for (int idx = 0; idx < kCharArray4Size; ++idx) {
+            for( int idx = 0; idx < kCharArray4Size; ++idx )
+            {
                 result += base64Chars[charArray4[idx]];
             }
 
@@ -210,24 +231,28 @@ char *CPLBase64Encode(int nDataLen, const GByte *pabyBytesToEncode) {
         }
     }
 
-    if (array3_idx) {
-        for (int idx = array3_idx; idx < kCharArray3Size; ++idx) {
+    if( array3_idx )
+    {
+        for( int idx = array3_idx; idx < kCharArray3Size; ++idx )
+        {
             charArray3[idx] = '\0';
         }
 
-        unsigned char charArray4[kCharArray4Size];
-        charArray4[0] = (charArray3[0]  & 0xfc) >> 2;
-        charArray4[1] = ((charArray3[0] & 0x03) << 4)
-            + ((charArray3[1] & 0xf0) >> 4);
-        charArray4[2] = ((charArray3[1] & 0x0f) << 2)
-            + ((charArray3[2] & 0xc0) >> 6);
-        charArray4[3] = charArray3[2] & 0x3f;
+        const unsigned char charArray4[kCharArray4Size] = {
+            static_cast<unsigned char>( (charArray3[0] & 0xfc) >> 2),
+            static_cast<unsigned char>(((charArray3[0] & 0x03) << 4) +
+                                       ((charArray3[1] & 0xf0) >> 4)),
+            static_cast<unsigned char>(((charArray3[1] & 0x0f) << 2) +
+                                       ((charArray3[2] & 0xc0) >> 6)),
+            static_cast<unsigned char>(  charArray3[2] & 0x3f)
+        };
 
-        for (int idx = 0; idx < (array3_idx + 1); ++idx) {
+        for( int idx = 0; idx < (array3_idx + 1); ++idx )
+        {
             result += base64Chars[charArray4[idx]];
         }
 
-        while (array3_idx++ < kCharArray3Size)
+        while( array3_idx++ < kCharArray3Size )
             result += '=';
     }
 
diff --git a/port/cpl_config.h.in b/port/cpl_config.h.in
index 2e82fbb..383fde1 100644
--- a/port/cpl_config.h.in
+++ b/port/cpl_config.h.in
@@ -1,4 +1,5 @@
 /* port/cpl_config.h.in.  Generated from configure.in by autoheader.  */
+/* $Id: cpl_config.h.in 36873 2016-12-15 01:53:11Z rouault $ */
 
 /* Define if you want to use pthreads based multiprocessing support */
 #undef CPL_MULTIPROC_PTHREAD
@@ -71,6 +72,9 @@
 /* Define to 1 if the system has the type `int8'. */
 #undef HAVE_INT8
 
+/* Define to 1 if the system has the type `__uint128_t'. */
+#undef HAVE_UINT128_T
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
@@ -98,6 +102,9 @@
 /* Define to 1, if your compiler supports long long data type */
 #undef HAVE_LONG_LONG
 
+/* Define to 1, if your compiler supports uintptr_t data type */
+#undef HAVE_UINTPTR_T
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -146,6 +153,9 @@
 /* Define to 1 if you have the `posix_spawnp' function. */
 #undef HAVE_POSIX_SPAWNP
 
+/* Define to 1 if you have the `posix_memalign' function. */
+#undef HAVE_POSIX_MEMALIGN
+
 /* Define to 1 if you have the `vfork' function. */
 #undef HAVE_VFORK
 
@@ -170,6 +180,9 @@
 /* For .cpp files, define as const if the declaration of iconv() needs const. */
 #undef ICONV_CPP_CONST
 
+/* Define to 1 if libjvm.so should be dlopen'd */
+#undef JVM_LIB_DLOPEN
+
 /* Define to the sub-directory in which libtool stores uninstalled libraries.
    */
 #undef LT_OBJDIR
@@ -201,6 +214,9 @@
 /* Define to 1 if GCC atomic builtins are available */
 #undef HAVE_GCC_ATOMIC_BUILTINS
 
+/* Define to 1 if GCC bswap builtins are available */
+#undef HAVE_GCC_BSWAP
+
 /* Define to name of 64bit fopen function */
 #undef VSI_FOPEN64
 
diff --git a/port/cpl_config.h.vc b/port/cpl_config.h.vc
index fe7b82a..f03d16e 100644
--- a/port/cpl_config.h.vc
+++ b/port/cpl_config.h.vc
@@ -47,7 +47,7 @@
 /* Define to 1 if you have the <sys/types.h> header file. */
 #define HAVE_SYS_TYPES_H 1
 
-#undef HAVE_LIBDL 
+#undef HAVE_LIBDL
 
 /* Define to 1 if you have the <locale.h> header file. */
 #define HAVE_LOCALE_H 1
diff --git a/port/cpl_config_extras.h b/port/cpl_config_extras.h
index 654f2fc..425c8c6 100644
--- a/port/cpl_config_extras.h
+++ b/port/cpl_config_extras.h
@@ -1,3 +1,4 @@
+/* $Id: cpl_config_extras.h 37003 2016-12-23 14:54:07Z goatbar $ */
 
 #ifndef INCLUDED_CPL_CONFIG_EXTRAS
 #define INCLUDED_CPL_CONFIG_EXTRAS
@@ -10,7 +11,6 @@
   #define HOST_FILLORDER FILLORDER_LSB2MSB
 #endif
 
-
 #ifdef __LP64__
   #define SIZEOF_UNSIGNED_LONG 8
 #else
@@ -37,4 +37,4 @@
 
 #endif // APPLE
 
-#endif //INCLUDED_CPL_CONFIG_EXTRAS
+#endif // INCLUDED_CPL_CONFIG_EXTRAS
diff --git a/port/cpl_conv.cpp b/port/cpl_conv.cpp
index d8f0708..5990d7d 100644
--- a/port/cpl_conv.cpp
+++ b/port/cpl_conv.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_conv.cpp 33769 2016-03-22 18:20:04Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Convenience functions.
@@ -28,11 +27,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-// For uselocale
+// For uselocale, define _XOPEN_SOURCE = 700
+// but on Solaris, we don't have uselocale and we cannot have
+// std=c++11 with _XOPEN_SOURCE != 600
+#if defined(__sun__) && __cplusplus >= 201103L
+#if _XOPEN_SOURCE != 600
+#ifdef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE
+#endif
+#define _XOPEN_SOURCE 600
+#endif
+#else
 #ifdef _XOPEN_SOURCE
 #undef _XOPEN_SOURCE
 #endif
 #define _XOPEN_SOURCE 700
+#endif
 
 // For atoll (at least for NetBSD)
 #define _ISOC99_SOURCE
@@ -40,44 +50,56 @@
 #ifdef MSVC_USE_VLD
 #include <vld.h>
 #endif
+
 #include "cpl_conv.h"
-#include "cpl_multiproc.h"
-#include "cpl_string.h"
-#include "cpl_vsi.h"
 
+#include <cctype>
 #include <cerrno>
+#include <climits>
 #include <clocale>
+#include <cmath>
+#include <cstdlib>
 #include <cstring>
-
-/* Uncomment to get list of options that have been fetched and set */
-//#define DEBUG_CONFIG_OPTIONS
+#include <ctime>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 #ifdef DEBUG_CONFIG_OPTIONS
-
 #include <set>
+#endif
+#include <string>
+
+#include "cpl_config.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 
-#endif
+// Uncomment to get list of options that have been fetched and set.
+// #define DEBUG_CONFIG_OPTIONS
 
-CPL_CVSID("$Id: cpl_conv.cpp 33769 2016-03-22 18:20:04Z goatbar $");
+CPL_CVSID("$Id: cpl_conv.cpp 37987 2017-04-14 07:42:50Z rouault $");
 
 static CPLMutex *hConfigMutex = NULL;
-static volatile char **papszConfigOptions = NULL;
+static volatile char **g_papszConfigOptions = NULL;
 
-/* Used by CPLOpenShared() and friends */
+// Used by CPLOpenShared() and friends.
 static CPLMutex *hSharedFileMutex = NULL;
 static volatile int nSharedFileCount = 0;
 static volatile CPLSharedFileInfo *pasSharedFileList = NULL;
 
-/* Used by CPLsetlocale() */
+// Used by CPLsetlocale().
 static CPLMutex *hSetLocaleMutex = NULL;
 
-/* Note: ideally this should be added in CPLSharedFileInfo* */
-/* but CPLSharedFileInfo is exposed in the API, hence that trick */
-/* to hide this detail */
+// Note: ideally this should be added in CPLSharedFileInfo*
+// but CPLSharedFileInfo is exposed in the API, hence that trick
+// to hide this detail.
 typedef struct
 {
-    GIntBig             nPID; // pid of opening thread
+    GIntBig nPID;  // pid of opening thread.
 } CPLSharedFileInfoExtra;
 
 static volatile CPLSharedFileInfoExtra *pasSharedFileListExtra = NULL;
@@ -109,8 +131,8 @@ void *CPLCalloc( size_t nCount, size_t nSize )
     if( nSize * nCount == 0 )
         return NULL;
 
-    void *pReturn = CPLMalloc( nCount * nSize );
-    memset( pReturn, 0, nCount * nSize );
+    void *pReturn = CPLMalloc(nCount * nSize);
+    memset(pReturn, 0, nCount * nSize);
     return pReturn;
 }
 
@@ -143,25 +165,25 @@ void *CPLMalloc( size_t nSize )
 
     if( static_cast<long>(nSize) < 0 )
     {
-        /* coverity[dead_error_begin] */
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "CPLMalloc(%ld): Silly size requested.\n",
-                  static_cast<long>(nSize) );
+        // coverity[dead_error_begin]
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "CPLMalloc(%ld): Silly size requested.",
+                 static_cast<long>(nSize));
         return NULL;
     }
 
-    void *pReturn = VSIMalloc( nSize );
+    void *pReturn = VSIMalloc(nSize);
     if( pReturn == NULL )
     {
         if( nSize > 0 && nSize < 2000 )
         {
-            CPLEmergencyError( "CPLMalloc(): Out of memory allocating a small "
-                               "number of bytes." );
+            CPLEmergencyError("CPLMalloc(): Out of memory allocating a small "
+                              "number of bytes.");
         }
 
-        CPLError( CE_Fatal, CPLE_OutOfMemory,
-                  "CPLMalloc(): Out of memory allocating %ld bytes.\n",
-                  static_cast<long>(nSize) );
+        CPLError(CE_Fatal, CPLE_OutOfMemory,
+                 "CPLMalloc(): Out of memory allocating %ld bytes.",
+                 static_cast<long>(nSize));
     }
 
     return pReturn;
@@ -190,11 +212,10 @@ void *CPLMalloc( size_t nSize )
  * @return pointer to allocated memory, only NULL if nNewSize is zero.
  */
 
-
 void * CPLRealloc( void * pData, size_t nNewSize )
 
 {
-    if ( nNewSize == 0 )
+    if( nNewSize == 0 )
     {
         VSIFree(pData);
         return NULL;
@@ -202,35 +223,37 @@ void * CPLRealloc( void * pData, size_t nNewSize )
 
     if( static_cast<long>(nNewSize) < 0 )
     {
-        /* coverity[dead_error_begin] */
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "CPLRealloc(%ld): Silly size requested.\n",
-                  static_cast<long>( nNewSize ) );
+        // coverity[dead_error_begin]
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "CPLRealloc(%ld): Silly size requested.",
+                 static_cast<long>(nNewSize));
         return NULL;
     }
 
     void *pReturn = NULL;
 
     if( pData == NULL )
-        pReturn = VSIMalloc( nNewSize );
+        pReturn = VSIMalloc(nNewSize);
     else
-        pReturn = VSIRealloc( pData, nNewSize );
+        pReturn = VSIRealloc(pData, nNewSize);
 
     if( pReturn == NULL )
     {
         if( nNewSize > 0 && nNewSize < 2000 )
         {
-            char szSmallMsg[60];
+            char szSmallMsg[60] = {};
 
-            snprintf( szSmallMsg, sizeof(szSmallMsg),
-                      "CPLRealloc(): Out of memory allocating %ld bytes.",
-                      static_cast<long>( nNewSize ) );
-            CPLEmergencyError( szSmallMsg );
+            snprintf(szSmallMsg, sizeof(szSmallMsg),
+                     "CPLRealloc(): Out of memory allocating %ld bytes.",
+                     static_cast<long>(nNewSize));
+            CPLEmergencyError(szSmallMsg);
         }
         else
-            CPLError( CE_Fatal, CPLE_OutOfMemory,
-                      "CPLRealloc(): Out of memory allocating %ld bytes.\n",
-                      static_cast<long>( nNewSize ) );
+        {
+            CPLError(CE_Fatal, CPLE_OutOfMemory,
+                     "CPLRealloc(): Out of memory allocating %ld bytes.",
+                     static_cast<long>(nNewSize));
+        }
     }
 
     return pReturn;
@@ -264,16 +287,15 @@ char *CPLStrdup( const char * pszString )
     if( pszString == NULL )
         pszString = "";
 
-    char *pszReturn
-        = reinterpret_cast<char *>( CPLMalloc(strlen(pszString) + 1 ) );
+    char *pszReturn = static_cast<char *>(CPLMalloc(strlen(pszString) + 1));
     if( pszReturn == NULL )
     {
-        CPLError( CE_Fatal, CPLE_OutOfMemory,
-                  "CPLStrdup(): Out of memory allocating %ld bytes.\n",
-                  static_cast<long>( strlen(pszString) ) );
+        CPLError(CE_Fatal, CPLE_OutOfMemory,
+                 "CPLStrdup(): Out of memory allocating %ld bytes.",
+                 static_cast<long>(strlen(pszString)));
     }
 
-    strcpy( pszReturn, pszString );
+    strcpy(pszReturn, pszString);
     return pszReturn;
 }
 
@@ -299,9 +321,9 @@ char *CPLStrlwr( char *pszString )
 
     char *pszTemp = pszString;
 
-    while (*pszTemp)
+    while( *pszTemp )
     {
-        *pszTemp = static_cast<char>( tolower (*pszTemp) );
+        *pszTemp = static_cast<char>(tolower(*pszTemp));
         pszTemp++;
     }
 
@@ -332,10 +354,10 @@ char *CPLStrlwr( char *pszString )
  * from the file or NULL if the error or end of file was encountered.
  */
 
-char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
+char *CPLFGets( char *pszBuffer, int nBufferSize, FILE *fp )
 
 {
-    if ( nBufferSize == 0 || pszBuffer == NULL || fp == NULL )
+    if( nBufferSize == 0 || pszBuffer == NULL || fp == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
@@ -345,29 +367,29 @@ char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 /*      just the newline (LF).  If it is in binary mode it may well     */
 /*      have both.                                                      */
 /* -------------------------------------------------------------------- */
-    const long nOriginalOffset = VSIFTell( fp );
-    if( VSIFGets( pszBuffer, nBufferSize, fp ) == NULL )
+    const long nOriginalOffset = VSIFTell(fp);
+    if( VSIFGets(pszBuffer, nBufferSize, fp) == NULL )
         return NULL;
 
-    int nActuallyRead = static_cast<int>( strlen(pszBuffer) );
-    if ( nActuallyRead == 0 )
+    int nActuallyRead = static_cast<int>(strlen(pszBuffer));
+    if( nActuallyRead == 0 )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      If we found \r and out buffer is full, it is possible there     */
 /*      is also a pending \n.  Check for it.                            */
 /* -------------------------------------------------------------------- */
-    if( nBufferSize == nActuallyRead+1
-        && pszBuffer[nActuallyRead-1] == 13 )
+    if( nBufferSize == nActuallyRead + 1 &&
+        pszBuffer[nActuallyRead - 1] == 13 )
     {
-        const int chCheck = fgetc( fp );
+        const int chCheck = fgetc(fp);
         if( chCheck != 10 )
         {
             // unget the character.
-            if (VSIFSeek( fp, nOriginalOffset+nActuallyRead, SEEK_SET ) == -1)
+            if( VSIFSeek(fp, nOriginalOffset + nActuallyRead, SEEK_SET) == -1 )
             {
-                CPLError( CE_Failure, CPLE_FileIO,
-                          "Unable to unget a character");
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "Unable to unget a character");
             }
         }
     }
@@ -376,16 +398,16 @@ char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 /*      Trim off \n, \r or \r\n if it appears at the end.  We don't     */
 /*      need to do any "seeking" since we want the newline eaten.       */
 /* -------------------------------------------------------------------- */
-    if( nActuallyRead > 1
-        && pszBuffer[nActuallyRead-1] == 10
-        && pszBuffer[nActuallyRead-2] == 13 )
+    if( nActuallyRead > 1 &&
+        pszBuffer[nActuallyRead-1] == 10 &&
+        pszBuffer[nActuallyRead-2] == 13 )
     {
-        pszBuffer[nActuallyRead-2] = '\0';
+        pszBuffer[nActuallyRead - 2] = '\0';
     }
-    else if( pszBuffer[nActuallyRead-1] == 10
-             || pszBuffer[nActuallyRead-1] == 13 )
+    else if( pszBuffer[nActuallyRead - 1] == 10 ||
+             pszBuffer[nActuallyRead - 1] == 13 )
     {
-        pszBuffer[nActuallyRead-1] = '\0';
+        pszBuffer[nActuallyRead - 1] = '\0';
     }
 
 /* -------------------------------------------------------------------- */
@@ -393,37 +415,35 @@ char *CPLFGets( char *pszBuffer, int nBufferSize, FILE * fp )
 /*      apparently), and if we find it we need to trim the string,      */
 /*      and seek back.                                                  */
 /* -------------------------------------------------------------------- */
-    char *pszExtraNewline = strchr( pszBuffer, 13 );
+    char *pszExtraNewline = strchr(pszBuffer, 13);
 
     if( pszExtraNewline != NULL )
     {
         nActuallyRead = static_cast<int>(pszExtraNewline - pszBuffer + 1);
 
         *pszExtraNewline = '\0';
-        if( VSIFSeek( fp, nOriginalOffset + nActuallyRead - 1, SEEK_SET ) != 0)
+        if( VSIFSeek(fp, nOriginalOffset + nActuallyRead - 1, SEEK_SET) != 0)
             return NULL;
 
-        /*
-         * This hackery is necessary to try and find our correct
-         * spot on win32 systems with text mode line translation going
-         * on.  Sometimes the fseek back overshoots, but it doesn't
-         * "realize it" till a character has been read. Try to read till
-         * we get to the right spot and get our CR.
-         */
-        int chCheck = fgetc( fp );
-        while( (chCheck != 13 && chCheck != EOF)
-               || VSIFTell(fp) < nOriginalOffset + nActuallyRead )
+        // This hackery is necessary to try and find our correct
+        // spot on win32 systems with text mode line translation going
+        // on.  Sometimes the fseek back overshoots, but it doesn't
+        // "realize it" till a character has been read. Try to read till
+        // we get to the right spot and get our CR.
+        int chCheck = fgetc(fp);
+        while( (chCheck != 13 && chCheck != EOF) ||
+               VSIFTell(fp) < nOriginalOffset + nActuallyRead )
         {
             static bool bWarned = false;
 
             if( !bWarned )
             {
                 bWarned = true;
-                CPLDebug( "CPL",
-                          "CPLFGets() correcting for DOS text mode translation "
-                          "seek problem." );
+                CPLDebug("CPL",
+                         "CPLFGets() correcting for DOS text mode translation "
+                         "seek problem.");
             }
-            chCheck = fgetc( fp );
+            chCheck = fgetc(fp);
         }
     }
 
@@ -450,11 +470,11 @@ static char *CPLReadLineBuffer( int nRequiredSize )
     if( nRequiredSize == -1 )
     {
         int bMemoryError = FALSE;
-        void* pRet = CPLGetTLSEx( CTLS_RLBUFFERINFO, &bMemoryError );
+        void *pRet = CPLGetTLSEx(CTLS_RLBUFFERINFO, &bMemoryError);
         if( pRet != NULL )
         {
-            CPLFree( pRet );
-            CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
+            CPLFree(pRet);
+            CPLSetTLS(CTLS_RLBUFFERINFO, NULL, FALSE);
         }
         return NULL;
     }
@@ -463,51 +483,51 @@ static char *CPLReadLineBuffer( int nRequiredSize )
 /*      If the buffer doesn't exist yet, create it.                     */
 /* -------------------------------------------------------------------- */
     int bMemoryError = FALSE;
-    GUInt32 *pnAlloc = reinterpret_cast<GUInt32 *>(
-        CPLGetTLSEx( CTLS_RLBUFFERINFO, &bMemoryError ) );
+    GUInt32 *pnAlloc =
+        static_cast<GUInt32 *>(CPLGetTLSEx(CTLS_RLBUFFERINFO, &bMemoryError));
     if( bMemoryError )
         return NULL;
 
     if( pnAlloc == NULL )
     {
-        pnAlloc = reinterpret_cast<GUInt32 *>( VSI_MALLOC_VERBOSE(200) );
+        pnAlloc = static_cast<GUInt32 *>(VSI_MALLOC_VERBOSE(200));
         if( pnAlloc == NULL )
             return NULL;
         *pnAlloc = 196;
-        CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
+        CPLSetTLS(CTLS_RLBUFFERINFO, pnAlloc, TRUE);
     }
 
 /* -------------------------------------------------------------------- */
 /*      If it is too small, grow it bigger.                             */
 /* -------------------------------------------------------------------- */
-    if( static_cast<int>( *pnAlloc ) - 1 < nRequiredSize )
+    if( static_cast<int>(*pnAlloc) - 1 < nRequiredSize )
     {
-        int nNewSize = nRequiredSize + 4 + 500;
-        if (nNewSize <= 0)
+        const int nNewSize = nRequiredSize + 4 + 500;
+        if( nNewSize <= 0 )
         {
-            VSIFree( pnAlloc );
-            CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
-            CPLError( CE_Failure, CPLE_OutOfMemory,
-                      "CPLReadLineBuffer(): Trying to allocate more than "
-                      "2 GB." );
+            VSIFree(pnAlloc);
+            CPLSetTLS(CTLS_RLBUFFERINFO, NULL, FALSE);
+            CPLError(CE_Failure, CPLE_OutOfMemory,
+                     "CPLReadLineBuffer(): Trying to allocate more than "
+                     "2 GB.");
             return NULL;
         }
 
-        GUInt32* pnAllocNew = reinterpret_cast<GUInt32 *>(
-            VSI_REALLOC_VERBOSE( pnAlloc, nNewSize ) );
+        GUInt32 *pnAllocNew =
+            static_cast<GUInt32 *>(VSI_REALLOC_VERBOSE(pnAlloc, nNewSize));
         if( pnAllocNew == NULL )
         {
-            VSIFree( pnAlloc );
-            CPLSetTLS( CTLS_RLBUFFERINFO, NULL, FALSE );
+            VSIFree(pnAlloc);
+            CPLSetTLS(CTLS_RLBUFFERINFO, NULL, FALSE);
             return NULL;
         }
         pnAlloc = pnAllocNew;
 
         *pnAlloc = nNewSize - 4;
-        CPLSetTLS( CTLS_RLBUFFERINFO, pnAlloc, TRUE );
+        CPLSetTLS(CTLS_RLBUFFERINFO, pnAlloc, TRUE);
     }
 
-    return reinterpret_cast<char *>( pnAlloc + 1 );
+    return reinterpret_cast<char *>(pnAlloc + 1);
 }
 
 /************************************************************************/
@@ -520,7 +540,7 @@ static char *CPLReadLineBuffer( int nRequiredSize )
  * Read a line of text from the given file handle, taking care
  * to capture CR and/or LF and strip off ... equivalent of
  * DKReadLine().  Pointer to an internal buffer is returned.
- * The application shouldn't free it, or depend on it's value
+ * The application shouldn't free it, or depend on its value
  * past the next call to CPLReadLine().
  *
  * Note that CPLReadLine() uses VSIFGets(), so any hooking of VSI file
@@ -536,7 +556,7 @@ static char *CPLReadLineBuffer( int nRequiredSize )
  * from the file or NULL if the end of file was encountered.
  */
 
-const char *CPLReadLine( FILE * fp )
+const char *CPLReadLine( FILE *fp )
 
 {
 /* -------------------------------------------------------------------- */
@@ -544,7 +564,7 @@ const char *CPLReadLine( FILE * fp )
 /* -------------------------------------------------------------------- */
     if( fp == NULL )
     {
-        CPLReadLineBuffer( -1 );
+        CPLReadLineBuffer(-1);
         return NULL;
     }
 
@@ -553,7 +573,7 @@ const char *CPLReadLine( FILE * fp )
 /*      the line.                                                       */
 /* -------------------------------------------------------------------- */
     size_t nBytesReadThisTime = 0;
-    char* pszRLBuffer = NULL;
+    char *pszRLBuffer = NULL;
     size_t nReadSoFar = 0;
 
     do {
@@ -563,25 +583,24 @@ const char *CPLReadLine( FILE * fp )
 /*      instance for a _very large_ file with no newlines).             */
 /* -------------------------------------------------------------------- */
         if( nReadSoFar > 100 * 1024 * 1024 )
-             // It is dubious that we need to read a line longer than 100 MB.
+            // It is dubious that we need to read a line longer than 100 MB.
             return NULL;
-        pszRLBuffer = CPLReadLineBuffer( static_cast<int>(nReadSoFar) + 129 );
+        pszRLBuffer = CPLReadLineBuffer(static_cast<int>(nReadSoFar) + 129);
         if( pszRLBuffer == NULL )
             return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      Do the actual read.                                             */
 /* -------------------------------------------------------------------- */
-        if( CPLFGets( pszRLBuffer+nReadSoFar, 128, fp ) == NULL
-            && nReadSoFar == 0 )
+        if( CPLFGets(pszRLBuffer + nReadSoFar, 128, fp) == NULL &&
+            nReadSoFar == 0 )
             return NULL;
 
-        nBytesReadThisTime = strlen(pszRLBuffer+nReadSoFar);
+        nBytesReadThisTime = strlen(pszRLBuffer + nReadSoFar);
         nReadSoFar += nBytesReadThisTime;
-
-    } while( nBytesReadThisTime >= 127
-             && pszRLBuffer[nReadSoFar-1] != 13
-             && pszRLBuffer[nReadSoFar-1] != 10 );
+    } while( nBytesReadThisTime >= 127 &&
+             pszRLBuffer[nReadSoFar - 1] != 13 &&
+             pszRLBuffer[nReadSoFar - 1] != 10 );
 
     return pszRLBuffer;
 }
@@ -601,10 +620,7 @@ const char *CPLReadLine( FILE * fp )
  * from the file or NULL if the end of file was encountered.
  */
 
-const char *CPLReadLineL( VSILFILE * fp )
-{
-    return CPLReadLine2L( fp, -1, NULL );
-}
+const char *CPLReadLineL(VSILFILE *fp) { return CPLReadLine2L(fp, -1, NULL); }
 
 /************************************************************************/
 /*                           CPLReadLine2L()                            */
@@ -626,8 +642,8 @@ const char *CPLReadLineL( VSILFILE * fp )
  * @since GDAL 1.7.0
  */
 
-const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
-                           char** /*papszOptions */ )
+const char *CPLReadLine2L( VSILFILE *fp, int nMaxCars,
+                           CPL_UNUSED const char *const *papszOptions )
 
 {
 /* -------------------------------------------------------------------- */
@@ -635,7 +651,7 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
 /* -------------------------------------------------------------------- */
     if( fp == NULL )
     {
-        CPLReadLineBuffer( -1 );
+        CPLReadLineBuffer(-1);
         return NULL;
     }
 
@@ -645,7 +661,7 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
 /* -------------------------------------------------------------------- */
     char *pszRLBuffer = NULL;
     const size_t nChunkSize = 40;
-    char szChunk[nChunkSize];
+    char szChunk[nChunkSize] = {};
     size_t nChunkBytesRead = 0;
     int nBufLength = 0;
     size_t nChunkBytesConsumed = 0;
@@ -657,15 +673,16 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
 /* -------------------------------------------------------------------- */
 /*      Read a chunk from the input file.                               */
 /* -------------------------------------------------------------------- */
-        if ( nBufLength > INT_MAX - static_cast<int>(nChunkSize) - 1 )
+        if( nBufLength > INT_MAX - static_cast<int>(nChunkSize) - 1 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Too big line : more than 2 billion characters!." );
-            CPLReadLineBuffer( -1 );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Too big line : more than 2 billion characters!.");
+            CPLReadLineBuffer(-1);
             return NULL;
         }
 
-        pszRLBuffer = CPLReadLineBuffer( static_cast<int>(nBufLength + nChunkSize + 1) );
+        pszRLBuffer =
+            CPLReadLineBuffer(static_cast<int>(nBufLength + nChunkSize + 1));
         if( pszRLBuffer == NULL )
             return NULL;
 
@@ -676,14 +693,14 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
             szChunk[0] = szChunk[nChunkBytesConsumed];
 
             nChunkBytesConsumed = 0;
-            nChunkBytesRead = VSIFReadL( szChunk+1, 1, nChunkSize-1, fp ) + 1;
+            nChunkBytesRead = VSIFReadL(szChunk + 1, 1, nChunkSize - 1, fp) + 1;
         }
         else
         {
             nChunkBytesConsumed = 0;
 
             // fresh read.
-            nChunkBytesRead = VSIFReadL( szChunk, 1, nChunkSize, fp );
+            nChunkBytesRead = VSIFReadL(szChunk, 1, nChunkSize, fp);
             if( nChunkBytesRead == 0 )
             {
                 if( nBufLength == 0 )
@@ -697,12 +714,12 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
 /*      copy over characters watching for end-of-line.                  */
 /* -------------------------------------------------------------------- */
         bool bBreak = false;
-        while( nChunkBytesConsumed < nChunkBytesRead-1 && !bBreak )
+        while( nChunkBytesConsumed < nChunkBytesRead - 1 && !bBreak )
         {
-            if( (szChunk[nChunkBytesConsumed] == 13
-                 && szChunk[nChunkBytesConsumed+1] == 10)
-                || (szChunk[nChunkBytesConsumed] == 10
-                    && szChunk[nChunkBytesConsumed+1] == 13) )
+            if( (szChunk[nChunkBytesConsumed] == 13 &&
+                 szChunk[nChunkBytesConsumed+1] == 10) ||
+                (szChunk[nChunkBytesConsumed] == 10 &&
+                 szChunk[nChunkBytesConsumed+1] == 13) )
             {
                 nChunkBytesConsumed += 2;
                 bBreak = true;
@@ -716,10 +733,10 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
             else
             {
                 pszRLBuffer[nBufLength++] = szChunk[nChunkBytesConsumed++];
-                if (nMaxCars >= 0 && nBufLength == nMaxCars)
+                if( nMaxCars >= 0 && nBufLength == nMaxCars )
                 {
-                    CPLError( CE_Failure, CPLE_AppDefined,
-                              "Maximum number of characters allowed reached." );
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Maximum number of characters allowed reached.");
                     return NULL;
                 }
             }
@@ -733,11 +750,11 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
 /*      consume it.  If it is a newline, but we are clearly at the      */
 /*      end of the file then consume it.                                */
 /* -------------------------------------------------------------------- */
-        if( nChunkBytesConsumed == nChunkBytesRead-1
-            && nChunkBytesRead < nChunkSize )
+        if( nChunkBytesConsumed == nChunkBytesRead - 1 &&
+            nChunkBytesRead < nChunkSize )
         {
-            if( szChunk[nChunkBytesConsumed] == 10
-                || szChunk[nChunkBytesConsumed] == 13 )
+            if( szChunk[nChunkBytesConsumed] == 10 ||
+                szChunk[nChunkBytesConsumed] == 13 )
             {
                 nChunkBytesConsumed++;
                 break;
@@ -756,7 +773,7 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
     {
         const size_t nBytesToPush = nChunkBytesRead - nChunkBytesConsumed;
 
-        if( VSIFSeekL( fp, VSIFTellL( fp ) - nBytesToPush, SEEK_SET ) != 0 )
+        if( VSIFSeekL(fp, VSIFTellL(fp) - nBytesToPush, SEEK_SET) != 0 )
             return NULL;
     }
 
@@ -792,32 +809,32 @@ const char *CPLReadLine2L( VSILFILE * fp, int nMaxCars,
 char *CPLScanString( const char *pszString, int nMaxLength,
                      int bTrimSpaces, int bNormalize )
 {
-    if ( !pszString )
+    if( !pszString )
         return NULL;
 
-    if ( !nMaxLength )
-        return CPLStrdup( "" );
+    if( !nMaxLength )
+        return CPLStrdup("");
 
-    char *pszBuffer = reinterpret_cast<char *>( CPLMalloc( nMaxLength + 1 ) );
-    if ( !pszBuffer )
+    char *pszBuffer = static_cast<char *>(CPLMalloc(nMaxLength + 1));
+    if( !pszBuffer )
         return NULL;
 
-    strncpy( pszBuffer, pszString,  nMaxLength );
+    strncpy(pszBuffer, pszString, nMaxLength);
     pszBuffer[nMaxLength] = '\0';
 
-    if ( bTrimSpaces )
+    if( bTrimSpaces )
     {
-        size_t i = strlen( pszBuffer );
-        while ( i-- > 0 && isspace((unsigned char)pszBuffer[i]) )
+        size_t i = strlen(pszBuffer);
+        while( i-- > 0 && isspace(static_cast<unsigned char>(pszBuffer[i])) )
             pszBuffer[i] = '\0';
     }
 
-    if ( bNormalize )
+    if( bNormalize )
     {
-        size_t i = strlen( pszBuffer );
-        while ( i-- > 0 )
+        size_t i = strlen(pszBuffer);
+        while( i-- > 0 )
         {
-            if ( pszBuffer[i] == ':' )
+            if( pszBuffer[i] == ':' )
                 pszBuffer[i] = '_';
         }
     }
@@ -845,15 +862,14 @@ char *CPLScanString( const char *pszString, int nMaxLength,
 
 long CPLScanLong( const char *pszString, int nMaxLength )
 {
-    CPLAssert( nMaxLength >= 0 );
+    CPLAssert(nMaxLength >= 0);
     if( pszString == NULL )
         return 0;
     const size_t nLength = CPLStrnlen(pszString, nMaxLength);
-    const std::string osValue( pszString, nLength );
-    return atol( osValue.c_str() );
+    const std::string osValue(pszString, nLength);
+    return atol(osValue.c_str());
 }
 
-
 /************************************************************************/
 /*                            CPLScanULong()                            */
 /************************************************************************/
@@ -874,12 +890,12 @@ long CPLScanLong( const char *pszString, int nMaxLength )
 
 unsigned long CPLScanULong( const char *pszString, int nMaxLength )
 {
-    CPLAssert( nMaxLength >= 0 );
+    CPLAssert(nMaxLength >= 0);
     if( pszString == NULL )
         return 0;
     const size_t nLength = CPLStrnlen(pszString, nMaxLength);
-    const std::string osValue( pszString, nLength );
-    return strtoul( osValue.c_str(), NULL, 10 );
+    const std::string osValue(pszString, nLength);
+    return strtoul(osValue.c_str(), NULL, 10);
 }
 
 /************************************************************************/
@@ -904,21 +920,21 @@ unsigned long CPLScanULong( const char *pszString, int nMaxLength )
 
 GUIntBig CPLScanUIntBig( const char *pszString, int nMaxLength )
 {
-    CPLAssert( nMaxLength >= 0 );
+    CPLAssert(nMaxLength >= 0);
     if( pszString == NULL )
         return 0;
     const size_t nLength = CPLStrnlen(pszString, nMaxLength);
-    const std::string osValue( pszString, nLength );
+    const std::string osValue(pszString, nLength);
 
 /* -------------------------------------------------------------------- */
 /*      Fetch out the result                                            */
 /* -------------------------------------------------------------------- */
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
-    return static_cast<GUIntBig>( _atoi64( osValue.c_str() ) );
-# elif HAVE_ATOLL
-    return atoll( osValue.c_str() );
+    return static_cast<GUIntBig>(_atoi64(osValue.c_str()));
+#elif HAVE_ATOLL
+    return atoll(osValue.c_str());
 #else
-    return = atol( osValue.c_str() );
+    return atol(osValue.c_str());
 #endif
 }
 
@@ -934,14 +950,14 @@ GUIntBig CPLScanUIntBig( const char *pszString, int nMaxLength )
  * @since GDAL 2.0
  */
 
-GIntBig CPLAtoGIntBig( const char* pszString )
+GIntBig CPLAtoGIntBig( const char *pszString )
 {
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
-    return _atoi64( pszString );
-# elif HAVE_ATOLL
-    return atoll( pszString );
+    return _atoi64(pszString);
+#elif HAVE_ATOLL
+    return atoll(pszString);
 #else
-    return atol( pszString );
+    return atol(pszString);
 #endif
 }
 
@@ -953,10 +969,10 @@ static int CPLAtoGIntBigExHasOverflow(const char* pszString, GIntBig nVal)
     if( strlen(pszString) <= 18 )
         return FALSE;
     while( *pszString == ' ' )
-        pszString ++;
+        pszString++;
     if( *pszString == '+' )
-        pszString ++;
-    char szBuffer[32];
+        pszString++;
+    char szBuffer[32] = {};
 /* x86_64-w64-mingw32-g++ (GCC) 4.8.2 annoyingly warns */
 #ifdef HAVE_GCC_DIAGNOSTIC_PUSH
 #pragma GCC diagnostic push
@@ -980,7 +996,8 @@ static int CPLAtoGIntBigExHasOverflow(const char* pszString, GIntBig nVal)
  *
  * @param pszString String containing 64 bit signed integer.
  * @param bWarn Issue a warning if an overflow occurs during conversion
- * @param pbOverflow Pointer to an integer to store if an overflow occurred, or NULL
+ * @param pbOverflow Pointer to an integer to store if an overflow occurred, or
+ *        NULL
  * @return 64 bit signed integer.
  * @since GDAL 2.0
  */
@@ -989,11 +1006,11 @@ GIntBig CPLAtoGIntBigEx( const char* pszString, int bWarn, int *pbOverflow )
 {
     errno = 0;
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
-    GIntBig nVal = _atoi64( pszString );
-# elif HAVE_ATOLL
-    GIntBig nVal = atoll( pszString );
+    GIntBig nVal = _atoi64(pszString);
+#elif HAVE_ATOLL
+    GIntBig nVal = atoll(pszString);
 #else
-    GIntBig nVal = atol( pszString );
+    GIntBig nVal = atol(pszString);
 #endif
     if( errno == ERANGE
 #if defined(__MINGW32__) || defined(__sun__)
@@ -1001,7 +1018,8 @@ GIntBig CPLAtoGIntBigEx( const char* pszString, int bWarn, int *pbOverflow )
 #endif
         )
     {
-        if( pbOverflow ) *pbOverflow = TRUE;
+        if( pbOverflow )
+            *pbOverflow = TRUE;
         if( bWarn )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
@@ -1009,10 +1027,13 @@ GIntBig CPLAtoGIntBigEx( const char* pszString, int bWarn, int *pbOverflow )
                      pszString);
         }
         while( *pszString == ' ' )
-            pszString ++;
-        return (*pszString == '-' ) ? GINTBIG_MIN : GINTBIG_MAX;
+            pszString++;
+        return (*pszString == '-') ? GINTBIG_MIN : GINTBIG_MAX;
+    }
+    else if( pbOverflow )
+    {
+        *pbOverflow = FALSE;
     }
-    else if( pbOverflow ) *pbOverflow = FALSE;
     return nVal;
 }
 
@@ -1038,7 +1059,7 @@ GIntBig CPLAtoGIntBigEx( const char* pszString, int bWarn, int *pbOverflow )
 
 void *CPLScanPointer( const char *pszString, int nMaxLength )
 {
-    char  szTemp[128];
+    char szTemp[128] = {};
 
 /* -------------------------------------------------------------------- */
 /*      Compute string into local buffer, and terminate it.             */
@@ -1046,7 +1067,7 @@ void *CPLScanPointer( const char *pszString, int nMaxLength )
     if( nMaxLength > static_cast<int>( sizeof(szTemp) ) - 1 )
         nMaxLength = sizeof(szTemp) - 1;
 
-    strncpy( szTemp, pszString, nMaxLength );
+    strncpy(szTemp, pszString, nMaxLength);
     szTemp[nMaxLength] = '\0';
 
 /* -------------------------------------------------------------------- */
@@ -1058,23 +1079,26 @@ void *CPLScanPointer( const char *pszString, int nMaxLength )
         void *pResult = NULL;
 
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
-        sscanf( szTemp+2, "%p", &pResult );
+        // cppcheck-suppress invalidscanf
+        sscanf(szTemp + 2, "%p", &pResult);
 #else
-        sscanf( szTemp, "%p", &pResult );
+        // cppcheck-suppress invalidscanf
+        sscanf(szTemp, "%p", &pResult);
 
-        /* Solaris actually behaves like MSVCRT... */
-        if (pResult == NULL)
+        // Solaris actually behaves like MSVCRT.
+        if( pResult == NULL )
         {
-            sscanf( szTemp+2, "%p", &pResult );
+            // cppcheck-suppress invalidscanf
+            sscanf(szTemp + 2, "%p", &pResult);
         }
 #endif
         return pResult;
     }
 
 #if SIZEOF_VOIDP == 8
-    return reinterpret_cast<void *>( CPLScanUIntBig( szTemp, nMaxLength ) );
+    return reinterpret_cast<void *>(CPLScanUIntBig(szTemp, nMaxLength));
 #else
-    return reinterpret_cast<void *>( CPLScanULong( szTemp, nMaxLength ) );
+    return reinterpret_cast<void *>(CPLScanULong(szTemp, nMaxLength));
 #endif
 }
 
@@ -1101,34 +1125,34 @@ void *CPLScanPointer( const char *pszString, int nMaxLength )
 
 double CPLScanDouble( const char *pszString, int nMaxLength )
 {
-    char        szValue[32];
-    char        *pszValue;
+    char szValue[32] = {};
+    char *pszValue = NULL;
 
-    if( nMaxLength + 1 < static_cast<int>( sizeof(szValue) ) )
+    if( nMaxLength + 1 < static_cast<int>(sizeof(szValue)) )
         pszValue = szValue;
     else
-        pszValue = reinterpret_cast<char *>( CPLMalloc( nMaxLength + 1 ) );
+        pszValue = static_cast<char *>(CPLMalloc(nMaxLength + 1));
 
 /* -------------------------------------------------------------------- */
 /*      Compute string into local buffer, and terminate it.             */
 /* -------------------------------------------------------------------- */
-    strncpy( pszValue, pszString, nMaxLength );
+    strncpy(pszValue, pszString, nMaxLength);
     pszValue[nMaxLength] = '\0';
 
 /* -------------------------------------------------------------------- */
 /*      Make a pass through converting 'D's to 'E's.                    */
 /* -------------------------------------------------------------------- */
     for( int i = 0; i < nMaxLength; i++ )
-        if ( pszValue[i] == 'd' || pszValue[i] == 'D' )
+        if( pszValue[i] == 'd' || pszValue[i] == 'D' )
             pszValue[i] = 'E';
 
 /* -------------------------------------------------------------------- */
 /*      The conversion itself.                                          */
 /* -------------------------------------------------------------------- */
-    const double dfValue = CPLAtof( pszValue );
+    const double dfValue = CPLAtof(pszValue);
 
     if( pszValue != szValue )
-        CPLFree( pszValue );
+        CPLFree(pszValue);
     return dfValue;
 }
 
@@ -1153,19 +1177,19 @@ double CPLScanDouble( const char *pszString, int nMaxLength )
 
 int CPLPrintString( char *pszDest, const char *pszSrc, int nMaxLen )
 {
-    if ( !pszDest )
+    if( !pszDest )
         return 0;
 
-    if ( !pszSrc )
+    if( !pszSrc )
     {
         *pszDest = '\0';
         return 1;
     }
 
-    int  nChars = 0;
+    int nChars = 0;
     char *pszTemp = pszDest;
 
-    while ( nChars < nMaxLen && *pszSrc )
+    while( nChars < nMaxLen && *pszSrc )
     {
         *pszTemp++ = *pszSrc++;
         nChars++;
@@ -1197,24 +1221,24 @@ int CPLPrintString( char *pszDest, const char *pszSrc, int nMaxLen )
 
 int CPLPrintStringFill( char *pszDest, const char *pszSrc, int nMaxLen )
 {
-    if ( !pszDest )
+    if( !pszDest )
         return 0;
 
-    if ( !pszSrc )
+    if( !pszSrc )
     {
-        memset( pszDest, ' ', nMaxLen );
+        memset(pszDest, ' ', nMaxLen);
         return nMaxLen;
     }
 
     char *pszTemp = pszDest;
-    while ( nMaxLen && *pszSrc )
+    while( nMaxLen && *pszSrc )
     {
         *pszTemp++ = *pszSrc++;
         nMaxLen--;
     }
 
-    if ( nMaxLen )
-        memset( pszTemp, ' ', nMaxLen );
+    if( nMaxLen )
+        memset(pszTemp, ' ', nMaxLen);
 
     return nMaxLen;
 }
@@ -1241,21 +1265,21 @@ int CPLPrintStringFill( char *pszDest, const char *pszSrc, int nMaxLen )
 
 int CPLPrintInt32( char *pszBuffer, GInt32 iValue, int nMaxLen )
 {
-    if ( !pszBuffer )
+    if( !pszBuffer )
         return 0;
 
-    if ( nMaxLen >= 64 )
+    if( nMaxLen >= 64 )
         nMaxLen = 63;
 
-    char    szTemp[64];
+    char szTemp[64] = {};
 
 #if UINT_MAX == 65535
-    snprintf( szTemp, sizeof(szTemp), "%*ld", nMaxLen, iValue );
+    snprintf(szTemp, sizeof(szTemp), "%*ld", nMaxLen, iValue);
 #else
-    snprintf( szTemp, sizeof(szTemp), "%*d", nMaxLen, iValue );
+    snprintf(szTemp, sizeof(szTemp), "%*d", nMaxLen, iValue);
 #endif
 
-    return CPLPrintString( pszBuffer, szTemp, nMaxLen );
+    return CPLPrintString(pszBuffer, szTemp, nMaxLen);
 }
 
 /************************************************************************/
@@ -1280,13 +1304,13 @@ int CPLPrintInt32( char *pszBuffer, GInt32 iValue, int nMaxLen )
 
 int CPLPrintUIntBig( char *pszBuffer, GUIntBig iValue, int nMaxLen )
 {
-    if ( !pszBuffer )
+    if( !pszBuffer )
         return 0;
 
-    if ( nMaxLen >= 64 )
+    if( nMaxLen >= 64 )
         nMaxLen = 63;
 
-    char szTemp[64];
+    char szTemp[64] = {};
 
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
 /* x86_64-w64-mingw32-g++ (GCC) 4.8.2 annoyingly warns */
@@ -1295,18 +1319,17 @@ int CPLPrintUIntBig( char *pszBuffer, GUIntBig iValue, int nMaxLen )
 #pragma GCC diagnostic ignored "-Wformat"
 #pragma GCC diagnostic ignored "-Wformat-extra-args"
 #endif
-    snprintf( szTemp, sizeof(szTemp), "%*I64d", nMaxLen, iValue );
+    snprintf(szTemp, sizeof(szTemp), "%*I64u", nMaxLen, iValue);
 #ifdef HAVE_GCC_DIAGNOSTIC_PUSH
 #pragma GCC diagnostic pop
 #endif
-# elif HAVE_LONG_LONG
-    snprintf( szTemp, sizeof(szTemp), "%*lld", nMaxLen, (long long) iValue );
-//    sprintf( szTemp, "%*Ld", nMaxLen, (long long) iValue );
+#elif HAVE_LONG_LONG
+    snprintf(szTemp, sizeof(szTemp), "%*llu", nMaxLen, iValue);
 #else
-    snprintf( szTemp, sizeof(szTemp), "%*ld", nMaxLen, iValue );
+    snprintf(szTemp, sizeof(szTemp), "%*lu", nMaxLen, iValue);
 #endif
 
-    return CPLPrintString( pszBuffer, szTemp, nMaxLen );
+    return CPLPrintString(pszBuffer, szTemp, nMaxLen);
 }
 
 /************************************************************************/
@@ -1331,24 +1354,24 @@ int CPLPrintUIntBig( char *pszBuffer, GUIntBig iValue, int nMaxLen )
 
 int CPLPrintPointer( char *pszBuffer, void *pValue, int nMaxLen )
 {
-    if ( !pszBuffer )
+    if( !pszBuffer )
         return 0;
 
-    if ( nMaxLen >= 64 )
+    if( nMaxLen >= 64 )
         nMaxLen = 63;
 
-    char szTemp[64];
+    char szTemp[64] = {};
 
-    snprintf( szTemp, sizeof(szTemp), "%p", pValue );
+    snprintf(szTemp, sizeof(szTemp), "%p", pValue);
 
     // On windows, and possibly some other platforms the sprintf("%p")
     // does not prefix things with 0x so it is hard to know later if the
     // value is hex encoded.  Fix this up here.
 
     if( !STARTS_WITH_CI(szTemp, "0x") )
-        snprintf( szTemp, sizeof(szTemp), "0x%p", pValue );
+        snprintf(szTemp, sizeof(szTemp), "0x%p", pValue);
 
-    return CPLPrintString( pszBuffer, szTemp, nMaxLen );
+    return CPLPrintString(pszBuffer, szTemp, nMaxLen);
 }
 
 /************************************************************************/
@@ -1368,26 +1391,21 @@ int CPLPrintPointer( char *pszBuffer, void *pValue, int nMaxLen )
  *
  * @param dfValue Numerical value to print.
  *
- * @param pszLocale Pointer to a character string containing locale name
- * ("C", "POSIX", "us_US", "ru_RU.KOI8-R" etc.). If NULL we will not
- * manipulate with locale settings and current process locale will be used for
- * printing. With the pszLocale option we can control what exact locale
- * will be used for printing a numeric value to the string (in most cases
- * it should be C/POSIX).
+ * @param pszLocale Unused.
  *
  * @return Number of characters printed.
  */
 
 int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
-                    double dfValue, const char * /* pszLocale */ )
+                    double dfValue, CPL_UNUSED const char *pszLocale )
 {
-    if ( !pszBuffer )
+    if( !pszBuffer )
         return 0;
 
     const int double_buffer_size = 64;
-    char szTemp[double_buffer_size];
+    char szTemp[double_buffer_size] = {};
 
-    CPLsnprintf( szTemp, double_buffer_size, pszFormat, dfValue );
+    CPLsnprintf(szTemp, double_buffer_size, pszFormat, dfValue);
     szTemp[double_buffer_size - 1] = '\0';
 
     for( int i = 0; szTemp[i] != '\0'; i++ )
@@ -1439,35 +1457,35 @@ int CPLPrintDouble( char *pszBuffer, const char *pszFormat,
 int CPLPrintTime( char *pszBuffer, int nMaxLen, const char *pszFormat,
                   const struct tm *poBrokenTime, const char *pszLocale )
 {
-    char *pszTemp = reinterpret_cast<char *>(
-        CPLMalloc( (nMaxLen + 1) * sizeof(char) ) );
+    char *pszTemp =
+        static_cast<char *>(CPLMalloc((nMaxLen + 1) * sizeof(char)));
 
 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
-    char        *pszCurLocale = NULL;
+    char *pszCurLocale = NULL;
 
-    if ( pszLocale || EQUAL( pszLocale, "" ) )
+    if( pszLocale || EQUAL(pszLocale, "") )
     {
-        // Save the current locale
-        pszCurLocale = CPLsetlocale(LC_ALL, NULL );
-        // Set locale to the specified value
-        CPLsetlocale( LC_ALL, pszLocale );
+        // Save the current locale.
+        pszCurLocale = CPLsetlocale(LC_ALL, NULL);
+        // Set locale to the specified value.
+        CPLsetlocale(LC_ALL, pszLocale);
     }
 #else
-    (void) pszLocale;
+    (void)pszLocale;
 #endif
 
-    if ( !strftime( pszTemp, nMaxLen + 1, pszFormat, poBrokenTime ) )
-        memset( pszTemp, 0, nMaxLen + 1);
+    if( !strftime(pszTemp, nMaxLen + 1, pszFormat, poBrokenTime) )
+        memset(pszTemp, 0, nMaxLen + 1);
 
 #if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE)
-    // Restore stored locale back
-    if ( pszCurLocale )
+    // Restore stored locale back.
+    if( pszCurLocale )
         CPLsetlocale( LC_ALL, pszCurLocale );
 #endif
 
-    const int nChars = CPLPrintString( pszBuffer, pszTemp, nMaxLen );
+    const int nChars = CPLPrintString(pszBuffer, pszTemp, nMaxLen);
 
-    CPLFree( pszTemp );
+    CPLFree(pszTemp);
 
     return nChars;
 }
@@ -1480,7 +1498,8 @@ void CPLVerifyConfiguration()
 
 {
     static bool verified = false;
-    if (!verified) {
+    if( !verified )
+    {
         return;
     }
     verified = true;
@@ -1488,30 +1507,30 @@ void CPLVerifyConfiguration()
 /* -------------------------------------------------------------------- */
 /*      Verify data types.                                              */
 /* -------------------------------------------------------------------- */
-    CPL_STATIC_ASSERT( sizeof(GInt32) == 4 );
-    CPL_STATIC_ASSERT( sizeof(GInt16) == 2 );
-    CPL_STATIC_ASSERT( sizeof(GByte) == 1 );
+    CPL_STATIC_ASSERT(sizeof(GInt32) == 4);
+    CPL_STATIC_ASSERT(sizeof(GInt16) == 2);
+    CPL_STATIC_ASSERT(sizeof(GByte) == 1);
 
 /* -------------------------------------------------------------------- */
 /*      Verify byte order                                               */
 /* -------------------------------------------------------------------- */
-    GInt32   nTest = 1;
+    GInt32 nTest = 1;
 
 #ifdef CPL_LSB
-    if( reinterpret_cast<GByte *>( &nTest )[0] != 1 )
+    if( reinterpret_cast<GByte *>(&nTest)[0] != 1 )
 #endif
 #ifdef CPL_MSB
-    if( reinterpret_cast<GByte *>( &nTest )[3] != 1 )
+    if( reinterpret_cast<GByte *>(&nTest)[3] != 1 )
 #endif
-        CPLError( CE_Fatal, CPLE_AppDefined,
-                  "CPLVerifyConfiguration(): byte order set wrong.\n" );
+        CPLError(CE_Fatal, CPLE_AppDefined,
+                 "CPLVerifyConfiguration(): byte order set wrong.");
 }
 
 #ifdef DEBUG_CONFIG_OPTIONS
 
-static void* hRegisterConfigurationOptionMutex = 0;
-static std::set<CPLString>* paoGetKeys = NULL;
-static std::set<CPLString>* paoSetKeys = NULL;
+static void *hRegisterConfigurationOptionMutex = 0;
+static std::set<CPLString> *paoGetKeys = NULL;
+static std::set<CPLString> *paoSetKeys = NULL;
 
 /************************************************************************/
 /*                      CPLShowAccessedOptions()                        */
@@ -1521,37 +1540,38 @@ static void CPLShowAccessedOptions()
 {
     std::set<CPLString>::iterator aoIter;
 
-    printf("Configuration options accessed in reading : "),
+    printf("Configuration options accessed in reading : "); /*ok*/
     aoIter = paoGetKeys->begin();
-    while(aoIter != paoGetKeys->end())
+    while( aoIter != paoGetKeys->end() )
     {
-        printf("%s, ", (*aoIter).c_str());
-        aoIter ++;
+        printf("%s, ", (*aoIter).c_str()); /*ok*/
+        ++aoIter;
     }
-    printf("\n");
+    printf("\n");/*ok*/
 
-    printf("Configuration options accessed in writing : "),
+    printf("Configuration options accessed in writing : "); /*ok*/
     aoIter = paoSetKeys->begin();
-    while(aoIter != paoSetKeys->end())
+    while( aoIter != paoSetKeys->end() )
     {
-        printf("%s, ", (*aoIter).c_str());
-        aoIter ++;
+        printf("%s, ", (*aoIter).c_str()); /*ok*/
+        ++aoIter;
     }
-    printf("\n");
+    printf("\n"); /*ok*/
 
     delete paoGetKeys;
     delete paoSetKeys;
-    paoGetKeys = paoSetKeys = NULL;
+    paoGetKeys = NULL;
+    paoSetKeys = NULL;
 }
 
 /************************************************************************/
 /*                       CPLAccessConfigOption()                        */
 /************************************************************************/
 
-static void CPLAccessConfigOption(const char* pszKey, bool bGet)
+static void CPLAccessConfigOption( const char *pszKey, bool bGet )
 {
     CPLMutexHolderD(&hRegisterConfigurationOptionMutex);
-    if (paoGetKeys == NULL)
+    if( paoGetKeys == NULL )
     {
         paoGetKeys = new std::set<CPLString>;
         paoSetKeys = new std::set<CPLString>;
@@ -1572,7 +1592,8 @@ static void CPLAccessConfigOption(const char* pszKey, bool bGet)
   * Get the value of a configuration option.
   *
   * The value is the value of a (key, value) option set with
-  * CPLSetConfigOption().  If the given option was no defined with
+  * CPLSetConfigOption(), or CPLSetThreadLocalConfigOption() of the same
+  * thread. If the given option was no defined with
   * CPLSetConfigOption(), it tries to find it in environment variables.
   *
   * Note: the string returned by CPLGetConfigOption() might be short-lived, and
@@ -1612,19 +1633,20 @@ CPLGetConfigOption( const char *pszKey, const char *pszDefault )
 
     int bMemoryError = FALSE;
     char **papszTLConfigOptions = reinterpret_cast<char **>(
-        CPLGetTLSEx( CTLS_CONFIGOPTIONS, &bMemoryError ) );
+        CPLGetTLSEx(CTLS_CONFIGOPTIONS, &bMemoryError));
     if( papszTLConfigOptions != NULL )
-        pszResult = CSLFetchNameValue( papszTLConfigOptions, pszKey );
+        pszResult = CSLFetchNameValue(papszTLConfigOptions, pszKey);
 
     if( pszResult == NULL )
     {
-        CPLMutexHolderD( &hConfigMutex );
+        CPLMutexHolderD(&hConfigMutex);
 
-        pszResult = CSLFetchNameValue( (char **) papszConfigOptions, pszKey );
+        pszResult =
+            CSLFetchNameValue(const_cast<char **>(g_papszConfigOptions), pszKey);
     }
 
     if( pszResult == NULL )
-        pszResult = getenv( pszKey );
+        pszResult = getenv(pszKey);
 
     if( pszResult == NULL )
         return pszDefault;
@@ -1633,9 +1655,60 @@ CPLGetConfigOption( const char *pszKey, const char *pszDefault )
 }
 
 /************************************************************************/
+/*                         CPLGetConfigOptions()                        */
+/************************************************************************/
+
+/**
+  * Return the list of configuration options as KEY=VALUE pairs.
+  *
+  * The list is the one set through the CPLSetConfigOption() API.
+  *
+  * Options that through environment variables or with
+  * CPLSetThreadLocalConfigOption() will *not* be listed.
+  *
+  * @return a copy of the list, to be freed with CSLDestroy().
+  * @since GDAL 2.2
+  */
+char** CPLGetConfigOptions(void)
+{
+    CPLMutexHolderD(&hConfigMutex);
+    return CSLDuplicate(const_cast<char**>(g_papszConfigOptions));
+}
+
+/************************************************************************/
+/*                         CPLSetConfigOptions()                        */
+/************************************************************************/
+
+/**
+  * Replace the full list of configuration options with the passed list of
+  * KEY=VALUE pairs.
+  *
+  * This has the same effect of clearing the existing list, and setting
+  * individually each pair with the CPLSetConfigOption() API.
+  *
+  * This does not affect options set through environment variables or with
+  * CPLSetThreadLocalConfigOption().
+  *
+  * The passed list is copied by the function.
+  *
+  * @param papszConfigOptions the new list (or NULL).
+  *
+  * @since GDAL 2.2
+  */
+void CPLSetConfigOptions(const char* const * papszConfigOptions)
+{
+    CPLMutexHolderD(&hConfigMutex);
+    CSLDestroy(const_cast<char**>(g_papszConfigOptions));
+    g_papszConfigOptions = const_cast<volatile char**>(
+            CSLDuplicate(const_cast<char**>(papszConfigOptions)));
+}
+
+/************************************************************************/
 /*                   CPLGetThreadLocalConfigOption()                    */
 /************************************************************************/
 
+/** Same as CPLGetConfigOption() but only with options set with
+ * CPLSetThreadLocalConfigOption() */
 const char * CPL_STDCALL
 CPLGetThreadLocalConfigOption( const char *pszKey, const char *pszDefault )
 
@@ -1648,9 +1721,9 @@ CPLGetThreadLocalConfigOption( const char *pszKey, const char *pszDefault )
 
     int bMemoryError = FALSE;
     char **papszTLConfigOptions = reinterpret_cast<char **>(
-        CPLGetTLSEx( CTLS_CONFIGOPTIONS, &bMemoryError ) );
+        CPLGetTLSEx(CTLS_CONFIGOPTIONS, &bMemoryError));
     if( papszTLConfigOptions != NULL )
-        pszResult = CSLFetchNameValue( papszTLConfigOptions, pszKey );
+        pszResult = CSLFetchNameValue(papszTLConfigOptions, pszKey);
 
     if( pszResult == NULL )
         return pszDefault;
@@ -1695,10 +1768,11 @@ CPLSetConfigOption( const char *pszKey, const char *pszValue )
 #ifdef DEBUG_CONFIG_OPTIONS
     CPLAccessConfigOption(pszKey, FALSE);
 #endif
-    CPLMutexHolderD( &hConfigMutex );
+    CPLMutexHolderD(&hConfigMutex);
 
-    papszConfigOptions = (volatile char **)
-      CSLSetNameValue( (char **) papszConfigOptions, pszKey, pszValue );
+    g_papszConfigOptions = const_cast<volatile char **>(
+        CSLSetNameValue(
+            const_cast<char **>(g_papszConfigOptions), pszKey, pszValue));
 }
 
 /************************************************************************/
@@ -1706,9 +1780,9 @@ CPLSetConfigOption( const char *pszKey, const char *pszValue )
 /************************************************************************/
 
 /* non-stdcall wrapper function for CSLDestroy() (#5590) */
-static void CPLSetThreadLocalTLSFreeFunc( void* pData )
+static void CPLSetThreadLocalTLSFreeFunc( void *pData )
 {
-    CSLDestroy( reinterpret_cast<char**>( pData ) );
+    CSLDestroy(reinterpret_cast<char **>(pData));
 }
 
 /************************************************************************/
@@ -1723,11 +1797,14 @@ static void CPLSetThreadLocalTLSFreeFunc( void* pData )
   *
   * This function sets the configuration option that only applies in the
   * current thread, as opposed to CPLSetConfigOption() which sets an option
-  * that applies on all threads.
+  * that applies on all threads. CPLSetThreadLocalConfigOption() will override
+  * the effect of CPLSetConfigOption) for the current thread.
   *
   * This function can also be used to clear a setting by passing NULL as the
-  * value (note: passing NULL will not unset an existing environment variable;
-  * it will just unset a value previously set by CPLSetThreadLocalConfigOption()).
+  * value (note: passing NULL will not unset an existing environment variable or
+  * a value set through CPLSetConfigOption();
+  * it will just unset a value previously set by
+  * CPLSetThreadLocalConfigOption()).
   *
   * @param pszKey the key of the option
   * @param pszValue the value of the option, or NULL to clear a setting.
@@ -1743,15 +1820,71 @@ CPLSetThreadLocalConfigOption( const char *pszKey, const char *pszValue )
 
     int bMemoryError = FALSE;
     char **papszTLConfigOptions = reinterpret_cast<char **>(
-        CPLGetTLSEx( CTLS_CONFIGOPTIONS, &bMemoryError ) );
+        CPLGetTLSEx(CTLS_CONFIGOPTIONS, &bMemoryError));
     if( bMemoryError )
         return;
 
     papszTLConfigOptions =
-        CSLSetNameValue( papszTLConfigOptions, pszKey, pszValue );
+        CSLSetNameValue(papszTLConfigOptions, pszKey, pszValue);
 
-    CPLSetTLSWithFreeFunc( CTLS_CONFIGOPTIONS, papszTLConfigOptions,
-                           CPLSetThreadLocalTLSFreeFunc );
+    CPLSetTLSWithFreeFunc(CTLS_CONFIGOPTIONS, papszTLConfigOptions,
+                          CPLSetThreadLocalTLSFreeFunc);
+}
+
+/************************************************************************/
+/*                   CPLGetThreadLocalConfigOptions()                   */
+/************************************************************************/
+
+/**
+  * Return the list of thread local configuration options as KEY=VALUE pairs.
+  *
+  * Options that through environment variables or with
+  * CPLSetConfigOption() will *not* be listed.
+  *
+  * @return a copy of the list, to be freed with CSLDestroy().
+  * @since GDAL 2.2
+  */
+char** CPLGetThreadLocalConfigOptions(void)
+{
+    int bMemoryError = FALSE;
+    char **papszTLConfigOptions = reinterpret_cast<char **>(
+        CPLGetTLSEx(CTLS_CONFIGOPTIONS, &bMemoryError));
+    if( bMemoryError )
+        return NULL;
+    return CSLDuplicate(papszTLConfigOptions);
+}
+
+/************************************************************************/
+/*                   CPLSetThreadLocalConfigOptions()                   */
+/************************************************************************/
+
+/**
+  * Replace the full list of thread local configuration options with the
+  * passed list of KEY=VALUE pairs.
+  *
+  * This has the same effect of clearing the existing list, and setting
+  * individually each pair with the CPLSetThreadLocalConfigOption() API.
+  *
+  * This does not affect options set through environment variables or with
+  * CPLSetConfigOption().
+  *
+  * The passed list is copied by the function.
+  *
+  * @param papszConfigOptions the new list (or NULL).
+  *
+  * @since GDAL 2.2
+  */
+void CPLSetThreadLocalConfigOptions(const char* const * papszConfigOptions)
+{
+    int bMemoryError = FALSE;
+    char **papszTLConfigOptions = reinterpret_cast<char **>(
+        CPLGetTLSEx(CTLS_CONFIGOPTIONS, &bMemoryError));
+    if( bMemoryError )
+        return;
+    CSLDestroy(papszTLConfigOptions);
+    papszTLConfigOptions = CSLDuplicate(const_cast<char**>(papszConfigOptions));
+    CPLSetTLSWithFreeFunc(CTLS_CONFIGOPTIONS, papszTLConfigOptions,
+                          CPLSetThreadLocalTLSFreeFunc);
 }
 
 /************************************************************************/
@@ -1762,62 +1895,58 @@ void CPL_STDCALL CPLFreeConfig()
 
 {
     {
-        CPLMutexHolderD( &hConfigMutex );
+        CPLMutexHolderD(&hConfigMutex);
 
-        CSLDestroy( (char **) papszConfigOptions);
-        papszConfigOptions = NULL;
+        CSLDestroy(const_cast<char **>(g_papszConfigOptions));
+        g_papszConfigOptions = NULL;
 
         int bMemoryError = FALSE;
         char **papszTLConfigOptions = reinterpret_cast<char **>(
-            CPLGetTLSEx( CTLS_CONFIGOPTIONS, &bMemoryError ) );
+            CPLGetTLSEx(CTLS_CONFIGOPTIONS, &bMemoryError));
         if( papszTLConfigOptions != NULL )
         {
-            CSLDestroy( papszTLConfigOptions );
-            CPLSetTLS( CTLS_CONFIGOPTIONS, NULL, FALSE );
+            CSLDestroy(papszTLConfigOptions);
+            CPLSetTLS(CTLS_CONFIGOPTIONS, NULL, FALSE);
         }
     }
-    CPLDestroyMutex( hConfigMutex );
+    CPLDestroyMutex(hConfigMutex);
     hConfigMutex = NULL;
 }
 
 /************************************************************************/
 /*                              CPLStat()                               */
-/*                                                                      */
-/*      Same as VSIStat() except it works on "C:" as if it were         */
-/*      "C:\".                                                          */
 /************************************************************************/
 
+/** Same as VSIStat() except it works on "C:" as if it were "C:\". */
+
 int CPLStat( const char *pszPath, VSIStatBuf *psStatBuf )
 
 {
     if( strlen(pszPath) == 2 && pszPath[1] == ':' )
     {
-        char szAltPath[4] = { pszPath[0], pszPath[1], '\\', '\0' };
-        return VSIStat( szAltPath, psStatBuf );
+        char szAltPath[4] = {pszPath[0], pszPath[1], '\\', '\0'};
+        return VSIStat(szAltPath, psStatBuf);
     }
 
-    return VSIStat( pszPath, psStatBuf );
+    return VSIStat(pszPath, psStatBuf);
 }
 
 /************************************************************************/
 /*                            proj_strtod()                             */
 /************************************************************************/
-static double
-proj_strtod(char *nptr, char **endptr)
+static double proj_strtod(char *nptr, char **endptr)
 
 {
-    char c, *cp = nptr;
+    char c = '\0';
+    char *cp = nptr;
 
-    /*
-     * Scan for characters which cause problems with VC++ strtod()
-     */
-    while ((c = *cp) != '\0') {
-        if (c == 'd' || c == 'D') {
-
-            /*
-             * Found one, so NUL it out, call strtod(),
-             * then restore it and return
-             */
+    // Scan for characters which cause problems with VC++ strtod().
+    while( (c = *cp) != '\0')
+    {
+        if( c == 'd' || c == 'D' )
+        {
+            // Found one, so NUL it out, call strtod(),
+            // then restore it and return.
             *cp = '\0';
             const double result = CPLStrtod(nptr, endptr);
             *cp = c;
@@ -1826,7 +1955,7 @@ proj_strtod(char *nptr, char **endptr)
         ++cp;
     }
 
-    /* no offending characters, just handle normally */
+    // No offending characters, just handle normally.
 
     return CPLStrtod(nptr, endptr);
 }
@@ -1835,49 +1964,57 @@ proj_strtod(char *nptr, char **endptr)
 /*                            CPLDMSToDec()                             */
 /************************************************************************/
 
-static const char*sym = "NnEeSsWw";
+static const char *sym = "NnEeSsWw";
 static const double vm[] = { 1.0, 0.0166666666667, 0.00027777778 };
 
+/** CPLDMSToDec */
 double CPLDMSToDec( const char *is )
 
 {
     int sign = 0;
 
-    /* copy sting into work space */
-    while (isspace(static_cast<unsigned char>(sign = *is)))
+    // Copy string into work space.
+    while( isspace(static_cast<unsigned char>(sign = *is)) )
         ++is;
 
-    char *p = const_cast<char *>( is );
-    char work[64];
+    const char *p = is;
+    char work[64] = {};
     char *s = work;
     int n = sizeof(work);
-    for( ;
-         isgraph(*p) && --n ; )
+    for( ; isgraph(*p) && --n; )
         *s++ = *p++;
     *s = '\0';
-    /* it is possible that a really odd input (like lots of leading
-       zeros) could be truncated in copying into work.  But ... */
+    // It is possible that a really odd input (like lots of leading
+    // zeros) could be truncated in copying into work.  But...
     sign = *(s = work);
 
-    if (sign == '+' || sign == '-') s++;
-    else sign = '+';
+    if( sign == '+' || sign == '-' )
+        s++;
+    else
+        sign = '+';
 
     int nl = 0;
     double v = 0.0;
-    for ( ; nl < 3 ; nl = n + 1 ) {
-        if (!(isdigit(*s) || *s == '.')) break;
+    for( ; nl < 3; nl = n + 1 )
+    {
+        if( !(isdigit(*s) || *s == '.') )
+            break;
         const double tv = proj_strtod(s, &s);
         if( tv == HUGE_VAL )
             return tv;
-        switch (*s) {
-          case 'D': case 'd':
+        switch( *s )
+        {
+          case 'D':
+          case 'd':
             n = 0; break;
           case '\'':
             n = 1; break;
           case '"':
             n = 2; break;
-          case 'r': case 'R':
-            if (nl) {
+          case 'r':
+          case 'R':
+            if( nl )
+            {
                 return 0.0;
             }
             ++s;
@@ -1885,76 +2022,77 @@ double CPLDMSToDec( const char *is )
             goto skip;
           default:
             v += tv * vm[nl];
-          skip: n = 4;
+          skip:
+            n = 4;
             continue;
         }
-        if (n < nl) {
+        if( n < nl )
+        {
             return 0.0;
         }
         v += tv * vm[n];
         ++s;
     }
-    /* postfix sign */
-    if (*s && ((p = (char *) strchr(sym, *s))) != NULL) {
+    // Postfix sign.
+    if( *s && ((p = strchr(sym, *s))) != NULL )
+    {
         sign = (p - sym) >= 4 ? '-' : '+';
         ++s;
     }
-    if (sign == '-')
+    if( sign == '-' )
         v = -v;
 
     return v;
 }
 
-
 /************************************************************************/
 /*                            CPLDecToDMS()                             */
-/*                                                                      */
-/*      Translate a decimal degrees value to a DMS string with          */
-/*      hemisphere.                                                     */
 /************************************************************************/
 
+/** Translate a decimal degrees value to a DMS string with hemisphere. */
+
 const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
                          int nPrecision )
 
 {
-    VALIDATE_POINTER1( pszAxis, "CPLDecToDMS", "" );
+    VALIDATE_POINTER1(pszAxis, "CPLDecToDMS", "");
 
     if( CPLIsNan(dfAngle) )
         return "Invalid angle";
 
-    const double dfEpsilon = (0.5/3600.0) * pow(0.1,nPrecision);
-    const double dfABSAngle = ABS(dfAngle) + dfEpsilon;
-    if (dfABSAngle > 361)
+    const double dfEpsilon = (0.5 / 3600.0) * pow(0.1, nPrecision);
+    const double dfABSAngle = std::abs(dfAngle) + dfEpsilon;
+    if( dfABSAngle > 361.0 )
     {
         return "Invalid angle";
     }
 
-    const int nDegrees = (int) dfABSAngle;
-    const int nMinutes = (int) ((dfABSAngle - nDegrees) * 60);
-    double dfSeconds = dfABSAngle * 3600 - nDegrees*3600 - nMinutes*60;
+    const int nDegrees = static_cast<int>(dfABSAngle);
+    const int nMinutes = static_cast<int>((dfABSAngle - nDegrees) * 60);
+    double dfSeconds = dfABSAngle * 3600 - nDegrees * 3600 - nMinutes * 60;
 
     if( dfSeconds > dfEpsilon * 3600.0 )
         dfSeconds -= dfEpsilon * 3600.0;
 
-    const char  *pszHemisphere;
-    if( EQUAL(pszAxis,"Long") && dfAngle < 0.0 )
+    const char *pszHemisphere = NULL;
+    if( EQUAL(pszAxis, "Long") && dfAngle < 0.0 )
         pszHemisphere = "W";
-    else if( EQUAL(pszAxis,"Long") )
+    else if( EQUAL(pszAxis, "Long") )
         pszHemisphere = "E";
     else if( dfAngle < 0.0 )
         pszHemisphere = "S";
     else
         pszHemisphere = "N";
 
-    char szFormat[30];
-    CPLsnprintf( szFormat, sizeof(szFormat),
-                 "%%3dd%%2d\'%%%d.%df\"%s",
-                 nPrecision+3, nPrecision, pszHemisphere );
+    char szFormat[30] = {};
+    CPLsnprintf(szFormat, sizeof(szFormat),
+                "%%3dd%%2d\'%%%d.%df\"%s",
+                nPrecision+3, nPrecision, pszHemisphere);
 
-    static CPL_THREADLOCAL char szBuffer[50] = { 0 };
-    CPLsnprintf( szBuffer, sizeof(szBuffer),
-                 szFormat,
-                 nDegrees, nMinutes, dfSeconds );
+    static CPL_THREADLOCAL char szBuffer[50] = {};
+    CPLsnprintf(szBuffer, sizeof(szBuffer),
+                szFormat,
+                nDegrees, nMinutes, dfSeconds);
 
     return szBuffer;
 }
@@ -2008,14 +2146,14 @@ const char *CPLDecToDMS( double dfAngle, const char * pszAxis,
 
 double CPLPackedDMSToDec( double dfPacked )
 {
-    const double dfSign = ( dfPacked < 0.0 )? -1 : 1;
+    const double dfSign = dfPacked < 0.0 ? -1 : 1;
 
-    double dfSeconds = ABS( dfPacked );
+    double dfSeconds = std::abs(dfPacked);
     double dfDegrees = floor(dfSeconds / 1000000.0);
     dfSeconds -= dfDegrees * 1000000.0;
-    double dfMinutes = floor(dfSeconds / 1000.0);
+    const double dfMinutes = floor(dfSeconds / 1000.0);
     dfSeconds -= dfMinutes * 1000.0;
-    dfSeconds = dfSign * ( dfDegrees * 3600.0 + dfMinutes * 60.0 + dfSeconds);
+    dfSeconds = dfSign * (dfDegrees * 3600.0 + dfMinutes * 60.0 + dfSeconds);
     dfDegrees = dfSeconds / 3600.0;
 
     return dfDegrees;
@@ -2042,12 +2180,12 @@ double CPLPackedDMSToDec( double dfPacked )
 
 double CPLDecToPackedDMS( double dfDec )
 {
-    const double dfSign = ( dfDec < 0.0 ) ? -1 : 1;
+    const double dfSign = dfDec < 0.0 ? -1 : 1;
 
-    dfDec = ABS( dfDec );
-    const double dfDegrees = floor( dfDec );
-    const double dfMinutes = floor( ( dfDec - dfDegrees ) * 60.0 );
-    const double dfSeconds = ( dfDec - dfDegrees ) * 3600.0 - dfMinutes * 60.0;
+    dfDec = std::abs(dfDec);
+    const double dfDegrees = floor(dfDec);
+    const double dfMinutes = floor((dfDec - dfDegrees) * 60.0);
+    const double dfSeconds = (dfDec - dfDegrees) * 3600.0 - dfMinutes * 60.0;
 
     return dfSign * (dfDegrees * 1000000.0 + dfMinutes * 1000.0 + dfSeconds);
 }
@@ -2056,6 +2194,7 @@ double CPLDecToPackedDMS( double dfDec )
 /*                         CPLStringToComplex()                         */
 /************************************************************************/
 
+/** Fetch the real and imaginary part of a serialized complex number */
 void CPL_DLL CPLStringToComplex( const char *pszString,
                                  double *pdfReal, double *pdfImag )
 
@@ -2070,7 +2209,7 @@ void CPL_DLL CPLStringToComplex( const char *pszString,
     int iImagEnd = -1;
 
     for( int i = 0;
-         pszString[i] != '\0' && pszString[i] != ' ' && i < 100;
+         i < 100 && pszString[i] != '\0' && pszString[i] != ' ';
          i++ )
     {
         if( pszString[i] == '+' && i > 0 )
@@ -2112,30 +2251,31 @@ void CPL_DLL CPLStringToComplex( const char *pszString,
  *
  * @param pszFilename the name of the file to open.
  * @param pszAccess the normal fopen()/VSIFOpen() style access string.
- * @param bLarge If TRUE VSIFOpenL() (for large files) will be used instead of
+ * @param bLargeIn If TRUE VSIFOpenL() (for large files) will be used instead of
  * VSIFOpen().
  *
  * @return a file handle or NULL if opening fails.
  */
 
 FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
-                     int bLarge )
+                     int bLargeIn )
 
 {
-    CPLMutexHolderD( &hSharedFileMutex );
+    const bool bLarge = CPL_TO_BOOL(bLargeIn);
+    CPLMutexHolderD(&hSharedFileMutex);
     const GIntBig nPID = CPLGetPID();
 
 /* -------------------------------------------------------------------- */
 /*      Is there an existing file we can use?                           */
 /* -------------------------------------------------------------------- */
-    const bool bReuse = EQUAL(pszAccess,"rb") || EQUAL(pszAccess, "rb+");
+    const bool bReuse = EQUAL(pszAccess, "rb") || EQUAL(pszAccess, "rb+");
 
     for( int i = 0; bReuse && i < nSharedFileCount; i++ )
     {
-        if( strcmp(pasSharedFileList[i].pszFilename,pszFilename) == 0
-            && !bLarge == !pasSharedFileList[i].bLarge
-            && EQUAL(pasSharedFileList[i].pszAccess,pszAccess)
-            && nPID == pasSharedFileListExtra[i].nPID)
+        if( strcmp(pasSharedFileList[i].pszFilename, pszFilename) == 0 &&
+            !bLarge == !pasSharedFileList[i].bLarge &&
+            EQUAL(pasSharedFileList[i].pszAccess, pszAccess) &&
+            nPID == pasSharedFileListExtra[i].nPID)
         {
             pasSharedFileList[i].nRefCount++;
             return pasSharedFileList[i].fp;
@@ -2145,12 +2285,9 @@ FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
 /* -------------------------------------------------------------------- */
 /*      Open the file.                                                  */
 /* -------------------------------------------------------------------- */
-    FILE *fp;
-
-    if( bLarge )
-        fp = reinterpret_cast<FILE *>( VSIFOpenL( pszFilename, pszAccess ) );
-    else
-        fp = VSIFOpen( pszFilename, pszAccess );
+    FILE *fp = bLarge
+        ? reinterpret_cast<FILE *>(VSIFOpenL(pszFilename, pszAccess))
+        : VSIFOpen(pszFilename, pszAccess);
 
     if( fp == NULL )
         return NULL;
@@ -2160,19 +2297,21 @@ FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
 /* -------------------------------------------------------------------- */
     nSharedFileCount++;
 
-    pasSharedFileList = reinterpret_cast<CPLSharedFileInfo *>(
-        CPLRealloc( (void *) pasSharedFileList,
-                    sizeof(CPLSharedFileInfo) * nSharedFileCount ) );
-    pasSharedFileListExtra = reinterpret_cast<CPLSharedFileInfoExtra *>(
-        CPLRealloc( (void *) pasSharedFileListExtra,
-                    sizeof(CPLSharedFileInfoExtra) * nSharedFileCount ) );
-
-    pasSharedFileList[nSharedFileCount-1].fp = fp;
-    pasSharedFileList[nSharedFileCount-1].nRefCount = 1;
-    pasSharedFileList[nSharedFileCount-1].bLarge = bLarge;
-    pasSharedFileList[nSharedFileCount-1].pszFilename =CPLStrdup(pszFilename);
-    pasSharedFileList[nSharedFileCount-1].pszAccess = CPLStrdup(pszAccess);
-    pasSharedFileListExtra[nSharedFileCount-1].nPID = nPID;
+    pasSharedFileList = static_cast<CPLSharedFileInfo *>(
+        CPLRealloc(const_cast<CPLSharedFileInfo *>(pasSharedFileList),
+                   sizeof(CPLSharedFileInfo) * nSharedFileCount));
+    pasSharedFileListExtra = static_cast<CPLSharedFileInfoExtra *>(
+        CPLRealloc(
+            const_cast<CPLSharedFileInfoExtra *>(pasSharedFileListExtra),
+            sizeof(CPLSharedFileInfoExtra) * nSharedFileCount));
+
+    pasSharedFileList[nSharedFileCount - 1].fp = fp;
+    pasSharedFileList[nSharedFileCount - 1].nRefCount = 1;
+    pasSharedFileList[nSharedFileCount - 1].bLarge = bLarge;
+    pasSharedFileList[nSharedFileCount - 1].pszFilename =
+        CPLStrdup(pszFilename);
+    pasSharedFileList[nSharedFileCount - 1].pszAccess = CPLStrdup(pszAccess);
+    pasSharedFileListExtra[nSharedFileCount - 1].nPID = nPID;
 
     return fp;
 }
@@ -2194,19 +2333,19 @@ FILE *CPLOpenShared( const char *pszFilename, const char *pszAccess,
 void CPLCloseShared( FILE * fp )
 
 {
-    CPLMutexHolderD( &hSharedFileMutex );
+    CPLMutexHolderD(&hSharedFileMutex);
 
 /* -------------------------------------------------------------------- */
 /*      Search for matching information.                                */
 /* -------------------------------------------------------------------- */
     int i = 0;
-    for( ; i < nSharedFileCount && fp != pasSharedFileList[i].fp; i++ ){}
+    for( ; i < nSharedFileCount && fp != pasSharedFileList[i].fp; i++ ) {}
 
     if( i == nSharedFileCount )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to find file handle %p in CPLCloseShared().",
-                  fp );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to find file handle %p in CPLCloseShared().",
+                 fp);
         return;
     }
 
@@ -2221,36 +2360,41 @@ void CPLCloseShared( FILE * fp )
 /* -------------------------------------------------------------------- */
     if( pasSharedFileList[i].bLarge )
     {
-        if( VSIFCloseL( reinterpret_cast<VSILFILE *>( pasSharedFileList[i].fp ) ) != 0 )
+        if( VSIFCloseL(reinterpret_cast<VSILFILE *>(pasSharedFileList[i].fp)) !=
+            0 )
         {
             CPLError(CE_Failure, CPLE_FileIO, "Error while closing %s",
-                     pasSharedFileList[i].pszFilename );
+                     pasSharedFileList[i].pszFilename);
         }
     }
     else
-        VSIFClose( pasSharedFileList[i].fp );
+    {
+        VSIFClose(pasSharedFileList[i].fp);
+    }
 
-    CPLFree( pasSharedFileList[i].pszFilename );
-    CPLFree( pasSharedFileList[i].pszAccess );
+    CPLFree(pasSharedFileList[i].pszFilename);
+    CPLFree(pasSharedFileList[i].pszAccess);
 
-    nSharedFileCount --;
-    memmove( (void *) (pasSharedFileList + i),
-             (void *) (pasSharedFileList + nSharedFileCount),
-             sizeof(CPLSharedFileInfo) );
-    memmove( (void *) (pasSharedFileListExtra + i),
-             (void *) (pasSharedFileListExtra + nSharedFileCount),
-             sizeof(CPLSharedFileInfoExtra) );
+    nSharedFileCount--;
+    memmove(
+        const_cast<CPLSharedFileInfo *>(pasSharedFileList + i),
+        const_cast<CPLSharedFileInfo *>(pasSharedFileList + nSharedFileCount),
+        sizeof(CPLSharedFileInfo));
+    memmove(
+        const_cast<CPLSharedFileInfoExtra *>(pasSharedFileListExtra + i),
+        const_cast<CPLSharedFileInfoExtra *>(pasSharedFileListExtra +
+                                             nSharedFileCount),
+        sizeof(CPLSharedFileInfoExtra));
 
     if( nSharedFileCount == 0 )
     {
-        CPLFree( (void *) pasSharedFileList );
+        CPLFree(const_cast<CPLSharedFileInfo *>(pasSharedFileList));
         pasSharedFileList = NULL;
-        CPLFree( (void *) pasSharedFileListExtra );
+        CPLFree(const_cast<CPLSharedFileInfoExtra *>(pasSharedFileListExtra));
         pasSharedFileListExtra = NULL;
     }
 }
 
-
 /************************************************************************/
 /*                   CPLCleanupSharedFileMutex()                        */
 /************************************************************************/
@@ -2283,7 +2427,7 @@ CPLSharedFileInfo *CPLGetSharedList( int *pnCount )
     if( pnCount != NULL )
         *pnCount = nSharedFileCount;
 
-    return (CPLSharedFileInfo *) pasSharedFileList;
+    return const_cast<CPLSharedFileInfo *>(pasSharedFileList);
 }
 
 /************************************************************************/
@@ -2305,26 +2449,26 @@ void CPLDumpSharedList( FILE *fp )
     if( nSharedFileCount > 0 )
     {
         if( fp == NULL )
-            CPLDebug( "CPL", "%d Shared files open.", nSharedFileCount );
+            CPLDebug("CPL", "%d Shared files open.", nSharedFileCount);
         else
-            fprintf( fp, "%d Shared files open.", nSharedFileCount );
+            fprintf(fp, "%d Shared files open.", nSharedFileCount);
     }
 
     for( int i = 0; i < nSharedFileCount; i++ )
     {
         if( fp == NULL )
-            CPLDebug( "CPL",
-                      "%2d %d %4s %s",
-                      pasSharedFileList[i].nRefCount,
-                      pasSharedFileList[i].bLarge,
-                      pasSharedFileList[i].pszAccess,
-                      pasSharedFileList[i].pszFilename );
-        else
-            fprintf( fp, "%2d %d %4s %s",
+            CPLDebug("CPL",
+                     "%2d %d %4s %s",
                      pasSharedFileList[i].nRefCount,
                      pasSharedFileList[i].bLarge,
                      pasSharedFileList[i].pszAccess,
-                     pasSharedFileList[i].pszFilename );
+                     pasSharedFileList[i].pszFilename);
+        else
+            fprintf(fp, "%2d %d %4s %s",
+                    pasSharedFileList[i].nRefCount,
+                    pasSharedFileList[i].bLarge,
+                    pasSharedFileList[i].pszAccess,
+                    pasSharedFileList[i].pszFilename);
     }
 }
 
@@ -2332,7 +2476,8 @@ void CPLDumpSharedList( FILE *fp )
 /*                           CPLUnlinkTree()                            */
 /************************************************************************/
 
-/**
+/** Recursively unlink a directory.
+ *
  * @return 0 on successful completion, -1 if function fails.
  */
 
@@ -2344,11 +2489,11 @@ int CPLUnlinkTree( const char *pszPath )
 /* -------------------------------------------------------------------- */
     VSIStatBufL sStatBuf;
 
-    if( VSIStatL( pszPath, &sStatBuf ) != 0 )
+    if( VSIStatL(pszPath, &sStatBuf) != 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "It seems no file system object called '%s' exists.",
-                  pszPath );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "It seems no file system object called '%s' exists.",
+                 pszPath);
 
         return -1;
     }
@@ -2356,12 +2501,12 @@ int CPLUnlinkTree( const char *pszPath )
 /* -------------------------------------------------------------------- */
 /*      If it's a simple file, just delete it.                          */
 /* -------------------------------------------------------------------- */
-    if( VSI_ISREG( sStatBuf.st_mode ) )
+    if( VSI_ISREG(sStatBuf.st_mode) )
     {
-        if( VSIUnlink( pszPath ) != 0 )
+        if( VSIUnlink(pszPath) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
-                      pszPath );
+            CPLError(CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
+                     pszPath);
 
             return -1;
         }
@@ -2372,34 +2517,33 @@ int CPLUnlinkTree( const char *pszPath )
 /* -------------------------------------------------------------------- */
 /*      If it is a directory recurse then unlink the directory.         */
 /* -------------------------------------------------------------------- */
-    else if( VSI_ISDIR( sStatBuf.st_mode ) )
+    else if( VSI_ISDIR(sStatBuf.st_mode) )
     {
-        char **papszItems = VSIReadDir( pszPath );
+        char **papszItems = VSIReadDir(pszPath);
 
         for( int i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
         {
-            if( EQUAL(papszItems[i],".") || EQUAL(papszItems[i],"..") )
+            if( EQUAL(papszItems[i], ".") || EQUAL(papszItems[i], "..") )
                 continue;
 
-            char *pszSubPath = CPLStrdup(
-                CPLFormFilename( pszPath, papszItems[i], NULL ) );
+            const std::string osSubPath =
+                CPLFormFilename(pszPath, papszItems[i], NULL);
 
-            const int nErr = CPLUnlinkTree( pszSubPath );
-            CPLFree( pszSubPath );
+            const int nErr = CPLUnlinkTree(osSubPath.c_str());
 
             if( nErr != 0 )
             {
-                CSLDestroy( papszItems );
+                CSLDestroy(papszItems);
                 return nErr;
             }
         }
 
-        CSLDestroy( papszItems );
+        CSLDestroy(papszItems);
 
-        if( VSIRmdir( pszPath ) != 0 )
+        if( VSIRmdir(pszPath) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
-                      pszPath );
+            CPLError(CE_Failure, CPLE_AppDefined, "Failed to unlink %s.",
+                     pszPath);
 
             return -1;
         }
@@ -2410,9 +2554,9 @@ int CPLUnlinkTree( const char *pszPath )
 /* -------------------------------------------------------------------- */
 /*      otherwise report an error.                                      */
 /* -------------------------------------------------------------------- */
-    CPLError( CE_Failure, CPLE_AppDefined,
-              "Failed to unlink %s.\nUnrecognised filesystem object.",
-              pszPath );
+    CPLError(CE_Failure, CPLE_AppDefined,
+             "Failed to unlink %s.\nUnrecognised filesystem object.",
+             pszPath);
     return 1000;
 }
 
@@ -2420,20 +2564,21 @@ int CPLUnlinkTree( const char *pszPath )
 /*                            CPLCopyFile()                             */
 /************************************************************************/
 
+/** Copy a file */
 int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
 
 {
 /* -------------------------------------------------------------------- */
 /*      Open old and new file.                                          */
 /* -------------------------------------------------------------------- */
-    VSILFILE *fpOld = VSIFOpenL( pszOldPath, "rb" );
+    VSILFILE *fpOld = VSIFOpenL(pszOldPath, "rb");
     if( fpOld == NULL )
         return -1;
 
-    VSILFILE *fpNew = VSIFOpenL( pszNewPath, "wb" );
+    VSILFILE *fpNew = VSIFOpenL(pszNewPath, "wb");
     if( fpNew == NULL )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fpOld ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpOld));
         return -1;
     }
 
@@ -2441,12 +2586,11 @@ int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
 /*      Prepare buffer.                                                 */
 /* -------------------------------------------------------------------- */
     const size_t nBufferSize = 1024 * 1024;
-    GByte *pabyBuffer
-        = reinterpret_cast<GByte *>( VSI_MALLOC_VERBOSE(nBufferSize) );
+    GByte *pabyBuffer = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nBufferSize));
     if( pabyBuffer == NULL )
     {
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fpNew ));
-        CPL_IGNORE_RET_VAL(VSIFCloseL( fpOld ));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpNew));
+        CPL_IGNORE_RET_VAL(VSIFCloseL(fpOld));
         return -1;
     }
 
@@ -2455,24 +2599,25 @@ int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
 /* -------------------------------------------------------------------- */
     size_t nBytesRead = 0;
     int nRet = 0;
-    do {
-        nBytesRead = VSIFReadL( pabyBuffer, 1, nBufferSize, fpOld );
+    do
+    {
+        nBytesRead = VSIFReadL(pabyBuffer, 1, nBufferSize, fpOld);
         if( long(nBytesRead) < 0 )
             nRet = -1;
 
-        if( nRet == 0
-            && VSIFWriteL( pabyBuffer, 1, nBytesRead, fpNew ) < nBytesRead )
+        if( nRet == 0 &&
+            VSIFWriteL(pabyBuffer, 1, nBytesRead, fpNew) < nBytesRead )
             nRet = -1;
     } while( nRet == 0 && nBytesRead == nBufferSize );
 
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    if( VSIFCloseL( fpNew ) != 0 )
+    if( VSIFCloseL(fpNew) != 0 )
         nRet = -1;
-    CPL_IGNORE_RET_VAL(VSIFCloseL( fpOld ));
+    CPL_IGNORE_RET_VAL(VSIFCloseL(fpOld));
 
-    CPLFree( pabyBuffer );
+    CPLFree(pabyBuffer);
 
     return nRet;
 }
@@ -2481,75 +2626,76 @@ int CPLCopyFile( const char *pszNewPath, const char *pszOldPath )
 /*                            CPLCopyTree()                             */
 /************************************************************************/
 
+/** Recursively copy a tree */
 int CPLCopyTree( const char *pszNewPath, const char *pszOldPath )
 
 {
     VSIStatBufL sStatBuf;
 
-    if( VSIStatL( pszOldPath, &sStatBuf ) != 0 )
+    if( VSIStatL(pszOldPath, &sStatBuf) != 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "It seems no file system object called '%s' exists.",
-                  pszOldPath );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "It seems no file system object called '%s' exists.",
+                 pszOldPath);
 
         return -1;
     }
-    if( VSIStatL( pszNewPath, &sStatBuf ) == 0 )
+    if( VSIStatL(pszNewPath, &sStatBuf) == 0 )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "It seems that a file system object called '%s' already exists.",
-                  pszNewPath );
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "It seems that a file system object called '%s' already exists.",
+            pszNewPath);
 
         return -1;
     }
 
-    if( VSI_ISDIR( sStatBuf.st_mode ) )
+    if( VSI_ISDIR(sStatBuf.st_mode) )
     {
-        if( VSIMkdir( pszNewPath, 0755 ) != 0 )
+        if( VSIMkdir(pszNewPath, 0755) != 0 )
         {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                    "Cannot create directory '%s'.",
-                    pszNewPath );
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "Cannot create directory '%s'.",
+                     pszNewPath);
 
             return -1;
         }
 
-        char **papszItems = VSIReadDir( pszOldPath );
+        char **papszItems = VSIReadDir(pszOldPath);
 
         for( int i = 0; papszItems != NULL && papszItems[i] != NULL; i++ )
         {
-            if( EQUAL(papszItems[i],".") || EQUAL(papszItems[i],"..") )
+            if( EQUAL(papszItems[i], ".") || EQUAL(papszItems[i], "..") )
                 continue;
 
-            char *pszNewSubPath = CPLStrdup(
-                CPLFormFilename( pszNewPath, papszItems[i], NULL ) );
-            char *pszOldSubPath = CPLStrdup(
-                CPLFormFilename( pszOldPath, papszItems[i], NULL ) );
+            const std::string osNewSubPath =
+                CPLFormFilename(pszNewPath, papszItems[i], NULL);
+            const std::string osOldSubPath =
+                CPLFormFilename(pszOldPath, papszItems[i], NULL);
 
-            const int nErr = CPLCopyTree( pszNewSubPath, pszOldSubPath );
+            const int nErr =
+                CPLCopyTree(osNewSubPath.c_str(), osOldSubPath.c_str());
 
-            CPLFree( pszNewSubPath );
-            CPLFree( pszOldSubPath );
 
             if( nErr != 0 )
             {
-                CSLDestroy( papszItems );
+                CSLDestroy(papszItems);
                 return nErr;
             }
         }
-        CSLDestroy( papszItems );
+        CSLDestroy(papszItems);
 
         return 0;
     }
-    else if( VSI_ISREG( sStatBuf.st_mode ) )
+    else if( VSI_ISREG(sStatBuf.st_mode) )
     {
-        return CPLCopyFile( pszNewPath, pszOldPath );
+        return CPLCopyFile(pszNewPath, pszOldPath);
     }
     else
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unrecognized filesystem object : '%s'.",
-                  pszOldPath );
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unrecognized filesystem object : '%s'.",
+                 pszOldPath);
         return -1;
     }
 }
@@ -2558,16 +2704,17 @@ int CPLCopyTree( const char *pszNewPath, const char *pszOldPath )
 /*                            CPLMoveFile()                             */
 /************************************************************************/
 
+/** Move a file */
 int CPLMoveFile( const char *pszNewPath, const char *pszOldPath )
 
 {
-    if( VSIRename( pszOldPath, pszNewPath ) == 0 )
+    if( VSIRename(pszOldPath, pszNewPath) == 0 )
         return 0;
 
-    const int nRet = CPLCopyFile( pszNewPath, pszOldPath );
+    const int nRet = CPLCopyFile(pszNewPath, pszOldPath);
 
     if( nRet == 0 )
-        VSIUnlink( pszOldPath );
+        VSIUnlink(pszOldPath);
     return nRet;
 }
 
@@ -2575,22 +2722,17 @@ int CPLMoveFile( const char *pszNewPath, const char *pszOldPath )
 /*                             CPLSymlink()                             */
 /************************************************************************/
 
-int CPLSymlink( const char*
-#ifndef WIN32
-                pszOldPath
-#endif
-                , const char*
-#ifndef WIN32
-                pszNewPath
-#endif
-                , char** /* papszOptions */)
-{
+/** Create a symbolic link */
 #ifdef WIN32
-    return -1;
+int CPLSymlink( const char *, const char *, char ** ) { return -1; }
 #else
+int CPLSymlink( const char *pszOldPath,
+                const char *pszNewPath,
+                char** /* papszOptions */ )
+{
     return symlink(pszOldPath, pszNewPath);
-#endif
 }
+#endif
 
 /************************************************************************/
 /* ==================================================================== */
@@ -2598,6 +2740,7 @@ int CPLSymlink( const char*
 /* ==================================================================== */
 /************************************************************************/
 
+//! @cond Doxygen_Suppress
 /************************************************************************/
 /*                             CPLLocaleC()                             */
 /************************************************************************/
@@ -2605,15 +2748,15 @@ int CPLSymlink( const char*
 CPLLocaleC::CPLLocaleC() :
     pszOldLocale(NULL)
 {
-    if( CSLTestBoolean(CPLGetConfigOption("GDAL_DISABLE_CPLLOCALEC","NO")) )
+    if( CPLTestBool(CPLGetConfigOption("GDAL_DISABLE_CPLLOCALEC", "NO")) )
         return;
 
-    pszOldLocale = CPLStrdup(CPLsetlocale(LC_NUMERIC,NULL));
-    if( EQUAL(pszOldLocale,"C")
-        || EQUAL(pszOldLocale,"POSIX")
-        || CPLsetlocale(LC_NUMERIC,"C") == NULL )
+    pszOldLocale = CPLStrdup(CPLsetlocale(LC_NUMERIC, NULL));
+    if( EQUAL(pszOldLocale, "C")
+        || EQUAL(pszOldLocale, "POSIX")
+        || CPLsetlocale(LC_NUMERIC, "C") == NULL )
     {
-        CPLFree( pszOldLocale );
+        CPLFree(pszOldLocale);
         pszOldLocale = NULL;
     }
 }
@@ -2628,11 +2771,10 @@ CPLLocaleC::~CPLLocaleC()
     if( pszOldLocale == NULL )
         return;
 
-    CPLsetlocale( LC_NUMERIC, pszOldLocale );
-    CPLFree( pszOldLocale );
+    CPLsetlocale(LC_NUMERIC, pszOldLocale);
+    CPLFree(pszOldLocale);
 }
 
-
 /************************************************************************/
 /*                        CPLThreadLocaleC()                            */
 /************************************************************************/
@@ -2641,7 +2783,7 @@ CPLThreadLocaleC::CPLThreadLocaleC()
 
 {
 #ifdef HAVE_USELOCALE
-    nNewLocale = newlocale (LC_NUMERIC_MASK, "C", NULL);
+    nNewLocale = newlocale(LC_NUMERIC_MASK, "C", NULL);
     nOldLocale = uselocale(nNewLocale);
 #else
 
@@ -2651,12 +2793,12 @@ CPLThreadLocaleC::CPLThreadLocaleC()
     if( pszOldLocale )
         pszOldLocale = CPLStrdup(pszOldLocale);
 #else
-    pszOldLocale = CPLStrdup(CPLsetlocale(LC_NUMERIC,NULL));
-    if( EQUAL(pszOldLocale,"C")
-        || EQUAL(pszOldLocale,"POSIX")
-        || CPLsetlocale(LC_NUMERIC,"C") == NULL )
+    pszOldLocale = CPLStrdup(CPLsetlocale(LC_NUMERIC, NULL));
+    if( EQUAL(pszOldLocale, "C")
+        || EQUAL(pszOldLocale, "POSIX")
+        || CPLsetlocale(LC_NUMERIC, "C") == NULL )
     {
-        CPLFree( pszOldLocale );
+        CPLFree(pszOldLocale);
         pszOldLocale = NULL;
     }
 #endif
@@ -2680,20 +2822,20 @@ CPLThreadLocaleC::~CPLThreadLocaleC()
     if( pszOldLocale != NULL )
     {
         setlocale(LC_NUMERIC, pszOldLocale);
-        CPLFree( pszOldLocale );
+        CPLFree(pszOldLocale);
     }
     _configthreadlocale(nOldValConfigThreadLocale);
 #else
     if( pszOldLocale != NULL )
     {
-        CPLsetlocale( LC_NUMERIC, pszOldLocale );
-        CPLFree( pszOldLocale );
+        CPLsetlocale(LC_NUMERIC, pszOldLocale);
+        CPLFree(pszOldLocale);
     }
 #endif
 
 #endif
 }
-
+//! @endcond
 
 /************************************************************************/
 /*                          CPLsetlocale()                              */
@@ -2714,18 +2856,17 @@ CPLThreadLocaleC::~CPLThreadLocaleC()
  *
  * @return See your compiler's documentation on setlocale.
  */
-char* CPLsetlocale (int category, const char* locale)
+char *CPLsetlocale (int category, const char *locale)
 {
     CPLMutexHolder oHolder(&hSetLocaleMutex);
-    char* pszRet = setlocale(category, locale);
+    char *pszRet = setlocale(category, locale);
     if( pszRet == NULL )
         return pszRet;
 
     // Make it thread-locale storage.
-    return const_cast<char*>( CPLSPrintf("%s", pszRet) );
+    return const_cast<char *>(CPLSPrintf("%s", pszRet));
 }
 
-
 /************************************************************************/
 /*                       CPLCleanupSetlocaleMutex()                     */
 /************************************************************************/
@@ -2775,20 +2916,20 @@ int CPLCheckForFile( char *pszFilename, char **papszSiblingFiles )
     {
         VSIStatBufL sStatBuf;
 
-        return VSIStatL( pszFilename, &sStatBuf ) == 0;
+        return VSIStatL(pszFilename, &sStatBuf) == 0;
     }
 
 /* -------------------------------------------------------------------- */
 /*      We have sibling files, compare the non-path filename portion    */
 /*      of pszFilename too all entries.                                 */
 /* -------------------------------------------------------------------- */
-    const CPLString osFileOnly = CPLGetFilename( pszFilename );
+    const CPLString osFileOnly = CPLGetFilename(pszFilename);
 
     for( int i = 0; papszSiblingFiles[i] != NULL; i++ )
     {
-        if( EQUAL(papszSiblingFiles[i],osFileOnly) )
+        if( EQUAL(papszSiblingFiles[i], osFileOnly) )
         {
-            strcpy( pszFilename + strlen(pszFilename) - strlen(osFileOnly),
+            strcpy( pszFilename + strlen(pszFilename) - osFileOnly.size(),
                     papszSiblingFiles[i] );
             return TRUE;
         }
@@ -2803,51 +2944,32 @@ int CPLCheckForFile( char *pszFilename, char **papszSiblingFiles )
 
 #if !defined(HAVE_LIBZ)
 
-void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
+void *CPLCreateZip( const char *, char ** )
 
 {
-    CPLError( CE_Failure, CPLE_NotSupported,
-              "This GDAL/OGR build does not include zlib and zip services." );
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "This GDAL/OGR build does not include zlib and zip services.");
     return NULL;
 }
 
-CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename,
-                           char **papszOptions )
+CPLErr CPLCreateFileInZip(void *, const char *, char **) { return CE_Failure; }
 
-{
-    return CE_Failure;
-}
+CPLErr CPLWriteFileInZip(void *, const void *, int) { return CE_Failure; }
 
-CPLErr CPLWriteFileInZip( void *hZip, const void *pBuffer, int nBufferSize )
+CPLErr CPLCloseFileInZip(void *) { return CE_Failure; }
 
-{
-    return CE_Failure;
-}
-
-CPLErr CPLCloseFileInZip( void *hZip )
-
-{
-    return CE_Failure;
-}
-
-CPLErr CPLCloseZip( void *hZip )
-
-{
-    return CE_Failure;
-}
+CPLErr CPLCloseZip(void *) { return CE_Failure; }
 
-void* CPLZLibDeflate( const void* ptr, size_t nBytes, int nLevel,
-                      void* outptr, size_t nOutAvailableBytes,
-                      size_t* pnOutBytes )
+void* CPLZLibDeflate( const void *, size_t, int,
+                      void *, size_t,
+                      size_t *pnOutBytes )
 {
     if( pnOutBytes != NULL )
         *pnOutBytes = 0;
     return NULL;
 }
 
-void* CPLZLibInflate( const void* ptr, size_t nBytes,
-                      void* outptr, size_t nOutAvailableBytes,
-                      size_t* pnOutBytes )
+void *CPLZLibInflate( const void *, size_t, void *, size_t, size_t *pnOutBytes )
 {
     if( pnOutBytes != NULL )
         *pnOutBytes = 0;
diff --git a/port/cpl_conv.h b/port/cpl_conv.h
index 2e3d883..644e1fe 100644
--- a/port/cpl_conv.h
+++ b/port/cpl_conv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_conv.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cpl_conv.h 37866 2017-03-30 20:16:05Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Convenience functions declarations.
@@ -48,7 +48,9 @@
 /* -------------------------------------------------------------------- */
 CPL_C_START
 
+/*! @cond Doxygen_Suppress */
 void CPL_DLL CPLVerifyConfiguration(void);
+/*! @endcond */
 
 const char CPL_DLL * CPL_STDCALL
 CPLGetConfigOption( const char *, const char * ) CPL_WARN_UNUSED_RESULT;
@@ -57,7 +59,13 @@ CPLGetThreadLocalConfigOption( const char *, const char * ) CPL_WARN_UNUSED_RESU
 void CPL_DLL CPL_STDCALL CPLSetConfigOption( const char *, const char * );
 void CPL_DLL CPL_STDCALL CPLSetThreadLocalConfigOption( const char *pszKey,
                                                         const char *pszValue );
+/*! @cond Doxygen_Suppress */
 void CPL_DLL CPL_STDCALL CPLFreeConfig(void);
+/*! @endcond */
+char CPL_DLL** CPLGetConfigOptions(void);
+void CPL_DLL   CPLSetConfigOptions(const char* const * papszConfigOptions);
+char CPL_DLL** CPLGetThreadLocalConfigOptions(void);
+void CPL_DLL   CPLSetThreadLocalConfigOptions(const char* const * papszConfigOptions);
 
 /* -------------------------------------------------------------------- */
 /*      Safe malloc() API.  Thin cover over VSI functions with fatal    */
@@ -69,6 +77,7 @@ void CPL_DLL *CPLRealloc( void *, size_t ) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL *CPLStrdup( const char * ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
 char CPL_DLL *CPLStrlwr( char *);
 
+/** Alias of VSIFree() */
 #define CPLFree VSIFree
 
 /* -------------------------------------------------------------------- */
@@ -77,7 +86,13 @@ char CPL_DLL *CPLStrlwr( char *);
 char CPL_DLL *CPLFGets( char *, int, FILE *);
 const char CPL_DLL *CPLReadLine( FILE * );
 const char CPL_DLL *CPLReadLineL( VSILFILE * );
-const char CPL_DLL *CPLReadLine2L( VSILFILE * , int nMaxCols, char** papszOptions);
+#ifdef __cplusplus
+const char CPL_DLL *CPLReadLine2L( VSILFILE * , int nMaxCols,
+                                   const char * const * papszOptions );
+#else
+const char CPL_DLL *CPLReadLine2L( VSILFILE * , int nMaxCols,
+                                   char** papszOptions );
+#endif
 
 /* -------------------------------------------------------------------- */
 /*      Convert ASCII string to floating point number                  */
@@ -158,10 +173,13 @@ char CPL_DLL      **CPLCorrespondingPaths( const char *pszOldFilename,
 int CPL_DLL CPLCheckForFile( char *pszFilename, char **papszSiblingList );
 
 const char CPL_DLL *CPLGenerateTempFilename( const char *pszStem ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
+const char CPL_DLL *CPLExpandTilde( const char *pszFilename ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
 
 /* -------------------------------------------------------------------- */
 /*      Find File Function                                              */
 /* -------------------------------------------------------------------- */
+
+/** Callback for CPLPushFileFinder */
 typedef const char *(*CPLFileFinder)(const char *, const char *);
 
 const char    CPL_DLL *CPLFindFile(const char *pszClass,
@@ -183,19 +201,23 @@ int CPL_DLL     CPLStat( const char *, VSIStatBuf * ) CPL_WARN_UNUSED_RESULT;
 /*      Reference counted file handle manager.  Makes sharing file      */
 /*      handles more practical.                                         */
 /* -------------------------------------------------------------------- */
+
+/** Information on a shared file */
 typedef struct {
-    FILE *fp;
-    int   nRefCount;
-    int   bLarge;
-    char  *pszFilename;
-    char  *pszAccess;
+    FILE *fp;               /**< File pointer */
+    int   nRefCount;        /**< Reference counter */
+    int   bLarge;           /**< Whether fp must be interpreted as VSIFILE* */
+    char  *pszFilename;     /**< Filename */
+    char  *pszAccess;       /**< Access mode */
 } CPLSharedFileInfo;
 
 FILE CPL_DLL    *CPLOpenShared( const char *, const char *, int );
 void CPL_DLL     CPLCloseShared( FILE * );
 CPLSharedFileInfo CPL_DLL *CPLGetSharedList( int * );
 void CPL_DLL     CPLDumpSharedList( FILE * );
+/*! @cond Doxygen_Suppress */
 void CPL_DLL     CPLCleanupSharedFileMutex( void );
+/*! @endcond */
 
 /* -------------------------------------------------------------------- */
 /*      DMS to Dec to DMS conversion.                                   */
@@ -221,7 +243,10 @@ int CPL_DLL CPLSymlink( const char* pszOldPath, const char* pszNewPath, char** p
 /* -------------------------------------------------------------------- */
 /*      ZIP Creation.                                                   */
 /* -------------------------------------------------------------------- */
+
+/*! @cond Doxygen_Suppress */
 #define CPL_ZIP_API_OFFERED
+/*! @endcond */
 void CPL_DLL  *CPLCreateZip( const char *pszZipFilename, char **papszOptions );
 CPLErr CPL_DLL CPLCreateFileInZip( void *hZip, const char *pszFilename,
                                    char **papszOptions );
@@ -251,7 +276,9 @@ int CPL_DLL CPLValidateXML(const char* pszXMLFilename,
 /*      Locale handling. Prevents parallel executions of setlocale().   */
 /* -------------------------------------------------------------------- */
 char* CPLsetlocale (int category, const char* locale);
+/*! @cond Doxygen_Suppress */
 void CPLCleanupSetlocaleMutex(void);
+/*! @endcond */
 
 CPL_C_END
 
@@ -259,6 +286,7 @@ CPL_C_END
 /*      C++ object for temporarily forcing a LC_NUMERIC locale to "C".  */
 /* -------------------------------------------------------------------- */
 
+//! @cond Doxygen_Suppress
 #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
 
 class CPL_DLL CPLLocaleC
@@ -302,6 +330,6 @@ private:
 };
 
 #endif /* def __cplusplus */
-
+//! @endcond
 
 #endif /* ndef CPL_CONV_H_INCLUDED */
diff --git a/port/cpl_cpu_features.cpp b/port/cpl_cpu_features.cpp
new file mode 100644
index 0000000..d103f83
--- /dev/null
+++ b/port/cpl_cpu_features.cpp
@@ -0,0 +1,214 @@
+/******************************************************************************
+ *
+ * Project:  CPL - Common Portability Library
+ * Purpose:  CPU features detection
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_port.h"
+#include "cpl_string.h"
+#include "cpl_cpu_features.h"
+
+CPL_CVSID("$Id: cpl_cpu_features.cpp 36861 2016-12-14 22:03:57Z goatbar $");
+
+//! @cond Doxygen_Suppress
+
+#define CPUID_SSSE3_ECX_BIT     9
+#define CPUID_OSXSAVE_ECX_BIT   27
+#define CPUID_AVX_ECX_BIT       28
+
+#define CPUID_SSE_EDX_BIT       25
+
+#define BIT_XMM_STATE           (1 << 1)
+#define BIT_YMM_STATE           (2 << 1)
+
+#define REG_EAX                 0
+#define REG_EBX                 1
+#define REG_ECX                 2
+#define REG_EDX                 3
+
+#if defined(__GNUC__)
+#if defined(__x86_64)
+#define GCC_CPUID(level, a, b, c, d)            \
+  __asm__ ("xchgq %%rbx, %q1\n"                 \
+           "cpuid\n"                            \
+           "xchgq %%rbx, %q1"                   \
+       : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+       : "0" (level))
+#else
+#define GCC_CPUID(level, a, b, c, d)            \
+  __asm__ ("xchgl %%ebx, %1\n"                  \
+           "cpuid\n"                            \
+           "xchgl %%ebx, %1"                    \
+       : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+       : "0" (level))
+#endif
+
+#define CPL_CPUID(level, array) GCC_CPUID(level, array[0], array[1], array[2], array[3])
+
+#elif defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER <= 1310
+static void inline __cpuid( int cpuinfo[4], int level )
+{
+    __asm
+    {
+        push   ebx
+        push   esi
+
+        mov    esi,cpuinfo
+        mov    eax, level
+        cpuid
+        mov    dword ptr [esi], eax
+        mov    dword ptr [esi+4], ebx
+        mov    dword ptr [esi+8], ecx
+        mov    dword ptr [esi+0Ch], edx
+
+        pop    esi
+        pop    ebx
+    }
+}
+
+#define CPL_CPUID(level, array) __cpuid(array, level)
+
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+
+#include <intrin.h>
+#define CPL_CPUID(level, array) __cpuid(array, level)
+
+#endif
+
+#if defined(HAVE_SSE_AT_COMPILE_TIME) && !defined(HAVE_INLINE_SSE)
+
+/************************************************************************/
+/*                          CPLHaveRuntimeSSE()                         */
+/************************************************************************/
+
+bool CPLHaveRuntimeSSE()
+{
+    int cpuinfo[4] = { 0, 0, 0, 0 };
+    CPL_CPUID(1, cpuinfo);
+    return (cpuinfo[REG_EDX] & (1 << CPUID_SSE_EDX_BIT)) != 0;
+}
+
+#endif
+
+#if defined(HAVE_SSSE3_AT_COMPILE_TIME) && !defined(HAVE_INLINE_SSSE3)
+
+/************************************************************************/
+/*                         CPLHaveRuntimeSSSE3()                        */
+/************************************************************************/
+
+bool CPLHaveRuntimeSSSE3()
+{
+#ifdef DEBUG
+    if( !CPLTestBool(CPLGetConfigOption("GDAL_USE_SSSE3", "YES")) )
+        return false;
+#endif
+    int cpuinfo[4] = { 0, 0, 0, 0 };
+    CPL_CPUID(1, cpuinfo);
+    return (cpuinfo[REG_ECX] & (1 << CPUID_SSSE3_ECX_BIT)) != 0;
+}
+
+#endif
+
+#if defined(HAVE_AVX_AT_COMPILE_TIME) && !defined(HAVE_INLINE_AVX)
+
+/************************************************************************/
+/*                          CPLHaveRuntimeAVX()                         */
+/************************************************************************/
+
+#if defined(__GNUC__) && (defined(__i386__) ||defined(__x86_64))
+
+bool CPLHaveRuntimeAVX()
+{
+    int cpuinfo[4] = { 0, 0, 0, 0 };
+    CPL_CPUID(1, cpuinfo);
+
+    // Check OSXSAVE feature.
+    if( (cpuinfo[REG_ECX] & (1 << CPUID_OSXSAVE_ECX_BIT)) == 0 )
+    {
+        return false;
+    }
+
+    // Check AVX feature.
+    if( (cpuinfo[REG_ECX] & (1 << CPUID_AVX_ECX_BIT)) == 0 )
+    {
+        return false;
+    }
+
+    // Issue XGETBV and check the XMM and YMM state bit.
+    unsigned int nXCRLow;
+    unsigned int nXCRHigh;
+    __asm__ ("xgetbv" : "=a" (nXCRLow), "=d" (nXCRHigh) : "c" (0));
+    if( (nXCRLow & ( BIT_XMM_STATE | BIT_YMM_STATE )) !=
+                ( BIT_XMM_STATE | BIT_YMM_STATE ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+#elif defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 160040219) && (defined(_M_IX86) || defined(_M_X64))
+// _xgetbv available only in Visual Studio 2010 SP1 or later
+
+bool CPLHaveRuntimeAVX()
+{
+    int cpuinfo[4] = { 0, 0, 0, 0 };
+    CPL_CPUID(1, cpuinfo);
+
+    // Check OSXSAVE feature.
+    if( (cpuinfo[REG_ECX] & (1 << CPUID_OSXSAVE_ECX_BIT)) == 0 )
+    {
+        return false;
+    }
+
+    // Check AVX feature.
+    if( (cpuinfo[REG_ECX] & (1 << CPUID_AVX_ECX_BIT)) == 0 )
+    {
+        return false;
+    }
+
+    // Issue XGETBV and check the XMM and YMM state bit.
+    unsigned __int64 xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
+    if( (xcrFeatureMask & ( BIT_XMM_STATE | BIT_YMM_STATE )) !=
+                          ( BIT_XMM_STATE | BIT_YMM_STATE ) )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+#else
+
+int CPLHaveRuntimeAVX()
+{
+    return false;
+}
+
+#endif
+
+#endif // defined(HAVE_AVX_AT_COMPILE_TIME) && !defined(CPLHaveRuntimeAVX)
+
+//! @endcond
diff --git a/port/cpl_cpu_features.h b/port/cpl_cpu_features.h
new file mode 100644
index 0000000..39a4d2d
--- /dev/null
+++ b/port/cpl_cpu_features.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ *
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Prototypes, and definitions for of CPU features detection
+ * Author:   Even Rouault, <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef CPL_CPU_FEATURES_H
+#define CPL_CPU_FEATURES_H
+
+#include "cpl_port.h"
+#include "cpl_string.h"
+
+//! @cond Doxygen_Suppress
+
+#ifdef HAVE_SSE_AT_COMPILE_TIME
+#if (defined(_M_X64) || defined(__x86_64))
+#define HAVE_INLINE_SSE
+static bool inline CPLHaveRuntimeSSE() { return true; }
+#else
+bool CPLHaveRuntimeSSE();
+#endif
+#endif
+
+#ifdef HAVE_SSSE3_AT_COMPILE_TIME
+#if __SSSE3__
+#define HAVE_INLINE_SSSE3
+static bool inline CPLHaveRuntimeSSSE3()
+{
+#ifdef DEBUG
+    if( !CPLTestBool(CPLGetConfigOption("GDAL_USE_SSSE3", "YES")) )
+        return false;
+#endif
+    return true;
+}
+#else
+bool CPLHaveRuntimeSSSE3();
+#endif
+#endif
+
+#ifdef HAVE_AVX_AT_COMPILE_TIME
+#if __AVX__
+#define HAVE_INLINE_AVX
+static bool inline CPLHaveRuntimeAVX() { return true; }
+#else
+bool CPLHaveRuntimeAVX();
+#endif
+#endif
+
+//! @endcond
+
+#endif // CPL_CPU_FEATURES_H
diff --git a/port/cpl_csv.cpp b/port/cpl_csv.cpp
index ef44a4e..5d8dece 100644
--- a/port/cpl_csv.cpp
+++ b/port/cpl_csv.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_csv.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CSV (comma separated value) file access.
@@ -28,12 +27,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_csv.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
 #include "gdal_csv.h"
 
-CPL_CVSID("$Id: cpl_csv.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+CPL_CVSID("$Id: cpl_csv.cpp 37621 2017-03-06 11:38:25Z rouault $");
 
 /* ==================================================================== */
 /*      The CSVTable is a persistent set of info about an open CSV      */
@@ -48,7 +57,7 @@ typedef struct ctb {
     char      **papszFieldNames;
     char      **papszRecFields;
     int         iLastLine;
-    int         bNonUniqueKey;
+    bool        bNonUniqueKey;
 
     /* Cache for whole file */
     int         nLineCount;
@@ -57,7 +66,7 @@ typedef struct ctb {
     char       *pszRawData;
 } CSVTable;
 
-static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS,
+static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, bool bCanUseTLS,
                                  const char * pszFilename );
 
 /************************************************************************/
@@ -65,7 +74,7 @@ static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS,
 /************************************************************************/
 static void CSVFreeTLS( void* pData )
 {
-    CSVDeaccessInternal( reinterpret_cast<CSVTable **>( pData ), FALSE, NULL );
+    CSVDeaccessInternal( static_cast<CSVTable **>( pData ), false, NULL );
     CPLFree(pData);
 }
 
@@ -91,13 +100,13 @@ static CSVTable *CSVAccess( const char * pszFilename )
 /*      if there isn't already one.                                     */
 /* -------------------------------------------------------------------- */
     int bMemoryError = FALSE;
-    CSVTable **ppsCSVTableList = reinterpret_cast<CSVTable **>(
+    CSVTable **ppsCSVTableList = static_cast<CSVTable **>(
         CPLGetTLSEx( CTLS_CSVTABLEPTR, &bMemoryError ) );
     if( bMemoryError )
         return NULL;
     if( ppsCSVTableList == NULL )
     {
-        ppsCSVTableList = reinterpret_cast<CSVTable **>(
+        ppsCSVTableList = static_cast<CSVTable **>(
             VSI_CALLOC_VERBOSE( 1, sizeof(CSVTable*) ) );
         if( ppsCSVTableList == NULL )
             return NULL;
@@ -132,7 +141,7 @@ static CSVTable *CSVAccess( const char * pszFilename )
 /*      Create an information structure about this table, and add to    */
 /*      the front of the list.                                          */
 /* -------------------------------------------------------------------- */
-    CSVTable * const psTable = reinterpret_cast<CSVTable *>(
+    CSVTable * const psTable = static_cast<CSVTable *>(
         VSI_CALLOC_VERBOSE( sizeof(CSVTable), 1 ) );
     if( psTable == NULL )
     {
@@ -148,7 +157,7 @@ static CSVTable *CSVAccess( const char * pszFilename )
         VSIFCloseL(fp);
         return NULL;
     }
-    psTable->bNonUniqueKey = FALSE; /* as far as we know now */
+    psTable->bNonUniqueKey = false;  // As far as we know now.
     psTable->psNext = *ppsCSVTableList;
 
     *ppsCSVTableList = psTable;
@@ -165,7 +174,7 @@ static CSVTable *CSVAccess( const char * pszFilename )
 /*                            CSVDeaccess()                             */
 /************************************************************************/
 
-static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS,
+static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, bool bCanUseTLS,
                                  const char * pszFilename )
 
 {
@@ -198,7 +207,7 @@ static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS,
 
     if( psTable == NULL )
     {
-        if (bCanUseTLS)
+        if( bCanUseTLS )
             CPLDebug( "CPL_CSV", "CPLDeaccess( %s ) - no match.", pszFilename );
         return;
     }
@@ -226,7 +235,7 @@ static void CSVDeaccessInternal( CSVTable **ppsCSVTableList, int bCanUseTLS,
 
     CPLFree( psTable );
 
-    if (bCanUseTLS)
+    if( bCanUseTLS )
         CPLReadLine( NULL );
 }
 
@@ -237,10 +246,10 @@ void CSVDeaccess( const char * pszFilename )
 /*      if there isn't already one.                                     */
 /* -------------------------------------------------------------------- */
     int bMemoryError = FALSE;
-    CSVTable **ppsCSVTableList = reinterpret_cast<CSVTable **>(
+    CSVTable **ppsCSVTableList = static_cast<CSVTable **>(
         CPLGetTLSEx( CTLS_CSVTABLEPTR, &bMemoryError ) );
 
-    CSVDeaccessInternal(ppsCSVTableList, TRUE, pszFilename);
+    CSVDeaccessInternal(ppsCSVTableList, true, pszFilename);
 }
 
 /************************************************************************/
@@ -256,7 +265,7 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter )
 
 {
 
-    char *pszToken = reinterpret_cast<char *>( VSI_CALLOC_VERBOSE( 10, 1 ) );
+    char *pszToken = static_cast<char *>( VSI_CALLOC_VERBOSE( 10, 1 ) );
     if( pszToken == NULL )
         return NULL;
 
@@ -295,7 +304,7 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter )
             if( nTokenLen >= nTokenMax-2 )
             {
                 nTokenMax = nTokenMax * 2 + 10;
-                char* pszTokenNew = reinterpret_cast<char *>(
+                char* pszTokenNew = static_cast<char *>(
                     VSI_REALLOC_VERBOSE( pszToken, nTokenMax ) );
                 if( pszTokenNew == NULL )
                 {
@@ -323,7 +332,7 @@ static char **CSVSplitLine( const char *pszString, char chDelimiter )
         /* If the last token is an empty token, then we have to catch
          * it now, otherwise we won't reenter the loop and it will be lost.
          */
-        if ( *pszString == '\0' && *(pszString-1) == chDelimiter )
+        if( *pszString == '\0' && *(pszString-1) == chDelimiter )
         {
             papszRetListNew = CSLAddStringMayFail( papszRetList, "" );
             if( papszRetListNew == NULL )
@@ -416,7 +425,7 @@ static void CSVIngest( const char *pszFilename )
     }
     VSIRewindL( psTable->fp );
 
-    psTable->pszRawData = reinterpret_cast<char *>(
+    psTable->pszRawData = static_cast<char *>(
         VSI_MALLOC_VERBOSE( static_cast<size_t>(nFileLen) + 1) );
     if( psTable->pszRawData == NULL )
         return;
@@ -444,7 +453,7 @@ static void CSVIngest( const char *pszFilename )
             nMaxLineCount++;
     }
 
-    psTable->papszLines = reinterpret_cast<char **>(
+    psTable->papszLines = static_cast<char **>(
         VSI_CALLOC_VERBOSE( sizeof(char*), nMaxLineCount ) );
     if( psTable->papszLines == NULL )
         return;
@@ -460,7 +469,8 @@ static void CSVIngest( const char *pszFilename )
     int iLine = 0;
     while( pszThisLine != NULL && iLine < nMaxLineCount )
     {
-        psTable->papszLines[iLine++] = pszThisLine;
+        if( pszThisLine[0] != '#' )
+            psTable->papszLines[iLine++] = pszThisLine;
         pszThisLine = CSVFindNextLine( pszThisLine );
     }
 
@@ -471,7 +481,7 @@ static void CSVIngest( const char *pszFilename )
 /*      ascending order so that binary searches can be done on the      */
 /*      array.                                                          */
 /* -------------------------------------------------------------------- */
-    psTable->panLineIndex = reinterpret_cast<int *>(
+    psTable->panLineIndex = static_cast<int *>(
         VSI_MALLOC_VERBOSE( sizeof(int) * psTable->nLineCount ) );
     if( psTable->panLineIndex == NULL )
         return;
@@ -508,22 +518,24 @@ static void CSVIngest( const char *pszFilename )
  *
  * @return ',', ';', ' ' or '\t'
  */
-char CSVDetectSeperator (const char* pszLine)
+char CSVDetectSeperator( const char* pszLine )
 {
-    bool    bInString = false;
-    char    chDelimiter = '\0';
-    int     nCountSpace = 0;
+    bool bInString = false;
+    char chDelimiter = '\0';
+    int nCountSpace = 0;
 
     for( ; *pszLine != '\0'; pszLine++ )
     {
         if( !bInString && ( *pszLine == ',' || *pszLine == ';'
                             || *pszLine == '\t'))
         {
-            if (chDelimiter == '\0')
+            if( chDelimiter == '\0' )
+            {
                 chDelimiter = *pszLine;
-            else if (chDelimiter != *pszLine)
+            }
+            else if( chDelimiter != *pszLine )
             {
-                /* The separator is not consistent on the line. */
+                // The separator is not consistent on the line.
                 CPLDebug( "CSV", "Inconsistent separator. '%c' and '%c' found. "
                           "Using ',' as default",
                           chDelimiter, *pszLine);
@@ -549,7 +561,7 @@ char CSVDetectSeperator (const char* pszLine)
         }
     }
 
-    if (chDelimiter == '\0')
+    if( chDelimiter == '\0' )
     {
         if( nCountSpace > 0 )
             chDelimiter = ' ';
@@ -581,7 +593,7 @@ char **CSVReadParseLine2( FILE * fp, char chDelimiter )
     if( fp == NULL )
         return NULL;
 
-    const char  *pszLine = CPLReadLine( fp );
+    const char *pszLine = CPLReadLine( fp );
     if( pszLine == NULL )
         return NULL;
 
@@ -589,7 +601,7 @@ char **CSVReadParseLine2( FILE * fp, char chDelimiter )
 /*      If there are no quotes, then this is the simple case.           */
 /*      Parse, and return tokens.                                       */
 /* -------------------------------------------------------------------- */
-    if( strchr(pszLine,'\"') == NULL )
+    if( strchr(pszLine, '\"') == NULL )
         return CSVSplitLine( pszLine, chDelimiter );
 
 /* -------------------------------------------------------------------- */
@@ -620,10 +632,10 @@ char **CSVReadParseLine2( FILE * fp, char chDelimiter )
 
         const size_t nLineLen = strlen(pszLine);
 
-        char* pszWorkLineTmp = reinterpret_cast<char *>(
+        char* pszWorkLineTmp = static_cast<char *>(
             VSIRealloc(pszWorkLine,
                        nWorkLineLength + nLineLen + 2) );
-        if (pszWorkLineTmp == NULL)
+        if( pszWorkLineTmp == NULL )
             break;
         pszWorkLine = pszWorkLineTmp;
         // The newline gets lost in CPLReadLine().
@@ -662,7 +674,7 @@ char **CSVReadParseLine2L( VSILFILE * fp, char chDelimiter )
     if( fp == NULL )
         return NULL;
 
-    const char  *pszLine = CPLReadLineL( fp );
+    const char *pszLine = CPLReadLineL( fp );
     if( pszLine == NULL )
         return NULL;
 
@@ -670,7 +682,7 @@ char **CSVReadParseLine2L( VSILFILE * fp, char chDelimiter )
 /*      If there are no quotes, then this is the simple case.           */
 /*      Parse, and return tokens.                                       */
 /* -------------------------------------------------------------------- */
-    if( strchr(pszLine,'\"') == NULL )
+    if( strchr(pszLine, '\"') == NULL )
         return CSVSplitLine( pszLine, chDelimiter );
 
 /* -------------------------------------------------------------------- */
@@ -704,7 +716,7 @@ char **CSVReadParseLine2L( VSILFILE * fp, char chDelimiter )
         char* pszWorkLineTmp = static_cast<char *>(
             VSIRealloc(pszWorkLine,
                        nWorkLineLength + nLineLen + 2) );
-        if (pszWorkLineTmp == NULL)
+        if( pszWorkLineTmp == NULL )
             break;
 
         pszWorkLine = pszWorkLineTmp;
@@ -743,7 +755,8 @@ static bool CSVCompare( const char * pszFieldValue, const char * pszTarget,
     }
     else if( eCriteria == CC_Integer )
     {
-        return( atoi(pszFieldValue) == atoi(pszTarget) );
+        return( CPLGetValueType(pszFieldValue) == CPL_VALUE_INTEGER &&
+                atoi(pszFieldValue) == atoi(pszTarget) );
     }
 
     return false;
@@ -886,7 +899,7 @@ CSVScanLinesIndexed( CSVTable *psTable, int nKeyValue )
             while( iResult > 0
                    && psTable->panLineIndex[iResult-1] == nKeyValue )
             {
-                psTable->bNonUniqueKey = TRUE;
+                psTable->bNonUniqueKey = true;
                 iResult--;
             }
             break;
@@ -990,7 +1003,7 @@ char **CSVGetNextLine( const char *pszFilename )
 /*      If we use CSVGetNextLine() we can pretty much assume we have    */
 /*      a non-unique key.                                               */
 /* -------------------------------------------------------------------- */
-    psTable->bNonUniqueKey = TRUE;
+    psTable->bNonUniqueKey = true;
 
 /* -------------------------------------------------------------------- */
 /*      Do we have a next line available?  This only works for          */
@@ -1038,7 +1051,7 @@ char **CSVScanFile( const char * pszFilename, int iKeyField,
 /* -------------------------------------------------------------------- */
     if( iKeyField >= 0
         && iKeyField < CSLCount(psTable->papszRecFields)
-        && CSVCompare(pszValue,psTable->papszRecFields[iKeyField],eCriteria)
+        && CSVCompare(psTable->papszRecFields[iKeyField], pszValue, eCriteria)
         && !psTable->bNonUniqueKey )
     {
         return psTable->papszRecFields;
@@ -1089,7 +1102,7 @@ int CSVGetFieldId( FILE * fp, const char * pszFieldName )
     char **papszFields = CSVReadParseLine( fp );
     for( int i = 0; papszFields != NULL && papszFields[i] != NULL; i++ )
     {
-        if( EQUAL(papszFields[i],pszFieldName) )
+        if( EQUAL(papszFields[i], pszFieldName) )
         {
             CSLDestroy( papszFields );
             return i;
@@ -1122,7 +1135,7 @@ int CSVGetFieldIdL( VSILFILE * fp, const char * pszFieldName )
     char **papszFields = CSVReadParseLineL( fp );
     for( int i = 0; papszFields != NULL && papszFields[i] != NULL; i++ )
     {
-        if( EQUAL(papszFields[i],pszFieldName) )
+        if( EQUAL(papszFields[i], pszFieldName) )
         {
             CSLDestroy( papszFields );
             return i;
@@ -1161,7 +1174,7 @@ int CSVGetFileFieldId( const char * pszFilename, const char * pszFieldName )
              && psTable->papszFieldNames[i] != NULL;
          i++ )
     {
-        if( EQUAL(psTable->papszFieldNames[i],pszFieldName) )
+        if( EQUAL(psTable->papszFieldNames[i], pszFieldName) )
         {
             return i;
         }
@@ -1170,7 +1183,6 @@ int CSVGetFileFieldId( const char * pszFilename, const char * pszFieldName )
     return -1;
 }
 
-
 /************************************************************************/
 /*                         CSVScanFileByName()                          */
 /*                                                                      */
@@ -1229,7 +1241,7 @@ const char *CSVGetField( const char * pszFilename,
     if( iTargetField < 0 )
         return "";
 
-    for(int i=0; papszRecord[i] != NULL; ++i)
+    for( int i=0; papszRecord[i] != NULL; ++i )
     {
         if( i == iTargetField )
             return papszRecord[iTargetField];
@@ -1244,10 +1256,9 @@ const char *CSVGetField( const char * pszFilename,
 typedef struct
 {
     char szPath[512];
-    int  bCSVFinderInitialized;
+    bool bCSVFinderInitialized;
 } DefaultCSVFileNameTLS;
 
-
 const char * GDALDefaultCSVFilename( const char *pszBasename )
 
 {
@@ -1256,7 +1267,7 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
 /*      the existing path without any further probing.                  */
 /* -------------------------------------------------------------------- */
     int bMemoryError = FALSE;
-    CSVTable **ppsCSVTableList = reinterpret_cast<CSVTable **>(
+    CSVTable **ppsCSVTableList = static_cast<CSVTable **>(
       CPLGetTLSEx( CTLS_CSVTABLEPTR, &bMemoryError ) );
     if( ppsCSVTableList != NULL )
     {
@@ -1271,7 +1282,7 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
             if( nFullLen > nBasenameLen
                 && strcmp(psTable->pszFilename+nFullLen-nBasenameLen,
                           pszBasename) == 0
-                && strchr("/\\",psTable->pszFilename[+nFullLen-nBasenameLen-1])
+                && strchr("/\\", psTable->pszFilename[+nFullLen-nBasenameLen-1])
                           != NULL )
             {
                 return psTable->pszFilename;
@@ -1283,11 +1294,11 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
 /*      Otherwise we need to look harder for it.                        */
 /* -------------------------------------------------------------------- */
     DefaultCSVFileNameTLS* pTLSData =
-        reinterpret_cast<DefaultCSVFileNameTLS *>(
+        static_cast<DefaultCSVFileNameTLS *>(
             CPLGetTLSEx( CTLS_CSVDEFAULTFILENAME, &bMemoryError ) );
-    if (pTLSData == NULL && !bMemoryError)
+    if( pTLSData == NULL && !bMemoryError )
     {
-        pTLSData = reinterpret_cast<DefaultCSVFileNameTLS *>(
+        pTLSData = static_cast<DefaultCSVFileNameTLS *>(
             VSI_CALLOC_VERBOSE( 1, sizeof(DefaultCSVFileNameTLS) ) );
         if( pTLSData )
             CPLSetTLS( CTLS_CSVDEFAULTFILENAME, pTLSData, TRUE );
@@ -1302,13 +1313,13 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
 
     if( !pTLSData->bCSVFinderInitialized )
     {
-        pTLSData->bCSVFinderInitialized = TRUE;
+        pTLSData->bCSVFinderInitialized = true;
 
-        if( CPLGetConfigOption("GEOTIFF_CSV",NULL) != NULL )
-            CPLPushFinderLocation( CPLGetConfigOption("GEOTIFF_CSV",NULL));
+        if( CPLGetConfigOption("GEOTIFF_CSV", NULL) != NULL )
+            CPLPushFinderLocation( CPLGetConfigOption("GEOTIFF_CSV", NULL));
 
-        if( CPLGetConfigOption("GDAL_DATA",NULL) != NULL )
-            CPLPushFinderLocation( CPLGetConfigOption("GDAL_DATA",NULL) );
+        if( CPLGetConfigOption("GDAL_DATA", NULL) != NULL )
+            CPLPushFinderLocation( CPLGetConfigOption("GDAL_DATA", NULL) );
 
         pszResult = CPLFindFile( "epsg_csv", pszBasename );
 
@@ -1316,6 +1327,16 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
             return pszResult;
     }
 
+#ifdef GDAL_NO_HARDCODED_FIND
+    // For systems like sandboxes that do not allow other checks.
+    CPLDebug( "CPL_CSV",
+              "Failed to find file in GDALDefaultCSVFilename.  "
+              "Returning original basename: %s",
+              pszBasename );
+    strcpy( pTLSData->szPath, pszBasename );
+    return pTLSData->szPath;
+#else
+
 #ifdef GDAL_PREFIX
   #ifdef MACOSX_FRAMEWORK
     strcpy( pTLSData->szPath, GDAL_PREFIX "/Resources/epsg_csv/" );
@@ -1327,7 +1348,7 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
 #else
     strcpy( pTLSData->szPath, "/usr/local/share/epsg_csv/" );
     CPLStrlcat( pTLSData->szPath, pszBasename, sizeof(pTLSData->szPath) );
-#endif
+#endif  // GDAL_PREFIX
 
     VSILFILE *fp = VSIFOpenL( pTLSData->szPath, "rt" );
     if( fp == NULL )
@@ -1337,6 +1358,7 @@ const char * GDALDefaultCSVFilename( const char *pszBasename )
         VSIFCloseL( fp );
 
     return pTLSData->szPath;
+#endif  // GDAL_NO_HARDCODED_FIND
 }
 
 /************************************************************************/
@@ -1395,7 +1417,7 @@ put into CSVDirName).  <p>
 static const char *CSVFileOverride( const char * pszInput )
 
 {
-    static char         szPath[1024];
+    static char szPath[1024] = {};
 
 #ifdef WIN32
     sprintf( szPath, "%s\\%s", CSVDirName, pszInput );
diff --git a/port/cpl_csv.h b/port/cpl_csv.h
index 6337431..8193003 100644
--- a/port/cpl_csv.h
+++ b/port/cpl_csv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_csv.h 33844 2016-04-01 08:42:13Z rouault $
+ * $Id: cpl_csv.h 36376 2016-11-21 06:54:04Z goatbar $
  *
  * Project:  Common Portability Library
  * Purpose:  Functions for reading and scanning CSV (comma separated,
@@ -31,6 +31,8 @@
 #ifndef CPL_CSV_H_INCLUDED
 #define CPL_CSV_H_INCLUDED
 
+#include <stdio.h>
+
 #include "cpl_conv.h"
 #include "cpl_string.h"
 #include "cpl_vsi.h"
diff --git a/port/cpl_error.cpp b/port/cpl_error.cpp
index 0ae5ab2..2182bb8 100644
--- a/port/cpl_error.cpp
+++ b/port/cpl_error.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_error.cpp 34109 2016-04-25 17:28:36Z rouault $
  *
  * Name:     cpl_error.cpp
  * Project:  CPL - Common Portability Library
@@ -30,15 +29,24 @@
  ****************************************************************************/
 
 #include "cpl_error.h"
-#include "cpl_string.h"
-#include "cpl_vsi.h"
+
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
+
+#include "cpl_config.h"
 #include "cpl_conv.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 
 #define TIMESTAMP_DEBUG
-//#define MEMORY_DEBUG
+// #define MEMORY_DEBUG
 
-CPL_CVSID("$Id: cpl_error.cpp 34109 2016-04-25 17:28:36Z rouault $");
+CPL_CVSID("$Id: cpl_error.cpp 37003 2016-12-23 14:54:07Z goatbar $");
 
 static CPLMutex *hErrorMutex = NULL;
 static void *pErrorHandlerUserData = NULL;
@@ -47,11 +55,11 @@ static bool gbCatchDebug = true;
 
 static const int DEFAULT_LAST_ERR_MSG_SIZE =
 #if !defined(HAVE_VSNPRINTF)
-  20000
+    20000
 #else
-  500
+    500
 #endif
-  ;
+    ;
 
 typedef struct errHandler
 {
@@ -68,7 +76,8 @@ typedef struct {
     int     nLastErrMsgMax;
     int     nFailureIntoWarning;
     char    szLastErrMsg[DEFAULT_LAST_ERR_MSG_SIZE];
-    /* Do not add anything here. szLastErrMsg must be the last field. See CPLRealloc() below */
+    // Do not add anything here. szLastErrMsg must be the last field.
+    // See CPLRealloc() below.
 } CPLErrorContext;
 
 static const CPLErrorContext sNoErrorContext =
@@ -101,7 +110,9 @@ static const CPLErrorContext sFailureContext =
     "A failure was emitted"
 };
 
-#define IS_PREFEFINED_ERROR_CTX(psCtxt) ( psCtx == &sNoErrorContext || psCtx == &sWarningContext || psCtxt == &sFailureContext )
+#define IS_PREFEFINED_ERROR_CTX(psCtxt) ( psCtx == &sNoErrorContext || \
+                                          psCtx == &sWarningContext || \
+                                          psCtxt == &sFailureContext )
 
 /************************************************************************/
 /*                         CPLGetErrorContext()                         */
@@ -119,9 +130,10 @@ static CPLErrorContext *CPLGetErrorContext()
 
     if( psCtx == NULL )
     {
-      psCtx = reinterpret_cast<CPLErrorContext *>(
-          VSICalloc( sizeof(CPLErrorContext), 1) );
-        if (psCtx == NULL) {
+        psCtx = static_cast<CPLErrorContext *>(
+            VSICalloc( sizeof(CPLErrorContext), 1) );
+        if( psCtx == NULL )
+        {
             fprintf(stderr, "Out of memory attempting to report error.\n");
             return NULL;
         }
@@ -196,11 +208,12 @@ void* CPL_STDCALL CPLGetErrorHandlerUserData(void)
  * similar to printf().
  */
 
-void    CPLError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)
+void CPLError( CPLErr eErrClass, CPLErrorNum err_no,
+               CPL_FORMAT_STRING(const char *fmt), ... )
 {
     va_list args;
 
-    // Expand the error message
+    // Expand the error message.
     va_start(args, fmt);
     CPLErrorV( eErrClass, err_no, fmt, args );
     va_end(args);
@@ -210,8 +223,9 @@ void    CPLError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)
 /*                             CPLErrorV()                              */
 /************************************************************************/
 
-void    CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
-                   va_list args )
+/** Same as CPLError() but with a va_list */
+void CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
+                va_list args )
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
     if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
@@ -236,8 +250,7 @@ void    CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
 
         // TODO: Is it possible to move the entire szShortMessage under the if
         // pfnErrorHandler?
-        char szShortMessage[80];
-        szShortMessage[0] = '\0';
+        char szShortMessage[80] = {};
         CPLvsnprintf( szShortMessage, sizeof(szShortMessage), fmt, args );
 
         CPLMutexHolderD( &hErrorMutex );
@@ -246,7 +259,7 @@ void    CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
         return;
     }
 
-    if (psCtx->nFailureIntoWarning > 0 && eErrClass == CE_Failure)
+    if( psCtx->nFailureIntoWarning > 0 && eErrClass == CE_Failure )
         eErrClass = CE_Warning;
 
 /* -------------------------------------------------------------------- */
@@ -267,25 +280,25 @@ void    CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
 /*      rather than just replacing the last error message.              */
 /* -------------------------------------------------------------------- */
         int nPreviousSize = 0;
-        if ( psCtx->psHandlerStack != NULL &&
-             EQUAL(CPLGetConfigOption( "CPL_ACCUM_ERROR_MSG", "" ), "ON"))
+        if( psCtx->psHandlerStack != NULL &&
+            EQUAL(CPLGetConfigOption( "CPL_ACCUM_ERROR_MSG", "" ), "ON"))
         {
             nPreviousSize = static_cast<int>(strlen(psCtx->szLastErrMsg));
-            if (nPreviousSize)
+            if( nPreviousSize )
             {
-                if (nPreviousSize + 1 + 1 >= psCtx->nLastErrMsgMax)
+                if( nPreviousSize + 1 + 1 >= psCtx->nLastErrMsgMax )
                 {
                     psCtx->nLastErrMsgMax *= 3;
                     psCtx = static_cast<CPLErrorContext *> (
-                        CPLRealloc( psCtx,
-                                    sizeof(CPLErrorContext)
-                                    - DEFAULT_LAST_ERR_MSG_SIZE
-                                    + psCtx->nLastErrMsgMax + 1));
+                        CPLRealloc(psCtx,
+                                   sizeof(CPLErrorContext)
+                                   - DEFAULT_LAST_ERR_MSG_SIZE
+                                   + psCtx->nLastErrMsgMax + 1));
                     CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
                 }
                 psCtx->szLastErrMsg[nPreviousSize] = '\n';
                 psCtx->szLastErrMsg[nPreviousSize+1] = '0';
-                nPreviousSize ++;
+                nPreviousSize++;
             }
         }
 
@@ -304,10 +317,10 @@ void    CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
 #endif
             psCtx->nLastErrMsgMax *= 3;
             psCtx = static_cast<CPLErrorContext *> (
-                CPLRealloc( psCtx,
-                            sizeof(CPLErrorContext)
-                            - DEFAULT_LAST_ERR_MSG_SIZE
-                            + psCtx->nLastErrMsgMax + 1) );
+                CPLRealloc(psCtx,
+                           sizeof(CPLErrorContext)
+                           - DEFAULT_LAST_ERR_MSG_SIZE
+                           + psCtx->nLastErrMsgMax + 1));
             CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
         }
 
@@ -321,7 +334,6 @@ void    CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
 /* -------------------------------------------------------------------- */
 /*      Obfuscate any password in error message                         */
 /* -------------------------------------------------------------------- */
-
     char* pszPassword = strstr(psCtx->szLastErrMsg, "password=");
     if( pszPassword != NULL )
     {
@@ -329,7 +341,7 @@ void    CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
         while( *pszIter != ' ' && *pszIter != '\0' )
         {
             *pszIter = 'X';
-            pszIter ++;
+            pszIter++;
         }
     }
 
@@ -340,7 +352,7 @@ void    CPLErrorV( CPLErr eErrClass, CPLErrorNum err_no, const char *fmt,
     psCtx->nLastErrNo = err_no;
     psCtx->eLastErrType = eErrClass;
 
-    if( CPLGetConfigOption("CPL_LOG_ERRORS",NULL) != NULL )
+    if( CPLGetConfigOption("CPL_LOG_ERRORS", NULL) != NULL )
         CPLDebug( "CPLError", "%s", psCtx->szLastErrMsg );
 
 /* -------------------------------------------------------------------- */
@@ -391,8 +403,8 @@ void CPLEmergencyError( const char *pszMessage )
     if( !bInEmergencyError )
     {
         bInEmergencyError = true;
-        CPLErrorContext *psCtx
-            = static_cast<CPLErrorContext *>( CPLGetTLS( CTLS_ERRORCONTEXT ) );
+        CPLErrorContext *psCtx =
+            static_cast<CPLErrorContext *>(CPLGetTLS( CTLS_ERRORCONTEXT ));
 
         if( psCtx != NULL && psCtx->psHandlerStack != NULL )
         {
@@ -424,14 +436,14 @@ static int CPLGetProcessMemorySize()
     if( fp == NULL )
         return -1;
     int nRet = -1;
-    char szLine[128];
-    while (fgets(szLine, sizeof(szLine), fp) != NULL)
+    char szLine[128] = {};
+    while( fgets(szLine, sizeof(szLine), fp) != NULL )
     {
-        if (STARTS_WITH(szLine, "VmSize:"))
+        if( STARTS_WITH(szLine, "VmSize:") )
         {
             const char* pszPtr = szLine;
             while( !(*pszPtr == '\0' || (*pszPtr >= '0' && *pszPtr <= '9')) )
-                 pszPtr ++;
+                 pszPtr++;
             nRet = atoi(pszPtr);
             break;
         }
@@ -455,7 +467,7 @@ static int CPLGetProcessMemorySize()
  * The category argument is used in conjunction with the CPL_DEBUG
  * environment variable to establish if the message should be displayed.
  * If the CPL_DEBUG environment variable is not set, no debug messages
- * are emitted (use CPLError(CE_Warning,...) to ensure messages are displayed).
+ * are emitted (use CPLError(CE_Warning, ...) to ensure messages are displayed).
  * If CPL_DEBUG is set, but is an empty string or the word "ON" then all
  * debug messages are shown.  Otherwise only messages whose category appears
  * somewhere within the CPL_DEBUG value are displayed (as determined by
@@ -470,13 +482,17 @@ static int CPLGetProcessMemorySize()
  *        Remaining arguments are assumed to be for format.
  */
 
-void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
+#ifdef WITHOUT_CPLDEBUG
+// Do not include CPLDebug.  Only available in custom builds.
+#else
+void CPLDebug( const char * pszCategory,
+               CPL_FORMAT_STRING(const char * pszFormat), ... )
 
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
     if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
         return;
-    const char  *pszDebug = CPLGetConfigOption("CPL_DEBUG",NULL);
+    const char *pszDebug = CPLGetConfigOption("CPL_DEBUG", NULL);
 
 /* -------------------------------------------------------------------- */
 /*      Does this message pass our current criteria?                    */
@@ -484,13 +500,14 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
     if( pszDebug == NULL )
         return;
 
-    if( !EQUAL(pszDebug,"ON") && !EQUAL(pszDebug,"") )
+    if( !EQUAL(pszDebug, "ON") && !EQUAL(pszDebug, "") )
     {
-        size_t  i, nLen = strlen(pszCategory);
+        const size_t nLen = strlen(pszCategory);
 
+        size_t i = 0;
         for( i = 0; pszDebug[i] != '\0'; i++ )
         {
-            if( EQUALN(pszCategory,pszDebug+i,nLen) )
+            if( EQUALN(pszCategory, pszDebug+i, nLen) )
                 break;
         }
 
@@ -521,7 +538,7 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
         // convinced this is standard behaviour, so we'll get rid of it
         // carefully
 
-        if (pszMessage[strlen(pszMessage) -1 ] == '\n')
+        if( pszMessage[strlen(pszMessage) -1 ] == '\n' )
         {
             pszMessage[strlen(pszMessage) - 1] = 0; // blow it out
         }
@@ -533,13 +550,11 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
 /*      Add the process memory size.                                    */
 /* -------------------------------------------------------------------- */
 #ifdef MEMORY_DEBUG
-    char szVmSize[32];
+    char szVmSize[32] = {};
     CPLsprintf( szVmSize, "[VmSize: %d] ", CPLGetProcessMemorySize());
     strcat( pszMessage, szVmSize );
 #endif
 
-    //sprintf(pszMessage,"[%d] ", (int)getpid());
-
 /* -------------------------------------------------------------------- */
 /*      Add the category.                                               */
 /* -------------------------------------------------------------------- */
@@ -549,11 +564,11 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
 /* -------------------------------------------------------------------- */
 /*      Format the application provided portion of the debug message.   */
 /* -------------------------------------------------------------------- */
-    va_list     args;
+    va_list args;
     va_start(args, pszFormat);
 
     CPLvsnprintf(pszMessage+strlen(pszMessage), ERROR_MAX - strlen(pszMessage),
-              pszFormat, args);
+                 pszFormat, args);
 
     va_end(args);
 
@@ -568,7 +583,7 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
         while( *pszIter != ' ' && *pszIter != '\0' )
         {
             *pszIter = 'X';
-            pszIter ++;
+            pszIter++;
         }
     }
 
@@ -579,7 +594,8 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
     {
         if( psCtx->psHandlerStack->bCatchDebug )
         {
-            psCtx->psHandlerStack->pfnHandler( CE_Debug, CPLE_None, pszMessage );
+            psCtx->psHandlerStack->pfnHandler( CE_Debug, CPLE_None,
+                                               pszMessage );
         }
         else
         {
@@ -617,6 +633,7 @@ void CPLDebug( const char * pszCategory, const char * pszFormat, ... )
 
     VSIFree( pszMessage );
 }
+#endif  // !WITHOUT_CPLDEBUG
 
 /**********************************************************************
  *                          CPLErrorReset()
@@ -696,8 +713,8 @@ void CPL_DLL CPLErrorSetState( CPLErr eErrClass, CPLErrorNum err_no,
     psCtx->nLastErrNo = err_no;
     strncpy(psCtx->szLastErrMsg, pszMsg, psCtx->nLastErrMsgMax);
     psCtx->szLastErrMsg[
-        MAX(psCtx->nLastErrMsgMax-1,
-            static_cast<int>( strlen(pszMsg) ))] = '\0';
+        std::max(psCtx->nLastErrMsgMax-1,
+                 static_cast<int>( strlen(pszMsg) ))] = '\0';
     psCtx->eLastErrType = eErrClass;
 }
 
@@ -777,14 +794,15 @@ const char* CPL_STDCALL CPLGetLastErrorMsg()
 /*                       CPLDefaultErrorHandler()                       */
 /************************************************************************/
 
+/** Default error handler. */
 void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
-                             const char * pszErrorMsg )
+                                         const char * pszErrorMsg )
 
 {
-    static int       nCount = 0;
-    static int       nMaxErrors = -1;
+    static int nCount = 0;
+    static int nMaxErrors = -1;
 
-    if (eErrClass != CE_Debug)
+    if( eErrClass != CE_Debug )
     {
         if( nMaxErrors == -1 )
         {
@@ -793,7 +811,7 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
         }
 
         nCount++;
-        if (nCount > nMaxErrors && nMaxErrors > 0 )
+        if( nCount > nMaxErrors && nMaxErrors > 0 )
             return;
     }
 
@@ -810,7 +828,7 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
             const char* pszAccess = "wt";
             if( CPLGetConfigOption( "CPL_LOG_APPEND", NULL ) != NULL )
                 pszAccess = "at";
-            fpLog = fopen( CPLGetConfigOption("CPL_LOG",""), pszAccess );
+            fpLog = fopen( CPLGetConfigOption("CPL_LOG", ""), pszAccess );
             if( fpLog == NULL )
                 fpLog = stderr;
         }
@@ -823,7 +841,7 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
     else
         fprintf( fpLog, "ERROR %d: %s\n", nError, pszErrorMsg );
 
-    if (eErrClass != CE_Debug
+    if( eErrClass != CE_Debug
         && nMaxErrors > 0
         && nCount == nMaxErrors )
     {
@@ -840,8 +858,9 @@ void CPL_STDCALL CPLDefaultErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
 /*                        CPLQuietErrorHandler()                        */
 /************************************************************************/
 
+/** Error handler that does not do anything, except for debug messages. */
 void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , CPLErrorNum nError,
-                           const char * pszErrorMsg )
+                                       const char * pszErrorMsg )
 
 {
     if( eErrClass == CE_Debug )
@@ -852,12 +871,15 @@ void CPL_STDCALL CPLQuietErrorHandler( CPLErr eErrClass , CPLErrorNum nError,
 /*                       CPLLoggingErrorHandler()                       */
 /************************************************************************/
 
+/** Error handler that logs into the file defined by the CPL_LOG configuration
+ * option, or stderr otherwise.
+ */
 void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
-                             const char * pszErrorMsg )
+                                         const char * pszErrorMsg )
 
 {
-    static bool      bLogInit = false;
-    static FILE *    fpLog = stderr;
+    static bool bLogInit = false;
+    static FILE *fpLog = stderr;
 
     if( !bLogInit )
     {
@@ -868,15 +890,14 @@ void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
         const char *cpl_log = CPLGetConfigOption("CPL_LOG", NULL );
 
         fpLog = stderr;
-        if( cpl_log != NULL && EQUAL(cpl_log,"OFF") )
+        if( cpl_log != NULL && EQUAL(cpl_log, "OFF") )
         {
             fpLog = NULL;
         }
         else if( cpl_log != NULL )
         {
             size_t nPathLen = strlen(cpl_log) + 20;
-            char* pszPath
-                = static_cast<char *>( CPLMalloc(nPathLen) );
+            char* pszPath = static_cast<char *>(CPLMalloc(nPathLen));
             strcpy(pszPath, cpl_log);
 
             int i = 0;
@@ -884,8 +905,8 @@ void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
             {
                 fclose( fpLog );
 
-                /* generate sequenced log file names, inserting # before ext.*/
-                if (strrchr(cpl_log, '.') == NULL)
+                // Generate sequenced log file names, inserting # before ext.
+                if( strrchr(cpl_log, '.') == NULL )
                 {
                     snprintf( pszPath, nPathLen, "%s_%d%s", cpl_log, i++,
                              ".log" );
@@ -895,7 +916,7 @@ void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
                     size_t pos = 0;
                     char *cpl_log_base = CPLStrdup(cpl_log);
                     pos = strcspn(cpl_log_base, ".");
-                    if (pos > 0)
+                    if( pos > 0 )
                     {
                         cpl_log_base[pos] = '\0';
                     }
@@ -927,6 +948,8 @@ void CPL_STDCALL CPLLoggingErrorHandler( CPLErr eErrClass, CPLErrorNum nError,
  *                      CPLTurnFailureIntoWarning()                   *
  **********************************************************************/
 
+/** Whether failures should be turned into warnings.
+ */
 void CPLTurnFailureIntoWarning( int bOn )
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
@@ -936,7 +959,7 @@ void CPLTurnFailureIntoWarning( int bOn )
         return;
     }
     psCtx->nFailureIntoWarning += (bOn) ? 1 : -1;
-    if (psCtx->nFailureIntoWarning < 0)
+    if( psCtx->nFailureIntoWarning < 0 )
     {
         CPLDebug( "CPL", "Wrong nesting of CPLTurnFailureIntoWarning(TRUE) / "
                   "CPLTurnFailureIntoWarning(FALSE)" );
@@ -951,7 +974,7 @@ void CPLTurnFailureIntoWarning( int bOn )
  * Install custom error handle with user's data. This method is
  * essentially CPLSetErrorHandler with an added pointer to pUserData.
  * The pUserData is not returned in the CPLErrorHandler, however, and
- * must be fetched via CPLGetLastErrorUserData
+ * must be fetched via CPLGetErrorHandlerUserData.
  *
  * @param pfnErrorHandlerNew new error handler function.
  * @param pUserData User data to carry along with the error context.
@@ -959,8 +982,7 @@ void CPLTurnFailureIntoWarning( int bOn )
  */
 
 CPLErrorHandler CPL_STDCALL
-CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew,
-                      void* pUserData )
+CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew, void* pUserData )
 {
     CPLErrorContext *psCtx = CPLGetErrorContext();
     if( psCtx == NULL || IS_PREFEFINED_ERROR_CTX(psCtx) )
@@ -972,12 +994,12 @@ CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew,
     if( psCtx->psHandlerStack != NULL )
     {
         CPLDebug( "CPL",
-                  "CPLSetErrorHandler() called with an error handler on\n"
+                  "CPLSetErrorHandler() called with an error handler on "
                   "the local stack.  New error handler will not be used "
-                  "immediately.\n" );
+                  "immediately." );
     }
 
-    CPLErrorHandler pfnOldHandler;
+    CPLErrorHandler pfnOldHandler = NULL;
     {
         CPLMutexHolderD( &hErrorMutex );
 
@@ -994,7 +1016,6 @@ CPLSetErrorHandlerEx( CPLErrorHandler pfnErrorHandlerNew,
     return pfnOldHandler;
 }
 
-
 /**********************************************************************
  *                          CPLSetErrorHandler()                      *
  **********************************************************************/
@@ -1065,7 +1086,6 @@ void CPL_STDCALL CPLPushErrorHandler( CPLErrorHandler pfnErrorHandlerNew )
     CPLPushErrorHandlerEx(pfnErrorHandlerNew, NULL);
 }
 
-
 /************************************************************************/
 /*                        CPLPushErrorHandlerEx()                       */
 /************************************************************************/
@@ -1151,7 +1171,8 @@ void CPL_STDCALL CPLPopErrorHandler()
  * previous installed handler exists in the stack) deal with it. In which
  * case, this function should be called with bCatchDebug.
  *
- * @param bCatchDebug FALSE if the current error handler should not intercept debug messages
+ * @param bCatchDebug FALSE if the current error handler should not intercept
+ * debug messages
  * @since GDAL 2.1
  */
 
@@ -1190,19 +1211,18 @@ void CPL_STDCALL CPLSetCurrentErrorHandlerCatchDebug( int bCatchDebug )
  */
 
 void CPL_STDCALL _CPLAssert( const char * pszExpression, const char * pszFile,
-                 int iLine )
+                             int iLine )
 
 {
     CPLError( CE_Fatal, CPLE_AssertionFailed,
-              "Assertion `%s' failed\n"
-              "in file `%s', line %d\n",
+              "Assertion `%s' failed "
+              "in file `%s', line %d",
               pszExpression, pszFile, iLine );
 
     // Just to please compiler so it is aware the function does not return.
     abort();
 }
 
-
 /************************************************************************/
 /*                       CPLCleanupErrorMutex()                         */
 /************************************************************************/
diff --git a/port/cpl_error.h b/port/cpl_error.h
index 3ddad1a..79a8269 100644
--- a/port/cpl_error.h
+++ b/port/cpl_error.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_error.h 33842 2016-04-01 08:37:32Z rouault $
+ * $Id: cpl_error.h 36675 2016-12-04 11:10:10Z rouault $
  *
  * Name:     cpl_error.h
  * Project:  CPL - Common Portability Library
@@ -33,6 +33,9 @@
 
 #include "cpl_port.h"
 
+#include <stdarg.h>
+#include <stddef.h>
+
 /*=====================================================================
                    Error handling functions (cpl_error.c)
  =====================================================================*/
@@ -45,6 +48,7 @@
 
 CPL_C_START
 
+/** Error category */
 typedef enum
 {
     CE_None = 0,
@@ -87,35 +91,53 @@ typedef enum
 
 #else
 
+/** Error number */
 typedef int CPLErrorNum;
 
+/** No error */
 #define CPLE_None                       0
+/** Application defined error */
 #define CPLE_AppDefined                 1
+/** Out of memory error */
 #define CPLE_OutOfMemory                2
+/** File I/O error */
 #define CPLE_FileIO                     3
+/** Open failed */
 #define CPLE_OpenFailed                 4
+/** Illegal argument */
 #define CPLE_IllegalArg                 5
+/** Not supported */
 #define CPLE_NotSupported               6
+/** Assertion failed */
 #define CPLE_AssertionFailed            7
+/** No write access */
 #define CPLE_NoWriteAccess              8
+/** User interrupted */
 #define CPLE_UserInterrupt              9
+/** NULL object */
 #define CPLE_ObjectNull                 10
 
 /*
  * Filesystem-specific errors
  */
+/** HTTP response */
 #define CPLE_HttpResponse               11
+/** AWSBucketNotFound */
 #define CPLE_AWSBucketNotFound          12
+/** AWSObjectNotFound */
 #define CPLE_AWSObjectNotFound          13
+/** AWSAccessDenied */
 #define CPLE_AWSAccessDenied            14
+/** AWSInvalidCredentials */
 #define CPLE_AWSInvalidCredentials      15
+/** AWSSignatureDoesNotMatch */
 #define CPLE_AWSSignatureDoesNotMatch    16
 
 /* 100 - 299 reserved for GDAL */
 
 #endif
 
-void CPL_DLL CPLError(CPLErr eErrClass, CPLErrorNum err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (3, 4);
+void CPL_DLL CPLError(CPLErr eErrClass, CPLErrorNum err_no, CPL_FORMAT_STRING(const char *fmt), ...)  CPL_PRINT_FUNC_FORMAT (3, 4);
 void CPL_DLL CPLErrorV(CPLErr, CPLErrorNum, const char *, va_list );
 void CPL_DLL CPLEmergencyError( const char * ) CPL_NO_RETURN;
 void CPL_DLL CPL_STDCALL CPLErrorReset( void );
@@ -124,33 +146,45 @@ CPLErr CPL_DLL CPL_STDCALL CPLGetLastErrorType( void );
 const char CPL_DLL * CPL_STDCALL CPLGetLastErrorMsg( void );
 void CPL_DLL * CPL_STDCALL CPLGetErrorHandlerUserData(void);
 void CPL_DLL CPLErrorSetState( CPLErr eErrClass, CPLErrorNum err_no, const char* pszMsg );
+/*! @cond Doxygen_Suppress */
 void CPL_DLL CPLCleanupErrorMutex( void );
+/*! @endcond */
 
+/** Callback for a custom error handler */
 typedef void (CPL_STDCALL *CPLErrorHandler)(CPLErr, CPLErrorNum, const char*);
 
 void CPL_DLL CPL_STDCALL CPLLoggingErrorHandler( CPLErr, CPLErrorNum, const char * );
 void CPL_DLL CPL_STDCALL CPLDefaultErrorHandler( CPLErr, CPLErrorNum, const char * );
 void CPL_DLL CPL_STDCALL CPLQuietErrorHandler( CPLErr, CPLErrorNum, const char * );
-void CPLTurnFailureIntoWarning(int bOn );
+void CPLTurnFailureIntoWarning( int bOn );
 
-CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandler(CPLErrorHandler);
-CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandlerEx(CPLErrorHandler, void*);
+CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandler( CPLErrorHandler );
+CPLErrorHandler CPL_DLL CPL_STDCALL CPLSetErrorHandlerEx( CPLErrorHandler, void* );
 void CPL_DLL CPL_STDCALL CPLPushErrorHandler( CPLErrorHandler );
 void CPL_DLL CPL_STDCALL CPLPushErrorHandlerEx( CPLErrorHandler, void* );
 void CPL_DLL CPL_STDCALL CPLSetCurrentErrorHandlerCatchDebug( int bCatchDebug );
 void CPL_DLL CPL_STDCALL CPLPopErrorHandler(void);
 
-void CPL_DLL CPL_STDCALL CPLDebug( const char *, const char *, ... )  CPL_PRINT_FUNC_FORMAT (2, 3);
+#ifdef WITHOUT_CPLDEBUG
+#define CPLDebug(...)  /* Eat all CPLDebug calls. */
+#else
+void CPL_DLL CPL_STDCALL CPLDebug(const char *, CPL_FORMAT_STRING(const char *), ...)
+    CPL_PRINT_FUNC_FORMAT(2, 3);
+#endif
+
 void CPL_DLL CPL_STDCALL _CPLAssert( const char *, const char *, int ) CPL_NO_RETURN;
 
 #ifdef DEBUG
+/** Assert on an expression. Only enabled in DEBUG mode */
 #  define CPLAssert(expr)  ((expr) ? (void)(0) : _CPLAssert(#expr,__FILE__,__LINE__))
 #else
+/** Assert on an expression. Only enabled in DEBUG mode */
 #  define CPLAssert(expr)
 #endif
 
 CPL_C_END
 
+/*! @cond Doxygen_Suppress */
 /*
  * Helper macros used for input parameters validation.
  */
@@ -159,7 +193,9 @@ CPL_C_END
 #else
 #  define VALIDATE_POINTER_ERR CE_Failure
 #endif
+/*! @endcond */
 
+/** Validate that a pointer is not NULL */
 #define VALIDATE_POINTER0(ptr, func) \
    do { if( NULL == ptr ) \
       { \
@@ -168,6 +204,7 @@ CPL_C_END
            "Pointer \'%s\' is NULL in \'%s\'.\n", #ptr, (func)); \
          return; }} while(0)
 
+/** Validate that a pointer is not NULL, and return rc if it is NULL */
 #define VALIDATE_POINTER1(ptr, func, rc) \
    do { if( NULL == ptr ) \
       { \
diff --git a/port/cpl_findfile.cpp b/port/cpl_findfile.cpp
index bf1eea3..8b62854 100644
--- a/port/cpl_findfile.cpp
+++ b/port/cpl_findfile.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_findfile.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Generic data file location finder, with application hooking.
@@ -28,30 +27,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
+
+#include <cstddef>
+
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_findfile.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+CPL_CVSID("$Id: cpl_findfile.cpp 36797 2016-12-11 21:48:20Z goatbar $");
 
 typedef struct
 {
-    int bFinderInitialized;
+    bool bFinderInitialized;
     int nFileFinders;
     CPLFileFinder *papfnFinders;
     char **papszFinderLocations;
 } FindFileTLS;
 
-
 /************************************************************************/
 /*                      CPLFindFileDeinitTLS()                          */
 /************************************************************************/
 
-static void CPLPopFinderLocationInternal(FindFileTLS* pTLSData);
-static CPLFileFinder CPLPopFileFinderInternal(FindFileTLS* pTLSData);
+static void CPLPopFinderLocationInternal( FindFileTLS* pTLSData );
+static CPLFileFinder CPLPopFileFinderInternal( FindFileTLS* pTLSData );
 
-static void CPLFindFileFreeTLS(void* pData)
+static void CPLFindFileFreeTLS( void* pData )
 {
     FindFileTLS* pTLSData = reinterpret_cast<FindFileTLS *>( pData );
     if( pTLSData != NULL && pTLSData->bFinderInitialized )
@@ -60,7 +62,7 @@ static void CPLFindFileFreeTLS(void* pData)
             CPLPopFinderLocationInternal(pTLSData);
         while( CPLPopFileFinderInternal(pTLSData) != NULL ) {}
 
-        pTLSData->bFinderInitialized = FALSE;
+        pTLSData->bFinderInitialized = false;
     }
     CPLFree(pTLSData);
 }
@@ -77,7 +79,7 @@ static FindFileTLS* CPLGetFindFileTLS()
             CPLGetTLSEx( CTLS_FINDFILE, &bMemoryError ) );
     if( bMemoryError )
         return NULL;
-    if (pTLSData == NULL)
+    if( pTLSData == NULL )
     {
         pTLSData = static_cast<FindFileTLS *>(
             VSI_CALLOC_VERBOSE(1, sizeof(FindFileTLS) ) );
@@ -98,7 +100,7 @@ static FindFileTLS* CPLFinderInit()
     FindFileTLS* pTLSData = CPLGetFindFileTLS();
     if( pTLSData != NULL && !pTLSData->bFinderInitialized )
     {
-        pTLSData->bFinderInitialized = TRUE;
+        pTLSData->bFinderInitialized = true;
         CPLPushFileFinder( CPLDefaultFindFile );
 
         CPLPushFinderLocation( "." );
@@ -109,14 +111,15 @@ static FindFileTLS* CPLFinderInit()
         }
         else
         {
+#ifdef INST_DATA
+            CPLPushFinderLocation( INST_DATA );
+#endif
 #ifdef GDAL_PREFIX
   #ifdef MACOSX_FRAMEWORK
             CPLPushFinderLocation( GDAL_PREFIX "/Resources/gdal" );
   #else
             CPLPushFinderLocation( GDAL_PREFIX "/share/gdal" );
   #endif
-#else
-            CPLPushFinderLocation( "/usr/local/share/gdal" );
 #endif
         }
     }
@@ -127,6 +130,7 @@ static FindFileTLS* CPLFinderInit()
 /*                           CPLFinderClean()                           */
 /************************************************************************/
 
+/** CPLFinderClean */
 void CPLFinderClean()
 
 {
@@ -134,15 +138,14 @@ void CPLFinderClean()
     CPLFindFileFreeTLS(pTLSData);
     int bMemoryError = FALSE;
     CPLSetTLSWithFreeFuncEx( CTLS_FINDFILE, NULL, NULL, &bMemoryError );
-    // TODO: if( bMemoryError )
-    // {
-    // }
+    // TODO: if( bMemoryError ) {}
 }
 
 /************************************************************************/
 /*                         CPLDefaultFindFile()                         */
 /************************************************************************/
 
+/** CPLDefaultFindFile */
 const char *CPLDefaultFindFile( const char * /* pszClass */,
                                 const char *pszBasename )
 
@@ -154,11 +157,11 @@ const char *CPLDefaultFindFile( const char * /* pszClass */,
 
     for( int i = nLocations-1; i >= 0; i-- )
     {
-        const char  *pszResult
-            = CPLFormFilename( pTLSData->papszFinderLocations[i], pszBasename,
-                               NULL );
+        const char *pszResult =
+            CPLFormFilename( pTLSData->papszFinderLocations[i], pszBasename,
+                             NULL );
 
-        VSIStatBufL  sStat;
+        VSIStatBufL sStat;
         if( VSIStatL( pszResult, &sStat ) == 0 )
             return pszResult;
     }
@@ -170,6 +173,7 @@ const char *CPLDefaultFindFile( const char * /* pszClass */,
 /*                            CPLFindFile()                             */
 /************************************************************************/
 
+/** CPLFindFile */
 const char *CPLFindFile( const char *pszClass, const char *pszBasename )
 
 {
@@ -179,8 +183,8 @@ const char *CPLFindFile( const char *pszClass, const char *pszBasename )
 
     for( int i = pTLSData->nFileFinders-1; i >= 0; i-- )
     {
-        const char * pszResult
-            = (pTLSData->papfnFinders[i])( pszClass, pszBasename );
+        const char * pszResult =
+            (pTLSData->papfnFinders[i])( pszClass, pszBasename );
         if( pszResult != NULL )
             return pszResult;
     }
@@ -192,11 +196,12 @@ const char *CPLFindFile( const char *pszClass, const char *pszBasename )
 /*                         CPLPushFileFinder()                          */
 /************************************************************************/
 
+/** CPLPushFileFinder */
 void CPLPushFileFinder( CPLFileFinder pfnFinder )
 
 {
     FindFileTLS* pTLSData = CPLFinderInit();
-    if (pTLSData == NULL )
+    if( pTLSData == NULL )
         return;
 
     pTLSData->papfnFinders = static_cast<CPLFileFinder *>(
@@ -209,7 +214,7 @@ void CPLPushFileFinder( CPLFileFinder pfnFinder )
 /*                          CPLPopFileFinder()                          */
 /************************************************************************/
 
-CPLFileFinder CPLPopFileFinderInternal(FindFileTLS* pTLSData)
+CPLFileFinder CPLPopFileFinderInternal( FindFileTLS* pTLSData )
 
 {
     if( pTLSData == NULL || pTLSData->nFileFinders == 0 )
@@ -226,6 +231,7 @@ CPLFileFinder CPLPopFileFinderInternal(FindFileTLS* pTLSData)
     return pfnReturn;
 }
 
+/** CPLPopFileFinder */
 CPLFileFinder CPLPopFileFinder()
 
 {
@@ -236,23 +242,26 @@ CPLFileFinder CPLPopFileFinder()
 /*                       CPLPushFinderLocation()                        */
 /************************************************************************/
 
+/** CPLPushFinderLocation */
 void CPLPushFinderLocation( const char *pszLocation )
 
 {
     FindFileTLS* pTLSData = CPLFinderInit();
     if( pTLSData == NULL )
         return;
-    pTLSData->papszFinderLocations
-        = CSLAddStringMayFail( pTLSData->papszFinderLocations,
-                                   pszLocation );
+    // Check if location already is in list.
+    if( CSLFindStringCaseSensitive(pTLSData->papszFinderLocations,
+                                   pszLocation) > -1 )
+        return;
+    pTLSData->papszFinderLocations =
+        CSLAddStringMayFail( pTLSData->papszFinderLocations, pszLocation );
 }
 
-
 /************************************************************************/
 /*                       CPLPopFinderLocation()                         */
 /************************************************************************/
 
-static void CPLPopFinderLocationInternal(FindFileTLS* pTLSData)
+static void CPLPopFinderLocationInternal( FindFileTLS* pTLSData )
 
 {
     if( pTLSData == NULL || pTLSData->papszFinderLocations == NULL )
@@ -272,6 +281,7 @@ static void CPLPopFinderLocationInternal(FindFileTLS* pTLSData)
     }
 }
 
+/** CPLPopFinderLocation */
 void CPLPopFinderLocation()
 {
     CPLPopFinderLocationInternal(CPLFinderInit());
diff --git a/port/cpl_getexecpath.cpp b/port/cpl_getexecpath.cpp
index 9e076a5..8020f32 100644
--- a/port/cpl_getexecpath.cpp
+++ b/port/cpl_getexecpath.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_getexecpath.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement CPLGetExecPath().
@@ -27,10 +26,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_conv.h"
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "cpl_multiproc.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_getexecpath.cpp 33646 2016-03-05 15:54:03Z goatbar $");
+
+CPL_CVSID("$Id: cpl_getexecpath.cpp 36862 2016-12-14 22:16:39Z goatbar $");
 
 #if defined(WIN32)
 
@@ -44,11 +51,10 @@ CPL_CVSID("$Id: cpl_getexecpath.cpp 33646 2016-03-05 15:54:03Z goatbar $");
 
 int CPLGetExecPath( char *pszPathBuf, int nMaxLength )
 {
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
-        wchar_t *pwszPathBuf = (wchar_t*)
-            CPLCalloc(nMaxLength+1,sizeof(wchar_t));
+        wchar_t *pwszPathBuf = static_cast<wchar_t *>(
+            CPLCalloc(nMaxLength + 1, sizeof(wchar_t)));
 
         if( GetModuleFileNameW( NULL, pwszPathBuf, nMaxLength ) == 0 )
         {
@@ -58,7 +64,7 @@ int CPLGetExecPath( char *pszPathBuf, int nMaxLength )
         else
         {
             char *pszDecoded =
-                CPLRecodeFromWChar(pwszPathBuf,CPL_ENC_UCS2,CPL_ENC_UTF8);
+                CPLRecodeFromWChar(pwszPathBuf, CPL_ENC_UCS2, CPL_ENC_UTF8);
 
             strncpy( pszPathBuf, pszDecoded, nMaxLength );
             CPLFree( pszDecoded );
@@ -123,7 +129,7 @@ int CPLGetExecPath( char *pszPathBuf, int nMaxLength )
 
 #ifndef HAVE_IMPLEMENTATION
 
-int CPLGetExecPath( CPL_UNUSED char *pszPathBuf, CPL_UNUSED int nMaxLength )
+int CPLGetExecPath( CPL_UNUSED char * pszPathBuf, CPL_UNUSED int nMaxLength )
 {
     return FALSE;
 }
diff --git a/port/cpl_google_cloud.cpp b/port/cpl_google_cloud.cpp
new file mode 100644
index 0000000..795d516
--- /dev/null
+++ b/port/cpl_google_cloud.cpp
@@ -0,0 +1,180 @@
+/**********************************************************************
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Google Cloud Storage routines
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ **********************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+//! @cond Doxygen_Suppress
+
+#include "cpl_google_cloud.h"
+#include "cpl_vsi_error.h"
+#include "cpl_sha1.h"
+#include "cpl_time.h"
+
+CPL_CVSID("$Id: cpl_google_cloud.cpp 37645 2017-03-08 00:15:33Z rouault $");
+
+#ifdef HAVE_CURL
+
+/************************************************************************/
+/*                            GetGSHeaders()                            */
+/************************************************************************/
+
+static
+struct curl_slist* GetGSHeaders( const CPLString& osVerb,
+                                 const CPLString& osCanonicalResource,
+                                 const CPLString& osSecretAccessKey,
+                                 const CPLString& osAccessKeyId )
+{
+    if( osSecretAccessKey.empty() )
+    {
+        VSIError(VSIE_AWSInvalidCredentials,
+                 "GS_SECRET_ACCESS_KEY configuration option not defined");
+        return NULL;
+    }
+
+    if( osAccessKeyId.empty() )
+    {
+        VSIError(VSIE_AWSInvalidCredentials,
+                 "GS_ACCESS_KEY_ID configuration option not defined");
+        return NULL;
+    }
+
+    CPLString osDate = CPLGetConfigOption("CPL_GS_TIMESTAMP", "");
+    if( osDate.empty() )
+    {
+        char szDate[64];
+        time_t nNow = time(NULL);
+        struct tm tm;
+        CPLUnixTimeToYMDHMS(nNow, &tm);
+        strftime(szDate, sizeof(szDate), "%a, %d %b %Y %H:%M:%S GMT", &tm);
+        osDate = szDate;
+    }
+
+    // See https://cloud.google.com/storage/docs/migrating
+    CPLString osStringToSign;
+    osStringToSign += osVerb + "\n";
+    osStringToSign += /* Content-MD5 */ "\n";
+    osStringToSign += /* Content-Type */ "\n";
+    osStringToSign += osDate + "\n";
+    osStringToSign += osCanonicalResource;
+#ifdef DEBUG_VERBOSE
+    CPLDebug("GS", "osStringToSign = %s", osStringToSign.c_str());
+#endif
+
+    GByte abySignature[CPL_SHA1_HASH_SIZE] = {};
+    CPL_HMAC_SHA1( osSecretAccessKey.c_str(), osSecretAccessKey.size(),
+                   osStringToSign, osStringToSign.size(),
+                   abySignature);
+
+    char* pszBase64 = CPLBase64Encode( sizeof(abySignature), abySignature );
+    CPLString osAuthorization("GOOG1 ");
+    osAuthorization += osAccessKeyId;
+    osAuthorization += ":";
+    osAuthorization += pszBase64;
+    CPLFree(pszBase64);
+
+    struct curl_slist *headers=NULL;
+    headers = curl_slist_append(
+        headers, CPLSPrintf("Date: %s", osDate.c_str()));
+    headers = curl_slist_append(
+        headers, CPLSPrintf("Authorization: %s", osAuthorization.c_str()));
+    return headers;
+}
+
+/************************************************************************/
+/*                         VSIGSHandleHelper()                          */
+/************************************************************************/
+VSIGSHandleHelper::VSIGSHandleHelper( const CPLString& osEndpoint,
+                                      const CPLString& osBucketObjectKey,
+                                      const CPLString& osSecretAccessKey,
+                                      const CPLString& osAccessKeyId,
+                                      bool bUseHeaderFile ) :
+    m_osURL(osEndpoint + osBucketObjectKey),
+    m_osEndpoint(osEndpoint),
+    m_osBucketObjectKey(osBucketObjectKey),
+    m_osSecretAccessKey(osSecretAccessKey),
+    m_osAccessKeyId(osAccessKeyId),
+    m_bUseHeaderFile(bUseHeaderFile)
+{}
+
+/************************************************************************/
+/*                        ~VSIGSHandleHelper()                          */
+/************************************************************************/
+
+VSIGSHandleHelper::~VSIGSHandleHelper()
+{
+}
+
+/************************************************************************/
+/*                          BuildFromURI()                              */
+/************************************************************************/
+
+VSIGSHandleHelper* VSIGSHandleHelper::BuildFromURI( const char* pszURI,
+                                                    const char* /*pszFSPrefix*/ )
+{
+    // pszURI == bucket/object
+    const CPLString osBucketObject( pszURI );
+    const CPLString osEndpoint( CPLGetConfigOption("CPL_GS_ENDPOINT",
+                                    "https://storage.googleapis.com/") );
+    const CPLString osSecretAccessKey(
+        CPLGetConfigOption("GS_SECRET_ACCESS_KEY", ""));
+    const CPLString osAccessKeyId(
+        CPLGetConfigOption("GS_ACCESS_KEY_ID", ""));
+    const CPLString osHeaderFile(
+        CPLGetConfigOption("GDAL_HTTP_HEADER_FILE", "") );
+
+    if( osHeaderFile.empty() )
+    {
+        struct curl_slist* headers = 
+            GetGSHeaders( "GET", "",  osSecretAccessKey, osAccessKeyId );
+        if( headers == NULL )
+            return NULL;
+        curl_slist_free_all(headers);
+    }
+
+    return new VSIGSHandleHelper( osEndpoint,
+                                  osBucketObject,
+                                  osSecretAccessKey,
+                                  osAccessKeyId,
+                                  !osHeaderFile.empty() );
+}
+
+/************************************************************************/
+/*                           GetCurlHeaders()                           */
+/************************************************************************/
+
+struct curl_slist *
+VSIGSHandleHelper::GetCurlHeaders( const CPLString& osVerb ) const
+{
+    if( m_bUseHeaderFile )
+        return NULL;
+    return GetGSHeaders( osVerb,
+                         "/" + m_osBucketObjectKey,
+                         m_osSecretAccessKey,
+                         m_osAccessKeyId );
+}
+
+#endif
+
+//! @endcond
diff --git a/port/cpl_google_cloud.h b/port/cpl_google_cloud.h
new file mode 100644
index 0000000..430cc5f
--- /dev/null
+++ b/port/cpl_google_cloud.h
@@ -0,0 +1,70 @@
+/**********************************************************************
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Google Cloud Storage routines
+ * Author:   Even Rouault <even.rouault at spatialys.com>
+ *
+ **********************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef CPL_GOOGLE_CLOUD_INCLUDED_H
+#define CPL_GOOGLE_CLOUD_INCLUDED_H
+
+#ifndef DOXYGEN_SKIP
+
+#include <cstddef>
+
+#include "cpl_string.h"
+
+#ifdef HAVE_CURL
+
+#include <curl/curl.h>
+
+class VSIGSHandleHelper
+{
+        CPLString m_osURL;
+        CPLString m_osEndpoint;
+        CPLString m_osBucketObjectKey;
+        CPLString m_osSecretAccessKey;
+        CPLString m_osAccessKeyId;
+        bool      m_bUseHeaderFile;
+
+    public:
+        VSIGSHandleHelper(const CPLString& osEndpoint,
+                          const CPLString& osBucketObjectKey,
+                          const CPLString& osSecretAccessKey,
+                          const CPLString& osAccessKeyId,
+                          bool bUseHeaderFile);
+       ~VSIGSHandleHelper();
+
+        static VSIGSHandleHelper* BuildFromURI(const char* pszURI,
+                                               const char* pszFSPrefix);
+
+        struct curl_slist* GetCurlHeaders(const CPLString& osVerb) const;
+
+        const CPLString& GetURL() const { return m_osURL; }
+};
+
+#endif /* HAVE_CURL */
+
+#endif /* #ifndef DOXYGEN_SKIP */
+
+#endif /* CPL_GOOGLE_CLOUD_INCLUDED_H */
diff --git a/port/cpl_google_oauth2.cpp b/port/cpl_google_oauth2.cpp
index cc38de7..28127d9 100644
--- a/port/cpl_google_oauth2.cpp
+++ b/port/cpl_google_oauth2.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  Common Portability Library
  * Purpose:  Google OAuth2 Authentication Services
@@ -28,8 +27,15 @@
  ****************************************************************************/
 
 #include "cpl_http.h"
+#include "cpl_port.h"
 
-CPL_CVSID("$Id$");
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
+
+CPL_CVSID("$Id: cpl_google_oauth2.cpp 37452 2017-02-25 15:47:11Z goatbar $");
 
 /* ==================================================================== */
 /*      Values related to OAuth2 authorization to use fusion            */
@@ -82,7 +88,7 @@ static CPLStringList ParseSimpleJson(const char *pszJson)
 
     for( int i=0; i < oWords.size(); i += 2 )
     {
-        oNameValue.SetNameValue( oWords[i], oWords[i+1] );
+        oNameValue.SetNameValue(oWords[i], oWords[i+1]);
     }
 
     return oNameValue;
@@ -118,13 +124,15 @@ char *GOA2GetAuthorizationURL(const char *pszScope)
 
 {
     CPLString osScope;
-    CPLString osURL;
-
     osScope.Seize(CPLEscapeString(pszScope, -1, CPLES_URL));
-    osURL.Printf( "%s/auth?scope=%s&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&client_id=%s",
-                  GOOGLE_AUTH_URL,
-                  osScope.c_str(),
-                  CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID));
+
+    CPLString osURL;
+    osURL.Printf(
+        "%s/auth?scope=%s&redirect_uri=urn:ietf:wg:oauth:2.0:oob&"
+        "response_type=code&client_id=%s",
+        GOOGLE_AUTH_URL,
+        osScope.c_str(),
+        CPLGetConfigOption("GOA2_CLIENT_ID", GDAL_CLIENT_ID));
     return CPLStrdup(osURL);
 }
 
@@ -160,7 +168,7 @@ char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken,
     CPLStringList oOptions;
 
     oOptions.AddString(
-        "HEADERS=Content-Type: application/x-www-form-urlencoded" );
+        "HEADERS=Content-Type: application/x-www-form-urlencoded");
 
     osItem.Printf(
         "POSTFIELDS="
@@ -178,74 +186,76 @@ char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken,
 /*      Submit request by HTTP.                                         */
 /* -------------------------------------------------------------------- */
     CPLHTTPResult * psResult =
-        CPLHTTPFetch( GOOGLE_AUTH_URL "/token", oOptions);
+        CPLHTTPFetch(GOOGLE_AUTH_URL "/token", oOptions);
 
-    if (psResult == NULL)
+    if( psResult == NULL )
         return NULL;
 
 /* -------------------------------------------------------------------- */
 /*      One common mistake is to try and reuse the auth token.          */
 /*      After the first use it will return invalid_grant.               */
 /* -------------------------------------------------------------------- */
-    if( psResult->pabyData != NULL
-        && strstr((const char *) psResult->pabyData,"invalid_grant") != NULL)
+    if( psResult->pabyData != NULL &&
+        strstr(reinterpret_cast<char *>(psResult->pabyData), "invalid_grant")
+        != NULL )
     {
         CPLString osURL;
-        osURL.Seize( GOA2GetAuthorizationURL(pszScope) );
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Attempt to use a OAuth2 authorization code multiple times.\n"
-                  "Request a fresh authorization token at\n%s.",
-                  osURL.c_str() );
+        osURL.Seize(GOA2GetAuthorizationURL(pszScope));
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Attempt to use a OAuth2 authorization code multiple times.  "
+                 "Request a fresh authorization token at %s.",
+                 osURL.c_str());
         CPLHTTPDestroyResult(psResult);
         return NULL;
     }
 
-    if (psResult->pabyData == NULL ||
-        psResult->pszErrBuf != NULL)
+    if( psResult->pabyData == NULL ||
+        psResult->pszErrBuf != NULL )
     {
         if( psResult->pszErrBuf != NULL )
-            CPLDebug( "GOA2", "%s", psResult->pszErrBuf );
+            CPLDebug("GOA2", "%s", psResult->pszErrBuf);
         if( psResult->pabyData != NULL )
-            CPLDebug( "GOA2", "%s", psResult->pabyData );
+            CPLDebug("GOA2", "%s", psResult->pabyData);
 
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Fetching OAuth2 access code from auth code failed.");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Fetching OAuth2 access code from auth code failed.");
         CPLHTTPDestroyResult(psResult);
         return NULL;
     }
 
-    CPLDebug( "GOA2", "Access Token Response:\n%s",
-              (const char *) psResult->pabyData );
+    CPLDebug("GOA2", "Access Token Response:\n%s",
+             reinterpret_cast<char *>(psResult->pabyData));
 
 /* -------------------------------------------------------------------- */
 /*      This response is in JSON and will look something like:          */
 /* -------------------------------------------------------------------- */
 /*
 {
-  "access_token" : "ya29.AHES6ZToqkIJkat5rIqMixR1b8PlWBACNO8OYbqqV-YF1Q13E2Kzjw",
-  "token_type" : "Bearer",
-  "expires_in" : 3600,
-  "refresh_token" : "1/eF88pciwq9Tp_rHEhuiIv9AS44Ufe4GOymGawTVPGYo"
+ "access_token" : "ya29.AHES6ZToqkIJkat5rIqMixR1b8PlWBACNO8OYbqqV-YF1Q13E2Kzjw",
+ "token_type" : "Bearer",
+ "expires_in" : 3600,
+ "refresh_token" : "1/eF88pciwq9Tp_rHEhuiIv9AS44Ufe4GOymGawTVPGYo"
 }
 */
     CPLStringList oResponse = ParseSimpleJson(
-        (const char *) psResult->pabyData );
+        reinterpret_cast<char *>(psResult->pabyData));
     CPLHTTPDestroyResult(psResult);
 
-    CPLString osAccessToken = oResponse.FetchNameValueDef( "access_token", "" );
-    CPLString osRefreshToken = oResponse.FetchNameValueDef( "refresh_token", "" );
+    CPLString osAccessToken = oResponse.FetchNameValueDef("access_token", "");
+    CPLString osRefreshToken = oResponse.FetchNameValueDef("refresh_token", "");
     CPLDebug("GOA2", "Access Token : '%s'", osAccessToken.c_str());
     CPLDebug("GOA2", "Refresh Token : '%s'", osRefreshToken.c_str());
 
-    if( osRefreshToken.size() == 0)
+    if( osRefreshToken.empty() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to identify a refresh token in the OAuth2 response.");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to identify a refresh token in the OAuth2 response.");
         return NULL;
     }
     else
     {
-        // Currently we discard the access token and just return the refresh token
+        // Currently we discard the access token and just return the
+        // refresh token.
         return CPLStrdup(osRefreshToken);
     }
 }
@@ -265,13 +275,13 @@ char CPL_DLL *GOA2GetRefreshToken( const char *pszAuthToken,
  * user or http connection problems.
  *
  * @param pszRefreshToken the refresh token from GOA2GetRefreshToken().
- * @param pszScope the scope for which it is valid.
+ * @param pszScope the scope for which it is valid. Currently unused
  *
  * @return access token, to be freed with CPLFree(), null on failure.
  */
 
 char *GOA2GetAccessToken( const char *pszRefreshToken,
-                          CPL_UNUSED const char *pszScope )
+                          CPL_UNUSED const char * pszScope )
 {
 /* -------------------------------------------------------------------- */
 /*      Prepare request.                                                */
@@ -298,25 +308,25 @@ char *GOA2GetAccessToken( const char *pszRefreshToken,
 /* -------------------------------------------------------------------- */
     CPLHTTPResult *psResult = CPLHTTPFetch(GOOGLE_AUTH_URL "/token", oOptions);
 
-    if (psResult == NULL)
+    if( psResult == NULL )
         return NULL;
 
-    if (psResult->pabyData == NULL ||
-        psResult->pszErrBuf != NULL)
+    if( psResult->pabyData == NULL ||
+        psResult->pszErrBuf != NULL )
     {
         if( psResult->pszErrBuf != NULL )
-            CPLDebug( "GFT", "%s", psResult->pszErrBuf );
+            CPLDebug("GFT", "%s", psResult->pszErrBuf);
         if( psResult->pabyData != NULL )
-            CPLDebug( "GFT", "%s", psResult->pabyData );
+            CPLDebug("GFT", "%s", psResult->pabyData);
 
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Fetching OAuth2 access code from auth code failed.");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Fetching OAuth2 access code from auth code failed.");
         CPLHTTPDestroyResult(psResult);
         return NULL;
     }
 
-    CPLDebug( "GOA2", "Refresh Token Response:\n%s",
-              (const char *) psResult->pabyData );
+    CPLDebug("GOA2", "Refresh Token Response:\n%s",
+             reinterpret_cast<char *>(psResult->pabyData));
 
 /* -------------------------------------------------------------------- */
 /*      This response is in JSON and will look something like:          */
@@ -329,19 +339,19 @@ char *GOA2GetAccessToken( const char *pszRefreshToken,
 }
 */
     CPLStringList oResponse = ParseSimpleJson(
-        (const char *) psResult->pabyData );
+        reinterpret_cast<char *>(psResult->pabyData));
     CPLHTTPDestroyResult(psResult);
 
-    CPLString osAccessToken = oResponse.FetchNameValueDef( "access_token", "" );
+    CPLString osAccessToken = oResponse.FetchNameValueDef("access_token", "");
 
     CPLDebug("GOA2", "Access Token : '%s'", osAccessToken.c_str());
 
-    if (osAccessToken.size() == 0)
+    if( osAccessToken.empty() )
     {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Unable to identify an access token in the OAuth2 response.");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "Unable to identify an access token in the OAuth2 response.");
         return NULL;
     }
-    else
-        return CPLStrdup(osAccessToken);
+
+    return CPLStrdup(osAccessToken);
 }
diff --git a/port/cpl_hash_set.cpp b/port/cpl_hash_set.cpp
index 01dd7ff..600b579 100644
--- a/port/cpl_hash_set.cpp
+++ b/port/cpl_hash_set.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_hash_set.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_hash_set.cpp
  * Project:  CPL - Common Portability Library
@@ -28,10 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_conv.h"
 #include "cpl_hash_set.h"
+
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_list.h"
 
+CPL_CVSID("$Id: cpl_hash_set.cpp 36925 2016-12-17 04:17:39Z goatbar $");
+
 struct _CPLHashSet
 {
     CPLHashSetHashFunc    fnHashFunc;
@@ -43,18 +48,20 @@ struct _CPLHashSet
     int                   nAllocatedSize;
     CPLList              *psRecyclingList;
     int                   nRecyclingListSize;
-    int                   bRehash;
+    bool                  bRehash;
 #ifdef HASH_DEBUG
     int                   nCollisions;
 #endif
 };
 
 static const int anPrimes[] =
-{ 53, 97, 193, 389, 769, 1543, 3079, 6151,
-  12289, 24593, 49157, 98317, 196613, 393241,
-  786433, 1572869, 3145739, 6291469, 12582917,
-  25165843, 50331653, 100663319, 201326611,
-  402653189, 805306457, 1610612741 };
+{
+    53, 97, 193, 389, 769, 1543, 3079, 6151,
+    12289, 24593, 49157, 98317, 196613, 393241,
+    786433, 1572869, 3145739, 6291469, 12582917,
+    25165843, 50331653, 100663319, 201326611,
+    402653189, 805306457, 1610612741
+};
 
 /************************************************************************/
 /*                          CPLHashSetNew()                             */
@@ -71,7 +78,8 @@ static const int anPrimes[] =
  *
  * The free function is used to free elements inserted in the hash set,
  * when the hash set is destroyed, when elements are removed or replaced.
- * If fnFreeEltFunc is NULL, elements inserted into the hash set will not be freed.
+ * If fnFreeEltFunc is NULL, elements inserted into the hash set will not be
+ * freed.
  *
  * @param fnHashFunc hash function. May be NULL.
  * @param fnEqualFunc equal function. May be NULL.
@@ -80,28 +88,27 @@ static const int anPrimes[] =
  * @return a new hash set
  */
 
-CPLHashSet* CPLHashSetNew(CPLHashSetHashFunc fnHashFunc,
-                          CPLHashSetEqualFunc fnEqualFunc,
-                          CPLHashSetFreeEltFunc fnFreeEltFunc)
+CPLHashSet* CPLHashSetNew( CPLHashSetHashFunc fnHashFunc,
+                           CPLHashSetEqualFunc fnEqualFunc,
+                           CPLHashSetFreeEltFunc fnFreeEltFunc )
 {
-    CPLHashSet* set = (CPLHashSet*) CPLMalloc(sizeof(CPLHashSet));
-    set->fnHashFunc = (fnHashFunc) ? fnHashFunc : CPLHashSetHashPointer;
-    set->fnEqualFunc = (fnEqualFunc) ? fnEqualFunc : CPLHashSetEqualPointer;
+    CPLHashSet* set = static_cast<CPLHashSet *>(CPLMalloc(sizeof(CPLHashSet)));
+    set->fnHashFunc = fnHashFunc ? fnHashFunc : CPLHashSetHashPointer;
+    set->fnEqualFunc = fnEqualFunc ? fnEqualFunc : CPLHashSetEqualPointer;
     set->fnFreeEltFunc = fnFreeEltFunc;
     set->nSize = 0;
-    set->tabList = (CPLList**) CPLCalloc(sizeof(CPLList*), 53);
+    set->tabList = static_cast<CPLList**>(CPLCalloc(sizeof(CPLList*), 53));
     set->nIndiceAllocatedSize = 0;
     set->nAllocatedSize = 53;
     set->psRecyclingList = NULL;
     set->nRecyclingListSize = 0;
-    set->bRehash = FALSE;
+    set->bRehash = false;
 #ifdef HASH_DEBUG
     set->nCollisions = 0;
 #endif
     return set;
 }
 
-
 /************************************************************************/
 /*                          CPLHashSetSize()                            */
 /************************************************************************/
@@ -116,7 +123,7 @@ CPLHashSet* CPLHashSetNew(CPLHashSetHashFunc fnHashFunc,
  * @return the number of elements in the hash set
  */
 
-int CPLHashSetSize(const CPLHashSet* set)
+int CPLHashSetSize( const CPLHashSet* set )
 {
     CPLAssert(set != NULL);
     return set->nSize;
@@ -126,31 +133,31 @@ int CPLHashSetSize(const CPLHashSet* set)
 /*                       CPLHashSetGetNewListElt()                      */
 /************************************************************************/
 
-static CPLList* CPLHashSetGetNewListElt(CPLHashSet* set)
+static CPLList* CPLHashSetGetNewListElt( CPLHashSet* set )
 {
     if( set->psRecyclingList )
     {
         CPLList* psRet = set->psRecyclingList;
         psRet->pData = NULL;
-        set->nRecyclingListSize --;
+        set->nRecyclingListSize--;
         set->psRecyclingList = psRet->psNext;
         return psRet;
     }
-    else
-        return (CPLList*) CPLMalloc(sizeof(CPLList));
+
+    return static_cast<CPLList *>(CPLMalloc(sizeof(CPLList)));
 }
 
 /************************************************************************/
 /*                       CPLHashSetReturnListElt()                      */
 /************************************************************************/
 
-static void CPLHashSetReturnListElt(CPLHashSet* set, CPLList* psList)
+static void CPLHashSetReturnListElt( CPLHashSet* set, CPLList* psList )
 {
     if( set->nRecyclingListSize < 128 )
     {
         psList->psNext = set->psRecyclingList;
         set->psRecyclingList = psList;
-        set->nRecyclingListSize ++;
+        set->nRecyclingListSize++;
     }
     else
     {
@@ -162,15 +169,15 @@ static void CPLHashSetReturnListElt(CPLHashSet* set, CPLList* psList)
 /*                   CPLHashSetClearInternal()                          */
 /************************************************************************/
 
-static void CPLHashSetClearInternal(CPLHashSet* set, int bFinalize)
+static void CPLHashSetClearInternal( CPLHashSet* set, bool bFinalize )
 {
     CPLAssert(set != NULL);
-    for(int i=0;i<set->nAllocatedSize;i++)
+    for( int i = 0; i < set->nAllocatedSize; i++ )
     {
         CPLList* cur = set->tabList[i];
-        while(cur)
+        while( cur )
         {
-            if (set->fnFreeEltFunc)
+            if( set->fnFreeEltFunc )
                 set->fnFreeEltFunc(cur->pData);
             CPLList* psNext = cur->psNext;
             if( bFinalize )
@@ -181,7 +188,7 @@ static void CPLHashSetClearInternal(CPLHashSet* set, int bFinalize)
         }
         set->tabList[i] = NULL;
     }
-    set->bRehash = FALSE;
+    set->bRehash = false;
 }
 
 /************************************************************************/
@@ -197,9 +204,9 @@ static void CPLHashSetClearInternal(CPLHashSet* set, int bFinalize)
  * @param set the hash set
  */
 
-void CPLHashSetDestroy(CPLHashSet* set)
+void CPLHashSetDestroy( CPLHashSet* set )
 {
-    CPLHashSetClearInternal(set, TRUE);
+    CPLHashSetClearInternal(set, true);
     CPLFree(set->tabList);
     CPLListDestroy(set->psRecyclingList);
     CPLFree(set);
@@ -219,10 +226,11 @@ void CPLHashSetDestroy(CPLHashSet* set)
  * @since GDAL 2.1
  */
 
-void CPLHashSetClear(CPLHashSet* set)
+void CPLHashSetClear( CPLHashSet* set )
 {
-    CPLHashSetClearInternal(set, FALSE);
-    set->tabList = (CPLList**) CPLRealloc(set->tabList, sizeof(CPLList*) * 53);
+    CPLHashSetClearInternal(set, false);
+    set->tabList = static_cast<CPLList**>(
+        CPLRealloc(set->tabList, sizeof(CPLList*) * 53));
     set->nIndiceAllocatedSize = 0;
     set->nAllocatedSize = 53;
 #ifdef HASH_DEBUG
@@ -235,7 +243,6 @@ void CPLHashSetClear(CPLHashSet* set)
 /*                       CPLHashSetForeach()                            */
 /************************************************************************/
 
-
 /**
  * Walk through the hash set and runs the provided function on all the
  * elements
@@ -252,19 +259,19 @@ void CPLHashSetClear(CPLHashSet* set)
  * @param user_data the user data provided to the function.
  */
 
-void  CPLHashSetForeach(CPLHashSet* set,
+void CPLHashSetForeach( CPLHashSet* set,
                         CPLHashSetIterEltFunc fnIterFunc,
-                        void* user_data)
+                        void* user_data )
 {
     CPLAssert(set != NULL);
-    if (!fnIterFunc) return;
+    if( !fnIterFunc ) return;
 
-    for(int i=0;i<set->nAllocatedSize;i++)
+    for( int i = 0; i < set->nAllocatedSize; i++ )
     {
         CPLList* cur = set->tabList[i];
-        while(cur)
+        while( cur )
         {
-            if (fnIterFunc(cur->pData, user_data) == FALSE)
+            if( !fnIterFunc(cur->pData, user_data) )
                 return;
 
             cur = cur->psNext;
@@ -276,24 +283,28 @@ void  CPLHashSetForeach(CPLHashSet* set,
 /*                        CPLHashSetRehash()                            */
 /************************************************************************/
 
-static void CPLHashSetRehash(CPLHashSet* set)
+static void CPLHashSetRehash( CPLHashSet* set )
 {
     int nNewAllocatedSize = anPrimes[set->nIndiceAllocatedSize];
-    CPLList** newTabList = (CPLList**) CPLCalloc(sizeof(CPLList*), nNewAllocatedSize);
+    CPLList** newTabList = static_cast<CPLList **>(
+        CPLCalloc(sizeof(CPLList*), nNewAllocatedSize));
 #ifdef HASH_DEBUG
-    CPLDebug("CPLHASH", "hashSet=%p, nSize=%d, nCollisions=%d, fCollisionRate=%.02f",
-             set, set->nSize, set->nCollisions, set->nCollisions * 100.0 / set->nSize);
+    CPLDebug("CPLHASH", "hashSet=%p, nSize=%d, nCollisions=%d, "
+             "fCollisionRate=%.02f",
+             set, set->nSize, set->nCollisions,
+             set->nCollisions * 100.0 / set->nSize);
     set->nCollisions = 0;
 #endif
-    for(int i=0;i<set->nAllocatedSize;i++)
+    for( int i = 0; i < set->nAllocatedSize; i++ )
     {
         CPLList* cur = set->tabList[i];
-        while(cur)
+        while( cur )
         {
-            unsigned long nNewHashVal = set->fnHashFunc(cur->pData) % nNewAllocatedSize;
+            const unsigned long nNewHashVal =
+                set->fnHashFunc(cur->pData) % nNewAllocatedSize;
 #ifdef HASH_DEBUG
-            if (newTabList[nNewHashVal])
-                set->nCollisions ++;
+            if( newTabList[nNewHashVal] )
+                set->nCollisions++;
 #endif
             CPLList* psNext = cur->psNext;
             cur->psNext = newTabList[nNewHashVal];
@@ -304,21 +315,20 @@ static void CPLHashSetRehash(CPLHashSet* set)
     CPLFree(set->tabList);
     set->tabList = newTabList;
     set->nAllocatedSize = nNewAllocatedSize;
-    set->bRehash = FALSE;
+    set->bRehash = false;
 }
 
-
 /************************************************************************/
 /*                        CPLHashSetFindPtr()                           */
 /************************************************************************/
 
-static void** CPLHashSetFindPtr(CPLHashSet* set, const void* elt)
+static void** CPLHashSetFindPtr( CPLHashSet* set, const void* elt )
 {
-    unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize;
+    const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize;
     CPLList* cur = set->tabList[nHashVal];
-    while(cur)
+    while( cur )
     {
-        if (set->fnEqualFunc(cur->pData, elt))
+        if( set->fnEqualFunc(cur->pData, elt) )
             return &cur->pData;
         cur = cur->psNext;
     }
@@ -342,13 +352,13 @@ static void** CPLHashSetFindPtr(CPLHashSet* set, const void* elt)
  * @return TRUE if the element was not already in the hash set
  */
 
-int CPLHashSetInsert(CPLHashSet* set, void* elt)
+int CPLHashSetInsert( CPLHashSet* set, void* elt )
 {
     CPLAssert(set != NULL);
     void** pElt = CPLHashSetFindPtr(set, elt);
-    if (pElt)
+    if( pElt )
     {
-        if (set->fnFreeEltFunc)
+        if( set->fnFreeEltFunc )
             set->fnFreeEltFunc(*pElt);
 
         *pElt = elt;
@@ -356,20 +366,21 @@ int CPLHashSetInsert(CPLHashSet* set, void* elt)
     }
 
     if( set->nSize >= 2 * set->nAllocatedSize / 3 ||
-        (set->bRehash && set->nIndiceAllocatedSize > 0 && set->nSize <= set->nAllocatedSize / 2) )
+        (set->bRehash && set->nIndiceAllocatedSize > 0 &&
+         set->nSize <= set->nAllocatedSize / 2) )
     {
         set->nIndiceAllocatedSize++;
         CPLHashSetRehash(set);
     }
 
-    unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize;
+    const unsigned long nHashVal = set->fnHashFunc(elt) % set->nAllocatedSize;
 #ifdef HASH_DEBUG
-    if (set->tabList[nHashVal])
-        set->nCollisions ++;
+    if( set->tabList[nHashVal] )
+        set->nCollisions++;
 #endif
 
     CPLList* new_elt = CPLHashSetGetNewListElt(set);
-    new_elt->pData = (void*) elt;
+    new_elt->pData = elt;
     new_elt->psNext = set->tabList[nHashVal];
     set->tabList[nHashVal] = new_elt;
     set->nSize++;
@@ -391,14 +402,14 @@ int CPLHashSetInsert(CPLHashSet* set, void* elt)
  * @return the element found in the hash set or NULL
  */
 
-void* CPLHashSetLookup(CPLHashSet* set, const void* elt)
+void* CPLHashSetLookup( CPLHashSet* set, const void* elt )
 {
     CPLAssert(set != NULL);
     void** pElt = CPLHashSetFindPtr(set, elt);
-    if (pElt)
+    if( pElt )
         return *pElt;
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
@@ -406,14 +417,15 @@ void* CPLHashSetLookup(CPLHashSet* set, const void* elt)
 /************************************************************************/
 
 static
-int CPLHashSetRemoveInternal(CPLHashSet* set, const void* elt, int bDeferRehash)
+bool CPLHashSetRemoveInternal( CPLHashSet* set, const void* elt,
+                               bool bDeferRehash )
 {
     CPLAssert(set != NULL);
-    if (set->nIndiceAllocatedSize > 0 && set->nSize <= set->nAllocatedSize / 2)
+    if( set->nIndiceAllocatedSize > 0 && set->nSize <= set->nAllocatedSize / 2 )
     {
         set->nIndiceAllocatedSize--;
         if( bDeferRehash )
-            set->bRehash = TRUE;
+            set->bRehash = true;
         else
             CPLHashSetRehash(set);
     }
@@ -421,31 +433,30 @@ int CPLHashSetRemoveInternal(CPLHashSet* set, const void* elt, int bDeferRehash)
     int nHashVal = static_cast<int>(set->fnHashFunc(elt) % set->nAllocatedSize);
     CPLList* cur = set->tabList[nHashVal];
     CPLList* prev = NULL;
-    while(cur)
+    while( cur )
     {
-        if (set->fnEqualFunc(cur->pData, elt))
+        if( set->fnEqualFunc(cur->pData, elt) )
         {
-            if (prev)
+            if( prev )
                 prev->psNext = cur->psNext;
             else
                 set->tabList[nHashVal] = cur->psNext;
 
-            if (set->fnFreeEltFunc)
+            if( set->fnFreeEltFunc )
                 set->fnFreeEltFunc(cur->pData);
 
             CPLHashSetReturnListElt(set, cur);
 #ifdef HASH_DEBUG
-            if (set->tabList[nHashVal])
-                set->nCollisions --;
+            if( set->tabList[nHashVal] )
+                set->nCollisions--;
 #endif
-
             set->nSize--;
-            return TRUE;
+            return true;
         }
         prev = cur;
         cur = cur->psNext;
     }
-    return FALSE;
+    return false;
 }
 
 /************************************************************************/
@@ -461,9 +472,9 @@ int CPLHashSetRemoveInternal(CPLHashSet* set, const void* elt, int bDeferRehash)
  * @return TRUE if the element was in the hash set
  */
 
-int CPLHashSetRemove(CPLHashSet* set, const void* elt)
+int CPLHashSetRemove( CPLHashSet* set, const void* elt )
 {
-    return CPLHashSetRemoveInternal(set, elt, FALSE);
+    return CPLHashSetRemoveInternal(set, elt, false);
 }
 
 /************************************************************************/
@@ -483,9 +494,9 @@ int CPLHashSetRemove(CPLHashSet* set, const void* elt)
  * @since GDAL 2.1
  */
 
-int CPLHashSetRemoveDeferRehash(CPLHashSet* set, const void* elt)
+int CPLHashSetRemoveDeferRehash( CPLHashSet* set, const void* elt )
 {
-    return CPLHashSetRemoveInternal(set, elt, TRUE);
+    return CPLHashSetRemoveInternal(set, elt, true);
 }
 
 /************************************************************************/
@@ -500,9 +511,10 @@ int CPLHashSetRemoveDeferRehash(CPLHashSet* set, const void* elt)
  * @return the hash value of the pointer
  */
 
-unsigned long CPLHashSetHashPointer(const void* elt)
+unsigned long CPLHashSetHashPointer( const void* elt )
 {
-    return (unsigned long)(GUIntBig) elt;
+    return static_cast<unsigned long>(
+        reinterpret_cast<GUIntptr_t>(const_cast<void *>(elt)));
 }
 
 /************************************************************************/
@@ -518,7 +530,7 @@ unsigned long CPLHashSetHashPointer(const void* elt)
  * @return TRUE if the pointers are equal
  */
 
-int CPLHashSetEqualPointer(const void* elt1, const void* elt2)
+int CPLHashSetEqualPointer( const void* elt1, const void* elt2 )
 {
     return elt1 == elt2;
 }
@@ -535,16 +547,16 @@ int CPLHashSetEqualPointer(const void* elt1, const void* elt2)
  * @return the hash value of the string
  */
 
-unsigned long CPLHashSetHashStr(const void *elt)
+unsigned long CPLHashSetHashStr( const void *elt )
 {
-    unsigned char* pszStr = (unsigned char*)elt;
-    unsigned long hash = 0;
-
-    if (pszStr == NULL)
+    if( elt == NULL )
         return 0;
 
+    const unsigned char* pszStr = static_cast<const unsigned char *>(elt);
+    unsigned long hash = 0;
+
     int c = 0;
-    while ((c = *pszStr++) != '\0')
+    while( (c = *pszStr++) != '\0' )
         hash = c + (hash << 6) + (hash << 16) - hash;
 
     return hash;
@@ -563,16 +575,19 @@ unsigned long CPLHashSetHashStr(const void *elt)
  * @return TRUE if the strings are equal
  */
 
-int CPLHashSetEqualStr(const void* elt1, const void* elt2)
+int CPLHashSetEqualStr( const void* elt1, const void* elt2 )
 {
-    const char* pszStr1 = (const char*)elt1;
-    const char* pszStr2 = (const char*)elt2;
-    if (pszStr1 == NULL && pszStr2 != NULL)
+    const char* pszStr1 = static_cast<const char *>(elt1);
+    const char* pszStr2 = static_cast<const char *>(elt2);
+
+    if( pszStr1 == NULL && pszStr2 != NULL )
         return FALSE;
-    else if (pszStr1 != NULL && pszStr2 == NULL)
+
+    if( pszStr1 != NULL && pszStr2 == NULL )
         return FALSE;
-    else if (pszStr1 == NULL && pszStr2 == NULL)
+
+    if( pszStr1 == NULL && pszStr2 == NULL )
         return TRUE;
-    else
-        return strcmp(pszStr1, pszStr2) == 0;
+
+    return strcmp(pszStr1, pszStr2) == 0;
 }
diff --git a/port/cpl_hash_set.h b/port/cpl_hash_set.h
index 37b68d8..07d307e 100644
--- a/port/cpl_hash_set.h
+++ b/port/cpl_hash_set.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_hash_set.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cpl_hash_set.h 34931 2016-08-05 17:13:05Z rouault $
  *
  * Name:     cpl_hash_set.h
  * Project:  CPL - Common Portability Library
@@ -48,14 +48,19 @@ CPL_C_START
 
 /* Types */
 
+/** Opaque type for a hash set */
 typedef struct _CPLHashSet CPLHashSet;
 
+/** CPLHashSetHashFunc */
 typedef unsigned long (*CPLHashSetHashFunc)(const void* elt);
 
+/** CPLHashSetEqualFunc */
 typedef int          (*CPLHashSetEqualFunc)(const void* elt1, const void* elt2);
 
+/** CPLHashSetFreeEltFunc */
 typedef void         (*CPLHashSetFreeEltFunc)(void* elt);
 
+/** CPLHashSetIterEltFunc */
 typedef int          (*CPLHashSetIterEltFunc)(void* elt, void* user_data);
 
 /* Functions */
diff --git a/port/cpl_http.cpp b/port/cpl_http.cpp
index 10bf7e9..31f1d56 100644
--- a/port/cpl_http.cpp
+++ b/port/cpl_http.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_http.cpp 36551 2016-11-28 23:01:13Z rouault $
  *
  * Project:  libcurl based HTTP client
  * Purpose:  libcurl based HTTP client
@@ -28,28 +27,35 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "cpl_http.h"
+
+#include <cstddef>
+#include <cstring>
+
 #include <map>
+#include <string>
+
 #include "cpl_http.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
 
 #ifdef HAVE_CURL
 #  include <curl/curl.h>
-
-void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions);
-
-/* CURLINFO_RESPONSE_CODE was known as CURLINFO_HTTP_CODE in libcurl 7.10.7 and earlier */
+// CURLINFO_RESPONSE_CODE was known as CURLINFO_HTTP_CODE in libcurl 7.10.7 and
+// earlier.
 #if LIBCURL_VERSION_NUM < 0x070a07
 #define CURLINFO_RESPONSE_CODE CURLINFO_HTTP_CODE
 #endif
 
 #endif
 
-CPL_CVSID("$Id: cpl_http.cpp 36551 2016-11-28 23:01:13Z rouault $");
+CPL_CVSID("$Id: cpl_http.cpp 37970 2017-04-12 11:07:46Z rouault $");
 
 // list of named persistent http sessions
 
 #ifdef HAVE_CURL
-static std::map<CPLString,CURL*>* poSessionMap = NULL;
+static std::map<CPLString, CURL*>* poSessionMap = NULL;
 static CPLMutex *hSessionMapMutex = NULL;
 #endif
 
@@ -61,19 +67,28 @@ static CPLMutex *hSessionMapMutex = NULL;
 /************************************************************************/
 
 #ifdef HAVE_CURL
+
+typedef struct
+{
+    CPLHTTPResult* psResult;
+    int            nMaxFileSize;
+} CPLHTTPResultWithLimit;
+
 static size_t
 CPLWriteFct(void *buffer, size_t size, size_t nmemb, void *reqInfo)
 
 {
-    CPLHTTPResult *psResult = (CPLHTTPResult *) reqInfo;
+    CPLHTTPResultWithLimit *psResultWithLimit =
+        static_cast<CPLHTTPResultWithLimit *>(reqInfo);
+    CPLHTTPResult* psResult = psResultWithLimit->psResult;
 
     int nBytesToWrite = static_cast<int>(nmemb)*static_cast<int>(size);
     int nNewSize = psResult->nDataLen + nBytesToWrite + 1;
     if( nNewSize > psResult->nDataAlloc )
     {
-        psResult->nDataAlloc = (int) (nNewSize * 1.25 + 100);
-        GByte* pabyNewData = (GByte *) VSIRealloc(psResult->pabyData,
-                                                  psResult->nDataAlloc);
+        psResult->nDataAlloc = static_cast<int>(nNewSize * 1.25 + 100);
+        GByte* pabyNewData = static_cast<GByte *>(
+            VSIRealloc(psResult->pabyData, psResult->nDataAlloc));
         if( pabyNewData == NULL )
         {
             VSIFree(psResult->pabyData);
@@ -91,21 +106,32 @@ CPLWriteFct(void *buffer, size_t size, size_t nmemb, void *reqInfo)
     psResult->nDataLen += nBytesToWrite;
     psResult->pabyData[psResult->nDataLen] = 0;
 
+    if( psResultWithLimit->nMaxFileSize > 0 &&
+        psResult->nDataLen > psResultWithLimit->nMaxFileSize )
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Maximum file size reached");
+        return 0;
+    }
+
     return nmemb;
 }
 
 /************************************************************************/
 /*                           CPLHdrWriteFct()                           */
 /************************************************************************/
-static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqInfo)
+static size_t CPLHdrWriteFct( void *buffer, size_t size, size_t nmemb,
+                              void *reqInfo )
 {
-    CPLHTTPResult *psResult = (CPLHTTPResult *) reqInfo;
-    // copy the buffer to a char* and initialize with zeros (zero terminate as well)
-    char* pszHdr = (char*)CPLCalloc(nmemb + 1, size);
-    CPLPrintString(pszHdr, (char *)buffer, static_cast<int>(nmemb) * static_cast<int>(size));
+    CPLHTTPResult *psResult = static_cast<CPLHTTPResult *>(reqInfo);
+    // Copy the buffer to a char* and initialize with zeros (zero
+    // terminate as well).
+    char* pszHdr = static_cast<char *>(CPLCalloc(nmemb + 1, size));
+    CPLPrintString(pszHdr, static_cast<char *>(buffer),
+                   static_cast<int>(nmemb) * static_cast<int>(size));
     char *pszKey = NULL;
     const char *pszValue = CPLParseNameValue(pszHdr, &pszKey );
-    psResult->papszHeaders = CSLSetNameValue(psResult->papszHeaders, pszKey, pszValue);
+    psResult->papszHeaders =
+        CSLSetNameValue(psResult->papszHeaders, pszKey, pszValue);
     CPLFree(pszHdr);
     CPLFree(pszKey);
     return nmemb;
@@ -114,6 +140,49 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
 #endif /* def HAVE_CURL */
 
 /************************************************************************/
+/*                       CPLHTTPGetOptionsFromEnv()                     */
+/************************************************************************/
+
+typedef struct
+{
+    const char* pszEnvVar;
+    const char* pszOptionName;
+} TupleEnvVarOptionName;
+
+static const TupleEnvVarOptionName asAssocEnvVarOptionName[] =
+{
+    { "GDAL_HTTP_CONNECTTIMEOUT", "CONNECTTIMEOUT" },
+    { "GDAL_HTTP_TIMEOUT", "TIMEOUT" },
+    { "GDAL_HTTP_LOW_SPEED_TIME", "LOW_SPEED_TIME" },
+    { "GDAL_HTTP_LOW_SPEED_LIMIT", "LOW_SPEED_LIMIT" },
+    { "GDAL_HTTP_PROXY", "PROXY" },
+    { "GDAL_HTTP_PROXYUSERPWD", "PROXYUSERPWD" },
+    { "GDAL_PROXY_AUTH", "PROXYAUTH" },
+    { "GDAL_HTTP_NETRC", "NETRC" },
+    { "GDAL_HTTP_MAX_RETRY", "MAX_RETRY" },
+    { "GDAL_HTTP_RETRY_DELAY", "RETRY_DELAY" },
+    { "CURL_CA_BUNDLE", "CAINFO" },
+    { "SSL_CERT_FILE", "CAINFO" },
+    { "GDAL_HTTP_HEADER_FILE", "HEADER_FILE" }
+};
+
+char** CPLHTTPGetOptionsFromEnv()
+{
+    char** papszOptions = NULL;
+    for( size_t i = 0; i < CPL_ARRAYSIZE(asAssocEnvVarOptionName); ++i )
+    {
+        const char* pszVal = CPLGetConfigOption(
+            asAssocEnvVarOptionName[i].pszEnvVar, NULL);
+        if( pszVal != NULL )
+        {
+            papszOptions = CSLSetNameValue(papszOptions,
+                asAssocEnvVarOptionName[i].pszOptionName, pszVal);
+        }
+    }
+    return papszOptions;
+}
+
+/************************************************************************/
 /*                           CPLHTTPFetch()                             */
 /************************************************************************/
 
@@ -124,6 +193,9 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
  * @param papszOptions option list as a NULL-terminated array of strings. May be NULL.
  *                     The following options are handled :
  * <ul>
+ * <li>CONNECTTIMEOUT=val, where val is in seconds (possibly with decimals).
+ *     This is the maximum delay for the connection to be established before
+ *     being aborted (GDAL >= 2.2).</li>
  * <li>TIMEOUT=val, where val is in seconds. This is the maximum delay for the whole
  *     request to complete before being aborted.</li>
  * <li>LOW_SPEED_TIME=val, where val is in seconds. This is the maximum time where the
@@ -132,22 +204,25 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
  * <li>LOW_SPEED_LIMIT=val, where val is in bytes/second. See LOW_SPEED_TIME. Has only
  *     effect if LOW_SPEED_TIME is specified too. (GDAL >= 2.1)</li>
  * <li>HEADERS=val, where val is an extra header to use when getting a web page.
- *                  For example "Accept: application/x-ogcwkt"
- * <li>HTTPAUTH=[BASIC/NTLM/GSSNEGOTIATE/ANY] to specify an authentication scheme to use.
- * <li>USERPWD=userid:password to specify a user and password for authentication
+ *                  For example "Accept: application/x-ogcwkt"</li>
+ * <li>HEADER_FILE=filename: filename of a text file with "key: value" headers.
+ *     (GDAL >= 2.2)</li>
+ * <li>HTTPAUTH=[BASIC/NTLM/GSSNEGOTIATE/ANY] to specify an authentication scheme to use.</li>
+ * <li>USERPWD=userid:password to specify a user and password for authentication</li>
  * <li>POSTFIELDS=val, where val is a nul-terminated string to be passed to the server
- *                     with a POST request.
+ *                     with a POST request.</li>
  * <li>PROXY=val, to make requests go through a proxy server, where val is of the
- *                form proxy.server.com:port_number
- * <li>PROXYUSERPWD=val, where val is of the form username:password
- * <li>PROXYAUTH=[BASIC/NTLM/DIGEST/ANY] to specify an proxy authentication scheme to use.
- * <li>NETRC=[YES/NO] to enable or disable use of $HOME/.netrc, default YES.
- * <li>CUSTOMREQUEST=val, where val is GET, PUT, POST, DELETE, etc.. (GDAL >= 1.9.0)
- * <li>COOKIE=val, where val is formatted as COOKIE1=VALUE1; COOKIE2=VALUE2; ...
+ *                form proxy.server.com:port_number</li>
+ * <li>PROXYUSERPWD=val, where val is of the form username:password</li>
+ * <li>PROXYAUTH=[BASIC/NTLM/DIGEST/ANY] to specify an proxy authentication scheme to use.</li>
+ * <li>NETRC=[YES/NO] to enable or disable use of $HOME/.netrc, default YES.</li>
+ * <li>CUSTOMREQUEST=val, where val is GET, PUT, POST, DELETE, etc.. (GDAL >= 1.9.0)</li>
+ * <li>COOKIE=val, where val is formatted as COOKIE1=VALUE1; COOKIE2=VALUE2; ...</li>
  * <li>MAX_RETRY=val, where val is the maximum number of retry attempts if a 503 or
- *               504 HTTP error occurs. Default is 0. (GDAL >= 2.0)
+ *               504 HTTP error occurs. Default is 0. (GDAL >= 2.0)</li>
  * <li>RETRY_DELAY=val, where val is the number of seconds between retry attempts.
- *                 Default is 30. (GDAL >= 2.0)
+ *                 Default is 30. (GDAL >= 2.0)</li>
+ * <li>MAX_FILE_SIZE=val, where val is a number of bytes (GDAL >= 2.2)</li>
  * <li>CAINFO=/path/to/bundle.crt. This is path to Certificate Authority (CA)
  *     bundle file. By default, it will be looked in a system location. If
  *     the CAINFO options is not defined, GDAL will also look if the CURL_CA_BUNDLE
@@ -155,12 +230,15 @@ static size_t CPLHdrWriteFct(void *buffer, size_t size, size_t nmemb, void *reqI
  *     fallback to the SSL_CERT_FILE environment variable. (GDAL >= 2.1.3)</li>
  * </ul>
  *
- * Alternatively, if not defined in the papszOptions arguments, the TIMEOUT,
+ * Alternatively, if not defined in the papszOptions arguments, the
+ * CONNECTTIMEOUT, TIMEOUT,
  * LOW_SPEED_TIME, LOW_SPEED_LIMIT, PROXY, PROXYUSERPWD, PROXYAUTH, NETRC,
- * MAX_RETRY and RETRY_DELAY values are searched in the configuration
- * options named GDAL_HTTP_TIMEOUT, GDAL_HTTP_LOW_SPEED_TIME, GDAL_HTTP_LOW_SPEED_LIMIT,
+ * MAX_RETRY and RETRY_DELAY, HEADER_FILE values are searched in the configuration
+ * options named GDAL_HTTP_CONNECTTIMEOUT, GDAL_HTTP_TIMEOUT,
+ * GDAL_HTTP_LOW_SPEED_TIME, GDAL_HTTP_LOW_SPEED_LIMIT,
  * GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD, GDAL_PROXY_AUTH,
- * GDAL_HTTP_NETRC, GDAL_HTTP_MAX_RETRY and GDAL_HTTP_RETRY_DELAY.
+ * GDAL_HTTP_NETRC, GDAL_HTTP_MAX_RETRY, GDAL_HTTP_RETRY_DELAY,
+ * GDAL_HTTP_HEADER_FILE.
  *
  * @return a CPLHTTPResult* structure that must be freed by
  * CPLHTTPDestroyResult(), or NULL if libcurl support is disabled
@@ -169,51 +247,62 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 
 {
     if( STARTS_WITH(pszURL, "/vsimem/") &&
-        /* Disabled by default for potential security issues */
-        CSLTestBoolean(CPLGetConfigOption("CPL_CURL_ENABLE_VSIMEM", "FALSE")) )
+        // Disabled by default for potential security issues.
+        CPLTestBool(CPLGetConfigOption("CPL_CURL_ENABLE_VSIMEM", "FALSE")) )
     {
         CPLString osURL(pszURL);
-        const char* pszCustomRequest = CSLFetchNameValue( papszOptions, "CUSTOMREQUEST" );
+        const char* pszCustomRequest =
+            CSLFetchNameValue( papszOptions, "CUSTOMREQUEST" );
         if( pszCustomRequest != NULL )
         {
             osURL += "&CUSTOMREQUEST=";
             osURL += pszCustomRequest;
         }
         const char* pszPost = CSLFetchNameValue( papszOptions, "POSTFIELDS" );
-        if( pszPost != NULL ) /* Hack: we append post content to filename */
+        if( pszPost != NULL ) // Hack: We append post content to filename.
         {
             osURL += "&POSTFIELDS=";
             osURL += pszPost;
         }
         vsi_l_offset nLength = 0;
-        CPLHTTPResult* psResult = (CPLHTTPResult* )CPLCalloc(1, sizeof(CPLHTTPResult));
+        CPLHTTPResult* psResult =
+            static_cast<CPLHTTPResult *>(CPLCalloc(1, sizeof(CPLHTTPResult)));
         GByte* pabyData = VSIGetMemFileBuffer( osURL, &nLength, FALSE );
         if( pabyData == NULL )
         {
             CPLDebug("HTTP", "Cannot find %s", osURL.c_str());
             psResult->nStatus = 1;
-            psResult->pszErrBuf = CPLStrdup(CPLSPrintf("HTTP error code : %d", 404));
+            psResult->pszErrBuf =
+                CPLStrdup(CPLSPrintf("HTTP error code : %d", 404));
             CPLError( CE_Failure, CPLE_AppDefined, "%s", psResult->pszErrBuf );
         }
         else if( nLength != 0 )
         {
             psResult->nDataLen = static_cast<int>(nLength);
-            psResult->pabyData = (GByte*) CPLMalloc((size_t)nLength + 1);
-            memcpy(psResult->pabyData, pabyData, (size_t)nLength);
-            psResult->pabyData[(size_t)nLength] = 0;
+            psResult->pabyData = static_cast<GByte *>(
+                CPLMalloc(static_cast<size_t>(nLength) + 1));
+            memcpy(psResult->pabyData, pabyData, static_cast<size_t>(nLength));
+            psResult->pabyData[static_cast<size_t>(nLength)] = 0;
         }
 
         if( psResult->pabyData != NULL &&
-            STARTS_WITH((const char*)psResult->pabyData, "Content-Type: ") )        {
-            const char* pszContentType = (const char*)psResult->pabyData + strlen("Content-type: ");
+            STARTS_WITH(reinterpret_cast<char *>(psResult->pabyData),
+                        "Content-Type: ") )
+        {
+            const char* pszContentType =
+                reinterpret_cast<char *>(psResult->pabyData) +
+                strlen("Content-type: ");
             const char* pszEOL = strchr(pszContentType, '\r');
             if( pszEOL )
                 pszEOL = strchr(pszContentType, '\n');
             if( pszEOL )
             {
                 size_t nContentLength = pszEOL - pszContentType;
-                psResult->pszContentType = (char*)CPLMalloc(nContentLength + 1);
-                memcpy(psResult->pszContentType, pszContentType, nContentLength);
+                psResult->pszContentType =
+                    static_cast<char *>(CPLMalloc(nContentLength + 1));
+                memcpy(psResult->pszContentType,
+                       pszContentType,
+                       nContentLength);
                 psResult->pszContentType[nContentLength] = 0;
             }
         }
@@ -226,7 +315,8 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
     (void) pszURL;
 
     CPLError( CE_Failure, CPLE_NotSupported,
-              "GDAL/OGR not compiled with libcurl support, remote requests not supported." );
+              "GDAL/OGR not compiled with libcurl support, "
+              "remote requests not supported." );
     return NULL;
 #else
 
@@ -243,14 +333,15 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
     CURL *http_handle = NULL;
 
     const char *pszPersistent = CSLFetchNameValue( papszOptions, "PERSISTENT" );
-    const char *pszClosePersistent = CSLFetchNameValue( papszOptions, "CLOSE_PERSISTENT" );
-    if (pszPersistent)
+    const char *pszClosePersistent =
+        CSLFetchNameValue( papszOptions, "CLOSE_PERSISTENT" );
+    if( pszPersistent )
     {
         CPLString osSessionName = pszPersistent;
         CPLMutexHolder oHolder( &hSessionMapMutex );
 
         if( poSessionMap == NULL )
-            poSessionMap = new std::map<CPLString,CURL*>;
+            poSessionMap = new std::map<CPLString, CURL *>;
         if( poSessionMap->count( osSessionName ) == 0 )
         {
             (*poSessionMap)[osSessionName] = curl_easy_init();
@@ -261,21 +352,22 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
         http_handle = (*poSessionMap)[osSessionName];
     }
 /* -------------------------------------------------------------------- */
-/*      Are we requested to close a persistent named session?          */
+/*      Are we requested to close a persistent named session?           */
 /* -------------------------------------------------------------------- */
-    else if (pszClosePersistent)
+    else if( pszClosePersistent )
     {
         CPLString osSessionName = pszClosePersistent;
         CPLMutexHolder oHolder( &hSessionMapMutex );
 
         if( poSessionMap )
         {
-            std::map<CPLString,CURL*>::iterator oIter = poSessionMap->find( osSessionName );
+            std::map<CPLString, CURL *>::iterator oIter =
+                poSessionMap->find( osSessionName );
             if( oIter != poSessionMap->end() )
             {
                 curl_easy_cleanup(oIter->second);
                 poSessionMap->erase(oIter);
-                if( poSessionMap->size() == 0 )
+                if( poSessionMap->empty() )
                 {
                     delete poSessionMap;
                     poSessionMap = NULL;
@@ -285,8 +377,9 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
             }
             else
             {
-                CPLDebug( "HTTP", "Could not find persistent session named '%s'.",
-                        osSessionName.c_str() );
+                CPLDebug(
+                    "HTTP", "Could not find persistent session named '%s'.",
+                    osSessionName.c_str() );
             }
         }
 
@@ -298,19 +391,18 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Setup the request.                                              */
 /* -------------------------------------------------------------------- */
-    char szCurlErrBuf[CURL_ERROR_SIZE+1];
-    CPLHTTPResult *psResult;
-    struct curl_slist *headers=NULL;
+    char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
 
     const char* pszArobase = strchr(pszURL, '@');
     const char* pszSlash = strchr(pszURL, '/');
     const char* pszColon = (pszSlash) ? strchr(pszSlash, ':') : NULL;
-    if (pszArobase != NULL && pszColon != NULL && pszArobase - pszColon > 0)
+    if( pszArobase != NULL && pszColon != NULL && pszArobase - pszColon > 0 )
     {
         /* http://user:password@www.example.com */
         char* pszSanitizedURL = CPLStrdup(pszURL);
         pszSanitizedURL[pszColon-pszURL] = 0;
-        CPLDebug( "HTTP", "Fetch(%s:#password#%s)", pszSanitizedURL, pszArobase );
+        CPLDebug( "HTTP", "Fetch(%s:#password#%s)",
+                  pszSanitizedURL, pszArobase );
         CPLFree(pszSanitizedURL);
     }
     else
@@ -318,39 +410,56 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
         CPLDebug( "HTTP", "Fetch(%s)", pszURL );
     }
 
-    psResult = (CPLHTTPResult *) CPLCalloc(1,sizeof(CPLHTTPResult));
+    CPLHTTPResult *psResult =
+        static_cast<CPLHTTPResult *>(CPLCalloc(1, sizeof(CPLHTTPResult)));
 
     curl_easy_setopt(http_handle, CURLOPT_URL, pszURL );
 
-    CPLHTTPSetOptions(http_handle, papszOptions);
+    struct curl_slist* headers= reinterpret_cast<struct curl_slist*>(
+                            CPLHTTPSetOptions(http_handle, papszOptions));
 
-    // turn off SSL verification, accept all servers with ssl
-    curl_easy_setopt(http_handle, CURLOPT_SSL_VERIFYPEER, FALSE);
-
-    /* Set Headers.*/
+    // Set Headers.
     const char *pszHeaders = CSLFetchNameValue( papszOptions, "HEADERS" );
     if( pszHeaders != NULL ) {
         CPLDebug ("HTTP", "These HTTP headers were set: %s", pszHeaders);
-        headers = curl_slist_append(headers, pszHeaders);
-        curl_easy_setopt(http_handle, CURLOPT_HTTPHEADER, headers);
+        char** papszTokensHeaders = CSLTokenizeString2(pszHeaders, "\r\n", 0);
+        for( int i=0; papszTokensHeaders[i] != NULL; ++i )
+            headers = curl_slist_append(headers, papszTokensHeaders[i]);
+        CSLDestroy(papszTokensHeaders);
     }
 
-    // are we making a head request
+    if( headers != NULL )
+        curl_easy_setopt(http_handle, CURLOPT_HTTPHEADER, headers);
+
+    // Are we making a head request.
     const char* pszNoBody = NULL;
-    if ((pszNoBody = CSLFetchNameValue( papszOptions, "NO_BODY" )) != NULL)
+    if( (pszNoBody = CSLFetchNameValue( papszOptions, "NO_BODY" )) != NULL )
     {
-        if (CSLTestBoolean(pszNoBody))
+        if( CPLTestBool(pszNoBody) )
         {
             CPLDebug ("HTTP", "HEAD Request: %s", pszURL);
             curl_easy_setopt(http_handle, CURLOPT_NOBODY, 1L);
         }
     }
 
-    // capture response headers
+    // Capture response headers.
     curl_easy_setopt(http_handle, CURLOPT_HEADERDATA, psResult);
     curl_easy_setopt(http_handle, CURLOPT_HEADERFUNCTION, CPLHdrWriteFct);
 
-    curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, psResult );
+    CPLHTTPResultWithLimit sResultWithLimit;
+    sResultWithLimit.psResult = psResult;
+    sResultWithLimit.nMaxFileSize = 0;
+    const char* pszMaxFileSize = CSLFetchNameValue(papszOptions,
+                                                   "MAX_FILE_SIZE");
+    if( pszMaxFileSize != NULL )
+    {
+        sResultWithLimit.nMaxFileSize = atoi(pszMaxFileSize);
+        // Only useful if size is returned by server before actual download.
+        curl_easy_setopt(http_handle, CURLOPT_MAXFILESIZE,
+                         sResultWithLimit.nMaxFileSize);
+    }
+
+    curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, &sResultWithLimit );
     curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, CPLWriteFct );
 
     szCurlErrBuf[0] = '\0';
@@ -359,13 +468,14 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 
     static bool bHasCheckVersion = false;
     static bool bSupportGZip = false;
-    if (!bHasCheckVersion)
+    if( !bHasCheckVersion )
     {
         bSupportGZip = strstr(curl_version(), "zlib/") != NULL;
         bHasCheckVersion = true;
     }
-    int bGZipRequested = false;
-    if (bSupportGZip && CSLTestBoolean(CPLGetConfigOption("CPL_CURL_GZIP", "YES")))
+    bool bGZipRequested = false;
+    if( bSupportGZip &&
+        CPLTestBool(CPLGetConfigOption("CPL_CURL_GZIP", "YES")) )
     {
         bGZipRequested = true;
         curl_easy_setopt(http_handle, CURLOPT_ENCODING, "gzip");
@@ -375,7 +485,8 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 /*      If 502, 503 or 504 status code retry this HTTP call until max   */
 /*      retry has been reached                                          */
 /* -------------------------------------------------------------------- */
-    const char *pszRetryDelay = CSLFetchNameValue( papszOptions, "RETRY_DELAY" );
+    const char *pszRetryDelay =
+        CSLFetchNameValue( papszOptions, "RETRY_DELAY" );
     if( pszRetryDelay == NULL )
         pszRetryDelay = CPLGetConfigOption( "GDAL_HTTP_RETRY_DELAY", "30" );
     const char *pszMaxRetries = CSLFetchNameValue( papszOptions, "MAX_RETRY" );
@@ -393,7 +504,7 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 /* -------------------------------------------------------------------- */
 /*      Execute the request, waiting for results.                       */
 /* -------------------------------------------------------------------- */
-        psResult->nStatus = (int) curl_easy_perform( http_handle );
+        psResult->nStatus = static_cast<int>(curl_easy_perform(http_handle));
 
 /* -------------------------------------------------------------------- */
 /*      Fetch content-type if possible.                                 */
@@ -411,31 +522,36 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
         {
             bool bSkipError = false;
 
-            /* Some servers such as http://115.113.193.14/cgi-bin/world/qgis_mapserv.fcgi?VERSION=1.1.1&SERVICE=WMS&REQUEST=GetCapabilities */
-            /* invalidly return Content-Length as the uncompressed size, with makes curl to wait for more data */
-            /* and time-out finally. If we got the expected data size, then we don't emit an error */
-            /* but turn off GZip requests */
-            if (bGZipRequested &&
+            // Some servers such as
+            // http://115.113.193.14/cgi-bin/world/qgis_mapserv.fcgi?VERSION=1.1.1&SERVICE=WMS&REQUEST=GetCapabilities
+            // invalidly return Content-Length as the uncompressed size, with
+            // makes curl to wait for more data and time-out finally. If we got
+            // the expected data size, then we don't emit an error but turn off
+            // GZip requests.
+            if( bGZipRequested &&
                 strstr(szCurlErrBuf, "transfer closed with") &&
-                strstr(szCurlErrBuf, "bytes remaining to read"))
+                strstr(szCurlErrBuf, "bytes remaining to read") )
             {
                 const char* pszContentLength =
                     CSLFetchNameValue(psResult->papszHeaders, "Content-Length");
-                if (pszContentLength && psResult->nDataLen != 0 &&
-                    atoi(pszContentLength) == psResult->nDataLen)
+                if( pszContentLength && psResult->nDataLen != 0 &&
+                    atoi(pszContentLength) == psResult->nDataLen )
                 {
-                    const char* pszCurlGZIPOption = CPLGetConfigOption("CPL_CURL_GZIP", NULL);
-                    if (pszCurlGZIPOption == NULL)
+                    const char* pszCurlGZIPOption =
+                        CPLGetConfigOption("CPL_CURL_GZIP", NULL);
+                    if( pszCurlGZIPOption == NULL )
                     {
                         CPLSetConfigOption("CPL_CURL_GZIP", "NO");
-                        CPLDebug("HTTP", "Disabling CPL_CURL_GZIP, because %s doesn't support it properly",
+                        CPLDebug("HTTP",
+                                 "Disabling CPL_CURL_GZIP, "
+                                 "because %s doesn't support it properly",
                                  pszURL);
                     }
                     psResult->nStatus = 0;
                     bSkipError = true;
                 }
             }
-            if (!bSkipError)
+            if( !bSkipError )
             {
                 psResult->pszErrBuf = CPLStrdup(szCurlErrBuf);
                 CPLError( CE_Failure, CPLE_AppDefined,
@@ -444,19 +560,24 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
         }
         else
         {
-            /* HTTP errors do not trigger curl errors. But we need to */
-            /* propagate them to the caller though */
+            // HTTP errors do not trigger curl errors. But we need to
+            // propagate them to the caller though.
             long response_code = 0;
-            curl_easy_getinfo(http_handle, CURLINFO_RESPONSE_CODE, &response_code);
+            curl_easy_getinfo(http_handle, CURLINFO_RESPONSE_CODE,
+                              &response_code);
 
-            if (response_code >= 400 && response_code < 600)
+            if( response_code >= 400 && response_code < 600 )
             {
-                /* If HTTP 502, 503 or 504 gateway timeout error retry after a pause */
-                if ((response_code >= 502 && response_code <= 504) && nRetryCount < nMaxRetries)
+                // If HTTP 502, 503 or 504 gateway timeout error retry after a
+                // pause.
+                if( (response_code >= 502 && response_code <= 504) &&
+                    nRetryCount < nMaxRetries )
                 {
                     CPLError(CE_Warning, CPLE_AppDefined,
-                             "HTTP error code: %d - %s. Retrying again in %d secs",
-                             (int)response_code, pszURL, nRetryDelaySecs);
+                             "HTTP error code: %d - %s. "
+                             "Retrying again in %d secs",
+                             static_cast<int>(response_code), pszURL,
+                             nRetryDelaySecs);
                     CPLSleep(nRetryDelaySecs);
                     nRetryCount++;
 
@@ -473,15 +594,18 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
                 }
                 else
                 {
-                    psResult->pszErrBuf = CPLStrdup(CPLSPrintf("HTTP error code : %d", (int)response_code));
-                    CPLError( CE_Failure, CPLE_AppDefined, "%s", psResult->pszErrBuf );
+                    psResult->pszErrBuf =
+                        CPLStrdup(CPLSPrintf("HTTP error code : %d",
+                                             static_cast<int>(response_code)));
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "%s", psResult->pszErrBuf);
                 }
             }
         }
     }
-    while (bRequestRetry);
+    while( bRequestRetry );
 
-    if (!pszPersistent)
+    if( !pszPersistent )
         curl_easy_cleanup( http_handle );
 
     curl_slist_free_all(headers);
@@ -495,14 +619,18 @@ CPLHTTPResult *CPLHTTPFetch( const char *pszURL, char **papszOptions )
 /*                         CPLHTTPSetOptions()                          */
 /************************************************************************/
 
-void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
+void* CPLHTTPSetOptions(void *pcurl, const char * const* papszOptions)
 {
-    if (CSLTestBoolean(CPLGetConfigOption("CPL_CURL_VERBOSE", "NO")))
+    CURL *http_handle = reinterpret_cast<CURL *>(pcurl);
+
+    if( CPLTestBool(CPLGetConfigOption("CPL_CURL_VERBOSE", "NO")) )
         curl_easy_setopt(http_handle, CURLOPT_VERBOSE, 1);
 
-    const char *pszHttpVersion = CSLFetchNameValue( papszOptions, "HTTP_VERSION");
+    const char *pszHttpVersion =
+        CSLFetchNameValue( papszOptions, "HTTP_VERSION");
     if( pszHttpVersion && strcmp(pszHttpVersion, "1.0") == 0 )
-        curl_easy_setopt(http_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 );
+        curl_easy_setopt(http_handle, CURLOPT_HTTP_VERSION,
+                         CURL_HTTP_VERSION_1_0);
 
     /* Support control over HTTPAUTH */
     const char *pszHttpAuth = CSLFetchNameValue( papszOptions, "HTTPAUTH" );
@@ -513,14 +641,14 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
 
     /* CURLOPT_HTTPAUTH is defined in curl 7.11.0 or newer */
 #if LIBCURL_VERSION_NUM >= 0x70B00
-    else if( EQUAL(pszHttpAuth,"BASIC") )
+    else if( EQUAL(pszHttpAuth, "BASIC") )
         curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC );
-    else if( EQUAL(pszHttpAuth,"NTLM") )
+    else if( EQUAL(pszHttpAuth, "NTLM") )
         curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, CURLAUTH_NTLM );
-    else if( EQUAL(pszHttpAuth,"ANY") )
+    else if( EQUAL(pszHttpAuth, "ANY") )
         curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY );
 #ifdef CURLAUTH_GSSNEGOTIATE
-    else if( EQUAL(pszHttpAuth,"NEGOTIATE") )
+    else if( EQUAL(pszHttpAuth, "NEGOTIATE") )
         curl_easy_setopt(http_handle, CURLOPT_HTTPAUTH, CURLAUTH_GSSNEGOTIATE );
 #endif
     else
@@ -537,48 +665,51 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
     }
 #endif
 
-    /* Support use of .netrc - default enabled */
+    // Support use of .netrc - default enabled.
     const char *pszHttpNetrc = CSLFetchNameValue( papszOptions, "NETRC" );
     if( pszHttpNetrc == NULL )
         pszHttpNetrc = CPLGetConfigOption( "GDAL_HTTP_NETRC", "YES" );
-    if( pszHttpNetrc == NULL || CSLTestBoolean(pszHttpNetrc) )
+    if( pszHttpNetrc == NULL || CPLTestBool(pszHttpNetrc) )
         curl_easy_setopt(http_handle, CURLOPT_NETRC, 1L);
 
-    /* Support setting userid:password */
+    // Support setting userid:password.
     const char *pszUserPwd = CSLFetchNameValue( papszOptions, "USERPWD" );
-    if (pszUserPwd == NULL)
+    if( pszUserPwd == NULL )
         pszUserPwd = CPLGetConfigOption("GDAL_HTTP_USERPWD", NULL);
     if( pszUserPwd != NULL )
         curl_easy_setopt(http_handle, CURLOPT_USERPWD, pszUserPwd );
 
-    /* Set Proxy parameters */
+    // Set Proxy parameters.
     const char* pszProxy = CSLFetchNameValue( papszOptions, "PROXY" );
-    if (pszProxy == NULL)
+    if( pszProxy == NULL )
         pszProxy = CPLGetConfigOption("GDAL_HTTP_PROXY", NULL);
-    if (pszProxy)
-        curl_easy_setopt(http_handle,CURLOPT_PROXY,pszProxy);
+    if( pszProxy )
+        curl_easy_setopt(http_handle, CURLOPT_PROXY, pszProxy);
 
-    const char* pszProxyUserPwd = CSLFetchNameValue( papszOptions, "PROXYUSERPWD" );
-    if (pszProxyUserPwd == NULL)
+    const char* pszProxyUserPwd =
+        CSLFetchNameValue( papszOptions, "PROXYUSERPWD" );
+    if( pszProxyUserPwd == NULL )
         pszProxyUserPwd = CPLGetConfigOption("GDAL_HTTP_PROXYUSERPWD", NULL);
-    if (pszProxyUserPwd)
-        curl_easy_setopt(http_handle,CURLOPT_PROXYUSERPWD,pszProxyUserPwd);
+    if( pszProxyUserPwd )
+        curl_easy_setopt(http_handle, CURLOPT_PROXYUSERPWD, pszProxyUserPwd);
 
-    /* Support control over PROXYAUTH */
+    // Support control over PROXYAUTH.
     const char *pszProxyAuth = CSLFetchNameValue( papszOptions, "PROXYAUTH" );
     if( pszProxyAuth == NULL )
         pszProxyAuth = CPLGetConfigOption( "GDAL_PROXY_AUTH", NULL );
     if( pszProxyAuth == NULL )
-        /* do nothing */;
-    /* CURLOPT_PROXYAUTH is defined in curl 7.11.0 or newer */
+    {
+        // Do nothing.
+    }
+    // CURLOPT_PROXYAUTH is defined in curl 7.11.0 or newer.
 #if LIBCURL_VERSION_NUM >= 0x70B00
-    else if( EQUAL(pszProxyAuth,"BASIC") )
+    else if( EQUAL(pszProxyAuth, "BASIC") )
         curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH, CURLAUTH_BASIC );
-    else if( EQUAL(pszProxyAuth,"NTLM") )
+    else if( EQUAL(pszProxyAuth, "NTLM") )
         curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM );
-    else if( EQUAL(pszProxyAuth,"DIGEST") )
+    else if( EQUAL(pszProxyAuth, "DIGEST") )
         curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST );
-    else if( EQUAL(pszProxyAuth,"ANY") )
+    else if( EQUAL(pszProxyAuth, "ANY") )
         curl_easy_setopt(http_handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY );
     else
     {
@@ -594,36 +725,52 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
     }
 #endif
 
-    /* Enable following redirections.  Requires libcurl 7.10.1 at least */
+    // Enable following redirections.  Requires libcurl 7.10.1 at least.
     curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1 );
     curl_easy_setopt(http_handle, CURLOPT_MAXREDIRS, 10 );
-
-    /* Set timeout.*/
+    curl_easy_setopt(http_handle, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL );
+
+    // Set connect timeout.
+    const char *pszConnectTimeout =
+        CSLFetchNameValue( papszOptions, "CONNECTTIMEOUT" );
+    if( pszConnectTimeout == NULL )
+        pszConnectTimeout = CPLGetConfigOption("GDAL_HTTP_CONNECTTIMEOUT", NULL);
+    if( pszConnectTimeout != NULL )
+        curl_easy_setopt(http_handle, CURLOPT_CONNECTTIMEOUT_MS,
+                         static_cast<int>(1000 * CPLAtof(pszConnectTimeout)) );
+
+    // Set timeout.
     const char *pszTimeout = CSLFetchNameValue( papszOptions, "TIMEOUT" );
-    if (pszTimeout == NULL)
+    if( pszTimeout == NULL )
         pszTimeout = CPLGetConfigOption("GDAL_HTTP_TIMEOUT", NULL);
     if( pszTimeout != NULL )
-        curl_easy_setopt(http_handle, CURLOPT_TIMEOUT, atoi(pszTimeout) );
+        curl_easy_setopt(http_handle, CURLOPT_TIMEOUT_MS,
+                         static_cast<int>(1000 * CPLAtof(pszTimeout)) );
 
-    /* Set low speed time and limit.*/
-    const char *pszLowSpeedTime = CSLFetchNameValue( papszOptions, "LOW_SPEED_TIME" );
-    if (pszLowSpeedTime == NULL)
+    // Set low speed time and limit.
+    const char *pszLowSpeedTime =
+        CSLFetchNameValue( papszOptions, "LOW_SPEED_TIME" );
+    if( pszLowSpeedTime == NULL )
         pszLowSpeedTime = CPLGetConfigOption("GDAL_HTTP_LOW_SPEED_TIME", NULL);
     if( pszLowSpeedTime != NULL )
     {
-        curl_easy_setopt(http_handle, CURLOPT_LOW_SPEED_TIME, atoi(pszLowSpeedTime) );
-
-        const char *pszLowSpeedLimit = CSLFetchNameValue( papszOptions, "LOW_SPEED_LIMIT" );
-        if (pszLowSpeedLimit == NULL)
-            pszLowSpeedLimit = CPLGetConfigOption("GDAL_HTTP_LOW_SPEED_LIMIT", "1");
-        curl_easy_setopt(http_handle, CURLOPT_LOW_SPEED_LIMIT, atoi(pszLowSpeedLimit) );
+        curl_easy_setopt(http_handle, CURLOPT_LOW_SPEED_TIME,
+                         atoi(pszLowSpeedTime) );
+
+        const char *pszLowSpeedLimit =
+            CSLFetchNameValue( papszOptions, "LOW_SPEED_LIMIT" );
+        if( pszLowSpeedLimit == NULL )
+            pszLowSpeedLimit =
+                CPLGetConfigOption("GDAL_HTTP_LOW_SPEED_LIMIT", "1");
+        curl_easy_setopt(http_handle, CURLOPT_LOW_SPEED_LIMIT,
+                         atoi(pszLowSpeedLimit) );
     }
 
     /* Disable some SSL verification */
     const char *pszUnsafeSSL = CSLFetchNameValue( papszOptions, "UNSAFESSL" );
-    if (pszUnsafeSSL == NULL)
+    if( pszUnsafeSSL == NULL )
         pszUnsafeSSL = CPLGetConfigOption("GDAL_HTTP_UNSAFESSL", NULL);
-    if (pszUnsafeSSL != NULL && CSLTestBoolean(pszUnsafeSSL))
+    if( pszUnsafeSSL != NULL && CPLTestBool(pszUnsafeSSL) )
     {
         curl_easy_setopt(http_handle, CURLOPT_SSL_VERIFYPEER, 0L);
         curl_easy_setopt(http_handle, CURLOPT_SSL_VERIFYHOST, 0L);
@@ -631,10 +778,10 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
 
     // Custom path to SSL certificates.
     const char* pszCAInfo = CSLFetchNameValue( papszOptions, "CAINFO" );
-    if (pszCAInfo == NULL)
+    if( pszCAInfo == NULL )
         // Name of environment variable used by the curl binary
         pszCAInfo = CPLGetConfigOption("CURL_CA_BUNDLE", NULL);
-    if (pszCAInfo == NULL)
+    if( pszCAInfo == NULL )
         // Name of environment variable used by the curl binary (tested
         // after CURL_CA_BUNDLE
         pszCAInfo = CPLGetConfigOption("SSL_CERT_FILE", NULL);
@@ -645,14 +792,14 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
 
     /* Set Referer */
     const char *pszReferer = CSLFetchNameValue(papszOptions, "REFERER");
-    if (pszReferer != NULL)
+    if( pszReferer != NULL )
         curl_easy_setopt(http_handle, CURLOPT_REFERER, pszReferer);
 
     /* Set User-Agent */
     const char *pszUserAgent = CSLFetchNameValue(papszOptions, "USERAGENT");
-    if (pszUserAgent == NULL)
+    if( pszUserAgent == NULL )
         pszUserAgent = CPLGetConfigOption("GDAL_HTTP_USERAGENT", NULL);
-    if (pszUserAgent != NULL)
+    if( pszUserAgent != NULL )
         curl_easy_setopt(http_handle, CURLOPT_USERAGENT, pszUserAgent);
 
     /* NOSIGNAL should be set to true for timeout to work in multithread
@@ -672,19 +819,44 @@ void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions)
         curl_easy_setopt(http_handle, CURLOPT_POSTFIELDS, pszPost );
     }
 
-    const char* pszCustomRequest = CSLFetchNameValue( papszOptions, "CUSTOMREQUEST" );
+    const char* pszCustomRequest =
+        CSLFetchNameValue( papszOptions, "CUSTOMREQUEST" );
     if( pszCustomRequest != NULL )
     {
         curl_easy_setopt(http_handle, CURLOPT_CUSTOMREQUEST, pszCustomRequest );
     }
 
     const char* pszCookie = CSLFetchNameValue(papszOptions, "COOKIE");
-    if (pszCookie == NULL)
+    if( pszCookie == NULL )
         pszCookie = CPLGetConfigOption("GDAL_HTTP_COOKIE", NULL);
-    if (pszCookie != NULL)
+    if( pszCookie != NULL )
         curl_easy_setopt(http_handle, CURLOPT_COOKIE, pszCookie);
+
+    struct curl_slist* headers = NULL;
+    const char *pszHeaderFile = CSLFetchNameValue( papszOptions, "HEADER_FILE" );
+    if( pszHeaderFile == NULL )
+        pszHeaderFile = CPLGetConfigOption( "GDAL_HTTP_HEADER_FILE", NULL );
+    if( pszHeaderFile != NULL )
+    {
+        VSILFILE *fp = VSIFOpenL( pszHeaderFile, "rb" );
+        if( fp == NULL )
+        {
+            CPLError(CE_Failure, CPLE_FileIO,
+                     "Cannot read %s", pszHeaderFile);
+        }
+        else
+        {
+            const char* pszLine = NULL;
+            while( (pszLine = CPLReadLineL(fp)) != NULL )
+            {
+                headers = curl_slist_append(headers, pszLine);
+            }
+            VSIFCloseL(fp);
+        }
+    }
+    return headers;
 }
-#endif /* def HAVE_CURL */
+#endif  // def HAVE_CURL
 
 /************************************************************************/
 /*                           CPLHTTPEnabled()                           */
@@ -723,17 +895,21 @@ void CPLHTTPCleanup()
 
     {
         CPLMutexHolder oHolder( &hSessionMapMutex );
-        std::map<CPLString,CURL*>::iterator oIt;
         if( poSessionMap )
         {
-            for( oIt=poSessionMap->begin(); oIt != poSessionMap->end(); oIt++ )
+            for( std::map<CPLString, CURL *>::iterator oIt =
+                     poSessionMap->begin();
+                 oIt != poSessionMap->end();
+                 oIt++ )
+            {
                 curl_easy_cleanup( oIt->second );
+            }
             delete poSessionMap;
             poSessionMap = NULL;
         }
     }
 
-    // not quite a safe sequence.
+    // Not quite a safe sequence.
     CPLDestroyMutex( hSessionMapMutex );
     hSessionMapMutex = NULL;
 #endif
@@ -758,7 +934,7 @@ void CPLHTTPDestroyResult( CPLHTTPResult *psResult )
         CPLFree( psResult->pszContentType );
         CSLDestroy( psResult->papszHeaders );
 
-        for(int i=0;i<psResult->nMimePartCount;i++)
+        for( int i = 0; i < psResult->nMimePartCount; i++ )
         {
             CSLDestroy( psResult->pasMimePart[i].papszHeaders );
         }
@@ -796,7 +972,7 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
     const char *pszBound = NULL;
 
     if( psResult->pszContentType != NULL )
-        pszBound = strstr(psResult->pszContentType,"boundary=");
+        pszBound = strstr(psResult->pszContentType, "boundary=");
 
     if( pszBound == NULL )
     {
@@ -825,8 +1001,9 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
 /* -------------------------------------------------------------------- */
 /*      Find the start of the first chunk.                              */
 /* -------------------------------------------------------------------- */
-    char *pszNext = (char *)
-        strstr((const char *) psResult->pabyData,osBoundary.c_str());
+    char *pszNext =
+        strstr(reinterpret_cast<char *>(psResult->pabyData),
+               osBoundary.c_str());
 
     if( pszNext == NULL )
     {
@@ -834,7 +1011,7 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
         return FALSE;
     }
 
-    pszNext += strlen(osBoundary);
+    pszNext += osBoundary.size();
     while( *pszNext != '\n' && *pszNext != '\r' && *pszNext != '\0' )
         pszNext++;
     if( *pszNext == '\r' )
@@ -848,9 +1025,9 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
     while( true )
     {
         psResult->nMimePartCount++;
-        psResult->pasMimePart = (CPLMimePart *)
+        psResult->pasMimePart = static_cast<CPLMimePart *>(
             CPLRealloc(psResult->pasMimePart,
-                       sizeof(CPLMimePart) * psResult->nMimePartCount );
+                       sizeof(CPLMimePart) * psResult->nMimePartCount));
 
         CPLMimePart *psPart = psResult->pasMimePart+psResult->nMimePartCount-1;
 
@@ -861,25 +1038,26 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
 /* -------------------------------------------------------------------- */
         while( *pszNext != '\n' && *pszNext != '\r' && *pszNext != '\0' )
         {
-            char *pszEOL = strstr(pszNext,"\n");
+            char *pszEOL = strstr(pszNext, "\n");
 
             if( pszEOL == NULL )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
-                         "Error while parsing multipart content (at line %d)", __LINE__);
+                         "Error while parsing multipart content (at line %d)",
+                         __LINE__);
                 return FALSE;
             }
 
             *pszEOL = '\0';
             bool bRestoreAntislashR = false;
-            if (pszEOL - pszNext > 1 && pszEOL[-1] == '\r')
+            if( pszEOL - pszNext > 1 && pszEOL[-1] == '\r' )
             {
                 bRestoreAntislashR = true;
                 pszEOL[-1] = '\0';
             }
             psPart->papszHeaders =
                 CSLAddString( psPart->papszHeaders, pszNext );
-            if (bRestoreAntislashR)
+            if( bRestoreAntislashR )
                 pszEOL[-1] = '\r';
             *pszEOL = '\n';
 
@@ -894,14 +1072,16 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
 /* -------------------------------------------------------------------- */
 /*      Work out the data block size.                                   */
 /* -------------------------------------------------------------------- */
-        psPart->pabyData = (GByte *) pszNext;
+        psPart->pabyData = reinterpret_cast<GByte *>(pszNext);
 
-        int nBytesAvail = psResult->nDataLen -
-            static_cast<int>(pszNext - (const char *) psResult->pabyData);
+        int nBytesAvail =
+            psResult->nDataLen -
+            static_cast<int>(
+                pszNext - reinterpret_cast<char *>(psResult->pabyData));
 
         while( nBytesAvail > 0
                && (*pszNext != '-'
-                   || strncmp(pszNext,osBoundary,strlen(osBoundary)) != 0) )
+                   || strncmp(pszNext, osBoundary, osBoundary.size()) != 0) )
         {
             pszNext++;
             nBytesAvail--;
@@ -910,12 +1090,15 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
         if( nBytesAvail == 0 )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                        "Error while parsing multipart content (at line %d)", __LINE__);
+                     "Error while parsing multipart content (at line %d)",
+                     __LINE__);
             return FALSE;
         }
 
-        psPart->nDataLen = static_cast<int>(pszNext - (const char *) psPart->pabyData);
-        pszNext += strlen(osBoundary);
+        psPart->nDataLen =
+            static_cast<int>(
+                pszNext - reinterpret_cast<char *>(psPart->pabyData));
+        pszNext += osBoundary.size();
 
         if( STARTS_WITH(pszNext, "--") )
         {
@@ -929,7 +1112,8 @@ int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult )
         else
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                        "Error while parsing multipart content (at line %d)", __LINE__);
+                     "Error while parsing multipart content (at line %d)",
+                     __LINE__);
             return FALSE;
         }
     }
diff --git a/port/cpl_http.h b/port/cpl_http.h
index 071ed11..a032f0e 100644
--- a/port/cpl_http.h
+++ b/port/cpl_http.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_http.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cpl_http.h 37645 2017-03-08 00:15:33Z rouault $
  *
  * Project:  Common Portability Library
  * Purpose:  Function wrapper for libcurl HTTP access.
@@ -64,6 +64,7 @@ typedef struct {
 
     /*! Length of the pabyData buffer */
     int     nDataLen;
+    /*! Allocated size of the pabyData buffer */
     int     nDataAlloc;
 
     /*! Buffer with downloaded data */
@@ -102,4 +103,12 @@ char CPL_DLL *GOA2GetAccessToken( const char *pszRefreshToken,
 
 CPL_C_END
 
+#ifdef __cplusplus
+/*! @cond Doxygen_Suppress */
+// Not sure if this belong here, used in cpl_http.cpp, cpl_vsil_curl.cpp and frmts/wms/gdalhttp.cpp
+void* CPLHTTPSetOptions(void *pcurl, const char * const* papszOptions);
+char** CPLHTTPGetOptionsFromEnv();
+/*! @endcond */
+#endif // __cplusplus
+
 #endif /* ndef CPL_HTTP_H_INCLUDED */
diff --git a/port/cpl_list.cpp b/port/cpl_list.cpp
index 7859b4d..f3333e9 100644
--- a/port/cpl_list.cpp
+++ b/port/cpl_list.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_list.cpp 33671 2016-03-07 18:39:06Z goatbar $
  *
  * Name:     cpl_list.cpp
  * Project:  CPL - Common Portability Library
@@ -29,10 +28,13 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_conv.h"
 #include "cpl_list.h"
 
-CPL_CVSID("$Id: cpl_list.cpp 33671 2016-03-07 18:39:06Z goatbar $");
+#include <cstddef>
+
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: cpl_list.cpp 36798 2016-12-11 22:19:57Z goatbar $");
 
 /*=====================================================================
                     List manipulation functions.
@@ -56,8 +58,8 @@ CPLList *CPLListAppend( CPLList *psList, void *pData )
 {
     CPLList *psLast = NULL;
 
-    /* Allocate room for the new object */
-    if ( psList == NULL )
+    // Allocate room for the new object.
+    if( psList == NULL )
     {
       psLast = static_cast<CPLList *>( CPLMalloc( sizeof(CPLList) ) );
       psList = psLast;
@@ -69,7 +71,7 @@ CPLList *CPLListAppend( CPLList *psList, void *pData )
             CPLMalloc( sizeof(CPLList) ) );
     }
 
-    /* Append object to the end of list */
+    // Append object to the end of list.
     psLast->pData = pData;
     psLast->psNext = NULL;
 
@@ -93,10 +95,10 @@ CPLList *CPLListAppend( CPLList *psList, void *pData )
 
 CPLList *CPLListInsert( CPLList *psList, void *pData, int nPosition )
 {
-    if ( nPosition < 0 )
-        return psList;      /* Nothing to do!*/
+    if( nPosition < 0 )
+        return psList;  // Nothing to do.
 
-    if ( nPosition == 0)
+    if( nPosition == 0 )
     {
         CPLList *psNew = static_cast<CPLList *>( CPLMalloc( sizeof(CPLList) ) );
         psNew->pData = pData;
@@ -107,20 +109,20 @@ CPLList *CPLListInsert( CPLList *psList, void *pData, int nPosition )
 
     const int nCount = CPLListCount( psList );
 
-    if ( nCount < nPosition )
+    if( nCount < nPosition )
     {
-        /* Allocate room for the new object */
+        // Allocate room for the new object.
         CPLList* psLast = CPLListGetLast(psList);
-        for ( int i = nCount; i <= nPosition - 1; i++ )
+        for( int i = nCount; i <= nPosition - 1; i++ )
         {
             psLast = CPLListAppend( psLast, NULL );
-            if (psList == NULL)
+            if( psList == NULL )
                 psList = psLast;
             else
                 psLast = psLast->psNext;
         }
         psLast = CPLListAppend( psLast, pData );
-        if (psList == NULL)
+        if( psList == NULL )
             psList = psLast;
 
         /* coverity[leaked_storage] */
@@ -131,7 +133,7 @@ CPLList *CPLListInsert( CPLList *psList, void *pData, int nPosition )
     psNew->pData = pData;
 
     CPLList *psCurrent = psList;
-    for ( int i = 0; i < nPosition - 1; i++ )
+    for( int i = 0; i < nPosition - 1; i++ )
         psCurrent = psCurrent->psNext;
     psNew->psNext = psCurrent->psNext;
     psCurrent->psNext = psNew;
@@ -153,11 +155,11 @@ CPLList *CPLListInsert( CPLList *psList, void *pData, int nPosition )
 
 CPLList *CPLListGetLast( CPLList * const psList )
 {
-    if ( psList == NULL )
+    if( psList == NULL )
         return NULL;
 
     CPLList * psCurrent = psList;
-    while ( psCurrent->psNext )
+    while( psCurrent->psNext )
         psCurrent = psCurrent->psNext;
 
     return psCurrent;
@@ -171,19 +173,20 @@ CPLList *CPLListGetLast( CPLList * const psList )
  * Return the pointer to the specified element in a list.
  *
  * @param psList pointer to list head.
- * @param nPosition the index of the element in the list, 0 being the first element
+ * @param nPosition the index of the element in the list, 0 being the
+ * first element.
  *
  * @return pointer to the specified element in a list.
  */
 
 CPLList *CPLListGet( CPLList *psList, int nPosition )
 {
-    if ( nPosition < 0 )
+    if( nPosition < 0 )
         return NULL;
 
     CPLList *psCurrent = psList;
-    int     iItem = 0;
-    while ( iItem < nPosition && psCurrent )
+    int iItem = 0;
+    while( iItem < nPosition && psCurrent )
     {
         psCurrent = psCurrent->psNext;
         iItem++;
@@ -209,7 +212,7 @@ int CPLListCount( const CPLList *psList )
     int nItems = 0;
     const CPLList *psCurrent = psList;
 
-    while ( psCurrent )
+    while( psCurrent )
     {
         nItems++;
         psCurrent = psCurrent->psNext;
@@ -235,13 +238,13 @@ int CPLListCount( const CPLList *psList )
 CPLList *CPLListRemove( CPLList *psList, int nPosition )
 {
 
-    if ( psList == NULL)
+    if( psList == NULL )
         return NULL;
 
-    if ( nPosition < 0)
+    if( nPosition < 0 )
         return psList;      /* Nothing to do. */
 
-    if ( nPosition == 0 )
+    if( nPosition == 0 )
     {
         CPLList *psCurrent = psList->psNext;
         CPLFree( psList );
@@ -250,16 +253,16 @@ CPLList *CPLListRemove( CPLList *psList, int nPosition )
     }
 
     CPLList *psCurrent = psList;
-    for ( int i = 0; i < nPosition - 1; i++ )
+    for( int i = 0; i < nPosition - 1; i++ )
     {
         psCurrent = psCurrent->psNext;
-        /* psCurrent == NULL if nPosition >= CPLListCount(psList) */
-        if (psCurrent == NULL)
+        // psCurrent == NULL if nPosition >= CPLListCount(psList).
+        if( psCurrent == NULL )
             return psList;
     }
     CPLList *psRemoved = psCurrent->psNext;
-    /* psRemoved == NULL if nPosition >= CPLListCount(psList) */
-    if (psRemoved == NULL)
+    // psRemoved == NULL if nPosition >= CPLListCount(psList).
+    if( psRemoved == NULL )
         return psList;
     psCurrent->psNext = psRemoved->psNext;
     CPLFree( psRemoved );
@@ -283,7 +286,7 @@ void CPLListDestroy( CPLList *psList )
 {
     CPLList *psCurrent = psList;
 
-    while ( psCurrent )
+    while( psCurrent )
     {
         CPLList * const psNext = psCurrent->psNext;
         CPLFree( psCurrent );
@@ -305,7 +308,7 @@ void CPLListDestroy( CPLList *psList )
 
 CPLList *CPLListGetNext( const CPLList *psElement )
 {
-    if ( psElement == NULL )
+    if( psElement == NULL )
         return NULL;
 
     return psElement->psNext;
@@ -325,7 +328,7 @@ CPLList *CPLListGetNext( const CPLList *psElement )
 
 void *CPLListGetData( const CPLList *psElement )
 {
-    if ( psElement == NULL )
+    if( psElement == NULL )
         return NULL;
 
     return psElement->pData;
diff --git a/port/cpl_list.h b/port/cpl_list.h
index a6e64d8..f802fcd 100644
--- a/port/cpl_list.h
+++ b/port/cpl_list.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_list.h 33671 2016-03-07 18:39:06Z goatbar $
+ * $Id: cpl_list.h 37825 2017-03-21 20:14:08Z rouault $
  *
  * Name:     cpl_list.h
  * Project:  CPL - Common Portability Library
@@ -45,7 +45,10 @@
 CPL_C_START
 
 /** List element structure. */
-typedef struct _CPLList
+typedef struct _CPLList CPLList;
+
+/** List element structure. */
+struct _CPLList
 {
     /*! Pointer to the data object. Should be allocated and freed by the
      * caller.
@@ -55,7 +58,7 @@ typedef struct _CPLList
      * last one.
      */
     struct _CPLList    *psNext;
-} CPLList;
+};
 
 CPLList CPL_DLL *CPLListAppend( CPLList *psList, void * pData );
 CPLList CPL_DLL *CPLListInsert( CPLList *psList, void * pData, int nPosition );
diff --git a/port/cpl_minixml.cpp b/port/cpl_minixml.cpp
index 8b15696..b078f3d 100644
--- a/port/cpl_minixml.cpp
+++ b/port/cpl_minixml.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_minixml.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of MiniXML Parser and handling.
@@ -40,12 +39,21 @@
  */
 
 #include "cpl_minixml.h"
-#include "cpl_error.h"
+
+#include <cctype>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+
+#include <algorithm>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_string.h"
-#include <ctype.h>
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_minixml.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+CPL_CVSID("$Id: cpl_minixml.cpp 37918 2017-04-07 17:05:53Z rouault $");
 
 typedef enum {
     TNone,
@@ -70,7 +78,7 @@ typedef struct {
     const char *pszInput;
     int        nInputOffset;
     int        nInputLine;
-    int        bInElement;
+    bool       bInElement;
     XMLTokenType  eTokenType;
     char       *pszToken;
     size_t     nTokenMaxSize;
@@ -84,7 +92,8 @@ typedef struct {
     CPLXMLNode *psLastNode;
 } ParseContext;
 
-static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
+static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent,
+                                      CPLXMLNodeType eType,
                                       const char *pszText );
 
 /************************************************************************/
@@ -129,22 +138,24 @@ static CPL_INLINE void UnreadChar( ParseContext *psContext, char chToUnread )
 
 static bool ReallocToken( ParseContext *psContext )
 {
-    if (psContext->nTokenMaxSize > INT_MAX / 2)
+    if( psContext->nTokenMaxSize > INT_MAX / 2 )
     {
         CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Out of memory allocating %d*2 bytes", (int)psContext->nTokenMaxSize);
+                 "Out of memory allocating %d*2 bytes",
+                 static_cast<int>(psContext->nTokenMaxSize));
         VSIFree(psContext->pszToken);
         psContext->pszToken = NULL;
         return false;
     }
 
     psContext->nTokenMaxSize *= 2;
-    char* pszToken = (char *)
-        VSIRealloc(psContext->pszToken,psContext->nTokenMaxSize);
-    if (pszToken == NULL)
+    char* pszToken = static_cast<char *>(
+        VSIRealloc(psContext->pszToken, psContext->nTokenMaxSize));
+    if( pszToken == NULL )
     {
         CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Out of memory allocating %d bytes", (int)psContext->nTokenMaxSize);
+                 "Out of memory allocating %d bytes",
+                 static_cast<int>(psContext->nTokenMaxSize));
         VSIFree(psContext->pszToken);
         psContext->pszToken = NULL;
         return false;
@@ -162,7 +173,7 @@ static CPL_INLINE bool _AddToToken( ParseContext *psContext, char chNewChar )
 {
     if( psContext->nTokenSize >= psContext->nTokenMaxSize - 2 )
     {
-        if (!ReallocToken(psContext))
+        if( !ReallocToken(psContext) )
             return false;
     }
 
@@ -171,7 +182,9 @@ static CPL_INLINE bool _AddToToken( ParseContext *psContext, char chNewChar )
     return true;
 }
 
-#define AddToToken(psContext, chNewChar) if (!_AddToToken(psContext, chNewChar)) goto fail;
+// TODO(schwehr): Remove the goto.
+#define AddToToken(psContext, chNewChar) \
+    if( !_AddToToken(psContext, chNewChar)) goto fail;
 
 /************************************************************************/
 /*                             ReadToken()                              */
@@ -184,7 +197,7 @@ static XMLTokenType ReadToken( ParseContext *psContext )
     psContext->pszToken[0] = '\0';
 
     char chNext = ReadChar( psContext );
-    while( isspace((unsigned char)chNext) )
+    while( isspace(static_cast<unsigned char>(chNext)) )
         chNext = ReadChar( psContext );
 
 /* -------------------------------------------------------------------- */
@@ -195,16 +208,17 @@ static XMLTokenType ReadToken( ParseContext *psContext )
     {
         psContext->eTokenType = TComment;
 
-        // Skip "!--" characters
+        // Skip "!--" characters.
         ReadChar(psContext);
         ReadChar(psContext);
         ReadChar(psContext);
 
-        while( !STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "-->")
+        while( !STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset,
+                               "-->")
                && (chNext = ReadChar(psContext)) != '\0' )
             AddToToken( psContext, chNext );
 
-        // Skip "-->" characters
+        // Skip "-->" characters.
         ReadChar(psContext);
         ReadChar(psContext);
         ReadChar(psContext);
@@ -212,8 +226,9 @@ static XMLTokenType ReadToken( ParseContext *psContext )
 /* -------------------------------------------------------------------- */
 /*      Handle DOCTYPE.                                                 */
 /* -------------------------------------------------------------------- */
-    else if( chNext == '<'
-          && STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "!DOCTYPE") )
+    else if( chNext == '<' &&
+             STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset,
+                            "!DOCTYPE") )
     {
         bool bInQuotes = false;
         psContext->eTokenType = TLiteral;
@@ -245,37 +260,37 @@ static XMLTokenType ReadToken( ParseContext *psContext )
                 do
                 {
                     chNext = ReadChar( psContext );
-                    if (chNext == ']')
+                    if( chNext == ']' )
                         break;
                     AddToToken( psContext, chNext );
                 }
-                while( chNext != '\0'
-                    && !STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "]>") );
+                while( chNext != '\0' &&
+                       !STARTS_WITH_CI(
+                           psContext->pszInput+psContext->nInputOffset, "]>") );
 
-                if (chNext == '\0')
+                if( chNext == '\0' )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
-                          "Parse error in DOCTYPE on or before line %d, "
-                          "reached end of file without ']'.",
+                              "Parse error in DOCTYPE on or before line %d, "
+                              "reached end of file without ']'.",
                           psContext->nInputLine );
                     break;
                 }
 
-                if (chNext != ']')
+                if( chNext != ']' )
                 {
                     chNext = ReadChar( psContext );
                     AddToToken( psContext, chNext );
 
-                    // Skip ">" character, will be consumed below
+                    // Skip ">" character, will be consumed below.
                     chNext = ReadChar( psContext );
                 }
             }
 
-
             if( chNext == '\"' )
                 bInQuotes = !bInQuotes;
 
-             if( chNext == '>' && !bInQuotes )
+            if( chNext == '>' && !bInQuotes )
             {
                 AddToToken( psContext, '>' );
                 break;
@@ -287,8 +302,9 @@ static XMLTokenType ReadToken( ParseContext *psContext )
 /* -------------------------------------------------------------------- */
 /*      Handle CDATA.                                                   */
 /* -------------------------------------------------------------------- */
-    else if( chNext == '<'
-          && STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "![CDATA[") )
+    else if( chNext == '<' &&
+             STARTS_WITH_CI(
+                 psContext->pszInput+psContext->nInputOffset, "![CDATA[") )
     {
         psContext->eTokenType = TString;
 
@@ -302,11 +318,12 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         ReadChar( psContext );
         ReadChar( psContext );
 
-        while( !STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset, "]]>")
+        while( !STARTS_WITH_CI(psContext->pszInput+psContext->nInputOffset,
+                               "]]>")
                && (chNext = ReadChar(psContext)) != '\0' )
             AddToToken( psContext, chNext );
 
-        // Skip "]]>" characters
+        // Skip "]]>" characters.
         ReadChar(psContext);
         ReadChar(psContext);
         ReadChar(psContext);
@@ -317,12 +334,12 @@ static XMLTokenType ReadToken( ParseContext *psContext )
     else if( chNext == '<' && !psContext->bInElement )
     {
         psContext->eTokenType = TOpen;
-        psContext->bInElement = TRUE;
+        psContext->bInElement = true;
     }
     else if( chNext == '>' && psContext->bInElement )
     {
         psContext->eTokenType = TClose;
-        psContext->bInElement = FALSE;
+        psContext->bInElement = false;
     }
     else if( chNext == '=' && psContext->bInElement )
     {
@@ -342,7 +359,7 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         CPLAssert( chNext == '>' );
 
         psContext->eTokenType = TSlashClose;
-        psContext->bInElement = FALSE;
+        psContext->bInElement = false;
     }
 /* -------------------------------------------------------------------- */
 /*      Handle the ?> token terminator.                                 */
@@ -355,9 +372,8 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         CPLAssert( chNext == '>' );
 
         psContext->eTokenType = TQuestionClose;
-        psContext->bInElement = FALSE;
+        psContext->bInElement = false;
     }
-
 /* -------------------------------------------------------------------- */
 /*      Collect a quoted string.                                        */
 /* -------------------------------------------------------------------- */
@@ -372,13 +388,14 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         if( chNext != '"' )
         {
             psContext->eTokenType = TNone;
-            CPLError( CE_Failure, CPLE_AppDefined,
-                  "Parse error on line %d, reached EOF before closing quote.",
-                      psContext->nInputLine );
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Parse error on line %d, reached EOF before closing quote.",
+                psContext->nInputLine);
         }
 
-        /* Do we need to unescape it? */
-        if( strchr(psContext->pszToken,'&') != NULL )
+        // Do we need to unescape it?
+        if( strchr(psContext->pszToken, '&') != NULL )
         {
             int nLength = 0;
             char *pszUnescaped = CPLUnescapeString( psContext->pszToken,
@@ -388,7 +405,6 @@ static XMLTokenType ReadToken( ParseContext *psContext )
             psContext->nTokenSize = strlen(psContext->pszToken );
         }
     }
-
     else if( psContext->bInElement && chNext == '\'' )
     {
         psContext->eTokenType = TString;
@@ -400,13 +416,14 @@ static XMLTokenType ReadToken( ParseContext *psContext )
         if( chNext != '\'' )
         {
             psContext->eTokenType = TNone;
-            CPLError( CE_Failure, CPLE_AppDefined,
-                  "Parse error on line %d, reached EOF before closing quote.",
-                      psContext->nInputLine );
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Parse error on line %d, reached EOF before closing quote.",
+                psContext->nInputLine);
         }
 
-        /* Do we need to unescape it? */
-        if( strchr(psContext->pszToken,'&') != NULL )
+        // Do we need to unescape it?
+        if( strchr(psContext->pszToken, '&') != NULL )
         {
             int nLength = 0;
             char *pszUnescaped = CPLUnescapeString( psContext->pszToken,
@@ -416,7 +433,6 @@ static XMLTokenType ReadToken( ParseContext *psContext )
             psContext->nTokenSize = strlen(psContext->pszToken );
         }
     }
-
 /* -------------------------------------------------------------------- */
 /*      Collect an unquoted string, terminated by a open angle          */
 /*      bracket.                                                        */
@@ -431,8 +447,8 @@ static XMLTokenType ReadToken( ParseContext *psContext )
             AddToToken( psContext, chNext );
         UnreadChar( psContext, chNext );
 
-        /* Do we need to unescape it? */
-        if( strchr(psContext->pszToken,'&') != NULL )
+        // Do we need to unescape it?
+        if( strchr(psContext->pszToken, '&') != NULL )
         {
             int nLength = 0;
             char *pszUnescaped = CPLUnescapeString( psContext->pszToken,
@@ -451,7 +467,7 @@ static XMLTokenType ReadToken( ParseContext *psContext )
     {
         psContext->eTokenType = TToken;
 
-        /* add the first character to the token regardless of what it is */
+        // Add the first character to the token regardless of what it is.
         AddToToken( psContext, chNext );
 
         for( chNext = ReadChar(psContext);
@@ -486,24 +502,26 @@ static bool PushNode( ParseContext *psContext, CPLXMLNode *psNode )
 {
     if( psContext->nStackMaxSize <= psContext->nStackSize )
     {
-        /* Somewhat arbitrary number... */
-        if (psContext->nStackMaxSize >= 10000)
+        // Somewhat arbitrary number.
+        if( psContext->nStackMaxSize >= 10000 )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
-                 "XML element depth beyond 10000. Giving up");
+                     "XML element depth beyond 10000. Giving up");
             VSIFree(psContext->papsStack);
             psContext->papsStack = NULL;
             return false;
         }
         psContext->nStackMaxSize += 10;
 
-        StackContext* papsStack;
-        papsStack = (StackContext *)VSIRealloc(psContext->papsStack,
-                    sizeof(StackContext) * psContext->nStackMaxSize);
-        if (papsStack == NULL)
+        StackContext* papsStack = static_cast<StackContext *>(
+            VSIRealloc(psContext->papsStack,
+                       sizeof(StackContext) * psContext->nStackMaxSize));
+        if( papsStack == NULL )
         {
             CPLError(CE_Failure, CPLE_OutOfMemory,
-                 "Out of memory allocating %d bytes", (int)(sizeof(StackContext) * psContext->nStackMaxSize));
+                     "Out of memory allocating %d bytes",
+                     static_cast<int>(sizeof(StackContext)) *
+                     psContext->nStackMaxSize);
             VSIFree(psContext->papsStack);
             psContext->papsStack = NULL;
             return false;
@@ -511,14 +529,15 @@ static bool PushNode( ParseContext *psContext, CPLXMLNode *psNode )
         psContext->papsStack = papsStack;
     }
 #ifdef DEBUG
-    // To make Coverity happy, but cannot happen
+    // To make Coverity happy, but cannot happen.
     if( psContext->papsStack == NULL )
         return false;
 #endif
 
     psContext->papsStack[psContext->nStackSize].psFirstNode = psNode;
     psContext->papsStack[psContext->nStackSize].psLastChild = NULL;
-    psContext->nStackSize ++;
+    psContext->nStackSize++;
+
     return true;
 }
 
@@ -545,13 +564,16 @@ static void AttachNode( ParseContext *psContext, CPLXMLNode *psNode )
     }
     else
     {
-        if( psContext->papsStack[psContext->nStackSize-1].psFirstNode->psChild == NULL )
+        if( psContext->papsStack[psContext->nStackSize-1].psFirstNode->psChild
+            == NULL )
         {
-            psContext->papsStack[psContext->nStackSize-1].psFirstNode->psChild = psNode;
+            psContext->papsStack[psContext->nStackSize-1].psFirstNode->psChild =
+                psNode;
         }
         else
         {
-            psContext->papsStack[psContext->nStackSize-1].psLastChild->psNext = psNode;
+            psContext->papsStack[psContext->nStackSize-1].psLastChild->psNext =
+                psNode;
         }
         psContext->papsStack[psContext->nStackSize-1].psLastChild = psNode;
     }
@@ -587,8 +609,6 @@ static void AttachNode( ParseContext *psContext, CPLXMLNode *psNode )
 CPLXMLNode *CPLParseXMLString( const char *pszString )
 
 {
-    CPLErrorReset();
-
     if( pszString == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -596,6 +616,14 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
         return NULL;
     }
 
+    // Save back error context.
+    const CPLErr eErrClass = CPLGetLastErrorType();
+    const CPLErrorNum nErrNum = CPLGetLastErrorNo();
+    const CPLString osErrMsg = CPLGetLastErrorMsg();
+
+    // Reset it now.
+    CPLErrorReset();
+
 /* -------------------------------------------------------------------- */
 /*      Check for a UTF-8 BOM and skip if found                         */
 /*                                                                      */
@@ -603,10 +631,10 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
 /*            Add BOM detection for other encodings.                    */
 /* -------------------------------------------------------------------- */
 
-    // Used to skip to actual beginning of XML data
-    if( ( (unsigned char)pszString[0] == 0xEF )
-        && ( (unsigned char)pszString[1] == 0xBB )
-        && ( (unsigned char)pszString[2] == 0xBF) )
+    // Used to skip to actual beginning of XML data.
+    if( ( static_cast<unsigned char>(pszString[0]) == 0xEF )
+        && ( static_cast<unsigned char>(pszString[1]) == 0xBB )
+        && ( static_cast<unsigned char>(pszString[2]) == 0xBF) )
     {
         pszString += 3;
     }
@@ -618,10 +646,10 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
     sContext.pszInput = pszString;
     sContext.nInputOffset = 0;
     sContext.nInputLine = 0;
-    sContext.bInElement = FALSE;
+    sContext.bInElement = false;
     sContext.nTokenMaxSize = 10;
-    sContext.pszToken = (char *) VSIMalloc(sContext.nTokenMaxSize);
-    if (sContext.pszToken == NULL)
+    sContext.pszToken = static_cast<char *>(VSIMalloc(sContext.nTokenMaxSize));
+    if( sContext.pszToken == NULL )
         return NULL;
     sContext.nTokenSize = 0;
     sContext.eTokenType = TNone;
@@ -644,36 +672,40 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
             if( ReadToken(&sContext) != TToken )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "Line %d: Didn't find element token after open angle bracket.",
+                          "Line %d: Didn't find element token after "
+                          "open angle bracket.",
                           sContext.nInputLine );
                 break;
             }
 
-            CPLXMLNode *psElement;
+            CPLXMLNode *psElement = NULL;
             if( sContext.pszToken[0] != '/' )
             {
                 psElement = _CPLCreateXMLNode( NULL, CXT_Element,
                                               sContext.pszToken );
-                if (!psElement) break;
+                if( !psElement ) break;
                 AttachNode( &sContext, psElement );
-                if (!PushNode( &sContext, psElement ))
+                if( !PushNode( &sContext, psElement ) )
                     break;
             }
             else
             {
-                if( sContext.nStackSize == 0
-                    || !EQUAL(sContext.pszToken+1,
-                         sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue) )
+                if( sContext.nStackSize == 0 ||
+                    !EQUAL(sContext.pszToken+1,
+                           sContext.papsStack[sContext.nStackSize-1].
+                               psFirstNode->pszValue) )
                 {
 #ifdef DEBUG
-                    /* Makes life of fuzzers easier if we accept somewhat corrupted XML */
-                    /* like <foo> ... </not_foo> */
-                    if( CPLTestBool(CPLGetConfigOption("CPL_MINIXML_RELAXED", "FALSE")) )
+                    // Makes life of fuzzers easier if we accept somewhat
+                    // corrupted XML like <foo> ... </not_foo>.
+                    if( CPLTestBool(CPLGetConfigOption("CPL_MINIXML_RELAXED",
+                                                       "FALSE")) )
                     {
-                        CPLError( CE_Warning, CPLE_AppDefined,
-                                "Line %d: <%.500s> doesn't have matching <%.500s>.",
-                                sContext.nInputLine,
-                                sContext.pszToken, sContext.pszToken+1 );
+                        CPLError(
+                            CE_Warning, CPLE_AppDefined,
+                            "Line %d: <%.500s> doesn't have matching <%.500s>.",
+                            sContext.nInputLine,
+                            sContext.pszToken, sContext.pszToken + 1 );
                         if( sContext.nStackSize == 0 )
                             break;
                         goto end_processing_close;
@@ -681,27 +713,31 @@ CPLXMLNode *CPLParseXMLString( const char *pszString )
                     else
 #endif
                     {
-                        CPLError( CE_Failure, CPLE_AppDefined,
-                                "Line %d: <%.500s> doesn't have matching <%.500s>.",
-                                sContext.nInputLine,
-                                sContext.pszToken, sContext.pszToken+1 );
+                        CPLError(
+                            CE_Failure, CPLE_AppDefined,
+                            "Line %d: <%.500s> doesn't have matching <%.500s>.",
+                            sContext.nInputLine,
+                            sContext.pszToken, sContext.pszToken + 1 );
                         break;
                     }
                 }
                 else
                 {
-                    if (strcmp(sContext.pszToken+1,
-                         sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue) != 0)
+                    if( strcmp(sContext.pszToken + 1,
+                               sContext.papsStack[sContext.nStackSize-1].
+                                   psFirstNode->pszValue) != 0)
                     {
-                        /* TODO: at some point we could just error out like any other */
-                        /* sane XML parser would do */
-                        CPLError( CE_Warning, CPLE_AppDefined,
-                                "Line %d: <%.500s> matches <%.500s>, but the case isn't the same. "
-                                "Going on, but this is invalid XML that might be rejected in "
-                                "future versions.",
-                                sContext.nInputLine,
-                                sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue,
-                                sContext.pszToken );
+                        // TODO: At some point we could just error out like any
+                        // other sane XML parser would do.
+                        CPLError(
+                            CE_Warning, CPLE_AppDefined,
+                            "Line %d: <%.500s> matches <%.500s>, but the case "
+                            "isn't the same.  Going on, but this is invalid "
+                            "XML that might be rejected in future versions.",
+                            sContext.nInputLine,
+                            sContext.papsStack[sContext.nStackSize-1].
+                                psFirstNode->pszValue,
+                            sContext.pszToken );
                     }
 #ifdef DEBUG
 end_processing_close:
@@ -709,13 +745,14 @@ end_processing_close:
                     if( ReadToken(&sContext) != TClose )
                     {
                         CPLError( CE_Failure, CPLE_AppDefined,
-                                  "Line %d: Missing close angle bracket after <%.500s.",
+                                  "Line %d: Missing close angle bracket "
+                                  "after <%.500s.",
                                   sContext.nInputLine,
                                   sContext.pszToken );
                         break;
                     }
 
-                    /* pop element off stack */
+                    // Pop element off stack
                     sContext.nStackSize--;
                 }
             }
@@ -726,32 +763,46 @@ end_processing_close:
 /* -------------------------------------------------------------------- */
         else if( sContext.eTokenType == TToken )
         {
-            CPLXMLNode *psAttr = _CPLCreateXMLNode(NULL, CXT_Attribute, sContext.pszToken);
-            if (!psAttr) break;
+            CPLXMLNode *psAttr =
+                _CPLCreateXMLNode(NULL, CXT_Attribute, sContext.pszToken);
+            if( !psAttr ) break;
             AttachNode( &sContext, psAttr );
 
             if( ReadToken(&sContext) != TEqual )
             {
-                // Parse stuff like <?valbuddy_schematron ../wmtsSimpleGetCapabilities.sch?>
+                // Parse stuff like <?valbuddy_schematron
+                // ../wmtsSimpleGetCapabilities.sch?>
                 if( sContext.nStackSize > 0 &&
-                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue[0] == '?' &&
-                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->psChild == psAttr )
+                      sContext.papsStack[sContext.nStackSize - 1]
+                              .psFirstNode->pszValue[0] == '?' &&
+                      sContext.papsStack[sContext.nStackSize - 1]
+                              .psFirstNode->psChild == psAttr )
                 {
                     CPLDestroyXMLNode(psAttr);
-                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->psChild = NULL;
-                    sContext.papsStack[sContext.nStackSize-1].psLastChild = NULL;
-
-                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue = (char*)CPLRealloc(
-                        sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue,
-                        strlen(sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue) + 1 + strlen(sContext.pszToken) + 1);
-                    strcat(sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue, " ");
-                    strcat(sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue, sContext.pszToken);
-
+                    sContext.papsStack[sContext.nStackSize - 1]
+                        .psFirstNode->psChild = NULL;
+                    sContext.papsStack[sContext.nStackSize - 1].psLastChild =
+                        NULL;
+
+                    sContext.papsStack[sContext.nStackSize - 1]
+                        .psFirstNode->pszValue = static_cast<char *>(CPLRealloc(
+                        sContext.papsStack[sContext.nStackSize - 1]
+                            .psFirstNode->pszValue,
+                        strlen(sContext.papsStack[sContext.nStackSize - 1]
+                                   .psFirstNode->pszValue) +
+                            1 + strlen(sContext.pszToken) + 1));
+                    strcat(sContext.papsStack[sContext.nStackSize - 1]
+                               .psFirstNode->pszValue,
+                           " ");
+                    strcat(sContext.papsStack[sContext.nStackSize - 1]
+                               .psFirstNode->pszValue,
+                           sContext.pszToken);
                     continue;
                 }
 
                 CPLError( CE_Failure, CPLE_AppDefined,
-                          "Line %d: Didn't find expected '=' for value of attribute '%.500s'.",
+                          "Line %d: Didn't find expected '=' for value of "
+                          "attribute '%.500s'.",
                           sContext.nInputLine, psAttr->pszValue );
                 break;
             }
@@ -761,9 +812,9 @@ end_processing_close:
                 /* TODO: at some point we could just error out like any other */
                 /* sane XML parser would do */
                 CPLError( CE_Warning, CPLE_AppDefined,
-                          "Line %d: Attribute value should be single or double quoted. "
-                          "Going on, but this is invalid XML that might be rejected in "
-                          "future versions.",
+                          "Line %d: Attribute value should be single or double "
+                          "quoted.  Going on, but this is invalid XML that "
+                          "might be rejected in future versions.",
                           sContext.nInputLine );
             }
             else if( sContext.eTokenType != TString )
@@ -774,7 +825,8 @@ end_processing_close:
                 break;
             }
 
-            if (!_CPLCreateXMLNode( psAttr, CXT_Text, sContext.pszToken )) break;
+            if( !_CPLCreateXMLNode( psAttr, CXT_Text, sContext.pszToken ) )
+                break;
         }
 
 /* -------------------------------------------------------------------- */
@@ -807,7 +859,6 @@ end_processing_close:
 
             sContext.nStackSize--;
         }
-
 /* -------------------------------------------------------------------- */
 /*      Close the start section of a <?...?> element, and pop it        */
 /*      immediately.                                                    */
@@ -821,7 +872,8 @@ end_processing_close:
                           sContext.nInputLine );
                 break;
             }
-            else if( sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue[0] != '?' )
+            else if( sContext.papsStack[sContext.nStackSize-1].
+                         psFirstNode->pszValue[0] != '?' )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
                           "Line %d: Found '?>' without matching '<?'.",
@@ -831,7 +883,6 @@ end_processing_close:
 
             sContext.nStackSize--;
         }
-
 /* -------------------------------------------------------------------- */
 /*      Handle comments.  They are returned as a whole token with the     */
 /*      prefix and postfix omitted.  No processing of white space       */
@@ -839,28 +890,29 @@ end_processing_close:
 /* -------------------------------------------------------------------- */
         else if( sContext.eTokenType == TComment )
         {
-            CPLXMLNode *psValue = _CPLCreateXMLNode(NULL, CXT_Comment, sContext.pszToken);
-            if (!psValue) break;
+            CPLXMLNode *psValue =
+                _CPLCreateXMLNode(NULL, CXT_Comment, sContext.pszToken);
+            if( !psValue ) break;
             AttachNode( &sContext, psValue );
         }
-
 /* -------------------------------------------------------------------- */
 /*      Handle literals.  They are returned without processing.         */
 /* -------------------------------------------------------------------- */
         else if( sContext.eTokenType == TLiteral )
         {
-            CPLXMLNode *psValue = _CPLCreateXMLNode(NULL, CXT_Literal, sContext.pszToken);
-            if (!psValue) break;
+            CPLXMLNode *psValue =
+                _CPLCreateXMLNode(NULL, CXT_Literal, sContext.pszToken);
+            if( !psValue ) break;
             AttachNode( &sContext, psValue );
         }
-
 /* -------------------------------------------------------------------- */
 /*      Add a text value node as a child of the current element.        */
 /* -------------------------------------------------------------------- */
         else if( sContext.eTokenType == TString && !sContext.bInElement )
         {
-            CPLXMLNode *psValue = _CPLCreateXMLNode(NULL, CXT_Text, sContext.pszToken);
-            if (!psValue) break;
+            CPLXMLNode *psValue =
+                _CPLCreateXMLNode(NULL, CXT_Text, sContext.pszToken);
+            if( !psValue ) break;
             AttachNode( &sContext, psValue );
         }
 /* -------------------------------------------------------------------- */
@@ -869,7 +921,7 @@ end_processing_close:
         else
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                      "Parse error at line %d, unexpected token:%.500s\n",
+                      "Parse error at line %d, unexpected token:%.500s",
                       sContext.nInputLine, sContext.pszToken );
             break;
         }
@@ -882,22 +934,24 @@ end_processing_close:
         sContext.papsStack != NULL )
     {
 #ifdef DEBUG
-        /* Makes life of fuzzers easier if we accept somewhat corrupted XML */
-        /* like <x> ... */
+        // Makes life of fuzzers easier if we accept somewhat corrupted XML
+        // like <x> ...
         if( CPLTestBool(CPLGetConfigOption("CPL_MINIXML_RELAXED", "FALSE")) )
         {
-            CPLError( CE_Warning, CPLE_AppDefined,
-                    "Parse error at EOF, not all elements have been closed,\n"
-                    "starting with %.500s\n",
-                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue );
+            CPLError(CE_Warning, CPLE_AppDefined,
+                     "Parse error at EOF, not all elements have been closed, "
+                     "starting with %.500s",
+                     sContext.papsStack[sContext.nStackSize-1].
+                         psFirstNode->pszValue );
         }
         else
 #endif
         {
             CPLError( CE_Failure, CPLE_AppDefined,
-                    "Parse error at EOF, not all elements have been closed,\n"
-                    "starting with %.500s\n",
-                    sContext.papsStack[sContext.nStackSize-1].psFirstNode->pszValue );
+                      "Parse error at EOF, not all elements have been closed, "
+                      "starting with %.500s",
+                      sContext.papsStack[sContext.nStackSize-1].
+                          psFirstNode->pszValue );
         }
     }
 
@@ -915,6 +969,12 @@ end_processing_close:
         sContext.psLastNode = NULL;
     }
 
+    if( CPLGetLastErrorType() == CE_None )
+    {
+        // Restore initial error state.
+        CPLErrorSetState(eErrClass, nErrNum, osErrMsg);
+    }
+
     return sContext.psFirstNode;
 }
 
@@ -928,8 +988,9 @@ static bool _GrowBuffer( size_t nNeeded,
 {
     if( nNeeded+1 >= *pnMaxLength )
     {
-        *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
-        char* pszTextNew = (char *) VSIRealloc(*ppszText, *pnMaxLength);
+        *pnMaxLength = std::max(*pnMaxLength * 2, nNeeded + 1);
+        char* pszTextNew =
+            static_cast<char *>(VSIRealloc(*ppszText, *pnMaxLength));
         if( pszTextNew == NULL )
             return false;
         *ppszText = pszTextNew;
@@ -941,6 +1002,8 @@ static bool _GrowBuffer( size_t nNeeded,
 /*                        CPLSerializeXMLNode()                         */
 /************************************************************************/
 
+// TODO(schwehr): Rewrite this whole thing using C++ string.
+// CPLSerializeXMLNode has buffer overflows.
 static bool
 CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
                      char **ppszText, size_t *pnLength,
@@ -964,11 +1027,12 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
 /* -------------------------------------------------------------------- */
     if( psNode->eType == CXT_Text )
     {
-        char *pszEscaped = CPLEscapeString( psNode->pszValue, -1, CPLES_XML_BUT_QUOTES );
+        char *pszEscaped =
+            CPLEscapeString( psNode->pszValue, -1, CPLES_XML_BUT_QUOTES );
 
         CPLAssert( psNode->psChild == NULL );
 
-        /* Escaped text might be bigger than expected. */
+        // Escaped text might be bigger than expected.
         if( !_GrowBuffer( strlen(pszEscaped) + *pnLength,
                           ppszText, pnMaxLength ) )
         {
@@ -988,10 +1052,12 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
         CPLAssert( psNode->psChild != NULL
                    && psNode->psChild->eType == CXT_Text );
 
-        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength, " %s=\"", psNode->pszValue );
+        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength,
+                  " %s=\"", psNode->pszValue );
         *pnLength += strlen(*ppszText + *pnLength);
 
-        char *pszEscaped = CPLEscapeString( psNode->psChild->pszValue, -1, CPLES_XML );
+        char *pszEscaped =
+            CPLEscapeString( psNode->psChild->pszValue, -1, CPLES_XML );
 
         if( !_GrowBuffer( strlen(pszEscaped) + *pnLength,
                           ppszText, pnMaxLength ) )
@@ -1019,8 +1085,9 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
         for( int i = 0; i < nIndent; i++ )
             (*ppszText)[(*pnLength)++] = ' ';
 
-        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength, "<!--%s-->\n",
-                 psNode->pszValue );
+        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength,
+                  "<!--%s-->\n",
+                  psNode->pszValue );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1050,10 +1117,11 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
         *pnLength += nIndent;
         (*ppszText)[*pnLength] = '\0';
 
-        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength, "<%s", psNode->pszValue );
+        snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength,
+                  "<%s", psNode->pszValue );
 
-        /* Serialize *all* the attribute children, regardless of order */
-        CPLXMLNode *psChild;
+        // Serialize *all* the attribute children, regardless of order
+        CPLXMLNode *psChild = NULL;
         for( psChild = psNode->psChild;
              psChild != NULL;
              psChild = psChild->psNext )
@@ -1095,16 +1163,21 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
                 if( psChild->eType != CXT_Text && bJustText )
                 {
                     bJustText = false;
+                    *pnLength += strlen(*ppszText + *pnLength);
+                    if( !_GrowBuffer( 1 + *pnLength, ppszText, pnMaxLength ) )
+                        return false;
                     strcat( *ppszText + *pnLength, "\n" );
                 }
 
-                if( !CPLSerializeXMLNode( psChild, nIndent + 2, ppszText, pnLength,
+                if( !CPLSerializeXMLNode( psChild, nIndent + 2,
+                                          ppszText, pnLength,
                                           pnMaxLength ) )
                     return false;
             }
 
             *pnLength += strlen(*ppszText + *pnLength);
-            if( !_GrowBuffer( strlen(psNode->pszValue) + *pnLength + 40 + nIndent,
+            if( !_GrowBuffer( strlen(psNode->pszValue) +
+                              *pnLength + 40 + nIndent,
                               ppszText, pnMaxLength ) )
                 return false;
 
@@ -1117,7 +1190,8 @@ CPLSerializeXMLNode( const CPLXMLNode *psNode, int nIndent,
             }
 
             *pnLength += strlen(*ppszText + *pnLength);
-            snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength, "</%s>\n", psNode->pszValue );
+            snprintf( *ppszText + *pnLength, *pnMaxLength - *pnLength,
+                      "</%s>\n", psNode->pszValue );
         }
     }
 
@@ -1146,10 +1220,9 @@ char *CPLSerializeXMLTree( const CPLXMLNode *psNode )
 
 {
     size_t nMaxLength = 100;
-    char *pszText =  (char *) VSIMalloc(nMaxLength);
+    char *pszText = static_cast<char *>(CPLCalloc(nMaxLength, sizeof(char)));
     if( pszText == NULL )
         return NULL;
-    pszText[0] = '\0';
 
     size_t nLength = 0;
     for( const CPLXMLNode *psThis = psNode;
@@ -1196,8 +1269,8 @@ CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
 /* -------------------------------------------------------------------- */
 /*      Create new node.                                                */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psNode
-        = (CPLXMLNode *) CPLCalloc(sizeof(CPLXMLNode),1);
+    CPLXMLNode *psNode =
+        static_cast<CPLXMLNode *>(CPLCalloc(sizeof(CPLXMLNode), 1));
 
     psNode->eType = eType;
     psNode->pszValue = CPLStrdup( pszText );
@@ -1208,10 +1281,12 @@ CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
     if( poParent != NULL )
     {
         if( poParent->psChild == NULL )
+        {
             poParent->psChild = psNode;
+        }
         else
         {
-            CPLXMLNode  *psLink = poParent->psChild;
+            CPLXMLNode *psLink = poParent->psChild;
 
             while( psLink->psNext != NULL )
                 psLink = psLink->psNext;
@@ -1225,7 +1300,7 @@ CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
         // Coverity sometimes doesn't realize that this function is passed
         // with a non NULL parent and thinks that this branch is taken, leading
         // to creating object being leak by caller. This ugly hack hopefully
-        // makes it believe that someone will reference it...
+        // makes it believe that someone will reference it.
         psDummyStaticNode = psNode;
     }
 #endif
@@ -1240,7 +1315,8 @@ CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
 /* Same as CPLCreateXMLNode() but can return NULL in case of out-of-memory */
 /* situation */
 
-static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType,
+static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent,
+                                      CPLXMLNodeType eType,
                                       const char *pszText )
 
 {
@@ -1248,9 +1324,9 @@ static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType
 /* -------------------------------------------------------------------- */
 /*      Create new node.                                                */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode  *psNode
-        = (CPLXMLNode *) VSICalloc(sizeof(CPLXMLNode),1);
-    if (psNode == NULL)
+    CPLXMLNode *psNode =
+        static_cast<CPLXMLNode *>(VSICalloc(sizeof(CPLXMLNode), 1));
+    if( psNode == NULL )
     {
         CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate CPLXMLNode");
         return NULL;
@@ -1258,9 +1334,10 @@ static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType
 
     psNode->eType = eType;
     psNode->pszValue = VSIStrdup( pszText );
-    if (psNode->pszValue == NULL)
+    if( psNode->pszValue == NULL )
     {
-        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate psNode->pszValue");
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "Cannot allocate psNode->pszValue");
         VSIFree(psNode);
         return NULL;
     }
@@ -1274,7 +1351,7 @@ static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType
             poParent->psChild = psNode;
         else
         {
-            CPLXMLNode  *psLink = poParent->psChild;
+            CPLXMLNode *psLink = poParent->psChild;
 
             while( psLink->psNext != NULL )
                 psLink = psLink->psNext;
@@ -1302,7 +1379,7 @@ static CPLXMLNode *_CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType
 void CPLDestroyXMLNode( CPLXMLNode *psNode )
 
 {
-    while(psNode != NULL)
+    while( psNode != NULL )
     {
         if( psNode->pszValue != NULL )
             CPLFree( psNode->pszValue );
@@ -1311,12 +1388,12 @@ void CPLDestroyXMLNode( CPLXMLNode *psNode )
         {
             CPLXMLNode* psNext = psNode->psNext;
             psNode->psNext = psNode->psChild;
-            /* Move the child and its siblings as the next */
-            /* siblings of the current node */
-            if (psNext != NULL)
+            // Move the child and its siblings as the next
+            // siblings of the current node.
+            if( psNext != NULL )
             {
                 CPLXMLNode* psIter = psNode->psChild;
-                while(psIter->psNext != NULL)
+                while( psIter->psNext != NULL )
                     psIter = psIter->psNext;
                 psIter->psNext = psNext;
             }
@@ -1341,7 +1418,7 @@ void CPLDestroyXMLNode( CPLXMLNode *psNode )
  * passed in for the named element or attribute.  To search following
  * siblings as well as children, prefix the pszElement name with an equal
  * sign.  This function does an in-order traversal of the document tree.
- * So it will first match against the current node, then it's first child,
+ * So it will first match against the current node, then its first child,
  * that child's first child, and so on.
  *
  * Use CPLGetXMLNode() to find a specific child, or along a specific
@@ -1374,18 +1451,18 @@ CPLXMLNode *CPLSearchXMLNode( CPLXMLNode *psRoot, const char *pszElement )
 /* -------------------------------------------------------------------- */
     if( (psRoot->eType == CXT_Element
          || psRoot->eType == CXT_Attribute)
-        && EQUAL(pszElement,psRoot->pszValue) )
+        && EQUAL(pszElement, psRoot->pszValue) )
         return psRoot;
 
 /* -------------------------------------------------------------------- */
 /*      Search children.                                                */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psChild;
+    CPLXMLNode *psChild = NULL;
     for( psChild = psRoot->psChild; psChild != NULL; psChild = psChild->psNext)
     {
         if( (psChild->eType == CXT_Element
              || psChild->eType == CXT_Attribute)
-            && EQUAL(pszElement,psChild->pszValue) )
+            && EQUAL(pszElement, psChild->pszValue) )
             return psChild;
 
         if( psChild->psChild != NULL )
@@ -1432,7 +1509,7 @@ CPLXMLNode *CPLSearchXMLNode( CPLXMLNode *psRoot, const char *pszElement )
  * level in the subdocument.
  *
  * If the pszPath is prefixed by "=" then the search will begin with the
- * root node, and it's siblings, instead of the root nodes children.  This
+ * root node, and its siblings, instead of the root nodes children.  This
  * is particularly useful when searching within a whole document which is
  * often prefixed by one or more "junk" nodes like the <?xml> declaration.
  *
@@ -1450,10 +1527,7 @@ CPLXMLNode *CPLGetXMLNode( CPLXMLNode *psRoot, const char *pszPath )
     if( psRoot == NULL || pszPath == NULL )
         return NULL;
 
-    char        *apszTokens[2];
-    char        **papszTokens;
-    int         iToken = 0;
-    bool        bSideSearch = false;
+    bool bSideSearch = false;
 
     if( *pszPath == '=' )
     {
@@ -1461,20 +1535,19 @@ CPLXMLNode *CPLGetXMLNode( CPLXMLNode *psRoot, const char *pszPath )
         pszPath++;
     }
 
-    /* Slight optimization : avoid using CSLTokenizeStringComplex that */
-    /* does memory allocations when it is not really necessary */
-    if (strchr(pszPath, '.'))
-        papszTokens = CSLTokenizeStringComplex( pszPath, ".", FALSE, FALSE );
-    else
-    {
-        apszTokens[0] = (char*) pszPath;
-        apszTokens[1] = NULL;
-        papszTokens = apszTokens;
-    }
+    char *apszTokens[2] = { const_cast<char*>(pszPath), NULL };
+
+    // Slight optimization: avoid using CSLTokenizeStringComplex that
+    // does memory allocations when it is not really necessary.
+    char **papszTokens =
+        strchr(pszPath, '.')
+        ? CSLTokenizeStringComplex( pszPath, ".", FALSE, FALSE )
+        : apszTokens;
 
+    int iToken = 0;
     while( papszTokens[iToken] != NULL && psRoot != NULL )
     {
-        CPLXMLNode *psChild;
+        CPLXMLNode *psChild = NULL;
 
         if( bSideSearch )
         {
@@ -1487,7 +1560,7 @@ CPLXMLNode *CPLGetXMLNode( CPLXMLNode *psRoot, const char *pszPath )
         for( ; psChild != NULL; psChild = psChild->psNext )
         {
             if( psChild->eType != CXT_Text
-                && EQUAL(papszTokens[iToken],psChild->pszValue) )
+                && EQUAL(papszTokens[iToken], psChild->pszValue) )
                 break;
         }
 
@@ -1501,7 +1574,7 @@ CPLXMLNode *CPLGetXMLNode( CPLXMLNode *psRoot, const char *pszPath )
         iToken++;
     }
 
-    if (papszTokens != apszTokens)
+    if( papszTokens != apszTokens )
         CSLDestroy( papszTokens );
     return psRoot;
 }
@@ -1540,10 +1613,10 @@ const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
                             const char *pszDefault )
 
 {
-    CPLXMLNode  *psTarget;
+    CPLXMLNode *psTarget = NULL;
 
     if( pszPath == NULL || *pszPath == '\0' )
-        psTarget  = psRoot;
+        psTarget = psRoot;
     else
         psTarget = CPLGetXMLNode( psRoot, pszPath );
 
@@ -1561,7 +1634,7 @@ const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
     if( psTarget->eType == CXT_Element )
     {
         // Find first non-attribute child, and verify it is a single text
-        // with no siblings
+        // with no siblings.
 
         psTarget = psTarget->psChild;
 
@@ -1589,7 +1662,7 @@ const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
  * list, but attributes (CXT_Attribute) will be inserted after any other
  * attributes but before any other element type.  Ownership of the child
  * node is effectively assumed by the parent node.   If the child has
- * siblings (it's psNext is not NULL) they will be trimmed, but if the child
+ * siblings (its psNext is not NULL) they will be trimmed, but if the child
  * has children they are carried with it.
  *
  * @param psParent the node to attach the child to.  May not be NULL.
@@ -1617,7 +1690,7 @@ void CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
     }
 
     // Search for end of list.
-    CPLXMLNode *psSib;
+    CPLXMLNode *psSib = NULL;
     for( psSib = psParent->psChild;
          psSib->psNext != NULL;
          psSib = psSib->psNext )
@@ -1644,7 +1717,7 @@ void CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
  * \brief Remove child node from parent.
  *
  * The passed child is removed from the child list of the passed parent,
- * but the child is not destroyed.  The child retains ownership of it's
+ * but the child is not destroyed.  The child retains ownership of its
  * own children, but is cleanly removed from the child list of the parent.
  *
  * @param psParent the node to the child is attached to.
@@ -1660,7 +1733,8 @@ int CPLRemoveXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild )
     if( psParent == NULL )
         return FALSE;
 
-    CPLXMLNode *psLast = NULL, *psThis;
+    CPLXMLNode *psLast = NULL;
+    CPLXMLNode *psThis = NULL;
     for( psThis = psParent->psChild;
          psThis != NULL;
          psLast = psThis, psThis = psThis->psNext )
@@ -1746,8 +1820,8 @@ CPLXMLNode *CPLCreateXMLElementAndValue( CPLXMLNode *psParent,
                                          const char *pszValue )
 
 {
-    CPLXMLNode *psElementNode
-        = CPLCreateXMLNode( psParent, CXT_Element, pszName );
+    CPLXMLNode *psElementNode =
+        CPLCreateXMLNode( psParent, CXT_Element, pszName );
     CPLCreateXMLNode( psElementNode, CXT_Text, pszValue );
 
     return psElementNode;
@@ -1785,8 +1859,8 @@ void CPLAddXMLAttributeAndValue( CPLXMLNode *psParent,
                                  const char *pszValue )
 {
     CPLAssert(psParent != NULL);
-    CPLXMLNode *psAttributeNode
-        = CPLCreateXMLNode( psParent, CXT_Attribute, pszName );
+    CPLXMLNode *psAttributeNode =
+        CPLCreateXMLNode( psParent, CXT_Attribute, pszName );
     CPLCreateXMLNode( psAttributeNode, CXT_Text, pszValue );
 }
 
@@ -1812,8 +1886,8 @@ CPLXMLNode *CPLCloneXMLTree( CPLXMLNode *psTree )
 
     while( psTree != NULL )
     {
-        CPLXMLNode *psCopy
-            = CPLCreateXMLNode( NULL, psTree->eType, psTree->pszValue );
+        CPLXMLNode *psCopy =
+            CPLCreateXMLNode( NULL, psTree->eType, psTree->pszValue );
         if( psReturn == NULL )
             psReturn = psCopy;
         if( psPrevious != NULL )
@@ -1859,7 +1933,7 @@ CPLXMLNode *CPLCloneXMLTree( CPLXMLNode *psTree )
  * @return TRUE on success.
  */
 
-int CPLSetXMLValue( CPLXMLNode *psRoot,  const char *pszPath,
+int CPLSetXMLValue( CPLXMLNode *psRoot, const char *pszPath,
                     const char *pszValue )
 
 {
@@ -1868,7 +1942,7 @@ int CPLSetXMLValue( CPLXMLNode *psRoot,  const char *pszPath,
 
     while( papszTokens[iToken] != NULL )
     {
-        bool        bIsAttribute = false;
+        bool bIsAttribute = false;
         const char *pszName = papszTokens[iToken];
 
         if( pszName[0] == '#' )
@@ -1883,12 +1957,12 @@ int CPLSetXMLValue( CPLXMLNode *psRoot,  const char *pszPath,
             return FALSE;
         }
 
-        CPLXMLNode *psChild;
+        CPLXMLNode *psChild = NULL;
         for( psChild = psRoot->psChild; psChild != NULL;
              psChild = psChild->psNext )
         {
             if( psChild->eType != CXT_Text
-                && EQUAL(pszName,psChild->pszValue) )
+                && EQUAL(pszName, psChild->pszValue) )
                 break;
         }
 
@@ -1960,12 +2034,11 @@ void CPLStripXMLNamespace( CPLXMLNode *psRoot,
 
     while( psRoot != NULL )
     {
-
         if( psRoot->eType == CXT_Element || psRoot->eType == CXT_Attribute )
         {
             if( pszNamespace != NULL )
             {
-                if( EQUALN(pszNamespace,psRoot->pszValue,nNameSpaceLen)
+                if( EQUALN(pszNamespace, psRoot->pszValue, nNameSpaceLen)
                     && psRoot->pszValue[nNameSpaceLen] == ':' )
                 {
                     memmove(psRoot->pszValue, psRoot->pszValue+nNameSpaceLen+1,
@@ -1974,13 +2047,15 @@ void CPLStripXMLNamespace( CPLXMLNode *psRoot,
             }
             else
             {
-                const char *pszCheck;
-
-                for( pszCheck = psRoot->pszValue; *pszCheck != '\0'; pszCheck++ )
+                for( const char *pszCheck = psRoot->pszValue;
+                     *pszCheck != '\0';
+                     pszCheck++ )
                 {
                     if( *pszCheck == ':' )
                     {
-                        memmove(psRoot->pszValue, pszCheck + 1, strlen(pszCheck + 1) + 1);
+                        memmove(psRoot->pszValue,
+                                pszCheck + 1,
+                                strlen(pszCheck + 1) + 1);
                         break;
                     }
                 }
@@ -1995,7 +2070,9 @@ void CPLStripXMLNamespace( CPLXMLNode *psRoot,
             psRoot = psRoot->psNext;
         }
         else
+        {
             break;
+        }
     }
 }
 
@@ -2028,7 +2105,7 @@ CPLXMLNode *CPLParseXMLFile( const char *pszFilename )
     if( !VSIIngestFile( NULL, pszFilename, &pabyOut, NULL, -1 ) )
         return NULL;
 
-    char *pszDoc = (char*) pabyOut;
+    char *pszDoc = reinterpret_cast<char *>(pabyOut);
 
 /* -------------------------------------------------------------------- */
 /*      Parse it.                                                       */
@@ -2056,7 +2133,8 @@ CPLXMLNode *CPLParseXMLFile( const char *pszFilename )
  * @return TRUE on success, FALSE otherwise.
  */
 
-int CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree, const char *pszFilename )
+int CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree,
+                               const char *pszFilename )
 
 {
 /* -------------------------------------------------------------------- */
@@ -2066,7 +2144,7 @@ int CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree, const char *pszFilename
     if( pszDoc == NULL )
         return FALSE;
 
-    vsi_l_offset nLength = strlen(pszDoc);
+    const vsi_l_offset nLength = strlen(pszDoc);
 
 /* -------------------------------------------------------------------- */
 /*      Create file.                                                    */
@@ -2083,7 +2161,7 @@ int CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree, const char *pszFilename
 /* -------------------------------------------------------------------- */
 /*      Write file.                                                     */
 /* -------------------------------------------------------------------- */
-    if( VSIFWriteL( pszDoc, 1, (size_t)nLength, fp ) != nLength )
+    if( VSIFWriteL(pszDoc, 1, static_cast<size_t>(nLength), fp ) != nLength )
     {
         CPLError( CE_Failure, CPLE_FileIO,
                   "Failed to write whole XML document (%.500s).",
@@ -2096,7 +2174,7 @@ int CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree, const char *pszFilename
 /* -------------------------------------------------------------------- */
 /*      Cleanup                                                         */
 /* -------------------------------------------------------------------- */
-    int bRet = VSIFCloseL( fp ) == 0;
+    const bool bRet = VSIFCloseL( fp ) == 0;
     if( !bRet )
     {
         CPLError( CE_Failure, CPLE_FileIO,
@@ -2136,7 +2214,7 @@ void CPLCleanXMLElementName( char *pszTarget )
         if( (*((unsigned char *) pszTarget) & 0x80) || isalnum( *pszTarget )
             || *pszTarget == '_' || *pszTarget == '.' )
         {
-            /* ok */
+            // Ok.
         }
         else
         {
diff --git a/port/cpl_minixml.h b/port/cpl_minixml.h
index 3b53e13..d9fc46c 100644
--- a/port/cpl_minixml.h
+++ b/port/cpl_minixml.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_minixml.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cpl_minixml.h 35921 2016-10-25 02:28:29Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Declarations for MiniXML Handler.
@@ -40,6 +40,7 @@
 
 CPL_C_START
 
+/** XML node type */
 typedef enum
 {
     /*! Node is an element */           CXT_Element = 0,
@@ -117,7 +118,6 @@ typedef struct CPLXMLNode
     struct CPLXMLNode  *psChild;
 } CPLXMLNode;
 
-
 CPLXMLNode CPL_DLL *CPLParseXMLString( const char * );
 void       CPL_DLL  CPLDestroyXMLNode( CPLXMLNode * );
 CPLXMLNode CPL_DLL *CPLGetXMLNode( CPLXMLNode *poRoot,
@@ -158,19 +158,27 @@ int        CPL_DLL CPLSerializeXMLTreeToFile( const CPLXMLNode *psTree,
 CPL_C_END
 
 #ifdef __cplusplus
-// Manage a tree of XML nodes so that all nodes are freed when the instance goes
-// out of scope.  Only the top level node should be in a CPLXMLTreeCloser.
+/** Manage a tree of XML nodes so that all nodes are freed when the instance goes
+ * out of scope.  Only the top level node should be in a CPLXMLTreeCloser.
+ */
 class CPLXMLTreeCloser {
  public:
+  /** Constructor */
   explicit CPLXMLTreeCloser(CPLXMLNode* data) { the_data_ = data; }
 
+  /** Destructor */
   ~CPLXMLTreeCloser() {
     if (the_data_) CPLDestroyXMLNode(the_data_);
   }
 
-  // Modifying the contents pointed to by the return is allowed.
+  /** Returns the node pointer/
+   * Modifying the contents pointed to by the return is allowed.
+   * @return the node pointer */
   CPLXMLNode* get() const { return the_data_; }
 
+  /** Returns the node pointer/
+   * Modifying the contents pointed to by the return is allowed.
+   * @return the node pointer */
   CPLXMLNode* operator->() const { return get(); }
 
  private:
diff --git a/port/cpl_minizip_ioapi.cpp b/port/cpl_minizip_ioapi.cpp
index 8ba44d1..2f19dfe 100644
--- a/port/cpl_minizip_ioapi.cpp
+++ b/port/cpl_minizip_ioapi.cpp
@@ -9,7 +9,6 @@
    Original licence available in port/LICENCE_minizip
 */
 
-
 /* ioapi.c -- IO base function header for compress/uncompress .zip
    files using zlib + zip or unzip API
 
@@ -18,17 +17,27 @@
    Copyright (C) 1998-2005 Gilles Vollant
 */
 
-#include "cpl_vsi.h"
+#include "cpl_port.h"
+#include "cpl_minizip_ioapi.h"
 
+#include <cstddef>
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
 
-#include "zlib.h"
 #include "cpl_minizip_ioapi.h"
+#include "cpl_vsi.h"
+#include "zconf.h"
+#include "zlib.h"
+
+CPL_CVSID("$Id: cpl_minizip_ioapi.cpp 37090 2017-01-10 17:24:54Z rouault $");
 
 static
-voidpf ZCALLBACK fopen_file_func (CPL_UNUSED voidpf opaque, const char* filename, int mode)
+voidpf ZCALLBACK fopen_file_func ( voidpf /* opaque */ ,
+                                   const char* filename, int mode )
 {
     VSILFILE* file = NULL;
     const char* mode_fopen = NULL;
@@ -39,7 +48,11 @@ voidpf ZCALLBACK fopen_file_func (CPL_UNUSED voidpf opaque, const char* filename
         mode_fopen = "r+b";
     else
     if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+    {
         mode_fopen = "wb";
+        if( filename != NULL )
+            return VSIFOpenExL(filename, mode_fopen, true);
+    }
 
     if ((filename!=NULL) && (mode_fopen != NULL))
         file = VSIFOpenL(filename, mode_fopen);
@@ -47,23 +60,27 @@ voidpf ZCALLBACK fopen_file_func (CPL_UNUSED voidpf opaque, const char* filename
 }
 
 static
-uLong ZCALLBACK fread_file_func (CPL_UNUSED voidpf opaque, voidpf stream, void* buf, uLong size)
+uLong ZCALLBACK fread_file_func ( voidpf /* opaque */, voidpf stream,
+                                  void* buf, uLong size )
 {
-    uLong ret;
-    ret = (uLong)VSIFReadL(buf, 1, (size_t)size, (VSILFILE *)stream);
+    uLong ret =
+        static_cast<uLong>(VSIFReadL(buf, 1, static_cast<size_t>(size),
+                                     static_cast<VSILFILE *>(stream)));
     return ret;
 }
 
 static
-uLong ZCALLBACK fwrite_file_func (CPL_UNUSED voidpf opaque, voidpf stream, const void* buf, uLong size)
+uLong ZCALLBACK fwrite_file_func ( voidpf /* opaque */, voidpf stream,
+                                   const void* buf, uLong size )
 {
-    uLong ret;
-    ret = (uLong)VSIFWriteL(buf, 1, (size_t)size, (VSILFILE *)stream);
+    uLong ret =
+        static_cast<uLong>(VSIFWriteL(buf, 1, static_cast<size_t>(size),
+                                      static_cast<VSILFILE *>(stream)));
     return ret;
 }
 
 static
-uLong64 ZCALLBACK ftell_file_func (CPL_UNUSED voidpf opaque, voidpf stream)
+uLong64 ZCALLBACK ftell_file_func ( voidpf /* opaque */, voidpf stream )
 {
     uLong64 ret;
     ret = VSIFTellL((VSILFILE *)stream);
@@ -71,7 +88,8 @@ uLong64 ZCALLBACK ftell_file_func (CPL_UNUSED voidpf opaque, voidpf stream)
 }
 
 static
-long ZCALLBACK fseek_file_func (CPL_UNUSED voidpf  opaque, voidpf stream, uLong64 offset, int origin)
+long ZCALLBACK fseek_file_func ( voidpf /* opaque */, voidpf stream,
+                                 uLong64 offset, int origin )
 {
     int fseek_origin=0;
     switch (origin)
@@ -91,18 +109,15 @@ long ZCALLBACK fseek_file_func (CPL_UNUSED voidpf  opaque, voidpf stream, uLong6
 }
 
 static
-int ZCALLBACK fclose_file_func (CPL_UNUSED voidpf opaque, voidpf stream)
+int ZCALLBACK fclose_file_func ( voidpf /* opaque */, voidpf stream )
 {
     return VSIFCloseL((VSILFILE *)stream);
 }
 
 static
-int ZCALLBACK ferror_file_func (CPL_UNUSED voidpf opaque,
-                                CPL_UNUSED voidpf stream)
+int ZCALLBACK ferror_file_func ( voidpf /* opaque */, voidpf /* stream */ )
 {
-    // int ret;
-    // ret = 0; // FIXME
-    //ret = ferror((FILE *)stream);
+    // ret = ferror((FILE *)stream);
     return 0;
 }
 
diff --git a/port/cpl_minizip_ioapi.h b/port/cpl_minizip_ioapi.h
index 15f188d..b0fd4b7 100644
--- a/port/cpl_minizip_ioapi.h
+++ b/port/cpl_minizip_ioapi.h
@@ -1,3 +1,5 @@
+/* $Id: cpl_minizip_ioapi.h 36484 2016-11-24 06:35:54Z goatbar $ */
+
 /* Modified version by Even Rouault. :
       - change fill_fopen_filefunc to cpl_fill_fopen_filefunc
       - Add support for ZIP64
@@ -18,7 +20,11 @@
 #ifndef CPL_MINIZIP_IOAPI_H_INCLUDED
 #define CPL_MINIZIP_IOAPI_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "cpl_vsi.h"
+#include "zlib.h"
+
 #define uLong64 vsi_l_offset
 
 #define ZLIB_FILEFUNC_SEEK_CUR (1)
@@ -74,9 +80,10 @@ void cpl_fill_fopen_filefunc (zlib_filefunc_def* pzlib_filefunc_def);
 #define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
 #define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
 
-
 #ifdef __cplusplus
 }
 #endif
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* CPL_MINIZIP_IOAPI_H_INCLUDED */
diff --git a/port/cpl_minizip_unzip.cpp b/port/cpl_minizip_unzip.cpp
index d8c56b8..d0352d3 100644
--- a/port/cpl_minizip_unzip.cpp
+++ b/port/cpl_minizip_unzip.cpp
@@ -13,7 +13,6 @@
    Original licence available in port/LICENCE_minizip
 */
 
-
 /* unzip.c -- IO for uncompress .zip files using zlib
    Version 1.01e, February 12th, 2005
 
@@ -50,23 +49,24 @@ woven in by Terry Thorsen 1/2003.
   version without encryption capabilities).
  */
 
+#include "cpl_port.h"
+#include "cpl_minizip_unzip.h"
 
-#include <cstdio>
+#include <cstddef>
 #include <cstdlib>
 #include <cstring>
 
-#include "zlib.h"
-#include "cpl_minizip_unzip.h"
+#include "cpl_conv.h"
 #include "cpl_string.h"
 
-#include <cstddef>
-
 #ifdef NO_ERRNO_H
     extern int errno;
 #else
 #   include <errno.h>
 #endif
 
+CPL_CVSID("$Id: cpl_minizip_unzip.cpp 37003 2016-12-23 14:54:07Z goatbar $");
+
 #ifndef CASESENSITIVITYDEFAULT_NO
 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
 #    define CASESENSITIVITYDEFAULT_NO
@@ -91,7 +91,6 @@ woven in by Terry Thorsen 1/2003.
 #define SIZECENTRALDIRITEM (0x2e)
 #define SIZEZIPLOCALHEADER (0x1e)
 
-
 const char unz_copyright[] =
    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
 
@@ -101,7 +100,6 @@ typedef struct unz_file_info_internal_s
     uLong64 offset_curfile;/* relative offset of local header 4 bytes */
 } unz_file_info_internal;
 
-
 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
     when reading and decompress it */
 typedef struct
@@ -127,7 +125,6 @@ typedef struct
     int   raw;
 } file_in_zip_read_info_s;
 
-
 /* unz_s contain internal information about the zipfile
 */
 typedef struct
@@ -159,7 +156,6 @@ typedef struct
 #    endif
 } unz_s;
 
-
 #ifndef NOUNCRYPT
 #include "crypt.h"
 #endif
@@ -170,14 +166,15 @@ typedef struct
    IN assertion: the stream s has been successfully opened for reading.
 */
 
-
-static int unzlocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream, int *pi)
+static int unzlocal_getByte( const zlib_filefunc_def* pzlib_filefunc_def,
+                             voidpf filestream, int *pi )
 {
     unsigned char c = 0;
-    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+    const int err =
+        static_cast<int>(ZREAD(*pzlib_filefunc_def, filestream, &c, 1));
     if (err==1)
     {
-        *pi = (int)c;
+        *pi = static_cast<int>(c);
         return UNZ_OK;
     }
     else
@@ -189,7 +186,6 @@ static int unzlocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def, voidpf
     }
 }
 
-
 /* ===========================================================================
    Reads a long in LSB order from the given gz_stream. Sets
 */
@@ -197,7 +193,7 @@ static int unzlocal_getShort (const zlib_filefunc_def* pzlib_filefunc_def,
                              voidpf filestream,
                              uLong *pX)
 {
-    uLong x ;
+    uLong x;
     int i = 0;
     int err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
@@ -217,7 +213,7 @@ static int unzlocal_getLong (const zlib_filefunc_def* pzlib_filefunc_def,
                             voidpf filestream,
                             uLong *pX)
 {
-    uLong x ;
+    uLong x;
     int i = 0;
     int err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong)i;
@@ -245,7 +241,7 @@ static int unzlocal_getLong64 (const zlib_filefunc_def* pzlib_filefunc_def,
                             voidpf filestream,
                             uLong64 *pX)
 {
-    uLong64 x ;
+    uLong64 x;
     int i = 0;
     int err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
     x = (uLong64)i;
@@ -307,7 +303,6 @@ static int strcmpcasenosensitive_internal (const char* fileName1, const char* fi
     }
 }
 
-
 #ifdef  CASESENSITIVITYDEFAULT_NO
 #define CASESENSITIVITYDEFAULTVALUE 2
 #else
@@ -361,7 +356,6 @@ static uLong64 unzlocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc
     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
         return 0;
 
-
     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
 
     if (uMaxBack>uSizeFile)
@@ -375,22 +369,24 @@ static uLong64 unzlocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc
     while (uBackRead<uMaxBack)
     {
         uLong uReadSize;
-        uLong64 uReadPos ;
+        uLong64 uReadPos;
         if (uBackRead+BUFREADCOMMENT>uMaxBack)
             uBackRead = uMaxBack;
         else
             uBackRead+=BUFREADCOMMENT;
-        uReadPos = uSizeFile-uBackRead ;
+        uReadPos = uSizeFile-uBackRead;
 
         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
-        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        if( ZSEEK(*pzlib_filefunc_def, filestream, uReadPos,
+                  ZLIB_FILEFUNC_SEEK_SET) != 0 )
             break;
 
         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
             break;
 
-        for( int i=(int)uReadSize-3; (i--)>0;)
+        // TODO(schwehr): Fix where the decrement is in this for loop.
+        for( int i = static_cast<int>(uReadSize)  -3; (i--) > 0; )
             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
             {
@@ -405,13 +401,13 @@ static uLong64 unzlocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc
     return uPosFound;
 }
 
-
 /*
   Locate the Central directory 64 of a zipfile (at the end, just before
     the global comment)
 */
-static uLong64 unzlocal_SearchCentralDir64(const zlib_filefunc_def* pzlib_filefunc_def,
-                                      voidpf filestream)
+static uLong64
+unzlocal_SearchCentralDir64( const zlib_filefunc_def* pzlib_filefunc_def,
+                             voidpf filestream )
 {
     unsigned char* buf;
     uLong64 uSizeFile;
@@ -423,7 +419,6 @@ static uLong64 unzlocal_SearchCentralDir64(const zlib_filefunc_def* pzlib_filefu
     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
         return 0;
 
-
     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
 
     if (uMaxBack>uSizeFile)
@@ -442,7 +437,7 @@ static uLong64 unzlocal_SearchCentralDir64(const zlib_filefunc_def* pzlib_filefu
             uBackRead = uMaxBack;
         else
             uBackRead+=BUFREADCOMMENT;
-        uReadPos = uSizeFile-uBackRead ;
+        uReadPos = uSizeFile-uBackRead;
 
         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
@@ -452,7 +447,7 @@ static uLong64 unzlocal_SearchCentralDir64(const zlib_filefunc_def* pzlib_filefu
         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
             break;
 
-        for( int i=(int)uReadSize-3; (i--)>0; )
+        for( int i =static_cast<int>(uReadSize) - 3; (i--) > 0; )
             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
                 ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
             {
@@ -534,6 +529,8 @@ extern unzFile ZEXPORT cpl_unzOpen2 (const char *path,
 
     int err=UNZ_OK;
 
+    // Must be a trick to ensure that unz_copyright remains in the binary!
+    // cppcheck-suppress knownConditionTrueFalse
     if (unz_copyright[0]!=' ')
         return NULL;
 
@@ -557,8 +554,6 @@ extern unzFile ZEXPORT cpl_unzOpen2 (const char *path,
 
         us.isZip64 = 1;
 
-        //printf("ZIP64 file !\n");
-
         if (ZSEEK(us.z_filefunc, us.filestream,
                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
         err=UNZ_ERRNO;
@@ -691,7 +686,6 @@ extern unzFile ZEXPORT cpl_unzOpen2 (const char *path,
     return (unzFile)s;
 }
 
-
 extern unzFile ZEXPORT cpl_unzOpen (const char *path)
 {
     return cpl_unzOpen2(path, NULL);
@@ -717,7 +711,6 @@ extern int ZEXPORT cpl_unzClose (unzFile file)
     return UNZ_OK;
 }
 
-
 /*
   Write info about the ZipFile in the *pglobal_info structure.
   No preparation of the structure is needed
@@ -732,7 +725,6 @@ extern int ZEXPORT cpl_unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_
     return UNZ_OK;
 }
 
-
 /*
    Translate date/time from Dos format to tm_unz (readable more easily).
 */
@@ -740,28 +732,29 @@ static void unzlocal_DosDateToTmuDate (uLong64 ulDosDate, tm_unz* ptm)
 {
     uLong64 uDate;
     uDate = (uLong64)(ulDosDate>>16);
-    ptm->tm_mday = (uInt)(uDate&0x1f) ;
-    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
-    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+    ptm->tm_mday = (uInt)(uDate&0x1f);
+    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1);
+    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980);
 
     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
-    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
-    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
+    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20);
+    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f));
 }
 
 /*
   Get Info about the current file in the zipfile, with internal only info
 */
-static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
-                                               unz_file_info *pfile_info,
-                                               unz_file_info_internal
-                                               *pfile_info_internal,
-                                               char *szFileName,
-                                               uLong fileNameBufferSize,
-                                               CPL_UNUSED void *extraField,
-                                               CPL_UNUSED uLong extraFieldBufferSize,
-                                               CPL_UNUSED char *szComment,
-                                               CPL_UNUSED uLong commentBufferSize)
+static int unzlocal_GetCurrentFileInfoInternal (
+    unzFile file,
+    unz_file_info *pfile_info,
+    unz_file_info_internal
+    *pfile_info_internal,
+    char *szFileName,
+    uLong fileNameBufferSize,
+    void * /* extraField */,
+    uLong /* extraFieldBufferSize */,
+    char * /* szComment */,
+    uLong /* commentBufferSize */ )
 {
     unz_s* s;
     unz_file_info file_info;
@@ -780,7 +773,6 @@ static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
               ZLIB_FILEFUNC_SEEK_SET)!=0)
         err=UNZ_ERRNO;
 
-
     /* we check the magic */
     if (err==UNZ_OK)
     {
@@ -843,7 +835,7 @@ static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
     lSeek+=file_info.size_filename;
     if ((err==UNZ_OK) && (szFileName!=NULL))
     {
-        uLong uSizeRead ;
+        uLong uSizeRead;
         if (file_info.size_filename<fileNameBufferSize)
         {
             *(szFileName+file_info.size_filename)='\0';
@@ -863,7 +855,7 @@ static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
 #if 0
     if ((err==UNZ_OK) && (extraField!=NULL))
     {
-        uLong64 uSizeRead ;
+        uLong64 uSizeRead;
         if (file_info.size_file_extra<extraFieldBufferSize)
             uSizeRead = file_info.size_file_extra;
         else
@@ -968,7 +960,7 @@ static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
                     if( nameCRC32 == crc32(0, (const Bytef*)szFileName, static_cast<uInt>(file_info.size_filename)) )
                     {
                         uLong utf8Size = dataSize - 1 - 4;
-                        uLong uSizeRead ;
+                        uLong uSizeRead;
 
                         bHasUTF8Filename = true;
 
@@ -1028,7 +1020,7 @@ static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
 #if 0
     if ((err==UNZ_OK) && (szComment!=NULL))
     {
-        uLong64 uSizeRead ;
+        uLong64 uSizeRead;
         if (file_info.size_file_comment<commentBufferSize)
         {
             *(szComment+file_info.size_file_comment)='\0';
@@ -1063,8 +1055,6 @@ static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
     return err;
 }
 
-
-
 /*
   Write info about the ZipFile in the *pglobal_info structure.
   No preparation of the structure is needed
@@ -1121,7 +1111,7 @@ extern int ZEXPORT cpl_unzGoToNextFile (unzFile  file)
         return UNZ_END_OF_LIST_OF_FILE;
 
     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
-            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
     s->num_file++;
     int err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
                                                &s->cur_file_info_internal,
@@ -1130,7 +1120,6 @@ extern int ZEXPORT cpl_unzGoToNextFile (unzFile  file)
     return err;
 }
 
-
 /*
   Try locate the file szFileName in the zipfile.
   For the iCaseSensitivity signification, see unzipStringFileNameCompare
@@ -1151,7 +1140,6 @@ extern int ZEXPORT cpl_unzLocateFile (unzFile file, const char *szFileName, int
     uLong64 num_fileSaved;
     uLong64 pos_in_central_dirSaved;
 
-
     if (file==NULL)
         return UNZ_PARAMERROR;
 
@@ -1188,14 +1176,13 @@ extern int ZEXPORT cpl_unzLocateFile (unzFile file, const char *szFileName, int
     /* We failed, so restore the state of the 'current file' to where we
      * were.
      */
-    s->num_file = num_fileSaved ;
-    s->pos_in_central_dir = pos_in_central_dirSaved ;
+    s->num_file = num_fileSaved;
+    s->pos_in_central_dir = pos_in_central_dirSaved;
     s->cur_file_info = cur_file_infoSaved;
     s->cur_file_info_internal = cur_file_info_internalSaved;
     return err;
 }
 
-
 /*
 ///////////////////////////////////////////
 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
@@ -1280,7 +1267,6 @@ static int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar,
                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
         return UNZ_ERRNO;
 
-
     if (err==UNZ_OK)
     {
         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
@@ -1328,7 +1314,6 @@ static int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar,
                               ((uFlags & 8)==0))
         err=UNZ_BADZIPFILE;
 
-
     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
         err=UNZ_ERRNO;
     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
@@ -1385,7 +1370,8 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file, int* method,
     if (pfile_in_zip_read_info==NULL)
         return UNZ_INTERNALERROR;
 
-    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+    pfile_in_zip_read_info->read_buffer =
+        static_cast<char *>(ALLOC(UNZ_BUFSIZE));
     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
     pfile_in_zip_read_info->pos_local_extrafield=0;
@@ -1400,7 +1386,7 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file, int* method,
     pfile_in_zip_read_info->stream_initialised=0;
 
     if (method!=NULL)
-        *method = (int)s->cur_file_info.compression_method;
+        *method = static_cast<int>(s->cur_file_info.compression_method);
 
     if (level!=NULL)
     {
@@ -1453,10 +1439,9 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file, int* method,
          */
     }
     pfile_in_zip_read_info->rest_read_compressed =
-            s->cur_file_info.compressed_size ;
+            s->cur_file_info.compressed_size;
     pfile_in_zip_read_info->rest_read_uncompressed =
-            s->cur_file_info.uncompressed_size ;
-
+            s->cur_file_info.uncompressed_size;
 
     pfile_in_zip_read_info->pos_in_zipfile =
             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
@@ -1487,7 +1472,6 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file, int* method,
     }
 #    endif
 
-
     return UNZ_OK;
 }
 
@@ -1514,10 +1498,10 @@ extern uLong64 ZEXPORT cpl_unzGetCurrentFileZStreamPos( unzFile file)
     file_in_zip_read_info_s* pfile_in_zip_read_info;
     s=(unz_s*)file;
     if (file==NULL)
-        return 0; //UNZ_PARAMERROR;
+        return 0;  // UNZ_PARAMERROR;
     pfile_in_zip_read_info=s->pfile_in_zip_read;
     if (pfile_in_zip_read_info==NULL)
-        return 0; //UNZ_PARAMERROR;
+        return 0;  // UNZ_PARAMERROR;
     return pfile_in_zip_read_info->pos_in_zipfile +
                          pfile_in_zip_read_info->byte_before_the_zipfile;
 }
@@ -1548,7 +1532,6 @@ extern int ZEXPORT cpl_unzReadCurrentFile  (unzFile file, voidp buf, unsigned le
     if (pfile_in_zip_read_info==NULL)
         return UNZ_PARAMERROR;
 
-
     if (pfile_in_zip_read_info->read_buffer == NULL)
         return UNZ_END_OF_LIST_OF_FILE;
     if (len==0)
@@ -1592,7 +1575,6 @@ extern int ZEXPORT cpl_unzReadCurrentFile  (unzFile file, voidp buf, unsigned le
                       uReadThis)!=uReadThis)
                 return UNZ_ERRNO;
 
-
 #            ifndef NOUNCRYPT
             if(s->encrypted)
             {
@@ -1604,7 +1586,6 @@ extern int ZEXPORT cpl_unzReadCurrentFile  (unzFile file, voidp buf, unsigned le
             }
 #            endif
 
-
             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
 
             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
@@ -1616,7 +1597,7 @@ extern int ZEXPORT cpl_unzReadCurrentFile  (unzFile file, voidp buf, unsigned le
 
         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
         {
-            uInt uDoCopy,i ;
+            uInt uDoCopy, i;
 
             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
                 (pfile_in_zip_read_info->rest_read_compressed == 0))
@@ -1624,9 +1605,9 @@ extern int ZEXPORT cpl_unzReadCurrentFile  (unzFile file, voidp buf, unsigned le
 
             if (pfile_in_zip_read_info->stream.avail_out <
                             pfile_in_zip_read_info->stream.avail_in)
-                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+                uDoCopy = pfile_in_zip_read_info->stream.avail_out;
             else
-                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+                uDoCopy = pfile_in_zip_read_info->stream.avail_in;
 
             for (i=0;i<uDoCopy;i++)
                 *(pfile_in_zip_read_info->stream.next_out+i) =
@@ -1688,7 +1669,6 @@ extern int ZEXPORT cpl_unzReadCurrentFile  (unzFile file, voidp buf, unsigned le
     return err;
 }
 
-
 /*
   Give the current position in uncompressed data
 */
@@ -1707,7 +1687,6 @@ extern z_off_t ZEXPORT cpl_unztell (unzFile file)
     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
 }
 
-
 /*
   return 1 if the end of file was reached, 0 elsewhere
 */
@@ -1729,8 +1708,6 @@ extern int ZEXPORT cpl_unzeof (unzFile file)
         return 0;
 }
 
-
-
 /*
   Read extra field from the current file (opened by unzOpenCurrentFile)
   This is the local-header version of the extra field (sometimes, there is
@@ -1743,7 +1720,8 @@ extern int ZEXPORT cpl_unzeof (unzFile file)
   the return value is the number of bytes copied in buf, or (if <0)
     the error code
 */
-extern int ZEXPORT cpl_unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
+extern int ZEXPORT cpl_unzGetLocalExtrafield ( unzFile file, voidp buf,
+                                               unsigned len )
 {
     unz_s* s;
     file_in_zip_read_info_s* pfile_in_zip_read_info;
@@ -1762,12 +1740,12 @@ extern int ZEXPORT cpl_unzGetLocalExtrafield (unzFile file, voidp buf, unsigned
                 pfile_in_zip_read_info->pos_local_extrafield);
 
     if (buf==NULL)
-        return (int)size_to_read;
+      return static_cast<int>(size_to_read);
 
     if (len>size_to_read)
-        read_now = (uInt)size_to_read;
+        read_now = static_cast<uInt>(size_to_read);
     else
-        read_now = (uInt)len ;
+      read_now = static_cast<uInt>(len);
 
     if (read_now==0)
         return 0;
@@ -1784,7 +1762,7 @@ extern int ZEXPORT cpl_unzGetLocalExtrafield (unzFile file, voidp buf, unsigned
               buf,read_now)!=read_now)
         return UNZ_ERRNO;
 
-    return (int)read_now;
+    return static_cast<int>(read_now);
 }
 
 /*
@@ -1805,7 +1783,6 @@ extern int ZEXPORT cpl_unzCloseCurrentFile (unzFile file)
     if (pfile_in_zip_read_info==NULL)
         return UNZ_PARAMERROR;
 
-
     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
         (!pfile_in_zip_read_info->raw))
     {
@@ -1813,7 +1790,6 @@ extern int ZEXPORT cpl_unzCloseCurrentFile (unzFile file)
             err=UNZ_CRCERROR;
     }
 
-
     TRYFREE(pfile_in_zip_read_info->read_buffer);
     pfile_in_zip_read_info->read_buffer = NULL;
     if (pfile_in_zip_read_info->stream_initialised)
@@ -1827,7 +1803,6 @@ extern int ZEXPORT cpl_unzCloseCurrentFile (unzFile file)
     return err;
 }
 
-
 /*
   Get the global comment string of the ZipFile, in the szComment buffer.
   uSizeBuf is the size of the szComment buffer.
@@ -1837,7 +1812,7 @@ extern int ZEXPORT cpl_unzGetGlobalComment (unzFile file, char * szComment, uLon
 {
     /* int err=UNZ_OK; */
     unz_s* s;
-    uLong uReadThis ;
+    uLong uReadThis;
     if (file==NULL)
         return UNZ_PARAMERROR;
     s=(unz_s*)file;
@@ -1858,16 +1833,16 @@ extern int ZEXPORT cpl_unzGetGlobalComment (unzFile file, char * szComment, uLon
 
     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
         *(szComment+s->gi.size_comment)='\0';
-    return (int)uReadThis;
+    return static_cast<int>(uReadThis);
 }
 
-/* Additions by RX '2004 */
+// Additions by RX '2004.
 extern uLong64 ZEXPORT cpl_unzGetOffset (unzFile file)
 {
     unz_s* s;
 
     if (file==NULL)
-          return 0; //UNZ_PARAMERROR;
+          return 0;  // UNZ_PARAMERROR;
     s=(unz_s*)file;
     if (!s->current_file_ok)
       return 0;
diff --git a/port/cpl_minizip_unzip.h b/port/cpl_minizip_unzip.h
index b02d830..f210918 100644
--- a/port/cpl_minizip_unzip.h
+++ b/port/cpl_minizip_unzip.h
@@ -1,3 +1,4 @@
+/* $Id: cpl_minizip_unzip.h 35921 2016-10-25 02:28:29Z goatbar $ */
 /* Modified version by Even Rouault. :
      - Addition of cpl_unzGetCurrentFileZStreamPos
      - Decoration of symbol names unz* -> cpl_unz*
@@ -21,7 +22,6 @@
    Encryption compatible with pkzip 2.04g only supported
    Old compressions used by old PKZip 1.x are not supported
 
-
    I WAIT FEEDBACK at mail info at winimage.com
    Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
 
@@ -42,8 +42,6 @@
   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original software.
   3. This notice may not be removed or altered from any source distribution.
-
-
 */
 
 /* for more info about .ZIP format, see
@@ -56,6 +54,8 @@
 #ifndef CPL_MINIZIP_UNZIP_H_INCLUDED
 #define CPL_MINIZIP_UNZIP_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "cpl_vsi.h"
 #define uLong64 vsi_l_offset
 
@@ -85,7 +85,6 @@ typedef unzFile__ *unzFile;
 typedef voidp unzFile;
 #endif
 
-
 #define UNZ_OK                          (0)
 #define UNZ_END_OF_LIST_OF_FILE         (-100)
 #define UNZ_ERRNO                       (Z_ERRNO)
@@ -115,7 +114,6 @@ typedef struct unz_global_info_s
     uLong size_comment;         /* size of the global comment of the zipfile */
 } unz_global_info;
 
-
 /* unz_file_info contain information about a file in the zipfile */
 typedef struct unz_file_info_s
 {
@@ -150,7 +148,6 @@ extern int ZEXPORT cpl_unzStringFileNameCompare (const char* fileName1,
     (like 1 on Unix, 2 on Windows)
 */
 
-
 extern unzFile ZEXPORT cpl_unzOpen (const char *path);
 /*
   Open a Zip file. path contain the full pathname (by example,
@@ -183,7 +180,6 @@ extern int ZEXPORT cpl_unzGetGlobalInfo (unzFile file,
   No preparation of the structure is needed
   return UNZ_OK if there is no problem. */
 
-
 extern int ZEXPORT cpl_unzGetGlobalComment (unzFile file,
                                             char *szComment,
                                             uLong uSizeBuf);
@@ -193,7 +189,6 @@ extern int ZEXPORT cpl_unzGetGlobalComment (unzFile file,
   return the number of byte copied or an error code <0
 */
 
-
 /***************************************************************************/
 /* Unzip package allow you browse the directory of the zipfile */
 
@@ -222,7 +217,6 @@ extern int ZEXPORT cpl_unzLocateFile (unzFile file,
   UNZ_END_OF_LIST_OF_FILE if the file is not found
 */
 
-
 /* ****************************************** */
 /* Ryan supplied functions */
 /* unz_file_info contain information about a file in the zipfile */
@@ -263,14 +257,12 @@ extern int ZEXPORT cpl_unzGetCurrentFileInfo (unzFile file,
             (commentBufferSize is the size of the buffer)
 */
 
-
 /** Addition for GDAL : START */
 
 extern uLong64 ZEXPORT cpl_unzGetCurrentFileZStreamPos (unzFile file);
 
 /** Addition for GDAL : END */
 
-
 /***************************************************************************/
 /* for reading the content of the current zipfile, you can open it, read data
    from it, and close it (you can close it before reading all the file)
@@ -317,7 +309,6 @@ extern int ZEXPORT cpl_unzOpenCurrentFile3 (unzFile file,
          but you CANNOT set method parameter as NULL
 */
 
-
 extern int ZEXPORT cpl_unzCloseCurrentFile (unzFile file);
 /*
   Close the file in zip opened with unzOpenCurrentFile
@@ -372,10 +363,10 @@ extern uLong64 ZEXPORT cpl_unzGetOffset (unzFile file);
 /* Set the current file offset */
 extern int ZEXPORT cpl_unzSetOffset (unzFile file, uLong64 pos);
 
-
-
 #ifdef __cplusplus
 }
 #endif
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* CPL_MINIZIP_UNZIP_H_INCLUDED */
diff --git a/port/cpl_minizip_zip.cpp b/port/cpl_minizip_zip.cpp
index fda7b88..be69357 100644
--- a/port/cpl_minizip_zip.cpp
+++ b/port/cpl_minizip_zip.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_minizip_zip.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -27,25 +26,29 @@
    Read zip.h for more info
 */
 
+#include "cpl_port.h"
+#include "cpl_minizip_zip.h"
 
-#include <cstdio>
+#include <cstddef>
 #include <cstdlib>
 #include <cstring>
-#include <ctime>
-#include "zlib.h"
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
 #include "cpl_conv.h"
-#include "cpl_minizip_zip.h"
-#include "cpl_port.h"
+#include "cpl_error.h"
+#include "cpl_minizip_unzip.h"
 #include "cpl_string.h"
 
-#include <cstddef>
-
 #ifdef NO_ERRNO_H
     extern int errno;
 #else
 #   include <errno.h>
 #endif
 
+CPL_CVSID("$Id: cpl_minizip_zip.cpp 36909 2016-12-16 18:47:29Z goatbar $");
+
 #ifndef VERSIONMADEBY
 # define VERSIONMADEBY   (0x0) /* platform dependent */
 #endif
@@ -88,9 +91,8 @@
 #endif
 #endif
 
-CPL_UNUSED const char zip_copyright[] =
-   " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
-
+CPL_UNUSED static const char zip_copyright[] =
+    " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
 
 #define SIZEDATA_INDATABLOCK (4096-(4*4))
 
@@ -118,7 +120,6 @@ typedef struct linkedlist_data_s
     linkedlist_datablock_internal* last_block;
 } linkedlist_data;
 
-
 typedef struct
 {
     z_stream stream;            /* zLib stream structure for inflate */
@@ -162,8 +163,6 @@ typedef struct
 #endif
 } zip_internal;
 
-
-
 #ifndef NOCRYPT
 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
 #include "crypt.h"
@@ -176,9 +175,9 @@ static linkedlist_datablock_internal* allocate_new_datablock()
                  ALLOC(sizeof(linkedlist_datablock_internal));
     if (ldi!=NULL)
     {
-        ldi->next_datablock = NULL ;
-        ldi->filled_in_this_block = 0 ;
-        ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
+        ldi->next_datablock = NULL;
+        ldi->filled_in_this_block = 0;
+        ldi->avail_in_this_block = SIZEDATA_INDATABLOCK;
     }
     return ldi;
 }
@@ -228,7 +227,7 @@ static int add_data_in_datablock(linkedlist_data*ll,
             ldi->next_datablock = allocate_new_datablock();
             if (ldi->next_datablock == NULL)
                 return ZIP_INTERNALERROR;
-            ldi = ldi->next_datablock ;
+            ldi = ldi->next_datablock;
             ll->last_block = ldi;
         }
 
@@ -244,14 +243,12 @@ static int add_data_in_datablock(linkedlist_data*ll,
 
         ldi->filled_in_this_block += copy_this;
         ldi->avail_in_this_block -= copy_this;
-        from_copy += copy_this ;
+        from_copy += copy_this;
         len -= copy_this;
     }
     return ZIP_OK;
 }
 
-
-
 /****************************************************************************/
 
 #ifndef NO_ADDFILEINEXISTINGZIP
@@ -302,9 +299,8 @@ static void ziplocal_putValue_inmemory (void *dest, uLong x, int nbByte)
 
 /****************************************************************************/
 
-
-static uLong ziplocal_TmzDateToDosDate(const tm_zip *ptm,
-                                      CPL_UNUSED uLong dosDate)
+static uLong ziplocal_TmzDateToDosDate( const tm_zip *ptm,
+                                        uLong /* dosDate */ )
 {
     uLong year = (uLong)ptm->tm_year;
     if (year>1980)
@@ -316,17 +312,17 @@ static uLong ziplocal_TmzDateToDosDate(const tm_zip *ptm,
         ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
 }
 
-
 /****************************************************************************/
 
-static int ziplocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def,
-                            voidpf filestream, int *pi)
+static int ziplocal_getByte( const zlib_filefunc_def* pzlib_filefunc_def,
+                             voidpf filestream, int *pi )
 {
     unsigned char c = 0;
-    int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
+    const int err =
+        static_cast<int>(ZREAD(*pzlib_filefunc_def, filestream, &c, 1));
     if (err==1)
     {
-        *pi = (int)c;
+        *pi = static_cast<int>(c);
         return ZIP_OK;
     }
     else
@@ -338,7 +334,6 @@ static int ziplocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def,
     }
 }
 
-
 /* ===========================================================================
    Reads a long in LSB order from the given gz_stream. Sets
 */
@@ -421,17 +416,18 @@ static uLong ziplocal_SearchCentralDir(
             uBackRead = uMaxBack;
         else
             uBackRead+=BUFREADCOMMENT;
-        uLong uReadPos = uSizeFile-uBackRead ;
+        uLong uReadPos = uSizeFile-uBackRead;
 
         uLong uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
-        if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+        if( ZSEEK(*pzlib_filefunc_def, filestream, uReadPos,
+                  ZLIB_FILEFUNC_SEEK_SET) != 0 )
             break;
 
         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
             break;
 
-        for (int i=(int)uReadSize-3; (i--)>0;)
+        for( int i = static_cast<int>(uReadSize) - 3; (i--) > 0;)
             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
             {
@@ -652,7 +648,12 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
     int memLevel,
     int strategy,
     const char* password,
-    CPL_UNUSED uLong crcForCrypting )
+#ifdef NOCRYPT
+    uLong /* crcForCrypting */
+#else
+    uLong crcForCrypting
+#endif
+ )
 {
     zip_internal* zi;
     uInt size_filename;
@@ -679,7 +680,6 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
             return err;
     }
 
-
     if (filename==NULL)
         filename="-";
 
@@ -717,7 +717,7 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
     zi->ci.stream_initialised = 0;
     zi->ci.pos_in_buffered_data = 0;
     zi->ci.raw = raw;
-    zi->ci.pos_local_header = (uLong) ZTELL(zi->z_filefunc,zi->filestream) ;
+    zi->ci.pos_local_header = (uLong) ZTELL(zi->z_filefunc,zi->filestream);
     zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
                                       size_extrafield_global + size_comment;
     zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
@@ -819,7 +819,7 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
         if (err==Z_OK)
             zi->ci.stream_initialised = 1;
     }
-#    ifndef NOCRYPT
+#ifndef NOCRYPT
     zi->ci.crypt_header_size = 0;
     if ((err==Z_OK) && (password != NULL))
     {
@@ -835,7 +835,7 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (
         if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
                 err = ZIP_ERRNO;
     }
-#    endif
+#endif
 
     if (err==Z_OK)
         zi->in_opened_file_inzip = 1;
@@ -930,7 +930,6 @@ extern int ZEXPORT cpl_zipWriteInFileInZip (
             zi->ci.stream.next_out = zi->ci.buffered_data;
         }
 
-
         if(err != ZIP_OK)
             break;
 
@@ -939,7 +938,6 @@ extern int ZEXPORT cpl_zipWriteInFileInZip (
             uLong uTotalOutBefore = zi->ci.stream.total_out;
             err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
             zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
-
         }
         else
         {
@@ -1101,7 +1099,7 @@ extern int ZEXPORT cpl_zipClose (
     centraldir_pos_inzip = (uLong) ZTELL(zi->z_filefunc,zi->filestream);
     if (err==ZIP_OK)
     {
-        linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
+        linkedlist_datablock_internal* ldi = zi->central_dir.first_block;
         while (ldi!=NULL)
         {
             if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
@@ -1178,10 +1176,12 @@ typedef struct
 /*                            CPLCreateZip()                            */
 /************************************************************************/
 
+/** Create ZIP file */
 void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
 
 {
-    bool bAppend = CPL_TO_BOOL(CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "APPEND", "FALSE")));
+    const bool bAppend =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions, "APPEND", "FALSE"));
     char** papszFilenames = NULL;
 
     if( bAppend )
@@ -1213,7 +1213,7 @@ void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
         return NULL;
     }
 
-    CPLZip* psZip = (CPLZip*)CPLMalloc(sizeof(CPLZip));
+    CPLZip* psZip = static_cast<CPLZip *>(CPLMalloc(sizeof(CPLZip)));
     psZip->hZip = hZip;
     psZip->papszFilenames = papszFilenames;
     return psZip;
@@ -1223,6 +1223,7 @@ void *CPLCreateZip( const char *pszZipFilename, char **papszOptions )
 /*                         CPLCreateFileInZip()                         */
 /************************************************************************/
 
+/** Create a file in a ZIP file */
 CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename,
                            char **papszOptions )
 
@@ -1239,11 +1240,67 @@ CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename,
         return CE_Failure;
     }
 
-    int bCompressed = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "COMPRESSED", "TRUE"));
+    const bool bCompressed =
+        CPLTestBool(CSLFetchNameValueDef(papszOptions, "COMPRESSED", "TRUE"));
+
+    // If the filename is ASCII only, then no need for an extended field
+    bool bIsAscii = true;
+    for( int i=0; pszFilename[i] != '\0'; i++ )
+    {
+        if( (reinterpret_cast<const GByte*>(pszFilename))[i] > 127 )
+        {
+            bIsAscii = false;
+            break;
+        }
+    }
+
+    char* pszCPFilename = NULL;
+    unsigned int nExtraLength = 0;
+    GByte* pabyExtra = NULL;
+    if( !bIsAscii )
+    {
+        const char* pszDestEncoding = CPLGetConfigOption("CPL_ZIP_ENCODING",
+#if defined(_WIN32) && !defined(HAVE_ICONV)
+                                                        "CP_OEMCP"
+#else
+                                                        "CP437"
+#endif
+                                                        );
+
+        pszCPFilename = CPLRecode(pszFilename, CPL_ENC_UTF8, pszDestEncoding);
+
+        /* Create a Info-ZIP Unicode Path Extra Field (0x7075) */
+        const GUInt16 nDataLength = 1 + 4 +
+                                    static_cast<GUInt16>(strlen(pszFilename));
+        nExtraLength = 2 + 2 + nDataLength;
+        pabyExtra = static_cast<GByte*>(CPLMalloc(nExtraLength));
+        const GUInt16 nHeaderIdLE = CPL_LSBWORD16(0x7075);
+        memcpy(pabyExtra, &nHeaderIdLE, 2);
+        const GUInt16 nDataLengthLE = CPL_LSBWORD16(nDataLength);
+        memcpy(pabyExtra + 2, &nDataLengthLE, 2);
+        const GByte nVersion = 1;
+        memcpy(pabyExtra + 2 + 2, &nVersion, 1);
+        const GUInt32 nNameCRC32 = static_cast<GUInt32>(crc32(0,
+                (const Bytef*)pszCPFilename,
+                static_cast<uInt>(strlen(pszCPFilename))));
+        const GUInt32 nNameCRC32LE = CPL_LSBWORD32(nNameCRC32);
+        memcpy(pabyExtra + 2 + 2 + 1, &nNameCRC32LE, 4);
+        memcpy(pabyExtra + 2 + 2 + 1 + 4, pszFilename, strlen(pszFilename));
+    }
+    else
+    {
+        pszCPFilename = CPLStrdup(pszFilename);
+    }
+
+    const int nErr =
+        cpl_zipOpenNewFileInZip(
+            psZip->hZip, pszCPFilename, NULL,
+            NULL, 0, pabyExtra, nExtraLength, "",
+            bCompressed ? Z_DEFLATED : 0,
+            bCompressed ? Z_DEFAULT_COMPRESSION : 0 );
 
-    int nErr = cpl_zipOpenNewFileInZip( psZip->hZip, pszFilename, NULL,
-                                    NULL, 0, NULL, 0, "",
-                                    bCompressed ? Z_DEFLATED : 0, bCompressed ? Z_DEFAULT_COMPRESSION : 0 );
+    CPLFree( pabyExtra );
+    CPLFree( pszCPFilename );
 
     if( nErr != ZIP_OK )
         return CE_Failure;
@@ -1256,6 +1313,7 @@ CPLErr CPLCreateFileInZip( void *hZip, const char *pszFilename,
 /*                         CPLWriteFileInZip()                          */
 /************************************************************************/
 
+/** Write in current file inside a ZIP file */
 CPLErr CPLWriteFileInZip( void *hZip, const void *pBuffer, int nBufferSize )
 
 {
@@ -1277,6 +1335,7 @@ CPLErr CPLWriteFileInZip( void *hZip, const void *pBuffer, int nBufferSize )
 /*                         CPLCloseFileInZip()                          */
 /************************************************************************/
 
+/** Close current file inside ZIP file */
 CPLErr CPLCloseFileInZip( void *hZip )
 
 {
@@ -1297,6 +1356,7 @@ CPLErr CPLCloseFileInZip( void *hZip )
 /*                            CPLCloseZip()                             */
 /************************************************************************/
 
+/** Close ZIP file */
 CPLErr CPLCloseZip( void *hZip )
 
 {
diff --git a/port/cpl_minizip_zip.h b/port/cpl_minizip_zip.h
index b086990..e086e51 100644
--- a/port/cpl_minizip_zip.h
+++ b/port/cpl_minizip_zip.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_minizip_zip.h 31826 2015-11-29 15:39:57Z goatbar $
+ * $Id: cpl_minizip_zip.h 35921 2016-10-25 02:28:29Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -28,7 +28,6 @@
 
   For uncompress .zip file, look at unzip.h
 
-
    I WAIT FEEDBACK at mail info at winimage.com
    Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
 
@@ -49,8 +48,6 @@
   2. Altered source versions must be plainly marked as such, and must not be
      misrepresented as being the original software.
   3. This notice may not be removed or altered from any source distribution.
-
-
 */
 
 /* for more info about .ZIP format, see
@@ -63,6 +60,8 @@
 #ifndef CPL_MINIZIP_ZIP_H_INCLUDED
 #define CPL_MINIZIP_ZIP_H_INCLUDED
 
+#ifndef DOXYGEN_SKIP
+
 #include "cpl_vsi.h"
 #define uLong64 vsi_l_offset
 
@@ -130,7 +129,6 @@ typedef struct
 
 typedef const char* zipcharpc;
 
-
 #define APPEND_STATUS_CREATE        (0)
 #define APPEND_STATUS_CREATEAFTER   (1)
 #define APPEND_STATUS_ADDINZIP      (2)
@@ -183,7 +181,6 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip (zipFile file,
   level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
 */
 
-
 extern int ZEXPORT cpl_zipOpenNewFileInZip2 (zipFile file,
                                              const char* filename,
                                              const zip_fileinfo* zipfi,
@@ -224,7 +221,6 @@ extern int ZEXPORT cpl_zipOpenNewFileInZip3 (zipFile file,
     crcForCtypting : crc of file to compress (needed for crypting)
  */
 
-
 extern int ZEXPORT cpl_zipWriteInFileInZip (zipFile file,
                                             const void* buf,
                                             unsigned len);
@@ -256,4 +252,6 @@ extern int ZEXPORT cpl_zipClose (zipFile file,
 }
 #endif
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif /* _zip_H */
diff --git a/port/cpl_multiproc.cpp b/port/cpl_multiproc.cpp
index 4ea484b..cc29f1f 100644
--- a/port/cpl_multiproc.cpp
+++ b/port/cpl_multiproc.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_multiproc.cpp 33817 2016-03-30 17:35:37Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL Multi-Threading, and process handling portability functions.
@@ -32,24 +31,43 @@
 #define _GNU_SOURCE
 #endif
 
+// Include cpl_config.h BEFORE cpl_multiproc.h, as the later may undefine
+// CPL_MULTIPROC_PTHREAD for mingw case.
+
+#include "cpl_config.h"
 #include "cpl_multiproc.h"
 
-#include "cpl_conv.h"
+#ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
+#  include <cassert>
+#endif
+#include <cerrno>
+#ifndef DEBUG_BOOL
+#include <cmath>
+#endif
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <algorithm>
 
-#include <time.h>
-#include <assert.h>
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_multiproc.cpp 33817 2016-03-30 17:35:37Z rouault $");
+CPL_CVSID("$Id: cpl_multiproc.cpp 37003 2016-12-23 14:54:07Z goatbar $");
 
 #if defined(CPL_MULTIPROC_STUB) && !defined(DEBUG)
 #  define MUTEX_NONE
 #endif
 
-//#define DEBUG_MUTEX
+// #define DEBUG_MUTEX
 
 #if defined(DEBUG) && (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
+#ifndef DEBUG_CONTENTION
 #define DEBUG_CONTENTION
 #endif
+#endif
 
 typedef struct _CPLSpinLock CPLSpinLock;
 
@@ -63,7 +81,7 @@ struct _CPLLock
     } u;
 
 #ifdef DEBUG_CONTENTION
-    int      bDebugPerf;
+    bool     bDebugPerf;
     GUIntBig nStartTime;
     GIntBig  nMaxDiff;
     double   dfAvgDiff;
@@ -72,47 +90,60 @@ struct _CPLLock
 };
 
 #ifdef DEBUG_CONTENTION
-static GUIntBig CPLrdtsc(void)
+static GUIntBig CPLrdtsc()
 {
-   unsigned int a, d, x, y;
-   __asm__ volatile ("cpuid" : "=a" (x), "=d" (y) : "a"(0) : "cx", "bx" );
-   __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d) );
-   return ((GUIntBig )a) | (((GUIntBig )d) << 32);
+    unsigned int a;
+    unsigned int d;
+    unsigned int x;
+    unsigned int y;
+    __asm__ volatile ("cpuid" : "=a" (x), "=d" (y) : "a"(0) : "cx", "bx" );
+    __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d) );
+    return static_cast<GUIntBig>(a) | (static_cast<GUIntBig>(d) << 32);
 }
 
-static GUIntBig CPLrdtscp(void)
+static GUIntBig CPLrdtscp()
 {
-   unsigned int a, d, x, y;
-   __asm__ volatile ("rdtscp" : "=a" (a), "=d" (d) );
-   __asm__ volatile ("cpuid"  : "=a" (x), "=d" (y) : "a"(0) : "cx", "bx" );
-   return ((GUIntBig )a) | (((GUIntBig )d) << 32);
+    unsigned int a;
+    unsigned int d;
+    unsigned int x;
+    unsigned int y;
+    __asm__ volatile ("rdtscp" : "=a" (a), "=d" (d) );
+    __asm__ volatile ("cpuid"  : "=a" (x), "=d" (y) : "a"(0) : "cx", "bx" );
+    return static_cast<GUIntBig>(a) | (static_cast<GUIntBig>(d) << 32);
 }
 #endif
 
-static CPLSpinLock   *CPLCreateSpinLock( void ); /* returned NON acquired */
+static CPLSpinLock *CPLCreateSpinLock();  // Returned NON acquired.
 static int     CPLCreateOrAcquireSpinLockInternal( CPLLock** );
 static int     CPLAcquireSpinLock( CPLSpinLock* );
 static void    CPLReleaseSpinLock( CPLSpinLock* );
 static void    CPLDestroySpinLock( CPLSpinLock* );
 
-/* We don't want it to be publicly used since it solves rather tricky issues */
-/* that are better to remain hidden... */
+// We don't want it to be publicly used since it solves rather tricky issues
+// that are better to remain hidden.
 void CPLFinalizeTLS();
 
 /************************************************************************/
 /*                           CPLMutexHolder()                           */
 /************************************************************************/
 
-CPLMutexHolder::CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds,
+#ifdef MUTEX_NONE
+CPLMutexHolder::CPLMutexHolder( CPLMutex ** /* phMutex */,
+                                double /* dfWaitInSeconds */,
+                                const char * /* pszFileIn */,
+                                int /* nLineIn */,
+                                int /* nOptions */ ) {}
+
+#else
+CPLMutexHolder::CPLMutexHolder( CPLMutex **phMutex,
+                                double dfWaitInSeconds,
                                 const char *pszFileIn,
                                 int nLineIn,
-                                int nOptions )
-
+                                int nOptions ) :
+    hMutex(NULL),
+    pszFile(pszFileIn),
+    nLine(nLineIn)
 {
-#ifndef MUTEX_NONE
-    pszFile = pszFileIn;
-    nLine = nLineIn;
-
     if( phMutex == NULL )
     {
         fprintf( stderr, "CPLMutexHolder: phMutex )) NULL !\n" );
@@ -121,14 +152,16 @@ CPLMutexHolder::CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds,
     }
 
 #ifdef DEBUG_MUTEX
-    /*
-     * XXX: There is no way to use CPLDebug() here because it works with
-     * mutexes itself so we will fall in infinite recursion. Good old
-     * fprintf() will do the job right.
-     */
+    // There is no way to use CPLDebug() here because it works with
+    // mutexes itself so we will fall in infinite recursion.
+    // fprintf() will do the job right.
     fprintf( stderr,
              "CPLMutexHolder: Request %p for pid %ld at %d/%s.\n",
-             *phMutex, (long) CPLGetPID(), nLine, pszFile );
+             *phMutex, static_cast<long>(CPLGetPID()), nLine, pszFile );
+#else
+    // TODO(schwehr): Find a better way to do handle this.
+    (void)pszFile;
+    (void)nLine;
 #endif
 
     if( !CPLCreateOrAcquireMutexEx( phMutex, dfWaitInSeconds, nOptions ) )
@@ -141,60 +174,66 @@ CPLMutexHolder::CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds,
 #ifdef DEBUG_MUTEX
         fprintf( stderr,
                  "CPLMutexHolder: Acquired %p for pid %ld at %d/%s.\n",
-                 *phMutex, (long) CPLGetPID(), nLine, pszFile );
+                 *phMutex, static_cast<long>(CPLGetPID()), nLine, pszFile );
 #endif
 
         hMutex = *phMutex;
     }
-#endif /* ndef MUTEX_NONE */
 }
+#endif  // ndef MUTEX_NONE
 
 /************************************************************************/
 /*                           CPLMutexHolder()                           */
 /************************************************************************/
 
+#ifdef MUTEX_NONE
+CPLMutexHolder::CPLMutexHolder( CPLMutex * /* hMutexIn */,
+                                double /* dfWaitInSeconds */,
+                                const char * /* pszFileIn */,
+                                int /* nLineIn */ ) {}
+#else
 CPLMutexHolder::CPLMutexHolder( CPLMutex *hMutexIn, double dfWaitInSeconds,
                                 const char *pszFileIn,
-                                int nLineIn )
-
+                                int nLineIn ) :
+    hMutex(hMutexIn),
+    pszFile(pszFileIn),
+    nLine(nLineIn)
 {
-#ifndef MUTEX_NONE
-    pszFile = pszFileIn;
-    nLine = nLineIn;
-    hMutex = hMutexIn;
-
     if( hMutex != NULL &&
         !CPLAcquireMutex( hMutex, dfWaitInSeconds ) )
     {
         fprintf( stderr, "CPLMutexHolder: Failed to acquire mutex!\n" );
         hMutex = NULL;
     }
-#endif /* ndef MUTEX_NONE */
 }
+#endif  // ndef MUTEX_NONE
 
 /************************************************************************/
 /*                          ~CPLMutexHolder()                           */
 /************************************************************************/
 
+#ifdef MUTEX_NONE
+CPLMutexHolder::~CPLMutexHolder() {}
+#else
 CPLMutexHolder::~CPLMutexHolder()
-
 {
-#ifndef MUTEX_NONE
     if( hMutex != NULL )
     {
 #ifdef DEBUG_MUTEX
         fprintf( stderr,
                  "~CPLMutexHolder: Release %p for pid %ld at %d/%s.\n",
-                 hMutex, (long) CPLGetPID(), nLine, pszFile );
+                 hMutex, static_cast<long>(CPLGetPID()), nLine, pszFile );
 #endif
         CPLReleaseMutex( hMutex );
     }
-#endif /* ndef MUTEX_NONE */
 }
+#endif  // ndef MUTEX_NONE
 
 int CPLCreateOrAcquireMutex( CPLMutex **phMutex, double dfWaitInSeconds )
 {
-    return CPLCreateOrAcquireMutexEx(phMutex, dfWaitInSeconds, CPL_MUTEX_RECURSIVE);
+    return
+        CPLCreateOrAcquireMutexEx(phMutex, dfWaitInSeconds,
+                                  CPL_MUTEX_RECURSIVE);
 }
 
 /************************************************************************/
@@ -207,22 +246,26 @@ int CPLCreateOrAcquireMutex( CPLMutex **phMutex, double dfWaitInSeconds )
 static CPLMutex *hCOAMutex = NULL;
 #endif
 
-int CPLCreateOrAcquireMutexEx( CPLMutex **phMutex, double dfWaitInSeconds, int nOptions )
+#ifdef MUTEX_NONE
 
+int CPLCreateOrAcquireMutexEx( CPLMutex **phMutex, double dfWaitInSeconds,
+                               int nOptions )
 {
-    int bSuccess = FALSE;
-
-#ifndef MUTEX_NONE
+    return false;
+}
+#else
+int CPLCreateOrAcquireMutexEx( CPLMutex **phMutex, double dfWaitInSeconds,
+                               int nOptions )
+{
+    bool bSuccess = false;
 
-    /*
-    ** ironically, creation of this initial mutex is not threadsafe
-    ** even though we use it to ensure that creation of other mutexes
-    ** is threadsafe.
-    */
+    // Ironically, creation of this initial mutex is not threadsafe
+    // even though we use it to ensure that creation of other mutexes
+    // is threadsafe.
     if( hCOAMutex == NULL )
     {
         hCOAMutex = CPLCreateMutex();
-        if (hCOAMutex == NULL)
+        if( hCOAMutex == NULL )
         {
             *phMutex = NULL;
             return FALSE;
@@ -243,35 +286,39 @@ int CPLCreateOrAcquireMutexEx( CPLMutex **phMutex, double dfWaitInSeconds, int n
     {
         CPLReleaseMutex( hCOAMutex );
 
-        bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds );
+        bSuccess = CPL_TO_BOOL(CPLAcquireMutex( *phMutex, dfWaitInSeconds ));
     }
-#endif /* ndef MUTEX_NONE */
 
     return bSuccess;
 }
+#endif  // ndef MUTEX_NONE
 
 /************************************************************************/
 /*                   CPLCreateOrAcquireMutexInternal()                  */
 /************************************************************************/
 
+#ifdef MUTEX_NONE
 static
 int CPLCreateOrAcquireMutexInternal( CPLLock **phLock, double dfWaitInSeconds,
                                      CPLLockType eType )
-
 {
-    int bSuccess = FALSE;
+    return false;
+}
+#else
+static
+int CPLCreateOrAcquireMutexInternal( CPLLock **phLock, double dfWaitInSeconds,
+                                     CPLLockType eType )
 
-#ifndef MUTEX_NONE
+{
+    bool bSuccess = false;
 
-    /*
-    ** ironically, creation of this initial mutex is not threadsafe
-    ** even though we use it to ensure that creation of other mutexes
-    ** is threadsafe.
-    */
+    // Ironically, creation of this initial mutex is not threadsafe
+    // even though we use it to ensure that creation of other mutexes.
+    // is threadsafe.
     if( hCOAMutex == NULL )
     {
         hCOAMutex = CPLCreateMutex();
-        if (hCOAMutex == NULL)
+        if( hCOAMutex == NULL )
         {
             *phLock = NULL;
             return FALSE;
@@ -284,12 +331,14 @@ int CPLCreateOrAcquireMutexInternal( CPLLock **phLock, double dfWaitInSeconds,
 
     if( *phLock == NULL )
     {
-        *phLock = (CPLLock*) calloc(1, sizeof(CPLLock));
+        *phLock = static_cast<CPLLock *>(calloc(1, sizeof(CPLLock)));
         if( *phLock )
         {
             (*phLock)->eType = eType;
             (*phLock)->u.hMutex = CPLCreateMutexEx(
-                (eType == LOCK_RECURSIVE_MUTEX) ? CPL_MUTEX_RECURSIVE : CPL_MUTEX_ADAPTIVE );
+                (eType == LOCK_RECURSIVE_MUTEX)
+                ? CPL_MUTEX_RECURSIVE
+                : CPL_MUTEX_ADAPTIVE );
             if( (*phLock)->u.hMutex == NULL )
             {
                 free(*phLock);
@@ -303,14 +352,16 @@ int CPLCreateOrAcquireMutexInternal( CPLLock **phLock, double dfWaitInSeconds,
     {
         CPLReleaseMutex( hCOAMutex );
 
-        bSuccess = CPLAcquireMutex( (*phLock)->u.hMutex, dfWaitInSeconds );
+        bSuccess =
+            CPL_TO_BOOL(CPLAcquireMutex( (*phLock)->u.hMutex,
+                                         dfWaitInSeconds ));
     }
-#endif /* ndef MUTEX_NONE */
 
     return bSuccess;
 }
+#endif  // ndef MUTEX_NONE
 
-#endif /* CPL_MULTIPROC_PTHREAD */
+#endif  // CPL_MULTIPROC_PTHREAD
 
 /************************************************************************/
 /*                      CPLCleanupMasterMutex()                         */
@@ -340,7 +391,7 @@ static void CPLCleanupTLSList( void **papTLSList )
 
 {
 #ifdef DEBUG_VERBOSE
-    printf( "CPLCleanupTLSList(%p)\n", papTLSList );
+    printf( "CPLCleanupTLSList(%p)\n", papTLSList );  /*ok*/
 #endif
 
     if( papTLSList == NULL )
@@ -393,11 +444,15 @@ const char *CPLGetThreadingModel()
 /*                           CPLCreateMutex()                           */
 /************************************************************************/
 
+#ifndef MUTEX_NONE
 CPLMutex *CPLCreateMutex()
-
 {
-#ifndef MUTEX_NONE
-    unsigned char *pabyMutex = (unsigned char *) malloc( 4 );
+    return (CPLMutex *) 0xdeadbeef;
+}
+#else
+CPLMutex *CPLCreateMutex()
+{
+    unsigned char *pabyMutex = static_cast<unsigned char *>(malloc(4));
     if( pabyMutex == NULL )
         return NULL;
 
@@ -407,12 +462,10 @@ CPLMutex *CPLCreateMutex()
     pabyMutex[3] = 'd';
 
     return (CPLMutex *) pabyMutex;
-#else
-    return (CPLMutex *) 0xdeadbeef;
-#endif
 }
+#endif
 
-CPLMutex *CPLCreateMutexEx(CPL_UNUSED int nOptions)
+CPLMutex *CPLCreateMutexEx( int nOptions )
 
 {
     return CPLCreateMutex();
@@ -422,11 +475,15 @@ CPLMutex *CPLCreateMutexEx(CPL_UNUSED int nOptions)
 /*                          CPLAcquireMutex()                           */
 /************************************************************************/
 
-int CPLAcquireMutex( CPLMutex *hMutex,
-                     CPL_UNUSED double dfWaitInSeconds )
+#ifdef MUTEX_NONE
+int CPLAcquireMutex( CPLMutex *hMutex, double /* dfWaitInSeconds */ )
 {
-#ifndef MUTEX_NONE
-    unsigned char *pabyMutex = (unsigned char *) hMutex;
+    return TRUE;
+}
+#else
+int CPLAcquireMutex( CPLMutex *hMutex, double dfWaitInSeconds )
+{
+    unsigned char *pabyMutex = reinterpret_cast<unsigned char *>(hMutex);
 
     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e'
                && pabyMutex[3] == 'd' );
@@ -434,20 +491,19 @@ int CPLAcquireMutex( CPLMutex *hMutex,
     pabyMutex[0] += 1;
 
     return TRUE;
-#else
-    return TRUE;
-#endif
 }
+#endif  // ! MUTEX_NONE
 
 /************************************************************************/
 /*                          CPLReleaseMutex()                           */
 /************************************************************************/
 
+#ifdef MUTEX_NONE
+void CPLReleaseMutex( CPLMutex * /* hMutex */ ) {}
+#else
 void CPLReleaseMutex( CPLMutex *hMutex )
-
 {
-#ifndef MUTEX_NONE
-    unsigned char *pabyMutex = (unsigned char *) hMutex;
+    unsigned char *pabyMutex = retinterpret_cast<unsigned char *>(hMutex);
 
     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e'
                && pabyMutex[3] == 'd' );
@@ -458,31 +514,32 @@ void CPLReleaseMutex( CPLMutex *hMutex )
                   pabyMutex[0] );
 
     pabyMutex[0] -= 1;
-#endif
 }
+#endif
 
 /************************************************************************/
 /*                          CPLDestroyMutex()                           */
 /************************************************************************/
 
+#ifdef MUTEX_NONE
+void CPLDestroyMutex( CPLMutex * /* hMutex */ ) {}
+#else
 void CPLDestroyMutex( CPLMutex *hMutex )
-
 {
-#ifndef MUTEX_NONE
-    unsigned char *pabyMutex = (unsigned char *) hMutex;
+    unsigned char *pabyMutex = reinterpret_cast<unsigned char *>(hMutex);
 
     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e'
                && pabyMutex[3] == 'd' );
 
     free( pabyMutex );
-#endif
 }
+#endif
 
 /************************************************************************/
 /*                            CPLCreateCond()                           */
 /************************************************************************/
 
-CPLCond  *CPLCreateCond()
+CPLCond *CPLCreateCond()
 {
     return NULL;
 }
@@ -491,33 +548,25 @@ CPLCond  *CPLCreateCond()
 /*                            CPLCondWait()                             */
 /************************************************************************/
 
-void  CPLCondWait( CPL_UNUSED CPLCond *hCond, CPL_UNUSED CPLMutex* hMutex )
-{
-}
+void CPLCondWait( CPLCond * /* hCond */ , CPLMutex* /* hMutex */ ) {}
 
 /************************************************************************/
 /*                            CPLCondSignal()                           */
 /************************************************************************/
 
-void  CPLCondSignal( CPL_UNUSED CPLCond *hCond )
-{
-}
+void CPLCondSignal( CPLCond * /* hCond */ ) {}
 
 /************************************************************************/
 /*                           CPLCondBroadcast()                         */
 /************************************************************************/
 
-void  CPLCondBroadcast( CPL_UNUSED CPLCond *hCond )
-{
-}
+void CPLCondBroadcast( CPLCond * /* hCond */ ) {}
 
 /************************************************************************/
 /*                            CPLDestroyCond()                          */
 /************************************************************************/
 
-void  CPLDestroyCond( CPL_UNUSED CPLCond *hCond )
-{
-}
+void CPLDestroyCond( CPLCond * /* hCond */ ) {}
 
 /************************************************************************/
 /*                            CPLLockFile()                             */
@@ -536,23 +585,21 @@ void  CPLDestroyCond( CPL_UNUSED CPLCond *hCond )
 void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 
 {
-    FILE      *fpLock;
-    char      *pszLockFilename;
-
 /* -------------------------------------------------------------------- */
 /*      We use a lock file with a name derived from the file we want    */
 /*      to lock to represent the file being locked.  Note that for      */
 /*      the stub implementation the target file does not even need      */
 /*      to exist to be locked.                                          */
 /* -------------------------------------------------------------------- */
-    pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
+    char *pszLockFilename = static_cast<char *>(
+        CPLMalloc(strlen(pszPath) + 30));
     snprintf( pszLockFilename, strlen(pszPath) + 30, "%s.lock", pszPath );
 
-    fpLock = fopen( pszLockFilename, "r" );
+    FILE *fpLock = fopen( pszLockFilename, "r" );
     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
     {
         fclose( fpLock );
-        CPLSleep( MIN(dfWaitInSeconds,0.5) );
+        CPLSleep( std::min(dfWaitInSeconds, 0.5) );
         dfWaitInSeconds -= 0.5;
 
         fpLock = fopen( pszLockFilename, "r" );
@@ -586,7 +633,7 @@ void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 void CPLUnlockFile( void *hLock )
 
 {
-    char *pszLockFilename = (char *) hLock;
+    char *pszLockFilename = static_cast<char *>(hLock);
 
     if( hLock == NULL )
         return;
@@ -610,7 +657,7 @@ GIntBig CPLGetPID()
 /*                          CPLCreateThread();                          */
 /************************************************************************/
 
-int CPLCreateThread( CPL_UNUSED CPLThreadFunc pfnMain, CPL_UNUSED void *pArg )
+int CPLCreateThread( CPLThreadFunc /* pfnMain */, void * /* pArg */)
 {
     CPLDebug( "CPLCreateThread", "Fails to dummy implementation" );
 
@@ -621,7 +668,8 @@ int CPLCreateThread( CPL_UNUSED CPLThreadFunc pfnMain, CPL_UNUSED void *pArg )
 /*                      CPLCreateJoinableThread()                       */
 /************************************************************************/
 
-CPLJoinableThread* CPLCreateJoinableThread( CPL_UNUSED CPLThreadFunc pfnMain, CPL_UNUSED void *pThreadArg )
+CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc /* pfnMain */,
+                                            void * /* pThreadArg */ )
 {
     CPLDebug( "CPLCreateJoinableThread", "Fails to dummy implementation" );
 
@@ -632,9 +680,7 @@ CPLJoinableThread* CPLCreateJoinableThread( CPL_UNUSED CPLThreadFunc pfnMain, CP
 /*                          CPLJoinThread()                             */
 /************************************************************************/
 
-void CPLJoinThread(CPL_UNUSED CPLJoinableThread* hJoinableThread)
-{
-}
+void CPLJoinThread( CPLJoinableThread* /* hJoinableThread */ ) {}
 
 /************************************************************************/
 /*                              CPLSleep()                              */
@@ -642,15 +688,14 @@ void CPLJoinThread(CPL_UNUSED CPLJoinableThread* hJoinableThread)
 
 void CPLSleep( double dfWaitInSeconds )
 {
-    time_t  ltime;
+    time_t ltime;
 
     time( &ltime );
-    time_t ttime = ltime + (int) (dfWaitInSeconds+0.5);
+    const time_t ttime = ltime + static_cast<int>(dfWaitInSeconds + 0.5);
 
     for( ; ltime < ttime; time(&ltime) )
     {
-        /* currently we just busy wait.  Perhaps we could at least block on
-           io? */
+        // Currently we just busy wait.  Perhaps we could at least block on io?
     }
 }
 
@@ -660,20 +705,22 @@ void CPLSleep( double dfWaitInSeconds )
 
 static void **papTLSList = NULL;
 
-static void **CPLGetTLSList(int *pbMemoryErrorOccurred)
+static void **CPLGetTLSList( int *pbMemoryErrorOccurred )
 
 {
     if( pbMemoryErrorOccurred )
         *pbMemoryErrorOccurred = FALSE;
     if( papTLSList == NULL )
     {
-        papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
+        papTLSList =
+            static_cast<void **>(VSICalloc(sizeof(void*), CTLS_MAX * 2));
         if( papTLSList == NULL )
         {
             if( pbMemoryErrorOccurred )
             {
                 *pbMemoryErrorOccurred = TRUE;
-                fprintf(stderr, "CPLGetTLSList() failed to allocate TLS list!\n");
+                fprintf(stderr,
+                        "CPLGetTLSList() failed to allocate TLS list!\n");
                 return NULL;
             }
             CPLEmergencyError("CPLGetTLSList() failed to allocate TLS list!");
@@ -703,11 +750,10 @@ void CPLCleanupTLS()
     papTLSList = NULL;
 }
 
-/* endif CPL_MULTIPROC_STUB */
+// endif CPL_MULTIPROC_STUB
 
 #elif defined(CPL_MULTIPROC_WIN32)
 
-
   /************************************************************************/
   /* ==================================================================== */
   /*                        CPL_MULTIPROC_WIN32                           */
@@ -730,10 +776,10 @@ int CPLGetNumCPUs()
 {
     SYSTEM_INFO info;
     GetSystemInfo(&info);
-    DWORD dwNum = info.dwNumberOfProcessors;
+    const DWORD dwNum = info.dwNumberOfProcessors;
     if( dwNum < 1 )
         return 1;
-    return (int)dwNum;
+    return static_cast<int>(dwNum);
 }
 
 /************************************************************************/
@@ -754,17 +800,15 @@ CPLMutex *CPLCreateMutex()
 
 {
 #ifdef USE_WIN32_MUTEX
-    HANDLE hMutex;
-
-    hMutex = CreateMutex( NULL, TRUE, NULL );
+    HANDLE hMutex = CreateMutex( NULL, TRUE, NULL );
 
     return (CPLMutex *) hMutex;
 #else
-    CRITICAL_SECTION *pcs;
 
-	/* Do not use CPLMalloc() since its debugging infrastructure */
-	/* can call the CPL*Mutex functions... */
-    pcs = (CRITICAL_SECTION *)malloc(sizeof(*pcs));
+    // Do not use CPLMalloc() since its debugging infrastructure
+    // can call the CPL*Mutex functions.
+    CRITICAL_SECTION *pcs =
+        static_cast<CRITICAL_SECTION *>(malloc(sizeof(*pcs)));
     if( pcs )
     {
       InitializeCriticalSectionAndSpinCount(pcs, 4000);
@@ -775,7 +819,7 @@ CPLMutex *CPLCreateMutex()
 #endif
 }
 
-CPLMutex *CPLCreateMutexEx(CPL_UNUSED int nOptions)
+CPLMutex *CPLCreateMutexEx( int /* nOptions */ )
 
 {
     return CPLCreateMutex();
@@ -791,7 +835,7 @@ int CPLAcquireMutex( CPLMutex *hMutexIn, double dfWaitInSeconds )
 #ifdef USE_WIN32_MUTEX
     HANDLE hMutex = (HANDLE) hMutexIn;
     const DWORD hr =
-        WaitForSingleObject( hMutex, (int) (dfWaitInSeconds * 1000) );
+        WaitForSingleObject(hMutex, static_cast<int>(dfWaitInSeconds * 1000));
 
     return hr != WAIT_TIMEOUT;
 #else
@@ -807,9 +851,10 @@ int CPLAcquireMutex( CPLMutex *hMutexIn, double dfWaitInSeconds )
     }
     else
     {
-        while( (ret = TryEnterCriticalSection(pcs)) == 0 && dfWaitInSeconds > 0.0 )
+        while( (ret = TryEnterCriticalSection(pcs)) == 0 &&
+               dfWaitInSeconds > 0.0 )
         {
-            CPLSleep( MIN(dfWaitInSeconds,0.01) );
+            CPLSleep( std::min(dfWaitInSeconds, 0.01) );
             dfWaitInSeconds -= 0.01;
         }
     }
@@ -872,13 +917,13 @@ typedef struct
     WaiterItem  *psWaiterList;
 } Win32Cond;
 
-CPLCond  *CPLCreateCond()
+CPLCond *CPLCreateCond()
 {
-    Win32Cond* psCond = (Win32Cond*) malloc(sizeof(Win32Cond));
-    if (psCond == NULL)
+    Win32Cond* psCond = static_cast<Win32Cond *>(malloc(sizeof(Win32Cond)));
+    if( psCond == NULL )
         return NULL;
     psCond->hInternalMutex = CPLCreateMutex();
-    if (psCond->hInternalMutex == NULL)
+    if( psCond->hInternalMutex == NULL )
     {
         free(psCond);
         return NULL;
@@ -892,17 +937,17 @@ CPLCond  *CPLCreateCond()
 /*                            CPLCondWait()                             */
 /************************************************************************/
 
-static void CPLTLSFreeEvent(void* pData)
+static void CPLTLSFreeEvent( void* pData )
 {
     CloseHandle((HANDLE)pData);
 }
 
-void  CPLCondWait( CPLCond *hCond, CPLMutex* hClientMutex )
+void CPLCondWait( CPLCond *hCond, CPLMutex* hClientMutex )
 {
     Win32Cond* psCond = (Win32Cond*) hCond;
 
     HANDLE hEvent = (HANDLE) CPLGetTLS(CTLS_WIN32_COND);
-    if (hEvent == NULL)
+    if( hEvent == NULL )
     {
         hEvent = CreateEvent(NULL, /* security attributes */
                              0,    /* manual reset = no */
@@ -916,7 +961,7 @@ void  CPLCondWait( CPLCond *hCond, CPLMutex* hClientMutex )
     /* Insert the waiter into the waiter list of the condition */
     CPLAcquireMutex(psCond->hInternalMutex, 1000.0);
 
-    WaiterItem* psItem = (WaiterItem*)malloc(sizeof(WaiterItem));
+    WaiterItem* psItem = static_cast<WaiterItem *>(malloc(sizeof(WaiterItem)));
     CPLAssert(psItem != NULL);
 
     psItem->hEvent = hEvent;
@@ -926,14 +971,14 @@ void  CPLCondWait( CPLCond *hCond, CPLMutex* hClientMutex )
 
     CPLReleaseMutex(psCond->hInternalMutex);
 
-    /* Release the client mutex before waiting for the event being signaled */
+    // Release the client mutex before waiting for the event being signaled.
     CPLReleaseMutex(hClientMutex);
 
     // Ideally we would check that we do not get WAIT_FAILED but it is hard
     // to report a failure.
     WaitForSingleObject(hEvent, INFINITE);
 
-    /* Reacquire the client mutex */
+    // Reacquire the client mutex.
     CPLAcquireMutex(hClientMutex, 1000.0);
 }
 
@@ -941,15 +986,15 @@ void  CPLCondWait( CPLCond *hCond, CPLMutex* hClientMutex )
 /*                            CPLCondSignal()                           */
 /************************************************************************/
 
-void  CPLCondSignal( CPLCond *hCond )
+void CPLCondSignal( CPLCond *hCond )
 {
     Win32Cond* psCond = (Win32Cond*) hCond;
 
-    /* Signal the first registered event, and remove it from the list */
+    // Signal the first registered event, and remove it from the list.
     CPLAcquireMutex(psCond->hInternalMutex, 1000.0);
 
     WaiterItem* psIter = psCond->psWaiterList;
-    if (psIter != NULL)
+    if( psIter != NULL )
     {
         SetEvent(psIter->hEvent);
         psCond->psWaiterList = psIter->psNext;
@@ -963,15 +1008,15 @@ void  CPLCondSignal( CPLCond *hCond )
 /*                           CPLCondBroadcast()                         */
 /************************************************************************/
 
-void  CPLCondBroadcast( CPLCond *hCond )
+void CPLCondBroadcast( CPLCond *hCond )
 {
     Win32Cond* psCond = (Win32Cond*) hCond;
 
-    /* Signal all the registered events, and remove them from the list */
+    // Signal all the registered events, and remove them from the list.
     CPLAcquireMutex(psCond->hInternalMutex, 1000.0);
 
     WaiterItem* psIter = psCond->psWaiterList;
-    while (psIter != NULL)
+    while( psIter != NULL )
     {
         WaiterItem* psNext = psIter->psNext;
         SetEvent(psIter->hEvent);
@@ -987,7 +1032,7 @@ void  CPLCondBroadcast( CPLCond *hCond )
 /*                            CPLDestroyCond()                          */
 /************************************************************************/
 
-void  CPLDestroyCond( CPLCond *hCond )
+void CPLDestroyCond( CPLCond *hCond )
 {
     Win32Cond* psCond = (Win32Cond*) hCond;
     CPLDestroyMutex(psCond->hInternalMutex);
@@ -1003,18 +1048,19 @@ void  CPLDestroyCond( CPLCond *hCond )
 void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 
 {
-    char *pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
+    char *pszLockFilename =
+        static_cast<char *>(CPLMalloc(strlen(pszPath) + 30));
     snprintf( pszLockFilename, strlen(pszPath) + 30, "%s.lock", pszPath );
 
     HANDLE hLockFile =
-        CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL,CREATE_NEW,
-                    FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL );
+        CreateFile(pszLockFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW,
+                   FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL);
 
     while( GetLastError() == ERROR_ALREADY_EXISTS
            && dfWaitInSeconds > 0.0 )
     {
         CloseHandle( hLockFile );
-        CPLSleep( MIN(dfWaitInSeconds,0.125) );
+        CPLSleep( std::min(dfWaitInSeconds, 0.125) );
         dfWaitInSeconds -= 0.125;
 
         hLockFile =
@@ -1056,7 +1102,7 @@ void CPLUnlockFile( void *hLock )
 GIntBig CPLGetPID()
 
 {
-    return (GIntBig) GetCurrentThreadId();
+    return static_cast<GIntBig>(GetCurrentThreadId());
 }
 
 /************************************************************************/
@@ -1072,12 +1118,12 @@ typedef struct {
 static DWORD WINAPI CPLStdCallThreadJacket( void *pData )
 
 {
-    CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
+    CPLStdCallThreadInfo *psInfo = static_cast<CPLStdCallThreadInfo *>(pData);
 
     psInfo->pfnMain( psInfo->pAppData );
 
-    if (psInfo->hThread == NULL)
-        CPLFree( psInfo ); /* Only for detached threads */
+    if( psInfo->hThread == NULL )
+        CPLFree( psInfo );  // Only for detached threads.
 
     CPLCleanupTLS();
 
@@ -1095,9 +1141,8 @@ static DWORD WINAPI CPLStdCallThreadJacket( void *pData )
 int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
 
 {
-    CPLStdCallThreadInfo *psInfo;
-
-    psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
+    CPLStdCallThreadInfo *psInfo = static_cast<CPLStdCallThreadInfo *>(
+        CPLCalloc(sizeof(CPLStdCallThreadInfo), 1));
     psInfo->pAppData = pThreadArg;
     psInfo->pfnMain = pfnMain;
     psInfo->hThread = NULL;
@@ -1118,12 +1163,12 @@ int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
 /*                      CPLCreateJoinableThread()                       */
 /************************************************************************/
 
-CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThreadArg )
+CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain,
+                                            void *pThreadArg )
 
 {
-    CPLStdCallThreadInfo *psInfo;
-
-    psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
+    CPLStdCallThreadInfo *psInfo = static_cast<CPLStdCallThreadInfo *>(
+        CPLCalloc(sizeof(CPLStdCallThreadInfo), 1));
     psInfo->pAppData = pThreadArg;
     psInfo->pfnMain = pfnMain;
 
@@ -1142,7 +1187,7 @@ CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThread
 /*                          CPLJoinThread()                             */
 /************************************************************************/
 
-void CPLJoinThread(CPLJoinableThread* hJoinableThread)
+void CPLJoinThread( CPLJoinableThread* hJoinableThread )
 {
     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) hJoinableThread;
 
@@ -1161,17 +1206,17 @@ void CPLSleep( double dfWaitInSeconds )
     Sleep( (DWORD) (dfWaitInSeconds * 1000.0) );
 }
 
-static bool          bTLSKeySetup = false;
+static bool bTLSKeySetup = false;
 static DWORD nTLSKey = 0;
 
 /************************************************************************/
 /*                           CPLGetTLSList()                            */
 /************************************************************************/
 
-static void **CPLGetTLSList(int *pbMemoryErrorOccurred)
+static void **CPLGetTLSList( int *pbMemoryErrorOccurred )
 
 {
-    void **papTLSList;
+    void **papTLSList = NULL;
 
     if( pbMemoryErrorOccurred )
         *pbMemoryErrorOccurred = FALSE;
@@ -1194,13 +1239,15 @@ static void **CPLGetTLSList(int *pbMemoryErrorOccurred)
     papTLSList = (void **) TlsGetValue( nTLSKey );
     if( papTLSList == NULL )
     {
-        papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
+        papTLSList =
+            static_cast<void **>(VSICalloc(sizeof(void*), CTLS_MAX * 2));
         if( papTLSList == NULL )
         {
             if( pbMemoryErrorOccurred )
             {
                 *pbMemoryErrorOccurred = TRUE;
-                fprintf(stderr, "CPLGetTLSList() failed to allocate TLS list!\n" );
+                fprintf(stderr,
+                        "CPLGetTLSList() failed to allocate TLS list!\n" );
                 return NULL;
             }
             CPLEmergencyError("CPLGetTLSList() failed to allocate TLS list!");
@@ -1236,12 +1283,10 @@ void CPLFinalizeTLS()
 void CPLCleanupTLS()
 
 {
-    void **papTLSList;
-
     if( !bTLSKeySetup )
         return;
 
-    papTLSList = (void **) TlsGetValue( nTLSKey );
+    void **papTLSList = (void **) TlsGetValue( nTLSKey );
     if( papTLSList == NULL )
         return;
 
@@ -1250,7 +1295,7 @@ void CPLCleanupTLS()
     CPLCleanupTLSList( papTLSList );
 }
 
-/* endif CPL_MULTIPROC_WIN32 */
+// endif CPL_MULTIPROC_WIN32
 
 #elif defined(CPL_MULTIPROC_PTHREAD)
 
@@ -1273,7 +1318,7 @@ void CPLCleanupTLS()
 int CPLGetNumCPUs()
 {
 #ifdef _SC_NPROCESSORS_ONLN
-    return (int)sysconf(_SC_NPROCESSORS_ONLN);
+    return static_cast<int>(sysconf(_SC_NPROCESSORS_ONLN));
 #else
     return 1;
 #endif
@@ -1284,18 +1329,19 @@ int CPLGetNumCPUs()
 /************************************************************************/
 
 static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
-static CPLMutex *CPLCreateMutexInternal(int bAlreadyInGlobalLock, int nOptions);
+static CPLMutex *CPLCreateMutexInternal( bool bAlreadyInGlobalLock,
+                                         int nOptions );
 
 int CPLCreateOrAcquireMutexEx( CPLMutex **phMutex, double dfWaitInSeconds,
                                int nOptions )
 
 {
-    int bSuccess = FALSE;
+    bool bSuccess = false;
 
     pthread_mutex_lock(&global_mutex);
     if( *phMutex == NULL )
     {
-        *phMutex = CPLCreateMutexInternal(TRUE, nOptions);
+        *phMutex = CPLCreateMutexInternal(true, nOptions);
         bSuccess = *phMutex != NULL;
         pthread_mutex_unlock(&global_mutex);
     }
@@ -1303,7 +1349,7 @@ int CPLCreateOrAcquireMutexEx( CPLMutex **phMutex, double dfWaitInSeconds,
     {
         pthread_mutex_unlock(&global_mutex);
 
-        bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds );
+        bSuccess = CPL_TO_BOOL(CPLAcquireMutex( *phMutex, dfWaitInSeconds ));
     }
 
     return bSuccess;
@@ -1317,17 +1363,19 @@ static
 int CPLCreateOrAcquireMutexInternal( CPLLock **phLock, double dfWaitInSeconds,
                                      CPLLockType eType )
 {
-    int bSuccess = FALSE;
+    bool bSuccess = false;
 
     pthread_mutex_lock(&global_mutex);
     if( *phLock == NULL )
     {
-        *phLock = (CPLLock*) calloc(1, sizeof(CPLLock));
+        *phLock = static_cast<CPLLock *>(calloc(1, sizeof(CPLLock)));
         if( *phLock )
         {
             (*phLock)->eType = eType;
-            (*phLock)->u.hMutex = CPLCreateMutexInternal(TRUE,
-                (eType == LOCK_RECURSIVE_MUTEX) ? CPL_MUTEX_RECURSIVE : CPL_MUTEX_ADAPTIVE );
+            (*phLock)->u.hMutex = CPLCreateMutexInternal(
+                true,
+                eType == LOCK_RECURSIVE_MUTEX
+                ? CPL_MUTEX_RECURSIVE : CPL_MUTEX_ADAPTIVE );
             if( (*phLock)->u.hMutex == NULL )
             {
                 free(*phLock);
@@ -1341,7 +1389,8 @@ int CPLCreateOrAcquireMutexInternal( CPLLock **phLock, double dfWaitInSeconds,
     {
         pthread_mutex_unlock(&global_mutex);
 
-        bSuccess = CPLAcquireMutex( (*phLock)->u.hMutex, dfWaitInSeconds );
+        bSuccess = CPL_TO_BOOL(
+            CPLAcquireMutex( (*phLock)->u.hMutex, dfWaitInSeconds ));
     }
 
     return bSuccess;
@@ -1371,7 +1420,7 @@ struct _MutexLinkedElt
 };
 static MutexLinkedElt* psMutexList = NULL;
 
-static void CPLInitMutex(MutexLinkedElt* psItem)
+static void CPLInitMutex( MutexLinkedElt* psItem )
 {
     if( psItem->nOptions == CPL_MUTEX_REGULAR )
     {
@@ -1380,12 +1429,12 @@ static void CPLInitMutex(MutexLinkedElt* psItem)
         return;
     }
 
-    /* When an adaptive mutex is required, we can safely fallback to regular */
-    /* mutex if we don't have HAVE_PTHREAD_MUTEX_ADAPTIVE_NP */
+    // When an adaptive mutex is required, we can safely fallback to regular
+    // mutex if we don't have HAVE_PTHREAD_MUTEX_ADAPTIVE_NP.
     if( psItem->nOptions == CPL_MUTEX_ADAPTIVE )
     {
 #if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP)
-        pthread_mutexattr_t  attr;
+        pthread_mutexattr_t attr;
         pthread_mutexattr_init( &attr );
         pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ADAPTIVE_NP );
         pthread_mutex_init( &(psItem->sMutex), &attr );
@@ -1398,16 +1447,16 @@ static void CPLInitMutex(MutexLinkedElt* psItem)
 
 #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
     {
-        pthread_mutexattr_t  attr;
+        pthread_mutexattr_t attr;
         pthread_mutexattr_init( &attr );
         pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
         pthread_mutex_init( &(psItem->sMutex), &attr );
     }
-/* BSDs have PTHREAD_MUTEX_RECURSIVE as an enum, not a define. */
-/* But they have #define MUTEX_TYPE_COUNTING_FAST   PTHREAD_MUTEX_RECURSIVE */
+// BSDs have PTHREAD_MUTEX_RECURSIVE as an enum, not a define.
+// But they have #define MUTEX_TYPE_COUNTING_FAST PTHREAD_MUTEX_RECURSIVE
 #elif defined(MUTEX_TYPE_COUNTING_FAST)
     {
-        pthread_mutexattr_t  attr;
+        pthread_mutexattr_t attr;
         pthread_mutexattr_init( &attr );
         pthread_mutexattr_settype( &attr, MUTEX_TYPE_COUNTING_FAST );
         pthread_mutex_init( &(psItem->sMutex), &attr );
@@ -1420,10 +1469,12 @@ static void CPLInitMutex(MutexLinkedElt* psItem)
 #endif
 }
 
-static CPLMutex *CPLCreateMutexInternal(int bAlreadyInGlobalLock, int nOptions)
+static CPLMutex *CPLCreateMutexInternal( bool bAlreadyInGlobalLock,
+                                         int nOptions )
 {
-    MutexLinkedElt* psItem = (MutexLinkedElt *) malloc(sizeof(MutexLinkedElt));
-    if (psItem == NULL)
+    MutexLinkedElt* psItem = static_cast<MutexLinkedElt *>(
+        malloc(sizeof(MutexLinkedElt)) );
+    if( psItem == NULL )
     {
         fprintf(stderr, "CPLCreateMutexInternal() failed.\n");
         return NULL;
@@ -1442,7 +1493,7 @@ static CPLMutex *CPLCreateMutexInternal(int bAlreadyInGlobalLock, int nOptions)
     psItem->nOptions = nOptions;
     CPLInitMutex(psItem);
 
-    // mutexes are implicitly acquired when created.
+    // Mutexes are implicitly acquired when created.
     CPLAcquireMutex( (CPLMutex*)psItem, 0.0 );
 
     return (CPLMutex*)psItem;
@@ -1450,31 +1501,31 @@ static CPLMutex *CPLCreateMutexInternal(int bAlreadyInGlobalLock, int nOptions)
 
 CPLMutex *CPLCreateMutex()
 {
-    return CPLCreateMutexInternal(FALSE, CPL_MUTEX_RECURSIVE);
+    return CPLCreateMutexInternal(false, CPL_MUTEX_RECURSIVE);
 }
 
-CPLMutex *CPLCreateMutexEx(int nOptions)
+CPLMutex *CPLCreateMutexEx( int nOptions )
 {
-    return CPLCreateMutexInternal(FALSE, nOptions);
+    return CPLCreateMutexInternal(false, nOptions);
 }
 
 /************************************************************************/
 /*                          CPLAcquireMutex()                           */
 /************************************************************************/
 
-int CPLAcquireMutex( CPLMutex *hMutexIn, CPL_UNUSED double dfWaitInSeconds )
+int CPLAcquireMutex( CPLMutex *hMutexIn, double /* dfWaitInSeconds */ )
 {
-
-    /* we need to add timeout support */
+    // TODO: Need to add timeout support.
     MutexLinkedElt* psItem = (MutexLinkedElt *) hMutexIn;
     const int err = pthread_mutex_lock( &(psItem->sMutex) );
 
     if( err != 0 )
     {
         if( err == EDEADLK )
-            fprintf(stderr, "CPLAcquireMutex: Error = %d/EDEADLK", err );
+            fprintf(stderr, "CPLAcquireMutex: Error = %d/EDEADLK\n", err );
         else
-            fprintf(stderr, "CPLAcquireMutex: Error = %d", err );
+            fprintf(stderr, "CPLAcquireMutex: Error = %d (%s)\n", err,
+                    strerror(err));
 
         return FALSE;
     }
@@ -1490,7 +1541,12 @@ void CPLReleaseMutex( CPLMutex *hMutexIn )
 
 {
     MutexLinkedElt* psItem = (MutexLinkedElt *) hMutexIn;
-    pthread_mutex_unlock( &(psItem->sMutex) );
+    const int err = pthread_mutex_unlock( &(psItem->sMutex) );
+    if( err != 0 )
+    {
+        fprintf(stderr, "CPLReleaseMutex: Error = %d (%s)\n", err,
+                strerror(err));
+    }
 }
 
 /************************************************************************/
@@ -1501,7 +1557,12 @@ void CPLDestroyMutex( CPLMutex *hMutexIn )
 
 {
     MutexLinkedElt* psItem = (MutexLinkedElt *) hMutexIn;
-    pthread_mutex_destroy( &(psItem->sMutex) );
+    const int err = pthread_mutex_destroy( &(psItem->sMutex) );
+        if( err != 0 )
+    {
+        fprintf(stderr, "CPLDestroyMutex: Error = %d (%s)\n", err,
+                strerror(err));
+    }
     pthread_mutex_lock(&global_mutex);
     if( psItem->psPrev )
         psItem->psPrev->psNext = psItem->psNext;
@@ -1517,13 +1578,13 @@ void CPLDestroyMutex( CPLMutex *hMutexIn )
 /*                          CPLReinitAllMutex()                         */
 /************************************************************************/
 
-/* Used by gdalclientserver.cpp just after forking, to avoid */
-/* deadlocks while mixing threads with fork */
-void CPLReinitAllMutex();
+// Used by gdalclientserver.cpp just after forking, to avoid
+// deadlocks while mixing threads with fork.
+void CPLReinitAllMutex();  // TODO(schwehr): Put this in a header.
 void CPLReinitAllMutex()
 {
     MutexLinkedElt* psItem = psMutexList;
-    while(psItem != NULL )
+    while( psItem != NULL )
     {
         CPLInitMutex(psItem);
         psItem = psItem->psNext;
@@ -1536,10 +1597,11 @@ void CPLReinitAllMutex()
 /*                            CPLCreateCond()                           */
 /************************************************************************/
 
-CPLCond  *CPLCreateCond()
+CPLCond *CPLCreateCond()
 {
-    pthread_cond_t* pCond = (pthread_cond_t* )malloc(sizeof(pthread_cond_t));
-    if (pCond && pthread_cond_init(pCond, NULL) == 0 )
+    pthread_cond_t* pCond =
+      static_cast<pthread_cond_t *>(malloc(sizeof(pthread_cond_t)));
+    if( pCond && pthread_cond_init(pCond, NULL) == 0 )
         return (CPLCond*) pCond;
     fprintf(stderr, "CPLCreateCond() failed.\n");
     free(pCond);
@@ -1550,19 +1612,19 @@ CPLCond  *CPLCreateCond()
 /*                            CPLCondWait()                             */
 /************************************************************************/
 
-void  CPLCondWait( CPLCond *hCond, CPLMutex* hMutex )
+void CPLCondWait( CPLCond *hCond, CPLMutex* hMutex )
 {
     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
     MutexLinkedElt* psItem = (MutexLinkedElt *) hMutex;
     pthread_mutex_t * pMutex = &(psItem->sMutex);
-    pthread_cond_wait(pCond,  pMutex);
+    pthread_cond_wait(pCond, pMutex);
 }
 
 /************************************************************************/
 /*                            CPLCondSignal()                           */
 /************************************************************************/
 
-void  CPLCondSignal( CPLCond *hCond )
+void CPLCondSignal( CPLCond *hCond )
 {
     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
     pthread_cond_signal(pCond);
@@ -1572,7 +1634,7 @@ void  CPLCondSignal( CPLCond *hCond )
 /*                           CPLCondBroadcast()                         */
 /************************************************************************/
 
-void  CPLCondBroadcast( CPLCond *hCond )
+void CPLCondBroadcast( CPLCond *hCond )
 {
     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
     pthread_cond_broadcast(pCond);
@@ -1582,7 +1644,7 @@ void  CPLCondBroadcast( CPLCond *hCond )
 /*                            CPLDestroyCond()                          */
 /************************************************************************/
 
-void  CPLDestroyCond( CPLCond *hCond )
+void CPLDestroyCond( CPLCond *hCond )
 {
     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
     pthread_cond_destroy(pCond);
@@ -1599,9 +1661,6 @@ void  CPLDestroyCond( CPLCond *hCond )
 void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 
 {
-    FILE      *fpLock;
-    char      *pszLockFilename;
-
 /* -------------------------------------------------------------------- */
 /*      We use a lock file with a name derived from the file we want    */
 /*      to lock to represent the file being locked.  Note that for      */
@@ -1609,14 +1668,14 @@ void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 /*      to exist to be locked.                                          */
 /* -------------------------------------------------------------------- */
     const size_t nLen = strlen(pszPath) + 30;
-    pszLockFilename = (char *) CPLMalloc(nLen);
+    char *pszLockFilename = static_cast<char *>(CPLMalloc(nLen));
     snprintf( pszLockFilename, nLen, "%s.lock", pszPath );
 
-    fpLock = fopen( pszLockFilename, "r" );
+    FILE *fpLock = fopen( pszLockFilename, "r" );
     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
     {
         fclose( fpLock );
-        CPLSleep( MIN(dfWaitInSeconds,0.5) );
+        CPLSleep( std::min(dfWaitInSeconds, 0.5) );
         dfWaitInSeconds -= 0.5;
 
         fpLock = fopen( pszLockFilename, "r" );
@@ -1650,7 +1709,7 @@ void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
 void CPLUnlockFile( void *hLock )
 
 {
-    char *pszLockFilename = (char *) hLock;
+    char *pszLockFilename = static_cast<char *>(hLock);
 
     if( hLock == NULL )
         return;
@@ -1667,10 +1726,11 @@ void CPLUnlockFile( void *hLock )
 GIntBig CPLGetPID()
 
 {
-    return (GIntBig) pthread_self();
+    // TODO(schwehr): What is the correct C++ way to do this cast?
+    return (GIntBig)pthread_self();
 }
 
-static pthread_key_t  oTLSKey;
+static pthread_key_t oTLSKey;
 static pthread_once_t oTLSKeySetup = PTHREAD_ONCE_INIT;
 
 /************************************************************************/
@@ -1680,7 +1740,8 @@ static pthread_once_t oTLSKeySetup = PTHREAD_ONCE_INIT;
 static void CPLMake_key()
 
 {
-    if( pthread_key_create( &oTLSKey, (void (*)(void*)) CPLCleanupTLSList ) != 0 )
+    if( pthread_key_create( &oTLSKey,
+                            (void (*)(void*)) CPLCleanupTLSList ) != 0 )
     {
         CPLError( CE_Fatal, CPLE_AppDefined, "pthread_key_create() failed!" );
     }
@@ -1690,14 +1751,13 @@ static void CPLMake_key()
 /*                           CPLGetTLSList()                            */
 /************************************************************************/
 
-static void **CPLGetTLSList(int* pbMemoryErrorOccurred)
+static void **CPLGetTLSList( int* pbMemoryErrorOccurred )
 
 {
-    void **papTLSList;
-
     if( pbMemoryErrorOccurred )
         *pbMemoryErrorOccurred = FALSE;
-    if ( pthread_once(&oTLSKeySetup, CPLMake_key) != 0 )
+
+    if( pthread_once(&oTLSKeySetup, CPLMake_key) != 0 )
     {
         if( pbMemoryErrorOccurred )
         {
@@ -1708,15 +1768,17 @@ static void **CPLGetTLSList(int* pbMemoryErrorOccurred)
         CPLEmergencyError( "CPLGetTLSList(): pthread_once() failed!" );
     }
 
-    papTLSList = (void **) pthread_getspecific( oTLSKey );
+    void **papTLSList = (void **) pthread_getspecific( oTLSKey );
     if( papTLSList == NULL )
     {
-        papTLSList = (void **) VSICalloc(sizeof(void*),CTLS_MAX*2);
+        papTLSList =
+            static_cast<void **>(VSICalloc(sizeof(void*), CTLS_MAX * 2));
         if( papTLSList == NULL )
         {
             if( pbMemoryErrorOccurred )
             {
-                fprintf(stderr, "CPLGetTLSList() failed to allocate TLS list!\n" );
+                fprintf(stderr,
+                        "CPLGetTLSList() failed to allocate TLS list!\n" );
                 *pbMemoryErrorOccurred = TRUE;
                 return NULL;
             }
@@ -1726,7 +1788,8 @@ static void **CPLGetTLSList(int* pbMemoryErrorOccurred)
         {
             if( pbMemoryErrorOccurred )
             {
-                fprintf(stderr, "CPLGetTLSList(): pthread_setspecific() failed!\n" );
+                fprintf(stderr,
+                        "CPLGetTLSList(): pthread_setspecific() failed!\n" );
                 *pbMemoryErrorOccurred = TRUE;
                 return NULL;
             }
@@ -1758,7 +1821,7 @@ typedef struct {
 static void *CPLStdCallThreadJacket( void *pData )
 
 {
-    CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
+    CPLStdCallThreadInfo *psInfo = static_cast<CPLStdCallThreadInfo *>(pData);
 
 #ifdef CHECK_THREAD_CAN_ALLOCATE_TLS
     int bMemoryError = FALSE;
@@ -1774,7 +1837,7 @@ static void *CPLStdCallThreadJacket( void *pData )
 
     psInfo->pfnMain( psInfo->pAppData );
 
-    if (!psInfo->bJoinable)
+    if( !psInfo->bJoinable )
         CPLFree( psInfo );
 
     return NULL;
@@ -1801,11 +1864,8 @@ error:
 int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
 
 {
-
-    CPLStdCallThreadInfo *psInfo;
-    pthread_attr_t hThreadAttr;
-
-    psInfo = (CPLStdCallThreadInfo*) VSI_CALLOC_VERBOSE(sizeof(CPLStdCallThreadInfo),1);
+    CPLStdCallThreadInfo *psInfo = static_cast<CPLStdCallThreadInfo *>(
+        VSI_CALLOC_VERBOSE(sizeof(CPLStdCallThreadInfo), 1));
     if( psInfo == NULL )
         return -1;
     psInfo->pAppData = pThreadArg;
@@ -1824,6 +1884,7 @@ int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
     }
 #endif
 
+    pthread_attr_t hThreadAttr;
     pthread_attr_init( &hThreadAttr );
     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_DETACHED );
     if( pthread_create( &(psInfo->hThread), &hThreadAttr,
@@ -1844,7 +1905,8 @@ int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
         assert(pthread_mutex_lock( &(psInfo->sMutex) ) == 0);
         bool bInitDone = psInfo->bInitDone;
         if( !bInitDone )
-            assert(pthread_cond_wait( &(psInfo->sCond),  &(psInfo->sMutex)  ) == 0);
+            assert(
+                pthread_cond_wait( &(psInfo->sCond), &(psInfo->sMutex)) == 0);
         bInitSucceeded = psInfo->bInitSucceeded;
         assert(pthread_mutex_unlock( &(psInfo->sMutex) ) == 0);
         if( bInitDone )
@@ -1861,20 +1923,19 @@ int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
     }
 #endif
 
-    return 1; /* can we return the actual thread pid? */
+    return 1;  // Can we return the actual thread pid?
 }
 
 /************************************************************************/
 /*                      CPLCreateJoinableThread()                       */
 /************************************************************************/
 
-CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThreadArg )
+CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain,
+                                            void *pThreadArg )
 
 {
-    CPLStdCallThreadInfo *psInfo;
-    pthread_attr_t hThreadAttr;
-
-    psInfo = (CPLStdCallThreadInfo*) VSI_CALLOC_VERBOSE(sizeof(CPLStdCallThreadInfo),1);
+    CPLStdCallThreadInfo *psInfo = static_cast<CPLStdCallThreadInfo *>(
+        VSI_CALLOC_VERBOSE(sizeof(CPLStdCallThreadInfo), 1));
     if( psInfo == NULL )
         return NULL;
     psInfo->pAppData = pThreadArg;
@@ -1893,6 +1954,7 @@ CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThread
     }
 #endif
 
+    pthread_attr_t hThreadAttr;
     pthread_attr_init( &hThreadAttr );
     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_JOINABLE );
     if( pthread_create( &(psInfo->hThread), &hThreadAttr,
@@ -1913,7 +1975,8 @@ CPLJoinableThread* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThread
         assert(pthread_mutex_lock( &(psInfo->sMutex) ) == 0);
         bool bInitDone = psInfo->bInitDone;
         if( !bInitDone )
-            assert(pthread_cond_wait( &(psInfo->sCond),  &(psInfo->sMutex)  ) == 0);
+            assert(
+                pthread_cond_wait( &(psInfo->sCond), &(psInfo->sMutex)) == 0);
         bInitSucceeded = psInfo->bInitSucceeded;
         assert(pthread_mutex_unlock( &(psInfo->sMutex) ) == 0);
         if( bInitDone )
@@ -1958,10 +2021,12 @@ void CPLJoinThread(CPLJoinableThread* hJoinableThread)
 void CPLSleep( double dfWaitInSeconds )
 
 {
-    struct timespec sRequest, sRemain;
+    struct timespec sRequest;
+    struct timespec sRemain;
 
-    sRequest.tv_sec = (int) floor(dfWaitInSeconds);
-    sRequest.tv_nsec = (int) ((dfWaitInSeconds - sRequest.tv_sec)*1000000000);
+    sRequest.tv_sec = static_cast<int>(floor(dfWaitInSeconds));
+    sRequest.tv_nsec =
+        static_cast<int>((dfWaitInSeconds - sRequest.tv_sec) * 1000000000);
     nanosleep( &sRequest, &sRemain );
 }
 
@@ -1972,7 +2037,7 @@ void CPLSleep( double dfWaitInSeconds )
 void CPLFinalizeTLS()
 {
     CPLCleanupTLS();
-    /* See #5509 for the explanation why this may be needed */
+    // See #5509 for the explanation why this may be needed.
     pthread_key_delete(oTLSKey);
 }
 
@@ -1983,9 +2048,7 @@ void CPLFinalizeTLS()
 void CPLCleanupTLS()
 
 {
-    void **papTLSList;
-
-    papTLSList = (void **) pthread_getspecific( oTLSKey );
+    void **papTLSList = (void **) pthread_getspecific( oTLSKey );
     if( papTLSList == NULL )
         return;
 
@@ -2006,9 +2069,10 @@ struct _CPLSpinLock
     pthread_spinlock_t spin;
 };
 
-CPLSpinLock  *CPLCreateSpinLock( void )
+CPLSpinLock *CPLCreateSpinLock()
 {
-    CPLSpinLock* psSpin = (CPLSpinLock*)malloc(sizeof(CPLSpinLock));
+    CPLSpinLock* psSpin =
+        static_cast<CPLSpinLock *>(malloc(sizeof(CPLSpinLock)));
     if( psSpin != NULL &&
         pthread_spin_init(&(psSpin->spin), PTHREAD_PROCESS_PRIVATE) == 0 )
     {
@@ -2035,12 +2099,12 @@ int   CPLAcquireSpinLock( CPLSpinLock* psSpin )
 /*                   CPLCreateOrAcquireSpinLockInternal()               */
 /************************************************************************/
 
-int  CPLCreateOrAcquireSpinLockInternal( CPLLock** ppsLock )
+int CPLCreateOrAcquireSpinLockInternal( CPLLock** ppsLock )
 {
     pthread_mutex_lock(&global_mutex);
     if( *ppsLock == NULL )
     {
-        *ppsLock = (CPLLock*) calloc(1, sizeof(CPLLock));
+        *ppsLock = static_cast<CPLLock *>(calloc(1, sizeof(CPLLock)));
         if( *ppsLock != NULL )
         {
             (*ppsLock)->eType = LOCK_SPIN;
@@ -2053,7 +2117,7 @@ int  CPLCreateOrAcquireSpinLockInternal( CPLLock** ppsLock )
         }
     }
     pthread_mutex_unlock(&global_mutex);
-    /* coverity[missing_unlock] */
+    // coverity[missing_unlock]
     return( *ppsLock != NULL && CPLAcquireSpinLock( (*ppsLock)->u.hSpinLock ) );
 }
 
@@ -2061,7 +2125,7 @@ int  CPLCreateOrAcquireSpinLockInternal( CPLLock** ppsLock )
 /*                       CPLReleaseSpinLock()                           */
 /************************************************************************/
 
-void  CPLReleaseSpinLock( CPLSpinLock* psSpin )
+void CPLReleaseSpinLock( CPLSpinLock* psSpin )
 {
     pthread_spin_unlock( &(psSpin->spin) );
 }
@@ -2070,14 +2134,14 @@ void  CPLReleaseSpinLock( CPLSpinLock* psSpin )
 /*                        CPLDestroySpinLock()                          */
 /************************************************************************/
 
-void  CPLDestroySpinLock( CPLSpinLock* psSpin )
+void CPLDestroySpinLock( CPLSpinLock* psSpin )
 {
     pthread_spin_destroy( &(psSpin->spin) );
     free( psSpin );
 }
-#endif /* HAVE_PTHREAD_SPINLOCK */
+#endif  // HAVE_PTHREAD_SPINLOCK
 
-#endif /* def CPL_MULTIPROC_PTHREAD */
+#endif  // def CPL_MULTIPROC_PTHREAD
 
 /************************************************************************/
 /*                             CPLGetTLS()                              */
@@ -2123,8 +2187,8 @@ void CPLSetTLS( int nIndex, void *pData, int bFreeOnExit )
 /*                      CPLSetTLSWithFreeFunc()                         */
 /************************************************************************/
 
-/* Warning : the CPLTLSFreeFunc must not in any case directly or indirectly */
-/* use or fetch any TLS data, or a terminating thread will hang ! */
+// Warning: The CPLTLSFreeFunc must not in any case directly or indirectly
+// use or fetch any TLS data, or a terminating thread will hang!
 void CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree )
 
 {
@@ -2140,10 +2204,11 @@ void CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree )
 /*                      CPLSetTLSWithFreeFuncEx()                       */
 /************************************************************************/
 
-/* Warning : the CPLTLSFreeFunc must not in any case directly or indirectly */
-/* use or fetch any TLS data, or a terminating thread will hang ! */
+// Warning: the CPLTLSFreeFunc must not in any case directly or indirectly
+// use or fetch any TLS data, or a terminating thread will hang!
 void CPLSetTLSWithFreeFuncEx( int nIndex, void *pData,
-                              CPLTLSFreeFunc pfnFree, int* pbMemoryErrorOccurred  )
+                              CPLTLSFreeFunc pfnFree,
+                              int* pbMemoryErrorOccurred )
 
 {
     void **papTLSList = CPLGetTLSList(pbMemoryErrorOccurred);
@@ -2155,7 +2220,7 @@ void CPLSetTLSWithFreeFuncEx( int nIndex, void *pData,
 }
 #ifndef HAVE_SPINLOCK_IMPL
 
-/* No spinlock specific API ? Fallback to mutex */
+// No spinlock specific API? Fallback to mutex.
 
 /************************************************************************/
 /*                          CPLCreateSpinLock()                         */
@@ -2182,7 +2247,7 @@ int   CPLCreateOrAcquireSpinLockInternal( CPLLock** ppsLock )
 /*                        CPLAcquireSpinLock()                          */
 /************************************************************************/
 
-int  CPLAcquireSpinLock( CPLSpinLock* psSpin )
+int CPLAcquireSpinLock( CPLSpinLock* psSpin )
 {
     return CPLAcquireMutex( (CPLMutex*)psSpin, 1000 );
 }
@@ -2191,7 +2256,7 @@ int  CPLAcquireSpinLock( CPLSpinLock* psSpin )
 /*                       CPLReleaseSpinLock()                           */
 /************************************************************************/
 
-void  CPLReleaseSpinLock( CPLSpinLock* psSpin )
+void CPLReleaseSpinLock( CPLSpinLock* psSpin )
 {
     CPLReleaseMutex( (CPLMutex*)psSpin );
 }
@@ -2200,13 +2265,12 @@ void  CPLReleaseSpinLock( CPLSpinLock* psSpin )
 /*                        CPLDestroySpinLock()                          */
 /************************************************************************/
 
-void  CPLDestroySpinLock( CPLSpinLock* psSpin )
+void CPLDestroySpinLock( CPLSpinLock* psSpin )
 {
     CPLDestroyMutex( (CPLMutex*)psSpin );
 }
 
-#endif /* HAVE_SPINLOCK_IMPL */
-
+#endif  // HAVE_SPINLOCK_IMPL
 
 /************************************************************************/
 /*                            CPLCreateLock()                           */
@@ -2220,11 +2284,12 @@ CPLLock *CPLCreateLock( CPLLockType eType )
         case LOCK_ADAPTIVE_MUTEX:
         {
             CPLMutex* hMutex = CPLCreateMutexEx(
-                (eType == LOCK_RECURSIVE_MUTEX) ? CPL_MUTEX_RECURSIVE : CPL_MUTEX_ADAPTIVE);
-            if(!hMutex)
+                eType == LOCK_RECURSIVE_MUTEX
+                ? CPL_MUTEX_RECURSIVE : CPL_MUTEX_ADAPTIVE);
+            if( !hMutex )
                 return NULL;
             CPLReleaseMutex(hMutex);
-            CPLLock* psLock = (CPLLock*)malloc(sizeof(CPLLock));
+            CPLLock* psLock = static_cast<CPLLock *>(malloc(sizeof(CPLLock)));
             if( psLock == NULL )
             {
                 fprintf(stderr, "CPLCreateLock() failed.\n");
@@ -2234,7 +2299,7 @@ CPLLock *CPLCreateLock( CPLLockType eType )
             psLock->eType = eType;
             psLock->u.hMutex = hMutex;
 #ifdef DEBUG_CONTENTION
-            psLock->bDebugPerf = FALSE;
+            psLock->bDebugPerf = false;
 #endif
             return psLock;
         }
@@ -2243,7 +2308,7 @@ CPLLock *CPLCreateLock( CPLLockType eType )
             CPLSpinLock* hSpinLock = CPLCreateSpinLock();
             if( !hSpinLock )
                 return NULL;
-            CPLLock* psLock = (CPLLock*)malloc(sizeof(CPLLock));
+            CPLLock* psLock = static_cast<CPLLock *>(malloc(sizeof(CPLLock)));
             if( psLock == NULL )
             {
                 fprintf(stderr, "CPLCreateLock() failed.\n");
@@ -2253,12 +2318,12 @@ CPLLock *CPLCreateLock( CPLLockType eType )
             psLock->eType = eType;
             psLock->u.hSpinLock = hSpinLock;
 #ifdef DEBUG_CONTENTION
-            psLock->bDebugPerf = FALSE;
+            psLock->bDebugPerf = false;
 #endif
             return psLock;
         }
         default:
-            CPLAssert(0);
+            CPLAssert(false);
             return NULL;
     }
 }
@@ -2290,7 +2355,7 @@ int   CPLCreateOrAcquireLock( CPLLock** ppsLock, CPLLockType eType )
             break;
         }
         default:
-            CPLAssert(0);
+            CPLAssert(false);
             return FALSE;
     }
 #ifdef DEBUG_CONTENTION
@@ -2306,7 +2371,7 @@ int   CPLCreateOrAcquireLock( CPLLock** ppsLock, CPLLockType eType )
 /*                          CPLAcquireLock()                            */
 /************************************************************************/
 
-int  CPLAcquireLock( CPLLock* psLock )
+int CPLAcquireLock( CPLLock* psLock )
 {
 #ifdef DEBUG_CONTENTION
     if( psLock->bDebugPerf )
@@ -2322,24 +2387,25 @@ int  CPLAcquireLock( CPLLock* psLock )
 /*                         CPLReleaseLock()                             */
 /************************************************************************/
 
-void  CPLReleaseLock( CPLLock* psLock )
+void CPLReleaseLock( CPLLock* psLock )
 {
 #ifdef DEBUG_CONTENTION
-    int bHitMaxDiff = FALSE;
+    bool bHitMaxDiff = false;
     GIntBig nMaxDiff = 0;
     double dfAvgDiff = 0;
     GUIntBig nIters = 0;
     if( psLock->bDebugPerf && psLock->nStartTime )
     {
-        GUIntBig nStopTime = CPLrdtscp();
-        GIntBig nDiffTime = (GIntBig)(nStopTime - psLock->nStartTime);
+        const GUIntBig nStopTime = CPLrdtscp();
+        const GIntBig nDiffTime =
+            static_cast<GIntBig>(nStopTime - psLock->nStartTime);
         if( nDiffTime > psLock->nMaxDiff )
         {
-            bHitMaxDiff = TRUE;
+            bHitMaxDiff = true;
             psLock->nMaxDiff = nDiffTime;
         }
         nMaxDiff = psLock->nMaxDiff;
-        psLock->nIters ++;
+        psLock->nIters++;
         nIters = psLock->nIters;
         psLock->dfAvgDiff += (nDiffTime - psLock->dfAvgDiff) / nIters;
         dfAvgDiff = psLock->dfAvgDiff;
@@ -2350,7 +2416,8 @@ void  CPLReleaseLock( CPLLock* psLock )
     else
         CPLReleaseMutex( psLock->u.hMutex );
 #ifdef DEBUG_CONTENTION
-    if( psLock->bDebugPerf && (bHitMaxDiff || (psLock->nIters % 1000000) == (1000000-1) ))
+    if( psLock->bDebugPerf &&
+        (bHitMaxDiff || (psLock->nIters % 1000000) == (1000000-1) ))
     {
         CPLDebug("LOCK", "Lock contention : max = " CPL_FRMT_GIB ", avg = %.0f",
                  nMaxDiff, dfAvgDiff);
@@ -2362,7 +2429,7 @@ void  CPLReleaseLock( CPLLock* psLock )
 /*                          CPLDestroyLock()                            */
 /************************************************************************/
 
-void  CPLDestroyLock( CPLLock* psLock )
+void CPLDestroyLock( CPLLock* psLock )
 {
     if( psLock->eType == LOCK_SPIN )
         CPLDestroySpinLock( psLock->u.hSpinLock );
@@ -2378,7 +2445,7 @@ void  CPLDestroyLock( CPLLock* psLock )
 #ifdef DEBUG_CONTENTION
 void CPLLockSetDebugPerf(CPLLock* psLock, int bEnableIn)
 {
-    psLock->bDebugPerf = bEnableIn;
+    psLock->bDebugPerf = CPL_TO_BOOL(bEnableIn);
 }
 #else
 void CPLLockSetDebugPerf(CPLLock* /* psLock */, int bEnableIn)
@@ -2410,14 +2477,12 @@ CPLLockHolder::CPLLockHolder( CPLLock **phLock,
     nLine = nLineIn;
 
 #ifdef DEBUG_MUTEX
-    /*
-     * XXX: There is no way to use CPLDebug() here because it works with
-     * mutexes itself so we will fall in infinite recursion. Good old
-     * fprintf() will do the job right.
-     */
+    // XXX: There is no way to use CPLDebug() here because it works with
+    // mutexes itself so we will fall in infinite recursion. Good old
+    // fprintf() will do the job right.
     fprintf( stderr,
              "CPLLockHolder: Request %p for pid %ld at %d/%s.\n",
-             *phLock, (long) CPLGetPID(), nLine, pszFile );
+             *phLock, static_cast<long>(CPLGetPID()), nLine, pszFile );
 #endif
 
     if( !CPLCreateOrAcquireLock( phLock, eType ) )
@@ -2430,12 +2495,12 @@ CPLLockHolder::CPLLockHolder( CPLLock **phLock,
 #ifdef DEBUG_MUTEX
         fprintf( stderr,
                  "CPLLockHolder: Acquired %p for pid %ld at %d/%s.\n",
-                 *phLock, (long) CPLGetPID(), nLine, pszFile );
+                 *phLock, static_cast<long>(CPLGetPID()), nLine, pszFile );
 #endif
 
         hLock = *phLock;
     }
-#endif /* ndef MUTEX_NONE */
+#endif  // ndef MUTEX_NONE
 }
 
 /************************************************************************/
@@ -2460,7 +2525,7 @@ CPLLockHolder::CPLLockHolder( CPLLock *hLockIn,
             hLock = NULL;
         }
     }
-#endif /* ndef MUTEX_NONE */
+#endif // ndef MUTEX_NONE
 }
 
 /************************************************************************/
@@ -2476,11 +2541,11 @@ CPLLockHolder::~CPLLockHolder()
 #ifdef DEBUG_MUTEX
         fprintf( stderr,
                  "~CPLLockHolder: Release %p for pid %ld at %d/%s.\n",
-                 hLock, (long) CPLGetPID(), nLine, pszFile );
+                 hLock, static_cast<long>(CPLGetPID()), nLine, pszFile );
 #endif
         CPLReleaseLock( hLock );
     }
-#endif /* ndef MUTEX_NONE */
+#endif  // ndef MUTEX_NONE
 }
 
 /************************************************************************/
diff --git a/port/cpl_multiproc.h b/port/cpl_multiproc.h
index 0a3cfba..5a0d623 100644
--- a/port/cpl_multiproc.h
+++ b/port/cpl_multiproc.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_multiproc.h 33817 2016-03-30 17:35:37Z rouault $
+ * $Id: cpl_multiproc.h 35921 2016-10-25 02:28:29Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL Multi-Threading, and process handling portability functions.
@@ -101,7 +101,6 @@ const char CPL_DLL *CPLGetThreadingModel( void );
 
 int CPL_DLL CPLGetNumCPUs( void );
 
-
 typedef struct _CPLLock CPLLock;
 
 /* Currently LOCK_ADAPTIVE_MUTEX is Linux-only and LOCK_SPIN only available */
@@ -121,7 +120,6 @@ void  CPL_DLL  CPLReleaseLock( CPLLock* );
 void  CPL_DLL  CPLDestroyLock( CPLLock* );
 void  CPL_DLL  CPLLockSetDebugPerf( CPLLock*, int bEnableIn ); /* only available on x86/x86_64 with GCC for now */
 
-
 CPL_C_END
 
 #ifdef __cplusplus
@@ -137,23 +135,25 @@ CPL_C_END
 /* be a no-op. The parameter x should be a (void*) */
 #define CPLMutexHolderOptionalLockD(x)  CPLMutexHolder oHolder(x,1000.0,__FILE__,__LINE__);
 
+/** Object to hold a mutex */
 class CPL_DLL CPLMutexHolder
 {
   private:
     CPLMutex   *hMutex;
+    // Only used for debugging.
     const char *pszFile;
     int         nLine;
 
   public:
 
-    /* Instantiates the mutex if not already done. */
+    /** Instantiates the mutex if not already done. */
     CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds = 1000.0,
                     const char *pszFile = __FILE__,
                     int nLine = __LINE__,
                     int nOptions = CPL_MUTEX_RECURSIVE);
 
-    /* This variant assumes the mutex has already been created. If not, it will */
-    /* be a no-op */
+    /** This variant assumes the mutex has already been created. If not, it will
+     * be a no-op */
     CPLMutexHolder( CPLMutex* hMutex, double dfWaitInSeconds = 1000.0,
                     const char *pszFile = __FILE__,
                     int nLine = __LINE__ );
@@ -168,6 +168,7 @@ class CPL_DLL CPLMutexHolder
 /* be a no-op. The parameter should be (CPLLock*) */
 #define CPLLockHolderOptionalLockD(x)  CPLLockHolder oHolder(x,__FILE__,__LINE__);
 
+/** Object to hold a lock */
 class CPL_DLL CPLLockHolder
 {
   private:
@@ -177,13 +178,13 @@ class CPL_DLL CPLLockHolder
 
   public:
 
-    /* Instantiates the lock if not already done. */
+    /** Instantiates the lock if not already done. */
     CPLLockHolder( CPLLock **phSpin, CPLLockType eType,
                     const char *pszFile = __FILE__,
                     int nLine = __LINE__);
 
-    /* This variant assumes the lock has already been created. If not, it will */
-    /* be a no-op */
+    /** This variant assumes the lock has already been created. If not, it will
+     * be a no-op */
     CPLLockHolder( CPLLock* hSpin,
                     const char *pszFile = __FILE__,
                     int nLine = __LINE__ );
@@ -191,7 +192,6 @@ class CPL_DLL CPLLockHolder
     ~CPLLockHolder();
 };
 
-
 #endif /* def __cplusplus */
 
 /* -------------------------------------------------------------------- */
diff --git a/port/cpl_odbc.cpp b/port/cpl_odbc.cpp
index b3acd18..8780e93 100644
--- a/port/cpl_odbc.cpp
+++ b/port/cpl_odbc.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_odbc.cpp 33807 2016-03-29 19:06:42Z tamas $
  *
  * Project:  OGR ODBC Driver
  * Purpose:  Declarations for ODBC Access Cover API.
@@ -33,8 +32,7 @@
 #include "cpl_string.h"
 #include "cpl_error.h"
 
-
-CPL_CVSID("$Id: cpl_odbc.cpp 33807 2016-03-29 19:06:42Z tamas $");
+CPL_CVSID("$Id: cpl_odbc.cpp 36945 2016-12-18 06:05:56Z goatbar $");
 
 #ifndef SQLColumns_TABLE_CAT
 #define SQLColumns_TABLE_CAT 1
@@ -55,7 +53,7 @@ CPL_CVSID("$Id: cpl_odbc.cpp 33807 2016-03-29 19:06:42Z tamas $");
 #define SQLColumns_CHAR_OCTET_LENGTH 16
 #define SQLColumns_ORDINAL_POSITION 17
 #define SQLColumns_IS_NULLABLE 18
-#endif /* ndef SQLColumns_TABLE_CAT */
+#endif  // ndef SQLColumns_TABLE_CAT
 
 /************************************************************************/
 /*                           CPLODBCDriverInstaller()                   */
@@ -79,44 +77,44 @@ int CPLODBCDriverInstaller::InstallDriver( const char* pszDriver,
 {
     CPLAssert( NULL != pszDriver );
 
-    // Try to install driver to system-wide location
-    if ( FALSE == SQLInstallDriverEx( pszDriver, NULL, m_szPathOut,
-                    ODBC_FILENAME_MAX, NULL, fRequest,
-                    &m_nUsageCount ) )
+    // Try to install driver to system-wide location.
+    if( FALSE == SQLInstallDriverEx( pszDriver, NULL, m_szPathOut,
+                                     ODBC_FILENAME_MAX, NULL, fRequest,
+                                     &m_nUsageCount ) )
     {
-        const WORD nErrorNum = 1; // TODO - a function param?
+        const WORD nErrorNum = 1;  // TODO - a function param?
         CPL_UNUSED RETCODE cRet = SQL_ERROR;
 
         // Failure is likely related to no write permissions to
-        // system-wide default location, so try to install to HOME
+        // system-wide default location, so try to install to HOME.
 
         static char* pszEnvIni = NULL;
-        if (pszEnvIni == NULL)
+        if( pszEnvIni == NULL )
         {
-            // Read HOME location
+            // Read HOME location.
             char* pszEnvHome = NULL;
             pszEnvHome = getenv("HOME");
 
             CPLAssert( NULL != pszEnvHome );
             CPLDebug( "ODBC", "HOME=%s", pszEnvHome );
 
-            // Set ODBCSYSINI variable pointing to HOME location
+            // Set ODBCSYSINI variable pointing to HOME location.
             const size_t nLen = strlen(pszEnvHome) + 12;
-            pszEnvIni = (char *)CPLMalloc( nLen );
+            pszEnvIni = static_cast<char *>(CPLMalloc(nLen));
 
             snprintf( pszEnvIni, nLen, "ODBCSYSINI=%s", pszEnvHome );
-            /* a 'man putenv' shows that we cannot free pszEnvIni */
-            /* because the pointer is used directly by putenv in old glibc */
-            /* coverity[tainted_string] */
+            // A 'man putenv' shows that we cannot free pszEnvIni
+            // because the pointer is used directly by putenv in old glibc.
+            // coverity[tainted_string]
             putenv( pszEnvIni );
 
             CPLDebug( "ODBC", "%s", pszEnvIni );
         }
 
-        // Try to install ODBC driver in new location
-        if ( FALSE == SQLInstallDriverEx( pszDriver, NULL, m_szPathOut,
-                ODBC_FILENAME_MAX, NULL, fRequest,
-                &m_nUsageCount ) )
+        // Try to install ODBC driver in new location.
+        if( FALSE == SQLInstallDriverEx(pszDriver, NULL, m_szPathOut,
+                                        ODBC_FILENAME_MAX, NULL, fRequest,
+                                        &m_nUsageCount) )
         {
             cRet = SQLInstallerError( nErrorNum, &m_nErrorCode,
                             m_szError, SQL_MAX_MESSAGE_LENGTH, NULL );
@@ -135,15 +133,16 @@ int CPLODBCDriverInstaller::InstallDriver( const char* pszDriver,
 /*                           RemoveDriver()                             */
 /************************************************************************/
 
-int CPLODBCDriverInstaller::RemoveDriver( const char* pszDriverName, int fRemoveDSN )
+int CPLODBCDriverInstaller::RemoveDriver( const char* pszDriverName,
+                                          int fRemoveDSN )
 {
     CPLAssert( NULL != pszDriverName );
 
-    if ( FALSE == SQLRemoveDriver( pszDriverName, fRemoveDSN, &m_nUsageCount ) )
+    if( FALSE == SQLRemoveDriver( pszDriverName, fRemoveDSN, &m_nUsageCount ) )
     {
         const WORD nErrorNum = 1; // TODO - a function param?
 
-        // Retrieve error code and message
+        // Retrieve error code and message.
         SQLInstallerError( nErrorNum, &m_nErrorCode,
                            m_szError, SQL_MAX_MESSAGE_LENGTH, NULL );
 
@@ -158,20 +157,21 @@ int CPLODBCDriverInstaller::RemoveDriver( const char* pszDriverName, int fRemove
 /*                           CPLODBCSession()                           */
 /************************************************************************/
 
-CPLODBCSession::CPLODBCSession()
-
+/** Constructor */
+CPLODBCSession::CPLODBCSession() :
+    m_hEnv(NULL),
+    m_hDBC(NULL),
+    m_bInTransaction(FALSE),
+    m_bAutoCommit(TRUE)
 {
     m_szLastError[0] = '\0';
-    m_hEnv = NULL;
-    m_hDBC = NULL;
-    m_bInTransaction = FALSE;
-    m_bAutoCommit = TRUE;
 }
 
 /************************************************************************/
 /*                          ~CPLODBCSession()                           */
 /************************************************************************/
 
+/** Destructor */
 CPLODBCSession::~CPLODBCSession()
 
 {
@@ -182,13 +182,15 @@ CPLODBCSession::~CPLODBCSession()
 /*                            CloseSession()                            */
 /************************************************************************/
 
+/** Close session */
 int CPLODBCSession::CloseSession()
 
 {
     if( m_hDBC!=NULL )
     {
-        if ( IsInTransaction() )
-            CPLError( CE_Warning, CPLE_AppDefined, "Closing session with active transactions." );
+        if( IsInTransaction() )
+            CPLError( CE_Warning, CPLE_AppDefined,
+                      "Closing session with active transactions." );
         CPLDebug( "ODBC", "SQLDisconnect()" );
         SQLDisconnect( m_hDBC );
         SQLFreeConnect( m_hDBC );
@@ -208,23 +210,26 @@ int CPLODBCSession::CloseSession()
 /*                       ClearTransaction()                             */
 /************************************************************************/
 
+/** Clear transaction */
 int CPLODBCSession::ClearTransaction()
 
 {
 #if (ODBCVER >= 0x0300)
 
-    if (m_bAutoCommit)
+    if( m_bAutoCommit )
         return TRUE;
 
     SQLUINTEGER bAutoCommit;
-    /* See if we already in manual commit mode */
-    if ( Failed( SQLGetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, &bAutoCommit, sizeof(SQLUINTEGER), NULL) ) )
+    // See if we already in manual commit mode.
+    if( Failed( SQLGetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, &bAutoCommit,
+                                   sizeof(SQLUINTEGER), NULL) ) )
         return FALSE;
 
-    if (bAutoCommit == SQL_AUTOCOMMIT_OFF)
+    if( bAutoCommit == SQL_AUTOCOMMIT_OFF )
     {
-        /* switch the connection to auto commit mode (default) */
-        if( Failed( SQLSetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0 ) ) )
+        // Switch the connection to auto commit mode (default).
+        if( Failed( SQLSetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT,
+                                       (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0 ) ) )
             return FALSE;
     }
 
@@ -239,20 +244,23 @@ int CPLODBCSession::ClearTransaction()
 /*                       CommitTransaction()                            */
 /************************************************************************/
 
+/** Begin transaction */
 int CPLODBCSession::BeginTransaction()
 
 {
 #if (ODBCVER >= 0x0300)
 
     SQLUINTEGER bAutoCommit;
-    /* See if we already in manual commit mode */
-    if ( Failed( SQLGetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, &bAutoCommit, sizeof(SQLUINTEGER), NULL) ) )
+    // See if we already in manual commit mode.
+    if( Failed( SQLGetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, &bAutoCommit,
+                                   sizeof(SQLUINTEGER), NULL) ) )
         return FALSE;
 
-    if (bAutoCommit == SQL_AUTOCOMMIT_ON)
+    if( bAutoCommit == SQL_AUTOCOMMIT_ON )
     {
-        /* switch the connection to manual commit mode */
-        if( Failed( SQLSetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0 ) ) )
+        // Switch the connection to manual commit mode.
+        if( Failed( SQLSetConnectAttr( m_hDBC, SQL_ATTR_AUTOCOMMIT,
+                                       (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0 ) ) )
             return FALSE;
     }
 
@@ -267,12 +275,13 @@ int CPLODBCSession::BeginTransaction()
 /*                       CommitTransaction()                            */
 /************************************************************************/
 
+/** Commit transaction */
 int CPLODBCSession::CommitTransaction()
 
 {
 #if (ODBCVER >= 0x0300)
 
-    if (m_bInTransaction)
+    if( m_bInTransaction )
     {
         if( Failed( SQLEndTran( SQL_HANDLE_DBC, m_hDBC, SQL_COMMIT ) ) )
         {
@@ -289,14 +298,16 @@ int CPLODBCSession::CommitTransaction()
 /*                       RollbackTransaction()                          */
 /************************************************************************/
 
+/** Rollback transaction */
 int CPLODBCSession::RollbackTransaction()
 
 {
 #if (ODBCVER >= 0x0300)
 
-    if (m_bInTransaction)
+    if( m_bInTransaction )
     {
-        /* Rollback should not hide the previous error so Failed() is not called. */
+        // Rollback should not hide the previous error so Failed() is not
+        // called.
         int nRetCode = SQLEndTran( SQL_HANDLE_DBC, m_hDBC, SQL_ROLLBACK );
         m_bInTransaction = FALSE;
 
@@ -309,23 +320,22 @@ int CPLODBCSession::RollbackTransaction()
 
 /************************************************************************/
 /*                               Failed()                               */
-/*                                                                      */
-/*      Test if a return code indicates failure, return TRUE if that    */
-/*      is the case. Also update error text.                            */
 /************************************************************************/
 
+/** Test if a return code indicates failure, return TRUE if that
+ * is the case. Also update error text.
+ */
 int CPLODBCSession::Failed( int nRetCode, HSTMT hStmt )
 
 {
-    SQLCHAR achSQLState[SQL_MAX_MESSAGE_LENGTH];
-    SQLINTEGER nNativeError;
-    SQLSMALLINT nTextLength=0;
-
     m_szLastError[0] = '\0';
 
     if( nRetCode == SQL_SUCCESS || nRetCode == SQL_SUCCESS_WITH_INFO )
         return FALSE;
 
+    SQLCHAR achSQLState[SQL_MAX_MESSAGE_LENGTH] = {};
+    SQLINTEGER nNativeError = 0;
+    SQLSMALLINT nTextLength = 0;
     SQLError( m_hEnv, m_hDBC, hStmt, achSQLState, &nNativeError,
               (SQLCHAR *) m_szLastError, sizeof(m_szLastError)-1,
               &nTextLength );
@@ -375,9 +385,11 @@ int CPLODBCSession::EstablishSession( const char *pszDSN,
 
 #ifdef _MSC_VER
 #pragma warning( push )
-#pragma warning( disable : 4996 )  /*  warning C4996: 'SQLSetConnectOption': ODBC API: SQLSetConnectOption is deprecated. Please use SQLSetConnectAttr instead */
+// warning C4996: 'SQLSetConnectOption': ODBC API: SQLSetConnectOption is
+// deprecated. Please use SQLSetConnectAttr instead
+#pragma warning( disable : 4996 )
 #endif
-    SQLSetConnectOption( m_hDBC,SQL_LOGIN_TIMEOUT,30 );
+    SQLSetConnectOption( m_hDBC, SQL_LOGIN_TIMEOUT, 30 );
 #ifdef _MSC_VER
 #pragma warning( pop )
 #endif
@@ -387,26 +399,26 @@ int CPLODBCSession::EstablishSession( const char *pszDSN,
     if( pszPassword == NULL )
         pszPassword = "";
 
-    int bFailed = FALSE;
-    if( strstr(pszDSN,"=") != NULL )
+    bool bFailed = false;
+    if( strstr(pszDSN, "=") != NULL )
     {
-        SQLCHAR szOutConnString[1024];
+        CPLDebug( "ODBC", "SQLDriverConnect(%s)", pszDSN );
+        SQLCHAR szOutConnString[1024] = {};
         SQLSMALLINT nOutConnStringLen = 0;
 
-        CPLDebug( "ODBC", "SQLDriverConnect(%s)", pszDSN );
-        bFailed = Failed(
+        bFailed = CPL_TO_BOOL(Failed(
             SQLDriverConnect( m_hDBC, NULL,
                               (SQLCHAR *) pszDSN, (SQLSMALLINT)strlen(pszDSN),
                               szOutConnString, sizeof(szOutConnString),
-                              &nOutConnStringLen, SQL_DRIVER_NOPROMPT ) );
+                              &nOutConnStringLen, SQL_DRIVER_NOPROMPT ) ));
     }
     else
     {
         CPLDebug( "ODBC", "SQLConnect(%s)", pszDSN );
-        bFailed = Failed(
+        bFailed = CPL_TO_BOOL(Failed(
             SQLConnect( m_hDBC, (SQLCHAR *) pszDSN, SQL_NTS,
                         (SQLCHAR *) pszUserid, SQL_NTS,
-                        (SQLCHAR *) pszPassword, SQL_NTS ) );
+                        (SQLCHAR *) pszPassword, SQL_NTS ) ));
     }
 
     if( bFailed )
@@ -447,32 +459,28 @@ const char *CPLODBCSession::GetLastError()
 /*                          CPLODBCStatement()                          */
 /************************************************************************/
 
-CPLODBCStatement::CPLODBCStatement( CPLODBCSession *poSession )
-
+/** Constructor */
+CPLODBCStatement::CPLODBCStatement( CPLODBCSession *poSession ) :
+    m_poSession(poSession),
+    m_hStmt(NULL),
+    m_nColCount(0),
+    m_papszColNames(NULL),
+    m_panColType(NULL),
+    m_papszColTypeNames(NULL),
+    m_panColSize(NULL),
+    m_panColPrecision(NULL),
+    m_panColNullable(NULL),
+    m_papszColColumnDef(NULL),
+    m_papszColValues(NULL),
+    m_panColValueLengths(NULL),
+    m_pszStatement(NULL),
+    m_nStatementMax(0),
+    m_nStatementLen(0)
 {
-    m_poSession = poSession;
-
-    m_nColCount = 0;
-    m_papszColNames = NULL;
-    m_panColType = NULL;
-    m_papszColTypeNames = NULL;
-    m_panColSize = NULL;
-    m_panColPrecision = NULL;
-    m_panColNullable = NULL;
-    m_papszColColumnDef = NULL;
-
-    m_papszColValues = NULL;
-    m_panColValueLengths = NULL;
-
-    m_pszStatement = NULL;
-    m_nStatementMax = 0;
-    m_nStatementLen = 0;
 
-    if( Failed(
-            SQLAllocStmt( poSession->GetConnection(), &m_hStmt ) ) )
+    if( Failed(SQLAllocStmt(poSession->GetConnection(), &m_hStmt)) )
     {
         m_hStmt = NULL;
-        return;
     }
 }
 
@@ -480,6 +488,7 @@ CPLODBCStatement::CPLODBCStatement( CPLODBCSession *poSession )
 /*                         ~CPLODBCStatement()                          */
 /************************************************************************/
 
+/** Destructor */
 CPLODBCStatement::~CPLODBCStatement()
 
 {
@@ -513,7 +522,7 @@ int CPLODBCStatement::ExecuteSQL( const char *pszStatement )
 {
     if( m_poSession == NULL || m_hStmt == NULL )
     {
-        // we should post an error.
+        // We should post an error.
         return FALSE;
     }
 
@@ -523,18 +532,18 @@ int CPLODBCStatement::ExecuteSQL( const char *pszStatement )
         Append( pszStatement );
     }
 
-#if (ODBCVER >= 0x0300)
+#if( ODBCVER >= 0x0300 )
 
-    if ( !m_poSession->IsInTransaction() )
+    if( !m_poSession->IsInTransaction() )
     {
-        /* commit pending transactions and set to autocommit mode*/
+        // Commit pending transactions and set to autocommit mode.
         m_poSession->ClearTransaction();
     }
 
 #endif
 
-    /* SQL_NTS=-3 is a valid value for SQLExecDirect */
-    /* coverity[negative_returns] */
+    // SQL_NTS=-3 is a valid value for SQLExecDirect.
+    // coverity[negative_returns]
     if( Failed(
             SQLExecDirect( m_hStmt, (SQLCHAR *) m_pszStatement, SQL_NTS ) ) )
         return FALSE;
@@ -546,64 +555,76 @@ int CPLODBCStatement::ExecuteSQL( const char *pszStatement )
 /*                         CollectResultsInfo()                         */
 /************************************************************************/
 
+/** CollectResultsInfo */
 int CPLODBCStatement::CollectResultsInfo()
 
 {
     if( m_poSession == NULL || m_hStmt == NULL )
     {
-        // we should post an error.
+        // We should post an error.
         return FALSE;
     }
 
-    if( Failed( SQLNumResultCols(m_hStmt,&m_nColCount) ) )
+    if( Failed( SQLNumResultCols(m_hStmt, &m_nColCount) ) )
         return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Allocate per column information.                                */
 /* -------------------------------------------------------------------- */
-    m_papszColNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
-    m_papszColValues = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
-    m_panColValueLengths = (CPL_SQLLEN *) CPLCalloc(sizeof(CPL_SQLLEN),(m_nColCount+1));
-
-    m_panColType = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
-    m_papszColTypeNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
-    m_panColSize = (CPL_SQLULEN *) CPLCalloc(sizeof(CPL_SQLULEN),m_nColCount);
-    m_panColPrecision = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
-    m_panColNullable = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
-    m_papszColColumnDef = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+    m_papszColNames =
+        static_cast<char **>(CPLCalloc(sizeof(char *), m_nColCount + 1));
+    m_papszColValues =
+        static_cast<char **>(CPLCalloc(sizeof(char *), m_nColCount + 1));
+    m_panColValueLengths = static_cast<CPL_SQLLEN *>(
+        CPLCalloc(sizeof(CPL_SQLLEN), m_nColCount + 1));
+
+    m_panColType =
+        static_cast<SQLSMALLINT *>(CPLCalloc(sizeof(SQLSMALLINT), m_nColCount));
+    m_papszColTypeNames =
+        static_cast<char **>(CPLCalloc(sizeof(char *), m_nColCount + 1));
+    m_panColSize =
+        static_cast<CPL_SQLULEN *>(CPLCalloc(sizeof(CPL_SQLULEN), m_nColCount));
+    m_panColPrecision =
+        static_cast<SQLSMALLINT *>(CPLCalloc(sizeof(SQLSMALLINT), m_nColCount));
+    m_panColNullable =
+        static_cast<SQLSMALLINT *>(CPLCalloc(sizeof(SQLSMALLINT), m_nColCount));
+    m_papszColColumnDef =
+        static_cast<char **>(CPLCalloc(sizeof(char *), m_nColCount + 1));
 
 /* -------------------------------------------------------------------- */
 /*      Fetch column descriptions.                                      */
 /* -------------------------------------------------------------------- */
     for( SQLUSMALLINT iCol = 0; iCol < m_nColCount; iCol++ )
     {
-        SQLCHAR     szName[256];
+        SQLCHAR szName[256] = {};
         SQLSMALLINT nNameLength = 0;
 
-        if ( Failed( SQLDescribeCol(m_hStmt, iCol+1,
-                                    szName, sizeof(szName), &nNameLength,
-                                    m_panColType + iCol,
-                                    m_panColSize + iCol,
-                                    m_panColPrecision + iCol,
-                                    m_panColNullable + iCol) ) )
+        if( Failed( SQLDescribeCol(m_hStmt, iCol+1,
+                                   szName, sizeof(szName), &nNameLength,
+                                   m_panColType + iCol,
+                                   m_panColSize + iCol,
+                                   m_panColPrecision + iCol,
+                                   m_panColNullable + iCol) ) )
             return FALSE;
 
         szName[nNameLength] = '\0';  // Paranoid; the string should be
-                                      // null-terminated by the driver
-        m_papszColNames[iCol] = CPLStrdup((const char*)szName);
+                                     // null-terminated by the driver.
+        m_papszColNames[iCol] = CPLStrdup(reinterpret_cast<char *>(szName));
 
         // SQLDescribeCol() fetches just a subset of column attributes.
         // In addition to above data we need data type name.
-        if ( Failed( SQLColAttribute(m_hStmt, iCol + 1, SQL_DESC_TYPE_NAME,
-                                     szName, sizeof(szName),
-                                     &nNameLength, NULL) ) )
+        if( Failed( SQLColAttribute(m_hStmt, iCol + 1, SQL_DESC_TYPE_NAME,
+                                    szName, sizeof(szName),
+                                    &nNameLength, NULL) ) )
             return FALSE;
 
-        szName[nNameLength] = '\0';  // Paranoid
-        m_papszColTypeNames[iCol] = CPLStrdup((const char*)szName);
+        szName[nNameLength] = '\0';  // Paranoid.
+        m_papszColTypeNames[iCol] = CPLStrdup(reinterpret_cast<char *>(szName));
 
-//        CPLDebug( "ODBC", "%s %s %d", m_papszColNames[iCol],
-//                  szName, m_panColType[iCol] );
+#if DEBUG_VERBOSE
+        CPLDebug( "ODBC", "%s %s %d", m_papszColNames[iCol],
+                  szName, m_panColType[iCol] );
+#endif
     }
 
     return TRUE;
@@ -613,12 +634,13 @@ int CPLODBCStatement::CollectResultsInfo()
 /*                            GetRowCountAffected()                     */
 /************************************************************************/
 
+/** GetRowCountAffected */
 int CPLODBCStatement::GetRowCountAffected()
 {
-    SQLLEN nResultCount=0;
+    SQLLEN nResultCount = 0;
     SQLRowCount( m_hStmt, &nResultCount );
 
-    return (int)nResultCount;
+    return static_cast<int>(nResultCount);
 }
 
 /************************************************************************/
@@ -655,8 +677,8 @@ const char *CPLODBCStatement::GetColName( int iCol )
 {
     if( iCol < 0 || iCol >= m_nColCount )
         return NULL;
-    else
-        return m_papszColNames[iCol];
+
+    return m_papszColNames[iCol];
 }
 
 /************************************************************************/
@@ -681,8 +703,8 @@ short CPLODBCStatement::GetColType( int iCol )
 {
     if( iCol < 0 || iCol >= m_nColCount )
         return -1;
-    else
-        return m_panColType[iCol];
+
+    return m_panColType[iCol];
 }
 
 /************************************************************************/
@@ -706,8 +728,8 @@ const char *CPLODBCStatement::GetColTypeName( int iCol )
 {
     if( iCol < 0 || iCol >= m_nColCount )
         return NULL;
-    else
-        return m_papszColTypeNames[iCol];
+
+    return m_papszColTypeNames[iCol];
 }
 
 /************************************************************************/
@@ -727,8 +749,8 @@ short CPLODBCStatement::GetColSize( int iCol )
 {
     if( iCol < 0 || iCol >= m_nColCount )
         return -1;
-    else
-        return (short) m_panColSize[iCol];
+
+    return static_cast<short>(m_panColSize[iCol]);
 }
 
 /************************************************************************/
@@ -749,8 +771,8 @@ short CPLODBCStatement::GetColPrecision( int iCol )
 {
     if( iCol < 0 || iCol >= m_nColCount )
         return -1;
-    else
-        return m_panColPrecision[iCol];
+
+    return m_panColPrecision[iCol];
 }
 
 /************************************************************************/
@@ -770,8 +792,8 @@ short CPLODBCStatement::GetColNullable( int iCol )
 {
     if( iCol < 0 || iCol >= m_nColCount )
         return -1;
-    else
-        return m_panColNullable[iCol];
+
+    return m_panColNullable[iCol];
 }
 
 /************************************************************************/
@@ -794,8 +816,8 @@ const char *CPLODBCStatement::GetColColumnDef( int iCol )
 {
     if( iCol < 0 || iCol >= m_nColCount )
         return NULL;
-    else
-        return m_papszColColumnDef[iCol];
+
+    return m_papszColColumnDef[iCol];
 }
 
 /************************************************************************/
@@ -843,7 +865,7 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
         nRetCode = SQLFetch( m_hStmt );
         if( Failed(nRetCode) )
         {
-            if ( nRetCode != SQL_NO_DATA )
+            if( nRetCode != SQL_NO_DATA )
             {
                 CPLError( CE_Failure, CPLE_AppDefined, "%s",
                           m_poSession->GetLastError() );
@@ -853,10 +875,12 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
     }
     else
     {
-        nRetCode = SQLFetchScroll(m_hStmt, (SQLSMALLINT) nOrientation, nOffset);
+        nRetCode = SQLFetchScroll(m_hStmt,
+                                  static_cast<SQLSMALLINT>(nOrientation),
+                                  nOffset);
         if( Failed(nRetCode) )
         {
-            if ( nRetCode == SQL_NO_DATA )
+            if( nRetCode == SQL_NO_DATA )
             {
                 CPLError( CE_Failure, CPLE_AppDefined, "%s",
                           m_poSession->GetLastError() );
@@ -868,34 +892,30 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
 /* -------------------------------------------------------------------- */
 /*      Pull out all the column values.                                 */
 /* -------------------------------------------------------------------- */
-    SQLSMALLINT iCol;
-
-    for( iCol = 0; iCol < m_nColCount; iCol++ )
+    for( SQLSMALLINT iCol = 0; iCol < m_nColCount; iCol++ )
     {
-        char szWrkData[513];
-        CPL_SQLLEN cbDataLen;
+        CPL_SQLLEN cbDataLen = 0;
         SQLSMALLINT nFetchType = GetTypeMapping( m_panColType[iCol] );
 
         // Handle values other than WCHAR and BINARY as CHAR.
         if( nFetchType != SQL_C_BINARY && nFetchType != SQL_C_WCHAR )
             nFetchType = SQL_C_CHAR;
 
-        szWrkData[0] = '\0';
-        szWrkData[sizeof(szWrkData)-1] = '\0';
+        char szWrkData[513] = {};
 
         nRetCode = SQLGetData( m_hStmt, iCol + 1, nFetchType,
-                               szWrkData, sizeof(szWrkData)-1,
+                               szWrkData, sizeof(szWrkData) - 1,
                                &cbDataLen );
 
-/* SQLGetData() is giving garbage values in the first 4 bytes of cbDataLen *
- * in some architectures. Converting it to (int) discards the unnecessary  *
- * bytes. This should not be a problem unless the buffer size reaches      *
- * 2GB. (#3385)                                                            */
-        cbDataLen = (int) cbDataLen;
+        // SQLGetData() is giving garbage values in the first 4 bytes of
+        // cbDataLen in some architectures. Converting it to int discards the
+        // unnecessary bytes. This should not be a problem unless the buffer
+        // size reaches 2GB. (#3385)
+        cbDataLen = static_cast<int>(cbDataLen);
 
         if( Failed( nRetCode ) )
         {
-            if ( nRetCode == SQL_NO_DATA )
+            if( nRetCode == SQL_NO_DATA )
             {
                 CPLError( CE_Failure, CPLE_AppDefined, "%s",
                           m_poSession->GetLastError() );
@@ -909,23 +929,23 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
             m_panColValueLengths[iCol] = 0;
         }
 
-        // assume big result: should check for state=SQLSATE 01004.
-        else if( nRetCode == SQL_SUCCESS_WITH_INFO  )
+        // Assume big result: should check for state=SQLSATE 01004.
+        else if( nRetCode == SQL_SUCCESS_WITH_INFO )
         {
             if( cbDataLen >= (CPL_SQLLEN)(sizeof(szWrkData)-1) )
             {
                 cbDataLen = (CPL_SQLLEN)(sizeof(szWrkData)-1);
-                if (nFetchType == SQL_C_CHAR)
-                    while ((cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0))
-                        --cbDataLen; // trimming the extra terminators: bug 990
-                else if (nFetchType == SQL_C_WCHAR)
-                    while ((cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0)
+                if( nFetchType == SQL_C_CHAR )
+                    while( (cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0) )
+                        --cbDataLen;  // Trimming the extra terminators: bug 990
+                else if( nFetchType == SQL_C_WCHAR )
+                    while( (cbDataLen > 1) && (szWrkData[cbDataLen - 1] == 0 )
                         && (szWrkData[cbDataLen - 2] == 0))
-                        cbDataLen -= 2; // trimming the extra terminators
-
+                        cbDataLen -= 2;  // Trimming the extra terminators.
             }
 
-            m_papszColValues[iCol] = (char *) CPLMalloc(cbDataLen+2);
+            m_papszColValues[iCol] =
+                static_cast<char *>(CPLMalloc(cbDataLen + 2));
             memcpy( m_papszColValues[iCol], szWrkData, cbDataLen );
             m_papszColValues[iCol][cbDataLen] = '\0';
             m_papszColValues[iCol][cbDataLen+1] = '\0';
@@ -933,9 +953,8 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
 
             while( true )
             {
-                CPL_SQLLEN nChunkLen;
-
-                nRetCode = SQLGetData( m_hStmt, (SQLUSMALLINT) iCol+1,
+                nRetCode = SQLGetData( m_hStmt,
+                                       static_cast<SQLUSMALLINT>(iCol) + 1,
                                        nFetchType,
                                        szWrkData, sizeof(szWrkData)-1,
                                        &cbDataLen );
@@ -949,27 +968,30 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
                     return FALSE;
                 }
 
-                if( cbDataLen >= (int) (sizeof(szWrkData) - 1)
+                CPL_SQLLEN nChunkLen;
+                if( cbDataLen >= static_cast<int>(sizeof(szWrkData) - 1)
                     || cbDataLen == SQL_NO_TOTAL )
                 {
                     nChunkLen = sizeof(szWrkData)-1;
-                    if (nFetchType == SQL_C_CHAR)
-                        while ( (nChunkLen > 1)
-                                && (szWrkData[nChunkLen - 1] == 0) )
-                            --nChunkLen;  // trimming the extra terminators
-                    else if (nFetchType == SQL_C_WCHAR)
-                        while ( (nChunkLen > 1)
-                                && (szWrkData[nChunkLen - 1] == 0)
-                                && (szWrkData[nChunkLen - 2] == 0) )
-                            nChunkLen -= 2;  // trimming the extra terminators
+                    if( nFetchType == SQL_C_CHAR )
+                        while( (nChunkLen > 1)
+                               && (szWrkData[nChunkLen - 1] == 0) )
+                            --nChunkLen;  // Trimming the extra terminators.
+                    else if( nFetchType == SQL_C_WCHAR )
+                        while( (nChunkLen > 1)
+                               && (szWrkData[nChunkLen - 1] == 0)
+                               && (szWrkData[nChunkLen - 2] == 0) )
+                            nChunkLen -= 2;  // Trimming the extra terminators.
                 }
                 else
+                {
                     nChunkLen = cbDataLen;
+                }
                 szWrkData[nChunkLen] = '\0';
 
-                m_papszColValues[iCol] = (char *)
+                m_papszColValues[iCol] = static_cast<char *>(
                     CPLRealloc( m_papszColValues[iCol],
-                                m_panColValueLengths[iCol] + nChunkLen + 2 );
+                                m_panColValueLengths[iCol] + nChunkLen + 2 ));
                 memcpy( m_papszColValues[iCol] + m_panColValueLengths[iCol],
                         szWrkData, nChunkLen );
                 m_panColValueLengths[iCol] += nChunkLen;
@@ -980,7 +1002,8 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
         else
         {
             m_panColValueLengths[iCol] = cbDataLen;
-            m_papszColValues[iCol] = (char *) CPLMalloc(cbDataLen+2);
+            m_papszColValues[iCol] =
+                static_cast<char *>(CPLMalloc(cbDataLen + 2));
             memcpy( m_papszColValues[iCol], szWrkData, cbDataLen );
             m_papszColValues[iCol][cbDataLen] = '\0';
             m_papszColValues[iCol][cbDataLen+1] = '\0';
@@ -992,7 +1015,7 @@ int CPLODBCStatement::Fetch( int nOrientation, int nOffset )
             char *pszTarget = m_papszColValues[iCol];
             size_t iEnd = strlen(pszTarget);
 
-            while ( iEnd > 0 && pszTarget[iEnd - 1] == ' ' )
+            while( iEnd > 0 && pszTarget[iEnd - 1] == ' ' )
                 pszTarget[--iEnd] = '\0';
         }
 
@@ -1068,7 +1091,7 @@ const char *CPLODBCStatement::GetColData( const char *pszColName,
                                           const char *pszDefault )
 
 {
-    int iCol = GetColId( pszColName );
+    const int iCol = GetColId( pszColName );
 
     if( iCol == -1 )
         return pszDefault;
@@ -1080,13 +1103,14 @@ const char *CPLODBCStatement::GetColData( const char *pszColName,
 /*                          GetColDataLength()                          */
 /************************************************************************/
 
+/** GetColDataLength */
 int CPLODBCStatement::GetColDataLength( int iCol )
 
 {
     if( iCol < 0 || iCol >= m_nColCount )
         return 0;
     else if( m_papszColValues[iCol] != NULL )
-        return (int)m_panColValueLengths[iCol];
+        return static_cast<int>(m_panColValueLengths[iCol]);
     else
         return 0;
 }
@@ -1120,6 +1144,7 @@ int CPLODBCStatement::GetColId( const char *pszColName )
 /*                          ClearColumnData()                           */
 /************************************************************************/
 
+/** ClearColumnData */
 void CPLODBCStatement::ClearColumnData()
 
 {
@@ -1140,6 +1165,7 @@ void CPLODBCStatement::ClearColumnData()
 /*                               Failed()                               */
 /************************************************************************/
 
+/** Failed */
 int CPLODBCStatement::Failed( int nResultCode )
 
 {
@@ -1164,19 +1190,20 @@ int CPLODBCStatement::Failed( int nResultCode )
 void CPLODBCStatement::Append( const char *pszText )
 
 {
-    size_t  nTextLen = strlen(pszText);
+    const size_t nTextLen = strlen(pszText);
 
     if( m_nStatementMax < m_nStatementLen + nTextLen + 1 )
     {
         m_nStatementMax = (m_nStatementLen + nTextLen) * 2 + 100;
         if( m_pszStatement == NULL )
         {
-            m_pszStatement = (char *) VSIMalloc(m_nStatementMax);
+            m_pszStatement = static_cast<char *>(VSIMalloc(m_nStatementMax));
             m_pszStatement[0] = '\0';
         }
         else
         {
-            m_pszStatement = (char *) VSIRealloc(m_pszStatement, m_nStatementMax);
+            m_pszStatement = static_cast<char *>(
+                CPLRealloc(m_pszStatement, m_nStatementMax));
         }
     }
 
@@ -1201,10 +1228,11 @@ void CPLODBCStatement::Append( const char *pszText )
 void CPLODBCStatement::AppendEscaped( const char *pszText )
 
 {
-    size_t  iIn, iOut ,nTextLen = strlen(pszText);
-    char    *pszEscapedText = (char *) VSIMalloc(nTextLen*2 + 1);
+    const size_t nTextLen = strlen(pszText);
+    char *pszEscapedText = static_cast<char *>(VSIMalloc(nTextLen*2 + 1));
 
-    for( iIn = 0, iOut = 0; iIn < nTextLen; iIn++ )
+    size_t iOut = 0;  // Used after for.
+    for( size_t iIn = 0; iIn < nTextLen; iIn++ )
     {
         switch( pszText[iIn] )
         {
@@ -1241,7 +1269,7 @@ void CPLODBCStatement::AppendEscaped( const char *pszText )
 void CPLODBCStatement::Append( int nValue )
 
 {
-    char szFormattedValue[32];
+    char szFormattedValue[32] = {};
 
     snprintf( szFormattedValue, sizeof(szFormattedValue), "%d", nValue );
     Append( szFormattedValue );
@@ -1262,7 +1290,7 @@ void CPLODBCStatement::Append( int nValue )
 void CPLODBCStatement::Append( double dfValue )
 
 {
-    char szFormattedValue[100];
+    char szFormattedValue[100] = {};
 
     snprintf( szFormattedValue, sizeof(szFormattedValue), "%24g", dfValue );
     Append( szFormattedValue );
@@ -1284,14 +1312,14 @@ void CPLODBCStatement::Append( double dfValue )
  * @return FALSE if formatting fails due to result being too large.
  */
 
-int CPLODBCStatement::Appendf( const char *pszFormat, ... )
+int CPLODBCStatement::Appendf( CPL_FORMAT_STRING(const char *pszFormat), ... )
 
 {
     va_list args;
 
     va_start( args, pszFormat );
 
-    char szFormattedText[8000];  // TODO: Move this off the stack.
+    char szFormattedText[8000] = {};  // TODO: Move this off the stack.
     szFormattedText[0] = '\0';
 
 #if defined(HAVE_VSNPRINTF)
@@ -1368,7 +1396,6 @@ void CPLODBCStatement::Clear()
         CPLFree( m_panColValueLengths );
         m_panColValueLengths = NULL;
     }
-
 }
 
 /************************************************************************/
@@ -1410,7 +1437,7 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
 
 #if (ODBCVER >= 0x0300)
 
-    if ( !m_poSession->IsInTransaction() )
+    if( !m_poSession->IsInTransaction() )
     {
         /* commit pending transactions and set to autocommit mode*/
         m_poSession->ClearTransaction();
@@ -1433,7 +1460,7 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
 #ifdef notdef
     // SQLRowCount() is too unreliable (with unixodbc on AIX for instance)
     // so we now avoid it.
-    SQLINTEGER nResultCount=0;
+    SQLINTEGER nResultCount = 0;
 
     if( Failed(SQLRowCount( m_hStmt, &nResultCount ) ) )
         nResultCount = 0;
@@ -1446,33 +1473,37 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
 
     m_nColCount = 500;
 
-    m_papszColNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
-    m_papszColValues = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
-
-    m_panColType = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
-    m_papszColTypeNames = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
-    m_panColSize = (CPL_SQLULEN *) CPLCalloc(sizeof(CPL_SQLULEN),m_nColCount);
-    m_panColPrecision = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
-    m_panColNullable = (SQLSMALLINT *) CPLCalloc(sizeof(SQLSMALLINT),m_nColCount);
-    m_papszColColumnDef = (char **) CPLCalloc(sizeof(char *),(m_nColCount+1));
+    m_papszColNames =
+        static_cast<char **>(CPLCalloc(sizeof(char *), m_nColCount + 1));
+    m_papszColValues =
+        static_cast<char **>(CPLCalloc(sizeof(char *), m_nColCount + 1));
+
+    m_panColType =
+        static_cast<SQLSMALLINT *>(CPLCalloc(sizeof(SQLSMALLINT), m_nColCount));
+    m_papszColTypeNames =
+        static_cast<char **>(CPLCalloc(sizeof(char *), m_nColCount + 1));
+    m_panColSize =
+        static_cast<CPL_SQLULEN *>(CPLCalloc(sizeof(CPL_SQLULEN), m_nColCount));
+    m_panColPrecision =
+        static_cast<SQLSMALLINT *>(CPLCalloc(sizeof(SQLSMALLINT), m_nColCount));
+    m_panColNullable =
+        static_cast<SQLSMALLINT *>(CPLCalloc(sizeof(SQLSMALLINT), m_nColCount));
+    m_papszColColumnDef =
+        static_cast<char **>(CPLCalloc(sizeof(char *), m_nColCount + 1));
 
 /* -------------------------------------------------------------------- */
 /*      Establish columns to use for key information.                   */
 /* -------------------------------------------------------------------- */
-    SQLUSMALLINT iCol;
-
-    for( iCol = 0; iCol < m_nColCount; iCol++ )
+    for( SQLUSMALLINT iCol = 0; iCol < m_nColCount; iCol++ )
     {
-        char szWrkData[8193];
-        CPL_SQLLEN cbDataLen;
-
         if( Failed( SQLFetch( m_hStmt ) ) )
         {
             m_nColCount = iCol;
             break;
         }
 
-        szWrkData[0] = '\0';
+        char szWrkData[8193] = {};
+        CPL_SQLLEN cbDataLen = 0;
 
         SQLGetData( m_hStmt, SQLColumns_COLUMN_NAME, SQL_C_CHAR,
                     szWrkData, sizeof(szWrkData)-1, &cbDataLen );
@@ -1480,7 +1511,7 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
 
         SQLGetData( m_hStmt, SQLColumns_DATA_TYPE, SQL_C_CHAR,
                     szWrkData, sizeof(szWrkData)-1, &cbDataLen );
-        m_panColType[iCol] = (short) atoi(szWrkData);
+        m_panColType[iCol] = static_cast<short>(atoi(szWrkData));
 
         SQLGetData( m_hStmt, SQLColumns_TYPE_NAME, SQL_C_CHAR,
                     szWrkData, sizeof(szWrkData)-1, &cbDataLen );
@@ -1492,7 +1523,7 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
 
         SQLGetData( m_hStmt, SQLColumns_DECIMAL_DIGITS, SQL_C_CHAR,
                     szWrkData, sizeof(szWrkData)-1, &cbDataLen );
-        m_panColPrecision[iCol] = (short) atoi(szWrkData);
+        m_panColPrecision[iCol] = static_cast<short>(atoi(szWrkData));
 
         SQLGetData( m_hStmt, SQLColumns_NULLABLE, SQL_C_CHAR,
                     szWrkData, sizeof(szWrkData)-1, &cbDataLen );
@@ -1500,7 +1531,7 @@ int CPLODBCStatement::GetColumns( const char *pszTable,
 #if (ODBCVER >= 0x0300)
         SQLGetData( m_hStmt, SQLColumns_COLUMN_DEF, SQL_C_CHAR,
                     szWrkData, sizeof(szWrkData)-1, &cbDataLen );
-        if (cbDataLen > 0)
+        if( cbDataLen > 0 )
             m_papszColColumnDef[iCol] = CPLStrdup(szWrkData);
 #endif
     }
@@ -1545,7 +1576,7 @@ int CPLODBCStatement::GetPrimaryKeys( const char *pszTable,
 
 #if (ODBCVER >= 0x0300)
 
-    if ( !m_poSession->IsInTransaction() )
+    if( !m_poSession->IsInTransaction() )
     {
         /* commit pending transactions and set to autocommit mode*/
         m_poSession->ClearTransaction();
@@ -1561,8 +1592,8 @@ int CPLODBCStatement::GetPrimaryKeys( const char *pszTable,
                                 (SQLCHAR *) pszSchema, SQL_NTS,
                                 (SQLCHAR *) pszTable, SQL_NTS ) ) )
         return FALSE;
-    else
-        return CollectResultsInfo();
+
+    return CollectResultsInfo();
 }
 
 /************************************************************************/
@@ -1590,14 +1621,14 @@ int CPLODBCStatement::GetTables( const char *pszCatalog,
                                  const char *pszSchema )
 
 {
-    CPLDebug( "ODBC", "CatalogNameL: %s\nSchema name: %s\n",
+    CPLDebug( "ODBC", "CatalogNameL: %s\nSchema name: %s",
                 pszCatalog, pszSchema );
 
 #if (ODBCVER >= 0x0300)
 
-    if ( !m_poSession->IsInTransaction() )
+    if( !m_poSession->IsInTransaction() )
     {
-        /* commit pending transactions and set to autocommit mode*/
+        // Commit pending transactions and set to autocommit mode.
         m_poSession->ClearTransaction();
     }
 
@@ -1612,8 +1643,8 @@ int CPLODBCStatement::GetTables( const char *pszCatalog,
                            (SQLCHAR *) NULL, SQL_NTS,
                            (SQLCHAR *) "'TABLE','VIEW'", SQL_NTS ) ) )
         return FALSE;
-    else
-        return CollectResultsInfo();
+
+    return CollectResultsInfo();
 }
 
 /************************************************************************/
@@ -1795,8 +1826,8 @@ SQLSMALLINT CPLODBCStatement::GetTypeMapping( SQLSMALLINT nTypeCode )
 
         case SQL_BIT:
         case SQL_TINYINT:
-/*        case SQL_TYPE_UTCDATETIME:
-        case SQL_TYPE_UTCTIME:*/
+        // case SQL_TYPE_UTCDATETIME:
+        // case SQL_TYPE_UTCTIME:
         case SQL_INTERVAL_MONTH:
         case SQL_INTERVAL_YEAR:
         case SQL_INTERVAL_YEAR_TO_MONTH:
@@ -1828,7 +1859,7 @@ SQLSMALLINT CPLODBCStatement::GetTypeMapping( SQLSMALLINT nTypeCode )
         case SQL_BINARY:
         case SQL_VARBINARY:
         case SQL_LONGVARBINARY:
-        case -151: /*SQL_SS_UDT*/
+        case -151:  // SQL_SS_UDT
             return SQL_C_BINARY;
 
         default:
diff --git a/port/cpl_odbc.h b/port/cpl_odbc.h
index a97f0f1..dd0043d 100644
--- a/port/cpl_odbc.h
+++ b/port/cpl_odbc.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_odbc.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cpl_odbc.h 36675 2016-12-04 11:10:10Z rouault $
  *
  * Project:  OGR ODBC Driver
  * Purpose:  Declarations for ODBC Access Cover API.
@@ -41,12 +41,13 @@
 #include <odbcinst.h>
 #include "cpl_string.h"
 
+/*! @cond Doxygen_Suppress */
 #ifdef PATH_MAX
 #  define ODBC_FILENAME_MAX PATH_MAX
 #else
 #  define ODBC_FILENAME_MAX (255 + 1) /* Max path length */
 #endif
-
+/*! @endcond */
 
 /**
  * \file cpl_odbc.h
@@ -69,7 +70,6 @@ class CPL_DLL CPLODBCDriverInstaller
     // Default constructor.
     CPLODBCDriverInstaller();
 
-
     /**
      * Installs ODBC driver or updates definition of already installed driver.
      * Interanally, it calls ODBC's SQLInstallDriverEx function.
@@ -108,26 +108,26 @@ class CPL_DLL CPLODBCDriverInstaller
      */
     int RemoveDriver( const char* pszDriverName, int fRemoveDSN = FALSE );
 
-
-    // The usage count of the driver after this function has been called
+    /** The usage count of the driver after this function has been called */
     int GetUsageCount() const {  return m_nUsageCount; }
 
-
-    // Path of the target directory where the driver should be installed.
-    // For details, see ODBC API Reference and lpszPathOut
-    // parameter of SQLInstallDriverEx
+    /** Path of the target directory where the driver should be installed.
+     * For details, see ODBC API Reference and lpszPathOut
+     * parameter of SQLInstallDriverEx
+     */
     const char* GetPathOut() const { return m_szPathOut; }
 
-
-    // If InstallDriver returns FALSE, then GetLastError then
-    // error message can be obtained by calling this function.
-    // Internally, it calls ODBC's SQLInstallerError function.
+    /** If InstallDriver returns FALSE, then GetLastError then
+     * error message can be obtained by calling this function.
+     * Internally, it calls ODBC's SQLInstallerError function.
+     */
     const char* GetLastError() const { return m_szError; }
 
-    // If InstallDriver returns FALSE, then GetLastErrorCode then
-    // error code can be obtained by calling this function.
-    // Internally, it calls ODBC's SQLInstallerError function.
-    // See ODBC API Reference for possible error flags.
+    /** If InstallDriver returns FALSE, then GetLastErrorCode then
+     * error code can be obtained by calling this function.
+     * Internally, it calls ODBC's SQLInstallerError function.
+     * See ODBC API Reference for possible error flags.
+     */
     DWORD GetLastErrorCode() const { return m_nErrorCode; }
 };
 
@@ -141,6 +141,7 @@ class CPLODBCStatement;
 #  define MISSING_SQLULEN
 #endif
 
+/*! @cond Doxygen_Suppress */
 #if !defined(MISSING_SQLULEN)
 /* ODBC types to support 64 bit compilation */
 #  define CPL_SQLULEN SQLULEN
@@ -148,8 +149,8 @@ class CPLODBCStatement;
 #else
 #  define CPL_SQLULEN SQLUINTEGER
 #  define CPL_SQLLEN  SQLINTEGER
-#endif	/* ifdef SQLULEN */
-
+#endif  /* ifdef SQLULEN */
+/*! @endcond */
 
 /**
  * A class representing an ODBC database session.
@@ -179,6 +180,7 @@ class CPL_DLL CPLODBCSession {
     int         BeginTransaction();
     int         CommitTransaction();
     int         RollbackTransaction();
+    /** Returns whether a transaction is active */
     int         IsInTransaction() { return m_bInTransaction; }
 
     // Essentially internal.
@@ -186,7 +188,9 @@ class CPL_DLL CPLODBCSession {
     int         CloseSession();
 
     int         Failed( int, HSTMT = NULL );
+    /** Return connection handle */
     HDBC        GetConnection() { return m_hDBC; }
+    /** Return GetEnvironment handle */
     HENV        GetEnvironment()  { return m_hEnv; }
 };
 
@@ -223,9 +227,10 @@ class CPL_DLL CPLODBCStatement {
     size_t         m_nStatementLen;
 
   public:
-    CPLODBCStatement( CPLODBCSession * );
+    explicit CPLODBCStatement( CPLODBCSession * );
     ~CPLODBCStatement();
 
+    /** Return statement handle */
     HSTMT          GetStatement() { return m_hStmt; }
 
     // Command buffer related.
@@ -234,7 +239,8 @@ class CPL_DLL CPLODBCStatement {
     void           Append( const char * );
     void           Append( int );
     void           Append( double );
-    int            Appendf( const char *, ... ) CPL_PRINT_FUNC_FORMAT (2, 3);
+    int            Appendf( CPL_FORMAT_STRING(const char *), ... ) CPL_PRINT_FUNC_FORMAT (2, 3);
+    /** Return statement string */
     const char    *GetCommand() { return m_pszStatement; }
 
     int            ExecuteSQL( const char * = NULL );
diff --git a/port/cpl_path.cpp b/port/cpl_path.cpp
index f9e5485..9330357 100644
--- a/port/cpl_path.cpp
+++ b/port/cpl_path.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_path.cpp 33817 2016-03-30 17:35:37Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Portable filename/path parsing, and forming ala "Glob API".
@@ -28,14 +27,31 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_atomic_ops.h"
+#include "cpl_port.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
+
+#include <cctype>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <algorithm>
+#include <string>
+
+#include "cpl_atomic_ops.h"
+#include "cpl_config.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_path.cpp 33817 2016-03-30 17:35:37Z rouault $");
+CPL_CVSID("$Id: cpl_path.cpp 37866 2017-03-30 20:16:05Z rouault $");
 
-/* should be size of larged possible filename */
+// Should be size of larged possible filename.
 static const int CPL_PATH_BUF_SIZE = 2048;
 static const int CPL_PATH_BUF_COUNT = 10;
 
@@ -45,7 +61,7 @@ static const char SEP_STRING[] = "\\";
 static const char SEP_STRING[] = "/";
 #endif
 
-static const char* CPLStaticBufferTooSmall(char *pszStaticResult)
+static const char* CPLStaticBufferTooSmall( char *pszStaticResult )
 {
     CPLError(CE_Failure, CPLE_AppDefined, "Destination buffer too small");
     if( pszStaticResult == NULL )
@@ -62,8 +78,8 @@ static char *CPLGetStaticResult()
 
 {
     int bMemoryError = FALSE;
-    char *pachBufRingInfo
-        = static_cast<char *>( CPLGetTLSEx( CTLS_PATHBUF, &bMemoryError ) );
+    char *pachBufRingInfo =
+        static_cast<char *>( CPLGetTLSEx( CTLS_PATHBUF, &bMemoryError ) );
     if( bMemoryError )
         return NULL;
     if( pachBufRingInfo == NULL )
@@ -81,8 +97,8 @@ static char *CPLGetStaticResult()
 /*      time.                                                           */
 /* -------------------------------------------------------------------- */
     int *pnBufIndex = reinterpret_cast<int *>( pachBufRingInfo );
-    size_t nOffset
-        = sizeof(int) + static_cast<size_t>( *pnBufIndex * CPL_PATH_BUF_SIZE );
+    const size_t nOffset =
+        sizeof(int) + static_cast<size_t>( *pnBufIndex * CPL_PATH_BUF_SIZE );
     char *pachBuffer = pachBufRingInfo + nOffset;
 
     *pnBufIndex = (*pnBufIndex + 1) % CPL_PATH_BUF_COUNT;
@@ -90,7 +106,6 @@ static char *CPLGetStaticResult()
     return pachBuffer;
 }
 
-
 /************************************************************************/
 /*                        CPLFindFilenameStart()                        */
 /************************************************************************/
@@ -139,13 +154,13 @@ const char *CPLGetPath( const char *pszFilename )
 
 {
     const int iFileStart = CPLFindFilenameStart(pszFilename);
-    char       *pszStaticResult = CPLGetStaticResult();
+    char *pszStaticResult = CPLGetStaticResult();
 
     if( pszStaticResult == NULL || iFileStart >= CPL_PATH_BUF_SIZE )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! (pszFilename >= pszStaticResult
-                  && pszFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( !(pszFilename >= pszStaticResult
+                 && pszFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
 
     if( iFileStart == 0 )
     {
@@ -194,13 +209,13 @@ const char *CPLGetDirname( const char *pszFilename )
 
 {
     const int iFileStart = CPLFindFilenameStart(pszFilename);
-    char       *pszStaticResult = CPLGetStaticResult();
+    char *pszStaticResult = CPLGetStaticResult();
 
     if( pszStaticResult == NULL || iFileStart >= CPL_PATH_BUF_SIZE )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! (pszFilename >= pszStaticResult
-                  && pszFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( !(pszFilename >= pszStaticResult
+                 && pszFilename < pszStaticResult + CPL_PATH_BUF_SIZE) );
 
     if( iFileStart == 0 )
     {
@@ -277,14 +292,14 @@ const char *CPLGetFilename( const char *pszFullFilename )
 const char *CPLGetBasename( const char *pszFullFilename )
 
 {
-    const size_t iFileStart
-        = static_cast<size_t>( CPLFindFilenameStart( pszFullFilename ) );
-    char    *pszStaticResult = CPLGetStaticResult();
+    const size_t iFileStart =
+        static_cast<size_t>( CPLFindFilenameStart( pszFullFilename ) );
+    char *pszStaticResult = CPLGetStaticResult();
     if( pszStaticResult == NULL )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! ( pszFullFilename >= pszStaticResult
-                   && pszFullFilename < pszStaticResult + CPL_PATH_BUF_SIZE ) );
+    CPLAssert( !( pszFullFilename >= pszStaticResult
+                  && pszFullFilename < pszStaticResult + CPL_PATH_BUF_SIZE ) );
 
     size_t iExtStart = strlen(pszFullFilename);
     for( ;
@@ -304,7 +319,6 @@ const char *CPLGetBasename( const char *pszFullFilename )
     return pszStaticResult;
 }
 
-
 /************************************************************************/
 /*                           CPLGetExtension()                          */
 /************************************************************************/
@@ -331,16 +345,16 @@ const char *CPLGetBasename( const char *pszFullFilename )
 const char *CPLGetExtension( const char *pszFullFilename )
 
 {
-    size_t iFileStart
-        = static_cast<size_t>( CPLFindFilenameStart( pszFullFilename ) );
-    char    *pszStaticResult = CPLGetStaticResult();
+    size_t iFileStart =
+        static_cast<size_t>( CPLFindFilenameStart( pszFullFilename ) );
+    char *pszStaticResult = CPLGetStaticResult();
     if( pszStaticResult == NULL )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! ( pszFullFilename >= pszStaticResult
-                   && pszFullFilename < pszStaticResult + CPL_PATH_BUF_SIZE ) );
+    CPLAssert( !( pszFullFilename >= pszStaticResult
+                  && pszFullFilename < pszStaticResult + CPL_PATH_BUF_SIZE ) );
 
-    size_t  iExtStart = strlen(pszFullFilename);
+    size_t iExtStart = strlen(pszFullFilename);
     for( ;
          iExtStart > iFileStart && pszFullFilename[iExtStart] != '.';
          iExtStart-- ) {}
@@ -348,7 +362,7 @@ const char *CPLGetExtension( const char *pszFullFilename )
     if( iExtStart == iFileStart )
         iExtStart = strlen(pszFullFilename)-1;
 
-    if (CPLStrlcpy( pszStaticResult, pszFullFilename+iExtStart+1,
+    if( CPLStrlcpy( pszStaticResult, pszFullFilename+iExtStart+1,
                     CPL_PATH_BUF_SIZE )
         >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
         return CPLStaticBufferTooSmall(pszStaticResult);
@@ -369,8 +383,8 @@ const char *CPLGetExtension( const char *pszFullFilename )
  * If HAVE_GETCWD macro is not defined, the function returns NULL.
  **/
 
+#ifdef HAVE_GETCWD
 char *CPLGetCurrentDir()
-
 {
 #ifdef _MAX_PATH
     const size_t nPathMax = _MAX_PATH;
@@ -381,15 +395,14 @@ char *CPLGetCurrentDir()
 #endif
 
     char *pszDirPath = static_cast<char *>( VSI_MALLOC_VERBOSE( nPathMax ) );
-    if ( !pszDirPath )
+    if( !pszDirPath )
         return NULL;
 
-#ifdef HAVE_GETCWD
     return getcwd( pszDirPath, nPathMax );
-#else
-    return NULL;
-#endif /* HAVE_GETCWD */
 }
+#else  // !HAVE_GETCWD
+char *CPLGetCurrentDir() { return NULL; }
+#endif // HAVE_GETCWD
 
 /************************************************************************/
 /*                         CPLResetExtension()                          */
@@ -409,7 +422,7 @@ char *CPLGetCurrentDir()
 const char *CPLResetExtension( const char *pszPath, const char *pszExt )
 
 {
-    char    *pszStaticResult = CPLGetStaticResult();
+    char *pszStaticResult = CPLGetStaticResult();
     if( pszStaticResult == NULL )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
@@ -419,11 +432,11 @@ const char *CPLResetExtension( const char *pszPath, const char *pszExt )
 /* -------------------------------------------------------------------- */
 /*      First, try and strip off any existing extension.                */
 /* -------------------------------------------------------------------- */
-    if ( CPLStrlcpy( pszStaticResult, pszPath, CPL_PATH_BUF_SIZE )
-         >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
+    if( CPLStrlcpy( pszStaticResult, pszPath, CPL_PATH_BUF_SIZE )
+        >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
-    if (*pszStaticResult)
+    if( *pszStaticResult )
     {
         for( size_t i = strlen(pszStaticResult) - 1; i > 0; i-- )
         {
@@ -464,10 +477,10 @@ const char *CPLResetExtension( const char *pszPath, const char *pszExt )
  * an extension if desired.
  *
  * <pre>
- * CPLFormFilename("abc/xyz","def", ".dat" ) == "abc/xyz/def.dat"
+ * CPLFormFilename("abc/xyz", "def", ".dat" ) == "abc/xyz/def.dat"
  * CPLFormFilename(NULL,"def", NULL ) == "def"
- * CPLFormFilename(NULL,"abc/def.dat", NULL ) == "abc/def.dat"
- * CPLFormFilename("/abc/xyz/","def.dat", NULL ) == "/abc/xyz/def.dat"
+ * CPLFormFilename(NULL, "abc/def.dat", NULL ) == "abc/def.dat"
+ * CPLFormFilename("/abc/xyz/", "def.dat", NULL ) == "/abc/xyz/def.dat"
  * </pre>
  *
  * @param pszPath directory path to the directory containing the file.  This
@@ -502,8 +515,8 @@ const char *CPLFormFilename( const char * pszPath,
     if( pszBasename[0] == '.' && pszBasename[1] == '/' )
         pszBasename += 2;
 
-    const char  *pszAddedPathSep = "";
-    const char  *pszAddedExtSep = "";
+    const char *pszAddedPathSep = "";
+    const char *pszAddedExtSep = "";
 
     if( pszPath == NULL )
         pszPath = "";
@@ -511,14 +524,14 @@ const char *CPLFormFilename( const char * pszPath,
     if( !CPLIsFilenameRelative(pszPath) &&
         strcmp(pszBasename, "..") == 0 )
     {
-        /* /a/b + .. --> /a */
+        // /a/b + .. --> /a
         if( pszPath[nLenPath-1] == '\\' || pszPath[nLenPath-1] == '/' )
-            nLenPath --;
+            nLenPath--;
         size_t nLenPathOri = nLenPath;
         while( nLenPath > 0 && pszPath[nLenPath-1] != '\\' &&
                pszPath[nLenPath-1] != '/')
         {
-            nLenPath --;
+            nLenPath--;
         }
         if( nLenPath == 1 && pszPath[0] == '/' )
         {
@@ -528,7 +541,7 @@ const char *CPLFormFilename( const char * pszPath,
                  (nLenPath > 2 && pszPath[1] == ':') ||
                  (nLenPath > 6 && strncmp(pszPath, "\\\\$\\", 4) == 0) )
         {
-            nLenPath --;
+            nLenPath--;
             pszBasename = "";
         }
         else
@@ -541,12 +554,13 @@ const char *CPLFormFilename( const char * pszPath,
              && pszPath[nLenPath-1] != '/'
              && pszPath[nLenPath-1] != '\\' )
     {
-        /* FIXME? would be better to ask the filesystems what they */
-        /* prefer as directory separator */
-        if (STARTS_WITH(pszPath, "/vsicurl/") ||
-            STARTS_WITH(pszPath, "/vsicurl_streaming/"))
-            pszAddedPathSep = "/";
-        else if (STARTS_WITH(pszPath, "/vsizip/"))
+        // FIXME? Would be better to ask the filesystems what it
+        // prefers as directory separator?
+        if( strcmp(pszPath, "/vsimem") == 0 ||
+            STARTS_WITH(pszPath, "/vsimem/") ||
+            STARTS_WITH(pszPath, "/vsicurl/") ||
+            STARTS_WITH(pszPath, "/vsicurl_streaming/") ||
+            STARTS_WITH(pszPath, "/vsizip/") )
             pszAddedPathSep = "/";
         else
             pszAddedPathSep = SEP_STRING;
@@ -557,7 +571,9 @@ const char *CPLFormFilename( const char * pszPath,
     else if( pszExtension[0] != '.' && strlen(pszExtension) > 0 )
         pszAddedExtSep = ".";
 
-    if( CPLStrlcpy( pszStaticResult, pszPath, MIN(nLenPath+1, static_cast<size_t>(CPL_PATH_BUF_SIZE)) )
+    if( CPLStrlcpy( pszStaticResult, pszPath,
+                    std::min(nLenPath + 1,
+                             static_cast<size_t>(CPL_PATH_BUF_SIZE)) )
         >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) ||
         CPLStrlcat( pszStaticResult, pszAddedPathSep, CPL_PATH_BUF_SIZE)
         >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) ||
@@ -607,13 +623,12 @@ const char *CPLFormCIFilename( const char * pszPath,
                                const char * pszExtension )
 
 {
-    // On case insensitive filesystems, just default to
-    // CPLFormFilename()
+    // On case insensitive filesystems, just default to CPLFormFilename().
     if( !VSIIsCaseSensitiveFS(pszPath) )
         return CPLFormFilename( pszPath, pszBasename, pszExtension );
 
-    const char  *pszAddedExtSep = "";
-    size_t       nLen = strlen(pszBasename)+2;
+    const char *pszAddedExtSep = "";
+    size_t nLen = strlen(pszBasename) + 2;
 
     if( pszExtension != NULL )
         nLen += strlen(pszExtension);
@@ -679,11 +694,11 @@ const char *CPLFormCIFilename( const char * pszPath,
  *
  * Examples:
  * <pre>
- * CPLProjectRelativeFilename("abc/def","tmp/abc.gif") == "abc/def/tmp/abc.gif"
- * CPLProjectRelativeFilename("abc/def","/tmp/abc.gif") == "/tmp/abc.gif"
+ * CPLProjectRelativeFilename("abc/def", "tmp/abc.gif") == "abc/def/tmp/abc.gif"
+ * CPLProjectRelativeFilename("abc/def", "/tmp/abc.gif") == "/tmp/abc.gif"
  * CPLProjectRelativeFilename("/xy", "abc.gif") == "/xy/abc.gif"
- * CPLProjectRelativeFilename("/abc/def","../abc.gif") == "/abc/def/../abc.gif"
- * CPLProjectRelativeFilename("C:\WIN","abc.gif") == "C:\WIN\abc.gif"
+ * CPLProjectRelativeFilename("/abc/def", "../abc.gif") == "/abc/def/../abc.gif"
+ * CPLProjectRelativeFilename("C:\WIN", "abc.gif") == "C:\WIN\abc.gif"
  * </pre>
  *
  * @param pszProjectDir the directory relative to which the secondary files
@@ -704,11 +719,11 @@ const char *CPLProjectRelativeFilename( const char *pszProjectDir,
     if( pszStaticResult == NULL )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
-    CPLAssert( ! ( pszProjectDir >= pszStaticResult
-                   && pszProjectDir < pszStaticResult + CPL_PATH_BUF_SIZE ) );
-    CPLAssert( ! ( pszSecondaryFilename >= pszStaticResult
-                   && pszSecondaryFilename
-                   < pszStaticResult + CPL_PATH_BUF_SIZE) );
+    CPLAssert( !(pszProjectDir >= pszStaticResult
+                 && pszProjectDir < pszStaticResult + CPL_PATH_BUF_SIZE ) );
+    CPLAssert( !(pszSecondaryFilename >= pszStaticResult
+                 && pszSecondaryFilename
+                 < pszStaticResult + CPL_PATH_BUF_SIZE) );
 
     if( !CPLIsFilenameRelative( pszSecondaryFilename ) )
         return pszSecondaryFilename;
@@ -723,10 +738,12 @@ const char *CPLProjectRelativeFilename( const char *pszProjectDir,
     if( pszProjectDir[strlen(pszProjectDir)-1] != '/'
         && pszProjectDir[strlen(pszProjectDir)-1] != '\\' )
     {
-        /* FIXME? would be better to ask the filesystems what they */
-        /* prefer as directory separator */
-        const char* pszAddedPathSep;
-        if (STARTS_WITH(pszStaticResult, "/vsicurl/"))
+        // FIXME: Better to ask the filesystems what it
+        // prefers as directory separator?
+        const char* pszAddedPathSep = NULL;
+        if( strcmp(pszStaticResult, "/vsimem") == 0 ||
+            STARTS_WITH(pszStaticResult, "/vsicurl/") ||
+            STARTS_WITH(pszStaticResult, "/vsimem/") )
             pszAddedPathSep = "/";
         else
             pszAddedPathSep = SEP_STRING;
@@ -742,7 +759,6 @@ const char *CPLProjectRelativeFilename( const char *pszProjectDir,
     return pszStaticResult;
 }
 
-
 /************************************************************************/
 /*                       CPLIsFilenameRelative()                        */
 /************************************************************************/
@@ -765,7 +781,7 @@ int CPLIsFilenameRelative( const char *pszFilename )
     if( (pszFilename[0] != '\0'
          && (STARTS_WITH(pszFilename+1, ":\\")
              || STARTS_WITH(pszFilename+1, ":/")))
-        || STARTS_WITH(pszFilename, "\\\\?\\") /* Windows extended Length Path */
+        || STARTS_WITH(pszFilename, "\\\\?\\")  // Windows extended Length Path.
         || pszFilename[0] == '\\'
         || pszFilename[0] == '/' )
         return FALSE;
@@ -822,7 +838,7 @@ const char *CPLExtractRelativePath( const char *pszBaseDir,
 /*      One simple case is when the base dir is '.' and the target      */
 /*      filename is relative.                                           */
 /* -------------------------------------------------------------------- */
-    if( (nBasePathLen == 0 || EQUAL(pszBaseDir,"."))
+    if( (nBasePathLen == 0 || EQUAL(pszBaseDir, "."))
         && CPLIsFilenameRelative(pszTarget) )
     {
         if( pbGotRelative != NULL )
@@ -847,7 +863,7 @@ const char *CPLExtractRelativePath( const char *pszBaseDir,
 /*      If we don't have a common path prefix, then we can't get a      */
 /*      relative path.                                                  */
 /* -------------------------------------------------------------------- */
-    if( !EQUALN(pszBaseDir,pszTarget,nBasePathLen)
+    if( !EQUALN(pszBaseDir, pszTarget, nBasePathLen)
         || (pszTarget[nBasePathLen] != '\\'
             && pszTarget[nBasePathLen] != '/') )
     {
@@ -895,14 +911,14 @@ const char *CPLExtractRelativePath( const char *pszBaseDir,
 const char *CPLCleanTrailingSlash( const char *pszPath )
 
 {
-    char       *pszStaticResult = CPLGetStaticResult();
+    char *pszStaticResult = CPLGetStaticResult();
     if( pszStaticResult == NULL )
         return CPLStaticBufferTooSmall(pszStaticResult);
     CPLAssert( ! ( pszPath >= pszStaticResult
                    && pszPath < pszStaticResult + CPL_PATH_BUF_SIZE) );
 
     const size_t iPathLength = strlen(pszPath);
-    if (iPathLength >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
+    if( iPathLength >= static_cast<size_t>( CPL_PATH_BUF_SIZE ) )
         return CPLStaticBufferTooSmall(pszStaticResult);
 
     CPLStrlcpy( pszStaticResult, pszPath, iPathLength+1 );
@@ -956,7 +972,7 @@ char **CPLCorrespondingPaths( const char *pszOldFilename,
 /*      matches the old name, to rename to the new name.                */
 /* -------------------------------------------------------------------- */
     if( CSLCount(papszFileList) == 1
-        && strcmp(pszOldFilename,papszFileList[0]) == 0 )
+        && strcmp(pszOldFilename, papszFileList[0]) == 0 )
     {
         return CSLAddString( NULL, pszNewFilename );
     }
@@ -971,7 +987,7 @@ char **CPLCorrespondingPaths( const char *pszOldFilename,
 /* -------------------------------------------------------------------- */
     if( osOldBasename != osNewBasename )
     {
-        for( int i=0; papszFileList[i] != NULL; i++ )
+        for( int i = 0; papszFileList[i] != NULL; i++ )
         {
             if( osOldBasename == CPLGetBasename( papszFileList[i] ) )
                 continue;
@@ -979,8 +995,8 @@ char **CPLCorrespondingPaths( const char *pszOldFilename,
             const CPLString osFilePath = CPLGetPath( papszFileList[i] );
             const CPLString osFileName = CPLGetFilename( papszFileList[i] );
 
-            if( !EQUALN(osFileName,osOldBasename,osOldBasename.size())
-                || !EQUAL(osFilePath,osOldPath)
+            if( !EQUALN(osFileName, osOldBasename, osOldBasename.size())
+                || !EQUAL(osFilePath, osOldPath)
                 || osFileName[osOldBasename.size()] != '.' )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
@@ -996,10 +1012,10 @@ char **CPLCorrespondingPaths( const char *pszOldFilename,
 /* -------------------------------------------------------------------- */
     if( osOldBasename != osNewBasename )
     {
-        const CPLString osOldExtra = CPLGetFilename(pszOldFilename)
-            + strlen(osOldBasename);
-        const CPLString osNewExtra = CPLGetFilename(pszNewFilename)
-            + strlen(osNewBasename);
+        const CPLString osOldExtra =
+            CPLGetFilename(pszOldFilename) + osOldBasename.size();
+        const CPLString osNewExtra =
+            CPLGetFilename(pszNewFilename) + osNewBasename.size();
 
         if( osOldExtra != osNewExtra )
         {
@@ -1016,18 +1032,15 @@ char **CPLCorrespondingPaths( const char *pszOldFilename,
     char **papszNewList = NULL;
     const CPLString osNewPath = CPLGetPath( pszNewFilename );
 
-    for( int i=0; papszFileList[i] != NULL; i++ )
+    for( int i = 0; papszFileList[i] != NULL; i++ )
     {
-        CPLString osNewFilename;
         const CPLString osOldFilename = CPLGetFilename( papszFileList[i] );
 
-        if( osOldBasename == osNewBasename )
-            osNewFilename =
-                CPLFormFilename( osNewPath, osOldFilename, NULL );
-        else
-            osNewFilename =
-                CPLFormFilename( osNewPath, osNewBasename,
-                                 osOldFilename.c_str()+strlen(osOldBasename));
+        const CPLString osNewFilename =
+            osOldBasename == osNewBasename
+            ? CPLFormFilename( osNewPath, osOldFilename, NULL )
+            : CPLFormFilename( osNewPath, osNewBasename,
+                               osOldFilename.c_str() + osOldBasename.size());
 
         papszNewList = CSLAddString( papszNewList, osNewFilename );
     }
@@ -1077,3 +1090,32 @@ const char *CPLGenerateTempFilename( const char *pszStem )
 
     return CPLFormFilename( pszDir, osFilename, NULL );
 }
+
+/************************************************************************/
+/*                         CPLExpandTilde()                             */
+/************************************************************************/
+
+/**
+ * Expands ~/ at start of filename.
+ * 
+ * Assumes that the HOME configuration option is defined.
+ *
+ * @param pszFilename filename potentially starting with ~/
+ *
+ * @return an expanded filename.
+ *
+ * @since GDAL 2.2
+ */
+
+const char *CPLExpandTilde( const char *pszFilename )
+
+{
+    if( !STARTS_WITH_CI(pszFilename, "~/") )
+        return pszFilename;
+
+    const char* pszHome = CPLGetConfigOption("HOME", NULL);
+    if( pszHome == NULL )
+        return pszFilename;
+
+    return CPLFormFilename( pszHome, pszFilename + 2, NULL );
+}
diff --git a/port/cpl_port.h b/port/cpl_port.h
index 36b15df..f4f910f 100644
--- a/port/cpl_port.h
+++ b/port/cpl_port.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_port.h 34135 2016-04-27 21:44:07Z rouault $
+ * $Id: cpl_port.h 37456 2017-02-25 18:35:03Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -82,7 +82,6 @@
 #error "Unexpected value for SIZEOF_VOIDP"
 #endif
 
-
 /* ==================================================================== */
 /*      This will disable most WIN32 stuff in a Cygnus build which      */
 /*      defines unix to 1.                                              */
@@ -92,6 +91,7 @@
 #  undef WIN32
 #endif
 
+/*! @cond Doxygen_Suppress */
 #if defined(VSI_NEED_LARGEFILE64_SOURCE) && !defined(_LARGEFILE64_SOURCE)
 #  define _LARGEFILE64_SOURCE 1
 #endif
@@ -107,18 +107,27 @@
 #endif
 
 #define CPL_RECODE_STUB
+/*! @endcond */
 
 /* ==================================================================== */
 /*      MinGW stuff                                                     */
 /* ==================================================================== */
 
-/* We need __MSVCRT_VERSION__ >= 0x0601 to have "struct __stat64" */
+/* We need __MSVCRT_VERSION__ >= 0x0700 to have "_aligned_malloc" */
 /* Latest versions of mingw32 define it, but with older ones, */
 /* we need to define it manually */
 #if defined(__MINGW32__)
 #ifndef __MSVCRT_VERSION__
-#define __MSVCRT_VERSION__ 0x0601
+#define __MSVCRT_VERSION__ 0x0700
+#endif
+#endif
+
+/* Needed for std=c11 on Solaris to have strcasecmp() */
+#if defined(GDAL_COMPILATION) && defined(__sun__) && __STDC_VERSION__ >= 201112L && _XOPEN_SOURCE < 600
+#ifdef _XOPEN_SOURCE
+#undef _XOPEN_SOURCE
 #endif
+#define _XOPEN_SOURCE 600
 #endif
 
 /* ==================================================================== */
@@ -175,7 +184,7 @@
 #    define HAVE_CXX11 1
 #  endif
 /* TODO(schwehr): What are the correct tests for C++ 14 and 17? */
-#endif  /* __cpluscplus */
+#endif  /* __cplusplus */
 
 /*---------------------------------------------------------------------
  *        types for 16 and 32 bits integers, etc...
@@ -184,17 +193,25 @@
 typedef long            GInt32;
 typedef unsigned long   GUInt32;
 #else
+/** Int32 type */
 typedef int             GInt32;
+/** Unsigned int32 type */
 typedef unsigned int    GUInt32;
 #endif
 
+/** Int16 type */
 typedef short           GInt16;
+/** Unsigned int16 type */
 typedef unsigned short  GUInt16;
+/** Unsigned byte type */
 typedef unsigned char   GByte;
 /* hack for PDF driver and poppler >= 0.15.0 that defines incompatible "typedef bool GBool" */
 /* in include/poppler/goo/gtypes.h */
 #ifndef CPL_GBOOL_DEFINED
+/*! @cond Doxygen_Suppress */
 #define CPL_GBOOL_DEFINED
+/*! @endcond */
+/** Type for boolean values (alias to int) */
 typedef int             GBool;
 #endif
 
@@ -208,21 +225,62 @@ typedef int             GBool;
 typedef __int64          GIntBig;
 typedef unsigned __int64 GUIntBig;
 
+/** Minimum GIntBig value */
 #define GINTBIG_MIN     ((GIntBig)(0x80000000) << 32)
+/** Maximum GIntBig value */
 #define GINTBIG_MAX     (((GIntBig)(0x7FFFFFFF) << 32) | 0xFFFFFFFFU)
+/** Maximum GUIntBig value */
 #define GUINTBIG_MAX     (((GUIntBig)(0xFFFFFFFFU) << 32) | 0xFFFFFFFFU)
 
+#define CPL_HAS_GINT64 1
+
+/** Signed 64 bit integer type */
+typedef GIntBig          GInt64;
+/** Unsigned 64 bit integer type */
+typedef GUIntBig         GUInt64;
+
+#define GINT64_MIN      GINTBIG_MIN
+#define GINT64_MAX      GINTBIG_MAX
+#define GUINT64_MAX     GUINTBIG_MAX
+
 #elif HAVE_LONG_LONG
 
+/** Large signed integer type (generally 64-bit integer type).
+ *  Use GInt64 when exactly 64 bit is needed */
 typedef long long        GIntBig;
+/** Large unsigned integer type (generally 64-bit unsigned integer type).
+ *  Use GUInt64 when exactly 64 bit is needed */
 typedef unsigned long long GUIntBig;
 
+/** Minimum GIntBig value */
 #define GINTBIG_MIN     ((GIntBig)(0x80000000) << 32)
+/** Maximum GIntBig value */
 #define GINTBIG_MAX     (((GIntBig)(0x7FFFFFFF) << 32) | 0xFFFFFFFFU)
+/** Maximum GUIntBig value */
 #define GUINTBIG_MAX     (((GUIntBig)(0xFFFFFFFFU) << 32) | 0xFFFFFFFFU)
 
+/*! @cond Doxygen_Suppress */
+#define CPL_HAS_GINT64 1
+/*! @endcond */
+
+/* Note: we might want to use instead int64_t / uint64_t if they are available */
+
+/** Signed 64 bit integer type */
+typedef GIntBig          GInt64;
+/** Unsigned 64 bit integer type */
+typedef GUIntBig         GUInt64;
+
+/** Minimum GInt64 value */
+#define GINT64_MIN      GINTBIG_MIN
+/** Maximum GInt64 value */
+#define GINT64_MAX      GINTBIG_MAX
+/** Minimum GUInt64 value */
+#define GUINT64_MAX     GUINTBIG_MAX
+
 #else
 
+// NOTE: we don't really support such platforms ! Many things might break
+
 typedef long             GIntBig;
 typedef unsigned long    GUIntBig;
 
@@ -232,40 +290,67 @@ typedef unsigned long    GUIntBig;
 #endif
 
 #if SIZEOF_VOIDP == 8
+/** Integer type large enough to hold the difference between 2 addresses */
 typedef GIntBig          GPtrDiff_t;
 #else
+/** Integer type large enough to hold the difference between 2 addresses */
 typedef int              GPtrDiff_t;
 #endif
 
+#ifdef GDAL_COMPILATION
+#if HAVE_UINTPTR_T
+#if !defined(_MSC_VER) || _MSC_VER > 1500
+#include <stdint.h>
+#endif
+typedef uintptr_t GUIntptr_t;
+#elif SIZEOF_VOIDP == 8
+typedef GUIntBig GUIntptr_t;
+#else
+typedef unsigned int  GUIntptr_t;
+#endif
+
+#define CPL_IS_ALIGNED(ptr, quant) (((GUIntptr_t)(ptr) % (quant)) == 0)
+
+#endif
+
 #if defined(__MSVCRT__) || (defined(WIN32) && defined(_MSC_VER))
   #define CPL_FRMT_GB_WITHOUT_PREFIX     "I64"
 #elif HAVE_LONG_LONG
+/** Printf formatting suffix for GIntBig */
   #define CPL_FRMT_GB_WITHOUT_PREFIX     "ll"
 #else
   #define CPL_FRMT_GB_WITHOUT_PREFIX     "l"
 #endif
 
+/** Printf formatting for GIntBig */
 #define CPL_FRMT_GIB     "%" CPL_FRMT_GB_WITHOUT_PREFIX "d"
+/** Printf formatting for GUIntBig */
 #define CPL_FRMT_GUIB    "%" CPL_FRMT_GB_WITHOUT_PREFIX "u"
 
+/*! @cond Doxygen_Suppress */
 /* Workaround VC6 bug */
 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
 #define GUINTBIG_TO_DOUBLE(x) (double)(GIntBig)(x)
 #else
 #define GUINTBIG_TO_DOUBLE(x) (double)(x)
 #endif
+/*! @endcond */
 
+/*! @cond Doxygen_Suppress */
 #ifdef COMPAT_WITH_ICC_CONVERSION_CHECK
 #define CPL_INT64_FITS_ON_INT32(x) ((x) >= INT_MIN && (x) <= INT_MAX)
 #else
 #define CPL_INT64_FITS_ON_INT32(x) (((GIntBig)(int)(x)) == (x))
 #endif
+/*! @endcond */
 
 /* ==================================================================== */
 /*      Other standard services.                                        */
 /* ==================================================================== */
 #ifdef __cplusplus
+/** Macro to start a block of C symbols */
 #  define CPL_C_START           extern "C" {
+/** Macro to end a block of C symbols */
 #  define CPL_C_END             }
 #else
 #  define CPL_C_START
@@ -284,12 +369,14 @@ typedef int              GPtrDiff_t;
 #endif
 #endif
 
+/*! @cond Doxygen_Suppress */
 /* Should optional (normally private) interfaces be exported? */
 #ifdef CPL_OPTIONAL_APIS
 #  define CPL_ODLL CPL_DLL
 #else
 #  define CPL_ODLL
 #endif
+/*! @endcond */
 
 #ifndef CPL_STDCALL
 #if defined(_MSC_VER) && !defined(CPL_DISABLE_STDCALL)
@@ -299,12 +386,15 @@ typedef int              GPtrDiff_t;
 #endif
 #endif
 
+/*! @cond Doxygen_Suppress */
 #ifdef _MSC_VER
 #  define FORCE_CDECL  __cdecl
 #else
 #  define FORCE_CDECL
 #endif
+/*! @endcond */
 
+/*! @cond Doxygen_Suppress */
 /* TODO : support for other compilers needed */
 #if (defined(__GNUC__) && !defined(__NO_INLINE__)) || defined(_MSC_VER)
 #define HAS_CPL_INLINE  1
@@ -315,7 +405,9 @@ typedef int              GPtrDiff_t;
 #else
 #define CPL_INLINE
 #endif
+/*! @endcond*/
 
+/*! @cond Doxygen_Suppress */
 // Define NULL_AS_NULLPTR together with -std=c++11 -Wzero-as-null-pointer-constant with GCC
 // to detect misuses of NULL
 #if defined(NULL_AS_NULLPTR) && HAVE_CXX11
@@ -359,19 +451,23 @@ extern "C++" {
 #  define NULL  0
 #endif
 #endif /* defined(NULL_AS_NULLPTR) && HAVE_CXX11 */
-
+/*! @endcond */
 
 #ifndef MAX
-#  define MIN(a,b)      ((a<b) ? a : b)
-#  define MAX(a,b)      ((a>b) ? a : b)
+/** Macro to compute the minimum of 2 values */
+#  define MIN(a,b)      (((a)<(b)) ? (a) : (b))
+/** Macro to compute the maximum of 2 values */
+#  define MAX(a,b)      (((a)>(b)) ? (a) : (b))
 #endif
 
 #ifndef ABS
-#  define ABS(x)        ((x<0) ? (-1*(x)) : x)
+/** Macro to compute the absolute value */
+#  define ABS(x)        (((x)<0) ? (-1*(x)) : (x))
 #endif
 
 #ifndef M_PI
-# define M_PI		3.14159265358979323846
+/** PI definition */
+# define M_PI 3.14159265358979323846
 /* 3.1415926535897932384626433832795 */
 #endif
 
@@ -380,9 +476,11 @@ extern "C++" {
 /*      We use fabs() function instead of ABS() macro to avoid side     */
 /*      effects.                                                        */
 /* -------------------------------------------------------------------- */
+/*! @cond Doxygen_Suppress */
 #ifndef CPLIsEqual
 #  define CPLIsEqual(x,y) (fabs((x) - (y)) < 0.0000000000001)
 #endif
+/*! @endcond */
 
 /* -------------------------------------------------------------------- */
 /*      Provide macros for case insensitive string comparisons.         */
@@ -513,10 +611,14 @@ static inline char* CPL_afl_friendly_strstr(const char* haystack, const char* ne
 #    define STRCASECMP(a,b)         (stricmp(a,b))
 #    define STRNCASECMP(a,b,n)      (strnicmp(a,b,n))
 #  else
+/** Alias for strcasecmp() */
 #    define STRCASECMP(a,b)         (strcasecmp(a,b))
+/** Alias for strncasecmp() */
 #    define STRNCASECMP(a,b,n)      (strncasecmp(a,b,n))
 #  endif
+/** Alias for strncasecmp() == 0 */
 #  define EQUALN(a,b,n)           (STRNCASECMP(a,b,n)==0)
+/** Alias for strcasecmp() == 0 */
 #  define EQUAL(a,b)              (STRCASECMP(a,b)==0)
 #endif
 
@@ -525,13 +627,17 @@ static inline char* CPL_afl_friendly_strstr(const char* haystack, const char* ne
  * with CI, it is a case-insensitive comparison.
  *--------------------------------------------------------------------- */
 #ifndef STARTS_WITH_CI
+/** Returns whether a starts with b */
 #define STARTS_WITH(a,b)               (strncmp(a,b,strlen(b)) == 0)
+/** Returns whether a starts with b (case insensitive comparison) */
 #define STARTS_WITH_CI(a,b)            EQUALN(a,b,strlen(b))
 #endif
 
+/*! @cond Doxygen_Suppress */
 #ifndef CPL_THREADLOCAL
 #  define CPL_THREADLOCAL
 #endif
+/*! @endcond */
 
 /* -------------------------------------------------------------------- */
 /*      Handle isnan() and isinf().  Note that isinf() and isnan()      */
@@ -547,16 +653,42 @@ static inline char* CPL_afl_friendly_strstr(const char* haystack, const char* ne
 #  define CPLIsNan(x) _isnan(x)
 #  define CPLIsInf(x) (!_isnan(x) && !_finite(x))
 #  define CPLIsFinite(x) _finite(x)
-#elif defined(HAVE_CXX11) && HAVE_CXX11 && defined(__GNUC__)
+#elif defined(__cplusplus) && defined(__MINGW32__) &&  __GNUC__ == 4 && __GNUC_MINOR__ == 2
+/* Hack for compatibility with ancient i586-mingw32msvc toolchain */
+extern "C++" {
+#include <cmath>
+static inline int CPLIsNan(float f) { return std::isnan(f); }
+static inline int CPLIsNan(double f) { return std::isnan(f); }
+static inline int CPLIsInf(float f) { return std::isinf(f); }
+static inline int CPLIsInf(double f) { return std::isinf(f); }
+static inline int CPLIsFinite(float f) { return std::isfinite(f); }
+static inline int CPLIsFinite(double f) { return std::isfinite(f); }
+}
+#elif defined(__GNUC__) && ( __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) )
 /* When including <cmath> in C++11 the isnan() macro is undefined, so that */
 /* std::isnan() can work (#6489). This is a GCC specific workaround for now. */
 #  define CPLIsNan(x)    __builtin_isnan(x)
 #  define CPLIsInf(x)    __builtin_isinf(x)
 #  define CPLIsFinite(x) __builtin_isfinite(x)
 #else
+/** Return whether a floating-pointer number is NaN */
+#if defined(__cplusplus) && defined(__GNUC__) && defined(__linux) && !defined(__ANDROID__)
+/* so to not get warning about conversion from double to float with */
+/* gcc -Wfloat-conversion when using isnan()/isinf() macros */
+extern "C++" {
+static inline int CPLIsNan(float f) { return __isnanf(f); }
+static inline int CPLIsNan(double f) { return __isnan(f); }
+static inline int CPLIsInf(float f) { return __isinff(f); }
+static inline int CPLIsInf(double f) { return __isinf(f); }
+static inline int CPLIsFinite(float f) { return !__isnanf(f) && !__isinff(f); }
+static inline int CPLIsFinite(double f) { return !__isnan(f) && !__isinf(f); }
+}
+#else
 #  define CPLIsNan(x) isnan(x)
-#  ifdef isinf
+#  if defined(isinf) || defined(__FreeBSD__)
+/** Return whether a floating-pointer number is +/- infinty */
 #    define CPLIsInf(x) isinf(x)
+/** Return whether a floating-pointer number is finite */
 #    define CPLIsFinite(x) (!isnan(x) && !isinf(x))
 #  elif defined(__sun__)
 #    include <ieeefp.h>
@@ -567,7 +699,9 @@ static inline char* CPL_afl_friendly_strstr(const char* haystack, const char* ne
 #    define CPLIsFinite(x) (!isnan(x))
 #  endif
 #endif
+#endif
 
+/*! @cond Doxygen_Suppress */
 /*---------------------------------------------------------------------
  *                         CPL_LSB and CPL_MSB
  * Only one of these 2 macros should be defined and specifies the byte
@@ -588,9 +722,11 @@ static inline char* CPL_afl_friendly_strstr(const char* haystack, const char* ne
 #else
 #  define CPL_IS_LSB 0
 #endif
+/*! @endcond */
 
 #ifdef __cplusplus
 
+/*! @cond Doxygen_Suppress */
 extern "C++" {
 
 template <bool b> struct CPLStaticAssert {};
@@ -609,16 +745,44 @@ template<> struct CPLStaticAssert<true>
 #define CPL_STATIC_ASSERT_IF_AVAILABLE(x)
 
 #endif  /* __cplusplus */
+/*! @endcond */
 
 /*---------------------------------------------------------------------
  *        Little endian <==> big endian byte swap macros.
  *--------------------------------------------------------------------*/
 
-#define CPL_SWAP16(x) \
-        ((GUInt16)( \
-            (((GUInt16)(x) & 0x00ffU) << 8) | \
-            (((GUInt16)(x) & 0xff00U) >> 8) ))
+/** Byte-swap a 16bit unsigned integer */
+#define CPL_SWAP16(x) ((GUInt16)( ((GUInt16)(x) << 8) | ((GUInt16)(x) >> 8) ))
+
+#if defined(HAVE_GCC_BSWAP) && (defined(__i386__) || defined(__x86_64__))
+/* Could potentially be extended to other architectures but must be checked */
+/* that the intrinsic is indeed efficient */
+/* GCC (at least 4.6  or above) need that include */
+#include <x86intrin.h>
+/** Byte-swap a 32bit unsigned integer */
+#define CPL_SWAP32(x) ((GUInt32)(__builtin_bswap32((GUInt32)(x))))
+/** Byte-swap a 64bit unsigned integer */
+#define CPL_SWAP64(x) ((GUInt64)(__builtin_bswap64((GUInt64)(x))))
+#elif defined(_MSC_VER)
+#define CPL_SWAP32(x) ((GUInt32)(_byteswap_ulong((GUInt32)(x))))
+#define CPL_SWAP64(x) ((GUInt64)(_byteswap_uint64((GUInt64)(x))))
+#else
+/** Byte-swap a 32bit unsigned integer */
+#define CPL_SWAP32(x) \
+        ((GUInt32)( \
+            (((GUInt32)(x) & (GUInt32)0x000000ffUL) << 24) | \
+            (((GUInt32)(x) & (GUInt32)0x0000ff00UL) <<  8) | \
+            (((GUInt32)(x) & (GUInt32)0x00ff0000UL) >>  8) | \
+            (((GUInt32)(x) & (GUInt32)0xff000000UL) >> 24) ))
+
+/** Byte-swap a 64bit unsigned integer */
+#define CPL_SWAP64(x) \
+            (((GUInt64)(CPL_SWAP32((GUInt32)(x))) << 32) | \
+             (GUInt64)(CPL_SWAP32((GUInt32)((GUInt64)(x) >> 32))))
+
+#endif
 
+/** Byte-swap a 16 bit pointer */
 #define CPL_SWAP16PTR(x) \
 {                                                                 \
     GByte       byTemp, *_pabyDataT = (GByte *) (x);              \
@@ -629,13 +793,9 @@ template<> struct CPLStaticAssert<true>
     _pabyDataT[1] = byTemp;                                       \
 }
 
-#define CPL_SWAP32(x) \
-        ((GUInt32)( \
-            (((GUInt32)(x) & (GUInt32)0x000000ffUL) << 24) | \
-            (((GUInt32)(x) & (GUInt32)0x0000ff00UL) <<  8) | \
-            (((GUInt32)(x) & (GUInt32)0x00ff0000UL) >>  8) | \
-            (((GUInt32)(x) & (GUInt32)0xff000000UL) >> 24) ))
+#if defined(MAKE_SANITIZE_HAPPY) || !(defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
 
+/** Byte-swap a 32 bit pointer */
 #define CPL_SWAP32PTR(x) \
 {                                                                 \
     GByte       byTemp, *_pabyDataT = (GByte *) (x);              \
@@ -649,6 +809,7 @@ template<> struct CPLStaticAssert<true>
     _pabyDataT[2] = byTemp;                                       \
 }
 
+/** Byte-swap a 64 bit pointer */
 #define CPL_SWAP64PTR(x) \
 {                                                                 \
     GByte       byTemp, *_pabyDataT = (GByte *) (x);              \
@@ -668,23 +829,33 @@ template<> struct CPLStaticAssert<true>
     _pabyDataT[4] = byTemp;                                       \
 }
 
+#else
 
-/* Until we have a safe 64 bits integer data type defined, we'll replace
- * this version of the CPL_SWAP64() macro with a less efficient one.
- */
-/*
-#define CPL_SWAP64(x) \
-        ((uint64)( \
-            (uint64)(((uint64)(x) & (uint64)0x00000000000000ffULL) << 56) | \
-            (uint64)(((uint64)(x) & (uint64)0x000000000000ff00ULL) << 40) | \
-            (uint64)(((uint64)(x) & (uint64)0x0000000000ff0000ULL) << 24) | \
-            (uint64)(((uint64)(x) & (uint64)0x00000000ff000000ULL) << 8) | \
-            (uint64)(((uint64)(x) & (uint64)0x000000ff00000000ULL) >> 8) | \
-            (uint64)(((uint64)(x) & (uint64)0x0000ff0000000000ULL) >> 24) | \
-            (uint64)(((uint64)(x) & (uint64)0x00ff000000000000ULL) >> 40) | \
-            (uint64)(((uint64)(x) & (uint64)0xff00000000000000ULL) >> 56) ))
-*/
+/** Byte-swap a 32 bit pointer */
+#define CPL_SWAP32PTR(x) \
+{                                                                           \
+    GUInt32 _n32;                                                           \
+    void* _lx = x;                                                          \
+    memcpy(&_n32, _lx, 4);                                                  \
+    CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 4); \
+    _n32 = CPL_SWAP32(_n32);                                                \
+    memcpy(_lx, &_n32, 4);                                                  \
+}
+
+/** Byte-swap a 64 bit pointer */
+#define CPL_SWAP64PTR(x) \
+{                                                                           \
+    GUInt64 _n64;                                                           \
+    void* _lx = x;                                                          \
+    memcpy(&_n64, _lx, 8);                                                    \
+    CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 8); \
+    _n64 = CPL_SWAP64(_n64);                                                \
+    memcpy(_lx, &_n64, 8);                                                    \
+}
+
+#endif
 
+/** Byte-swap a 64 bit pointer */
 #define CPL_SWAPDOUBLE(p) CPL_SWAP64PTR(p)
 
 #ifdef CPL_MSB
@@ -699,22 +870,36 @@ template<> struct CPLStaticAssert<true>
 #  define CPL_MSBPTR64(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 8)
 #  define CPL_LSBPTR64(x)       CPL_SWAP64PTR(x)
 #else
+/** Return a 16bit word from a originally LSB ordered word */
 #  define CPL_LSBWORD16(x)      (x)
+/** Return a 16bit word from a originally MSB ordered word */
 #  define CPL_MSBWORD16(x)      CPL_SWAP16(x)
+/** Return a 32bit word from a originally LSB ordered word */
 #  define CPL_LSBWORD32(x)      (x)
+/** Return a 32bit word from a originally MSB ordered word */
 #  define CPL_MSBWORD32(x)      CPL_SWAP32(x)
+/** Byte-swap if necessary a 16bit word at the location pointed from a originally LSB ordered pointer */
 #  define CPL_LSBPTR16(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 2)
+/** Byte-swap if necessary a 16bit word at the location pointed from a originally MSB ordered pointer */
 #  define CPL_MSBPTR16(x)       CPL_SWAP16PTR(x)
+/** Byte-swap if necessary a 32bit word at the location pointed from a originally LSB ordered pointer */
 #  define CPL_LSBPTR32(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 4)
+/** Byte-swap if necessary a 32bit word at the location pointed from a originally MSB ordered pointer */
 #  define CPL_MSBPTR32(x)       CPL_SWAP32PTR(x)
+/** Byte-swap if necessary a 64bit word at the location pointed from a originally LSB ordered pointer */
 #  define CPL_LSBPTR64(x)       CPL_STATIC_ASSERT_IF_AVAILABLE(sizeof(*(x)) == 1 || sizeof(*(x)) == 8)
+/** Byte-swap if necessary a 64bit word at the location pointed from a originally MSB ordered pointer */
 #  define CPL_MSBPTR64(x)       CPL_SWAP64PTR(x)
 #endif
 
-/** Return a Int16 from the 2 bytes ordered in LSB order at address x */
+/** Return a Int16 from the 2 bytes ordered in LSB order at address x.
+ * @deprecated Use rather CPL_LSBSINT16PTR or CPL_LSBUINT16PTR for explicit
+ * signedness. */
 #define CPL_LSBINT16PTR(x)    ((*(GByte*)(x)) | (*(((GByte*)(x))+1) << 8))
 
-/** Return a Int32 from the 4 bytes ordered in LSB order at address x */
+/** Return a Int32 from the 4 bytes ordered in LSB order at address x.
+ * @deprecated Use rather CPL_LSBSINT32PTR or CPL_LSBUINT32PTR for explicit
+ * signedness. */
 #define CPL_LSBINT32PTR(x)    ((*(GByte*)(x)) | (*(((GByte*)(x))+1) << 8) | \
                               (*(((GByte*)(x))+2) << 16) | (*(((GByte*)(x))+3) << 24))
 
@@ -730,7 +915,7 @@ template<> struct CPLStaticAssert<true>
 /** Return a unsigned Int32 from the 4 bytes ordered in LSB order at address x */
 #define CPL_LSBUINT32PTR(x) ((GUInt32)CPL_LSBINT32PTR(x))
 
-
+/*! @cond Doxygen_Suppress */
 /* Utility macro to explicitly mark intentionally unreferenced parameters. */
 #ifndef UNREFERENCED_PARAM
 #  ifdef UNREFERENCED_PARAMETER /* May be defined by Windows API */
@@ -739,6 +924,7 @@ template<> struct CPLStaticAssert<true>
 #    define UNREFERENCED_PARAM(param) ((void)param)
 #  endif /* UNREFERENCED_PARAMETER */
 #endif /* UNREFERENCED_PARAM */
+/*! @endcond */
 
 /***********************************************************************
  * Define CPL_CVSID() macro.  It can be disabled during a build by
@@ -748,6 +934,7 @@ template<> struct CPLStaticAssert<true>
  * being unused.
  */
 
+/*! @cond Doxygen_Suppress */
 #ifndef DISABLE_CVSID
 #if defined(__GNUC__) && __GNUC__ >= 4
 #  define CPL_CVSID(string)     static const char cpl_cvsid[] __attribute__((used)) = string;
@@ -758,74 +945,142 @@ static const char *cvsid_aw() { return( cvsid_aw() ? NULL : cpl_cvsid ); }
 #else
 #  define CPL_CVSID(string)
 #endif
+/*! @endcond */
 
-/* Null terminated variadic */
 /* We exclude mingw64 4.6 which seems to be broken regarding this */
 #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP) && !(defined(__MINGW64__) && __GNUC__ == 4 && __GNUC_MINOR__ == 6)
+/** Null terminated variadic */
 #   define CPL_NULL_TERMINATED     __attribute__((__sentinel__))
 #else
+/** Null terminated variadic */
 #   define CPL_NULL_TERMINATED
 #endif
 
 #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP)
+/** Tag a function to have printf() formatting */
 #define CPL_PRINT_FUNC_FORMAT( format_idx, arg_idx )  __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+/** Tag a function to have scanf() formatting */
 #define CPL_SCAN_FUNC_FORMAT( format_idx, arg_idx )  __attribute__((__format__ (__scanf__, format_idx, arg_idx)))
 #else
+/** Tag a function to have printf() formatting */
 #define CPL_PRINT_FUNC_FORMAT( format_idx, arg_idx )
+/** Tag a function to have scanf() formatting */
 #define CPL_SCAN_FUNC_FORMAT( format_idx, arg_idx )
 #endif
 
+#if defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(GDAL_COMPILATION) || defined(CPL_ENABLE_MSVC_ANNOTATIONS))
+#include <sal.h>
+# if _MSC_VER > 1400
+/** Macro into which to wrap the format argument of a printf-like function.
+ * Only used if ANALYZE=1 is specified to nmake */
+#  define CPL_FORMAT_STRING(arg) _Printf_format_string_ arg
+/** Macro into which to wrap the format argument of a sscanf-like function.
+ * Only used if ANALYZE=1 is specified to nmake */
+#  define CPL_SCANF_FORMAT_STRING(arg) _Scanf_format_string_ arg
+# else
+/** Macro into which to wrap the format argument of a printf-like function */
+#  define CPL_FORMAT_STRING(arg) __format_string arg
+/** Macro into which to wrap the format argument of a sscanf-like function. */
+#  define CPL_SCANF_FORMAT_STRING(arg) arg
+# endif
+#else
+/** Macro into which to wrap the format argument of a printf-like function */
+# define CPL_FORMAT_STRING(arg) arg
+/** Macro into which to wrap the format argument of a sscanf-like function. */
+# define CPL_SCANF_FORMAT_STRING(arg) arg
+#endif /* defined(_MSC_VER) && _MSC_VER >= 1400 && defined(GDAL_COMPILATION) */
+
 #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
+/** Qualifier to warn when the return value of a function is not used */
 #define CPL_WARN_UNUSED_RESULT                        __attribute__((warn_unused_result))
 #else
+/** Qualifier to warn when the return value of a function is not used */
 #define CPL_WARN_UNUSED_RESULT
 #endif
 
 #if defined(__GNUC__) && __GNUC__ >= 4
+/** Qualifier for an argument that is unused */
 #  define CPL_UNUSED __attribute((__unused__))
 #else
 /* TODO: add cases for other compilers */
+/** Qualifier for an argument that is unused */
 #  define CPL_UNUSED
 #endif
 
 #if defined(__GNUC__) && __GNUC__ >= 3 && !defined(DOXYGEN_SKIP)
+/** Qualifier for a function that does not return at all (terminates the process) */
 #define CPL_NO_RETURN                                __attribute__((noreturn))
 #else
+/** Qualifier for a function that does not return at all (terminates the process) */
 #define CPL_NO_RETURN
 #endif
 
+/*! @cond Doxygen_Suppress */
 /* Clang __has_attribute */
 #ifndef __has_attribute
   #define __has_attribute(x) 0  // Compatibility with non-clang compilers.
 #endif
 
-#if ((defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) || __has_attribute(returns_nonnull)) && !defined(DOXYGEN_SKIP)
+/*! @endcond */
+
+#if ((defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) || __has_attribute(returns_nonnull)) && !defined(DOXYGEN_SKIP) && !defined(__INTEL_COMPILER)
+/** Qualifier for a function that does not return NULL */
 #  define CPL_RETURNS_NONNULL __attribute__((returns_nonnull))
 #else
+/** Qualifier for a function that does not return NULL */
 #  define CPL_RETURNS_NONNULL
 #endif
 
-
 #if defined(__GNUC__) && __GNUC__ >= 4 && !defined(DOXYGEN_SKIP)
+/** restrict keyword to declare that pointers do not alias */
 #define CPL_RESTRICT __restrict__
 #else
+/** restrict keyword to declare that pointers do not alias */
 #define CPL_RESTRICT
 #endif
 
-/* Helper to remove the copy and assignment constructors so that the compiler
-   will not generate the default versions.
-
-   Must be placed in the private section of a class and should be at the end.
-*/
 #ifdef __cplusplus
 
+#if HAVE_CXX11 || _MSC_VER >= 1500
+
+/** To be used in public headers only. For non-public headers or .cpp files,
+ * use override directly. */
+#  define CPL_OVERRIDE override
+
+#else
+
+/** To be used in public headers only. For non-public headers or .cpp files,
+ * use override directly. */
+#  define CPL_OVERRIDE
+
+/* For GDAL source compilation only, ignore override if non C++11 compiler */
+#ifdef GDAL_COMPILATION
+#  define override
+#endif
+
+#endif /* HAVE_CXX11 || _MSC_VER >= 1500 */
+
 #if HAVE_CXX11
+/** C++11 final qualifier */
 #  define CPL_FINAL final
+
+/** Helper to remove the copy and assignment constructors so that the compiler
+   will not generate the default versions.
+
+   Must be placed in the private section of a class and should be at the end.
+*/
 #  define CPL_DISALLOW_COPY_ASSIGN(ClassName) \
     ClassName( const ClassName & ) = delete; \
     ClassName &operator=( const ClassName & ) = delete;
 #else
+/** C++11 final qualifier */
 #  define CPL_FINAL
+
+/** Helper to remove the copy and assignment constructors so that the compiler
+   will not generate the default versions.
+
+   Must be placed in the private section of a class and should be at the end.
+*/
 #  define CPL_DISALLOW_COPY_ASSIGN(ClassName) \
     ClassName( const ClassName & ); \
     ClassName &operator=( const ClassName & );
@@ -848,28 +1103,33 @@ static const char *cvsid_aw() { return( cvsid_aw() ? NULL : cpl_cvsid ); }
 #endif
 #endif
 
-#if !defined(_MSC_VER) && !defined(__APPLE__)
+#if !defined(_MSC_VER) && !defined(__APPLE__) && !defined(_FORTIFY_SOURCE)
 CPL_C_START
-#ifdef WARN_STANDARD_PRINTF
-int vsnprintf(char *str, size_t size, const char* fmt, va_list args) CPL_WARN_DEPRECATED("Use CPLvsnprintf() instead");
-int snprintf(char *str, size_t size, const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(3,4) CPL_WARN_DEPRECATED("Use CPLsnprintf() instead");
-int sprintf(char *str, const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_DEPRECATED("Use CPLsnprintf() instead");
-#elif defined(GDAL_COMPILATION) && !defined(DONT_DEPRECATE_SPRINTF)
-int sprintf(char *str, const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_DEPRECATED("Use snprintf() or CPLsnprintf() instead");
-#endif
+#  if defined(GDAL_COMPILATION) && defined(WARN_STANDARD_PRINTF)
+int vsnprintf(char *str, size_t size, const char* fmt, va_list args)
+    CPL_WARN_DEPRECATED("Use CPLvsnprintf() instead");
+int snprintf(char *str, size_t size, const char* fmt, ...)
+    CPL_PRINT_FUNC_FORMAT(3,4)
+    CPL_WARN_DEPRECATED("Use CPLsnprintf() instead");
+int sprintf(char *str, const char* fmt, ...)
+    CPL_PRINT_FUNC_FORMAT(2, 3)
+    CPL_WARN_DEPRECATED("Use CPLsnprintf() instead");
+#  elif defined(GDAL_COMPILATION) && !defined(DONT_DEPRECATE_SPRINTF)
+int sprintf(char *str, const char* fmt, ...)
+    CPL_PRINT_FUNC_FORMAT(2, 3)
+    CPL_WARN_DEPRECATED("Use snprintf() or CPLsnprintf() instead");
+#  endif /* defined(GDAL_COMPILATION) && defined(WARN_STANDARD_PRINTF) */
 CPL_C_END
 #endif /* !defined(_MSC_VER) && !defined(__APPLE__) */
 
 #if defined(MAKE_SANITIZE_HAPPY) || !(defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64))
+/*! @cond Doxygen_Suppress */
 #define CPL_CPU_REQUIRES_ALIGNED_ACCESS
-#define CPL_IS_DOUBLE_A_INT(d)  ( (d) >= INT_MIN && (d) <= INT_MAX && (double)(int)(d) == (d) )
-#else
-/* This is technically unspecified behaviour if the double is out of range, but works OK on x86 */
-#define CPL_IS_DOUBLE_A_INT(d)  ( (double)(int)(d) == (d) )
+/*! @endcond */
 #endif
 
 #ifdef __cplusplus
-/* The size of C style arrays. */
+/** Returns the size of C style arrays. */
 #define CPL_ARRAYSIZE(array) \
   ((sizeof(array) / sizeof(*(array))) / \
   static_cast<size_t>(!(sizeof(array) % sizeof(*(array)))))
@@ -889,12 +1149,15 @@ inline static bool CPL_TO_BOOL(int x) { return x != 0; }
 #define HAVE_GCC_SYSTEM_HEADER
 #endif
 
-#if defined(__clang__)
+#if ((defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))) || __GNUC__ >= 7) && HAVE_CXX11
+/** Macro for fallthrough in a switch case construct */
 #  define CPL_FALLTHROUGH [[clang::fallthrough]];
 #else
+/** Macro for fallthrough in a switch case construct */
 #  define CPL_FALLTHROUGH
 #endif
 
+/*! @cond Doxygen_Suppress */
 // Define DEBUG_BOOL to compile in "MSVC mode", ie error out when
 // a integer is assigned to a bool
 // WARNING: use only at compilation time, since it is know to not work
@@ -976,5 +1239,6 @@ inline bool operator!= (const bool& one, const MSVCPedanticBool& other) { return
 #define VOLATILE_BOOL volatile bool
 
 #endif /* defined(__cplusplus) && defined(DEBUG_BOOL) */
+/*! @endcond */
 
 #endif /* ndef CPL_BASE_H_INCLUDED */
diff --git a/port/cpl_progress.cpp b/port/cpl_progress.cpp
index a1828df..311a980 100644
--- a/port/cpl_progress.cpp
+++ b/port/cpl_progress.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -28,13 +27,15 @@
  ****************************************************************************/
 
 #include "cpl_progress.h"
-#include "cpl_conv.h"
 
 #include <cmath>
+#include <cstdio>
 
 #include <algorithm>
 
-CPL_CVSID("$Id: gdal_misc.cpp 25494 2013-01-13 12:55:17Z etourigny $");
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: cpl_progress.cpp 36768 2016-12-10 01:32:06Z goatbar $");
 
 /************************************************************************/
 /*                         GDALDummyProgress()                          */
@@ -146,8 +147,8 @@ void * CPL_STDCALL GDALCreateScaledProgress( double dfMin, double dfMax,
     if( pfnProgress == NULL || pfnProgress == GDALDummyProgress )
         return NULL;
 
-    GDALScaledProgressInfo *psInfo
-        = static_cast<GDALScaledProgressInfo *>(
+    GDALScaledProgressInfo *psInfo =
+        static_cast<GDALScaledProgressInfo *>(
             CPLCalloc( sizeof(GDALScaledProgressInfo), 1 ) );
 
     if( std::abs(dfMin-dfMax) < 0.0000001 )
@@ -185,6 +186,7 @@ void CPL_STDCALL GDALDestroyScaledProgress( void * pData )
 /************************************************************************/
 
 /**
+ * \fn GDALTermProgress(double, const char*, void*)
  * \brief Simple progress report to terminal.
  *
  * This progress reporter prints simple progress report to the
@@ -212,11 +214,11 @@ void CPL_STDCALL GDALDestroyScaledProgress( void * pData )
  * @return Always returns TRUE indicating the process should continue.
  */
 
-int CPL_STDCALL GDALTermProgress( CPL_UNUSED double dfComplete,
-                                  CPL_UNUSED const char *pszMessage,
-                                  void * /* pProgressArg */ )
+int CPL_STDCALL GDALTermProgress( double dfComplete,
+                                  CPL_UNUSED const char * pszMessage,
+                                  CPL_UNUSED void * pProgressArg )
 {
-    int nThisTick = std::min(40, std::max(0,
+    const int nThisTick = std::min(40, std::max(0,
         static_cast<int>(dfComplete * 40.0) ));
 
     // Have we started a new progress run?
diff --git a/port/cpl_progress.h b/port/cpl_progress.h
index aa5fe52..08b9a5e 100644
--- a/port/cpl_progress.h
+++ b/port/cpl_progress.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: cpl_progress.h 34518 2016-07-02 21:01:34Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
diff --git a/port/cpl_quad_tree.cpp b/port/cpl_quad_tree.cpp
index 09963a6..c10c51a 100644
--- a/port/cpl_quad_tree.cpp
+++ b/port/cpl_quad_tree.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_quad_tree.cpp 33199 2016-01-29 15:48:41Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of quadtree building and searching functions.
@@ -31,10 +30,16 @@
  ******************************************************************************
  */
 
-#include "cpl_conv.h"
+#include "cpl_port.h"
 #include "cpl_quad_tree.h"
 
-CPL_CVSID("$Id: cpl_quad_tree.cpp 33199 2016-01-29 15:48:41Z rouault $");
+#include <cstdio>
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+
+CPL_CVSID("$Id: cpl_quad_tree.cpp 36978 2016-12-20 17:25:51Z goatbar $");
 
 static const int MAX_DEFAULT_TREE_DEPTH = 12;
 static const int MAX_SUBNODES = 4;
@@ -66,17 +71,16 @@ struct _CPLQuadTree
   double                    dfSplitRatio;
 };
 
-
 static void CPLQuadTreeAddFeatureInternal(CPLQuadTree *hQuadTree,
                                           void* hFeature,
                                           const CPLRectObj *pRect);
 
 /* -------------------------------------------------------------------- */
-/*      If the following is 0.5, psNodes will be split in half.  If it    */
-/*      is 0.6 then each apSubNode will contain 60% of the parent         */
-/*      psNode, with 20% representing overlap.  This can be help to       */
+/*      If the following is 0.5, psNodes will be split in half.  If it  */
+/*      is 0.6 then each apSubNode will contain 60% of the parent       */
+/*      psNode, with 20% representing overlap.  This can be help to     */
 /*      prevent small objects on a boundary from shifting too high      */
-/*      up the hQuadTree.                                                    */
+/*      up the hQuadTree.                                               */
 /* -------------------------------------------------------------------- */
 static const double DEFAULT_SPLIT_RATIO = 0.55;
 
@@ -86,10 +90,9 @@ static const double DEFAULT_SPLIT_RATIO = 0.55;
 static CPL_INLINE bool CPL_RectContained( const CPLRectObj *a,
                                           const CPLRectObj *b )
 {
-  if(a->minx >= b->minx && a->maxx <= b->maxx)
-    if(a->miny >= b->miny && a->maxy <= b->maxy)
-      return(true);
-  return(false);
+    return
+        a->minx >= b->minx && a->maxx <= b->maxx &&
+        a->miny >= b->miny && a->maxy <= b->maxy;
 }
 
 /*
@@ -98,11 +101,11 @@ static CPL_INLINE bool CPL_RectContained( const CPLRectObj *a,
 static CPL_INLINE bool CPL_RectOverlap( const CPLRectObj *a,
                                         const CPLRectObj *b )
 {
-  if(a->minx > b->maxx) return(false);
-  if(a->maxx < b->minx) return(false);
-  if(a->miny > b->maxy) return(false);
-  if(a->maxy < b->miny) return(false);
-  return(true);
+    if( a->minx > b->maxx ) return false;
+    if( a->maxx < b->minx ) return false;
+    if( a->miny > b->maxy ) return false;
+    if( a->maxy < b->miny ) return false;
+    return true;
 }
 
 /************************************************************************/
@@ -213,7 +216,6 @@ int CPLQuadTreeGetAdvisedMaxDepth(int nExpectedFeatures)
                   "Falling back to max number of allowed index tree "
                   "levels (%d).",
                   MAX_DEFAULT_TREE_DEPTH );
-
     }
 
     return nMaxDepth;
@@ -274,7 +276,7 @@ void CPLQuadTreeInsert(CPLQuadTree * hQuadTree, void* hFeature)
                  "hQuadTree->pfnGetBounds == NULL");
         return;
     }
-    hQuadTree->nFeatures ++;
+    hQuadTree->nFeatures++;
     CPLRectObj bounds;
     hQuadTree->pfnGetBounds(hFeature, &bounds);
     CPLQuadTreeAddFeatureInternal(hQuadTree, hFeature, &bounds);
@@ -295,7 +297,7 @@ void CPLQuadTreeInsertWithBounds(CPLQuadTree *hQuadTree,
                                  void* hFeature,
                                  const CPLRectObj* psBounds)
 {
-    hQuadTree->nFeatures ++;
+    hQuadTree->nFeatures++;
     CPLQuadTreeAddFeatureInternal(hQuadTree, hFeature, psBounds);
 }
 
@@ -305,13 +307,13 @@ void CPLQuadTreeInsertWithBounds(CPLQuadTree *hQuadTree,
 
 static void CPLQuadTreeNodeDestroy(QuadTreeNode *psNode)
 {
-    for(int i=0; i<psNode->nNumSubNodes; i++ )
+    for( int i = 0; i < psNode->nNumSubNodes; i++ )
     {
-        if(psNode->apSubNode[i])
+        if( psNode->apSubNode[i] )
             CPLQuadTreeNodeDestroy(psNode->apSubNode[i]);
     }
 
-    if(psNode->pahFeatures)
+    if( psNode->pahFeatures )
     {
         CPLFree(psNode->pahFeatures);
         CPLFree(psNode->pasBounds);
@@ -320,7 +322,6 @@ static void CPLQuadTreeNodeDestroy(QuadTreeNode *psNode)
     CPLFree(psNode);
 }
 
-
 /************************************************************************/
 /*                       CPLQuadTreeDestroy()                           */
 /************************************************************************/
@@ -338,8 +339,6 @@ void CPLQuadTreeDestroy(CPLQuadTree *hQuadTree)
     CPLFree(hQuadTree);
 }
 
-
-
 /************************************************************************/
 /*                     CPLQuadTreeSplitBounds()                         */
 /************************************************************************/
@@ -349,32 +348,34 @@ static void CPLQuadTreeSplitBounds( double dfSplitRatio,
                                       CPLRectObj *out1,
                                       CPLRectObj *out2)
 {
-  /* -------------------------------------------------------------------- */
-  /*      The output bounds will be very similar to the input bounds,     */
-  /*      so just copy over to start.                                     */
-  /* -------------------------------------------------------------------- */
-  memcpy(out1, in, sizeof(CPLRectObj));
-  memcpy(out2, in, sizeof(CPLRectObj));
+    /* -------------------------------------------------------------------- */
+    /*      The output bounds will be very similar to the input bounds,     */
+    /*      so just copy over to start.                                     */
+    /* -------------------------------------------------------------------- */
+    memcpy(out1, in, sizeof(CPLRectObj));
+    memcpy(out2, in, sizeof(CPLRectObj));
 
-  /* -------------------------------------------------------------------- */
-  /*      Split in X direction.                                           */
-  /* -------------------------------------------------------------------- */
-  if((in->maxx - in->minx) > (in->maxy - in->miny)) {
-    const double range = in->maxx - in->minx;
+    /* -------------------------------------------------------------------- */
+    /*      Split in X direction.                                           */
+    /* -------------------------------------------------------------------- */
+    if( (in->maxx - in->minx) > (in->maxy - in->miny) )
+    {
+        const double range = in->maxx - in->minx;
 
-    out1->maxx = in->minx + range * dfSplitRatio;
-    out2->minx = in->maxx - range * dfSplitRatio;
-  }
+        out1->maxx = in->minx + range * dfSplitRatio;
+        out2->minx = in->maxx - range * dfSplitRatio;
+    }
 
-  /* -------------------------------------------------------------------- */
-  /*      Otherwise split in Y direction.                                 */
-  /* -------------------------------------------------------------------- */
-  else {
-    const double range = in->maxy - in->miny;
+    /* -------------------------------------------------------------------- */
+    /*      Otherwise split in Y direction.                                 */
+    /* -------------------------------------------------------------------- */
+    else
+    {
+        const double range = in->maxy - in->miny;
 
-    out1->maxy = in->miny + range * dfSplitRatio;
-    out2->miny = in->maxy - range * dfSplitRatio;
-  }
+        out1->maxy = in->miny + range * dfSplitRatio;
+        out2->miny = in->maxy - range * dfSplitRatio;
+    }
 }
 
 /************************************************************************/
@@ -386,13 +387,18 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
                                            void* hFeature,
                                            const CPLRectObj* pRect)
 {
-    if (psNode->nNumSubNodes == 0)
+    if( psNode->nNumSubNodes == 0 )
     {
-        /* If we have reached the max bucket capacity, try to insert */
-        /* in a subnode if possible */
-        if (psNode->nFeatures >= hQuadTree->nBucketCapacity)
+        // If we have reached the max bucket capacity, try to insert
+        // in a subnode if possible.
+        if( psNode->nFeatures >= hQuadTree->nBucketCapacity )
         {
-            CPLRectObj half1, half2, quad1, quad2, quad3, quad4;
+            CPLRectObj half1 = { 0.0, 0.0, 0.0, 0.0 };
+            CPLRectObj half2 = { 0.0, 0.0, 0.0, 0.0 };
+            CPLRectObj quad1 = { 0.0, 0.0, 0.0, 0.0 };
+            CPLRectObj quad2 = { 0.0, 0.0, 0.0, 0.0 };
+            CPLRectObj quad3 = { 0.0, 0.0, 0.0, 0.0 };
+            CPLRectObj quad4 = { 0.0, 0.0, 0.0, 0.0 };
 
             CPLQuadTreeSplitBounds( hQuadTree->dfSplitRatio, &psNode->rect,
                                     &half1, &half2);
@@ -401,14 +407,14 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
             CPLQuadTreeSplitBounds( hQuadTree->dfSplitRatio, &half2,
                                     &quad3, &quad4);
 
-            if (memcmp(&psNode->rect, &quad1, sizeof(CPLRectObj)) != 0 &&
+            if( memcmp(&psNode->rect, &quad1, sizeof(CPLRectObj)) != 0 &&
                 memcmp(&psNode->rect, &quad2, sizeof(CPLRectObj)) != 0 &&
                 memcmp(&psNode->rect, &quad3, sizeof(CPLRectObj)) != 0 &&
                 memcmp(&psNode->rect, &quad4, sizeof(CPLRectObj)) != 0 &&
                 (CPL_RectContained(pRect, &quad1) ||
                 CPL_RectContained(pRect, &quad2) ||
                 CPL_RectContained(pRect, &quad3) ||
-                CPL_RectContained(pRect, &quad4)))
+                CPL_RectContained(pRect, &quad4)) )
             {
                 psNode->nNumSubNodes = 4;
                 psNode->apSubNode[0] = CPLQuadTreeNodeCreate(&quad1);
@@ -423,8 +429,8 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
                 psNode->pahFeatures = NULL;
                 psNode->pasBounds = NULL;
 
-                /* redispatch existing pahFeatures in apSubNodes */
-                for(int i=0;i<oldNumFeatures;i++)
+                // Redispatch existing pahFeatures in apSubNodes.
+                for( int i = 0; i < oldNumFeatures; i++ )
                 {
                     if( hQuadTree->pfnGetBounds == NULL )
                         CPLQuadTreeNodeAddFeatureAlg1( hQuadTree, psNode,
@@ -453,10 +459,10 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
     else
     {
     /* -------------------------------------------------------------------- */
-    /*      If there are apSubNodes, then consider whether this object        */
+    /*      If there are apSubNodes, then consider whether this object      */
     /*      will fit in them.                                               */
     /* -------------------------------------------------------------------- */
-        for(int i=0; i<psNode->nNumSubNodes; i++ )
+        for( int i = 0; i < psNode->nNumSubNodes; i++ )
         {
             if( CPL_RectContained(pRect, &psNode->apSubNode[i]->rect))
             {
@@ -495,10 +501,9 @@ static void CPLQuadTreeNodeAddFeatureAlg1( CPLQuadTree* hQuadTree,
     if( hQuadTree->pfnGetBounds == NULL )
         psNode->pasBounds[psNode->nFeatures-1] = *pRect;
 
-    return ;
+    return;
 }
 
-
 /************************************************************************/
 /*                  CPLQuadTreeNodeAddFeatureAlg2()                     */
 /************************************************************************/
@@ -510,12 +515,12 @@ static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
                                            int nMaxDepth)
 {
   /* -------------------------------------------------------------------- */
-  /*      If there are apSubNodes, then consider whether this object        */
+  /*      If there are apSubNodes, then consider whether this object      */
   /*      will fit in them.                                               */
   /* -------------------------------------------------------------------- */
     if( nMaxDepth > 1 && psNode->nNumSubNodes > 0 )
     {
-        for(int i=0; i<psNode->nNumSubNodes; i++ )
+        for( int i = 0; i < psNode->nNumSubNodes; i++ )
         {
             if( CPL_RectContained(pRect, &psNode->apSubNode[i]->rect))
             {
@@ -527,8 +532,8 @@ static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
     }
 
   /* -------------------------------------------------------------------- */
-  /*      Otherwise, consider creating four apSubNodes if could fit into    */
-  /*      them, and adding to the appropriate apSubNode.                    */
+  /*      Otherwise, consider creating four apSubNodes if could fit into  */
+  /*      them, and adding to the appropriate apSubNode.                  */
   /* -------------------------------------------------------------------- */
     else if( nMaxDepth > 1 && psNode->nNumSubNodes == 0 )
     {
@@ -561,9 +566,8 @@ static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
         }
     }
 
-
 /* -------------------------------------------------------------------- */
-/*      If none of that worked, just add it to this psNodes list.         */
+/*      If none of that worked, just add it to this psNodes list.       */
 /* -------------------------------------------------------------------- */
     psNode->nFeatures++;
 
@@ -584,7 +588,6 @@ static void CPLQuadTreeNodeAddFeatureAlg2( CPLQuadTree *hQuadTree,
     }
 }
 
-
 /************************************************************************/
 /*                  CPLQuadTreeAddFeatureInternal()                     */
 /************************************************************************/
@@ -593,7 +596,7 @@ static void CPLQuadTreeAddFeatureInternal(CPLQuadTree *hQuadTree,
                                           void* hFeature,
                                           const CPLRectObj *pRect)
 {
-    if (hQuadTree->nMaxDepth == 0)
+    if( hQuadTree->nMaxDepth == 0 )
     {
         CPLQuadTreeNodeAddFeatureAlg1(hQuadTree, hQuadTree->psRoot,
                                      hFeature, pRect);
@@ -616,52 +619,53 @@ static void CPLQuadTreeCollectFeatures(const CPLQuadTree *hQuadTree,
                                        int* pnMaxFeatures,
                                        void*** pppFeatureList)
 {
-  /* -------------------------------------------------------------------- */
-  /*      Does this psNode overlap the area of interest at all?  If not,  */
-  /*      return without adding to the list at all.                       */
-  /* -------------------------------------------------------------------- */
-  if(!CPL_RectOverlap(&psNode->rect, pAoi))
-     return;
+    /* -------------------------------------------------------------------- */
+    /*      Does this psNode overlap the area of interest at all?  If not,  */
+    /*      return without adding to the list at all.                       */
+    /* -------------------------------------------------------------------- */
+    if( !CPL_RectOverlap(&psNode->rect, pAoi) )
+        return;
 
-  /* -------------------------------------------------------------------- */
-  /*      Grow the list to hold the features on this psNode.              */
-  /* -------------------------------------------------------------------- */
-  if( *pnFeatureCount + psNode->nFeatures > *pnMaxFeatures )
-  {
-      *pnMaxFeatures = (*pnFeatureCount + psNode->nFeatures) * 2 + 20;
-      *pppFeatureList = static_cast<void **>(
-          CPLRealloc(*pppFeatureList,sizeof(void*) * *pnMaxFeatures) );
-  }
+    /* -------------------------------------------------------------------- */
+    /*      Grow the list to hold the features on this psNode.              */
+    /* -------------------------------------------------------------------- */
+    if( *pnFeatureCount + psNode->nFeatures > *pnMaxFeatures )
+    {
+        // TODO(schwehr): Symbolic constant.
+        *pnMaxFeatures = (*pnFeatureCount + psNode->nFeatures) * 2 + 20;
+        *pppFeatureList = static_cast<void **>(
+            CPLRealloc(*pppFeatureList, sizeof(void*) * *pnMaxFeatures) );
+    }
 
-  /* -------------------------------------------------------------------- */
-  /*      Add the local features to the list.                             */
-  /* -------------------------------------------------------------------- */
-  for(int i=0; i<psNode->nFeatures; i++)
-  {
-      if( hQuadTree->pfnGetBounds == NULL )
-      {
-          if (CPL_RectOverlap(&psNode->pasBounds[i], pAoi))
-            (*pppFeatureList)[(*pnFeatureCount)++] = psNode->pahFeatures[i];
-      }
-      else
-      {
-          CPLRectObj bounds;
-          hQuadTree->pfnGetBounds(psNode->pahFeatures[i], &bounds);
-          if (CPL_RectOverlap(&bounds, pAoi))
-            (*pppFeatureList)[(*pnFeatureCount)++] = psNode->pahFeatures[i];
-      }
-  }
+    /* -------------------------------------------------------------------- */
+    /*      Add the local features to the list.                             */
+    /* -------------------------------------------------------------------- */
+    for( int i = 0; i < psNode->nFeatures; i++ )
+    {
+        if( hQuadTree->pfnGetBounds == NULL )
+        {
+            if( CPL_RectOverlap(&psNode->pasBounds[i], pAoi) )
+                (*pppFeatureList)[(*pnFeatureCount)++] = psNode->pahFeatures[i];
+        }
+        else
+        {
+            CPLRectObj bounds;
+            hQuadTree->pfnGetBounds(psNode->pahFeatures[i], &bounds);
+            if( CPL_RectOverlap(&bounds, pAoi) )
+                (*pppFeatureList)[(*pnFeatureCount)++] = psNode->pahFeatures[i];
+        }
+    }
 
-  /* -------------------------------------------------------------------- */
-  /*      Recurse to subnodes if they exist.                              */
-  /* -------------------------------------------------------------------- */
-  for(int i=0; i<psNode->nNumSubNodes; i++)
-  {
-      if(psNode->apSubNode[i])
-        CPLQuadTreeCollectFeatures( hQuadTree, psNode->apSubNode[i], pAoi,
-                                    pnFeatureCount, pnMaxFeatures,
-                                    pppFeatureList );
-  }
+    /* -------------------------------------------------------------------- */
+    /*      Recurse to subnodes if they exist.                              */
+    /* -------------------------------------------------------------------- */
+    for( int i = 0; i < psNode->nNumSubNodes; i++ )
+    {
+        if( psNode->apSubNode[i] )
+            CPLQuadTreeCollectFeatures( hQuadTree, psNode->apSubNode[i], pAoi,
+                                        pnFeatureCount, pnMaxFeatures,
+                                        pppFeatureList );
+    }
 }
 
 /************************************************************************/
@@ -679,25 +683,25 @@ static void CPLQuadTreeCollectFeatures(const CPLQuadTree *hQuadTree,
  * @return an array of features that must be freed with CPLFree
  */
 
-void** CPLQuadTreeSearch(const CPLQuadTree *hQuadTree,
-                         const CPLRectObj* pAoi,
-                         int* pnFeatureCount)
+void** CPLQuadTreeSearch( const CPLQuadTree *hQuadTree,
+                          const CPLRectObj* pAoi,
+                          int* pnFeatureCount )
 {
-  CPLAssert(hQuadTree);
-  CPLAssert(pAoi);
+    CPLAssert(hQuadTree);
+    CPLAssert(pAoi);
 
-  int nFeatureCount = 0;
-  if (pnFeatureCount == NULL)
-      pnFeatureCount = &nFeatureCount;
+    int nFeatureCount = 0;
+    if( pnFeatureCount == NULL )
+        pnFeatureCount = &nFeatureCount;
 
-  *pnFeatureCount = 0;
+    *pnFeatureCount = 0;
 
-  int nMaxFeatures = 0;
-  void** ppFeatureList = NULL;
-  CPLQuadTreeCollectFeatures(hQuadTree, hQuadTree->psRoot, pAoi,
-                            pnFeatureCount, &nMaxFeatures, &ppFeatureList);
+    int nMaxFeatures = 0;
+    void** ppFeatureList = NULL;
+    CPLQuadTreeCollectFeatures(hQuadTree, hQuadTree->psRoot, pAoi,
+                               pnFeatureCount, &nMaxFeatures, &ppFeatureList);
 
-  return ppFeatureList;
+    return ppFeatureList;
 }
 
 /************************************************************************/
@@ -708,15 +712,16 @@ static bool CPLQuadTreeNodeForeach(const QuadTreeNode *psNode,
                                   CPLQuadTreeForeachFunc pfnForeach,
                                   void* pUserData)
 {
-    for(int i=0; i<psNode->nNumSubNodes; i++ )
+    for( int i = 0; i < psNode->nNumSubNodes; i++ )
     {
-        if( !CPLQuadTreeNodeForeach(psNode->apSubNode[i], pfnForeach, pUserData) )
+        if( !CPLQuadTreeNodeForeach(psNode->apSubNode[i], pfnForeach,
+                                    pUserData) )
             return false;
     }
 
-    for(int i=0; i<psNode->nFeatures; i++)
+    for( int i = 0; i < psNode->nFeatures; i++ )
     {
-        if (pfnForeach(psNode->pahFeatures[i], pUserData) == FALSE)
+        if( pfnForeach(psNode->pahFeatures[i], pUserData) == FALSE )
             return false;
     }
 
@@ -743,9 +748,9 @@ static bool CPLQuadTreeNodeForeach(const QuadTreeNode *psNode,
  * @param pUserData the user data provided to the function.
  */
 
-void  CPLQuadTreeForeach(const CPLQuadTree *hQuadTree,
+void CPLQuadTreeForeach( const CPLQuadTree *hQuadTree,
                          CPLQuadTreeForeachFunc pfnForeach,
-                         void* pUserData)
+                         void* pUserData )
 {
     CPLAssert(hQuadTree);
     CPLAssert(pfnForeach);
@@ -756,40 +761,48 @@ void  CPLQuadTreeForeach(const CPLQuadTree *hQuadTree,
 /*                       CPLQuadTreeDumpNode()                          */
 /************************************************************************/
 
-static void CPLQuadTreeDumpNode(const QuadTreeNode *psNode,
-                                int nIndentLevel,
-                                CPLQuadTreeDumpFeatureFunc pfnDumpFeatureFunc,
-                                void* pUserData)
+static void CPLQuadTreeDumpNode( const QuadTreeNode *psNode,
+                                 int nIndentLevel,
+                                 CPLQuadTreeDumpFeatureFunc pfnDumpFeatureFunc,
+                                 void* pUserData )
 {
-    if (psNode->nNumSubNodes)
+    if( psNode->nNumSubNodes )
     {
-        for(int count=nIndentLevel;--count>=0;)
-            printf("  ");
-        printf("SubhQuadTrees :\n");
-        for(int i=0; i<psNode->nNumSubNodes; i++ )
+        for( int count = nIndentLevel; --count >= 0; )
+        {
+            printf("  "); /*ok*/
+        }
+        printf("SubhQuadTrees :\n"); /*ok*/
+        for( int i = 0; i < psNode->nNumSubNodes; i++ )
         {
-            for(int count=nIndentLevel+1;--count>=0;)
-                printf("  ");
-            printf("SubhQuadTree %d :\n", i+1);
+            for( int count = nIndentLevel+1; --count >= 0; )
+            {
+                printf("  "); /*ok*/
+            }
+            printf("SubhQuadTree %d :\n", i+1); /*ok*/
             CPLQuadTreeDumpNode(psNode->apSubNode[i], nIndentLevel + 2,
                                 pfnDumpFeatureFunc, pUserData);
         }
     }
-    if (psNode->nFeatures)
+    if( psNode->nFeatures )
     {
-        for(int count=nIndentLevel;--count>=0;)
-            printf("  ");
-        printf("Leaves (%d):\n", psNode->nFeatures);
-        for(int i=0; i<psNode->nFeatures; i++)
+        for( int count = nIndentLevel; --count >= 0; )
+            printf("  "); /*ok*/
+        printf("Leaves (%d):\n", psNode->nFeatures); /*ok*/
+        for( int i = 0; i < psNode->nFeatures; i++ )
         {
-            if (pfnDumpFeatureFunc)
+            if( pfnDumpFeatureFunc )
+            {
                 pfnDumpFeatureFunc(psNode->pahFeatures[i], nIndentLevel + 2,
                                    pUserData);
+            }
             else
             {
-                for(int count=nIndentLevel + 1;--count>=0;)
-                    printf("  ");
-                printf("%p\n", psNode->pahFeatures[i]);
+                for( int count = nIndentLevel + 1; --count >= 0; )
+                {
+                    printf("  "); /*ok*/
+                }
+                printf("%p\n", psNode->pahFeatures[i]); /*ok*/
             }
         }
     }
@@ -799,9 +812,10 @@ static void CPLQuadTreeDumpNode(const QuadTreeNode *psNode,
 /*                         CPLQuadTreeDump()                            */
 /************************************************************************/
 
-void CPLQuadTreeDump(const CPLQuadTree *hQuadTree,
-                     CPLQuadTreeDumpFeatureFunc pfnDumpFeatureFunc,
-                     void* pUserData)
+/** Dump quad tree */
+void CPLQuadTreeDump( const CPLQuadTree *hQuadTree,
+                      CPLQuadTreeDumpFeatureFunc pfnDumpFeatureFunc,
+                      void* pUserData )
 {
     CPLQuadTreeDumpNode(hQuadTree->psRoot, 0, pfnDumpFeatureFunc, pUserData);
 }
@@ -811,45 +825,49 @@ void CPLQuadTreeDump(const CPLQuadTree *hQuadTree,
 /************************************************************************/
 
 static
-void CPLQuadTreeGetStatsNode(const QuadTreeNode *psNode,
-                             int nDepthLevel,
-                             int* pnNodeCount,
-                             int* pnMaxDepth,
-                             int* pnMaxBucketCapacity)
+void CPLQuadTreeGetStatsNode( const QuadTreeNode *psNode,
+                              int nDepthLevel,
+                              int* pnNodeCount,
+                              int* pnMaxDepth,
+                              int* pnMaxBucketCapacity )
 {
     (*pnNodeCount) ++;
-    if (nDepthLevel > *pnMaxDepth)
+    if( nDepthLevel > *pnMaxDepth )
         *pnMaxDepth = nDepthLevel;
-    if (psNode->nFeatures > *pnMaxBucketCapacity)
+    if( psNode->nFeatures > *pnMaxBucketCapacity )
         *pnMaxBucketCapacity = psNode->nFeatures;
 
-    for(int i=0; i<psNode->nNumSubNodes; i++ )
+    for( int i = 0; i < psNode->nNumSubNodes; i++ )
     {
         CPLQuadTreeGetStatsNode(psNode->apSubNode[i], nDepthLevel + 1,
                                 pnNodeCount, pnMaxDepth, pnMaxBucketCapacity);
     }
 }
 
-
 /************************************************************************/
 /*                    CPLQuadTreeGetStats()                             */
 /************************************************************************/
 
-void CPLQuadTreeGetStats(const CPLQuadTree *hQuadTree,
-                         int* pnFeatureCount,
-                         int* pnNodeCount,
-                         int* pnMaxDepth,
-                         int* pnMaxBucketCapacity)
+/** Get stats */
+void CPLQuadTreeGetStats( const CPLQuadTree *hQuadTree,
+                          int* pnFeatureCount,
+                          int* pnNodeCount,
+                          int* pnMaxDepth,
+                          int* pnMaxBucketCapacity )
 {
-    int nFeatureCount, nNodeCount, nMaxDepth, nMaxBucketCapacity;
     CPLAssert(hQuadTree);
-    if (pnFeatureCount == NULL)
+
+    int nFeatureCount = 0;
+    if( pnFeatureCount == NULL )
         pnFeatureCount = &nFeatureCount;
-    if (pnNodeCount == NULL)
+    int nNodeCount = 0;
+    if( pnNodeCount == NULL )
         pnNodeCount = &nNodeCount;
-    if (pnMaxDepth == NULL)
+    int nMaxDepth = 0;
+    if( pnMaxDepth == NULL )
         pnMaxDepth = &nMaxDepth;
-    if (pnMaxBucketCapacity == NULL)
+    int nMaxBucketCapacity = 0;
+    if( pnMaxBucketCapacity == NULL )
         pnMaxBucketCapacity = &nMaxBucketCapacity;
 
     *pnFeatureCount = hQuadTree->nFeatures;
@@ -859,4 +877,7 @@ void CPLQuadTreeGetStats(const CPLQuadTree *hQuadTree,
 
     CPLQuadTreeGetStatsNode( hQuadTree->psRoot, 0, pnNodeCount, pnMaxDepth,
                              pnMaxBucketCapacity );
+
+    // TODO(schwehr): If any of the pointers were set to local vars,
+    // do they need to be reset to a nullptr?
 }
diff --git a/port/cpl_quad_tree.h b/port/cpl_quad_tree.h
index c02831a..08a374a 100644
--- a/port/cpl_quad_tree.h
+++ b/port/cpl_quad_tree.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_quad_tree.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cpl_quad_tree.h 34931 2016-08-05 17:13:05Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implementation of quadtree building and searching functions.
@@ -50,14 +50,22 @@ CPL_C_START
 
 /* Types */
 
+/** Describe a rectangle */
 typedef struct {
-  double minx, miny, maxx, maxy;
+  double minx; /**< Minimum x */
+  double miny; /**< Minimum y */
+  double maxx; /**< Maximum x */
+  double maxy; /**< Maximum y */
 } CPLRectObj;
 
+/** Opaque type for a quad tree */
 typedef struct _CPLQuadTree CPLQuadTree;
 
+/** CPLQuadTreeGetBoundsFunc */
 typedef void         (*CPLQuadTreeGetBoundsFunc)(const void* hFeature, CPLRectObj* pBounds);
+/** CPLQuadTreeForeachFunc */
 typedef int          (*CPLQuadTreeForeachFunc)(void* pElt, void* pUserData);
+/** CPLQuadTreeDumpFeatureFunc */
 typedef void         (*CPLQuadTreeDumpFeatureFunc)(const void* hFeature, int nIndentLevel, void* pUserData);
 
 /* Functions */
diff --git a/port/cpl_recode.cpp b/port/cpl_recode.cpp
index 13f5abd..72bf709 100644
--- a/port/cpl_recode.cpp
+++ b/port/cpl_recode.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_recode.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_recode.cpp
  * Project:  CPL - Common Portability Library
@@ -24,21 +23,28 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_recode.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+#include <cstring>
+
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: cpl_recode.cpp 36880 2016-12-15 05:11:47Z goatbar $");
 
 #ifdef CPL_RECODE_ICONV
 extern void CPLClearRecodeIconvWarningFlags();
-extern char *CPLRecodeIconv( const char *, const char *, const char * ) CPL_RETURNS_NONNULL;
+extern char *CPLRecodeIconv( const char *, const char *, const char * )
+    CPL_RETURNS_NONNULL;
 extern char *CPLRecodeFromWCharIconv( const wchar_t *,
                                       const char *, const char * );
 extern wchar_t *CPLRecodeToWCharIconv( const char *,
                                        const char *, const char * );
-#endif /* CPL_RECODE_ICONV */
+#endif  // CPL_RECODE_ICONV
 
 extern void CPLClearRecodeStubWarningFlags();
-extern char *CPLRecodeStub( const char *, const char *, const char * ) CPL_RETURNS_NONNULL;
+extern char *CPLRecodeStub( const char *, const char *, const char * )
+    CPL_RETURNS_NONNULL;
 extern char *CPLRecodeFromWCharStub( const wchar_t *,
                                      const char *, const char * );
 extern wchar_t *CPLRecodeToWCharStub( const char *,
@@ -55,7 +61,8 @@ extern int CPLIsUTF8Stub( const char *, int );
  * The only guaranteed supported encodings are CPL_ENC_UTF8, CPL_ENC_ASCII
  * and CPL_ENC_ISO8859_1. Currently, the following conversions are supported :
  * <ul>
- *  <li>CPL_ENC_ASCII -> CPL_ENC_UTF8 or CPL_ENC_ISO8859_1 (no conversion in fact)</li>
+ *  <li>CPL_ENC_ASCII -> CPL_ENC_UTF8 or CPL_ENC_ISO8859_1 (no conversion in
+ *  fact)</li>
  *  <li>CPL_ENC_ISO8859_1 -> CPL_ENC_UTF8</li>
  *  <li>CPL_ENC_UTF8 -> CPL_ENC_ISO8859_1</li>
  * </ul>
@@ -79,10 +86,10 @@ char CPL_DLL *CPLRecode( const char *pszSource,
 /* -------------------------------------------------------------------- */
 /*      Handle a few common short cuts.                                 */
 /* -------------------------------------------------------------------- */
-    if ( EQUAL(pszSrcEncoding, pszDstEncoding) )
+    if( EQUAL(pszSrcEncoding, pszDstEncoding) )
         return CPLStrdup(pszSource);
 
-    if ( EQUAL(pszSrcEncoding, CPL_ENC_ASCII)
+    if( EQUAL(pszSrcEncoding, CPL_ENC_ASCII)
         && ( EQUAL(pszDstEncoding, CPL_ENC_UTF8)
              || EQUAL(pszDstEncoding, CPL_ENC_ISO8859_1) ) )
         return CPLStrdup(pszSource);
@@ -95,10 +102,10 @@ char CPL_DLL *CPLRecode( const char *pszSource,
 /*      iconv() route. Use a stub for these two ones and iconv()        */
 /*      everything else.                                                */
 /* -------------------------------------------------------------------- */
-    if ( ( EQUAL(pszSrcEncoding, CPL_ENC_ISO8859_1)
-           && EQUAL(pszDstEncoding, CPL_ENC_UTF8) )
-         || ( EQUAL(pszSrcEncoding, CPL_ENC_UTF8)
-              && EQUAL(pszDstEncoding, CPL_ENC_ISO8859_1) ) )
+    if( ( EQUAL(pszSrcEncoding, CPL_ENC_ISO8859_1)
+          && EQUAL(pszDstEncoding, CPL_ENC_UTF8) )
+        || ( EQUAL(pszSrcEncoding, CPL_ENC_UTF8)
+             && EQUAL(pszDstEncoding, CPL_ENC_ISO8859_1) ) )
     {
         return CPLRecodeStub( pszSource, pszSrcEncoding, pszDstEncoding );
     }
@@ -106,9 +113,9 @@ char CPL_DLL *CPLRecode( const char *pszSource,
     {
         return CPLRecodeIconv( pszSource, pszSrcEncoding, pszDstEncoding );
     }
-#else /* CPL_RECODE_STUB */
+#else  // CPL_RECODE_STUB
     return CPLRecodeStub( pszSource, pszSrcEncoding, pszDstEncoding );
-#endif /* CPL_RECODE_ICONV */
+#endif  // CPL_RECODE_ICONV
 }
 
 /************************************************************************/
@@ -150,7 +157,8 @@ char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource,
 /*      to CPL_ENC_UTF8, CPL_ENC_ISO8859_1 and CPL_ENC_ASCII are well   */
 /*      handled by the stub implementation.                             */
 /* -------------------------------------------------------------------- */
-    if ( (EQUAL(pszSrcEncoding, CPL_ENC_UCS2) || EQUAL(pszSrcEncoding, "WCHAR_T"))
+    if( (EQUAL(pszSrcEncoding, CPL_ENC_UCS2) ||
+         EQUAL(pszSrcEncoding, "WCHAR_T"))
          && ( EQUAL(pszDstEncoding, CPL_ENC_UTF8)
               || EQUAL(pszDstEncoding, CPL_ENC_ASCII)
               || EQUAL(pszDstEncoding, CPL_ENC_ISO8859_1) ) )
@@ -162,10 +170,10 @@ char CPL_DLL *CPLRecodeFromWChar( const wchar_t *pwszSource,
     return CPLRecodeFromWCharIconv( pwszSource,
                                     pszSrcEncoding, pszDstEncoding );
 
-#else /* CPL_RECODE_STUB */
+#else  // CPL_RECODE_STUB
     return CPLRecodeFromWCharStub( pwszSource,
                                    pszSrcEncoding, pszDstEncoding );
-#endif /* CPL_RECODE_ICONV */
+#endif  // CPL_RECODE_ICONV
 }
 
 /************************************************************************/
@@ -208,11 +216,11 @@ wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
 /*      from CPL_ENC_UTF8, CPL_ENC_ISO8859_1 and CPL_ENC_ASCII are well */
 /*      handled by the stub implementation.                             */
 /* -------------------------------------------------------------------- */
-    if ( (EQUAL(pszDstEncoding, CPL_ENC_UCS2)
-          || EQUAL(pszDstEncoding, "WCHAR_T"))
-         && ( EQUAL(pszSrcEncoding, CPL_ENC_UTF8)
-              || EQUAL(pszSrcEncoding, CPL_ENC_ASCII)
-              || EQUAL(pszSrcEncoding, CPL_ENC_ISO8859_1) ) )
+    if( (EQUAL(pszDstEncoding, CPL_ENC_UCS2)
+         || EQUAL(pszDstEncoding, "WCHAR_T"))
+        && ( EQUAL(pszSrcEncoding, CPL_ENC_UTF8)
+             || EQUAL(pszSrcEncoding, CPL_ENC_ASCII)
+             || EQUAL(pszSrcEncoding, CPL_ENC_ISO8859_1) ) )
     {
         return CPLRecodeToWCharStub( pszSource,
                                      pszSrcEncoding, pszDstEncoding );
@@ -221,9 +229,9 @@ wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
     return CPLRecodeToWCharIconv( pszSource,
                                   pszSrcEncoding, pszDstEncoding );
 
-#else /* CPL_RECODE_STUB */
+#else  // CPL_RECODE_STUB
     return CPLRecodeToWCharStub( pszSource, pszSrcEncoding, pszDstEncoding );
-#endif /* CPL_RECODE_ICONV */
+#endif  // CPL_RECODE_ICONV
 }
 
 /************************************************************************/
@@ -240,7 +248,7 @@ wchar_t CPL_DLL *CPLRecodeToWChar( const char *pszSource,
  *
  * @since GDAL 1.7.0
  */
-int CPLIsUTF8(const char* pabyData, int nLen)
+int CPLIsUTF8( const char* pabyData, int nLen )
 {
     return CPLIsUTF8Stub( pabyData, nLen );
 }
@@ -257,17 +265,18 @@ int CPLIsUTF8(const char* pabyData, int nLen)
  * @param pabyData input string to test
  * @param nLen length of the input string, or -1 if the function must compute
  *             the string length. In which case it must be null terminated.
+
  * @param chReplacementChar character which will be used when the input stream
- *                          contains a non ASCII character. Must be valid ASCII !
+ *                          contains a non ASCII character. Must be valid ASCII!
  *
  * @return a new string that must be freed with CPLFree().
  *
  * @since GDAL 1.7.0
  */
 char CPL_DLL *CPLForceToASCII( const char* pabyData, int nLen,
-                               char chReplacementChar)
+                               char chReplacementChar )
 {
-    if (nLen < 0)
+    if( nLen < 0 )
         nLen = static_cast<int>(strlen(pabyData));
     char* pszOutputString = static_cast<char *>( CPLMalloc(nLen + 1) );
     for( int i=0;i < nLen; i++ )
@@ -309,15 +318,15 @@ char CPL_DLL *CPLForceToASCII( const char* pabyData, int nLen,
 int CPLEncodingCharSize( const char *pszEncoding )
 
 {
-    if( EQUAL(pszEncoding,CPL_ENC_UTF8) )
+    if( EQUAL(pszEncoding, CPL_ENC_UTF8) )
         return 1;
-    else if( EQUAL(pszEncoding,CPL_ENC_UTF16) )
+    else if( EQUAL(pszEncoding, CPL_ENC_UTF16) )
         return 2;
-    else if( EQUAL(pszEncoding,CPL_ENC_UCS2) )
+    else if( EQUAL(pszEncoding, CPL_ENC_UCS2) )
         return 2;
-    else if( EQUAL(pszEncoding,CPL_ENC_UCS4) )
+    else if( EQUAL(pszEncoding, CPL_ENC_UCS4) )
         return 4;
-    else if( EQUAL(pszEncoding,CPL_ENC_ASCII) )
+    else if( EQUAL(pszEncoding, CPL_ENC_ASCII) )
         return 1;
     else if( STARTS_WITH_CI(pszEncoding, "ISO-8859-") )
         return 1;
@@ -337,7 +346,6 @@ void CPLClearRecodeWarningFlags()
     CPLClearRecodeStubWarningFlags();
 }
 
-
 /************************************************************************/
 /*                         CPLStrlenUTF8()                              */
 /************************************************************************/
@@ -352,7 +360,8 @@ void CPLClearRecodeWarningFlags()
  * @return the number of UTF-8 characters.
  */
 
-int CPLStrlenUTF8(const char *pszUTF8Str) {
+int CPLStrlenUTF8( const char *pszUTF8Str )
+{
     int nCharacterCount = 0;
     for( int i = 0; pszUTF8Str[i] != '\0'; ++i )
     {
diff --git a/port/cpl_recode_iconv.cpp b/port/cpl_recode_iconv.cpp
index bd602f0..303df4c 100644
--- a/port/cpl_recode_iconv.cpp
+++ b/port/cpl_recode_iconv.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_recode_iconv.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_recode_iconv.cpp
  * Project:  CPL - Common Portability Library
@@ -26,7 +25,9 @@
 
 #include "cpl_port.h"
 
-CPL_CVSID("$Id: cpl_recode_iconv.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+#include <algorithm>
+
+CPL_CVSID("$Id: cpl_recode_iconv.cpp 36880 2016-12-15 05:11:47Z goatbar $");
 
 #ifdef CPL_RECODE_ICONV
 
@@ -37,7 +38,7 @@ CPL_CVSID("$Id: cpl_recode_iconv.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 #define ICONV_CPP_CONST ICONV_CONST
 #endif
 
-#define CPL_RECODE_DSTBUF_SIZE 32768
+static const size_t CPL_RECODE_DSTBUF_SIZE = 32768;
 
  /* used by cpl_recode.cpp */
 extern void CPLClearRecodeIconvWarningFlags();
@@ -86,7 +87,7 @@ char *CPLRecodeIconv( const char *pszSource,
 
     sConv = iconv_open( pszDstEncoding, pszSrcEncoding );
 
-    if ( sConv == (iconv_t)-1 )
+    if( sConv == (iconv_t)-1 )
     {
         CPLError( CE_Warning, CPLE_AppDefined,
                   "Recode from %s to %s failed with the error: \"%s\".",
@@ -102,42 +103,45 @@ char *CPLRecodeIconv( const char *pszSource,
 /*      as a const char**. Handle it with the ICONV_CPP_CONST macro here.   */
 /* -------------------------------------------------------------------- */
     ICONV_CPP_CONST char *pszSrcBuf = (ICONV_CPP_CONST char *)pszSource;
-    size_t  nSrcLen = strlen( pszSource );
-    size_t  nDstCurLen = MAX(CPL_RECODE_DSTBUF_SIZE, nSrcLen + 1);
-    size_t  nDstLen = nDstCurLen;
-    char    *pszDestination = (char *)CPLCalloc( nDstCurLen, sizeof(char) );
-    char    *pszDstBuf = pszDestination;
-
-    while ( nSrcLen > 0 )
+    size_t nSrcLen = strlen( pszSource );
+    size_t nDstCurLen = std::max(CPL_RECODE_DSTBUF_SIZE, nSrcLen + 1);
+    size_t nDstLen = nDstCurLen;
+    char *pszDestination =
+        static_cast<char *>(CPLCalloc(nDstCurLen, sizeof(char)));
+    char *pszDstBuf = pszDestination;
+
+    while( nSrcLen > 0 )
     {
-        size_t  nConverted =
+        size_t nConverted =
             iconv( sConv, &pszSrcBuf, &nSrcLen, &pszDstBuf, &nDstLen );
 
-        if ( nConverted == (size_t)-1 )
+        if( nConverted == static_cast<size_t>(-1) )
         {
-            if ( errno == EILSEQ )
+            if( errno == EILSEQ )
             {
                 // Skip the invalid sequence in the input string.
-                if (!bHaveWarned1)
+                if( !bHaveWarned1 )
                 {
                     bHaveWarned1 = true;
                     CPLError(CE_Warning, CPLE_AppDefined,
-                            "One or several characters couldn't be converted correctly from %s to %s.\n"
-                            "This warning will not be emitted anymore",
+                             "One or several characters couldn't be converted "
+                             "correctly from %s to %s.  "
+                             "This warning will not be emitted anymore",
                              pszSrcEncoding, pszDstEncoding);
                 }
-                nSrcLen--, pszSrcBuf++;
+                nSrcLen--;
+                pszSrcBuf++;
                 continue;
             }
 
-            else if ( errno == E2BIG )
+            else if( errno == E2BIG )
             {
                 // We are running out of the output buffer.
                 // Dynamically increase the buffer size.
                 size_t nTmp = nDstCurLen;
                 nDstCurLen *= 2;
                 pszDestination =
-                    (char *)CPLRealloc( pszDestination, nDstCurLen );
+                    static_cast<char *>(CPLRealloc(pszDestination, nDstCurLen));
                 pszDstBuf = pszDestination + nTmp - nDstLen;
                 nDstLen += nDstCurLen - nTmp;
                 continue;
@@ -186,9 +190,9 @@ char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
 /* -------------------------------------------------------------------- */
 /*      What is the source length.                                      */
 /* -------------------------------------------------------------------- */
-    size_t  nSrcLen = 0;
+    size_t nSrcLen = 0;
 
-    while ( pwszSource[nSrcLen] != 0 )
+    while( pwszSource[nSrcLen] != 0 )
         nSrcLen++;
 
 /* -------------------------------------------------------------------- */
@@ -198,7 +202,7 @@ char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
 /*      source is UTF16 then we need to pack down into 2 byte           */
 /*      characters before passing to iconv().                           */
 /* -------------------------------------------------------------------- */
-    int nTargetCharWidth = CPLEncodingCharSize( pszSrcEncoding );
+    const int nTargetCharWidth = CPLEncodingCharSize( pszSrcEncoding );
 
     if( nTargetCharWidth < 1 )
     {
@@ -209,14 +213,16 @@ char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
         return CPLStrdup("");
     }
 
-    GByte *pszIconvSrcBuf = (GByte*) CPLCalloc((nSrcLen+1),nTargetCharWidth);
+    GByte *pszIconvSrcBuf =
+        static_cast<GByte *>(CPLCalloc((nSrcLen + 1), nTargetCharWidth));
 
     for( unsigned int iSrc = 0; iSrc <= nSrcLen; iSrc++ )
     {
         if( nTargetCharWidth == 1 )
-            pszIconvSrcBuf[iSrc] = (GByte) pwszSource[iSrc];
+            pszIconvSrcBuf[iSrc] = static_cast<GByte>(pwszSource[iSrc]);
         else if( nTargetCharWidth == 2 )
-            ((short *)pszIconvSrcBuf)[iSrc] = (short) pwszSource[iSrc];
+            ((short *)pszIconvSrcBuf)[iSrc] =
+                static_cast<short>(pwszSource[iSrc]);
         else if( nTargetCharWidth == 4 )
             ((GInt32 *)pszIconvSrcBuf)[iSrc] = pwszSource[iSrc];
     }
@@ -228,7 +234,7 @@ char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
 
     sConv = iconv_open( pszDstEncoding, pszSrcEncoding );
 
-    if ( sConv == (iconv_t)-1 )
+    if( sConv == (iconv_t)-1 )
     {
         CPLFree( pszIconvSrcBuf );
         CPLError( CE_Warning, CPLE_AppDefined,
@@ -252,42 +258,44 @@ char *CPLRecodeFromWCharIconv( const wchar_t *pwszSource,
 /* -------------------------------------------------------------------- */
 /*      Allocate destination buffer.                                    */
 /* -------------------------------------------------------------------- */
-    size_t  nDstCurLen = MAX(CPL_RECODE_DSTBUF_SIZE, nSrcLen + 1);
-    size_t  nDstLen = nDstCurLen;
-    char    *pszDestination = (char *)CPLCalloc( nDstCurLen, sizeof(char) );
-    char    *pszDstBuf = pszDestination;
+    size_t nDstCurLen = std::max(CPL_RECODE_DSTBUF_SIZE, nSrcLen + 1);
+    size_t nDstLen = nDstCurLen;
+    char *pszDestination =
+        static_cast<char *>(CPLCalloc(nDstCurLen, sizeof(char)));
+    char *pszDstBuf = pszDestination;
 
-    while ( nSrcLen > 0 )
+    while( nSrcLen > 0 )
     {
-        size_t  nConverted =
+        const size_t nConverted =
             iconv( sConv, &pszSrcBuf, &nSrcLen, &pszDstBuf, &nDstLen );
 
-        if ( nConverted == (size_t)-1 )
+        if( nConverted == static_cast<size_t>(-1) )
         {
-            if ( errno == EILSEQ )
+            if( errno == EILSEQ )
             {
                 // Skip the invalid sequence in the input string.
                 nSrcLen--;
                 pszSrcBuf += sizeof(wchar_t);
-                if (!bHaveWarned2)
+                if( !bHaveWarned2 )
                 {
                     bHaveWarned2 = true;
                     CPLError(CE_Warning, CPLE_AppDefined,
-                            "One or several characters couldn't be converted correctly from %s to %s.\n"
-                            "This warning will not be emitted anymore",
+                             "One or several characters couldn't be converted "
+                             "correctly from %s to %s.  "
+                             "This warning will not be emitted anymore",
                              pszSrcEncoding, pszDstEncoding);
                 }
                 continue;
             }
 
-            else if ( errno == E2BIG )
+            else if( errno == E2BIG )
             {
                 // We are running out of the output buffer.
                 // Dynamically increase the buffer size.
                 size_t nTmp = nDstCurLen;
                 nDstCurLen *= 2;
                 pszDestination =
-                    (char *)CPLRealloc( pszDestination, nDstCurLen );
+                    static_cast<char *>(CPLRealloc(pszDestination, nDstCurLen));
                 pszDstBuf = pszDestination + nTmp - nDstLen;
                 nDstLen += nDstCurLen - nTmp;
                 continue;
diff --git a/port/cpl_recode_stub.cpp b/port/cpl_recode_stub.cpp
index 1d4ce3a..33eeb09 100644
--- a/port/cpl_recode_stub.cpp
+++ b/port/cpl_recode_stub.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_recode_stub.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_recode_stub.cpp
  * Project:  CPL - Common Portability Library
@@ -30,9 +29,15 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  **********************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_recode_stub.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+#include <cstring>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+
+CPL_CVSID("$Id: cpl_recode_stub.cpp 37987 2017-04-14 07:42:50Z rouault $");
 
 #ifdef CPL_RECODE_STUB
 
@@ -52,20 +57,15 @@ static int utf8test(const char* src, unsigned srclen);
 #include <windows.h>
 #include <winnls.h>
 
-static char* CPLWin32Recode( const char* src,
-                             unsigned src_code_page, unsigned dst_code_page ) CPL_RETURNS_NONNULL;
+static char* CPLWin32Recode( const char* src, unsigned src_code_page,
+                             unsigned dst_code_page )
+    CPL_RETURNS_NONNULL;
 #endif
 
-#ifdef FUTURE_NEEDS
-static const char* utf8fwd(const char* p, const char* start, const char* end);
-static const char* utf8back(const char* p, const char* start, const char*end);
-static int utf8encode(unsigned ucs, char* buf);
-static int utf8bytes(unsigned ucs);
-#endif /* def FUTURE_NEEDS */
-
 /* used by cpl_recode.cpp */
 extern void CPLClearRecodeStubWarningFlags();
-extern char *CPLRecodeStub( const char *, const char *, const char * ) CPL_RETURNS_NONNULL;
+extern char *CPLRecodeStub( const char *, const char *, const char * )
+    CPL_RETURNS_NONNULL;
 extern char *CPLRecodeFromWCharStub( const wchar_t *,
                                      const char *, const char * );
 extern wchar_t *CPLRecodeToWCharStub( const char *,
@@ -74,7 +74,7 @@ extern int CPLIsUTF8Stub( const char *, int );
 
 /************************************************************************/
 /* ==================================================================== */
-/*	Stub Implementation not depending on iconv() or WIN32 API.	*/
+/*      Stub Implementation not depending on iconv() or WIN32 API.      */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -109,7 +109,8 @@ void CPLClearRecodeStubWarningFlags()
  * The only guaranteed supported encodings are CPL_ENC_UTF8, CPL_ENC_ASCII
  * and CPL_ENC_ISO8859_1. Currently, the following conversions are supported :
  * <ul>
- *  <li>CPL_ENC_ASCII -> CPL_ENC_UTF8 or CPL_ENC_ISO8859_1 (no conversion in fact)</li>
+ *  <li>CPL_ENC_ASCII -> CPL_ENC_UTF8 or CPL_ENC_ISO8859_1 (no conversion in
+ *  fact)</li>
  *  <li>CPL_ENC_ISO8859_1 -> CPL_ENC_UTF8</li>
  *  <li>CPL_ENC_UTF8 -> CPL_ENC_ISO8859_1</li>
  * </ul>
@@ -143,13 +144,13 @@ char *CPLRecodeStub( const char *pszSource,
 /* -------------------------------------------------------------------- */
 /*      ISO8859 to UTF8                                                 */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszSrcEncoding,CPL_ENC_ISO8859_1) == 0
-        && strcmp(pszDstEncoding,CPL_ENC_UTF8) == 0 )
+    if( strcmp(pszSrcEncoding, CPL_ENC_ISO8859_1) == 0
+        && strcmp(pszDstEncoding, CPL_ENC_UTF8) == 0 )
     {
-        int nCharCount = static_cast<int>(strlen(pszSource));
-        char *pszResult = (char *) CPLCalloc(1,nCharCount*2+1);
+        const int nCharCount = static_cast<int>(strlen(pszSource));
+        char *pszResult = static_cast<char *>(CPLCalloc(1, nCharCount * 2 + 1));
 
-        utf8froma( pszResult, nCharCount*2+1, pszSource, nCharCount );
+        utf8froma(pszResult, nCharCount * 2 + 1, pszSource, nCharCount);
 
         return pszResult;
     }
@@ -157,13 +158,13 @@ char *CPLRecodeStub( const char *pszSource,
 /* -------------------------------------------------------------------- */
 /*      UTF8 to ISO8859                                                 */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) == 0
-        && strcmp(pszDstEncoding,CPL_ENC_ISO8859_1) == 0 )
+    if( strcmp(pszSrcEncoding, CPL_ENC_UTF8) == 0
+        && strcmp(pszDstEncoding, CPL_ENC_ISO8859_1) == 0 )
     {
         int nCharCount = static_cast<int>(strlen(pszSource));
-        char *pszResult = (char *) CPLCalloc(1,nCharCount+1);
+        char *pszResult = static_cast<char *>(CPLCalloc(1, nCharCount + 1));
 
-        utf8toa( pszSource, nCharCount, pszResult, nCharCount+1 );
+        utf8toa(pszSource, nCharCount, pszResult, nCharCount + 1);
 
         return pszResult;
     }
@@ -173,7 +174,7 @@ char *CPLRecodeStub( const char *pszSource,
 /*      CPXXX to UTF8                                                   */
 /* ---------------------------------------------------------------------*/
     if( STARTS_WITH(pszSrcEncoding, "CP")
-        && strcmp(pszDstEncoding,CPL_ENC_UTF8) == 0 )
+        && strcmp(pszDstEncoding, CPL_ENC_UTF8) == 0 )
     {
         int nCode = atoi( pszSrcEncoding + 2 );
         if( nCode > 0 ) {
@@ -186,7 +187,7 @@ char *CPLRecodeStub( const char *pszSource,
 /* ---------------------------------------------------------------------*/
 /*      UTF8 to CPXXX                                                   */
 /* ---------------------------------------------------------------------*/
-    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) == 0
+    if( strcmp(pszSrcEncoding, CPL_ENC_UTF8) == 0
         && STARTS_WITH(pszDstEncoding, "CP") )
     {
          int nCode = atoi( pszDstEncoding + 2 );
@@ -200,15 +201,15 @@ char *CPLRecodeStub( const char *pszSource,
 /*      Anything else to UTF-8 is treated as ISO8859-1 to UTF-8 with    */
 /*      a one-time warning.                                             */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszDstEncoding,CPL_ENC_UTF8) == 0 )
+    if( strcmp(pszDstEncoding, CPL_ENC_UTF8) == 0 )
     {
         int nCharCount = static_cast<int>(strlen(pszSource));
-        char *pszResult = (char *) CPLCalloc(1,nCharCount*2+1);
+        char *pszResult = static_cast<char *>(CPLCalloc(1, nCharCount * 2 + 1));
 
-        if( EQUAL( pszSrcEncoding, "CP437") ) /* For ZIP file handling */
+        if( EQUAL( pszSrcEncoding, "CP437") ) // For ZIP file handling.
         {
             bool bIsAllPrintableASCII = true;
-            for(int i=0;i<nCharCount;i++)
+            for( int i = 0; i <nCharCount; i++ )
             {
                 if( pszSource[i] < 32 || pszSource[i] > 126 )
                 {
@@ -228,7 +229,8 @@ char *CPLRecodeStub( const char *pszSource,
         {
             bHaveWarned1 = true;
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Recode from %s to UTF-8 not supported, treated as ISO8859-1 to UTF-8.",
+                      "Recode from %s to UTF-8 not supported, "
+                      "treated as ISO8859-1 to UTF-8.",
                       pszSrcEncoding );
         }
 
@@ -241,21 +243,22 @@ char *CPLRecodeStub( const char *pszSource,
 /*      UTF-8 to anything else is treated as UTF-8 to ISO-8859-1        */
 /*      with a warning.                                                 */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) == 0
-        && strcmp(pszDstEncoding,CPL_ENC_ISO8859_1) == 0 )
+    if( strcmp(pszSrcEncoding, CPL_ENC_UTF8) == 0
+        && strcmp(pszDstEncoding, CPL_ENC_ISO8859_1) == 0 )
     {
         int nCharCount = static_cast<int>(strlen(pszSource));
-        char *pszResult = (char *) CPLCalloc(1,nCharCount+1);
+        char *pszResult = static_cast<char *>(CPLCalloc(1, nCharCount + 1));
 
         if( !bHaveWarned2 )
         {
             bHaveWarned2 = true;
             CPLError( CE_Warning, CPLE_AppDefined,
-                      "Recode from UTF-8 to %s not supported, treated as UTF-8 to ISO8859-1.",
+                      "Recode from UTF-8 to %s not supported, "
+                      "treated as UTF-8 to ISO8859-1.",
                       pszDstEncoding );
         }
 
-        utf8toa( pszSource, nCharCount, pszResult, nCharCount+1 );
+        utf8toa(pszSource, nCharCount, pszResult, nCharCount + 1);
 
         return pszResult;
     }
@@ -311,14 +314,14 @@ char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
 /*      We try to avoid changes of character set.  We are just          */
 /*      providing for unicode to unicode.                               */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszSrcEncoding,"WCHAR_T") != 0 &&
-        strcmp(pszSrcEncoding,CPL_ENC_UTF8) != 0
-        && strcmp(pszSrcEncoding,CPL_ENC_UTF16) != 0
-        && strcmp(pszSrcEncoding,CPL_ENC_UCS2) != 0
-        && strcmp(pszSrcEncoding,CPL_ENC_UCS4) != 0 )
+    if( strcmp(pszSrcEncoding, "WCHAR_T") != 0 &&
+        strcmp(pszSrcEncoding, CPL_ENC_UTF8) != 0
+        && strcmp(pszSrcEncoding, CPL_ENC_UTF16) != 0
+        && strcmp(pszSrcEncoding, CPL_ENC_UCS2) != 0
+        && strcmp(pszSrcEncoding, CPL_ENC_UCS4) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Stub recoding implementation does not support\n"
+                  "Stub recoding implementation does not support "
                   "CPLRecodeFromWCharStub(...,%s,%s)",
                   pszSrcEncoding, pszDstEncoding );
         return NULL;
@@ -335,13 +338,11 @@ char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
 /* -------------------------------------------------------------------- */
 /*      Allocate destination buffer plenty big.                         */
 /* -------------------------------------------------------------------- */
-    char *pszResult;
-    int nDstBufSize, nDstLen;
-
-    nDstBufSize = nSrcLen * 4 + 1;
-    pszResult = (char *) CPLMalloc(nDstBufSize); // nearly worst case.
+    const int nDstBufSize = nSrcLen * 4 + 1;
+    // Nearly worst case.
+    char *pszResult = static_cast<char *>(CPLMalloc(nDstBufSize));
 
-    if (nSrcLen == 0)
+    if( nSrcLen == 0 )
     {
         pszResult[0] = '\0';
         return pszResult;
@@ -350,7 +351,8 @@ char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
 /* -------------------------------------------------------------------- */
 /*      Convert, and confirm we had enough space.                       */
 /* -------------------------------------------------------------------- */
-    nDstLen = utf8fromwc( pszResult, nDstBufSize, pwszSource, nSrcLen );
+    const int nDstLen =
+        utf8fromwc( pszResult, nDstBufSize, pwszSource, nSrcLen );
     if( nDstLen >= nDstBufSize )
     {
         CPLAssert( false ); // too small!
@@ -360,7 +362,7 @@ char *CPLRecodeFromWCharStub( const wchar_t *pwszSource,
 /* -------------------------------------------------------------------- */
 /*      If something other than UTF-8 was requested, recode now.        */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszDstEncoding,CPL_ENC_UTF8) == 0 )
+    if( strcmp(pszDstEncoding, CPL_ENC_UTF8) == 0 )
         return pszResult;
 
     char *pszFinalResult =
@@ -405,12 +407,13 @@ wchar_t *CPLRecodeToWCharStub( const char *pszSource,
                                const char *pszDstEncoding )
 
 {
-    char *pszUTF8Source = (char *) pszSource;
+    char *pszUTF8Source = const_cast<char *>(pszSource);
 
-    if( strcmp(pszSrcEncoding,CPL_ENC_UTF8) != 0
-        && strcmp(pszSrcEncoding,CPL_ENC_ASCII) != 0 )
+    if( strcmp(pszSrcEncoding, CPL_ENC_UTF8) != 0
+        && strcmp(pszSrcEncoding, CPL_ENC_ASCII) != 0 )
     {
-        pszUTF8Source = CPLRecodeStub( pszSource, pszSrcEncoding, CPL_ENC_UTF8 );
+        pszUTF8Source =
+            CPLRecodeStub(pszSource, pszSrcEncoding, CPL_ENC_UTF8);
         if( pszUTF8Source == NULL )
             return NULL;
     }
@@ -419,13 +422,13 @@ wchar_t *CPLRecodeToWCharStub( const char *pszSource,
 /*      We try to avoid changes of character set.  We are just          */
 /*      providing for unicode to unicode.                               */
 /* -------------------------------------------------------------------- */
-    if( strcmp(pszDstEncoding,"WCHAR_T") != 0
-        && strcmp(pszDstEncoding,CPL_ENC_UCS2) != 0
-        && strcmp(pszDstEncoding,CPL_ENC_UCS4) != 0
-        && strcmp(pszDstEncoding,CPL_ENC_UTF16) != 0 )
+    if( strcmp(pszDstEncoding, "WCHAR_T") != 0
+        && strcmp(pszDstEncoding, CPL_ENC_UCS2) != 0
+        && strcmp(pszDstEncoding, CPL_ENC_UCS4) != 0
+        && strcmp(pszDstEncoding, CPL_ENC_UTF16) != 0 )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Stub recoding implementation does not support\n"
+                  "Stub recoding implementation does not support "
                   "CPLRecodeToWCharStub(...,%s,%s)",
                   pszSrcEncoding, pszDstEncoding );
         if( pszUTF8Source != pszSource )
@@ -437,7 +440,8 @@ wchar_t *CPLRecodeToWCharStub( const char *pszSource,
 /*      Do the UTF-8 to UCS-2 recoding.                                 */
 /* -------------------------------------------------------------------- */
     int nSrcLen = static_cast<int>(strlen(pszUTF8Source));
-    wchar_t *pwszResult = (wchar_t *) CPLCalloc(sizeof(wchar_t),nSrcLen+1);
+    wchar_t *pwszResult =
+        static_cast<wchar_t *>(CPLCalloc(sizeof(wchar_t), nSrcLen + 1));
 
     utf8towc( pszUTF8Source, nSrcLen, pwszResult, nSrcLen+1 );
 
@@ -447,7 +451,6 @@ wchar_t *CPLRecodeToWCharStub( const char *pszSource,
     return pwszResult;
 }
 
-
 /************************************************************************/
 /*                                 CPLIsUTF8()                          */
 /************************************************************************/
@@ -464,14 +467,14 @@ wchar_t *CPLRecodeToWCharStub( const char *pszSource,
  */
 int CPLIsUTF8Stub(const char* pabyData, int nLen)
 {
-    if (nLen < 0)
+    if( nLen < 0 )
         nLen = static_cast<int>(strlen(pabyData));
     return utf8test(pabyData, (unsigned)nLen) != 0;
 }
 
 /************************************************************************/
 /* ==================================================================== */
-/*	UTF.C code from FLTK with some modifications.                   */
+/*      UTF.C code from FLTK with some modifications.                   */
 /* ==================================================================== */
 /************************************************************************/
 
@@ -505,10 +508,10 @@ int CPLIsUTF8Stub(const char* pabyData, int nLen)
 // Codes 0x80..0x9f from the Microsoft CP1252 character set, translated
 // to Unicode:
 static const unsigned short cp1252[32] = {
-  0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
-  0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
-  0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
-  0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178
+    0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
+    0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
+    0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
+    0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178
 };
 #endif
 
@@ -535,10 +538,13 @@ static const unsigned short cp1252[32] = {
     unexpectedly 1 will work:
 
 \code
-    if (*p & 0x80) { // what should be a multibyte encoding
-      code = utf8decode(p,end,&len);
-      if (len<2) code = 0xFFFD; // Turn errors into REPLACEMENT CHARACTER
-    } else { // handle the 1-byte utf8 encoding:
+    if( *p & 0x80 )
+    {  // What should be a multibyte encoding.
+      code = utf8decode(p, end, &len);
+      if( len<2 ) code = 0xFFFD;  // Turn errors into REPLACEMENT CHARACTER.
+    }
+    else
+    {  // Handle the 1-byte utf8 encoding:
       code = *p;
       len = 1;
     }
@@ -551,67 +557,89 @@ static const unsigned short cp1252[32] = {
 static unsigned utf8decode(const char* p, const char* end, int* len)
 {
   unsigned char c = *(unsigned char*)p;
-  if (c < 0x80) {
+  if( c < 0x80 )
+  {
     *len = 1;
     return c;
 #if ERRORS_TO_CP1252
-  } else if (c < 0xa0) {
+  }
+  else if( c < 0xa0 )
+  {
     *len = 1;
     return cp1252[c-0x80];
 #endif
-  } else if (c < 0xc2) {
+  }
+  else if( c < 0xc2 )
+  {
     goto FAIL;
   }
-  if (p+1 >= end || (p[1]&0xc0) != 0x80) goto FAIL;
-  if (c < 0xe0) {
+  if( p+1 >= end || (p[1] & 0xc0) != 0x80 ) goto FAIL;
+  if( c < 0xe0 )
+  {
     *len = 2;
     return
       ((p[0] & 0x1f) << 6) +
       ((p[1] & 0x3f));
-  } else if (c == 0xe0) {
-    if (((unsigned char*)p)[1] < 0xa0) goto FAIL;
+  }
+  else if( c == 0xe0 )
+  {
+    if( ((unsigned char*)p)[1] < 0xa0 ) goto FAIL;
     goto UTF8_3;
 #if STRICT_RFC3629
-  } else if (c == 0xed) {
+  }
+  else if( c == 0xed )
+  {
     // RFC 3629 says surrogate chars are illegal.
-    if (((unsigned char*)p)[1] >= 0xa0) goto FAIL;
+    if( ((unsigned char*)p)[1] >= 0xa0 ) goto FAIL;
     goto UTF8_3;
-  } else if (c == 0xef) {
-    // 0xfffe and 0xffff are also illegal characters
-    if (((unsigned char*)p)[1]==0xbf &&
-	((unsigned char*)p)[2]>=0xbe) goto FAIL;
+  }
+  else if( c == 0xef )
+  {
+    // 0xfffe and 0xffff are also illegal characters.
+    if( ((unsigned char*)p)[1]==0xbf &&
+        ((unsigned char*)p)[2]>=0xbe ) goto FAIL;
     goto UTF8_3;
 #endif
-  } else if (c < 0xf0) {
+  }
+  else if( c < 0xf0 )
+  {
   UTF8_3:
-    if (p+2 >= end || (p[2]&0xc0) != 0x80) goto FAIL;
+    if( p+2 >= end || (p[2]&0xc0) != 0x80 ) goto FAIL;
     *len = 3;
     return
       ((p[0] & 0x0f) << 12) +
       ((p[1] & 0x3f) << 6) +
       ((p[2] & 0x3f));
-  } else if (c == 0xf0) {
-    if (((unsigned char*)p)[1] < 0x90) goto FAIL;
+  }
+  else if( c == 0xf0 )
+  {
+    if( ((unsigned char*)p)[1] < 0x90 ) goto FAIL;
     goto UTF8_4;
-  } else if (c < 0xf4) {
+  }
+  else if( c < 0xf4 )
+  {
   UTF8_4:
-    if (p+3 >= end || (p[2]&0xc0) != 0x80 || (p[3]&0xc0) != 0x80) goto FAIL;
+    if( p+3 >= end || (p[2]&0xc0) != 0x80 || (p[3]&0xc0) != 0x80 ) goto FAIL;
     *len = 4;
 #if STRICT_RFC3629
     // RFC 3629 says all codes ending in fffe or ffff are illegal:
-    if ((p[1]&0xf)==0xf &&
-	((unsigned char*)p)[2] == 0xbf &&
-	((unsigned char*)p)[3] >= 0xbe) goto FAIL;
+    if( (p[1]&0xf)==0xf &&
+        ((unsigned char*)p)[2] == 0xbf &&
+        ((unsigned char*)p)[3] >= 0xbe ) goto FAIL;
 #endif
     return
       ((p[0] & 0x07) << 18) +
       ((p[1] & 0x3f) << 12) +
       ((p[2] & 0x3f) << 6) +
       ((p[3] & 0x3f));
-  } else if (c == 0xf4) {
-    if (((unsigned char*)p)[1] > 0x8f) goto FAIL; // after 0x10ffff
+  }
+  else if( c == 0xf4 )
+  {
+    if( ((unsigned char*)p)[1] > 0x8f ) goto FAIL; // After 0x10ffff.
     goto UTF8_4;
-  } else {
+  }
+  else
+  {
   FAIL:
     *len = 1;
 #if ERRORS_TO_ISO8859_1
@@ -623,160 +651,6 @@ static unsigned utf8decode(const char* p, const char* end, int* len)
 }
 
 /************************************************************************/
-/*                              utf8fwd()                               */
-/************************************************************************/
-
-/*
-  Move \a p forward until it points to the start of a UTF-8
-  character. If it already points at the start of one then it
-  is returned unchanged. Any UTF-8 errors are treated as though each
-  byte of the error is an individual character.
-
-  \e start is the start of the string and is used to limit the
-  backwards search for the start of a utf8 character.
-
-  \e end is the end of the string and is assummed to be a break
-  between characters. It is assummed to be greater than p.
-
-  This function is for moving a pointer that was jumped to the
-  middle of a string, such as when doing a binary search for
-  a position. You should use either this or utf8back() depending
-  on which direction your algorithm can handle the pointer
-  moving. Do not use this to scan strings, use utf8decode()
-  instead.
-*/
-
-#ifdef FUTURE_NEEDS
-static const char* utf8fwd(const char* p, const char* start, const char* end)
-{
-  const char* a;
-  // if we are not pointing at a continuation character, we are done:
-  if ((*p&0xc0) != 0x80) return p;
-  // search backwards for a 0xc0 starting the character:
-  for (a = p-1; ; --a) {
-    if (a < start) return p;
-    if (!(a[0]&0x80)) return p;
-    if ((a[0]&0x40)) break;
-  }
-  int len = 0;
-  utf8decode(a,end,&len);
-  a += len;
-  if (a > p) return a;
-  return p;
-}
-#endif /* def FUTURE_NEEDS */
-
-/************************************************************************/
-/*                              utf8back()                              */
-/************************************************************************/
-
-/*
-  Move \a p backward until it points to the start of a UTF-8
-  character. If it already points at the start of one then it
-  is returned unchanged. Any UTF-8 errors are treated as though each
-  byte of the error is an individual character.
-
-  \e start is the start of the string and is used to limit the
-  backwards search for the start of a UTF-8 character.
-
-  \e end is the end of the string and is assummed to be a break
-  between characters. It is assummed to be greater than p.
-
-  If you wish to decrement a UTF-8 pointer, pass p-1 to this.
-*/
-
-#ifdef FUTURE_NEEDS
-static const char* utf8back(const char* p, const char* start, const char* end)
-{
-  const char* a;
-  // if we are not pointing at a continuation character, we are done:
-  if ((*p&0xc0) != 0x80) return p;
-  // search backwards for a 0xc0 starting the character:
-  for (a = p-1; ; --a) {
-    if (a < start) return p;
-    if (!(a[0]&0x80)) return p;
-    if ((a[0]&0x40)) break;
-  }
-  int len = 0;
-  utf8decode(a,end,&len);
-  if (a+len > p) return a;
-  return p;
-}
-#endif /* def FUTURE_NEEDS */
-
-/************************************************************************/
-/*                             utf8bytes()                              */
-/************************************************************************/
-
-/* Returns number of bytes that utf8encode() will use to encode the
-  character \a ucs. */
-#ifdef FUTURE_NEEDS
-static int utf8bytes(unsigned ucs) {
-  if (ucs < 0x000080U) {
-    return 1;
-  } else if (ucs < 0x000800U) {
-    return 2;
-  } else if (ucs < 0x010000U) {
-    return 3;
-  } else if (ucs < 0x10ffffU) {
-    return 4;
-  } else {
-    return 3; // length of the illegal character encoding
-  }
-}
-#endif /* def FUTURE_NEEDS */
-
-/************************************************************************/
-/*                             utf8encode()                             */
-/************************************************************************/
-
-/* Write the UTF-8 encoding of \e ucs into \e buf and return the
-    number of bytes written. Up to 4 bytes may be written. If you know
-    that \a ucs is less than 0x10000 then at most 3 bytes will be written.
-    If you wish to speed this up, remember that anything less than 0x80
-    is written as a single byte.
-
-    If ucs is greater than 0x10ffff this is an illegal character
-    according to RFC 3629. These are converted as though they are
-    0xFFFD (REPLACEMENT CHARACTER).
-
-    RFC 3629 also says many other values for \a ucs are illegal (in
-    the range 0xd800 to 0xdfff, or ending with 0xfffe or
-    0xffff). However I encode these as though they are legal, so that
-    utf8encode/utf8decode will be the identity for all codes between 0
-    and 0x10ffff.
-*/
-#ifdef FUTURE_NEEDS
-static int utf8encode(unsigned ucs, char* buf) {
-  if (ucs < 0x000080U) {
-    buf[0] = ucs;
-    return 1;
-  } else if (ucs < 0x000800U) {
-    buf[0] = 0xc0 | (ucs >> 6);
-    buf[1] = 0x80 | (ucs & 0x3F);
-    return 2;
-  } else if (ucs < 0x010000U) {
-    buf[0] = 0xe0 | (ucs >> 12);
-    buf[1] = 0x80 | ((ucs >> 6) & 0x3F);
-    buf[2] = 0x80 | (ucs & 0x3F);
-    return 3;
-  } else if (ucs < 0x0010ffffU) {
-    buf[0] = 0xf0 | (ucs >> 18);
-    buf[1] = 0x80 | ((ucs >> 12) & 0x3F);
-    buf[2] = 0x80 | ((ucs >> 6) & 0x3F);
-    buf[3] = 0x80 | (ucs & 0x3F);
-    return 4;
-  } else {
-    // encode 0xfffd:
-    buf[0] = 0xefU;
-    buf[1] = 0xbfU;
-    buf[2] = 0xbdU;
-    return 3;
-  }
-}
-#endif /* def FUTURE_NEEDS */
-
-/************************************************************************/
 /*                              utf8towc()                              */
 /************************************************************************/
 
@@ -817,20 +691,37 @@ static unsigned utf8towc(const char* src, unsigned srclen,
   const char* p = src;
   const char* e = src+srclen;
   unsigned count = 0;
-  if (dstlen) for (;;) {
-    if (p >= e) {dst[count] = 0; return count;}
-    if (!(*p & 0x80)) { // ascii
-      dst[count] = *p++;
-    } else {
+  if( dstlen ) while( true )
+  {
+    if( p >= e )
+    {
+        dst[count] = 0;
+        return count;
+    }
+    if( !(*p & 0x80) )
+    {
+        // ASCII
+        dst[count] = *p++;
+    }
+    else
+    {
       int len = 0;
-      unsigned ucs = utf8decode(p,e,&len);
+      unsigned ucs = utf8decode(p, e, &len);
       p += len;
 #ifdef _WIN32
-      if (ucs < 0x10000) {
+      if( ucs < 0x10000 )
+      {
           dst[count] = (wchar_t)ucs;
-      } else {
-	// make a surrogate pair:
-	if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;}
+      }
+      else
+      {
+        // Make a surrogate pair:
+        if( count+2 >= dstlen)
+        {
+            dst[count] = 0;
+            count += 2;
+            break;
+        }
         dst[count] = (wchar_t)((((ucs-0x10000u)>>10)&0x3ff) | 0xd800);
         dst[++count] = (wchar_t)((ucs&0x3ff) | 0xdc00);
       }
@@ -838,25 +729,34 @@ static unsigned utf8towc(const char* src, unsigned srclen,
       dst[count] = (wchar_t)ucs;
 #endif
     }
-    if (++count == dstlen) {dst[count-1] = 0; break;}
+    if( ++count == dstlen )
+    {
+        dst[count-1] = 0;
+        break;
+    }
   }
-  // we filled dst, measure the rest:
-  while (p < e) {
-    if (!(*p & 0x80)) p++;
-    else {
-#ifdef _WIN32
+  // We filled dst, measure the rest:
+  while( p < e )
+  {
+    if( !(*p & 0x80) )
+    {
+        p++;
+    }
+    else
+    {
       int len = 0;
-      unsigned ucs = utf8decode(p,e,&len);
+#ifdef _WIN32
+      const unsigned ucs = utf8decode(p, e, &len);
       p += len;
-      if (ucs >= 0x10000) ++count;
+      if( ucs >= 0x10000 ) ++count;
 #else
-      int len = 0;
-      utf8decode(p,e,&len);
+      utf8decode(p, e, &len);
       p += len;
 #endif
     }
     ++count;
   }
+
   return count;
 }
 
@@ -883,44 +783,66 @@ static unsigned utf8towc(const char* src, unsigned srclen,
     nothing is written and this call just measures the storage space
     needed.
 */
-static unsigned utf8toa(const char* src, unsigned srclen,
-                        char* dst, unsigned dstlen)
+static unsigned int utf8toa( const char* src, unsigned srclen,
+                             char* dst, unsigned dstlen )
 {
   const char* p = src;
   const char* e = src+srclen;
-  unsigned count = 0;
-  if (dstlen) for (;;) {
-    if (p >= e) {dst[count] = 0; return count;}
+  unsigned int count = 0;
+  if( dstlen ) while( true )
+  {
+    if( p >= e )
+    {
+        dst[count] = 0;
+        return count;
+    }
     unsigned char c = *(unsigned char*)p;
-    if (c < 0xC2) { // ascii or bad code
-      dst[count] = c;
-      p++;
-    } else {
-      int len = 0;
-      unsigned ucs = utf8decode(p,e,&len);
-      p += len;
-      if (ucs < 0x100) dst[count] = (char)ucs;
-      else
-      {
-          if (!bHaveWarned4)
-          {
-              bHaveWarned4 = true;
-              CPLError(CE_Warning, CPLE_AppDefined,
-                       "One or several characters couldn't be converted correctly from UTF-8 to ISO-8859-1.\n"
-                       "This warning will not be emitted anymore.");
-          }
-          dst[count] = '?';
+    if( c < 0xC2 )
+    {
+        // ASCII or bad code.
+        dst[count] = c;
+        p++;
+    }
+    else
+    {
+        int len = 0;
+        const unsigned int ucs = utf8decode(p, e, &len);
+        p += len;
+        if( ucs < 0x100 )
+        {
+            dst[count] = static_cast<char>(ucs);
+        }
+        else
+        {
+            if( !bHaveWarned4 )
+            {
+                bHaveWarned4 = true;
+                CPLError(CE_Warning, CPLE_AppDefined,
+                         "One or several characters couldn't be converted "
+                         "correctly from UTF-8 to ISO-8859-1.  "
+                         "This warning will not be emitted anymore.");
+            }
+            dst[count] = '?';
       }
     }
-    if (++count >= dstlen) {dst[count-1] = 0; break;}
+    if( ++count >= dstlen )
+    {
+        dst[count-1] = 0;
+        break;
+    }
   }
-  // we filled dst, measure the rest:
-  while (p < e) {
-    if (!(*p & 0x80)) p++;
-    else {
-      int len = 0;
-      utf8decode(p,e,&len);
-      p += len;
+  // We filled dst, measure the rest:
+  while( p < e )
+  {
+    if( !(*p & 0x80) )
+    {
+        p++;
+    }
+    else
+    {
+        int len = 0;
+        utf8decode(p, e, &len);
+        p += len;
     }
     ++count;
   }
@@ -957,75 +879,121 @@ static unsigned utf8toa(const char* src, unsigned srclen,
     and UTF-8 encoded (as 4 bytes). Mismatched halves of surrogate
     pairs are converted as though they are individual characters.
 */
-static unsigned utf8fromwc(char* dst, unsigned dstlen,
-                           const wchar_t* src, unsigned srclen) {
-  unsigned i = 0;
-  unsigned count = 0;
-  if (dstlen) for (;;) {
-    unsigned ucs;
-    if (i >= srclen) {dst[count] = 0; return count;}
-    ucs = src[i++];
-    if (ucs < 0x80U) {
-      dst[count++] = (char)ucs;
-      if (count >= dstlen) {dst[count-1] = 0; break;}
-    } else if (ucs < 0x800U) { // 2 bytes
-      if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;}
-      dst[count++] = 0xc0 | (char)(ucs >> 6);
-      dst[count++] = 0x80 | (char)(ucs & 0x3F);
+static unsigned int utf8fromwc( char* dst, unsigned dstlen,
+                                const wchar_t* src, unsigned srclen )
+{
+  unsigned int i = 0;
+  unsigned int count = 0;
+  if( dstlen ) while( true )
+  {
+      if( i >= srclen )
+      {
+          dst[count] = 0;
+          return count;
+      }
+      unsigned int ucs = src[i++];
+      if( ucs < 0x80U )
+      {
+          dst[count++] = static_cast<char>(ucs);
+          if( count >= dstlen )
+          {
+              dst[count-1] = 0;
+              break;
+          }
+      }
+      else if( ucs < 0x800U )
+      {
+          // 2 bytes.
+          if( count+2 >= dstlen )
+          {
+              dst[count] = 0;
+              count += 2;
+              break;
+          }
+          dst[count++] = 0xc0 | static_cast<char>(ucs >> 6);
+          dst[count++] = 0x80 | static_cast<char>(ucs & 0x3F);
 #ifdef _WIN32
-    } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen &&
-	       src[i] >= 0xdc00 && src[i] <= 0xdfff) {
-      // surrogate pair
-      unsigned ucs2 = src[i++];
-      ucs = 0x10000U + ((ucs&0x3ff)<<10) + (ucs2&0x3ff);
-      // all surrogate pairs turn into 4-byte utf8
+      }
+      else if( ucs >= 0xd800 && ucs <= 0xdbff && i < srclen &&
+               src[i] >= 0xdc00 && src[i] <= 0xdfff)
+      {
+          // Surrogate pair.
+          unsigned int ucs2 = src[i++];
+          ucs = 0x10000U + ((ucs & 0x3ff) << 10) + (ucs2 & 0x3ff);
+          // All surrogate pairs turn into 4-byte utf8.
 #else
-    } else if (ucs >= 0x10000) {
-      if (ucs > 0x10ffff) {
-	ucs = 0xfffd;
-	goto J1;
       }
+      else if( ucs >= 0x10000 )
+      {
+          if( ucs > 0x10ffff )
+          {
+              ucs = 0xfffd;
+              goto J1;
+          }
 #endif
-      if (count+4 >= dstlen) {dst[count] = 0; count += 4; break;}
-      dst[count++] = 0xf0 | (char)(ucs >> 18);
-      dst[count++] = 0x80 | (char)((ucs >> 12) & 0x3F);
-      dst[count++] = 0x80 | (char)((ucs >> 6) & 0x3F);
-      dst[count++] = 0x80 | (char)(ucs & 0x3F);
-    } else {
+          if( count+4 >= dstlen )
+          {
+              dst[count] = 0;
+              count += 4;
+              break;
+          }
+          dst[count++] = 0xf0 | static_cast<char>(ucs >> 18);
+          dst[count++] = 0x80 | static_cast<char>((ucs >> 12) & 0x3F);
+          dst[count++] = 0x80 | static_cast<char>((ucs >> 6) & 0x3F);
+          dst[count++] = 0x80 | static_cast<char>(ucs & 0x3F);
+      }
+      else
+      {
 #ifndef _WIN32
     J1:
 #endif
-      // all others are 3 bytes:
-      if (count+3 >= dstlen) {dst[count] = 0; count += 3; break;}
-      dst[count++] = 0xe0 | (char)(ucs >> 12);
-      dst[count++] = 0x80 | (char)((ucs >> 6) & 0x3F);
-      dst[count++] = 0x80 | (char)(ucs & 0x3F);
-    }
+      // All others are 3 bytes:
+          if( count+3 >= dstlen )
+          {
+              dst[count] = 0;
+              count += 3;
+              break;
+          }
+          dst[count++] = 0xe0 | static_cast<char>(ucs >> 12);
+          dst[count++] = 0x80 | static_cast<char>((ucs >> 6) & 0x3F);
+          dst[count++] = 0x80 | static_cast<char>(ucs & 0x3F);
+      }
   }
-  // we filled dst, measure the rest:
-  while (i < srclen) {
-    unsigned ucs = src[i++];
-    if (ucs < 0x80U) {
-      count++;
-    } else if (ucs < 0x800U) { // 2 bytes
-      count += 2;
+
+  // We filled dst, measure the rest:
+  while( i < srclen )
+  {
+      unsigned int ucs = src[i++];
+      if( ucs < 0x80U )
+      {
+          count++;
+      }
+      else if( ucs < 0x800U )
+      {
+          // 2 bytes.
+          count += 2;
 #ifdef _WIN32
-    } else if (ucs >= 0xd800 && ucs <= 0xdbff && i < srclen-1 &&
-	       src[i+1] >= 0xdc00 && src[i+1] <= 0xdfff) {
-      // surrogate pair
-      ++i;
+      }
+      else if( ucs >= 0xd800 && ucs <= 0xdbff && i < srclen-1 &&
+               src[i+1] >= 0xdc00 && src[i+1] <= 0xdfff )
+      {
+          // Surrogate pair.
+          ++i;
 #else
-    } else if (ucs >= 0x10000 && ucs <= 0x10ffff) {
+      }
+      else if( ucs >= 0x10000 && ucs <= 0x10ffff )
+      {
 #endif
-      count += 4;
-    } else {
-      count += 3;
-    }
+          count += 4;
+      }
+      else
+      {
+          count += 3;
+      }
   }
   return count;
 }
 
-
 /************************************************************************/
 /*                             utf8froma()                              */
 /************************************************************************/
@@ -1052,31 +1020,55 @@ static unsigned utf8fromwc(char* dst, unsigned dstlen,
 */
 static unsigned utf8froma(char* dst, unsigned dstlen,
                           const char* src, unsigned srclen) {
-  const char* p = src;
-  const char* e = src+srclen;
-  unsigned count = 0;
-  if (dstlen) for (;;) {
-    if (p >= e) {dst[count] = 0; return count;}
-    unsigned char ucs = *(unsigned char*)p++;
-    if (ucs < 0x80U) {
-      dst[count++] = ucs;
-      if (count >= dstlen) {dst[count-1] = 0; break;}
-    } else { // 2 bytes (note that CP1252 translate could make 3 bytes!)
-      if (count+2 >= dstlen) {dst[count] = 0; count += 2; break;}
-      dst[count++] = 0xc0 | (ucs >> 6);
-      dst[count++] = 0x80 | (ucs & 0x3F);
+    const char* p = src;
+    const char* e = src+srclen;
+    unsigned count = 0;
+    if( dstlen ) while( true )
+    {
+        if( p >= e )
+        {
+            dst[count] = 0;
+            return count;
+        }
+        unsigned char ucs = *(unsigned char*)p++;
+        if( ucs < 0x80U )
+        {
+            dst[count++] = ucs;
+            if( count >= dstlen )
+            {
+                dst[count-1] = 0;
+                break;
+            }
+        }
+        else
+        {
+            // 2 bytes (note that CP1252 translate could make 3 bytes!)
+            if( count+2 >= dstlen )
+            {
+                dst[count] = 0;
+                count += 2;
+                break;
+            }
+            dst[count++] = 0xc0 | (ucs >> 6);
+            dst[count++] = 0x80 | (ucs & 0x3F);
+        }
     }
-  }
-  // we filled dst, measure the rest:
-  while (p < e) {
-    unsigned char ucs = *(unsigned char*)p++;
-    if (ucs < 0x80U) {
-      count++;
-    } else {
-      count += 2;
+
+    // We filled dst, measure the rest:
+    while( p < e )
+    {
+        unsigned char ucs = *(unsigned char*)p++;
+        if( ucs < 0x80U )
+        {
+            count++;
+        }
+        else
+        {
+            count += 2;
+        }
     }
-  }
-  return count;
+
+    return count;
 }
 
 #ifdef _WIN32
@@ -1136,57 +1128,62 @@ static unsigned utf8froma(char* dst, unsigned dstlen,
 
 */
 
-char* CPLWin32Recode( const char* src, unsigned src_code_page, unsigned dst_code_page )
+char* CPLWin32Recode( const char* src, unsigned src_code_page,
+                      unsigned dst_code_page )
 {
-    /* Convert from source code page to Unicode */
+    // Convert from source code page to Unicode.
 
-    /* Compute the length in wide characters */
-    int wlen = MultiByteToWideChar( src_code_page, MB_ERR_INVALID_CHARS, src, -1, 0, 0 );
-    if (wlen == 0 && GetLastError() == ERROR_NO_UNICODE_TRANSLATION)
+    // Compute the length in wide characters.
+    int wlen = MultiByteToWideChar( src_code_page, MB_ERR_INVALID_CHARS, src,
+                                    -1, 0, 0 );
+    if( wlen == 0 && GetLastError() == ERROR_NO_UNICODE_TRANSLATION )
     {
-        if (!bHaveWarned5)
+        if( !bHaveWarned5 )
         {
             bHaveWarned5 = true;
-            CPLError(CE_Warning, CPLE_AppDefined,
-                    "One or several characters could not be translated from CP%d. "
-                    "This warning will not be emitted anymore.", src_code_page);
+            CPLError(
+                CE_Warning, CPLE_AppDefined,
+                "One or several characters could not be translated from CP%d. "
+                "This warning will not be emitted anymore.", src_code_page);
         }
 
-        /* Retry now without MB_ERR_INVALID_CHARS flag */
+        // Retry now without MB_ERR_INVALID_CHARS flag.
         wlen = MultiByteToWideChar( src_code_page, 0, src, -1, 0, 0 );
     }
 
-    /* Do the actual conversion */
-    wchar_t* tbuf = (wchar_t*)CPLCalloc(sizeof(wchar_t),wlen+1);
+    // Do the actual conversion.
+    wchar_t* tbuf =
+        static_cast<wchar_t *>(CPLCalloc(sizeof(wchar_t), wlen + 1));
     tbuf[wlen] = 0;
     MultiByteToWideChar( src_code_page, 0, src, -1, tbuf, wlen+1 );
 
-    /* Convert from Unicode to destination code page */
+    // Convert from Unicode to destination code page.
 
-    /* Compute the length in chars */
+    // Compute the length in chars.
     BOOL bUsedDefaultChar = FALSE;
     int len = 0;
-    if ( dst_code_page == CP_UTF7 || dst_code_page == CP_UTF8 )
+    if( dst_code_page == CP_UTF7 || dst_code_page == CP_UTF8 )
         len = WideCharToMultiByte( dst_code_page, 0, tbuf, -1, 0, 0, 0, NULL );
     else
-        len = WideCharToMultiByte( dst_code_page, 0, tbuf, -1, 0, 0, 0, &bUsedDefaultChar );
-    if (bUsedDefaultChar)
+        len = WideCharToMultiByte( dst_code_page, 0, tbuf, -1, 0, 0, 0,
+                                   &bUsedDefaultChar );
+    if( bUsedDefaultChar )
     {
-        if (!bHaveWarned6)
+        if( !bHaveWarned6 )
         {
             bHaveWarned6 = true;
-            CPLError(CE_Warning, CPLE_AppDefined,
-                    "One or several characters could not be translated to CP%d. "
-                    "This warning will not be emitted anymore.", dst_code_page);
+            CPLError(
+                CE_Warning, CPLE_AppDefined,
+                "One or several characters could not be translated to CP%d. "
+                "This warning will not be emitted anymore.", dst_code_page);
         }
     }
 
-    /* Do the actual conversion */
-    char* pszResult = (char*)CPLCalloc(sizeof(char),len+1);
-    WideCharToMultiByte( dst_code_page, 0, tbuf, -1, pszResult, len+1, 0, NULL );
+    // Do the actual conversion.
+    char* pszResult = static_cast<char *>(CPLCalloc(sizeof(char), len + 1));
+    WideCharToMultiByte(dst_code_page, 0, tbuf, -1, pszResult, len+1, 0, NULL);
     pszResult[len] = 0;
 
-    /* Cleanup */
     CPLFree(tbuf);
 
     return pszResult;
@@ -1194,8 +1191,6 @@ char* CPLWin32Recode( const char* src, unsigned src_code_page, unsigned dst_code
 
 #endif
 
-
-
 /*
 ** For now we disable the rest which is locale() related.  We may need
 ** parts of it later.
@@ -1219,22 +1214,25 @@ char* CPLWin32Recode( const char* src, unsigned src_code_page, unsigned dst_code
     it is likely that all non-Asian Unix systems will return true,
     due to the compatibility of UTF-8 with ISO-8859-1.
 */
-int utf8locale(void) {
-  static int ret = 2;
-  if (ret == 2) {
+int utf8locale( void )
+{
+    static int ret = 2;
+    if( ret == 2 ) {
 #ifdef _WIN32
-    ret = GetACP() == CP_UTF8;
+        ret = GetACP() == CP_UTF8;
 #else
-    char* s;
-    ret = 1; // assumme UTF-8 if no locale
-    if (((s = getenv("LC_CTYPE")) && *s) ||
-	((s = getenv("LC_ALL"))   && *s) ||
-	((s = getenv("LANG"))     && *s)) {
-      ret = (strstr(s,"utf") || strstr(s,"UTF"));
-    }
+        char* s;
+        ret = 1; // assume UTF-8 if no locale
+        if( ((s = getenv("LC_CTYPE")) && *s) ||
+            ((s = getenv("LC_ALL"))   && *s) ||
+            ((s = getenv("LANG"))     && *s) )
+        {
+            ret = strstr(s, "utf") || strstr(s, "UTF");
+        }
 #endif
-  }
-  return ret;
+    }
+
+    return ret;
 }
 
 /*! Convert the UTF-8 used by FLTK to the locale-specific encoding
@@ -1253,20 +1251,23 @@ int utf8locale(void) {
     If utf8locale() returns true then this does not change the data.
     It is copied and truncated as necessary to
     the destination buffer and \a srclen is always returned.  */
-unsigned utf8tomb(const char* src, unsigned srclen,
-		  char* dst, unsigned dstlen)
+unsigned utf8tomb( const char* src, unsigned srclen,
+                   char* dst, unsigned dstlen )
 {
-  if (!utf8locale()) {
+  if( !utf8locale() )
+  {
 #ifdef _WIN32
-    wchar_t lbuf[1024];
+    wchar_t lbuf[1024] = {};
     wchar_t* buf = lbuf;
     unsigned length = utf8towc(src, srclen, buf, 1024);
     unsigned ret;
-    if (length >= 1024) {
-      buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t)));
-      utf8towc(src, srclen, buf, length+1);
+    if( length >= 1024 )
+    {
+        buf = static_cast<wchar_t *>(malloc((length + 1) * sizeof(wchar_t)));
+        utf8towc(src, srclen, buf, length + 1);
     }
-    if (dstlen) {
+    if( dstlen )
+    {
       // apparently this does not null-terminate, even though msdn
       // documentation claims it does:
       ret =
@@ -1274,33 +1275,35 @@ unsigned utf8tomb(const char* src, unsigned srclen,
       dst[ret] = 0;
     }
     // if it overflows or measuring length, get the actual length:
-    if (dstlen==0 || ret >= dstlen-1)
-      ret =
-	WideCharToMultiByte(GetACP(), 0, buf, length, 0, 0, 0, 0);
-    if (buf != lbuf) free((void*)buf);
+    if( dstlen==0 || ret >= dstlen-1 )
+        ret = WideCharToMultiByte(GetACP(), 0, buf, length, 0, 0, 0, 0);
+    if( buf != lbuf ) free((void*)buf);
     return ret;
 #else
-    wchar_t lbuf[1024];
+    wchar_t lbuf[1024] = {};
     wchar_t* buf = lbuf;
     unsigned length = utf8towc(src, srclen, buf, 1024);
-    if (length >= 1024) {
-      buf = (wchar_t*)(malloc((length+1)*sizeof(wchar_t)));
-      utf8towc(src, srclen, buf, length+1);
+    if( length >= 1024 )
+    {
+        buf = static_cast<wchar_t *>(malloc((length + 1) * sizeof(wchar_t)));
+        utf8towc(src, srclen, buf, length+1);
     }
     int ret = 0;
-    if (dstlen) {
+    if( dstlen )
+    {
       ret = wcstombs(dst, buf, dstlen);
-      if (ret >= dstlen-1) ret = wcstombs(0,buf,0);
+      if( ret >= dstlen - 1 ) ret = wcstombs(0, buf, 0);
     } else {
-      ret = wcstombs(0,buf,0);
+      ret = wcstombs(0, buf, 0);
     }
-    if (buf != lbuf) free((void*)buf);
-    if (ret >= 0) return (unsigned)ret;
-    // on any errors we return the UTF-8 as raw text...
+    if( buf != lbuf ) free((void*)buf);
+    if( ret >= 0 ) return (unsigned)ret;
+    // On any errors we return the UTF-8 as raw text...
 #endif
   }
-  // identity transform:
-  if (srclen < dstlen) {
+  // Identity transform:
+  if( srclen < dstlen )
+  {
     memcpy(dst, src, srclen);
     dst[srclen] = 0;
   } else {
@@ -1329,54 +1332,59 @@ unsigned utf8tomb(const char* src, unsigned srclen,
     the locale.
 */
 unsigned utf8frommb(char* dst, unsigned dstlen,
-		    const char* src, unsigned srclen)
+                    const char* src, unsigned srclen)
 {
-  if (!utf8locale()) {
+  if( !utf8locale() )
+  {
 #ifdef _WIN32
-    wchar_t lbuf[1024];
+    wchar_t lbuf[1024] = {};
     wchar_t* buf = lbuf;
-    unsigned length;
     unsigned ret;
-    length =
+    const unsigned length =
       MultiByteToWideChar(GetACP(), 0, src, srclen, buf, 1024);
-    if (length >= 1024) {
+    if( length >= 1024 )
+    {
       length = MultiByteToWideChar(GetACP(), 0, src, srclen, 0, 0);
-      buf = (wchar_t*)(malloc(length*sizeof(wchar_t)));
+      buf = static_cast<wchar_t *>(malloc(length * sizeof(wchar_t)));
       MultiByteToWideChar(GetACP(), 0, src, srclen, buf, length);
     }
     ret = utf8fromwc(dst, dstlen, buf, length);
-    if (buf != lbuf) free((void*)buf);
+    if( buf != lbuf ) free(buf);
     return ret;
 #else
-    wchar_t lbuf[1024];
+    wchar_t lbuf[1024] = {};
     wchar_t* buf = lbuf;
-    unsigned ret;
-    int length = mbstowcs(buf, src, 1024);
-    if (length >= 1024) {
+    const int length = mbstowcs(buf, src, 1024);
+    if( length >= 1024 )
+    {
       length = mbstowcs(0, src, 0)+1;
-      buf = (wchar_t*)(malloc(length*sizeof(unsigned short)));
+      buf = static_cast<wchar_t *>(malloc(length*sizeof(unsigned short)));
       mbstowcs(buf, src, length);
     }
-    if (length >= 0) {
-      ret = utf8fromwc(dst, dstlen, buf, length);
-      if (buf != lbuf) free((void*)buf);
+    if( length >= 0 )
+    {
+      const unsigned ret = utf8fromwc(dst, dstlen, buf, length);
+      if( buf != lbuf ) free(buf);
       return ret;
     }
-    // errors in conversion return the UTF-8 unchanged
+    // Errors in conversion return the UTF-8 unchanged.
 #endif
   }
-  // identity transform:
-  if (srclen < dstlen) {
+  // Identity transform:
+  if( srclen < dstlen )
+  {
     memcpy(dst, src, srclen);
     dst[srclen] = 0;
-  } else {
+  }
+  else
+  {
     memcpy(dst, src, dstlen-1);
     dst[dstlen-1] = 0;
   }
   return srclen;
 }
 
-#endif /* def notdef - disabled locale specific stuff */
+#endif // def notdef - disabled locale specific stuff.
 
 /*! Examines the first \a srclen bytes in \a src and return a verdict
     on whether it is UTF-8 or not.
@@ -1399,22 +1407,25 @@ unsigned utf8frommb(char* dst, unsigned dstlen,
     encoding.
 */
 
-static int utf8test(const char* src, unsigned srclen) {
-  int ret = 1;
-  const char* p = src;
-  const char* e = src+srclen;
-  while (p < e) {
-    if (*p & 0x80) {
-      int len = 0;
-      utf8decode(p,e,&len);
-      if (len < 2) return 0;
-      if (len > ret) ret = len;
-      p += len;
-    } else {
-      p++;
+static int utf8test( const char* src, unsigned srclen )
+{
+    int ret = 1;
+    const char* p = src;
+    const char* e = src + srclen;
+    while( p < e )
+    {
+        if( *p & 0x80 )
+        {
+            int len = 0;
+            utf8decode(p, e, &len);
+            if( len < 2 ) return 0;
+            if( len > ret ) ret = len;
+            p += len;
+        } else {
+            p++;
+        }
     }
-  }
-  return ret;
+    return ret;
 }
 
 #endif /* defined(CPL_RECODE_STUB) */
diff --git a/port/cpl_sha1.cpp b/port/cpl_sha1.cpp
new file mode 100644
index 0000000..dd9632c
--- /dev/null
+++ b/port/cpl_sha1.cpp
@@ -0,0 +1,253 @@
+/******************************************************************************
+ *
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Implement SHA1
+ * Author:   Even Rouault, even.rouault at spatialys.com
+ *
+ * SHA1 computation coming from Public Domain code at:
+ * https://github.com/B-Con/crypto-algorithms/blob/master/sha1.c
+ * by Brad Conte (brad AT bradconte.com)
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <string.h>
+#include "cpl_sha1.h"
+
+CPL_CVSID("$Id: cpl_sha1.cpp 37641 2017-03-07 15:22:31Z rouault $");
+
+
+typedef struct {
+    GByte data[64];
+    GUInt32 datalen;
+    GUIntBig bitlen;
+    GUInt32 state[5];
+} CPL_SHA1Context;
+
+#define ROTLEFT(a, b) ((a << b) | (a >> (32 - b)))
+
+/************************************************************************/
+/*                         sha1_transform()                             */
+/************************************************************************/
+
+static
+void sha1_transform(CPL_SHA1Context *ctx, const GByte data[])
+{
+    GUInt32 a, b, c, d, e, i, j, t, m[80];
+
+    for (i = 0, j = 0; i < 16; ++i, j += 4)
+        m[i] = (data[j] << 24) + (data[j + 1] << 16) +
+               (data[j + 2] << 8) + (data[j + 3]);
+    for ( ; i < 80; ++i) {
+        m[i] = (m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]);
+        m[i] = (m[i] << 1) | (m[i] >> 31);
+    }
+
+    a = ctx->state[0];
+    b = ctx->state[1];
+    c = ctx->state[2];
+    d = ctx->state[3];
+    e = ctx->state[4];
+
+    for (i = 0; i < 20; ++i) {
+        t = ROTLEFT(a, 5) + ((b & c) ^ (~b & d)) + e + 0x5a827999U + m[i];
+        e = d;
+        d = c;
+        c = ROTLEFT(b, 30);
+        b = a;
+        a = t;
+    }
+    for ( ; i < 40; ++i) {
+        t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0x6ed9eba1U + m[i];
+        e = d;
+        d = c;
+        c = ROTLEFT(b, 30);
+        b = a;
+        a = t;
+    }
+    for ( ; i < 60; ++i) {
+        t = ROTLEFT(a, 5) + ((b & c) ^ (b & d) ^ (c & d))  + e +
+            0x8f1bbcdcU + m[i];
+        e = d;
+        d = c;
+        c = ROTLEFT(b, 30);
+        b = a;
+        a = t;
+    }
+    for ( ; i < 80; ++i) {
+        t = ROTLEFT(a, 5) + (b ^ c ^ d) + e + 0xca62c1d6U + m[i];
+        e = d;
+        d = c;
+        c = ROTLEFT(b, 30);
+        b = a;
+        a = t;
+    }
+
+    ctx->state[0] += a;
+    ctx->state[1] += b;
+    ctx->state[2] += c;
+    ctx->state[3] += d;
+    ctx->state[4] += e;
+}
+
+/************************************************************************/
+/*                           CPL_SHA1Init()                             */
+/************************************************************************/
+
+static
+void CPL_SHA1Init(CPL_SHA1Context *ctx)
+{
+    ctx->datalen = 0;
+    ctx->bitlen = 0;
+    ctx->state[0] = 0x67452301U;
+    ctx->state[1] = 0xEFCDAB89U;
+    ctx->state[2] = 0x98BADCFEU;
+    ctx->state[3] = 0x10325476U;
+    ctx->state[4] = 0xc3d2e1f0U;
+}
+
+/************************************************************************/
+/*                          CPL_SHA1Update()                            */
+/************************************************************************/
+
+static
+void CPL_SHA1Update(CPL_SHA1Context *ctx, const GByte data[], size_t len)
+{
+    size_t i;
+
+    for (i = 0; i < len; ++i) {
+        ctx->data[ctx->datalen] = data[i];
+        ctx->datalen++;
+        if (ctx->datalen == 64) {
+                sha1_transform(ctx, ctx->data);
+                ctx->bitlen += 512;
+                ctx->datalen = 0;
+        }
+    }
+}
+
+/************************************************************************/
+/*                           CPL_SHA1Final()                            */
+/************************************************************************/
+
+static
+void CPL_SHA1Final(CPL_SHA1Context *ctx, GByte hash[CPL_SHA1_HASH_SIZE])
+{
+    GUInt32 i;
+
+    i = ctx->datalen;
+
+    // Pad whatever data is left in the buffer.
+    if (ctx->datalen < 56) {
+        ctx->data[i++] = 0x80;
+        while (i < 56)
+            ctx->data[i++] = 0x00;
+    }
+    else {
+        ctx->data[i++] = 0x80;
+        while (i < 64)
+            ctx->data[i++] = 0x00;
+        sha1_transform(ctx, ctx->data);
+        memset(ctx->data, 0, 56);
+    }
+
+    // Append to the padding the total message's length in bits and transform.
+    ctx->bitlen += ctx->datalen * 8;
+    ctx->data[63] = static_cast<GByte>((ctx->bitlen) & 0xFFU);
+    ctx->data[62] = static_cast<GByte>((ctx->bitlen >> 8) & 0xFFU);
+    ctx->data[61] = static_cast<GByte>((ctx->bitlen >> 16) & 0xFFU);
+    ctx->data[60] = static_cast<GByte>((ctx->bitlen >> 24) & 0xFFU);
+    ctx->data[59] = static_cast<GByte>((ctx->bitlen >> 32) & 0xFFU);
+    ctx->data[58] = static_cast<GByte>((ctx->bitlen >> 40) & 0xFFU);
+    ctx->data[57] = static_cast<GByte>((ctx->bitlen >> 48) & 0xFFU);
+    ctx->data[56] = static_cast<GByte>((ctx->bitlen >> 56) & 0xFFU);
+    sha1_transform(ctx, ctx->data);
+
+    // Since this implementation uses little endian byte ordering and MD uses big endian,
+    // reverse all the bytes when copying the final state to the output hash.
+    for (i = 0; i < 4; ++i) {
+        hash[i]      = static_cast<GByte>((ctx->state[0] >> (24 - i * 8)) & 0x000000ffU);
+        hash[i + 4]  = static_cast<GByte>((ctx->state[1] >> (24 - i * 8)) & 0x000000ffU);
+        hash[i + 8]  = static_cast<GByte>((ctx->state[2] >> (24 - i * 8)) & 0x000000ffU);
+        hash[i + 12] = static_cast<GByte>((ctx->state[3] >> (24 - i * 8)) & 0x000000ffU);
+        hash[i + 16] = static_cast<GByte>((ctx->state[4] >> (24 - i * 8)) & 0x000000ffU);
+    }
+}
+
+/************************************************************************/
+/*                              CPL_SHA1()                              */
+/************************************************************************/
+
+static
+void CPL_SHA1( const void *data, size_t len, GByte hash[CPL_SHA1_HASH_SIZE] )
+{
+    CPL_SHA1Context sSHA1Ctxt;
+    CPL_SHA1Init(&sSHA1Ctxt);
+    CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte*>(data), len);
+    CPL_SHA1Final(&sSHA1Ctxt, hash);
+    memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
+}
+
+/************************************************************************/
+/*                           CPL_HMAC_SHA1()                            */
+/************************************************************************/
+
+#define CPL_HMAC_SHA1_BLOCKSIZE 64U
+
+// See https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Implementation
+void CPL_HMAC_SHA1(const void *pKey, size_t nKeyLen,
+                             const void *pabyMessage, size_t nMessageLen,
+                             GByte abyDigest[CPL_SHA1_HASH_SIZE])
+{
+    GByte abyPad[CPL_HMAC_SHA1_BLOCKSIZE] = {};
+    if( nKeyLen > CPL_HMAC_SHA1_BLOCKSIZE )
+    {
+        CPL_SHA1(pKey, nKeyLen, abyPad);
+    }
+    else
+    {
+        memcpy(abyPad, pKey, nKeyLen);
+    }
+
+    // Compute ipad.
+    for( size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++ )
+        abyPad[i] = 0x36 ^ abyPad[i];
+
+    CPL_SHA1Context sSHA1Ctxt;
+    CPL_SHA1Init(&sSHA1Ctxt);
+    CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
+    CPL_SHA1Update(&sSHA1Ctxt, static_cast<const GByte*>(pabyMessage),
+                   nMessageLen);
+    CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
+
+    // Compute opad.
+    for( size_t i = 0; i < CPL_HMAC_SHA1_BLOCKSIZE; i++ )
+        abyPad[i] = (0x36 ^ 0x5C) ^ abyPad[i];
+
+    CPL_SHA1Init(&sSHA1Ctxt);
+    CPL_SHA1Update(&sSHA1Ctxt, abyPad, CPL_HMAC_SHA1_BLOCKSIZE);
+    CPL_SHA1Update(&sSHA1Ctxt, abyDigest, CPL_SHA1_HASH_SIZE);
+    CPL_SHA1Final(&sSHA1Ctxt, abyDigest);
+
+    memset(&sSHA1Ctxt, 0, sizeof(sSHA1Ctxt));
+    memset(abyPad, 0, CPL_HMAC_SHA1_BLOCKSIZE);
+}
diff --git a/port/cpl_sha1.h b/port/cpl_sha1.h
new file mode 100644
index 0000000..7d3729f
--- /dev/null
+++ b/port/cpl_sha1.h
@@ -0,0 +1,53 @@
+/******************************************************************************
+ *
+ * Project:  CPL - Common Portability Library
+ * Purpose:  Implement SHA1
+ * Author:   Even Rouault, even.rouault at spatialys.com
+ *
+ * SHA1 computation coming from Public Domain code at:
+ * https://github.com/B-Con/crypto-algorithms/blob/master/sha1.c
+ * by Brad Conte (brad AT bradconte.com)
+ *
+ ******************************************************************************
+ * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef CPL_SHA1_INCLUDED_H
+#define CPL_SHA1_INCLUDED_H
+
+#ifndef DOXYGEN_SKIP
+
+#include "cpl_port.h"
+
+#define CPL_SHA1_HASH_SIZE 20 // SHA1 outputs a 20 byte digest
+
+CPL_C_START
+
+/* Not CPL_DLL exported */
+void CPL_HMAC_SHA1(const void *pKey, size_t nKeyLen,
+                   const void *pabyMessage, size_t nMessageLen,
+                   GByte abyDigest[CPL_SHA1_HASH_SIZE]);
+
+CPL_C_END
+
+#endif /* #ifndef DOXYGEN_SKIP */
+
+#endif  /* CPL_SHA1_INCLUDED_H */
diff --git a/port/cpl_sha256.cpp b/port/cpl_sha256.cpp
index dc61a3c..b3063b9 100644
--- a/port/cpl_sha256.cpp
+++ b/port/cpl_sha256.cpp
@@ -1,5 +1,3 @@
-/* $Id: cpl_sha256.cpp 33724 2016-03-16 17:14:11Z goatbar $ */
-
 /* CPL_SHA256* functions derived from http://code.google.com/p/ulib/source/browse/trunk/src/base/sha256sum.c?r=39 */
 
 /* The MIT License
@@ -36,7 +34,7 @@
 #include <string.h>
 #include "cpl_sha256.h"
 
-CPL_CVSID("$Id: cpl_sha256.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+CPL_CVSID("$Id: cpl_sha256.cpp 36929 2016-12-17 06:39:24Z goatbar $");
 
 #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
 #define ROTR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
@@ -62,22 +60,22 @@ CPL_CVSID("$Id: cpl_sha256.cpp 33724 2016-03-16 17:14:11Z goatbar $");
         }
 
 static const GUInt32 K[64] = {
-        0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U,
-        0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
-        0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U,
-        0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
-        0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
-        0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
-        0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,
-        0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,
-        0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U,
-        0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
-        0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U,
-        0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,
-        0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U,
-        0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
-        0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
-        0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
+    0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U,
+    0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
+    0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U,
+    0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
+    0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
+    0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
+    0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,
+    0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,
+    0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U,
+    0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
+    0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U,
+    0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,
+    0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U,
+    0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
+    0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
+    0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U
 };
 
 #ifdef WORDS_BIGENDIAN
@@ -85,17 +83,19 @@ static const GUInt32 K[64] = {
 #define BYTESWAP(x) (x)
 #define BYTESWAP64(x) (x)
 
-#else                           /* WORDS_BIGENDIAN */
+#else  // WORDS_BIGENDIAN
 
-#define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00U) |     \
+#define BYTESWAP(x) ((ROTR((x), 8) & 0xff00ff00U) | \
                      (ROTL((x), 8) & 0x00ff00ffU))
 #define BYTESWAP64(x) _byteswap64(x)
 
 static inline GUInt64 _byteswap64(GUInt64 x)
 {
-        GUInt32 a = (GUInt32) (x >> 32);
-        GUInt32 b = (GUInt32) x;
-        return ((GUInt64) BYTESWAP(b) << 32) | (GUInt64) BYTESWAP(a);
+    GUInt32 a = static_cast<GUInt32>(x >> 32);
+    GUInt32 b = static_cast<GUInt32>(x);
+    return
+        (static_cast<GUInt64>(BYTESWAP(b)) << 32) |
+        static_cast<GUInt64>(BYTESWAP(a));
 }
 
 #endif /* !(WORDS_BIGENDIAN) */
@@ -125,56 +125,56 @@ void CPL_SHA256Init(CPL_SHA256Context * sc)
         sc->bufferLength = 0U;
 }
 
-static GUInt32 burnStack(int size)
+static GUInt32 burnStack( int size )
 {
-        GByte buf[128];
-        GUInt32 ret = 0;
-
-        memset(buf, (GByte)(size & 0xff), sizeof(buf));
-        for( size_t i = 0; i < sizeof(buf); i++ )
-            ret += ret * buf[i];
-        size -= sizeof(buf);
-        if (size > 0)
-                ret += burnStack(size);
-        return ret;
+    GByte buf[128];
+    GUInt32 ret = 0;
+
+    memset(buf, static_cast<GByte>(size & 0xff), sizeof(buf));
+    for( size_t i = 0; i < sizeof(buf); i++ )
+        ret += ret * buf[i];
+    size -= sizeof(buf);
+    if( size > 0 )
+        ret += burnStack(size);
+    return ret;
 }
 
 static void CPL_SHA256Guts(CPL_SHA256Context * sc, const GUInt32 * cbuf)
 {
-        GUInt32 buf[64];
-        GUInt32 *W, *W2, *W7, *W15, *W16;
-        GUInt32 a, b, c, d, e, f, g, h;
-        GUInt32 t1, t2;
-        const GUInt32 *Kp;
+        GUInt32 buf[64] = {};
+        GUInt32 t1 = 0;
+        GUInt32 t2 = 0;
 
-        W = buf;
+        GUInt32 *W = buf;
 
-        for ( int i = 15; i >= 0; i-- ) {
+        for( int i = 15; i >= 0; i-- )
+        {
                 *(W++) = BYTESWAP(*cbuf);
                 cbuf++;
         }
 
-        W16 = &buf[0];
-        W15 = &buf[1];
-        W7 = &buf[9];
-        W2 = &buf[14];
+        GUInt32 *W16 = &buf[0];
+        GUInt32 *W15 = &buf[1];
+        GUInt32 *W7 = &buf[9];
+        GUInt32 *W2 = &buf[14];
 
-        for ( int i = 47; i >= 0; i-- ) {
+        for( int i = 47; i >= 0; i-- )
+        {
                 *(W++) = sigma1(*W2) + *(W7++) + sigma0(*W15) + *(W16++);
                 W2++;
                 W15++;
         }
 
-        a = sc->hash[0];
-        b = sc->hash[1];
-        c = sc->hash[2];
-        d = sc->hash[3];
-        e = sc->hash[4];
-        f = sc->hash[5];
-        g = sc->hash[6];
-        h = sc->hash[7];
+        GUInt32 a = sc->hash[0];
+        GUInt32 b = sc->hash[1];
+        GUInt32 c = sc->hash[2];
+        GUInt32 d = sc->hash[3];
+        GUInt32 e = sc->hash[4];
+        GUInt32 f = sc->hash[5];
+        GUInt32 g = sc->hash[6];
+        GUInt32 h = sc->hash[7];
 
-        Kp = K;
+        const GUInt32 *Kp = K;
         W = buf;
 
 #ifndef CPL_SHA256_UNROLL
@@ -182,22 +182,25 @@ static void CPL_SHA256Guts(CPL_SHA256Context * sc, const GUInt32 * cbuf)
 #endif                          /* !CPL_SHA256_UNROLL */
 
 #if CPL_SHA256_UNROLL == 1
-        for ( int i = 63; i >= 0; i-- )
+        for( int i = 63; i >= 0; i-- )
                 DO_ROUND();
 #elif CPL_SHA256_UNROLL == 2
-        for ( int i = 31; i >= 0; i-- ) {
+        for( int i = 31; i >= 0; i-- )
+        {
                 DO_ROUND();
                 DO_ROUND();
         }
 #elif CPL_SHA256_UNROLL == 4
-        for ( int i = 15; i >= 0; i-- ) {
+        for( int i = 15; i >= 0; i-- )
+        {
                 DO_ROUND();
                 DO_ROUND();
                 DO_ROUND();
                 DO_ROUND();
         }
 #elif CPL_SHA256_UNROLL == 8
-        for ( int i = 7; i >= 0; i-- ) {
+        for( int i = 7; i >= 0; i-- )
+        {
                 DO_ROUND();
                 DO_ROUND();
                 DO_ROUND();
@@ -208,7 +211,8 @@ static void CPL_SHA256Guts(CPL_SHA256Context * sc, const GUInt32 * cbuf)
                 DO_ROUND();
         }
 #elif CPL_SHA256_UNROLL == 16
-        for ( int i = 3; i >= 0; i-- ) {
+        for( int i = 3; i >= 0; i-- )
+        {
                 DO_ROUND();
                 DO_ROUND();
                 DO_ROUND();
@@ -227,7 +231,8 @@ static void CPL_SHA256Guts(CPL_SHA256Context * sc, const GUInt32 * cbuf)
                 DO_ROUND();
         }
 #elif CPL_SHA256_UNROLL == 32
-        for ( int i = 1; i >= 0; i-- ) {
+        for( int i = 1; i >= 0; i-- )
+        {
                 DO_ROUND();
                 DO_ROUND();
                 DO_ROUND();
@@ -340,88 +345,92 @@ static void CPL_SHA256Guts(CPL_SHA256Context * sc, const GUInt32 * cbuf)
         sc->hash[7] += h;
 }
 
-void CPL_SHA256Update(CPL_SHA256Context * sc, const void *data, size_t len)
+void CPL_SHA256Update( CPL_SHA256Context * sc, const void *data, size_t len )
 {
-        GUInt32 bufferBytesLeft;
-        GUInt32 bytesToCopy;
-        int needBurn = 0;
+    int needBurn = 0;
 
-        if (sc->bufferLength) {
-                bufferBytesLeft = 64U - sc->bufferLength;
+    if( sc->bufferLength )
+    {
+        const GUInt32 bufferBytesLeft = 64U - sc->bufferLength;
 
-                bytesToCopy = bufferBytesLeft;
-                if (bytesToCopy > len)
-                        bytesToCopy = (GUInt32)len;
+        GUInt32 bytesToCopy = bufferBytesLeft;
+        if( bytesToCopy > len )
+            bytesToCopy = static_cast<GUInt32>(len);
 
-                memcpy(&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
+        memcpy(&sc->buffer.bytes[sc->bufferLength], data, bytesToCopy);
 
-                sc->totalLength += bytesToCopy * 8U;
+        sc->totalLength += bytesToCopy * 8U;
 
-                sc->bufferLength += bytesToCopy;
-                data = ((GByte *) data) + bytesToCopy;
-                len -= bytesToCopy;
+        sc->bufferLength += bytesToCopy;
+        data = static_cast<const GByte *>(data) + bytesToCopy;
+        len -= bytesToCopy;
 
-                if (sc->bufferLength == 64U) {
-                        CPL_SHA256Guts(sc, sc->buffer.words);
-                        needBurn = 1;
-                        sc->bufferLength = 0U;
-                }
+        if( sc->bufferLength == 64U )
+        {
+            CPL_SHA256Guts(sc, sc->buffer.words);
+            needBurn = 1;
+            sc->bufferLength = 0U;
         }
+    }
 
-        while (len > 63U) {
-                sc->totalLength += 512U;
+    while( len > 63U )
+    {
+        sc->totalLength += 512U;
 
-                CPL_SHA256Guts(sc, (const GUInt32 *)data);
-                needBurn = 1;
+        CPL_SHA256Guts(sc, static_cast<const GUInt32 *>(data));
+        needBurn = 1;
 
-                data = ((GByte *) data) + 64U;
-                len -= 64U;
-        }
+        data = static_cast<const GByte *>(data) + 64U;
+        len -= 64U;
+    }
 
-        if (len) {
-                memcpy(&sc->buffer.bytes[sc->bufferLength], data, len);
+    if( len )
+    {
+        memcpy(&sc->buffer.bytes[sc->bufferLength], data, len);
 
-                sc->totalLength += (GUInt32)len * 8U;
+        sc->totalLength += static_cast<GUInt32>(len) * 8U;
 
-                sc->bufferLength += (GUInt32)len;
-        }
+        sc->bufferLength += static_cast<GUInt32>(len);
+    }
 
-        if (needBurn)
-        {
-                // Clean stack state of CPL_SHA256Guts()
-                // We add dummy side effects to avoid burnStack() to be optimized away (#6157)
-                static GUInt32 accumulator = 0;
-                accumulator += burnStack( static_cast<int>(
-                        sizeof(GUInt32[74]) + sizeof(GUInt32 *[6]) +
-                        sizeof(int) + ((len%2) ? sizeof(int) : 0)) );
-                if( accumulator == 0xDEADBEEF )
-                    fprintf(stderr, "%s", "");
-        }
+    if( needBurn )
+    {
+        // Clean stack state of CPL_SHA256Guts()
+
+        // We add dummy side effects to avoid burnStack() to be
+        // optimized away (#6157).
+        static GUInt32 accumulator = 0;
+        accumulator += burnStack(
+            static_cast<int>(sizeof(GUInt32[74]) + sizeof(GUInt32 *[6]) +
+                             sizeof(int) + ((len%2) ? sizeof(int) : 0)) );
+        if( accumulator == 0xDEADBEEF )
+            fprintf(stderr, "%s", ""); /*ok*/
+    }
 }
 
-void CPL_SHA256Final(CPL_SHA256Context * sc, GByte hash[CPL_SHA256_HASH_SIZE])
+void CPL_SHA256Final( CPL_SHA256Context * sc, GByte hash[CPL_SHA256_HASH_SIZE] )
 {
-        GUInt32 bytesToPad;
-        GUInt64 lengthPad;
-
-        bytesToPad = 120U - sc->bufferLength;
-        if (bytesToPad > 64U)
-                bytesToPad -= 64U;
+    GUInt32 bytesToPad = 120U - sc->bufferLength;
+    if( bytesToPad > 64U )
+        bytesToPad -= 64U;
 
-        lengthPad = BYTESWAP64(sc->totalLength);
+    const GUInt64 lengthPad = BYTESWAP64(sc->totalLength);
 
-        CPL_SHA256Update(sc, padding, bytesToPad);
-        CPL_SHA256Update(sc, &lengthPad, 8U);
+    CPL_SHA256Update(sc, padding, bytesToPad);
+    CPL_SHA256Update(sc, &lengthPad, 8U);
 
-        if (hash) {
-            for ( int i = 0; i < CPL_SHA256_HASH_WORDS; i++ ) {
-                *((GUInt32 *) hash) = BYTESWAP(sc->hash[i]);
-                hash += 4;
-            }
+    if( hash )
+    {
+        for( int i = 0; i < CPL_SHA256_HASH_WORDS; i++ )
+        {
+            *((GUInt32 *) hash) = BYTESWAP(sc->hash[i]);
+            hash += 4;
         }
+    }
 }
 
-void CPL_SHA256(const void *data, size_t len, GByte hash[CPL_SHA256_HASH_SIZE])
+void CPL_SHA256( const void *data, size_t len,
+                 GByte hash[CPL_SHA256_HASH_SIZE] )
 {
     CPL_SHA256Context sSHA256Ctxt;
     CPL_SHA256Init(&sSHA256Ctxt);
@@ -432,13 +441,12 @@ void CPL_SHA256(const void *data, size_t len, GByte hash[CPL_SHA256_HASH_SIZE])
 
 #define CPL_HMAC_SHA256_BLOCKSIZE 64U
 
-/* See https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Implementation */
-void CPL_HMAC_SHA256(const void *pKey, size_t nKeyLen,
-                     const void *pabyMessage, size_t nMessageLen,
-                     GByte abyDigest[CPL_SHA256_HASH_SIZE])
+// See https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Implementation
+void CPL_HMAC_SHA256( const void *pKey, size_t nKeyLen,
+                      const void *pabyMessage, size_t nMessageLen,
+                      GByte abyDigest[CPL_SHA256_HASH_SIZE] )
 {
-    GByte abyPad[CPL_HMAC_SHA256_BLOCKSIZE];
-    memset(abyPad, 0, CPL_HMAC_SHA256_BLOCKSIZE);
+    GByte abyPad[CPL_HMAC_SHA256_BLOCKSIZE] = {};
     if( nKeyLen > CPL_HMAC_SHA256_BLOCKSIZE )
     {
         CPL_SHA256(pKey, nKeyLen, abyPad);
@@ -448,7 +456,7 @@ void CPL_HMAC_SHA256(const void *pKey, size_t nKeyLen,
         memcpy(abyPad, pKey, nKeyLen);
     }
 
-    /* Compute ipad */
+    // Compute ipad.
     for( size_t i = 0; i < CPL_HMAC_SHA256_BLOCKSIZE; i++ )
         abyPad[i] = 0x36 ^ abyPad[i];
 
@@ -458,7 +466,7 @@ void CPL_HMAC_SHA256(const void *pKey, size_t nKeyLen,
     CPL_SHA256Update(&sSHA256Ctxt, pabyMessage, nMessageLen);
     CPL_SHA256Final(&sSHA256Ctxt, abyDigest);
 
-    /* Compute opad */
+    // Compute opad.
     for( size_t i = 0; i < CPL_HMAC_SHA256_BLOCKSIZE; i++ )
         abyPad[i] = (0x36 ^ 0x5C) ^ abyPad[i];
 
diff --git a/port/cpl_sha256.h b/port/cpl_sha256.h
index 0868cf9..6066073 100644
--- a/port/cpl_sha256.h
+++ b/port/cpl_sha256.h
@@ -1,4 +1,4 @@
-/* $Id: cpl_sha256.h 31777 2015-11-26 14:14:41Z rouault $ */
+/* $Id: cpl_sha256.h 34921 2016-08-04 22:26:31Z rouault $ */
 
 /* The MIT License
 
@@ -29,6 +29,8 @@
 #ifndef CPL_SHA256_INCLUDED_H
 #define CPL_SHA256_INCLUDED_H
 
+#ifndef DOXYGEN_SKIP
+
 #include "cpl_port.h"
 
 #define CPL_SHA256_HASH_SIZE 32     /* 256 bit */
@@ -65,4 +67,6 @@ void CPL_DLL CPL_HMAC_SHA256(const void *pKey, size_t nKeyLen,
 
 CPL_C_END
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 #endif  /* CPL_SHA256_INCLUDED_H */
diff --git a/port/cpl_spawn.cpp b/port/cpl_spawn.cpp
index b375ebb..9b790ce 100644
--- a/port/cpl_spawn.cpp
+++ b/port/cpl_spawn.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_spawn.cpp 33726 2016-03-16 18:48:51Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement CPLSystem().
@@ -27,8 +26,12 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_spawn.h"
 
+#include <cstring>
+
+#include "cpl_config.h"
 #include "cpl_conv.h"
 #include "cpl_error.h"
 #include "cpl_multiproc.h"
@@ -63,26 +66,24 @@ static const int PIPE_BUFFER_SIZE = 4096;
 static const int IN_FOR_PARENT = 0;
 static const int OUT_FOR_PARENT = 1;
 
-CPL_CVSID("$Id: cpl_spawn.cpp 33726 2016-03-16 18:48:51Z goatbar $");
+CPL_CVSID("$Id: cpl_spawn.cpp 36989 2016-12-21 19:05:47Z goatbar $");
 
 static void FillFileFromPipe(CPL_FILE_HANDLE pipe_fd, VSILFILE* fout);
 
-//int CPL_DLL CPLSystem( const char* pszApplicationName, const char* pszCommandLine );
-
 /************************************************************************/
 /*                        FillPipeFromFile()                            */
 /************************************************************************/
 
-static void FillPipeFromFile(VSILFILE* fin, CPL_FILE_HANDLE pipe_fd)
+static void FillPipeFromFile( VSILFILE* fin, CPL_FILE_HANDLE pipe_fd )
 {
-    char buf[PIPE_BUFFER_SIZE];
-    while(true)
+    char buf[PIPE_BUFFER_SIZE] = {};
+    while( true )
     {
-        const int nRead
-            = static_cast<int>( VSIFReadL(buf, 1, PIPE_BUFFER_SIZE, fin) );
+        const int nRead =
+            static_cast<int>( VSIFReadL(buf, 1, PIPE_BUFFER_SIZE, fin) );
         if( nRead <= 0 )
             break;
-        if (!CPLPipeWrite(pipe_fd, buf, nRead))
+        if( !CPLPipeWrite(pipe_fd, buf, nRead) )
             break;
     }
 }
@@ -104,30 +105,31 @@ static void FillPipeFromFile(VSILFILE* fin, CPL_FILE_HANDLE pipe_fd)
  *                  name of the executable
  * @param fin File handle for input data to feed to the standard input of the
  *            sub-process. May be NULL.
- * @param fout File handle for output data to extract from the standard output of the
- *            sub-process. May be NULL.
- * @param bDisplayErr Set to TRUE to emit the content of the standard error stream of
- *                    the sub-process with CPLError().
+ * @param fout File handle for output data to extract from the standard output
+ *            of the sub-process. May be NULL.
+ * @param bDisplayErr Set to TRUE to emit the content of the standard error
+ *                    stream of the sub-process with CPLError().
  *
  * @return the exit code of the spawned process, or -1 in case of error.
  *
  * @since GDAL 1.10.0
  */
 
-int CPLSpawn(const char * const papszArgv[], VSILFILE* fin, VSILFILE* fout,
-             int bDisplayErr)
+int CPLSpawn( const char * const papszArgv[], VSILFILE* fin, VSILFILE* fout,
+              int bDisplayErr )
 {
-    CPLSpawnedProcess* sp = CPLSpawnAsync(NULL, papszArgv, TRUE, TRUE, TRUE, NULL);
+    CPLSpawnedProcess* sp =
+        CPLSpawnAsync(NULL, papszArgv, TRUE, TRUE, TRUE, NULL);
     if( sp == NULL )
         return -1;
 
     CPL_FILE_HANDLE in_child = CPLSpawnAsyncGetOutputFileHandle(sp);
-    if (fin != NULL)
+    if( fin != NULL )
         FillPipeFromFile(fin, in_child);
     CPLSpawnAsyncCloseOutputFileHandle(sp);
 
     CPL_FILE_HANDLE out_child = CPLSpawnAsyncGetInputFileHandle(sp);
-    if (fout != NULL)
+    if( fout != NULL )
         FillFileFromPipe(out_child, fout);
     CPLSpawnAsyncCloseInputFileHandle(sp);
 
@@ -149,7 +151,8 @@ int CPLSpawn(const char * const papszArgv[], VSILFILE* fin, VSILFILE* fout,
             "An error occurred while forking process") != NULL )
         bDisplayErr = TRUE;
     if( pData && bDisplayErr )
-        CPLError(CE_Failure, CPLE_AppDefined, "[%s error] %s", papszArgv[0], pData);
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "[%s error] %s", papszArgv[0], pData);
     CPLFree(pData);
 
     return CPLSpawnAsyncFinish(sp, TRUE, FALSE);
@@ -157,75 +160,18 @@ int CPLSpawn(const char * const papszArgv[], VSILFILE* fin, VSILFILE* fout,
 
 #if defined(WIN32)
 
-#if 0
-/************************************************************************/
-/*                            CPLSystem()                               */
-/************************************************************************/
-
-int CPLSystem( const char* pszApplicationName, const char* pszCommandLine )
-{
-    int nRet = -1;
-    PROCESS_INFORMATION processInfo;
-    STARTUPINFO startupInfo;
-    ZeroMemory( &processInfo, sizeof(PROCESS_INFORMATION) );
-    ZeroMemory( &startupInfo, sizeof(STARTUPINFO) );
-    startupInfo.cb = sizeof(STARTUPINFO);
-
-    char* pszDupedCommandLine = (pszCommandLine) ? CPLStrdup(pszCommandLine) : NULL;
-
-    if( !CreateProcess( pszApplicationName,
-                        pszDupedCommandLine,
-                        NULL,
-                        NULL,
-                        FALSE,
-                        CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS,
-                        NULL,
-                        NULL,
-                        &startupInfo,
-                        &processInfo) )
-    {
-        DWORD err = GetLastError();
-        CPLDebug("CPL", "'%s' failed : err = %d", pszCommandLine, (int)err);
-        nRet = -1;
-    }
-    else
-    {
-        WaitForSingleObject( processInfo.hProcess, INFINITE );
-
-        DWORD exitCode = 0;
-
-        // Get the exit code.
-        int err = GetExitCodeProcess(processInfo.hProcess, &exitCode);
-
-        CloseHandle(processInfo.hProcess);
-        CloseHandle(processInfo.hThread);
-
-        if( !err )
-        {
-            CPLDebug("CPL", "GetExitCodeProcess() failed : err = %d", err);
-        }
-        else
-            nRet = exitCode;
-    }
-
-    CPLFree(pszDupedCommandLine);
-
-    return nRet;
-}
-#endif  // if 0
-
 /************************************************************************/
 /*                          CPLPipeRead()                               */
 /************************************************************************/
 
-int CPLPipeRead(CPL_FILE_HANDLE fin, void* data, int length)
+int CPLPipeRead( CPL_FILE_HANDLE fin, void* data, int length )
 {
-    GByte* pabyData = reinterpret_cast<GByte *>( data );
+    GByte* pabyData = static_cast<GByte *>(data);
     int nRemain = length;
     while( nRemain > 0 )
     {
         DWORD nRead = 0;
-        if (!ReadFile( fin, pabyData, nRemain, &nRead, NULL))
+        if( !ReadFile(fin, pabyData, nRemain, &nRead, NULL) )
             return FALSE;
         pabyData += nRead;
         nRemain -= nRead;
@@ -237,14 +183,14 @@ int CPLPipeRead(CPL_FILE_HANDLE fin, void* data, int length)
 /*                         CPLPipeWrite()                               */
 /************************************************************************/
 
-int CPLPipeWrite(CPL_FILE_HANDLE fout, const void* data, int length)
+int CPLPipeWrite( CPL_FILE_HANDLE fout, const void* data, int length )
 {
-    const GByte* pabyData = (const GByte*)data;
+    const GByte* pabyData = static_cast<const GByte *>(data);
     int nRemain = length;
     while( nRemain > 0 )
     {
         DWORD nWritten = 0;
-        if (!WriteFile(fout, pabyData, nRemain, &nWritten, NULL))
+        if( !WriteFile(fout, pabyData, nRemain, &nWritten, NULL) )
             return FALSE;
         pabyData += nWritten;
         nRemain -= nWritten;
@@ -258,16 +204,16 @@ int CPLPipeWrite(CPL_FILE_HANDLE fout, const void* data, int length)
 
 static void FillFileFromPipe(CPL_FILE_HANDLE pipe_fd, VSILFILE* fout)
 {
-    char buf[PIPE_BUFFER_SIZE];
-    while(true)
+    char buf[PIPE_BUFFER_SIZE] = {};
+    while( true )
     {
         DWORD nRead = 0;
-        if (!ReadFile( pipe_fd, buf, PIPE_BUFFER_SIZE, &nRead, NULL))
+        if( !ReadFile( pipe_fd, buf, PIPE_BUFFER_SIZE, &nRead, NULL) )
             break;
-        if (nRead <= 0)
+        if( nRead <= 0 )
             break;
-        int nWritten = (int)VSIFWriteL(buf, 1, nRead, fout);
-        if (nWritten < (int)nRead)
+        const int nWritten = static_cast<int>(VSIFWriteL(buf, 1, nRead, fout));
+        if( nWritten < static_cast<int>(nRead) )
             break;
     }
 }
@@ -286,22 +232,14 @@ struct _CPLSpawnedProcess
 /*                            CPLSpawnAsync()                           */
 /************************************************************************/
 
-CPLSpawnedProcess* CPLSpawnAsync(CPL_UNUSED int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE),
-                                 const char * const papszArgv[],
-                                 int bCreateInputPipe,
-                                 int bCreateOutputPipe,
-                                 int bCreateErrorPipe,
-                                 CPL_UNUSED char** papszOptions)
+CPLSpawnedProcess* CPLSpawnAsync(
+    CPL_UNUSED int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE),
+    const char * const papszArgv[],
+    int bCreateInputPipe,
+    int bCreateOutputPipe,
+    int bCreateErrorPipe,
+    char** /* papszOptions */)
 {
-    HANDLE pipe_in[2] = {NULL, NULL};
-    HANDLE pipe_out[2] = {NULL, NULL};
-    HANDLE pipe_err[2] = {NULL, NULL};
-    SECURITY_ATTRIBUTES saAttr;
-    PROCESS_INFORMATION piProcInfo;
-    STARTUPINFO siStartInfo;
-    CPLString osCommandLine;
-    CPLSpawnedProcess* p = NULL;
-
     if( papszArgv == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -309,50 +247,73 @@ CPLSpawnedProcess* CPLSpawnAsync(CPL_UNUSED int (*pfnMain)(CPL_FILE_HANDLE, CPL_
         return NULL;
     }
 
+    // TODO(schwehr): Consider initializing saAttr.
+    SECURITY_ATTRIBUTES saAttr;
     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
     saAttr.bInheritHandle = TRUE;
     saAttr.lpSecurityDescriptor = NULL;
 
+    // TODO(schwehr): Move these to where they are used after gotos are removed.
+    HANDLE pipe_out[2] = { NULL, NULL };
+    HANDLE pipe_err[2] = { NULL, NULL };
+    CPLString osCommandLine;
+
+    HANDLE pipe_in[2] = { NULL, NULL };
     if( bCreateInputPipe )
     {
-        if (!CreatePipe(&pipe_in[IN_FOR_PARENT],&pipe_in[OUT_FOR_PARENT],&saAttr, 0))
+        if( !CreatePipe(&pipe_in[IN_FOR_PARENT], &pipe_in[OUT_FOR_PARENT],
+                        &saAttr, 0) )
             goto err_pipe;
-        /* The child must not inherit from the write side of the pipe_in */
-        if (!SetHandleInformation(pipe_in[OUT_FOR_PARENT],HANDLE_FLAG_INHERIT,0))
+        // The child must not inherit from the write side of the pipe_in.
+        if( !SetHandleInformation(pipe_in[OUT_FOR_PARENT], HANDLE_FLAG_INHERIT,
+                                  0) )
             goto err_pipe;
     }
 
     if( bCreateOutputPipe )
     {
-        if (!CreatePipe(&pipe_out[IN_FOR_PARENT],&pipe_out[OUT_FOR_PARENT],&saAttr, 0))
+        if( !CreatePipe(&pipe_out[IN_FOR_PARENT], &pipe_out[OUT_FOR_PARENT],
+                        &saAttr, 0) )
             goto err_pipe;
-        /* The child must not inherit from the read side of the pipe_out */
-        if (!SetHandleInformation(pipe_out[IN_FOR_PARENT],HANDLE_FLAG_INHERIT,0))
+        // The child must not inherit from the read side of the pipe_out.
+        if( !SetHandleInformation(pipe_out[IN_FOR_PARENT], HANDLE_FLAG_INHERIT,
+                                  0) )
             goto err_pipe;
     }
 
     if( bCreateErrorPipe )
     {
-        if (!CreatePipe(&pipe_err[IN_FOR_PARENT],&pipe_err[OUT_FOR_PARENT],&saAttr, 0))
+        if( !CreatePipe(&pipe_err[IN_FOR_PARENT], &pipe_err[OUT_FOR_PARENT],
+                        &saAttr, 0) )
             goto err_pipe;
-        /* The child must not inherit from the read side of the pipe_err */
-        if (!SetHandleInformation(pipe_err[IN_FOR_PARENT],HANDLE_FLAG_INHERIT,0))
+        // The child must not inherit from the read side of the pipe_err.
+        if( !SetHandleInformation(pipe_err[IN_FOR_PARENT], HANDLE_FLAG_INHERIT,
+                                  0) )
             goto err_pipe;
     }
 
+    // TODO(schwehr): Consider initializing piProcInfo.
+    PROCESS_INFORMATION piProcInfo;
     memset(&piProcInfo, 0, sizeof(PROCESS_INFORMATION));
+    STARTUPINFO siStartInfo;
     memset(&siStartInfo, 0, sizeof(STARTUPINFO));
     siStartInfo.cb = sizeof(STARTUPINFO);
-    siStartInfo.hStdInput = (bCreateInputPipe) ? pipe_in[IN_FOR_PARENT] : GetStdHandle(STD_INPUT_HANDLE);
-    siStartInfo.hStdOutput = (bCreateOutputPipe) ? pipe_out[OUT_FOR_PARENT] : GetStdHandle(STD_OUTPUT_HANDLE);
-    siStartInfo.hStdError = (bCreateErrorPipe) ? pipe_err[OUT_FOR_PARENT] : GetStdHandle(STD_ERROR_HANDLE);
+    siStartInfo.hStdInput =
+        bCreateInputPipe
+        ? pipe_in[IN_FOR_PARENT] : GetStdHandle(STD_INPUT_HANDLE);
+    siStartInfo.hStdOutput =
+        bCreateOutputPipe
+        ? pipe_out[OUT_FOR_PARENT] : GetStdHandle(STD_OUTPUT_HANDLE);
+    siStartInfo.hStdError =
+        bCreateErrorPipe
+        ? pipe_err[OUT_FOR_PARENT] : GetStdHandle(STD_ERROR_HANDLE);
     siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
 
-    for( int i=0; papszArgv[i] != NULL; i++ )
+    for( int i = 0; papszArgv[i] != NULL; i++ )
     {
-        if (i > 0)
+        if( i > 0 )
             osCommandLine += " ";
-        /* We need to quote arguments with spaces in them (if not already done) */
+        // We need to quote arguments with spaces in them (if not already done).
         if( strchr(papszArgv[i], ' ') != NULL &&
             papszArgv[i][0] != '"' )
         {
@@ -361,26 +322,28 @@ CPLSpawnedProcess* CPLSpawnAsync(CPL_UNUSED int (*pfnMain)(CPL_FILE_HANDLE, CPL_
             osCommandLine += "\"";
         }
         else
+        {
             osCommandLine += papszArgv[i];
+        }
     }
 
-    if (!CreateProcess(NULL,
+    if( !CreateProcess(NULL,
                        (CHAR*)osCommandLine.c_str(),
-                       NULL,          // process security attributes
-                       NULL,          // primary thread security attributes
-                       TRUE,          // handles are inherited
-                       CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS,             // creation flags
-                       NULL,          // use parent's environment
-                       NULL,          // use parent's current directory
+                       NULL,          // Process security attributes
+                       NULL,          // Primary thread security attributes
+                       TRUE,          // Handles are inherited
+                       CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS, // Creation flags
+                       NULL,          // Use parent's environment
+                       NULL,          // Use parent's current directory
                        &siStartInfo,
-                       &piProcInfo))
+                       &piProcInfo) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Could not create process %s",
                  osCommandLine.c_str());
         goto err;
     }
 
-    /* Close unused end of pipe */
+    // Close unused end of pipe.
     if( bCreateInputPipe )
         CloseHandle(pipe_in[IN_FOR_PARENT]);
     if( bCreateOutputPipe )
@@ -388,25 +351,29 @@ CPLSpawnedProcess* CPLSpawnAsync(CPL_UNUSED int (*pfnMain)(CPL_FILE_HANDLE, CPL_
     if( bCreateErrorPipe )
         CloseHandle(pipe_err[OUT_FOR_PARENT]);
 
-    p = (CPLSpawnedProcess*)CPLMalloc(sizeof(CPLSpawnedProcess));
-    p->hProcess = piProcInfo.hProcess;
-    p->nProcessId = piProcInfo.dwProcessId;
-    p->hThread = piProcInfo.hThread;
-    p->fin = pipe_out[IN_FOR_PARENT];
-    p->fout = pipe_in[OUT_FOR_PARENT];
-    p->ferr = pipe_err[IN_FOR_PARENT];
-    return p;
+    {
+        CPLSpawnedProcess* p = static_cast<CPLSpawnedProcess *>(
+            CPLMalloc(sizeof(CPLSpawnedProcess)));
+        p->hProcess = piProcInfo.hProcess;
+        p->nProcessId = piProcInfo.dwProcessId;
+        p->hThread = piProcInfo.hThread;
+        p->fin = pipe_out[IN_FOR_PARENT];
+        p->fout = pipe_in[OUT_FOR_PARENT];
+        p->ferr = pipe_err[IN_FOR_PARENT];
+
+        return p;
+    }
 
 err_pipe:
     CPLError(CE_Failure, CPLE_AppDefined, "Could not create pipe");
 err:
-    for( int i=0; i < 2; i++ )
+    for( int i = 0; i < 2; i++ )
     {
-        if (pipe_in[i] != NULL)
+        if( pipe_in[i] != NULL )
             CloseHandle(pipe_in[i]);
-        if (pipe_out[i] != NULL)
+        if( pipe_out[i] != NULL )
             CloseHandle(pipe_out[i]);
-        if (pipe_err[i] != NULL)
+        if( pipe_err[i] != NULL )
             CloseHandle(pipe_err[i]);
     }
 
@@ -426,7 +393,7 @@ CPL_PID CPLSpawnAsyncGetChildProcessId(CPLSpawnedProcess* p)
 /*                        CPLSpawnAsyncFinish()                         */
 /************************************************************************/
 
-int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, CPL_UNUSED int bKill)
+int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, int /* bKill */ )
 {
     // Get the exit code.
     DWORD exitCode = -1;
@@ -437,7 +404,9 @@ int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, CPL_UNUSED int bKill)
         GetExitCodeProcess(p->hProcess, &exitCode);
     }
     else
+    {
         exitCode = 0;
+    }
 
     CloseHandle(p->hProcess);
     CloseHandle(p->hThread);
@@ -447,7 +416,7 @@ int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, CPL_UNUSED int bKill)
     CPLSpawnAsyncCloseErrorFileHandle(p);
     CPLFree(p);
 
-    return (int)exitCode;
+    return static_cast<int>(exitCode);
 }
 
 /************************************************************************/
@@ -485,35 +454,6 @@ void CPLSpawnAsyncCloseErrorFileHandle(CPLSpawnedProcess* p)
 
 #else  // Not WIN32
 
-#if 0
-/************************************************************************/
-/*                            CPLSystem()                               */
-/************************************************************************/
-
-/**
- * Runs an executable in another process.
- *
- * This function runs an executable, wait for it to finish and returns
- * its exit code.
- *
- * It is implemented as CreateProcess() on Windows platforms, and system()
- * on other platforms.
- *
- * @param pszApplicationName the lpApplicationName for Windows (might be NULL),
- *                           or ignored on other platforms.
- * @param pszCommandLine the command line, starting with the executable name
- *
- * @return the exit code of the spawned process, or -1 in case of error.
- *
- * @since GDAL 1.10.0
- */
-
-int CPLSystem( const char* pszApplicationName, const char* pszCommandLine )
-{
-    return system(pszCommandLine);
-}
-#endif
-
 /************************************************************************/
 /*                          CPLPipeRead()                               */
 /************************************************************************/
@@ -521,7 +461,7 @@ int CPLSystem( const char* pszApplicationName, const char* pszCommandLine )
 /**
  * Read data from the standard output of a forked process.
  *
- * @param p handle returned by CPLSpawnAsyncGetInputFileHandle().
+ * @param fin handle returned by CPLSpawnAsyncGetInputFileHandle().
  * @param data buffer in which to write.
  * @param length number of bytes to read.
  *
@@ -529,13 +469,13 @@ int CPLSystem( const char* pszApplicationName, const char* pszCommandLine )
  *
  * @since GDAL 1.10.0
  */
-int CPLPipeRead(CPL_FILE_HANDLE fin, void* data, int length)
+int CPLPipeRead( CPL_FILE_HANDLE fin, void* data, int length )
 {
-    GByte* pabyData = reinterpret_cast<GByte*>( data );
+    GByte* pabyData = static_cast<GByte*>( data );
     int nRemain = length;
     while( nRemain > 0 )
     {
-        while(true)
+        while( true )
         {
             const int n = static_cast<int>(read(fin, pabyData, nRemain));
             if( n < 0 )
@@ -570,13 +510,13 @@ int CPLPipeRead(CPL_FILE_HANDLE fin, void* data, int length)
  *
  * @since GDAL 1.10.0
  */
-int CPLPipeWrite(CPL_FILE_HANDLE fout, const void* data, int length)
+int CPLPipeWrite( CPL_FILE_HANDLE fout, const void* data, int length )
 {
-    const GByte* pabyData = reinterpret_cast<const GByte*>( data );
+    const GByte* pabyData = static_cast<const GByte*>( data );
     int nRemain = length;
     while( nRemain > 0 )
     {
-        while(true)
+        while( true )
         {
             const int n = static_cast<int>(write(fout, pabyData, nRemain));
             if( n < 0 )
@@ -598,17 +538,18 @@ int CPLPipeWrite(CPL_FILE_HANDLE fout, const void* data, int length)
 /*                          FillFileFromPipe()                              */
 /************************************************************************/
 
-static void FillFileFromPipe(CPL_FILE_HANDLE pipe_fd, VSILFILE* fout)
+static void FillFileFromPipe( CPL_FILE_HANDLE pipe_fd, VSILFILE* fout )
 {
-    char buf[PIPE_BUFFER_SIZE];
-    while(true)
+    char buf[PIPE_BUFFER_SIZE] = {};
+    while( true )
     {
-        const int nRead = static_cast<int>(read(pipe_fd, buf, PIPE_BUFFER_SIZE));
-        if (nRead <= 0)
+        const int nRead =
+            static_cast<int>(read(pipe_fd, buf, PIPE_BUFFER_SIZE));
+        if( nRead <= 0 )
             break;
         const int nWritten = static_cast<int>(
             VSIFWriteL(buf, 1, nRead, fout) );
-        if (nWritten < nRead)
+        if( nWritten < nRead )
             break;
     }
 }
@@ -624,7 +565,7 @@ struct _CPLSpawnedProcess
     CPL_FILE_HANDLE fout;
     CPL_FILE_HANDLE ferr;
 #ifdef HAVE_POSIX_SPAWNP
-    int bFreeActions;
+    bool bFreeActions;
     posix_spawn_file_actions_t actions;
 #endif
 };
@@ -645,45 +586,51 @@ struct _CPLSpawnedProcess
  * @param pfnMain the function to run in the child process (Unix only).
  * @param papszArgv argument list of the executable to run. papszArgv[0] is the
  *                  name of the executable.
- * @param bCreateInputPipe set to TRUE to create a pipe for the child input stream.
- * @param bCreateOutputPipe set to TRUE to create a pipe for the child output stream.
- * @param bCreateErrorPipe set to TRUE to create a pipe for the child error stream.
+ * @param bCreateInputPipe set to TRUE to create a pipe for the child
+ * input stream.
+ * @param bCreateOutputPipe set to TRUE to create a pipe for the child
+ * output stream.
+ * @param bCreateErrorPipe set to TRUE to create a pipe for the child
+ * error stream.
+
  *
  * @return a handle, that must be freed with CPLSpawnAsyncFinish()
  *
  * @since GDAL 1.10.0
  */
-CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE),
-                                 const char * const papszArgv[],
-                                 int bCreateInputPipe,
-                                 int bCreateOutputPipe,
-                                 int bCreateErrorPipe,
-                                 CPL_UNUSED char** papszOptions)
+CPLSpawnedProcess* CPLSpawnAsync( int (*pfnMain)(CPL_FILE_HANDLE,
+                                                 CPL_FILE_HANDLE),
+                                  const char * const papszArgv[],
+                                  int bCreateInputPipe,
+                                  int bCreateOutputPipe,
+                                  int bCreateErrorPipe,
+                                  char** /* papszOptions */ )
 {
     int pipe_in[2] = { -1, -1 };
     int pipe_out[2] = { -1, -1 };
     int pipe_err[2] = { -1, -1 };
-    bool bDup2In = CPL_TO_BOOL(bCreateInputPipe);
-    bool bDup2Out = CPL_TO_BOOL(bCreateOutputPipe);
-    bool bDup2Err = CPL_TO_BOOL(bCreateErrorPipe);
 
-    if ((bCreateInputPipe && pipe(pipe_in)) ||
+    if( (bCreateInputPipe && pipe(pipe_in)) ||
         (bCreateOutputPipe && pipe(pipe_out)) ||
-        (bCreateErrorPipe && pipe(pipe_err)))
+        (bCreateErrorPipe && pipe(pipe_err)) )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Could not create pipe");
         return NULL;
     }
 
+    bool bDup2In = CPL_TO_BOOL(bCreateInputPipe);
+    bool bDup2Out = CPL_TO_BOOL(bCreateOutputPipe);
+    bool bDup2Err = CPL_TO_BOOL(bCreateErrorPipe);
+
     char** papszArgvDup = CSLDuplicate( const_cast<char **>( papszArgv ) );
 
-    /* If we don't do any file actions, posix_spawnp() might be implemented */
-    /* efficiently as a vfork()/exec() pair (or if it is not available, we */
-    /* can use vfork()/exec()), so if the child is cooperative */
-    /* we pass the pipe handles as commandline arguments */
+    // If we don't do any file actions, posix_spawnp() might be implemented
+    // efficiently as a vfork()/exec() pair (or if it is not available, we
+    // can use vfork()/exec()), so if the child is cooperative
+    // we pass the pipe handles as commandline arguments.
     if( papszArgv != NULL )
     {
-        for( int i=0; papszArgvDup[i] != NULL; i++ )
+        for( int i = 0; papszArgvDup[i] != NULL; i++ )
         {
             if( bCreateInputPipe && strcmp(papszArgvDup[i], "{pipe_in}") == 0 )
             {
@@ -692,14 +639,16 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
                     pipe_in[IN_FOR_PARENT], pipe_in[OUT_FOR_PARENT]));
                 bDup2In = false;
             }
-            else if( bCreateOutputPipe && strcmp(papszArgvDup[i], "{pipe_out}") == 0 )
+            else if( bCreateOutputPipe &&
+                     strcmp(papszArgvDup[i], "{pipe_out}") == 0 )
             {
                 CPLFree(papszArgvDup[i]);
                 papszArgvDup[i] = CPLStrdup(CPLSPrintf("%d,%d",
                     pipe_out[OUT_FOR_PARENT], pipe_out[IN_FOR_PARENT]));
                 bDup2Out = false;
             }
-            else if( bCreateErrorPipe && strcmp(papszArgvDup[i], "{pipe_err}") == 0 )
+            else if( bCreateErrorPipe &&
+                     strcmp(papszArgvDup[i], "{pipe_err}") == 0 )
             {
                 CPLFree(papszArgvDup[i]);
                 papszArgvDup[i] = CPLStrdup(CPLSPrintf("%d,%d",
@@ -718,43 +667,60 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
         if( bDup2In )
         {
             if( !bHasActions ) posix_spawn_file_actions_init(&actions);
-            posix_spawn_file_actions_adddup2(&actions, pipe_in[IN_FOR_PARENT], fileno(stdin));
-            posix_spawn_file_actions_addclose(&actions, pipe_in[OUT_FOR_PARENT]);
+            posix_spawn_file_actions_adddup2(&actions, pipe_in[IN_FOR_PARENT],
+                                             fileno(stdin));
+            posix_spawn_file_actions_addclose(&actions,
+                                              pipe_in[OUT_FOR_PARENT]);
             bHasActions = true;
         }
 
         if( bDup2Out )
         {
             if( !bHasActions ) posix_spawn_file_actions_init(&actions);
-            posix_spawn_file_actions_adddup2(&actions, pipe_out[OUT_FOR_PARENT], fileno(stdout));
-            posix_spawn_file_actions_addclose(&actions, pipe_out[IN_FOR_PARENT]);
+            posix_spawn_file_actions_adddup2(&actions, pipe_out[OUT_FOR_PARENT],
+                                             fileno(stdout));
+            posix_spawn_file_actions_addclose(&actions,
+                                              pipe_out[IN_FOR_PARENT]);
             bHasActions = true;
         }
 
         if( bDup2Err )
         {
             if( !bHasActions ) posix_spawn_file_actions_init(&actions);
-            posix_spawn_file_actions_adddup2(&actions, pipe_err[OUT_FOR_PARENT], fileno(stderr));
-            posix_spawn_file_actions_addclose(&actions, pipe_err[IN_FOR_PARENT]);
+            posix_spawn_file_actions_adddup2(&actions, pipe_err[OUT_FOR_PARENT],
+                                             fileno(stderr));
+            posix_spawn_file_actions_addclose(&actions,
+                                              pipe_err[IN_FOR_PARENT]);
             bHasActions = true;
         }
 
-        pid_t pid;
+        pid_t pid = 0;
         if( posix_spawnp(&pid, papszArgvDup[0],
                          bHasActions ? &actions : NULL,
                          NULL,
-                         reinterpret_cast<char* const*>( papszArgvDup ),
+                         papszArgvDup,
                          environ) != 0 )
         {
             if( bHasActions )
                 posix_spawn_file_actions_destroy(&actions);
             CPLError(CE_Failure, CPLE_AppDefined, "posix_spawnp() failed");
-            goto err;
+            CSLDestroy(papszArgvDup);
+            for( int i = 0; i < 2; i++ )
+            {
+                if( pipe_in[i] >= 0 )
+                    close(pipe_in[i]);
+                if( pipe_out[i] >= 0 )
+                    close(pipe_out[i]);
+                if( pipe_err[i] >= 0 )
+                    close(pipe_err[i]);
+            }
+
+            return NULL;
         }
 
         CSLDestroy(papszArgvDup);
 
-        /* Close unused end of pipe */
+        // Close unused end of pipe.
         if( bCreateInputPipe )
             close(pipe_in[IN_FOR_PARENT]);
         if( bCreateOutputPipe )
@@ -762,7 +728,7 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
         if( bCreateErrorPipe )
             close(pipe_err[OUT_FOR_PARENT]);
 
-        /* Ignore SIGPIPE */
+        // Ignore SIGPIPE.
     #ifdef SIGPIPE
         std::signal( SIGPIPE, SIG_IGN );
     #endif
@@ -779,21 +745,24 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
     }
 #endif // #ifdef HAVE_POSIX_SPAWNP
 
-    pid_t pid;
-#ifdef HAVE_VFORK
-    /* coverity[dead_error_line] */
+    pid_t pid = 0;
+
+#if defined(HAVE_VFORK) && !defined(HAVE_POSIX_SPAWNP)
     if( papszArgv != NULL && !bDup2In && !bDup2Out && !bDup2Err )
     {
-        /* Workaround clang static analyzer warning about unsafe use of vfork */
+        // Workaround clang static analyzer warning about unsafe use of vfork.
         pid_t (*p_vfork)(void) = vfork;
         pid = p_vfork();
     }
     else
 #endif
+    {
         pid = fork();
-    if (pid == 0)
+    }
+
+    if( pid == 0 )
     {
-        /* Close unused end of pipe */
+        // Close unused end of pipe.
         if( bDup2In )
             close(pipe_in[OUT_FOR_PARENT]);
         if( bDup2Out )
@@ -811,7 +780,7 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
             if( bDup2Err )
                 dup2(pipe_err[OUT_FOR_PARENT], fileno(stderr));
 
-            execvp(papszArgvDup[0], (char* const*) papszArgvDup);
+            execvp(papszArgvDup[0], papszArgvDup);
 
             _exit(1);
         }
@@ -822,9 +791,11 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
                 close(pipe_err[OUT_FOR_PARENT]);
 
             int nRet = 0;
-            if (pfnMain != NULL)
-                nRet = pfnMain((bCreateInputPipe) ? pipe_in[IN_FOR_PARENT] : fileno(stdin),
-                               (bCreateOutputPipe) ? pipe_out[OUT_FOR_PARENT] : fileno(stdout));
+            if( pfnMain != NULL )
+                nRet = pfnMain(
+                    bCreateInputPipe ? pipe_in[IN_FOR_PARENT] : fileno(stdin),
+                    bCreateOutputPipe ?
+                    pipe_out[OUT_FOR_PARENT] : fileno(stdout));
             _exit(nRet);
         }
     }
@@ -832,7 +803,7 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
     {
         CSLDestroy(papszArgvDup);
 
-        /* Close unused end of pipe */
+        // Close unused end of pipe.
         if( bCreateInputPipe )
             close(pipe_in[IN_FOR_PARENT]);
         if( bCreateOutputPipe )
@@ -840,14 +811,14 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
         if( bCreateErrorPipe )
             close(pipe_err[OUT_FOR_PARENT]);
 
-        /* Ignore SIGPIPE */
+        // Ignore SIGPIPE.
 #ifdef SIGPIPE
         std::signal( SIGPIPE, SIG_IGN );
 #endif
         CPLSpawnedProcess* p = static_cast<CPLSpawnedProcess *>(
             CPLMalloc( sizeof(CPLSpawnedProcess) ) );
 #ifdef HAVE_POSIX_SPAWNP
-        p->bFreeActions = FALSE;
+        p->bFreeActions = false;
 #endif
         p->pid = pid;
         p->fin = pipe_out[IN_FOR_PARENT];
@@ -855,21 +826,17 @@ CPLSpawnedProcess* CPLSpawnAsync(int (*pfnMain)(CPL_FILE_HANDLE, CPL_FILE_HANDLE
         p->ferr = pipe_err[IN_FOR_PARENT];
         return p;
     }
-    else
-    {
-        CPLError(CE_Failure, CPLE_AppDefined, "Fork failed");
-        goto err;
-    }
 
-err:
+    CPLError(CE_Failure, CPLE_AppDefined, "Fork failed");
+
     CSLDestroy(papszArgvDup);
     for( int i = 0; i < 2; i++ )
     {
-        if (pipe_in[i] >= 0)
+        if( pipe_in[i] >= 0 )
             close(pipe_in[i]);
-        if (pipe_out[i] >= 0)
+        if( pipe_out[i] >= 0 )
             close(pipe_out[i]);
-        if (pipe_err[i] >= 0)
+        if( pipe_err[i] >= 0 )
             close(pipe_err[i]);
     }
 
@@ -880,7 +847,7 @@ err:
 /*                  CPLSpawnAsyncGetChildProcessId()                    */
 /************************************************************************/
 
-CPL_PID CPLSpawnAsyncGetChildProcessId(CPLSpawnedProcess* p)
+CPL_PID CPLSpawnAsyncGetChildProcessId( CPLSpawnedProcess* p )
 {
     return p->pid;
 }
@@ -890,36 +857,42 @@ CPL_PID CPLSpawnAsyncGetChildProcessId(CPLSpawnedProcess* p)
 /************************************************************************/
 
 /**
+ * \fn CPLSpawnAsyncFinish(CPLSpawnedProcess*,int,int)
  * Wait for the forked process to finish.
  *
  * @param p handle returned by CPLSpawnAsync()
- * @param bWait set to TRUE to wait for the child to terminate. Otherwise the associated
- *              handles are just cleaned.
- * @param bKill set to TRUE to force child termination (unimplemented right now).
+ * @param bWait set to TRUE to wait for the child to terminate. Otherwise the
+ *              associated handles are just cleaned.
+ * @param bKill set to TRUE to force child termination (unimplemented right
+ *              now).
  *
  * @return the return code of the forked process if bWait == TRUE, 0 otherwise
  *
  * @since GDAL 1.10.0
  */
-int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, CPL_UNUSED int bKill)
+
+int CPLSpawnAsyncFinish( CPLSpawnedProcess* p, int bWait,
+                         CPL_UNUSED int bKill )
 {
     int status = 0;
 
     if( bWait )
     {
-        while(1)
+        while( true )
         {
             status = -1;
             const int ret = waitpid (p->pid, &status, 0);
-            if (ret < 0)
+            if( ret < 0 )
             {
-                if (errno != EINTR)
+                if( errno != EINTR )
                 {
                     break;
                 }
             }
             else
+            {
                 break;
+            }
         }
     }
 
@@ -938,7 +911,7 @@ int CPLSpawnAsyncFinish(CPLSpawnedProcess* p, int bWait, CPL_UNUSED int bKill)
 /*                 CPLSpawnAsyncCloseInputFileHandle()                  */
 /************************************************************************/
 
-void CPLSpawnAsyncCloseInputFileHandle(CPLSpawnedProcess* p)
+void CPLSpawnAsyncCloseInputFileHandle( CPLSpawnedProcess* p )
 {
     if( p->fin >= 0 )
         close(p->fin);
@@ -949,7 +922,7 @@ void CPLSpawnAsyncCloseInputFileHandle(CPLSpawnedProcess* p)
 /*                 CPLSpawnAsyncCloseOutputFileHandle()                 */
 /************************************************************************/
 
-void CPLSpawnAsyncCloseOutputFileHandle(CPLSpawnedProcess* p)
+void CPLSpawnAsyncCloseOutputFileHandle( CPLSpawnedProcess* p )
 {
     if( p->fout >= 0 )
         close(p->fout);
@@ -960,7 +933,7 @@ void CPLSpawnAsyncCloseOutputFileHandle(CPLSpawnedProcess* p)
 /*                 CPLSpawnAsyncCloseErrorFileHandle()                  */
 /************************************************************************/
 
-void CPLSpawnAsyncCloseErrorFileHandle(CPLSpawnedProcess* p)
+void CPLSpawnAsyncCloseErrorFileHandle( CPLSpawnedProcess* p )
 {
     if( p->ferr >= 0 )
         close(p->ferr);
@@ -983,7 +956,7 @@ void CPLSpawnAsyncCloseErrorFileHandle(CPLSpawnedProcess* p)
  *
  * @since GDAL 1.10.0
  */
-CPL_FILE_HANDLE CPLSpawnAsyncGetInputFileHandle(CPLSpawnedProcess* p)
+CPL_FILE_HANDLE CPLSpawnAsyncGetInputFileHandle( CPLSpawnedProcess* p )
 {
     return p->fin;
 }
@@ -1002,7 +975,7 @@ CPL_FILE_HANDLE CPLSpawnAsyncGetInputFileHandle(CPLSpawnedProcess* p)
  *
  * @since GDAL 1.10.0
  */
-CPL_FILE_HANDLE CPLSpawnAsyncGetOutputFileHandle(CPLSpawnedProcess* p)
+CPL_FILE_HANDLE CPLSpawnAsyncGetOutputFileHandle( CPLSpawnedProcess* p )
 {
     return p->fout;
 }
@@ -1021,7 +994,7 @@ CPL_FILE_HANDLE CPLSpawnAsyncGetOutputFileHandle(CPLSpawnedProcess* p)
  *
  * @since GDAL 1.10.0
  */
-CPL_FILE_HANDLE CPLSpawnAsyncGetErrorFileHandle(CPLSpawnedProcess* p)
+CPL_FILE_HANDLE CPLSpawnAsyncGetErrorFileHandle( CPLSpawnedProcess* p )
 {
     return p->ferr;
 }
diff --git a/port/cpl_string.cpp b/port/cpl_string.cpp
index b095042..aee5c88 100644
--- a/port/cpl_string.cpp
+++ b/port/cpl_string.cpp
@@ -1,6 +1,4 @@
-
 /**********************************************************************
- * $Id: cpl_string.cpp 33960 2016-04-13 08:51:33Z rouault $
  *
  * Name:     cpl_string.cpp
  * Project:  CPL - Common Portability Library
@@ -49,11 +47,19 @@
 
 #undef WARN_STANDARD_PRINTF
 
-#include "cpl_multiproc.h"
+#include "cpl_port.h"
 #include "cpl_string.h"
+
+#include <cctype>
+#include <climits>
+#include <cstdlib>
+#include <cstring>
+
+#include "cpl_config.h"
+#include "cpl_multiproc.h"
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_string.cpp 33960 2016-04-13 08:51:33Z rouault $");
+CPL_CVSID("$Id: cpl_string.cpp 37457 2017-02-25 18:57:53Z rouault $");
 
 /*=====================================================================
                     StringList manipulation functions.
@@ -61,14 +67,16 @@ CPL_CVSID("$Id: cpl_string.cpp 33960 2016-04-13 08:51:33Z rouault $");
 
 /**********************************************************************
  *                       CSLAddString()
- *
- * Append a string to a StringList and return a pointer to the modified
+ **********************************************************************/
+
+/** Append a string to a StringList and return a pointer to the modified
  * StringList.
+ *
  * If the input StringList is NULL, then a new StringList is created.
  * Note that CSLAddString performance when building a list is in O(n^2)
  * which can cause noticeable slow down when n > 10000.
- **********************************************************************/
-char **CSLAddString(char **papszStrList, const char *pszNewString)
+ */
+char **CSLAddString( char **papszStrList, const char *pszNewString )
 {
     char** papszRet = CSLAddStringMayFail(papszStrList, pszNewString);
     if( papszRet == NULL && pszNewString != NULL )
@@ -76,20 +84,21 @@ char **CSLAddString(char **papszStrList, const char *pszNewString)
     return papszRet;
 }
 
-char **CSLAddStringMayFail(char **papszStrList, const char *pszNewString)
+/** Same as CSLAddString() but may return NULL in case of (memory) failure */
+char **CSLAddStringMayFail( char **papszStrList, const char *pszNewString )
 {
-    if (pszNewString == NULL)
-        return papszStrList;    /* Nothing to do!*/
+    if( pszNewString == NULL )
+        return papszStrList;  // Nothing to do!
 
     char* pszDup = VSI_STRDUP_VERBOSE(pszNewString);
     if( pszDup == NULL )
         return NULL;
 
-    /* Allocate room for the new string */
+    // Allocate room for the new string.
     char** papszStrListNew = NULL;
     int nItems = 0;
 
-    if (papszStrList == NULL)
+    if( papszStrList == NULL )
         papszStrListNew = static_cast<char**>(
             VSI_CALLOC_VERBOSE( 2, sizeof(char*) ) );
     else
@@ -104,7 +113,7 @@ char **CSLAddStringMayFail(char **papszStrList, const char *pszNewString)
         return NULL;
     }
 
-    /* Copy the string in the list */
+    // Copy the string in the list.
     papszStrListNew[nItems] = pszDup;
     papszStrListNew[nItems+1] = NULL;
 
@@ -131,14 +140,14 @@ char **CSLAddStringMayFail(char **papszStrList, const char *pszNewString)
  *
  * @return the number of entries.
  */
-int CSLCount(const char * const *papszStrList)
+int CSLCount( const char * const *papszStrList )
 {
-    if (!papszStrList)
+    if( !papszStrList )
         return 0;
 
-    int nItems=0;
+    int nItems = 0;
 
-    while(*papszStrList != NULL)
+    while( *papszStrList != NULL )
     {
         ++nItems;
         ++papszStrList;
@@ -149,13 +158,14 @@ int CSLCount(const char * const *papszStrList)
 
 /************************************************************************/
 /*                            CSLGetField()                             */
-/*                                                                      */
-/*      Fetches the indicated field, being careful not to crash if      */
-/*      the field doesn't exist within this string list.  The           */
-/*      returned pointer should not be freed, and doesn't               */
-/*      necessarily last long.                                          */
 /************************************************************************/
 
+/**
+ * Fetches the indicated field, being careful not to crash if the field
+ * doesn't exist within this string list.
+ *
+ * The returned pointer should not be freed, and doesn't necessarily last long.
+ */
 const char *CSLGetField( char ** papszStrList, int iField )
 
 {
@@ -183,9 +193,9 @@ const char *CSLGetField( char ** papszStrList, int iField )
  *
  * @param papszStrList the list to free.
  */
-void CPL_STDCALL CSLDestroy(char **papszStrList)
+void CPL_STDCALL CSLDestroy( char **papszStrList )
 {
-    if (!papszStrList)
+    if( !papszStrList )
         return;
 
     for( char **papszPtr = papszStrList; *papszPtr != NULL; ++papszPtr )
@@ -211,16 +221,16 @@ void CPL_STDCALL CSLDestroy(char **papszStrList)
  * @return newly allocated copy.
  */
 
-char **CSLDuplicate(char **papszStrList)
+char **CSLDuplicate( char **papszStrList )
 {
     const int nLines = CSLCount(papszStrList);
 
-    if (nLines == 0)
+    if( nLines == 0 )
         return NULL;
 
     char **papszSrc = papszStrList;
 
-    char **papszNewList = static_cast<char**>(
+    char **papszNewList = static_cast<char **>(
         CPLMalloc( (nLines + 1) * sizeof(char*) ) );
 
     char **papszDst = papszNewList;
@@ -287,26 +297,29 @@ char **CSLMerge( char **papszOrig, char **papszOverride )
  * If reading the file fails a CPLError() will be issued and NULL returned.
  *
  * @param pszFname the name of the file to read.
- * @param nMaxLines maximum number of lines to read before stopping, or -1 for no limit.
- * @param nMaxCols  maximum number of characters in a line before stopping, or -1 for no limit.
+ * @param nMaxLines maximum number of lines to read before stopping, or -1 for
+ * no limit.
+ * @param nMaxCols maximum number of characters in a line before stopping, or -1
+ * for no limit.
  * @param papszOptions NULL-terminated array of options. Unused for now.
  *
- * @return a string list with the files lines, now owned by caller. To be freed with CSLDestroy()
+ * @return a string list with the files lines, now owned by caller. To be freed
+ * with CSLDestroy()
  *
  * @since GDAL 1.7.0
  */
 
 char **CSLLoad2( const char *pszFname, int nMaxLines, int nMaxCols,
-                 char** papszOptions )
+                 const char * const * papszOptions )
 {
     VSILFILE *fp = VSIFOpenL(pszFname, "rb");
 
-    if (!fp)
+    if( !fp )
     {
-        if( CSLFetchBoolean( papszOptions, "EMIT_ERROR_IF_CANNOT_OPEN_FILE",
-                             TRUE ) )
+        if( CPLFetchBool( papszOptions, "EMIT_ERROR_IF_CANNOT_OPEN_FILE",
+                          true ) )
         {
-            /* Unable to open file */
+            // Unable to open file.
             CPLError( CE_Failure, CPLE_OpenFailed,
                     "CSLLoad2(\"%s\") failed: unable to open file.",
                     pszFname );
@@ -314,29 +327,30 @@ char **CSLLoad2( const char *pszFname, int nMaxLines, int nMaxCols,
         return NULL;
     }
 
-    char        **papszStrList=NULL;
-    int          nLines = 0;
-    int          nAllocatedLines = 0;
+    char **papszStrList=NULL;
+    int nLines = 0;
+    int nAllocatedLines = 0;
 
     CPLErrorReset();
-    while(!VSIFEofL(fp) && (nMaxLines == -1 || nLines < nMaxLines))
+    while( !VSIFEofL(fp) && (nMaxLines == -1 || nLines < nMaxLines) )
     {
-        const char  *pszLine = CPLReadLine2L(fp, nMaxCols, papszOptions);
-        if (pszLine == NULL)
+        const char *pszLine = CPLReadLine2L(fp, nMaxCols, papszOptions);
+        if( pszLine == NULL )
             break;
 
-        if (nLines + 1 >= nAllocatedLines)
+        if( nLines + 1 >= nAllocatedLines )
         {
             nAllocatedLines = 16 + nAllocatedLines * 2;
-            char** papszStrListNew
-                = static_cast<char**>(
+            char** papszStrListNew =
+                static_cast<char**>(
                     VSIRealloc( papszStrList,
                                 nAllocatedLines * sizeof(char*) ) );
-            if (papszStrListNew == NULL)
+            if( papszStrListNew == NULL )
             {
                 CPL_IGNORE_RET_VAL( VSIFCloseL(fp) );
                 CPLReadLineL( NULL );
-                CPLError( CE_Failure, CPLE_OutOfMemory,  "CSLLoad2(\"%s\") "
+                CPLError( CE_Failure, CPLE_OutOfMemory,
+                          "CSLLoad2(\"%s\") "
                           "failed: not enough memory to allocate lines.",
                           pszFname );
                 return papszStrList;
@@ -376,26 +390,28 @@ char **CSLLoad2( const char *pszFname, int nMaxLines, int nMaxCols,
  * with CSLDestroy()
  */
 
-char **CSLLoad(const char *pszFname)
+char **CSLLoad( const char *pszFname )
 {
     return CSLLoad2(pszFname, -1, -1, NULL);
 }
 
 /**********************************************************************
  *                       CSLSave()
- *
- * Write a StringList to a text file.
+ **********************************************************************/
+
+/** Write a StringList to a text file.
  *
  * Returns the number of lines written, or 0 if the file could not
  * be written.
- **********************************************************************/
-int CSLSave(char **papszStrList, const char *pszFname)
+ */
+
+int CSLSave( char **papszStrList, const char *pszFname )
 {
     if( papszStrList == NULL )
         return 0;
 
     VSILFILE *fp = VSIFOpenL( pszFname, "wt" );
-    if (fp == NULL)
+    if( fp == NULL )
     {
         // Unable to open file.
         CPLError( CE_Failure, CPLE_OpenFailed,
@@ -431,23 +447,24 @@ int CSLSave(char **papszStrList, const char *pszFname)
 
 /**********************************************************************
  *                       CSLPrint()
- *
- * Print a StringList to fpOut.  If fpOut==NULL, then output is sent
+ **********************************************************************/
+
+/** Print a StringList to fpOut.  If fpOut==NULL, then output is sent
  * to stdout.
  *
  * Returns the number of lines printed.
- **********************************************************************/
+ */
 int CSLPrint( char **papszStrList, FILE *fpOut )
 {
-    if (!papszStrList)
+    if( !papszStrList )
         return 0;
 
-    if (fpOut == NULL)
+    if( fpOut == NULL )
         fpOut = stdout;
 
-    int nLines=0;
+    int nLines = 0;
 
-    while(*papszStrList != NULL)
+    while( *papszStrList != NULL )
     {
         if( VSIFPrintf(fpOut, "%s\n", *papszStrList) < 0 )
             return nLines;
@@ -460,8 +477,9 @@ int CSLPrint( char **papszStrList, FILE *fpOut )
 
 /**********************************************************************
  *                       CSLInsertStrings()
- *
- * Copies the contents of a StringList inside another StringList
+**********************************************************************/
+
+/** Copies the contents of a StringList inside another StringList
  * before the specified line.
  *
  * nInsertAtLineNo is a 0-based line index before which the new strings
@@ -470,9 +488,10 @@ int CSLPrint( char **papszStrList, FILE *fpOut )
  * of the source StringList.
  *
  * Returns the modified StringList.
- **********************************************************************/
-char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
-                        char **papszNewLines)
+ */
+
+char **CSLInsertStrings( char **papszStrList, int nInsertAtLineNo,
+                         char **papszNewLines )
 {
     if( papszNewLines == NULL )
         return papszStrList;  // Nothing to do!
@@ -484,37 +503,35 @@ char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
     const int nSrcLines = CSLCount(papszStrList);
     const int nDstLines = nSrcLines + nToInsert;
 
-    /* Allocate room for the new strings */
-    papszStrList = reinterpret_cast<char**>(
+    // Allocate room for the new strings.
+    papszStrList = static_cast<char**>(
         CPLRealloc( papszStrList, (nDstLines+1) * sizeof(char*) ) );
 
-    /* Make sure the array is NULL-terminated... it may not be if
-     * papszStrList was NULL before Realloc()
-     */
+    // Make sure the array is NULL-terminated.  It may not be if
+    // papszStrList was NULL before Realloc().
     papszStrList[nSrcLines] = NULL;
 
-    /* Make some room in the original list at the specified location
-     * Note that we also have to move the NULL pointer at the end of
-     * the source StringList.
-     */
-    if (nInsertAtLineNo == -1 || nInsertAtLineNo > nSrcLines)
+    // Make some room in the original list at the specified location.
+    // Note that we also have to move the NULL pointer at the end of
+    // the source StringList.
+    if( nInsertAtLineNo == -1 || nInsertAtLineNo > nSrcLines )
         nInsertAtLineNo = nSrcLines;
 
     char **ppszSrc = papszStrList + nSrcLines;
     char **ppszDst = papszStrList + nDstLines;
 
-    for (int i=nSrcLines; i>=nInsertAtLineNo; --i)
+    for( int i = nSrcLines; i >= nInsertAtLineNo; --i )
     {
         *ppszDst = *ppszSrc;
         --ppszDst;
         --ppszSrc;
     }
 
-    /* Copy the strings to the list */
+    // Copy the strings to the list.
     ppszSrc = papszNewLines;
     ppszDst = papszStrList + nInsertAtLineNo;
 
-    for (; *ppszSrc != NULL; ++ppszSrc, ++ppszDst)
+    for( ; *ppszSrc != NULL; ++ppszSrc, ++ppszDst )
     {
         *ppszDst = CPLStrdup(*ppszSrc);
     }
@@ -524,8 +541,9 @@ char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
 
 /**********************************************************************
  *                       CSLInsertString()
- *
- * Insert a string at a given line number inside a StringList
+ **********************************************************************/
+
+/** Insert a string at a given line number inside a StringList
  *
  * nInsertAtLineNo is a 0-based line index before which the new string
  * should be inserted.  If this value is -1 or is larger than the actual
@@ -533,19 +551,21 @@ char **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
  * of the source StringList.
  *
  * Returns the modified StringList.
- **********************************************************************/
-char **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
-                       const char *pszNewLine)
+ */
+
+char **CSLInsertString( char **papszStrList, int nInsertAtLineNo,
+                        const char *pszNewLine )
 {
-    char *apszList[2] = {const_cast<char *>(pszNewLine), NULL};
+    char *apszList[2] = { const_cast<char *>(pszNewLine), NULL };
 
     return CSLInsertStrings(papszStrList, nInsertAtLineNo, apszList);
 }
 
 /**********************************************************************
  *                       CSLRemoveStrings()
- *
- * Remove strings inside a StringList
+**********************************************************************/
+
+/** Remove strings inside a StringList
  *
  * nFirstLineToDelete is the 0-based line index of the first line to
  * remove. If this value is -1 or is larger than the actual
@@ -557,36 +577,34 @@ char **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
  * this new list will be returned in *ppapszRetStrings.
  *
  * Returns the modified StringList.
- **********************************************************************/
-char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
-                        int nNumToRemove, char ***ppapszRetStrings)
+ */
+
+char **CSLRemoveStrings( char **papszStrList, int nFirstLineToDelete,
+                         int nNumToRemove, char ***ppapszRetStrings )
 {
     const int nSrcLines = CSLCount(papszStrList);
 
-    if (nNumToRemove < 1 || nSrcLines == 0)
-        return papszStrList;    /* Nothing to do!*/
+    if( nNumToRemove < 1 || nSrcLines == 0 )
+      return papszStrList;  // Nothing to do!
 
-    /* If operation will result in an empty StringList then don't waste
-     * time here!
-     */
+    // If operation will result in an empty StringList, don't waste
+    // time here.
     const int nDstLines = nSrcLines - nNumToRemove;
-    if (nDstLines < 1)
+    if( nDstLines < 1 )
     {
         CSLDestroy(papszStrList);
         return NULL;
     }
 
-    /* Remove lines from the source StringList...
-     * Either free() each line or store them to a new StringList depending on
-     * the caller's choice.
-     */
+    // Remove lines from the source StringList.
+    // Either free() each line or store them to a new StringList depending on
+    // the caller's choice.
     char **ppszDst = papszStrList + nFirstLineToDelete;
 
-    if (ppapszRetStrings == NULL)
+    if( ppapszRetStrings == NULL )
     {
-        /* free() all the strings that will be removed.
-         */
-        for (int i=0; i < nNumToRemove; ++i)
+        // free() all the strings that will be removed.
+        for( int i = 0; i < nNumToRemove; ++i )
         {
             CPLFree(*ppszDst);
             *ppszDst = NULL;
@@ -594,12 +612,11 @@ char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
     }
     else
     {
-        /* Store the strings to remove in a new StringList
-         */
+        // Store the strings to remove in a new StringList.
         *ppapszRetStrings = static_cast<char **>(
             CPLCalloc( nNumToRemove+1, sizeof(char*) ) );
 
-        for (int i=0; i < nNumToRemove; ++i)
+        for( int i=0; i < nNumToRemove; ++i )
         {
             (*ppapszRetStrings)[i] = *ppszDst;
             *ppszDst = NULL;
@@ -607,26 +624,23 @@ char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
         }
     }
 
-    /* Shift down all the lines that follow the lines to remove.
-     */
-    if (nFirstLineToDelete == -1 || nFirstLineToDelete > nSrcLines)
+    // Shift down all the lines that follow the lines to remove.
+    if( nFirstLineToDelete == -1 || nFirstLineToDelete > nSrcLines )
         nFirstLineToDelete = nDstLines;
 
     char **ppszSrc = papszStrList + nFirstLineToDelete + nNumToRemove;
     ppszDst = papszStrList + nFirstLineToDelete;
 
-    for ( ; *ppszSrc != NULL; ++ppszSrc, ++ppszDst)
+    for( ; *ppszSrc != NULL; ++ppszSrc, ++ppszDst )
     {
         *ppszDst = *ppszSrc;
     }
-    /* Move the NULL pointer at the end of the StringList     */
+    // Move the NULL pointer at the end of the StringList.
     *ppszDst = *ppszSrc;
 
-    /* At this point, we could realloc() papszStrList to a smaller size, but
-     * since this array will likely grow again in further operations on the
-     * StringList we'll leave it as it is.
-     */
-
+    // At this point, we could realloc() papszStrList to a smaller size, but
+    // since this array will likely grow again in further operations on the
+    // StringList we'll leave it as it is.
     return papszStrList;
 }
 
@@ -647,7 +661,7 @@ char **CSLRemoveStrings(char **papszStrList, int nFirstLineToDelete,
  * @return the index of the string within the list or -1 on failure.
  */
 
-int CSLFindString( char ** papszList, const char * pszTarget )
+int CSLFindString( const char * const * papszList, const char * pszTarget )
 
 {
     if( papszList == NULL )
@@ -655,7 +669,7 @@ int CSLFindString( char ** papszList, const char * pszTarget )
 
     for( int i = 0; papszList[i] != NULL; ++i )
     {
-        if( EQUAL(papszList[i],pszTarget) )
+        if( EQUAL(papszList[i], pszTarget) )
             return i;
     }
 
@@ -681,7 +695,8 @@ int CSLFindString( char ** papszList, const char * pszTarget )
  * @since GDAL 2.0
  */
 
-int CSLFindStringCaseSensitive( char ** papszList, const char * pszTarget )
+int CSLFindStringCaseSensitive( const char * const * papszList,
+                                const char * pszTarget )
 
 {
     if( papszList == NULL )
@@ -689,7 +704,7 @@ int CSLFindStringCaseSensitive( char ** papszList, const char * pszTarget )
 
     for( int i = 0; papszList[i] != NULL; ++i )
     {
-        if( strcmp(papszList[i],pszTarget) == 0 )
+        if( strcmp(papszList[i], pszTarget) == 0 )
             return i;
     }
 
@@ -713,14 +728,15 @@ int CSLFindStringCaseSensitive( char ** papszList, const char * pszTarget )
  * @return the index of the string within the list or -1 on failure.
  */
 
-int CSLPartialFindString( char **papszHaystack, const char * pszNeedle )
+int CSLPartialFindString( const char * const *papszHaystack,
+                          const char * pszNeedle )
 {
-    if (papszHaystack == NULL || pszNeedle == NULL)
+    if( papszHaystack == NULL || pszNeedle == NULL )
         return -1;
 
-    for (int i = 0; papszHaystack[i] != NULL; ++i)
+    for( int i = 0; papszHaystack[i] != NULL; ++i )
     {
-        if (strstr(papszHaystack[i], pszNeedle))
+        if( strstr(papszHaystack[i], pszNeedle) )
             return i;
     }
 
@@ -729,10 +745,11 @@ int CSLPartialFindString( char **papszHaystack, const char * pszNeedle )
 
 /**********************************************************************
  *                       CSLTokenizeString()
- *
- * Tokenizes a string and returns a StringList with one string for
+**********************************************************************/
+
+/** Tokenizes a string and returns a StringList with one string for
  * each token.
- **********************************************************************/
+ */
 char **CSLTokenizeString( const char *pszString )
 {
     return CSLTokenizeString2( pszString, " ", CSLT_HONOURSTRINGS );
@@ -740,10 +757,9 @@ char **CSLTokenizeString( const char *pszString )
 
 /************************************************************************/
 /*                      CSLTokenizeStringComplex()                      */
-/*                                                                      */
-/*      Obsolete tokenizing api.                                        */
 /************************************************************************/
 
+/** Obsolete tokenizing api. Use CSLTokenizeString2() */
 char ** CSLTokenizeStringComplex( const char * pszString,
                                   const char * pszDelimiters,
                                   int bHonourStrings, int bAllowEmptyTokens )
@@ -799,7 +815,7 @@ char ** CSLTokenizeStringComplex( const char * pszString,
                             CSLT_HONOURSTRINGS | CSLT_ALLOWEMPTYTOKENS );
 
     for( int i = 0; papszTokens != NULL && papszTokens[i] != NULL; ++i )
-        printf( "arg %d: '%s'", papszTokens[i] );
+        printf( "arg %d: '%s'", papszTokens[i] );  // ok
 
     CSLDestroy( papszTokens );
 \endcode
@@ -817,7 +833,7 @@ char ** CSLTokenizeString2( const char * pszString,
 {
     if( pszString == NULL )
         return static_cast<char **>(
-            CPLCalloc(sizeof(char *),1));
+            CPLCalloc(sizeof(char *), 1));
 
     CPLStringList oRetList;
     const bool bHonourStrings = (nCSLTFlags & CSLT_HONOURSTRINGS) != 0;
@@ -825,7 +841,7 @@ char ** CSLTokenizeString2( const char * pszString,
     const bool bStripLeadSpaces = (nCSLTFlags & CSLT_STRIPLEADSPACES) != 0;
     const bool bStripEndSpaces = (nCSLTFlags & CSLT_STRIPENDSPACES) != 0;
 
-    char *pszToken = reinterpret_cast<char *>( CPLCalloc(10,1) );
+    char *pszToken = static_cast<char *>(CPLCalloc(10, 1));
     int nTokenMax = 10;
 
     while( *pszString != '\0' )
@@ -834,12 +850,10 @@ char ** CSLTokenizeString2( const char * pszString,
         bool bStartString = true;
         int nTokenLen = 0;
 
-        /* Try to find the next delimiter, marking end of token */
+        // Try to find the next delimiter, marking end of token.
         for( ; *pszString != '\0'; ++pszString )
         {
-            /*
-             * Extend token buffer if we are running close to its end.
-             */
+            // Extend token buffer if we are running close to its end.
             if( nTokenLen >= nTokenMax-3 )
             {
                 nTokenMax = nTokenMax * 2 + 10;
@@ -847,16 +861,16 @@ char ** CSLTokenizeString2( const char * pszString,
                     CPLRealloc( pszToken, nTokenMax ));
             }
 
-            /* End if this is a delimiter skip it and break. */
+            // End if this is a delimiter skip it and break.
             if( !bInString && strchr(pszDelimiters, *pszString) != NULL )
             {
                 ++pszString;
                 break;
             }
 
-            /* If this is a quote, and we are honouring constant
-               strings, then process the constant strings, with out delim
-               but don't copy over the quotes */
+            // If this is a quote, and we are honouring constant
+            // strings, then process the constant strings, with out delim
+            // but don't copy over the quotes.
             if( bHonourStrings && *pszString == '"' )
             {
                 if( nCSLTFlags & CSLT_PRESERVEQUOTES )
@@ -876,7 +890,7 @@ char ** CSLTokenizeString2( const char * pszString,
              */
             if( bInString && pszString[0] == '\\' )
             {
-                if ( pszString[1] == '"' || pszString[1] == '\\' )
+                if( pszString[1] == '"' || pszString[1] == '\\' )
                 {
                     if( nCSLTFlags & CSLT_PRESERVEESCAPES )
                     {
@@ -888,12 +902,10 @@ char ** CSLTokenizeString2( const char * pszString,
                 }
             }
 
-            /*
-             * Strip spaces at the token start if requested.
-             */
-            if ( !bInString && bStripLeadSpaces
-                 && bStartString
-                 && isspace(static_cast<unsigned char>( *pszString )) )
+            // Strip spaces at the token start if requested.
+            if( !bInString && bStripLeadSpaces
+                && bStartString
+                && isspace(static_cast<unsigned char>( *pszString )) )
                 continue;
 
             bStartString = false;
@@ -902,22 +914,18 @@ char ** CSLTokenizeString2( const char * pszString,
             ++nTokenLen;
         }
 
-        /*
-         * Strip spaces at the token end if requested.
-         */
-        if ( !bInString && bStripEndSpaces )
+        // Strip spaces at the token end if requested.
+        if( !bInString && bStripEndSpaces )
         {
-            while ( nTokenLen
-                    && isspace(
-                        static_cast<unsigned char>( pszToken[nTokenLen - 1]) ) )
+            while( nTokenLen
+                   && isspace(
+                       static_cast<unsigned char>( pszToken[nTokenLen - 1]) ) )
                 nTokenLen--;
         }
 
         pszToken[nTokenLen] = '\0';
 
-        /*
-         * Add the token.
-         */
+        // Add the token.
         if( pszToken[0] != '\0' || bAllowEmptyTokens )
             oRetList.AddString( pszToken );
     }
@@ -927,7 +935,7 @@ char ** CSLTokenizeString2( const char * pszString,
      * it now, as the loop would skip it.
      */
     if( *pszString == '\0' && bAllowEmptyTokens && oRetList.Count() > 0
-        && strchr(pszDelimiters,*(pszString-1)) != NULL )
+        && strchr(pszDelimiters, *(pszString-1)) != NULL )
     {
         oRetList.AddString( "" );
     }
@@ -936,10 +944,9 @@ char ** CSLTokenizeString2( const char * pszString,
 
     if( oRetList.List() == NULL )
     {
-        // we prefer to return empty lists as a pointer to
+        // Prefer to return empty lists as a pointer to
         // a null pointer since some client code might depend on this.
-        oRetList.Assign(
-            reinterpret_cast<char **>( CPLCalloc(sizeof(char*),1) ) );
+        oRetList.Assign(static_cast<char **>(CPLCalloc(sizeof(char*), 1)));
     }
 
     return oRetList.StealList();
@@ -948,19 +955,20 @@ char ** CSLTokenizeString2( const char * pszString,
 /**********************************************************************
  *                       CPLSPrintf()
  *
- * My own version of CPLSPrintf() that works with 10 static buffer.
- *
- * It returns a ref. to a static buffer that should not be freed and
- * is valid only until the next call to CPLSPrintf().
- *
  * NOTE: This function should move to cpl_conv.cpp.
  **********************************************************************/
-/* For now, assume that a 8000 chars buffer will be enough.
- */
+
+// For now, assume that a 8000 chars buffer will be enough.
 static const int CPLSPrintf_BUF_SIZE = 8000;
 static const int CPLSPrintf_BUF_Count = 10;
 
-const char *CPLSPrintf(const char *fmt, ...)
+/** CPLSPrintf() that works with 10 static buffer.
+ *
+ * It returns a ref. to a static buffer that should not be freed and
+ * is valid only until the next call to CPLSPrintf().
+ */
+
+const char *CPLSPrintf( CPL_FORMAT_STRING(const char *fmt), ... )
 {
     va_list args;
 
@@ -972,7 +980,8 @@ const char *CPLSPrintf(const char *fmt, ...)
     if( pachBufRingInfo == NULL )
     {
         pachBufRingInfo = static_cast<char *>(
-            CPLCalloc(1,sizeof(int)+CPLSPrintf_BUF_Count*CPLSPrintf_BUF_SIZE));
+            CPLCalloc(
+                1, sizeof(int) + CPLSPrintf_BUF_Count*CPLSPrintf_BUF_SIZE));
         CPLSetTLS( CTLS_CPLSPRINTF, pachBufRingInfo, TRUE );
     }
 
@@ -1006,12 +1015,13 @@ const char *CPLSPrintf(const char *fmt, ...)
 
 /**********************************************************************
  *                       CSLAppendPrintf()
- *
- * Use CPLSPrintf() to append a new line at the end of a StringList.
- *
- * Returns the modified StringList.
  **********************************************************************/
-char **CSLAppendPrintf(char **papszStrList, const char *fmt, ...)
+
+/** Use CPLSPrintf() to append a new line at the end of a StringList.
+ * Returns the modified StringList.
+ */
+char **CSLAppendPrintf( char **papszStrList,
+                        CPL_FORMAT_STRING(const char *fmt), ... )
 {
     va_list args;
 
@@ -1025,13 +1035,11 @@ char **CSLAppendPrintf(char **papszStrList, const char *fmt, ...)
 
 /************************************************************************/
 /*                            CPLVASPrintf()                            */
-/*                                                                      */
-/*      This is intended to serve as an easy to use C callable          */
-/*      vasprintf() alternative.  Used in the GeoJSON library for       */
-/*      instance.                                                       */
 /************************************************************************/
 
-int CPLVASPrintf( char **buf, const char *fmt, va_list ap )
+/** This is intended to serve as an easy to use C callable vasprintf()
+  * alternative.  Used in the GeoJSON library for instance */
+int CPLVASPrintf( char **buf, CPL_FORMAT_STRING(const char *fmt), va_list ap )
 
 {
     CPLString osWork;
@@ -1041,51 +1049,51 @@ int CPLVASPrintf( char **buf, const char *fmt, va_list ap )
     if( buf )
         *buf = CPLStrdup(osWork.c_str());
 
-    return static_cast<int>(strlen(osWork));
+    return static_cast<int>(osWork.size());
 }
 
 /************************************************************************/
 /*                  CPLvsnprintf_get_end_of_formatting()                */
 /************************************************************************/
 
-static const char* CPLvsnprintf_get_end_of_formatting(const char* fmt)
+static const char* CPLvsnprintf_get_end_of_formatting( const char* fmt )
 {
-    char ch;
-    /*flag */
+    char ch = '\0';
+    // Flag.
     for( ; (ch = *fmt) != '\0'; ++fmt )
     {
         if( ch == '\'' )
-            continue; /* bad idea as this is locale specific */
+            continue;  // Bad idea as this is locale specific.
         if( ch == '-' || ch == '+' || ch == ' ' || ch == '#' || ch == '0' )
             continue;
         break;
     }
 
-    /* field width */
+    // Field width.
     for( ; (ch = *fmt) != '\0'; ++fmt )
     {
         if( ch == '$' )
-            return NULL; /* we don't want to support this */
+            return NULL;  // Do not support this.
         if( *fmt >= '0' && *fmt <= '9' )
             continue;
         break;
     }
 
-    /* precision */
+    // Precision.
     if( ch == '.' )
     {
         ++fmt;
         for( ; (ch = *fmt) != '\0'; ++fmt )
         {
             if( ch == '$' )
-                return NULL; /* we don't want to support this */
+                return NULL;  // Do not support this.
             if( *fmt >= '0' && *fmt <= '9' )
                 continue;
             break;
         }
     }
 
-    /* length modifier */
+    // Length modifier.
     for( ; (ch = *fmt) != '\0'; ++fmt )
     {
         if( ch == 'h' || ch == 'l' || ch == 'j' || ch == 'z' ||
@@ -1105,7 +1113,8 @@ static const char* CPLvsnprintf_get_end_of_formatting(const char* fmt)
 /************************************************************************/
 
 #define call_native_snprintf(type) \
-    local_ret = snprintf(str + offset_out, size - offset_out, localfmt, va_arg(wrk_args, type))
+    local_ret = snprintf(str + offset_out, size - offset_out, localfmt, \
+                         va_arg(wrk_args, type))
 
 /** vsnprintf() wrapper that is not sensitive to LC_NUMERIC settings.
   *
@@ -1121,7 +1130,8 @@ static const char* CPLvsnprintf_get_end_of_formatting(const char* fmt)
   * written if size is big enough
   * @since GDAL 2.0
   */
-int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
+int CPLvsnprintf( char *str, size_t size,
+                  CPL_FORMAT_STRING(const char* fmt), va_list args )
 {
     if( size == 0 )
         return vsnprintf(str, size, fmt, args);
@@ -1136,7 +1146,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
 
     const char* fmt_ori = fmt;
     size_t offset_out = 0;
-    char ch;
+    char ch = '\0';
     bool bFormatUnknown = false;
 
     for( ; (ch = *fmt) != '\0'; ++fmt )
@@ -1152,7 +1162,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
             char end = *ptrend;
             char end_m1 = ptrend[-1];
 
-            char localfmt[22];
+            char localfmt[22] = {};
             memcpy(localfmt, fmt, ptrend - fmt + 1);
             localfmt[ptrend-fmt+1] = '\0';
 
@@ -1164,7 +1174,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
                 local_ret = 1;
                 str[offset_out] = '%';
             }
-            else if( end == 'd' ||  end == 'i' ||  end == 'c' )
+            else if( end == 'd' || end == 'i' ||  end == 'c' )
             {
                 if( end_m1 == 'h' )
                     call_native_snprintf(int);
@@ -1172,7 +1182,9 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
                     call_native_snprintf(long);
                 else if( end_m1 == 'l' && ptrend[-2] == 'l' )
                     call_native_snprintf(GIntBig);
-                else if( end_m1 == '4' && ptrend[-2] == '6' && ptrend[-3] == 'I' ) /* Microsoft I64 modifier */
+                else if( end_m1 == '4' && ptrend[-2] == '6' &&
+                         ptrend[-3] == 'I' )
+                    // Microsoft I64 modifier.
                     call_native_snprintf(GIntBig);
                 else if( end_m1 == 'z')
                     call_native_snprintf(size_t);
@@ -1185,7 +1197,7 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
                 else
                     call_native_snprintf(int);
             }
-            else  if( end == 'o' || end == 'u' || end == 'x' || end == 'X' )
+            else if( end == 'o' || end == 'u' || end == 'x' || end == 'X' )
             {
                 if( end_m1 == 'h' )
                     call_native_snprintf(unsigned int);
@@ -1193,7 +1205,9 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
                     call_native_snprintf(unsigned long);
                 else if( end_m1 == 'l' && ptrend[-2] == 'l' )
                     call_native_snprintf(GUIntBig);
-                else if( end_m1 == '4' && ptrend[-2] == '6' && ptrend[-3] == 'I' ) /* Microsoft I64 modifier */
+                else if( end_m1 == '4' && ptrend[-2] == '6' &&
+                         ptrend[-3] == 'I' )
+                    // Microsoft I64 modifier.
                     call_native_snprintf(GUIntBig);
                 else if( end_m1 == 'z')
                     call_native_snprintf(size_t);
@@ -1215,8 +1229,8 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
                     call_native_snprintf(long double);
                 else
                     call_native_snprintf(double);
-                /* MSVC vsnprintf() returns -1... */
-                if( local_ret <  0 || offset_out + local_ret >= size )
+                // MSVC vsnprintf() returns -1.
+                if( local_ret < 0 || offset_out + local_ret >= size )
                     break;
                 for( int j = 0; j < local_ret; ++j )
                 {
@@ -1231,7 +1245,8 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
             {
                 const char* pszPtr = va_arg(wrk_args, const char*);
                 CPLAssert(pszPtr);
-                local_ret = snprintf(str + offset_out, size - offset_out, localfmt, pszPtr);
+                local_ret = snprintf(str + offset_out, size - offset_out,
+                                     localfmt, pszPtr);
             }
             else if( end == 'p' )
             {
@@ -1242,8 +1257,8 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
                 bFormatUnknown = true;
                 break;
             }
-            /* MSVC vsnprintf() returns -1... */
-            if( local_ret <  0 || offset_out + local_ret >= size )
+            // MSVC vsnprintf() returns -1.
+            if( local_ret < 0 || offset_out + local_ret >= size )
                 break;
             offset_out += local_ret;
             fmt = ptrend;
@@ -1288,6 +1303,14 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
 /*                           CPLsnprintf()                              */
 /************************************************************************/
 
+#if !defined(ALIAS_CPLSNPRINTF_AS_SNPRINTF)
+
+#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
+
 /** snprintf() wrapper that is not sensitive to LC_NUMERIC settings.
   *
   * This function has the same contract as standard snprintf(), except that
@@ -1302,7 +1325,9 @@ int CPLvsnprintf(char *str, size_t size, const char* fmt, va_list args)
   * written if size is big enough
   * @since GDAL 2.0
   */
-int CPLsnprintf(char *str, size_t size, const char* fmt, ...)
+
+int CPLsnprintf( char *str, size_t size,
+                 CPL_FORMAT_STRING(const char* fmt), ... )
 {
     va_list args;
 
@@ -1312,6 +1337,8 @@ int CPLsnprintf(char *str, size_t size, const char* fmt, ...)
     return ret;
 }
 
+#endif //  !defined(ALIAS_CPLSNPRINTF_AS_SNPRINTF)
+
 /************************************************************************/
 /*                           CPLsprintf()                               */
 /************************************************************************/
@@ -1329,7 +1356,7 @@ int CPLsnprintf(char *str, size_t size, const char* fmt, ...)
 ` * output buffer.
   * @since GDAL 2.0
   */
-int CPLsprintf(char *str, const char* fmt, ...)
+int CPLsprintf( char *str, CPL_FORMAT_STRING(const char* fmt), ... )
 {
     va_list args;
 
@@ -1355,7 +1382,7 @@ int CPLsprintf(char *str, const char* fmt, ...)
   * output buffer.
   * @since GDAL 2.0
   */
-int CPLprintf(const char* fmt, ...)
+int CPLprintf( CPL_FORMAT_STRING(const char* fmt), ... )
 {
     va_list wrk_args, args;
 
@@ -1367,9 +1394,8 @@ int CPLprintf(const char* fmt, ...)
     wrk_args = args;
 #endif
 
-    char szBuffer[4096];
+    char szBuffer[4096] = {};
     // Quiet coverity by staring off nul terminated.
-    szBuffer[0] = '\0';
     int ret = CPLvsnprintf( szBuffer, sizeof(szBuffer), fmt, wrk_args );
 
 #ifdef va_copy
@@ -1377,7 +1403,7 @@ int CPLprintf(const char* fmt, ...)
 #endif
 
     if( ret < int(sizeof(szBuffer))-1 )
-        ret = printf("%s", szBuffer);
+        ret = printf("%s", szBuffer); /*ok*/
     else
     {
 #ifdef va_copy
@@ -1402,7 +1428,7 @@ int CPLprintf(const char* fmt, ...)
 /*                           CPLsscanf()                                */
 /************************************************************************/
 
-/** sscanf() wrapper that is not sensitive to LC_NUMERIC settings.
+/** \brief sscanf() wrapper that is not sensitive to LC_NUMERIC settings.
   *
   * This function has the same contract as standard sscanf(), except that
   * formatting of floating-point numbers will use decimal point, whatever the
@@ -1411,13 +1437,13 @@ int CPLprintf(const char* fmt, ...)
   * CAUTION: only works with a very limited number of formatting strings,
   * consisting only of "%lf" and regular characters.
   *
-  * param str input string
+  * @param str input string
   * @param fmt formatting string
   * @param ... arguments
   * @return the number of matched patterns;
   * @since GDAL 2.0
   */
-int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
+int CPLsscanf( const char* str, CPL_SCANF_FORMAT_STRING(const char* fmt), ... )
 {
     bool error = false;
     int ret = 0;
@@ -1470,6 +1496,10 @@ int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
     return ret;
 }
 
+#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 2
+#pragma clang diagnostic pop
+#endif
+
 /************************************************************************/
 /*                         CPLTestBool()                                */
 /************************************************************************/
@@ -1487,10 +1517,10 @@ int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
 
 bool CPLTestBool( const char *pszValue )
 {
-  return !( EQUAL(pszValue,"NO")
-            || EQUAL(pszValue,"FALSE")
-            || EQUAL(pszValue,"OFF")
-            || EQUAL(pszValue,"0") );
+    return !(EQUAL(pszValue, "NO")
+             || EQUAL(pszValue, "FALSE")
+             || EQUAL(pszValue, "OFF")
+             || EQUAL(pszValue, "0"));
 }
 
 /************************************************************************/
@@ -1539,11 +1569,11 @@ int CPLTestBoolean( const char *pszValue )
     return CPLTestBool( pszValue ) ? TRUE : FALSE;
 }
 
-
 /**********************************************************************
  *                       CPLFetchBool()
- *
- * Check for boolean key value.
+ **********************************************************************/
+
+/** Check for boolean key value.
  *
  * In a StringList of "Name=Value" pairs, look to see if there is a key
  * with the given name, and if it can be interpreted as being TRUE.  If
@@ -1557,17 +1587,17 @@ int CPLTestBoolean( const char *pszValue )
  * @param bDefault the value to return if the key isn't found at all.
  *
  * @return true or false
- **********************************************************************/
+ */
 
-bool CPLFetchBool( const char **papszStrList, const char *pszKey,
+bool CPLFetchBool( const char * const *papszStrList, const char *pszKey,
                    bool bDefault )
 
 {
-    if( CSLFindString( const_cast<char **>(papszStrList), pszKey ) != -1 )
+    if( CSLFindString( papszStrList, pszKey ) != -1 )
         return true;
 
     const char * const pszValue =
-        CSLFetchNameValue( const_cast<char **>(papszStrList), pszKey );
+        CSLFetchNameValue( papszStrList, pszKey );
     if( pszValue == NULL )
         return bDefault;
 
@@ -1576,8 +1606,9 @@ bool CPLFetchBool( const char **papszStrList, const char *pszKey,
 
 /**********************************************************************
  *                       CSLFetchBoolean()
- *
- * DEPRECATED.  Check for boolean key value.
+ **********************************************************************/
+
+/** DEPRECATED.  Check for boolean key value.
  *
  * In a StringList of "Name=Value" pairs, look to see if there is a key
  * with the given name, and if it can be interpreted as being TRUE.  If
@@ -1591,20 +1622,20 @@ bool CPLFetchBool( const char **papszStrList, const char *pszKey,
  * @param bDefault the value to return if the key isn't found at all.
  *
  * @return TRUE or FALSE
- **********************************************************************/
+ */
 
 int CSLFetchBoolean( char **papszStrList, const char *pszKey, int bDefault )
 
 {
-    return CPLFetchBool( const_cast<const char **>(papszStrList),
-                         pszKey, CPL_TO_BOOL(bDefault) );
+    return CPLFetchBool( papszStrList, pszKey, CPL_TO_BOOL(bDefault) );
 }
 
 /************************************************************************/
 /*                     CSLFetchNameValueDefaulted()                     */
 /************************************************************************/
 
-const char *CSLFetchNameValueDef( char **papszStrList,
+/** Same as CSLFetchNameValue() but return pszDefault in case of no match */
+const char *CSLFetchNameValueDef( const char * const *papszStrList,
                                   const char *pszName,
                                   const char *pszDefault )
 
@@ -1618,8 +1649,9 @@ const char *CSLFetchNameValueDef( char **papszStrList,
 
 /**********************************************************************
  *                       CSLFetchNameValue()
- *
- * In a StringList of "Name=Value" pairs, look for the
+ **********************************************************************/
+
+/** In a StringList of "Name=Value" pairs, look for the
  * first value associated with the specified name.  The search is not
  * case sensitive.
  * ("Name:Value" pairs are also supported for backward compatibility
@@ -1629,16 +1661,18 @@ const char *CSLFetchNameValueDef( char **papszStrList,
  * should not attempt to free.
  *
  * Returns NULL if the name is not found.
- **********************************************************************/
-const char *CSLFetchNameValue(char **papszStrList, const char *pszName)
+ */
+
+const char *CSLFetchNameValue( const char * const *papszStrList,
+                               const char *pszName )
 {
-    if (papszStrList == NULL || pszName == NULL)
+    if( papszStrList == NULL || pszName == NULL )
         return NULL;
 
     const size_t nLen = strlen(pszName);
     while( *papszStrList != NULL )
     {
-        if (EQUALN(*papszStrList, pszName, nLen)
+        if( EQUALN(*papszStrList, pszName, nLen)
             && ( (*papszStrList)[nLen] == '=' ||
                  (*papszStrList)[nLen] == ':' ) )
         {
@@ -1663,16 +1697,16 @@ const char *CSLFetchNameValue(char **papszStrList, const char *pszName)
  * matching the given key.
  */
 
-int CSLFindName(char **papszStrList, const char *pszName)
+int CSLFindName( char **papszStrList, const char *pszName )
 {
-    if (papszStrList == NULL || pszName == NULL)
+    if( papszStrList == NULL || pszName == NULL )
         return -1;
 
     const size_t nLen = strlen(pszName);
     int iIndex = 0;
-    while(*papszStrList != NULL)
+    while( *papszStrList != NULL )
     {
-        if (EQUALN(*papszStrList, pszName, nLen)
+        if( EQUALN(*papszStrList, pszName, nLen)
             && ( (*papszStrList)[nLen] == '=' ||
                  (*papszStrList)[nLen] == ':' ) )
         {
@@ -1709,7 +1743,7 @@ int CSLFindName(char **papszStrList, const char *pszName)
  * @return the value portion (pointing into original string).
  */
 
-const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey )
+const char *CPLParseNameValue( const char *pszNameValue, char **ppszKey )
 {
     for( int i = 0; pszNameValue[i] != '\0'; ++i )
     {
@@ -1721,7 +1755,7 @@ const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey )
 
             if( ppszKey != NULL )
             {
-                *ppszKey = reinterpret_cast<char *>( CPLMalloc(i+1) );
+                *ppszKey = static_cast<char *>(CPLMalloc(i + 1));
                 strncpy( *ppszKey, pszNameValue, i );
                 (*ppszKey)[i] = '\0';
                 while( i > 0 &&
@@ -1741,8 +1775,9 @@ const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey )
 
 /**********************************************************************
  *                       CSLFetchNameValueMultiple()
- *
- * In a StringList of "Name=Value" pairs, look for all the
+ **********************************************************************/
+
+/** In a StringList of "Name=Value" pairs, look for all the
  * values with the specified name.  The search is not case
  * sensitive.
  * ("Name:Value" pairs are also supported for backward compatibility
@@ -1753,17 +1788,18 @@ const char *CPLParseNameValue(const char *pszNameValue, char **ppszKey )
  * by calling CSLDestroy().
  *
  * Returns NULL if the name is not found.
- **********************************************************************/
-char **CSLFetchNameValueMultiple(char **papszStrList, const char *pszName)
+ */
+
+char **CSLFetchNameValueMultiple( char **papszStrList, const char *pszName )
 {
-    if (papszStrList == NULL || pszName == NULL)
+    if( papszStrList == NULL || pszName == NULL )
         return NULL;
 
     const size_t nLen = strlen(pszName);
     char **papszValues = NULL;
-    while(*papszStrList != NULL)
+    while( *papszStrList != NULL )
     {
-        if (EQUALN(*papszStrList, pszName, nLen)
+        if( EQUALN(*papszStrList, pszName, nLen)
             && ( (*papszStrList)[nLen] == '=' ||
                  (*papszStrList)[nLen] == ':' ) )
         {
@@ -1778,8 +1814,9 @@ char **CSLFetchNameValueMultiple(char **papszStrList, const char *pszName)
 
 /**********************************************************************
  *                       CSLAddNameValue()
- *
- * Add a new entry to a StringList of "Name=Value" pairs,
+ **********************************************************************/
+
+/** Add a new entry to a StringList of "Name=Value" pairs,
  * ("Name:Value" pairs are also supported for backward compatibility
  * with older stuff.)
  *
@@ -1788,11 +1825,12 @@ char **CSLFetchNameValueMultiple(char **papszStrList, const char *pszName)
  * Use CSLSetNameValue() if you want each name to have only one value.
  *
  * Returns the modified StringList.
- **********************************************************************/
-char **CSLAddNameValue(char **papszStrList,
-                       const char *pszName, const char *pszValue)
+ */
+
+char **CSLAddNameValue( char **papszStrList,
+                        const char *pszName, const char *pszValue )
 {
-    if (pszName == NULL || pszValue==NULL)
+    if( pszName == NULL || pszValue==NULL )
         return papszStrList;
 
     const size_t nLen = strlen(pszName)+strlen(pszValue)+2;
@@ -1836,22 +1874,19 @@ char **CSLSetNameValue( char **papszList,
 
     const size_t nLen = strlen(pszName);
     char **papszPtr = papszList;
-    while(papszPtr && *papszPtr != NULL)
+    while( papszPtr && *papszPtr != NULL )
     {
-        if (EQUALN(*papszPtr, pszName, nLen)
+        if( EQUALN(*papszPtr, pszName, nLen)
             && ( (*papszPtr)[nLen] == '=' ||
                  (*papszPtr)[nLen] == ':' ) )
         {
-            /* Found it!
-             * Change the value... make sure to keep the ':' or '='
-             */
+            // Found it.
+            // Change the value... make sure to keep the ':' or '='.
             const char cSep = (*papszPtr)[nLen];
 
             CPLFree(*papszPtr);
 
-            /*
-             * If the value is NULL, remove this entry completely/
-             */
+            // If the value is NULL, remove this entry completely.
             if( pszValue == NULL )
             {
                 while( papszPtr[1] != NULL )
@@ -1862,9 +1897,7 @@ char **CSLSetNameValue( char **papszList,
                 *papszPtr = NULL;
             }
 
-            /*
-             * Otherwise replace with new value.
-             */
+            // Otherwise replace with new value.
             else
             {
                 const size_t nLen2 = strlen(pszName)+strlen(pszValue)+2;
@@ -1879,8 +1912,7 @@ char **CSLSetNameValue( char **papszList,
     if( pszValue == NULL )
         return papszList;
 
-    /* The name does not exist yet... create a new entry
-     */
+    // The name does not exist yet.  Create a new entry.
     return CSLAddNameValue(papszList, pszName, pszValue);
 }
 
@@ -1941,7 +1973,7 @@ void CSLSetNameValueSeparator( char ** papszList, const char *pszSeparator )
  * This function will "escape" a variety of special characters
  * to make the string suitable to embed within a string constant
  * or to write within a text stream but in a form that can be
- * reconstituted to it's original form.  The escaping will even preserve
+ * reconstituted to its original form.  The escaping will even preserve
  * zero bytes allowing preservation of raw binary data.
  *
  * CPLES_BackslashQuotable(0): This scheme turns a binary string into
@@ -1987,11 +2019,10 @@ char *CPLEscapeString( const char *pszInput, int nLength,
 
     const size_t nSizeAlloc = nLength * 6 + 1;
     char *pszOutput = static_cast<char *>( CPLMalloc( nSizeAlloc ) );
+    int iOut = 0;
 
     if( nScheme == CPLES_BackslashQuotable )
     {
-        int iOut = 0;
-
         for( int iIn = 0; iIn < nLength; iIn++ )
         {
             if( pszInput[iIn] == '\0' )
@@ -2017,12 +2048,10 @@ char *CPLEscapeString( const char *pszInput, int nLength,
             else
                 pszOutput[iOut++] = pszInput[iIn];
         }
-        pszOutput[iOut] = '\0';
+        pszOutput[iOut++] = '\0';
     }
     else if( nScheme == CPLES_XML || nScheme == CPLES_XML_BUT_QUOTES )
     {
-        int iOut = 0;
-
         for( int iIn = 0; iIn < nLength; ++iIn )
         {
             if( pszInput[iIn] == '<' )
@@ -2056,11 +2085,14 @@ char *CPLEscapeString( const char *pszInput, int nLength,
                 pszOutput[iOut++] = 't';
                 pszOutput[iOut++] = ';';
             }
-            /* Python 2 does not display the UTF-8 character corresponding */
-            /* to the byte-order mark (BOM), so escape it */
-            else if( (reinterpret_cast<const unsigned char*>(pszInput))[iIn] == 0xEF &&
-                     (reinterpret_cast<const unsigned char*>(pszInput))[iIn+1] == 0xBB &&
-                     (reinterpret_cast<const unsigned char*>(pszInput))[iIn+2] == 0xBF )
+            // Python 2 does not display the UTF-8 character corresponding
+            // to the byte-order mark (BOM), so escape it.
+            else if( (reinterpret_cast<const unsigned char*>(pszInput))[iIn]
+                         == 0xEF &&
+                     (reinterpret_cast<const unsigned char*>(pszInput))[iIn+1]
+                         == 0xBB &&
+                     (reinterpret_cast<const unsigned char*>(pszInput))[iIn+2]
+                         == 0xBF )
             {
                 pszOutput[iOut++] = '&';
                 pszOutput[iOut++] = '#';
@@ -2072,7 +2104,8 @@ char *CPLEscapeString( const char *pszInput, int nLength,
                 pszOutput[iOut++] = ';';
                 iIn += 2;
             }
-            else if( (reinterpret_cast<const unsigned char*>(pszInput))[iIn] < 0x20
+            else if( (reinterpret_cast<const unsigned char*>(pszInput))[iIn]
+                         < 0x20
                      && pszInput[iIn] != 0x9
                      && pszInput[iIn] != 0xA
                      && pszInput[iIn] != 0xD )
@@ -2081,15 +2114,15 @@ char *CPLEscapeString( const char *pszInput, int nLength,
                 // so we just drop them.  #4117
             }
             else
+            {
                 pszOutput[iOut++] = pszInput[iIn];
+            }
         }
-        pszOutput[iOut] = '\0';
+        pszOutput[iOut++] = '\0';
     }
-    else if( nScheme == CPLES_URL ) /* Untested at implementation */
+    else if( nScheme == CPLES_URL ) // Untested at implementation.
     {
-        int iOut = 0, iIn;
-
-        for( iIn = 0; iIn < nLength; ++iIn )
+        for( int iIn = 0; iIn < nLength; ++iIn )
         {
             if( (pszInput[iIn] >= 'a' && pszInput[iIn] <= 'z')
                 || (pszInput[iIn] >= 'A' && pszInput[iIn] <= 'Z')
@@ -2110,12 +2143,10 @@ char *CPLEscapeString( const char *pszInput, int nLength,
                 iOut += 3;
             }
         }
-        pszOutput[iOut] = '\0';
+        pszOutput[iOut++] = '\0';
     }
     else if( nScheme == CPLES_SQL )
     {
-        int iOut = 0;
-
         for( int iIn = 0; iIn < nLength; ++iIn )
         {
             if( pszInput[iIn] == '\'' )
@@ -2124,26 +2155,22 @@ char *CPLEscapeString( const char *pszInput, int nLength,
                 pszOutput[iOut++] = '\'';
             }
             else
+            {
                 pszOutput[iOut++] = pszInput[iIn];
+            }
         }
-        pszOutput[iOut] = '\0';
+        pszOutput[iOut++] = '\0';
     }
     else if( nScheme == CPLES_CSV )
     {
-        if( strchr( pszInput, '\"' ) == NULL
-            && strchr( pszInput, ',') == NULL
-            && strchr( pszInput, ';') == NULL
-            && strchr( pszInput, '\t') == NULL
-            && strchr( pszInput, 10) == NULL  // \n
-            && strchr( pszInput, 13) == NULL )  // \r
+        if( static_cast<int>(strcspn( pszInput, "\",;\t\n\r" )) == nLength )
         {
-            strcpy( pszOutput, pszInput );
+            memcpy( pszOutput, pszInput, nLength + 1 );
+            iOut = nLength + 1;
         }
         else
         {
-            int iOut = 1;
-
-            pszOutput[0] = '\"';
+            pszOutput[iOut++] = '\"';
 
             for( int iIn = 0; iIn < nLength; ++iIn )
             {
@@ -2161,17 +2188,15 @@ char *CPLEscapeString( const char *pszInput, int nLength,
     }
     else
     {
-        pszOutput[0] = '\0';
+        pszOutput[iOut++] = '\0';
         CPLError( CE_Failure, CPLE_AppDefined,
                   "Undefined escaping scheme (%d) in CPLEscapeString()",
                   nScheme );
     }
 
-    // TODO: Was pszShortOutput supposed to start part way through pszOutput?
-    char *pszShortOutput = CPLStrdup( pszOutput );
-    CPLFree( pszOutput );
-
-    return pszShortOutput;
+    if( iOut == nLength + 1 )
+        return pszOutput;
+    return static_cast<char*>(CPLRealloc( pszOutput, iOut));
 }
 
 /************************************************************************/
@@ -2183,7 +2208,7 @@ char *CPLEscapeString( const char *pszInput, int nLength,
  *
  * This function does the opposite of CPLEscapeString().  Given a string
  * with special values escaped according to some scheme, it will return a
- * new copy of the string returned to it's original form.
+ * new copy of the string returned to its original form.
  *
  * @param pszInput the input string.  This is a zero terminated string.
  * @param pnLength location to return the length of the unescaped string,
@@ -2198,11 +2223,10 @@ char *CPLEscapeString( const char *pszInput, int nLength,
 char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
 
 {
-    int iOut=0;
+    int iOut = 0;
 
     // TODO: Why times 4?
-    char *pszOutput = reinterpret_cast<char *>(
-        CPLMalloc(4 * strlen(pszInput) + 1) );
+    char *pszOutput = static_cast<char *>(CPLMalloc(4 * strlen(pszInput) + 1));
     pszOutput[0] = '\0';
 
     if( nScheme == CPLES_BackslashQuotable )
@@ -2225,9 +2249,9 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
             }
         }
     }
-    else if( nScheme == CPLES_XML || nScheme == CPLES_XML_BUT_QUOTES  )
+    else if( nScheme == CPLES_XML || nScheme == CPLES_XML_BUT_QUOTES )
     {
-        char ch;
+        char ch = '\0';
         for( int iIn = 0; (ch = pszInput[iIn]) != '\0'; ++iIn )
         {
             if( ch != '&' )
@@ -2264,23 +2288,24 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
                 wchar_t anVal[2] = {0 , 0};
                 iIn += 3;
 
-                while(true)
+                while( true )
                 {
                     ch = pszInput[iIn++];
-                    if (ch >= 'a' && ch <= 'f')
+                    if( ch >= 'a' && ch <= 'f' )
                         anVal[0] = anVal[0] * 16 + ch - 'a' + 10;
-                    else if (ch >= 'A' && ch <= 'F')
+                    else if( ch >= 'A' && ch <= 'F' )
                         anVal[0] = anVal[0] * 16 + ch - 'A' + 10;
-                    else if (ch >= '0' && ch <= '9')
+                    else if( ch >= '0' && ch <= '9' )
                         anVal[0] = anVal[0] * 16 + ch - '0';
                     else
                         break;
                 }
-                if (ch != ';')
+                if( ch != ';' )
                     break;
-                iIn --;
+                iIn--;
 
-                char * pszUTF8 = CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
+                char * pszUTF8 =
+                    CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
                 int nLen = static_cast<int>(strlen(pszUTF8));
                 memcpy(pszOutput + iOut, pszUTF8, nLen);
                 CPLFree(pszUTF8);
@@ -2288,30 +2313,31 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
             }
             else if( STARTS_WITH_CI(pszInput+iIn, "&#") )
             {
-                wchar_t anVal[2] = {0 , 0};
+                wchar_t anVal[2] = { 0, 0 };
                 iIn += 2;
 
-                while(true)
+                while( true )
                 {
-                    ch = pszInput[iIn ++];
-                    if (ch >= '0' && ch <= '9')
+                    ch = pszInput[iIn++];
+                    if( ch >= '0' && ch <= '9' )
                         anVal[0] = anVal[0] * 10 + ch - '0';
                     else
                         break;
                 }
-                if (ch != ';')
+                if( ch != ';' )
                     break;
-                iIn --;
+                iIn--;
 
-                char * pszUTF8 = CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
-                int nLen = static_cast<int>(strlen(pszUTF8));
+                char *pszUTF8 =
+                    CPLRecodeFromWChar( anVal, "WCHAR_T", CPL_ENC_UTF8);
+                const int nLen = static_cast<int>(strlen(pszUTF8));
                 memcpy(pszOutput + iOut, pszUTF8, nLen);
                 CPLFree(pszUTF8);
                 iOut += nLen;
             }
             else
             {
-                /* illegal escape sequence */
+                // Illegal escape sequence.
                 CPLDebug( "CPL",
                           "Error unescaping CPLES_XML text, '&' character "
                           "followed by unhandled escape sequence." );
@@ -2414,15 +2440,15 @@ char *CPLUnescapeString( const char *pszInput, int *pnLength, int nScheme )
 char *CPLBinaryToHex( int nBytes, const GByte *pabyData )
 
 {
-    char *pszHex = reinterpret_cast<char *>( CPLMalloc(nBytes * 2 + 1 ) );
+    char *pszHex = static_cast<char *>(CPLMalloc(nBytes * 2 + 1));
     pszHex[nBytes*2] = '\0';
 
     static const char achHex[] = "0123456789ABCDEF";
 
     for( int i = 0; i < nBytes; ++i )
     {
-        int nLow = pabyData[i] & 0x0f;
-        int nHigh = (pabyData[i] & 0xf0) >> 4;
+        const int nLow = pabyData[i] & 0x0f;
+        const int nHigh = (pabyData[i] & 0xf0) >> 4;
 
         pszHex[i*2] = achHex[nHigh];
         pszHex[i*2+1] = achHex[nLow];
@@ -2435,30 +2461,21 @@ char *CPLBinaryToHex( int nBytes, const GByte *pabyData )
 /*                           CPLHexToBinary()                           */
 /************************************************************************/
 
-/**
- * Hexadecimal to binary translation
- *
- * @param pszHex the input hex encoded string.
- * @param pnBytes the returned count of decoded bytes placed here.
- *
- * @return returns binary buffer of data - free with CPLFree().
- */
-
 static const unsigned char hex2char[256] = {
-    /* not Hex characters */
+    // Not Hex characters.
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    /* 0-9 */
+    // 0-9
     0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
-       /* A-F */
+    // A-F
     0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
-    /* not Hex characters */
+    // Not Hex characters.
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-      /* a-f */
+    // a-f
     0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-    /* not Hex characters (upper 128 characters) */
+    // Not Hex characters (upper 128 characters).
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -2469,6 +2486,15 @@ static const unsigned char hex2char[256] = {
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 };
 
+/**
+ * Hexadecimal to binary translation
+ *
+ * @param pszHex the input hex encoded string.
+ * @param pnBytes the returned count of decoded bytes placed here.
+ *
+ * @return returns binary buffer of data - free with CPLFree().
+ */
+
 GByte *CPLHexToBinary( const char *pszHex, int *pnBytes )
 {
     const size_t nHexLen = strlen(pszHex);
@@ -2477,10 +2503,10 @@ GByte *CPLHexToBinary( const char *pszHex, int *pnBytes )
 
     for( size_t i = 0; i < nHexLen/2; ++i )
     {
-        unsigned char h1 = hex2char[static_cast<int>( pszHex[2*i] )];
-        unsigned char h2 = hex2char[static_cast<int>( pszHex[2*i+1] )];
+        const unsigned char h1 = hex2char[static_cast<int>( pszHex[2*i] )];
+        const unsigned char h2 = hex2char[static_cast<int>( pszHex[2*i+1] )];
 
-        /* First character is high bits, second is low bits */
+        // First character is high bits, second is low bits.
         pabyWKB[i] = static_cast<GByte>( (h1 << 4) | h2 );
     }
     pabyWKB[nHexLen/2] = 0;
@@ -2507,28 +2533,26 @@ GByte *CPLHexToBinary( const char *pszHex, int *pnBytes )
  * @return returns the type of the value contained in the string.
  */
 
-CPLValueType CPLGetValueType(const char* pszValue)
+CPLValueType CPLGetValueType( const char* pszValue )
 {
-    /*
-    doubles : "+25.e+3", "-25.e-3", "25.e3", "25e3", " 25e3 "
-    not doubles: "25e 3", "25e.3", "-2-5e3", "2-5e3", "25.25.3", "-3d", "d1"
-                 "XXeYYYYYYYYYYYYYYYYYYY" that evaluates to infinity
-    */
+    // Doubles : "+25.e+3", "-25.e-3", "25.e3", "25e3", " 25e3 "
+    // Not doubles: "25e 3", "25e.3", "-2-5e3", "2-5e3", "25.25.3", "-3d", "d1"
+    //              "XXeYYYYYYYYYYYYYYYYYYY" that evaluates to infinity
 
-    if (pszValue == NULL)
+    if( pszValue == NULL )
         return CPL_VALUE_STRING;
 
     const char* pszValueInit = pszValue;
 
-    /* Skip leading spaces */
+    // Skip leading spaces.
     while( isspace( *pszValue ) )
         ++pszValue;
 
-    if (*pszValue == '\0')
+    if( *pszValue == '\0' )
         return CPL_VALUE_STRING;
 
-    /* Skip leading + or - */
-    if (*pszValue == '+' || *pszValue == '-')
+    // Skip leading + or -.
+    if( *pszValue == '+' || *pszValue == '-' )
         ++pszValue;
 
     bool bFoundDot = false;
@@ -2538,53 +2562,55 @@ CPLValueType CPLGetValueType(const char* pszValue)
     const char* pszAfterExponent = NULL;
     bool bFoundMantissa = false;
 
-    for(; *pszValue != '\0'; ++pszValue )
+    for( ; *pszValue != '\0'; ++pszValue )
     {
         if( isdigit( *pszValue))
         {
             bIsLastCharExponent = false;
             bFoundMantissa = true;
         }
-        else if ( isspace( *pszValue ) )
+        else if( isspace( *pszValue ) )
         {
             const char* pszTmp = pszValue;
             while( isspace( *pszTmp ) )
                 ++pszTmp;
-            if (*pszTmp == 0)
+            if( *pszTmp == 0 )
                 break;
             else
                 return CPL_VALUE_STRING;
         }
-        else if ( *pszValue == '-' || *pszValue == '+' )
+        else if( *pszValue == '-' || *pszValue == '+' )
         {
-            if (bIsLastCharExponent)
+            if( bIsLastCharExponent )
             {
-                /* do nothing */
+                // Do nothing.
             }
             else
+            {
                 return CPL_VALUE_STRING;
+            }
             bIsLastCharExponent = false;
         }
-        else if ( *pszValue == '.')
+        else if( *pszValue == '.')
         {
             bIsReal = true;
-            if (!bFoundDot && !bIsLastCharExponent)
+            if( !bFoundDot && !bIsLastCharExponent )
                 bFoundDot = true;
             else
                 return CPL_VALUE_STRING;
             bIsLastCharExponent = false;
         }
-        else if (*pszValue == 'D' || *pszValue == 'd'
+        else if( *pszValue == 'D' || *pszValue == 'd'
                  || *pszValue == 'E' || *pszValue == 'e' )
         {
             if( !bFoundMantissa )
                 return CPL_VALUE_STRING;
-            if (!(pszValue[1] == '+' || pszValue[1] == '-' ||
-                  isdigit(pszValue[1])))
+            if( !(pszValue[1] == '+' || pszValue[1] == '-' ||
+                  isdigit(pszValue[1])) )
                 return CPL_VALUE_STRING;
 
             bIsReal = true;
-            if (!bFoundExponent)
+            if( !bFoundExponent )
                 bFoundExponent = true;
             else
                 return CPL_VALUE_STRING;
@@ -2599,12 +2625,13 @@ CPLValueType CPLGetValueType(const char* pszValue)
 
     if( bIsReal && pszAfterExponent && strlen(pszAfterExponent) > 3 )
     {
+        // cppcheck-suppress unreadVariable
         const double dfVal = CPLAtof(pszValueInit);
         if( CPLIsInf(dfVal) )
             return CPL_VALUE_STRING;
     }
 
-    return (bIsReal) ? CPL_VALUE_REAL : CPL_VALUE_INTEGER;
+    return bIsReal ? CPL_VALUE_REAL : CPL_VALUE_INTEGER;
 }
 
 /************************************************************************/
@@ -2624,8 +2651,8 @@ CPLValueType CPLGetValueType(const char* pszValue)
  * is greater or equal to nDestSize.
 
 \verbatim
-char szDest[5];
-if (CPLStrlcpy(szDest, "abcde", sizeof(szDest)) >= sizeof(szDest))
+char szDest[5] = {};
+if( CPLStrlcpy(szDest, "abcde", sizeof(szDest)) >= sizeof(szDest) )
     fprintf(stderr, "truncation occurred !\n");
 \endverbatim
 
@@ -2638,16 +2665,16 @@ if (CPLStrlcpy(szDest, "abcde", sizeof(szDest)) >= sizeof(szDest))
  *
  * @since GDAL 1.7.0
  */
-size_t CPLStrlcpy(char* pszDest, const char* pszSrc, size_t nDestSize)
+size_t CPLStrlcpy( char* pszDest, const char* pszSrc, size_t nDestSize )
 {
-    if (nDestSize == 0)
+    if( nDestSize == 0 )
         return strlen(pszSrc);
 
     char* pszDestIter = pszDest;
     const char* pszSrcIter = pszSrc;
 
     --nDestSize;
-    while(nDestSize != 0 && *pszSrcIter != '\0')
+    while( nDestSize != 0 && *pszSrcIter != '\0' )
     {
         *pszDestIter = *pszSrcIter;
         ++pszDestIter;
@@ -2676,9 +2703,9 @@ size_t CPLStrlcpy(char* pszDest, const char* pszSrc, size_t nDestSize)
  * is greater or equal to nDestSize.
 
 \verbatim
-char szDest[5];
+char szDest[5] = {};
 CPLStrlcpy(szDest, "ab", sizeof(szDest));
-if (CPLStrlcat(szDest, "cde", sizeof(szDest)) >= sizeof(szDest))
+if( CPLStrlcat(szDest, "cde", sizeof(szDest)) >= sizeof(szDest) )
     fprintf(stderr, "truncation occurred !\n");
 \endverbatim
 
@@ -2695,11 +2722,11 @@ if (CPLStrlcat(szDest, "cde", sizeof(szDest)) >= sizeof(szDest))
  *
  * @since GDAL 1.7.0
  */
-size_t CPLStrlcat(char* pszDest, const char* pszSrc, size_t nDestSize)
+size_t CPLStrlcat( char* pszDest, const char* pszSrc, size_t nDestSize )
 {
     char* pszDestIter = pszDest;
 
-    while(nDestSize != 0 && *pszDestIter != '\0')
+    while( nDestSize != 0 && *pszDestIter != '\0' )
     {
         ++pszDestIter;
         --nDestSize;
@@ -2716,7 +2743,7 @@ size_t CPLStrlcat(char* pszDest, const char* pszSrc, size_t nDestSize)
  * Returns the length of a NUL terminated string by reading at most
  * the specified number of bytes.
  *
- * The CPLStrnlen() function returns MIN(strlen(pszStr), nMaxLen).
+ * The CPLStrnlen() function returns min(strlen(pszStr), nMaxLen).
  * Only the first nMaxLen bytes of the string will be read. Useful to
  * test if a string contains at least nMaxLen characters without reading
  * the full string up to the NUL terminating character.
@@ -2730,10 +2757,10 @@ size_t CPLStrlcat(char* pszDest, const char* pszSrc, size_t nDestSize)
  * @since GDAL 1.7.0
  */
 
-size_t CPLStrnlen (const char *pszStr, size_t nMaxLen)
+size_t CPLStrnlen ( const char *pszStr, size_t nMaxLen )
 {
     size_t nLen = 0;
-    while(nLen < nMaxLen && *pszStr != '\0')
+    while( nLen < nMaxLen && *pszStr != '\0' )
     {
         ++nLen;
         ++pszStr;
@@ -2754,7 +2781,7 @@ size_t CPLStrnlen (const char *pszStr, size_t nMaxLen)
  *
  * @since GDAL 2.1
  */
-char CPL_DLL ** CSLParseCommandLine(const char* pszCommandLine)
+char ** CSLParseCommandLine(const char* pszCommandLine)
 {
     return CSLTokenizeString(pszCommandLine);
 }
diff --git a/port/cpl_string.h b/port/cpl_string.h
index c57b467..0a22717 100644
--- a/port/cpl_string.h
+++ b/port/cpl_string.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_string.h 33788 2016-03-26 00:45:58Z goatbar $
+ * $Id: cpl_string.h 37869 2017-03-31 00:15:46Z rouault $
  *
  * Name:     cpl_string.h
  * Project:  CPL - Common Portability Library
@@ -83,17 +83,30 @@ char CPL_DLL **CSLTokenizeString2( const char *pszString,
                                    const char *pszDelimiter,
                                    int nCSLTFlags ) CPL_WARN_UNUSED_RESULT;
 
+/** Flag for CSLTokenizeString2() to honour strings */
 #define CSLT_HONOURSTRINGS      0x0001
+/** Flag for CSLTokenizeString2() to allow empty tokens */
 #define CSLT_ALLOWEMPTYTOKENS   0x0002
+/** Flag for CSLTokenizeString2() to preserve quotes */
 #define CSLT_PRESERVEQUOTES     0x0004
+/** Flag for CSLTokenizeString2() to preserve escape characters */
 #define CSLT_PRESERVEESCAPES    0x0008
+/** Flag for CSLTokenizeString2() to strip leading spaces */
 #define CSLT_STRIPLEADSPACES    0x0010
+/** Flag for CSLTokenizeString2() to strip trailaing spaces */
 #define CSLT_STRIPENDSPACES     0x0020
 
 int CPL_DLL CSLPrint(char **papszStrList, FILE *fpOut);
 char CPL_DLL **CSLLoad(const char *pszFname) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL **CSLLoad2(const char *pszFname, int nMaxLines, int nMaxCols,
-                        char** papszOptions) CPL_WARN_UNUSED_RESULT;
+#ifdef __cplusplus
+char CPL_DLL **CSLLoad2(
+    const char *pszFname, int nMaxLines, int nMaxCols,
+    const char * const * papszOptions) CPL_WARN_UNUSED_RESULT;
+#else
+char CPL_DLL **CSLLoad2(
+    const char *pszFname, int nMaxLines, int nMaxCols,
+    char **papszOptions) CPL_WARN_UNUSED_RESULT;
+#endif
 int CPL_DLL CSLSave(char **papszStrList, const char *pszFname);
 
 char CPL_DLL **CSLInsertStrings(char **papszStrList, int nInsertAtLineNo,
@@ -103,42 +116,69 @@ char CPL_DLL **CSLInsertString(char **papszStrList, int nInsertAtLineNo,
 char CPL_DLL **CSLRemoveStrings(
     char **papszStrList, int nFirstLineToDelete,
     int nNumToRemove, char ***ppapszRetStrings) CPL_WARN_UNUSED_RESULT;
-int CPL_DLL CSLFindString( char **, const char * );
-int CPL_DLL CSLFindStringCaseSensitive( char **, const char * );
-int CPL_DLL CSLPartialFindString( char **papszHaystack,
-                                  const char * pszNeedle );
+#ifdef __cplusplus
+int CPL_DLL CSLFindString( const char * const *papszList,
+                           const char *pszTarget );
+int CPL_DLL CSLFindStringCaseSensitive( const char * const *papszList,
+                                        const char *pszTarget );
+int CPL_DLL CSLPartialFindString( const char * const *papszHaystack,
+                                  const char *pszNeedle );
+#else
+// Present non-const to C code that does not like passing non-const to const.
+// Should be ABI compatible with the const versions.
+int CPL_DLL CSLFindString( char **papszList, const char *pszTarget );
+int CPL_DLL CSLFindStringCaseSensitive( char * const *papszList,
+                                        const char *pszTarget );
+int CPL_DLL CSLPartialFindString( char * const *papszHaystack,
+                                  const char *pszNeedle );
+#endif
 int CPL_DLL CSLFindName(char **papszStrList, const char *pszName);
 int CPL_DLL CSLFetchBoolean( char **papszStrList, const char *pszKey,
                              int bDefault );
 
 /* TODO: Deprecate CSLTestBoolean.  Remove in GDAL 3.x. */
 int CPL_DLL CSLTestBoolean( const char *pszValue );
+/* Do not use CPLTestBoolean in C++ code.  Use CPLTestBool. */
 int CPL_DLL CPLTestBoolean( const char *pszValue );
 
 #ifdef __cplusplus
 #ifdef DO_NOT_USE_DEBUG_BOOL
 #define CPLTestBool(x) CPL_TO_BOOL(CPLTestBoolean(x))
-#else
+#define CPLFetchBool(list,key,default) \
+    CPL_TO_BOOL(CSLFetchBoolean(list,key,default))
+#else /* DO_NOT_USE_DEBUG_BOOL */
 /* Prefer these for C++ code. */
 #ifdef DEBUG_BOOL
 extern "C++" {
 #endif
 bool CPL_DLL CPLTestBool( const char *pszValue );
+bool CPL_DLL CPLFetchBool( const char * const *papszStrList, const char *pszKey,
+                           bool bDefault );
 #ifdef DEBUG_BOOL
 }
 #endif
 #endif
-bool CPL_DLL CPLFetchBool( const char **papszStrList, const char *pszKey,
-                           bool bDefault );
 #endif  /* __cplusplus */
 
 const char CPL_DLL *
-      CPLParseNameValue(const char *pszNameValue, char **ppszKey );
+      CPLParseNameValue( const char *pszNameValue, char **ppszKey );
+
+#ifdef __cplusplus
+const char CPL_DLL *
+      CSLFetchNameValue( const char * const *papszStrList, const char *pszName);
+const char CPL_DLL *
+      CSLFetchNameValueDef( const char * const *papszStrList,
+                            const char *pszName,
+                            const char *pszDefault );
+#else
 const char CPL_DLL *
-      CSLFetchNameValue(char **papszStrList, const char *pszName);
+      CSLFetchNameValue( char **papszStrList, const char *pszName);
 const char CPL_DLL *
-      CSLFetchNameValueDef(char **papszStrList, const char *pszName,
-                           const char *pszDefault );
+      CSLFetchNameValueDef( char **papszStrList,
+                            const char *pszName,
+                            const char *pszDefault );
+#endif
+
 char CPL_DLL **
       CSLFetchNameValueMultiple(char **papszStrList, const char *pszName);
 char CPL_DLL **
@@ -154,11 +194,17 @@ void CPL_DLL CSLSetNameValueSeparator( char ** papszStrList,
 
 char CPL_DLL ** CSLParseCommandLine(const char* pszCommandLine);
 
+/** Scheme for CPLEscapeString()/CPLUnescapeString() for backlash quoting */
 #define CPLES_BackslashQuotable 0
+/** Scheme for CPLEscapeString()/CPLUnescapeString() for XML */
 #define CPLES_XML               1
+/** Scheme for CPLEscapeString()/CPLUnescapeString() for URL */
 #define CPLES_URL               2
+/** Scheme for CPLEscapeString()/CPLUnescapeString() for SQL */
 #define CPLES_SQL               3
+/** Scheme for CPLEscapeString()/CPLUnescapeString() for CSV */
 #define CPLES_CSV               4
+/** Scheme for CPLEscapeString()/CPLUnescapeString() for XML (preserves quotes) */
 #define CPLES_XML_BUT_QUOTES    5
 
 char CPL_DLL *CPLEscapeString( const char *pszString, int nLength,
@@ -175,11 +221,12 @@ char CPL_DLL *CPLBase64Encode( int nBytes,
                                const GByte *pabyData ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL CPLBase64DecodeInPlace( GByte* pszBase64 );
 
+/** Type of value */
 typedef enum
 {
-    CPL_VALUE_STRING,
-    CPL_VALUE_REAL,
-    CPL_VALUE_INTEGER
+    CPL_VALUE_STRING,  /**< String */
+    CPL_VALUE_REAL,    /**< Real number */
+    CPL_VALUE_INTEGER  /**< Integer */
 } CPLValueType;
 
 CPLValueType CPL_DLL CPLGetValueType(const char* pszValue);
@@ -191,42 +238,73 @@ size_t CPL_DLL CPLStrnlen(const char *pszStr, size_t nMaxLen);
 /* -------------------------------------------------------------------- */
 /*      Locale independent formatting functions.                        */
 /* -------------------------------------------------------------------- */
-int CPL_DLL CPLvsnprintf(char *str, size_t size, const char* fmt,
-                         va_list args) CPL_PRINT_FUNC_FORMAT (3, 0);
-int CPL_DLL CPLsnprintf(char *str, size_t size,
-                        const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(3,4);
+int CPL_DLL CPLvsnprintf( char *str, size_t size,
+                          CPL_FORMAT_STRING(const char* fmt),
+                          va_list args )
+    CPL_PRINT_FUNC_FORMAT(3, 0 );
+
+/* ALIAS_CPLSNPRINTF_AS_SNPRINTF might be defined to enable GCC 7 */
+/* -Wformat-truncation= warnings, but shouldn't be set for normal use */
+#if defined(ALIAS_CPLSNPRINTF_AS_SNPRINTF)
+#define CPLsnprintf snprintf
+#else
+int CPL_DLL CPLsnprintf( char *str, size_t size,
+                         CPL_FORMAT_STRING(const char* fmt), ... )
+    CPL_PRINT_FUNC_FORMAT(3, 4);
+#endif
+
+/*! @cond Doxygen_Suppress */
 #if defined(GDAL_COMPILATION) && !defined(DONT_DEPRECATE_SPRINTF)
-int CPL_DLL CPLsprintf(char *str, const char* fmt, ...)
-    CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_DEPRECATED("Use CPLsnprintf instead");
+int CPL_DLL CPLsprintf( char *str, CPL_FORMAT_STRING(const char* fmt), ... )
+    CPL_PRINT_FUNC_FORMAT(2, 3)
+    CPL_WARN_DEPRECATED("Use CPLsnprintf instead");
 #else
-int CPL_DLL CPLsprintf(char *str, const char* fmt, ...)
+int CPL_DLL CPLsprintf( char *str, CPL_FORMAT_STRING(const char* fmt), ... )
     CPL_PRINT_FUNC_FORMAT(2, 3);
 #endif
-int CPL_DLL CPLprintf(const char* fmt, ...) CPL_PRINT_FUNC_FORMAT(1, 2);
+/*! @endcond */
+int CPL_DLL CPLprintf( CPL_FORMAT_STRING(const char* fmt), ... )
+    CPL_PRINT_FUNC_FORMAT(1, 2);
+
+/* For some reason Doxygen_Suppress is needed to avoid warning. Not sure why */
+/*! @cond Doxygen_Suppress */
 /* caution: only works with limited number of formats */
-int CPL_DLL CPLsscanf(const char* str, const char* fmt, ...)
+int CPL_DLL CPLsscanf( const char* str,
+                       CPL_SCANF_FORMAT_STRING(const char* fmt), ... )
     CPL_SCAN_FUNC_FORMAT(2, 3);
+/*! @endcond */
 
-const char CPL_DLL *CPLSPrintf(const char *fmt, ...)
+const char CPL_DLL *CPLSPrintf( CPL_FORMAT_STRING(const char *fmt), ... )
     CPL_PRINT_FUNC_FORMAT(1, 2) CPL_WARN_UNUSED_RESULT;
-char CPL_DLL **CSLAppendPrintf(char **papszStrList, const char *fmt, ...)
+char CPL_DLL **CSLAppendPrintf( char **papszStrList,
+                                CPL_FORMAT_STRING(const char *fmt), ... )
     CPL_PRINT_FUNC_FORMAT(2, 3) CPL_WARN_UNUSED_RESULT;
-int CPL_DLL CPLVASPrintf(char **buf, const char *fmt, va_list args )
+int CPL_DLL CPLVASPrintf( char **buf,
+                          CPL_FORMAT_STRING(const char *fmt), va_list args )
     CPL_PRINT_FUNC_FORMAT(2, 0);
 
 /* -------------------------------------------------------------------- */
 /*      RFC 23 character set conversion/recoding API (cpl_recode.cpp).  */
 /* -------------------------------------------------------------------- */
+/** Encoding of the current locale */
 #define CPL_ENC_LOCALE     ""
+/** UTF-8 encoding */
 #define CPL_ENC_UTF8       "UTF-8"
+/** UTF-16 encoding */
 #define CPL_ENC_UTF16      "UTF-16"
+/** UCS-2 encoding */
 #define CPL_ENC_UCS2       "UCS-2"
+/** UCS-4 encoding */
 #define CPL_ENC_UCS4       "UCS-4"
+/** ASCII encoding */
 #define CPL_ENC_ASCII      "ASCII"
+/** ISO-8859-1 (LATIN1) encoding */
 #define CPL_ENC_ISO8859_1  "ISO-8859-1"
 
 int CPL_DLL  CPLEncodingCharSize( const char *pszEncoding );
+/*! @cond Doxygen_Suppress */
 void CPL_DLL  CPLClearRecodeWarningFlags( void );
+/*! @endcond */
 char CPL_DLL *CPLRecode(
     const char *pszSource, const char *pszSrcEncoding,
     const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT CPL_RETURNS_NONNULL;
@@ -236,11 +314,11 @@ char CPL_DLL *CPLRecodeFromWChar(
 wchar_t CPL_DLL *CPLRecodeToWChar(
     const char *pszSource, const char *pszSrcEncoding,
     const char *pszDstEncoding ) CPL_WARN_UNUSED_RESULT;
-int CPL_DLL CPLIsUTF8(const char* pabyData, int nLen);
+int CPL_DLL CPLIsUTF8( const char* pabyData, int nLen );
 char CPL_DLL *CPLForceToASCII(
     const char* pabyData, int nLen,
-    char chReplacementChar) CPL_WARN_UNUSED_RESULT;
-int CPL_DLL CPLStrlenUTF8(const char *pszUTF8Str);
+    char chReplacementChar ) CPL_WARN_UNUSED_RESULT;
+int CPL_DLL CPLStrlenUTF8( const char *pszUTF8Str );
 
 CPL_C_END
 
@@ -250,7 +328,11 @@ CPL_C_END
 
 #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
 
+extern "C++"
+{
+#ifndef DOXYGEN_SKIP
 #include <string>
+#endif
 
 /*
  * Simple trick to avoid "using" declaration in header for new compilers
@@ -276,7 +358,9 @@ CPL_C_END
     using std::string;
 # define gdal_std_string string
 #else
+/*! @cond Doxygen_Suppress */
 # define gdal_std_string std::string
+/*! @endcond */
 #endif
 
 //! Convenient string class based on std::string.
@@ -284,38 +368,59 @@ class CPL_DLL CPLString : public gdal_std_string
 {
 public:
 
+    /** Constructor */
     CPLString(void) {}
+    /** Constructor */
+    // cppcheck-suppress noExplicitConstructor
     CPLString( const std::string &oStr ) : gdal_std_string( oStr ) {}
+    /** Constructor */
+    // cppcheck-suppress noExplicitConstructor
     CPLString( const char *pszStr ) : gdal_std_string( pszStr ) {}
 
+    /** Return string as zero terminated character array */
     operator const char* (void) const { return c_str(); }
 
+    /** Return character at specified index */
     char& operator[](std::string::size_type i)
     {
         return gdal_std_string::operator[](i);
     }
 
+    /** Return character at specified index */
     const char& operator[](std::string::size_type i) const
     {
         return gdal_std_string::operator[](i);
     }
 
+    /** Return character at specified index */
     char& operator[](int i)
     {
         return gdal_std_string::operator[](
             static_cast<std::string::size_type>(i));
     }
 
+    /** Return character at specified index */
     const char& operator[](int i) const
     {
         return gdal_std_string::operator[](
             static_cast<std::string::size_type>(i));
     }
 
+    // Note: This is standard in C++11.
+#ifndef HAVE_CXX11
+    /** Return last character (undefined behaviour if string is empty) */
+    const char& back() const { return operator[](size()-1); }
+    /** Return last character (undefined behaviour if string is empty) */
+    char& back() { return operator[](size()-1); }
+#endif
+
+    /** Clear the string */
     void Clear() { resize(0); }
 
-    // NULL safe assign and free.
-    void Seize(char *pszValue)
+    /** Assign specified string and take ownership of it (assumed to be
+     * allocated with CPLMalloc()). NULL can be safely passed to clear the
+     * string. */
+    void Seize( char *pszValue )
     {
         if (pszValue == NULL )
             Clear();
@@ -329,12 +434,19 @@ public:
     /* There seems to be a bug in the way the compiler count indices...
      * Should be CPL_PRINT_FUNC_FORMAT (1, 2) */
     CPLString &Printf(
-        const char *pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (2, 3);
+        CPL_FORMAT_STRING(const char *pszFormat), ... )
+        CPL_PRINT_FUNC_FORMAT (2, 3);
     CPLString &vPrintf(
-        const char *pszFormat, va_list args ) CPL_PRINT_FUNC_FORMAT(2, 0);
+        CPL_FORMAT_STRING(const char *pszFormat), va_list args )
+        CPL_PRINT_FUNC_FORMAT(2, 0);
     CPLString &FormatC( double dfValue, const char *pszFormat = NULL );
     CPLString &Trim();
     CPLString &Recode( const char *pszSrcEncoding, const char *pszDstEncoding );
+    CPLString &replaceAll(
+        const std::string &osBefore, const std::string& osAfter );
+    CPLString &replaceAll( const std::string &osBefore, char chAfter );
+    CPLString &replaceAll( char chBefore, const std::string &osAfter );
+    CPLString &replaceAll( char chBefore, char chAfter );
 
     /* case insensitive find alternates */
     size_t    ifind( const std::string & str, size_t pos = 0 ) const;
@@ -343,9 +455,11 @@ public:
     CPLString &tolower( void );
 };
 
-CPLString CPLOPrintf(const char *pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (1, 2);
-CPLString CPLOvPrintf(
-    const char *pszFormat, va_list args) CPL_PRINT_FUNC_FORMAT (1, 0);
+CPLString CPL_DLL CPLOPrintf(CPL_FORMAT_STRING(const char *pszFormat), ... )
+    CPL_PRINT_FUNC_FORMAT (1, 2);
+CPLString CPL_DLL CPLOvPrintf(
+    CPL_FORMAT_STRING(const char *pszFormat), va_list args)
+    CPL_PRINT_FUNC_FORMAT (1, 0);
 
 /* -------------------------------------------------------------------- */
 /*      URL processing functions, here since they depend on CPLString.  */
@@ -380,9 +494,13 @@ class CPL_DLL CPLStringList
 
     CPLStringList &Clear();
 
+    /** Return size of list */
     int    size() const { return Count(); }
     int    Count() const;
 
+    /** Return whether the list is empty. */
+    bool   empty() const { return Count() == 0; }
+
     CPLStringList &AddString( const char *pszNewString );
     CPLStringList &AddStringDirectly( char *pszNewString );
 
@@ -393,8 +511,10 @@ class CPL_DLL CPLStringList
     // CPLStringList &InsertStrings( int nInsertAtLineNo, char **papszNewLines );
     // CPLStringList &RemoveStrings( int nFirstLineToDelete, int nNumToRemove=1 );
 
+    /** Return index of pszTarget in the list, or -1 */
     int    FindString( const char *pszTarget ) const
     { return CSLFindString( papszList, pszTarget ); }
+    /** Return index of pszTarget in the list (using partial search), or -1 */
     int    PartialFindString( const char *pszNeedle ) const
     { return CSLPartialFindString( papszList, pszNeedle ); }
 
@@ -409,25 +529,36 @@ class CPL_DLL CPLStringList
     CPLStringList &SetNameValue( const char *pszKey, const char *pszValue );
 
     CPLStringList &Assign( char **papszListIn, int bTakeOwnership=TRUE );
+    /** Assignment operator */
     CPLStringList &operator=(char **papszListIn) {
       return Assign( papszListIn, TRUE ); }
+    /** Assignment operator */
     CPLStringList &operator=(const CPLStringList& oOther);
 
+    /** Return string at specified index */
     char * operator[](int i);
+    /** Return string at specified index */
     char * operator[](size_t i) { return (*this)[static_cast<int>(i)]; }
+    /** Return string at specified index */
     const char * operator[](int i) const;
+    /** Return string at specified index */
     const char * operator[](size_t i) const {
       return (*this)[static_cast<int>(i)]; }
 
+    /** Return list. Ownership remains to the object */
     char **List() { return papszList; }
     char **StealList();
 
     CPLStringList &Sort();
+    /** Returns whether the list is sorted */
     int    IsSorted() const { return bIsSorted; }
 
+    /** Return lists */
     operator char**(void) { return List(); }
 };
 
+} // extern "C++"
+
 #endif /* def __cplusplus && !CPL_SUPRESS_CPLUSPLUS */
 
 #endif /* CPL_STRING_H_INCLUDED */
diff --git a/port/cpl_strtod.cpp b/port/cpl_strtod.cpp
index a0e6b50..9d6c1f4 100644
--- a/port/cpl_strtod.cpp
+++ b/port/cpl_strtod.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_strtod.cpp 33679 2016-03-07 22:02:50Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Functions to convert ASCII string to floating point number.
@@ -28,15 +27,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include <locale.h>
+#include "cpl_port.h"
+#include "cpl_conv.h"
 
 #include <cerrno>
+#include <clocale>
+#include <cstring>
 #include <cstdlib>
 #include <limits>
 
-#include "cpl_conv.h"
+#include "cpl_config.h"
 
-CPL_CVSID("$Id: cpl_strtod.cpp 33679 2016-03-07 22:02:50Z goatbar $");
+CPL_CVSID("$Id: cpl_strtod.cpp 36928 2016-12-17 06:12:35Z goatbar $");
 
 // XXX: with GCC 2.95 strtof() function is only available when in c99 mode.
 // Fix it here not touching the compiler options.
@@ -70,7 +72,7 @@ extern float strtof(const char *nptr, char **endptr);
  */
 double CPLAtofDelim(const char *nptr, char point)
 {
-  return CPLStrtodDelim(nptr, NULL, point);
+    return CPLStrtodDelim(nptr, NULL, point);
 }
 
 /************************************************************************/
@@ -91,14 +93,16 @@ double CPLAtofDelim(const char *nptr, char point)
  * (decimal point). Use CPLAtofDelim() function if you want to specify
  * custom delimiter.
  *
- * IMPORTANT NOTE.
- * Existence of this function does not mean you should always use it.
- * Sometimes you should use standard locale aware atof(3) and its family. When
- * you need to process the user's input (for example, command line parameters)
- * use atof(3), because the user works in a localized environment and the user's input will
+ * IMPORTANT NOTE:
+ *
+ * Existence of this function does not mean you should always use it.  Sometimes
+ * you should use standard locale aware atof(3) and its family. When you need to
+ * process the user's input (for example, command line parameters) use atof(3),
+ * because the user works in a localized environment and the user's input will
  * be done according to the locale set. In particular that means we should not
- * make assumptions about character used as decimal delimiter, it can be
- * either "." or ",".
+ * make assumptions about character used as decimal delimiter, it can be either
+ * "." or ",".
+ *
  * But when you are parsing some ASCII file in predefined format, you most
  * likely need CPLAtof(), because such files distributed across the systems
  * with different locales and floating point representation should be
@@ -112,7 +116,7 @@ double CPLAtofDelim(const char *nptr, char point)
  */
 double CPLAtof(const char *nptr)
 {
-  return CPLStrtod(nptr, NULL);
+    return CPLStrtod(nptr, NULL);
 }
 
 /************************************************************************/
@@ -155,20 +159,20 @@ double CPLAtofM( const char *nptr )
 /*                      CPLReplacePointByLocalePoint()                  */
 /************************************************************************/
 
-static char* CPLReplacePointByLocalePoint(const char* pszNumber, char point)
+static char* CPLReplacePointByLocalePoint( const char* pszNumber, char point )
 {
 #if defined(__ANDROID__)
     static char byPoint = 0;
-    if (byPoint == 0)
+    if( byPoint == 0 )
     {
-        char szBuf[16];
+        char szBuf[16] = {};
         snprintf(szBuf, sizeof(szBuf), "%.1f", 1.0);
         byPoint = szBuf[1];
     }
-    if (point != byPoint)
+    if( point != byPoint )
     {
         const char* pszPoint = strchr(pszNumber, point);
-        if (pszPoint)
+        if( pszPoint )
         {
             char* pszNew = CPLStrdup(pszNumber);
             pszNew[pszPoint - pszNumber] = byPoint;
@@ -177,17 +181,17 @@ static char* CPLReplacePointByLocalePoint(const char* pszNumber, char point)
     }
 #else  // ndef __ANDROID__
     struct lconv *poLconv = localeconv();
-    if ( poLconv
-         && poLconv->decimal_point
-         && poLconv->decimal_point[0] != '\0' )
+    if( poLconv
+        && poLconv->decimal_point
+        && poLconv->decimal_point[0] != '\0' )
     {
         char byPoint = poLconv->decimal_point[0];
 
-        if (point != byPoint)
+        if( point != byPoint )
         {
             const char* pszLocalePoint = strchr(pszNumber, byPoint);
             const char* pszPoint = strchr(pszNumber, point);
-            if (pszPoint || pszLocalePoint)
+            if( pszPoint || pszLocalePoint )
             {
                 char* pszNew = CPLStrdup(pszNumber);
                 if( pszLocalePoint )
@@ -227,48 +231,48 @@ static char* CPLReplacePointByLocalePoint(const char* pszNumber, char point)
 double CPLStrtodDelim(const char *nptr, char **endptr, char point)
 {
     while( *nptr == ' ' )
-        nptr ++;
+        nptr++;
 
-    if (nptr[0] == '-')
+    if( nptr[0] == '-' )
     {
-        if (strcmp(nptr, "-1.#QNAN") == 0 ||
-            strcmp(nptr, "-1.#IND") == 0)
+        if( strcmp(nptr, "-1.#QNAN") == 0 ||
+            strcmp(nptr, "-1.#IND") == 0 )
         {
-            if( endptr ) *endptr = (char*)nptr + strlen(nptr);
+            if( endptr ) *endptr = const_cast<char *>(nptr) + strlen(nptr);
             // While it is possible on some platforms to flip the sign
             // of NAN to negative, this function will always return a positive
             // quiet (non-signalling) NaN.
             return std::numeric_limits<double>::quiet_NaN();
         }
 
-        if (strcmp(nptr,"-inf") == 0 ||
-            STARTS_WITH_CI(nptr, "-1.#INF"))
+        if( strcmp(nptr, "-inf") == 0 ||
+            STARTS_WITH_CI(nptr, "-1.#INF") )
         {
-            if( endptr ) *endptr = (char*)nptr + strlen(nptr);
+            if( endptr ) *endptr = const_cast<char *>(nptr) + strlen(nptr);
             return -std::numeric_limits<double>::infinity();
         }
     }
-    else if (nptr[0] == '1')
+    else if( nptr[0] == '1' )
     {
-        if (strcmp(nptr, "1.#QNAN") == 0)
+        if( strcmp(nptr, "1.#QNAN") == 0 )
         {
-            if( endptr ) *endptr = (char*)nptr + strlen(nptr);
+            if( endptr ) *endptr = const_cast<char *>(nptr) + strlen(nptr);
             return std::numeric_limits<double>::quiet_NaN();
         }
         if( STARTS_WITH_CI(nptr, "1.#INF") )
         {
-            if( endptr ) *endptr = (char*)nptr + strlen(nptr);
+            if( endptr ) *endptr = const_cast<char*>(nptr) + strlen(nptr);
             return std::numeric_limits<double>::infinity();
         }
     }
-    else if (nptr[0] == 'i' && strcmp(nptr,"inf") == 0)
+    else if( nptr[0] == 'i' && strcmp(nptr, "inf") == 0 )
     {
-        if( endptr ) *endptr = (char*)nptr + strlen(nptr);
+        if( endptr ) *endptr = const_cast<char *>(nptr) + strlen(nptr);
         return std::numeric_limits<double>::infinity();
     }
-    else if (nptr[0] == 'n' && strcmp(nptr,"nan") == 0)
+    else if( nptr[0] == 'n' && strcmp(nptr, "nan") == 0 )
     {
-        if( endptr ) *endptr = (char*)nptr + strlen(nptr);
+        if( endptr ) *endptr = const_cast<char *>(nptr) + strlen(nptr);
         return std::numeric_limits<double>::quiet_NaN();
     }
 
@@ -283,10 +287,10 @@ double CPLStrtodDelim(const char *nptr, char **endptr, char point)
     const double dfValue = strtod( pszNumber, endptr );
     const int nError = errno;
 
-    if ( endptr )
-        *endptr = (char *)nptr + (*endptr - pszNumber);
+    if( endptr )
+        *endptr = const_cast<char *>(nptr) + (*endptr - pszNumber);
 
-    if (pszNumber != (char*) nptr)
+    if( pszNumber != const_cast<char *>(nptr) )
         CPLFree( pszNumber );
 
     errno = nError;
@@ -353,14 +357,14 @@ float CPLStrtofDelim(const char *nptr, char **endptr, char point)
     double dfValue = strtof( pszNumber, endptr );
     const int nError = errno;
 
-    if ( endptr )
+    if( endptr )
         *endptr = const_cast<char *>(nptr) + (*endptr - pszNumber);
 
-    if (pszNumber != nptr)
+    if( pszNumber != nptr )
         CPLFree( pszNumber );
 
     errno = nError;
-    return dfValue;
+    return static_cast<float>(dfValue);
 
 #else
 
diff --git a/port/cpl_time.cpp b/port/cpl_time.cpp
index d7e0131..b3b10ee 100644
--- a/port/cpl_time.cpp
+++ b/port/cpl_time.cpp
@@ -1,6 +1,4 @@
-
 /**********************************************************************
- * $Id: cpl_time.cpp 33783 2016-03-24 13:45:22Z goatbar $
  *
  * Name:     cpl_time.cpp
  * Project:  CPL - Common Portability Library
@@ -23,8 +21,14 @@
  */
 
 #include "cpl_time.h"
+
+#include <cstring>
+#include <ctime>
+
 #include "cpl_error.h"
 
+CPL_CVSID("$Id: cpl_time.cpp 36928 2016-12-17 06:12:35Z goatbar $");
+
 static const int SECSPERMIN = 60;
 static const int MINSPERHOUR = 60;
 static const int HOURSPERDAY = 24;
@@ -39,18 +43,20 @@ static const int TM_YEAR_BASE = 1900;
 static const int DAYSPERNYEAR = 365;
 static const int DAYSPERLYEAR = 366;
 
-static bool isleap(int y) {
-  return ((y % 4) == 0 && (y % 100) != 0) || (y % 400) == 0;
+static bool isleap( int y )
+{
+    return ((y % 4) == 0 && (y % 100) != 0) || (y % 400) == 0;
 }
 
-static int LEAPS_THROUGH_END_OF(int y) {
-  return y / 4 - y / 100 + y / 400;
+static int LEAPS_THROUGH_END_OF( int y )
+{
+    return y / 4 - y / 100 + y / 400;
 }
 
 static const int mon_lengths[2][MONSPERYEAR] = {
-  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
-  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
-} ;
+    { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+    { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
 
 static const int year_lengths[2] = { DAYSPERNYEAR, DAYSPERLYEAR };
 
@@ -75,8 +81,8 @@ struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
     GIntBig days = unixTime / SECSPERDAY;
     GIntBig rem = unixTime % SECSPERDAY;
 
-    if( unixTime < -(GIntBig)10000 * SECSPERDAY * DAYSPERLYEAR ||
-        unixTime > (GIntBig)10000 * SECSPERDAY * DAYSPERLYEAR )
+    if( unixTime < -static_cast<GIntBig>(10000) * SECSPERDAY * DAYSPERLYEAR ||
+        unixTime > static_cast<GIntBig>(10000) * SECSPERDAY * DAYSPERLYEAR )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Invalid unixTime = " CPL_FRMT_GIB,
@@ -85,7 +91,8 @@ struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
         return pRet;
     }
 
-    while (rem < 0) {
+    while( rem < 0 )
+    {
         rem += SECSPERDAY;
         --days;
     }
@@ -99,16 +106,16 @@ struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
     */
     pRet->tm_sec = static_cast<int>( rem % SECSPERMIN );
     pRet->tm_wday = static_cast<int>( (EPOCH_WDAY + days) % DAYSPERWEEK );
-    if (pRet->tm_wday < 0)
+    if( pRet->tm_wday < 0 )
         pRet->tm_wday += DAYSPERWEEK;
 
     int y = EPOCH_YEAR;
     int yleap = 0;
-    while ( days < 0
-            || days >= static_cast<GIntBig>( year_lengths[yleap = isleap(y)] ) )
+    while( days < 0
+           || days >= static_cast<GIntBig>( year_lengths[yleap = isleap(y)] ) )
     {
         int newy = y + static_cast<int>( days / DAYSPERNYEAR );
-        if (days < 0)
+        if( days < 0 )
             --newy;
         days -= (newy - y) * DAYSPERNYEAR +
             LEAPS_THROUGH_END_OF(newy - 1) -
@@ -120,7 +127,7 @@ struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
     pRet->tm_yday = static_cast<int>( days );
     const int* ip = mon_lengths[yleap];
 
-    for (pRet->tm_mon = 0;
+    for( pRet->tm_mon = 0;
          days >= static_cast<GIntBig>( ip[pRet->tm_mon] );
          ++(pRet->tm_mon) )
         days = days - static_cast<GIntBig>( ip[pRet->tm_mon] );
@@ -148,33 +155,37 @@ struct tm * CPLUnixTimeToYMDHMS(GIntBig unixTime, struct tm* pRet)
  *         GIntBig, or -1 if the time cannot be represented.
  */
 
-GIntBig CPLYMDHMSToUnixTime(const struct tm *brokendowntime)
+GIntBig CPLYMDHMSToUnixTime( const struct tm *brokendowntime )
 {
 
-  if (brokendowntime->tm_mon < 0 || brokendowntime->tm_mon >= 12)
-    return -1;
-
-  /* Number of days of the current month */
-  GIntBig days = brokendowntime->tm_mday - 1;
-
-  /* Add the number of days of the current year */
-  const int* ip = mon_lengths[static_cast<int>(isleap(TM_YEAR_BASE + brokendowntime->tm_year))];
-  for( int mon = 0; mon < brokendowntime->tm_mon; mon++ )
-      days += ip[mon];
-
-  /* Add the number of days of the other years */
-  days +=
-      ( TM_YEAR_BASE
-        + static_cast<GIntBig>( brokendowntime->tm_year )
-        - EPOCH_YEAR ) * DAYSPERNYEAR
-      + LEAPS_THROUGH_END_OF( static_cast<int> (TM_YEAR_BASE )
-                           + static_cast<int>( brokendowntime->tm_year )
-                           - static_cast<int>( 1 ) )
-      - LEAPS_THROUGH_END_OF( EPOCH_YEAR - 1 );
-
-  /* Now add the secondes, minutes and hours to the number of days since EPOCH */
-  return brokendowntime->tm_sec +
-         brokendowntime->tm_min * SECSPERMIN +
-         brokendowntime->tm_hour * SECSPERHOUR +
-         days * SECSPERDAY;
+    if( brokendowntime->tm_mon < 0 || brokendowntime->tm_mon >= 12 )
+        return -1;
+
+    // Number of days of the current month.
+    GIntBig days = brokendowntime->tm_mday - 1;
+
+    // Add the number of days of the current year.
+    const int* ip =
+        mon_lengths[static_cast<int>(isleap(TM_YEAR_BASE +
+                                            brokendowntime->tm_year))];
+    for( int mon = 0; mon < brokendowntime->tm_mon; mon++ )
+        days += ip[mon];
+
+    // Add the number of days of the other years.
+    days +=
+        ( TM_YEAR_BASE
+          + static_cast<GIntBig>(brokendowntime->tm_year)
+          - EPOCH_YEAR ) * DAYSPERNYEAR
+        + LEAPS_THROUGH_END_OF(static_cast<int>(TM_YEAR_BASE)
+                               + static_cast<int>( brokendowntime->tm_year)
+                               - static_cast<int>(1))
+        - LEAPS_THROUGH_END_OF( EPOCH_YEAR - 1 );
+
+    // Now add the secondes, minutes and hours to the number of days
+    // since EPOCH.
+    return
+        brokendowntime->tm_sec +
+        brokendowntime->tm_min * SECSPERMIN +
+        brokendowntime->tm_hour * SECSPERHOUR +
+        days * SECSPERDAY;
 }
diff --git a/port/cpl_time.h b/port/cpl_time.h
index 7b57f4a..432b32f 100644
--- a/port/cpl_time.h
+++ b/port/cpl_time.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_time.h 33783 2016-03-24 13:45:22Z goatbar $
+ * $Id: cpl_time.h 34518 2016-07-02 21:01:34Z goatbar $
  *
  * Name:     cpl_time.h
  * Project:  CPL - Common Portability Library
diff --git a/port/cpl_virtualmem.cpp b/port/cpl_virtualmem.cpp
index e230499..855d3fa 100644
--- a/port/cpl_virtualmem.cpp
+++ b/port/cpl_virtualmem.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_virtualmem.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Name:     cpl_virtualmem.cpp
  * Project:  CPL - Common Portability Library
@@ -38,18 +37,24 @@
 #endif
 
 #include "cpl_virtualmem.h"
-#include "cpl_error.h"
-#include "cpl_multiproc.h"
+
+#include <cassert>
+// TODO(schwehr): Should ucontext.h be included?
+// #include <ucontext.h>
+
 #include "cpl_atomic_ops.h"
+#include "cpl_config.h"
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
 
-#include <cassert>
+CPL_CVSID("$Id: cpl_virtualmem.cpp 36935 2016-12-17 15:12:03Z goatbar $");
 
 #ifdef NDEBUG
-/* Non NDEBUG: we ignore the result */
+// Non NDEBUG: Ignore the result.
 #define IGNORE_OR_ASSERT_IN_DEBUG(expr) CPL_IGNORE_RET_VAL((expr))
 #else
-/* Debug: assert */
+// Debug: Assert.
 #define IGNORE_OR_ASSERT_IN_DEBUG(expr) assert((expr))
 #endif
 
@@ -58,8 +63,8 @@
 #endif
 
 #if defined(HAVE_MMAP) || defined(HAVE_VIRTUAL_MEM_VMA)
-#include <unistd.h>     /* read, write, close, pipe, sysconf */
-#include <sys/mman.h>   /* mmap, munmap, mremap */
+#include <unistd.h>     // read, write, close, pipe, sysconf
+#include <sys/mman.h>   // mmap, munmap, mremap
 #endif
 
 typedef enum
@@ -78,11 +83,14 @@ struct CPLVirtualMem
     CPLVirtualMemAccessMode eAccessMode;
 
     size_t       nPageSize;
-    void        *pData;        // aligned on nPageSize
-    void        *pDataToFree;  // returned by mmap(), potentially lower than pData
-    size_t       nSize;        // requested size (unrounded)
+    // Aligned on nPageSize.
+    void        *pData;
+    // Returned by mmap(), potentially lower than pData.
+    void        *pDataToFree;
+    // Requested size (unrounded).
+    size_t       nSize;
 
-    int          bSingleThreadUsage;
+    bool         bSingleThreadUsage;
 
     void                         *pCbkUserData;
     CPLVirtualMemFreeUserData     pfnFreeUserData;
@@ -90,25 +98,25 @@ struct CPLVirtualMem
 
 #ifdef HAVE_VIRTUAL_MEM_VMA
 
-#include <sys/select.h> /* select */
-#include <sys/stat.h>   /* open() */
-#include <sys/types.h>  /* open() */
+#include <sys/select.h> // select
+#include <sys/stat.h>   // open()
+#include <sys/types.h>  // open()
 #include <errno.h>
-#include <fcntl.h>      /* open() */
-#include <signal.h>     /* sigaction */
+#include <fcntl.h>      // open()
+#include <signal.h>     // sigaction
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
 
 // FIXME? gcore/virtualmem.py tests fail/crash when HAVE_5ARGS_MREMAP
-// is not defined
+// is not defined.
 
 #ifndef HAVE_5ARGS_MREMAP
 #include "cpl_atomic_ops.h"
 #endif
 
-/* Linux specific (i.e. non POSIX compliant) features used :
+/* Linux specific (i.e. non POSIX compliant) features used:
    - returning from a SIGSEGV handler is clearly a POSIX violation, but in
      practice most POSIX systems should be happy.
    - mremap() with 5 args is Linux specific. It is used when the user
@@ -127,24 +135,23 @@ struct CPLVirtualMem
    - other things I've not identified
 */
 
-
-#define ALIGN_DOWN(p,pagesize)  (void*)(((size_t)(p)) / (pagesize) * (pagesize))
-#define ALIGN_UP(p,pagesize)    (void*)(((size_t)(p) + (pagesize) - 1) / (pagesize) * (pagesize))
+#define ALIGN_DOWN(p,pagesize) (void*)(((GUIntptr_t)(p)) / (pagesize) * (pagesize))
+#define ALIGN_UP(p,pagesize) (void*)(((GUIntptr_t)(p) + (pagesize) - 1) / (pagesize) * (pagesize))
 
 #define DEFAULT_PAGE_SIZE       (256*256)
 #define MAXIMUM_PAGE_SIZE       (32*1024*1024)
 
-/* Linux Kernel limit */
+// Linux Kernel limit.
 #define MAXIMUM_COUNT_OF_MAPPINGS   65536
 
-#define BYEBYE_ADDR             ((void*)(~(size_t)0))
+#define BYEBYE_ADDR             ((void*)(~static_cast<size_t>(0)))
 
 #define MAPPING_FOUND           "yeah"
 #define MAPPING_NOT_FOUND       "doh!"
 
-#define SET_BIT(ar,bitnumber)       ar[(bitnumber)/8] |= 1 << ((bitnumber) % 8)
-#define UNSET_BIT(ar,bitnumber)     ar[(bitnumber)/8] &= ~(1 << ((bitnumber) % 8))
-#define TEST_BIT(ar,bitnumber)      (ar[(bitnumber)/8] & (1 << ((bitnumber) % 8)))
+#define SET_BIT(ar,bitnumber)   ar[(bitnumber)/8] |= 1 << ((bitnumber) % 8)
+#define UNSET_BIT(ar,bitnumber) ar[(bitnumber)/8] &= ~(1 << ((bitnumber) % 8))
+#define TEST_BIT(ar,bitnumber)  (ar[(bitnumber)/8] & (1 << ((bitnumber) % 8)))
 
 typedef enum
 {
@@ -161,16 +168,20 @@ typedef struct
     GByte       *pabitMappedPages;
     GByte       *pabitRWMappedPages;
 
-    int          nCacheMaxSizeInPages;   /* maximum size of page array */
-    int         *panLRUPageIndices;      /* array with indices of cached pages */
-    int          iLRUStart;              /* index in array where to write next page index */
-    int          nLRUSize;               /* current size of the array */
+    int          nCacheMaxSizeInPages;   // Maximum size of page array.
+    int         *panLRUPageIndices;      // Array with indices of cached pages.
+    int          iLRUStart;              // Index in array where to
+                                         // write next page index.
+    int          nLRUSize;               // Current size of the array.
 
-    int          iLastPage;              /* last page accessed */
-    int          nRetry;                 /* number of consecutive retries to that last page */
+    int          iLastPage;              // Last page accessed.
+    int          nRetry;                 // Number of consecutive
+                                         // retries to that last page.
 
-    CPLVirtualMemCachePageCbk     pfnCachePage;       /* called when a page is mapped */
-    CPLVirtualMemUnCachePageCbk   pfnUnCachePage;     /* called when a (writable) page is unmapped */
+    CPLVirtualMemCachePageCbk     pfnCachePage;    // Called when a page is
+                                                   // mapped.
+    CPLVirtualMemUnCachePageCbk   pfnUnCachePage;  // Called when a (writable)
+                                                   // page is unmapped.
 
 #ifndef HAVE_5ARGS_MREMAP
     CPLMutex               *hMutexThreadArray;
@@ -181,7 +192,7 @@ typedef struct
 
 typedef struct
 {
-    /* hVirtualMemManagerMutex protects the 2 following variables */
+    // hVirtualMemManagerMutex protects the 2 following variables.
     CPLVirtualMemVMA **pasVirtualMem;
     int              nVirtualMemCount;
 
@@ -212,22 +223,31 @@ static bool CPLVirtualMemManagerInit();
 /*                           fprintfstderr()                            */
 /************************************************************************/
 
+// This function may be called from signal handlers where most functions
+// from the C library are unsafe to be called. fprintf() is clearly one
+// of those functions (see
+// http://stackoverflow.com/questions/4554129/linux-glibc-can-i-use-fprintf-in-signal-handler)
+// vsnprintf() is *probably* safer with respect to that (but there is no
+// guarantee though).
+// write() is async-signal-safe.
 static void fprintfstderr(const char* fmt, ...)
 {
-    char buffer[80];
+    char buffer[80] = {};
     va_list ap;
     va_start(ap, fmt);
     vsnprintf(buffer, sizeof(buffer), fmt, ap);
     va_end(ap);
     int offset = 0;
-    while(true)
+    while( true )
     {
-        int ret = write(2, buffer + offset, strlen(buffer + offset));
+        const size_t nSizeToWrite = strlen(buffer + offset);
+        int ret = static_cast<int>(write(2, buffer + offset, nSizeToWrite));
         if( ret < 0 && errno == EINTR )
-            ;
+        {
+        }
         else
         {
-            if( ret == static_cast<int>(strlen(buffer + offset)) )
+            if( ret == static_cast<int>(nSizeToWrite) )
                 break;
             offset += ret;
         }
@@ -240,7 +260,7 @@ static void fprintfstderr(const char* fmt, ...)
 /*              CPLVirtualMemManagerRegisterVirtualMem()                */
 /************************************************************************/
 
-static bool CPLVirtualMemManagerRegisterVirtualMem(CPLVirtualMemVMA* ctxt)
+static bool CPLVirtualMemManagerRegisterVirtualMem( CPLVirtualMemVMA* ctxt )
 {
     if( !CPLVirtualMemManagerInit() )
         return false;
@@ -248,15 +268,21 @@ static bool CPLVirtualMemManagerRegisterVirtualMem(CPLVirtualMemVMA* ctxt)
     bool bSuccess = true;
     IGNORE_OR_ASSERT_IN_DEBUG(ctxt);
     CPLAcquireMutex(hVirtualMemManagerMutex, 1000.0);
-    CPLVirtualMemVMA** pasVirtualMemNew = (CPLVirtualMemVMA**) VSI_REALLOC_VERBOSE(
-        pVirtualMemManager->pasVirtualMem, sizeof(CPLVirtualMemVMA*) * (pVirtualMemManager->nVirtualMemCount + 1) );
+    CPLVirtualMemVMA** pasVirtualMemNew = static_cast<CPLVirtualMemVMA **>(
+        VSI_REALLOC_VERBOSE(
+            pVirtualMemManager->pasVirtualMem,
+            sizeof(CPLVirtualMemVMA *) *
+            (pVirtualMemManager->nVirtualMemCount + 1)));
     if( pasVirtualMemNew == NULL )
+    {
         bSuccess = false;
+    }
     else
     {
         pVirtualMemManager->pasVirtualMem = pasVirtualMemNew;
-        pVirtualMemManager->pasVirtualMem[pVirtualMemManager->nVirtualMemCount] = ctxt;
-        pVirtualMemManager->nVirtualMemCount ++;
+        pVirtualMemManager->
+            pasVirtualMem[pVirtualMemManager->nVirtualMemCount] = ctxt;
+        pVirtualMemManager->nVirtualMemCount++;
     }
     CPLReleaseMutex(hVirtualMemManagerMutex);
     return bSuccess;
@@ -266,7 +292,7 @@ static bool CPLVirtualMemManagerRegisterVirtualMem(CPLVirtualMemVMA* ctxt)
 /*               CPLVirtualMemManagerUnregisterVirtualMem()             */
 /************************************************************************/
 
-static void CPLVirtualMemManagerUnregisterVirtualMem(CPLVirtualMemVMA* ctxt)
+static void CPLVirtualMemManagerUnregisterVirtualMem( CPLVirtualMemVMA* ctxt )
 {
     CPLAcquireMutex(hVirtualMemManagerMutex, 1000.0);
     for( int i=0; i < pVirtualMemManager->nVirtualMemCount; i++ )
@@ -275,11 +301,13 @@ static void CPLVirtualMemManagerUnregisterVirtualMem(CPLVirtualMemVMA* ctxt)
         {
             if( i < pVirtualMemManager->nVirtualMemCount - 1 )
             {
-                memmove( pVirtualMemManager->pasVirtualMem + i,
-                         pVirtualMemManager->pasVirtualMem + i + 1,
-                    sizeof(CPLVirtualMem*) * (pVirtualMemManager->nVirtualMemCount - i - 1) );
+                memmove(
+                    pVirtualMemManager->pasVirtualMem + i,
+                    pVirtualMemManager->pasVirtualMem + i + 1,
+                    sizeof(CPLVirtualMem*) *
+                    (pVirtualMemManager->nVirtualMemCount - i - 1) );
             }
-            pVirtualMemManager->nVirtualMemCount --;
+            pVirtualMemManager->nVirtualMemCount--;
             break;
         }
     }
@@ -290,25 +318,20 @@ static void CPLVirtualMemManagerUnregisterVirtualMem(CPLVirtualMemVMA* ctxt)
 /*                           CPLVirtualMemNew()                         */
 /************************************************************************/
 
-static void CPLVirtualMemFreeFileMemoryMapped(CPLVirtualMemVMA* ctxt);
-
-CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
-                                size_t nCacheSize,
-                                size_t nPageSizeHint,
-                                int bSingleThreadUsage,
-                                CPLVirtualMemAccessMode eAccessMode,
-                                CPLVirtualMemCachePageCbk pfnCachePage,
-                                CPLVirtualMemUnCachePageCbk pfnUnCachePage,
-                                CPLVirtualMemFreeUserData pfnFreeUserData,
-                                void *pCbkUserData)
+static void CPLVirtualMemFreeFileMemoryMapped( CPLVirtualMemVMA* ctxt );
+
+CPLVirtualMem* CPLVirtualMemNew( size_t nSize,
+                                 size_t nCacheSize,
+                                 size_t nPageSizeHint,
+                                 int bSingleThreadUsage,
+                                 CPLVirtualMemAccessMode eAccessMode,
+                                 CPLVirtualMemCachePageCbk pfnCachePage,
+                                 CPLVirtualMemUnCachePageCbk pfnUnCachePage,
+                                 CPLVirtualMemFreeUserData pfnFreeUserData,
+                                 void *pCbkUserData )
 {
-    CPLVirtualMemVMA* ctxt;
-    void* pData;
     size_t nMinPageSize = CPLGetPageSize();
     size_t nPageSize = DEFAULT_PAGE_SIZE;
-    size_t nRoundedMappingSize;
-    FILE* f;
-    int nMappings = 0;
 
     IGNORE_OR_ASSERT_IN_DEBUG(nSize > 0);
     IGNORE_OR_ASSERT_IN_DEBUG(pfnCachePage != NULL);
@@ -320,14 +343,14 @@ CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
         else
         {
             int nbits = 0;
-            nPageSize = (size_t)nPageSizeHint;
+            nPageSize = static_cast<size_t>(nPageSizeHint);
             do
             {
                 nPageSize >>= 1;
-                nbits ++;
-            } while(nPageSize > 0);
-            nPageSize = (size_t)1 << (nbits - 1);
-            if( nPageSize < (size_t)nPageSizeHint )
+                nbits++;
+            } while( nPageSize > 0 );
+            nPageSize = static_cast<size_t>(1) << (nbits - 1);
+            if( nPageSize < static_cast<size_t>(nPageSizeHint) )
                 nPageSize <<= 1;
         }
     }
@@ -340,36 +363,42 @@ CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
     else if( nCacheSize == 0 )
         nCacheSize = 1;
 
-    /* Linux specific */
-    /* Count the number of existing memory mappings */
-    f = fopen("/proc/self/maps", "rb");
+    int nMappings = 0;
+
+    // Linux specific:
+    // Count the number of existing memory mappings.
+    FILE* f = fopen("/proc/self/maps", "rb");
     if( f != NULL )
     {
-        char buffer[80];
+        char buffer[80] = {};
         while( fgets(buffer, sizeof(buffer), f) != NULL )
-            nMappings ++;
+            nMappings++;
         fclose(f);
     }
 
     size_t nCacheMaxSizeInPages = 0;
-    while(true)
+    while( true )
     {
-        /* /proc/self/maps must not have more than 65K lines */
+        // /proc/self/maps must not have more than 65K lines.
         nCacheMaxSizeInPages = (nCacheSize + 2 * nPageSize - 1) / nPageSize;
         if( nCacheMaxSizeInPages >
-                    (size_t)((MAXIMUM_COUNT_OF_MAPPINGS * 9 / 10) - nMappings) )
+            static_cast<size_t>((MAXIMUM_COUNT_OF_MAPPINGS * 9 / 10) -
+                                nMappings) )
             nPageSize <<= 1;
         else
             break;
     }
-    nRoundedMappingSize = ((nSize + 2 * nPageSize - 1) / nPageSize) * nPageSize;
-    pData = mmap(NULL, nRoundedMappingSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    size_t nRoundedMappingSize =
+        ((nSize + 2 * nPageSize - 1) / nPageSize) * nPageSize;
+    void* pData = mmap(NULL, nRoundedMappingSize, PROT_NONE,
+                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     if( pData == MAP_FAILED )
     {
         perror("mmap");
         return NULL;
     }
-    ctxt = (CPLVirtualMemVMA* )VSI_CALLOC_VERBOSE(1, sizeof(CPLVirtualMemVMA));
+    CPLVirtualMemVMA* ctxt = static_cast<CPLVirtualMemVMA *>(
+        VSI_CALLOC_VERBOSE(1, sizeof(CPLVirtualMemVMA)));
     if( ctxt == NULL )
         return NULL;
     ctxt->sBase.nRefCount = 1;
@@ -379,28 +408,31 @@ CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
     ctxt->sBase.pData = ALIGN_UP(pData, nPageSize);
     ctxt->sBase.nPageSize = nPageSize;
     ctxt->sBase.nSize = nSize;
-    ctxt->sBase.bSingleThreadUsage = bSingleThreadUsage;
+    ctxt->sBase.bSingleThreadUsage = CPL_TO_BOOL(bSingleThreadUsage);
     ctxt->sBase.pfnFreeUserData = pfnFreeUserData;
     ctxt->sBase.pCbkUserData = pCbkUserData;
 
-    ctxt->pabitMappedPages = (GByte*)VSI_CALLOC_VERBOSE(1, (nRoundedMappingSize / nPageSize + 7) / 8);
+    ctxt->pabitMappedPages = static_cast<GByte *>(
+        VSI_CALLOC_VERBOSE(1, (nRoundedMappingSize / nPageSize + 7) / 8));
     if( ctxt->pabitMappedPages == NULL )
     {
         CPLVirtualMemFreeFileMemoryMapped(ctxt);
         CPLFree(ctxt);
         return NULL;
     }
-    ctxt->pabitRWMappedPages = (GByte*)VSI_CALLOC_VERBOSE(1, (nRoundedMappingSize / nPageSize + 7) / 8);
+    ctxt->pabitRWMappedPages = static_cast<GByte*>(
+        VSI_CALLOC_VERBOSE(1, (nRoundedMappingSize / nPageSize + 7) / 8));
     if( ctxt->pabitRWMappedPages == NULL )
     {
         CPLVirtualMemFreeFileMemoryMapped(ctxt);
         CPLFree(ctxt);
         return NULL;
     }
-    /* we need at least 2 pages in case for a rep movs instruction */
-    /* that operate in the view */
+    // Need at least 2 pages in case for a rep movs instruction
+    // that operate in the view.
     ctxt->nCacheMaxSizeInPages = static_cast<int>(nCacheMaxSizeInPages);
-    ctxt->panLRUPageIndices = static_cast<int*>(VSI_MALLOC_VERBOSE(ctxt->nCacheMaxSizeInPages * sizeof(int)));
+    ctxt->panLRUPageIndices = static_cast<int*>(
+        VSI_MALLOC_VERBOSE(ctxt->nCacheMaxSizeInPages * sizeof(int)));
     if( ctxt->panLRUPageIndices == NULL )
     {
         CPLVirtualMemFreeFileMemoryMapped(ctxt);
@@ -436,20 +468,23 @@ CPLVirtualMem* CPLVirtualMemNew(size_t nSize,
 }
 
 /************************************************************************/
-/*                       CPLVirtualMemFreeVMA()                         */
+/*                  CPLVirtualMemFreeFileMemoryMapped()                 */
 /************************************************************************/
 
 static void CPLVirtualMemFreeFileMemoryMapped(CPLVirtualMemVMA* ctxt)
 {
     CPLVirtualMemManagerUnregisterVirtualMem(ctxt);
 
-    size_t nRoundedMappingSize = ((ctxt->sBase.nSize + 2 * ctxt->sBase.nPageSize - 1) /
-                                            ctxt->sBase.nPageSize) * ctxt->sBase.nPageSize;
+    size_t nRoundedMappingSize =
+        ((ctxt->sBase.nSize + 2 * ctxt->sBase.nPageSize - 1) /
+         ctxt->sBase.nPageSize) * ctxt->sBase.nPageSize;
     if( ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE &&
         ctxt->pabitRWMappedPages != NULL &&
         ctxt->pfnUnCachePage != NULL )
     {
-        for( size_t i = 0; i < nRoundedMappingSize / ctxt->sBase.nPageSize; i++ )
+        for( size_t i = 0;
+             i < nRoundedMappingSize / ctxt->sBase.nPageSize;
+             i++ )
         {
             if( TEST_BIT(ctxt->pabitRWMappedPages, i) )
             {
@@ -492,10 +527,12 @@ static void CPLVirtualMemSIGUSR1Handler( int /* signum_unused */,
 #if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
     fprintfstderr("entering CPLVirtualMemSIGUSR1Handler %X\n", pthread_self());
 #endif
-    /* I guess this is only POSIX correct if it is implemented by an intrinsic */
+    // Rouault guesses this is only POSIX correct if it is implemented by an
+    // intrinsic.
     CPLAtomicInc(&nCountThreadsInSigUSR1);
     while( nWaitHelperThread )
-        usleep(1); /* not explicitly indicated as signal-async-safe, but hopefully ok */
+        // Not explicitly indicated as signal-async-safe, but hopefully ok.
+        usleep(1);
     CPLAtomicDec(&nCountThreadsInSigUSR1);
 #if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
     fprintfstderr("leaving CPLVirtualMemSIGUSR1Handler %X\n", pthread_self());
@@ -507,7 +544,7 @@ static void CPLVirtualMemSIGUSR1Handler( int /* signum_unused */,
 /*                      CPLVirtualMemDeclareThread()                    */
 /************************************************************************/
 
-void CPLVirtualMemDeclareThread(CPLVirtualMem* ctxt)
+void CPLVirtualMemDeclareThread( CPLVirtualMem* ctxt )
 {
     if( ctxt->eType == VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED )
         return;
@@ -515,10 +552,11 @@ void CPLVirtualMemDeclareThread(CPLVirtualMem* ctxt)
     CPLVirtualMemVMA* ctxtVMA = (CPLVirtualMemVMA* )ctxt;
     IGNORE_OR_ASSERT_IN_DEBUG( !ctxt->bSingleThreadUsage );
     CPLAcquireMutex(ctxtVMA->hMutexThreadArray, 1000.0);
-    ctxtVMA->pahThreads = (pthread_t*) CPLRealloc(ctxtVMA->pahThreads,
-                                (ctxtVMA->nThreads + 1) * sizeof(pthread_t));
+    ctxtVMA->pahThreads = static_cast<pthread_t *>(
+        CPLRealloc(ctxtVMA->pahThreads,
+                   (ctxtVMA->nThreads + 1) * sizeof(pthread_t)));
     ctxtVMA->pahThreads[ctxtVMA->nThreads] = pthread_self();
-    ctxtVMA->nThreads ++;
+    ctxtVMA->nThreads++;
 
     CPLReleaseMutex(ctxtVMA->hMutexThreadArray);
 #endif
@@ -528,7 +566,7 @@ void CPLVirtualMemDeclareThread(CPLVirtualMem* ctxt)
 /*                     CPLVirtualMemUnDeclareThread()                   */
 /************************************************************************/
 
-void CPLVirtualMemUnDeclareThread(CPLVirtualMem* ctxt)
+void CPLVirtualMemUnDeclareThread( CPLVirtualMem* ctxt )
 {
     if( ctxt->eType == VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED )
         return;
@@ -545,7 +583,7 @@ void CPLVirtualMemUnDeclareThread(CPLVirtualMem* ctxt)
                 memmove(ctxtVMA->pahThreads + i + 1,
                         ctxtVMA->pahThreads + i,
                         (ctxtVMA->nThreads - 1 - i) * sizeof(pthread_t));
-            ctxtVMA->nThreads --;
+            ctxtVMA->nThreads--;
             break;
         }
     }
@@ -554,16 +592,16 @@ void CPLVirtualMemUnDeclareThread(CPLVirtualMem* ctxt)
 #endif
 }
 
-
 /************************************************************************/
 /*                     CPLVirtualMemGetPageToFill()                     */
 /************************************************************************/
 
-/* Must be paired with CPLVirtualMemAddPage */
+// Must be paired with CPLVirtualMemAddPage.
 static
-void* CPLVirtualMemGetPageToFill(CPLVirtualMemVMA* ctxt, void* start_page_addr)
+void* CPLVirtualMemGetPageToFill( CPLVirtualMemVMA* ctxt,
+                                  void* start_page_addr )
 {
-    void* pPageToFill;
+    void* pPageToFill = NULL;
 
     if( ctxt->sBase.bSingleThreadUsage )
     {
@@ -588,8 +626,8 @@ void* CPLVirtualMemGetPageToFill(CPLVirtualMemVMA* ctxt, void* start_page_addr)
         else
 #endif
         {
-            /* Allocate a temporary writable page that the user */
-            /* callback can fill */
+            // Allocate a temporary writable page that the user
+            // callback can fill.
             pPageToFill = mmap(NULL, ctxt->sBase.nPageSize,
                                 PROT_READ | PROT_WRITE,
                                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -604,10 +642,12 @@ void* CPLVirtualMemGetPageToFill(CPLVirtualMemVMA* ctxt, void* start_page_addr)
 /************************************************************************/
 
 static
-void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPageToFill,
-                       OpType opType, pthread_t hRequesterThread)
+void CPLVirtualMemAddPage( CPLVirtualMemVMA* ctxt, void* target_addr,
+                           void* pPageToFill,
+                           OpType opType, pthread_t hRequesterThread )
 {
-    int iPage = static_cast<int>(((char*)target_addr - (char*)ctxt->sBase.pData) / ctxt->sBase.nPageSize);
+    const int iPage = static_cast<int>(
+       ((char*)target_addr - (char*)ctxt->sBase.pData) / ctxt->sBase.nPageSize);
     if( ctxt->nLRUSize == ctxt->nCacheMaxSizeInPages )
     {
 #if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
@@ -620,8 +660,10 @@ void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPage
             TEST_BIT(ctxt->pabitRWMappedPages, nOldPage) )
         {
             size_t nToBeEvicted = ctxt->sBase.nPageSize;
-            if( (char*)addr + nToBeEvicted >= (char*) ctxt->sBase.pData + ctxt->sBase.nSize )
-                nToBeEvicted = (char*) ctxt->sBase.pData + ctxt->sBase.nSize - (char*)addr;
+            if( (char*)addr + nToBeEvicted >=
+                (char*)ctxt->sBase.pData + ctxt->sBase.nSize )
+                nToBeEvicted =
+                    (char*)ctxt->sBase.pData + ctxt->sBase.nSize - (char*)addr;
 
             ctxt->pfnUnCachePage((CPLVirtualMem*)ctxt,
                                  nOldPage * ctxt->sBase.nPageSize,
@@ -629,11 +671,11 @@ void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPage
                                  nToBeEvicted,
                                  ctxt->sBase.pCbkUserData);
         }
-        /* "Free" the least recently used page */
+        // "Free" the least recently used page.
         UNSET_BIT(ctxt->pabitMappedPages, nOldPage);
         UNSET_BIT(ctxt->pabitRWMappedPages, nOldPage);
-        /* Free the old page */
-        /* Not sure how portable it is to do that that way... */
+        // Free the old page.
+        // Not sure how portable it is to do that that way.
         const void * const pRet = mmap(addr, ctxt->sBase.nPageSize, PROT_NONE,
                     MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
         IGNORE_OR_ASSERT_IN_DEBUG(pRet == addr);
@@ -642,16 +684,17 @@ void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPage
     ctxt->iLRUStart = (ctxt->iLRUStart + 1) % ctxt->nCacheMaxSizeInPages;
     if( ctxt->nLRUSize < ctxt->nCacheMaxSizeInPages )
     {
-        ctxt->nLRUSize ++;
+        ctxt->nLRUSize++;
     }
     SET_BIT(ctxt->pabitMappedPages, iPage);
 
     if( ctxt->sBase.bSingleThreadUsage )
     {
-        if( opType == OP_STORE && ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
+        if( opType == OP_STORE &&
+            ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
         {
-            /* let (and mark) the page writable since the instruction that triggered */
-            /* the fault is a store */
+            // Let (and mark) the page writable since the instruction that
+            // triggered the fault is a store.
             SET_BIT(ctxt->pabitRWMappedPages, iPage);
         }
         else if( ctxt->sBase.eAccessMode != VIRTUALMEM_READONLY )
@@ -666,17 +709,20 @@ void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPage
 #ifdef HAVE_5ARGS_MREMAP
         (void)hRequesterThread;
 
-        if( opType == OP_STORE && ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
+        if( opType == OP_STORE &&
+            ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
         {
-            /* let (and mark) the page writable since the instruction that triggered */
-            /* the fault is a store */
+            // Let (and mark) the page writable since the instruction that
+            // triggered the fault is a store.
             SET_BIT(ctxt->pabitRWMappedPages, iPage);
         }
         else if( ctxt->sBase.eAccessMode != VIRTUALMEM_READONLY )
         {
-            /* Turn the temporary page read-only before remapping it. We will only turn it */
-            /* writtable when a new fault occurs (and that the mapping is writable) */
-            int nRet = mprotect(pPageToFill, ctxt->sBase.nPageSize, PROT_READ);
+            // Turn the temporary page read-only before remapping it.
+            // Only turn it writtable when a new fault occurs (and the
+            // mapping is writable).
+            const int nRet =
+                mprotect(pPageToFill, ctxt->sBase.nPageSize, PROT_READ);
             IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
         }
         /* Can now remap the pPageToFill onto the target page */
@@ -686,7 +732,7 @@ void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPage
         IGNORE_OR_ASSERT_IN_DEBUG(pRet == target_addr);
 
 #else
-        if (ctxt->nThreads > 1 )
+        if( ctxt->nThreads > 1 )
         {
             /* Pause threads that share this mem view */
             CPLAtomicInc(&nWaitHelperThread);
@@ -706,7 +752,7 @@ void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPage
                 if( ctxt->pahThreads[i] != hRequesterThread )
                 {
 #if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
-                    fprintfstderr("stopping thread %X\n", ctxt->pahThreads[i]); */
+                    fprintfstderr("stopping thread %X\n", ctxt->pahThreads[i]);
 #endif
                     IGNORE_OR_ASSERT_IN_DEBUG(
                         pthread_kill( ctxt->pahThreads[i], SIGUSR1 ) == 0);
@@ -728,10 +774,11 @@ void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPage
 #endif
             memcpy(target_addr, pPageToFill, ctxt->sBase.nPageSize);
 
-            if( opType == OP_STORE && ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
+            if( opType == OP_STORE &&
+                ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
             {
-                /* let (and mark) the page writable since the instruction that triggered */
-                /* the fault is a store */
+                // Let (and mark) the page writable since the instruction that
+                // triggered the fault is a store.
                 SET_BIT(ctxt->pabitRWMappedPages, iPage);
             }
             else
@@ -750,10 +797,11 @@ void CPLVirtualMemAddPage(CPLVirtualMemVMA* ctxt, void* target_addr, void* pPage
         }
         else
         {
-            if( opType == OP_STORE && ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
+            if( opType == OP_STORE &&
+                ctxt->sBase.eAccessMode == VIRTUALMEM_READWRITE )
             {
-                /* let (and mark) the page writable since the instruction that triggered */
-                /* the fault is a store */
+                // Let (and mark) the page writable since the instruction that
+                // triggered the fault is a store.
                 SET_BIT(ctxt->pabitRWMappedPages, iPage);
             }
             else if( ctxt->sBase.eAccessMode != VIRTUALMEM_READONLY )
@@ -778,22 +826,22 @@ static OpType CPLVirtualMemGetOpTypeImm(GByte val_rip)
 {
     OpType opType = OP_UNKNOWN;
     if( (/*val_rip >= 0x00 &&*/ val_rip <= 0x07) ||
-        (val_rip >= 0x40 && val_rip <= 0x47) ) /* add $,(X) */
+        (val_rip >= 0x40 && val_rip <= 0x47) )  // add $, (X)
         opType = OP_STORE;
     if( (val_rip >= 0x08 && val_rip <= 0x0f) ||
-        (val_rip >= 0x48 && val_rip <= 0x4f) ) /* or $,(X) */
+        (val_rip >= 0x48 && val_rip <= 0x4f) )  // or $, (X)
         opType = OP_STORE;
     if( (val_rip >= 0x20 && val_rip <= 0x27) ||
-        (val_rip >= 0x60 && val_rip <= 0x67) ) /* and $,(X) */
+        (val_rip >= 0x60 && val_rip <= 0x67) )  // and $, (X)
         opType = OP_STORE;
     if( (val_rip >= 0x28 && val_rip <= 0x2f) ||
-        (val_rip >= 0x68 && val_rip <= 0x6f) ) /* sub $,(X) */
+        (val_rip >= 0x68 && val_rip <= 0x6f) )  // sub $, (X)
         opType = OP_STORE;
     if( (val_rip >= 0x30 && val_rip <= 0x37) ||
-        (val_rip >= 0x70 && val_rip <= 0x77) ) /* xor $,(X) */
+        (val_rip >= 0x70 && val_rip <= 0x77) )  // xor $, (X)
         opType = OP_STORE;
     if( (val_rip >= 0x38 && val_rip <= 0x3f) ||
-        (val_rip >= 0x78 && val_rip <= 0x7f) ) /* cmp $,(X) */
+        (val_rip >= 0x78 && val_rip <= 0x7f) )  // cmp $, (X)
         opType = OP_LOAD;
     return opType;
 }
@@ -803,17 +851,17 @@ static OpType CPLVirtualMemGetOpTypeImm(GByte val_rip)
 /*                      CPLVirtualMemGetOpType()                        */
 /************************************************************************/
 
-/* We don't need exhaustivity. It is just a hint for an optimization : */
-/* if the fault occurs on a store operation, then we can directly put */
-/* the page in writable mode if the mapping allows it */
+// Don't need exhaustivity. It is just a hint for an optimization:
+// If the fault occurs on a store operation, then we can directly put
+// the page in writable mode if the mapping allows it.
 
 #if defined(__x86_64__) || defined(__i386__)
-static OpType CPLVirtualMemGetOpType(const GByte* rip)
+static OpType CPLVirtualMemGetOpType( const GByte* rip )
 {
     OpType opType = OP_UNKNOWN;
 
 #if defined(__x86_64__) || defined(__i386__)
-    switch(rip[0])
+    switch( rip[0] )
     {
         case 0x00: /* add %al,(%rax) */
         case 0x01: /* add %eax,(%rax) */
@@ -835,7 +883,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
 
         case 0x0f:
         {
-            switch(rip[1])
+            switch( rip[1] )
             {
                 case 0xb6: /* movzbl (%rax),%eax */
                 case 0xb7: /* movzwl (%rax),%eax */
@@ -886,7 +934,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
             break;
         case 0x40:
         {
-            switch(rip[1])
+            switch( rip[1] )
             {
                 case 0x00: /* add %spl,(%rax) */
                     opType = OP_STORE;
@@ -920,7 +968,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
         case 0x46: /* reg=%r8b/%r8w, X = %rax,%r8,1 */
         case 0x47: /* reg=%r8b/%r8w, X = %r8,%r8,1 */
         {
-            switch(rip[1])
+            switch( rip[1] )
             {
                 case 0x00: /* add regb,(X) */
                 case 0x01: /* add regl,(X) */
@@ -932,7 +980,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
                     break;
                 case 0x0f:
                 {
-                    switch(rip[2])
+                    switch( rip[2] )
                     {
                         case 0xb6: /* movzbl (X),regl */
                         case 0xb7: /* movzwl (X),regl */
@@ -953,8 +1001,8 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
                 case 0x2b: /* sub (X),regl */
                     opType = OP_LOAD;
                     break;
-                case 0x38: /* cmp  regb,(X) */
-                case 0x39: /* cmp  regl,(X) */
+                case 0x38: /* cmp regb,(X) */
+                case 0x39: /* cmp regl,(X) */
                     opType = OP_LOAD;
                     break;
                 case 0x80: /* cmpb,... $,(X) */
@@ -1000,7 +1048,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
         case 0x4e: /* reg=%r8, X=%rax,%r8,1 */
         case 0x4f: /* reg=%r8, X=%r8,%r8,1 */
         {
-            switch(rip[1])
+            switch( rip[1] )
             {
                 case 0x01: /* add reg,(X) */
                     opType = OP_STORE;
@@ -1017,7 +1065,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
                     break;
                 case 0x0f:
                 {
-                    switch(rip[2])
+                    switch( rip[2] )
                     {
                         case 0xc3: /* movnti reg,(X) */
                             opType = OP_STORE;
@@ -1088,7 +1136,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
 #endif
         case 0x66:
         {
-            switch(rip[1])
+            switch( rip[1] )
             {
                 case 0x01: /* add %ax,(%rax) */
                     opType = OP_STORE;
@@ -1098,7 +1146,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
                     break;
                 case 0x0f:
                 {
-                    switch(rip[2])
+                    switch( rip[2] )
                     {
                         case 0x2e: /* ucomisd (%rax),%xmm0 */
                             opType = OP_LOAD;
@@ -1138,7 +1186,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
                 case 0x46: /* reg = %r8w (or %xmm8), X = %rax,%r8,1 */
                 case 0x47: /* reg = %r8w (or %xmm8), X = %r8,%r8,1 */
                 {
-                    switch(rip[2])
+                    switch( rip[2] )
                     {
                         case 0x01: /* add reg,(X) */
                             opType = OP_STORE;
@@ -1148,7 +1196,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
                             break;
                         case 0x0f:
                         {
-                            switch(rip[3])
+                            switch( rip[3] )
                             {
                                 case 0x2e: /* ucomisd (X),reg */
                                     opType = OP_LOAD;
@@ -1282,11 +1330,11 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
         }
         case 0xf2: /* SSE 2 */
         {
-            switch(rip[1])
+            switch( rip[1] )
             {
                 case 0x0f:
                 {
-                    switch(rip[2])
+                    switch( rip[2] )
                     {
                         case 0x10: /* movsd (%rax),%xmm0 */
                             opType = OP_LOAD;
@@ -1320,11 +1368,11 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
                 case 0x46: /* reg=%xmm8, X=%rax,%r8,1 */
                 case 0x47: /* reg=%xmm8, X=%r8,%r8,1 */
                 {
-                    switch(rip[2])
+                    switch( rip[2] )
                     {
                         case 0x0f:
                         {
-                            switch(rip[3])
+                            switch( rip[3] )
                             {
                                 case 0x10: /* movsd (X),reg */
                                     opType = OP_LOAD;
@@ -1362,11 +1410,11 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
         }
         case 0xf3:
         {
-            switch(rip[1])
+            switch( rip[1] )
             {
                 case 0x0f: /* SSE 2 */
                 {
-                    switch(rip[2])
+                    switch( rip[2] )
                     {
                         case 0x10: /* movss (%rax),%xmm0 */
                             opType = OP_LOAD;
@@ -1394,11 +1442,11 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
                 case 0x46: /* reg=%xmm8, X = %rax,%r8,1 */
                 case 0x47: /* reg=%xmm8, X = %r8,%r8,1 */
                 {
-                    switch(rip[2])
+                    switch( rip[2] )
                     {
                         case 0x0f: /* SSE 2 */
                         {
-                            switch(rip[3])
+                            switch( rip[3] )
                             {
                                 case 0x10: /* movss (X),reg */
                                     opType = OP_LOAD;
@@ -1424,7 +1472,7 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
                 }
                 case 0x48:
                 {
-                    switch(rip[2])
+                    switch( rip[2] )
                     {
                         case 0xa5: /* rep movsq %ds:(%rsi),%es:(%rdi) */
                             opType = OP_MOVS_RSI_RDI;
@@ -1468,13 +1516,14 @@ static OpType CPLVirtualMemGetOpType(const GByte* rip)
 /*                    CPLVirtualMemManagerPinAddrInternal()             */
 /************************************************************************/
 
-static int CPLVirtualMemManagerPinAddrInternal(CPLVirtualMemMsgToWorkerThread* msg)
+static int
+CPLVirtualMemManagerPinAddrInternal( CPLVirtualMemMsgToWorkerThread* msg )
 {
-    char wait_ready;
-    char response_buf[4];
+    char wait_ready = '\0';
+    char response_buf[4] = {};
 
-    /* Wait for the helper thread to be ready to process another request */
-    while(true)
+    // Wait for the helper thread to be ready to process another request.
+    while( true )
     {
         const int ret =
             static_cast<int>(read( pVirtualMemManager->pipefd_wait_thread[0],
@@ -1490,13 +1539,13 @@ static int CPLVirtualMemManagerPinAddrInternal(CPLVirtualMemMsgToWorkerThread* m
         }
     }
 
-    /* Pass the address that caused the fault to the helper thread */
+    // Pass the address that caused the fault to the helper thread.
     const ssize_t nRetWrite =
         write(pVirtualMemManager->pipefd_to_thread[1], msg, sizeof(*msg));
     IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == sizeof(*msg));
 
-    /* Wait that the helper thread has fixed the fault */
-    while(true)
+    // Wait that the helper thread has fixed the fault.
+    while( true )
     {
         const int ret =
             static_cast<int>(read(pVirtualMemManager->pipefd_from_thread[0],
@@ -1512,9 +1561,9 @@ static int CPLVirtualMemManagerPinAddrInternal(CPLVirtualMemMsgToWorkerThread* m
         }
     }
 
-    /* In case the helper thread did not recognize the address as being */
-    /* one that it should take care of, just rely on the previous SIGSEGV */
-    /* handler (with might abort the process) */
+    // In case the helper thread did not recognize the address as being
+    // one that it should take care of, just rely on the previous SIGSEGV
+    // handler (with might abort the process).
     return( memcmp(response_buf, MAPPING_FOUND, 4) == 0 );
 }
 
@@ -1522,22 +1571,22 @@ static int CPLVirtualMemManagerPinAddrInternal(CPLVirtualMemMsgToWorkerThread* m
 /*                      CPLVirtualMemPin()                              */
 /************************************************************************/
 
-void CPLVirtualMemPin(CPLVirtualMem* ctxt,
-                      void* pAddr, size_t nSize, int bWriteOp)
+void CPLVirtualMemPin( CPLVirtualMem* ctxt,
+                       void* pAddr, size_t nSize, int bWriteOp )
 {
     if( ctxt->eType == VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED )
         return;
 
     CPLVirtualMemMsgToWorkerThread msg;
-    size_t i = 0, n;
 
     memset(&msg, 0, sizeof(msg));
     msg.hRequesterThread = pthread_self();
     msg.opType = (bWriteOp) ? OP_STORE : OP_LOAD;
 
     char* pBase = (char*)ALIGN_DOWN(pAddr, ctxt->nPageSize);
-    n = ((char*)pAddr - pBase + nSize + ctxt->nPageSize - 1) / ctxt->nPageSize;
-    for(i=0; i<n; i++)
+    const size_t n =
+        ((char*)pAddr - pBase + nSize + ctxt->nPageSize - 1) / ctxt->nPageSize;
+    for( size_t i = 0; i < n; i++ )
     {
         msg.pFaultAddr = (char*) pBase + i * ctxt->nPageSize;
         CPLVirtualMemManagerPinAddrInternal(&msg);
@@ -1558,12 +1607,12 @@ void CPLVirtualMemPin(CPLVirtualMem* ctxt,
 #define REG_DI      REG_EDI
 #endif
 
-/* We must take care of only using "asynchronous-signal-safe" functions in a signal handler */
-/* pthread_self(), read() and write() are such. See */
-/* https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers */
-static void CPLVirtualMemManagerSIGSEGVHandler(int the_signal,
-                                             siginfo_t* the_info,
-                                             void* the_ctxt)
+// Must take care of only using "asynchronous-signal-safe" functions in a signal
+// handler pthread_self(), read() and write() are such.  See:
+// https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers
+static void CPLVirtualMemManagerSIGSEGVHandler( int the_signal,
+                                                siginfo_t* the_info,
+                                                void* the_ctxt )
 {
     CPLVirtualMemMsgToWorkerThread msg;
 
@@ -1573,7 +1622,7 @@ static void CPLVirtualMemManagerSIGSEGVHandler(int the_signal,
     msg.opType = OP_UNKNOWN;
 
 #if defined(__x86_64__) || defined(__i386__)
-    ucontext_t* the_ucontext = (ucontext_t* )the_ctxt;
+    ucontext_t* the_ucontext = static_cast<ucontext_t *>(the_ctxt);
     const GByte* rip = (const GByte*)the_ucontext->uc_mcontext.gregs[REG_IP];
     msg.opType = CPLVirtualMemGetOpType(rip);
 #if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
@@ -1618,7 +1667,8 @@ static void CPLVirtualMemManagerSIGSEGVHandler(int the_signal,
 #endif
 
 #if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
-    fprintfstderr("entering handler for %X (addr=%p)\n", pthread_self(), the_info->si_addr);
+    fprintfstderr("entering handler for %X (addr=%p)\n",
+                  pthread_self(), the_info->si_addr);
 #endif
 
     if( the_info->si_code != SEGV_ACCERR )
@@ -1629,14 +1679,15 @@ static void CPLVirtualMemManagerSIGSEGVHandler(int the_signal,
 
     if( !CPLVirtualMemManagerPinAddrInternal(&msg) )
     {
-        /* In case the helper thread did not recognize the address as being */
-        /* one that it should take care of, just rely on the previous SIGSEGV */
-        /* handler (with might abort the process) */
+        // In case the helper thread did not recognize the address as being
+        // one that it should take care of, just rely on the previous SIGSEGV
+        // handler (with might abort the process).
         pVirtualMemManager->oldact.sa_sigaction(the_signal, the_info, the_ctxt);
     }
 
 #if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
-    fprintfstderr("leaving handler for %X (addr=%p)\n", pthread_self(), the_info->si_addr);
+    fprintfstderr("leaving handler for %X (addr=%p)\n",
+                  pthread_self(), the_info->si_addr);
 #endif
 }
 
@@ -1644,30 +1695,28 @@ static void CPLVirtualMemManagerSIGSEGVHandler(int the_signal,
 /*                      CPLVirtualMemManagerThread()                    */
 /************************************************************************/
 
-static void CPLVirtualMemManagerThread(void* unused_param)
+static void CPLVirtualMemManagerThread( void* /* unused_param */ )
 {
-    (void)unused_param;
-
-    while(true)
+    while( true )
     {
         char i_m_ready = 1;
         CPLVirtualMemVMA* ctxt = NULL;
         bool bMappingFound = false;
         CPLVirtualMemMsgToWorkerThread msg;
 
-        /* Signal that we are ready to process a new request */
+        // Signal that we are ready to process a new request.
         ssize_t nRetWrite =
             write(pVirtualMemManager->pipefd_wait_thread[1], &i_m_ready, 1);
         IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == 1);
 
-        /* Fetch the address to process */
+        // Fetch the address to process.
         const ssize_t nRetRead =
             read(pVirtualMemManager->pipefd_to_thread[0], &msg,
                  sizeof(msg));
         IGNORE_OR_ASSERT_IN_DEBUG(nRetRead == sizeof(msg));
 
-        /* If CPLVirtualMemManagerTerminate() is called, it will use BYEBYE_ADDR as a */
-        /* means to ask for our termination */
+        // If CPLVirtualMemManagerTerminate() is called, it will use BYEBYE_ADDR
+        // as a means to ask for our termination.
         if( msg.pFaultAddr == BYEBYE_ADDR )
             break;
 
@@ -1677,7 +1726,8 @@ static void CPLVirtualMemManagerThread(void* unused_param)
         {
             ctxt = pVirtualMemManager->pasVirtualMem[i];
             if( (char*)msg.pFaultAddr >= (char*) ctxt->sBase.pData &&
-                (char*)msg.pFaultAddr < (char*) ctxt->sBase.pData + ctxt->sBase.nSize )
+                (char*)msg.pFaultAddr <
+                (char*)ctxt->sBase.pData + ctxt->sBase.nSize )
             {
                 bMappingFound = true;
                 break;
@@ -1696,16 +1746,15 @@ static void CPLVirtualMemManagerThread(void* unused_param)
 
             if( iPage == ctxt->iLastPage )
             {
-                /* In case 2 threads try to access the same page */
-                /* concurrently it is possible that we are asked to mapped */
-                /* the page again whereas it is always mapped. However */
-                /* if that number of successive retries is too high, this */
-                /* is certainly a sign that something else happen, like */
-                /* trying to write-access a read-only page */
-                /* 100 is a bit of magic number. I believe it must be */
-                /* at least the number of concurrent threads. 100 seems */
-                /* to be really safe ! */
-                ctxt->nRetry ++;
+                // In case 2 threads try to access the same page concurrently it
+                // is possible that we are asked to mapped the page again
+                // whereas it is always mapped. However, if that number of
+                // successive retries is too high, this is certainly a sign that
+                // something else happen, like trying to write-access a
+                // read-only page 100 is a bit of magic number. Rouault believes
+                // it must be at least the number of concurrent threads. 100
+                // seems to be really safe!
+                ctxt->nRetry++;
 #if defined DEBUG_VIRTUALMEM && defined DEBUG_VERBOSE
                 fprintfstderr("retry on page %d : %d\n",
                               iPage, ctxt->nRetry);
@@ -1770,8 +1819,13 @@ static void CPLVirtualMemManagerThread(void* unused_param)
                         CPLVirtualMemGetPageToFill(ctxt, start_page_addr);
 
                     size_t nToFill = ctxt->sBase.nPageSize;
-                    if( start_page_addr + nToFill >= (char*) ctxt->sBase.pData + ctxt->sBase.nSize )
-                        nToFill = (char*) ctxt->sBase.pData + ctxt->sBase.nSize - start_page_addr;
+                    if( start_page_addr + nToFill >=
+                        (char*) ctxt->sBase.pData + ctxt->sBase.nSize )
+                    {
+                        nToFill =
+                            (char*) ctxt->sBase.pData +
+                            ctxt->sBase.nSize - start_page_addr;
+                    }
 
                     ctxt->pfnCachePage(
                             (CPLVirtualMem*)ctxt,
@@ -1780,14 +1834,14 @@ static void CPLVirtualMemManagerThread(void* unused_param)
                             nToFill,
                             ctxt->sBase.pCbkUserData);
 
-                    /* Now remap this page to its target address and */
-                    /* register it in the LRU */
+                    // Now remap this page to its target address and
+                    // register it in the LRU.
                     CPLVirtualMemAddPage(ctxt, start_page_addr, pPageToFill,
                                       msg.opType, msg.hRequesterThread);
                 }
             }
 
-            /* Warn the segfault handler that we have finished our job */
+            // Warn the segfault handler that we have finished our job.
             nRetWrite = write(pVirtualMemManager->pipefd_from_thread[1],
                             MAPPING_FOUND, 4);
             IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == 4);
@@ -1810,7 +1864,7 @@ static void CPLVirtualMemManagerThread(void* unused_param)
 /*                       CPLVirtualMemManagerInit()                     */
 /************************************************************************/
 
-static bool CPLVirtualMemManagerInit(void)
+static bool CPLVirtualMemManagerInit()
 {
     CPLMutexHolderD(&hVirtualMemManagerMutex);
     if( pVirtualMemManager != NULL )
@@ -1830,14 +1884,14 @@ static bool CPLVirtualMemManagerInit(void)
     nRet = pipe(pVirtualMemManager->pipefd_wait_thread);
     IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
 
-    /* Install our custom SIGSEGV handler */
+    // Install our custom SIGSEGV handler.
     act.sa_sigaction = CPLVirtualMemManagerSIGSEGVHandler;
     sigemptyset (&act.sa_mask);
     act.sa_flags = SA_SIGINFO;
     nRet = sigaction(SIGSEGV, &act, &pVirtualMemManager->oldact);
     IGNORE_OR_ASSERT_IN_DEBUG(nRet == 0);
 
-    /* Starts the helper thread */
+    // Starts the helper thread.
     pVirtualMemManager->hHelperThread =
             CPLCreateJoinableThread(CPLVirtualMemManagerThread, NULL);
     if( pVirtualMemManager->hHelperThread == NULL )
@@ -1863,23 +1917,25 @@ void CPLVirtualMemManagerTerminate(void)
     msg.opType = OP_UNKNOWN;
     memset(&msg.hRequesterThread, 0, sizeof(msg.hRequesterThread));
 
-    /* Wait for the helper thread to be ready */
+    // Wait for the helper thread to be ready.
     char wait_ready;
     const ssize_t nRetRead =
         read(pVirtualMemManager->pipefd_wait_thread[0], &wait_ready, 1);
     IGNORE_OR_ASSERT_IN_DEBUG(nRetRead == 1);
 
-    /* Ask it to terminate */
+    // Ask it to terminate.
     const ssize_t nRetWrite =
         write(pVirtualMemManager->pipefd_to_thread[1], &msg, sizeof(msg));
     IGNORE_OR_ASSERT_IN_DEBUG(nRetWrite == sizeof(msg));
 
-    /* Wait for its termination */
+    // Wait for its termination.
     CPLJoinThread(pVirtualMemManager->hHelperThread);
 
-    /* Cleanup everything */
-    while(pVirtualMemManager->nVirtualMemCount > 0)
-        CPLVirtualMemFree((CPLVirtualMem*)pVirtualMemManager->pasVirtualMem[pVirtualMemManager->nVirtualMemCount - 1]);
+    // Cleanup everything.
+    while( pVirtualMemManager->nVirtualMemCount > 0 )
+        CPLVirtualMemFree(
+            (CPLVirtualMem*)pVirtualMemManager->
+                pasVirtualMem[pVirtualMemManager->nVirtualMemCount - 1]);
     CPLFree(pVirtualMemManager->pasVirtualMem);
 
     close(pVirtualMemManager->pipefd_to_thread[0]);
@@ -1889,7 +1945,7 @@ void CPLVirtualMemManagerTerminate(void)
     close(pVirtualMemManager->pipefd_wait_thread[0]);
     close(pVirtualMemManager->pipefd_wait_thread[1]);
 
-    /* Restore previous handler */
+    // Restore previous handler.
     sigaction(SIGSEGV, &pVirtualMemManager->oldact, NULL);
 
     CPLFree(pVirtualMemManager);
@@ -1899,17 +1955,18 @@ void CPLVirtualMemManagerTerminate(void)
     hVirtualMemManagerMutex = NULL;
 }
 
-#else /* HAVE_VIRTUAL_MEM_VMA */
-
-CPLVirtualMem *CPLVirtualMemNew( size_t /* nSize */,
-                                 size_t /* nCacheSize */,
-                                 size_t /* nPageSizeHint */,
-                                 int /* bSingleThreadUsage */,
-                                 CPLVirtualMemAccessMode /* eAccessMode */,
-                                 CPLVirtualMemCachePageCbk /* pfnCachePage */,
-                                 CPLVirtualMemUnCachePageCbk /* pfnUnCachePage */,
-                                 CPLVirtualMemFreeUserData /* pfnFreeUserData */,
-                                 void * /* pCbkUserData  */)
+#else  // HAVE_VIRTUAL_MEM_VMA
+
+CPLVirtualMem *CPLVirtualMemNew(
+    size_t /* nSize */,
+    size_t /* nCacheSize */,
+    size_t /* nPageSizeHint */,
+    int /* bSingleThreadUsage */,
+    CPLVirtualMemAccessMode /* eAccessMode */,
+    CPLVirtualMemCachePageCbk /* pfnCachePage */,
+    CPLVirtualMemUnCachePageCbk /* pfnUnCachePage */,
+    CPLVirtualMemFreeUserData /* pfnFreeUserData */,
+    void * /* pCbkUserData */ )
 {
     CPLError(CE_Failure, CPLE_NotSupported,
              "CPLVirtualMemNew() unsupported on "
@@ -1927,10 +1984,9 @@ void CPLVirtualMemPin( CPLVirtualMem* /* ctxt */,
                        int /* bWriteOp */)
 {}
 
-void CPLVirtualMemManagerTerminate(void) {}
-
-#endif /* HAVE_VIRTUAL_MEM_VMA */
+void CPLVirtualMemManagerTerminate( void ) {}
 
+#endif  // HAVE_VIRTUAL_MEM_VMA
 
 #ifdef HAVE_MMAP
 
@@ -1938,7 +1994,7 @@ void CPLVirtualMemManagerTerminate(void) {}
 /*                     CPLVirtualMemFreeFileMemoryMapped()              */
 /************************************************************************/
 
-static void CPLVirtualMemFreeFileMemoryMapped(CPLVirtualMem* ctxt)
+static void CPLVirtualMemFreeFileMemoryMapped( CPLVirtualMem* ctxt )
 {
     const size_t nMappingSize =
         ctxt->nSize + (GByte*)ctxt->pData - (GByte*)ctxt->pDataToFree;
@@ -1950,19 +2006,21 @@ static void CPLVirtualMemFreeFileMemoryMapped(CPLVirtualMem* ctxt)
 /*                       CPLVirtualMemFileMapNew()                      */
 /************************************************************************/
 
-CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* fp,
-                                        vsi_l_offset nOffset,
-                                        vsi_l_offset nLength,
-                                        CPLVirtualMemAccessMode eAccessMode,
-                                        CPLVirtualMemFreeUserData pfnFreeUserData,
-                                        void *pCbkUserData )
+CPLVirtualMem *
+CPLVirtualMemFileMapNew( VSILFILE* fp,
+                         vsi_l_offset nOffset,
+                         vsi_l_offset nLength,
+                         CPLVirtualMemAccessMode eAccessMode,
+                         CPLVirtualMemFreeUserData pfnFreeUserData,
+                         void *pCbkUserData )
 {
 #if SIZEOF_VOIDP == 4
-    if( nLength != (size_t)nLength )
+    if( nLength != static_cast<size_t>(nLength) )
     {
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "nLength = " CPL_FRMT_GUIB " incompatible with 32 bit architecture",
-                 nLength);
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "nLength = " CPL_FRMT_GUIB " incompatible with 32 bit architecture",
+            nLength);
         return NULL;
     }
     if( nOffset + CPLGetPageSize() !=
@@ -1977,7 +2035,7 @@ CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* fp,
     }
 #endif
 
-    int fd = (int) (size_t) VSIFGetNativeFileDescriptorL(fp);
+    int fd = static_cast<int>((GUIntptr_t) VSIFGetNativeFileDescriptorL(fp));
     if( fd == 0 )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -1990,8 +2048,8 @@ CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* fp,
     size_t nAligment = static_cast<size_t>(nOffset - nAlignedOffset);
     size_t nMappingSize = static_cast<size_t>(nLength + nAligment);
 
-    /* We need to ensure that the requested extent fits into the file size */
-    /* otherwise SIGBUS errors will occur when using the mapping */
+    // Need to ensure that the requested extent fits into the file size
+    // otherwise SIGBUS errors will occur when using the mapping.
     vsi_l_offset nCurPos = VSIFTellL(fp);
     if( VSIFSeekL(fp, 0, SEEK_END) != 0 )
         return NULL;
@@ -2027,7 +2085,8 @@ CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* fp,
         return NULL;
 
     void* addr = mmap(NULL, nMappingSize,
-                      (eAccessMode == VIRTUALMEM_READWRITE) ? PROT_READ | PROT_WRITE : PROT_READ,
+                      eAccessMode == VIRTUALMEM_READWRITE
+                      ? PROT_READ | PROT_WRITE : PROT_READ,
                       MAP_SHARED, fd, nAlignedOffset);
     if( addr == MAP_FAILED )
     {
@@ -2035,32 +2094,34 @@ CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* fp,
         CPLError(CE_Failure, CPLE_AppDefined,
                  "mmap() failed : %s", strerror(myerrno));
         VSIFree(ctxt);
+        // cppcheck thinks we are leaking addr.
+        // cppcheck-suppress memleak
         return NULL;
     }
 
     ctxt->eType = VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED;
     ctxt->nRefCount = 1;
     ctxt->eAccessMode = eAccessMode;
-    ctxt->pData = (GByte*) addr + nAligment;
+    ctxt->pData = static_cast<GByte *>(addr) + nAligment;
     ctxt->pDataToFree = addr;
     ctxt->nSize = static_cast<size_t>(nLength);
     ctxt->nPageSize = CPLGetPageSize();
-    ctxt->bSingleThreadUsage = FALSE;
+    ctxt->bSingleThreadUsage = false;
     ctxt->pfnFreeUserData = pfnFreeUserData;
     ctxt->pCbkUserData = pCbkUserData;
 
     return ctxt;
 }
 
-#else /* HAVE_MMAP */
+#else  // HAVE_MMAP
 
-
-CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* /* fp */,
-                                        vsi_l_offset /* nOffset */,
-                                        vsi_l_offset /* nLength */,
-                                        CPLVirtualMemAccessMode /* eAccessMode */,
-                                        CPLVirtualMemFreeUserData /* pfnFreeUserData */,
-                                        void * /* pCbkUserData */)
+CPLVirtualMem *CPLVirtualMemFileMapNew(
+    VSILFILE* /* fp */,
+    vsi_l_offset /* nOffset */,
+    vsi_l_offset /* nLength */,
+    CPLVirtualMemAccessMode /* eAccessMode */,
+    CPLVirtualMemFreeUserData /* pfnFreeUserData */,
+    void * /* pCbkUserData */ )
 {
     CPLError(CE_Failure, CPLE_NotSupported,
              "CPLVirtualMemFileMapNew() unsupported on this "
@@ -2068,14 +2129,13 @@ CPLVirtualMem *CPLVirtualMemFileMapNew( VSILFILE* /* fp */,
     return NULL;
 }
 
-
-#endif /* HAVE_MMAP */
+#endif  // HAVE_MMAP
 
 /************************************************************************/
 /*                         CPLGetPageSize()                             */
 /************************************************************************/
 
-size_t CPLGetPageSize(void)
+size_t CPLGetPageSize( void )
 {
 #if defined(HAVE_MMAP) || defined(HAVE_VIRTUAL_MEM_VMA)
     return static_cast<size_t>( sysconf(_SC_PAGESIZE) );
@@ -2088,7 +2148,7 @@ size_t CPLGetPageSize(void)
 /*                   CPLIsVirtualMemFileMapAvailable()                  */
 /************************************************************************/
 
-int CPLIsVirtualMemFileMapAvailable(void)
+int CPLIsVirtualMemFileMapAvailable( void )
 {
 #ifdef HAVE_MMAP
     return TRUE;
@@ -2101,7 +2161,7 @@ int CPLIsVirtualMemFileMapAvailable(void)
 /*                        CPLVirtualMemFree()                           */
 /************************************************************************/
 
-void CPLVirtualMemFree(CPLVirtualMem* ctxt)
+void CPLVirtualMemFree( CPLVirtualMem* ctxt )
 {
     if( ctxt == NULL || --(ctxt->nRefCount) > 0 )
         return;
@@ -2134,7 +2194,7 @@ void CPLVirtualMemFree(CPLVirtualMem* ctxt)
 /*                      CPLVirtualMemGetAddr()                          */
 /************************************************************************/
 
-void* CPLVirtualMemGetAddr(CPLVirtualMem* ctxt)
+void* CPLVirtualMemGetAddr( CPLVirtualMem* ctxt )
 {
     return ctxt->pData;
 }
@@ -2143,7 +2203,7 @@ void* CPLVirtualMemGetAddr(CPLVirtualMem* ctxt)
 /*                     CPLVirtualMemIsFileMapping()                     */
 /************************************************************************/
 
-int CPLVirtualMemIsFileMapping(CPLVirtualMem* ctxt)
+int CPLVirtualMemIsFileMapping( CPLVirtualMem* ctxt )
 {
     return ctxt->eType == VIRTUAL_MEM_TYPE_FILE_MEMORY_MAPPED;
 }
@@ -2152,7 +2212,7 @@ int CPLVirtualMemIsFileMapping(CPLVirtualMem* ctxt)
 /*                     CPLVirtualMemGetAccessMode()                     */
 /************************************************************************/
 
-CPLVirtualMemAccessMode CPLVirtualMemGetAccessMode(CPLVirtualMem* ctxt)
+CPLVirtualMemAccessMode CPLVirtualMemGetAccessMode( CPLVirtualMem* ctxt )
 {
     return ctxt->eAccessMode;
 }
@@ -2161,7 +2221,7 @@ CPLVirtualMemAccessMode CPLVirtualMemGetAccessMode(CPLVirtualMem* ctxt)
 /*                      CPLVirtualMemGetPageSize()                      */
 /************************************************************************/
 
-size_t CPLVirtualMemGetPageSize(CPLVirtualMem* ctxt)
+size_t CPLVirtualMemGetPageSize( CPLVirtualMem* ctxt )
 {
     return ctxt->nPageSize;
 }
@@ -2170,7 +2230,7 @@ size_t CPLVirtualMemGetPageSize(CPLVirtualMem* ctxt)
 /*                        CPLVirtualMemGetSize()                        */
 /************************************************************************/
 
-size_t CPLVirtualMemGetSize(CPLVirtualMem* ctxt)
+size_t CPLVirtualMemGetSize( CPLVirtualMem* ctxt )
 {
     return ctxt->nSize;
 }
@@ -2179,7 +2239,7 @@ size_t CPLVirtualMemGetSize(CPLVirtualMem* ctxt)
 /*                   CPLVirtualMemIsAccessThreadSafe()                  */
 /************************************************************************/
 
-int CPLVirtualMemIsAccessThreadSafe(CPLVirtualMem* ctxt)
+int CPLVirtualMemIsAccessThreadSafe( CPLVirtualMem* ctxt )
 {
     return !ctxt->bSingleThreadUsage;
 }
@@ -2188,11 +2248,12 @@ int CPLVirtualMemIsAccessThreadSafe(CPLVirtualMem* ctxt)
 /*                       CPLVirtualMemDerivedNew()                      */
 /************************************************************************/
 
-CPLVirtualMem *CPLVirtualMemDerivedNew(CPLVirtualMem* pVMemBase,
-                                       vsi_l_offset nOffset,
-                                       vsi_l_offset nSize,
-                                       CPLVirtualMemFreeUserData pfnFreeUserData,
-                                       void *pCbkUserData)
+CPLVirtualMem *CPLVirtualMemDerivedNew(
+    CPLVirtualMem* pVMemBase,
+    vsi_l_offset nOffset,
+    vsi_l_offset nSize,
+    CPLVirtualMemFreeUserData pfnFreeUserData,
+    void *pCbkUserData )
 {
     if( nOffset + nSize > pVMemBase->nSize )
         return NULL;
@@ -2205,13 +2266,13 @@ CPLVirtualMem *CPLVirtualMemDerivedNew(CPLVirtualMem* pVMemBase,
     ctxt->eType = pVMemBase->eType;
     ctxt->nRefCount = 1;
     ctxt->pVMemBase = pVMemBase;
-    pVMemBase->nRefCount ++;
+    pVMemBase->nRefCount++;
     ctxt->eAccessMode = pVMemBase->eAccessMode;
     ctxt->pData = static_cast<GByte *>(pVMemBase->pData) + nOffset;
     ctxt->pDataToFree = NULL;
     ctxt->nSize = static_cast<size_t>(nSize);
     ctxt->nPageSize = pVMemBase->nPageSize;
-    ctxt->bSingleThreadUsage = pVMemBase->bSingleThreadUsage;
+    ctxt->bSingleThreadUsage = CPL_TO_BOOL(pVMemBase->bSingleThreadUsage);
     ctxt->pfnFreeUserData = pfnFreeUserData;
     ctxt->pCbkUserData = pCbkUserData;
 
diff --git a/port/cpl_virtualmem.h b/port/cpl_virtualmem.h
index 271c583..0aed5c7 100644
--- a/port/cpl_virtualmem.h
+++ b/port/cpl_virtualmem.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_virtualmem.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cpl_virtualmem.h 36485 2016-11-24 07:54:20Z goatbar $
  *
  * Name:     cpl_virtualmem.h
  * Project:  CPL - Common Portability Library
@@ -31,6 +31,8 @@
 #ifndef CPL_VIRTUAL_MEM_INCLUDED
 #define CPL_VIRTUAL_MEM_INCLUDED
 
+#include <stddef.h>
+
 #include "cpl_port.h"
 #include "cpl_vsi.h"
 
@@ -110,7 +112,6 @@ typedef enum
     VIRTUALMEM_READWRITE
 } CPLVirtualMemAccessMode;
 
-
 /** Return the size of a page of virtual memory.
  *
  * @return the page size.
@@ -173,7 +174,6 @@ CPLVirtualMem CPL_DLL *CPLVirtualMemNew(size_t nSize,
                                         CPLVirtualMemFreeUserData pfnFreeUserData,
                                         void *pCbkUserData);
 
-
 /** Return if virtual memory mapping of a file is available.
  *
  * @return TRUE if virtual memory mapping of a file is available.
@@ -384,7 +384,6 @@ void CPL_DLL CPLVirtualMemPin(CPLVirtualMem* ctxt,
  */
 void CPL_DLL CPLVirtualMemManagerTerminate(void);
 
-
 CPL_C_END
 
 #endif /* CPL_VIRTUAL_MEM_INCLUDED */
diff --git a/port/cpl_vsi.h b/port/cpl_vsi.h
index 16768a2..94e5e64 100644
--- a/port/cpl_vsi.h
+++ b/port/cpl_vsi.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi.h 33758 2016-03-21 09:06:22Z rouault $
+ * $Id: cpl_vsi.h 37640 2017-03-07 15:20:35Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Author:   Frank Warmerdam, warmerdam at pobox.com
@@ -65,18 +65,21 @@
 
 CPL_C_START
 
+/*! @cond Doxygen_Suppress */
 #ifdef ENABLE_EXPERIMENTAL_CPL_WARN_UNUSED_RESULT
 #define EXPERIMENTAL_CPL_WARN_UNUSED_RESULT CPL_WARN_UNUSED_RESULT
 #else
 #define EXPERIMENTAL_CPL_WARN_UNUSED_RESULT
 #endif
+/*! @endcond */
 
 /* ==================================================================== */
-/*      stdio file access functions.  These may not support large       */
-/*      files, and don't necessarily go through the virtualization      */
-/*      API.                                                            */
+/*      stdio file access functions.  These do not support large       */
+/*      files, and do not go through the virtualization API.           */
 /* ==================================================================== */
 
+/*! @cond Doxygen_Suppress */
+
 FILE CPL_DLL *  VSIFOpen( const char *, const char * ) CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIFClose( FILE * );
 int CPL_DLL     VSIFSeek( FILE *, long, int ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
@@ -88,19 +91,23 @@ size_t CPL_DLL  VSIFRead( void *, size_t, size_t, FILE * ) EXPERIMENTAL_CPL_WARN
 size_t CPL_DLL  VSIFWrite( const void *, size_t, size_t, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 char CPL_DLL   *VSIFGets( char *, int, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIFPuts( const char *, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
-int CPL_DLL     VSIFPrintf( FILE *, const char *, ... ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT CPL_PRINT_FUNC_FORMAT(2, 3);
+int CPL_DLL     VSIFPrintf( FILE *, CPL_FORMAT_STRING(const char *), ... ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT CPL_PRINT_FUNC_FORMAT(2, 3);
 
 int CPL_DLL     VSIFGetc( FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIFPutc( int, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIUngetc( int, FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIFEof( FILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 
+/*! @endcond */
+
 /* ==================================================================== */
 /*      VSIStat() related.                                              */
 /* ==================================================================== */
 
+/*! @cond Doxygen_Suppress */
 typedef struct stat VSIStatBuf;
 int CPL_DLL VSIStat( const char *, VSIStatBuf * ) CPL_WARN_UNUSED_RESULT;
+/*! @endcond */
 
 #ifdef _WIN32
 #  define VSI_ISLNK(x)  ( 0 )            /* N/A on Windows */
@@ -109,11 +116,16 @@ int CPL_DLL VSIStat( const char *, VSIStatBuf * ) CPL_WARN_UNUSED_RESULT;
 #  define VSI_ISCHR(x)  ((x) & S_IFCHR)
 #  define VSI_ISBLK(x)  ( 0 )            /* N/A on Windows */
 #else
+/** Test if the file is a symbolic link */
 #  define VSI_ISLNK(x)  S_ISLNK(x)
+/** Test if the file is a regular file */
 #  define VSI_ISREG(x)  S_ISREG(x)
+/** Test if the file is a directory */
 #  define VSI_ISDIR(x)  S_ISDIR(x)
+/*! @cond Doxygen_Suppress */
 #  define VSI_ISCHR(x)  S_ISCHR(x)
 #  define VSI_ISBLK(x)  S_ISBLK(x)
+/*! @endcond */
 #endif
 
 /* ==================================================================== */
@@ -121,17 +133,24 @@ int CPL_DLL VSIStat( const char *, VSIStatBuf * ) CPL_WARN_UNUSED_RESULT;
 /*      defined, then provide prototypes for the large file API,        */
 /*      otherwise redefine to use the regular api.                      */
 /* ==================================================================== */
+
+/** Type for a file offset */
 typedef GUIntBig vsi_l_offset;
+/** Maximum value for a file offset */
 #define VSI_L_OFFSET_MAX GUINTBIG_MAX
 
+/*! @cond Doxygen_Suppress */
 /* Make VSIL_STRICT_ENFORCE active in DEBUG builds */
 #ifdef DEBUG
 #define VSIL_STRICT_ENFORCE
 #endif
+/*! @endcond */
 
 #ifdef VSIL_STRICT_ENFORCE
+/** Opaque type for a FILE that implements the VSIVirtualHandle API */
 typedef struct _VSILFILE VSILFILE;
 #else
+/** Opaque type for a FILE that implements the VSIVirtualHandle API */
 typedef FILE VSILFILE;
 #endif
 
@@ -147,9 +166,19 @@ size_t CPL_DLL  VSIFWriteL( const void *, size_t, size_t, VSILFILE * ) EXPERIMEN
 int CPL_DLL     VSIFEofL( VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIFTruncateL( VSILFILE *, vsi_l_offset ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 int CPL_DLL     VSIFFlushL( VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
-int CPL_DLL     VSIFPrintfL( VSILFILE *, const char *, ... ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT CPL_PRINT_FUNC_FORMAT(2, 3);
+int CPL_DLL     VSIFPrintfL( VSILFILE *, CPL_FORMAT_STRING(const char *), ... ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT CPL_PRINT_FUNC_FORMAT(2, 3);
 int CPL_DLL     VSIFPutcL( int, VSILFILE * ) EXPERIMENTAL_CPL_WARN_UNUSED_RESULT;
 
+/** Range status */
+typedef enum
+{
+    VSI_RANGE_STATUS_UNKNOWN, /**< Unknown */
+    VSI_RANGE_STATUS_DATA,    /**< Data present */
+    VSI_RANGE_STATUS_HOLE     /**< Hole */
+} VSIRangeStatus;
+
+VSIRangeStatus CPL_DLL VSIFGetRangeStatusL( VSILFILE * fp, vsi_l_offset nStart, vsi_l_offset nLength );
+
 int CPL_DLL     VSIIngestFile( VSILFILE* fp,
                                const char* pszFilename,
                                GByte** ppabyRet,
@@ -157,22 +186,30 @@ int CPL_DLL     VSIIngestFile( VSILFILE* fp,
                                GIntBig nMaxSize ) CPL_WARN_UNUSED_RESULT;
 
 #if defined(VSI_STAT64_T)
+/** Type for VSIStatL() */
 typedef struct VSI_STAT64_T VSIStatBufL;
 #else
+/** Type for VSIStatL() */
 #define VSIStatBufL    VSIStatBuf
 #endif
 
 int CPL_DLL     VSIStatL( const char *, VSIStatBufL * ) CPL_WARN_UNUSED_RESULT;
 
+/** Flag provided to VSIStatExL() to test if the file exists */
 #define VSI_STAT_EXISTS_FLAG         0x1
+/** Flag provided to VSIStatExL() to query the nature (file/dir) of the file */
 #define VSI_STAT_NATURE_FLAG         0x2
+/** Flag provided to VSIStatExL() to query the file size */
 #define VSI_STAT_SIZE_FLAG           0x4
+/** Flag provided to VSIStatExL() to issue a VSIError in case of failure */
 #define VSI_STAT_SET_ERROR_FLAG      0x8
 
 int CPL_DLL     VSIStatExL( const char * pszFilename, VSIStatBufL * psStatBuf, int nFlags ) CPL_WARN_UNUSED_RESULT;
 
 int CPL_DLL     VSIIsCaseSensitiveFS( const char * pszFilename );
 
+int CPL_DLL     VSISupportsSparseFiles( const char* pszPath );
+
 void CPL_DLL   *VSIFGetNativeFileDescriptorL( VSILFILE* );
 
 /* ==================================================================== */
@@ -185,6 +222,14 @@ void CPL_DLL    VSIFree( void * );
 void CPL_DLL   *VSIRealloc( void *, size_t ) CPL_WARN_UNUSED_RESULT;
 char CPL_DLL   *VSIStrdup( const char * ) CPL_WARN_UNUSED_RESULT;
 
+void CPL_DLL   *VSIMallocAligned( size_t nAlignment, size_t nSize ) CPL_WARN_UNUSED_RESULT;
+void CPL_DLL   *VSIMallocAlignedAuto( size_t nSize ) CPL_WARN_UNUSED_RESULT;
+void CPL_DLL    VSIFreeAligned( void* ptr );
+
+void CPL_DLL   *VSIMallocAlignedAutoVerbose( size_t nSize, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+/** VSIMallocAlignedAutoVerbose() with FILE and LINE reporting */
+#define VSI_MALLOC_ALIGNED_AUTO_VERBOSE( size ) VSIMallocAlignedAutoVerbose(size,__FILE__,__LINE__)
+
 /**
  VSIMalloc2 allocates (nSize1 * nSize2) bytes.
  In case of overflow of the multiplication, or if memory allocation fails, a
@@ -203,26 +248,36 @@ void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 ) CPL_WARN_UNUSED_RESULT;
 */
 void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 ) CPL_WARN_UNUSED_RESULT;
 
-
+/** VSIMallocVerbose */
 void CPL_DLL   *VSIMallocVerbose( size_t nSize, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+/** VSI_MALLOC_VERBOSE */
 #define VSI_MALLOC_VERBOSE( size ) VSIMallocVerbose(size,__FILE__,__LINE__)
 
+/** VSIMalloc2Verbose */
 void CPL_DLL   *VSIMalloc2Verbose( size_t nSize1, size_t nSize2, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+/** VSI_MALLOC2_VERBOSE */
 #define VSI_MALLOC2_VERBOSE( nSize1, nSize2 ) VSIMalloc2Verbose(nSize1,nSize2,__FILE__,__LINE__)
 
+/** VSIMalloc3Verbose */
 void CPL_DLL   *VSIMalloc3Verbose( size_t nSize1, size_t nSize2, size_t nSize3, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+/** VSI_MALLOC3_VERBOSE */
 #define VSI_MALLOC3_VERBOSE( nSize1, nSize2, nSize3 ) VSIMalloc3Verbose(nSize1,nSize2,nSize3,__FILE__,__LINE__)
 
+/** VSICallocVerbose */
 void CPL_DLL   *VSICallocVerbose(  size_t nCount, size_t nSize, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+/** VSI_CALLOC_VERBOSE */
 #define VSI_CALLOC_VERBOSE( nCount, nSize ) VSICallocVerbose(nCount,nSize,__FILE__,__LINE__)
 
+/** VSIReallocVerbose */
 void CPL_DLL   *VSIReallocVerbose(  void* pOldPtr, size_t nNewSize, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+/** VSI_REALLOC_VERBOSE */
 #define VSI_REALLOC_VERBOSE( pOldPtr, nNewSize ) VSIReallocVerbose(pOldPtr,nNewSize,__FILE__,__LINE__)
 
+/** VSIStrdupVerbose */
 char CPL_DLL   *VSIStrdupVerbose(  const char* pszStr, const char* pszFile, int nLine ) CPL_WARN_UNUSED_RESULT;
+/** VSI_STRDUP_VERBOSE */
 #define VSI_STRDUP_VERBOSE( pszStr ) VSIStrdupVerbose(pszStr,__FILE__,__LINE__)
 
-
 GIntBig CPL_DLL CPLGetPhysicalRAM(void);
 GIntBig CPL_DLL CPLGetUsablePhysicalRAM(void);
 
@@ -230,6 +285,7 @@ GIntBig CPL_DLL CPLGetUsablePhysicalRAM(void);
 /*      Other...                                                        */
 /* ==================================================================== */
 
+/** Alias of VSIReadDir() */
 #define CPLReadDir VSIReadDir
 char CPL_DLL **VSIReadDir( const char * );
 char CPL_DLL **VSIReadDirRecursive( const char *pszPath );
@@ -245,12 +301,16 @@ GIntBig CPL_DLL VSIGetDiskFreeSpace(const char *pszDirname);
 /*      Install special file access handlers.                           */
 /* ==================================================================== */
 void CPL_DLL VSIInstallMemFileHandler(void);
+/*! @cond Doxygen_Suppress */
 void CPL_DLL VSIInstallLargeFileHandler(void);
+/*! @endcond */
 void CPL_DLL VSIInstallSubFileHandler(void);
 void VSIInstallCurlFileHandler(void);
 void VSIInstallCurlStreamingFileHandler(void);
 void VSIInstallS3FileHandler(void);
 void VSIInstallS3StreamingFileHandler(void);
+void VSIInstallGSFileHandler(void);
+void VSIInstallGSStreamingFileHandler(void);
 void VSIInstallGZipFileHandler(void); /* No reason to export that */
 void VSIInstallZipFileHandler(void); /* No reason to export that */
 void VSIInstallStdinHandler(void); /* No reason to export that */
@@ -259,7 +319,9 @@ void CPL_DLL VSIInstallSparseFileHandler(void);
 void VSIInstallTarFileHandler(void); /* No reason to export that */
 void CPL_DLL VSIInstallCryptFileHandler(void);
 void CPL_DLL VSISetCryptKey(const GByte* pabyKey, int nKeySize);
+/*! @cond Doxygen_Suppress */
 void CPL_DLL VSICleanupFileManager(void);
+/*! @endcond */
 
 VSILFILE CPL_DLL *VSIFileFromMemBuffer( const char *pszFilename,
                                     GByte *pabyData,
@@ -269,6 +331,7 @@ GByte CPL_DLL *VSIGetMemFileBuffer( const char *pszFilename,
                                     vsi_l_offset *pnDataLength,
                                     int bUnlinkAndSeize );
 
+/** Callback used by VSIStdoutSetRedirection() */
 typedef size_t (*VSIWriteFunction)(const void* ptr, size_t size, size_t nmemb, FILE* stream);
 void CPL_DLL VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream );
 
@@ -276,13 +339,16 @@ void CPL_DLL VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream );
 /*      Time querying.                                                  */
 /* ==================================================================== */
 
+/*! @cond Doxygen_Suppress */
 unsigned long CPL_DLL VSITime( unsigned long * );
 const char CPL_DLL *VSICTime( unsigned long );
 struct tm CPL_DLL *VSIGMTime( const time_t *pnTime,
                               struct tm *poBrokenTime );
 struct tm CPL_DLL *VSILocalTime( const time_t *pnTime,
                                  struct tm *poBrokenTime );
+/*! @endcond */
 
+/*! @cond Doxygen_Suppress */
 /* -------------------------------------------------------------------- */
 /*      the following can be turned on for detailed logging of          */
 /*      almost all IO calls.                                            */
@@ -305,6 +371,7 @@ struct tm CPL_DLL *VSILocalTime( const time_t *pnTime,
 #define VSIDebug2( f, a1, a2 )     {}
 #define VSIDebug1( f, a1 )         {}
 #endif
+/*! @endcond */
 
 CPL_C_END
 
diff --git a/port/cpl_vsi_error.cpp b/port/cpl_vsi_error.cpp
index 46b57e2..69bc3ed 100644
--- a/port/cpl_vsi_error.cpp
+++ b/port/cpl_vsi_error.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsi_error.cpp 34355 2016-06-16 08:55:20Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implement an error system for reporting file system errors.
@@ -30,39 +29,43 @@
  ****************************************************************************/
 
 #include "cpl_vsi_error.h"
+
+#include <cstdarg>
+#include <cstdio>
+
+#include "cpl_config.h"
+#include "cpl_conv.h"
 #include "cpl_error.h"
+#include "cpl_multiproc.h"
 #include "cpl_string.h"
 #include "cpl_vsi.h"
-#include "cpl_conv.h"
-#include "cpl_multiproc.h"
 
+// TODO(rouault): Why is this here?
 #if !defined(WIN32)
 #include <string.h>
 #endif
 
-
 #define TIMESTAMP_DEBUG
-//#define MEMORY_DEBUG
+// #define MEMORY_DEBUG
 
-CPL_CVSID("$Id: cpl_vsi_error.cpp 34355 2016-06-16 08:55:20Z rouault $");
+CPL_CVSID("$Id: cpl_vsi_error.cpp 37003 2016-12-23 14:54:07Z goatbar $");
 
 static const int DEFAULT_LAST_ERR_MSG_SIZE =
 #if !defined(HAVE_VSNPRINTF)
-  20000
+    20000
 #else
-  500
+    500
 #endif
-  ;
+    ;
 
 typedef struct {
     VSIErrorNum nLastErrNo;
     int     nLastErrMsgMax;
     char    szLastErrMsg[DEFAULT_LAST_ERR_MSG_SIZE];
-    /* Do not add anything here. szLastErrMsg must be the last field. See CPLRealloc() below */
+    // Do not add anything here. szLastErrMsg must be the last field. See
+    // CPLRealloc() below.
 } VSIErrorContext;
 
-static void VSIErrorV(VSIErrorNum, const char *, va_list );
-
 /************************************************************************/
 /*                         CPLGetErrorContext()                         */
 /************************************************************************/
@@ -70,7 +73,7 @@ static void VSIErrorV(VSIErrorNum, const char *, va_list );
 static VSIErrorContext *VSIGetErrorContext()
 
 {
-    int bError;
+    int bError = FALSE;
     VSIErrorContext *psCtx =
         reinterpret_cast<VSIErrorContext *>(
             CPLGetTLSEx( CTLS_VSIERRORCONTEXT, &bError ) );
@@ -79,10 +82,12 @@ static VSIErrorContext *VSIGetErrorContext()
 
     if( psCtx == NULL )
     {
-      psCtx = reinterpret_cast<VSIErrorContext *>(
-          VSICalloc( sizeof(VSIErrorContext), 1) );
-        if (psCtx == NULL) {
-            fprintf(stderr, "Out of memory attempting to record a VSI error.\n");
+        psCtx = static_cast<VSIErrorContext *>(
+            VSICalloc( sizeof(VSIErrorContext), 1) );
+        if( psCtx == NULL )
+        {
+            fprintf(stderr, /*ok*/
+                    "Out of memory attempting to record a VSI error.\n");
             return NULL;
         }
         psCtx->nLastErrNo = VSIE_None;
@@ -93,39 +98,11 @@ static VSIErrorContext *VSIGetErrorContext()
     return psCtx;
 }
 
-/**********************************************************************
- *                          VSIError()
- **********************************************************************/
-
-/**
- * Report an VSI filesystem error.
- *
- * This function records an error in the filesystem that may or may not be
- * used in the future, for example converted into a CPLError. This allows
- * filesystem errors to be available to error handling functionality, but
- * reported only when necessary.
- *
- * @param err_no the error number (VSIE_*) from cpl_vsi_error.h.
- * @param fmt a printf() style format string.  Any additional arguments
- * will be treated as arguments to fill in this format in a manner
- * similar to printf().
- */
-
-void    VSIError(VSIErrorNum err_no, const char *fmt, ...)
-{
-    va_list args;
-
-    // Expand the error message
-    va_start(args, fmt);
-    VSIErrorV( err_no, fmt, args );
-    va_end(args);
-}
-
 /************************************************************************/
 /*                             VSIErrorV()                              */
 /************************************************************************/
 
-void    VSIErrorV( VSIErrorNum err_no, const char *fmt, va_list args )
+static void VSIErrorV( VSIErrorNum err_no, const char *fmt, va_list args )
 {
     VSIErrorContext *psCtx = VSIGetErrorContext();
     if( psCtx == NULL )
@@ -145,7 +122,7 @@ void    VSIErrorV( VSIErrorNum err_no, const char *fmt, va_list args )
 #endif
 
         int nPreviousSize = 0;
-        int nPR;
+        int nPR = 0;
         while( ((nPR = CPLvsnprintf(
                      psCtx->szLastErrMsg+nPreviousSize,
                      psCtx->nLastErrMsgMax-nPreviousSize, fmt, wrk_args )) == -1
@@ -169,8 +146,7 @@ void    VSIErrorV( VSIErrorNum err_no, const char *fmt, va_list args )
 
         va_end( wrk_args );
     }
-#else
-    // !HAVE_VSNPRINTF
+#else // !HAVE_VSNPRINTF
     CPLvsnprintf( psCtx->szLastErrMsg, psCtx->nLastErrMsgMax, fmt, args);
 #endif
 
@@ -178,14 +154,42 @@ void    VSIErrorV( VSIErrorNum err_no, const char *fmt, va_list args )
 }
 
 /**********************************************************************
+ *                          VSIError()
+ **********************************************************************/
+
+/**
+ * Report an VSI filesystem error.
+ *
+ * This function records an error in the filesystem that may or may not be
+ * used in the future, for example converted into a CPLError. This allows
+ * filesystem errors to be available to error handling functionality, but
+ * reported only when necessary.
+ *
+ * @param err_no the error number (VSIE_*) from cpl_vsi_error.h.
+ * @param fmt a printf() style format string.  Any additional arguments
+ * will be treated as arguments to fill in this format in a manner
+ * similar to printf().
+ */
+
+void VSIError( VSIErrorNum err_no, CPL_FORMAT_STRING(const char *fmt), ... )
+{
+    va_list args;
+
+    // Expand the error message.
+    va_start(args, fmt);
+    VSIErrorV( err_no, fmt, args );
+    va_end(args);
+}
+
+/**********************************************************************
  *                          VSIErrorReset()
  **********************************************************************/
 
 /**
  * Erase any traces of previous errors.
  *
- * This is used to clear out the latest file system error when it is either translated
- * into a CPLError call or when it is determined to be ignorable.
+ * This is used to clear out the latest file system error when it is either
+ * translated into a CPLError call or when it is determined to be ignorable.
  */
 
 void CPL_STDCALL VSIErrorReset()
@@ -260,9 +264,12 @@ const char* CPL_STDCALL VSIGetLastErrorMsg()
  * @return TRUE if a CPLError was issued, or FALSE if not.
  */
 
-int CPL_DLL CPL_STDCALL VSIToCPLError(CPLErr eErrClass, CPLErrorNum eDefaultErrorNo) {
-    int err = VSIGetLastErrorNo();
-    switch(err) {
+int CPL_DLL CPL_STDCALL VSIToCPLError( CPLErr eErrClass,
+                                       CPLErrorNum eDefaultErrorNo )
+{
+    const int err = VSIGetLastErrorNo();
+    switch( err )
+    {
         case VSIE_None:
             return FALSE;
         case VSIE_FileError:
@@ -272,22 +279,28 @@ int CPL_DLL CPL_STDCALL VSIToCPLError(CPLErr eErrClass, CPLErrorNum eDefaultErro
             CPLError(eErrClass, CPLE_HttpResponse, "%s", VSIGetLastErrorMsg());
             break;
         case VSIE_AWSAccessDenied:
-            CPLError(eErrClass, CPLE_AWSAccessDenied, "%s", VSIGetLastErrorMsg());
+            CPLError(eErrClass, CPLE_AWSAccessDenied,
+                     "%s", VSIGetLastErrorMsg());
             break;
         case VSIE_AWSBucketNotFound:
-            CPLError(eErrClass, CPLE_AWSBucketNotFound, "%s", VSIGetLastErrorMsg());
+            CPLError(eErrClass, CPLE_AWSBucketNotFound,
+                     "%s", VSIGetLastErrorMsg());
             break;
         case VSIE_AWSObjectNotFound:
-            CPLError(eErrClass, CPLE_AWSObjectNotFound, "%s", VSIGetLastErrorMsg());
+            CPLError(eErrClass, CPLE_AWSObjectNotFound,
+                     "%s", VSIGetLastErrorMsg());
             break;
         case VSIE_AWSInvalidCredentials:
-            CPLError(eErrClass, CPLE_AWSInvalidCredentials, "%s", VSIGetLastErrorMsg());
+            CPLError(eErrClass, CPLE_AWSInvalidCredentials,
+                     "%s", VSIGetLastErrorMsg());
             break;
         case VSIE_AWSSignatureDoesNotMatch:
-            CPLError(eErrClass, CPLE_AWSSignatureDoesNotMatch, "%s", VSIGetLastErrorMsg());
+            CPLError(eErrClass, CPLE_AWSSignatureDoesNotMatch,
+                     "%s", VSIGetLastErrorMsg());
             break;
         default:
-            CPLError(eErrClass, CPLE_HttpResponse, "A filesystem error with code %d occurred", err);
+            CPLError(eErrClass, CPLE_HttpResponse,
+                     "A filesystem error with code %d occurred", err);
             break;
     }
 
diff --git a/port/cpl_vsi_error.h b/port/cpl_vsi_error.h
index 85f880f..379d2f5 100644
--- a/port/cpl_vsi_error.h
+++ b/port/cpl_vsi_error.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi_error.h 33758 2016-03-21 09:06:22Z rouault $
+ * $Id: cpl_vsi_error.h 36769 2016-12-10 01:44:43Z goatbar $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implement an error system for reporting file system errors.
@@ -54,13 +54,16 @@ typedef int VSIErrorNum;
 #define VSIE_AWSInvalidCredentials      9
 #define VSIE_AWSSignatureDoesNotMatch   10
 
-void CPL_DLL VSIError(VSIErrorNum err_no, const char *fmt, ...)  CPL_PRINT_FUNC_FORMAT (2, 3);
+void CPL_DLL VSIError( VSIErrorNum err_no,
+                       CPL_FORMAT_STRING(const char *fmt), ... )
+    CPL_PRINT_FUNC_FORMAT (2, 3);
 
 void CPL_DLL CPL_STDCALL VSIErrorReset( void );
 VSIErrorNum CPL_DLL CPL_STDCALL VSIGetLastErrorNo( void );
 const char CPL_DLL * CPL_STDCALL VSIGetLastErrorMsg( void );
 
-int CPL_DLL CPL_STDCALL VSIToCPLError(CPLErr eErrClass, CPLErrorNum eDefaultErrorNo);
+int CPL_DLL CPL_STDCALL VSIToCPLError( CPLErr eErrClass,
+                                       CPLErrorNum eDefaultErrorNo );
 
 CPL_C_END
 
diff --git a/port/cpl_vsi_mem.cpp b/port/cpl_vsi_mem.cpp
index 82fb27d..b0fee0b 100644
--- a/port/cpl_vsi_mem.cpp
+++ b/port/cpl_vsi_mem.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsi_mem.cpp 35728 2016-10-14 16:17:28Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of Memory Buffer virtual IO functions.
@@ -28,14 +27,34 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "cpl_vsi.h"
 #include "cpl_vsi_virtual.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
-#include "cpl_atomic_ops.h"
-#include <time.h>
+
+#include <cerrno>
+#include <cstddef>
+#include <cstring>
+#include <ctime>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#if HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+
 #include <map>
+#include <string>
+#include <utility>
+
+#include "cpl_atomic_ops.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
 
-CPL_CVSID("$Id: cpl_vsi_mem.cpp 35728 2016-10-14 16:17:28Z rouault $");
+//! @cond Doxygen_Suppress
+
+CPL_CVSID("$Id: cpl_vsi_mem.cpp 36990 2016-12-21 19:42:05Z goatbar $");
 
 /*
 ** Notes on Multithreading:
@@ -76,12 +95,13 @@ public:
     CPLString     osFilename;
     volatile int  nRefCount;
 
-    int           bIsDirectory;
+    bool          bIsDirectory;
 
-    int           bOwnData;
+    bool          bOwnData;
     GByte        *pabyData;
     vsi_l_offset  nLength;
     vsi_l_offset  nAllocLength;
+    vsi_l_offset  nMaxLength;
 
     time_t        mTime;
 
@@ -102,20 +122,27 @@ class VSIMemHandle CPL_FINAL : public VSIVirtualHandle
   public:
     VSIMemFile    *poFile;
     vsi_l_offset  m_nOffset;
-    int           bUpdate;
-    int           bEOF;
-    int           bExtendFileAtNextWrite;
-
-                      VSIMemHandle() : poFile(NULL), m_nOffset(0), bUpdate(0),
-                                       bEOF(0), bExtendFileAtNextWrite(0) {}
-
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Close();
-    virtual int       Truncate( vsi_l_offset nNewSize );
+    bool          bUpdate;
+    bool          bEOF;
+    bool          bExtendFileAtNextWrite;
+
+    VSIMemHandle() :
+        poFile(NULL),
+        m_nOffset(0),
+        bUpdate(false),
+        bEOF(false),
+        bExtendFileAtNextWrite(false) {}
+    virtual ~VSIMemHandle() {}
+
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize,
+                            size_t nMemb ) override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize,
+                             size_t nMemb ) override;
+    virtual int       Eof() override;
+    virtual int       Close() override;
+    virtual int       Truncate( vsi_l_offset nNewSize ) override;
 };
 
 /************************************************************************/
@@ -126,25 +153,29 @@ class VSIMemHandle CPL_FINAL : public VSIVirtualHandle
 
 class VSIMemFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
-public:
-    std::map<CPLString,VSIMemFile*>   oFileList;
+  public:
+    std::map<CPLString, VSIMemFile*> oFileList;
     CPLMutex        *hMutex;
 
                      VSIMemFilesystemHandler();
     virtual          ~VSIMemFilesystemHandler();
 
+    // TODO(schwehr): Fix VSIFileFromMemBuffer so that using is not needed.
     using VSIFilesystemHandler::Open;
 
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
-    virtual int      Unlink( const char *pszFilename );
-    virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
-    virtual int      Rename( const char *oldpath, const char *newpath );
-    virtual GIntBig  GetDiskFreeSpace( const char* pszDirname );
+                                    bool bSetError ) override;
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
+    virtual int      Unlink( const char *pszFilename ) override;
+    virtual int      Mkdir( const char *pszDirname, long nMode ) override;
+    virtual int      Rmdir( const char *pszDirname ) override;
+    virtual char   **ReadDirEx( const char *pszDirname,
+                                int nMaxFiles ) override;
+    virtual int      Rename( const char *oldpath,
+                             const char *newpath ) override;
+    virtual GIntBig  GetDiskFreeSpace( const char* pszDirname ) override;
 
     static  void     NormalizePath( CPLString & );
 
@@ -163,11 +194,12 @@ public:
 
 VSIMemFile::VSIMemFile() :
     nRefCount(0),
-    bIsDirectory(FALSE),
-    bOwnData(TRUE),
+    bIsDirectory(false),
+    bOwnData(true),
     pabyData(NULL),
     nLength(0),
-    nAllocLength(0)
+    nAllocLength(0),
+    nMaxLength(GUINTBIG_MAX)
 {
     time(&mTime);
 }
@@ -195,39 +227,52 @@ VSIMemFile::~VSIMemFile()
 bool VSIMemFile::SetLength( vsi_l_offset nNewLength )
 
 {
+    if( nNewLength > nMaxLength )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                 "Maximum file size reached!");
+        return false;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Grow underlying array if needed.                                */
 /* -------------------------------------------------------------------- */
     if( nNewLength > nAllocLength )
     {
-        /* If we don't own the buffer, we cannot reallocate it because */
-        /* the return address might be different from the one passed by */
-        /* the caller. Hence, the caller would not be able to free */
-        /* the buffer... */
+        // If we don't own the buffer, we cannot reallocate it because
+        // the return address might be different from the one passed by
+        // the caller. Hence, the caller would not be able to free
+        // the buffer.
         if( !bOwnData )
         {
-            CPLError(CE_Failure, CPLE_NotSupported,
-                     "Cannot extended in-memory file whose ownership was not transferred");
+            CPLError(
+                CE_Failure, CPLE_NotSupported,
+                "Cannot extended in-memory file whose ownership was not "
+                "transferred" );
             return false;
         }
 
-        GByte *pabyNewData;
         const vsi_l_offset nNewAlloc = (nNewLength + nNewLength / 10) + 5000;
-        if( (vsi_l_offset)(size_t)nNewAlloc != nNewAlloc )
-            pabyNewData = NULL;
-        else
-            pabyNewData = (GByte *) VSIRealloc(pabyData, (size_t)nNewAlloc);
+        GByte *pabyNewData = NULL;
+        if( static_cast<vsi_l_offset>(static_cast<size_t>(nNewAlloc))
+            == nNewAlloc )
+        {
+            pabyNewData = static_cast<GByte *>(
+                VSIRealloc(pabyData, static_cast<size_t>(nNewAlloc) ));
+        }
         if( pabyNewData == NULL )
         {
-            CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "Cannot extend in-memory file to " CPL_FRMT_GUIB " bytes due to out-of-memory situation",
-                     nNewAlloc);
+            CPLError(
+                CE_Failure, CPLE_OutOfMemory,
+                "Cannot extend in-memory file to " CPL_FRMT_GUIB
+                " bytes due to out-of-memory situation",
+                nNewAlloc);
             return false;
         }
 
-        /* Clear the new allocated part of the buffer */
+        // Clear the new allocated part of the buffer.
         memset(pabyNewData + nAllocLength, 0,
-               (size_t) (nNewAlloc - nAllocLength));
+               static_cast<size_t>(nNewAlloc - nAllocLength));
 
         pabyData = pabyNewData;
         nAllocLength = nNewAlloc;
@@ -245,7 +290,6 @@ bool VSIMemFile::SetLength( vsi_l_offset nNewLength )
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                               Close()                                */
 /************************************************************************/
@@ -268,37 +312,45 @@ int VSIMemHandle::Close()
 int VSIMemHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
 {
-    bExtendFileAtNextWrite = FALSE;
+    bExtendFileAtNextWrite = false;
     if( nWhence == SEEK_CUR )
+    {
         m_nOffset += nOffset;
+    }
     else if( nWhence == SEEK_SET )
+    {
         m_nOffset = nOffset;
+    }
     else if( nWhence == SEEK_END )
+    {
         m_nOffset = poFile->nLength + nOffset;
+    }
     else
     {
         errno = EINVAL;
         return -1;
     }
 
-    bEOF = FALSE;
+    bEOF = false;
 
     if( m_nOffset > poFile->nLength )
     {
-        if( !bUpdate ) // Read-only files cannot be extended by seek.
+        if( !bUpdate )  // Read-only files cannot be extended by seek.
         {
-            CPLDebug( "VSIMemHandle",
-                      "Attempt to extend read-only file '%s' to length " CPL_FRMT_GUIB " from " CPL_FRMT_GUIB ".",
-                      poFile->osFilename.c_str(),
-                      m_nOffset, poFile->nLength );
+            CPLDebug(
+                "VSIMemHandle",
+                "Attempt to extend read-only file '%s' to length " CPL_FRMT_GUIB
+                " from " CPL_FRMT_GUIB ".",
+                poFile->osFilename.c_str(),
+                m_nOffset, poFile->nLength);
 
             m_nOffset = poFile->nLength;
             errno = EACCES;
             return -1;
         }
-        else // Writable files are zero-extended by seek past end.
+        else  // Writable files are zero-extended by seek past end.
         {
-            bExtendFileAtNextWrite = TRUE;
+            bExtendFileAtNextWrite = true;
         }
     }
 
@@ -327,19 +379,20 @@ size_t VSIMemHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 
     if( nBytesToRead + m_nOffset > poFile->nLength )
     {
-        if (poFile->nLength < m_nOffset)
+        if( poFile->nLength < m_nOffset )
         {
-            bEOF = TRUE;
+            bEOF = true;
             return 0;
         }
 
-        nBytesToRead = (size_t)(poFile->nLength - m_nOffset);
+        nBytesToRead = static_cast<size_t>(poFile->nLength - m_nOffset);
         nCount = nBytesToRead / nSize;
-        bEOF = TRUE;
+        bEOF = true;
     }
 
     if( nBytesToRead )
-        memcpy( pBuffer, poFile->pabyData + m_nOffset, (size_t)nBytesToRead );
+        memcpy( pBuffer, poFile->pabyData + m_nOffset,
+                static_cast<size_t>(nBytesToRead) );
     m_nOffset += nBytesToRead;
 
     return nCount;
@@ -359,7 +412,7 @@ size_t VSIMemHandle::Write( const void * pBuffer, size_t nSize, size_t nCount )
     }
     if( bExtendFileAtNextWrite )
     {
-        bExtendFileAtNextWrite = FALSE;
+        bExtendFileAtNextWrite = false;
         if( !poFile->SetLength( m_nOffset ) )
             return 0;
     }
@@ -404,11 +457,11 @@ int VSIMemHandle::Truncate( vsi_l_offset nNewSize )
         return -1;
     }
 
-    bExtendFileAtNextWrite = FALSE;
-    if (poFile->SetLength( nNewSize ))
+    bExtendFileAtNextWrite = false;
+    if( poFile->SetLength( nNewSize ) )
         return 0;
-    else
-        return -1;
+
+    return -1;
 }
 
 /************************************************************************/
@@ -423,7 +476,7 @@ int VSIMemHandle::Truncate( vsi_l_offset nNewSize )
 
 VSIMemFilesystemHandler::VSIMemFilesystemHandler() :
     hMutex(NULL)
-{ }
+{}
 
 /************************************************************************/
 /*                      ~VSIMemFilesystemHandler()                      */
@@ -432,7 +485,8 @@ VSIMemFilesystemHandler::VSIMemFilesystemHandler() :
 VSIMemFilesystemHandler::~VSIMemFilesystemHandler()
 
 {
-    for( std::map<CPLString,VSIMemFile*>::const_iterator iter = oFileList.begin();
+    for( std::map<CPLString, VSIMemFile*>::const_iterator iter =
+             oFileList.begin();
          iter != oFileList.end();
          ++iter )
     {
@@ -459,37 +513,48 @@ VSIMemFilesystemHandler::Open( const char *pszFilename,
     CPLString osFilename = pszFilename;
     NormalizePath( osFilename );
 
+    vsi_l_offset nMaxLength = GUINTBIG_MAX;
+    const size_t iPos = osFilename.find("||maxlength=");
+    if( iPos != std::string::npos )
+    {
+        nMaxLength = static_cast<vsi_l_offset>(CPLAtoGIntBig(
+                    osFilename.substr(iPos + strlen("||maxlength=")).c_str()));
+    }
+
 /* -------------------------------------------------------------------- */
 /*      Get the filename we are opening, create if needed.              */
 /* -------------------------------------------------------------------- */
-    VSIMemFile *poFile;
-    if( oFileList.find(osFilename) == oFileList.end() )
-        poFile = NULL;
-    else
+    VSIMemFile *poFile = NULL;
+    if( oFileList.find(osFilename) != oFileList.end() )
         poFile = oFileList[osFilename];
 
-    // If no file and opening in read, error out
-    if( strstr(pszAccess,"w") == NULL
+    // If no file and opening in read, error out.
+    if( strstr(pszAccess, "w") == NULL
         && strstr(pszAccess, "a") == NULL
         && poFile == NULL )
     {
-        if(bSetError) { VSIError(VSIE_FileError, "No such file or directory"); }
+        if( bSetError )
+        {
+            VSIError(VSIE_FileError, "No such file or directory");
+        }
         errno = ENOENT;
         return NULL;
     }
 
-    // Create
+    // Create.
     if( poFile == NULL )
     {
         poFile = new VSIMemFile;
         poFile->osFilename = osFilename;
         oFileList[poFile->osFilename] = poFile;
-        CPLAtomicInc(&(poFile->nRefCount)); // for file list
+        CPLAtomicInc(&(poFile->nRefCount));  // For file list.
+        poFile->nMaxLength = nMaxLength;
     }
     // Overwrite
     else if( strstr(pszAccess, "w") )
     {
         poFile->SetLength(0);
+        poFile->nMaxLength = nMaxLength;
     }
 
     if( poFile->bIsDirectory )
@@ -505,16 +570,15 @@ VSIMemFilesystemHandler::Open( const char *pszFilename,
 
     poHandle->poFile = poFile;
     poHandle->m_nOffset = 0;
-    poHandle->bEOF = FALSE;
-    if( strstr(pszAccess,"w") || strstr(pszAccess,"+")
-        || strstr(pszAccess,"a") )
-        poHandle->bUpdate = TRUE;
-    else
-        poHandle->bUpdate = FALSE;
+    poHandle->bEOF = false;
+    poHandle->bUpdate =
+        strstr(pszAccess, "w") ||
+        strstr(pszAccess, "+") ||
+        strstr(pszAccess, "a");
 
     CPLAtomicInc(&(poFile->nRefCount));
 
-    if( strstr(pszAccess,"a") )
+    if( strstr(pszAccess, "a") )
         poHandle->m_nOffset = poFile->nLength;
 
     return poHandle;
@@ -536,7 +600,7 @@ int VSIMemFilesystemHandler::Stat( const char * pszFilename,
 
     memset( pStatBuf, 0, sizeof(VSIStatBufL) );
 
-    if ( osFilename == "/vsimem/" )
+    if( osFilename == "/vsimem/" )
     {
         pStatBuf->st_size = 0;
         pStatBuf->st_mode = S_IFDIR;
@@ -589,7 +653,6 @@ int VSIMemFilesystemHandler::Unlink_unlocked( const char * pszFilename )
     CPLString osFilename = pszFilename;
     NormalizePath( osFilename );
 
-
     if( oFileList.find(osFilename) == oFileList.end() )
     {
         errno = ENOENT;
@@ -629,9 +692,9 @@ int VSIMemFilesystemHandler::Mkdir( const char * pszPathname,
     VSIMemFile *poFile = new VSIMemFile;
 
     poFile->osFilename = osPathname;
-    poFile->bIsDirectory = TRUE;
+    poFile->bIsDirectory = true;
     oFileList[osPathname] = poFile;
-    CPLAtomicInc(&(poFile->nRefCount)); /* referenced by file list */
+    CPLAtomicInc(&(poFile->nRefCount));  // Referenced by file list.
 
     return 0;
 }
@@ -660,35 +723,37 @@ char **VSIMemFilesystemHandler::ReadDirEx( const char *pszPath,
 
     NormalizePath( osPath );
 
-    std::map<CPLString,VSIMemFile*>::const_iterator iter;
     char **papszDir = NULL;
-    size_t nPathLen = strlen(osPath);
+    size_t nPathLen = osPath.size();
 
-    if( nPathLen > 0 && osPath[nPathLen-1] == '/' )
+    if( nPathLen > 0 && osPath.back() == '/' )
         nPathLen--;
 
-    /* In case of really big number of files in the directory, CSLAddString */
-    /* can be slow (see #2158). We then directly build the list. */
-    int nItems=0;
-    int nAllocatedItems=0;
+    // In case of really big number of files in the directory, CSLAddString
+    // can be slow (see #2158). We then directly build the list.
+    int nItems = 0;
+    int nAllocatedItems = 0;
 
-    for( iter = oFileList.begin(); iter != oFileList.end(); ++iter )
+    for( std::map<CPLString, VSIMemFile*>::const_iterator iter =
+             oFileList.begin();
+         iter != oFileList.end();
+         ++iter )
     {
         const char *pszFilePath = iter->second->osFilename.c_str();
-        if( EQUALN(osPath,pszFilePath,nPathLen)
+        if( EQUALN(osPath, pszFilePath, nPathLen)
             && pszFilePath[nPathLen] == '/'
-            && strstr(pszFilePath+nPathLen+1,"/") == NULL )
+            && strstr(pszFilePath+nPathLen+1, "/") == NULL )
         {
-            if (nItems == 0)
+            if( nItems == 0 )
             {
-                papszDir = (char**) CPLCalloc(2,sizeof(char*));
+                papszDir = static_cast<char**>(CPLCalloc(2, sizeof(char*)));
                 nAllocatedItems = 1;
             }
-            else if (nItems >= nAllocatedItems)
+            else if( nItems >= nAllocatedItems )
             {
                 nAllocatedItems = nAllocatedItems * 2;
-                papszDir = (char**)CPLRealloc(papszDir,
-                                              (nAllocatedItems+2)*sizeof(char*));
+                papszDir = static_cast<char**>(
+                    CPLRealloc(papszDir, (nAllocatedItems + 2)*sizeof(char*)) );
             }
 
             papszDir[nItems] = CPLStrdup(pszFilePath+nPathLen+1);
@@ -719,7 +784,7 @@ int VSIMemFilesystemHandler::Rename( const char *pszOldPath,
     NormalizePath( osOldPath );
     NormalizePath( osNewPath );
 
-    if ( osOldPath.compare(osNewPath) == 0 )
+    if( osOldPath.compare(osNewPath) == 0 )
         return 0;
 
     if( oFileList.find(osOldPath) == oFileList.end() )
@@ -728,11 +793,11 @@ int VSIMemFilesystemHandler::Rename( const char *pszOldPath,
         return -1;
     }
 
-    std::map<CPLString,VSIMemFile*>::iterator it = oFileList.find(osOldPath);
-    while (it != oFileList.end() && it->first.ifind(osOldPath) == 0)
+    std::map<CPLString, VSIMemFile*>::iterator it = oFileList.find(osOldPath);
+    while( it != oFileList.end() && it->first.ifind(osOldPath) == 0 )
     {
         const CPLString osRemainder = it->first.substr(osOldPath.size());
-        if (osRemainder.empty() || osRemainder[0] == '/')
+        if( osRemainder.empty() || osRemainder[0] == '/' )
         {
             const CPLString osNewFullPath = osNewPath + osRemainder;
             Unlink_unlocked(osNewFullPath);
@@ -740,7 +805,10 @@ int VSIMemFilesystemHandler::Rename( const char *pszOldPath,
             it->second->osFilename = osNewFullPath;
             oFileList.erase(it++);
         }
-        else ++it;
+        else
+        {
+            ++it;
+        }
     }
 
     return 0;
@@ -760,7 +828,6 @@ void VSIMemFilesystemHandler::NormalizePath( CPLString &oPath )
         if( oPath[i] == '\\' )
             oPath[i] = '/';
     }
-
 }
 
 /************************************************************************/
@@ -769,12 +836,14 @@ void VSIMemFilesystemHandler::NormalizePath( CPLString &oPath )
 
 GIntBig VSIMemFilesystemHandler::GetDiskFreeSpace( const char* /*pszDirname*/ )
 {
-    GIntBig nRet = CPLGetUsablePhysicalRAM();
+    const GIntBig nRet = CPLGetUsablePhysicalRAM();
     if( nRet <= 0 )
-        nRet = -1;
+        return -1;
     return nRet;
 }
 
+//! @endcond
+
 /************************************************************************/
 /*                     VSIInstallLargeFileHandler()                     */
 /************************************************************************/
@@ -863,19 +932,20 @@ void VSIInstallMemFileHandler()
  */
 
 VSILFILE *VSIFileFromMemBuffer( const char *pszFilename,
-                          GByte *pabyData,
-                          vsi_l_offset nDataLength,
-                          int bTakeOwnership )
+                                GByte *pabyData,
+                                vsi_l_offset nDataLength,
+                                int bTakeOwnership )
 
 {
     if( VSIFileManager::GetHandler("")
         == VSIFileManager::GetHandler("/vsimem/") )
         VSIInstallMemFileHandler();
 
-    VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *)
-        VSIFileManager::GetHandler("/vsimem/");
+    VSIMemFilesystemHandler *poHandler =
+        static_cast<VSIMemFilesystemHandler *>(
+                VSIFileManager::GetHandler("/vsimem/"));
 
-    if (pszFilename == NULL)
+    if( pszFilename == NULL )
         return NULL;
 
     CPLString osFilename = pszFilename;
@@ -884,7 +954,7 @@ VSILFILE *VSIFileFromMemBuffer( const char *pszFilename,
     VSIMemFile *poFile = new VSIMemFile;
 
     poFile->osFilename = osFilename;
-    poFile->bOwnData = bTakeOwnership;
+    poFile->bOwnData = CPL_TO_BOOL(bTakeOwnership);
     poFile->pabyData = pabyData;
     poFile->nLength = nDataLength;
     poFile->nAllocLength = nDataLength;
@@ -896,7 +966,9 @@ VSILFILE *VSIFileFromMemBuffer( const char *pszFilename,
         CPLAtomicInc(&(poFile->nRefCount));
     }
 
-    return (VSILFILE *) poHandler->Open( osFilename, "r+" );
+    // TODO(schwehr): Fix this so that the using statement is not needed.
+    // Will just adding the bool for bSetError be okay?
+    return reinterpret_cast<VSILFILE *>( poHandler->Open( osFilename, "r+" ) );
 }
 
 /************************************************************************/
@@ -923,10 +995,11 @@ GByte *VSIGetMemFileBuffer( const char *pszFilename,
                             int bUnlinkAndSeize )
 
 {
-    VSIMemFilesystemHandler *poHandler = (VSIMemFilesystemHandler *)
-        VSIFileManager::GetHandler("/vsimem/");
+    VSIMemFilesystemHandler *poHandler =
+        static_cast<VSIMemFilesystemHandler *>(
+            VSIFileManager::GetHandler("/vsimem/"));
 
-    if (pszFilename == NULL)
+    if( pszFilename == NULL )
         return NULL;
 
     CPLString osFilename = pszFilename;
@@ -948,7 +1021,7 @@ GByte *VSIGetMemFileBuffer( const char *pszFilename,
             CPLDebug( "VSIMemFile",
                       "File doesn't own data in VSIGetMemFileBuffer!" );
         else
-            poFile->bOwnData = FALSE;
+            poFile->bOwnData = false;
 
         poHandler->oFileList.erase( poHandler->oFileList.find(osFilename) );
         CPLAtomicDec(&(poFile->nRefCount));
diff --git a/port/cpl_vsi_virtual.h b/port/cpl_vsi_virtual.h
index cdb7ae2..79b91fe 100644
--- a/port/cpl_vsi_virtual.h
+++ b/port/cpl_vsi_virtual.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsi_virtual.h 34165 2016-05-03 13:14:27Z rouault $
+ * $Id: cpl_vsi_virtual.h 36501 2016-11-25 14:09:24Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Declarations for classes related to the virtual filesystem.
@@ -43,22 +43,35 @@
 #include <vector>
 #include <string>
 
+// To avoid aliasing to GetDiskFreeSpace to GetDiskFreeSpaceA on Windows
+#ifdef GetDiskFreeSpace
+#undef GetDiskFreeSpace
+#endif
+
 /************************************************************************/
 /*                           VSIVirtualHandle                           */
 /************************************************************************/
 
+/** Virtual file handle */
 class CPL_DLL VSIVirtualHandle {
   public:
     virtual int       Seek( vsi_l_offset nOffset, int nWhence ) = 0;
     virtual vsi_l_offset Tell() = 0;
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb ) = 0;
-    virtual int       ReadMultiRange( int nRanges, void ** ppData, const vsi_l_offset* panOffsets, const size_t* panSizes );
-    virtual size_t    Write( const void *pBuffer, size_t nSize,size_t nMemb)=0;
+    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nCount ) = 0;
+    virtual int       ReadMultiRange( int nRanges, void ** ppData,
+                                      const vsi_l_offset* panOffsets,
+                                      const size_t* panSizes );
+    virtual size_t    Write( const void *pBuffer, size_t nSize,size_t nCount)=0;
     virtual int       Eof() = 0;
     virtual int       Flush() {return 0;}
     virtual int       Close() = 0;
-    virtual int       Truncate( CPL_UNUSED vsi_l_offset nNewSize ) { return -1; }
+    // Base implementation that only supports file extension.
+    virtual int       Truncate( vsi_l_offset nNewSize );
     virtual void     *GetNativeFileDescriptor() { return NULL; }
+    virtual VSIRangeStatus GetRangeStatus( CPL_UNUSED vsi_l_offset nOffset,
+                                           CPL_UNUSED vsi_l_offset nLength )
+                                          { return VSI_RANGE_STATUS_UNKNOWN; }
+
     virtual           ~VSIVirtualHandle() { }
 };
 
@@ -66,6 +79,7 @@ class CPL_DLL VSIVirtualHandle {
 /*                         VSIFilesystemHandler                         */
 /************************************************************************/
 
+#ifndef DOXYGEN_SKIP
 class CPL_DLL VSIFilesystemHandler {
 
 public:
@@ -94,12 +108,15 @@ public:
     virtual int IsCaseSensitive( const char* pszFilename )
                       { (void) pszFilename; return TRUE; }
     virtual GIntBig GetDiskFreeSpace( const char* /* pszDirname */ ) { return -1; }
+    virtual int SupportsSparseFiles( const char* /* pszPath */ ) { return FALSE; }
 };
+#endif /* #ifndef DOXYGEN_SKIP */
 
 /************************************************************************/
 /*                            VSIFileManager                            */
 /************************************************************************/
 
+#ifndef DOXYGEN_SKIP
 class CPL_DLL VSIFileManager
 {
 private:
@@ -119,7 +136,7 @@ public:
     /* RemoveHandler is never defined. */
     /* static void RemoveHandler( const std::string& osPrefix ); */
 };
-
+#endif /* #ifndef DOXYGEN_SKIP */
 
 /************************************************************************/
 /* ==================================================================== */
@@ -127,6 +144,8 @@ public:
 /* ==================================================================== */
 /************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
 class VSIArchiveEntryFileOffset
 {
     public:
@@ -185,12 +204,12 @@ public:
     VSIArchiveFilesystemHandler();
     virtual ~VSIArchiveFilesystemHandler();
 
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
-    virtual int      Unlink( const char *pszFilename );
-    virtual int      Rename( const char *oldpath, const char *newpath );
-    virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ) CPL_OVERRIDE;
+    virtual int      Unlink( const char *pszFilename ) CPL_OVERRIDE;
+    virtual int      Rename( const char *oldpath, const char *newpath ) CPL_OVERRIDE;
+    virtual int      Mkdir( const char *pszDirname, long nMode ) CPL_OVERRIDE;
+    virtual int      Rmdir( const char *pszDirname ) CPL_OVERRIDE;
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles ) CPL_OVERRIDE;
 
     virtual const VSIArchiveContent* GetContentOfArchive(const char* archiveFilename, VSIArchiveReader* poReader = NULL);
     virtual char* SplitFilename(const char *pszFilename, CPLString &osFileInArchive, int bCheckMainFileExists);
@@ -198,6 +217,8 @@ public:
     virtual int FindFileInArchive(const char* archiveFilename, const char* fileInArchiveName, const VSIArchiveEntry** archiveEntry);
 };
 
+#endif /* #ifndef DOXYGEN_SKIP */
+
 VSIVirtualHandle CPL_DLL *VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle);
 VSIVirtualHandle* VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
                                                 const GByte* pabyBeginningContent,
diff --git a/port/cpl_vsil.cpp b/port/cpl_vsil.cpp
index 57e0f16..8d1e2c6 100644
--- a/port/cpl_vsil.cpp
+++ b/port/cpl_vsil.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil.cpp 33853 2016-04-01 23:30:08Z goatbar $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation VSI*L File API and other file system access
@@ -29,14 +28,32 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "cpl_vsi.h"
+
+#include <cassert>
+#include <cstring>
+#include <cstdarg>
+#include <cstddef>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
 #include "cpl_multiproc.h"
 #include "cpl_string.h"
 #include "cpl_vsi_virtual.h"
 
-#include <cassert>
-#include <string>
 
-CPL_CVSID("$Id: cpl_vsil.cpp 33853 2016-04-01 23:30:08Z goatbar $");
+CPL_CVSID("$Id: cpl_vsil.cpp 37640 2017-03-07 15:20:35Z rouault $");
 
 /************************************************************************/
 /*                             VSIReadDir()                             */
@@ -62,7 +79,7 @@ CPL_CVSID("$Id: cpl_vsil.cpp 33853 2016-04-01 23:30:08Z goatbar $");
  * doesn't exist.  Filenames are returned in UTF-8 encoding.
  */
 
-char **VSIReadDir(const char *pszPath)
+char **VSIReadDir( const char *pszPath )
 {
     return VSIReadDirEx(pszPath, 0);
 }
@@ -96,7 +113,7 @@ char **VSIReadDir(const char *pszPath)
  * @since GDAL 2.1
  */
 
-char **VSIReadDirEx(const char *pszPath, int nMaxFiles)
+char **VSIReadDirEx( const char *pszPath, int nMaxFiles )
 {
     VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszPath );
@@ -115,7 +132,7 @@ typedef struct
     int i;
     char* pszPath;
     char* pszDisplayedPath;
-}  VSIReadDirRecursiveTask;
+} VSIReadDirRecursiveTask;
 
 /**
  * \brief Read names in a directory recursively.
@@ -153,32 +170,32 @@ char **VSIReadDirRecursive( const char *pszPathIn )
     char* pszPath = CPLStrdup(pszPathIn);
     char* pszDisplayedPath = NULL;
 
-    while(true)
+    while( true )
     {
         if( nCount < 0 )
         {
-            // get listing
+            // Get listing.
             papszFiles = VSIReadDir( pszPath );
 
-            // get files and directories inside listing
+            // Get files and directories inside listing.
             nCount = papszFiles ? CSLCount( papszFiles ) : 0;
             i = 0;
         }
 
-        for ( ; i < nCount; i++ )
+        for( ; i < nCount; i++ )
         {
             // Do not recurse up the tree.
-            if (EQUAL(".", papszFiles[i]) || EQUAL("..", papszFiles[i]))
+            if( EQUAL(".", papszFiles[i]) || EQUAL("..", papszFiles[i]) )
               continue;
 
-            // build complete file name for stat
+            // Build complete file name for stat.
             osTemp1.clear();
             osTemp1.append( pszPath );
             osTemp1.append( "/" );
             osTemp1.append( papszFiles[i] );
 
-            // if is file, add it
-            if ( VSIStatL( osTemp1.c_str(), &psStatBuf ) != 0 )
+            // If is file, add it.
+            if( VSIStatL( osTemp1.c_str(), &psStatBuf ) != 0 )
                 continue;
 
             if( VSI_ISREG( psStatBuf.st_mode ) )
@@ -194,9 +211,9 @@ char **VSIReadDirRecursive( const char *pszPathIn )
                 else
                     oFiles.AddString( papszFiles[i] );
             }
-            else if ( VSI_ISDIR( psStatBuf.st_mode ) )
+            else if( VSI_ISDIR( psStatBuf.st_mode ) )
             {
-                // add directory entry
+                // Add directory entry.
                 osTemp2.clear();
                 if( pszDisplayedPath )
                 {
@@ -212,7 +229,8 @@ char **VSIReadDirRecursive( const char *pszPathIn )
                 sTask.nCount = nCount;
                 sTask.i = i;
                 sTask.pszPath = CPLStrdup(pszPath);
-                sTask.pszDisplayedPath = pszDisplayedPath ? CPLStrdup(pszDisplayedPath) : NULL;
+                sTask.pszDisplayedPath =
+                    pszDisplayedPath ? CPLStrdup(pszDisplayedPath) : NULL;
                 aoStack.push_back(sTask);
 
                 CPLFree(pszPath);
@@ -220,9 +238,16 @@ char **VSIReadDirRecursive( const char *pszPathIn )
 
                 char* pszDisplayedPathNew = NULL;
                 if( pszDisplayedPath )
-                    pszDisplayedPathNew = CPLStrdup( CPLSPrintf("%s/%s", pszDisplayedPath, papszFiles[i]) );
+                {
+                    pszDisplayedPathNew =
+                        CPLStrdup(
+                            CPLSPrintf("%s/%s",
+                                       pszDisplayedPath, papszFiles[i]));
+                }
                 else
+                {
                     pszDisplayedPathNew = CPLStrdup( papszFiles[i] );
+                }
                 CPLFree(pszDisplayedPath);
                 pszDisplayedPath = pszDisplayedPathNew;
 
@@ -238,9 +263,9 @@ char **VSIReadDirRecursive( const char *pszPathIn )
         {
             CSLDestroy( papszFiles );
 
-            if( aoStack.size() )
+            if( !aoStack.empty() )
             {
-                int iLast = static_cast<int>(aoStack.size()) - 1;
+                const int iLast = static_cast<int>(aoStack.size()) - 1;
                 CPLFree(pszPath);
                 CPLFree(pszDisplayedPath);
                 nCount = aoStack[iLast].nCount;
@@ -252,7 +277,9 @@ char **VSIReadDirRecursive( const char *pszPathIn )
                 aoStack.resize(iLast);
             }
             else
+            {
                 break;
+            }
         }
     }
 
@@ -262,7 +289,6 @@ char **VSIReadDirRecursive( const char *pszPathIn )
     return oFiles.StealList();
 }
 
-
 /************************************************************************/
 /*                             CPLReadDir()                             */
 /*                                                                      */
@@ -415,7 +441,8 @@ int VSIRmdir( const char * pszDirname )
  *
  * Analog of the POSIX stat() function.
  *
- * @param pszFilename the path of the filesystem object to be queried.  UTF-8 encoded.
+ * @param pszFilename the path of the filesystem object to be queried.
+ * UTF-8 encoded.
  * @param psStatBuf the structure to load with information.
  *
  * @return 0 on success or -1 on an error.
@@ -427,7 +454,6 @@ int VSIStatL( const char * pszFilename, VSIStatBufL *psStatBuf )
     return VSIStatExL(pszFilename, psStatBuf, 0);
 }
 
-
 /************************************************************************/
 /*                            VSIStatExL()                              */
 /************************************************************************/
@@ -444,14 +470,17 @@ int VSIStatL( const char * pszFilename, VSIStatBufL *psStatBuf )
  * This method goes through the VSIFileHandler virtualization and may
  * work on unusual filesystems such as in memory.
  *
- * Analog of the POSIX stat() function, with an extra parameter to specify
- * which information is needed, which offers a potential for speed optimizations
- * on specialized and potentially slow virtual filesystem objects (/vsigzip/, /vsicurl/)
+ * Analog of the POSIX stat() function, with an extra parameter to
+ * specify which information is needed, which offers a potential for
+ * speed optimizations on specialized and potentially slow virtual
+ * filesystem objects (/vsigzip/, /vsicurl/)
  *
- * @param pszFilename the path of the filesystem object to be queried.  UTF-8 encoded.
+ * @param pszFilename the path of the filesystem object to be queried.
+ * UTF-8 encoded.
  * @param psStatBuf the structure to load with information.
- * @param nFlags 0 to get all information, or VSI_STAT_EXISTS_FLAG, VSI_STAT_NATURE_FLAG or
- *                  VSI_STAT_SIZE_FLAG, or a combination of those to get partial info.
+ * @param nFlags 0 to get all information, or VSI_STAT_EXISTS_FLAG,
+ *                  VSI_STAT_NATURE_FLAG or VSI_STAT_SIZE_FLAG, or a
+ *                  combination of those to get partial info.
  *
  * @return 0 on success or -1 on an error.
  *
@@ -461,8 +490,9 @@ int VSIStatL( const char * pszFilename, VSIStatBufL *psStatBuf )
 int VSIStatExL( const char * pszFilename, VSIStatBufL *psStatBuf, int nFlags )
 
 {
-    char    szAltPath[4] = { '\0' };
-    /* enable to work on "C:" as if it were "C:\" */
+    char szAltPath[4] = { '\0' };
+
+    // Enable to work on "C:" as if it were "C:\".
     if( strlen(pszFilename) == 2 && pszFilename[1] == ':' )
     {
         szAltPath[0] = pszFilename[0];
@@ -476,7 +506,7 @@ int VSIStatExL( const char * pszFilename, VSIStatBufL *psStatBuf, int nFlags )
     VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszFilename );
 
-    if (nFlags == 0)
+    if( nFlags == 0 )
         nFlags = VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG |
             VSI_STAT_SIZE_FLAG;
 
@@ -496,15 +526,17 @@ int VSIStatExL( const char * pszFilename, VSIStatBufL *psStatBuf, int nFlags )
  * Currently, this will return FALSE only for Windows real filenames. Other
  * VSI virtual filesystems are case sensitive.
  *
- * This methods avoid ugly #ifndef WIN32 / #endif code, that is wrong when
+ * This methods avoid ugly \#ifndef WIN32 / \#endif code, that is wrong when
  * dealing with virtual filenames.
  *
- * @param pszFilename the path of the filesystem object to be tested.  UTF-8 encoded.
+ * @param pszFilename the path of the filesystem object to be tested.
+ * UTF-8 encoded.
  *
  * @return TRUE if the filenames of the filesystem are case sensitive.
  *
  * @since GDAL 1.8.0
  */
+
 int VSIIsCaseSensitiveFS( const char * pszFilename )
 {
     VSIFilesystemHandler *poFSHandler =
@@ -514,6 +546,36 @@ int VSIIsCaseSensitiveFS( const char * pszFilename )
 }
 
 /************************************************************************/
+/*                       VSISupportsSparseFiles()                       */
+/************************************************************************/
+
+/**
+ * \brief Returns if the filesystem supports sparse files.
+ *
+ * Only supported on Linux (and no other Unix derivatives) and
+ * Windows.  On Linux, the answer depends on a few hardcoded
+ * signatures for common filesystems. Other filesystems will be
+ * considered as not supporting sparse files.
+ *
+ * @param pszPath the path of the filesystem object to be tested.
+ * UTF-8 encoded.
+ *
+ * @return TRUE if the file system is known to support sparse files. FALSE may
+ *              be returned both in cases where it is known to not support them,
+ *              or when it is unknown.
+ *
+ * @since GDAL 2.2
+ */
+
+int VSISupportsSparseFiles( const char* pszPath )
+{
+    VSIFilesystemHandler *poFSHandler =
+        VSIFileManager::GetHandler( pszPath );
+
+    return poFSHandler->SupportsSparseFiles( pszPath );
+}
+
+/************************************************************************/
 /*                             VSIFOpenL()                              */
 /************************************************************************/
 
@@ -553,12 +615,16 @@ VSILFILE *VSIFOpenL( const char * pszFilename, const char * pszAccess )
 /*                               Open()                                 */
 /************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
 VSIVirtualHandle *VSIFilesystemHandler::Open( const char *pszFilename,
-                                          const char *pszAccess )
+                                              const char *pszAccess )
 {
     return Open(pszFilename, pszAccess, false);
 }
 
+#endif
+
 /************************************************************************/
 /*                             VSIFOpenExL()                              */
 /************************************************************************/
@@ -585,14 +651,16 @@ VSIVirtualHandle *VSIFilesystemHandler::Open( const char *pszFilename,
  *
  * @param pszFilename the file to open.  UTF-8 encoded.
  * @param pszAccess access requested (i.e. "r", "r+", "w")
- * @param bSetError flag determining whether or not this open call should set VSIErrors on failure.
+ * @param bSetError flag determining whether or not this open call
+ * should set VSIErrors on failure.
  *
  * @return NULL on failure, or the file handle.
  *
  * @since GDAL 2.1
  */
 
-VSILFILE *VSIFOpenExL( const char * pszFilename, const char * pszAccess, int bSetError )
+VSILFILE *VSIFOpenExL( const char * pszFilename, const char * pszAccess,
+                       int bSetError )
 
 {
     VSIFilesystemHandler *poFSHandler =
@@ -601,7 +669,8 @@ VSILFILE *VSIFOpenExL( const char * pszFilename, const char * pszAccess, int bSe
     VSILFILE* fp = reinterpret_cast<VSILFILE *>(
         poFSHandler->Open( pszFilename, pszAccess, CPL_TO_BOOL(bSetError) ) );
 
-    VSIDebug4( "VSIFOpenExL(%s,%s,%d) = %p", pszFilename, pszAccess, bSetError, fp );
+    VSIDebug4( "VSIFOpenExL(%s,%s,%d) = %p",
+               pszFilename, pszAccess, bSetError, fp );
 
     return fp;
 }
@@ -611,6 +680,20 @@ VSILFILE *VSIFOpenExL( const char * pszFilename, const char * pszAccess, int bSe
 /************************************************************************/
 
 /**
+ * \fn VSIVirtualHandle::Close()
+ * \brief Close file.
+ *
+ * This function closes the indicated file.
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX fclose() function.
+ *
+ * @return 0 on success or -1 on failure.
+ */
+
+/**
  * \brief Close file.
  *
  * This function closes the indicated file.
@@ -645,6 +728,23 @@ int VSIFCloseL( VSILFILE * fp )
 /************************************************************************/
 
 /**
+ * \fn int VSIVirtualHandle::Seek( vsi_l_offset nOffset, int nWhence )
+ * \brief Seek to requested offset.
+ *
+ * Seek to the desired offset (nOffset) in the indicated file.
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX fseek() call.
+ *
+ * @param nOffset offset in bytes.
+ * @param nWhence one of SEEK_SET, SEEK_CUR or SEEK_END.
+ *
+ * @return 0 on success or -1 one failure.
+ */
+
+/**
  * \brief Seek to requested offset.
  *
  * Seek to the desired offset (nOffset) in the indicated file.
@@ -664,7 +764,7 @@ int VSIFCloseL( VSILFILE * fp )
 int VSIFSeekL( VSILFILE * fp, vsi_l_offset nOffset, int nWhence )
 
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>(fp);
 
     return poFileHandle->Seek( nOffset, nWhence );
 }
@@ -674,6 +774,21 @@ int VSIFSeekL( VSILFILE * fp, vsi_l_offset nOffset, int nWhence )
 /************************************************************************/
 
 /**
+ * \fn VSIVirtualHandle::Tell()
+ * \brief Tell current file offset.
+ *
+ * Returns the current file read/write offset in bytes from the beginning of
+ * the file.
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX ftell() call.
+ *
+ * @return file offset in bytes.
+ */
+
+/**
  * \brief Tell current file offset.
  *
  * Returns the current file read/write offset in bytes from the beginning of
@@ -722,6 +837,21 @@ void VSIRewindL( VSILFILE * fp )
 /************************************************************************/
 
 /**
+ * \fn VSIVirtualHandle::Flush()
+ * \brief Flush pending writes to disk.
+ *
+ * For files in write or update mode and on filesystem types where it is
+ * applicable, all pending output on the file is flushed to the physical disk.
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX fflush() call.
+ *
+ * @return 0 on success or -1 on error.
+ */
+
+/**
  * \brief Flush pending writes to disk.
  *
  * For files in write or update mode and on filesystem types where it is
@@ -750,6 +880,26 @@ int VSIFFlushL( VSILFILE * fp )
 /************************************************************************/
 
 /**
+ * \fn VSIVirtualHandle::Read( void *pBuffer, size_t nSize, size_t nCount )
+ * \brief Read bytes from file.
+ *
+ * Reads nCount objects of nSize bytes from the indicated file at the
+ * current offset into the indicated buffer.
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX fread() call.
+ *
+ * @param pBuffer the buffer into which the data should be read (at least
+ * nCount * nSize bytes in size.
+ * @param nSize size of objects to read in bytes.
+ * @param nCount number of objects to read.
+ *
+ * @return number of objects successfully read.
+ */
+
+/**
  * \brief Read bytes from file.
  *
  * Reads nCount objects of nSize bytes from the indicated file at the
@@ -777,12 +927,36 @@ size_t VSIFReadL( void * pBuffer, size_t nSize, size_t nCount, VSILFILE * fp )
     return poFileHandle->Read( pBuffer, nSize, nCount );
 }
 
-
 /************************************************************************/
 /*                       VSIFReadMultiRangeL()                          */
 /************************************************************************/
 
 /**
+ * \fn VSIVirtualHandle::ReadMultiRange( int nRanges, void ** ppData,
+ *                                       const vsi_l_offset* panOffsets,
+ *                                       const size_t* panSizes )
+ * \brief Read several ranges of bytes from file.
+ *
+ * Reads nRanges objects of panSizes[i] bytes from the indicated file at the
+ * offset panOffsets[i] into the buffer ppData[i].
+ *
+ * Ranges must be sorted in ascending start offset, and must not overlap each
+ * other.
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory or /vsicurl/.
+ *
+ * @param nRanges number of ranges to read.
+ * @param ppData array of nRanges buffer into which the data should be read
+ *               (ppData[i] must be at list panSizes[i] bytes).
+ * @param panOffsets array of nRanges offsets at which the data should be read.
+ * @param panSizes array of nRanges sizes of objects to read (in bytes).
+ *
+ * @return 0 in case of success, -1 otherwise.
+ * @since GDAL 1.9.0
+ */
+
+/**
  * \brief Read several ranges of bytes from file.
  *
  * Reads nRanges objects of panSizes[i] bytes from the indicated file at the
@@ -809,9 +983,9 @@ int VSIFReadMultiRangeL( int nRanges, void ** ppData,
                          const vsi_l_offset* panOffsets,
                          const size_t* panSizes, VSILFILE * fp )
 {
-    VSIVirtualHandle *poFileHandle = (VSIVirtualHandle *) fp;
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>(fp);
 
-    return poFileHandle->ReadMultiRange( nRanges, ppData, panOffsets, panSizes );
+    return poFileHandle->ReadMultiRange(nRanges, ppData, panOffsets, panSizes);
 }
 
 /************************************************************************/
@@ -819,6 +993,27 @@ int VSIFReadMultiRangeL( int nRanges, void ** ppData,
 /************************************************************************/
 
 /**
+ * \fn VSIVirtualHandle::Write( const void *pBuffer,
+ *                              size_t nSize, size_t nCount )
+ * \brief Write bytes to file.
+ *
+ * Writess nCount objects of nSize bytes to the indicated file at the
+ * current offset into the indicated buffer.
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX fwrite() call.
+ *
+ * @param pBuffer the buffer from which the data should be written (at least
+ * nCount * nSize bytes in size.
+ * @param nSize size of objects to read in bytes.
+ * @param nCount number of objects to read.
+ *
+ * @return number of objects successfully written.
+ */
+
+/**
  * \brief Write bytes to file.
  *
  * Writess nCount objects of nSize bytes to the indicated file at the
@@ -838,7 +1033,8 @@ int VSIFReadMultiRangeL( int nRanges, void ** ppData,
  * @return number of objects successfully written.
  */
 
-size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *fp )
+size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount,
+                   VSILFILE *fp )
 
 {
     VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
@@ -851,6 +1047,22 @@ size_t VSIFWriteL( const void *pBuffer, size_t nSize, size_t nCount, VSILFILE *f
 /************************************************************************/
 
 /**
+ * \fn VSIVirtualHandle::Eof()
+ * \brief Test for end of file.
+ *
+ * Returns TRUE (non-zero) if an end-of-file condition occurred during the
+ * previous read operation. The end-of-file flag is cleared by a successful
+ * VSIFSeekL() call.
+ *
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX feof() call.
+ *
+ * @return TRUE if at EOF else FALSE.
+ */
+
+/**
  * \brief Test for end of file.
  *
  * Returns TRUE (non-zero) if an end-of-file condition occurred during the
@@ -880,6 +1092,21 @@ int VSIFEofL( VSILFILE * fp )
 /************************************************************************/
 
 /**
+ * \fn VSIVirtualHandle::Truncate( vsi_l_offset nNewSize )
+ * \brief Truncate/expand the file to the specified size
+
+ * This method goes through the VSIFileHandler virtualization and may
+ * work on unusual filesystems such as in memory.
+ *
+ * Analog of the POSIX ftruncate() call.
+ *
+ * @param nNewSize new size in bytes.
+ *
+ * @return 0 on success
+ * @since GDAL 1.9.0
+ */
+
+/**
  * \brief Truncate/expand the file to the specified size
 
  * This method goes through the VSIFileHandler virtualization and may
@@ -897,7 +1124,7 @@ int VSIFEofL( VSILFILE * fp )
 int VSIFTruncateL( VSILFILE * fp, vsi_l_offset nNewSize )
 
 {
-  VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
 
     return poFileHandle->Truncate(nNewSize);
 }
@@ -915,12 +1142,12 @@ int VSIFTruncateL( VSILFILE * fp, vsi_l_offset nNewSize )
  * Analog of the POSIX fprintf() call.
  *
  * @param fp file handle opened with VSIFOpenL().
- * @param pszFormat the printf style format string.
+ * @param pszFormat the printf() style format string.
  *
  * @return the number of bytes written or -1 on an error.
  */
 
-int VSIFPrintfL( VSILFILE *fp, const char *pszFormat, ... )
+int VSIFPrintfL( VSILFILE *fp, CPL_FORMAT_STRING(const char *pszFormat), ... )
 
 {
     va_list args;
@@ -947,8 +1174,9 @@ int VSIFPrintfL( VSILFILE *fp, const char *pszFormat, ... )
  *
  * Writes the character nChar, cast to an unsigned char, to file.
  *
- * Almost an analog of the POSIX fputc() call, except that it returns
- * the number of character written (1 or 0), and not the (cast) character itself or EOF.
+ * Almost an analog of the POSIX  fputc() call, except that it returns
+ * the  number of  character  written (1  or 0),  and  not the  (cast)
+ * character itself or EOF.
  *
  * @param nChar character to write.
  * @param fp file handle opened with VSIFOpenL().
@@ -959,11 +1187,66 @@ int VSIFPrintfL( VSILFILE *fp, const char *pszFormat, ... )
 int VSIFPutcL( int nChar, VSILFILE * fp )
 
 {
-    unsigned char cChar = static_cast<unsigned char>(nChar);
+    const unsigned char cChar = static_cast<unsigned char>(nChar);
     return static_cast<int>(VSIFWriteL(&cChar, 1, 1, fp));
 }
 
 /************************************************************************/
+/*                        VSIFGetRangeStatusL()                        */
+/************************************************************************/
+
+// TODO(rouault): "exte,t" in r34586?
+
+/**
+ * \fn VSIVirtualHandle::GetRangeStatus( vsi_l_offset nOffset,
+ *                                       vsi_l_offset nLength )
+ * \brief Return if a given file range contains data or holes filled with zeroes
+ *
+ * This uses the filesystem capabilities of querying which regions of
+ * a sparse file are allocated or not. This is currently only
+ * implemented for Linux (and no other Unix derivatives) and Windows.
+ *
+ * Note: A return of VSI_RANGE_STATUS_DATA doesn't exclude that the
+ * exte,t is filled with zeroes! It must be interpreted as "may
+ * contain non-zero data".
+ *
+ * @param nOffset offset of the start of the extent.
+ * @param nLength extent length.
+ *
+ * @return extent status: VSI_RANGE_STATUS_UNKNOWN, VSI_RANGE_STATUS_DATA or
+ *         VSI_RANGE_STATUS_HOLE
+ * @since GDAL 2.2
+ */
+
+/**
+ * \brief Return if a given file range contains data or holes filled with zeroes
+ *
+ * This uses the filesystem capabilities of querying which regions of
+ * a sparse file are allocated or not. This is currently only
+ * implemented for Linux (and no other Unix derivatives) and Windows.
+ *
+ * Note: A return of VSI_RANGE_STATUS_DATA doesn't exclude that the
+ * exte,t is filled with zeroes! It must be interpreted as "may
+ * contain non-zero data".
+ *
+ * @param fp file handle opened with VSIFOpenL().
+ * @param nOffset offset of the start of the extent.
+ * @param nLength extent length.
+ *
+ * @return extent status: VSI_RANGE_STATUS_UNKNOWN, VSI_RANGE_STATUS_DATA or
+ *         VSI_RANGE_STATUS_HOLE
+ * @since GDAL 2.2
+ */
+
+VSIRangeStatus VSIFGetRangeStatusL( VSILFILE * fp, vsi_l_offset nOffset,
+                                    vsi_l_offset nLength )
+{
+    VSIVirtualHandle *poFileHandle = reinterpret_cast<VSIVirtualHandle *>( fp );
+
+    return poFileHandle->GetRangeStatus(nOffset, nLength);
+}
+
+/************************************************************************/
 /*                           VSIIngestFile()                            */
 /************************************************************************/
 
@@ -996,7 +1279,7 @@ int VSIIngestFile( VSILFILE* fp,
                    const char* pszFilename,
                    GByte** ppabyRet,
                    vsi_l_offset* pnSize,
-                   GIntBig nMaxSize)
+                   GIntBig nMaxSize )
 {
     if( fp == NULL && pszFilename == NULL )
         return FALSE;
@@ -1037,12 +1320,13 @@ int VSIIngestFile( VSILFILE* fp,
                 CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));
             return FALSE;
         }
-        while(true)
+        while( true )
         {
             if( nDataLen + 8192 + 1 > nDataAlloc )
             {
                 nDataAlloc = (nDataAlloc * 4) / 3 + 8192 + 1;
-                if( nDataAlloc > (vsi_l_offset)(size_t)nDataAlloc )
+                if( nDataAlloc >
+                    static_cast<vsi_l_offset>(static_cast<size_t>(nDataAlloc)) )
                 {
                     CPLError( CE_Failure, CPLE_AppDefined,
                               "Input file too large to be opened" );
@@ -1053,7 +1337,7 @@ int VSIIngestFile( VSILFILE* fp,
                     return FALSE;
                 }
                 GByte* pabyNew = static_cast<GByte *>(
-                    VSIRealloc(*ppabyRet, (size_t)nDataAlloc) );
+                    VSIRealloc(*ppabyRet, static_cast<size_t>(nDataAlloc)) );
                 if( pabyNew == NULL )
                 {
                     CPLError( CE_Failure, CPLE_OutOfMemory,
@@ -1071,10 +1355,11 @@ int VSIIngestFile( VSILFILE* fp,
                 VSIFReadL( *ppabyRet + nDataLen, 1, 8192, fp ) );
             nDataLen += nRead;
 
-            if ( nMaxSize >= 0 && nDataLen > (vsi_l_offset)nMaxSize )
+            if( nMaxSize >= 0 &&
+                nDataLen > static_cast<vsi_l_offset>(nMaxSize) )
             {
                 CPLError( CE_Failure, CPLE_AppDefined,
-                              "Input file too large to be opened" );
+                          "Input file too large to be opened" );
                 VSIFree( *ppabyRet );
                 *ppabyRet = NULL;
                 if( pnSize != NULL )
@@ -1103,8 +1388,9 @@ int VSIIngestFile( VSILFILE* fp,
 
         // With "large" VSI I/O API we can read data chunks larger than
         // VSIMalloc could allocate. Catch it here.
-        if ( nDataLen > (vsi_l_offset)(size_t)nDataLen ||
-             (nMaxSize >= 0 && nDataLen > (vsi_l_offset)nMaxSize) )
+        if( nDataLen > static_cast<vsi_l_offset>(static_cast<size_t>(nDataLen))
+            || (nMaxSize >= 0 &&
+                nDataLen > static_cast<vsi_l_offset>(nMaxSize)) )
         {
             CPLError( CE_Failure, CPLE_AppDefined,
                       "Input file too large to be opened" );
@@ -1121,7 +1407,7 @@ int VSIIngestFile( VSILFILE* fp,
         }
 
         *ppabyRet = static_cast<GByte *>(
-            VSIMalloc((size_t)(nDataLen + 1)) );
+            VSIMalloc(static_cast<size_t>(nDataLen + 1)) );
         if( NULL == *ppabyRet )
         {
             CPLError( CE_Failure, CPLE_OutOfMemory,
@@ -1133,7 +1419,8 @@ int VSIIngestFile( VSILFILE* fp,
         }
 
         (*ppabyRet)[nDataLen] = '\0';
-        if( ( nDataLen != VSIFReadL( *ppabyRet, 1, (size_t)nDataLen, fp ) ) )
+        if( nDataLen !=
+            VSIFReadL(*ppabyRet, 1, static_cast<size_t>(nDataLen), fp) )
         {
             CPLError( CE_Failure, CPLE_FileIO,
                       "Cannot read " CPL_FRMT_GIB " bytes",
@@ -1157,6 +1444,19 @@ int VSIIngestFile( VSILFILE* fp,
 /************************************************************************/
 
 /**
+ * \fn VSIVirtualHandle::GetNativeFileDescriptor()
+ * \brief Returns the "native" file descriptor for the virtual handle.
+ *
+ * This will only return a non-NULL value for "real" files handled by the
+ * operating system (to be opposed to GDAL virtual file systems).
+ *
+ * On POSIX systems, this will be a integer value ("fd") cast as a void*.
+ * On Windows systems, this will be the HANDLE.
+ *
+ * @return the native file descriptor, or NULL.
+ */
+
+/**
  * \brief Returns the "native" file descriptor for the virtual handle.
  *
  * This will only return a non-NULL value for "real" files handled by the
@@ -1191,7 +1491,7 @@ void *VSIFGetNativeFileDescriptorL( VSILFILE* fp )
  * @since GDAL 2.1
  */
 
-GIntBig VSIGetDiskFreeSpace(const char *pszDirname)
+GIntBig VSIGetDiskFreeSpace( const char *pszDirname )
 {
     VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszDirname );
@@ -1205,6 +1505,8 @@ GIntBig VSIGetDiskFreeSpace(const char *pszDirname)
 /* ==================================================================== */
 /************************************************************************/
 
+#ifndef DOXYGEN_SKIP
+
 /*
 ** Notes on Multithreading:
 **
@@ -1227,9 +1529,8 @@ VSIFileManager::VSIFileManager() :
 
 VSIFileManager::~VSIFileManager()
 {
-    std::map<std::string, VSIFilesystemHandler*>::const_iterator iter;
-
-    for( iter = oHandlers.begin();
+    for( std::map<std::string, VSIFilesystemHandler*>::const_iterator iter =
+             oHandlers.begin();
          iter != oHandlers.end();
          ++iter )
     {
@@ -1239,7 +1540,6 @@ VSIFileManager::~VSIFileManager()
     delete poDefaultHandler;
 }
 
-
 /************************************************************************/
 /*                                Get()                                 */
 /************************************************************************/
@@ -1261,7 +1561,7 @@ VSIFileManager *VSIFileManager::Get()
                 {
                     CPLMutexHolder oHolder( &hVSIFileManagerMutex );
                 }
-                if ( nConstructerPID != 0 )
+                if( nConstructerPID != 0 )
                 {
                     VSIDebug1( "nConstructerPID != 0: %d", nConstructerPID);
                     assert(false);
@@ -1276,7 +1576,8 @@ VSIFileManager *VSIFileManager::Get()
     {
         nConstructerPID = static_cast<GPtrDiff_t>(CPLGetPID());
 #ifdef DEBUG_VERBOSE
-        printf("Thread %d: VSIFileManager in construction\n", nConstructerPID);
+        printf("Thread %d: VSIFileManager in construction\n",  // ok
+               nConstructerPID);
 #endif
         poManager = new VSIFileManager;
         VSIInstallLargeFileHandler();
@@ -1291,6 +1592,8 @@ VSIFileManager *VSIFileManager::Get()
         VSIInstallCurlStreamingFileHandler();
         VSIInstallS3FileHandler();
         VSIInstallS3StreamingFileHandler();
+        VSIInstallGSFileHandler();
+        VSIInstallGSStreamingFileHandler();
 #endif
         VSIInstallStdinHandler();
         VSIInstallStdoutHandler();
@@ -1298,7 +1601,10 @@ VSIFileManager *VSIFileManager::Get()
         VSIInstallTarFileHandler();
         VSIInstallCryptFileHandler();
 
-        //printf("Thread %d: VSIFileManager construction finished\n", nConstructerPID);
+#ifdef DEBUG_VERBOSE
+        printf("Thread %d: VSIFileManager construction finished\n",  // ok
+               nConstructerPID);
+#endif
         nConstructerPID = 0;
     }
 
@@ -1313,28 +1619,28 @@ VSIFilesystemHandler *VSIFileManager::GetHandler( const char *pszPath )
 
 {
     VSIFileManager *poThis = Get();
-    std::map<std::string,VSIFilesystemHandler*>::const_iterator iter;
-    size_t nPathLen = strlen(pszPath);
+    const size_t nPathLen = strlen(pszPath);
 
-    for( iter = poThis->oHandlers.begin();
+    for( std::map<std::string, VSIFilesystemHandler*>::const_iterator iter =
+             poThis->oHandlers.begin();
          iter != poThis->oHandlers.end();
          ++iter )
     {
         const char* pszIterKey = iter->first.c_str();
-        size_t nIterKeyLen = iter->first.size();
-        if( strncmp(pszPath,pszIterKey,nIterKeyLen) == 0 )
+        const size_t nIterKeyLen = iter->first.size();
+        if( strncmp(pszPath, pszIterKey, nIterKeyLen) == 0 )
             return iter->second;
 
-        /* "/vsimem\foo" should be handled as "/vsimem/foo" */
-        if (nIterKeyLen && nPathLen > nIterKeyLen &&
+        // "/vsimem\foo" should be handled as "/vsimem/foo".
+        if( nIterKeyLen && nPathLen > nIterKeyLen &&
             pszIterKey[nIterKeyLen-1] == '/' &&
             pszPath[nIterKeyLen-1] == '\\' &&
-            strncmp(pszPath,pszIterKey,nIterKeyLen-1) == 0 )
+            strncmp(pszPath, pszIterKey, nIterKeyLen - 1) == 0 )
             return iter->second;
 
-        /* /vsimem should be treated as a match for /vsimem/ */
+        // /vsimem should be treated as a match for /vsimem/.
         if( nPathLen + 1 == nIterKeyLen
-            && strncmp(pszPath,pszIterKey,nPathLen) == 0 )
+            && strncmp(pszPath, pszIterKey, nPathLen) == 0 )
             return iter->second;
     }
 
@@ -1376,6 +1682,41 @@ void VSICleanupFileManager()
 }
 
 /************************************************************************/
+/*                            Truncate()                                */
+/************************************************************************/
+
+int VSIVirtualHandle::Truncate( vsi_l_offset nNewSize )
+{
+    const vsi_l_offset nOriginalPos = Tell();
+    if( Seek(0, SEEK_END) == 0 && nNewSize >= Tell() )
+    {
+        // Fill with zeroes
+        std::vector<GByte> aoBytes(4096, 0);
+        vsi_l_offset nCurOffset = nOriginalPos;
+        while( nCurOffset < nNewSize )
+        {
+            const vsi_l_offset nMaxOffset = 4096;
+            const int nSize =
+                static_cast<int>(
+                    std::min(nMaxOffset, nNewSize - nCurOffset));
+            if( Write(&aoBytes[0], nSize, 1) != 1 )
+            {
+                Seek( nOriginalPos, SEEK_SET );
+                return -1;
+            }
+            nCurOffset += nSize;
+        }
+        return Seek(nOriginalPos, SEEK_SET) == 0 ? 0 : -1;
+    }
+
+    CPLDebug("VSI",
+             "Truncation is not supported in generic implementation "
+             "of Truncate()");
+    Seek( nOriginalPos, SEEK_SET );
+    return -1;
+}
+
+/************************************************************************/
 /*                           ReadMultiRange()                           */
 /************************************************************************/
 
@@ -1387,14 +1728,14 @@ int VSIVirtualHandle::ReadMultiRange( int nRanges, void ** ppData,
     const vsi_l_offset nCurOffset = Tell();
     for( int i=0; i<nRanges; i++ )
     {
-        if (Seek(panOffsets[i], SEEK_SET) < 0)
+        if( Seek(panOffsets[i], SEEK_SET) < 0 )
         {
             nRet = -1;
             break;
         }
 
-        size_t nRead = Read(ppData[i], 1, panSizes[i]);
-        if (panSizes[i] != nRead)
+        const size_t nRead = Read(ppData[i], 1, panSizes[i]);
+        if( panSizes[i] != nRead )
         {
             nRet = -1;
             break;
@@ -1405,3 +1746,5 @@ int VSIVirtualHandle::ReadMultiRange( int nRanges, void ** ppData,
 
     return nRet;
 }
+
+#endif  // #ifndef DOXYGEN_SKIP
diff --git a/port/cpl_vsil_abstract_archive.cpp b/port/cpl_vsil_abstract_archive.cpp
index deab69a..96fdbbd 100644
--- a/port/cpl_vsil_abstract_archive.cpp
+++ b/port/cpl_vsil_abstract_archive.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil_abstract_archive.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for archive files.
@@ -27,31 +26,46 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_vsi_virtual.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
+
+#include <cstring>
+#if HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+#include <ctime>
 #include <map>
 #include <set>
+#include <string>
+#include <utility>
+#include <vector>
 
-#define ENABLE_DEBUG 0
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+
+//! @cond Doxygen_Suppress
 
-CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+CPL_CVSID("$Id: cpl_vsil_abstract_archive.cpp 37597 2017-03-04 17:27:00Z rouault $");
+
+static bool IsEitherSlash( char c )
+{
+    return c == '/' || c == '\\';
+}
 
 /************************************************************************/
 /*                    ~VSIArchiveEntryFileOffset()                      */
 /************************************************************************/
 
-VSIArchiveEntryFileOffset::~VSIArchiveEntryFileOffset()
-{
-}
+VSIArchiveEntryFileOffset::~VSIArchiveEntryFileOffset() {}
 
 /************************************************************************/
 /*                        ~VSIArchiveReader()                           */
 /************************************************************************/
 
-VSIArchiveReader::~VSIArchiveReader()
-{
-}
+VSIArchiveReader::~VSIArchiveReader() {}
 
 /************************************************************************/
 /*                        ~VSIArchiveContent()                          */
@@ -59,7 +73,7 @@ VSIArchiveReader::~VSIArchiveReader()
 
 VSIArchiveContent::~VSIArchiveContent()
 {
-    for(int i=0;i<nEntries;i++)
+    for( int i = 0; i < nEntries; i++ )
     {
         delete entries[i].file_pos;
         CPLFree(entries[i].fileName);
@@ -83,9 +97,10 @@ VSIArchiveFilesystemHandler::VSIArchiveFilesystemHandler()
 VSIArchiveFilesystemHandler::~VSIArchiveFilesystemHandler()
 
 {
-    std::map<CPLString,VSIArchiveContent*>::const_iterator iter;
-
-    for( iter = oFileList.begin(); iter != oFileList.end(); ++iter )
+    for( std::map<CPLString, VSIArchiveContent*>::const_iterator iter =
+             oFileList.begin();
+         iter != oFileList.end();
+         ++iter )
     {
         delete iter->second;
     }
@@ -95,26 +110,67 @@ VSIArchiveFilesystemHandler::~VSIArchiveFilesystemHandler()
     hMutex = NULL;
 }
 
+
+/************************************************************************/
+/*                       GetStrippedFilename()                          */
+/************************************************************************/
+
+static CPLString GetStrippedFilename(const CPLString& osFileName,
+                                     bool& bIsDir)
+{
+    bIsDir = false;
+    const char* fileName = osFileName.c_str();
+
+    // Remove ./ pattern at the beginning of a filename.
+    if( fileName[0] == '.' && fileName[1] == '/' )
+    {
+        fileName += 2;
+        if( fileName[0] == '\0' )
+            return CPLString();
+    }
+
+    char* pszStrippedFileName = CPLStrdup(fileName);
+    char* pszIter = NULL;
+    for( pszIter = pszStrippedFileName; *pszIter; pszIter++ )
+    {
+        if( *pszIter == '\\' )
+            *pszIter = '/';
+    }
+
+    const size_t nLen = strlen(fileName);
+    bIsDir = nLen > 0 && fileName[nLen-1] == '/';
+    if( bIsDir )
+    {
+        // Remove trailing slash.
+        pszStrippedFileName[nLen-1] = '\0';
+    }
+    CPLString osRet(pszStrippedFileName);
+    CPLFree(pszStrippedFileName);
+    return osRet;
+}
+
 /************************************************************************/
 /*                       GetContentOfArchive()                          */
 /************************************************************************/
 
-const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive
-        (const char* archiveFilename, VSIArchiveReader* poReader)
+const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive(
+    const char* archiveFilename, VSIArchiveReader* poReader )
 {
     CPLMutexHolder oHolder( &hMutex );
 
     VSIStatBufL sStat;
     if( VSIStatL(archiveFilename, &sStat) != 0 )
         return NULL;
-    if (oFileList.find(archiveFilename) != oFileList.end() )
+
+    if( oFileList.find(archiveFilename) != oFileList.end() )
     {
         VSIArchiveContent* content = oFileList[archiveFilename];
         if( (time_t)sStat.st_mtime > content->mTime ||
             (vsi_l_offset)sStat.st_size != content->nFileSize)
         {
-            CPLDebug("VSIArchive", "The content of %s has changed since it was cached",
-                    archiveFilename);
+            CPLDebug("VSIArchive",
+                     "The content of %s has changed since it was cached",
+                     archiveFilename);
             delete content;
             oFileList.erase(archiveFilename);
         }
@@ -124,17 +180,17 @@ const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive
         }
     }
 
-    int bMustClose = (poReader == NULL);
-    if (poReader == NULL)
+    bool bMustClose = poReader == NULL;
+    if( poReader == NULL )
     {
         poReader = CreateReader(archiveFilename);
-        if (!poReader)
+        if( !poReader )
             return NULL;
     }
 
-    if (poReader->GotoFirstFile() == FALSE)
+    if( poReader->GotoFirstFile() == FALSE )
     {
-        if (bMustClose)
+        if( bMustClose )
             delete(poReader);
         return NULL;
     }
@@ -150,59 +206,50 @@ const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive
 
     do
     {
-        CPLString osFileName = poReader->GetFileName();
-        const char* fileName = osFileName.c_str();
-
-        /* Remove ./ pattern at the beginning of a filename */
-        if (fileName[0] == '.' && fileName[1] == '/')
-        {
-            fileName += 2;
-            if (fileName[0] == '\0')
-                continue;
-        }
-
-        char* pszStrippedFileName = CPLStrdup(fileName);
-        char* pszIter;
-        for(pszIter = pszStrippedFileName;*pszIter;pszIter++)
+        const CPLString osFileName = poReader->GetFileName();
+        bool bIsDir = false;
+        const CPLString osStrippedFilename =
+                                GetStrippedFilename(osFileName, bIsDir);
+        if( osStrippedFilename.empty() )
+            continue;
+
+        if( oSet.find(osStrippedFilename) == oSet.end() )
         {
-            if (*pszIter == '\\')
-                *pszIter = '/';
-        }
+            oSet.insert(osStrippedFilename);
 
-        int bIsDir = strlen(fileName) > 0 &&
-                      fileName[strlen(fileName)-1] == '/';
-        if (bIsDir)
-        {
-            /* Remove trailing slash */
-            pszStrippedFileName[strlen(fileName)-1] = 0;
-        }
-
-        if (oSet.find(pszStrippedFileName) == oSet.end())
-        {
-            oSet.insert(pszStrippedFileName);
-
-            /* Add intermediate directory structure */
-            for(pszIter = pszStrippedFileName;*pszIter;pszIter++)
+            // Add intermediate directory structure.
+            const char* pszBegin = osStrippedFilename.c_str();
+            for( const char* pszIter = pszBegin; *pszIter; pszIter++ )
             {
-                if (*pszIter == '/')
+                if( *pszIter == '/' )
                 {
-                    char* pszStrippedFileName2 = CPLStrdup(pszStrippedFileName);
-                    pszStrippedFileName2[pszIter - pszStrippedFileName] = 0;
-                    if (oSet.find(pszStrippedFileName2) == oSet.end())
+                    char* pszStrippedFileName2 = CPLStrdup(osStrippedFilename);
+                    pszStrippedFileName2[pszIter - pszBegin] = 0;
+                    if( oSet.find(pszStrippedFileName2) == oSet.end() )
                     {
                         oSet.insert(pszStrippedFileName2);
 
-                        content->entries = (VSIArchiveEntry*)CPLRealloc(content->entries,
-                                sizeof(VSIArchiveEntry) * (content->nEntries + 1));
-                        content->entries[content->nEntries].fileName = pszStrippedFileName2;
-                        content->entries[content->nEntries].nModifiedTime = poReader->GetModifiedTime();
-                        content->entries[content->nEntries].uncompressed_size = 0;
+                        content->entries = static_cast<VSIArchiveEntry *>(
+                            CPLRealloc(
+                                content->entries,
+                                sizeof(VSIArchiveEntry) *
+                                (content->nEntries + 1)));
+                        content->entries[content->nEntries].fileName =
+                            pszStrippedFileName2;
+                        content->entries[content->nEntries].nModifiedTime =
+                            poReader->GetModifiedTime();
+                        content->entries[content->nEntries].uncompressed_size =
+                            0;
                         content->entries[content->nEntries].bIsDir = TRUE;
                         content->entries[content->nEntries].file_pos = NULL;
-                        if (ENABLE_DEBUG)
-                            CPLDebug("VSIArchive", "[%d] %s : " CPL_FRMT_GUIB " bytes", content->nEntries+1,
-                                content->entries[content->nEntries].fileName,
-                                content->entries[content->nEntries].uncompressed_size);
+#ifdef DEBUG_VERBOSE
+                        const int nEntries = content->nEntries;
+                        CPLDebug(
+                            "VSIArchive", "[%d] %s : " CPL_FRMT_GUIB " bytes",
+                            content->nEntries + 1,
+                            content->entries[nEntries].fileName,
+                            content->entries[nEntries].uncompressed_size);
+#endif
                         content->nEntries++;
                     }
                     else
@@ -212,26 +259,30 @@ const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive
                 }
             }
 
-            content->entries = (VSIArchiveEntry*)CPLRealloc(content->entries,
-                                sizeof(VSIArchiveEntry) * (content->nEntries + 1));
-            content->entries[content->nEntries].fileName = pszStrippedFileName;
-            content->entries[content->nEntries].nModifiedTime = poReader->GetModifiedTime();
-            content->entries[content->nEntries].uncompressed_size = poReader->GetFileSize();
+            content->entries = static_cast<VSIArchiveEntry *>(
+                CPLRealloc(content->entries,
+                           sizeof(VSIArchiveEntry) * (content->nEntries + 1)));
+            content->entries[content->nEntries].fileName =
+                CPLStrdup(osStrippedFilename);
+            content->entries[content->nEntries].nModifiedTime =
+                poReader->GetModifiedTime();
+            content->entries[content->nEntries].uncompressed_size =
+                poReader->GetFileSize();
             content->entries[content->nEntries].bIsDir = bIsDir;
-            content->entries[content->nEntries].file_pos = poReader->GetFileOffset();
-            if (ENABLE_DEBUG)
-                CPLDebug("VSIArchive", "[%d] %s : " CPL_FRMT_GUIB " bytes", content->nEntries+1,
-                    content->entries[content->nEntries].fileName,
-                    content->entries[content->nEntries].uncompressed_size);
+            content->entries[content->nEntries].file_pos =
+                poReader->GetFileOffset();
+#ifdef DEBUG_VERBOSE
+            CPLDebug("VSIArchive", "[%d] %s : " CPL_FRMT_GUIB " bytes",
+                     content->nEntries+1,
+                     content->entries[content->nEntries].fileName,
+                     content->entries[content->nEntries].uncompressed_size);
+#endif
             content->nEntries++;
         }
-        else
-        {
-            CPLFree(pszStrippedFileName);
-        }
-    } while(poReader->GotoNextFile());
 
-    if (bMustClose)
+    } while( poReader->GotoNextFile() );
+
+    if( bMustClose )
         delete(poReader);
 
     return content;
@@ -241,21 +292,23 @@ const VSIArchiveContent* VSIArchiveFilesystemHandler::GetContentOfArchive
 /*                        FindFileInArchive()                           */
 /************************************************************************/
 
-int VSIArchiveFilesystemHandler::FindFileInArchive(const char* archiveFilename,
-                                           const char* fileInArchiveName,
-                                           const VSIArchiveEntry** archiveEntry)
+int
+VSIArchiveFilesystemHandler::FindFileInArchive(
+    const char* archiveFilename,
+    const char* fileInArchiveName,
+    const VSIArchiveEntry** archiveEntry )
 {
-    if (fileInArchiveName == NULL)
+    if( fileInArchiveName == NULL )
         return FALSE;
 
     const VSIArchiveContent* content = GetContentOfArchive(archiveFilename);
-    if (content)
+    if( content )
     {
         for( int i = 0; i < content->nEntries; i++ )
         {
-            if (strcmp(fileInArchiveName, content->entries[i].fileName) == 0)
+            if( strcmp(fileInArchiveName, content->entries[i].fileName) == 0)
             {
-                if (archiveEntry)
+                if( archiveEntry )
                     *archiveEntry = &content->entries[i];
                 return TRUE;
             }
@@ -265,65 +318,184 @@ int VSIArchiveFilesystemHandler::FindFileInArchive(const char* archiveFilename,
 }
 
 /************************************************************************/
+/*                           CompactFilename()                          */
+/************************************************************************/
+
+static CPLString CompactFilename( const char* pszArchiveInFileNameIn )
+{
+    char* pszArchiveInFileName = CPLStrdup(pszArchiveInFileNameIn);
+
+    // Replace a/../b by b and foo/a/../b by foo/b.
+    while( true )
+    {
+        char* pszPrevDir = strstr(pszArchiveInFileName, "/../");
+        if( pszPrevDir == NULL || pszPrevDir == pszArchiveInFileName )
+            break;
+
+        char* pszPrevSlash = pszPrevDir - 1;
+        while( pszPrevSlash != pszArchiveInFileName &&
+               *pszPrevSlash != '/' )
+            pszPrevSlash--;
+        if( pszPrevSlash == pszArchiveInFileName )
+            memmove(pszArchiveInFileName,
+                    pszPrevDir + 4,
+                    strlen(pszPrevDir + 4) + 1);
+        else
+            memmove(pszPrevSlash + 1,
+                    pszPrevDir + 4,
+                    strlen(pszPrevDir + 4) + 1);
+    }
+
+    CPLString osFileInArchive = pszArchiveInFileName;
+    CPLFree(pszArchiveInFileName);
+    return osFileInArchive;
+}
+
+/************************************************************************/
 /*                           SplitFilename()                            */
 /************************************************************************/
 
-char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
-                                                 CPLString &osFileInArchive,
-                                                 int bCheckMainFileExists)
+char* VSIArchiveFilesystemHandler::SplitFilename( const char *pszFilename,
+                                                  CPLString &osFileInArchive,
+                                                  int bCheckMainFileExists )
 {
+    // TODO(schwehr): Cleanup redundant calls to GetPrefix and strlen.
+    if( strcmp(pszFilename, GetPrefix()) == 0 )
+        return NULL;
+
     int i = 0;
 
-    if (strcmp(pszFilename, GetPrefix()) == 0)
+    // Detect extended syntax: /vsiXXX/{archive_filename}/file_in_archive.
+    if( pszFilename[strlen(GetPrefix()) + 1] == '{' )
+    {
+        pszFilename += strlen(GetPrefix()) + 1;
+        int nCountCurlies = 0;
+        while( pszFilename[i] )
+        {
+            if( pszFilename[i] == '{' )
+                nCountCurlies++;
+            else if( pszFilename[i] == '}' )
+            {
+                nCountCurlies--;
+                if( nCountCurlies == 0 )
+                    break;
+            }
+            i++;
+        }
+        if( nCountCurlies > 0 )
+            return NULL;
+        char* archiveFilename = CPLStrdup(pszFilename + 1);
+        archiveFilename[i - 1] = 0;
+
+        bool bArchiveFileExists = false;
+        if( !bCheckMainFileExists )
+        {
+            bArchiveFileExists = true;
+        }
+        else
+        {
+            CPLMutexHolder oHolder( &hMutex );
+
+            if( oFileList.find(archiveFilename) != oFileList.end() )
+            {
+                bArchiveFileExists = true;
+            }
+        }
+
+        if( !bArchiveFileExists )
+        {
+            VSIStatBufL statBuf;
+            VSIFilesystemHandler *poFSHandler =
+                VSIFileManager::GetHandler( archiveFilename );
+            if( poFSHandler->Stat(
+                    archiveFilename, &statBuf,
+                    VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
+                !VSI_ISDIR(statBuf.st_mode) )
+            {
+                bArchiveFileExists = true;
+            }
+        }
+
+        if( bArchiveFileExists )
+        {
+            if( IsEitherSlash(pszFilename[i + 1]) )
+            {
+                osFileInArchive = CompactFilename(pszFilename + i + 2);
+            }
+            else if( pszFilename[i+1] == '\0' )
+            {
+                osFileInArchive = "";
+            }
+            else
+            {
+                CPLFree(archiveFilename);
+                return NULL;
+            }
+
+            // Remove trailing slash.
+            if( !osFileInArchive.empty() )
+            {
+                const char lastC = osFileInArchive.back();
+                if( IsEitherSlash(lastC) )
+                    osFileInArchive.resize(osFileInArchive.size() - 1);
+            }
+
+            return archiveFilename;
+        }
+
+        CPLFree(archiveFilename);
         return NULL;
+    }
 
-    /* Allow natural chaining of VSI drivers without requiring double slash */
+    // Allow natural chaining of VSI drivers without requiring double slash.
 
     CPLString osDoubleVsi(GetPrefix());
     osDoubleVsi += "/vsi";
 
-    if (strncmp(pszFilename, osDoubleVsi.c_str(), osDoubleVsi.size()) == 0)
+    if( strncmp(pszFilename, osDoubleVsi.c_str(), osDoubleVsi.size()) == 0 )
         pszFilename += strlen(GetPrefix());
     else
         pszFilename += strlen(GetPrefix()) + 1;
 
-    while(pszFilename[i])
+    while( pszFilename[i] )
     {
-        std::vector<CPLString> oExtensions = GetExtensions();
-        std::vector<CPLString>::const_iterator iter;
+        const std::vector<CPLString> oExtensions = GetExtensions();
         int nToSkip = 0;
 
-        for( iter = oExtensions.begin(); iter != oExtensions.end(); ++iter )
+        for( std::vector<CPLString>::const_iterator iter = oExtensions.begin();
+             iter != oExtensions.end();
+             ++iter )
         {
             const CPLString& osExtension = *iter;
-            if (EQUALN(pszFilename + i, osExtension.c_str(), strlen(osExtension.c_str())))
+            if( EQUALN(pszFilename + i,
+                       osExtension.c_str(),
+                       osExtension.size()) )
             {
-                nToSkip = static_cast<int>(strlen(osExtension.c_str()));
+                nToSkip = static_cast<int>(osExtension.size());
                 break;
             }
         }
 
 #ifdef DEBUG
-        /* For AFL, so that .cur_input is detected as the archive filename */
+        // For AFL, so that .cur_input is detected as the archive filename.
         if( EQUALN( pszFilename + i, ".cur_input", strlen(".cur_input") ) )
         {
             nToSkip = static_cast<int>(strlen(".cur_input"));
         }
 #endif
 
-        if (nToSkip != 0)
+        if( nToSkip != 0 )
         {
             VSIStatBufL statBuf;
             char* archiveFilename = CPLStrdup(pszFilename);
             bool bArchiveFileExists = false;
 
-            if (archiveFilename[i + nToSkip] == '/' ||
-                archiveFilename[i + nToSkip] == '\\')
+            if( IsEitherSlash(archiveFilename[i + nToSkip]) )
             {
                 archiveFilename[i + nToSkip] = 0;
             }
 
-            if (!bCheckMainFileExists)
+            if( !bCheckMainFileExists )
             {
                 bArchiveFileExists = true;
             }
@@ -331,60 +503,43 @@ char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
             {
                 CPLMutexHolder oHolder( &hMutex );
 
-                if (oFileList.find(archiveFilename) != oFileList.end() )
+                if( oFileList.find(archiveFilename) != oFileList.end() )
                 {
                     bArchiveFileExists = true;
                 }
             }
 
-            if (!bArchiveFileExists)
+            if( !bArchiveFileExists )
             {
                 VSIFilesystemHandler *poFSHandler =
                     VSIFileManager::GetHandler( archiveFilename );
-                if (poFSHandler->Stat(archiveFilename, &statBuf,
-                                      VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
+                if( poFSHandler->Stat(
+                        archiveFilename, &statBuf,
+                        VSI_STAT_EXISTS_FLAG | VSI_STAT_NATURE_FLAG) == 0 &&
                     !VSI_ISDIR(statBuf.st_mode))
                 {
                     bArchiveFileExists = true;
                 }
             }
 
-            if (bArchiveFileExists)
+            if( bArchiveFileExists )
             {
-                if (pszFilename[i + nToSkip] == '/' ||
-                    pszFilename[i + nToSkip] == '\\')
+                if( IsEitherSlash(pszFilename[i + nToSkip]) )
                 {
-                    char* pszArchiveInFileName = CPLStrdup(pszFilename + i + nToSkip + 1);
-
-                    /* Replace a/../b by b and foo/a/../b by foo/b */
-                    while(true)
-                    {
-                        char* pszPrevDir = strstr(pszArchiveInFileName, "/../");
-                        if (pszPrevDir == NULL || pszPrevDir == pszArchiveInFileName)
-                            break;
-
-                        char* pszPrevSlash = pszPrevDir - 1;
-                        while(pszPrevSlash != pszArchiveInFileName &&
-                                *pszPrevSlash != '/')
-                            pszPrevSlash --;
-                        if (pszPrevSlash == pszArchiveInFileName)
-                            memmove(pszArchiveInFileName, pszPrevDir + nToSkip, strlen(pszPrevDir + nToSkip) + 1);
-                        else
-                            memmove(pszPrevSlash + 1, pszPrevDir + nToSkip, strlen(pszPrevDir + nToSkip) + 1);
-                    }
-
-                    osFileInArchive = pszArchiveInFileName;
-                    CPLFree(pszArchiveInFileName);
+                    osFileInArchive =
+                        CompactFilename(pszFilename + i + nToSkip + 1);
                 }
                 else
+                {
                     osFileInArchive = "";
+                }
 
-                /* Remove trailing slash */
-                if (osFileInArchive.size())
+                // Remove trailing slash.
+                if( !osFileInArchive.empty() )
                 {
-                    char lastC = osFileInArchive[strlen(osFileInArchive) - 1];
-                    if (lastC == '\\' || lastC == '/')
-                        osFileInArchive.resize(strlen(osFileInArchive) - 1);
+                    const char lastC = osFileInArchive.back();
+                    if( IsEitherSlash(lastC) )
+                        osFileInArchive.resize(osFileInArchive.size() - 1);
                 }
 
                 return archiveFilename;
@@ -400,48 +555,52 @@ char* VSIArchiveFilesystemHandler::SplitFilename(const char *pszFilename,
 /*                           OpenArchiveFile()                          */
 /************************************************************************/
 
-VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archiveFilename,
-                                                               const char* fileInArchiveName)
+VSIArchiveReader *
+VSIArchiveFilesystemHandler::OpenArchiveFile( const char* archiveFilename,
+                                              const char* fileInArchiveName )
 {
     VSIArchiveReader* poReader = CreateReader(archiveFilename);
 
-    if (poReader == NULL)
+    if( poReader == NULL )
     {
         return NULL;
     }
 
-    if (fileInArchiveName == NULL || strlen(fileInArchiveName) == 0)
+    if( fileInArchiveName == NULL || strlen(fileInArchiveName) == 0 )
     {
-        if (poReader->GotoFirstFile() == FALSE)
+        if( poReader->GotoFirstFile() == FALSE )
         {
             delete(poReader);
             return NULL;
         }
 
-        /* Skip optional leading subdir */
-        CPLString osFileName = poReader->GetFileName();
-        const char* fileName = osFileName.c_str();
-        if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
+        // Skip optional leading subdir.
+        const CPLString osFileName = poReader->GetFileName();
+        if( IsEitherSlash(osFileName.back()) )
         {
-            if (poReader->GotoNextFile() == FALSE)
+            if( poReader->GotoNextFile() == FALSE )
             {
                 delete(poReader);
                 return NULL;
             }
         }
 
-        if (poReader->GotoNextFile())
+        if( poReader->GotoNextFile() )
         {
             CPLString msg;
-            msg.Printf("Support only 1 file in archive file %s when no explicit in-archive filename is specified",
+            msg.Printf("Support only 1 file in archive file %s when "
+                       "no explicit in-archive filename is specified",
                        archiveFilename);
-            const VSIArchiveContent* content = GetContentOfArchive(archiveFilename, poReader);
-            if (content)
+            const VSIArchiveContent* content =
+                GetContentOfArchive(archiveFilename, poReader);
+            if( content )
             {
                 msg += "\nYou could try one of the following :\n";
                 for( int i=0; i < content->nEntries; i++ )
                 {
-                    msg += CPLString().Printf("  %s/%s/%s\n", GetPrefix(), archiveFilename, content->entries[i].fileName);
+                    msg += CPLString().Printf(
+                        "  %s/%s/%s\n", GetPrefix(),
+                        archiveFilename, content->entries[i].fileName);
                 }
             }
 
@@ -453,14 +612,50 @@ VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archi
     }
     else
     {
+        // Optimization: instead of iterating over all files which can be
+        // slow on .tar.gz files, try reading the first one first.
+        // This can help if it is really huge.
+        {
+            CPLMutexHolder oHolder( &hMutex );
+
+            if( oFileList.find(archiveFilename) == oFileList.end() )
+            {
+                if( poReader->GotoFirstFile() == FALSE )
+                {
+                    delete(poReader);
+                    return NULL;
+                }
+
+                const CPLString osFileName = poReader->GetFileName();
+                bool bIsDir = false;
+                const CPLString osStrippedFilename =
+                            GetStrippedFilename(osFileName, bIsDir);
+                if( !osStrippedFilename.empty() )
+                {
+                    const bool bMatch = strcmp(osStrippedFilename,
+                                               fileInArchiveName) == 0;
+                    if( bMatch )
+                    {
+                        if( bIsDir )
+                        {
+                            delete(poReader);
+                            return NULL;
+                        }
+                        return poReader;
+                    }
+                }
+            }
+        }
+
         const VSIArchiveEntry* archiveEntry = NULL;
-        if (FindFileInArchive(archiveFilename, fileInArchiveName, &archiveEntry) == FALSE ||
-            archiveEntry->bIsDir)
+        if( FindFileInArchive(archiveFilename, fileInArchiveName,
+                              &archiveEntry) == FALSE ||
+            archiveEntry->bIsDir )
         {
             delete(poReader);
             return NULL;
         }
-        if (!poReader->GotoFileOffset(archiveEntry->file_pos))
+        if( !poReader->GotoFileOffset(archiveEntry->file_pos) )
         {
             delete poReader;
             return NULL;
@@ -475,29 +670,30 @@ VSIArchiveReader* VSIArchiveFilesystemHandler::OpenArchiveFile(const char* archi
 
 int VSIArchiveFilesystemHandler::Stat( const char *pszFilename,
                                        VSIStatBufL *pStatBuf,
-                                       CPL_UNUSED int nFlags )
+                                       int /* nFlags */ )
 {
-    int ret = -1;
-    CPLString osFileInArchive;
-
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
 
+    CPLString osFileInArchive;
     char* archiveFilename = SplitFilename(pszFilename, osFileInArchive, TRUE);
-    if (archiveFilename == NULL)
+    if( archiveFilename == NULL )
         return -1;
 
-    if (strlen(osFileInArchive) != 0)
+    int ret = -1;
+    if( !osFileInArchive.empty() )
     {
-        if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Looking for %s %s\n",
-                                    archiveFilename, osFileInArchive.c_str());
+#ifdef DEBUG_VERBOSE
+        CPLDebug("VSIArchive", "Looking for %s %s",
+                 archiveFilename, osFileInArchive.c_str());
+#endif
 
         const VSIArchiveEntry* archiveEntry = NULL;
-        if (FindFileInArchive(archiveFilename, osFileInArchive, &archiveEntry))
+        if( FindFileInArchive(archiveFilename, osFileInArchive, &archiveEntry) )
         {
-            /* Patching st_size with uncompressed file size */
+            // Patching st_size with uncompressed file size.
             pStatBuf->st_size = archiveEntry->uncompressed_size;
             pStatBuf->st_mtime = (time_t)archiveEntry->nModifiedTime;
-            if (archiveEntry->bIsDir)
+            if( archiveEntry->bIsDir )
                 pStatBuf->st_mode = S_IFDIR;
             else
                 pStatBuf->st_mode = S_IFREG;
@@ -510,29 +706,28 @@ int VSIArchiveFilesystemHandler::Stat( const char *pszFilename,
         CPLFree(archiveFilename);
         archiveFilename = NULL;
 
-        if (poReader != NULL && poReader->GotoFirstFile())
+        if( poReader != NULL && poReader->GotoFirstFile() )
         {
-            /* Skip optional leading subdir */
-            CPLString osFileName = poReader->GetFileName();
-            const char* fileName = osFileName.c_str();
-            if (fileName[strlen(fileName)-1] == '/' || fileName[strlen(fileName)-1] == '\\')
+            // Skip optional leading subdir.
+            const CPLString osFileName = poReader->GetFileName();
+            if( IsEitherSlash(osFileName.back()) )
             {
-                if (poReader->GotoNextFile() == FALSE)
+                if( poReader->GotoNextFile() == FALSE )
                 {
                     delete(poReader);
                     return -1;
                 }
             }
 
-            if (poReader->GotoNextFile())
+            if( poReader->GotoNextFile() )
             {
-                /* Several files in archive --> treat as dir */
+                // Several files in archive --> treat as dir.
                 pStatBuf->st_size = 0;
                 pStatBuf->st_mode = S_IFDIR;
             }
             else
             {
-                /* Patching st_size with uncompressed file size */
+                // Patching st_size with uncompressed file size.
                 pStatBuf->st_size = poReader->GetFileSize();
                 pStatBuf->st_mtime = (time_t)poReader->GetModifiedTime();
                 pStatBuf->st_mode = S_IFREG;
@@ -552,7 +747,7 @@ int VSIArchiveFilesystemHandler::Stat( const char *pszFilename,
 /*                              Unlink()                                */
 /************************************************************************/
 
-int VSIArchiveFilesystemHandler::Unlink( CPL_UNUSED const char *pszFilename )
+int VSIArchiveFilesystemHandler::Unlink( const char * /* pszFilename */ )
 {
     return -1;
 }
@@ -561,8 +756,8 @@ int VSIArchiveFilesystemHandler::Unlink( CPL_UNUSED const char *pszFilename )
 /*                             Rename()                                 */
 /************************************************************************/
 
-int VSIArchiveFilesystemHandler::Rename( CPL_UNUSED const char *oldpath,
-                                         CPL_UNUSED const char *newpath )
+int VSIArchiveFilesystemHandler::Rename( const char * /* oldpath */,
+                                         const char * /* newpath */ )
 {
     return -1;
 }
@@ -571,8 +766,8 @@ int VSIArchiveFilesystemHandler::Rename( CPL_UNUSED const char *oldpath,
 /*                             Mkdir()                                  */
 /************************************************************************/
 
-int VSIArchiveFilesystemHandler::Mkdir( CPL_UNUSED const char *pszDirname,
-                                        CPL_UNUSED long nMode )
+int VSIArchiveFilesystemHandler::Mkdir( const char * /* pszDirname */,
+                                        long /* nMode */ )
 {
     return -1;
 }
@@ -581,7 +776,7 @@ int VSIArchiveFilesystemHandler::Mkdir( CPL_UNUSED const char *pszDirname,
 /*                             Rmdir()                                  */
 /************************************************************************/
 
-int VSIArchiveFilesystemHandler::Rmdir( CPL_UNUSED const char *pszDirname )
+int VSIArchiveFilesystemHandler::Rmdir( const char * /* pszDirname */ )
 {
     return -1;
 }
@@ -595,51 +790,59 @@ char** VSIArchiveFilesystemHandler::ReadDirEx( const char *pszDirname,
 {
     CPLString osInArchiveSubDir;
     char* archiveFilename = SplitFilename(pszDirname, osInArchiveSubDir, TRUE);
-    if (archiveFilename == NULL)
+    if( archiveFilename == NULL )
         return NULL;
-    int lenInArchiveSubDir = static_cast<int>(strlen(osInArchiveSubDir));
+
+    const int lenInArchiveSubDir = static_cast<int>(osInArchiveSubDir.size());
 
     CPLStringList oDir;
 
     const VSIArchiveContent* content = GetContentOfArchive(archiveFilename);
-    if (!content)
+    if( !content )
     {
         CPLFree(archiveFilename);
         return NULL;
     }
 
-    if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Read dir %s", pszDirname);
-    for( int i=0; i < content->nEntries; i++ )
+#ifdef DEBUG_VERBOSE
+    CPLDebug("VSIArchive", "Read dir %s", pszDirname);
+#endif
+    for( int i = 0; i < content->nEntries; i++ )
     {
         const char* fileName = content->entries[i].fileName;
         /* Only list entries at the same level of inArchiveSubDir */
-        if (lenInArchiveSubDir != 0 &&
+        if( lenInArchiveSubDir != 0 &&
             strncmp(fileName, osInArchiveSubDir, lenInArchiveSubDir) == 0 &&
-            (fileName[lenInArchiveSubDir] == '/' || fileName[lenInArchiveSubDir] == '\\') &&
-            fileName[lenInArchiveSubDir + 1] != 0)
+            IsEitherSlash(fileName[lenInArchiveSubDir]) &&
+            fileName[lenInArchiveSubDir + 1] != 0 )
         {
             const char* slash = strchr(fileName + lenInArchiveSubDir + 1, '/');
-            if (slash == NULL)
+            if( slash == NULL )
                 slash = strchr(fileName + lenInArchiveSubDir + 1, '\\');
-            if (slash == NULL || slash[1] == 0)
+            if( slash == NULL || slash[1] == 0 )
             {
                 char* tmpFileName = CPLStrdup(fileName);
-                if (slash != NULL)
+                if( slash != NULL )
                 {
                     tmpFileName[strlen(tmpFileName)-1] = 0;
                 }
-                if (ENABLE_DEBUG)
-                    CPLDebug("VSIArchive", "Add %s as in directory %s\n",
-                            tmpFileName + lenInArchiveSubDir + 1, pszDirname);
+#ifdef DEBUG_VERBOSE
+                CPLDebug("VSIArchive", "Add %s as in directory %s",
+                         tmpFileName + lenInArchiveSubDir + 1, pszDirname);
+#endif
                 oDir.AddString(tmpFileName + lenInArchiveSubDir + 1);
                 CPLFree(tmpFileName);
             }
         }
-        else if (lenInArchiveSubDir == 0 &&
-                 strchr(fileName, '/') == NULL && strchr(fileName, '\\') == NULL)
+        else if( lenInArchiveSubDir == 0 &&
+                 strchr(fileName, '/') == NULL &&
+                 strchr(fileName, '\\') == NULL )
         {
-            /* Only list toplevel files and directories */
-            if (ENABLE_DEBUG) CPLDebug("VSIArchive", "Add %s as in directory %s\n", fileName, pszDirname);
+            // Only list toplevel files and directories.
+#ifdef DEBUG_VERBOSE
+            CPLDebug("VSIArchive", "Add %s as in directory %s",
+                     fileName, pszDirname);
+#endif
             oDir.AddString(fileName);
         }
 
@@ -650,3 +853,5 @@ char** VSIArchiveFilesystemHandler::ReadDirEx( const char *pszDirname,
     CPLFree(archiveFilename);
     return oDir.StealList();
 }
+
+//! @endcond
diff --git a/port/cpl_vsil_buffered_reader.cpp b/port/cpl_vsil_buffered_reader.cpp
index 35ba4dd..71c1e61 100644
--- a/port/cpl_vsil_buffered_reader.cpp
+++ b/port/cpl_vsil_buffered_reader.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil_buffered_reader.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of buffered reader IO functions.
@@ -27,19 +26,33 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-/* The intent of this class is to be a wrapper around an underlying virtual */
-/* handle and add very basic caching of last read bytes, so that a backward */
-/* seek of a few bytes doesn't require a seek on the underlying virtual handle. */
-/* This enable us to improve dramatically the performance of CPLReadLine2L() on */
-/* a gzip file */
+//! @cond Doxygen_Suppress
 
-#include "cpl_vsi_virtual.h"
+// The intent of this class is to be a wrapper around an underlying virtual
+// handle and add very basic caching of last read bytes, so that a backward
+// seek of a few bytes doesn't require a seek on the underlying virtual handle.
+// This enable us to improve dramatically the performance of CPLReadLine2L() on
+// a gzip file.
 
 #include "cpl_port.h"
+#include "cpl_vsi_virtual.h"
+
+#include <cstddef>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
+#include <vector>
 
-#define MAX_BUFFER_SIZE 65536
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_vsil_buffered_reader.cpp 33646 2016-03-05 15:54:03Z goatbar $");
+static const int MAX_BUFFER_SIZE = 65536;
+
+CPL_CVSID("$Id: cpl_vsil_buffered_reader.cpp 36848 2016-12-13 14:31:42Z goatbar $");
 
 class VSIBufferedReaderHandle CPL_FINAL : public VSIVirtualHandle
 {
@@ -48,76 +61,87 @@ class VSIBufferedReaderHandle CPL_FINAL : public VSIVirtualHandle
     GUIntBig          nBufferOffset;
     int               nBufferSize;
     GUIntBig          nCurOffset;
-    int               bNeedBaseHandleSeek;
-    int               bEOF;
+    bool              bNeedBaseHandleSeek;
+    bool              bEOF;
     vsi_l_offset      nCheatFileSize;
 
-    int               SeekBaseTo(vsi_l_offset nTargetOffset);
+    int               SeekBaseTo( vsi_l_offset nTargetOffset );
 
   public:
-
-    VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle);
-    VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
-                            const GByte* pabyBeginningContent,
-                            vsi_l_offset nCheatFileSizeIn);
-    ~VSIBufferedReaderHandle();
-
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Flush();
-    virtual int       Close();
+    explicit VSIBufferedReaderHandle( VSIVirtualHandle* poBaseHandle );
+    VSIBufferedReaderHandle( VSIVirtualHandle* poBaseHandle,
+                             const GByte* pabyBeginningContent,
+                             vsi_l_offset nCheatFileSizeIn );
+    // TODO(schwehr): Add override when support dropped for VS2008.
+    virtual ~VSIBufferedReaderHandle();
+
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize,
+                            size_t nMemb ) override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize,
+                             size_t nMemb ) override;
+    virtual int       Eof() override;
+    virtual int       Flush() override;
+    virtual int       Close() override;
 };
 
+//! @endcond
+
 /************************************************************************/
 /*                    VSICreateBufferedReaderHandle()                   */
 /************************************************************************/
 
-VSIVirtualHandle* VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle)
+VSIVirtualHandle *
+VSICreateBufferedReaderHandle( VSIVirtualHandle* poBaseHandle )
 {
     return new VSIBufferedReaderHandle(poBaseHandle);
 }
 
-VSIVirtualHandle* VSICreateBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
-                                                const GByte* pabyBeginningContent,
-                                                vsi_l_offset nCheatFileSizeIn)
+VSIVirtualHandle* VSICreateBufferedReaderHandle(
+    VSIVirtualHandle* poBaseHandle,
+    const GByte* pabyBeginningContent,
+    vsi_l_offset nCheatFileSizeIn )
 {
     return new VSIBufferedReaderHandle(poBaseHandle,
                                        pabyBeginningContent,
                                        nCheatFileSizeIn);
 }
 
+//! @cond Doxygen_Suppress
+
 /************************************************************************/
 /*                        VSIBufferedReaderHandle()                     */
 /************************************************************************/
 
-VSIBufferedReaderHandle::VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle)
-{
-    m_poBaseHandle = poBaseHandle;
-    pabyBuffer = (GByte*)CPLMalloc(MAX_BUFFER_SIZE);
-    nBufferOffset = 0;
-    nBufferSize = 0;
-    nCurOffset = 0;
-    bNeedBaseHandleSeek = FALSE;
-    bEOF = FALSE;
-    nCheatFileSize = 0;
-}
-
-VSIBufferedReaderHandle::VSIBufferedReaderHandle(VSIVirtualHandle* poBaseHandle,
-                                                 const GByte* pabyBeginningContent,
-                                                 vsi_l_offset nCheatFileSizeIn)
+VSIBufferedReaderHandle::VSIBufferedReaderHandle(
+    VSIVirtualHandle* poBaseHandle) :
+    m_poBaseHandle(poBaseHandle),
+    pabyBuffer(static_cast<GByte*>(CPLMalloc(MAX_BUFFER_SIZE))),
+    nBufferOffset(0),
+    nBufferSize(0),
+    nCurOffset(0),
+    bNeedBaseHandleSeek(false),
+    bEOF(false),
+    nCheatFileSize(0)
+{}
+
+VSIBufferedReaderHandle::VSIBufferedReaderHandle(
+    VSIVirtualHandle* poBaseHandle,
+    const GByte* pabyBeginningContent,
+    vsi_l_offset nCheatFileSizeIn ) :
+    m_poBaseHandle(poBaseHandle),
+    pabyBuffer(static_cast<GByte *>(
+        CPLMalloc(std::max(MAX_BUFFER_SIZE,
+                           static_cast<int>(poBaseHandle->Tell()))))),
+    nBufferOffset(0),
+    nBufferSize(static_cast<int>(poBaseHandle->Tell())),
+    nCurOffset(0),
+    bNeedBaseHandleSeek(true),
+    bEOF(false),
+    nCheatFileSize(nCheatFileSizeIn)
 {
-    m_poBaseHandle = poBaseHandle;
-    nBufferOffset = 0;
-    nBufferSize = (int)poBaseHandle->Tell();
-    pabyBuffer = (GByte*)CPLMalloc(MAX(MAX_BUFFER_SIZE,nBufferSize));
     memcpy(pabyBuffer, pabyBeginningContent, nBufferSize);
-    nCurOffset = 0;
-    bNeedBaseHandleSeek = TRUE;
-    bEOF = FALSE;
-    nCheatFileSize = nCheatFileSizeIn;
 }
 
 /************************************************************************/
@@ -136,23 +160,32 @@ VSIBufferedReaderHandle::~VSIBufferedReaderHandle()
 
 int VSIBufferedReaderHandle::Seek( vsi_l_offset nOffset, int nWhence )
 {
-    //CPLDebug( "BUFFERED", "Seek(%d,%d)", (int)nOffset, (int)nWhence);
-    bEOF = FALSE;
-    if (nWhence == SEEK_CUR)
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "BUFFERED", "Seek(%d,%d)",
+              static_cast<int>(nOffset), static_cast<int>(nWhence) );
+#endif
+    bEOF = false;
+    if( nWhence == SEEK_CUR )
+    {
         nCurOffset += nOffset;
-    else if (nWhence == SEEK_END)
+    }
+    else if( nWhence == SEEK_END )
     {
         if( nCheatFileSize )
+        {
             nCurOffset = nCheatFileSize;
+        }
         else
         {
             m_poBaseHandle->Seek(nOffset, nWhence);
             nCurOffset = m_poBaseHandle->Tell();
-            bNeedBaseHandleSeek = TRUE;
+            bNeedBaseHandleSeek = true;
         }
     }
     else
+    {
         nCurOffset = nOffset;
+    }
 
     return 0;
 }
@@ -163,7 +196,9 @@ int VSIBufferedReaderHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
 vsi_l_offset VSIBufferedReaderHandle::Tell()
 {
-    //CPLDebug( "BUFFERED", "Tell() = %d", (int)nCurOffset);
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "BUFFERED", "Tell() = %d", static_cast<int>(nCurOffset));
+#endif
     return nCurOffset;
 }
 
@@ -171,7 +206,7 @@ vsi_l_offset VSIBufferedReaderHandle::Tell()
 /*                           SeekBaseTo()                               */
 /************************************************************************/
 
-int VSIBufferedReaderHandle::SeekBaseTo(vsi_l_offset nTargetOffset)
+int VSIBufferedReaderHandle::SeekBaseTo( vsi_l_offset nTargetOffset )
 {
     if( m_poBaseHandle->Seek(nTargetOffset, SEEK_SET) == 0 )
         return TRUE;
@@ -179,19 +214,26 @@ int VSIBufferedReaderHandle::SeekBaseTo(vsi_l_offset nTargetOffset)
     nCurOffset = m_poBaseHandle->Tell();
     if( nCurOffset > nTargetOffset )
         return FALSE;
-    char abyTemp[8192];
+
+    const vsi_l_offset nMaxOffset = 8192;
+
+    std::vector<char> oTemp(nMaxOffset, 0);
+    char *pabyTemp = &oTemp[0];
+
     while( true )
     {
-        int nToRead = (int) MIN(8192, nTargetOffset - nCurOffset);
-        int nRead = (int)m_poBaseHandle->Read(abyTemp, 1, nToRead );
+        const size_t nToRead = static_cast<size_t>(
+            std::min(nMaxOffset, nTargetOffset - nCurOffset));
+        const size_t nRead = m_poBaseHandle->Read(pabyTemp, 1, nToRead);
+
         nCurOffset += nRead;
 
-        if (nRead < nToRead)
+        if( nRead < nToRead )
         {
-            bEOF = TRUE;
+            bEOF = true;
             return FALSE;
         }
-        if (nToRead < 8192)
+        if( nToRead < nMaxOffset )
             break;
     }
     return TRUE;
@@ -201,26 +243,34 @@ int VSIBufferedReaderHandle::SeekBaseTo(vsi_l_offset nTargetOffset)
 /*                               Read()                                 */
 /************************************************************************/
 
-size_t VSIBufferedReaderHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
+size_t VSIBufferedReaderHandle::Read( void *pBuffer, size_t nSize,
+                                      size_t nMemb )
 {
     const size_t nTotalToRead = nSize * nMemb;
-    //CPLDebug( "BUFFERED", "Read(%d)", (int)nTotalToRead);
+#ifdef DEBUG_VERBOSE
+    CPLDebug( "BUFFERED", "Read(%d)", static_cast<int>(nTotalToRead));
+#endif
 
-    if (nSize == 0)
+    if( nSize == 0 )
         return 0;
 
-    if (nBufferSize != 0 &&
-        nCurOffset >= nBufferOffset && nCurOffset <= nBufferOffset + nBufferSize)
+    if( nBufferSize != 0 &&
+        nCurOffset >= nBufferOffset &&
+        nCurOffset <= nBufferOffset + nBufferSize )
     {
-        /* We try to read from an offset located within the buffer */
-        const size_t nReadInBuffer = static_cast<size_t>( MIN(nTotalToRead, nBufferOffset + nBufferSize - nCurOffset) );
+        // We try to read from an offset located within the buffer.
+        const size_t nReadInBuffer =
+            static_cast<size_t>(
+                std::min(nTotalToRead,
+                         static_cast<size_t>(nBufferOffset + nBufferSize -
+                                             nCurOffset)));
         memcpy(pBuffer, pabyBuffer + nCurOffset - nBufferOffset, nReadInBuffer);
         const size_t nToReadInFile = nTotalToRead - nReadInBuffer;
-        if (nToReadInFile > 0)
+        if( nToReadInFile > 0 )
         {
-            /* The beginning of the data to read is located in the buffer */
-            /* but the end must be read from the file */
-            if (bNeedBaseHandleSeek)
+            // The beginning of the data to read is located in the buffer
+            // but the end must be read from the file.
+            if( bNeedBaseHandleSeek )
             {
                 if( !SeekBaseTo(nBufferOffset + nBufferSize) )
                 {
@@ -228,67 +278,82 @@ size_t VSIBufferedReaderHandle::Read( void *pBuffer, size_t nSize, size_t nMemb
                     return nReadInBuffer / nSize;
                 }
             }
-            bNeedBaseHandleSeek = FALSE;
-            //CPLAssert(m_poBaseHandle->Tell() == nBufferOffset + nBufferSize);
-
-            const size_t nReadInFile = m_poBaseHandle->Read((GByte*)pBuffer + nReadInBuffer, 1, nToReadInFile);
+            bNeedBaseHandleSeek = false;
+#ifdef DEBUG_VERBOSE
+            CPLAssert(m_poBaseHandle->Tell() == nBufferOffset + nBufferSize);
+#endif
+
+            const size_t nReadInFile =
+                m_poBaseHandle->Read(
+                    static_cast<GByte *>(pBuffer) + nReadInBuffer,
+                    1, nToReadInFile);
             const size_t nRead = nReadInBuffer + nReadInFile;
 
-            nBufferSize = static_cast<int>( MIN(nRead, MAX_BUFFER_SIZE) );
+            nBufferSize = static_cast<int>(
+                std::min(nRead, static_cast<size_t>(MAX_BUFFER_SIZE)));
             nBufferOffset = nCurOffset + nRead - nBufferSize;
-            memcpy(pabyBuffer, (GByte*)pBuffer + nRead - nBufferSize, nBufferSize);
+            memcpy(pabyBuffer,
+                   static_cast<GByte *>(pBuffer) + nRead - nBufferSize,
+                   nBufferSize);
 
             nCurOffset += nRead;
-            //CPLAssert(m_poBaseHandle->Tell() == nBufferOffset + nBufferSize);
-            //CPLAssert(m_poBaseHandle->Tell() == nCurOffset);
+#ifdef DEBUG_VERBOSE
+            CPLAssert(m_poBaseHandle->Tell() == nBufferOffset + nBufferSize);
+            CPLAssert(m_poBaseHandle->Tell() == nCurOffset);
+#endif
 
-            bEOF = m_poBaseHandle->Eof();
+            bEOF = CPL_TO_BOOL(m_poBaseHandle->Eof());
 
             return nRead / nSize;
         }
         else
         {
-            /* The data to read is completely located within the buffer */
+            // The data to read is completely located within the buffer.
             nCurOffset += nTotalToRead;
             return nTotalToRead / nSize;
         }
     }
     else
     {
-        /* We try either to read before or after the buffer, so a seek is necessary */
+        // We try either to read before or after the buffer, so a seek is
+        // necessary.
         if( !SeekBaseTo(nCurOffset) )
             return 0;
-        bNeedBaseHandleSeek = FALSE;
-        const size_t nReadInFile = m_poBaseHandle->Read(pBuffer, 1, nTotalToRead);
-        nBufferSize = static_cast<int>( MIN(nReadInFile, MAX_BUFFER_SIZE) );
+        bNeedBaseHandleSeek = false;
+        const size_t nReadInFile =
+            m_poBaseHandle->Read(pBuffer, 1, nTotalToRead);
+        nBufferSize = static_cast<int>(
+            std::min(nReadInFile, static_cast<size_t>(MAX_BUFFER_SIZE)));
         nBufferOffset = nCurOffset + nReadInFile - nBufferSize;
-        memcpy(pabyBuffer, (GByte*)pBuffer + nReadInFile - nBufferSize, nBufferSize);
+        memcpy(pabyBuffer,
+               static_cast<GByte *>(pBuffer) + nReadInFile - nBufferSize,
+               nBufferSize);
 
         nCurOffset += nReadInFile;
-        //CPLAssert(m_poBaseHandle->Tell() == nBufferOffset + nBufferSize);
-        //CPLAssert(m_poBaseHandle->Tell() == nCurOffset);
+#ifdef DEBUG_VERBOSE
+        CPLAssert(m_poBaseHandle->Tell() == nBufferOffset + nBufferSize);
+        CPLAssert(m_poBaseHandle->Tell() == nCurOffset);
+#endif
 
-        bEOF = m_poBaseHandle->Eof();
+        bEOF = CPL_TO_BOOL(m_poBaseHandle->Eof());
 
         return nReadInFile / nSize;
     }
-
 }
 
 /************************************************************************/
 /*                              Write()                                 */
 /************************************************************************/
 
-size_t VSIBufferedReaderHandle::Write( CPL_UNUSED const void *pBuffer,
-                                       CPL_UNUSED size_t nSize,
-                                       CPL_UNUSED size_t nMemb )
+size_t VSIBufferedReaderHandle::Write( const void * /* pBuffer */,
+                                       size_t /* nSize */,
+                                       size_t /* nMemb */)
 {
     CPLError(CE_Failure, CPLE_NotSupported,
-             "VSIFWriteL is not supported on buffer reader streams\n");
+             "VSIFWriteL is not supported on buffer reader streams");
     return 0;
 }
 
-
 /************************************************************************/
 /*                               Eof()                                  */
 /************************************************************************/
@@ -313,7 +378,7 @@ int VSIBufferedReaderHandle::Flush()
 
 int VSIBufferedReaderHandle::Close()
 {
-    if (m_poBaseHandle)
+    if( m_poBaseHandle )
     {
         m_poBaseHandle->Close();
         delete m_poBaseHandle;
@@ -321,3 +386,5 @@ int VSIBufferedReaderHandle::Close()
     }
     return 0;
 }
+
+//! @endcond
diff --git a/port/cpl_vsil_cache.cpp b/port/cpl_vsil_cache.cpp
index 16161f6..3c65014 100644
--- a/port/cpl_vsil_cache.cpp
+++ b/port/cpl_vsil_cache.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id$
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of caching IO layer.
@@ -28,10 +27,27 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_vsi_virtual.h"
+
+#include <cstddef>
+#include <cstring>
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <algorithm>
 #include <map>
+#include <utility>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+#include "cpl_vsi_virtual.h"
+
+//! @cond Doxygen_Suppress
 
-CPL_CVSID("$Id$");
+CPL_CVSID("$Id: cpl_vsil_cache.cpp 36772 2016-12-10 06:29:22Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -43,13 +59,13 @@ class VSICacheChunk
 {
 public:
   VSICacheChunk() :
-      bDirty(FALSE),
+      bDirty(false),
       iBlock(0),
       poLRUPrev(NULL),
       poLRUNext(NULL),
       nDataFilled(0),
       pabyData(NULL)
-    { }
+    {}
 
     virtual ~VSICacheChunk()
     {
@@ -59,11 +75,11 @@ public:
     bool Allocate( size_t nChunkSize )
     {
         CPLAssert( pabyData == NULL );
-        pabyData = (GByte *)VSIMalloc( nChunkSize );
+        pabyData = static_cast<GByte *>(VSIMalloc( nChunkSize ));
         return (pabyData != NULL);
     }
 
-    int            bDirty;
+    bool           bDirty;  // TODO(schwehr): Not used?  Added in r22564.
     vsi_l_offset   iBlock;
 
     VSICacheChunk *poLRUPrev;
@@ -85,7 +101,7 @@ class VSICachedFile CPL_FINAL : public VSIVirtualHandle
     VSICachedFile( VSIVirtualHandle *poBaseHandle,
                    size_t nChunkSize,
                    size_t nCacheSize );
-    ~VSICachedFile() { Close(); }
+    virtual ~VSICachedFile() { Close(); }
 
     void          FlushLRU();
     int           LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
@@ -107,43 +123,44 @@ class VSICachedFile CPL_FINAL : public VSIVirtualHandle
 
     std::map<vsi_l_offset, VSICacheChunk*> oMapOffsetToCache;
 
-    int            bEOF;
-
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Flush();
-    virtual int       Close();
-    virtual void     *GetNativeFileDescriptor() { return poBase->GetNativeFileDescriptor(); }
+    bool           bEOF;
+
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize,
+                            size_t nMemb ) override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize,
+                             size_t nMemb ) override;
+    virtual int       Eof() override;
+    virtual int       Flush() override;
+    virtual int       Close() override;
+    virtual void     *GetNativeFileDescriptor() override
+        { return poBase->GetNativeFileDescriptor(); }
 };
 
 /************************************************************************/
 /*                           VSICachedFile()                            */
 /************************************************************************/
 
-VSICachedFile::VSICachedFile( VSIVirtualHandle *poBaseHandle, size_t nChunkSize, size_t nCacheSize )
-
+VSICachedFile::VSICachedFile( VSIVirtualHandle *poBaseHandle, size_t nChunkSize,
+                              size_t nCacheSize ) :
+    poBase(poBaseHandle),
+    nOffset(0),
+    nFileSize(0),  // Set below.
+    nCacheUsed(0),
+    nCacheMax(nCacheSize),
+    poLRUStart(NULL),
+    poLRUEnd(NULL),
+    bEOF(false)
 {
-    poBase = poBaseHandle;
     m_nChunkSize = nChunkSize;
 
-    nCacheUsed = 0;
-    if ( nCacheSize == 0 )
+    if( nCacheSize == 0 )
         nCacheMax = CPLScanUIntBig(
              CPLGetConfigOption( "VSI_CACHE_SIZE", "25000000" ), 40 );
-    else
-        nCacheMax = nCacheSize;
-
-    poLRUStart = NULL;
-    poLRUEnd = NULL;
 
     poBase->Seek( 0, SEEK_END );
     nFileSize = poBase->Tell();
-
-    nOffset = 0;
-    bEOF = FALSE;
 }
 
 /************************************************************************/
@@ -153,8 +170,10 @@ VSICachedFile::VSICachedFile( VSIVirtualHandle *poBaseHandle, size_t nChunkSize,
 int VSICachedFile::Close()
 
 {
-    for( std::map<vsi_l_offset, VSICacheChunk*>::iterator oIter = oMapOffsetToCache.begin();
-         oIter != oMapOffsetToCache.end(); ++oIter )
+    for( std::map<vsi_l_offset, VSICacheChunk*>::iterator oIter =
+             oMapOffsetToCache.begin();
+         oIter != oMapOffsetToCache.end();
+         ++oIter )
     {
         delete oIter->second;
     }
@@ -182,18 +201,16 @@ int VSICachedFile::Close()
 int VSICachedFile::Seek( vsi_l_offset nReqOffset, int nWhence )
 
 {
-    bEOF = FALSE;
+    bEOF = false;
 
     if( nWhence == SEEK_SET )
     {
-        // use offset directly.
+        // Use offset directly.
     }
-
     else if( nWhence == SEEK_CUR )
     {
         nReqOffset += nOffset;
     }
-
     else if( nWhence == SEEK_END )
     {
         nReqOffset += nFileSize;
@@ -254,7 +271,7 @@ void VSICachedFile::FlushLRU()
 void VSICachedFile::Demote( VSICacheChunk *poBlock )
 
 {
-    // already at end?
+    // Already at end?
     if( poLRUEnd == poBlock )
         return;
 
@@ -272,6 +289,7 @@ void VSICachedFile::Demote( VSICacheChunk *poBlock )
 
     if( poLRUEnd != NULL )
         poLRUEnd->poLRUNext = poBlock;
+
     poLRUEnd = poBlock;
 
     if( poLRUStart == NULL )
@@ -283,6 +301,8 @@ void VSICachedFile::Demote( VSICacheChunk *poBlock )
 /*                                                                      */
 /*      Load the desired set of blocks.  Use pBuffer as a temporary     */
 /*      buffer if it would be helpful.                                  */
+/*                                                                      */
+/*  RETURNS: TRUE on success; FALSE on failure.                         */
 /************************************************************************/
 
 int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
@@ -290,7 +310,7 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
 
 {
     if( nBlockCount == 0 )
-        return 1;
+        return TRUE;
 
 /* -------------------------------------------------------------------- */
 /*      When we want to load only one block, we can directly load it    */
@@ -298,25 +318,27 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
 /* -------------------------------------------------------------------- */
     if( nBlockCount == 1 )
     {
-        poBase->Seek( (vsi_l_offset)nStartBlock * m_nChunkSize, SEEK_SET );
+        poBase->Seek( static_cast<vsi_l_offset>(nStartBlock) * m_nChunkSize,
+                      SEEK_SET );
 
         VSICacheChunk *poBlock = new VSICacheChunk();
-        if ( !poBlock || !poBlock->Allocate( m_nChunkSize ) )
+        if( !poBlock || !poBlock->Allocate( m_nChunkSize ) )
         {
             delete poBlock;
-            return 0;
+            return FALSE;
         }
 
         oMapOffsetToCache[nStartBlock] = poBlock;
 
         poBlock->iBlock = nStartBlock;
-        poBlock->nDataFilled = poBase->Read( poBlock->pabyData, 1, m_nChunkSize );
+        poBlock->nDataFilled =
+            poBase->Read( poBlock->pabyData, 1, m_nChunkSize );
         nCacheUsed += poBlock->nDataFilled;
 
         // Merges into the LRU list.
         Demote( poBlock );
 
-        return 1;
+        return TRUE;
     }
 
 /* -------------------------------------------------------------------- */
@@ -329,27 +351,30 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
         && nBufferSize < nBlockCount * m_nChunkSize )
     {
         if( !LoadBlocks( nStartBlock, 2, pBuffer, nBufferSize ) )
-            return 0;
+            return FALSE;
 
         return LoadBlocks( nStartBlock+2, nBlockCount-2, pBuffer, nBufferSize );
     }
 
-    if( poBase->Seek( (vsi_l_offset)nStartBlock * m_nChunkSize, SEEK_SET ) != 0 )
-        return 0;
+    if( poBase->Seek( static_cast<vsi_l_offset>(nStartBlock) * m_nChunkSize,
+                      SEEK_SET ) != 0 )
+        return FALSE;
 
 /* -------------------------------------------------------------------- */
 /*      Do we need to allocate our own buffer?                          */
 /* -------------------------------------------------------------------- */
-    GByte *pabyWorkBuffer = (GByte *) pBuffer;
+    GByte *pabyWorkBuffer = static_cast<GByte *>(pBuffer);
 
     if( nBufferSize < m_nChunkSize * nBlockCount )
-        pabyWorkBuffer = (GByte *) CPLMalloc(m_nChunkSize * nBlockCount);
+        pabyWorkBuffer =
+            static_cast<GByte *>( CPLMalloc(m_nChunkSize * nBlockCount) );
 
 /* -------------------------------------------------------------------- */
 /*      Read the whole request into the working buffer.                 */
 /* -------------------------------------------------------------------- */
 
-    size_t nDataRead = poBase->Read( pabyWorkBuffer, 1, nBlockCount*m_nChunkSize);
+    const size_t nDataRead =
+        poBase->Read( pabyWorkBuffer, 1, nBlockCount*m_nChunkSize);
 
     if( nBlockCount * m_nChunkSize > nDataRead + m_nChunkSize - 1 )
         nBlockCount = (nDataRead + m_nChunkSize - 1) / m_nChunkSize;
@@ -357,10 +382,10 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
     for( size_t i = 0; i < nBlockCount; i++ )
     {
         VSICacheChunk *poBlock = new VSICacheChunk();
-        if ( !poBlock || !poBlock->Allocate( m_nChunkSize ) )
+        if( !poBlock || !poBlock->Allocate( m_nChunkSize ) )
         {
             delete poBlock;
-            return 0;
+            return FALSE;
         }
 
         poBlock->iBlock = nStartBlock + i;
@@ -375,7 +400,7 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
             poBlock->nDataFilled = nDataRead - i*m_nChunkSize;
 
         memcpy( poBlock->pabyData, pabyWorkBuffer + i*m_nChunkSize,
-                (size_t) poBlock->nDataFilled );
+                static_cast<size_t>(poBlock->nDataFilled) );
 
         nCacheUsed += poBlock->nDataFilled;
 
@@ -386,7 +411,7 @@ int VSICachedFile::LoadBlocks( vsi_l_offset nStartBlock, size_t nBlockCount,
     if( pabyWorkBuffer != pBuffer )
         CPLFree( pabyWorkBuffer );
 
-    return 1;
+    return TRUE;
 }
 
 /************************************************************************/
@@ -398,15 +423,16 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
 {
     if( nOffset >= nFileSize )
     {
-        bEOF = TRUE;
+        bEOF = true;
         return 0;
     }
 
 /* ==================================================================== */
 /*      Make sure the cache is loaded for the whole request region.     */
 /* ==================================================================== */
-    vsi_l_offset nStartBlock = nOffset / m_nChunkSize;
-    vsi_l_offset nEndBlock = (nOffset + nSize * nCount - 1) / m_nChunkSize;
+    const vsi_l_offset nStartBlock = nOffset / m_nChunkSize;
+    const vsi_l_offset nEndBlock =
+        (nOffset + nSize * nCount - 1) / m_nChunkSize;
 
     for( vsi_l_offset iBlock = nStartBlock; iBlock <= nEndBlock; iBlock++ )
     {
@@ -428,22 +454,24 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
 
     while( nAmountCopied < nSize * nCount )
     {
-        vsi_l_offset iBlock = (nOffset + nAmountCopied) / m_nChunkSize;
-        VSICacheChunk *poBlock = oMapOffsetToCache[iBlock];
+        const vsi_l_offset iBlock = (nOffset + nAmountCopied) / m_nChunkSize;
+        VSICacheChunk * poBlock = oMapOffsetToCache[iBlock];
         if( poBlock == NULL )
         {
-            /* We can reach that point when the amount to read exceeds */
-            /* the cache size */
-            LoadBlocks( iBlock, 1, ((GByte *) pBuffer) + nAmountCopied,
-                        MIN(nSize * nCount - nAmountCopied, m_nChunkSize) );
+            // We can reach that point when the amount to read exceeds
+            // the cache size.
+            LoadBlocks(iBlock, 1,
+                       static_cast<GByte *>(pBuffer) + nAmountCopied,
+                       std::min(nSize * nCount - nAmountCopied, m_nChunkSize));
             poBlock = oMapOffsetToCache[iBlock];
             CPLAssert(poBlock != NULL);
         }
 
-        vsi_l_offset nStartOffset = (vsi_l_offset)iBlock * m_nChunkSize;
-        size_t nThisCopy = (size_t)
+        const vsi_l_offset nStartOffset =
+            static_cast<vsi_l_offset>(iBlock) * m_nChunkSize;
+        size_t nThisCopy = static_cast<size_t>(
             ((nStartOffset + poBlock->nDataFilled)
-             - nAmountCopied - nOffset);
+             - nAmountCopied - nOffset));
 
         if( nThisCopy > nSize * nCount - nAmountCopied )
             nThisCopy = nSize * nCount - nAmountCopied;
@@ -451,7 +479,7 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
         if( nThisCopy == 0 )
             break;
 
-        memcpy( ((GByte *) pBuffer) + nAmountCopied,
+        memcpy( static_cast<GByte *>(pBuffer) + nAmountCopied,
                 poBlock->pabyData
                 + (nOffset + nAmountCopied) - nStartOffset,
                 nThisCopy );
@@ -467,9 +495,9 @@ size_t VSICachedFile::Read( void * pBuffer, size_t nSize, size_t nCount )
     while( nCacheUsed > nCacheMax )
         FlushLRU();
 
-    size_t nRet = nAmountCopied / nSize;
-    if (nRet != nCount)
-        bEOF = TRUE;
+    const size_t nRet = nAmountCopied / nSize;
+    if( nRet != nCount )
+        bEOF = true;
     return nRet;
 }
 
@@ -504,12 +532,15 @@ int VSICachedFile::Flush()
     return 0;
 }
 
+//! @endcond
+
 /************************************************************************/
 /*                        VSICreateCachedFile()                         */
 /************************************************************************/
 
 VSIVirtualHandle *
-VSICreateCachedFile( VSIVirtualHandle *poBaseHandle, size_t nChunkSize, size_t nCacheSize )
+VSICreateCachedFile( VSIVirtualHandle *poBaseHandle,
+                     size_t nChunkSize, size_t nCacheSize )
 
 {
     return new VSICachedFile( poBaseHandle, nChunkSize, nCacheSize );
diff --git a/port/cpl_vsil_crypt.cpp b/port/cpl_vsil_crypt.cpp
index 926e4fd..32d3b2b 100644
--- a/port/cpl_vsil_crypt.cpp
+++ b/port/cpl_vsil_crypt.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_vsil_crypt.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for encrypted files.
@@ -28,22 +27,31 @@
  ****************************************************************************/
 
 #ifdef DEBUG_BOOL
-#undef DEBUG_BOOL
+#define DO_NOT_USE_DEBUG_BOOL
 #endif
 
+#include "cpl_port.h"
 #include "cpl_vsi_virtual.h"
 
+#include <cstddef>
+#include <algorithm>
+
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+
 CPL_C_START
-void CPL_DLL VSIInstallCryptFileHandler(void);
-void CPL_DLL VSISetCryptKey(const GByte* pabyKey, int nKeySize);
+void CPL_DLL VSIInstallCryptFileHandler();
+void CPL_DLL VSISetCryptKey( const GByte* pabyKey, int nKeySize );
 CPL_C_END
 
-CPL_CVSID("$Id: cpl_vsil_crypt.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_crypt.cpp 37003 2016-12-23 14:54:07Z goatbar $");
 
 static const char VSICRYPT_PREFIX[] = "/vsicrypt/";
 
 #if defined(HAVE_CRYPTOPP) || defined(DOXYGEN_SKIP)
 
+//! @cond Doxygen_Suppress
+
 /* Increase Major in case of backward incompatible changes */
 static const int VSICRYPT_CURRENT_MAJOR = 1;
 static const int VSICRYPT_CURRENT_MINOR = 0;
@@ -105,25 +113,26 @@ static CryptoPP::PNew s_pNew = NULL;
 static CryptoPP::PDelete s_pDelete = NULL;
 
 extern "C" __declspec(dllexport)
-void __cdecl SetNewAndDeleteFromCryptoPP(CryptoPP::PNew pNew,
-                                         CryptoPP::PDelete pDelete,
-                                         CryptoPP::PSetNewHandler pSetNewHandler)
+void __cdecl SetNewAndDeleteFromCryptoPP(
+    CryptoPP::PNew pNew,
+    CryptoPP::PDelete pDelete,
+    CryptoPP::PSetNewHandler pSetNewHandler )
 {
-	s_pNew = pNew;
-	s_pDelete = pDelete;
+    s_pNew = pNew;
+    s_pDelete = pDelete;
 }
 
-void * __cdecl operator new (size_t size)
+void * __cdecl operator new( vsize_t size )
 {
-	return s_pNew(size);
+    return s_pNew(size);
 }
 
-void __cdecl operator delete (void * p)
+void __cdecl operator delete( void * p )
 {
-	s_pDelete(p);
+    s_pDelete(p);
 }
 
-#endif //  defined(WIN32) && defined(USE_ONLY_CRYPTODLL_ALG)
+#endif  // defined(WIN32) && defined(USE_ONLY_CRYPTODLL_ALG)
 
 static GByte* pabyGlobalKey = NULL;
 static int nGlobalKeySize = 0;
@@ -133,26 +142,26 @@ typedef enum
     ALG_AES,
     ALG_Blowfish,
     ALG_Camellia,
-    //ALG_CAST128, (obsolete)
+    // ALG_CAST128, (obsolete)
     ALG_CAST256,
-    //ALG_DES, (obsolete)
+    // ALG_DES, (obsolete)
     ALG_DES_EDE2,
     ALG_DES_EDE3,
-    //ALG_DES_XEX3, (obsolete)
-    //ALG_Gost, (obsolete)
+    // ALG_DES_XEX3, (obsolete)
+    // ALG_Gost, (obsolete)
     ALG_MARS,
     ALG_IDEA,
-    //ALG_RC2, (obsolete)
+    // ALG_RC2, (obsolete)
     ALG_RC5,
     ALG_RC6,
-    //ALG_SAFER_K, (obsolete)
-    //ALG_SAFER_SK, (obsolete)
+    // ALG_SAFER_K, (obsolete)
+    // ALG_SAFER_SK, (obsolete)
     ALG_Serpent,
     ALG_SHACAL2,
-    //ALG_SHARK, (obsolete)
+    // ALG_SHARK, (obsolete)
     ALG_SKIPJACK,
     ALG_Twofish,
-    //ALG_ThreeWay, (obsolete)
+    // ALG_ThreeWay, (obsolete)
     ALG_XTEA,
     ALG_MAX = ALG_XTEA
 } VSICryptAlg;
@@ -167,6 +176,8 @@ typedef enum
     MODE_MAX = MODE_CBC_CTS
 } VSICryptMode;
 
+//! @endcond
+
 /************************************************************************/
 /*                          VSISetCryptKey()                            */
 /************************************************************************/
@@ -178,11 +189,12 @@ typedef enum
  * in other places in memory or in on-disk temporary file.
  *
  * @param pabyKey key. Might be NULL to clear previously set key.
- * @param nKeySize length of the key in bytes. Might be 0 to clear previously set key.
+ * @param nKeySize length of the key in bytes. Might be 0 to clear
+ * previously set key.
  *
  * @see VSIInstallCryptFileHandler() for documentation on /vsicrypt/
  */
-void VSISetCryptKey(const GByte* pabyKey, int nKeySize)
+void VSISetCryptKey( const GByte* pabyKey, int nKeySize )
 {
     CPLAssert( (pabyKey != NULL && nKeySize != 0) ||
                (pabyKey == NULL && nKeySize == 0) );
@@ -197,12 +209,14 @@ void VSISetCryptKey(const GByte* pabyKey, int nKeySize)
     }
     if( pabyKey )
     {
-        pabyGlobalKey = (GByte*) CPLMalloc(nKeySize);
+        pabyGlobalKey = static_cast<GByte *>(CPLMalloc(nKeySize));
         memcpy(pabyGlobalKey, pabyKey, nKeySize);
         nGlobalKeySize = nKeySize;
     }
 }
 
+//! @cond Doxygen_Suppress
+
 /************************************************************************/
 /*                             GetAlg()                                 */
 /************************************************************************/
@@ -210,35 +224,35 @@ void VSISetCryptKey(const GByte* pabyKey, int nKeySize)
 #undef CASE_ALG
 #define CASE_ALG(alg)   if( EQUAL(pszName, #alg) ) return ALG_##alg;
 
-static VSICryptAlg GetAlg(const char* pszName)
+static VSICryptAlg GetAlg( const char* pszName )
 {
     CASE_ALG(AES)
     CASE_ALG(Blowfish)
     CASE_ALG(Camellia)
-    //CASE_ALG(CAST128) (obsolete)
+    // CASE_ALG(CAST128) (obsolete)
     CASE_ALG(CAST256)
-    //CASE_ALG(DES) (obsolete)
+    // CASE_ALG(DES) (obsolete)
     CASE_ALG(DES_EDE2)
     CASE_ALG(DES_EDE3)
-    //CASE_ALG(DES_XEX3) (obsolete)
-    //CASE_ALG(Gost) (obsolete)
+    // CASE_ALG(DES_XEX3) (obsolete)
+    // CASE_ALG(Gost) (obsolete)
     CASE_ALG(MARS)
     CASE_ALG(IDEA)
-    //CASE_ALG(RC2) (obsolete)
+    // CASE_ALG(RC2) (obsolete)
     CASE_ALG(RC5)
     CASE_ALG(RC6)
-    //CASE_ALG(SAFER_K) (obsolete)
-    //CASE_ALG(SAFER_SK) (obsolete)
+    // CASE_ALG(SAFER_K) (obsolete)
+    // CASE_ALG(SAFER_SK) (obsolete)
     CASE_ALG(Serpent)
     CASE_ALG(SHACAL2)
-    //CASE_ALG(SHARK) (obsolete)
+    // CASE_ALG(SHARK) (obsolete)
     CASE_ALG(SKIPJACK)
-    //CASE_ALG(ThreeWay) (obsolete)
+    // CASE_ALG(ThreeWay) (obsolete)
     CASE_ALG(Twofish)
     CASE_ALG(XTEA)
 
     CPLError(CE_Warning, CPLE_NotSupported,
-                "Unsupported cipher algorithm: %s. Using AES instead", pszName);
+             "Unsupported cipher algorithm: %s. Using AES instead", pszName);
     return ALG_AES;
 }
 
@@ -249,7 +263,7 @@ static VSICryptAlg GetAlg(const char* pszName)
 #undef CASE_ALG
 #define CASE_ALG(alg)   case ALG_##alg: return new CryptoPP::alg::Encryption();
 
-static CryptoPP::BlockCipher* GetEncBlockCipher(VSICryptAlg eAlg)
+static CryptoPP::BlockCipher* GetEncBlockCipher( VSICryptAlg eAlg )
 {
     switch( eAlg )
     {
@@ -257,29 +271,29 @@ static CryptoPP::BlockCipher* GetEncBlockCipher(VSICryptAlg eAlg)
 #ifndef USE_ONLY_CRYPTODLL_ALG
         CASE_ALG(Blowfish)
         CASE_ALG(Camellia)
-        //CASE_ALG(CAST128) (obsolete)
+        // CASE_ALG(CAST128) (obsolete)
         CASE_ALG(CAST256)
 #endif
-        //CASE_ALG(DES) (obsolete)
+        // CASE_ALG(DES) (obsolete)
         CASE_ALG(DES_EDE2)
         CASE_ALG(DES_EDE3)
-        //CASE_ALG(DES_XEX3) (obsolete)
+        // CASE_ALG(DES_XEX3) (obsolete)
 #ifndef USE_ONLY_CRYPTODLL_ALG
-        //CASE_ALG(Gost) (obsolete)
+        // CASE_ALG(Gost) (obsolete)
         CASE_ALG(MARS)
         CASE_ALG(IDEA)
-        //CASE_ALG(RC2) (obsolete)
+        // CASE_ALG(RC2) (obsolete)
         CASE_ALG(RC5)
         CASE_ALG(RC6)
-        //CASE_ALG(SAFER_K) (obsolete)
-        //CASE_ALG(SAFER_SK) (obsolete)
+        // CASE_ALG(SAFER_K) (obsolete)
+        // CASE_ALG(SAFER_SK) (obsolete)
         CASE_ALG(Serpent)
         CASE_ALG(SHACAL2)
-        //CASE_ALG(SHARK) (obsolete)
+        // CASE_ALG(SHARK) (obsolete)
 #endif
         CASE_ALG(SKIPJACK)
 #ifndef USE_ONLY_CRYPTODLL_ALG
-        //CASE_ALG(ThreeWay) (obsolete)
+        // CASE_ALG(ThreeWay) (obsolete)
         CASE_ALG(Twofish)
         CASE_ALG(XTEA)
 #endif
@@ -294,7 +308,7 @@ static CryptoPP::BlockCipher* GetEncBlockCipher(VSICryptAlg eAlg)
 #undef CASE_ALG
 #define CASE_ALG(alg)   case ALG_##alg: return new CryptoPP::alg::Decryption();
 
-static CryptoPP::BlockCipher* GetDecBlockCipher(VSICryptAlg eAlg)
+static CryptoPP::BlockCipher* GetDecBlockCipher( VSICryptAlg eAlg )
 {
     switch( eAlg )
     {
@@ -302,29 +316,29 @@ static CryptoPP::BlockCipher* GetDecBlockCipher(VSICryptAlg eAlg)
 #ifndef USE_ONLY_CRYPTODLL_ALG
         CASE_ALG(Blowfish)
         CASE_ALG(Camellia)
-        //CASE_ALG(CAST128) (obsolete)
+        // CASE_ALG(CAST128) (obsolete)
         CASE_ALG(CAST256)
 #endif
-        //CASE_ALG(DES) (obsolete)
+        // CASE_ALG(DES) (obsolete)
         CASE_ALG(DES_EDE2)
         CASE_ALG(DES_EDE3)
-        //CASE_ALG(DES_XEX3) (obsolete)
+        // CASE_ALG(DES_XEX3) (obsolete)
 #ifndef USE_ONLY_CRYPTODLL_ALG
-        //CASE_ALG(Gost) (obsolete)
+        // CASE_ALG(Gost) (obsolete)
         CASE_ALG(MARS)
         CASE_ALG(IDEA)
-        //CASE_ALG(RC2) (obsolete)
+        // CASE_ALG(RC2) (obsolete)
         CASE_ALG(RC5)
         CASE_ALG(RC6)
-        //CASE_ALG(SAFER_K) (obsolete)
-        //CASE_ALG(SAFER_SK) (obsolete)
+        // CASE_ALG(SAFER_K) (obsolete)
+        // CASE_ALG(SAFER_SK) (obsolete)
         CASE_ALG(Serpent)
         CASE_ALG(SHACAL2)
-        //CASE_ALG(SHARK) (obsolete)
+        // CASE_ALG(SHARK) (obsolete)
 #endif
         CASE_ALG(SKIPJACK)
 #ifndef USE_ONLY_CRYPTODLL_ALG
-        //CASE_ALG(ThreeWay) (obsolete)
+        // CASE_ALG(ThreeWay) (obsolete)
         CASE_ALG(Twofish)
         CASE_ALG(XTEA)
 #endif
@@ -336,7 +350,7 @@ static CryptoPP::BlockCipher* GetDecBlockCipher(VSICryptAlg eAlg)
 /*                             GetMode()                                */
 /************************************************************************/
 
-static VSICryptMode GetMode(const char* pszName)
+static VSICryptMode GetMode( const char* pszName )
 {
     if( EQUAL(pszName, "CBC") )
         return MODE_CBC;
@@ -350,7 +364,7 @@ static VSICryptMode GetMode(const char* pszName)
         return MODE_CBC_CTS;
 
     CPLError(CE_Warning, CPLE_NotSupported,
-                "Unsupported cipher block mode: %s. Using CBC instead", pszName);
+             "Unsupported cipher block mode: %s. Using CBC instead", pszName);
     return MODE_CBC;
 }
 
@@ -360,7 +374,7 @@ static VSICryptMode GetMode(const char* pszName)
 
 class VSICryptFileHeader
 {
-        std::string             CryptKeyCheck(CryptoPP::BlockCipher* poEncCipher);
+        std::string CryptKeyCheck( CryptoPP::BlockCipher* poEncCipher );
 
     public:
         VSICryptFileHeader() : nHeaderSize(0),
@@ -369,11 +383,12 @@ class VSICryptFileHeader
                                nSectorSize(512),
                                eAlg(ALG_AES),
                                eMode(MODE_CBC),
-                               bAddKeyCheck(FALSE),
-                               nPayloadFileSize(0)  {}
+                               bAddKeyCheck(false),
+                               nPayloadFileSize(0) {}
 
-        int ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKey);
-        int WriteToFile(VSIVirtualHandle* fp, CryptoPP::BlockCipher* poEncCipher);
+        int ReadFromFile( VSIVirtualHandle* fp, const CPLString& osKey );
+        int WriteToFile( VSIVirtualHandle* fp,
+                         CryptoPP::BlockCipher* poEncCipher );
 
         GUInt16 nHeaderSize;
         GByte nMajorVersion;
@@ -382,7 +397,7 @@ class VSICryptFileHeader
         VSICryptAlg eAlg;
         VSICryptMode eMode;
         CPLString osIV;
-        int bAddKeyCheck;
+        bool bAddKeyCheck;
         GUIntBig nPayloadFileSize;
         CPLString osFreeText;
         CPLString osExtraContent;
@@ -402,14 +417,16 @@ static bool VSICryptReadError()
 /*                       VSICryptGenerateSectorIV()                     */
 /************************************************************************/
 
-static std::string VSICryptGenerateSectorIV(const std::string& osIV,
-                                            vsi_l_offset nOffset)
+// TODO(rouault): This function really needs a comment saying what it does.
+static std::string VSICryptGenerateSectorIV( const std::string& osIV,
+                                             vsi_l_offset nOffset )
 {
     std::string osSectorIV(osIV);
-    size_t nLength = MIN(sizeof(vsi_l_offset), osSectorIV.size());
-    for( size_t i=0; i < nLength; i++ )
+    const size_t nLength = std::min(sizeof(vsi_l_offset), osSectorIV.size());
+    for( size_t i = 0; i < nLength; i++ )
     {
-        osSectorIV[i] = (char)((osSectorIV[i] ^ nOffset) & 0xff);
+        // TODO(rouault): Explain what this block is trying to do?
+        osSectorIV[i] = static_cast<char>((osSectorIV[i] ^ nOffset) & 0xff);
         nOffset >>= 8;
     }
     return osSectorIV;
@@ -419,19 +436,29 @@ static std::string VSICryptGenerateSectorIV(const std::string& osIV,
 /*                          CryptKeyCheck()                             */
 /************************************************************************/
 
-std::string VSICryptFileHeader::CryptKeyCheck(CryptoPP::BlockCipher* poEncCipher)
+std::string
+VSICryptFileHeader::CryptKeyCheck( CryptoPP::BlockCipher* poEncCipher )
 {
     std::string osKeyCheckRes;
 
     CPLAssert( osIV.size() == poEncCipher->BlockSize() );
-    // Generate a unique IV with a sector offset of 0xFFFFFFFFFFFFFFFF
+    // Generate a unique IV with a sector offset of 0xFFFFFFFFFFFFFFFF.
     std::string osCheckIV(VSICryptGenerateSectorIV(osIV, ~((vsi_l_offset)0)));
     CryptoPP::StringSink* poSink = new CryptoPP::StringSink(osKeyCheckRes);
-    CryptoPP::StreamTransformation* poMode = new CryptoPP::CBC_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osCheckIV.c_str() );
-    CryptoPP::StreamTransformationFilter* poEnc = new CryptoPP::StreamTransformationFilter(*poMode, poSink, CryptoPP::StreamTransformationFilter::NO_PADDING);
-    /* Not sure if it is add extra security, but pick up something that is unlikely to be a plain text (random number) */
-    poEnc->Put((const byte*)"\xDB\x31\xB9\x1B\xD3\x1C\xFA\x3E\x84\x06\xC1\x42\xC3\xEC\xCD\x9A\x02\x36\x22\x15\x58\x88\x74\x65\x00\x2F\x98\xBC\x69\x22\xE1\x63",
-               MIN(32, poEncCipher->BlockSize()));
+    CryptoPP::StreamTransformation* poMode =
+        new CryptoPP::CBC_Mode_ExternalCipher::Encryption(
+            *poEncCipher, (const byte*)osCheckIV.c_str());
+    CryptoPP::StreamTransformationFilter* poEnc =
+        new CryptoPP::StreamTransformationFilter(
+            *poMode, poSink,
+            CryptoPP::StreamTransformationFilter::NO_PADDING);
+    // Not sure if it is add extra security, but pick up something that is
+    // unlikely to be a plain text (random number).
+    poEnc->Put(
+        reinterpret_cast<const byte*>(
+            "\xDB\x31\xB9\x1B\xD3\x1C\xFA\x3E\x84\x06\xC1\x42\xC3\xEC\xCD\x9A"
+            "\x02\x36\x22\x15\x58\x88\x74\x65\x00\x2F\x98\xBC\x69\x22\xE1\x63"),
+        std::min(32U, poEncCipher->BlockSize()));
     poEnc->MessageEnd();
     delete poEnc;
     delete poMode;
@@ -443,9 +470,10 @@ std::string VSICryptFileHeader::CryptKeyCheck(CryptoPP::BlockCipher* poEncCipher
 /*                          ReadFromFile()                              */
 /************************************************************************/
 
-int VSICryptFileHeader::ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKey)
+int VSICryptFileHeader::ReadFromFile( VSIVirtualHandle* fp,
+                                      const CPLString& osKey )
 {
-    GByte abySignature[8];
+    GByte abySignature[8] = {};
     fp->Seek(0, SEEK_SET);
     CPL_STATIC_ASSERT(sizeof(VSICRYPT_SIGNATURE) == 8+1);
     if( fp->Read(abySignature, 8, 1) == 0 ||
@@ -511,6 +539,7 @@ int VSICryptFileHeader::ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKe
         return VSICryptReadError();
 
     osIV.resize(nIVSize);
+    // TODO(schwehr): Using the const buffer of a string is a bad idea.
     if( fp->Read((void*)osIV.c_str(), 1, nIVSize) != nIVSize )
         return VSICryptReadError();
 
@@ -525,19 +554,21 @@ int VSICryptFileHeader::ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKe
     GByte nKeyCheckSize;
     if( fp->Read(&nKeyCheckSize, 1, 1) == 0 )
         return VSICryptReadError();
-    bAddKeyCheck = (nKeyCheckSize != 0);
+    bAddKeyCheck = nKeyCheckSize != 0;
     if( nKeyCheckSize )
     {
         CPLString osKeyCheck;
         osKeyCheck.resize(nKeyCheckSize);
-        if( fp->Read((void*)osKeyCheck.c_str(), 1, nKeyCheckSize) != nKeyCheckSize )
+        if( fp->Read((void*)osKeyCheck.c_str(), 1,
+                     nKeyCheckSize) != nKeyCheckSize )
             return VSICryptReadError();
 
-        if( osKey.size() == 0 && pabyGlobalKey == NULL )
+        if( osKey.empty() && pabyGlobalKey == NULL )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                    "Encryption key not defined as key/key_b64 parameter, "
-                    "VSICRYPT_KEY/VSICRYPT_KEY_B64 configuration option or VSISetCryptKey() API");
+                     "Encryption key not defined as key/key_b64 parameter, "
+                     "VSICRYPT_KEY/VSICRYPT_KEY_B64 configuration option or "
+                     "VSISetCryptKey() API");
             return FALSE;
         }
 
@@ -557,14 +588,15 @@ int VSICryptFileHeader::ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKe
 
         try
         {
-            if( osKey.size() )
+            if( !osKey.empty() )
             {
-                int nKeySize = MIN(nMaxKeySize, (int)osKey.size());
+                const int nKeySize =
+                    std::min(nMaxKeySize, static_cast<int>(osKey.size()));
                 poEncCipher->SetKey((const byte*)osKey.c_str(), nKeySize);
             }
             else if( pabyGlobalKey )
             {
-                int nKeySize = MIN(nMaxKeySize, nGlobalKeySize);
+                const int nKeySize = std::min(nMaxKeySize, nGlobalKeySize);
                 poEncCipher->SetKey(pabyGlobalKey, nKeySize);
             }
         }
@@ -580,7 +612,8 @@ int VSICryptFileHeader::ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKe
         delete poEncCipher;
 
         if( osKeyCheck.size() != osKeyCheckRes.size() ||
-            memcmp(osKeyCheck.c_str(), osKeyCheckRes.c_str(), osKeyCheck.size()) != 0 )
+            memcmp(osKeyCheck.c_str(), osKeyCheckRes.c_str(), osKeyCheck.size())
+            != 0 )
         {
             CPLError(CE_Failure, CPLE_AppDefined, "Bad key");
             return FALSE;
@@ -595,13 +628,14 @@ int VSICryptFileHeader::ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKe
              nPayloadFileSize);
 #endif
 
-    GUInt16 nExtraContentSize;
+    GUInt16 nExtraContentSize = 0;
     if( fp->Read(&nExtraContentSize, 2, 1) == 0 )
         return VSICryptReadError();
     nExtraContentSize = CPL_LSBWORD16(nExtraContentSize);
 
     osExtraContent.resize(nExtraContentSize);
-    if( fp->Read((void*)osExtraContent.c_str(), 1, nExtraContentSize) != nExtraContentSize )
+    if( fp->Read((void*)osExtraContent.c_str(), 1, nExtraContentSize)
+        != nExtraContentSize )
         return VSICryptReadError();
 
     return TRUE;
@@ -611,13 +645,12 @@ int VSICryptFileHeader::ReadFromFile(VSIVirtualHandle* fp, const CPLString& osKe
 /*                          WriteToFile()                               */
 /************************************************************************/
 
-int VSICryptFileHeader::WriteToFile(VSIVirtualHandle* fp, CryptoPP::BlockCipher* poEncCipher)
+int VSICryptFileHeader::WriteToFile( VSIVirtualHandle* fp,
+                                     CryptoPP::BlockCipher* poEncCipher )
 {
-    int bRet = TRUE;
-
     fp->Seek(0, SEEK_SET);
 
-    bRet &= (fp->Write(VSICRYPT_SIGNATURE, 8, 1) == 1);
+    bool bRet = fp->Write(VSICRYPT_SIGNATURE, 8, 1) == 1;
 
     std::string osKeyCheckRes;
     if( bAddKeyCheck )
@@ -654,34 +687,38 @@ int VSICryptFileHeader::WriteToFile(VSIVirtualHandle* fp, CryptoPP::BlockCipher*
     GUInt16 nSectorSizeToWrite = CPL_LSBWORD16(nSectorSize);
     bRet &= (fp->Write(&nSectorSizeToWrite, 2, 1) == 1);
 
-    GByte nAlg = (GByte)eAlg;
+    GByte nAlg = static_cast<GByte>(eAlg);
     bRet &= (fp->Write(&nAlg, 1, 1) == 1);
 
-    GByte nMode = (GByte)eMode;
+    GByte nMode = static_cast<GByte>(eMode);
     bRet &= (fp->Write(&nMode, 1, 1) == 1);
 
-    GByte nIVSizeToWrite = (GByte)osIV.size();
+    GByte nIVSizeToWrite = static_cast<GByte>(osIV.size());
     CPLAssert(nIVSizeToWrite == osIV.size());
     bRet &= (fp->Write(&nIVSizeToWrite, 1, 1) == 1);
     bRet &= (fp->Write(osIV.c_str(), 1, osIV.size()) == osIV.size());
 
     GUInt16 nFreeTextSizeToWrite = CPL_LSBWORD16((GUInt16)osFreeText.size());
     bRet &= (fp->Write(&nFreeTextSizeToWrite, 2, 1) == 1);
-    bRet &= (fp->Write(osFreeText.c_str(), 1, osFreeText.size()) == osFreeText.size());
+    bRet &= (fp->Write(osFreeText.c_str(), 1,
+                       osFreeText.size()) == osFreeText.size());
 
-    GByte nSize = (GByte)osKeyCheckRes.size();
+    GByte nSize = static_cast<GByte>(osKeyCheckRes.size());
     bRet &= (fp->Write(&nSize, 1, 1) == 1);
-    bRet &= (fp->Write(osKeyCheckRes.c_str(), 1, osKeyCheckRes.size()) == osKeyCheckRes.size());
+    bRet &= (fp->Write(osKeyCheckRes.c_str(), 1,
+                       osKeyCheckRes.size()) == osKeyCheckRes.size());
 
     GUIntBig nPayloadFileSizeToWrite = nPayloadFileSize;
     CPL_LSBPTR64(&nPayloadFileSizeToWrite);
     bRet &= (fp->Write(&nPayloadFileSizeToWrite, 8, 1) == 1);
 
-    GUInt16 nExtraContentSizeToWrite = CPL_LSBWORD16((GUInt16)osExtraContent.size());
+    GUInt16 nExtraContentSizeToWrite =
+        CPL_LSBWORD16(static_cast<GUInt16>(osExtraContent.size()));
     bRet &= (fp->Write(&nExtraContentSizeToWrite, 2, 1) == 1);
-    bRet &= (fp->Write(osExtraContent.c_str(), 1, osExtraContent.size()) == osExtraContent.size());
+    bRet &= (fp->Write(osExtraContent.c_str(), 1, osExtraContent.size()) ==
+             osExtraContent.size());
 
-    CPLAssert( fp->Tell() == nHeaderSize) ;
+    CPLAssert(fp->Tell() == nHeaderSize);
 
     return bRet;
 }
@@ -697,9 +734,9 @@ class VSICryptFileHandle CPL_FINAL : public VSIVirtualHandle
         int                 nPerms;
         VSIVirtualHandle   *poBaseHandle;
         VSICryptFileHeader *poHeader;
-        int                 bUpdateHeader;
+        bool                bUpdateHeader;
         vsi_l_offset        nCurPos;
-        int                 bEOF;
+        bool                bEOF;
 
         CryptoPP::BlockCipher* poEncCipher;
         CryptoPP::BlockCipher* poDecCipher;
@@ -708,49 +745,60 @@ class VSICryptFileHandle CPL_FINAL : public VSIVirtualHandle
         vsi_l_offset        nWBOffset;
         GByte*              pabyWB;
         int                 nWBSize;
-        int                 bWBDirty;
+        bool                bWBDirty;
 
-        int                 bLastSectorWasModified;
+        bool                bLastSectorWasModified;
 
-        void                 EncryptBlock(GByte* pabyData, vsi_l_offset nOffset);
-        int                  DecryptBlock(GByte* pabyData, vsi_l_offset nOffset);
-        int                  FlushDirty();
+        void             EncryptBlock( GByte* pabyData, vsi_l_offset nOffset );
+        bool             DecryptBlock( GByte* pabyData, vsi_l_offset nOffset );
+        bool             FlushDirty();
 
   public:
-
-    VSICryptFileHandle(CPLString osBaseFilename,
-                       VSIVirtualHandle* poBaseHandle,
-                       VSICryptFileHeader* poHeader,
-                       int nPerms);
-    ~VSICryptFileHandle();
-
-    int                  Init(const CPLString& osKey, int bWriteHeader = FALSE);
-
-    virtual int          Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t       Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t       Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int          Eof();
-    virtual int          Flush();
-    virtual int          Close();
-    virtual int          Truncate( vsi_l_offset nNewSize );
+    VSICryptFileHandle( CPLString osBaseFilename,
+                        VSIVirtualHandle* poBaseHandle,
+                        VSICryptFileHeader* poHeader,
+                        int nPerms );
+    virtual ~VSICryptFileHandle();
+
+    int                  Init( const CPLString& osKey,
+                               bool bWriteHeader = false );
+
+    virtual int          Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t       Read( void *pBuffer, size_t nSize,
+                               size_t nMemb ) override;
+    virtual size_t       Write( const void *pBuffer, size_t nSize,
+                                size_t nMemb ) override;
+    virtual int          Eof() override;
+    virtual int          Flush() override;
+    virtual int          Close() override;
+    virtual int          Truncate( vsi_l_offset nNewSize ) override;
 };
 
 /************************************************************************/
 /*                          VSICryptFileHandle()                        */
 /************************************************************************/
 
-VSICryptFileHandle::VSICryptFileHandle(CPLString osBaseFilenameIn,
-                                       VSIVirtualHandle* poBaseHandleIn,
-                                       VSICryptFileHeader* poHeaderIn,
-                                       int nPermsIn) :
-        osBaseFilename(osBaseFilenameIn), nPerms(nPermsIn),
-        poBaseHandle(poBaseHandleIn), poHeader(poHeaderIn), bUpdateHeader(FALSE),
-        nCurPos(0), bEOF(FALSE), poEncCipher(NULL), poDecCipher(NULL), nBlockSize(0),
-        nWBOffset(0), pabyWB(NULL), nWBSize(0), bWBDirty(FALSE), bLastSectorWasModified(FALSE)
-{
-
-}
+VSICryptFileHandle::VSICryptFileHandle( CPLString osBaseFilenameIn,
+                                        VSIVirtualHandle* poBaseHandleIn,
+                                        VSICryptFileHeader* poHeaderIn,
+                                        int nPermsIn ) :
+    osBaseFilename(osBaseFilenameIn),
+    nPerms(nPermsIn),
+    poBaseHandle(poBaseHandleIn),
+    poHeader(poHeaderIn),
+    bUpdateHeader(false),
+    nCurPos(0),
+    bEOF(false),
+    poEncCipher(NULL),
+    poDecCipher(NULL),
+    nBlockSize(0),
+    nWBOffset(0),
+    pabyWB(NULL),
+    nWBSize(0),
+    bWBDirty(false),
+    bLastSectorWasModified(false)
+{}
 
 /************************************************************************/
 /*                         ~VSICryptFileHandle()                        */
@@ -769,14 +817,14 @@ VSICryptFileHandle::~VSICryptFileHandle()
 /*                               Init()                                 */
 /************************************************************************/
 
-int VSICryptFileHandle::Init(const CPLString& osKey, int bWriteHeader)
+int VSICryptFileHandle::Init( const CPLString& osKey, bool bWriteHeader )
 {
     poEncCipher = GetEncBlockCipher(poHeader->eAlg);
     if( poEncCipher == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                    "Cipher algorithm not supported in this build: %d",
-                    (int)poHeader->eAlg);
+                 "Cipher algorithm not supported in this build: %d",
+                 static_cast<int>(poHeader->eAlg));
         return FALSE;
     }
 
@@ -793,15 +841,16 @@ int VSICryptFileHandle::Init(const CPLString& osKey, int bWriteHeader)
 
     try
     {
-        if( osKey.size() )
+        if( !osKey.empty() )
         {
-            int nKeySize = MIN(nMaxKeySize, (int)osKey.size());
+            const int nKeySize =
+                std::min(nMaxKeySize, static_cast<int>(osKey.size()));
             poEncCipher->SetKey((const byte*)osKey.c_str(), nKeySize);
             poDecCipher->SetKey((const byte*)osKey.c_str(), nKeySize);
         }
         else if( pabyGlobalKey )
         {
-            int nKeySize = MIN(nMaxKeySize, nGlobalKeySize);
+            const int nKeySize = std::min(nMaxKeySize, nGlobalKeySize);
             poEncCipher->SetKey(pabyGlobalKey, nKeySize);
             poDecCipher->SetKey(pabyGlobalKey, nKeySize);
         }
@@ -815,7 +864,7 @@ int VSICryptFileHandle::Init(const CPLString& osKey, int bWriteHeader)
         return FALSE;
     }
 
-    pabyWB = (GByte*)CPLCalloc(1, poHeader->nSectorSize);
+    pabyWB = static_cast<GByte *>(CPLCalloc(1, poHeader->nSectorSize));
 
     if( (poHeader->nSectorSize % nBlockSize) != 0 )
     {
@@ -824,10 +873,12 @@ int VSICryptFileHandle::Init(const CPLString& osKey, int bWriteHeader)
                  poHeader->nSectorSize, nBlockSize);
         return FALSE;
     }
-    if( poHeader->eMode == MODE_CBC_CTS && poHeader->nSectorSize < 2 * nBlockSize )
+    if( poHeader->eMode == MODE_CBC_CTS &&
+        poHeader->nSectorSize < 2 * nBlockSize )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Sector size (%d) should be at least twice larger than the block size (%d) in CBC_CTS.",
+                 "Sector size (%d) should be at least twice larger than "
+                 "the block size (%d) in CBC_CTS.",
                  poHeader->nSectorSize, nBlockSize);
         return FALSE;
     }
@@ -844,32 +895,39 @@ int VSICryptFileHandle::Init(const CPLString& osKey, int bWriteHeader)
 /*                          EncryptBlock()                              */
 /************************************************************************/
 
-void VSICryptFileHandle::EncryptBlock(GByte* pabyData, vsi_l_offset nOffset)
+void VSICryptFileHandle::EncryptBlock( GByte* pabyData, vsi_l_offset nOffset )
 {
     std::string osRes;
     std::string osIV(VSICryptGenerateSectorIV(poHeader->osIV, nOffset));
-    CPLAssert( (int)osIV.size() == nBlockSize );
+    CPLAssert( static_cast<int>(osIV.size()) == nBlockSize );
 
     CryptoPP::StringSink* poSink = new CryptoPP::StringSink(osRes);
     CryptoPP::StreamTransformation* poMode;
     if( poHeader->eMode == MODE_CBC )
-        poMode = new CryptoPP::CBC_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
+        poMode = new CryptoPP::CBC_Mode_ExternalCipher::Encryption(
+            *poEncCipher, reinterpret_cast<const byte *>(osIV.c_str()) );
     else if( poHeader->eMode == MODE_CFB )
-        poMode = new CryptoPP::CFB_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
+        poMode = new CryptoPP::CFB_Mode_ExternalCipher::Encryption(
+            *poEncCipher, reinterpret_cast<const byte *>(osIV.c_str()) );
     else if( poHeader->eMode == MODE_OFB )
-        poMode = new CryptoPP::OFB_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
+        poMode = new CryptoPP::OFB_Mode_ExternalCipher::Encryption(
+            *poEncCipher, reinterpret_cast<const byte *>(osIV.c_str()) );
     else if( poHeader->eMode == MODE_CTR )
-        poMode = new CryptoPP::CTR_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
+        poMode = new CryptoPP::CTR_Mode_ExternalCipher::Encryption(
+            *poEncCipher, reinterpret_cast<const byte *>(osIV.c_str()) );
     else
-        poMode = new CryptoPP::CBC_CTS_Mode_ExternalCipher::Encryption(*poEncCipher, (const byte*)osIV.c_str() );
-    CryptoPP::StreamTransformationFilter* poEnc = new CryptoPP::StreamTransformationFilter(*poMode, poSink, CryptoPP::StreamTransformationFilter::NO_PADDING);
-    poEnc->Put((const byte*)pabyData, poHeader->nSectorSize);
+        poMode = new CryptoPP::CBC_CTS_Mode_ExternalCipher::Encryption(
+            *poEncCipher, reinterpret_cast<const byte *>(osIV.c_str()) );
+    CryptoPP::StreamTransformationFilter* poEnc =
+        new CryptoPP::StreamTransformationFilter(
+            *poMode, poSink, CryptoPP::StreamTransformationFilter::NO_PADDING);
+    poEnc->Put(pabyData, poHeader->nSectorSize);
     poEnc->MessageEnd();
     delete poEnc;
 
     delete poMode;
 
-    CPLAssert( (int)osRes.length() == poHeader->nSectorSize );
+    CPLAssert( static_cast<int>(osRes.length()) == poHeader->nSectorSize );
     memcpy( pabyData, osRes.c_str(), osRes.length() );
 }
 
@@ -877,29 +935,35 @@ void VSICryptFileHandle::EncryptBlock(GByte* pabyData, vsi_l_offset nOffset)
 /*                          DecryptBlock()                              */
 /************************************************************************/
 
-int VSICryptFileHandle::DecryptBlock(GByte* pabyData, vsi_l_offset nOffset)
+bool VSICryptFileHandle::DecryptBlock( GByte* pabyData, vsi_l_offset nOffset )
 {
     std::string osRes;
     std::string osIV(VSICryptGenerateSectorIV(poHeader->osIV, nOffset));
-    CPLAssert( (int)osIV.size() == nBlockSize );
+    CPLAssert( static_cast<int>(osIV.size()) == nBlockSize );
     CryptoPP::StringSink* poSink = new CryptoPP::StringSink(osRes);
     CryptoPP::StreamTransformation* poMode = NULL;
     CryptoPP::StreamTransformationFilter* poDec = NULL;
 
     try
     {
-        /* Yes, some modes need the encryption cipher */
+        // Yes, some modes need the encryption cipher.
         if( poHeader->eMode == MODE_CBC )
-            poMode = new CryptoPP::CBC_Mode_ExternalCipher::Decryption(*poDecCipher, (const byte*)osIV.c_str() );
+            poMode = new CryptoPP::CBC_Mode_ExternalCipher::Decryption(
+                *poDecCipher, (const byte*)osIV.c_str() );
         else if( poHeader->eMode == MODE_CFB )
-            poMode = new CryptoPP::CFB_Mode_ExternalCipher::Decryption(*poEncCipher, (const byte*)osIV.c_str() );
+            poMode = new CryptoPP::CFB_Mode_ExternalCipher::Decryption(
+                *poEncCipher, (const byte*)osIV.c_str() );
         else if( poHeader->eMode == MODE_OFB )
-            poMode = new CryptoPP::OFB_Mode_ExternalCipher::Decryption(*poEncCipher, (const byte*)osIV.c_str() );
+            poMode = new CryptoPP::OFB_Mode_ExternalCipher::Decryption(
+                *poEncCipher, (const byte*)osIV.c_str() );
         else if( poHeader->eMode == MODE_CTR )
-            poMode = new CryptoPP::CTR_Mode_ExternalCipher::Decryption(*poEncCipher, (const byte*)osIV.c_str() );
+            poMode = new CryptoPP::CTR_Mode_ExternalCipher::Decryption(
+                *poEncCipher, (const byte*)osIV.c_str() );
         else
-            poMode = new CryptoPP::CBC_CTS_Mode_ExternalCipher::Decryption(*poDecCipher, (const byte*)osIV.c_str() );
-        poDec = new CryptoPP::StreamTransformationFilter(*poMode, poSink, CryptoPP::StreamTransformationFilter::NO_PADDING);
+            poMode = new CryptoPP::CBC_CTS_Mode_ExternalCipher::Decryption(
+                *poDecCipher, (const byte*)osIV.c_str() );
+        poDec = new CryptoPP::StreamTransformationFilter(
+            *poMode, poSink, CryptoPP::StreamTransformationFilter::NO_PADDING);
         poDec->Put((const byte*)pabyData, poHeader->nSectorSize);
         poDec->MessageEnd();
         delete poDec;
@@ -912,24 +976,24 @@ int VSICryptFileHandle::DecryptBlock(GByte* pabyData, vsi_l_offset nOffset)
 
         CPLError(CE_Failure, CPLE_AppDefined,
                  "CryptoPP exception: %s", e.what());
-        return FALSE;
+        return false;
     }
 
-    CPLAssert( (int)osRes.length() == poHeader->nSectorSize );
+    CPLAssert( static_cast<int>(osRes.length()) == poHeader->nSectorSize );
     memcpy( pabyData, osRes.c_str(), osRes.length() );
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
 /*                             FlushDirty()                             */
 /************************************************************************/
 
-int VSICryptFileHandle::FlushDirty()
+bool VSICryptFileHandle::FlushDirty()
 {
     if( !bWBDirty )
-        return TRUE;
-    bWBDirty = FALSE;
+        return true;
+    bWBDirty = false;
 
     EncryptBlock(pabyWB, nWBOffset);
     poBaseHandle->Seek( poHeader->nHeaderSize + nWBOffset, SEEK_SET );
@@ -938,9 +1002,9 @@ int VSICryptFileHandle::FlushDirty()
     nWBSize = 0;
 
     if( poBaseHandle->Write( pabyWB, poHeader->nSectorSize, 1 ) != 1 )
-        return FALSE;
+        return false;
 
-    return TRUE;
+    return true;
 }
 
 /************************************************************************/
@@ -950,10 +1014,11 @@ int VSICryptFileHandle::FlushDirty()
 int VSICryptFileHandle::Seek( vsi_l_offset nOffset, int nWhence )
 {
 #ifdef VERBOSE_VSICRYPT
-    CPLDebug("VSICRYPT", "Seek(nOffset=" CPL_FRMT_GUIB ", nWhence=%d)", nOffset, nWhence);
+    CPLDebug("VSICRYPT", "Seek(nOffset=" CPL_FRMT_GUIB ", nWhence=%d)",
+             nOffset, nWhence);
 #endif
 
-    bEOF = FALSE;
+    bEOF = false;
 
     if( nWhence == SEEK_SET )
         nCurPos = nOffset;
@@ -983,10 +1048,11 @@ vsi_l_offset VSICryptFileHandle::Tell()
 size_t VSICryptFileHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
 {
     size_t nToRead = nSize * nMemb;
-    GByte* pabyBuffer = (GByte*)pBuffer;
+    GByte* pabyBuffer = static_cast<GByte *>(pBuffer);
 
 #ifdef VERBOSE_VSICRYPT
-    CPLDebug("VSICRYPT", "Read(nCurPos=" CPL_FRMT_GUIB ", nToRead=%d)", nCurPos, (int)nToRead);
+    CPLDebug("VSICRYPT", "Read(nCurPos=" CPL_FRMT_GUIB ", nToRead=%d)",
+             nCurPos, static_cast<int>(nToRead));
 #endif
 
     if( (nPerms & VSICRYPT_READ) == 0 )
@@ -994,23 +1060,26 @@ size_t VSICryptFileHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
 
     if( nCurPos >= poHeader->nPayloadFileSize )
     {
-        bEOF = TRUE;
+        bEOF = true;
         return 0;
     }
 
     if( !FlushDirty() )
         return 0;
 
-    while(nToRead > 0)
+    while( nToRead > 0 )
     {
         if( nCurPos >= nWBOffset && nCurPos < nWBOffset + nWBSize )
         {
-            int nToCopy = MIN(static_cast<int>(nToRead),
-                              static_cast<int>(nWBSize - (nCurPos - nWBOffset)));
+            // TODO(schwehr): Can nToCopy be a size_t to simplify casting?
+            int nToCopy = std::min(
+                static_cast<int>(nToRead),
+                static_cast<int>(nWBSize - (nCurPos - nWBOffset)));
             if( nCurPos + nToCopy > poHeader->nPayloadFileSize )
             {
-                bEOF = TRUE;
-                nToCopy = static_cast<int>(poHeader->nPayloadFileSize - nCurPos);
+                bEOF = true;
+                nToCopy =
+                    static_cast<int>(poHeader->nPayloadFileSize - nCurPos);
             }
             memcpy(pabyBuffer, pabyWB + nCurPos - nWBOffset, nToCopy);
             pabyBuffer += nToCopy;
@@ -1021,11 +1090,12 @@ size_t VSICryptFileHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
             CPLAssert( (nCurPos % poHeader->nSectorSize) == 0 );
         }
 
-        vsi_l_offset nSectorOffset = (nCurPos / poHeader->nSectorSize) * poHeader->nSectorSize;
+        vsi_l_offset nSectorOffset =
+            (nCurPos / poHeader->nSectorSize) * poHeader->nSectorSize;
         poBaseHandle->Seek( poHeader->nHeaderSize + nSectorOffset, SEEK_SET );
         if( poBaseHandle->Read( pabyWB, poHeader->nSectorSize, 1 ) != 1 )
         {
-            bEOF = TRUE;
+            bEOF = true;
             break;
         }
         if( !DecryptBlock( pabyWB, nSectorOffset) )
@@ -1035,10 +1105,12 @@ size_t VSICryptFileHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
         if( (nPerms & VSICRYPT_WRITE) &&
             nSectorOffset + poHeader->nSectorSize > poHeader->nPayloadFileSize )
         {
-            // If the last sector was padded with random values, decrypt it to 0 in case of update scenarios
+            // If the last sector was padded with random values, decrypt it to 0
+            // in case of update scenarios.
             CPLAssert( nSectorOffset < poHeader->nPayloadFileSize );
             memset( pabyWB + poHeader->nPayloadFileSize - nSectorOffset, 0,
-                    nSectorOffset + poHeader->nSectorSize - poHeader->nPayloadFileSize );
+                    nSectorOffset + poHeader->nSectorSize -
+                    poHeader->nPayloadFileSize );
         }
         nWBOffset = nSectorOffset;
         nWBSize = poHeader->nSectorSize;
@@ -1046,7 +1118,8 @@ size_t VSICryptFileHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
 
     int nRet = static_cast<int>( (nSize * nMemb - nToRead) / nSize );
 #ifdef VERBOSE_VSICRYPT
-    CPLDebug("VSICRYPT", "Read ret = %d (nMemb = %d)", nRet, (int)nMemb);
+    CPLDebug("VSICRYPT", "Read ret = %d (nMemb = %d)",
+             nRet, static_cast<int>(nMemb));
 #endif
     return nRet;
 }
@@ -1055,22 +1128,29 @@ size_t VSICryptFileHandle::Read( void *pBuffer, size_t nSize, size_t nMemb )
 /*                                Write()                               */
 /************************************************************************/
 
-size_t VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMemb )
+size_t
+VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMemb )
 {
     size_t nToWrite = nSize * nMemb;
-    const GByte* pabyBuffer = (const GByte*)pBuffer;
+    const GByte* pabyBuffer = static_cast<const GByte *>(pBuffer);
 
 #ifdef VERBOSE_VSICRYPT
     CPLDebug("VSICRYPT", "Write(nCurPos=" CPL_FRMT_GUIB ", nToWrite=%d,"
-             "nPayloadFileSize=" CPL_FRMT_GUIB ",bWBDirty=%d,nWBOffset=" CPL_FRMT_GUIB ",nWBSize=%d)",
-             nCurPos, (int)nToWrite, poHeader->nPayloadFileSize, bWBDirty, nWBOffset, nWBSize);
+             "nPayloadFileSize=" CPL_FRMT_GUIB
+             ",bWBDirty=%d,nWBOffset=" CPL_FRMT_GUIB ",nWBSize=%d)",
+             nCurPos, static_cast<int>(nToWrite), poHeader->nPayloadFileSize,
+             static_cast<int>(bWBDirty), nWBOffset, nWBSize);
 #endif
 
     if( (nPerms & VSICRYPT_WRITE) == 0 )
         return 0;
 
-    if( nCurPos >= (poHeader->nPayloadFileSize / poHeader->nSectorSize) * poHeader->nSectorSize )
-        bLastSectorWasModified = TRUE;
+    if( nCurPos >=
+        (poHeader->nPayloadFileSize / poHeader->nSectorSize) *
+        poHeader->nSectorSize )
+    {
+        bLastSectorWasModified = true;
+    }
 
     // If seeking past end of file, we need to explicitly encrypt the
     // padding zeroes.
@@ -1078,8 +1158,11 @@ size_t VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMem
     {
         if( !FlushDirty() )
             return 0;
-        vsi_l_offset nOffset = (poHeader->nPayloadFileSize + poHeader->nSectorSize - 1) / poHeader->nSectorSize * poHeader->nSectorSize;
-        vsi_l_offset nEndOffset = nCurPos / poHeader->nSectorSize * poHeader->nSectorSize;
+        vsi_l_offset nOffset =
+            (poHeader->nPayloadFileSize + poHeader->nSectorSize - 1) /
+            poHeader->nSectorSize * poHeader->nSectorSize;
+        const vsi_l_offset nEndOffset =
+            nCurPos / poHeader->nSectorSize * poHeader->nSectorSize;
         for( ; nOffset < nEndOffset; nOffset += poHeader->nSectorSize )
         {
             memset( pabyWB, 0, poHeader->nSectorSize );
@@ -1088,7 +1171,7 @@ size_t VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMem
             if( poBaseHandle->Write( pabyWB, poHeader->nSectorSize, 1 ) != 1 )
                 return 0;
             poHeader->nPayloadFileSize = nOffset + poHeader->nSectorSize;
-            bUpdateHeader = TRUE;
+            bUpdateHeader = true;
         }
     }
 
@@ -1096,28 +1179,30 @@ size_t VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMem
     {
         if( nCurPos >= nWBOffset && nCurPos < nWBOffset + nWBSize )
         {
-            bWBDirty = TRUE;
-            int nToCopy = MIN(static_cast<int>(nToWrite),
-                              static_cast<int>(nWBSize - (nCurPos - nWBOffset)));
+            bWBDirty = true;
+            const int nToCopy =
+                std::min(static_cast<int>(nToWrite),
+                         static_cast<int>(nWBSize - (nCurPos - nWBOffset)));
             memcpy(pabyWB + nCurPos - nWBOffset, pabyBuffer, nToCopy);
             pabyBuffer += nToCopy;
             nToWrite -= nToCopy;
             nCurPos += nToCopy;
             if( nCurPos > poHeader->nPayloadFileSize )
             {
-                bUpdateHeader = TRUE;
+                bUpdateHeader = true;
                 poHeader->nPayloadFileSize = nCurPos;
             }
             if( nToWrite == 0 )
                 break;
             CPLAssert( (nCurPos % poHeader->nSectorSize) == 0 );
         }
-        else if( (nCurPos % poHeader->nSectorSize) == 0 && nToWrite >= (size_t)poHeader->nSectorSize )
+        else if( (nCurPos % poHeader->nSectorSize) == 0 &&
+                 nToWrite >= static_cast<size_t>(poHeader->nSectorSize) )
         {
             if( !FlushDirty() )
                 break;
 
-            bWBDirty = TRUE;
+            bWBDirty = true;
             nWBOffset = nCurPos;
             nWBSize = poHeader->nSectorSize;
             memcpy( pabyWB, pabyBuffer, poHeader->nSectorSize );
@@ -1126,7 +1211,7 @@ size_t VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMem
             nCurPos += poHeader->nSectorSize;
             if( nCurPos > poHeader->nPayloadFileSize )
             {
-                bUpdateHeader = TRUE;
+                bUpdateHeader = true;
                 poHeader->nPayloadFileSize = nCurPos;
             }
         }
@@ -1135,44 +1220,59 @@ size_t VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMem
             if( !FlushDirty() )
                 break;
 
-            vsi_l_offset nSectorOffset = (nCurPos / poHeader->nSectorSize) * poHeader->nSectorSize;
-            vsi_l_offset nLastSectorOffset = (poHeader->nPayloadFileSize / poHeader->nSectorSize) * poHeader->nSectorSize;
+            const vsi_l_offset nSectorOffset =
+                (nCurPos / poHeader->nSectorSize) * poHeader->nSectorSize;
+            const vsi_l_offset nLastSectorOffset =
+                (poHeader->nPayloadFileSize / poHeader->nSectorSize) *
+                poHeader->nSectorSize;
             if( nSectorOffset > nLastSectorOffset &&
                 (poHeader->nPayloadFileSize % poHeader->nSectorSize) != 0 )
             {
-                if( poBaseHandle->Seek( poHeader->nHeaderSize + nLastSectorOffset, 0) == 0 &&
-                    poBaseHandle->Read( pabyWB, poHeader->nSectorSize, 1 ) == 1 &&
+                if( poBaseHandle->Seek(
+                        poHeader->nHeaderSize + nLastSectorOffset, 0) == 0 &&
+                    poBaseHandle->Read(
+                       pabyWB, poHeader->nSectorSize, 1 ) == 1 &&
                     DecryptBlock( pabyWB, nLastSectorOffset) )
                 {
-                    // Fill with 0
 #ifdef VERBOSE_VSICRYPT
                     CPLDebug("VSICRYPT", "Filling %d trailing bytes with 0",
-                            (int)(poHeader->nSectorSize - (poHeader->nPayloadFileSize - nLastSectorOffset )));
+                             static_cast<int>(poHeader->nSectorSize -
+                                              (poHeader->nPayloadFileSize -
+                                               nLastSectorOffset )));
 #endif
+                    // Fill with 0.
                     memset(
-                        (byte*)(pabyWB + poHeader->nPayloadFileSize - nLastSectorOffset),
+                        (byte*)(pabyWB + poHeader->nPayloadFileSize -
+                                nLastSectorOffset),
                         0,
-                        (int)(poHeader->nSectorSize - (poHeader->nPayloadFileSize - nLastSectorOffset )));
+                        static_cast<int>(
+                            poHeader->nSectorSize -
+                            (poHeader->nPayloadFileSize - nLastSectorOffset)));
 
-                    if( poBaseHandle->Seek( poHeader->nHeaderSize + nLastSectorOffset, 0) == 0)
+                    if( poBaseHandle->Seek(
+                            poHeader->nHeaderSize + nLastSectorOffset, 0) == 0 )
                     {
                         EncryptBlock( pabyWB, nLastSectorOffset);
                         poBaseHandle->Write( pabyWB, poHeader->nSectorSize, 1 );
                     }
                 }
             }
-            poBaseHandle->Seek( poHeader->nHeaderSize + nSectorOffset, SEEK_SET );
+            poBaseHandle->Seek(poHeader->nHeaderSize + nSectorOffset, SEEK_SET);
             if( poBaseHandle->Read( pabyWB, poHeader->nSectorSize, 1 ) == 0 ||
                 !DecryptBlock( pabyWB, nSectorOffset) )
             {
                 memset( pabyWB, 0, poHeader->nSectorSize );
             }
-            else if( nSectorOffset + poHeader->nSectorSize > poHeader->nPayloadFileSize )
+            else if( nSectorOffset + poHeader->nSectorSize >
+                     poHeader->nPayloadFileSize )
             {
-                // If the last sector was padded with random values, decrypt it to 0 in case of update scenarios
+                // If the last sector was padded with random values,
+                // decrypt it to 0 in case of update scenarios.
                 CPLAssert( nSectorOffset < poHeader->nPayloadFileSize );
-                memset( pabyWB + poHeader->nPayloadFileSize - nSectorOffset, 0,
-                        nSectorOffset + poHeader->nSectorSize - poHeader->nPayloadFileSize );
+                memset(pabyWB + poHeader->nPayloadFileSize - nSectorOffset,
+                       0,
+                       nSectorOffset + poHeader->nSectorSize -
+                       poHeader->nPayloadFileSize );
             }
             nWBOffset = nSectorOffset;
             nWBSize = poHeader->nSectorSize;
@@ -1181,7 +1281,8 @@ size_t VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMem
 
     int nRet = static_cast<int>( (nSize * nMemb - nToWrite) / nSize );
 #ifdef VERBOSE_VSICRYPT
-    CPLDebug("VSICRYPT", "Write ret = %d (nMemb = %d)", nRet, (int)nMemb);
+    CPLDebug("VSICRYPT", "Write ret = %d (nMemb = %d)",
+             nRet, static_cast<int>(nMemb));
 #endif
     return nRet;
 }
@@ -1190,6 +1291,7 @@ size_t VSICryptFileHandle::Write( const void *pBuffer, size_t nSize, size_t nMem
 /*                             Truncate()                               */
 /************************************************************************/
 
+// Returns 0 on success.  Returns -1 on error.
 int VSICryptFileHandle::Truncate( vsi_l_offset nNewSize )
 {
 #ifdef VERBOSE_VSICRYPT
@@ -1200,10 +1302,12 @@ int VSICryptFileHandle::Truncate( vsi_l_offset nNewSize )
 
     if( !FlushDirty() )
         return -1;
-    if( poBaseHandle->Truncate( poHeader->nHeaderSize +
-            ((nNewSize + poHeader->nSectorSize - 1) / poHeader->nSectorSize) * poHeader->nSectorSize ) != 0 )
+    if( poBaseHandle->Truncate(
+            poHeader->nHeaderSize +
+            ((nNewSize + poHeader->nSectorSize - 1) / poHeader->nSectorSize) *
+            poHeader->nSectorSize ) != 0 )
         return -1;
-    bUpdateHeader = TRUE;
+    bUpdateHeader = true;
     poHeader->nPayloadFileSize = nNewSize;
     return 0;
 }
@@ -1215,7 +1319,7 @@ int VSICryptFileHandle::Truncate( vsi_l_offset nNewSize )
 int VSICryptFileHandle::Eof()
 {
 #ifdef VERBOSE_VSICRYPT
-    CPLDebug("VSICRYPT", "Eof() = %d", bEOF);
+    CPLDebug("VSICRYPT", "Eof() = %d", static_cast<int>(bEOF));
 #endif
     return bEOF;
 }
@@ -1235,30 +1339,43 @@ int VSICryptFileHandle::Flush()
     }
     if( (nPerms & VSICRYPT_WRITE) )
     {
-        if( bLastSectorWasModified && (poHeader->nPayloadFileSize % poHeader->nSectorSize) != 0 )
+        if( bLastSectorWasModified &&
+            (poHeader->nPayloadFileSize % poHeader->nSectorSize) != 0 )
         {
-            vsi_l_offset nLastSectorOffset = (poHeader->nPayloadFileSize / poHeader->nSectorSize) * poHeader->nSectorSize;
-            if( poBaseHandle->Seek( poHeader->nHeaderSize + nLastSectorOffset, 0) == 0 &&
-                poBaseHandle->Read( pabyWB, poHeader->nSectorSize, 1 ) == 1 &&
+            const vsi_l_offset nLastSectorOffset =
+                (poHeader->nPayloadFileSize / poHeader->nSectorSize) *
+                poHeader->nSectorSize;
+            if( poBaseHandle->Seek(
+                    poHeader->nHeaderSize + nLastSectorOffset, 0) == 0 &&
+                poBaseHandle->Read(
+                    pabyWB, poHeader->nSectorSize, 1 ) == 1 &&
                 DecryptBlock( pabyWB, nLastSectorOffset) )
             {
                 // Fill with random
 #ifdef VERBOSE_VSICRYPT
-                CPLDebug("VSICRYPT", "Filling %d trailing bytes with random",
-                         (int)(poHeader->nSectorSize - (poHeader->nPayloadFileSize - nLastSectorOffset )));
+                CPLDebug(
+                    "VSICRYPT", "Filling %d trailing bytes with random",
+                    static_cast<int>(
+                        poHeader->nSectorSize -
+                        (poHeader->nPayloadFileSize - nLastSectorOffset)));
 #endif
-                CryptoPP::OS_GenerateRandomBlock(false /* we do not need cryptographic randomness */,
-                    (byte*)(pabyWB + poHeader->nPayloadFileSize - nLastSectorOffset),
-                    (int)(poHeader->nSectorSize - (poHeader->nPayloadFileSize - nLastSectorOffset )));
-
-                if( poBaseHandle->Seek( poHeader->nHeaderSize + nLastSectorOffset, 0) == 0)
+                CryptoPP::OS_GenerateRandomBlock(
+                    false, // Do not need cryptographic randomness.
+                    (byte*)(pabyWB +
+                            poHeader->nPayloadFileSize - nLastSectorOffset),
+                    static_cast<int>(
+                        poHeader->nSectorSize -
+                        (poHeader->nPayloadFileSize - nLastSectorOffset)));
+
+                if( poBaseHandle->Seek(
+                         poHeader->nHeaderSize + nLastSectorOffset, 0) == 0 )
                 {
                     EncryptBlock( pabyWB, nLastSectorOffset);
                     poBaseHandle->Write( pabyWB, poHeader->nSectorSize, 1 );
                 }
             }
         }
-        bLastSectorWasModified = FALSE;
+        bLastSectorWasModified = false;
         if( poBaseHandle->Flush() != 0 )
             return -1;
     }
@@ -1304,17 +1421,18 @@ class VSICryptFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 public:
     VSICryptFilesystemHandler();
-    ~VSICryptFilesystemHandler();
-
-    using VSIFilesystemHandler::Open;
+    virtual ~VSICryptFilesystemHandler();
 
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
-    virtual int      Unlink( const char *pszFilename );
-    virtual int      Rename( const char *oldpath, const char *newpath );
-    virtual char**   ReadDirEx( const char *pszDirname, int nMaxFiles );
+                                    bool bSetError ) override;
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
+    virtual int      Unlink( const char *pszFilename ) override;
+    virtual int      Rename( const char *oldpath, const char *newpath )
+        override;
+    virtual char**   ReadDirEx( const char *pszDirname, int nMaxFiles )
+        override;
 };
 
 /************************************************************************/
@@ -1337,12 +1455,13 @@ VSICryptFilesystemHandler::~VSICryptFilesystemHandler()
 /*                             GetFilename()                            */
 /************************************************************************/
 
-static CPLString GetFilename(const char* pszFilename)
+static CPLString GetFilename( const char* pszFilename )
 {
     if( strcmp(pszFilename, VSICRYPT_PREFIX_WITHOUT_SLASH) == 0 )
         pszFilename = VSICRYPT_PREFIX;
 
-    CPLAssert( strncmp(pszFilename, VSICRYPT_PREFIX, strlen(VSICRYPT_PREFIX)) == 0 );
+    CPLAssert( strncmp(pszFilename, VSICRYPT_PREFIX,
+                       strlen(VSICRYPT_PREFIX)) == 0 );
     pszFilename += strlen(VSICRYPT_PREFIX);
     const char* pszFileArg = strstr(pszFilename, "file=");
     if( pszFileArg == NULL )
@@ -1355,8 +1474,8 @@ static CPLString GetFilename(const char* pszFilename)
 /*                             GetArgument()                            */
 /************************************************************************/
 
-static CPLString GetArgument(const char* pszFilename, const char* pszParamName,
-                             const char* pszDefault = "")
+static CPLString GetArgument( const char* pszFilename, const char* pszParamName,
+                              const char* pszDefault = "" )
 {
     CPLString osParamName(pszParamName);
     osParamName += "=";
@@ -1376,17 +1495,30 @@ static CPLString GetArgument(const char* pszFilename, const char* pszParamName,
 /*                               GetKey()                               */
 /************************************************************************/
 
-static CPLString GetKey(const char* pszFilename)
+static CPLString GetKey( const char* pszFilename )
 {
     CPLString osKey = GetArgument(pszFilename, "key");
-    if( osKey.size() == 0 )
-        osKey = CPLGetConfigOption("VSICRYPT_KEY", "");
-    if( osKey.size() == 0 || EQUAL(osKey, "GENERATE_IT") )
+    // TODO(schwehr): Make 10U and 1024U into symbolic constants.
+    if( osKey.empty() )
+    {
+        const char* pszKey = CPLGetConfigOption("VSICRYPT_KEY", "");
+        // Do some form of validation to please Coverity
+        CPLAssert( strlen(pszKey) < 10U * 1024U );
+        // coverity [tainted_data_transitive]
+        osKey = pszKey;
+    }
+    if( osKey.empty() || EQUAL(osKey, "GENERATE_IT") )
     {
         CPLString osKeyB64(GetArgument(pszFilename, "key_b64"));
-        if( osKeyB64.size() == 0 )
-            osKeyB64 = CPLGetConfigOption("VSICRYPT_KEY_B64", "");
-        if( osKeyB64.size() )
+        if( osKeyB64.empty() )
+        {
+            const char* pszKey = CPLGetConfigOption("VSICRYPT_KEY_B64", "");
+            // Do some form of validation to please Coverity
+            CPLAssert( strlen(pszKey) < 10U * 1024U );
+            // coverity [tainted_data_transitive]
+            osKeyB64 = pszKey;
+        }
+        if( !osKeyB64.empty() )
         {
             GByte* key = (GByte*)CPLStrdup(osKeyB64);
             int nLength = CPLBase64DecodeInPlace(key);
@@ -1413,11 +1545,12 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
     CPLString osFilename(GetFilename(pszFilename));
 
     CPLString osKey(GetKey(pszFilename));
-    if( osKey.size() == 0 && pabyGlobalKey == NULL )
+    if( osKey.empty() && pabyGlobalKey == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                 "Encryption key not defined as key/key_b64 parameter, "
-                "VSICRYPT_KEY/VSICRYPT_KEY_B64 configuration option or VSISetCryptKey() API");
+                "VSICRYPT_KEY/VSICRYPT_KEY_B64 configuration option or "
+                 "VSISetCryptKey() API");
         return NULL;
     }
 
@@ -1426,7 +1559,8 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
         CPLString osAccess(pszAccess);
         if( strchr(pszAccess, 'b') == NULL )
             osAccess += "b";
-        VSIVirtualHandle* fpBase = (VSIVirtualHandle*)VSIFOpenL(osFilename, osAccess);
+        VSIVirtualHandle* fpBase =
+            (VSIVirtualHandle*)VSIFOpenL(osFilename, osAccess);
         if( fpBase == NULL )
             return NULL;
         VSICryptFileHeader* poHeader = new VSICryptFileHeader();
@@ -1439,9 +1573,13 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
             return NULL;
         }
 
-        VSICryptFileHandle* poHandle = new VSICryptFileHandle( osFilename, fpBase, poHeader,
-                    strchr(pszAccess, '+') ? VSICRYPT_READ | VSICRYPT_WRITE : VSICRYPT_READ);
-        if( !poHandle->Init(osKey, FALSE) )
+        VSICryptFileHandle* poHandle =
+            new VSICryptFileHandle(
+                osFilename, fpBase, poHeader,
+                strchr(pszAccess, '+')
+                ? VSICRYPT_READ | VSICRYPT_WRITE
+                : VSICRYPT_READ);
+        if( !poHandle->Init(osKey, false) )
         {
             memset((void*)osKey.c_str(), 0, osKey.size());
             delete poHandle;
@@ -1453,28 +1591,37 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
     else if( strchr(pszAccess, 'w' ) )
     {
         CPLString osAlg(GetArgument(pszFilename, "alg",
-                                              CPLGetConfigOption("VSICRYPT_ALG", "AES")));
+                                    CPLGetConfigOption("VSICRYPT_ALG", "AES")));
         VSICryptAlg eAlg = GetAlg(osAlg);
 
-        VSICryptMode eMode = GetMode(GetArgument(pszFilename, "mode",
-                                              CPLGetConfigOption("VSICRYPT_MODE", "CBC")));
+        VSICryptMode eMode =
+            GetMode(GetArgument(pszFilename, "mode",
+                                CPLGetConfigOption("VSICRYPT_MODE", "CBC")));
 
-        CPLString osFreeText = GetArgument(pszFilename, "freetext",
-                                           CPLGetConfigOption("VSICRYPT_FREETEXT", ""));
+        CPLString osFreeText =
+            GetArgument(pszFilename, "freetext",
+                        CPLGetConfigOption("VSICRYPT_FREETEXT", ""));
 
         CPLString osIV = GetArgument(pszFilename, "iv",
-                                           CPLGetConfigOption("VSICRYPT_IV", ""));
+                                           CPLGetConfigOption("VSICRYPT_IV",
+                                                              ""));
 
-        int nSectorSize = atoi(GetArgument(pszFilename, "sector_size",
-                                           CPLGetConfigOption("VSICRYPT_SECTOR_SIZE", "512")));
+        int nSectorSize =
+            atoi(GetArgument(pszFilename, "sector_size",
+                             CPLGetConfigOption("VSICRYPT_SECTOR_SIZE",
+                                                "512")));
         if( nSectorSize <= 0 || nSectorSize >= 65535 )
         {
-            CPLError(CE_Warning, CPLE_NotSupported, "Invalid value for sector_size. Defaulting to 512.");
+            CPLError(CE_Warning, CPLE_NotSupported,
+                     "Invalid value for sector_size. Defaulting to 512.");
             nSectorSize = 512;
         }
 
-        int bAddKeyCheck = CSLTestBoolean(GetArgument(pszFilename, "add_key_check",
-                                           CPLGetConfigOption("VSICRYPT_ADD_KEY_CHECK", "NO")));
+        const bool bAddKeyCheck =
+            CPLTestBool(
+                GetArgument(pszFilename, "add_key_check",
+                            CPLGetConfigOption("VSICRYPT_ADD_KEY_CHECK",
+                                               "NO")));
 
         /* Generate random initial vector */
         CryptoPP::BlockCipher* poBlock = GetEncBlockCipher(eAlg);
@@ -1491,43 +1638,52 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
         int nBlockSize = static_cast<int>(poBlock->BlockSize());
         delete poBlock;
 
-        if( osIV.size() != 0 )
+        if( !osIV.empty() )
         {
-            if( (int)osIV.size() != nBlockSize )
+            if( static_cast<int>(osIV.size()) != nBlockSize )
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "IV should be %d byte large",
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "IV should be %d byte large",
                          nBlockSize);
-                memset((void*)osKey.c_str(), 0, osKey.size());
+                memset(const_cast<char *>(osKey.c_str()), 0, osKey.size());
                 return NULL;
             }
         }
         else
         {
             osIV.resize(nBlockSize);
-            CryptoPP::OS_GenerateRandomBlock(false /* we do not need cryptographic randomness */,
-                                            (byte*)osIV.c_str(), osIV.size());
+            CryptoPP::OS_GenerateRandomBlock(
+                false,  // Do not need cryptographic randomness.
+                (byte*)osIV.c_str(), osIV.size());
         }
 
         if( EQUAL(osKey, "GENERATE_IT") )
         {
             osKey.resize(nMaxKeySize);
-            CPLDebug("VSICRYPT", "Generating key. This might take some time...");
+            CPLDebug("VSICRYPT",
+                     "Generating key. This might take some time...");
             CryptoPP::OS_GenerateRandomBlock(
-                /* we need cryptographic randomness (config option for speeding tests) */
-                CSLTestBoolean(CPLGetConfigOption("VSICRYPT_CRYPTO_RANDOM", "TRUE")) != FALSE,
+                // Need cryptographic randomness.
+                // Config option for speeding tests.
+                CPLTestBool(CPLGetConfigOption("VSICRYPT_CRYPTO_RANDOM",
+                                               "TRUE")),
                 (byte*)osKey.c_str(), osKey.size());
 
-            char* pszB64 = CPLBase64Encode(static_cast<int>(osKey.size()), (const GByte*)osKey.c_str());
-            if( CSLTestBoolean(CPLGetConfigOption("VSICRYPT_DISPLAY_GENERATED_KEY", "TRUE")) )
+            char* pszB64 = CPLBase64Encode(static_cast<int>(osKey.size()),
+                                           (const GByte*)osKey.c_str());
+            if( CPLTestBool(CPLGetConfigOption("VSICRYPT_DISPLAY_GENERATED_KEY",
+                                               "TRUE")) )
             {
-                fprintf(stderr, "BASE64 key '%s' has been generated, and installed in "
-                        "the VSICRYPT_KEY_B64 configuration option.\n", pszB64);
+                CPLError(CE_Failure, CPLE_AppDefined,
+                        "BASE64 key '%s' has been generated, and installed in "
+                        "the VSICRYPT_KEY_B64 configuration option.", pszB64);
             }
             CPLSetConfigOption("VSICRYPT_KEY_B64", pszB64);
             CPLFree(pszB64);
         }
 
-        int nKeyLength = ( osKey.size() ) ? (int)osKey.size() : nGlobalKeySize;
+        const int nKeyLength =
+            !osKey.empty() ? static_cast<int>(osKey.size()) : nGlobalKeySize;
         if( nKeyLength < nMinKeySize )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
@@ -1537,7 +1693,8 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
             return NULL;
         }
 
-        VSIVirtualHandle* fpBase = (VSIVirtualHandle*)VSIFOpenL(osFilename, "wb+");
+        VSIVirtualHandle* fpBase =
+            reinterpret_cast<VSIVirtualHandle *>(VSIFOpenL(osFilename, "wb+"));
         if( fpBase == NULL )
         {
             memset((void*)osKey.c_str(), 0, osKey.size());
@@ -1552,9 +1709,13 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
         poHeader->osFreeText = osFreeText;
         poHeader->bAddKeyCheck = bAddKeyCheck;
 
-        VSICryptFileHandle* poHandle = new VSICryptFileHandle( osFilename, fpBase, poHeader,
-                    strchr(pszAccess, '+') ? VSICRYPT_READ | VSICRYPT_WRITE : VSICRYPT_WRITE);
-        if( !poHandle->Init(osKey, TRUE) )
+        VSICryptFileHandle* poHandle =
+            new VSICryptFileHandle(
+                osFilename, fpBase, poHeader,
+                strchr(pszAccess, '+')
+                ? VSICRYPT_READ | VSICRYPT_WRITE
+                : VSICRYPT_WRITE);
+        if( !poHandle->Init(osKey, true) )
         {
             memset((void*)osKey.c_str(), 0, osKey.size());
             delete poHandle;
@@ -1565,11 +1726,12 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
     }
     else if( strchr(pszAccess, 'a') )
     {
-        VSIVirtualHandle* fpBase = (VSIVirtualHandle*)VSIFOpenL(osFilename, "rb+");
+        VSIVirtualHandle* fpBase =
+            reinterpret_cast<VSIVirtualHandle *>(VSIFOpenL(osFilename, "rb+"));
         if( fpBase == NULL )
         {
             memset((void*)osKey.c_str(), 0, osKey.size());
-            return Open(pszFilename, "wb+");
+            return VSIFilesystemHandler::Open(pszFilename, "wb+");
         }
         VSICryptFileHeader* poHeader = new VSICryptFileHeader();
         if( !poHeader->ReadFromFile(fpBase, osKey) )
@@ -1581,8 +1743,9 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
             return NULL;
         }
 
-        VSICryptFileHandle* poHandle = new VSICryptFileHandle( osFilename, fpBase, poHeader,
-                                                               VSICRYPT_READ | VSICRYPT_WRITE );
+        VSICryptFileHandle* poHandle =
+            new VSICryptFileHandle( osFilename, fpBase, poHeader,
+                                    VSICRYPT_READ | VSICRYPT_WRITE );
         if( !poHandle->Init(osKey) )
         {
             delete poHandle;
@@ -1601,7 +1764,8 @@ VSIVirtualHandle *VSICryptFilesystemHandler::Open( const char *pszFilename,
 /*                                Stat()                                */
 /************************************************************************/
 
-int VSICryptFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags )
+int VSICryptFilesystemHandler::Stat( const char *pszFilename,
+                                     VSIStatBufL *pStatBuf, int nFlags )
 {
 #ifdef VERBOSE_VSICRYPT
     CPLDebug("VSICRYPT", "Stat(%s)", pszFilename);
@@ -1648,7 +1812,8 @@ int VSICryptFilesystemHandler::Unlink( const char *pszFilename )
 /*                               Rename()                               */
 /************************************************************************/
 
-int VSICryptFilesystemHandler::Rename( const char *oldpath, const char* newpath )
+int VSICryptFilesystemHandler::Rename( const char *oldpath,
+                                       const char* newpath )
 {
     CPLString osNewPath;
     if( strncmp(newpath, VSICRYPT_PREFIX, strlen(VSICRYPT_PREFIX)) == 0 )
@@ -1696,102 +1861,119 @@ static GDALDataset* VSICryptOpen(GDALOpenInfo* poOpenInfo)
 {
     if( !VSICryptIdentify(poOpenInfo) )
         return NULL;
-    return (GDALDataset*)GDALOpen( (CPLString(VSICRYPT_PREFIX) + poOpenInfo->pszFilename).c_str(),
-                     poOpenInfo->eAccess );
+    return (GDALDataset*)GDALOpen(
+        (CPLString(VSICRYPT_PREFIX) + poOpenInfo->pszFilename).c_str(),
+        poOpenInfo->eAccess );
 }
 
 #endif
 
+//! @endcond
+
 /************************************************************************/
 /*                   VSIInstallCryptFileHandler()                       */
 /************************************************************************/
 
 /**
- * \brief Install /vsicrypt/ encrypted file system handler (requires <a href="http://www.cryptopp.com/">libcrypto++</a>)
+ * \brief Install /vsicrypt/ encrypted file system handler
+ * (requires <a href="http://www.cryptopp.com/">libcrypto++</a>)
  *
- * A special file handler is installed that allows reading/creating/update encrypted
- * files on the fly, with random access capabilities.
+ * A special file handler is installed that allows reading/creating/update
+ * encrypted files on the fly, with random access capabilities.
  *
  * The cryptographic algorithms used are
- * <a href="https://en.wikipedia.org/wiki/Block_cipher">block ciphers</a>, with symmetric key.
+ * <a href="https://en.wikipedia.org/wiki/Block_cipher">block ciphers</a>,
+ * with symmetric key.
  *
- * In their simplest form, recognized filenames are of the form /vsicrypt//absolute_path/to/file,
- * /vsicrypt/c:/absolute_path/to/file or /vsicrypt/relative/path/to/file.
+ * In their simplest form, recognized filenames are of the form
+ * /vsicrypt//absolute_path/to/file, /vsicrypt/c:/absolute_path/to/file or
+ * /vsicrypt/relative/path/to/file.
  *
  * Options can also be used with the following format :
  * /vsicrypt/option1=val1,option2=val2,...,file=/path/to/file
  *
  * They can also be passed as configuration option/environment variable, because
- * in some use cases, the syntax with option in the filename might not properly work with some drivers.
+ * in some use cases, the syntax with option in the filename might not properly
+ * work with some drivers.
  *
  * In all modes, the encryption key must be provided. There are several ways
  * of doing so :
  * <ul>
- * <li>By adding a key= parameter to the filename, like /vsicrypt/key=my_secret_key,file=/path/to/file.
- *     Note that this restricts the key to be in text format, whereas at its full power,
- *     it can be binary content.</li>
- * <li>By adding a key_b64= parameter to the filename, to specify a binary key expressed
- *     in Base64 encoding, like /vsicrypt/key_b64=th1sl00kslikebase64=,file=/path/to/file.</li>
- * <li>By setting the VSICRYPT_KEY configuration option. The key should be in text format.</li>
- * <li>By setting the VSICRYPT_KEY_B64 configuration option. The key should be encoded in Base64.</li>
+ * <li>By adding a key= parameter to the filename, like
+ *     /vsicrypt/key=my_secret_key,file=/path/to/file.  Note that this restricts
+ *     the key to be in text format, whereas at its full power, it can be binary
+ *     content.</li>
+ * <li>By adding a key_b64= parameter to the filename, to specify a binary key
+ *     expressed in Base64 encoding, like
+ *     /vsicrypt/key_b64=th1sl00kslikebase64=,file=/path/to/file.</li>
+ * <li>By setting the VSICRYPT_KEY configuration option. The key should be in
+ * text format.</li>
+ * <li>By setting the VSICRYPT_KEY_B64 configuration option. The key should be
+ * encoded in Base64.</li>
  * <li>By using the VSISetCryptKey() C function.</li>
  * </ul>
  *
- * When creating a file, if key=GENERATE_IT or VSICRYPT_KEY=GENERATE_IT is passed,
- * the encryption key will be generated from the pseudo-random number generator of the
- * operating system. The key will be displayed on the standard error stream in a Base64 form
- * (unless the VSICRYPT_DISPLAY_GENERATED_KEY configuration option is set to OFF),
- * and the VSICRYPT_KEY_B64 configuration option will also be set with the Base64 form
- * of the key (so that CPLGetConfigOption("VSICRYPT_KEY_B64", NULL) can be used to get it back).
+ * When creating a file, if key=GENERATE_IT or VSICRYPT_KEY=GENERATE_IT is
+ * passed, the encryption key will be generated from the pseudo-random number
+ * generator of the operating system. The key will be displayed on the standard
+ * error stream in a Base64 form (unless the VSICRYPT_DISPLAY_GENERATED_KEY
+ * configuration option is set to OFF), and the VSICRYPT_KEY_B64 configuration
+ * option will also be set with the Base64 form of the key (so that
+ * CPLGetConfigOption("VSICRYPT_KEY_B64", NULL) can be used to get it back).
  *
  * The available options are :
  * <ul>
+
  * <li>alg=AES/Blowfish/Camellia/CAST256/DES_EDE2/DES_EDE3/MARS/IDEA/RC5/RC6/Serpent/SHACAL2/SKIPJACK/Twofish/XTEA:
- *     to specify the <a href="https://en.wikipedia.org/wiki/Block_cipher">block cipher</a> algorithm.
- *     The default is AES.
- *     Only used on creation. Ignored otherwise.
- *     Note: depending on how GDAL is build, if linked against the DLL version of libcrypto++,
- *     only a subset of those algorithms will be available, namely AES, DES_EDE2, DES_EDE3 and SKIPJACK.
- *     Also available as VSICRYPT_ALG configuration option.</li>
- * <li>mode=CBC/CFB/OFB/CTR/CBC_CTS: to specify the <a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation">block cipher mode of operation</a>.
+ *     to specify the <a href="https://en.wikipedia.org/wiki/Block_cipher">block
+ *     cipher</a> algorithm.  The default is AES.  Only used on
+ *     creation. Ignored otherwise.  Note: depending on how GDAL is build, if
+ *     linked against the DLL version of libcrypto++, only a subset of those
+ *     algorithms will be available, namely AES, DES_EDE2, DES_EDE3 and
+ *     SKIPJACK.  Also available as VSICRYPT_ALG configuration option.</li>
+ * <li>mode=CBC/CFB/OFB/CTR/CBC_CTS: to specify the
+ *     <a href="https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation">
+ *       block cipher mode of operation</a>.
  *     The default is CBC.
  *     Only used on creation. Ignored otherwise.
  *     Also available as VSICRYPT_MODE configuration option.</li>
  * <li>key=text_key: see above.</li>
  * <li>key_b64=base64_encoded_key: see above.</li>
- * <li>freetext=some_text: to specify a text content that will be written *unencrypted*
- *     in the file header, for informational purposes. Default to empty.
- *     Only used on creation. Ignored otherwise.
+ * <li>freetext=some_text: to specify a text content that will be written
+ *     *unencrypted* in the file header, for informational purposes. Default to
+ *     empty.  Only used on creation. Ignored otherwise.
  *     Also available as VSICRYPT_FREETEXT configuration option.</li>
  * <li>sector_size=int_value: to specify the size of the "sector", which is the
- *     unit chunk of information that is encrypted/decrypted. Default to 512 bytes.
- *     The valid values depend on the algorithm and block cipher mode of operation.
- *     Only used on creation. Ignored otherwise.
- *     Also available as VSICRYPT_SECTOR_SIZE configuration option.</li>
+ *     unit chunk of information that is encrypted/decrypted. Default to 512
+ *     bytes.  The valid values depend on the algorithm and block cipher mode of
+ *     operation.  Only used on creation. Ignored otherwise.  Also available as
+ *     VSICRYPT_SECTOR_SIZE configuration option.</li>
  * <li>iv=initial_vector_as_text: to specify the Initial Vector. This is an
- *     advanced option that should generally *NOT* be used. It is only useful
- *     to get completely deterministic output
- *     given the plaintext, key and other parameters, which in general *NOT* what
- *     you want to do. By default, a random initial vector of the appropriate size
- *     will be generated for each new file created.
- *     Only used on creation. Ignored otherwise.
- *     Also available as VSICRYPT_IV configuration option.</li>
- * <li>add_key_check=YES/NO: whether a special value should be encrypted in the header,
- *     so as to be quickly able to determine if the decryption key is correct.
- *     Defaults to NO.
- *     Only used on creation. Ignored otherwise.
+ *     advanced option that should generally *NOT* be used. It is only useful to
+ *     get completely deterministic output given the plaintext, key and other
+ *     parameters, which in general *NOT* what you want to do. By default, a
+ *     random initial vector of the appropriate size will be generated for each
+ *     new file created.  Only used on creation. Ignored otherwise.  Also
+ *     available as VSICRYPT_IV configuration option.</li>
+
+ * <li>add_key_check=YES/NO: whether a special value should be encrypted in the
+ *     header, so as to be quickly able to determine if the decryption key is
+ *     correct.  Defaults to NO.  Only used on creation. Ignored otherwise.
  *     Also available as VSICRYPT_ADD_KEY_CHECK configuration option.</li>
- * <li>file=filename. To specify the filename. This must be the last option put in the
- *     option list (so as to make it possible to use filenames with comma in them. )
+ * <li>file=filename. To specify the filename. This must be the last option put
+ *     in the option list (so as to make it possible to use filenames with comma
+ *     in them. )
  * </ul>
  *
- * This special file handler can be combined with other virtual filesystems handlers,
- * such as /vsizip. For example, /vsicrypt//vsicurl/path/to/remote/encrypted/file.tif
+ * This special file handler can be combined with other virtual filesystems
+ * handlers, such as /vsizip. For example,
+ * /vsicrypt//vsicurl/path/to/remote/encrypted/file.tif
  *
  * Implementation details:
  *
  * The structure of encrypted files is the following: a header, immediately
- * followed by the encrypted payload (by sectors, i.e. chunks of sector_size bytes).
+ * followed by the encrypted payload (by sectors, i.e. chunks of sector_size
+ * bytes).
  *
  * The header structure is the following :
  * <ol>
@@ -1800,74 +1982,85 @@ static GDALDataset* VSICryptOpen(GDALOpenInfo* poOpenInfo)
  * <li>UINT8. Format major version. Current value: 1.</li>
  * <li>UINT8. Format minor version. Current value: 0.</li>
  * <li>UINT16. Sector size.</li>
- * <li>UINT8. Cipher algorithm. Valid values are: 0 = AES (Rijndael), 1 = Blowfish, 2 = Camellia, 3 = CAST256,
- *     4 = DES_EDE2, 5 = DES_EDE3, 6 = MARS, 7 = IDEA, 8 = RC5, 9 = RC6, 10 = Serpent, 11 = SHACAL2,
- *     12 = SKIPJACK, 13 = Twofish, 14 = XTEA.</li>
- * <li>UINT8. Block cipher mode of operation. Valid values are: 0 = CBC, 1 = CFB, 2 = OFB, 3 = CTR, 4 = CBC_CTS.</li>
+ * <li>UINT8. Cipher algorithm. Valid values are: 0 = AES (Rijndael), 1 =
+ *     Blowfish, 2 = Camellia, 3 = CAST256, 4 = DES_EDE2, 5 = DES_EDE3, 6 =
+ *     MARS, 7 = IDEA, 8 = RC5, 9 = RC6, 10 = Serpent, 11 = SHACAL2, 12 =
+ *     SKIPJACK, 13 = Twofish, 14 = XTEA.</li>
+ * <li>UINT8. Block cipher mode of operation. Valid values are: 0 = CBC, 1 =
+ *     CFB, 2 = OFB, 3 = CTR, 4 = CBC_CTS.</li>
  * <li>UINT8. Size in bytes of the Initial Vector.</li>
- * <li>N bytes with the content of the Initial Vector, where N is the value of the previous field.</li>
+ * <li>N bytes with the content of the Initial Vector, where N is the value of
+ *     the previous field.</li>
  * <li>UINT16_LE. Size in bytes of the free text.</li>
- * <li>N bytes with the content of the free text, where N is the value of the previous field.</li>
- * <li>UINT8. Size in bytes of encrypted content (key check), or 0 if key check is absent.</li>
- * <li>N bytes with encrypted content (key check), where N is the value of the previous field.</li>
+ * <li>N bytes with the content of the free text, where N is the value of the
+ *     previous field.</li>
+ * <li>UINT8. Size in bytes of encrypted content (key check), or 0 if key check
+ *     is absent.</li>
+ * <li>N bytes with encrypted content (key check), where N is the value of the
+ *     previous field.</li>
  * <li>UINT64_LE. Size of the unencrypted file, in bytes.</li>
- * <li>UINT16_LE. Size in bytes of extra content (of unspecified semantics). For v1.0, fixed value of 0</li>
- * <li>N bytes with extra content (of unspecified semantics), where N is the value of the previous field.</li>
+ * <li>UINT16_LE. Size in bytes of extra content (of unspecified semantics). For
+ *     v1.0, fixed value of 0</li>
+ * <li>N bytes with extra content (of unspecified semantics), where N is the
+ *     value of the previous field.</li>
  * </ol>
  *
  * This design does not provide any means of authentication or integrity check.
  *
- * Each sector is encrypted/decrypted independently of other sectors.
- * For that, the Initial Vector contained in the header is XOR'ed with the file offset
- * (relative to plain text file) of the start of the sector being processed, as a 8-byte integer.
- * More precisely, the first byte of the main IV is XOR'ed with the 8 least-significant
- * bits of the sector offset, the second byte of the main IV is XOR'ed with the following
- * 8 bits of the sector offset, etc... until the 8th byte.
+ * Each sector is encrypted/decrypted independently of other sectors.  For that,
+ * the Initial Vector contained in the header is XOR'ed with the file offset
+ * (relative to plain text file) of the start of the sector being processed, as
+ * a 8-byte integer.  More precisely, the first byte of the main IV is XOR'ed
+ * with the 8 least-significant bits of the sector offset, the second byte of
+ * the main IV is XOR'ed with the following 8 bits of the sector offset,
+ * etc... until the 8th byte.
  *
- * This design could potentially be prone to chosen-plaintext attack, for example
- * if the attacker managed to get (part of) an existing encrypted file to be encrypted from
- * plaintext he might have selected.
+ * This design could potentially be prone to chosen-plaintext attack, for
+ * example if the attacker managed to get (part of) an existing encrypted file
+ * to be encrypted from plaintext he might have selected.
  *
  * Note: if "hostile" code can explore process content, or attach to it with a
- * debugger, it might be relatively easy to retrieve the encryption key.
- * A GDAL plugin could for example get the content of configuration options, or
- * list opened datasets and see the key/key_b64 values, so disabling plugin loading
- * might be a first step, as well as linking statically GDAL to application code.
- * If plugin loading is enabled or GDAL dynamically linked, using VSISetCryptKey()
- * to set the key might make it a bit more complicated to spy the key.
- * But, as said initially, this is in no way a perfect protection.
+ * debugger, it might be relatively easy to retrieve the encryption key.  A GDAL
+ * plugin could for example get the content of configuration options, or list
+ * opened datasets and see the key/key_b64 values, so disabling plugin loading
+ * might be a first step, as well as linking statically GDAL to application
+ * code.  If plugin loading is enabled or GDAL dynamically linked, using
+ * VSISetCryptKey() to set the key might make it a bit more complicated to spy
+ * the key.  But, as said initially, this is in no way a perfect protection.
  *
  * @since GDAL 2.1.0
  */
 void VSIInstallCryptFileHandler(void)
 
 {
-    VSIFileManager::InstallHandler( VSICRYPT_PREFIX, new VSICryptFilesystemHandler );
+    VSIFileManager::InstallHandler( VSICRYPT_PREFIX,
+                                    new VSICryptFilesystemHandler );
 
 #ifdef VSICRYPT_DRIVER
-    if( GDALGetDriverByName( "VSICRYPT" ) == NULL )
-    {
-        GDALDriver      *poDriver = new GDALDriver();
+    if( GDALGetDriverByName( "VSICRYPT" ) != NULL )
+        return;
 
-        poDriver->SetDescription( "VSICRYPT" );
+    GDALDriver *poDriver = new GDALDriver();
+
+    poDriver->SetDescription( "VSICRYPT" );
 #ifdef GDAL_DCAP_RASTER
-        poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
-        poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_RASTER, "YES" );
+    poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
 #endif
-        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
-                                   CPLSPrintf("Wrapper for %s files", VSICRYPT_PREFIX) );
+    poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
+                               CPLSPrintf("Wrapper for %s files",
+                                          VSICRYPT_PREFIX) );
 
-        poDriver->pfnOpen = VSICryptOpen;
-        poDriver->pfnIdentify = VSICryptIdentify;
+    poDriver->pfnOpen = VSICryptOpen;
+    poDriver->pfnIdentify = VSICryptIdentify;
 
-        GetGDALDriverManager()->RegisterDriver( poDriver );
-    }
+    GetGDALDriverManager()->RegisterDriver( poDriver );
 #endif
 }
 
-//#ifdef _MSC_VER
-//#pragma warning( pop ) /* 5105 */
-//#endif
+// #ifdef _MSC_VER
+// #pragma warning( pop ) /* 5105 */
+// #endif
 
 #else /* HAVE_CRYPTOPP */
 
@@ -1876,17 +2069,17 @@ class VSIDummyCryptFilesystemHandler : public VSIFilesystemHandler
 public:
     VSIDummyCryptFilesystemHandler() {}
 
-    virtual VSIVirtualHandle *Open( CPL_UNUSED const char *pszFilename,
-                                    CPL_UNUSED const char *pszAccess,
-                                    bool)
+    virtual VSIVirtualHandle *Open( const char * /* pszFilename */,
+                                    const char * /* pszAccess */,
+                                    bool /* bSetError */ ) override
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "%s support not available in this build", VSICRYPT_PREFIX);
         return NULL;
     }
 
-    virtual int Stat( CPL_UNUSED const char *pszFilename,
-                      CPL_UNUSED VSIStatBufL *pStatBuf, CPL_UNUSED int nFlags )
+    virtual int Stat( const char * /* pszFilename */,
+                      VSIStatBufL * /*pStatBuf */, int /* nFlags */ ) override
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "%s support not available in this build", VSICRYPT_PREFIX);
@@ -1896,17 +2089,18 @@ public:
 
 void VSIInstallCryptFileHandler(void)
 {
-    VSIFileManager::InstallHandler( VSICRYPT_PREFIX, new VSIDummyCryptFilesystemHandler );
+    VSIFileManager::InstallHandler( VSICRYPT_PREFIX,
+                                    new VSIDummyCryptFilesystemHandler );
 }
 
-void VSISetCryptKey(CPL_UNUSED const GByte* pabyKey, CPL_UNUSED int nKeySize)
+void VSISetCryptKey( const GByte* /* pabyKey */, int /* nKeySize */ )
 {
-    /* not supported */
+    // Not supported.
 }
 
-#endif /* HAVE_CRYPTOPP */
+#endif  // HAVE_CRYPTOPP
 
-/* Below is only useful if using as a plugin over GDAL 1.11 or GDAL 2.0 */
+// Below is only useful if using as a plugin over GDAL 1.11 or GDAL 2.0.
 #ifdef VSICRYPT_AUTOLOAD
 
 CPL_C_START
@@ -1915,7 +2109,8 @@ CPL_C_END
 
 void GDALRegisterMe()
 {
-    if( VSIFileManager::GetHandler(VSICRYPT_PREFIX) == VSIFileManager::GetHandler(".") )
+    if( VSIFileManager::GetHandler(VSICRYPT_PREFIX) ==
+        VSIFileManager::GetHandler(".") )
         VSIInstallCryptFileHandler();
 }
 
@@ -1926,7 +2121,8 @@ CPL_C_END
 
 void RegisterOGRCRYPT()
 {
-    if( VSIFileManager::GetHandler(VSICRYPT_PREFIX) == VSIFileManager::GetHandler(".") )
+    if( VSIFileManager::GetHandler(VSICRYPT_PREFIX) ==
+        VSIFileManager::GetHandler(".") )
         VSIInstallCryptFileHandler();
 }
 #endif
diff --git a/port/cpl_vsil_curl.cpp b/port/cpl_vsil_curl.cpp
index e528c88..2b4ebb0 100644
--- a/port/cpl_vsil_curl.cpp
+++ b/port/cpl_vsil_curl.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl.cpp 35828 2016-10-19 23:23:39Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for HTTP/FTP files
@@ -27,57 +26,73 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi_virtual.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
-#include "cpl_hash_set.h"
-#include "cpl_time.h"
+#include "cpl_port.h"
 #include "cpl_vsil_curl_priv.h"
+
+#include <algorithm>
+
 #include "cpl_aws.h"
+#include "cpl_google_cloud.h"
+#include "cpl_hash_set.h"
 #include "cpl_minixml.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_time.h"
+#include "cpl_vsi.h"
+#include "cpl_vsi_virtual.h"
+#include "cpl_http.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl.cpp 35828 2016-10-19 23:23:39Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl.cpp 37987 2017-04-14 07:42:50Z rouault $");
 
 #ifndef HAVE_CURL
 
-void VSIInstallCurlFileHandler(void)
+void VSIInstallCurlFileHandler( void )
+{
+    // Not supported.
+}
+
+void VSIInstallS3FileHandler( void )
 {
-    /* not supported */
+    // Not supported.
 }
 
-void VSIInstallS3FileHandler(void)
+void VSIInstallGSFileHandler( void )
 {
-    /* not supported */
+    // Not supported.
 }
 
 /************************************************************************/
 /*                      VSICurlInstallReadCbk()                         */
 /************************************************************************/
 
-int VSICurlInstallReadCbk (CPL_UNUSED VSILFILE* fp,
-                           CPL_UNUSED VSICurlReadCbkFunc pfnReadCbk,
-                           CPL_UNUSED void* pfnUserData,
-                           CPL_UNUSED int bStopOnInterrruptUntilUninstall)
+int VSICurlInstallReadCbk ( VSILFILE* /* fp */,
+                            VSICurlReadCbkFunc /* pfnReadCbk */,
+                            void* /* pfnUserData */,
+                            int /* bStopOnInterruptUntilUninstall */)
 {
     return FALSE;
 }
 
-
 /************************************************************************/
 /*                    VSICurlUninstallReadCbk()                         */
 /************************************************************************/
 
-int VSICurlUninstallReadCbk(CPL_UNUSED VSILFILE* fp)
+int VSICurlUninstallReadCbk( VSILFILE* /* fp */ )
 {
     return FALSE;
 }
 
 #else
 
+//! @cond Doxygen_Suppress
+#ifndef DOXYGEN_SKIP
+
 #include <curl/curl.h>
 
-void CPLHTTPSetOptions(CURL *http_handle, char** papszOptions);
-void VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL);
+struct curl_slist* VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL,
+                       const char * const* papszOptions);
+struct curl_slist* VSICurlMergeHeaders( struct curl_slist* poDest,
+                                        struct curl_slist* poSrcToDestroy );
 
 #include <map>
 
@@ -107,14 +122,15 @@ class CachedFileProp
     time_t          nExpireTimestampLocal;
     CPLString       osRedirectURL;
 
-                    CachedFileProp() : eExists(EXIST_UNKNOWN),
-                                       bHasComputedFileSize(false),
-                                       fileSize(0),
-                                       bIsDirectory(false),
-                                       mTime(0),
-                                       bS3Redirect(false),
-                                       nExpireTimestampLocal(0)
-                                       {}
+                    CachedFileProp() :
+                        eExists(EXIST_UNKNOWN),
+                        bHasComputedFileSize(false),
+                        fileSize(0),
+                        bIsDirectory(false),
+                        mTime(0),
+                        bS3Redirect(false),
+                        nExpireTimestampLocal(0)
+                        {}
 };
 
 typedef struct
@@ -153,8 +169,6 @@ typedef struct
     bool                bInterrupted;
 } WriteFuncStruct;
 
-} /* end of anoymous namespace */
-
 static const char* VSICurlGetCacheFileName()
 {
     return "gdal_vsicurl_cache.bin";
@@ -164,8 +178,9 @@ static const char* VSICurlGetCacheFileName()
 /*          VSICurlFindStringSensitiveExceptEscapeSequences()           */
 /************************************************************************/
 
-static int VSICurlFindStringSensitiveExceptEscapeSequences( char ** papszList,
-                                                            const char * pszTarget )
+static int
+VSICurlFindStringSensitiveExceptEscapeSequences( char ** papszList,
+                                                 const char * pszTarget )
 
 {
     if( papszList == NULL )
@@ -175,31 +190,32 @@ static int VSICurlFindStringSensitiveExceptEscapeSequences( char ** papszList,
     {
         const char* pszIter1 = papszList[i];
         const char* pszIter2 = pszTarget;
-        char ch1, ch2;
+        char ch1 = '\0';
+        char ch2 = '\0';
         /* The comparison is case-sensitive, escape for escaped */
         /* sequences where letters of the hexadecimal sequence */
         /* can be uppercase or lowercase depending on the quoting algorithm */
-        while(true)
+        while( true )
         {
             ch1 = *pszIter1;
             ch2 = *pszIter2;
-            if (ch1 == '\0' || ch2 == '\0')
+            if( ch1 == '\0' || ch2 == '\0' )
                 break;
-            if (ch1 == '%' && ch2 == '%' &&
+            if( ch1 == '%' && ch2 == '%' &&
                 pszIter1[1] != '\0' && pszIter1[2] != '\0' &&
-                pszIter2[1] != '\0' && pszIter2[2] != '\0')
+                pszIter2[1] != '\0' && pszIter2[2] != '\0' )
             {
-                if (!EQUALN(pszIter1+1, pszIter2+1, 2))
+                if( !EQUALN(pszIter1+1, pszIter2+1, 2) )
                     break;
                 pszIter1 += 2;
                 pszIter2 += 2;
             }
-            if (ch1 != ch2)
+            if( ch1 != ch2 )
                 break;
-            pszIter1 ++;
-            pszIter2 ++;
+            pszIter1++;
+            pszIter2++;
         }
-        if (ch1 == ch2 && ch1 == '\0')
+        if( ch1 == ch2 && ch1 == '\0' )
             return i;
     }
 
@@ -212,15 +228,17 @@ static int VSICurlFindStringSensitiveExceptEscapeSequences( char ** papszList,
 
 static int VSICurlIsFileInList( char ** papszList, const char * pszTarget )
 {
-    int nRet = VSICurlFindStringSensitiveExceptEscapeSequences(papszList, pszTarget);
-    if (nRet >= 0)
+    int nRet =
+        VSICurlFindStringSensitiveExceptEscapeSequences(papszList, pszTarget);
+    if( nRet >= 0 )
         return nRet;
 
-    /* If we didn't find anything, try to URL-escape the target filename */
+    // If we didn't find anything, try to URL-escape the target filename.
     char* pszEscaped = CPLEscapeString(pszTarget, -1, CPLES_URL);
-    if (strcmp(pszTarget, pszEscaped) != 0)
+    if( strcmp(pszTarget, pszEscaped) != 0 )
     {
-        nRet = VSICurlFindStringSensitiveExceptEscapeSequences(papszList, pszEscaped);
+        nRet = VSICurlFindStringSensitiveExceptEscapeSequences(papszList,
+                                                               pszEscaped);
     }
     CPLFree(pszEscaped);
     return nRet;
@@ -246,12 +264,11 @@ class VSICurlFilesystemHandler : public VSIFilesystemHandler
     std::map<CPLString, CachedFileProp*>   cacheFileSize;
     std::map<CPLString, CachedDirList*>        cacheDirList;
 
-    int             bUseCacheDisk;
+    bool            bUseCacheDisk;
 
-    /* Per-thread Curl connection cache */
+    // Per-thread Curl connection cache.
     std::map<GIntBig, CachedConnection*> mapConnections;
 
-
     char**              ParseHTMLFileList(const char* pszFilename,
                                           int nMaxFiles,
                                           char* pszData,
@@ -260,8 +277,7 @@ class VSICurlFilesystemHandler : public VSIFilesystemHandler
 protected:
     CPLMutex       *hMutex;
 
-    virtual CPLString GetFSPrefix() { return "/vsicurl/"; }
-    virtual VSICurlHandle* CreateFileHandle(const char* pszURL);
+    virtual VSICurlHandle* CreateFileHandle(const char* pszUnprefixed);
     virtual char** GetFileList(const char *pszFilename,
                                int nMaxFiles,
                                bool* pbGotFileList);
@@ -276,40 +292,43 @@ protected:
 
 public:
     VSICurlFilesystemHandler();
-    ~VSICurlFilesystemHandler();
-
-    using VSIFilesystemHandler::Open;
+    virtual ~VSICurlFilesystemHandler();
 
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
-    virtual int      Unlink( const char *pszFilename );
-    virtual int      Rename( const char *oldpath, const char *newpath );
-    virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
-            char   **ReadDirInternal( const char *pszDirname, int nMaxFiles, bool* pbGotFileList );
+                                    bool bSetError ) override;
+
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
+    virtual int      Unlink( const char *pszFilename ) override;
+    virtual int      Rename( const char *oldpath, const char *newpath )
+        override;
+    virtual int      Mkdir( const char *pszDirname, long nMode ) override;
+    virtual int      Rmdir( const char *pszDirname ) override;
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles )
+        override;
+            char   **ReadDirInternal( const char *pszDirname, int nMaxFiles,
+                                      bool* pbGotFileList );
             void     InvalidateDirContent( const char *pszDirname );
 
+    virtual CPLString GetFSPrefix() { return "/vsicurl/"; }
 
-    const CachedRegion* GetRegion(const char*     pszURL,
-                                  vsi_l_offset    nFileOffsetStart);
+    const CachedRegion* GetRegion( const char* pszURL,
+                                   vsi_l_offset nFileOffsetStart );
 
-    void                AddRegion(const char*     pszURL,
-                                  vsi_l_offset    nFileOffsetStart,
-                                  size_t          nSize,
-                                  const char     *pData);
+    void                AddRegion( const char* pszURL,
+                                   vsi_l_offset nFileOffsetStart,
+                                   size_t nSize,
+                                   const char *pData );
 
-    CachedFileProp*     GetCachedFileProp(const char*     pszURL);
-    void                InvalidateCachedFileProp(const char*     pszURL);
+    CachedFileProp*     GetCachedFileProp( const char* pszURL );
+    void                InvalidateCachedFileProp( const char* pszURL );
 
-    void                AddRegionToCacheDisk(CachedRegion* psRegion);
-    const CachedRegion* GetRegionFromCacheDisk(const char*     pszURL,
-                                               vsi_l_offset nFileOffsetStart);
+    void                AddRegionToCacheDisk( CachedRegion* psRegion );
+    const CachedRegion* GetRegionFromCacheDisk( const char* pszURL,
+                                                vsi_l_offset nFileOffsetStart );
 
-    CURL               *GetCurlHandleFor(CPLString osURL);
+    CURL               *GetCurlHandleFor( CPLString osURL );
 };
 
 /************************************************************************/
@@ -326,9 +345,11 @@ class VSICurlHandle : public VSIVirtualHandle
     bool            bHasComputedFileSize;
     ExistStatus     eExists;
     bool            bIsDirectory;
+    char*           m_pszURL;
+
+    char          **m_papszHTTPOptions;
 
   private:
-    char*           pszURL;
 
     vsi_l_offset    curOffset;
     time_t          mTime;
@@ -341,7 +362,7 @@ class VSICurlHandle : public VSIVirtualHandle
 
     VSICurlReadCbkFunc  pfnReadCbk;
     void               *pReadCbkUserData;
-    bool                bStopOnInterrruptUntilUninstall;
+    bool                bStopOnInterruptUntilUninstall;
     bool                bInterrupted;
 
     bool                m_bS3Redirect;
@@ -349,38 +370,44 @@ class VSICurlHandle : public VSIVirtualHandle
     CPLString           m_osRedirectURL;
 
   protected:
-    virtual struct curl_slist* GetCurlHeaders(const CPLString& ) { return NULL; }
-    bool CanRestartOnError(const char* pszErrorMsg) { return CanRestartOnError(pszErrorMsg, false); }
-    virtual bool CanRestartOnError(const char*, bool) { return false; }
+    virtual struct curl_slist* GetCurlHeaders( const CPLString& )
+        { return NULL; }
+    bool CanRestartOnError( const char* pszErrorMsg )
+        { return CanRestartOnError(pszErrorMsg, false); }
+    virtual bool CanRestartOnError( const char*, bool ) { return false; }
     virtual bool UseLimitRangeGetInsteadOfHead() { return false; }
     virtual void ProcessGetFileSizeResult(const char* /* pszContent */ ) {}
     void SetURL(const char* pszURL);
 
   public:
 
-    VSICurlHandle(VSICurlFilesystemHandler* poFS, const char* pszURL);
-    ~VSICurlHandle();
+    VSICurlHandle( VSICurlFilesystemHandler* poFS, const char* pszURL );
+    virtual ~VSICurlHandle();
 
-    virtual int          Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t       Read( void *pBuffer, size_t nSize, size_t nMemb );
+    virtual int          Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t       Read( void *pBuffer, size_t nSize, size_t nMemb )
+        override;
     virtual int          ReadMultiRange( int nRanges, void ** ppData,
-                                         const vsi_l_offset* panOffsets, const size_t* panSizes );
-    virtual size_t       Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int          Eof();
-    virtual int          Flush();
-    virtual int          Close();
-
-    bool                 IsKnownFileSize() const { return bHasComputedFileSize; }
+                                         const vsi_l_offset* panOffsets,
+                                         const size_t* panSizes ) override;
+    virtual size_t       Write( const void *pBuffer, size_t nSize,
+                                size_t nMemb ) override;
+    virtual int          Eof() override;
+    virtual int          Flush() override;
+    virtual int          Close() override;
+
+    bool                 IsKnownFileSize() const
+        { return bHasComputedFileSize; }
     vsi_l_offset         GetFileSize() { return GetFileSize(false); }
-    vsi_l_offset         GetFileSize(bool bSetError);
-    bool                 Exists(bool bSetError);
+    vsi_l_offset         GetFileSize( bool bSetError );
+    bool                 Exists( bool bSetError );
     bool                 IsDirectory() const { return bIsDirectory; }
     time_t               GetMTime() const { return mTime; }
 
-    int                  InstallReadCbk(VSICurlReadCbkFunc pfnReadCbk,
-                                        void* pfnUserData,
-                                        int bStopOnInterrruptUntilUninstall);
+    int                  InstallReadCbk( VSICurlReadCbkFunc pfnReadCbk,
+                                         void* pfnUserData,
+                                         int bStopOnInterruptUntilUninstall );
     int                  UninstallReadCbk();
 };
 
@@ -388,7 +415,8 @@ class VSICurlHandle : public VSIVirtualHandle
 /*                           VSICurlHandle()                            */
 /************************************************************************/
 
-VSICurlHandle::VSICurlHandle(VSICurlFilesystemHandler* poFSIn, const char* pszURLIn) :
+VSICurlHandle::VSICurlHandle( VSICurlFilesystemHandler* poFSIn,
+                              const char* pszURLIn ) :
     poFS(poFSIn),
     curOffset(0),
     lastDownloadedOffset(VSI_L_OFFSET_MAX),
@@ -396,13 +424,14 @@ VSICurlHandle::VSICurlHandle(VSICurlFilesystemHandler* poFSIn, const char* pszUR
     bEOF(false),
     pfnReadCbk(NULL),
     pReadCbkUserData(NULL),
-    bStopOnInterrruptUntilUninstall(false),
+    bStopOnInterruptUntilUninstall(false),
     bInterrupted(false),
     m_bS3Redirect(false),
     m_nExpireTimestampLocal(0)
 {
-    pszURL = CPLStrdup(pszURLIn);
-    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+    m_pszURL = CPLStrdup(pszURLIn);
+    m_papszHTTPOptions = CPLHTTPGetOptionsFromEnv();
+    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(m_pszURL);
     eExists = cachedFileProp->eExists;
     fileSize = cachedFileProp->fileSize;
     bHasComputedFileSize = cachedFileProp->bHasComputedFileSize;
@@ -416,7 +445,8 @@ VSICurlHandle::VSICurlHandle(VSICurlFilesystemHandler* poFSIn, const char* pszUR
 
 VSICurlHandle::~VSICurlHandle()
 {
-    CPLFree(pszURL);
+    CPLFree(m_pszURL);
+    CSLDestroy(m_papszHTTPOptions);
 }
 
 /************************************************************************/
@@ -425,24 +455,25 @@ VSICurlHandle::~VSICurlHandle()
 
 void VSICurlHandle::SetURL(const char* pszURLIn)
 {
-    CPLFree(pszURL);
-    pszURL = CPLStrdup(pszURLIn);
+    CPLFree(m_pszURL);
+    m_pszURL = CPLStrdup(pszURLIn);
 }
 
 /************************************************************************/
 /*                          InstallReadCbk()                            */
 /************************************************************************/
 
-int   VSICurlHandle::InstallReadCbk(VSICurlReadCbkFunc pfnReadCbkIn,
-                                    void* pfnUserDataIn,
-                                    int bStopOnInterrruptUntilUninstallIn)
+int VSICurlHandle::InstallReadCbk( VSICurlReadCbkFunc pfnReadCbkIn,
+                                   void* pfnUserDataIn,
+                                   int bStopOnInterruptUntilUninstallIn )
 {
-    if (pfnReadCbk != NULL)
+    if( pfnReadCbk != NULL )
         return FALSE;
 
     pfnReadCbk = pfnReadCbkIn;
     pReadCbkUserData = pfnUserDataIn;
-    bStopOnInterrruptUntilUninstall = CPL_TO_BOOL(bStopOnInterrruptUntilUninstallIn);
+    bStopOnInterruptUntilUninstall =
+        CPL_TO_BOOL(bStopOnInterruptUntilUninstallIn);
     bInterrupted = false;
     return TRUE;
 }
@@ -453,12 +484,12 @@ int   VSICurlHandle::InstallReadCbk(VSICurlReadCbkFunc pfnReadCbkIn,
 
 int VSICurlHandle::UninstallReadCbk()
 {
-    if (pfnReadCbk == NULL)
+    if( pfnReadCbk == NULL )
         return FALSE;
 
     pfnReadCbk = NULL;
     pReadCbkUserData = NULL;
-    bStopOnInterrruptUntilUninstall = false;
+    bStopOnInterruptUntilUninstall = false;
     bInterrupted = false;
     return TRUE;
 }
@@ -469,11 +500,11 @@ int VSICurlHandle::UninstallReadCbk()
 
 int VSICurlHandle::Seek( vsi_l_offset nOffset, int nWhence )
 {
-    if (nWhence == SEEK_SET)
+    if( nWhence == SEEK_SET )
     {
         curOffset = nOffset;
     }
-    else if (nWhence == SEEK_CUR)
+    else if( nWhence == SEEK_CUR )
     {
         curOffset = curOffset + nOffset;
     }
@@ -486,61 +517,30 @@ int VSICurlHandle::Seek( vsi_l_offset nOffset, int nWhence )
 }
 
 /************************************************************************/
-/*                       VSICurlSetOptions()                            */
-/************************************************************************/
-
-void VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL)
-{
-    curl_easy_setopt(hCurlHandle, CURLOPT_URL, pszURL);
-
-    CPLHTTPSetOptions(hCurlHandle, NULL);
-
-/* 7.16 */
-#if LIBCURL_VERSION_NUM >= 0x071000
-    long option = CURLFTPMETHOD_SINGLECWD;
-    curl_easy_setopt(hCurlHandle, CURLOPT_FTP_FILEMETHOD, option);
-#endif
-
-/* 7.12.3 */
-#if LIBCURL_VERSION_NUM > 0x070C03
-    /* ftp://ftp2.cits.rncan.gc.ca/pub/cantopo/250k_tif/ doesn't like EPSV command */
-    curl_easy_setopt(hCurlHandle, CURLOPT_FTP_USE_EPSV, 0);
-#endif
-
-    curl_easy_setopt(hCurlHandle, CURLOPT_NOBODY, 0);
-    curl_easy_setopt(hCurlHandle, CURLOPT_HTTPGET, 1);
-    curl_easy_setopt(hCurlHandle, CURLOPT_HEADER, 0);
-
-/* 7.16.4 */
-#if LIBCURL_VERSION_NUM <= 0x071004
-    curl_easy_setopt(hCurlHandle, CURLOPT_FTPLISTONLY, 0);
-#elif LIBCURL_VERSION_NUM > 0x071004
-    curl_easy_setopt(hCurlHandle, CURLOPT_DIRLISTONLY, 0);
-#endif
-
-    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, NULL);
-    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, NULL);
-}
-
-/************************************************************************/
 /*                 VSICurlGetTimeStampFromRFC822DateTime()              */
 /************************************************************************/
 
-static GIntBig VSICurlGetTimeStampFromRFC822DateTime(const char* pszDT)
+static GIntBig VSICurlGetTimeStampFromRFC822DateTime( const char* pszDT )
 {
-    /* Sun, 03 Apr 2016 12:07:27 GMT */
-    static const char* const aszMonthStr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-    if( strlen(pszDT) && pszDT[3] == ',' && pszDT[4] == ' ' )
+    // Sun, 03 Apr 2016 12:07:27 GMT
+    if( strlen(pszDT) >= 5 && pszDT[3] == ',' && pszDT[4] == ' ' )
         pszDT += 5;
-    int nDay, nYear, nHour, nMinute, nSecond;
-    char szMonth[4];
+    int nDay = 0;
+    int nYear = 0;
+    int nHour = 0;
+    int nMinute = 0;
+    int nSecond = 0;
+    char szMonth[4] = {};
     szMonth[3] = 0;
     if( sscanf(pszDT, "%02d %03s %04d %02d:%02d:%02d GMT",
                 &nDay, szMonth, &nYear, &nHour, &nMinute, &nSecond) == 6 )
     {
+        static const char* const aszMonthStr[] = {
+            "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
         int nMonthIdx0 = -1;
-        for(int i=0;i<12;i++)
+        for( int i = 0; i < 12; i++ )
         {
             if( EQUAL(szMonth, aszMonthStr[i]) )
             {
@@ -567,10 +567,10 @@ static GIntBig VSICurlGetTimeStampFromRFC822DateTime(const char* pszDT)
 /*                    VSICURLInitWriteFuncStruct()                      */
 /************************************************************************/
 
-static void VSICURLInitWriteFuncStruct(WriteFuncStruct   *psStruct,
-                                       VSILFILE          *fp,
-                                       VSICurlReadCbkFunc pfnReadCbk,
-                                       void              *pReadCbkUserData)
+static void VSICURLInitWriteFuncStruct( WriteFuncStruct   *psStruct,
+                                        VSILFILE          *fp,
+                                        VSICurlReadCbkFunc pfnReadCbk,
+                                        void              *pReadCbkUserData )
 {
     psStruct->pBuffer = NULL;
     psStruct->nSize = 0;
@@ -596,30 +596,38 @@ static void VSICURLInitWriteFuncStruct(WriteFuncStruct   *psStruct,
 /*                       VSICurlHandleWriteFunc()                       */
 /************************************************************************/
 
-static size_t VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, void *req)
+static size_t VSICurlHandleWriteFunc( void *buffer, size_t count,
+                                      size_t nmemb, void *req )
 {
-    WriteFuncStruct* psStruct = (WriteFuncStruct*) req;
+    WriteFuncStruct* psStruct = static_cast<WriteFuncStruct *>(req);
     const size_t nSize = count * nmemb;
 
-    char* pNewBuffer = (char*) VSIRealloc(psStruct->pBuffer,
-                                          psStruct->nSize + nSize + 1);
-    if (pNewBuffer)
+    char* pNewBuffer = static_cast<char *>(
+        VSIRealloc(psStruct->pBuffer, psStruct->nSize + nSize + 1));
+    if( pNewBuffer )
     {
         psStruct->pBuffer = pNewBuffer;
         memcpy(psStruct->pBuffer + psStruct->nSize, buffer, nSize);
         psStruct->pBuffer[psStruct->nSize + nSize] = '\0';
-        if (psStruct->bIsHTTP && psStruct->bIsInHeader)
+        if( psStruct->bIsHTTP && psStruct->bIsInHeader )
         {
             char* pszLine = psStruct->pBuffer + psStruct->nSize;
-            if (STARTS_WITH_CI(pszLine, "HTTP/1.0 ") ||
-                STARTS_WITH_CI(pszLine, "HTTP/1.1 "))
+            if( STARTS_WITH_CI(pszLine, "HTTP/1.0 ") ||
+                STARTS_WITH_CI(pszLine, "HTTP/1.1 ") )
+            {
                 psStruct->nHTTPCode = atoi(pszLine + 9);
-            else if (STARTS_WITH_CI(pszLine, "Content-Length: "))
-                psStruct->nContentLength = CPLScanUIntBig(pszLine + 16,
-                                                          static_cast<int>(strlen(pszLine + 16)));
-            else if (STARTS_WITH_CI(pszLine, "Content-Range: "))
+            }
+            else if( STARTS_WITH_CI(pszLine, "Content-Length: ") )
+            {
+                psStruct->nContentLength =
+                    CPLScanUIntBig(pszLine + 16,
+                                   static_cast<int>(strlen(pszLine + 16)));
+            }
+            else if( STARTS_WITH_CI(pszLine, "Content-Range: ") )
+            {
                 psStruct->bFoundContentRange = true;
-            else if (STARTS_WITH_CI(pszLine, "Date: "))
+            }
+            else if( STARTS_WITH_CI(pszLine, "Date: ") )
             {
                 CPLString osDate = pszLine + strlen("Date: ");
                 size_t nSizeLine = osDate.size();
@@ -628,43 +636,51 @@ static size_t VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, v
                         osDate[nSizeLine-1] == '\n') )
                 {
                     osDate.resize(nSizeLine-1);
-                    nSizeLine --;
+                    nSizeLine--;
                 }
                 osDate.Trim();
 
-                GIntBig nTimestampDate = VSICurlGetTimeStampFromRFC822DateTime(osDate);
-                //CPLDebug("VSICURL", "Timestamp = " CPL_FRMT_GIB, nTimestampDate);
+                GIntBig nTimestampDate =
+                    VSICurlGetTimeStampFromRFC822DateTime(osDate);
+#if DEBUG_VERBOSE
+                CPLDebug("VSICURL",
+                         "Timestamp = " CPL_FRMT_GIB, nTimestampDate);
+#endif
                 psStruct->nTimestampDate = nTimestampDate;
             }
-            /*if (nSize > 2 && pszLine[nSize - 2] == '\r' &&
-                pszLine[nSize - 1] == '\n')
+            /*if( nSize > 2 && pszLine[nSize - 2] == '\r' &&
+                  pszLine[nSize - 1] == '\n' )
             {
                 pszLine[nSize - 2] = 0;
                 CPLDebug("VSICURL", "%s", pszLine);
                 pszLine[nSize - 2] = '\r';
             }*/
 
-            if (pszLine[0] == '\r' || pszLine[0] == '\n')
+            if( pszLine[0] == '\r' || pszLine[0] == '\n' )
             {
-                if (psStruct->bDownloadHeaderOnly)
+                if( psStruct->bDownloadHeaderOnly )
                 {
-                    /* If moved permanently/temporarily, go on. Otherwise stop now*/
-                    if (!(psStruct->nHTTPCode == 301 || psStruct->nHTTPCode == 302))
+                    // If moved permanently/temporarily, go on.
+                    // Otherwise stop now,
+                    if( !(psStruct->nHTTPCode == 301 ||
+                          psStruct->nHTTPCode == 302) )
                         return 0;
                 }
                 else
                 {
                     psStruct->bIsInHeader = false;
 
-                    /* Detect servers that don't support range downloading */
-                    if (psStruct->nHTTPCode == 200 &&
+                    // Detect servers that don't support range downloading.
+                    if( psStruct->nHTTPCode == 200 &&
                         !psStruct->bMultiRange &&
                         !psStruct->bFoundContentRange &&
-                        (psStruct->nStartOffset != 0 || psStruct->nContentLength > 10 *
-                            (psStruct->nEndOffset - psStruct->nStartOffset + 1)))
+                        (psStruct->nStartOffset != 0 ||
+                         psStruct->nContentLength > 10 *
+                         (psStruct->nEndOffset - psStruct->nStartOffset + 1)) )
                     {
                         CPLError(CE_Failure, CPLE_AppDefined,
-                                "Range downloading not supported by this server !");
+                                 "Range downloading not supported by this "
+                                 "server!");
                         psStruct->bError = true;
                         return 0;
                     }
@@ -673,10 +689,10 @@ static size_t VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, v
         }
         else
         {
-            if (psStruct->pfnReadCbk)
+            if( psStruct->pfnReadCbk )
             {
-                if ( ! psStruct->pfnReadCbk(psStruct->fp, buffer, nSize,
-                                            psStruct->pReadCbkUserData) )
+                if( !psStruct->pfnReadCbk(psStruct->fp, buffer, nSize,
+                                          psStruct->pReadCbkUserData) )
                 {
                     psStruct->bInterrupted = true;
                     return 0;
@@ -696,17 +712,19 @@ static size_t VSICurlHandleWriteFunc(void *buffer, size_t count, size_t nmemb, v
 /*                       VSICurlIsS3SignedURL()                         */
 /************************************************************************/
 
-static bool VSICurlIsS3SignedURL(const char* pszURL)
+static bool VSICurlIsS3SignedURL( const char* pszURL )
 {
-    return strstr(pszURL, ".s3.amazonaws.com/") != NULL &&
-           (strstr(pszURL, "&Signature=") != NULL || strstr(pszURL, "?Signature=") != NULL);
+    return
+        strstr(pszURL, ".s3.amazonaws.com/") != NULL &&
+        (strstr(pszURL, "&Signature=") != NULL ||
+         strstr(pszURL, "?Signature=") != NULL);
 }
 
 /************************************************************************/
 /*                      VSICurlGetExpiresFromS3SigneURL()               */
 /************************************************************************/
 
-static GIntBig VSICurlGetExpiresFromS3SigneURL(const char* pszURL)
+static GIntBig VSICurlGetExpiresFromS3SigneURL( const char* pszURL )
 {
     const char* pszExpires = strstr(pszURL, "&Expires=");
     if( pszExpires == NULL )
@@ -720,33 +738,32 @@ static GIntBig VSICurlGetExpiresFromS3SigneURL(const char* pszURL)
 /*                           GetFileSize()                              */
 /************************************************************************/
 
-vsi_l_offset VSICurlHandle::GetFileSize(bool bSetError)
+vsi_l_offset VSICurlHandle::GetFileSize( bool bSetError )
 {
-    WriteFuncStruct sWriteFuncData;
-    WriteFuncStruct sWriteFuncHeaderData;
-
-    if (bHasComputedFileSize)
+    if( bHasComputedFileSize )
         return fileSize;
 
     bHasComputedFileSize = true;
 
 #if LIBCURL_VERSION_NUM < 0x070B00
-    /* Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have been */
-    /* previously set, so we have to reinit the connection handle */
+    // Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have
+    // been previously set, so we have to reinit the connection handle.
     poFS->GetCurlHandleFor("");
 #endif
-    CURL* hCurlHandle = poFS->GetCurlHandleFor(pszURL);
-    CPLString osURL(pszURL);
+    CURL* hCurlHandle = poFS->GetCurlHandleFor(m_pszURL);
+    CPLString osURL(m_pszURL);
     bool bRetryWithGet = false;
     bool bS3Redirect = false;
 
 retry:
-    VSICurlSetOptions(hCurlHandle, osURL);
+    struct curl_slist* headers =
+            VSICurlSetOptions(hCurlHandle, osURL, m_papszHTTPOptions);
 
-    /* We need that otherwise OSGEO4W's libcurl issue a dummy range request */
-    /* when doing a HEAD when recycling connections */
+    // We need that otherwise OSGEO4W's libcurl issue a dummy range request
+    // when doing a HEAD when recycling connections.
     curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, NULL);
 
+    WriteFuncStruct sWriteFuncHeaderData;
     VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData, NULL, NULL, NULL);
 
     CPLString osVerb;
@@ -756,12 +773,14 @@ retry:
 
         curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, "0-4095");
     }
-    /* HACK for mbtiles driver: http://a.tiles.mapbox.com/v3/ doesn't accept HEAD, */
-    /* as it is a redirect to AWS S3 signed URL, but those are only valid for a */
-    /* given type of HTTP request, and thus GET. This is valid for any signed URL for AWS S3. */
-    else if (strstr(osURL, ".tiles.mapbox.com/") != NULL ||
+    // HACK for mbtiles driver: http://a.tiles.mapbox.com/v3/ doesn't accept
+    // HEAD, as it is a redirect to AWS S3 signed URL, but those are only valid
+    // for a given type of HTTP request, and thus GET. This is valid for any
+    // signed URL for AWS S3.
+    else if( strstr(osURL, ".tiles.mapbox.com/") != NULL ||
              VSICurlIsS3SignedURL(osURL) ||
-             !CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", "YES")))
+             !CPLTestBool(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD",
+                                             "YES")) )
     {
         sWriteFuncHeaderData.bDownloadHeaderOnly = true;
         osVerb = "GET";
@@ -776,22 +795,28 @@ retry:
     }
 
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION,
+                     VSICurlHandleWriteFunc);
     sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(osURL, "http");
 
-    /* Bug with older curl versions (<=7.16.4) and FTP. See http://curl.haxx.se/mail/lib-2007-08/0312.html */
+    // Bug with older curl versions (<=7.16.4) and FTP.
+    // See http://curl.haxx.se/mail/lib-2007-08/0312.html
+    WriteFuncStruct sWriteFuncData;
     VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                     VSICurlHandleWriteFunc);
 
-    char szCurlErrBuf[CURL_ERROR_SIZE+1];
+    char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
     szCurlErrBuf[0] = '\0';
     curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
-    struct curl_slist* headers = GetCurlHeaders(osVerb);
+    headers = VSICurlMergeHeaders(headers, GetCurlHeaders(osVerb));
     if( headers != NULL )
         curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
 
+    curl_easy_setopt(hCurlHandle, CURLOPT_FILETIME, 1);
+
     curl_easy_perform(hCurlHandle);
 
     if( headers != NULL )
@@ -799,42 +824,54 @@ retry:
 
     eExists = EXIST_UNKNOWN;
 
-    if (STARTS_WITH(osURL, "ftp"))
+    long mtime = 0;
+    curl_easy_getinfo(hCurlHandle, CURLINFO_FILETIME, &mtime);
+
+    if( STARTS_WITH(osURL, "ftp") )
     {
-        if (sWriteFuncData.pBuffer != NULL &&
-            STARTS_WITH(sWriteFuncData.pBuffer, "Content-Length: "))
+        if( sWriteFuncData.pBuffer != NULL &&
+            STARTS_WITH(sWriteFuncData.pBuffer, "Content-Length: ") )
         {
-            const char* pszBuffer = sWriteFuncData.pBuffer + strlen("Content-Length: ");
+            const char* pszBuffer =
+                sWriteFuncData.pBuffer + strlen("Content-Length: ");
             eExists = EXIST_YES;
-            fileSize = CPLScanUIntBig(pszBuffer, static_cast<int>(sWriteFuncData.nSize - strlen("Content-Length: ")));
-            if (ENABLE_DEBUG)
+            fileSize = CPLScanUIntBig(
+                pszBuffer,
+                static_cast<int>(sWriteFuncData.nSize -
+                                 strlen("Content-Length: ")));
+            if( ENABLE_DEBUG )
                 CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB,
                          osURL.c_str(), fileSize);
         }
     }
 
     double dfSize = 0;
-    if (eExists != EXIST_YES)
+    if( eExists != EXIST_YES )
     {
         long response_code = 0;
         curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
 
         char *pszEffectiveURL = NULL;
-        curl_easy_getinfo(hCurlHandle, CURLINFO_EFFECTIVE_URL, &pszEffectiveURL);
+        curl_easy_getinfo(hCurlHandle, CURLINFO_EFFECTIVE_URL,
+                          &pszEffectiveURL);
         if( pszEffectiveURL != NULL && strstr(pszEffectiveURL, osURL) == NULL )
         {
             CPLDebug("VSICURL", "Effective URL: %s", pszEffectiveURL);
 
-            // Is this is a redirect to a S3 URL ?
-            if( VSICurlIsS3SignedURL(pszEffectiveURL) && !VSICurlIsS3SignedURL(osURL) )
+            // Is this is a redirect to a S3 URL?
+            if( VSICurlIsS3SignedURL(pszEffectiveURL) &&
+                !VSICurlIsS3SignedURL(osURL) )
             {
-                // Note that this is a redirect as we won't notice after the retry.
+                // Note that this is a redirect as we won't notice after the
+                // retry.
                 bS3Redirect = true;
 
                 if( !bRetryWithGet && osVerb == "HEAD" && response_code == 403 )
                 {
-                    CPLDebug("VSICURL", "Redirected to a AWS S3 signed URL. Retrying "
-                             "with GET request instead of HEAD since the URL might be valid only for GET");
+                    CPLDebug("VSICURL",
+                             "Redirected to a AWS S3 signed URL. Retrying "
+                             "with GET request instead of HEAD since the URL "
+                             "might be valid only for GET");
                     bRetryWithGet = true;
                     osURL = pszEffectiveURL;
                     CPLFree(sWriteFuncData.pBuffer);
@@ -845,35 +882,44 @@ retry:
         }
 
         if( bS3Redirect && response_code >= 200 && response_code < 300 &&
-            sWriteFuncHeaderData.nTimestampDate > 0 && pszEffectiveURL != NULL &&
-            CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_USE_S3_REDIRECT", "TRUE")) )
+            sWriteFuncHeaderData.nTimestampDate > 0 &&
+            pszEffectiveURL != NULL &&
+            CPLTestBool(CPLGetConfigOption("CPL_VSIL_CURL_USE_S3_REDIRECT",
+                                           "TRUE")) )
         {
-            GIntBig nExpireTimestamp = VSICurlGetExpiresFromS3SigneURL(pszEffectiveURL);
+            const GIntBig nExpireTimestamp =
+                VSICurlGetExpiresFromS3SigneURL(pszEffectiveURL);
             if( nExpireTimestamp > sWriteFuncHeaderData.nTimestampDate + 10 )
             {
-                int nValidity = static_cast<int>(nExpireTimestamp - sWriteFuncHeaderData.nTimestampDate);
-                CPLDebug("VSICURL", "Will use redirect URL for the next %d seconds",
+                const int nValidity =
+                    static_cast<int>(nExpireTimestamp -
+                                     sWriteFuncHeaderData.nTimestampDate);
+                CPLDebug("VSICURL",
+                         "Will use redirect URL for the next %d seconds",
                          nValidity);
                 // As our local clock might not be in sync with server clock,
                 // figure out the expiration timestamp in local time
                 m_bS3Redirect = true;
                 m_nExpireTimestampLocal = time(NULL) + nValidity;
                 m_osRedirectURL = pszEffectiveURL;
-                CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+                CachedFileProp* cachedFileProp =
+                    poFS->GetCachedFileProp(m_pszURL);
                 cachedFileProp->bS3Redirect = m_bS3Redirect;
                 cachedFileProp->nExpireTimestampLocal = m_nExpireTimestampLocal;
                 cachedFileProp->osRedirectURL = m_osRedirectURL;
             }
         }
 
-        CURLcode code = curl_easy_getinfo(hCurlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dfSize );
-        if (code == 0)
+        const CURLcode code =
+            curl_easy_getinfo(hCurlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+                              &dfSize );
+        if( code == 0 )
         {
             eExists = EXIST_YES;
-            if (dfSize < 0)
+            if( dfSize < 0 )
                 fileSize = 0;
             else
-                fileSize = (GUIntBig)dfSize;
+                fileSize = static_cast<GUIntBig>(dfSize);
         }
 
         if( UseLimitRangeGetInsteadOfHead() && response_code == 206 )
@@ -882,20 +928,25 @@ retry:
             fileSize = 0;
             if( sWriteFuncHeaderData.pBuffer != NULL )
             {
-                const char* pszContentRange = strstr((const char*)sWriteFuncHeaderData.pBuffer, "Content-Range: bytes ");
+                const char* pszContentRange =
+                    strstr(sWriteFuncHeaderData.pBuffer,
+                           "Content-Range: bytes ");
                 if( pszContentRange )
                     pszContentRange = strchr(pszContentRange, '/');
                 if( pszContentRange )
                 {
                     eExists = EXIST_YES;
-                    fileSize = (GUIntBig)CPLAtoGIntBig(pszContentRange+1);
+                    fileSize = static_cast<GUIntBig>(
+                        CPLAtoGIntBig(pszContentRange + 1));
                 }
             }
         }
         else if( response_code != 200 )
         {
-            if( UseLimitRangeGetInsteadOfHead() && sWriteFuncData.pBuffer != NULL &&
-                CanRestartOnError((const char*)sWriteFuncData.pBuffer, bSetError) )
+            if( UseLimitRangeGetInsteadOfHead() &&
+                sWriteFuncData.pBuffer != NULL &&
+                CanRestartOnError(sWriteFuncData.pBuffer,
+                                  bSetError) )
             {
                 bHasComputedFileSize = false;
                 CPLFree(sWriteFuncData.pBuffer);
@@ -905,15 +956,26 @@ retry:
 
             // If there was no VSI error thrown in the process,
             // fail by reporting the HTTP response code.
-            if(bSetError && VSIGetLastErrorNo() == 0) {
-                if(strlen(szCurlErrBuf) > 0) {
-                    if(response_code == 0) {
-                        VSIError(VSIE_HttpError, "CURL error: %s", szCurlErrBuf);
-                    } else {
-                        VSIError(VSIE_HttpError, "HTTP response code: %d - %s", (int)response_code, szCurlErrBuf);
+            if( bSetError && VSIGetLastErrorNo() == 0 )
+            {
+                if( strlen(szCurlErrBuf) > 0 )
+                {
+                    if( response_code == 0 )
+                    {
+                        VSIError(VSIE_HttpError,
+                                 "CURL error: %s", szCurlErrBuf);
+                    }
+                    else
+                    {
+                        VSIError(VSIE_HttpError,
+                                 "HTTP response code: %d - %s",
+                                 static_cast<int>(response_code), szCurlErrBuf);
                     }
-                } else {
-                    VSIError(VSIE_HttpError, "HTTP response code: %d", (int)response_code);
+                }
+                else
+                {
+                    VSIError(VSIE_HttpError, "HTTP response code: %d",
+                             static_cast<int>(response_code));
                 }
             }
 
@@ -925,29 +987,34 @@ retry:
             ProcessGetFileSizeResult( (const char*)sWriteFuncData.pBuffer );
         }
 
-        /* Try to guess if this is a directory. Generally if this is a directory, */
-        /* curl will retry with an URL with slash added */
-        if (pszEffectiveURL != NULL && strncmp(osURL, pszEffectiveURL, strlen(osURL)) == 0 &&
-            pszEffectiveURL[strlen(osURL)] == '/')
+        // Try to guess if this is a directory. Generally if this is a
+        // directory, curl will retry with an URL with slash added.
+        if( pszEffectiveURL != NULL &&
+            strncmp(osURL, pszEffectiveURL, osURL.size()) == 0 &&
+            pszEffectiveURL[osURL.size()] == '/' )
         {
             eExists = EXIST_YES;
             fileSize = 0;
             bIsDirectory = true;
         }
 
-        if (ENABLE_DEBUG)
-            CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB "  response_code=%d",
-                    osURL.c_str(), fileSize, (int)response_code);
+        if( ENABLE_DEBUG )
+            CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB
+                     "  response_code=%d",
+                     osURL.c_str(), fileSize,
+                     static_cast<int>(response_code));
     }
 
     CPLFree(sWriteFuncData.pBuffer);
     CPLFree(sWriteFuncHeaderData.pBuffer);
 
-    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
+    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(m_pszURL);
     cachedFileProp->bHasComputedFileSize = true;
     cachedFileProp->fileSize = fileSize;
     cachedFileProp->eExists = eExists;
     cachedFileProp->bIsDirectory = bIsDirectory;
+    if( mtime != 0 )
+        cachedFileProp->mTime = mtime;
 
     return fileSize;
 }
@@ -956,11 +1023,12 @@ retry:
 /*                                 Exists()                             */
 /************************************************************************/
 
-bool VSICurlHandle::Exists(bool bSetError)
+bool VSICurlHandle::Exists( bool bSetError )
 {
-  if (eExists == EXIST_UNKNOWN) {
+    if( eExists == EXIST_UNKNOWN )
+    {
         GetFileSize(bSetError);
-  }
+    }
     return eExists == EXIST_YES;
 }
 
@@ -977,16 +1045,14 @@ vsi_l_offset VSICurlHandle::Tell()
 /*                          DownloadRegion()                            */
 /************************************************************************/
 
-bool VSICurlHandle::DownloadRegion(const vsi_l_offset startOffset, const int nBlocks)
+bool VSICurlHandle::DownloadRegion( const vsi_l_offset startOffset,
+                                    const int nBlocks )
 {
-    WriteFuncStruct sWriteFuncData;
-    WriteFuncStruct sWriteFuncHeaderData;
-
-    if (bInterrupted && bStopOnInterrruptUntilUninstall)
+    if( bInterrupted && bStopOnInterruptUntilUninstall )
         return false;
 
-    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
-    if (cachedFileProp->eExists == EXIST_NO)
+    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(m_pszURL);
+    if( cachedFileProp->eExists == EXIST_NO )
         return false;
     if( cachedFileProp->bS3Redirect )
     {
@@ -995,16 +1061,18 @@ bool VSICurlHandle::DownloadRegion(const vsi_l_offset startOffset, const int nBl
         m_osRedirectURL = cachedFileProp->osRedirectURL;
     }
 
-    CURL* hCurlHandle = poFS->GetCurlHandleFor(pszURL);
+    CURL* hCurlHandle = poFS->GetCurlHandleFor(m_pszURL);
 
-    CPLString osURL(pszURL);
+    CPLString osURL(m_pszURL);
     bool bUsedRedirect = false;
     if( m_bS3Redirect )
     {
         if( time(NULL) + 1 < m_nExpireTimestampLocal )
         {
-            CPLDebug("VSICURL", "Using redirect URL as it looks to be still valid (%d seconds left)",
-                     static_cast<int>(m_nExpireTimestampLocal - time(NULL)) );
+            CPLDebug("VSICURL",
+                     "Using redirect URL as it looks to be still valid "
+                     "(%d seconds left)",
+                     static_cast<int>(m_nExpireTimestampLocal - time(NULL)));
             osURL = m_osRedirectURL;
             bUsedRedirect = true;
         }
@@ -1015,44 +1083,56 @@ bool VSICurlHandle::DownloadRegion(const vsi_l_offset startOffset, const int nBl
             cachedFileProp->bS3Redirect = false;
         }
     }
+
+    WriteFuncStruct sWriteFuncData;
+    WriteFuncStruct sWriteFuncHeaderData;
+
 retry:
-    VSICurlSetOptions(hCurlHandle, osURL);
+    struct curl_slist* headers =
+        VSICurlSetOptions(hCurlHandle, osURL, m_papszHTTPOptions);
 
-    VSICURLInitWriteFuncStruct(&sWriteFuncData, (VSILFILE*)this, pfnReadCbk, pReadCbkUserData);
+    VSICURLInitWriteFuncStruct(&sWriteFuncData,
+                               reinterpret_cast<VSILFILE *>(this),
+                               pfnReadCbk, pReadCbkUserData);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                     VSICurlHandleWriteFunc);
 
     VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
-    sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(pszURL, "http");
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION,
+                     VSICurlHandleWriteFunc);
+    sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(m_pszURL, "http");
     sWriteFuncHeaderData.nStartOffset = startOffset;
-    sWriteFuncHeaderData.nEndOffset = startOffset + nBlocks * DOWNLOAD_CHUNK_SIZE - 1;
-    /* Some servers don't like we try to read after end-of-file (#5786) */
+    sWriteFuncHeaderData.nEndOffset =
+        startOffset + nBlocks * DOWNLOAD_CHUNK_SIZE - 1;
+    // Some servers don't like we try to read after end-of-file (#5786).
     if( cachedFileProp->bHasComputedFileSize &&
         sWriteFuncHeaderData.nEndOffset >= cachedFileProp->fileSize )
     {
         sWriteFuncHeaderData.nEndOffset = cachedFileProp->fileSize - 1;
     }
 
-    char rangeStr[512];
+    char rangeStr[512] = {};
     snprintf(rangeStr, sizeof(rangeStr),
              CPL_FRMT_GUIB "-" CPL_FRMT_GUIB, startOffset,
             sWriteFuncHeaderData.nEndOffset);
 
-    if (ENABLE_DEBUG)
+    if( ENABLE_DEBUG )
         CPLDebug("VSICURL", "Downloading %s (%s)...", rangeStr, osURL.c_str());
 
     curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, rangeStr);
 
-    char szCurlErrBuf[CURL_ERROR_SIZE+1];
+    char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
     szCurlErrBuf[0] = '\0';
     curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
-    struct curl_slist* headers = GetCurlHeaders("GET");
+    headers = VSICurlMergeHeaders(headers, GetCurlHeaders("GET"));
     if( headers != NULL )
         curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
 
+    curl_easy_setopt(hCurlHandle, CURLOPT_FILETIME, 1);
+
     curl_easy_perform(hCurlHandle);
 
     if( headers != NULL )
@@ -1063,7 +1143,7 @@ retry:
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, NULL);
 
-    if (sWriteFuncData.bInterrupted)
+    if( sWriteFuncData.bInterrupted )
     {
         bInterrupted = true;
 
@@ -1079,16 +1159,22 @@ retry:
     char *content_type = NULL;
     curl_easy_getinfo(hCurlHandle, CURLINFO_CONTENT_TYPE, &content_type);
 
-    if (ENABLE_DEBUG)
+    long mtime = 0;
+    curl_easy_getinfo(hCurlHandle, CURLINFO_FILETIME, &mtime);
+    if( mtime != 0 )
+        cachedFileProp->mTime = mtime;
+
+    if( ENABLE_DEBUG )
         CPLDebug("VSICURL", "Got response_code=%ld", response_code);
 
     if( response_code == 403 && bUsedRedirect )
     {
-        CPLDebug("VSICURL", "Got an error with redirect URL. Retrying with original one");
+        CPLDebug("VSICURL",
+                 "Got an error with redirect URL. Retrying with original one");
         m_bS3Redirect = false;
         cachedFileProp->bS3Redirect = false;
         bUsedRedirect = false;
-        osURL = pszURL;
+        osURL = m_pszURL;
         CPLFree(sWriteFuncData.pBuffer);
         CPLFree(sWriteFuncHeaderData.pBuffer);
         goto retry;
@@ -1096,22 +1182,29 @@ retry:
 
     char *pszEffectiveURL = NULL;
     curl_easy_getinfo(hCurlHandle, CURLINFO_EFFECTIVE_URL, &pszEffectiveURL);
-    if( !m_bS3Redirect && pszEffectiveURL != NULL && strstr(pszEffectiveURL, pszURL) == NULL )
+    if( !m_bS3Redirect && pszEffectiveURL != NULL &&
+        strstr(pszEffectiveURL, m_pszURL) == NULL )
     {
         CPLDebug("VSICURL", "Effective URL: %s", pszEffectiveURL);
         if( response_code >= 200 && response_code < 300 &&
             sWriteFuncHeaderData.nTimestampDate > 0 &&
-            VSICurlIsS3SignedURL(pszEffectiveURL) && !VSICurlIsS3SignedURL(pszURL) &&
-            CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_USE_S3_REDIRECT", "TRUE")) )
+            VSICurlIsS3SignedURL(pszEffectiveURL) &&
+            !VSICurlIsS3SignedURL(m_pszURL) &&
+            CPLTestBool(CPLGetConfigOption("CPL_VSIL_CURL_USE_S3_REDIRECT",
+                                           "TRUE")) )
         {
-            GIntBig nExpireTimestamp = VSICurlGetExpiresFromS3SigneURL(pszEffectiveURL);
+            GIntBig nExpireTimestamp =
+                VSICurlGetExpiresFromS3SigneURL(pszEffectiveURL);
             if( nExpireTimestamp > sWriteFuncHeaderData.nTimestampDate + 10 )
             {
-                int nValidity = static_cast<int>(nExpireTimestamp - sWriteFuncHeaderData.nTimestampDate);
-                CPLDebug("VSICURL", "Will use redirect URL for the next %d seconds",
+                const int nValidity =
+                    static_cast<int>(nExpireTimestamp -
+                                     sWriteFuncHeaderData.nTimestampDate);
+                CPLDebug("VSICURL",
+                         "Will use redirect URL for the next %d seconds",
                          nValidity);
                 // As our local clock might not be in sync with server clock,
-                // figure out the expiration timestamp in local time
+                // figure out the expiration timestamp in local time.
                 m_bS3Redirect = true;
                 m_nExpireTimestampLocal = time(NULL) + nValidity;
                 m_osRedirectURL = pszEffectiveURL;
@@ -1122,8 +1215,10 @@ retry:
         }
     }
 
-    if ((response_code != 200 && response_code != 206 &&
-         response_code != 225 && response_code != 226 && response_code != 426) || sWriteFuncHeaderData.bError)
+    if( (response_code != 200 && response_code != 206 &&
+         response_code != 225 && response_code != 226 &&
+         response_code != 426) ||
+        sWriteFuncHeaderData.bError )
     {
         if( sWriteFuncData.pBuffer != NULL &&
             CanRestartOnError((const char*)sWriteFuncData.pBuffer) )
@@ -1133,16 +1228,18 @@ retry:
             return DownloadRegion(startOffset, nBlocks);
         }
 
-        if (response_code >= 400 && szCurlErrBuf[0] != '\0')
+        if( response_code >= 400 && szCurlErrBuf[0] != '\0' )
         {
-            if (strcmp(szCurlErrBuf, "Couldn't use REST") == 0)
-                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s, %s",
-                         (int)response_code, szCurlErrBuf,
-                         "Range downloading not supported by this server !");
+            if( strcmp(szCurlErrBuf, "Couldn't use REST") == 0 )
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "%d: %s, Range downloading not supported by this server!",
+                    static_cast<int>(response_code), szCurlErrBuf);
             else
-                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s", (int)response_code, szCurlErrBuf);
+                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s",
+                         static_cast<int>(response_code), szCurlErrBuf);
         }
-        if (!bHasComputedFileSize && startOffset == 0)
+        if( !bHasComputedFileSize && startOffset == 0 )
         {
             cachedFileProp->bHasComputedFileSize = bHasComputedFileSize = true;
             cachedFileProp->fileSize = fileSize = 0;
@@ -1153,55 +1250,61 @@ retry:
         return false;
     }
 
-    if (!bHasComputedFileSize && sWriteFuncHeaderData.pBuffer)
+    if( !bHasComputedFileSize && sWriteFuncHeaderData.pBuffer )
     {
-        /* Try to retrieve the filesize from the HTTP headers */
-        /* if in the form : "Content-Range: bytes x-y/filesize" */
-        char* pszContentRange = strstr(sWriteFuncHeaderData.pBuffer, "Content-Range: bytes ");
-        if (pszContentRange)
+        // Try to retrieve the filesize from the HTTP headers
+        // if in the form: "Content-Range: bytes x-y/filesize".
+        char* pszContentRange =
+            strstr(sWriteFuncHeaderData.pBuffer, "Content-Range: bytes ");
+        if( pszContentRange )
         {
             char* pszEOL = strchr(pszContentRange, '\n');
-            if (pszEOL)
+            if( pszEOL )
             {
                 *pszEOL = 0;
                 pszEOL = strchr(pszContentRange, '\r');
-                if (pszEOL)
+                if( pszEOL )
                     *pszEOL = 0;
                 char* pszSlash = strchr(pszContentRange, '/');
-                if (pszSlash)
+                if( pszSlash )
                 {
-                    pszSlash ++;
-                    fileSize = CPLScanUIntBig(pszSlash, static_cast<int>(strlen(pszSlash)));
+                    pszSlash++;
+                    fileSize =
+                        CPLScanUIntBig(pszSlash,
+                                       static_cast<int>(strlen(pszSlash)));
                 }
             }
         }
-        else if (STARTS_WITH(pszURL, "ftp"))
+        else if( STARTS_WITH(m_pszURL, "ftp") )
         {
-            /* Parse 213 answer for FTP protocol */
+            // Parse 213 answer for FTP protocol.
             char* pszSize = strstr(sWriteFuncHeaderData.pBuffer, "213 ");
-            if (pszSize)
+            if( pszSize )
             {
                 pszSize += 4;
                 char* pszEOL = strchr(pszSize, '\n');
-                if (pszEOL)
+                if( pszEOL )
                 {
                     *pszEOL = 0;
                     pszEOL = strchr(pszSize, '\r');
-                    if (pszEOL)
+                    if( pszEOL )
                         *pszEOL = 0;
 
-                    fileSize = CPLScanUIntBig(pszSize, static_cast<int>(strlen(pszSize)));
+                    fileSize =
+                        CPLScanUIntBig(pszSize,
+                                       static_cast<int>(strlen(pszSize)));
                 }
             }
         }
 
-        if (fileSize != 0)
+        if( fileSize != 0 )
         {
             eExists = EXIST_YES;
 
-            if (ENABLE_DEBUG)
-                CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB "  response_code=%d",
-                        pszURL, fileSize, (int)response_code);
+            if( ENABLE_DEBUG )
+                CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB
+                         "  response_code=%d",
+                         m_pszURL, fileSize, static_cast<int>(response_code));
 
             bHasComputedFileSize = cachedFileProp->bHasComputedFileSize = true;
             cachedFileProp->fileSize = fileSize;
@@ -1214,20 +1317,30 @@ retry:
     char* pBuffer = sWriteFuncData.pBuffer;
     size_t nSize = sWriteFuncData.nSize;
 
-    if (nSize > static_cast<size_t>(nBlocks) * DOWNLOAD_CHUNK_SIZE)
+    if( nSize > static_cast<size_t>(nBlocks) * DOWNLOAD_CHUNK_SIZE )
     {
-        if (ENABLE_DEBUG)
-            CPLDebug("VSICURL", "Got more data than expected : %u instead of %d",
-                     static_cast<unsigned int>(nSize), nBlocks * DOWNLOAD_CHUNK_SIZE);
+        if( ENABLE_DEBUG )
+            CPLDebug(
+                "VSICURL", "Got more data than expected : %u instead of %u",
+                static_cast<unsigned int>(nSize),
+                static_cast<unsigned int>(nBlocks * DOWNLOAD_CHUNK_SIZE));
     }
 
     vsi_l_offset l_startOffset = startOffset;
-    while(nSize > 0)
+    while( nSize > 0 )
     {
-        //if (ENABLE_DEBUG)
-        //    CPLDebug("VSICURL", "Add region %d - %d", startOffset, MIN(DOWNLOAD_CHUNK_SIZE, nSize));
-        size_t nChunkSize = MIN((size_t)DOWNLOAD_CHUNK_SIZE, nSize);
-        poFS->AddRegion(pszURL, l_startOffset, nChunkSize, pBuffer);
+#if DEBUG_VERBOSE
+        if( ENABLE_DEBUG )
+            CPLDebug(
+                "VSICURL",
+                "Add region %u - %u",
+                static_cast<unsigned int>(startOffset),
+                static_cast<unsigned int>(
+                    std::min(static_cast<size_t>(DOWNLOAD_CHUNK_SIZE), nSize)));
+#endif
+        const size_t nChunkSize =
+            std::min(static_cast<size_t>(DOWNLOAD_CHUNK_SIZE), nSize);
+        poFS->AddRegion(m_pszURL, l_startOffset, nChunkSize, pBuffer);
         l_startOffset += nChunkSize;
         pBuffer += nChunkSize;
         nSize -= nChunkSize;
@@ -1243,52 +1356,63 @@ retry:
 /*                                Read()                                */
 /************************************************************************/
 
-size_t VSICurlHandle::Read( void * const pBufferIn, size_t const  nSize, size_t const  nMemb )
+size_t VSICurlHandle::Read( void * const pBufferIn, size_t const nSize,
+                            size_t const  nMemb )
 {
-    void* pBuffer = pBufferIn;
     size_t nBufferRequestSize = nSize * nMemb;
-    if (nBufferRequestSize == 0)
+    if( nBufferRequestSize == 0 )
         return 0;
 
-    //CPLDebug("VSICURL", "offset=%d, size=%d", (int)curOffset, (int)nBufferRequestSize);
+    void* pBuffer = pBufferIn;
+
+#if DEBUG_VERBOSE
+    CPLDebug("VSICURL", "offset=%d, size=%d",
+             static_cast<int>(curOffset), static_cast<int>(nBufferRequestSize));
+#endif
 
     vsi_l_offset iterOffset = curOffset;
-    while (nBufferRequestSize)
+    while( nBufferRequestSize )
     {
-        const CachedRegion* psRegion = poFS->GetRegion(pszURL, iterOffset);
-        if (psRegion == NULL)
+        const CachedRegion* psRegion = poFS->GetRegion(m_pszURL, iterOffset);
+        if( psRegion == NULL )
         {
-            vsi_l_offset nOffsetToDownload =
+            const vsi_l_offset nOffsetToDownload =
                 (iterOffset / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
 
-            if (nOffsetToDownload == lastDownloadedOffset)
+            if( nOffsetToDownload == lastDownloadedOffset )
             {
-                /* In case of consecutive reads (of small size), we use a */
-                /* heuristic that we will read the file sequentially, so */
-                /* we double the requested size to decrease the number of */
-                /* client/server roundtrips. */
-                if (nBlocksToDownload < 100)
+                // In case of consecutive reads (of small size), we use a
+                // heuristic that we will read the file sequentially, so
+                // we double the requested size to decrease the number of
+                // client/server roundtrips.
+                if( nBlocksToDownload < 100 )
                     nBlocksToDownload *= 2;
             }
             else
             {
-                /* Random reads. Cancel the above heuristics */
+                // Random reads. Cancel the above heuristics.
                 nBlocksToDownload = 1;
             }
 
-            /* Ensure that we will request at least the number of blocks */
-            /* to satisfy the remaining buffer size to read */
-            vsi_l_offset nEndOffsetToDownload =
-                ((iterOffset + nBufferRequestSize) / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
-            int nMinBlocksToDownload = 1 + (int)
-                ((nEndOffsetToDownload - nOffsetToDownload) / DOWNLOAD_CHUNK_SIZE);
-            if (nBlocksToDownload < nMinBlocksToDownload)
+            // Ensure that we will request at least the number of blocks
+            // to satisfy the remaining buffer size to read.
+            const vsi_l_offset nEndOffsetToDownload =
+                ((iterOffset + nBufferRequestSize) / DOWNLOAD_CHUNK_SIZE) *
+                DOWNLOAD_CHUNK_SIZE;
+            const int nMinBlocksToDownload =
+                1 +
+                static_cast<int>(
+                    (nEndOffsetToDownload - nOffsetToDownload) /
+                    DOWNLOAD_CHUNK_SIZE);
+            if( nBlocksToDownload < nMinBlocksToDownload )
                 nBlocksToDownload = nMinBlocksToDownload;
 
-            /* Avoid reading already cached data */
-            for( int i=1; i < nBlocksToDownload; i++ )
+            // Avoid reading already cached data.
+            for( int i = 1; i < nBlocksToDownload; i++ )
             {
-                if (poFS->GetRegion(pszURL, nOffsetToDownload + i * DOWNLOAD_CHUNK_SIZE) != NULL)
+                if( poFS->GetRegion(
+                        m_pszURL,
+                        nOffsetToDownload + i * DOWNLOAD_CHUNK_SIZE) != NULL )
                 {
                     nBlocksToDownload = i;
                     break;
@@ -1298,33 +1422,38 @@ size_t VSICurlHandle::Read( void * const pBufferIn, size_t const  nSize, size_t
             if( nBlocksToDownload > N_MAX_REGIONS )
                 nBlocksToDownload = N_MAX_REGIONS;
 
-            if (DownloadRegion(nOffsetToDownload, nBlocksToDownload) == false)
+            if( DownloadRegion(nOffsetToDownload, nBlocksToDownload) == false )
             {
-                if (!bInterrupted)
+                if( !bInterrupted )
                     bEOF = true;
                 return 0;
             }
-            psRegion = poFS->GetRegion(pszURL, iterOffset);
+            psRegion = poFS->GetRegion(m_pszURL, iterOffset);
         }
-        if (psRegion == NULL || psRegion->pData == NULL)
+        if( psRegion == NULL || psRegion->pData == NULL )
         {
             bEOF = true;
             return 0;
         }
-        int nToCopy = (int) MIN(nBufferRequestSize, psRegion->nSize - (iterOffset - psRegion->nFileOffsetStart));
-        memcpy(pBuffer, psRegion->pData + iterOffset - psRegion->nFileOffsetStart,
-                nToCopy);
-        pBuffer = (char*) pBuffer + nToCopy;
+        const int nToCopy = static_cast<int>(
+            std::min(static_cast<vsi_l_offset>(nBufferRequestSize),
+                     psRegion->nSize -
+                     (iterOffset - psRegion->nFileOffsetStart)));
+        memcpy(pBuffer,
+               psRegion->pData + iterOffset - psRegion->nFileOffsetStart,
+               nToCopy);
+        pBuffer = static_cast<char *>(pBuffer) + nToCopy;
         iterOffset += nToCopy;
         nBufferRequestSize -= nToCopy;
-        if (psRegion->nSize != (size_t)DOWNLOAD_CHUNK_SIZE && nBufferRequestSize != 0)
+        if( psRegion->nSize != static_cast<size_t>(DOWNLOAD_CHUNK_SIZE) &&
+            nBufferRequestSize != 0 )
         {
             break;
         }
     }
 
-    size_t ret = (size_t) ((iterOffset - curOffset) / nSize);
-    if (ret != nMemb)
+    const size_t ret = static_cast<size_t>((iterOffset - curOffset) / nSize);
+    if( ret != nMemb )
         bEOF = true;
 
     curOffset = iterOffset;
@@ -1332,7 +1461,6 @@ size_t VSICurlHandle::Read( void * const pBufferIn, size_t const  nSize, size_t
     return ret;
 }
 
-
 /************************************************************************/
 /*                           ReadMultiRange()                           */
 /************************************************************************/
@@ -1341,88 +1469,101 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
                                    const vsi_l_offset* const panOffsets,
                                    const size_t* const panSizes )
 {
-    WriteFuncStruct sWriteFuncData;
-    WriteFuncStruct sWriteFuncHeaderData;
-
-    if (bInterrupted && bStopOnInterrruptUntilUninstall)
+    if( bInterrupted && bStopOnInterruptUntilUninstall )
         return FALSE;
 
-    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
-    if (cachedFileProp->eExists == EXIST_NO)
+    CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(m_pszURL);
+    if( cachedFileProp->eExists == EXIST_NO )
         return -1;
 
-    CPLString osRanges, osFirstRange, osLastRange;
+    CPLString osRanges;
+    CPLString osFirstRange;
+    CPLString osLastRange;
     int nMergedRanges = 0;
     vsi_l_offset nTotalReqSize = 0;
     for( int i=0; i < nRanges; i++ )
     {
         CPLString osCurRange;
-        if (i != 0)
+        if( i != 0 )
             osRanges.append(",");
         osCurRange = CPLSPrintf(CPL_FRMT_GUIB "-", panOffsets[i]);
-        while (i + 1 < nRanges && panOffsets[i] + panSizes[i] == panOffsets[i+1])
+        while( i + 1 < nRanges &&
+               panOffsets[i] + panSizes[i] == panOffsets[i+1] )
         {
             nTotalReqSize += panSizes[i];
-            i ++;
+            i++;
         }
         nTotalReqSize += panSizes[i];
-        osCurRange.append(CPLSPrintf(CPL_FRMT_GUIB, panOffsets[i] + panSizes[i]-1));
-        nMergedRanges ++;
+        osCurRange.append
+            (CPLSPrintf(CPL_FRMT_GUIB, panOffsets[i] + panSizes[i]-1));
+        nMergedRanges++;
 
         osRanges += osCurRange;
 
-        if (nMergedRanges == 1)
+        if( nMergedRanges == 1 )
             osFirstRange = osCurRange;
         osLastRange = osCurRange;
     }
 
-    const char* pszMaxRanges = CPLGetConfigOption("CPL_VSIL_CURL_MAX_RANGES", "250");
+    const char* pszMaxRanges =
+        CPLGetConfigOption("CPL_VSIL_CURL_MAX_RANGES", "250");
     int nMaxRanges = atoi(pszMaxRanges);
-    if (nMaxRanges <= 0)
+    if( nMaxRanges <= 0 )
         nMaxRanges = 250;
-    if (nMergedRanges > nMaxRanges)
+    if( nMergedRanges > nMaxRanges )
     {
-        int nHalf = nRanges / 2;
-        int nRet = ReadMultiRange(nHalf, ppData, panOffsets, panSizes);
-        if (nRet != 0)
+        const int nHalf = nRanges / 2;
+        const int nRet = ReadMultiRange(nHalf, ppData, panOffsets, panSizes);
+        if( nRet != 0 )
             return nRet;
-        return ReadMultiRange(nRanges - nHalf, ppData + nHalf, panOffsets + nHalf, panSizes + nHalf);
+        return ReadMultiRange(nRanges - nHalf, ppData + nHalf,
+                              panOffsets + nHalf, panSizes + nHalf);
     }
 
-    CURL* hCurlHandle = poFS->GetCurlHandleFor(pszURL);
-    VSICurlSetOptions(hCurlHandle, pszURL);
+    CURL* hCurlHandle = poFS->GetCurlHandleFor(m_pszURL);
+    struct curl_slist* headers =
+        VSICurlSetOptions(hCurlHandle, m_pszURL, m_papszHTTPOptions);
 
-    VSICURLInitWriteFuncStruct(&sWriteFuncData, (VSILFILE*)this, pfnReadCbk, pReadCbkUserData);
+    WriteFuncStruct sWriteFuncData;
+    WriteFuncStruct sWriteFuncHeaderData;
+
+    VSICURLInitWriteFuncStruct(&sWriteFuncData,
+                               reinterpret_cast<VSILFILE *>(this),
+                               pfnReadCbk, pReadCbkUserData);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                     VSICurlHandleWriteFunc);
 
     VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
-    sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(pszURL, "http");
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION,
+                     VSICurlHandleWriteFunc);
+    sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(m_pszURL, "http");
     sWriteFuncHeaderData.bMultiRange = nMergedRanges > 1;
-    if (nMergedRanges == 1)
+    if( nMergedRanges == 1 )
     {
         sWriteFuncHeaderData.nStartOffset = panOffsets[0];
         sWriteFuncHeaderData.nEndOffset = panOffsets[0] + nTotalReqSize-1;
     }
 
-    if (ENABLE_DEBUG)
+    if( ENABLE_DEBUG )
     {
-        if (nMergedRanges == 1)
-            CPLDebug("VSICURL", "Downloading %s (%s)...", osRanges.c_str(), pszURL);
+        if( nMergedRanges == 1 )
+            CPLDebug("VSICURL", "Downloading %s (%s)...",
+                     osRanges.c_str(), m_pszURL);
         else
-            CPLDebug("VSICURL", "Downloading %s, ..., %s (" CPL_FRMT_GUIB " bytes, %s)...",
-                     osFirstRange.c_str(), osLastRange.c_str(), (GUIntBig)nTotalReqSize, pszURL);
+            CPLDebug("VSICURL", "Downloading %s, ..., %s (" CPL_FRMT_GUIB
+                     " bytes, %s)...",
+                     osFirstRange.c_str(), osLastRange.c_str(),
+                     static_cast<GUIntBig>(nTotalReqSize), m_pszURL);
     }
 
     curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, osRanges.c_str());
 
-    char szCurlErrBuf[CURL_ERROR_SIZE+1];
-    szCurlErrBuf[0] = '\0';
+    char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
     curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
-    struct curl_slist* headers = GetCurlHeaders("GET");
+    headers = VSICurlMergeHeaders(headers, GetCurlHeaders("GET"));
     if( headers != NULL )
         curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
 
@@ -1436,7 +1577,7 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, NULL);
 
-    if (sWriteFuncData.bInterrupted)
+    if( sWriteFuncData.bInterrupted )
     {
         bInterrupted = true;
 
@@ -1452,20 +1593,24 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
     char *content_type = NULL;
     curl_easy_getinfo(hCurlHandle, CURLINFO_CONTENT_TYPE, &content_type);
 
-    if ((response_code != 200 && response_code != 206 &&
-         response_code != 225 && response_code != 226 && response_code != 426) || sWriteFuncHeaderData.bError)
+    if( (response_code != 200 && response_code != 206 &&
+         response_code != 225 && response_code != 226 &&
+         response_code != 426)
+        || sWriteFuncHeaderData.bError )
     {
-        if (response_code >= 400 && szCurlErrBuf[0] != '\0')
+        if( response_code >= 400 && szCurlErrBuf[0] != '\0' )
         {
-            if (strcmp(szCurlErrBuf, "Couldn't use REST") == 0)
-                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s, %s",
-                         (int)response_code, szCurlErrBuf,
-                         "Range downloading not supported by this server !");
+            if( strcmp(szCurlErrBuf, "Couldn't use REST") == 0 )
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "%d: %s, Range downloading not supported by this server!",
+                    static_cast<int>(response_code), szCurlErrBuf);
             else
-                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s", (int)response_code, szCurlErrBuf);
+                CPLError(CE_Failure, CPLE_AppDefined, "%d: %s",
+                         static_cast<int>(response_code), szCurlErrBuf);
         }
         /*
-        if (!bHasComputedFileSize && startOffset == 0)
+        if( !bHasComputedFileSize && startOffset == 0 )
         {
             cachedFileProp->bHasComputedFileSize = bHasComputedFileSize = true;
             cachedFileProp->fileSize = fileSize = 0;
@@ -1480,22 +1625,23 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
     char* pBuffer = sWriteFuncData.pBuffer;
     size_t nSize = sWriteFuncData.nSize;
 
+    // TODO(schwehr): Localize after removing gotos.
     int nRet = -1;
     char* pszBoundary;
     CPLString osBoundary;
-    char *pszNext;
+    char *pszNext = NULL;
     int iRange = 0;
     int iPart = 0;
-    char* pszEOL;
+    char* pszEOL = NULL;
 
 /* -------------------------------------------------------------------- */
 /*      No multipart if a single range has been requested               */
 /* -------------------------------------------------------------------- */
 
-    if (nMergedRanges == 1)
+    if( nMergedRanges == 1 )
     {
         size_t nAccSize = 0;
-        if ((vsi_l_offset)nSize < nTotalReqSize)
+        if( static_cast<vsi_l_offset>(nSize) < nTotalReqSize )
             goto end;
 
         for( int i=0; i < nRanges; i++ )
@@ -1524,18 +1670,18 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
     pszBoundary += strlen( "Content-Type: multipart/byteranges; boundary=" );
 
     pszEOL = strchr(pszBoundary, '\r');
-    if (pszEOL)
+    if( pszEOL )
         *pszEOL = 0;
     pszEOL = strchr(pszBoundary, '\n');
-    if (pszEOL)
+    if( pszEOL )
         *pszEOL = 0;
 
     /* Remove optional double-quote character around boundary name */
-    if (pszBoundary[0] == '"')
+    if( pszBoundary[0] == '"' )
     {
-        pszBoundary ++;
+        pszBoundary++;
         char* pszLastDoubleQuote = strrchr(pszBoundary, '"');
-        if (pszLastDoubleQuote)
+        if( pszLastDoubleQuote )
             *pszLastDoubleQuote = 0;
     }
 
@@ -1545,14 +1691,14 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
 /* -------------------------------------------------------------------- */
 /*      Find the start of the first chunk.                              */
 /* -------------------------------------------------------------------- */
-    pszNext = strstr(pBuffer,osBoundary.c_str());
+    pszNext = strstr(pBuffer, osBoundary.c_str());
     if( pszNext == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined, "No parts found." );
         goto end;
     }
 
-    pszNext += strlen(osBoundary);
+    pszNext += osBoundary.size();
     while( *pszNext != '\n' && *pszNext != '\r' && *pszNext != '\0' )
         pszNext++;
     if( *pszNext == '\r' )
@@ -1572,39 +1718,41 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
 
         while( *pszNext != '\n' && *pszNext != '\r' && *pszNext != '\0' )
         {
-            pszEOL = strstr(pszNext,"\n");
+            pszEOL = strstr(pszNext, "\n");
 
             if( pszEOL == NULL )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
-                         "Error while parsing multipart content (at line %d)", __LINE__);
+                         "Error while parsing multipart content (at line %d)",
+                         __LINE__);
                 goto end;
             }
 
             *pszEOL = '\0';
             bool bRestoreAntislashR = false;
-            if (pszEOL - pszNext > 1 && pszEOL[-1] == '\r')
+            if( pszEOL - pszNext > 1 && pszEOL[-1] == '\r' )
             {
                 bRestoreAntislashR = true;
                 pszEOL[-1] = '\0';
             }
 
-            if (STARTS_WITH_CI(pszNext, "Content-Range: bytes "))
+            if( STARTS_WITH_CI(pszNext, "Content-Range: bytes ") )
             {
                 bExpectedRange = true; /* FIXME */
             }
 
-            if (bRestoreAntislashR)
+            if( bRestoreAntislashR )
                 pszEOL[-1] = '\r';
             *pszEOL = '\n';
 
             pszNext = pszEOL + 1;
         }
 
-        if (!bExpectedRange)
+        if( !bExpectedRange )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                        "Error while parsing multipart content (at line %d)", __LINE__);
+                     "Error while parsing multipart content (at line %d)",
+                     __LINE__);
             goto end;
         }
 
@@ -1618,12 +1766,13 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
 /* -------------------------------------------------------------------- */
         size_t nBytesAvail = nSize - (pszNext - pBuffer);
 
-        while(true)
+        while( true )
         {
-            if (nBytesAvail < panSizes[iRange])
+            if( nBytesAvail < panSizes[iRange] )
             {
                 CPLError(CE_Failure, CPLE_AppDefined,
-                            "Error while parsing multipart content (at line %d)", __LINE__);
+                         "Error while parsing multipart content (at line %d)",
+                         __LINE__);
                 goto end;
             }
 
@@ -1631,20 +1780,23 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
             pszNext += panSizes[iRange];
             nBytesAvail -= panSizes[iRange];
             if( iRange + 1 < nRanges &&
-                panOffsets[iRange] + panSizes[iRange] == panOffsets[iRange + 1] )
+                panOffsets[iRange] + panSizes[iRange] ==
+                panOffsets[iRange + 1] )
             {
                 iRange++;
             }
             else
+            {
                 break;
+            }
         }
 
-        iPart ++;
-        iRange ++;
+        iPart++;
+        iRange++;
 
         while( nBytesAvail > 0
                && (*pszNext != '-'
-                   || strncmp(pszNext,osBoundary,strlen(osBoundary)) != 0) )
+                   || strncmp(pszNext, osBoundary, osBoundary.size()) != 0) )
         {
             pszNext++;
             nBytesAvail--;
@@ -1653,14 +1805,15 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
         if( nBytesAvail == 0 )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                        "Error while parsing multipart content (at line %d)", __LINE__);
+                     "Error while parsing multipart content (at line %d)",
+                     __LINE__);
             goto end;
         }
 
-        pszNext += strlen(osBoundary);
+        pszNext += osBoundary.size();
         if( STARTS_WITH(pszNext, "--") )
         {
-            /* End of multipart */
+            // End of multipart.
             break;
         }
 
@@ -1671,16 +1824,18 @@ int VSICurlHandle::ReadMultiRange( int const nRanges, void ** const ppData,
         else
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                        "Error while parsing multipart content (at line %d)", __LINE__);
+                     "Error while parsing multipart content (at line %d)",
+                     __LINE__);
             goto end;
         }
     }
 
-    if (iPart == nMergedRanges)
+    if( iPart == nMergedRanges )
         nRet = 0;
     else
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Got only %d parts, where %d were expected", iPart, nMergedRanges);
+                 "Got only %d parts, where %d were expected",
+                 iPart, nMergedRanges);
 
 end:
     CPLFree(sWriteFuncData.pBuffer);
@@ -1693,9 +1848,9 @@ end:
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSICurlHandle::Write( CPL_UNUSED const void *pBuffer,
-                             CPL_UNUSED size_t nSize,
-                             CPL_UNUSED size_t nMemb )
+size_t VSICurlHandle::Write( const void * /* pBuffer */,
+                             size_t /* nSize */,
+                             size_t /* nMemb */ )
 {
     return 0;
 }
@@ -1704,7 +1859,6 @@ size_t VSICurlHandle::Write( CPL_UNUSED const void *pBuffer,
 /*                                 Eof()                                */
 /************************************************************************/
 
-
 int       VSICurlHandle::Eof()
 {
     return bEOF;
@@ -1728,9 +1882,6 @@ int       VSICurlHandle::Close()
     return 0;
 }
 
-
-
-
 /************************************************************************/
 /*                   VSICurlFilesystemHandler()                         */
 /************************************************************************/
@@ -1740,7 +1891,8 @@ VSICurlFilesystemHandler::VSICurlFilesystemHandler()
     hMutex = NULL;
     papsRegions = NULL;
     nRegions = 0;
-    bUseCacheDisk = CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_USE_CACHE", "NO"));
+    bUseCacheDisk =
+        CPLTestBool(CPLGetConfigOption("CPL_VSIL_CURL_USE_CACHE", "NO"));
 }
 
 /************************************************************************/
@@ -1758,21 +1910,27 @@ VSICurlFilesystemHandler::~VSICurlFilesystemHandler()
 
     std::map<CPLString, CachedFileProp*>::const_iterator iterCacheFileSize;
 
-    for( iterCacheFileSize = cacheFileSize.begin(); iterCacheFileSize != cacheFileSize.end(); iterCacheFileSize++ )
+    for( iterCacheFileSize = cacheFileSize.begin();
+         iterCacheFileSize != cacheFileSize.end();
+         ++iterCacheFileSize )
     {
         delete iterCacheFileSize->second;
     }
 
     std::map<CPLString, CachedDirList*>::const_iterator iterCacheDirList;
 
-    for( iterCacheDirList = cacheDirList.begin(); iterCacheDirList != cacheDirList.end(); iterCacheDirList++ )
+    for( iterCacheDirList = cacheDirList.begin();
+         iterCacheDirList != cacheDirList.end();
+         ++iterCacheDirList )
     {
         CSLDestroy(iterCacheDirList->second->papszFileList);
         CPLFree(iterCacheDirList->second);
     }
 
     std::map<GIntBig, CachedConnection*>::const_iterator iterConnections;
-    for( iterConnections = mapConnections.begin(); iterConnections != mapConnections.end(); iterConnections++ )
+    for( iterConnections = mapConnections.begin();
+         iterConnections != mapConnections.end();
+         ++iterConnections )
     {
         curl_easy_cleanup(iterConnections->second->hCurlHandle);
         delete iterConnections->second;
@@ -1791,10 +1949,9 @@ CURL* VSICurlFilesystemHandler::GetCurlHandleFor(CPLString osURL)
 {
     CPLMutexHolder oHolder( &hMutex );
 
-    std::map<GIntBig, CachedConnection*>::const_iterator iterConnections;
-
-    iterConnections = mapConnections.find(CPLGetPID());
-    if (iterConnections == mapConnections.end())
+    std::map<GIntBig, CachedConnection*>::const_iterator iterConnections =
+        mapConnections.find(CPLGetPID());
+    if( iterConnections == mapConnections.end() )
     {
         CURL* hCurlHandle = curl_easy_init();
         CachedConnection* psCachedConnection = new CachedConnection;
@@ -1803,33 +1960,30 @@ CURL* VSICurlFilesystemHandler::GetCurlHandleFor(CPLString osURL)
         mapConnections[CPLGetPID()] = psCachedConnection;
         return hCurlHandle;
     }
-    else
-    {
-        CachedConnection* psCachedConnection = iterConnections->second;
-        if (osURL == psCachedConnection->osURL)
-            return psCachedConnection->hCurlHandle;
-
-        const char* pszURL = osURL.c_str();
-        const char* pszEndOfServ = strchr(pszURL, '.');
-        if (pszEndOfServ != NULL)
-            pszEndOfServ = strchr(pszEndOfServ, '/');
-        if (pszEndOfServ == NULL)
-            pszURL = pszURL + strlen(pszURL);
-        bool bReinitConnection = strncmp(psCachedConnection->osURL,
-                                        pszURL, pszEndOfServ-pszURL) != 0;
-
-        if (bReinitConnection)
-        {
-            if (psCachedConnection->hCurlHandle)
-                curl_easy_cleanup(psCachedConnection->hCurlHandle);
-            psCachedConnection->hCurlHandle = curl_easy_init();
-        }
-        psCachedConnection->osURL = osURL;
 
+    CachedConnection* psCachedConnection = iterConnections->second;
+    if( osURL == psCachedConnection->osURL )
         return psCachedConnection->hCurlHandle;
+
+    const char* pszURL = osURL.c_str();
+    const char* pszEndOfServ = strchr(pszURL, '.');
+    if( pszEndOfServ != NULL )
+        pszEndOfServ = strchr(pszEndOfServ, '/');
+    if( pszEndOfServ == NULL )
+        pszURL = pszURL + strlen(pszURL);
+    const bool bReinitConnection =
+        strncmp(psCachedConnection->osURL, pszURL, pszEndOfServ-pszURL) != 0;
+
+    if( bReinitConnection )
+    {
+        if( psCachedConnection->hCurlHandle )
+            curl_easy_cleanup(psCachedConnection->hCurlHandle);
+        psCachedConnection->hCurlHandle = curl_easy_init();
     }
-}
+    psCachedConnection->osURL = osURL;
 
+    return psCachedConnection->hCurlHandle;
+}
 
 /************************************************************************/
 /*                   GetRegionFromCacheDisk()                           */
@@ -1839,30 +1993,34 @@ const CachedRegion*
 VSICurlFilesystemHandler::GetRegionFromCacheDisk(const char* pszURL,
                                                  vsi_l_offset nFileOffsetStart)
 {
-    nFileOffsetStart = (nFileOffsetStart / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
+    nFileOffsetStart =
+        (nFileOffsetStart / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
     VSILFILE* fp = VSIFOpenL(VSICurlGetCacheFileName(), "rb");
-    if (fp)
+    if( fp )
     {
-        unsigned long   pszURLHash = CPLHashSetHashStr(pszURL);
-        vsi_l_offset    nFileOffsetStartCached;
-        while(true)
+        const unsigned long pszURLHash = CPLHashSetHashStr(pszURL);
+        while( true )
         {
             unsigned long pszURLHashCached = 0;
-            if (VSIFReadL(&pszURLHashCached, sizeof(unsigned long), 1, fp) == 0)
+            if( VSIFReadL(&pszURLHashCached, sizeof(unsigned long),
+                          1, fp) == 0 )
                 break;
-            if( VSIFReadL(&nFileOffsetStartCached, sizeof(vsi_l_offset), 1, fp) == 0)
+            vsi_l_offset nFileOffsetStartCached = 0;
+            if( VSIFReadL(&nFileOffsetStartCached, sizeof(vsi_l_offset),
+                          1, fp) == 0)
                 break;
             size_t nSizeCached = 0;
             if( VSIFReadL(&nSizeCached, sizeof(size_t), 1, fp) == 0)
                 break;
-            if (pszURLHash == pszURLHashCached &&
-                nFileOffsetStart == nFileOffsetStartCached)
+            if( pszURLHash == pszURLHashCached &&
+                nFileOffsetStart == nFileOffsetStartCached )
             {
-                if (ENABLE_DEBUG)
-                    CPLDebug("VSICURL", "Got data at offset " CPL_FRMT_GUIB " from disk" , nFileOffsetStart);
-                if (nSizeCached)
+                if( ENABLE_DEBUG )
+                    CPLDebug("VSICURL", "Got data at offset "
+                             CPL_FRMT_GUIB " from disk", nFileOffsetStart);
+                if( nSizeCached )
                 {
-                    char* pBuffer = (char*) CPLMalloc(nSizeCached);
+                    char* pBuffer = static_cast<char *>(CPLMalloc(nSizeCached));
                     if( VSIFReadL(pBuffer, 1, nSizeCached, fp) != nSizeCached )
                     {
                         CPLFree(pBuffer);
@@ -1889,7 +2047,6 @@ VSICurlFilesystemHandler::GetRegionFromCacheDisk(const char* pszURL,
     return NULL;
 }
 
-
 /************************************************************************/
 /*                  AddRegionToCacheDisk()                                */
 /************************************************************************/
@@ -1897,21 +2054,23 @@ VSICurlFilesystemHandler::GetRegionFromCacheDisk(const char* pszURL,
 void VSICurlFilesystemHandler::AddRegionToCacheDisk(CachedRegion* psRegion)
 {
     VSILFILE* fp = VSIFOpenL(VSICurlGetCacheFileName(), "r+b");
-    if (fp)
+    if( fp )
     {
-        while(true)
+        while( true )
         {
             unsigned long pszURLHashCached = 0;
-            if (VSIFReadL(&pszURLHashCached, 1, sizeof(unsigned long), fp) == 0)
+            if( VSIFReadL(&pszURLHashCached, 1, sizeof(unsigned long),
+                          fp) == 0 )
                 break;
             vsi_l_offset nFileOffsetStartCached = 0;
-            if( VSIFReadL(&nFileOffsetStartCached, sizeof(vsi_l_offset), 1, fp) == 0 )
+            if( VSIFReadL(&nFileOffsetStartCached, sizeof(vsi_l_offset), 1, fp)
+                == 0 )
                 break;
             size_t nSizeCached = 0;
             if( VSIFReadL(&nSizeCached, sizeof(size_t), 1, fp) == 0 )
                 break;
-            if (psRegion->pszURLHash == pszURLHashCached &&
-                psRegion->nFileOffsetStart == nFileOffsetStartCached)
+            if( psRegion->pszURLHash == pszURLHashCached &&
+                psRegion->nFileOffsetStart == nFileOffsetStartCached )
             {
                 CPLAssert(psRegion->nSize == nSizeCached);
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
@@ -1928,47 +2087,53 @@ void VSICurlFilesystemHandler::AddRegionToCacheDisk(CachedRegion* psRegion)
     {
         fp = VSIFOpenL(VSICurlGetCacheFileName(), "wb");
     }
-    if (fp)
+    if( fp )
     {
-        if (ENABLE_DEBUG)
-             CPLDebug("VSICURL", "Write data at offset " CPL_FRMT_GUIB " to disk" , psRegion->nFileOffsetStart);
-        CPL_IGNORE_RET_VAL(VSIFWriteL(&psRegion->pszURLHash, 1, sizeof(unsigned long), fp));
-        CPL_IGNORE_RET_VAL(VSIFWriteL(&psRegion->nFileOffsetStart, 1, sizeof(vsi_l_offset), fp));
+        if( ENABLE_DEBUG )
+            CPLDebug("VSICURL",
+                     "Write data at offset " CPL_FRMT_GUIB " to disk",
+                     psRegion->nFileOffsetStart);
+        CPL_IGNORE_RET_VAL(VSIFWriteL(&psRegion->pszURLHash, 1,
+                                      sizeof(unsigned long), fp));
+        CPL_IGNORE_RET_VAL(VSIFWriteL(&psRegion->nFileOffsetStart, 1,
+                                      sizeof(vsi_l_offset), fp));
         CPL_IGNORE_RET_VAL(VSIFWriteL(&psRegion->nSize, 1, sizeof(size_t), fp));
-        if (psRegion->nSize)
-            CPL_IGNORE_RET_VAL(VSIFWriteL(psRegion->pData, 1, psRegion->nSize, fp));
+        if( psRegion->nSize )
+            CPL_IGNORE_RET_VAL(
+                VSIFWriteL(psRegion->pData, 1, psRegion->nSize, fp));
 
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
     }
     return;
 }
 
-
 /************************************************************************/
 /*                          GetRegion()                                 */
 /************************************************************************/
 
-const CachedRegion* VSICurlFilesystemHandler::GetRegion(const char* pszURL,
-                                                        vsi_l_offset nFileOffsetStart)
+const CachedRegion*
+VSICurlFilesystemHandler::GetRegion( const char* pszURL,
+                                     vsi_l_offset nFileOffsetStart )
 {
     CPLMutexHolder oHolder( &hMutex );
 
-    unsigned long   pszURLHash = CPLHashSetHashStr(pszURL);
+    const unsigned long pszURLHash = CPLHashSetHashStr(pszURL);
 
-    nFileOffsetStart = (nFileOffsetStart / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
+    nFileOffsetStart =
+        (nFileOffsetStart / DOWNLOAD_CHUNK_SIZE) * DOWNLOAD_CHUNK_SIZE;
 
-    for( int i=0; i < nRegions; i++ )
+    for( int i = 0; i < nRegions; i++ )
     {
         CachedRegion* psRegion = papsRegions[i];
-        if (psRegion->pszURLHash == pszURLHash &&
-            nFileOffsetStart == psRegion->nFileOffsetStart)
+        if( psRegion->pszURLHash == pszURLHash &&
+            nFileOffsetStart == psRegion->nFileOffsetStart )
         {
             memmove(papsRegions + 1, papsRegions, i * sizeof(CachedRegion*));
             papsRegions[0] = psRegion;
             return psRegion;
         }
     }
-    if (bUseCacheDisk)
+    if( bUseCacheDisk )
         return GetRegionFromCacheDisk(pszURL, nFileOffsetStart);
     return NULL;
 }
@@ -1977,40 +2142,46 @@ const CachedRegion* VSICurlFilesystemHandler::GetRegion(const char* pszURL,
 /*                          AddRegion()                                 */
 /************************************************************************/
 
-void  VSICurlFilesystemHandler::AddRegion(const char* pszURL,
-                                          vsi_l_offset    nFileOffsetStart,
-                                          size_t          nSize,
-                                          const char     *pData)
+void VSICurlFilesystemHandler::AddRegion( const char* pszURL,
+                                          vsi_l_offset nFileOffsetStart,
+                                          size_t nSize,
+                                          const char *pData )
 {
     CPLMutexHolder oHolder( &hMutex );
 
-    unsigned long   pszURLHash = CPLHashSetHashStr(pszURL);
+    const unsigned long pszURLHash = CPLHashSetHashStr(pszURL);
 
-    CachedRegion* psRegion;
-    if (nRegions == N_MAX_REGIONS)
+    CachedRegion* psRegion = NULL;
+    if( nRegions == N_MAX_REGIONS )
     {
         psRegion = papsRegions[N_MAX_REGIONS-1];
-        memmove(papsRegions + 1, papsRegions, (N_MAX_REGIONS-1) * sizeof(CachedRegion*));
+        memmove(papsRegions + 1,
+                papsRegions,
+                (N_MAX_REGIONS-1) * sizeof(CachedRegion*));
         papsRegions[0] = psRegion;
         CPLFree(psRegion->pData);
     }
     else
     {
-        papsRegions = (CachedRegion**) CPLRealloc(papsRegions, (nRegions + 1) * sizeof(CachedRegion*));
-        if (nRegions)
-            memmove(papsRegions + 1, papsRegions, nRegions * sizeof(CachedRegion*));
-        nRegions ++;
-        papsRegions[0] = psRegion = (CachedRegion*) CPLMalloc(sizeof(CachedRegion));
+        papsRegions = static_cast<CachedRegion **>(
+            CPLRealloc(papsRegions, (nRegions + 1) * sizeof(CachedRegion*)));
+        if( nRegions )
+            memmove(papsRegions + 1,
+                    papsRegions,
+                    nRegions * sizeof(CachedRegion*));
+        nRegions++;
+        psRegion = static_cast<CachedRegion *>(CPLMalloc(sizeof(CachedRegion)));
+        papsRegions[0] = psRegion;
     }
 
     psRegion->pszURLHash = pszURLHash;
     psRegion->nFileOffsetStart = nFileOffsetStart;
     psRegion->nSize = nSize;
-    psRegion->pData = (nSize) ? (char*) CPLMalloc(nSize) : NULL;
-    if (nSize)
+    psRegion->pData = nSize ? static_cast<char *>(CPLMalloc(nSize)) : NULL;
+    if( nSize )
         memcpy(psRegion->pData, pData, nSize);
 
-    if (bUseCacheDisk)
+    if( bUseCacheDisk )
         AddRegionToCacheDisk(psRegion);
 }
 
@@ -2018,12 +2189,13 @@ void  VSICurlFilesystemHandler::AddRegion(const char* pszURL,
 /*                         GetCachedFileProp()                          */
 /************************************************************************/
 
-CachedFileProp*  VSICurlFilesystemHandler::GetCachedFileProp(const char* pszURL)
+CachedFileProp *
+VSICurlFilesystemHandler::GetCachedFileProp( const char* pszURL )
 {
     CPLMutexHolder oHolder( &hMutex );
 
     CachedFileProp* cachedFileProp = cacheFileSize[pszURL];
-    if (cachedFileProp == NULL)
+    if( cachedFileProp == NULL )
     {
         cachedFileProp = new CachedFileProp;
         cacheFileSize[pszURL] = cachedFileProp;
@@ -2036,11 +2208,12 @@ CachedFileProp*  VSICurlFilesystemHandler::GetCachedFileProp(const char* pszURL)
 /*                    InvalidateCachedFileProp()                        */
 /************************************************************************/
 
-void VSICurlFilesystemHandler::InvalidateCachedFileProp(const char* pszURL)
+void VSICurlFilesystemHandler::InvalidateCachedFileProp( const char* pszURL )
 {
     CPLMutexHolder oHolder( &hMutex );
 
-    std::map<CPLString, CachedFileProp*>::iterator oIter = cacheFileSize.find(pszURL);
+    std::map<CPLString, CachedFileProp*>::iterator oIter =
+        cacheFileSize.find(pszURL);
     if( oIter != cacheFileSize.end() )
     {
         delete oIter->second;
@@ -2052,9 +2225,10 @@ void VSICurlFilesystemHandler::InvalidateCachedFileProp(const char* pszURL)
 /*                          CreateFileHandle()                          */
 /************************************************************************/
 
-VSICurlHandle* VSICurlFilesystemHandler::CreateFileHandle(const char* pszURL)
+VSICurlHandle* VSICurlFilesystemHandler::CreateFileHandle(
+                                                const char* pszUnprefixed )
 {
-    return new VSICurlHandle(this, pszURL);
+    return new VSICurlHandle(this, pszUnprefixed);
 }
 
 /************************************************************************/
@@ -2063,28 +2237,29 @@ VSICurlHandle* VSICurlFilesystemHandler::CreateFileHandle(const char* pszURL)
 
 static bool IsAllowedFilename( const char* pszFilename )
 {
-    const char* pszAllowedFilename = 
+    const char* pszAllowedFilename =
         CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_FILENAME", NULL);
     if( pszAllowedFilename != NULL )
     {
         return strcmp( pszFilename, pszAllowedFilename ) == 0;
     }
 
-    /* Consider that only the files whose extension ends up with one that is */
-    /* listed in CPL_VSIL_CURL_ALLOWED_EXTENSIONS exist on the server */
-    /* This can speeds up dramatically open experience, in case the server */
-    /* cannot return a file list */
-    /* {noext} can be used as a special token to mean file with no extension */
-    /* For example : */
-    /* gdalinfo --config CPL_VSIL_CURL_ALLOWED_EXTENSIONS ".tif" /vsicurl/http://igskmncngs506.cr.usgs.gov/gmted/Global_tiles_GMTED/075darcsec/bln/W030/30N030W_20101117_gmted_bln075.tif */
+    // Consider that only the files whose extension ends up with one that is
+    // listed in CPL_VSIL_CURL_ALLOWED_EXTENSIONS exist on the server.  This can
+    // speeds up dramatically open experience, in case the server cannot return
+    // a file list.  {noext} can be used as a special token to mean file with no
+    // extension.
+    // For example:
+    // gdalinfo --config CPL_VSIL_CURL_ALLOWED_EXTENSIONS ".tif" /vsicurl/http://igskmncngs506.cr.usgs.gov/gmted/Global_tiles_GMTED/075darcsec/bln/W030/30N030W_20101117_gmted_bln075.tif
     const char* pszAllowedExtensions =
         CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", NULL);
-    if (pszAllowedExtensions)
+    if( pszAllowedExtensions )
     {
-        char** papszExtensions = CSLTokenizeString2( pszAllowedExtensions, ", ", 0 );
+        char** papszExtensions =
+            CSLTokenizeString2( pszAllowedExtensions, ", ", 0 );
         const size_t nURLLen = strlen(pszFilename);
         bool bFound = false;
-        for(int i=0;papszExtensions[i] != NULL;i++)
+        for( int i = 0; papszExtensions[i] != NULL; i++ )
         {
             const size_t nExtensionLen = strlen(papszExtensions[i]);
             if( EQUAL(papszExtensions[i], "{noext}") )
@@ -2096,8 +2271,9 @@ static bool IsAllowedFilename( const char* pszFilename )
                     break;
                 }
             }
-            else if (nURLLen > nExtensionLen &&
-                EQUAL(pszFilename + nURLLen - nExtensionLen, papszExtensions[i]))
+            else if( nURLLen > nExtensionLen &&
+                     EQUAL(pszFilename + nURLLen - nExtensionLen,
+                           papszExtensions[i]) )
             {
                 bFound = true;
                 break;
@@ -2119,8 +2295,8 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
                                                   const char *pszAccess,
                                                   bool bSetError )
 {
-    if (strchr(pszAccess, 'w') != NULL ||
-        strchr(pszAccess, '+') != NULL)
+    if( strchr(pszAccess, 'w') != NULL ||
+        strchr(pszAccess, '+') != NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Only read-only mode is supported for /vsicurl");
@@ -2131,37 +2307,59 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
 
     const char* pszOptionVal =
         CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
-    const bool bSkipReadDir = EQUAL(pszOptionVal, "EMPTY_DIR") ||
-                              CSLTestBoolean(pszOptionVal);
+    const bool bSkipReadDir =
+        EQUAL(pszOptionVal, "EMPTY_DIR") || CPLTestBool(pszOptionVal);
 
     CPLString osFilename(pszFilename);
     bool bGotFileList = true;
-    if (strchr(CPLGetFilename(osFilename), '.') != NULL &&
+    bool bForceExistsCheck = false;
+    CachedFileProp* cachedFileProp =
+        GetCachedFileProp(osFilename + strlen(GetFSPrefix()));
+    if( !(cachedFileProp != NULL && cachedFileProp->eExists == EXIST_YES) &&
+        strchr(CPLGetFilename(osFilename), '.') != NULL &&
         !STARTS_WITH(CPLGetExtension(osFilename), "zip") && !bSkipReadDir)
     {
-        char** papszFileList = ReadDirInternal(CPLGetDirname(osFilename), 0, &bGotFileList);
-        const bool bFound = (VSICurlIsFileInList(papszFileList, CPLGetFilename(osFilename)) != -1);
-        CSLDestroy(papszFileList);
-        if (bGotFileList && !bFound)
+        char** papszFileList =
+            ReadDirInternal(CPLGetDirname(osFilename), 0, &bGotFileList);
+        const bool bFound =
+            VSICurlIsFileInList(papszFileList,
+                                CPLGetFilename(osFilename)) != -1;
+        if( bGotFileList && !bFound )
         {
-            return NULL;
+            // Some file servers are case insensitive, so in case there is a
+            // match with case difference, do a full check just in case.
+            // e.g.
+            // http://pds-geosciences.wustl.edu/mgs/mgs-m-mola-5-megdr-l3-v1/mgsl_300x/meg004/MEGA90N000CB.IMG
+            // that is queried by
+            // gdalinfo /vsicurl/http://pds-geosciences.wustl.edu/mgs/mgs-m-mola-5-megdr-l3-v1/mgsl_300x/meg004/mega90n000cb.lbl
+            if( CSLFindString(papszFileList, CPLGetFilename(osFilename)) != -1 )
+            {
+                bForceExistsCheck = true;
+            }
+            else
+            {
+                CSLDestroy(papszFileList);
+                return NULL;
+            }
         }
+        CSLDestroy(papszFileList);
     }
 
-    VSICurlHandle* poHandle = CreateFileHandle(osFilename + strlen(GetFSPrefix()));
+    VSICurlHandle* poHandle =
+        CreateFileHandle(osFilename + strlen(GetFSPrefix()));
     if( poHandle == NULL )
         return NULL;
-    if (!bGotFileList)
+    if( !bGotFileList || bForceExistsCheck )
     {
-        /* If we didn't get a filelist, check that the file really exists */
-        if (!poHandle->Exists(bSetError))
+        // If we didn't get a filelist, check that the file really exists.
+        if( !poHandle->Exists(bSetError) )
         {
             delete poHandle;
             return NULL;
         }
     }
 
-    if( CSLTestBoolean( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
         return VSICreateCachedFile( poHandle );
     else
         return poHandle;
@@ -2178,15 +2376,15 @@ VSIVirtualHandle* VSICurlFilesystemHandler::Open( const char *pszFilename,
 static char *VSICurlParserFindEOL( char *pszData )
 
 {
-    while( *pszData != '\0' && *pszData != '\n' && !STARTS_WITH_CI(pszData, "<br>") )
+    while( *pszData != '\0' && *pszData != '\n' &&
+           !STARTS_WITH_CI(pszData, "<br>") )
         pszData++;
 
     if( *pszData == '\0' )
         return NULL;
-    else
-        return pszData;
-}
 
+    return pszData;
+}
 
 /************************************************************************/
 /*                   VSICurlParseHTMLDateTimeFileSize()                 */
@@ -2197,14 +2395,14 @@ static const char* const apszMonths[] = { "January", "February", "March",
                                           "August", "September", "October",
                                           "November", "December" };
 
-static bool VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
-                                            struct tm& brokendowntime,
-                                            GUIntBig& nFileSize,
-                                            GIntBig& mTime)
+static bool VSICurlParseHTMLDateTimeFileSize( const char* pszStr,
+                                              struct tm& brokendowntime,
+                                              GUIntBig& nFileSize,
+                                              GIntBig& mTime )
 {
-    for(int iMonth=0;iMonth<12;iMonth++)
+    for( int iMonth = 0; iMonth < 12; iMonth++ )
     {
-        char szMonth[32];
+        char szMonth[32] = {};
         szMonth[0] = '-';
         memcpy(szMonth + 1, apszMonths[iMonth], 3);
         szMonth[4] = '-';
@@ -2212,18 +2410,19 @@ static bool VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
         const char* pszMonthFound = strstr(pszStr, szMonth);
         if (pszMonthFound)
         {
-            /* Format of Apache, like in http://download.osgeo.org/gdal/data/gtiff/ */
-            /* "17-May-2010 12:26" */
-            if (pszMonthFound - pszStr > 2 && strlen(pszMonthFound) > 15 &&
-                pszMonthFound[-2 + 11] == ' ' && pszMonthFound[-2 + 14] == ':')
+            // Format of Apache, like in
+            // http://download.osgeo.org/gdal/data/gtiff/
+            // "17-May-2010 12:26"
+            if( pszMonthFound - pszStr > 2 && strlen(pszMonthFound) > 15 &&
+                pszMonthFound[-2 + 11] == ' ' && pszMonthFound[-2 + 14] == ':' )
             {
                 pszMonthFound -= 2;
                 int nDay = atoi(pszMonthFound);
                 int nYear = atoi(pszMonthFound + 7);
                 int nHour = atoi(pszMonthFound + 12);
                 int nMin = atoi(pszMonthFound + 15);
-                if (nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
-                    nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60)
+                if( nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
+                    nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60 )
                 {
                     brokendowntime.tm_year = nYear - 1900;
                     brokendowntime.tm_mon = iMonth;
@@ -2239,46 +2438,47 @@ static bool VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
         }
 
         /* Microsoft IIS */
-        szMonth[0] = ' ';
-        strcpy(szMonth + 1, apszMonths[iMonth]);
-        strcat(szMonth, " ");
+        snprintf( szMonth, sizeof(szMonth), " %s ", apszMonths[iMonth] );
         pszMonthFound = strstr(pszStr, szMonth);
-        if (pszMonthFound)
+        if( pszMonthFound )
         {
             int nLenMonth = static_cast<int>(strlen(apszMonths[iMonth]));
-            if (pszMonthFound - pszStr > 2 &&
+            if( pszMonthFound - pszStr > 2 &&
                 pszMonthFound[-1] != ',' &&
                 pszMonthFound[-2] != ' ' &&
-                (int)strlen(pszMonthFound-2) > 2 + 1 + nLenMonth + 1 + 4 + 1 + 5 + 1 + 4)
+                static_cast<int>(strlen(pszMonthFound - 2)) >
+                2 + 1 + nLenMonth + 1 + 4 + 1 + 5 + 1 + 4 )
             {
                 /* Format of http://ortho.linz.govt.nz/tifs/1994_95/ */
                 /* "        Friday, 21 April 2006 12:05 p.m.     48062343 m35a_fy_94_95.tif" */
                 pszMonthFound -= 2;
-                    int nDay = atoi(pszMonthFound);
+                int nDay = atoi(pszMonthFound);
                 int nCurOffset = 2 + 1 + nLenMonth + 1;
                 int nYear = atoi(pszMonthFound + nCurOffset);
                 nCurOffset += 4 + 1;
                 int nHour = atoi(pszMonthFound + nCurOffset);
-                if (nHour < 10)
+                if( nHour < 10 )
                     nCurOffset += 1 + 1;
                 else
                     nCurOffset += 2 + 1;
-                int nMin = atoi(pszMonthFound + nCurOffset);
+                const int nMin = atoi(pszMonthFound + nCurOffset);
                 nCurOffset += 2 + 1;
-                if (STARTS_WITH(pszMonthFound + nCurOffset, "p.m."))
+                if( STARTS_WITH(pszMonthFound + nCurOffset, "p.m.") )
                     nHour += 12;
-                else if (!STARTS_WITH(pszMonthFound + nCurOffset, "a.m."))
+                else if( !STARTS_WITH(pszMonthFound + nCurOffset, "a.m.") )
                     nHour = -1;
                 nCurOffset += 4;
 
                 const char* pszFilesize = pszMonthFound + nCurOffset;
-                while(*pszFilesize == ' ')
-                    pszFilesize ++;
-                if (*pszFilesize >= '1' && *pszFilesize <= '9')
-                    nFileSize = CPLScanUIntBig(pszFilesize, static_cast<int>(strlen(pszFilesize)));
-
-                if (nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
-                    nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60)
+                while( *pszFilesize == ' ' )
+                    pszFilesize++;
+                if( *pszFilesize >= '1' && *pszFilesize <= '9' )
+                    nFileSize =
+                        CPLScanUIntBig(pszFilesize,
+                                       static_cast<int>(strlen(pszFilesize)));
+
+                if( nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
+                    nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60 )
                 {
                     brokendowntime.tm_year = nYear - 1900;
                     brokendowntime.tm_mon = iMonth;
@@ -2291,12 +2491,13 @@ static bool VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                 }
                 nFileSize = 0;
             }
-            else if (pszMonthFound - pszStr > 1 &&
-                        pszMonthFound[-1] == ',' &&
-                        (int)strlen(pszMonthFound) > 1 + nLenMonth + 1 + 2 + 1 + 1 + 4 + 1 + 5 + 1 + 2)
+            else if( pszMonthFound - pszStr > 1 &&
+                     pszMonthFound[-1] == ',' &&
+                     static_cast<int>(strlen(pszMonthFound)) >
+                     1 + nLenMonth + 1 + 2 + 1 + 1 + 4 + 1 + 5 + 1 + 2 )
             {
-                /* Format of http://publicfiles.dep.state.fl.us/dear/BWR_GIS/2007NWFLULC/ */
-                /* "        Sunday, June 20, 2010  6:46 PM    233170905 NWF2007LULCForSDE.zip" */
+                // Format of http://publicfiles.dep.state.fl.us/dear/BWR_GIS/2007NWFLULC/
+                // "        Sunday, June 20, 2010  6:46 PM    233170905 NWF2007LULCForSDE.zip"
                 pszMonthFound += 1;
                 int nCurOffset = nLenMonth + 1;
                 int nDay = atoi(pszMonthFound + nCurOffset);
@@ -2305,22 +2506,24 @@ static bool VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
                 nCurOffset += 4 + 1;
                 int nHour = atoi(pszMonthFound + nCurOffset);
                 nCurOffset += 2 + 1;
-                int nMin = atoi(pszMonthFound + nCurOffset);
+                const int nMin = atoi(pszMonthFound + nCurOffset);
                 nCurOffset += 2 + 1;
-                if (STARTS_WITH(pszMonthFound + nCurOffset, "PM"))
+                if( STARTS_WITH(pszMonthFound + nCurOffset, "PM") )
                     nHour += 12;
-                else if (!STARTS_WITH(pszMonthFound + nCurOffset, "AM"))
+                else if( !STARTS_WITH(pszMonthFound + nCurOffset, "AM") )
                     nHour = -1;
                 nCurOffset += 2;
 
                 const char* pszFilesize = pszMonthFound + nCurOffset;
-                while(*pszFilesize == ' ')
-                    pszFilesize ++;
-                if (*pszFilesize >= '1' && *pszFilesize <= '9')
-                    nFileSize = CPLScanUIntBig(pszFilesize, static_cast<int>(strlen(pszFilesize)));
-
-                if (nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
-                    nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60)
+                while( *pszFilesize == ' ' )
+                    pszFilesize++;
+                if( *pszFilesize >= '1' && *pszFilesize <= '9' )
+                    nFileSize =
+                        CPLScanUIntBig(pszFilesize,
+                                       static_cast<int>(strlen(pszFilesize)));
+
+                if( nDay >= 1 && nDay <= 31 && nYear >= 1900 &&
+                    nHour >= 0 && nHour <= 24 && nMin >= 0 && nMin < 60 )
                 {
                     brokendowntime.tm_year = nYear - 1900;
                     brokendowntime.tm_mon = iMonth;
@@ -2346,21 +2549,21 @@ static bool VSICurlParseHTMLDateTimeFileSize(const char* pszStr,
 /*      Parse a file list document and return all the components.       */
 /************************************************************************/
 
-char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
-                                                   int nMaxFiles,
-                                                   char* pszData,
-                                                   bool* pbGotFileList)
+char** VSICurlFilesystemHandler::ParseHTMLFileList( const char* pszFilename,
+                                                    int nMaxFiles,
+                                                    char* pszData,
+                                                    bool* pbGotFileList )
 {
     *pbGotFileList = false;
 
     const char* pszDir;
-    if (STARTS_WITH_CI(pszFilename, "/vsicurl/http://"))
+    if( STARTS_WITH_CI(pszFilename, "/vsicurl/http://") )
         pszDir = strchr(pszFilename + strlen("/vsicurl/http://"), '/');
-    else if (STARTS_WITH_CI(pszFilename, "/vsicurl/https://"))
+    else if( STARTS_WITH_CI(pszFilename, "/vsicurl/https://") )
         pszDir = strchr(pszFilename + strlen("/vsicurl/https://"), '/');
     else
         pszDir = strchr(pszFilename + strlen("/vsicurl/ftp://"), '/');
-    if (pszDir == NULL)
+    if( pszDir == NULL )
         pszDir = "";
 
     /* Apache */
@@ -2380,12 +2583,15 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
     osExpectedString4 += pszDir;
     osExpectedString4 += "</TITLE>";
 
-    /* The listing of http://dds.cr.usgs.gov/srtm/SRTM_image_sample/picture%20examples/ */
-    /* has "<title>Index of /srtm/SRTM_image_sample/picture examples</title>" so we must */
-    /* try unescaped %20 also */
-    /* Similar with http://datalib.usask.ca/gis/Data/Central_America_goodbutdoweown%3f/ */
+    // The listing of
+    // http://dds.cr.usgs.gov/srtm/SRTM_image_sample/picture%20examples/
+    // has
+    // "<title>Index of /srtm/SRTM_image_sample/picture examples</title>"
+    // so we must try unescaped %20 also.
+    // Similar with
+    // http://datalib.usask.ca/gis/Data/Central_America_goodbutdoweown%3f/
     CPLString osExpectedString_unescaped;
-    if (strchr(pszDir, '%'))
+    if( strchr(pszDir, '%') )
     {
         char* pszUnescapedDir = CPLUnescapeString(pszDir, NULL, CPLES_URL);
         osExpectedString_unescaped = "<title>Index of ";
@@ -2394,7 +2600,7 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
         CPLFree(pszUnescapedDir);
     }
 
-    char* c;
+    char* c = NULL;
     int nCount = 0;
     int nCountTable = 0;
     CPLStringList oFileList;
@@ -2403,51 +2609,57 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
 
     while( (c = VSICurlParserFindEOL( pszLine )) != NULL )
     {
-        *c = 0;
+        *c = '\0';
 
-        /* To avoid false positive on pages such as http://www.ngs.noaa.gov/PC_PROD/USGG2009BETA */
-        /* This is a heuristics, but normal HTML listing of files have not more than one table */
-        if (strstr(pszLine, "<table"))
+        // To avoid false positive on pages such as
+        // http://www.ngs.noaa.gov/PC_PROD/USGG2009BETA
+        // This is a heuristics, but normal HTML listing of files have not more
+        // than one table.
+        if( strstr(pszLine, "<table") )
         {
-            nCountTable ++;
-            if (nCountTable == 2)
+            nCountTable++;
+            if( nCountTable == 2 )
             {
                 *pbGotFileList = false;
                 return NULL;
             }
         }
 
-        if (!bIsHTMLDirList &&
+        if( !bIsHTMLDirList &&
             (strstr(pszLine, osExpectedString.c_str()) ||
              strstr(pszLine, osExpectedString2.c_str()) ||
              strstr(pszLine, osExpectedString3.c_str()) ||
              strstr(pszLine, osExpectedString4.c_str()) ||
-             (osExpectedString_unescaped.size() != 0 && strstr(pszLine, osExpectedString_unescaped.c_str()))))
+             (!osExpectedString_unescaped.empty() &&
+              strstr(pszLine, osExpectedString_unescaped.c_str()))) )
         {
             bIsHTMLDirList = true;
             *pbGotFileList = true;
         }
-        /* Subversion HTTP listing */
-        /* or Microsoft-IIS/6.0 listing (e.g. http://ortho.linz.govt.nz/tifs/2005_06/) */
-        else if (!bIsHTMLDirList && strstr(pszLine, "<title>"))
+        // Subversion HTTP listing
+        // or Microsoft-IIS/6.0 listing
+        // (e.g. http://ortho.linz.govt.nz/tifs/2005_06/) */
+        else if( !bIsHTMLDirList && strstr(pszLine, "<title>") )
         {
-            /* Detect something like : <html><head><title>gdal - Revision 20739: /trunk/autotest/gcore/data</title></head> */
-            /* The annoying thing is that what is after ': ' is a subpart of what is after http://server/ */
+            // Detect something like:
+            // <html><head><title>gdal - Revision 20739: /trunk/autotest/gcore/data</title></head> */
+            // The annoying thing is that what is after ': ' is a subpart of
+            // what is after http://server/
             char* pszSubDir = strstr(pszLine, ": ");
-            if (pszSubDir == NULL)
-                /* or <title>ortho.linz.govt.nz - /tifs/2005_06/</title> */
+            if( pszSubDir == NULL )
+                // or <title>ortho.linz.govt.nz - /tifs/2005_06/</title>
                 pszSubDir = strstr(pszLine, "- ");
-            if (pszSubDir)
+            if( pszSubDir )
             {
                 pszSubDir += 2;
                 char* pszTmp = strstr(pszSubDir, "</title>");
-                if (pszTmp)
+                if( pszTmp )
                 {
-                    if (pszTmp[-1] == '/')
+                    if( pszTmp[-1] == '/' )
                         pszTmp[-1] = 0;
                     else
                         *pszTmp = 0;
-                    if (strstr(pszDir, pszSubDir))
+                    if( strstr(pszDir, pszSubDir) )
                     {
                         bIsHTMLDirList = true;
                         *pbGotFileList = true;
@@ -2455,17 +2667,22 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
                 }
             }
         }
-        else if (bIsHTMLDirList &&
-                 (strstr(pszLine, "<a href=\"") != NULL || strstr(pszLine, "<A HREF=\"") != NULL) &&
-                 strstr(pszLine, "<a href=\"http://") == NULL && /* exclude absolute links, like to subversion home */
-                 strstr(pszLine, "Parent Directory") == NULL /* exclude parent directory */)
+        else if( bIsHTMLDirList &&
+                 (strstr(pszLine, "<a href=\"") != NULL ||
+                  strstr(pszLine, "<A HREF=\"") != NULL) &&
+                 // Exclude absolute links, like to subversion home.
+                 strstr(pszLine, "<a href=\"http://") == NULL &&
+                 // exclude parent directory.
+                 strstr(pszLine, "Parent Directory") == NULL )
         {
             char *beginFilename = strstr(pszLine, "<a href=\"");
-            if (beginFilename == NULL)
+            if( beginFilename == NULL )
                 beginFilename = strstr(pszLine, "<A HREF=\"");
             beginFilename += strlen("<a href=\"");
             char *endQuote = strchr(beginFilename, '"');
-            if (endQuote && !STARTS_WITH(beginFilename, "?C=") && !STARTS_WITH(beginFilename, "?N="))
+            if( endQuote &&
+                !STARTS_WITH(beginFilename, "?C=") &&
+                !STARTS_WITH(beginFilename, "?N=") )
             {
                 struct tm brokendowntime;
                 memset(&brokendowntime, 0, sizeof(brokendowntime));
@@ -2479,25 +2696,28 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
 
                 *endQuote = '\0';
 
-                /* Remove trailing slash, that are returned for directories by */
-                /* Apache */
+                // Remove trailing slash, that are returned for directories by
+                // Apache.
                 bool bIsDirectory = false;
-                if (endQuote[-1] == '/')
+                if( endQuote[-1] == '/' )
                 {
                     bIsDirectory = true;
                     endQuote[-1] = 0;
                 }
 
-                /* shttpd links include slashes from the root directory. Skip them */
-                while(strchr(beginFilename, '/'))
+                // shttpd links include slashes from the root directory.
+                // Skip them.
+                while( strchr(beginFilename, '/') )
                     beginFilename = strchr(beginFilename, '/') + 1;
 
-                if (strcmp(beginFilename, ".") != 0 &&
-                    strcmp(beginFilename, "..") != 0)
+                if( strcmp(beginFilename, ".") != 0 &&
+                    strcmp(beginFilename, "..") != 0 )
                 {
                     CPLString osCachedFilename =
-                        CPLSPrintf("%s/%s", pszFilename + strlen("/vsicurl/"), beginFilename);
-                    CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
+                        CPLSPrintf("%s/%s", pszFilename + strlen("/vsicurl/"),
+                                   beginFilename);
+                    CachedFileProp* cachedFileProp =
+                        GetCachedFileProp(osCachedFilename);
                     cachedFileProp->eExists = EXIST_YES;
                     cachedFileProp->bIsDirectory = bIsDirectory;
                     cachedFileProp->mTime = static_cast<time_t>(mTime);
@@ -2505,12 +2725,19 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
                     cachedFileProp->fileSize = nFileSize;
 
                     oFileList.AddString( beginFilename );
-                    if (ENABLE_DEBUG)
-                        CPLDebug("VSICURL", "File[%d] = %s, is_dir = %d, size = " CPL_FRMT_GUIB ", time = %04d/%02d/%02d %02d:%02d:%02d",
-                                nCount, beginFilename, bIsDirectory ? 1 : 0, nFileSize,
-                                brokendowntime.tm_year + 1900, brokendowntime.tm_mon + 1, brokendowntime.tm_mday,
-                                brokendowntime.tm_hour, brokendowntime.tm_min, brokendowntime.tm_sec);
-                    nCount ++;
+                    if( ENABLE_DEBUG )
+                        CPLDebug("VSICURL",
+                                 "File[%d] = %s, is_dir = %d, size = "
+                                 CPL_FRMT_GUIB
+                                 ", time = %04d/%02d/%02d %02d:%02d:%02d",
+                                 nCount, beginFilename, bIsDirectory ? 1 : 0,
+                                 nFileSize,
+                                 brokendowntime.tm_year + 1900,
+                                 brokendowntime.tm_mon + 1,
+                                 brokendowntime.tm_mday,
+                                 brokendowntime.tm_hour, brokendowntime.tm_min,
+                                 brokendowntime.tm_sec);
+                    nCount++;
 
                     if( nMaxFiles > 0 && oFileList.Count() > nMaxFiles )
                         break;
@@ -2527,15 +2754,17 @@ char** VSICurlFilesystemHandler::ParseHTMLFileList(const char* pszFilename,
 /*                          AnalyseS3FileList()                         */
 /************************************************************************/
 
-#include "cpl_minixml.h"
-void VSICurlFilesystemHandler::AnalyseS3FileList( const CPLString& osBaseURL,
-                                        const char* pszXML,
-                                        CPLStringList& osFileList,
-                                        int nMaxFiles,
-                                        bool& bIsTruncated,
-                                        CPLString& osNextMarker )
+void VSICurlFilesystemHandler::AnalyseS3FileList(
+    const CPLString& osBaseURL,
+    const char* pszXML,
+    CPLStringList& osFileList,
+    int nMaxFiles,
+    bool& bIsTruncated,
+    CPLString& osNextMarker )
 {
-    //CPLDebug("S3", "%s", pszXML);
+#if DEBUG_VERBOSE
+    CPLDebug("S3", "%s", pszXML);
+#endif
     osNextMarker = "";
     bIsTruncated = false;
     CPLXMLNode* psTree = CPLParseXMLString(pszXML);
@@ -2556,19 +2785,29 @@ void VSICurlFilesystemHandler::AnalyseS3FileList( const CPLString& osBaseURL,
                 if( pszKey && strlen(pszKey) > osPrefix.size() )
                 {
                     CPLString osCachedFilename = osBaseURL + pszKey;
-                    //CPLDebug("S3", "Cache %s", osCachedFilename.c_str());
+#if DEBUG_VERBOSE
+                    CPLDebug("S3", "Cache %s", osCachedFilename.c_str());
+#endif
 
-                    CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
+                    CachedFileProp* cachedFileProp =
+                        GetCachedFileProp(osCachedFilename);
                     cachedFileProp->eExists = EXIST_YES;
                     cachedFileProp->bHasComputedFileSize = true;
-                    cachedFileProp->fileSize = (GUIntBig)CPLAtoGIntBig(CPLGetXMLValue(psIter, "Size", "0"));
+                    cachedFileProp->fileSize = static_cast<GUIntBig>(
+                        CPLAtoGIntBig(CPLGetXMLValue(psIter, "Size", "0")));
                     cachedFileProp->bIsDirectory = false;
                     cachedFileProp->mTime = 0;
 
-                    int nYear, nMonth, nDay, nHour, nMin, nSec;
+                    int nYear = 0;
+                    int nMonth = 0;
+                    int nDay = 0;
+                    int nHour = 0;
+                    int nMin = 0;
+                    int nSec = 0;
                     if( sscanf( CPLGetXMLValue(psIter, "LastModified", ""),
                                 "%04d-%02d-%02dT%02d:%02d:%02d",
-                                &nYear, &nMonth, &nDay, &nHour, &nMin, &nSec ) == 6 )
+                                &nYear, &nMonth, &nDay,
+                                &nHour, &nMin, &nSec ) == 6 )
                     {
                         struct tm brokendowntime;
                         brokendowntime.tm_year = nYear - 1900;
@@ -2577,7 +2816,9 @@ void VSICurlFilesystemHandler::AnalyseS3FileList( const CPLString& osBaseURL,
                         brokendowntime.tm_hour = nHour;
                         brokendowntime.tm_min = nMin;
                         brokendowntime.tm_sec = nSec;
-                        cachedFileProp->mTime = static_cast<time_t>(CPLYMDHMSToUnixTime(&brokendowntime));
+                        cachedFileProp->mTime =
+                            static_cast<time_t>(
+                                CPLYMDHMSToUnixTime(&brokendowntime));
                     }
 
                     osFileList.AddString(pszKey + osPrefix.size());
@@ -2586,17 +2827,20 @@ void VSICurlFilesystemHandler::AnalyseS3FileList( const CPLString& osBaseURL,
             else if( strcmp(psIter->pszValue, "CommonPrefixes") == 0 )
             {
                 const char* pszKey = CPLGetXMLValue(psIter, "Prefix", NULL);
-                if( pszKey && strncmp(pszKey, osPrefix, osPrefix.size()) == 0  )
+                if( pszKey && strncmp(pszKey, osPrefix, osPrefix.size()) == 0 )
                 {
                     CPLString osKey = pszKey;
-                    if( osKey.size() && osKey[osKey.size()-1] == '/' )
+                    if( !osKey.empty() && osKey.back() == '/' )
                         osKey.resize(osKey.size()-1);
                     if( osKey.size() > osPrefix.size() )
                     {
                         CPLString osCachedFilename = osBaseURL + osKey;
-                        //CPLDebug("S3", "Cache %s", osCachedFilename.c_str());
+#if DEBUG_VERBOSE
+                        CPLDebug("S3", "Cache %s", osCachedFilename.c_str());
+#endif
 
-                        CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
+                        CachedFileProp* cachedFileProp =
+                            GetCachedFileProp(osCachedFilename);
                         cachedFileProp->eExists = EXIST_YES;
                         cachedFileProp->bIsDirectory = true;
                         cachedFileProp->mTime = 0;
@@ -2613,7 +2857,9 @@ void VSICurlFilesystemHandler::AnalyseS3FileList( const CPLString& osBaseURL,
         if( !(nMaxFiles > 0 && osFileList.Count() > nMaxFiles) )
         {
             osNextMarker = CPLGetXMLValue(psListBucketResult, "NextMarker", "");
-            bIsTruncated = CPL_TO_BOOL(CSLTestBoolean(CPLGetXMLValue(psListBucketResult, "IsTruncated", "false")));
+            bIsTruncated =
+                CPLTestBool(CPLGetXMLValue(psListBucketResult,
+                                           "IsTruncated", "false"));
         }
     }
     CPLDestroyXMLNode(psTree);
@@ -2623,27 +2869,29 @@ void VSICurlFilesystemHandler::AnalyseS3FileList( const CPLString& osBaseURL,
 /*                         VSICurlGetToken()                            */
 /************************************************************************/
 
-static char* VSICurlGetToken(char* pszCurPtr, char** ppszNextToken)
+static char* VSICurlGetToken( char* pszCurPtr, char** ppszNextToken )
 {
-    if (pszCurPtr == NULL)
+    if( pszCurPtr == NULL )
         return NULL;
 
-    while((*pszCurPtr) == ' ')
-        pszCurPtr ++;
-    if (*pszCurPtr == '\0')
+    while( (*pszCurPtr) == ' ' )
+        pszCurPtr++;
+    if( *pszCurPtr == '\0' )
         return NULL;
 
     char* pszToken = pszCurPtr;
-    while((*pszCurPtr) != ' ' && (*pszCurPtr) != '\0')
-        pszCurPtr ++;
-    if (*pszCurPtr == '\0')
+    while( (*pszCurPtr) != ' ' && (*pszCurPtr) != '\0' )
+        pszCurPtr++;
+    if( *pszCurPtr == '\0' )
+    {
         *ppszNextToken = NULL;
+    }
     else
     {
         *pszCurPtr = '\0';
-        pszCurPtr ++;
-        while((*pszCurPtr) == ' ')
-            pszCurPtr ++;
+        pszCurPtr++;
+        while( (*pszCurPtr) == ' ' )
+            pszCurPtr++;
         *ppszNextToken = pszCurPtr;
     }
 
@@ -2661,32 +2909,32 @@ lrwxrwxrwx    1 ftp      ftp            28 Jun 14 14:13 MPlayer -> mirrors/mplay
 drwxr-xr-x  280 1003  1003  6656 Aug 26 04:17 gnu
 */
 
-static bool VSICurlParseFullFTPLine(char* pszLine,
-                                   char*& pszFilename,
-                                   bool& bSizeValid,
-                                   GUIntBig& nSize,
-                                   bool& bIsDirectory,
-                                   GIntBig& nUnixTime)
+static bool VSICurlParseFullFTPLine( char* pszLine,
+                                     char*& pszFilename,
+                                     bool& bSizeValid,
+                                     GUIntBig& nSize,
+                                     bool& bIsDirectory,
+                                     GIntBig& nUnixTime )
 {
     char* pszNextToken = pszLine;
     char* pszPermissions = VSICurlGetToken(pszNextToken, &pszNextToken);
-    if (pszPermissions == NULL || strlen(pszPermissions) != 10)
+    if( pszPermissions == NULL || strlen(pszPermissions) != 10 )
         return false;
-    bIsDirectory = (pszPermissions[0] == 'd');
+    bIsDirectory = pszPermissions[0] == 'd';
 
-    for(int i = 0; i < 3; i++)
+    for( int i = 0; i < 3; i++ )
     {
-        if (VSICurlGetToken(pszNextToken, &pszNextToken) == NULL)
+        if( VSICurlGetToken(pszNextToken, &pszNextToken) == NULL )
             return false;
     }
 
     char* pszSize = VSICurlGetToken(pszNextToken, &pszNextToken);
-    if (pszSize == NULL)
+    if( pszSize == NULL )
         return false;
 
-    if (pszPermissions[0] == '-')
+    if( pszPermissions[0] == '-' )
     {
-        /* Regular file */
+        // Regular file.
         bSizeValid = true;
         nSize = CPLScanUIntBig(pszSize, static_cast<int>(strlen(pszSize)));
     }
@@ -2696,33 +2944,34 @@ static bool VSICurlParseFullFTPLine(char* pszLine,
     bool bBrokenDownTimeValid = true;
 
     char* pszMonth = VSICurlGetToken(pszNextToken, &pszNextToken);
-    if (pszMonth == NULL || strlen(pszMonth) != 3)
+    if( pszMonth == NULL || strlen(pszMonth) != 3 )
         return false;
 
     int i = 0;  // Used after for.
     for( ; i < 12; i++ )
     {
-        if (EQUALN(pszMonth, apszMonths[i], 3))
+        if( EQUALN(pszMonth, apszMonths[i], 3) )
             break;
     }
-    if (i < 12)
+    if( i < 12 )
         brokendowntime.tm_mon = i;
     else
         bBrokenDownTimeValid = false;
 
     char* pszDay = VSICurlGetToken(pszNextToken, &pszNextToken);
-    if (pszDay == NULL || (strlen(pszDay) != 1 && strlen(pszDay) != 2))
+    if( pszDay == NULL || (strlen(pszDay) != 1 && strlen(pszDay) != 2) )
         return false;
     int nDay = atoi(pszDay);
-    if (nDay >= 1 && nDay <= 31)
+    if( nDay >= 1 && nDay <= 31 )
         brokendowntime.tm_mday = nDay;
     else
         bBrokenDownTimeValid = false;
 
     char* pszHourOrYear = VSICurlGetToken(pszNextToken, &pszNextToken);
-    if (pszHourOrYear == NULL || (strlen(pszHourOrYear) != 4 && strlen(pszHourOrYear) != 5))
+    if( pszHourOrYear == NULL ||
+        (strlen(pszHourOrYear) != 4 && strlen(pszHourOrYear) != 5) )
         return false;
-    if (strlen(pszHourOrYear) == 4)
+    if( strlen(pszHourOrYear) == 4 )
     {
         brokendowntime.tm_year = atoi(pszHourOrYear) - 1900;
     }
@@ -2731,18 +2980,19 @@ static bool VSICurlParseFullFTPLine(char* pszLine,
         time_t sTime;
         time(&sTime);
         struct tm currentBrokendowntime;
-        CPLUnixTimeToYMDHMS((GIntBig)sTime, &currentBrokendowntime);
+        CPLUnixTimeToYMDHMS(static_cast<GIntBig>(sTime),
+                            &currentBrokendowntime);
         brokendowntime.tm_year = currentBrokendowntime.tm_year;
         brokendowntime.tm_hour = atoi(pszHourOrYear);
         brokendowntime.tm_min = atoi(pszHourOrYear + 3);
     }
 
-    if (bBrokenDownTimeValid)
+    if( bBrokenDownTimeValid )
         nUnixTime = CPLYMDHMSToUnixTime(&brokendowntime);
     else
         nUnixTime = 0;
 
-    if (pszNextToken == NULL)
+    if( pszNextToken == NULL )
         return false;
 
     pszFilename = pszNextToken;
@@ -2750,12 +3000,12 @@ static bool VSICurlParseFullFTPLine(char* pszLine,
     char* pszCurPtr = pszFilename;
     while( *pszCurPtr != '\0')
     {
-        /* In case of a link, stop before the pointed part of the link */
-        if (pszPermissions[0] == 'l' && STARTS_WITH(pszCurPtr, " -> "))
+        // In case of a link, stop before the pointed part of the link.
+        if( pszPermissions[0] == 'l' && STARTS_WITH(pszCurPtr, " -> ") )
         {
             break;
         }
-        pszCurPtr ++;
+        pszCurPtr++;
     }
     *pszCurPtr = '\0';
 
@@ -2766,7 +3016,8 @@ static bool VSICurlParseFullFTPLine(char* pszLine,
 /*                          GetURLFromDirname()                         */
 /************************************************************************/
 
-CPLString VSICurlFilesystemHandler::GetURLFromDirname( const CPLString& osDirname )
+CPLString
+VSICurlFilesystemHandler::GetURLFromDirname( const CPLString& osDirname )
 {
     return osDirname.substr(GetFSPrefix().size());
 }
@@ -2779,16 +3030,16 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
                                              int nMaxFiles,
                                              bool* pbGotFileList)
 {
-    if (ENABLE_DEBUG)
+    if( ENABLE_DEBUG )
         CPLDebug("VSICURL", "GetFileList(%s)" , pszDirname);
 
     *pbGotFileList = false;
 
-    /* HACK (optimization in fact) for MBTiles driver */
-    if (strstr(pszDirname, ".tiles.mapbox.com") != NULL)
+    // HACK (optimization in fact) for MBTiles driver.
+    if( strstr(pszDirname, ".tiles.mapbox.com") != NULL )
         return NULL;
 
-    if (STARTS_WITH(pszDirname, "/vsicurl/ftp"))
+    if( STARTS_WITH(pszDirname, "/vsicurl/ftp") )
     {
         WriteFuncStruct sWriteFuncData;
         sWriteFuncData.pBuffer = NULL;
@@ -2798,43 +3049,50 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
 
         char** papszFileList = NULL;
 
-        for(int iTry=0;iTry<2;iTry++)
+        for( int iTry = 0; iTry < 2; iTry++ )
         {
             CURL* hCurlHandle = GetCurlHandleFor(osDirname);
-            VSICurlSetOptions(hCurlHandle, osDirname.c_str());
+            struct curl_slist* headers =
+                VSICurlSetOptions(hCurlHandle, osDirname.c_str(), NULL);
 
-            /* On the first pass, we want to try fetching all the possible */
-            /* information (filename, file/directory, size). If that */
-            /* does not work, then try again with CURLOPT_DIRLISTONLY set */
-            if (iTry == 1)
+            // On the first pass, we want to try fetching all the possible
+            // information (filename, file/directory, size). If that does not
+            // work, then try again with CURLOPT_DIRLISTONLY set.
+            if( iTry == 1 )
             {
-        /* 7.16.4 */
-        #if LIBCURL_VERSION_NUM <= 0x071004
+// 7.16.4
+#if LIBCURL_VERSION_NUM <= 0x071004
                 curl_easy_setopt(hCurlHandle, CURLOPT_FTPLISTONLY, 1);
-        #elif LIBCURL_VERSION_NUM > 0x071004
+#elif LIBCURL_VERSION_NUM > 0x071004
                 curl_easy_setopt(hCurlHandle, CURLOPT_DIRLISTONLY, 1);
-        #endif
+#endif
             }
 
             VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
             curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-            curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+            curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                             VSICurlHandleWriteFunc);
 
-            char szCurlErrBuf[CURL_ERROR_SIZE+1];
-            szCurlErrBuf[0] = '\0';
+            char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
             curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
+            if( headers != NULL )
+                curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
             curl_easy_perform(hCurlHandle);
 
-            if (sWriteFuncData.pBuffer == NULL)
+            if( headers != NULL )
+                curl_slist_free_all(headers);
+
+            if( sWriteFuncData.pBuffer == NULL )
                 return NULL;
 
             char* pszLine = sWriteFuncData.pBuffer;
-            char* c;
+            char* c = NULL;
             int nCount = 0;
 
-            if (STARTS_WITH_CI(pszLine, "<!DOCTYPE HTML") ||
-                STARTS_WITH_CI(pszLine, "<HTML>"))
+            if( STARTS_WITH_CI(pszLine, "<!DOCTYPE HTML") ||
+                STARTS_WITH_CI(pszLine, "<HTML>") )
             {
                 papszFileList = ParseHTMLFileList(pszDirname,
                                                   nMaxFiles,
@@ -2842,7 +3100,7 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
                                                   pbGotFileList);
                 break;
             }
-            else if (iTry == 0)
+            else if( iTry == 0 )
             {
                 CPLStringList oFileList;
                 *pbGotFileList = true;
@@ -2850,7 +3108,7 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
                 while( (c = strchr(pszLine, '\n')) != NULL)
                 {
                     *c = 0;
-                    if (c - pszLine > 0 && c[-1] == '\r')
+                    if( c - pszLine > 0 && c[-1] == '\r' )
                         c[-1] = 0;
 
                     char* pszFilename = NULL;
@@ -2858,17 +3116,20 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
                     GUIntBig nFileSize = 0;
                     bool bIsDirectory = false;
                     GIntBig mUnixTime = 0;
-                    if (!VSICurlParseFullFTPLine(pszLine, pszFilename,
+                    if( !VSICurlParseFullFTPLine(pszLine, pszFilename,
                                                  bSizeValid, nFileSize,
-                                                 bIsDirectory, mUnixTime))
+                                                 bIsDirectory, mUnixTime) )
                         break;
 
-                    if (strcmp(pszFilename, ".") != 0 &&
-                        strcmp(pszFilename, "..") != 0)
+                    if( strcmp(pszFilename, ".") != 0 &&
+                        strcmp(pszFilename, "..") != 0 )
                     {
                         CPLString osCachedFilename =
-                            CPLSPrintf("%s/%s", pszDirname + strlen("/vsicurl/"), pszFilename);
-                        CachedFileProp* cachedFileProp = GetCachedFileProp(osCachedFilename);
+                            CPLSPrintf("%s/%s",
+                                       pszDirname + strlen("/vsicurl/"),
+                                       pszFilename);
+                        CachedFileProp* cachedFileProp =
+                            GetCachedFileProp(osCachedFilename);
                         cachedFileProp->eExists = EXIST_YES;
                         cachedFileProp->bHasComputedFileSize = bSizeValid;
                         cachedFileProp->fileSize = nFileSize;
@@ -2876,17 +3137,25 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
                         cachedFileProp->mTime = static_cast<time_t>(mUnixTime);
 
                         oFileList.AddString(pszFilename);
-                        if (ENABLE_DEBUG)
+                        if( ENABLE_DEBUG )
                         {
                             struct tm brokendowntime;
                             CPLUnixTimeToYMDHMS(mUnixTime, &brokendowntime);
-                            CPLDebug("VSICURL", "File[%d] = %s, is_dir = %d, size = " CPL_FRMT_GUIB ", time = %04d/%02d/%02d %02d:%02d:%02d",
-                                    nCount, pszFilename, bIsDirectory ? 1 : 0, nFileSize,
-                                    brokendowntime.tm_year + 1900, brokendowntime.tm_mon + 1, brokendowntime.tm_mday,
-                                    brokendowntime.tm_hour, brokendowntime.tm_min, brokendowntime.tm_sec);
+                            CPLDebug("VSICURL",
+                                     "File[%d] = %s, is_dir = %d, size = "
+                                     CPL_FRMT_GUIB
+                                     ", time = %04d/%02d/%02d %02d:%02d:%02d",
+                                     nCount, pszFilename, bIsDirectory ? 1 : 0,
+                                     nFileSize,
+                                     brokendowntime.tm_year + 1900,
+                                     brokendowntime.tm_mon + 1,
+                                     brokendowntime.tm_mday,
+                                     brokendowntime.tm_hour,
+                                     brokendowntime.tm_min,
+                                     brokendowntime.tm_sec);
                         }
 
-                        nCount ++;
+                        nCount++;
 
                         if( nMaxFiles > 0 && oFileList.Count() > nMaxFiles )
                             break;
@@ -2895,7 +3164,7 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
                     pszLine = c + 1;
                 }
 
-                if (c == NULL)
+                if( c == NULL )
                 {
                     papszFileList = oFileList.StealList();
                     break;
@@ -2909,16 +3178,17 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
                 while( (c = strchr(pszLine, '\n')) != NULL)
                 {
                     *c = 0;
-                    if (c - pszLine > 0 && c[-1] == '\r')
+                    if( c - pszLine > 0 && c[-1] == '\r' )
                         c[-1] = 0;
 
-                    if (strcmp(pszLine, ".") != 0 &&
-                        strcmp(pszLine, "..") != 0)
+                    if( strcmp(pszLine, ".") != 0 &&
+                        strcmp(pszLine, "..") != 0 )
                     {
                         oFileList.AddString(pszLine);
-                        if (ENABLE_DEBUG)
-                            CPLDebug("VSICURL", "File[%d] = %s", nCount, pszLine);
-                        nCount ++;
+                        if( ENABLE_DEBUG )
+                            CPLDebug("VSICURL",
+                                     "File[%d] = %s", nCount, pszLine);
+                        nCount++;
                     }
 
                     pszLine = c + 1;
@@ -2936,43 +3206,49 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
         return papszFileList;
     }
 
-    /* Try to recognize HTML pages that list the content of a directory */
-    /* Currently this supports what Apache and shttpd can return */
-    else if (STARTS_WITH(pszDirname, "/vsicurl/http://") ||
-             STARTS_WITH(pszDirname, "/vsicurl/https://"))
+    // Try to recognize HTML pages that list the content of a directory.
+    // Currently this supports what Apache and shttpd can return.
+    else if( STARTS_WITH(pszDirname, "/vsicurl/http://") ||
+             STARTS_WITH(pszDirname, "/vsicurl/https://") )
     {
-        WriteFuncStruct sWriteFuncData;
-
         CPLString osDirname(pszDirname + strlen("/vsicurl/"));
         osDirname += '/';
 
-    #if LIBCURL_VERSION_NUM < 0x070B00
-        /* Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have been */
-        /* previously set, so we have to reinit the connection handle */
+#if LIBCURL_VERSION_NUM < 0x070B00
+        // Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have
+        // been previously set, so we have to reinit the connection handle.
         GetCurlHandleFor("");
-    #endif
+#endif
 
         CURL* hCurlHandle = GetCurlHandleFor(osDirname);
-        VSICurlSetOptions(hCurlHandle, osDirname.c_str());
+        struct curl_slist* headers =
+            VSICurlSetOptions(hCurlHandle, osDirname.c_str(), NULL);
 
         curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, NULL);
 
+        WriteFuncStruct sWriteFuncData;
         VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
         curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                         VSICurlHandleWriteFunc);
 
-        char szCurlErrBuf[CURL_ERROR_SIZE+1];
-        szCurlErrBuf[0] = '\0';
+        char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
         curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
+        if( headers != NULL )
+            curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
         curl_easy_perform(hCurlHandle);
 
-        if (sWriteFuncData.pBuffer == NULL)
+        if( headers != NULL )
+            curl_slist_free_all(headers);
+
+        if( sWriteFuncData.pBuffer == NULL )
             return NULL;
 
         char** papszFileList = NULL;
-        if( STARTS_WITH_CI((const char*)sWriteFuncData.pBuffer, "<?xml") &&
-            strstr((const char*)sWriteFuncData.pBuffer, "<ListBucketResult") != NULL )
+        if( STARTS_WITH_CI(sWriteFuncData.pBuffer, "<?xml") &&
+            strstr(sWriteFuncData.pBuffer, "<ListBucketResult") != NULL )
         {
             CPLString osNextMarker;
             CPLStringList osFileList;
@@ -2980,12 +3256,12 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
             osBaseURL += "/";
             bool bIsTruncated = true;
             AnalyseS3FileList( osBaseURL,
-                               (const char*)sWriteFuncData.pBuffer,
+                               sWriteFuncData.pBuffer,
                                osFileList,
                                nMaxFiles,
                                bIsTruncated,
                                osNextMarker );
-            // If the list is truncated, then don't report it
+            // If the list is truncated, then don't report it.
             if( !bIsTruncated )
             {
                 papszFileList = osFileList.StealList();
@@ -3011,7 +3287,8 @@ char** VSICurlFilesystemHandler::GetFileList(const char *pszDirname,
 /*                                Stat()                                */
 /************************************************************************/
 
-int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+int VSICurlFilesystemHandler::Stat( const char *pszFilename,
+                                    VSIStatBufL *pStatBuf,
                                     int nFlags )
 {
     const CPLString osFilename(pszFilename);
@@ -3023,15 +3300,15 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatB
 
     const char* pszOptionVal =
         CPLGetConfigOption( "GDAL_DISABLE_READDIR_ON_OPEN", "NO" );
-    const bool bSkipReadDir = EQUAL(pszOptionVal, "EMPTY_DIR") ||
-                              CSLTestBoolean(pszOptionVal);
+    const bool bSkipReadDir =
+        EQUAL(pszOptionVal, "EMPTY_DIR") || CPLTestBool(pszOptionVal);
 
-    /* Does it look like a FTP directory ? */
-    if (STARTS_WITH(osFilename, "/vsicurl/ftp") &&
-        pszFilename[strlen(osFilename) - 1] == '/' && !bSkipReadDir)
+    // Does it look like a FTP directory?
+    if( STARTS_WITH(osFilename, "/vsicurl/ftp") &&
+        osFilename.back() == '/' && !bSkipReadDir )
     {
         char** papszFileList = ReadDirEx(osFilename, 0);
-        if (papszFileList)
+        if( papszFileList )
         {
             pStatBuf->st_mode = S_IFDIR;
             pStatBuf->st_size = 0;
@@ -3042,32 +3319,40 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatB
         }
         return -1;
     }
-    else if (strchr(CPLGetFilename(osFilename), '.') != NULL &&
+    else if( strchr(CPLGetFilename(osFilename), '.') != NULL &&
              !STARTS_WITH_CI(CPLGetExtension(osFilename), "zip") &&
              strstr(osFilename, ".zip.") != NULL &&
              strstr(osFilename, ".ZIP.") != NULL &&
-             !bSkipReadDir)
+             !bSkipReadDir )
     {
-        bool bGotFileList;
-        char** papszFileList = ReadDirInternal(CPLGetDirname(osFilename), 0, &bGotFileList);
-        const bool bFound = (VSICurlIsFileInList(papszFileList, CPLGetFilename(osFilename)) != -1);
+        bool bGotFileList = false;
+        char** papszFileList =
+            ReadDirInternal(CPLGetDirname(osFilename), 0, &bGotFileList);
+        const bool bFound =
+            VSICurlIsFileInList(papszFileList,
+                                CPLGetFilename(osFilename)) != -1;
         CSLDestroy(papszFileList);
-        if (bGotFileList && !bFound)
+        if( bGotFileList && !bFound )
         {
             return -1;
         }
     }
 
-    VSICurlHandle* poHandle = CreateFileHandle( osFilename + strlen(GetFSPrefix()) );
+    VSICurlHandle* poHandle =
+        CreateFileHandle( osFilename + strlen(GetFSPrefix()) );
     if( poHandle == NULL )
         return -1;
 
-    if ( poHandle->IsKnownFileSize() ||
-         ((nFlags & VSI_STAT_SIZE_FLAG) && !poHandle->IsDirectory() &&
-           CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_SLOW_GET_SIZE", "YES"))) )
+    if( poHandle->IsKnownFileSize() ||
+        ((nFlags & VSI_STAT_SIZE_FLAG) && !poHandle->IsDirectory() &&
+         CPLTestBool(CPLGetConfigOption("CPL_VSIL_CURL_SLOW_GET_SIZE",
+                                        "YES"))) )
+    {
         pStatBuf->st_size = poHandle->GetFileSize();
+    }
 
-    int nRet = poHandle->Exists((nFlags & VSI_STAT_SET_ERROR_FLAG) > 0) ? 0 : -1;
+    const int nRet =
+        poHandle->Exists((nFlags & VSI_STAT_SET_ERROR_FLAG) > 0) ? 0 : -1;
     pStatBuf->st_mtime = poHandle->GetMTime();
     pStatBuf->st_mode = poHandle->IsDirectory() ? S_IFDIR : S_IFREG;
     delete poHandle;
@@ -3078,7 +3363,7 @@ int VSICurlFilesystemHandler::Stat( const char *pszFilename, VSIStatBufL *pStatB
 /*                               Unlink()                               */
 /************************************************************************/
 
-int VSICurlFilesystemHandler::Unlink( CPL_UNUSED const char *pszFilename )
+int VSICurlFilesystemHandler::Unlink( const char * /* pszFilename */ )
 {
     return -1;
 }
@@ -3087,8 +3372,8 @@ int VSICurlFilesystemHandler::Unlink( CPL_UNUSED const char *pszFilename )
 /*                               Rename()                               */
 /************************************************************************/
 
-int VSICurlFilesystemHandler::Rename( CPL_UNUSED const char *oldpath,
-                                      CPL_UNUSED const char *newpath )
+int VSICurlFilesystemHandler::Rename( const char * /* oldpath */,
+                                      const char * /* newpath */ )
 {
     return -1;
 }
@@ -3097,8 +3382,8 @@ int VSICurlFilesystemHandler::Rename( CPL_UNUSED const char *oldpath,
 /*                               Mkdir()                                */
 /************************************************************************/
 
-int VSICurlFilesystemHandler::Mkdir( CPL_UNUSED const char *pszDirname,
-                                     CPL_UNUSED long nMode )
+int VSICurlFilesystemHandler::Mkdir( const char * /* pszDirname */,
+                                     long /* nMode */ )
 {
     return -1;
 }
@@ -3106,7 +3391,7 @@ int VSICurlFilesystemHandler::Mkdir( CPL_UNUSED const char *pszDirname,
 /*                               Rmdir()                                */
 /************************************************************************/
 
-int VSICurlFilesystemHandler::Rmdir( CPL_UNUSED const char *pszDirname )
+int VSICurlFilesystemHandler::Rmdir( const char * /* pszDirname */ )
 {
     return -1;
 }
@@ -3116,20 +3401,20 @@ int VSICurlFilesystemHandler::Rmdir( CPL_UNUSED const char *pszDirname )
 /************************************************************************/
 
 char** VSICurlFilesystemHandler::ReadDirInternal( const char *pszDirname,
-                                          int nMaxFiles,
-                                          bool* pbGotFileList )
+                                                  int nMaxFiles,
+                                                  bool* pbGotFileList )
 {
     CPLString osDirname(pszDirname);
-    while (osDirname[strlen(osDirname) - 1] == '/')
-        osDirname.erase(strlen(osDirname) - 1);
+    while( osDirname.back() == '/' )
+        osDirname.erase(osDirname.size() - 1);
 
     const char* pszUpDir = strstr(osDirname, "/..");
-    if (pszUpDir != NULL)
+    if( pszUpDir != NULL )
     {
         int pos = static_cast<int>(pszUpDir - osDirname.c_str() - 1);
-        while(pos >= 0 && osDirname[pos] != '/')
-            pos --;
-        if (pos >= 1)
+        while( pos >= 0 && osDirname[pos] != '/' )
+            pos--;
+        if( pos >= 1 )
         {
             osDirname = osDirname.substr(0, pos) + CPLString(pszUpDir + 3);
         }
@@ -3137,32 +3422,36 @@ char** VSICurlFilesystemHandler::ReadDirInternal( const char *pszDirname,
 
     if( osDirname.size() <= GetFSPrefix().size() )
     {
-        if (pbGotFileList)
+        if( pbGotFileList )
             *pbGotFileList = true;
         return NULL;
     }
 
     CPLMutexHolder oHolder( &hMutex );
 
-    /* If we know the file exists and is not a directory, then don't try to list its content */
-    CachedFileProp* cachedFileProp = GetCachedFileProp(GetURLFromDirname(osDirname));
-    if (cachedFileProp->eExists == EXIST_YES && !cachedFileProp->bIsDirectory)
+    // If we know the file exists and is not a directory,
+    // then don't try to list its content.
+    CachedFileProp* cachedFileProp =
+        GetCachedFileProp(GetURLFromDirname(osDirname));
+    if( cachedFileProp->eExists == EXIST_YES && !cachedFileProp->bIsDirectory )
     {
-        if (pbGotFileList)
+        if( pbGotFileList )
             *pbGotFileList = true;
         return NULL;
     }
 
     CachedDirList* psCachedDirList = cacheDirList[osDirname];
-    if (psCachedDirList == NULL)
+    if( psCachedDirList == NULL )
     {
-        psCachedDirList = (CachedDirList*) CPLMalloc(sizeof(CachedDirList));
-        psCachedDirList->papszFileList = GetFileList(osDirname, nMaxFiles,
-                                                     &psCachedDirList->bGotFileList);
+        psCachedDirList =
+            static_cast<CachedDirList *>(CPLMalloc(sizeof(CachedDirList)));
+        psCachedDirList->papszFileList =
+            GetFileList(osDirname, nMaxFiles,
+                        &psCachedDirList->bGotFileList);
         cacheDirList[osDirname] = psCachedDirList;
     }
 
-    if (pbGotFileList)
+    if( pbGotFileList )
         *pbGotFileList = psCachedDirList->bGotFileList;
 
     return CSLDuplicate(psCachedDirList->papszFileList);
@@ -3196,78 +3485,6 @@ char** VSICurlFilesystemHandler::ReadDirEx( const char *pszDirname,
 }
 
 /************************************************************************/
-/*                   VSIInstallCurlFileHandler()                        */
-/************************************************************************/
-
-/**
- * \brief Install /vsicurl/ HTTP/FTP file system handler (requires libcurl)
- *
- * A special file handler is installed that allows on-the-fly random reading of files
- * available through HTTP/FTP web protocols, without prior download of the entire file.
- *
- * Recognized filenames are of the form /vsicurl/http://path/to/remote/resource or
- * /vsicurl/ftp://path/to/remote/resource where path/to/remote/resource is the
- * URL of a remote resource.
- *
- * Partial downloads (requires the HTTP server to support random reading) are done
- * with a 16 KB granularity by default. If the driver detects sequential reading
- * it will progressively increase the chunk size up to 2 MB to improve download
- * performance.
- *
- * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration options can be
- * used to define a proxy server. The syntax to use is the one of Curl CURLOPT_PROXY,
- * CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
- *
- * Starting with GDAL 1.10, the file can be cached in RAM by setting the configuration option
- * VSI_CACHE to TRUE. The cache size defaults to 25 MB, but can be modified by setting
- * the configuration option VSI_CACHE_SIZE (in bytes).
- *
- * Starting with GDAL 2.1, /vsicurl/ will try to query directly redirected URLs to Amazon S3
- * signed URLs during their validity period, so as to minimize round-trips. This behaviour
- * can be disabled by setting the configuration option CPL_VSIL_CURL_USE_S3_REDIRECT to NO.
- *
- * VSIStatL() will return the size in st_size member and file
- * nature- file or directory - in st_mode member (the later only reliable with FTP
- * resources for now).
- *
- * VSIReadDir() should be able to parse the HTML directory listing returned by the
- * most popular web servers, such as Apache or Microsoft IIS.
- *
- * This special file handler can be combined with other virtual filesystems handlers,
- * such as /vsizip. For example, /vsizip//vsicurl/path/to/remote/file.zip/path/inside/zip
- *
- * @since GDAL 1.8.0
- */
-void VSIInstallCurlFileHandler(void)
-{
-    VSIFileManager::InstallHandler( "/vsicurl/", new VSICurlFilesystemHandler );
-}
-
-/************************************************************************/
-/*                      VSICurlInstallReadCbk()                         */
-/************************************************************************/
-
-int VSICurlInstallReadCbk (VSILFILE* fp,
-                           VSICurlReadCbkFunc pfnReadCbk,
-                           void* pfnUserData,
-                           int bStopOnInterrruptUntilUninstall)
-{
-    return ((VSICurlHandle*)fp)->InstallReadCbk(pfnReadCbk, pfnUserData,
-                                                bStopOnInterrruptUntilUninstall);
-}
-
-
-/************************************************************************/
-/*                    VSICurlUninstallReadCbk()                         */
-/************************************************************************/
-
-int VSICurlUninstallReadCbk(VSILFILE* fp)
-{
-    return ((VSICurlHandle*)fp)->UninstallReadCbk();
-}
-
-
-/************************************************************************/
 /*                         VSIS3FSHandler                               */
 /************************************************************************/
 
@@ -3276,24 +3493,26 @@ class VSIS3FSHandler CPL_FINAL : public VSICurlFilesystemHandler
     std::map< CPLString, VSIS3UpdateParams > oMapBucketsToS3Params;
 
 protected:
-    virtual CPLString GetFSPrefix() { return "/vsis3/"; }
-    virtual VSICurlHandle* CreateFileHandle(const char* pszURL);
-    virtual char** GetFileList(const char *pszFilename,
-                               int nMaxFiles,
-                               bool* pbGotFileList);
-    virtual CPLString GetURLFromDirname( const CPLString& osDirname );
+    virtual VSICurlHandle* CreateFileHandle( const char* pszUnprefixed ) override;
+    virtual char** GetFileList( const char *pszFilename,
+                                int nMaxFiles,
+                                bool* pbGotFileList ) override;
+    virtual CPLString GetURLFromDirname( const CPLString& osDirname ) override;
 
 public:
         VSIS3FSHandler() {}
 
         virtual VSIVirtualHandle *Open( const char *pszFilename,
                                         const char *pszAccess,
-                                        bool bSetError );
-        virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
-        virtual int      Unlink( const char *pszFilename );
+                                        bool bSetError ) override;
+        virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                               int nFlags ) override;
+        virtual int      Unlink( const char *pszFilename ) override;
 
-        void UpdateMapFromHandle(VSIS3HandleHelper * poS3HandleHelper);
-        void UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper);
+        virtual CPLString GetFSPrefix() override { return "/vsis3/"; }
+
+        void UpdateMapFromHandle( VSIS3HandleHelper * poS3HandleHelper );
+        void UpdateHandleFromMap( VSIS3HandleHelper * poS3HandleHelper );
 };
 
 /************************************************************************/
@@ -3305,15 +3524,17 @@ class VSIS3Handle CPL_FINAL : public VSICurlHandle
     VSIS3HandleHelper* m_poS3HandleHelper;
 
   protected:
-        virtual struct curl_slist* GetCurlHeaders(const CPLString& osVerb);
-        virtual bool CanRestartOnError(const char*, bool);
-        virtual bool UseLimitRangeGetInsteadOfHead() { return true; }
-        virtual void ProcessGetFileSizeResult(const char* pszContent);
+        virtual struct curl_slist* GetCurlHeaders( const CPLString& osVerb )
+            override;
+        virtual bool CanRestartOnError( const char*, bool ) override;
+        virtual bool UseLimitRangeGetInsteadOfHead() override { return true; }
+        virtual void ProcessGetFileSizeResult( const char* pszContent )
+            override;
 
     public:
-        VSIS3Handle(VSIS3FSHandler* poFS,
-                    VSIS3HandleHelper* poS3HandleHelper);
-        ~VSIS3Handle();
+        VSIS3Handle( VSIS3FSHandler* poFS,
+                     VSIS3HandleHelper* poS3HandleHelper );
+        virtual ~VSIS3Handle();
 };
 
 /************************************************************************/
@@ -3349,18 +3570,19 @@ class VSIS3WriteHandle CPL_FINAL : public VSIVirtualHandle
     bool                DoSinglePartPUT();
 
     public:
-        VSIS3WriteHandle(VSIS3FSHandler* poFS,
-                         const char* pszFilename,
-                         VSIS3HandleHelper* poS3HandleHelper);
-        ~VSIS3WriteHandle();
-
-        virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-        virtual vsi_l_offset Tell();
-        virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-        virtual size_t    Write( const void *pBuffer, size_t nSize
-                                 ,size_t nMemb );
-        virtual int       Eof();
-        virtual int       Close();
+        VSIS3WriteHandle( VSIS3FSHandler* poFS,
+                          const char* pszFilename,
+                          VSIS3HandleHelper* poS3HandleHelper );
+        virtual ~VSIS3WriteHandle();
+
+        virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+        virtual vsi_l_offset Tell() override;
+        virtual size_t    Read( void *pBuffer, size_t nSize,
+                                size_t nMemb ) override;
+        virtual size_t    Write( const void *pBuffer, size_t nSize,
+                                 size_t nMemb ) override;
+        virtual int       Eof() override;
+        virtual int       Close() override;
 
         bool              IsOK() { return m_pabyBuffer != NULL; }
 };
@@ -3369,9 +3591,9 @@ class VSIS3WriteHandle CPL_FINAL : public VSIVirtualHandle
 /*                         VSIS3WriteHandle()                           */
 /************************************************************************/
 
-VSIS3WriteHandle::VSIS3WriteHandle(VSIS3FSHandler* poFS,
-                                   const char* pszFilename,
-                                   VSIS3HandleHelper* poS3HandleHelper) :
+VSIS3WriteHandle::VSIS3WriteHandle( VSIS3FSHandler* poFS,
+                                    const char* pszFilename,
+                                    VSIS3HandleHelper* poS3HandleHelper ) :
         m_poFS(poFS), m_osFilename(pszFilename),
         m_poS3HandleHelper(poS3HandleHelper),
         m_nCurOffset(0),
@@ -3382,12 +3604,12 @@ VSIS3WriteHandle::VSIS3WriteHandle(VSIS3FSHandler* poFS,
         m_nOffsetInXML(0),
         m_bError(false)
 {
-    int nChunkSizeMB = atoi(CPLGetConfigOption("VSIS3_CHUNK_SIZE", "50"));
+    const int nChunkSizeMB = atoi(CPLGetConfigOption("VSIS3_CHUNK_SIZE", "50"));
     if( nChunkSizeMB <= 0 || nChunkSizeMB > 1000 )
         m_nBufferSize = 0;
     else
         m_nBufferSize = nChunkSizeMB * 1024 * 1024;
-    m_pabyBuffer = (GByte*)VSIMalloc(m_nBufferSize);
+    m_pabyBuffer = static_cast<GByte *>(VSIMalloc(m_nBufferSize));
     if( m_pabyBuffer == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
@@ -3416,7 +3638,7 @@ int VSIS3WriteHandle::Seek( vsi_l_offset nOffset, int nWhence )
         nOffset != 0 )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                    "Seek not supported on writable /vsis3 files");
+                 "Seek not supported on writable /vsis3 files");
         m_bError = true;
         return -1;
     }
@@ -3458,7 +3680,8 @@ bool VSIS3WriteHandle::InitiateMultipartUpload()
         bGoOn = false;
         CURL* hCurlHandle = curl_easy_init();
         m_poS3HandleHelper->AddQueryParameter("uploads", "");
-        curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+        curl_easy_setopt(hCurlHandle, CURLOPT_URL,
+                         m_poS3HandleHelper->GetURL().c_str());
         CPLHTTPSetOptions(hCurlHandle, NULL);
         curl_easy_setopt(hCurlHandle, CURLOPT_CUSTOMREQUEST, "POST");
 
@@ -3470,7 +3693,8 @@ bool VSIS3WriteHandle::InitiateMultipartUpload()
         WriteFuncStruct sWriteFuncData;
         VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
         curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                         VSICurlHandleWriteFunc);
 
         curl_easy_perform(hCurlHandle);
 
@@ -3481,35 +3705,45 @@ bool VSIS3WriteHandle::InitiateMultipartUpload()
         if( response_code != 200 || sWriteFuncData.pBuffer == NULL )
         {
             if( sWriteFuncData.pBuffer != NULL &&
-                m_poS3HandleHelper->CanRestartOnError( (const char*)sWriteFuncData.pBuffer) )
+                m_poS3HandleHelper->CanRestartOnError(sWriteFuncData.pBuffer) )
             {
                 m_poFS->UpdateMapFromHandle(m_poS3HandleHelper);
                 bGoOn = true;
             }
             else
             {
-                CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
-                CPLError(CE_Failure, CPLE_AppDefined, "InitiateMultipartUpload of %s failed",
-                            m_osFilename.c_str());
+                CPLDebug("S3", "%s",
+                         sWriteFuncData.pBuffer
+                         ? sWriteFuncData.pBuffer
+                         : "(null)");
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "InitiateMultipartUpload of %s failed",
+                         m_osFilename.c_str());
                 bSuccess = false;
             }
         }
         else
         {
-            m_poFS->InvalidateCachedFileProp( m_poS3HandleHelper->GetURL().c_str() );
+            m_poFS->InvalidateCachedFileProp(
+                m_poS3HandleHelper->GetURL().c_str());
             m_poFS->InvalidateDirContent( CPLGetDirname(m_osFilename) );
 
-            CPLXMLNode* psNode = CPLParseXMLString( (const char*)sWriteFuncData.pBuffer );
+            CPLXMLNode* psNode =
+                CPLParseXMLString( sWriteFuncData.pBuffer );
             if( psNode )
             {
-                m_osUploadID = CPLGetXMLValue(psNode, "=InitiateMultipartUploadResult.UploadId", "");
+                m_osUploadID =
+                    CPLGetXMLValue(
+                        psNode, "=InitiateMultipartUploadResult.UploadId", "");
                 CPLDebug("S3", "UploadId: %s", m_osUploadID.c_str());
                 CPLDestroyXMLNode(psNode);
             }
-            if( m_osUploadID.size() == 0 )
+            if( m_osUploadID.empty() )
             {
-                CPLError(CE_Failure, CPLE_AppDefined, "InitiateMultipartUpload of %s failed: cannot get UploadId",
-                         m_osFilename.c_str());
+                CPLError(
+                    CE_Failure, CPLE_AppDefined,
+                    "InitiateMultipartUpload of %s failed: cannot get UploadId",
+                    m_osFilename.c_str());
                 bSuccess = false;
             }
         }
@@ -3527,11 +3761,13 @@ bool VSIS3WriteHandle::InitiateMultipartUpload()
 /************************************************************************/
 
 size_t VSIS3WriteHandle::ReadCallBackBuffer( char *buffer, size_t size,
-                                             size_t nitems, void *instream)
+                                             size_t nitems, void *instream )
 {
-    VSIS3WriteHandle* poThis = (VSIS3WriteHandle*)instream;
-    int nSizeMax = (int)(size * nitems);
-    int nSizeToWrite = MIN(nSizeMax, poThis->m_nBufferOff - poThis->m_nBufferOffReadCallback);
+    VSIS3WriteHandle* poThis = static_cast<VSIS3WriteHandle *>(instream);
+    const int nSizeMax = static_cast<int>(size * nitems);
+    const int nSizeToWrite =
+        std::min(nSizeMax,
+                 poThis->m_nBufferOff - poThis->m_nBufferOffReadCallback);
     memcpy(buffer, poThis->m_pabyBuffer + poThis->m_nBufferOffReadCallback,
            nSizeToWrite);
     poThis->m_nBufferOffReadCallback += nSizeToWrite;
@@ -3544,14 +3780,16 @@ size_t VSIS3WriteHandle::ReadCallBackBuffer( char *buffer, size_t size,
 
 bool VSIS3WriteHandle::UploadPart()
 {
-    ++ m_nPartNumber;
+    ++m_nPartNumber;
     if( m_nPartNumber > 10000 )
     {
         m_bError = true;
-        CPLError(CE_Failure, CPLE_AppDefined,
-                 "10000 parts have been uploaded for %s failed. This is the maximum. "
-                 "Increase VSIS3_CHUNK_SIZE to a higher value (e.g. 500 for 500 MB)",
-                 m_osFilename.c_str());
+        CPLError(
+            CE_Failure, CPLE_AppDefined,
+            "10000 parts have been uploaded for %s failed. "
+            "This is the maximum. "
+            "Increase VSIS3_CHUNK_SIZE to a higher value (e.g. 500 for 500 MB)",
+            m_osFilename.c_str());
         return false;
     }
 
@@ -3559,18 +3797,21 @@ bool VSIS3WriteHandle::UploadPart()
 
     m_nBufferOffReadCallback = 0;
     CURL* hCurlHandle = curl_easy_init();
-    m_poS3HandleHelper->AddQueryParameter("partNumber", CPLSPrintf("%d", m_nPartNumber));
+    m_poS3HandleHelper->AddQueryParameter("partNumber",
+                                          CPLSPrintf("%d", m_nPartNumber));
     m_poS3HandleHelper->AddQueryParameter("uploadId", m_osUploadID);
-    curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+    curl_easy_setopt(hCurlHandle, CURLOPT_URL,
+                     m_poS3HandleHelper->GetURL().c_str());
     CPLHTTPSetOptions(hCurlHandle, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_UPLOAD, 1L);
     curl_easy_setopt(hCurlHandle, CURLOPT_READFUNCTION, ReadCallBackBuffer);
     curl_easy_setopt(hCurlHandle, CURLOPT_READDATA, this);
     curl_easy_setopt(hCurlHandle, CURLOPT_INFILESIZE, m_nBufferOff);
 
-    struct curl_slist* headers = m_poS3HandleHelper->GetCurlHeaders("PUT",
-                                                                    m_pabyBuffer,
-                                                                    m_nBufferOff);
+    struct curl_slist* headers =
+        m_poS3HandleHelper->GetCurlHeaders("PUT",
+                                           m_pabyBuffer,
+                                           m_nBufferOff);
     curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
 
     m_poS3HandleHelper->ResetQueryParameters();
@@ -3578,12 +3819,14 @@ bool VSIS3WriteHandle::UploadPart()
     WriteFuncStruct sWriteFuncData;
     VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                     VSICurlHandleWriteFunc);
 
     WriteFuncStruct sWriteFuncHeaderData;
     VSICURLInitWriteFuncStruct(&sWriteFuncHeaderData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlHandleWriteFunc);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION,
+                     VSICurlHandleWriteFunc);
 
     curl_easy_perform(hCurlHandle);
 
@@ -3593,27 +3836,30 @@ bool VSIS3WriteHandle::UploadPart()
     curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
     if( response_code != 200 || sWriteFuncHeaderData.pBuffer == NULL )
     {
-        CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
+        CPLDebug("S3", "%s",
+                 sWriteFuncData.pBuffer ? sWriteFuncData.pBuffer : "(null)");
         CPLError(CE_Failure, CPLE_AppDefined, "UploadPart(%d) of %s failed",
                     m_nPartNumber, m_osFilename.c_str());
         bSuccess = false;
     }
     else
     {
-        const char* pszEtag = strstr((const char*)sWriteFuncHeaderData.pBuffer, "ETag: ");
+        const char* pszEtag = strstr(sWriteFuncHeaderData.pBuffer, "ETag: ");
         if( pszEtag != NULL )
         {
             CPLString osEtag = pszEtag + strlen("ETag: ");
-            size_t nPos = osEtag.find("\r");
+            const size_t nPos = osEtag.find("\r");
             if( nPos != std::string::npos )
                 osEtag.resize(nPos);
-            CPLDebug("S3", "Etag for part %d is %s", m_nPartNumber, osEtag.c_str());
+            CPLDebug("S3", "Etag for part %d is %s",
+                     m_nPartNumber, osEtag.c_str());
             m_aosEtags.push_back(osEtag);
         }
         else
         {
-            CPLError(CE_Failure, CPLE_AppDefined, "UploadPart(%d) of %s (uploadId = %s) failed",
-                        m_nPartNumber, m_osFilename.c_str(), m_osUploadID.c_str());
+            CPLError(CE_Failure, CPLE_AppDefined,
+                     "UploadPart(%d) of %s (uploadId = %s) failed",
+                     m_nPartNumber, m_osFilename.c_str(), m_osUploadID.c_str());
             bSuccess = false;
         }
     }
@@ -3630,16 +3876,19 @@ bool VSIS3WriteHandle::UploadPart()
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSIS3WriteHandle::Write( const void *pBuffer, size_t nSize,size_t nMemb)
+size_t
+VSIS3WriteHandle::Write( const void *pBuffer, size_t nSize, size_t nMemb )
 {
-    size_t nBytesToWrite = nSize * nMemb;
-
     if( m_bError )
         return false;
 
+    size_t nBytesToWrite = nSize * nMemb;
+
     while( nBytesToWrite > 0 )
     {
-        int nToWriteInBuffer = (int)MIN((size_t)(m_nBufferSize - m_nBufferOff), nBytesToWrite);
+        const int nToWriteInBuffer = static_cast<int>(
+            std::min(static_cast<size_t>(m_nBufferSize - m_nBufferOff),
+                     nBytesToWrite));
         memcpy(m_pabyBuffer + m_nBufferOff, pBuffer, nToWriteInBuffer);
         m_nBufferOff += nToWriteInBuffer;
         m_nCurOffset += nToWriteInBuffer;
@@ -3687,22 +3936,25 @@ bool VSIS3WriteHandle::DoSinglePartPUT()
         bGoOn = false;
         m_nBufferOffReadCallback = 0;
         CURL* hCurlHandle = curl_easy_init();
-        curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+        curl_easy_setopt(hCurlHandle, CURLOPT_URL,
+                         m_poS3HandleHelper->GetURL().c_str());
         CPLHTTPSetOptions(hCurlHandle, NULL);
         curl_easy_setopt(hCurlHandle, CURLOPT_UPLOAD, 1L);
         curl_easy_setopt(hCurlHandle, CURLOPT_READFUNCTION, ReadCallBackBuffer);
         curl_easy_setopt(hCurlHandle, CURLOPT_READDATA, this);
         curl_easy_setopt(hCurlHandle, CURLOPT_INFILESIZE, m_nBufferOff);
 
-        struct curl_slist* headers = m_poS3HandleHelper->GetCurlHeaders("PUT",
-                                                                        m_pabyBuffer,
-                                                                        m_nBufferOff);
+        struct curl_slist* headers =
+            m_poS3HandleHelper->GetCurlHeaders("PUT",
+                                               m_pabyBuffer,
+                                               m_nBufferOff);
         curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
 
         WriteFuncStruct sWriteFuncData;
         VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
         curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                         VSICurlHandleWriteFunc);
 
         curl_easy_perform(hCurlHandle);
 
@@ -3713,22 +3965,27 @@ bool VSIS3WriteHandle::DoSinglePartPUT()
         if( response_code != 200 )
         {
             if( sWriteFuncData.pBuffer != NULL &&
-                m_poS3HandleHelper->CanRestartOnError( (const char*)sWriteFuncData.pBuffer) )
+                m_poS3HandleHelper->CanRestartOnError(sWriteFuncData.pBuffer) )
             {
                 m_poFS->UpdateMapFromHandle(m_poS3HandleHelper);
                 bGoOn = true;
             }
             else
             {
-                CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
-                CPLError(CE_Failure, CPLE_AppDefined, "DoSinglePartPUT of %s failed",
-                            m_osFilename.c_str());
+                CPLDebug("S3", "%s",
+                         sWriteFuncData.pBuffer
+                         ? sWriteFuncData.pBuffer
+                         : "(null)");
+                CPLError(CE_Failure, CPLE_AppDefined,
+                         "DoSinglePartPUT of %s failed",
+                         m_osFilename.c_str());
                 bSuccess = false;
             }
         }
         else
         {
-            m_poFS->InvalidateCachedFileProp( m_poS3HandleHelper->GetURL().c_str() );
+            m_poFS->InvalidateCachedFileProp(
+                m_poS3HandleHelper->GetURL().c_str() );
             m_poFS->InvalidateDirContent( CPLGetDirname(m_osFilename) );
         }
 
@@ -3744,11 +4001,15 @@ bool VSIS3WriteHandle::DoSinglePartPUT()
 /*                            ReadCallBackXML()                         */
 /************************************************************************/
 
-size_t VSIS3WriteHandle::ReadCallBackXML(char *buffer, size_t size, size_t nitems, void *instream)
+size_t VSIS3WriteHandle::ReadCallBackXML( char *buffer, size_t size,
+                                          size_t nitems, void *instream )
 {
-    VSIS3WriteHandle* poThis = (VSIS3WriteHandle*)instream;
-    int nSizeMax = (int)(size * nitems);
-    int nSizeToWrite = MIN(nSizeMax, (int)poThis->m_osXML.size() - poThis->m_nOffsetInXML);
+    VSIS3WriteHandle* poThis = static_cast<VSIS3WriteHandle *>(instream);
+    const int nSizeMax = static_cast<int>(size * nitems);
+    const int nSizeToWrite =
+        std::min(nSizeMax,
+                 static_cast<int>(poThis->m_osXML.size()) -
+                 poThis->m_nOffsetInXML);
     memcpy(buffer, poThis->m_osXML.c_str() + poThis->m_nOffsetInXML,
            nSizeToWrite);
     poThis->m_nOffsetInXML += nSizeToWrite;
@@ -3764,10 +4025,11 @@ bool VSIS3WriteHandle::CompleteMultipart()
     bool bSuccess = true;
 
     m_osXML = "<CompleteMultipartUpload>\n";
-    for(size_t i=0;i<m_aosEtags.size();i++)
+    for( size_t i = 0; i < m_aosEtags.size(); i++ )
     {
         m_osXML += "<Part>\n";
-        m_osXML += CPLSPrintf("<PartNumber>%d</PartNumber>", (int)(i+1));
+        m_osXML += CPLSPrintf("<PartNumber>%d</PartNumber>",
+                              static_cast<int>(i+1));
         m_osXML += "<ETag>" + m_aosEtags[i] + "</ETag>";
         m_osXML += "</Part>\n";
     }
@@ -3776,17 +4038,19 @@ bool VSIS3WriteHandle::CompleteMultipart()
     m_nOffsetInXML = 0;
     CURL* hCurlHandle = curl_easy_init();
     m_poS3HandleHelper->AddQueryParameter("uploadId", m_osUploadID);
-    curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+    curl_easy_setopt(hCurlHandle, CURLOPT_URL,
+                     m_poS3HandleHelper->GetURL().c_str());
     CPLHTTPSetOptions(hCurlHandle, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_UPLOAD, 1L);
     curl_easy_setopt(hCurlHandle, CURLOPT_READFUNCTION, ReadCallBackXML);
     curl_easy_setopt(hCurlHandle, CURLOPT_READDATA, this);
-    curl_easy_setopt(hCurlHandle, CURLOPT_INFILESIZE, (int)m_osXML.size());
+    curl_easy_setopt(hCurlHandle, CURLOPT_INFILESIZE,
+                     static_cast<int>(m_osXML.size()));
     curl_easy_setopt(hCurlHandle, CURLOPT_CUSTOMREQUEST, "POST");
 
-    struct curl_slist* headers = m_poS3HandleHelper->GetCurlHeaders("POST",
-                                                                    m_osXML.c_str(),
-                                                                    m_osXML.size());
+    struct curl_slist* headers =
+        m_poS3HandleHelper->GetCurlHeaders("POST", m_osXML.c_str(),
+                                           m_osXML.size());
     curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
 
     m_poS3HandleHelper->ResetQueryParameters();
@@ -3794,7 +4058,8 @@ bool VSIS3WriteHandle::CompleteMultipart()
     WriteFuncStruct sWriteFuncData;
     VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                     VSICurlHandleWriteFunc);
 
     curl_easy_perform(hCurlHandle);
 
@@ -3804,9 +4069,11 @@ bool VSIS3WriteHandle::CompleteMultipart()
     curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
     if( response_code != 200 )
     {
-        CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
-        CPLError(CE_Failure, CPLE_AppDefined, "CompleteMultipart of %s (uploadId=%s) failed",
-                    m_osFilename.c_str(), m_osUploadID.c_str());
+        CPLDebug("S3", "%s",
+                 sWriteFuncData.pBuffer ? sWriteFuncData.pBuffer : "(null)");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "CompleteMultipart of %s (uploadId=%s) failed",
+                 m_osFilename.c_str(), m_osUploadID.c_str());
         bSuccess = false;
     }
 
@@ -3827,7 +4094,8 @@ bool VSIS3WriteHandle::AbortMultipart()
 
     CURL* hCurlHandle = curl_easy_init();
     m_poS3HandleHelper->AddQueryParameter("uploadId", m_osUploadID);
-    curl_easy_setopt(hCurlHandle, CURLOPT_URL, m_poS3HandleHelper->GetURL().c_str());
+    curl_easy_setopt(hCurlHandle, CURLOPT_URL,
+                     m_poS3HandleHelper->GetURL().c_str());
     CPLHTTPSetOptions(hCurlHandle, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
 
@@ -3839,7 +4107,8 @@ bool VSIS3WriteHandle::AbortMultipart()
     WriteFuncStruct sWriteFuncData;
     VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                     VSICurlHandleWriteFunc);
 
     curl_easy_perform(hCurlHandle);
 
@@ -3849,9 +4118,11 @@ bool VSIS3WriteHandle::AbortMultipart()
     curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
     if( response_code != 204 )
     {
-        CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
-        CPLError(CE_Failure, CPLE_AppDefined, "AbortMultipart of %s (uploadId=%s) failed",
-                    m_osFilename.c_str(), m_osUploadID.c_str());
+        CPLDebug("S3", "%s",
+                 sWriteFuncData.pBuffer ? sWriteFuncData.pBuffer : "(null)");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "AbortMultipart of %s (uploadId=%s) failed",
+                 m_osFilename.c_str(), m_osUploadID.c_str());
         bSuccess = false;
     }
 
@@ -3872,7 +4143,7 @@ int VSIS3WriteHandle::Close()
     if( !m_bClosed )
     {
         m_bClosed = true;
-        if( m_osUploadID.size() == 0 )
+        if( m_osUploadID.empty() )
         {
             if( !m_bError && !DoSinglePartPUT() )
                 nRet = -1;
@@ -3901,7 +4172,7 @@ VSIVirtualHandle* VSIS3FSHandler::Open( const char *pszFilename,
                                         const char *pszAccess,
                                         bool bSetError)
 {
-    if (strchr(pszAccess, 'w') != NULL )
+    if( strchr(pszAccess, 'w') != NULL || strchr(pszAccess, 'a') != NULL )
     {
         /*if( strchr(pszAccess, '+') != NULL)
         {
@@ -3915,7 +4186,8 @@ VSIVirtualHandle* VSIS3FSHandler::Open( const char *pszFilename,
         if( poS3HandleHelper == NULL )
             return NULL;
         UpdateHandleFromMap(poS3HandleHelper);
-        VSIS3WriteHandle* poHandle = new VSIS3WriteHandle(this, pszFilename, poS3HandleHelper);
+        VSIS3WriteHandle* poHandle =
+            new VSIS3WriteHandle(this, pszFilename, poS3HandleHelper);
         if( !poHandle->IsOK() )
         {
             delete poHandle;
@@ -3923,10 +4195,9 @@ VSIVirtualHandle* VSIS3FSHandler::Open( const char *pszFilename,
         }
         return poHandle;
     }
-    else
-    {
-        return VSICurlFilesystemHandler::Open(pszFilename, pszAccess, bSetError);
-    }
+
+    return
+        VSICurlFilesystemHandler::Open(pszFilename, pszAccess, bSetError);
 }
 
 /************************************************************************/
@@ -3946,10 +4217,10 @@ int VSIS3FSHandler::Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
 /*                          CreateFileHandle()                          */
 /************************************************************************/
 
-VSICurlHandle* VSIS3FSHandler::CreateFileHandle(const char* pszURL)
+VSICurlHandle* VSIS3FSHandler::CreateFileHandle(const char* pszUnprefixed)
 {
     VSIS3HandleHelper* poS3HandleHelper =
-            VSIS3HandleHelper::BuildFromURI(pszURL, GetFSPrefix().c_str(), false);
+        VSIS3HandleHelper::BuildFromURI(pszUnprefixed, GetFSPrefix().c_str(), false);
     if( poS3HandleHelper )
     {
         UpdateHandleFromMap(poS3HandleHelper);
@@ -3967,14 +4238,15 @@ CPLString VSIS3FSHandler::GetURLFromDirname( const CPLString& osDirname )
     CPLString osDirnameWithoutPrefix = osDirname.substr(GetFSPrefix().size());
 
     VSIS3HandleHelper* poS3HandleHelper =
-            VSIS3HandleHelper::BuildFromURI(osDirnameWithoutPrefix, GetFSPrefix().c_str(), true);
+        VSIS3HandleHelper::BuildFromURI(osDirnameWithoutPrefix,
+                                        GetFSPrefix().c_str(), true);
     if( poS3HandleHelper == NULL )
     {
         return "";
     }
     UpdateHandleFromMap(poS3HandleHelper);
     CPLString osBaseURL(poS3HandleHelper->GetURL());
-    if( osBaseURL.size() && osBaseURL[osBaseURL.size()-1] == '/' )
+    if( !osBaseURL.empty() && osBaseURL.back() == '/' )
         osBaseURL.resize(osBaseURL.size()-1);
     delete poS3HandleHelper;
 
@@ -3989,7 +4261,8 @@ int VSIS3FSHandler::Unlink( const char *pszFilename )
 {
     CPLString osNameWithoutPrefix = pszFilename + GetFSPrefix().size();
     VSIS3HandleHelper* poS3HandleHelper =
-            VSIS3HandleHelper::BuildFromURI(osNameWithoutPrefix, GetFSPrefix().c_str(), false);
+        VSIS3HandleHelper::BuildFromURI(osNameWithoutPrefix,
+                                        GetFSPrefix().c_str(), false);
     if( poS3HandleHelper == NULL )
     {
         return -1;
@@ -4003,7 +4276,8 @@ int VSIS3FSHandler::Unlink( const char *pszFilename )
     {
         bGoOn = false;
         CURL* hCurlHandle = curl_easy_init();
-        curl_easy_setopt(hCurlHandle, CURLOPT_URL, poS3HandleHelper->GetURL().c_str());
+        curl_easy_setopt(hCurlHandle, CURLOPT_URL,
+                         poS3HandleHelper->GetURL().c_str());
         CPLHTTPSetOptions(hCurlHandle, NULL);
         curl_easy_setopt(hCurlHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
 
@@ -4013,7 +4287,8 @@ int VSIS3FSHandler::Unlink( const char *pszFilename )
         WriteFuncStruct sWriteFuncData;
         VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
         curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                         VSICurlHandleWriteFunc);
 
         curl_easy_perform(hCurlHandle);
 
@@ -4024,14 +4299,17 @@ int VSIS3FSHandler::Unlink( const char *pszFilename )
         if( response_code != 204 )
         {
             if( sWriteFuncData.pBuffer != NULL &&
-                poS3HandleHelper->CanRestartOnError( (const char*)sWriteFuncData.pBuffer) )
+                poS3HandleHelper->CanRestartOnError(sWriteFuncData.pBuffer) )
             {
                 UpdateMapFromHandle(poS3HandleHelper);
                 bGoOn = true;
             }
             else
             {
-                CPLDebug("S3", "%s", (sWriteFuncData.pBuffer) ? (const char*)sWriteFuncData.pBuffer : "(null)");
+                CPLDebug("S3", "%s",
+                         sWriteFuncData.pBuffer
+                         ? sWriteFuncData.pBuffer
+                         : "(null)");
                 CPLError(CE_Failure, CPLE_AppDefined, "Delete of %s failed",
                          pszFilename);
                 nRet = -1;
@@ -4061,15 +4339,14 @@ char** VSIS3FSHandler::GetFileList( const char *pszDirname,
                                     int nMaxFiles,
                                     bool* pbGotFileList )
 {
-    // TODO: to implement
-    if (ENABLE_DEBUG)
+    if( ENABLE_DEBUG )
         CPLDebug("S3", "GetFileList(%s)" , pszDirname);
     *pbGotFileList = false;
     CPLString osDirnameWithoutPrefix = pszDirname + GetFSPrefix().size();
 
-
     VSIS3HandleHelper* poS3HandleHelper =
-            VSIS3HandleHelper::BuildFromURI(osDirnameWithoutPrefix, GetFSPrefix().c_str(), true);
+            VSIS3HandleHelper::BuildFromURI(osDirnameWithoutPrefix,
+                                            GetFSPrefix().c_str(), true);
     if( poS3HandleHelper == NULL )
     {
         return NULL;
@@ -4081,45 +4358,47 @@ char** VSIS3FSHandler::GetFileList( const char *pszDirname,
 
     WriteFuncStruct sWriteFuncData;
 
-    CPLStringList osFileList;
-    CPLString osNextMarker;
+    CPLStringList osFileList; // must be left in this scope !
+    CPLString osNextMarker; // must be left in this scope !
 
     CPLString osMaxKeys = CPLGetConfigOption("AWS_MAX_KEYS", "");
 
-    while(true)
+    while( true )
     {
         poS3HandleHelper->ResetQueryParameters();
         CPLString osBaseURL(poS3HandleHelper->GetURL());
 
-    #if LIBCURL_VERSION_NUM < 0x070B00
-        /* Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have been */
-        /* previously set, so we have to reinit the connection handle */
+#if LIBCURL_VERSION_NUM < 0x070B00
+        // Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have
+        // been previously set, so we have to reinit the connection handle.
         GetCurlHandleFor("");
-    #endif
+#endif
 
         CURL* hCurlHandle = GetCurlHandleFor(osBaseURL);
 
         poS3HandleHelper->AddQueryParameter("delimiter", "/");
-        if( osNextMarker.size() )
+        if( !osNextMarker.empty() )
             poS3HandleHelper->AddQueryParameter("marker", osNextMarker);
-        if( osMaxKeys.size() )
+        if( !osMaxKeys.empty() )
              poS3HandleHelper->AddQueryParameter("max-keys", osMaxKeys);
-        if( osObjectKey.size() )
+        if( !osObjectKey.empty() )
              poS3HandleHelper->AddQueryParameter("prefix", osObjectKey + "/");
 
-        VSICurlSetOptions(hCurlHandle, poS3HandleHelper->GetURL());
+        struct curl_slist* headers = 
+            VSICurlSetOptions(hCurlHandle, poS3HandleHelper->GetURL(), NULL);
 
         curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, NULL);
 
         VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
         curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlHandleWriteFunc);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                         VSICurlHandleWriteFunc);
 
-        char szCurlErrBuf[CURL_ERROR_SIZE+1];
-        szCurlErrBuf[0] = '\0';
+        char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
         curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
-        struct curl_slist* headers = poS3HandleHelper->GetCurlHeaders("GET");
+        headers = VSICurlMergeHeaders(headers,
+                               poS3HandleHelper->GetCurlHeaders("GET"));
         if( headers != NULL )
             curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
 
@@ -4128,7 +4407,7 @@ char** VSIS3FSHandler::GetFileList( const char *pszDirname,
         if( headers != NULL )
             curl_slist_free_all(headers);
 
-        if (sWriteFuncData.pBuffer == NULL)
+        if( sWriteFuncData.pBuffer == NULL)
         {
             delete poS3HandleHelper;
             return NULL;
@@ -4139,14 +4418,16 @@ char** VSIS3FSHandler::GetFileList( const char *pszDirname,
         if( response_code != 200 )
         {
             if( sWriteFuncData.pBuffer != NULL &&
-                poS3HandleHelper->CanRestartOnError( (const char*)sWriteFuncData.pBuffer) )
+                poS3HandleHelper->CanRestartOnError(sWriteFuncData.pBuffer) )
             {
                 UpdateMapFromHandle(poS3HandleHelper);
                 CPLFree(sWriteFuncData.pBuffer);
             }
             else
             {
-                CPLDebug("S3", "%s", sWriteFuncData.pBuffer ? (const char*)sWriteFuncData.pBuffer : "(null)");
+                CPLDebug("S3", "%s",
+                         sWriteFuncData.pBuffer
+                         ? sWriteFuncData.pBuffer : "(null)");
                 CPLFree(sWriteFuncData.pBuffer);
                 delete poS3HandleHelper;
                 return NULL;
@@ -4155,17 +4436,17 @@ char** VSIS3FSHandler::GetFileList( const char *pszDirname,
         else
         {
             *pbGotFileList = true;
-            bool bIsTrucated;
+            bool bIsTruncated;
             AnalyseS3FileList( osBaseURL,
-                               (const char*)sWriteFuncData.pBuffer,
+                               sWriteFuncData.pBuffer,
                                osFileList,
                                nMaxFiles,
-                               bIsTrucated,
+                               bIsTruncated,
                                osNextMarker );
 
             CPLFree(sWriteFuncData.pBuffer);
 
-            if( osNextMarker.size() == 0 )
+            if( osNextMarker.empty() )
             {
                 delete poS3HandleHelper;
                 return osFileList.StealList();
@@ -4178,13 +4459,14 @@ char** VSIS3FSHandler::GetFileList( const char *pszDirname,
 /*                         UpdateMapFromHandle()                        */
 /************************************************************************/
 
-void VSIS3FSHandler::UpdateMapFromHandle(VSIS3HandleHelper * poS3HandleHelper)
+void VSIS3FSHandler::UpdateMapFromHandle( VSIS3HandleHelper * poS3HandleHelper )
 {
     CPLMutexHolder oHolder( &hMutex );
 
     oMapBucketsToS3Params[ poS3HandleHelper->GetBucket() ] =
         VSIS3UpdateParams ( poS3HandleHelper->GetAWSRegion(),
                       poS3HandleHelper->GetAWSS3Endpoint(),
+                      poS3HandleHelper->GetRequestPayer(),
                       poS3HandleHelper->GetVirtualHosting() );
 }
 
@@ -4192,7 +4474,7 @@ void VSIS3FSHandler::UpdateMapFromHandle(VSIS3HandleHelper * poS3HandleHelper)
 /*                         UpdateHandleFromMap()                        */
 /************************************************************************/
 
-void VSIS3FSHandler::UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper)
+void VSIS3FSHandler::UpdateHandleFromMap( VSIS3HandleHelper * poS3HandleHelper )
 {
     CPLMutexHolder oHolder( &hMutex );
 
@@ -4200,9 +4482,10 @@ void VSIS3FSHandler::UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper)
         oMapBucketsToS3Params.find(poS3HandleHelper->GetBucket());
     if( oIter != oMapBucketsToS3Params.end() )
     {
-        poS3HandleHelper->SetAWSRegion( oIter->second.m_osAWSRegion );
-        poS3HandleHelper->SetAWSS3Endpoint( oIter->second.m_osAWSS3Endpoint );
-        poS3HandleHelper->SetVirtualHosting( oIter->second.m_bUseVirtualHosting );
+        poS3HandleHelper->SetAWSRegion(oIter->second.m_osAWSRegion);
+        poS3HandleHelper->SetAWSS3Endpoint(oIter->second.m_osAWSS3Endpoint);
+        poS3HandleHelper->SetRequestPayer(oIter->second.m_osRequestPayer);
+        poS3HandleHelper->SetVirtualHosting(oIter->second.m_bUseVirtualHosting);
     }
 }
 
@@ -4210,11 +4493,11 @@ void VSIS3FSHandler::UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper)
 /*                             VSIS3Handle()                            */
 /************************************************************************/
 
-VSIS3Handle::VSIS3Handle(VSIS3FSHandler* poFSIn, VSIS3HandleHelper* poS3HandleHelper) :
+VSIS3Handle::VSIS3Handle( VSIS3FSHandler* poFSIn,
+                          VSIS3HandleHelper* poS3HandleHelper ) :
         VSICurlHandle(poFSIn, poS3HandleHelper->GetURL()),
         m_poS3HandleHelper(poS3HandleHelper)
-{
-}
+{}
 
 /************************************************************************/
 /*                            ~VSIS3Handle()                            */
@@ -4229,7 +4512,7 @@ VSIS3Handle::~VSIS3Handle()
 /*                           GetCurlHeaders()                           */
 /************************************************************************/
 
-struct curl_slist* VSIS3Handle::GetCurlHeaders(const CPLString& osVerb)
+struct curl_slist* VSIS3Handle::GetCurlHeaders( const CPLString& osVerb )
 {
     return m_poS3HandleHelper->GetCurlHeaders(osVerb);
 }
@@ -4242,7 +4525,8 @@ bool VSIS3Handle::CanRestartOnError(const char* pszErrorMsg, bool bSetError)
 {
     if( m_poS3HandleHelper->CanRestartOnError(pszErrorMsg, bSetError) )
     {
-        ((VSIS3FSHandler*) poFS)->UpdateMapFromHandle(m_poS3HandleHelper);
+        static_cast<VSIS3FSHandler *>(poFS)->
+            UpdateMapFromHandle(m_poS3HandleHelper);
 
         SetURL(m_poS3HandleHelper->GetURL());
         return true;
@@ -4254,11 +4538,365 @@ bool VSIS3Handle::CanRestartOnError(const char* pszErrorMsg, bool bSetError)
 /*                    ProcessGetFileSizeResult()                        */
 /************************************************************************/
 
-void VSIS3Handle::ProcessGetFileSizeResult(const char* pszContent)
+void VSIS3Handle::ProcessGetFileSizeResult( const char* pszContent )
 {
     bIsDirectory = strstr(pszContent, "ListBucketResult") != NULL;
 }
 
+
+/************************************************************************/
+/*                         VSIGSFSHandler                               */
+/************************************************************************/
+
+class VSIGSFSHandler CPL_FINAL : public VSICurlFilesystemHandler
+{
+protected:
+    virtual VSICurlHandle* CreateFileHandle( const char* pszUnprefixed ) override;
+    virtual char** GetFileList( const char *pszFilename,
+                                int nMaxFiles,
+                                bool* pbGotFileList ) override;
+
+public:
+        VSIGSFSHandler() {}
+
+        virtual CPLString GetFSPrefix() override { return "/vsigs/"; }
+        virtual CPLString GetURLFromDirname( const CPLString& osDirname ) override;
+};
+
+/************************************************************************/
+/*                            VSIGSHandle                               */
+/************************************************************************/
+
+class VSIGSHandle CPL_FINAL : public VSICurlHandle
+{
+    VSIGSHandleHelper* m_poHandleHelper;
+
+  protected:
+        virtual struct curl_slist* GetCurlHeaders( const CPLString& osVerb )
+            override;
+
+    public:
+        VSIGSHandle( VSIGSFSHandler* poFS, VSIGSHandleHelper* poHandleHelper);
+        virtual ~VSIGSHandle();
+};
+
+/************************************************************************/
+/*                          CreateFileHandle()                          */
+/************************************************************************/
+
+VSICurlHandle* VSIGSFSHandler::CreateFileHandle(const char* pszUnprefixed)
+{
+    VSIGSHandleHelper* poHandleHelper =
+        VSIGSHandleHelper::BuildFromURI( pszUnprefixed, GetFSPrefix() );
+    if( poHandleHelper == NULL )
+        return NULL;
+    return new VSIGSHandle(this, poHandleHelper);
+}
+
+/************************************************************************/
+/*                          GetURLFromDirname()                         */
+/************************************************************************/
+
+CPLString VSIGSFSHandler::GetURLFromDirname( const CPLString& osDirname )
+{
+    VSIGSHandleHelper* poHandleHelper =
+        VSIGSHandleHelper::BuildFromURI( osDirname, GetFSPrefix() );
+    if( poHandleHelper == NULL )
+        return CPLString();
+    CPLString osURL( poHandleHelper->GetURL() );
+    delete poHandleHelper;
+    return osURL;
+}
+
+/************************************************************************/
+/*                           GetFileList()                              */
+/************************************************************************/
+
+char** VSIGSFSHandler::GetFileList( const char *pszDirname,
+                                    int nMaxFiles,
+                                    bool* pbGotFileList )
+{
+    if( ENABLE_DEBUG )
+        CPLDebug("GS", "GetFileList(%s)" , pszDirname);
+    *pbGotFileList = false;
+
+    WriteFuncStruct sWriteFuncData;
+
+    CPLAssert( STARTS_WITH(pszDirname, GetFSPrefix().c_str()) );
+    CPLString osBucketObjectKey(pszDirname + GetFSPrefix().size());
+    CPLString osBucket(osBucketObjectKey);
+    CPLString osObjectKey;
+    size_t nSlashPos = osBucketObjectKey.find('/');
+    if( nSlashPos != std::string::npos )
+    {
+        osBucket = osBucketObjectKey.substr(0, nSlashPos);
+        osObjectKey = osBucketObjectKey.substr(nSlashPos+1);
+    }
+
+    VSIGSHandleHelper* poHandleHelper =
+        VSIGSHandleHelper::BuildFromURI( osBucket, GetFSPrefix() );
+    if( poHandleHelper == NULL )
+        return NULL;
+
+    CPLStringList osFileList; // must be left in this scope !
+    CPLString osNextMarker; // must be left in this scope !
+
+    const CPLString osMaxKeys = CPLGetConfigOption("AWS_MAX_KEYS", "");
+    const CPLString osBaseURL ( poHandleHelper->GetURL() );
+
+    while( true )
+    {
+
+#if LIBCURL_VERSION_NUM < 0x070B00
+        // Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have
+        // been previously set, so we have to reinit the connection handle.
+        GetCurlHandleFor("");
+#endif
+
+        CURL* hCurlHandle = GetCurlHandleFor(osBaseURL);
+        CPLString osURL ( osBaseURL );
+        osURL += "?delimiter=/";
+        if( !osNextMarker.empty() )
+            osURL += "&marker=" + osNextMarker;
+        if( !osMaxKeys.empty() )
+            osURL += "&max-keys=" + osMaxKeys;
+        if( !osObjectKey.empty() )
+            osURL += "&prefix=" + osObjectKey + "/";
+
+        struct curl_slist* headers =
+            VSICurlSetOptions(hCurlHandle, osURL, NULL);
+
+        curl_easy_setopt(hCurlHandle, CURLOPT_RANGE, NULL);
+
+        VSICURLInitWriteFuncStruct(&sWriteFuncData, NULL, NULL, NULL);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
+        curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                         VSICurlHandleWriteFunc);
+
+        char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
+        curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
+
+        headers = VSICurlMergeHeaders(headers,
+                                      poHandleHelper->GetCurlHeaders("GET"));
+        if( headers != NULL )
+            curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
+
+        curl_easy_perform(hCurlHandle);
+
+        if( headers != NULL )
+            curl_slist_free_all(headers);
+
+        if( sWriteFuncData.pBuffer == NULL)
+        {
+            delete poHandleHelper;
+            return NULL;
+        }
+
+        long response_code = 0;
+        curl_easy_getinfo(hCurlHandle, CURLINFO_HTTP_CODE, &response_code);
+        if( response_code == 200 )
+        {
+            *pbGotFileList = true;
+            bool bIsTruncated;
+            AnalyseS3FileList( osBaseURL + "/",
+                               sWriteFuncData.pBuffer,
+                               osFileList,
+                               nMaxFiles,
+                               bIsTruncated,
+                               osNextMarker );
+
+            CPLFree(sWriteFuncData.pBuffer);
+
+            if( osNextMarker.empty() )
+            {
+                delete poHandleHelper;
+                return osFileList.StealList();
+            }
+        }
+        else
+        {
+            delete poHandleHelper;
+            return NULL;
+        }
+    }
+}
+
+/************************************************************************/
+/*                             VSIGSHandle()                            */
+/************************************************************************/
+
+VSIGSHandle::VSIGSHandle( VSIGSFSHandler* poFSIn,
+                          VSIGSHandleHelper* poHandleHelper ) :
+        VSICurlHandle(poFSIn, poHandleHelper->GetURL()),
+        m_poHandleHelper(poHandleHelper)
+{}
+
+/************************************************************************/
+/*                            ~VSIGSHandle()                            */
+/************************************************************************/
+
+VSIGSHandle::~VSIGSHandle()
+{
+    delete m_poHandleHelper;
+}
+
+
+/************************************************************************/
+/*                          GetCurlHeaders()                            */
+/************************************************************************/
+
+struct curl_slist* VSIGSHandle::GetCurlHeaders( const CPLString& osVerb )
+{
+    if( CSLFetchNameValue(m_papszHTTPOptions, "HEADER_FILE") )
+        return NULL;
+    return m_poHandleHelper->GetCurlHeaders( osVerb );
+}
+
+} /* end of anoymous namespace */
+
+/************************************************************************/
+/*                      VSICurlInstallReadCbk()                         */
+/************************************************************************/
+
+int VSICurlInstallReadCbk( VSILFILE* fp,
+                           VSICurlReadCbkFunc pfnReadCbk,
+                           void* pfnUserData,
+                           int bStopOnInterruptUntilUninstall )
+{
+    return reinterpret_cast<VSICurlHandle *>(fp)->
+        InstallReadCbk(pfnReadCbk, pfnUserData, bStopOnInterruptUntilUninstall);
+}
+
+/************************************************************************/
+/*                    VSICurlUninstallReadCbk()                         */
+/************************************************************************/
+
+int VSICurlUninstallReadCbk( VSILFILE* fp )
+{
+    return reinterpret_cast<VSICurlHandle *>(fp)->UninstallReadCbk();
+}
+
+/************************************************************************/
+/*                       VSICurlSetOptions()                            */
+/************************************************************************/
+
+struct curl_slist* VSICurlSetOptions(
+                        CURL* hCurlHandle, const char* pszURL,
+                        const char * const* papszOptions )
+{
+    curl_easy_setopt(hCurlHandle, CURLOPT_URL, pszURL);
+
+    struct curl_slist* headers = static_cast<struct curl_slist*>(
+        CPLHTTPSetOptions(hCurlHandle, papszOptions));
+
+// 7.16
+#if LIBCURL_VERSION_NUM >= 0x071000
+    long option = CURLFTPMETHOD_SINGLECWD;
+    curl_easy_setopt(hCurlHandle, CURLOPT_FTP_FILEMETHOD, option);
+#endif
+
+// 7.12.3
+#if LIBCURL_VERSION_NUM > 0x070C03
+    // ftp://ftp2.cits.rncan.gc.ca/pub/cantopo/250k_tif/
+    // doesn't like EPSV command,
+    curl_easy_setopt(hCurlHandle, CURLOPT_FTP_USE_EPSV, 0);
+#endif
+
+    curl_easy_setopt(hCurlHandle, CURLOPT_NOBODY, 0);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HTTPGET, 1);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADER, 0);
+
+/* 7.16.4 */
+#if LIBCURL_VERSION_NUM <= 0x071004
+    curl_easy_setopt(hCurlHandle, CURLOPT_FTPLISTONLY, 0);
+#elif LIBCURL_VERSION_NUM > 0x071004
+    curl_easy_setopt(hCurlHandle, CURLOPT_DIRLISTONLY, 0);
+#endif
+
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, NULL);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, NULL);
+
+    return headers;
+}
+
+/************************************************************************/
+/*                     VSICurlMergeHeaders()                            */
+/************************************************************************/
+
+struct curl_slist* VSICurlMergeHeaders( struct curl_slist* poDest,
+                                        struct curl_slist* poSrcToDestroy )
+{
+    struct curl_slist* iter = poSrcToDestroy;
+    while( iter != NULL )
+    {
+        poDest = curl_slist_append(poDest, iter->data);
+        iter = iter->next;
+    }
+    if( poSrcToDestroy )
+        curl_slist_free_all(poSrcToDestroy);
+    return poDest;
+}
+
+
+#endif // DOXYGEN_SKIP
+//! @endcond
+
+/************************************************************************/
+/*                   VSIInstallCurlFileHandler()                        */
+/************************************************************************/
+
+/**
+ * \brief Install /vsicurl/ HTTP/FTP file system handler (requires libcurl)
+ *
+ * A special file handler is installed that allows on-the-fly random reading of
+ * files available through HTTP/FTP web protocols, without prior download of the
+ * entire file.
+ *
+ * Recognized filenames are of the form /vsicurl/http://path/to/remote/resource
+ * or /vsicurl/ftp://path/to/remote/resource where path/to/remote/resource is
+ * the URL of a remote resource.
+ *
+ * Partial downloads (requires the HTTP server to support random reading) are
+ * done with a 16 KB granularity by default. If the driver detects sequential
+ * reading it will progressively increase the chunk size up to 2 MB to improve
+ * download performance.
+ *
+ * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration
+ * options can be used to define a proxy server. The syntax to use is the one of
+ * Curl CURLOPT_PROXY, CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
+ *
+ * Starting with GDAL 1.10, the file can be cached in RAM by setting the
+ * configuration option VSI_CACHE to TRUE. The cache size defaults to 25 MB, but
+ * can be modified by setting the configuration option VSI_CACHE_SIZE (in
+ * bytes).
+ *
+ * Starting with GDAL 2.1, /vsicurl/ will try to query directly redirected URLs
+ * to Amazon S3 signed URLs during their validity period, so as to minimize
+ * round-trips. This behaviour can be disabled by setting the configuration
+ * option CPL_VSIL_CURL_USE_S3_REDIRECT to NO.
+ *
+ * Starting with GDAL 2.1.3, the CURL_CA_BUNDLE or SSL_CERT_FILE configuration
+ * options can be used to set the path to the Certification Authority (CA)
+ * bundle file (if not specified, curl will use a file in a system location).
+ *
+ * VSIStatL() will return the size in st_size member and file nature- file or
+ * directory - in st_mode member (the later only reliable with FTP resources for
+ * now).
+ *
+ * VSIReadDir() should be able to parse the HTML directory listing returned by
+ * the most popular web servers, such as Apache or Microsoft IIS.
+ *
+ * This special file handler can be combined with other virtual filesystems
+ * handlers, such as /vsizip. For example,
+ * /vsizip//vsicurl/path/to/remote/file.zip/path/inside/zip
+ *
+ * @since GDAL 1.8.0
+ */
+void VSIInstallCurlFileHandler( void )
+{
+    VSIFileManager::InstallHandler( "/vsicurl/", new VSICurlFilesystemHandler );
+}
+
 /************************************************************************/
 /*                      VSIInstallS3FileHandler()                       */
 /************************************************************************/
@@ -4266,10 +4904,11 @@ void VSIS3Handle::ProcessGetFileSizeResult(const char* pszContent)
 /**
  * \brief Install /vsis3/ Amazon S3 file system handler (requires libcurl)
  *
- * A special file handler is installed that allows on-the-fly random reading of files
- * available in AWS S3 buckets, without prior download of the entire file.
- * It also allows sequential writing of files (no seeks or read operations are then
- * allowed).
+ * A special file handler is installed that allows on-the-fly random reading of
+ * non-public  files available in AWS S3 buckets, without prior download of the
+ * entire file.
+ * It also allows sequential writing of files (no seeks or read operations are
+ * then allowed).
  *
  * Recognized filenames are of the form /vsis3/bucket/key where
  * bucket is the name of the S3 bucket and key the S3 object "key", i.e.
@@ -4280,43 +4919,100 @@ void VSIS3Handle::ProcessGetFileSizeResult(const char* pszContent)
  * it will progressively increase the chunk size up to 2 MB to improve download
  * performance.
  *
- * The AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID configuration options *must* be
- * set.
- * The AWS_SESSION_TOKEN configuration option must be set when temporary credentials
- * are used.
- * The AWS_REGION configuration option may be set to one of the supported
- * <a href="http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region">S3 regions</a>
- * and defaults to 'us-east-1'
- * The AWS_S3_ENDPOINT configuration option defaults to s3.amazonaws.com.
+ * The AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID configuration options *must*
+ * be set.  The AWS_SESSION_TOKEN configuration option must be set when
+ * temporary credentials are used.  The AWS_REGION configuration option may be
+ * set to one of the supported
+ * <a href="http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region">S3
+ * regions</a> and defaults to 'us-east-1' The AWS_S3_ENDPOINT configuration
+ * option defaults to s3.amazonaws.com. Starting with GDAL 2.2, the
+ * AWS_REQUEST_PAYER configuration option may be set to "requester" to
+ * facilitate use with
+ * <a href="http://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html">Requester
+ * Pays buckets</a>.
+ *
+ * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration
+ * options can be used to define a proxy server. The syntax to use is the one of
+ * Curl CURLOPT_PROXY, CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
  *
- * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration options can be
- * used to define a proxy server. The syntax to use is the one of Curl CURLOPT_PROXY,
- * CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
+ * Starting with GDAL 2.1.3, the CURL_CA_BUNDLE or SSL_CERT_FILE configuration
+ * options can be used to set the path to the Certification Authority (CA)
+ * bundle file (if not specified, curl will use a file in a system location).
  *
  * On reading, the file can be cached in RAM by setting the configuration option
- * VSI_CACHE to TRUE. The cache size defaults to 25 MB, but can be modified by setting
- * the configuration option VSI_CACHE_SIZE (in bytes).
+ * VSI_CACHE to TRUE. The cache size defaults to 25 MB, but can be modified by
+ * setting the configuration option VSI_CACHE_SIZE (in bytes).
  *
- * On writing, the file is uploaded using the S3 <a href="http://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html">multipart upload API</a>.
+ * On writing, the file is uploaded using the S3
+ * <a href="http://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html">multipart upload API</a>.
  * The size of chunks is set to 50 MB by default, allowing creating files up to
- * 500 GB (10000 parts of 50 MB each). If larger files are needed, then increase the
- * value of the VSIS3_CHUNK_SIZE config option to a larger value (expressed in MB).
- * In case the process is killed and the file not properly closed, the multipart upload
- * will remain open, causing Amazon to charge you for the parts storage. You'll have to
- * abort yourself with other means such "ghost" uploads
- * (e.g. with the <a href="http://s3tools.org/s3cmd">s3cmd</a> utility)
- * For files smaller than the chunk size, a simple PUT request is used instead
- * of the multipart upload API.
+ * 500 GB (10000 parts of 50 MB each). If larger files are needed, then increase
+ * the value of the VSIS3_CHUNK_SIZE config option to a larger value (expressed
+ * in MB).  In case the process is killed and the file not properly closed, the
+ * multipart upload will remain open, causing Amazon to charge you for the parts
+ * storage. You'll have to abort yourself with other means such "ghost" uploads
+ * (e.g. with the <a href="http://s3tools.org/s3cmd">s3cmd</a> utility) For
+ * files smaller than the chunk size, a simple PUT request is used instead of
+ * the multipart upload API.
  *
  * VSIStatL() will return the size in st_size member.
  *
  * @since GDAL 2.1
  */
-void VSIInstallS3FileHandler(void)
+void VSIInstallS3FileHandler( void )
 {
     VSIFileManager::InstallHandler( "/vsis3/", new VSIS3FSHandler );
 }
 
+/************************************************************************/
+/*                      VSIInstallGSFileHandler()                       */
+/************************************************************************/
 
+/**
+ * \brief Install /vsigs/ Google Cloud Storage file system handler
+ * (requires libcurl)
+ *
+ * A special file handler is installed that allows on-the-fly random reading of
+ * non-public files available in Google Cloud Storage buckets, without prior
+ * download of the entire file.
+ * Read-only support for now.
+ *
+ * Recognized filenames are of the form /vsigs/bucket/key where
+ * bucket is the name of the bucket and key the object "key", i.e.
+ * a filename potentially containing subdirectories.
+ *
+ * Partial downloads are done with a 16 KB granularity by default.
+ * If the driver detects sequential reading
+ * it will progressively increase the chunk size up to 2 MB to improve download
+ * performance.
+ *
+ * The GS_SECRET_ACCESS_KEY and GS_ACCESS_KEY_ID configuration options must be
+ * set to use the AWS S3 authentication compatibility method.
+ * 
+ * Alternatively, it is possible to set the GDAL_HTTP_HEADER_FILE configuration
+ * option to point to a filename of a text file with "key: value" headers.
+ * Typically, it must contain a "Authorization: Bearer XXXXXXXXX" line.
+ *
+ * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration
+ * options can be used to define a proxy server. The syntax to use is the one of
+ * Curl CURLOPT_PROXY, CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
+ *
+ * The CURL_CA_BUNDLE or SSL_CERT_FILE configuration
+ * options can be used to set the path to the Certification Authority (CA)
+ * bundle file (if not specified, curl will use a file in a system location).
+ *
+ * On reading, the file can be cached in RAM by setting the configuration option
+ * VSI_CACHE to TRUE. The cache size defaults to 25 MB, but can be modified by
+ * setting the configuration option VSI_CACHE_SIZE (in bytes).
+ *
+ * VSIStatL() will return the size in st_size member.
+ *
+ * @since GDAL 2.2
+ */
+
+void VSIInstallGSFileHandler( void )
+{
+    VSIFileManager::InstallHandler( "/vsigs/", new VSIGSFSHandler );
+}
 
 #endif /* HAVE_CURL */
diff --git a/port/cpl_vsil_curl_priv.h b/port/cpl_vsil_curl_priv.h
index 259dfac..ba06e78 100644
--- a/port/cpl_vsil_curl_priv.h
+++ b/port/cpl_vsil_curl_priv.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl_priv.h 31749 2015-11-25 02:32:55Z goatbar $
+ * $Id: cpl_vsil_curl_priv.h 36772 2016-12-10 06:29:22Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Private API for VSICurl
@@ -32,18 +32,22 @@
 
 #include "cpl_vsi_virtual.h"
 
-/* NOTE: this is private API for GDAL internal use. May change without notice. */
-/* Used by the MBTiles driver for now */
+/* NOTE: this is private API for GDAL internal use. */
+/* May change without notice. */
+/* Used by the MBTiles driver for now. */
 
-/* Return TRUE to go on downloading, FALSE to stop */
-typedef int (*VSICurlReadCbkFunc) (VSILFILE* fp, void *pabyBuffer, size_t nBufferSize, void* pfnUserData);
+/* Return TRUE to go on downloading, FALSE to stop. */
+typedef int (*VSICurlReadCbkFunc) (VSILFILE* fp, void *pabyBuffer,
+                                   size_t nBufferSize, void* pfnUserData);
 
-/* fp must be a VSICurl file handle, otherwise bad things will happen ! */
-/* bStopOnInterrruptUntilUninstall must be set to TRUE if all downloads */
-/* must be canceled after a first one has been stopped by the callback function. */
-/* In that case, downloads will restart after uninstalling the callback. */
-int VSICurlInstallReadCbk(VSILFILE* fp, VSICurlReadCbkFunc pfnReadCbk, void* pfnUserData,
-                          int bStopOnInterrruptUntilUninstall);
-int VSICurlUninstallReadCbk(VSILFILE* fp);
+/* fp must be a VSICurl file handle, otherwise bad things will happen. */
+/* bStopOnInterruptUntilUninstall must be set to TRUE if all downloads */
+/* must be canceled after a first one has been stopped by the callback */
+/* function.  In that case, downloads will restart after uninstalling the */
+/* callback. */
+int VSICurlInstallReadCbk( VSILFILE* fp, VSICurlReadCbkFunc pfnReadCbk,
+                           void* pfnUserData,
+                           int bStopOnInterruptUntilUninstall );
+int VSICurlUninstallReadCbk( VSILFILE* fp );
 
 #endif // CPL_VSIL_CURL_PRIV_H_INCLUDED
diff --git a/port/cpl_vsil_curl_streaming.cpp b/port/cpl_vsil_curl_streaming.cpp
index ff02056..3dc3e28 100644
--- a/port/cpl_vsil_curl_streaming.cpp
+++ b/port/cpl_vsil_curl_streaming.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil_curl_streaming.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for HTTP/FTP files in streaming mode
@@ -27,34 +26,50 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "cpl_vsi.h"
 #include "cpl_vsi_virtual.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
+
+#include <algorithm>
+#include <map>
+
+#include "cpl_aws.h"
+#include "cpl_google_cloud.h"
 #include "cpl_hash_set.h"
+#include "cpl_http.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
 #include "cpl_time.h"
-#include "cpl_aws.h"
 
-CPL_CVSID("$Id: cpl_vsil_curl_streaming.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_curl_streaming.cpp 37645 2017-03-08 00:15:33Z rouault $");
 
 #if !defined(HAVE_CURL) || defined(CPL_MULTIPROC_STUB)
 
 void VSIInstallCurlStreamingFileHandler(void)
 {
-    /* not supported */
+    // Not supported.
 }
 
 void VSIInstallS3StreamingFileHandler(void)
 {
-    /* not supported */
+    // Not supported.
+}
+
+void VSIInstallGSStreamingFileHandler(void)
+{
+    // Not supported.
 }
 
 #else
 
+//! @cond Doxygen_Suppress
+
 #include <curl/curl.h>
 
-void VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL);
-
-#include <map>
+struct curl_slist* VSICurlSetOptions( CURL* hCurlHandle, const char* pszURL,
+                        const char * const* papszOptions );
+struct curl_slist* VSICurlMergeHeaders( struct curl_slist* poDest,
+                                        struct curl_slist* poSrcToDestroy );
 
 #define ENABLE_DEBUG        0
 
@@ -62,7 +77,6 @@ void VSICurlSetOptions(CURL* hCurlHandle, const char* pszURL);
 
 #define BKGND_BUFFER_SIZE   (1024 * 1024)
 
-
 /************************************************************************/
 /*                               RingBuffer                             */
 /************************************************************************/
@@ -86,13 +100,12 @@ class RingBuffer
         void Read(void* pBuffer, size_t nSize);
 };
 
-RingBuffer::RingBuffer(size_t nCapacityIn)
-{
-    pabyBuffer = (GByte*)CPLMalloc(nCapacityIn);
-    nCapacity = nCapacityIn;
-    nOffset = 0;
-    nLength = 0;
-}
+RingBuffer::RingBuffer( size_t nCapacityIn ) :
+    pabyBuffer(static_cast<GByte*>(CPLMalloc(nCapacityIn))),
+    nCapacity(nCapacityIn),
+    nOffset(0),
+    nLength(0)
+{}
 
 RingBuffer::~RingBuffer()
 {
@@ -105,29 +118,29 @@ void RingBuffer::Reset()
     nLength = 0;
 }
 
-void RingBuffer::Write(void* pBuffer, size_t nSize)
+void RingBuffer::Write( void* pBuffer, size_t nSize )
 {
     CPLAssert(nLength + nSize <= nCapacity);
 
-    size_t nEndOffset = (nOffset + nLength) % nCapacity;
-    size_t nSz = MIN(nSize, nCapacity - nEndOffset);
+    const size_t nEndOffset = (nOffset + nLength) % nCapacity;
+    const size_t nSz = std::min(nSize, nCapacity - nEndOffset);
     memcpy(pabyBuffer + nEndOffset, pBuffer, nSz);
-    if (nSz < nSize)
-        memcpy(pabyBuffer, (GByte*)pBuffer + nSz, nSize - nSz);
+    if( nSz < nSize )
+        memcpy(pabyBuffer, static_cast<GByte *>(pBuffer) + nSz, nSize - nSz);
 
     nLength += nSize;
 }
 
-void RingBuffer::Read(void* pBuffer, size_t nSize)
+void RingBuffer::Read( void* pBuffer, size_t nSize )
 {
     CPLAssert(nSize <= nLength);
 
-    if (pBuffer)
+    if( pBuffer )
     {
-        size_t nSz = MIN(nSize, nCapacity - nOffset);
+        const size_t nSz = std::min(nSize, nCapacity - nOffset);
         memcpy(pBuffer, pabyBuffer + nOffset, nSz);
-        if (nSz < nSize)
-            memcpy((GByte*)pBuffer + nSz, pabyBuffer, nSize - nSz);
+        if( nSz < nSize )
+          memcpy(static_cast<GByte *>(pBuffer) + nSz, pabyBuffer, nSize - nSz);
     }
 
     nOffset = (nOffset + nSize) % nCapacity;
@@ -166,8 +179,6 @@ typedef struct
     int             bDownloadHeaderOnly;
 } WriteFuncStruct;
 
-} /* end of anoymous namespace */
-
 /************************************************************************/
 /*                       VSICurlStreamingFSHandler                      */
 /************************************************************************/
@@ -186,14 +197,13 @@ protected:
 
 public:
     VSICurlStreamingFSHandler();
-    ~VSICurlStreamingFSHandler();
-
-    using VSIFilesystemHandler::Open;
+    virtual ~VSICurlStreamingFSHandler();
 
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
+                                    bool bSetError ) override;
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
 
     void                AcquireMutex();
     void                ReleaseMutex();
@@ -209,9 +219,9 @@ class VSICurlStreamingHandle : public VSIVirtualHandle
 {
   protected:
     VSICurlStreamingFSHandler* m_poFS;
-
+    char**          m_papszHTTPOptions;
+    
   private:
-
     char*           m_pszURL;
 
 #ifdef notdef
@@ -260,45 +270,52 @@ class VSICurlStreamingHandle : public VSIVirtualHandle
                                    GByte          *pData );
 
   protected:
-    virtual struct curl_slist* GetCurlHeaders(const CPLString& ) { return NULL; }
+    virtual struct curl_slist* GetCurlHeaders(const CPLString& )
+        { return NULL; }
     virtual bool StopReceivingBytesOnError() { return true; }
-    bool CanRestartOnError(const char* pszErrorMsg) { return CanRestartOnError(pszErrorMsg, false); }
-    virtual bool CanRestartOnError(const char*, bool) { return false; }
+    virtual bool CanRestartOnError( const char* /*pszErrorMsg*/,
+                                    bool /*bSetError*/ ) { return false; }
     virtual bool InterpretRedirect() { return true; }
-    void SetURL(const char* pszURL);
+    void SetURL( const char* pszURL );
 
   public:
-
-    VSICurlStreamingHandle(VSICurlStreamingFSHandler* poFS, const char* pszURL);
-    ~VSICurlStreamingHandle();
-
-    virtual int          Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t       Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t       Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int          Eof();
-    virtual int          Flush();
-    virtual int          Close();
+    VSICurlStreamingHandle( VSICurlStreamingFSHandler* poFS,
+                            const char* pszURL );
+    virtual ~VSICurlStreamingHandle();
+
+    virtual int          Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t       Read( void *pBuffer, size_t nSize,
+                               size_t nMemb ) override;
+    virtual size_t       Write( const void *pBuffer, size_t nSize,
+                                size_t nMemb ) override;
+    virtual int          Eof() override;
+    virtual int          Flush() override;
+    virtual int          Close() override;
 
     void                 DownloadInThread();
-    size_t               ReceivedBytes(GByte *buffer, size_t count, size_t nmemb);
-    size_t               ReceivedBytesHeader(GByte *buffer, size_t count, size_t nmemb);
+    size_t               ReceivedBytes( GByte *buffer, size_t count,
+                                        size_t nmemb);
+    size_t               ReceivedBytesHeader( GByte *buffer, size_t count,
+                                              size_t nmemb );
 
-    int                  IsKnownFileSize() const { return bHasComputedFileSize; }
+    int                  IsKnownFileSize() const
+        { return bHasComputedFileSize; }
     vsi_l_offset         GetFileSize();
     int                  Exists();
     int                  IsDirectory() const { return bIsDirectory; }
 };
 
-
 /************************************************************************/
 /*                       VSICurlStreamingHandle()                       */
 /************************************************************************/
 
-VSICurlStreamingHandle::VSICurlStreamingHandle(VSICurlStreamingFSHandler* poFS, const char* pszURL)
+VSICurlStreamingHandle::VSICurlStreamingHandle( VSICurlStreamingFSHandler* poFS,
+                                                const char* pszURL )
 {
     m_poFS = poFS;
     m_pszURL = CPLStrdup(pszURL);
+    m_papszHTTPOptions = CPLHTTPGetOptionsFromEnv();
 
 #ifdef notdef
     nRecomputedChecksumOfFirst1024Bytes = 0;
@@ -350,8 +367,9 @@ VSICurlStreamingHandle::~VSICurlStreamingHandle()
     StopDownload();
 
     CPLFree(m_pszURL);
-    if (hCurlHandle != NULL)
+    if( hCurlHandle != NULL )
         curl_easy_cleanup(hCurlHandle);
+    CSLDestroy( m_papszHTTPOptions );
 
     CPLFree(pCachedData);
 
@@ -398,8 +416,10 @@ int VSICurlStreamingHandle::Seek( vsi_l_offset nOffset, int nWhence )
 {
     if( curOffset >= BKGND_BUFFER_SIZE )
     {
-        if (ENABLE_DEBUG)
-            CPLDebug("VSICURL", "Invalidating cache and file size due to Seek() beyond caching zone");
+        if( ENABLE_DEBUG )
+            CPLDebug("VSICURL",
+                     "Invalidating cache and file size due to Seek() "
+                     "beyond caching zone");
         CPLFree(pCachedData);
         pCachedData = NULL;
         nCachedSize = 0;
@@ -409,11 +429,11 @@ int VSICurlStreamingHandle::Seek( vsi_l_offset nOffset, int nWhence )
         ReleaseMutex();
     }
 
-    if (nWhence == SEEK_SET)
+    if( nWhence == SEEK_SET )
     {
         curOffset = nOffset;
     }
-    else if (nWhence == SEEK_CUR)
+    else if( nWhence == SEEK_CUR )
     {
         curOffset = curOffset + nOffset;
     }
@@ -426,10 +446,10 @@ int VSICurlStreamingHandle::Seek( vsi_l_offset nOffset, int nWhence )
 }
 
 /************************************************************************/
-/*                  VSICURLStreamingInitWriteFuncStruct()                */
+/*                  VSICURLStreamingInitWriteFuncStruct()               */
 /************************************************************************/
 
-static void VSICURLStreamingInitWriteFuncStruct(WriteFuncStruct   *psStruct)
+static void VSICURLStreamingInitWriteFuncStruct( WriteFuncStruct *psStruct )
 {
     psStruct->pBuffer = NULL;
     psStruct->nSize = 0;
@@ -443,31 +463,35 @@ static void VSICURLStreamingInitWriteFuncStruct(WriteFuncStruct   *psStruct)
 /*                 VSICurlStreamingHandleWriteFuncForHeader()           */
 /************************************************************************/
 
-static size_t VSICurlStreamingHandleWriteFuncForHeader(void *buffer, size_t count, size_t nmemb, void *req)
+static size_t
+VSICurlStreamingHandleWriteFuncForHeader( void *buffer, size_t count,
+                                          size_t nmemb, void *req )
 {
-    WriteFuncStruct* psStruct = (WriteFuncStruct*) req;
-    size_t nSize = count * nmemb;
+    WriteFuncStruct* psStruct = static_cast<WriteFuncStruct *>(req);
+    const size_t nSize = count * nmemb;
 
-    char* pNewBuffer = (char*) VSIRealloc(psStruct->pBuffer,
-                                          psStruct->nSize + nSize + 1);
-    if (pNewBuffer)
+    char* pNewBuffer = static_cast<char*>(
+        VSIRealloc(psStruct->pBuffer, psStruct->nSize + nSize + 1));
+    if( pNewBuffer )
     {
         psStruct->pBuffer = pNewBuffer;
         memcpy(psStruct->pBuffer + psStruct->nSize, buffer, nSize);
         psStruct->pBuffer[psStruct->nSize + nSize] = '\0';
-        if (psStruct->bIsHTTP && psStruct->bIsInHeader)
+        if( psStruct->bIsHTTP && psStruct->bIsInHeader )
         {
             char* pszLine = psStruct->pBuffer + psStruct->nSize;
-            if (STARTS_WITH_CI(pszLine, "HTTP/1.0 ") ||
-                STARTS_WITH_CI(pszLine, "HTTP/1.1 "))
+            if( STARTS_WITH_CI(pszLine, "HTTP/1.0 ") ||
+                STARTS_WITH_CI(pszLine, "HTTP/1.1 ") )
                 psStruct->nHTTPCode = atoi(pszLine + 9);
 
-            if (pszLine[0] == '\r' || pszLine[0] == '\n')
+            if( pszLine[0] == '\r' || pszLine[0] == '\n' )
             {
-                if (psStruct->bDownloadHeaderOnly)
+                if( psStruct->bDownloadHeaderOnly )
                 {
-                    /* If moved permanently/temporarily, go on. Otherwise stop now*/
-                    if (!(psStruct->nHTTPCode == 301 || psStruct->nHTTPCode == 302))
+                    // If moved permanently/temporarily, go on.
+                    // Otherwise stop now.
+                    if( !(psStruct->nHTTPCode == 301 ||
+                          psStruct->nHTTPCode == 302) )
                         return 0;
                 }
                 else
@@ -485,7 +509,6 @@ static size_t VSICurlStreamingHandleWriteFuncForHeader(void *buffer, size_t coun
     }
 }
 
-
 /************************************************************************/
 /*                           GetFileSize()                              */
 /************************************************************************/
@@ -496,18 +519,18 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
     WriteFuncStruct sWriteFuncHeaderData;
 
     AcquireMutex();
-    if (bHasComputedFileSize)
+    if( bHasComputedFileSize )
     {
-        vsi_l_offset nRet = fileSize;
+        const vsi_l_offset nRet = fileSize;
         ReleaseMutex();
         return nRet;
     }
     ReleaseMutex();
 
 #if LIBCURL_VERSION_NUM < 0x070B00
-    /* Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have been */
-    /* previously set, so we have to reinit the connection handle */
-    if (hCurlHandle)
+    // Curl 7.10.X doesn't manage to unset the CURLOPT_RANGE that would have
+    // been previously set, so we have to reinit the connection handle.
+    if( hCurlHandle )
     {
         curl_easy_cleanup(hCurlHandle);
         hCurlHandle = curl_easy_init();
@@ -516,18 +539,21 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
 
     CURL* hLocalHandle = curl_easy_init();
 
-    VSICurlSetOptions(hLocalHandle, m_pszURL);
+    struct curl_slist* headers = 
+        VSICurlSetOptions(hLocalHandle, m_pszURL, m_papszHTTPOptions);
 
     VSICURLStreamingInitWriteFuncStruct(&sWriteFuncHeaderData);
 
-    /* HACK for mbtiles driver: proper fix would be to auto-detect servers that don't accept HEAD */
-    /* http://a.tiles.mapbox.com/v3/ doesn't accept HEAD, so let's start a GET */
-    /* and interrupt is as soon as the header is found */
+    // HACK for mbtiles driver: Proper fix would be to auto-detect servers that
+    // don't accept HEAD http://a.tiles.mapbox.com/v3/ doesn't accept HEAD, so
+    // let's start a GET and interrupt is as soon as the header is found.
     CPLString osVerb;
-    if (strstr(m_pszURL, ".tiles.mapbox.com/") != NULL)
+    if( strstr(m_pszURL, ".tiles.mapbox.com/") != NULL )
     {
-        curl_easy_setopt(hLocalHandle, CURLOPT_HEADERDATA, &sWriteFuncHeaderData);
-        curl_easy_setopt(hLocalHandle, CURLOPT_HEADERFUNCTION, VSICurlStreamingHandleWriteFuncForHeader);
+        curl_easy_setopt(hLocalHandle, CURLOPT_HEADERDATA,
+                         &sWriteFuncHeaderData);
+        curl_easy_setopt(hLocalHandle, CURLOPT_HEADERFUNCTION,
+                         VSICurlStreamingHandleWriteFuncForHeader);
 
         sWriteFuncHeaderData.bIsHTTP = STARTS_WITH(m_pszURL, "http");
         sWriteFuncHeaderData.bDownloadHeaderOnly = TRUE;
@@ -541,24 +567,24 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
         osVerb = "HEAD";
     }
 
-    struct curl_slist* headers = GetCurlHeaders(osVerb);
+    headers = VSICurlMergeHeaders(headers, GetCurlHeaders(osVerb));
     if( headers != NULL )
         curl_easy_setopt(hLocalHandle, CURLOPT_HTTPHEADER, headers);
 
-    /* We need that otherwise OSGEO4W's libcurl issue a dummy range request */
-    /* when doing a HEAD when recycling connections */
+    // We need that otherwise OSGEO4W's libcurl issue a dummy range request
+    // when doing a HEAD when recycling connections.
     curl_easy_setopt(hLocalHandle, CURLOPT_RANGE, NULL);
 
-    /* Bug with older curl versions (<=7.16.4) and FTP. See http://curl.haxx.se/mail/lib-2007-08/0312.html */
+    // Bug with older curl versions (<=7.16.4) and FTP.
+    // See http://curl.haxx.se/mail/lib-2007-08/0312.html
     VSICURLStreamingInitWriteFuncStruct(&sWriteFuncData);
     curl_easy_setopt(hLocalHandle, CURLOPT_WRITEDATA, &sWriteFuncData);
-    curl_easy_setopt(hLocalHandle, CURLOPT_WRITEFUNCTION, VSICurlStreamingHandleWriteFuncForHeader);
+    curl_easy_setopt(hLocalHandle, CURLOPT_WRITEFUNCTION,
+                     VSICurlStreamingHandleWriteFuncForHeader);
 
-    char szCurlErrBuf[CURL_ERROR_SIZE+1];
-    szCurlErrBuf[0] = '\0';
+    char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
     curl_easy_setopt(hLocalHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
-    double dfSize = 0;
     curl_easy_perform(hLocalHandle);
     if( headers != NULL )
         curl_slist_free_all(headers);
@@ -568,30 +594,37 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
     eExists = EXIST_UNKNOWN;
     bHasComputedFileSize = TRUE;
 
-    if (STARTS_WITH(m_pszURL, "ftp"))
+    if( STARTS_WITH(m_pszURL, "ftp") )
     {
-        if (sWriteFuncData.pBuffer != NULL &&
-            STARTS_WITH(sWriteFuncData.pBuffer, "Content-Length: "))
+        if( sWriteFuncData.pBuffer != NULL &&
+            STARTS_WITH(sWriteFuncData.pBuffer, "Content-Length: ") )
         {
-            const char* pszBuffer = sWriteFuncData.pBuffer + strlen("Content-Length: ");
+            const char* pszBuffer =
+                sWriteFuncData.pBuffer + strlen("Content-Length: ");
             eExists = EXIST_YES;
-            fileSize = CPLScanUIntBig(pszBuffer, static_cast<int>(sWriteFuncData.nSize - strlen("Content-Length: ")));
-            if (ENABLE_DEBUG)
+            fileSize =
+                CPLScanUIntBig(pszBuffer,
+                               static_cast<int>(sWriteFuncData.nSize -
+                                                strlen("Content-Length: ")));
+            if( ENABLE_DEBUG )
                 CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB,
-                        m_pszURL, fileSize);
+                         m_pszURL, fileSize);
         }
     }
 
-    if (eExists != EXIST_YES)
+    double dfSize = 0;
+    if( eExists != EXIST_YES )
     {
-        CURLcode code = curl_easy_getinfo(hLocalHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &dfSize );
-        if (code == 0)
+        const CURLcode code =
+            curl_easy_getinfo(hLocalHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+                              &dfSize );
+        if( code == 0 )
         {
             eExists = EXIST_YES;
-            if (dfSize < 0)
+            if( dfSize < 0 )
                 fileSize = 0;
             else
-                fileSize = (GUIntBig)dfSize;
+                fileSize = static_cast<GUIntBig>(dfSize);
         }
         else
         {
@@ -603,28 +636,30 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
 
         long response_code = 0;
         curl_easy_getinfo(hLocalHandle, CURLINFO_HTTP_CODE, &response_code);
-        if (response_code != 200)
+        if( response_code != 200 )
         {
             eExists = EXIST_NO;
             fileSize = 0;
         }
 
-        /* Try to guess if this is a directory. Generally if this is a directory, */
-        /* curl will retry with an URL with slash added */
+        // Try to guess if this is a directory. Generally if this is a
+        // directory, curl will retry with an URL with slash added.
         char *pszEffectiveURL = NULL;
-        curl_easy_getinfo(hLocalHandle, CURLINFO_EFFECTIVE_URL, &pszEffectiveURL);
-        if (pszEffectiveURL != NULL &&
+        curl_easy_getinfo(hLocalHandle, CURLINFO_EFFECTIVE_URL,
+                          &pszEffectiveURL);
+        if( pszEffectiveURL != NULL &&
             strncmp(m_pszURL, pszEffectiveURL, strlen(m_pszURL)) == 0 &&
-            pszEffectiveURL[strlen(m_pszURL)] == '/')
+            pszEffectiveURL[strlen(m_pszURL)] == '/' )
         {
             eExists = EXIST_YES;
             fileSize = 0;
             bIsDirectory = TRUE;
         }
 
-        if (ENABLE_DEBUG)
-            CPLDebug("VSICURL", "GetFileSize(%s)=" CPL_FRMT_GUIB "  response_code=%d",
-                    m_pszURL, fileSize, (int)response_code);
+        if( ENABLE_DEBUG )
+            CPLDebug("VSICURL",
+                     "GetFileSize(%s)=" CPL_FRMT_GUIB " response_code=%d",
+                     m_pszURL, fileSize, static_cast<int>(response_code));
     }
 
     CPLFree(sWriteFuncData.pBuffer);
@@ -634,17 +669,18 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
     CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
     cachedFileProp->bHasComputedFileSize = TRUE;
 #ifdef notdef
-    cachedFileProp->nChecksumOfFirst1024Bytes = nRecomputedChecksumOfFirst1024Bytes;
+    cachedFileProp->nChecksumOfFirst1024Bytes =
+        nRecomputedChecksumOfFirst1024Bytes;
 #endif
     cachedFileProp->fileSize = fileSize;
     cachedFileProp->eExists = eExists;
     cachedFileProp->bIsDirectory = bIsDirectory;
     m_poFS->ReleaseMutex();
 
-    vsi_l_offset nRet = fileSize;
+    const vsi_l_offset nRet = fileSize;
     ReleaseMutex();
 
-    if (hCurlHandle == NULL)
+    if( hCurlHandle == NULL )
         hCurlHandle = hLocalHandle;
     else
         curl_easy_cleanup(hLocalHandle);
@@ -658,39 +694,42 @@ vsi_l_offset VSICurlStreamingHandle::GetFileSize()
 
 int VSICurlStreamingHandle::Exists()
 {
-    if (eExists == EXIST_UNKNOWN)
+    if( eExists == EXIST_UNKNOWN )
     {
-        /* Consider that only the files whose extension ends up with one that is */
-        /* listed in CPL_VSIL_CURL_ALLOWED_EXTENSIONS exist on the server */
-        /* This can speeds up dramatically open experience, in case the server */
-        /* cannot return a file list */
-        /* For example : */
-        /* gdalinfo --config CPL_VSIL_CURL_ALLOWED_EXTENSIONS ".tif" /vsicurl_streaming/http://igskmncngs506.cr.usgs.gov/gmted/Global_tiles_GMTED/075darcsec/bln/W030/30N030W_20101117_gmted_bln075.tif */
+        // Consider that only the files whose extension ends up with one that is
+        // listed in CPL_VSIL_CURL_ALLOWED_EXTENSIONS exist on the server.
+        // This can speeds up dramatically open experience, in case the server
+        // cannot return a file list.
+        // For example:
+        // gdalinfo --config CPL_VSIL_CURL_ALLOWED_EXTENSIONS ".tif" /vsicurl_streaming/http://igskmncngs506.cr.usgs.gov/gmted/Global_tiles_GMTED/075darcsec/bln/W030/30N030W_20101117_gmted_bln075.tif */
         const char* pszAllowedExtensions =
             CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", NULL);
-        if (pszAllowedExtensions)
+        if( pszAllowedExtensions )
         {
-            char** papszExtensions = CSLTokenizeString2( pszAllowedExtensions, ", ", 0 );
-            size_t nURLLen = strlen(m_pszURL);
+            char** papszExtensions =
+                CSLTokenizeString2( pszAllowedExtensions, ", ", 0 );
+            const size_t nURLLen = strlen(m_pszURL);
             bool bFound = false;
-            for(int i=0;papszExtensions[i] != NULL;i++)
+            for( int i = 0; papszExtensions[i] != NULL; i++ )
             {
-                size_t nExtensionLen = strlen(papszExtensions[i]);
-                if (nURLLen > nExtensionLen &&
-                    EQUAL(m_pszURL + nURLLen - nExtensionLen, papszExtensions[i]))
+                const size_t nExtensionLen = strlen(papszExtensions[i]);
+                if( nURLLen > nExtensionLen &&
+                    EQUAL(m_pszURL + nURLLen - nExtensionLen,
+                          papszExtensions[i]) )
                 {
                     bFound = true;
                     break;
                 }
             }
 
-            if (!bFound)
+            if( !bFound )
             {
                 eExists = EXIST_NO;
                 fileSize = 0;
 
                 m_poFS->AcquireMutex();
-                CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
+                CachedFileProp* cachedFileProp =
+                    m_poFS->GetCachedFileProp(m_pszURL);
                 cachedFileProp->bHasComputedFileSize = TRUE;
                 cachedFileProp->fileSize = fileSize;
                 cachedFileProp->eExists = eExists;
@@ -704,7 +743,7 @@ int VSICurlStreamingHandle::Exists()
             CSLDestroy(papszExtensions);
         }
 
-        char chFirstByte;
+        char chFirstByte = '\0';
         int bExists = (Read(&chFirstByte, 1, 1) == 1);
 
         AcquireMutex();
@@ -733,52 +772,54 @@ vsi_l_offset VSICurlStreamingHandle::Tell()
 /*                         ReceivedBytes()                              */
 /************************************************************************/
 
-size_t VSICurlStreamingHandle::ReceivedBytes(GByte *buffer, size_t count, size_t nmemb)
+size_t VSICurlStreamingHandle::ReceivedBytes( GByte *buffer, size_t count,
+                                              size_t nmemb )
 {
     size_t nSize = count * nmemb;
     nBodySize += nSize;
 
-    if (ENABLE_DEBUG)
-        CPLDebug("VSICURL", "Receiving %d bytes...", (int)nSize);
+    if( ENABLE_DEBUG )
+        CPLDebug("VSICURL", "Receiving %d bytes...", static_cast<int>(nSize));
 
-    if( bHasCandidateFileSize && bCanTrustCandidateFileSize && !bHasComputedFileSize )
+    if( bHasCandidateFileSize && bCanTrustCandidateFileSize &&
+        !bHasComputedFileSize )
     {
         m_poFS->AcquireMutex();
         CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
         cachedFileProp->fileSize = fileSize = nCandidateFileSize;
         cachedFileProp->bHasComputedFileSize = bHasComputedFileSize = TRUE;
-        if (ENABLE_DEBUG)
+        if( ENABLE_DEBUG )
             CPLDebug("VSICURL", "File size = " CPL_FRMT_GUIB, fileSize);
         m_poFS->ReleaseMutex();
     }
 
     AcquireMutex();
-    if (eExists == EXIST_UNKNOWN)
+    if( eExists == EXIST_UNKNOWN )
     {
         m_poFS->AcquireMutex();
         CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
         cachedFileProp->eExists = eExists = EXIST_YES;
         m_poFS->ReleaseMutex();
     }
-    else if (eExists == EXIST_NO && StopReceivingBytesOnError() )
+    else if( eExists == EXIST_NO && StopReceivingBytesOnError() )
     {
         ReleaseMutex();
         return 0;
     }
 
-    while(true)
+    while( true )
     {
-        size_t nFree = oRingBuffer.GetCapacity() - oRingBuffer.GetSize();
-        if (nSize <= nFree)
+        const size_t nFree = oRingBuffer.GetCapacity() - oRingBuffer.GetSize();
+        if( nSize <= nFree )
         {
             oRingBuffer.Write(buffer, nSize);
 
-            /* Signal to the consumer that we have added bytes to the buffer */
+            // Signal to the consumer that we have added bytes to the buffer.
             CPLCondSignal(hCondProducer);
 
-            if (bAskDownloadEnd)
+            if( bAskDownloadEnd )
             {
-                if (ENABLE_DEBUG)
+                if( ENABLE_DEBUG )
                     CPLDebug("VSICURL", "Download interruption asked");
 
                 ReleaseMutex();
@@ -792,20 +833,22 @@ size_t VSICurlStreamingHandle::ReceivedBytes(GByte *buffer, size_t count, size_t
             buffer += nFree;
             nSize -= nFree;
 
-            /* Signal to the consumer that we have added bytes to the buffer */
+            // Signal to the consumer that we have added bytes to the buffer.
             CPLCondSignal(hCondProducer);
 
-            if (ENABLE_DEBUG)
-                CPLDebug("VSICURL", "Waiting for reader to consume some bytes...");
+            if( ENABLE_DEBUG )
+                CPLDebug("VSICURL",
+                         "Waiting for reader to consume some bytes...");
 
-            while(oRingBuffer.GetSize() == oRingBuffer.GetCapacity() && !bAskDownloadEnd)
+            while( oRingBuffer.GetSize() == oRingBuffer.GetCapacity() &&
+                   !bAskDownloadEnd )
             {
                 CPLCondWait(hCondConsumer, hRingBufferMutex);
             }
 
-            if (bAskDownloadEnd)
+            if( bAskDownloadEnd )
             {
-                if (ENABLE_DEBUG)
+                if( ENABLE_DEBUG )
                     CPLDebug("VSICURL", "Download interruption asked");
 
                 ReleaseMutex();
@@ -823,88 +866,116 @@ size_t VSICurlStreamingHandle::ReceivedBytes(GByte *buffer, size_t count, size_t
 /*                 VSICurlStreamingHandleReceivedBytes()                */
 /************************************************************************/
 
-static size_t VSICurlStreamingHandleReceivedBytes(void *buffer, size_t count, size_t nmemb, void *req)
+static size_t VSICurlStreamingHandleReceivedBytes( void *buffer, size_t count,
+                                                   size_t nmemb, void *req )
 {
-    return ((VSICurlStreamingHandle*)req)->ReceivedBytes((GByte*)buffer, count, nmemb);
+    return
+        static_cast<VSICurlStreamingHandle *>(req)->
+            ReceivedBytes(static_cast<GByte *>(buffer), count, nmemb);
 }
 
-
 /************************************************************************/
 /*              VSICurlStreamingHandleReceivedBytesHeader()             */
 /************************************************************************/
 
 #define HEADER_SIZE 32768
 
-size_t VSICurlStreamingHandle::ReceivedBytesHeader(GByte *buffer, size_t count, size_t nmemb)
+size_t VSICurlStreamingHandle::ReceivedBytesHeader( GByte *buffer, size_t count,
+                                                    size_t nmemb )
 {
-    size_t nSize = count * nmemb;
-    if (ENABLE_DEBUG)
-        CPLDebug("VSICURL", "Receiving %d bytes for header...", (int)nSize);
-
-    /* Reset buffer if we have followed link after a redirect */
-    if (nSize >=9 && InterpretRedirect() && (nHTTPCode == 301 || nHTTPCode == 302) &&
-        (STARTS_WITH_CI((const char*)buffer, "HTTP/1.0 ") ||
-         STARTS_WITH_CI((const char*)buffer, "HTTP/1.1 ")))
+    const size_t nSize = count * nmemb;
+    if( ENABLE_DEBUG )
+        CPLDebug("VSICURL", "Receiving %d bytes for header...",
+                 static_cast<int>(nSize));
+
+    // Reset buffer if we have followed link after a redirect.
+    if( nSize >= 9 && InterpretRedirect() &&
+        (nHTTPCode == 301 || nHTTPCode == 302) &&
+        (STARTS_WITH_CI(reinterpret_cast<char *>(buffer), "HTTP/1.0 ") ||
+         STARTS_WITH_CI(reinterpret_cast<char *>(buffer), "HTTP/1.1 ")) )
     {
         nHeaderSize = 0;
         nHTTPCode = 0;
     }
 
-    if (nHeaderSize < HEADER_SIZE)
+    if( nHeaderSize < HEADER_SIZE )
     {
-        size_t nSz = MIN(nSize, HEADER_SIZE - nHeaderSize);
+        const size_t nSz = std::min(nSize, HEADER_SIZE - nHeaderSize);
         memcpy(pabyHeaderData + nHeaderSize, buffer, nSz);
         pabyHeaderData[nHeaderSize + nSz] = '\0';
         nHeaderSize += nSz;
 
-        //CPLDebug("VSICURL", "Header : %s", pabyHeaderData);
+#if DEBUG_VERBOSE
+        CPLDebug("VSICURL", "Header : %s", pabyHeaderData);
+#endif
 
         AcquireMutex();
 
-        if (eExists == EXIST_UNKNOWN && nHTTPCode == 0 &&
-            strchr((const char*)pabyHeaderData, '\n') != NULL &&
-            (STARTS_WITH_CI((const char*)pabyHeaderData, "HTTP/1.0 ") ||
-                STARTS_WITH_CI((const char*)pabyHeaderData, "HTTP/1.1 ")))
+        if( eExists == EXIST_UNKNOWN && nHTTPCode == 0 &&
+            strchr(reinterpret_cast<char *>(pabyHeaderData), '\n') != NULL &&
+            (STARTS_WITH_CI(reinterpret_cast<char *>(pabyHeaderData),
+                            "HTTP/1.0 ") ||
+             STARTS_WITH_CI(reinterpret_cast<char *>(pabyHeaderData),
+                            "HTTP/1.1 ")) )
         {
-            nHTTPCode = atoi((const char*)pabyHeaderData + 9);
-            if (ENABLE_DEBUG)
+            nHTTPCode = atoi(reinterpret_cast<char *>(pabyHeaderData) + 9);
+            if( ENABLE_DEBUG )
                 CPLDebug("VSICURL", "HTTP code = %d", nHTTPCode);
 
-            /* If moved permanently/temporarily, go on */
-            if( !(InterpretRedirect() && (nHTTPCode == 301 || nHTTPCode == 302)) )
+            // If moved permanently/temporarily, go on.
+            if( !(InterpretRedirect() &&
+                  (nHTTPCode == 301 || nHTTPCode == 302)) )
             {
                 m_poFS->AcquireMutex();
-                CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
-                cachedFileProp->eExists = eExists = (nHTTPCode == 200) ? EXIST_YES : EXIST_NO;
+                CachedFileProp* cachedFileProp =
+                    m_poFS->GetCachedFileProp(m_pszURL);
+                eExists = nHTTPCode == 200 ? EXIST_YES : EXIST_NO;
+                cachedFileProp->eExists = eExists;
                 m_poFS->ReleaseMutex();
             }
         }
 
-        if ( !(InterpretRedirect() && (nHTTPCode == 301 || nHTTPCode == 302)) && !bHasComputedFileSize)
+        if( !(InterpretRedirect() && (nHTTPCode == 301 || nHTTPCode == 302)) &&
+            !bHasComputedFileSize )
         {
-            /* Caution: when gzip compression is enabled, the content-length is the compressed */
-            /* size, which we are not interested in, so we must not take it into account. */
-
-            const char* pszContentLength = strstr((const char*)pabyHeaderData, "Content-Length: ");
-            const char* pszEndOfLine = pszContentLength ? strchr(pszContentLength, '\n') : NULL;
+            // Caution: When gzip compression is enabled, the content-length is
+            // the compressed size, which we are not interested in, so we must
+            // not take it into account.
+
+            const char* pszContentLength =
+                strstr(reinterpret_cast<char *>(pabyHeaderData),
+                       "Content-Length: ");
+            const char* pszEndOfLine =
+                pszContentLength ? strchr(pszContentLength, '\n') : NULL;
             if( bCanTrustCandidateFileSize && pszEndOfLine != NULL )
             {
-                const char* pszVal = pszContentLength + strlen("Content-Length: ");
+                const char* pszVal =
+                    pszContentLength + strlen("Content-Length: ");
                 bHasCandidateFileSize = TRUE;
-                nCandidateFileSize = CPLScanUIntBig(pszVal, static_cast<int>(pszEndOfLine - pszVal));
-                if (ENABLE_DEBUG)
-                    CPLDebug("VSICURL", "Has found candidate file size = " CPL_FRMT_GUIB, nCandidateFileSize);
+                nCandidateFileSize =
+                    CPLScanUIntBig(pszVal,
+                                   static_cast<int>(pszEndOfLine - pszVal));
+                if( ENABLE_DEBUG )
+                    CPLDebug("VSICURL",
+                             "Has found candidate file size = " CPL_FRMT_GUIB,
+                             nCandidateFileSize);
             }
 
-            const char* pszContentEncoding = strstr((const char*)pabyHeaderData, "Content-Encoding: ");
-            pszEndOfLine = pszContentEncoding ? strchr(pszContentEncoding, '\n') : NULL;
+            const char* pszContentEncoding =
+                strstr(reinterpret_cast<char *>(pabyHeaderData),
+                       "Content-Encoding: ");
+            pszEndOfLine =
+                pszContentEncoding ? strchr(pszContentEncoding, '\n') : NULL;
             if( bHasCandidateFileSize && pszEndOfLine != NULL )
             {
-                const char* pszVal = pszContentEncoding + strlen("Content-Encoding: ");
+                const char* pszVal =
+                    pszContentEncoding + strlen("Content-Encoding: ");
                 if( STARTS_WITH(pszVal, "gzip") )
                 {
-                    if (ENABLE_DEBUG)
-                        CPLDebug("VSICURL", "GZip compression enabled --> cannot trust candidate file size");
+                    if( ENABLE_DEBUG )
+                        CPLDebug("VSICURL",
+                                 "GZip compression enabled --> "
+                                 "cannot trust candidate file size");
                     bCanTrustCandidateFileSize = FALSE;
                 }
             }
@@ -920,9 +991,13 @@ size_t VSICurlStreamingHandle::ReceivedBytesHeader(GByte *buffer, size_t count,
 /*                 VSICurlStreamingHandleReceivedBytesHeader()          */
 /************************************************************************/
 
-static size_t VSICurlStreamingHandleReceivedBytesHeader(void *buffer, size_t count, size_t nmemb, void *req)
+static size_t
+VSICurlStreamingHandleReceivedBytesHeader( void *buffer, size_t count,
+                                           size_t nmemb, void *req )
 {
-    return ((VSICurlStreamingHandle*)req)->ReceivedBytesHeader((GByte*)buffer, count, nmemb);
+    return
+        static_cast<VSICurlStreamingHandle *>(req)->
+            ReceivedBytesHeader(static_cast<GByte *>(buffer), count, nmemb);
 }
 
 /************************************************************************/
@@ -931,36 +1006,40 @@ static size_t VSICurlStreamingHandleReceivedBytesHeader(void *buffer, size_t cou
 
 void VSICurlStreamingHandle::DownloadInThread()
 {
-    VSICurlSetOptions(hCurlHandle, m_pszURL);
-    struct curl_slist* headers = GetCurlHeaders("GET");
+    struct curl_slist* headers = 
+        VSICurlSetOptions(hCurlHandle, m_pszURL, m_papszHTTPOptions);
+    headers = VSICurlMergeHeaders(headers, GetCurlHeaders("GET"));
     if( headers != NULL )
         curl_easy_setopt(hCurlHandle, CURLOPT_HTTPHEADER, headers);
 
     static bool bHasCheckVersion = false;
     static bool bSupportGZip = false;
-    if (!bHasCheckVersion)
+    if( !bHasCheckVersion )
     {
         bSupportGZip = strstr(curl_version(), "zlib/") != NULL;
         bHasCheckVersion = true;
     }
-    if (bSupportGZip && CSLTestBoolean(CPLGetConfigOption("CPL_CURL_GZIP", "YES")))
+    if( bSupportGZip &&
+        CPLTestBool(CPLGetConfigOption("CPL_CURL_GZIP", "YES")) )
     {
         curl_easy_setopt(hCurlHandle, CURLOPT_ENCODING, "gzip");
     }
 
-    if (pabyHeaderData == NULL)
-        pabyHeaderData = (GByte*) CPLMalloc(HEADER_SIZE + 1);
+    if( pabyHeaderData == NULL )
+        pabyHeaderData = static_cast<GByte *>(CPLMalloc(HEADER_SIZE + 1));
     nHeaderSize = 0;
     nBodySize = 0;
     nHTTPCode = 0;
 
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERDATA, this);
-    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, VSICurlStreamingHandleReceivedBytesHeader);
+    curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION,
+                     VSICurlStreamingHandleReceivedBytesHeader);
 
     curl_easy_setopt(hCurlHandle, CURLOPT_WRITEDATA, this);
-    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION, VSICurlStreamingHandleReceivedBytes);
+    curl_easy_setopt(hCurlHandle, CURLOPT_WRITEFUNCTION,
+                     VSICurlStreamingHandleReceivedBytes);
 
-    char szCurlErrBuf[CURL_ERROR_SIZE+1];
+    char szCurlErrBuf[CURL_ERROR_SIZE+1] = {};
     szCurlErrBuf[0] = '\0';
     curl_easy_setopt(hCurlHandle, CURLOPT_ERRORBUFFER, szCurlErrBuf );
 
@@ -974,13 +1053,13 @@ void VSICurlStreamingHandle::DownloadInThread()
     curl_easy_setopt(hCurlHandle, CURLOPT_HEADERFUNCTION, NULL);
 
     AcquireMutex();
-    if (!bAskDownloadEnd && eRet == 0 && !bHasComputedFileSize)
+    if( !bAskDownloadEnd && eRet == 0 && !bHasComputedFileSize )
     {
         m_poFS->AcquireMutex();
         CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
         cachedFileProp->fileSize = fileSize = nBodySize;
         cachedFileProp->bHasComputedFileSize = bHasComputedFileSize = TRUE;
-        if (ENABLE_DEBUG)
+        if( ENABLE_DEBUG )
             CPLDebug("VSICURL", "File size = " CPL_FRMT_GUIB, fileSize);
         m_poFS->ReleaseMutex();
     }
@@ -988,14 +1067,14 @@ void VSICurlStreamingHandle::DownloadInThread()
     bDownloadInProgress = FALSE;
     bDownloadStopped = TRUE;
 
-    /* Signal to the consumer that the download has ended */
+    // Signal to the consumer that the download has ended.
     CPLCondSignal(hCondProducer);
     ReleaseMutex();
 }
 
-static void VSICurlDownloadInThread(void* pArg)
+static void VSICurlDownloadInThread( void* pArg )
 {
-    ((VSICurlStreamingHandle*)pArg)->DownloadInThread();
+    static_cast<VSICurlStreamingHandle *>(pArg)->DownloadInThread();
 }
 
 /************************************************************************/
@@ -1004,15 +1083,12 @@ static void VSICurlDownloadInThread(void* pArg)
 
 void VSICurlStreamingHandle::StartDownload()
 {
-    if (bDownloadInProgress || bDownloadStopped)
+    if( bDownloadInProgress || bDownloadStopped )
         return;
 
-    //if (ENABLE_DEBUG)
-    {
-        CPLDebug("VSICURL", "Start download for %s", m_pszURL);
-    }
+    CPLDebug("VSICURL", "Start download for %s", m_pszURL);
 
-    if (hCurlHandle == NULL)
+    if( hCurlHandle == NULL )
         hCurlHandle = curl_easy_init();
     oRingBuffer.Reset();
     bDownloadInProgress = TRUE;
@@ -1026,20 +1102,17 @@ void VSICurlStreamingHandle::StartDownload()
 
 void VSICurlStreamingHandle::StopDownload()
 {
-    if (hThread)
+    if( hThread )
     {
-        //if (ENABLE_DEBUG)
-        {
-            CPLDebug("VSICURL", "Stop download for %s", m_pszURL);
-        }
+        CPLDebug("VSICURL", "Stop download for %s", m_pszURL);
 
         AcquireMutex();
-        /* Signal to the producer that we ask for download interruption */
+        // Signal to the producer that we ask for download interruption.
         bAskDownloadEnd = TRUE;
         CPLCondSignal(hCondConsumer);
 
-        /* Wait for the producer to have finished */
-        while(bDownloadInProgress)
+        // Wait for the producer to have finished.
+        while( bDownloadInProgress )
             CPLCondWait(hCondProducer, hRingBufferMutex);
 
         bAskDownloadEnd = FALSE;
@@ -1063,21 +1136,22 @@ void VSICurlStreamingHandle::StopDownload()
 
 void VSICurlStreamingHandle::PutRingBufferInCache()
 {
-    if (nRingBufferFileOffset >= BKGND_BUFFER_SIZE)
+    if( nRingBufferFileOffset >= BKGND_BUFFER_SIZE )
         return;
 
     AcquireMutex();
 
-    /* Cache any remaining bytes available in the ring buffer */
+    // Cache any remaining bytes available in the ring buffer.
     size_t nBufSize = oRingBuffer.GetSize();
-    if ( nBufSize > 0 )
+    if( nBufSize > 0 )
     {
-        if (nRingBufferFileOffset + nBufSize > BKGND_BUFFER_SIZE)
-            nBufSize = (size_t) (BKGND_BUFFER_SIZE - nRingBufferFileOffset);
-        GByte* pabyTmp = (GByte*) CPLMalloc(nBufSize);
+        if( nRingBufferFileOffset + nBufSize > BKGND_BUFFER_SIZE )
+            nBufSize =
+                static_cast<size_t>(BKGND_BUFFER_SIZE - nRingBufferFileOffset);
+        GByte* pabyTmp = static_cast<GByte *>(CPLMalloc(nBufSize));
         oRingBuffer.Read(pabyTmp, nBufSize);
 
-        /* Signal to the producer that we have ingested some bytes */
+        // Signal to the producer that we have ingested some bytes.
         CPLCondSignal(hCondConsumer);
 
         AddRegion(nRingBufferFileOffset, nBufSize, pabyTmp);
@@ -1092,13 +1166,14 @@ void VSICurlStreamingHandle::PutRingBufferInCache()
 /*                                Read()                                */
 /************************************************************************/
 
-size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, size_t const nMemb )
+size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize,
+                                     size_t const nMemb )
 {
-    GByte* pabyBuffer = (GByte*)pBuffer;
+    GByte* pabyBuffer = static_cast<GByte *>(pBuffer);
     const size_t nBufferRequestSize = nSize * nMemb;
     const vsi_l_offset curOffsetOri = curOffset;
     const vsi_l_offset nRingBufferFileOffsetOri = nRingBufferFileOffset;
-    if (nBufferRequestSize == 0)
+    if( nBufferRequestSize == 0 )
         return 0;
     size_t nRemaining = nBufferRequestSize;
 
@@ -1107,18 +1182,18 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
     const vsi_l_offset fileSizeLocal = fileSize;
     ReleaseMutex();
 
-    if (bHasComputedFileSizeLocal && curOffset >= fileSizeLocal)
+    if( bHasComputedFileSizeLocal && curOffset >= fileSizeLocal )
     {
         CPLDebug("VSICURL", "Read attempt beyond end of file");
         bEOF = TRUE;
     }
-    if (bEOF)
+    if( bEOF )
         return 0;
 
-    if (curOffset < nRingBufferFileOffset)
+    if( curOffset < nRingBufferFileOffset )
         PutRingBufferInCache();
 
-    if (ENABLE_DEBUG)
+    if( ENABLE_DEBUG )
         CPLDebug("VSICURL", "Read [" CPL_FRMT_GUIB ", " CPL_FRMT_GUIB "[ in %s",
                  curOffset, curOffset + nBufferRequestSize, m_pszURL);
 
@@ -1126,9 +1201,9 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
     if( pCachedData != NULL && nCachedSize >= 1024 &&
         nRecomputedChecksumOfFirst1024Bytes == 0 )
     {
-        for(size_t i = 0; i < 1024 / sizeof(int); i ++)
+        for( size_t i = 0; i < 1024 / sizeof(int); i++ )
         {
-          int nVal = 0;
+            int nVal = 0;
             memcpy(&nVal, pCachedData + i * sizeof(int), sizeof(int));
             nRecomputedChecksumOfFirst1024Bytes += nVal;
         }
@@ -1139,11 +1214,15 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
             CachedFileProp* cachedFileProp = poFS->GetCachedFileProp(pszURL);
             if( cachedFileProp->nChecksumOfFirst1024Bytes == 0 )
             {
-                cachedFileProp->nChecksumOfFirst1024Bytes = nRecomputedChecksumOfFirst1024Bytes;
+                cachedFileProp->nChecksumOfFirst1024Bytes =
+                    nRecomputedChecksumOfFirst1024Bytes;
             }
-            else if( nRecomputedChecksumOfFirst1024Bytes != cachedFileProp->nChecksumOfFirst1024Bytes )
+            else if( nRecomputedChecksumOfFirst1024Bytes !=
+                     cachedFileProp->nChecksumOfFirst1024Bytes )
             {
-                CPLDebug("VSICURL", "Invalidating previously cached file size. First bytes of file have changed!");
+                CPLDebug("VSICURL",
+                         "Invalidating previously cached file size. "
+                         "First bytes of file have changed!");
                 AcquireMutex();
                 bHasComputedFileSize = FALSE;
                 cachedFileProp->bHasComputedFileSize = FALSE;
@@ -1155,29 +1234,32 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
     }
 #endif
 
-    /* Can we use the cache ? */
+    // Can we use the cache?
     if( pCachedData != NULL && curOffset < nCachedSize )
     {
-        size_t nSz = MIN(nRemaining, (size_t)(nCachedSize - curOffset));
-        if (ENABLE_DEBUG)
+        const size_t nSz =
+            std::min(nRemaining, static_cast<size_t>(nCachedSize - curOffset));
+        if( ENABLE_DEBUG )
             CPLDebug("VSICURL", "Using cache for [%d, %d[ in %s",
-                     (int)curOffset, (int)(curOffset + nSz), m_pszURL);
+                     static_cast<int>(curOffset),
+                     static_cast<int>(curOffset + nSz), m_pszURL);
         memcpy(pabyBuffer, pCachedData + curOffset, nSz);
         pabyBuffer += nSz;
         curOffset += nSz;
         nRemaining -= nSz;
     }
 
-    /* Is the request partially covered by the cache and going beyond file size ? */
-    if ( pCachedData != NULL && bHasComputedFileSizeLocal &&
-         curOffset <= nCachedSize &&
-         curOffset + nRemaining > fileSizeLocal &&
-         fileSize == nCachedSize )
+    // Is the request partially covered by the cache and going beyond file size?
+    if( pCachedData != NULL && bHasComputedFileSizeLocal &&
+        curOffset <= nCachedSize &&
+        curOffset + nRemaining > fileSizeLocal &&
+        fileSize == nCachedSize )
     {
-        size_t nSz = (size_t) (nCachedSize - curOffset);
-        if (ENABLE_DEBUG && nSz != 0)
+        size_t nSz = static_cast<size_t>(nCachedSize - curOffset);
+        if( ENABLE_DEBUG && nSz != 0 )
             CPLDebug("VSICURL", "Using cache for [%d, %d[ in %s",
-                    (int)curOffset, (int)(curOffset + nSz), m_pszURL);
+                     static_cast<int>(curOffset),
+                     static_cast<int>(curOffset + nSz), m_pszURL);
         memcpy(pabyBuffer, pCachedData + curOffset, nSz);
         pabyBuffer += nSz;
         curOffset += nSz;
@@ -1185,17 +1267,17 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
         bEOF = TRUE;
     }
 
-    /* Has a Seek() being done since the last Read() ? */
-    if (!bEOF && nRemaining > 0 && curOffset != nRingBufferFileOffset)
+    // Has a Seek() being done since the last Read()?
+    if( !bEOF && nRemaining > 0 && curOffset != nRingBufferFileOffset )
     {
-        /* Backward seek : we need to restart the download from the start */
-        if (curOffset < nRingBufferFileOffset)
+        // Backward seek: Need to restart the download from the beginning.
+        if( curOffset < nRingBufferFileOffset )
             StopDownload();
 
         StartDownload();
 
-#define SKIP_BUFFER_SIZE    32768
-        GByte* pabyTmp = (GByte*)CPLMalloc(SKIP_BUFFER_SIZE);
+        const vsi_l_offset SKIP_BUFFER_SIZE = 32768;
+        GByte* pabyTmp = static_cast<GByte *>(CPLMalloc(SKIP_BUFFER_SIZE));
 
         CPLAssert(curOffset >= nRingBufferFileOffset);
         vsi_l_offset nBytesToSkip = curOffset - nRingBufferFileOffset;
@@ -1204,67 +1286,69 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
             vsi_l_offset nBytesToRead = nBytesToSkip;
 
             AcquireMutex();
-            if (nBytesToRead > oRingBuffer.GetSize())
+            if( nBytesToRead > oRingBuffer.GetSize() )
                 nBytesToRead = oRingBuffer.GetSize();
-            if (nBytesToRead > SKIP_BUFFER_SIZE)
+            if( nBytesToRead > SKIP_BUFFER_SIZE )
                 nBytesToRead = SKIP_BUFFER_SIZE;
-            oRingBuffer.Read(pabyTmp, (size_t)nBytesToRead);
+            oRingBuffer.Read(pabyTmp, static_cast<size_t>(nBytesToRead));
 
-            /* Signal to the producer that we have ingested some bytes */
+            // Signal to the producer that we have ingested some bytes.
             CPLCondSignal(hCondConsumer);
             ReleaseMutex();
 
-            if (nBytesToRead)
-                AddRegion(nRingBufferFileOffset, (size_t)nBytesToRead, pabyTmp);
+            if( nBytesToRead )
+                AddRegion(nRingBufferFileOffset,
+                          static_cast<size_t>(nBytesToRead), pabyTmp);
 
             nBytesToSkip -= nBytesToRead;
             nRingBufferFileOffset += nBytesToRead;
 
-            if (nBytesToRead == 0 && nBytesToSkip != 0)
+            if( nBytesToRead == 0 && nBytesToSkip != 0 )
             {
-                if (ENABLE_DEBUG)
-                    CPLDebug("VSICURL", "Waiting for writer to produce some bytes...");
+                if( ENABLE_DEBUG )
+                    CPLDebug("VSICURL",
+                             "Waiting for writer to produce some bytes...");
 
                 AcquireMutex();
                 while(oRingBuffer.GetSize() == 0 && bDownloadInProgress)
                     CPLCondWait(hCondProducer, hRingBufferMutex);
-                int bBufferEmpty = (oRingBuffer.GetSize() == 0);
+                const int bBufferEmpty = (oRingBuffer.GetSize() == 0);
                 ReleaseMutex();
 
-                if (bBufferEmpty && !bDownloadInProgress)
+                if( bBufferEmpty && !bDownloadInProgress )
                     break;
             }
         }
 
         CPLFree(pabyTmp);
 
-        if (nBytesToSkip != 0)
+        if( nBytesToSkip != 0 )
         {
             bEOF = TRUE;
             return 0;
         }
     }
 
-    if (!bEOF && nRemaining > 0)
+    if( !bEOF && nRemaining > 0 )
     {
         StartDownload();
         CPLAssert(curOffset == nRingBufferFileOffset);
     }
 
-    /* Fill the destination buffer from the ring buffer */
+    // Fill the destination buffer from the ring buffer.
     while(!bEOF && nRemaining > 0)
     {
         AcquireMutex();
         size_t nToRead = oRingBuffer.GetSize();
-        if (nToRead > nRemaining)
+        if( nToRead > nRemaining )
             nToRead = nRemaining;
         oRingBuffer.Read(pabyBuffer, nToRead);
 
-        /* Signal to the producer that we have ingested some bytes */
+        // Signal to the producer that we have ingested some bytes.
         CPLCondSignal(hCondConsumer);
         ReleaseMutex();
 
-        if (nToRead)
+        if( nToRead )
             AddRegion(curOffset, nToRead, pabyBuffer);
 
         nRemaining -= nToRead;
@@ -1272,45 +1356,49 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
         curOffset += nToRead;
         nRingBufferFileOffset += nToRead;
 
-        if (nToRead == 0 && nRemaining != 0)
+        if( nToRead == 0 && nRemaining != 0 )
         {
-            if (ENABLE_DEBUG)
-                CPLDebug("VSICURL", "Waiting for writer to produce some bytes...");
+            if( ENABLE_DEBUG )
+                CPLDebug("VSICURL",
+                         "Waiting for writer to produce some bytes...");
 
             AcquireMutex();
             while(oRingBuffer.GetSize() == 0 && bDownloadInProgress)
                 CPLCondWait(hCondProducer, hRingBufferMutex);
-            int bBufferEmpty = (oRingBuffer.GetSize() == 0);
+            const bool bBufferEmpty = oRingBuffer.GetSize() == 0;
             ReleaseMutex();
 
-            if (bBufferEmpty && !bDownloadInProgress)
+            if( bBufferEmpty && !bDownloadInProgress )
                 break;
         }
     }
 
-    if (ENABLE_DEBUG)
+    if( ENABLE_DEBUG )
         CPLDebug("VSICURL", "Read(%d) = %d",
-                (int)nBufferRequestSize, (int)(nBufferRequestSize - nRemaining));
+                 static_cast<int>(nBufferRequestSize),
+                 static_cast<int>(nBufferRequestSize - nRemaining));
     size_t nRet = (nBufferRequestSize - nRemaining) / nSize;
-    if (nRet < nMemb)
+    if( nRet < nMemb )
         bEOF = TRUE;
 
-    /* Give a chance to specialized filesystem to deal with errors to redirect */
-    /* elsewhere */
+    // Give a chance to specialized filesystem to deal with errors to redirect
+    // elsewhere.
     if( curOffsetOri == 0 && nRingBufferFileOffsetOri == 0 &&
         !StopReceivingBytesOnError() &&
         eExists == EXIST_NO && nRemaining < nBufferRequestSize )
     {
         const size_t nErrorBufferMaxSize = 4096;
-        GByte* pabyErrorBuffer = (GByte*)CPLMalloc(nErrorBufferMaxSize + 1);
+        GByte* pabyErrorBuffer =
+            static_cast<GByte *>(CPLMalloc(nErrorBufferMaxSize + 1));
         size_t nRead = nBufferRequestSize - nRemaining;
-        size_t nErrorBufferSize = MIN(nErrorBufferMaxSize, nRead);
+        size_t nErrorBufferSize = std::min(nErrorBufferMaxSize, nRead);
         memcpy( pabyErrorBuffer, pBuffer, nErrorBufferSize );
         if( nRead < nErrorBufferMaxSize )
-            nErrorBufferSize += Read( pabyErrorBuffer + nRead, 1, nErrorBufferMaxSize - nRead );
+            nErrorBufferSize += Read(pabyErrorBuffer + nRead, 1,
+                                     nErrorBufferMaxSize - nRead);
         pabyErrorBuffer[nErrorBufferSize] = 0;
         StopDownload();
-        if( CanRestartOnError((const char*)pabyErrorBuffer, true) )
+        if( CanRestartOnError(reinterpret_cast<char *>(pabyErrorBuffer), true) )
         {
             curOffset = 0;
             nRingBufferFileOffset = 0;
@@ -1322,7 +1410,8 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
             ReleaseMutex();
             nCachedSize = 0;
             m_poFS->AcquireMutex();
-            CachedFileProp* cachedFileProp = m_poFS->GetCachedFileProp(m_pszURL);
+            CachedFileProp* cachedFileProp =
+                m_poFS->GetCachedFileProp(m_pszURL);
             cachedFileProp->bHasComputedFileSize = FALSE;
             cachedFileProp->fileSize = 0;
             cachedFileProp->eExists = EXIST_UNKNOWN;
@@ -1331,7 +1420,8 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
         }
         else
         {
-            CPLDebug("VSICURL", "Error buffer: %s", (const char*)pabyErrorBuffer);
+            CPLDebug("VSICURL", "Error buffer: %s",
+                     reinterpret_cast<char *>(pabyErrorBuffer));
             nRet = 0;
         }
 
@@ -1345,34 +1435,37 @@ size_t VSICurlStreamingHandle::Read( void * const pBuffer, size_t const nSize, s
 /*                          AddRegion()                                 */
 /************************************************************************/
 
-void  VSICurlStreamingHandle::AddRegion( vsi_l_offset    nFileOffsetStart,
-                                         size_t          nSize,
-                                         GByte          *pData )
+void VSICurlStreamingHandle::AddRegion( vsi_l_offset nFileOffsetStart,
+                                        size_t nSize,
+                                        GByte *pData )
 {
-    if (nFileOffsetStart >= BKGND_BUFFER_SIZE)
+    if( nFileOffsetStart >= BKGND_BUFFER_SIZE )
         return;
 
-    if (pCachedData == NULL)
-        pCachedData = (GByte*) CPLMalloc(BKGND_BUFFER_SIZE);
+    if( pCachedData == NULL )
+      pCachedData = static_cast<GByte *>(CPLMalloc(BKGND_BUFFER_SIZE));
 
-    if (nFileOffsetStart <= nCachedSize &&
-        nFileOffsetStart + nSize > nCachedSize)
+    if( nFileOffsetStart <= nCachedSize &&
+        nFileOffsetStart + nSize > nCachedSize )
     {
-        size_t nSz = MIN(nSize, (size_t) (BKGND_BUFFER_SIZE - nFileOffsetStart));
-        if (ENABLE_DEBUG)
+        const size_t nSz =
+            std::min(nSize,
+                     static_cast<size_t>(BKGND_BUFFER_SIZE - nFileOffsetStart));
+        if( ENABLE_DEBUG )
             CPLDebug("VSICURL", "Writing [%d, %d[ in cache for %s",
-                     (int)nFileOffsetStart, (int)(nFileOffsetStart + nSz), m_pszURL);
+                     static_cast<int>(nFileOffsetStart),
+                     static_cast<int>(nFileOffsetStart + nSz), m_pszURL);
         memcpy(pCachedData + nFileOffsetStart, pData, nSz);
-        nCachedSize = (size_t) (nFileOffsetStart + nSz);
+        nCachedSize = static_cast<size_t>(nFileOffsetStart + nSz);
     }
 }
 /************************************************************************/
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSICurlStreamingHandle::Write( CPL_UNUSED const void *pBuffer,
-                                      CPL_UNUSED size_t nSize,
-                                      CPL_UNUSED size_t nMemb )
+size_t VSICurlStreamingHandle::Write( const void * /* pBuffer */,
+                                      size_t /* nSize */,
+                                      size_t /* nMemb */ )
 {
     return 0;
 }
@@ -1381,8 +1474,7 @@ size_t VSICurlStreamingHandle::Write( CPL_UNUSED const void *pBuffer,
 /*                                 Eof()                                */
 /************************************************************************/
 
-
-int       VSICurlStreamingHandle::Eof()
+int VSICurlStreamingHandle::Eof()
 {
     return bEOF;
 }
@@ -1391,7 +1483,7 @@ int       VSICurlStreamingHandle::Eof()
 /*                                 Flush()                              */
 /************************************************************************/
 
-int       VSICurlStreamingHandle::Flush()
+int VSICurlStreamingHandle::Flush()
 {
     return 0;
 }
@@ -1405,7 +1497,6 @@ int       VSICurlStreamingHandle::Close()
     return 0;
 }
 
-
 /************************************************************************/
 /*                      VSICurlStreamingFSHandler()                     */
 /************************************************************************/
@@ -1422,9 +1513,8 @@ VSICurlStreamingFSHandler::VSICurlStreamingFSHandler()
 
 VSICurlStreamingFSHandler::~VSICurlStreamingFSHandler()
 {
-    std::map<CPLString, CachedFileProp*>::const_iterator iterCacheFileSize;
-
-    for( iterCacheFileSize = cacheFileSize.begin();
+    for( std::map<CPLString, CachedFileProp*>::const_iterator
+             iterCacheFileSize = cacheFileSize.begin();
          iterCacheFileSize != cacheFileSize.end();
          iterCacheFileSize++ )
     {
@@ -1459,12 +1549,14 @@ void VSICurlStreamingFSHandler::ReleaseMutex()
 
 /* Should be called under the FS Lock */
 
-CachedFileProp*  VSICurlStreamingFSHandler::GetCachedFileProp(const char* pszURL)
+CachedFileProp *
+VSICurlStreamingFSHandler::GetCachedFileProp( const char* pszURL )
 {
     CachedFileProp* cachedFileProp = cacheFileSize[pszURL];
-    if (cachedFileProp == NULL)
+    if( cachedFileProp == NULL )
     {
-        cachedFileProp = (CachedFileProp*) CPLMalloc(sizeof(CachedFileProp));
+        cachedFileProp =
+            static_cast<CachedFileProp *>(CPLMalloc(sizeof(CachedFileProp)));
         cachedFileProp->eExists = EXIST_UNKNOWN;
         cachedFileProp->bHasComputedFileSize = FALSE;
         cachedFileProp->fileSize = 0;
@@ -1482,7 +1574,8 @@ CachedFileProp*  VSICurlStreamingFSHandler::GetCachedFileProp(const char* pszURL
 /*                          CreateFileHandle()                          */
 /************************************************************************/
 
-VSICurlStreamingHandle* VSICurlStreamingFSHandler::CreateFileHandle(const char* pszURL)
+VSICurlStreamingHandle *
+VSICurlStreamingFSHandler::CreateFileHandle( const char* pszURL )
 {
     return new VSICurlStreamingHandle(this, pszURL);
 }
@@ -1495,26 +1588,28 @@ VSIVirtualHandle* VSICurlStreamingFSHandler::Open( const char *pszFilename,
                                                    const char *pszAccess,
                                                    bool /* bSetError */ )
 {
-    if (strchr(pszAccess, 'w') != NULL ||
-        strchr(pszAccess, '+') != NULL)
+    if( strchr(pszAccess, 'w') != NULL ||
+        strchr(pszAccess, '+') != NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
-                 "Only read-only mode is supported for %s", GetFSPrefix().c_str());
+                 "Only read-only mode is supported for %s",
+                 GetFSPrefix().c_str());
         return NULL;
     }
 
-    VSICurlStreamingHandle* poHandle = CreateFileHandle(pszFilename + GetFSPrefix().size());
-    /* If we didn't get a filelist, check that the file really exists */
-    if (poHandle == NULL || !poHandle->Exists())
+    VSICurlStreamingHandle* poHandle =
+        CreateFileHandle(pszFilename + GetFSPrefix().size());
+    // If we didn't get a filelist, check that the file really exists.
+    if( poHandle == NULL || !poHandle->Exists() )
     {
         delete poHandle;
         return NULL;
     }
 
-    if( CSLTestBoolean( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
         return VSICreateCachedFile( poHandle );
-    else
-        return poHandle;
+
+    return poHandle;
 }
 
 /************************************************************************/
@@ -1529,15 +1624,19 @@ int VSICurlStreamingFSHandler::Stat( const char *pszFilename,
 
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
 
-    VSICurlStreamingHandle* poHandle = CreateFileHandle(pszFilename + GetFSPrefix().size());
+    VSICurlStreamingHandle* poHandle =
+        CreateFileHandle(pszFilename + GetFSPrefix().size());
     if( poHandle == NULL )
     {
         return -1;
     }
-    if ( poHandle->IsKnownFileSize() ||
-         ((nFlags & VSI_STAT_SIZE_FLAG) && !poHandle->IsDirectory() &&
-           CSLTestBoolean(CPLGetConfigOption("CPL_VSIL_CURL_SLOW_GET_SIZE", "YES"))) )
+    if( poHandle->IsKnownFileSize() ||
+        ((nFlags & VSI_STAT_SIZE_FLAG) && !poHandle->IsDirectory() &&
+         CPLTestBool(CPLGetConfigOption("CPL_VSIL_CURL_SLOW_GET_SIZE",
+                                        "YES"))) )
+    {
         pStatBuf->st_size = poHandle->GetFileSize();
+    }
 
     int nRet = (poHandle->Exists()) ? 0 : -1;
     pStatBuf->st_mode = poHandle->IsDirectory() ? S_IFDIR : S_IFREG;
@@ -1547,45 +1646,6 @@ int VSICurlStreamingFSHandler::Stat( const char *pszFilename,
 }
 
 /************************************************************************/
-/*                   VSIInstallCurlFileHandler()                        */
-/************************************************************************/
-
-/**
- * \brief Install /vsicurl_streaming/ HTTP/FTP file system handler (requires libcurl)
- *
- * A special file handler is installed that allows on-the-fly sequential reading of files
- * streamed through HTTP/FTP web protocols (typically dynamically generated files),
- * without prior download of the entire file.
- *
- * Although this file handler is able seek to random offsets in the file, this will not
- * be efficient. If you need efficient random access and that the server supports range
- * dowloading, you should use the /vsicurl/ file system handler instead.
- *
- * Recognized filenames are of the form /vsicurl_streaming/http://path/to/remote/resource or
- * /vsicurl_streaming/ftp://path/to/remote/resource where path/to/remote/resource is the
- * URL of a remote resource.
- *
- * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration options can be
- * used to define a proxy server. The syntax to use is the one of Curl CURLOPT_PROXY,
- * CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
- *
- * The file can be cached in RAM by setting the configuration option
- * VSI_CACHE to TRUE. The cache size defaults to 25 MB, but can be modified by setting
- * the configuration option VSI_CACHE_SIZE (in bytes).
- *
- * VSIStatL() will return the size in st_size member and file
- * nature- file or directory - in st_mode member (the later only reliable with FTP
- * resources for now).
- *
- * @since GDAL 1.10
- */
-void VSIInstallCurlStreamingFileHandler(void)
-{
-    VSIFileManager::InstallHandler( "/vsicurl_streaming/", new VSICurlStreamingFSHandler );
-}
-
-
-/************************************************************************/
 /*                       VSIS3StreamingFSHandler                        */
 /************************************************************************/
 
@@ -1594,27 +1654,30 @@ class VSIS3StreamingFSHandler CPL_FINAL: public VSICurlStreamingFSHandler
     std::map< CPLString, VSIS3UpdateParams > oMapBucketsToS3Params;
 
 protected:
-    virtual CPLString GetFSPrefix() { return "/vsis3_streaming/"; }
-    virtual VSICurlStreamingHandle* CreateFileHandle(const char* pszURL);
+    virtual CPLString GetFSPrefix() override { return "/vsis3_streaming/"; }
+    virtual VSICurlStreamingHandle* CreateFileHandle( const char* pszURL )
+        override;
 
 public:
         VSIS3StreamingFSHandler() {}
 
-        void UpdateMapFromHandle(VSIS3HandleHelper * poS3HandleHelper);
-        void UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper);
+        void UpdateMapFromHandle( VSIS3HandleHelper * poS3HandleHelper );
+        void UpdateHandleFromMap( VSIS3HandleHelper * poS3HandleHelper );
 };
 
 /************************************************************************/
 /*                         UpdateMapFromHandle()                        */
 /************************************************************************/
 
-void VSIS3StreamingFSHandler::UpdateMapFromHandle(VSIS3HandleHelper * poS3HandleHelper)
+void VSIS3StreamingFSHandler::UpdateMapFromHandle(
+    VSIS3HandleHelper * poS3HandleHelper )
 {
     CPLMutexHolder oHolder( &hMutex );
 
     oMapBucketsToS3Params[ poS3HandleHelper->GetBucket() ] =
         VSIS3UpdateParams ( poS3HandleHelper->GetAWSRegion(),
                       poS3HandleHelper->GetAWSS3Endpoint(),
+                      poS3HandleHelper->GetRequestPayer(),
                       poS3HandleHelper->GetVirtualHosting() );
 }
 
@@ -1622,7 +1685,8 @@ void VSIS3StreamingFSHandler::UpdateMapFromHandle(VSIS3HandleHelper * poS3Handle
 /*                         UpdateHandleFromMap()                        */
 /************************************************************************/
 
-void VSIS3StreamingFSHandler::UpdateHandleFromMap(VSIS3HandleHelper * poS3HandleHelper)
+void VSIS3StreamingFSHandler::UpdateHandleFromMap(
+    VSIS3HandleHelper * poS3HandleHelper )
 {
     CPLMutexHolder oHolder( &hMutex );
 
@@ -1630,9 +1694,10 @@ void VSIS3StreamingFSHandler::UpdateHandleFromMap(VSIS3HandleHelper * poS3Handle
         oMapBucketsToS3Params.find(poS3HandleHelper->GetBucket());
     if( oIter != oMapBucketsToS3Params.end() )
     {
-        poS3HandleHelper->SetAWSRegion( oIter->second.m_osAWSRegion );
-        poS3HandleHelper->SetAWSS3Endpoint( oIter->second.m_osAWSS3Endpoint );
-        poS3HandleHelper->SetVirtualHosting( oIter->second.m_bUseVirtualHosting );
+        poS3HandleHelper->SetAWSRegion(oIter->second.m_osAWSRegion);
+        poS3HandleHelper->SetAWSS3Endpoint(oIter->second.m_osAWSS3Endpoint);
+        poS3HandleHelper->SetRequestPayer(oIter->second.m_osRequestPayer);
+        poS3HandleHelper->SetVirtualHosting(oIter->second.m_bUseVirtualHosting);
     }
 }
 
@@ -1645,25 +1710,29 @@ class VSIS3StreamingHandle CPL_FINAL: public VSICurlStreamingHandle
     VSIS3HandleHelper* m_poS3HandleHelper;
 
   protected:
-        virtual struct curl_slist* GetCurlHeaders(const CPLString& osVerb);
-        virtual bool StopReceivingBytesOnError() { return false; }
-        virtual bool CanRestartOnError(const char*, bool);
-        virtual bool InterpretRedirect() { return false; }
+    virtual struct curl_slist* GetCurlHeaders( const CPLString& osVerb )
+        override;
+    virtual bool StopReceivingBytesOnError() override { return false; }
+    virtual bool CanRestartOnError( const char* pszErrorMsg,
+                                    bool bSetError ) override;
+    virtual bool InterpretRedirect() override { return false; }
 
-    public:
-        VSIS3StreamingHandle(VSIS3StreamingFSHandler* poFS,
-                             VSIS3HandleHelper* poS3HandleHelper);
-        ~VSIS3StreamingHandle();
+  public:
+    VSIS3StreamingHandle( VSIS3StreamingFSHandler* poFS,
+                          VSIS3HandleHelper* poS3HandleHelper );
+    virtual ~VSIS3StreamingHandle();
 };
 
 /************************************************************************/
 /*                          CreateFileHandle()                          */
 /************************************************************************/
 
-VSICurlStreamingHandle* VSIS3StreamingFSHandler::CreateFileHandle(const char* pszURL)
+VSICurlStreamingHandle *
+VSIS3StreamingFSHandler::CreateFileHandle( const char* pszURL )
 {
     VSIS3HandleHelper* poS3HandleHelper =
-            VSIS3HandleHelper::BuildFromURI(pszURL, GetFSPrefix().c_str(), false);
+            VSIS3HandleHelper::BuildFromURI(pszURL, GetFSPrefix().c_str(),
+                                            false);
     if( poS3HandleHelper )
     {
         UpdateHandleFromMap(poS3HandleHelper);
@@ -1676,12 +1745,12 @@ VSICurlStreamingHandle* VSIS3StreamingFSHandler::CreateFileHandle(const char* ps
 /*                        VSIS3StreamingHandle()                        */
 /************************************************************************/
 
-VSIS3StreamingHandle::VSIS3StreamingHandle(VSIS3StreamingFSHandler* poFS,
-                                           VSIS3HandleHelper* poS3HandleHelper) :
-        VSICurlStreamingHandle(poFS, poS3HandleHelper->GetURL()),
-        m_poS3HandleHelper(poS3HandleHelper)
-{
-}
+VSIS3StreamingHandle::VSIS3StreamingHandle(
+    VSIS3StreamingFSHandler* poFS,
+    VSIS3HandleHelper* poS3HandleHelper) :
+    VSICurlStreamingHandle(poFS, poS3HandleHelper->GetURL()),
+    m_poS3HandleHelper(poS3HandleHelper)
+{}
 
 /************************************************************************/
 /*                       ~VSIS3StreamingHandle()                        */
@@ -1696,7 +1765,8 @@ VSIS3StreamingHandle::~VSIS3StreamingHandle()
 /*                           GetCurlHeaders()                           */
 /************************************************************************/
 
-struct curl_slist* VSIS3StreamingHandle::GetCurlHeaders(const CPLString& osVerb)
+struct curl_slist*
+VSIS3StreamingHandle::GetCurlHeaders( const CPLString& osVerb )
 {
     return m_poS3HandleHelper->GetCurlHeaders(osVerb);
 }
@@ -1705,11 +1775,13 @@ struct curl_slist* VSIS3StreamingHandle::GetCurlHeaders(const CPLString& osVerb)
 /*                          CanRestartOnError()                         */
 /************************************************************************/
 
-bool VSIS3StreamingHandle::CanRestartOnError(const char* pszErrorMsg, bool bSetError)
+bool VSIS3StreamingHandle::CanRestartOnError( const char* pszErrorMsg,
+                                              bool bSetError )
 {
     if( m_poS3HandleHelper->CanRestartOnError(pszErrorMsg, bSetError) )
     {
-        ((VSIS3StreamingFSHandler*) m_poFS)->UpdateMapFromHandle(m_poS3HandleHelper);
+        static_cast<VSIS3StreamingFSHandler*>(m_poFS)->
+            UpdateMapFromHandle(m_poS3HandleHelper);
 
         SetURL(m_poS3HandleHelper->GetURL());
         return true;
@@ -1717,36 +1789,183 @@ bool VSIS3StreamingHandle::CanRestartOnError(const char* pszErrorMsg, bool bSetE
     return false;
 }
 
+
+
+/************************************************************************/
+/*                       VSIGSStreamingFSHandler                        */
+/************************************************************************/
+
+class VSIGSStreamingFSHandler CPL_FINAL: public VSICurlStreamingFSHandler
+{
+protected:
+    virtual CPLString GetFSPrefix() override { return "/vsigs_streaming/"; }
+    virtual VSICurlStreamingHandle* CreateFileHandle( const char* pszURL )
+        override;
+
+public:
+        VSIGSStreamingFSHandler() {}
+};
+
+/************************************************************************/
+/*                            VSIGSStreamingHandle                      */
+/************************************************************************/
+
+class VSIGSStreamingHandle CPL_FINAL: public VSICurlStreamingHandle
+{
+    VSIGSHandleHelper* m_poGCHandleHelper;
+
+  protected:
+    virtual struct curl_slist* GetCurlHeaders( const CPLString& osVerb )
+        override;
+    virtual bool StopReceivingBytesOnError() override { return false; }
+    virtual bool InterpretRedirect() override { return false; }
+
+  public:
+    VSIGSStreamingHandle( VSIGSStreamingFSHandler* poFS,
+                          VSIGSHandleHelper* poGCHandleHelper );
+    virtual ~VSIGSStreamingHandle();
+};
+
+/************************************************************************/
+/*                          CreateFileHandle()                          */
+/************************************************************************/
+
+VSICurlStreamingHandle *
+VSIGSStreamingFSHandler::CreateFileHandle( const char* pszURL )
+{
+    VSIGSHandleHelper* poGCHandleHelper =
+            VSIGSHandleHelper::BuildFromURI(pszURL, GetFSPrefix().c_str());
+    if( poGCHandleHelper )
+    {
+        return new VSIGSStreamingHandle(this, poGCHandleHelper);
+    }
+    return NULL;
+}
+
+/************************************************************************/
+/*                        VSIGSStreamingHandle()                        */
+/************************************************************************/
+
+VSIGSStreamingHandle::VSIGSStreamingHandle(
+    VSIGSStreamingFSHandler* poFS,
+    VSIGSHandleHelper* poGCHandleHelper) :
+    VSICurlStreamingHandle(poFS, poGCHandleHelper->GetURL()),
+    m_poGCHandleHelper(poGCHandleHelper)
+{}
+
+/************************************************************************/
+/*                       ~VSIGSStreamingHandle()                        */
+/************************************************************************/
+
+VSIGSStreamingHandle::~VSIGSStreamingHandle()
+{
+    delete m_poGCHandleHelper;
+}
+
+/************************************************************************/
+/*                           GetCurlHeaders()                           */
+/************************************************************************/
+
+struct curl_slist*
+VSIGSStreamingHandle::GetCurlHeaders( const CPLString& osVerb )
+{
+    if( CSLFetchNameValue(m_papszHTTPOptions, "HEADER_FILE") )
+        return NULL;
+    return m_poGCHandleHelper->GetCurlHeaders(osVerb);
+}
+
+
+//! @endcond
+
+} /* end of anoymous namespace */
+
+/************************************************************************/
+/*                   VSIInstallCurlFileHandler()                        */
+/************************************************************************/
+
+/**
+ * \brief Install /vsicurl_streaming/ HTTP/FTP file system handler (requires
+ * libcurl).
+ *
+ * A special file handler is installed that allows on-the-fly sequential reading
+ * of files streamed through HTTP/FTP web protocols (typically dynamically
+ * generated files), without prior download of the entire file.
+ *
+ * Although this file handler is able seek to random offsets in the file, this
+ * will not be efficient. If you need efficient random access and that the
+ * server supports range dowloading, you should use the /vsicurl/ file system
+ * handler instead.
+ *
+ * Recognized filenames are of the form
+ * /vsicurl_streaming/http://path/to/remote/resource or
+ * /vsicurl_streaming/ftp://path/to/remote/resource where
+ * path/to/remote/resource is the URL of a remote resource.
+ *
+ * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration
+ * options can be used to define a proxy server. The syntax to use is the one of
+ * Curl CURLOPT_PROXY, CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
+ *
+ * Starting with GDAL 2.1.3, the CURL_CA_BUNDLE or SSL_CERT_FILE configuration
+ * options can be used to set the path to the Certification Authority (CA)
+ * bundle file (if not specified, curl will use a file in a system location).
+ *
+ * The file can be cached in RAM by setting the configuration option VSI_CACHE
+ * to TRUE. The cache size defaults to 25 MB, but can be modified by setting the
+ * configuration option VSI_CACHE_SIZE (in bytes).
+ *
+ * VSIStatL() will return the size in st_size member and file nature- file or
+ * directory - in st_mode member (the later only reliable with FTP resources for
+ * now).
+ *
+ * @since GDAL 1.10
+ */
+void VSIInstallCurlStreamingFileHandler(void)
+{
+    VSIFileManager::InstallHandler( "/vsicurl_streaming/",
+                                    new VSICurlStreamingFSHandler );
+}
+
 /************************************************************************/
 /*                   VSIInstallS3StreamingFileHandler()                 */
 /************************************************************************/
 
 /**
- * \brief Install /vsis3_streaming/ Amazon S3 file system handler (requires libcurl)
+ * \brief Install /vsis3_streaming/ Amazon S3 file system handler (requires
+ * libcurl).
  *
- * A special file handler is installed that allows on-the-fly sequential reading of files
- * streamed from AWS S3 buckets without prior download of the entire file.
+ * A special file handler is installed that allows on-the-fly sequential reading
+ * of non-public files streamed from AWS S3 buckets without prior download of
+ * the entire file.
  *
  * Recognized filenames are of the form /vsis3_streaming/bucket/key where
  * bucket is the name of the S3 bucket and resource the S3 object "key", i.e.
  * a filename potentially containing subdirectories.
  *
- * The AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID configuration options *must* be
- * set.
- * The AWS_SESSION_TOKEN configuration option must be set when temporary credentials
- * are used.
+ * The AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID configuration options *must*
+ * be set.
+ * The AWS_SESSION_TOKEN configuration option must be set when temporary
+ * credentials are used.
+
  * The AWS_REGION configuration option may be set to one of the supported
- * <a href="http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region">S3 regions</a>
- * and defaults to 'us-east-1'
- * The AWS_S3_ENDPOINT configuration option defaults to s3.amazonaws.com.
+ * <a href="http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region">
+ * S3 regions</a> and defaults to 'us-east-1'.  The AWS_S3_ENDPOINT
+ * configuration option defaults to s3.amazonaws.com. Starting with GDAL 2.2,
+ * the AWS_REQUEST_PAYER configuration option may be set to "requester" to
+ * facilitate use with
+ * <a href="http://docs.aws.amazon.com/AmazonS3/latest/dev/RequesterPaysBuckets.html">Requester
+ * Pays buckets</a>.
  *
- * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration options can be
- * used to define a proxy server. The syntax to use is the one of Curl CURLOPT_PROXY,
- * CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
+ * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration
+ * options can be used to define a proxy server. The syntax to use is the one of
+ * Curl CURLOPT_PROXY, CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
  *
- * The file can be cached in RAM by setting the configuration option
- * VSI_CACHE to TRUE. The cache size defaults to 25 MB, but can be modified by setting
- * the configuration option VSI_CACHE_SIZE (in bytes).
+ * Starting with GDAL 2.1.3, the CURL_CA_BUNDLE or SSL_CERT_FILE configuration
+ * options can be used to set the path to the Certification Authority (CA)
+ * bundle file (if not specified, curl will use a file in a system location).
+ *
+ * The file can be cached in RAM by setting the configuration option VSI_CACHE
+ * to TRUE. The cache size defaults to 25 MB, but can be modified by setting the
+ * configuration option VSI_CACHE_SIZE (in bytes).
  *
  * VSIStatL() will return the size in st_size member.
  *
@@ -1754,8 +1973,58 @@ bool VSIS3StreamingHandle::CanRestartOnError(const char* pszErrorMsg, bool bSetE
  */
 void VSIInstallS3StreamingFileHandler(void)
 {
-    VSIFileManager::InstallHandler( "/vsis3_streaming/", new VSIS3StreamingFSHandler );
+    VSIFileManager::InstallHandler( "/vsis3_streaming/",
+                                    new VSIS3StreamingFSHandler );
 }
 
+/************************************************************************/
+/*                      VSIInstallGSStreamingFileHandler()              */
+/************************************************************************/
+
+/**
+ * \brief Install /vsigs_streaming/ Google Cloud Storage file system handler
+ * (requires libcurl)
+ *
+ * A special file handler is installed that allows on-the-fly random reading of
+ * non-public files streamed from Google Cloud Storage buckets, without prior
+ * download of the entire file.
+ *
+ * Recognized filenames are of the form /vsigs_streaming/bucket/key where
+ * bucket is the name of the bucket and key the object "key", i.e.
+ * a filename potentially containing subdirectories.
+ *
+ * Partial downloads are done with a 16 KB granularity by default.
+ * If the driver detects sequential reading
+ * it will progressively increase the chunk size up to 2 MB to improve download
+ * performance.
+ *
+ * The GS_SECRET_ACCESS_KEY and GS_ACCESS_KEY_ID configuration options must be
+ * set to use the AWS S3 authentication compatibility method.
+ * 
+ * Alternatively, it is possible to set the GDAL_HTTP_HEADER_FILE configuration
+ * option to point to a filename of a text file with "key: value" headers.
+ * Typically, it must contain a "Authorization: Bearer XXXXXXXXX" line.
+ *
+ * The GDAL_HTTP_PROXY, GDAL_HTTP_PROXYUSERPWD and GDAL_PROXY_AUTH configuration
+ * options can be used to define a proxy server. The syntax to use is the one of
+ * Curl CURLOPT_PROXY, CURLOPT_PROXYUSERPWD and CURLOPT_PROXYAUTH options.
+ *
+ * The CURL_CA_BUNDLE or SSL_CERT_FILE configuration
+ * options can be used to set the path to the Certification Authority (CA)
+ * bundle file (if not specified, curl will use a file in a system location).
+ *
+ * On reading, the file can be cached in RAM by setting the configuration option
+ * VSI_CACHE to TRUE. The cache size defaults to 25 MB, but can be modified by
+ * setting the configuration option VSI_CACHE_SIZE (in bytes).
+ *
+ * VSIStatL() will return the size in st_size member.
+ *
+ * @since GDAL 2.2
+ */
+
+void VSIInstallGSStreamingFileHandler( void )
+{
+    VSIFileManager::InstallHandler( "/vsigs_streaming/", new VSIGSStreamingFSHandler );
+}
 
-#endif /*  !defined(HAVE_CURL) || defined(CPL_MULTIPROC_STUB) */
+#endif  // !defined(HAVE_CURL) || defined(CPL_MULTIPROC_STUB)
diff --git a/port/cpl_vsil_gzip.cpp b/port/cpl_vsil_gzip.cpp
index 5ff47c8..2889842 100644
--- a/port/cpl_vsil_gzip.cpp
+++ b/port/cpl_vsil_gzip.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil_gzip.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for gz/zip files (.gz and .zip).
@@ -27,6 +26,8 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+//! @cond Doxygen_Suppress
+
 /* gzio.c -- IO on .gz files
   Copyright (C) 1995-2005 Jean-loup Gailly.
 
@@ -49,61 +50,85 @@
   Jean-loup Gailly        Mark Adler
   jloup at gzip.org          madler at alumni.caltech.edu
 
-
   The data format used by the zlib library is described by RFCs (Request for
   Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
   (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
 */
 
-
 /* This file contains a refactoring of gzio.c from zlib project.
 
    It replaces classical calls operating on FILE* by calls to the VSI large file
    API. It also adds the capability to seek at the end of the file, which is not
-   implemented in original gzSeek. It also implements a concept of in-memory "snapshots",
-   that are a way of improving efficiency while seeking GZip files. Snapshots are
-   created regularly when decompressing  the data a snapshot of the gzip state.
-   Later we can seek directly in the compressed data to the closest snapshot in order to
-   reduce the amount of data to uncompress again.
-
-   For .gz files, an effort is done to cache the size of the uncompressed data in
-   a .gz.properties file, so that we don't need to seek at the end of the file
-   each time a Stat() is done.
-
-   For .zip and .gz, both reading and writing are supported, but just one mode at a time
-   (read-only or write-only)
+   implemented in original gzSeek. It also implements a concept of in-memory
+   "snapshots", that are a way of improving efficiency while seeking GZip
+   files. Snapshots are created regularly when decompressing the data a snapshot
+   of the gzip state.  Later we can seek directly in the compressed data to the
+   closest snapshot in order to reduce the amount of data to uncompress again.
+
+   For .gz files, an effort is done to cache the size of the uncompressed data
+   in a .gz.properties file, so that we don't need to seek at the end of the
+   file each time a Stat() is done.
+
+   For .zip and .gz, both reading and writing are supported, but just one mode
+   at a time (read-only or write-only).
 */
 
+#include "cpl_port.h"
+#include "cpl_conv.h"
+#include "cpl_vsi.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#if HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+#include <zlib.h>
 
-#include "cpl_vsi_virtual.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
+#include <algorithm>
 #include <map>
+#include <string>
+#include <utility>
+#include <vector>
 
-#include <zlib.h>
+#include "cpl_error.h"
+#include "cpl_minizip_ioapi.h"
 #include "cpl_minizip_unzip.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
 #include "cpl_time.h"
+#include "cpl_vsi_virtual.h"
+
 
-CPL_CVSID("$Id: cpl_vsil_gzip.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_gzip.cpp 36990 2016-12-21 19:42:05Z goatbar $");
 
-#define Z_BUFSIZE 65536  /* original size is 16384 */
-static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+static const int Z_BUFSIZE = 65536;  // Original size is 16384
+static const int gz_magic[2] = {0x1f, 0x8b};  // gzip magic header
 
-/* gzip flag byte */
-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
-#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-#define COMMENT      0x10 /* bit 4 set: file comment present */
-#define RESERVED     0xE0 /* bits 5..7: reserved */
+// gzip flag byte.
+#define ASCII_FLAG   0x01  // bit 0 set: file probably ascii text
+#define HEAD_CRC     0x02  // bit 1 set: header CRC present
+#define EXTRA_FIELD  0x04  // bit 2 set: extra field present
+#define ORIG_NAME    0x08  // bit 3 set: original file name present
+#define COMMENT      0x10  // bit 4 set: file comment present
+#define RESERVED     0xE0  // bits 5..7: reserved
 
 #define ALLOC(size) malloc(size)
 #define TRYFREE(p) {if (p) free(p);}
 
 #define CPL_VSIL_GZ_RETURN(ret)   \
-        CPLError(CE_Failure, CPLE_AppDefined, "In file %s, at line %d, return %d", __FILE__, __LINE__, ret)
+        CPLError(CE_Failure, CPLE_AppDefined, \
+                 "In file %s, at line %d, return %d", __FILE__, __LINE__, ret)
 
-#define ENABLE_DEBUG 0
+// #define ENABLE_DEBUG 1
 
 /************************************************************************/
 /* ==================================================================== */
@@ -124,13 +149,15 @@ typedef struct
 class VSIGZipHandle CPL_FINAL : public VSIVirtualHandle
 {
     VSIVirtualHandle* m_poBaseHandle;
+#ifdef DEBUG
     vsi_l_offset      m_offset;
+#endif
     vsi_l_offset      m_compressed_size;
     vsi_l_offset      m_uncompressed_size;
     vsi_l_offset      offsetEndCompressedData;
     uLong             m_expected_crc;
     char             *m_pszBaseFileName; /* optional */
-    int               m_bCanSaveInfo;
+    bool              m_bCanSaveInfo;
 
     /* Fields from gz_stream structure */
     z_stream stream;
@@ -156,24 +183,26 @@ class VSIGZipHandle CPL_FINAL : public VSIVirtualHandle
 
   public:
 
-    VSIGZipHandle(VSIVirtualHandle* poBaseHandle,
-                  const char* pszBaseFileName,
-                  vsi_l_offset offset = 0,
-                  vsi_l_offset compressed_size = 0,
-                  vsi_l_offset uncompressed_size = 0,
-                  uLong expected_crc = 0,
-                  int transparent = 0);
-    ~VSIGZipHandle();
+    VSIGZipHandle( VSIVirtualHandle* poBaseHandle,
+                   const char* pszBaseFileName,
+                   vsi_l_offset offset = 0,
+                   vsi_l_offset compressed_size = 0,
+                   vsi_l_offset uncompressed_size = 0,
+                   uLong expected_crc = 0,
+                   int transparent = 0 );
+    virtual ~VSIGZipHandle();
 
     bool              IsInitOK() const { return inbuf != NULL; }
 
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Flush();
-    virtual int       Close();
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb )
+        override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb )
+        override;
+    virtual int       Eof() override;
+    virtual int       Flush() override;
+    virtual int       Close() override;
 
     VSIGZipHandle*    Duplicate();
     bool              CloseBaseHandle();
@@ -181,13 +210,13 @@ class VSIGZipHandle CPL_FINAL : public VSIVirtualHandle
     vsi_l_offset      GetLastReadOffset() { return m_nLastReadOffset; }
     const char*       GetBaseFileName() { return m_pszBaseFileName; }
 
-    void              SetUncompressedSize(vsi_l_offset nUncompressedSize) { m_uncompressed_size = nUncompressedSize; }
+    void              SetUncompressedSize( vsi_l_offset nUncompressedSize )
+        { m_uncompressed_size = nUncompressedSize; }
     vsi_l_offset      GetUncompressedSize() { return m_uncompressed_size; }
 
     void              SaveInfo_unlocked();
 };
 
-
 class VSIGZipFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
     CPLMutex* hMutex;
@@ -195,27 +224,27 @@ class VSIGZipFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 
 public:
     VSIGZipFilesystemHandler();
-    ~VSIGZipFilesystemHandler();
-
-    using VSIFilesystemHandler::Open;
+    virtual ~VSIGZipFilesystemHandler();
 
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
+                                    bool bSetError ) override;
     VSIGZipHandle *OpenGZipReadOnly( const char *pszFilename,
                                      const char *pszAccess );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
-    virtual int      Unlink( const char *pszFilename );
-    virtual int      Rename( const char *oldpath, const char *newpath );
-    virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
-
-    void  SaveInfo( VSIGZipHandle* poHandle );
-    void  SaveInfo_unlocked( VSIGZipHandle* poHandle );
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
+    virtual int      Unlink( const char *pszFilename ) override;
+    virtual int      Rename( const char *oldpath,
+                             const char *newpath ) override;
+    virtual int      Mkdir( const char *pszDirname, long nMode ) override;
+    virtual int      Rmdir( const char *pszDirname ) override;
+    virtual char   **ReadDirEx( const char *pszDirname,
+                                int nMaxFiles ) override;
+
+    void SaveInfo( VSIGZipHandle* poHandle );
+    void SaveInfo_unlocked( VSIGZipHandle* poHandle );
 };
 
-
 /************************************************************************/
 /*                            Duplicate()                               */
 /************************************************************************/
@@ -232,7 +261,7 @@ VSIGZipHandle* VSIGZipHandle::Duplicate()
     VSIVirtualHandle* poNewBaseHandle =
         poFSHandler->Open( m_pszBaseFileName, "rb" );
 
-    if (poNewBaseHandle == NULL)
+    if( poNewBaseHandle == NULL )
         return NULL;
 
     VSIGZipHandle* poHandle = new VSIGZipHandle(poNewBaseHandle,
@@ -248,11 +277,13 @@ VSIGZipHandle* VSIGZipHandle::Duplicate()
 
     poHandle->m_nLastReadOffset = m_nLastReadOffset;
 
-    /* Most important : duplicate the snapshots ! */
+    // Most important: duplicate the snapshots!
 
-    for(unsigned int i=0;i<m_compressed_size / snapshot_byte_interval + 1;i++)
+    for( unsigned int i=0;
+         i < m_compressed_size / snapshot_byte_interval + 1;
+         i++ )
     {
-        if (snapshots[i].uncompressed_pos == 0)
+        if( snapshots[i].uncompressed_pos == 0 )
             break;
 
         poHandle->snapshots[i].uncompressed_pos = snapshots[i].uncompressed_pos;
@@ -270,10 +301,10 @@ VSIGZipHandle* VSIGZipHandle::Duplicate()
 /*                     CloseBaseHandle()                                */
 /************************************************************************/
 
-bool  VSIGZipHandle::CloseBaseHandle()
+bool VSIGZipHandle::CloseBaseHandle()
 {
     bool bRet = true;
-    if (m_poBaseHandle)
+    if( m_poBaseHandle )
         bRet = VSIFCloseL((VSILFILE*)m_poBaseHandle) == 0;
     m_poBaseHandle = NULL;
     return bRet;
@@ -283,21 +314,33 @@ bool  VSIGZipHandle::CloseBaseHandle()
 /*                       VSIGZipHandle()                                */
 /************************************************************************/
 
-VSIGZipHandle::VSIGZipHandle(VSIVirtualHandle* poBaseHandle,
-                             const char* pszBaseFileName,
-                             vsi_l_offset offset,
-                             vsi_l_offset compressed_size,
-                             vsi_l_offset uncompressed_size,
-                             uLong expected_crc,
-                             int transparent) :
+VSIGZipHandle::VSIGZipHandle( VSIVirtualHandle* poBaseHandle,
+                              const char* pszBaseFileName,
+                              vsi_l_offset offset,
+                              vsi_l_offset compressed_size,
+                              vsi_l_offset uncompressed_size,
+                              uLong expected_crc,
+                              int transparent ) :
+    m_poBaseHandle(poBaseHandle),
+#ifdef DEBUG
+    m_offset(offset),
+#endif
+    m_expected_crc(expected_crc),
+    m_pszBaseFileName(pszBaseFileName ? CPLStrdup(pszBaseFileName) : NULL),
+    m_bCanSaveInfo(true),
+    z_err(Z_OK),
+    z_eof(0),
+    outbuf(NULL),
+    crc(crc32(0L, NULL, 0)),
+    m_transparent(transparent),
+    startOff(0),
+    in(0),
+    out(0),
+    m_nLastReadOffset(0),
+    snapshots(NULL),
     snapshot_byte_interval(0)
 {
-    m_poBaseHandle = poBaseHandle;
-    m_expected_crc = expected_crc;
-    m_pszBaseFileName = (pszBaseFileName) ? CPLStrdup(pszBaseFileName) : NULL;
-    m_bCanSaveInfo = TRUE;
-    m_offset = offset;
-    if (compressed_size || transparent)
+    if( compressed_size || transparent )
     {
         m_compressed_size = compressed_size;
     }
@@ -314,46 +357,42 @@ VSIGZipHandle::VSIGZipHandle(VSIVirtualHandle* poBaseHandle,
     if( VSIFSeekL((VSILFILE*)poBaseHandle, offset, SEEK_SET) != 0 )
         CPLError(CE_Failure, CPLE_FileIO, "Seek() failed");
 
-    m_nLastReadOffset = 0;
     stream.zalloc = (alloc_func)NULL;
     stream.zfree = (free_func)NULL;
     stream.opaque = (voidpf)NULL;
     stream.next_in = inbuf = NULL;
     stream.next_out = outbuf = NULL;
     stream.avail_in = stream.avail_out = 0;
-    z_err = Z_OK;
-    z_eof = 0;
-    in = 0;
-    out = 0;
-    crc = crc32(0L, NULL, 0);
-    m_transparent = transparent;
-    startOff = 0;
-    snapshots = NULL;
 
-    stream.next_in  = inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+    inbuf = static_cast<Byte *>(ALLOC(Z_BUFSIZE));
+    stream.next_in = inbuf;
 
     int err = inflateInit2(&(stream), -MAX_WBITS);
-    /* windowBits is passed < 0 to tell that there is no zlib header.
-        * Note that in this case inflate *requires* an extra "dummy" byte
-        * after the compressed stream in order to complete decompression and
-        * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
-        * present after the compressed stream.
-        */
-    if (err != Z_OK || inbuf == NULL) {
+    // windowBits is passed < 0 to tell that there is no zlib header.
+    // Note that in this case inflate *requires* an extra "dummy" byte
+    // after the compressed stream in order to complete decompression and
+    // return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+    // present after the compressed stream.
+    if( err != Z_OK || inbuf == NULL )
+    {
         CPLError(CE_Failure, CPLE_NotSupported, "inflateInit2 init failed");
         TRYFREE(inbuf);
         inbuf = NULL;
         return;
     }
-    stream.avail_out = Z_BUFSIZE;
+    stream.avail_out = static_cast<uInt>(Z_BUFSIZE);
 
-    if (offset == 0) check_header(); /* skip the .gz header */
+    if( offset == 0 ) check_header();  // Skip the .gz header.
     startOff = VSIFTellL((VSILFILE*)poBaseHandle) - stream.avail_in;
 
-    if (transparent == 0)
+    if( transparent == 0 )
     {
-        snapshot_byte_interval = MAX(Z_BUFSIZE, compressed_size / 100);
-        snapshots = (GZipSnapshot*)CPLCalloc(sizeof(GZipSnapshot), (size_t) (compressed_size / snapshot_byte_interval + 1));
+        snapshot_byte_interval = std::max(
+            static_cast<vsi_l_offset>(Z_BUFSIZE), compressed_size / 100);
+        snapshots = static_cast<GZipSnapshot *>(
+            CPLCalloc(sizeof(GZipSnapshot),
+                      static_cast<size_t>(
+                          compressed_size / snapshot_byte_interval + 1)));
     }
 }
 
@@ -363,12 +402,13 @@ VSIGZipHandle::VSIGZipHandle(VSIVirtualHandle* poBaseHandle,
 
 void VSIGZipHandle::SaveInfo_unlocked()
 {
-    if (m_pszBaseFileName && m_bCanSaveInfo)
+    if( m_pszBaseFileName && m_bCanSaveInfo )
     {
         VSIFilesystemHandler *poFSHandler =
             VSIFileManager::GetHandler( "/vsigzip/" );
-        ((VSIGZipFilesystemHandler*)poFSHandler)->SaveInfo_unlocked(this);
-        m_bCanSaveInfo = FALSE;
+        reinterpret_cast<VSIGZipFilesystemHandler*>(poFSHandler)->
+                                                    SaveInfo_unlocked(this);
+        m_bCanSaveInfo = false;
     }
 }
 
@@ -378,25 +418,29 @@ void VSIGZipHandle::SaveInfo_unlocked()
 
 VSIGZipHandle::~VSIGZipHandle()
 {
-    if (m_pszBaseFileName && m_bCanSaveInfo)
+    if( m_pszBaseFileName && m_bCanSaveInfo )
     {
         VSIFilesystemHandler *poFSHandler =
             VSIFileManager::GetHandler( "/vsigzip/" );
-        ((VSIGZipFilesystemHandler*)poFSHandler)->SaveInfo(this);
+        reinterpret_cast<VSIGZipFilesystemHandler*>(poFSHandler)->
+            SaveInfo(this);
     }
 
-    if (stream.state != NULL) {
+    if( stream.state != NULL )
+    {
         inflateEnd(&(stream));
     }
 
     TRYFREE(inbuf);
     TRYFREE(outbuf);
 
-    if (snapshots != NULL)
+    if( snapshots != NULL )
     {
-        for(size_t i=0;i<m_compressed_size / snapshot_byte_interval + 1;i++)
+        for( size_t i=0;
+             i < m_compressed_size / snapshot_byte_interval + 1;
+             i++ )
         {
-            if (snapshots[i].uncompressed_pos)
+            if( snapshots[i].uncompressed_pos )
             {
                 inflateEnd(&(snapshots[i].stream));
             }
@@ -405,7 +449,7 @@ VSIGZipHandle::~VSIGZipHandle()
     }
     CPLFree(m_pszBaseFileName);
 
-    if (m_poBaseHandle)
+    if( m_poBaseHandle )
         CPL_IGNORE_RET_VAL(VSIFCloseL((VSILFILE*)m_poBaseHandle));
 }
 
@@ -415,37 +459,47 @@ VSIGZipHandle::~VSIGZipHandle()
 
 void VSIGZipHandle::check_header()
 {
-    /* Assure two bytes in the buffer so we can peek ahead -- handle case
-    where first byte of header is at the end of the buffer after the last
-    gzip segment */
+    // Assure two bytes in the buffer so we can peek ahead -- handle case
+    // where first byte of header is at the end of the buffer after the last
+    // gzip segment.
     uInt len = stream.avail_in;
-    if (len < 2) {
-        if (len) inbuf[0] = stream.next_in[0];
+    if( len < 2 )
+    {
+        if( len ) inbuf[0] = stream.next_in[0];
         errno = 0;
-        len = (uInt)VSIFReadL(inbuf + len, 1, Z_BUFSIZE >> len, (VSILFILE*)m_poBaseHandle);
-        if (ENABLE_DEBUG) CPLDebug("GZIP", CPL_FRMT_GUIB " " CPL_FRMT_GUIB,
-                                    VSIFTellL((VSILFILE*)m_poBaseHandle), offsetEndCompressedData);
-        if (VSIFTellL((VSILFILE*)m_poBaseHandle) > offsetEndCompressedData)
+        len = static_cast<uInt>(
+            VSIFReadL(inbuf + len, 1, static_cast<size_t>(Z_BUFSIZE) >> len,
+                      (VSILFILE*)m_poBaseHandle));
+#ifdef ENABLE_DEBUG
+        CPLDebug("GZIP", CPL_FRMT_GUIB " " CPL_FRMT_GUIB,
+                 VSIFTellL((VSILFILE*)m_poBaseHandle),
+                 offsetEndCompressedData);
+#endif
+        if( VSIFTellL((VSILFILE*)m_poBaseHandle) > offsetEndCompressedData )
         {
-            len = len + (uInt) (offsetEndCompressedData - VSIFTellL((VSILFILE*)m_poBaseHandle));
-            if(VSIFSeekL((VSILFILE*)m_poBaseHandle, offsetEndCompressedData, SEEK_SET) != 0)
+            len = len + static_cast<uInt>(
+                offsetEndCompressedData - VSIFTellL((VSILFILE*)m_poBaseHandle));
+            if( VSIFSeekL((VSILFILE*)m_poBaseHandle,
+                          offsetEndCompressedData, SEEK_SET) != 0 )
                 z_err = Z_DATA_ERROR;
         }
-        if (len == 0 /* && ferror(file)*/)
+        if( len == 0 )  // && ferror(file)
         {
-            if (VSIFTellL((VSILFILE*)m_poBaseHandle) != offsetEndCompressedData)
+            if( VSIFTellL((VSILFILE*)m_poBaseHandle) !=
+                offsetEndCompressedData )
                 z_err = Z_ERRNO;
         }
         stream.avail_in += len;
         stream.next_in = inbuf;
-        if (stream.avail_in < 2) {
+        if( stream.avail_in < 2 )
+        {
             m_transparent = stream.avail_in;
             return;
         }
     }
 
-    /* Peek ahead to check the gzip magic header */
-    if (stream.next_in[0] != gz_magic[0] ||
+    // Peek ahead to check the gzip magic header.
+    if( stream.next_in[0] != gz_magic[0] ||
         stream.next_in[1] != gz_magic[1]) {
         m_transparent = 1;
         return;
@@ -453,33 +507,44 @@ void VSIGZipHandle::check_header()
     stream.avail_in -= 2;
     stream.next_in += 2;
 
-    /* Check the rest of the gzip header */
+    // Check the rest of the gzip header.
     const int method = get_byte();
     const int flags = get_byte();
-    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+    if( method != Z_DEFLATED || (flags & RESERVED) != 0 )
+    {
         z_err = Z_DATA_ERROR;
         return;
     }
 
-    /* Discard time, xflags and OS code: */
-    for (len = 0; len < 6; len++) (void)get_byte();
+    // Discard time, xflags and OS code:
+    for( len = 0; len < 6; len++ )
+        CPL_IGNORE_RET_VAL(get_byte());
 
-    if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
-        len  =  (uInt)get_byte();
-        len += ((uInt)get_byte())<<8;
-        /* len is garbage if EOF but the loop below will quit anyway */
-        while (len-- != 0 && get_byte() != EOF) ;
+    if( (flags & EXTRA_FIELD) != 0 )
+    {
+        // Skip the extra field.
+        len = static_cast<uInt>(get_byte());
+        len += static_cast<uInt>(get_byte()) << 8;
+        // len is garbage if EOF but the loop below will quit anyway.
+        while( len-- != 0 && get_byte() != EOF ) {}
     }
 
     int c = 0;
-    if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
-        while ((c = get_byte()) != 0 && c != EOF) ;
+    if( (flags & ORIG_NAME) != 0 )
+    {
+        // Skip the original file name.
+        while( (c = get_byte()) != 0 && c != EOF ) {}
     }
-    if ((flags & COMMENT) != 0) {   /* skip the .gz file comment */
-        while ((c = get_byte()) != 0 && c != EOF) ;
+    if( (flags & COMMENT) != 0 )
+    {
+        // skip the .gz file comment.
+        while ((c = get_byte()) != 0 && c != EOF) {}
     }
-    if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
-        for (len = 0; len < 2; len++) (void)get_byte();
+    if( (flags & HEAD_CRC) != 0 )
+    {
+        // Skip the header crc.
+        for( len = 0; len < 2; len++ )
+            CPL_IGNORE_RET_VAL(get_byte());
     }
     z_err = z_eof ? Z_DATA_ERROR : Z_OK;
 }
@@ -490,23 +555,35 @@ void VSIGZipHandle::check_header()
 
 int VSIGZipHandle::get_byte()
 {
-    if (z_eof) return EOF;
-    if (stream.avail_in == 0) {
+    if( z_eof ) return EOF;
+    if( stream.avail_in == 0 )
+    {
         errno = 0;
-        stream.avail_in = (uInt)VSIFReadL(inbuf, 1, Z_BUFSIZE, (VSILFILE*)m_poBaseHandle);
-        if (ENABLE_DEBUG) CPLDebug("GZIP", CPL_FRMT_GUIB " " CPL_FRMT_GUIB,
-                                   VSIFTellL((VSILFILE*)m_poBaseHandle), offsetEndCompressedData);
-        if (VSIFTellL((VSILFILE*)m_poBaseHandle) > offsetEndCompressedData)
+        stream.avail_in = static_cast<uInt>(
+            VSIFReadL(inbuf, 1, static_cast<size_t>(Z_BUFSIZE),
+                      (VSILFILE*)m_poBaseHandle));
+#ifdef ENABLE_DEBUG
+        CPLDebug("GZIP", CPL_FRMT_GUIB " " CPL_FRMT_GUIB,
+                 VSIFTellL((VSILFILE*)m_poBaseHandle),
+                 offsetEndCompressedData);
+#endif
+        if( VSIFTellL((VSILFILE*)m_poBaseHandle) > offsetEndCompressedData )
         {
-            stream.avail_in = stream.avail_in + (uInt) (offsetEndCompressedData - VSIFTellL((VSILFILE*)m_poBaseHandle));
-            if( VSIFSeekL((VSILFILE*)m_poBaseHandle, offsetEndCompressedData, SEEK_SET) != 0 )
+            stream.avail_in =
+                stream.avail_in +
+                static_cast<uInt>(
+                    offsetEndCompressedData -
+                    VSIFTellL((VSILFILE*)m_poBaseHandle));
+            if( VSIFSeekL((VSILFILE*)m_poBaseHandle,
+                          offsetEndCompressedData, SEEK_SET) != 0 )
                 return EOF;
         }
-        if (stream.avail_in == 0) {
+        if( stream.avail_in == 0 ) {
             z_eof = 1;
-            if (VSIFTellL((VSILFILE*)m_poBaseHandle) != offsetEndCompressedData)
+            if( VSIFTellL((VSILFILE*)m_poBaseHandle) !=
+                offsetEndCompressedData )
                 z_err = Z_ERRNO;
-            /*if (ferror(file)) z_err = Z_ERRNO;*/
+            // if( ferror(file) ) z_err = Z_ERRNO;
             return EOF;
         }
         stream.next_in = inbuf;
@@ -526,7 +603,8 @@ int VSIGZipHandle::gzrewind ()
     stream.avail_in = 0;
     stream.next_in = inbuf;
     crc = crc32(0L, NULL, 0);
-    if (!m_transparent) (void)inflateReset(&stream);
+    if( !m_transparent )
+        CPL_IGNORE_RET_VAL(inflateReset(&stream));
     in = 0;
     out = 0;
     return VSIFSeekL((VSILFILE*)m_poBaseHandle, startOff, SEEK_SET);
@@ -555,15 +633,17 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
     const int original_nWhence = whence;
 
     z_eof = 0;
-    if (ENABLE_DEBUG) CPLDebug("GZIP", "Seek(" CPL_FRMT_GUIB ",%d)", offset, whence);
+#ifdef ENABLE_DEBUG
+    CPLDebug("GZIP", "Seek(" CPL_FRMT_GUIB ",%d)", offset, whence);
+#endif
 
-    if (m_transparent)
+    if( m_transparent )
     {
         stream.avail_in = 0;
         stream.next_in = inbuf;
-        if (whence == SEEK_CUR)
+        if( whence == SEEK_CUR )
         {
-            if (out + offset > m_compressed_size)
+            if( out + offset > m_compressed_size )
             {
                 CPL_VSIL_GZ_RETURN(-1);
                 return -1L;
@@ -571,9 +651,9 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
 
             offset = startOff + out + offset;
         }
-        else if (whence == SEEK_SET)
+        else if( whence == SEEK_SET )
         {
-            if (offset > m_compressed_size)
+            if( offset > m_compressed_size )
             {
                 CPL_VSIL_GZ_RETURN(-1);
                 return -1L;
@@ -581,11 +661,11 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
 
             offset = startOff + offset;
         }
-        else if (whence == SEEK_END)
+        else if( whence == SEEK_END )
         {
-            /* Commented test : because vsi_l_offset is unsigned (for the moment) */
-            /* so no way to seek backward. See #1590 */
-            if (offset > 0 /*|| -offset > compressed_size*/)
+            // Commented test: because vsi_l_offset is unsigned (for the moment)
+            // so no way to seek backward. See #1590 */
+            if( offset > 0 ) // || -offset > compressed_size
             {
                 CPL_VSIL_GZ_RETURN(-1);
                 return -1L;
@@ -598,34 +678,40 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
             CPL_VSIL_GZ_RETURN(-1);
             return -1L;
         }
-        if (VSIFSeekL((VSILFILE*)m_poBaseHandle, offset, SEEK_SET) < 0)
+
+        if( VSIFSeekL((VSILFILE*)m_poBaseHandle, offset, SEEK_SET) < 0 )
         {
             CPL_VSIL_GZ_RETURN(-1);
             return -1L;
         }
 
-        in = out = offset - startOff;
-        if (ENABLE_DEBUG) CPLDebug("GZIP", "return " CPL_FRMT_GUIB, in);
-        return (in > INT_MAX) ? INT_MAX : (int) in;
+        out = offset - startOff;
+        in = out;
+#ifdef ENABLE_DEBUG
+        CPLDebug("GZIP", "return " CPL_FRMT_GUIB, in);
+#endif
+        return in > INT_MAX ? INT_MAX : static_cast<int>(in);
     }
 
-    /* whence == SEEK_END is unsuppored in original gzseek. */
-    if (whence == SEEK_END)
+    // whence == SEEK_END is unsuppored in original gzseek.
+    if( whence == SEEK_END )
     {
-        /* If we known the uncompressed size, we can fake a jump to */
-        /* the end of the stream */
-        if (offset == 0 && m_uncompressed_size != 0)
+        // If we known the uncompressed size, we can fake a jump to
+        // the end of the stream.
+        if( offset == 0 && m_uncompressed_size != 0 )
         {
             out = m_uncompressed_size;
             return 1;
         }
 
-        /* We don't know the uncompressed size. This is unfortunate. Let's do the slow version... */
+        // We don't know the uncompressed size. This is unfortunate.
+        // Do the slow version.
         static int firstWarning = 1;
-        if (m_compressed_size > 10 * 1024 * 1024 && firstWarning)
+        if( m_compressed_size > 10 * 1024 * 1024 && firstWarning )
         {
             CPLError(CE_Warning, CPLE_AppDefined,
-                        "VSIFSeekL(xxx, SEEK_END) may be really slow on GZip streams.");
+                     "VSIFSeekL(xxx, SEEK_END) may be really slow "
+                     "on GZip streams.");
             firstWarning = 0;
         }
 
@@ -634,47 +720,61 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
         offset *= 1024 * 1024;
     }
 
-    if (/*whence == SEEK_END ||*/
-        z_err == Z_ERRNO || z_err == Z_DATA_ERROR) {
+    if( // whence == SEEK_END ||
+        z_err == Z_ERRNO || z_err == Z_DATA_ERROR )
+    {
         CPL_VSIL_GZ_RETURN(-1);
         return -1L;
     }
 
-    /* Rest of function is for reading only */
+    // Rest of function is for reading only.
 
-    /* compute absolute position */
-    if (whence == SEEK_CUR) {
+    // Compute absolute position.
+    if( whence == SEEK_CUR )
+    {
         offset += out;
     }
 
-    /* For a negative seek, rewind and use positive seek */
-    if (offset >= out) {
+    // For a negative seek, rewind and use positive seek.
+    if( offset >= out )
+    {
         offset -= out;
-    } else if (gzrewind() < 0) {
+    }
+    else if( gzrewind() < 0 )
+    {
             CPL_VSIL_GZ_RETURN(-1);
             return -1L;
     }
 
-    for(unsigned int i=0;i<m_compressed_size / snapshot_byte_interval + 1;i++)
+    for( unsigned int i = 0;
+         i < m_compressed_size / snapshot_byte_interval + 1;
+         i++ )
     {
-        if (snapshots[i].uncompressed_pos == 0)
+        if( snapshots[i].uncompressed_pos == 0 )
             break;
-        if (snapshots[i].out <= out + offset &&
-            (i == m_compressed_size / snapshot_byte_interval || snapshots[i+1].out == 0 || snapshots[i+1].out > out+offset))
+        if( snapshots[i].out <= out + offset &&
+            (i == m_compressed_size / snapshot_byte_interval ||
+             snapshots[i+1].out == 0 || snapshots[i+1].out > out+offset) )
         {
-            if (out >= snapshots[i].out)
+            if( out >= snapshots[i].out )
                 break;
 
-            if (ENABLE_DEBUG)
-                CPLDebug("SNAPSHOT", "using snapshot %d : uncompressed_pos(snapshot)=" CPL_FRMT_GUIB
-                                                        " in(snapshot)=" CPL_FRMT_GUIB
-                                                        " out(snapshot)=" CPL_FRMT_GUIB
-                                                        " out=" CPL_FRMT_GUIB
-                                                        " offset=" CPL_FRMT_GUIB,
-                         i, snapshots[i].uncompressed_pos, snapshots[i].in, snapshots[i].out, out, offset);
+#ifdef ENABLE_DEBUG
+            CPLDebug(
+                "SNAPSHOT", "using snapshot %d : "
+                "uncompressed_pos(snapshot)=" CPL_FRMT_GUIB
+                " in(snapshot)=" CPL_FRMT_GUIB
+                " out(snapshot)=" CPL_FRMT_GUIB
+                " out=" CPL_FRMT_GUIB
+                " offset=" CPL_FRMT_GUIB,
+                i, snapshots[i].uncompressed_pos, snapshots[i].in,
+                snapshots[i].out, out, offset);
+#endif
             offset = out + offset - snapshots[i].out;
-            if( VSIFSeekL((VSILFILE*)m_poBaseHandle, snapshots[i].uncompressed_pos, SEEK_SET) != 0 )
+            if( VSIFSeekL((VSILFILE*)m_poBaseHandle,
+                          snapshots[i].uncompressed_pos, SEEK_SET) != 0 )
                 CPLError(CE_Failure, CPLE_FileIO, "Seek() failed");
+
             inflateEnd(&stream);
             inflateCopy(&stream, &snapshots[i].stream);
             crc = snapshots[i].crc;
@@ -685,34 +785,42 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
         }
     }
 
-    /* offset is now the number of bytes to skip. */
+    // Offset is now the number of bytes to skip.
 
-    if (offset != 0 && outbuf == NULL) {
-        outbuf = (Byte*)ALLOC(Z_BUFSIZE);
-        if (outbuf == NULL) {
+    if( offset != 0 && outbuf == NULL )
+    {
+        outbuf = static_cast<Byte*>(ALLOC(Z_BUFSIZE));
+        if( outbuf == NULL )
+        {
             CPL_VSIL_GZ_RETURN(-1);
             return -1L;
         }
     }
 
-    if (original_nWhence == SEEK_END && z_err == Z_STREAM_END)
+    if( original_nWhence == SEEK_END && z_err == Z_STREAM_END )
     {
-        if (ENABLE_DEBUG) CPLDebug("GZIP", "gzseek return " CPL_FRMT_GUIB, out);
-        return (int) out;
+#ifdef ENABLE_DEBUG
+        CPLDebug("GZIP", "gzseek return " CPL_FRMT_GUIB, out);
+#endif
+        return static_cast<int>(out);
     }
 
-    while (offset > 0)  {
+    while( offset > 0 )
+    {
         int size = Z_BUFSIZE;
-        if (offset < Z_BUFSIZE) size = (int)offset;
+        if( offset < static_cast<vsi_l_offset>(Z_BUFSIZE) )
+            size = static_cast<int>(offset);
 
-        int read_size = static_cast<int>(Read(outbuf, 1, (uInt)size));
-        if (read_size == 0) {
-            //CPL_VSIL_GZ_RETURN(-1);
+        int read_size =
+            static_cast<int>(Read(outbuf, 1, static_cast<uInt>(size)));
+        if( read_size == 0 )
+        {
+            // CPL_VSIL_GZ_RETURN(-1);
             return -1L;
         }
-        if (original_nWhence == SEEK_END)
+        if( original_nWhence == SEEK_END )
         {
-            if (size != read_size)
+            if( size != read_size )
             {
                 z_err = Z_STREAM_END;
                 break;
@@ -720,41 +828,45 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
         }
         offset -= read_size;
     }
-    if (ENABLE_DEBUG) CPLDebug("GZIP", "gzseek return " CPL_FRMT_GUIB, out);
+#ifdef ENABLE_DEBUG
+    CPLDebug("GZIP", "gzseek return " CPL_FRMT_GUIB, out);
+#endif
 
-    if (original_offset == 0 && original_nWhence == SEEK_END)
+    if( original_offset == 0 && original_nWhence == SEEK_END )
     {
         m_uncompressed_size = out;
 
-        if (m_pszBaseFileName)
+        if( m_pszBaseFileName )
         {
             CPLString osCacheFilename (m_pszBaseFileName);
             osCacheFilename += ".properties";
 
-            /* Write a .properties file to avoid seeking next time */
+            // Write a .properties file to avoid seeking next time.
             VSILFILE* fpCacheLength = VSIFOpenL(osCacheFilename.c_str(), "wb");
-            if (fpCacheLength)
+            if( fpCacheLength )
             {
-                char* pszFirstNonSpace;
-                char szBuffer[32];
-                szBuffer[31] = 0;
+                char szBuffer[32] = {};
 
                 CPLPrintUIntBig(szBuffer, m_compressed_size, 31);
-                pszFirstNonSpace = szBuffer;
-                while (*pszFirstNonSpace == ' ') pszFirstNonSpace ++;
-                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCacheLength, "compressed_size=%s\n", pszFirstNonSpace));
+                char* pszFirstNonSpace = szBuffer;
+                while( *pszFirstNonSpace == ' ' ) pszFirstNonSpace++;
+                CPL_IGNORE_RET_VAL(
+                    VSIFPrintfL(fpCacheLength,
+                                "compressed_size=%s\n", pszFirstNonSpace));
 
                 CPLPrintUIntBig(szBuffer, m_uncompressed_size, 31);
                 pszFirstNonSpace = szBuffer;
-                while (*pszFirstNonSpace == ' ') pszFirstNonSpace ++;
-                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpCacheLength, "uncompressed_size=%s\n", pszFirstNonSpace));
+                while( *pszFirstNonSpace == ' ' ) pszFirstNonSpace++;
+                CPL_IGNORE_RET_VAL(
+                    VSIFPrintfL(fpCacheLength,
+                                "uncompressed_size=%s\n", pszFirstNonSpace));
 
                 CPL_IGNORE_RET_VAL(VSIFCloseL(fpCacheLength));
             }
         }
     }
 
-    return (int) out;
+    return static_cast<int>(out);
 }
 
 /************************************************************************/
@@ -763,7 +875,9 @@ int VSIGZipHandle::gzseek( vsi_l_offset offset, int whence )
 
 vsi_l_offset VSIGZipHandle::Tell()
 {
-    if (ENABLE_DEBUG) CPLDebug("GZIP", "Tell() = " CPL_FRMT_GUIB, out);
+#ifdef ENABLE_DEBUG
+    CPLDebug("GZIP", "Tell() = " CPL_FRMT_GUIB, out);
+#endif
     return out;
 }
 
@@ -771,110 +885,149 @@ vsi_l_offset VSIGZipHandle::Tell()
 /*                              Read()                                  */
 /************************************************************************/
 
-size_t VSIGZipHandle::Read( void * const buf, size_t const nSize, size_t const nMemb )
+size_t VSIGZipHandle::Read( void * const buf, size_t const nSize,
+                            size_t const nMemb )
 {
-    if (ENABLE_DEBUG) CPLDebug("GZIP", "Read(%p, %d, %d)", buf, (int)nSize, (int)nMemb);
+#ifdef ENABLE_DEBUG
+    CPLDebug("GZIP", "Read(%p, %d, %d)", buf,
+             static_cast<int>(nSize),
+             static_cast<int>(nMemb));
+#endif
 
-    if  (z_err == Z_DATA_ERROR || z_err == Z_ERRNO)
+    if( z_err == Z_DATA_ERROR || z_err == Z_ERRNO )
     {
-        z_eof = 1; /* to avoid infinite loop in reader code */
+        z_eof = 1;  // To avoid infinite loop in reader code.
         in = 0;
         CPL_VSIL_GZ_RETURN(0);
         return 0;
     }
-    if  ((z_eof && in == 0) || z_err == Z_STREAM_END)
+    if( (z_eof && in == 0) || z_err == Z_STREAM_END )
     {
         z_eof = 1;
         in = 0;
-        if (ENABLE_DEBUG) CPLDebug("GZIP", "Read: Eof");
+#ifdef ENABLE_DEBUG
+        CPLDebug("GZIP", "Read: Eof");
+#endif
         return 0;  /* EOF */
     }
 
-    const unsigned len = static_cast<unsigned int>(nSize) * static_cast<unsigned int>(nMemb);
-    Bytef *pStart = (Bytef*)buf; /* startOffing point for crc computation */
-    Byte  *next_out; /* == stream.next_out but not forced far (for MSDOS) */
-    next_out = (Byte*)buf;
-    stream.next_out = (Bytef*)buf;
+    const unsigned len =
+        static_cast<unsigned int>(nSize) * static_cast<unsigned int>(nMemb);
+    Bytef *pStart = (Bytef*)buf;  // Start off point for crc computation.
+    // == stream.next_out but not forced far (for MSDOS).
+    Byte *next_out = static_cast<Byte *>(buf);
+    stream.next_out = static_cast<Bytef *>(buf);
     stream.avail_out = len;
 
-    while  (stream.avail_out != 0) {
-
-        if  (m_transparent) {
-            /* Copy first the lookahead bytes: */
+    while( stream.avail_out != 0 )
+    {
+        if( m_transparent )
+        {
+            // Copy first the lookahead bytes:
             uInt nRead = 0;
             uInt n = stream.avail_in;
-            if (n > stream.avail_out) n = stream.avail_out;
-            if (n > 0) {
+            if( n > stream.avail_out )
+                n = stream.avail_out;
+            if( n > 0 )
+            {
                 memcpy (stream.next_out, stream.next_in, n);
                 next_out += n;
                 stream.next_out = next_out;
-                stream.next_in   += n;
+                stream.next_in += n;
                 stream.avail_out -= n;
-                stream.avail_in  -= n;
+                stream.avail_in -= n;
                 nRead += n;
             }
-            if  (stream.avail_out > 0) {
-                uInt nToRead = (uInt) MIN(m_compressed_size - (in + nRead), stream.avail_out);
-                uInt nReadFromFile =
-                    (uInt)VSIFReadL(next_out, 1, nToRead, (VSILFILE*)m_poBaseHandle);
+            if( stream.avail_out > 0 )
+            {
+                const uInt nToRead = static_cast<uInt>(
+                    std::min(m_compressed_size - (in + nRead),
+                             static_cast<vsi_l_offset>(stream.avail_out)));
+                uInt nReadFromFile = static_cast<uInt>(
+                    VSIFReadL(next_out, 1, nToRead, (VSILFILE*)m_poBaseHandle));
                 stream.avail_out -= nReadFromFile;
                 nRead += nReadFromFile;
             }
-            in  += nRead;
+            in += nRead;
             out += nRead;
-            if (nRead < len) z_eof = 1;
-            if (ENABLE_DEBUG) CPLDebug("GZIP", "Read return %d", (int)(nRead / nSize));
-            return (int)nRead / nSize;
+            if( nRead < len )
+                z_eof = 1;
+#ifdef ENABLE_DEBUG
+            CPLDebug("GZIP", "Read return %d", static_cast<int>(nRead / nSize));
+#endif
+            return static_cast<int>(nRead) / nSize;
         }
-        if  (stream.avail_in == 0 && !z_eof)
+        if( stream.avail_in == 0 && !z_eof )
         {
-            vsi_l_offset uncompressed_pos = VSIFTellL((VSILFILE*)m_poBaseHandle);
-            GZipSnapshot* snapshot = &snapshots[(uncompressed_pos - startOff) / snapshot_byte_interval];
-            if (snapshot->uncompressed_pos == 0)
+            vsi_l_offset uncompressed_pos =
+                VSIFTellL((VSILFILE*)m_poBaseHandle);
+            GZipSnapshot* snapshot =
+                &snapshots[(uncompressed_pos - startOff) /
+                           snapshot_byte_interval];
+            if( snapshot->uncompressed_pos == 0 )
             {
-                snapshot->crc = crc32 (crc, pStart, (uInt) (stream.next_out - pStart));
-                if (ENABLE_DEBUG)
-                    CPLDebug("SNAPSHOT",
-                             "creating snapshot %d : uncompressed_pos=" CPL_FRMT_GUIB
-                                                   " in=" CPL_FRMT_GUIB
-                                                   " out=" CPL_FRMT_GUIB
-                                                   " crc=%X",
-                          (int)((uncompressed_pos - startOff) / snapshot_byte_interval),
-                          uncompressed_pos, in, out, (unsigned int)snapshot->crc);
+                snapshot->crc =
+                    crc32(crc, pStart,
+                          static_cast<uInt>(stream.next_out - pStart));
+#ifdef ENABLE_DEBUG
+                CPLDebug("SNAPSHOT",
+                         "creating snapshot %d : "
+                         "uncompressed_pos=" CPL_FRMT_GUIB
+                         " in=" CPL_FRMT_GUIB
+                         " out=" CPL_FRMT_GUIB
+                         " crc=%X",
+                         static_cast<int>((uncompressed_pos - startOff) /
+                                          snapshot_byte_interval),
+                         uncompressed_pos, in, out,
+                         static_cast<unsigned int>(snapshot->crc));
+#endif
                 snapshot->uncompressed_pos = uncompressed_pos;
                 inflateCopy(&snapshot->stream, &stream);
                 snapshot->transparent = m_transparent;
                 snapshot->in = in;
                 snapshot->out = out;
 
-                if (out > m_nLastReadOffset)
+                if( out > m_nLastReadOffset )
                     m_nLastReadOffset = out;
             }
 
             errno = 0;
-            stream.avail_in = (uInt)VSIFReadL(inbuf, 1, Z_BUFSIZE, (VSILFILE*)m_poBaseHandle);
-            if (ENABLE_DEBUG)
-                CPLDebug("GZIP", CPL_FRMT_GUIB " " CPL_FRMT_GUIB,
-                                 VSIFTellL((VSILFILE*)m_poBaseHandle), offsetEndCompressedData);
-            if (VSIFTellL((VSILFILE*)m_poBaseHandle) > offsetEndCompressedData)
+            stream.avail_in = static_cast<uInt>(
+                VSIFReadL(inbuf, 1, Z_BUFSIZE, (VSILFILE*)m_poBaseHandle));
+#ifdef ENABLE_DEBUG
+            CPLDebug("GZIP", CPL_FRMT_GUIB " " CPL_FRMT_GUIB,
+                     VSIFTellL((VSILFILE*)m_poBaseHandle),
+                     offsetEndCompressedData);
+#endif
+            if( VSIFTellL((VSILFILE*)m_poBaseHandle) > offsetEndCompressedData )
             {
-                if (ENABLE_DEBUG) CPLDebug("GZIP", "avail_in before = %d", stream.avail_in);
-                stream.avail_in = stream.avail_in + (uInt) (offsetEndCompressedData - VSIFTellL((VSILFILE*)m_poBaseHandle));
-                if( VSIFSeekL((VSILFILE*)m_poBaseHandle, offsetEndCompressedData, SEEK_SET) != 0 )
+#ifdef ENABLE_DEBUG
+                CPLDebug("GZIP", "avail_in before = %d", stream.avail_in);
+#endif
+                stream.avail_in =
+                    stream.avail_in +
+                    static_cast<uInt>(offsetEndCompressedData -
+                                      VSIFTellL((VSILFILE*)m_poBaseHandle));
+                if( VSIFSeekL((VSILFILE*)m_poBaseHandle,
+                              offsetEndCompressedData, SEEK_SET) != 0 )
                     CPLError(CE_Failure, CPLE_FileIO, "Seek() failed");
-                if (ENABLE_DEBUG) CPLDebug("GZIP", "avail_in after = %d", stream.avail_in);
+#ifdef ENABLE_DEBUG
+                CPLDebug("GZIP", "avail_in after = %d", stream.avail_in);
+#endif
             }
-            if  (stream.avail_in == 0) {
+            if( stream.avail_in == 0 )
+            {
                 z_eof = 1;
-                if (VSIFTellL((VSILFILE*)m_poBaseHandle) != offsetEndCompressedData)
+                if( VSIFTellL((VSILFILE*)m_poBaseHandle) !=
+                    offsetEndCompressedData )
                 {
                     z_err = Z_ERRNO;
                     break;
                 }
-                /*if (ferror (file)) {
-                    z_err = Z_ERRNO;
-                    break;
-                }*/
+                // if( ferror (file) ) {
+                //    z_err = Z_ERRNO;
+                //    break;
+                // }
             }
             stream.next_in = inbuf;
         }
@@ -884,58 +1037,76 @@ size_t VSIGZipHandle::Read( void * const buf, size_t const nSize, size_t const n
         in -= stream.avail_in;
         out -= stream.avail_out;
 
-        if  (z_err == Z_STREAM_END && m_compressed_size != 2 ) {
-            /* Check CRC and original size */
-            crc = crc32 (crc, pStart, (uInt) (stream.next_out - pStart));
+        if( z_err == Z_STREAM_END && m_compressed_size != 2 )
+        {
+            // Check CRC and original size.
+            crc = crc32(crc, pStart,
+                        static_cast<uInt>(stream.next_out - pStart));
             pStart = stream.next_out;
-            if (m_expected_crc)
+            if( m_expected_crc )
             {
-                if (ENABLE_DEBUG) CPLDebug("GZIP", "Computed CRC = %X. Expected CRC = %X", static_cast<unsigned int>(crc), static_cast<unsigned int>(m_expected_crc));
+#ifdef ENABLE_DEBUG
+                CPLDebug(
+                    "GZIP",
+                    "Computed CRC = %X. Expected CRC = %X",
+                    static_cast<unsigned int>(crc),
+                    static_cast<unsigned int>(m_expected_crc));
+#endif
             }
-            if (m_expected_crc != 0 && m_expected_crc != crc)
+            if( m_expected_crc != 0 && m_expected_crc != crc )
             {
-                CPLError(CE_Failure, CPLE_FileIO, "CRC error. Got %X instead of %X", static_cast<unsigned int>(crc), static_cast<unsigned int>(m_expected_crc));
+                CPLError(CE_Failure, CPLE_FileIO,
+                         "CRC error. Got %X instead of %X",
+                         static_cast<unsigned int>(crc),
+                         static_cast<unsigned int>(m_expected_crc));
                 z_err = Z_DATA_ERROR;
             }
-            else if (m_expected_crc == 0)
+            else if( m_expected_crc == 0 )
             {
-                uLong read_crc = (unsigned long)getLong();
-                if (read_crc != crc)
+                const uLong read_crc =
+                    static_cast<unsigned long>(getLong());
+                if( read_crc != crc )
                 {
-                    CPLError(CE_Failure, CPLE_FileIO, "CRC error. Got %X instead of %X", static_cast<unsigned int>(crc), static_cast<unsigned int>(read_crc));
+                    CPLError(CE_Failure, CPLE_FileIO,
+                             "CRC error. Got %X instead of %X",
+                             static_cast<unsigned int>(crc),
+                             static_cast<unsigned int>(read_crc));
                     z_err = Z_DATA_ERROR;
                 }
                 else
                 {
-                    (void)getLong();
-                    /* The uncompressed length returned by above getlong() may be
-                    * different from out in case of concatenated .gz files.
-                    * Check for such files:
-                    */
+                    CPL_IGNORE_RET_VAL(getLong());
+                    // The uncompressed length returned by above getlong() may
+                    // be different from out in case of concatenated .gz files.
+                    // Check for such files:
                     check_header();
-                    if  (z_err == Z_OK) {
+                    if( z_err == Z_OK )
+                    {
                         inflateReset(& (stream));
                         crc = crc32(0L, NULL, 0);
                     }
                 }
             }
         }
-        if  (z_err != Z_OK || z_eof) break;
+        if( z_err != Z_OK || z_eof )
+            break;
     }
-    crc = crc32 (crc, pStart, (uInt) (stream.next_out - pStart));
+    crc = crc32(crc, pStart, static_cast<uInt>(stream.next_out - pStart));
 
-    if (len == stream.avail_out &&
-            (z_err == Z_DATA_ERROR || z_err == Z_ERRNO))
+    if( len == stream.avail_out &&
+        (z_err == Z_DATA_ERROR || z_err == Z_ERRNO) )
     {
         z_eof = 1;
         in = 0;
         CPL_VSIL_GZ_RETURN(0);
         return 0;
     }
-    if (ENABLE_DEBUG)
-        CPLDebug("GZIP", "Read return %d (z_err=%d, z_eof=%d)",
-                (int)((len - stream.avail_out) / nSize), z_err, z_eof);
-    return (int)(len - stream.avail_out) / nSize;
+#ifdef ENABLE_DEBUG
+    CPLDebug("GZIP", "Read return %d (z_err=%d, z_eof=%d)",
+             static_cast<int>((len - stream.avail_out) / nSize),
+             z_err, z_eof);
+#endif
+    return static_cast<int>(len - stream.avail_out) / nSize;
 }
 
 /************************************************************************/
@@ -944,18 +1115,18 @@ size_t VSIGZipHandle::Read( void * const buf, size_t const nSize, size_t const n
 
 uLong VSIGZipHandle::getLong ()
 {
-    uLong x = (uLong)get_byte();
+    uLong x = static_cast<uLong>(get_byte());
 
-    x += ((uLong)get_byte())<<8;
-    x += ((uLong)get_byte())<<16;
+    x += static_cast<uLong>(get_byte()) << 8;
+    x += static_cast<uLong>(get_byte()) << 16;
     const int c = get_byte();
-    if (c == EOF)
+    if( c == EOF )
     {
         z_err = Z_DATA_ERROR;
         return 0;
     }
-    x += ((uLong)c)<<24;
-    /* coverity[overflow_sink] */
+    x += static_cast<uLong>(c) << 24;
+    // coverity[overflow_sink]
     return x;
 }
 
@@ -963,11 +1134,12 @@ uLong VSIGZipHandle::getLong ()
 /*                              Write()                                 */
 /************************************************************************/
 
-size_t VSIGZipHandle::Write( CPL_UNUSED const void *pBuffer,
-                             CPL_UNUSED size_t nSize,
-                             CPL_UNUSED size_t nMemb )
+size_t VSIGZipHandle::Write( const void * /* pBuffer */,
+                             size_t /* nSize */,
+                             size_t /* nMemb */ )
 {
-    CPLError(CE_Failure, CPLE_NotSupported, "VSIFWriteL is not supported on GZip streams");
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "VSIFWriteL is not supported on GZip streams");
     return 0;
 }
 
@@ -975,10 +1147,11 @@ size_t VSIGZipHandle::Write( CPL_UNUSED const void *pBuffer,
 /*                               Eof()                                  */
 /************************************************************************/
 
-
 int VSIGZipHandle::Eof()
 {
-    if (ENABLE_DEBUG) CPLDebug("GZIP", "Eof()");
+#ifdef ENABLE_DEBUG
+    CPLDebug("GZIP", "Eof()");
+#endif
     return z_eof && in == 0;
 }
 
@@ -1000,7 +1173,6 @@ int VSIGZipHandle::Close()
     return 0;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                       VSIGZipWriteHandle                             */
@@ -1016,22 +1188,24 @@ class VSIGZipWriteHandle CPL_FINAL : public VSIVirtualHandle
     bool               bCompressActive;
     vsi_l_offset       nCurOffset;
     uLong              nCRC;
-    int                bRegularZLib;
-    int                bAutoCloseBaseHandle;
+    bool               bRegularZLib;
+    bool               bAutoCloseBaseHandle;
 
   public:
-
-    VSIGZipWriteHandle(VSIVirtualHandle* poBaseHandle, int bRegularZLib, int bAutoCloseBaseHandleIn);
-
-    ~VSIGZipWriteHandle();
-
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Flush();
-    virtual int       Close();
+    VSIGZipWriteHandle( VSIVirtualHandle* poBaseHandle, bool bRegularZLib,
+                        bool bAutoCloseBaseHandleIn );
+
+    virtual ~VSIGZipWriteHandle();
+
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb )
+        override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb )
+        override;
+    virtual int       Eof() override;
+    virtual int       Flush() override;
+    virtual int       Close() override;
 };
 
 /************************************************************************/
@@ -1039,17 +1213,17 @@ class VSIGZipWriteHandle CPL_FINAL : public VSIVirtualHandle
 /************************************************************************/
 
 VSIGZipWriteHandle::VSIGZipWriteHandle( VSIVirtualHandle *poBaseHandle,
-                                        int bRegularZLibIn,
-                                        int bAutoCloseBaseHandleIn )
-
+                                        bool bRegularZLibIn,
+                                        bool bAutoCloseBaseHandleIn ) :
+    m_poBaseHandle(poBaseHandle),
+    pabyInBuf(static_cast<Byte *>(CPLMalloc( Z_BUFSIZE ))),
+    pabyOutBuf(static_cast<Byte *>(CPLMalloc( Z_BUFSIZE ))),
+    bCompressActive(false),
+    nCurOffset(0),
+    nCRC(crc32(0L, NULL, 0)),
+    bRegularZLib(bRegularZLibIn),
+    bAutoCloseBaseHandle(bAutoCloseBaseHandleIn)
 {
-    nCurOffset = 0;
-
-    m_poBaseHandle = poBaseHandle;
-    bRegularZLib = bRegularZLibIn;
-    bAutoCloseBaseHandle = bAutoCloseBaseHandleIn;
-
-    nCRC = crc32(0L, NULL, 0);
     sStream.zalloc = (alloc_func)NULL;
     sStream.zfree = (free_func)NULL;
     sStream.opaque = (voidpf)NULL;
@@ -1057,26 +1231,24 @@ VSIGZipWriteHandle::VSIGZipWriteHandle( VSIVirtualHandle *poBaseHandle,
     sStream.next_out = NULL;
     sStream.avail_in = sStream.avail_out = 0;
 
-    pabyInBuf = (Byte *) CPLMalloc( Z_BUFSIZE );
-    sStream.next_in  = pabyInBuf;
-
-    pabyOutBuf = (Byte *) CPLMalloc( Z_BUFSIZE );
+    sStream.next_in = pabyInBuf;
 
     if( deflateInit2( &sStream, Z_DEFAULT_COMPRESSION,
-                      Z_DEFLATED, (bRegularZLib) ? MAX_WBITS : -MAX_WBITS, 8,
+                      Z_DEFLATED, bRegularZLib ? MAX_WBITS : -MAX_WBITS, 8,
                       Z_DEFAULT_STRATEGY ) != Z_OK )
+    {
         bCompressActive = false;
+    }
     else
     {
-        if (!bRegularZLib)
+        if( !bRegularZLib )
         {
-            char header[11];
+            char header[11] = {};
 
-            /* Write a very simple .gz header:
-            */
+            // Write a very simple .gz header:
             snprintf( header, sizeof(header),
                       "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
-                    Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/,
+                    Z_DEFLATED, 0 /*flags*/, 0, 0, 0, 0 /*time*/, 0 /*xflags*/,
                     0x03 );
             m_poBaseHandle->Write( header, 1, 10 );
         }
@@ -1093,7 +1265,9 @@ VSIVirtualHandle* VSICreateGZipWritable( VSIVirtualHandle* poBaseHandle,
                                          int bRegularZLibIn,
                                          int bAutoCloseBaseHandle )
 {
-    return new VSIGZipWriteHandle( poBaseHandle, bRegularZLibIn, bAutoCloseBaseHandle );
+    return new VSIGZipWriteHandle( poBaseHandle,
+                                   CPL_TO_BOOL(bRegularZLibIn),
+                                   CPL_TO_BOOL(bAutoCloseBaseHandle) );
 }
 
 /************************************************************************/
@@ -1121,11 +1295,12 @@ int VSIGZipWriteHandle::Close()
     if( bCompressActive )
     {
         sStream.next_out = pabyOutBuf;
-        sStream.avail_out = Z_BUFSIZE;
+        sStream.avail_out = static_cast<uInt>(Z_BUFSIZE);
 
-        deflate( &sStream, Z_FINISH );
+        CPL_IGNORE_RET_VAL( deflate( &sStream, Z_FINISH ) );
 
-        size_t nOutBytes = Z_BUFSIZE - sStream.avail_out;
+        const size_t nOutBytes =
+            static_cast<uInt>(Z_BUFSIZE) - sStream.avail_out;
 
         if( m_poBaseHandle->Write( pabyOutBuf, 1, nOutBytes ) < nOutBytes )
             return EOF;
@@ -1134,10 +1309,10 @@ int VSIGZipWriteHandle::Close()
 
         if( !bRegularZLib )
         {
-            GUInt32 anTrailer[2];
-
-            anTrailer[0] = CPL_LSBWORD32( static_cast<GUInt32>(nCRC) );
-            anTrailer[1] = CPL_LSBWORD32( (GUInt32) nCurOffset );
+            const GUInt32 anTrailer[2] = {
+                CPL_LSBWORD32(static_cast<GUInt32>(nCRC)),
+                CPL_LSBWORD32(static_cast<GUInt32>(nCurOffset))
+            };
 
             m_poBaseHandle->Write( anTrailer, 1, 8 );
         }
@@ -1159,11 +1334,12 @@ int VSIGZipWriteHandle::Close()
 /*                                Read()                                */
 /************************************************************************/
 
-size_t VSIGZipWriteHandle::Read( CPL_UNUSED void *pBuffer,
-                                 CPL_UNUSED size_t nSize,
-                                 CPL_UNUSED size_t nMemb )
+size_t VSIGZipWriteHandle::Read( void * /* pBuffer */,
+                                 size_t /* nSize */,
+                                 size_t /* nMemb */ )
 {
-    CPLError(CE_Failure, CPLE_NotSupported, "VSIFReadL is not supported on GZip write streams\n");
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "VSIFReadL is not supported on GZip write streams");
     return 0;
 }
 
@@ -1175,7 +1351,7 @@ size_t VSIGZipWriteHandle::Write( const void * const pBuffer,
                                   size_t const nSize, size_t const nMemb )
 
 {
-    int nBytesToWrite = (int) (nSize * nMemb);
+    int nBytesToWrite = static_cast<int>(nSize * nMemb);
     int nNextByte = 0;
 
     nCRC = crc32(nCRC, (const Bytef *)pBuffer, nBytesToWrite);
@@ -1186,13 +1362,14 @@ size_t VSIGZipWriteHandle::Write( const void * const pBuffer,
     while( nNextByte < nBytesToWrite )
     {
         sStream.next_out = pabyOutBuf;
-        sStream.avail_out = Z_BUFSIZE;
+        sStream.avail_out = static_cast<uInt>(Z_BUFSIZE);
 
         if( sStream.avail_in > 0 )
             memmove( pabyInBuf, sStream.next_in, sStream.avail_in );
 
-        int nNewBytesToWrite = MIN((int) (Z_BUFSIZE-sStream.avail_in),
-                                   nBytesToWrite - nNextByte);
+        const int nNewBytesToWrite = std::min(
+            static_cast<int>(Z_BUFSIZE-sStream.avail_in),
+            nBytesToWrite - nNextByte);
         memcpy( pabyInBuf + sStream.avail_in,
                 ((Byte *) pBuffer) + nNextByte,
                 nNewBytesToWrite );
@@ -1200,9 +1377,10 @@ size_t VSIGZipWriteHandle::Write( const void * const pBuffer,
         sStream.next_in = pabyInBuf;
         sStream.avail_in += nNewBytesToWrite;
 
-        deflate( &sStream, Z_NO_FLUSH );
+        CPL_IGNORE_RET_VAL( deflate( &sStream, Z_NO_FLUSH ) );
 
-        const size_t nOutBytes = Z_BUFSIZE - sStream.avail_out;
+        const size_t nOutBytes =
+            static_cast<uInt>(Z_BUFSIZE) - sStream.avail_out;
 
         if( nOutBytes > 0 )
         {
@@ -1253,7 +1431,7 @@ int VSIGZipWriteHandle::Seek( vsi_l_offset nOffset, int nWhence )
     else
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                 "Seeking on writable compressed data streams not supported." );
+                 "Seeking on writable compressed data streams not supported.");
 
         return -1;
     }
@@ -1269,14 +1447,12 @@ vsi_l_offset VSIGZipWriteHandle::Tell()
     return nCurOffset;
 }
 
-
 /************************************************************************/
 /* ==================================================================== */
 /*                       VSIGZipFilesystemHandler                       */
 /* ==================================================================== */
 /************************************************************************/
 
-
 /************************************************************************/
 /*                   VSIGZipFilesystemHandler()                         */
 /************************************************************************/
@@ -1294,7 +1470,7 @@ VSIGZipFilesystemHandler::VSIGZipFilesystemHandler()
 
 VSIGZipFilesystemHandler::~VSIGZipFilesystemHandler()
 {
-    if (poHandleLastGZipFile)
+    if( poHandleLastGZipFile )
         delete poHandleLastGZipFile;
 
     if( hMutex != NULL )
@@ -1306,20 +1482,22 @@ VSIGZipFilesystemHandler::~VSIGZipFilesystemHandler()
 /*                            SaveInfo()                                */
 /************************************************************************/
 
-void VSIGZipFilesystemHandler::SaveInfo(  VSIGZipHandle* poHandle )
+void VSIGZipFilesystemHandler::SaveInfo( VSIGZipHandle* poHandle )
 {
     CPLMutexHolder oHolder(&hMutex);
     SaveInfo_unlocked(poHandle);
 }
 
-void VSIGZipFilesystemHandler::SaveInfo_unlocked(  VSIGZipHandle* poHandle )
+void VSIGZipFilesystemHandler::SaveInfo_unlocked( VSIGZipHandle* poHandle )
 {
     CPLAssert(poHandle->GetBaseFileName() != NULL);
 
-    if (poHandleLastGZipFile &&
-        strcmp(poHandleLastGZipFile->GetBaseFileName(), poHandle->GetBaseFileName()) == 0)
+    if( poHandleLastGZipFile &&
+        strcmp(poHandleLastGZipFile->GetBaseFileName(),
+               poHandle->GetBaseFileName()) == 0 )
     {
-        if (poHandle->GetLastReadOffset() > poHandleLastGZipFile->GetLastReadOffset())
+        if( poHandle->GetLastReadOffset() >
+            poHandleLastGZipFile->GetLastReadOffset() )
         {
             VSIGZipHandle* poTmp = poHandleLastGZipFile;
             poHandleLastGZipFile = NULL;
@@ -1361,23 +1539,25 @@ VSIVirtualHandle* VSIGZipFilesystemHandler::Open( const char *pszFilename,
 /*      access?  If so, create a writable handle for the underlying     */
 /*      filename.                                                       */
 /* -------------------------------------------------------------------- */
-    if (strchr(pszAccess, 'w') != NULL )
+    if( strchr(pszAccess, 'w') != NULL )
     {
         if( strchr(pszAccess, '+') != NULL )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
-                     "Write+update (w+) not supported for /vsigzip, only read-only or write-only.");
+                     "Write+update (w+) not supported for /vsigzip, "
+                     "only read-only or write-only.");
             return NULL;
         }
 
         VSIVirtualHandle* poVirtualHandle =
             poFSHandler->Open( pszFilename + strlen("/vsigzip/"), "wb" );
 
-        if (poVirtualHandle == NULL)
+        if( poVirtualHandle == NULL )
             return NULL;
 
-        else
-            return new VSIGZipWriteHandle( poVirtualHandle, strchr(pszAccess, 'z') != NULL, TRUE );
+        return new VSIGZipWriteHandle( poVirtualHandle,
+                                       strchr(pszAccess, 'z') != NULL,
+                                       TRUE );
     }
 
 /* -------------------------------------------------------------------- */
@@ -1385,59 +1565,60 @@ VSIVirtualHandle* VSIGZipFilesystemHandler::Open( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 
     VSIGZipHandle* poGZIPHandle = OpenGZipReadOnly(pszFilename, pszAccess);
-    if (poGZIPHandle)
-        /* Wrap the VSIGZipHandle inside a buffered reader that will */
-        /* improve dramatically performance when doing small backward */
-        /* seeks */
+    if( poGZIPHandle )
+        // Wrap the VSIGZipHandle inside a buffered reader that will
+        // improve dramatically performance when doing small backward
+        // seeks.
         return VSICreateBufferedReaderHandle(poGZIPHandle);
-    else
-        return NULL;
+
+    return NULL;
 }
 
 /************************************************************************/
 /*                          OpenGZipReadOnly()                          */
 /************************************************************************/
 
-VSIGZipHandle* VSIGZipFilesystemHandler::OpenGZipReadOnly( const char *pszFilename,
-                                                      const char *pszAccess)
+VSIGZipHandle* VSIGZipFilesystemHandler::OpenGZipReadOnly(
+    const char *pszFilename, const char *pszAccess)
 {
     VSIFilesystemHandler *poFSHandler =
         VSIFileManager::GetHandler( pszFilename + strlen("/vsigzip/"));
 
     CPLMutexHolder oHolder(&hMutex);
 
-    if (poHandleLastGZipFile != NULL &&
-        strcmp(pszFilename + strlen("/vsigzip/"), poHandleLastGZipFile->GetBaseFileName()) == 0 &&
-        EQUAL(pszAccess, "rb"))
+    if( poHandleLastGZipFile != NULL &&
+        strcmp(pszFilename + strlen("/vsigzip/"),
+               poHandleLastGZipFile->GetBaseFileName()) == 0 &&
+        EQUAL(pszAccess, "rb") )
     {
         VSIGZipHandle* poHandle = poHandleLastGZipFile->Duplicate();
-        if (poHandle)
+        if( poHandle )
             return poHandle;
     }
 
-    unsigned char signature[2];
-
     VSIVirtualHandle* poVirtualHandle =
         poFSHandler->Open( pszFilename + strlen("/vsigzip/"), "rb" );
 
-    if (poVirtualHandle == NULL)
+    if( poVirtualHandle == NULL )
         return NULL;
 
-    if (VSIFReadL(signature, 1, 2, (VSILFILE*)poVirtualHandle) != 2 ||
-        signature[0] != gz_magic[0] || signature[1] != gz_magic[1])
+    unsigned char signature[2] = { '\0', '\0' };
+    if( VSIFReadL(signature, 1, 2, (VSILFILE*)poVirtualHandle) != 2 ||
+        signature[0] != gz_magic[0] || signature[1] != gz_magic[1] )
     {
         delete poVirtualHandle;
         return NULL;
     }
 
-    if (poHandleLastGZipFile)
+    if( poHandleLastGZipFile )
     {
         poHandleLastGZipFile->SaveInfo_unlocked();
         delete poHandleLastGZipFile;
         poHandleLastGZipFile = NULL;
     }
 
-    VSIGZipHandle* poHandle = new VSIGZipHandle(poVirtualHandle, pszFilename + strlen("/vsigzip/"));
+    VSIGZipHandle* poHandle =
+        new VSIGZipHandle(poVirtualHandle, pszFilename + strlen("/vsigzip/"));
     if( !(poHandle->IsInitOK()) )
     {
         delete poHandle;
@@ -1458,10 +1639,11 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename,
 
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
 
-    if (poHandleLastGZipFile != NULL &&
-        strcmp(pszFilename+strlen("/vsigzip/"), poHandleLastGZipFile->GetBaseFileName()) == 0)
+    if( poHandleLastGZipFile != NULL &&
+        strcmp(pszFilename+strlen("/vsigzip/"),
+               poHandleLastGZipFile->GetBaseFileName()) == 0 )
     {
-        if (poHandleLastGZipFile->GetUncompressedSize() != 0)
+        if( poHandleLastGZipFile->GetUncompressedSize() != 0 )
         {
             pStatBuf->st_mode = S_IFREG;
             pStatBuf->st_size = poHandleLastGZipFile->GetUncompressedSize();
@@ -1469,47 +1651,52 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename,
         }
     }
 
-    /* Begin by doing a stat on the real file */
+    // Begin by doing a stat on the real file.
     int ret = VSIStatExL(pszFilename+strlen("/vsigzip/"), pStatBuf, nFlags);
 
-    if (ret == 0 && (nFlags & VSI_STAT_SIZE_FLAG))
+    if( ret == 0 && (nFlags & VSI_STAT_SIZE_FLAG) )
     {
-        CPLString osCacheFilename(pszFilename+strlen("/vsigzip/"));
+        CPLString osCacheFilename(pszFilename + strlen("/vsigzip/"));
         osCacheFilename += ".properties";
 
-        /* Can we save a bit of seeking by using a .properties file ? */
+        // Can we save a bit of seeking by using a .properties file?
         VSILFILE* fpCacheLength = VSIFOpenL(osCacheFilename.c_str(), "rb");
-        if (fpCacheLength)
+        if( fpCacheLength )
         {
             const char* pszLine;
             GUIntBig nCompressedSize = 0;
             GUIntBig nUncompressedSize = 0;
-            while ((pszLine = CPLReadLineL(fpCacheLength)) != NULL)
+            while( (pszLine = CPLReadLineL(fpCacheLength)) != NULL )
             {
-                if (STARTS_WITH_CI(pszLine, "compressed_size="))
+                if( STARTS_WITH_CI(pszLine, "compressed_size=") )
                 {
-                    const char* pszBuffer = pszLine + strlen("compressed_size=");
+                    const char* pszBuffer =
+                        pszLine + strlen("compressed_size=");
                     nCompressedSize =
-                            CPLScanUIntBig(pszBuffer, static_cast<int>(strlen(pszBuffer)));
+                        CPLScanUIntBig(pszBuffer,
+                                       static_cast<int>(strlen(pszBuffer)));
                 }
-                else if (STARTS_WITH_CI(pszLine, "uncompressed_size="))
+                else if( STARTS_WITH_CI(pszLine, "uncompressed_size=") )
                 {
-                    const char* pszBuffer = pszLine + strlen("uncompressed_size=");
+                    const char* pszBuffer =
+                        pszLine + strlen("uncompressed_size=");
                     nUncompressedSize =
-                             CPLScanUIntBig(pszBuffer, static_cast<int>(strlen(pszBuffer)));
+                        CPLScanUIntBig(pszBuffer,
+                                       static_cast<int>(strlen(pszBuffer)));
                 }
             }
 
             CPL_IGNORE_RET_VAL(VSIFCloseL(fpCacheLength));
 
-            if (nCompressedSize == (GUIntBig) pStatBuf->st_size)
+            if( nCompressedSize == static_cast<GUIntBig>(pStatBuf->st_size) )
             {
-                /* Patch with the uncompressed size */
+                // Patch with the uncompressed size.
                 pStatBuf->st_size = nUncompressedSize;
 
                 VSIGZipHandle* poHandle =
-                    VSIGZipFilesystemHandler::OpenGZipReadOnly(pszFilename, "rb");
-                if (poHandle)
+                    VSIGZipFilesystemHandler::OpenGZipReadOnly(pszFilename,
+                                                               "rb");
+                if( poHandle )
                 {
                     poHandle->SetUncompressedSize(nUncompressedSize);
                     SaveInfo_unlocked(poHandle);
@@ -1520,16 +1707,17 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename,
             }
         }
 
-        /* No, then seek at the end of the data (slow) */
+        // No, then seek at the end of the data (slow).
         VSIGZipHandle* poHandle =
                 VSIGZipFilesystemHandler::OpenGZipReadOnly(pszFilename, "rb");
-        if (poHandle)
+        if( poHandle )
         {
             poHandle->Seek(0, SEEK_END);
-            const GUIntBig uncompressed_size = (GUIntBig) poHandle->Tell();
+            const GUIntBig uncompressed_size =
+                static_cast<GUIntBig>(poHandle->Tell());
             poHandle->Seek(0, SEEK_SET);
 
-            /* Patch with the uncompressed size */
+            // Patch with the uncompressed size.
             pStatBuf->st_size = uncompressed_size;
 
             delete poHandle;
@@ -1547,7 +1735,7 @@ int VSIGZipFilesystemHandler::Stat( const char *pszFilename,
 /*                               Unlink()                               */
 /************************************************************************/
 
-int VSIGZipFilesystemHandler::Unlink( CPL_UNUSED const char *pszFilename )
+int VSIGZipFilesystemHandler::Unlink( const char * /* pszFilename */ )
 {
     return -1;
 }
@@ -1556,8 +1744,8 @@ int VSIGZipFilesystemHandler::Unlink( CPL_UNUSED const char *pszFilename )
 /*                               Rename()                               */
 /************************************************************************/
 
-int VSIGZipFilesystemHandler::Rename( CPL_UNUSED const char *oldpath,
-                                      CPL_UNUSED const char *newpath )
+int VSIGZipFilesystemHandler::Rename( const char * /* oldpath */,
+                                      const char * /* newpath */ )
 {
     return -1;
 }
@@ -1566,8 +1754,8 @@ int VSIGZipFilesystemHandler::Rename( CPL_UNUSED const char *oldpath,
 /*                               Mkdir()                                */
 /************************************************************************/
 
-int VSIGZipFilesystemHandler::Mkdir( CPL_UNUSED const char *pszDirname,
-                                     CPL_UNUSED long nMode )
+int VSIGZipFilesystemHandler::Mkdir( const char * /* pszDirname */,
+                                     long /* nMode */ )
 {
     return -1;
 }
@@ -1575,7 +1763,7 @@ int VSIGZipFilesystemHandler::Mkdir( CPL_UNUSED const char *pszDirname,
 /*                               Rmdir()                                */
 /************************************************************************/
 
-int VSIGZipFilesystemHandler::Rmdir( CPL_UNUSED const char *pszDirname )
+int VSIGZipFilesystemHandler::Rmdir( const char * /* pszDirname */ )
 {
     return -1;
 }
@@ -1590,11 +1778,11 @@ char** VSIGZipFilesystemHandler::ReadDirEx( const char * /*pszDirname*/,
     return NULL;
 }
 
+//! @endcond
 /************************************************************************/
 /*                   VSIInstallGZipFileHandler()                        */
 /************************************************************************/
 
-
 /**
  * \brief Install GZip file system handler.
  *
@@ -1604,16 +1792,17 @@ char** VSIGZipFilesystemHandler::ReadDirEx( const char * /*pszDirname*/,
  * All portions of the file system underneath the base
  * path "/vsigzip/" will be handled by this driver.
  *
- * Additional documentation is to be found at http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
+ * Additional documentation is to be found at:
+ * http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
  *
  * @since GDAL 1.6.0
  */
 
-void VSIInstallGZipFileHandler(void)
+void VSIInstallGZipFileHandler()
 {
     VSIFileManager::InstallHandler( "/vsigzip/", new VSIGZipFilesystemHandler );
 }
-
+//! @cond Doxygen_Suppress
 
 /************************************************************************/
 /* ==================================================================== */
@@ -1626,7 +1815,7 @@ class VSIZipEntryFileOffset CPL_FINAL : public VSIArchiveEntryFileOffset
 public:
         unz_file_pos m_file_pos;
 
-        VSIZipEntryFileOffset(unz_file_pos file_pos)
+        explicit VSIZipEntryFileOffset( unz_file_pos file_pos )
         {
             m_file_pos.pos_in_zip_directory = file_pos.pos_in_zip_directory;
             m_file_pos.num_of_file = file_pos.num_of_file;
@@ -1651,28 +1840,29 @@ class VSIZipReader CPL_FINAL : public VSIArchiveReader
         void SetInfo();
 
     public:
-        VSIZipReader(const char* pszZipFileName);
+        explicit VSIZipReader( const char* pszZipFileName );
         virtual ~VSIZipReader();
 
         int IsValid() { return unzF != NULL; }
 
         unzFile GetUnzFileHandle() { return unzF; }
 
-        virtual int GotoFirstFile();
-        virtual int GotoNextFile();
-        virtual VSIArchiveEntryFileOffset* GetFileOffset() { return new VSIZipEntryFileOffset(file_pos); }
-        virtual GUIntBig GetFileSize() { return nNextFileSize; }
-        virtual CPLString GetFileName() { return osNextFileName; }
-        virtual GIntBig GetModifiedTime() { return nModifiedTime; }
-        virtual int GotoFileOffset(VSIArchiveEntryFileOffset* pOffset);
+        virtual int GotoFirstFile() override;
+        virtual int GotoNextFile() override;
+        virtual VSIArchiveEntryFileOffset* GetFileOffset() override
+            { return new VSIZipEntryFileOffset(file_pos); }
+        virtual GUIntBig GetFileSize() override { return nNextFileSize; }
+        virtual CPLString GetFileName() override { return osNextFileName; }
+        virtual GIntBig GetModifiedTime() override { return nModifiedTime; }
+        virtual int GotoFileOffset( VSIArchiveEntryFileOffset* pOffset )
+            override;
 };
 
-
 /************************************************************************/
 /*                           VSIZipReader()                             */
 /************************************************************************/
 
-VSIZipReader::VSIZipReader(const char* pszZipFileName) :
+VSIZipReader::VSIZipReader( const char* pszZipFileName ) :
     nNextFileSize(0),
     nModifiedTime(0)
 {
@@ -1687,7 +1877,7 @@ VSIZipReader::VSIZipReader(const char* pszZipFileName) :
 
 VSIZipReader::~VSIZipReader()
 {
-    if (unzF)
+    if( unzF )
         cpl_unzClose(unzF);
 }
 
@@ -1697,9 +1887,10 @@ VSIZipReader::~VSIZipReader()
 
 void VSIZipReader::SetInfo()
 {
-    char fileName[8193];
+    char fileName[8193] = {};
     unz_file_info file_info;
-    cpl_unzGetCurrentFileInfo (unzF, &file_info, fileName, sizeof(fileName) - 1, NULL, 0, NULL, 0);
+    cpl_unzGetCurrentFileInfo( unzF, &file_info, fileName, sizeof(fileName) - 1,
+                               NULL, 0, NULL, 0 );
     fileName[sizeof(fileName) - 1] = '\0';
     osNextFileName = fileName;
     nNextFileSize = file_info.uncompressed_size;
@@ -1709,10 +1900,11 @@ void VSIZipReader::SetInfo()
     brokendowntime.tm_hour = file_info.tmu_date.tm_hour;
     brokendowntime.tm_mday = file_info.tmu_date.tm_mday;
     brokendowntime.tm_mon = file_info.tmu_date.tm_mon;
-    brokendowntime.tm_year = file_info.tmu_date.tm_year - 1900; /* the minizip conventions differs from the Unix one */
+    // The minizip conventions differs from the Unix one.
+    brokendowntime.tm_year = file_info.tmu_date.tm_year - 1900;
     nModifiedTime = CPLYMDHMSToUnixTime(&brokendowntime);
 
-    cpl_unzGetFilePos(unzF, &this->file_pos);
+    cpl_unzGetFilePos(unzF, &file_pos);
 }
 
 /************************************************************************/
@@ -1721,7 +1913,7 @@ void VSIZipReader::SetInfo()
 
 int VSIZipReader::GotoNextFile()
 {
-    if (cpl_unzGoToNextFile(unzF) != UNZ_OK)
+    if( cpl_unzGoToNextFile(unzF) != UNZ_OK )
         return FALSE;
 
     SetInfo();
@@ -1735,7 +1927,7 @@ int VSIZipReader::GotoNextFile()
 
 int VSIZipReader::GotoFirstFile()
 {
-    if (cpl_unzGoToFirstFile(unzF) != UNZ_OK)
+    if( cpl_unzGoToFirstFile(unzF) != UNZ_OK )
         return FALSE;
 
     SetInfo();
@@ -1747,9 +1939,10 @@ int VSIZipReader::GotoFirstFile()
 /*                         GotoFileOffset()                             */
 /************************************************************************/
 
-int VSIZipReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset)
+int VSIZipReader::GotoFileOffset( VSIArchiveEntryFileOffset* pOffset )
 {
-    VSIZipEntryFileOffset* pZipEntryOffset = (VSIZipEntryFileOffset*)pOffset;
+    VSIZipEntryFileOffset* pZipEntryOffset =
+                        reinterpret_cast<VSIZipEntryFileOffset*>(pOffset);
     if( cpl_unzGoToFilePos(unzF, &(pZipEntryOffset->m_file_pos)) != UNZ_OK )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "GotoFileOffset failed");
@@ -1778,24 +1971,25 @@ class VSIZipFilesystemHandler CPL_FINAL : public VSIArchiveFilesystemHandler
 public:
     virtual ~VSIZipFilesystemHandler();
 
-    virtual const char* GetPrefix() { return "/vsizip"; }
-    virtual std::vector<CPLString> GetExtensions();
-    virtual VSIArchiveReader* CreateReader(const char* pszZipFileName);
-
-    using VSIFilesystemHandler::Open;
+    virtual const char* GetPrefix() override { return "/vsizip"; }
+    virtual std::vector<CPLString> GetExtensions() override;
+    virtual VSIArchiveReader* CreateReader( const char* pszZipFileName )
+        override;
 
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
+                                    bool bSetError ) override;
 
     virtual VSIVirtualHandle *OpenForWrite( const char *pszFilename,
                                             const char *pszAccess );
 
-    virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
+    virtual int      Mkdir( const char *pszDirname, long nMode ) override;
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles )
+        override;
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
 
-    void RemoveFromMap(VSIZipWriteHandle* poHandle);
+    void RemoveFromMap( VSIZipWriteHandle* poHandle );
 };
 
 /************************************************************************/
@@ -1810,30 +2004,31 @@ class VSIZipWriteHandle CPL_FINAL : public VSIVirtualHandle
    void                    *m_hZIP;
    VSIZipWriteHandle       *poChildInWriting;
    VSIZipWriteHandle       *m_poParent;
-   int                      bAutoDeleteParent;
+   bool                     bAutoDeleteParent;
    vsi_l_offset             nCurOffset;
 
   public:
-
-    VSIZipWriteHandle(VSIZipFilesystemHandler* poFS,
-                      void *hZIP,
-                      VSIZipWriteHandle* poParent);
-
-    ~VSIZipWriteHandle();
-
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Flush();
-    virtual int       Close();
-
-    void  StartNewFile(VSIZipWriteHandle* poSubFile);
+    VSIZipWriteHandle( VSIZipFilesystemHandler* poFS,
+                       void *hZIP,
+                       VSIZipWriteHandle* poParent );
+
+    virtual ~VSIZipWriteHandle();
+
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize,
+                            size_t nMemb ) override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize,
+                             size_t nMemb ) override;
+    virtual int       Eof() override;
+    virtual int       Flush() override;
+    virtual int       Close() override;
+
+    void  StartNewFile( VSIZipWriteHandle* poSubFile );
     void  StopCurrentFile();
     void* GetHandle() { return m_hZIP; }
     VSIZipWriteHandle* GetChildInWriting() { return poChildInWriting; };
-    void SetAutoDeleteParent() { bAutoDeleteParent = TRUE; }
+    void SetAutoDeleteParent() { bAutoDeleteParent = true; }
 };
 
 /************************************************************************/
@@ -1842,9 +2037,10 @@ class VSIZipWriteHandle CPL_FINAL : public VSIVirtualHandle
 
 VSIZipFilesystemHandler::~VSIZipFilesystemHandler()
 {
-    std::map<CPLString,VSIZipWriteHandle*>::const_iterator iter;
-
-    for( iter = oMapZipWriteHandles.begin(); iter != oMapZipWriteHandles.end(); ++iter )
+    for( std::map<CPLString, VSIZipWriteHandle*>::const_iterator iter =
+             oMapZipWriteHandles.begin();
+         iter != oMapZipWriteHandles.end();
+         ++iter )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "%s has not been closed",
                  iter->first.c_str());
@@ -1864,15 +2060,16 @@ std::vector<CPLString> VSIZipFilesystemHandler::GetExtensions()
     oList.push_back(".ods");
     oList.push_back(".xlsx");
 
-    /* Add to zip FS handler extensions array additional extensions */
-    /* listed in CPL_VSIL_ZIP_ALLOWED_EXTENSIONS config option. */
-    /* The extensions divided by comma */
+    // Add to zip FS handler extensions array additional extensions
+    // listed in CPL_VSIL_ZIP_ALLOWED_EXTENSIONS config option.
+    // The extensions are divided by commas.
     const char* pszAllowedExtensions =
         CPLGetConfigOption("CPL_VSIL_ZIP_ALLOWED_EXTENSIONS", NULL);
-    if (pszAllowedExtensions)
+    if( pszAllowedExtensions )
     {
-        char** papszExtensions = CSLTokenizeString2(pszAllowedExtensions, ", ", 0);
-        for (int i = 0; papszExtensions[i] != NULL; i++)
+        char** papszExtensions =
+            CSLTokenizeString2(pszAllowedExtensions, ", ", 0);
+        for( int i = 0; papszExtensions[i] != NULL; i++ )
         {
             oList.push_back(papszExtensions[i]);
         }
@@ -1886,17 +2083,18 @@ std::vector<CPLString> VSIZipFilesystemHandler::GetExtensions()
 /*                           CreateReader()                             */
 /************************************************************************/
 
-VSIArchiveReader* VSIZipFilesystemHandler::CreateReader(const char* pszZipFileName)
+VSIArchiveReader* VSIZipFilesystemHandler::CreateReader(
+    const char* pszZipFileName )
 {
     VSIZipReader* poReader = new VSIZipReader(pszZipFileName);
 
-    if (!poReader->IsValid())
+    if( !poReader->IsValid() )
     {
         delete poReader;
         return NULL;
     }
 
-    if (!poReader->GotoFirstFile())
+    if( !poReader->GotoFirstFile() )
     {
         delete poReader;
         return NULL;
@@ -1913,28 +2111,27 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
                                                  const char *pszAccess,
                                                  bool /* bSetError */ )
 {
-    CPLString osZipInFileName;
 
-    if (strchr(pszAccess, 'w') != NULL)
+    if( strchr(pszAccess, 'w') != NULL )
     {
         return OpenForWrite(pszFilename, pszAccess);
     }
 
-    if (strchr(pszAccess, '+') != NULL)
+    if( strchr(pszAccess, '+') != NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Random access not supported for /vsizip");
         return NULL;
     }
 
-    char* zipFilename
-        = SplitFilename(pszFilename, osZipInFileName, TRUE);
-    if (zipFilename == NULL)
+    CPLString osZipInFileName;
+    char* zipFilename = SplitFilename(pszFilename, osZipInFileName, TRUE);
+    if( zipFilename == NULL )
         return NULL;
 
     {
         CPLMutexHolder oHolder(&hMutex);
-        if (oMapZipWriteHandles.find(zipFilename) != oMapZipWriteHandles.end() )
+        if( oMapZipWriteHandles.find(zipFilename) != oMapZipWriteHandles.end() )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                     "Cannot read a zip file being written");
@@ -1944,7 +2141,7 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
     }
 
     VSIArchiveReader* poReader = OpenArchiveFile(zipFilename, osZipInFileName);
-    if (poReader == NULL)
+    if( poReader == NULL )
     {
         CPLFree(zipFilename);
         return NULL;
@@ -1959,17 +2156,19 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
     CPLFree(zipFilename);
     zipFilename = NULL;
 
-    if (poVirtualHandle == NULL)
+    if( poVirtualHandle == NULL )
     {
         delete poReader;
         return NULL;
     }
 
-    unzFile unzF = ((VSIZipReader*)poReader)->GetUnzFileHandle();
+    unzFile unzF = reinterpret_cast<VSIZipReader*>(poReader)->
+                                                            GetUnzFileHandle();
 
     if( cpl_unzOpenCurrentFile(unzF) != UNZ_OK )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "cpl_unzOpenCurrentFile() failed");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "cpl_unzOpenCurrentFile() failed");
         delete poReader;
         return NULL;
     }
@@ -1977,9 +2176,11 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
     uLong64 pos = cpl_unzGetCurrentFileZStreamPos(unzF);
 
     unz_file_info file_info;
-    if( cpl_unzGetCurrentFileInfo (unzF, &file_info, NULL, 0, NULL, 0, NULL, 0) != UNZ_OK )
+    if( cpl_unzGetCurrentFileInfo (unzF, &file_info, NULL, 0, NULL, 0, NULL, 0)
+        != UNZ_OK )
     {
-        CPLError(CE_Failure, CPLE_AppDefined, "cpl_unzGetCurrentFileInfo() failed");
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "cpl_unzGetCurrentFileInfo() failed");
         cpl_unzCloseCurrentFile(unzF);
         delete poReader;
         return NULL;
@@ -1989,22 +2190,23 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
 
     delete poReader;
 
-    VSIGZipHandle* poGZIPHandle = new VSIGZipHandle(poVirtualHandle,
-                             NULL,
-                             pos,
-                             file_info.compressed_size,
-                             file_info.uncompressed_size,
-                             file_info.crc,
-                             file_info.compression_method == 0);
+    VSIGZipHandle* poGZIPHandle =
+        new VSIGZipHandle(poVirtualHandle,
+                          NULL,
+                          pos,
+                          file_info.compressed_size,
+                          file_info.uncompressed_size,
+                          file_info.crc,
+                          file_info.compression_method == 0);
     if( !(poGZIPHandle->IsInitOK()) )
     {
         delete poGZIPHandle;
         return NULL;
     }
 
-    /* Wrap the VSIGZipHandle inside a buffered reader that will */
-    /* improve dramatically performance when doing small backward */
-    /* seeks */
+    // Wrap the VSIGZipHandle inside a buffered reader that will
+    // improve dramatically performance when doing small backward
+    // seeks.
     return VSICreateBufferedReaderHandle(poGZIPHandle);
 }
 
@@ -2012,13 +2214,14 @@ VSIVirtualHandle* VSIZipFilesystemHandler::Open( const char *pszFilename,
 /*                                Mkdir()                               */
 /************************************************************************/
 
-int VSIZipFilesystemHandler::Mkdir( const char *pszDirname, CPL_UNUSED long nMode )
+int VSIZipFilesystemHandler::Mkdir( const char *pszDirname,
+                                    long /* nMode */ )
 {
     CPLString osDirname = pszDirname;
-    if (osDirname.size() != 0 && osDirname[osDirname.size() - 1] != '/')
+    if( !osDirname.empty() && osDirname.back() != '/' )
         osDirname += "/";
     VSIVirtualHandle* poZIPHandle = OpenForWrite(osDirname, "wb");
-    if (poZIPHandle == NULL)
+    if( poZIPHandle == NULL )
         return -1;
     delete poZIPHandle;
     return 0;
@@ -2033,13 +2236,13 @@ char **VSIZipFilesystemHandler::ReadDirEx( const char *pszDirname,
 {
     CPLString osInArchiveSubDir;
     char* zipFilename = SplitFilename(pszDirname, osInArchiveSubDir, TRUE);
-    if (zipFilename == NULL)
+    if( zipFilename == NULL )
         return NULL;
 
     {
         CPLMutexHolder oHolder(&hMutex);
 
-        if (oMapZipWriteHandles.find(zipFilename) != oMapZipWriteHandles.end() )
+        if( oMapZipWriteHandles.find(zipFilename) != oMapZipWriteHandles.end() )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                     "Cannot read a zip file being written");
@@ -2052,7 +2255,6 @@ char **VSIZipFilesystemHandler::ReadDirEx( const char *pszDirname,
     return VSIArchiveFilesystemHandler::ReadDirEx(pszDirname, nMaxFiles);
 }
 
-
 /************************************************************************/
 /*                                 Stat()                               */
 /************************************************************************/
@@ -2065,13 +2267,13 @@ int VSIZipFilesystemHandler::Stat( const char *pszFilename,
     memset(pStatBuf, 0, sizeof(VSIStatBufL));
 
     char* zipFilename = SplitFilename(pszFilename, osInArchiveSubDir, TRUE);
-    if (zipFilename == NULL)
+    if( zipFilename == NULL )
         return -1;
 
     {
         CPLMutexHolder oHolder(&hMutex);
 
-        if (oMapZipWriteHandles.find(zipFilename) != oMapZipWriteHandles.end() )
+        if( oMapZipWriteHandles.find(zipFilename) != oMapZipWriteHandles.end() )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                     "Cannot read a zip file being written");
@@ -2088,15 +2290,16 @@ int VSIZipFilesystemHandler::Stat( const char *pszFilename,
 /*                             RemoveFromMap()                           */
 /************************************************************************/
 
-void VSIZipFilesystemHandler::RemoveFromMap(VSIZipWriteHandle* poHandle)
+void VSIZipFilesystemHandler::RemoveFromMap( VSIZipWriteHandle* poHandle )
 {
     CPLMutexHolder oHolder( &hMutex );
-    std::map<CPLString,VSIZipWriteHandle*>::iterator iter;
 
-    for( iter = oMapZipWriteHandles.begin();
-         iter != oMapZipWriteHandles.end(); ++iter )
+    for( std::map<CPLString, VSIZipWriteHandle*>::iterator iter =
+             oMapZipWriteHandles.begin();
+         iter != oMapZipWriteHandles.end();
+         ++iter )
     {
-        if (iter->second == poHandle)
+        if( iter->second == poHandle )
         {
             oMapZipWriteHandles.erase(iter);
             break;
@@ -2108,65 +2311,67 @@ void VSIZipFilesystemHandler::RemoveFromMap(VSIZipWriteHandle* poHandle)
 /*                             OpenForWrite()                           */
 /************************************************************************/
 
-VSIVirtualHandle* VSIZipFilesystemHandler::OpenForWrite( const char *pszFilename,
-                                                         const char *pszAccess)
+VSIVirtualHandle *
+VSIZipFilesystemHandler::OpenForWrite( const char *pszFilename,
+                                       const char *pszAccess )
 {
     CPLMutexHolder oHolder( &hMutex );
     return OpenForWrite_unlocked(pszFilename, pszAccess);
 }
 
-
-VSIVirtualHandle* VSIZipFilesystemHandler::OpenForWrite_unlocked( const char *pszFilename,
-                                                         const char *pszAccess)
+VSIVirtualHandle *
+VSIZipFilesystemHandler::OpenForWrite_unlocked( const char *pszFilename,
+                                                const char *pszAccess )
 {
     CPLString osZipInFileName;
 
     char* zipFilename = SplitFilename(pszFilename, osZipInFileName, FALSE);
-    if (zipFilename == NULL)
+    if( zipFilename == NULL )
         return NULL;
     CPLString osZipFilename = zipFilename;
     CPLFree(zipFilename);
     zipFilename = NULL;
 
-    /* Invalidate cached file list */
-    std::map<CPLString,VSIArchiveContent*>::iterator iter = oFileList.find(osZipFilename);
-    if (iter != oFileList.end())
+    // Invalidate cached file list.
+    std::map<CPLString,VSIArchiveContent*>::iterator iter =
+        oFileList.find(osZipFilename);
+    if( iter != oFileList.end() )
     {
         delete iter->second;
 
         oFileList.erase(iter);
     }
 
-    VSIZipWriteHandle* poZIPHandle;
-
-    if (oMapZipWriteHandles.find(osZipFilename) != oMapZipWriteHandles.end() )
+    if( oMapZipWriteHandles.find(osZipFilename) != oMapZipWriteHandles.end() )
     {
-        if (strchr(pszAccess, '+') != NULL)
+        if( strchr(pszAccess, '+') != NULL )
         {
             CPLError(CE_Failure, CPLE_AppDefined,
                     "Random access not supported for writable file in /vsizip");
             return NULL;
         }
 
-        poZIPHandle = oMapZipWriteHandles[osZipFilename];
+        VSIZipWriteHandle* poZIPHandle = oMapZipWriteHandles[osZipFilename];
 
-        if (poZIPHandle->GetChildInWriting() != NULL)
+        if( poZIPHandle->GetChildInWriting() != NULL )
         {
-            CPLError(CE_Failure, CPLE_AppDefined,
-                     "Cannot create %s while another file is being written in the .zip",
-                     osZipInFileName.c_str());
+            CPLError(
+                CE_Failure, CPLE_AppDefined,
+                "Cannot create %s while another file is being "
+                "written in the .zip",
+                osZipInFileName.c_str());
             return NULL;
         }
 
         poZIPHandle->StopCurrentFile();
 
-        /* Re-add path separator when creating directories */
+        // Re-add path separator when creating directories.
         char chLastChar = pszFilename[strlen(pszFilename) - 1];
-        if (chLastChar == '/' || chLastChar == '\\')
+        if( chLastChar == '/' || chLastChar == '\\' )
             osZipInFileName += chLastChar;
 
-        if (CPLCreateFileInZip(poZIPHandle->GetHandle(),
-                               osZipInFileName, NULL) != CE_None)
+        if( CPLCreateFileInZip(poZIPHandle->GetHandle(),
+                               osZipInFileName, NULL) != CE_None )
             return NULL;
 
         VSIZipWriteHandle* poChildHandle =
@@ -2179,28 +2384,28 @@ VSIVirtualHandle* VSIZipFilesystemHandler::OpenForWrite_unlocked( const char *ps
     else
     {
         char** papszOptions = NULL;
-        if ((strchr(pszAccess, '+') && osZipInFileName.size() == 0) ||
-             osZipInFileName.size() != 0)
+        if( (strchr(pszAccess, '+') && osZipInFileName.empty()) ||
+             !osZipInFileName.empty() )
         {
             VSIStatBufL sBuf;
-            if (VSIStatExL(osZipFilename, &sBuf, VSI_STAT_EXISTS_FLAG) == 0)
+            if( VSIStatExL(osZipFilename, &sBuf, VSI_STAT_EXISTS_FLAG) == 0 )
                 papszOptions = CSLAddNameValue(papszOptions, "APPEND", "TRUE");
         }
 
         void* hZIP = CPLCreateZip(osZipFilename, papszOptions);
         CSLDestroy(papszOptions);
 
-        if (hZIP == NULL)
+        if( hZIP == NULL )
             return NULL;
 
         oMapZipWriteHandles[osZipFilename] =
             new VSIZipWriteHandle(this, hZIP, NULL);
 
-        if (osZipInFileName.size() != 0)
+        if( !osZipInFileName.empty() )
         {
-            VSIZipWriteHandle* poRes =
-                (VSIZipWriteHandle*)OpenForWrite_unlocked(pszFilename, pszAccess);
-            if (poRes == NULL)
+            VSIZipWriteHandle* poRes = reinterpret_cast<VSIZipWriteHandle*>(
+                OpenForWrite_unlocked(pszFilename, pszAccess));
+            if( poRes == NULL )
             {
                 delete oMapZipWriteHandles[osZipFilename];
                 return NULL;
@@ -2215,22 +2420,20 @@ VSIVirtualHandle* VSIZipFilesystemHandler::OpenForWrite_unlocked( const char *ps
     }
 }
 
-
 /************************************************************************/
 /*                          VSIZipWriteHandle()                         */
 /************************************************************************/
 
-VSIZipWriteHandle::VSIZipWriteHandle(VSIZipFilesystemHandler* poFS,
-                                     void* hZIP,
-                                     VSIZipWriteHandle* poParent)
-{
-    m_poFS = poFS;
-    m_hZIP = hZIP;
-    m_poParent = poParent;
-    poChildInWriting = NULL;
-    bAutoDeleteParent = FALSE;
-    nCurOffset = 0;
-}
+VSIZipWriteHandle::VSIZipWriteHandle( VSIZipFilesystemHandler* poFS,
+                                      void* hZIP,
+                                      VSIZipWriteHandle* poParent ) :
+    m_poFS(poFS),
+    m_hZIP(hZIP),
+    poChildInWriting(NULL),
+    m_poParent(poParent),
+    bAutoDeleteParent(false),
+    nCurOffset(0)
+{}
 
 /************************************************************************/
 /*                         ~VSIZipWriteHandle()                         */
@@ -2270,9 +2473,9 @@ vsi_l_offset VSIZipWriteHandle::Tell()
 /*                               Read()                                 */
 /************************************************************************/
 
-size_t VSIZipWriteHandle::Read( CPL_UNUSED void *pBuffer,
-                                CPL_UNUSED size_t nSize,
-                                CPL_UNUSED size_t nMemb )
+size_t VSIZipWriteHandle::Read( void * /* pBuffer */,
+                                size_t /* nSize */,
+                                size_t /* nMemb */ )
 {
     CPLError(CE_Failure, CPLE_NotSupported,
              "VSIFReadL() is not supported on writable Zip files");
@@ -2283,19 +2486,23 @@ size_t VSIZipWriteHandle::Read( CPL_UNUSED void *pBuffer,
 /*                               Write()                                 */
 /************************************************************************/
 
-size_t    VSIZipWriteHandle::Write( const void *pBuffer, size_t nSize, size_t nMemb )
+size_t VSIZipWriteHandle::Write( const void *pBuffer, size_t nSize,
+                                 size_t nMemb )
 {
-    if (m_poParent == NULL)
+    if( m_poParent == NULL )
     {
-        CPLError(CE_Failure, CPLE_NotSupported,
-                 "VSIFWriteL() is not supported on main Zip file or closed subfiles");
+        CPLError(
+            CE_Failure, CPLE_NotSupported,
+            "VSIFWriteL() is not supported on "
+            "main Zip file or closed subfiles");
         return 0;
     }
 
-    if (CPLWriteFileInZip( m_poParent->m_hZIP, pBuffer, (int)(nSize * nMemb) ) != CE_None)
+    if( CPLWriteFileInZip( m_poParent->m_hZIP, pBuffer,
+                           static_cast<int>(nSize * nMemb) ) != CE_None )
         return 0;
 
-    nCurOffset +=(int) (nSize * nMemb);
+    nCurOffset += static_cast<int>(nSize * nMemb);
 
     return nMemb;
 }
@@ -2328,20 +2535,20 @@ int VSIZipWriteHandle::Flush()
 
 int VSIZipWriteHandle::Close()
 {
-    if (m_poParent)
+    if( m_poParent )
     {
         CPLCloseFileInZip(m_poParent->m_hZIP);
         m_poParent->poChildInWriting = NULL;
-        if (bAutoDeleteParent)
+        if( bAutoDeleteParent )
             delete m_poParent;
         m_poParent = NULL;
     }
-    if (poChildInWriting)
+    if( poChildInWriting )
     {
         poChildInWriting->Close();
         poChildInWriting = NULL;
     }
-    if (m_hZIP)
+    if( m_hZIP )
     {
         CPLCloseZip(m_hZIP);
         m_hZIP = NULL;
@@ -2356,9 +2563,9 @@ int VSIZipWriteHandle::Close()
 /*                           StopCurrentFile()                          */
 /************************************************************************/
 
-void  VSIZipWriteHandle::StopCurrentFile()
+void VSIZipWriteHandle::StopCurrentFile()
 {
-    if (poChildInWriting)
+    if( poChildInWriting )
         poChildInWriting->Close();
     poChildInWriting = NULL;
 }
@@ -2367,16 +2574,17 @@ void  VSIZipWriteHandle::StopCurrentFile()
 /*                           StartNewFile()                             */
 /************************************************************************/
 
-void  VSIZipWriteHandle::StartNewFile(VSIZipWriteHandle* poSubFile)
+void VSIZipWriteHandle::StartNewFile( VSIZipWriteHandle* poSubFile )
 {
     poChildInWriting = poSubFile;
 }
 
+//! @endcond
+
 /************************************************************************/
 /*                    VSIInstallZipFileHandler()                        */
 /************************************************************************/
 
-
 /**
  * \brief Install ZIP file system handler.
  *
@@ -2386,13 +2594,19 @@ void  VSIZipWriteHandle::StartNewFile(VSIZipWriteHandle* poSubFile)
  * All portions of the file system underneath the base path "/vsizip/" will be
  * handled by this driver.
  *
- * The syntax to open a file inside a zip file is /vsizip/path/to/the/file.zip/path/inside/the/zip/file
- * were path/to/the/file.zip is relative or absolute and path/inside/the/zip/file
- * is the relative path to the file inside the archive.
+ * The syntax to open a file inside a zip file is
+ * /vsizip/path/to/the/file.zip/path/inside/the/zip/file were
+ * path/to/the/file.zip is relative or absolute and path/inside/the/zip/file is
+ * the relative path to the file inside the archive.
+ *
+ * Starting with GDAL 2.2, an alternate syntax is available so as to enable
+ * chaining and not being dependent on .zip extension :
+ * /vsitar/{/path/to/the/archive}/path/inside/the/zip/file.
+ * Note that /path/to/the/archive may also itself this alternate syntax.
  *
- * If the path is absolute, it should begin with a / on a Unix-like OS (or C:\ on Windows),
- * so the line looks like /vsizip//home/gdal/...
- * For example gdalinfo /vsizip/myarchive.zip/subdir1/file1.tif
+ * If the path is absolute, it should begin with a / on a Unix-like OS (or C:\
+ * on Windows), so the line looks like /vsizip//home/gdal/...  For example
+ * gdalinfo /vsizip/myarchive.zip/subdir1/file1.tif
  *
  * Syntactic sugar : if the .zip file contains only one file located at its
  * root, just mentioning "/vsizip/path/to/the/file.zip" will work
@@ -2407,17 +2621,17 @@ void  VSIZipWriteHandle::StartNewFile(VSIZipWriteHandle* poSubFile)
  * zip file. Read and write operations cannot be interleaved : the new zip must
  * be closed before being re-opened for read.
  *
- * Additional documentation is to be found at http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
+ * Additional documentation is to be found at
+ * http://trac.osgeo.org/gdal/wiki/UserDocs/ReadInZip
  *
  * @since GDAL 1.6.0
  */
 
-void VSIInstallZipFileHandler(void)
+void VSIInstallZipFileHandler()
 {
     VSIFileManager::InstallHandler( "/vsizip/", new VSIZipFilesystemHandler() );
 }
 
-
 /************************************************************************/
 /*                         CPLZLibDeflate()                             */
 /************************************************************************/
@@ -2427,7 +2641,7 @@ void VSIInstallZipFileHandler(void)
  *
  * @param ptr input buffer.
  * @param nBytes size of input buffer in bytes.
- * @param nLevel ZLib compression level (-1 for default).
+ * @param nLevel ZLib compression level (-1 for default). Currently unused
  * @param outptr output buffer, or NULL to let the function allocate it.
  * @param nOutAvailableBytes size of output buffer if provided, or ignored.
  * @param pnOutBytes pointer to a size_t, where to store the size of the
@@ -2451,7 +2665,7 @@ void* CPLZLibDeflate( const void* ptr,
     strm.zfree = NULL;
     strm.opaque = NULL;
     int ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
-    if (ret != Z_OK)
+    if( ret != Z_OK )
     {
         if( pnOutBytes != NULL )
             *pnOutBytes = 0;
@@ -2528,7 +2742,7 @@ void* CPLZLibInflate( const void* ptr, size_t nBytes,
     strm.avail_in = static_cast<uInt>(nBytes);
     strm.next_in = (Bytef*) ptr;
     int ret = inflateInit(&strm);
-    if (ret != Z_OK)
+    if( ret != Z_OK )
     {
         if( pnOutBytes != NULL )
             *pnOutBytes = 0;
@@ -2536,11 +2750,11 @@ void* CPLZLibInflate( const void* ptr, size_t nBytes,
     }
 
     size_t nTmpSize = 0;
-    char* pszTmp;
+    char* pszTmp = NULL;
     if( outptr == NULL )
     {
         nTmpSize = 2 * nBytes;
-        pszTmp = (char*) VSIMalloc(nTmpSize + 1);
+        pszTmp = static_cast<char *>(VSIMalloc(nTmpSize + 1));
         if( pszTmp == NULL )
         {
             inflateEnd(&strm);
@@ -2551,14 +2765,14 @@ void* CPLZLibInflate( const void* ptr, size_t nBytes,
     }
     else
     {
-        pszTmp = (char*) outptr;
+        pszTmp = static_cast<char *>(outptr);
         nTmpSize = nOutAvailableBytes;
     }
 
     strm.avail_out = static_cast<uInt>(nTmpSize);
-    strm.next_out = (Bytef*) pszTmp;
+    strm.next_out = reinterpret_cast<Bytef *>(pszTmp);
 
-    while(true)
+    while( true )
     {
         ret = inflate(&strm, Z_FINISH);
         if( ret == Z_BUF_ERROR )
@@ -2573,7 +2787,8 @@ void* CPLZLibInflate( const void* ptr, size_t nBytes,
 
             size_t nAlreadyWritten = nTmpSize - strm.avail_out;
             nTmpSize = nTmpSize * 2;
-            char* pszTmpNew = (char*) VSIRealloc(pszTmp, nTmpSize + 1);
+            char* pszTmpNew =
+                static_cast<char *>(VSIRealloc(pszTmp, nTmpSize + 1));
             if( pszTmpNew == NULL )
             {
                 VSIFree(pszTmp);
@@ -2590,10 +2805,10 @@ void* CPLZLibInflate( const void* ptr, size_t nBytes,
             break;
     }
 
-    if (ret == Z_OK || ret == Z_STREAM_END)
+    if( ret == Z_OK || ret == Z_STREAM_END )
     {
         size_t nOutBytes = nTmpSize - strm.avail_out;
-        /* Nul-terminate if possible */
+        // Nul-terminate if possible.
         if( outptr != pszTmp || nOutBytes < nTmpSize )
             pszTmp[nOutBytes] = '\0';
         inflateEnd(&strm);
diff --git a/port/cpl_vsil_simple.cpp b/port/cpl_vsil_simple.cpp
index a224f27..db78ccd 100644
--- a/port/cpl_vsil_simple.cpp
+++ b/port/cpl_vsil_simple.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil_simple.cpp 10645 2007-01-18 02:22:39Z warmerdam $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Alternatve simplified implementation VSI*L File API that just
@@ -32,7 +31,7 @@
 
 #include "cpl_vsi.h"
 
-CPL_CVSID("$Id: cpl_vsil_simple.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
+CPL_CVSID("$Id: cpl_vsil_simple.cpp 36888 2016-12-15 19:26:17Z goatbar $");
 
 #ifdef WIN32
 #  include <sys/stat.h>
@@ -128,7 +127,7 @@ int VSIFCloseL( FILE * fp )
 int VSIFSeekL( FILE * fp, vsi_l_offset nOffset, int nWhence )
 
 {
-    return VSIFSeek( fp, (int) nOffset, nWhence );
+    return VSIFSeek(fp, static_ast<int>(nOffset), nWhence);
 }
 
 /************************************************************************/
@@ -138,7 +137,7 @@ int VSIFSeekL( FILE * fp, vsi_l_offset nOffset, int nWhence )
 vsi_l_offset VSIFTellL( FILE * fp )
 
 {
-    return (vsi_l_offset) VSIFTell( fp );
+    return static_cast<vsi_l_offset>(VSIFTell(fp));
 }
 
 /************************************************************************/
diff --git a/port/cpl_vsil_sparsefile.cpp b/port/cpl_vsil_sparsefile.cpp
index 74be14c..d996f20 100644
--- a/port/cpl_vsil_sparsefile.cpp
+++ b/port/cpl_vsil_sparsefile.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil_sparsefile.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of sparse file virtual io driver.
@@ -28,18 +27,36 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi_virtual.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
-#include "cpl_minixml.h"
+#include "cpl_port.h"
+#include "cpl_vsi.h"
+
+#include <cerrno>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
+
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <algorithm>
 #include <map>
+#include <memory>
+#include <vector>
 
-CPL_CVSID("$Id: cpl_vsil_sparsefile.cpp 33758 2016-03-21 09:06:22Z rouault $");
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_minixml.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi_virtual.h"
+
+CPL_CVSID("$Id: cpl_vsil_sparsefile.cpp 36990 2016-12-21 19:42:05Z goatbar $");
 
 class SFRegion {
 public:
     SFRegion() : fp(NULL), nDstOffset(0), nSrcOffset(0), nLength(0),
-                 byValue(0), bTriedOpen(FALSE) {}
+                 byValue(0), bTriedOpen(false) {}
 
     CPLString     osFilename;
     VSILFILE     *fp;
@@ -47,7 +64,7 @@ public:
     GUIntBig      nSrcOffset;
     GUIntBig      nLength;
     GByte         byValue;
-    int           bTriedOpen;
+    bool          bTriedOpen;
 };
 
 /************************************************************************/
@@ -63,19 +80,22 @@ class VSISparseFileHandle : public VSIVirtualHandle
     VSISparseFileFilesystemHandler* m_poFS;
 
   public:
-    VSISparseFileHandle(VSISparseFileFilesystemHandler* poFS) : m_poFS(poFS), nOverallLength(0), nCurOffset(0) {}
+    explicit VSISparseFileHandle(VSISparseFileFilesystemHandler* poFS) :
+                            m_poFS(poFS), nOverallLength(0), nCurOffset(0) {}
 
     GUIntBig           nOverallLength;
     GUIntBig           nCurOffset;
 
     std::vector<SFRegion> aoRegions;
 
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Close();
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize,
+                            size_t nMemb ) override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize,
+                             size_t nMemb ) override;
+    virtual int       Eof() override;
+    virtual int       Close() override;
 };
 
 /************************************************************************/
@@ -97,16 +117,18 @@ public:
                                     vsi_l_offset &nSparseFileOffset,
                                     vsi_l_offset &nSparseFileSize );
 
+    // TODO(schwehr): Fix VSISparseFileFilesystemHandler::Stat to not need using.
     using VSIFilesystemHandler::Open;
 
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
-    virtual int      Unlink( const char *pszFilename );
-    virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDir( const char *pszDirname );
+                                    bool bSetError ) override;
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
+    virtual int      Unlink( const char *pszFilename ) override;
+    virtual int      Mkdir( const char *pszDirname, long nMode ) override;
+    virtual int      Rmdir( const char *pszDirname ) override;
+    virtual char   **ReadDir( const char *pszDirname ) override;
 
     int              GetRecCounter() { return oRecOpenCount[CPLGetPID()]; }
     void             IncRecCounter() { oRecOpenCount[CPLGetPID()] ++; }
@@ -182,12 +204,13 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /*      Find what region we are in, searching linearly from the         */
 /*      start.                                                          */
 /* -------------------------------------------------------------------- */
-    unsigned int iRegion;
+    unsigned int iRegion = 0;  // Used after for.
 
-    for( iRegion = 0; iRegion < aoRegions.size(); iRegion++ )
+    for( ; iRegion < aoRegions.size(); iRegion++ )
     {
-        if( nCurOffset >= aoRegions[iRegion].nDstOffset
-            && nCurOffset < aoRegions[iRegion].nDstOffset + aoRegions[iRegion].nLength )
+        if( nCurOffset >= aoRegions[iRegion].nDstOffset &&
+            nCurOffset <
+                aoRegions[iRegion].nDstOffset + aoRegions[iRegion].nLength )
             break;
     }
 
@@ -208,18 +231,18 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /* -------------------------------------------------------------------- */
     size_t nReturnCount = nCount;
     GUIntBig nBytesRequested = nSize * nCount;
-    GUIntBig nBytesAvailable =
+    const GUIntBig nBytesAvailable =
         aoRegions[iRegion].nDstOffset + aoRegions[iRegion].nLength;
 
     if( nCurOffset + nBytesRequested > nBytesAvailable )
     {
-        size_t nExtraBytes =
-            (size_t) (nCurOffset + nBytesRequested - nBytesAvailable);
+        const size_t nExtraBytes =
+            static_cast<size_t>(nCurOffset + nBytesRequested - nBytesAvailable);
         // Recurse to get the rest of the request.
 
-        GUIntBig nCurOffsetSave = nCurOffset;
+        const GUIntBig nCurOffsetSave = nCurOffset;
         nCurOffset += nBytesRequested - nExtraBytes;
-        size_t nBytesRead =
+        const size_t nBytesRead =
             this->Read( ((char *) pBuffer) + nBytesRequested - nExtraBytes,
                         1, nExtraBytes );
         nCurOffset = nCurOffsetSave;
@@ -233,10 +256,10 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /* -------------------------------------------------------------------- */
 /*      Handle a constant region.                                       */
 /* -------------------------------------------------------------------- */
-    if( aoRegions[iRegion].osFilename.size() == 0 )
+    if( aoRegions[iRegion].osFilename.empty() )
     {
         memset( pBuffer, aoRegions[iRegion].byValue,
-                (size_t) nBytesRequested );
+                static_cast<size_t>(nBytesRequested) );
     }
 
 /* -------------------------------------------------------------------- */
@@ -255,7 +278,7 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
                     CPLDebug( "/vsisparse/", "Failed to open '%s'.",
                               aoRegions[iRegion].osFilename.c_str() );
                 }
-                aoRegions[iRegion].bTriedOpen = TRUE;
+                aoRegions[iRegion].bTriedOpen = true;
             }
             if( aoRegions[iRegion].fp == NULL )
             {
@@ -271,8 +294,9 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
             return 0;
 
         m_poFS->IncRecCounter();
-        size_t nBytesRead = VSIFReadL( pBuffer, 1, (size_t) nBytesRequested,
-                                       aoRegions[iRegion].fp );
+        const size_t nBytesRead =
+            VSIFReadL( pBuffer, 1, static_cast<size_t>(nBytesRequested),
+                       aoRegions[iRegion].fp );
         m_poFS->DecRecCounter();
 
         if( nBytesAvailable < nBytesRequested )
@@ -288,9 +312,9 @@ size_t VSISparseFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSISparseFileHandle::Write( CPL_UNUSED const void * pBuffer,
-                                   CPL_UNUSED size_t nSize,
-                                   CPL_UNUSED size_t nCount )
+size_t VSISparseFileHandle::Write( const void * /* pBuffer */,
+                                   size_t /* nSize */,
+                                   size_t /* nCount */ )
 {
     errno = EBADF;
     return 0;
@@ -316,19 +340,13 @@ int VSISparseFileHandle::Eof()
 /*                      VSISparseFileFilesystemHandler()                */
 /************************************************************************/
 
-VSISparseFileFilesystemHandler::VSISparseFileFilesystemHandler()
-
-{
-}
+VSISparseFileFilesystemHandler::VSISparseFileFilesystemHandler() {}
 
 /************************************************************************/
 /*                      ~VSISparseFileFilesystemHandler()               */
 /************************************************************************/
 
-VSISparseFileFilesystemHandler::~VSISparseFileFilesystemHandler()
-
-{
-}
+VSISparseFileFilesystemHandler::~VSISparseFileFilesystemHandler() {}
 
 /************************************************************************/
 /*                                Open()                                */
@@ -337,22 +355,22 @@ VSISparseFileFilesystemHandler::~VSISparseFileFilesystemHandler()
 VSIVirtualHandle *
 VSISparseFileFilesystemHandler::Open( const char *pszFilename,
                                       const char *pszAccess,
-                                      bool /* bSetError */)
+                                      bool /* bSetError */ )
 
 {
     CPLAssert( STARTS_WITH_CI(pszFilename, "/vsisparse/") );
 
-    if( !EQUAL(pszAccess,"r") && !EQUAL(pszAccess,"rb") )
+    if( !EQUAL(pszAccess, "r") && !EQUAL(pszAccess, "rb") )
     {
         errno = EACCES;
         return NULL;
     }
 
-    /* Arbitrary number */
+    // Arbitrary number.
     if( GetRecCounter() == 32 )
         return NULL;
 
-    CPLString osSparseFilePath = pszFilename + 11;
+    const CPLString osSparseFilePath = pszFilename + 11;
 
 /* -------------------------------------------------------------------- */
 /*      Does this file even exist?                                      */
@@ -378,17 +396,15 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename,
 /* -------------------------------------------------------------------- */
 /*      Translate the desired fields out of the XML tree.               */
 /* -------------------------------------------------------------------- */
-    CPLXMLNode *psRegion;
-
-    for( psRegion = psXMLRoot->psChild;
+    for( CPLXMLNode *psRegion = psXMLRoot->psChild;
          psRegion != NULL;
          psRegion = psRegion->psNext )
     {
         if( psRegion->eType != CXT_Element )
             continue;
 
-        if( !EQUAL(psRegion->pszValue,"SubfileRegion")
-            && !EQUAL(psRegion->pszValue,"ConstantRegion") )
+        if( !EQUAL(psRegion->pszValue, "SubfileRegion")
+            && !EQUAL(psRegion->pszValue, "ConstantRegion") )
             continue;
 
         SFRegion oRegion;
@@ -396,22 +412,24 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename,
         oRegion.osFilename = CPLGetXMLValue( psRegion, "Filename", "" );
         if( atoi(CPLGetXMLValue( psRegion, "Filename.relative", "0" )) != 0 )
         {
-            CPLString osSFPath = CPLGetPath(osSparseFilePath);
+            const CPLString osSFPath = CPLGetPath(osSparseFilePath);
             oRegion.osFilename = CPLFormFilename( osSFPath,
                                                   oRegion.osFilename, NULL );
         }
 
+        // TODO(schwehr): Symbolic constant and an explanation for 32.
         oRegion.nDstOffset =
-            CPLScanUIntBig( CPLGetXMLValue(psRegion,"DestinationOffset","0" ),
+            CPLScanUIntBig( CPLGetXMLValue(psRegion, "DestinationOffset", "0"),
                             32 );
 
         oRegion.nSrcOffset =
-            CPLScanUIntBig( CPLGetXMLValue(psRegion,"SourceOffset","0" ), 32);
+            CPLScanUIntBig( CPLGetXMLValue(psRegion, "SourceOffset", "0"), 32);
 
         oRegion.nLength =
-            CPLScanUIntBig( CPLGetXMLValue(psRegion,"RegionLength","0" ), 32);
+            CPLScanUIntBig( CPLGetXMLValue(psRegion, "RegionLength", "0"), 32);
 
-        oRegion.byValue = (GByte) atoi(CPLGetXMLValue(psRegion,"Value","0" ));
+        oRegion.byValue = static_cast<GByte>(
+            atoi(CPLGetXMLValue(psRegion, "Value", "0")));
 
         poHandle->aoRegions.push_back( oRegion );
     }
@@ -421,14 +439,15 @@ VSISparseFileFilesystemHandler::Open( const char *pszFilename,
 /*      explicit in file.                                               */
 /* -------------------------------------------------------------------- */
     poHandle->nOverallLength =
-        CPLScanUIntBig( CPLGetXMLValue(psXMLRoot,"Length","0" ), 32);
+        CPLScanUIntBig( CPLGetXMLValue(psXMLRoot, "Length", "0" ), 32);
     if( poHandle->nOverallLength == 0 )
     {
         for( unsigned int i = 0; i < poHandle->aoRegions.size(); i++ )
         {
-            poHandle->nOverallLength = MAX(poHandle->nOverallLength,
-                                           poHandle->aoRegions[i].nDstOffset
-                                           + poHandle->aoRegions[i].nLength);
+            poHandle->nOverallLength =
+                std::max(poHandle->nOverallLength,
+                         poHandle->aoRegions[i].nDstOffset
+                         + poHandle->aoRegions[i].nLength);
         }
     }
 
@@ -446,6 +465,8 @@ int VSISparseFileFilesystemHandler::Stat( const char * pszFilename,
                                           int nFlags )
 
 {
+    // TODO(schwehr): Fix this so that the using statement is not needed.
+    // Will just adding the bool for bSetError be okay?
     VSIVirtualHandle *poFile = Open( pszFilename, "r" );
 
     memset( psStatBuf, 0, sizeof(VSIStatBufL) );
@@ -454,11 +475,11 @@ int VSISparseFileFilesystemHandler::Stat( const char * pszFilename,
         return -1;
 
     poFile->Seek( 0, SEEK_END );
-    size_t nLength = (size_t) poFile->Tell();
+    const size_t nLength = static_cast<size_t>(poFile->Tell());
     delete poFile;
 
-    int nResult = VSIStatExL( pszFilename + strlen("/vsisparse/"),
-                            psStatBuf, nFlags );
+    const int nResult =
+        VSIStatExL( pszFilename + strlen("/vsisparse/"), psStatBuf, nFlags );
 
     psStatBuf->st_size = nLength;
 
@@ -469,7 +490,7 @@ int VSISparseFileFilesystemHandler::Stat( const char * pszFilename,
 /*                               Unlink()                               */
 /************************************************************************/
 
-int VSISparseFileFilesystemHandler::Unlink( CPL_UNUSED const char * pszFilename )
+int VSISparseFileFilesystemHandler::Unlink( const char * /* pszFilename */ )
 {
     errno = EACCES;
     return -1;
@@ -479,8 +500,8 @@ int VSISparseFileFilesystemHandler::Unlink( CPL_UNUSED const char * pszFilename
 /*                               Mkdir()                                */
 /************************************************************************/
 
-int VSISparseFileFilesystemHandler::Mkdir( CPL_UNUSED const char * pszPathname,
-                                           CPL_UNUSED long nMode )
+int VSISparseFileFilesystemHandler::Mkdir( const char * /* pszPathname */,
+                                           long /* nMode */ )
 {
     errno = EACCES;
     return -1;
@@ -490,7 +511,7 @@ int VSISparseFileFilesystemHandler::Mkdir( CPL_UNUSED const char * pszPathname,
 /*                               Rmdir()                                */
 /************************************************************************/
 
-int VSISparseFileFilesystemHandler::Rmdir( CPL_UNUSED const char * pszPathname )
+int VSISparseFileFilesystemHandler::Rmdir( const char * /* pszPathname */ )
 {
     errno = EACCES;
     return -1;
@@ -500,7 +521,7 @@ int VSISparseFileFilesystemHandler::Rmdir( CPL_UNUSED const char * pszPathname )
 /*                              ReadDir()                               */
 /************************************************************************/
 
-char **VSISparseFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath )
+char **VSISparseFileFilesystemHandler::ReadDir( const char * /* pszPath */ )
 {
     errno = EACCES;
     return NULL;
diff --git a/port/cpl_vsil_stdin.cpp b/port/cpl_vsil_stdin.cpp
index 9e8d754..f73a42c 100644
--- a/port/cpl_vsil_stdin.cpp
+++ b/port/cpl_vsil_stdin.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_vsil_stdin.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for stdin
@@ -27,26 +26,43 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+//! @cond Doxygen_Suppress
+
 #include "cpl_port.h"
+#include "cpl_vsi.h"
+
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include <algorithm>
+
+#include "cpl_conv.h"
 #include "cpl_error.h"
 #include "cpl_vsi_virtual.h"
 
-#include <stdio.h>
 #ifdef WIN32
 #include <io.h>
 #include <fcntl.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_stdin.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_stdin.cpp 36988 2016-12-21 18:14:06Z goatbar $");
 
-/* We buffer the first 1MB of standard input to enable drivers */
-/* to autodetect data. In the first MB, backward and forward seeking */
-/* is allowed, after only forward seeking will work */
+// We buffer the first 1MB of standard input to enable drivers
+// to autodetect data. In the first MB, backward and forward seeking
+// is allowed, after only forward seeking will work.
+// TODO(schwehr): Make BUFFER_SIZE a static const.
 #define BUFFER_SIZE (1024 * 1024)
 
-static GByte* pabyBuffer;
-static GUInt32 nBufferLen;
-static GUIntBig nRealPos;
+static GByte* pabyBuffer = NULL;
+static GUInt32 nBufferLen = 0;
+static GUIntBig nRealPos = 0;
 
 /************************************************************************/
 /*                           VSIStdinInit()                             */
@@ -54,12 +70,12 @@ static GUIntBig nRealPos;
 
 static void VSIStdinInit()
 {
-    if (pabyBuffer == NULL)
+    if( pabyBuffer == NULL )
     {
 #ifdef WIN32
         setmode( fileno( stdin ), O_BINARY );
 #endif
-        pabyBuffer = (GByte*)CPLMalloc(BUFFER_SIZE);
+        pabyBuffer = static_cast<GByte *>(CPLMalloc(BUFFER_SIZE));
     }
 }
 
@@ -75,13 +91,12 @@ public:
                               VSIStdinFilesystemHandler();
     virtual                  ~VSIStdinFilesystemHandler();
 
-    using VSIFilesystemHandler::Open;
-
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
+                                    bool bSetError ) override;
     virtual int               Stat( const char *pszFilename,
-                                    VSIStatBufL *pStatBuf, int nFlags );
+                                    VSIStatBufL *pStatBuf,
+                                    int nFlags ) override;
 };
 
 /************************************************************************/
@@ -100,12 +115,14 @@ class VSIStdinHandle CPL_FINAL : public VSIVirtualHandle
                       VSIStdinHandle();
     virtual          ~VSIStdinHandle();
 
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Close();
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize,
+                            size_t nMemb ) override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize,
+                             size_t nMemb ) override;
+    virtual int       Eof() override;
+    virtual int       Close() override;
 };
 
 /************************************************************************/
@@ -125,7 +142,6 @@ VSIStdinHandle::~VSIStdinHandle()
 {
 }
 
-
 /************************************************************************/
 /*                              ReadAndCache()                          */
 /************************************************************************/
@@ -136,9 +152,10 @@ int VSIStdinHandle::ReadAndCache( void* pBuffer, int nToRead )
 
     int nRead = static_cast<int>(fread(pBuffer, 1, nToRead, stdin));
 
-    if (nRealPos < BUFFER_SIZE)
+    if( nRealPos < BUFFER_SIZE )
     {
-        int nToCopy = MIN(BUFFER_SIZE - (int)nRealPos, nRead);
+        const int nToCopy =
+            std::min(BUFFER_SIZE - static_cast<int>(nRealPos), nRead);
         memcpy(pabyBuffer + nRealPos, pBuffer, nToCopy);
         nBufferLen += nToCopy;
     }
@@ -156,26 +173,27 @@ int VSIStdinHandle::ReadAndCache( void* pBuffer, int nToRead )
 int VSIStdinHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
 {
-    if (nWhence == SEEK_SET && nOffset == nCurOff)
+    if( nWhence == SEEK_SET && nOffset == nCurOff )
         return 0;
 
     VSIStdinInit();
-    if (nRealPos < BUFFER_SIZE )
+    if( nRealPos < BUFFER_SIZE )
     {
-        nRealPos += fread(pabyBuffer + nRealPos, 1, BUFFER_SIZE - (int)nRealPos, stdin);
+        nRealPos += fread(pabyBuffer + nRealPos, 1,
+                          BUFFER_SIZE - static_cast<int>(nRealPos), stdin);
         nBufferLen = static_cast<int>(nRealPos);
     }
 
-    if (nWhence == SEEK_END)
+    if( nWhence == SEEK_END )
     {
-        if (nOffset != 0)
+        if( nOffset != 0 )
         {
             CPLError(CE_Failure, CPLE_NotSupported,
                      "Seek(xx != 0, SEEK_END) unsupported on /vsistdin");
             return -1;
         }
 
-        if (nBufferLen < BUFFER_SIZE)
+        if( nBufferLen < BUFFER_SIZE )
         {
             nCurOff = nBufferLen;
             return 0;
@@ -186,38 +204,40 @@ int VSIStdinHandle::Seek( vsi_l_offset nOffset, int nWhence )
         return -1;
     }
 
-    if (nWhence == SEEK_CUR)
+    if( nWhence == SEEK_CUR )
         nOffset += nCurOff;
 
-    if (nRealPos > nBufferLen && nOffset < nRealPos)
+    if( nRealPos > nBufferLen && nOffset < nRealPos )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
-                "backward Seek() unsupported on /vsistdin above first MB");
+                 "backward Seek() unsupported on /vsistdin above first MB");
         return -1;
     }
 
-    if (nOffset < nBufferLen)
+    if( nOffset < nBufferLen )
     {
         nCurOff = nOffset;
         return 0;
     }
 
-    if (nOffset == nCurOff)
+    if( nOffset == nCurOff )
         return 0;
 
     CPLDebug("VSI", "Forward seek from " CPL_FRMT_GUIB " to " CPL_FRMT_GUIB,
              nCurOff, nOffset);
 
-    char abyTemp[8192];
+    char abyTemp[8192] = {};
     nCurOff = nRealPos;
-    while(true)
+    while( true )
     {
-        int nToRead = (int) MIN(8192, nOffset - nCurOff);
-        int nRead = ReadAndCache( abyTemp, nToRead );
+        const vsi_l_offset nMaxToRead = 8192;
+        const int nToRead = static_cast<int>(std::min(nMaxToRead,
+                                                      nOffset - nCurOff));
+        const int nRead = ReadAndCache(abyTemp, nToRead);
 
-        if (nRead < nToRead)
+        if( nRead < nToRead )
             return -1;
-        if (nToRead < 8192)
+        if( nToRead < 8192 )
             break;
     }
 
@@ -242,27 +262,28 @@ size_t VSIStdinHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 {
     VSIStdinInit();
 
-    if (nCurOff < nBufferLen)
+    if( nCurOff < nBufferLen )
     {
-        if (nCurOff + nSize * nCount < nBufferLen)
+        if( nCurOff + nSize * nCount < nBufferLen )
         {
             memcpy(pBuffer, pabyBuffer + nCurOff, nSize * nCount);
             nCurOff += nSize * nCount;
             return nCount;
         }
 
-        int nAlreadyCached = (int)(nBufferLen - nCurOff);
+        const int nAlreadyCached = static_cast<int>(nBufferLen - nCurOff);
         memcpy(pBuffer, pabyBuffer + nCurOff, nAlreadyCached);
 
         nCurOff += nAlreadyCached;
 
-        int nRead = ReadAndCache( (GByte*)pBuffer + nAlreadyCached,
-                                  (int)(nSize*nCount - nAlreadyCached) );
+        const int nRead =
+            ReadAndCache( static_cast<GByte *>(pBuffer) + nAlreadyCached,
+                          static_cast<int>(nSize*nCount - nAlreadyCached) );
 
-        return ((nRead + nAlreadyCached) / nSize);
+        return (nRead + nAlreadyCached) / nSize;
     }
 
-    int nRead = ReadAndCache( pBuffer, (int)(nSize * nCount) );
+    int nRead = ReadAndCache( pBuffer, static_cast<int>(nSize * nCount) );
     return nRead / nSize;
 }
 
@@ -270,9 +291,9 @@ size_t VSIStdinHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSIStdinHandle::Write( CPL_UNUSED const void * pBuffer,
-                              CPL_UNUSED size_t nSize,
-                              CPL_UNUSED size_t nCount )
+size_t VSIStdinHandle::Write( const void * /* pBuffer */,
+                              size_t /* nSize */,
+                              size_t /* nCount */ )
 {
     CPLError(CE_Failure, CPLE_NotSupported,
              "Write() unsupported on /vsistdin");
@@ -286,7 +307,7 @@ size_t VSIStdinHandle::Write( CPL_UNUSED const void * pBuffer,
 int VSIStdinHandle::Eof()
 
 {
-    if (nCurOff < nBufferLen)
+    if( nCurOff < nBufferLen )
         return FALSE;
     return feof(stdin);
 }
@@ -338,11 +359,11 @@ VSIStdinFilesystemHandler::Open( const char *pszFilename,
                                  bool /* bSetError */ )
 
 {
-    if (strcmp(pszFilename, "/vsistdin/") != 0)
+    if( strcmp(pszFilename, "/vsistdin/") != 0 )
         return NULL;
 
-    if ( strchr(pszAccess, 'w') != NULL ||
-         strchr(pszAccess, '+') != NULL )
+    if( strchr(pszAccess, 'w') != NULL ||
+        strchr(pszAccess, '+') != NULL )
     {
         CPLError(CE_Failure, CPLE_NotSupported,
                  "Write or update mode not supported on /vsistdin");
@@ -363,14 +384,15 @@ int VSIStdinFilesystemHandler::Stat( const char * pszFilename,
 {
     memset( pStatBuf, 0, sizeof(VSIStatBufL) );
 
-    if (strcmp(pszFilename, "/vsistdin/") != 0)
+    if( strcmp(pszFilename, "/vsistdin/") != 0 )
         return -1;
 
-    if ((nFlags & VSI_STAT_SIZE_FLAG))
+    if( nFlags & VSI_STAT_SIZE_FLAG )
     {
         VSIStdinInit();
-        if (nBufferLen == 0)
-            nRealPos = nBufferLen = static_cast<int>(fread(pabyBuffer, 1, BUFFER_SIZE, stdin));
+        if( nBufferLen == 0 )
+            nRealPos = nBufferLen =
+                static_cast<int>(fread(pabyBuffer, 1, BUFFER_SIZE, stdin));
 
         pStatBuf->st_size = nBufferLen;
     }
@@ -379,6 +401,8 @@ int VSIStdinFilesystemHandler::Stat( const char * pszFilename,
     return 0;
 }
 
+//! @endcond
+
 /************************************************************************/
 /*                       VSIInstallStdinHandler()                       */
 /************************************************************************/
@@ -397,5 +421,5 @@ int VSIStdinFilesystemHandler::Stat( const char * pszFilename,
 void VSIInstallStdinHandler()
 
 {
-    VSIFileManager::InstallHandler( "/vsistdin/", new VSIStdinFilesystemHandler );
+    VSIFileManager::InstallHandler("/vsistdin/", new VSIStdinFilesystemHandler);
 }
diff --git a/port/cpl_vsil_stdout.cpp b/port/cpl_vsil_stdout.cpp
index 708415e..253e4cc 100644
--- a/port/cpl_vsil_stdout.cpp
+++ b/port/cpl_vsil_stdout.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_vsil_stdout.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for stdout
@@ -28,16 +27,24 @@
  ****************************************************************************/
 
 #include "cpl_port.h"
+#include "cpl_vsi.h"
+
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
 #include "cpl_error.h"
 #include "cpl_vsi_virtual.h"
 
-#include <stdio.h>
 #ifdef WIN32
 #include <io.h>
 #include <fcntl.h>
 #endif
 
-CPL_CVSID("$Id: cpl_vsil_stdout.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_stdout.cpp 36990 2016-12-21 19:42:05Z goatbar $");
 
 static VSIWriteFunction pWriteFunction = fwrite;
 static FILE* pWriteStream = stdout;
@@ -60,6 +67,7 @@ void VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream )
     pWriteStream = stream;
 }
 
+//! @cond Doxygen_Suppress
 
 /************************************************************************/
 /* ==================================================================== */
@@ -70,12 +78,11 @@ void VSIStdoutSetRedirection( VSIWriteFunction pFct, FILE* stream )
 class VSIStdoutFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 public:
-    using VSIFilesystemHandler::Open;
-
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
+                                    bool bSetError ) override;
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
 };
 
 /************************************************************************/
@@ -91,13 +98,15 @@ class VSIStdoutHandle CPL_FINAL : public VSIVirtualHandle
   public:
                       VSIStdoutHandle() : m_nOffset(0) {}
 
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Flush();
-    virtual int       Close();
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb )
+        override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb )
+        override;
+    virtual int       Eof() override;
+    virtual int       Flush() override;
+    virtual int       Close() override;
 };
 
 /************************************************************************/
@@ -141,9 +150,9 @@ int VSIStdoutHandle::Flush()
 /*                                Read()                                */
 /************************************************************************/
 
-size_t VSIStdoutHandle::Read( CPL_UNUSED void * pBuffer,
-                              CPL_UNUSED size_t nSize,
-                              CPL_UNUSED size_t nCount )
+size_t VSIStdoutHandle::Read( void * /* pBuffer */,
+                              size_t /* nSize */,
+                              size_t /* nCount */ )
 {
     CPLError(CE_Failure, CPLE_NotSupported, "Read() unsupported on /vsistdout");
     return 0;
@@ -193,7 +202,7 @@ int VSIStdoutHandle::Close()
 /************************************************************************/
 
 VSIVirtualHandle *
-VSIStdoutFilesystemHandler::Open( CPL_UNUSED const char *pszFilename,
+VSIStdoutFilesystemHandler::Open( const char * /* pszFilename */,
                                   const char *pszAccess,
                                   bool /* bSetError */ )
 {
@@ -217,9 +226,9 @@ VSIStdoutFilesystemHandler::Open( CPL_UNUSED const char *pszFilename,
 /*                                Stat()                                */
 /************************************************************************/
 
-int VSIStdoutFilesystemHandler::Stat( CPL_UNUSED const char * pszFilename,
+int VSIStdoutFilesystemHandler::Stat( const char * /* pszFilename */,
                                       VSIStatBufL * pStatBuf,
-                                      CPL_UNUSED int nFlags )
+                                      int /* nFlags */ )
 
 {
     memset( pStatBuf, 0, sizeof(VSIStatBufL) );
@@ -227,8 +236,6 @@ int VSIStdoutFilesystemHandler::Stat( CPL_UNUSED const char * pszFilename,
     return -1;
 }
 
-
-
 /************************************************************************/
 /* ==================================================================== */
 /*                   VSIStdoutRedirectFilesystemHandler                 */
@@ -238,12 +245,11 @@ int VSIStdoutFilesystemHandler::Stat( CPL_UNUSED const char * pszFilename,
 class VSIStdoutRedirectFilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 public:
-    using VSIFilesystemHandler::Open;
-
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
+                                    bool bSetError ) override;
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
 };
 
 /************************************************************************/
@@ -256,16 +262,18 @@ class VSIStdoutRedirectHandle CPL_FINAL : public VSIVirtualHandle
 {
     VSIVirtualHandle* m_poHandle;
   public:
-                      VSIStdoutRedirectHandle(VSIVirtualHandle* poHandle);
-                     ~VSIStdoutRedirectHandle();
-
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Flush();
-    virtual int       Close();
+              explicit VSIStdoutRedirectHandle( VSIVirtualHandle* poHandle );
+              virtual ~VSIStdoutRedirectHandle();
+
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize,
+                            size_t nMemb ) override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb )
+        override;
+    virtual int       Eof() override;
+    virtual int       Flush() override;
+    virtual int       Close() override;
 };
 
 /************************************************************************/
@@ -290,10 +298,11 @@ VSIStdoutRedirectHandle::~VSIStdoutRedirectHandle()
 /*                                Seek()                                */
 /************************************************************************/
 
-int VSIStdoutRedirectHandle::Seek( CPL_UNUSED vsi_l_offset nOffset,
-                                   CPL_UNUSED int nWhence )
+int VSIStdoutRedirectHandle::Seek( vsi_l_offset /* nOffset */,
+                                   int /* nWhence */ )
 {
-    CPLError(CE_Failure, CPLE_NotSupported, "Seek() unsupported on /vsistdout_redirect");
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "Seek() unsupported on /vsistdout_redirect");
     return -1;
 }
 
@@ -320,11 +329,12 @@ int VSIStdoutRedirectHandle::Flush()
 /*                                Read()                                */
 /************************************************************************/
 
-size_t VSIStdoutRedirectHandle::Read( CPL_UNUSED void * pBuffer,
-                                      CPL_UNUSED size_t nSize,
-                                      CPL_UNUSED size_t nCount )
+size_t VSIStdoutRedirectHandle::Read( void * /* pBuffer */,
+                                      size_t /* nSize */,
+                                      size_t /* nCount */ )
 {
-    CPLError(CE_Failure, CPLE_NotSupported, "Read() unsupported on /vsistdout_redirect");
+    CPLError(CE_Failure, CPLE_NotSupported,
+             "Read() unsupported on /vsistdout_redirect");
     return 0;
 }
 
@@ -333,7 +343,7 @@ size_t VSIStdoutRedirectHandle::Read( CPL_UNUSED void * pBuffer,
 /************************************************************************/
 
 size_t VSIStdoutRedirectHandle::Write( const void * pBuffer, size_t nSize,
-                                  size_t nCount )
+                                       size_t nCount )
 
 {
     return m_poHandle->Write(pBuffer, nSize, nCount);
@@ -383,8 +393,8 @@ VSIStdoutRedirectFilesystemHandler::Open( const char *pszFilename,
         return NULL;
     }
 
-    VSIVirtualHandle* poHandle = (VSIVirtualHandle* )VSIFOpenL(
-            pszFilename + strlen("/vsistdout_redirect/"), pszAccess);
+    VSIVirtualHandle* poHandle = reinterpret_cast<VSIVirtualHandle*>(
+        VSIFOpenL(pszFilename + strlen("/vsistdout_redirect/"), pszAccess));
     if (poHandle == NULL)
         return NULL;
 
@@ -395,15 +405,17 @@ VSIStdoutRedirectFilesystemHandler::Open( const char *pszFilename,
 /*                                Stat()                                */
 /************************************************************************/
 
-int VSIStdoutRedirectFilesystemHandler::Stat( CPL_UNUSED const char * pszFilename,
+int VSIStdoutRedirectFilesystemHandler::Stat( const char * /* pszFilename */,
                                               VSIStatBufL * pStatBuf,
-                                              CPL_UNUSED int nFlags )
+                                              int /* nFlags */ )
 {
     memset( pStatBuf, 0, sizeof(VSIStatBufL) );
 
     return -1;
 }
 
+//! @endcond
+
 /************************************************************************/
 /*                       VSIInstallStdoutHandler()                      */
 /************************************************************************/
diff --git a/port/cpl_vsil_subfile.cpp b/port/cpl_vsil_subfile.cpp
index 10050e8..4da0aa2 100644
--- a/port/cpl_vsil_subfile.cpp
+++ b/port/cpl_vsil_subfile.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil_subfile.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  VSI Virtual File System
  * Purpose:  Implementation of subfile virtual IO functions.
@@ -28,12 +27,22 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_vsi_virtual.h"
-#include "cpl_string.h"
+#include "cpl_port.h"
+#include "cpl_vsi.h"
+
+#include <cerrno>
+#include <cstddef>
+#include <cstring>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include "cpl_conv.h"
 #include "cpl_multiproc.h"
-#include <map>
+#include "cpl_string.h"
+#include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_subfile.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_subfile.cpp 36990 2016-12-21 19:42:05Z goatbar $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -47,16 +56,19 @@ class VSISubFileHandle : public VSIVirtualHandle
     VSILFILE     *fp;
     vsi_l_offset  nSubregionOffset;
     vsi_l_offset  nSubregionSize;
-    int           bAtEOF;
-
-                      VSISubFileHandle() : fp(NULL), nSubregionOffset(0), nSubregionSize(0), bAtEOF(FALSE) {}
-
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Close();
+    bool          bAtEOF;
+
+                      VSISubFileHandle() : fp(NULL), nSubregionOffset(0),
+                                           nSubregionSize(0), bAtEOF(false) {}
+
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize,
+                            size_t nMemb ) override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize,
+                             size_t nMemb ) override;
+    virtual int       Eof() override;
+    virtual int       Close() override;
 };
 
 /************************************************************************/
@@ -71,21 +83,20 @@ public:
                      VSISubFileFilesystemHandler();
     virtual          ~VSISubFileFilesystemHandler();
 
-    int              DecomposePath( const char *pszPath,
+    static int              DecomposePath( const char *pszPath,
                                     CPLString &osFilename,
                                     vsi_l_offset &nSubFileOffset,
                                     vsi_l_offset &nSubFileSize );
 
-    using VSIFilesystemHandler::Open;
-
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
-    virtual int      Unlink( const char *pszFilename );
-    virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDir( const char *pszDirname );
+                                    bool bSetError ) override;
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                           int nFlags ) override;
+    virtual int      Unlink( const char *pszFilename ) override;
+    virtual int      Mkdir( const char *pszDirname, long nMode ) override;
+    virtual int      Rmdir( const char *pszDirname ) override;
+    virtual char   **ReadDir( const char *pszDirname ) override;
 };
 
 /************************************************************************/
@@ -114,7 +125,7 @@ int VSISubFileHandle::Close()
 int VSISubFileHandle::Seek( vsi_l_offset nOffset, int nWhence )
 
 {
-    bAtEOF = FALSE;
+    bAtEOF = false;
 
     if( nWhence == SEEK_SET )
         nOffset += nSubregionOffset;
@@ -156,32 +167,42 @@ vsi_l_offset VSISubFileHandle::Tell()
 size_t VSISubFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 
 {
-    size_t nRet;
-    if (nSubregionSize == 0)
+    size_t nRet = 0;
+    if( nSubregionSize == 0 )
+    {
         nRet = VSIFReadL( pBuffer, nSize, nCount, fp );
+    }
     else
     {
-        if (nSize == 0)
+        if( nSize == 0 )
             return 0;
 
-        vsi_l_offset nCurOffset = VSIFTellL(fp);
-        if (nCurOffset >= nSubregionOffset + nSubregionSize)
+        const vsi_l_offset nCurOffset = VSIFTellL(fp);
+        if( nCurOffset >= nSubregionOffset + nSubregionSize )
         {
-            bAtEOF = TRUE;
+            bAtEOF = true;
             return 0;
         }
 
-        size_t nByteToRead = nSize * nCount;
-        if (nCurOffset + nByteToRead > nSubregionOffset + nSubregionSize)
+        const size_t nByteToRead = nSize * nCount;
+        if( nCurOffset + nByteToRead > nSubregionOffset + nSubregionSize )
         {
-            int nRead = (int)VSIFReadL( pBuffer, 1, (size_t)(nSubregionOffset + nSubregionSize - nCurOffset), fp);
+            const int nRead = static_cast<int>(
+                VSIFReadL(
+                    pBuffer, 1,
+                    static_cast<size_t>(nSubregionOffset + nSubregionSize -
+                                        nCurOffset), fp));
             nRet = nRead / nSize;
         }
         else
+        {
             nRet = VSIFReadL( pBuffer, nSize, nCount, fp );
+        }
     }
+
     if( nRet < nCount )
-        bAtEOF = TRUE;
+        bAtEOF = true;
+
     return nRet;
 }
 
@@ -189,29 +210,35 @@ size_t VSISubFileHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /*                               Write()                                */
 /************************************************************************/
 
-size_t VSISubFileHandle::Write( const void * pBuffer, size_t nSize, size_t nCount )
+size_t VSISubFileHandle::Write( const void * pBuffer, size_t nSize,
+                                size_t nCount )
 
 {
-    bAtEOF = FALSE;
+    bAtEOF = false;
 
-    if (nSubregionSize == 0)
+    if( nSubregionSize == 0 )
         return VSIFWriteL( pBuffer, nSize, nCount, fp );
 
-    if (nSize == 0)
+    if( nSize == 0 )
         return 0;
 
-    vsi_l_offset nCurOffset = VSIFTellL(fp);
-    if (nCurOffset >= nSubregionOffset + nSubregionSize)
+    const vsi_l_offset nCurOffset = VSIFTellL(fp);
+    if( nCurOffset >= nSubregionOffset + nSubregionSize )
         return 0;
 
-    size_t nByteToWrite = nSize * nCount;
-    if (nCurOffset + nByteToWrite > nSubregionOffset + nSubregionSize)
+    const size_t nByteToWrite = nSize * nCount;
+    if( nCurOffset + nByteToWrite > nSubregionOffset + nSubregionSize )
     {
-        int nWritten = (int)VSIFWriteL( pBuffer, 1, (size_t)(nSubregionOffset + nSubregionSize - nCurOffset), fp);
+        const int nWritten = static_cast<int>(
+            VSIFWriteL(
+                pBuffer, 1,
+                static_cast<size_t>(nSubregionOffset + nSubregionSize -
+                                     nCurOffset),
+                fp));
         return nWritten / nSize;
     }
-    else
-        return VSIFWriteL( pBuffer, nSize, nCount, fp );
+
+    return VSIFWriteL( pBuffer, nSize, nCount, fp );
 }
 
 /************************************************************************/
@@ -234,19 +261,13 @@ int VSISubFileHandle::Eof()
 /*                      VSISubFileFilesystemHandler()                   */
 /************************************************************************/
 
-VSISubFileFilesystemHandler::VSISubFileFilesystemHandler()
-
-{
-}
+VSISubFileFilesystemHandler::VSISubFileFilesystemHandler() {}
 
 /************************************************************************/
 /*                      ~VSISubFileFilesystemHandler()                  */
 /************************************************************************/
 
-VSISubFileFilesystemHandler::~VSISubFileFilesystemHandler()
-
-{
-}
+VSISubFileFilesystemHandler::~VSISubFileFilesystemHandler() {}
 
 /************************************************************************/
 /*                           DecomposePath()                            */
@@ -269,18 +290,22 @@ VSISubFileFilesystemHandler::DecomposePath( const char *pszPath,
     nSubFileOffset = 0;
     nSubFileSize = 0;
 
-    nSubFileOffset = CPLScanUIntBig(pszPath+12, static_cast<int>(strlen(pszPath + 12)));
+    nSubFileOffset =
+        CPLScanUIntBig(pszPath+12, static_cast<int>(strlen(pszPath + 12)));
     for( int i = 12; pszPath[i] != '\0'; i++ )
     {
         if( pszPath[i] == '_' && nSubFileSize == 0 )
         {
-            /* -1 is sometimes passed to mean that we don't know the file size */
-            /* for example when creating a JPEG2000 datastream in a NITF file */
-            /* Transform it into 0  for correct behaviour of Read(), Write() and Eof() */
-            if (pszPath[i + 1] == '-')
+            // -1 is sometimes passed to mean that we don't know the file size
+            // for example when creating a JPEG2000 datastream in a NITF file
+            // Transform it into 0 for correct behaviour of Read(), Write() and
+            // Eof().
+            if( pszPath[i + 1] == '-' )
                 nSubFileSize = 0;
             else
-                nSubFileSize = CPLScanUIntBig(pszPath + i + 1, static_cast<int>(strlen(pszPath + i + 1)));
+                nSubFileSize =
+                    CPLScanUIntBig(pszPath + i + 1,
+                                   static_cast<int>(strlen(pszPath + i + 1)));
         }
         else if( pszPath[i] == ',' )
         {
@@ -289,7 +314,7 @@ VSISubFileFilesystemHandler::DecomposePath( const char *pszPath,
         }
         else if( pszPath[i] == '/' )
         {
-            // missing comma!
+            // Missing comma!
             return FALSE;
         }
     }
@@ -297,7 +322,6 @@ VSISubFileFilesystemHandler::DecomposePath( const char *pszPath,
     return FALSE;
 }
 
-
 /************************************************************************/
 /*                                Open()                                */
 /************************************************************************/
@@ -309,7 +333,8 @@ VSISubFileFilesystemHandler::Open( const char *pszFilename,
 
 {
     CPLString osSubFilePath;
-    vsi_l_offset nOff, nSize;
+    vsi_l_offset nOff = 0;
+    vsi_l_offset nSize = 0;
 
     if( !DecomposePath( pszFilename, osSubFilePath, nOff, nSize ) )
     {
@@ -360,7 +385,8 @@ int VSISubFileFilesystemHandler::Stat( const char * pszFilename,
 
 {
     CPLString osSubFilePath;
-    vsi_l_offset nOff, nSize;
+    vsi_l_offset nOff = 0;
+    vsi_l_offset nSize = 0;
 
     memset( psStatBuf, 0, sizeof(VSIStatBufL) );
 
@@ -370,7 +396,7 @@ int VSISubFileFilesystemHandler::Stat( const char * pszFilename,
         return -1;
     }
 
-    int nResult = VSIStatExL( osSubFilePath, psStatBuf, nFlags );
+    const int nResult = VSIStatExL( osSubFilePath, psStatBuf, nFlags );
 
     if( nResult == 0 )
     {
@@ -387,7 +413,7 @@ int VSISubFileFilesystemHandler::Stat( const char * pszFilename,
 /*                               Unlink()                               */
 /************************************************************************/
 
-int VSISubFileFilesystemHandler::Unlink( CPL_UNUSED const char * pszFilename )
+int VSISubFileFilesystemHandler::Unlink( const char * /* pszFilename */ )
 {
     errno = EACCES;
     return -1;
@@ -397,8 +423,8 @@ int VSISubFileFilesystemHandler::Unlink( CPL_UNUSED const char * pszFilename )
 /*                               Mkdir()                                */
 /************************************************************************/
 
-int VSISubFileFilesystemHandler::Mkdir( CPL_UNUSED const char * pszPathname,
-                                        CPL_UNUSED long nMode )
+int VSISubFileFilesystemHandler::Mkdir( const char * /* pszPathname */,
+                                        long /* nMode */ )
 {
     errno = EACCES;
     return -1;
@@ -408,7 +434,7 @@ int VSISubFileFilesystemHandler::Mkdir( CPL_UNUSED const char * pszPathname,
 /*                               Rmdir()                                */
 /************************************************************************/
 
-int VSISubFileFilesystemHandler::Rmdir( CPL_UNUSED const char * pszPathname )
+int VSISubFileFilesystemHandler::Rmdir( const char * /* pszPathname */ )
 
 {
     errno = EACCES;
@@ -419,7 +445,7 @@ int VSISubFileFilesystemHandler::Rmdir( CPL_UNUSED const char * pszPathname )
 /*                              ReadDir()                               */
 /************************************************************************/
 
-char **VSISubFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath )
+char **VSISubFileFilesystemHandler::ReadDir( const char * /* pszPath */ )
 {
     errno = EACCES;
     return NULL;
@@ -439,13 +465,13 @@ char **VSISubFileFilesystemHandler::ReadDir( CPL_UNUSED const char *pszPath )
  * A special form of the filename is used to indicate a subportion
  * of another file:
  *
- *   /vsisubfile/<offset>[_<size>],<filename>
+ *   /vsisubfile/<offset>[_<size>],<filename>
  *
- * The size parameter is optional.  Without it the remainder of the
- * file from the start offset as treated as part of the subfile.  Otherwise
- * only <size> bytes from <offset> are treated as part of the subfile.
- * The <filename> portion may be a relative or absolute path using normal
- * rules.   The <offset> and <size> values are in bytes.
+ * The size parameter is optional.  Without it the remainder of the file from
+ * the start offset as treated as part of the subfile.  Otherwise only
+ * <size> bytes from <offset> are treated as part of the subfile.
+ * The <filename> portion may be a relative or absolute path using normal
+ * rules.  The <offset> and <size> values are in bytes.
  *
  * eg.
  *   /vsisubfile/1000_3000,/data/abc.ntf
diff --git a/port/cpl_vsil_tar.cpp b/port/cpl_vsil_tar.cpp
index fc0aa12..31d8ac2 100644
--- a/port/cpl_vsil_tar.cpp
+++ b/port/cpl_vsil_tar.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsil_tar.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for tar files (.tar).
@@ -27,9 +26,26 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+//! @cond Doxygen_Suppress
+
+#include "cpl_port.h"
+#include "cpl_vsi.h"
+
+#include <cstring>
+
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
+
+#include <string>
+#include <vector>
+
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_tar.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_tar.cpp 37001 2016-12-22 18:09:05Z goatbar $");
 
 #if defined(DEBUG) && !defined(HAVE_FUZZER_FRIENDLY_ARCHIVE)
 /* This is a completely custom archive format that is rather inefficient */
@@ -53,7 +69,7 @@ public:
         CPLString m_osFileName;
 #endif
 
-        VSITarEntryFileOffset(GUIntBig nOffset)
+        explicit VSITarEntryFileOffset(GUIntBig nOffset)
         {
             m_nOffset = nOffset;
 #ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
@@ -62,11 +78,11 @@ public:
         }
 
 #ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
-        VSITarEntryFileOffset(GUIntBig nOffset, GUIntBig nFileSize, const CPLString& osFileName)
+        VSITarEntryFileOffset(GUIntBig nOffset, GUIntBig nFileSize, const CPLString& osFileName) :
+            m_nOffset(nOffset),
+            m_nFileSize(nFileSize),
+            m_osFileName(osFileName)
         {
-            m_nOffset = nOffset;
-            m_nFileSize = nFileSize;
-            m_osFileName = osFileName;
         }
 #endif
 };
@@ -94,21 +110,20 @@ class VSITarReader CPL_FINAL : public VSIArchiveReader
 #endif
 
     public:
-        VSITarReader(const char* pszTarFileName);
+        explicit VSITarReader(const char* pszTarFileName);
         virtual ~VSITarReader();
 
         int IsValid() { return fp != NULL; }
 
-        virtual int GotoFirstFile();
-        virtual int GotoNextFile();
-        virtual VSIArchiveEntryFileOffset* GetFileOffset();
-        virtual GUIntBig GetFileSize() { return nNextFileSize; }
-        virtual CPLString GetFileName() { return osNextFileName; }
-        virtual GIntBig GetModifiedTime() { return nModifiedTime; }
-        virtual int GotoFileOffset(VSIArchiveEntryFileOffset* pOffset);
+        virtual int GotoFirstFile() override;
+        virtual int GotoNextFile() override;
+        virtual VSIArchiveEntryFileOffset* GetFileOffset() override;
+        virtual GUIntBig GetFileSize() override { return nNextFileSize; }
+        virtual CPLString GetFileName() override { return osNextFileName; }
+        virtual GIntBig GetModifiedTime() override { return nModifiedTime; }
+        virtual int GotoFileOffset(VSIArchiveEntryFileOffset* pOffset) override;
 };
 
-
 /************************************************************************/
 /*                               VSIIsTGZ()                             */
 /************************************************************************/
@@ -126,6 +141,9 @@ static bool VSIIsTGZ(const char* pszFilename)
 /*                           VSITarReader()                             */
 /************************************************************************/
 
+// TODO(schwehr): What is this ***NEWFILE*** thing?
+// And make it a symbolic constant.
+
 VSITarReader::VSITarReader(const char* pszTarFileName) :
     nCurOffset(0),
     nNextFileSize(0),
@@ -134,16 +152,18 @@ VSITarReader::VSITarReader(const char* pszTarFileName) :
     fp = VSIFOpenL(pszTarFileName, "rb");
 #ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
     m_bIsFuzzerFriendly = false;
+    m_abyBuffer[0] = '\0';
     m_abyBufferIdx = 0;
     m_abyBufferSize = 0;
     m_nCurOffsetOld = 0;
     if( fp != NULL )
     {
-        GByte abySignature[24];
+        GByte abySignature[24] = {};
         m_bIsFuzzerFriendly =
             (VSIFReadL(abySignature, 1, 24, fp) == 24) &&
             (memcmp(abySignature, "FUZZER_FRIENDLY_ARCHIVE\n", 24) == 0 ||
-             memcmp(abySignature, "***NEWFILE***:", strlen("***NEWFILE***:")) == 0);
+             memcmp(abySignature, "***NEWFILE***:",
+                    strlen("***NEWFILE***:")) == 0);
         CPL_IGNORE_RET_VAL(VSIFSeekL(fp, 0, SEEK_SET));
     }
 #endif
@@ -168,7 +188,8 @@ VSIArchiveEntryFileOffset* VSITarReader::GetFileOffset()
 #ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
     if( m_bIsFuzzerFriendly )
     {
-        return new VSITarEntryFileOffset(nCurOffset, nNextFileSize, osNextFileName);
+        return new VSITarEntryFileOffset(nCurOffset, nNextFileSize,
+                                         osNextFileName);
     }
 #endif
     return new VSITarEntryFileOffset(nCurOffset);
@@ -189,7 +210,8 @@ int VSITarReader::GotoNextFile()
             {
                 if( m_abyBufferSize == 0 )
                 {
-                    m_abyBufferSize = static_cast<int>(VSIFReadL(m_abyBuffer, 1, 2048, fp));
+                    m_abyBufferSize = static_cast<int>(
+                        VSIFReadL(m_abyBuffer, 1, 2048, fp));
                     if( m_abyBufferSize == 0 )
                         return FALSE;
                 }
@@ -212,16 +234,25 @@ int VSITarReader::GotoNextFile()
                         return FALSE;
                     }
                     memcpy(m_abyBuffer, m_abyBuffer + 1024, 1024);
-                    m_abyBufferSize = static_cast<int>(VSIFReadL(m_abyBuffer + 1024, 1, 1024, fp));
+                    m_abyBufferSize = static_cast<int>(
+                         VSIFReadL(m_abyBuffer + 1024, 1, 1024, fp));
                     if( m_abyBufferSize == 0 )
                         return FALSE;
                     m_abyBufferIdx = 0;
                     m_abyBufferSize += 1024;
                 }
             }
-            if( ((m_abyBufferSize == 2048 && m_abyBufferIdx < m_abyBufferSize - ((int)strlen("***NEWFILE***:")+64)) ||
-                 (m_abyBufferSize < 2048 && m_abyBufferIdx < m_abyBufferSize - ((int)strlen("***NEWFILE***:")+2))) &&
-                memcmp( m_abyBuffer + m_abyBufferIdx, "***NEWFILE***:", strlen("***NEWFILE***:")) == 0 )
+            if( ((m_abyBufferSize == 2048 &&
+                  m_abyBufferIdx <
+                  m_abyBufferSize -
+                  (static_cast<int>(strlen("***NEWFILE***:")) + 64)) ||
+                 (m_abyBufferSize < 2048 &&
+                  m_abyBufferIdx < m_abyBufferSize -
+                  (static_cast<int>(strlen("***NEWFILE***:"))+2))) &&
+                m_abyBufferIdx >= 0 &&  // Make CSA happy, but useless.
+                memcmp(m_abyBuffer + m_abyBufferIdx,
+                       "***NEWFILE***:",
+                       strlen("***NEWFILE***:")) == 0 )
             {
                 if( nCurOffset > 0 && nCurOffset != m_nCurOffsetOld )
                 {
@@ -235,26 +266,32 @@ int VSITarReader::GotoNextFile()
                         return TRUE;
                     }
                 }
-                m_abyBufferIdx += (int)strlen("***NEWFILE***:");
-                int nFilenameStartIdx = m_abyBufferIdx;
-                for(; m_abyBuffer[m_abyBufferIdx] != '\n' && m_abyBufferIdx < m_abyBufferSize; ++m_abyBufferIdx)
+                m_abyBufferIdx += static_cast<int>(strlen("***NEWFILE***:"));
+                const int nFilenameStartIdx = m_abyBufferIdx;
+                for( ; m_abyBufferIdx < m_abyBufferSize &&
+                       m_abyBuffer[m_abyBufferIdx] != '\n';
+                     ++m_abyBufferIdx)
                 {
-                    /* do nothing */
+                    // Do nothing.
                 }
                 if( m_abyBufferIdx < m_abyBufferSize )
                 {
-                    osNextFileName.assign( (const char*)(m_abyBuffer + nFilenameStartIdx), m_abyBufferIdx - nFilenameStartIdx );
+                    osNextFileName.assign(
+                        (const char*)(m_abyBuffer + nFilenameStartIdx),
+                        m_abyBufferIdx - nFilenameStartIdx);
                     nCurOffset = VSIFTellL(fp);
                     nCurOffset -= m_abyBufferSize;
                     nCurOffset += m_abyBufferIdx + 1;
                 }
             }
             else
-                m_abyBufferIdx ++;
+            {
+                m_abyBufferIdx++;
+            }
         }
     }
 #endif
-    char abyHeader[512];
+    char abyHeader[512] = {};
     if (VSIFReadL(abyHeader, 512, 1, fp) != 1)
         return FALSE;
 
@@ -282,7 +319,7 @@ int VSITarReader::GotoNextFile()
     nCurOffset = VSIFTellL(fp);
 
     const GUIntBig nBytesToSkip = ((nNextFileSize + 511) / 512) * 512;
-    if( nBytesToSkip > (~((GUIntBig)0)) - nCurOffset )
+    if( nBytesToSkip > (~(static_cast<GUIntBig>(0))) - nCurOffset )
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Bad .tar structure");
         return FALSE;
@@ -317,9 +354,10 @@ int VSITarReader::GotoFirstFile()
 /*                         GotoFileOffset()                             */
 /************************************************************************/
 
-int VSITarReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset)
+int VSITarReader::GotoFileOffset( VSIArchiveEntryFileOffset* pOffset )
 {
-    VSITarEntryFileOffset* pTarEntryOffset = (VSITarEntryFileOffset*)pOffset;
+    VSITarEntryFileOffset* pTarEntryOffset =
+        static_cast<VSITarEntryFileOffset*>(pOffset);
 #ifdef HAVE_FUZZER_FRIENDLY_ARCHIVE
     if( m_bIsFuzzerFriendly )
     {
@@ -348,18 +386,15 @@ int VSITarReader::GotoFileOffset(VSIArchiveEntryFileOffset* pOffset)
 class VSITarFilesystemHandler CPL_FINAL : public VSIArchiveFilesystemHandler
 {
 public:
-    virtual const char* GetPrefix() { return "/vsitar"; }
-    virtual std::vector<CPLString> GetExtensions();
-    virtual VSIArchiveReader* CreateReader(const char* pszTarFileName);
-
-    using VSIFilesystemHandler::Open;
+    virtual const char* GetPrefix() override { return "/vsitar"; }
+    virtual std::vector<CPLString> GetExtensions() override;
+    virtual VSIArchiveReader* CreateReader(const char* pszTarFileName) override;
 
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
+                                    bool bSetError ) override;
 };
 
-
 /************************************************************************/
 /*                          GetExtensions()                             */
 /************************************************************************/
@@ -437,7 +472,8 @@ VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename,
     }
 
     CPLString osSubFileName("/vsisubfile/");
-    VSITarEntryFileOffset* pOffset = (VSITarEntryFileOffset*) poReader->GetFileOffset();
+    VSITarEntryFileOffset* pOffset = reinterpret_cast<VSITarEntryFileOffset*>(
+                                                    poReader->GetFileOffset());
     osSubFileName += CPLString().Printf(CPL_FRMT_GUIB, pOffset->m_nOffset);
     osSubFileName += "_";
     osSubFileName += CPLString().Printf(CPL_FRMT_GUIB, poReader->GetFileSize());
@@ -457,9 +493,11 @@ VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename,
     CPLFree(tarFilename);
     tarFilename = NULL;
 
-    return (VSIVirtualHandle* )VSIFOpenL(osSubFileName, "rb");
+    return reinterpret_cast<VSIVirtualHandle*>(VSIFOpenL(osSubFileName, "rb"));
 }
 
+//! @endcond
+
 /************************************************************************/
 /*                    VSIInstallTarFileHandler()                        */
 /************************************************************************/
@@ -473,10 +511,15 @@ VSIVirtualHandle* VSITarFilesystemHandler::Open( const char *pszFilename,
  * All portions of the file system underneath the base path "/vsitar/" will be
  * handled by this driver.
  *
- * The syntax to open a file inside a zip file is /vsitar/path/to/the/file.tar/path/inside/the/tar/file
+ * The syntax to open a file inside a tar file is /vsitar/path/to/the/file.tar/path/inside/the/tar/file
  * were path/to/the/file.tar is relative or absolute and path/inside/the/tar/file
  * is the relative path to the file inside the archive.
  *
+ * Starting with GDAL 2.2, an alternate syntax is available so as to enable
+ * chaining and not being dependent on .tar extension :
+ * /vsitar/{/path/to/the/archive}/path/inside/the/tar/file. Note that /path/to/the/archive
+ * may also itself this alternate syntax.
+ *
  * If the path is absolute, it should begin with a / on a Unix-like OS (or C:\ on Windows),
  * so the line looks like /vsitar//home/gdal/...
  * For example gdalinfo /vsitar/myarchive.tar/subdir1/file1.tif
diff --git a/port/cpl_vsil_unix_stdio_64.cpp b/port/cpl_vsil_unix_stdio_64.cpp
index f634ad5..05a6b02 100644
--- a/port/cpl_vsil_unix_stdio_64.cpp
+++ b/port/cpl_vsil_unix_stdio_64.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_vsil_unix_stdio_64.cpp 36874 2016-12-15 01:53:28Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for Unix platforms with fseek64()
@@ -36,6 +35,8 @@
  *
  ****************************************************************************/
 
+//! @cond Doxygen_Suppress
+
 //#define VSI_COUNT_BYTES_READ
 
 // Some unusual filesystems do not work if _FORTIFY_SOURCE in GCC or
@@ -51,22 +52,36 @@
 
 #if !defined(WIN32)
 
+#include "cpl_vsi.h"
 #include "cpl_vsi_virtual.h"
-#include "cpl_vsi_error.h"
-#include "cpl_string.h"
-#include "cpl_multiproc.h"
 
-#include <unistd.h>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#include <dirent.h>
+#include <errno.h>
+#if HAVE_FCNTL_H
+#  include <fcntl.h>
+#endif
 #include <sys/stat.h>
 #ifdef HAVE_STATVFS
 #include <sys/statvfs.h>
 #endif
 #include <sys/types.h>
-#include <dirent.h>
-#include <errno.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #include <new>
 
-CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 36874 2016-12-15 01:53:28Z rouault $");
+#include "cpl_config.h"
+#include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_multiproc.h"
+#include "cpl_string.h"
+#include "cpl_vsi_error.h"
+
+CPL_CVSID("$Id: cpl_vsil_unix_stdio_64.cpp 36990 2016-12-21 19:42:05Z goatbar $");
 
 #if defined(UNIX_STDIO_64)
 
@@ -131,19 +146,18 @@ public:
     virtual                  ~VSIUnixStdioFilesystemHandler();
 #endif
 
-    using VSIFilesystemHandler::Open;
-
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
-                           int nFlags );
-    virtual int      Unlink( const char *pszFilename );
-    virtual int      Rename( const char *oldpath, const char *newpath );
-    virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
-    virtual GIntBig  GetDiskFreeSpace( const char* pszDirname );
+                                    bool bSetError ) override;
+    virtual int     Stat( const char *pszFilename, VSIStatBufL *pStatBuf,
+                          int nFlags ) override;
+    virtual int     Unlink( const char *pszFilename ) override;
+    virtual int     Rename( const char *oldpath, const char *newpath ) override;
+    virtual int     Mkdir( const char *pszDirname, long nMode ) override;
+    virtual int     Rmdir( const char *pszDirname ) override;
+    virtual char  **ReadDirEx( const char *pszDirname, int nMaxFiles ) override;
+    virtual GIntBig GetDiskFreeSpace( const char* pszDirname ) override;
+    virtual int SupportsSparseFiles( const char* pszPath ) override;
 
 #ifdef VSI_COUNT_BYTES_READ
     void             AddToTotal(vsi_l_offset nBytes);
@@ -164,27 +178,35 @@ class VSIUnixStdioHandle CPL_FINAL : public VSIVirtualHandle
     bool          bLastOpWrite;
     bool          bLastOpRead;
     bool          bAtEOF;
+    // In a+ mode, disable any optimization since the behaviour of the file
+    // pointer on Mac and other BSD system is to have a seek() to the end of
+    // file and thus a call to our Seek(0, SEEK_SET) before a read will be a
+    // no-op.
+    bool          bModeAppendReadWrite;
 #ifdef VSI_COUNT_BYTES_READ
     vsi_l_offset  nTotalBytesRead;
     VSIUnixStdioFilesystemHandler *poFS;
 #endif
   public:
-                      VSIUnixStdioHandle(VSIUnixStdioFilesystemHandler *poFSIn,
-                                         FILE* fpIn, bool bReadOnlyIn);
-
-    virtual int       Seek( vsi_l_offset nOffsetIn, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Flush();
-    virtual int       Close();
-    virtual int       Truncate( vsi_l_offset nNewSize );
-    virtual void     *GetNativeFileDescriptor() {
+                   VSIUnixStdioHandle( VSIUnixStdioFilesystemHandler *poFSIn,
+                                       FILE* fpIn, bool bReadOnlyIn,
+                                       bool bModeAppendReadWriteIn );
+
+    virtual int    Seek( vsi_l_offset nOffsetIn, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t Read( void *pBuffer, size_t nSize, size_t nMemb ) override;
+    virtual size_t Write( const void *pBuffer, size_t nSize,
+                          size_t nMemb ) override;
+    virtual int    Eof() override;
+    virtual int    Flush() override;
+    virtual int    Close() override;
+    virtual int    Truncate( vsi_l_offset nNewSize ) override;
+    virtual void  *GetNativeFileDescriptor() override {
         return reinterpret_cast<void *>(static_cast<size_t>(fileno(fp))); }
+    virtual VSIRangeStatus GetRangeStatus( vsi_l_offset nOffset,
+                                           vsi_l_offset nLength ) override;
 };
 
-
 /************************************************************************/
 /*                       VSIUnixStdioHandle()                           */
 /************************************************************************/
@@ -194,13 +216,15 @@ VSIUnixStdioHandle::VSIUnixStdioHandle(
 CPL_UNUSED
 #endif
                                        VSIUnixStdioFilesystemHandler *poFSIn,
-                                       FILE* fpIn, bool bReadOnlyIn) :
+                                       FILE* fpIn, bool bReadOnlyIn,
+                                       bool bModeAppendReadWriteIn) :
     fp(fpIn),
     m_nOffset(0),
     bReadOnly(bReadOnlyIn),
     bLastOpWrite(false),
     bLastOpRead(false),
-    bAtEOF(false)
+    bAtEOF(false),
+    bModeAppendReadWrite(bModeAppendReadWriteIn)
 #ifdef VSI_COUNT_BYTES_READ
     ,
     nTotalBytesRead(0),
@@ -232,19 +256,19 @@ int VSIUnixStdioHandle::Seek( vsi_l_offset nOffsetIn, int nWhence )
 {
     bAtEOF = false;
 
-    // seeks that do nothing are still surprisingly expensive with MSVCRT.
+    // Seeks that do nothing are still surprisingly expensive with MSVCRT.
     // try and short circuit if possible.
-    if( nWhence == SEEK_SET && nOffsetIn == m_nOffset )
+    if( !bModeAppendReadWrite && nWhence == SEEK_SET && nOffsetIn == m_nOffset )
         return 0;
 
-    // on a read-only file, we can avoid a lseek() system call to be issued
-    // if the next position to seek to is within the buffered page
+    // On a read-only file, we can avoid a lseek() system call to be issued
+    // if the next position to seek to is within the buffered page.
     if( bReadOnly && nWhence == SEEK_SET )
     {
         if( nOffsetIn > m_nOffset && nOffsetIn < 4096 + m_nOffset )
         {
             const int nDiff = static_cast<int>(nOffsetIn - m_nOffset);
-            GByte abyTemp[4096];
+            GByte abyTemp[4096] = {};
             const int nRead = static_cast<int>(fread(abyTemp, 1, nDiff, fp));
             if( nRead == nDiff )
             {
@@ -357,7 +381,7 @@ size_t VSIUnixStdioHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
 /*      keep careful track of what happened last to know if we          */
 /*      skipped a flushing seek that we may need to do now.             */
 /* -------------------------------------------------------------------- */
-    if( bLastOpWrite )
+    if( !bModeAppendReadWrite && bLastOpWrite )
     {
         if( VSI_FSEEK64( fp, m_nOffset, SEEK_SET ) != 0 )
         {
@@ -371,7 +395,7 @@ size_t VSIUnixStdioHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
     const size_t nResult = fread( pBuffer, nSize, nCount, fp );
 
 #ifdef VSI_DEBUG
-    int nError = errno;
+    const int nError = errno;
     VSIDebug4( "VSIUnixStdioHandle::Read(%p,%ld,%ld) = %ld",
                fp, static_cast<long>(nSize), static_cast<long>(nCount),
                static_cast<long>(nResult) );
@@ -390,7 +414,7 @@ size_t VSIUnixStdioHandle::Read( void * pBuffer, size_t nSize, size_t nCount )
     bLastOpWrite = false;
     bLastOpRead = true;
 
-    if (nResult != nCount)
+    if( nResult != nCount )
     {
         errno = 0;
         vsi_l_offset nNewOffset = VSI_FTELL64( fp );
@@ -419,7 +443,7 @@ size_t VSIUnixStdioHandle::Write( const void * pBuffer, size_t nSize,
 /*      keep careful track of what happened last to know if we          */
 /*      skipped a flushing seek that we may need to do now.             */
 /* -------------------------------------------------------------------- */
-    if( bLastOpRead )
+    if( !bModeAppendReadWrite && bLastOpRead )
     {
         if( VSI_FSEEK64( fp, m_nOffset, SEEK_SET ) != 0 )
         {
@@ -472,6 +496,79 @@ int VSIUnixStdioHandle::Truncate( vsi_l_offset nNewSize )
     return VSI_FTRUNCATE64( fileno(fp), nNewSize );
 }
 
+/************************************************************************/
+/*                          GetRangeStatus()                            */
+/************************************************************************/
+
+#ifdef __linux
+#include <linux/fs.h> /* FS_IOC_FIEMAP */
+#ifdef FS_IOC_FIEMAP
+#include <linux/fiemap.h> /* struct fiemap */
+#endif
+#include <sys/ioctl.h>
+#include <errno.h>
+#endif
+
+VSIRangeStatus VSIUnixStdioHandle::GetRangeStatus( vsi_l_offset
+#ifdef FS_IOC_FIEMAP
+                                                                nOffset
+#endif
+                                                     , vsi_l_offset
+#ifdef FS_IOC_FIEMAP
+                                                                nLength
+#endif
+                                                    )
+{
+#ifdef FS_IOC_FIEMAP
+    // fiemap IOCTL documented at
+    // https://www.kernel.org/doc/Documentation/filesystems/fiemap.txt
+
+    // The fiemap struct contains a "variable length" array at its end
+    // As we are interested in only one extent, we allocate the base size of
+    // fiemap + one fiemap_extent.
+    GByte abyBuffer[sizeof(struct fiemap) + sizeof(struct fiemap_extent)];
+    int fd = fileno(fp);
+    struct fiemap *psExtentMap = reinterpret_cast<struct fiemap *>(&abyBuffer);
+    memset(psExtentMap,
+           0,
+           sizeof(struct fiemap) + sizeof(struct fiemap_extent));
+    psExtentMap->fm_start = nOffset;
+    psExtentMap->fm_length = nLength;
+    psExtentMap->fm_extent_count = 1;
+    int ret = ioctl(fd, FS_IOC_FIEMAP, psExtentMap);
+    if( ret < 0 )
+        return VSI_RANGE_STATUS_UNKNOWN;
+    if( psExtentMap->fm_mapped_extents == 0 )
+        return VSI_RANGE_STATUS_HOLE;
+    // In case there is one extent with unknown status, retry after having
+    // asked the kernel to sync the file.
+    const fiemap_extent* pasExtent = &(psExtentMap->fm_extents[0]);
+    if( psExtentMap->fm_mapped_extents == 1 &&
+        (pasExtent[0].fe_flags & FIEMAP_EXTENT_UNKNOWN) != 0 )
+    {
+        psExtentMap->fm_flags = FIEMAP_FLAG_SYNC;
+        psExtentMap->fm_start = nOffset;
+        psExtentMap->fm_length = nLength;
+        psExtentMap->fm_extent_count = 1;
+        ret = ioctl(fd, FS_IOC_FIEMAP, psExtentMap);
+        if( ret < 0 )
+            return VSI_RANGE_STATUS_UNKNOWN;
+        if( psExtentMap->fm_mapped_extents == 0 )
+            return VSI_RANGE_STATUS_HOLE;
+    }
+    return VSI_RANGE_STATUS_DATA;
+#else
+    static bool bMessageEmitted = false;
+    if( !bMessageEmitted )
+    {
+        CPLDebug("VSI",
+                 "Sorry: GetExtentStatus() not implemented for "
+                 "this operating system");
+        bMessageEmitted = true;
+    }
+    return VSI_RANGE_STATUS_UNKNOWN;
+#endif
+}
 
 /************************************************************************/
 /* ==================================================================== */
@@ -518,7 +615,7 @@ VSIUnixStdioFilesystemHandler::Open( const char *pszFilename,
                                      bool bSetError )
 
 {
-    FILE    *fp = VSI_FOPEN64( pszFilename, pszAccess );
+    FILE *fp = VSI_FOPEN64( pszFilename, pszAccess );
     const int nError = errno;
 
     VSIDebug3( "VSIUnixStdioFilesystemHandler::Open(\"%s\",\"%s\") = %p",
@@ -526,15 +623,21 @@ VSIUnixStdioFilesystemHandler::Open( const char *pszFilename,
 
     if( fp == NULL )
     {
-        if(bSetError) { VSIError(VSIE_FileError, "%s: %s", pszFilename, strerror(nError)); }
+        if( bSetError )
+        {
+            VSIError(VSIE_FileError, "%s: %s", pszFilename, strerror(nError));
+        }
         errno = nError;
         return NULL;
     }
 
     const bool bReadOnly =
         strcmp(pszAccess, "rb") == 0 || strcmp(pszAccess, "r") == 0;
+    const bool bModeAppendReadWrite =
+        strcmp(pszAccess, "a+b") == 0 || strcmp(pszAccess, "a+") == 0;
     VSIUnixStdioHandle *poHandle =
-        new(std::nothrow) VSIUnixStdioHandle( this, fp, bReadOnly );
+        new(std::nothrow) VSIUnixStdioHandle( this, fp, bReadOnly,
+                                              bModeAppendReadWrite );
     if( poHandle == NULL )
     {
         fclose(fp);
@@ -547,8 +650,8 @@ VSIUnixStdioFilesystemHandler::Open( const char *pszFilename,
 /*      If VSI_CACHE is set we want to use a cached reader instead      */
 /*      of more direct io on the underlying file.                       */
 /* -------------------------------------------------------------------- */
-    if( bReadOnly
-        && CSLTestBoolean( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
+    if( bReadOnly &&
+        CPLTestBool( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
     {
         return VSICreateCachedFile( poHandle );
     }
@@ -617,17 +720,17 @@ char **VSIUnixStdioFilesystemHandler::ReadDirEx( const char *pszPath,
                                                  int nMaxFiles )
 
 {
-    if (strlen(pszPath) == 0)
+    if( strlen(pszPath) == 0 )
         pszPath = ".";
 
-    CPLStringList  oDir;
+    CPLStringList oDir;
     DIR *hDir = opendir(pszPath);
-    if ( hDir != NULL )
+    if( hDir != NULL )
     {
-        // we want to avoid returning NULL for an empty list.
-        oDir.Assign( static_cast<char**>( CPLCalloc(2,sizeof(char*)) ) );
+        // We want to avoid returning NULL for an empty list.
+        oDir.Assign(static_cast<char**>(CPLCalloc(2, sizeof(char*))));
 
-        struct dirent *psDirEntry;
+        struct dirent *psDirEntry = NULL;
         while( (psDirEntry = readdir(hDir)) != NULL )
         {
             oDir.AddString( psDirEntry->d_name );
@@ -639,9 +742,8 @@ char **VSIUnixStdioFilesystemHandler::ReadDirEx( const char *pszPath,
     }
     else
     {
-        /* Should we generate an error???
-         * For now we'll just return NULL (at the end of the function)
-         */
+        // Should we generate an error?
+        // For now we'll just return NULL (at the end of the function).
     }
 
     return oDir.StealList();
@@ -664,13 +766,15 @@ GIntBig VSIUnixStdioFilesystemHandler::GetDiskFreeSpace( const char*
     struct statvfs64 buf;
     if( statvfs64(pszDirname, &buf) == 0 )
     {
-        nRet = static_cast<GIntBig>(buf.f_frsize * static_cast<GUIntBig>(buf.f_bavail));
+        nRet = static_cast<GIntBig>(buf.f_frsize *
+                                    static_cast<GUIntBig>(buf.f_bavail));
     }
 #else
     struct statvfs buf;
     if( statvfs(pszDirname, &buf) == 0 )
     {
-        nRet = static_cast<GIntBig>(buf.f_frsize * static_cast<GUIntBig>(buf.f_bavail));
+        nRet = static_cast<GIntBig>(buf.f_frsize *
+                                    static_cast<GUIntBig>(buf.f_bavail));
     }
 #endif
 
@@ -678,12 +782,76 @@ GIntBig VSIUnixStdioFilesystemHandler::GetDiskFreeSpace( const char*
     return nRet;
 }
 
+/************************************************************************/
+/*                      SupportsSparseFiles()                           */
+/************************************************************************/
+
+#ifdef __linux
+#include <sys/vfs.h>
+#endif
+
+int VSIUnixStdioFilesystemHandler::SupportsSparseFiles( const char*
+#ifdef __linux
+                                                        pszPath
+#endif
+                                                        )
+{
+#ifdef __linux
+    struct statfs sStatFS;
+    if( statfs( pszPath, &sStatFS ) == 0 )
+    {
+        // Add here any missing filesystem supporting sparse files.
+        // See http://en.wikipedia.org/wiki/Comparison_of_file_systems
+        switch( sStatFS.f_type )
+        {
+            // Codes from http://man7.org/linux/man-pages/man2/statfs.2.html
+            case 0xef53:  // ext2, 3, 4
+            case 0x52654973:  // reiser
+            case 0x58465342:  // xfs
+            case 0x3153464a:  // jfs
+            case 0x5346544e:  // ntfs
+            case 0x9123683e:  // brfs
+            // nfs: NFS < 4.2 supports creating sparse files (but reading them
+            // not efficiently).
+            case 0x6969:
+            case 0x01021994:  // tmpfs
+                return TRUE;
+
+            case 0x4d44: // msdos
+                return FALSE;
+
+            default:
+                static bool bUnknownFSEmitted = false;
+                if( !bUnknownFSEmitted )
+                {
+                    CPLDebug("VSI", "Filesystem with type %X unknown. "
+                             "Assuming it does not support sparse files",
+                             static_cast<int>(sStatFS.f_type) );
+                    bUnknownFSEmitted = true;
+                }
+                return FALSE;
+        }
+    }
+    return FALSE;
+#else
+    static bool bMessageEmitted = false;
+    if( !bMessageEmitted )
+    {
+        CPLDebug("VSI",
+                 "Sorry: SupportsSparseFiles() not implemented "
+                 "for this operating system");
+        bMessageEmitted = true;
+    }
+    return FALSE;
+#endif
+}
+
 #ifdef VSI_COUNT_BYTES_READ
 /************************************************************************/
 /*                            AddToTotal()                              */
 /************************************************************************/
 
-void VSIUnixStdioFilesystemHandler::AddToTotal(vsi_l_offset nBytes)
+void VSIUnixStdioFilesystemHandler::AddToTotal( vsi_l_offset nBytes )
 {
     CPLMutexHolder oHolder(&hMutex);
     nTotalBytesRead += nBytes;
@@ -701,4 +869,6 @@ void VSIInstallLargeFileHandler()
     VSIFileManager::InstallHandler( "", new VSIUnixStdioFilesystemHandler() );
 }
 
-#endif /* ndef WIN32 */
+#endif  // ndef WIN32
+
+//! @endcond
diff --git a/port/cpl_vsil_win32.cpp b/port/cpl_vsil_win32.cpp
index cdc96f3..73de624 100644
--- a/port/cpl_vsil_win32.cpp
+++ b/port/cpl_vsil_win32.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_vsil_win32.cpp 33758 2016-03-21 09:06:22Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement VSI large file api for Win32.
@@ -30,11 +29,13 @@
 
 #include "cpl_vsi_virtual.h"
 
-CPL_CVSID("$Id: cpl_vsil_win32.cpp 33758 2016-03-21 09:06:22Z rouault $");
+CPL_CVSID("$Id: cpl_vsil_win32.cpp 37127 2017-01-12 19:07:33Z rouault $");
 
 #if defined(WIN32)
 
 #include <windows.h>
+#include <winioctl.h> // for FSCTL_SET_SPARSE
+
 #include "cpl_string.h"
 
 #include <sys/types.h>
@@ -49,24 +50,30 @@ CPL_CVSID("$Id: cpl_vsil_win32.cpp 33758 2016-03-21 09:06:22Z rouault $");
 /* ==================================================================== */
 /************************************************************************/
 
+// To avoid aliasing to GetDiskFreeSpace to GetDiskFreeSpaceA on Windows
+#ifdef GetDiskFreeSpace
+#undef GetDiskFreeSpace
+#endif
+
 class VSIWin32FilesystemHandler CPL_FINAL : public VSIFilesystemHandler
 {
 public:
-
+    // TODO(schwehr): Fix Open call to remove the need for this using call.
     using VSIFilesystemHandler::Open;
 
     virtual VSIVirtualHandle *Open( const char *pszFilename,
                                     const char *pszAccess,
-                                    bool bSetError );
-    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags );
-    virtual int      Unlink( const char *pszFilename );
-    virtual int      Rename( const char *oldpath, const char *newpath );
-    virtual int      Mkdir( const char *pszDirname, long nMode );
-    virtual int      Rmdir( const char *pszDirname );
-    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles );
-    virtual int      IsCaseSensitive( const char* pszFilename )
+                                    bool bSetError ) override;
+    virtual int      Stat( const char *pszFilename, VSIStatBufL *pStatBuf, int nFlags ) override;
+    virtual int      Unlink( const char *pszFilename ) override;
+    virtual int      Rename( const char *oldpath, const char *newpath ) override;
+    virtual int      Mkdir( const char *pszDirname, long nMode ) override;
+    virtual int      Rmdir( const char *pszDirname ) override;
+    virtual char   **ReadDirEx( const char *pszDirname, int nMaxFiles ) override;
+    virtual int      IsCaseSensitive( const char* pszFilename ) override
                       { (void) pszFilename; return FALSE; }
-    virtual GIntBig  GetDiskFreeSpace( const char* pszDirname );
+    virtual GIntBig  GetDiskFreeSpace( const char* pszDirname ) override;
+    virtual int SupportsSparseFiles( const char* pszPath ) override;
 };
 
 /************************************************************************/
@@ -81,15 +88,17 @@ class VSIWin32Handle CPL_FINAL : public VSIVirtualHandle
     HANDLE       hFile;
     int          bEOF;
 
-    virtual int       Seek( vsi_l_offset nOffset, int nWhence );
-    virtual vsi_l_offset Tell();
-    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb );
-    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb );
-    virtual int       Eof();
-    virtual int       Flush();
-    virtual int       Close();
-    virtual int       Truncate( vsi_l_offset nNewSize );
-    virtual void     *GetNativeFileDescriptor() { return (void*) hFile; }
+    virtual int       Seek( vsi_l_offset nOffset, int nWhence ) override;
+    virtual vsi_l_offset Tell() override;
+    virtual size_t    Read( void *pBuffer, size_t nSize, size_t nMemb ) override;
+    virtual size_t    Write( const void *pBuffer, size_t nSize, size_t nMemb ) override;
+    virtual int       Eof() override;
+    virtual int       Flush() override;
+    virtual int       Close() override;
+    virtual int       Truncate( vsi_l_offset nNewSize ) override;
+    virtual void     *GetNativeFileDescriptor() override { return (void*) hFile; }
+    virtual VSIRangeStatus GetRangeStatus( vsi_l_offset nOffset,
+                                           vsi_l_offset nLength ) override;
 };
 
 /************************************************************************/
@@ -235,8 +244,8 @@ int VSIWin32Handle::Seek( vsi_l_offset nOffset, int nWhence )
                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                        (LPTSTR) &lpMsgBuf, 0, NULL );
 
-        printf( "[ERROR %d]\n %s\n", GetLastError(), (char *) lpMsgBuf );
-        printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n",
+        printf( "[ERROR %d]\n %s\n", GetLastError(), (char *) lpMsgBuf );/*ok*/
+        printf( "nOffset=%u, nMoveLow=%u, dwMoveHigh=%u\n",/*ok*/
                 (GUInt32) nOffset, nMoveLow, dwMoveHigh );
 #endif
         errno = ErrnoFromGetLastError();
@@ -274,7 +283,7 @@ int VSIWin32Handle::Flush()
     /* See http://trac.osgeo.org/gdal/ticket/5556 */
 
     // Add this as a hack to make ogr_mitab_30 and _31 tests pass
-    if( CSLTestBoolean(CPLGetConfigOption("VSI_FLUSH", "FALSE")) )
+    if( CPLTestBool(CPLGetConfigOption("VSI_FLUSH", "FALSE")) )
         FlushFileBuffers(hFile);
     return 0;
 }
@@ -346,6 +355,13 @@ int VSIWin32Handle::Eof()
 int VSIWin32Handle::Truncate( vsi_l_offset nNewSize )
 {
     vsi_l_offset nCur = Tell();
+    Seek( 0, SEEK_END );
+    if( nNewSize > Tell() )
+    {
+        // Enable sparse files if growing size
+        DWORD dwTemp;
+        DeviceIoControl(hFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwTemp, NULL);
+    }
     Seek( nNewSize, SEEK_SET );
     BOOL bRes = SetEndOfFile( hFile );
     Seek( nCur, SEEK_SET );
@@ -357,6 +373,53 @@ int VSIWin32Handle::Truncate( vsi_l_offset nNewSize )
 }
 
 /************************************************************************/
+/*                           GetRangeStatus()                           */
+/************************************************************************/
+
+VSIRangeStatus VSIWin32Handle::GetRangeStatus( vsi_l_offset
+#ifdef FSCTL_QUERY_ALLOCATED_RANGES
+                                                        nOffset
+#endif
+                                               ,vsi_l_offset
+#ifdef FSCTL_QUERY_ALLOCATED_RANGES
+                                                        nLength
+#endif
+                                              )
+{
+    // Not available on mingw includes
+#ifdef FSCTL_QUERY_ALLOCATED_RANGES
+    FILE_ALLOCATED_RANGE_BUFFER sQueryRange;
+    FILE_ALLOCATED_RANGE_BUFFER asOutputRange[1];
+    DWORD nOutputBytes = 0;
+
+    sQueryRange.FileOffset.QuadPart = nOffset;
+    sQueryRange.Length.QuadPart = nOffset + nLength;
+
+    if( !DeviceIoControl(hFile, FSCTL_QUERY_ALLOCATED_RANGES,
+                        &sQueryRange, sizeof(sQueryRange),
+                        asOutputRange, sizeof(asOutputRange),
+                        &nOutputBytes, NULL) )
+    {
+        if( GetLastError() == ERROR_MORE_DATA )
+        {
+            return VSI_RANGE_STATUS_DATA;
+        }
+        else
+        {
+            return VSI_RANGE_STATUS_UNKNOWN;
+        }
+    }
+
+    if( nOutputBytes )
+        return VSI_RANGE_STATUS_DATA;
+    else
+        return VSI_RANGE_STATUS_HOLE;
+#else
+    return VSI_RANGE_STATUS_UNKNOWN;
+#endif
+}
+
+/************************************************************************/
 /* ==================================================================== */
 /*                       VSIWin32FilesystemHandler                      */
 /* ==================================================================== */
@@ -403,17 +466,20 @@ static void VSIWin32TryLongFilename(wchar_t*& pwszFilename)
         pwszFilename[1] == ':' &&
         (pwszFilename[2] == '\\' || pwszFilename[2] == '/' ) )
     {
-        pwszFilename = (wchar_t*) CPLRealloc( pwszFilename,
-                    (4 + nLen + 1) * sizeof(wchar_t));
+        pwszFilename = static_cast<wchar_t *>(
+            CPLRealloc( pwszFilename, (4 + nLen + 1) * sizeof(wchar_t)));
         memmove( pwszFilename + 4, pwszFilename, (nLen+1) * sizeof(wchar_t));
     }
     else
     {
-        wchar_t* pwszCurDir = (wchar_t*) CPLMalloc(32768 * sizeof(wchar_t));
+        // TODO(schwehr): 32768 should be a symbolic constant.
+        wchar_t* pwszCurDir =
+            static_cast<wchar_t *>(CPLMalloc(32768 * sizeof(wchar_t)));
         DWORD nCurDirLen = GetCurrentDirectoryW( 32768, pwszCurDir );
         CPLAssert(nCurDirLen < 32768);
-        pwszFilename = (wchar_t*) CPLRealloc( pwszFilename,
-                    (4 + nCurDirLen + 1 + nLen + 1) * sizeof(wchar_t));
+        pwszFilename = static_cast<wchar_t *>(
+            CPLRealloc(pwszFilename,
+                       (4 + nCurDirLen + 1 + nLen + 1) * sizeof(wchar_t)));
         int nOffset = 0;
         if( pwszFilename[0] == '.' &&
             (pwszFilename[1] == '/' || pwszFilename[1] == '\\') )
@@ -473,13 +539,15 @@ static bool VSIWin32IsLongFilename( const wchar_t* pwszFilename )
 
 VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
                                                    const char *pszAccess,
-                                                   bool /* bSetError */ )
+                                                   bool bSetError )
 
 {
-    DWORD dwDesiredAccess, dwCreationDisposition, dwFlagsAndAttributes;
+    DWORD dwDesiredAccess;
+    DWORD dwCreationDisposition;
+    DWORD dwFlagsAndAttributes;
     HANDLE hFile;
 
-    // GENERICs are used instead of FILE_GENERIC_READ
+    // GENERICs are used instead of FILE_GENERIC_READ.
     dwDesiredAccess = GENERIC_READ;
     if (strchr(pszAccess, '+') != NULL || strchr(pszAccess, 'w') != NULL)
         dwDesiredAccess |= GENERIC_WRITE;
@@ -512,8 +580,11 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
             }
             if( nVersion < 1 * 10000 + 7 * 100 + 4 )
             {
-                //CPLDebug("VSI", "Wine %s detected. Append mode needs FILE_WRITE_DATA",
-                //         pszWineVersion);
+#if DEBUG_VERBOSE
+                CPLDebug("VSI",
+                         "Wine %s detected. Append mode needs FILE_WRITE_DATA",
+                         pszWineVersion);
+#endif
                 dwDesiredAccess |= FILE_WRITE_DATA;
             }
         }
@@ -534,8 +605,7 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
 /*      converting to wide characters to open.                          */
 /* -------------------------------------------------------------------- */
     DWORD nLastError = 0;
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool(CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
@@ -584,7 +654,12 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
 
     if( hFile == INVALID_HANDLE_VALUE )
     {
-        errno = ErrnoFromGetLastError(nLastError);
+        const int nError = ErrnoFromGetLastError(nLastError);
+        if( bSetError && nError != 0 )
+        {
+            VSIError(VSIE_FileError, "%s: %s", pszFilename, strerror(nError));
+        }
+        errno = nError;
         return NULL;
     }
 
@@ -604,7 +679,7 @@ VSIVirtualHandle *VSIWin32FilesystemHandler::Open( const char *pszFilename,
 /*      of more direct io on the underlying file.                       */
 /* -------------------------------------------------------------------- */
     if( (EQUAL(pszAccess,"r") || EQUAL(pszAccess,"rb"))
-        && CSLTestBoolean( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
+        && CPLTestBool( CPLGetConfigOption( "VSI_CACHE", "FALSE" ) ) )
     {
         return VSICreateCachedFile( poHandle );
     }
@@ -626,8 +701,7 @@ int VSIWin32FilesystemHandler::Stat( const char * pszFilename,
     (void) nFlags;
 
 #if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
@@ -658,7 +732,7 @@ int VSIWin32FilesystemHandler::Stat( const char * pszFilename,
         {
             // _wstat64 doesn't like \\?\ paths, so do our poor-man
             // stat like.
-            //nResult = _wstat64( pwszFilename, pStatBuf );
+            // nResult = _wstat64( pwszFilename, pStatBuf );
 
             VSIVirtualHandle* poHandle = Open( pszFilename, "rb");
             if( poHandle != NULL )
@@ -695,8 +769,7 @@ int VSIWin32FilesystemHandler::Unlink( const char * pszFilename )
 
 {
 #if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
@@ -721,8 +794,7 @@ int VSIWin32FilesystemHandler::Rename( const char *oldpath,
 
 {
 #if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         wchar_t *pwszOldPath =
             CPLRecodeToWChar( oldpath, CPL_ENC_UTF8, CPL_ENC_UCS2 );
@@ -751,8 +823,7 @@ int VSIWin32FilesystemHandler::Mkdir( const char * pszPathname,
 {
     (void) nMode;
 #if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         wchar_t *pwszFilename =
             CPLRecodeToWChar( pszPathname, CPL_ENC_UTF8, CPL_ENC_UCS2 );
@@ -776,8 +847,7 @@ int VSIWin32FilesystemHandler::Rmdir( const char * pszPathname )
 
 {
 #if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         wchar_t *pwszFilename =
             CPLRecodeToWChar( pszPathname, CPL_ENC_UTF8, CPL_ENC_UCS2 );
@@ -802,8 +872,7 @@ char **VSIWin32FilesystemHandler::ReadDirEx( const char *pszPath,
 
 {
 #if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         struct _wfinddata_t c_file;
         intptr_t hFile;
@@ -894,6 +963,31 @@ GIntBig VSIWin32FilesystemHandler::GetDiskFreeSpace( const char* pszDirname )
 }
 
 /************************************************************************/
+/*                      SupportsSparseFiles()                           */
+/************************************************************************/
+
+int VSIWin32FilesystemHandler::SupportsSparseFiles( const char* pszPath )
+{
+    CPLString osPath(pszPath);
+    DWORD dwVolFlags = 0;
+    if( CPLIsFilenameRelative(pszPath) )
+    {
+        char* pszTmp = CPLGetCurrentDir();
+        osPath = pszTmp;
+        CPLFree(pszTmp);
+    }
+    if( osPath.size() >= 3 && osPath[1] == ':' &&
+        (osPath[2] == '/' || osPath[2] == '\\') )
+    {
+        osPath.resize(3);
+    }
+
+    GetVolumeInformation(osPath.c_str(), NULL, 0, NULL,
+                         NULL, &dwVolFlags, NULL, 0);
+    return (dwVolFlags & FILE_SUPPORTS_SPARSE_FILES);
+}
+
+/************************************************************************/
 /*                     VSIInstallLargeFileHandler()                     */
 /************************************************************************/
 
diff --git a/port/cpl_vsisimple.cpp b/port/cpl_vsisimple.cpp
index cb6a9a3..c006199 100644
--- a/port/cpl_vsisimple.cpp
+++ b/port/cpl_vsisimple.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_vsisimple.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  Common Portability Library
  * Purpose:  Simple implementation of POSIX VSI functions.
@@ -35,46 +34,61 @@
  *
  ****************************************************************************/
 
+#include "cpl_port.h"
+#include "cpl_vsi.h"
+
+#include <cerrno>
+#include <cstdarg>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#if HAVE_SYS_STAT_H
+#  include <sys/stat.h>
+#endif
+
 #include "cpl_config.h"
 #include "cpl_error.h"
-#include "cpl_port.h"
 #include "cpl_string.h"
-#include "cpl_vsi.h"
 
-/* Uncomment to check consistent usage of VSIMalloc(), VSIRealloc(), */
-/* VSICalloc(), VSIFree(), VSIStrdup() */
-//#define DEBUG_VSIMALLOC
+#ifdef _WIN32
+#include <malloc.h> // For _aligned_malloc
+#endif
+
+// Uncomment to check consistent usage of VSIMalloc(), VSIRealloc(),
+// VSICalloc(), VSIFree(), VSIStrdup().
+// #define DEBUG_VSIMALLOC
 
-/* Uncomment to compute memory usage statistics. */
-/* DEBUG_VSIMALLOC must also be defined */
-//#define DEBUG_VSIMALLOC_STATS
+// Uncomment to compute memory usage statistics.
+// DEBUG_VSIMALLOC must also be defined.
+// #define DEBUG_VSIMALLOC_STATS
 
-/* Highly experimental, and likely buggy. Do not use, except for fixing it! */
-/* DEBUG_VSIMALLOC must also be defined */
-//#define DEBUG_VSIMALLOC_MPROTECT
+// Highly experimental, and likely buggy. Do not use, except for fixing it!
+// DEBUG_VSIMALLOC must also be defined.
+// #define DEBUG_VSIMALLOC_MPROTECT
 
 #ifdef DEBUG_VSIMALLOC_MPROTECT
 #include <sys/mman.h>
 #endif
 
-/* Uncomment to print every memory allocation or deallocation. */
-/* DEBUG_VSIMALLOC must also be defined */
-//#define DEBUG_VSIMALLOC_VERBOSE
+// Uncomment to print every memory allocation or deallocation.
+// DEBUG_VSIMALLOC must also be defined.
+// #define DEBUG_VSIMALLOC_VERBOSE
 
-/* Number of bytes of the malloc/calloc/free that triggers a debug trace. Can be 0 for all allocs */
+// Number of bytes of the malloc/calloc/free that triggers a debug trace.
+// Can be 0 for all allocs.
 #define THRESHOLD_PRINT 10000
 
-/* Uncomment to print GDAL block cache use. */
-/* Only used if DEBUG_VSIMALLOC_VERBOSE is enabled */
-//#define DEBUG_BLOCK_CACHE_USE
+// Uncomment to print GDAL block cache use.
+// Only used if DEBUG_VSIMALLOC_VERBOSE is enabled.
+// #define DEBUG_BLOCK_CACHE_USE
 
 #ifdef DEBUG_BLOCK_CACHE_USE
 extern "C" GIntBig CPL_DLL CPL_STDCALL GDALGetCacheUsed64(void);
 #endif
 
-CPL_CVSID("$Id: cpl_vsisimple.cpp 33724 2016-03-16 17:14:11Z goatbar $");
-
-/* for stat() */
+CPL_CVSID("$Id: cpl_vsisimple.cpp 36911 2016-12-16 19:42:07Z goatbar $");
 
 /* Unix or Windows NT/2000/XP */
 #if !defined(WIN32)
@@ -85,9 +99,6 @@ CPL_CVSID("$Id: cpl_vsisimple.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 #  include <direct.h>
 #endif
 
-#include <sys/stat.h>
-#include <time.h>
-
 /************************************************************************/
 /*                              VSIFOpen()                              */
 /************************************************************************/
@@ -95,11 +106,9 @@ CPL_CVSID("$Id: cpl_vsisimple.cpp 33724 2016-03-16 17:14:11Z goatbar $");
 FILE *VSIFOpen( const char * pszFilename, const char * pszAccess )
 
 {
-    FILE *fp = NULL;
-
 #if defined(WIN32)
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    FILE *fp = NULL;
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
@@ -112,8 +121,14 @@ FILE *VSIFOpen( const char * pszFilename, const char * pszAccess )
         CPLFree( pwszAccess );
     }
     else
+    {
+        // Are the casts really necessary?
+        fp = fopen(const_cast<char *>(pszFilename),
+                   const_cast<char *>(pszAccess));
+    }
+#else
+    FILE *fp = fopen(pszFilename, pszAccess);
 #endif
-    fp = fopen( (char *) pszFilename, (char *) pszAccess );
 
 #ifdef VSI_DEBUG
     // Capture the error from fopen to avoid being overwritten by errors
@@ -146,8 +161,8 @@ int VSIFSeek( FILE * fp, long nOffset, int nWhence )
 
 {
 #ifdef DEBUG
-    /* To workaround Coverity strange warning about potential negative seek */
-    /* CID 1340084 when called from dgnwrite.cpp */
+    // To workaround Coverity strange warning about potential negative seek
+    // CID 1340084 when called from dgnwrite.cpp.
     if( nWhence == SEEK_SET && nOffset < 0 )
         return -1;
 #endif
@@ -282,7 +297,7 @@ void VSIFFlush( FILE * fp )
     // from VSIDebug.
     const int nError = errno;
     VSIDebug2( "VSIRewind(%p) errno = %d", fp, nError );
-    if ( result != 0 )
+    if( result != 0 )
     {
         CPLError( CE_Failure, CPLE_FileIO, "Flush failed.  errno = %d",
                   nError);
@@ -329,10 +344,10 @@ int VSIUngetc( int c, FILE * fp )
 /*      have to use vfprintf().                                         */
 /************************************************************************/
 
-int     VSIFPrintf( FILE * fp, const char * pszFormat, ... )
+int VSIFPrintf( FILE * fp, CPL_FORMAT_STRING(const char * pszFormat), ... )
 
 {
-    va_list     args;
+    va_list args;
 
     va_start( args, pszFormat );
     const int nReturn = vfprintf( fp, pszFormat, args );
@@ -371,11 +386,10 @@ int VSIFPutc( int nChar, FILE * fp )
     return fputc( nChar, fp );
 }
 
-
 #ifdef DEBUG_VSIMALLOC_STATS
 #include "cpl_multiproc.h"
 
-static CPLMutex* hMemStatMutex = 0;
+static CPLMutex* hMemStatMutex = NULL;
 static size_t nCurrentTotalAllocs = 0;
 static size_t nMaxTotalAllocs = 0;
 static GUIntBig nVSIMallocs = 0;
@@ -383,11 +397,6 @@ static GUIntBig nVSICallocs = 0;
 static GUIntBig nVSIReallocs = 0;
 static GUIntBig nVSIFrees = 0;
 
-/*size_t GetMaxTotalAllocs()
-{
-    return nMaxTotalAllocs;
-}*/
-
 /************************************************************************/
 /*                         VSIShowMemStats()                            */
 /************************************************************************/
@@ -397,22 +406,22 @@ void VSIShowMemStats();
 void VSIShowMemStats()
 {
     char* pszShowMemStats = getenv("CPL_SHOW_MEM_STATS");
-    if (pszShowMemStats == NULL || pszShowMemStats[0] == '\0' )
+    if( pszShowMemStats == NULL || pszShowMemStats[0] == '\0' )
         return;
-    printf("Current VSI memory usage        : " CPL_FRMT_GUIB " bytes\n",
-            (GUIntBig)nCurrentTotalAllocs);
-    printf("Maximum VSI memory usage        : " CPL_FRMT_GUIB " bytes\n",
-            (GUIntBig)nMaxTotalAllocs);
-    printf("Number of calls to VSIMalloc()  : " CPL_FRMT_GUIB "\n",
-            nVSIMallocs);
-    printf("Number of calls to VSICalloc()  : " CPL_FRMT_GUIB "\n",
-            nVSICallocs);
-    printf("Number of calls to VSIRealloc() : " CPL_FRMT_GUIB "\n",
-            nVSIReallocs);
-    printf("Number of calls to VSIFree()    : " CPL_FRMT_GUIB "\n",
-            nVSIFrees);
-    printf("VSIMalloc + VSICalloc - VSIFree : " CPL_FRMT_GUIB "\n",
-            nVSIMallocs + nVSICallocs - nVSIFrees);
+    printf("Current VSI memory usage        : " CPL_FRMT_GUIB " bytes\n", /*ok*/
+           static_cast<GUIntBig>(nCurrentTotalAllocs));
+    printf("Maximum VSI memory usage        : " CPL_FRMT_GUIB " bytes\n", /*ok*/
+           static_cast<GUIntBig>(nMaxTotalAllocs));
+    printf("Number of calls to VSIMalloc()  : " CPL_FRMT_GUIB "\n", /*ok*/
+           nVSIMallocs);
+    printf("Number of calls to VSICalloc()  : " CPL_FRMT_GUIB "\n", /*ok*/
+           nVSICallocs);
+    printf("Number of calls to VSIRealloc() : " CPL_FRMT_GUIB "\n", /*ok*/
+           nVSIReallocs);
+    printf("Number of calls to VSIFree()    : " CPL_FRMT_GUIB "\n", /*ok*/
+           nVSIFrees);
+    printf("VSIMalloc + VSICalloc - VSIFree : " CPL_FRMT_GUIB "\n", /*ok*/
+           nVSIMallocs + nVSICallocs - nVSIFrees);
 }
 #endif
 
@@ -425,41 +434,53 @@ static GIntBig nMaxCumulAllocSize = -1;
 /*                             VSICalloc()                              */
 /************************************************************************/
 
+/** Analog of calloc(). Use VSIFree() to free */
 void *VSICalloc( size_t nCount, size_t nSize )
 
 {
 #ifdef DEBUG_VSIMALLOC
     size_t nMul = nCount * nSize;
-    if (nCount != 0 && nMul / nCount != nSize)
+    if( nCount != 0 && nMul / nCount != nSize )
     {
-        fprintf(stderr, "Overflow in VSICalloc(%d, %d)\n",
-                (int)nCount, (int)nSize);
+        fprintf(stderr, "Overflow in VSICalloc(%d, %d)\n", /*ok*/
+                static_cast<int>(nCount), static_cast<int>(nSize));
         return NULL;
     }
-    if (nMaxPeakAllocSize < 0)
+    if( nMaxPeakAllocSize < 0 )
     {
         char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
-        nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
+        nMaxPeakAllocSize = pszMaxPeakAllocSize ? atoi(pszMaxPeakAllocSize) : 0;
         char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
-        nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
+        nMaxCumulAllocSize =
+            pszMaxCumulAllocSize ? atoi(pszMaxCumulAllocSize) : 0;
     }
-    if (nMaxPeakAllocSize > 0 && (GIntBig)nMul > nMaxPeakAllocSize)
+    if( nMaxPeakAllocSize > 0 &&
+        static_cast<GIntBig>(nMul) > nMaxPeakAllocSize )
         return NULL;
 #ifdef DEBUG_VSIMALLOC_STATS
-    if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nMul > nMaxCumulAllocSize)
+    if( nMaxCumulAllocSize > 0 &&
+        static_cast<GIntBig>(nCurrentTotalAllocs) + static_cast<GIntBig>(nMul) >
+        nMaxCumulAllocSize )
         return NULL;
 #endif
 
 #ifdef DEBUG_VSIMALLOC_MPROTECT
     char* ptr = NULL;
-    size_t nPageSize = getpagesize();
-    posix_memalign((void**)&ptr, nPageSize, (3 * sizeof(void*) + nMul + nPageSize - 1) & ~(nPageSize - 1));
-    if (ptr == NULL)
+    const size_t nPageSize = getpagesize();
+    const size_t nRequestedSize =
+        (3 * sizeof(void*) + nMul + nPageSize - 1) & ~(nPageSize - 1);
+    if( nRequestedSize < nMul )
+        return NULL;
+    posix_memalign((void**)&ptr, nPageSize, nRequestedSize);
+    if( ptr == NULL )
         return NULL;
     memset(ptr + 2 * sizeof(void*), 0, nMul);
 #else
-    char* ptr = (char*) calloc(1, 3 * sizeof(void*) + nMul);
-    if (ptr == NULL)
+    const size_t nRequestedSize = 3 * sizeof(void*) + nMul;
+    if( nRequestedSize < nMul )
+        return NULL;
+    char* ptr = static_cast<char *>(calloc(1, nRequestedSize));
+    if( ptr == NULL )
         return NULL;
 #endif
 
@@ -467,6 +488,7 @@ void *VSICalloc( size_t nCount, size_t nSize )
     ptr[1] = 'S';
     ptr[2] = 'I';
     ptr[3] = 'M';
+    // cppcheck-suppress pointerSize
     memcpy(ptr + sizeof(void*), &nMul, sizeof(void*));
     ptr[2 * sizeof(void*) + nMul + 0] = 'E';
     ptr[2 * sizeof(void*) + nMul + 1] = 'V';
@@ -478,20 +500,39 @@ void *VSICalloc( size_t nCount, size_t nSize )
 #ifdef DEBUG_VSIMALLOC_VERBOSE
         if( nMul > THRESHOLD_PRINT )
         {
-            fprintf(stderr, "Thread[%p] VSICalloc(%d,%d) = %p\n",
-                    (void*)CPLGetPID(), (int)nCount, (int)nSize, ptr + 2 * sizeof(void*));
+            fprintf(stderr, "Thread[%p] VSICalloc(%d,%d) = %p" /*ok*/
+#ifdef DEBUG_VSIMALLOC_STATS
+                         ", current_cumul = " CPL_FRMT_GUIB
+#ifdef DEBUG_BLOCK_CACHE_USE
+                         ", block_cache_used = " CPL_FRMT_GIB
+#endif
+                         ", mal+cal-free = %d"
+#endif
+                         "\n",
+                    (void*)CPLGetPID(),
+                    static_cast<int>(nCount),
+                    static_cast<int>(nSize), ptr + 2 * sizeof(void*)
+#ifdef DEBUG_VSIMALLOC_STATS
+                    , static_cast<GUIntBig>(nCurrentTotalAllocs + nMul)
+#ifdef DEBUG_BLOCK_CACHE_USE
+                    , GDALGetCacheUsed64()
+#endif
+                    , static_cast<int>(nVSIMallocs + nVSICallocs - nVSIFrees)
+#endif
+                );
         }
 #endif
 #ifdef DEBUG_VSIMALLOC_STATS
-        nVSICallocs ++;
-        if (nMaxTotalAllocs == 0)
+        nVSICallocs++;
+        if( nMaxTotalAllocs == 0 )
             atexit(VSIShowMemStats);
         nCurrentTotalAllocs += nMul;
-        if (nCurrentTotalAllocs > nMaxTotalAllocs)
+        if( nCurrentTotalAllocs > nMaxTotalAllocs )
             nMaxTotalAllocs = nCurrentTotalAllocs;
 #endif
     }
 #endif
+    // cppcheck-suppress memleak
     return ptr + 2 * sizeof(void*);
 #else
     return calloc( nCount, nSize );
@@ -503,6 +544,7 @@ void *VSICalloc( size_t nCount, size_t nSize )
 /************************************************************************/
 
 #ifndef DEBUG_VSIMALLOC
+/** Analog of malloc(). Use VSIFree() to free */
 void *VSIMalloc( size_t nSize )
 
 {
@@ -514,33 +556,45 @@ void *VSIMalloc( size_t nSize )
 void *VSIMalloc( size_t nSize )
 
 {
-    if (nMaxPeakAllocSize < 0)
+    if( nMaxPeakAllocSize < 0 )
     {
         char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
-        nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
+        nMaxPeakAllocSize = pszMaxPeakAllocSize ? atoi(pszMaxPeakAllocSize) : 0;
         char* pszMaxCumulAllocSize = getenv("CPL_MAX_CUMUL_ALLOC_SIZE");
-        nMaxCumulAllocSize = (pszMaxCumulAllocSize) ? atoi(pszMaxCumulAllocSize) : 0;
+        nMaxCumulAllocSize =
+            pszMaxCumulAllocSize ? atoi(pszMaxCumulAllocSize) : 0;
     }
-    if (nMaxPeakAllocSize > 0 && (GIntBig)nSize > nMaxPeakAllocSize)
+    if( nMaxPeakAllocSize > 0 &&
+        static_cast<GIntBig>(nSize) > nMaxPeakAllocSize )
         return NULL;
 #ifdef DEBUG_VSIMALLOC_STATS
-    if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nSize > nMaxCumulAllocSize)
+    if( nMaxCumulAllocSize > 0 &&
+        static_cast<GIntBig>(nCurrentTotalAllocs) +
+        static_cast<GIntBig>(nSize) > nMaxCumulAllocSize )
         return NULL;
 #endif  // DEBUG_VSIMALLOC_STATS
 
 #ifdef DEBUG_VSIMALLOC_MPROTECT
     char* ptr = NULL;
-    size_t nPageSize = getpagesize();
-    posix_memalign((void**)&ptr, nPageSize, (3 * sizeof(void*) + nSize + nPageSize - 1) & ~(nPageSize - 1));
+    const size_t nPageSize = getpagesize();
+    const size_t nRequestedSize =
+        (3 * sizeof(void*) + nSize + nPageSize - 1) & ~(nPageSize - 1);
+    if( nRequestedSize < nSize )
+        return NULL;
+    posix_memalign((void**)&ptr, nPageSize, nRequestedSize );
 #else
-    char* ptr = (char*) malloc(3 * sizeof(void*) + nSize);
+    const size_t nRequestedSize = 3 * sizeof(void*) + nSize;
+    if( nRequestedSize < nSize )
+        return NULL;
+    char* ptr = static_cast<char *>(malloc(nRequestedSize));
 #endif  // DEBUG_VSIMALLOC_MPROTECT
-    if (ptr == NULL)
+    if( ptr == NULL )
         return NULL;
     ptr[0] = 'V';
     ptr[1] = 'S';
     ptr[2] = 'I';
     ptr[3] = 'M';
+    // cppcheck-suppress pointerSize
     memcpy(ptr + sizeof(void*), &nSize, sizeof(void*));
     ptr[2 * sizeof(void*) + nSize + 0] = 'E';
     ptr[2 * sizeof(void*) + nSize + 1] = 'V';
@@ -552,52 +606,55 @@ void *VSIMalloc( size_t nSize )
 #ifdef DEBUG_VSIMALLOC_VERBOSE
         if( nSize > THRESHOLD_PRINT )
         {
-            fprintf(stderr, "Thread[%p] VSIMalloc(%d) = %p"
+            fprintf(stderr, "Thread[%p] VSIMalloc(%d) = %p"/*ok*/
 #ifdef DEBUG_VSIMALLOC_STATS
-                         ", current_cumul = " CPL_FRMT_GUIB
+                    ", current_cumul = " CPL_FRMT_GUIB
 #ifdef DEBUG_BLOCK_CACHE_USE
-                         ", block_cache_used = " CPL_FRMT_GIB
+                    ", block_cache_used = " CPL_FRMT_GIB
 #endif
-                         ", mal+cal-free = %d"
+                    ", mal+cal-free = %d"
 #endif
-                         "\n",
-                (void*)CPLGetPID(), (int)nSize, ptr + 2 * sizeof(void*)
+                    "\n",
+                    (void*)CPLGetPID(),
+                    static_cast<int>(nSize), ptr + 2 * sizeof(void*)
 #ifdef DEBUG_VSIMALLOC_STATS
-                , (GUIntBig)(nCurrentTotalAllocs + nSize),
+                    , static_cast<GUIntBig>(nCurrentTotalAllocs + nSize)
 #ifdef DEBUG_BLOCK_CACHE_USE
-                , GDALGetCacheUsed64()
+                    , GDALGetCacheUsed64()
 #endif
-                ,(int)(nVSIMallocs + nVSICallocs - nVSIFrees)
+                    , static_cast<int>(nVSIMallocs + nVSICallocs - nVSIFrees)
 #endif
                 );
         }
 #endif  // DEBUG_VSIMALLOC_VERBOSE
 #ifdef DEBUG_VSIMALLOC_STATS
-        nVSIMallocs ++;
-        if (nMaxTotalAllocs == 0)
+        nVSIMallocs++;
+        if( nMaxTotalAllocs == 0 )
             atexit(VSIShowMemStats);
         nCurrentTotalAllocs += nSize;
-        if (nCurrentTotalAllocs > nMaxTotalAllocs)
+        if( nCurrentTotalAllocs > nMaxTotalAllocs )
             nMaxTotalAllocs = nCurrentTotalAllocs;
 #endif  // DEBUG_VSIMALLOC_STATS
     }
 #endif  // DEBUG_VSIMALLOC_STATS || DEBUG_VSIMALLOC_VERBOSE
+    // cppcheck-suppress memleak
     return ptr + 2 * sizeof(void*);
 }
 
 static void VSICheckMarkerBegin(char* ptr)
 {
-    if (memcmp(ptr, "VSIM", 4) != 0)
+    if( memcmp(ptr, "VSIM", 4) != 0 )
     {
         CPLError(CE_Fatal, CPLE_AppDefined,
-                 "Inconsistent use of VSI memory allocation primitives for %p : %c%c%c%c",
+                 "Inconsistent use of VSI memory allocation primitives "
+                 "for %p : %c%c%c%c",
                  ptr, ptr[0], ptr[1], ptr[2], ptr[3]);
     }
 }
 
 static void VSICheckMarkerEnd(char* ptr, size_t nEnd)
 {
-    if (memcmp(ptr + nEnd, "EVSI", 4) != 0)
+    if( memcmp(ptr + nEnd, "EVSI", 4) != 0 )
     {
         CPLError(CE_Fatal, CPLE_AppDefined,
                  "Memory has been written after the end of %p", ptr);
@@ -610,29 +667,35 @@ static void VSICheckMarkerEnd(char* ptr, size_t nEnd)
 /*                             VSIRealloc()                             */
 /************************************************************************/
 
+/** Analog of realloc(). Use VSIFree() to free */
 void * VSIRealloc( void * pData, size_t nNewSize )
 
 {
 #ifdef DEBUG_VSIMALLOC
-    if (pData == NULL)
+    if( pData == NULL )
         return VSIMalloc(nNewSize);
 
     char* ptr = ((char*)pData) - 2 * sizeof(void*);
     VSICheckMarkerBegin(ptr);
 
     size_t nOldSize = 0;
+    // cppcheck-suppress pointerSize
     memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
     VSICheckMarkerEnd(ptr, 2 * sizeof(void*) + nOldSize);
 
-    if (nMaxPeakAllocSize < 0)
+    if( nMaxPeakAllocSize < 0 )
     {
         char* pszMaxPeakAllocSize = getenv("CPL_MAX_PEAK_ALLOC_SIZE");
-        nMaxPeakAllocSize = (pszMaxPeakAllocSize) ? atoi(pszMaxPeakAllocSize) : 0;
+        nMaxPeakAllocSize = pszMaxPeakAllocSize ? atoi(pszMaxPeakAllocSize) : 0;
     }
-    if (nMaxPeakAllocSize > 0 && (GIntBig)nNewSize > nMaxPeakAllocSize)
+    if( nMaxPeakAllocSize > 0 &&
+        static_cast<GIntBig>(nNewSize) > nMaxPeakAllocSize )
         return NULL;
 #ifdef DEBUG_VSIMALLOC_STATS
-    if (nMaxCumulAllocSize > 0 && (GIntBig)nCurrentTotalAllocs + (GIntBig)nNewSize - (GIntBig)nOldSize > nMaxCumulAllocSize)
+    if( nMaxCumulAllocSize > 0 &&
+        static_cast<GIntBig>(nCurrentTotalAllocs) +
+        static_cast<GIntBig>(nNewSize) -
+        static_cast<GIntBig>(nOldSize) > nMaxCumulAllocSize )
         return NULL;
 #endif
 
@@ -643,9 +706,19 @@ void * VSIRealloc( void * pData, size_t nNewSize )
 
 #ifdef DEBUG_VSIMALLOC_MPROTECT
     char* newptr = NULL;
-    size_t nPageSize = getpagesize();
-    posix_memalign((void**)&newptr, nPageSize, (nNewSize + 3 * sizeof(void*) + nPageSize - 1) & ~(nPageSize - 1));
-    if (newptr == NULL)
+    const size_t nPageSize = getpagesize();
+    const size_t nRequestedSize =
+        (nNewSize + 3 * sizeof(void*) + nPageSize - 1) & ~(nPageSize - 1);
+    if( nRequestedSize < nNewSize )
+    {
+        ptr[2 * sizeof(void*) + nOldSize + 0] = 'E';
+        ptr[2 * sizeof(void*) + nOldSize + 1] = 'V';
+        ptr[2 * sizeof(void*) + nOldSize + 2] = 'S';
+        ptr[2 * sizeof(void*) + nOldSize + 3] = 'I';
+        return NULL;
+    }
+    posix_memalign((void**)&newptr, nPageSize, nRequestedSize);
+    if( newptr == NULL )
     {
         ptr[2 * sizeof(void*) + nOldSize + 0] = 'E';
         ptr[2 * sizeof(void*) + nOldSize + 1] = 'V';
@@ -664,8 +737,17 @@ void * VSIRealloc( void * pData, size_t nNewSize )
     newptr[2] = 'I';
     newptr[3] = 'M';
 #else
-    void* newptr = realloc(ptr, nNewSize + 3 * sizeof(void*));
-    if (newptr == NULL)
+    const size_t nRequestedSize = 3 * sizeof(void*) + nNewSize;
+    if( nRequestedSize < nNewSize )
+    {
+        ptr[2 * sizeof(void*) + nOldSize + 0] = 'E';
+        ptr[2 * sizeof(void*) + nOldSize + 1] = 'V';
+        ptr[2 * sizeof(void*) + nOldSize + 2] = 'S';
+        ptr[2 * sizeof(void*) + nOldSize + 3] = 'I';
+        return NULL;
+    }
+    void* newptr = realloc(ptr, nRequestedSize);
+    if( newptr == NULL )
     {
         ptr[2 * sizeof(void*) + nOldSize + 0] = 'E';
         ptr[2 * sizeof(void*) + nOldSize + 1] = 'V';
@@ -674,7 +756,8 @@ void * VSIRealloc( void * pData, size_t nNewSize )
         return NULL;
     }
 #endif
-    ptr = (char*) newptr;
+    ptr = static_cast<char *>(newptr);
+    // cppcheck-suppress pointerSize
     memcpy(ptr + sizeof(void*), &nNewSize, sizeof(void*));
     ptr[2 * sizeof(void*) + nNewSize + 0] = 'E';
     ptr[2 * sizeof(void*) + nNewSize + 1] = 'V';
@@ -687,15 +770,35 @@ void * VSIRealloc( void * pData, size_t nNewSize )
 #ifdef DEBUG_VSIMALLOC_VERBOSE
         if( nNewSize > THRESHOLD_PRINT )
         {
-            fprintf(stderr, "Thread[%p] VSIRealloc(%p, %d) = %p\n",
-                    (void*)CPLGetPID(), pData, (int)nNewSize, ptr + 2 * sizeof(void*));
+            fprintf(stderr, "Thread[%p] VSIRealloc(%p, %d) = %p"/*ok*/
+#ifdef DEBUG_VSIMALLOC_STATS
+                    ", current_cumul = " CPL_FRMT_GUIB
+#ifdef DEBUG_BLOCK_CACHE_USE
+                    ", block_cache_used = " CPL_FRMT_GIB
+#endif
+                    ", mal+cal-free = %d"
+#endif
+                    "\n",
+                    (void*)CPLGetPID(),
+                    pData,
+                    static_cast<int>(nNewSize),
+                    ptr + 2 * sizeof(void*)
+#ifdef DEBUG_VSIMALLOC_STATS
+                    , static_cast<GUIntBig>(
+                        nCurrentTotalAllocs - nOldSize + nNewSize)
+#ifdef DEBUG_BLOCK_CACHE_USE
+                    , GDALGetCacheUsed64()
+#endif
+                    , static_cast<int>(nVSIMallocs + nVSICallocs - nVSIFrees)
+#endif
+                    );
         }
 #endif
 #ifdef DEBUG_VSIMALLOC_STATS
-        nVSIReallocs ++;
+        nVSIReallocs++;
         nCurrentTotalAllocs -= nOldSize;
         nCurrentTotalAllocs += nNewSize;
-        if (nCurrentTotalAllocs > nMaxTotalAllocs)
+        if( nCurrentTotalAllocs > nMaxTotalAllocs )
             nMaxTotalAllocs = nCurrentTotalAllocs;
 #endif
     }
@@ -710,16 +813,18 @@ void * VSIRealloc( void * pData, size_t nNewSize )
 /*                              VSIFree()                               */
 /************************************************************************/
 
+/** Analog of free() for data allocated with VSIMalloc(), VSICalloc(), VSIRealloc() */
 void VSIFree( void * pData )
 
 {
 #ifdef DEBUG_VSIMALLOC
-    if (pData == NULL)
+    if( pData == NULL )
         return;
 
     char* ptr = ((char*)pData) - 2 * sizeof(void*);
     VSICheckMarkerBegin(ptr);
     size_t nOldSize = 0;
+    // cppcheck-suppress pointerSize
     memcpy(&nOldSize, ptr + sizeof(void*), sizeof(void*));
     VSICheckMarkerEnd(ptr, 2 * sizeof(void*) + nOldSize);
     ptr[0] = 'M';
@@ -736,12 +841,12 @@ void VSIFree( void * pData )
 #ifdef DEBUG_VSIMALLOC_VERBOSE
         if( nOldSize > THRESHOLD_PRINT )
         {
-            fprintf(stderr, "Thread[%p] VSIFree(%p, (%d bytes))\n",
-                    (void*)CPLGetPID(), pData, (int)nOldSize);
+            fprintf(stderr, "Thread[%p] VSIFree(%p, (%d bytes))\n", /*ok*/
+                    (void*)CPLGetPID(), pData, static_cast<int>(nOldSize));
         }
 #endif
 #ifdef DEBUG_VSIMALLOC_STATS
-        nVSIFrees ++;
+        nVSIFrees++;
         nCurrentTotalAllocs -= nOldSize;
 #endif
     }
@@ -760,15 +865,129 @@ void VSIFree( void * pData )
 }
 
 /************************************************************************/
+/*                      VSIMallocAligned()                              */
+/************************************************************************/
+
+/** Allocates a buffer with an alignment constraint.
+ *
+ * The return value must be freed with VSIFreeAligned().
+ *
+ * @param nAlignment Must be a power of 2, multiple of sizeof(void*), and
+ *                   lesser than 256.
+ * @param nSize Size of the buffer to allocate.
+ * @return a buffer aligned on nAlignment and of size nSize, or NULL
+ * @since GDAL 2.2
+ */
+
+void* VSIMallocAligned( size_t nAlignment, size_t nSize )
+{
+#if defined(HAVE_POSIX_MEMALIGN) && !defined(DEBUG_VSIMALLOC)
+    void* pRet = NULL;
+    if( posix_memalign( &pRet, nAlignment, nSize ) != 0 )
+    {
+        pRet = NULL;
+    }
+    return pRet;
+#elif defined(_WIN32) && !defined(DEBUG_VSIMALLOC)
+    return _aligned_malloc( nSize, nAlignment );
+#else
+    // Check constraints on alignment.
+    if( nAlignment < sizeof(void*) || nAlignment >= 256 ||
+        (nAlignment & (nAlignment - 1)) != 0 )
+        return NULL;
+    // Detect overflow.
+    if( nSize + nAlignment < nSize )
+        return NULL;
+    // TODO(schwehr): C++11 has std::aligned_storage, alignas, and related.
+    GByte* pabyData = static_cast<GByte*>(VSIMalloc( nSize + nAlignment ));
+    if( pabyData == NULL )
+        return NULL;
+    size_t nShift =
+        nAlignment - (reinterpret_cast<size_t>(pabyData) % nAlignment);
+    GByte* pabyAligned = pabyData + nShift;
+    // Guaranteed to fit on a byte since nAlignment < 256.
+    pabyAligned[-1] = static_cast<GByte>(nShift);
+    return pabyAligned;
+#endif
+}
+
+/************************************************************************/
+/*                     VSIMallocAlignedAuto()                           */
+/************************************************************************/
+
+/** Allocates a buffer with an alignment constraint such that it can be
+ * used by the most demanding vector instruction set on that platform.
+ *
+ * The return value must be freed with VSIFreeAligned().
+ *
+ * @param nSize Size of the buffer to allocate.
+ * @return an aligned buffer of size nSize, or NULL
+ * @since GDAL 2.2
+ */
+
+void* VSIMallocAlignedAuto( size_t nSize )
+{
+    // We could potentially dynamically detect the capability of the CPU
+    // but to simplify use 64 for AVX512 requirements (we use only AVX256
+    // currently).
+    return VSIMallocAligned(64, nSize);
+}
+
+/************************************************************************/
+/*                        VSIMallocAlignedAutoVerbose()                 */
+/************************************************************************/
+
+/** See VSIMallocAlignedAuto() */
+void *VSIMallocAlignedAutoVerbose( size_t nSize, const char* pszFile,
+                                   int nLine )
+{
+    void* pRet = VSIMallocAlignedAuto(nSize);
+    if( pRet == NULL && nSize != 0 )
+    {
+        CPLError(CE_Failure, CPLE_OutOfMemory,
+                 "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
+                 pszFile ? pszFile : "(unknown file)",
+                 nLine, static_cast<GUIntBig>(nSize));
+    }
+    return pRet;
+}
+
+/************************************************************************/
+/*                        VSIFreeAligned()                              */
+/************************************************************************/
+
+/** Free a buffer allocated with VSIMallocAligned().
+ *
+ * @param ptr Buffer to free.
+ * @since GDAL 2.2
+ */
+
+void VSIFreeAligned( void* ptr )
+{
+#if defined(HAVE_POSIX_MEMALIGN) && !defined(DEBUG_VSIMALLOC)
+    free(ptr);
+#elif defined(_WIN32) && !defined(DEBUG_VSIMALLOC)
+    _aligned_free(ptr);
+#else
+    if( ptr == NULL )
+        return;
+    GByte* pabyAligned = static_cast<GByte*>(ptr);
+    size_t nShift = pabyAligned[-1];
+    VSIFree( pabyAligned - nShift );
+#endif
+}
+
+/************************************************************************/
 /*                             VSIStrdup()                              */
 /************************************************************************/
 
+/** Analog of strdup(). Use VSIFree() to free */
 char *VSIStrdup( const char * pszString )
 
 {
     const size_t nSize = strlen(pszString) + 1;
     char* ptr = static_cast<char*>( VSIMalloc(nSize) );
-    if (ptr == NULL)
+    if( ptr == NULL )
         return NULL;
     memcpy(ptr, pszString, nSize);
     return ptr;
@@ -778,32 +997,34 @@ char *VSIStrdup( const char * pszString )
 /*                          VSICheckMul2()                              */
 /************************************************************************/
 
-static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag,
+static size_t VSICheckMul2( size_t mul1, size_t mul2, bool *pbOverflowFlag,
                             const char* pszFile, int nLine )
 {
     const size_t res = mul1 * mul2;
-    if (mul1 != 0)
+    if( mul1 != 0 )
     {
-        if (res / mul1 == mul2)
+        if( res / mul1 == mul2 )
         {
-            if (pbOverflowFlag)
+            if( pbOverflowFlag )
                 *pbOverflowFlag = FALSE;
             return res;
         }
         else
         {
-            if (pbOverflowFlag)
+            if( pbOverflowFlag )
                 *pbOverflowFlag = TRUE;
             CPLError(CE_Failure, CPLE_OutOfMemory,
-                     "%s: %d: Multiplication overflow : " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB,
+                     "%s: %d: Multiplication overflow : " CPL_FRMT_GUIB
+                     " * " CPL_FRMT_GUIB,
                      pszFile ? pszFile : "(unknown file)",
                      nLine,
-                     (GUIntBig)mul1, (GUIntBig)mul2);
+                     static_cast<GUIntBig>(mul1),
+                     static_cast<GUIntBig>(mul2));
         }
     }
     else
     {
-        if (pbOverflowFlag)
+        if( pbOverflowFlag )
              *pbOverflowFlag = FALSE;
     }
     return 0;
@@ -813,61 +1034,66 @@ static size_t VSICheckMul2( size_t mul1, size_t mul2, int *pbOverflowFlag,
 /*                          VSICheckMul3()                              */
 /************************************************************************/
 
-static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3, int *pbOverflowFlag,
+static size_t VSICheckMul3( size_t mul1, size_t mul2, size_t mul3,
+                            bool *pbOverflowFlag,
                             const char* pszFile, int nLine )
 {
-    if (mul1 != 0)
+    if( mul1 != 0 )
     {
         const size_t res = mul1 * mul2;
-        if (res / mul1 == mul2)
+        if( res / mul1 == mul2 )
         {
             const size_t res2 = res * mul3;
-            if (mul3 != 0)
+            if( mul3 != 0 )
             {
-                if (res2 / mul3 == res)
+                if( res2 / mul3 == res )
                 {
-                    if (pbOverflowFlag)
-                        *pbOverflowFlag = FALSE;
+                    if( pbOverflowFlag )
+                        *pbOverflowFlag = false;
                     return res2;
                 }
                 else
                 {
-                    if (pbOverflowFlag)
-                        *pbOverflowFlag = TRUE;
+                    if( pbOverflowFlag )
+                        *pbOverflowFlag = true;
                     CPLError(CE_Failure, CPLE_OutOfMemory,
-                            "%s: %d: Multiplication overflow : " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB,
-                            pszFile ? pszFile : "(unknown file)",
-                            nLine,
-                            (GUIntBig)mul1, (GUIntBig)mul2, (GUIntBig)mul3);
+                             "%s: %d: Multiplication overflow : " CPL_FRMT_GUIB
+                             " * " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB,
+                             pszFile ? pszFile : "(unknown file)",
+                             nLine,
+                             static_cast<GUIntBig>(mul1),
+                             static_cast<GUIntBig>(mul2),
+                             static_cast<GUIntBig>(mul3));
                 }
             }
             else
             {
-                if (pbOverflowFlag)
-                    *pbOverflowFlag = FALSE;
+                if( pbOverflowFlag )
+                    *pbOverflowFlag = false;
             }
         }
         else
         {
-            if (pbOverflowFlag)
-                *pbOverflowFlag = TRUE;
+            if( pbOverflowFlag )
+                *pbOverflowFlag = true;
             CPLError(CE_Failure, CPLE_OutOfMemory,
-                    "%s: %d: Multiplication overflow : " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB " * " CPL_FRMT_GUIB,
-                    pszFile ? pszFile : "(unknown file)",
-                    nLine,
-                    (GUIntBig)mul1, (GUIntBig)mul2, (GUIntBig)mul3);
+                     "%s: %d: Multiplication overflow : " CPL_FRMT_GUIB " * "
+                     CPL_FRMT_GUIB " * " CPL_FRMT_GUIB,
+                     pszFile ? pszFile : "(unknown file)",
+                     nLine,
+                     static_cast<GUIntBig>(mul1),
+                     static_cast<GUIntBig>(mul2),
+                     static_cast<GUIntBig>(mul3));
         }
     }
     else
     {
-        if (pbOverflowFlag)
-             *pbOverflowFlag = FALSE;
+        if( pbOverflowFlag )
+             *pbOverflowFlag = false;
     }
     return 0;
 }
 
-
-
 /**
  VSIMalloc2 allocates (nSize1 * nSize2) bytes.
  In case of overflow of the multiplication, or if memory allocation fails, a
@@ -884,8 +1110,9 @@ void CPL_DLL *VSIMalloc2( size_t nSize1, size_t nSize2 )
  VSIMalloc3 allocates (nSize1 * nSize2 * nSize3) bytes.
  In case of overflow of the multiplication, or if memory allocation fails, a
  NULL pointer is returned and a CE_Failure error is raised with CPLError().
- If nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be returned.
- CPLFree() or VSIFree() can be used to free memory allocated by this function.
+ If nSize1 == 0 || nSize2 == 0 || nSize3 == 0, a NULL pointer will also be
+ returned.  CPLFree() or VSIFree() can be used to free memory allocated by this
+ function.
 */
 void CPL_DLL *VSIMalloc3( size_t nSize1, size_t nSize2, size_t nSize3 )
 {
@@ -904,7 +1131,7 @@ void *VSIMallocVerbose( size_t nSize, const char* pszFile, int nLine )
         CPLError(CE_Failure, CPLE_OutOfMemory,
                  "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
                  pszFile ? pszFile : "(unknown file)",
-                 nLine, (GUIntBig)nSize);
+                 nLine, static_cast<GUIntBig>(nSize));
     }
     return pRet;
 }
@@ -913,11 +1140,13 @@ void *VSIMallocVerbose( size_t nSize, const char* pszFile, int nLine )
 /*                          VSIMalloc2Verbose()                         */
 /************************************************************************/
 
-void *VSIMalloc2Verbose( size_t nSize1, size_t nSize2, const char* pszFile, int nLine )
+void *VSIMalloc2Verbose( size_t nSize1, size_t nSize2, const char* pszFile,
+                         int nLine )
 {
-    int bOverflowFlag = FALSE;
-    size_t nSizeToAllocate = VSICheckMul2( nSize1, nSize2, &bOverflowFlag, pszFile, nLine );
-    if (bOverflowFlag || nSizeToAllocate == 0)
+    bool bOverflowFlag = false;
+    const size_t nSizeToAllocate =
+        VSICheckMul2( nSize1, nSize2, &bOverflowFlag, pszFile, nLine );
+    if( bOverflowFlag || nSizeToAllocate == 0 )
         return NULL;
 
     void* pRet = VSIMalloc(nSizeToAllocate);
@@ -926,7 +1155,8 @@ void *VSIMalloc2Verbose( size_t nSize1, size_t nSize2, const char* pszFile, int
         CPLError(CE_Failure, CPLE_OutOfMemory,
                  "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
                  pszFile ? pszFile : "(unknown file)",
-                 nLine, (GUIntBig)nSize1 * (GUIntBig)nSize2);
+                 nLine,
+                 static_cast<GUIntBig>(nSize1) * static_cast<GUIntBig>(nSize2));
     }
     return pRet;
 }
@@ -938,10 +1168,10 @@ void *VSIMalloc2Verbose( size_t nSize1, size_t nSize2, const char* pszFile, int
 void *VSIMalloc3Verbose( size_t nSize1, size_t nSize2, size_t nSize3,
                          const char* pszFile, int nLine )
 {
-    int bOverflowFlag = FALSE;
+    bool bOverflowFlag = false;
     size_t nSizeToAllocate = VSICheckMul3( nSize1, nSize2, nSize3,
                                            &bOverflowFlag, pszFile, nLine );
-    if (bOverflowFlag || nSizeToAllocate == 0)
+    if( bOverflowFlag || nSizeToAllocate == 0 )
         return NULL;
 
     void* pRet = VSIMalloc(nSizeToAllocate);
@@ -950,7 +1180,9 @@ void *VSIMalloc3Verbose( size_t nSize1, size_t nSize2, size_t nSize3,
         CPLError(CE_Failure, CPLE_OutOfMemory,
                  "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
                  pszFile ? pszFile : "(unknown file)",
-                 nLine, (GUIntBig)nSize1 * (GUIntBig)nSize2 * (GUIntBig)nSize3);
+                 nLine,
+                 static_cast<GUIntBig>(nSize1) * static_cast<GUIntBig>(nSize2) *
+                 static_cast<GUIntBig>(nSize3));
     }
     return pRet;
 }
@@ -958,7 +1190,8 @@ void *VSIMalloc3Verbose( size_t nSize1, size_t nSize2, size_t nSize3,
 /*                          VSICallocVerbose()                          */
 /************************************************************************/
 
-void *VSICallocVerbose(  size_t nCount, size_t nSize, const char* pszFile, int nLine )
+void *VSICallocVerbose( size_t nCount, size_t nSize, const char* pszFile,
+                        int nLine )
 {
     void* pRet = VSICalloc(nCount, nSize);
     if( pRet == NULL && nCount != 0 && nSize != 0 )
@@ -966,7 +1199,8 @@ void *VSICallocVerbose(  size_t nCount, size_t nSize, const char* pszFile, int n
         CPLError(CE_Failure, CPLE_OutOfMemory,
                  "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
                  pszFile ? pszFile : "(unknown file)",
-                 nLine, (GUIntBig)nCount * (GUIntBig)nSize);
+                 nLine,
+                 static_cast<GUIntBig>(nCount) * static_cast<GUIntBig>(nSize));
     }
     return pRet;
 }
@@ -975,7 +1209,8 @@ void *VSICallocVerbose(  size_t nCount, size_t nSize, const char* pszFile, int n
 /*                          VSIReallocVerbose()                         */
 /************************************************************************/
 
-void *VSIReallocVerbose( void* pOldPtr, size_t nNewSize, const char* pszFile, int nLine )
+void *VSIReallocVerbose( void* pOldPtr, size_t nNewSize, const char* pszFile,
+                         int nLine )
 {
     void* pRet = VSIRealloc(pOldPtr, nNewSize);
     if( pRet == NULL && nNewSize != 0 )
@@ -983,7 +1218,7 @@ void *VSIReallocVerbose( void* pOldPtr, size_t nNewSize, const char* pszFile, in
         CPLError(CE_Failure, CPLE_OutOfMemory,
                  "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
                  pszFile ? pszFile : "(unknown file)",
-                 nLine, (GUIntBig)(nNewSize));
+                 nLine, static_cast<GUIntBig>(nNewSize));
     }
     return pRet;
 }
@@ -992,7 +1227,7 @@ void *VSIReallocVerbose( void* pOldPtr, size_t nNewSize, const char* pszFile, in
 /*                          VSIStrdupVerbose()                          */
 /************************************************************************/
 
-char *VSIStrdupVerbose(  const char* pszStr, const char* pszFile, int nLine )
+char *VSIStrdupVerbose( const char* pszStr, const char* pszFile, int nLine )
 {
     char* pRet = VSIStrdup(pszStr);
     if( pRet == NULL )
@@ -1000,7 +1235,7 @@ char *VSIStrdupVerbose(  const char* pszStr, const char* pszFile, int nLine )
         CPLError(CE_Failure, CPLE_OutOfMemory,
                  "%s, %d: cannot allocate " CPL_FRMT_GUIB " bytes",
                  pszFile ? pszFile : "(unknown file)",
-                 nLine, (GUIntBig)(strlen(pszStr)+1));
+                 nLine, static_cast<GUIntBig>(strlen(pszStr) + 1));
     }
     return pRet;
 }
@@ -1013,8 +1248,7 @@ int VSIStat( const char * pszFilename, VSIStatBuf * pStatBuf )
 
 {
 #if defined(WIN32)
-    if( CSLTestBoolean(
-            CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
+    if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         wchar_t *pwszFilename =
             CPLRecodeToWChar( pszFilename, CPL_ENC_UTF8, CPL_ENC_UCS2 );
@@ -1097,13 +1331,13 @@ struct tm *VSILocalTime( const time_t *pnTime, struct tm *poBrokenTime )
 /*                            VSIStrerror()                             */
 /************************************************************************/
 
+/** Return the error string corresponding to the error number. Do not free it */
 char *VSIStrerror( int nErrno )
 
 {
     return strerror( nErrno );
 }
 
-
 /************************************************************************/
 /*                        CPLGetPhysicalRAM()                           */
 /************************************************************************/
@@ -1115,10 +1349,13 @@ char *VSIStrerror( int nErrno )
  * @return the total physical RAM in bytes (or 0 in case of failure).
  * @since GDAL 2.0
  */
-GIntBig CPLGetPhysicalRAM(void)
+GIntBig CPLGetPhysicalRAM( void )
 {
-    return static_cast<GIntBig>(sysconf(_SC_PHYS_PAGES))
-        * sysconf(_SC_PAGESIZE);
+    const long nPhysPages = sysconf(_SC_PHYS_PAGES);
+    const long nPageSize = sysconf(_SC_PAGESIZE);
+    if( nPhysPages < 0 || nPageSize < 0 )
+        return 0;
+    return static_cast<GIntBig>(nPhysPages) * nPageSize;
 }
 
 #elif defined(__MACH__) && defined(__APPLE__)
@@ -1139,13 +1376,13 @@ GIntBig CPLGetPhysicalRAM(void)
 
 #elif defined(WIN32)
 
-/* GlobalMemoryStatusEx requires _WIN32_WINNT >= 0x0500 */
+// GlobalMemoryStatusEx requires _WIN32_WINNT >= 0x0500.
 #ifndef _WIN32_WINNT
 #define _WIN32_WINNT 0x0500
 #endif
 #include <windows.h>
 
-GIntBig CPLGetPhysicalRAM(void)
+GIntBig CPLGetPhysicalRAM( void )
 {
     MEMORYSTATUSEX statex;
     statex.ullTotalPhys = 0;
@@ -1156,7 +1393,7 @@ GIntBig CPLGetPhysicalRAM(void)
 
 #else
 
-GIntBig CPLGetPhysicalRAM(void)
+GIntBig CPLGetPhysicalRAM( void )
 {
     static bool bOnce = false;
     if( !bOnce )
@@ -1179,10 +1416,11 @@ GIntBig CPLGetPhysicalRAM(void)
  *
  * Note: This memory may already be partly used by other processes.
  *
- * @return the total physical RAM, usable by a process, in bytes (or 0 in case of failure).
+ * @return the total physical RAM, usable by a process, in bytes (or 0
+ * in case of failure).
  * @since GDAL 2.0
  */
-GIntBig  CPLGetUsablePhysicalRAM(void)
+GIntBig CPLGetUsablePhysicalRAM( void )
 {
     GIntBig nRAM = CPLGetPhysicalRAM();
 #if SIZEOF_VOIDP == 4
diff --git a/port/cpl_worker_thread_pool.cpp b/port/cpl_worker_thread_pool.cpp
index e4a949a..9ea421d 100644
--- a/port/cpl_worker_thread_pool.cpp
+++ b/port/cpl_worker_thread_pool.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: cpl_worker_thread_pool.cpp 35363 2016-09-08 07:35:28Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL worker thread pool
@@ -27,8 +26,18 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_worker_thread_pool.h"
+
+#include <cstddef>
+#include <memory>
+
 #include "cpl_conv.h"
+#include "cpl_error.h"
+#include "cpl_vsi.h"
+
+
+CPL_CVSID("$Id: cpl_worker_thread_pool.cpp 37003 2016-12-23 14:54:07Z goatbar $");
 
 /************************************************************************/
 /*                         CPLWorkerThreadPool()                        */
@@ -109,7 +118,9 @@ void CPLWorkerThreadPool::WorkerThreadFunction(void* user_data)
             psJob->pfnFunc(psJob->pData);
         }
         CPLFree(psJob);
-        //CPLDebug("JOB", "%p finished a job", psWT);
+#if DEBUG_VERBOSE
+        CPLDebug("JOB", "%p finished a job", psWT);
+#endif
         poTP->DeclareJobFinished();
     }
 }
@@ -124,17 +135,19 @@ void CPLWorkerThreadPool::WorkerThreadFunction(void* user_data)
  * @param pData User data to pass to the job function.
  * @return true in case of success.
  */
-bool CPLWorkerThreadPool::SubmitJob(CPLThreadFunc pfnFunc, void* pData)
+bool CPLWorkerThreadPool::SubmitJob( CPLThreadFunc pfnFunc, void* pData )
 {
-    CPLAssert( aWT.size() > 0 );
+    CPLAssert( !aWT.empty() );
 
-    CPLWorkerThreadJob* psJob = (CPLWorkerThreadJob*)VSI_MALLOC_VERBOSE(sizeof(CPLWorkerThreadJob));
+    CPLWorkerThreadJob* psJob = static_cast<CPLWorkerThreadJob *>(
+        VSI_MALLOC_VERBOSE(sizeof(CPLWorkerThreadJob)));
     if( psJob == NULL )
         return false;
     psJob->pfnFunc = pfnFunc;
     psJob->pData = pData;
 
-    CPLList* psItem = (CPLList*) VSI_MALLOC_VERBOSE(sizeof(CPLList));
+    CPLList* psItem =
+        static_cast<CPLList *>(VSI_MALLOC_VERBOSE(sizeof(CPLList)));
     if( psItem == NULL )
     {
         VSIFree(psJob);
@@ -146,13 +159,12 @@ bool CPLWorkerThreadPool::SubmitJob(CPLThreadFunc pfnFunc, void* pData)
 
     psItem->psNext = psJobQueue;
     psJobQueue = psItem;
-    nPendingJobs ++;
+    nPendingJobs++;
 
     if( psWaitingWorkerThreadsList )
     {
-        CPLWorkerThread* psWorkerThread;
-
-        psWorkerThread = (CPLWorkerThread*)psWaitingWorkerThreadsList->pData;
+        CPLWorkerThread* psWorkerThread =
+            static_cast<CPLWorkerThread *>(psWaitingWorkerThreadsList->pData);
 
         CPLAssert( psWorkerThread->bMarkedAsWaiting );
         psWorkerThread->bMarkedAsWaiting = FALSE;
@@ -160,11 +172,14 @@ bool CPLWorkerThreadPool::SubmitJob(CPLThreadFunc pfnFunc, void* pData)
         CPLList* psNext = psWaitingWorkerThreadsList->psNext;
         CPLList* psToFree = psWaitingWorkerThreadsList;
         psWaitingWorkerThreadsList = psNext;
-        nWaitingWorkerThreads --;
+        nWaitingWorkerThreads--;
 
-        //CPLAssert( CPLListCount(psWaitingWorkerThreadsList) == nWaitingWorkerThreads);
+        // CPLAssert(
+        //   CPLListCount(psWaitingWorkerThreadsList) == nWaitingWorkerThreads);
 
-        //CPLDebug("JOB", "Waking up %p", psWorkerThread);
+#if DEBUG_VERBOSE
+        CPLDebug("JOB", "Waking up %p", psWorkerThread);
+#endif
         CPLAcquireMutex(psWorkerThread->hMutex, 1000.0);
         CPLReleaseMutex(hMutex);
         CPLCondSignal(psWorkerThread->hCond);
@@ -173,7 +188,9 @@ bool CPLWorkerThreadPool::SubmitJob(CPLThreadFunc pfnFunc, void* pData)
         CPLFree(psToFree);
     }
     else
+    {
         CPLReleaseMutex(hMutex);
+    }
 
     return true;
 }
@@ -188,9 +205,10 @@ bool CPLWorkerThreadPool::SubmitJob(CPLThreadFunc pfnFunc, void* pData)
  * @param apData User data instances to pass to the job function.
  * @return true in case of success.
  */
-bool CPLWorkerThreadPool::SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<void*>& apData)
+bool CPLWorkerThreadPool::SubmitJobs(CPLThreadFunc pfnFunc,
+                                     const std::vector<void*>& apData)
 {
-    CPLAssert( aWT.size() > 0 );
+    CPLAssert( !aWT.empty() );
 
     CPLAcquireMutex(hMutex, 1000.0);
 
@@ -199,7 +217,8 @@ bool CPLWorkerThreadPool::SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<vo
 
     for(size_t i=0;i<apData.size();i++)
     {
-        CPLWorkerThreadJob* psJob = (CPLWorkerThreadJob*)VSI_MALLOC_VERBOSE(sizeof(CPLWorkerThreadJob));
+        CPLWorkerThreadJob* psJob = static_cast<CPLWorkerThreadJob*>(
+            VSI_MALLOC_VERBOSE(sizeof(CPLWorkerThreadJob)));
         if( psJob == NULL )
         {
             bRet = false;
@@ -208,7 +227,8 @@ bool CPLWorkerThreadPool::SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<vo
         psJob->pfnFunc = pfnFunc;
         psJob->pData = apData[i];
 
-        CPLList* psItem = (CPLList*) VSI_MALLOC_VERBOSE(sizeof(CPLList));
+        CPLList* psItem =
+            static_cast<CPLList *>(VSI_MALLOC_VERBOSE(sizeof(CPLList)));
         if( psItem == NULL )
         {
             VSIFree(psJob);
@@ -219,7 +239,7 @@ bool CPLWorkerThreadPool::SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<vo
 
         psItem->psNext = psJobQueue;
         psJobQueue = psItem;
-        nPendingJobs ++;
+        nPendingJobs++;
     }
 
     if( !bRet )
@@ -229,7 +249,7 @@ bool CPLWorkerThreadPool::SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<vo
             CPLList* psNext = psIter->psNext;
             VSIFree(psIter->pData);
             VSIFree(psIter);
-            nPendingJobs --;
+            nPendingJobs--;
             psIter = psNext;
         }
     }
@@ -255,18 +275,23 @@ bool CPLWorkerThreadPool::SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<vo
             CPLList* psNext = psWaitingWorkerThreadsList->psNext;
             CPLList* psToFree = psWaitingWorkerThreadsList;
             psWaitingWorkerThreadsList = psNext;
-            nWaitingWorkerThreads --;
+            nWaitingWorkerThreads--;
 
-            //CPLAssert( CPLListCount(psWaitingWorkerThreadsList) == nWaitingWorkerThreads);
+            // CPLAssert(
+            //    CPLListCount(psWaitingWorkerThreadsList) ==
+            //    nWaitingWorkerThreads);
 
-            //CPLDebug("JOB", "Waking up %p", psWorkerThread);
+#if DEBUG_VERBOSE
+            CPLDebug("JOB", "Waking up %p", psWorkerThread);
+#endif
             CPLAcquireMutex(psWorkerThread->hMutex, 1000.0);
 
-            //CPLAssert(psWorkerThread->psNextJob == NULL);
-            //psWorkerThread->psNextJob = (CPLWorkerThreadJob*)psJobQueue->pData;
-            //psNext = psJobQueue->psNext;
-            //CPLFree(psJobQueue);
-            //psJobQueue = psNext;
+            // CPLAssert(psWorkerThread->psNextJob == NULL);
+            // psWorkerThread->psNextJob =
+            //     (CPLWorkerThreadJob*)psJobQueue->pData;
+            // psNext = psJobQueue->psNext;
+            // CPLFree(psJobQueue);
+            // psJobQueue = psNext;
 
             CPLReleaseMutex(hMutex);
             CPLCondSignal(psWorkerThread->hCond);
@@ -360,9 +385,10 @@ bool CPLWorkerThreadPool::Setup(int nThreads,
         }
 
         aWT[i].bMarkedAsWaiting = FALSE;
-        //aWT[i].psNextJob = NULL;
+        // aWT[i].psNextJob = NULL;
 
-        aWT[i].hThread = CPLCreateJoinableThread(WorkerThreadFunction, &(aWT[i]));
+        aWT[i].hThread =
+            CPLCreateJoinableThread(WorkerThreadFunction, &(aWT[i]));
         if( aWT[i].hThread == NULL )
         {
             nThreads = i;
@@ -397,7 +423,7 @@ bool CPLWorkerThreadPool::Setup(int nThreads,
 void CPLWorkerThreadPool::DeclareJobFinished()
 {
     CPLAcquireMutex(hMutex, 1000.0);
-    nPendingJobs --;
+    nPendingJobs--;
     CPLCondSignal(hCond);
     CPLReleaseMutex(hMutex);
 }
@@ -406,7 +432,8 @@ void CPLWorkerThreadPool::DeclareJobFinished()
 /*                             GetNextJob()                             */
 /************************************************************************/
 
-CPLWorkerThreadJob* CPLWorkerThreadPool::GetNextJob(CPLWorkerThread* psWorkerThread)
+CPLWorkerThreadJob *
+CPLWorkerThreadPool::GetNextJob( CPLWorkerThread* psWorkerThread )
 {
     while(true)
     {
@@ -421,8 +448,11 @@ CPLWorkerThreadJob* CPLWorkerThreadPool::GetNextJob(CPLWorkerThread* psWorkerThr
         {
             psJobQueue = psTopJobIter->psNext;
 
-            //CPLDebug("JOB", "%p got a job", psWorkerThread);
-            CPLWorkerThreadJob* psJob = (CPLWorkerThreadJob*)psTopJobIter->pData;
+#if DEBUG_VERBOSE
+            CPLDebug("JOB", "%p got a job", psWorkerThread);
+#endif
+            CPLWorkerThreadJob* psJob =
+                (CPLWorkerThreadJob*)psTopJobIter->pData;
             CPLReleaseMutex(hMutex);
             CPLFree(psTopJobIter);
             return psJob;
@@ -431,10 +461,11 @@ CPLWorkerThreadJob* CPLWorkerThreadPool::GetNextJob(CPLWorkerThread* psWorkerThr
         if( !psWorkerThread->bMarkedAsWaiting )
         {
             psWorkerThread->bMarkedAsWaiting = TRUE;
-            nWaitingWorkerThreads ++;
-            CPLAssert(nWaitingWorkerThreads <= (int)aWT.size());
+            nWaitingWorkerThreads++;
+            CPLAssert(nWaitingWorkerThreads <= static_cast<int>(aWT.size()));
 
-            CPLList* psItem = (CPLList*) VSI_MALLOC_VERBOSE(sizeof(CPLList));
+            CPLList* psItem =
+                static_cast<CPLList *>(VSI_MALLOC_VERBOSE(sizeof(CPLList)));
             if( psItem == NULL )
             {
                 eState = CPLWTS_ERROR;
@@ -448,23 +479,30 @@ CPLWorkerThreadJob* CPLWorkerThreadPool::GetNextJob(CPLWorkerThread* psWorkerThr
             psItem->psNext = psWaitingWorkerThreadsList;
             psWaitingWorkerThreadsList = psItem;
 
-            //CPLAssert( CPLListCount(psWaitingWorkerThreadsList) == nWaitingWorkerThreads);
+#if DEBUG_VERBOSE
+            CPLAssert(CPLListCount(psWaitingWorkerThreadsList) ==
+                      nWaitingWorkerThreads);
+#endif
         }
 
         CPLCondSignal(hCond);
 
         CPLAcquireMutex(psWorkerThread->hMutex, 1000.0);
-        //CPLDebug("JOB", "%p sleeping", psWorkerThread);
+#if DEBUG_VERBOSE
+        CPLDebug("JOB", "%p sleeping", psWorkerThread);
+#endif
         CPLReleaseMutex(hMutex);
 
         CPLCondWait( psWorkerThread->hCond, psWorkerThread->hMutex );
 
-        //CPLWorkerThreadJob* psJob = psWorkerThread->psNextJob;
-        //psWorkerThread->psNextJob = NULL;
+        // TODO(rouault): Explain or delete.
+        // CPLWorkerThreadJob* psJob = psWorkerThread->psNextJob;
+        // psWorkerThread->psNextJob = NULL;
 
         CPLReleaseMutex(psWorkerThread->hMutex);
 
-        //if( psJob )
+        // TODO(rouault): Explain or delete.
+        // if( psJob )
         //    return psJob;
     }
 }
diff --git a/port/cpl_worker_thread_pool.h b/port/cpl_worker_thread_pool.h
index d9a4331..9956b3e 100644
--- a/port/cpl_worker_thread_pool.h
+++ b/port/cpl_worker_thread_pool.h
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: cpl_worker_thread_pool.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cpl_worker_thread_pool.h 37003 2016-12-23 14:54:07Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  CPL worker thread pool
@@ -41,6 +41,7 @@
  * @since GDAL 2.1
  */
 
+#ifndef DOXYGEN_SKIP
 class CPLWorkerThreadPool;
 
 typedef struct
@@ -56,7 +57,7 @@ typedef struct
     CPLWorkerThreadPool *poTP;
     CPLJoinableThread   *hThread;
     int                  bMarkedAsWaiting;
-    //CPLWorkerThreadJob  *psNextJob;
+    // CPLWorkerThreadJob  *psNextJob;
 
     CPLMutex            *hMutex;
     CPLCond             *hCond;
@@ -68,7 +69,9 @@ typedef enum
     CPLWTS_STOP,
     CPLWTS_ERROR
 } CPLWorkerThreadState;
+#endif  // ndef DOXYGEN_SKIP
 
+/** Pool of worker threads */
 class CPL_DLL CPLWorkerThreadPool
 {
         std::vector<CPLWorkerThread> aWT;
@@ -97,6 +100,7 @@ class CPL_DLL CPLWorkerThreadPool
         bool SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<void*>& apData);
         void WaitCompletion(int nMaxRemainingJobs = 0);
 
+        /** Return the number of threads setup */
         int GetThreadCount() const { return (int)aWT.size(); }
 };
 
diff --git a/port/cpl_xml_validate.cpp b/port/cpl_xml_validate.cpp
index 8d4fa52..00ba60e 100644
--- a/port/cpl_xml_validate.cpp
+++ b/port/cpl_xml_validate.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cpl_xml_validate.cpp 32883 2016-01-09 18:24:40Z rouault $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Implement XML validation against XSD schema
@@ -27,22 +26,24 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_conv.h"
+#include "cpl_error.h"
 
-CPL_CVSID("$Id: cpl_xml_validate.cpp 32883 2016-01-09 18:24:40Z rouault $");
+CPL_CVSID("$Id: cpl_xml_validate.cpp 36911 2016-12-16 19:42:07Z goatbar $");
 
 #ifdef HAVE_LIBXML2
 #include <libxml/xmlversion.h>
 #if defined(LIBXML_VERSION) && LIBXML_VERSION >= 20622
-/* We need at least 2.6.20 for xmlSchemaValidateDoc */
-/* and xmlParseDoc to accept a const xmlChar* */
-/* We could workaround it, but likely not worth the effort for now. */
-/* Actually, we need at least 2.6.22, at runtime, to be */
-/* able to parse the OGC GML schemas */
+// We need at least 2.6.20 for xmlSchemaValidateDoc
+// and xmlParseDoc to accept a const xmlChar*
+// We could workaround it, but likely not worth the effort for now.
+// Actually, we need at least 2.6.22, at runtime, to be
+// able to parse the OGC GML schemas
 #define HAVE_RECENT_LIBXML2
 
-/* libxml2 before 2.8.0 had a bug to parse the OGC GML schemas */
-/* We have a workaround for that for versions >= 2.6.20 and < 2.8.0 */
+// libxml2 before 2.8.0 had a bug to parse the OGC GML schemas
+// We have a workaround for that for versions >= 2.6.20 and < 2.8.0.
 #if defined(LIBXML_VERSION) && LIBXML_VERSION < 20800
 #define HAS_VALIDATION_BUG
 #endif
@@ -54,10 +55,21 @@ CPL_CVSID("$Id: cpl_xml_validate.cpp 32883 2016-01-09 18:24:40Z rouault $");
 
 #ifdef HAVE_RECENT_LIBXML2
 #include <string.h>
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wdocumentation"
+#endif
+
 #include <libxml/xmlschemas.h>
 #include <libxml/parserInternals.h>
 #include <libxml/catalog.h>
 
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
 #include "cpl_string.h"
 #include "cpl_hash_set.h"
 #include "cpl_minixml.h"
@@ -68,25 +80,25 @@ static xmlExternalEntityLoader pfnLibXMLOldExtranerEntityLoader = NULL;
 /*                            CPLFixPath()                              */
 /************************************************************************/
 
-/* Replace \ by / to make libxml2 happy on Windows and */
-/* replace "a/b/../c" pattern by "a/c" */
+// Replace \ by / to make libxml2 happy on Windows and
+// replace "a/b/../c" pattern by "a/c".
 static void CPLFixPath(char* pszPath)
 {
-    for(int i=0;pszPath[i] != '\0';i++)
+    for( int i = 0; pszPath[i] != '\0'; ++i )
     {
-        if (pszPath[i] == '\\')
+        if( pszPath[i] == '\\' )
             pszPath[i] = '/';
     }
 
-    while(true)
+    while( true )
     {
         char* pszSlashDotDot = strstr(pszPath, "/../");
-        if (pszSlashDotDot == NULL || pszSlashDotDot == pszPath)
+        if( pszSlashDotDot == NULL || pszSlashDotDot == pszPath )
             return;
-        char* pszSlashBefore = pszSlashDotDot-1;
-        while(pszSlashBefore > pszPath && *pszSlashBefore != '/')
-            pszSlashBefore --;
-        if (pszSlashBefore == pszPath)
+        char* pszSlashBefore = pszSlashDotDot - 1;
+        while( pszSlashBefore > pszPath && *pszSlashBefore != '/' )
+            pszSlashBefore--;
+        if( pszSlashBefore == pszPath )
             return;
         memmove(pszSlashBefore + 1, pszSlashDotDot + 4,
                 strlen(pszSlashDotDot + 4) + 1);
@@ -95,16 +107,13 @@ static void CPLFixPath(char* pszPath)
 
 #ifdef HAS_VALIDATION_BUG
 
-static int bHasLibXMLBug = -1;
-
 /************************************************************************/
 /*                  CPLHasLibXMLBugWarningCallback()                    */
 /************************************************************************/
 
-static void CPLHasLibXMLBugWarningCallback (void * /*ctx*/,
-                                            const char* /*msg*/, ...)
-{
-}
+static void CPLHasLibXMLBugWarningCallback ( void * /*ctx*/,
+                                             const char* /*msg*/, ... )
+{}
 
 /************************************************************************/
 /*                          CPLHasLibXMLBug()                           */
@@ -112,54 +121,58 @@ static void CPLHasLibXMLBugWarningCallback (void * /*ctx*/,
 
 static bool CPLHasLibXMLBug()
 {
-    if (bHasLibXMLBug >= 0)
-        return CPL_TO_BOOL(bHasLibXMLBug);
+    static bool bHasLibXMLBug = false;
+    static bool bLibXMLBugChecked = false;
+    if( bLibXMLBugChecked )
+        return bHasLibXMLBug;
 
     static const char szLibXMLBugTester[] =
-    "<schema targetNamespace=\"http://foo\" xmlns:foo=\"http://foo\" xmlns=\"http://www.w3.org/2001/XMLSchema\">"
-    "<simpleType name=\"t1\">"
-    "<list itemType=\"double\"/>"
-    "</simpleType>"
-    "<complexType name=\"t2\">"
-    "<simpleContent>"
-    "<extension base=\"foo:t1\"/>"
-    "</simpleContent>"
-    "</complexType>"
-    "<complexType name=\"t3\">"
-    "<simpleContent>"
-    "<restriction base=\"foo:t2\">"
-    "<length value=\"2\"/>"
-    "</restriction>"
-    "</simpleContent>"
-    "</complexType>"
-    "</schema>";
+        "<schema targetNamespace=\"http://foo\" "
+        "xmlns:foo=\"http://foo\" xmlns=\"http://www.w3.org/2001/XMLSchema\">"
+        "<simpleType name=\"t1\">"
+        "<list itemType=\"double\"/>"
+        "</simpleType>"
+        "<complexType name=\"t2\">"
+        "<simpleContent>"
+        "<extension base=\"foo:t1\"/>"
+        "</simpleContent>"
+        "</complexType>"
+        "<complexType name=\"t3\">"
+        "<simpleContent>"
+        "<restriction base=\"foo:t2\">"
+        "<length value=\"2\"/>"
+        "</restriction>"
+        "</simpleContent>"
+        "</complexType>"
+        "</schema>";
 
-    xmlSchemaParserCtxtPtr pSchemaParserCtxt;
-    xmlSchemaPtr pSchema;
-
-    pSchemaParserCtxt = xmlSchemaNewMemParserCtxt(szLibXMLBugTester, strlen(szLibXMLBugTester));
+    xmlSchemaParserCtxtPtr pSchemaParserCtxt =
+        xmlSchemaNewMemParserCtxt(szLibXMLBugTester, strlen(szLibXMLBugTester));
 
     xmlSchemaSetParserErrors(pSchemaParserCtxt,
                              CPLHasLibXMLBugWarningCallback,
                              CPLHasLibXMLBugWarningCallback,
                              NULL);
 
-    pSchema = xmlSchemaParse(pSchemaParserCtxt);
+    xmlSchemaPtr pSchema = xmlSchemaParse(pSchemaParserCtxt);
     xmlSchemaFreeParserCtxt(pSchemaParserCtxt);
 
-    bHasLibXMLBug = (pSchema == NULL);
+    bHasLibXMLBug = pSchema == NULL;
+    bLibXMLBugChecked = true;
 
-    if (pSchema)
+    if( pSchema )
         xmlSchemaFree(pSchema);
 
-    if (bHasLibXMLBug)
+    if( bHasLibXMLBug )
     {
-        CPLDebug("CPL",
-                 "LibXML bug found (cf https://bugzilla.gnome.org/show_bug.cgi?id=630130). "
-                 "Will try to workaround for GML schemas.");
+        CPLDebug(
+            "CPL",
+            "LibXML bug found "
+            "(cf https://bugzilla.gnome.org/show_bug.cgi?id=630130). "
+            "Will try to workaround for GML schemas." );
     }
 
-    return CPL_TO_BOOL(bHasLibXMLBug);
+    return bHasLibXMLBug;
 }
 
 #endif
@@ -168,9 +181,11 @@ static bool CPLHasLibXMLBug()
 /*                         CPLExtractSubSchema()                        */
 /************************************************************************/
 
-static CPLXMLNode* CPLExtractSubSchema(CPLXMLNode* psSubXML, CPLXMLNode* psMainSchema)
+static CPLXMLNode* CPLExtractSubSchema( CPLXMLNode* psSubXML,
+                                        CPLXMLNode* psMainSchema )
 {
-    if (psSubXML->eType == CXT_Element && strcmp(psSubXML->pszValue, "?xml") == 0)
+    if( psSubXML->eType == CXT_Element &&
+        strcmp(psSubXML->pszValue, "?xml") == 0 )
     {
         CPLXMLNode* psNext = psSubXML->psNext;
         psSubXML->psNext = NULL;
@@ -178,7 +193,7 @@ static CPLXMLNode* CPLExtractSubSchema(CPLXMLNode* psSubXML, CPLXMLNode* psMainS
         psSubXML = psNext;
     }
 
-    if (psSubXML != NULL && psSubXML->eType == CXT_Comment)
+    if( psSubXML != NULL && psSubXML->eType == CXT_Comment )
     {
         CPLXMLNode* psNext = psSubXML->psNext;
         psSubXML->psNext = NULL;
@@ -186,22 +201,23 @@ static CPLXMLNode* CPLExtractSubSchema(CPLXMLNode* psSubXML, CPLXMLNode* psMainS
         psSubXML = psNext;
     }
 
-    if (psSubXML != NULL && psSubXML->eType == CXT_Element &&
+    if( psSubXML != NULL && psSubXML->eType == CXT_Element &&
         (strcmp(psSubXML->pszValue, "schema") == 0 ||
          strcmp(psSubXML->pszValue, "xs:schema") == 0 ||
          strcmp(psSubXML->pszValue, "xsd:schema") == 0) &&
-        psSubXML->psNext == NULL)
+        psSubXML->psNext == NULL )
     {
         CPLXMLNode* psNext = psSubXML->psChild;
-        while(psNext != NULL && psNext->eType != CXT_Element &&
-              psNext->psNext != NULL && psNext->psNext->eType != CXT_Element)
+        while( psNext != NULL && psNext->eType != CXT_Element &&
+               psNext->psNext != NULL && psNext->psNext->eType != CXT_Element )
         {
-            /* Add xmlns: from subschema to main schema if missing */
-            if (psNext->eType == CXT_Attribute &&
+            // Add xmlns: from subschema to main schema if missing.
+            if( psNext->eType == CXT_Attribute &&
                 STARTS_WITH(psNext->pszValue, "xmlns:") &&
-                CPLGetXMLValue(psMainSchema, psNext->pszValue, NULL) == NULL)
+                CPLGetXMLValue(psMainSchema, psNext->pszValue, NULL) == NULL )
             {
-                CPLXMLNode* psAttr = CPLCreateXMLNode(NULL, CXT_Attribute, psNext->pszValue);
+                CPLXMLNode* psAttr =
+                    CPLCreateXMLNode(NULL, CXT_Attribute, psNext->pszValue);
                 CPLCreateXMLNode(psAttr, CXT_Text, psNext->psChild->pszValue);
 
                 psAttr->psNext = psMainSchema->psChild;
@@ -210,8 +226,8 @@ static CPLXMLNode* CPLExtractSubSchema(CPLXMLNode* psSubXML, CPLXMLNode* psMainS
             psNext = psNext->psNext;
         }
 
-        if (psNext != NULL && psNext->eType != CXT_Element &&
-            psNext->psNext != NULL && psNext->psNext->eType == CXT_Element)
+        if( psNext != NULL && psNext->eType != CXT_Element &&
+            psNext->psNext != NULL && psNext->psNext->eType == CXT_Element )
         {
             CPLXMLNode* psNext2 = psNext->psNext;
             psNext->psNext = NULL;
@@ -228,70 +244,91 @@ static CPLXMLNode* CPLExtractSubSchema(CPLXMLNode* psSubXML, CPLXMLNode* psMainS
 /*                        CPLWorkaroundLibXMLBug()                      */
 /************************************************************************/
 
-/* Return TRUE if the current node must be destroyed */
-static bool CPLWorkaroundLibXMLBug(CPLXMLNode* psIter)
+// Return TRUE if the current node must be destroyed.
+static bool CPLWorkaroundLibXMLBug( CPLXMLNode* psIter )
 {
-    if (psIter->eType == CXT_Element &&
+    if( psIter->eType == CXT_Element &&
         strcmp(psIter->pszValue, "element") == 0 &&
         strcmp(CPLGetXMLValue(psIter, "name", ""), "QuantityExtent") == 0 &&
-        strcmp(CPLGetXMLValue(psIter, "type", ""), "gml:QuantityExtentType") == 0)
+        strcmp(CPLGetXMLValue(psIter, "type", ""),
+               "gml:QuantityExtentType") == 0 )
     {
         CPLXMLNode* psIter2 = psIter->psChild;
-        while(psIter2)
+        while( psIter2 )
         {
-            if (psIter2->eType == CXT_Attribute && strcmp(psIter2->pszValue, "type") == 0)
+            if( psIter2->eType == CXT_Attribute &&
+                strcmp(psIter2->pszValue, "type") == 0 )
             {
                 CPLFree(psIter2->psChild->pszValue);
-                if (strcmp(CPLGetXMLValue(psIter, "substitutionGroup", ""), "gml:AbstractValue") == 0)
-                    psIter2->psChild->pszValue = CPLStrdup("gml:MeasureOrNilReasonListType"); /* GML 3.2.1 */
+                if( strcmp(CPLGetXMLValue(psIter, "substitutionGroup", ""),
+                           "gml:AbstractValue") == 0 )
+                     // GML 3.2.1.
+                    psIter2->psChild->pszValue =
+                        CPLStrdup("gml:MeasureOrNilReasonListType");
                 else
-                    psIter2->psChild->pszValue = CPLStrdup("gml:MeasureOrNullListType");
+                    psIter2->psChild->pszValue =
+                        CPLStrdup("gml:MeasureOrNullListType");
             }
             psIter2 = psIter2->psNext;
         }
     }
 
-    else if (psIter->eType == CXT_Element &&
-        strcmp(psIter->pszValue, "element") == 0 &&
-        strcmp(CPLGetXMLValue(psIter, "name", ""), "CategoryExtent") == 0 &&
-        strcmp(CPLGetXMLValue(psIter, "type", ""), "gml:CategoryExtentType") == 0)
+    else if( psIter->eType == CXT_Element &&
+             strcmp(psIter->pszValue, "element") == 0 &&
+             strcmp(CPLGetXMLValue(psIter, "name", ""),
+                    "CategoryExtent") == 0 &&
+             strcmp(CPLGetXMLValue(psIter, "type", ""),
+                    "gml:CategoryExtentType") == 0 )
     {
         CPLXMLNode* psIter2 = psIter->psChild;
-        while(psIter2)
+        while( psIter2 )
         {
-            if (psIter2->eType == CXT_Attribute && strcmp(psIter2->pszValue, "type") == 0)
+            if( psIter2->eType == CXT_Attribute &&
+                strcmp(psIter2->pszValue, "type") == 0 )
             {
                 CPLFree(psIter2->psChild->pszValue);
-                if (strcmp(CPLGetXMLValue(psIter, "substitutionGroup", ""), "gml:AbstractValue") == 0)
-                    psIter2->psChild->pszValue = CPLStrdup("gml:CodeOrNilReasonListType"); /* GML 3.2.1 */
+                if( strcmp(CPLGetXMLValue(psIter, "substitutionGroup", ""),
+                           "gml:AbstractValue") == 0 )
+                    // GML 3.2.1
+                    psIter2->psChild->pszValue =
+                        CPLStrdup("gml:CodeOrNilReasonListType");
                 else
-                    psIter2->psChild->pszValue = CPLStrdup("gml:CodeOrNullListType");
+                    psIter2->psChild->pszValue =
+                        CPLStrdup("gml:CodeOrNullListType");
             }
             psIter2 = psIter2->psNext;
         }
     }
 
-    else if (bHasLibXMLBug && psIter->eType == CXT_Element &&
+    else if( CPLHasLibXMLBug() && psIter->eType == CXT_Element &&
              strcmp(psIter->pszValue, "complexType") == 0 &&
-             (strcmp(CPLGetXMLValue(psIter, "name", ""), "QuantityExtentType") == 0 ||
-              strcmp(CPLGetXMLValue(psIter, "name", ""), "CategoryExtentType") == 0))
+             (strcmp(CPLGetXMLValue(psIter, "name", ""),
+                     "QuantityExtentType") == 0 ||
+              strcmp(CPLGetXMLValue(psIter, "name", ""),
+                     "CategoryExtentType") == 0) )
     {
-        /* Destroy this element */
+        // Destroy this element.
         return true;
     }
 
-    /* For GML 3.2.1 */
-    else if (psIter->eType == CXT_Element &&
+    // For GML 3.2.1
+    else if( psIter->eType == CXT_Element &&
              strcmp(psIter->pszValue, "complexType") == 0 &&
-             strcmp(CPLGetXMLValue(psIter, "name", ""), "VectorType") == 0)
+             strcmp(CPLGetXMLValue(psIter, "name", ""), "VectorType") == 0 )
     {
-        CPLXMLNode* psSimpleContent = CPLCreateXMLNode(NULL, CXT_Element, "simpleContent");
-        CPLXMLNode* psExtension = CPLCreateXMLNode(psSimpleContent, CXT_Element, "extension");
-        CPLXMLNode* psExtensionBase = CPLCreateXMLNode(psExtension, CXT_Attribute, "base");
+        CPLXMLNode* psSimpleContent =
+            CPLCreateXMLNode(NULL, CXT_Element, "simpleContent");
+        CPLXMLNode* psExtension =
+            CPLCreateXMLNode(psSimpleContent, CXT_Element, "extension");
+        CPLXMLNode* psExtensionBase =
+            CPLCreateXMLNode(psExtension, CXT_Attribute, "base");
         CPLCreateXMLNode(psExtensionBase, CXT_Text, "gml:doubleList");
-        CPLXMLNode* psAttributeGroup = CPLCreateXMLNode(psExtension, CXT_Element, "attributeGroup");
-        CPLXMLNode* psAttributeGroupRef = CPLCreateXMLNode(psAttributeGroup, CXT_Attribute, "ref");
-        CPLCreateXMLNode(psAttributeGroupRef, CXT_Text, "gml:SRSReferenceGroup");
+        CPLXMLNode* psAttributeGroup =
+            CPLCreateXMLNode(psExtension, CXT_Element, "attributeGroup");
+        CPLXMLNode* psAttributeGroupRef =
+            CPLCreateXMLNode(psAttributeGroup, CXT_Attribute, "ref");
+        CPLCreateXMLNode(psAttributeGroupRef, CXT_Text,
+                         "gml:SRSReferenceGroup");
 
         CPLXMLNode* psName = CPLCreateXMLNode(NULL, CXT_Attribute, "name");
         CPLCreateXMLNode(psName, CXT_Text, "VectorType");
@@ -301,20 +338,28 @@ static bool CPLWorkaroundLibXMLBug(CPLXMLNode* psIter)
         psIter->psChild->psNext = psSimpleContent;
     }
 
-    else if (psIter->eType == CXT_Element &&
+    else if( psIter->eType == CXT_Element &&
              strcmp(psIter->pszValue, "element") == 0 &&
-             (strcmp(CPLGetXMLValue(psIter, "name", ""), "domainOfValidity") == 0 ||
-              strcmp(CPLGetXMLValue(psIter, "name", ""), "coordinateOperationAccuracy") == 0 ||
-              strcmp(CPLGetXMLValue(psIter, "name", ""), "formulaCitation") == 0))
+             (strcmp(CPLGetXMLValue(psIter, "name", ""),
+                     "domainOfValidity") == 0 ||
+              strcmp(CPLGetXMLValue(psIter, "name", ""),
+                     "coordinateOperationAccuracy") == 0 ||
+              strcmp(CPLGetXMLValue(psIter, "name", ""),
+                     "formulaCitation") == 0) )
     {
-        CPLXMLNode* psComplexType = CPLCreateXMLNode(NULL, CXT_Element, "complexType");
-        CPLXMLNode* psSequence = CPLCreateXMLNode(psComplexType, CXT_Element, "sequence");
-        CPLXMLNode* psSequenceMinOccurs = CPLCreateXMLNode(psSequence, CXT_Attribute, "minOccurs");
+        CPLXMLNode* psComplexType =
+            CPLCreateXMLNode(NULL, CXT_Element, "complexType");
+        CPLXMLNode* psSequence =
+            CPLCreateXMLNode(psComplexType, CXT_Element, "sequence");
+        CPLXMLNode* psSequenceMinOccurs =
+            CPLCreateXMLNode(psSequence, CXT_Attribute, "minOccurs");
         CPLCreateXMLNode(psSequenceMinOccurs, CXT_Text, "0");
         CPLXMLNode* psAny = CPLCreateXMLNode(psSequence, CXT_Element, "any");
-        CPLXMLNode* psAnyMinOccurs = CPLCreateXMLNode(psAny, CXT_Attribute, "minOccurs");
+        CPLXMLNode* psAnyMinOccurs =
+            CPLCreateXMLNode(psAny, CXT_Attribute, "minOccurs");
         CPLCreateXMLNode(psAnyMinOccurs, CXT_Text, "0");
-        CPLXMLNode* psAnyProcessContents = CPLCreateXMLNode(psAny, CXT_Attribute, " processContents");
+        CPLXMLNode* psAnyProcessContents =
+            CPLCreateXMLNode(psAny, CXT_Attribute, " processContents");
         CPLCreateXMLNode(psAnyProcessContents, CXT_Text, "lax");
 
         CPLXMLNode* psName = CPLCreateXMLNode(NULL, CXT_Attribute, "name");
@@ -334,10 +379,10 @@ static bool CPLWorkaroundLibXMLBug(CPLXMLNode* psIter)
 /************************************************************************/
 
 static
-CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
-                                     const char* pszFile)
+CPLXMLNode* CPLLoadSchemaStrInternal( CPLHashSet* hSetSchemas,
+                                      const char* pszFile )
 {
-    if (CPLHashSetLookup(hSetSchemas, pszFile))
+    if( CPLHashSetLookup(hSetSchemas, pszFile) )
         return NULL;
 
     CPLHashSetInsert(hSetSchemas, CPLStrdup(pszFile));
@@ -345,7 +390,7 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
     CPLDebug("CPL", "Parsing %s", pszFile);
 
     CPLXMLNode* psXML = CPLParseXMLFile(pszFile);
-    if (psXML == NULL)
+    if( psXML == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot open %s", pszFile);
@@ -353,11 +398,15 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
     }
 
     CPLXMLNode* psSchema = CPLGetXMLNode(psXML, "=schema");
-    if (psSchema == NULL)
+    if( psSchema == NULL )
+    {
         psSchema = CPLGetXMLNode(psXML, "=xs:schema");
-    if (psSchema == NULL)
+    }
+    if( psSchema == NULL )
+    {
         psSchema = CPLGetXMLNode(psXML, "=xsd:schema");
-    if (psSchema == NULL)
+    }
+    if( psSchema == NULL )
     {
         CPLError(CE_Failure, CPLE_AppDefined,
                  "Cannot find schema node in %s", pszFile);
@@ -367,37 +416,38 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
 
     CPLXMLNode* psPrev = NULL;
     CPLXMLNode* psIter = psSchema->psChild;
-    while(psIter)
+    while( psIter )
     {
         bool bDestroyCurrentNode = false;
 
 #ifdef HAS_VALIDATION_BUG
-        if (bHasLibXMLBug)
+        if( CPLHasLibXMLBug() )
             bDestroyCurrentNode = CPLWorkaroundLibXMLBug(psIter);
 #endif
 
-        /* Load the referenced schemas, and integrate them in the main schema */
-        if (psIter->eType == CXT_Element &&
+        // Load the referenced schemas, and integrate them in the main schema.
+        if( psIter->eType == CXT_Element &&
             (strcmp(psIter->pszValue, "include") == 0 ||
              strcmp(psIter->pszValue, "xs:include") == 0||
              strcmp(psIter->pszValue, "xsd:include") == 0) &&
             psIter->psChild != NULL &&
             psIter->psChild->eType == CXT_Attribute &&
-            strcmp(psIter->psChild->pszValue, "schemaLocation") == 0)
+            strcmp(psIter->psChild->pszValue, "schemaLocation") == 0 )
         {
             const char* pszIncludeSchema = psIter->psChild->psChild->pszValue;
             char* pszFullFilename = CPLStrdup(
-                CPLFormFilename(CPLGetPath(pszFile), pszIncludeSchema, NULL));
+                CPLFormFilename(CPLGetPath(pszFile), pszIncludeSchema, NULL) );
 
             CPLFixPath(pszFullFilename);
 
             CPLXMLNode* psSubXML = NULL;
 
-            /* If we haven't yet loaded that schema, do it now */
-            if (!CPLHashSetLookup(hSetSchemas, pszFullFilename))
+            // If we haven't yet loaded that schema, do it now.
+            if( !CPLHashSetLookup(hSetSchemas, pszFullFilename) )
             {
-                psSubXML = CPLLoadSchemaStrInternal(hSetSchemas, pszFullFilename);
-                if (psSubXML == NULL)
+                psSubXML =
+                    CPLLoadSchemaStrInternal(hSetSchemas, pszFullFilename);
+                if( psSubXML == NULL )
                 {
                     CPLFree(pszFullFilename);
                     CPLDestroyXMLNode(psXML);
@@ -407,24 +457,24 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
             CPLFree(pszFullFilename);
             pszFullFilename = NULL;
 
-            if (psSubXML)
+            if( psSubXML )
             {
                 CPLXMLNode* psNext = psIter->psNext;
 
                 psSubXML = CPLExtractSubSchema(psSubXML, psSchema);
-                if (psSubXML == NULL)
+                if( psSubXML == NULL )
                 {
                     CPLDestroyXMLNode(psXML);
                     return NULL;
                 }
 
-                /* Replace <include/> node by the subXML */
+                // Replace <include/> node by the subXML.
                 CPLXMLNode* psIter2 = psSubXML;
-                while(psIter2->psNext)
+                while( psIter2->psNext )
                     psIter2 = psIter2->psNext;
                 psIter2->psNext = psNext;
 
-                if (psPrev == NULL)
+                if( psPrev == NULL )
                     psSchema->psChild = psSubXML;
                 else
                     psPrev->psNext = psSubXML;
@@ -438,31 +488,34 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
             }
             else
             {
-                /* We have already included that file, */
-                /* so just remove the <include/> node */
+                // We have already included that file,
+                // so just remove the <include/> node
                 bDestroyCurrentNode = true;
             }
         }
 
-        /* Patch the schemaLocation of <import/> */
-        else if (psIter->eType == CXT_Element &&
-                    (strcmp(psIter->pszValue, "import") == 0 ||
-                     strcmp(psIter->pszValue, "xs:import") == 0||
-                     strcmp(psIter->pszValue, "xsd:import") == 0))
+        // Patch the schemaLocation of <import/>.
+        else if( psIter->eType == CXT_Element &&
+                 (strcmp(psIter->pszValue, "import") == 0 ||
+                  strcmp(psIter->pszValue, "xs:import") == 0||
+                  strcmp(psIter->pszValue, "xsd:import") == 0) )
         {
             CPLXMLNode* psIter2 = psIter->psChild;
-            while(psIter2)
+            while( psIter2 )
             {
-                if (psIter2->eType == CXT_Attribute &&
+                if( psIter2->eType == CXT_Attribute &&
                     strcmp(psIter2->pszValue, "schemaLocation") == 0 &&
                     psIter2->psChild != NULL &&
                     !STARTS_WITH(psIter2->psChild->pszValue, "http://") &&
                     !STARTS_WITH(psIter2->psChild->pszValue, "ftp://") &&
-                    /* If the top file is our warping file, don't alter the path of the import */
+                    // If the top file is our warping file, don't alter the path
+                    // of the import.
                     strstr(pszFile, "/vsimem/CPLValidateXML_") == NULL )
                 {
-                    char* pszFullFilename = CPLStrdup(CPLFormFilename(
-                                      CPLGetPath(pszFile), psIter2->psChild->pszValue, NULL));
+                    char* pszFullFilename =
+                        CPLStrdup(CPLFormFilename(
+                            CPLGetPath(pszFile),
+                            psIter2->psChild->pszValue, NULL ));
                     CPLFixPath(pszFullFilename);
                     CPLFree(psIter2->psChild->pszValue);
                     psIter2->psChild->pszValue = pszFullFilename;
@@ -471,10 +524,10 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
             }
         }
 
-        if (bDestroyCurrentNode)
+        if( bDestroyCurrentNode )
         {
             CPLXMLNode* psNext = psIter->psNext;
-            if (psPrev == NULL)
+            if( psPrev == NULL )
                 psSchema->psChild = psNext;
             else
                 psPrev->psNext = psNext;
@@ -498,26 +551,26 @@ CPLXMLNode* CPLLoadSchemaStrInternal(CPLHashSet* hSetSchemas,
 /************************************************************************/
 
 static
-void CPLMoveImportAtBeginning(CPLXMLNode* psXML)
+void CPLMoveImportAtBeginning( CPLXMLNode* psXML )
 {
     CPLXMLNode* psSchema = CPLGetXMLNode(psXML, "=schema");
-    if (psSchema == NULL)
+    if( psSchema == NULL )
         psSchema = CPLGetXMLNode(psXML, "=xs:schema");
-    if (psSchema == NULL)
+    if( psSchema == NULL )
         psSchema = CPLGetXMLNode(psXML, "=xsd:schema");
-    if (psSchema == NULL)
+    if( psSchema == NULL )
         return;
 
     CPLXMLNode* psPrev = NULL;
     CPLXMLNode* psIter = psSchema->psChild;
-    while(psIter)
+    while( psIter )
     {
-        if (psPrev != NULL && psIter->eType == CXT_Element &&
+        if( psPrev != NULL && psIter->eType == CXT_Element &&
             (strcmp(psIter->pszValue, "import") == 0 ||
              strcmp(psIter->pszValue, "xs:import") == 0 ||
-             strcmp(psIter->pszValue, "xsd:import") == 0))
+             strcmp(psIter->pszValue, "xsd:import") == 0) )
         {
-            /* Reorder at the beginning */
+            // Reorder at the beginning.
             CPLXMLNode* psNext = psIter->psNext;
 
             psPrev->psNext = psNext;
@@ -540,7 +593,7 @@ void CPLMoveImportAtBeginning(CPLXMLNode* psXML)
 /************************************************************************/
 
 static
-char* CPLLoadSchemaStr(const char* pszXSDFilename)
+char* CPLLoadSchemaStr( const char* pszXSDFilename )
 {
 #ifdef HAS_VALIDATION_BUG
     CPLHasLibXMLBug();
@@ -552,7 +605,7 @@ char* CPLLoadSchemaStr(const char* pszXSDFilename)
         CPLLoadSchemaStrInternal(hSetSchemas, pszXSDFilename);
 
     char* pszStr = NULL;
-    if (psSchema)
+    if( psSchema )
     {
         CPLMoveImportAtBeginning(psSchema);
         pszStr = CPLSerializeXMLTree(psSchema);
@@ -566,7 +619,7 @@ char* CPLLoadSchemaStr(const char* pszXSDFilename)
 /*                     CPLLibXMLInputStreamCPLFree()                    */
 /************************************************************************/
 
-static void CPLLibXMLInputStreamCPLFree(xmlChar* pszBuffer)
+static void CPLLibXMLInputStreamCPLFree( xmlChar* pszBuffer )
 {
     CPLFree(pszBuffer);
 }
@@ -575,15 +628,15 @@ static void CPLLibXMLInputStreamCPLFree(xmlChar* pszBuffer)
 /*                           CPLFindLocalXSD()                          */
 /************************************************************************/
 
-static CPLString CPLFindLocalXSD(const char* pszXSDFilename)
+static CPLString CPLFindLocalXSD( const char* pszXSDFilename )
 {
     CPLString osTmp;
-    const char *pszSchemasOpenGIS
-        = CPLGetConfigOption("GDAL_OPENGIS_SCHEMAS", NULL);
-    if (pszSchemasOpenGIS != NULL)
+    const char *pszSchemasOpenGIS =
+        CPLGetConfigOption("GDAL_OPENGIS_SCHEMAS", NULL);
+    if( pszSchemasOpenGIS != NULL )
     {
-        int nLen = (int)strlen(pszSchemasOpenGIS);
-        if (nLen > 0 && pszSchemasOpenGIS[nLen-1] == '/')
+        int nLen = static_cast<int>(strlen(pszSchemasOpenGIS));
+        if( nLen > 0 && pszSchemasOpenGIS[nLen-1] == '/' )
         {
             osTmp = pszSchemasOpenGIS;
             osTmp += pszXSDFilename;
@@ -595,7 +648,8 @@ static CPLString CPLFindLocalXSD(const char* pszXSDFilename)
             osTmp += pszXSDFilename;
         }
     }
-    else if ((pszSchemasOpenGIS = CPLFindFile( "gdal", "SCHEMAS_OPENGIS_NET" )) != NULL)
+    else if( (pszSchemasOpenGIS = CPLFindFile( "gdal", "SCHEMAS_OPENGIS_NET" ))
+             != NULL )
     {
         osTmp = pszSchemasOpenGIS;
         osTmp += "/";
@@ -612,165 +666,195 @@ static CPLString CPLFindLocalXSD(const char* pszXSDFilename)
 /*                      CPLExternalEntityLoader()                       */
 /************************************************************************/
 
-static const char szXML_XSD[] = "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://www.w3.org/XML/1998/namespace\">"
-"<attribute name=\"lang\">"
-"<simpleType>"
-"<union memberTypes=\"language\">"
-"<simpleType>"
-"<restriction base=\"string\">"
-"<enumeration value=\"\"/>"
-"</restriction>"
-"</simpleType>"
-"</union>"
-"</simpleType>"
-"</attribute>"
-"<attribute name=\"space\">"
-"<simpleType>"
-"<restriction base=\"NCName\">"
-"<enumeration value=\"default\"/>"
-"<enumeration value=\"preserve\"/>"
-"</restriction>"
-"</simpleType>"
-"</attribute>"
-"<attribute name=\"base\" type=\"anyURI\"/>"
-"<attribute name=\"id\" type=\"ID\"/>"
-"<attributeGroup name=\"specialAttrs\">"
-"<attribute ref=\"xml:base\"/>"
-"<attribute ref=\"xml:lang\"/>"
-"<attribute ref=\"xml:space\"/>"
-"<attribute ref=\"xml:id\"/>"
-"</attributeGroup>"
-"</schema>";
-
-/* Simplified (and truncated) version of http://www.w3.org/1999/xlink.xsd (sufficient for GML schemas) */
-static const char szXLINK_XSD[] = "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"http://www.w3.org/1999/xlink\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
-"<attribute name=\"type\" type=\"string\"/>"
-"<attribute name=\"href\" type=\"anyURI\"/>"
-"<attribute name=\"role\" type=\"anyURI\"/>"
-"<attribute name=\"arcrole\" type=\"anyURI\"/>"
-"<attribute name=\"title\" type=\"string\"/>"
-"<attribute name=\"show\" type=\"string\"/>"
-"<attribute name=\"actuate\" type=\"string\"/>"
-"<attribute name=\"label\" type=\"NCName\"/>"
-"<attribute name=\"from\" type=\"NCName\"/>"
-"<attribute name=\"to\" type=\"NCName\"/>"
-"<attributeGroup name=\"simpleAttrs\">"
-"<attribute ref=\"xlink:type\" fixed=\"simple\"/>"
-"<attribute ref=\"xlink:href\"/>"
-"<attribute ref=\"xlink:role\"/>"
-"<attribute ref=\"xlink:arcrole\"/>"
-"<attribute ref=\"xlink:title\"/>"
-"<attribute ref=\"xlink:show\"/>"
-"<attribute ref=\"xlink:actuate\"/>"
-"</attributeGroup>"
-"</schema>";
+static const char szXML_XSD[] =
+    "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" "
+    "targetNamespace=\"http://www.w3.org/XML/1998/namespace\">"
+    "<attribute name=\"lang\">"
+    "<simpleType>"
+    "<union memberTypes=\"language\">"
+    "<simpleType>"
+    "<restriction base=\"string\">"
+    "<enumeration value=\"\"/>"
+    "</restriction>"
+    "</simpleType>"
+    "</union>"
+    "</simpleType>"
+    "</attribute>"
+    "<attribute name=\"space\">"
+    "<simpleType>"
+    "<restriction base=\"NCName\">"
+    "<enumeration value=\"default\"/>"
+    "<enumeration value=\"preserve\"/>"
+    "</restriction>"
+    "</simpleType>"
+    "</attribute>"
+    "<attribute name=\"base\" type=\"anyURI\"/>"
+    "<attribute name=\"id\" type=\"ID\"/>"
+    "<attributeGroup name=\"specialAttrs\">"
+    "<attribute ref=\"xml:base\"/>"
+    "<attribute ref=\"xml:lang\"/>"
+    "<attribute ref=\"xml:space\"/>"
+    "<attribute ref=\"xml:id\"/>"
+    "</attributeGroup>"
+    "</schema>";
+
+// Simplified (and truncated) version of http://www.w3.org/1999/xlink.xsd
+// (sufficient for GML schemas).
+static const char szXLINK_XSD[] =
+    "<schema xmlns=\"http://www.w3.org/2001/XMLSchema\" "
+    "targetNamespace=\"http://www.w3.org/1999/xlink\" "
+    "xmlns:xlink=\"http://www.w3.org/1999/xlink\">"
+    "<attribute name=\"type\" type=\"string\"/>"
+    "<attribute name=\"href\" type=\"anyURI\"/>"
+    "<attribute name=\"role\" type=\"anyURI\"/>"
+    "<attribute name=\"arcrole\" type=\"anyURI\"/>"
+    "<attribute name=\"title\" type=\"string\"/>"
+    "<attribute name=\"show\" type=\"string\"/>"
+    "<attribute name=\"actuate\" type=\"string\"/>"
+    "<attribute name=\"label\" type=\"NCName\"/>"
+    "<attribute name=\"from\" type=\"NCName\"/>"
+    "<attribute name=\"to\" type=\"NCName\"/>"
+    "<attributeGroup name=\"simpleAttrs\">"
+    "<attribute ref=\"xlink:type\" fixed=\"simple\"/>"
+    "<attribute ref=\"xlink:href\"/>"
+    "<attribute ref=\"xlink:role\"/>"
+    "<attribute ref=\"xlink:arcrole\"/>"
+    "<attribute ref=\"xlink:title\"/>"
+    "<attribute ref=\"xlink:show\"/>"
+    "<attribute ref=\"xlink:actuate\"/>"
+    "</attributeGroup>"
+    "</schema>";
 
 static
-xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
+xmlParserInputPtr CPLExternalEntityLoader( const char * URL,
                                            const char * ID,
-                                           xmlParserCtxtPtr context)
+                                           xmlParserCtxtPtr context )
 {
-    //CPLDebug("CPL", "CPLExternalEntityLoader(%s)", URL);
+#if DEBUG_VERBOSE
+    CPLDebug("CPL", "CPLExternalEntityLoader(%s)", URL);
+#endif
+    // Use libxml2 catalog mechanism to resolve the URL to something else.
+    // xmlChar* pszResolved = xmlCatalogResolveSystem((const xmlChar*)URL);
+    xmlChar* pszResolved =
+        xmlCatalogResolveSystem(reinterpret_cast<const xmlChar *>(URL));
+    if( pszResolved == NULL )
+        pszResolved =
+            xmlCatalogResolveURI(reinterpret_cast<const xmlChar *>(URL));
     CPLString osURL;
-
-    /* Use libxml2 catalog mechanism to resolve the URL to something else */
-    xmlChar* pszResolved = xmlCatalogResolveSystem((const xmlChar*)URL);
-    if (pszResolved == NULL)
-        pszResolved = xmlCatalogResolveURI((const xmlChar*)URL);
-    if (pszResolved)
+    if( pszResolved )
     {
-        CPLDebug("CPL", "Resolving %s in %s", URL, (const char*)pszResolved );
-        osURL = (const char*)pszResolved;
+        CPLDebug( "CPL", "Resolving %s in %s", URL,
+                  reinterpret_cast<const char *>(pszResolved) );
+        osURL = reinterpret_cast<const char *>(pszResolved);
         URL = osURL.c_str();
         xmlFree(pszResolved);
         pszResolved = NULL;
     }
 
-    if (STARTS_WITH(URL, "http://"))
+    if( STARTS_WITH(URL, "http://") )
     {
-        /* Make sure to use http://schemas.opengis.net/ */
-        /* when gml/2 or gml/3 is detected */
+        // Make sure to use http://schemas.opengis.net/
+        // when gml/2 or gml/3 is detected.
         const char* pszGML = strstr(URL, "gml/2");
-        if (pszGML == NULL)
+        if( pszGML == NULL )
             pszGML = strstr(URL, "gml/3");
-        if (pszGML != NULL)
+        if( pszGML != NULL )
         {
             osURL = "http://schemas.opengis.net/";
             osURL += pszGML;
             URL = osURL.c_str();
         }
-        else if (strcmp(URL, "http://www.w3.org/2001/xml.xsd") == 0)
+        else if( strcmp(URL, "http://www.w3.org/2001/xml.xsd") == 0 )
         {
             CPLString osTmp = CPLFindLocalXSD("xml.xsd");
-            if( osTmp.size() != 0 )
+            if( !osTmp.empty() )
             {
                 osURL = osTmp;
                 URL = osURL.c_str();
             }
             else
             {
-                CPLDebug("CPL", "Resolving %s to local definition", "http://www.w3.org/2001/xml.xsd");
-                return xmlNewStringInputStream(context, (const xmlChar*) szXML_XSD);
+                CPLDebug(
+                    "CPL",
+                    "Resolving %s to local definition",
+                    "http://www.w3.org/2001/xml.xsd" );
+                return xmlNewStringInputStream(
+                    context, reinterpret_cast<const xmlChar*>(szXML_XSD) );
             }
         }
-        else if (strcmp(URL, "http://www.w3.org/1999/xlink.xsd") == 0)
+        else if( strcmp(URL, "http://www.w3.org/1999/xlink.xsd") == 0 )
         {
             CPLString osTmp = CPLFindLocalXSD("xlink.xsd");
-            if( osTmp.size() != 0 )
+            if( !osTmp.empty() )
             {
                 osURL = osTmp;
                 URL = osURL.c_str();
             }
             else
             {
-                CPLDebug("CPL", "Resolving %s to local definition", "http://www.w3.org/1999/xlink.xsd");
-                return xmlNewStringInputStream(context, (const xmlChar*) szXLINK_XSD);
+                CPLDebug(
+                    "CPL",
+                    "Resolving %s to local definition",
+                    "http://www.w3.org/1999/xlink.xsd" );
+                return xmlNewStringInputStream(
+                    context, reinterpret_cast<const xmlChar *>( szXLINK_XSD) );
             }
         }
-        else if (!STARTS_WITH(URL, "http://schemas.opengis.net/"))        {
+        else if( !STARTS_WITH(URL, "http://schemas.opengis.net/") )
+        {
             CPLDebug("CPL", "Loading %s", URL);
             return pfnLibXMLOldExtranerEntityLoader(URL, ID, context);
         }
     }
-    else if (STARTS_WITH(URL, "ftp://"))
+    else if( STARTS_WITH(URL, "ftp://") )
     {
         return pfnLibXMLOldExtranerEntityLoader(URL, ID, context);
     }
-    else if (STARTS_WITH(URL, "file://"))
+    else if( STARTS_WITH(URL, "file://") )
     {
-        /* Parse file:// URI so as to be able to open them with VSI*L API */
-        if (STARTS_WITH(URL, "file://localhost/"))
+        // Parse file:// URI so as to be able to open them with VSI*L API.
+        if( STARTS_WITH(URL, "file://localhost/") )
             URL += 16;
         else
             URL += 7;
-        if (URL[0] == '/' && URL[1] != '\0' && URL[2] == ':' && URL[3] == '/') /* Windows */
-            URL ++;
-        else if (URL[0] == '/') /* Unix */
-            ;
+
+        if( URL[0] == '/' && URL[1] != '\0' && URL[2] == ':' && URL[3] == '/' )
+        {
+            // Windows.
+            ++URL;
+        }
+        else if( URL[0] == '/' )
+        {
+            // Unix.
+        }
         else
+        {
             return pfnLibXMLOldExtranerEntityLoader(URL, ID, context);
+        }
     }
 
     CPLString osModURL;
-    if (STARTS_WITH(URL, "/vsizip/vsicurl/http%3A//"))    {
+    if( STARTS_WITH(URL, "/vsizip/vsicurl/http%3A//") )
+    {
         osModURL = "/vsizip/vsicurl/http://";
         osModURL += URL + strlen("/vsizip/vsicurl/http%3A//");
     }
-    else if (STARTS_WITH(URL, "/vsicurl/http%3A//"))    {
+    else if( STARTS_WITH(URL, "/vsicurl/http%3A//") )
+    {
         osModURL = "vsicurl/http://";
         osModURL += URL + strlen("/vsicurl/http%3A//");
     }
-    else if (STARTS_WITH(URL, "http://schemas.opengis.net/"))    {
+    else if( STARTS_WITH(URL, "http://schemas.opengis.net/") )
+    {
         const char *pszAfterOpenGIS =
                 URL + strlen("http://schemas.opengis.net/");
 
-        const char *pszSchemasOpenGIS;
-
-        pszSchemasOpenGIS = CPLGetConfigOption("GDAL_OPENGIS_SCHEMAS", NULL);
-        if (pszSchemasOpenGIS != NULL)
+        const char *pszSchemasOpenGIS =
+            CPLGetConfigOption("GDAL_OPENGIS_SCHEMAS", NULL);
+        if( pszSchemasOpenGIS != NULL )
         {
-            int nLen = (int)strlen(pszSchemasOpenGIS);
-            if (nLen > 0 && pszSchemasOpenGIS[nLen-1] == '/')
+            const int nLen = static_cast<int>(strlen(pszSchemasOpenGIS));
+            if( nLen > 0 && pszSchemasOpenGIS[nLen-1] == '/' )
             {
                 osModURL = pszSchemasOpenGIS;
                 osModURL += pszAfterOpenGIS;
@@ -782,13 +866,16 @@ xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
                 osModURL += pszAfterOpenGIS;
             }
         }
-        else if ((pszSchemasOpenGIS = CPLFindFile( "gdal", "SCHEMAS_OPENGIS_NET" )) != NULL)
+        else if( (pszSchemasOpenGIS =
+                      CPLFindFile( "gdal", "SCHEMAS_OPENGIS_NET" )) != NULL )
         {
             osModURL = pszSchemasOpenGIS;
             osModURL += "/";
             osModURL += pszAfterOpenGIS;
         }
-        else if ((pszSchemasOpenGIS = CPLFindFile( "gdal", "SCHEMAS_OPENGIS_NET.zip" )) != NULL)
+        else if( (pszSchemasOpenGIS =
+                      CPLFindFile( "gdal", "SCHEMAS_OPENGIS_NET.zip" ))
+                 != NULL )
         {
             osModURL = "/vsizip/";
             osModURL += pszSchemasOpenGIS;
@@ -797,7 +884,9 @@ xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
         }
         else
         {
-            osModURL = "/vsizip/vsicurl/http://schemas.opengis.net/SCHEMAS_OPENGIS_NET.zip/";
+            osModURL =
+                "/vsizip/vsicurl/"
+                "http://schemas.opengis.net/SCHEMAS_OPENGIS_NET.zip/";
             osModURL += pszAfterOpenGIS;
         }
     }
@@ -806,12 +895,14 @@ xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
         osModURL = URL;
     }
 
-    xmlChar* pszBuffer = (xmlChar*)CPLLoadSchemaStr(osModURL);
-    if (pszBuffer == NULL)
+    xmlChar* pszBuffer =
+        reinterpret_cast<xmlChar *>(CPLLoadSchemaStr(osModURL));
+    if( pszBuffer == NULL )
         return NULL;
 
-    xmlParserInputPtr poInputStream = xmlNewStringInputStream(context, pszBuffer);
-    if (poInputStream != NULL)
+    xmlParserInputPtr poInputStream =
+        xmlNewStringInputStream(context, pszBuffer);
+    if( poInputStream != NULL )
         poInputStream->free = CPLLibXMLInputStreamCPLFree;
     return poInputStream;
 }
@@ -820,20 +911,20 @@ xmlParserInputPtr CPLExternalEntityLoader (const char * URL,
 /*                    CPLLibXMLWarningErrorCallback()                   */
 /************************************************************************/
 
-static void CPLLibXMLWarningErrorCallback (void * ctx, const char * msg, ...)
+static void CPLLibXMLWarningErrorCallback ( void * ctx, const char * msg, ... )
 {
     va_list varg;
     va_start(varg, msg);
 
-    char *pszStr = (char *)va_arg( varg, char *);
+    char *pszStr = reinterpret_cast<char *>(va_arg( varg, char *));
 
-    if (strstr(pszStr, "since this namespace was already imported") == NULL)
+    if( strstr(pszStr, "since this namespace was already imported") == NULL )
     {
         xmlErrorPtr pErrorPtr = xmlGetLastError();
-        const char* pszFilename = (const char*)ctx;
+        const char* pszFilename = static_cast<char *>(ctx);
         char* pszStrDup = CPLStrdup(pszStr);
-        int nLen = (int)strlen(pszStrDup);
-        if (nLen > 0 && pszStrDup[nLen-1] == '\n')
+        int nLen = static_cast<int>(strlen(pszStrDup));
+        if( nLen > 0 && pszStrDup[nLen-1] == '\n' )
             pszStrDup[nLen-1] = '\0';
         if( pszFilename != NULL && pszFilename[0] != '<' )
         {
@@ -856,36 +947,38 @@ static void CPLLibXMLWarningErrorCallback (void * ctx, const char * msg, ...)
 /************************************************************************/
 
 static
-char* CPLLoadContentFromFile(const char* pszFilename)
+char* CPLLoadContentFromFile( const char* pszFilename )
 {
     VSILFILE* fp = VSIFOpenL(pszFilename, "rb");
-    if (fp == NULL)
+    if( fp == NULL )
         return NULL;
-    vsi_l_offset nSize;
     if( VSIFSeekL(fp, 0, SEEK_END) != 0 )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
-    nSize = VSIFTellL(fp);
+    vsi_l_offset nSize = VSIFTellL(fp);
     if( VSIFSeekL(fp, 0, SEEK_SET) != 0 )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
-    if ((vsi_l_offset)(int)nSize != nSize ||
+    if( static_cast<vsi_l_offset>(static_cast<int>(nSize)) != nSize ||
         nSize > INT_MAX - 1 )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
-    char* pszBuffer = (char*)VSIMalloc((size_t)nSize + 1);
-    if (pszBuffer == NULL)
+    char* pszBuffer =
+        static_cast<char *>(VSIMalloc(static_cast<size_t>(nSize) + 1));
+    if( pszBuffer == NULL )
     {
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
         return NULL;
     }
-    if( (size_t)VSIFReadL(pszBuffer, 1, (size_t)nSize, fp) != (size_t)nSize )
+    if( static_cast<size_t>(VSIFReadL(pszBuffer, 1,
+                                      static_cast<size_t>(nSize), fp))
+        != static_cast<size_t>(nSize) )
     {
         VSIFree(pszBuffer);
         CPL_IGNORE_RET_VAL(VSIFCloseL(fp));
@@ -914,10 +1007,10 @@ typedef void* CPLXMLSchemaPtr;
  */
 
 static
-CPLXMLSchemaPtr CPLLoadXMLSchema(const char* pszXSDFilename)
+CPLXMLSchemaPtr CPLLoadXMLSchema( const char* pszXSDFilename )
 {
     char* pszStr = CPLLoadSchemaStr(pszXSDFilename);
-    if (pszStr == NULL)
+    if( pszStr == NULL )
         return NULL;
 
     xmlExternalEntityLoader pfnLibXMLOldExtranerEntityLoaderLocal = NULL;
@@ -926,7 +1019,7 @@ CPLXMLSchemaPtr CPLLoadXMLSchema(const char* pszXSDFilename)
     xmlSetExternalEntityLoader(CPLExternalEntityLoader);
 
     xmlSchemaParserCtxtPtr pSchemaParserCtxt =
-                            xmlSchemaNewMemParserCtxt(pszStr, static_cast<int>(strlen(pszStr)));
+        xmlSchemaNewMemParserCtxt(pszStr, static_cast<int>(strlen(pszStr)));
 
     xmlSchemaSetParserErrors(pSchemaParserCtxt,
                              CPLLibXMLWarningErrorCallback,
@@ -940,7 +1033,7 @@ CPLXMLSchemaPtr CPLLoadXMLSchema(const char* pszXSDFilename)
 
     CPLFree(pszStr);
 
-    return (CPLXMLSchemaPtr) pSchema;
+    return static_cast<CPLXMLSchemaPtr>( pSchema );
 }
 
 /************************************************************************/
@@ -956,10 +1049,10 @@ CPLXMLSchemaPtr CPLLoadXMLSchema(const char* pszXSDFilename)
  */
 
 static
-void CPLFreeXMLSchema(CPLXMLSchemaPtr pSchema)
+void CPLFreeXMLSchema( CPLXMLSchemaPtr pSchema )
 {
-    if (pSchema)
-        xmlSchemaFree((xmlSchemaPtr)pSchema);
+    if( pSchema )
+        xmlSchemaFree(static_cast<xmlSchemaPtr>(pSchema));
 }
 
 /************************************************************************/
@@ -971,17 +1064,17 @@ void CPLFreeXMLSchema(CPLXMLSchemaPtr pSchema)
  *
  * @param pszXMLFilename the filename of the XML file to validate.
  * @param pszXSDFilename the filename of the XSD schema.
- * @param papszOptions unused for now.
+ * @param papszOptions unused for now. Set to NULL.
  * @return TRUE if the XML file validates against the XML schema.
  *
  * @since GDAL 1.10.0
  */
 
-int CPLValidateXML(const char* pszXMLFilename,
-                   const char* pszXSDFilename,
-                   CPL_UNUSED char** papszOptions)
+int CPLValidateXML( const char* pszXMLFilename,
+                    const char* pszXSDFilename,
+                    CPL_UNUSED char** papszOptions )
 {
-    char szHeader[2048];
+    char szHeader[2048] = {};  // TODO(schwehr): Get this off of the stack.
     CPLString osTmpXSDFilename;
 
     if( pszXMLFilename[0] == '<' )
@@ -992,84 +1085,112 @@ int CPLValidateXML(const char* pszXMLFilename,
     else
     {
         VSILFILE* fpXML = VSIFOpenL(pszXMLFilename, "rb");
-        if (fpXML == NULL)
+        if( fpXML == NULL )
         {
-            CPLError(CE_Failure, CPLE_OpenFailed,
-                    "Cannot open %s", pszXMLFilename);
+            CPLError( CE_Failure, CPLE_OpenFailed,
+                      "Cannot open %s", pszXMLFilename );
             return FALSE;
         }
-        int nRead = (int)VSIFReadL(szHeader, 1, sizeof(szHeader)-1, fpXML);
+        const vsi_l_offset nRead =
+            VSIFReadL(szHeader, 1, sizeof(szHeader) - 1, fpXML);
         szHeader[nRead] = '\0';
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpXML));
     }
 
-    /* Workaround following bug : "element FeatureCollection: Schemas validity error : Element '{http://www.opengis.net/wfs}FeatureCollection': No matching global declaration available for the validation root" */
-    /* We create a wrapping XSD that imports the WFS .xsd (and possibly the GML .xsd too) and the application schema */
-    /* This is a known libxml2 limitation */
-    if (strstr(szHeader, "<wfs:FeatureCollection") ||
-        (strstr(szHeader, "<FeatureCollection") && strstr(szHeader, "xmlns:wfs=\"http://www.opengis.net/wfs\"")))
+    // Workaround following bug:
+    //
+    // "element FeatureCollection: Schemas validity error : Element
+    // '{http://www.opengis.net/wfs}FeatureCollection': No matching global
+    // declaration available for the validation root"
+    //
+    // We create a wrapping XSD that imports the WFS .xsd (and possibly the GML
+    // .xsd too) and the application schema.  This is a known libxml2
+    // limitation.
+    if( strstr(szHeader, "<wfs:FeatureCollection") ||
+        (strstr(szHeader, "<FeatureCollection") &&
+         strstr(szHeader, "xmlns:wfs=\"http://www.opengis.net/wfs\"")) )
     {
         const char* pszWFSSchemaNamespace = "http://www.opengis.net/wfs";
         const char* pszWFSSchemaLocation = NULL;
         const char* pszGMLSchemaLocation = NULL;
-        if (strstr(szHeader, "wfs/1.0.0/WFS-basic.xsd"))
+        if( strstr(szHeader, "wfs/1.0.0/WFS-basic.xsd") )
         {
-            pszWFSSchemaLocation = "http://schemas.opengis.net/wfs/1.0.0/WFS-basic.xsd";
+            pszWFSSchemaLocation =
+                "http://schemas.opengis.net/wfs/1.0.0/WFS-basic.xsd";
         }
-        else if (strstr(szHeader, "wfs/1.1.0/wfs.xsd"))
+        else if( strstr(szHeader, "wfs/1.1.0/wfs.xsd") )
         {
-            pszWFSSchemaLocation = "http://schemas.opengis.net/wfs/1.1.0/wfs.xsd";
+            pszWFSSchemaLocation =
+                "http://schemas.opengis.net/wfs/1.1.0/wfs.xsd";
         }
-        else if (strstr(szHeader, "wfs/2.0/wfs.xsd"))
+        else if( strstr(szHeader, "wfs/2.0/wfs.xsd") )
         {
             pszWFSSchemaNamespace = "http://www.opengis.net/wfs/2.0";
             pszWFSSchemaLocation = "http://schemas.opengis.net/wfs/2.0/wfs.xsd";
         }
 
         VSILFILE* fpXSD = VSIFOpenL(pszXSDFilename, "rb");
-        if (fpXSD == NULL)
+        if( fpXSD == NULL )
         {
             CPLError(CE_Failure, CPLE_OpenFailed,
                     "Cannot open %s", pszXSDFilename);
             return FALSE;
         }
-        int nRead = (int)VSIFReadL(szHeader, 1, sizeof(szHeader)-1, fpXSD);
+        const vsi_l_offset nRead =
+            VSIFReadL(szHeader, 1, sizeof(szHeader) - 1, fpXSD);
         szHeader[nRead] = '\0';
         CPL_IGNORE_RET_VAL(VSIFCloseL(fpXSD));
 
-        if (strstr(szHeader, "gml/3.1.1") != NULL &&
-            strstr(szHeader, "gml/3.1.1/base/gml.xsd") == NULL)
+        if( strstr(szHeader, "gml/3.1.1") != NULL &&
+            strstr(szHeader, "gml/3.1.1/base/gml.xsd") == NULL )
         {
-            pszGMLSchemaLocation = "http://schemas.opengis.net/gml/3.1.1/base/gml.xsd";
+            pszGMLSchemaLocation =
+                "http://schemas.opengis.net/gml/3.1.1/base/gml.xsd";
         }
 
-        if (pszWFSSchemaLocation != NULL)
+        if( pszWFSSchemaLocation != NULL )
         {
-            osTmpXSDFilename = CPLSPrintf("/vsimem/CPLValidateXML_%p_%p.xsd", pszXMLFilename, pszXSDFilename);
-            char* pszEscapedXSDFilename = CPLEscapeString(pszXSDFilename, -1, CPLES_XML);
-            VSILFILE* fpMEM = VSIFOpenL(osTmpXSDFilename, "wb");
-            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"));
-            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "   <xs:import namespace=\"%s\" schemaLocation=\"%s\"/>\n", pszWFSSchemaNamespace, pszWFSSchemaLocation));
-            CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "   <xs:import namespace=\"ignored\" schemaLocation=\"%s\"/>\n", pszEscapedXSDFilename));
-            if (pszGMLSchemaLocation)
-                CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "   <xs:import namespace=\"http://www.opengis.net/gml\" schemaLocation=\"%s\"/>\n", pszGMLSchemaLocation));
+            osTmpXSDFilename = CPLSPrintf(
+                "/vsimem/CPLValidateXML_%p_%p.xsd",
+                pszXMLFilename, pszXSDFilename );
+            char * const pszEscapedXSDFilename =
+                CPLEscapeString(pszXSDFilename, -1, CPLES_XML);
+            VSILFILE * const fpMEM = VSIFOpenL(osTmpXSDFilename, "wb");
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(
+                fpMEM,
+                "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(
+                fpMEM,
+                "   <xs:import namespace=\"%s\" schemaLocation=\"%s\"/>\n",
+                pszWFSSchemaNamespace, pszWFSSchemaLocation));
+            CPL_IGNORE_RET_VAL(VSIFPrintfL(
+                fpMEM,
+                "   <xs:import namespace=\"ignored\" schemaLocation=\"%s\"/>\n",
+                pszEscapedXSDFilename));
+            if( pszGMLSchemaLocation )
+                CPL_IGNORE_RET_VAL(VSIFPrintfL(
+                    fpMEM,
+                    "   <xs:import namespace=\"http://www.opengis.net/gml\" "
+                    "schemaLocation=\"%s\"/>\n", pszGMLSchemaLocation));
             CPL_IGNORE_RET_VAL(VSIFPrintfL(fpMEM, "</xs:schema>\n"));
             CPL_IGNORE_RET_VAL(VSIFCloseL(fpMEM));
             CPLFree(pszEscapedXSDFilename);
         }
     }
 
-    CPLXMLSchemaPtr pSchema = CPLLoadXMLSchema(osTmpXSDFilename.size() ? osTmpXSDFilename.c_str() : pszXSDFilename);
-    if (osTmpXSDFilename.size())
+    CPLXMLSchemaPtr pSchema =
+        CPLLoadXMLSchema(!osTmpXSDFilename.empty()
+                         ? osTmpXSDFilename.c_str()
+                         : pszXSDFilename);
+    if( !osTmpXSDFilename.empty() )
         VSIUnlink(osTmpXSDFilename);
-    if (pSchema == NULL)
+    if( pSchema == NULL )
         return FALSE;
 
-    xmlSchemaValidCtxtPtr pSchemaValidCtxt;
-
-    pSchemaValidCtxt = xmlSchemaNewValidCtxt((xmlSchemaPtr)pSchema);
+    xmlSchemaValidCtxtPtr pSchemaValidCtxt =
+        xmlSchemaNewValidCtxt((xmlSchemaPtr)pSchema);
 
-    if (pSchemaValidCtxt == NULL)
+    if( pSchemaValidCtxt == NULL )
     {
         CPLFreeXMLSchema(pSchema);
         return FALSE;
@@ -1078,19 +1199,20 @@ int CPLValidateXML(const char* pszXMLFilename,
     xmlSchemaSetValidErrors(pSchemaValidCtxt,
                             CPLLibXMLWarningErrorCallback,
                             CPLLibXMLWarningErrorCallback,
-                            (void*) pszXMLFilename);
+                            const_cast<char *>(pszXMLFilename) );
 
     bool bValid = false;
     if( pszXMLFilename[0] == '<' )
     {
-        xmlDocPtr pDoc = xmlParseDoc((const xmlChar *)pszXMLFilename);
-        if (pDoc != NULL)
+        xmlDocPtr pDoc =
+            xmlParseDoc(reinterpret_cast<const xmlChar *>(pszXMLFilename));
+        if( pDoc != NULL )
         {
             bValid = xmlSchemaValidateDoc(pSchemaValidCtxt, pDoc) == 0;
         }
         xmlFreeDoc(pDoc);
     }
-    else if (!STARTS_WITH(pszXMLFilename, "/vsi"))
+    else if( !STARTS_WITH(pszXMLFilename, "/vsi") )
     {
         bValid =
             xmlSchemaValidateFile(pSchemaValidCtxt, pszXMLFilename, 0) == 0;
@@ -1098,10 +1220,11 @@ int CPLValidateXML(const char* pszXMLFilename,
     else
     {
         char* pszXML = CPLLoadContentFromFile(pszXMLFilename);
-        if (pszXML != NULL)
+        if( pszXML != NULL )
         {
-            xmlDocPtr pDoc = xmlParseDoc((const xmlChar *)pszXML);
-            if (pDoc != NULL)
+            xmlDocPtr pDoc =
+                xmlParseDoc(reinterpret_cast<const xmlChar *>(pszXML));
+            if( pDoc != NULL )
             {
                 bValid = xmlSchemaValidateDoc(pSchemaValidCtxt, pDoc) == 0;
             }
@@ -1115,20 +1238,20 @@ int CPLValidateXML(const char* pszXMLFilename,
     return bValid;
 }
 
-#else // HAVE_RECENT_LIBXML2
+#else  // HAVE_RECENT_LIBXML2
 
 /************************************************************************/
 /*                          CPLValidateXML()                            */
 /************************************************************************/
 
-int CPLValidateXML(CPL_UNUSED const char* pszXMLFilename,
-                   CPL_UNUSED const char* pszXSDFilename,
-                   CPL_UNUSED char** papszOptions)
+int CPLValidateXML( const char* /* pszXMLFilename */,
+                    const char* /* pszXSDFilename */,
+                    char** /* papszOptions */ )
 {
-    CPLError(CE_Failure, CPLE_NotSupported,
-             "%s not implemented due to missing libxml2 support",
-             "CPLValidateXML()");
+    CPLError( CE_Failure, CPLE_NotSupported,
+              "%s not implemented due to missing libxml2 support",
+              "CPLValidateXML()" );
     return FALSE;
 }
 
-#endif // HAVE_RECENT_LIBXML2
+#endif  // HAVE_RECENT_LIBXML2
diff --git a/port/cplgetsymbol.cpp b/port/cplgetsymbol.cpp
index a8f2c4b..e42013a 100644
--- a/port/cplgetsymbol.cpp
+++ b/port/cplgetsymbol.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cplgetsymbol.cpp 35433 2016-09-14 07:44:24Z rouault $
  *
  * Project:  Common Portability Library
  * Purpose:  Fetch a function pointer from a shared library / DLL.
@@ -28,11 +27,16 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_conv.h"
-#include "cpl_string.h"
 
-CPL_CVSID("$Id: cplgetsymbol.cpp 35433 2016-09-14 07:44:24Z rouault $");
+#include <cstddef>
+
+#include "cpl_config.h"
+#include "cpl_error.h"
+#include "cpl_string.h"
 
+CPL_CVSID("$Id: cplgetsymbol.cpp 36910 2016-12-16 18:49:46Z goatbar $");
 
 /* ==================================================================== */
 /*                  Unix Implementation                                 */
@@ -85,10 +89,7 @@ CPL_CVSID("$Id: cplgetsymbol.cpp 35433 2016-09-14 07:44:24Z rouault $");
 void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 
 {
-    void        *pLibrary;
-    void        *pSymbol;
-
-    pLibrary = dlopen(pszLibrary, RTLD_LAZY);
+    void *pLibrary = dlopen(pszLibrary, RTLD_LAZY);
     if( pLibrary == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -96,7 +97,7 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
         return NULL;
     }
 
-    pSymbol = dlsym( pLibrary, pszSymbolName );
+    void *pSymbol = dlsym( pLibrary, pszSymbolName );
 
 #if (defined(__APPLE__) && defined(__MACH__))
     /* On mach-o systems, C symbols have a leading underscore and depending
@@ -105,7 +106,7 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
      */
     if( pSymbol == NULL )
     {
-        char withUnder[256];
+        char withUnder[256] = {};
         snprintf(withUnder, sizeof(withUnder), "_%s", pszSymbolName);
         pSymbol = dlsym( pLibrary, withUnder );
     }
@@ -142,14 +143,14 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 
 {
-    void        *pLibrary;
-    void        *pSymbol;
-    UINT        uOldErrorMode;
+    void *pLibrary = NULL;
+    void *pSymbol = NULL;
 
-    /* Avoid error boxes to pop up (#5211, #5525) */
-    uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
+    // Avoid error boxes to pop up (#5211, #5525).
+    UINT uOldErrorMode =
+        SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
 
-#if (defined(WIN32) && _MSC_VER >= 1310) || __MSVCRT_VERSION__ >= 0x0601
+#if _MSC_VER >= 1310 || __MSVCRT_VERSION__ >= 0x0601
     if( CPLTestBool( CPLGetConfigOption( "GDAL_FILENAME_IS_UTF8", "YES" ) ) )
     {
         wchar_t *pwszFilename =
@@ -165,10 +166,10 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
 
     if( pLibrary <= (void*)HINSTANCE_ERROR )
     {
-        LPVOID      lpMsgBuf = NULL;
-        int         nLastError = GetLastError();
+        LPVOID lpMsgBuf = NULL;
+        int nLastError = GetLastError();
 
-        /* Restore old error mode */
+        // Restore old error mode.
         SetErrorMode(uOldErrorMode);
 
         FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
@@ -184,7 +185,7 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
         return NULL;
     }
 
-    /* Restore old error mode */
+    // Restore old error mode.
     SetErrorMode(uOldErrorMode);
 
     pSymbol = (void *) GetProcAddress( (HINSTANCE) pLibrary, pszSymbolName );
@@ -192,14 +193,14 @@ void *CPLGetSymbol( const char * pszLibrary, const char * pszSymbolName )
     if( pSymbol == NULL )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
-                  "Can't find requested entry point: %s\n", pszSymbolName );
+                  "Can't find requested entry point: %s", pszSymbolName );
         return NULL;
     }
 
     return( pSymbol );
 }
 
-#endif /* def _WIN32 */
+#endif  // def _WIN32
 
 /* ==================================================================== */
 /*      Dummy implementation.                                           */
diff --git a/port/cplkeywordparser.cpp b/port/cplkeywordparser.cpp
index 743c21c..131ef6a 100644
--- a/port/cplkeywordparser.cpp
+++ b/port/cplkeywordparser.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cplkeywordparser.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  Common Portability Library
  * Purpose:  Implementation of CPLKeywordParser - a class for parsing
@@ -31,10 +30,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
-#include "cpl_string.h"
+//! @cond Doxygen_Suppress
+
+#include "cpl_port.h"
 #include "cplkeywordparser.h"
 
-CPL_CVSID("$Id");
+#include <cctype>
+#include <cstring>
+#include <string>
+
+#include "cpl_string.h"
+#include "cpl_vsi.h"
+
+CPL_CVSID("$Id: cplkeywordparser.cpp 36979 2016-12-20 18:40:40Z rouault $");
 
 /************************************************************************/
 /* ==================================================================== */
@@ -69,11 +77,11 @@ int CPLKeywordParser::Ingest( VSILFILE *fp )
 
 {
 /* -------------------------------------------------------------------- */
-/*      Read in buffer till we find END all on it's own line.           */
+/*      Read in buffer till we find END all on its own line.            */
 /* -------------------------------------------------------------------- */
     for( ; true; )
     {
-        char szChunk[513];
+        char szChunk[513] = {};
         const size_t nBytesRead = VSIFReadL( szChunk, 1, 512, fp );
 
         szChunk[nBytesRead] = '\0';
@@ -82,14 +90,14 @@ int CPLKeywordParser::Ingest( VSILFILE *fp )
         if( nBytesRead < 512 )
             break;
 
-        const char *pszCheck;
+        const char *pszCheck = NULL;
         if( osHeaderText.size() > 520 )
             pszCheck = osHeaderText.c_str() + (osHeaderText.size() - 520);
         else
             pszCheck = szChunk;
 
-        if( strstr(pszCheck,"\r\nEND;\r\n") != NULL
-            || strstr(pszCheck,"\nEND;\n") != NULL )
+        if( strstr(pszCheck, "\r\nEND;\r\n") != NULL
+            || strstr(pszCheck, "\nEND;\n") != NULL )
             break;
     }
 
@@ -108,16 +116,17 @@ int CPLKeywordParser::Ingest( VSILFILE *fp )
 int CPLKeywordParser::ReadGroup( const char *pszPathPrefix )
 
 {
-    CPLString osName, osValue;
+    CPLString osName;
+    CPLString osValue;
 
     for( ; true; )
     {
         if( !ReadPair( osName, osValue ) )
             return FALSE;
 
-        if( EQUAL(osName,"BEGIN_GROUP") || EQUAL(osName,"GROUP") )
+        if( EQUAL(osName, "BEGIN_GROUP") || EQUAL(osName, "GROUP") )
         {
-            if( !ReadGroup( (CPLString(pszPathPrefix) + osValue + ".").c_str() ) )
+            if( !ReadGroup((CPLString(pszPathPrefix) + osValue + ".").c_str()) )
                 return FALSE;
         }
         else if( STARTS_WITH_CI(osName, "END") )
@@ -151,13 +160,13 @@ int CPLKeywordParser::ReadPair( CPLString &osName, CPLString &osValue )
 
     SkipWhite();
 
-    if( EQUAL(osName,"END") )
+    if( EQUAL(osName, "END") )
         return TRUE;
 
     if( *pszHeaderNext != '=' )
     {
         // ISIS3 does not have anything after the end group/object keyword.
-        if( EQUAL(osName,"End_Group") || EQUAL(osName,"End_Object") )
+        if( EQUAL(osName, "End_Group") || EQUAL(osName, "End_Object") )
             return TRUE;
         else
             return FALSE;
@@ -170,7 +179,7 @@ int CPLKeywordParser::ReadPair( CPLString &osName, CPLString &osValue )
     osValue = "";
 
     // Handle value lists like:     Name   = (Red, Red)
-    // or list of lists like : TLCList = ( (0,  0.000000), (8299,  4.811014) );
+    // or list of lists like: TLCList = ( (0, 0.000000), (8299, 4.811014) );
     if( *pszHeaderNext == '(' )
     {
         CPLString osWord;
@@ -185,24 +194,24 @@ int CPLKeywordParser::ReadPair( CPLString &osName, CPLString &osValue )
             osValue += osWord;
             const char* pszIter = osWord.c_str();
             bool bInQuote = false;
-            while(*pszIter != '\0')
+            while( *pszIter != '\0' )
             {
-                if (*pszIter == '"')
+                if( *pszIter == '"' )
                     bInQuote = !bInQuote;
-                else if (!bInQuote)
+                else if( !bInQuote )
                 {
-                    if (*pszIter == '(')
-                        nDepth ++;
-                    else if (*pszIter == ')')
+                    if( *pszIter == '(' )
+                        nDepth++;
+                    else if( *pszIter == ')' )
                     {
-                        nDepth --;
-                        if (nDepth == 0)
+                        nDepth--;
+                        if( nDepth == 0 )
                             break;
                     }
                 }
-                pszIter ++;
+                pszIter++;
             }
-            if (*pszIter == ')' && nDepth == 0)
+            if( *pszIter == ')' && nDepth == 0 )
                 break;
         }
     }
@@ -211,7 +220,6 @@ int CPLKeywordParser::ReadPair( CPLString &osName, CPLString &osValue )
     {
         if( !ReadWord( osValue ) )
             return FALSE;
-
     }
 
     SkipWhite();
@@ -232,7 +240,7 @@ int CPLKeywordParser::ReadPair( CPLString &osName, CPLString &osValue )
         SkipWhite();
 
         osValue += osWord;
-        if( osWord[strlen(osWord)-1] == '>' )
+        if( osWord.back() == '>' )
             break;
     }
 
@@ -328,7 +336,7 @@ void CPLKeywordParser::SkipWhite()
         }
 
         // Skip # style comments
-        if( *pszHeaderNext == '#'  )
+        if( *pszHeaderNext == '#' )
         {
             pszHeaderNext += 1;
 
@@ -361,3 +369,5 @@ const char *CPLKeywordParser::GetKeyword( const char *pszPath,
 
     return pszResult;
 }
+
+//! @endcond
diff --git a/port/cplkeywordparser.h b/port/cplkeywordparser.h
index 70f0013..fb1ade9 100644
--- a/port/cplkeywordparser.h
+++ b/port/cplkeywordparser.h
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cplkeywordparser.h 33666 2016-03-07 05:21:07Z goatbar $
+ * $Id: cplkeywordparser.h 34931 2016-08-05 17:13:05Z rouault $
  *
  * Project:  Common Portability Library
  * Purpose:  Implementation of CPLKeywordParser - a class for parsing
@@ -41,6 +41,8 @@
 /* ==================================================================== */
 /************************************************************************/
 
+/*! @cond Doxygen_Suppress */
+
 class CPLKeywordParser
 {
     char     **papszKeywordList;
@@ -63,4 +65,6 @@ public:
     char  **GetAllKeywords() { return papszKeywordList; }
 };
 
+/*! @endcond */
+
 #endif /* def CPL_KEYWORD_PARSER */
diff --git a/port/cplstring.cpp b/port/cplstring.cpp
index 4097f0a..bc98411 100644
--- a/port/cplstring.cpp
+++ b/port/cplstring.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cplstring.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  CPLString implementation.
@@ -28,10 +27,19 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_string.h"
+
+#include <cctype>
+#include <cstdarg>
+#include <cstddef>
+#include <cstring>
 #include <string>
 
-CPL_CVSID("$Id: cplstring.cpp 33646 2016-03-05 15:54:03Z goatbar $");
+#include "cpl_config.h"
+#include "cpl_conv.h"
+
+CPL_CVSID("$Id: cplstring.cpp 36981 2016-12-20 19:46:41Z rouault $");
 
 /*
  * The CPLString class is derived from std::string, so the vast majority
@@ -43,7 +51,8 @@ CPL_CVSID("$Id: cplstring.cpp 33646 2016-03-05 15:54:03Z goatbar $");
 /*                               Printf()                               */
 /************************************************************************/
 
-CPLString &CPLString::Printf( const char *pszFormat, ... )
+/** Assign the content of the string using sprintf() */
+CPLString &CPLString::Printf( CPL_FORMAT_STRING(const char *pszFormat), ... )
 
 {
     va_list args;
@@ -59,7 +68,9 @@ CPLString &CPLString::Printf( const char *pszFormat, ... )
 /*                              vPrintf()                               */
 /************************************************************************/
 
-CPLString &CPLString::vPrintf( const char *pszFormat, va_list args )
+/** Assign the content of the string using vsprintf() */
+CPLString &CPLString::vPrintf( CPL_FORMAT_STRING(const char *pszFormat),
+                               va_list args )
 
 {
 /* -------------------------------------------------------------------- */
@@ -68,7 +79,7 @@ CPLString &CPLString::vPrintf( const char *pszFormat, va_list args )
 /* -------------------------------------------------------------------- */
 
 #if !defined(HAVE_VSNPRINTF)
-    char *pszBuffer = (char *) CPLMalloc(30000);
+    char *pszBuffer = static_cast<char *>(CPLMalloc(30000));
     if( CPLvsnprintf( pszBuffer, 30000, pszFormat, args) > 29998 )
     {
         CPLError( CE_Fatal, CPLE_AppDefined,
@@ -90,14 +101,14 @@ CPLString &CPLString::vPrintf( const char *pszFormat, va_list args )
     wrk_args = args;
 #endif
 
-    char szModestBuffer[500];
+    char szModestBuffer[500] = {};
     szModestBuffer[0] = '\0';
     int nPR = CPLvsnprintf( szModestBuffer, sizeof(szModestBuffer), pszFormat,
                              wrk_args );
     if( nPR == -1 || nPR >= (int) sizeof(szModestBuffer)-1 )
     {
         int nWorkBufferSize = 2000;
-        char *pszWorkBuffer = reinterpret_cast<char *>(
+        char *pszWorkBuffer = static_cast<char *>(
             CPLMalloc(nWorkBufferSize));
 
 #ifdef va_copy
@@ -106,13 +117,14 @@ CPLString &CPLString::vPrintf( const char *pszFormat, va_list args )
 #else
         wrk_args = args;
 #endif
-        while( (nPR=CPLvsnprintf( pszWorkBuffer, nWorkBufferSize, pszFormat,wrk_args))
+        while( (nPR = CPLvsnprintf(pszWorkBuffer, nWorkBufferSize, pszFormat,
+                                   wrk_args))
                >= nWorkBufferSize-1
                || nPR == -1 )
         {
             nWorkBufferSize *= 4;
-            pszWorkBuffer = (char *) CPLRealloc(pszWorkBuffer,
-                                                nWorkBufferSize );
+            pszWorkBuffer = static_cast<char *>(
+                CPLRealloc(pszWorkBuffer, nWorkBufferSize));
 #ifdef va_copy
             va_end( wrk_args );
             va_copy( wrk_args, args );
@@ -162,7 +174,7 @@ CPLString &CPLString::FormatC( double dfValue, const char *pszFormat )
 
     // presumably long enough for any number.
     const size_t buf_size = 512;
-    char szWork[buf_size];
+    char szWork[buf_size] = {};
 
     CPLsnprintf( szWork, buf_size, pszFormat, dfValue );
 
@@ -179,7 +191,7 @@ CPLString &CPLString::FormatC( double dfValue, const char *pszFormat )
  * Trim white space.
  *
  * Trims white space off the let and right of the string.  White space
- * is any of a space, a tab, a newline ('\n') or a carriage control ('\r').
+ * is any of a space, a tab, a newline ('\\n') or a carriage control ('\\r').
  *
  * @return a reference to the CPLString.
  */
@@ -207,6 +219,7 @@ CPLString &CPLString::Trim()
 /*                               Recode()                               */
 /************************************************************************/
 
+/** Recode the string */
 CPLString &CPLString::Recode( const char *pszSrcEncoding,
                               const char *pszDstEncoding )
 
@@ -216,7 +229,7 @@ CPLString &CPLString::Recode( const char *pszSrcEncoding,
     if( pszDstEncoding == NULL )
         pszDstEncoding = CPL_ENC_UTF8;
 
-    if( strcmp(pszSrcEncoding,pszDstEncoding) == 0 )
+    if( strcmp(pszSrcEncoding, pszDstEncoding) == 0 )
         return *this;
 
     char *pszRecoded = CPLRecode( c_str(),
@@ -256,7 +269,8 @@ size_t CPLString::ifind( const std::string & str, size_t pos ) const
  *
  * @param s substring to find.
  * @param nPos offset in the string at which the search starts.
- * @return the position of the substring in the string or std::string::npos if not found.
+ * @return the position of the substring in the string or std::string::npos if
+ * not found.
  * @since GDAL 1.9.0
  */
 
@@ -264,8 +278,8 @@ size_t CPLString::ifind( const char *s, size_t nPos ) const
 
 {
     const char *pszHaystack = c_str();
-    char chFirst = (char) ::tolower( s[0] );
-    size_t nTargetLen = strlen(s);
+    const char chFirst = static_cast<char>(::tolower(s[0]));
+    const size_t nTargetLen = strlen(s);
 
     if( nPos > size() )
         nPos = size();
@@ -276,7 +290,7 @@ size_t CPLString::ifind( const char *s, size_t nPos ) const
     {
         if( chFirst == ::tolower(*pszHaystack) )
         {
-            if( EQUALN(pszHaystack,s,nTargetLen) )
+            if( EQUALN(pszHaystack, s, nTargetLen) )
                 return nPos;
         }
 
@@ -299,7 +313,7 @@ CPLString &CPLString::toupper()
 
 {
     for( size_t i = 0; i < size(); i++ )
-        (*this)[i] = (char) ::toupper( (*this)[i] );
+        (*this)[i] = static_cast<char>(::toupper((*this)[i]));
 
     return *this;
 }
@@ -315,12 +329,63 @@ CPLString &CPLString::toupper()
 CPLString &CPLString::tolower()
 
 {
-    for(size_t i = 0; i < size(); i++ )
-        (*this)[i] = (char) ::tolower( (*this)[i] );
+    for( size_t i = 0; i < size(); i++ )
+        (*this)[i] = static_cast<char>(::tolower((*this)[i]));
+
+    return *this;
+}
+
+/************************************************************************/
+/*                             replaceAll()                             */
+/************************************************************************/
 
+/**
+ * Replace all occurrences of osBefore with osAfter.
+ */
+CPLString &CPLString::replaceAll( const std::string &osBefore,
+                                  const std::string &osAfter )
+{
+    const size_t nBeforeSize = osBefore.size();
+    const size_t nAfterSize = osAfter.size();
+    if( nBeforeSize )
+    {
+        size_t nStartPos = 0;
+        while( (nStartPos = find(osBefore, nStartPos)) != std::string::npos )
+        {
+            replace(nStartPos, nBeforeSize, osAfter);
+            nStartPos += nAfterSize;
+        }
+    }
     return *this;
 }
 
+/**
+ * Replace all occurrences of chBefore with osAfter.
+ */
+CPLString &CPLString::replaceAll( char chBefore,
+                                  const std::string &osAfter )
+{
+    return replaceAll(std::string(&chBefore, 1), osAfter);
+}
+
+/**
+ * Replace all occurrences of osBefore with chAfter.
+ */
+CPLString &CPLString::replaceAll( const std::string &osBefore,
+                                  char chAfter )
+{
+    return replaceAll(osBefore, std::string(&chAfter, 1));
+}
+
+/**
+ * Replace all occurrences of chBefore with chAfter.
+ */
+CPLString &CPLString::replaceAll( char chBefore,
+                                  char chAfter )
+{
+    return replaceAll(std::string(&chBefore, 1), std::string(&chAfter, 1));
+}
+
 /************************************************************************/
 /*                         CPLURLGetValue()                             */
 /************************************************************************/
@@ -338,13 +403,13 @@ CPLString CPLURLGetValue(const char* pszURL, const char* pszKey)
     CPLString osKey(pszKey);
     osKey += "=";
     size_t nKeyPos = CPLString(pszURL).ifind(osKey);
-    if (nKeyPos != std::string::npos && nKeyPos > 0 &&
-        (pszURL[nKeyPos-1] == '?' || pszURL[nKeyPos-1] == '&'))
+    if( nKeyPos != std::string::npos && nKeyPos > 0 &&
+        (pszURL[nKeyPos-1] == '?' || pszURL[nKeyPos-1] == '&') )
     {
-        CPLString osValue(pszURL + nKeyPos + strlen(osKey));
+        CPLString osValue(pszURL + nKeyPos + osKey.size());
         const char* pszValue = osValue.c_str();
         const char* pszSep = strchr(pszValue, '&');
-        if (pszSep)
+        if( pszSep )
         {
             osValue.resize(pszSep - pszValue);
         }
@@ -370,28 +435,28 @@ CPLString CPLURLAddKVP(const char* pszURL, const char* pszKey,
                        const char* pszValue)
 {
     CPLString osURL(pszURL);
-    if (strchr(osURL, '?') == NULL)
+    if( strchr(osURL, '?') == NULL )
         osURL += "?";
     pszURL = osURL.c_str();
 
     CPLString osKey(pszKey);
     osKey += "=";
     size_t nKeyPos = osURL.ifind(osKey);
-    if (nKeyPos != std::string::npos && nKeyPos > 0 &&
-        (pszURL[nKeyPos-1] == '?' || pszURL[nKeyPos-1] == '&'))
+    if( nKeyPos != std::string::npos && nKeyPos > 0 &&
+        (pszURL[nKeyPos-1] == '?' || pszURL[nKeyPos-1] == '&') )
     {
         CPLString osNewURL(osURL);
         osNewURL.resize(nKeyPos);
-        if (pszValue)
+        if( pszValue )
         {
             osNewURL += osKey;
             osNewURL += pszValue;
         }
         const char* pszNext = strchr(pszURL + nKeyPos, '&');
-        if (pszNext)
+        if( pszNext )
         {
-            if (osNewURL[osNewURL.size()-1] == '&'
-                || osNewURL[osNewURL.size()-1] == '?' )
+            if( osNewURL.back() == '&'
+                || osNewURL.back() == '?' )
                 osNewURL += pszNext + 1;
             else
                 osNewURL += pszNext;
@@ -400,9 +465,9 @@ CPLString CPLURLAddKVP(const char* pszURL, const char* pszKey,
     }
     else
     {
-        if (pszValue)
+        if( pszValue )
         {
-            if (osURL[osURL.size()-1] != '&' && osURL[osURL.size()-1] != '?')
+            if( osURL.back() != '&' && osURL.back() != '?' )
                 osURL += '&';
             osURL += osKey;
             osURL += pszValue;
@@ -415,7 +480,8 @@ CPLString CPLURLAddKVP(const char* pszURL, const char* pszKey,
 /*                            CPLOPrintf()                              */
 /************************************************************************/
 
-CPLString CPLOPrintf( const char *pszFormat, ... )
+/** Return a CPLString with the content of sprintf() */
+CPLString CPLOPrintf( CPL_FORMAT_STRING(const char *pszFormat), ... )
 
 {
     va_list args;
@@ -433,7 +499,8 @@ CPLString CPLOPrintf( const char *pszFormat, ... )
 /*                            CPLOvPrintf()                             */
 /************************************************************************/
 
-CPLString CPLOvPrintf( const char *pszFormat, va_list args )
+/** Return a CPLString with the content of vsprintf() */
+CPLString CPLOvPrintf( CPL_FORMAT_STRING(const char *pszFormat), va_list args )
 
 {
     CPLString osTarget;
diff --git a/port/cplstringlist.cpp b/port/cplstringlist.cpp
index 2ab5018..ef3e91f 100644
--- a/port/cplstringlist.cpp
+++ b/port/cplstringlist.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: cplstringlist.cpp 33789 2016-03-26 01:31:36Z goatbar $
  *
  * Project:  GDAL
  * Purpose:  CPLStringList implementation.
@@ -28,10 +27,21 @@
  * DEALINGS IN THE SOFTWARE.
  ****************************************************************************/
 
+#include "cpl_port.h"
 #include "cpl_string.h"
+
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <algorithm>
 #include <string>
 
-CPL_CVSID("$Id: cplstringlist.cpp 33789 2016-03-26 01:31:36Z goatbar $");
+#include "cpl_conv.h"
+#include "cpl_error.h"
+
+CPL_CVSID("$Id: cplstringlist.cpp 36910 2016-12-16 18:49:46Z goatbar $");
 
 /************************************************************************/
 /*                           CPLStringList()                            */
@@ -76,7 +86,7 @@ CPLStringList::CPLStringList( const CPLStringList &oOther )
     Assign( oOther.papszList, FALSE );
 
     // We don't want to just retain a reference to the others list
-    // as we don't want to make assumptions about it's lifetime that
+    // as we don't want to make assumptions about its lifetime that
     // might surprise the client developer.
     MakeOurOwnCopy();
     bIsSorted = oOther.bIsSorted;
@@ -86,14 +96,14 @@ CPLStringList::CPLStringList( const CPLStringList &oOther )
 /*                             operator=()                              */
 /************************************************************************/
 
-CPLStringList &CPLStringList::operator=(const CPLStringList& oOther)
+CPLStringList &CPLStringList::operator=( const CPLStringList& oOther )
 {
-    if (this != &oOther)
+    if( this != &oOther )
     {
         Assign( oOther.papszList, FALSE );
 
         // We don't want to just retain a reference to the others list
-        // as we don't want to make assumptions about it's lifetime that
+        // as we don't want to make assumptions about its lifetime that
         // might surprise the client developer.
         MakeOurOwnCopy();
         bIsSorted = oOther.bIsSorted;
@@ -198,12 +208,13 @@ int CPLStringList::Count() const
     {
         if( papszList == NULL )
         {
-            nCount = nAllocation = 0;
+            nCount = 0;
+            nAllocation = 0;
         }
         else
         {
             nCount = CSLCount( papszList );
-            nAllocation = MAX(nCount+1,nAllocation);
+            nAllocation = std::max(nCount + 1, nAllocation);
         }
     }
 
@@ -248,7 +259,7 @@ void CPLStringList::EnsureAllocation( int nMaxList )
 
     if( nAllocation <= nMaxList )
     {
-        nAllocation = MAX(nAllocation*2 + 20,nMaxList+1);
+        nAllocation = std::max(nAllocation * 2 + 20, nMaxList + 1);
         if( papszList == NULL )
         {
             papszList = static_cast<char **>(
@@ -325,11 +336,11 @@ CPLStringList &CPLStringList::AddString( const char *pszNewString )
  * @param pszValue the key value to add.
  */
 
-CPLStringList &CPLStringList::AddNameValue( const char  *pszKey,
+CPLStringList &CPLStringList::AddNameValue( const char *pszKey,
                                             const char *pszValue )
 
 {
-    if (pszKey == NULL || pszValue==NULL)
+    if( pszKey == NULL || pszValue==NULL )
         return *this;
 
     MakeOurOwnCopy();
@@ -474,7 +485,6 @@ char **CPLStringList::StealList()
     return papszRetList;
 }
 
-
 static int CPLCompareKeyValueString(const char* pszKVa, const char* pszKVb)
 {
     const char* pszItera = pszKVa;
@@ -502,8 +512,8 @@ static int CPLCompareKeyValueString(const char* pszKVa, const char* pszKVb)
             return -1;
         else if( cha > chb )
             return 1;
-        pszItera ++;
-        pszIterb ++;
+        pszItera++;
+        pszIterb++;
     }
 }
 
@@ -581,11 +591,11 @@ int CPLStringList::FindName( const char *pszKey ) const
         const int iMiddle = (iEnd + iStart) / 2;
         const char *pszMiddle = papszList[iMiddle];
 
-        if (EQUALN(pszMiddle, pszKey, nKeyLen)
+        if( EQUALN(pszMiddle, pszKey, nKeyLen )
             && (pszMiddle[nKeyLen] == '=' || pszMiddle[nKeyLen] == ':') )
             return iMiddle;
 
-        if( CPLCompareKeyValueString(pszKey,pszMiddle) < 0 )
+        if( CPLCompareKeyValueString(pszKey, pszMiddle) < 0 )
             iEnd = iMiddle-1;
         else
             iStart = iMiddle+1;
@@ -727,7 +737,6 @@ const char *CPLStringList::FetchNameValueDef( const char *pszName,
  * @param pszNewLine to the line to insert.  This string will be copied.
  */
 
-
 /************************************************************************/
 /*                        InsertStringDirectly()                        */
 /************************************************************************/
@@ -784,26 +793,26 @@ int CPLStringList::FindSortedInsertionPoint( const char *pszLine )
 {
     CPLAssert( IsSorted() );
 
-    int iStart=0;
-    int iEnd=nCount-1;
+    int iStart = 0;
+    int iEnd = nCount - 1;
 
     while( iStart <= iEnd )
     {
-        int iMiddle = (iEnd+iStart)/2;
+        const int iMiddle = (iEnd + iStart) / 2;
         const char *pszMiddle = papszList[iMiddle];
 
-        if( CPLCompareKeyValueString(pszLine,pszMiddle) < 0 )
-            iEnd = iMiddle-1;
+        if( CPLCompareKeyValueString(pszLine, pszMiddle) < 0 )
+            iEnd = iMiddle - 1;
         else
-            iStart = iMiddle+1;
+            iStart = iMiddle + 1;
     }
 
     iEnd++;
     CPLAssert( iEnd >= 0 && iEnd <= nCount );
     CPLAssert( iEnd == 0
-               || CPLCompareKeyValueString(pszLine,papszList[iEnd-1]) >= 0 );
+               || CPLCompareKeyValueString(pszLine, papszList[iEnd-1]) >= 0 );
     CPLAssert( iEnd == nCount
-               || CPLCompareKeyValueString(pszLine,papszList[iEnd]) <= 0 );
+               || CPLCompareKeyValueString(pszLine, papszList[iEnd]) <= 0 );
 
     return iEnd;
 }
diff --git a/port/makefile.vc b/port/makefile.vc
index 6fa11a3..b351157 100644
--- a/port/makefile.vc
+++ b/port/makefile.vc
@@ -20,9 +20,9 @@ OBJ	=	cpl_conv.obj \
 		cpl_getexecpath.obj \
 		cpl_vsil.obj \
 		cpl_vsi_mem.obj \
-                cpl_http.obj \
-                cpl_hash_set.obj \
-                cplkeywordparser.obj \
+		cpl_http.obj \
+		cpl_hash_set.obj \
+		cplkeywordparser.obj \
 		cpl_recode.obj \
 		cpl_recode_iconv.obj \
 		cpl_recode_stub.obj \
@@ -51,9 +51,12 @@ OBJ	=	cpl_conv.obj \
 		cpl_virtualmem.obj \
 		cpl_worker_thread_pool.obj \
 		cpl_vsil_crypt.obj \
+		cpl_sha1.obj \
 		cpl_sha256.obj \
 		cpl_aws.obj \
 		cpl_vsi_error.obj \
+		cpl_cpu_features.obj \
+		cpl_google_cloud.obj \
 		$(ODBC_OBJ)
 
 LIB	=	cpl.lib
@@ -62,7 +65,13 @@ GDAL_ROOT = ..
 
 !INCLUDE ..\nmake.opt
 
-EXTRAFLAGS	= 	 -I..\frmts\zlib -DHAVE_LIBZ
+!IFDEF ZLIB_EXTERNAL_LIB
+EXTRAFLAGS = $(ZLIB_INC)
+!ELSE
+EXTRAFLAGS = -I..\frmts\zlib
+!ENDIF
+
+EXTRAFLAGS	= 	 $(EXTRAFLAGS) -DHAVE_LIBZ
 
 !IFDEF LIBICONV_INCLUDE
 EXTRAFLAGS =	$(EXTRAFLAGS) -DHAVE_ICONV $(LIBICONV_CFLAGS) $(LIBICONV_INCLUDE)
@@ -94,7 +103,7 @@ $(LIB):	$(OBJ)
 	lib /out:cpl.lib *.obj
 
 clean:
-	-del *.obj *.lib
+	-del *.obj *.lib cpl_config.h
 
 cpl_config.h:	cpl_config.h.vc
 	copy cpl_config.h.vc cpl_config.h
diff --git a/port/vsipreload.cpp b/port/vsipreload.cpp
index 79e96c7..0da1de5 100644
--- a/port/vsipreload.cpp
+++ b/port/vsipreload.cpp
@@ -1,5 +1,4 @@
 /******************************************************************************
- * $Id: vsipreload.cpp 33724 2016-03-16 17:14:11Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  Standalone shared library that can be LD_PRELOAD'ed as an overload of
@@ -68,7 +67,7 @@
 #include "cpl_string.h"
 #include "cpl_hash_set.h"
 
-CPL_CVSID("$Id: vsipreload.cpp 33724 2016-03-16 17:14:11Z goatbar $");
+CPL_CVSID("$Id: vsipreload.cpp 37003 2016-12-23 14:54:07Z goatbar $");
 
 static int DEBUG_VSIPRELOAD = 0;
 static int DEBUG_VSIPRELOAD_ONLY_VSIL = 1;
@@ -84,8 +83,10 @@ static int DEBUG_VSIPRELOAD_ONLY_VSIL = 1;
 
 DECLARE_SYMBOL(fopen, FILE*, (const char *path, const char *mode));
 DECLARE_SYMBOL(fopen64, FILE*, (const char *path, const char *mode));
-DECLARE_SYMBOL(fread, size_t, (void *ptr, size_t size, size_t nmemb, FILE *stream));
-DECLARE_SYMBOL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb, FILE *stream));
+DECLARE_SYMBOL(fread, size_t, (void *ptr, size_t size, size_t nmemb,
+                               FILE *stream));
+DECLARE_SYMBOL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb,
+                                FILE *stream));
 DECLARE_SYMBOL(fclose, int, (FILE *stream));
 DECLARE_SYMBOL(__xstat, int, (int ver, const char *path, struct stat *buf));
 DECLARE_SYMBOL(__lxstat, int, (int ver, const char *path, struct stat *buf));
@@ -103,11 +104,12 @@ DECLARE_SYMBOL(ferror, int, (FILE *stream));
 DECLARE_SYMBOL(clearerr, void, (FILE *stream));
 
 DECLARE_SYMBOL(fdopen, FILE*, (int fd, const char *mode));
-DECLARE_SYMBOL(freopen, FILE*, (const char *path, const char *mode, FILE *stream));
+DECLARE_SYMBOL(freopen, FILE*, (const char *path, const char *mode,
+                                FILE *stream));
 
 DECLARE_SYMBOL(open, int, (const char *path, int flags, mode_t mode));
 DECLARE_SYMBOL(open64, int, (const char *path, int flags, mode_t mode));
-//DECLARE_SYMBOL(creat, int, (const char *path, mode_t mode));
+// DECLARE_SYMBOL(creat, int, (const char *path, mode_t mode));
 DECLARE_SYMBOL(close, int, (int fd));
 DECLARE_SYMBOL(read, ssize_t, (int fd, void *buf, size_t count));
 DECLARE_SYMBOL(write, ssize_t, (int fd, const void *buf, size_t count));
@@ -116,7 +118,8 @@ DECLARE_SYMBOL(fdatasync, int, (int fd));
 DECLARE_SYMBOL(__fxstat, int, (int ver, int fd, struct stat *__stat_buf));
 DECLARE_SYMBOL(__fxstat64, int, (int ver, int fd, struct stat64 *__stat_buf));
 #ifdef HAVE_FSTATAT
-DECLARE_SYMBOL(__fxstatat, int, (int ver, int dirfd, const char *pathname, struct stat *buf, int flags));
+DECLARE_SYMBOL(__fxstatat, int, (int ver, int dirfd, const char *pathname,
+                                 struct stat *buf, int flags));
 #endif
 
 DECLARE_SYMBOL(lseek, off_t, (int fd, off_t off, int whence));
@@ -161,7 +164,7 @@ std::string osCurDir;
     pfn ## x = (fn ## x ## Type) dlsym(RTLD_NEXT, #x); \
     assert(pfn ## x)
 
-static void myinit(void)
+static void myinit()
 {
     CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
 
@@ -192,7 +195,7 @@ static void myinit(void)
 
     LOAD_SYMBOL(open);
     LOAD_SYMBOL(open64);
-    //LOAD_SYMBOL(creat);
+    // LOAD_SYMBOL(creat);
     LOAD_SYMBOL(close);
     LOAD_SYMBOL(read);
     LOAD_SYMBOL(write);
@@ -221,11 +224,11 @@ static void myinit(void)
 /*                          getVSILFILE()                               */
 /************************************************************************/
 
-static VSILFILE* getVSILFILE(FILE* stream)
+static VSILFILE* getVSILFILE( FILE* stream )
 {
-    VSILFILE* ret;
     CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
     std::set<VSILFILE*>::iterator oIter = oSetFiles.find((VSILFILE*)stream);
+    VSILFILE* ret = NULL;
     if( oIter != oSetFiles.end() )
         ret = *oIter;
     else
@@ -237,11 +240,11 @@ static VSILFILE* getVSILFILE(FILE* stream)
 /*                          getVSILFILE()                               */
 /************************************************************************/
 
-static VSILFILE* getVSILFILE(int fd)
+static VSILFILE* getVSILFILE( int fd )
 {
-    VSILFILE* ret;
     CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
     std::map<int, VSILFILE*>::iterator oIter = oMapfdToVSI.find(fd);
+    VSILFILE* ret = NULL;
     if( oIter != oMapfdToVSI.end() )
         ret = oIter->second;
     else
@@ -253,7 +256,7 @@ static VSILFILE* getVSILFILE(int fd)
 /*                        VSIFSeekLHelper()                             */
 /************************************************************************/
 
-static int VSIFSeekLHelper(VSILFILE* fpVSIL, off64_t off, int whence)
+static int VSIFSeekLHelper( VSILFILE* fpVSIL, off64_t off, int whence )
 {
     if( off < 0 && whence == SEEK_CUR )
     {
@@ -264,15 +267,15 @@ static int VSIFSeekLHelper(VSILFILE* fpVSIL, off64_t off, int whence)
         VSIFSeekL(fpVSIL, 0, SEEK_END);
         return VSIFSeekL(fpVSIL, VSIFTellL(fpVSIL) + off, SEEK_SET);
     }
-    else
-        return VSIFSeekL(fpVSIL, off, whence);
+
+    return VSIFSeekL(fpVSIL, off, whence);
 }
 
 /************************************************************************/
 /*                          VSIFopenHelper()                            */
 /************************************************************************/
 
-static VSILFILE* VSIFfopenHelper(const char *path, const char *mode)
+static VSILFILE* VSIFfopenHelper( const char *path, const char *mode )
 {
     VSILFILE* fpVSIL = VSIFOpenL(path, mode);
     if( fpVSIL != NULL )
@@ -288,7 +291,7 @@ static VSILFILE* VSIFfopenHelper(const char *path, const char *mode)
 /*                         getfdFromVSILFILE()                          */
 /************************************************************************/
 
-static int getfdFromVSILFILE(VSILFILE* fpVSIL)
+static int getfdFromVSILFILE( VSILFILE* fpVSIL )
 {
     CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
 
@@ -310,12 +313,12 @@ static int getfdFromVSILFILE(VSILFILE* fpVSIL)
 /*                          VSIFopenHelper()                            */
 /************************************************************************/
 
-static int VSIFopenHelper(const char *path, int flags)
+static int VSIFopenHelper( const char *path, int flags )
 {
     const char* pszMode = "rb";
-    if ((flags & 3) == O_RDONLY)
+    if( (flags & 3) == O_RDONLY )
         pszMode = "rb";
-    else if ((flags & 3) == O_WRONLY)
+    else if( (flags & 3) == O_WRONLY )
     {
         if( flags & O_APPEND )
             pszMode = "ab";
@@ -349,31 +352,37 @@ static int VSIFopenHelper(const char *path, int flags)
 /*                    GET_DEBUG_VSIPRELOAD_COND()                             */
 /************************************************************************/
 
-static bool GET_DEBUG_VSIPRELOAD_COND(const char* path)
+static bool GET_DEBUG_VSIPRELOAD_COND( const char* path )
 {
-    return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || STARTS_WITH(path, "/vsi")) );
+    return
+        DEBUG_VSIPRELOAD &&
+        (!DEBUG_VSIPRELOAD_ONLY_VSIL || STARTS_WITH(path, "/vsi"));
 }
 
 static bool GET_DEBUG_VSIPRELOAD_COND(VSILFILE* fpVSIL)
 {
-    return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || fpVSIL != NULL));
+    return DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || fpVSIL != NULL);
 }
 
 static bool GET_DEBUG_VSIPRELOAD_COND(VSIDIR* dirP)
 {
-    return (DEBUG_VSIPRELOAD && (!DEBUG_VSIPRELOAD_ONLY_VSIL || oSetVSIDIR.find(dirP) != oSetVSIDIR.end()));
+    return
+        DEBUG_VSIPRELOAD &&
+        (!DEBUG_VSIPRELOAD_ONLY_VSIL ||
+         oSetVSIDIR.find(dirP) != oSetVSIDIR.end());
 }
 
 /************************************************************************/
 /*                     copyVSIStatBufLToBuf()                           */
 /************************************************************************/
 
-static void copyVSIStatBufLToBuf(VSIStatBufL* bufSrc, struct stat *buf)
+static void copyVSIStatBufLToBuf( VSIStatBufL* bufSrc, struct stat *buf )
 {
     buf->st_dev = bufSrc->st_dev;
     buf->st_ino = bufSrc->st_ino;
-    buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH; // S_IXUSR | S_IXGRP | S_IXOTH;
-    buf->st_nlink = 1; //bufSrc->st_nlink;
+    // S_IXUSR | S_IXGRP | S_IXOTH;
+    buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH;
+    buf->st_nlink = 1;   // bufSrc->st_nlink;
     buf->st_uid = bufSrc->st_uid;
     buf->st_gid = bufSrc->st_gid;
     buf->st_rdev = bufSrc->st_rdev;
@@ -389,12 +398,13 @@ static void copyVSIStatBufLToBuf(VSIStatBufL* bufSrc, struct stat *buf)
 /*                     copyVSIStatBufLToBuf64()                         */
 /************************************************************************/
 
-static void copyVSIStatBufLToBuf64(VSIStatBufL *bufSrc, struct stat64 *buf)
+static void copyVSIStatBufLToBuf64( VSIStatBufL *bufSrc, struct stat64 *buf )
 {
     buf->st_dev = bufSrc->st_dev;
     buf->st_ino = bufSrc->st_ino;
-    buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH; // S_IXUSR | S_IXGRP | S_IXOTH;
-    buf->st_nlink = 1; //bufSrc->st_nlink;
+    // S_IXUSR | S_IXGRP | S_IXOTH;
+    buf->st_mode = bufSrc->st_mode | S_IRUSR | S_IRGRP | S_IROTH;
+    buf->st_nlink = 1; // bufSrc->st_nlink;
     buf->st_uid = bufSrc->st_uid;
     buf->st_gid = bufSrc->st_gid;
     buf->st_rdev = bufSrc->st_rdev;
@@ -410,17 +420,17 @@ static void copyVSIStatBufLToBuf64(VSIStatBufL *bufSrc, struct stat64 *buf)
 /*                             fopen()                                  */
 /************************************************************************/
 
-FILE *fopen(const char *path, const char *mode)
+FILE *fopen( const char *path, const char *mode )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen(%s, %s)\n", path, mode);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fopen(%s, %s)\n", path, mode);
     FILE* ret;
     if( STARTS_WITH(path, "/vsi") )
         ret = (FILE*) VSIFfopenHelper(path, mode);
     else
         ret = pfnfopen(path, mode);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen() = %p\n", ret);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fopen() = %p\n", ret);
     return ret;
 }
 
@@ -428,17 +438,18 @@ FILE *fopen(const char *path, const char *mode)
 /*                            fopen64()                                 */
 /************************************************************************/
 
-FILE *fopen64(const char *path, const char *mode)
+FILE *fopen64( const char *path, const char *mode )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen64(%s, %s)\n", path, mode);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "fopen64(%s, %s)\n", path, mode);
     FILE* ret;
     if( STARTS_WITH(path, "/vsi") )
         ret = (FILE*) VSIFfopenHelper(path, mode);
     else
         ret = pfnfopen64(path, mode);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fopen64() = %p\n", ret);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fopen64() = %p\n", ret);
     return ret;
 }
 
@@ -446,20 +457,23 @@ FILE *fopen64(const char *path, const char *mode)
 /*                            fread()                                   */
 /************************************************************************/
 
-size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
+size_t fread( void *ptr, size_t size, size_t nmemb, FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d)\n",
-        stream, (int)size, (int)nmemb);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d)\n",
+                stream, static_cast<int>(size), static_cast<int>(nmemb));
     size_t ret = 0;
     if( fpVSIL )
         ret = VSIFReadL(ptr, size, nmemb, fpVSIL);
     else
         ret = pfnfread(ptr, size, nmemb, stream);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d) -> %d\n",
-        stream, (int)size, (int)nmemb, (int)ret);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "fread(stream=%p,size=%d,nmemb=%d) -> %d\n",
+                stream, static_cast<int>(size), static_cast<int>(nmemb),
+                static_cast<int>(ret));
     return ret;
 }
 
@@ -467,20 +481,23 @@ size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
 /*                            fwrite()                                  */
 /************************************************************************/
 
-size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+size_t fwrite( const void *ptr, size_t size, size_t nmemb, FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d)\n",
-        stream, (int)size, (int)nmemb);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d)\n",
+                stream, static_cast<int>(size), static_cast<int>(nmemb));
     size_t ret = 0;
     if( fpVSIL != NULL )
         ret = VSIFWriteL(ptr, size, nmemb, fpVSIL);
     else
         ret = pfnfwrite(ptr, size, nmemb, stream);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d) -> %d\n",
-        stream, (int)size, (int)nmemb, (int)ret);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "fwrite(stream=%p,size=%d,nmemb=%d) -> %d\n",
+                stream, static_cast<int>(size), static_cast<int>(nmemb),
+                static_cast<int>(ret));
     return ret;
 }
 
@@ -488,12 +505,12 @@ size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
 /*                            fclose()                                  */
 /************************************************************************/
 
-int fclose(FILE *stream)
+int fclose( FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fclose(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fclose(stream=%p)\n", stream);
     if( fpVSIL != NULL )
     {
         CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
@@ -521,30 +538,32 @@ int fclose(FILE *stream)
 /*                            __xstat()                                 */
 /************************************************************************/
 
-int __xstat(int ver, const char *path, struct stat *buf)
+int __xstat( int ver, const char *path, struct stat *buf )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
+    if( DEBUG_VSIPRELOAD && (!osCurDir.empty() && path[0] != '/') )
         DEBUG_VSIPRELOAD_COND = 1;
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__xstat(%s)\n", path);
-    if( (osCurDir.size() != 0 && path[0] != '/') || STARTS_WITH(path, "/vsi") )
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__xstat(%s)\n", path);
+    if( (!osCurDir.empty() && path[0] != '/') || STARTS_WITH(path, "/vsi") )
     {
         VSIStatBufL sStatBufL;
         std::string newpath;
-        if( (osCurDir.size() != 0 && path[0] != '/') )
+        if( (!osCurDir.empty() && path[0] != '/') )
         {
             newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
             path = newpath.c_str();
         }
         const int ret = VSIStatL(path, &sStatBufL);
-        sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
+        sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(path));
         if( ret == 0 )
         {
             copyVSIStatBufLToBuf(&sStatBufL, buf);
-            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-                "__xstat(%s) ret = 0, mode = %d, size=%d\n",
-                path, sStatBufL.st_mode, (int)sStatBufL.st_size);
+            if( DEBUG_VSIPRELOAD_COND )
+                fprintf(stderr,
+                        "__xstat(%s) ret = 0, mode = %d, size=%d\n",
+                        path, sStatBufL.st_mode,
+                        static_cast<int>(sStatBufL.st_size));
         }
         return ret;
     }
@@ -553,7 +572,7 @@ int __xstat(int ver, const char *path, struct stat *buf)
         int ret = pfn__xstat(ver, path, buf);
         if( ret == 0 )
         {
-            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+            if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr,
                 "__xstat ret = 0, mode = %d\n", buf->st_mode);
         }
         return ret;
@@ -564,30 +583,32 @@ int __xstat(int ver, const char *path, struct stat *buf)
 /*                           __lxstat()                                 */
 /************************************************************************/
 
-int __lxstat(int ver, const char *path, struct stat *buf)
+int __lxstat( int ver, const char *path, struct stat *buf )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
+    if( DEBUG_VSIPRELOAD && (!osCurDir.empty() && path[0] != '/') )
         DEBUG_VSIPRELOAD_COND = 1;
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__lxstat(%s)\n", path);
-    if( (osCurDir.size() != 0 && path[0] != '/') || STARTS_WITH(path, "/vsi") )
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__lxstat(%s)\n", path);
+    if( (!osCurDir.empty() && path[0] != '/') || STARTS_WITH(path, "/vsi") )
     {
         VSIStatBufL sStatBufL;
         std::string newpath;
-        if( (osCurDir.size() != 0 && path[0] != '/') )
+        if( (!osCurDir.empty() && path[0] != '/') )
         {
             newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
             path = newpath.c_str();
         }
         const int ret = VSIStatL(path, &sStatBufL);
-        sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
+        sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(path));
         if( ret == 0 )
         {
             copyVSIStatBufLToBuf(&sStatBufL, buf);
-            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-                "__lxstat(%s) ret = 0, mode = %d, size=%d\n",
-                path, sStatBufL.st_mode, (int)sStatBufL.st_size);
+            if( DEBUG_VSIPRELOAD_COND )
+                fprintf(stderr,
+                        "__lxstat(%s) ret = 0, mode = %d, size=%d\n",
+                        path, sStatBufL.st_mode,
+                        static_cast<int>(sStatBufL.st_size));
         }
         return ret;
     }
@@ -596,7 +617,7 @@ int __lxstat(int ver, const char *path, struct stat *buf)
         int ret = pfn__lxstat(ver, path, buf);
         if( ret == 0 )
         {
-            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
+            if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr,
                 "__lxstat ret = 0, mode = %d\n", buf->st_mode);
         }
         return ret;
@@ -607,30 +628,31 @@ int __lxstat(int ver, const char *path, struct stat *buf)
 /*                           __xstat64()                                */
 /************************************************************************/
 
-int __xstat64(int ver, const char *path, struct stat64 *buf)
+int __xstat64( int ver, const char *path, struct stat64 *buf )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if( DEBUG_VSIPRELOAD && (osCurDir.size() != 0 && path[0] != '/') )
+    if( DEBUG_VSIPRELOAD && (!osCurDir.empty() && path[0] != '/') )
         DEBUG_VSIPRELOAD_COND = 1;
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__xstat64(%s)\n", path);
-    if( (osCurDir.size() != 0 && path[0] != '/') || STARTS_WITH(path, "/vsi") )
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__xstat64(%s)\n", path);
+    if( (!osCurDir.empty() && path[0] != '/') || STARTS_WITH(path, "/vsi") )
     {
         VSIStatBufL sStatBufL;
         std::string newpath;
-        if( (osCurDir.size() != 0 && path[0] != '/') )
+        if( (!osCurDir.empty() && path[0] != '/') )
         {
             newpath = CPLFormFilename(osCurDir.c_str(), path, NULL);
             path = newpath.c_str();
         }
         const int ret = VSIStatL(path, &sStatBufL);
-        sStatBufL.st_ino = (int)CPLHashSetHashStr(path);
+        sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(path));
         if( ret == 0 )
         {
             copyVSIStatBufLToBuf64(&sStatBufL, buf);
-            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-                "__xstat64(%s) ret = 0, mode = %d, size = %d\n",
-                path, buf->st_mode, (int)buf->st_size);
+            if( DEBUG_VSIPRELOAD_COND )
+                fprintf(stderr,
+                        "__xstat64(%s) ret = 0, mode = %d, size = %d\n",
+                        path, buf->st_mode, static_cast<int>(buf->st_size));
         }
         return ret;
     }
@@ -642,13 +664,14 @@ int __xstat64(int ver, const char *path, struct stat64 *buf)
 /*                           fseeko64()                                 */
 /************************************************************************/
 
-int fseeko64 (FILE *stream, off64_t off, int whence)
+int fseeko64( FILE *stream, off64_t off, int whence )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fseeko64(stream=%p, off=%d, whence=%d)\n",
-        stream, (int)off, whence);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "fseeko64(stream=%p, off=%d, whence=%d)\n",
+                stream, static_cast<int>(off), whence);
     if( fpVSIL != NULL )
         return VSIFSeekLHelper(fpVSIL, off, whence);
     else
@@ -659,13 +682,14 @@ int fseeko64 (FILE *stream, off64_t off, int whence)
 /*                           fseeko()                                 */
 /************************************************************************/
 
-int fseeko (FILE *stream, off_t off, int whence)
+int fseeko( FILE *stream, off_t off, int whence )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fseeko(stream=%p, off=%d, whence=%d)\n",
-        stream, (int)off, whence);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "fseeko(stream=%p, off=%d, whence=%d)\n",
+                stream, static_cast<int>(off), whence);
     if( fpVSIL != NULL )
         return VSIFSeekLHelper(fpVSIL, off, whence);
     else
@@ -676,13 +700,14 @@ int fseeko (FILE *stream, off_t off, int whence)
 /*                            fseek()                                   */
 /************************************************************************/
 
-int fseek (FILE *stream, off_t off, int whence)
+int fseek( FILE *stream, off_t off, int whence )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fseek(stream=%p, off=%d, whence=%d)\n",
-        stream, (int)off, whence);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "fseek(stream=%p, off=%d, whence=%d)\n",
+                stream, static_cast<int>(off), whence);
     if( fpVSIL != NULL )
         return VSIFSeekLHelper(fpVSIL, off, whence);
     else
@@ -693,12 +718,13 @@ int fseek (FILE *stream, off_t off, int whence)
 /*                           ftello64()                                 */
 /************************************************************************/
 
-off64_t ftello64(FILE *stream)
+off64_t ftello64( FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftello64(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "ftello64(stream=%p)\n", stream);
     if( fpVSIL != NULL )
         return VSIFTellL(fpVSIL);
     else
@@ -709,12 +735,12 @@ off64_t ftello64(FILE *stream)
 /*                            ftello()                                  */
 /************************************************************************/
 
-off_t ftello(FILE *stream)
+off_t ftello( FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftello(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "ftello(stream=%p)\n", stream);
     if( fpVSIL != NULL )
         return VSIFTellL(fpVSIL);
     else
@@ -725,12 +751,12 @@ off_t ftello(FILE *stream)
 /*                            ftell()                                   */
 /************************************************************************/
 
-off_t ftell(FILE *stream)
+off_t ftell( FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftell(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "ftell(stream=%p)\n", stream);
     if( fpVSIL != NULL )
         return VSIFTellL(fpVSIL);
     else
@@ -741,12 +767,12 @@ off_t ftell(FILE *stream)
 /*                             feof()                                   */
 /************************************************************************/
 
-int feof(FILE *stream)
+int feof( FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "feof(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "feof(stream=%p)\n", stream);
     if( fpVSIL != NULL )
         return VSIFEofL(fpVSIL);
     else
@@ -757,7 +783,7 @@ int feof(FILE *stream)
 /*                            rewind()                                  */
 /************************************************************************/
 
-void rewind(FILE *stream)
+void rewind( FILE *stream )
 {
     fseek(stream, 0, SEEK_SET);
 }
@@ -766,12 +792,12 @@ void rewind(FILE *stream)
 /*                            fflush()                                  */
 /************************************************************************/
 
-int fflush(FILE *stream)
+int fflush( FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fflush(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fflush(stream=%p)\n", stream);
     if( fpVSIL != NULL )
         return 0;
     else
@@ -782,12 +808,12 @@ int fflush(FILE *stream)
 /*                            fgetpos()                                 */
 /************************************************************************/
 
-int fgetpos(FILE *stream, fpos_t *pos)
+int fgetpos( FILE *stream, fpos_t *pos )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fgetpos(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fgetpos(stream=%p)\n", stream);
     if( fpVSIL != NULL )
     {
         fprintf(stderr, "fgetpos() unimplemented for VSILFILE\n");
@@ -801,12 +827,12 @@ int fgetpos(FILE *stream, fpos_t *pos)
 /*                            fsetpos()                                 */
 /************************************************************************/
 
-int fsetpos(FILE *stream, fpos_t *pos)
+int fsetpos( FILE *stream, fpos_t *pos )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fsetpos(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fsetpos(stream=%p)\n", stream);
     if( fpVSIL != NULL )
     {
         fprintf(stderr, "fsetpos() unimplemented for VSILFILE\n");
@@ -820,18 +846,19 @@ int fsetpos(FILE *stream, fpos_t *pos)
 /*                             fileno()                                 */
 /************************************************************************/
 
-int fileno(FILE *stream)
+int fileno( FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fileno(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fileno(stream=%p)\n", stream);
     int fd = 0;
     if( fpVSIL != NULL )
         fd = getfdFromVSILFILE(fpVSIL);
     else
         fd = pfnfileno(stream);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fileno(stream=%p) = %d\n", stream, fd);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "fileno(stream=%p) = %d\n", stream, fd);
     return fd;
 }
 
@@ -839,12 +866,12 @@ int fileno(FILE *stream)
 /*                             ferror()                                 */
 /************************************************************************/
 
-int ferror(FILE *stream)
+int ferror( FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ferror(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "ferror(stream=%p)\n", stream);
     if( fpVSIL != NULL )
     {
         fprintf(stderr, "ferror() unimplemented for VSILFILE\n");
@@ -858,12 +885,13 @@ int ferror(FILE *stream)
 /*                             clearerr()                               */
 /************************************************************************/
 
-void clearerr(FILE *stream)
+void clearerr( FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "clearerr(stream=%p)\n", stream);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "clearerr(stream=%p)\n", stream);
     if( fpVSIL != NULL )
     {
         fprintf(stderr, "clearerr() unimplemented for VSILFILE\n");
@@ -876,12 +904,12 @@ void clearerr(FILE *stream)
 /*                             fdopen()                                 */
 /************************************************************************/
 
-FILE * fdopen(int fd, const char *mode)
+FILE * fdopen( int fd, const char *mode )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fdopen(fd=%d)\n", fd);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fdopen(fd=%d)\n", fd);
     if( fpVSIL != NULL )
     {
         fprintf(stderr, "fdopen() unimplemented for VSILFILE\n");
@@ -895,12 +923,14 @@ FILE * fdopen(int fd, const char *mode)
 /*                             freopen()                                */
 /************************************************************************/
 
-FILE *freopen(const char *path, const char *mode, FILE *stream)
+FILE *freopen( const char *path, const char *mode, FILE *stream )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(stream);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "freopen(path=%s,mode=%s,stream=%p)\n", path, mode, stream);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "freopen(path=%s,mode=%s,stream=%p)\n",
+                path, mode, stream);
     if( fpVSIL != NULL )
     {
         fprintf(stderr, "freopen() unimplemented for VSILFILE\n");
@@ -914,16 +944,17 @@ FILE *freopen(const char *path, const char *mode, FILE *stream)
 /*                              open()                                  */
 /************************************************************************/
 
-int open(const char *path, int flags, ...)
+int open( const char *path, int flags, ... )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 && path[0] != '/' )
+    if( DEBUG_VSIPRELOAD && !osCurDir.empty() && path[0] != '/' )
         DEBUG_VSIPRELOAD_COND = 1;
-    if (DEBUG_VSIPRELOAD_COND)
+    if( DEBUG_VSIPRELOAD_COND )
     {
-        if( osCurDir.size() != 0 && path[0] != '/' )
-            fprintf(stderr, "open(%s)\n", CPLFormFilename(osCurDir.c_str(), path, NULL));
+        if( !osCurDir.empty() && path[0] != '/' )
+            fprintf(stderr, "open(%s)\n",
+                    CPLFormFilename(osCurDir.c_str(), path, NULL));
         else
             fprintf(stderr, "open(%s)\n", path);
     }
@@ -932,10 +963,12 @@ int open(const char *path, int flags, ...)
     va_start(args, flags);
     mode_t mode = va_arg(args, mode_t);
     int fd = 0;
-    if( osCurDir.size() != 0 && path[0] != '/' && (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
+    if( !osCurDir.empty() && path[0] != '/' &&
+        (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
     {
         VSIStatBufL sStatBufL;
-        char* newname = (char*)CPLFormFilename(osCurDir.c_str(), path, NULL);
+        char* newname =
+            const_cast<char *>(CPLFormFilename(osCurDir.c_str(), path, NULL));
         if( strchr(osCurDir.c_str(), '/') != NULL && strcmp(path, "..") == 0 )
         {
             char* lastslash = strrchr(newname, '/');
@@ -962,7 +995,7 @@ int open(const char *path, int flags, ...)
     else
         fd = pfnopen(path, flags, mode);
     va_end(args);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "open(%s) = %d\n", path, fd);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "open(%s) = %d\n", path, fd);
     return fd;
 }
 
@@ -970,16 +1003,17 @@ int open(const char *path, int flags, ...)
 /*                             open64()                                 */
 /************************************************************************/
 
-int open64(const char *path, int flags, ...)
+int open64( const char *path, int flags, ... )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 && path[0] != '/' )
+    if( DEBUG_VSIPRELOAD && !osCurDir.empty() && path[0] != '/' )
         DEBUG_VSIPRELOAD_COND = 1;
-    if (DEBUG_VSIPRELOAD_COND)
+    if( DEBUG_VSIPRELOAD_COND )
     {
-        if( osCurDir.size() != 0 && path[0] != '/' )
-            fprintf(stderr, "open64(%s)\n", CPLFormFilename(osCurDir.c_str(), path, NULL));
+        if( !osCurDir.empty() && path[0] != '/' )
+            fprintf(stderr, "open64(%s)\n",
+                    CPLFormFilename(osCurDir.c_str(), path, NULL));
         else
             fprintf(stderr, "open64(%s)\n", path);
     }
@@ -988,10 +1022,12 @@ int open64(const char *path, int flags, ...)
     va_start(args, flags);
     mode_t mode = va_arg(args, mode_t);
     int fd = 0;
-    if( osCurDir.size() != 0 && path[0] != '/' && (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
+    if( !osCurDir.empty() && path[0] != '/' &&
+        (flags & 3) == O_RDONLY && (flags & O_DIRECTORY) != 0 )
     {
         VSIStatBufL sStatBufL;
-        char* newname = (char*)CPLFormFilename(osCurDir.c_str(), path, NULL);
+        char* newname =
+            const_cast<char *>(CPLFormFilename(osCurDir.c_str(), path, NULL));
         if( strchr(osCurDir.c_str(), '/') != NULL && strcmp(path, "..") == 0 )
         {
             char* lastslash = strrchr(newname, '/');
@@ -1018,7 +1054,7 @@ int open64(const char *path, int flags, ...)
     else
         fd = pfnopen64(path, flags, mode);
     va_end(args);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "open64(%s) = %d\n", path, fd);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "open64(%s) = %d\n", path, fd);
     return fd;
 }
 
@@ -1026,7 +1062,7 @@ int open64(const char *path, int flags, ...)
 /*                             creat()                                  */
 /************************************************************************/
 
-int creat(const char *path, mode_t mode)
+int creat( const char *path, mode_t mode )
 {
     return open64(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
 }
@@ -1035,7 +1071,7 @@ int creat(const char *path, mode_t mode)
 /*                             close()                                  */
 /************************************************************************/
 
-int close(int fd)
+int close( int fd )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(fd);
@@ -1044,6 +1080,7 @@ int close(int fd)
         CPLLockHolderD(&hLock, LOCK_RECURSIVE_MUTEX);
         assert( oMapfdToVSIDIR.find(fd) == oMapfdToVSIDIR.end() );
 
+        // cppcheck-suppress redundantIfRemove
         if( oMapDirFdToName.find(fd) != oMapDirFdToName.end())
         {
             oMapDirFdToName.erase(fd);
@@ -1051,7 +1088,7 @@ int close(int fd)
                 DEBUG_VSIPRELOAD_COND = 1;
         }
     }
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "close(fd=%d)\n", fd);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "close(fd=%d)\n", fd);
     if( fpVSIL != NULL )
     {
         VSIFCloseL(fpVSIL);
@@ -1071,30 +1108,34 @@ int close(int fd)
 /*                              read()                                  */
 /************************************************************************/
 
-ssize_t read(int fd, void *buf, size_t count)
+ssize_t read( int fd, void *buf, size_t count )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "read(fd=%d, count=%d)\n", fd, (int)count);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "read(fd=%d, count=%d)\n",
+                fd, static_cast<int>(count));
     ssize_t ret = 0;
     if( fpVSIL != NULL )
         ret = VSIFReadL(buf, 1, count, fpVSIL);
     else
         ret = pfnread(fd, buf, count);
-    if (DEBUG_VSIPRELOAD_COND && DEBUG_OUTPUT_READ && ret < 40)
+    if( DEBUG_VSIPRELOAD_COND && DEBUG_OUTPUT_READ && ret < 40 )
     {
         fprintf(stderr, "read() : ");
-        for(int i=0;i<ret;i++)
+        for( int i = 0; i < ret; i++ )
         {
-            if( ((unsigned char*)buf)[i] >= 'A' && ((unsigned char*)buf)[i] <= 'Z' )
+            if( ((unsigned char*)buf)[i] >= 'A' &&
+                ((unsigned char*)buf)[i] <= 'Z' )
                 fprintf(stderr, "%c ", ((unsigned char*)buf)[i]);
             else
                 fprintf(stderr, "\\%02X ", ((unsigned char*)buf)[i]);
         }
         fprintf(stderr, "\n");
     }
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "read() -> %d\n", (int)ret);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "read() -> %d\n", static_cast<int>(ret));
     return ret;
 }
 
@@ -1102,12 +1143,14 @@ ssize_t read(int fd, void *buf, size_t count)
 /*                              write()                                 */
 /************************************************************************/
 
-ssize_t write(int fd, const void *buf, size_t count)
+ssize_t write( int fd, const void *buf, size_t count )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "write(fd=%d, count=%d)\n", fd, (int)count);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "write(fd=%d, count=%d)\n",
+                fd, static_cast<int>(count));
     if( fpVSIL != NULL )
         return VSIFWriteL(buf, 1, count, fpVSIL);
     else
@@ -1118,12 +1161,12 @@ ssize_t write(int fd, const void *buf, size_t count)
 /*                              fsync()                                 */
 /************************************************************************/
 
-int fsync(int fd)
+int fsync( int fd )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fsync(fd=%d)\n", fd);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fsync(fd=%d)\n", fd);
     if( fpVSIL != NULL )
         return 0;
     else
@@ -1134,12 +1177,12 @@ int fsync(int fd)
 /*                           fdatasync()                                */
 /************************************************************************/
 
-int fdatasync(int fd)
+int fdatasync( int fd )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fdatasync(fd=%d)\n", fd);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fdatasync(fd=%d)\n", fd);
     if( fpVSIL != NULL )
         return 0;
     else
@@ -1150,7 +1193,7 @@ int fdatasync(int fd)
 /*                            __fxstat()                                */
 /************************************************************************/
 
-int __fxstat (int ver, int fd, struct stat *buf)
+int __fxstat( int ver, int fd, struct stat *buf )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(fd);
@@ -1165,19 +1208,21 @@ int __fxstat (int ver, int fd, struct stat *buf)
                 DEBUG_VSIPRELOAD_COND = 1;
         }
     }
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstat(fd=%d)\n", fd);
-    if( name.size() )
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__fxstat(fd=%d)\n", fd);
+    if( !name.empty() )
     {
         VSIStatBufL sStatBufL;
-        if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstat(%s)\n", name.c_str());
+        if( DEBUG_VSIPRELOAD_COND )
+            fprintf(stderr, "__fxstat(%s)\n", name.c_str());
         int ret = VSIStatL(name.c_str(), &sStatBufL);
-        sStatBufL.st_ino = (int)CPLHashSetHashStr(name.c_str());
+        sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(name.c_str()));
         if( ret == 0 )
         {
             copyVSIStatBufLToBuf(&sStatBufL, buf);
-            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-                "__fxstat ret = 0, mode = %d, size = %d\n",
-                sStatBufL.st_mode, (int)sStatBufL.st_size);
+            if( DEBUG_VSIPRELOAD_COND )
+                fprintf(stderr,
+                        "__fxstat ret = 0, mode = %d, size = %d\n",
+                        sStatBufL.st_mode, static_cast<int>(sStatBufL.st_size));
         }
         return ret;
     }
@@ -1189,13 +1234,14 @@ int __fxstat (int ver, int fd, struct stat *buf)
             name = oMapVSIToString[fpVSIL];
         }
         int ret = VSIStatL(name.c_str(), &sStatBufL);
-        sStatBufL.st_ino = (int)CPLHashSetHashStr(name.c_str());
+        sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(name.c_str()));
         if( ret == 0 )
         {
             copyVSIStatBufLToBuf(&sStatBufL, buf);
-            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-                "__fxstat ret = 0, mode = %d, size = %d\n",
-                sStatBufL.st_mode, (int)sStatBufL.st_size);
+            if( DEBUG_VSIPRELOAD_COND )
+                fprintf(stderr,
+                        "__fxstat ret = 0, mode = %d, size = %d\n",
+                        sStatBufL.st_mode, static_cast<int>(sStatBufL.st_size));
         }
         return ret;
     }
@@ -1207,12 +1253,12 @@ int __fxstat (int ver, int fd, struct stat *buf)
 /*                           __fxstat64()                               */
 /************************************************************************/
 
-int __fxstat64 (int ver, int fd, struct stat64 *buf)
+int __fxstat64( int ver, int fd, struct stat64 *buf )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstat64(fd=%d)\n", fd);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "__fxstat64(fd=%d)\n", fd);
     if( fpVSIL != NULL )
     {
         VSIStatBufL sStatBufL;
@@ -1222,13 +1268,14 @@ int __fxstat64 (int ver, int fd, struct stat64 *buf)
             name = oMapVSIToString[fpVSIL];
         }
         int ret = VSIStatL(name.c_str(), &sStatBufL);
-        sStatBufL.st_ino = (int)CPLHashSetHashStr(name.c_str());
+        sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(name.c_str()));
         if( ret == 0 )
         {
             copyVSIStatBufLToBuf64(&sStatBufL, buf);
-            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-                "__fxstat64 ret = 0, mode = %d, size = %d\n",
-                buf->st_mode, (int)buf->st_size);
+            if( DEBUG_VSIPRELOAD_COND )
+                fprintf(stderr,
+                        "__fxstat64 ret = 0, mode = %d, size = %d\n",
+                        buf->st_mode, static_cast<int>(buf->st_size));
         }
         return ret;
     }
@@ -1241,28 +1288,31 @@ int __fxstat64 (int ver, int fd, struct stat64 *buf)
 /************************************************************************/
 
 #ifdef HAVE_FSTATAT
-int __fxstatat (int ver, int dirfd, const char *pathname, struct stat *buf,
-                int flags)
+int __fxstatat( int ver, int dirfd, const char *pathname, struct stat *buf,
+                int flags )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(pathname);
-    if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 )
+    if( DEBUG_VSIPRELOAD && !osCurDir.empty() )
         DEBUG_VSIPRELOAD_COND = 1;
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "__fxstatat(dirfd=%d,pathname=%s,flags=%d)\n", dirfd, pathname, flags);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "__fxstatat(dirfd=%d,pathname=%s,flags=%d)\n",
+                dirfd, pathname, flags);
 
-    if( osCurDir.size() != 0 || STARTS_WITH(pathname, "/vsi") )
+    if( !osCurDir.empty() || STARTS_WITH(pathname, "/vsi") )
     {
         VSIStatBufL sStatBufL;
-        if( osCurDir.size() && dirfd == AT_FDCWD && pathname[0] != '/' )
+        if( !osCurDir.empty() && dirfd == AT_FDCWD && pathname[0] != '/' )
             pathname = CPLFormFilename(osCurDir.c_str(), pathname, NULL);
         const int ret = VSIStatL(pathname, &sStatBufL);
-        sStatBufL.st_ino = (int)CPLHashSetHashStr(pathname);
+        sStatBufL.st_ino = static_cast<int>(CPLHashSetHashStr(pathname));
         if( ret == 0 )
         {
             copyVSIStatBufLToBuf(&sStatBufL, buf);
-            if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-                "__fxstatat(%s) ret = 0, mode = %d, size = %d\n",
-                pathname, buf->st_mode, (int)buf->st_size);
+            if( DEBUG_VSIPRELOAD_COND )
+                fprintf(stderr,
+                        "__fxstatat(%s) ret = 0, mode = %d, size = %d\n",
+                        pathname, buf->st_mode, static_cast<int>(buf->st_size));
         }
         return ret;
     }
@@ -1275,14 +1325,16 @@ int __fxstatat (int ver, int dirfd, const char *pathname, struct stat *buf,
 /*                              lseek()                                 */
 /************************************************************************/
 
-off_t lseek(int fd, off_t off, int whence)
+off_t lseek( int fd, off_t off, int whence )
 {
     myinit();
     off_t ret;
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-        "lseek(fd=%d, off=%d, whence=%d)\n", fd, (int)off, whence);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr,
+                "lseek(fd=%d, off=%d, whence=%d)\n",
+                fd, static_cast<int>(off), whence);
     if( fpVSIL != NULL )
     {
         VSIFSeekLHelper(fpVSIL, off, whence);
@@ -1290,7 +1342,8 @@ off_t lseek(int fd, off_t off, int whence)
     }
     else
         ret = pfnlseek(fd, off, whence);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "lseek() -> ret = %d\n", (int)ret);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "lseek() -> ret = %d\n", static_cast<int>(ret));
     return ret;
 }
 
@@ -1298,14 +1351,16 @@ off_t lseek(int fd, off_t off, int whence)
 /*                             lseek64()                                */
 /************************************************************************/
 
-off64_t lseek64(int fd, off64_t off, int whence)
+off64_t lseek64( int fd, off64_t off, int whence )
 {
     myinit();
     off_t ret;
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-        "lseek64(fd=%d, off=%d, whence=%d)\n", fd, (int)off, whence);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr,
+                "lseek64(fd=%d, off=%d, whence=%d)\n",
+                fd, static_cast<int>(off), whence);
     if( fpVSIL != NULL )
     {
         VSIFSeekLHelper(fpVSIL, off, whence);
@@ -1313,8 +1368,9 @@ off64_t lseek64(int fd, off64_t off, int whence)
     }
     else
         ret = pfnlseek64(fd, off, whence);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr,
-        "lseek64() -> ret = %d\n", (int)ret);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr,
+                "lseek64() -> ret = %d\n", static_cast<int>(ret));
     return ret;
 }
 
@@ -1322,11 +1378,11 @@ off64_t lseek64(int fd, off64_t off, int whence)
 /*                            truncate()                                */
 /************************************************************************/
 
-int truncate(const char *path, off_t length)
+int truncate( const char *path, off_t length )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "truncate(%s)\n", path);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "truncate(%s)\n", path);
 
     int ret = 0;
     if( STARTS_WITH(path, "/vsi") )
@@ -1349,12 +1405,12 @@ int truncate(const char *path, off_t length)
 /*                           ftruncate()                                */
 /************************************************************************/
 
-int ftruncate(int fd, off_t length)
+int ftruncate( int fd, off_t length )
 {
     myinit();
     VSILFILE* fpVSIL = getVSILFILE(fd);
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(fpVSIL);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "ftruncate(fd=%d)\n", fd);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "ftruncate(fd=%d)\n", fd);
     int ret = 0;
     if( fpVSIL != NULL )
     {
@@ -1369,19 +1425,19 @@ int ftruncate(int fd, off_t length)
 /*                             opendir()                                */
 /************************************************************************/
 
-DIR *opendir(const char *name)
+DIR *opendir( const char *name )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(name);
-    if( DEBUG_VSIPRELOAD && osCurDir.size() != 0 )
+    if( DEBUG_VSIPRELOAD && !osCurDir.empty() )
         DEBUG_VSIPRELOAD_COND = 1;
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "opendir(%s)\n", name);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "opendir(%s)\n", name);
 
     DIR * ret;
-    if( osCurDir.size() != 0 || STARTS_WITH(name, "/vsi") )
+    if( !osCurDir.empty() || STARTS_WITH(name, "/vsi") )
     {
         char** papszDir;
-        if( osCurDir.size() != 0 && name[0] != '/' )
+        if( !osCurDir.empty() && name[0] != '/' )
             name = CPLFormFilename(osCurDir.c_str(), name, NULL);
         papszDir = VSIReadDir(name);
         if( papszDir == NULL )
@@ -1389,7 +1445,7 @@ DIR *opendir(const char *name)
             VSIStatBufL sStatBufL;
             if( VSIStatL(name, &sStatBufL) == 0 && S_ISDIR(sStatBufL.st_mode) )
             {
-                papszDir = (char**) CPLMalloc(sizeof(char*));
+                papszDir = static_cast<char **>(CPLMalloc(sizeof(char*)));
                 papszDir[0] = NULL;
             }
         }
@@ -1397,7 +1453,7 @@ DIR *opendir(const char *name)
             ret = NULL;
         else
         {
-            VSIDIR* mydir = (VSIDIR*)malloc(sizeof(VSIDIR));
+            VSIDIR* mydir = static_cast<VSIDIR *>(malloc(sizeof(VSIDIR)));
             mydir->pszDirname = CPLStrdup(name);
             mydir->papszDir = papszDir;
             mydir->nIter = 0;
@@ -1408,8 +1464,11 @@ DIR *opendir(const char *name)
         }
     }
     else
+    {
         ret = pfnopendir(name);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "opendir(%s) -> %p\n", name, ret);
+    }
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "opendir(%s) -> %p\n", name, ret);
     return ret;
 }
 
@@ -1417,7 +1476,7 @@ DIR *opendir(const char *name)
 /*                             filldir()                                */
 /************************************************************************/
 
-static bool filldir(VSIDIR* mydir)
+static bool filldir( VSIDIR* mydir )
 {
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(mydir);
     char* pszName = mydir->papszDir[mydir->nIter++];
@@ -1427,7 +1486,7 @@ static bool filldir(VSIDIR* mydir)
     mydir->ent.d_off = 0;
     mydir->ent.d_reclen = sizeof(mydir->ent);
     VSIStatBufL sStatBufL;
-    VSIStatL(CPLFormFilename(mydir->pszDirname, pszName, NULL), &sStatBufL);
+    CPL_IGNORE_RET_VAL(VSIStatL(CPLFormFilename(mydir->pszDirname, pszName, NULL), &sStatBufL));
     if( DEBUG_VSIPRELOAD_COND && S_ISDIR(sStatBufL.st_mode) )
         fprintf(stderr, "%s is dir\n", pszName);
     mydir->ent.d_type = S_ISDIR(sStatBufL.st_mode) ? DT_DIR :
@@ -1450,11 +1509,11 @@ static bool filldir(VSIDIR* mydir)
 /*                             readdir()                                */
 /************************************************************************/
 
-struct dirent *readdir(DIR *dirp)
+struct dirent *readdir( DIR *dirp )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "readdir(%p)\n", dirp);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "readdir(%p)\n", dirp);
     if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
     {
         VSIDIR* mydir = (VSIDIR*)dirp;
@@ -1471,11 +1530,11 @@ struct dirent *readdir(DIR *dirp)
 /*                             readdir64()                              */
 /************************************************************************/
 
-struct dirent64 *readdir64(DIR *dirp)
+struct dirent64 *readdir64( DIR *dirp )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "readdir64(%p)\n", dirp);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "readdir64(%p)\n", dirp);
     if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
     {
         VSIDIR* mydir = (VSIDIR*)dirp;
@@ -1492,11 +1551,11 @@ struct dirent64 *readdir64(DIR *dirp)
 /*                             closedir()                               */
 /************************************************************************/
 
-int closedir(DIR *dirp)
+int closedir( DIR *dirp )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "closedir(%p)\n", dirp);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "closedir(%p)\n", dirp);
     if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
     {
         VSIDIR* mydir = (VSIDIR*)dirp;
@@ -1520,11 +1579,11 @@ int closedir(DIR *dirp)
 /*                               dirfd()                                */
 /************************************************************************/
 
-int dirfd(DIR *dirp)
+int dirfd( DIR *dirp )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND((VSIDIR*)dirp);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "dirfd(%p)\n", dirp);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "dirfd(%p)\n", dirp);
     int ret = 0;
     if( oSetVSIDIR.find((VSIDIR*)dirp) != oSetVSIDIR.end() )
     {
@@ -1539,7 +1598,7 @@ int dirfd(DIR *dirp)
     }
     else
         ret = pfndirfd(dirp);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "dirfd(%p) -> %d\n", dirp, ret);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "dirfd(%p) -> %d\n", dirp, ret);
     return ret;
 }
 
@@ -1547,7 +1606,7 @@ int dirfd(DIR *dirp)
 /*                              fchdir()                                */
 /************************************************************************/
 
-int fchdir(int fd)
+int fchdir( int fd )
 {
     VSIDIR* mydir = NULL;
     {
@@ -1566,23 +1625,26 @@ int fchdir(int fd)
                 DEBUG_VSIPRELOAD_COND = 1;
         }
     }
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d)\n", fd);
-    if( name.size() )
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "fchdir(%d)\n", fd);
+    if( !name.empty() )
     {
         osCurDir = name;
-        if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
+        if( DEBUG_VSIPRELOAD_COND )
+            fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
         return 0;
     }
     else if( mydir != NULL )
     {
         osCurDir = mydir->pszDirname;
-        if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
+        if( DEBUG_VSIPRELOAD_COND )
+            fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
         return 0;
     }
     else
     {
         osCurDir = "";
-        if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
+        if( DEBUG_VSIPRELOAD_COND )
+            fprintf(stderr, "fchdir(%d) -> %s\n", fd, osCurDir.c_str());
         return pfnfchdir(fd);
     }
 }
@@ -1595,18 +1657,20 @@ int fchdir(int fd)
 extern "C" int acl_extended_file(const char *name);
 DECLARE_SYMBOL(acl_extended_file, int, (const char *name));
 
-int acl_extended_file(const char *path)
+int acl_extended_file( const char *path )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "acl_extended_file(%s)\n", path);
+    if( DEBUG_VSIPRELOAD_COND )
+        fprintf(stderr, "acl_extended_file(%s)\n", path);
     int ret = 0;
     if( STARTS_WITH(path, "/vsi") )
         ret = -1;
     else
     {
         if( pfnacl_extended_file == NULL )
-            pfnacl_extended_file = (fnacl_extended_fileType) dlsym(RTLD_NEXT, "acl_extended_file");
+            pfnacl_extended_file =
+                (fnacl_extended_fileType) dlsym(RTLD_NEXT, "acl_extended_file");
         if( pfnacl_extended_file == NULL )
             ret = -1;
         else
@@ -1623,11 +1687,11 @@ int acl_extended_file(const char *path)
 extern "C" int getfilecon(const char *name, void* con);
 DECLARE_SYMBOL(getfilecon, int, (const char *name, void* con));
 
-int getfilecon(const char *path, /*security_context_t **/ void* con)
+int getfilecon( const char *path, /*security_context_t **/ void* con )
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "getfilecon(%s)\n", path);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "getfilecon(%s)\n", path);
     int ret = 0;
     if( STARTS_WITH(path, "/vsi") )
     {
@@ -1658,7 +1722,7 @@ int lgetfilecon(const char *path, /*security_context_t **/ void* con)
 {
     myinit();
     int DEBUG_VSIPRELOAD_COND = GET_DEBUG_VSIPRELOAD_COND(path);
-    if (DEBUG_VSIPRELOAD_COND) fprintf(stderr, "lgetfilecon(%s)\n", path);
+    if( DEBUG_VSIPRELOAD_COND ) fprintf(stderr, "lgetfilecon(%s)\n", path);
     int ret = 0;
     if( STARTS_WITH(path, "/vsi") )
     {
@@ -1668,7 +1732,8 @@ int lgetfilecon(const char *path, /*security_context_t **/ void* con)
     else
     {
         if( pfnlgetfilecon == NULL )
-            pfnlgetfilecon = (fnlgetfileconType) dlsym(RTLD_NEXT, "lgetfilecon");
+            pfnlgetfilecon =
+                (fnlgetfileconType) dlsym(RTLD_NEXT, "lgetfilecon");
         if( pfnlgetfilecon == NULL )
             ret = -1;
         else
diff --git a/port/xmlreformat.cpp b/port/xmlreformat.cpp
index 96b8fc3..715482a 100644
--- a/port/xmlreformat.cpp
+++ b/port/xmlreformat.cpp
@@ -1,5 +1,4 @@
 /**********************************************************************
- * $Id: xmlreformat.cpp 33646 2016-03-05 15:54:03Z goatbar $
  *
  * Project:  CPL - Common Portability Library
  * Purpose:  XML Reformatting - mostly for testing minixml implementation.
@@ -30,17 +29,22 @@
 #include "cpl_minixml.h"
 #include "cpl_conv.h"
 
+CPL_CVSID("$Id: xmlreformat.cpp 36907 2016-12-16 17:16:35Z goatbar $");
+
 int main( int argc, char **argv )
 
 {
-    static char  szXML[20000000];
-    FILE       *fp;
+    // TODO(schwehr): Switch to using std::string.
+    static char szXML[20000000] = {};
+    FILE *fp = NULL;
 
     if( argc == 1 )
+    {
         fp = stdin;
+    }
     else if( argv[1][0] == '-' )
     {
-        printf( "Usage: xmlreformat [filename]\n" );
+        printf( "Usage: xmlreformat [filename]\n" );/*ok*/
         exit( 0 );
     }
     else
@@ -48,16 +52,17 @@ int main( int argc, char **argv )
         fp = fopen( argv[1], "rt" );
         if( fp == NULL )
         {
-            printf( "Failed to open file %s.\n", argv[1] );
+            printf( "Failed to open file %s.\n", argv[1] );/*ok*/
             exit( 1 );
         }
     }
 
-    int nLen = fread( szXML, 1, sizeof(szXML), fp );
-    if( nLen >= (int) sizeof(szXML)-2 ) {
+    const int nLen = static_cast<int>(fread(szXML, 1, sizeof(szXML), fp));
+    if( nLen >= static_cast<int>(sizeof(szXML)) - 2 )
+    {
         fprintf( stderr,
                  "xmlreformat fixed sized buffer (%d bytes) exceeded.\n",
-                 (int) sizeof(szXML) );
+                 static_cast<int>(sizeof(szXML)) );
         exit(1);
     }
 
@@ -70,7 +75,7 @@ int main( int argc, char **argv )
     if( poTree != NULL )
     {
         char *pszRawXML = CPLSerializeXMLTree( poTree );
-        printf( "%s", pszRawXML );
+        printf( "%s", pszRawXML );/*ok*/
         CPLFree( pszRawXML );
         CPLDestroyXMLNode( poTree );
     }
diff --git a/scripts/clang-format b/scripts/clang-format
new file mode 100644
index 0000000..8bcce74
--- /dev/null
+++ b/scripts/clang-format
@@ -0,0 +1,67 @@
+---
+Language:        Cpp
+# BasedOnStyle:  LLVM
+AccessModifierOffset: -2
+AlignAfterOpenBracket: true
+AlignConsecutiveAssignments: false
+AlignEscapedNewlinesLeft: false
+AlignOperands:   true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: true
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: None
+AlwaysBreakBeforeMultilineStrings: false
+AlwaysBreakTemplateDeclarations: false
+BinPackArguments: true
+BinPackParameters: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Allman
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+ColumnLimit:     80
+CommentPragmas:  '^ IWYU pragma:'
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat:   false
+ExperimentalAutoDetectBinPacking: false
+ForEachMacros:   [ foreach, Q_FOREACH, BOOST_FOREACH ]
+IndentCaseLabels: false
+IndentWidth:     4
+IndentWrappedFunctionNames: false
+KeepEmptyLinesAtTheStartOfBlocks: true
+MacroBlockBegin: ''
+MacroBlockEnd:   ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PenaltyBreakBeforeFirstCallParameter: 19
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 60
+PointerAlignment: Right
+SpaceAfterCStyleCast: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: Never
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 2
+SpacesInAngles:  false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard:        Cpp11
+TabWidth:        4
+UseTab:          Never
+...
+
diff --git a/scripts/completionFinder.py b/scripts/completionFinder.py
index 3368588..5b2e204 100644
--- a/scripts/completionFinder.py
+++ b/scripts/completionFinder.py
@@ -36,7 +36,7 @@ from subprocess import call, Popen, PIPE, STDOUT
 
 def showHelp():
   print "Usage : completionFinder.py  output_script"
-  
+
 
 def processLine(line):
   outList = []
@@ -50,7 +50,7 @@ def processLine(line):
   lvl4 = []
   for item in lvl3:
     lvl4 += item.split('|')
-  
+
   for item in lvl4:
     if len(item) >= 2:
       if item[0] == '-':
@@ -63,7 +63,7 @@ def processLine(line):
             outList.append(pair[0]+"="+c)
         else:
           outList.append(key)
-  
+
   return outList
 
 def processTool(toolName):
@@ -73,21 +73,21 @@ def processTool(toolName):
   result = process.communicate()[0]
   lines = result.split('\n')
   index = 0
-  
+
   while index < len(lines):
     if (lines[index].find("Usage:") >= 0):
       break
     index += 1
-  
+
   options = []
-  
+
   while index < len(lines):
     cleanLine = lines[index].strip('\t\r ')
     if (len(cleanLine) == 0):
       break;
     options += processLine(cleanLine)
     index += 1
-  
+
   return options
 
 def parseGDALGeneralOptions():
@@ -143,13 +143,13 @@ def getCompletionScript(name,optList):
   output.append("      return 0\n")
   output.append("      ;;\n")
   output.append("  esac\n")
-  
+
   # adapt format parsing command : GDAL type of OGR type
-  
+
   isGdal = True
   if (name.find("ogr") == 0):
     isGdal = False
-    
+
   # gdal type
   if isGdal:
     formatParsingCmd = "$tool --formats | tail -n +2 | cut -f 3 -d ' '"
@@ -176,7 +176,7 @@ def getCompletionScript(name,optList):
     # ogr type
     formatParsingCmd = "$tool --formats | tail -n +2 | grep -o -E '\"[^\"]+\"' | sed 's/\ /__/'"
     if ("-f" in optList):
-      # replace ogrtindex by ogr2ogr to check --formats 
+      # replace ogrtindex by ogr2ogr to check --formats
       output.append("  tool=${COMP_WORDS[0]/ogrtindex/ogr2ogr}\n")
       output.append("  case \"$prev\" in\n")
       if ("-f" in optList) and not isGdal:
@@ -190,18 +190,18 @@ def getCompletionScript(name,optList):
         output.append("      done\n")
         output.append("      ;;\n")
       output.append("  esac\n")
-  
+
   output.append("  return 0\n")
   output.append("}\n")
   output.append("complete -o default -F _"+name+" "+name+"\n")
-  
+
   return output
 
 def main(argv):
   if len(argv) < 2 :
     showHelp()
     return 1
-  
+
   gdaltools = [ "gdal2tiles.py",\
                 "gdal2xyz.py",\
                 "gdaladdo",\
@@ -235,16 +235,17 @@ def main(argv):
                 "gdaltransform",\
                 "gdal_translate",\
                 "gdalwarp"]
-  
+
   ogrtools = [ "ogr2ogr",\
                "ogrinfo",\
                "ogrlineref",\
-               "ogrtindex"]
-  
+               "ogrtindex",
+               "ogrmerge.py"]
+
   # parse general options
   generalOptions = parseGDALGeneralOptions()
   generalOGROptions = parseOGRGeneralOptions()
-  
+
   outFile = argv[1]
   of = open(outFile,'w')
   of.write("# File auto-generated by completionFinder.py, do not modify manually\n")
@@ -277,7 +278,7 @@ function_exists _get_comp_words_by_ref || return 0
         if not item in optList:
           optList.append(item)
     of.writelines(getCompletionScript(name,optList))
-  
+
   of.close()
   return 0
 
diff --git a/scripts/cppcheck.sh b/scripts/cppcheck.sh
new file mode 100755
index 0000000..6c25019
--- /dev/null
+++ b/scripts/cppcheck.sh
@@ -0,0 +1,489 @@
+#!/bin/bash
+# Note: tested with cppcheck 1.72 as shipped with Ubuntu 16.04
+# as well as with cppcheck 1.76.1
+
+LOG_FILE=/tmp/cppcheck_gdal.txt
+
+echo "" > ${LOG_FILE}
+for dirname in alg port gcore ogr frmts gnm apps; do
+    echo "Running cppcheck on $dirname... (can be long)"
+    cppcheck --inline-suppr --template='{file}:{line},{severity},{id},{message}' \
+        --enable=all --inconclusive --std=posix -UAFL_FRIENDLY -UANDROID \
+        -UCOMPAT_WITH_ICC_CONVERSION_CHECK -DDEBUG -UDEBUG_BOOL -DHAVE_CXX11=1 \
+        -DGBool=int -DCPL_HAS_GINT64=1 -DHAVE_GEOS -DHAVE_EXPAT -DHAVE_XERCES -DCOMPILATION_ALLOWED \
+        -DHAVE_SFCGAL -DHAVE_SPATIALITE -DSPATIALITE_412_OR_LATER \
+        -DHAVE_SQLITE -DSQLITE_VERSION_NUMBER=3006000 -DHAVE_SQLITE_VFS \
+        -DPTHREAD_MUTEX_RECURSIVE -DCPU_LITTLE_ENDIAN -DCPL_IS_LSB=1 \
+        -DKDU_MAJOR_VERSION=7 -DKDU_MINOR_VERSION=5 \
+        -DHAVE_JASPER_UUID \
+        -D__GNUC__==5 -DGDAL_COMPILATION \
+        -DODBCVER=0x0300 \
+        -DNETCDF_HAS_NC4 \
+        -UGDAL_NO_AUTOLOAD \
+        -DHAVE_MITAB \
+        -Dva_copy=va_start \
+        -D__cplusplus \
+        -DVSIRealloc=realloc \
+        -DCPPCHECK \
+        -DDEBUG_MUTEX \
+        -DDEBUG_PROXY_POOL \
+        -Doverride= \
+        --include=port/cpl_config.h \
+        --include=port/cpl_port.h \
+        -I port -I gcore -I ogr -I ogr/ogrsf_frmts \
+        -i ogrdissolve.cpp \
+        -i gdalasyncread.cpp \
+        -i gdaltorture.cpp \
+        $dirname \
+        -j 8 >>${LOG_FILE} 2>&1
+    if [[ $? -ne 0 ]] ; then
+        echo "cppcheck failed"
+        exit 1
+    fi
+done
+
+ret_code=0
+
+cat ${LOG_FILE} | grep -v "unmatchedSuppression" | grep -v " yacc.c" | grep -v PublicDecompWT | grep -v "kdu_cache_wrapper.h"  > ${LOG_FILE}.tmp
+mv ${LOG_FILE}.tmp ${LOG_FILE}
+
+grep "null pointer" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "Null pointer check failed"
+    ret_code=1
+fi
+
+grep "duplicateBreak" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "duplicateBreak check failed"
+    ret_code=1
+fi
+
+grep "duplicateBranch" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "duplicateBranch check failed"
+    ret_code=1
+fi
+
+grep "uninitMemberVar" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "uninitMemberVar check failed"
+    ret_code=1
+fi
+
+grep "useInitializationList" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "uninitMemberVar check failed"
+    ret_code=1
+fi
+
+grep "clarifyCalculation" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "clarifyCalculation check failed"
+    ret_code=1
+fi
+
+grep "invalidPrintfArgType_uint" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "invalidPrintfArgType_uint check failed"
+    ret_code=1
+fi
+
+grep "catchExceptionByValue" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "catchExceptionByValue check failed"
+    ret_code=1
+fi
+
+grep "memleakOnRealloc" ${LOG_FILE} | grep frmts/hdf4/hdf-eos > /dev/null && echo "memleakOnRealloc issues in frmts/hdf4/hdf-eos ignored"
+grep "memleakOnRealloc" ${LOG_FILE} | grep frmts/grib/degrib18 > /dev/null && echo "memleakOnRealloc issues in frmts/grib/degrib18 ignored"
+grep "memleakOnRealloc" ${LOG_FILE} | grep -v frmts/hdf4/hdf-eos | grep -v frmts/grib/degrib18
+if [[ $? -eq 0 ]] ; then
+    echo "memleakOnRealloc check failed"
+    ret_code=1
+fi
+
+# Those warnings in libjpeg seems to be false positives
+#grep "arrayIndexOutOfBoundsCond" ${LOG_FILE} | grep frmts/jpeg/libjpeg > /dev/null && echo "arrayIndexOutOfBoundsCond issues in frmts/jpeg/libjpeg ignored"
+grep "arrayIndexOutOfBoundsCond" ${LOG_FILE} | grep -v frmts/jpeg/libjpeg
+if [[ $? -eq 0 ]] ; then
+    echo "arrayIndexOutOfBoundsCond check failed"
+    ret_code=1
+fi
+
+grep "arrayIndexOutOfBounds," ${LOG_FILE} | grep frmts/hdf4/hdf-eos > /dev/null && echo "arrayIndexOutOfBounds issues in frmts/hdf4/hdf-eos ignored"
+grep "arrayIndexOutOfBounds," ${LOG_FILE} | grep -v frmts/hdf4/hdf-eos
+if [[ $? -eq 0 ]] ; then
+    echo "arrayIndexOutOfBounds check failed"
+    ret_code=1
+fi
+
+grep "syntaxError" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "syntaxError check failed"
+    ret_code=1
+fi
+
+grep "memleak," ${LOG_FILE} | grep frmts/hdf4/hdf-eos > /dev/null && echo "memleak issues in frmts/hdf4/hdf-eos ignored"
+grep "memleak," ${LOG_FILE} | grep frmts/grib/degrib18 > /dev/null && echo "memleak issues in frmts/grib/degrib18 ignored"
+grep "memleak," ${LOG_FILE} | grep -v frmts/hdf4/hdf-eos | grep -v frmts/grib/degrib18
+if [[ $? -eq 0 ]] ; then
+    echo "memleak check failed"
+    ret_code=1
+fi
+
+grep "eraseDereference" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "eraseDereference check failed"
+    ret_code=1
+fi
+
+grep "memsetClass," ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "memsetClass check failed"
+    ret_code=1
+fi
+
+# Most if not all of them are false positives
+grep "uninitvar," ${LOG_FILE} | grep frmts/hdf4/hdf-eos > /dev/null && echo "(potential) uninitvar issues in frmts/hdf4/hdf-eos ignored"
+grep "uninitvar," ${LOG_FILE} | grep frmts/grib/degrib18 > /dev/null && echo "(potential) uninitvar issues in frmts/grib/degrib18 ignored"
+grep "uninitvar," ${LOG_FILE} | grep frmts/gtiff/libtiff > /dev/null && echo "(potential) uninitvar issues in frmts/gtiff/libtiff ignored"
+grep "uninitvar," ${LOG_FILE} | grep frmts/gtiff/libgeotiff > /dev/null && echo "(potential) uninitvar issues in frmts/gtiff/libgeotiff ignored"
+grep "uninitvar," ${LOG_FILE} | grep frmts/jpeg/libjpeg > /dev/null && echo "(potential) uninitvar issues in frmts/jpeg/libjpeg ignored"
+grep "uninitvar," ${LOG_FILE} | grep frmts/gif/giflib > /dev/null && echo "(potential) uninitvar issues in frmts/gif/giflib ignored"
+grep "uninitvar," ${LOG_FILE} | grep frmts/png/libpng > /dev/null && echo "(potential) uninitvar issues in frmts/png/libpng ignored"
+grep "uninitvar," ${LOG_FILE} | grep frmts/zlib > /dev/null && echo "(potential) uninitvar issues in frmts/zlib ignored"
+grep "uninitvar," ${LOG_FILE} | grep ogr/ogrsf_frmts/geojson/libjson > /dev/null && echo "(potential) uninitvar issues in ogr/ogrsf_frmts/geojson/libjson ignored"
+
+grep "uninitvar," ${LOG_FILE} | grep -v frmts/hdf4/hdf-eos | \
+                                grep -v frmts/grib/degrib18 | \
+                                grep -v frmts/gtiff/libtiff | \
+                                grep -v frmts/gtiff/libgeotiff | \
+                                grep -v frmts/jpeg/libjpeg | \
+                                grep -v frmts/gif/giflib | \
+                                grep -v frmts/png/libpng | \
+                                grep -v frmts/zlib | \
+                                grep -v ogr/ogrsf_frmts/geojson/libjson | \
+                                grep -v osr_cs_wkt_parser.c
+if [[ $? -eq 0 ]] ; then
+    echo "uninitvar check failed"
+    ret_code=1
+fi
+
+grep "uninitdata," ${LOG_FILE} | grep "frmts/grib/degrib18/g2clib-1.0.4" > /dev/null && echo "(potential) uninitdata issues in frmts/grib/degrib18/g2clib-1.0.4 ignored"
+
+grep "uninitdata," ${LOG_FILE} | grep -v "frmts/grib/degrib18/g2clib-1.0.4"
+if [[ $? -eq 0 ]] ; then
+    echo "uninitdata check failed"
+    ret_code=1
+fi
+
+grep "va_list_usedBeforeStarted" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "va_list_usedBeforeStarted check failed"
+    ret_code=1
+fi
+
+grep "duplInheritedMember" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "duplInheritedMember check failed"
+    ret_code=1
+fi
+
+grep "terminateStrncpy" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "terminateStrncpy check failed"
+    ret_code=1
+fi
+
+grep "operatorEqVarError" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "operatorEqVarError check failed"
+    ret_code=1
+fi
+
+grep "uselessAssignmentPtrArg" ${LOG_FILE} | grep -v swq_parser.cpp | grep -v osr_cs_wkt_parser.c | grep -v ods_formula_parser.cpp
+if [[ $? -eq 0 ]] ; then
+    echo "uselessAssignmentPtrArg check failed"
+    ret_code=1
+fi
+
+grep "bufferNotZeroTerminated" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "bufferNotZeroTerminated check failed"
+    ret_code=1
+fi
+
+grep "sizeofDivisionMemfunc" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "sizeofDivisionMemfunc check failed"
+    ret_code=1
+fi
+
+grep "selfAssignment" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "selfAssignment check failed"
+    ret_code=1
+fi
+
+grep "invalidPrintfArgType_sint" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "invalidPrintfArgType_sint check failed"
+    ret_code=1
+fi
+
+grep "redundantAssignInSwitch" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "redundantAssignInSwitch check failed"
+    ret_code=1
+fi
+
+grep "publicAllocationError" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "publicAllocationError check failed"
+    ret_code=1
+fi
+
+grep "invalidScanfArgType_int" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "invalidScanfArgType_int check failed"
+    ret_code=1
+fi
+
+grep "invalidscanf," ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "invalidscanf check failed"
+    ret_code=1
+fi
+
+grep "moduloAlwaysTrueFalse" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "moduloAlwaysTrueFalse check failed"
+    ret_code=1
+fi
+
+grep "charLiteralWithCharPtrCompare" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "charLiteralWithCharPtrCompare check failed"
+    ret_code=1
+fi
+
+grep "noConstructor" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "noConstructor check failed"
+    ret_code=1
+fi
+
+grep "noExplicitConstructor" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "noExplicitConstructor check failed"
+    ret_code=1
+fi
+
+grep "noCopyConstructor" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "noCopyConstructor check failed"
+    ret_code=1
+fi
+
+grep "passedByValue" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "passedByValue check failed"
+    ret_code=1
+fi
+
+grep "postfixOperator" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "postfixOperator check failed"
+    ret_code=1
+fi
+
+grep "redundantCopy" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "redundantCopy check failed"
+    ret_code=1
+fi
+
+grep "stlIfStrFind" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "stlIfStrFind check failed"
+    ret_code=1
+fi
+
+grep "functionStatic" ${LOG_FILE} | grep -v "OGRSQLiteDataSource::OpenRaster" | grep -v "OGRSQLiteDataSource::OpenRasterSubDataset"
+if [[ $? -eq 0 ]] ; then
+    echo "functionStatic check failed"
+    ret_code=1
+fi
+
+grep "knownConditionTrueFalse" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "knownConditionTrueFalse check failed"
+    ret_code=1
+fi
+
+grep "arrayIndexThenCheck" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "arrayIndexThenCheck check failed"
+    ret_code=1
+fi
+
+grep "unusedPrivateFunction" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "unusedPrivateFunction check failed"
+    ret_code=1
+fi
+
+grep "redundantCondition" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "redundantCondition check failed"
+    ret_code=1
+fi
+
+grep "unusedStructMember" ${LOG_FILE} | grep -v frmts/jpeg/libjpeg | grep -v frmts/gtiff/libtiff | grep -v frmts/zlib
+if [[ $? -eq 0 ]] ; then
+    echo "unusedStructMember check failed"
+    ret_code=1
+fi
+
+grep "multiCondition" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "multiCondition check failed"
+    ret_code=1
+fi
+
+grep "duplicateExpression" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "duplicateExpression check failed"
+    ret_code=1
+fi
+
+grep "operatorEq" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "operatorEq check failed"
+    ret_code=1
+fi
+
+grep "truncLongCastAssignment" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "truncLongCastAssignment check failed"
+    ret_code=1
+fi
+
+grep "exceptRethrowCopy" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "exceptRethrowCopy check failed"
+    ret_code=1
+fi
+
+grep "unusedVariable" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "unusedVariable check failed"
+    ret_code=1
+fi
+
+grep "unsafeClassCanLeak" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "unsafeClassCanLeak check failed"
+    ret_code=1
+fi
+
+grep "unsignedLessThanZero" ${LOG_FILE} | grep -v frmts/jpeg/libjpeg
+if [[ $? -eq 0 ]] ; then
+    echo "unsignedLessThanZero check failed"
+    ret_code=1
+fi
+
+grep "unpreciseMathCall" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "unpreciseMathCall check failed"
+    ret_code=1
+fi
+
+grep "unreachableCode" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "unreachableCode check failed"
+    ret_code=1
+fi
+
+grep "clarifyCondition" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "clarifyCondition check failed"
+    ret_code=1
+fi
+
+grep "redundantIfRemove" ${LOG_FILE}
+if [[ $? -eq 0 ]] ; then
+    echo "redundantIfRemove check failed"
+    ret_code=1
+fi
+
+grep "unassignedVariable" ${LOG_FILE} | grep -v frmts/png/libpng
+if [[ $? -eq 0 ]] ; then
+    echo "unassignedVariable check failed"
+    ret_code=1
+fi
+
+grep "redundantAssignment" ${LOG_FILE} | grep -v frmts/grib/degrib18/g2clib-1.0.4 | grep -v frmts/hdf4/hdf-eos | grep -v frmts/png/libpng
+if [[ $? -eq 0 ]] ; then
+    echo "redundantAssignment check failed"
+    ret_code=1
+fi
+
+grep "unreadVariable" ${LOG_FILE} | grep -v alg/internal_libqhull | \
+                                    grep -v frmts/gtiff/libtiff  | \
+                                    grep -v frmts/jpeg/libjpeg | \
+                                    grep -v frmts/png/libpng | \
+                                    grep -v frmts/grib/degrib18/degrib | \
+                                    grep -v frmts/hdf4/hdf-eos | \
+                                    grep -v frmts/zlib
+if [[ $? -eq 0 ]] ; then
+    echo "unreadVariable check failed"
+    ret_code=1
+fi
+
+
+for whitelisted_dir in alg/ port/; do
+    grep "cstyleCast" ${LOG_FILE} | grep $whitelisted_dir
+    if [[ $? -eq 0 ]] ; then
+        echo "cstyleCast check failed"
+        ret_code=1
+    fi
+done
+
+# Check any remaining errors
+grep "error," ${LOG_FILE} | grep -v "uninitvar" | \
+    grep -v "memleak," | grep -v "memleakOnRealloc" | \
+    grep -v "frmts/jpeg/libjpeg/jdphuff.c:493,error,shiftNegative,Shifting a negative value is undefined behaviour" | \
+    grep -v "ogr/ogrsf_frmts/avc/avc_bin.c:1866,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds" | \
+    grep -v "frmts/hdf4/hdf-eos/EHapi.c:1890,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
+    grep -v "frmts/hdf4/hdf-eos/EHapi.c:1920,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
+    grep -v "frmts/hdf4/hdf-eos/EHapi.c:1958,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
+    grep -v "frmts/hdf4/hdf-eos/EHapi.c:1994,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
+    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2056,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
+    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2118,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
+    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2159,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
+    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2208,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
+    grep -v "frmts/hdf4/hdf-eos/EHapi.c:2227,error,bufferAccessOutOfBounds,Buffer is accessed out of bounds." | \
+    grep -v "frmts/grib/degrib18/g2clib-1.0.4"
+
+if [[ $? -eq 0 ]] ; then
+    echo "Errors check failed"
+    ret_code=1
+fi
+
+# Check any remaining warnings
+grep "warning," ${LOG_FILE} | grep -v "ods_formula_parser" | \
+    grep -v "osr_cs_wkt_parser" | grep -v "swq_parser" | \
+    grep -v "frmts/jpeg/libjpeg"
+if [[ $? -eq 0 ]] ; then
+    echo "Warnings check failed"
+    ret_code=1
+fi
+
+if [ ${ret_code} = 0 ]; then
+    echo "cppcheck succeeded"
+fi
+
+exit ${ret_code}
+
diff --git a/scripts/detect_printf.sh b/scripts/detect_printf.sh
new file mode 100755
index 0000000..6090d28
--- /dev/null
+++ b/scripts/detect_printf.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+ret_code=0
+
+echo "Checking for printf() statements..."
+grep -r --include="*.c*" " printf" alg gnm port ogr gcore frmts | grep -v "/*ok" | grep -v "printf()" | grep -v "printf-like" | grep -v "printf style" | grep -v "with printf"  | grep -v "/\* printf" |  grep -v "//" | grep -v degrib | grep -v aitest | grep -v dted_test | grep -v giflib | grep -v 8211view | grep -v 8211dump | grep -v timetest | grep -v 8211createfromxml | grep -v hfatest | grep -v zlib | grep -v libtiff | grep -v envisat_dump | grep -v dumpgeo | grep -v nitfdump | grep -v  [...]
+
+if [[ $? -eq 0 ]] ; then
+    echo "FAIL: suspicious printf found. Remove or tag it with /*ok*/"
+    ret_code=1
+else
+    echo "OK: no suspicious printf found."
+fi
+
+
+echo "Checking for fprintf(stderr,) statements..."
+grep fprintf -r  alg gnm port ogr gcore frmts --include="*.cpp" | grep stderr | grep -v -G "/[/|*][ ]*fprintf" | grep -v "/*ok" | grep -v sdts2shp | grep -v degrib18  | grep -v 8211view | grep -v 8211createfromxml | grep -v 8211dump | grep -v pcidskexception | grep -v vsipreload | grep -v fprintfstderr | grep -v cpl_multiproc | grep -v "truncation occurred" | grep -v xmlreformat | grep -v cpl_error
+
+if [[ $? -eq 0 ]] ; then
+    echo "FAIL: suspicious fprintf(stder,...) found. Remove or tag it with /*ok*/"
+    ret_code=1
+else
+    echo "OK: no suspicious fprintf(stder,...) found."
+fi
+
+exit $ret_code
diff --git a/scripts/detect_self_assignment.py b/scripts/detect_self_assignment.py
new file mode 100755
index 0000000..51b1a80
--- /dev/null
+++ b/scripts/detect_self_assignment.py
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+import sys
+
+f = open(sys.argv[1], "rt")
+lines = f.readlines()
+ret = 0
+for i in range(len(lines)):
+    line = lines[i]
+    if len(line) > 0 and line[len(line)-1] == '\n':
+        line = line[0:-1]
+    tab = line.split('=')
+    if len(tab) != 2:
+        continue
+    left = tab[0].strip()
+    right = tab[1].strip()
+    if len(right) > 0 and right[len(right)-1] == ';':
+        right = right[0:-1]
+    else:
+        continue
+    right = right.strip()
+    if left == right:
+        print("%s: %d: %s" % (sys.argv[1], i+1, line))
+        ret = 1
+
+sys.exit(ret)
diff --git a/scripts/detect_self_assignment.sh b/scripts/detect_self_assignment.sh
new file mode 100755
index 0000000..6ee7237
--- /dev/null
+++ b/scripts/detect_self_assignment.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+ret_code=0
+
+# This catches a bit more than gcc -Winit-self and clang -Wself-assign (https://trac.osgeo.org/gdal/ticket/6196)
+
+echo "Checking for self assignment..."
+find alg port gcore apps ogr frmts gnm \( -name "*.cpp" -o -name "*.c" -o -name "*.h" \) -exec python scripts/detect_self_assignment.py {} \; | grep ''
+
+if [[ $? -eq 0 ]] ; then
+    echo "FAIL: check assignment detected. Please remove them!"
+    ret_code=1
+else
+    echo "OK: no self assignment found."
+fi
+
+exit $ret_code
diff --git a/scripts/detect_tabulations.sh b/scripts/detect_tabulations.sh
new file mode 100755
index 0000000..6841dfe
--- /dev/null
+++ b/scripts/detect_tabulations.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+ret_code=0
+
+echo "Checking for tabulation characters..."
+find alg gnm port ogr gcore frmts apps \( -name "*.cpp" -o -name "*.h" \) -exec sh -c "grep -P '\t' {} >/dev/null && echo {}" \; | grep -v frmts/msg/PublicDecompWT | grep -v frmts/jpeg/libjpeg | grep -v frmts/gtiff/libtiff | grep -v frmts/gtiff/libgeotiff | grep -v frmts/grib/degrib18 | grep -v ogr/ogrsf_frmts/geojson/libjson | grep -v frmts/hdf4/hdf-eos | grep -v frmts/gif/giflib | grep -v frmts/pcraster/libcsf | grep -v frmts/png/libpng
+
+if [[ $? -eq 0 ]] ; then
+    echo "FAIL: tabulations detected. Please remove them!"
+    ret_code=1
+else
+    echo "OK: no tabulations found."
+fi
+
+exit $ret_code
diff --git a/scripts/fix_container_dot_size_zero.py b/scripts/fix_container_dot_size_zero.py
new file mode 100755
index 0000000..ef3a53d
--- /dev/null
+++ b/scripts/fix_container_dot_size_zero.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+###############################################################################
+# $Id: fix_container_dot_size_zero.py 36913 2016-12-16 20:59:09Z rouault $
+#
+#  Project:  GDAL samples
+#  Purpose:  Replace container.size() by !container.empty(), and reverse
+#  Author:   Even Rouault <even.rouault at spatialys.com>
+#
+###############################################################################
+#  Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+
+import sys
+
+def find_start_identifier_pos(content, pos_start_identifier):
+    level_parenthesis = 0
+    level_bracket = 0
+    while True:
+        c  = content[pos_start_identifier]
+        if level_parenthesis > 0 and c != '(' and c != ')':
+            pos_start_identifier -= 1
+        elif c == ')':
+            level_parenthesis += 1
+            pos_start_identifier -= 1
+        elif c == '(':
+            if level_parenthesis == 0:
+                break
+            level_parenthesis -= 1
+            pos_start_identifier -= 1
+        elif level_bracket > 0 and c != '[' and c != ']':
+            pos_start_identifier -= 1
+        elif c == ']':
+            level_bracket += 1
+            pos_start_identifier -= 1
+        elif c == '[':
+            if level_bracket == 0:
+                break
+            level_bracket -= 1
+            pos_start_identifier -= 1
+        elif c.isalnum() or c == '_' or c == '.':
+            pos_start_identifier -= 1
+        elif c == '>' and content[pos_start_identifier-1] == '-':
+            pos_start_identifier -= 2
+        else:
+            break
+    pos_start_identifier += 1
+    return pos_start_identifier
+
+content = open(sys.argv[1], 'rb').read()
+pos = 0
+modified = False
+while True:
+    pos1 = content.find('.size()', pos)
+    pos2 = content.find('->size()', pos)
+    if pos1 < 0 and pos2 < 0:
+        break
+    separator = ''
+    if pos1 >= 0 and (pos1 < pos2 or pos2 < 0): 
+        pos = pos1
+        pos_after = pos + len('.size()')
+        separator = '.'
+    else:
+        pos = pos2
+        dot_variant = False
+        pos_after = pos + len('->size()')
+        separator = '->'
+
+    if content[pos_after] == ' ':
+        pos_after += 1
+    extra_space = ''
+    empty = False
+    non_empty = False
+    if content[pos_after:].startswith('== 0'):
+        empty = True
+        pos_after += len('== 0')
+    elif content[pos_after:].startswith('==0'):
+        empty = True
+        pos_after += len('==0')
+    elif content[pos_after:].startswith('!= 0'):
+        non_empty = True
+        pos_after += len('!= 0')
+    elif content[pos_after:].startswith('!=0'):
+        non_empty = True
+        pos_after += len('!=0')
+    elif content[pos_after:].startswith('> 0'):
+        non_empty = True
+        pos_after += len('> 0')
+    elif content[pos_after:].startswith('>0'):
+        non_empty = True
+        pos_after += len('>0')
+
+    if not empty and not non_empty and ( \
+            content[pos_after:].startswith(' )') or \
+            content[pos_after:].startswith(')') or \
+            content[pos_after:].startswith(' &&') or \
+            content[pos_after:].startswith(' ||') or \
+            content[pos_after:].startswith('&&') or \
+            content[pos_after:].startswith('||') or \
+            content[pos_after:].startswith(' ?') or \
+            content[pos_after:].startswith('?') ):
+        if content[pos_after] != ' ':
+            extra_space = ' '
+        pos_cur = find_start_identifier_pos(content, pos - 1)
+        pos_cur -= 1
+        while content[pos_cur] == ' ' or content[pos_cur] == '\n' or \
+              content[pos_cur] == '\t':
+            pos_cur -= 1
+        pos_cur += 1
+        if (content[pos_after:].startswith(' ?') or \
+            content[pos_after:].startswith('?')) and \
+           (content[pos_cur-1] == '(' or content[pos_cur-1] == ',') :
+            non_empty = True
+        elif content[pos_cur-3:pos_cur] == 'if(':
+            non_empty = True
+        elif content[pos_cur-4:pos_cur] == 'if (':
+            non_empty = True
+        elif content[pos_cur-2:pos_cur] == '&&':
+            non_empty = True
+        elif content[pos_cur-2:pos_cur] == '||':
+            non_empty = True
+
+
+    if empty:
+        modified = True
+        content = content[0:pos] + separator + 'empty()' + content[pos_after:]
+    elif non_empty:
+        modified = True
+        pos_start_identifier = find_start_identifier_pos(content, pos - 1)
+        content = content[0:pos_start_identifier] + '!' + \
+                  content[pos_start_identifier:pos] + separator + 'empty()' + \
+                  extra_space + content[pos_after:]
+
+    pos += 1
+
+if modified:
+    open(sys.argv[1], 'wb').write(content)
+
+#sys.stdout.write(content)
diff --git a/scripts/fix_container_dot_size_zero.sh b/scripts/fix_container_dot_size_zero.sh
new file mode 100755
index 0000000..7a30bfc
--- /dev/null
+++ b/scripts/fix_container_dot_size_zero.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+find port alg gcore gnm ogr frmts apps -name "*.c*" -exec python scripts/fix_container_dot_size_zero.py {} \;
diff --git a/scripts/fix_typos.sh b/scripts/fix_typos.sh
index 02ddc69..aeb7f74 100755
--- a/scripts/fix_typos.sh
+++ b/scripts/fix_typos.sh
@@ -43,6 +43,8 @@ if ! test -d fix_typos; then
     cat codespell/data/dictionary.txt qgis.txt debian.txt | awk 'NF' > gdal_dict.txt
     echo "difered->deferred" >> gdal_dict.txt
     echo "differed->deferred" >> gdal_dict.txt
+    cat gdal_dict.txt | grep -v 404 > gdal_dict.txt.tmp
+    mv gdal_dict.txt.tmp gdal_dict.txt
     cd ..
 fi
 
@@ -50,6 +52,8 @@ EXCLUDED_FILES="*/.svn*,configure,config.status,config.sub,*/autom4te.cache/*"
 EXCLUDED_FILES="$EXCLUDED_FILES,*/hdf-eos/*,teststream.out,ogrogdilayer.cpp"
 EXCLUDED_FILES="$EXCLUDED_FILES,*/doc/br/*,*/data/*,figures.mp,*/tmp/*,*/ruby/*"
 EXCLUDED_FILES="$EXCLUDED_FILES,*/fix_typos/*,fix_typos.sh,*.eps,geopackage_aspatial.html"
+EXCLUDED_FILES="$EXCLUDED_FILES,*/kdu_cache_wrapper.h,*/PublicDecompWT/*,*/man/*,./html/*"
+EXCLUDED_FILES="$EXCLUDED_FILES,PROVENANCE.TXT,libtool,ltmain.sh,libtool.m4,./m4/*"
 WORDS_WHITE_LIST="poSession,FIDN,TRAFIC,HTINK,repID,oCurr,INTREST,oPosition"
 WORDS_WHITE_LIST="$WORDS_WHITE_LIST,CPL_SUPRESS_CPLUSPLUS,SRP_NAM,ADRG_NAM,'SRP_NAM,AuxilaryTarget"
 # IRIS driver metadata item names: FIXME ?
@@ -60,7 +64,14 @@ WORDS_WHITE_LIST="$WORDS_WHITE_LIST,JBUF_PASS_THRU"
 WORDS_WHITE_LIST="$WORDS_WHITE_LIST,IS_WRITEABLE,E_GIF_ERR_NOT_WRITEABLE"
 # libtiff
 WORDS_WHITE_LIST="$WORDS_WHITE_LIST,THRESHHOLD_BILEVEL,THRESHHOLD_HALFTONE,THRESHHOLD_ERRORDIFFUSE"
+# mffdataset.cpp
+WORDS_WHITE_LIST="$WORDS_WHITE_LIST,oUTMorLL"
+# hf2dataset.cpp
+WORDS_WHITE_LIST="$WORDS_WHITE_LIST,fVertPres"
 
 python3 fix_typos/codespell/codespell.py -w -i 3 -q 2 -S $EXCLUDED_FILES \
     -x scripts/typos_whitelist.txt --words-white-list=$WORDS_WHITE_LIST \
-    -D fix_typos/gdal_dict.txt  ..
+    ../autotest
+python3 fix_typos/codespell/codespell.py -w -i 3 -q 2 -S $EXCLUDED_FILES \
+    -x scripts/typos_whitelist.txt --words-white-list=$WORDS_WHITE_LIST \
+    -D ./fix_typos/gdal_dict.txt  .
diff --git a/scripts/gdal-bash-completion.sh b/scripts/gdal-bash-completion.sh
index 3b9e01a..aaf973e 100644
--- a/scripts/gdal-bash-completion.sh
+++ b/scripts/gdal-bash-completion.sh
@@ -67,7 +67,7 @@ _gdalbuildvrt()
   _get_comp_words_by_ref cur prev
   case "$cur" in
     -*)
-      key_list="-tileindex -resolution -te -tr -tap -separate -b -sd -allow_projection_difference -q -addalpha -hidenodata -srcnodata -vrtnodata -a_srs -r -input_file_list -overwrite "
+      key_list="-tileindex -resolution -te -tr -tap -separate -b -sd -allow_projection_difference -q -addalpha -hidenodata -srcnodata -vrtnodata -a_srs -r -oo -input_file_list -overwrite "
       COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
       return 0
       ;;
@@ -82,7 +82,7 @@ _gdal_calc.py()
   _get_comp_words_by_ref cur prev
   case "$cur" in
     -*)
-      key_list="-A --A_band -B...-Z "
+      key_list="--calc=expression --outfile=out_filename -A --A_band=n -B...-Z "
       COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
       return 0
       ;;
@@ -172,7 +172,7 @@ _gdal_edit.py()
   _get_comp_words_by_ref cur prev
   case "$cur" in
     -*)
-      key_list="--help-general -ro -a_srs -a_ullr -tr -unsetgt -a_nodata -unsetnodata -unsetstats -stats -approx_stats -gcp -unsetmd -oo -mo --version --license --formats --format --optfile --config --debug --pause --locale "
+      key_list="--help-general -ro -a_srs -a_ullr -tr -unsetgt -a_nodata -unsetnodata -offset -scale -unsetstats -stats -approx_stats -gcp -unsetmd -oo -mo --version --license --formats --format --optfile --config --debug --pause --locale "
       COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
       return 0
       ;;
@@ -459,7 +459,7 @@ _gdal_retile.py()
   _get_comp_words_by_ref cur prev
   case "$cur" in
     -*)
-      key_list="-v -q -co -of -ps -ot -tileIndex -tileIndexField -csv -csvDelim -s_srs -pyramidOnly -levels -r -useDirForEachRow -targetDir "
+      key_list="-v -q -co -of -ps -overlap -ot -tileIndex -tileIndexField -csv -csvDelim -s_srs -pyramidOnly -levels -r -useDirForEachRow -targetDir "
       COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
       return 0
       ;;
@@ -604,7 +604,7 @@ _gdalwarp()
   _get_comp_words_by_ref cur prev
   case "$cur" in
     -*)
-      key_list="--help-general --formats -s_srs -t_srs -to -order -tps -rpc -geoloc -et -refine_gcps -te -tr -tap -ts -ovr -wo -ot -wt -srcnodata -dstnodata -dstalpha -r -wm -multi -q -cutline -cl -cwhere -csql -cblend -crop_to_cutline -of -co -overwrite -nomd -cvmd -setci -oo -doo --version --license --format --optfile --config --debug --pause --locale "
+      key_list="--help-general --formats -s_srs -t_srs -to -novshiftgrid -order -tps -rpc -geoloc -et -refine_gcps -te -tr -tap -ts -ovr -wo -ot -wt -srcnodata -dstnodata -dstalpha -r -wm -multi -q -cutline -cl -cwhere -csql -cblend -crop_to_cutline -of -co -overwrite -nomd -cvmd -setci -oo -doo --version --license --format --optfile --config --debug --pause --locale "
       COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
       return 0
       ;;
@@ -634,7 +634,7 @@ _ogr2ogr()
   _get_comp_words_by_ref cur prev
   case "$cur" in
     -*)
-      key_list="--help-general -skipfailures -append -update -select -where -progress -sql -dialect -preserve_fid -fid -spat -spat_srs -geomfield -a_srs -t_srs -s_srs -f -overwrite -dsco -lco -nln -nlt -dim --version --license --formats --format --optfile --config --debug --pause --locale "
+      key_list="--help-general -skipfailures -append -update -select -where -progress -sql -dialect -preserve_fid -fid -limit -spat -spat_srs -geomfield -a_srs -t_srs -s_srs -f -overwrite -dsco -lco -nln -nlt -dim --version --license --formats --format --optfile --config --debug --pause --locale "
       COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
       return 0
       ;;
@@ -660,7 +660,7 @@ _ogrinfo()
   _get_comp_words_by_ref cur prev
   case "$cur" in
     -*)
-      key_list="--help-general -ro -q -where -spat -geomfield -fid -sql -dialect -al -so -fields=YES -fields=NO -geom=YES -geom=NO -geom=SUMMARY -formats -oo -nomd -listmdd -mdd -nocount -noextent --version --license --formats --format --optfile --config --debug --pause --locale "
+      key_list="--help-general -ro -q -where -spat -geomfield -fid -sql -dialect -al -rl -so -fields=YES -fields=NO -geom=YES -geom=NO -geom=SUMMARY -formats -oo -nomd -listmdd -mdd -nocount -noextent --version --license --formats --format --optfile --config --debug --pause --locale "
       COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
       return 0
       ;;
@@ -701,7 +701,7 @@ _ogrtindex()
   _get_comp_words_by_ref cur prev
   case "$cur" in
     -*)
-      key_list="-lnum -lname -f -write_absolute_path -skip_different_projection -accept_different_schemas "
+      key_list="-lnum -lname -f -write_absolute_path -skip_different_projection -t_srs -src_srs_name -src_srs_format -accept_different_schemas "
       COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
       return 0
       ;;
@@ -720,3 +720,18 @@ _ogrtindex()
   return 0
 }
 complete -o default -F _ogrtindex ogrtindex
+_ogrmerge.py()
+{
+  local cur prev
+  COMPREPLY=()
+  _get_comp_words_by_ref cur prev
+  case "$cur" in
+    -*)
+      key_list=""
+      COMPREPLY=( $( compgen -W '$key_list' -- $cur) )
+      return 0
+      ;;
+  esac
+  return 0
+}
+complete -o default -F _ogrmerge.py ogrmerge.py
diff --git a/scripts/typos_whitelist.txt b/scripts/typos_whitelist.txt
index be2b5c7..892a8a0 100644
--- a/scripts/typos_whitelist.txt
+++ b/scripts/typos_whitelist.txt
@@ -22,7 +22,7 @@ See COMMITERS file.
     sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
     sizeOfFields[nFields] += WriteSubFieldStr(fd, osNAM.c_str(), 8); /* NAM */
                                                   "NAM!STR!PRT!SWO!SWA!NEO!NEA",
-        sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); /* NAM */
+        sizeOfFields[nFields] += WriteSubFieldStr(fd, osBaseFileName, 8); // NAM
       {136, "Socialist Republic of Viet Nam"},
 		double	eps[NANGLES], ua, va, ang, epsa;
 				ang = uv2ang(ua, va);
@@ -37,3 +37,31 @@ See COMMITERS file.
             passport.stMapDescription.eUnitInPlan = SXF_COORD_MU_MILLIMETRE;
     SXF_COORD_MU_CENTIMETRE,
     SXF_COORD_MU_MILLIMETRE,
+      addSimpleType(&oTypes, "GVAKT_PROS", "geoVernAktivProsess", OFTString);
+      addSimpleType(&oTypes, "GVVKT_PROS", "geoVernViktigProsess", OFTString);
+      addSimpleType(&oTypes, "PROSESS_HISTORIE", "prosesshistorie", OFTString);
+            ih.Put( "<unintialized>", 64, 64 );  // TODO: Spelling?
+      {7, 110, "NAM Model - 15km version"},
+      {7, 111, "NAM model, generic resolution"},
+      {7, 115, "Downscaled GFS from NAM eXtension"},
+      {7, 130, "Merge of fields from the RUC, NAM, and Spectral Model"},
+   /* 0 */ {"ACCES", "Air concentration of Caesium 137", "Bq/(m^3)", UC_NONE},
+        : CPLGetXMLValue( psSrcXML, "metresPerUnit", NULL );
+{ "kilometre", SRS_UL_KILOMETER_CONV, "km" },
+    { CADObject::DIMENSION_ANG_3PT,    "DIMENSION ANG 3PT" },
+    {"SCALING_FACTOR_ATM_PRES",                           16, EDT_Float32,     1},
+    {"SCALING_FACTOR_SURF_PRES",                         104, EDT_Float32,     1},
+    {"OFFSET_SURF_PRES",                                 208, EDT_Float32,     1},
+  /* now prec is nonzero iff there are any 16-bit quant tables. */
+   * a box is splittable iff norm > 0.
+  boolean saw_JFIF_marker;	/* TRUE iff a JFIF APP0 marker was found */
+  boolean saw_Adobe_marker;	/* TRUE iff an Adobe APP14 marker was found */
+        // We will update the object count iff we are writing beyond the end.
+   /* 1 */ {"PRES", "Pressure", "Pa", UC_NONE},
+   /* 1 */ {"PRES", "Pressure", "hPa", UC_NONE},
+   /* 0 */ {"PRES", "Pressure", "Pa", UC_NONE},
+ * copied iff they didn't exist before.  ColorTransIn2 maps the old
+      nearzero iff determinant < qh NEARzero[dim-1]
+      facet->visitid= 0 iff vertex-at-infinity (i.e., unbounded)
+    sets same iff vertices have the same orientation
+      nearzero iff diagonal[k] < qh NEARzero[k]
diff --git a/scripts/vagrant/gdal.sh b/scripts/vagrant/gdal.sh
index 4b5acd3..a5f6ba4 100755
--- a/scripts/vagrant/gdal.sh
+++ b/scripts/vagrant/gdal.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 # abort install if any errors occur and enable tracing
 set -o errexit
@@ -32,7 +32,7 @@ sudo rm -f /usr/lib/libgdal.so*
 sudo make install
 sudo ldconfig
 # not sure why we need to do that
-sudo cp -r /usr/lib/python2.7/site-packages/*  /usr/lib/python2.7/dist-packages/
+#sudo cp -r /usr/lib/python2.7/site-packages/*  /usr/lib/python2.7/dist-packages/
 
 cd swig/perl
 make veryclean
diff --git a/scripts/vagrant/libkml.sh b/scripts/vagrant/libkml.sh
index 2f8a58e..0871cd7 100755
--- a/scripts/vagrant/libkml.sh
+++ b/scripts/vagrant/libkml.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 # abort install if any errors occur and enable tracing
 set -o errexit
diff --git a/scripts/vagrant/openjpeg.sh b/scripts/vagrant/openjpeg.sh
index 0a539f0..906e113 100755
--- a/scripts/vagrant/openjpeg.sh
+++ b/scripts/vagrant/openjpeg.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 # abort install if any errors occur and enable tracing
 set -o errexit
@@ -12,7 +12,7 @@ fi
 #NUMTHREADS=1 # disable MP
 export NUMTHREADS
 
-wget http://sourceforge.net/projects/openjpeg.mirror/files/openjpeg-2.0.0.tar.gz/download -O openjpeg-2.0.0.tar.gz
+wget --no-check-certificate https://sourceforge.net/projects/openjpeg.mirror/files/openjpeg-2.0.0.tar.gz/download -O openjpeg-2.0.0.tar.gz
 tar xvzf openjpeg-2.0.0.tar.gz
 cd openjpeg-2.0.0
 mkdir build
diff --git a/scripts/vagrant/sfcgal.sh b/scripts/vagrant/sfcgal.sh
new file mode 100755
index 0000000..e4bec6b
--- /dev/null
+++ b/scripts/vagrant/sfcgal.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+# Build CGAL
+wget https://gforge.inria.fr/frs/download.php/file/34400/CGAL-4.5.1.tar.gz
+tar xf CGAL-4.5.1.tar.gz
+cd CGAL-4.5.1
+cmake . && make && sudo make install
+cd ../
+rm -rf CGAL-4.5.1 CGAL-4.5.1.tar.gz
+# Build SFCGAL
+wget https://codeload.github.com/Oslandia/SFCGAL/tar.gz/v1.3.0 -O SFCGAL1.3.0.tar.gz
+tar xf SFCGAL1.3.0.tar.gz
+cd SFCGAL-1.3.0/
+cmake . && make && sudo make install
+cd ../
+sudo ldconfig
diff --git a/scripts/vagrant/swig-1.3.40.sh b/scripts/vagrant/swig-1.3.40.sh
index eb83310..7812026 100755
--- a/scripts/vagrant/swig-1.3.40.sh
+++ b/scripts/vagrant/swig-1.3.40.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 # abort install if any errors occur and enable tracing
 set -o errexit
@@ -12,7 +12,7 @@ fi
 #NUMTHREADS=1 # disable MP
 export NUMTHREADS
 
-wget "http://downloads.sourceforge.net/project/swig/swig/swig-1.3.40/swig-1.3.40.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fswig%2Ffiles%2Fswig%2Fswig-1.3.40%2F&ts=1425900154&use_mirror=freefr" -O swig-1.3.40.tar.gz
+wget --no-check-certificate https://sourceforge.net/projects/swig/files/swig/swig-1.3.40/swig-1.3.40.tar.gz/download -O swig-1.3.40.tar.gz
 tar xvzf swig-1.3.40.tar.gz
 cd  swig-1.3.40
 ./configure --prefix=$HOME/install-swig-1.3.40
diff --git a/swig/SWIGmake.base b/swig/SWIGmake.base
index a245c06..3a4dd35 100644
--- a/swig/SWIGmake.base
+++ b/swig/SWIGmake.base
@@ -6,17 +6,17 @@ SWIGOUTPUTDIR=
 WRAPPERS_WITHOUT_GNM = gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp
 WRAPPERS = $(WRAPPERS_WITHOUT_GNM) gnm_wrap.cpp
 
-gdal_wrap.cpp: ../include/gdal.i ../include/MajorObject.i ../include/Driver.i ../include/Dataset.i ../include/Band.i ../include/ColorTable.i ../include/cpl.i ../include/$(BINDING)/gdal_$(BINDING).i ../include/$(BINDING)/typemaps_$(BINDING).i
+gdal_wrap.cpp: ../include/gdal.i ../include/MajorObject.i ../include/Driver.i ../include/Dataset.i ../include/Band.i ../include/ColorTable.i ../include/cpl.i ../include/$(BINDING)/gdal_$(BINDING).i ../include/$(BINDING)/typemaps_$(BINDING).i $(SWIG_INCLUDES)
 	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -c++ -$(BINDING) -o $(SWIGOUTPUTDIR)$@ ../include/gdal.i
 
-gdalconst_wrap.c: ../include/gdalconst.i
+gdalconst_wrap.c: ../include/gdalconst.i $(SWIG_INCLUDES)
 	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -$(BINDING) -o $(SWIGOUTPUTDIR)$@ ../include/gdalconst.i
 
-ogr_wrap.cpp:  ../include/ogr.i ../include/$(BINDING)/ogr_$(BINDING).i ../include/$(BINDING)/typemaps_$(BINDING).i
+ogr_wrap.cpp:  ../include/ogr.i ../include/$(BINDING)/ogr_$(BINDING).i ../include/$(BINDING)/typemaps_$(BINDING).i $(SWIG_INCLUDES)
 	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -c++ -$(BINDING) -o $(SWIGOUTPUTDIR)$@ ../include/ogr.i
 
-osr_wrap.cpp:  ../include/osr.i ../include/$(BINDING)/osr_$(BINDING).i ../include/$(BINDING)/typemaps_$(BINDING).i
+osr_wrap.cpp:  ../include/osr.i ../include/$(BINDING)/osr_$(BINDING).i ../include/$(BINDING)/typemaps_$(BINDING).i $(SWIG_INCLUDES)
 	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -c++ -$(BINDING) -o $(SWIGOUTPUTDIR)$@ ../include/osr.i
 
-gnm_wrap.cpp:  ../include/gnm.i ../include/MajorObject.i ../include/Dataset.i ../include/$(BINDING)/typemaps_$(BINDING).i
+gnm_wrap.cpp:  ../include/gnm.i ../include/$(BINDING)/gnm_$(BINDING).i ../include/$(BINDING)/typemaps_$(BINDING).i $(SWIG_INCLUDES)
 	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -c++ -$(BINDING) -o $(SWIGOUTPUTDIR)$@ ../include/gnm.i
diff --git a/swig/csharp/apps/GDALAdjustContrast.cs b/swig/csharp/apps/GDALAdjustContrast.cs
index 2765ab4..c903e72 100644
--- a/swig/csharp/apps/GDALAdjustContrast.cs
+++ b/swig/csharp/apps/GDALAdjustContrast.cs
@@ -1,10 +1,10 @@
 /******************************************************************************
- * $Id: GDALAdjustContrast.cs 14383 2008-05-06 21:12:07Z tamas $
+ * $Id: GDALAdjustContrast.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALAdjustContrast.cs
  * Project:  GDAL CSharp Interface
  * Purpose:  A sample app to demonstrate how to read the dataset into the
- *           memory, adjust the contrast of the image and write back to the 
+ *           memory, adjust the contrast of the image and write back to the
  *           dataset persistently.
  * Author:   Tamas Szekeres, szekerest at gmail.com
  *
@@ -49,11 +49,11 @@ using OSGeo.GDAL;
 /// <summary>
 /// A sample app to demonstrate how to read the dataset into the
 /// memory, adjust the contrast of the image and write back to the dataset persistently.
-/// </summary> 
+/// </summary>
 
 class GDALAdjustContrast {
-	
-	public static void usage() 
+
+	public static void usage()
 
 	{
         Console.WriteLine("usage: GDALAdjustContrast {dataset name} {contrast ratio}");
@@ -73,7 +73,7 @@ class GDALAdjustContrast {
     static DataType dataType;
     static int pixelSpace;
 
-    public static void Main(string[] args) 
+    public static void Main(string[] args)
     {
 
         if (args.Length != 2) usage();
@@ -81,7 +81,7 @@ class GDALAdjustContrast {
         // Using early initialization of System.Console
         Console.WriteLine("Adjusting the image: " + args[0]);
 
-        try 
+        try
         {
             float contrastRatio = float.Parse(args[1]);
             /* -------------------------------------------------------------------- */
@@ -93,8 +93,8 @@ class GDALAdjustContrast {
             /*      Open dataset.                                                   */
             /* -------------------------------------------------------------------- */
             Dataset ds = Gdal.Open(args[0], Access.GA_Update);
-		
-            if (ds == null) 
+
+            if (ds == null)
             {
                 Console.WriteLine("Can't open " + args[0]);
                 System.Environment.Exit(-1);
@@ -134,7 +134,7 @@ class GDALAdjustContrast {
             ds.FlushCache();
 
         }
-        catch (Exception e) 
+        catch (Exception e)
         {
             Console.WriteLine("Application error: " + e.Message);
         }
diff --git a/swig/csharp/apps/GDALColorTable.cs b/swig/csharp/apps/GDALColorTable.cs
index a1b8033..b1310a2 100644
--- a/swig/csharp/apps/GDALColorTable.cs
+++ b/swig/csharp/apps/GDALColorTable.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALColorTable.cs 13677 2008-02-02 23:05:45Z tamas $
+ * $Id: GDALColorTable.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALColorTable.cs
  * Project:  GDAL CSharp Interface
@@ -44,18 +44,18 @@ using OSGeo.GDAL;
 
 /// <summary>
 /// A C# based sample for demonstrating the usage of the ColorTable object.
-/// </summary> 
+/// </summary>
 
 class GDALColorTable {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage: gdalcolortable {source dataset} {destination file}");
 		System.Environment.Exit(-1);
 	}
- 
-    public static void Main(string[] args) 
+
+    public static void Main(string[] args)
     {
 
         if (args.Length != 2) usage();
@@ -68,7 +68,7 @@ class GDALColorTable {
             /*      Register driver(s).                                             */
             /* -------------------------------------------------------------------- */
             Gdal.AllRegister();
-            
+
             Driver dv = null;
             Dataset ds = null, ds_out = null;
             Band ba = null, ba_out = null;
@@ -84,7 +84,7 @@ class GDALColorTable {
 
             if( ct != null )
                 Console.WriteLine( "Band has a color table with " + ct.GetCount() + " entries.");
-            else 
+            else
             {
                 Console.WriteLine( "Data source has no color table");
                 return;
@@ -96,7 +96,7 @@ class GDALColorTable {
 
             /* -------------------------------------------------------------------- */
             /*      Get driver                                                      */
-            /* -------------------------------------------------------------------- */	
+            /* -------------------------------------------------------------------- */
             dv = Gdal.GetDriverByName("GTiff");
 
             ds_out = dv.Create(file_out, ds.RasterXSize, ds.RasterYSize,
@@ -130,7 +130,7 @@ class GDALColorTable {
 
             ba_out.SetRasterColorTable(ct_out);
         }
-        catch (Exception e) 
+        catch (Exception e)
         {
             Console.WriteLine("Application error: " + e.Message);
         }
diff --git a/swig/csharp/apps/GDALCreateCopy.cs b/swig/csharp/apps/GDALCreateCopy.cs
index 79c46b2..1e37656 100644
--- a/swig/csharp/apps/GDALCreateCopy.cs
+++ b/swig/csharp/apps/GDALCreateCopy.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALCreateCopy.cs 13678 2008-02-02 23:29:37Z tamas $
+ * $Id: GDALCreateCopy.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALWrite.cs
  * Project:  GDAL CSharp Interface
@@ -44,42 +44,42 @@ using OSGeo.GDAL;
 
 /// <summary>
 /// A C# based sample to write a GDAL raster using CreateCopy.
-/// </summary> 
+/// </summary>
 
 class GDALWrite {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage: gdalcreatecopy {dataset name} {out file name}");
 		System.Environment.Exit(-1);
 	}
- 
-    public static void Main(string[] args) 
+
+    public static void Main(string[] args)
     {
 
         if (args.Length != 2) usage();
 
         Console.WriteLine("");
 
-        try 
+        try
         {
             /* -------------------------------------------------------------------- */
             /*      Register driver(s).                                             */
             /* -------------------------------------------------------------------- */
             Gdal.AllRegister();
-            
+
             /* -------------------------------------------------------------------- */
             /*      Get driver                                                      */
-            /* -------------------------------------------------------------------- */	
+            /* -------------------------------------------------------------------- */
             Driver drv = Gdal.GetDriverByName("GTiff");
 
-            if (drv == null) 
+            if (drv == null)
             {
                 Console.WriteLine("Can't get driver.");
                 System.Environment.Exit(-1);
             }
-            
+
             Console.WriteLine("Using driver " + drv.LongName);
 
             /* -------------------------------------------------------------------- */
@@ -87,7 +87,7 @@ class GDALWrite {
             /* -------------------------------------------------------------------- */
             Dataset ds = Gdal.Open( args[0], Access.GA_ReadOnly );
 
-            if (ds == null) 
+            if (ds == null)
             {
                 Console.WriteLine("Can't open source dataset " + args[1]);
                 System.Environment.Exit(-1);
@@ -95,14 +95,14 @@ class GDALWrite {
 
             string[] options = new string [] {"TILED=YES"};
             Dataset dso = drv.CreateCopy(args[1], ds, 0, options, new Gdal.GDALProgressFuncDelegate(ProgressFunc), "Sample Data");
-		
-            if (dso == null) 
+
+            if (dso == null)
             {
                 Console.WriteLine("Can't create dest dataset " + args[1]);
                 System.Environment.Exit(-1);
             }
         }
-        catch (Exception e) 
+        catch (Exception e)
         {
             Console.WriteLine("Application error: " + e.Message);
         }
@@ -115,7 +115,7 @@ class GDALWrite {
             Console.Write(" Message:" + System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Message));
         if (Data != IntPtr.Zero)
             Console.Write(" Data:" + System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Data));
-	
+
         Console.WriteLine("");
         return 1;
     }
diff --git a/swig/csharp/apps/GDALInfo.cs b/swig/csharp/apps/GDALInfo.cs
index 7517efb..d8985cc 100644
--- a/swig/csharp/apps/GDALInfo.cs
+++ b/swig/csharp/apps/GDALInfo.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALInfo.cs 18705 2010-02-02 21:11:43Z tamas $
+ * $Id: GDALInfo.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALInfo.cs
  * Project:  GDAL CSharp Interface
@@ -46,25 +46,25 @@ using OSGeo.OSR;
 
 /// <summary>
 /// A C# based sample to read GDAL raster data information.
-/// </summary> 
+/// </summary>
 
 class GDALInfo {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage: gdalinfo {GDAL dataset name}");
 		System.Environment.Exit(-1);
 	}
- 
-    public static void Main(string[] args) 
+
+    public static void Main(string[] args)
     {
 
         if (args.Length != 1) usage();
 
         Console.WriteLine("");
 
-        try 
+        try
         {
             /* -------------------------------------------------------------------- */
             /*      Register driver(s).                                             */
@@ -75,8 +75,8 @@ class GDALInfo {
             /*      Open dataset.                                                   */
             /* -------------------------------------------------------------------- */
             Dataset ds = Gdal.Open( args[0], Access.GA_ReadOnly );
-		
-            if (ds == null) 
+
+            if (ds == null)
             {
                 Console.WriteLine("Can't open " + args[0]);
                 System.Environment.Exit(-1);
@@ -86,18 +86,18 @@ class GDALInfo {
             Console.WriteLine("  Projection: " + ds.GetProjectionRef());
             Console.WriteLine("  RasterCount: " + ds.RasterCount);
             Console.WriteLine("  RasterSize (" + ds.RasterXSize + "," + ds.RasterYSize + ")");
-            
+
             /* -------------------------------------------------------------------- */
             /*      Get driver                                                      */
-            /* -------------------------------------------------------------------- */	
+            /* -------------------------------------------------------------------- */
             Driver drv = ds.GetDriver();
 
-            if (drv == null) 
+            if (drv == null)
             {
                 Console.WriteLine("Can't get driver.");
                 System.Environment.Exit(-1);
             }
-            
+
             Console.WriteLine("Using driver " + drv.LongName);
 
             /* -------------------------------------------------------------------- */
@@ -198,7 +198,7 @@ class GDALInfo {
                 for( int i = 0; i < ds.GetGCPCount(); i++ )
                 {
                     Console.WriteLine("GCP[" + i + "]: Id=" + GCPs[i].Id + ", Info=" + GCPs[i].Info);
-                    Console.WriteLine("          (" + GCPs[i].GCPPixel + "," + GCPs[i].GCPLine + ") -> (" 
+                    Console.WriteLine("          (" + GCPs[i].GCPPixel + "," + GCPs[i].GCPLine + ") -> ("
                                 + GCPs[i].GCPX + "," + GCPs[i].GCPY + "," + GCPs[i].GCPZ + ")");
                     Console.WriteLine("");
                 }
@@ -215,7 +215,7 @@ class GDALInfo {
             /* -------------------------------------------------------------------- */
             /*      Get raster band                                                 */
             /* -------------------------------------------------------------------- */
-            for (int iBand = 1; iBand <= ds.RasterCount; iBand++) 
+            for (int iBand = 1; iBand <= ds.RasterCount; iBand++)
             {
                 Band band = ds.GetRasterBand(iBand);
                 Console.WriteLine("Band " + iBand + " :");
@@ -224,7 +224,7 @@ class GDALInfo {
                 ColorTable ct = band.GetRasterColorTable();
 				if (ct != null)
 					Console.WriteLine("   Band has a color table with " + ct.GetCount() + " entries.");
-                
+
 				Console.WriteLine("   Description: " + band.GetDescription());
                 Console.WriteLine("   Size (" + band.XSize + "," + band.YSize + ")");
                 int BlockXSize, BlockYSize;
@@ -253,7 +253,7 @@ class GDALInfo {
                 }
             }
         }
-        catch (Exception e) 
+        catch (Exception e)
         {
             Console.WriteLine("Application error: " + e.Message);
         }
diff --git a/swig/csharp/apps/GDALMemDataset.cs b/swig/csharp/apps/GDALMemDataset.cs
index 7a46072..7fd4e44 100644
--- a/swig/csharp/apps/GDALMemDataset.cs
+++ b/swig/csharp/apps/GDALMemDataset.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALMemDataset.cs 25794 2013-03-24 13:15:43Z tamas $
+ * $Id: GDALMemDataset.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     VSIMem.cs
  * Project:  GDAL CSharp Interface
@@ -49,17 +49,17 @@ using System.Drawing.Imaging;
 
 /// <summary>
 /// A C# based sample for demonstrating the in-memory dataset driver..
-/// </summary> 
+/// </summary>
 
 class GDALMemDataset {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage example: GDALMemDataset [image file]");
 		System.Environment.Exit(-1);
 	}
- 
+
 	public static void Main(string[] args) {
 
 		if (args.Length != 1) usage();
diff --git a/swig/csharp/apps/GDALOverviews.cs b/swig/csharp/apps/GDALOverviews.cs
index 3ac82aa..63326b0 100644
--- a/swig/csharp/apps/GDALOverviews.cs
+++ b/swig/csharp/apps/GDALOverviews.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALOverviews.cs 13678 2008-02-02 23:29:37Z tamas $
+ * $Id: GDALOverviews.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALOverviews.cs
  * Project:  GDAL CSharp Interface
@@ -45,25 +45,25 @@ using OSGeo.GDAL;
 
 /// <summary>
 /// A C# based sample to create GDAL raster overviews.
-/// </summary> 
+/// </summary>
 
 class GDALOverviews {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage: gdaloverviews {GDAL dataset name} {resamplealg} {level1} {level2} ....");
 		Console.WriteLine("example: gdaloverviews sample.tif \"NEAREST\" 2 4");
 		System.Environment.Exit(-1);
 	}
- 
-    public static void Main(string[] args) 
+
+    public static void Main(string[] args)
     {
         if (args.Length <= 2) usage();
-        
+
         Console.WriteLine("");
 
-        try 
+        try
         {
             /* -------------------------------------------------------------------- */
             /*      Register driver(s).                                             */
@@ -74,8 +74,8 @@ class GDALOverviews {
             /*      Open dataset.                                                   */
             /* -------------------------------------------------------------------- */
             Dataset ds = Gdal.Open( args[0], Access.GA_Update );
-		
-            if (ds == null) 
+
+            if (ds == null)
             {
                 Console.WriteLine("Can't open " + args[0]);
                 System.Environment.Exit(-1);
@@ -85,26 +85,26 @@ class GDALOverviews {
             Console.WriteLine("  Projection: " + ds.GetProjectionRef());
             Console.WriteLine("  RasterCount: " + ds.RasterCount);
             Console.WriteLine("  RasterSize (" + ds.RasterXSize + "," + ds.RasterYSize + ")");
-            
+
             int[] levels = new int[args.Length -2];
 
             Console.WriteLine(levels.Length);
-           
+
             for (int i = 2; i < args.Length; i++)
             {
                 levels[i-2] = int.Parse(args[i]);
             }
-			
+
             if (ds.BuildOverviews(args[1], levels, new Gdal.GDALProgressFuncDelegate(ProgressFunc), "Sample Data") != (int)CPLErr.CE_None)
             {
                 Console.WriteLine("The BuildOverviews operation doesn't work");
                 System.Environment.Exit(-1);
             }
- 
+
             /* -------------------------------------------------------------------- */
             /*      Displaying the raster parameters                                */
             /* -------------------------------------------------------------------- */
-            for (int iBand = 1; iBand <= ds.RasterCount; iBand++) 
+            for (int iBand = 1; iBand <= ds.RasterCount; iBand++)
             {
                 Band band = ds.GetRasterBand(iBand);
                 Console.WriteLine("Band " + iBand + " :");
@@ -124,7 +124,7 @@ class GDALOverviews {
             Console.WriteLine("Completed.");
             Console.WriteLine("Use:  gdalread " + args[0] + " outfile.png [overview] to extract a particular overview!" );
         }
-        catch (Exception e) 
+        catch (Exception e)
         {
             Console.WriteLine("Application error: " + e.Message);
         }
@@ -137,7 +137,7 @@ class GDALOverviews {
 			Console.Write(" Message:" + System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Message));
 		if (Data != IntPtr.Zero)
 			Console.Write(" Data:" + System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Data));
-	
+
 		Console.WriteLine("");
 		return 1;
 	}
diff --git a/swig/csharp/apps/GDALRead.cs b/swig/csharp/apps/GDALRead.cs
index 7b9d1c0..ca42371 100644
--- a/swig/csharp/apps/GDALRead.cs
+++ b/swig/csharp/apps/GDALRead.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALRead.cs 13437 2007-12-21 21:02:38Z tamas $
+ * $Id: GDALRead.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALRead.cs
  * Project:  GDAL CSharp Interface
@@ -47,18 +47,18 @@ using OSGeo.GDAL;
 
 /// <summary>
 /// A C# based sample to read GDAL raster data.
-/// </summary> 
+/// </summary>
 
 class GDALRead {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage: gdalread {GDAL dataset name} {output file name} {overview}");
 		System.Environment.Exit(-1);
 	}
- 
-    public static void Main(string[] args) 
+
+    public static void Main(string[] args)
     {
         int iOverview = -1;
         if (args.Length < 2) usage();
@@ -67,7 +67,7 @@ class GDALRead {
         // Using early initialization of System.Console
         Console.WriteLine("");
 
-        try 
+        try
         {
             /* -------------------------------------------------------------------- */
             /*      Register driver(s).                                             */
@@ -78,8 +78,8 @@ class GDALRead {
             /*      Open dataset.                                                   */
             /* -------------------------------------------------------------------- */
             Dataset ds = Gdal.Open( args[0], Access.GA_ReadOnly );
-		
-            if (ds == null) 
+
+            if (ds == null)
             {
                 Console.WriteLine("Can't open " + args[0]);
                 System.Environment.Exit(-1);
@@ -89,24 +89,24 @@ class GDALRead {
             Console.WriteLine("  Projection: " + ds.GetProjectionRef());
             Console.WriteLine("  RasterCount: " + ds.RasterCount);
             Console.WriteLine("  RasterSize (" + ds.RasterXSize + "," + ds.RasterYSize + ")");
-            
+
             /* -------------------------------------------------------------------- */
             /*      Get driver                                                      */
-            /* -------------------------------------------------------------------- */	
+            /* -------------------------------------------------------------------- */
             Driver drv = ds.GetDriver();
 
-            if (drv == null) 
+            if (drv == null)
             {
                 Console.WriteLine("Can't get driver.");
                 System.Environment.Exit(-1);
             }
-            
+
             Console.WriteLine("Using driver " + drv.LongName);
 
             /* -------------------------------------------------------------------- */
             /*      Get raster band                                                 */
             /* -------------------------------------------------------------------- */
-            for (int iBand = 1; iBand <= ds.RasterCount; iBand++) 
+            for (int iBand = 1; iBand <= ds.RasterCount; iBand++)
             {
                 Band band = ds.GetRasterBand(iBand);
                 Console.WriteLine("Band " + iBand + " :");
@@ -128,19 +128,19 @@ class GDALRead {
             /*      Processing the raster                                           */
             /* -------------------------------------------------------------------- */
             SaveBitmapBuffered(ds, args[1], iOverview);
-            
+
         }
-        catch (Exception e) 
+        catch (Exception e)
         {
             Console.WriteLine("Application error: " + e.Message);
         }
     }
 
-    private static void SaveBitmapBuffered(Dataset ds, string filename, int iOverview) 
+    private static void SaveBitmapBuffered(Dataset ds, string filename, int iOverview)
     {
         // Get the GDAL Band objects from the Dataset
         Band redBand = ds.GetRasterBand(1);
-        
+
 		if (redBand.GetRasterColorInterpretation() == ColorInterp.GCI_PaletteIndex)
 		{
 			SaveBitmapPaletteBuffered(ds, filename, iOverview);
@@ -155,42 +155,42 @@ class GDALRead {
 
 		if (redBand.GetRasterColorInterpretation() != ColorInterp.GCI_RedBand)
 		{
-            Console.WriteLine("Non RGB images are not supported by this sample! ColorInterp = " + 
+            Console.WriteLine("Non RGB images are not supported by this sample! ColorInterp = " +
                 redBand.GetRasterColorInterpretation().ToString());
 			return;
 		}
 
-		if (ds.RasterCount < 3) 
+		if (ds.RasterCount < 3)
 		{
 			Console.WriteLine("The number of the raster bands is not enough to run this sample");
 			System.Environment.Exit(-1);
 		}
 
-        if (iOverview >= 0 && redBand.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && redBand.GetOverviewCount() > iOverview)
             redBand = redBand.GetOverview(iOverview);
 
         Band greenBand = ds.GetRasterBand(2);
-        
+
 		if (greenBand.GetRasterColorInterpretation() != ColorInterp.GCI_GreenBand)
 		{
-            Console.WriteLine("Non RGB images are not supported by this sample! ColorInterp = " + 
+            Console.WriteLine("Non RGB images are not supported by this sample! ColorInterp = " +
                 greenBand.GetRasterColorInterpretation().ToString());
 			return;
 		}
 
-        if (iOverview >= 0 && greenBand.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && greenBand.GetOverviewCount() > iOverview)
             greenBand = greenBand.GetOverview(iOverview);
 
         Band blueBand = ds.GetRasterBand(3);
-        
+
 		if (blueBand.GetRasterColorInterpretation() != ColorInterp.GCI_BlueBand)
 		{
-            Console.WriteLine("Non RGB images are not supported by this sample! ColorInterp = " + 
+            Console.WriteLine("Non RGB images are not supported by this sample! ColorInterp = " +
                 blueBand.GetRasterColorInterpretation().ToString());
 			return;
 		}
 
-        if (iOverview >= 0 && blueBand.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && blueBand.GetOverviewCount() > iOverview)
             blueBand = blueBand.GetOverview(iOverview);
 
         // Get the width and height of the raster
@@ -201,7 +201,7 @@ class GDALRead {
         Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
 
         DateTime start = DateTime.Now;
-        
+
         byte[] r = new byte[width * height];
         byte[] g = new byte[width * height];
         byte[] b = new byte[width * height];
@@ -213,7 +213,7 @@ class GDALRead {
         Console.WriteLine("SaveBitmapBuffered fetch time: " + renderTime.TotalMilliseconds + " ms");
 
         int i, j;
-        for (i = 0; i< width; i++) 
+        for (i = 0; i< width; i++)
         {
             for (j=0; j<height; j++)
             {
@@ -225,11 +225,11 @@ class GDALRead {
         bitmap.Save(filename);
     }
 
-	private static void SaveBitmapPaletteBuffered(Dataset ds, string filename, int iOverview) 
+	private static void SaveBitmapPaletteBuffered(Dataset ds, string filename, int iOverview)
 	{
 		// Get the GDAL Band objects from the Dataset
 		Band band = ds.GetRasterBand(1);
-        if (iOverview >= 0 && band.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && band.GetOverviewCount() > iOverview)
             band = band.GetOverview(iOverview);
 
 		ColorTable ct = band.GetRasterColorTable();
@@ -253,15 +253,15 @@ class GDALRead {
 		Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
 
 		DateTime start = DateTime.Now;
-        
+
 		byte[] r = new byte[width * height];
-		
+
 		band.ReadRaster(0, 0, width, height, r, width, height, 0, 0);
 		TimeSpan renderTime = DateTime.Now - start;
 		Console.WriteLine("SaveBitmapBuffered fetch time: " + renderTime.TotalMilliseconds + " ms");
 
 		int i, j;
-		for (i = 0; i< width; i++) 
+		for (i = 0; i< width; i++)
 		{
 			for (j=0; j<height; j++)
 			{
@@ -274,11 +274,11 @@ class GDALRead {
 		bitmap.Save(filename);
 	}
 
-	private static void SaveBitmapGrayBuffered(Dataset ds, string filename, int iOverview) 
+	private static void SaveBitmapGrayBuffered(Dataset ds, string filename, int iOverview)
 	{
 		// Get the GDAL Band objects from the Dataset
 		Band band = ds.GetRasterBand(1);
-        if (iOverview >= 0 && band.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && band.GetOverviewCount() > iOverview)
             band = band.GetOverview(iOverview);
 
 		// Get the width and height of the Dataset
@@ -289,15 +289,15 @@ class GDALRead {
 		Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
 
 		DateTime start = DateTime.Now;
-        
+
 		byte[] r = new byte[width * height];
-		
+
 		band.ReadRaster(0, 0, width, height, r, width, height, 0, 0);
 		TimeSpan renderTime = DateTime.Now - start;
 		Console.WriteLine("SaveBitmapBuffered fetch time: " + renderTime.TotalMilliseconds + " ms");
 
 		int i, j;
-		for (i = 0; i< width; i++) 
+		for (i = 0; i< width; i++)
 		{
 			for (j=0; j<height; j++)
 			{
diff --git a/swig/csharp/apps/GDALReadDirect.cs b/swig/csharp/apps/GDALReadDirect.cs
index 5dfc620..eaef436 100644
--- a/swig/csharp/apps/GDALReadDirect.cs
+++ b/swig/csharp/apps/GDALReadDirect.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALReadDirect.cs 13437 2007-12-21 21:02:38Z tamas $
+ * $Id: GDALReadDirect.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALReadDirect.cs
  * Project:  GDAL CSharp Interface
@@ -47,18 +47,18 @@ using OSGeo.GDAL;
 
 /// <summary>
 /// A C# based sample to read GDAL raster data directly to a C# bitmap.
-/// </summary> 
+/// </summary>
 
 class GDALReadDirect {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage: gdalread {GDAL dataset name} {output file name} {overview}");
 		System.Environment.Exit(-1);
 	}
- 
-    public static void Main(string[] args) 
+
+    public static void Main(string[] args)
     {
 
         int iOverview = -1;
@@ -68,7 +68,7 @@ class GDALReadDirect {
         // Using early initialization of System.Console
         Console.WriteLine("");
 
-        try 
+        try
         {
             /* -------------------------------------------------------------------- */
             /*      Register driver(s).                                             */
@@ -79,8 +79,8 @@ class GDALReadDirect {
             /*      Open dataset.                                                   */
             /* -------------------------------------------------------------------- */
             Dataset ds = Gdal.Open( args[0], Access.GA_ReadOnly );
-		
-            if (ds == null) 
+
+            if (ds == null)
             {
                 Console.WriteLine("Can't open " + args[0]);
                 System.Environment.Exit(-1);
@@ -90,24 +90,24 @@ class GDALReadDirect {
             Console.WriteLine("  Projection: " + ds.GetProjectionRef());
             Console.WriteLine("  RasterCount: " + ds.RasterCount);
             Console.WriteLine("  RasterSize (" + ds.RasterXSize + "," + ds.RasterYSize + ")");
-            
+
             /* -------------------------------------------------------------------- */
             /*      Get driver                                                      */
-            /* -------------------------------------------------------------------- */	
+            /* -------------------------------------------------------------------- */
             Driver drv = ds.GetDriver();
 
-            if (drv == null) 
+            if (drv == null)
             {
                 Console.WriteLine("Can't get driver.");
                 System.Environment.Exit(-1);
             }
-            
+
             Console.WriteLine("Using driver " + drv.LongName);
 
             /* -------------------------------------------------------------------- */
             /*      Get raster band                                                 */
             /* -------------------------------------------------------------------- */
-            for (int iBand = 1; iBand <= ds.RasterCount; iBand++) 
+            for (int iBand = 1; iBand <= ds.RasterCount; iBand++)
             {
                 Band band = ds.GetRasterBand(iBand);
                 Console.WriteLine("Band " + iBand + " :");
@@ -129,7 +129,7 @@ class GDALReadDirect {
             /*      Processing the raster                                           */
             /* -------------------------------------------------------------------- */
             SaveBitmapDirect(ds, args[1], iOverview);
-            
+
         }
         catch (Exception e)
         {
@@ -137,7 +137,7 @@ class GDALReadDirect {
         }
     }
 
-    private static void SaveBitmapDirect(Dataset ds, string filename, int iOverview) 
+    private static void SaveBitmapDirect(Dataset ds, string filename, int iOverview)
     {
         // Get the GDAL Band objects from the Dataset
         Band redBand = ds.GetRasterBand(1);
@@ -154,23 +154,23 @@ class GDALReadDirect {
             return;
         }
 
-        if (ds.RasterCount < 3) 
+        if (ds.RasterCount < 3)
         {
             Console.WriteLine("The number of the raster bands is not enough to run this sample");
             System.Environment.Exit(-1);
         }
 
-        if (iOverview >= 0 && redBand.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && redBand.GetOverviewCount() > iOverview)
             redBand = redBand.GetOverview(iOverview);
 
         Band greenBand = ds.GetRasterBand(2);
 
-        if (iOverview >= 0 && greenBand.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && greenBand.GetOverviewCount() > iOverview)
             greenBand = greenBand.GetOverview(iOverview);
 
         Band blueBand = ds.GetRasterBand(3);
 
-        if (iOverview >= 0 && blueBand.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && blueBand.GetOverviewCount() > iOverview)
             blueBand = blueBand.GetOverview(iOverview);
 
         // Get the width and height of the Dataset
@@ -181,11 +181,11 @@ class GDALReadDirect {
         Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
 
         DateTime start = DateTime.Now;
-        
+
         // Use GDAL raster reading methods to read the image data directly into the Bitmap
         BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
 
-        try 
+        try
         {
             int stride = bitmapData.Stride;
             IntPtr buf = bitmapData.Scan0;
@@ -196,7 +196,7 @@ class GDALReadDirect {
             TimeSpan renderTime = DateTime.Now - start;
             Console.WriteLine("SaveBitmapDirect fetch time: " + renderTime.TotalMilliseconds + " ms");
         }
-        finally 
+        finally
         {
             bitmap.UnlockBits(bitmapData);
         }
@@ -204,11 +204,11 @@ class GDALReadDirect {
         bitmap.Save(filename);
     }
 
-    private static void SaveBitmapPaletteDirect(Dataset ds, string filename, int iOverview) 
+    private static void SaveBitmapPaletteDirect(Dataset ds, string filename, int iOverview)
     {
         // Get the GDAL Band objects from the Dataset
         Band band = ds.GetRasterBand(1);
-        if (iOverview >= 0 && band.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && band.GetOverviewCount() > iOverview)
             band = band.GetOverview(iOverview);
 
         ColorTable ct = band.GetRasterColorTable();
@@ -232,14 +232,14 @@ class GDALReadDirect {
         Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
 
         DateTime start = DateTime.Now;
-        
+
         byte[] r = new byte[width * height];
-		
+
         band.ReadRaster(0, 0, width, height, r, width, height, 0, 0);
         // Use GDAL raster reading methods to read the image data directly into the Bitmap
         BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
 
-        try 
+        try
         {
             int iCol = ct.GetCount();
             ColorPalette pal = bitmap.Palette;
@@ -249,7 +249,7 @@ class GDALReadDirect {
                 pal.Entries[i] = Color.FromArgb(ce.c4, ce.c1, ce.c2, ce.c3);
             }
             bitmap.Palette = pal;
-            
+
             int stride = bitmapData.Stride;
             IntPtr buf = bitmapData.Scan0;
 
@@ -257,7 +257,7 @@ class GDALReadDirect {
             TimeSpan renderTime = DateTime.Now - start;
             Console.WriteLine("SaveBitmapDirect fetch time: " + renderTime.TotalMilliseconds + " ms");
         }
-        finally 
+        finally
         {
             bitmap.UnlockBits(bitmapData);
         }
@@ -265,11 +265,11 @@ class GDALReadDirect {
         bitmap.Save(filename);
     }
 
-    private static void SaveBitmapGrayDirect(Dataset ds, string filename, int iOverview) 
+    private static void SaveBitmapGrayDirect(Dataset ds, string filename, int iOverview)
     {
         // Get the GDAL Band objects from the Dataset
         Band band = ds.GetRasterBand(1);
-        if (iOverview >= 0 && band.GetOverviewCount() > iOverview) 
+        if (iOverview >= 0 && band.GetOverviewCount() > iOverview)
             band = band.GetOverview(iOverview);
 
         // Get the width and height of the Dataset
@@ -280,20 +280,20 @@ class GDALReadDirect {
         Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
 
         DateTime start = DateTime.Now;
-        
+
         byte[] r = new byte[width * height];
-		
+
         band.ReadRaster(0, 0, width, height, r, width, height, 0, 0);
         // Use GDAL raster reading methods to read the image data directly into the Bitmap
         BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
 
-        try 
+        try
         {
-            ColorPalette pal = bitmap.Palette; 
-            for(int i = 0; i < 256; i++) 
-                pal.Entries[i] = Color.FromArgb( 255, i, i, i ); 
+            ColorPalette pal = bitmap.Palette;
+            for(int i = 0; i < 256; i++)
+                pal.Entries[i] = Color.FromArgb( 255, i, i, i );
             bitmap.Palette = pal;
-            
+
             int stride = bitmapData.Stride;
             IntPtr buf = bitmapData.Scan0;
 
@@ -301,7 +301,7 @@ class GDALReadDirect {
             TimeSpan renderTime = DateTime.Now - start;
             Console.WriteLine("SaveBitmapDirect fetch time: " + renderTime.TotalMilliseconds + " ms");
         }
-        finally 
+        finally
         {
             bitmap.UnlockBits(bitmapData);
         }
diff --git a/swig/csharp/apps/GDALWrite.cs b/swig/csharp/apps/GDALWrite.cs
index 4d5e5f3..bb2b296 100644
--- a/swig/csharp/apps/GDALWrite.cs
+++ b/swig/csharp/apps/GDALWrite.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALWrite.cs 17453 2009-07-25 19:23:06Z tamas $
+ * $Id: GDALWrite.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALWrite.cs
  * Project:  GDAL CSharp Interface
@@ -44,18 +44,18 @@ using OSGeo.GDAL;
 
 /// <summary>
 /// A C# based sample to write a GDAL raster.
-/// </summary> 
+/// </summary>
 
 class GDALWrite {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage: gdalwrite {dataset name} {width} {height}");
 		System.Environment.Exit(-1);
 	}
- 
-    public static void Main(string[] args) 
+
+    public static void Main(string[] args)
     {
 
         if (args.Length < 1) usage();
@@ -78,24 +78,24 @@ class GDALWrite {
         bXSize = w;
         bYSize = 1;
 
-        //try 
+        //try
         {
             /* -------------------------------------------------------------------- */
             /*      Register driver(s).                                             */
             /* -------------------------------------------------------------------- */
             Gdal.AllRegister();
-            
+
             /* -------------------------------------------------------------------- */
             /*      Get driver                                                      */
-            /* -------------------------------------------------------------------- */	
+            /* -------------------------------------------------------------------- */
             Driver drv = Gdal.GetDriverByName("GTiff");
 
-            if (drv == null) 
+            if (drv == null)
             {
                 Console.WriteLine("Can't get driver.");
                 System.Environment.Exit(-1);
             }
-            
+
             Console.WriteLine("Using driver " + drv.LongName);
 
             /* -------------------------------------------------------------------- */
@@ -103,8 +103,8 @@ class GDALWrite {
             /* -------------------------------------------------------------------- */
             string[] options = new string [] {"BLOCKXSIZE=" + bXSize, "BLOCKYSIZE=" + bYSize};
             Dataset ds = drv.Create(args[0], w, h, 1, DataType.GDT_Byte, options);
-		
-            if (ds == null) 
+
+            if (ds == null)
             {
                 Console.WriteLine("Can't open " + args[0]);
                 System.Environment.Exit(-1);
@@ -113,7 +113,7 @@ class GDALWrite {
             /* -------------------------------------------------------------------- */
             /*      Setting corner GCPs.                                            */
             /* -------------------------------------------------------------------- */
-            GCP[] GCPs = new GCP[] { 
+            GCP[] GCPs = new GCP[] {
                 new GCP(44.5, 27.5, 0, 0, 0, "info0", "id0"),
                 new GCP(45.5, 27.5, 0, 100, 0, "info1", "id1"),
                 new GCP(44.5, 26.5, 0, 0, 100, "info2", "id2"),
@@ -139,7 +139,7 @@ class GDALWrite {
             ds.FlushCache();
 
         }
-        /*catch (Exception e) 
+        /*catch (Exception e)
         {
             Console.WriteLine("Application error: " + e.Message);
         }*/
diff --git a/swig/csharp/apps/OGRGEOS.cs b/swig/csharp/apps/OGRGEOS.cs
index 9b05fd6..93c092e 100644
--- a/swig/csharp/apps/OGRGEOS.cs
+++ b/swig/csharp/apps/OGRGEOS.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: OGRGEOS.cs 13678 2008-02-02 23:29:37Z tamas $
+ * $Id: OGRGEOS.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     OGRGEOS.cs
  * Project:  GDAL CSharp Interface
@@ -45,10 +45,10 @@ using OSGeo.OGR;
 
 /// <summary>
 /// A C# based sample for testing the OGR GEOS support.
-/// </summary> 
+/// </summary>
 
 class OGRGEOS {
-	
+
 	public static void Main(string[] args) {
         Console.WriteLine("");
 
@@ -105,7 +105,7 @@ class OGRGEOS {
             Console.WriteLine("Intersect: wrong result (got true)");
             return -1;
         }
-        
+
         Console.WriteLine("Intersect test OK");
         return 0;
     }
diff --git a/swig/csharp/apps/OGRLayerAlg.cs b/swig/csharp/apps/OGRLayerAlg.cs
index 6b06d02..71f2466 100644
--- a/swig/csharp/apps/OGRLayerAlg.cs
+++ b/swig/csharp/apps/OGRLayerAlg.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: OGRLayerAlg.cs 27014 2014-03-06 20:06:32Z tamas $
+ * $Id: OGRLayerAlg.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     OGRLayerAlg.cs
  * Project:  GDAL CSharp Interface
@@ -45,25 +45,25 @@ using OSGeo.OGR;
 
 /// <summary>
 /// A sample app to demonstrate the usage of the RFC-39 functions.
-/// </summary> 
+/// </summary>
 
 class OGRLayerAlg {
-	
-	public static void usage() 
+
+	public static void usage()
 
 	{
         Console.WriteLine("usage: ogrlayeralg {function} {Data Source 1} {layer1} {Data Source 2} {layer2} {Result Data Source Name} {Result Layer Name} [{Options}]");
         Console.WriteLine("example: ogrlayeralg Union data1.shp layer1 data.shp layer2 result.shp resultlayer SKIP_FAILURES=YES");
 		System.Environment.Exit(-1);
 	}
- 
-    public static void Main(string[] args) 
+
+    public static void Main(string[] args)
     {
         if (args.Length <= 6) usage();
-        
+
         Console.WriteLine("");
 
-        try 
+        try
         {
             /* -------------------------------------------------------------------- */
             /*      Register driver(s).                                             */
@@ -107,10 +107,10 @@ class OGRLayerAlg {
 
             /* -------------------------------------------------------------------- */
 		    /*      Get driver for creating the result ds                          */
-		    /* -------------------------------------------------------------------- */	
+		    /* -------------------------------------------------------------------- */
             Driver drv = Ogr.GetDriverByName("ESRI Shapefile");
 
-		    if (drv == null) 
+		    if (drv == null)
 		    {
 			    Console.WriteLine("Can't get driver.");
                 System.Environment.Exit(-1);
@@ -118,10 +118,10 @@ class OGRLayerAlg {
 
             /* -------------------------------------------------------------------- */
 		    /*      Creating the datasource                                         */
-		    /* -------------------------------------------------------------------- */	
+		    /* -------------------------------------------------------------------- */
 
             DataSource ds = drv.CreateDataSource( args[5], new string[] {} );
-            if (drv == null) 
+            if (drv == null)
             {
                 Console.WriteLine("Can't create the datasource.");
                 System.Environment.Exit(-1);
@@ -143,7 +143,7 @@ class OGRLayerAlg {
             /* -------------------------------------------------------------------- */
 
             Layer layer;
-        
+
             int i;
             for(i=0;i<ds.GetLayerCount();i++)
             {
@@ -188,7 +188,7 @@ class OGRLayerAlg {
                     break;
             }
         }
-        catch (Exception e) 
+        catch (Exception e)
         {
             Console.WriteLine("Application error: " + e.Message);
         }
@@ -201,7 +201,7 @@ class OGRLayerAlg {
 			Console.Write(" Message:" + System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Message));
 		if (Data != IntPtr.Zero)
 			Console.Write(" Data:" + System.Runtime.InteropServices.Marshal.PtrToStringAnsi(Data));
-	
+
 		Console.WriteLine("");
 		return 1;
 	}
diff --git a/swig/csharp/apps/OSRTransform.cs b/swig/csharp/apps/OSRTransform.cs
index b3d659f..ae8832a 100644
--- a/swig/csharp/apps/OSRTransform.cs
+++ b/swig/csharp/apps/OSRTransform.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: OSRTransform.cs 13437 2007-12-21 21:02:38Z tamas $
+ * $Id: OSRTransform.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     OSRTransform.cs
  * Project:  GDAL CSharp Interface
@@ -40,7 +40,7 @@ using OSGeo.OSR;
 
 /// <summary>
 /// A C# based sample to make simple transformations.
-/// </summary> 
+/// </summary>
 class OSRTransform {
 	public static void Main(string[] args) {
 		try
diff --git a/swig/csharp/apps/ReadXML.cs b/swig/csharp/apps/ReadXML.cs
index c23cce0..b116c75 100644
--- a/swig/csharp/apps/ReadXML.cs
+++ b/swig/csharp/apps/ReadXML.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ReadXML.cs 13437 2007-12-21 21:02:38Z tamas $
+ * $Id: ReadXML.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     ReadXML.cs
  * Project:  GDAL CSharp Interface
@@ -43,23 +43,23 @@ using OSGeo.GDAL;
 
 /// <summary>
 /// A C# based sample for demonstrating the usage of the XMLNode class.
-/// </summary> 
+/// </summary>
 
 class ReadXML {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage example: readxml {xml string}");
 		System.Environment.Exit(-1);
 	}
- 
+
 	public static void Main(string[] args) {
 
 		if (args.Length != 1) usage();
 
         XMLNode node = new XMLNode(args[0]);
-        
+
         PrintNode(0, node);
 	}
 
diff --git a/swig/csharp/apps/VSIMem.cs b/swig/csharp/apps/VSIMem.cs
index 49afb45..1e6f8a9 100644
--- a/swig/csharp/apps/VSIMem.cs
+++ b/swig/csharp/apps/VSIMem.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: VSIMem.cs 25805 2013-03-26 10:46:39Z tamas $
+ * $Id: VSIMem.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     VSIMem.cs
  * Project:  GDAL CSharp Interface
@@ -47,17 +47,17 @@ using OSGeo.GDAL;
 
 /// <summary>
 /// A C# based sample for demonstrating the in-memory virtual file support.
-/// </summary> 
+/// </summary>
 
 class VSIMem {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage example: vsimem [image file]");
 		System.Environment.Exit(-1);
 	}
- 
+
 	public static void Main(string[] args) {
 
 		if (args.Length != 1) usage();
diff --git a/swig/csharp/apps/WKT2WKB.cs b/swig/csharp/apps/WKT2WKB.cs
index 00813b8..ce1fb05 100644
--- a/swig/csharp/apps/WKT2WKB.cs
+++ b/swig/csharp/apps/WKT2WKB.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: WKT2WKB.cs 13437 2007-12-21 21:02:38Z tamas $
+ * $Id: WKT2WKB.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     WKT2WKB.cs
  * Project:  GDAL CSharp Interface
@@ -45,17 +45,17 @@ using OSGeo.OGR;
 
 /// <summary>
 /// A C# based sample for demonstrating the usage of ExportToWkb.
-/// </summary> 
+/// </summary>
 
 class WKT2WKB {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage example: wkt2wkb \"POINT(47.0 19.2)\"");
 		System.Environment.Exit(-1);
 	}
- 
+
 	public static void Main(string[] args) {
 
 		if (args.Length != 1) usage();
@@ -66,14 +66,14 @@ class WKT2WKB {
         Ogr.RegisterAll();
 
         Geometry geom = Geometry.CreateFromWkt(args[0]);
-        
+
 		int wkbSize = geom.WkbSize();
-        if (wkbSize > 0) 
+        if (wkbSize > 0)
         {
             byte[] wkb = new byte[wkbSize];
             geom.ExportToWkb( wkb );
             Console.WriteLine( "wkt-->wkb: " + BitConverter.ToString(wkb) );
-			
+
 			// wkb --> wkt (reverse test)
 			Geometry geom2 = Geometry.CreateFromWkb(wkb);
 			string geom_wkt;
diff --git a/swig/csharp/apps/createdata.cs b/swig/csharp/apps/createdata.cs
index ca1aea7..66c1428 100644
--- a/swig/csharp/apps/createdata.cs
+++ b/swig/csharp/apps/createdata.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: createdata.cs 27044 2014-03-16 23:41:27Z rouault $
+ * $Id: createdata.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     createdata.cs
  * Project:  GDAL CSharp Interface
@@ -48,17 +48,17 @@ using OSGeo.OSR;
 
 /// <summary>
 /// A C# based sample to create a layer.
-/// </summary> 
+/// </summary>
 
 class CreateData {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage: createdata {data source name} {layername}");
 		System.Environment.Exit(-1);
 	}
- 
+
 	public static void Main(string[] args) {
 
 		if (args.Length != 2) usage();
@@ -73,10 +73,10 @@ class CreateData {
 
 		/* -------------------------------------------------------------------- */
 		/*      Get driver                                                      */
-		/* -------------------------------------------------------------------- */	
+		/* -------------------------------------------------------------------- */
         Driver drv = Ogr.GetDriverByName("ESRI Shapefile");
 
-		if (drv == null) 
+		if (drv == null)
 		{
 			Console.WriteLine("Can't get driver.");
             System.Environment.Exit(-1);
@@ -88,10 +88,10 @@ class CreateData {
 
 		/* -------------------------------------------------------------------- */
 		/*      Creating the datasource                                         */
-		/* -------------------------------------------------------------------- */	
+		/* -------------------------------------------------------------------- */
 
         DataSource ds = drv.CreateDataSource( args[0], new string[] {} );
-        if (drv == null) 
+        if (drv == null)
         {
             Console.WriteLine("Can't create the datasource.");
             System.Environment.Exit(-1);
@@ -102,7 +102,7 @@ class CreateData {
         /* -------------------------------------------------------------------- */
 
         Layer layer;
-        
+
         int i;
         for(i=0;i<ds.GetLayerCount();i++)
         {
@@ -168,7 +168,7 @@ class CreateData {
 		feature.SetField( "DateField", 2007, 3, 15, 18, 24, 30, 0 );
 
         Geometry geom = Geometry.CreateFromWkt("POINT(47.0 19.2)");
-        
+
         if( feature.SetGeometry( geom ) != 0 )
         {
             Console.WriteLine( "Failed add geometry to the feature" );
@@ -180,7 +180,7 @@ class CreateData {
             Console.WriteLine( "Failed to create feature in shapefile" );
             System.Environment.Exit(-1);
         }
-        
+
 		ReportLayer(layer);
 	}
 
@@ -193,13 +193,13 @@ class CreateData {
 		layer.GetExtent(ext, 1);
 		Console.WriteLine( "Extent: " + ext.MinX + "," + ext.MaxX + "," +
 			ext.MinY + "," + ext.MaxY);
-		
+
 		/* -------------------------------------------------------------------- */
 		/*      Reading the spatial reference                                   */
 		/* -------------------------------------------------------------------- */
         OSGeo.OSR.SpatialReference sr = layer.GetSpatialRef();
 		string srs_wkt;
-		if ( sr != null ) 
+		if ( sr != null )
 		{
 			sr.ExportToPrettyWkt( out srs_wkt, 1 );
 		}
@@ -216,8 +216,8 @@ class CreateData {
 		for( int iAttr = 0; iAttr < def.GetFieldCount(); iAttr++ )
 		{
 			FieldDefn fdef = def.GetFieldDefn( iAttr );
-            
-			Console.WriteLine( fdef.GetNameRef() + ": " + 
+
+			Console.WriteLine( fdef.GetNameRef() + ": " +
 				fdef.GetFieldTypeName( fdef.GetFieldType() ) + " (" +
 				fdef.GetWidth() + "." +
 				fdef.GetPrecision() + ")");
@@ -241,7 +241,7 @@ class CreateData {
 		for( int iField = 0; iField < feat.GetFieldCount(); iField++ )
 		{
 			FieldDefn fdef = def.GetFieldDefn( iField );
-            
+
 			Console.Write( fdef.GetNameRef() + " (" +
 				fdef.GetFieldTypeName(fdef.GetFieldType()) + ") = ");
 
@@ -249,15 +249,15 @@ class CreateData {
 				Console.WriteLine( feat.GetFieldAsString( iField ) );
 			else
 				Console.WriteLine( "(null)" );
-            
+
 		}
 
 		if( feat.GetStyleString() != null )
 			Console.WriteLine( "  Style = " + feat.GetStyleString() );
-    
+
 		Geometry geom = feat.GetGeometryRef();
 		if( geom != null )
-			Console.WriteLine( "  " + geom.GetGeometryName() + 
+			Console.WriteLine( "  " + geom.GetGeometryName() +
 				"(" + geom.GetGeometryType() + ")" );
 
 		Envelope env = new Envelope();
diff --git a/swig/csharp/apps/ogrinfo.cs b/swig/csharp/apps/ogrinfo.cs
index e603952..fc0a2d6 100644
--- a/swig/csharp/apps/ogrinfo.cs
+++ b/swig/csharp/apps/ogrinfo.cs
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrinfo.cs 19470 2010-04-20 20:22:42Z tamas $
+ * $Id: ogrinfo.cs 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     ogrinfo.cs
  * Project:  GDAL CSharp Interface
@@ -46,17 +46,17 @@ using OSGeo.OSR;
 
 /// <summary>
 /// A C# based sample to dump information from a data source.
-/// </summary> 
+/// </summary>
 
 class OGRInfo {
-	
-	public static void usage() 
 
-	{ 
+	public static void usage()
+
+	{
 		Console.WriteLine("usage: ogrinfo {data source name}");
 		System.Environment.Exit(-1);
 	}
- 
+
 	public static void Main(string[] args) {
 
 		if (args.Length != 1) usage();
@@ -73,7 +73,7 @@ class OGRInfo {
 		/*      Open data source.                                               */
 		/* -------------------------------------------------------------------- */
 		DataSource ds = Ogr.Open( args[0], 0 );
-		
+
 		if (ds == null) {
 			Console.WriteLine("Can't open " + args[0]);
 			System.Environment.Exit(-1);
@@ -81,10 +81,10 @@ class OGRInfo {
 
 		/* -------------------------------------------------------------------- */
 		/*      Get driver                                                      */
-		/* -------------------------------------------------------------------- */	
+		/* -------------------------------------------------------------------- */
 		Driver drv = ds.GetDriver();
 
-		if (drv == null) 
+		if (drv == null)
 		{
 			Console.WriteLine("Can't get driver.");
 			System.Environment.Exit(-1);
@@ -94,7 +94,7 @@ class OGRInfo {
 
 		/* -------------------------------------------------------------------- */
 		/*      Iterating through the layers                                    */
-		/* -------------------------------------------------------------------- */	
+		/* -------------------------------------------------------------------- */
 
 		for( int iLayer = 0; iLayer < ds.GetLayerCount(); iLayer++ )
 		{
@@ -118,13 +118,13 @@ class OGRInfo {
 		layer.GetExtent(ext, 1);
 		Console.WriteLine( "Extent: " + ext.MinX + "," + ext.MaxX + "," +
 			ext.MinY + "," + ext.MaxY);
-		
+
 		/* -------------------------------------------------------------------- */
 		/*      Reading the spatial reference                                   */
 		/* -------------------------------------------------------------------- */
         OSGeo.OSR.SpatialReference sr = layer.GetSpatialRef();
 		string srs_wkt;
-		if ( sr != null ) 
+		if ( sr != null )
 		{
 			sr.ExportToPrettyWkt( out srs_wkt, 1 );
 		}
@@ -141,8 +141,8 @@ class OGRInfo {
 		for( int iAttr = 0; iAttr < def.GetFieldCount(); iAttr++ )
 		{
 			FieldDefn fdef = def.GetFieldDefn( iAttr );
-            
-			Console.WriteLine( fdef.GetNameRef() + ": " + 
+
+			Console.WriteLine( fdef.GetNameRef() + ": " +
 				fdef.GetFieldTypeName( fdef.GetFieldType() ) + " (" +
 				fdef.GetWidth() + "." +
 				fdef.GetPrecision() + ")");
@@ -166,7 +166,7 @@ class OGRInfo {
 		for( int iField = 0; iField < feat.GetFieldCount(); iField++ )
 		{
 			FieldDefn fdef = def.GetFieldDefn( iField );
-            
+
 			Console.Write( fdef.GetNameRef() + " (" +
 				fdef.GetFieldTypeName(fdef.GetFieldType()) + ") = ");
 
@@ -206,16 +206,16 @@ class OGRInfo {
             }
 			else
 				Console.WriteLine( "(null)" );
-            
+
 		}
 
 		if( feat.GetStyleString() != null )
 			Console.WriteLine( "  Style = " + feat.GetStyleString() );
-    
+
 		Geometry geom = feat.GetGeometryRef();
-		if( geom != null ) 
+		if( geom != null )
 		{
-			Console.WriteLine( "  " + geom.GetGeometryName() + 
+			Console.WriteLine( "  " + geom.GetGeometryName() +
 				"(" + geom.GetGeometryType() + ")" );
 			Geometry sub_geom;
 			for (int i = 0; i < geom.GetGeometryCount(); i++)
@@ -223,7 +223,7 @@ class OGRInfo {
 				sub_geom = geom.GetGeometryRef(i);
 				if ( sub_geom != null )
 				{
-					Console.WriteLine( "  subgeom" + i + ": " + sub_geom.GetGeometryName() + 
+					Console.WriteLine( "  subgeom" + i + ": " + sub_geom.GetGeometryName() +
 						"(" + sub_geom.GetGeometryType() + ")" );
 				}
 			}
diff --git a/swig/csharp/const/GdalConst.cs b/swig/csharp/const/GdalConst.cs
index b18d3fa..c639cdd 100644
--- a/swig/csharp/const/GdalConst.cs
+++ b/swig/csharp/const/GdalConst.cs
@@ -143,6 +143,9 @@ public class GdalConst {
   public static readonly int GMF_PER_DATASET = GdalConstPINVOKE.GMF_PER_DATASET_get();
   public static readonly int GMF_ALPHA = GdalConstPINVOKE.GMF_ALPHA_get();
   public static readonly int GMF_NODATA = GdalConstPINVOKE.GMF_NODATA_get();
+  public static readonly int GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED = GdalConstPINVOKE.GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED_get();
+  public static readonly int GDAL_DATA_COVERAGE_STATUS_DATA = GdalConstPINVOKE.GDAL_DATA_COVERAGE_STATUS_DATA_get();
+  public static readonly int GDAL_DATA_COVERAGE_STATUS_EMPTY = GdalConstPINVOKE.GDAL_DATA_COVERAGE_STATUS_EMPTY_get();
   public static readonly int GARIO_PENDING = GdalConstPINVOKE.GARIO_PENDING_get();
   public static readonly int GARIO_UPDATE = GdalConstPINVOKE.GARIO_UPDATE_get();
   public static readonly int GARIO_ERROR = GdalConstPINVOKE.GARIO_ERROR_get();
diff --git a/swig/csharp/const/GdalConstPINVOKE.cs b/swig/csharp/const/GdalConstPINVOKE.cs
index 8b4285e..fc2b7d6 100644
--- a/swig/csharp/const/GdalConstPINVOKE.cs
+++ b/swig/csharp/const/GdalConstPINVOKE.cs
@@ -582,6 +582,15 @@ class GdalConstPINVOKE {
   [DllImport("gdalconst_wrap", EntryPoint="CSharp_GMF_NODATA_get")]
   public static extern int GMF_NODATA_get();
 
+  [DllImport("gdalconst_wrap", EntryPoint="CSharp_GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED_get")]
+  public static extern int GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED_get();
+
+  [DllImport("gdalconst_wrap", EntryPoint="CSharp_GDAL_DATA_COVERAGE_STATUS_DATA_get")]
+  public static extern int GDAL_DATA_COVERAGE_STATUS_DATA_get();
+
+  [DllImport("gdalconst_wrap", EntryPoint="CSharp_GDAL_DATA_COVERAGE_STATUS_EMPTY_get")]
+  public static extern int GDAL_DATA_COVERAGE_STATUS_EMPTY_get();
+
   [DllImport("gdalconst_wrap", EntryPoint="CSharp_GARIO_PENDING_get")]
   public static extern int GARIO_PENDING_get();
 
diff --git a/swig/csharp/const/gdalconst_wrap.c b/swig/csharp/const/gdalconst_wrap.c
index afea243..3e0de9e 100644
--- a/swig/csharp/const/gdalconst_wrap.c
+++ b/swig/csharp/const/gdalconst_wrap.c
@@ -1576,6 +1576,36 @@ SWIGEXPORT int SWIGSTDCALL CSharp_GMF_NODATA_get() {
 }
 
 
+SWIGEXPORT int SWIGSTDCALL CSharp_GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED_get() {
+  int jresult ;
+  int result;
+  
+  result = (int)(0x01);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_GDAL_DATA_COVERAGE_STATUS_DATA_get() {
+  int jresult ;
+  int result;
+  
+  result = (int)(0x02);
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT int SWIGSTDCALL CSharp_GDAL_DATA_COVERAGE_STATUS_EMPTY_get() {
+  int jresult ;
+  int result;
+  
+  result = (int)(0x04);
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_GARIO_PENDING_get() {
   int jresult ;
   int result;
diff --git a/swig/csharp/gdal/Gdal.cs b/swig/csharp/gdal/Gdal.cs
index 76aebab..30f3924 100644
--- a/swig/csharp/gdal/Gdal.cs
+++ b/swig/csharp/gdal/Gdal.cs
@@ -619,6 +619,13 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
+  public static Dataset ApplyVerticalShiftGrid(Dataset src_ds, Dataset grid_ds, bool inverse, double srcUnitToMeter, double dstUnitToMeter, string[] options) {
+    IntPtr cPtr = GdalPINVOKE.ApplyVerticalShiftGrid(Dataset.getCPtr(src_ds), Dataset.getCPtr(grid_ds), inverse, srcUnitToMeter, dstUnitToMeter, (options != null)? new GdalPINVOKE.StringListMarshal(options)._ar : null);
+    Dataset ret = (cPtr == IntPtr.Zero) ? null : new Dataset(cPtr, true, ThisOwn_true());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public static void ApplyGeoTransform(double[] padfGeoTransform, double dfPixel, double dfLine, out double pdfGeoX, out double pdfGeoY) {
     GdalPINVOKE.ApplyGeoTransform(padfGeoTransform, dfPixel, dfLine, out pdfGeoX, out pdfGeoY);
     if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
@@ -784,6 +791,13 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
     return ret;
   }
 
+  public static Driver IdentifyDriverEx(string utf8_path, uint nIdentifyFlags, string[] allowed_drivers, string[] sibling_files) {
+    IntPtr cPtr = GdalPINVOKE.IdentifyDriverEx(Gdal.StringToUtf8Bytes(utf8_path), nIdentifyFlags, (allowed_drivers != null)? new GdalPINVOKE.StringListMarshal(allowed_drivers)._ar : null, (sibling_files != null)? new GdalPINVOKE.StringListMarshal(sibling_files)._ar : null);
+    Driver ret = (cPtr == IntPtr.Zero) ? null : new Driver(cPtr, false, ThisOwn_false());
+    if (GdalPINVOKE.SWIGPendingException.Pending) throw GdalPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public static string[] GeneralCmdLineProcessor(string[] papszArgv, int nOptions) {
         /* %typemap(csout) char**options */
         IntPtr cPtr = GdalPINVOKE.GeneralCmdLineProcessor((papszArgv != null)? new GdalPINVOKE.StringListMarshal(papszArgv)._ar : null, nOptions);
diff --git a/swig/csharp/gdal/GdalPINVOKE.cs b/swig/csharp/gdal/GdalPINVOKE.cs
index 64f807a..6e854e3 100644
--- a/swig/csharp/gdal/GdalPINVOKE.cs
+++ b/swig/csharp/gdal/GdalPINVOKE.cs
@@ -1021,6 +1021,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_Transformer_TransformGeolocations")]
   public static extern int Transformer_TransformGeolocations(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, HandleRef jarg4, Gdal.GDALProgressFuncDelegate jarg5, string jarg6, IntPtr[] jarg7);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_ApplyVerticalShiftGrid")]
+  public static extern IntPtr ApplyVerticalShiftGrid(HandleRef jarg1, HandleRef jarg2, bool jarg3, double jarg4, double jarg5, IntPtr[] jarg6);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_ApplyGeoTransform")]
   public static extern void ApplyGeoTransform(double[] jarg1, double jarg2, double jarg3, out double jarg4, out double jarg5);
 
@@ -1102,6 +1105,9 @@ class GdalPINVOKE {
   [DllImport("gdal_wrap", EntryPoint="CSharp_IdentifyDriver")]
   public static extern IntPtr IdentifyDriver(byte[] jarg1, IntPtr[] jarg2);
 
+  [DllImport("gdal_wrap", EntryPoint="CSharp_IdentifyDriverEx")]
+  public static extern IntPtr IdentifyDriverEx(byte[] jarg1, uint jarg2, IntPtr[] jarg3, IntPtr[] jarg4);
+
   [DllImport("gdal_wrap", EntryPoint="CSharp_GeneralCmdLineProcessor")]
   public static extern IntPtr GeneralCmdLineProcessor(IntPtr[] jarg1, int jarg2);
 
diff --git a/swig/csharp/gdal/gdal_wrap.cpp b/swig/csharp/gdal/gdal_wrap.cpp
index 49b343d..42f0722 100644
--- a/swig/csharp/gdal/gdal_wrap.cpp
+++ b/swig/csharp/gdal/gdal_wrap.cpp
@@ -1676,6 +1676,22 @@ SWIGINTERN int GDALTransformerInfoShadow_TransformGeolocations(GDALTransformerIn
                             	      callback, callback_data, options );
   }
 
+GDALDatasetShadow* ApplyVerticalShiftGrid( GDALDatasetShadow *src_ds,
+                                           GDALDatasetShadow *grid_ds,
+                                           bool inverse = false,
+                                           double srcUnitToMeter = 1.0,
+                                           double dstUnitToMeter = 1.0,
+                                           char** options = NULL ) {
+  GDALDatasetShadow *ds = GDALApplyVerticalShiftGrid( src_ds, grid_ds,
+                                                      inverse,
+                                                      srcUnitToMeter,
+                                                      dstUnitToMeter,
+                                                      options );
+  return ds;
+
+}
+
+
 int wrapper_GDALGetCacheMax()
 {
     return GDALGetCacheMax();
@@ -1774,6 +1790,18 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
 }
 
 
+GDALDriverShadow *IdentifyDriverEx( const char* utf8_path,
+                                    unsigned int nIdentifyFlags = 0,
+                                    char** allowed_drivers = NULL,
+                                    char** sibling_files = NULL )
+{
+    return  (GDALDriverShadow *) GDALIdentifyDriverEx( utf8_path,
+                                                nIdentifyFlags,
+                                                allowed_drivers,
+                                                sibling_files );
+}
+
+
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
 
@@ -12092,6 +12120,63 @@ SWIGEXPORT int SWIGSTDCALL CSharp_Transformer_TransformGeolocations(void * jarg1
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_ApplyVerticalShiftGrid(void * jarg1, void * jarg2, unsigned int jarg3, double jarg4, double jarg5, void * jarg6) {
+  void * jresult ;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  bool arg3 = (bool) false ;
+  double arg4 = (double) 1.0 ;
+  double arg5 = (double) 1.0 ;
+  char **arg6 = (char **) NULL ;
+  GDALDatasetShadow *result = 0 ;
+  
+  arg1 = (GDALDatasetShadow *)jarg1; 
+  arg2 = (GDALDatasetShadow *)jarg2; 
+  arg3 = jarg3 ? true : false; 
+  arg4 = (double)jarg4; 
+  arg5 = (double)jarg5; 
+  arg6 = (char **)jarg6; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDatasetShadow *)ApplyVerticalShiftGrid(arg1,arg2,arg3,arg4,arg5,arg6);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
 SWIGEXPORT void SWIGSTDCALL CSharp_ApplyGeoTransform(void * jarg1, double jarg2, double jarg3, double * jarg4, double * jarg5) {
   double *arg1 ;
   double arg2 ;
@@ -13064,6 +13149,52 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_IdentifyDriver(char * jarg1, void * jarg2)
 }
 
 
+SWIGEXPORT void * SWIGSTDCALL CSharp_IdentifyDriverEx(char * jarg1, unsigned int jarg2, void * jarg3, void * jarg4) {
+  void * jresult ;
+  char *arg1 = (char *) 0 ;
+  unsigned int arg2 = (unsigned int) 0 ;
+  char **arg3 = (char **) NULL ;
+  char **arg4 = (char **) NULL ;
+  GDALDriverShadow *result = 0 ;
+  
+  arg1 = (char *)jarg1; 
+  arg2 = (unsigned int)jarg2; 
+  arg3 = (char **)jarg3; 
+  arg4 = (char **)jarg4; 
+  {
+    if (!arg1) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (GDALDriverShadow *)IdentifyDriverEx((char const *)arg1,arg2,arg3,arg4);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = (void *)result; 
+  return jresult;
+}
+
+
 SWIGEXPORT void * SWIGSTDCALL CSharp_GeneralCmdLineProcessor(void * jarg1, int jarg2) {
   void * jresult ;
   char **arg1 = (char **) 0 ;
diff --git a/swig/csharp/ogr/Feature.cs b/swig/csharp/ogr/Feature.cs
index 8b51115..5c15330 100644
--- a/swig/csharp/ogr/Feature.cs
+++ b/swig/csharp/ogr/Feature.cs
@@ -310,6 +310,30 @@ public class Feature : IDisposable {
     return ret;
   }
 
+  public bool IsFieldNull(int id) {
+    bool ret = OgrPINVOKE.Feature_IsFieldNull__SWIG_0(swigCPtr, id);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public bool IsFieldNull(string name) {
+    bool ret = OgrPINVOKE.Feature_IsFieldNull__SWIG_1(swigCPtr, name);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public bool IsFieldSetAndNotNull(int id) {
+    bool ret = OgrPINVOKE.Feature_IsFieldSetAndNotNull__SWIG_0(swigCPtr, id);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
+  public bool IsFieldSetAndNotNull(string name) {
+    bool ret = OgrPINVOKE.Feature_IsFieldSetAndNotNull__SWIG_1(swigCPtr, name);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public int GetFieldIndex(string name) {
     int ret = OgrPINVOKE.Feature_GetFieldIndex(swigCPtr, name);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
@@ -349,6 +373,16 @@ public class Feature : IDisposable {
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
   }
 
+  public void SetFieldNull(int id) {
+    OgrPINVOKE.Feature_SetFieldNull__SWIG_0(swigCPtr, id);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
+  public void SetFieldNull(string name) {
+    OgrPINVOKE.Feature_SetFieldNull__SWIG_1(swigCPtr, name);
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+  }
+
   public void SetField(int id, string value) {
     OgrPINVOKE.Feature_SetField__SWIG_0(swigCPtr, id, Ogr.StringToUtf8Bytes(value));
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/ogr/Geometry.cs b/swig/csharp/ogr/Geometry.cs
index 87244de..9d5818c 100644
--- a/swig/csharp/ogr/Geometry.cs
+++ b/swig/csharp/ogr/Geometry.cs
@@ -396,6 +396,12 @@ public int ExportToWkb( byte[] buffer, wkbByteOrder byte_order ) {
     return ret;
   }
 
+  public double Distance3D(Geometry other) {
+    double ret = OgrPINVOKE.Geometry_Distance3D(swigCPtr, Geometry.getCPtr(other));
+    if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public void Empty() {
     OgrPINVOKE.Geometry_Empty(swigCPtr);
     if (OgrPINVOKE.SWIGPendingException.Pending) throw OgrPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/ogr/Ogr.cs b/swig/csharp/ogr/Ogr.cs
index 4043709..1c08939 100644
--- a/swig/csharp/ogr/Ogr.cs
+++ b/swig/csharp/ogr/Ogr.cs
@@ -358,6 +358,8 @@ public delegate int GDALProgressFuncDelegate(double Complete, IntPtr Message, In
   public static readonly string ODsCTransactions = OgrPINVOKE.ODsCTransactions_get();
   public static readonly string ODsCEmulatedTransactions = OgrPINVOKE.ODsCEmulatedTransactions_get();
   public static readonly string ODsCMeasuredGeometries = OgrPINVOKE.ODsCMeasuredGeometries_get();
+  public static readonly string ODsCRandomLayerRead = OgrPINVOKE.ODsCRandomLayerRead_get();
+  public static readonly string ODsCRandomLayerWrite = OgrPINVOKE.ODsCRandomLayerWrite_get();
   public static readonly string ODrCCreateDataSource = OgrPINVOKE.ODrCCreateDataSource_get();
   public static readonly string ODrCDeleteDataSource = OgrPINVOKE.ODrCDeleteDataSource_get();
   public static readonly string OLMD_FID64 = OgrPINVOKE.OLMD_FID64_get();
diff --git a/swig/csharp/ogr/OgrPINVOKE.cs b/swig/csharp/ogr/OgrPINVOKE.cs
index 6b0a41a..1a2851c 100644
--- a/swig/csharp/ogr/OgrPINVOKE.cs
+++ b/swig/csharp/ogr/OgrPINVOKE.cs
@@ -277,6 +277,12 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_ODsCMeasuredGeometries_get")]
   public static extern string ODsCMeasuredGeometries_get();
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_ODsCRandomLayerRead_get")]
+  public static extern string ODsCRandomLayerRead_get();
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_ODsCRandomLayerWrite_get")]
+  public static extern string ODsCRandomLayerWrite_get();
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_ODrCCreateDataSource_get")]
   public static extern string ODrCCreateDataSource_get();
 
@@ -775,6 +781,18 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_IsFieldSet__SWIG_1")]
   public static extern bool Feature_IsFieldSet__SWIG_1(HandleRef jarg1, string jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_IsFieldNull__SWIG_0")]
+  public static extern bool Feature_IsFieldNull__SWIG_0(HandleRef jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_IsFieldNull__SWIG_1")]
+  public static extern bool Feature_IsFieldNull__SWIG_1(HandleRef jarg1, string jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_IsFieldSetAndNotNull__SWIG_0")]
+  public static extern bool Feature_IsFieldSetAndNotNull__SWIG_0(HandleRef jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_IsFieldSetAndNotNull__SWIG_1")]
+  public static extern bool Feature_IsFieldSetAndNotNull__SWIG_1(HandleRef jarg1, string jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_GetFieldIndex")]
   public static extern int Feature_GetFieldIndex(HandleRef jarg1, string jarg2);
 
@@ -796,6 +814,12 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_UnsetField__SWIG_1")]
   public static extern void Feature_UnsetField__SWIG_1(HandleRef jarg1, string jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetFieldNull__SWIG_0")]
+  public static extern void Feature_SetFieldNull__SWIG_0(HandleRef jarg1, int jarg2);
+
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetFieldNull__SWIG_1")]
+  public static extern void Feature_SetFieldNull__SWIG_1(HandleRef jarg1, string jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Feature_SetField__SWIG_0")]
   public static extern void Feature_SetField__SWIG_0(HandleRef jarg1, int jarg2, byte[] jarg3);
 
@@ -1225,6 +1249,9 @@ class OgrPINVOKE {
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_Distance")]
   public static extern double Geometry_Distance(HandleRef jarg1, HandleRef jarg2);
 
+  [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_Distance3D")]
+  public static extern double Geometry_Distance3D(HandleRef jarg1, HandleRef jarg2);
+
   [DllImport("ogr_wrap", EntryPoint="CSharp_Geometry_Empty")]
   public static extern void Geometry_Empty(HandleRef jarg1);
 
diff --git a/swig/csharp/ogr/OsrPINVOKE.cs b/swig/csharp/ogr/OsrPINVOKE.cs
index a9f183b..7ce84ce 100644
--- a/swig/csharp/ogr/OsrPINVOKE.cs
+++ b/swig/csharp/ogr/OsrPINVOKE.cs
@@ -304,6 +304,9 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetLinearUnitsAndUpdateParameters")]
   public static extern int SpatialReference_SetLinearUnitsAndUpdateParameters(HandleRef jarg1, string jarg2, double jarg3);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_GetTargetLinearUnits")]
+  public static extern double SpatialReference_GetTargetLinearUnits(HandleRef jarg1, string jarg2);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_GetLinearUnits")]
   public static extern double SpatialReference_GetLinearUnits(HandleRef jarg1);
 
diff --git a/swig/csharp/ogr/SpatialReference.cs b/swig/csharp/ogr/SpatialReference.cs
index b2c0225..5e90ae6 100644
--- a/swig/csharp/ogr/SpatialReference.cs
+++ b/swig/csharp/ogr/SpatialReference.cs
@@ -198,6 +198,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public double GetTargetLinearUnits(string target_key) {
+    double ret = OsrPINVOKE.SpatialReference_GetTargetLinearUnits(swigCPtr, target_key);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public double GetLinearUnits() {
     double ret = OsrPINVOKE.SpatialReference_GetLinearUnits(swigCPtr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/ogr/ogr_wrap.cpp b/swig/csharp/ogr/ogr_wrap.cpp
index 32d5b61..a07ac96 100644
--- a/swig/csharp/ogr/ogr_wrap.cpp
+++ b/swig/csharp/ogr/ogr_wrap.cpp
@@ -897,6 +897,28 @@ SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_1(OGRFeatureShadow *self,char
 	  return (OGR_F_IsFieldSet(self, i) > 0);
       return false;
   }
+SWIGINTERN bool OGRFeatureShadow_IsFieldNull__SWIG_0(OGRFeatureShadow *self,int id){
+    return (OGR_F_IsFieldNull(self, id) > 0);
+  }
+SWIGINTERN bool OGRFeatureShadow_IsFieldNull__SWIG_1(OGRFeatureShadow *self,char const *name){
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+	  return (OGR_F_IsFieldNull(self, i) > 0);
+      return false;
+  }
+SWIGINTERN bool OGRFeatureShadow_IsFieldSetAndNotNull__SWIG_0(OGRFeatureShadow *self,int id){
+    return (OGR_F_IsFieldSetAndNotNull(self, id) > 0);
+  }
+SWIGINTERN bool OGRFeatureShadow_IsFieldSetAndNotNull__SWIG_1(OGRFeatureShadow *self,char const *name){
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+	  return (OGR_F_IsFieldSetAndNotNull(self, i) > 0);
+      return false;
+  }
 SWIGINTERN int OGRFeatureShadow_GetFieldIndex(OGRFeatureShadow *self,char const *name){
       // Do not issue an error if the field doesn't exist. It is intended to be silent
       return OGR_F_GetFieldIndex(self, name);
@@ -924,6 +946,16 @@ SWIGINTERN void OGRFeatureShadow_UnsetField__SWIG_1(OGRFeatureShadow *self,char
       else
           OGR_F_UnsetField(self, i);
   }
+SWIGINTERN void OGRFeatureShadow_SetFieldNull__SWIG_0(OGRFeatureShadow *self,int id){
+    OGR_F_SetFieldNull(self, id);
+  }
+SWIGINTERN void OGRFeatureShadow_SetFieldNull__SWIG_1(OGRFeatureShadow *self,char const *name){
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          OGR_F_SetFieldNull(self, i);
+  }
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_0(OGRFeatureShadow *self,int id,char const *value){
     OGR_F_SetFieldString(self, id, value);
   }
@@ -1067,6 +1099,11 @@ SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char
             case wkbCurvePolygon:
             case wkbMultiCurve:
             case wkbMultiSurface:
+            case wkbCurve:
+            case wkbSurface:
+            case wkbTriangle:
+            case wkbTIN:
+            case wkbPolyhedralSurface:
             case wkbNone:
             /*case wkbLinearRing:*/
             case wkbCircularStringZ:
@@ -1074,6 +1111,11 @@ SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char
             case wkbCurvePolygonZ:
             case wkbMultiCurveZ:
             case wkbMultiSurfaceZ:
+            case wkbCurveZ:
+            case wkbSurfaceZ:
+            case wkbTriangleZ:
+            case wkbTINZ:
+            case wkbPolyhedralSurfaceZ:
             case wkbPoint25D:
             case wkbLineString25D:
             case wkbPolygon25D:
@@ -1093,6 +1135,11 @@ SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char
             case wkbCurvePolygonM:
             case wkbMultiCurveM:
             case wkbMultiSurfaceM:
+            case wkbCurveM:
+            case wkbSurfaceM:
+            case wkbTriangleM:
+            case wkbTINM:
+            case wkbPolyhedralSurfaceM:
             case wkbPointZM:
             case wkbLineStringZM:
             case wkbPolygonZM:
@@ -1105,6 +1152,11 @@ SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char
             case wkbCurvePolygonZM:
             case wkbMultiCurveZM:
             case wkbMultiSurfaceZM:
+            case wkbCurveZM:
+            case wkbSurfaceZM:
+            case wkbTriangleZM:
+            case wkbTINZM:
+            case wkbPolyhedralSurfaceZM:
                 return TRUE;
             default:
                 CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
@@ -1625,6 +1677,9 @@ SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SymmetricDifference(OGRGeometryS
 SWIGINTERN double OGRGeometryShadow_Distance(OGRGeometryShadow *self,OGRGeometryShadow *other){
     return OGR_G_Distance(self, other);
   }
+SWIGINTERN double OGRGeometryShadow_Distance3D(OGRGeometryShadow *self,OGRGeometryShadow *other){
+    return OGR_G_Distance3D(self, other);
+  }
 SWIGINTERN void OGRGeometryShadow_Empty(OGRGeometryShadow *self){
     OGR_G_Empty(self);
   }
@@ -2122,6 +2177,26 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_ODsCMeasuredGeometries_get() {
 }
 
 
+SWIGEXPORT char * SWIGSTDCALL CSharp_ODsCRandomLayerRead_get() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  result = (char *)("RandomLayerRead");
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
+SWIGEXPORT char * SWIGSTDCALL CSharp_ODsCRandomLayerWrite_get() {
+  char * jresult ;
+  char *result = 0 ;
+  
+  result = (char *)("RandomLayerWrite");
+  jresult = SWIG_csharp_string_callback((const char *)result); 
+  return jresult;
+}
+
+
 SWIGEXPORT char * SWIGSTDCALL CSharp_ODrCCreateDataSource_get() {
   char * jresult ;
   char *result = 0 ;
@@ -7247,6 +7322,160 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldSet__SWIG_1(void * jar
 }
 
 
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldNull__SWIG_0(void * jarg1, int jarg2) {
+  unsigned int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  bool result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (bool)OGRFeatureShadow_IsFieldNull__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldNull__SWIG_1(void * jarg1, char * jarg2) {
+  unsigned int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  bool result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (bool)OGRFeatureShadow_IsFieldNull__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldSetAndNotNull__SWIG_0(void * jarg1, int jarg2) {
+  unsigned int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  bool result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    result = (bool)OGRFeatureShadow_IsFieldSetAndNotNull__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_Feature_IsFieldSetAndNotNull__SWIG_1(void * jarg1, char * jarg2) {
+  unsigned int jresult ;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  bool result;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (bool)OGRFeatureShadow_IsFieldSetAndNotNull__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT int SWIGSTDCALL CSharp_Feature_GetFieldIndex(void * jarg1, char * jarg2) {
   int jresult ;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
@@ -7504,6 +7733,75 @@ SWIGEXPORT void SWIGSTDCALL CSharp_Feature_UnsetField__SWIG_1(void * jarg1, char
 }
 
 
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldNull__SWIG_0(void * jarg1, int jarg2) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (int)jarg2; 
+  {
+    CPLErrorReset();
+    OGRFeatureShadow_SetFieldNull__SWIG_0(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
+SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetFieldNull__SWIG_1(void * jarg1, char * jarg2) {
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  
+  arg1 = (OGRFeatureShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return ; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    OGRFeatureShadow_SetFieldNull__SWIG_1(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+}
+
+
 SWIGEXPORT void SWIGSTDCALL CSharp_Feature_SetField__SWIG_0(void * jarg1, int jarg2, char * jarg3) {
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
   int arg2 ;
@@ -12641,6 +12939,48 @@ SWIGEXPORT double SWIGSTDCALL CSharp_Geometry_Distance(void * jarg1, void * jarg
 }
 
 
+SWIGEXPORT double SWIGSTDCALL CSharp_Geometry_Distance3D(void * jarg1, void * jarg2) {
+  double jresult ;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+  double result;
+  
+  arg1 = (OGRGeometryShadow *)jarg1; 
+  arg2 = (OGRGeometryShadow *)jarg2; 
+  {
+    if (!arg2) {
+      {
+        SWIG_CSharpException(SWIG_ValueError, "Received a NULL pointer."); return 0; 
+      };
+    }
+  }
+  {
+    CPLErrorReset();
+    result = (double)OGRGeometryShadow_Distance3D(arg1,arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT void SWIGSTDCALL CSharp_Geometry_Empty(void * jarg1) {
   OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
   
diff --git a/swig/csharp/ogr/osr_wrap.cpp b/swig/csharp/ogr/osr_wrap.cpp
index 71e4c46..7cb489f 100644
--- a/swig/csharp/ogr/osr_wrap.cpp
+++ b/swig/csharp/ogr/osr_wrap.cpp
@@ -505,6 +505,10 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnits(OSRSpatialReferenceSh
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnitsAndUpdateParameters(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
     return OSRSetLinearUnitsAndUpdateParameters( self, name, to_meters );
   }
+SWIGINTERN double OSRSpatialReferenceShadow_GetTargetLinearUnits(OSRSpatialReferenceShadow *self,char const *target_key){
+    // Return code ignored.
+    return OSRGetTargetLinearUnits( self, target_key, 0 );
+  }
 SWIGINTERN double OSRSpatialReferenceShadow_GetLinearUnits(OSRSpatialReferenceShadow *self){
     // Return code ignored.
     return OSRGetLinearUnits( self, 0 );
@@ -2084,6 +2088,41 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetLinearUnitsAndUpdateParame
 }
 
 
+SWIGEXPORT double SWIGSTDCALL CSharp_SpatialReference_GetTargetLinearUnits(void * jarg1, char * jarg2) {
+  double jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  double result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    CPLErrorReset();
+    result = (double)OSRSpatialReferenceShadow_GetTargetLinearUnits(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT double SWIGSTDCALL CSharp_SpatialReference_GetLinearUnits(void * jarg1) {
   double jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
diff --git a/swig/csharp/ogr/wkbGeometryType.cs b/swig/csharp/ogr/wkbGeometryType.cs
index f833bc2..5df317b 100644
--- a/swig/csharp/ogr/wkbGeometryType.cs
+++ b/swig/csharp/ogr/wkbGeometryType.cs
@@ -26,6 +26,7 @@ public enum wkbGeometryType {
   wkbSurface = 14,
   wkbPolyhedralSurface = 15,
   wkbTIN = 16,
+  wkbTriangle = 17,
   wkbNone = 100,
   wkbLinearRing = 101,
   wkbCircularStringZ = 1008,
@@ -37,6 +38,7 @@ public enum wkbGeometryType {
   wkbSurfaceZ = 1014,
   wkbPolyhedralSurfaceZ = 1015,
   wkbTINZ = 1016,
+  wkbTriangleZ = 1017,
   wkbPointM = 2001,
   wkbLineStringM = 2002,
   wkbPolygonM = 2003,
@@ -53,6 +55,7 @@ public enum wkbGeometryType {
   wkbSurfaceM = 2014,
   wkbPolyhedralSurfaceM = 2015,
   wkbTINM = 2016,
+  wkbTriangleM = 2017,
   wkbPointZM = 3001,
   wkbLineStringZM = 3002,
   wkbPolygonZM = 3003,
@@ -69,6 +72,7 @@ public enum wkbGeometryType {
   wkbSurfaceZM = 3014,
   wkbPolyhedralSurfaceZM = 3015,
   wkbTINZM = 3016,
+  wkbTriangleZM = 3017,
   wkbPoint25D = -2147483647,
   wkbLineString25D = -2147483646,
   wkbPolygon25D = -2147483645,
diff --git a/swig/csharp/osr/OsrPINVOKE.cs b/swig/csharp/osr/OsrPINVOKE.cs
index d24f39c..6f1ee04 100644
--- a/swig/csharp/osr/OsrPINVOKE.cs
+++ b/swig/csharp/osr/OsrPINVOKE.cs
@@ -304,6 +304,9 @@ class OsrPINVOKE {
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_SetLinearUnitsAndUpdateParameters")]
   public static extern int SpatialReference_SetLinearUnitsAndUpdateParameters(HandleRef jarg1, string jarg2, double jarg3);
 
+  [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_GetTargetLinearUnits")]
+  public static extern double SpatialReference_GetTargetLinearUnits(HandleRef jarg1, string jarg2);
+
   [DllImport("osr_wrap", EntryPoint="CSharp_SpatialReference_GetLinearUnits")]
   public static extern double SpatialReference_GetLinearUnits(HandleRef jarg1);
 
diff --git a/swig/csharp/osr/SpatialReference.cs b/swig/csharp/osr/SpatialReference.cs
index d6cb864..7a9dd18 100644
--- a/swig/csharp/osr/SpatialReference.cs
+++ b/swig/csharp/osr/SpatialReference.cs
@@ -198,6 +198,12 @@ public class SpatialReference : IDisposable {
     return ret;
   }
 
+  public double GetTargetLinearUnits(string target_key) {
+    double ret = OsrPINVOKE.SpatialReference_GetTargetLinearUnits(swigCPtr, target_key);
+    if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
+    return ret;
+  }
+
   public double GetLinearUnits() {
     double ret = OsrPINVOKE.SpatialReference_GetLinearUnits(swigCPtr);
     if (OsrPINVOKE.SWIGPendingException.Pending) throw OsrPINVOKE.SWIGPendingException.Retrieve();
diff --git a/swig/csharp/osr/osr_wrap.cpp b/swig/csharp/osr/osr_wrap.cpp
index 71e4c46..7cb489f 100644
--- a/swig/csharp/osr/osr_wrap.cpp
+++ b/swig/csharp/osr/osr_wrap.cpp
@@ -505,6 +505,10 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnits(OSRSpatialReferenceSh
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnitsAndUpdateParameters(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
     return OSRSetLinearUnitsAndUpdateParameters( self, name, to_meters );
   }
+SWIGINTERN double OSRSpatialReferenceShadow_GetTargetLinearUnits(OSRSpatialReferenceShadow *self,char const *target_key){
+    // Return code ignored.
+    return OSRGetTargetLinearUnits( self, target_key, 0 );
+  }
 SWIGINTERN double OSRSpatialReferenceShadow_GetLinearUnits(OSRSpatialReferenceShadow *self){
     // Return code ignored.
     return OSRGetLinearUnits( self, 0 );
@@ -2084,6 +2088,41 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SpatialReference_SetLinearUnitsAndUpdateParame
 }
 
 
+SWIGEXPORT double SWIGSTDCALL CSharp_SpatialReference_GetTargetLinearUnits(void * jarg1, char * jarg2) {
+  double jresult ;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  double result;
+  
+  arg1 = (OSRSpatialReferenceShadow *)jarg1; 
+  arg2 = (char *)jarg2; 
+  {
+    CPLErrorReset();
+    result = (double)OSRSpatialReferenceShadow_GetTargetLinearUnits(arg1,(char const *)arg2);
+    CPLErr eclass = CPLGetLastErrorType();
+    if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+      SWIG_CSharpException(SWIG_RuntimeError, CPLGetLastErrorMsg());
+      
+      
+      
+    }
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+  }
+  jresult = result; 
+  return jresult;
+}
+
+
 SWIGEXPORT double SWIGSTDCALL CSharp_SpatialReference_GetLinearUnits(void * jarg1) {
   double jresult ;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
diff --git a/swig/include/Band.i b/swig/include/Band.i
index 7e82cd7..cb49908 100644
--- a/swig/include/Band.i
+++ b/swig/include/Band.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Band.i 32928 2016-01-11 14:21:32Z rouault $
+ * $Id: Band.i 35453 2016-09-15 15:35:48Z rouault $
  *
  * Name:     Band.i
  * Project:  GDAL Python Interface
@@ -127,7 +127,7 @@ CPLErr ReadRaster_internal( GDALRasterBandShadow *obj,
   }
   else
   {
-    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate "CPL_FRMT_GIB" bytes", *buf_size);
+    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate " CPL_FRMT_GIB " bytes", *buf_size);
     result = CE_Failure;
     *buf = 0;
     *buf_size = 0;
@@ -199,6 +199,13 @@ public:
       GDALGetBlockSize(self, pnBlockXSize, pnBlockYSize);
   }
 
+#if defined(SWIGPYTHON)
+  void GetActualBlockSize(int nXBlockOff, int nYBlockOff, int* pnxvalid, int* pnyvalid, int* pisvalid)
+  {
+    *pisvalid = (GDALGetActualBlockSize(self, nXBlockOff, nYBlockOff, pnxvalid, pnyvalid) == CE_None);
+  }
+#endif
+
   // Preferred name to match C++ API
   /* Interface method added for GDAL 1.7.0 */
   GDALColorInterp GetColorInterpretation() {
@@ -676,6 +683,24 @@ CPLErr SetDefaultHistogram( double min, double max,
 
 #endif /* #if defined(SWIGPYTHON) */
 
+#if defined(SWIGPYTHON)
+    // Check with other bindings how to return both the integer status and
+    // *pdfDataPct
+
+    %apply (double *OUTPUT) {(double *)};
+    int GetDataCoverageStatus( int nXOff, int nYOff,
+                               int nXSize, int nYSize,
+                               int nMaskFlagStop = 0,
+                               double* pdfDataPct = NULL)
+    {
+        return GDALGetDataCoverageStatus(self, nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nMaskFlagStop,
+                                         pdfDataPct);
+    }
+    %clear (double *);
+#endif
+
 } /* %extend */
 
 };
diff --git a/swig/include/ColorTable.i b/swig/include/ColorTable.i
index fb3200c..c6cb204 100644
--- a/swig/include/ColorTable.i
+++ b/swig/include/ColorTable.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ColorTable.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: ColorTable.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     ColorTable.i
  * Project:  GDAL Python Interface
diff --git a/swig/include/Dataset.i b/swig/include/Dataset.i
index 5d79706..9b4ebe7 100644
--- a/swig/include/Dataset.i
+++ b/swig/include/Dataset.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Dataset.i 32935 2016-01-11 16:49:14Z rouault $
+ * $Id: Dataset.i 37423 2017-02-19 13:25:24Z rouault $
  *
  * Name:     Dataset.i
  * Project:  GDAL Python Interface
@@ -139,7 +139,7 @@ CPLErr DSReadRaster_internal( GDALDatasetShadow *obj,
   }
   else
   {
-    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate "CPL_FRMT_GIB" bytes", *buf_size);
+    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate " CPL_FRMT_GIB " bytes", *buf_size);
     result = CE_Failure;
     *buf = 0;
     *buf_size = 0;
@@ -199,7 +199,11 @@ static void DeleteAsyncReaderWrapper(GDALAsyncReaderWrapperH hWrapper)
 %}
 
 #if defined(SWIGPYTHON)
+
+%nothread;
+
 %{
+
 static GDALAsyncReaderWrapper* CreateAsyncReaderWrapper(GDALAsyncReaderH  hAsyncReader,
                                                         void             *pyObject)
 {
@@ -220,8 +224,10 @@ static void DisableAsyncReaderWrapper(GDALAsyncReaderWrapperH hWrapper)
     psWrapper->pyObject = NULL;
     psWrapper->hAsyncReader = NULL;
 }
-
 %}
+
+%thread;
+
 #endif
 
 class GDALAsyncReaderShadow {
@@ -611,8 +617,8 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
             else
             {
                 int nRes = 1 << nLevel;
-                buf_xsize = ceil(xSize / (1.0 * nRes));
-                buf_ysize = ceil(ySize / (1.0 * nRes));
+                buf_xsize = static_cast<int>(ceil(xSize / (1.0 * nRes)));
+                buf_ysize = static_cast<int>(ceil(ySize / (1.0 * nRes)));
             }
         }
     }
@@ -701,7 +707,7 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
                                       char** options = NULL )
     {
         int nPixelSpace;
-        GIntBig nBandSpace;
+        int nBandSpace;
         if( bIsBandSequential != 0 && bIsBandSequential != 1 )
             return NULL;
         if( band_list == 0 )
@@ -714,7 +720,7 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
         else
         {
             nBandSpace = GDALGetDataTypeSize(eBufType) / 8;
-            nPixelSpace  = nBandSpace * band_list;
+            nPixelSpace = nBandSpace * band_list;
         }
         CPLVirtualMem* vmem = GDALDatasetGetVirtualMem( self,
                                          eRWFlag,
@@ -843,6 +849,33 @@ CPLErr ReadRaster(  int xoff, int yoff, int xsize, int ysize,
     return layer;
   }
 
+  void ResetReading()
+  {
+    GDALDatasetResetReading( self );
+  }
+
+#ifdef SWIGPYTHON
+%newobject GetNextFeature;
+%feature( "kwargs" ) GetNextFeature;
+  OGRFeatureShadow* GetNextFeature( bool include_layer = true,
+                                    bool include_pct = false,
+                                    OGRLayerShadow** ppoBelongingLayer = NULL,
+                                    double* pdfProgressPct = NULL,
+                                    GDALProgressFunc callback = NULL,
+                                    void* callback_data=NULL )
+  {
+    return GDALDatasetGetNextFeature( self, ppoBelongingLayer, pdfProgressPct,
+                                      callback, callback_data );
+  }
+#else
+    // FIXME: return layer
+%newobject GetNextFeature;
+  OGRFeatureShadow* GetNextFeature()
+  {
+    return GDALDatasetGetNextFeature( self, NULL, NULL, NULL, NULL );
+  }
+#endif
+
   bool TestCapability(const char * cap) {
     return (GDALDatasetTestCapability(self, cap) > 0);
   }
diff --git a/swig/include/Driver.i b/swig/include/Driver.i
index 49cd1b6..2e4e699 100644
--- a/swig/include/Driver.i
+++ b/swig/include/Driver.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Driver.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: Driver.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     Driver.i
  * Project:  GDAL Python Interface
diff --git a/swig/include/MajorObject.i b/swig/include/MajorObject.i
index 8517182..2a89f1c 100644
--- a/swig/include/MajorObject.i
+++ b/swig/include/MajorObject.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: MajorObject.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: MajorObject.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  SWIG Definitions for GDALMajorObject.
diff --git a/swig/include/Operations.i b/swig/include/Operations.i
index 17ce7dc..50e27d0 100644
--- a/swig/include/Operations.i
+++ b/swig/include/Operations.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Operations.i 33447 2016-02-12 20:59:51Z goatbar $
+ * $Id: Operations.i 37723 2017-03-16 17:07:53Z rouault $
  *
  * Name:     Operations.i
  * Project:  GDAL Python Interface
@@ -693,3 +693,31 @@ public:
 
 } /*extend */
 };
+
+/************************************************************************/
+/*                        ApplyVerticalShiftGrid()                      */
+/************************************************************************/
+
+%newobject ApplyVerticalShiftGrid;
+%apply Pointer NONNULL {GDALDatasetShadow *src_ds, GDALDatasetShadow *grid_ds};
+#ifndef SWIGJAVA
+%feature( "kwargs" ) ApplyVerticalShiftGrid;
+#endif
+%inline %{
+GDALDatasetShadow* ApplyVerticalShiftGrid( GDALDatasetShadow *src_ds,
+                                           GDALDatasetShadow *grid_ds,
+                                           bool inverse = false,
+                                           double srcUnitToMeter = 1.0,
+                                           double dstUnitToMeter = 1.0,
+                                           char** options = NULL ) {
+  GDALDatasetShadow *ds = GDALApplyVerticalShiftGrid( src_ds, grid_ds,
+                                                      inverse,
+                                                      srcUnitToMeter,
+                                                      dstUnitToMeter,
+                                                      options );
+  return ds;
+
+}
+%}
+%clear GDALDatasetShadow *src_ds, GDALDatasetShadow *grid_ds;
+
diff --git a/swig/include/README.typemaps b/swig/include/README.typemaps
index d66310b..275168b 100644
--- a/swig/include/README.typemaps
+++ b/swig/include/README.typemaps
@@ -24,13 +24,13 @@ argout (int *nLen, char **pBuf) -
   type.  Typemap needs to deallocate memory.
   FrankW:  Should this be done with free?
 
-argout (char **argout ) - Required - 
+argout (char **argout ) - Required -
 
-argout (long *OUTPUT) - Required - 
+argout (long *OUTPUT) - Required -
 
 -------------------
 
-in (char **dict) - Required 
+in (char **dict) - Required
   Convert a native dictionary/hash type into name value pairs.
 
 in (char **ignorechange) - Required
@@ -66,10 +66,10 @@ directly calls AsString (i.e. str()) on the object.  This
 functionality could be reduced in other languages as long as it's
 documented.
 
-in (const char *utf8_path) - Optional - 
+in (const char *utf8_path) - Optional -
   Any inputs marked this way should be treated as utf-8, and if the language supports it
   a conversion should be applied.  For many languages the default (the fallback const char *
-  handler) will be sufficient. 
+  handler) will be sufficient.
 
 -------------------
 
@@ -86,7 +86,7 @@ out GDALColorEntry* - Return a GDALColorEntry from a function.
 out (IF_FALSE_RETURN_NONE) - Required - This is a typedef'd int.  Must support use in conjunction with
 argout typemaps.
 
-out OGRErr - 
+out OGRErr -
 
 out (char **CSL) - Required - The return value is a list that is copied
 into a list in the target language and then CSLDestroyed
diff --git a/swig/include/RasterAttributeTable.i b/swig/include/RasterAttributeTable.i
index 2104d2b..530f4c4 100644
--- a/swig/include/RasterAttributeTable.i
+++ b/swig/include/RasterAttributeTable.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ColorTable.i 11505 2007-05-13 17:25:26Z tamas $
+ * $Id: RasterAttributeTable.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     RAT.i
  * Project:  GDAL Python Interface
diff --git a/swig/include/Transform.i b/swig/include/Transform.i
index a687217..6fb410d 100644
--- a/swig/include/Transform.i
+++ b/swig/include/Transform.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: Transform.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: Transform.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  GDAL transformer related declarations.
diff --git a/swig/include/XMLNode.i b/swig/include/XMLNode.i
index 3ab41ad..e26d491 100644
--- a/swig/include/XMLNode.i
+++ b/swig/include/XMLNode.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: XMLNode.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: XMLNode.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Project:  GDAL SWIG Interface
  * Purpose:  GDAL XML SWIG Interface declarations.
diff --git a/swig/include/cpl.i b/swig/include/cpl.i
index 8605130..53959a8 100644
--- a/swig/include/cpl.i
+++ b/swig/include/cpl.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl.i 33758 2016-03-21 09:06:22Z rouault $
+ * $Id: cpl.i 37544 2017-03-01 18:36:56Z rouault $
  *
  * Name:     cpl.i
  * Project:  GDAL Python Interface
@@ -71,15 +71,21 @@ typedef char retStringAndCPLFree;
 
 #ifdef SWIGPYTHON
 
+%nothread;
+
 %{
 void CPL_STDCALL PyCPLErrorHandler(CPLErr eErrClass, int err_no, const char* pszErrorMsg)
 {
     void* user_data = CPLGetErrorHandlerUserData();
     PyObject *psArgs;
 
+    SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
     psArgs = Py_BuildValue("(iis)", eErrClass, err_no, pszErrorMsg );
     PyEval_CallObject( (PyObject*)user_data, psArgs);
     Py_XDECREF(psArgs);
+
+    SWIG_PYTHON_THREAD_END_BLOCK;
 }
 %}
 
@@ -99,11 +105,15 @@ void CPL_STDCALL PyCPLErrorHandler(CPLErr eErrClass, int err_no, const char* psz
   {
      void* user_data = CPLGetErrorHandlerUserData();
      if( user_data != NULL )
-       Py_XDECREF((PyObject*)user_data);
+     {
+         Py_XDECREF((PyObject*)user_data);
+     }
      CPLPopErrorHandler();
   }
 %}
 
+%thread;
+
 #else
 %inline %{
   CPLErr PushErrorHandler( char const * pszCallbackName = NULL ) {
@@ -361,10 +371,25 @@ GByte *CPLHexToBinary( const char *pszHex, int *pnBytes );
 
 %apply Pointer NONNULL {const char * pszFilename};
 /* Added in GDAL 1.7.0 */
-#ifdef SWIGJAVA
+
+#if defined(SWIGPYTHON)
+
+%apply (GIntBig nLen, char *pBuf) {( GIntBig nBytes, const GByte *pabyData )};
+%inline {
+void wrapper_VSIFileFromMemBuffer( const char* utf8_path, GIntBig nBytes, const GByte *pabyData)
+{
+    const size_t nSize = static_cast<size_t>(nBytes);
+    GByte* pabyDataDup = (GByte*)VSIMalloc(nSize);
+    if (pabyDataDup == NULL)
+            return;
+    memcpy(pabyDataDup, pabyData, nSize);
+    VSIFCloseL(VSIFileFromMemBuffer(utf8_path, (GByte*) pabyDataDup, nSize, TRUE));
+}
+}
+%clear ( GIntBig nBytes, const GByte *pabyData );
+#else
+#if defined(SWIGJAVA)
 %apply (int nLen, unsigned char *pBuf ) {( int nBytes, const GByte *pabyData )};
-#elif defined(SWIGPYTHON)
-%apply (int nLen, char *pBuf) {( int nBytes, const GByte *pabyData )};
 #endif
 %inline {
 void wrapper_VSIFileFromMemBuffer( const char* utf8_path, int nBytes, const GByte *pabyData)
@@ -377,9 +402,10 @@ void wrapper_VSIFileFromMemBuffer( const char* utf8_path, int nBytes, const GByt
 }
 
 }
-#if defined(SWIGJAVA) || defined(SWIGPYTHON)
+#if defined(SWIGJAVA)
 %clear ( int nBytes, const GByte *pabyData );
 #endif
+#endif
 
 /* Added in GDAL 1.7.0 */
 VSI_RETVAL VSIUnlink(const char * utf8_path );
@@ -509,6 +535,14 @@ VSI_RETVAL VSIFCloseL( VSILFILE* fp );
 int     VSIFSeekL( VSILFILE* fp, GIntBig offset, int whence);
 GIntBig    VSIFTellL( VSILFILE* fp );
 int     VSIFTruncateL( VSILFILE* fp, GIntBig length );
+
+int     VSISupportsSparseFiles( const char* utf8_path );
+
+#define VSI_RANGE_STATUS_UNKNOWN    0
+#define VSI_RANGE_STATUS_DATA       1
+#define VSI_RANGE_STATUS_HOLE       2
+
+int     VSIFGetRangeStatusL( VSILFILE* fp, GIntBig offset, GIntBig length );
 #else
 VSI_RETVAL VSIFSeekL( VSILFILE* fp, long offset, int whence);
 long    VSIFTellL( VSILFILE* fp );
@@ -520,12 +554,12 @@ VSI_RETVAL VSIFTruncateL( VSILFILE* fp, long length );
 %inline {
 int wrapper_VSIFWriteL( int nLen, char *pBuf, int size, int memb, VSILFILE* fp)
 {
-    if (nLen < size * memb)
+    if (nLen < static_cast<GIntBig>(size) * memb)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Inconsistent buffer size with 'size' and 'memb' values");
         return 0;
     }
-    return VSIFWriteL(pBuf, size, memb, fp);
+    return static_cast<int>(VSIFWriteL(pBuf, size, memb, fp));
 }
 }
 #elif defined(SWIGPERL)
diff --git a/swig/include/cpl_exceptions.i b/swig/include/cpl_exceptions.i
index 11abd66..9c35b58 100644
--- a/swig/include/cpl_exceptions.i
+++ b/swig/include/cpl_exceptions.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: cpl_exceptions.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: cpl_exceptions.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Code for Optional Exception Handling through UseExceptions(),
  * DontUseExceptions()
diff --git a/swig/include/csharp/gdal_csharp.i b/swig/include/csharp/gdal_csharp.i
index 169b682..a19ac07 100644
--- a/swig/include/csharp/gdal_csharp.i
+++ b/swig/include/csharp/gdal_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_csharp.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: gdal_csharp.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     gdal_csharp.i
  * Project:  GDAL CSharp Interface
diff --git a/swig/include/csharp/gdal_csharp_extend.i b/swig/include/csharp/gdal_csharp_extend.i
index 70ca565..d0ce051 100644
--- a/swig/include/csharp/gdal_csharp_extend.i
+++ b/swig/include/csharp/gdal_csharp_extend.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_csharp_extend.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: gdal_csharp_extend.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     gdal_csharp_extend.i
  * Project:  GDAL CSharp Interface
diff --git a/swig/include/csharp/gnm_csharp.i b/swig/include/csharp/gnm_csharp.i
new file mode 100644
index 0000000..32a46b5
--- /dev/null
+++ b/swig/include/csharp/gnm_csharp.i
@@ -0,0 +1,14 @@
+/******************************************************************************
+ * $Id: gnm_csharp.i 34525 2016-07-03 02:53:47Z goatbar $
+******************************************************************************/
+
+%include cpl_exceptions.i
+
+%rename (RegisterAll) OGRRegisterAll();
+
+%include typemaps_csharp.i
+
+DEFINE_EXTERNAL_CLASS(OSRSpatialReferenceShadow, OSGeo.OSR.SpatialReference)
+DEFINE_EXTERNAL_CLASS(OSRCoordinateTransformationShadow, OSGeo.OSR.CoordinateTransformation)
+DEFINE_EXTERNAL_CLASS(GDALMajorObjectShadow, OSGeo.GDAL.MajorObject)
+
diff --git a/swig/include/csharp/ogr_csharp.i b/swig/include/csharp/ogr_csharp.i
index 1427bd0..23587cf 100644
--- a/swig/include/csharp/ogr_csharp.i
+++ b/swig/include/csharp/ogr_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_csharp.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: ogr_csharp.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     ogr_csharp.i
  * Project:  GDAL CSharp Interface
diff --git a/swig/include/csharp/ogr_csharp_extend.i b/swig/include/csharp/ogr_csharp_extend.i
index 09f1951..15c0887 100644
--- a/swig/include/csharp/ogr_csharp_extend.i
+++ b/swig/include/csharp/ogr_csharp_extend.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_csharp_extend.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: ogr_csharp_extend.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     ogr_csharp_extend.i
  * Project:  GDAL CSharp Interface
diff --git a/swig/include/csharp/osr_csharp.i b/swig/include/csharp/osr_csharp.i
index a14abff..1d47505 100644
--- a/swig/include/csharp/osr_csharp.i
+++ b/swig/include/csharp/osr_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr_csharp.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: osr_csharp.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     osr_csharp.i
  * Project:  GDAL CSharp Interface
diff --git a/swig/include/csharp/swig_csharp_extensions.i b/swig/include/csharp/swig_csharp_extensions.i
index 3a2692d..b93f596 100644
--- a/swig/include/csharp/swig_csharp_extensions.i
+++ b/swig/include/csharp/swig_csharp_extensions.i
@@ -1,6 +1,6 @@
 
 /******************************************************************************
- * $Id: swig_csharp_extensions.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: swig_csharp_extensions.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     swig_csharp_extensions.i
  * Purpose:  Fix for the SWIG Interface problems (early GC)
diff --git a/swig/include/csharp/typemaps_csharp.i b/swig/include/csharp/typemaps_csharp.i
index aa49cea..dd603bd 100644
--- a/swig/include/csharp/typemaps_csharp.i
+++ b/swig/include/csharp/typemaps_csharp.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_csharp.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: typemaps_csharp.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     typemaps_csharp.i
  * Project:  GDAL CSharp Interface
diff --git a/swig/include/gdal.i b/swig/include/gdal.i
index eedb847..b8190b5 100644
--- a/swig/include/gdal.i
+++ b/swig/include/gdal.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal.i 33758 2016-03-21 09:06:22Z rouault $
+ * $Id: gdal.i 35668 2016-10-09 20:52:50Z rouault $
  *
  * Name:     gdal.i
  * Project:  GDAL Python Interface
@@ -80,10 +80,12 @@ typedef void GDALAsyncReaderShadow;
 #ifdef DEBUG
 typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
 typedef struct OGRLayerHS OGRLayerShadow;
+typedef struct OGRFeatureHS OGRFeatureShadow;
 typedef struct OGRGeometryHS OGRGeometryShadow;
 #else
 typedef void OSRSpatialReferenceShadow;
 typedef void OGRLayerShadow;
+typedef void OGRFeatureShadow;
 typedef void OGRGeometryShadow;
 #endif
 typedef struct OGRStyleTableHS OGRStyleTableShadow;
@@ -858,6 +860,30 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
 %}
 %clear char **papszSiblings;
 
+
+%apply (char **options) {char** allowed_drivers};
+%apply (char **options) {char** sibling_files};
+
+#ifndef SWIGJAVA
+%feature( "kwargs" ) IdentifyDriverEx;
+#endif
+%inline %{
+GDALDriverShadow *IdentifyDriverEx( const char* utf8_path,
+                                    unsigned int nIdentifyFlags = 0,
+                                    char** allowed_drivers = NULL,
+                                    char** sibling_files = NULL )
+{
+    return  (GDALDriverShadow *) GDALIdentifyDriverEx( utf8_path,
+                                                nIdentifyFlags,
+                                                allowed_drivers,
+                                                sibling_files );
+}
+%}
+
+%clear char **allowed_drivers;
+%clear char **sibling_files;
+
+
 //************************************************************************
 //
 // Define Algorithms
diff --git a/swig/include/gdal_array.i b/swig/include/gdal_array.i
index d076853..3565f9c 100644
--- a/swig/include/gdal_array.i
+++ b/swig/include/gdal_array.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_array.i 33792 2016-03-26 12:54:28Z goatbar $
+ * $Id: gdal_array.i 37276 2017-02-02 14:56:32Z rouault $
  *
  * Name:     gdal_array.i
  * Project:  GDAL Python Interface
@@ -32,6 +32,18 @@
 
 %module gdal_array
 
+%{
+// Define this unconditionnaly of whether DEBUG_BOOL is defined or not,
+// since we do not pass -DDEBUG_BOOL when building the bindings
+#define DO_NOT_USE_DEBUG_BOOL
+
+// So that override is properly defined
+#ifndef GDAL_COMPILATION
+#define GDAL_COMPILATION
+#endif
+
+%}
+
 %include constraints.i
 
 %import typemaps_python.i
@@ -98,16 +110,16 @@ class NUMPYDataset : public GDALDataset
                  NUMPYDataset();
                  ~NUMPYDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) override;
 
     static GDALDataset *Open( PyArrayObject *psArray );
     static GDALDataset *Open( GDALOpenInfo * );
@@ -179,7 +191,13 @@ NUMPYDataset::~NUMPYDataset()
     }
 
     FlushCache();
+
+    // Although the module has thread disabled, we go here from GDALClose()
+    SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
     Py_DECREF( psArray );
+
+    SWIG_PYTHON_THREAD_END_BLOCK;
 }
 
 /************************************************************************/
@@ -312,7 +330,8 @@ GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    if( !CSLTestBoolean(CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME", "FALSE")) )
+    if( !CPLTestBool(CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME",
+                                        "FALSE")) )
     {
         if( CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME", NULL) == NULL )
         {
@@ -438,20 +457,36 @@ GDALDataset* NUMPYDataset::Open( PyArrayObject *psArray )
 
     if( psArray->nd == 3 )
     {
-        nBands = psArray->dimensions[0];
+        if( psArray->dimensions[0] > INT_MAX ||
+            psArray->dimensions[1] > INT_MAX ||
+            psArray->dimensions[2] > INT_MAX ||
+            !GDALCheckBandCount(static_cast<int>(psArray->dimensions[0]), 0) )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Too big array dimensions");
+            delete poDS;
+            return NULL;
+        }
+        nBands = static_cast<int>(psArray->dimensions[0]);
         nBandOffset = psArray->strides[0];
-        poDS->nRasterXSize = psArray->dimensions[2];
+        poDS->nRasterXSize = static_cast<int>(psArray->dimensions[2]);
         nPixelOffset = psArray->strides[2];
-        poDS->nRasterYSize = psArray->dimensions[1];
+        poDS->nRasterYSize = static_cast<int>(psArray->dimensions[1]);
         nLineOffset = psArray->strides[1];
     }
     else
     {
+        if( psArray->dimensions[0] > INT_MAX ||
+            psArray->dimensions[1] > INT_MAX )
+        {
+            delete poDS;
+            return NULL;
+        }
         nBands = 1;
         nBandOffset = 0;
-        poDS->nRasterXSize = psArray->dimensions[1];
+        poDS->nRasterXSize = static_cast<int>(psArray->dimensions[1]);
         nPixelOffset = psArray->strides[1];
-        poDS->nRasterYSize = psArray->dimensions[0];
+        poDS->nRasterYSize = static_cast<int>(psArray->dimensions[0]);
         nLineOffset = psArray->strides[0];
     }
 
@@ -476,6 +511,12 @@ GDALDataset* NUMPYDataset::Open( PyArrayObject *psArray )
 
 %}
 
+
+#ifdef SWIGPYTHON
+%nothread;
+#endif
+
+
 // So that SWIGTYPE_p_f_double_p_q_const__char_p_void__int is declared...
 /************************************************************************/
 /*                            TermProgress()                            */
@@ -527,11 +568,15 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     GDALRegister_NUMPY();
 
     /* I wish I had a safe way of checking the type */
-    sprintf( szString, "NUMPY:::%p", psArray );
+    snprintf( szString, sizeof(szString), "NUMPY:::%p", psArray );
     return CPLStrdup(szString);
 }
 %}
 
+#ifdef SWIGPYTHON
+%thread;
+#endif
+
 %feature( "kwargs" ) BandRasterIONumPy;
 %inline %{
   CPLErr BandRasterIONumPy( GDALRasterBandShadow* band, int bWrite, double xoff, double yoff, double xsize, double ysize,
@@ -553,9 +598,17 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     int xdim = ( psArray->nd == 2) ? 1 : 2;
     int ydim = ( psArray->nd == 2) ? 0 : 1;
 
-    int nxsize, nysize, pixel_space, line_space;
-    nxsize = psArray->dimensions[xdim];
-    nysize = psArray->dimensions[ydim];
+    if( psArray->dimensions[xdim] > INT_MAX ||
+        psArray->dimensions[ydim] > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "Too big array dimensions");
+        return CE_Failure;
+    }
+    int nxsize, nysize;
+    GSpacing pixel_space, line_space;
+    nxsize = static_cast<int>(psArray->dimensions[xdim]);
+    nysize = static_cast<int>(psArray->dimensions[ydim]);
     pixel_space = psArray->strides[xdim];
     line_space = psArray->strides[ydim];
 
@@ -604,12 +657,20 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
 
     int xdim = 2;
     int ydim = 1;
+    if( psArray->dimensions[xdim] > INT_MAX ||
+        psArray->dimensions[ydim] > INT_MAX ||
+        psArray->dimensions[0] > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "Too big array dimensions");
+        return CE_Failure;
+    }
 
     int bandsize, nxsize, nysize;
     GIntBig pixel_space, line_space, band_space;
-    nxsize = psArray->dimensions[xdim];
-    nysize = psArray->dimensions[ydim];
-    bandsize = psArray->dimensions[0];
+    nxsize = static_cast<int>(psArray->dimensions[xdim]);
+    nysize = static_cast<int>(psArray->dimensions[ydim]);
+    bandsize = static_cast<int>(psArray->dimensions[0]);
     if( bandsize != GDALGetRasterCount(ds) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -635,6 +696,10 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
   }
 %}
 
+#ifdef SWIGPYTHON
+%nothread;
+#endif
+
 %typemap(in,numinputs=0) (CPLVirtualMemShadow** pvirtualmem, int numpytypemap) (CPLVirtualMemShadow* virtualmem)
 {
   $1 = &virtualmem;
@@ -741,8 +806,8 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     }
     else
     {
-        int nTilesPerRow = (nBufXSize + nTileXSize - 1) / nTileXSize;
-        int nTilesPerCol = (nBufYSize + nTileYSize - 1) / nTileYSize;
+        npy_intp nTilesPerRow = static_cast<npy_intp>((nBufXSize + nTileXSize - 1) / nTileXSize);
+        npy_intp nTilesPerCol = static_cast<npy_intp>((nBufYSize + nTileYSize - 1) / nTileYSize);
         npy_intp shape[5], stride[5];
         if( nBandCount == 1 )
         {
@@ -835,8 +900,14 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
                   PyArray_NDIM(psArray) );
         return CE_Failure;
     }
+    if( PyArray_DIM(psArray, 0) > INT_MAX )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Too big array dimension");
+        return CE_Failure;
+    }
 
-    int nLength = PyArray_DIM(psArray, 0);
+    int nLength = static_cast<int>(PyArray_DIM(psArray, 0));
     int nType = PyArray_TYPE(psArray);
     CPLErr retval = CE_None;
 
@@ -938,7 +1009,7 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
         {
             // note strlen doesn't include null char
             // but that is what numpy expects so all good
-            nLen = strlen(papszStringList[n]);
+            nLen = static_cast<int>(strlen(papszStringList[n]));
             if( nLen > nMaxLen )
                 nMaxLen = nLen;
         }
@@ -994,7 +1065,7 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
 
 %pythoncode %{
 import numpy
-import _gdal_array
+from . import _gdal_array
 
 import gdalconst
 import gdal
@@ -1330,3 +1401,7 @@ def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
 
     return
 %}
+
+#ifdef SWIGPYTHON
+%thread;
+#endif
diff --git a/swig/include/gdal_typemaps.i b/swig/include/gdal_typemaps.i
index f2792ef..59912be 100644
--- a/swig/include/gdal_typemaps.i
+++ b/swig/include/gdal_typemaps.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_typemaps.i 10967 2007-03-15 20:04:37Z warmerdam $
+ * $Id: gdal_typemaps.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     typemaps.i
  * Project:  GDAL Typemap library
diff --git a/swig/include/gdalconst.i b/swig/include/gdalconst.i
index a5338f2..d1d36bc 100644
--- a/swig/include/gdalconst.i
+++ b/swig/include/gdalconst.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalconst.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: gdalconst.i 35418 2016-09-13 13:37:01Z rouault $
  *
  * Name:     gdalconst.i
  * Project:  GDAL Python Interface
@@ -28,6 +28,10 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#ifdef SWIGPYTHON
+%nothread;
+#endif
+
 #ifdef PERL_CPAN_NAMESPACE
 %module "Geo::GDAL::Const"
 #elif defined(SWIGCSHARP)
@@ -237,6 +241,10 @@
 %constant GMF_ALPHA               = 0x04;
 %constant GMF_NODATA              = 0x08;
 
+%constant GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED  = 0x01;
+%constant GDAL_DATA_COVERAGE_STATUS_DATA           = 0x02;
+%constant GDAL_DATA_COVERAGE_STATUS_EMPTY          = 0x04;
+
 // GDALAsyncStatusType
 %constant GARIO_PENDING = GARIO_PENDING;
 %constant GARIO_UPDATE = GARIO_UPDATE;
@@ -248,3 +256,7 @@
 %constant GTO_BIT = GTO_BIT;
 %constant GTO_BSQ = GTO_BSQ;
 
+
+#ifdef SWIGPYTHON
+%thread;
+#endif
diff --git a/swig/include/gnm.i b/swig/include/gnm.i
index f6ef5e0..e4020c0 100644
--- a/swig/include/gnm.i
+++ b/swig/include/gnm.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id$
+ * $Id: gnm.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Project:  GNM Core SWIG Interface declarations.
  * Purpose:  GNM declarations.
@@ -29,9 +29,9 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
-//#ifndef FROM_GDAL_I
+#ifndef FROM_GDAL_I
 %include "exception.i"
-//#endif
+#endif
 %include constraints.i
 
 #ifdef PERL_CPAN_NAMESPACE
@@ -55,28 +55,51 @@
 #endif
 
 %{
+#include <iostream>
+using namespace std;
+
 #include "gdal.h"
+#include "ogr_api.h"
+#include "ogr_p.h"
+#include "ogr_core.h"
+#include "cpl_port.h"
+#include "cpl_string.h"
+#include "ogr_srs_api.h"
 #include "gnm_api.h"
 
 typedef void GDALMajorObjectShadow;
 typedef void GNMNetworkShadow;
 typedef void GNMGenericNetworkShadow;
-%}
 
-#if defined(SWIGPYTHON) || defined(SWIGJAVA) || defined(SWIGPERL)
-%{
 #ifdef DEBUG
+typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
+typedef struct OGRDriverHS OGRDriverShadow;
+typedef struct OGRDataSourceHS OGRDataSourceShadow;
+#endif
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRFeatureHS OGRFeatureShadow;
-typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+typedef struct OGRFeatureDefnHS OGRFeatureDefnShadow;
+typedef struct OGRGeometryHS OGRGeometryShadow;
+typedef struct OGRCoordinateTransformationHS OSRCoordinateTransformationShadow;
+typedef struct OGRCoordinateTransformationHS OGRCoordinateTransformationShadow;
+typedef struct OGRFieldDefnHS OGRFieldDefnShadow;
 #else
+typedef void OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
+typedef void OGRDriverShadow;
+typedef void OGRDataSourceShadow;
+#endif
 typedef void OGRLayerShadow;
 typedef void OGRFeatureShadow;
-typedef void OSRSpatialReferenceShadow;
+typedef void OGRFeatureDefnShadow;
+typedef void OGRGeometryShadow;
+typedef void OSRCoordinateTransformationShadow;
+typedef void OGRFieldDefnShadow;
 #endif
+typedef struct OGRStyleTableHS OGRStyleTableShadow;
+typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
 %}
-#endif /* #if defined(SWIGPYTHON) || defined(SWIGJAVA) */
-
 
 #if defined(SWIGPYTHON)
 %include python_exceptions.i
@@ -89,7 +112,7 @@ typedef void OSRSpatialReferenceShadow;
 #elif defined(SWIGCSHARP)
 //%include gnm_csharp.i
 #elif defined(SWIGJAVA)
-//%include gnm_java.i
+%include gnm_java.i
 #elif defined(SWIGPERL)
 //%include gnm_perl.i
 %import typemaps_perl.i
@@ -97,15 +120,28 @@ typedef void OSRSpatialReferenceShadow;
 %include gdal_typemaps.i
 #endif
 
-typedef int CPLErr;
+#define FROM_OGR_I
+%import ogr.i
+
+
 typedef int GNMDirection;
+typedef int CPLErr;
 
 //************************************************************************
 //
 // Define the MajorObject object
 //
 //************************************************************************
-%include "MajorObject.i"
+#if defined(SWIGPYTHON)
+%{
+#include "gdal.h"
+%}
+#define FROM_PYTHON_OGR_I
+%include MajorObject.i
+#undef FROM_PYTHON_OGR_I
+#else /* defined(SWIGPYTHON) */
+%import MajorObject.i
+#endif /* defined(SWIGPYTHON) */
 
 %feature("autodoc");
 
@@ -123,6 +159,7 @@ typedef enum
 #define GNM_EDGE_DIR_SRCTOTGT   1   // from source to target
 #define GNM_EDGE_DIR_TGTTOSRC   2   // from target to source
 
+#ifndef SWIGJAVA
 %inline %{
   GNMNetworkShadow* CastToNetwork(GDALMajorObjectShadow* base) {
       return (GNMNetworkShadow*)dynamic_cast<GNMNetwork*>((GDALMajorObject*)base);
@@ -134,11 +171,6 @@ typedef enum
       return (GNMGenericNetworkShadow*)dynamic_cast<GNMGenericNetwork*>((GDALMajorObject*)base);
   }
 %}
-
-#if !defined(FROM_GDAL_I) && !defined(FROM_OGR_I)
-%inline %{
-typedef char retStringAndCPLFree;
-%}
 #endif
 
 /************************************************************************/
@@ -162,11 +194,13 @@ class GNMNetworkShadow : public GDALMajorObjectShadow
             }
         }
 
+#ifndef SWIGJAVA
         %apply SWIGTYPE *DISOWN {OGRLayerShadow *layer};
         void ReleaseResultSet(OGRLayerShadow *layer){
             GDALDatasetReleaseResultSet(self, layer);
         }
         %clear OGRLayerShadow *layer;
+#endif
 
         int GetVersion()
         {
@@ -381,4 +415,3 @@ class GNMGenericNetworkShadow : public GNMNetworkShadow
         }
     }
 };
-
diff --git a/swig/include/java/gdal_java.i b/swig/include/java/gdal_java.i
index b2c9c9c..e1e9c7f 100644
--- a/swig/include/java/gdal_java.i
+++ b/swig/include/java/gdal_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdal_java.i 33123 2016-01-23 18:59:28Z rouault $
+ * $Id: gdal_java.i 35649 2016-10-08 10:16:30Z rouault $
  *
  * Name:     gdal_java.i
  * Project:  GDAL SWIG Interface
@@ -41,6 +41,7 @@ import org.gdal.osr.SpatialReference;
 import org.gdal.ogr.Geometry;
 import org.gdal.ogr.StyleTable;
 import org.gdal.ogr.Layer;
+import org.gdal.ogr.Feature;
 %}
 
 %pragma(java) moduleimports=%{
@@ -48,6 +49,7 @@ import org.gdal.osr.SpatialReference;
 import org.gdal.ogr.Geometry;
 import org.gdal.ogr.StyleTable;
 import org.gdal.ogr.Layer;
+import org.gdal.ogr.Feature;
 %}
 
 %typemap(javaimports) GDALDatasetShadow %{
@@ -55,6 +57,7 @@ import org.gdal.osr.SpatialReference;
 import org.gdal.ogr.Geometry;
 import org.gdal.ogr.StyleTable;
 import org.gdal.ogr.Layer;
+import org.gdal.ogr.Feature;
 %}
 
 
diff --git a/swig/include/java/gdalconst_java.i b/swig/include/java/gdalconst_java.i
index 87cb963..704c948 100644
--- a/swig/include/java/gdalconst_java.i
+++ b/swig/include/java/gdalconst_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalconst_java.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: gdalconst_java.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     gdalconst_java.i
  * Project:  GDAL SWIG Interface
diff --git a/swig/include/java/gnm_java.i b/swig/include/java/gnm_java.i
new file mode 100644
index 0000000..fc0425f
--- /dev/null
+++ b/swig/include/java/gnm_java.i
@@ -0,0 +1,130 @@
+/******************************************************************************
+ * $Id: gnm_java.i 34525 2016-07-03 02:53:47Z goatbar $
+ *
+ * Project:  GNM Core SWIG Interface declarations.
+ * Purpose:  GNM declarations.
+ * Authors:  Mikhail Gusev (gusevmihs at gmail dot com)
+ *           Dmitry Baryshnikov, polimax at mail.ru
+ *
+ ******************************************************************************
+ * Copyright (c) 2016, Dmitry Baryshnikov
+ * Copyright (c) 2016, NextGIS <info at nextgis.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+#ifndef FROM_GDAL_I
+%include java_exceptions.i
+#endif
+
+%pragma(java) jniclasscode=%{
+  private static boolean available = false;
+
+  static {
+    try {
+      System.loadLibrary("gnmjni");
+      available = true;
+
+      if (org.gdal.gdal.gdal.HasThreadSupport() == 0)
+      {
+        System.err.println("WARNING : GDAL should be compiled with thread support for safe execution in Java.");
+      }
+
+    } catch (UnsatisfiedLinkError e) {
+      available = false;
+      System.err.println("Native library load failed.");
+      System.err.println(e);
+    }
+  }
+
+  public static boolean isAvailable() {
+    return available;
+  }
+%}
+
+%pragma(java) jniclassimports=%{
+import org.gdal.osr.SpatialReference;
+import org.gdal.osr.CoordinateTransformation;
+import org.gdal.gdal.MajorObject;
+import org.gdal.ogr.Geometry;
+import org.gdal.ogr.Feature;
+import org.gdal.ogr.StyleTable;
+import org.gdal.ogr.Layer;
+%}
+
+%pragma(java) moduleimports=%{
+import org.gdal.osr.SpatialReference;
+import org.gdal.gdal.MajorObject;
+import org.gdal.ogr.Geometry;
+import org.gdal.ogr.Feature;
+import org.gdal.ogr.StyleTable;
+import org.gdal.ogr.Layer;
+%}
+
+%typemap(javaimports) GNMNetworkShadow %{
+import org.gdal.osr.SpatialReference;
+import org.gdal.gdal.MajorObject;
+import org.gdal.ogr.Geometry;
+import org.gdal.ogr.Feature;
+import org.gdal.ogr.StyleTable;
+import org.gdal.ogr.Layer;
+%}
+
+%typemap(javaimports) GNMGenericNetworkShadow %{
+import org.gdal.osr.SpatialReference;
+import org.gdal.gdal.MajorObject;
+import org.gdal.ogr.Geometry;
+import org.gdal.ogr.Feature;
+import org.gdal.ogr.StyleTable;
+import org.gdal.ogr.Layer;
+%}
+
+%typemap(javacode) GNMNetworkShadow %{
+
+  public boolean equals(Object obj) {
+    boolean equal = false;
+    if (obj instanceof $javaclassname)
+      equal = ((($javaclassname)obj).swigCPtr == this.swigCPtr);
+    return equal;
+  }
+
+  public int hashCode() {
+     return (int)swigCPtr;
+  }
+%}
+
+%typemap(javacode) GNMGenericNetworkShadow %{
+
+  public boolean equals(Object obj) {
+    boolean equal = false;
+    if (obj instanceof $javaclassname)
+      equal = ((($javaclassname)obj).swigCPtr == this.swigCPtr);
+    return equal;
+  }
+
+  public int hashCode() {
+     return (int)swigCPtr;
+  }
+%}
+
+#ifndef FROM_GDAL_I
+%include callback.i
+#endif
+
+%include typemaps_java.i
\ No newline at end of file
diff --git a/swig/include/java/ogr_java.i b/swig/include/java/ogr_java.i
index 46ae178..01bd1ab 100644
--- a/swig/include/java/ogr_java.i
+++ b/swig/include/java/ogr_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_java.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: ogr_java.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     ogr_java.i
  * Project:  GDAL SWIG Interface
diff --git a/swig/include/java/ogr_java_extend.i b/swig/include/java/ogr_java_extend.i
index de8dce3..61e0491 100644
--- a/swig/include/java/ogr_java_extend.i
+++ b/swig/include/java/ogr_java_extend.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_java_extend.i 10639 2007-01-17 20:57:32Z tamas $
+ * $Id: ogr_java_extend.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     ogr_java_extend.i
  * Project:  GDAL SWIG Interface
diff --git a/swig/include/java/osr_java.i b/swig/include/java/osr_java.i
index 5241acc..bd0644e 100644
--- a/swig/include/java/osr_java.i
+++ b/swig/include/java/osr_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr_java.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: osr_java.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     osr_java.i
  * Project:  GDAL SWIG Interface
diff --git a/swig/include/java/typemaps_java.i b/swig/include/java/typemaps_java.i
index 96fd116..fa79fe0 100644
--- a/swig/include/java/typemaps_java.i
+++ b/swig/include/java/typemaps_java.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_java.i 34011 2016-04-18 16:22:21Z rouault $
+ * $Id: typemaps_java.i 37359 2017-02-12 19:40:53Z rouault $
  *
  * Name:     typemaps_java.i
  * Project:  GDAL SWIG Interface
@@ -643,7 +643,7 @@
  *  Java typemaps for (int* pnList, int** ppListOut)
  *
  ***************************************************/
-%typemap(in) (int* pnList, int** ppListOut) (int nLen, int* pBuf)
+%typemap(in) (int* pnList, int** ppListOut) (int nLen = 0, int* pBuf = NULL)
 {
   /* %typemap(in) (int* pnList, int** ppListOut) */
   $1 = &nLen;
diff --git a/swig/include/ogr.i b/swig/include/ogr.i
index 8deeeed..e90ebf1 100644
--- a/swig/include/ogr.i
+++ b/swig/include/ogr.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr.i 34224 2016-05-13 06:04:34Z ajolma $
+ * $Id: ogr.i 37371 2017-02-13 11:41:59Z rouault $
  *
  * Project:  OGR Core SWIG Interface declarations.
  * Purpose:  OGR declarations.
@@ -27,6 +27,10 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#ifdef SWIGPYTHON
+%nothread;
+#endif
+
 #ifndef FROM_GDAL_I
 %include "exception.i"
 #endif
@@ -99,6 +103,8 @@ typedef enum
                                *   ISO SQL/MM Part 3. GDAL >= 2.1 */
     wkbTIN = 16,              /**< a PolyhedralSurface consisting only of Triangle patches
                                *    ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbTriangle = 17,       /**< A Triangle is a polygon with 3 distinct, non-collinear vertices and no
+                                 interior boundary. GDAL >= 2.2 */
 
     wkbNone = 100,          /**< non-standard, for pure attribute records */
     wkbLinearRing = 101,    /**< non-standard, just for createGeometry() */
@@ -112,6 +118,7 @@ typedef enum
     wkbSurfaceZ = 1014,         /**< wkbSurface with Z component. ISO SQL/MM Part 3. GDAL >= 2.0 */
     wkbPolyhedralSurfaceZ = 1015,  /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
     wkbTINZ = 1016,                /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbTriangleZ = 1017,         /**< wkbTriangle with Z component. GDAL >= 2.2 */
 
     wkbPointM = 2001,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
     wkbLineStringM = 2002,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
@@ -129,6 +136,7 @@ typedef enum
     wkbSurfaceM = 2014,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
     wkbPolyhedralSurfaceM = 2015,  /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
     wkbTINM = 2016,                /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbTriangleM = 2017,            /**<  GDAL >= 2.2 */
 
     wkbPointZM = 3001,              /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
     wkbLineStringZM = 3002,         /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
@@ -146,6 +154,7 @@ typedef enum
     wkbSurfaceZM = 3014,            /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
     wkbPolyhedralSurfaceZM = 3015,  /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
     wkbTINZM = 3016,                /**< ISO SQL/MM Part 3. GDAL >= 2.1 */
+    wkbTriangleZM = 3017,           /**<  GDAL >= 2.2 */
 
     wkbPoint25D = -2147483647,   /* 2.5D extensions as per 99-402 */
     wkbLineString25D = -2147483646,
@@ -279,6 +288,7 @@ typedef void retGetPoints;
 %constant wkbSurface = 14;
 %constant wkbPolyhedralSurface = 15;
 %constant wkbTIN = 16;
+%constant wkbTriangle = 17;
 
 %constant wkbNone = 100;
 %constant wkbLinearRing = 101;
@@ -292,6 +302,7 @@ typedef void retGetPoints;
 %constant wkbSurfaceZ = 1014;
 %constant wkbPolyhedralSurfaceZ = 1015;
 %constant wkbTINZ = 1016;
+%constant wkbTriangleZ = 1017;
 
 %constant wkbPointM = 2001;
 %constant wkbLineStringM = 2002;
@@ -309,6 +320,7 @@ typedef void retGetPoints;
 %constant wkbSurfaceM = 2014;
 %constant wkbPolyhedralSurfaceM = 2015;
 %constant wkbTINM = 2016;
+%constant wkbTriangleM = 2017;
 
 %constant wkbPointZM = 3001;
 %constant wkbLineStringZM = 3002;
@@ -326,6 +338,7 @@ typedef void retGetPoints;
 %constant wkbSurfaceZM = 3014;
 %constant wkbPolyhedralSurfaceZM = 3015;
 %constant wkbTINZM = 3016;
+%constant wkbTriangleZM = 3017;
 
 %constant wkbPoint25D =              0x80000001;
 %constant wkbLineString25D =         0x80000002;
@@ -403,6 +416,8 @@ typedef void retGetPoints;
 %constant char *ODsCTransactions       = "Transactions";
 %constant char *ODsCEmulatedTransactions = "EmulatedTransactions";
 %constant char *ODsCMeasuredGeometries = "MeasuredGeometries";
+%constant char *ODsCRandomLayerRead    = "RandomLayerRead";
+%constant char *ODsCRandomLayerWrite   = "RandomLayerWrite";
 
 %constant char *ODrCCreateDataSource   = "CreateDataSource";
 %constant char *ODrCDeleteDataSource   = "DeleteDataSource";
@@ -443,6 +458,8 @@ typedef int OGRErr;
 #define ODsCTransactions       "Transactions"
 #define ODsCEmulatedTransactions "EmulatedTransactions"
 #define ODsCMeasuredGeometries  "MeasuredGeometries";
+#define ODsCRandomLayerRead    "RandomLayerRead";
+#define ODsCRandomLayerWrite   "RandomLayerWrite";
 
 #define ODrCCreateDataSource   "CreateDataSource"
 #define ODrCDeleteDataSource   "DeleteDataSource"
@@ -617,6 +634,9 @@ public:
 %mutable;
 
 %newobject CreateDataSource;
+#ifdef SWIGPYTHON
+%thread;
+#endif
 #ifndef SWIGJAVA
 %feature( "kwargs" ) CreateDataSource;
 #endif
@@ -625,8 +645,14 @@ public:
     OGRDataSourceShadow *ds = (OGRDataSourceShadow*) OGR_Dr_CreateDataSource( self, utf8_path, options);
     return ds;
   }
+#ifdef SWIGPYTHON
+%nothread;
+#endif
 
 %newobject CopyDataSource;
+#ifdef SWIGPYTHON
+%thread;
+#endif
 #ifndef SWIGJAVA
 %feature( "kwargs" ) CopyDataSource;
 #endif
@@ -636,8 +662,14 @@ public:
     OGRDataSourceShadow *ds = (OGRDataSourceShadow*) OGR_Dr_CopyDataSource(self, copy_ds, utf8_path, options);
     return ds;
   }
+#ifdef SWIGPYTHON
+%nothread;
+#endif
 
 %newobject Open;
+#ifdef SWIGPYTHON
+%thread;
+#endif
 #ifndef SWIGJAVA
 %feature( "kwargs" ) Open;
 #endif
@@ -657,6 +689,9 @@ public:
     }
     return ds;
   }
+#ifdef SWIGPYTHON
+%nothread;
+#endif
 
 #ifdef SWIGJAVA
   OGRErr DeleteDataSource( const char *utf8_path ) {
@@ -1288,6 +1323,7 @@ public:
     return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, id);
   }
 
+#ifndef SWIGPERL
   OGRFieldDefnShadow *GetFieldDefnRef(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1296,6 +1332,7 @@ public:
           return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
       return NULL;
   }
+#endif
   /* ------------------------------------------- */
 
   int GetGeomFieldCount() {
@@ -1307,6 +1344,7 @@ public:
       return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
   }
 
+#ifndef SWIGPERL
   OGRGeomFieldDefnShadow *GetGeomFieldDefnRef(const char* name) {
       int i = OGR_F_GetGeomFieldIndex(self, name);
       if (i == -1)
@@ -1315,6 +1353,7 @@ public:
           return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
       return NULL;
   }
+#endif
   /* ------------------------------------------- */
 
   /* ---- GetFieldAsString --------------------- */
@@ -1323,6 +1362,7 @@ public:
     return (const char *) OGR_F_GetFieldAsString(self, id);
   }
 
+#ifndef SWIGPERL
   const char* GetFieldAsString(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1331,6 +1371,7 @@ public:
 	  return (const char *) OGR_F_GetFieldAsString(self, i);
       return NULL;
   }
+#endif
   /* ------------------------------------------- */
 
   /* ---- GetFieldAsInteger -------------------- */
@@ -1339,6 +1380,7 @@ public:
     return OGR_F_GetFieldAsInteger(self, id);
   }
 
+#ifndef SWIGPERL
   int GetFieldAsInteger(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1347,6 +1389,7 @@ public:
 	  return OGR_F_GetFieldAsInteger(self, i);
       return 0;
   }
+#endif
   /* ------------------------------------------- */
 
   /* ---- GetFieldAsInteger64 ------------------ */
@@ -1355,6 +1398,7 @@ public:
     return OGR_F_GetFieldAsInteger64(self, id);
   }
 
+#ifndef SWIGPERL
   GIntBig GetFieldAsInteger64(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1363,6 +1407,7 @@ public:
           return OGR_F_GetFieldAsInteger64(self, i);
       return 0;
   }
+#endif
   /* ------------------------------------------- */
 
   /* ---- GetFieldAsDouble --------------------- */
@@ -1371,6 +1416,7 @@ public:
     return OGR_F_GetFieldAsDouble(self, id);
   }
 
+#ifndef SWIGPERL
   double GetFieldAsDouble(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1379,6 +1425,7 @@ public:
           return OGR_F_GetFieldAsDouble(self, i);
       return 0;
   }
+#endif
   /* ------------------------------------------- */
 
   %apply (int *OUTPUT) {(int *)};
@@ -1390,6 +1437,7 @@ public:
 			       pnHour, pnMinute, pfSecond,
 			       pnTZFlag);
   }
+#ifndef SWIGPERL
   void GetFieldAsDateTime(const char* name, int *pnYear, int *pnMonth, int *pnDay,
 			  int *pnHour, int *pnMinute, float *pfSecond,
 			  int *pnTZFlag) {
@@ -1401,6 +1449,7 @@ public:
 			       pnHour, pnMinute, pfSecond,
 			       pnTZFlag);
   }
+#endif
   %clear (int *);
   %clear (float *);
 
@@ -1422,6 +1471,7 @@ public:
       *pList = OGR_F_GetFieldAsIntegerList(self, id, nLen);
   }
 
+#ifndef SWIGPERL
   void GetFieldAsIntegerList(const char* name, int *nLen, const int **pList) {
       int id = OGR_F_GetFieldIndex(self, name);
       if (id == -1)
@@ -1430,21 +1480,12 @@ public:
           *pList = OGR_F_GetFieldAsIntegerList(self, id, nLen);
   }
 #endif
+#endif
 
 #if defined(SWIGPYTHON) || defined(SWIGPERL)
   void GetFieldAsInteger64List(int id, int *nLen, const GIntBig **pList) {
       *pList = OGR_F_GetFieldAsInteger64List(self, id, nLen);
   }
-
-#if defined(SWIGPERL)
-  void GetFieldAsInteger64List(const char* name, int *nLen, const GIntBig **pList) {
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          *pList = OGR_F_GetFieldAsInteger64List(self, id, nLen);
-  }
-#endif
 #endif
 
 #if defined(SWIGJAVA)
@@ -1465,6 +1506,7 @@ public:
       *pList = OGR_F_GetFieldAsDoubleList(self, id, nLen);
   }
 
+#ifndef SWIGPERL
   void GetFieldAsDoubleList(const char* name, int *nLen, const double **pList) {
       int id = OGR_F_GetFieldIndex(self, name);
       if (id == -1)
@@ -1473,6 +1515,7 @@ public:
           *pList = OGR_F_GetFieldAsDoubleList(self, id, nLen);
   }
 #endif
+#endif
 
 #if defined(SWIGJAVA)
   %apply (char** retAsStringArrayNoFree) {(char**)};
@@ -1491,6 +1534,7 @@ public:
       *pList = OGR_F_GetFieldAsStringList(self, id);
   }
 
+#ifndef SWIGPERL
   void GetFieldAsStringList(const char* name, char ***pList) {
       int id = OGR_F_GetFieldIndex(self, name);
       if (id == -1)
@@ -1499,6 +1543,7 @@ public:
           *pList = OGR_F_GetFieldAsStringList(self, id);
   }
 #endif
+#endif
 
 #ifndef SWIGCSHARP
 #ifdef SWIGJAVA
@@ -1534,6 +1579,7 @@ public:
     return OGRERR_NONE;
   }
 
+#ifndef SWIGPERL
   OGRErr GetFieldAsBinary(const char* name, int *nLen, char **pBuf) {
       int id = OGR_F_GetFieldIndex(self, name);
       if (id == -1)
@@ -1549,6 +1595,7 @@ public:
         return OGRERR_NONE;
       }
   }
+#endif
 #endif /* SWIGJAVA */
 
 #endif /* SWIGCSHARP */
@@ -1558,6 +1605,7 @@ public:
     return (OGR_F_IsFieldSet(self, id) > 0);
   }
 
+#ifndef SWIGPERL
   bool IsFieldSet(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1566,47 +1614,52 @@ public:
 	  return (OGR_F_IsFieldSet(self, i) > 0);
       return false;
   }
+#endif
   /* ------------------------------------------- */
 
-#ifdef SWIGPERL
-  int GetFieldIndex(int i) {
-      if (i < 0 || i >= OGR_F_GetFieldCount(self))
-          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
-      return i;
+  /* ---- IsFieldNull --------------------------- */
+  bool IsFieldNull(int id) {
+    return (OGR_F_IsFieldNull(self, id) > 0);
   }
-  int GetFieldIndex(const char* name) {
-      // Perl bindings let Swig handle overloaded methods. Thus they need to behave similarly.
+
+#ifndef SWIGPERL
+  bool IsFieldNull(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
-      if (i < 0)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      return i;
+      if (i == -1)
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+	  return (OGR_F_IsFieldNull(self, i) > 0);
+      return false;
   }
-#else
+#endif
+  /* ------------------------------------------- */
+
+  /* ---- IsFieldSetAndNotNull --------------------------- */
+  bool IsFieldSetAndNotNull(int id) {
+    return (OGR_F_IsFieldSetAndNotNull(self, id) > 0);
+  }
+
+#ifndef SWIGPERL
+  bool IsFieldSetAndNotNull(const char* name) {
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+	  return (OGR_F_IsFieldSetAndNotNull(self, i) > 0);
+      return false;
+  }
+#endif
+  /* ------------------------------------------- */
+
   int GetFieldIndex(const char* name) {
       // Do not issue an error if the field doesn't exist. It is intended to be silent
       return OGR_F_GetFieldIndex(self, name);
   }
-#endif
 
-#ifdef SWIGPERL
-  int GetGeomFieldIndex(int i) {
-      if (i < 0 || i >= OGR_F_GetGeomFieldCount(self))
-          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
-      return i;
-  }
-  int GetGeomFieldIndex(const char* name) {
-      // Perl bindings let Swig handle overloaded methods. Thus they need to behave similarly.
-      int i = OGR_F_GetGeomFieldIndex(self, name);
-      if (i < 0)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      return i;
-  }
-#else
   int GetGeomFieldIndex(const char* name) {
       // Do not issue an error if the field doesn't exist. It is intended to be silent
       return OGR_F_GetGeomFieldIndex(self, name);
   }
-#endif
 
   GIntBig GetFID() {
     return OGR_F_GetFID(self);
@@ -1624,6 +1677,7 @@ public:
     OGR_F_UnsetField(self, id);
   }
 
+#ifndef SWIGPERL
   void UnsetField(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1631,6 +1685,21 @@ public:
       else
           OGR_F_UnsetField(self, i);
   }
+#endif
+
+  void SetFieldNull(int id) {
+    OGR_F_SetFieldNull(self, id);
+  }
+
+#ifndef SWIGPERL
+  void SetFieldNull(const char* name) {
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          OGR_F_SetFieldNull(self, i);
+  }
+#endif
 
   /* ---- SetField ----------------------------- */
 #ifndef SWIGCSHARP
@@ -1642,6 +1711,7 @@ public:
     OGR_F_SetFieldString(self, id, value);
   }
 
+#ifndef SWIGPERL
   void SetField(const char* name, const char* value) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1649,6 +1719,7 @@ public:
       else
           OGR_F_SetFieldString(self, i, value);
   }
+#endif
   %clear (const char* value );
 
   void SetFieldInteger64(int id, GIntBig value) {
@@ -1660,6 +1731,7 @@ public:
     OGR_F_SetFieldInteger(self, id, value);
   }
 
+#ifndef SWIGPERL
   void SetField(const char* name, int value) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1667,12 +1739,14 @@ public:
       else
 	  OGR_F_SetFieldInteger(self, i, value);
   }
+#endif
 #endif /* SWIGPYTHON */
 
   void SetField(int id, double value) {
     OGR_F_SetFieldDouble(self, id, value);
   }
 
+#ifndef SWIGPERL
   void SetField(const char* name, double value) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1)
@@ -1680,6 +1754,7 @@ public:
       else
 	  OGR_F_SetFieldDouble(self, i, value);
   }
+#endif
 
   void SetField( int id, int year, int month, int day,
                              int hour, int minute, float second,
@@ -1689,6 +1764,7 @@ public:
                              tzflag);
   }
 
+#ifndef SWIGPERL
   void SetField(const char* name, int year, int month, int day,
                              int hour, int minute, float second,
                              int tzflag ) {
@@ -1700,79 +1776,33 @@ public:
 				 hour, minute, second,
 				 tzflag);
   }
+#endif
 
   void SetFieldIntegerList(int id, int nList, int *pList) {
       OGR_F_SetFieldIntegerList(self, id, nList, pList);
   }
 
-#if defined(SWIGPERL)
-  void SetFieldIntegerList(const char* name, int nList, int *pList) {
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-       	  OGR_F_SetFieldIntegerList(self, id, nList, pList);
-  }
-#endif
-
 #if defined(SWIGPYTHON) || defined(SWIGPERL)
   void SetFieldInteger64List(int id, int nList, GIntBig *pList) {
       OGR_F_SetFieldInteger64List(self, id, nList, pList);
   }
 
-#if defined(SWIGPERL)
-  void SetFieldInteger64List(const char* name, int nList, GIntBig *pList) {
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_SetFieldInteger64List(self, id, nList, pList);
-  }
-#endif
 #endif
 
   void SetFieldDoubleList(int id, int nList, double *pList) {
       OGR_F_SetFieldDoubleList(self, id, nList, pList);
   }
 
-#if defined(SWIGPERL)
-  void SetFieldDoubleList(const char* name, int nList, double *pList) {
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_SetFieldDoubleList(self, id, nList, pList);
-  }
-#endif
-
 %apply (char **options) {char **pList};
   void SetFieldStringList(int id, char **pList) {
       OGR_F_SetFieldStringList(self, id, pList);
   }
-
-#if defined(SWIGPERL)
-  void SetFieldStringList(const char* name, char **pList) {
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_SetFieldStringList(self, id, pList);
-  }
-#endif
 %clear char**pList;
 
 #if defined(SWIGPERL)
   void SetFieldBinary(int i, int nBytes, GByte* pabyBuf) {
       OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
   }
-
-  void SetFieldBinary(const char* name, int nBytes, GByte* pabyBuf) {
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
-  }
 #endif
 
   void SetFieldBinaryFromHexString(int id, const char* pszValue)
@@ -1783,6 +1813,7 @@ public:
      CPLFree(pabyBuf);
   }
 
+#ifndef SWIGPERL
   void SetFieldBinaryFromHexString(const char* name, const char* pszValue)
   {
       int i = OGR_F_GetFieldIndex(self, name);
@@ -1796,6 +1827,7 @@ public:
           CPLFree(pabyBuf);
       }
   }
+#endif
 
   /* ------------------------------------------- */
 
@@ -1837,6 +1869,7 @@ public:
           return (OGRFieldType)0;
   }
 
+#ifndef SWIGPERL
   OGRFieldType GetFieldType(const char* name) {
       int i = OGR_F_GetFieldIndex(self, name);
       if (i == -1) {
@@ -1845,6 +1878,7 @@ public:
       } else
           return (OGRFieldType) OGR_Fld_GetType( OGR_F_GetFieldDefnRef( self, i ) );
   }
+#endif
   /* ------------------------------------------- */
 
   int Validate( int flags = OGR_F_VAL_ALL, int bEmitError = TRUE ) {
@@ -1900,6 +1934,11 @@ public:
             case wkbCurvePolygon:
             case wkbMultiCurve:
             case wkbMultiSurface:
+            case wkbCurve:
+            case wkbSurface:
+            case wkbTriangle:
+            case wkbTIN:
+            case wkbPolyhedralSurface:
             case wkbNone:
             /*case wkbLinearRing:*/
             case wkbCircularStringZ:
@@ -1907,6 +1946,11 @@ public:
             case wkbCurvePolygonZ:
             case wkbMultiCurveZ:
             case wkbMultiSurfaceZ:
+            case wkbCurveZ:
+            case wkbSurfaceZ:
+            case wkbTriangleZ:
+            case wkbTINZ:
+            case wkbPolyhedralSurfaceZ:
             case wkbPoint25D:
             case wkbLineString25D:
             case wkbPolygon25D:
@@ -1926,6 +1970,11 @@ public:
             case wkbCurvePolygonM:
             case wkbMultiCurveM:
             case wkbMultiSurfaceM:
+            case wkbCurveM:
+            case wkbSurfaceM:
+            case wkbTriangleM:
+            case wkbTINM:
+            case wkbPolyhedralSurfaceM:
             case wkbPointZM:
             case wkbLineStringZM:
             case wkbPolygonZM:
@@ -1938,6 +1987,11 @@ public:
             case wkbCurvePolygonZM:
             case wkbMultiCurveZM:
             case wkbMultiSurfaceZM:
+            case wkbCurveZM:
+            case wkbSurfaceZM:
+            case wkbTriangleZM:
+            case wkbTINZM:
+            case wkbPolyhedralSurfaceZM:
                 return TRUE;
             default:
                 CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
@@ -1978,14 +2032,6 @@ public:
     return (OGRFieldDefnShadow*) OGR_FD_GetFieldDefn(self, i);
   }
 
-#ifdef SWIGPERL
-  int GetFieldIndex(int i) {
-      if (i < 0 || i >= OGR_FD_GetFieldCount(self))
-          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
-      return i;
-  }
-#endif
-
   int GetFieldIndex(const char* name) {
       // Do not issue an error if the field doesn't exist. It is intended to be silent
       return OGR_FD_GetFieldIndex(self, name);
@@ -2007,23 +2053,6 @@ public:
     return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, i);
   }
 
-#ifdef SWIGPERL
-  OGRGeomFieldDefnShadow* GetGeomFieldDefn(const char* name) {
-      int iField = OGR_FD_GetGeomFieldIndex(self, name);
-      if (iField == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, iField);
-      return NULL;
-  }
-
-  int GetGeomFieldIndex(int i) {
-      if (i < 0 || i >= OGR_FD_GetGeomFieldCount(self))
-          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
-      return i;
-  }
-#endif
-
   int GetGeomFieldIndex(const char* name) {
       // Do not issue an error if the field doesn't exist. It is intended to be silent
       return OGR_FD_GetGeomFieldIndex(self, name);
@@ -2955,6 +2984,10 @@ public:
   double Distance( OGRGeometryShadow* other) {
     return OGR_G_Distance(self, other);
   }
+  
+  double Distance3D( OGRGeometryShadow* other) {
+    return OGR_G_Distance3D(self, other);
+  }
 %clear OGRGeometryShadow* other;
 
   void Empty () {
@@ -3270,6 +3303,9 @@ int OGRGetNonLinearGeometriesEnabledFlag(void);
 
 #if !(defined(FROM_GDAL_I) && (defined(SWIGJAVA) || defined(SWIGPYTHON)))
 
+#ifdef SWIGPYTHON
+%thread;
+#endif
 %newobject Open;
 #ifndef SWIGJAVA
 %feature( "kwargs" ) Open;
@@ -3290,7 +3326,13 @@ int OGRGetNonLinearGeometriesEnabledFlag(void);
     return ds;
   }
 %}
+#ifdef SWIGPYTHON
+%nothread;
+#endif
 
+#ifdef SWIGPYTHON
+%thread;
+#endif
 %newobject OpenShared;
 #ifndef SWIGJAVA
 %feature( "kwargs" ) OpenShared;
@@ -3308,6 +3350,9 @@ int OGRGetNonLinearGeometriesEnabledFlag(void);
     return ds;
   }
 %}
+#ifdef SWIGPYTHON
+%nothread;
+#endif
 
 #endif /* !(defined(FROM_GDAL_I) && (defined(SWIGJAVA) || defined(SWIGPYTHON))) */
 
@@ -3438,3 +3483,8 @@ int GDALTermProgress( double, const char *, void * );
 #ifdef SWIGJAVA
 %include "ogr_java_extend.i"
 #endif
+
+
+#ifdef SWIGPYTHON
+%thread;
+#endif
diff --git a/swig/include/ogr_error_map.i b/swig/include/ogr_error_map.i
index fc6229b..063a16e 100644
--- a/swig/include/ogr_error_map.i
+++ b/swig/include/ogr_error_map.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr_error_map.i 32864 2016-01-08 21:00:50Z goatbar $
+ * $Id: ogr_error_map.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  OGRErr handling typemap.
diff --git a/swig/include/osr.i b/swig/include/osr.i
index 9f86366..b887eec 100644
--- a/swig/include/osr.i
+++ b/swig/include/osr.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: osr.i 33909 2016-04-07 08:10:58Z rouault $
+ * $Id: osr.i 35418 2016-09-13 13:37:01Z rouault $
  *
  * Project:  GDAL SWIG Interfaces.
  * Purpose:  OGRSpatialReference related declarations.
@@ -27,6 +27,10 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+#ifdef SWIGPYTHON
+%nothread;
+#endif
+
 %include constraints.i
 
 #ifdef PERL_CPAN_NAMESPACE
@@ -354,6 +358,11 @@ public:
     return OSRSetLinearUnitsAndUpdateParameters( self, name, to_meters );
   }
 
+  double GetTargetLinearUnits( const char *target_key ) {
+    // Return code ignored.
+    return OSRGetTargetLinearUnits( self, target_key, 0 );
+  }
+
   double GetLinearUnits() {
     // Return code ignored.
     return OSRGetLinearUnits( self, 0 );
@@ -1017,3 +1026,8 @@ public:
     return obj;
 }
 %}
+
+
+#ifdef SWIGPYTHON
+%thread;
+#endif
diff --git a/swig/include/perl/band.i b/swig/include/perl/band.i
new file mode 100644
index 0000000..b0eacf7
--- /dev/null
+++ b/swig/include/perl/band.i
@@ -0,0 +1,422 @@
+/* Perl specific Band methods, i.e., use Perl data structures directly in the C++ code */
+
+%header %{
+  double NVClassify(int comparison, double nv, AV* classifier, const char **error) {
+     /* recursive, return nv < classifier[0] ? classifier[1] : classifier[2]
+        returns error if there are not three values in the classifier,
+        first is not a number, or second or third are not a number of arrayref
+     */
+     SV** f = av_fetch(classifier, 0, 0);
+     SV** s = av_fetch(classifier, 1, 0);
+     SV** t = av_fetch(classifier, 2, 0);
+     if (f && SvNOK(*f)) {
+         switch(comparison) {
+         case 0: /* lt */
+         if (nv < SvNV(*f))
+             t = s;
+         break;
+         case 1: /* lte */
+         if (nv <= SvNV(*f))
+             t = s;
+         break;
+         case 2: /* gt */
+         if (nv > SvNV(*f))
+             t = s;
+         break;
+         case 3: /* gte */
+         if (nv >= SvNV(*f))
+             t = s;
+         break;
+         }
+         if (t && SvNOK(*t))
+             return SvNV(*t);
+         else if (t && SvROK(*t) && (SvTYPE(SvRV(*t)) == SVt_PVAV))
+             return NVClassify(comparison, nv, (AV*)(SvRV(*t)), error);
+         else {
+             *error = "The decision in a classifier must be a number or a reference to a classifier.";
+             return 0;
+         }
+     } else {
+         *error = "The first value in a classifier must be a number.";
+         return 0;
+     }
+  }
+  void NVClass(int comparison, double nv, AV* classifier, int *klass, const char **error) {
+     /* recursive, return nv < classifier[0] ? classifier[1] : classifier[2]
+        returns NULL if there are not three values in the classifier,
+        first is not a number, or second or third are not a number of arrayref
+     */
+     SV** f = av_fetch(classifier, 0, 0);
+     SV** s = av_fetch(classifier, 1, 0);
+     SV** t = av_fetch(classifier, 2, 0);
+     if (f && SvNOK(*f)) {
+         ++*klass;
+         switch(comparison) {
+         case 0: /* lt */
+         if (nv < SvNV(*f))
+             --*klass;
+             t = s;
+         break;
+         case 1: /* lte */
+         if (nv <= SvNV(*f))
+             --*klass;
+             t = s;
+         break;
+         case 2: /* gt */
+         if (nv > SvNV(*f))
+             --*klass;
+             t = s;
+         break;
+         case 3: /* gte */
+         if (nv >= SvNV(*f))
+             --*klass;
+             t = s;
+         break;
+         }
+         if (t && SvNOK(*t))
+             return;
+         else if (t && SvROK(*t) && (SvTYPE(SvRV(*t)) == SVt_PVAV))
+             NVClass(comparison, nv, (AV*)(SvRV(*t)), klass, error);
+         else {
+             *error = "The decision in a classifier must be a number or a reference to a classifier.";
+             return;
+         }
+     } else {
+         *error = "The first value in a classifier must be a number.";
+         return;
+     }
+  }
+  AV* to_array_classifier(SV* classifier, int* comparison, const char **error) {
+      if (SvROK(classifier) && (SvTYPE(SvRV(classifier)) == SVt_PVAV)) {
+          SV** f = av_fetch((AV*)SvRV(classifier), 0, 0);
+          SV** s = av_fetch((AV*)SvRV(classifier), 1, 0);
+          if (f && SvPOK(*f)) {
+              char *c = SvPV_nolen(*f);
+              if (strcmp(c, "<") == 0)
+                  *comparison = 0;
+              else if (strcmp(c, "<=") == 0)
+                  *comparison = 1;
+              else if (strcmp(c, ">") == 0)
+                  *comparison = 2;
+              else if (strcmp(c, ">=") == 0)
+                  *comparison = 3;
+              else
+                  *error = "The first element in classifier object must be a comparison.";
+          }
+          if (s && SvROK(*s) && (SvTYPE(SvRV(*s)) == SVt_PVAV))
+              return (AV*)SvRV(*s);
+          else
+              *error = "The second element in classifier object must be an array reference.";
+      } else {
+          *error = NEED_ARRAY_REF;
+      }
+  }
+%}
+
+%extend GDALRasterBandShadow {
+  
+    %apply (int nList, double* pList) {(int nFixedLevelCount, double *padfFixedLevels)};
+    %apply (int defined, double value) {(int bUseNoData, double dfNoDataValue)};
+    CPLErr ContourGenerate(double dfContourInterval, double dfContourBase,
+                           int nFixedLevelCount, double *padfFixedLevels,
+                           int bUseNoData, double dfNoDataValue,
+                           OGRLayerShadow *hLayer, int iIDField, int iElevField,
+                           GDALProgressFunc progress = NULL,
+                           void* progress_data = NULL) {
+        return GDALContourGenerate( self, dfContourInterval, dfContourBase,
+                                    nFixedLevelCount, padfFixedLevels,
+                                    bUseNoData, dfNoDataValue,
+                                    hLayer, iIDField, iElevField,
+                                    progress,
+                                    progress_data );
+    }
+    %clear (int nFixedLevelCount, double *padfFixedLevels);
+    %clear (int bUseNoData, double dfNoDataValue);
+
+    SV *ClassCounts(GDALProgressFunc callback = NULL,
+                    void* callback_data = NULL) {
+        GDALDataType dt = GDALGetRasterDataType(self);
+        if (!(dt == GDT_Byte || dt == GDT_UInt16 || dt == GDT_Int16 || dt == GDT_UInt32 || dt == GDT_Int32)) {
+            do_confess("ClassCounts without classifier requires an integer band.", 1);
+        }
+        HV* hash = newHV();
+        int XBlockSize, YBlockSize;
+        GDALGetBlockSize( self, &XBlockSize, &YBlockSize );
+        int XBlocks = (GDALGetRasterBandXSize(self) + XBlockSize - 1) / XBlockSize;
+        int YBlocks = (GDALGetRasterBandYSize(self) + YBlockSize - 1) / YBlockSize;
+        void *data = CPLMalloc(XBlockSize * YBlockSize * GDALGetDataTypeSizeBytes(dt));
+        for (int yb = 0; yb < YBlocks; ++yb) {
+            if (callback) {
+                double p = (double)yb/(double)YBlocks;
+                if (!callback(p, "", callback_data)) {
+                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
+                    hv_undef(hash);
+                    hash = NULL;
+                    break;
+                }
+            }
+            for (int xb = 0; xb < XBlocks; ++xb) {
+                int XValid, YValid;
+                CPLErr e = GDALReadBlock(self, xb, yb, data);
+                GDALGetActualBlockSize(self, xb, yb, &XValid, &YValid);
+                for (int iY = 0; iY < YValid; ++iY) {
+                    for (int iX = 0; iX < XValid; ++iX) {
+                        int32_t k;
+                        switch(dt) {
+                        case GDT_Byte:
+                          k = ((GByte*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_UInt16:
+                          k = ((GUInt16*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Int16:
+                          k = ((GInt16*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_UInt32:
+                          k = ((GUInt32*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Int32:
+                          k = ((GInt32*)(data))[iX + iY * XBlockSize];
+                          break;
+                        }
+                        char key[12];
+                        int klen = sprintf(key, "%i", k);
+                        SV* sv;
+                        SV** sv2 = hv_fetch(hash, key, klen, 0);
+                        if (sv2 && SvOK(*sv2)) {
+                            sv = *sv2;
+                            sv_setiv(sv, SvIV(sv)+1);
+                            SvREFCNT_inc(sv);
+                        } else {
+                            sv = newSViv(1);
+                        }
+                        if (!hv_store(hash, key, klen, sv, 0))
+                            SvREFCNT_dec(sv);
+                    }
+                }
+            }
+        }
+        CPLFree(data);
+        if (hash)
+            return newRV_noinc((SV*)hash);
+        else
+            return &PL_sv_undef;
+    }
+
+    SV *ClassCounts(SV* classifier,
+                    GDALProgressFunc callback = NULL,
+                    void* callback_data = NULL) {
+                    
+        const char *error = NULL;
+        GDALDataType dt = GDALGetRasterDataType(self);
+        if (!(dt == GDT_Float32 || dt == GDT_Float64)) {
+            do_confess("ClassCounts with classifier requires a float band.", 1);
+        }
+
+        AV* array_classifier = NULL;
+        int comparison = 0;
+
+        array_classifier = to_array_classifier(classifier, &comparison, &error);
+        if (error) do_confess(error, 1);
+
+        HV* hash = newHV();
+        int XBlockSize, YBlockSize;
+        GDALGetBlockSize( self, &XBlockSize, &YBlockSize );
+        int XBlocks = (GDALGetRasterBandXSize(self) + XBlockSize - 1) / XBlockSize;
+        int YBlocks = (GDALGetRasterBandYSize(self) + YBlockSize - 1) / YBlockSize;
+        void *data = CPLMalloc(XBlockSize * YBlockSize * GDALGetDataTypeSizeBytes(dt));
+
+        for (int yb = 0; yb < YBlocks; ++yb) {
+            if (callback) {
+                double p = (double)yb/(double)YBlocks;
+                if (!callback(p, "", callback_data)) {
+                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
+                    hv_undef(hash);
+                    hash = NULL;
+                    break;
+                }
+            }
+            for (int xb = 0; xb < XBlocks; ++xb) {
+                int XValid, YValid;
+                CPLErr e = GDALReadBlock(self, xb, yb, data);
+                GDALGetActualBlockSize(self, xb, yb, &XValid, &YValid);
+                for (int iY = 0; iY < YValid; ++iY) {
+                    for (int iX = 0; iX < XValid; ++iX) {
+                        double nv = 0;
+                        switch(dt) {
+                        case GDT_Float32:
+                          nv = ((float*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Float64:
+                          nv = ((double*)(data))[iX + iY * XBlockSize];
+                          break;
+                        }
+                        int k = 0;
+                        NVClass(comparison, nv, array_classifier, &k, &error);
+                        if (error) goto fail;
+                        char key[12];
+                        int klen = sprintf(key, "%i", k);
+                        SV* sv;
+                        SV** sv2 = hv_fetch(hash, key, klen, 0);
+                        if (sv2 && SvOK(*sv2)) {
+                            sv = *sv2;
+                            sv_setiv(sv, SvIV(sv)+1);
+                            SvREFCNT_inc(sv);
+                        } else {
+                            sv = newSViv(1);
+                        }
+                        if (!hv_store(hash, key, klen, sv, 0))
+                            SvREFCNT_dec(sv);
+                    }
+                }
+            }
+        }
+        
+        CPLFree(data);
+        if (hash)
+            return newRV_noinc((SV*)hash);
+        else
+            return &PL_sv_undef;
+        fail:
+        CPLFree(data);
+        do_confess(error, 1);
+        return &PL_sv_undef;
+    }
+
+    void Reclassify(SV* classifier,
+                    GDALProgressFunc callback = NULL,
+                    void* callback_data = NULL) {
+                    
+        const char *error = NULL;
+        
+        GDALDataType dt = GDALGetRasterDataType(self);
+        
+        bool is_integer_raster = true;
+        HV* hash_classifier = NULL;
+        bool has_default = false;
+        int32_t deflt = 0;
+
+        AV* array_classifier = NULL;
+        int comparison = 0;
+        
+        if (dt == GDT_Byte || dt == GDT_UInt16 || dt == GDT_Int16 || dt == GDT_UInt32 || dt == GDT_Int32) {
+            if (SvROK(classifier) && (SvTYPE(SvRV(classifier)) == SVt_PVHV)) {
+                hash_classifier = (HV*)SvRV(classifier);
+                SV** sv = hv_fetch(hash_classifier, "*", 1, 0);
+                if (sv && SvOK(*sv)) {
+                    has_default = true;
+                    deflt = SvIV(*sv);
+                }
+            } else {
+                do_confess(NEED_HASH_REF, 1);
+            }
+        } else if (dt == GDT_Float32 || dt == GDT_Float64) {
+            is_integer_raster = false;
+            array_classifier = to_array_classifier(classifier, &comparison, &error);
+            if (error) do_confess(error, 1);
+        } else {
+            do_confess("Only integer and float rasters can be reclassified.", 1);
+        }
+        
+        int has_no_data;
+        double no_data = GDALGetRasterNoDataValue(self, &has_no_data);
+        int XBlockSize, YBlockSize;
+        GDALGetBlockSize( self, &XBlockSize, &YBlockSize );
+        int XBlocks = (GDALGetRasterBandXSize(self) + XBlockSize - 1) / XBlockSize;
+        int YBlocks = (GDALGetRasterBandYSize(self) + YBlockSize - 1) / YBlockSize;
+        void *data = CPLMalloc(XBlockSize * YBlockSize * GDALGetDataTypeSizeBytes(dt));
+
+        for (int yb = 0; yb < YBlocks; ++yb) {
+            if (callback) {
+                double p = (double)yb/(double)YBlocks;
+                if (!callback(p, "", callback_data)) {
+                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
+                    break;
+                }
+            }
+            for (int xb = 0; xb < XBlocks; ++xb) {
+                int XValid, YValid;
+                CPLErr e = GDALReadBlock(self, xb, yb, data);
+                GDALGetActualBlockSize(self, xb, yb, &XValid, &YValid);
+                for (int iY = 0; iY < YValid; ++iY) {
+                    for (int iX = 0; iX < XValid; ++iX) {
+                        int32_t k = 0;
+                        double nv = 0;
+                        switch(dt) {
+                        case GDT_Byte:
+                          k = ((GByte*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_UInt16:
+                          k = ((GUInt16*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Int16:
+                          k = ((GInt16*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_UInt32:
+                          k = ((GUInt32*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Int32:
+                          k = ((GInt32*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Float32:
+                          nv = ((float*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Float64:
+                          nv = ((double*)(data))[iX + iY * XBlockSize];
+                          break;
+                        }
+
+                        if (is_integer_raster) {
+                            char key[12];
+                            int klen = sprintf(key, "%i", k);
+                            SV** sv = hv_fetch(hash_classifier, key, klen, 0);
+                            if (sv && SvOK(*sv)) {
+                                k = SvIV(*sv);
+                            } else if (has_default) {
+                                if (!(has_no_data && k == no_data))
+                                    k = deflt;
+                                else
+                                    continue;
+                            }
+                        } else {
+                            nv = NVClassify(comparison, nv, array_classifier, &error);
+                            if (error) goto fail;
+                        }
+
+                        switch(dt) {
+                        case GDT_Byte:
+                          ((GByte*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_UInt16:
+                          ((GUInt16*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_Int16:
+                          ((GInt16*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_UInt32:
+                          ((GUInt32*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_Int32:
+                          ((GInt32*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_Float32:
+                          ((float*)(data))[iX + iY * XBlockSize] = nv;
+                          break;
+                        case GDT_Float64:
+                          ((double*)(data))[iX + iY * XBlockSize] = nv;
+                          break;
+                        }
+                    }
+                }
+                e = GDALWriteBlock(self, xb, yb, data);
+            }
+        }
+        CPLFree(data);
+        return;
+        fail:
+        CPLFree(data);
+        do_confess(error, 1);        
+        return;
+    }
+
+}
diff --git a/swig/include/perl/confess.i b/swig/include/perl/confess.i
index 62cc957..07372c8 100644
--- a/swig/include/perl/confess.i
+++ b/swig/include/perl/confess.i
@@ -25,9 +25,11 @@
     #define NEED_DEF "A parameter which must be defined or not empty, is not."
     #define WRONG_CLASS "Object has a wrong class."
     #define NEED_REF "A parameter which must be a reference, is not."
+    #define NEED_HASH_REF "A parameter/item which must be a hash reference, is not."
     #define NEED_ARRAY_REF "A parameter/item which must be an array reference, is not."
     #define NEED_BINARY_DATA "A parameter which must be binary data, is not."
     #define NEED_CODE_REF "A parameter which must be an anonymous subroutine, is not."
     #define WRONG_ITEM_IN_ARRAY "An item in an array parameter has wrong type."
     #define ARRAY_TO_XML_FAILED "An array parameter cannot be converted to an XMLTree."
+    #define NOT_ENOUGH_ELEMENTS "The supplied array does not have enough elements."
 %}
diff --git a/swig/include/perl/destroy.i b/swig/include/perl/destroy.i
index 75d9133..511e9e1 100644
--- a/swig/include/perl/destroy.i
+++ b/swig/include/perl/destroy.i
@@ -15,7 +15,7 @@ sub DESTROY {
         Geo::modulec::delete_class($self);
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
     if ($code) {
         Geo::GDAL::VSIStdoutUnsetRedirection();
         $code->close;
diff --git a/swig/include/perl/gdal_perl.i b/swig/include/perl/gdal_perl.i
index c12d6c4..bfb6e2c 100644
--- a/swig/include/perl/gdal_perl.i
+++ b/swig/include/perl/gdal_perl.i
@@ -26,6 +26,8 @@
  * DEALINGS IN THE SOFTWARE.
  *****************************************************************************/
 
+%include init.i
+
 %init %{
   /* gdal_perl.i %init code */
   UseExceptions();
@@ -38,6 +40,8 @@
 %include confess.i
 %include cpl_exceptions.i
 
+%include band.i
+
 %rename (GetMetadata) GetMetadata_Dict;
 %ignore GetMetadata_List;
 
@@ -127,8 +131,7 @@ use Carp;
 use Encode;
 use Exporter 'import';
 use Geo::GDAL::Const;
-use Geo::OGR;
-use Geo::OSR;
+
 # $VERSION is the Perl module (CPAN) version number, which must be
 # an increasing floating point number.  $GDAL_VERSION is the
 # version number of the GDAL that this module is a part of. It is
@@ -140,8 +143,8 @@ use Geo::OSR;
 # Note that the 1/100000 digits may be used to create more than one
 # CPAN release from one GDAL release.
 
-our $VERSION = '2.0103';
-our $GDAL_VERSION = '2.1.3';
+our $VERSION = '2.0200';
+our $GDAL_VERSION = '2.2.0';
 
 =pod
 
@@ -208,15 +211,22 @@ use Scalar::Util 'blessed';
 use vars qw/
     @EXPORT_OK %EXPORT_TAGS
     @DATA_TYPES @OPEN_FLAGS @RESAMPLING_TYPES @RIO_RESAMPLING_TYPES @NODE_TYPES
-    %TYPE_STRING2INT %TYPE_INT2STRING
-    %OF_STRING2INT
-    %RESAMPLING_STRING2INT %RESAMPLING_INT2STRING
-    %RIO_RESAMPLING_STRING2INT %RIO_RESAMPLING_INT2STRING
-    %NODE_TYPE_STRING2INT %NODE_TYPE_INT2STRING
-    @error %stdout_redirection
+    %S2I %I2S @error %stdout_redirection
     /;
- at EXPORT_OK = qw/Driver Open BuildVRT/;
-%EXPORT_TAGS = (all => [qw(Driver Open BuildVRT)]);
+BEGIN {
+ at EXPORT_OK = qw(
+    Driver Open BuildVRT
+    ParseXMLString NodeData Child Children NodeData ParseXMLString SerializeXMLTree
+    error last_error named_parameters keep unkeep parent note unnote make_processing_options
+    VSIStdoutSetRedirection VSIStdoutUnsetRedirection
+    i2s s2i s_exists);
+%EXPORT_TAGS = (
+    all => [qw(Driver Open BuildVRT)],
+    XML => [qw(ParseXMLString NodeData Child Children NodeData ParseXMLString SerializeXMLTree)],
+    INTERNAL => [qw(error last_error named_parameters keep unkeep parent note unnote make_processing_options
+                    VSIStdoutSetRedirection VSIStdoutUnsetRedirection i2s s2i s_exists)]
+    );
+}
 *BuildVRT = *Geo::GDAL::Dataset::BuildVRT;
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
@@ -228,29 +238,33 @@ for (keys %Geo::GDAL::Const::) {
 }
 for my $string (@DATA_TYPES) {
     my $int = eval "\$Geo::GDAL::Const::GDT_$string";
-    $TYPE_STRING2INT{$string} = $int;
-    $TYPE_INT2STRING{$int} = $string;
+    $S2I{data_type}{$string} = $int;
+    $I2S{data_type}{$int} = $string;
 }
 for my $string (@OPEN_FLAGS) {
     my $int = eval "\$Geo::GDAL::Const::OF_$string";
-    $OF_STRING2INT{$string} = $int;
+    $S2I{open_flag}{$string} = $int;
 }
 for my $string (@RESAMPLING_TYPES) {
     my $int = eval "\$Geo::GDAL::Const::GRA_$string";
-    $RESAMPLING_STRING2INT{$string} = $int;
-    $RESAMPLING_INT2STRING{$int} = $string;
+    $S2I{resampling}{$string} = $int;
+    $I2S{resampling}{$int} = $string;
 }
 for my $string (@RIO_RESAMPLING_TYPES) {
     my $int = eval "\$Geo::GDAL::Const::GRIORA_$string";
-    $RIO_RESAMPLING_STRING2INT{$string} = $int;
-    $RIO_RESAMPLING_INT2STRING{$int} = $string;
+    $S2I{rio_resampling}{$string} = $int;
+    $I2S{rio_resampling}{$int} = $string;
 }
 for my $string (@NODE_TYPES) {
     my $int = eval "\$Geo::GDAL::Const::CXT_$string";
-    $NODE_TYPE_STRING2INT{$string} = $int;
-    $NODE_TYPE_INT2STRING{$int} = $string;
+    $S2I{node_type}{$string} = $int;
+    $I2S{node_type}{$int} = $string;
 }
 
+our $HAVE_PDL;
+eval 'require PDL';
+$HAVE_PDL = 1 unless $@;
+
 sub error {
     if (@_) {
         my $error;
@@ -278,7 +292,17 @@ sub error {
 }
 
 sub last_error {
-    my $error = $error[$#error] // '';
+    my $error;
+    # all errors should be in @error
+    if (@error) {
+        $error = $error[$#error];
+    } elsif ($@) {
+        # swig exceptions are not in @error
+        $error = $@;
+        $error =~ s/ at .*//;
+    } else {
+        $error = 'unknown error';
+    }
     chomp($error);
     return $error;
 }
@@ -329,16 +353,60 @@ sub named_parameters {
     return \%named;
 }
 
-sub string2int {
-    my ($string, $string2int_hash, $int2string_hash, $default) = @_;
+sub i2s {
+    my ($class, $int) = @_;
+    return $I2S{$class}{$int} if exists $I2S{$class}{$int};
+    return $int;
+}
+
+sub s2i {
+    my ($class, $string, $backwards, $default) = @_;
     $string = $default if defined $default && !defined $string;
     return unless defined $string;
-    return $string if $int2string_hash && exists $int2string_hash->{$string};
-    error(1, $string, $string2int_hash) unless exists $string2int_hash->{$string};
-    $string2int_hash->{$string};
+    return $string if $backwards && exists $I2S{$class}{$string};
+    error(1, $string, $S2I{$class}) unless exists $S2I{$class}{$string};
+    $S2I{$class}{$string};
+}
+
+sub s_exists {
+    my ($class, $string) = @_;
+    return exists $S2I{$class}{$string};
+}
+
+sub make_processing_options {
+    my ($o) = @_;
+    my @options;
+    my $processor = sub {
+        my $val = shift;
+        if (ref $val eq 'ARRAY') {
+            return @$val;
+        } elsif (not ref $val) {
+            if ($val =~ /\s/ && $val =~ /^[+\-0-9.,% ]+$/) {
+                return split /\s+/, $val;
+            }
+            return $val;
+        } else {
+            error("'$val' is not a valid processing option.");
+        }
+    };
+    if (ref $o eq 'HASH') {
+        for my $key (keys %$o) {
+            my $val = $o->{$key};
+            # without hyphen is deprecated
+            $key = '-'.$key unless $key =~ /^-/;
+            push @options, $key;
+            push @options, $processor->($val);
+        }
+    } elsif (ref $o eq 'ARRAY') {
+        for my $item (@$o) {
+            push @options, $processor->($item);
+        }
+    }
+    $o = \@options;
+    return $o;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
 }
 
 sub FindFile {
@@ -371,13 +439,13 @@ sub NodeTypes {
 
 sub NodeType {
     my $type = shift;
-    return $NODE_TYPE_INT2STRING{$type} if $type =~ /^\d/;
-    return $NODE_TYPE_STRING2INT{$type};
+    return i2s(node_type => $type) if $type =~ /^\d/;
+    return s2i(node_type => $type);
 }
 
 sub NodeData {
     my $node = shift;
-    return (Geo::GDAL::NodeType($node->[0]), $node->[1]);
+    return (NodeType($node->[0]), $node->[1]);
 }
 
 sub Children {
@@ -391,12 +459,12 @@ sub Child {
 }
 
 sub GetDataTypeSize {
-    return _GetDataTypeSize(string2int(shift, \%TYPE_STRING2INT, \%TYPE_INT2STRING));
+    return _GetDataTypeSize(s2i(data_type => shift, 1));
 }
 
 sub DataTypeValueRange {
     my $t = shift;
-    Geo::GDAL::error(1, $t, \%TYPE_STRING2INT) unless exists $TYPE_STRING2INT{$t};
+    s2i(data_type => $t);
     # these values are from gdalrasterband.cpp
     return (0,255) if $t =~ /Byte/;
     return (0,65535) if $t =~/UInt16/;
@@ -408,13 +476,13 @@ sub DataTypeValueRange {
 }
 
 sub DataTypeIsComplex {
-    return _DataTypeIsComplex(string2int(shift, \%TYPE_STRING2INT));
+    return _DataTypeIsComplex(s2i(data_type => shift));
 }
 
 sub PackCharacter {
     my $t = shift;
-    $t = $TYPE_INT2STRING{$t} if exists $TYPE_INT2STRING{$t};
-    Geo::GDAL::error(1, $t, \%TYPE_STRING2INT) unless exists $TYPE_STRING2INT{$t};
+    $t = i2s(data_type => $t);
+    s2i(data_type => $t); # test
     my $is_big_endian = unpack("h*", pack("s", 1)) =~ /01/; # from Programming Perl
     return 'C' if $t =~ /^Byte$/;
     return ($is_big_endian ? 'n': 'v') if $t =~ /^UInt16$/;
@@ -446,7 +514,11 @@ sub Drivers {
 
 sub Driver {
     return 'Geo::GDAL::Driver' unless @_;
-    return GetDriver(@_);
+    my $name = shift;
+    my $driver = GetDriver($name);
+    error("Driver \"$name\" not found. Is it built in? Check with Geo::GDAL::Drivers or Geo::OGR::Drivers.") 
+        unless $driver;
+    return $driver;
 }
 
 sub AccessTypes {
@@ -454,13 +526,13 @@ sub AccessTypes {
 }
 
 sub Open {
-    my $p = Geo::GDAL::named_parameters(\@_, Name => '.', Access => 'ReadOnly', Type => 'Any', Options => {}, Files => []);
+    my $p = named_parameters(\@_, Name => '.', Access => 'ReadOnly', Type => 'Any', Options => {}, Files => []);
     my @flags;
     my %o = (READONLY => 1, UPDATE => 1);
-    Geo::GDAL::error(1, $p->{access}, \%o) unless $o{uc($p->{access})};
+    error(1, $p->{access}, \%o) unless $o{uc($p->{access})};
     push @flags, uc($p->{access});
     %o = (RASTER => 1, VECTOR => 1, ANY => 1);
-    Geo::GDAL::error(1, $p->{type}, \%o) unless $o{uc($p->{type})};
+    error(1, $p->{type}, \%o) unless $o{uc($p->{type})};
     push @flags, uc($p->{type}) unless uc($p->{type}) eq 'ANY';
     my $dataset = OpenEx(Name => $p->{name}, Flags => \@flags, Options => $p->{options}, Files => $p->{files});
     unless ($dataset) {
@@ -475,7 +547,7 @@ sub OpenShared {
     my @p = @_; # name, update
     my @flags = qw/RASTER SHARED/;
     $p[1] //= 'ReadOnly';
-    Geo::GDAL::error(1, $p[1], {ReadOnly => 1, Update => 1}) unless ($p[1] eq 'ReadOnly' or $p[1] eq 'Update');
+    error(1, $p[1], {ReadOnly => 1, Update => 1}) unless ($p[1] eq 'ReadOnly' or $p[1] eq 'Update');
     push @flags, qw/READONLY/ if $p[1] eq 'ReadOnly';
     push @flags, qw/UPDATE/ if $p[1] eq 'Update';
     my $dataset = OpenEx($p[0], \@flags);
@@ -484,7 +556,7 @@ sub OpenShared {
 }
 
 sub OpenEx {
-    my $p = Geo::GDAL::named_parameters(\@_, Name => '.', Flags => [], Drivers => [], Options => {}, Files => []);
+    my $p = named_parameters(\@_, Name => '.', Flags => [], Drivers => [], Options => {}, Files => []);
     unless ($p) {
         my $name = shift // '';
         my @flags = @_;
@@ -493,8 +565,7 @@ sub OpenEx {
     if ($p->{flags}) {
         my $f = 0;
         for my $flag (@{$p->{flags}}) {
-            Geo::GDAL::error(1, $flag, \%OF_STRING2INT) unless exists $OF_STRING2INT{$flag};
-            $f |= $Geo::GDAL::OF_STRING2INT{$flag};
+            $f |= s2i(open_flag => $flag);
         }
         $p->{flags} = $f;
     }
@@ -521,7 +592,7 @@ sub RegenerateOverview {
 
 sub ReprojectImage {
     my @p = @_;
-    $p[4] = string2int($p[4], \%RESAMPLING_STRING2INT);
+    $p[4] = s2i(resampling => $p[4]);
     return _ReprojectImage(@p);
 }
 
@@ -532,24 +603,10 @@ sub AutoCreateWarpedVRT {
             $p[$i] = $p[$i]->ExportToWkt;
         }
     }
-    $p[3] = string2int($p[3], \%RESAMPLING_STRING2INT, undef, 'NearestNeighbour');
+    $p[3] = s2i(resampling => $p[3], undef, 'NearestNeighbour');
     return _AutoCreateWarpedVRT(@p);
 }
 
-sub make_processing_options {
-    my ($o) = @_;
-    if (ref $o eq 'HASH') {
-        for my $key (keys %$o) {
-            unless ($key =~ /^-/) {
-                $o->{'-'.$key} = $o->{$key};
-                delete $o->{$key};
-            }
-        }
-        $o = [%$o];
-    }
-    return $o;
-}
-
 
 
 
@@ -585,6 +642,8 @@ use warnings;
 use Carp;
 use Scalar::Util 'blessed';
 
+Geo::GDAL->import(qw(:XML :INTERNAL));
+
 use vars qw/@CAPABILITIES @DOMAINS/;
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
@@ -621,7 +680,20 @@ sub TestCapability {
 sub Extension {
     my $self = shift;
     my $h = $self->GetMetadata;
-    return $h->{DMD_EXTENSION};
+    if (wantarray) {
+        my $e = $h->{DMD_EXTENSIONS};
+        my @e = split / /, $e;
+        @e = split /\//, $e if $e =~ /\//; # ILWIS returns mpr/mpl
+        for my $i (0..$#e) {
+            $e[$i] =~ s/^\.//; # CALS returns extensions with a dot prefix
+        }
+        return @e;
+    } else {
+        my $e = $h->{DMD_EXTENSION};
+        return '' if $e =~ /\//; # ILWIS returns mpr/mpl
+        $e =~ s/^\.//;
+        return $e;
+    }
 }
 
 sub MIMEType {
@@ -635,14 +707,14 @@ sub CreationOptionList {
     my @options;
     my $h = $self->GetMetadata->{DMD_CREATIONOPTIONLIST};
     if ($h) {
-        $h = Geo::GDAL::ParseXMLString($h);
-        my($type, $value) = Geo::GDAL::NodeData($h);
+        $h = ParseXMLString($h);
+        my($type, $value) = NodeData($h);
         if ($value eq 'CreationOptionList') {
-            for my $o (Geo::GDAL::Children($h)) {
+            for my $o (Children($h)) {
                 my %option;
-                for my $a (Geo::GDAL::Children($o)) {
-                    my(undef, $key) = Geo::GDAL::NodeData($a);
-                    my(undef, $value) = Geo::GDAL::NodeData(Geo::GDAL::Child($a, 0));
+                for my $a (Children($o)) {
+                    my(undef, $key) = NodeData($a);
+                    my(undef, $value) = NodeData(Child($a, 0));
                     if ($key eq 'Value') {
                         push @{$option{$key}}, $value;
                     } else {
@@ -668,7 +740,7 @@ sub stdout_redirection_wrapper {
     if ($name && blessed $name) {
         $object = $name;
         my $ref = $object->can('write');
-        Geo::GDAL::VSIStdoutSetRedirection($ref);
+        VSIStdoutSetRedirection($ref);
         $name = '/vsistdout/';
     }
     my $ds;
@@ -679,19 +751,19 @@ sub stdout_redirection_wrapper {
         if ($ds) {
             $Geo::GDAL::stdout_redirection{tied(%$ds)} = $object;
         } else {
-            Geo::GDAL::VSIStdoutUnsetRedirection();
+            VSIStdoutUnsetRedirection();
             $object->close;
         }
     }
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
     confess("Failed. Use Geo::OGR::Driver for vector drivers.") unless $ds;
     return $ds;
 }
 
 sub Create {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Name => 'unnamed', Width => 256, Height => 256, Bands => 1, Type => 'Byte', Options => {});
-    my $type = Geo::GDAL::string2int($p->{type}, \%Geo::GDAL::TYPE_STRING2INT);
+    my $p = named_parameters(\@_, Name => 'unnamed', Width => 256, Height => 256, Bands => 1, Type => 'Byte', Options => {});
+    my $type = s2i(data_type => $p->{type});
     return $self->stdout_redirection_wrapper(
         $p->{name},
         $self->can('_Create'),
@@ -702,7 +774,7 @@ sub Create {
 
 sub Copy {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Name => 'unnamed', Src => undef, Strict => 1, Options => {}, Progress => undef, ProgressData => undef);
+    my $p = named_parameters(\@_, Name => 'unnamed', Src => undef, Strict => 1, Options => {}, Progress => undef, ProgressData => undef);
     return $self->stdout_redirection_wrapper(
         $p->{name},
         $self->can('_CreateCopy'),
@@ -716,8 +788,8 @@ sub Open {
     my @flags = qw/RASTER/;
     push @flags, qw/READONLY/ if $p[1] eq 'ReadOnly';
     push @flags, qw/UPDATE/ if $p[1] eq 'Update';
-    my $dataset = Geo::GDAL::OpenEx($p[0], \@flags, [$self->Name()]);
-    Geo::GDAL::error("Failed to open $p[0]. Is it a raster dataset?") unless $dataset;
+    my $dataset = OpenEx($p[0], \@flags, [$self->Name()]);
+    error("Failed to open $p[0]. Is it a raster dataset?") unless $dataset;
     return $dataset;
 }
 
@@ -732,18 +804,23 @@ use Scalar::Util 'blessed';
 use Carp;
 use Exporter 'import';
 
-use vars qw/@EXPORT @DOMAINS @CAPABILITIES %CAPABILITIES %BANDS %LAYERS %RESULT_SET/;
+Geo::GDAL->import(qw(:INTERNAL));
+
+use vars qw/@EXPORT @DOMAINS @CAPABILITIES %CAPABILITIES/;
+ 
 @EXPORT = qw/BuildVRT/;
 @DOMAINS = qw/IMAGE_STRUCTURE SUBDATASETS GEOLOCATION/;
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $BANDS{$self};
+    unkeep($self);
 }
 
+*Driver = *GetDriver;
+
 sub Dataset {
     my $self = shift;
-    return $BANDS{tied(%$self)};
+    parent($self);
 }
 
 sub Domains {
@@ -775,16 +852,15 @@ sub GetRasterBand {
     my ($self, $index) = @_;
     $index //= 1;
     my $band = _GetRasterBand($self, $index);
-    Geo::GDAL::error(2, $index, 'Band') unless $band;
-    $BANDS{tied(%{$band})} = $self;
-    return $band;
+    error(2, $index, 'Band') unless $band;
+    keep($band, $self);
 }
 *Band = *GetRasterBand;
 
 sub AddBand {
     my ($self, $type, $options) = @_;
     $type //= 'Byte';
-    $type = Geo::GDAL::string2int($type, \%Geo::GDAL::TYPE_STRING2INT);
+    $type = s2i(data_type => $type);
     $self->_AddBand($type, $options);
     return unless defined wantarray;
     return $self->GetRasterBand($self->{RasterCount});
@@ -797,9 +873,8 @@ sub CreateMaskBand {
 sub ExecuteSQL {
     my $self = shift;
     my $layer = $self->_ExecuteSQL(@_);
-    $LAYERS{tied(%$layer)} = $self;
-    $RESULT_SET{tied(%$layer)} = 1;
-    return $layer;
+    note($layer, "is result set");
+    keep($layer, $self);
 }
 
 sub ReleaseResultSet {
@@ -810,9 +885,8 @@ sub GetLayer {
     my($self, $name) = @_;
     my $layer = defined $name ? GetLayerByName($self, "$name") : GetLayerByIndex($self, 0);
     $name //= '';
-    Geo::GDAL::error(2, $name, 'Layer') unless $layer;
-    $LAYERS{tied(%$layer)} = $self;
-    return $layer;
+    error(2, $name, 'Layer') unless $layer;
+    keep($layer, $self);
 }
 *Layer = *GetLayer;
 
@@ -829,15 +903,15 @@ sub GetLayerNames {
 
 sub CreateLayer {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        Name => 'unnamed',
-                                        SRS => undef,
-                                        GeometryType => 'Unknown',
-                                        Options => {},
-                                        Schema => undef,
-                                        Fields => undef,
-                                        ApproxOK => 1);
-    Geo::GDAL::error("The 'Fields' argument must be an array reference.") if $p->{fields} && ref($p->{fields}) ne 'ARRAY';
+    my $p = named_parameters(\@_,
+                             Name => 'unnamed',
+                             SRS => undef,
+                             GeometryType => 'Unknown',
+                             Options => {},
+                             Schema => undef,
+                             Fields => undef,
+                             ApproxOK => 1);
+    error("The 'Fields' argument must be an array reference.") if $p->{fields} && ref($p->{fields}) ne 'ARRAY';
     if (defined $p->{schema}) {
         my $s = $p->{schema};
         $p->{geometrytype} = $s->{GeometryType} if exists $s->{GeometryType};
@@ -847,18 +921,18 @@ sub CreateLayer {
     $p->{fields} = [] unless ref($p->{fields}) eq 'ARRAY';
     # if fields contains spatial fields, then do not create default one
     for my $f (@{$p->{fields}}) {
-        if ($f->{GeometryType} or exists $Geo::OGR::Geometry::TYPE_STRING2INT{$f->{Type}}) {
+        error("Field definitions must be hash references.") unless ref $f eq 'HASH';
+        if ($f->{GeometryType} || ($f->{Type} && s_exists(geometry_type => $f->{Type}))) {
             $p->{geometrytype} = 'None';
             last;
         }
     }
-    my $gt = Geo::GDAL::string2int($p->{geometrytype}, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+    my $gt = s2i(geometry_type => $p->{geometrytype});
     my $layer = _CreateLayer($self, $p->{name}, $p->{srs}, $gt, $p->{options});
-    $LAYERS{tied(%$layer)} = $self;
     for my $f (@{$p->{fields}}) {
         $layer->CreateField($f);
     }
-    return $layer;
+    keep($layer, $self);
 }
 
 sub DeleteLayer {
@@ -868,7 +942,7 @@ sub DeleteLayer {
         my $layer = GetLayerByIndex($self, $i);
         $index = $i, last if $layer->GetName eq $name;
     }
-    Geo::GDAL::error(2, $name, 'Layer') unless defined $index;
+    error(2, $name, 'Layer') unless defined $index;
     _DeleteLayer($self, $index);
 }
 
@@ -897,7 +971,7 @@ sub GeoTransform {
             SetGeoTransform($self, \@_);
         }
     };
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
     return unless defined wantarray;
     my $t = GetGeoTransform($self);
     if (wantarray) {
@@ -909,24 +983,40 @@ sub GeoTransform {
 
 sub Extent {
     my $self = shift;
-    return $self->GeoTransform->Extent($self->Size);
+    my $t = $self->GeoTransform;
+    my $extent = $t->Extent($self->Size);
+    if (@_) {
+        my ($xoff, $yoff, $w, $h) = @_;
+        my ($x, $y) = $t->Apply([$xoff, $xoff+$w, $xoff+$w, $xoff], [$yoff, $yoff, $yoff+$h, $yoff+$h]);
+        my $xmin = shift @$x;
+        my $xmax = $xmin;
+        for my $x (@$x) {
+            $xmin = $x if $x < $xmin;
+            $xmax = $x if $x > $xmax;
+        }
+        my $ymin = shift @$y;
+        my $ymax = $ymin;
+        for my $y (@$y) {
+            $ymin = $y if $y < $ymin;
+            $ymax = $y if $y > $ymax;
+        }
+        $extent = Geo::GDAL::Extent->new($xmin, $ymin, $xmax, $ymax);
+    }
+    return $extent;
 }
 
 sub Tile { # $xoff, $yoff, $xsize, $ysize, assuming strict north up
     my ($self, $e) = @_;
     my ($w, $h) = $self->Size;
-    #print "sz $w $h\n";
-    my $gt = $self->GeoTransform;
-    #print "gt @$gt\n";
-    confess "GeoTransform is not \"north up\"." unless $gt->NorthUp;
-    my $x = $gt->Extent($w, $h);
-    my $xoff = floor(($e->[0] - $gt->[0])/$gt->[1]);
+    my $t = $self->GeoTransform;
+    confess "GeoTransform is not \"north up\"." unless $t->NorthUp;
+    my $xoff = floor(($e->[0] - $t->[0])/$t->[1]);
     $xoff = 0 if $xoff < 0;
-    my $yoff = floor(($gt->[3] - $e->[3])/(-$gt->[5]));
+    my $yoff = floor(($e->[1] - $t->[3])/$t->[5]);
     $yoff = 0 if $yoff < 0;
-    my $xsize = ceil(($e->[2] - $gt->[0])/$gt->[1]) - $xoff;
+    my $xsize = ceil(($e->[2] - $t->[0])/$t->[1]) - $xoff;
     $xsize = $w - $xoff if $xsize > $w - $xoff;
-    my $ysize = ceil(($gt->[3] - $e->[1])/(-$gt->[5])) - $yoff;
+    my $ysize = ceil(($e->[3] - $t->[3])/$t->[5]) - $yoff;
     $ysize = $h - $yoff if $ysize > $h - $yoff;
     return ($xoff, $yoff, $xsize, $ysize);
 }
@@ -966,24 +1056,24 @@ sub ReadRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->Band->DataType;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        XOff => 0,
-                                        YOff => 0,
-                                        XSize => $width,
-                                        YSize => $height,
-                                        BufXSize => undef,
-                                        BufYSize => undef,
-                                        BufType => $type,
-                                        BandList => [1],
-                                        BufPixelSpace => 0,
-                                        BufLineSpace => 0,
-                                        BufBandSpace => 0,
-                                        ResampleAlg => 'NearestNeighbour',
-                                        Progress => undef,
-                                        ProgressData => undef
+    my $p = named_parameters(\@_,
+                             XOff => 0,
+                             YOff => 0,
+                             XSize => $width,
+                             YSize => $height,
+                             BufXSize => undef,
+                             BufYSize => undef,
+                             BufType => $type,
+                             BandList => [1],
+                             BufPixelSpace => 0,
+                             BufLineSpace => 0,
+                             BufBandSpace => 0,
+                             ResampleAlg => 'NearestNeighbour',
+                             Progress => undef,
+                             ProgressData => undef
         );
-    $p->{resamplealg} = Geo::GDAL::string2int($p->{resamplealg}, \%Geo::GDAL::RIO_RESAMPLING_STRING2INT);
-    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $p->{resamplealg} = s2i(rio_resampling => $p->{resamplealg});
+    $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
     $self->_ReadRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bandlist},$p->{bufpixelspace},$p->{buflinespace},$p->{bufbandspace},$p->{resamplealg},$p->{progress},$p->{progressdata});
 }
 
@@ -991,21 +1081,21 @@ sub WriteRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->Band->DataType;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        XOff => 0,
-                                        YOff => 0,
-                                        XSize => $width,
-                                        YSize => $height,
-                                        Buf => undef,
-                                        BufXSize => undef,
-                                        BufYSize => undef,
-                                        BufType => $type,
-                                        BandList => [1],
-                                        BufPixelSpace => 0,
-                                        BufLineSpace => 0,
-                                        BufBandSpace => 0
+    my $p = named_parameters(\@_,
+                             XOff => 0,
+                             YOff => 0,
+                             XSize => $width,
+                             YSize => $height,
+                             Buf => undef,
+                             BufXSize => undef,
+                             BufYSize => undef,
+                             BufType => $type,
+                             BandList => [1],
+                             BufPixelSpace => 0,
+                             BufLineSpace => 0,
+                             BufBandSpace => 0
         );
-    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
     $self->_WriteRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{buf},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bandlist},$p->{bufpixelspace},$p->{buflinespace},$p->{bufbandspace});
 }
 
@@ -1016,7 +1106,7 @@ sub BuildOverviews {
     eval {
         $self->_BuildOverviews(@p);
     };
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
 }
 
 sub stdout_redirection_wrapper {
@@ -1025,7 +1115,7 @@ sub stdout_redirection_wrapper {
     if ($name && blessed $name) {
         $object = $name;
         my $ref = $object->can('write');
-        Geo::GDAL::VSIStdoutSetRedirection($ref);
+        VSIStdoutSetRedirection($ref);
         $name = '/vsistdout/';
     }
     my $ds;
@@ -1036,17 +1126,17 @@ sub stdout_redirection_wrapper {
         if ($ds) {
             $Geo::GDAL::stdout_redirection{tied(%$ds)} = $object;
         } else {
-            Geo::GDAL::VSIStdoutUnsetRedirection();
+            VSIStdoutUnsetRedirection();
             $object->close;
         }
     }
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
     return $ds;
 }
 
 sub DEMProcessing {
     my ($self, $dest, $Processing, $ColorFilename, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALDEMProcessingOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALDEMProcessingOptions->new(make_processing_options($options));
     return $self->stdout_redirection_wrapper(
         $dest,
         \&Geo::GDAL::wrapper_GDALDEMProcessing,
@@ -1056,7 +1146,7 @@ sub DEMProcessing {
 
 sub Nearblack {
     my ($self, $dest, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALNearblackOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALNearblackOptions->new(make_processing_options($options));
     my $b = blessed($dest);
     if ($b && $b eq 'Geo::GDAL::Dataset') {
         Geo::GDAL::wrapper_GDALNearblackDestDS($dest, $self, $options, $progress, $progress_data);
@@ -1077,10 +1167,10 @@ sub Translate {
             my ($dest, $self) = @_;
             my $ds;
             if ($self->_GetRasterBand(1)) {
-                $options = Geo::GDAL::GDALTranslateOptions->new(Geo::GDAL::make_processing_options($options));
+                $options = Geo::GDAL::GDALTranslateOptions->new(make_processing_options($options));
                 $ds = Geo::GDAL::wrapper_GDALTranslate($dest, $self, $options, $progress, $progress_data);
             } else {
-                $options = Geo::GDAL::GDALVectorTranslateOptions->new(Geo::GDAL::make_processing_options($options));
+                $options = Geo::GDAL::GDALVectorTranslateOptions->new(make_processing_options($options));
                 Geo::GDAL::wrapper_GDALVectorTranslateDestDS($dest, $self, $options, $progress, $progress_data);
                 $ds = Geo::GDAL::wrapper_GDALVectorTranslateDestName($dest, $self, $options, $progress, $progress_data);
             }
@@ -1091,20 +1181,19 @@ sub Translate {
 
 sub Warped {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, SrcSRS => undef, DstSRS => undef, ResampleAlg => 'NearestNeighbour', MaxError => 0);
+    my $p = named_parameters(\@_, SrcSRS => undef, DstSRS => undef, ResampleAlg => 'NearestNeighbour', MaxError => 0);
     for my $srs (qw/srcsrs dstsrs/) {
         $p->{$srs} = $p->{$srs}->ExportToWkt if $p->{$srs} && blessed $p->{$srs};
     }
-    $p->{resamplealg} = Geo::GDAL::string2int($p->{resamplealg}, \%Geo::GDAL::RESAMPLING_STRING2INT);
+    $p->{resamplealg} = s2i(resampling => $p->{resamplealg});
     my $warped = Geo::GDAL::_AutoCreateWarpedVRT($self, $p->{srcsrs}, $p->{dstsrs}, $p->{resamplealg}, $p->{maxerror});
-    $BANDS{tied(%{$warped})} = $self if $warped; # self must live as long as warped
-    return $warped;
+    keep($warped, $self) if $warped; # self must live as long as warped
 }
 
 sub Warp {
     my ($self, $dest, $options, $progress, $progress_data) = @_;
     # can be run as object method (one dataset) and as package sub (a list of datasets)
-    $options = Geo::GDAL::GDALWarpAppOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALWarpAppOptions->new(make_processing_options($options));
     my $b = blessed($dest);
     $self = [$self] unless ref $self eq 'ARRAY';
     if ($b && $b eq 'Geo::GDAL::Dataset') {
@@ -1121,13 +1210,13 @@ sub Warp {
 
 sub Info {
     my ($self, $o) = @_;
-    $o = Geo::GDAL::GDALInfoOptions->new(Geo::GDAL::make_processing_options($o));
-    return Geo::GDAL::GDALInfo($self, $o);
+    $o = Geo::GDAL::GDALInfoOptions->new(make_processing_options($o));
+    return GDALInfo($self, $o);
 }
 
 sub Grid {
     my ($self, $dest, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALGridOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALGridOptions->new(make_processing_options($options));
     return $self->stdout_redirection_wrapper(
         $dest,
         \&Geo::GDAL::wrapper_GDALGrid,
@@ -1137,11 +1226,12 @@ sub Grid {
 
 sub Rasterize {
     my ($self, $dest, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALRasterizeOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALRasterizeOptions->new(make_processing_options($options));
     my $b = blessed($dest);
     if ($b && $b eq 'Geo::GDAL::Dataset') {
         Geo::GDAL::wrapper_GDALRasterizeDestDS($dest, $self, $options, $progress, $progress_data);
     } else {
+        # TODO: options need to force a new raster be made, otherwise segfault
         return $self->stdout_redirection_wrapper(
             $dest,
             \&Geo::GDAL::wrapper_GDALRasterizeDestName,
@@ -1152,8 +1242,8 @@ sub Rasterize {
 
 sub BuildVRT {
     my ($dest, $sources, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALBuildVRTOptions->new(Geo::GDAL::make_processing_options($options));
-    Geo::GDAL::error("Usage: Geo::GDAL::DataSet::BuildVRT(\$vrt_file_name, \\\@sources)")
+    $options = Geo::GDAL::GDALBuildVRTOptions->new(make_processing_options($options));
+    error("Usage: Geo::GDAL::DataSet::BuildVRT(\$vrt_file_name, \\\@sources)")
         unless ref $sources eq 'ARRAY' && defined $sources->[0];
     unless (blessed($dest)) {
         if (blessed($sources->[0])) {
@@ -1178,14 +1268,14 @@ sub BuildVRT {
 
 sub ComputeColorTable {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        Red => undef,
-                                        Green => undef,
-                                        Blue => undef,
-                                        NumColors => 256,
-                                        Progress => undef,
-                                        ProgressData => undef,
-                                        Method => 'MedianCut');
+    my $p = named_parameters(\@_,
+                             Red => undef,
+                             Green => undef,
+                             Blue => undef,
+                             NumColors => 256,
+                             Progress => undef,
+                             ProgressData => undef,
+                             Method => 'MedianCut');
     for my $b ($self->Bands) {
         for my $cion ($b->ColorInterpretation) {
             if ($cion eq 'RedBand') { $p->{red} //= $b; last; }
@@ -1205,14 +1295,14 @@ sub ComputeColorTable {
 
 sub Dither {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        Red => undef,
-                                        Green => undef,
-                                        Blue => undef,
-                                        Dest => undef,
-                                        ColorTable => undef,
-                                        Progress => undef,
-                                        ProgressData => undef);
+    my $p = named_parameters(\@_,
+                             Red => undef,
+                             Green => undef,
+                             Blue => undef,
+                             Dest => undef,
+                             ColorTable => undef,
+                             Progress => undef,
+                             ProgressData => undef);
     for my $b ($self->Bands) {
         for my $cion ($b->ColorInterpretation) {
             if ($cion eq 'RedBand') { $p->{red} //= $b; last; }
@@ -1253,22 +1343,53 @@ use POSIX;
 use Carp;
 use Scalar::Util 'blessed';
 
-use vars qw/ %RATS
-    @COLOR_INTERPRETATIONS
-    %COLOR_INTERPRETATION_STRING2INT %COLOR_INTERPRETATION_INT2STRING @DOMAINS
-    %MASK_FLAGS
+Geo::GDAL->import(qw(:INTERNAL));
+
+use vars qw/
+    @COLOR_INTERPRETATIONS @DOMAINS
+    %MASK_FLAGS %DATATYPE2PDL %PDL2DATATYPE
     /;
+
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
     push(@COLOR_INTERPRETATIONS, $1), next if /^GCI_(\w+)/;
 }
 for my $string (@COLOR_INTERPRETATIONS) {
     my $int = eval "\$Geo::GDAL::Constc::GCI_$string";
-    $COLOR_INTERPRETATION_STRING2INT{$string} = $int;
-    $COLOR_INTERPRETATION_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{color_interpretation}{$string} = $int;
+    $Geo::GDAL::I2S{color_interpretation}{$int} = $string;
 }
 @DOMAINS = qw/IMAGE_STRUCTURE RESAMPLING/;
 %MASK_FLAGS = (AllValid => 1, PerDataset => 2, Alpha => 4, NoData => 8);
+if ($Geo::GDAL::HAVE_PDL) {
+    require PDL;
+    require PDL::Types;
+    %DATATYPE2PDL = (
+        $Geo::GDAL::Const::GDT_Byte => $PDL::Types::PDL_B,
+        $Geo::GDAL::Const::GDT_Int16 => $PDL::Types::PDL_S,
+        $Geo::GDAL::Const::GDT_UInt16 => $PDL::Types::PDL_US,
+        $Geo::GDAL::Const::GDT_Int32 => $PDL::Types::PDL_L,
+        $Geo::GDAL::Const::GDT_UInt32 => -1,
+        #$PDL_IND,
+        #$PDL_LL,
+        $Geo::GDAL::Const::GDT_Float32 => $PDL::Types::PDL_F,
+        $Geo::GDAL::Const::GDT_Float64 => $PDL::Types::PDL_D,
+        $Geo::GDAL::Const::GDT_CInt16 => -1,
+        $Geo::GDAL::Const::GDT_CInt32 => -1,
+        $Geo::GDAL::Const::GDT_CFloat32 => -1,
+        $Geo::GDAL::Const::GDT_CFloat64 => -1
+        );
+    %PDL2DATATYPE = (
+        $PDL::Types::PDL_B => $Geo::GDAL::Const::GDT_Byte,
+        $PDL::Types::PDL_S => $Geo::GDAL::Const::GDT_Int16,
+        $PDL::Types::PDL_US => $Geo::GDAL::Const::GDT_UInt16,
+        $PDL::Types::PDL_L  => $Geo::GDAL::Const::GDT_Int32,
+        $PDL::Types::PDL_IND  => -1,
+        $PDL::Types::PDL_LL  => -1,
+        $PDL::Types::PDL_F  => $Geo::GDAL::Const::GDT_Float32,
+        $PDL::Types::PDL_D => $Geo::GDAL::Const::GDT_Float64
+        );
+}
 
 sub Domains {
     return @DOMAINS;
@@ -1294,27 +1415,28 @@ sub DESTROY {
     if (exists $OWNER{$self}) {
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::GDAL::Dataset::BANDS{$self};
+    unkeep($self);
 }
 
 sub Dataset {
     my $self = shift;
-    return $Geo::GDAL::Dataset::BANDS{tied(%{$self})};
+    parent($self);
 }
 
 sub Size {
     my $self = shift;
     return ($self->{XSize}, $self->{YSize});
 }
+*BlockSize = *GetBlockSize;
 
 sub DataType {
     my $self = shift;
-    return $Geo::GDAL::TYPE_INT2STRING{$self->{DataType}};
+    return i2s(data_type => $self->{DataType});
 }
 
 sub PackCharacter {
@@ -1364,8 +1486,8 @@ sub ReadTile {
     $w_tile //= $xsize;
     $h_tile //= $ysize;
     $alg //= 'NearestNeighbour';
+    $alg = s2i(rio_resampling => $alg);
     my $t = $self->{DataType};
-    $alg = Geo::GDAL::string2int($alg, \%Geo::GDAL::RIO_RESAMPLING_STRING2INT);
     my $buf = $self->_ReadRaster($xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $t, 0, 0, $alg);
     my $pc = Geo::GDAL::PackCharacter($t);
     my $w = $w_tile * Geo::GDAL::GetDataTypeSize($t)/8;
@@ -1383,6 +1505,7 @@ sub WriteTile {
     my($self, $data, $xoff, $yoff) = @_;
     $xoff //= 0;
     $yoff //= 0;
+    error('The data must be in a two-dimensional array') unless ref $data eq 'ARRAY' && ref $data->[0] eq 'ARRAY';
     my $xsize = @{$data->[0]};
     if ($xsize > $self->{XSize} - $xoff) {
         warn "Buffer XSize too large ($xsize) for this raster band (width = $self->{XSize}, offset = $xoff).";
@@ -1403,11 +1526,11 @@ sub WriteTile {
 sub ColorInterpretation {
     my($self, $ci) = @_;
     if (defined $ci) {
-        $ci = Geo::GDAL::string2int($ci, \%COLOR_INTERPRETATION_STRING2INT);
+        $ci = s2i(color_interpretation => $ci);
         SetRasterColorInterpretation($self, $ci);
     }
     return unless defined wantarray;
-    $COLOR_INTERPRETATION_INT2STRING{GetRasterColorInterpretation($self)};
+    i2s(color_interpretation => GetRasterColorInterpretation($self));
 }
 
 sub ColorTable {
@@ -1430,21 +1553,20 @@ sub AttributeTable {
     SetDefaultRAT($self, $_[0]) if @_ and defined $_[0];
     return unless defined wantarray;
     my $r = GetDefaultRAT($self);
-    $RATS{tied(%$r)} = $self if $r;
-    return $r;
+    keep($r, $self) if $r;
 }
 *RasterAttributeTable = *AttributeTable;
 
 sub GetHistogram {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        Min => -0.5,
-                                        Max => 255.5,
-                                        Buckets => 256,
-                                        IncludeOutOfRange => 0,
-                                        ApproxOK => 0,
-                                        Progress => undef,
-                                        ProgressData => undef);
+    my $p = named_parameters(\@_,
+                             Min => -0.5,
+                             Max => 255.5,
+                             Buckets => 256,
+                             IncludeOutOfRange => 0,
+                             ApproxOK => 0,
+                             Progress => undef,
+                             ProgressData => undef);
     $p->{progressdata} = 1 if $p->{progress} and not defined $p->{progressdata};
     _GetHistogram($self, $p->{min}, $p->{max}, $p->{buckets},
                   $p->{includeoutofrange}, $p->{approxok},
@@ -1453,17 +1575,17 @@ sub GetHistogram {
 
 sub Contours {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        DataSource => undef,
-                                        LayerConstructor => {Name => 'contours'},
-                                        ContourInterval => 100,
-                                        ContourBase => 0,
-                                        FixedLevels => [],
-                                        NoDataValue => undef,
-                                        IDField => -1,
-                                        ElevField => -1,
-                                        Progress => undef,
-                                        ProgressData => undef);
+    my $p = named_parameters(\@_,
+                             DataSource => undef,
+                             LayerConstructor => {Name => 'contours'},
+                             ContourInterval => 100,
+                             ContourBase => 0,
+                             FixedLevels => [],
+                             NoDataValue => undef,
+                             IDField => -1,
+                             ElevField => -1,
+                             Progress => undef,
+                             ProgressData => undef);
     $p->{datasource} //= Geo::OGR::GetDriver('Memory')->CreateDataSource('ds');
     $p->{layerconstructor}->{Schema} //= {};
     $p->{layerconstructor}->{Schema}{Fields} //= [];
@@ -1503,22 +1625,22 @@ sub ReadRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->DataType;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        XOff => 0,
-                                        YOff => 0,
-                                        XSize => $width,
-                                        YSize => $height,
-                                        BufXSize => undef,
-                                        BufYSize => undef,
-                                        BufType => $type,
-                                        BufPixelSpace => 0,
-                                        BufLineSpace => 0,
-                                        ResampleAlg => 'NearestNeighbour',
-                                        Progress => undef,
-                                        ProgressData => undef
+    my $p = named_parameters(\@_,
+                             XOff => 0,
+                             YOff => 0,
+                             XSize => $width,
+                             YSize => $height,
+                             BufXSize => undef,
+                             BufYSize => undef,
+                             BufType => $type,
+                             BufPixelSpace => 0,
+                             BufLineSpace => 0,
+                             ResampleAlg => 'NearestNeighbour',
+                             Progress => undef,
+                             ProgressData => undef
         );
-    $p->{resamplealg} = Geo::GDAL::string2int($p->{resamplealg}, \%Geo::GDAL::RIO_RESAMPLING_STRING2INT);
-    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $p->{resamplealg} = s2i(rio_resampling => $p->{resamplealg});
+    $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
     $self->_ReadRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bufpixelspace},$p->{buflinespace},$p->{resamplealg},$p->{progress},$p->{progressdata});
 }
 
@@ -1526,20 +1648,20 @@ sub WriteRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->DataType;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        XOff => 0,
-                                        YOff => 0,
-                                        XSize => $width,
-                                        YSize => $height,
-                                        Buf => undef,
-                                        BufXSize => undef,
-                                        BufYSize => undef,
-                                        BufType => $type,
-                                        BufPixelSpace => 0,
-                                        BufLineSpace => 0
+    my $p = named_parameters(\@_,
+                             XOff => 0,
+                             YOff => 0,
+                             XSize => $width,
+                             YSize => $height,
+                             Buf => undef,
+                             BufXSize => undef,
+                             BufYSize => undef,
+                             BufType => $type,
+                             BufPixelSpace => 0,
+                             BufLineSpace => 0
         );
     confess "Usage: \$band->WriteRaster( Buf => \$data, ... )" unless defined $p->{buf};
-    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
     $self->_WriteRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{buf},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bufpixelspace},$p->{buflinespace});
 }
 
@@ -1568,46 +1690,66 @@ sub CreateMaskBand {
 }
 
 sub Piddle {
-    my $self = shift; # should use named parameters for read raster and band
-    # add Piddle sub to dataset too to make N x M x n piddles
-    my ($w, $h) = $self->Size;
-    my $data = $self->ReadRaster;
+    # TODO: add Piddle sub to dataset too to make Width x Height x Bands piddles
+    error("PDL is not available.") unless $Geo::GDAL::HAVE_PDL;
+    my $self = shift;
+    my $t = $self->{DataType};
+    unless (defined wantarray) {
+        my $pdl = shift;
+        error("The datatype of the Piddle and the band do not match.") 
+          unless $PDL2DATATYPE{$pdl->get_datatype} == $t;
+        my ($xoff, $yoff, $xsize, $ysize) = @_;
+        $xoff //= 0;
+        $yoff //= 0;
+        my $data = $pdl->get_dataref();
+        my ($xdim, $ydim) = $pdl->dims();
+        if ($xdim > $self->{XSize} - $xoff) {
+            warn "Piddle XSize too large ($xdim) for this raster band (width = $self->{XSize}, offset = $xoff).";
+            $xdim = $self->{XSize} - $xoff;
+        }
+        if ($ydim > $self->{YSize} - $yoff) {
+            $ydim = $self->{YSize} - $yoff;
+            warn "Piddle YSize too large ($ydim) for this raster band (height = $self->{YSize}, offset = $yoff).";
+        }
+        $xsize //= $xdim;
+        $ysize //= $ydim;
+        $self->_WriteRaster($xoff, $yoff, $xsize, $ysize, $data, $xdim, $ydim, $t, 0, 0);
+        return;
+    }
+    my ($xoff, $yoff, $xsize, $ysize, $xdim, $ydim, $alg) = @_;
+    $xoff //= 0;
+    $yoff //= 0;
+    $xsize //= $self->{XSize} - $xoff;
+    $ysize //= $self->{YSize} - $yoff;
+    $xdim //= $xsize;
+    $ydim //= $ysize;
+    $alg //= 'NearestNeighbour';
+    $alg = s2i(rio_resampling => $alg);
+    my $buf = $self->_ReadRaster($xoff, $yoff, $xsize, $ysize, $xdim, $ydim, $t, 0, 0, $alg);
     my $pdl = PDL->new;
-    my %map = (
-        Byte => 0,
-        UInt16 => 2,
-        Int16 => 1,
-        UInt32 => -1,
-        Int32 => 3,
-        Float32 => 5,
-        Float64 => 6,
-        CInt16 => -1,
-        CInt32 => -1,
-        CFloat32 => -1,
-        CFloat64 => -1
-        );
-    my $datatype = $map{$self->DataType};
-    croak "there is no direct mapping between the band datatype and PDL" if $datatype < 0;
+    my $datatype = $DATATYPE2PDL{$t};
+    error("The band datatype is not supported by PDL.") if $datatype < 0;
     $pdl->set_datatype($datatype);
-    $pdl->setdims([1,$w,$h]);
-    my $dref = $pdl->get_dataref();
-    $$dref = $data;
+    $pdl->setdims([$xdim, $ydim]);
+    my $data = $pdl->get_dataref();
+    $$data = $buf;
     $pdl->upd_data;
+    # FIXME: we want approximate equality since no data value can be very large floating point value
+    my $bad = GetNoDataValue($self);
+    return $pdl->setbadif($pdl == $bad) if defined $bad;
     return $pdl;
 }
 
 sub GetMaskBand {
     my $self = shift;
     my $band = _GetMaskBand($self);
-    $Geo::GDAL::Dataset::BANDS{tied(%{$band})} = $self;
-    return $band;
+    keep($band, $self);
 }
 
 sub GetOverview {
     my ($self, $index) = @_;
     my $band = _GetOverview($self, $index);
-    $Geo::GDAL::Dataset::BANDS{tied(%{$band})} = $self;
-    return $band;
+    keep($band, $self);
 }
 
 sub RegenerateOverview {
@@ -1626,7 +1768,12 @@ sub RegenerateOverviews {
 
 sub Polygonize {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Mask => undef, OutLayer => undef, PixValField => 'val', Options => undef, Progress => undef, ProgressData => undef);
+    my $p = named_parameters(\@_, Mask => undef, OutLayer => undef, PixValField => 'val', Options => undef, Progress => undef, ProgressData => undef);
+    my %known_options = (Connectedness => 1, ForceIntPixel => 1, DATASET_FOR_GEOREF => 1, '8CONNECTED' => 1);
+    for my $option (keys %{$p->{options}}) {
+        error(1, $option, \%known_options) unless exists $known_options{$option};
+    }
+
     my $dt = $self->DataType;
     my %leInt32 = (Byte => 1, Int16 => 1, Int32 => 1, UInt16 => 1);
     my $leInt32 = $leInt32{$dt};
@@ -1636,7 +1783,7 @@ sub Polygonize {
                     Fields => [{Name => 'val', Type => $dt},
                                {Name => 'geom', Type => 'Polygon'}]);
     $p->{pixvalfield} = $p->{outlayer}->GetLayerDefn->GetFieldIndex($p->{pixvalfield});
-    $p->{options}{'8CONNECTED'} = $p->{options}{Connectedness} if $p->{options}{Connectedness};
+    $p->{options}{'8CONNECTED'} = 1 if $p->{options}{Connectedness} && $p->{options}{Connectedness} == 8;
     if ($leInt32 || $p->{options}{ForceIntPixel}) {
         Geo::GDAL::_Polygonize($self, $p->{mask}, $p->{outlayer}, $p->{pixvalfield}, $p->{options}, $p->{progress}, $p->{progressdata});
     } else {
@@ -1648,7 +1795,7 @@ sub Polygonize {
 
 sub Sieve {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Mask => undef, Dest => undef, Threshold => 10, Options => undef, Progress => undef, ProgressData => undef);
+    my $p = named_parameters(\@_, Mask => undef, Dest => undef, Threshold => 10, Options => undef, Progress => undef, ProgressData => undef);
     unless ($p->{dest}) {
         my ($w, $h) = $self->Size;
         $p->{dest} = Geo::GDAL::Driver('MEM')->Create(Name => 'sieved', Width => $w, Height => $h, Type => $self->DataType)->Band;
@@ -1664,7 +1811,7 @@ sub Sieve {
 
 sub Distance {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Distance => undef, Options => undef, Progress => undef, ProgressData => undef);
+    my $p = named_parameters(\@_, Distance => undef, Options => undef, Progress => undef, ProgressData => undef);
     for my $key (keys %{$p->{options}}) {
         $p->{options}{uc($key)} = $p->{options}{$key};
     }
@@ -1685,12 +1832,13 @@ use strict;
 use warnings;
 use Carp;
 
-use vars qw/%PALETTE_INTERPRETATION_STRING2INT %PALETTE_INTERPRETATION_INT2STRING/;
+Geo::GDAL->import(qw(:INTERNAL));
+
 for (keys %Geo::GDAL::Const::) {
     if (/^GPI_(\w+)/) {
         my $int = eval "\$Geo::GDAL::Const::GPI_$1";
-        $PALETTE_INTERPRETATION_STRING2INT{$1} = $int;
-        $PALETTE_INTERPRETATION_INT2STRING{$int} = $1;
+        $Geo::GDAL::S2I{palette_interpretation}{$1} = $int;
+        $Geo::GDAL::I2S{palette_interpretation}{$int} = $1;
     }
 }
 %}
@@ -1701,7 +1849,7 @@ use Carp;
 sub new {
     my($pkg, $pi) = @_;
     $pi //= 'RGB';
-    $pi = Geo::GDAL::string2int($pi, \%PALETTE_INTERPRETATION_STRING2INT);
+    $pi = s2i(palette_interpretation => $pi);
     my $self = Geo::GDALc::new_ColorTable($pi);
     bless $self, $pkg if defined($self);
 }
@@ -1710,7 +1858,7 @@ sub new {
 %perlcode %{
 sub GetPaletteInterpretation {
     my $self = shift;
-    return $PALETTE_INTERPRETATION_INT2STRING{GetPaletteInterpretation($self)};
+    return i2s(palette_interpretation => GetPaletteInterpretation($self));
 }
 
 sub SetColorEntry {
@@ -1725,7 +1873,7 @@ sub SetColorEntry {
     eval {
         $self->_SetColorEntry($index, $color);
     };
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
 }
 
 sub ColorEntry {
@@ -1764,11 +1912,9 @@ use strict;
 use warnings;
 use Carp;
 
-use vars qw/
-    @FIELD_TYPES @FIELD_USAGES
-    %FIELD_TYPE_STRING2INT %FIELD_TYPE_INT2STRING
-    %FIELD_USAGE_STRING2INT %FIELD_USAGE_INT2STRING
-    /;
+Geo::GDAL->import(qw(:INTERNAL));
+
+use vars qw(@FIELD_TYPES @FIELD_USAGES);
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
     push(@FIELD_TYPES, $1), next if /^GFT_(\w+)/;
@@ -1776,13 +1922,13 @@ for (keys %Geo::GDAL::Const::) {
 }
 for my $string (@FIELD_TYPES) {
     my $int = eval "\$Geo::GDAL::Constc::GFT_$string";
-    $FIELD_TYPE_STRING2INT{$string} = $int;
-    $FIELD_TYPE_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{rat_field_type}{$string} = $int;
+    $Geo::GDAL::I2S{rat_field_type}{$int} = $string;
 }
 for my $string (@FIELD_USAGES) {
     my $int = eval "\$Geo::GDAL::Constc::GFU_$string";
-    $FIELD_USAGE_STRING2INT{$string} = $int;
-    $FIELD_USAGE_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{rat_field_usage}{$string} = $int;
+    $Geo::GDAL::I2S{rat_field_usage}{$int} = $string;
 }
 
 sub FieldTypes {
@@ -1793,29 +1939,29 @@ sub FieldUsages {
     return @FIELD_USAGES;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::GDAL::Band::RATS{$self};
+    unkeep($self);
 }
 
 sub Band {
     my $self = shift;
-    return $Geo::GDAL::Band::RATS{tied(%$self)};
+    parent($self);
 }
 
 sub GetUsageOfCol {
     my($self, $col) = @_;
-    $FIELD_USAGE_INT2STRING{_GetUsageOfCol($self, $col)};
+    i2s(rat_field_usage => _GetUsageOfCol($self, $col));
 }
 
 sub GetColOfUsage {
     my($self, $usage) = @_;
-    _GetColOfUsage($self, $FIELD_USAGE_STRING2INT{$usage});
+    _GetColOfUsage($self, s2i(rat_field_usage => $usage));
 }
 
 sub GetTypeOfCol {
     my($self, $col) = @_;
-    $FIELD_TYPE_INT2STRING{_GetTypeOfCol($self, $col)};
+    i2s(rat_field_type => _GetTypeOfCol($self, $col));
 }
 
 sub Columns {
@@ -1841,8 +1987,8 @@ sub CreateColumn {
     for my $color (qw/Red Green Blue Alpha/) {
         carp "RAT column type will be 'Integer' for usage '$color'." if $usage eq $color and $type ne 'Integer';
     }
-    $type = Geo::GDAL::string2int($type, \%FIELD_TYPE_STRING2INT);
-    $usage = Geo::GDAL::string2int($usage, \%FIELD_USAGE_STRING2INT);
+    $type = s2i(rat_field_type => $type);
+    $usage = s2i(rat_field_usage => $usage);
     _CreateColumn($self, $name, $type, $usage);
 }
 
@@ -1871,7 +2017,7 @@ package Geo::GDAL::GCP;
 *swig_Line_get = *Geo::GDALc::GCP_Row_get;
 *swig_Line_set = *Geo::GDALc::GCP_Row_set;
 
-
+Geo::GDAL->import(qw(:INTERNAL));
 
 package Geo::GDAL::VSIF;
 use strict;
@@ -1883,6 +2029,8 @@ our @ISA = qw(Exporter);
 our @EXPORT_OK   = qw(Open Close Write Read Seek Tell Truncate MkDir ReadDir ReadDirRecursive Rename RmDir Stat Unlink);
 our %EXPORT_TAGS = (all => \@EXPORT_OK);
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub Open {
     my ($path, $mode) = @_;
     my $self = Geo::GDAL::VSIFOpenL($path, $mode);
@@ -1962,7 +2110,7 @@ sub RmDir {
     };
     if ($@) {
         my $r = $recursive ? ' recursively' : '';
-        Geo::GDAL::error("Cannot remove directory \"$dirname\"$r.");
+        error("Cannot remove directory \"$dirname\"$r.");
     }
 }
 *Rmdir = *RmDir;
@@ -1986,19 +2134,29 @@ use warnings;
 use Carp;
 use Scalar::Util 'blessed';
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub new {
     my $class = shift;
     my $self;
     if (@_ == 0) {
         $self = [0,1,0,0,0,1];
-    } elsif (@_ == 1) {
-        $self = $_[0];
+    } elsif (ref $_[0]) {
+        @$self = @{$_[0]};
+    } elsif ($_[0] =~ /^[a-zA-Z]/i) {
+        my $p = named_parameters(\@_, GCPs => undef, ApproxOK => 1, Extent => undef, CellSize => 1);
+        if ($p->{gcps}) {
+            $self = Geo::GDAL::GCPsToGeoTransform($p->{gcps}, $p->{approxok});
+        } elsif ($p->{extent}) {
+            $self = Geo::GDAL::GeoTransform->new($p->{extent}[0], $p->{cellsize}, 0, $p->{extent}[2], 0, -$p->{cellsize});
+        } else {
+            error("Missing GCPs or Extent");
+        }
     } else {
         my @a = @_;
         $self = \@a;
     }
     bless $self, $class;
-    return $self;
 }
 
 sub NorthUp {
@@ -2019,7 +2177,7 @@ sub FromGCPs {
         }
     }
     my $approx_ok = shift // 1;
-    Geo::GDAL::error('Usage: Geo::GDAL::GeoTransform::FromGCPs(\@gcps, $approx_ok)') unless @$gcps;
+    error('Usage: Geo::GDAL::GeoTransform::FromGCPs(\@gcps, $approx_ok)') unless @$gcps;
     my $self = Geo::GDAL::GCPsToGeoTransform($gcps, $approx_ok);
     bless $self, 'Geo::GDAL::GetTransform';
     return $self;
@@ -2027,6 +2185,7 @@ sub FromGCPs {
 
 sub Apply {
     my ($self, $columns, $rows) = @_;
+    return Geo::GDAL::ApplyGeoTransform($self, $columns, $rows) unless ref($columns) eq 'ARRAY';
     my (@x, @y);
     for my $i (0..$#$columns) {
         ($x[$i], $y[$i]) =
@@ -2038,7 +2197,7 @@ sub Apply {
 sub Inv {
     my $self = shift;
     my @inv = Geo::GDAL::InvGeoTransform($self);
-    return new(@inv) if defined wantarray;
+    return Geo::GDAL::GeoTransform->new(@inv) if defined wantarray;
     @$self = @inv;
 }
 
@@ -2063,11 +2222,13 @@ use warnings;
 use Carp;
 use Scalar::Util 'blessed';
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub new {
     my $class = shift;
     my $self;
     if (@_ == 0) {
-        $self = [0,0,0,0];
+        $self = [0,0,-1,0];
     } elsif (ref $_[0]) {
         @$self = @{$_[0]};
     } else {
@@ -2077,8 +2238,14 @@ sub new {
     return $self;
 }
 
+sub IsEmpty {
+    my $self = shift;
+    return $self->[2] < $self->[0];
+}
+
 sub Size {
     my $self = shift;
+    return (0,0) if $self->IsEmpty;
     return ($self->[2] - $self->[0], $self->[3] - $self->[1]);
 }
 
@@ -2089,7 +2256,7 @@ sub Overlaps {
 
 sub Overlap {
     my ($self, $e) = @_;
-    return undef unless $self->Overlaps($e);
+    return Geo::GDAL::Extent->new() unless $self->Overlaps($e);
     my $ret = Geo::GDAL::Extent->new($self);
     $ret->[0] = $e->[0] if $self->[0] < $e->[0];
     $ret->[1] = $e->[1] if $self->[1] < $e->[1];
@@ -2100,10 +2267,15 @@ sub Overlap {
 
 sub ExpandToInclude {
     my ($self, $e) = @_;
-    $self->[0] = $e->[0] if $e->[0] < $self->[0];
-    $self->[1] = $e->[1] if $e->[1] < $self->[1];
-    $self->[2] = $e->[2] if $e->[2] > $self->[2];
-    $self->[3] = $e->[3] if $e->[3] > $self->[3];
+    return if $e->IsEmpty;
+    if ($self->IsEmpty) {
+        @$self = @$e;
+    } else {
+        $self->[0] = $e->[0] if $e->[0] < $self->[0];
+        $self->[1] = $e->[1] if $e->[1] < $self->[1];
+        $self->[2] = $e->[2] if $e->[2] > $self->[2];
+        $self->[3] = $e->[3] if $e->[3] > $self->[3];
+    }
 }
 
 package Geo::GDAL::XML;
@@ -2112,6 +2284,8 @@ use strict;
 use warnings;
 use Carp;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 # XML related subs in Geo::GDAL
 
 #Geo::GDAL::Child
@@ -2125,7 +2299,7 @@ use Carp;
 sub new {
     my $class = shift;
     my $xml = shift // '';
-    my $self = Geo::GDAL::ParseXMLString($xml);
+    my $self = ParseXMLString($xml);
     bless $self, $class;
     $self->traverse(sub {my $node = shift; bless $node, $class});
     return $self;
@@ -2135,7 +2309,7 @@ sub traverse {
     my ($self, $sub) = @_;
     my $type = $self->[0];
     my $data = $self->[1];
-    $type = Geo::GDAL::NodeType($type);
+    $type = NodeType($type);
     $sub->($self, $type, $data);
     for my $child (@{$self}[2..$#$self]) {
         traverse($child, $sub);
@@ -2144,30 +2318,7 @@ sub traverse {
 
 sub serialize {
     my $self = shift;
-    return Geo::GDAL::SerializeXMLTree($self);
+    return SerializeXMLTree($self);
 }
 
 %}
-
-%{
-typedef void OGRLayerShadow;
-%}
-%extend GDALRasterBandShadow {
-    %apply (int nList, double* pList) {(int nFixedLevelCount, double *padfFixedLevels)};
-    %apply (int defined, double value) {(int bUseNoData, double dfNoDataValue)};
-    CPLErr ContourGenerate(double dfContourInterval, double dfContourBase,
-                           int nFixedLevelCount, double *padfFixedLevels,
-                           int bUseNoData, double dfNoDataValue,
-                           OGRLayerShadow *hLayer, int iIDField, int iElevField,
-                           GDALProgressFunc progress = NULL,
-                           void* progress_data = NULL) {
-        return GDALContourGenerate( self, dfContourInterval, dfContourBase,
-                                    nFixedLevelCount, padfFixedLevels,
-                                    bUseNoData, dfNoDataValue,
-                                    hLayer, iIDField, iElevField,
-                                    progress,
-                                    progress_data );
-    }
-    %clear (int nFixedLevelCount, double *padfFixedLevels);
-    %clear (int bUseNoData, double dfNoDataValue);
-}
diff --git a/swig/include/perl/gnm_perl.i b/swig/include/perl/gnm_perl.i
new file mode 100644
index 0000000..93193fa
--- /dev/null
+++ b/swig/include/perl/gnm_perl.i
@@ -0,0 +1,30 @@
+/******************************************************************************
+ *
+ * Project:  GNM SWIG Interface declarations for Perl.
+ *****************************************************************************/
+
+%init %{
+
+  /*UseExceptions(); is set by GDAL module */
+  if ( OGRGetDriverCount() == 0 ) {
+    OGRRegisterAll();
+  }
+
+%}
+
+%include callback.i
+%include confess.i
+%include cpl_exceptions.i
+
+%rename (GetDriverCount) OGRGetDriverCount;
+%rename (GetOpenDSCount) OGRGetOpenDSCount;
+%rename (RegisterAll) OGRRegisterAll();
+
+%import typemaps_perl.i
+
+%import destroy.i
+
+%rename (_CreateLayer) CreateLayer;
+%rename (_DeleteLayer) DeleteLayer;
+%rename (_Validate) Validate;
+
diff --git a/swig/include/perl/init.i b/swig/include/perl/init.i
new file mode 100644
index 0000000..ac224cd
--- /dev/null
+++ b/swig/include/perl/init.i
@@ -0,0 +1,48 @@
+%perlcode %{
+
+    # keeper maintains child -> parent relationships
+    # child is kept as a key, i.e., string not the real object 
+    # parent is kept as the value, i.e., a real object
+    # a child may have only one parent!
+    # call these as Geo::GDAL::*
+
+    my %keeper;
+    my %notes;
+
+    sub note {
+        my ($object, $note) = @_;
+        if (defined wantarray) {
+            return unless $note{$object};
+            return $notes{$object}{$note};
+        }
+        $notes{$object}{$note} = 1;
+    }
+
+    sub unnote {
+        my ($object, $note) = @_;
+        if ($note) {
+            delete $notes{$object}{$note};
+        } else {
+            delete $notes{$object};
+        }
+    }
+
+    sub keep {
+        my ($child, $parent) = @_;
+        $keeper{tied(%$child)} = $parent;
+        return $child;
+    }
+
+    # this is called from RELEASE_PARENT, so the child is already the tied one
+    sub unkeep {
+        my ($child) = @_;
+        delete $keeper{$child};
+    }
+    
+    sub parent {
+        my ($child) = @_;
+        $child = tied(%$child) if $child->isa('HASH');
+        return $keeper{$child};
+    }
+
+%}
diff --git a/swig/include/perl/ogr_perl.i b/swig/include/perl/ogr_perl.i
index 7ae6093..3a07284 100644
--- a/swig/include/perl/ogr_perl.i
+++ b/swig/include/perl/ogr_perl.i
@@ -100,6 +100,12 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 
 }
 
+%rename (_GetFieldIndex) GetFieldIndex;
+%rename (_GetGeomFieldIndex) GetGeomFieldIndex;
+
+%rename (_GetFieldDefn) GetFieldDefn;
+%rename (_GetGeomFieldDefn) GetGeomFieldDefn;
+
 /* wrapped layer methods: */
 %rename (_TestCapability) TestCapability;
 %rename (_ReleaseResultSet) ReleaseResultSet;
@@ -120,7 +126,21 @@ ALTERED_DESTROY(OGRGeometryShadow, OGRc, delete_Geometry)
 %perlcode %{
 
 package Geo::OGR;
-our $VERSION = '2.0103'; # this needs to be the same as that in gdal_perl.i
+our $VERSION = '2.0200'; # this needs to be the same as that in gdal_perl.i
+
+Geo::GDAL->import(qw(:INTERNAL));
+
+use vars qw(@EXPORT_OK %EXPORT_TAGS);
+BEGIN {
+ at EXPORT_OK = qw(HasZ HasM Flatten);
+%EXPORT_TAGS = (
+    all => [qw()],
+    INTERNAL => [qw(HasZ HasM Flatten)]
+    );
+}
+*HasZ = *GT_HasZ;
+*HasM = *GT_HasM;
+*Flatten = *GT_Flatten;
 
 sub Driver {
     return 'Geo::GDAL::Driver' unless @_;
@@ -152,7 +172,7 @@ sub Open {
     my @flags = qw/VECTOR/;
     push @flags, qw/UPDATE/ if $p[1];
     my $dataset = Geo::GDAL::OpenEx($p[0], \@flags);
-    Geo::GDAL::error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
+    error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
     return $dataset;
 }
 
@@ -161,13 +181,15 @@ sub OpenShared {
     my @flags = qw/VECTOR SHARED/;
     push @flags, qw/UPDATE/ if $p[1];
     my $dataset = Geo::GDAL::OpenEx($p[0], \@flags);
-    Geo::GDAL::error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
+    error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
     return $dataset;
 }
 
 package Geo::OGR::Driver;
 our @ISA = qw/Geo::GDAL::Driver/;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub Create {
     my ($self, $name, $options) = @_; # name, options
     $options //= {};
@@ -187,13 +209,15 @@ sub Open {
     my @flags = qw/VECTOR/;
     push @flags, qw/UPDATE/ if $p[1];
     my $dataset = Geo::GDAL::OpenEx($p[0], \@flags, [$self->Name()]);
-    Geo::GDAL::error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
+    error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
     return $dataset;
 }
 
 
 package Geo::OGR::DataSource;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 *Open = *Geo::OGR::Open;
 *OpenShared = *Geo::OGR::OpenShared;
 
@@ -203,7 +227,10 @@ use strict;
 use warnings;
 use Carp;
 use Scalar::Util 'blessed';
-use vars qw /@CAPABILITIES %CAPABILITIES %DEFNS %FEATURES/;
+use vars qw /@CAPABILITIES %CAPABILITIES/;
+
+Geo::GDAL->import(qw(:INTERNAL));
+
 for (keys %Geo::OGR::) {
     push(@CAPABILITIES, $1), next if /^OLC(\w+)/;
 }
@@ -219,25 +246,25 @@ sub DESTROY {
         $self = tied(%{$self});
         return unless defined $self;
     }
-    if ($Geo::GDAL::Dataset::RESULT_SET{$self}) {
-        $Geo::GDAL::Dataset::LAYERS{$self}->_ReleaseResultSet($self);
-        delete $Geo::GDAL::Dataset::RESULT_SET{$self}
+    if (note($self, 'is result set')) {
+        parent($self)->_ReleaseResultSet($self);
+        unnote($self);
     }
     delete $ITERATORS{$self};
     if (exists $OWNER{$self}) {
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::GDAL::Dataset::LAYERS{$self};
+    unkeep($self);
 }
 
 sub Dataset {
     my $self = shift;
-    return $Geo::GDAL::Dataset::LAYERS{tied(%$self)};
+    parent($self);
 }
 
 sub Capabilities {
@@ -257,15 +284,14 @@ sub TestCapability {
 
 sub GetDataSource {
     my $self = shift;
-    return $Geo::GDAL::Dataset::LAYERS{tied(%$self)};
+    parent($self);
 }
 *DataSource = *GetDataSource;
 
 sub GetDefn {
     my $self = shift;
     my $defn = $self->GetLayerDefn;
-    $DEFNS{tied(%$defn)} = $self;
-    return $defn;
+    keep($defn, $self);
 }
 
 sub CreateField {
@@ -289,46 +315,62 @@ sub CreateField {
     } elsif (blessed($_[0]) and $params{Defn}->isa('Geo::OGR::GeomFieldDefn')) {
         $self->CreateGeomField($params{Defn}, $params{ApproxOK});
     } else {
+        # if Name and Type are missing, assume Name => Type
+        if (!(exists $params{Name} && exists $params{Type})) {
+            for my $key (sort keys %params) {
+                if (s_exists(field_type => $params{$key}) ||
+                    s_exists(geometry_type => $params{$key}))
+                {
+                    $params{Name} = $key;
+                    $params{Type} = $params{$key};
+                    delete $params{$key};
+                    last;
+                }
+            }
+        }
         my $a = $params{ApproxOK};
         delete $params{ApproxOK};
         if (exists $params{GeometryType}) {
             $params{Type} = $params{GeometryType};
             delete $params{GeometryType};
         }
-        if (exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$params{Type}}) {
+        if (s_exists(field_type => $params{Type})) {
             my $fd = Geo::OGR::FieldDefn->new(%params);
             _CreateField($self, $fd, $a);
-        } elsif (exists $Geo::OGR::Geometry::TYPE_STRING2INT{$params{Type}}) {
+        } elsif (s_exists(geometry_type => $params{Type})) {
             my $fd = Geo::OGR::GeomFieldDefn->new(%params);
             CreateGeomField($self, $fd, $a);
+        } elsif ($params{Type} ) {
+            error("Invalid field type: $params{Type}.")
+        } elsif ($params{Name} ) {
+            error("Missing type for field: $params{Name}.")
         } else {
-            Geo::GDAL::error("Invalid field type: $params{Type}.")
+            error("Missing name and type for a field.")
         }
     }
 }
 
 sub AlterFieldDefn {
     my $self = shift;
-    my $field = shift;
-    my $index = $self->GetLayerDefn->GetFieldIndex($field);
-    if (blessed($_[0]) and $_[0]->isa('Geo::OGR::FieldDefn')) {
+    my $index = $self->GetLayerDefn->GetFieldIndex(shift // 0);
+    my $param = @_ % 2 == 0 ? {@_} : shift;
+    if (blessed($param) and $param->isa('Geo::OGR::FieldDefn')) {
         _AlterFieldDefn($self, $index, @_);
     } else {
-        my $params = @_ % 2 == 0 ? {@_} : shift;
-        my $definition = Geo::OGR::FieldDefn->new($params);
+        my $definition = Geo::OGR::FieldDefn->new($param);
         my $flags = 0;
-        $flags |= 1 if exists $params->{Name};
-        $flags |= 2 if exists $params->{Type};
-        $flags |= 4 if exists $params->{Width} or exists $params->{Precision};
-        $flags |= 8 if exists $params->{Nullable};
-        $flags |= 16 if exists $params->{Default};
+        $flags |= 1 if exists $param->{Name};
+        $flags |= 2 if exists $param->{Type};
+        $flags |= 4 if exists $param->{Width} or exists $param->{Precision};
+        $flags |= 8 if exists $param->{Nullable};
+        $flags |= 16 if exists $param->{Default};
         _AlterFieldDefn($self, $index, $definition, $flags);
     }
 }
 
 sub DeleteField {
-    my($self, $field) = @_;
-    my $index = $self->GetLayerDefn->GetFieldIndex($field);
+    my ($self, $field) = @_;
+    my $index = $self->GetLayerDefn->GetFieldIndex($field // 0);
     _DeleteField($self, $index);
 }
 
@@ -390,30 +432,47 @@ sub SpatialFilter {
     $self->GetSpatialFilter;
 }
 
+*FeatureCount = *GetFeatureCount;
+
 sub InsertFeature {
     my $self = shift;
     my $feature = shift;
-    Geo::GDAL::error("Usage: \$feature->InsertFeature(reference to a hash or array).") unless ref($feature);
-    my $new = Geo::OGR::Feature->new($self->GetDefn);
-    if (ref($feature) eq 'HASH') {
-        $new->Row(%$feature);
-    } elsif (ref($feature) eq 'ARRAY') {
-        $new->Tuple(@$feature);
-    } elsif (blessed($feature) and $feature->isa('Geo::OGR::Feature')) {
-        $new->Row($feature->Row);
-    }
+    error("Usage: \$feature->InsertFeature(reference to a hash or array).") unless ref($feature);
+    my $new = Geo::OGR::Feature->new(Schema => $self, Values => $feature);
     $self->CreateFeature($new);
     return unless defined wantarray;
-    $FEATURES{tied(%$new)} = $self;
-    return $new;
+    keep($new, $self);
 }
 
 sub GetFeature {
     my ($self, $fid) = @_;
     $fid //= 0;
     my $f = $self->_GetFeature($fid);
-    $FEATURES{tied(%$f)} = $self;
-    return $f;
+    error(2, "FID=$fid", '"Feature') unless ref $f eq 'Geo::OGR::Feature';
+    keep($f, $self);
+}
+
+sub Feature {
+    my $self = shift;
+    my $x = shift;
+    return $self->GetFeature($x) unless $x && ref $x;
+    # Insert or Set depending on the FID
+    my $fid;
+    if (ref $x eq 'ARRAY') {
+        # FID is the first item in the array
+        $fid = $x->[0];
+    } elsif (ref $x eq 'HASH') {
+        # FID is FID
+        $fid = $x->{FID};
+    } else {
+        $fid = $x->FID;
+    }
+    # OGRNullFID is -1
+    if (!defined $fid || $fid < 0) {
+        $self->InsertFeature($x);
+    } else {
+        $self->SetFeature($x);
+    }
 }
 
 sub ForFeatures {
@@ -422,7 +481,7 @@ sub ForFeatures {
     my $in_place = shift;
     $self->ResetReading;
     while (my $f = $self->GetNextFeature) {
-        $FEATURES{tied(%$f)} = $self;
+        keep($f, $self);
         $code->($f);
         $self->SetFeature($f) if $in_place;
     };
@@ -457,37 +516,33 @@ sub GetFieldNames {
 }
 
 sub GetFieldDefn {
-    my ($self, $name) = @_;
+    my $self = shift;
     my $d = $self->GetDefn;
-    for (my $i = 0; $i < $d->GetFieldCount; $i++) {
-        my $fd = $d->GetFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    for (my $i = 0; $i < $d->GetGeomFieldCount; $i++) {
-        my $fd = $d->GetGeomFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    Geo::GDAL::error(2, $name, 'Field');
+    my $field = $d->GetFieldIndex(shift // 0);
+    return $d->_GetFieldDefn($field);
+}
+
+sub GetGeomFieldDefn {
+    my $self = shift;
+    my $d = $self->GetDefn;
+    my $field = $d->GetGeomFieldIndex(shift // 0);
+    return $d->_GetGeomFieldDefn($field);
 }
 
 sub GeometryType {
     my $self = shift;
-    my $field = shift;
-    $field //= 0;
-    my $fd = $self->GetDefn->GetGeomFieldDefn($field);
+    my $d = $self->GetDefn;
+    my $field = $d->GetGeomFieldIndex(shift // 0);
+    my $fd = $d->_GetGeomFieldDefn($field);
     return $fd->Type if $fd;
 }
 
 sub SpatialReference {
-    my($self, $field, $sr) = @_;
+    my $self = shift;
     my $d = $self->GetDefn;
-    my $i;
-    if (not defined $field or (blessed($field) and $field->isa('Geo::OSR::SpatialReference'))) {
-        $i = 0;
-    } else {
-        $i = $d->GetGeomFieldIndex($field);
-    }
-    my $d2 = $d->GetGeomFieldDefn($i);
+    my $field = @_ == 2 ? $d->GetGeomFieldIndex(shift // 0) : 0;
+    my $sr = shift;
+    my $d2 = $d->_GetGeomFieldDefn($field);
     $d2->SpatialReference($sr) if defined $sr;
     return $d2->SpatialReference() if defined wantarray;
 }
@@ -502,15 +557,16 @@ use Encode;
 use Carp;
 use Scalar::Util 'blessed';
 
-sub RELEASE_PARENTS {
+Geo::GDAL->import(qw(:INTERNAL));
+
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::OGR::Feature::DEFNS{$self};
-    delete $Geo::OGR::Layer::DEFNS{$self};
+    unkeep($self);
 }
 
 sub Feature {
     my $self = shift;
-    return $Geo::OGR::Feature::DEFNS{tied(%$self)};
+    return parent($self);
 }
 %}
 
@@ -529,7 +585,7 @@ sub new {
         %schema = @_;
     }
     my $fields = $schema{Fields};
-    Geo::GDAL::error("The 'Fields' argument must be an array reference.") if $fields and ref($fields) ne 'ARRAY';
+    error("The 'Fields' argument must be an array reference.") if $fields and ref($fields) ne 'ARRAY';
     $schema{Name} //= '';
     my $self = Geo::OGRc::new_FeatureDefn($schema{Name});
     bless $self, $pkg;
@@ -543,7 +599,22 @@ sub new {
     for my $fd (@{$fields}) {
         my $d = $fd;
         if (ref($fd) eq 'HASH') {
-            if ($fd->{GeometryType} or exists $Geo::OGR::Geometry::TYPE_STRING2INT{$fd->{Type}}) {
+
+            # if Name and Type are missing, assume Name => Type
+            if (!(exists $fd->{Name} && exists $fd->{Type})) {
+                for my $key (sort keys %$fd) {
+                    if (s_exists(field_type => $fd->{$key}) ||
+                        s_exists(geometry_type => $fd->{$key}))
+                    {
+                        $fd->{Name} = $key;
+                        $fd->{Type} = $fd->{$key};
+                        delete $fd->{$key};
+                        last;
+                    }
+                }
+            }
+            
+            if ($fd->{GeometryType} or ($fd->{Type} && s_exists(geometry_type => $fd->{Type}))) {
                 $d = Geo::OGR::GeomFieldDefn->new(%$fd);
             } else {
                 $d = Geo::OGR::FieldDefn->new(%$fd);
@@ -552,10 +623,10 @@ sub new {
         if (blessed($d) and $d->isa('Geo::OGR::FieldDefn')) {
             AddFieldDefn($self, $d);
         } elsif (blessed($d) and $d->isa('Geo::OGR::GeomFieldDefn')) {
-            Geo::GDAL::error("Do not mix GeometryType and geometry fields in Fields.") if $gt;
+            error("Do not mix GeometryType and geometry fields in Fields.") if $gt;
             AddGeomFieldDefn($self, $d);
         } else {
-            Geo::GDAL::error("Item in field list does not define a field.");
+            error("Item in field list does not define a field.");
         }
     }
     return $self;
@@ -563,6 +634,29 @@ sub new {
 %}
 
 %perlcode %{
+
+sub GetFieldIndex {
+    my ($self, $name) = @_;
+    my $index = $self->_GetFieldIndex($name);
+    if ($index < 0 and $name =~ /^\d+$/) {
+        # the name is allowed to be an index
+        $index = $name if $name >= 0 && $name < $self->GetFieldCount();
+    }
+    error("'$name' is not a non-spatial field.") if $index < 0;
+    return $index;
+}
+
+sub GetGeomFieldIndex {
+    my ($self, $name) = @_;
+    my $index = $self->_GetGeomFieldIndex($name);
+    if ($index < 0 and $name =~ /^\d+$/) {
+        # the name is allowed to be an index
+        $index = $name if $name >= 0 && $name < $self->GetGeomFieldCount();
+    }
+    error("'$name' is not a spatial field.") if $index < 0;
+    return $index;
+}
+
 *Name = *GetName;
 
 sub GetSchema {
@@ -581,11 +675,11 @@ sub GetSchema {
     $schema{StyleIgnored} = $self->StyleIgnored();
     $schema{Fields} = [];
     for my $i (0..$self->GetFieldCount-1) {
-        my $s = $self->GetFieldDefn($i)->Schema;
+        my $s = $self->_GetFieldDefn($i)->Schema;
         push @{$schema{Fields}}, $s;
     }
     for my $i (0..$self->GetGeomFieldCount-1) {
-        my $s = $self->GetGeomFieldDefn($i)->Schema;
+        my $s = $self->_GetGeomFieldDefn($i)->Schema;
         push @{$schema{Fields}}, $s;
     }
     return wantarray ? %schema : \%schema;
@@ -594,7 +688,7 @@ sub GetSchema {
 
 sub AddField {
     my $self = shift;
-    Geo::GDAL::error("Read-only definition.") if $Geo::OGR::Feature::DEFNS{tied(%$self)} || $Geo::OGR::Layer::DEFNS{tied(%$self)};
+    error("Read-only definition.") if parent($self);
     my %params;
     if (@_ == 0) {
     } elsif (ref($_[0]) eq 'HASH') {
@@ -603,7 +697,7 @@ sub AddField {
         %params = @_;
     }
     $params{Type} //= '';
-    if (exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$params{Type}}) {
+    if (s_exists(field_type => $params{Type})) {
         my $fd = Geo::OGR::FieldDefn->new(%params);
         $self->AddFieldDefn($fd);
     } else {
@@ -614,49 +708,48 @@ sub AddField {
 
 sub DeleteField {
     my ($self, $name) = @_;
-    Geo::GDAL::error("Read-only definition.") if $Geo::OGR::Feature::DEFNS{tied(%$self)} || $Geo::OGR::Layer::DEFNS{tied(%$self)};
+    error("Read-only definition.") if parent($self);
     for my $i (0..$self->GetFieldCount-1) {
-        Geo::GDAL::error("Non-geometry fields cannot be deleted.") if $self->GetFieldDefn($i)->Name eq $name;
+        error("Non-spatial fields cannot be deleted.") if $self->_GetFieldDefn($i)->Name eq $name;
     }
     for my $i (0..$self->GetGeomFieldCount-1) {
-        $self->DeleteGeomFieldDefn($i) if $self->GetGeomFieldDefn($i)->Name eq $name;
+        $self->DeleteGeomFieldDefn($i) if $self->_GetGeomFieldDefn($i)->Name eq $name;
     }
-    Geo::GDAL::error(2, $name, 'Field');
+    error(2, $name, 'Field');
 }
 
 sub GetFieldNames {
     my $self = shift;
     my @names = ();
     for my $i (0..$self->GetFieldCount-1) {
-        push @names, $self->GetFieldDefn($i)->Name;
+        push @names, $self->_GetFieldDefn($i)->Name;
     }
     for my $i (0..$self->GetGeomFieldCount-1) {
-        push @names, $self->GetGeomFieldDefn($i)->Name;
+        push @names, $self->_GetGeomFieldDefn($i)->Name;
     }
     return @names;
 }
 
 sub GetFieldDefn {
-    my ($self, $name) = @_;
-    for my $i (0..$self->GetFieldCount-1) {
-        my $fd = $self->GetFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    for my $i (0..$self->GetGeomFieldCount-1) {
-        my $fd = $self->GetGeomFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    Geo::GDAL::error(2, $name, 'Field');
+    my $self = shift;
+    my $field = $self->GetFieldIndex(shift);
+    return $self->_GetFieldDefn($field);
+}
+
+sub GetGeomFieldDefn {
+    my $self = shift;
+    my $field = $self->GetGeomFieldIndex(shift);
+    return $self->_GetGeomFieldDefn($field);
 }
 
 sub GeomType {
     my ($self, $type) = @_;
-    Geo::GDAL::error("Read-only definition.") if $Geo::OGR::Feature::DEFNS{tied(%$self)} || $Geo::OGR::Layer::DEFNS{tied(%$self)};
+    error("Read-only definition.") if parent($self);
     if (defined $type) {
-        $type = Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+        $type = s2i(geometry_type => $type);
         SetGeomType($self, $type);
     }
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GetGeomType($self)} if defined wantarray;
+    return i2s(geometry_type => GetGeomType($self)) if defined wantarray;
 }
 *GeometryType = *GeomType;
 
@@ -678,10 +771,11 @@ sub StyleIgnored {
 package Geo::OGR::Feature;
 use strict;
 use warnings;
-use vars qw /%GEOMETRIES %DEFNS/;
 use Carp;
 use Encode;
 use Scalar::Util 'blessed';
+
+Geo::GDAL->import(qw(:INTERNAL));
 %}
 
 %feature("shadow") OGRFeatureShadow( OGRFeatureDefnShadow *feature_def )
@@ -689,48 +783,88 @@ use Scalar::Util 'blessed';
 use Carp;
 sub new {
     my $pkg = shift;
-    my $arg = blessed($_[0]);
-    my $defn;
-    if ($arg && $arg eq 'Geo::OGR::FeatureDefn') {
-        $defn = $_[0];
+    my $arg;
+    if (ref $_[0]) {
+        if (ref $_[0] eq 'HASH' && $_[0]->{Schema}) {
+            $arg = $_[0];
+        } else {
+            $arg = {Schema => $_[0]};
+        }
+    } elsif (@_ and @_ % 2 == 0) {
+        %$arg = @_;
+        unless ($arg->{Schema}) {
+            my %tmp = @_;
+            $arg->{Schema} = \%tmp;
+        }
     } else {
-        $defn = Geo::OGR::FeatureDefn->new(@_);
+        error("The argument must be either a schema or a hash.");
+    }
+    error("Missing schema.") unless $arg->{Schema};
+    my $defn;
+    for (ref $arg->{Schema}) {
+        (/Geo::OGR::Layer$/ || /Geo::OGR::Feature$/) && do {
+            $defn = $arg->{Schema}->GetDefn;
+            last;
+        };
+        /Geo::OGR::FeatureDefn$/ && do {
+            $defn = $arg->{Schema};
+            last;
+        };
+        $defn = Geo::OGR::FeatureDefn->new($arg->{Schema});
     }
     my $self = Geo::OGRc::new_Feature($defn);
-    bless $self, $pkg if defined($self);
+    error("Feature creation failed.") unless $self;
+    bless $self, $pkg;
+    for (ref $arg->{Values}) {
+        /ARRAY/  && do {
+            $self->Tuple($arg->{Values});
+            last;
+        };
+        /HASH/ && do {
+            $self->Row($arg->{Values});
+            last;
+        };
+        /Geo::OGR::Feature$/ && do {
+            $self->Tuple($arg->{Values}->Tuple);
+            last;
+        };
+        /^$/ && do {
+            last;
+        };
+        error("Value parameter must be an array, hash, or another feature. Not $_.");
+    }
+    return $self;
 }
 %}
 
 %perlcode %{
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::OGR::Layer::FEATURES{$self};
+    unkeep($self);
 }
 
 sub Layer {
     my $self = shift;
-    return $Geo::OGR::Layer::FEATURES{tied(%$self)};
+    parent($self);
 }
 
 sub FETCH {
-    my($self, $index) = @_;
-    my $i;
-    eval {$i = $self->GetFieldIndex($index)};
-    return $self->GetField($i) unless $@;
-    Geo::GDAL::error("'$index' is not a non-spatial field and it is not safe to retrieve geometries from a feature this way.");
+    my $self = shift;
+    my $field = shift;
+    eval {my $i = $self->GetFieldIndex($field)};
+    return $self->GetField($field) unless $@;
+    error("'$field' is not a non-spatial field and it is not safe to retrieve geometries from a feature this way.");
 }
 
 sub STORE {
     my $self = shift;
-    my $index = shift;
-    my $i;
-    eval {$i = $self->GetFieldIndex($index)};
+    my $field = shift;
+    eval {my $i = $self->GetFieldIndex($field)};
     unless ($@) {
-      $self->SetField($i, @_);
+        $self->SetField($field, @_);
     } else {
-      $i = $self->GetGeomFieldIndex($index);
-      $self->Geometry($i, @_);
+        $self->Geometry($field, @_);
     }
 }
 
@@ -741,6 +875,40 @@ sub FID {
     $self->GetFID;
 }
 
+sub GetFieldIndex {
+    my ($self, $name) = @_;
+    my $index = $self->_GetFieldIndex($name);
+    if ($index < 0 and $name =~ /^\d+$/) {
+        # the name is allowed to be an index
+        $index = $name if $name >= 0 && $name < $self->GetFieldCount();
+    }
+    error("'$name' is not a non-spatial field.") if $index < 0;
+    return $index;
+}
+
+sub GetGeomFieldIndex {
+    my ($self, $name) = @_;
+    my $index = $self->_GetGeomFieldIndex($name);
+    if ($index < 0 and $name =~ /^\d+$/) {
+        # the name is allowed to be an index
+        $index = $name if $name >= 0 && $name < $self->GetGeomFieldCount();
+    }
+    error("'$name' is not a spatial field.") if $index < 0;
+    return $index;
+}
+
+sub GetFieldDefn {
+    my $self = shift;
+    my $field = $self->GetFieldIndex(shift);
+    return $self->GetFieldDefnRef($field);
+}
+
+sub GetGeomFieldDefn {
+    my $self = shift;
+    my $field = $self->GetGeomFieldIndex(shift);
+    return $self->GetGeomFieldDefnRef($field);
+}
+
 sub StyleString {
     my $self = shift;
     $self->SetStyleString($_[0]) if @_;
@@ -760,7 +928,7 @@ sub Validate {
 
 sub GetSchema {
     my $self = shift;
-    Geo::GDAL::error("Schema of a feature cannot be set directly.") if @_;
+    error("Schema of a feature cannot be set directly.") if @_;
     return $self->GetDefnRef->Schema;
 }
 *Schema = *GetSchema;
@@ -776,7 +944,7 @@ sub Row {
         } elsif (@_ and @_ % 2 == 0) {
             %row = @_;
         } else {
-            Geo::GDAL::error('Usage: $feature->Row(%FeatureData).');
+            error('Usage: $feature->Row(%FeatureData).');
         }
         $self->SetFID($row{FID}) if defined $row{FID};
         #$self->Geometry($schema, $row{Geometry}) if $row{Geometry};
@@ -825,13 +993,13 @@ sub Tuple {
     my $nf = $self->GetFieldCount;
     my $ngf = $self->GetGeomFieldCount;
     if (@_) {
+        my $values = ref $_[0] ? $_[0] : \@_;
         my $FID;
-        $FID = shift if @_ == $nf + $ngf + 1;
+        $FID = shift @$values if @$values == $nf + $ngf + 1;
         $self->SetFID($FID) if defined $FID;
-        my $values = \@_;
         if (@$values != $nf + $ngf) {
             my $n = $nf + $ngf;
-            Geo::GDAL::error("Too many or too few attribute values for a feature (need $n).");
+            error("Too many or too few attribute values for a feature (need $n).");
         }
         my $index = 0; # index to non-geometry and geometry fields
         for my $i (0..$nf-1) {
@@ -857,31 +1025,20 @@ sub Tuple {
 sub GetDefn {
     my $self = shift;
     my $defn = $self->GetDefnRef;
-    $DEFNS{tied(%$defn)} = $self;
-    return $defn;
+    keep($defn, $self);
 }
 
-*GetGeomFieldDefn = *GetGeomFieldDefnRef;
-
 *GetFieldNames = *Geo::OGR::Layer::GetFieldNames;
-*GetFieldDefn = *Geo::OGR::Layer::GetFieldDefn;
 
 sub GetField {
-    my($self, $field) = @_;
+    my ($self, $field) = @_;
+    $field = $self->GetFieldIndex($field);
     return unless IsFieldSet($self, $field);
     my $type = GetFieldType($self, $field);
-    if ($type == $Geo::OGR::OFTInteger) {
-        return GetFieldAsInteger($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTInteger64) {
-        return GetFieldAsInteger64($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTReal) {
-        return GetFieldAsDouble($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTString) {
-        return GetFieldAsString($self, $field);
-    }
+    return GetFieldAsInteger($self, $field) if $type == $Geo::OGR::OFTInteger;
+    return GetFieldAsInteger64($self, $field) if $type == $Geo::OGR::OFTInteger64;
+    return GetFieldAsDouble($self, $field) if $type == $Geo::OGR::OFTReal;
+    return GetFieldAsString($self, $field) if $type == $Geo::OGR::OFTString;
     if ($type == $Geo::OGR::OFTIntegerList) {
         my $ret = GetFieldAsIntegerList($self, $field);
         return wantarray ? @$ret : $ret;
@@ -914,17 +1071,18 @@ sub GetField {
         my @ret = GetFieldAsDateTime($self, $field);
         return wantarray ? @ret : [@ret];
     }
-    Geo::GDAL::error("Perl bindings do not support field type '$Geo::OGR::FieldDefn::TYPE_INT2STRING{$type}'.");
+    error("Perl bindings do not support the field type '".i2s(field_type => $type)."'.");
 }
 
 sub UnsetField {
-    my($self, $field) = @_;
+    my ($self, $field) = @_;
+    $field = $self->GetFieldIndex($field);
     _UnsetField($self, $field);
 }
 
 sub SetField {
     my $self = shift;
-    my $field = shift;
+    my $field = $self->GetFieldIndex(shift);
     my $arg = $_[0];
     if (@_ == 0 or !defined($arg)) {
         _UnsetField($self, $field);
@@ -956,22 +1114,39 @@ sub SetField {
             $arg->[6] //= 0;
             _SetField($self, $field, @$arg[0..6]);
         }
+        elsif ($type == $Geo::OGR::OFTInteger64)
+        {
+            SetFieldInteger64($self, $field, $arg);
+        }
         else {
-            _SetField($self, $field, @$arg);
+            $type = i2s(field_type => $type);
+            my $name = $self->GetFieldDefnRef($field)->Name;
+            error("'$arg' is not a suitable value for field $name($type).");
         }
     } else {
         if ($type == $Geo::OGR::OFTBinary) {
             #$arg = unpack('H*', $arg); # remove when SetFieldBinary is available
             $self->SetFieldBinary($field, $arg);
-        } else {
+        }
+        elsif ($type == $Geo::OGR::OFTInteger64)
+        {
+            SetFieldInteger64($self, $field, $arg);
+        }
+        elsif ($type == $Geo::OGR::OFTInteger or $type == $Geo::OGR::OFTReal or $type == $Geo::OGR::OFTString)
+        {
             _SetField($self, $field, $arg);
         }
+        else {
+            $type = i2s(field_type => $type);
+            my $name = $self->GetFieldDefnRef($field)->Name;
+            error("'$arg' is not a suitable value for field $name($type).");
+        }
     }
 }
 
 sub Field {
     my $self = shift;
-    my $field = shift;
+    my $field = $self->GetFieldIndex(shift // 0);
     $self->SetField($field, @_) if @_;
     $self->GetField($field) if defined wantarray;
 }
@@ -979,6 +1154,7 @@ sub Field {
 sub Geometry {
     my $self = shift;
     my $field = ((@_ > 0 and ref($_[0]) eq '') or (@_ > 2 and @_ % 2 == 1)) ? shift : 0;
+    $field = $self->GetGeomFieldIndex($field);
     my $geometry;
     if (@_ and @_ % 2 == 0) {
         %$geometry = @_;
@@ -989,33 +1165,32 @@ sub Geometry {
         my $type = $self->GetDefn->GetGeomFieldDefn($field)->Type;
         if (blessed($geometry) and $geometry->isa('Geo::OGR::Geometry')) {
             my $gtype = $geometry->GeometryType;
-            Geo::GDAL::error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
+            error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
                 if $type ne 'Unknown' and $type ne $gtype;
             eval {
                 $self->SetGeomFieldDirectly($field, $geometry->Clone);
             };
-            confess Geo::GDAL->last_error if $@;
+            confess last_error() if $@;
         } elsif (ref($geometry) eq 'HASH') {
             $geometry->{GeometryType} //= $type;
             eval {
                 $geometry = Geo::OGR::Geometry->new($geometry);
             };
             my $gtype = $geometry->GeometryType;
-            Geo::GDAL::error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
+            error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
                 if $type ne 'Unknown' and $type ne $gtype;
             eval {
                 $self->SetGeomFieldDirectly($field, $geometry);
             };
-            confess Geo::GDAL->last_error if $@;
+            confess last_error() if $@;
         } else {
-            Geo::GDAL::error("Usage: \$feature->Geometry([field],[geometry])");
+            error("Usage: \$feature->Geometry([field],[geometry])");
         }
     }
     return unless defined wantarray;
     $geometry = $self->GetGeomFieldRef($field);
     return unless $geometry;
-    $GEOMETRIES{tied(%$geometry)} = $self;
-    return $geometry;
+    keep($geometry, $self);
 }
 *GetGeometry = *Geometry;
 *SetGeometry = *Geometry;
@@ -1039,47 +1214,43 @@ sub SetFrom {
 package Geo::OGR::FieldDefn;
 use strict;
 use warnings;
-use vars qw /
-    %SCHEMA_KEYS
-    @TYPES @SUB_TYPES @JUSTIFY_VALUES
-    %TYPE_STRING2INT %TYPE_INT2STRING
-    %SUB_TYPE_STRING2INT %SUB_TYPE_INT2STRING
-    %JUSTIFY_STRING2INT %JUSTIFY_INT2STRING
-    /;
+use vars qw(%SCHEMA_KEYS @TYPES @SUBTYPES @JUSTIFY);
 use Carp;
 use Encode;
 %SCHEMA_KEYS = map {$_ => 1} qw/Name Type SubType Justify Width Precision Nullable Default Ignored/;
 for (keys %Geo::OGR::) {
     push(@TYPES, $1), next if /^OFT(\w+)/;
-    push(@SUB_TYPES, $1), next if /^OFST(\w+)/;
-    push(@JUSTIFY_VALUES, $1), next if /^OJ(\w+)/;
+    push(@SUBTYPES, $1), next if /^OFST(\w+)/;
+    push(@JUSTIFY, $1), next if /^OJ(\w+)/;
 }
 for my $string (@TYPES) {
     my $int = eval "\$Geo::OGR::OFT$string";
-    $TYPE_STRING2INT{$string} = $int;
-    $TYPE_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{field_type}{$string} = $int;
+    $Geo::GDAL::I2S{field_type}{$int} = $string;
 }
-for my $string (@SUB_TYPES) {
+for my $string (@SUBTYPES) {
     my $int = eval "\$Geo::OGR::OFST$string";
-    $SUB_TYPE_STRING2INT{$string} = $int;
-    $SUB_TYPE_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{field_subtype}{$string} = $int;
+    $Geo::GDAL::I2S{field_subtype}{$int} = $string;
 }
-for my $string (@JUSTIFY_VALUES) {
+for my $string (@JUSTIFY) {
     my $int = eval "\$Geo::OGR::OJ$string";
-    $JUSTIFY_STRING2INT{$string} = $int;
-    $JUSTIFY_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{justify}{$string} = $int;
+    $Geo::GDAL::I2S{justify}{$int} = $string;
 }
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub Types {
     return @TYPES;
 }
 
 sub SubTypes {
-    return @SUB_TYPES;
+    return @SUBTYPES;
 }
 
 sub JustifyValues {
-    return @JUSTIFY_VALUES;
+    return @JUSTIFY;
 }
 %}
 
@@ -1105,7 +1276,7 @@ sub new {
             }
         }
     }
-    $params->{Type} = Geo::GDAL::string2int($params->{Type}, \%Geo::OGR::FieldDefn::TYPE_STRING2INT);
+    $params->{Type} = s2i(field_type => $params->{Type});
     my $self = Geo::OGRc::new_FieldDefn($params->{Name}, $params->{Type});
     bless $self, $pkg;
     delete $params->{Name};
@@ -1123,7 +1294,7 @@ sub Schema {
         for my $key (keys %SCHEMA_KEYS) {
             next unless exists $params->{$key};
             eval "\$self->$key(\$params->{$key})";
-            confess(Geo::GDAL->last_error()) if $@;
+            confess(last_error()) if $@;
         }
     }
     return unless defined wantarray;
@@ -1145,31 +1316,28 @@ sub Name {
 sub Type {
     my($self, $type) = @_;
     if (defined $type) {
-        Geo::GDAL::error(1, $type, \%TYPE_STRING2INT) unless exists $TYPE_STRING2INT{$type};
-        $type = $TYPE_STRING2INT{$type};
+        $type = s2i(field_type => $type);
         SetType($self, $type);
     }
-    return $TYPE_INT2STRING{GetType($self)} if defined wantarray;
+    return i2s(field_type => GetType($self)) if defined wantarray;
 }
 
 sub SubType {
-    my($self, $sub_type) = @_;
-    if (defined $sub_type) {
-        Geo::GDAL::error(1, $sub_type, \%SUB_TYPE_STRING2INT) unless exists $SUB_TYPE_STRING2INT{$sub_type};
-        $sub_type = $SUB_TYPE_STRING2INT{$sub_type};
-        SetSubType($self, $sub_type);
+    my($self, $subtype) = @_;
+    if (defined $subtype) {
+        $subtype = s2i(field_subtype => $subtype);
+        SetSubType($self, $subtype);
     }
-    return $SUB_TYPE_INT2STRING{GetSubType($self)} if defined wantarray;
+    return i2s(field_subtype => GetSubType($self)) if defined wantarray;
 }
 
 sub Justify {
     my($self, $justify) = @_;
     if (defined $justify) {
-        Geo::GDAL::error(1, $justify, \%JUSTIFY_STRING2INT) unless exists $JUSTIFY_STRING2INT{$justify};
-        $justify = $JUSTIFY_STRING2INT{$justify} if exists $JUSTIFY_STRING2INT{$justify};
+        $justify = s2i(justify => $justify);
         SetJustify($self, $justify);
     }
-    return $JUSTIFY_INT2STRING{GetJustify($self)} if defined wantarray;
+    return i2s(justify => GetJustify($self)) if defined wantarray;
 }
 
 sub Width {
@@ -1212,6 +1380,8 @@ use vars qw / %SCHEMA_KEYS /;
 use Carp;
 use Scalar::Util 'blessed';
 %SCHEMA_KEYS = map {$_ => 1} qw/Name Type SpatialReference Nullable Ignored/;
+
+Geo::GDAL->import(qw(:INTERNAL));
 %}
 
 %feature("shadow") OGRGeomFieldDefnShadow( const char* name_null_ok="", OGRwkbGeometryType field_type = wkbUnknown)
@@ -1237,7 +1407,7 @@ sub new {
         }
         $params->{Type} //= $tmp->{GeometryType};
     }
-    $params->{Type} = Geo::GDAL::string2int($params->{Type}, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+    $params->{Type} = s2i(geometry_type => $params->{Type});
     my $self = Geo::OGRc::new_GeomFieldDefn($params->{Name}, $params->{Type});
     bless $self, $pkg;
     delete $params->{Name};
@@ -1255,7 +1425,7 @@ sub Schema {
         for my $key (keys %SCHEMA_KEYS) {
             next unless exists $params->{$key};
             eval "\$self->$key(\$params->{$key})";
-            confess Geo::GDAL->last_error() if $@;
+            confess last_error() if $@;
         }
     }
     return unless defined wantarray;
@@ -1277,15 +1447,15 @@ sub Name {
 sub Type {
     my($self, $type) = @_;
     if (defined $type) {
-        $type = Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+        $type = s2i(geometry_type => $type);
         SetType($self, $type);
     }
-    $Geo::OGR::Geometry::TYPE_INT2STRING{GetType($self)} if defined wantarray;
+    i2s(geometry_type => GetType($self)) if defined wantarray;
 }
 *GeometryType = *Type;
 
 sub Types {
-  return @Geo::OGR::Geometry::GEOMETRY_TYPES;
+    return Geo::OGR::Geometry::GeometryTypes();
 }
 
 sub SpatialReference {
@@ -1315,14 +1485,12 @@ use warnings;
 use Carp;
 use vars qw /
     @BYTE_ORDER_TYPES @GEOMETRY_TYPES
-    %BYTE_ORDER_STRING2INT %BYTE_ORDER_INT2STRING
-    %TYPE_STRING2INT %TYPE_INT2STRING
     /;
 @BYTE_ORDER_TYPES = qw/XDR NDR/;
 for my $string (@BYTE_ORDER_TYPES) {
     my $int = eval "\$Geo::OGR::wkb$string";
-    $BYTE_ORDER_STRING2INT{$string} = $int;
-    $BYTE_ORDER_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{byte_order}{$string} = $int;
+    $Geo::GDAL::I2S{byte_order}{$int} = $string;
 }
 for (keys %Geo::OGR::) {
     next if /^wkb25/;
@@ -1331,15 +1499,17 @@ for (keys %Geo::OGR::) {
 }
 for my $string (@GEOMETRY_TYPES) {
     my $int = eval "\$Geo::OGR::wkb$string";
-    $TYPE_STRING2INT{$string} = $int;
+    $Geo::GDAL::I2S{geometry_type}{$int} = $string;
+    $Geo::GDAL::S2I{geometry_type}{$string} = $int;
     if ($string =~ /25D/) {
-        my $s = $string;
-        $s =~ s/25D/Z/;
-        $TYPE_STRING2INT{$s} = $int;
+        $string =~ s/25D/Z/;
+        $Geo::GDAL::S2I{geometry_type}{$string} = $int;
     }
-    $TYPE_INT2STRING{$int} = $string;
 }
 
+Geo::GDAL->import(qw(:INTERNAL));
+Geo::OGR->import(qw(:INTERNAL));
+
 sub ByteOrders {
     return @BYTE_ORDER_TYPES;
 }
@@ -1348,14 +1518,14 @@ sub GeometryTypes {
     return @GEOMETRY_TYPES;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::OGR::Feature::GEOMETRIES{$self};
+    unkeep($self);
 }
 
 sub Feature {
     my $self = shift;
-    return $Geo::OGR::Feature::GEOMETRIES{tied(%$self)};
+    parent($self);
 }
 %}
 
@@ -1405,14 +1575,14 @@ sub new {
     } elsif (defined $json) {
         $self = Geo::OGRc::CreateGeometryFromJson($json);
     } elsif (defined $type) {
-        $type = Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+        $type = s2i(geometry_type => $type);
         $self = Geo::OGRc::new_Geometry($type); # flattens the type
-        $self->Set3D(1) if Geo::OGR::GT_HasZ($type);
-        $self->SetMeasured(1) if Geo::OGR::GT_HasM($type);
+        $self->Set3D(1) if HasZ($type);
+        $self->SetMeasured(1) if HasM($type);
     } elsif (defined $arc) {
         $self = Geo::OGRc::ApproximateArcAngles(@$arc);
     } else {
-        Geo::GDAL::error(1, undef, map {$_=>1} qw/GeometryType WKT WKB HEXEWKB HEXWKB GML GeoJSON Arc/);
+        error(1, undef, map {$_=>1} qw/GeometryType WKT WKB HEXEWKB HEXWKB GML GeoJSON Arc/);
     }
     bless $self, $pkg if defined $self;
     $self->Points($points) if $points;
@@ -1441,7 +1611,7 @@ sub ApproximateArcAngles {
     for my $p (keys %default) {
         $p{$p} //= $default{$p};
     }
-    Geo::GDAL::error("Usage: Center => [x,y,z].") unless ref($p{Center}) eq 'ARRAY';
+    error("Usage: Center => [x,y,z].") unless ref($p{Center}) eq 'ARRAY';
     for my $i (0..2) {
         $p{Center}->[$i] //= 0;
     }
@@ -1450,7 +1620,7 @@ sub ApproximateArcAngles {
 
 sub As {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Format => undef, ByteOrder => 'XDR', SRID => undef, Options => undef, AltitudeMode => undef);
+    my $p = named_parameters(\@_, Format => undef, ByteOrder => 'XDR', SRID => undef, Options => undef, AltitudeMode => undef);
     my $f = $p->{format};
     if ($f =~ /text/i) {
         return $self->AsText;
@@ -1464,7 +1634,7 @@ sub As {
         return $self->ExportToWkb($p->{byteorder});
     } elsif ($f =~ /wkb/i) {
         if ($f =~ /iso/i) {
-            $p->{byteorder} = Geo::GDAL::string2int($p->{byteorder}, \%Geo::OGR::Geometry::BYTE_ORDER_STRING2INT);
+            $p->{byteorder} = s2i(byte_order => $p->{byteorder});
             return $self->ExportToIsoWkb($p->{byteorder});
         } elsif ($f =~ /ewkb/i) {
             return $self->AsHEXEWKB($p->{srid});
@@ -1480,7 +1650,7 @@ sub As {
     } elsif ($f =~ /json/i) {
         return $self->AsJSON;
     } else {
-        Geo::GDAL::error(1, $f, map {$_=>1} qw/Text WKT ISO_WKT ISO_WKB HEX_WKB HEX_EWKB Binary GML KML JSON/);
+        error(1, $f, map {$_=>1} qw/Text WKT ISO_WKT ISO_WKB HEX_WKB HEX_EWKB Binary GML KML JSON/);
     }
 }
 
@@ -1526,7 +1696,7 @@ sub AsHEXEWKB {
 
 sub GeometryType {
     my $self = shift;
-    return $TYPE_INT2STRING{$self->GetGeometryType};
+    return i2s(geometry_type => $self->GetGeometryType);
 }
 
 sub CoordinateDimension {
@@ -1543,8 +1713,8 @@ sub Extent {
 sub AddPoint {
     my $self = shift;
     my $t = $self->GetGeometryType;
-    my $has_z = Geo::OGR::GT_HasZ($t);
-    my $has_m = Geo::OGR::GT_HasM($t);
+    my $has_z = HasZ($t);
+    my $has_m = HasM($t);
     if (!$has_z && !$has_m) {
         $self->AddPoint_2D(@_[0..1]);
     } elsif ($has_z && !$has_m) {
@@ -1559,8 +1729,8 @@ sub AddPoint {
 sub SetPoint {
     my $self = shift;
     my $t = $self->GetGeometryType;
-    my $has_z = Geo::OGR::GT_HasZ($t);
-    my $has_m = Geo::OGR::GT_HasM($t);
+    my $has_z = HasZ($t);
+    my $has_m = HasM($t);
     if (!$has_z && !$has_m) {
         $self->SetPoint_2D(@_[0..2]);
     } elsif ($has_z && !$has_m) {
@@ -1576,8 +1746,8 @@ sub GetPoint {
     my($self, $i) = @_;
     $i //= 0;
     my $t = $self->GetGeometryType;
-    my $has_z = Geo::OGR::GT_HasZ($t);
-    my $has_m = Geo::OGR::GT_HasM($t);
+    my $has_z = HasZ($t);
+    my $has_m = HasM($t);
     my $point;
     if (!$has_z && !$has_m) {
         $point = $self->GetPoint_2D($i);
@@ -1598,9 +1768,9 @@ sub Point {
     if (@_) {
         my $t = $self->GetGeometryType;
         my $i;
-        if (Geo::OGR::GT_Flatten($t) == $Geo::OGR::wkbPoint) {
-            my $has_z = Geo::OGR::GT_HasZ($t);
-            my $has_m = Geo::OGR::GT_HasM($t);
+        if (Flatten($t) == $Geo::OGR::wkbPoint) {
+            my $has_z = HasZ($t);
+            my $has_m = HasM($t);
             if (!$has_z && !$has_m) {
                 shift if @_ > 2;
                 $i = 0;
@@ -1623,17 +1793,17 @@ sub Point {
 sub Points {
     my $self = shift;
     my $t = $self->GetGeometryType;
-    my $has_z = Geo::OGR::GT_HasZ($t);
-    my $has_m = Geo::OGR::GT_HasM($t);
+    my $has_z = HasZ($t);
+    my $has_m = HasM($t);
     my $postfix = '';
-    $postfix .= 'Z' if Geo::OGR::GT_HasZ($t);
-    $postfix .= 'M' if Geo::OGR::GT_HasM($t);
-    $t = $TYPE_INT2STRING{Geo::OGR::GT_Flatten($t)};
+    $postfix .= 'Z' if HasZ($t);
+    $postfix .= 'M' if HasM($t);
+    $t = i2s(geometry_type => Flatten($t));
     my $points = shift;
     if ($points) {
         Empty($self);
         if ($t eq 'Unknown' or $t eq 'None' or $t eq 'GeometryCollection') {
-            Geo::GDAL::error("Can't set points of a geometry of type '$t'.");
+            error("Can't set points of a geometry of type '$t'.");
         } elsif ($t eq 'Point') {
             # support both "Point" as a list of one point and one point
             if (ref($points->[0])) {
@@ -1700,18 +1870,18 @@ sub _GetPoints {
 
 sub ExportToWkb {
     my($self, $bo) = @_;
-    $bo = Geo::GDAL::string2int($bo, \%BYTE_ORDER_STRING2INT);
+    $bo = s2i(byte_order => $bo);
     return _ExportToWkb($self, $bo);
 }
 
 sub ForceTo {
     my $self = shift;
     my $type = shift;
-    $type = Geo::GDAL::string2int($type, \%TYPE_STRING2INT);
+    $type = s2i(geometry_type => $type);
     eval {
         $self = Geo::OGR::ForceTo($self, $type, @_);
     };
-    confess Geo::GDAL->last_error if $@;
+    confess last_error() if $@;
     return $self;
 }
 
@@ -1783,10 +1953,12 @@ use strict;
 use warnings;
 use Carp;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub GeometryType {
     my($type) = @_;
     if (defined $type) {
-        return Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT, \%Geo::OGR::Geometry::TYPE_INT2STRING);
+        return s2i(geometry_type => $type, 1);
     } else {
         return @Geo::OGR::Geometry::GEOMETRY_TYPES;
     }
@@ -1794,35 +1966,32 @@ sub GeometryType {
 
 sub GeometryTypeModify {
     my($type, $modifier) = @_;
-    Geo::GDAL::error(1, $type, \%Geo::OGR::Geometry::TYPE_STRING2INT) unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_Flatten($type)} if $modifier =~ /flat/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_SetZ($type)} if $modifier =~ /z/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetCollection($type)} if $modifier =~ /collection/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetCurve($type)} if $modifier =~ /curve/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetLinear($type)} if $modifier =~ /linear/i;
-    Geo::GDAL::error(1, $modifier, {Flatten => 1, SetZ => 1, GetCollection => 1, GetCurve => 1, GetLinear => 1});
+    $type = s2i(geometry_type => $type);
+    return i2s(geometry_type => GT_Flatten($type)) if $modifier =~ /flat/i;
+    return i2s(geometry_type => GT_SetZ($type)) if $modifier =~ /z/i;
+    return i2s(geometry_type => GT_GetCollection($type)) if $modifier =~ /collection/i;
+    return i2s(geometry_type => GT_GetCurve($type)) if $modifier =~ /curve/i;
+    return i2s(geometry_type => GT_GetLinear($type)) if $modifier =~ /linear/i;
+    error(1, $modifier, {Flatten => 1, SetZ => 1, GetCollection => 1, GetCurve => 1, GetLinear => 1});
 }
 
 sub GeometryTypeTest {
     my($type, $test, $type2) = @_;
-    Geo::GDAL::error(1, $type, \%Geo::OGR::Geometry::TYPE_STRING2INT) unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
+    $type = s2i(geometry_type => $type);
     if (defined $type2) {
-        Geo::GDAL::error(1, $type2, \%Geo::OGR::Geometry::TYPE_STRING2INT) unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type2};
-        $type2 = $Geo::OGR::Geometry::TYPE_STRING2INT{$type2};
+        $type = s2i(geometry_type => $type);
     } else {
-        Geo::GDAL::error("Usage: GeometryTypeTest(type1, 'is_subclass_of', type2).") if $test =~ /subclass/i;
+        error("Usage: GeometryTypeTest(type1, 'is_subclass_of', type2).") if $test =~ /subclass/i;
     }
     return GT_HasZ($type) if $test =~ /z/i;
     return GT_IsSubClassOf($type, $type2) if $test =~ /subclass/i;
     return GT_IsCurve($type) if $test =~ /curve/i;
     return GT_IsSurface($type) if $test =~ /surface/i;
     return GT_IsNonLinear($type) if $test =~ /linear/i;
-    Geo::GDAL::error(1, $test, {HasZ => 1, IsSubClassOf => 1, IsCurve => 1, IsSurface => 1, IsNonLinear => 1});
+    error(1, $test, {HasZ => 1, IsSubClassOf => 1, IsCurve => 1, IsSurface => 1, IsNonLinear => 1});
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
 }
 
 *ByteOrders = *Geo::OGR::Geometry::ByteOrders;
diff --git a/swig/include/perl/osr_perl.i b/swig/include/perl/osr_perl.i
index fde1115..7ac8a7a 100644
--- a/swig/include/perl/osr_perl.i
+++ b/swig/include/perl/osr_perl.i
@@ -56,7 +56,7 @@ sub Datums {
     return keys %DATUMS;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
 }
 
 
@@ -64,6 +64,8 @@ package Geo::OSR::SpatialReference;
 use strict;
 use warnings;
 use Carp;
+
+Geo::GDAL->import(qw(:INTERNAL));
 %}
 
 %feature("shadow") OSRSpatialReferenceShadow( char const * wkt = "" )
@@ -107,9 +109,9 @@ sub new {
         eval {
             SetWellKnownGeogCS($self, 'WGS'.$param{WGS});
         };
-        confess Geo::GDAL->last_error if $@;
+        confess last_error() if $@;
     } else {
-        Geo::GDAL::error("Unrecognized/missing parameters: @_.");
+        error("Unrecognized/missing parameters: @_.");
     }
     bless $self, $pkg if defined $self;
 }
@@ -136,7 +138,7 @@ sub Export {
         MICoordSys => sub { return ExportToMICoordSys() },
         MapInfoCS => sub { return ExportToMICoordSys() },
         );
-    Geo::GDAL::error(1, $format, \%converters) unless $converters{$format};
+    error(1, $format, \%converters) unless $converters{$format};
     return $converters{$format}->();
 }
 *AsText = *ExportToWkt;
@@ -155,7 +157,7 @@ sub Set {
     } elsif (exists $params{LinearUnits} and exists $params{Value}) {
         SetLinearUnitsAndUpdateParameters($self, $params{LinearUnits}, $params{Value});
     } elsif ($params{Parameter} and exists $params{Value}) {
-        Geo::GDAL::error(1, $params{Parameter}, \%Geo::OSR::PARAMETERS) unless exists $Geo::OSR::PARAMETERS{$params{Parameter}};
+        error(1, $params{Parameter}, \%Geo::OSR::PARAMETERS) unless exists $Geo::OSR::PARAMETERS{$params{Parameter}};
         $params{Normalized} ?
             SetNormProjParm($self, $params{Parameter}, $params{Value}) :
             SetProjParm($self, $params{Parameter}, $params{Value});
@@ -191,7 +193,7 @@ sub Set {
             SetProjCS($self, $params{CoordinateSystem});
         }
     } elsif (exists $params{Projection}) {
-        Geo::GDAL::error(1, $params{Projection}, \%Geo::OSR::PROJECTIONS) unless exists $Geo::OSR::PROJECTIONS{$params{Projection}};
+        error(1, $params{Projection}, \%Geo::OSR::PROJECTIONS) unless exists $Geo::OSR::PROJECTIONS{$params{Projection}};
         my @parameters = ();
         @parameters = @{$params{Parameters}} if ref($params{Parameters});
         if ($params{Projection} eq 'Albers_Conic_Equal_Area') {
@@ -289,7 +291,7 @@ sub Set {
             SetProjection($self, $params{Projection});
         }
     } else {
-        Geo::GDAL::error("Not enough information to create a spatial reference object.");
+        error("Not enough information to create a spatial reference object.");
     }
 }
 
@@ -313,6 +315,8 @@ package Geo::OSR::CoordinateTransformation;
 use strict;
 use warnings;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub TransformPoints {
     my($self, $points) = @_;
     _TransformPoints($self, $points), return unless ref($points->[0]->[0]);
diff --git a/swig/include/perl/typemaps_perl.i b/swig/include/perl/typemaps_perl.i
index 308c330..ef3df43 100644
--- a/swig/include/perl/typemaps_perl.i
+++ b/swig/include/perl/typemaps_perl.i
@@ -18,7 +18,7 @@
 %typemap(out) GIntBig
 {
     char temp[256];
-    sprintf(temp, ""CPL_FRMT_GIB"", $1);
+    sprintf(temp, "" CPL_FRMT_GIB "", $1);
     $result = sv_2mortal(newSVpv(temp, 0));
     argvi++;
 }
@@ -31,7 +31,7 @@
 %typemap(out) GUIntBig
 {
     char temp[256];
-    sprintf(temp, ""CPL_FRMT_GUIB"", $1);
+    sprintf(temp, "" CPL_FRMT_GUIB "", $1);
     $result = sv_2mortal(newSVpv(temp, 0));
     argvi++;
 }
@@ -41,9 +41,11 @@
 %apply (double *OUTPUT) { double *defaultval };
 
 %fragment("sv_to_utf8_string", "header") %{
-    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf) {
-        /* if tmpbuf, only tmpbuf is freed; if not, ret is freed*/
+    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf, bool *safefree = NULL) {
+        /* if tmpbuf is given, only tmpbuf needs to be freed, use Safefree!
+           if not, ret needs to be freed, if safefree use Safefree else use free! */
         char *ret;
+        if (safefree) *safefree = false;
         if (SvOK(sv)) {
             STRLEN len;
             ret = SvPV(sv, len);
@@ -54,6 +56,7 @@
                 } else {
                     ret = (char *)bytes_to_utf8((const U8*)ret, &len);
                 }
+                if (safefree) *safefree = true;
             } else {
                 if (!tmpbuf)
                     ret = strdup(ret);
@@ -512,6 +515,8 @@
         do_confess(NEED_ARRAY_REF, 1);
     $1 = argin;
     AV *av = (AV*)(SvRV($input));
+    if (av_len(av)+1 < $dim0)
+      do_confess(NOT_ENOUGH_ELEMENTS, 1);
     for (unsigned int i=0; i<$dim0; i++) {
         SV *sv = *av_fetch(av, i, 0);
         if (!SvOK(sv))
@@ -960,9 +965,10 @@
                 AV *av = (AV*)(SvRV($input));
                 for (int i = 0; i < av_len(av)+1; i++) {
                     SV *sv = *(av_fetch(av, i, 0));
-                    char *tmp = sv_to_utf8_string(sv, NULL);
+                    bool sf;
+                    char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                     $1 = CSLAddString($1, tmp);
-                    free(tmp);
+                    if (sf) Safefree(tmp); else free(tmp);
                 }
             } else if (SvTYPE(SvRV($input))==SVt_PVHV) {
                 HV *hv = (HV*)SvRV($input);
@@ -972,9 +978,10 @@
                 $1 = NULL;
                 hv_iterinit(hv);
                 while(sv = hv_iternextsv(hv, &key, &klen)) {
-                    char *tmp = sv_to_utf8_string(sv, NULL);
+                    bool sf;
+                    char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                     $1 = CSLAddNameValue($1, key, tmp);
-                    free(tmp);
+                    if (sf) Safefree(tmp); else free(tmp);
                 }
             } else
                 do_confess(NEED_REF, 1);
@@ -1019,7 +1026,7 @@
 %typemap(freearg) (char **ignorechange)
 {
     /* %typemap(freearg) (char **ignorechange) */
-    if (tmpbuf$argnum) free(tmpbuf$argnum);
+    if (tmpbuf$argnum) Safefree(tmpbuf$argnum);
 }
 
 /*
@@ -1095,7 +1102,7 @@
 %typemap(freearg) (tostring argin)
 {
     /* %typemap(freearg) (tostring argin) */
-    if (tmpbuf$argnum) free(tmpbuf$argnum);
+    if (tmpbuf$argnum) Safefree(tmpbuf$argnum);
 }
 
 /*
@@ -1148,9 +1155,10 @@
 
         nType = SvIV(*(av_fetch(av,0,0)));
         SV *sv = *(av_fetch(av,1,0));
-        char *tmp = sv_to_utf8_string(sv, NULL);
+        bool sf;
+        char *tmp = sv_to_utf8_string(sv, NULL, &sf);
         psThisNode = CPLCreateXMLNode(NULL, (CPLXMLNodeType)nType, tmp);
-        free(tmp);
+        if (sf) Safefree(tmp); else free(tmp);
 
         for( iChild = 0; iChild < nChildCount; iChild++ )
         {
@@ -1185,9 +1193,9 @@
     if ( !$1 ) {
         switch (err) {
         case 1:
-            do_confess(ARRAY_TO_XML_FAILED" "NEED_DEF, 1);
+            do_confess(ARRAY_TO_XML_FAILED " " NEED_DEF, 1);
         case 2:
-            do_confess(ARRAY_TO_XML_FAILED" "NEED_ARRAY_REF, 1);
+            do_confess(ARRAY_TO_XML_FAILED " " NEED_ARRAY_REF, 1);
         }
     }
 }
@@ -1359,6 +1367,10 @@ IF_UNDEF_NULL(const char *, target_key)
     $1 = (void *)(&saved_env);
 }
 
+%typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) GDALProgressFunc callback {
+    /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) GDALProgressFunc callback */
+   $1 = SvOK($input) && SvROK($input) && SvTYPE(SvRV($input)) == SVt_PVCV;
+}
 %typemap(in) (GDALProgressFunc callback = NULL)
 {
     /* %typemap(in) (GDALProgressFunc callback = NULL) */
@@ -1524,7 +1536,7 @@ IF_UNDEF_NULL(const char *, target_key)
 %typemap(freearg) (const char* utf8_path)
 {
     /* %typemap(freearg) (const char* utf8_path) */
-    if (tmpbuf$argnum) free(tmpbuf$argnum);
+    if (tmpbuf$argnum) Safefree(tmpbuf$argnum);
 }
 
 %typemap(in, numinputs=1, fragment="sv_to_utf8_string") (const char* layer_name) (U8 *tmpbuf = NULL)
@@ -1535,7 +1547,7 @@ IF_UNDEF_NULL(const char *, target_key)
 %typemap(freearg) (const char* layer_name)
 {
     /* %typemap(freearg) (const char* layer_name) */
-    if (tmpbuf$argnum) free(tmpbuf$argnum);
+    if (tmpbuf$argnum) Safefree(tmpbuf$argnum);
 }
 
 %typemap(in, numinputs=1, fragment="sv_to_utf8_string") (const char* name) (U8 *tmpbuf = NULL)
@@ -1546,7 +1558,7 @@ IF_UNDEF_NULL(const char *, target_key)
 %typemap(freearg) (const char* name)
 {
     /* %typemap(freearg) (const char* name) */
-    if (tmpbuf$argnum) free(tmpbuf$argnum);
+    if (tmpbuf$argnum) Safefree(tmpbuf$argnum);
 }
 
 %typemap(in,numinputs=0) (int *pnBytes) (int bytes)
diff --git a/swig/include/php/gdal_php.i b/swig/include/php/gdal_php.i
index a3ca90b..12d5b24 100644
--- a/swig/include/php/gdal_php.i
+++ b/swig/include/php/gdal_php.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_php.i 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: gdal_php.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * php specific code for gdal bindings.
  */
diff --git a/swig/include/php/gnm_php.i b/swig/include/php/gnm_php.i
new file mode 100644
index 0000000..d70269e
--- /dev/null
+++ b/swig/include/php/gnm_php.i
@@ -0,0 +1,13 @@
+/*
+ * $Id: gnm_php.i 34525 2016-07-03 02:53:47Z goatbar $
+ *
+ * php specific code for gnm bindings.
+ */
+
+%init %{
+  if ( OGRGetDriverCount() == 0 ) {
+    OGRRegisterAll();
+  }
+%}
+
+%include typemaps_php.i
diff --git a/swig/include/php/ogr_php.i b/swig/include/php/ogr_php.i
index 699174d..e50ce7c 100644
--- a/swig/include/php/ogr_php.i
+++ b/swig/include/php/ogr_php.i
@@ -1,5 +1,5 @@
 /*
- * $Id: ogr_php.i 28039 2014-11-30 18:24:59Z rouault $
+ * $Id: ogr_php.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * php specific code for ogr bindings.
  */
diff --git a/swig/include/php/typemaps_php.i b/swig/include/php/typemaps_php.i
index 0330335..0487130 100644
--- a/swig/include/php/typemaps_php.i
+++ b/swig/include/php/typemaps_php.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_php.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: typemaps_php.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     typemaps_php.i
  * Project:  GDAL PHP Interface
diff --git a/swig/include/python/callback.i b/swig/include/python/callback.i
index 27e9065..f59f4ad 100644
--- a/swig/include/python/callback.i
+++ b/swig/include/python/callback.i
@@ -33,6 +33,8 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
     if( pszMessage == NULL )
         pszMessage = "";
 
+    SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
     if( psInfo->psPyCallbackData == NULL )
         psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, Py_None );
     else
@@ -45,16 +47,19 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
     if( PyErr_Occurred() != NULL )
     {
         PyErr_Clear();
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return FALSE;
     }
 
     if( psResult == NULL )
     {
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return TRUE;
     }
 
     if( psResult == Py_None )
     {
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return TRUE;
     }
 
@@ -63,10 +68,12 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
         PyErr_Clear();
         CPLError(CE_Failure, CPLE_AppDefined, "bad progress return value");
         Py_XDECREF(psResult);
-	return FALSE;
+        SWIG_PYTHON_THREAD_END_BLOCK;
+        return FALSE;
     }
 
     Py_XDECREF(psResult);
+    SWIG_PYTHON_THREAD_END_BLOCK;
 
     return bContinue;
 }
diff --git a/swig/include/python/docs/doxy2swig.py b/swig/include/python/docs/doxy2swig.py
index 61a9c33..89df0ac 100755
--- a/swig/include/python/docs/doxy2swig.py
+++ b/swig/include/python/docs/doxy2swig.py
@@ -160,7 +160,7 @@ class Doxy2SWIG:
         if pad:
             npiece = len(self.pieces)
             if pad == 2:
-                self.add_text('\n')                
+                self.add_text('\n')
         for n in node.childNodes:
             self.parse(n)
         if pad:
@@ -235,7 +235,7 @@ class Doxy2SWIG:
         tmp = node.parentNode.parentNode.parentNode
         compdef = tmp.getElementsByTagName('compounddef')[0]
         cdef_kind = compdef.attributes['kind'].value
-        
+
         if prot == 'public':
             first = self.get_specific_nodes(node, ('definition', 'name'))
             name = first['name'].firstChild.data
@@ -246,7 +246,7 @@ class Doxy2SWIG:
             defn = first['definition'].firstChild.data
             self.add_text('\n')
             self.add_text('%feature("docstring") ')
-            
+
             anc = node.parentNode.parentNode
             if cdef_kind in ('file', 'namespace'):
                 ns_node = anc.getElementsByTagName('innernamespace')
@@ -267,7 +267,7 @@ class Doxy2SWIG:
                 if n not in first.values():
                     self.parse(n)
             self.add_text(['";', '\n'])
-        
+
     def do_definition(self, node):
         data = node.firstChild.data
         self.add_text('%s "\n%s'%(data, data))
@@ -327,7 +327,7 @@ class Doxy2SWIG:
         """Cleans the list of strings given as `pieces`.  It replaces
         multiple newlines by a maximum of 2 and returns a new list.
         It also wraps the paragraphs nicely.
-        
+
         """
         ret = []
         count = 0
diff --git a/swig/include/python/docs/ogr_geometry_docs.i b/swig/include/python/docs/ogr_geometry_docs.i
index 9f190f8..4f75b5e 100644
--- a/swig/include/python/docs/ogr_geometry_docs.i
+++ b/swig/include/python/docs/ogr_geometry_docs.i
@@ -504,7 +504,7 @@ hGeom:  handle on the geometry to convert to a text format from.
 
 ppszSrcText:  a text buffer is allocated by the program, and assigned
 to the passed pointer. After use, *ppszDstText should be freed with
-OGRFree().
+CPLFree().
 
 Currently OGRERR_NONE is always returned. ";
 
@@ -528,7 +528,7 @@ hGeom:  handle on the geometry to convert to a text format from.
 
 ppszSrcText:  a text buffer is allocated by the program, and assigned
 to the passed pointer. After use, *ppszDstText should be freed with
-OGRFree().
+CPLFree().
 
 Currently OGRERR_NONE is always returned.
 
@@ -1613,4 +1613,4 @@ TRUE if the geometry type is a non-linear geometry type.
 
 GDAL 2.0 ";
 
-}
\ No newline at end of file
+}
diff --git a/swig/include/python/docs/ogr_layer_docs.i b/swig/include/python/docs/ogr_layer_docs.i
index e4b9595..0ef8ccf 100644
--- a/swig/include/python/docs/ogr_layer_docs.i
+++ b/swig/include/python/docs/ogr_layer_docs.i
@@ -1,7 +1,6 @@
 %extend OGRLayerShadow {
 // File: ogrlayer_8cpp.xml
-%feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogrlayer.cpp 33568
-2016-02-26 21:01:54Z rouault $\") ";
+%feature("docstring")  CPL_CVSID "CPL_CVSID(\"$Id: ogr_layer_docs.i 34525 2016-07-03 02:53:47Z goatbar $\") ";
 
 %feature("docstring")  Reference "int OGR_L_Reference(OGRLayerH
 hLayer) ";
@@ -1597,4 +1596,4 @@ The first geometry field is always used.
 
 OGR 1.10 ";
 
-}
\ No newline at end of file
+}
diff --git a/swig/include/python/gdal_python.i b/swig/include/python/gdal_python.i
index 6138189..1c44e19 100644
--- a/swig/include/python/gdal_python.i
+++ b/swig/include/python/gdal_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_python.i 37118 2017-01-12 12:15:16Z rouault $
+ * $Id: gdal_python.i 37485 2017-02-27 15:34:30Z rouault $
  *
  * python specific code for gdal bindings.
  */
@@ -95,10 +95,10 @@
 
 %apply ( void **outPythonObject ) { (void **buf ) };
 %inline %{
-int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
+unsigned int wrapper_VSIFReadL( void **buf, unsigned int nMembSize, unsigned int nMembCount, VSILFILE *fp)
 {
-    GUIntBig buf_size = (GUIntBig)nMembSize * nMembCount;
-    if( nMembSize < 0 || nMembCount < 0 || buf_size > 0xFFFFFFFFU )
+    size_t buf_size = static_cast<size_t>(nMembSize) * nMembCount;
+    if( buf_size > 0xFFFFFFFFU )
    {
         CPLError(CE_Failure, CPLE_AppDefined, "Too big request");
         *buf = NULL;
@@ -127,7 +127,7 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         _PyBytes_Resize(&o, nRet * nMembSize);
         *buf = o;
     }
-    return nRet;
+    return static_cast<unsigned int>(nRet);
 #else
     *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
@@ -144,7 +144,7 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         _PyString_Resize(&o, nRet * nMembSize);
         *buf = o;
     }
-    return nRet;
+    return static_cast<unsigned int>(nRet);
 #endif
 }
 %}
@@ -195,15 +195,17 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
                      GDALRIOResampleAlg resample_alg = GRIORA_NearestNeighbour,
                      GDALProgressFunc callback = NULL,
                      void* callback_data=NULL) {
-    int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
-    int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
+    int nxsize = (buf_xsize==0) ? static_cast<int>(xsize) : *buf_xsize;
+    int nysize = (buf_ysize==0) ? static_cast<int>(ysize) : *buf_ysize;
     GDALDataType ntype  = (buf_type==0) ? GDALGetRasterDataType(self)
                                         : (GDALDataType)*buf_type;
     GIntBig pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
     GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
 
-    GIntBig buf_size = ComputeBandRasterIOSize( nxsize, nysize, GDALGetDataTypeSize( ntype ) / 8,
-                                            pixel_space, line_space, FALSE );
+    size_t buf_size = static_cast<size_t>(
+        ComputeBandRasterIOSize( nxsize, nysize,
+                                 GDALGetDataTypeSize( ntype ) / 8,
+                                 pixel_space, line_space, FALSE ) );
     if (buf_size == 0)
     {
         *buf = NULL;
@@ -276,7 +278,8 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
     int nBlockXSize, nBlockYSize;
     GDALGetBlockSize(self, &nBlockXSize, &nBlockYSize);
     int nDataTypeSize = (GDALGetDataTypeSize(GDALGetRasterDataType(self)) / 8);
-    GIntBig buf_size = (GIntBig)nBlockXSize * nBlockYSize * nDataTypeSize;
+    size_t buf_size = static_cast<size_t>(nBlockXSize) *
+                                                nBlockYSize * nDataTypeSize;
 
 %#if PY_VERSION_HEX >= 0x03000000
     *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
@@ -311,6 +314,19 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
 
 %pythoncode %{
 
+  def ComputeStatistics(self, approx_ok):
+    """ComputeStatistics(Band self, bool approx_ok, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
+
+    # For backward compatibility. New SWIG has stricter typing and really
+    # enforces bool
+    if approx_ok == 0:
+        approx_ok = False
+    elif approx_ok == 1:
+        approx_ok = True
+
+    return _gdal.Band_ComputeStatistics(self, approx_ok)
+
+
   def ReadRaster(self, xoff = 0, yoff = 0, xsize = None, ysize = None,
                    buf_xsize = None, buf_ysize = None, buf_type = None,
                    buf_pixel_space = None, buf_line_space = None,
@@ -462,9 +478,13 @@ CPLErr ReadRaster1(  int xoff, int yoff, int xsize, int ysize,
     GIntBig band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
 
     int ntypesize = GDALGetDataTypeSize( ntype ) / 8;
-    GIntBig buf_size = ComputeDatasetRasterIOSize (nxsize, nysize, ntypesize,
-                                               band_list ? band_list : GDALGetRasterCount(self), pband_list, band_list,
-                                               pixel_space, line_space, band_space, FALSE);
+    size_t buf_size = static_cast<size_t>(
+        ComputeDatasetRasterIOSize (nxsize, nysize, ntypesize,
+                                    band_list ? band_list :
+                                        GDALGetRasterCount(self),
+                                    pband_list, band_list,
+                                    pixel_space, line_space, band_space,
+                                    FALSE));
     if (buf_size == 0)
     {
         *buf = NULL;
@@ -952,7 +972,7 @@ def Translate(destName, srcDS, **kwargs):
           destName --- Output dataset name
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.TranslateOptions(), string or array of strings
           other keywords arguments of gdal.TranslateOptions()
         If options is provided as a gdal.TranslateOptions() object, other keywords are ignored. """
 
@@ -1125,7 +1145,7 @@ def Warp(destNameOrDestDS, srcDSOrSrcDSTab, **kwargs):
           destNameOrDestDS --- Output dataset name or object
           srcDSOrSrcDSTab --- an array of Dataset objects or filenames, or a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.WarpOptions(), string or array of strings
           other keywords arguments of gdal.WarpOptions()
         If options is provided as a gdal.WarpOptions() object, other keywords are ignored. """
 
@@ -1154,7 +1174,8 @@ def Warp(destNameOrDestDS, srcDSOrSrcDSTab, **kwargs):
 def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
          accessMode = None,
          srcSRS = None, dstSRS = None, reproject = True,
-         SQLStatement = None, SQLDialect = None, where = None, selectFields = None, spatFilter = None,
+         SQLStatement = None, SQLDialect = None, where = None, selectFields = None,
+         spatFilter = None, spatSRS = None,
          datasetCreationOptions = None,
          layerCreationOptions = None,
          layers = None,
@@ -1164,6 +1185,7 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
          segmentizeMaxDist= None,
          zField = None,
          skipFailures = False,
+         limit = None,
          callback = None, callback_data = None):
     """ Create a VectorTranslateOptions() object that can be passed to gdal.VectorTranslate()
         Keyword arguments are :
@@ -1178,6 +1200,7 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
           where --- WHERE clause to apply to source layer(s)
           selectFields --- list of fields to select
           spatFilter --- spatial filter as (minX, minY, maxX, maxY) bounding box
+          spatSRS --- SRS in which the spatFilter is expressed. If not specified, it is assumed to be the one of the layer(s)
           datasetCreationOptions --- list of dataset creation options
           layerCreationOptions --- list of layer creation options
           layers --- list of layers to convert
@@ -1187,6 +1210,7 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
           segmentizeMaxDist --- maximum distance between consecutive nodes of a line geometry
           zField --- name of field to use to set the Z component of geometries
           skipFailures --- whether to skip failures
+          limit -- maximum number of features to read per layer
           callback --- callback method
           callback_data --- user data for callback
     """
@@ -1233,12 +1257,17 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
             for opt in layerCreationOptions:
                 new_options += ['-lco', opt ]
         if layers is not None:
-            for lyr in layers:
-                new_options += [ lyr ]
+            if _is_str_or_unicode(layers):
+                new_options += [ layers ]
+            else:
+                for lyr in layers:
+                    new_options += [ lyr ]
         if segmentizeMaxDist is not None:
             new_options += ['-segmentize', str(segmentizeMaxDist) ]
         if spatFilter is not None:
             new_options += ['-spat', str(spatFilter[0]), str(spatFilter[1]), str(spatFilter[2]), str(spatFilter[3]) ]
+        if spatSRS is not None:
+            new_options += ['-spat_srs', str(spatSRS) ]
         if layerName is not None:
             new_options += ['-nln', layerName]
         if geometryType is not None:
@@ -1249,7 +1278,8 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
             new_options += ['-zfield', zField]
         if skipFailures:
             new_options += ['-skip']
-
+        if limit is not None:
+            new_options += ['-limit', str(limit)]
     if callback is not None:
         new_options += [ '-progress' ]
 
@@ -1261,7 +1291,7 @@ def VectorTranslate(destNameOrDestDS, srcDS, **kwargs):
           destNameOrDestDS --- Output dataset name or object
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.VectorTranslateOptions(), string or array of strings
           other keywords arguments of gdal.VectorTranslateOptions()
         If options is provided as a gdal.VectorTranslateOptions() object, other keywords are ignored. """
 
@@ -1279,7 +1309,8 @@ def VectorTranslate(destNameOrDestDS, srcDS, **kwargs):
 
 def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
               creationOptions = None, computeEdges = False, alg = 'Horn', band = 1,
-              zFactor = None, scale = None, azimuth = None, altitude = None, combined = False,
+              zFactor = None, scale = None, azimuth = None, altitude = None,
+              combined = False, multiDirectional = False,
               slopeFormat = None, trigonometric = False, zeroForFlat = False,
               callback = None, callback_data = None):
     """ Create a DEMProcessingOptions() object that can be passed to gdal.DEMProcessing()
@@ -1296,6 +1327,7 @@ def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
           azimuth --- (hillshade only) azimuth of the light, in degrees. 0 if it comes from the top of the raster, 90 from the east, ... The default value, 315, should rarely be changed as it is the value generally used to generate shaded maps.
           altitude ---(hillshade only) altitude of the light, in degrees. 90 if the light comes from above the DEM, 0 if it is raking light.
           combined --- (hillshade only) whether to compute combined shading, a combination of slope and oblique shading.
+          multiDirectional --- (hillshade only) whether to compute multi-directional shading
           slopeformat --- (slope only) "degree" or "percent".
           trigonometric --- (aspect only) whether to return trigonometric angle instead of azimuth. Thus 0deg means East, 90deg North, 180deg West, 270deg South.
           zeroForFlat --- (aspect only) whether to return 0 for flat areas with slope=0, instead of -9999.
@@ -1327,6 +1359,8 @@ def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
             new_options += ['-alt', str(altitude) ]
         if combined:
             new_options += ['-combined' ]
+        if multiDirectional:
+            new_options += ['-multidirectional' ]
         if slopeFormat == 'percent':
             new_options += ['-p' ]
         if trigonometric:
@@ -1343,7 +1377,7 @@ def DEMProcessing(destName, srcDS, processing, **kwargs):
           srcDS --- a Dataset object or a filename
           processing --- one of "hillshade", "slope", "aspect", "color-relief", "TRI", "TPI", "Roughness"
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.DEMProcessingOptions(), string or array of strings
           other keywords arguments of gdal.DEMProcessingOptions()
         If options is provided as a gdal.DEMProcessingOptions() object, other keywords are ignored. """
 
@@ -1412,7 +1446,7 @@ def Nearblack(destNameOrDestDS, srcDS, **kwargs):
           destNameOrDestDS --- Output dataset name or object
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.NearblackOptions(), string or array of strings
           other keywords arguments of gdal.NearblackOptions()
         If options is provided as a gdal.NearblackOptions() object, other keywords are ignored. """
 
@@ -1514,7 +1548,7 @@ def Grid(destName, srcDS, **kwargs):
           destName --- Output dataset name
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.GridOptions(), string or array of strings
           other keywords arguments of gdal.GridOptions()
         If options is provided as a gdal.GridOptions() object, other keywords are ignored. """
 
@@ -1635,7 +1669,7 @@ def Rasterize(destNameOrDestDS, srcDS, **kwargs):
           destNameOrDestDS --- Output dataset name or object
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.RasterizeOptions(), string or array of strings
           other keywords arguments of gdal.RasterizeOptions()
         If options is provided as a gdal.RasterizeOptions() object, other keywords are ignored. """
 
@@ -1745,7 +1779,7 @@ def BuildVRT(destName, srcDSOrSrcDSTab, **kwargs):
           destName --- Output dataset name
           srcDSOrSrcDSTab --- an array of Dataset objects or filenames, or a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.BuildVRTOptions(), string or array of strings
           other keywords arguments of gdal.BuildVRTOptions()
         If options is provided as a gdal.BuildVRTOptions() object, other keywords are ignored. """
 
diff --git a/swig/include/python/gnm_python.i b/swig/include/python/gnm_python.i
new file mode 100644
index 0000000..48ad18f
--- /dev/null
+++ b/swig/include/python/gnm_python.i
@@ -0,0 +1,39 @@
+/*
+ * $Id: gnm_python.i 34525 2016-07-03 02:53:47Z goatbar $
+ *
+ * python specific code for ogr bindings.
+ */
+
+%feature("autodoc");
+
+#ifndef FROM_GDAL_I
+%init %{
+
+  if ( OGRGetDriverCount() == 0 ) {
+    OGRRegisterAll();
+  }
+
+%}
+#endif
+
+%rename (RegisterAll) OGRRegisterAll();
+
+#ifndef FROM_GDAL_I
+%include "python_exceptions.i"
+%include "python_strings.i"
+
+%import typemaps_python.i
+
+%include "callback.i"
+
+
+%extend GDALMajorObjectShadow {
+%pythoncode %{
+  def GetMetadata( self, domain = '' ):
+    if domain[:4] == 'xml:':
+      return self.GetMetadata_List( domain )
+    return self.GetMetadata_Dict( domain )
+%}
+}
+#endif
+
diff --git a/swig/include/python/ogr_python.i b/swig/include/python/ogr_python.i
index e0580d2..a5d6244 100644
--- a/swig/include/python/ogr_python.i
+++ b/swig/include/python/ogr_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: ogr_python.i 33763 2016-03-21 16:31:17Z rouault $
+ * $Id: ogr_python.i 37371 2017-02-13 11:41:59Z rouault $
  *
  * python specific code for ogr bindings.
  */
@@ -290,7 +290,7 @@
             fld_index = self.GetFieldIndex(fld_index)
         if (fld_index < 0) or (fld_index > self.GetFieldCount()):
             raise ValueError("Illegal field requested in GetField()")
-        if not (self.IsFieldSet(fld_index)):
+        if not (self.IsFieldSet(fld_index)) or self.IsFieldNull(fld_index):
             return None
         fld_type = self.GetFieldType(fld_index)
         if fld_type == OFTInteger:
@@ -332,6 +332,9 @@
             int minute, int second, int tzflag)
         """
 
+        if len(args) == 2 and args[1] is None:
+            return _ogr.Feature_SetFieldNull(self, args[0])
+
         if len(args) == 2 and (type(args[1]) == type(1) or type(args[1]) == type(12345678901234)):
             fld_index = args[0]
             if isinstance(fld_index, str):
@@ -354,12 +357,12 @@
             raise ValueError("Illegal field requested in SetField2()")
 
         if value is None:
-            self.UnsetField( fld_index )
+            self.SetFieldNull( fld_index )
             return
 
         if isinstance(value,list):
             if len(value) == 0:
-                self.UnsetField( fld_index )
+                self.SetFieldNull( fld_index )
                 return
             if isinstance(value[0],type(1)) or isinstance(value[0],type(12345678901234)):
                 self.SetFieldInteger64List(fld_index,value)
diff --git a/swig/include/python/osr_python.i b/swig/include/python/osr_python.i
index 5fb8555..29962d8 100644
--- a/swig/include/python/osr_python.i
+++ b/swig/include/python/osr_python.i
@@ -1,5 +1,5 @@
 /*
- * $Id: osr_python.i 32939 2016-01-11 18:01:28Z rouault $
+ * $Id: osr_python.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * python specific code for ogr bindings.
  */
diff --git a/swig/include/python/typemaps_python.i b/swig/include/python/typemaps_python.i
index bf1b934..1600a58 100644
--- a/swig/include/python/typemaps_python.i
+++ b/swig/include/python/typemaps_python.i
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: typemaps_python.i 32994 2016-01-15 10:53:46Z rouault $
+ * $Id: typemaps_python.i 37499 2017-02-28 01:00:01Z rouault $
  *
  * Name:     typemaps_python.i
  * Project:  GDAL Python Interface
@@ -161,7 +161,11 @@
 {
   /* %typemap(out) OGRErr */
   if ( result != 0 && bUseExceptions) {
-    PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+    const char* pszMessage = CPLGetLastErrorMsg();
+    if( pszMessage[0] != '\0' )
+        PyErr_SetString( PyExc_RuntimeError, pszMessage );
+    else
+        PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
     SWIG_fail;
   }
 }
@@ -475,12 +479,18 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
     }
 
     if (safeLen) safeLen--;
+    if( safeLen > INT_MAX ) {
+      SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+    }
     $1 = (int) safeLen;
   }
   else if (PyBytes_Check($input))
   {
     Py_ssize_t safeLen = 0;
     PyBytes_AsStringAndSize($input, (char**) &$2, &safeLen);
+    if( safeLen > INT_MAX ) {
+      SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+    }
     $1 = (int) safeLen;
   }
   else
@@ -493,6 +503,9 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
   {
     Py_ssize_t safeLen = 0;
     PyString_AsStringAndSize($input, (char**) &$2, &safeLen);
+    if( safeLen > INT_MAX ) {
+      SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+    }
     $1 = (int) safeLen;
   }
   else
@@ -600,7 +613,7 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
 /*
  * Typemap argout used in Feature::GetFieldAsIntegerList()
  */
-%typemap(in,numinputs=0) (int *nLen, const int **pList) (int nLen, int *pList)
+%typemap(in,numinputs=0) (int *nLen, const int **pList) (int nLen = 0, int *pList = NULL)
 {
   /* %typemap(in,numinputs=0) (int *nLen, const int **pList) (int nLen, int *pList) */
   $1 = &nLen;
@@ -622,36 +635,7 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
 /*
  * Typemap argout used in Feature::GetFieldAsInteger64List()
  */
-%typemap(in,numinputs=0) (int *nLen, const GIntBig **pList) (int nLen, GIntBig *pList)
-{
-  /* %typemap(in,numinputs=0) (int *nLen, const GIntBig **pList) (int nLen, GIntBig *pList) */
-  $1 = &nLen;
-  $2 = &pList;
-}
-
-%typemap(argout) (int *nLen, const GIntBig **pList )
-{
-  /* %typemap(argout) (int *nLen, const GIntBig **pList ) */
-  Py_DECREF($result);
-  PyObject *out = PyList_New( *$1 );
-  for( int i=0; i<*$1; i++ ) {
-    char szTmp[32];
-    sprintf(szTmp, CPL_FRMT_GIB, (*$2)[i]);
-    PyObject* val;
-%#if PY_VERSION_HEX>=0x03000000
-    val = PyLong_FromString(szTmp, NULL, 10);
-%#else
-    val = PyInt_FromString(szTmp, NULL, 10);
-%#endif
-    PyList_SetItem( out, i, val );
-  }
-  $result = out;
-}
-
-/*
- * Typemap argout used in Feature::GetFieldAsInteger64List()
- */
-%typemap(in,numinputs=0) (int *nLen, const GIntBig **pList) (int nLen, GIntBig *pList)
+%typemap(in,numinputs=0) (int *nLen, const GIntBig **pList) (int nLen = 0, GIntBig *pList = NULL)
 {
   /* %typemap(in,numinputs=0) (int *nLen, const GIntBig **pList) (int nLen, GIntBig *pList) */
   $1 = &nLen;
@@ -680,7 +664,7 @@ CreateTupleFromDoubleArray( int *first, unsigned int size ) {
 /*
  * Typemap argout used in Feature::GetFieldAsDoubleList()
  */
-%typemap(in,numinputs=0) (int *nLen, const double **pList) (int nLen, double *pList)
+%typemap(in,numinputs=0) (int *nLen, const double **pList) (int nLen = 0, double *pList = NULL)
 {
   /* %typemap(in,numinputs=0) (int *nLen, const double **pList) (int nLen, double *pList) */
   $1 = &nLen;
@@ -1132,7 +1116,12 @@ static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
     CPLXMLNode *psChild;
     char       *pszText = NULL;
 
-    nChildCount = PyList_Size(pyList) - 2;
+    if( PyList_Size(pyList) > INT_MAX )
+    {
+        PyErr_SetString(PyExc_TypeError,"Error in input XMLTree." );
+        return NULL;
+    }
+    nChildCount = static_cast<int>(PyList_Size(pyList)) - 2;
     if( nChildCount < 0 )
     {
         PyErr_SetString(PyExc_TypeError,"Error in input XMLTree." );
@@ -1905,3 +1894,77 @@ DecomposeSequenceOfCoordinates( PyObject *seq, int nCount, double *x, double *y,
   PyErr_SetString( PyExc_RuntimeError, "needs Python 2.7 or later" );
 %#endif
 }
+
+
+
+%typemap(in,numinputs=0) (int *pnxvalid, int *pnyvalid, int* pisvalid) ( int nxvalid = 0, int nyvalid = 0, int isvalid = 0  )
+{
+  /* %typemap(in) (int *pnxvalid, int *pnyvalid, int* pisvalid) */
+  $1 = &nxvalid;
+  $2 = &nyvalid;
+  $3 = &isvalid;
+}
+
+%typemap(argout) (int *pnxvalid, int *pnyvalid, int* pisvalid)
+{
+   /* %typemap(argout) (int *pnxvalid, int *pnyvalid, int* pisvalid)  */
+  PyObject *r;
+  if ( !*$3 ) {
+    Py_INCREF(Py_None);
+    r = Py_None;
+  }
+  else {
+    r = PyTuple_New( 2 );
+    PyTuple_SetItem( r, 0, PyLong_FromLong(*$1) );
+    PyTuple_SetItem( r, 1, PyLong_FromLong(*$2) );
+  }
+  $result = t_output_helper($result,r);
+}
+
+%typemap(in,numinputs=0) (OGRLayerShadow** ppoBelongingLayer, double* pdfProgressPct) ( OGRLayerShadow* poBelongingLayer = NULL, double dfProgressPct = 0 )
+{
+  /* %typemap(in) (OGRLayerShadow** ppoBelongingLayer, double* pdfProgressPct)  */
+  $1 = &poBelongingLayer;
+  $2 = &dfProgressPct;
+}
+
+%typemap(check) (OGRLayerShadow** ppoBelongingLayer, double* pdfProgressPct)
+{
+   /* %typemap(check) (OGRLayerShadow** ppoBelongingLayer, double* pdfProgressPct)  */
+  if( !arg3 )
+    $2 = NULL;
+}
+
+%typemap(argout) (OGRLayerShadow** ppoBelongingLayer, double* pdfProgressPct)
+{
+   /* %typemap(argout) (OGRLayerShadow** ppoBelongingLayer, double* pdfProgressPct)  */
+
+  if( arg2 )
+  {
+    if( $result == Py_None )
+    {
+        $result = PyList_New(1);
+        PyList_SetItem($result, 0, Py_None);
+    }
+
+    if ( !*$1 ) {
+        Py_INCREF(Py_None);
+        $result = SWIG_Python_AppendOutput($result, Py_None);
+    }
+    else {
+        $result = SWIG_Python_AppendOutput($result,
+            SWIG_NewPointerObj(SWIG_as_voidptr( *$1), SWIGTYPE_p_OGRLayerShadow, 0 ));
+    }
+  }
+
+  if( arg3 )
+  {
+    if( $result == Py_None )
+    {
+        $result = PyList_New(1);
+        PyList_SetItem($result, 0, Py_None);
+    }
+    $result = SWIG_Python_AppendOutput($result, PyFloat_FromDouble( *$2));
+  }
+
+}
diff --git a/swig/include/ruby/gdal_ruby.i b/swig/include/ruby/gdal_ruby.i
index 9964189..2456ca1 100644
--- a/swig/include/ruby/gdal_ruby.i
+++ b/swig/include/ruby/gdal_ruby.i
@@ -1,5 +1,5 @@
 /*
- * $Id: gdal_ruby.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: gdal_ruby.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * ruby specific code for gdal bindings.
  */
diff --git a/swig/include/ruby/gnm_ruby.i b/swig/include/ruby/gnm_ruby.i
new file mode 100644
index 0000000..a105d15
--- /dev/null
+++ b/swig/include/ruby/gnm_ruby.i
@@ -0,0 +1,28 @@
+/*
+ * $Id: gnm_ruby.i 34525 2016-07-03 02:53:47Z goatbar $
+ *
+ * ruby specific code for ogr bindings.
+ */
+
+/* Include default Ruby typemaps */
+%include typemaps_ruby.i
+
+/* Include exception handling code */
+%include cpl_exceptions.i
+
+/* Setup a few renames */
+%rename(get_driver_count) OGRGetDriverCount;
+%rename(get_open_dscount) OGRGetOpenDSCount;
+%rename(register_all) OGRRegisterAll;
+
+
+%init %{
+
+  if ( OGRGetDriverCount() == 0 ) {
+    OGRRegisterAll();
+  }
+
+  /* Setup exception handling */
+  UseExceptions();
+%}
+
diff --git a/swig/include/ruby/ogr_ruby.i b/swig/include/ruby/ogr_ruby.i
index 293bf66..c0ecee9 100644
--- a/swig/include/ruby/ogr_ruby.i
+++ b/swig/include/ruby/ogr_ruby.i
@@ -1,5 +1,5 @@
 /*
- * $Id: ogr_ruby.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: ogr_ruby.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * ruby specific code for ogr bindings.
  */
diff --git a/swig/include/ruby/typemaps_ruby.i b/swig/include/ruby/typemaps_ruby.i
index d18dd69..7398350 100644
--- a/swig/include/ruby/typemaps_ruby.i
+++ b/swig/include/ruby/typemaps_ruby.i
@@ -1,6 +1,6 @@
 
 /******************************************************************************
- * $Id: typemaps_ruby.i 33721 2016-03-15 00:56:01Z goatbar $
+ * $Id: typemaps_ruby.i 34525 2016-07-03 02:53:47Z goatbar $
  *
  * Name:     typemaps_ruby.i
  * Project:  GDAL Ruby Interface
diff --git a/swig/java/GNUmakefile b/swig/java/GNUmakefile
index e77d7ce..8676fea 100644
--- a/swig/java/GNUmakefile
+++ b/swig/java/GNUmakefile
@@ -31,12 +31,10 @@ makedir:
 	mkdir -p org/gdal/gdalconst
 	mkdir -p org/gdal/ogr
 	mkdir -p org/gdal/osr
-#	mkdir -p org/gdal/gnm
+	mkdir -p org/gdal/gnm
 
-JAVA_MODULES = libgdaljni.$(SO_EXT) libogrjni.$(SO_EXT) libgdalconstjni.$(SO_EXT) libosrjni.$(SO_EXT)
-#libgnmjni.$(SO_EXT)
-JAVA_OBJECTS = gdalconst_wrap.$(OBJ_EXT) gdal_wrap.$(OBJ_EXT) osr_wrap.$(OBJ_EXT) ogr_wrap.$(OBJ_EXT)
-#gnm_wrap.$(OBJ_EXT)
+JAVA_MODULES = libgdaljni.$(SO_EXT) libogrjni.$(SO_EXT) libgdalconstjni.$(SO_EXT) libosrjni.$(SO_EXT) libgnmjni.$(SO_EXT)
+JAVA_OBJECTS = gdalconst_wrap.$(OBJ_EXT) gdal_wrap.$(OBJ_EXT) osr_wrap.$(OBJ_EXT) ogr_wrap.$(OBJ_EXT) gnm_wrap.$(OBJ_EXT)
 
 clean:
 	-rm -f ${JAVA_MODULES}
@@ -49,10 +47,10 @@ clean:
 	ant clean
 
 veryclean: clean
-	-rm -f ${WRAPPERS_WITHOUT_GNM}
+	-rm -f ${WRAPPERS}
 	-rm -rf ${EXTRA_DIST}/*
 
-generate: makedir ${WRAPPERS_WITHOUT_GNM}
+generate: makedir ${WRAPPERS}
 
 build: generate ${JAVA_OBJECTS} ${JAVA_MODULES}
 ifeq ($(HAVE_LIBTOOL),yes)
diff --git a/swig/java/add_javadoc.c b/swig/java/add_javadoc.c
index ebf33a3..3185257 100644
--- a/swig/java/add_javadoc.c
+++ b/swig/java/add_javadoc.c
@@ -5,10 +5,10 @@
 * Project:  GDAL/OGR Java bindings
 * Purpose:  Add javadoc located in a special file into generated SWIG Java files
 * Author:   Even Rouault <even dot rouault at mines dash paris dot org>
-* 
+*
 *******************************************************************************
  * Copyright (c) 2009, Even Rouault <even dot rouault at mines-paris dot org>
-* 
+*
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
@@ -18,7 +18,7 @@
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
-* 
+*
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -54,7 +54,7 @@ char* stripline(char* pszBuf)
     while(pszBuf[i] == ' ' && pszBuf[i] != 0)
         i ++;
     memmove(pszBuf, pszBuf + i, strlen(pszBuf) - i + 1);
-    
+
     i = strlen(pszBuf) - 1;
     while(i > 0 && (pszBuf[i] == '{' || pszBuf[i] == '\n' || pszBuf[i] == ' '))
     {
@@ -78,7 +78,7 @@ char* removeargnames(char* pszBuf)
 
     if (strstr(pszBuf, "(") == NULL)
         return pszBuf;
-    
+
     //fprintf(stderr, "%s\n", pszBuf);
 
     if (strstr(pszBuf, "{"))
@@ -128,7 +128,7 @@ char* removeargnames(char* pszBuf)
 int main(int argc, char* argv[])
 {
     const char* patch_filename = argv[1];
-    
+
     FILE* fSrc = fopen(patch_filename, "rt");
     FILE* fDst;
     JavaDocInstance* instances = (JavaDocInstance*)calloc(sizeof(JavaDocInstance), 3000);
@@ -155,7 +155,7 @@ begin:
             else if (strstr(szLine, "*") == NULL)
             {
                 instances[nInstances].javadoc = strdup(javadoc);
-                
+
                 char* pszLine = szLine;
                 if (strncmp(pszLine, "@hide ", 6) == 0)
                 {
@@ -164,7 +164,7 @@ begin:
                 }
                 else
                     instances[nInstances].bHide = 0;
-                
+
                 instances[nInstances].methodName = strdup(stripline(pszLine));
                 instances[nInstances].compactMethodName = strdup(removeargnames(stripline(pszLine)));
                 nInstances++;
@@ -177,7 +177,7 @@ begin:
     }
     //fprintf(stderr, "nInstances=%d\n", nInstances);
     fclose(fSrc);
-    
+
     int i;
     for(i=3;i<argc;i++)
     {
@@ -266,7 +266,7 @@ begin:
                             }
                             break;
                         }
-                            
+
                         fprintf(fDst, "%s", instances[j].javadoc);
                         if (strchr(szMethodName, '('))
                         {
@@ -313,17 +313,17 @@ begin:
                 fprintf(fDst, "%s", szOriLine);
             free(szOriLine);
         }
-        
+
         fclose(fSrc);
         fclose(fDst);
     }
-    
+
     int j;
     for(j=0;j<nInstances;j++)
     {
         if (!instances[j].bUsed)
             fprintf(stderr, "WARNING: did not find occurrence of %s\n", instances[j].methodName);
     }
-    
+
     return 0;
 }
diff --git a/swig/java/apps/GDALContour.java b/swig/java/apps/GDALContour.java
index 66f80d5..9a27e10 100644
--- a/swig/java/apps/GDALContour.java
+++ b/swig/java/apps/GDALContour.java
@@ -1,24 +1,24 @@
 /******************************************************************************
  * $Id: GDALCountuor.java $
- * 
- * Project: GDAL Java applications 
+ *
+ * Project: GDAL Java applications
  * Purpose: Contour Generator mainline
- * Author:  Ivan Lucena, ivan.lucena at pmldnet.com, 
- *          translated from gdal_counter.cpp 
+ * Author:  Ivan Lucena, ivan.lucena at pmldnet.com,
+ *          translated from gdal_counter.cpp
  *          originally written by Frank Warmerdam <warmerdam at pobox.com>
- ****************************************************************************** 
+ ******************************************************************************
  * Copyright (c) 2010, Ivan Lucena
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
  * in the Software without restriction, including without limitation the rights
  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  * copies of the Software, and to permit persons to whom the Software is
  * furnished to do so, subject to the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice shall be included in
  * all copies or substantial portions of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -59,7 +59,7 @@ public class GDALContour {
         String sourceFilename = null;
         String outputFilename = null;
         int sourceBand = 1;
-        String attributName = null;
+        String attributeName = null;
         boolean threeDimension = false;
         boolean ignoreNodata = false;
         boolean hasSourceNodata = false;
@@ -99,7 +99,7 @@ public class GDALContour {
 
             } else if (args[i].equals("-a") && args.length > i) {
 
-                attributName = args[++i];
+                attributeName = args[++i];
 
             } else if (args[i].equals("-off") && args.length > i) {
 
@@ -271,9 +271,9 @@ public class GDALContour {
         layer.CreateField(field, 0);
         field.delete();
 
-        if (attributName != null) {
+        if (attributeName != null) {
 
-            field = new FieldDefn(attributName, ogr.OFTReal);
+            field = new FieldDefn(attributeName, ogr.OFTReal);
             field.SetWidth(12);
             field.SetPrecision(3);
 
@@ -297,7 +297,7 @@ public class GDALContour {
 
         gdal.ContourGenerate(band, contourInterval, offset, fixedLevelsDouble,
                 (ignoreNodata ? 1 : 0), sourceNodata, layer, feature.GetFieldIndex("ID"),
-                (attributName != null ? feature.GetFieldIndex(attributName) : -1),
+                (attributeName != null ? feature.GetFieldIndex(attributeName) : -1),
                 progressCallback);
 
         dataSource.delete();
diff --git a/swig/java/apps/GDALGrid.java b/swig/java/apps/GDALGrid.java
index f1abfa8..d56db50 100644
--- a/swig/java/apps/GDALGrid.java
+++ b/swig/java/apps/GDALGrid.java
@@ -1,923 +1,923 @@
-/******************************************************************************
- * $Id: GDALGrid.java $
- * 
- * Project: GDAL Java applications 
- * Purpose: GDAL scattered data gridding (interpolation) tool 
- * Author:  Ivan Lucena, ivan.lucena at pmldnet.com, 
- *          translated from gdal_grid.cpp 
- *          originally written by Andrey Kiselev, dron at ak4719.spb.edu
- ****************************************************************************** 
- * Copyright (c) 2010, Ivan Lucena
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- * 
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- ****************************************************************************/
-
-import java.util.ArrayList;
-import java.util.List;
-import java.nio.ByteBuffer;
-
-import org.gdal.gdal.Band;
-import org.gdal.gdal.Dataset;
-import org.gdal.gdal.Driver;
-import org.gdal.gdal.ProgressCallback;
-import org.gdal.gdal.TermProgressCallback;
-import org.gdal.gdal.gdal;
-import org.gdal.gdalconst.gdalconstConstants;
-import org.gdal.ogr.DataSource;
-import org.gdal.ogr.Feature;
-import org.gdal.ogr.Geometry;
-import org.gdal.ogr.Layer;
-import org.gdal.ogr.ogr;
-import org.gdal.ogr.ogrConstants;
-import org.gdal.osr.SpatialReference;
-
-public class GDALGrid {
-
-    public static void Usage() {
-        System.out
-                .println("Usage: gridcreate [--help-general] [--formats]\n"
-                        + "    [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
-                        + "            CInt16/CInt32/CFloat32/CFloat64}]\n"
-                        + "    [-of format] [-co \"NAME=VALUE\"]\n"
-                        + "    [-zfield field_name]\n"
-                        + "    [-a_srs srs_def] [-spat xmin ymin xmax ymax]\n"
-                        + "    [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]\n"
-                        + "    [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
-                        + "    [-clipsrcwhere expression]\n"
-                        + "    [-l layername]* [-where expression] [-sql select_statement]\n"
-                        + "    [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]\n"
-                        + "    [-a algorithm[:parameter1=value1]*]\n"
-                        + "    [-q]\n"
-                        + "    <src_datasource> <dst_filename>\n"
-                        + "\n"
-                        + "Available algorithms and parameters with their's defaults:\n"
-                        + "    Inverse distance to a power (default)\n"
-                        + "        invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:"
-                        + "angle=0.0:max_points=0:min_points=0:nodata=0.0\n"
-                        + "    Moving average\n"
-                        + "        average:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
-                        + "    Nearest neighbor\n"
-                        + "        nearest:radius1=0.0:radius2=0.0:angle=0.0:nodata=0.0\n"
-                        + "    Various data metrics\n"
-                        + "        <metric name>:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
-                        + "        possible metrics are:\n"
-                        + "            minimum\n"
-                                                + "            maximum\n"
-                        + "            range\n"
-                                                + "            count\n"
-                        + "            average_distance\n"
-                        + "            average_distance_pts\n");
-        System.exit(-1);
-    }
-
-    /*
-     * Print algorithm and options.
-     */
-    public static void PrintAlgorithmAndOptions(String algorithmAndOptions) {
-
-        if (algorithmAndOptions == null) {
-
-            System.out
-                    .println("Algorithm name: not selected, using default Inverse Distance");
-        } else {
-
-            int firstColon = algorithmAndOptions.indexOf(':');
-            System.out.println("Algorithm name: "
-                    + algorithmAndOptions.substring(0, firstColon));
-            System.out.println("Options are \""
-                    + algorithmAndOptions.substring(firstColon + 1) + "\"");
-        }
-    }
-
-    /*
-     * ProcessGeometry
-     * 
-     * Extract point coordinates from the geometry reference and set the Z value
-     * as requested. Test whether we are in the clipped region before
-     * processing.
-     */
-    public static void ProcessGeometry(Geometry point, Geometry clipSrc,
-            int burnField, double burnValue, List<Double> X, List<Double> Y,
-            List<Double> Z) {
-
-        if (clipSrc != null && point.Within(clipSrc) == false)
-            return;
-
-        X.add(point.GetX());
-        Y.add(point.GetY());
-
-        if (burnField < 0) {
-
-            Z.add(point.GetZ());
-        } else {
-
-            Z.add(burnValue);
-        }
-    }
-
-    /*
-     * Process all the features in a layer selection, collecting geometries and
-     * burn values.
-     */
-    public static void ProcessLayer(Layer srcLayer, Dataset dstDS,
-            Geometry clipSrc, int sizeX, int sizeY, int bandIndex,
-            boolean[] isXExtentSet, boolean[] isYExtentSet, double[] minX,
-            double[] maxX, double[] minY, double[] maxY, String burnAttribute,
-            int type, String algorithmAndOptions, boolean quiet,
-            ProgressCallback progressCallback) {
-
-        /*
-         * Get field index, and check.
-         */
-
-        int burnFieldIndex = -1;
-
-        if (burnAttribute != null) {
-
-            burnFieldIndex = srcLayer.GetLayerDefn().GetFieldIndex(
-                    burnAttribute);
-
-            if (burnFieldIndex == -1) {
-
-                System.out.println("Failed to find field " + burnAttribute
-                        + " on layer " + srcLayer.GetLayerDefn().GetName());
-                return;
-            }
-        }
-
-        /*
-         * Collect the geometries from this layer, and build list of values to
-         * be interpolated.
-         */
-
-        Feature feature;
-
-        List<Double> X = new ArrayList<Double>();
-        List<Double> Y = new ArrayList<Double>();
-        List<Double> Z = new ArrayList<Double>();
-
-        srcLayer.ResetReading();
-
-        while ((feature = srcLayer.GetNextFeature()) != null) {
-
-            Geometry geometry = feature.GetGeometryRef();
-
-            if (geometry != null) {
-
-                int geomtype = geometry.GetGeometryType()
-                        & (~ogrConstants.wkb25DBit);
-
-                double burnValue = 0.0;
-
-                if (burnFieldIndex >= 0) {
-
-                    burnValue = feature.GetFieldAsDouble(burnFieldIndex);
-                }
-
-                if (geomtype == ogr.wkbMultiPoint) {
-
-                    int geomIndex = 0;
-                    int geomCount = geometry.GetGeometryCount();
-
-                    for (geomIndex = 0; geomIndex < geomCount; geomIndex++) {
-
-                        ProcessGeometry(geometry.GetGeometryRef(geomIndex),
-                                clipSrc, burnFieldIndex, burnValue, X, Y, Z);
-                    }
-
-                } else {
-
-                    ProcessGeometry(geometry, clipSrc, burnFieldIndex,
-                            burnValue, X, Y, Z);
-                }
-            }
-
-            feature.delete();
-        }
-
-        if (X.size() == 0) {
-
-            System.out.println("No point geometry found on layer "
-                    + srcLayer.GetLayerDefn().GetName() + ", skipping.");
-            return;
-        }
-
-        /*
-         * Compute grid geometry.
-         */
-
-        if (isXExtentSet[0] == false) {
-
-            minX[0] = X.get(0);
-            maxX[0] = X.get(0);
-
-            for (int i = 1; i < X.size(); i++) {
-
-                if (minX[0] > X.get(i))
-                    minX[0] = X.get(i);
-
-                if (maxX[0] < X.get(i))
-                    maxX[0] = X.get(i);
-            }
-
-            isXExtentSet[0] = true;
-        }
-
-        if (isYExtentSet[0] == false) {
-
-            minY[0] = Y.get(0);
-            maxY[0] = Y.get(0);
-
-            for (int i = 1; i < Y.size(); i++) {
-
-                if (minY[0] > Y.get(i))
-                    minY[0] = Y.get(i);
-
-                if (maxY[0] < Y.get(i))
-                    maxY[0] = Y.get(i);
-            }
-
-            isYExtentSet[0] = true;
-        }
-
-        /*
-         * Perform gridding.
-         */
-
-        Double deltaX = (maxX[0] - minX[0]) / sizeX;
-        Double deltaY = (maxY[0] - minY[0]) / sizeY;
-
-        if (!quiet) {
-
-            System.out.println("Grid data type is "
-                    + gdal.GetDataTypeName(type));
-            System.out.println("Grid size = (" + sizeX + " " + sizeY + ").");
-            System.out.println("Corner coordinates = (" + (minX[0] - deltaX / 2)
-                    + " " + (maxY[0] + deltaY / 2) + ") - (" + (maxX[0] + deltaX / 2)
-                    + " " + (minY[0] - deltaY / 2) + ")");
-            System.out.println("Grid cell size = (" + deltaX + " " + deltaY
-                    + ").");
-            System.out.println("Source point count = " + X.size() + " .");
-            PrintAlgorithmAndOptions(algorithmAndOptions);
-        }
-
-        Band band = dstDS.GetRasterBand(bandIndex);
-
-        if (X.size() == 0) {
-
-            Double val[] = new Double[1];
-
-            band.GetNoDataValue(val);
-
-            if (val[0] != null) {
-                band.Fill(val[0]);
-            } else {
-                band.Fill(0.0);
-            }
-
-            return;
-        }
-
-        int offsetX = 0;
-        int offsetY = 0;
-        int[] blockXSize = new int[1];
-        int[] blockYSize = new int[1];
-
-        band.GetBlockSize(blockXSize, blockYSize);
-
-        int bufferSize = blockXSize[0] * blockYSize[0]
-                * gdal.GetDataTypeSize(type) / 8;
-
-        ByteBuffer data = ByteBuffer.allocateDirect(bufferSize);
-
-        int blockIndex = 0;
-        int blockCount = ((sizeX + blockXSize[0] - 1) / blockXSize[0])
-                * ((sizeY + blockYSize[0] - 1) / blockYSize[0]);
-
-        GDALGridScaledProgress griddingProgress = null;
-
-        for (offsetY = 0; offsetY < sizeY; offsetY += blockYSize[0]) {
-
-            for (offsetX = 0; offsetX < sizeX; offsetX += blockXSize[0]) {
-
-                int requestX = blockXSize[0];
-
-                if (offsetX + requestX > sizeX) {
-
-                    requestX = sizeX - offsetX;
-                }
-
-                int requestY = blockYSize[0];
-
-                if (offsetY + requestY > sizeY) {
-
-                    requestY = sizeY - offsetY;
-                }
-
-                
-                /*
-                 * Reformat arguments
-                 */
-
-                double[][] points = new double[X.size()][3];
-                for (int i = 0; i < X.size(); i++)
-                    points[i][0] = X.get(i);
-                for (int i = 0; i < Y.size(); i++)
-                    points[i][1] = Y.get(i);
-                for (int i = 0; i < Z.size(); i++)
-                    points[i][2] = Z.get(i);
-
-                /*
-                 * Create Scaled progress report
-                 */
-
-                if (quiet == false) {
-                    griddingProgress = new GDALGridScaledProgress(
-                            blockIndex * 1.0 / blockCount, 
-                            (blockIndex + 1) * 1.0 / blockCount, 
-                            progressCallback);
-                }
-
-                /*
-                 * Create Grid
-                 */
-                                
-                gdal.GridCreate(algorithmAndOptions, points, minX[0] + deltaX
-                        * offsetX, minX[0] + deltaX * (offsetX + requestX), minY[0]
-                        + deltaY * offsetY, minY[0] + deltaY
-                        * (offsetY + requestY), requestX, requestY, type, data,
-                        griddingProgress);
-
-                /*
-                 * Write grid to raster output
-                 */
-
-                band.WriteRaster_Direct(offsetX, offsetY, requestX, requestY,
-                        requestX, requestY, type, data);
-
-                if (quiet == false) {
-                    griddingProgress.delete();
-                }
-
-                blockIndex++;
-            }
-        }
-    }
-
-    /*
-     * LoadGeometry
-     * 
-     * Read geometries from the given dataset using specified filters and
-     * returns a collection of read geometries.
-     */
-    static Geometry LoadGeometry(String srcDS, String srcSQL, String srcLyr,
-            String srcWhere) {
-
-        DataSource DS;
-        Layer lyr;
-        Feature feat;
-        Geometry geom = null;
-
-        DS = ogr.Open(srcDS, false);
-
-        if (DS == null) {
-
-            return null;
-        }
-
-        if (srcSQL != null) {
-
-            lyr = DS.ExecuteSQL(srcSQL, null, null);
-        } else if (srcLyr != null) {
-
-            lyr = DS.GetLayerByName(srcLyr);
-        } else {
-
-            lyr = DS.GetLayer(0);
-        }
-
-        if (lyr == null) {
-
-            System.err
-                    .println("Failed to identify source layer from datasource.");
-            DS.delete();
-            return null;
-        }
-
-        if (srcWhere != null) {
-
-            lyr.SetAttributeFilter(srcWhere);
-        }
-
-        while ((feat = lyr.GetNextFeature()) != null) {
-
-            Geometry srcGeom = feat.GetGeometryRef();
-
-            if (srcGeom != null) {
-
-                int srcType = srcGeom.GetGeometryType()
-                        & (~ogrConstants.wkb25DBit);
-
-                if (geom == null) {
-
-                    geom = new Geometry(ogr.wkbMultiPolygon);
-                }
-
-                if (srcType == ogr.wkbPolygon) {
-
-                    geom.AddGeometry(srcGeom);
-                } else if (srcType == ogr.wkbMultiPolygon) {
-
-                    int geomIndex = 0;
-                    int geomCount = srcGeom.GetGeometryCount();
-
-                    for (geomIndex = 0; geomIndex < geomCount; geomIndex++) {
-
-                        geom.AddGeometry(srcGeom.GetGeometryRef(geomIndex));
-                    }
-
-                } else {
-
-                    System.err
-                            .println("FAILURE: Geometry not of polygon type.");
-
-                    if (srcSQL != null) {
-
-                        DS.ReleaseResultSet(lyr);
-                    }
-
-                    DS.delete();
-
-                    return null;
-                }
-            }
-        }
-
-        if (srcSQL != null) {
-
-            DS.ReleaseResultSet(lyr);
-        }
-
-        DS.delete();
-
-        return geom;
-    }
-
-    public static void main(String[] args) {
-
-        String sourceFilename = null;
-        String outputFilename = null;
-        String outputFormat = "GTiff";
-        String layers = null;
-        String burnAttribute = null;
-        String where = null;
-        int outputType = gdalconstConstants.GDT_Float64;
-        String createOptions = null;
-        boolean quiet = false;
-        double[] minX = new double[1];
-        double[] maxX = new double[1];
-        double[] minY = new double[1];
-        double[] maxY = new double[1];
-        int sizeX = 0;
-        int sizeY = 0;
-        String SQL = null;
-        boolean hasClipSrc = false;
-        String clipSQL = null;
-        String clipLayer = null;
-        String clipWhere = null;
-        String outputSRS = null;
-        String algorithmAndOptions = null;
-        Geometry clipSrc = null;
-        Geometry spatialFilter = null;
-        ProgressCallback progressCallback = null;
-        String clipSrcDS = null;
-        boolean[] isXExtentSet = new boolean[1];
-        boolean[] isYExtentSet = new boolean[1];
-
-        minX[0] = 0.0;
-        maxX[0] = 0.0;
-        minY[0] = 0.0;
-        maxY[0] = 0.0;
-
-        isXExtentSet[0] = false;
-        isYExtentSet[0] = false;
-
-        /*
-         * Register GDAL and OGR format(s)
-         */
-
-        gdal.AllRegister();
-        ogr.RegisterAll();
-
-        /*
-         * Parse arguments
-         */
-
-        args = ogr.GeneralCmdLineProcessor(args);
-
-        if (args.length < 2) {
-            Usage();
-        }
-
-        for (int i = 0; i < args.length; i++) {
-            if (args[i].equals("---utility_version")) {
-
-                System.out.println("Running against GDAL " + gdal.VersionInfo());
-                return;
-
-            } else if (args[i].equals("-of") && args.length > i) {
-
-                outputFormat = args[++i];
-
-            } else if (args[i].equals("-q") || args[i].equals("-quiet")) {
-
-                quiet = true;
-
-            } else if (args[i].equals("-ot") && args.length > i) {
-
-                outputType = gdal.GetDataTypeByName(args[++i]);
-
-                if (outputType == gdalconstConstants.GDT_Unknown) {
-
-                    System.err.println("FAILURE: Unknown output pixel type: "
-                            + args[i]);
-                    Usage();
-                }
-
-            } else if (args[i].equals("-txe") && args.length > i + 1) {
-
-                minX[0] = Double.parseDouble(args[++i]);
-                maxX[0] = Double.parseDouble(args[++i]);
-                isXExtentSet[0] = true;
-
-            } else if (args[i].equals("-tye") && args.length > i + 1) {
-
-                minY[0] = Double.parseDouble(args[++i]);
-                maxY[0] = Double.parseDouble(args[++i]);
-                isYExtentSet[0] = true;
-
-            } else if (args[i].equals("-outsize") && args.length > i + 1) {
-
-                sizeX = Integer.parseInt(args[++i]);
-                sizeY = Integer.parseInt(args[++i]);
-
-            } else if (args[i].equals("-co") && args.length > i) {
-
-                if (createOptions == null) {
-                    createOptions = args[++i];
-                } else {
-                    createOptions += ':' + args[++i];
-                }
-
-            } else if (args[i].equals("-zfield") && args.length > i) {
-
-                burnAttribute = args[++i];
-
-            } else if (args[i].equals("-where") && args.length > i) {
-
-                where = args[++i];
-
-            } else if (args[i].equals("-l") && args.length > i) {
-
-                if (layers == null) {
-                    layers = args[++i];
-                } else {
-                    layers += ':' + args[++i];
-                }
-
-            } else if (args[i].equals("-sql") && args.length > i) {
-
-                SQL = args[++i];
-
-            } else if (args[i].equals("-spat") && args.length > i + 3) {
-
-                double clipMinX = Double.parseDouble(args[i + 1]);
-                double clipMinY = Double.parseDouble(args[i + 2]);
-                double clipMaxX = Double.parseDouble(args[i + 3]);
-                double clipMaxY = Double.parseDouble(args[i + 4]);
-                i += 4;
-                clipSrc = new Geometry(ogr.wkbPolygon);
-                clipSrc.AddPoint(clipMinX, clipMinY);
-                clipSrc.AddPoint(clipMinX, clipMaxY);
-                clipSrc.AddPoint(clipMaxX, clipMaxY);
-                clipSrc.AddPoint(clipMaxX, clipMinY);
-                clipSrc.AddPoint(clipMinX, clipMinY);
-
-            } else if (args[i].equals("-clipsrc") && args.length > i) {
-
-                hasClipSrc = true;
-
-                try {
-
-                    double clipMinX = Double.parseDouble(args[i + 1]);
-                    double clipMinY = Double.parseDouble(args[i + 2]);
-                    double clipMaxX = Double.parseDouble(args[i + 3]);
-                    double clipMaxY = Double.parseDouble(args[i + 4]);
-                    i += 4;
-                    clipSrc = new Geometry(ogr.wkbPolygon);
-                    clipSrc.AddPoint(clipMinX, clipMinY);
-                    clipSrc.AddPoint(clipMinX, clipMaxY);
-                    clipSrc.AddPoint(clipMaxX, clipMaxY);
-                    clipSrc.AddPoint(clipMaxX, clipMinY);
-                    clipSrc.AddPoint(clipMinX, clipMinY);
-
-                } catch (NumberFormatException e) {
-
-                    if (args[i].substring(0, 6).equals("POLYGON")
-                            || args[i].substring(0, 11).equals("MULTIPOLYGON")) {
-
-                        clipSrc = ogr.CreateGeometryFromWkt(args[++i]);
-
-                    } else if (args[i].equals("spat_extent")) {
-
-                        ++i;
-
-                    } else {
-
-                        clipSrcDS = args[++i];
-                    }
-                }
-
-            } else if (args[i].equals("-clipsrcsql") && args.length > i) {
-
-                clipSQL = args[++i];
-
-            } else if (args[i].equals("-clipsrclayer") && args.length > i) {
-
-                clipLayer = args[++i];
-
-            } else if (args[i].equals("-clipsrcwhere") && args.length > i) {
-
-                clipLayer = args[++i];
-
-            } else if (args[i].equals("-a_srs") && args.length > i) {
-
-                SpatialReference enteredSRS = new SpatialReference();
-
-                if (enteredSRS.SetFromUserInput(args[i + 1]) != 0) {
-                    System.err.println("Failed to process SRS definition: "
-                            + args[i + 1]);
-                    Usage();
-                }
-                i++;
-
-                outputSRS = enteredSRS.ExportToWkt();
-
-            } else if (args[i].equals("-a") && args.length > i) {
-
-                if (algorithmAndOptions == null) {
-                    algorithmAndOptions = args[++i];
-                } else {
-                    algorithmAndOptions += ':' + args[++i];
-                }
-
-            } else if (args[i].substring(0, 1).equals("-")) {
-
-                System.err.println("FAILURE: Option " + args[i]
-                        + "incomplete, or not recognised");
-                Usage();
-
-            } else if (sourceFilename == null) {
-
-                sourceFilename = args[i];
-
-            } else if (outputFilename == null) {
-
-                outputFilename = args[i];
-
-            } else {
-
-                Usage();
-
-            }
-        }
-
-        if (sourceFilename == null || outputFilename == null
-                || (SQL == null && layers == null)) {
-
-            Usage();
-        }
-
-        /*
-         * Open Input
-         */
-
-        if (hasClipSrc && clipSrcDS != null) {
-
-            clipSrc = LoadGeometry(clipSrcDS, clipSQL, clipLayer, clipWhere);
-
-            if (clipSrc == null) {
-
-                System.out.println("FAILURE: cannot load source clip geometry");
-                Usage();
-            }
-
-        } else if (hasClipSrc && clipSrcDS == null) {
-
-            clipSrc = spatialFilter.Clone();
-
-            if (clipSrc == null) {
-
-                System.out
-                        .println("FAILURE: "
-                                + "-clipsrc must be used with -spat option or \n"
-                                + "a bounding box, WKT string or datasource must be specified");
-                Usage();
-            }
-        }
-
-        /*
-         * Find the output driver.
-         */
-
-        Driver driver = gdal.GetDriverByName(outputFormat);
-
-        if (driver == null) {
-
-            System.out.println("FAILURE: Output driver '" + outputFormat
-                    + "' not recognized.");
-            Usage();
-        }
-
-        /*
-         * Open input datasource.
-         */
-
-        DataSource srcDS = ogr.Open(sourceFilename);
-
-        if (srcDS == null) {
-
-            System.out.println("Unable to open input datasource '"
-                    + sourceFilename);
-            System.out.println(gdal.GetLastErrorMsg());
-            System.exit(3);
-        }
-
-        /*
-         * Create target raster file.
-         */
-
-        Dataset dstDS = null;
-        String[] layerList = layers.split(":");
-        int layerCount = layerList.length;
-        int bandCount = layerCount;
-
-        if (SQL != null) {
-            bandCount++;
-        }
-
-        if (sizeX == 0) {
-            sizeX = 256;
-        }
-
-        if (sizeY == 0) {
-            sizeY = 256;
-        }
-
-        String[] optionList = createOptions == null ? null : createOptions
-                .split(":");
-
-        dstDS = driver.Create(outputFilename, sizeX, sizeY, 1, outputType,
-                optionList);
-
-        if (dstDS == null) {
-
-            System.out.println("Unable to create dataset '" + outputFilename);
-            System.out.println(gdal.GetLastErrorMsg());
-            System.exit(3);
-        }
-
-        /*
-         * Use terminal progress report
-         */
-        if (quiet == false) {
-
-            progressCallback = new TermProgressCallback();
-        }
-
-        /*
-         * Process SQL request.
-         */
-
-        if (SQL != null) {
-
-            Layer srcLayer = srcDS.ExecuteSQL(SQL);
-
-            if (srcLayer != null) {
-
-                ProcessLayer(srcLayer, dstDS, clipSrc, sizeX, sizeY, 1,
-                        isXExtentSet, isYExtentSet, minX, maxX, minY, maxY,
-                        burnAttribute, outputType, algorithmAndOptions, quiet,
-                        progressCallback);
-            }
-        }
-
-        /*
-         * Process each layer.
-         */
-
-        for (int i = 0; i < layerList.length; i++) {
-
-            Layer srcLayer = srcDS.GetLayerByName(layerList[i]);
-
-            if (srcLayer == null) {
-
-                System.out.println("Unable to find layer '" + layerList[i]);
-                continue;
-            }
-
-            if (where != null) {
-
-                if (srcLayer.SetAttributeFilter(where) != gdalconstConstants.CE_None) {
-                    break;
-                }
-            }
-
-            if (spatialFilter != null) {
-
-                srcLayer.SetSpatialFilter(spatialFilter);
-            }
-
-            if (outputSRS == null) {
-
-                SpatialReference srs = srcLayer.GetSpatialRef();
-
-                if (srs != null) {
-
-                    outputSRS = srs.ExportToWkt();
-                }
-            }
-
-            ProcessLayer(srcLayer, dstDS, clipSrc, sizeX, sizeY, i + 1
-                    + bandCount - layerCount, isXExtentSet, isYExtentSet, minX,
-                    maxX, minY, maxY, burnAttribute, outputType,
-                    algorithmAndOptions, quiet, progressCallback);
-        }
-
-        /*
-         * Apply geotransformation matrix.
-         */
-
-        double[] geoTransform = new double[6];
-
-        geoTransform[0] = minX[0];
-        geoTransform[1] = (maxX[0] - minX[0]) / sizeX;
-        geoTransform[2] = 0.0;
-        geoTransform[3] = minY[0];
-        geoTransform[4] = 0.0;
-        geoTransform[5] = (maxY[0] - minY[0]) / sizeY;
-
-        dstDS.SetGeoTransform(geoTransform);
-
-        /*
-         * Apply SRS definition if set.
-         */
-
-        if (outputSRS != null) {
-
-            dstDS.SetProjection(outputSRS);
-        }
-
-        /*
-         * Cleanup.
-         */
-
-        srcDS.delete();
-        dstDS.delete();
-
-        gdal.GDALDestroyDriverManager();
-    }
-}
-
-class GDALGridScaledProgress extends ProgressCallback {
-    private double pctMin;
-    private double pctMax;
-    private ProgressCallback mainCbk;
-
-    public GDALGridScaledProgress(double pctMin, double pctMax,
-            ProgressCallback mainCbk) {
-        this.pctMin = pctMin;
-        this.pctMax = pctMax;
-        this.mainCbk = mainCbk;
-    }
-
-    public int run(double dfComplete, String message) {
-        return mainCbk.run(pctMin + dfComplete * (pctMax - pctMin), message);
-    }
-};
+/******************************************************************************
+ * $Id: GDALGrid.java $
+ *
+ * Project: GDAL Java applications
+ * Purpose: GDAL scattered data gridding (interpolation) tool
+ * Author:  Ivan Lucena, ivan.lucena at pmldnet.com,
+ *          translated from gdal_grid.cpp
+ *          originally written by Andrey Kiselev, dron at ak4719.spb.edu
+ ******************************************************************************
+ * Copyright (c) 2010, Ivan Lucena
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ ****************************************************************************/
+
+import java.util.ArrayList;
+import java.util.List;
+import java.nio.ByteBuffer;
+
+import org.gdal.gdal.Band;
+import org.gdal.gdal.Dataset;
+import org.gdal.gdal.Driver;
+import org.gdal.gdal.ProgressCallback;
+import org.gdal.gdal.TermProgressCallback;
+import org.gdal.gdal.gdal;
+import org.gdal.gdalconst.gdalconstConstants;
+import org.gdal.ogr.DataSource;
+import org.gdal.ogr.Feature;
+import org.gdal.ogr.Geometry;
+import org.gdal.ogr.Layer;
+import org.gdal.ogr.ogr;
+import org.gdal.ogr.ogrConstants;
+import org.gdal.osr.SpatialReference;
+
+public class GDALGrid {
+
+    public static void Usage() {
+        System.out
+                .println("Usage: gridcreate [--help-general] [--formats]\n"
+                        + "    [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
+                        + "            CInt16/CInt32/CFloat32/CFloat64}]\n"
+                        + "    [-of format] [-co \"NAME=VALUE\"]\n"
+                        + "    [-zfield field_name]\n"
+                        + "    [-a_srs srs_def] [-spat xmin ymin xmax ymax]\n"
+                        + "    [-clipsrc <xmin ymin xmax ymax>|WKT|datasource|spat_extent]\n"
+                        + "    [-clipsrcsql sql_statement] [-clipsrclayer layer]\n"
+                        + "    [-clipsrcwhere expression]\n"
+                        + "    [-l layername]* [-where expression] [-sql select_statement]\n"
+                        + "    [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]\n"
+                        + "    [-a algorithm[:parameter1=value1]*]\n"
+                        + "    [-q]\n"
+                        + "    <src_datasource> <dst_filename>\n"
+                        + "\n"
+                        + "Available algorithms and parameters with their's defaults:\n"
+                        + "    Inverse distance to a power (default)\n"
+                        + "        invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:"
+                        + "angle=0.0:max_points=0:min_points=0:nodata=0.0\n"
+                        + "    Moving average\n"
+                        + "        average:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
+                        + "    Nearest neighbor\n"
+                        + "        nearest:radius1=0.0:radius2=0.0:angle=0.0:nodata=0.0\n"
+                        + "    Various data metrics\n"
+                        + "        <metric name>:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
+                        + "        possible metrics are:\n"
+                        + "            minimum\n"
+                                                + "            maximum\n"
+                        + "            range\n"
+                                                + "            count\n"
+                        + "            average_distance\n"
+                        + "            average_distance_pts\n");
+        System.exit(-1);
+    }
+
+    /*
+     * Print algorithm and options.
+     */
+    public static void PrintAlgorithmAndOptions(String algorithmAndOptions) {
+
+        if (algorithmAndOptions == null) {
+
+            System.out
+                    .println("Algorithm name: not selected, using default Inverse Distance");
+        } else {
+
+            int firstColon = algorithmAndOptions.indexOf(':');
+            System.out.println("Algorithm name: "
+                    + algorithmAndOptions.substring(0, firstColon));
+            System.out.println("Options are \""
+                    + algorithmAndOptions.substring(firstColon + 1) + "\"");
+        }
+    }
+
+    /*
+     * ProcessGeometry
+     *
+     * Extract point coordinates from the geometry reference and set the Z value
+     * as requested. Test whether we are in the clipped region before
+     * processing.
+     */
+    public static void ProcessGeometry(Geometry point, Geometry clipSrc,
+            int burnField, double burnValue, List<Double> X, List<Double> Y,
+            List<Double> Z) {
+
+        if (clipSrc != null && point.Within(clipSrc) == false)
+            return;
+
+        X.add(point.GetX());
+        Y.add(point.GetY());
+
+        if (burnField < 0) {
+
+            Z.add(point.GetZ());
+        } else {
+
+            Z.add(burnValue);
+        }
+    }
+
+    /*
+     * Process all the features in a layer selection, collecting geometries and
+     * burn values.
+     */
+    public static void ProcessLayer(Layer srcLayer, Dataset dstDS,
+            Geometry clipSrc, int sizeX, int sizeY, int bandIndex,
+            boolean[] isXExtentSet, boolean[] isYExtentSet, double[] minX,
+            double[] maxX, double[] minY, double[] maxY, String burnAttribute,
+            int type, String algorithmAndOptions, boolean quiet,
+            ProgressCallback progressCallback) {
+
+        /*
+         * Get field index, and check.
+         */
+
+        int burnFieldIndex = -1;
+
+        if (burnAttribute != null) {
+
+            burnFieldIndex = srcLayer.GetLayerDefn().GetFieldIndex(
+                    burnAttribute);
+
+            if (burnFieldIndex == -1) {
+
+                System.out.println("Failed to find field " + burnAttribute
+                        + " on layer " + srcLayer.GetLayerDefn().GetName());
+                return;
+            }
+        }
+
+        /*
+         * Collect the geometries from this layer, and build list of values to
+         * be interpolated.
+         */
+
+        Feature feature;
+
+        List<Double> X = new ArrayList<Double>();
+        List<Double> Y = new ArrayList<Double>();
+        List<Double> Z = new ArrayList<Double>();
+
+        srcLayer.ResetReading();
+
+        while ((feature = srcLayer.GetNextFeature()) != null) {
+
+            Geometry geometry = feature.GetGeometryRef();
+
+            if (geometry != null) {
+
+                int geomtype = geometry.GetGeometryType()
+                        & (~ogrConstants.wkb25DBit);
+
+                double burnValue = 0.0;
+
+                if (burnFieldIndex >= 0) {
+
+                    burnValue = feature.GetFieldAsDouble(burnFieldIndex);
+                }
+
+                if (geomtype == ogr.wkbMultiPoint) {
+
+                    int geomIndex = 0;
+                    int geomCount = geometry.GetGeometryCount();
+
+                    for (geomIndex = 0; geomIndex < geomCount; geomIndex++) {
+
+                        ProcessGeometry(geometry.GetGeometryRef(geomIndex),
+                                clipSrc, burnFieldIndex, burnValue, X, Y, Z);
+                    }
+
+                } else {
+
+                    ProcessGeometry(geometry, clipSrc, burnFieldIndex,
+                            burnValue, X, Y, Z);
+                }
+            }
+
+            feature.delete();
+        }
+
+        if (X.size() == 0) {
+
+            System.out.println("No point geometry found on layer "
+                    + srcLayer.GetLayerDefn().GetName() + ", skipping.");
+            return;
+        }
+
+        /*
+         * Compute grid geometry.
+         */
+
+        if (isXExtentSet[0] == false) {
+
+            minX[0] = X.get(0);
+            maxX[0] = X.get(0);
+
+            for (int i = 1; i < X.size(); i++) {
+
+                if (minX[0] > X.get(i))
+                    minX[0] = X.get(i);
+
+                if (maxX[0] < X.get(i))
+                    maxX[0] = X.get(i);
+            }
+
+            isXExtentSet[0] = true;
+        }
+
+        if (isYExtentSet[0] == false) {
+
+            minY[0] = Y.get(0);
+            maxY[0] = Y.get(0);
+
+            for (int i = 1; i < Y.size(); i++) {
+
+                if (minY[0] > Y.get(i))
+                    minY[0] = Y.get(i);
+
+                if (maxY[0] < Y.get(i))
+                    maxY[0] = Y.get(i);
+            }
+
+            isYExtentSet[0] = true;
+        }
+
+        /*
+         * Perform gridding.
+         */
+
+        Double deltaX = (maxX[0] - minX[0]) / sizeX;
+        Double deltaY = (maxY[0] - minY[0]) / sizeY;
+
+        if (!quiet) {
+
+            System.out.println("Grid data type is "
+                    + gdal.GetDataTypeName(type));
+            System.out.println("Grid size = (" + sizeX + " " + sizeY + ").");
+            System.out.println("Corner coordinates = (" + (minX[0] - deltaX / 2)
+                    + " " + (maxY[0] + deltaY / 2) + ") - (" + (maxX[0] + deltaX / 2)
+                    + " " + (minY[0] - deltaY / 2) + ")");
+            System.out.println("Grid cell size = (" + deltaX + " " + deltaY
+                    + ").");
+            System.out.println("Source point count = " + X.size() + " .");
+            PrintAlgorithmAndOptions(algorithmAndOptions);
+        }
+
+        Band band = dstDS.GetRasterBand(bandIndex);
+
+        if (X.size() == 0) {
+
+            Double val[] = new Double[1];
+
+            band.GetNoDataValue(val);
+
+            if (val[0] != null) {
+                band.Fill(val[0]);
+            } else {
+                band.Fill(0.0);
+            }
+
+            return;
+        }
+
+        int offsetX = 0;
+        int offsetY = 0;
+        int[] blockXSize = new int[1];
+        int[] blockYSize = new int[1];
+
+        band.GetBlockSize(blockXSize, blockYSize);
+
+        int bufferSize = blockXSize[0] * blockYSize[0]
+                * gdal.GetDataTypeSize(type) / 8;
+
+        ByteBuffer data = ByteBuffer.allocateDirect(bufferSize);
+
+        int blockIndex = 0;
+        int blockCount = ((sizeX + blockXSize[0] - 1) / blockXSize[0])
+                * ((sizeY + blockYSize[0] - 1) / blockYSize[0]);
+
+        GDALGridScaledProgress griddingProgress = null;
+
+        for (offsetY = 0; offsetY < sizeY; offsetY += blockYSize[0]) {
+
+            for (offsetX = 0; offsetX < sizeX; offsetX += blockXSize[0]) {
+
+                int requestX = blockXSize[0];
+
+                if (offsetX + requestX > sizeX) {
+
+                    requestX = sizeX - offsetX;
+                }
+
+                int requestY = blockYSize[0];
+
+                if (offsetY + requestY > sizeY) {
+
+                    requestY = sizeY - offsetY;
+                }
+
+
+                /*
+                 * Reformat arguments
+                 */
+
+                double[][] points = new double[X.size()][3];
+                for (int i = 0; i < X.size(); i++)
+                    points[i][0] = X.get(i);
+                for (int i = 0; i < Y.size(); i++)
+                    points[i][1] = Y.get(i);
+                for (int i = 0; i < Z.size(); i++)
+                    points[i][2] = Z.get(i);
+
+                /*
+                 * Create Scaled progress report
+                 */
+
+                if (quiet == false) {
+                    griddingProgress = new GDALGridScaledProgress(
+                            blockIndex * 1.0 / blockCount,
+                            (blockIndex + 1) * 1.0 / blockCount,
+                            progressCallback);
+                }
+
+                /*
+                 * Create Grid
+                 */
+
+                gdal.GridCreate(algorithmAndOptions, points, minX[0] + deltaX
+                        * offsetX, minX[0] + deltaX * (offsetX + requestX), minY[0]
+                        + deltaY * offsetY, minY[0] + deltaY
+                        * (offsetY + requestY), requestX, requestY, type, data,
+                        griddingProgress);
+
+                /*
+                 * Write grid to raster output
+                 */
+
+                band.WriteRaster_Direct(offsetX, offsetY, requestX, requestY,
+                        requestX, requestY, type, data);
+
+                if (quiet == false) {
+                    griddingProgress.delete();
+                }
+
+                blockIndex++;
+            }
+        }
+    }
+
+    /*
+     * LoadGeometry
+     *
+     * Read geometries from the given dataset using specified filters and
+     * returns a collection of read geometries.
+     */
+    static Geometry LoadGeometry(String srcDS, String srcSQL, String srcLyr,
+            String srcWhere) {
+
+        DataSource DS;
+        Layer lyr;
+        Feature feat;
+        Geometry geom = null;
+
+        DS = ogr.Open(srcDS, false);
+
+        if (DS == null) {
+
+            return null;
+        }
+
+        if (srcSQL != null) {
+
+            lyr = DS.ExecuteSQL(srcSQL, null, null);
+        } else if (srcLyr != null) {
+
+            lyr = DS.GetLayerByName(srcLyr);
+        } else {
+
+            lyr = DS.GetLayer(0);
+        }
+
+        if (lyr == null) {
+
+            System.err
+                    .println("Failed to identify source layer from datasource.");
+            DS.delete();
+            return null;
+        }
+
+        if (srcWhere != null) {
+
+            lyr.SetAttributeFilter(srcWhere);
+        }
+
+        while ((feat = lyr.GetNextFeature()) != null) {
+
+            Geometry srcGeom = feat.GetGeometryRef();
+
+            if (srcGeom != null) {
+
+                int srcType = srcGeom.GetGeometryType()
+                        & (~ogrConstants.wkb25DBit);
+
+                if (geom == null) {
+
+                    geom = new Geometry(ogr.wkbMultiPolygon);
+                }
+
+                if (srcType == ogr.wkbPolygon) {
+
+                    geom.AddGeometry(srcGeom);
+                } else if (srcType == ogr.wkbMultiPolygon) {
+
+                    int geomIndex = 0;
+                    int geomCount = srcGeom.GetGeometryCount();
+
+                    for (geomIndex = 0; geomIndex < geomCount; geomIndex++) {
+
+                        geom.AddGeometry(srcGeom.GetGeometryRef(geomIndex));
+                    }
+
+                } else {
+
+                    System.err
+                            .println("FAILURE: Geometry not of polygon type.");
+
+                    if (srcSQL != null) {
+
+                        DS.ReleaseResultSet(lyr);
+                    }
+
+                    DS.delete();
+
+                    return null;
+                }
+            }
+        }
+
+        if (srcSQL != null) {
+
+            DS.ReleaseResultSet(lyr);
+        }
+
+        DS.delete();
+
+        return geom;
+    }
+
+    public static void main(String[] args) {
+
+        String sourceFilename = null;
+        String outputFilename = null;
+        String outputFormat = "GTiff";
+        String layers = null;
+        String burnAttribute = null;
+        String where = null;
+        int outputType = gdalconstConstants.GDT_Float64;
+        String createOptions = null;
+        boolean quiet = false;
+        double[] minX = new double[1];
+        double[] maxX = new double[1];
+        double[] minY = new double[1];
+        double[] maxY = new double[1];
+        int sizeX = 0;
+        int sizeY = 0;
+        String SQL = null;
+        boolean hasClipSrc = false;
+        String clipSQL = null;
+        String clipLayer = null;
+        String clipWhere = null;
+        String outputSRS = null;
+        String algorithmAndOptions = null;
+        Geometry clipSrc = null;
+        Geometry spatialFilter = null;
+        ProgressCallback progressCallback = null;
+        String clipSrcDS = null;
+        boolean[] isXExtentSet = new boolean[1];
+        boolean[] isYExtentSet = new boolean[1];
+
+        minX[0] = 0.0;
+        maxX[0] = 0.0;
+        minY[0] = 0.0;
+        maxY[0] = 0.0;
+
+        isXExtentSet[0] = false;
+        isYExtentSet[0] = false;
+
+        /*
+         * Register GDAL and OGR format(s)
+         */
+
+        gdal.AllRegister();
+        ogr.RegisterAll();
+
+        /*
+         * Parse arguments
+         */
+
+        args = ogr.GeneralCmdLineProcessor(args);
+
+        if (args.length < 2) {
+            Usage();
+        }
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("---utility_version")) {
+
+                System.out.println("Running against GDAL " + gdal.VersionInfo());
+                return;
+
+            } else if (args[i].equals("-of") && args.length > i) {
+
+                outputFormat = args[++i];
+
+            } else if (args[i].equals("-q") || args[i].equals("-quiet")) {
+
+                quiet = true;
+
+            } else if (args[i].equals("-ot") && args.length > i) {
+
+                outputType = gdal.GetDataTypeByName(args[++i]);
+
+                if (outputType == gdalconstConstants.GDT_Unknown) {
+
+                    System.err.println("FAILURE: Unknown output pixel type: "
+                            + args[i]);
+                    Usage();
+                }
+
+            } else if (args[i].equals("-txe") && args.length > i + 1) {
+
+                minX[0] = Double.parseDouble(args[++i]);
+                maxX[0] = Double.parseDouble(args[++i]);
+                isXExtentSet[0] = true;
+
+            } else if (args[i].equals("-tye") && args.length > i + 1) {
+
+                minY[0] = Double.parseDouble(args[++i]);
+                maxY[0] = Double.parseDouble(args[++i]);
+                isYExtentSet[0] = true;
+
+            } else if (args[i].equals("-outsize") && args.length > i + 1) {
+
+                sizeX = Integer.parseInt(args[++i]);
+                sizeY = Integer.parseInt(args[++i]);
+
+            } else if (args[i].equals("-co") && args.length > i) {
+
+                if (createOptions == null) {
+                    createOptions = args[++i];
+                } else {
+                    createOptions += ':' + args[++i];
+                }
+
+            } else if (args[i].equals("-zfield") && args.length > i) {
+
+                burnAttribute = args[++i];
+
+            } else if (args[i].equals("-where") && args.length > i) {
+
+                where = args[++i];
+
+            } else if (args[i].equals("-l") && args.length > i) {
+
+                if (layers == null) {
+                    layers = args[++i];
+                } else {
+                    layers += ':' + args[++i];
+                }
+
+            } else if (args[i].equals("-sql") && args.length > i) {
+
+                SQL = args[++i];
+
+            } else if (args[i].equals("-spat") && args.length > i + 3) {
+
+                double clipMinX = Double.parseDouble(args[i + 1]);
+                double clipMinY = Double.parseDouble(args[i + 2]);
+                double clipMaxX = Double.parseDouble(args[i + 3]);
+                double clipMaxY = Double.parseDouble(args[i + 4]);
+                i += 4;
+                clipSrc = new Geometry(ogr.wkbPolygon);
+                clipSrc.AddPoint(clipMinX, clipMinY);
+                clipSrc.AddPoint(clipMinX, clipMaxY);
+                clipSrc.AddPoint(clipMaxX, clipMaxY);
+                clipSrc.AddPoint(clipMaxX, clipMinY);
+                clipSrc.AddPoint(clipMinX, clipMinY);
+
+            } else if (args[i].equals("-clipsrc") && args.length > i) {
+
+                hasClipSrc = true;
+
+                try {
+
+                    double clipMinX = Double.parseDouble(args[i + 1]);
+                    double clipMinY = Double.parseDouble(args[i + 2]);
+                    double clipMaxX = Double.parseDouble(args[i + 3]);
+                    double clipMaxY = Double.parseDouble(args[i + 4]);
+                    i += 4;
+                    clipSrc = new Geometry(ogr.wkbPolygon);
+                    clipSrc.AddPoint(clipMinX, clipMinY);
+                    clipSrc.AddPoint(clipMinX, clipMaxY);
+                    clipSrc.AddPoint(clipMaxX, clipMaxY);
+                    clipSrc.AddPoint(clipMaxX, clipMinY);
+                    clipSrc.AddPoint(clipMinX, clipMinY);
+
+                } catch (NumberFormatException e) {
+
+                    if (args[i].substring(0, 6).equals("POLYGON")
+                            || args[i].substring(0, 11).equals("MULTIPOLYGON")) {
+
+                        clipSrc = ogr.CreateGeometryFromWkt(args[++i]);
+
+                    } else if (args[i].equals("spat_extent")) {
+
+                        ++i;
+
+                    } else {
+
+                        clipSrcDS = args[++i];
+                    }
+                }
+
+            } else if (args[i].equals("-clipsrcsql") && args.length > i) {
+
+                clipSQL = args[++i];
+
+            } else if (args[i].equals("-clipsrclayer") && args.length > i) {
+
+                clipLayer = args[++i];
+
+            } else if (args[i].equals("-clipsrcwhere") && args.length > i) {
+
+                clipLayer = args[++i];
+
+            } else if (args[i].equals("-a_srs") && args.length > i) {
+
+                SpatialReference enteredSRS = new SpatialReference();
+
+                if (enteredSRS.SetFromUserInput(args[i + 1]) != 0) {
+                    System.err.println("Failed to process SRS definition: "
+                            + args[i + 1]);
+                    Usage();
+                }
+                i++;
+
+                outputSRS = enteredSRS.ExportToWkt();
+
+            } else if (args[i].equals("-a") && args.length > i) {
+
+                if (algorithmAndOptions == null) {
+                    algorithmAndOptions = args[++i];
+                } else {
+                    algorithmAndOptions += ':' + args[++i];
+                }
+
+            } else if (args[i].substring(0, 1).equals("-")) {
+
+                System.err.println("FAILURE: Option " + args[i]
+                        + "incomplete, or not recognised");
+                Usage();
+
+            } else if (sourceFilename == null) {
+
+                sourceFilename = args[i];
+
+            } else if (outputFilename == null) {
+
+                outputFilename = args[i];
+
+            } else {
+
+                Usage();
+
+            }
+        }
+
+        if (sourceFilename == null || outputFilename == null
+                || (SQL == null && layers == null)) {
+
+            Usage();
+        }
+
+        /*
+         * Open Input
+         */
+
+        if (hasClipSrc && clipSrcDS != null) {
+
+            clipSrc = LoadGeometry(clipSrcDS, clipSQL, clipLayer, clipWhere);
+
+            if (clipSrc == null) {
+
+                System.out.println("FAILURE: cannot load source clip geometry");
+                Usage();
+            }
+
+        } else if (hasClipSrc && clipSrcDS == null) {
+
+            clipSrc = spatialFilter.Clone();
+
+            if (clipSrc == null) {
+
+                System.out
+                        .println("FAILURE: "
+                                + "-clipsrc must be used with -spat option or \n"
+                                + "a bounding box, WKT string or datasource must be specified");
+                Usage();
+            }
+        }
+
+        /*
+         * Find the output driver.
+         */
+
+        Driver driver = gdal.GetDriverByName(outputFormat);
+
+        if (driver == null) {
+
+            System.out.println("FAILURE: Output driver '" + outputFormat
+                    + "' not recognized.");
+            Usage();
+        }
+
+        /*
+         * Open input datasource.
+         */
+
+        DataSource srcDS = ogr.Open(sourceFilename);
+
+        if (srcDS == null) {
+
+            System.out.println("Unable to open input datasource '"
+                    + sourceFilename);
+            System.out.println(gdal.GetLastErrorMsg());
+            System.exit(3);
+        }
+
+        /*
+         * Create target raster file.
+         */
+
+        Dataset dstDS = null;
+        String[] layerList = layers.split(":");
+        int layerCount = layerList.length;
+        int bandCount = layerCount;
+
+        if (SQL != null) {
+            bandCount++;
+        }
+
+        if (sizeX == 0) {
+            sizeX = 256;
+        }
+
+        if (sizeY == 0) {
+            sizeY = 256;
+        }
+
+        String[] optionList = createOptions == null ? null : createOptions
+                .split(":");
+
+        dstDS = driver.Create(outputFilename, sizeX, sizeY, 1, outputType,
+                optionList);
+
+        if (dstDS == null) {
+
+            System.out.println("Unable to create dataset '" + outputFilename);
+            System.out.println(gdal.GetLastErrorMsg());
+            System.exit(3);
+        }
+
+        /*
+         * Use terminal progress report
+         */
+        if (quiet == false) {
+
+            progressCallback = new TermProgressCallback();
+        }
+
+        /*
+         * Process SQL request.
+         */
+
+        if (SQL != null) {
+
+            Layer srcLayer = srcDS.ExecuteSQL(SQL);
+
+            if (srcLayer != null) {
+
+                ProcessLayer(srcLayer, dstDS, clipSrc, sizeX, sizeY, 1,
+                        isXExtentSet, isYExtentSet, minX, maxX, minY, maxY,
+                        burnAttribute, outputType, algorithmAndOptions, quiet,
+                        progressCallback);
+            }
+        }
+
+        /*
+         * Process each layer.
+         */
+
+        for (int i = 0; i < layerList.length; i++) {
+
+            Layer srcLayer = srcDS.GetLayerByName(layerList[i]);
+
+            if (srcLayer == null) {
+
+                System.out.println("Unable to find layer '" + layerList[i]);
+                continue;
+            }
+
+            if (where != null) {
+
+                if (srcLayer.SetAttributeFilter(where) != gdalconstConstants.CE_None) {
+                    break;
+                }
+            }
+
+            if (spatialFilter != null) {
+
+                srcLayer.SetSpatialFilter(spatialFilter);
+            }
+
+            if (outputSRS == null) {
+
+                SpatialReference srs = srcLayer.GetSpatialRef();
+
+                if (srs != null) {
+
+                    outputSRS = srs.ExportToWkt();
+                }
+            }
+
+            ProcessLayer(srcLayer, dstDS, clipSrc, sizeX, sizeY, i + 1
+                    + bandCount - layerCount, isXExtentSet, isYExtentSet, minX,
+                    maxX, minY, maxY, burnAttribute, outputType,
+                    algorithmAndOptions, quiet, progressCallback);
+        }
+
+        /*
+         * Apply geotransformation matrix.
+         */
+
+        double[] geoTransform = new double[6];
+
+        geoTransform[0] = minX[0];
+        geoTransform[1] = (maxX[0] - minX[0]) / sizeX;
+        geoTransform[2] = 0.0;
+        geoTransform[3] = minY[0];
+        geoTransform[4] = 0.0;
+        geoTransform[5] = (maxY[0] - minY[0]) / sizeY;
+
+        dstDS.SetGeoTransform(geoTransform);
+
+        /*
+         * Apply SRS definition if set.
+         */
+
+        if (outputSRS != null) {
+
+            dstDS.SetProjection(outputSRS);
+        }
+
+        /*
+         * Cleanup.
+         */
+
+        srcDS.delete();
+        dstDS.delete();
+
+        gdal.GDALDestroyDriverManager();
+    }
+}
+
+class GDALGridScaledProgress extends ProgressCallback {
+    private double pctMin;
+    private double pctMax;
+    private ProgressCallback mainCbk;
+
+    public GDALGridScaledProgress(double pctMin, double pctMax,
+            ProgressCallback mainCbk) {
+        this.pctMin = pctMin;
+        this.pctMax = pctMax;
+        this.mainCbk = mainCbk;
+    }
+
+    public int run(double dfComplete, String message) {
+        return mainCbk.run(pctMin + dfComplete * (pctMax - pctMin), message);
+    }
+};
diff --git a/swig/java/apps/GDALOverviews.java b/swig/java/apps/GDALOverviews.java
index ebcf983..9543da3 100644
--- a/swig/java/apps/GDALOverviews.java
+++ b/swig/java/apps/GDALOverviews.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALOverviews.java 32865 2016-01-08 21:22:17Z goatbar $
+ * $Id: GDALOverviews.java 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALOverviews.java
  * Project:  GDAL Java Interface
@@ -50,19 +50,19 @@ import org.gdal.gdal.TermProgressCallback;
 
 /// <summary>
 /// A Java based sample to create GDAL raster overviews.
-/// </summary> 
+/// </summary>
 
 class GDALOverviews {
 
-	public static void usage() 
+	public static void usage()
 
-	{ 
+	{
 		System.out.println("usage: gdaloverviews {GDAL dataset name} {resamplealg} {level1} {level2} ....");
 		System.out.println("example: gdaloverviews sample.tif \"NEAREST\" 2 4");
 		System.exit(-1);
 	}
 
-    public static void main(String[] args) 
+    public static void main(String[] args)
     {
         /* -------------------------------------------------------------------- */
         /*      Register driver(s).                                             */
@@ -72,14 +72,14 @@ class GDALOverviews {
         args = gdal.GeneralCmdLineProcessor(args);
         if (args.length <= 2) usage();
 
-        try 
+        try
         {
             /* -------------------------------------------------------------------- */
             /*      Open dataset.                                                   */
             /* -------------------------------------------------------------------- */
             Dataset ds = gdal.Open( args[0], gdalconst.GA_Update );
 
-            if (ds == null) 
+            if (ds == null)
             {
                 System.out.println("Can't open " + args[0]);
                 System.exit(-1);
@@ -108,7 +108,7 @@ class GDALOverviews {
             /* -------------------------------------------------------------------- */
             /*      Displaying the raster parameters                                */
             /* -------------------------------------------------------------------- */
-            for (int iBand = 1; iBand <= ds.getRasterCount(); iBand++) 
+            for (int iBand = 1; iBand <= ds.getRasterCount(); iBand++)
             {
                 Band band = ds.GetRasterBand(iBand);
                 System.out.println("Band " + iBand + " :");
@@ -132,7 +132,7 @@ class GDALOverviews {
             System.out.println("Completed.");
             System.out.println("Use:  gdalread " + args[0] + " outfile.png [overview] to extract a particular overview!" );
         }
-        catch (Exception e) 
+        catch (Exception e)
         {
             System.out.println("Application error: " + e.getMessage());
         }
diff --git a/swig/java/apps/GDALProximity.java b/swig/java/apps/GDALProximity.java
index aff3ac9..cafaee0 100644
--- a/swig/java/apps/GDALProximity.java
+++ b/swig/java/apps/GDALProximity.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: GDALProximity.java 32865 2016-01-08 21:22:17Z goatbar $
+ * $Id: GDALProximity.java 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Project: GDAL
  * Purpose: Compute each pixel's proximity to a set of target pixels.
@@ -209,7 +209,7 @@ public class GDALProximity {
 
             WorkProximityDriver = gdal.GetDriverByName(OutputFormat);
 
-            WorkProximityDataset = WorkProximityDriver.Create(OutputFilename, 
+            WorkProximityDataset = WorkProximityDriver.Create(OutputFilename,
                     SourceDataset.getRasterXSize(), SourceDataset.getRasterYSize(),
                     SourceDataset.getRasterCount(), gdal.GetDataTypeByName(OutputType),
                     Options.split(";"));
@@ -292,7 +292,7 @@ public class GDALProximity {
 
         String tempFilename = null;
 
-        if (ProxType == gdalconstConstants.GDT_Byte 
+        if (ProxType == gdalconstConstants.GDT_Byte
                 || ProxType == gdalconstConstants.GDT_UInt16
                 || ProxType == gdalconstConstants.GDT_UInt32) {
             tempFilename = "/vsimem/proximity_" + String.valueOf(System.currentTimeMillis()) + ".tif";
diff --git a/swig/java/apps/GDALTestIO.java b/swig/java/apps/GDALTestIO.java
index 8c37ad5..94f476c 100644
--- a/swig/java/apps/GDALTestIO.java
+++ b/swig/java/apps/GDALTestIO.java
@@ -1,203 +1,203 @@
-/******************************************************************************
- * $Id: GDALTestIO.java 25018 2012-09-30 13:15:35Z rouault $
- *
- * Name:     GDALTestIO.java
- * Project:  GDAL Java Interface
- * Purpose:  A sample app to test ReadRaster_Direct / WriteRaster_Direct
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- * Adapted from a sample by Ivan Lucena
- *
- ******************************************************************************
- * Copyright (c) 2009, Even Rouault
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-import org.gdal.gdal.gdal;
-import org.gdal.gdal.Band;
-import org.gdal.gdal.Dataset;
-import org.gdal.gdal.Driver;
-import org.gdal.gdalconst.gdalconst;
-
-public class GDALTestIO implements Runnable
-{
-    String filename;
-    int    nbIters;
-    static final int METHOD_DBB = 1;
-    static final int METHOD_JAVA_ARRAYS = 2;
-    static int    method;
-
-    static volatile boolean bWait = true;
-    static volatile int nReady = 0;
-    static Object waiter = new Object();
-    static Object notifier = new Object();
-    
-    public GDALTestIO(String filename, int nbIters)
-    {
-        this.filename = filename;
-        this.nbIters = nbIters;
-    }
-    
-    public void run()
-    {
-        Dataset dataset = null;
-        Driver driver = null;
-        Band band = null;
-        
-        int xsize = 4000;
-        int ysize = 400;
-
-        synchronized(notifier)
-        {
-            nReady ++;
-            notifier.notify();
-        }
-
-        synchronized(waiter)
-        {
-            while( bWait )
-            {
-                try
-                {
-                    waiter.wait();
-                }
-                catch(InterruptedException ie)
-                {
-                }
-            }
-        }
-
-        driver = gdal.GetDriverByName("GTiff");
-            
-        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * xsize);
-        byteBuffer.order(ByteOrder.nativeOrder());
-        FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
-        int[] intArray = new int[xsize];
-        float[] floatArray = new float[xsize];
-        
-        dataset = driver.Create(filename, xsize, ysize, 1, gdalconst.GDT_Float32);
-        band = dataset.GetRasterBand(1);
-        
-        for(int iter = 0; iter < nbIters; iter++)
-        {
-            if (method == METHOD_DBB)
-            {
-                for( int i = 0; i < ysize; i++) {
-                    for( int j = 0; j < xsize; j++) {
-                        floatBuffer.put(j, (float) (i + j));
-                    }
-                    band.WriteRaster_Direct(0, i, xsize, 1, gdalconst.GDT_Float32, byteBuffer);
-                }
-            }
-            else
-            {
-                for( int i = 0; i < ysize; i++) {
-                    for( int j = 0; j < xsize; j++) {
-                        floatArray[j] = (float) (i + j);
-                    }
-                    band.WriteRaster(0, i, xsize, 1, floatArray);
-                }
-            }
-        }
-        
-        dataset.delete();
-        
-        /* Open the file to check the values */
-        dataset = gdal.Open(filename);
-        band = dataset.GetRasterBand(1);
-        
-        for(int iter = 0; iter < nbIters; iter++)
-        {
-            if (method == METHOD_DBB)
-            {
-                for( int i = 0; i < ysize; i++) {
-                    band.ReadRaster_Direct(0, i, xsize, 1, xsize, 1, gdalconst.GDT_Int32, byteBuffer);
-                    for( int j = 0; j < xsize; j++) {
-                        int val = byteBuffer.getInt(j*4);
-                        if (val != (i + j))
-                            throw new RuntimeException("Bad value for (" + j + "," + i + ") : " + val);
-                    }
-                }
-            }
-            else
-            {
-                for( int i = 0; i < ysize; i++) {
-                    band.ReadRaster(0, i, xsize, 1, intArray);
-                    for( int j = 0; j < xsize; j++) {
-                        int val = intArray[j];
-                        if (val != (i + j))
-                            throw new RuntimeException("Bad value for (" + j + "," + i + ") : " + val);
-                    }
-                } 
-            }
-        }
-        
-        dataset.delete();
-        
-        /* Free the memory occupied by the /vsimem file */
-        gdal.Unlink(filename);  
-    }
-
-    public static void main(String[] args) throws InterruptedException
-    {
-        gdal.AllRegister();
-        
-        int nbIters = 50;
-        
-        method = METHOD_JAVA_ARRAYS;
-        if (args.length >= 1 && args[0].equalsIgnoreCase("-dbb"))
-            method = METHOD_DBB;
-        
-        Thread t1 = new Thread(new GDALTestIO("/vsimem/test1.tif", nbIters));
-        Thread t2 = new Thread(new GDALTestIO("/vsimem/test2.tif", nbIters));
-        t1.start();
-        t2.start();
-
-        synchronized(notifier)
-        {
-            while( nReady != 2 )
-            {
-                try
-                {
-                    notifier.wait();
-                }
-                catch(InterruptedException ie)
-                {
-                }
-            }
-        }
-
-
-        synchronized(waiter)
-        {
-            bWait = false;
-            waiter.notifyAll();
-        }
-
-        t1.join();
-        t2.join();
-
-        System.out.println("Success !");
-    }
-}
+/******************************************************************************
+ * $Id: GDALTestIO.java 35222 2016-08-28 06:06:11Z goatbar $
+ *
+ * Name:     GDALTestIO.java
+ * Project:  GDAL Java Interface
+ * Purpose:  A sample app to test ReadRaster_Direct / WriteRaster_Direct
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ * Adapted from a sample by Ivan Lucena
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import org.gdal.gdal.gdal;
+import org.gdal.gdal.Band;
+import org.gdal.gdal.Dataset;
+import org.gdal.gdal.Driver;
+import org.gdal.gdalconst.gdalconst;
+
+public class GDALTestIO implements Runnable
+{
+    String filename;
+    int    nbIters;
+    static final int METHOD_DBB = 1;
+    static final int METHOD_JAVA_ARRAYS = 2;
+    static int    method;
+
+    static volatile boolean bWait = true;
+    static volatile int nReady = 0;
+    static Object waiter = new Object();
+    static Object notifier = new Object();
+
+    public GDALTestIO(String filename, int nbIters)
+    {
+        this.filename = filename;
+        this.nbIters = nbIters;
+    }
+
+    public void run()
+    {
+        Dataset dataset = null;
+        Driver driver = null;
+        Band band = null;
+
+        int xsize = 4000;
+        int ysize = 400;
+
+        synchronized(notifier)
+        {
+            nReady ++;
+            notifier.notify();
+        }
+
+        synchronized(waiter)
+        {
+            while( bWait )
+            {
+                try
+                {
+                    waiter.wait();
+                }
+                catch(InterruptedException ie)
+                {
+                }
+            }
+        }
+
+        driver = gdal.GetDriverByName("GTiff");
+
+        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4 * xsize);
+        byteBuffer.order(ByteOrder.nativeOrder());
+        FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
+        int[] intArray = new int[xsize];
+        float[] floatArray = new float[xsize];
+
+        dataset = driver.Create(filename, xsize, ysize, 1, gdalconst.GDT_Float32);
+        band = dataset.GetRasterBand(1);
+
+        for(int iter = 0; iter < nbIters; iter++)
+        {
+            if (method == METHOD_DBB)
+            {
+                for( int i = 0; i < ysize; i++) {
+                    for( int j = 0; j < xsize; j++) {
+                        floatBuffer.put(j, (float) (i + j));
+                    }
+                    band.WriteRaster_Direct(0, i, xsize, 1, gdalconst.GDT_Float32, byteBuffer);
+                }
+            }
+            else
+            {
+                for( int i = 0; i < ysize; i++) {
+                    for( int j = 0; j < xsize; j++) {
+                        floatArray[j] = (float) (i + j);
+                    }
+                    band.WriteRaster(0, i, xsize, 1, floatArray);
+                }
+            }
+        }
+
+        dataset.delete();
+
+        /* Open the file to check the values */
+        dataset = gdal.Open(filename);
+        band = dataset.GetRasterBand(1);
+
+        for(int iter = 0; iter < nbIters; iter++)
+        {
+            if (method == METHOD_DBB)
+            {
+                for( int i = 0; i < ysize; i++) {
+                    band.ReadRaster_Direct(0, i, xsize, 1, xsize, 1, gdalconst.GDT_Int32, byteBuffer);
+                    for( int j = 0; j < xsize; j++) {
+                        int val = byteBuffer.getInt(j*4);
+                        if (val != (i + j))
+                            throw new RuntimeException("Bad value for (" + j + "," + i + ") : " + val);
+                    }
+                }
+            }
+            else
+            {
+                for( int i = 0; i < ysize; i++) {
+                    band.ReadRaster(0, i, xsize, 1, intArray);
+                    for( int j = 0; j < xsize; j++) {
+                        int val = intArray[j];
+                        if (val != (i + j))
+                            throw new RuntimeException("Bad value for (" + j + "," + i + ") : " + val);
+                    }
+                }
+            }
+        }
+
+        dataset.delete();
+
+        /* Free the memory occupied by the /vsimem file */
+        gdal.Unlink(filename);
+    }
+
+    public static void main(String[] args) throws InterruptedException
+    {
+        gdal.AllRegister();
+
+        int nbIters = 50;
+
+        method = METHOD_JAVA_ARRAYS;
+        if (args.length >= 1 && args[0].equalsIgnoreCase("-dbb"))
+            method = METHOD_DBB;
+
+        Thread t1 = new Thread(new GDALTestIO("/vsimem/test1.tif", nbIters));
+        Thread t2 = new Thread(new GDALTestIO("/vsimem/test2.tif", nbIters));
+        t1.start();
+        t2.start();
+
+        synchronized(notifier)
+        {
+            while( nReady != 2 )
+            {
+                try
+                {
+                    notifier.wait();
+                }
+                catch(InterruptedException ie)
+                {
+                }
+            }
+        }
+
+
+        synchronized(waiter)
+        {
+            bWait = false;
+            waiter.notifyAll();
+        }
+
+        t1.join();
+        t2.join();
+
+        System.out.println("Success !");
+    }
+}
diff --git a/swig/java/apps/GDALtest.java b/swig/java/apps/GDALtest.java
index 80d448e..c23543b 100644
--- a/swig/java/apps/GDALtest.java
+++ b/swig/java/apps/GDALtest.java
@@ -1,9 +1,9 @@
 /******************************************************************************
- * $Id: GDALtest.java 17965 2009-11-04 21:41:21Z rouault $
+ * $Id: GDALtest.java 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     GDALtest.java
  * Project:  GDAL SWIG Interface
- * Purpose:  Sample Java application showing some basic loading of raster data 
+ * Purpose:  Sample Java application showing some basic loading of raster data
  * Author:   Benjamin Collins, The MITRE Corporation
  *
  *
@@ -72,8 +72,8 @@ public class GDALtest extends JFrame implements ActionListener{
 			}
 		}
 	}
-	
-	public GDALtest() {		
+
+	public GDALtest() {
 		load = new JButton("Load Image");
 		load.addActionListener(this);
 
@@ -88,15 +88,15 @@ public class GDALtest extends JFrame implements ActionListener{
 		this.setSize(1024, 768);
 		this.show();
 	}
-	
+
 	public void setImage(BufferedImage image) {
 		ImageIcon icon = new ImageIcon(image);
-		
+
 		if(this.canvas != null) {
 			canvas.setIcon(icon);
 		}
 	}
-	
+
 	public BufferedImage openFile(File f) {
 		Dataset poDataset = null;
 		try {
@@ -124,7 +124,7 @@ public class GDALtest extends JFrame implements ActionListener{
 		if (poDataset.GetProjectionRef() != null)
 			System.out.println("Projection is `" + poDataset.GetProjectionRef()
 					+ "'");
-		
+
 		Hashtable dict = poDataset.GetMetadata_Dict("");
 		Enumeration keys = dict.keys();
 		System.out.println(dict.size() + " items of metadata found (via Hashtable dict):");
@@ -140,7 +140,7 @@ public class GDALtest extends JFrame implements ActionListener{
 			String s = (String)enumerate.nextElement();
 			System.out.println(" " + s);
 		}
-		
+
 		Vector GCPs = new Vector();
 		poDataset.GetGCPs(GCPs);
 		System.out.println("Got " + GCPs.size() + " GCPs");
@@ -154,7 +154,7 @@ public class GDALtest extends JFrame implements ActionListener{
 					" line:" + gcp.getGCPLine() +
 					" line:" + gcp.getInfo());
 		}
-		
+
 
 		poDataset.GetGeoTransform(adfGeoTransform);
 		{
@@ -169,12 +169,12 @@ public class GDALtest extends JFrame implements ActionListener{
 		double[] adfMinMax = new double[2];
 		Double[] max = new Double[1];
 		Double[] min = new Double[1];
-		
+
 		int bandCount = poDataset.getRasterCount();
 		ByteBuffer[] bands = new ByteBuffer[bandCount];
 		int[] banks = new int[bandCount];
 		int[] offsets = new int[bandCount];
-		
+
 		int xsize = 1024;//poDataset.getRasterXSize();
 		int ysize = 1024;//poDataset.getRasterYSize();
 		int pixels = xsize * ysize;
@@ -183,7 +183,7 @@ public class GDALtest extends JFrame implements ActionListener{
 		for(int band = 0; band < bandCount; band++) {
 			/* Bands are not 0-base indexed, so we must add 1 */
 			poBand = poDataset.GetRasterBand(band+1);
-			
+
 			buf_type = poBand.getDataType();
 			buf_size = pixels * gdal.GetDataTypeSize(buf_type) / 8;
 
@@ -192,10 +192,10 @@ public class GDALtest extends JFrame implements ActionListener{
 			System.out.println(" ColorInterp = "
 					+ gdal.GetColorInterpretationName(poBand
 							.GetRasterColorInterpretation()));
-			
+
 			System.out.println("Band size is: " + poBand.getXSize() + "x"
 					+ poBand.getYSize());
-	
+
 			poBand.GetMinimum(min);
 			poBand.GetMaximum(max);
 			if(min[0] != null || max[0] != null) {
@@ -204,21 +204,21 @@ public class GDALtest extends JFrame implements ActionListener{
 			} else {
 				System.out.println("  No Min/Max values stored in raster.");
 			}
-	
+
 			if (poBand.GetOverviewCount() > 0) {
 				System.out.println("Band has " + poBand.GetOverviewCount()
 						+ " overviews.");
 			}
-	
+
 			if (poBand.GetRasterColorTable() != null) {
 				System.out.println("Band has a color table with "
 						+ poBand.GetRasterColorTable().GetCount() + " entries.");
 				for(int i = 0; i < poBand.GetRasterColorTable().GetCount(); i++) {
-					System.out.println(" " + i + ": " + 
+					System.out.println(" " + i + ": " +
 							poBand.GetRasterColorTable().GetColorEntry(i));
 				}
 			}
-			
+
 			System.out.println("Allocating ByteBuffer of size: " + buf_size);
 
 			ByteBuffer data = ByteBuffer.allocateDirect(buf_size);
@@ -226,7 +226,7 @@ public class GDALtest extends JFrame implements ActionListener{
 
 			int returnVal = 0;
 			try {
-				returnVal = poBand.ReadRaster_Direct(0, 0, poBand.getXSize(), 
+				returnVal = poBand.ReadRaster_Direct(0, 0, poBand.getXSize(),
 						poBand.getYSize(), xsize, ysize,
 						buf_type, data);
 			} catch(Exception ex) {
@@ -247,40 +247,40 @@ public class GDALtest extends JFrame implements ActionListener{
 		DataBuffer imgBuffer = null;
 		SampleModel sampleModel = null;
 		int data_type = 0, buffer_type = 0;
-		
+
 		if(buf_type == gdalconstConstants.GDT_Byte) {
 			byte[][] bytes = new byte[bandCount][];
-			for(int i = 0; i < bandCount; i++) {				
+			for(int i = 0; i < bandCount; i++) {
 				bytes[i] = new byte[pixels];
 				bands[i].get(bytes[i]);
 			}
 			imgBuffer = new DataBufferByte(bytes, pixels);
 			buffer_type = DataBuffer.TYPE_BYTE;
-			sampleModel = new BandedSampleModel(buffer_type, 
+			sampleModel = new BandedSampleModel(buffer_type,
 					xsize, ysize, xsize, banks, offsets);
-			data_type = (poBand.GetRasterColorInterpretation() == 
-				gdalconstConstants.GCI_PaletteIndex)? 
+			data_type = (poBand.GetRasterColorInterpretation() ==
+				gdalconstConstants.GCI_PaletteIndex)?
 				BufferedImage.TYPE_BYTE_INDEXED : BufferedImage.TYPE_BYTE_GRAY;
 		} else if(buf_type == gdalconstConstants.GDT_Int16) {
 			short[][] shorts = new short[bandCount][];
-			for(int i = 0; i < bandCount; i++) {				
+			for(int i = 0; i < bandCount; i++) {
 				shorts[i] = new short[pixels];
 				bands[i].asShortBuffer().get(shorts[i]);
 			}
 			imgBuffer = new DataBufferShort(shorts, pixels);
 			buffer_type = DataBuffer.TYPE_USHORT;
-			sampleModel = new BandedSampleModel(buffer_type, 
+			sampleModel = new BandedSampleModel(buffer_type,
 					xsize, ysize, xsize, banks, offsets);
 			data_type = BufferedImage.TYPE_USHORT_GRAY;
 		} else if(buf_type == gdalconstConstants.GDT_Int32) {
 			int[][] ints = new int[bandCount][];
-			for(int i = 0; i < bandCount; i++) {				
+			for(int i = 0; i < bandCount; i++) {
 				ints[i] = new int[pixels];
 				bands[i].asIntBuffer().get(ints[i]);
 			}
 			imgBuffer = new DataBufferInt(ints, pixels);
 			buffer_type = DataBuffer.TYPE_INT;
-			sampleModel = new BandedSampleModel(buffer_type, 
+			sampleModel = new BandedSampleModel(buffer_type,
 					xsize, ysize, xsize, banks, offsets);
 			data_type = BufferedImage.TYPE_CUSTOM;
 		}
@@ -289,7 +289,7 @@ public class GDALtest extends JFrame implements ActionListener{
 		BufferedImage img = null;
 		ColorModel cm = null;
 
-		if(poBand.GetRasterColorInterpretation() == 
+		if(poBand.GetRasterColorInterpretation() ==
 			gdalconstConstants.GCI_PaletteIndex) {
 			data_type = BufferedImage.TYPE_BYTE_INDEXED;
 			cm = poBand.GetRasterColorTable().getIndexColorModel(
@@ -299,7 +299,7 @@ public class GDALtest extends JFrame implements ActionListener{
 			ColorSpace cs = null;
 			if(bandCount > 2){
 				cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
-				cm = new ComponentColorModel(cs, false, false, 
+				cm = new ComponentColorModel(cs, false, false,
 						ColorModel.OPAQUE, buffer_type);
 				img = new BufferedImage(cm, raster, true, null);
 			} else {
diff --git a/swig/java/apps/OGRFeature.java b/swig/java/apps/OGRFeature.java
index 095cee8..c78500f 100644
--- a/swig/java/apps/OGRFeature.java
+++ b/swig/java/apps/OGRFeature.java
@@ -1,136 +1,136 @@
-/******************************************************************************
- * $Id: OGRFeature.java 16357 2009-02-16 23:30:06Z rouault $
- *
- * Name:     OGRFeature.java
- * Project:  OGR Java Interface
- * Purpose:  A sample app for demonstrating the caveats with JNI and garbage collecting...
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2009, Even Rouault
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-import org.gdal.ogr.Feature;
-import org.gdal.ogr.FeatureDefn;
-
-/* The nasty things below are necessary if the Feature class has a finalize() */
-/* method, which is no longer the case. See OGRTestGC.java */
-
-public class OGRFeature
-{
-    static int i;
-    static boolean doCleanup = false;
-    static boolean bHasFinished = false;
-    static FeatureDefn featureDefn;
-    static Object mutex = new Object();
-
-    public static void main(String[] args)
-    {
-        featureDefn = new FeatureDefn();
-
-        new Thread() {
-            public void run()
-            {
-                while(!bHasFinished)
-                {
-                    if (doCleanup)
-                    {
-                        int refBefore, refAfter;
-                        while(true)
-                        {
-                            refBefore = featureDefn.GetReferenceCount();
-                            System.out.print("i=" + i + " ref(before)="+ refBefore );
-                            System.runFinalization();
-                            refAfter = featureDefn.GetReferenceCount();
-                            System.out.println(" ref(after)="+ refAfter );
-                            if (refBefore == refAfter)
-                                System.gc();
-                            else
-                                break;
-                        }
-                        synchronized (mutex) {
-                            doCleanup = false;
-                            mutex.notify();
-                        }
-                    }
-
-                    synchronized (mutex) {
-                        while (doCleanup == false && bHasFinished == false)
-                        {
-                            //System.out.println("thread wakeup");
-                            try
-                            {
-                                mutex.wait();
-                            }
-                            catch(InterruptedException ie)
-                            {
-                                System.out.println("InterruptedException");
-                            }
-                        }
-                    }
-                }
-            }
-        }.start();
-
-        // Add features
-        for (i = 0; i < 5000000; i++)
-        {
-            new Feature(featureDefn);
-
-            if ((i % 100000) == 0)
-            {
-                /* Due to the fact that the Feature class has a finalize() method */
-                /* the garbage collector will differ finalization. So we have to do */
-                /* wait that the cleanup thread has forced finalizations */
-                while(featureDefn.GetReferenceCount() > 100000)
-                {
-                    //System.out.println("waiting for cleanup");
-                    synchronized (mutex) {
-                        doCleanup = true;
-                        mutex.notify();
-                        while (doCleanup)
-                        {
-                            //System.out.println("main thread wakeup");
-                            try
-                            {
-                                mutex.wait();
-                            }
-                            catch(InterruptedException ie)
-                            {
-                                System.out.println("InterruptedException");
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        synchronized (mutex) {
-            bHasFinished = true;
-            mutex.notify();
-        }
-
-        System.out.print("i=" + i + " ref(before)="+ featureDefn.GetReferenceCount() );
-        System.gc();
-        System.runFinalization();
-        System.out.println(" ref(after)="+ featureDefn.GetReferenceCount() );
-    }
-}
+/******************************************************************************
+ * $Id: OGRFeature.java 35219 2016-08-27 22:39:24Z goatbar $
+ *
+ * Name:     OGRFeature.java
+ * Project:  OGR Java Interface
+ * Purpose:  A sample app for demonstrating the caveats with JNI and garbage collecting...
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+import org.gdal.ogr.Feature;
+import org.gdal.ogr.FeatureDefn;
+
+/* The nasty things below are necessary if the Feature class has a finalize() */
+/* method, which is no longer the case. See OGRTestGC.java */
+
+public class OGRFeature
+{
+    static int i;
+    static boolean doCleanup = false;
+    static boolean bHasFinished = false;
+    static FeatureDefn featureDefn;
+    static Object mutex = new Object();
+
+    public static void main(String[] args)
+    {
+        featureDefn = new FeatureDefn();
+
+        new Thread() {
+            public void run()
+            {
+                while(!bHasFinished)
+                {
+                    if (doCleanup)
+                    {
+                        int refBefore, refAfter;
+                        while(true)
+                        {
+                            refBefore = featureDefn.GetReferenceCount();
+                            System.out.print("i=" + i + " ref(before)="+ refBefore );
+                            System.runFinalization();
+                            refAfter = featureDefn.GetReferenceCount();
+                            System.out.println(" ref(after)="+ refAfter );
+                            if (refBefore == refAfter)
+                                System.gc();
+                            else
+                                break;
+                        }
+                        synchronized (mutex) {
+                            doCleanup = false;
+                            mutex.notify();
+                        }
+                    }
+
+                    synchronized (mutex) {
+                        while (doCleanup == false && bHasFinished == false)
+                        {
+                            //System.out.println("thread wakeup");
+                            try
+                            {
+                                mutex.wait();
+                            }
+                            catch(InterruptedException ie)
+                            {
+                                System.out.println("InterruptedException");
+                            }
+                        }
+                    }
+                }
+            }
+        }.start();
+
+        // Add features
+        for (i = 0; i < 5000000; i++)
+        {
+            new Feature(featureDefn);
+
+            if ((i % 100000) == 0)
+            {
+                /* Due to the fact that the Feature class has a finalize() method */
+                /* the garbage collector will differ finalization. So we have to do */
+                /* wait that the cleanup thread has forced finalizations */
+                while(featureDefn.GetReferenceCount() > 100000)
+                {
+                    //System.out.println("waiting for cleanup");
+                    synchronized (mutex) {
+                        doCleanup = true;
+                        mutex.notify();
+                        while (doCleanup)
+                        {
+                            //System.out.println("main thread wakeup");
+                            try
+                            {
+                                mutex.wait();
+                            }
+                            catch(InterruptedException ie)
+                            {
+                                System.out.println("InterruptedException");
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        synchronized (mutex) {
+            bHasFinished = true;
+            mutex.notify();
+        }
+
+        System.out.print("i=" + i + " ref(before)="+ featureDefn.GetReferenceCount() );
+        System.gc();
+        System.runFinalization();
+        System.out.println(" ref(after)="+ featureDefn.GetReferenceCount() );
+    }
+}
diff --git a/swig/java/apps/OGRTestGC.java b/swig/java/apps/OGRTestGC.java
index 1bfc25f..b53084a 100644
--- a/swig/java/apps/OGRTestGC.java
+++ b/swig/java/apps/OGRTestGC.java
@@ -1,103 +1,103 @@
-/******************************************************************************
- * $Id: OGRTestGC.java 16357 2009-02-16 23:30:06Z rouault $
- *
- * Name:     OGRTestGC.java
- * Project:  OGR Java Interface
- * Purpose:  A sample app for demonstrating the caveats with JNI and garbage collecting...
- * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
- *
- ******************************************************************************
- * Copyright (c) 2009, Even Rouault
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-import org.gdal.ogr.ogr;
-import org.gdal.ogr.Feature;
-import org.gdal.ogr.FeatureDefn;
-import org.gdal.ogr.Geometry;
-
-/* This test should run fine as we use a smarter GC for */
-/* Geometry and Feature objects */
-
-public class OGRTestGC
-{
-    public static void main(String[] args)
-    {
-        FeatureDefn featureDefn = new FeatureDefn();
-
-        Geometry point1 = new Geometry(ogr.wkbPoint);
-        Geometry multipoint1 = new Geometry(ogr.wkbMultiPoint);
-        multipoint1.AddGeometryDirectly(point1);
-        try
-        {
-            /* Just to show that we are smart ! */
-            multipoint1.AddGeometryDirectly(point1);
-            System.err.println("should not reach that point");
-        }
-        catch(RuntimeException re)
-        {
-        }
-
-        Geometry multipoint2 = new Geometry(ogr.wkbMultiPoint);
-        multipoint2.AddGeometry(multipoint1.GetGeometryRef(0));
-        try
-        {
-            /* Just to show that we are smart ! */
-            multipoint2.AddGeometryDirectly(multipoint1.GetGeometryRef(0));
-            System.err.println("should not reach that point");
-        }
-        catch(RuntimeException re)
-        {
-        }
-
-        Geometry point3 = new Geometry(ogr.wkbPoint);
-        new Feature(featureDefn).SetGeometryDirectly(point3);
-
-        multipoint1 = null;
-
-        for (int i = 0; i < 500000; i++)
-        {
-            if ((i % 100000) == 0) System.out.println(i);
-            Feature feat = new Feature(featureDefn);
-            feat.SetGeometryDirectly(new Geometry(ogr.wkbMultiPoint));
-            feat.SetGeometry(null);
-            feat.GetGeometryRef();
-        }
-
-        // Add features
-        for (int i = 0; i < 1000000; i++)
-        {
-            if ((i % 100000) == 0) System.out.println(i);
-            Feature feat = new Feature(featureDefn);
-            feat.SetGeometry(new Geometry(ogr.wkbPoint));
-
-            Geometry point = new Geometry(ogr.wkbPoint);
-            Geometry multipoint = new Geometry(ogr.wkbMultiPoint);
-            multipoint.AddGeometryDirectly(point);
-        }
-
-        /* Check that the objects are still alive despite their */
-        /* Java containers and associated native objects */
-        /* would have been finalized without a trick */
-        System.out.println(point1.ExportToWkt());
-        System.out.println(point3.ExportToWkt());
-
-    }
-}
+/******************************************************************************
+ * $Id: OGRTestGC.java 35219 2016-08-27 22:39:24Z goatbar $
+ *
+ * Name:     OGRTestGC.java
+ * Project:  OGR Java Interface
+ * Purpose:  A sample app for demonstrating the caveats with JNI and garbage collecting...
+ * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
+ *
+ ******************************************************************************
+ * Copyright (c) 2009, Even Rouault
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *****************************************************************************/
+
+import org.gdal.ogr.ogr;
+import org.gdal.ogr.Feature;
+import org.gdal.ogr.FeatureDefn;
+import org.gdal.ogr.Geometry;
+
+/* This test should run fine as we use a smarter GC for */
+/* Geometry and Feature objects */
+
+public class OGRTestGC
+{
+    public static void main(String[] args)
+    {
+        FeatureDefn featureDefn = new FeatureDefn();
+
+        Geometry point1 = new Geometry(ogr.wkbPoint);
+        Geometry multipoint1 = new Geometry(ogr.wkbMultiPoint);
+        multipoint1.AddGeometryDirectly(point1);
+        try
+        {
+            /* Just to show that we are smart ! */
+            multipoint1.AddGeometryDirectly(point1);
+            System.err.println("should not reach that point");
+        }
+        catch(RuntimeException re)
+        {
+        }
+
+        Geometry multipoint2 = new Geometry(ogr.wkbMultiPoint);
+        multipoint2.AddGeometry(multipoint1.GetGeometryRef(0));
+        try
+        {
+            /* Just to show that we are smart ! */
+            multipoint2.AddGeometryDirectly(multipoint1.GetGeometryRef(0));
+            System.err.println("should not reach that point");
+        }
+        catch(RuntimeException re)
+        {
+        }
+
+        Geometry point3 = new Geometry(ogr.wkbPoint);
+        new Feature(featureDefn).SetGeometryDirectly(point3);
+
+        multipoint1 = null;
+
+        for (int i = 0; i < 500000; i++)
+        {
+            if ((i % 100000) == 0) System.out.println(i);
+            Feature feat = new Feature(featureDefn);
+            feat.SetGeometryDirectly(new Geometry(ogr.wkbMultiPoint));
+            feat.SetGeometry(null);
+            feat.GetGeometryRef();
+        }
+
+        // Add features
+        for (int i = 0; i < 1000000; i++)
+        {
+            if ((i % 100000) == 0) System.out.println(i);
+            Feature feat = new Feature(featureDefn);
+            feat.SetGeometry(new Geometry(ogr.wkbPoint));
+
+            Geometry point = new Geometry(ogr.wkbPoint);
+            Geometry multipoint = new Geometry(ogr.wkbMultiPoint);
+            multipoint.AddGeometryDirectly(point);
+        }
+
+        /* Check that the objects are still alive despite their */
+        /* Java containers and associated native objects */
+        /* would have been finalized without a trick */
+        System.out.println(point1.ExportToWkt());
+        System.out.println(point3.ExportToWkt());
+
+    }
+}
diff --git a/swig/java/apps/OSRTransform.java b/swig/java/apps/OSRTransform.java
index 4ce7b23..544ea0a 100644
--- a/swig/java/apps/OSRTransform.java
+++ b/swig/java/apps/OSRTransform.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: OSRTransform.java 25229 2012-11-16 19:06:58Z rouault $
+ * $Id: OSRTransform.java 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     OSRTransform.java
  * Project:  GDAL Java Interface
@@ -43,7 +43,7 @@ import org.gdal.osr.CoordinateTransformation;
 
 /// <summary>
 /// A Java based sample to make simple transformations.
-/// </summary> 
+/// </summary>
 public class OSRTransform {
 	public static void main(String[] args) {
 		try
@@ -75,4 +75,4 @@ public class OSRTransform {
 			System.exit(-1);
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/swig/java/apps/ReadXML.java b/swig/java/apps/ReadXML.java
index 2e5fc24..5d78b70 100644
--- a/swig/java/apps/ReadXML.java
+++ b/swig/java/apps/ReadXML.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ReadXML.java 32865 2016-01-08 21:22:17Z goatbar $
+ * $Id: ReadXML.java 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     ReadXML.java
  * Project:  GDAL Java Interface
@@ -46,11 +46,11 @@ import org.gdal.gdal.XMLNodeType;
 
 /// <summary>
 /// A C# based sample for demonstrating the usage of the XMLNode class.
-/// </summary> 
+/// </summary>
 
 public class ReadXML {
 
-    public static void usage() 
+    public static void usage()
 
     {
             System.out.println("usage example: readxml {xml string}");
diff --git a/swig/java/apps/WKT2WKB.java b/swig/java/apps/WKT2WKB.java
index 1f1c1c3..8194443 100644
--- a/swig/java/apps/WKT2WKB.java
+++ b/swig/java/apps/WKT2WKB.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: WKT2WKB.java 32865 2016-01-08 21:22:17Z goatbar $
+ * $Id: WKT2WKB.java 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     WKT2WKB.java
  * Project:  GDAL Java Interface
@@ -45,11 +45,11 @@ import org.gdal.ogr.Geometry;
 
 /// <summary>
 /// A Java based sample for demonstrating the usage of ExportToWkb.
-/// </summary> 
+/// </summary>
 
 public class WKT2WKB {
 
-        public static void usage() 
+        public static void usage()
         {
                 System.out.println("usage example: wkt2wkb \"POINT(47.0 19.2)\"");
                 System.exit(-1);
@@ -68,7 +68,7 @@ public class WKT2WKB {
             {
                 System.exit(-1);
             }
-            if (wkbSize > 0) 
+            if (wkbSize > 0)
             {
                 System.out.print( "wkt-->wkb: ");
                 for(int i=0;i<wkbSize;i++)
diff --git a/swig/java/apps/gdalinfo.java b/swig/java/apps/gdalinfo.java
index 8f2ed5b..d57c673 100644
--- a/swig/java/apps/gdalinfo.java
+++ b/swig/java/apps/gdalinfo.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: gdalinfo.java 32865 2016-01-08 21:22:17Z goatbar $
+ * $Id: gdalinfo.java 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Name:     gdalinfo.java
  * Project:  GDAL SWIG Interface
@@ -442,7 +442,7 @@ public class gdalinfo {
                                         if ( bComputeChecksum)
                                         {
                                             System.out.print( "  Overviews checksum: " );
-                                            for( iOverview = 0; 
+                                            for( iOverview = 0;
                                                 iOverview < hBand.GetOverviewCount();
                                                 iOverview++ )
                                             {
@@ -486,7 +486,7 @@ public class gdalinfo {
                                         int		iOverview;
 
                                         System.out.print( "  Overviews of mask band: " );
-                                        for( iOverview = 0; 
+                                        for( iOverview = 0;
                                             iOverview < hMaskBand.GetOverviewCount();
                                             iOverview++ )
                                         {
@@ -496,7 +496,7 @@ public class gdalinfo {
                                                 System.out.print( ", " );
 
                                             hOverview = hMaskBand.GetOverview( iOverview );
-                                            System.out.print( 
+                                            System.out.print(
                                                     hOverview.getXSize() + "x" +
                                                     hOverview.getYSize() );
                                         }
diff --git a/swig/java/apps/ogr2ogr.java b/swig/java/apps/ogr2ogr.java
index 3197a1c..33617ca 100644
--- a/swig/java/apps/ogr2ogr.java
+++ b/swig/java/apps/ogr2ogr.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogr2ogr.java 32865 2016-01-08 21:22:17Z goatbar $
+ * $Id: ogr2ogr.java 35222 2016-08-28 06:06:11Z goatbar $
  *
  * Project:  OpenGIS Simple Features Reference Implementation
  * Purpose:  Java port of a simple client for translating between formats.
@@ -524,7 +524,7 @@ public class ogr2ogr
     /* -------------------------------------------------------------------- */
         if( poDS == null )
         {
-            System.err.println("FAILURE:\n" + 
+            System.err.println("FAILURE:\n" +
                     "Unable to open datasource ` " + pszDataSource + "' with the following drivers.");
 
             for( int iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
@@ -682,7 +682,7 @@ public class ogr2ogr
             if( papszLayers.size() > 0 )
                 System.err.println( "layer names ignored in combination with -sql." );
 
-            poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter, 
+            poResultSet = poDS.ExecuteSQL( pszSQLStatement, poSpatialFilter,
                                             null );
 
             if( poResultSet != null )
@@ -720,7 +720,7 @@ public class ogr2ogr
                     }
                 }
 
-                if( !TranslateLayer( poDS, poResultSet, poODS, papszLCO, 
+                if( !TranslateLayer( poDS, poResultSet, poODS, papszLCO,
                                     pszNewLayerName, bTransform, poOutputSRS,
                                     poSourceSRS, papszSelFields, bAppend, eGType,
                                     bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
@@ -749,8 +749,8 @@ public class ogr2ogr
                 nLayerCount = poDS.GetLayerCount();
                 papoLayers = new Layer[nLayerCount];
 
-                for( int iLayer = 0; 
-                    iLayer < nLayerCount; 
+                for( int iLayer = 0;
+                    iLayer < nLayerCount;
                     iLayer++ )
                 {
                     Layer        poLayer = poDS.GetLayer(iLayer);
@@ -772,8 +772,8 @@ public class ogr2ogr
                 nLayerCount = papszLayers.size();
                 papoLayers = new Layer[nLayerCount];
 
-                for( int iLayer = 0; 
-                    iLayer < papszLayers.size(); 
+                for( int iLayer = 0;
+                    iLayer < papszLayers.size();
                     iLayer++ )
                 {
                     Layer        poLayer = poDS.GetLayerByName((String)papszLayers.get(iLayer));
@@ -811,8 +811,8 @@ public class ogr2ogr
             long nAccCountFeatures = 0;
 
             /* First pass to apply filters and count all features if necessary */
-            for( int iLayer = 0; 
-                iLayer < nLayerCount; 
+            for( int iLayer = 0;
+                iLayer < nLayerCount;
                 iLayer++ )
             {
                 Layer        poLayer = papoLayers[iLayer];
@@ -846,8 +846,8 @@ public class ogr2ogr
             }
 
             /* Second pass to do the real job */
-            for( int iLayer = 0; 
-                iLayer < nLayerCount; 
+            for( int iLayer = 0;
+                iLayer < nLayerCount;
                 iLayer++ )
             {
                 Layer        poLayer = papoLayers[iLayer];
@@ -862,12 +862,12 @@ public class ogr2ogr
 
                 nAccCountFeatures += panLayerCountFeatures[iLayer];
 
-                if( !TranslateLayer( poDS, poLayer, poODS, papszLCO, 
+                if( !TranslateLayer( poDS, poLayer, poODS, papszLCO,
                                     pszNewLayerName, bTransform, poOutputSRS,
                                     poSourceSRS, papszSelFields, bAppend, eGType,
                                     bOverwrite, eGeomOp, dfGeomOpParam, papszFieldTypesToString,
                                     panLayerCountFeatures[iLayer], poClipSrc, poClipDst, bExplodeCollections,
-                                    pszZField, pszWHERE, pfnProgress) 
+                                    pszZField, pszWHERE, pfnProgress)
                     && !bSkipFailures )
                 {
                     System.err.println(
@@ -897,7 +897,7 @@ public class ogr2ogr
     {
         System.out.print( "Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update] [-gt n]\n" +
                 "               [-select field_list] [-where restricted_where] \n" +
-                "               [-progress] [-sql <sql statement>] \n" + 
+                "               [-progress] [-sql <sql statement>] \n" +
                 "               [-spat xmin ymin xmax ymax] [-preserve_fid] [-fid FID]\n" +
                 "               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n" +
                 "               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n" +
@@ -922,8 +922,8 @@ public class ogr2ogr
                 " -update: Open existing output datasource in update mode\n" +
                 " -progress: Display progress on terminal. Only works if input layers have the \"fast feature count\" capability\n" +
                 " -select field_list: Comma-delimited list of fields from input layer to\n" +
-                "                     copy to the new layer (defaults to all)\n" + 
-                " -where restricted_where: Attribute query (like SQL WHERE)\n" + 
+                "                     copy to the new layer (defaults to all)\n" +
+                " -where restricted_where: Attribute query (like SQL WHERE)\n" +
                 " -sql statement: Execute given SQL statement and save result.\n" +
                 " -skipfailures: skip features or layers that fail to convert\n" +
                 " -gt n: group n features per transaction (default 200)\n" +
@@ -946,7 +946,7 @@ public class ogr2ogr
         System.out.print(" -a_srs srs_def: Assign an output SRS\n" +
             " -t_srs srs_def: Reproject/transform to this SRS on output\n" +
             " -s_srs srs_def: Override source SRS\n" +
-            "\n" + 
+            "\n" +
             " Srs_def can be a full WKT definition (hard to escape properly),\n" +
             " or a well known definition (i.e. EPSG:4326) or a file with a WKT\n" +
             " definition.\n" );
@@ -996,7 +996,7 @@ public class ogr2ogr
             return null;
 
         if (pszSQL != null)
-            poLyr = poDS.ExecuteSQL( pszSQL, null, null ); 
+            poLyr = poDS.ExecuteSQL( pszSQL, null, null );
         else if (pszLyr != null)
             poLyr = poDS.GetLayerByName(pszLyr);
         else
@@ -1102,12 +1102,12 @@ public class ogr2ogr
     /*                           TranslateLayer()                           */
     /************************************************************************/
 
-    static boolean TranslateLayer( DataSource poSrcDS, 
+    static boolean TranslateLayer( DataSource poSrcDS,
                             Layer poSrcLayer,
                             DataSource poDstDS,
                             Vector papszLCO,
                             String pszNewLayerName,
-                            boolean bTransform, 
+                            boolean bTransform,
                             SpatialReference poOutputSRS,
                             SpatialReference poSourceSRS,
                             Vector papszSelFields,
diff --git a/swig/java/apps/ogrinfo.java b/swig/java/apps/ogrinfo.java
index 0048583..16606ff 100644
--- a/swig/java/apps/ogrinfo.java
+++ b/swig/java/apps/ogrinfo.java
@@ -1,5 +1,5 @@
 /******************************************************************************
- * $Id: ogrinfo.java 34011 2016-04-18 16:22:21Z rouault $
+ * $Id: ogrinfo.java 34009 2016-04-18 16:18:31Z rouault $
  *
  * Name:     ogrinfo.java
  * Project:  GDAL SWIG Interface
diff --git a/swig/java/apps/ogrtindex.java b/swig/java/apps/ogrtindex.java
index d9a73f8..8f93204 100644
--- a/swig/java/apps/ogrtindex.java
+++ b/swig/java/apps/ogrtindex.java
@@ -1,579 +1,579 @@
-/******************************************************************************
- * $Id: ogrtindex.java 28375 2015-01-30 12:06:11Z rouault $
- *
- * Project:  OpenGIS Simple Features Reference Implementation
- * Purpose:  Program to generate a UMN MapServer compatible tile index for a
- *           set of OGR data sources. 
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2002, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-import org.gdal.gdal.gdal;
-import org.gdal.ogr.DataSource;
-import org.gdal.ogr.Driver;
-import org.gdal.ogr.Feature;
-import org.gdal.ogr.FeatureDefn;
-import org.gdal.ogr.FieldDefn;
-import org.gdal.ogr.Geometry;
-import org.gdal.ogr.Layer;
-import org.gdal.ogr.ogr;
-import org.gdal.osr.SpatialReference;
-
-/* Note : this is the most direct port of ogrtindex.cpp possible */
-/* It could be made much more java'ish ! */
-
-public class ogrtindex {
-
-   public static void main(String[] args) {
-
-      boolean bLayersWildcarded = true; 
-      int nFirstSourceDataset = -1; 
-      String pszFormat = "ESRI Shapefile";
-      String pszTileIndexField = "LOCATION";
-      String pszOutputName = null;
-      boolean write_absolute_path = false;
-      boolean skip_different_projection = false;
-      String current_path = null;
-      boolean accept_different_schemas = false;
-      boolean bFirstWarningForNonMatchingAttributes = true;
-
-      ogr.DontUseExceptions();
-
-      /* -------------------------------------------------------------------- */
-      /*      Register format(s).                                             */
-      /* -------------------------------------------------------------------- */
-      // fixed: http://osgeo-org.1803224.n2.nabble.com/GDAL-Java-Binding-meomory-problem-under-intensive-method-calls-td7155011.html#a7157916
-      if( ogr.GetDriverCount() == 0 )
-         ogr.RegisterAll(); 
-
-      /* -------------------------------------------------------------------- */
-      /*      Processing command line arguments.                              */
-      /* -------------------------------------------------------------------- */
-      args = ogr.GeneralCmdLineProcessor( args );
-
-      if( args.length < 2 )
-      {
-         Usage();
-         return;
-      }
-
-      for( int iArg = 0; iArg < args.length; iArg++ )
-      {
-         if( args[iArg].equalsIgnoreCase("-f") && iArg < args.length-1 )
-         {
-            pszFormat = args[++iArg];
-         }
-         else if( args[iArg].equalsIgnoreCase("-write_absolute_path") )
-         {
-            write_absolute_path = true;
-         }
-         else if( args[iArg].equalsIgnoreCase("-skip_different_projection") )
-         {
-            skip_different_projection = true;
-         }
-         else if( args[iArg].equalsIgnoreCase("-accept_different_schemas") )
-         {
-            accept_different_schemas = true;
-         }
-         else if( args[iArg].equalsIgnoreCase("-tileindex") && iArg < args.length-1 )
-         {
-            pszTileIndexField = args[++iArg];
-         }
-         else if( args[iArg].equalsIgnoreCase("-lnum") 
-               || args[iArg].equalsIgnoreCase("-lname") )
-         {
-            iArg++;
-            bLayersWildcarded = false;
-         }
-         else if( args[iArg].charAt(0) == '-' )
-            Usage();
-         else if( pszOutputName == null )
-            pszOutputName = args[iArg];
-         else if( nFirstSourceDataset == -1 )
-            nFirstSourceDataset = iArg;
-      }
-
-      if( pszOutputName == null || nFirstSourceDataset == -1 )
-         Usage();
-
-      /* -------------------------------------------------------------------- */
-      /*      Try to open as an existing dataset for update access.           */
-      /* -------------------------------------------------------------------- */
-      DataSource poDstDS;
-      Layer poDstLayer = null;
-
-      poDstDS = ogr.Open( pszOutputName, true );
-
-      /* -------------------------------------------------------------------- */
-      /*      If that failed, find the driver so we can create the tile index.*/
-      /* -------------------------------------------------------------------- */
-      if( poDstDS == null )
-      {        
-         Driver poDriver = null;
-
-         for( int iDriver = 0; iDriver < ogr.GetDriverCount() && poDriver == null; iDriver++ )
-         {
-            poDriver = ogr.GetDriverByName(pszFormat);
-         }
-
-         if( poDriver == null )
-         {
-            System.err.print("Unable to find driver '"+pszFormat+"'.\n");
-            System.err.print("The following drivers are available:\n" );
-
-            for( int iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
-            {
-               System.err.print("  . '"+ogr.GetDriver(iDriver).GetName()+"'\n");
-            }
-            return;
-         }
-
-         if( !poDriver.TestCapability( ogr.ODrCCreateDataSource ) )
-         {
-            System.err.print(pszFormat + " driver does not support data source creation.\n");                  
-            return;
-         }
-
-         /* -------------------------------------------------------------------- */
-         /*      Now create it.                                                  */
-         /* -------------------------------------------------------------------- */
-
-         poDstDS = poDriver.CreateDataSource( pszOutputName );
-         if( poDstDS == null )
-         {
-            System.err.print(pszFormat + " driver failed to create "+pszOutputName+"\n");
-            return;
-         }
-
-         if ( poDstDS.GetLayerCount() == 0 )
-         {
-            FieldDefn oLocation = new FieldDefn( pszTileIndexField, ogr.OFTString );
-
-            oLocation.SetWidth( 200 );
-
-            if( nFirstSourceDataset < args.length-2 && args[nFirstSourceDataset].charAt(0) == '-' )
-            {
-               nFirstSourceDataset++;
-            }
-
-            SpatialReference poSrcSpatialRef = null;
-
-            /* Fetches the SRS of the first layer and use it when creating the tileindex layer */
-            if (nFirstSourceDataset < args.length)
-            {
-               DataSource poDS = ogr.Open( args[nFirstSourceDataset],false );
-
-               if (poDS!=null)
-               {
-                  for(int iLayer = 0; iLayer < poDS.GetLayerCount(); iLayer++ )
-                  {
-                     boolean bRequested = bLayersWildcarded;
-                     Layer poLayer = poDS.GetLayer(iLayer);
-
-                     for(int iArg = 0; iArg < args.length && !bRequested; iArg++ )
-                     {
-                        if( args[iArg].equalsIgnoreCase("-lnum") 
-                              && Integer.parseInt(args[iArg+1]) == iLayer )
-                           bRequested = true;
-                        else if( args[iArg].equalsIgnoreCase("-lname") 
-                              && args[iArg+1].equalsIgnoreCase(poLayer.GetLayerDefn().GetName()) )
-                           bRequested = true;
-                     }
-
-                     if( !bRequested )
-                        continue;
-
-                     if ( poLayer.GetSpatialRef() != null)
-                        poSrcSpatialRef = poLayer.GetSpatialRef().Clone();
-                     break;
-                  }
-               }
-
-               poDS.delete();
-            }
-
-            poDstLayer = poDstDS.CreateLayer( "tileindex", poSrcSpatialRef );
-            poDstLayer.CreateField( oLocation, ogr.OFTString );
-
-            /* with the OGR Java bindings, avoid using the delete() methods,
-             * except on the datasource objects, where it is necessary to close properly the
-             * native file handles.
-             */  
-            // poSrcSpatialRef.delete();
-         }
-      }
-
-      /* -------------------------------------------------------------------- */
-      /*      Identify target layer and field.                                */
-      /* -------------------------------------------------------------------- */
-      int   iTileIndexField;
-
-      poDstLayer = poDstDS.GetLayer(0);
-      if( poDstLayer == null )
-      {
-         System.err.print("Can't find any layer in output tileindex!\n" );
-         return;
-      }
-
-      iTileIndexField = 
-         poDstLayer.GetLayerDefn().GetFieldIndex( pszTileIndexField );
-      if( iTileIndexField == -1 )
-      {
-         System.err.print("Can't find "+pszTileIndexField+" field in tile index dataset.\n");
-         return;
-      }
-
-      FeatureDefn poFeatureDefn = null;
-
-      /* Load in memory existing file names in SHP */
-      int nExistingLayers = 0;
-      String[] existingLayersTab = null;
-      SpatialReference alreadyExistingSpatialRef = null;
-      boolean alreadyExistingSpatialRefValid = false;
-      nExistingLayers = (int)poDstLayer.GetFeatureCount();
-      if (nExistingLayers > 0)
-      {
-         existingLayersTab = new String[nExistingLayers];
-         for(int i=0;i<nExistingLayers;i++)
-         {
-            Feature feature = poDstLayer.GetNextFeature();
-            existingLayersTab[i] = feature.GetFieldAsString( iTileIndexField);
-            if (i == 0)
-            {
-               DataSource       poDS;
-               String filename = existingLayersTab[i];
-               int j;
-               for(j=filename.length()-1;j>=0;j--)
-               {
-                  if (filename.charAt(j) == ',')
-                     break;
-               }
-               if (j >= 0)
-               {
-                  int iLayer = Integer.parseInt(filename.substring(j + 1));
-                  filename = filename.substring(0, j);
-                  poDS = ogr.Open(filename,false );
-                  if (poDS!=null)
-                  {
-                     Layer poLayer = poDS.GetLayer(iLayer);
-                     if (poLayer!=null)
-                     {
-                        alreadyExistingSpatialRefValid = true;
-                        alreadyExistingSpatialRef =
-                           (poLayer.GetSpatialRef()!=null) ? poLayer.GetSpatialRef().Clone() : null;
-
-                           if (poFeatureDefn == null) {
-                              poFeatureDefn = CloneFeatureDefn(poLayer.GetLayerDefn()); // XXX: no Clone supported in java binding!!
-                           }
-                     }
-                     poDS.delete();
-                  }
-               }
-            }
-         }
-      }
-
-      /* ignore check */
-      //if (write_absolute_path)
-      //{
-      //   current_path = CPLGetCurrentDir();
-      //   if (current_path == null)
-      //   {
-      //      fprintf( stderr, "This system does not support the CPLGetCurrentDir call. "
-      //      "The option -write_absolute_path will have no effect\n");
-      //      write_absolute_path = false;
-      //   }
-      //}
-      /* ==================================================================== */
-      /*      Process each input datasource in turn.                          */
-      /* ==================================================================== */
-
-      for(; nFirstSourceDataset < args.length; nFirstSourceDataset++ )
-      {
-         DataSource       poDS;
-
-         if( args[nFirstSourceDataset].charAt(0) == '-' )
-         {
-            nFirstSourceDataset++;
-            continue;
-         }
-
-         String fileNameToWrite;
-
-         //VSIStatBuf sStatBuf;
-         // FIXME: handle absolute path check 
-         //if (write_absolute_path && CPLIsFilenameRelative( args[nFirstSourceDataset] ) &&
-         //      VSIStat( args[nFirstSourceDataset], &sStatBuf ) == 0)
-         //{
-         //   fileNameToWrite = CPLStrdup(CPLProjectRelativeFilename(current_path,args[nFirstSourceDataset]));
-         //}
-         //else
-         //{
-         //   fileNameToWrite = args[nFirstSourceDataset];
-         //}
-         fileNameToWrite = args[nFirstSourceDataset];
-
-         poDS = ogr.Open( args[nFirstSourceDataset], false );
-
-         if( poDS == null )
-         {
-            System.err.print("Failed to open dataset "+args[nFirstSourceDataset]+", skipping.\n");
-            continue;
-         }
-
-         /* -------------------------------------------------------------------- */
-         /*      Check all layers, and see if they match requests.               */
-         /* -------------------------------------------------------------------- */
-         for(int iLayer = 0; iLayer < poDS.GetLayerCount(); iLayer++ )
-         {
-            boolean bRequested = bLayersWildcarded;
-            Layer poLayer = poDS.GetLayer(iLayer);
-
-            for(int iArg = 0; iArg < args.length && !bRequested; iArg++ )
-            {
-               if( args[iArg].equalsIgnoreCase("-lnum") 
-                     && Integer.parseInt(args[iArg+1]) == iLayer )
-                  bRequested = true;
-               else if( args[iArg].equalsIgnoreCase("-lname") 
-                     && args[iArg+1].equalsIgnoreCase(poLayer.GetLayerDefn().GetName()) )
-                  bRequested = true;
-            }
-
-            if( !bRequested )
-               continue;
-
-            /* Checks that the layer is not already in tileindex */
-            int i;
-            for(i=0;i<nExistingLayers;i++)
-            {
-               String szLocation = fileNameToWrite+","+iLayer;
-               if (szLocation.equalsIgnoreCase(existingLayersTab[i]))
-               {
-                  System.err.println("Layer "+iLayer+" of "+args[nFirstSourceDataset]+" is already in tileindex. Skipping it.\n");
-                  break;
-               }
-            }
-            if (i != nExistingLayers)
-            {
-               continue;
-            }
-
-            SpatialReference spatialRef = poLayer.GetSpatialRef();
-            if (alreadyExistingSpatialRefValid)
-            {
-               if ((spatialRef != null && alreadyExistingSpatialRef != null &&
-                     spatialRef.IsSame(alreadyExistingSpatialRef) == 0) ||
-                     ((spatialRef != null) != (alreadyExistingSpatialRef != null)))
-               {
-                  System.err.print("Warning : layer "+iLayer+" of "+args[nFirstSourceDataset]+" is not using the same projection system as "
-                        + "other files in the tileindex. This may cause problems when "
-                        + "using it in MapServer for example."+((skip_different_projection) ? " Skipping it" : "")+"\n");
-                  ;
-                  if (skip_different_projection)
-                  {
-                     continue;
-                  }
-               }
-            }
-            else
-            {
-               alreadyExistingSpatialRefValid = true;
-               alreadyExistingSpatialRef = (spatialRef!=null) ? spatialRef.Clone() : null;
-            }
-
-            /* -------------------------------------------------------------------- */
-            /*    Check if all layers in dataset have the same attributes  schema. */
-            /* -------------------------------------------------------------------- */
-            if( poFeatureDefn == null )
-            {
-               poFeatureDefn = CloneFeatureDefn(poLayer.GetLayerDefn()); // XXX: no Clone supported in java binding!!
-            }
-            else if ( !accept_different_schemas )
-            {
-               FeatureDefn poFeatureDefnCur = poLayer.GetLayerDefn();
-               assert(null != poFeatureDefnCur);
-
-               int fieldCount = poFeatureDefnCur.GetFieldCount();
-
-               if( fieldCount != poFeatureDefn.GetFieldCount())
-               {
-                  System.err.print("Number of attributes of layer "+poLayer.GetLayerDefn().GetName()+" of "+args[nFirstSourceDataset]+" does not match ... skipping it.\n");
-
-                  if (bFirstWarningForNonMatchingAttributes)
-                  {
-                     System.err.print("Note : you can override this behaviour with -accept_different_schemas option\n"
-                           + "but this may result in a tileindex incompatible with MapServer\n");
-                     bFirstWarningForNonMatchingAttributes = false;
-                  }
-                  continue;
-               }
-
-               boolean bSkip = false;
-               for( int fn = 0; fn < poFeatureDefnCur.GetFieldCount(); fn++ )
-               {
-                  FieldDefn poField = poFeatureDefn.GetFieldDefn(fn);
-                  FieldDefn poFieldCur = poFeatureDefnCur.GetFieldDefn(fn);
-
-                  /* XXX - Should those pointers be checked against null? */ 
-                  assert(null != poField);
-                  assert(null != poFieldCur);
-
-                  if( !poField.GetTypeName().equalsIgnoreCase(poFieldCur.GetTypeName()) 
-                        || poField.GetWidth() != poFieldCur.GetWidth() 
-                        || poField.GetPrecision() != poFieldCur.GetPrecision() 
-                        || !poField.GetNameRef().equalsIgnoreCase(poFieldCur.GetNameRef()) )
-                  {
-                     System.err.print("Schema of attributes of layer "+poLayer.GetLayerDefn().GetName()+" of "+args[nFirstSourceDataset]+" does not match ... skipping it.\n");
-
-                     if (bFirstWarningForNonMatchingAttributes)
-                     {
-                        System.err.print("Note : you can override this behaviour with -accept_different_schemas option\n"
-                              + "but this may result in a tileindex incompatible with MapServer\n");
-                        bFirstWarningForNonMatchingAttributes = false;
-                     }
-                     bSkip = true; 
-                     break;
-                  }
-               }
-
-               if (bSkip)
-                  continue;
-            }
-
-
-            /* -------------------------------------------------------------------- */
-            /*      Get layer extents, and create a corresponding polygon           */
-            /*      geometry.                                                       */
-            /* -------------------------------------------------------------------- */
-            double sExtents[] = poLayer.GetExtent(true);
-            Geometry/*Polygon*/ oRegion = new Geometry(ogr.wkbPolygon);
-            Geometry/*LinearRing*/ oRing = new Geometry(ogr.wkbLinearRing);
-             
-            if (sExtents == null) {
-               System.err.print("GetExtent() failed on layer "+poLayer.GetLayerDefn().GetName()+" of "+args[nFirstSourceDataset]+", skipping.\n");
-               continue;
-            }
-                                    
-            // XXX: sExtents [minX, maxX, minY, maxY]
-            //oRing.addPoint( sExtents.MinX, sExtents.MinY );
-            //oRing.addPoint( sExtents.MinX, sExtents.MaxY );
-            //oRing.addPoint( sExtents.MaxX, sExtents.MaxY );
-            //oRing.addPoint( sExtents.MaxX, sExtents.MinY );
-            //oRing.addPoint( sExtents.MinX, sExtents.MinY );
-            oRing.AddPoint_2D( sExtents[0], sExtents[2] );
-            oRing.AddPoint_2D( sExtents[0], sExtents[3] );
-            oRing.AddPoint_2D( sExtents[1], sExtents[3] );
-            oRing.AddPoint_2D( sExtents[1], sExtents[2] );
-            oRing.AddPoint_2D( sExtents[0], sExtents[2] );
-
-            oRegion.AddGeometry( oRing );
-
-            /* -------------------------------------------------------------------- */
-            /*      Add layer to tileindex.                                         */
-            /* -------------------------------------------------------------------- */
-            String        szLocation = fileNameToWrite+","+iLayer;
-            Feature  oTileFeat = new Feature( poDstLayer.GetLayerDefn() );
-
-            oTileFeat.SetGeometry( oRegion );
-            oTileFeat.SetField( iTileIndexField, szLocation );
-
-            if( poDstLayer.CreateFeature( oTileFeat ) != ogr.OGRERR_NONE )
-            {
-               System.err.print("Failed to create feature on tile index ... terminating." );
-               poDS.delete();
-               poDstDS.delete();
-               return;
-            }
-         }
-
-         /* -------------------------------------------------------------------- */
-         /*      Cleanup this data source.                                       */
-         /* -------------------------------------------------------------------- */
-         poDS.delete();
-      }
-
-      /* -------------------------------------------------------------------- */
-      /*      Close tile index and clear buffers.                             */
-      /* -------------------------------------------------------------------- */
-      poDstDS.delete();
-      //OGRFeatureDefn::DestroyFeatureDefn( poFeatureDefn );
-
-      //if (alreadyExistingSpatialRef != null)
-      //   alreadyExistingSpatialRef.delete();
-
-
-   }
-
-
-
-   /************************************************************************/
-   /*                               Usage()                                */
-   /************************************************************************/
-
-   static void Usage()
-
-   {
-      System.out.print( 
-            "Usage: ogrtindex [-lnum n]... [-lname name]... [-f output_format]\n" 
-            + "                 [-write_absolute_path] [-skip_different_projection]\n"
-            + "                 [-accept_different_schemas]\n"
-            + "                 output_dataset src_dataset...\n" );
-      System.out.print( "\n" );
-      System.out.print( 
-            "  -lnum n: Add layer number 'n' from each source file\n"
-            + "           in the tile index.\n" );
-      System.out.print( 
-            "  -lname name: Add the layer named 'name' from each source file\n"
-            + "               in the tile index.\n" );
-      System.out.print( 
-            "  -f output_format: Select an output format name.  The default\n"
-            + "                    is to create a shapefile.\n" );
-      System.out.print( 
-            "  -tileindex field_name: The name to use for the dataset name.\n"
-            + "                         Defaults to LOCATION.\n" );
-      System.out.print( "  -write_absolute_path: Filenames are written with absolute paths.\n" );
-      System.out.print( 
-            "  -skip_different_projection: Only layers with same projection ref \n"
-            + "        as layers already inserted in the tileindex will be inserted.\n" );
-      System.out.print( 
-            "  -accept_different_schemas: by default ogrtindex checks that all layers inserted\n"
-            + "                             into the index have the same attribute schemas. If you\n"
-            + "                             specify this option, this test will be disabled. Be aware that\n"
-            + "                             resulting index may be incompatible with MapServer!\n" );
-      System.out.print( "\n" );
-      System.out.print( 
-            "If no -lnum or -lname arguments are given it is assumed that\n"
-            + "all layers in source datasets should be added to the tile index\n"
-            + "as independent records.\n" );
-   }
-
-    /* Adhoc method to workaround the lack of a FeatureDefn.Clone() method */
-    static FeatureDefn CloneFeatureDefn(FeatureDefn poSrcFeatureDefn)
-    {
-        FeatureDefn poFeatureDefn = new FeatureDefn(poSrcFeatureDefn.GetName());
-        poFeatureDefn.SetGeomType(poSrcFeatureDefn.GetGeomType());
-        for(int fi = 0; fi < poSrcFeatureDefn.GetFieldCount(); fi++)
-            poFeatureDefn.AddFieldDefn(poSrcFeatureDefn.GetFieldDefn(fi));
-        return poFeatureDefn;
-    }
-}
+/******************************************************************************
+ * $Id: ogrtindex.java 35222 2016-08-28 06:06:11Z goatbar $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Program to generate a UMN MapServer compatible tile index for a
+ *           set of OGR data sources.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+import org.gdal.gdal.gdal;
+import org.gdal.ogr.DataSource;
+import org.gdal.ogr.Driver;
+import org.gdal.ogr.Feature;
+import org.gdal.ogr.FeatureDefn;
+import org.gdal.ogr.FieldDefn;
+import org.gdal.ogr.Geometry;
+import org.gdal.ogr.Layer;
+import org.gdal.ogr.ogr;
+import org.gdal.osr.SpatialReference;
+
+/* Note : this is the most direct port of ogrtindex.cpp possible */
+/* It could be made much more java'ish ! */
+
+public class ogrtindex {
+
+   public static void main(String[] args) {
+
+      boolean bLayersWildcarded = true;
+      int nFirstSourceDataset = -1;
+      String pszFormat = "ESRI Shapefile";
+      String pszTileIndexField = "LOCATION";
+      String pszOutputName = null;
+      boolean write_absolute_path = false;
+      boolean skip_different_projection = false;
+      String current_path = null;
+      boolean accept_different_schemas = false;
+      boolean bFirstWarningForNonMatchingAttributes = true;
+
+      ogr.DontUseExceptions();
+
+      /* -------------------------------------------------------------------- */
+      /*      Register format(s).                                             */
+      /* -------------------------------------------------------------------- */
+      // fixed: http://osgeo-org.1803224.n2.nabble.com/GDAL-Java-Binding-meomory-problem-under-intensive-method-calls-td7155011.html#a7157916
+      if( ogr.GetDriverCount() == 0 )
+         ogr.RegisterAll();
+
+      /* -------------------------------------------------------------------- */
+      /*      Processing command line arguments.                              */
+      /* -------------------------------------------------------------------- */
+      args = ogr.GeneralCmdLineProcessor( args );
+
+      if( args.length < 2 )
+      {
+         Usage();
+         return;
+      }
+
+      for( int iArg = 0; iArg < args.length; iArg++ )
+      {
+         if( args[iArg].equalsIgnoreCase("-f") && iArg < args.length-1 )
+         {
+            pszFormat = args[++iArg];
+         }
+         else if( args[iArg].equalsIgnoreCase("-write_absolute_path") )
+         {
+            write_absolute_path = true;
+         }
+         else if( args[iArg].equalsIgnoreCase("-skip_different_projection") )
+         {
+            skip_different_projection = true;
+         }
+         else if( args[iArg].equalsIgnoreCase("-accept_different_schemas") )
+         {
+            accept_different_schemas = true;
+         }
+         else if( args[iArg].equalsIgnoreCase("-tileindex") && iArg < args.length-1 )
+         {
+            pszTileIndexField = args[++iArg];
+         }
+         else if( args[iArg].equalsIgnoreCase("-lnum")
+               || args[iArg].equalsIgnoreCase("-lname") )
+         {
+            iArg++;
+            bLayersWildcarded = false;
+         }
+         else if( args[iArg].charAt(0) == '-' )
+            Usage();
+         else if( pszOutputName == null )
+            pszOutputName = args[iArg];
+         else if( nFirstSourceDataset == -1 )
+            nFirstSourceDataset = iArg;
+      }
+
+      if( pszOutputName == null || nFirstSourceDataset == -1 )
+         Usage();
+
+      /* -------------------------------------------------------------------- */
+      /*      Try to open as an existing dataset for update access.           */
+      /* -------------------------------------------------------------------- */
+      DataSource poDstDS;
+      Layer poDstLayer = null;
+
+      poDstDS = ogr.Open( pszOutputName, true );
+
+      /* -------------------------------------------------------------------- */
+      /*      If that failed, find the driver so we can create the tile index.*/
+      /* -------------------------------------------------------------------- */
+      if( poDstDS == null )
+      {
+         Driver poDriver = null;
+
+         for( int iDriver = 0; iDriver < ogr.GetDriverCount() && poDriver == null; iDriver++ )
+         {
+            poDriver = ogr.GetDriverByName(pszFormat);
+         }
+
+         if( poDriver == null )
+         {
+            System.err.print("Unable to find driver '"+pszFormat+"'.\n");
+            System.err.print("The following drivers are available:\n" );
+
+            for( int iDriver = 0; iDriver < ogr.GetDriverCount(); iDriver++ )
+            {
+               System.err.print("  . '"+ogr.GetDriver(iDriver).GetName()+"'\n");
+            }
+            return;
+         }
+
+         if( !poDriver.TestCapability( ogr.ODrCCreateDataSource ) )
+         {
+            System.err.print(pszFormat + " driver does not support data source creation.\n");
+            return;
+         }
+
+         /* -------------------------------------------------------------------- */
+         /*      Now create it.                                                  */
+         /* -------------------------------------------------------------------- */
+
+         poDstDS = poDriver.CreateDataSource( pszOutputName );
+         if( poDstDS == null )
+         {
+            System.err.print(pszFormat + " driver failed to create "+pszOutputName+"\n");
+            return;
+         }
+
+         if ( poDstDS.GetLayerCount() == 0 )
+         {
+            FieldDefn oLocation = new FieldDefn( pszTileIndexField, ogr.OFTString );
+
+            oLocation.SetWidth( 200 );
+
+            if( nFirstSourceDataset < args.length-2 && args[nFirstSourceDataset].charAt(0) == '-' )
+            {
+               nFirstSourceDataset++;
+            }
+
+            SpatialReference poSrcSpatialRef = null;
+
+            /* Fetches the SRS of the first layer and use it when creating the tileindex layer */
+            if (nFirstSourceDataset < args.length)
+            {
+               DataSource poDS = ogr.Open( args[nFirstSourceDataset],false );
+
+               if (poDS!=null)
+               {
+                  for(int iLayer = 0; iLayer < poDS.GetLayerCount(); iLayer++ )
+                  {
+                     boolean bRequested = bLayersWildcarded;
+                     Layer poLayer = poDS.GetLayer(iLayer);
+
+                     for(int iArg = 0; iArg < args.length && !bRequested; iArg++ )
+                     {
+                        if( args[iArg].equalsIgnoreCase("-lnum")
+                              && Integer.parseInt(args[iArg+1]) == iLayer )
+                           bRequested = true;
+                        else if( args[iArg].equalsIgnoreCase("-lname")
+                              && args[iArg+1].equalsIgnoreCase(poLayer.GetLayerDefn().GetName()) )
+                           bRequested = true;
+                     }
+
+                     if( !bRequested )
+                        continue;
+
+                     if ( poLayer.GetSpatialRef() != null)
+                        poSrcSpatialRef = poLayer.GetSpatialRef().Clone();
+                     break;
+                  }
+               }
+
+               poDS.delete();
+            }
+
+            poDstLayer = poDstDS.CreateLayer( "tileindex", poSrcSpatialRef );
+            poDstLayer.CreateField( oLocation, ogr.OFTString );
+
+            /* with the OGR Java bindings, avoid using the delete() methods,
+             * except on the datasource objects, where it is necessary to close properly the
+             * native file handles.
+             */
+            // poSrcSpatialRef.delete();
+         }
+      }
+
+      /* -------------------------------------------------------------------- */
+      /*      Identify target layer and field.                                */
+      /* -------------------------------------------------------------------- */
+      int   iTileIndexField;
+
+      poDstLayer = poDstDS.GetLayer(0);
+      if( poDstLayer == null )
+      {
+         System.err.print("Can't find any layer in output tileindex!\n" );
+         return;
+      }
+
+      iTileIndexField =
+         poDstLayer.GetLayerDefn().GetFieldIndex( pszTileIndexField );
+      if( iTileIndexField == -1 )
+      {
+         System.err.print("Can't find "+pszTileIndexField+" field in tile index dataset.\n");
+         return;
+      }
+
+      FeatureDefn poFeatureDefn = null;
+
+      /* Load in memory existing file names in SHP */
+      int nExistingLayers = 0;
+      String[] existingLayersTab = null;
+      SpatialReference alreadyExistingSpatialRef = null;
+      boolean alreadyExistingSpatialRefValid = false;
+      nExistingLayers = (int)poDstLayer.GetFeatureCount();
+      if (nExistingLayers > 0)
+      {
+         existingLayersTab = new String[nExistingLayers];
+         for(int i=0;i<nExistingLayers;i++)
+         {
+            Feature feature = poDstLayer.GetNextFeature();
+            existingLayersTab[i] = feature.GetFieldAsString( iTileIndexField);
+            if (i == 0)
+            {
+               DataSource       poDS;
+               String filename = existingLayersTab[i];
+               int j;
+               for(j=filename.length()-1;j>=0;j--)
+               {
+                  if (filename.charAt(j) == ',')
+                     break;
+               }
+               if (j >= 0)
+               {
+                  int iLayer = Integer.parseInt(filename.substring(j + 1));
+                  filename = filename.substring(0, j);
+                  poDS = ogr.Open(filename,false );
+                  if (poDS!=null)
+                  {
+                     Layer poLayer = poDS.GetLayer(iLayer);
+                     if (poLayer!=null)
+                     {
+                        alreadyExistingSpatialRefValid = true;
+                        alreadyExistingSpatialRef =
+                           (poLayer.GetSpatialRef()!=null) ? poLayer.GetSpatialRef().Clone() : null;
+
+                           if (poFeatureDefn == null) {
+                              poFeatureDefn = CloneFeatureDefn(poLayer.GetLayerDefn()); // XXX: no Clone supported in java binding!!
+                           }
+                     }
+                     poDS.delete();
+                  }
+               }
+            }
+         }
+      }
+
+      /* ignore check */
+      //if (write_absolute_path)
+      //{
+      //   current_path = CPLGetCurrentDir();
+      //   if (current_path == null)
+      //   {
+      //      fprintf( stderr, "This system does not support the CPLGetCurrentDir call. "
+      //      "The option -write_absolute_path will have no effect\n");
+      //      write_absolute_path = false;
+      //   }
+      //}
+      /* ==================================================================== */
+      /*      Process each input datasource in turn.                          */
+      /* ==================================================================== */
+
+      for(; nFirstSourceDataset < args.length; nFirstSourceDataset++ )
+      {
+         DataSource       poDS;
+
+         if( args[nFirstSourceDataset].charAt(0) == '-' )
+         {
+            nFirstSourceDataset++;
+            continue;
+         }
+
+         String fileNameToWrite;
+
+         //VSIStatBuf sStatBuf;
+         // FIXME: handle absolute path check
+         //if (write_absolute_path && CPLIsFilenameRelative( args[nFirstSourceDataset] ) &&
+         //      VSIStat( args[nFirstSourceDataset], &sStatBuf ) == 0)
+         //{
+         //   fileNameToWrite = CPLStrdup(CPLProjectRelativeFilename(current_path,args[nFirstSourceDataset]));
+         //}
+         //else
+         //{
+         //   fileNameToWrite = args[nFirstSourceDataset];
+         //}
+         fileNameToWrite = args[nFirstSourceDataset];
+
+         poDS = ogr.Open( args[nFirstSourceDataset], false );
+
+         if( poDS == null )
+         {
+            System.err.print("Failed to open dataset "+args[nFirstSourceDataset]+", skipping.\n");
+            continue;
+         }
+
+         /* -------------------------------------------------------------------- */
+         /*      Check all layers, and see if they match requests.               */
+         /* -------------------------------------------------------------------- */
+         for(int iLayer = 0; iLayer < poDS.GetLayerCount(); iLayer++ )
+         {
+            boolean bRequested = bLayersWildcarded;
+            Layer poLayer = poDS.GetLayer(iLayer);
+
+            for(int iArg = 0; iArg < args.length && !bRequested; iArg++ )
+            {
+               if( args[iArg].equalsIgnoreCase("-lnum")
+                     && Integer.parseInt(args[iArg+1]) == iLayer )
+                  bRequested = true;
+               else if( args[iArg].equalsIgnoreCase("-lname")
+                     && args[iArg+1].equalsIgnoreCase(poLayer.GetLayerDefn().GetName()) )
+                  bRequested = true;
+            }
+
+            if( !bRequested )
+               continue;
+
+            /* Checks that the layer is not already in tileindex */
+            int i;
+            for(i=0;i<nExistingLayers;i++)
+            {
+               String szLocation = fileNameToWrite+","+iLayer;
+               if (szLocation.equalsIgnoreCase(existingLayersTab[i]))
+               {
+                  System.err.println("Layer "+iLayer+" of "+args[nFirstSourceDataset]+" is already in tileindex. Skipping it.\n");
+                  break;
+               }
+            }
+            if (i != nExistingLayers)
+            {
+               continue;
+            }
+
+            SpatialReference spatialRef = poLayer.GetSpatialRef();
+            if (alreadyExistingSpatialRefValid)
+            {
+               if ((spatialRef != null && alreadyExistingSpatialRef != null &&
+                     spatialRef.IsSame(alreadyExistingSpatialRef) == 0) ||
+                     ((spatialRef != null) != (alreadyExistingSpatialRef != null)))
+               {
+                  System.err.print("Warning : layer "+iLayer+" of "+args[nFirstSourceDataset]+" is not using the same projection system as "
+                        + "other files in the tileindex. This may cause problems when "
+                        + "using it in MapServer for example."+((skip_different_projection) ? " Skipping it" : "")+"\n");
+                  ;
+                  if (skip_different_projection)
+                  {
+                     continue;
+                  }
+               }
+            }
+            else
+            {
+               alreadyExistingSpatialRefValid = true;
+               alreadyExistingSpatialRef = (spatialRef!=null) ? spatialRef.Clone() : null;
+            }
+
+            /* -------------------------------------------------------------------- */
+            /*    Check if all layers in dataset have the same attributes  schema. */
+            /* -------------------------------------------------------------------- */
+            if( poFeatureDefn == null )
+            {
+               poFeatureDefn = CloneFeatureDefn(poLayer.GetLayerDefn()); // XXX: no Clone supported in java binding!!
+            }
+            else if ( !accept_different_schemas )
+            {
+               FeatureDefn poFeatureDefnCur = poLayer.GetLayerDefn();
+               assert(null != poFeatureDefnCur);
+
+               int fieldCount = poFeatureDefnCur.GetFieldCount();
+
+               if( fieldCount != poFeatureDefn.GetFieldCount())
+               {
+                  System.err.print("Number of attributes of layer "+poLayer.GetLayerDefn().GetName()+" of "+args[nFirstSourceDataset]+" does not match ... skipping it.\n");
+
+                  if (bFirstWarningForNonMatchingAttributes)
+                  {
+                     System.err.print("Note : you can override this behaviour with -accept_different_schemas option\n"
+                           + "but this may result in a tileindex incompatible with MapServer\n");
+                     bFirstWarningForNonMatchingAttributes = false;
+                  }
+                  continue;
+               }
+
+               boolean bSkip = false;
+               for( int fn = 0; fn < poFeatureDefnCur.GetFieldCount(); fn++ )
+               {
+                  FieldDefn poField = poFeatureDefn.GetFieldDefn(fn);
+                  FieldDefn poFieldCur = poFeatureDefnCur.GetFieldDefn(fn);
+
+                  /* XXX - Should those pointers be checked against null? */
+                  assert(null != poField);
+                  assert(null != poFieldCur);
+
+                  if( !poField.GetTypeName().equalsIgnoreCase(poFieldCur.GetTypeName())
+                        || poField.GetWidth() != poFieldCur.GetWidth()
+                        || poField.GetPrecision() != poFieldCur.GetPrecision()
+                        || !poField.GetNameRef().equalsIgnoreCase(poFieldCur.GetNameRef()) )
+                  {
+                     System.err.print("Schema of attributes of layer "+poLayer.GetLayerDefn().GetName()+" of "+args[nFirstSourceDataset]+" does not match ... skipping it.\n");
+
+                     if (bFirstWarningForNonMatchingAttributes)
+                     {
+                        System.err.print("Note : you can override this behaviour with -accept_different_schemas option\n"
+                              + "but this may result in a tileindex incompatible with MapServer\n");
+                        bFirstWarningForNonMatchingAttributes = false;
+                     }
+                     bSkip = true;
+                     break;
+                  }
+               }
+
+               if (bSkip)
+                  continue;
+            }
+
+
+            /* -------------------------------------------------------------------- */
+            /*      Get layer extents, and create a corresponding polygon           */
+            /*      geometry.                                                       */
+            /* -------------------------------------------------------------------- */
+            double sExtents[] = poLayer.GetExtent(true);
+            Geometry/*Polygon*/ oRegion = new Geometry(ogr.wkbPolygon);
+            Geometry/*LinearRing*/ oRing = new Geometry(ogr.wkbLinearRing);
+
+            if (sExtents == null) {
+               System.err.print("GetExtent() failed on layer "+poLayer.GetLayerDefn().GetName()+" of "+args[nFirstSourceDataset]+", skipping.\n");
+               continue;
+            }
+
+            // XXX: sExtents [minX, maxX, minY, maxY]
+            //oRing.addPoint( sExtents.MinX, sExtents.MinY );
+            //oRing.addPoint( sExtents.MinX, sExtents.MaxY );
+            //oRing.addPoint( sExtents.MaxX, sExtents.MaxY );
+            //oRing.addPoint( sExtents.MaxX, sExtents.MinY );
+            //oRing.addPoint( sExtents.MinX, sExtents.MinY );
+            oRing.AddPoint_2D( sExtents[0], sExtents[2] );
+            oRing.AddPoint_2D( sExtents[0], sExtents[3] );
+            oRing.AddPoint_2D( sExtents[1], sExtents[3] );
+            oRing.AddPoint_2D( sExtents[1], sExtents[2] );
+            oRing.AddPoint_2D( sExtents[0], sExtents[2] );
+
+            oRegion.AddGeometry( oRing );
+
+            /* -------------------------------------------------------------------- */
+            /*      Add layer to tileindex.                                         */
+            /* -------------------------------------------------------------------- */
+            String        szLocation = fileNameToWrite+","+iLayer;
+            Feature  oTileFeat = new Feature( poDstLayer.GetLayerDefn() );
+
+            oTileFeat.SetGeometry( oRegion );
+            oTileFeat.SetField( iTileIndexField, szLocation );
+
+            if( poDstLayer.CreateFeature( oTileFeat ) != ogr.OGRERR_NONE )
+            {
+               System.err.print("Failed to create feature on tile index ... terminating." );
+               poDS.delete();
+               poDstDS.delete();
+               return;
+            }
+         }
+
+         /* -------------------------------------------------------------------- */
+         /*      Cleanup this data source.                                       */
+         /* -------------------------------------------------------------------- */
+         poDS.delete();
+      }
+
+      /* -------------------------------------------------------------------- */
+      /*      Close tile index and clear buffers.                             */
+      /* -------------------------------------------------------------------- */
+      poDstDS.delete();
+      //OGRFeatureDefn::DestroyFeatureDefn( poFeatureDefn );
+
+      //if (alreadyExistingSpatialRef != null)
+      //   alreadyExistingSpatialRef.delete();
+
+
+   }
+
+
+
+   /************************************************************************/
+   /*                               Usage()                                */
+   /************************************************************************/
+
+   static void Usage()
+
+   {
+      System.out.print(
+            "Usage: ogrtindex [-lnum n]... [-lname name]... [-f output_format]\n"
+            + "                 [-write_absolute_path] [-skip_different_projection]\n"
+            + "                 [-accept_different_schemas]\n"
+            + "                 output_dataset src_dataset...\n" );
+      System.out.print( "\n" );
+      System.out.print(
+            "  -lnum n: Add layer number 'n' from each source file\n"
+            + "           in the tile index.\n" );
+      System.out.print(
+            "  -lname name: Add the layer named 'name' from each source file\n"
+            + "               in the tile index.\n" );
+      System.out.print(
+            "  -f output_format: Select an output format name.  The default\n"
+            + "                    is to create a shapefile.\n" );
+      System.out.print(
+            "  -tileindex field_name: The name to use for the dataset name.\n"
+            + "                         Defaults to LOCATION.\n" );
+      System.out.print( "  -write_absolute_path: Filenames are written with absolute paths.\n" );
+      System.out.print(
+            "  -skip_different_projection: Only layers with same projection ref \n"
+            + "        as layers already inserted in the tileindex will be inserted.\n" );
+      System.out.print(
+            "  -accept_different_schemas: by default ogrtindex checks that all layers inserted\n"
+            + "                             into the index have the same attribute schemas. If you\n"
+            + "                             specify this option, this test will be disabled. Be aware that\n"
+            + "                             resulting index may be incompatible with MapServer!\n" );
+      System.out.print( "\n" );
+      System.out.print(
+            "If no -lnum or -lname arguments are given it is assumed that\n"
+            + "all layers in source datasets should be added to the tile index\n"
+            + "as independent records.\n" );
+   }
+
+    /* Adhoc method to workaround the lack of a FeatureDefn.Clone() method */
+    static FeatureDefn CloneFeatureDefn(FeatureDefn poSrcFeatureDefn)
+    {
+        FeatureDefn poFeatureDefn = new FeatureDefn(poSrcFeatureDefn.GetName());
+        poFeatureDefn.SetGeomType(poSrcFeatureDefn.GetGeomType());
+        for(int fi = 0; fi < poSrcFeatureDefn.GetFieldCount(); fi++)
+            poFeatureDefn.AddFieldDefn(poSrcFeatureDefn.GetFieldDefn(fi));
+        return poFeatureDefn;
+    }
+}
diff --git a/swig/java/javadoc.java b/swig/java/javadoc.java
index 9206d3e..601a2a2 100644
--- a/swig/java/javadoc.java
+++ b/swig/java/javadoc.java
@@ -1,14 +1,14 @@
 /* ***************************************************************************
-* $Id: javadoc.java 33909 2016-04-07 08:10:58Z rouault $
+* $Id: javadoc.java 35425 2016-09-13 18:07:32Z rouault $
 *
 * Project:  GDAL/OGR Java bindings
 * Purpose:  Documentation for the Java bindings
 * Author:   Even Rouault <even dot rouault at mines dash paris dot org>
-* 
+*
 *******************************************************************************
 * Copyright (c) 2009, Even Rouault <even dot rouault at mines dash paris dot org>
 * Copyright (c) 1999-2009, Frank Warmerdam
-* 
+*
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
@@ -18,7 +18,7 @@
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
-* 
+*
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -45,25 +45,25 @@ public class gdal
    /**
     * General utility option processing.
     *
-    * This function is intended to provide a variety of generic commandline 
+    * This function is intended to provide a variety of generic commandline
     * options for all GDAL commandline utilities.  It takes care of the following
     * commandline options:
     * <p><ul>
     *  <li>--version: report version of GDAL in use.
     *  <li>--license: report GDAL license info.
     *  <li>--formats: report all format drivers configured.
-    *  <li>--format [format]: report details of one format driver. 
-    *  <li>--optfile filename: expand an option file into the argument list. 
-    *  <li>--config key value: set system configuration option. 
+    *  <li>--format [format]: report details of one format driver.
+    *  <li>--optfile filename: expand an option file into the argument list.
+    *  <li>--config key value: set system configuration option.
     *  <li>--debug [on/off/value]: set debug level.
     *  <li>--mempreload dir: preload directory contents into /vsimem
-    *  <li>--help-general: report detailed help on general options. 
+    *  <li>--help-general: report detailed help on general options.
     * </ul><p>
     * The typical usage looks something like the following.  Note that the formats
     * should be registered so that the --formats and --format options will work properly.
     * <pre>
     *  public static void main( Strings[] args )
-    *  { 
+    *  {
     *    gdal.AllRegister();
     *
     *    args = gdal.GeneralCmdLineProcessor( args, 0 );
@@ -128,11 +128,11 @@ public class gdal:public static java.util.Vector GeneralCmdLineProcessor(java.ut
  * <p>
  * Categories are usually an identifier for the subsystem producing the
  * error.  For instance "GDAL" might be used for the GDAL core, and "TIFF"
- * for messages from the TIFF translator.  
+ * for messages from the TIFF translator.
  *
  * @param msg_class name of the debugging message category.
  * @param message message to display.
- */ 
+ */
 public class gdal:public static void Debug(String msg_class, String message)
 
 /**
@@ -159,7 +159,7 @@ public class gdal:public static int PushErrorHandler()
  * Set a global error handler.
  *
  * This installs a global error handler.
- * 
+ *
  * Note; if a local handler is already installed with PushErrorHandler(), the global error
  * handler will not be used until the last local handler is uninstalled with PopErrorHandler().
   *
@@ -173,7 +173,7 @@ public class gdal:public static int SetErrorHandler(String callbackName)
  * Set a quiet global error handler.
  *
  * This installs a quiet global error handler.
- * 
+ *
  * Note; if a local handler is already installed with PushErrorHandler(), the global error
  * handler will not be used until the last local handler is uninstalled with PopErrorHandler().
   *
@@ -191,7 +191,7 @@ public class gdal:public static int SetErrorHandler()
  * message is an informational warning, gdalconst.CE_Failure indicating that the
  * action failed, but that normal recover mechanisms will be used or
  * CE_Fatal meaning that a fatal error has occurred, and that Error()
- * should not return.  
+ * should not return.
  * <p>
  * The default behaviour of Error() is to report errors to stderr,
  * and to abort() after reporting a gdalconst.CE_Fatal error.  It is expected that
@@ -212,11 +212,11 @@ public class gdal:public static void Error(int msg_class, int err_code, String m
 /**
  * Pop error handler off stack.
  * <p>
- * Discards the current error handler on the error handler stack, and restores 
+ * Discards the current error handler on the error handler stack, and restores
  * the one in use before the last gdal.PushErrorHandler() call.  This method
  * has no effect if there are no error handlers on the current threads error
- * handler stack. 
- */ 
+ * handler stack.
+ */
 public class gdal:public static void PopErrorHandler()
 
 /**
@@ -281,33 +281,33 @@ public class gdal:public static int Unlink(String fileName)
  * reconstituted to it's original form.  The escaping will even preserve
  * zero bytes allowing preservation of raw binary data.
  * <ul>
- * <li>gdalconst.CPLES_BackslashQuotable(0): This scheme turns a binary string into 
+ * <li>gdalconst.CPLES_BackslashQuotable(0): This scheme turns a binary string into
  * a form suitable to be placed within double quotes as a string constant.
- * The backslash, quote, '\\0' and newline characters are all escaped in 
- * the usual C style. 
+ * The backslash, quote, '\\0' and newline characters are all escaped in
+ * the usual C style.
  *
  * <li>gdalconst.CPLES_XML(1): This scheme converts the '<', '<' and '&' characters into
  * their XML/HTML equivalent (>, < and &) making a string safe
- * to embed as CDATA within an XML element.  The '\\0' is not escaped and 
+ * to embed as CDATA within an XML element.  The '\\0' is not escaped and
  * should not be included in the input.
  *
- * <li>gdalconst.CPLES_URL(2): Everything except alphanumerics and the underscore are 
+ * <li>gdalconst.CPLES_URL(2): Everything except alphanumerics and the underscore are
  * converted to a percent followed by a two digit hex encoding of the character
  * (leading zero supplied if needed).  This is the mechanism used for encoding
  * values to be passed in URLs.
  *
- * <li>gdalconst.CPLES_SQL(3): All single quotes are replaced with two single quotes.  
+ * <li>gdalconst.CPLES_SQL(3): All single quotes are replaced with two single quotes.
  * Suitable for use when constructing literal values for SQL commands where
  * the literal will be enclosed in single quotes.
  *
- * <li>gdalconst.CPLES_CSV(4): If the values contains commas, double quotes, or newlines it 
+ * <li>gdalconst.CPLES_CSV(4): If the values contains commas, double quotes, or newlines it
  * placed in double quotes, and double quotes in the value are doubled.
  * Suitable for use when constructing field values for .csv files.  Note that
- * gdal.UnescapeString() currently does not support this format, only 
+ * gdal.UnescapeString() currently does not support this format, only
  * gdal.EscapeString().  See cpl_csv.cpp for csv parsing support.
  * </ul>
- * @param str the string to escape.  
- * @param scheme the encoding scheme to use.  
+ * @param str the string to escape.
+ * @param scheme the encoding scheme to use.
  *
  * @return an escaped string
  *
@@ -401,24 +401,24 @@ public class gdal:public static String GetConfigOption(String key)
 
 
 /**
- * Generate Geotransform from GCPs. 
+ * Generate Geotransform from GCPs.
  * <p>
- * Given a set of GCPs perform first order fit as a geotransform. 
+ * Given a set of GCPs perform first order fit as a geotransform.
  * <p>
- * Due to imprecision in the calculations the fit algorithm will often 
+ * Due to imprecision in the calculations the fit algorithm will often
  * return non-zero rotational coefficients even if given perfectly non-rotated
  * inputs.  A special case has been implemented for corner corner coordinates
  * given in TL, TR, BR, BL order.  So when using this to get a geotransform
- * from 4 corner coordinates, pass them in this order. 
- * 
- * @param gcpArray the array of GCP. 
- * @param outGeoTransform the six double array in which the affine 
- * geotransformation will be returned. 
- * @param bApproxOK If 0 the function will fail if the geotransform is not 
- * essentially an exact fit (within 0.25 pixel) for all GCPs. 
- * 
+ * from 4 corner coordinates, pass them in this order.
+ *
+ * @param gcpArray the array of GCP.
+ * @param outGeoTransform the six double array in which the affine
+ * geotransformation will be returned.
+ * @param bApproxOK If 0 the function will fail if the geotransform is not
+ * essentially an exact fit (within 0.25 pixel) for all GCPs.
+ *
  * @return 1 on success or 0 if there aren't enough points to prepare a
- * geotransform, the pointers are ill-determined or if bApproxOK is 0 
+ * geotransform, the pointers are ill-determined or if bApproxOK is 0
  * and the fit is poor.
  *
  * @since Java bindings 1.7.0
@@ -426,7 +426,7 @@ public class gdal:public static String GetConfigOption(String key)
 public class gdal:public static int GCPsToGeoTransform(GCP[] gcpArray, double[] outGeoTransform, int bApproxOK)
 
 /**
- * Generate Geotransform from GCPs. 
+ * Generate Geotransform from GCPs.
  * <p>
  * Same as below with bApproxOK == 0
  *
@@ -443,7 +443,7 @@ public class gdal:public static int GCPsToGeoTransform(GCP[] gcpArray, double[]
  * This function implements a median cut algorithm to compute an "optimal"
  * pseudocolor table for representing an input RGB image.  This PCT could
  * then be used with GDALDitherRGB2PCT() to convert a 24bit RGB image into
- * an eightbit pseudo-colored image. 
+ * an eightbit pseudo-colored image.
  * <p>
  * This code was based on the tiffmedian.c code from libtiff (www.libtiff.org)
  * which was based on a paper by Paul Heckbert:
@@ -456,16 +456,16 @@ public class gdal:public static int GCPsToGeoTransform(GCP[] gcpArray, double[]
  * The red, green and blue input bands do not necessarily need to come
  * from the same file, but they must be the same width and height.  They will
  * be clipped to 8bit during reading, so non-eight bit bands are generally
- * inappropriate. 
+ * inappropriate.
  *
- * @param red Red input band. 
- * @param green Green input band. 
- * @param blue Blue input band. 
+ * @param red Red input band.
+ * @param green Green input band.
+ * @param blue Blue input band.
  * @param num_colors the desired number of colors to be returned (2-256).
  * @param colors the color table will be returned in this color table object.
  * @param callback for reporting algorithm progress. May be null
  *
- * @return returns gdalconst.CE_None on success or gdalconst.CE_Failure if an error occurs. 
+ * @return returns gdalconst.CE_None on success or gdalconst.CE_Failure if an error occurs.
  *
  * @since Java bindings 1.7.0
  */
@@ -487,26 +487,26 @@ public class gdal:public static int ComputeMedianCutPCT(Band red, Band green, Ba
 /**
  * 24bit to 8bit conversion with dithering.
  * <p>
- * This functions utilizes Floyd-Steinberg dithering in the process of 
+ * This functions utilizes Floyd-Steinberg dithering in the process of
  * converting a 24bit RGB image into a pseudocolored 8bit image using a
- * provided color table.  
+ * provided color table.
  * <p>
  * The red, green and blue input bands do not necessarily need to come
  * from the same file, but they must be the same width and height.  They will
  * be clipped to 8bit during reading, so non-eight bit bands are generally
  * inappropriate.  Likewise the hTarget band will be written with 8bit values
- * and must match the width and height of the source bands. 
+ * and must match the width and height of the source bands.
  * <p>
  * The color table cannot have more than 256 entries.
  *
- * @param red Red input band. 
- * @param green Green input band. 
- * @param blue Blue input band. 
- * @param target Output band. 
- * @param colors the color table to use with the output band. 
+ * @param red Red input band.
+ * @param green Green input band.
+ * @param blue Blue input band.
+ * @param target Output band.
+ * @param colors the color table to use with the output band.
  * @param callback for reporting algorithm progress. May be null
  *
- * @return gdalconst.CE_None on success or gdalconst.CE_Failure if an error occurs. 
+ * @return gdalconst.CE_None on success or gdalconst.CE_Failure if an error occurs.
  *
  * @since Java bindings 1.7.0
  */
@@ -528,15 +528,15 @@ public class gdal:public static int DitherRGB2PCT(Band red, Band green, Band blu
  * This is a convenience function utilizing the GDALWarpOperation class to
  * reproject an image from a source to a destination.  In particular, this
  * function takes care of establishing the transformation function to
- * implement the reprojection, and will default a variety of other 
- * warp options. 
+ * implement the reprojection, and will default a variety of other
+ * warp options.
  * <p>
  * By default all bands are transferred, with no masking or nodata values
- * in effect.  No metadata, projection info, or color tables are transferred 
- * to the output file. 
+ * in effect.  No metadata, projection info, or color tables are transferred
+ * to the output file.
  *
- * @param src_ds the source image file. 
- * @param dst_ds the destination image file. 
+ * @param src_ds the source image file.
+ * @param dst_ds the destination image file.
  * @param src_wkt the source projection.  If null the source projection
  * is read from from src_ds.
  * @param dst_wkt the destination projection.  If null the destination
@@ -560,7 +560,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
  * Reproject image.
  * <p>
  * Same as below with callback == null.
- * 
+ *
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
  *
  * @return gdalconst.CE_None on success or gdalconst.CE_Failure if something goes wrong.
@@ -573,7 +573,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
  * Reproject image.
  * <p>
  * Same as below with maxError == 0.0 and callback == null.
- * 
+ *
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
  *
  * @since Java bindings 1.7.0
@@ -584,7 +584,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
  * Reproject image.
  * <p>
  * Same as below with warpMemoryLimit == 0.0, maxError == 0.0 and callback == null.
- * 
+ *
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
  *
  * @since Java bindings 1.7.0
@@ -595,7 +595,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
  * Reproject image.
  * <p>
  * Same as below with resampleAlg == gdalconst.GRA_NearestNeighbour, warpMemoryLimit == 0.0, maxError == 0.0 and callback == null.
- * 
+ *
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
  *
  * @since Java bindings 1.7.0
@@ -606,7 +606,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
  * Reproject image.
  * <p>
  * Same as below with dst_wkt == null, resampleAlg == gdalconst.GRA_NearestNeighbour, warpMemoryLimit == 0.0, maxError == 0.0 and callback == null.
- * 
+ *
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
  *
  * @since Java bindings 1.7.0
@@ -617,7 +617,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
  * Reproject image.
  * <p>
  * Same as below with src_wkt == null, dst_wkt == null, resampleAlg == gdalconst.GRA_NearestNeighbour, warpMemoryLimit == 0.0, maxError == 0.0 and callback == null.
- * 
+ *
  * @see #ReprojectImage(Dataset src_ds, Dataset dst_ds, String src_wkt, String dst_wkt, int resampleAlg, double warpMemoryLimit, double maxError, ProgressCallback callback)
  *
  * @since Java bindings 1.7.0
@@ -642,7 +642,7 @@ public class gdal:public static int ReprojectImage(Dataset src_ds, Dataset dst_d
  * integers.</dd>
  * <dt>DISTUNITS=[PIXEL]/GEO</dt> <dd>
  * Indicates whether distances will be computed in pixel units or
- * in georeferenced units.  The default is pixel units.  This also 
+ * in georeferenced units.  The default is pixel units.  This also
  * determines the interpretation of MAXDIST.</dd>
  * <dt>MAXDIST=n</dt> <dd>
  * The maximum distance to search.  Proximity distances greater than
@@ -704,12 +704,12 @@ public class gdal:public static int ComputeProximity(Band srcBand, Band proximit
  * The output raster may be of any GDAL supported datatype, though currently
  * internally the burning is done either as gdal.GDT_Byte or gdal.GDT_Float32.  This
  * may be improved in the future.  An explicit list of burn values for
- * each layer for each band must be passed in. 
+ * each layer for each band must be passed in.
  *
  * @param dataset output data, must be opened in update mode.
- * @param bandNumbers the list of bands to be updated. 
- * @param layer the layer to burn in. 
- * @param burn_values the array of values to burn into the raster.  
+ * @param bandNumbers the list of bands to be updated.
+ * @param layer the layer to burn in.
+ * @param burn_values the array of values to burn into the raster.
  * There should be as many values as in bandNumbers. If null, 255 will be used
  * @param options a vector of strings for special options controlling rasterization:
  * <dl>
@@ -776,42 +776,42 @@ public class gdal:public static int RasterizeLayer(Dataset dataset, int[] bandNu
  * can be provided to determine which pixels are eligible for processing.
  * <p>
  * Note that currently the source pixel band values are read into a
- * signed 32bit integer buffer (Int32), so floating point or complex 
- * bands will be implicitly truncated before processing.  
+ * signed 32bit integer buffer (Int32), so floating point or complex
+ * bands will be implicitly truncated before processing.
  * <p>
- * Polygon features will be created on the output layer, with polygon 
+ * Polygon features will be created on the output layer, with polygon
  * geometries representing the polygons.  The polygon geometries will be
  * in the georeferenced coordinate system of the image (based on the
  * geotransform of the source dataset).  It is acceptable for the output
  * layer to already have features.  Note that gdal.Polygonize() does not
  * set the coordinate system on the output layer.  Application code should
- * do this when the layer is created, presumably matching the raster 
- * coordinate system. 
+ * do this when the layer is created, presumably matching the raster
+ * coordinate system.
  * <p>
  * The algorithm used attempts to minimize memory use so that very large
- * rasters can be processed.  However, if the raster has many polygons 
- * or very large/complex polygons, the memory use for holding polygon 
- * enumerations and active polygon geometries may grow to be quite large. 
+ * rasters can be processed.  However, if the raster has many polygons
+ * or very large/complex polygons, the memory use for holding polygon
+ * enumerations and active polygon geometries may grow to be quite large.
  * <p>
  * The algorithm will generally produce very dense polygon geometries, with
  * edges that follow exactly on pixel boundaries for all non-interior pixels.
  * For non-thematic raster data (such as satellite images) the result will
  * essentially be one small polygon per pixel, and memory and output layer
- * sizes will be substantial.  The algorithm is primarily intended for 
- * relatively simple thematic imagery, masks, and classification results. 
- * 
+ * sizes will be substantial.  The algorithm is primarily intended for
+ * relatively simple thematic imagery, masks, and classification results.
+ *
  * @param srcBand the source raster band to be processed.
- * @param maskBand an optional mask band (or null).  All pixels in the mask band with a 
- * value other than zero will be considered suitable for collection as 
- * polygons.  
+ * @param maskBand an optional mask band (or null).  All pixels in the mask band with a
+ * value other than zero will be considered suitable for collection as
+ * polygons.
  * @param outLayer the vector feature layer to which the polygons should
- * be written. 
+ * be written.
  * @param iPixValField the attribute field index indicating the feature
  * attribute into which the pixel value of the polygon should be written.
  * @param options a name/value list of additional options (none currently
- * supported. just pass null). 
+ * supported. just pass null).
  * @param callback for reporting progress or null
- * 
+ *
  * @return gdalconst.CE_None on success or gdalconst.CE_Failure on a failure.
  *
  * @since Java bindings 1.7.0
@@ -843,31 +843,31 @@ public class gdal:public static int Polygonize(Band srcBand, Band maskBand, org.
 /**
  * Fill selected raster regions by interpolation from the edges.
  * <p>
- * This algorithm will interpolate values for all designated 
+ * This algorithm will interpolate values for all designated
  * nodata pixels (marked by zeros in maskBand).  For each pixel
  * a four direction conic search is done to find values to interpolate
  * from (using inverse distance weighting).  Once all values are
  * interpolated, zero or more smoothing iterations (3x3 average
- * filters on interpolated pixels) are applied to smooth out 
- * artifacts. 
+ * filters on interpolated pixels) are applied to smooth out
+ * artifacts.
  * <p>
  * This algorithm is generally suitable for interpolating missing
  * regions of fairly continuously varying rasters (such as elevation
  * models for instance).  It is also suitable for filling small holes
  * and cracks in more irregularly varying images (like airphotos).  It
- * is generally not so great for interpolating a raster from sparse 
+ * is generally not so great for interpolating a raster from sparse
  * point data - see the algorithms defined in gdal_grid.h for that case.
  *
- * @param targetBand the raster band to be modified in place. 
+ * @param targetBand the raster band to be modified in place.
  * @param maskBand a mask band indicating pixels to be interpolated (zero valued
- * @param maxSearchDist the maximum number of pixels to search in all 
+ * @param maxSearchDist the maximum number of pixels to search in all
  * directions to find values to interpolate from.
- * @param smoothingIterations the number of 3x3 smoothing filter passes to 
+ * @param smoothingIterations the number of 3x3 smoothing filter passes to
  * run (0 or more).
- * @param options additional name=value options in a string list (none 
+ * @param options additional name=value options in a string list (none
  * supported at this time - just pass null).
  * @param callback for reporting progress or null
- * 
+ *
  * @return gdalconst.CE_None on success or gdalconst.CE_Failure on a failure.
  *
  * @since Java bindings 1.7.0
@@ -896,47 +896,47 @@ public class gdal:public static int FillNodata(Band targetBand, Band maskBand, d
  */
 public class gdal:public static int FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations)
 
-/** 
- * Removes small raster polygons. 
+/**
+ * Removes small raster polygons.
  * <p>
  * The function removes raster polygons smaller than a provided
- * threshold size (in pixels) and replaces replaces them with the pixel value 
- * of the largest neighbour polygon.  
+ * threshold size (in pixels) and replaces replaces them with the pixel value
+ * of the largest neighbour polygon.
  * <p>
  * Polygon are determined (per GDALRasterPolygonEnumerator) as regions of
  * the raster where the pixels all have the same value, and that are contiguous
- * (connected).  
+ * (connected).
  * <p>
  * Pixels determined to be "nodata" per maskBand will not be treated as part
  * of a polygon regardless of their pixel values.  Nodata areas will never be
- * changed nor affect polygon sizes. 
+ * changed nor affect polygon sizes.
  * <p>
  * Polygons smaller than the threshold with no neighbours that are as large
  * as the threshold will not be altered.  Polygons surrounded by nodata areas
- * will therefore not be altered.  
+ * will therefore not be altered.
  * <p>
  * The algorithm makes three passes over the input file to enumerate the
- * polygons and collect limited information about them.  Memory use is 
+ * polygons and collect limited information about them.  Memory use is
  * proportional to the number of polygons (roughly 24 bytes per polygon), but
  * is not directly related to the size of the raster.  So very large raster
  * files can be processed effectively if there aren't too many polygons.  But
- * extremely noisy rasters with many one pixel polygons will end up being 
+ * extremely noisy rasters with many one pixel polygons will end up being
  * expensive (in memory) to process.
- * 
+ *
  * @param srcBand the source raster band to be processed.
- * @param maskBand an optional mask band.  All pixels in the mask band with a 
+ * @param maskBand an optional mask band.  All pixels in the mask band with a
  * value other than zero will be considered suitable for inclusion in polygons.
  * @param dstBand the output raster band.  It may be the same as srcBand
- * to update the source in place. 
+ * to update the source in place.
  * @param threshold raster polygons with sizes smaller than this will
  * be merged into their largest neighbour.
  * @param connectedness either 4 indicating that diagonal pixels are not
  * considered directly adjacent for polygon membership purposes or 8
- * indicating they are. 
+ * indicating they are.
  * @param options algorithm options in name=value list form.  None currently
  * supported. just pass null
  * @param callback for reporting progress or null
- * 
+ *
  * @return gdalconst.CE_None on success or gdalconst.CE_Failure on a failure.
  *
  * @since Java bindings 1.7.0
@@ -944,7 +944,7 @@ public class gdal:public static int FillNodata(Band targetBand, Band maskBand, d
 public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness, java.util.Vector options, ProgressCallback callback)
 
 /**
- * Removes small raster polygons. 
+ * Removes small raster polygons.
  * <p>
  * Same as below with callback == null
  *
@@ -955,7 +955,7 @@ public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Ban
 public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness, java.util.Vector options)
 
 /**
- * Removes small raster polygons. 
+ * Removes small raster polygons.
  * <p>
  * Same as below with options == null and callback == null
  *
@@ -966,7 +966,7 @@ public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Ban
 public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness)
 
 /**
- * Removes small raster polygons. 
+ * Removes small raster polygons.
  * <p>
  * Same as below with connectedness == 4, options == null and callback == null
  *
@@ -985,14 +985,14 @@ public class gdal:public static int SieveFilter(Band srcBand, Band maskBand, Ban
  * can also be used to generate downsampled images in one file from another
  * outside the overview architecture.
  * <p>
- * The output bands need to exist in advance. 
+ * The output bands need to exist in advance.
  * <p>
- * The full set of resampling algorithms is documented in 
+ * The full set of resampling algorithms is documented in
  * Dataset.BuildOverviews().
  *
- * @param srcBand the source (base level) band. 
+ * @param srcBand the source (base level) band.
  * @param overviewBands the list of downsampled bands to be generated.
- * @param resampling Resampling algorithm (eg. "AVERAGE"). 
+ * @param resampling Resampling algorithm (eg. "AVERAGE").
  * @param callback for reporting progress or null
  *
  * @return gdalconst.CE_None on success or gdalconst.CE_Failure on a failure.
@@ -1062,37 +1062,37 @@ public class gdal:public static int RegenerateOverview(Band srcBand, Band overvi
 /**
  * Create virtual warped dataset automatically.
  * <p>
- * This function will create a warped virtual file representing the 
+ * This function will create a warped virtual file representing the
  * input image warped into the target coordinate system.  A GenImgProj
  * transformation is created to accomplish any required GCP/Geotransform
  * warp and reprojection to the target coordinate system.  The output virtual
  * dataset will be "northup" in the target coordinate system.   The
  * GDALSuggestedWarpOutput() function is used to determine the bounds and
- * resolution of the output virtual file which should be large enough to 
- * include all the input image 
+ * resolution of the output virtual file which should be large enough to
+ * include all the input image
  * <p>
- * Note that the constructed Dataset object will acquire one or more references 
- * to the passed in src_ds.  Reference counting semantics on the source 
- * dataset should be honoured.  That is, don't just GDALClose() it unless it 
- * was opened with GDALOpenShared(). 
+ * Note that the constructed Dataset object will acquire one or more references
+ * to the passed in src_ds.  Reference counting semantics on the source
+ * dataset should be honoured.  That is, don't just GDALClose() it unless it
+ * was opened with GDALOpenShared().
  * <p>
  * The returned dataset will have no associated filename for itself.  If you
  * want to write the virtual dataset description to a file, use the
  * SetDescription() method on the dataset
- * to assign a filename before it is closed.  
+ * to assign a filename before it is closed.
  *
- * @param src_ds The source dataset. 
+ * @param src_ds The source dataset.
  *
- * @param src_wkt The coordinate system of the source image.  If null, it 
- * will be read from the source image. 
+ * @param src_wkt The coordinate system of the source image.  If null, it
+ * will be read from the source image.
  *
- * @param dst_wkt The coordinate system to convert to.  If null no change 
- * of coordinate system will take place.  
+ * @param dst_wkt The coordinate system to convert to.  If null no change
+ * of coordinate system will take place.
  *
- * @param eResampleAlg One of gdalconst.GRA_NearestNeighbour, gdalconst.GRA_Bilinear, gdalconst.GRA_Cubic or 
- * gdalconst.RA_CubicSpline.  Controls the sampling method used. 
+ * @param eResampleAlg One of gdalconst.GRA_NearestNeighbour, gdalconst.GRA_Bilinear, gdalconst.GRA_Cubic or
+ * gdalconst.RA_CubicSpline.  Controls the sampling method used.
  *
- * @param maxError Maximum error measured in input pixels that is allowed in 
+ * @param maxError Maximum error measured in input pixels that is allowed in
  * approximating the transformation (0.0 for exact calculations).
  *
  * @return null on failure, or a new virtual dataset handle on success.
@@ -1150,10 +1150,10 @@ public class gdal:public static Dataset AutoCreateWarpedVRT(Dataset src_ds)
  * <ul>
  * <li> "VERSION_NUM": Returns GDAL_VERSION_NUM formatted as a string.  i.e. "1170"
  *      Note: starting with GDAL 1.10, this string will be longer than 4 characters.
- * <li> "RELEASE_DATE": Returns GDAL_RELEASE_DATE formatted as a string.  
+ * <li> "RELEASE_DATE": Returns GDAL_RELEASE_DATE formatted as a string.
  * i.e. "20020416".
  * <li> "RELEASE_NAME": Returns the GDAL_RELEASE_NAME. i.e. "1.1.7"
- * <li> "--version": Returns one line version message suitable for use in 
+ * <li> "--version": Returns one line version message suitable for use in
  * response to --version requests.  i.e. "GDAL 1.1.7, released 2002/04/16"
  * <li> "LICENCE": Returns the content of the LICENSE.TXT file from the GDAL_DATA directory.
  * </ul>
@@ -1206,9 +1206,9 @@ public class gdal:public static void AllRegister()
  * Get maximum cache memory.
  * <p>
  * Gets the maximum amount of memory available to the GDALRasterBlock
- * caching system for caching GDAL read/write imagery. 
+ * caching system for caching GDAL read/write imagery.
  *
- * @return maximum in bytes. 
+ * @return maximum in bytes.
  */
 public class gdal:public static int GetCacheMax()
 
@@ -1224,8 +1224,8 @@ public class gdal:public static void SetCacheMax(int newSize)
 
 /**
  * Get cache memory used.
- * 
- * @return the number of bytes of memory currently in use by the 
+ *
+ * @return the number of bytes of memory currently in use by the
  * GDALRasterBlock memory caching.
  */
 public class gdal:public static int GetCacheUsed()
@@ -1236,17 +1236,17 @@ public class gdal:public static int GetCacheUsed()
  * <p>
  * Returns the size of a GDT_* type <b>in bits</b>, not bytes!
  *
- * @param eDataType type, such as gdalconst.GDT_Byte. 
+ * @param eDataType type, such as gdalconst.GDT_Byte.
  * @return the number of bits or zero if it is not recognised.
  */
 public class gdal:public static int GetDataTypeSize(int eDataType)
 
 /**
- * Is data type complex? 
+ * Is data type complex?
  *
- * @return 1 if the passed type is complex (one of gdalconst.GDT_CInt16, GDT_CInt32, 
+ * @return 1 if the passed type is complex (one of gdalconst.GDT_CInt16, GDT_CInt32,
  * GDT_CFloat32 or GDT_CFloat64), that is it consists of a real and imaginary
- * component. 
+ * component.
  */
 public class gdal:public static int DataTypeIsComplex(int eDataType)
 
@@ -1256,7 +1256,7 @@ public class gdal:public static int DataTypeIsComplex(int eDataType)
  * Returns a symbolic name for the data type.  This is essentially the
  * the enumerated item name with the GDT_ prefix removed.  So gdalconst.GDT_Byte returns
  * "Byte". These strings are useful for reporting
- * datatypes in debug statements, errors and other user output. 
+ * datatypes in debug statements, errors and other user output.
  *
  * @param eDataType type to get name of.
  * @return string corresponding to type.
@@ -1270,7 +1270,7 @@ public class gdal:public static String GetDataTypeName(int eDataType)
  * function is opposite to the gdal.GetDataTypeName().
  *
  * @param dataTypeName string containing the symbolic name of the type.
- * 
+ *
  * @return GDAL data type.
  */
 public class gdal:public static int GetDataTypeByName(String dataTypeName)
@@ -1332,7 +1332,7 @@ public class gdal:public static Driver GetDriver(int iDriver)
  * Open a raster file as a Dataset object.
  * <p>
  * This function will try to open the passed file, or virtual dataset
- * name by invoking the Open method of each registered Driver in turn. 
+ * name by invoking the Open method of each registered Driver in turn.
  * The first successful open will result in a returned dataset.  If all
  * drivers fail then null is returned.
  * <p>
@@ -1404,7 +1404,7 @@ public class gdal:public static Dataset OpenShared(String name)
  * Identify the driver that can open a raster file.
  * <p>
  * This function will try to identify the driver that can open the passed file
- * name by invoking the Identify method of each registered Driver in turn. 
+ * name by invoking the Identify method of each registered Driver in turn.
  * The first driver that successful identifies the file name will be returned.
  * If all drivers fail then null is returned.
  * <p>
@@ -1442,20 +1442,20 @@ public class gdal:public static Driver IdentifyDriver(String name)
 /**
  * Parse an XML string into tree form.
  * <p>
- * The passed document is parsed into a  XMLNode tree representation. 
+ * The passed document is parsed into a  XMLNode tree representation.
  * If the document is not well formed XML then null is returned, and errors
  * are reported via CPLError().  No validation beyond wellformedness is
  * done.
  * <p>
- * If the document has more than one "root level" element then those after the 
+ * If the document has more than one "root level" element then those after the
  * first will be attached to the first as siblings (via the psNext pointers)
  * even though there is no common parent.  A document with no XML structure
- * (no angle brackets for instance) would be considered well formed, and 
- * returned as a single CXT_Text node.  
- * 
- * @param xmlString the document to parse. 
+ * (no angle brackets for instance) would be considered well formed, and
+ * returned as a single CXT_Text node.
+ *
+ * @param xmlString the document to parse.
  *
- * @return parsed tree or null on error. 
+ * @return parsed tree or null on error.
  *
  * @since Java bindings 1.7.0
  */
@@ -1470,7 +1470,7 @@ public class gdal:public static XMLNode ParseXMLString(String xmlString)
  *
  * @param xmlnode the root of the tree to serialize
  *
- * @return the document on success or null on failure. 
+ * @return the document on success or null on failure.
  *
  * @since Java bindings 1.7.0
  */
@@ -1490,7 +1490,7 @@ public class gdal:public static String SerializeXMLTree(XMLNode xmlnode)
  * @param dfPixel 	Input pixel position
  * @param dfLine 	Input line position.
  * @param pdfGeoX 	allocated array of 1 double where geo_x (easting/longitude) location is placed.
- * @param pdfGeoY 	allocated array of 1 double where geo_y (northing/latitude) location is placed. 
+ * @param pdfGeoY 	allocated array of 1 double where geo_y (northing/latitude) location is placed.
  *
  * @since Java bindings 1.7.0
  */
@@ -1660,14 +1660,14 @@ public class ColorTable:public void CreateColorRamp(int nStartIndex, java.awt.Co
  *
  * @param entry entry offset from zero to GetCount()-1.
  *
- * @return  color entry, or null if index is out of range. 
+ * @return  color entry, or null if index is out of range.
  */
-public class ColorTable:public java.awt.Color GetColorEntry(int entry) 
+public class ColorTable:public java.awt.Color GetColorEntry(int entry)
 
 /**
  * Get number of color entries in table.
  *
- * @return the number of color entries. 
+ * @return the number of color entries.
  */
 public class ColorTable:public int GetCount()
 
@@ -1676,7 +1676,7 @@ public class ColorTable:public int GetCount()
  * <p>
  * The returned value is used to interpret the values in the GDALColorEntry.
  *
- * @return palette interpretation enumeration value, usually gdalconst.GPI_RGB. 
+ * @return palette interpretation enumeration value, usually gdalconst.GPI_RGB.
  */
 public class ColorTable:public int GetPaletteInterpretation()
 
@@ -1718,16 +1718,16 @@ public class Dataset
  * supports this action.  Except VRT and MEM drivers, most formats do not.
  * <p>
  * Note that the new Band object is not returned.  It may be fetched
- * after successful completion of the method by calling 
+ * after successful completion of the method by calling
  * ds.GetRasterBand(ds.GetRasterCount()) as the newest
  * band will always be the last band.
  *
- * @param datatype the data type of the pixels in the new band. 
+ * @param datatype the data type of the pixels in the new band.
  *
  * @param options a vector of options strings, each being "NAME=VALUE".  The supported
  * options are format specific.  null may be passed by default.
  *
- * @return gdalconst.CE_None on success or gdalconst.CE_Failure on failure.  
+ * @return gdalconst.CE_None on success or gdalconst.CE_Failure on failure.
  */
 public class Dataset:public int AddBand(int datatype, java.util.Vector options)
 
@@ -1757,8 +1757,8 @@ public class Dataset:public int AddBand()
 /**
  * Build raster overview(s).
  * <p>
- * If the operation is unsupported for the indicated dataset, then 
- * gdalconst.CE_Failure is returned, and gdal.GetLastErrorNo() will return 
+ * If the operation is unsupported for the indicated dataset, then
+ * gdalconst.CE_Failure is returned, and gdal.GetLastErrorNo() will return
  * gdalconst.CPLE_NotSupported.
  * <p>
  *
@@ -1768,9 +1768,9 @@ public class Dataset:public int AddBand()
  *   ds.BuildOverviews( "NEAREST", new int[] { 2, 4, 8 }, null );
  * </pre>
  *
- * @param resampling one of "NEAREST", "GAUSS", "AVERAGE", 
+ * @param resampling one of "NEAREST", "GAUSS", "AVERAGE",
  * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
- * @param overviewlist the list of overview decimation factors to build. 
+ * @param overviewlist the list of overview decimation factors to build.
  * @param callback for reporting progress or null
  *
  * @return gdalconst.CE_None on success or gdalconst.CE_Failure if the operation doesn't work.
@@ -1881,7 +1881,7 @@ public class Dataset:public Band GetRasterBand(int nBandId)
  * Fetch the projection definition string for this dataset.
  * <p>
  * The returned string defines the projection coordinate system of the
- * image in OpenGIS WKT format.  It should be suitable for use with the 
+ * image in OpenGIS WKT format.  It should be suitable for use with the
  * OGRSpatialReference class.
  * <p>
  * When a projection definition is not available an empty (but not null)
@@ -1897,7 +1897,7 @@ public class Dataset:public String GetProjection()
  * Fetch the projection definition string for this dataset.
  * <p>
  * The returned string defines the projection coordinate system of the
- * image in OpenGIS WKT format.  It should be suitable for use with the 
+ * image in OpenGIS WKT format.  It should be suitable for use with the
  * OGRSpatialReference class.
  * <p>
  * When a projection definition is not available an empty (but not null)
@@ -1995,26 +1995,26 @@ public class Dataset:public int SetGeoTransform(double[] geoTransformArray)
  * an empty list of files it means there is believed to be no local file
  * system files associated with the dataset (for instance a virtual dataset).
  * <p>
- * The returned filenames will normally be relative or absolute paths 
+ * The returned filenames will normally be relative or absolute paths
  * depending on the path used to originally open the dataset.
  *
- * @return null or a vector of strings of file names. 
+ * @return null or a vector of strings of file names.
  */
 public class Dataset:public java.util.Vector GetFileList()
 
 /**
- * Get number of GCPs. 
+ * Get number of GCPs.
  *
  * @return number of GCPs for this dataset.  Zero if there are none.
  */
 public class Dataset:public int GetGCPCount()
 
 /**
- * Get output projection for GCPs. 
+ * Get output projection for GCPs.
  * <p>
  * The projection string follows the normal rules from <a href="#GetProjectionRef()">GetProjectionRef()</a>.
- * 
- * @return projection string or "" if there are no GCPs. 
+ *
+ * @return projection string or "" if there are no GCPs.
  */
 public class Dataset:public String GetGCPProjection()
 
@@ -2024,7 +2024,7 @@ public class Dataset:public String GetGCPProjection()
  * Add to the provided vector the GCPs of the dataset
  *
  * @param gcpVector non null Vector object
- */ 
+ */
 public class Dataset:public void GetGCPs(java.util.Vector gcpVector)
 
 /**
@@ -2043,22 +2043,22 @@ public class Dataset:public java.util.Vector GetGCPs()
  * This method assigns the passed set of GCPs to this dataset, as well as
  * setting their coordinate system.  Internally copies are made of the
  * coordinate system and list of points, so the caller remains responsible for
- * deallocating these arguments if appropriate. 
+ * deallocating these arguments if appropriate.
  * <p>
- * Most formats do not support setting of GCPs, even formats that can 
- * handle GCPs.  These formats will return CE_Failure. 
+ * Most formats do not support setting of GCPs, even formats that can
+ * handle GCPs.  These formats will return CE_Failure.
  *
  * @param gcpArray array of GCP objects being assigned
  *
- * @param GCPProjection the new OGC WKT coordinate system to assign for the 
+ * @param GCPProjection the new OGC WKT coordinate system to assign for the
  * GCP output coordinates.  This parameter should be "" if no output coordinate
  * system is known.
  *
  * @return gdalconst.CE_None on success, gdalconst.CE_Failure on failure (including if action is
- * not supported for this format). 
+ * not supported for this format).
  *
  * @since Java bindings 1.7.0
- */ 
+ */
 public class Dataset:public int SetGCPs(GCP[] gcpArray, String GCPProjection)
 
 /**
@@ -2121,7 +2121,7 @@ public class Dataset:public int GetRasterCount()
  * region being accessed (xsize x ysize).
  * <p>
  * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
- * writing from various organization of buffers. 
+ * writing from various organization of buffers.
  * <p>
  * For highest performance full resolution data access, read
  * on "block boundaries" as returned by <a href="Band.html#GetBlockSize(int[], int[])">Band.GetBlockSize(int[], int[])</a>, or use the
@@ -2160,7 +2160,7 @@ public class Dataset:public int GetRasterCount()
  * nPixelSpace, and nLineSpace parameters.
  *
  * @param band_list the list of band numbers being read/written.
- * Note band numbers are 1 based.   This may be null to select the first 
+ * Note band numbers are 1 based.   This may be null to select the first
  * nBandCount bands.
  *
  * @param nPixelSpace The byte offset from the start of one pixel value in
@@ -2172,9 +2172,9 @@ public class Dataset:public int GetRasterCount()
  * buf_type * buf_xsize is used.
  *
  * @param nBandSpace the byte offset from the start of one bands data to the
- * start of the next.  If defaulted (zero) the value will be 
+ * start of the next.  If defaulted (zero) the value will be
  * nLineSpace * buf_ysize implying band sequential organization
- * of the data buffer. 
+ * of the data buffer.
  *
  * @return gdalconst.CE_Failure if the access fails, otherwise gdalconst.CE_None.
  *
@@ -2208,7 +2208,7 @@ public class Dataset:public int ReadRaster_Direct(int xoff, int yoff, int xsize,
  * region being accessed (xsize x ysize).
  * <p>
  * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
- * writing from various organization of buffers. 
+ * writing from various organization of buffers.
  * <p>
  * For highest performance full resolution data access, read
  * on "block boundaries" as returned by <a href="Band.html#GetBlockSize(int[], int[])">Band.GetBlockSize(int[], int[])</a>, or use the
@@ -2243,7 +2243,7 @@ public class Dataset:public int ReadRaster_Direct(int xoff, int yoff, int xsize,
  * nPixelSpace, and nLineSpace parameters.
  *
  * @param band_list the list of band numbers being read/written.
- * Note band numbers are 1 based.   This may be null to select the first 
+ * Note band numbers are 1 based.   This may be null to select the first
  * nBandCount bands.
  *
  * @param nPixelSpace The byte offset from the start of one pixel value in
@@ -2255,9 +2255,9 @@ public class Dataset:public int ReadRaster_Direct(int xoff, int yoff, int xsize,
  * buf_type * buf_xsize is used.
  *
  * @param nBandSpace the byte offset from the start of one bands data to the
- * start of the next.  If defaulted (zero) the value will be 
+ * start of the next.  If defaulted (zero) the value will be
  * nLineSpace * buf_ysize implying band sequential organization
- * of the data buffer. 
+ * of the data buffer.
  *
  * @return gdalconst.CE_Failure if the access fails, otherwise gdalconst.CE_None.
  *
@@ -2374,7 +2374,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
 /**
  * Write a region of image data from multiple bands.
  * <p>
- * This method allows writing data from a buffer into a region 
+ * This method allows writing data from a buffer into a region
  * of the Band's.  It automatically takes care of data type
  * translation if the data type (buf_type) of the buffer is different than
  * that of the Band.
@@ -2383,7 +2383,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
  * region being accessed (xsize x ysize).
  * <p>
  * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
- * writing from various organization of buffers. 
+ * writing from various organization of buffers.
  * <p>
  * For highest performance full resolution data access, write
  * on "block boundaries" as returned by <a href="Band.html#GetBlockSize(int[], int[])">Band.GetBlockSize(int[], int[])</a>, or use the
@@ -2421,7 +2421,7 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
  * nPixelSpace, and nLineSpace parameters.
  *
  * @param band_list the list of band numbers being read/written.
- * Note band numbers are 1 based.   This may be null to select the first 
+ * Note band numbers are 1 based.   This may be null to select the first
  * nBandCount bands.
  *
  * @param nPixelSpace The byte offset from the start of one pixel value in
@@ -2433,9 +2433,9 @@ public class Dataset:public int ReadRaster(int xoff, int yoff, int xsize, int ys
  * buf_type * buf_xsize is used.
  *
  * @param nBandSpace the byte offset from the start of one bands data to the
- * start of the next.  If defaulted (zero) the value will be 
+ * start of the next.  If defaulted (zero) the value will be
  * nLineSpace * buf_ysize implying band sequential organization
- * of the data buffer. 
+ * of the data buffer.
  *
  * @return gdalconst.CE_Failure if the access fails, otherwise gdalconst.CE_None.
  *
@@ -2462,7 +2462,7 @@ public class Dataset:public int WriteRaster_Direct(int xoff, int yoff, int xsize
 /**
  * Write a region of image data from multiple bands.
  * <p>
- * This method allows writing data from a buffer into a region 
+ * This method allows writing data from a buffer into a region
  * of the Band's.  It automatically takes care of data type
  * translation if the data type (buf_type) of the buffer is different than
  * that of the Band.
@@ -2471,7 +2471,7 @@ public class Dataset:public int WriteRaster_Direct(int xoff, int yoff, int xsize
  * region being accessed (xsize x ysize).
  * <p>
  * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
- * writing from various organization of buffers. 
+ * writing from various organization of buffers.
  * <p>
  * For highest performance full resolution data access, write
  * on "block boundaries" as returned by <a href="Band.html#GetBlockSize(int[], int[])">Band.GetBlockSize(int[], int[])</a>, or use the
@@ -2504,7 +2504,7 @@ public class Dataset:public int WriteRaster_Direct(int xoff, int yoff, int xsize
  * nPixelSpace, and nLineSpace parameters.
  *
  * @param band_list the list of band numbers being read/written.
- * Note band numbers are 1 based.   This may be null to select the first 
+ * Note band numbers are 1 based.   This may be null to select the first
  * nBandCount bands.
  *
  * @param nPixelSpace The byte offset from the start of one pixel value in
@@ -2516,9 +2516,9 @@ public class Dataset:public int WriteRaster_Direct(int xoff, int yoff, int xsize
  * buf_type * buf_xsize is used.
  *
  * @param nBandSpace the byte offset from the start of one bands data to the
- * start of the next.  If defaulted (zero) the value will be 
+ * start of the next.  If defaulted (zero) the value will be
  * nLineSpace * buf_ysize implying band sequential organization
- * of the data buffer. 
+ * of the data buffer.
  *
  * @return gdalconst.CE_Failure if the access fails, otherwise gdalconst.CE_None.
  *
@@ -2660,7 +2660,7 @@ public class Dataset:public int WriteRaster(int xoff, int yoff, int xsize, int y
 
 /**
  * Class Band is an uninstanciable class providing various methods to access a single raster band (or channel).
- * 
+ *
  * <p>
  * The Band class is a binding for the C++ <a href="http://gdal.org/classGDALRasterBand.html">GDALRasterBand</a> class.
  * <p>
@@ -2692,7 +2692,7 @@ public class Dataset:public int WriteRaster(int xoff, int yoff, int xsize, int y
  *   }
  *   band2.WriteRaster(0, 0, xsize, ysize, gdalconst.GDT_Byte, byteArray2);
  * </pre>
- * 
+ *
  *
  */
 public class Band
@@ -2703,19 +2703,19 @@ public class Band
 public class Band:public void delete()
 
 /**
- * Compute checksum for image region. 
+ * Compute checksum for image region.
  * <p>
  * Computes a 16bit (0-65535) checksum from a region of raster data on the raster band.
- * Floating point data is converted to 32bit integer 
+ * Floating point data is converted to 32bit integer
  * so decimal portions of such raster data will not affect the checksum.
- * Real and Imaginary components of complex bands influence the result. 
+ * Real and Imaginary components of complex bands influence the result.
  *
  * @param xoff pixel offset of window to read.
  * @param yoff line offset of window to read.
  * @param xsize pixel size of window to read.
  * @param ysize line size of window to read.
  *
- * @return Checksum value. 
+ * @return Checksum value.
  */
 public class Band:public int Checksum(int xoff, int yoff, int xsize, int ysize)
 
@@ -2723,12 +2723,12 @@ public class Band:public int Checksum(int xoff, int yoff, int xsize, int ysize)
  * Compute checksum for while image.
  * <p>
  * Computes a 16bit (0-65535) checksum from data on the raster band.
- * Floating point data is converted to 32bit integer 
+ * Floating point data is converted to 32bit integer
  * so decimal portions of such raster data will not affect the checksum.
- * Real and Imaginary components of complex bands influence the result. 
+ * Real and Imaginary components of complex bands influence the result.
  *
  * @return Checksum value.
- * @since Java bindings 1.7.0 
+ * @since Java bindings 1.7.0
  */
 public class Band:public int Checksum()
 
@@ -2761,7 +2761,7 @@ public class Band:public void ComputeBandStats(double[] meanAndStdDevArray)
  * <p>
  * If approx_ok is 0, then all pixels will be read and used to compute
  * an exact range.
- * 
+ *
  * @param minMaxArray the allocated array of 2 doubles in which the minimum (minMaxArray[0]) and the
  * maximum (minMaxArray[1]) are returned.
  * @param approx_ok 1 if an approximate (faster) answer is OK, otherwise 0.
@@ -2779,26 +2779,26 @@ public class Band:public void ComputeRasterMinMax(double[] minMaxArray, int appr
 public class Band:public void ComputeRasterMinMax(double[] minMaxArray)
 
 /**
- * Compute image statistics. 
+ * Compute image statistics.
  * <p>
  * Returns the minimum, maximum, mean and standard deviation of all
  * pixel values in this band.  If approximate statistics are sufficient,
  * the approx_ok flag can be set to true in which case overviews, or a
- * subset of image tiles may be used in computing the statistics.  
+ * subset of image tiles may be used in computing the statistics.
  * <p>
- * Once computed, the statistics will generally be "set" back on the 
- * raster band using SetStatistics(). 
+ * Once computed, the statistics will generally be "set" back on the
+ * raster band using SetStatistics().
  *
  * @param approx_ok If true statistics may be computed based on overviews
- * or a subset of all tiles. 
- * 
+ * or a subset of all tiles.
+ *
  * @param min Allocated array of one double into which to load image minimum (may be null).
  *
  * @param max Allocated array of one double into which to load image maximum (may be null).
  *
  * @param mean Allocated array of one double into which to load image mean (may be null).
  *
- * @param stddev Allocated array of one double into which to load image standard deviation 
+ * @param stddev Allocated array of one double into which to load image standard deviation
  * (may be null).
  *
  * @param callback for reporting algorithm progress. May be null
@@ -2811,7 +2811,7 @@ public class Band:public void ComputeRasterMinMax(double[] minMaxArray)
 public class Band:public int ComputeStatistics(boolean approx_ok, double[] min, double[] max, double[] mean, double[] stddev, ProgressCallback callback)
 
 /**
- * Compute image statistics. 
+ * Compute image statistics.
  * <p>
  * Same as below with callback == null
  *
@@ -2824,7 +2824,7 @@ public class Band:public int ComputeStatistics(boolean approx_ok, double[] min,
 @hide public class Band:public int ComputeStatistics(boolean approx_ok, double[] min, double[] max, double[] mean)
 
 /**
- * Compute image statistics. 
+ * Compute image statistics.
  * <p>
  * Same as below with mean == null, stddev == null and callback == null
  *
@@ -2837,7 +2837,7 @@ public class Band:public int ComputeStatistics(boolean approx_ok, double[] min,
 @hide public class Band:public int ComputeStatistics(boolean approx_ok, double[] min)
 
 /**
- * Compute image statistics. 
+ * Compute image statistics.
  * <p>
  * Same as below with min == null, max == null, mean == null, stddev == null and callback == null
  *
@@ -2867,7 +2867,7 @@ public class Band:public int ComputeStatistics(boolean approx_ok)
  */
 public class Band:public int CreateMaskBand(int nFlags)
 
-/** 
+/**
  * Fill this band with a constant value.
  * <p>
  * GDAL makes no guarantees
@@ -2877,15 +2877,15 @@ public class Band:public int CreateMaskBand(int nFlags)
  * to the underlying type before writing to the file. An optional
  * second argument allows the imaginary component of a complex
  * constant value to be specified.
- * 
+ *
  * @param real_fill Real component of fill value
  * @param imag_fill Imaginary component of fill value, defaults to zero
- * 
+ *
  * @return gdalconst.CE_Failure if the write fails, otherwise gdalconst.CE_None
  */
 public class Band:public int Fill(double real_fill, double imag_fill)
 
-/** 
+/**
  * Fill this band with a constant value.
  * <p>
  * Same as below with image_fill == 0
@@ -2961,7 +2961,7 @@ public class Band:public int GetBlockYSize()
  * How should this band be interpreted as color?
  * <p>
  * gdalconst.GCI_Undefined is returned when the format doesn't know anything
- * about the color interpretation. 
+ * about the color interpretation.
  *
  * @return color interpretation value for band.
  *
@@ -2990,7 +2990,7 @@ public class Band:public int getDataType()
 
 
 /**
- * Fetch default raster histogram. 
+ * Fetch default raster histogram.
  * <p>
  * The default method in GDALRasterBand will compute a default histogram. This
  * method is overridden by derived classes (such as GDALPamRasterBand, VRTDataset, HFADataset...)
@@ -3020,7 +3020,7 @@ public class Band:public int getDataType()
  * @param force true to force the computation. If false and no default histogram is available, the method will return CE_Warning
  * @param callback for reporting algorithm progress. May be null
  *
- * @return gdalconst.CE_None on success, gdalconst.CE_Failure if something goes wrong, or 
+ * @return gdalconst.CE_None on success, gdalconst.CE_Failure if something goes wrong, or
  * gdalconst.CE_Warning if no default histogram is available.
  *
  * @since Java bindings 1.7.0
@@ -3028,7 +3028,7 @@ public class Band:public int getDataType()
 public class Band:public int GetDefaultHistogram(double[] min_ret, double[] max_ret, int[][] histogram_ret, boolean force, ProgressCallback callback)
 
 /**
- * Fetch default raster histogram. 
+ * Fetch default raster histogram.
  * <p>
  * Same as below with callback == null
  *
@@ -3039,7 +3039,7 @@ public class Band:public int GetDefaultHistogram(double[] min_ret, double[] max_
 public class Band:public int GetDefaultHistogram(double[] min_ret, double[] max_ret, int[][] histogram_ret, boolean force)
 
 /**
- * Fetch default raster histogram. 
+ * Fetch default raster histogram.
  * <p>
  * Same as below with force == true and callback == null
  *
@@ -3054,29 +3054,29 @@ public class Band:public int GetDefaultHistogram(double[] min_ret, double[] max_
  * <p>
  * A RAT will be returned if there is a default one associated with the
  * band, otherwise null is returned.  The returned RAT is owned by the
- * band and should not be altered by the application. 
- * 
+ * band and should not be altered by the application.
+ *
  * @return a RAT or null
  */
 public class Band:public RasterAttributeTable GetDefaultRAT()
 
 /**
- * Compute raster histogram. 
+ * Compute raster histogram.
  * <p>
- * Note that the bucket size is (dfMax-dfMin) / nBuckets.  
+ * Note that the bucket size is (dfMax-dfMin) / nBuckets.
  * <p>
- * For example to compute a simple 256 entry histogram of eight bit data, 
+ * For example to compute a simple 256 entry histogram of eight bit data,
  * the following would be suitable.  The unusual bounds are to ensure that
  * bucket boundaries don't fall right on integer values causing possible errors
- * due to rounding after scaling. 
+ * due to rounding after scaling.
  * <pre>
  *     int anHistogram = new int[256];
- * 
+ *
  *     band.GetHistogram( -0.5, 255.5, 256, anHistogram, false, false, null);
  * </pre>
  * <p>
  * Note that setting approx_ok will generally result in a subsampling of the
- * file, and will utilize overviews if available.  It should generally 
+ * file, and will utilize overviews if available.  It should generally
  * produce a representative histogram for the data that is suitable for use
  * in generating histogram based luts for instance.  Generally bApproxOK is
  * much faster than an exactly computed histogram.
@@ -3085,19 +3085,19 @@ public class Band:public RasterAttributeTable GetDefaultRAT()
  * @param max the upper bound of the histogram.
  * @param histogram allocated array into which the histogram totals are placed.
  * @param include_out_of_range if true values below the histogram range will
- * mapped into anHistogram[0], and values above will be mapped into 
+ * mapped into anHistogram[0], and values above will be mapped into
  * anHistogram[anHistogram.length-1] otherwise out of range values are discarded.
  * @param approx_ok true if an approximate, or incomplete histogram OK.
  * @param callback for reporting algorithm progress. May be null
  *
- * @return gdalconst.CE_None on success, or gdalconst.CE_Failure if something goes wrong. 
+ * @return gdalconst.CE_None on success, or gdalconst.CE_Failure if something goes wrong.
  *
  * @since Java bindings 1.7.0
  */
 public class Band:public int GetHistogram(double min, double max, int[] histogram, boolean include_out_of_range, boolean approx_ok, ProgressCallback callback)
 
 /**
- * Compute raster histogram. 
+ * Compute raster histogram.
  * <p>
  * Same as below with callback == null
  *
@@ -3108,7 +3108,7 @@ public class Band:public int GetHistogram(double min, double max, int[] histogra
 public class Band:public int GetHistogram(double min, double max, int[] histogram, boolean include_out_of_range, boolean approx_ok)
 
 /**
- * Compute raster histogram. 
+ * Compute raster histogram.
  * <p>
  * Same as below with include_out_of_range == 0, approx_ok == true and callback == null
  *
@@ -3119,7 +3119,7 @@ public class Band:public int GetHistogram(double min, double max, int[] histogra
 public class Band:public int GetHistogram(double min, double max, int[] histogram)
 
 /**
- * Compute raster histogram. 
+ * Compute raster histogram.
  * <p>
  * Same as below with include_out_of_range == 0, approx_ok == true and callback == null
  *
@@ -3152,7 +3152,7 @@ public class Band:public int GetHistogram(int[] histogram)
  * </ul>
  * <p>
  * Note that the GetMaskBand() should always return a GDALRasterBand mask, even if it is only
- * an all 255 mask with the flags indicating GMF_ALL_VALID. 
+ * an all 255 mask with the flags indicating GMF_ALL_VALID.
  *
  * @return a valid mask band.
  *
@@ -3230,9 +3230,9 @@ public class Band:public void GetMaximum(Double[] val)
  * Fetch the raster value offset.
  * <p>
  * This value (in combination with the GetScale() value) is used to
- * transform raw pixel values into the units returned by GetUnits().  
+ * transform raw pixel values into the units returned by GetUnits().
  * For example this might be used to store elevations in GUInt16 bands
- * with a precision of 0.1, and starting from -100. 
+ * with a precision of 0.1, and starting from -100.
  * <p>
  * Units value = (raw value * scale) + offset
  * <p>
@@ -3247,9 +3247,9 @@ public class Band:public void GetOffset(Double[] val)
  * Fetch the raster value scale.
  * <p>
  * This value (in combination with the GetOffset() value) is used to
- * transform raw pixel values into the units returned by GetUnits().  
+ * transform raw pixel values into the units returned by GetUnits().
  * For example this might be used to store elevations in GUInt16 bands
- * with a precision of 0.1, and starting from -100. 
+ * with a precision of 0.1, and starting from -100.
  * <p>
  * Units value = (raw value * scale) + offset
  * <p>
@@ -3274,9 +3274,9 @@ public class Band:public void GetNoDataValue(Double[] val)
 
 /**
  * Fetch overview raster band object.
- * 
+ *
  * @param i overview index between 0 and GetOverviewCount()-1.
- * 
+ *
  * @return overview Band.
  */
 public class Band:public Band GetOverview(int i)
@@ -3304,10 +3304,10 @@ public class Band:public java.util.Vector GetCategoryNames()
 /**
  * Fetch the list of category names for this raster.
  * <p>
- * Raster values without 
+ * Raster values without
  * associated names will have an empty string in the returned list.  The
- * first entry in the list is for raster values of zero, and so on. 
- * 
+ * first entry in the list is for raster values of zero, and so on.
+ *
  * @return vector of names, or null if none.
  */
 public class Band:public java.util.Vector GetRasterCategoryNames()
@@ -3316,7 +3316,7 @@ public class Band:public java.util.Vector GetRasterCategoryNames()
  * How should this band be interpreted as color?
  * <p>
  * gdalconst.GCI_Undefined is returned when the format doesn't know anything
- * about the color interpretation. 
+ * about the color interpretation.
  *
  * @return color interpretation value for band.
  */
@@ -3344,28 +3344,28 @@ public class Band:public ColorTable GetRasterColorTable()
 public class Band:public int GetRasterDataType()
 
 /**
- * Fetch image statistics. 
+ * Fetch image statistics.
  * <p>
  * Returns the minimum, maximum, mean and standard deviation of all
  * pixel values in this band.  If approximate statistics are sufficient,
  * the approx_ok flag can be set to true in which case overviews, or a
- * subset of image tiles may be used in computing the statistics.  
+ * subset of image tiles may be used in computing the statistics.
  * <p>
- * If force is false results will only be returned if it can be done 
- * quickly (i.e. without scanning the data).  If force is false and 
+ * If force is false results will only be returned if it can be done
+ * quickly (i.e. without scanning the data).  If force is false and
  * results cannot be returned efficiently, the method will return CE_Warning
  * but no warning will have been issued.   This is a non-standard use of
- * the CE_Warning return value to indicate "nothing done". 
+ * the CE_Warning return value to indicate "nothing done".
  * <p>
  * Note that file formats using PAM (Persistent Auxiliary Metadata) services
  * will generally cache statistics in the .pam file allowing fast fetch
- * after the first request. 
+ * after the first request.
  *
  * @param approx_ok If true statistics may be computed based on overviews
- * or a subset of all tiles. 
- * 
+ * or a subset of all tiles.
+ *
  * @param force If true statistics will only be returned if it can
- * be done without rescanning the image. 
+ * be done without rescanning the image.
  *
  * @param min Allocated array of one double into which to load image minimum (may be null).
  *
@@ -3373,10 +3373,10 @@ public class Band:public int GetRasterDataType()
  *
  * @param mean Allocated array of one double into which to load image mean (may be null).
  *
- * @param stddev Allocated array of one double into which to load image standard deviation 
+ * @param stddev Allocated array of one double into which to load image standard deviation
  * (may be null).
  *
- * @return gdalconst.CE_None on success, gdalconst.CE_Warning if no values returned, 
+ * @return gdalconst.CE_None on success, gdalconst.CE_Warning if no values returned,
  * gdalconst.CE_Failure if an error occurs.
  *
  * @since Java bindings 1.7.0
@@ -3384,7 +3384,7 @@ public class Band:public int GetRasterDataType()
 public class Band:public int GetStatistics(boolean approx_ok, boolean force, double[] min, double[] max, double[] mean, double[] stddev)
 
 /**
- * Fetch image statistics. 
+ * Fetch image statistics.
  * <p>
  * Same as below but boolean value of true should be replaced with 1, and false with 0.
  *
@@ -3396,7 +3396,7 @@ public class Band:public int GetStatistics(int approx_ok, int force, double[] mi
  * Return raster unit type.
  * <p>
  * Return a name for the units of this raster's values.  For instance, it
- * might be "m" for an elevation model in meters, or "ft" for feet.  If no 
+ * might be "m" for an elevation model in meters, or "ft" for feet.  If no
  * units are available, a value of "" will be returned.
  *
  * @return unit name string.
@@ -3406,14 +3406,14 @@ public class Band:public int GetStatistics(int approx_ok, int force, double[] mi
 public class Band:public String GetUnitType()
 
 /**
- * Fetch XSize of raster. 
+ * Fetch XSize of raster.
  *
  * @return the width in pixels of this band.
  */
 public class Band:public int getXSize()
 
 /**
- * Fetch XSize of raster. 
+ * Fetch XSize of raster.
  *
  * @return the width in pixels of this band.
  *
@@ -3423,14 +3423,14 @@ public class Band:public int getXSize()
 public class Band:public int GetXSize()
 
 /**
- * Fetch YSize of raster. 
+ * Fetch YSize of raster.
  *
  * @return the height in pixels of this band.
  */
 public class Band:public int getYSize()
 
 /**
- * Fetch YSize of raster. 
+ * Fetch YSize of raster.
  *
  * @return the height in pixels of this band.
  *
@@ -3441,14 +3441,14 @@ public class Band:public int GetYSize()
 /**
  * Check for arbitrary overviews.
  * <p>
- * This returns true if the underlying datastore can compute arbitrary 
- * overviews efficiently, such as is the case with OGDI over a network. 
+ * This returns true if the underlying datastore can compute arbitrary
+ * overviews efficiently, such as is the case with OGDI over a network.
  * Datastores with arbitrary overviews don't generally have any fixed
  * overviews, but the ReadRaster() method can be used in downsampling mode
  * to get overview data efficiently.
  *
  * @return true if arbitrary overviews available (efficiently), otherwise
- * false. 
+ * false.
  *
  * @since Java bindings 1.7.0
  */
@@ -3467,7 +3467,7 @@ public class Band:public boolean HasArbitraryOverviews()
  * The nPixelSpace and nLineSpace parameters allow reading into or
  * writing from unusually organized buffers.  This is primarily used
  * for buffers containing more than one bands raster data in interleaved
- * format. 
+ * format.
  *<p>
  * Some formats may efficiently implement decimation into a buffer by
  * reading from lower resolution overview images.
@@ -3610,7 +3610,7 @@ public class Band:public java.nio.ByteBuffer ReadRaster_Direct(int xoff, int yof
  * The nPixelSpace and nLineSpace parameters allow reading into or
  * writing from unusually organized buffers.  This is primarily used
  * for buffers containing more than one bands raster data in interleaved
- * format. 
+ * format.
  *<p>
  * Some formats may efficiently implement decimation into a buffer by
  * reading from lower resolution overview images.
@@ -3891,7 +3891,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
 /**
  * Write a region of image data for this band.
  * <p>
- * This method allows writing data from a buffer into a region 
+ * This method allows writing data from a buffer into a region
  * of the Band.  It
  * automatically takes care of data type translation if the data type
  * (buf_type) of the buffer is different than that of the GDALRasterBand.
@@ -3902,7 +3902,7 @@ public class Band:public int ReadRaster(int xoff, int yoff, int xsize, int ysize
  * The nPixelSpace and nLineSpace parameters allow reading into or
  * writing from unusually organized buffers.  This is primarily used
  * for buffers containing more than one bands raster data in interleaved
- * format. 
+ * format.
  *<p>
  * Some formats may efficiently implement decimation into a buffer by
  * reading from lower resolution overview images.
@@ -4007,7 +4007,7 @@ public class Band:public int WriteRaster_Direct(int xoff, int yoff, int xsize, i
 /**
  * Write a region of image data for this band.
  * <p>
- * This method allows writing data from a buffer into a region 
+ * This method allows writing data from a buffer into a region
  * of the Band.  It
  * automatically takes care of data type translation if the data type
  * (buf_type) of the buffer is different than that of the GDALRasterBand.
@@ -4018,7 +4018,7 @@ public class Band:public int WriteRaster_Direct(int xoff, int yoff, int xsize, i
  * The nPixelSpace and nLineSpace parameters allow reading into or
  * writing from unusually organized buffers.  This is primarily used
  * for buffers containing more than one bands raster data in interleaved
- * format. 
+ * format.
  *<p>
  * Some formats may efficiently implement decimation into a buffer by
  * reading from lower resolution overview images.
@@ -4291,7 +4291,7 @@ public class Band:public int WriteRaster(int xoff, int yoff, int xsize, int ysiz
  * potentially less efficient access use ReadRaster().
  *
  * @param nXBlockOff the horizontal block offset, with zero indicating
- * the left most block, 1 the next block and so forth. 
+ * the left most block, 1 the next block and so forth.
  *
  * @param nYBlockOff the vertical block offset, with zero indicating
  * the left most block, 1 the next block and so forth.
@@ -4314,7 +4314,7 @@ public class Band:public int ReadBlock_Direct(int nXBlockOff, int nYBlockOff, ja
  * potentially less efficient access use WriteRaster().
  *
  * @param nXBlockOff the horizontal block offset, with zero indicating
- * the left most block, 1 the next block and so forth. 
+ * the left most block, 1 the next block and so forth.
  *
  * @param nYBlockOff the vertical block offset, with zero indicating
  * the left most block, 1 the next block and so forth.
@@ -4333,7 +4333,7 @@ public class Band:public int WriteBlock_Direct(int nXBlockOff, int nYBlockOff, j
  * Set color interpretation of a band.
  *
  * @param eColorInterp the new color interpretation to apply to this band.
- * 
+ *
  * @return gdalconst.CE_None on success or gdalconst.CE_Failure if method is unsupported by format.
  *
  * @since Java bindings 1.7.0
@@ -4344,15 +4344,15 @@ public class Band:public int SetColorInterpretation(int eColorInterp)
  * Set color interpretation of a band.
  *
  * @param eColorInterp the new color interpretation to apply to this band.
- * 
+ *
  * @return gdalconst.CE_None on success or gdalconst.CE_Failure if method is unsupported by format.
  */
 public class Band:public int SetRasterColorInterpretation(int eColorInterp)
 
 /**
- * Set the raster color table. 
+ * Set the raster color table.
  *
- * @param colorTable the color table to apply.  This may be null to clear the color 
+ * @param colorTable the color table to apply.  This may be null to clear the color
  * table (where supported).
  *
  * @return gdalconst.CE_None on success, or gdalconst.CE_Failure on failure.  If the action is
@@ -4362,9 +4362,9 @@ public class Band:public int SetRasterColorInterpretation(int eColorInterp)
 public class Band:public int SetColorTable(ColorTable colorTable)
 
 /**
- * Set the raster color table. 
+ * Set the raster color table.
  *
- * @param colorTable the color table to apply.  This may be null to clear the color 
+ * @param colorTable the color table to apply.  This may be null to clear the color
  * table (where supported).
  *
  * @return gdalconst.CE_None on success, or gdalconst.CE_Failure on failure.  If the action is
@@ -4388,13 +4388,13 @@ public class Band:public int SetDefaultHistogram(double min, double max, int[] h
  *
  * @param table the RAT to assign to the band.
  *
- * @return gdalconst.CE_None on success or gdalconst.CE_Failure if unsupported or otherwise 
+ * @return gdalconst.CE_None on success or gdalconst.CE_Failure if unsupported or otherwise
  * failing.
  */
 public class Band:public int SetDefaultRAT(RasterAttributeTable table)
 
 /**
- * Set the no data value for this band. 
+ * Set the no data value for this band.
  * <p>
  * To clear the nodata value, just set it with an "out of range" value.
  * Complex band no data values must have an imagery component of zero.
@@ -4415,7 +4415,7 @@ public class Band:public int SetNoDataValue(double nodataValue)
  *
  * @param newoffset the new offset.
  *
- * @return gdalconst.CE_None or success or gdalconst.CE_Failure on failure. 
+ * @return gdalconst.CE_None or success or gdalconst.CE_Failure on failure.
  *
  * @since Java bindings 1.8.0
  */
@@ -4429,7 +4429,7 @@ public class Band:public int SetOffset(double newoffset)
  *
  * @param newscale the new scale.
  *
- * @return gdalconst.CE_None or success or gdalconst.CE_Failure on failure. 
+ * @return gdalconst.CE_None or success or gdalconst.CE_Failure on failure.
  *
  * @since Java bindings 1.8.0
  */
@@ -4439,12 +4439,12 @@ public class Band:public int SetScale(double newscale)
  * Set unit type.
  * <p>
  * Set the unit type for a raster band.  Values should be one of
- * "" (the default indicating it is unknown), "m" indicating meters, 
+ * "" (the default indicating it is unknown), "m" indicating meters,
  * or "ft" indicating feet, though other nonstandard values are allowed.
  *
  * @param newunittype the new unit type value.
  *
- * @return gdalconst.CE_None on success or gdalconst.CE_Failure if not succuessful, or 
+ * @return gdalconst.CE_None on success or gdalconst.CE_Failure if not succuessful, or
  * unsupported.
  *
  * @since Java bindings 1.8.0
@@ -4472,10 +4472,10 @@ public class Band:public int SetCategoryNames(java.util.Vector names)
  * Set the category names for this band.
  * <p>
  * See the GetCategoryNames() method for more on the interpretation of
- * category names. 
+ * category names.
  *
  * @param names a vector of strings with category names.  May
- * be ,ull to just clear the existing list. 
+ * be ,ull to just clear the existing list.
  *
  * @return gdalconst.CE_None on success, or gdalconst.CE_Failure on failure.  If unsupported
  * by the driver, CE_Failure is returned by no error message will have
@@ -4487,22 +4487,22 @@ public class Band:public int SetRasterCategoryNames(java.util.Vector names)
  * Set statistics on band.
  * <p>
  * This method can be used to store min/max/mean/standard deviation
- * statistics on a raster band.  
+ * statistics on a raster band.
  * <p>
- * The default implementation stores them as metadata, and will only work 
+ * The default implementation stores them as metadata, and will only work
  * on formats that can save arbitrary metadata.  This method cannot detect
  * whether metadata will be properly saved and so may return CE_None even
  * if the statistics will never be saved.
- * 
+ *
  * @param min minimum pixel value.
- * 
+ *
  * @param max maximum pixel value.
  *
- * @param mean mean (average) of all pixel values.		
+ * @param mean mean (average) of all pixel values.
  *
  * @param stddev Standard deviation of all pixel values.
  *
- * @return gdalconst.CE_None on success or gdalconst.CE_Failure on failure. 
+ * @return gdalconst.CE_None on success or gdalconst.CE_Failure on failure.
  */
 public class Band:public int SetStatistics(double min, double max, double mean, double stddev)
 
@@ -4514,30 +4514,30 @@ public class Band:public int SetStatistics(double min, double max, double mean,
  * in the table applies to a range of pixel values (or a single value in
  * some cases), and might have attributes such as the histogram count for
  * that range, the color pixels of that range should be drawn names of classes
- * or any other generic information. 
+ * or any other generic information.
  *
  * <p>
  * The RasterAttributeTable class is a binding for the C++ <a href="http://gdal.org/classGDALRasterAttributeTable.html">GDALRasterAttributeTable</a> class.
  * <p>
  * Raster attribute tables can be used to represent histograms, color tables,
- * and classification information.  
+ * and classification information.
  * <p>
  * Each column in a raster attribute table has a name, a type (integer,
- * floating point or string), and a GDALRATFieldUsage.  The usage distinguishes 
- * columns with particular understood purposes (such as color, histogram 
- * count, name) and columns that have specific purposes not understood by 
- * the library (long label, suitability_for_growing_wheat, etc).  
+ * floating point or string), and a GDALRATFieldUsage.  The usage distinguishes
+ * columns with particular understood purposes (such as color, histogram
+ * count, name) and columns that have specific purposes not understood by
+ * the library (long label, suitability_for_growing_wheat, etc).
  * <p>
  * In the general case each row has a column indicating the minimum pixel
  * values falling into that category, and a column indicating the maximum
  * pixel value.  These are indicated with usage values of GFU_Min, and
  * GFU_Max.  In other cases where each row is a discrete pixel value, one
- * column of usage GFU_MinMax can be used.  
+ * column of usage GFU_MinMax can be used.
  *  <p>
- * In other cases all the categories are of equal size and regularly spaced 
+ * In other cases all the categories are of equal size and regularly spaced
  * and the categorization information can be determine just by knowing the
  * value at which the categories start, and the size of a category.  This
- * is called "Linear Binning" and the information is kept specially on 
+ * is called "Linear Binning" and the information is kept specially on
  * the raster attribute table as a whole.
  * <p>
  * RATs are normally associated with Bands and be be queried
@@ -4555,7 +4555,7 @@ public class RasterAttributeTable:public RasterAttributeTable()
  * <p>
  * Creates a new copy of an existing raster attribute table.
  *
- * @return new copy of the RAT. 
+ * @return new copy of the RAT.
  */
 public class RasterAttributeTable:public RasterAttributeTable Clone()
 
@@ -4564,7 +4564,7 @@ public class RasterAttributeTable:public RasterAttributeTable Clone()
  * <p>
  * If the table already has rows, all row values for the new column will
  * be initialized to the default value ("", or zero).  The new column is
- * always created as the last column, can will be column (field) 
+ * always created as the last column, can will be column (field)
  * "GetColumnCount()-1" after CreateColumn() has completed successfully.
  *
  * @param name the name of the field to create.
@@ -4578,12 +4578,12 @@ public class RasterAttributeTable:public int CreateColumn(String name, int eFiel
 /**
  * Fetch column index for given usage.
  * <p>
- * Returns the index of the first column of the requested usage type, or -1 
- * if no match is found. 
+ * Returns the index of the first column of the requested usage type, or -1
+ * if no match is found.
  *
  * @param eUsage usage type to search for.
  *
- * @return column index, or -1 on failure. 
+ * @return column index, or -1 on failure.
  */
 public class RasterAttributeTable:public int GetColOfUsage(int eUsage)
 
@@ -4611,7 +4611,7 @@ public class RasterAttributeTable:public boolean GetLinearBinning(double[] pdfRo
 /**
  * Fetch name of indicated column.
  *
- * @param iCol the column index (zero based). 
+ * @param iCol the column index (zero based).
  *
  * @return the column name or an empty string for invalid column numbers.
  */
@@ -4620,20 +4620,20 @@ public class RasterAttributeTable:public String GetNameOfCol(int iCol)
 /**
  * Fetch row count.
  *
- * @return the number of rows. 
+ * @return the number of rows.
  */
 public class RasterAttributeTable:public int GetRowCount()
 
 /**
  * Get row for pixel value.
  * <p>
- * Given a raw pixel value, the raster attribute table is scanned to 
+ * Given a raw pixel value, the raster attribute table is scanned to
  * determine which row in the table applies to the pixel value.  The
- * row index is returned. 
+ * row index is returned.
  *
- * @param dfValue the pixel value. 
+ * @param dfValue the pixel value.
  *
- * @return the row index or -1 if no row is appropriate. 
+ * @return the row index or -1 if no row is appropriate.
  */
 public class RasterAttributeTable:public int GetRowOfValue(double dfValue)
 
@@ -4647,7 +4647,7 @@ public class RasterAttributeTable:public int GetRowOfValue(double dfValue)
 public class RasterAttributeTable:public int GetTypeOfCol(int iCol)
 
 /**
- * Fetch column usage value. 
+ * Fetch column usage value.
  *
  * @param iCol the column index (zero based).
  *
@@ -4664,7 +4664,7 @@ public class RasterAttributeTable:public int GetUsageOfCol(int iCol)
  *
  * @param iRow row to fetch (zero based).
  * @param iCol column to fetch (zero based).
- * 
+ *
  * @return field value
  */
 public class RasterAttributeTable:public double GetValueAsDouble(int iRow, int iCol)
@@ -4678,7 +4678,7 @@ public class RasterAttributeTable:public double GetValueAsDouble(int iRow, int i
  *
  * @param iRow row to fetch (zero based).
  * @param iCol column to fetch (zero based).
- * 
+ *
  * @return field value
  */
 public class RasterAttributeTable:public int GetValueAsInt(int iRow, int iCol)
@@ -4693,7 +4693,7 @@ public class RasterAttributeTable:public int GetValueAsInt(int iRow, int iCol)
  *
  * @param iRow row to fetch (zero based).
  * @param iCol column to fetch (zero based).
- * 
+ *
  * @return field value
  */
 public class RasterAttributeTable:public String GetValueAsString(int iRow, int iCol)
@@ -4706,7 +4706,7 @@ public class RasterAttributeTable:public String GetValueAsString(int iRow, int i
  * information with the table.
  *
  * @param dfRow0Min the lower bound (pixel value) of the first category.
- * @param dfBinSize the width of each category (in pixel value units). 
+ * @param dfBinSize the width of each category (in pixel value units).
  *
  * @return CE_None on success or CE_Failure on failure.
  *
@@ -4718,8 +4718,8 @@ public class RasterAttributeTable:public int SetLinearBinning(double dfRow0Min,
  * Set row count.
  * <p>
  * Resizes the table to include the indicated number of rows.  Newly created
- * rows will be initialized to their default values - "" for strings, 
- * and zero for numeric fields. 
+ * rows will be initialized to their default values - "" for strings,
+ * and zero for numeric fields.
  *
  * @param nCount the new number of rows.
  */
@@ -4762,7 +4762,7 @@ public class RasterAttributeTable:public void SetValueAsInt(int iRow, int iCol,
  * @param iCol column to fetch (zero based).
  * @param pszValue the value to assign.
  */
-public class RasterAttributeTable:public void SetValueAsString(int iRow, int iCol, String pszValue) 
+public class RasterAttributeTable:public void SetValueAsString(int iRow, int iCol, String pszValue)
 
 /* Class Driver */
 
@@ -4868,9 +4868,9 @@ public class org.gdal.gdal.Driver:public Dataset Create(String name, int xsize,
  * Create a copy of a dataset.
  * <p>
  * This method will attempt to create a copy of a raster dataset with the
- * indicated filename, and in this drivers format.  Band number, size, 
+ * indicated filename, and in this drivers format.  Band number, size,
  * type, projection, geotransform and so forth are all to be copied from
- * the provided template dataset.  
+ * the provided template dataset.
  * <p>
  * Note that many sequential write once formats (such as JPEG and PNG) don't
  * implement the Create() method but do implement this CreateCopy() method.
@@ -4890,13 +4890,13 @@ public class org.gdal.gdal.Driver:public Dataset Create(String name, int xsize,
  * At the end of dataset manipulation, the delete() method <b>must</b> be called
  * on the returned dataset otherwise data might not be properly flushed to the disk.
  *
- * @param name the name for the new dataset. 
- * @param src_ds the dataset being duplicated. 
+ * @param name the name for the new dataset.
+ * @param src_ds the dataset being duplicated.
  * @param strict 1 if the copy must be strictly equivalent, or more
- * normally 0 indicating that the copy may adapt as needed for the 
- * output format. 
- * @param options additional format dependent options controlling 
- * creation of the output file. 
+ * normally 0 indicating that the copy may adapt as needed for the
+ * output format.
+ * @param options additional format dependent options controlling
+ * creation of the output file.
  * @param callback for reporting algorithm progress. May be null
  *
  * @return the newly created dataset (may be read-only access).
@@ -4989,10 +4989,10 @@ public class org.gdal.gdal.Driver:public int Delete(String name)
  * Rename a dataset.
  * <p>
  * Rename a dataset. This may including moving the dataset to a new directory
- * or even a new filesystem.  
+ * or even a new filesystem.
  * <p>
  * It is unwise to have open dataset handles on this dataset when it is
- * being renamed. 
+ * being renamed.
  *
  * @param newName new name for the dataset.
  * @param oldName old name for the dataset.
@@ -5117,20 +5117,20 @@ public class TermProgressCallback
 /* Class MajorObject */
 
 /**
-  * Class used for object with metadata. 
-  * 
+  * Class used for object with metadata.
+  *
   * <p>
   * The MajorObject class is a binding for the C++ <a href="http://gdal.org/classGDALMajorObject.html">GDALMajorObject</a> class.
   */
 public class MajorObject
 
 /**
- * Fetch object description. 
+ * Fetch object description.
  * <p>
  * The semantics of the returned description are specific to the derived
  * type.  For Dataset object it is the dataset name.  For Band object
  * it is actually a description (if supported) or "".
- * 
+ *
  * @return description
  */
 
@@ -5138,13 +5138,13 @@ public class MajorObject:public String GetDescription()
 
 
 /**
- * Set object description. 
+ * Set object description.
  * <p>
  * The semantics of the returned description are specific to the derived
  * type.  For Dataset object it is the dataset name.  For Band object
  * it is actually a description (if supported) or "".
  *
- * Normally application code should not set the "description" for 
+ * Normally application code should not set the "description" for
  * GDALDatasets.  It is handled internally.
  *
  * @param newDescription new description
@@ -5159,7 +5159,7 @@ public class MajorObject:public void SetDescription(String newDescription)
  *
  * @param domain the domain of interest.  Use "" or null for the default
  * domain.
- * 
+ *
  * @return null or a hash table with metadata
  */
 public class MajorObject:public java.util.Hashtable GetMetadata_Dict(String domain)
@@ -5168,7 +5168,7 @@ public class MajorObject:public java.util.Hashtable GetMetadata_Dict(String doma
  * Fetch metadata.
  *
  * Returns metadata from the default domain as (key, value) tuples in the result table
- * 
+ *
  * @return null or a hash table with metadata
  *
  * @since Java bindings 1.7.0
@@ -5183,7 +5183,7 @@ public class MajorObject:public java.util.Hashtable GetMetadata_Dict()
  *
  * @param domain the domain of interest.  Use "" or null for the default
  * domain.
- * 
+ *
  * @return null or a vector of strings
  */
 public class MajorObject:public java.util.Vector GetMetadata_List(String domain)
@@ -5192,36 +5192,36 @@ public class MajorObject:public java.util.Vector GetMetadata_List(String domain)
  * Fetch metadata.
  * <p>
  * Returns metadata from the default domain as a vector of strings of the format "KEY=VALUE".
- * 
+ *
  * @return null or a vector of strings
  *
  * @since Java bindings 1.7.0
  */
 public class MajorObject:public java.util.Vector GetMetadata_List()
 
-/** 
- * Set metadata. 
+/**
+ * Set metadata.
  * <p>
  * The metadata is set into the domain specified.
  *
  * @param metadata the metadata as a table of (key, value) tuples to apply
  * @param domain the domain of interest.  Use "" or null for the default
- * domain. 
+ * domain.
  * @return gdalconst.CE_None on success, gdalconst.CE_Failure on failure and gdalconst.CE_Warning if the
- * metadata has been accepted, but is likely not maintained persistently 
+ * metadata has been accepted, but is likely not maintained persistently
  * by the underlying object between sessions.
  */
 
 public class MajorObject:public int SetMetadata(java.util.Hashtable metadata, String domain)
 
 
-/** 
- * Set metadata. 
+/**
+ * Set metadata.
  * <p>
  * The metadata is set into the default domain
  *
  * @return gdalconst.CE_None on success, gdalconst.CE_Failure on failure and gdalconst.CE_Warning if the
- * metadata has been accepted, but is likely not maintained persistently 
+ * metadata has been accepted, but is likely not maintained persistently
  * by the underlying object between sessions.
  *
  * @since Java bindings 1.7.0
@@ -5229,29 +5229,29 @@ public class MajorObject:public int SetMetadata(java.util.Hashtable metadata, St
 
 public class MajorObject:public int SetMetadata(java.util.Hashtable metadata)
 
-/** 
+/**
  * Set metadata.
  * <p>
  * The metadata is set into the domain specified.
  *
  * @param metadataString the metadata to apply as a string of the format "KEY=VALUE".
  * @param domain the domain of interest.  Use "" or null for the default
- * domain. 
+ * domain.
  * @return gdalconst.CE_None on success, gdalconst.CE_Failure on failure and gdalconst.CE_Warning if the
- * metadata has been accepted, but is likely not maintained persistently 
+ * metadata has been accepted, but is likely not maintained persistently
  * by the underlying object between sessions.
  */
 
 public class MajorObject:public int SetMetadata(String metadataString, String domain)
 
-/** 
+/**
  * Set metadata.
  * <p>
  * The metadata is set into the default domain
  *
  * @param metadataString the metadata to apply as a string of the format "KEY=VALUE".
  * @return gdalconst.CE_None on success, gdalconst.CE_Failure on failure and gdalconst.CE_Warning if the
- * metadata has been accepted, but is likely not maintained persistently 
+ * metadata has been accepted, but is likely not maintained persistently
  * by the underlying object between sessions.
  *
  * @since Java bindings 1.7.0
@@ -5259,16 +5259,16 @@ public class MajorObject:public int SetMetadata(String metadataString, String do
 
 public class MajorObject:public int SetMetadata(String metadataString)
 
-/** 
+/**
  * Set metadata.
  * <p>
  * The metadata is set into the domain specified.
  *
  * @param metadata the metadata to apply as a vector of strings of the format "KEY=VALUE".
  * @param domain the domain of interest.  Use "" or null for the default
- * domain. 
+ * domain.
  * @return gdalconst.CE_None on success, gdalconst.CE_Failure on failure and gdalconst.CE_Warning if the
- * metadata has been accepted, but is likely not maintained persistently 
+ * metadata has been accepted, but is likely not maintained persistently
  * by the underlying object between sessions.
  *
  * @since Java bindings 1.7.0
@@ -5276,14 +5276,14 @@ public class MajorObject:public int SetMetadata(String metadataString)
 
 public class MajorObject:public int SetMetadata(java.util.Vector metadata, String domain)
 
-/** 
+/**
  * Set metadata.
  * <p>
  * The metadata is set into the default domain
  *
  * @param metadata the metadata to apply as a vector of strings of the format "KEY=VALUE".
  * @return gdalconst.CE_None on success, gdalconst.CE_Failure on failure and gdalconst.CE_Warning if the
- * metadata has been accepted, but is likely not maintained persistently 
+ * metadata has been accepted, but is likely not maintained persistently
  * by the underlying object between sessions.
  *
  * @since Java bindings 1.7.0
@@ -5358,44 +5358,44 @@ public class Transformer
  * <p>
  * This function creates a transformation object that maps from pixel/line
  * coordinates on one image to pixel/line coordinates on another image.  The
- * images may potentially be georeferenced in different coordinate systems, 
- * and may used GCPs to map between their pixel/line coordinates and 
+ * images may potentially be georeferenced in different coordinate systems,
+ * and may used GCPs to map between their pixel/line coordinates and
  * georeferenced coordinates (as opposed to the default assumption that their
- * geotransform should be used). 
+ * geotransform should be used).
  * <p>
  * This transformer potentially performs three concatenated transformations.
  * <p>
  * The first stage is from source image pixel/line coordinates to source
- * image georeferenced coordinates, and may be done using the geotransform, 
+ * image georeferenced coordinates, and may be done using the geotransform,
  * or if not defined using a polynomial model derived from GCPs.  If GCPs
- * are used this stage is accomplished using GDALGCPTransform(). 
+ * are used this stage is accomplished using GDALGCPTransform().
  * <p>
  * The second stage is to change projections from the source coordinate system
- * to the destination coordinate system, assuming they differ.  This is 
+ * to the destination coordinate system, assuming they differ.  This is
  * accomplished internally using GDALReprojectionTransform().
  * <p>
  * The third stage is converting from destination image georeferenced
  * coordinates to destination image coordinates.  This is done using the
- * destination image geotransform, or if not available, using a polynomial 
- * model derived from GCPs. If GCPs are used this stage is accomplished using 
+ * destination image geotransform, or if not available, using a polynomial
+ * model derived from GCPs. If GCPs are used this stage is accomplished using
  * GDALGCPTransform().  This stage is skipped if dst_ds is null when the
- * transformation is created. 
+ * transformation is created.
  *
  * Supported Options:
  * <ul>
  * <li> SRC_SRS: WKT SRS to be used as an override for src_ds.
  * <li> DST_SRS: WKT SRS to be used as an override for dst_ds.
- * <li> GCPS_OK: If FALSE, GCPs will not be used, default is TRUE. 
+ * <li> GCPS_OK: If FALSE, GCPs will not be used, default is TRUE.
  * <li> MAX_GCP_ORDER: the maximum order to use for GCP derived polynomials if
- * possible.  The default is to autoselect based on the number of GCPs.  
+ * possible.  The default is to autoselect based on the number of GCPs.
  * A value of -1 triggers use of Thin Plate Spline instead of polynomials.
  * <li> METHOD: may have a value which is one of GEOTRANSFORM, GCP_POLYNOMIAL,
  * GCP_TPS, GEOLOC_ARRAY, RPC to force only one geolocation method to be
- * considered on the source dataset. 
+ * considered on the source dataset.
  * <li> RPC_HEIGHT: A fixed height to be used with RPC calculations.
  * <li> RPC_DEM: The name of a DEM file to be used with RPC calculations.
  * </ul>
- * 
+ *
  * @param src_ds source dataset, or null.
  * @param dst_ds destination dataset (or null).
  * @param options options provides as a vector of strings of the format "NAME=VALUE" (or null)
@@ -5454,7 +5454,7 @@ public class Transformer:public int TransformPoint(double[] argout, int bDstToSr
   * @param bDstToSrc 1 for inverse transformation, 0 for forward transformation.
   * @param panSuccess array where to put the success flag for each transformation.
   *                   May be null, otherwise panSuccess.length must be equal to arrayOfCoords.length
-  * 
+  *
   * @return 1 on success, 0 otherwise
   *
   * @since Java bindings 1.7.0
@@ -5558,10 +5558,10 @@ public interface gdalconstConstants:public final static int CPLE_ObjectNull
 /**
  * CPLES_BackslashQuotable(0).
  * <p>
- * This scheme turns a binary string into 
+ * This scheme turns a binary string into
  * a form suitable to be placed within double quotes as a string constant.
- * The backslash, quote, '\\0' and newline characters are all escaped in 
- * the usual C style. 
+ * The backslash, quote, '\\0' and newline characters are all escaped in
+ * the usual C style.
  */
 public interface gdalconstConstants:public final static int CPLES_BackslashQuotable
 
@@ -5570,7 +5570,7 @@ public interface gdalconstConstants:public final static int CPLES_BackslashQuota
  * <p>
  * This scheme converts the '<', '<' and '&' characters into
  * their XML/HTML equivalent (>, < and &) making a string safe
- * to embed as CDATA within an XML element.  The '\\0' is not escaped and 
+ * to embed as CDATA within an XML element.  The '\\0' is not escaped and
  * should not be included in the input.
  */
 public interface gdalconstConstants:public final static int CPLES_XML
@@ -5578,7 +5578,7 @@ public interface gdalconstConstants:public final static int CPLES_XML
 /**
  * CPLES_URL(2).
  * <p>
- * Everything except alphanumerics and the underscore are 
+ * Everything except alphanumerics and the underscore are
  * converted to a percent followed by a two digit hex encoding of the character
  * (leading zero supplied if needed).  This is the mechanism used for encoding
  * values to be passed in URLs.
@@ -5588,7 +5588,7 @@ public interface gdalconstConstants:public final static int CPLES_URL
 /**
  * CPLES_SQL(3).
  * <p>
- * All single quotes are replaced with two single quotes.  
+ * All single quotes are replaced with two single quotes.
  * Suitable for use when constructing literal values for SQL commands where
  * the literal will be enclosed in single quotes.
  */
@@ -5597,10 +5597,10 @@ public interface gdalconstConstants:public final static int CPLES_SQL
 /**
  * CPLES_CSV(4).
  * <p>
- * If the values contains commas, double quotes, or newlines it 
+ * If the values contains commas, double quotes, or newlines it
  * placed in double quotes, and double quotes in the value are doubled.
  * Suitable for use when constructing field values for .csv files.  Note that
- * CPLUnescapeString() currently does not support this format, only 
+ * CPLUnescapeString() currently does not support this format, only
  * CPLEscapeString().  See cpl_csv.cpp for csv parsing support.
  */
 public interface gdalconstConstants:public final static int CPLES_CSV
@@ -5644,7 +5644,7 @@ public interface gdalconstConstants:public final static String DCAP_CREATECOPY
 
 /**
  * DCAP_VIRTUALIO.
- * Driver.GetMetadataItem(gdalconst.DCAP_VIRTUALIO) will return "YES" if the driver supports virtual file IO 
+ * Driver.GetMetadataItem(gdalconst.DCAP_VIRTUALIO) will return "YES" if the driver supports virtual file IO
  */
 public interface gdalconstConstants:public final static String DCAP_VIRTUALIO
 
@@ -5955,11 +5955,11 @@ public class org.gdal.ogr.Driver:public void delete()
 
  @param name the name for the new data source.
  @param options a vector of strings of the format name=value.  Options are driver
-specific, and driver information can be found at the following url:  
+specific, and driver information can be found at the following url:
 <a href="http://www.gdal.org/ogr/ogr_formats.html ">OGR Formats</a>
 
- @return null is returned on failure, or a new DataSource on 
-success. 
+ @return null is returned on failure, or a new DataSource on
+success.
 */
 public class org.gdal.ogr.Driver:public DataSource CreateDataSource(String name, java.util.Vector options)
 
@@ -5981,11 +5981,11 @@ public class org.gdal.ogr.Driver:public DataSource CreateDataSource(String name)
  @param src_ds source datasource
  @param name the name for the new data source.
  @param options a vector of strings of the format name=value.  Options are driver
-specific, and driver information can be found at the following url:  
+specific, and driver information can be found at the following url:
 <a href="http://www.gdal.org/ogr/ogr_formats.html ">OGR Formats</a>
 
- @return null is returned on failure, or a new DataSource on 
-success. 
+ @return null is returned on failure, or a new DataSource on
+success.
 */
 public class org.gdal.ogr.Driver:public DataSource CopyDataSource(DataSource src_ds, String name, java.util.Vector options)
 
@@ -6002,7 +6002,7 @@ public class org.gdal.ogr.Driver:public DataSource CopyDataSource(DataSource src
 public class org.gdal.ogr.Driver:public DataSource CopyDataSource(DataSource src_ds, String name)
 
 /**
-  Attempt to open file with this driver. 
+  Attempt to open file with this driver.
  <p>
  The returned dataset should be properly closed with the
  DataSource.<a href="DataSource.html#delete()">delete()</a> method.
@@ -6017,7 +6017,7 @@ public class org.gdal.ogr.Driver:public DataSource CopyDataSource(DataSource src
 public class org.gdal.ogr.Driver:public DataSource Open(String name, int update)
 
 /**
- * Attempt to open file with this driver. 
+ * Attempt to open file with this driver.
  * <p>
  * Same as below with update == 0.
  *
@@ -6031,12 +6031,12 @@ public class org.gdal.ogr.Driver:public DataSource Open(String name)
  Destroy a datasource.
  <p>
  Destroy the named datasource.  Normally it would be safest if the
- datasource was not open at the time. 
+ datasource was not open at the time.
  <p>
  Whether this is a supported operation on this driver case be tested
  using TestCapability() on ODrCDeleteDataSource.
 
- @param name the name of the datasource to delete. 
+ @param name the name of the datasource to delete.
 
  @return 0 on success. Otherwise throws a RuntimeException if this
  is not supported by this driver (or an error code if DontUseExceptions() has been called)
@@ -6064,7 +6064,7 @@ public class org.gdal.ogr.Driver:public int DeleteDataSource(String name)
 */
 public class org.gdal.ogr.Driver:public boolean TestCapability(String cap)
 
-/** 
+/**
   Fetch name of driver (file format).
  <p>
   This name should be relatively short
@@ -6075,7 +6075,7 @@ public class org.gdal.ogr.Driver:public boolean TestCapability(String cap)
 */
 public class org.gdal.ogr.Driver:public String getName()
 
-/** 
+/**
   Fetch name of driver (file format).
  <p>
   This name should be relatively short
@@ -6087,10 +6087,10 @@ public class org.gdal.ogr.Driver:public String getName()
 public class org.gdal.ogr.Driver:public String GetName()
 
 
-/** 
+/**
   Add a driver to the list of registered drivers.
  <p>
-  If the driver is already registered (based on handle comparison) 
+  If the driver is already registered (based on handle comparison)
   then the driver isn't registered.  New drivers are added at the end of
   the list of registered drivers.
 
@@ -6098,7 +6098,7 @@ public class org.gdal.ogr.Driver:public String GetName()
 */
 public class org.gdal.ogr.Driver:public void Register()
 
-/** 
+/**
   Remove the  driver from the list of registered drivers.
 
   @since GDAL 1.8.0
@@ -6108,7 +6108,7 @@ public class org.gdal.ogr.Driver:public void Deregister()
 /* Class DataSource */
 /**
   * This class represents a data source.
-  * 
+  *
   * <p>
   * The DataSource class is a binding for the C++ <a href="http://gdal.org/ogr/classOGRDataSource.html">OGRDataSource</a> class.
   * <p>
@@ -6145,7 +6145,7 @@ public class DataSource:public void delete()
  @param src_layer source layer.
  @param new_name the name of the layer to create.
  @param options a StringList of name=value options.  Options are driver
-specific, and driver information can be found at the following url:  
+specific, and driver information can be found at the following url:
 <a href="http://www.gdal.org/ogr/ogr_formats.html ">OGR Formats</a>
 
  @return a new layer, or null if an error occurs.
@@ -6168,7 +6168,7 @@ Create a new layer on the data source with the indicated name, coordinate system
 <p>
 The options argument
 can be used to control driver specific creation options.  These options are
-normally documented in the format specific documentation. 
+normally documented in the format specific documentation.
 <p>
 Example:
 
@@ -6188,20 +6188,20 @@ Example:
         if( layer == null )
         {
             ...
-        }        
+        }
 </pre>
 
- @param name the name for the new layer.  This should ideally not 
+ @param name the name for the new layer.  This should ideally not
 match any existing layer on the datasource.
  @param srs the coordinate system to use for the new layer, or null if
-no coordinate system is available. 
+no coordinate system is available.
  @param geom_type the geometry type for the layer.  Use ogr.wkbUnknown if there
-are no constraints on the types geometry to be written. 
+are no constraints on the types geometry to be written.
  @param options a vector of strings of the format name=value.  Options are driver
-specific, and driver information can be found at the following url:  
+specific, and driver information can be found at the following url:
 <a href="http://www.gdal.org/ogr/ogr_formats.html ">OGR Formats</a>
 
- @return null is returned on failure, or a new Layer on success. 
+ @return null is returned on failure, or a new Layer on success.
 */
 public class DataSource:public Layer CreateLayer(String name, SpatialReference srs, int geom_type, java.util.Vector options)
 
@@ -6244,7 +6244,7 @@ public class DataSource:public Layer CreateLayer(String name)
  If this method is supported
  the ODsCDeleteLayer capability will test true on the DataSource.
 
- @param index the index of the layer to delete. 
+ @param index the index of the layer to delete.
 
  @return 0 on success. Otherwise throws a RuntimeException if deleting
  layers is not supported for this datasource  (or an error code if DontUseExceptions() has been called).
@@ -6252,22 +6252,22 @@ public class DataSource:public Layer CreateLayer(String name)
 public class DataSource:public int DeleteLayer(int index)
 
 /**
- Execute an SQL statement against the data store. 
+ Execute an SQL statement against the data store.
  <p>
  The result of an SQL query is either null for statements that are in error,
  or that have no results set, or a Layer representing a results
  set from the query.  Note that this Layer is in addition to the layers
- in the data store and must be destroyed with 
+ in the data store and must be destroyed with
  ReleaseResultsSet() before the data source is closed  (destroyed).
  <p>
  For more information on the SQL dialect supported internally by OGR
  review the <a href="ogr_sql.html">OGR SQL</a> document.  Some drivers (i.e.
  Oracle and PostGIS) pass the SQL directly through to the underlying RDBMS.
 
- @param statement the SQL statement to execute. 
+ @param statement the SQL statement to execute.
  @param spatialFilter geometry which represents a spatial filter.
- @param dialect allows control of the statement dialect.  By default it 
- is assumed to be "generic" SQL, whatever that is. 
+ @param dialect allows control of the statement dialect.  By default it
+ is assumed to be "generic" SQL, whatever that is.
 
  @return a Layer containing the results of the query.  Deallocate with
  ReleaseResultsSet().
@@ -6301,7 +6301,7 @@ public class DataSource:public Layer ExecuteSQL(String statement)
  <p>
  This method should only be used to deallocate Layers resulting from
  an ExecuteSQL() call on the same DataSource.  Failure to deallocate a
- results set before destroying the DataSource may cause errors. 
+ results set before destroying the DataSource may cause errors.
 
  @param layer the result of a previous ExecuteSQL() call.
 */
@@ -6351,13 +6351,13 @@ public class DataSource:public int SyncToDisk()
  @param cap the capability to test.
 
  @return true if capability available otherwise false.
-*/ 
+*/
 public class DataSource:public boolean TestCapability(String cap)
 
 /**
  Fetch a layer by index.
  <p>
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  DataSource and should not be deleted by the application.
 
  @param index a layer number between 0 and GetLayerCount()-1.
@@ -6369,7 +6369,7 @@ public class DataSource:public Layer GetLayerByIndex(int index)
 /**
  Fetch a layer by index.
  <p>
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  DataSource and should not be deleted by the application.
 
  @param index a layer number between 0 and GetLayerCount()-1.
@@ -6383,7 +6383,7 @@ public class DataSource:public Layer GetLayer(int index)
 /**
  Fetch a layer by name.
  <p>
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  DataSource and should not be deleted by the application.
 
  @param layer_name the layer name of the layer to fetch.
@@ -6395,7 +6395,7 @@ public class DataSource:public Layer GetLayerByName(String layer_name)
 /**
  Fetch a layer by name.
 
- The returned layer remains owned by the 
+ The returned layer remains owned by the
  DataSource and should not be deleted by the application.
 
  @param layer_name the layer name of the layer to fetch.
@@ -6413,32 +6413,32 @@ public class DataSource:public Layer GetLayer(String layer_name)
 */
 public class DataSource:public int GetLayerCount()
 
-/** 
+/**
  Returns the name of the data source.
 <p>
  This string should be sufficient to
  open the data source if passed to the same Driver that this data
  source was opened with, but it need not be exactly the same string that
- was used to open the data source.  Normally this is a filename. 
+ was used to open the data source.  Normally this is a filename.
 
  @return name of the data source
 */
 public class DataSource:public String GetName()
 
-/** 
+/**
  Returns the name of the data source.
  <p>
  This string should be sufficient to
  open the data source if passed to the same Driver that this data
  source was opened with, but it need not be exactly the same string that
- was used to open the data source.  Normally this is a filename. 
+ was used to open the data source.  Normally this is a filename.
 
  @return name of the data source
 */
 public class DataSource:public String getName()
 
 /**
-  Returns the driver that the dataset was opened with. 
+  Returns the driver that the dataset was opened with.
 
   @return null if driver info is not available, or the driver
 */
@@ -6481,10 +6481,10 @@ public class Layer:public void delete()
  The passed feature is written to the layer as a new feature, rather than
  overwriting an existing one.  If the feature has a feature id other than
  OGRNullFID, then the native implementation may use that as the feature id
- of the new feature, but not necessarily.  Upon successful return the 
- passed feature will have been updated with the new feature id. 
+ of the new feature, but not necessarily.  Upon successful return the
+ passed feature will have been updated with the new feature id.
 
- @param feature the feature to write to disk. 
+ @param feature the feature to write to disk.
 
  @return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
 
@@ -6508,7 +6508,7 @@ with the OLCCreateField capability. Some drivers may only support this method wh
 there are still no features in the layer. When it is supported, the existing features of the
 backing file/database should be updated accordingly.
 
- at param field_def field definition to write to disk. 
+ at param field_def field definition to write to disk.
 @param approx_ok If 1, the field may be created in a slightly different
 form depending on the limitations of the format driver.
 
@@ -6649,7 +6649,7 @@ public class Layer:public int AlterFieldDefn( int iField, FieldDefn newFieldDefn
  <p>
  Returns the extent (MBR) of the data in the layer.  If force is 0,
  and it would be expensive to establish the extent then a RuntimeException
- will be thrown indicating that the extent is not known.  If force is 
+ will be thrown indicating that the extent is not known.  If force is
  1 then some implementations will actually scan the entire layer once
  to compute the MBR of all the features in the layer.
  <p>
@@ -6673,7 +6673,7 @@ public class Layer:public int GetExtent(double[] extent, int force)
  <p>
  Returns the extent (MBR) of the data in the layer.  If force is false,
  and it would be expensive to establish the extent then a null value
- will be returned indicating that the extent isn't know.  If force is 
+ will be returned indicating that the extent isn't know.  If force is
  true then some implementations will actually scan the entire layer once
  to compute the MBR of all the features in the layer.
  <p>
@@ -6710,10 +6710,10 @@ public class Layer:public double[] GetExtent()
  The feature with the indicated feature id is deleted from the layer if
  supported by the driver.  Most drivers do not support feature deletion,
  and will throw a RuntimeException.  The <a href="#TestCapability(java.lang.String)">TestCapability()</a>
- layer method may be called with OLCDeleteFeature to check if the driver 
+ layer method may be called with OLCDeleteFeature to check if the driver
  supports feature deletion.
 
- @param fid the feature id to be deleted from the layer 
+ @param fid the feature id to be deleted from the layer
 
  @return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
 
@@ -6727,7 +6727,7 @@ public class Layer:public int DeleteFeature(long fid)
  value cannot be OGRNullFID.  Success or failure of this operation is
  unaffected by the spatial or attribute filters.
  <p>
- If this method returns a non-null feature, it is guaranteed that its 
+ If this method returns a non-null feature, it is guaranteed that its
  feature id (Feature.GetFID()) will be the same as fid.
  <p>
  Use Layer.<a href="#TestCapability(java.lang.String)">TestCapability</a>(ogr.OLCRandomRead) to establish if this layer
@@ -6741,27 +6741,27 @@ public class Layer:public int DeleteFeature(long fid)
  but you can help it by explicitly calling the
  Feature.<a href="Feature.html#delete()">delete()</a> method.
 
- @param fid the feature id of the feature to read. 
+ @param fid the feature id of the feature to read.
 
- @return a feature, or null on failure. 
+ @return a feature, or null on failure.
 */
 public class Layer:public Feature GetFeature(long fid)
 
 /**
- Fetch the feature count in this layer. 
+ Fetch the feature count in this layer.
  <p>
  Returns the number of features in the layer.  For dynamic databases the
  count may not be exact.  If force is 0, and it would be expensive
  to establish the feature count a value of -1 may be returned indicating
  that the count isn't know.  If force is 1 some implementations will
- actually scan the entire layer once to count objects. 
+ actually scan the entire layer once to count objects.
  <p>
- The returned count takes the spatial filter into account. 
+ The returned count takes the spatial filter into account.
 
  @param force Flag indicating whether the count should be computed even
  if it is expensive.
 
- @return feature count, -1 if count not known. 
+ @return feature count, -1 if count not known.
 */
 public class Layer:public long GetFeatureCount(int force)
 
@@ -6825,12 +6825,12 @@ public class Layer:public String GetGeometryColumn()
 */
 public class Layer:public int SetIgnoredFields(java.util.Vector fieldNames)
 
-/** 
+/**
  Fetch the schema information for this layer.
  <p>
  The returned FeatureDefn is owned by the Layer, and should not be
  modified or freed by the application.  It encapsulates the attribute schema
- of the features of the layer. 
+ of the features of the layer.
 
  @return feature definition.
 */
@@ -6863,17 +6863,17 @@ public class Layer:public int GetGeomType()
 /**
  Fetch the next available feature from this layer.
  <p>
- Only features matching the current spatial filter (set with 
- <a href="#SetSpatialFilter(org.gdal.ogr.Geometry)")>SetSpatialFilter()</a> will be returned. 
+ Only features matching the current spatial filter (set with
+ <a href="#SetSpatialFilter(org.gdal.ogr.Geometry)")>SetSpatialFilter()</a> will be returned.
  <p>
  This method implements sequential access to the features of a layer.  The
- ResetReading() method can be used to start at the beginning again.  
+ ResetReading() method can be used to start at the beginning again.
  <p>
  The returned feature will be properly handled by the Java garbage collector,
  but you can help it by explicitly calling the
  Feature.<a href="Feature.html#delete()">delete()</a> method.
 
- @return a feature, or null if no more features are available. 
+ @return a feature, or null if no more features are available.
 */
 public class Layer:public Feature GetNextFeature()
 
@@ -6894,22 +6894,22 @@ public class Layer:public int GetRefCount()
 public class Layer:public Geometry GetSpatialFilter()
 
 /**
- Fetch the spatial reference system for this layer. 
+ Fetch the spatial reference system for this layer.
 
  @return spatial reference, or null if there isn't one.
 */
 public class Layer:public SpatialReference GetSpatialRef()
 
 /**
- Reset feature reading to start on the first feature.  This affects 
+ Reset feature reading to start on the first feature.  This affects
  GetNextFeature().
 */
 public class Layer:public void ResetReading()
 
-/** 
+/**
  Set a new attribute query.
  <p>
- This method sets the attribute query string to be used when 
+ This method sets the attribute query string to be used when
  fetching features via the <a href="#GetNextFeature()">GetNextFeature()</a> method.  Only features for which
  the query evaluates as true will be returned.
  <p>
@@ -6922,7 +6922,7 @@ public class Layer:public void ResetReading()
    <a href="http://ogdi.sourceforge.net/prop/6.2.CapabilitiesMetadata.html">Proposal 6.2: Capabilities Metadata</a>
   </pre>
  Note that installing a query string will generally result in resetting
- the current reading position (ala <a href="#ResetReading()">ResetReading()</a>).  
+ the current reading position (ala <a href="#ResetReading()">ResetReading()</a>).
 
  @param filter_string query in restricted SQL WHERE format, or null to clear the
  current query.
@@ -6949,49 +6949,49 @@ public class Layer:public int SetAttributeFilter(String filter_string)
 public class Layer:public int SetFeature(Feature feature)
 
 /**
- Move read cursor to the new_index'th feature in the current resultset. 
+ Move read cursor to the new_index'th feature in the current resultset.
  <p>
  This method allows positioning of a layer such that the <a href="#GetNextFeature()">GetNextFeature()</a>
  call will read the requested feature, where nIndex is an absolute index
  into the current result set.   So, setting it to 3 would mean the next
  feature read with GetNextFeature() would have been the 4th feature to have
  been read if sequential reading took place from the beginning of the layer,
- including accounting for spatial and attribute filters. 
+ including accounting for spatial and attribute filters.
  <p>
- Only in rare circumstances is SetNextByIndex() efficiently implemented.  
+ Only in rare circumstances is SetNextByIndex() efficiently implemented.
  In all other cases the default implementation which calls ResetReading()
- and then calls GetNextFeature() nIndex times is used.  To determine if 
+ and then calls GetNextFeature() nIndex times is used.  To determine if
  fast seeking is available on the current layer use the TestCapability()
- method with a value of OLCFastSetNextByIndex.  
+ method with a value of OLCFastSetNextByIndex.
 
  @param new_index the index indicating how many steps into the result set
- to seek. 
+ to seek.
 
  @return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
 */
 public class Layer:public int SetNextByIndex(long new_index)
 
 
-/** 
- Set a new spatial filter. 
+/**
+ Set a new spatial filter.
  <p>
- This method set the geometry to be used as a spatial filter when 
+ This method set the geometry to be used as a spatial filter when
  fetching features via the <a href="#GetNextFeature()">GetNextFeature()</a> method.  Only features that
- geometrically intersect the filter geometry will be returned.  
+ geometrically intersect the filter geometry will be returned.
  <p>
  Currently this test is may be inaccurately implemented, but it is
  guaranteed that all features who's envelope (as returned by
  Geometry.getEnvelope()) overlaps the envelope of the spatial filter
- will be returned.  This can result in more shapes being returned that 
- should strictly be the case. 
+ will be returned.  This can result in more shapes being returned that
+ should strictly be the case.
  <p>
- This method makes an internal copy of the passed geometry. The 
- passed geometry remains the responsibility of the caller, and may 
- be safely destroyed. 
+ This method makes an internal copy of the passed geometry. The
+ passed geometry remains the responsibility of the caller, and may
+ be safely destroyed.
  <p>
  For the time being the passed filter geometry should be in the same
  SRS as the layer (as returned by <a href="#GetSpatialRef()">GetSpatialRef()</a>).  In the
- future this may be generalized. 
+ future this may be generalized.
 
  @param filter the geometry to use as a filtering region.  null may
  be passed indicating that the current spatial filter should be cleared,
@@ -6999,21 +6999,21 @@ public class Layer:public int SetNextByIndex(long new_index)
  */
 public class Layer:public void SetSpatialFilter(Geometry filter)
 
-/** 
- Set a new rectangular spatial filter. 
+/**
+ Set a new rectangular spatial filter.
 
- This method set rectangle to be used as a spatial filter when 
+ This method set rectangle to be used as a spatial filter when
  fetching features via the <a href="#GetNextFeature()">GetNextFeature()</a> method method.  Only features that
- geometrically intersect the given rectangle will be returned.  
+ geometrically intersect the given rectangle will be returned.
  <p>
  The x/y values should be in the same coordinate system as the layer as
- a whole (as returned by <a href="#GetSpatialRef()">GetSpatialRef()</a>).   Internally this 
+ a whole (as returned by <a href="#GetSpatialRef()">GetSpatialRef()</a>).   Internally this
  method is normally implemented as creating a 5 vertex closed rectangular
  polygon and passing it to <a href="#SetSpatialFilter(org.gdal.ogr.Geometry)">SetSpatialFilter()</a>.  It exists as
- a convenience. 
+ a convenience.
  <p>
- The only way to clear a spatial filter set with this method is to 
- call SetSpatialFilter(null). 
+ The only way to clear a spatial filter set with this method is to
+ call SetSpatialFilter(null).
 
  @param minx the minimum X coordinate for the rectangular region.
  @param miny the minimum Y coordinate for the rectangular region.
@@ -7027,9 +7027,9 @@ Flush pending changes to disk.
 <p>
 This call is intended to force the layer to flush any pending writes to
 disk, and leave the disk file in a consistent state.  It would not normally
-have any effect on read-only datasources. 
+have any effect on read-only datasources.
 <p>
-Some layers do not implement this method, and will still return 
+Some layers do not implement this method, and will still return
 0.  The default implementation just returns 0.  An error
 is only returned if an error occurs while attempting to flush to disk.
 
@@ -7038,7 +7038,7 @@ is only returned if an error occurs while attempting to flush to disk.
 public class Layer:public int SyncToDisk()
 
 /**
- For datasources which support transactions, StartTransaction creates 
+ For datasources which support transactions, StartTransaction creates
  a transaction.
  <p>
  If starting the transaction fails, will throw a RuntimeException (or an error code if DontUseExceptions() has been called).
@@ -7049,7 +7049,7 @@ public class Layer:public int SyncToDisk()
 public class Layer:public int StartTransaction()
 
 /**
- For datasources which support transactions, CommitTransaction commits a 
+ For datasources which support transactions, CommitTransaction commits a
  transaction.
  <p>
  If no transaction is active, or the commit fails, will throw a RuntimeException (or an error code if DontUseExceptions() has been called).
@@ -7061,7 +7061,7 @@ public class Layer:public int CommitTransaction()
 
 /**
 
- For datasources which support transactions, RollbackTransaction will roll 
+ For datasources which support transactions, RollbackTransaction will roll
  back a datasource to its state before the start of the current transaction.
  <p>
  If no transaction is active, or the rollback fails, will throw a RuntimeException (or an error code if DontUseExceptions() has been called).
@@ -7075,47 +7075,47 @@ public class Layer:public int RollbackTransaction()
  Test if this layer supported the named capability.
  <p>
  The capability codes that can be tested are represented as strings, but
- ogrConstants constants exists to ensure correct spelling.  Specific layer 
+ ogrConstants constants exists to ensure correct spelling.  Specific layer
  types may implement class specific capabilities, but this can't generally
  be discovered by the caller. <p>
 
 <ul>
 
- <li> <b>OLCRandomRead</b> / "RandomRead": true if the GetFeature() method 
+ <li> <b>OLCRandomRead</b> / "RandomRead": true if the GetFeature() method
 is implemented in an optimized way for this layer, as opposed to the default
 implementation using ResetReading() and GetNextFeature() to find the requested
 feature id.<p>
 
- <li> <b>OLCSequentialWrite</b> / "SequentialWrite": true if the 
-CreateFeature() method works for this layer.  Note this means that this 
-particular layer is writable.  The same Layer class  may returned false 
+ <li> <b>OLCSequentialWrite</b> / "SequentialWrite": true if the
+CreateFeature() method works for this layer.  Note this means that this
+particular layer is writable.  The same Layer class  may returned false
 for other layer instances that are effectively read-only.<p>
 
  <li> <b>OLCRandomWrite</b> / "RandomWrite": true if the SetFeature() method
-is operational on this layer.   Note this means that this 
-particular layer is writable.  The same Layer class  may returned false 
+is operational on this layer.   Note this means that this
+particular layer is writable.  The same Layer class  may returned false
 for other layer instances that are effectively read-only.<p>
 
  <li> <b>OLCFastSpatialFilter</b> / "FastSpatialFilter": true if this layer
 implements spatial filtering efficiently.  Layers that effectively read all
 features, and test them with the Feature intersection methods should
-return false.  This can be used as a clue by the application whether it 
+return false.  This can be used as a clue by the application whether it
 should build and maintain it's own spatial index for features in this layer.<p>
 
- <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount": 
+ <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount":
 true if this layer can return a feature
 count (via GetFeatureCount()) efficiently, i.e. without counting
 the features.  In some cases this will return true until a spatial filter is
 installed after which it will return false.<p>
 
- <li> <b>OLCFastGetExtent</b> / "FastGetExtent": 
+ <li> <b>OLCFastGetExtent</b> / "FastGetExtent":
 true if this layer can return its data extent (via GetExtent()) efficiently, i.e. without scanning all the features.  In some cases this will return true until a spatial filter is installed after which it will return false.<p>
 
- <li> <b>OLCFastSetNextByIndex</b> / "FastSetNextByIndex": 
+ <li> <b>OLCFastSetNextByIndex</b> / "FastSetNextByIndex":
 true if this layer can perform the SetNextByIndex() call efficiently, otherwise
 false.<p>
 
- <li> <b>OLCCreateField</b> / "CreateField": true if this layer can create 
+ <li> <b>OLCCreateField</b> / "CreateField": true if this layer can create
 new fields on the current layer using CreateField(), otherwise false.<p>
 
  <li> <b>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
@@ -7131,11 +7131,11 @@ the definition of an existing field on the current layer using AlterFieldDefn(),
 method is supported on this layer, otherwise false.<p>
 
  <li> <b>OLCStringsAsUTF8</b> / "StringsAsUTF8": true if values of OFTString
-fields are assured to be in UTF-8 format.  If false the encoding of fields 
+fields are assured to be in UTF-8 format.  If false the encoding of fields
 is uncertain, though it might still be UTF-8.<p>
 
  <li> <b>OLCStringsAsUTF8</b> / "StringsAsUTF8": true if values of OFTString
-fields are assured to be in UTF-8 format.  If false the encoding of fields 
+fields are assured to be in UTF-8 format.  If false the encoding of fields
 is uncertain, though it might still be UTF-8.<p>
 
 <li> <b>OLCTransactions</b> / "Transactions": true if the StartTransaction(), CommitTransaction() and RollbackTransaction() methods work in a meaningful way, otherwise false.<p>
@@ -7800,9 +7800,9 @@ public class Feature:public FieldDefn GetFieldDefnRef(String name)
 /**
  * Fetch the field index given field name.
  *
- * This is a cover for the FeatureDefn.GetFieldIndex() method. 
+ * This is a cover for the FeatureDefn.GetFieldIndex() method.
  *
- * @param name the name of the field to search for. 
+ * @param name the name of the field to search for.
  *
  * @return the field index, or -1 if no matching field is found.
  */
@@ -7811,7 +7811,7 @@ public class Feature:public int GetFieldIndex(String name)
 /**
  * Fetch the field type.
  * <p>
- * This is a cover for the FeatureDefn.GetFieldType() method. 
+ * This is a cover for the FeatureDefn.GetFieldType() method.
  *
  * @param ifield the field to fetch, from 0 to GetFieldCount()-1.
  *
@@ -7822,7 +7822,7 @@ public class Feature:public int GetFieldType(int ifield)
 /**
  * Fetch the field type.
  * <p>
- * This is a cover for the FeatureDefn.GetFieldType() method. 
+ * This is a cover for the FeatureDefn.GetFieldType() method.
  *
  * @param name the name of the field to fetch.
  *
@@ -7843,9 +7843,9 @@ public class Feature:public Geometry GetGeometryRef()
  * <p>
  * Set the OGR Feature Style Specification for details on the format of
  * this string, and ogr_featurestyle.h for services available to parse it.
- * 
- * @return a reference to a representation in string format, or null if 
- * there isn't one. 
+ *
+ * @return a reference to a representation in string format, or null if
+ * there isn't one.
  */
 public class Feature:public String GetStyleString()
 
@@ -7882,7 +7882,7 @@ public class Feature:public boolean IsFieldSet(String name)
 public class Feature:public int SetFID(long fid)
 
 /**
- * Set field to double value. 
+ * Set field to double value.
  * <p>
  * OFTInteger and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -7895,7 +7895,7 @@ public class Feature:public int SetFID(long fid)
 public class Feature:public void SetField(int ifield, double val)
 
 /**
- * Set field to integer value. 
+ * Set field to integer value.
  * <p>
  * OFTInteger and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -7925,7 +7925,7 @@ public class Feature:public void SetField(int ifield, int val)
 public class Feature:public void SetField(int ifield, int year, int month, int day, int hour, int minute, int second, int tzflag)
 
 /**
- * Set field to string value. 
+ * Set field to string value.
  * <p>
  * OFTInteger fields will be set based on an atoi() conversion of the string.
  * OFTReal fields will be set based on an atof() conversion of the string.
@@ -7937,7 +7937,7 @@ public class Feature:public void SetField(int ifield, int year, int month, int d
 public class Feature:public void SetField(int ifield, String val)
 
 /**
- * Set field to double value. 
+ * Set field to double value.
  * <p>
  * OFTInteger and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -7950,7 +7950,7 @@ public class Feature:public void SetField(int ifield, String val)
 public class Feature:public void SetField(String name, double val)
 
 /**
- * Set field to integer value. 
+ * Set field to integer value.
  * <p>
  * OFTInteger and OFTReal fields will be set directly.  OFTString fields
  * will be assigned a string representation of the value, but not necessarily
@@ -7980,7 +7980,7 @@ public class Feature:public void SetField(String name, int val)
 public class Feature:public void SetField(String name, int year, int month, int day, int hour, int minute, int second, int tzflag)
 
 /**
- * Set field to string value. 
+ * Set field to string value.
  * <p>
  * OFTInteger fields will be set based on an atoi() conversion of the string.
  * OFTReal fields will be set based on an atof() conversion of the string.
@@ -7992,7 +7992,7 @@ public class Feature:public void SetField(String name, int year, int month, int
 public class Feature:public void SetField(String name, String val)
 
 /**
- * Set field to list of doubles value. 
+ * Set field to list of doubles value.
  * <p>
  * This method currently on has an effect of OFTRealList fields.
  *
@@ -8003,7 +8003,7 @@ public class Feature:public void SetField(String name, String val)
 public class Feature:public void SetFieldDoubleList(int ifield, double[] values)
 
 /**
- * Set field to list of integers value. 
+ * Set field to list of integers value.
  * <p>
  * This method currently on has an effect of OFTIntegerList fields.
  *
@@ -8013,7 +8013,7 @@ public class Feature:public void SetFieldDoubleList(int ifield, double[] values)
 public class Feature:public void SetFieldIntegerList(int ifield, int[] values)
 
 /**
- * Set field to list of strings value. 
+ * Set field to list of strings value.
  * <p>
  * This method currently on has an effect of OFTStringList fields.
  *
@@ -8096,7 +8096,7 @@ public class Feature:public int SetFromWithMap(Feature srcFeature, int forgiving
  * <p>
  * This method updates the features geometry, and operate exactly as
  * SetGeometryDirectly(), except that this method does not assume ownership
- * of the passed geometry, but instead makes a copy of it. 
+ * of the passed geometry, but instead makes a copy of it.
  *
  * @param geom new geometry to apply to feature. Passing null value here
  * is correct and it will result in deallocation of currently assigned geometry
@@ -8104,8 +8104,8 @@ public class Feature:public int SetFromWithMap(Feature srcFeature, int forgiving
  *
  * @return 0 if successful, or throws a RuntimeException (or an error code if DontUseExceptions() has been called) if
  * the geometry type is illegal for the FeatureDefn (checking not yet
- * implemented). 
- */ 
+ * implemented).
+ */
 public class Feature:public int SetGeometry(Geometry geom)
 
 /**
@@ -8121,8 +8121,8 @@ public class Feature:public int SetGeometry(Geometry geom)
  *
  * @return 0 if successful, or throws a RuntimeException (or an error code if DontUseExceptions() has been called) if
  * the geometry type is illegal for the FeatureDefn (checking not yet
- * implemented). 
- */ 
+ * implemented).
+ */
 public class Feature:public int SetGeometryDirectly(Geometry geom)
 
 /**
@@ -8165,7 +8165,7 @@ public class Feature:public void UnsetField(String name)
  */
 public class Geometry
 
-/** 
+/**
  * Create an empty geometry of desired type.
  * <p>
  * The type may be one of ogr.wkbPoint, etc..
@@ -8176,7 +8176,7 @@ public class Geometry
  */
 public class Geometry:public Geometry(int eGeometryType)
 
-/** 
+/**
  * Create a new geometry.
  * <p>
  * The geometry can be instantiated by 4 different and exclusive way:
@@ -8287,7 +8287,7 @@ public class Geometry:public void AddPoint(double x, double y)
  * is replaced, but under no circumstances does this result in the object
  * being reprojected.  It is just changing the interpretation of the existing
  * geometry.  Note that assigning a spatial reference increments the
- * reference count on the SpatialReference, but does not copy it. 
+ * reference count on the SpatialReference, but does not copy it.
  *
  * This is similar to the SFCOM IGeometry::put_SpatialReference() method.
  *
@@ -8301,25 +8301,25 @@ public class Geometry:public void AssignSpatialReference(SpatialReference srs)
  * <p>
  * Builds a new geometry containing the buffer region around the geometry
  * on which it is invoked.  The buffer is a polygon containing the region within
- * the buffer distance of the original geometry.  
+ * the buffer distance of the original geometry.
  * <p>
  * Some buffer sections are properly described as curves, but are converted to
  * approximate polygons.  The nQuadSegs parameter can be used to control how many
- * segements should be used to define a 90 degree curve - a quadrant of a circle. 
+ * segments should be used to define a 90 degree curve - a quadrant of a circle.
  * A value of 30 is a reasonable default.  Large values result in large numbers
- * of vertices in the resulting buffer geometry while small numbers reduce the 
- * accuracy of the result. 
+ * of vertices in the resulting buffer geometry while small numbers reduce the
+ * accuracy of the result.
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
  * If OGR is built without the GEOS library, this method will always fail.
  *
- * @param distance the buffer distance to be applied. 
+ * @param distance the buffer distance to be applied.
  *
  * @param quadsecs the number of segments used to approximate a 90 degree (quadrant) of
- * curvature. 
+ * curvature.
  *
- * @return the newly created geometry, or null if an error occurs. 
+ * @return the newly created geometry, or null if an error occurs.
  */
 public class Geometry:public Geometry Buffer(double distance, int quadsecs)
 
@@ -8337,7 +8337,7 @@ public class Geometry:public Geometry Buffer(double distance)
 /**
  * Compute the geometry centroid.
  *
- * The centroid is not necessarily within the geometry.  
+ * The centroid is not necessarily within the geometry.
  * <p>
  * This method relates to the SFCOM ISurface::get_Centroid() method
  * however the current implementation based on GEOS can operate on other
@@ -8348,8 +8348,8 @@ public class Geometry:public Geometry Buffer(double distance)
  * <p>
  * This function is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this function will always fail, 
- * issuing a CPLE_NotSupported error. 
+ * If OGR is built without the GEOS library, this function will always fail,
+ * issuing a CPLE_NotSupported error.
  *
  * @return point with the centroid location, or null in case of failure
  */
@@ -8359,7 +8359,7 @@ public class Geometry:public Geometry Centroid()
  * Make a copy of this object.
  * <p>
  * This method relates to the SFCOM IGeometry::clone() method.
- * 
+ *
  * @return a new object instance with the same geometry, and spatial
  * reference system as the original.
  */
@@ -8368,9 +8368,9 @@ public class Geometry:public Geometry Clone()
 /**
  * Force rings to be closed.
  * <p>
- * If this geometry, or any contained geometries has polygon rings that 
+ * If this geometry, or any contained geometries has polygon rings that
  * are not closed, they will be closed by adding the starting point at
- * the end. 
+ * the end.
  */
 public class Geometry:public void CloseRings()
 
@@ -8393,7 +8393,7 @@ public class Geometry:public boolean Contains(Geometry other)
  * Compute convex hull.
  * <p>
  * A new geometry object is created and returned containing the convex
- * hull of the geometry on which the method is invoked.  
+ * hull of the geometry on which the method is invoked.
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
@@ -8409,7 +8409,7 @@ public class Geometry:public Geometry ConvexHull()
  * This method translates a fragment of GML containing only the geometry
  * portion into a corresponding Geometry.  There are many limitations
  * on the forms of GML geometries supported by this parser, but they are
- * too numerous to list here. 
+ * too numerous to list here.
  *
  * @param gml The GML fragment for the geometry.
  *
@@ -8484,7 +8484,7 @@ public class Geometry:public void delete()
  * Compute difference.
  * <p>
  * Generates a new geometry which is the region of this geometry with the
- * region of the second geometry removed. 
+ * region of the second geometry removed.
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
@@ -8492,7 +8492,7 @@ public class Geometry:public void delete()
  *
  * @param other the other geometry removed from "this" geometry.
  *
- * @return a new geometry representing the difference or null if the 
+ * @return a new geometry representing the difference or null if the
  * difference is empty or an error occurs.
  */
 public class Geometry:public Geometry Difference(Geometry other)
@@ -8500,7 +8500,7 @@ public class Geometry:public Geometry Difference(Geometry other)
 /**
  * Test for disjointness.
  * <p>
- * Tests if this geometry and the other passed into the method are disjoint. 
+ * Tests if this geometry and the other passed into the method are disjoint.
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
@@ -8515,7 +8515,7 @@ public class Geometry:public boolean Disjoint(Geometry other)
 /**
  * Compute distance between two geometries.
  * <p>
- * Returns the shortest distance between the two geometries. 
+ * Returns the shortest distance between the two geometries.
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
@@ -8781,7 +8781,7 @@ public class Geometry:public int GetGeometryCount()
 /**
  * Fetch WKT name for geometry type.
  * <p>
- * There is no SFCOM analog to this method.  
+ * There is no SFCOM analog to this method.
  *
  * @return name used for this geometry type in well known text format.
  */
@@ -8795,7 +8795,7 @@ public class Geometry:public String GetGeometryName()
  * modified.  The handle is only valid until the next change to the
  * geometry container.  Use Clone() to make a copy.
  * <p>
- * This function relates to the SFCOM 
+ * This function relates to the SFCOM
  * IGeometryCollection::get_Geometry() method.
  * <p>
  * For a polygon, OGR_G_GetGeometryRef(iSubGeom) returns the exterior ring
@@ -8910,7 +8910,7 @@ public class Geometry:public SpatialReference GetSpatialReference()
  * Fetch the x coordinate of a point from a geometry.
  *
  * @param ipoint point to get the x coordinate. (must be 0 for a point geometry)
- * @return the X coordinate of this point. 
+ * @return the X coordinate of this point.
  */
 public class Geometry:public double GetX(int ipoint)
 
@@ -8918,7 +8918,7 @@ public class Geometry:public double GetX(int ipoint)
  * Fetch the y coordinate of a point from a geometry.
  *
  * @param ipoint point to get the y coordinate. (must be 0 for a point geometry)
- * @return the Y coordinate of this point. 
+ * @return the Y coordinate of this point.
  */
 public class Geometry:public double GetY(int ipoint)
 
@@ -8926,14 +8926,14 @@ public class Geometry:public double GetY(int ipoint)
  * Fetch the z coordinate of a point from a geometry.
  *
  * @param ipoint point to get the z coordinate. (must be 0 for a point geometry)
- * @return the Z coordinate of this point. 
+ * @return the Z coordinate of this point.
  */
 public class Geometry:public double GetZ(int ipoint)
 
 /**
  * Fetch the x coordinate of the first point from a geometry.
  *
- * @return the X coordinate of this point. 
+ * @return the X coordinate of this point.
  *
  * @since Java bindings 1.7.0
  */
@@ -8942,7 +8942,7 @@ public class Geometry:public double GetX()
 /**
  * Fetch the y coordinate of the first point from a geometry.
  *
- * @return the Y coordinate of this point. 
+ * @return the Y coordinate of this point.
  *
  * @since Java bindings 1.7.0
  */
@@ -8951,7 +8951,7 @@ public class Geometry:public double GetY()
 /**
  * Fetch the z coordinate of the first point from a geometry.
  *
- * @return the Z coordinate of this point. 
+ * @return the Z coordinate of this point.
  *
  * @since Java bindings 1.7.0
  */
@@ -8990,7 +8990,7 @@ public class Geometry:public boolean Intersects(Geometry other)
  * <p>
  * Generates a new geometry which is the region of intersection of the
  * two geometries operated on.  The Intersects() method can be used to test if
- * two geometries intersect. 
+ * two geometries intersect.
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
@@ -9023,11 +9023,11 @@ public class Geometry:public boolean IsEmpty()
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always return 
- * false. 
+ * If OGR is built without the GEOS library, this method will always return
+ * false.
  *
  *
- * @return true if the geometry has no points, otherwise false.  
+ * @return true if the geometry has no points, otherwise false.
  */
 
 public class Geometry:public boolean IsValid()
@@ -9037,11 +9037,11 @@ public class Geometry:public boolean IsValid()
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always return 
- * false. 
+ * If OGR is built without the GEOS library, this method will always return
+ * false.
  *
  *
- * @return true if the geometry has no points, otherwise false.  
+ * @return true if the geometry has no points, otherwise false.
  */
 public class Geometry:public boolean IsSimple()
 
@@ -9050,11 +9050,11 @@ public class Geometry:public boolean IsSimple()
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
- * If OGR is built without the GEOS library, this method will always return 
- * false. 
+ * If OGR is built without the GEOS library, this method will always return
+ * false.
  *
  *
- * @return true if the geometry has no points, otherwise false.  
+ * @return true if the geometry has no points, otherwise false.
  */
 public class Geometry:public boolean IsRing()
 
@@ -9062,7 +9062,7 @@ public class Geometry:public boolean IsRing()
  * Test for overlap.
  * <p>
  * Tests if this geometry and the other passed into the method overlap, that is
- * their intersection has a non-zero area. 
+ * their intersection has a non-zero area.
  *
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
@@ -9070,7 +9070,7 @@ public class Geometry:public boolean IsRing()
  *
  * @param other the geometry to compare to this geometry.
  *
- * @return true if they are overlapping, otherwise false.  
+ * @return true if they are overlapping, otherwise false.
  */
 public class Geometry:public boolean Overlaps(Geometry other)
 
@@ -9087,12 +9087,12 @@ public class Geometry:public boolean Overlaps(Geometry other)
 public class Geometry:public void Segmentize(double max_length)
 
 /**
- * Set the coordinate dimension. 
+ * Set the coordinate dimension.
  * <p>
  * This method sets the explicit coordinate dimension.  Setting the coordinate
  * dimension of a geometry to 2 should zero out any existing Z values.  Setting
  * the dimension of a geometry collection will not necessarily affect the
- * children geometries. 
+ * children geometries.
  *
  * @param dimension New coordinate dimension value, either 2 or 3.
  */
@@ -9188,7 +9188,7 @@ public class Geometry:public Geometry SimplifyPreserveTopology(double dTolerance
  *
  * @param other the other geometry.
  *
- * @return a new geometry representing the symmetric difference or null if the 
+ * @return a new geometry representing the symmetric difference or null if the
  * difference is empty or an error occurs.
  *
  * @since OGR 1.8.0
@@ -9215,7 +9215,7 @@ public class Geometry:public Geometry SymmetricDifference(Geometry other)
  *
  * @param other the geometry to compare to this geometry.
  *
- * @return true if they are touching, otherwise false.  
+ * @return true if they are touching, otherwise false.
  */
 public class Geometry:public boolean Touches(Geometry other)
 
@@ -9225,7 +9225,7 @@ public class Geometry:public boolean Touches(Geometry other)
  * This method will transform the coordinates of a geometry from
  * their current spatial reference system to a new target spatial
  * reference system.  Normally this means reprojecting the vectors,
- * but it could include datum shifts, and changes of units. 
+ * but it could include datum shifts, and changes of units.
  * <p>
  * This method will only work if the geometry already has an assigned
  * spatial reference system, and if it is transformable to the target
@@ -9237,7 +9237,7 @@ public class Geometry:public boolean Touches(Geometry other)
  * CoordinateTransformation in advance, and call transform() with that
  * transformation.  This method exists primarily for convenience when only
  * transforming a single geometry.
- * 
+ *
  * @param srs spatial reference system to transform to.
  *
  * @return 0 on success. Otherwise throws a RuntimeException (or an error code if DontUseExceptions() has been called).
@@ -9251,7 +9251,7 @@ public class Geometry:public int TransformTo(SpatialReference srs)
  * This method will transform the coordinates of a geometry from
  * their current spatial reference system to a new target spatial
  * reference system.  Normally this means reprojecting the vectors,
- * but it could include datum shifts, and changes of units. 
+ * but it could include datum shifts, and changes of units.
  * <p>
  * Note that this method does not require that the geometry already
  * have a spatial reference system.  It will be assumed that they can
@@ -9270,7 +9270,7 @@ public class Geometry:public int Transform(CoordinateTransformation ct)
  * Compute union.
  * <p>
  * Generates a new geometry which is the region of union of the
- * two geometries operated on.  
+ * two geometries operated on.
  * <p>
  * This method is built on the GEOS library, check it for the definition
  * of the geometry operation.
@@ -9345,7 +9345,7 @@ public class Geometry:public double Length()
  * <p>
  * This object also can contain some other information such as a name, the base geometry type and potentially other metadata.
  * <p>
- * It is reasonable for different translators to derive classes from FeatureDefn with additional translator specific information. 
+ * It is reasonable for different translators to derive classes from FeatureDefn with additional translator specific information.
  */
 public class FeatureDefn
 
@@ -9467,7 +9467,7 @@ public class FeatureDefn:public void SetStyleIgnored(int bIgnore)
  * wkbNone indicates no geometry is available for the layer at all.
  * Many drivers do not properly mark the geometry
  * type as 25D even if some or all geometries are in fact 25D.  A few (broken)
- * drivers return wkbPolygon for layers that also include wkbMultiPolygon.  
+ * drivers return wkbPolygon for layers that also include wkbMultiPolygon.
  *
  * @return the base type for all geometry related to this definition.
  */
@@ -9479,7 +9479,7 @@ public class FeatureDefn:public int GetGeomType()
  * All geometry objects using this type must be of the defined type or
  * a derived type.  The default upon creation is wkbUnknown which allows for
  * any geometry type.  The geometry type should generally not be changed
- * after any Features have been created against this definition. 
+ * after any Features have been created against this definition.
  *
  * @param geom_type the new type to assign.
  */
@@ -9587,7 +9587,7 @@ public class FieldDefn:public String GetTypeName()
 /**
  * Get the formatting width for this field.
  *
- * @return the width, zero means no specified width. 
+ * @return the width, zero means no specified width.
  */
 public class FieldDefn:public int GetWidth()
 
@@ -9608,9 +9608,9 @@ public class FieldDefn:public void SetName(String name)
 /**
  * Set the formatting precision for this field in characters.
  *  <p>
- * This should normally be zero for fields of types other than OFTReal. 
+ * This should normally be zero for fields of types other than OFTReal.
  *
- * @param precision the new precision. 
+ * @param precision the new precision.
  */
 public class FieldDefn:public void SetPrecision(int precision)
 
@@ -9629,7 +9629,7 @@ public class FieldDefn:public void SetType(int type)
  *
  * @param width the new width.
  */
-public class FieldDefn:public void SetWidth(int width) 
+public class FieldDefn:public void SetWidth(int width)
 
 /**
  * Return whether this field should be omitted when fetching features.
@@ -9647,7 +9647,7 @@ public class FieldDefn:public int IsIgnored()
  *
  * @since OGR 1.8.0
  */
-public class FieldDefn:public void SetIgnored(int bIgnored) 
+public class FieldDefn:public void SetIgnored(int bIgnored)
 
 /* Class ogr */
 
@@ -9695,17 +9695,17 @@ public class ogr:public static void DontUseExceptions()
  * @param dfCenterY center Y
  * @param dfZ center Z
  * @param dfPrimaryRadius X radius of ellipse.
- * @param dfSecondaryRadius Y radius of ellipse. 
+ * @param dfSecondaryRadius Y radius of ellipse.
  * @param dfRotation rotation of the ellipse clockwise.
- * @param dfStartAngle angle to first point on arc (clockwise of X-positive) 
- * @param dfEndAngle angle to last point on arc (clockwise of X-positive) 
+ * @param dfStartAngle angle to first point on arc (clockwise of X-positive)
+ * @param dfEndAngle angle to last point on arc (clockwise of X-positive)
  * @param dfMaxAngleStepSizeDegrees the largest step in degrees along the arc.
- * 
+ *
  * @return LineString geometry representing an approximation of the arc.
  *
  * @since Java bindings 1.7.0
  */
-public class ogr:public static Geometry ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, double dfSecondaryRadius, double dfRotation, double dfStartAngle, double dfEndAngle, double dfMaxAngleStepSizeDegrees) 
+public class ogr:public static Geometry ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, double dfSecondaryRadius, double dfRotation, double dfStartAngle, double dfEndAngle, double dfMaxAngleStepSizeDegrees)
 
 /**
  * Build a ring from a bunch of arcs.
@@ -9800,25 +9800,25 @@ public class ogr:public static Geometry CreateGeometryFromWkt(String wkt, Spatia
    /**
     * General utility option processing.
     * <p>
-    * This function is intended to provide a variety of generic commandline 
+    * This function is intended to provide a variety of generic commandline
     * options for all OGR commandline utilities.  It takes care of the following
     * commandline options:
     * <p><ul>
     *  <li>--version: report version of OGR in use.
     *  <li>--license: report OGR license info.
     *  <li>--formats: report all format drivers configured.
-    *  <li>--format [format]: report details of one format driver. 
-    *  <li>--optfile filename: expand an option file into the argument list. 
-    *  <li>--config key value: set system configuration option. 
+    *  <li>--format [format]: report details of one format driver.
+    *  <li>--optfile filename: expand an option file into the argument list.
+    *  <li>--config key value: set system configuration option.
     *  <li>--debug [on/off/value]: set debug level.
     *  <li>--mempreload dir: preload directory contents into /vsimem
-    *  <li>--help-general: report detailed help on general options. 
+    *  <li>--help-general: report detailed help on general options.
     * </ul><p>
     * The typical usage looks something like the following.  Note that the formats
     * should be registered so that the --formats and --format options will work properly.
     * <pre>
     *  public static void main( Strings[] args )
-    *  { 
+    *  {
     *    ogr.RegisterAll();
     *
     *    args = ogr.GeneralCmdLineProcessor( args, 0 );
@@ -9980,7 +9980,7 @@ public class ogr:public static DataSource Open(String filename, boolean update)
   </pre>
 
   @param filename the name of the file, or data source to open.
-  @param update 0 for read-only access (the default) or 1 for 
+  @param update 0 for read-only access (the default) or 1 for
          read-write access.
 
   @return null on error or if the pass name is not supported by this driver,
@@ -10078,7 +10078,7 @@ public class ogr:public static void RegisterAll()
   * WKB.  This entry point is used to turn on or off the
   * generation of such WKB.
   */
-public class ogr:public static int SetGenerate_DB2_V72_BYTE_ORDER(int bGenerate_DB2_V72_BYTE_ORDER) 
+public class ogr:public static int SetGenerate_DB2_V72_BYTE_ORDER(int bGenerate_DB2_V72_BYTE_ORDER)
 
 /**
  * Convert to polygon.
@@ -10087,7 +10087,7 @@ public class ogr:public static int SetGenerate_DB2_V72_BYTE_ORDER(int bGenerate_
  * this just effects a change on multipolygons.
  * <p>
  * Note: contrary to the C/C++ method, a new object is returned.
- * 
+ *
  * @param geom the input geometry
  * @return new geometry.
  * @since Java bindings 1.8.0
@@ -10101,7 +10101,7 @@ public class ogr:public static Geometry ForceToPolygon(Geometry geom)
  * this just effects a change on polygons.
  * <p>
  * Note: contrary to the C/C++ method, a new object is returned.
- * 
+ *
  * @param geom the input geometry
  * @return new geometry.
  * @since Java bindings 1.8.0
@@ -10115,7 +10115,7 @@ public class ogr:public static Geometry ForceToMultiPolygon(Geometry geom)
  * this just effects a change on points.
  * <p>
  * Note: contrary to the C/C++ method, a new object is returned.
- * 
+ *
  * @param geom the input geometry
  * @return new geometry.
  * @since Java bindings 1.8.0
@@ -10128,13 +10128,13 @@ public class ogr:public static Geometry ForceToMultiPoint(Geometry geom)
  * Tries to force the provided geometry to be a multilinestring.
  * <ul>
  * <li>linestrings are placed in a multilinestring.
- * <li>geometry collections will be converted to multilinestring if they only 
+ * <li>geometry collections will be converted to multilinestring if they only
  * contain linestrings.
  * <li>polygons will be changed to a collection of linestrings (one per ring).
  * </ul>
  * <p>
  * Note: contrary to the C/C++ method, a new object is returned.
- * 
+ *
  * @param geom the input geometry
  * @return new geometry.
  * @since Java bindings 1.8.0
@@ -10167,10 +10167,10 @@ public class SpatialReference
  * should be a WKT representation of an SRS.  Passing this is equivalent
  * to not passing it, and then calling importFromWkt() with the WKT string.
  * <p>
- * Note that newly created objects are given a reference count of one. 
+ * Note that newly created objects are given a reference count of one.
  *
  * @param wkt well known text definition to which the object should
- * be initialized, or null (the default). 
+ * be initialized, or null (the default).
  */
 public class SpatialReference:public SpatialReference(String wkt)
 
@@ -10196,15 +10196,15 @@ public class SpatialReference:public String __str__()
  * Set EPSG authority info if possible.
  * <p>
  * This method inspects a WKT definition, and adds EPSG authority nodes
- * where an aspect of the coordinate system can be easily and safely 
- * corresponded with an EPSG identifier.  In practice, this method will 
+ * where an aspect of the coordinate system can be easily and safely
+ * corresponded with an EPSG identifier.  In practice, this method will
  * evolve over time.  In theory it can add authority nodes for any object
- * (i.e. spheroid, datum, GEOGCS, units, and PROJCS) that could have an 
- * authority node.  Mostly this is useful to inserting appropriate 
- * PROJCS codes for common formulations (like UTM n WGS84). 
+ * (i.e. spheroid, datum, GEOGCS, units, and PROJCS) that could have an
+ * authority node.  Mostly this is useful to inserting appropriate
+ * PROJCS codes for common formulations (like UTM n WGS84).
  * <p>
- * If it success the OGRSpatialReference is updated in place, and the 
- * method return 0.  If the method fails to identify the 
+ * If it success the OGRSpatialReference is updated in place, and the
+ * method return 0.  If the method fails to identify the
  * general coordinate system, a RuntimeException() will be throwned
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
@@ -10214,14 +10214,14 @@ public class SpatialReference:public int AutoIdentifyEPSG()
 /**
  * Make a duplicate of this SpatialReference object.
  *
- * @return a new SRS, which becomes the responsibility of the caller. 
+ * @return a new SRS, which becomes the responsibility of the caller.
  */
 public class SpatialReference:public SpatialReference Clone()
 
 /**
  * Make a duplicate of the GEOGCS node of this SpatialReference object.
  *
- * @return a new SRS, which becomes the responsibility of the caller. 
+ * @return a new SRS, which becomes the responsibility of the caller.
  */
 public class SpatialReference:public SpatialReference CloneGeogCS()
 
@@ -10232,16 +10232,16 @@ public class SpatialReference:public SpatialReference CloneGeogCS()
  * The GEOGCS information is copied into this SpatialReference from another.
  * If this object has a PROJCS root already, the GEOGCS is installed within
  * it, otherwise it is installed as the root.
- * 
+ *
  * @param src_srs the spatial reference to copy the GEOGCS information from.
- * 
+ *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int CopyGeogCSFrom(SpatialReference src_srs)
 
 /**
  * Export coordinate system in Mapinfo style CoordSys format.
- * 
+ *
  * @return the coordinate system in Mapinfo style CoordSys format.
  *
  * @since Java bindings 1.7.0
@@ -10250,7 +10250,7 @@ public class SpatialReference:public String ExportToMICoordSys()
 
 /**
  * Export coordinate system in Mapinfo style CoordSys format.
- * 
+ *
  * @param argout an already allocated array of 1 string to receive the output
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
@@ -10260,19 +10260,19 @@ public class SpatialReference:public int ExportToMICoordSys(String[] argout)
  * Export coordinate system in PCI projection definition.
  * <p>
  * Converts the loaded coordinate reference system into PCI projection
- * definition to the extent possible. 
+ * definition to the extent possible.
  * <p>
  * LOCAL_CS coordinate systems are not translatable.  An empty string
  * will be returned along with 0.
  *
  * @param proj an already allocated array of 1 string to receive the PCI projection
  * definition
- * 
+ *
  * @param units an already allocated array of 1 string to receive units definition
  *
  * @param parms an already allocated array of 17 doubles to receive the 17
  * projection parameters will be assigned. See importFromPCI() for the list of parameters.
- * 
+ *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int ExportToPCI(String[] proj, String[] units, double[] parms)
@@ -10335,10 +10335,10 @@ public class SpatialReference:public String ExportToProj4()
  * Export coordinate system in PROJ.4 format.
  * <p>
  * Converts the loaded coordinate reference system into PROJ.4 format
- * to the extent possible. 
+ * to the extent possible.
  * <p>
  * LOCAL_CS coordinate systems are not translatable.  An empty string
- * will be returned along with 0.  
+ * will be returned along with 0.
  *
  * @param argout an already allocated array of 1 string to receive the PROJ.4 definition
  *
@@ -10353,8 +10353,8 @@ public class SpatialReference:public int ExportToProj4(String[] argout)
  *
  * @param zone an already allocated array of 1 integer to receive the zone for UTM and State Plane
  * projection.
- * 
- * @param parms n already allocated array of 15 doubles to receive 
+ *
+ * @param parms n already allocated array of 15 doubles to receive
  * 15 projection parameters. See importFromUSGS() for
  * the list of parameters.
  *
@@ -10419,7 +10419,7 @@ public class SpatialReference:public int ExportToXML(String[] argout)
  * to the extent possible.
  * <p>
  * LOCAL_CS coordinate systems are not translatable.  An empty string
- * will be returned along with 0.  
+ * will be returned along with 0.
  *
  * @param argout an already allocated array of 1 string to receive the XML definition.
  * @param dialect currently ignored. The dialect used is GML based.
@@ -10435,7 +10435,7 @@ public class SpatialReference:public int ExportToXML(String[] argout, String dia
  * imported WKT, are not valid according to the OGC CT specification.  This
  * method attempts to fill in any missing defaults that are required, and
  * fixup ordering problems (using OSRFixupOrdering()) so that the resulting
- * WKT is valid. 
+ * WKT is valid.
  * <p>
  * This method should be expected to evolve over time to as problems are
  * discovered.  The following are among the fixup actions this method will
@@ -10465,11 +10465,11 @@ public class SpatialReference:public int FixupOrdering()
 /**
  * Fetch angular geographic coordinate system units.
  * <p>
- * If no units are available, a value of SRS_UA_DEGREE_CONV 
+ * If no units are available, a value of SRS_UA_DEGREE_CONV
  * will be assumed.  This method only checks directly under the GEOGCS node
  * for units.
  *
- * @return the value to multiply by angular distances to transform them to 
+ * @return the value to multiply by angular distances to transform them to
  * radians.
  */
 public class SpatialReference:public double GetAngularUnits()
@@ -10496,7 +10496,7 @@ public class SpatialReference:public String GetAngularUnitsName()
  *
  * @return the requested value, or null if it fails for any reason.
  *
- * @since Java bindings 1.7.0 
+ * @since Java bindings 1.7.0
  */
 public class SpatialReference:public String GetAttrValue(String name)
 
@@ -10511,21 +10511,21 @@ public class SpatialReference:public String GetAttrValue(String name)
  * @param name the tree node to look for (case insensitive).
  * @param child the child of the node to fetch (zero based).
  *
- * @return the requested value, or null if it fails for any reason. 
+ * @return the requested value, or null if it fails for any reason.
  */
 public class SpatialReference:public String GetAttrValue(String name, int child)
 
 /**
  * Get the authority code for a node.
  * <p>
- * This method is used to query an AUTHORITY[] node from within the 
- * WKT tree, and fetch the code value.  
+ * This method is used to query an AUTHORITY[] node from within the
+ * WKT tree, and fetch the code value.
  * <p>
  * While in theory values may be non-numeric, for the EPSG authority all
  * code values should be integral.
  *
- * @param target_key the partial or complete path to the node to 
- * get an authority from.  i.e. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or null to 
+ * @param target_key the partial or complete path to the node to
+ * get an authority from.  i.e. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or null to
  * search for an authority node on the root element.
  *
  * @return value code from authority node, or null on failure.
@@ -10535,13 +10535,13 @@ public class SpatialReference:public String GetAuthorityCode(String target_key)
 /**
  * Get the authority name for a node.
  * <p>
- * This method is used to query an AUTHORITY[] node from within the 
- * WKT tree, and fetch the authority name value.  
+ * This method is used to query an AUTHORITY[] node from within the
+ * WKT tree, and fetch the authority name value.
  * <p>
  * The most common authority is "EPSG".
  *
- * @param target_key the partial or complete path to the node to 
- * get an authority from.  i.e. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or null to 
+ * @param target_key the partial or complete path to the node to
+ * get an authority from.  i.e. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or null to
  * search for an authority node on the root element.
  *
  * @return value code from authority node, or null on failure.
@@ -10551,12 +10551,12 @@ public class SpatialReference:public String GetAuthorityName(String target_key)
 /**
  * Get the axis name for a node.
  * <p>
- * This method is used to query an AXIS[] node from within the 
- * WKT tree, and fetch the axis name value.  
+ * This method is used to query an AXIS[] node from within the
+ * WKT tree, and fetch the axis name value.
  * <p>
  *
- * @param target_key the partial or complete path to the node to 
- * get an authority from.  i.e. "PROJCS", "GEOGCS" or null to 
+ * @param target_key the partial or complete path to the node to
+ * get an authority from.  i.e. "PROJCS", "GEOGCS" or null to
  * search for an authority node on the root element.
  * @param iAxis axis index (starting with 0)
  *
@@ -10568,12 +10568,12 @@ public class SpatialReference:public String GetAxisName(String target_key, int i
 /**
  * Get the axis orientation for a node.
  * <p>
- * This method is used to query an AXIS[] node from within the 
- * WKT tree, and fetch the axis orientation value.  
+ * This method is used to query an AXIS[] node from within the
+ * WKT tree, and fetch the axis orientation value.
  * <p>
  *
- * @param target_key the partial or complete path to the node to 
- * get an authority from.  i.e. "PROJCS", "GEOGCS" or null to 
+ * @param target_key the partial or complete path to the node to
+ * get an authority from.  i.e. "PROJCS", "GEOGCS" or null to
  * search for an authority node on the root element.
  * @param iAxis axis index (starting with 0)
  *
@@ -10585,13 +10585,13 @@ public class SpatialReference:public String GetAxisName(String target_key, int i
 public class SpatialReference:public int GetAxisOrientation(String target_key, int iAxis)
 
 /**
- * Fetch linear projection units. 
+ * Fetch linear projection units.
  * <p>
  * If no units are available, a value of "Meters" and 1.0 will be assumed.
- * This method only checks directly under the PROJCS or LOCAL_CS node for 
+ * This method only checks directly under the PROJCS or LOCAL_CS node for
  * units.
  *
- * @return the value to multiply by linear distances to transform them to 
+ * @return the value to multiply by linear distances to transform them to
  * meters.
  */
 public class SpatialReference:public double GetLinearUnits()
@@ -10600,7 +10600,7 @@ public class SpatialReference:public double GetLinearUnits()
  * Fetch linear projection units name.
  * <p>
  * If no units are available, a value of "Meters" will be assumed.
- * This method only checks directly under the PROJCS or LOCAL_CS node for 
+ * This method only checks directly under the PROJCS or LOCAL_CS node for
  * units.
  *
  * @return the units name
@@ -10622,10 +10622,10 @@ public class SpatialReference:public double GetNormProjParm(String name)
  * Fetch a normalized projection parameter value.
  * <p>
  * This method is the same as GetProjParm() except that the value of
- * the parameter is "normalized" into degrees or meters depending on 
+ * the parameter is "normalized" into degrees or meters depending on
  * whether it is linear or angular.
  *
- * @param name the name of the parameter to fetch, from the set of 
+ * @param name the name of the parameter to fetch, from the set of
  * SRS_PP codes in ogr_srs_api.h.
  *
  * @param default_val the value to return if this parameter doesn't exist.
@@ -10651,7 +10651,7 @@ public class SpatialReference:public double GetProjParm(String name)
  * NOTE: This code should be modified to translate non degree angles into
  * degrees based on the GEOGCS unit.  This has not yet been done.
  *
- * @param name the name of the parameter to fetch, from the set of 
+ * @param name the name of the parameter to fetch, from the set of
  * SRS_PP codes in ogr_srs_api.h.
  *
  * @param default_val the value to return if this parameter doesn't exist.
@@ -10661,8 +10661,8 @@ public class SpatialReference:public double GetProjParm(String name)
 public class SpatialReference:public double GetProjParm(String name, double default_val)
 
 /**
- * Fetch TOWGS84 parameters, if available. 
- * 
+ * Fetch TOWGS84 parameters, if available.
+ *
  * @return an array of doubles into which up to 7 coefficients are placed.
  *
  * @since Java bindings 1.7.0
@@ -10670,10 +10670,10 @@ public class SpatialReference:public double GetProjParm(String name, double defa
 public class SpatialReference:public double[] GetTOWGS84()
 
 /**
- * Fetch TOWGS84 parameters, if available. 
- * 
+ * Fetch TOWGS84 parameters, if available.
+ *
  * @param argout allocated array of 7 doubles into which up to 7 coefficients are placed.
- * 
+ *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int GetTOWGS84(double[] argout)
@@ -10683,9 +10683,9 @@ public class SpatialReference:public int GetTOWGS84(double[] argout)
  * <p>
  * This method will initialize the spatial reference based on the
  * passed in EPSG GCS or PCS code.  The coordinate system definitions
- * are normally read from the EPSG derived support files such as 
- * pcs.csv, gcs.csv, pcs.override.csv, gcs.override.csv and falling 
- * back to search for a PROJ.4 epsg init file or a definition in epsg.wkt. 
+ * are normally read from the EPSG derived support files such as
+ * pcs.csv, gcs.csv, pcs.override.csv, gcs.override.csv and falling
+ * back to search for a PROJ.4 epsg init file or a definition in epsg.wkt.
  * <p>
  * These support files are normally searched for in /usr/local/share/gdal
  * or in the directory identified by the GDAL_DATA configuration option.
@@ -10693,15 +10693,15 @@ public class SpatialReference:public int GetTOWGS84(double[] argout)
  * <p>
  * This method is relatively expensive, and generally involves quite a bit
  * of text file scanning.  Reasonable efforts should be made to avoid calling
- * it many times for the same coordinate system. 
+ * it many times for the same coordinate system.
  * <p>
- * This method is similar to importFromEPSGA() except that EPSG preferred 
+ * This method is similar to importFromEPSGA() except that EPSG preferred
  * axis ordering will *not* be applied for geographic coordinate systems.
- * EPSG normally defines geographic coordinate systems to use lat/long 
- * contrary to typical GIS use). 
+ * EPSG normally defines geographic coordinate systems to use lat/long
+ * contrary to typical GIS use).
  *
  * @param nCode a GCS or PCS code from the horizontal coordinate system table.
- * 
+ *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int ImportFromEPSG(int nCode)
@@ -10715,16 +10715,16 @@ public class SpatialReference:public int ImportFromEPSG(int nCode)
  * as the newer pseudo-OGC WKT .prj files.  Note that new style .prj files
  * are in OGC WKT format, but require some manipulation to correct datum
  * names, and units on some projection parameters.  This is addressed within
- * importFromESRI() by an automatic call to morphFromESRI(). 
+ * importFromESRI() by an automatic call to morphFromESRI().
  * <p>
- * Currently only GEOGRAPHIC, UTM, STATEPLANE, GREATBRITIAN_GRID, ALBERS, 
+ * Currently only GEOGRAPHIC, UTM, STATEPLANE, GREATBRITIAN_GRID, ALBERS,
  * EQUIDISTANT_CONIC, and TRANSVERSE (mercator) projections are supported
- * from old style files. 
+ * from old style files.
  * <p>
  * At this time there is no equivalent exportToESRI() method.  Writing old
  * style .prj files is not supported by OGRSpatialReference. However the
  * morphToESRI() and exportToWkt() methods can be used to generate output
- * suitable to write to new style (Arc 8) .prj files. 
+ * suitable to write to new style (Arc 8) .prj files.
  *
  * @param ppszInput vector of strings containing the definition.
  *
@@ -10814,10 +10814,10 @@ public class SpatialReference:public int ImportFromPCI(String proj, String units
  * coordinate system string.  In addition to many +proj formulations which
  * have OGC equivalents, it is also possible to import "+init=epsg:n" style
  * definitions.  These are passed to importFromEPSG().  Other init strings
- * (such as the state plane zones) are not currently supported.   
+ * (such as the state plane zones) are not currently supported.
  * <p><pre>
  * Example:
- *   pszProj4 = "+proj=utm +zone=11 +datum=WGS84" 
+ *   pszProj4 = "+proj=utm +zone=11 +datum=WGS84"
  * </pre><p>
  * Some parameters, such as grids, recognized by PROJ.4 may not be well
  * understood and translated into the OGRSpatialReference model. It is possible
@@ -10843,11 +10843,11 @@ public class SpatialReference:public int ImportFromPCI(String proj, String units
  *    PARAMETER["false_easting",2510000],
  *    PARAMETER["false_northing",6023150],
  *    UNIT["Meter",1],
- *    EXTENSION["PROJ4","+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000 
+ *    EXTENSION["PROJ4","+proj=nzmg +lat_0=-41 +lon_0=173 +x_0=2510000
  *               +y_0=6023150 +ellps=intl  +units=m +nadgrids=nzgd2kgrid0005.gsb +wktext"]]
  * </pre>
  *
- * @param proj4 the PROJ.4 style string. 
+ * @param proj4 the PROJ.4 style string.
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
@@ -10856,13 +10856,13 @@ public class SpatialReference:public int ImportFromProj4(String proj4)
 /**
  * Set spatial reference from a URL.
  * <p>
- * This method will download the spatial reference at a given URL and 
+ * This method will download the spatial reference at a given URL and
  * feed it into SetFromUserInput for you.
- * 
+ *
  * @param url text definition to try to deduce SRS from.
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
- */ 
+ */
 public class SpatialReference:public int ImportFromUrl(String url)
 
 /**
@@ -10910,13 +10910,13 @@ public class SpatialReference:public int ImportFromUSGS(int iProjSys, int iZone,
  *  Projection Transformation Package Projection Parameters:
  * <pre>
  * ----------------------------------------------------------------------------
- *                         |                    Array Element                  
+ *                         |                    Array Element
  *  Code & Projection Id   |---------------------------------------------------
  *                         |   0  |   1  |  2   |  3   |   4   |    5    |6 | 7
  * ----------------------------------------------------------------------------
- *  0 Geographic           |      |      |      |      |       |         |  |  
- *  1 U T M                |Lon/Z |Lat/Z |      |      |       |         |  |  
- *  2 State Plane          |      |      |      |      |       |         |  |  
+ *  0 Geographic           |      |      |      |      |       |         |  |
+ *  1 U T M                |Lon/Z |Lat/Z |      |      |       |         |  |
+ *  2 State Plane          |      |      |      |      |       |         |  |
  *  3 Albers Equal Area    |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
  *  4 Lambert Conformal C  |SMajor|SMinor|STDPR1|STDPR2|CentMer|OriginLat|FE|FN
  *  5 Mercator             |SMajor|SMinor|      |      |CentMer|TrueScale|FE|FN
@@ -10941,19 +10941,19 @@ public class SpatialReference:public int ImportFromUSGS(int iProjSys, int iZone,
  * 22 Space Oblique Merc A |SMajor|SMinor|      |IncAng|AscLong|         |FE|FN
  *    Space Oblique Merc B |SMajor|SMinor|Satnum|Path  |       |         |FE|FN
  * 23 Alaska Conformal     |SMajor|SMinor|      |      |       |         |FE|FN
- * 24 Interrupted Goode    |Sphere|      |      |      |       |         |  |  
+ * 24 Interrupted Goode    |Sphere|      |      |      |       |         |  |
  * 25 Mollweide            |Sphere|      |      |      |CentMer|         |FE|FN
- * 26 Interrupt Mollweide  |Sphere|      |      |      |       |         |  |  
+ * 26 Interrupt Mollweide  |Sphere|      |      |      |       |         |  |
  * 27 Hammer               |Sphere|      |      |      |CentMer|         |FE|FN
  * 28 Wagner IV            |Sphere|      |      |      |CentMer|         |FE|FN
  * 29 Wagner VII           |Sphere|      |      |      |CentMer|         |FE|FN
  * 30 Oblated Equal Area   |Sphere|      |Shapem|Shapen|CentLon|CenterLat|FE|FN
  * ----------------------------------------------------------------------------
- * 
+ *
  *       ----------------------------------------------------
  *                               |      Array Element       |
  *         Code & Projection Id  |---------------------------
- *                               |  8  |  9 |  10 | 11 | 12 |  
+ *                               |  8  |  9 |  10 | 11 | 12 |
  *       ----------------------------------------------------
  *        0 Geographic           |     |    |     |    |    |
  *        1 U T M                |     |    |     |    |    |
@@ -10963,12 +10963,12 @@ public class SpatialReference:public int ImportFromUSGS(int iProjSys, int iZone,
  *        5 Mercator             |     |    |     |    |    |
  *        6 Polar Stereographic  |     |    |     |    |    |
  *        7 Polyconic            |     |    |     |    |    |
- *        8 Equid. Conic A       |zero |    |     |    |    |   
+ *        8 Equid. Conic A       |zero |    |     |    |    |
  *          Equid. Conic B       |one  |    |     |    |    |
  *        9 Transverse Mercator  |     |    |     |    |    |
  *       10 Stereographic        |     |    |     |    |    |
- *       11 Lambert Azimuthal    |     |    |     |    |    |    
- *       12 Azimuthal            |     |    |     |    |    |    
+ *       11 Lambert Azimuthal    |     |    |     |    |    |
+ *       12 Azimuthal            |     |    |     |    |    |
  *       13 Gnomonic             |     |    |     |    |    |
  *       14 Orthographic         |     |    |     |    |    |
  *       15 Gen. Vert. Near Per  |     |    |     |    |    |
@@ -10976,10 +10976,10 @@ public class SpatialReference:public int ImportFromUSGS(int iProjSys, int iZone,
  *       17 Equirectangular      |     |    |     |    |    |
  *       18 Miller Cylindrical   |     |    |     |    |    |
  *       19 Van der Grinten      |     |    |     |    |    |
- *       20 Hotin Oblique Merc A |Long1|Lat1|Long2|Lat2|zero|   
+ *       20 Hotin Oblique Merc A |Long1|Lat1|Long2|Lat2|zero|
  *          Hotin Oblique Merc B |     |    |     |    |one |
  *       21 Robinson             |     |    |     |    |    |
- *       22 Space Oblique Merc A |PSRev|LRat|PFlag|    |zero|    
+ *       22 Space Oblique Merc A |PSRev|LRat|PFlag|    |zero|
  *          Space Oblique Merc B |     |    |     |    |one |
  *       23 Alaska Conformal     |     |    |     |    |    |
  *       24 Interrupted Goode    |     |    |     |    |    |
@@ -11136,7 +11136,7 @@ public class SpatialReference:public int ImportFromUSGS(int iProjSys, int iZone,
  */
 public class SpatialReference:public int ImportFromWkt(String wkt)
 
-/** 
+/**
  * Import coordinate system from XML format (GML only currently).
  *
  * @param xmlString XML string to import
@@ -11167,24 +11167,24 @@ public class SpatialReference:public int IsGeocentric()
 /**
  * Check if geographic coordinate system.
  *
- * @return 1 if this spatial reference is geographic ... that is the 
- * root is a GEOGCS node. 
+ * @return 1 if this spatial reference is geographic ... that is the
+ * root is a GEOGCS node.
  */
 public class SpatialReference:public int IsGeographic()
 
 /**
  * Check if local coordinate system.
  *
- * @return 1 if this spatial reference is local ... that is the 
- * root is a LOCAL_CS node. 
+ * @return 1 if this spatial reference is local ... that is the
+ * root is a LOCAL_CS node.
  */
 public class SpatialReference:public int IsLocal()
 
 /**
  * Check if projected coordinate system.
  *
- * @return 1 if this contains a PROJCS node indicating a it is a 
- * projected coordinate system. 
+ * @return 1 if this contains a PROJCS node indicating a it is a
+ * projected coordinate system.
  */
 public class SpatialReference:public int IsProjected()
 
@@ -11193,16 +11193,16 @@ public class SpatialReference:public int IsProjected()
  *
  * @param other the SRS being compared to.
  *
- * @return 1 if equivalent or 0 otherwise. 
+ * @return 1 if equivalent or 0 otherwise.
  */
 public class SpatialReference:public int IsSame(SpatialReference other)
 
 /**
  * Do the GeogCS'es match?
  *
- * @param other the SRS being compared against. 
+ * @param other the SRS being compared against.
  *
- * @return 1 if they are the same or 0 otherwise. 
+ * @return 1 if they are the same or 0 otherwise.
  */
 public class SpatialReference:public int IsSameGeogCS(SpatialReference other)
 
@@ -11243,8 +11243,8 @@ public class SpatialReference:public int MorphFromESRI()
  * <p>
  * The value nodes of this coordinate system are modified in various manners
  * more closely map onto the ESRI concept of WKT format.  This includes
- * renaming a variety of projections and arguments, and stripping out 
- * nodes note recognised by ESRI (like AUTHORITY and AXIS). 
+ * renaming a variety of projections and arguments, and stripping out
+ * nodes note recognised by ESRI (like AUTHORITY and AXIS).
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
@@ -11254,14 +11254,14 @@ public class SpatialReference:public int MorphToESRI()
  * Set the angular units for the geographic coordinate system.
  * <p>
  * This method creates a UNITS subnode with the specified values as a
- * child of the GEOGCS node. 
+ * child of the GEOGCS node.
  *
  * @param name the units name to be used.  Some preferred units
- * names can be found in ogr_srs_api.h such as SRS_UA_DEGREE. 
+ * names can be found in ogr_srs_api.h such as SRS_UA_DEGREE.
  *
  * @param to_radians the value to multiple by an angle in the indicated
  * units to transform to radians.  Some standard conversion factors can
- * be found in ogr_srs_api.h. 
+ * be found in ogr_srs_api.h.
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
@@ -11276,8 +11276,8 @@ public class SpatialReference:public int SetAngularUnits(String name, double to_
  *
  * @param name full path to attribute to be set.  For instance
  * "PROJCS|GEOGCS|UNITS".
- * 
- * @param value value to be assigned to node, such as "meter". 
+ *
+ * @param value value to be assigned to node, such as "meter".
  * This may be null if you just want to force creation of the intermediate
  * path.
  *
@@ -11288,7 +11288,7 @@ public class SpatialReference:public int SetAttrValue(String name, String value)
 /**
  * Set the authority for a node.
  *
- * @param target_key the partial or complete path to the node to 
+ * @param target_key the partial or complete path to the node to
  * set an authority on.  i.e. "PROJCS", "GEOGCS" or "GEOGCS|UNIT".
  *
  * @param authority authority name, such as "EPSG".
@@ -11308,31 +11308,31 @@ public class SpatialReference:public int SetAuthority(String target_key, String
  *
  * <ol>
  * <li> Well Known Text definition - passed on to importFromWkt().
- * <li> "EPSG:n" - number passed on to importFromEPSG(). 
- * <li> "EPSGA:n" - number passed on to importFromEPSGA(). 
+ * <li> "EPSG:n" - number passed on to importFromEPSG().
+ * <li> "EPSGA:n" - number passed on to importFromEPSGA().
  * <li> "AUTO:proj_id,unit_id,lon0,lat0" - WMS auto projections.
  * <li> "urn:ogc:def:crs:EPSG::n" - ogc urns
  * <li> PROJ.4 definitions - passed on to importFromProj4().
  * <li> filename - file read for WKT, XML or PROJ.4 definition.
  * <li> well known name accepted by SetWellKnownGeogCS(), such as NAD27, NAD83,
- * WGS84 or WGS72. 
+ * WGS84 or WGS72.
  * <li> WKT (directly or in a file) in ESRI format should be prefixed with
  * ESRI:: to trigger an automatic morphFromESRI().
  * </ol>
  *
  * It is expected that this method will be extended in the future to support
  * XML and perhaps a simplified "minilanguage" for indicating common UTM and
- * State Plane definitions. 
+ * State Plane definitions.
  * <p>
- * This method is intended to be flexible, but by it's nature it is 
+ * This method is intended to be flexible, but by it's nature it is
  * imprecise as it must guess information about the format intended.  When
  * possible applications should call the specific method appropriate if the
- * input is known to be in a particular format. 
- * 
+ * input is known to be in a particular format.
+ *
  * @param definition text definition to try to deduce SRS from.
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
- */ 
+ */
 public class SpatialReference:public int SetFromUserInput(String definition)
 
 /**
@@ -11363,7 +11363,7 @@ public class SpatialReference:public int SetGeocCS()
 public class SpatialReference:public int SetGeocCS(String name)
 
 /**
- * Set geographic coordinate system. 
+ * Set geographic coordinate system.
  * <p>
  * Same as below with pszPMName = "Greenwich", dfPMOffset = 0.0, pszAngularUnits = "degree" and dfConvertToRadians =  0.0174532925199433
  *
@@ -11374,7 +11374,7 @@ public class SpatialReference:public int SetGeocCS(String name)
 public class SpatialReference:public int SetGeogCS(String pszGeogName, String pszDatumName, String pszSpheroidName, double dfSemiMajor, double dfInvFlattening)
 
 /**
- * Set geographic coordinate system. 
+ * Set geographic coordinate system.
  * <p>
  * Same as below with dfPMOffset = 0.0, pszAngularUnits = "degree" and dfConvertToRadians =  0.0174532925199433
  *
@@ -11385,7 +11385,7 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
 public class SpatialReference:public int SetGeogCS(String pszGeogName, String pszDatumName, String pszSpheroidName, double dfSemiMajor, double dfInvFlattening, String pszPMName)
 
 /**
- * Set geographic coordinate system. 
+ * Set geographic coordinate system.
  * <p>
  * Same as below with pszAngularUnits = "degree" and dfConvertToRadians =  0.0174532925199433
  *
@@ -11396,7 +11396,7 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
 public class SpatialReference:public int SetGeogCS(String pszGeogName, String pszDatumName, String pszSpheroidName, double dfSemiMajor, double dfInvFlattening, String pszPMName, double dfPMOffset)
 
 /**
- * Set geographic coordinate system. 
+ * Set geographic coordinate system.
  * <p>
  * Same as below with dfConvertToRadians =  0.0174532925199433
  *
@@ -11407,38 +11407,38 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
 public class SpatialReference:public int SetGeogCS(String pszGeogName, String pszDatumName, String pszSpheroidName, double dfSemiMajor, double dfInvFlattening, String pszPMName, double dfPMOffset, String pszAngularUnits)
 
 /**
- * Set geographic coordinate system. 
+ * Set geographic coordinate system.
  * <p>
  * This method is used to set the datum, ellipsoid, prime meridian and
  * angular units for a geographic coordinate system.  It can be used on it's
- * own to establish a geographic spatial reference, or applied to a 
- * projected coordinate system to establish the underlying geographic 
- * coordinate system. 
+ * own to establish a geographic spatial reference, or applied to a
+ * projected coordinate system to establish the underlying geographic
+ * coordinate system.
  *
  * @param pszGeogName user visible name for the geographic coordinate system
  * (not to serve as a key).
- * 
- * @param pszDatumName key name for this datum.  The OpenGIS specification 
+ *
+ * @param pszDatumName key name for this datum.  The OpenGIS specification
  * lists some known values, and otherwise EPSG datum names with a standard
- * transformation are considered legal keys. 
- * 
+ * transformation are considered legal keys.
+ *
  * @param pszSpheroidName user visible spheroid name (not to serve as a key)
  *
  * @param dfSemiMajor the semi major axis of the spheroid.
- * 
+ *
  * @param dfInvFlattening the inverse flattening for the spheroid.
- * This can be computed from the semi minor axis as 
+ * This can be computed from the semi minor axis as
  * 1/f = 1.0 / (1.0 - semiminor/semimajor).
  *
  * @param pszPMName the name of the prime meridian (not to serve as a key)
- * If this is null a default value of "Greenwich" will be used. 
- * 
+ * If this is null a default value of "Greenwich" will be used.
+ *
  * @param dfPMOffset the longitude of greenwich relative to this prime
  * meridian.
  *
  * @param pszAngularUnits the angular units name (see ogr_srs_api.h for some
- * standard names).  If null a value of "degrees" will be assumed. 
- * 
+ * standard names).  If null a value of "degrees" will be assumed.
+ *
  * @param dfConvertToRadians value to multiply angular units by to transform
  * them to radians.  A value of SRS_UL_DEGREE_CONV will be used if
  * pszAngularUnits is null.
@@ -11451,15 +11451,15 @@ public class SpatialReference:public int SetGeogCS(String pszGeogName, String ps
  * Set the linear units for the projection.
  * <p>
  * This method creates a UNITS subnode with the specified values as a
- * child of the PROJCS or LOCAL_CS node. 
+ * child of the PROJCS or LOCAL_CS node.
  *
  * @param name the units name to be used.  Some preferred units
- * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT 
- * and SRS_UL_US_FOOT. 
+ * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
+ * and SRS_UL_US_FOOT.
  *
  * @param to_meters the value to multiple by a length in the indicated
  * units to transform to meters.  Some standard conversion factors can
- * be found in ogr_srs_api.h. 
+ * be found in ogr_srs_api.h.
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
@@ -11471,15 +11471,15 @@ public class SpatialReference:public int SetLinearUnits(String name, double to_m
  * This method creates a UNITS subnode with the specified values as a
  * child of the PROJCS or LOCAL_CS node.   It works the same as the
  * SetLinearUnits() method, but it also updates all existing linear
- * projection parameter values from the old units to the new units. 
+ * projection parameter values from the old units to the new units.
  *
  * @param name the units name to be used.  Some preferred units
- * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT 
- * and SRS_UL_US_FOOT. 
+ * names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
+ * and SRS_UL_US_FOOT.
  *
  * @param to_meters the value to multiple by a length in the indicated
  * units to transform to meters.  Some standard conversion factors can
- * be found in ogr_srs_api.h. 
+ * be found in ogr_srs_api.h.
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
@@ -11488,11 +11488,11 @@ public class SpatialReference:public int SetLinearUnitsAndUpdateParameters(Strin
 /**
  * Set the user visible LOCAL_CS name.
  * <p>
- * This method is will ensure a LOCAL_CS node is created as the root, 
+ * This method is will ensure a LOCAL_CS node is created as the root,
  * and set the provided name on it.  It must be used before SetLinearUnits().
  *
  * @param name the user visible name to assign.  Not used as a key.
- * 
+ *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int SetLocalCS(String name)
@@ -11502,14 +11502,14 @@ public class SpatialReference:public int SetLocalCS(String name)
  * <p>
  * This method is the same as SetProjParm() except that the value of
  * the parameter passed in is assumed to be in "normalized" form (decimal
- * degrees for angular values, meters for linear values.  The values are 
+ * degrees for angular values, meters for linear values.  The values are
  * converted in a form suitable for the GEOGCS and linear units in effect.
  *
  * @param name the parameter name, which should be selected from
- * the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN. 
+ * the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN.
+ *
+ * @param val value to assign.
  *
- * @param val value to assign. 
- * 
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int SetNormProjParm(String name, double val)
@@ -11526,12 +11526,12 @@ public class SpatialReference:public int SetProjCS()
 /**
  * Set the user visible PROJCS name.
  * <p>
- * This method is will ensure a PROJCS node is created as the root, 
- * and set the provided name on it.  If used on a GEOGCS coordinate system, 
+ * This method is will ensure a PROJCS node is created as the root,
+ * and set the provided name on it.  If used on a GEOGCS coordinate system,
  * the GEOGCS node will be demoted to be a child of the new PROJCS root.
  *
  * @param name the user visible name to assign.  May be null
- * 
+ *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int SetProjCS(String name)
@@ -11540,7 +11540,7 @@ public class SpatialReference:public int SetProjCS(String name)
  * Set a projection name.
  *
  * @param name the projection name, which should be selected from
- * the macros in ogr_srs_api.h, such as SRS_PT_TRANSVERSE_MERCATOR. 
+ * the macros in ogr_srs_api.h, such as SRS_PT_TRANSVERSE_MERCATOR.
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
@@ -11553,12 +11553,12 @@ public class SpatialReference:public int SetProjection(String name)
  * <p>
  * Please check <a href="http://www.remotesensing.org/geotiff/proj_list">http://www.remotesensing.org/geotiff/proj_list</a> pages for
  * legal parameter names for specific projections.
- * 
+ *
  * @param name the parameter name, which should be selected from
- * the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN. 
+ * the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN.
+ *
+ * @param val value to assign.
  *
- * @param val value to assign. 
- * 
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int SetProjParm(String name, double val)
@@ -11605,17 +11605,17 @@ public class SpatialReference:public int SetStatePlane(int zone, int is_nad83, S
  * and return OGRERR_FAILURE.
  *
  * @param zone State plane zone number, in the USGS numbering scheme (as
- * distinct from the Arc/Info and Erdas numbering scheme. 
+ * distinct from the Arc/Info and Erdas numbering scheme.
  *
  * @param is_nad83 1 if the NAD83 zone definition should be used or 0
- * if the NAD27 zone definition should be used.  
+ * if the NAD27 zone definition should be used.
  *
- * @param unitsname Linear unit name to apply overriding the 
+ * @param unitsname Linear unit name to apply overriding the
  * legal definition for this zone.
  *
  * @param units Linear unit conversion factor to apply overriding
- * the legal definition for this zone. 
- * 
+ * the legal definition for this zone.
+ *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int SetStatePlane(int zone, int is_nad83, String unitsname, double units)
@@ -11644,7 +11644,7 @@ public class SpatialReference:public int SetStatePlane(int zone, int is_nad83, S
 public class SpatialReference:public int SetTargetLinearUnits(String target, String name, double to_meters)
 
 /**
- * Set the Bursa-Wolf conversion to WGS84. 
+ * Set the Bursa-Wolf conversion to WGS84.
  * <p>
  * Same as below with dfEX == dfEY == dfEZ == dfPPM == 0
  *
@@ -11655,16 +11655,16 @@ public class SpatialReference:public int SetTargetLinearUnits(String target, Str
 public class SpatialReference:public int SetTOWGS84(double p1, double p2, double p3)
 
 /**
- * Set the Bursa-Wolf conversion to WGS84. 
+ * Set the Bursa-Wolf conversion to WGS84.
  * <p>
  * This will create the TOWGS84 node as a child of the DATUM.  It will fail
  * if there is no existing DATUM node.  Unlike most OGRSpatialReference
  * methods it will insert itself in the appropriate order, and will replace
- * an existing TOWGS84 node if there is one. 
+ * an existing TOWGS84 node if there is one.
  * <p>
  * The parameters have the same meaning as EPSG transformation 9606
- * (Position Vector 7-param. transformation). 
- * 
+ * (Position Vector 7-param. transformation).
+ *
  * @param dfDX X child in meters.
  * @param dfDY Y child in meters.
  * @param dfDZ Z child in meters.
@@ -11672,9 +11672,9 @@ public class SpatialReference:public int SetTOWGS84(double p1, double p2, double
  * @param dfEY Y rotation in arc seconds (optional, defaults to zero).
  * @param dfEZ Z rotation in arc seconds (optional, defaults to zero).
  * @param dfPPM scaling factor (parts per million).
- * 
+ *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
- */ 
+ */
 public class SpatialReference:public int SetTOWGS84(double dfDX, double dfDY, double dfDZ, double dfEX, double dfEY, double dfEZ, double dfPPM)
 
 /**
@@ -11691,16 +11691,16 @@ public class SpatialReference:public int SetUTM(int zone)
 /**
  * Set UTM projection definition.
  * <p>
- * This will generate a projection definition with the full set of 
+ * This will generate a projection definition with the full set of
  * transverse mercator projection parameters for the given UTM zone.
  * If no PROJCS[] description is set yet, one will be set to look
- * like "UTM Zone %d, {Northern, Southern} Hemisphere". 
+ * like "UTM Zone %d, {Northern, Southern} Hemisphere".
  *
  * @param zone UTM zone.
  *
- * @param north 1 for northern hemisphere, or 0 for southern 
- * hemisphere. 
- * 
+ * @param north 1 for northern hemisphere, or 0 for southern
+ * hemisphere.
+ *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int SetUTM(int zone, int north)
@@ -11740,9 +11740,9 @@ public class SpatialReference:public int SetVertCS(String VertCSName, String Ver
  * Set a GeogCS based on well known name.
  * <p>
  * This may be called on an empty OGRSpatialReference to make a geographic
- * coordinate system, or on something with an existing PROJCS node to 
+ * coordinate system, or on something with an existing PROJCS node to
  * set the underlying geographic coordinate system of a projected coordinate
- * system. 
+ * system.
  * <p>
  * The following well known text values are currently supported:
  * <ul>
@@ -11752,18 +11752,18 @@ public class SpatialReference:public int SetVertCS(String VertCSName, String Ver
  * <li> "NAD83": same as "EPSG:4269" but has no dependence on EPSG data files.
  * <li> "EPSG:n": same as doing an ImportFromEPSG(n).
  * </ul>
- * 
+ *
  * @param name name of well known geographic coordinate system.
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
 public class SpatialReference:public int SetWellKnownGeogCS(String name)
 
-/** 
+/**
  * Strip OGC CT Parameters.
  * <p>
  * This method will remove all components of the coordinate system
  * that are specific to the OGC CT Specification.  That is it will attempt
- * to strip it down to being compatible with the Simple Features 1.0 
+ * to strip it down to being compatible with the Simple Features 1.0
  * specification.
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
@@ -11782,7 +11782,7 @@ public class SpatialReference:public String toString()
  * <p>
  * This method attempts to verify that the spatial reference system is
  * well formed, and consists of known tokens.  The validation is not
- * comprehensive. 
+ * comprehensive.
  *
  * @return 0 on success. Otherwise throws a RuntimeException() (or an error code if DontUseExceptions() has been called).
  */
@@ -11834,17 +11834,17 @@ public class CoordinateTransformation
  *    hTransform = null;
  * </pre>
  *
- * @param src source spatial reference system. 
+ * @param src source spatial reference system.
  * @param dst target spatial reference system.
- * @deprecated 
+ * @deprecated
  * @see #CreateCoordinateTransformation(org.gdal.osr.SpatialReference, org.gdal.osr.SpatialReference)
  */
-public class CoordinateTransformation:public CoordinateTransformation(SpatialReference src, SpatialReference dst) 
+public class CoordinateTransformation:public CoordinateTransformation(SpatialReference src, SpatialReference dst)
 
 /**
  * Create transformation object.
  *
- * @param src source spatial reference system. 
+ * @param src source spatial reference system.
  * @param dst target spatial reference system.
  * @return a new CoordinateTransformation object, or null in case of failure
  * @since GDAL 1.10
@@ -11910,7 +11910,7 @@ public class CoordinateTransformation:public double[] TransformPoint(double x, d
  *
  * @param pointArray an array of coordinates. Each coordinate can be either 2D or 3D
  */
-public class CoordinateTransformation:public void TransformPoints(double[][] pointArray) 
+public class CoordinateTransformation:public void TransformPoints(double[][] pointArray)
 
 
 /* Class osr */
@@ -11973,7 +11973,7 @@ public class osr:public static String GetWellKnownGeogCSAsWKT(String definition)
 /**
  * Create transformation object.
  *
- * @param src source spatial reference system. 
+ * @param src source spatial reference system.
  * @param dst target spatial reference system.
  * @return a new CoordinateTransformation object, or null in case of failure
  * @since GDAL 1.10
diff --git a/swig/makefile.vc b/swig/makefile.vc
index 868f5f8..668ff84 100644
--- a/swig/makefile.vc
+++ b/swig/makefile.vc
@@ -13,14 +13,15 @@ gdalvars:
 python: gdalvars 
         cd python
         -del setup_vars.ini
-        echo 'GNM_ENABLED=$(GNM_ENABLED)' > setup_vars.ini
+        echo 'GNM_ENABLED=$(INCLUDE_GNM_FRMTS)' > setup_vars.ini
         $(SWIG) -python -modern -new_repr -o extensions/gdalconst_wrap.c -outdir osgeo ..\include\gdalconst.i
         $(SWIG) -c++ -python -modern -new_repr -I../include/python -I../include/python/docs -o extensions/gdal_wrap.cpp -outdir osgeo ..\include\gdal.i
         $(SWIG) -c++ -python -modern -new_repr -I../include/python -I../include/python/docs -o extensions/osr_wrap.cpp -outdir osgeo ..\include\osr.i
         $(SWIG) -c++ -python -modern -new_repr -I../include/python -I../include/python/docs -o extensions/ogr_wrap.cpp -outdir osgeo ..\include\ogr.i
+        $(SWIG) -c++ -python -modern -new_repr -I../include/python -I../include/python/docs -o extensions/gnm_wrap.cpp -outdir osgeo ..\include\gnm.i
         $(SWIG) -c++ -python -modern -new_repr -I../include/python -I../include/python/docs -o extensions/gdal_array_wrap.cpp -outdir osgeo ..\include\gdal_array.i
         $(PYDIR)\python.exe setup.py build
-        
+
 #d:\Python\debug\Python-2.4\PCbuild\python_d.exe setup.py build   --debug
 
 csharp: gdalvars
diff --git a/swig/perl/Changes-in-the-API-in-2.0 b/swig/perl/Changes-in-the-API-in-2.0
index dd3c6a1..5c5719d 100644
--- a/swig/perl/Changes-in-the-API-in-2.0
+++ b/swig/perl/Changes-in-the-API-in-2.0
@@ -28,7 +28,7 @@ many classes:
 
 Geo::OSR::SpatialReference:
 
-    Overloading to "", and = have been removed. Use explicit 
+    Overloading to "", and = have been removed. Use explicit
     method call As('PrettyWKT') instead.
 
 Geo::OGR::Layer
diff --git a/swig/perl/Doxyfile b/swig/perl/Doxyfile
index d24c7d5..f57730c 100644
--- a/swig/perl/Doxyfile
+++ b/swig/perl/Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME           = Geo::GDAL
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 2.1
+PROJECT_NUMBER         = 2.2
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -859,7 +859,7 @@ IMAGE_PATH             =
 # code is scanned, but not when the output code is generated. If lines are added
 # or removed, the anchors will not be placed correctly.
 
-INPUT_FILTER           = doxygen-filter-perl
+INPUT_FILTER           =
 
 # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
 # basis. Doxygen will compare the file name with each pattern and apply the
@@ -868,7 +868,7 @@ INPUT_FILTER           = doxygen-filter-perl
 # filters are used. If the FILTER_PATTERNS tag is empty or if none of the
 # patterns match the file name, INPUT_FILTER is applied.
 
-FILTER_PATTERNS        =
+FILTER_PATTERNS        = *.pm=doxygen-filter-perl *.pl=doxygen-filter-perl
 
 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
 # INPUT_FILTER ) will also be used to filter the input files that are used for
@@ -1481,7 +1481,7 @@ SEARCHENGINE           = NO
 
 # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
 # implemented using a web server instead of a web client using Javascript. There
-# are two flavours of web server based searching depending on the
+# are two flavors of web server based searching depending on the
 # EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
 # searching and an index file used by the script. When EXTERNAL_SEARCH is
 # enabled the indexing and searching needs to be provided by external tools. See
diff --git a/swig/perl/GNUmakefile b/swig/perl/GNUmakefile
index c02f1e0..b4d1c39 100644
--- a/swig/perl/GNUmakefile
+++ b/swig/perl/GNUmakefile
@@ -6,6 +6,8 @@ BINDING = perl
 
 SWIGDEFINES = -DPERL_CPAN_NAMESPACE
 
+SWIG_INCLUDES = ../include/perl/callback.i ../include/perl/confess.i ../include/perl/destroy.i ../include/perl/init.i ../include/perl/band.i
+
 include ../SWIGmake.base
 
 generate: ${WRAPPERS}
diff --git a/swig/perl/MANIFEST b/swig/perl/MANIFEST
deleted file mode 100644
index 621dc4d..0000000
--- a/swig/perl/MANIFEST
+++ /dev/null
@@ -1,41 +0,0 @@
-MANIFEST
-Changes
-Doxyfile
-README
-Makefile
-make.bat
-lib/Geo/GDAL/Const.pm
-lib/Geo/GDAL.pm
-lib/Geo/OGR.pm
-lib/Geo/OSR.pm
-lib/Geo/GNM.pm
-lib/Geo/GDAL/Const.dox
-lib/Geo/GDAL.dox
-lib/Geo/OGR.dox
-lib/Geo/OSR.dox
-lib/Geo/GNM.dox
-t/00.t
-t/01.t
-t/02.t
-t/03.t
-t/gdal.t
-t/ogr.t
-t/osr.t
-t/open.t
-t/utf8.t
-t/gcp.t
-Makefile.PL
-gdalconst_wrap.c
-gdal_wrap.cpp
-ogr_wrap.cpp
-osr_wrap.cpp
-cr.dox
-cv.dox
-index.dox
-pdl.dox
-rr.dox
-rv.dox
-transform.dox
-check_dox.pl
-parse-for-doxygen.pl
-Changes-in-the-API-in-2.0
diff --git a/swig/perl/Makefile.PL b/swig/perl/Makefile.PL
index f711276..08d32b5 100644
--- a/swig/perl/Makefile.PL
+++ b/swig/perl/Makefile.PL
@@ -5,185 +5,24 @@ use ExtUtils::MakeMaker;
 use Config;
 use Cwd;
 
-# pick up our parameters from @ARGV
-my %ARGV;
-for (@ARGV) {
-    if (/^(.*?)\=(.*)/) {
-        $ARGV{$1} = $2;
-    } else {
-        $ARGV{$_} = 1;
-    }
-    $_ = '' if /^--gdal-source-tree/;
-    $_ = '' if /^--gdal-config/;
-    $_ = '' if /^--no-version-check/;
-    $_ = '' if /^--no-downloads/;
-    print STDERR "Warning: unknown parameter: '$_'.\n" if $_;
+my $source_tree = '../..';
+unless (-r "$source_tree/GDALmake.opt.in") {
+    die "../../GDALmake.opt.in was not found. Is this the GDAL source tree?";
 }
-# ... or from the environment
-$ARGV{'--gdal-source-tree'} = $ENV{PERL_GDAL_SOURCE_TREE} if $ENV{PERL_GDAL_SOURCE_TREE};
-$ARGV{'--gdal-config'} = $ENV{PERL_GDAL_CONFIG} if $ENV{PERL_GDAL_CONFIG};
-$ARGV{'--no-version-check'} = 1 if $ENV{PERL_GDAL_NO_VERSION_CHECK};
-$ARGV{'--no-downloads'} = 1 if $ENV{PERL_GDAL_NO_DOWNLOADS};
-
-if ($ARGV{'--help'}) {
-    print <<end;
-'perl Makefile.pl' configures this package to many kinds of systems.
-
-Usage: perl Makefile.pl [OPTION]
-
-To assign environment variables, specify them as VAR=VALUE.
-
-Control the GDAL that this module is built against:
-
-  --gdal-source-tree=PATH  use PATH as the gdal source
-    the same as environment variable PERL_GDAL_SOURCE_TREE=PATH
 
-  --gdal-config=PATH  use PATH as the gdal-config
-    the same as environment variable PERL_GDAL_CONFIG=PATH
-
-  --no-version-check  allow building against GDAL with different version
-    the same as setting environment variable PERL_GDAL_NO_VERSION_CHECK=1
-
-  --no-downloads      disable fetching GDAL source code as a last resort
-    the same as setting environment variable PERL_GDAL_NO_DOWNLOADS=1
-
-More information is available at ExtUtils-MakeMaker documentation.
-
-end
-exit;
-}
-
-my $source_tree;
-if ($ARGV{'--gdal-source-tree'}) {
-    $source_tree = $ARGV{'--gdal-source-tree'};
-    # hack to force downloading of the source
-    if ($ARGV{'--gdal-source-tree'} eq 'download') {
-        $source_tree = '';
-    } else {
-        die "Path '$source_tree' does not exist." unless -e $source_tree && -d $source_tree;
-    }
-}
-elsif (-r '../../GDALmake.opt.in') {
-    $source_tree = '../..';
-    print "Building in source tree.\n" if $source_tree;
-}
-
-# Obtain the version of GDAL for this module distribution.
-
-my $my_gdal_version;
-if (open(my $fh, "lib/Geo/GDAL.pm")) {
-    for (<$fh>) {
-        ($my_gdal_version) = /(\d+\.\d+\.\d+)/ if /GDAL_VERSION/;
-    }
-    close $fh;
-} else {
+unless (-r "lib/Geo/GDAL.pm") {
     die "GDAL Perl modules not found, perhaps you need to run make generate?";
 }
 
-# search and decide which GDAL (gdal-config) to build against if not given
-
-my $versions_may_differ = $ARGV{'--no-version-check'};
-my $downloads_are_ok = !$source_tree && !$ARGV{'--no-downloads'};
-my $gdal_config;
-if ($source_tree) {
-    $gdal_config = "$source_tree/apps/gdal-config";
+my $config = "$source_tree/apps/gdal-config";
+unless (-r $config) {
     die "There is no gdal-config in '$source_tree'.\n".
-        "You have to first say \"cd $source_tree; make\"." unless -r $gdal_config;
-}
-elsif ($ARGV{'--gdal-config'}) {
-    $gdal_config = $ARGV{'--gdal-config'};
-}
-my $config;
-if ($gdal_config) {
-    if (-r $gdal_config) {
-        $config = $gdal_config;
-    } else {
-        die "The gdal-config '$gdal_config' does not exist or is unreadable.\n";
-    }
-} else {
-    # scan known possible locations in the order of preference:
-    my @configs;
-    for ('c:/msys/1.0/local/bin/gdal-config',
-         '/usr/local/bin/gdal-config',
-         '/usr/bin/gdal-config') {
-        push @configs, $_ if -r $_;
-    }
-    if (@configs) {
-        $config = $configs[0];
-        if (@configs) {
-            print "Found gdal-config(s): '",join("', '", @configs),"'.\n";
-            print "Will try '$config'.\n";
-        } else {
-            print STDERR "Did not find any gdal-config(s)\n";
-        }
-    }
-}
-
-if (!$config && $downloads_are_ok) {
-    $source_tree = download_and_compile_gdal($my_gdal_version);
-    $config = "$source_tree/apps/gdal-config";
-}
-
-my $uri = gdal_source_location($my_gdal_version);
-
-my $gdal_version = get_gdal_version($config);
-my $different_versions = $my_gdal_version ne $gdal_version;
-
-my $msg = <<end;
-
-The version of the GDAL development files you spefied is different
-from the version these bindings were developed for (I have
-$my_gdal_version and $config has $gdal_version). 
-You can either
-
-- get GDAL development files from $uri or from wherever you get
-  development files for your system,
-
-- specify another gdal-config,
-
-- allow building against a different version of GDAL development files
-  (with --no-version-check or by setting the environment variable
-  PERL_GDAL_NO_VERSION_CHECK to a true value) - this is however not
-  recommended, or
-
-- let me download and build GDAL for you. It will happen automatically
-  if you clear the command line and remove environment variables that
-  may prevent it (see --help).
-
-end
-
-die $msg if ($gdal_config && $different_versions && !$versions_may_differ) ||
-    (!$downloads_are_ok && $different_versions && !$versions_may_differ);
-
-if ($different_versions && !$gdal_config && !$versions_may_differ && $downloads_are_ok) {
-    $source_tree = download_and_compile_gdal($my_gdal_version, $gdal_version);
-    $config = "$source_tree/apps/gdal-config";
-}
-
-# still in the game?
-
-my $have_gnm = `grep "CONFIG_GNM_ENABLED" $config`;
-my $have_ogr = `grep "CONFIG_OGR_ENABLED" $config`;
-for ($have_gnm, $have_ogr) {
-    chomp;
-    $_ = /yes/ ? 1 : 0;
+        "You have to first say \"cd $source_tree; make\".";
 }
 
-my ($INC, $LIB) = get_gdal_inc_lib($config);
-
-my %object = ( 'Geo::GDAL' => 'gdal_wrap.o',
-               'Geo::GDAL::Const' => 'gdalconst_wrap.o',
-               'Geo::OSR' => 'osr_wrap.o' );
-
-$object{'Geo::OGR'} = 'ogr_wrap.o' if $have_ogr;
-$object{'Geo::GNM'} = 'gnm_wrap.o' if $have_gnm;
+my ($INC, $LIB, $objects) = get_config($config);
 
-if ($ARGV{'--debug'}) {
-    print "LIB = $LIB\n";
-    print "INC = $INC\n";
-}
-
-for my $module (sort keys %object) {
+for my $module (sort keys %$objects) {
     my $add = $module;
     $add =~ s/:/_/g;
     my $LD = $Config{ld};
@@ -194,254 +33,64 @@ for my $module (sort keys %object) {
     $OPTIMIZE .= ' '.$ENV{CPPFLAGS} if $ENV{CFLAGS};
     
     my %PM = ( 'lib/Geo/GDAL.pm' => '$(INST_LIBDIR)/GDAL.pm',
+               'lib/Geo/OGR.pm' => '$(INST_LIBDIR)/OGR.pm',
                'lib/Geo/OSR.pm' => '$(INST_LIBDIR)/OSR.pm',
                'lib/Geo/GDAL/Const.pm' => '$(INST_LIBDIR)/GDAL/Const.pm' );
     
-    $PM{'lib/Geo/OGR.pm'} = '$(INST_LIBDIR)/OGR.pm' if $have_ogr;
-    $PM{'lib/Geo/GNM.pm'} = '$(INST_LIBDIR)/GNM.pm' if $have_gnm;
+    $PM{'lib/Geo/GNM.pm'} = '$(INST_LIBDIR)/GNM.pm' if $objects->{'Geo::GNM'};
 
     WriteMakefile( NAME => $module,
                    VERSION_FROM => 'lib/Geo/GDAL.pm',
-                   ABSTRACT_FROM => 'lib/Geo/GDAL.pm',
+                   ABSTRACT => 'Perl extension for the GDAL library for geospatial data',
                    AUTHOR => 'Ari Jolma <ari.jolma at gmail.com>',
-                   LICENSE => 'mit',
-                   META_MERGE => {
-                       'meta-spec' => { version => 2 },
-                       resources => {
-                           repository => {
-                               type => 'svn',
-                               url  => 'https://svn.osgeo.org/gdal/trunk/gdal/swig/perl',
-                               web  => 'https://trac.osgeo.org/gdal/browser/trunk/gdal/swig/perl',
-                           },
-                       },
-                   },
                    MAKEFILE => 'Makefile_'.$add,
                    LIBS => $LIB,
                    INC => $INC,
                    OPTIMIZE => $OPTIMIZE,
                    LD => $LD,
-                   OBJECT => $object{$module},
-                   PM => \%PM,
-                   CONFIGURE_REQUIRES => {
-                       'strict' => 0,
-                       'warnings' => 0,
-                       'File::Basename' => 0,
-                       'ExtUtils::MakeMaker' => 0,
-                       'Config' => 0,
-                       'Cwd' => 0,
-                       'File::Fetch' => 0,
-                       'Capture::Tiny' => 0,
-                   },
-                   BUILD_REQUIRES => {
-                       'strict' => 0,
-                       'warnings' => 0,
-                       'File::Basename' => 0,
-                       'ExtUtils::MakeMaker' => 0,
-                       'Config' => 0,
-                       'File::Fetch' => 0,
-                       'Capture::Tiny' => 0,
-                       'Cwd' => 0 
-                   },
-                   PREREQ_PM => {
-                       Carp => 0,
-                       Encode => 0,
-                       'Scalar::Util' => 0,
-                       POSIX => 0 
-                   },
-                   TEST_REQUIRES => {
-                       'Scalar::Util' => 0,
-                       'Test::More' => 0,
-                       'Encode' => 0,
-                       POSIX => 0
-                   }
-        );
+                   OBJECT => $objects->{$module},
+                   PM => \%PM );
 }
 
-sub gdal_source_location {
-    my $version = shift;
-    return "http://download.osgeo.org/gdal/$version/gdal-$version.tar.gz";
-}
-
-sub download_and_compile_gdal {
-    my ($version, $got_version) = @_;
-    
-    if (not defined $got_version) {
-        print STDERR <<end;
-
-I did not find GDAL development files. I am going to try to download
-and compile GDAL for you. You can prevent this happening by a command
-line argument --no-downloads or by setting the environment variable
-PERL_GDAL_NO_DOWNLOADS to a true value, or by specifying a good
-gdal-config with --gdal-config or the environment variable
-PERL_GDAL_CONFIG. If the version of the GDAL development files is
-different from what I have (it is $version) I will be back here.
-end
-
-    } else {
-        print STDERR <<end;
-
-The GDAL development files you gave or I found have a different
-version ($got_version) than what these bindings were developed for
-($version). I am going to try to download and compile GDAL for you.
-You can prevent this happening by pointing me to good GDAL development
-files, with a command line argument --no-downloads or by setting the
-environment variable PERL_GDAL_NO_DOWNLOADS to a true value, or by
-being adventurous by specifying --no-version-check or setting the
-environment variable PERL_GDAL_NO_VERSION_CHECK.
-end
-
-}
-    print STDERR <<end;
-
-Note that this automatic download and compile is mostly meant for
-automatic tests etc. It is recommended that you download and configure
-GDAL by hand. This may take a very long time. I will capture the
-output from the build and put it into gdal-build.log and
-gdal-build.err. You can look into them while this goes on but the
-output will be buffered.
-
-end
-
-{ 
-    require File::Fetch;
-    require Capture::Tiny;
-    Capture::Tiny->import(':all');
-    my $pwd = cwd();
-    open(my $log, ">", "gdal-build.log") 
-        or die "Can't open gdal-build.log: $!.";
-    open(my $err, ">", "gdal-build.err") 
-        or die "Can't open gdal-build.err: $!.";
-
-    my $step = sub {
-        my @cmd = @_;
-        my $ret;
-        print "@cmd\n";
-        my $code = sub {
-            if ($cmd[0] eq 'cd') {
-                $ret = chdir($cmd[1]);
-            } else {
-                $ret = system(@cmd);
-            }
-        };
-        my ($stdout, $stderr, $exit) = capture($code);
-        print $err $stderr;
-        print $log $stdout;
-        return $cmd[0] eq 'cd' ? $ret : ($ret == 0);
-    };
-
-    my $gdal = "gdal-$version";
-    my $uri = gdal_source_location($version);
-    my $ok = 1;
-    
-    print "get GDAL version $version\n";
-    my $code = sub {
-        if ($version eq '2.0.0' or $version eq '2.0.1') {
-            print "$version is buggy, get latest from 2.0 branch.\n";
-            $ok = $step->("svn", "checkout", "https://svn.osgeo.org/gdal/branches/2.0/gdal", "gdal");
-            $gdal = "gdal";
-        } 
-        elsif (-r "gdal-$version.tar.gz" and -s "gdal-$version.tar.gz") { # fetch leaves a zero sized file even when it fails
-            print "Using existing \"$gdal.tar.gz\"\n";
-            $ok = $step->("tar", "zxf", "$gdal.tar.gz");
-        }
-        else {
-            print "Attempting to fetch '$uri'\n";
-            my $ff = File::Fetch->new(uri => $uri);
-            $ok = $ff->fetch() if $ff;
-            if ($ok) {
-                $ok = $step->("tar", "zxf", "$gdal.tar.gz");
-            } else {
-                print "No luck. Maybe this is the development version?\n";
-                $ok = $step->("svn", "checkout", "https://svn.osgeo.org/gdal/trunk/gdal", "gdal");
-                $gdal = "gdal";
-            }
-        }
-    };
-    my ($stdout, $stderr, $exit) = capture($code);
-    print $err $stderr;
-    print $log $stdout;
-    if ($ok) {
-        for my $cmd (["cd", $gdal],
-                     ["./configure"],
-                     [($^O =~ /bsd/i ? "gmake" : "make"), "-j4"],
-                     ["cd", ".."]) 
-        {
-            $ok = $step->(@$cmd);
-            last unless $ok;
-        }
-    }
-    close $log;
-    close $err;
-    return "./$gdal" if $ok;
-    chdir($pwd);
-    open($err, "<", "gdal-build.err") 
-        or die "Can't open gdal-build.err: $!.";
-    my @err = <$err>;
-    close $err;
-    die "Downloading and compiling of GDAL failed.\n".
-        "The error is probably explained by the error log.\n".
-        "It is '$pwd/gdal-build.err'.\n".
-        "@err\n";
-}}
-
-sub get_gdal_version {
-    my $config = shift;
-    my $version;
-    if (-x $config) {
-        chomp($version = `$config --version`);
-    }
-    else {
-        if (open(my $fh, $config) || die "Can't open '$config': $!") {
-            for (<$fh>) {
-                ($version) = /(\d+\.\d+\.\d+)/ if /^CONFIG_VERSION/;
-            }
-            close $fh;
-        }
-        die "Can't find version from '$config'." unless $version;
-    }
-    return $version;
-}
-
-sub get_gdal_inc_lib {
+sub get_config {
     my $config = shift;
-    my ($INC, $LIB) = ('', '');
-    if ($source_tree) {
-        $LIB = "-L$source_tree/.libs -L$source_tree -lgdal ";
-        chomp($INC = `$config --cflags`);
-        $INC .= " -I$source_tree/gnm " if $have_gnm;
-    }
-    elsif (-x $config) {
-        chomp($INC = `$config --cflags`);
-        chomp($LIB = `$config --libs`);
-    }
-    else {
-        if (open(my $fh, $config) || die "Can't open '$config': $!") {
-            for (<$fh>) {
-                if (/^CONFIG_LIBS/) {
-                    s/^CONFIG_LIBS="//;
-                    s/"\s*$//;
-                    if ($_ =~ /\.la$/) { 
-                        $LIB .= parse_libtool_library_file_for_l($_);
-                    } else {
-                        $LIB .= $_;
-                    }
-                    $LIB .= ' ';
-                }
-                if (/^CONFIG_DEP_LIBS/) {
-                    s/^CONFIG_DEP_LIBS="//;
-                    s/"\s*$//;
+    my $INC = "-I$source_tree ";
+    my $LIB = "-L$source_tree/.libs -L$source_tree -lgdal ";
+    my $objects = { 
+        'Geo::GDAL' => 'gdal_wrap.o',
+        'Geo::OGR' => 'ogr_wrap.o',
+        'Geo::GDAL::Const' => 'gdalconst_wrap.o',
+        'Geo::OSR' => 'osr_wrap.o' };
+    if (open(my $fh, $config) || die "Can't open '$config': $!") {
+        for (<$fh>) {
+            if (/^CONFIG_LIBS/) {
+                s/^CONFIG_LIBS="//;
+                s/"\s*$//;
+                if ($_ =~ /\.la$/) { 
+                    $LIB .= parse_libtool_library_file_for_l($_);
+                } else {
                     $LIB .= $_;
                 }
-                if (/^CONFIG_CFLAGS/) {
-                    s/^CONFIG_CFLAGS="//;
-                    s/"\s*$//;
-                    $INC .= $_;
-                }
+                $LIB .= ' ';
+            }
+            if (/^CONFIG_DEP_LIBS/) {
+                s/^CONFIG_DEP_LIBS="//;
+                s/"\s*$//;
+                $LIB .= $_;
+            }
+            if (/^CONFIG_CFLAGS/) {
+                s/^CONFIG_CFLAGS="//;
+                s/"\s*$//;
+                $INC .= $_;
+            }
+            if (/CONFIG_GNM_ENABLED/ and /yes/) {
+                $objects->{'Geo::GNM'} = 'gnm_wrap.o';
+                $INC .= " -I$source_tree/gnm ";
             }
-            close $fh;
         }
+        close $fh;
     }
-    return ($INC, $LIB);
+    return ($INC, $LIB, $objects);
 }
 
 sub parse_libtool_library_file_for_l {
diff --git a/swig/perl/README b/swig/perl/README
index 377ec19..6acb70a 100644
--- a/swig/perl/README
+++ b/swig/perl/README
@@ -1,58 +1,13 @@
 Geo-GDAL
 =======================
 
-This is the swig-generated Perl interface to the GDAL/OGR library. The
-master copy of this module is developed and distributed with GDAL. 
-GDAL is available from www.gdal.org.
+This is the swig-generated Perl interface to the GDAL/OGR library.
 
-You need to have the development (header files etc.) versions of gdal and
-geos libraries available in your system to build these modules.
-
-The versions of GDAL and this interface must match. Makefile.PL
-attempts to do that, but it is highly recommended to install Geo::GDAL
-from GDAL sources.
-
-This module is _not_ compatible with Geo::GDAL 0.11
-
-INSTALLATION FROM CPAN DISTRIBUTION
-
-When this module is installed from a CPAN distribution, it must first
-find GDAL development files. That is basically about finding the
-gdal-config script. You can specify gdal-config or you can let
-Makefile.PL search for it. However, this module is usually very
-specific about the version of the GDAL it can be built against. The
-branch needs to be the same.
-
-If gdal-config was not found or its version is not good and
-Makefile.PL had to look it by itself, Makefile.PL will try to download
-and build GDAL. That is mostly meant for automatic testing only.
-
-Control the GDAL that this module is built against:
-
-  --gdal-config=PATH  use PATH as the gdal-config
-    the same as environment variable PERL_GDAL_CONFIG=PATH
-
-  --no-version-check  allow building against GDAL with different version
-    the same as setting environment variable PERL_GDAL_NO_VERSION_CHECK=1
-
-  --no-downloads      disable fetching GDAL source code as a last resort
-    the same as setting environment variable PERL_GDAL_NO_DOWNLOADS=1
-
-More information about running Makefile.PL is available at
-ExtUtils-MakeMaker documentation.
-
-To build, test and install this module the basic steps are
-
-perl Makefile.PL
-make
-make test
-make install
-
-INSTALLATION FROM GDAL SOURCE TREE
+INSTALLATION
 
 This module will be built and installed as a part of gdal build and
 installation, if you use --with-perl in configure of gdal. That
-process is controlled by GNUmakefile. 
+process is controlled by GNUmakefile.
 
 The build process comprises three steps:
 
@@ -96,24 +51,12 @@ make -f Makefile_Geo__OSR
 this is done by simple 'make' with the help of the GNUmakefile
 or Makefile in the case of dmake.
 
-The wrappers (*_wrap.c*) are already made in distribution packages.
-The wrappers in the repository are not guaranteed to be the latest
-ones.
-
-The wrappers may be tested with
-
-make -f Makefile_Geo__GDAL test
-
-or simply
+The bindings may be tested with
 
 make test
 
 You may need to edit the Makefile.PL.
 
-DEPENDENCIES
-
-This module requires the GDAL library.
-
 DOCUMENTATION
 
 The documentation is maintained in Doxygen files. You will also need
@@ -121,12 +64,11 @@ Doxygen-Filter-Perl. To generate the documentation type
 
 make doc
 
-You can find the documentation also at ajolma.net.
+You can find the documentation also at http://arijolma.org/Geo-GDAL/snapshot/.
 
 GDAL: http://www.gdal.org/
 Doxygen : http://www.doxygen.org
 Doxygen-Filter-Perl: http://search.cpan.org/~jordan/Doxygen-Filter-Perl/
-Geo::GDAL documentation: http://ajolma.net/Geo-GDAL/snapshot/
 
 COPYRIGHT AND LICENCE
 
diff --git a/swig/perl/cv.dox b/swig/perl/cv.dox
index a6a7517..ad129df 100644
--- a/swig/perl/cv.dox
+++ b/swig/perl/cv.dox
@@ -34,7 +34,7 @@ die "Can't create data source $dsname: $@" if $@;
 $osr = Geo::OSR::SpatialReference->new(WGS => 84);
 
 $layer = $datasource->CreateLayer(
-    Name => $lname, 
+    Name => $lname,
     SRS => $osr,
     # add the fields as in @data
     Fields => [
@@ -44,9 +44,9 @@ $layer = $datasource->CreateLayer(
     );
 
 for $item (@data) {
-    my @ring = ( $item->{points}[0], 
-                 $item->{points}[1], 
-                 $item->{points}[2], 
+    my @ring = ( $item->{points}[0],
+                 $item->{points}[1],
+                 $item->{points}[2],
                  $item->{points}[3],
                  $item->{points}[0] # close the ring
         );
@@ -61,7 +61,7 @@ for $item (@data) {
 # check that we got it ok
 
 $layer = $datasource->GetLayer($lname);
-while ($feature = $layer->GetNextFeature()) {  
+while ($feature = $layer->GetNextFeature()) {
     $feature->DumpReadable;
 }
 \endcode
diff --git a/swig/perl/gdal_wrap.cpp b/swig/perl/gdal_wrap.cpp
index 7a4a16d..9b69b56 100644
--- a/swig/perl/gdal_wrap.cpp
+++ b/swig/perl/gdal_wrap.cpp
@@ -1532,24 +1532,25 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 #define SWIGTYPE_p_GDAL_GCP swig_types[23]
 #define SWIGTYPE_p_GIntBig swig_types[24]
 #define SWIGTYPE_p_GUIntBig swig_types[25]
-#define SWIGTYPE_p_OGRGeometryShadow swig_types[26]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[27]
-#define SWIGTYPE_p_OGRStyleTableShadow swig_types[28]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[29]
-#define SWIGTYPE_p_VSIStatBufL swig_types[30]
-#define SWIGTYPE_p_VSIWriteFunction swig_types[31]
-#define SWIGTYPE_p_char swig_types[32]
-#define SWIGTYPE_p_double swig_types[33]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[34]
-#define SWIGTYPE_p_int swig_types[35]
-#define SWIGTYPE_p_p_GDALDatasetShadow swig_types[36]
-#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[37]
-#define SWIGTYPE_p_p_GDAL_GCP swig_types[38]
-#define SWIGTYPE_p_p_GUIntBig swig_types[39]
-#define SWIGTYPE_p_p_char swig_types[40]
-#define SWIGTYPE_p_void swig_types[41]
-static swig_type_info *swig_types[43];
-static swig_module_info swig_module = {swig_types, 42, 0, 0, 0, 0};
+#define SWIGTYPE_p_OGRFeatureShadow swig_types[26]
+#define SWIGTYPE_p_OGRGeometryShadow swig_types[27]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[28]
+#define SWIGTYPE_p_OGRStyleTableShadow swig_types[29]
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[30]
+#define SWIGTYPE_p_VSIStatBufL swig_types[31]
+#define SWIGTYPE_p_VSIWriteFunction swig_types[32]
+#define SWIGTYPE_p_char swig_types[33]
+#define SWIGTYPE_p_double swig_types[34]
+#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[35]
+#define SWIGTYPE_p_int swig_types[36]
+#define SWIGTYPE_p_p_GDALDatasetShadow swig_types[37]
+#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[38]
+#define SWIGTYPE_p_p_GDAL_GCP swig_types[39]
+#define SWIGTYPE_p_p_GUIntBig swig_types[40]
+#define SWIGTYPE_p_p_char swig_types[41]
+#define SWIGTYPE_p_void swig_types[42]
+static swig_type_info *swig_types[44];
+static swig_module_info swig_module = {swig_types, 43, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -1612,10 +1613,12 @@ typedef void GDALAsyncReaderShadow;
 #ifdef DEBUG
 typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
 typedef struct OGRLayerHS OGRLayerShadow;
+typedef struct OGRFeatureHS OGRFeatureShadow;
 typedef struct OGRGeometryHS OGRGeometryShadow;
 #else
 typedef void OSRSpatialReferenceShadow;
 typedef void OGRLayerShadow;
+typedef void OGRFeatureShadow;
 typedef void OGRGeometryShadow;
 #endif
 typedef struct OGRStyleTableHS OGRStyleTableShadow;
@@ -1704,11 +1707,13 @@ typedef int VSI_RETVAL;
     #define NEED_DEF "A parameter which must be defined or not empty, is not."
     #define WRONG_CLASS "Object has a wrong class."
     #define NEED_REF "A parameter which must be a reference, is not."
+    #define NEED_HASH_REF "A parameter/item which must be a hash reference, is not."
     #define NEED_ARRAY_REF "A parameter/item which must be an array reference, is not."
     #define NEED_BINARY_DATA "A parameter which must be binary data, is not."
     #define NEED_CODE_REF "A parameter which must be an anonymous subroutine, is not."
     #define WRONG_ITEM_IN_ARRAY "An item in an array parameter has wrong type."
     #define ARRAY_TO_XML_FAILED "An array parameter cannot be converted to an XMLTree."
+    #define NOT_ENOUGH_ELEMENTS "The supplied array does not have enough elements."
 
 
 void VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg ) {
@@ -1735,7 +1740,116 @@ void DontUseExceptions() {
 }
 
 
-typedef void OGRLayerShadow;
+  double NVClassify(int comparison, double nv, AV* classifier, const char **error) {
+     /* recursive, return nv < classifier[0] ? classifier[1] : classifier[2]
+        returns error if there are not three values in the classifier,
+        first is not a number, or second or third are not a number of arrayref
+     */
+     SV** f = av_fetch(classifier, 0, 0);
+     SV** s = av_fetch(classifier, 1, 0);
+     SV** t = av_fetch(classifier, 2, 0);
+     if (f && SvNOK(*f)) {
+         switch(comparison) {
+         case 0: /* lt */
+         if (nv < SvNV(*f))
+             t = s;
+         break;
+         case 1: /* lte */
+         if (nv <= SvNV(*f))
+             t = s;
+         break;
+         case 2: /* gt */
+         if (nv > SvNV(*f))
+             t = s;
+         break;
+         case 3: /* gte */
+         if (nv >= SvNV(*f))
+             t = s;
+         break;
+         }
+         if (t && SvNOK(*t))
+             return SvNV(*t);
+         else if (t && SvROK(*t) && (SvTYPE(SvRV(*t)) == SVt_PVAV))
+             return NVClassify(comparison, nv, (AV*)(SvRV(*t)), error);
+         else {
+             *error = "The decision in a classifier must be a number or a reference to a classifier.";
+             return 0;
+         }
+     } else {
+         *error = "The first value in a classifier must be a number.";
+         return 0;
+     }
+  }
+  void NVClass(int comparison, double nv, AV* classifier, int *klass, const char **error) {
+     /* recursive, return nv < classifier[0] ? classifier[1] : classifier[2]
+        returns NULL if there are not three values in the classifier,
+        first is not a number, or second or third are not a number of arrayref
+     */
+     SV** f = av_fetch(classifier, 0, 0);
+     SV** s = av_fetch(classifier, 1, 0);
+     SV** t = av_fetch(classifier, 2, 0);
+     if (f && SvNOK(*f)) {
+         ++*klass;
+         switch(comparison) {
+         case 0: /* lt */
+         if (nv < SvNV(*f))
+             --*klass;
+             t = s;
+         break;
+         case 1: /* lte */
+         if (nv <= SvNV(*f))
+             --*klass;
+             t = s;
+         break;
+         case 2: /* gt */
+         if (nv > SvNV(*f))
+             --*klass;
+             t = s;
+         break;
+         case 3: /* gte */
+         if (nv >= SvNV(*f))
+             --*klass;
+             t = s;
+         break;
+         }
+         if (t && SvNOK(*t))
+             return;
+         else if (t && SvROK(*t) && (SvTYPE(SvRV(*t)) == SVt_PVAV))
+             NVClass(comparison, nv, (AV*)(SvRV(*t)), klass, error);
+         else {
+             *error = "The decision in a classifier must be a number or a reference to a classifier.";
+             return;
+         }
+     } else {
+         *error = "The first value in a classifier must be a number.";
+         return;
+     }
+  }
+  AV* to_array_classifier(SV* classifier, int* comparison, const char **error) {
+      if (SvROK(classifier) && (SvTYPE(SvRV(classifier)) == SVt_PVAV)) {
+          SV** f = av_fetch((AV*)SvRV(classifier), 0, 0);
+          SV** s = av_fetch((AV*)SvRV(classifier), 1, 0);
+          if (f && SvPOK(*f)) {
+              char *c = SvPV_nolen(*f);
+              if (strcmp(c, "<") == 0)
+                  *comparison = 0;
+              else if (strcmp(c, "<=") == 0)
+                  *comparison = 1;
+              else if (strcmp(c, ">") == 0)
+                  *comparison = 2;
+              else if (strcmp(c, ">=") == 0)
+                  *comparison = 3;
+              else
+                  *error = "The first element in classifier object must be a comparison.";
+          }
+          if (s && SvROK(*s) && (SvTYPE(SvRV(*s)) == SVt_PVAV))
+              return (AV*)SvRV(*s);
+          else
+              *error = "The second element in classifier object must be an array reference.";
+      } else {
+          *error = NEED_ARRAY_REF;
+      }
+  }
 
 
 typedef char retStringAndCPLFree;
@@ -2008,9 +2122,11 @@ SWIG_From_int  SWIG_PERL_DECL_ARGS_1(int value)
 }
 
 
-    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf) {
-        /* if tmpbuf, only tmpbuf is freed; if not, ret is freed*/
+    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf, bool *safefree = NULL) {
+        /* if tmpbuf is given, only tmpbuf needs to be freed, use Safefree!
+           if not, ret needs to be freed, if safefree use Safefree else use free! */
         char *ret;
+        if (safefree) *safefree = false;
         if (SvOK(sv)) {
             STRLEN len;
             ret = SvPV(sv, len);
@@ -2021,6 +2137,7 @@ SWIG_From_int  SWIG_PERL_DECL_ARGS_1(int value)
                 } else {
                     ret = (char *)bytes_to_utf8((const U8*)ret, &len);
                 }
+                if (safefree) *safefree = true;
             } else {
                 if (!tmpbuf)
                     ret = strdup(ret);
@@ -2451,7 +2568,7 @@ CPLErr DSReadRaster_internal( GDALDatasetShadow *obj,
   }
   else
   {
-    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate "CPL_FRMT_GIB" bytes", *buf_size);
+    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate " CPL_FRMT_GIB " bytes", *buf_size);
     result = CE_Failure;
     *buf = 0;
     *buf_size = 0;
@@ -2730,6 +2847,12 @@ SWIGINTERN OGRLayerShadow *GDALDatasetShadow_GetLayerByName(GDALDatasetShadow *s
     OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetGetLayerByName(self, layer_name);
     return layer;
   }
+SWIGINTERN void GDALDatasetShadow_ResetReading(GDALDatasetShadow *self){
+    GDALDatasetResetReading( self );
+  }
+SWIGINTERN OGRFeatureShadow *GDALDatasetShadow_GetNextFeature(GDALDatasetShadow *self){
+    return GDALDatasetGetNextFeature( self, NULL, NULL, NULL, NULL );
+  }
 SWIGINTERN bool GDALDatasetShadow_TestCapability(GDALDatasetShadow *self,char const *cap){
     return (GDALDatasetTestCapability(self, cap) > 0);
   }
@@ -2868,7 +2991,7 @@ CPLErr ReadRaster_internal( GDALRasterBandShadow *obj,
   }
   else
   {
-    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate "CPL_FRMT_GIB" bytes", *buf_size);
+    CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory to allocate " CPL_FRMT_GIB " bytes", *buf_size);
     result = CE_Failure;
     *buf = 0;
     *buf_size = 0;
@@ -3118,6 +3241,284 @@ SWIGINTERN CPLErr GDALRasterBandShadow_ContourGenerate(GDALRasterBandShadow *sel
                                     progress,
                                     progress_data );
     }
+SWIGINTERN SV *GDALRasterBandShadow_ClassCounts__SWIG_0(GDALRasterBandShadow *self,GDALProgressFunc callback=NULL,void *callback_data=NULL){
+        GDALDataType dt = GDALGetRasterDataType(self);
+        if (!(dt == GDT_Byte || dt == GDT_UInt16 || dt == GDT_Int16 || dt == GDT_UInt32 || dt == GDT_Int32)) {
+            do_confess("ClassCounts without classifier requires an integer band.", 1);
+        }
+        HV* hash = newHV();
+        int XBlockSize, YBlockSize;
+        GDALGetBlockSize( self, &XBlockSize, &YBlockSize );
+        int XBlocks = (GDALGetRasterBandXSize(self) + XBlockSize - 1) / XBlockSize;
+        int YBlocks = (GDALGetRasterBandYSize(self) + YBlockSize - 1) / YBlockSize;
+        void *data = CPLMalloc(XBlockSize * YBlockSize * GDALGetDataTypeSizeBytes(dt));
+        for (int yb = 0; yb < YBlocks; ++yb) {
+            if (callback) {
+                double p = (double)yb/(double)YBlocks;
+                if (!callback(p, "", callback_data)) {
+                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
+                    hv_undef(hash);
+                    hash = NULL;
+                    break;
+                }
+            }
+            for (int xb = 0; xb < XBlocks; ++xb) {
+                int XValid, YValid;
+                CPLErr e = GDALReadBlock(self, xb, yb, data);
+                GDALGetActualBlockSize(self, xb, yb, &XValid, &YValid);
+                for (int iY = 0; iY < YValid; ++iY) {
+                    for (int iX = 0; iX < XValid; ++iX) {
+                        int32_t k;
+                        switch(dt) {
+                        case GDT_Byte:
+                          k = ((GByte*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_UInt16:
+                          k = ((GUInt16*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Int16:
+                          k = ((GInt16*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_UInt32:
+                          k = ((GUInt32*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Int32:
+                          k = ((GInt32*)(data))[iX + iY * XBlockSize];
+                          break;
+                        }
+                        char key[12];
+                        int klen = sprintf(key, "%i", k);
+                        SV* sv;
+                        SV** sv2 = hv_fetch(hash, key, klen, 0);
+                        if (sv2 && SvOK(*sv2)) {
+                            sv = *sv2;
+                            sv_setiv(sv, SvIV(sv)+1);
+                            SvREFCNT_inc(sv);
+                        } else {
+                            sv = newSViv(1);
+                        }
+                        if (!hv_store(hash, key, klen, sv, 0))
+                            SvREFCNT_dec(sv);
+                    }
+                }
+            }
+        }
+        CPLFree(data);
+        if (hash)
+            return newRV_noinc((SV*)hash);
+        else
+            return &PL_sv_undef;
+    }
+SWIGINTERN SV *GDALRasterBandShadow_ClassCounts__SWIG_1(GDALRasterBandShadow *self,SV *classifier,GDALProgressFunc callback=NULL,void *callback_data=NULL){
+                    
+        const char *error = NULL;
+        GDALDataType dt = GDALGetRasterDataType(self);
+        if (!(dt == GDT_Float32 || dt == GDT_Float64)) {
+            do_confess("ClassCounts with classifier requires a float band.", 1);
+        }
+
+        AV* array_classifier = NULL;
+        int comparison = 0;
+
+        array_classifier = to_array_classifier(classifier, &comparison, &error);
+        if (error) do_confess(error, 1);
+
+        HV* hash = newHV();
+        int XBlockSize, YBlockSize;
+        GDALGetBlockSize( self, &XBlockSize, &YBlockSize );
+        int XBlocks = (GDALGetRasterBandXSize(self) + XBlockSize - 1) / XBlockSize;
+        int YBlocks = (GDALGetRasterBandYSize(self) + YBlockSize - 1) / YBlockSize;
+        void *data = CPLMalloc(XBlockSize * YBlockSize * GDALGetDataTypeSizeBytes(dt));
+
+        for (int yb = 0; yb < YBlocks; ++yb) {
+            if (callback) {
+                double p = (double)yb/(double)YBlocks;
+                if (!callback(p, "", callback_data)) {
+                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
+                    hv_undef(hash);
+                    hash = NULL;
+                    break;
+                }
+            }
+            for (int xb = 0; xb < XBlocks; ++xb) {
+                int XValid, YValid;
+                CPLErr e = GDALReadBlock(self, xb, yb, data);
+                GDALGetActualBlockSize(self, xb, yb, &XValid, &YValid);
+                for (int iY = 0; iY < YValid; ++iY) {
+                    for (int iX = 0; iX < XValid; ++iX) {
+                        double nv = 0;
+                        switch(dt) {
+                        case GDT_Float32:
+                          nv = ((float*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Float64:
+                          nv = ((double*)(data))[iX + iY * XBlockSize];
+                          break;
+                        }
+                        int k = 0;
+                        NVClass(comparison, nv, array_classifier, &k, &error);
+                        if (error) goto fail;
+                        char key[12];
+                        int klen = sprintf(key, "%i", k);
+                        SV* sv;
+                        SV** sv2 = hv_fetch(hash, key, klen, 0);
+                        if (sv2 && SvOK(*sv2)) {
+                            sv = *sv2;
+                            sv_setiv(sv, SvIV(sv)+1);
+                            SvREFCNT_inc(sv);
+                        } else {
+                            sv = newSViv(1);
+                        }
+                        if (!hv_store(hash, key, klen, sv, 0))
+                            SvREFCNT_dec(sv);
+                    }
+                }
+            }
+        }
+        
+        CPLFree(data);
+        if (hash)
+            return newRV_noinc((SV*)hash);
+        else
+            return &PL_sv_undef;
+        fail:
+        CPLFree(data);
+        do_confess(error, 1);
+        return &PL_sv_undef;
+    }
+SWIGINTERN void GDALRasterBandShadow_Reclassify(GDALRasterBandShadow *self,SV *classifier,GDALProgressFunc callback=NULL,void *callback_data=NULL){
+                    
+        const char *error = NULL;
+        
+        GDALDataType dt = GDALGetRasterDataType(self);
+        
+        bool is_integer_raster = true;
+        HV* hash_classifier = NULL;
+        bool has_default = false;
+        int32_t deflt = 0;
+
+        AV* array_classifier = NULL;
+        int comparison = 0;
+        
+        if (dt == GDT_Byte || dt == GDT_UInt16 || dt == GDT_Int16 || dt == GDT_UInt32 || dt == GDT_Int32) {
+            if (SvROK(classifier) && (SvTYPE(SvRV(classifier)) == SVt_PVHV)) {
+                hash_classifier = (HV*)SvRV(classifier);
+                SV** sv = hv_fetch(hash_classifier, "*", 1, 0);
+                if (sv && SvOK(*sv)) {
+                    has_default = true;
+                    deflt = SvIV(*sv);
+                }
+            } else {
+                do_confess(NEED_HASH_REF, 1);
+            }
+        } else if (dt == GDT_Float32 || dt == GDT_Float64) {
+            is_integer_raster = false;
+            array_classifier = to_array_classifier(classifier, &comparison, &error);
+            if (error) do_confess(error, 1);
+        } else {
+            do_confess("Only integer and float rasters can be reclassified.", 1);
+        }
+        
+        int has_no_data;
+        double no_data = GDALGetRasterNoDataValue(self, &has_no_data);
+        int XBlockSize, YBlockSize;
+        GDALGetBlockSize( self, &XBlockSize, &YBlockSize );
+        int XBlocks = (GDALGetRasterBandXSize(self) + XBlockSize - 1) / XBlockSize;
+        int YBlocks = (GDALGetRasterBandYSize(self) + YBlockSize - 1) / YBlockSize;
+        void *data = CPLMalloc(XBlockSize * YBlockSize * GDALGetDataTypeSizeBytes(dt));
+
+        for (int yb = 0; yb < YBlocks; ++yb) {
+            if (callback) {
+                double p = (double)yb/(double)YBlocks;
+                if (!callback(p, "", callback_data)) {
+                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
+                    break;
+                }
+            }
+            for (int xb = 0; xb < XBlocks; ++xb) {
+                int XValid, YValid;
+                CPLErr e = GDALReadBlock(self, xb, yb, data);
+                GDALGetActualBlockSize(self, xb, yb, &XValid, &YValid);
+                for (int iY = 0; iY < YValid; ++iY) {
+                    for (int iX = 0; iX < XValid; ++iX) {
+                        int32_t k = 0;
+                        double nv = 0;
+                        switch(dt) {
+                        case GDT_Byte:
+                          k = ((GByte*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_UInt16:
+                          k = ((GUInt16*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Int16:
+                          k = ((GInt16*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_UInt32:
+                          k = ((GUInt32*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Int32:
+                          k = ((GInt32*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Float32:
+                          nv = ((float*)(data))[iX + iY * XBlockSize];
+                          break;
+                        case GDT_Float64:
+                          nv = ((double*)(data))[iX + iY * XBlockSize];
+                          break;
+                        }
+
+                        if (is_integer_raster) {
+                            char key[12];
+                            int klen = sprintf(key, "%i", k);
+                            SV** sv = hv_fetch(hash_classifier, key, klen, 0);
+                            if (sv && SvOK(*sv)) {
+                                k = SvIV(*sv);
+                            } else if (has_default) {
+                                if (!(has_no_data && k == no_data))
+                                    k = deflt;
+                                else
+                                    continue;
+                            }
+                        } else {
+                            nv = NVClassify(comparison, nv, array_classifier, &error);
+                            if (error) goto fail;
+                        }
+
+                        switch(dt) {
+                        case GDT_Byte:
+                          ((GByte*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_UInt16:
+                          ((GUInt16*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_Int16:
+                          ((GInt16*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_UInt32:
+                          ((GUInt32*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_Int32:
+                          ((GInt32*)(data))[iX + iY * XBlockSize] = k;
+                          break;
+                        case GDT_Float32:
+                          ((float*)(data))[iX + iY * XBlockSize] = nv;
+                          break;
+                        case GDT_Float64:
+                          ((double*)(data))[iX + iY * XBlockSize] = nv;
+                          break;
+                        }
+                    }
+                }
+                e = GDALWriteBlock(self, xb, yb, data);
+            }
+        }
+        CPLFree(data);
+        return;
+        fail:
+        CPLFree(data);
+        do_confess(error, 1);        
+        return;
+    }
 
 GDALDataType GDALRasterBandShadow_DataType_get( GDALRasterBandShadow *h ) {
   return GDALGetRasterDataType( h );
@@ -3576,6 +3977,22 @@ SWIGINTERN int GDALTransformerInfoShadow_TransformGeolocations(GDALTransformerIn
                             	      callback, callback_data, options );
   }
 
+GDALDatasetShadow* ApplyVerticalShiftGrid( GDALDatasetShadow *src_ds,
+                                           GDALDatasetShadow *grid_ds,
+                                           bool inverse = false,
+                                           double srcUnitToMeter = 1.0,
+                                           double dstUnitToMeter = 1.0,
+                                           char** options = NULL ) {
+  GDALDatasetShadow *ds = GDALApplyVerticalShiftGrid( src_ds, grid_ds,
+                                                      inverse,
+                                                      srcUnitToMeter,
+                                                      dstUnitToMeter,
+                                                      options );
+  return ds;
+
+}
+
+
 GIntBig wrapper_GDALGetCacheMax()
 {
     return GDALGetCacheMax64();
@@ -3646,9 +4063,10 @@ void wrapper_GDALSetCacheMax(GIntBig nBytes)
 
         nType = SvIV(*(av_fetch(av,0,0)));
         SV *sv = *(av_fetch(av,1,0));
-        char *tmp = sv_to_utf8_string(sv, NULL);
+        bool sf;
+        char *tmp = sv_to_utf8_string(sv, NULL, &sf);
         psThisNode = CPLCreateXMLNode(NULL, (CPLXMLNodeType)nType, tmp);
-        free(tmp);
+        if (sf) Safefree(tmp); else free(tmp);
 
         for( iChild = 0; iChild < nChildCount; iChild++ )
         {
@@ -3773,6 +4191,18 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
 }
 
 
+GDALDriverShadow *IdentifyDriverEx( const char* utf8_path,
+                                    unsigned int nIdentifyFlags = 0,
+                                    char** allowed_drivers = NULL,
+                                    char** sibling_files = NULL )
+{
+    return  (GDALDriverShadow *) GDALIdentifyDriverEx( utf8_path,
+                                                nIdentifyFlags,
+                                                allowed_drivers,
+                                                sibling_files );
+}
+
+
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
 
@@ -5250,13 +5680,13 @@ XS(_wrap_PushFinderLocation) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     XSRETURN(argvi);
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     SWIG_croak_null();
   }
@@ -5416,14 +5846,14 @@ XS(_wrap_FindFile) {
     if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -5522,14 +5952,14 @@ XS(_wrap_ReadDir) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     XSRETURN(argvi);
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     SWIG_croak_null();
@@ -5619,13 +6049,13 @@ XS(_wrap_ReadDirRecursive) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     XSRETURN(argvi);
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     SWIG_croak_null();
   }
@@ -5988,7 +6418,7 @@ XS(_wrap_FileFromMemBuffer) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -5996,7 +6426,7 @@ XS(_wrap_FileFromMemBuffer) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -6060,7 +6490,7 @@ XS(_wrap_Unlink) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(ret) VSI_RETVAL */
@@ -6072,7 +6502,7 @@ XS(_wrap_Unlink) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     SWIG_croak_null();
   }
@@ -6185,7 +6615,7 @@ XS(_wrap_Mkdir) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     {
@@ -6198,7 +6628,7 @@ XS(_wrap_Mkdir) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     SWIG_croak_null();
@@ -6261,7 +6691,7 @@ XS(_wrap_Rmdir) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(ret) VSI_RETVAL */
@@ -6273,7 +6703,7 @@ XS(_wrap_Rmdir) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     SWIG_croak_null();
   }
@@ -6352,11 +6782,11 @@ XS(_wrap_Rename) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     {
       /* %typemap(ret) VSI_RETVAL */
@@ -6368,11 +6798,11 @@ XS(_wrap_Rename) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -6456,7 +6886,7 @@ XS(_wrap_Stat) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     {
@@ -6469,7 +6899,7 @@ XS(_wrap_Stat) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     SWIG_croak_null();
@@ -6541,14 +6971,14 @@ XS(_wrap_VSIFOpenL) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     XSRETURN(argvi);
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     SWIG_croak_null();
@@ -6630,7 +7060,7 @@ XS(_wrap_VSIFOpenExL) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_void, 0 | 0); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
@@ -6638,7 +7068,7 @@ XS(_wrap_VSIFOpenExL) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     
@@ -7250,13 +7680,13 @@ XS(_wrap_ParseCommandLine) {
     }
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     XSRETURN(argvi);
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     SWIG_croak_null();
   }
@@ -8244,9 +8674,10 @@ XS(_wrap_Driver__Create) {
               AV *av = (AV*)(SvRV(ST(6)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg7 = CSLAddString(arg7, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(6)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(6));
@@ -8256,9 +8687,10 @@ XS(_wrap_Driver__Create) {
               arg7 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg7 = CSLAddNameValue(arg7, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -8300,7 +8732,7 @@ XS(_wrap_Driver__Create) {
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     
@@ -8315,7 +8747,7 @@ XS(_wrap_Driver__Create) {
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     
@@ -8400,9 +8832,10 @@ XS(_wrap_Driver__CreateCopy) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddString(arg5, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(4));
@@ -8412,9 +8845,10 @@ XS(_wrap_Driver__CreateCopy) {
               arg5 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddNameValue(arg5, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -8485,7 +8919,7 @@ XS(_wrap_Driver__CreateCopy) {
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     
@@ -8499,7 +8933,7 @@ XS(_wrap_Driver__CreateCopy) {
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     
@@ -8577,14 +9011,14 @@ XS(_wrap_Driver_Delete) {
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -11738,6 +12172,8 @@ XS(_wrap_Dataset_SetGeoTransform) {
       do_confess(NEED_ARRAY_REF, 1);
       arg2 = argin2;
       AV *av = (AV*)(SvRV(ST(1)));
+      if (av_len(av)+1 < 6)
+      do_confess(NOT_ENOUGH_ELEMENTS, 1);
       for (unsigned int i=0; i<6; i++) {
         SV *sv = *av_fetch(av, i, 0);
         if (!SvOK(sv))
@@ -12304,9 +12740,10 @@ XS(_wrap_Dataset__AddBand) {
               AV *av = (AV*)(SvRV(ST(2)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddString(arg3, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(2));
@@ -12316,9 +12753,10 @@ XS(_wrap_Dataset__AddBand) {
               arg3 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddNameValue(arg3, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -13113,9 +13551,10 @@ XS(_wrap_Dataset__CreateLayer) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddString(arg5, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(4));
@@ -13125,9 +13564,10 @@ XS(_wrap_Dataset__CreateLayer) {
               arg5 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddNameValue(arg5, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -13237,9 +13677,10 @@ XS(_wrap_Dataset_CopyLayer) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -13249,9 +13690,10 @@ XS(_wrap_Dataset_CopyLayer) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -13560,15 +14002,126 @@ XS(_wrap_Dataset_GetLayerByName) {
     
     {
       /* %typemap(freearg) (const char* layer_name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* layer_name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
+    }
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Dataset_ResetReading) {
+  {
+    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Dataset_ResetReading(self);");
+    }
+    {
+      /* %typemap(in) (GDALDatasetShadow *) */
+      void *argp = 0;
+      int res = SWIG_ConvertPtr(ST(0), &argp, SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+      if (!SWIG_IsOK(res)) {
+        do_confess(WRONG_CLASS, 1);
+      }
+      arg1 = reinterpret_cast< GDALDatasetShadow * >(argp);
+      if (arg1 == NULL)
+      do_confess(NEED_DEF, 1);
+    }
+    {
+      CPLErrorReset();
+      GDALDatasetShadow_ResetReading(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_Dataset_GetNextFeature) {
+  {
+    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+    int argvi = 0;
+    OGRFeatureShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Dataset_GetNextFeature(self);");
+    }
+    {
+      /* %typemap(in) (GDALDatasetShadow *) */
+      void *argp = 0;
+      int res = SWIG_ConvertPtr(ST(0), &argp, SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+      if (!SWIG_IsOK(res)) {
+        do_confess(WRONG_CLASS, 1);
+      }
+      arg1 = reinterpret_cast< GDALDatasetShadow * >(argp);
+      if (arg1 == NULL)
+      do_confess(NEED_DEF, 1);
+    }
+    {
+      CPLErrorReset();
+      result = (OGRFeatureShadow *)GDALDatasetShadow_GetNextFeature(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
     }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
     SWIG_croak_null();
   }
 }
@@ -15092,9 +15645,10 @@ XS(_wrap_Band_SetRasterCategoryNames) {
             AV *av = (AV*)(SvRV(ST(1)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddString(arg2, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(1));
@@ -15104,9 +15658,10 @@ XS(_wrap_Band_SetRasterCategoryNames) {
             arg2 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddNameValue(arg2, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -17950,9 +18505,10 @@ XS(_wrap_Band_SetCategoryNames) {
             AV *av = (AV*)(SvRV(ST(1)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddString(arg2, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(1));
@@ -17962,9 +18518,10 @@ XS(_wrap_Band_SetCategoryNames) {
             arg2 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddNameValue(arg2, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -18173,28 +18730,57 @@ XS(_wrap_Band_ContourGenerate) {
 }
 
 
-XS(_wrap_new_ColorTable) {
+XS(_wrap_Band_ClassCounts__SWIG_0) {
   {
-    GDALPaletteInterp arg1 = (GDALPaletteInterp) GPI_RGB ;
-    int val1 ;
-    int ecode1 = 0 ;
+    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+    GDALProgressFunc arg2 = (GDALProgressFunc) NULL ;
+    void *arg3 = (void *) NULL ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
     int argvi = 0;
-    GDALColorTableShadow *result = 0 ;
+    SV *result = 0 ;
     dXSARGS;
     
-    if ((items < 0) || (items > 1)) {
-      SWIG_croak("Usage: new_ColorTable(palette);");
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg3 = (void *)(&saved_env);
+    if ((items < 1) || (items > 3)) {
+      SWIG_croak("Usage: Band_ClassCounts(self,callback,callback_data);");
     }
-    if (items > 0) {
-      ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
-      if (!SWIG_IsOK(ecode1)) {
-        SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "new_ColorTable" "', argument " "1"" of type '" "GDALPaletteInterp""'");
-      } 
-      arg1 = static_cast< GDALPaletteInterp >(val1);
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_ClassCounts" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+    if (items > 1) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(1))) {
+          if (SvROK(ST(1))) {
+            if (SvTYPE(SvRV(ST(1))) != SVt_PVCV) {
+              do_confess(NEED_CODE_REF, 1);
+            } else {
+              saved_env.fct = (SV *)ST(1);
+              arg2 = &callback_d_cp_vp;
+            }
+          } else {
+            do_confess(NEED_CODE_REF, 1);
+          }
+        }
+      }
+    }
+    if (items > 2) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(2)))
+        saved_env.data = (SV *)ST(2);
+      }
     }
     {
       CPLErrorReset();
-      result = (GDALColorTableShadow *)new_GDALColorTableShadow(arg1);
+      result = (SV *)GDALRasterBandShadow_ClassCounts__SWIG_0(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -18216,35 +18802,71 @@ XS(_wrap_new_ColorTable) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    ST(argvi) = result; argvi++ ;
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_delete_ColorTable) {
+XS(_wrap_Band_ClassCounts__SWIG_1) {
   {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
+    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+    SV *arg2 = (SV *) 0 ;
+    GDALProgressFunc arg3 = (GDALProgressFunc) NULL ;
+    void *arg4 = (void *) NULL ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
+    SV *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: delete_ColorTable(self);");
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg4 = (void *)(&saved_env);
+    if ((items < 2) || (items > 4)) {
+      SWIG_croak("Usage: Band_ClassCounts(self,classifier,callback,callback_data);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, SWIG_POINTER_DISOWN |  0 );
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_ColorTable" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_ClassCounts" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+    arg2 = ST(1);
+    if (items > 2) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(2))) {
+          if (SvROK(ST(2))) {
+            if (SvTYPE(SvRV(ST(2))) != SVt_PVCV) {
+              do_confess(NEED_CODE_REF, 1);
+            } else {
+              saved_env.fct = (SV *)ST(2);
+              arg3 = &callback_d_cp_vp;
+            }
+          } else {
+            do_confess(NEED_CODE_REF, 1);
+          }
+        }
+      }
+    }
+    if (items > 3) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(3)))
+        saved_env.data = (SV *)ST(3);
+      }
     }
-    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
     {
       CPLErrorReset();
-      delete_GDALColorTableShadow(arg1);
+      result = (SV *)GDALRasterBandShadow_ClassCounts__SWIG_1(arg1,arg2,arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -18266,26 +18888,337 @@ XS(_wrap_delete_ColorTable) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
+    ST(argvi) = result; argvi++ ;
+    
+    
     
     XSRETURN(argvi);
   fail:
     
+    
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_ColorTable_Clone) {
+XS(_wrap_Band_ClassCounts) {
+  dXSARGS;
+  
   {
-    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GDALColorTableShadow *result = 0 ;
-    dXSARGS;
+    unsigned long _index = 0;
+    SWIG_TypeRank _rank = 0; 
+    if ((items >= 1) && (items <= 3)) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_GDALRasterBandShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_1;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (items > 1) {
+        {
+          {
+            /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) GDALProgressFunc callback */
+            _v = SvOK(ST(1)) && SvROK(ST(1)) && SvTYPE(SvRV(ST(1))) == SVt_PVCV;
+          }
+        }
+        if (!_v) goto check_1;
+        _ranki += _v*_pi;
+        _rankm += _pi;
+        _pi *= SWIG_MAXCASTRANK;
+        if (items > 2) {
+          {
+            void *ptr = 0;
+            int res = SWIG_ConvertPtr(ST(2), &ptr, 0, 0);
+            _v = SWIG_CheckState(res);
+          }
+          if (!_v) goto check_1;
+          _ranki += _v*_pi;
+          _rankm += _pi;
+          _pi *= SWIG_MAXCASTRANK;
+        }
+      }
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_1:
+    
+    if ((items >= 2) && (items <= 4)) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_GDALRasterBandShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        _v = (ST(1) != 0);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (items > 2) {
+        {
+          {
+            /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) GDALProgressFunc callback */
+            _v = SvOK(ST(2)) && SvROK(ST(2)) && SvTYPE(SvRV(ST(2))) == SVt_PVCV;
+          }
+        }
+        if (!_v) goto check_2;
+        _ranki += _v*_pi;
+        _rankm += _pi;
+        _pi *= SWIG_MAXCASTRANK;
+        if (items > 3) {
+          {
+            void *ptr = 0;
+            int res = SWIG_ConvertPtr(ST(3), &ptr, 0, 0);
+            _v = SWIG_CheckState(res);
+          }
+          if (!_v) goto check_2;
+          _ranki += _v*_pi;
+          _rankm += _pi;
+          _pi *= SWIG_MAXCASTRANK;
+        }
+      }
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 2;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_2:
+    
+  dispatch:
+    switch(_index) {
+    case 1:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Band_ClassCounts__SWIG_0); return;
+    case 2:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Band_ClassCounts__SWIG_1); return;
+    }
+  }
+  
+  croak("No matching function for overloaded 'Band_ClassCounts'");
+  XSRETURN(0);
+}
+
+
+XS(_wrap_Band_Reclassify) {
+  {
+    GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+    SV *arg2 = (SV *) 0 ;
+    GDALProgressFunc arg3 = (GDALProgressFunc) NULL ;
+    void *arg4 = (void *) NULL ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg4 = (void *)(&saved_env);
+    if ((items < 2) || (items > 4)) {
+      SWIG_croak("Usage: Band_Reclassify(self,classifier,callback,callback_data);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_Reclassify" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+    arg2 = ST(1);
+    if (items > 2) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(2))) {
+          if (SvROK(ST(2))) {
+            if (SvTYPE(SvRV(ST(2))) != SVt_PVCV) {
+              do_confess(NEED_CODE_REF, 1);
+            } else {
+              saved_env.fct = (SV *)ST(2);
+              arg3 = &callback_d_cp_vp;
+            }
+          } else {
+            do_confess(NEED_CODE_REF, 1);
+          }
+        }
+      }
+    }
+    if (items > 3) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(3)))
+        saved_env.data = (SV *)ST(3);
+      }
+    }
+    {
+      CPLErrorReset();
+      GDALRasterBandShadow_Reclassify(arg1,arg2,arg3,arg4);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_new_ColorTable) {
+  {
+    GDALPaletteInterp arg1 = (GDALPaletteInterp) GPI_RGB ;
+    int val1 ;
+    int ecode1 = 0 ;
+    int argvi = 0;
+    GDALColorTableShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 0) || (items > 1)) {
+      SWIG_croak("Usage: new_ColorTable(palette);");
+    }
+    if (items > 0) {
+      ecode1 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(0), &val1);
+      if (!SWIG_IsOK(ecode1)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "new_ColorTable" "', argument " "1"" of type '" "GDALPaletteInterp""'");
+      } 
+      arg1 = static_cast< GDALPaletteInterp >(val1);
+    }
+    {
+      CPLErrorReset();
+      result = (GDALColorTableShadow *)new_GDALColorTableShadow(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALColorTableShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_delete_ColorTable) {
+  {
+    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    dXSARGS;
+    
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: delete_ColorTable(self);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALColorTableShadow, SWIG_POINTER_DISOWN |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_ColorTable" "', argument " "1"" of type '" "GDALColorTableShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< GDALColorTableShadow * >(argp1);
+    {
+      CPLErrorReset();
+      delete_GDALColorTableShadow(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
+    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_ColorTable_Clone) {
+  {
+    GDALColorTableShadow *arg1 = (GDALColorTableShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int argvi = 0;
+    GDALColorTableShadow *result = 0 ;
+    dXSARGS;
     
     if ((items < 1) || (items > 1)) {
       SWIG_croak("Usage: ColorTable_Clone(self);");
@@ -19622,7 +20555,7 @@ XS(_wrap_RasterAttributeTable_SetValueAsString) {
     
     {
       /* %typemap(freearg) (tostring argin) */
-      if (tmpbuf4) free(tmpbuf4);
+      if (tmpbuf4) Safefree(tmpbuf4);
     }
     XSRETURN(argvi);
   fail:
@@ -19631,7 +20564,7 @@ XS(_wrap_RasterAttributeTable_SetValueAsString) {
     
     {
       /* %typemap(freearg) (tostring argin) */
-      if (tmpbuf4) free(tmpbuf4);
+      if (tmpbuf4) Safefree(tmpbuf4);
     }
     SWIG_croak_null();
   }
@@ -20749,9 +21682,10 @@ XS(_wrap__ReprojectImage) {
               AV *av = (AV*)(SvRV(ST(9)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg10 = CSLAddString(arg10, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(9)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(9));
@@ -20761,9 +21695,10 @@ XS(_wrap__ReprojectImage) {
               arg10 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg10 = CSLAddNameValue(arg10, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -20880,9 +21815,10 @@ XS(_wrap_ComputeProximity) {
               AV *av = (AV*)(SvRV(ST(2)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddString(arg3, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(2));
@@ -20892,9 +21828,10 @@ XS(_wrap_ComputeProximity) {
               arg3 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddNameValue(arg3, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -21081,9 +22018,10 @@ XS(_wrap_RasterizeLayer) {
               AV *av = (AV*)(SvRV(ST(6)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg9 = CSLAddString(arg9, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(6)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(6));
@@ -21093,9 +22031,10 @@ XS(_wrap_RasterizeLayer) {
               arg9 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg9 = CSLAddNameValue(arg9, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -21262,9 +22201,10 @@ XS(_wrap__Polygonize) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddString(arg5, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(4));
@@ -21274,9 +22214,10 @@ XS(_wrap__Polygonize) {
               arg5 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddNameValue(arg5, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -21427,9 +22368,10 @@ XS(_wrap_FPolygonize) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddString(arg5, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(4));
@@ -21439,9 +22381,10 @@ XS(_wrap_FPolygonize) {
               arg5 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddNameValue(arg5, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -21592,9 +22535,10 @@ XS(_wrap_FillNodata) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddString(arg5, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(4));
@@ -21604,9 +22548,10 @@ XS(_wrap_FillNodata) {
               arg5 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddNameValue(arg5, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -21762,9 +22707,10 @@ XS(_wrap_SieveFilter) {
               AV *av = (AV*)(SvRV(ST(5)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg6 = CSLAddString(arg6, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(5)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(5));
@@ -21774,9 +22720,10 @@ XS(_wrap_SieveFilter) {
               arg6 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg6 = CSLAddNameValue(arg6, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -22556,9 +23503,10 @@ XS(_wrap_new_Transformer) {
             AV *av = (AV*)(SvRV(ST(2)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg3 = CSLAddString(arg3, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(2));
@@ -22568,9 +23516,10 @@ XS(_wrap_new_Transformer) {
             arg3 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg3 = CSLAddNameValue(arg3, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -22708,6 +23657,8 @@ XS(_wrap_Transformer_TransformPoint__SWIG_0) {
       do_confess(NEED_ARRAY_REF, 1);
       arg3 = argin3;
       AV *av = (AV*)(SvRV(ST(2)));
+      if (av_len(av)+1 < 3)
+      do_confess(NOT_ENOUGH_ELEMENTS, 1);
       for (unsigned int i=0; i<3; i++) {
         SV *sv = *av_fetch(av, i, 0);
         if (!SvOK(sv))
@@ -23164,82 +24115,247 @@ XS(_wrap_Transformer_TransformGeolocations) {
     int result;
     dXSARGS;
     
-    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
-    SavedEnv saved_env;
-    saved_env.fct = NULL;
-    saved_env.data = &PL_sv_undef;
-    arg6 = (void *)(&saved_env);
-    if ((items < 4) || (items > 7)) {
-      SWIG_croak("Usage: Transformer_TransformGeolocations(self,xBand,yBand,zBand,callback,callback_data,options);");
+    /* %typemap(arginit, noblock=1) ( void* callback_data = NULL) */
+    SavedEnv saved_env;
+    saved_env.fct = NULL;
+    saved_env.data = &PL_sv_undef;
+    arg6 = (void *)(&saved_env);
+    if ((items < 4) || (items > 7)) {
+      SWIG_croak("Usage: Transformer_TransformGeolocations(self,xBand,yBand,zBand,callback,callback_data,options);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALTransformerInfoShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Transformer_TransformGeolocations" "', argument " "1"" of type '" "GDALTransformerInfoShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< GDALTransformerInfoShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Transformer_TransformGeolocations" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
+    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Transformer_TransformGeolocations" "', argument " "3"" of type '" "GDALRasterBandShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< GDALRasterBandShadow * >(argp3);
+    res4 = SWIG_ConvertPtr(ST(3), &argp4,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+    if (!SWIG_IsOK(res4)) {
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Transformer_TransformGeolocations" "', argument " "4"" of type '" "GDALRasterBandShadow *""'"); 
+    }
+    arg4 = reinterpret_cast< GDALRasterBandShadow * >(argp4);
+    if (items > 4) {
+      {
+        /* %typemap(in) (GDALProgressFunc callback = NULL) */
+        if (SvOK(ST(4))) {
+          if (SvROK(ST(4))) {
+            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
+              do_confess(NEED_CODE_REF, 1);
+            } else {
+              saved_env.fct = (SV *)ST(4);
+              arg5 = &callback_d_cp_vp;
+            }
+          } else {
+            do_confess(NEED_CODE_REF, 1);
+          }
+        }
+      }
+    }
+    if (items > 5) {
+      {
+        /* %typemap(in) (void* callback_data=NULL) */
+        if (SvOK(ST(5)))
+        saved_env.data = (SV *)ST(5);
+      }
+    }
+    if (items > 6) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(6))) {
+          if (SvROK(ST(6))) {
+            if (SvTYPE(SvRV(ST(6)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(6)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+                arg7 = CSLAddString(arg7, tmp);
+                if (sf) Safefree(tmp); else free(tmp);
+              }
+            } else if (SvTYPE(SvRV(ST(6)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(6));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg7 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv, &key, &klen)) {
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+                arg7 = CSLAddNameValue(arg7, key, tmp);
+                if (sf) Safefree(tmp); else free(tmp);
+              }
+            } else
+            do_confess(NEED_REF, 1);
+          } else
+          do_confess(NEED_REF, 1);
+        }
+      }
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      if (!arg3) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      if (!arg4) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (int)GDALTransformerInfoShadow_TransformGeolocations(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
+    
+    
+    
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg7) CSLDestroy( arg7 );
+    }
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg7) CSLDestroy( arg7 );
+    }
+    SWIG_croak_null();
+  }
+}
+
+
+XS(_wrap_ApplyVerticalShiftGrid) {
+  {
+    GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+    GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+    bool arg3 = (bool) false ;
+    double arg4 = (double) 1.0 ;
+    double arg5 = (double) 1.0 ;
+    char **arg6 = (char **) NULL ;
+    bool val3 ;
+    int ecode3 = 0 ;
+    double val4 ;
+    int ecode4 = 0 ;
+    double val5 ;
+    int ecode5 = 0 ;
+    int argvi = 0;
+    GDALDatasetShadow *result = 0 ;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 6)) {
+      SWIG_croak("Usage: ApplyVerticalShiftGrid(src_ds,grid_ds,inverse,srcUnitToMeter,dstUnitToMeter,options);");
     }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALTransformerInfoShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Transformer_TransformGeolocations" "', argument " "1"" of type '" "GDALTransformerInfoShadow *""'"); 
+    {
+      /* %typemap(in) (GDALDatasetShadow *) */
+      void *argp = 0;
+      int res = SWIG_ConvertPtr(ST(0), &argp, SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+      if (!SWIG_IsOK(res)) {
+        do_confess(WRONG_CLASS, 1);
+      }
+      arg1 = reinterpret_cast< GDALDatasetShadow * >(argp);
+      if (arg1 == NULL)
+      do_confess(NEED_DEF, 1);
     }
-    arg1 = reinterpret_cast< GDALTransformerInfoShadow * >(argp1);
-    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Transformer_TransformGeolocations" "', argument " "2"" of type '" "GDALRasterBandShadow *""'"); 
+    {
+      /* %typemap(in) (GDALDatasetShadow *) */
+      void *argp = 0;
+      int res = SWIG_ConvertPtr(ST(1), &argp, SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+      if (!SWIG_IsOK(res)) {
+        do_confess(WRONG_CLASS, 1);
+      }
+      arg2 = reinterpret_cast< GDALDatasetShadow * >(argp);
+      if (arg2 == NULL)
+      do_confess(NEED_DEF, 1);
     }
-    arg2 = reinterpret_cast< GDALRasterBandShadow * >(argp2);
-    res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Transformer_TransformGeolocations" "', argument " "3"" of type '" "GDALRasterBandShadow *""'"); 
+    if (items > 2) {
+      ecode3 = SWIG_AsVal_bool SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+      if (!SWIG_IsOK(ecode3)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ApplyVerticalShiftGrid" "', argument " "3"" of type '" "bool""'");
+      } 
+      arg3 = static_cast< bool >(val3);
     }
-    arg3 = reinterpret_cast< GDALRasterBandShadow * >(argp3);
-    res4 = SWIG_ConvertPtr(ST(3), &argp4,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Transformer_TransformGeolocations" "', argument " "4"" of type '" "GDALRasterBandShadow *""'"); 
+    if (items > 3) {
+      ecode4 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
+      if (!SWIG_IsOK(ecode4)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "ApplyVerticalShiftGrid" "', argument " "4"" of type '" "double""'");
+      } 
+      arg4 = static_cast< double >(val4);
     }
-    arg4 = reinterpret_cast< GDALRasterBandShadow * >(argp4);
     if (items > 4) {
-      {
-        /* %typemap(in) (GDALProgressFunc callback = NULL) */
-        if (SvOK(ST(4))) {
-          if (SvROK(ST(4))) {
-            if (SvTYPE(SvRV(ST(4))) != SVt_PVCV) {
-              do_confess(NEED_CODE_REF, 1);
-            } else {
-              saved_env.fct = (SV *)ST(4);
-              arg5 = &callback_d_cp_vp;
-            }
-          } else {
-            do_confess(NEED_CODE_REF, 1);
-          }
-        }
-      }
+      ecode5 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
+      if (!SWIG_IsOK(ecode5)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "ApplyVerticalShiftGrid" "', argument " "5"" of type '" "double""'");
+      } 
+      arg5 = static_cast< double >(val5);
     }
     if (items > 5) {
       {
-        /* %typemap(in) (void* callback_data=NULL) */
-        if (SvOK(ST(5)))
-        saved_env.data = (SV *)ST(5);
-      }
-    }
-    if (items > 6) {
-      {
         /* %typemap(in) char **options */
-        if (SvOK(ST(6))) {
-          if (SvROK(ST(6))) {
-            if (SvTYPE(SvRV(ST(6)))==SVt_PVAV) {
-              AV *av = (AV*)(SvRV(ST(6)));
+        if (SvOK(ST(5))) {
+          if (SvROK(ST(5))) {
+            if (SvTYPE(SvRV(ST(5)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(5)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
-                arg7 = CSLAddString(arg7, tmp);
-                free(tmp);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+                arg6 = CSLAddString(arg6, tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
-            } else if (SvTYPE(SvRV(ST(6)))==SVt_PVHV) {
-              HV *hv = (HV*)SvRV(ST(6));
+            } else if (SvTYPE(SvRV(ST(5)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(5));
               SV *sv;
               char *key;
               I32 klen;
-              arg7 = NULL;
+              arg6 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
-                arg7 = CSLAddNameValue(arg7, key, tmp);
-                free(tmp);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+                arg6 = CSLAddNameValue(arg6, key, tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -23249,23 +24365,18 @@ XS(_wrap_Transformer_TransformGeolocations) {
       }
     }
     {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      if (!arg3) {
+      if (!arg1) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
     {
-      if (!arg4) {
+      if (!arg2) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
     {
       CPLErrorReset();
-      result = (int)GDALTransformerInfoShadow_TransformGeolocations(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      result = (GDALDatasetShadow *)ApplyVerticalShiftGrid(arg1,arg2,arg3,arg4,arg5,arg6);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -23287,7 +24398,7 @@ XS(_wrap_Transformer_TransformGeolocations) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
     
     
@@ -23295,7 +24406,7 @@ XS(_wrap_Transformer_TransformGeolocations) {
     
     {
       /* %typemap(freearg) char **options */
-      if (arg7) CSLDestroy( arg7 );
+      if (arg6) CSLDestroy( arg6 );
     }
     XSRETURN(argvi);
   fail:
@@ -23306,7 +24417,7 @@ XS(_wrap_Transformer_TransformGeolocations) {
     
     {
       /* %typemap(freearg) char **options */
-      if (arg7) CSLDestroy( arg7 );
+      if (arg6) CSLDestroy( arg6 );
     }
     SWIG_croak_null();
   }
@@ -23343,6 +24454,8 @@ XS(_wrap_ApplyGeoTransform) {
       do_confess(NEED_ARRAY_REF, 1);
       arg1 = argin1;
       AV *av = (AV*)(SvRV(ST(0)));
+      if (av_len(av)+1 < 6)
+      do_confess(NOT_ENOUGH_ELEMENTS, 1);
       for (unsigned int i=0; i<6; i++) {
         SV *sv = *av_fetch(av, i, 0);
         if (!SvOK(sv))
@@ -23439,6 +24552,8 @@ XS(_wrap_InvGeoTransform) {
       do_confess(NEED_ARRAY_REF, 1);
       arg1 = argin1;
       AV *av = (AV*)(SvRV(ST(0)));
+      if (av_len(av)+1 < 6)
+      do_confess(NOT_ENOUGH_ELEMENTS, 1);
       for (unsigned int i=0; i<6; i++) {
         SV *sv = *av_fetch(av, i, 0);
         if (!SvOK(sv))
@@ -23687,7 +24802,7 @@ XS(_wrap_GetCacheMax) {
     }
     {
       char temp[256];
-      sprintf(temp, ""CPL_FRMT_GIB"", result);
+      sprintf(temp, "" CPL_FRMT_GIB "", result);
       ST(argvi) = sv_2mortal(newSVpv(temp, 0));
       argvi++;
     }
@@ -23733,7 +24848,7 @@ XS(_wrap_GetCacheUsed) {
     }
     {
       char temp[256];
-      sprintf(temp, ""CPL_FRMT_GIB"", result);
+      sprintf(temp, "" CPL_FRMT_GIB "", result);
       ST(argvi) = sv_2mortal(newSVpv(temp, 0));
       argvi++;
     }
@@ -24378,9 +25493,9 @@ XS(_wrap_SerializeXMLTree) {
       if ( !arg1 ) {
         switch (err) {
         case 1:
-          do_confess(ARRAY_TO_XML_FAILED" "NEED_DEF, 1);
+          do_confess(ARRAY_TO_XML_FAILED " " NEED_DEF, 1);
         case 2:
-          do_confess(ARRAY_TO_XML_FAILED" "NEED_ARRAY_REF, 1);
+          do_confess(ARRAY_TO_XML_FAILED " " NEED_ARRAY_REF, 1);
         }
       }
     }
@@ -24464,9 +25579,10 @@ XS(_wrap_GetJPEG2000StructureAsString) {
               AV *av = (AV*)(SvRV(ST(1)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddString(arg2, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(1));
@@ -24476,9 +25592,10 @@ XS(_wrap_GetJPEG2000StructureAsString) {
               arg2 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddNameValue(arg2, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -24877,14 +25994,14 @@ XS(_wrap__Open) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     XSRETURN(argvi);
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     SWIG_croak_null();
@@ -24935,9 +26052,10 @@ XS(_wrap__OpenEx) {
               AV *av = (AV*)(SvRV(ST(2)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddString(arg3, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(2));
@@ -24947,9 +26065,10 @@ XS(_wrap__OpenEx) {
               arg3 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddNameValue(arg3, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -24967,9 +26086,10 @@ XS(_wrap__OpenEx) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -24979,9 +26099,10 @@ XS(_wrap__OpenEx) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -24999,9 +26120,10 @@ XS(_wrap__OpenEx) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddString(arg5, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(4));
@@ -25011,9 +26133,10 @@ XS(_wrap__OpenEx) {
               arg5 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddNameValue(arg5, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -25054,7 +26177,7 @@ XS(_wrap__OpenEx) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     {
@@ -25073,7 +26196,7 @@ XS(_wrap__OpenEx) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     {
@@ -25156,14 +26279,14 @@ XS(_wrap__OpenShared) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     XSRETURN(argvi);
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     SWIG_croak_null();
@@ -25202,9 +26325,10 @@ XS(_wrap_IdentifyDriver) {
               AV *av = (AV*)(SvRV(ST(1)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddString(arg2, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(1));
@@ -25214,9 +26338,10 @@ XS(_wrap_IdentifyDriver) {
               arg2 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddNameValue(arg2, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -25257,7 +26382,7 @@ XS(_wrap_IdentifyDriver) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) char **options */
@@ -25267,7 +26392,7 @@ XS(_wrap_IdentifyDriver) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) char **options */
@@ -25278,6 +26403,170 @@ XS(_wrap_IdentifyDriver) {
 }
 
 
+XS(_wrap_IdentifyDriverEx) {
+  {
+    char *arg1 = (char *) 0 ;
+    unsigned int arg2 = (unsigned int) 0 ;
+    char **arg3 = (char **) NULL ;
+    char **arg4 = (char **) NULL ;
+    U8 *tmpbuf1 = NULL ;
+    unsigned int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    GDALDriverShadow *result = 0 ;
+    dXSARGS;
+    
+    {
+      /* %typemap(default) const char * utf8_path */
+      arg1 = (char *)"";
+    }
+    if ((items < 0) || (items > 4)) {
+      SWIG_croak("Usage: IdentifyDriverEx(utf8_path,nIdentifyFlags,allowed_drivers,sibling_files);");
+    }
+    if (items > 0) {
+      {
+        /* %typemap(in,numinputs=1) (const char* utf8_path) (U8 *tmpbuf1) */
+        arg1 = sv_to_utf8_string(ST(0), &tmpbuf1);
+      }
+    }
+    if (items > 1) {
+      ecode2 = SWIG_AsVal_unsigned_SS_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+      if (!SWIG_IsOK(ecode2)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "IdentifyDriverEx" "', argument " "2"" of type '" "unsigned int""'");
+      } 
+      arg2 = static_cast< unsigned int >(val2);
+    }
+    if (items > 2) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(2))) {
+          if (SvROK(ST(2))) {
+            if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(2)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+                arg3 = CSLAddString(arg3, tmp);
+                if (sf) Safefree(tmp); else free(tmp);
+              }
+            } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(2));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg3 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv, &key, &klen)) {
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+                arg3 = CSLAddNameValue(arg3, key, tmp);
+                if (sf) Safefree(tmp); else free(tmp);
+              }
+            } else
+            do_confess(NEED_REF, 1);
+          } else
+          do_confess(NEED_REF, 1);
+        }
+      }
+    }
+    if (items > 3) {
+      {
+        /* %typemap(in) char **options */
+        if (SvOK(ST(3))) {
+          if (SvROK(ST(3))) {
+            if (SvTYPE(SvRV(ST(3)))==SVt_PVAV) {
+              AV *av = (AV*)(SvRV(ST(3)));
+              for (int i = 0; i < av_len(av)+1; i++) {
+                SV *sv = *(av_fetch(av, i, 0));
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+                arg4 = CSLAddString(arg4, tmp);
+                if (sf) Safefree(tmp); else free(tmp);
+              }
+            } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
+              HV *hv = (HV*)SvRV(ST(3));
+              SV *sv;
+              char *key;
+              I32 klen;
+              arg4 = NULL;
+              hv_iterinit(hv);
+              while(sv = hv_iternextsv(hv, &key, &klen)) {
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+                arg4 = CSLAddNameValue(arg4, key, tmp);
+                if (sf) Safefree(tmp); else free(tmp);
+              }
+            } else
+            do_confess(NEED_REF, 1);
+          } else
+          do_confess(NEED_REF, 1);
+        }
+      }
+    }
+    {
+      if (!arg1) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (GDALDriverShadow *)IdentifyDriverEx((char const *)arg1,arg2,arg3,arg4);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 | SWIG_SHADOW); argvi++ ;
+    {
+      /* %typemap(freearg) (const char* utf8_path) */
+      if (tmpbuf1) Safefree(tmpbuf1);
+    }
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg3) CSLDestroy( arg3 );
+    }
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    XSRETURN(argvi);
+  fail:
+    {
+      /* %typemap(freearg) (const char* utf8_path) */
+      if (tmpbuf1) Safefree(tmpbuf1);
+    }
+    
+    {
+      /* %typemap(freearg) char **options */
+      if (arg3) CSLDestroy( arg3 );
+    }
+    {
+      /* %typemap(freearg) char **options */
+      if (arg4) CSLDestroy( arg4 );
+    }
+    SWIG_croak_null();
+  }
+}
+
+
 XS(_wrap_GeneralCmdLineProcessor) {
   {
     char **arg1 = (char **) 0 ;
@@ -25299,9 +26588,10 @@ XS(_wrap_GeneralCmdLineProcessor) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -25311,9 +26601,10 @@ XS(_wrap_GeneralCmdLineProcessor) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -25404,9 +26695,10 @@ XS(_wrap_new_GDALInfoOptions) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -25416,9 +26708,10 @@ XS(_wrap_new_GDALInfoOptions) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -25613,9 +26906,10 @@ XS(_wrap_new_GDALTranslateOptions) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -25625,9 +26919,10 @@ XS(_wrap_new_GDALTranslateOptions) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -25840,7 +27135,7 @@ XS(_wrap_wrapper_GDALTranslate) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -25849,7 +27144,7 @@ XS(_wrap_wrapper_GDALTranslate) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -25877,9 +27172,10 @@ XS(_wrap_new_GDALWarpAppOptions) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -25889,9 +27185,10 @@ XS(_wrap_new_GDALWarpAppOptions) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -26225,7 +27522,7 @@ XS(_wrap_wrapper_GDALWarpDestName) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -26233,7 +27530,7 @@ XS(_wrap_wrapper_GDALWarpDestName) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -26260,9 +27557,10 @@ XS(_wrap_new_GDALVectorTranslateOptions) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -26272,9 +27570,10 @@ XS(_wrap_new_GDALVectorTranslateOptions) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -26594,7 +27893,7 @@ XS(_wrap_wrapper_GDALVectorTranslateDestName) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -26603,7 +27902,7 @@ XS(_wrap_wrapper_GDALVectorTranslateDestName) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -26631,9 +27930,10 @@ XS(_wrap_new_GDALDEMProcessingOptions) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -26643,9 +27943,10 @@ XS(_wrap_new_GDALDEMProcessingOptions) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -26885,7 +28186,7 @@ XS(_wrap_wrapper_GDALDEMProcessing) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -26896,7 +28197,7 @@ XS(_wrap_wrapper_GDALDEMProcessing) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -26926,9 +28227,10 @@ XS(_wrap_new_GDALNearblackOptions) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -26938,9 +28240,10 @@ XS(_wrap_new_GDALNearblackOptions) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -27260,7 +28563,7 @@ XS(_wrap_wrapper_GDALNearblackDestName) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -27269,7 +28572,7 @@ XS(_wrap_wrapper_GDALNearblackDestName) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -27297,9 +28600,10 @@ XS(_wrap_new_GDALGridOptions) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -27309,9 +28613,10 @@ XS(_wrap_new_GDALGridOptions) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -27524,7 +28829,7 @@ XS(_wrap_wrapper_GDALGrid) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -27533,7 +28838,7 @@ XS(_wrap_wrapper_GDALGrid) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -27561,9 +28866,10 @@ XS(_wrap_new_GDALRasterizeOptions) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -27573,9 +28879,10 @@ XS(_wrap_new_GDALRasterizeOptions) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -27895,7 +29202,7 @@ XS(_wrap_wrapper_GDALRasterizeDestName) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -27904,7 +29211,7 @@ XS(_wrap_wrapper_GDALRasterizeDestName) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -27932,9 +29239,10 @@ XS(_wrap_new_GDALBuildVRTOptions) {
             AV *av = (AV*)(SvRV(ST(0)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddString(arg1, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(0)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(0));
@@ -27944,9 +29252,10 @@ XS(_wrap_new_GDALBuildVRTOptions) {
             arg1 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg1 = CSLAddNameValue(arg1, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -28162,7 +29471,7 @@ XS(_wrap_wrapper_GDALBuildVRT_objects) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -28170,7 +29479,7 @@ XS(_wrap_wrapper_GDALBuildVRT_objects) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     
@@ -28220,9 +29529,10 @@ XS(_wrap_wrapper_GDALBuildVRT_names) {
               AV *av = (AV*)(SvRV(ST(1)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddString(arg2, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(1));
@@ -28232,9 +29542,10 @@ XS(_wrap_wrapper_GDALBuildVRT_names) {
               arg2 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddNameValue(arg2, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -28306,7 +29617,7 @@ XS(_wrap_wrapper_GDALBuildVRT_names) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) char **options */
@@ -28318,7 +29629,7 @@ XS(_wrap_wrapper_GDALBuildVRT_names) {
   fail:
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) char **options */
@@ -28372,6 +29683,7 @@ static swig_type_info _swigt__p_GDALWarpAppOptions = {"_p_GDALWarpAppOptions", "
 static swig_type_info _swigt__p_GDAL_GCP = {"_p_GDAL_GCP", "GDAL_GCP *", 0, 0, (void*)"Geo::GDAL::GCP", 0};
 static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GUIntBig = {"_p_GUIntBig", "GUIntBig *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)"Geo::OGR::Feature", 0};
 static swig_type_info _swigt__p_OGRGeometryShadow = {"_p_OGRGeometryShadow", "OGRGeometryShadow *", 0, 0, (void*)"Geo::OGR::Geometry", 0};
 static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)"Geo::OGR::Layer", 0};
 static swig_type_info _swigt__p_OGRStyleTableShadow = {"_p_OGRStyleTableShadow", "OGRStyleTableShadow *", 0, 0, (void*)"Geo::OGR::StyleTable", 0};
@@ -28416,6 +29728,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_GDAL_GCP,
   &_swigt__p_GIntBig,
   &_swigt__p_GUIntBig,
+  &_swigt__p_OGRFeatureShadow,
   &_swigt__p_OGRGeometryShadow,
   &_swigt__p_OGRLayerShadow,
   &_swigt__p_OGRStyleTableShadow,
@@ -28460,6 +29773,7 @@ static swig_cast_info _swigc__p_GDALWarpAppOptions[] = {  {&_swigt__p_GDALWarpAp
 static swig_cast_info _swigc__p_GDAL_GCP[] = {  {&_swigt__p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GUIntBig[] = {  {&_swigt__p_GUIntBig, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRGeometryShadow[] = {  {&_swigt__p_OGRGeometryShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRStyleTableShadow[] = {  {&_swigt__p_OGRStyleTableShadow, 0, 0, 0},{0, 0, 0, 0}};
@@ -28504,6 +29818,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_GDAL_GCP,
   _swigc__p_GIntBig,
   _swigc__p_GUIntBig,
+  _swigc__p_OGRFeatureShadow,
   _swigc__p_OGRGeometryShadow,
   _swigc__p_OGRLayerShadow,
   _swigc__p_OGRStyleTableShadow,
@@ -28660,6 +29975,8 @@ static swig_command_info swig_commands[] = {
 {"Geo::GDALc::Dataset_GetLayerCount", _wrap_Dataset_GetLayerCount},
 {"Geo::GDALc::Dataset_GetLayerByIndex", _wrap_Dataset_GetLayerByIndex},
 {"Geo::GDALc::Dataset_GetLayerByName", _wrap_Dataset_GetLayerByName},
+{"Geo::GDALc::Dataset_ResetReading", _wrap_Dataset_ResetReading},
+{"Geo::GDALc::Dataset_GetNextFeature", _wrap_Dataset_GetNextFeature},
 {"Geo::GDALc::Dataset__TestCapability", _wrap_Dataset__TestCapability},
 {"Geo::GDALc::Dataset_ExecuteSQL", _wrap_Dataset_ExecuteSQL},
 {"Geo::GDALc::Dataset__ReleaseResultSet", _wrap_Dataset__ReleaseResultSet},
@@ -28719,6 +30036,8 @@ static swig_command_info swig_commands[] = {
 {"Geo::GDALc::Band_GetCategoryNames", _wrap_Band_GetCategoryNames},
 {"Geo::GDALc::Band_SetCategoryNames", _wrap_Band_SetCategoryNames},
 {"Geo::GDALc::Band_ContourGenerate", _wrap_Band_ContourGenerate},
+{"Geo::GDALc::Band_ClassCounts", _wrap_Band_ClassCounts},
+{"Geo::GDALc::Band_Reclassify", _wrap_Band_Reclassify},
 {"Geo::GDALc::new_ColorTable", _wrap_new_ColorTable},
 {"Geo::GDALc::delete_ColorTable", _wrap_delete_ColorTable},
 {"Geo::GDALc::ColorTable_Clone", _wrap_ColorTable_Clone},
@@ -28770,6 +30089,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::GDALc::Transformer_TransformPoint", _wrap_Transformer_TransformPoint},
 {"Geo::GDALc::Transformer__TransformPoints", _wrap_Transformer__TransformPoints},
 {"Geo::GDALc::Transformer_TransformGeolocations", _wrap_Transformer_TransformGeolocations},
+{"Geo::GDALc::ApplyVerticalShiftGrid", _wrap_ApplyVerticalShiftGrid},
 {"Geo::GDALc::ApplyGeoTransform", _wrap_ApplyGeoTransform},
 {"Geo::GDALc::InvGeoTransform", _wrap_InvGeoTransform},
 {"Geo::GDALc::VersionInfo", _wrap_VersionInfo},
@@ -28797,6 +30117,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::GDALc::_OpenEx", _wrap__OpenEx},
 {"Geo::GDALc::_OpenShared", _wrap__OpenShared},
 {"Geo::GDALc::IdentifyDriver", _wrap_IdentifyDriver},
+{"Geo::GDALc::IdentifyDriverEx", _wrap_IdentifyDriverEx},
 {"Geo::GDALc::GeneralCmdLineProcessor", _wrap_GeneralCmdLineProcessor},
 {"Geo::GDALc::new_GDALInfoOptions", _wrap_new_GDALInfoOptions},
 {"Geo::GDALc::delete_GDALInfoOptions", _wrap_delete_GDALInfoOptions},
diff --git a/swig/perl/gdalconst_wrap.c b/swig/perl/gdalconst_wrap.c
index f1f6551..79f60d1 100644
--- a/swig/perl/gdalconst_wrap.c
+++ b/swig/perl/gdalconst_wrap.c
@@ -2568,6 +2568,21 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
   /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x01)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "GDAL_DATA_COVERAGE_STATUS_DATA", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x02)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "GDAL_DATA_COVERAGE_STATUS_EMPTY", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(0x04)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GARIO_PENDING", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1((int)(GARIO_PENDING)));
     SvREADONLY_on(sv);
diff --git a/swig/perl/gnm_wrap.cpp b/swig/perl/gnm_wrap.cpp
index 1f303e1..6f1dd08 100644
--- a/swig/perl/gnm_wrap.cpp
+++ b/swig/perl/gnm_wrap.cpp
@@ -1513,12 +1513,11 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 #define SWIGTYPE_p_GNMNetworkShadow swig_types[4]
 #define SWIGTYPE_p_OGRFeatureShadow swig_types[5]
 #define SWIGTYPE_p_OGRLayerShadow swig_types[6]
-#define SWIGTYPE_p_OGRwkbGeometryType swig_types[7]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[8]
-#define SWIGTYPE_p_char swig_types[9]
-#define SWIGTYPE_p_int swig_types[10]
-static swig_type_info *swig_types[12];
-static swig_module_info swig_module = {swig_types, 11, 0, 0, 0, 0};
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[7]
+#define SWIGTYPE_p_char swig_types[8]
+#define SWIGTYPE_p_int swig_types[9]
+static swig_type_info *swig_types[11];
+static swig_module_info swig_module = {swig_types, 10, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -1580,118 +1579,61 @@ SWIGEXPORT void SWIG_init (CV *cv, CPerlObj *);
     #define NEED_DEF "A parameter which must be defined or not empty, is not."
     #define WRONG_CLASS "Object has a wrong class."
     #define NEED_REF "A parameter which must be a reference, is not."
+    #define NEED_HASH_REF "A parameter/item which must be a hash reference, is not."
     #define NEED_ARRAY_REF "A parameter/item which must be an array reference, is not."
     #define NEED_BINARY_DATA "A parameter which must be binary data, is not."
     #define NEED_CODE_REF "A parameter which must be an anonymous subroutine, is not."
     #define WRONG_ITEM_IN_ARRAY "An item in an array parameter has wrong type."
     #define ARRAY_TO_XML_FAILED "An array parameter cannot be converted to an XMLTree."
+    #define NOT_ENOUGH_ELEMENTS "The supplied array does not have enough elements."
 
 
+#include <iostream>
+using namespace std;
+
 #include "gdal.h"
+#include "ogr_api.h"
+#include "ogr_p.h"
+#include "ogr_core.h"
+#include "cpl_port.h"
+#include "cpl_string.h"
+#include "ogr_srs_api.h"
 #include "gnm_api.h"
 
 typedef void GDALMajorObjectShadow;
 typedef void GNMNetworkShadow;
 typedef void GNMGenericNetworkShadow;
 
-
 #ifdef DEBUG
+typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
+typedef struct OGRDriverHS OGRDriverShadow;
+typedef struct OGRDataSourceHS OGRDataSourceShadow;
+#endif
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRFeatureHS OGRFeatureShadow;
-typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+typedef struct OGRFeatureDefnHS OGRFeatureDefnShadow;
+typedef struct OGRGeometryHS OGRGeometryShadow;
+typedef struct OGRCoordinateTransformationHS OSRCoordinateTransformationShadow;
+typedef struct OGRCoordinateTransformationHS OGRCoordinateTransformationShadow;
+typedef struct OGRFieldDefnHS OGRFieldDefnShadow;
 #else
+typedef void OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
+typedef void OGRDriverShadow;
+typedef void OGRDataSourceShadow;
+#endif
 typedef void OGRLayerShadow;
 typedef void OGRFeatureShadow;
-typedef void OSRSpatialReferenceShadow;
+typedef void OGRFeatureDefnShadow;
+typedef void OGRGeometryShadow;
+typedef void OSRCoordinateTransformationShadow;
+typedef void OGRFieldDefnShadow;
 #endif
-
-SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
-    return GDALGetDescription( self );
-  }
-
-SWIGINTERN swig_type_info*
-SWIG_pchar_descriptor(void)
-{
-  static int init = 0;
-  static swig_type_info* info = 0;
-  if (!init) {
-    info = SWIG_TypeQuery("_p_char");
-    init = 1;
-  }
-  return info;
-}
-
-
-SWIGINTERN int
-SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc)
-{
-  if (SvMAGICAL(obj)) {
-     SV *tmp = sv_newmortal();
-     SvSetSV(tmp, obj);
-     obj = tmp;
-  }
-  if (SvPOK(obj)) {
-    STRLEN len = 0;
-    char *cstr = SvPV(obj, len); 
-    size_t size = len + 1;
-    if (cptr)  {
-      if (alloc) {
-	if (*alloc == SWIG_NEWOBJ) {
-	  *cptr = reinterpret_cast< char* >(memcpy((new char[size]), cstr, sizeof(char)*(size)));
-	} else {
-	  *cptr = cstr;
-	  *alloc = SWIG_OLDOBJ;
-	}
-      }
-    }
-    if (psize) *psize = size;
-    return SWIG_OK;
-  } else {
-    swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
-    if (pchar_descriptor) {
-      char* vptr = 0; 
-      if (SWIG_ConvertPtr(obj, (void**)&vptr, pchar_descriptor, 0) == SWIG_OK) {
-	if (cptr) *cptr = vptr;
-	if (psize) *psize = vptr ? (strlen(vptr) + 1) : 0;
-	if (alloc) *alloc = SWIG_OLDOBJ;
-	return SWIG_OK;
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
+typedef struct OGRStyleTableHS OGRStyleTableShadow;
+typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
 
 
-
-SWIGINTERN void GDALMajorObjectShadow_SetDescription(GDALMajorObjectShadow *self,char const *pszNewDesc){
-    GDALSetDescription( self, pszNewDesc );
-  }
-SWIGINTERN char **GDALMajorObjectShadow_GetMetadataDomainList(GDALMajorObjectShadow *self){
-    return GDALGetMetadataDomainList( self );
-  }
-SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_Dict(GDALMajorObjectShadow *self,char const *pszDomain=""){
-    return GDALGetMetadata( self, pszDomain );
-  }
-SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_List(GDALMajorObjectShadow *self,char const *pszDomain=""){
-    return GDALGetMetadata( self, pszDomain );
-  }
-SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_0(GDALMajorObjectShadow *self,char **papszMetadata,char const *pszDomain=""){
-    return GDALSetMetadata( self, papszMetadata, pszDomain );
-  }
-SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_1(GDALMajorObjectShadow *self,char *pszMetadataString,char const *pszDomain=""){
-    char *tmpList[2];
-    tmpList[0] = pszMetadataString;
-    tmpList[1] = 0;
-    return GDALSetMetadata( self, tmpList, pszDomain );
-  }
-SWIGINTERN char const *GDALMajorObjectShadow_GetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszDomain=""){
-    return GDALGetMetadataItem( self, pszName, pszDomain);
-  }
-SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszValue,char const *pszDomain=""){
-    return GDALSetMetadataItem( self, pszName, pszValue, pszDomain);
-  }
-
 SWIGINTERNINLINE SV *
 SWIG_From_long  SWIG_PERL_DECL_ARGS_1(long value)
 {
@@ -1720,9 +1662,6 @@ SWIG_From_int  SWIG_PERL_DECL_ARGS_1(int value)
       return (GNMGenericNetworkShadow*)dynamic_cast<GNMGenericNetwork*>((GDALMajorObject*)base);
   }
 
-
-typedef char retStringAndCPLFree;
-
 SWIGINTERN void delete_GNMNetworkShadow(GNMNetworkShadow *self){
             if ( GDALDereferenceDataset( self ) <= 0 ) {
               GDALClose(self);
@@ -1882,9 +1821,11 @@ SWIG_AsVal_int SWIG_PERL_DECL_ARGS_2(SV * obj, int *val)
 }
 
 
-    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf) {
-        /* if tmpbuf, only tmpbuf is freed; if not, ret is freed*/
+    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf, bool *safefree = NULL) {
+        /* if tmpbuf is given, only tmpbuf needs to be freed, use Safefree!
+           if not, ret needs to be freed, if safefree use Safefree else use free! */
         char *ret;
+        if (safefree) *safefree = false;
         if (SvOK(sv)) {
             STRLEN len;
             ret = SvPV(sv, len);
@@ -1895,6 +1836,7 @@ SWIG_AsVal_int SWIG_PERL_DECL_ARGS_2(SV * obj, int *val)
                 } else {
                     ret = (char *)bytes_to_utf8((const U8*)ret, &len);
                 }
+                if (safefree) *safefree = true;
             } else {
                 if (!tmpbuf)
                     ret = strdup(ret);
@@ -1922,6 +1864,62 @@ SWIGINTERN char const *GNMNetworkShadow_GetProjectionRef(GNMNetworkShadow *self)
 SWIGINTERN char **GNMNetworkShadow_GetFileList(GNMNetworkShadow *self){
             return GDALGetFileList( self );
         }
+
+SWIGINTERN swig_type_info*
+SWIG_pchar_descriptor(void)
+{
+  static int init = 0;
+  static swig_type_info* info = 0;
+  if (!init) {
+    info = SWIG_TypeQuery("_p_char");
+    init = 1;
+  }
+  return info;
+}
+
+
+SWIGINTERN int
+SWIG_AsCharPtrAndSize(SV *obj, char** cptr, size_t* psize, int *alloc)
+{
+  if (SvMAGICAL(obj)) {
+     SV *tmp = sv_newmortal();
+     SvSetSV(tmp, obj);
+     obj = tmp;
+  }
+  if (SvPOK(obj)) {
+    STRLEN len = 0;
+    char *cstr = SvPV(obj, len); 
+    size_t size = len + 1;
+    if (cptr)  {
+      if (alloc) {
+	if (*alloc == SWIG_NEWOBJ) {
+	  *cptr = reinterpret_cast< char* >(memcpy((new char[size]), cstr, sizeof(char)*(size)));
+	} else {
+	  *cptr = cstr;
+	  *alloc = SWIG_OLDOBJ;
+	}
+      }
+    }
+    if (psize) *psize = size;
+    return SWIG_OK;
+  } else {
+    swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+    if (pchar_descriptor) {
+      char* vptr = 0; 
+      if (SWIG_ConvertPtr(obj, (void**)&vptr, pchar_descriptor, 0) == SWIG_OK) {
+	if (cptr) *cptr = vptr;
+	if (psize) *psize = vptr ? (strlen(vptr) + 1) : 0;
+	if (alloc) *alloc = SWIG_OLDOBJ;
+	return SWIG_OK;
+      }
+    }
+  }
+  return SWIG_TypeError;
+}
+
+
+
+
 SWIGINTERN OGRLayerShadow *GNMNetworkShadow_CreateLayer(GNMNetworkShadow *self,char const *name,OSRSpatialReferenceShadow *srs=NULL,OGRwkbGeometryType geom_type=wkbUnknown,char **options=0){
             OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCreateLayer( self,
                                       name,
@@ -2067,632 +2065,28 @@ extern "C" {
 #ifdef PERL_OBJECT
 #define MAGIC_CLASS _wrap_Geo__GNM_var::
 class _wrap_Geo__GNM_var : public CPerlObj {
-public:
-#else
-#define MAGIC_CLASS
-#endif
-SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) {
-    MAGIC_PPERL
-    croak("Value is read-only.");
-    return 0;
-}
-
-
-#ifdef PERL_OBJECT
-};
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-XS(_wrap_MajorObject_GetDescription) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: MajorObject_GetDescription(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetDescription" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetDescription) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: MajorObject_SetDescription(self,pszNewDesc);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetDescription" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetDescription" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
-    {
-      /* %typemap(out) void */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_GetMetadataDomainList) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: MajorObject_GetMetadataDomainList(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataDomainList" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
-    {
-      /* %typemap(out) char **CSL */
-      if (GIMME_V == G_ARRAY) {
-        if (result) {
-          int n = CSLCount(result);
-          EXTEND(SP, argvi+n-items+1);
-          int i;
-          for (i = 0; result[i]; i++) {
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            ST(argvi++) = sv_2mortal(sv);
-          }
-          CSLDestroy(result);
-        }
-      } else {
-        AV *av = (AV*)sv_2mortal((SV*)newAV());
-        if (result) {
-          int i;
-          for (i = 0; result[i]; i++) {
-            SV *sv = newSVpv(result[i], 0);
-            SvUTF8_on(sv); /* expecting GDAL to give us UTF-8 */
-            av_push(av, sv);
-          }
-          CSLDestroy(result);
-        }
-        ST(argvi) = newRV((SV*)av);
-        sv_2mortal(ST(argvi));
-        argvi++;
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_GetMetadata_Dict) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: MajorObject_GetMetadata_Dict(self,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadata_Dict" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadata_Dict" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
-    {
-      /* %typemap(out) char **dict */
-      char **stringarray = result;
-      HV *hv = (HV*)sv_2mortal((SV*)newHV());
-      if ( stringarray != NULL ) {
-        while (*stringarray != NULL ) {
-          char const *valptr;
-          char *keyptr;
-          valptr = CPLParseNameValue( *stringarray, &keyptr );
-          if ( valptr != 0 ) {
-            hv_store(hv, keyptr, strlen(keyptr), newSVpv(valptr, strlen(valptr)), 0);
-            CPLFree( keyptr );
-          }
-          stringarray++;
-        }
-      }
-      ST(argvi) = newRV((SV*)hv);
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_GetMetadata_List) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int argvi = 0;
-    char **result = 0 ;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 2)) {
-      SWIG_croak("Usage: MajorObject_GetMetadata_List(self,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadata_List" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    if (items > 1) {
-      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-      if (!SWIG_IsOK(res2)) {
-        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadata_List" "', argument " "2"" of type '" "char const *""'");
-      }
-      arg2 = reinterpret_cast< char * >(buf2);
-    }
-    result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
-    {
-      /* %typemap(out) char **options -> ( string ) */
-      AV* av = (AV*)sv_2mortal((SV*)newAV());
-      char **stringarray = result;
-      if ( stringarray != NULL ) {
-        int n = CSLCount( stringarray );
-        for ( int i = 0; i < n; i++ ) {
-          SV *sv = newSVpv(stringarray[i], 0);
-          SvUTF8_on(sv); /* expecting UTF-8 from GDAL */
-          if (!av_store(av, i, sv))
-          SvREFCNT_dec(sv);
-        }
-      }
-      ST(argvi) = newRV((SV*)av);
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetMetadata__SWIG_0) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char **arg2 = (char **) 0 ;
-    char *arg3 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: MajorObject_SetMetadata(self,papszMetadata,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadata" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    {
-      /* %typemap(in) char **dict */
-      HV *hv = (HV*)SvRV(ST(1));
-      SV *sv;
-      char *key;
-      I32 klen;
-      arg2 = NULL;
-      hv_iterinit(hv);
-      while(sv = hv_iternextsv(hv,&key,&klen)) {
-        arg2 = CSLAddNameValue( arg2, key, SvPV_nolen(sv) );
-      }
-    }
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadata" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3);
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    {
-      /* %typemap(freearg) char **dict */
-      CSLDestroy( arg2 );
-    }
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) char **dict */
-      CSLDestroy( arg2 );
-    }
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetMetadata__SWIG_1) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: MajorObject_SetMetadata(self,pszMetadataString,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadata" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetMetadata" "', argument " "2"" of type '" "char *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadata" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3);
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetMetadata) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if ((items >= 2) && (items <= 3)) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_GDALMajorObjectShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typecheck(SWIG_TYPECHECK_POINTER) (char **dict) */
-          _v = (SvROK(ST(1)) && (SvTYPE(SvRV(ST(1)))==SVt_PVHV)) ? 1 : 0;
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 2) {
-        {
-          int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
-          _v = SWIG_CheckState(res);
-        }
-        if (!_v) goto check_1;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if ((items >= 2) && (items <= 3)) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_GDALMajorObjectShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 2) {
-        {
-          int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
-          _v = SWIG_CheckState(res);
-        }
-        if (!_v) goto check_2;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_MajorObject_SetMetadata__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_MajorObject_SetMetadata__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'MajorObject_SetMetadata'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_MajorObject_GetMetadataItem) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int argvi = 0;
-    char *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 3)) {
-      SWIG_croak("Usage: MajorObject_GetMetadataItem(self,pszName,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataItem" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadataItem" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    if (items > 2) {
-      res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-      if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_GetMetadataItem" "', argument " "3"" of type '" "char const *""'");
-      }
-      arg3 = reinterpret_cast< char * >(buf3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_MajorObject_SetMetadataItem) {
-  {
-    GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    char *arg4 = (char *) "" ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int res2 ;
-    char *buf2 = 0 ;
-    int alloc2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
-    int res4 ;
-    char *buf4 = 0 ;
-    int alloc4 = 0 ;
-    int argvi = 0;
-    CPLErr result;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 4)) {
-      SWIG_croak("Usage: MajorObject_SetMetadataItem(self,pszName,pszValue,pszDomain);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadataItem" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetMetadataItem" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadataItem" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-    if (items > 3) {
-      res4 = SWIG_AsCharPtrAndSize(ST(3), &buf4, NULL, &alloc4);
-      if (!SWIG_IsOK(res4)) {
-        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "MajorObject_SetMetadataItem" "', argument " "4"" of type '" "char const *""'");
-      }
-      arg4 = reinterpret_cast< char * >(buf4);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
-    {
-      /* %typemap(out) CPLErr */
-    }
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    XSRETURN(argvi);
-  fail:
-    
-    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-    if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
-    SWIG_croak_null();
-  }
+public:
+#else
+#define MAGIC_CLASS
+#endif
+SWIGCLASS_STATIC int swig_magic_readonly(pTHX_ SV *SWIGUNUSEDPARM(sv), MAGIC *SWIGUNUSEDPARM(mg)) {
+    MAGIC_PPERL
+    croak("Value is read-only.");
+    return 0;
 }
 
 
+#ifdef PERL_OBJECT
+};
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 XS(_wrap_CastToNetwork) {
   {
     GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
@@ -2710,7 +2104,30 @@ XS(_wrap_CastToNetwork) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CastToNetwork" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
     }
     arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    result = (GNMNetworkShadow *)CastToNetwork(arg1);
+    {
+      CPLErrorReset();
+      result = (GNMNetworkShadow *)CastToNetwork(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GNMNetworkShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
@@ -2738,7 +2155,30 @@ XS(_wrap_CastToGenericNetwork) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "CastToGenericNetwork" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
     }
     arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-    result = (GNMGenericNetworkShadow *)CastToGenericNetwork(arg1);
+    {
+      CPLErrorReset();
+      result = (GNMGenericNetworkShadow *)CastToGenericNetwork(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GNMGenericNetworkShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
@@ -2765,7 +2205,30 @@ XS(_wrap_delete_Network) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Network" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    delete_GNMNetworkShadow(arg1);
+    {
+      CPLErrorReset();
+      delete_GNMNetworkShadow(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) void */
     }
@@ -2778,7 +2241,7 @@ XS(_wrap_delete_Network) {
 }
 
 
-XS(_wrap_Network_ReleaseResultSet) {
+XS(_wrap_Network__ReleaseResultSet) {
   {
     GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
     OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
@@ -2789,18 +2252,41 @@ XS(_wrap_Network_ReleaseResultSet) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Network_ReleaseResultSet(self,layer);");
+      SWIG_croak("Usage: Network__ReleaseResultSet(self,layer);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_ReleaseResultSet" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network__ReleaseResultSet" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
     res2 = SWIG_ConvertPtr(ST(1), SWIG_as_voidptrptr(&arg2), SWIGTYPE_p_OGRLayerShadow, SWIG_POINTER_DISOWN |  0 );
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Network_ReleaseResultSet" "', argument " "2"" of type '" "OGRLayerShadow *""'");
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Network__ReleaseResultSet" "', argument " "2"" of type '" "OGRLayerShadow *""'");
+    }
+    {
+      CPLErrorReset();
+      GNMNetworkShadow_ReleaseResultSet(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
     }
-    GNMNetworkShadow_ReleaseResultSet(arg1,arg2);
     {
       /* %typemap(out) void */
     }
@@ -2832,7 +2318,30 @@ XS(_wrap_Network_GetVersion) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetVersion" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    result = (int)GNMNetworkShadow_GetVersion(arg1);
+    {
+      CPLErrorReset();
+      result = (int)GNMNetworkShadow_GetVersion(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
@@ -2860,7 +2369,30 @@ XS(_wrap_Network_GetName) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetName" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    result = (char *)GNMNetworkShadow_GetName(arg1);
+    {
+      CPLErrorReset();
+      result = (char *)GNMNetworkShadow_GetName(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) const char * */
       ST(argvi) = newSVpv(result, 0);
@@ -2898,8 +2430,31 @@ XS(_wrap_Network_GetFeatureByGlobalFID) {
     {
       arg2 = CPLAtoGIntBig(SvPV_nolen(ST(1)));
     }
-    result = (OGRFeatureShadow *)GNMNetworkShadow_GetFeatureByGlobalFID(arg1,arg2);
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | 0); argvi++ ;
+    {
+      CPLErrorReset();
+      result = (OGRFeatureShadow *)GNMNetworkShadow_GetFeatureByGlobalFID(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
     XSRETURN(argvi);
   fail:
@@ -2952,9 +2507,10 @@ XS(_wrap_Network_GetPath) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddString(arg5, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(4));
@@ -2964,9 +2520,10 @@ XS(_wrap_Network_GetPath) {
               arg5 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddNameValue(arg5, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -2975,8 +2532,31 @@ XS(_wrap_Network_GetPath) {
         }
       }
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_GetPath(arg1,arg2,arg3,arg4,arg5);
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, SWIG_OWNER | 0); argvi++ ;
+    {
+      CPLErrorReset();
+      result = (OGRLayerShadow *)GNMNetworkShadow_GetPath(arg1,arg2,arg3,arg4,arg5);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     
     
     {
@@ -3013,7 +2593,30 @@ XS(_wrap_Network_DisconnectAll) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_DisconnectAll" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    result = (CPLErr)GNMNetworkShadow_DisconnectAll(arg1);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMNetworkShadow_DisconnectAll(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -3043,7 +2646,30 @@ XS(_wrap_Network_GetProjection) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetProjection" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    result = (char *)GNMNetworkShadow_GetProjection(arg1);
+    {
+      CPLErrorReset();
+      result = (char *)GNMNetworkShadow_GetProjection(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) const char * */
       ST(argvi) = newSVpv(result, 0);
@@ -3077,7 +2703,30 @@ XS(_wrap_Network_GetProjectionRef) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetProjectionRef" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    result = (char *)GNMNetworkShadow_GetProjectionRef(arg1);
+    {
+      CPLErrorReset();
+      result = (char *)GNMNetworkShadow_GetProjectionRef(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) const char * */
       ST(argvi) = newSVpv(result, 0);
@@ -3111,7 +2760,30 @@ XS(_wrap_Network_GetFileList) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetFileList" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    result = (char **)GNMNetworkShadow_GetFileList(arg1);
+    {
+      CPLErrorReset();
+      result = (char **)GNMNetworkShadow_GetFileList(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) char **CSL */
       if (GIMME_V == G_ARRAY) {
@@ -3151,7 +2823,7 @@ XS(_wrap_Network_GetFileList) {
 }
 
 
-XS(_wrap_Network_CreateLayer) {
+XS(_wrap_Network__CreateLayer) {
   {
     GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
     char *arg2 = (char *) 0 ;
@@ -3163,18 +2835,18 @@ XS(_wrap_Network_CreateLayer) {
     U8 *tmpbuf2 = NULL ;
     void *argp3 = 0 ;
     int res3 = 0 ;
-    void *argp4 ;
-    int res4 = 0 ;
+    int val4 ;
+    int ecode4 = 0 ;
     int argvi = 0;
     OGRLayerShadow *result = 0 ;
     dXSARGS;
     
     if ((items < 2) || (items > 5)) {
-      SWIG_croak("Usage: Network_CreateLayer(self,name,srs,geom_type,options);");
+      SWIG_croak("Usage: Network__CreateLayer(self,name,srs,geom_type,options);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_CreateLayer" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network__CreateLayer" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
     {
@@ -3184,22 +2856,16 @@ XS(_wrap_Network_CreateLayer) {
     if (items > 2) {
       res3 = SWIG_ConvertPtr(ST(2), &argp3,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
       if (!SWIG_IsOK(res3)) {
-        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Network_CreateLayer" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
+        SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Network__CreateLayer" "', argument " "3"" of type '" "OSRSpatialReferenceShadow *""'"); 
       }
       arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
     }
     if (items > 3) {
-      {
-        res4 = SWIG_ConvertPtr(ST(3), &argp4, SWIGTYPE_p_OGRwkbGeometryType,  0 );
-        if (!SWIG_IsOK(res4)) {
-          SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Network_CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'"); 
-        }  
-        if (!argp4) {
-          SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "Network_CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
-        } else {
-          arg4 = *(reinterpret_cast< OGRwkbGeometryType * >(argp4));
-        }
-      }
+      ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
+      if (!SWIG_IsOK(ecode4)) {
+        SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Network__CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
+      } 
+      arg4 = static_cast< OGRwkbGeometryType >(val4);
     }
     if (items > 4) {
       {
@@ -3210,9 +2876,10 @@ XS(_wrap_Network_CreateLayer) {
               AV *av = (AV*)(SvRV(ST(4)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddString(arg5, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(4)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(4));
@@ -3222,9 +2889,10 @@ XS(_wrap_Network_CreateLayer) {
               arg5 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg5 = CSLAddNameValue(arg5, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -3234,18 +2902,42 @@ XS(_wrap_Network_CreateLayer) {
       }
     }
     {
-      /* %typemap(check) (const char *name) */
-      if (!arg2)
-      do_confess(NEED_DEF, 1);
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (OGRLayerShadow *)GNMNetworkShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | 0); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
+    
     {
       /* %typemap(freearg) char **options */
       if (arg5) CSLDestroy( arg5 );
@@ -3255,9 +2947,10 @@ XS(_wrap_Network_CreateLayer) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
+    
     {
       /* %typemap(freearg) char **options */
       if (arg5) CSLDestroy( arg5 );
@@ -3311,9 +3004,10 @@ XS(_wrap_Network_CopyLayer) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -3323,9 +3017,10 @@ XS(_wrap_Network_CopyLayer) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -3339,8 +3034,31 @@ XS(_wrap_Network_CopyLayer) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | 0); argvi++ ;
+    {
+      CPLErrorReset();
+      result = (OGRLayerShadow *)GNMNetworkShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
@@ -3362,7 +3080,7 @@ XS(_wrap_Network_CopyLayer) {
 }
 
 
-XS(_wrap_Network_DeleteLayer) {
+XS(_wrap_Network__DeleteLayer) {
   {
     GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
     int arg2 ;
@@ -3375,19 +3093,42 @@ XS(_wrap_Network_DeleteLayer) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Network_DeleteLayer(self,index);");
+      SWIG_croak("Usage: Network__DeleteLayer(self,index);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_DeleteLayer" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network__DeleteLayer" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Network_DeleteLayer" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Network__DeleteLayer" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
-    result = GNMNetworkShadow_DeleteLayer(arg1,arg2);
+    {
+      CPLErrorReset();
+      result = (OGRErr)GNMNetworkShadow_DeleteLayer(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) OGRErr */
       if ( result != 0 ) {
@@ -3423,8 +3164,31 @@ XS(_wrap_Network_GetLayerCount) {
     if (!SWIG_IsOK(res1)) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_GetLayerCount" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
-    arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    result = (int)GNMNetworkShadow_GetLayerCount(arg1);
+    arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
+    {
+      CPLErrorReset();
+      result = (int)GNMNetworkShadow_GetLayerCount(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
     XSRETURN(argvi);
@@ -3462,8 +3226,31 @@ XS(_wrap_Network_GetLayerByIndex) {
       } 
       arg2 = static_cast< int >(val2);
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByIndex(arg1,arg2);
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | 0); argvi++ ;
+    {
+      CPLErrorReset();
+      result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByIndex(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     
     XSRETURN(argvi);
@@ -3498,26 +3285,49 @@ XS(_wrap_Network_GetLayerByName) {
       /* %typemap(in,numinputs=1) (const char* layer_name) */
       arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByName(arg1,(char const *)arg2);
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | 0); argvi++ ;
+    {
+      CPLErrorReset();
+      result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByName(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     {
       /* %typemap(freearg) (const char* layer_name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* layer_name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Network_TestCapability) {
+XS(_wrap_Network__TestCapability) {
   {
     GNMNetworkShadow *arg1 = (GNMNetworkShadow *) 0 ;
     char *arg2 = (char *) 0 ;
@@ -3531,16 +3341,16 @@ XS(_wrap_Network_TestCapability) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Network_TestCapability(self,cap);");
+      SWIG_croak("Usage: Network__TestCapability(self,cap);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_GNMNetworkShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_TestCapability" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network__TestCapability" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
     res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
     if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Network_TestCapability" "', argument " "2"" of type '" "char const *""'");
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Network__TestCapability" "', argument " "2"" of type '" "char const *""'");
     }
     arg2 = reinterpret_cast< char * >(buf2);
     {
@@ -3548,7 +3358,30 @@ XS(_wrap_Network_TestCapability) {
       if (!arg2)
       do_confess(NEED_DEF, 1);
     }
-    result = (bool)GNMNetworkShadow_TestCapability(arg1,(char const *)arg2);
+    {
+      CPLErrorReset();
+      result = (bool)GNMNetworkShadow_TestCapability(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
     
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -3588,7 +3421,30 @@ XS(_wrap_Network_StartTransaction) {
       } 
       arg2 = static_cast< int >(val2);
     }
-    result = GNMNetworkShadow_StartTransaction(arg1,arg2);
+    {
+      CPLErrorReset();
+      result = (OGRErr)GNMNetworkShadow_StartTransaction(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) OGRErr */
       if ( result != 0 ) {
@@ -3625,7 +3481,30 @@ XS(_wrap_Network_CommitTransaction) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_CommitTransaction" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    result = GNMNetworkShadow_CommitTransaction(arg1);
+    {
+      CPLErrorReset();
+      result = (OGRErr)GNMNetworkShadow_CommitTransaction(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) OGRErr */
       if ( result != 0 ) {
@@ -3660,7 +3539,30 @@ XS(_wrap_Network_RollbackTransaction) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Network_RollbackTransaction" "', argument " "1"" of type '" "GNMNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMNetworkShadow * >(argp1);
-    result = GNMNetworkShadow_RollbackTransaction(arg1);
+    {
+      CPLErrorReset();
+      result = (OGRErr)GNMNetworkShadow_RollbackTransaction(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) OGRErr */
       if ( result != 0 ) {
@@ -3694,7 +3596,30 @@ XS(_wrap_delete_GenericNetwork) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_GenericNetwork" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
-    delete_GNMGenericNetworkShadow(arg1);
+    {
+      CPLErrorReset();
+      delete_GNMGenericNetworkShadow(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) void */
     }
@@ -3760,7 +3685,30 @@ XS(_wrap_GenericNetwork_ConnectFeatures) {
       SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "GenericNetwork_ConnectFeatures" "', argument " "7"" of type '" "GNMDirection""'");
     } 
     arg7 = static_cast< GNMDirection >(val7);
-    result = (CPLErr)GNMGenericNetworkShadow_ConnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_ConnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -3808,7 +3756,30 @@ XS(_wrap_GenericNetwork_DisconnectFeatures) {
     {
       arg4 = CPLAtoGIntBig(SvPV_nolen(ST(3)));
     }
-    result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeatures(arg1,arg2,arg3,arg4);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeatures(arg1,arg2,arg3,arg4);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -3842,7 +3813,30 @@ XS(_wrap_GenericNetwork_DisconnectFeaturesWithId) {
     {
       arg2 = CPLAtoGIntBig(SvPV_nolen(ST(1)));
     }
-    result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeaturesWithId(arg1,arg2);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeaturesWithId(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -3908,7 +3902,30 @@ XS(_wrap_GenericNetwork_ReconnectFeatures) {
       SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "GenericNetwork_ReconnectFeatures" "', argument " "7"" of type '" "GNMDirection""'");
     } 
     arg7 = static_cast< GNMDirection >(val7);
-    result = (CPLErr)GNMGenericNetworkShadow_ReconnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_ReconnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -3958,7 +3975,30 @@ XS(_wrap_GenericNetwork_CreateRule) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
-    result = (CPLErr)GNMGenericNetworkShadow_CreateRule(arg1,(char const *)arg2);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_CreateRule(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -3990,7 +4030,30 @@ XS(_wrap_GenericNetwork_DeleteAllRules) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_DeleteAllRules" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
-    result = (CPLErr)GNMGenericNetworkShadow_DeleteAllRules(arg1);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_DeleteAllRules(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -4034,7 +4097,30 @@ XS(_wrap_GenericNetwork_DeleteRule) {
         SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
     }
-    result = (CPLErr)GNMGenericNetworkShadow_DeleteRule(arg1,(char const *)arg2);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_DeleteRule(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -4066,7 +4152,30 @@ XS(_wrap_GenericNetwork_GetRules) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GenericNetwork_GetRules" "', argument " "1"" of type '" "GNMGenericNetworkShadow *""'"); 
     }
     arg1 = reinterpret_cast< GNMGenericNetworkShadow * >(argp1);
-    result = (char **)GNMGenericNetworkShadow_GetRules(arg1);
+    {
+      CPLErrorReset();
+      result = (char **)GNMGenericNetworkShadow_GetRules(arg1);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) char **CSL */
       if (GIMME_V == G_ARRAY) {
@@ -4144,9 +4253,10 @@ XS(_wrap_GenericNetwork_ConnectPointsByLines) {
             AV *av = (AV*)(SvRV(ST(1)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddString(arg2, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(1));
@@ -4156,9 +4266,10 @@ XS(_wrap_GenericNetwork_ConnectPointsByLines) {
             arg2 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddNameValue(arg2, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -4186,7 +4297,30 @@ XS(_wrap_GenericNetwork_ConnectPointsByLines) {
       SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "GenericNetwork_ConnectPointsByLines" "', argument " "6"" of type '" "GNMDirection""'");
     } 
     arg6 = static_cast< GNMDirection >(val6);
-    result = (CPLErr)GNMGenericNetworkShadow_ConnectPointsByLines(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_ConnectPointsByLines(arg1,arg2,arg3,arg4,arg5,arg6);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -4244,7 +4378,30 @@ XS(_wrap_GenericNetwork_ChangeBlockState) {
       SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "GenericNetwork_ChangeBlockState" "', argument " "3"" of type '" "bool""'");
     } 
     arg3 = static_cast< bool >(val3);
-    result = (CPLErr)GNMGenericNetworkShadow_ChangeBlockState(arg1,arg2,arg3);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_ChangeBlockState(arg1,arg2,arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -4286,7 +4443,30 @@ XS(_wrap_GenericNetwork_ChangeAllBlockState) {
       } 
       arg2 = static_cast< bool >(val2);
     }
-    result = (CPLErr)GNMGenericNetworkShadow_ChangeAllBlockState(arg1,arg2);
+    {
+      CPLErrorReset();
+      result = (CPLErr)GNMGenericNetworkShadow_ChangeAllBlockState(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
     {
       /* %typemap(out) CPLErr */
     }
@@ -4304,6 +4484,9 @@ XS(_wrap_GenericNetwork_ChangeAllBlockState) {
 
 /* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
 
+static void *_p_OGRLayerShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GDALMajorObjectShadow *)  ((OGRLayerShadow *) x));
+}
 static void *_p_GNMNetworkShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((GDALMajorObjectShadow *)  ((GNMNetworkShadow *) x));
 }
@@ -4313,17 +4496,16 @@ static void *_p_GNMGenericNetworkShadowTo_p_GDALMajorObjectShadow(void *x, int *
 static void *_p_GNMGenericNetworkShadowTo_p_GNMNetworkShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((GNMNetworkShadow *)  ((GNMGenericNetworkShadow *) x));
 }
-static swig_type_info _swigt__p_GDALMajorObjectShadow = {"_p_GDALMajorObjectShadow", "GDALMajorObjectShadow *", 0, 0, (void*)"Geo::GNM::MajorObject", 0};
+static swig_type_info _swigt__p_GDALMajorObjectShadow = {"_p_GDALMajorObjectShadow", "GDALMajorObjectShadow *", 0, 0, (void*)"Geo::GDAL::MajorObject", 0};
 static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GNMGenericNetworkShadow = {"_p_GNMGenericNetworkShadow", "GNMGenericNetworkShadow *", 0, 0, (void*)"Geo::GNM::GenericNetwork", 0};
 static swig_type_info _swigt__p_GNMGraphAlgorithmType = {"_p_GNMGraphAlgorithmType", "enum GNMGraphAlgorithmType *|GNMGraphAlgorithmType *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GNMNetworkShadow = {"_p_GNMNetworkShadow", "GNMNetworkShadow *", 0, 0, (void*)"Geo::GNM::Network", 0};
-static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_OGRwkbGeometryType = {"_p_OGRwkbGeometryType", "OGRwkbGeometryType *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_OSRSpatialReferenceShadow = {"_p_OSRSpatialReferenceShadow", "OSRSpatialReferenceShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)"Geo::OGR::Feature", 0};
+static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)"Geo::OGR::Layer", 0};
+static swig_type_info _swigt__p_OSRSpatialReferenceShadow = {"_p_OSRSpatialReferenceShadow", "OSRSpatialReferenceShadow *", 0, 0, (void*)"Geo::OSR::SpatialReference", 0};
 static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "CPLErr *|int *|GNMDirection *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "OGRFieldSubType *|OGRFieldType *|CPLErr *|int *|OGRwkbGeometryType *|OGRJustification *|OGRAxisOrientation *|GNMDirection *|OGRwkbByteOrder *|OGRErr *", 0, 0, (void*)0, 0};
 
 static swig_type_info *swig_type_initial[] = {
   &_swigt__p_GDALMajorObjectShadow,
@@ -4333,20 +4515,18 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_GNMNetworkShadow,
   &_swigt__p_OGRFeatureShadow,
   &_swigt__p_OGRLayerShadow,
-  &_swigt__p_OGRwkbGeometryType,
   &_swigt__p_OSRSpatialReferenceShadow,
   &_swigt__p_char,
   &_swigt__p_int,
 };
 
-static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_GNMNetworkShadow, _p_GNMNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGenericNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_OGRLayerShadow, _p_OGRLayerShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GNMNetworkShadow, _p_GNMNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGenericNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GNMGenericNetworkShadow[] = {  {&_swigt__p_GNMGenericNetworkShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GNMGraphAlgorithmType[] = {  {&_swigt__p_GNMGraphAlgorithmType, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GNMNetworkShadow[] = {  {&_swigt__p_GNMNetworkShadow, 0, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGenericNetworkShadowTo_p_GNMNetworkShadow, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRwkbGeometryType[] = {  {&_swigt__p_OGRwkbGeometryType, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OSRSpatialReferenceShadow[] = {  {&_swigt__p_OSRSpatialReferenceShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
@@ -4359,7 +4539,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_GNMNetworkShadow,
   _swigc__p_OGRFeatureShadow,
   _swigc__p_OGRLayerShadow,
-  _swigc__p_OGRwkbGeometryType,
   _swigc__p_OSRSpatialReferenceShadow,
   _swigc__p_char,
   _swigc__p_int,
@@ -4378,18 +4557,10 @@ static swig_variable_info swig_variables[] = {
 {0,0,0,0}
 };
 static swig_command_info swig_commands[] = {
-{"Geo::GNMc::MajorObject_GetDescription", _wrap_MajorObject_GetDescription},
-{"Geo::GNMc::MajorObject_SetDescription", _wrap_MajorObject_SetDescription},
-{"Geo::GNMc::MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList},
-{"Geo::GNMc::MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict},
-{"Geo::GNMc::MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List},
-{"Geo::GNMc::MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata},
-{"Geo::GNMc::MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem},
-{"Geo::GNMc::MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem},
 {"Geo::GNMc::CastToNetwork", _wrap_CastToNetwork},
 {"Geo::GNMc::CastToGenericNetwork", _wrap_CastToGenericNetwork},
 {"Geo::GNMc::delete_Network", _wrap_delete_Network},
-{"Geo::GNMc::Network_ReleaseResultSet", _wrap_Network_ReleaseResultSet},
+{"Geo::GNMc::Network__ReleaseResultSet", _wrap_Network__ReleaseResultSet},
 {"Geo::GNMc::Network_GetVersion", _wrap_Network_GetVersion},
 {"Geo::GNMc::Network_GetName", _wrap_Network_GetName},
 {"Geo::GNMc::Network_GetFeatureByGlobalFID", _wrap_Network_GetFeatureByGlobalFID},
@@ -4398,13 +4569,13 @@ static swig_command_info swig_commands[] = {
 {"Geo::GNMc::Network_GetProjection", _wrap_Network_GetProjection},
 {"Geo::GNMc::Network_GetProjectionRef", _wrap_Network_GetProjectionRef},
 {"Geo::GNMc::Network_GetFileList", _wrap_Network_GetFileList},
-{"Geo::GNMc::Network_CreateLayer", _wrap_Network_CreateLayer},
+{"Geo::GNMc::Network__CreateLayer", _wrap_Network__CreateLayer},
 {"Geo::GNMc::Network_CopyLayer", _wrap_Network_CopyLayer},
-{"Geo::GNMc::Network_DeleteLayer", _wrap_Network_DeleteLayer},
+{"Geo::GNMc::Network__DeleteLayer", _wrap_Network__DeleteLayer},
 {"Geo::GNMc::Network_GetLayerCount", _wrap_Network_GetLayerCount},
 {"Geo::GNMc::Network_GetLayerByIndex", _wrap_Network_GetLayerByIndex},
 {"Geo::GNMc::Network_GetLayerByName", _wrap_Network_GetLayerByName},
-{"Geo::GNMc::Network_TestCapability", _wrap_Network_TestCapability},
+{"Geo::GNMc::Network__TestCapability", _wrap_Network__TestCapability},
 {"Geo::GNMc::Network_StartTransaction", _wrap_Network_StartTransaction},
 {"Geo::GNMc::Network_CommitTransaction", _wrap_Network_CommitTransaction},
 {"Geo::GNMc::Network_RollbackTransaction", _wrap_Network_RollbackTransaction},
@@ -4717,7 +4888,6 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   }
   
-  SWIG_TypeClientData(SWIGTYPE_p_GDALMajorObjectShadow, (void*) "Geo::GNM::MajorObject");
   /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "GATDijkstraShortestPath", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(GATDijkstraShortestPath)));
diff --git a/swig/perl/index.dox b/swig/perl/index.dox
index c565ca2..7556ee4 100644
--- a/swig/perl/index.dox
+++ b/swig/perl/index.dox
@@ -3,7 +3,7 @@
 \section index_version Version
 
 These pages document the development version of the GDAL Perl API,
-which is extended from the released versions APIs. Old versions: 
+which is extended from the released versions APIs. Old versions:
 <a href="../1.4/index.html">1.4</a>
 <a href="../1.5/index.html">1.5</a>
 <a href="../1.6/index.html">1.6</a>
@@ -13,6 +13,7 @@ which is extended from the released versions APIs. Old versions:
 <a href="../1.10/index.html">1.10</a>
 <a href="../1.11/index.html">1.11</a>
 <a href="../2.0/index.html">2.0</a>
+<a href="../2.1/index.html">2.1</a>
 
 \section index_intro Introduction
 
@@ -200,17 +201,17 @@ OGR Error: Unsupported geometry type at <long path>/OGR.pm line 652.
 and
 
 \code
-BEGIN { 
-    $SIG{__WARN__} = sub {  print STDERR "Warning: @_"; } 
+BEGIN {
+    $SIG{__WARN__} = sub {  print STDERR "Warning: @_"; }
 }
-Geo::GDAL::GetDriver('GTiff')->Create( Name => 'my.tiff', 
-                                       Width => 100, 
-                                       Height => 100, 
-                                       Type => 'Byte', 
+Geo::GDAL::GetDriver('GTiff')->Create( Name => 'my.tiff',
+                                       Width => 100,
+                                       Height => 100,
+                                       Type => 'Byte',
                                        Options => { my_unknown_option => 'b' } );
 \endcode
 
-Produces: 
+Produces:
 \code
 Warning: Driver GTiff does not support my_unknown_option creation option at site/lib/Geo/GDAL.pm line 771.
 \endcode
@@ -238,7 +239,7 @@ Prints
 
 OGR: OGRMultiPoint::exportToWkt() - skipping POINT EMPTY.
 
-to STDERR, and 
+to STDERR, and
 
 MULTIPOINT ((1 1))
 
@@ -259,7 +260,7 @@ ProgressData, the method will happily recognize also progress_data.
 
 Some methods accept a callback function for reporting the
 progress. The progress subroutine is called with three arguments: a
-number, a string, and user defined data. The user defined data 
+number, a string, and user defined data. The user defined data
 is an argument to the method.
 
 \code
@@ -301,14 +302,14 @@ GDAL maintains its own reference counting but this is largely lost in
 the bindings.
 
 The Perl bindings attempt to maintain these dependencies by keeping
-the parent objects alive under the hood, independent of their existence 
+the parent objects alive under the hood, independent of their existence
 in the user space. Thus it is perfectly legal to do something like
 
 \code
 my $layer = Geo::OGR::Driver('Memory')->
     Create()->
-        CreateLayer(Name => 'layer', 
-                    Fields => [{Name => 'test', Type => 'Integer'}, 
+        CreateLayer(Name => 'layer',
+                    Fields => [{Name => 'test', Type => 'Integer'},
                                {Name => 'geom', Type => 'Point'}]);
 \endcode
 
@@ -341,16 +342,29 @@ my $feature = $lauer->InsertFeature({test => 13, geom => {WKT => 'POINT (10 20)'
 my $geom = $feature->{geom}; # will lead to memory error!
 \endcode
 
+\section index_processing_options Processing options
+
+Some methods are thin wrappers for <a
+href="http://www.gdal.org/pages.html">GDAL command line tools</a>.
+
+The options for these methods should be given in an anonymous hash
+where the key is the option name (-ot, -mask, etc) and the value is
+the option value. If the option expects a list of values, the list
+should be given as a reference to an array.
+
+In addition to the above, the API supports giving the options in an
+anonymous array; keys without hyphen (not if the options are in an
+array); and lists of values given as a string, separated with
+whitespace (only for lists of numeric values).
+
 \section index_footer Note
 
 This documentation is generated from files within the GDAL
 distribution (directory swig/perl) with Doxygen using a Perl module <a
-href="http://search.cpan.org/~jordan/Doxygen-Filter-Perl/">Doxygen::Filter::Perl</a>
-(see also <a
-href="https://rt.cpan.org/Public/Dist/Display.html?Name=Doxygen-Filter-Perl">the
-Doxygen::Filter::Perl bug reports</a>). A tailor made preprocessor in
-the GDAL distribution is used to process and put all Perl code and
-documentation into a single file (all.pm) for Doxygen.
+href="http://search.cpan.org/~jordan/Doxygen-Filter-Perl/">Doxygen::Filter::Perl</a>.
+A tailor made preprocessor in the GDAL distribution is used to process
+and put all Perl code and documentation into a single file (all.pm)
+for Doxygen-Filter-Perl and Doxygen.
 
 Many methods are just interfaces to non-Perl code in the bindings or
 GDAL and thus their code show as blank on these pages. The bindings
diff --git a/swig/perl/lib/Geo/GDAL.dox b/swig/perl/lib/Geo/GDAL.dox
index c0b0fa5..a15793c 100644
--- a/swig/perl/lib/Geo/GDAL.dox
+++ b/swig/perl/lib/Geo/GDAL.dox
@@ -1,7 +1,6 @@
 ## @class Geo::GDAL
 # @brief GDAL utility functions and a root class for raster classes.
-#
-# Geo::GDAL wraps many GDAL utility functions and is as a root class
+# @details Geo::GDAL wraps many GDAL utility functions and is as a root class
 # for all GDAL raster classes. A "raster" is an object, whose core is
 # a rectagular grid of cells, called a "band" in GDAL. Each cell
 # contains a numeric value of a specific data type.
@@ -24,7 +23,6 @@
 ## @ignore last_error
 ## @ignore error
 ## @ignore named_parameters
-## @ignore string2int
 
 ## @ignore GeneralCmdLineProcessor
 ## @ignore ParseCommandLine
@@ -116,7 +114,7 @@
 ## @ignore SerializeXMLTree
 
 
-## @sub UseExceptions 
+## @sub UseExceptions
 # Use the Perl exception mechanism for GDAL messages (failures are
 # confessed and warnings are warned) and collect the messages
 # into \@Geo::GDAL::error. This is the default.
@@ -249,6 +247,9 @@
 
 ## @sub @DriverNames()
 # Available raster format drivers.
+# \code
+# perl -MGeo::GDAL -e '@d=Geo::GDAL::DriverNames;print "@d\n"'
+# \endcode
 # @note Use Geo::OGR::DriverNames for vector drivers.
 # @return a list of the short names of all available GDAL raster drivers.
 
@@ -299,11 +300,7 @@
 #
 # @return a new Geo::GDAL::Dataset object if success.
 
-## @sub Geo::GDAL::Dataset OpenShared($name, $access = 'ReadOnly')
-# Open a raster dataset in shared mode.
-# @param name Raster dataset string (typically a filename).
-# @param access Access type, either 'ReadOnly' (the default) or 'Update'.
-# @return a new Geo::GDAL::Dataset object or undef.
+## @ignore OpenShared
 
 ## @sub Geo::GDAL::Dataset OpenEx(%params)
 # The generic dataset open method, used internally by all Open and OpenShared methods.
@@ -324,6 +321,7 @@
 
 ## @class Geo::GDAL::XML
 # @brief A simple XML parser
+# @details
 
 ## @method new($string)
 # @param string String containing XML.
@@ -339,15 +337,15 @@
 
 ## @class Geo::GDAL::AsyncReader
 # @brief Enable asynchronous requests.
+# @details This class is not yet documented nor tested in the GDAL Perl wrappers
 # @isa (Geo::GDAL)
 # @todo Test and document.
-#
-# This class is not yet documented nor tested in the GDAL Perl wrappers
 
 
 
 ## @class Geo::GDAL::MajorObject
 # @brief An object, which holds meta data.
+# @details
 # @isa (Geo::GDAL)
 
 ## @sub Domains
@@ -388,6 +386,7 @@
 
 ## @class Geo::GDAL::Driver
 # @brief A driver for a specific dataset format.
+# @details
 # @isa (Geo::GDAL::MajorObject Geo::GDAL)
 
 ## @method Open
@@ -439,8 +438,9 @@
 # @return a boolean value.
 
 ## @method $Extension()
-# @return a suggested extension or extensions (e.g., ext1/ext2) for
-# datasets.
+# @note The returned extension does not contain a '.' prefix.
+# @return a suggested single extension or a list of extensions (in
+# list context) for datasets.
 
 ## @method $MIMEType()
 # @return a suggested MIME type for datasets.
@@ -472,7 +472,7 @@
 
 ## @method Geo::GDAL::Dataset Copy(%params)
 # Create a new raster Geo::GDAL::Dataset as a copy of an existing dataset.
-# @note a.k.a. CreateCopy 
+# @note a.k.a. CreateCopy
 #
 # @param params Named parameters:
 # - \a Name name for the new raster dataset.
@@ -492,6 +492,7 @@
 
 ## @class Geo::GDAL::GCP
 # @brief A ground control point for georeferencing rasters.
+# @details
 # @isa (Geo::GDAL)
 
 ## @cmethod $new($x = 0.0, $y = 0.0, $z = 0.0, $column = 0.0, $row = 0.0, $info = "", $id = "")
@@ -530,6 +531,7 @@
 
 ## @class Geo::GDAL::Dataset
 # @brief A set of associated raster bands or vector layer source.
+# @details
 # @isa (Geo::GDAL::MajorObject Geo::GDAL)
 
 ## @sub Geo::GDAL::Dataset Open
@@ -556,7 +558,8 @@
 ## @method @Size()
 # @return (width, height)
 
-## @method Geo::GDAL::Driver GetDriver()
+## @method Geo::GDAL::Driver Driver()
+# @note a.k.a. GetDriver
 # @return a Geo::GDAL::Driver object that was used to open or create this dataset.
 
 ## @ignore GetRasterBand
@@ -564,7 +567,7 @@
 ## @method Geo::GDAL::Band Band($index)
 # Create a band object for the band within the dataset.
 # @note a.k.a. GetRasterBand
-# @param index 1...RasterCount
+# @param index 1...RasterCount, default is 1.
 # @return a new Geo::GDAL::Band object
 
 ## @method @Bands()
@@ -592,12 +595,12 @@
 #
 # @param %params Named parameters:
 # - \a Name (scalar) name for the new layer.
-# - \a Fields (array reference) a list of (scalar and geometry) field definitions as in 
+# - \a Fields (array reference) a list of (scalar and geometry) field definitions as in
 # Geo::OGR::Layer::CreateField.
 # - \a ApproxOK (boolean value, default is true) a flag, which is forwarded to Geo::OGR::Layer::CreateField.
 # - \a Options (hash reference) driver specific hash of layer creation options.
 # - \a Schema (hash reference, deprecated, use \a Fields and \a Name) may contain keys Name, Fields, GeomFields, GeometryType.
-# - \a SRS (scalar, deprecated) the spatial reference for the default geometry field.
+# - \a SRS (scalar) the spatial reference for the default geometry field.
 # - \a GeometryType (scalar) the type of the default geometry field
 # (if only one geometry field). Default is 'Unknown'.
 #
@@ -609,11 +612,11 @@
 # Example:
 # \code
 # my $roads = Geo::OGR::Driver('Memory')->Create('road')->
-# .   CreateLayer(
-# .       Fields => [ { Name => 'class', 
-# .                     Type => 'Integer' },
-# .                   { Name => 'geom', 
-# .                     Type => 'LineString25D' } ] );
+#    CreateLayer(
+#        Fields => [ { Name => 'class',
+#                      Type => 'Integer' },
+#                    { Name => 'geom',
+#                      Type => 'LineString25D' } ] );
 # \endcode
 #
 # @note Many formats allow only one spatial field, which currently
@@ -691,6 +694,18 @@
 ## @method $GetGCPProjection()
 # @return projection string.
 
+## @method Geo::GDAL::Extent Extent(@params)
+# @param params nothing, or a list ($xoff, $yoff, $w, $h)
+# @return A new Geo::GDAL::Extent object that represents the area that
+# this raster or the specified tile covers.
+
+## @method Tile(Geo::GDAL::Extent e)
+# Compute the top left cell coordinates and width and height of the
+# tile that covers the given extent.
+# @param e The extent whose tile is needed.
+# @note Requires that the raster is a strictly north up one.
+# @return A list ($xoff, $yoff, $xsize, $ysize).
+
 ## @method FlushCache()
 # Write cached data to disk. There is usually no need to call this
 # method.
@@ -702,7 +717,7 @@
 # @return The added band.
 
 ## @method WriteRaster(%params)
-# Write data into the dataset. 
+# Write data into the dataset.
 #
 # @param params Named parameters:
 # - \a XOff x offset (cell coordinates) (default is 0)
@@ -745,47 +760,32 @@
 ## @method CreateMaskBand()
 # Add a mask band to the dataset.
 
-## @method Geo::GDAL::Dataset DEMProcessing($Dest, $Processing, $ColorFilename, $Options, coderef progress, $progress_data)
+## @method Geo::GDAL::Dataset DEMProcessing($Dest, $Processing, $ColorFilename, hashref Options, coderef progress, $progress_data)
 # Apply a DEM processing to this dataset.
 # @param Dest Destination raster dataset definition string (typically filename) or an object, which implements write and close.
 # @param Processing Processing to apply, one of "hillshade", "slope", "aspect", "color-relief", "TRI", "TPI", or "Roughness".
 # @param ColorFilename The color palette for color-relief.
-# @param Options A reference to a hash or list of options. For a hash
-# the keys are without the prefix '-'. For example give { of => 'PNG'
-# } to set the output format. For a list the options are given as for
-# the command line utility. See <a
-# href="http://www.gdal.org/gdaldem.html">gdaldem</a> for all options.
+# @param Options See section \ref index_processing_options.
 # @param progress [optional] A reference to a subroutine, which will
 # be called with parameters (number progress, string msg, progress_data).
 # @param progress_data [optional]
 #
 
-## @method Geo::GDAL::Dataset Nearblack($Dest, $Options, coderef progress, $progress_data)
+## @method Geo::GDAL::Dataset Nearblack($Dest, hashref Options, coderef progress, $progress_data)
 # Convert nearly black/white pixels to black/white.
 # @param Dest Destination raster dataset definition string (typically
 # filename), destination dataset to which to add an alpha or mask
 # band, or an object, which implements write and close.
-# @param Options A reference to a hash or list of options. For a hash
-# the keys are without the prefix '-'. For example give { of => 'PNG'
-# } to set the output format. For a list the options are given as for
-# the command line utility. See <a
-# href="http://www.gdal.org/nearblack.html">nearblack</a> for all
-# options.
+# @param Options See section \ref index_processing_options.
 # @return Dataset if destination dataset definition string was given,
 # otherwise a boolean for success/fail but the method croaks if there
 # was an error.
 
-## @method Geo::GDAL::Dataset Translate($Dest, $Options, coderef progress, $progress_data)
+## @method Geo::GDAL::Dataset Translate($Dest, hashref Options, coderef progress, $progress_data)
 # Convert this dataset into another format.
 # @param Dest Destination dataset definition string (typically
 # filename) or an object, which implements write and close.
-# @param Options A reference to a hash or list of options. For a hash
-# the keys are without the prefix '-'. For example give { of => 'PNG'
-# } to set the output format. For a list the options are given as for
-# the command line utility. See <a
-# href="http://www.gdal.org/gdal_translate.html">gdal_translate</a>
-# and <a href="http://www.gdal.org/ogr2ogr.html">ogr2ogr</a> for all
-# options.
+# @param Options See section \ref index_processing_options.
 # @return New dataset object if destination dataset definition
 # string was given, otherwise a boolean for success/fail but the
 # method croaks if there was an error.
@@ -803,74 +803,46 @@
 #
 # @return a new Geo::GDAL::Dataset object
 
-## @method Geo::GDAL::Dataset Warp($Dest, $Options, coderef progress, $progress_data)
+## @method Geo::GDAL::Dataset Warp($Dest, hashref Options, coderef progress, $progress_data)
 # Reproject this dataset.
 # @param Dest Destination raster dataset definition string (typically
 # filename) or an object, which implements write and close.
-# @param Options A reference to a hash or list of options. For a hash
-# the keys are without the prefix '-'. For example give { of => 'PNG'
-# } to set the output format. For a list the options are given as for
-# the command line utility. See <a
-# href="http://www.gdal.org/gdalwarp.html">gdalwarp</a> for
-# all options.
-
-## @method Geo::GDAL::Dataset Grid($Dest, $Options)
+# @param Options See section \ref index_processing_options.
+# @note This method can be run as a package subroutine with a list of
+# datasets as the first argument to mosaic several datasets.
+
+## @method Geo::GDAL::Dataset Grid($Dest, hashref Options)
 # Creates a regular raster grid from this data source.
 # This is equivalent to the gdal_grid utility.
-# @param Dest Destination raster dataset definition string (typically filename) or an object, which implements write and close.
-# @param Options A reference to a hash or list of options. For a
-# hash the keys are without the prefix '-'. For example give { of =>
-# 'PNG' } to set the output format. You must specify at least layer
-# name (key = l) or SQL to create a layer (key = sql). For a list the
-# options are given as for the command line utility. See 
-# <a href="http://www.gdal.org/gdal_grid.html">gdal_grid</a> for a
-# complete list of options.
-#
+# @param Dest Destination raster dataset definition string (typically
+# filename) or an object, which implements write and close.
+# @param Options See section \ref index_processing_options.
 
-## @method Geo::GDAL::Dataset Rasterize($Dest, $Options, coderef progress, $progress_data)
+## @method Geo::GDAL::Dataset Rasterize($Dest, hashref Options, coderef progress, $progress_data)
 # Render data from this data source into a raster.
 # @param Dest Destination raster dataset definition string (typically
 # filename), destination dataset, or an object, which implements write and close.
-# @param Options A reference to a hash or list of options. For a hash the keys
-# are without the prefix '-' and the values must be strings. For
-# example give { of => 'PNG' } to set the output format. You must
-# specify at least layer name (key = l) or SQL to create a layer (key
-# = sql). To create a new raster, you need to specify either target
-# resolution (tr => xres,yres) or target file size (ts =>
-# width,height). For a list the options are given as for the command
-# line utility.See <a href="http://www.gdal.org/gdal_rasterize.html">gdal_rasterize</a> for a
-# complete list of options.
+# @param Options See section \ref index_processing_options.
 # @return Dataset if destination dataset definition string was given,
 # otherwise a boolean for success/fail but the method croaks if there
 # was an error.
 #
 
-## @method Geo::GDAL::Dataset BuildVRT($Dest, arrayref Sources, $Options, coderef progress, $progress_data)
+## @method Geo::GDAL::Dataset BuildVRT($Dest, arrayref Sources, hashref Options, coderef progress, $progress_data)
 # Build a virtual dataset from a set of datasets.
 # @param Dest Destination raster dataset definition string (typically
 # filename), or an object, which implements write and close.
 # @param Sources A list of filenames of input datasets or a list of
 # dataset objects.
-# @param Options A reference to a hash or list of options. For a hash
-# the keys are without the prefix '-' and the values must be
-# strings. For example give { r => 'cubic' } to select a resampling
-# algorithm. For a list the options are given as for the command line
-# utility. See <a
-# href="http://www.gdal.org/gdalbuildvrt.html">gdalbuildvrt</a> for a
-# complete list of options.
+# @param Options See section \ref index_processing_options.
 # @return Dataset object
 #
 # @note This subroutine is imported into the main namespace if Geo::GDAL
 # is use'd with qw/:all/.
 
-## @method $Info($Options)
+## @method $Info(hashref Options)
 # Information about this dataset.
-# @param Options A reference to a hash or list of options. For a hash
-# the keys are without the prefix '-'. For example give { JSON => 1 }
-# to set the output format to JSON. For a list the options are given
-# as for the command line utility. See <a
-# href="http://www.gdal.org/gdalinfo.html">gdalinfo</a> for all
-# options.
+# @param Options See section \ref index_processing_options.
 
 ## @method Geo::GDAL::ColorTable ComputeColorTable(%params)
 # Compute a color table from an RGB image
@@ -906,8 +878,36 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 
 
 
+
+## @class Geo::GDAL::Extent
+# @brief A rectangular area in projection coordinates: xmin, ymin, xmax, ymax.
+
+## @sub Geo::GDAL::Extent new(@params)
+# @param params nothing, a list ($xmin, $ymin, $xmax, $ymax), or an Extent object
+# @return A new Extent object (empty if no parameters, a copy of the parameter if it is an Extent object).
+
+## @sub @Size()
+# @return A list ($width, $height).
+
+## @sub $Overlaps($extent)
+# @param extent Another Geo::GDAL::Extent object.
+# @return True if this extent overlaps the other extent, false otherwise.
+
+## @sub $Overlap($extent)
+# @param extent Another Geo::GDAL::Extent object.
+# @return A new, possibly empty, Geo::GDAL::Extent object, which
+# represents the joint area of the two extents.
+
+## @sub ExpandToInclude($extent)
+# Extends this extent to include the other extent.
+# @param extent Another Geo::GDAL::Extent object.
+
+
+
+
 ## @class Geo::GDAL::Band
 # @brief A raster band.
+# @details
 # @isa ( Geo::GDAL::MajorObject Geo::GDAL )
 
 ## @sub ColorInterpretations
@@ -942,9 +942,10 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 ## @method @Size()
 # @return The size of the band as a list (width, height).
 
-## @method @GetBlockSize()
-# @return The size of a preferred i/o raster blocks as a list (width,
-# height).
+## @method @BlockSize()
+# A.k.a GetBlockSize
+# @return The size of a preferred i/o raster block size as a list
+# (width, height).
 
 ## @ignore GetRasterColorInterpretation
 ## @ignore SetRasterColorInterpretation
@@ -965,15 +966,13 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 ## @method $DeleteNoDataValue()
 
 ## @method $NoDataValue($NoDataValue)
-# Remove no data value from this band.
-
-# @param NoDataValue [optional]
 # Get or set the "no data" value.
-# @note $band->NoDataValue(undef) sets the "no data" value to the
+# @param NoDataValue [optional]
+# @note $band->NoDataValue(undef) sets the NoData value to the
 # Posix floating point maximum. Use Geo::GDAL::Band::DeleteNoDataValue
-# to remove no data value from this band.
-# @return The "no data" value or undef in scalar context. An undef
-# value indicates that there is no no data value associated with this
+# to stop this band using a NoData value.
+# @return The NoData value or undef in scalar context. An undef
+# value indicates that there is no NoData value associated with this
 # band.
 
 ## @ignore GetUnitType
@@ -1000,6 +999,44 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 # are not set.
 # @since version 1.9 of the bindings.
 
+## @method hashref ClassCounts($classifier, $progress = undef, $progress_data = undef)
+# Compute the counts of cell values or number of cell values in ranges.
+# @note Classifier is required only for float bands. Do not specify
+# one for integer bands.
+# @note NoData values are counted similar to other values.
+#
+# @param classifier Anonymous array of format [ $comparison,
+# $classifier ], where $comparison is a string '<', '<=', '>', or '>='
+# and $classifier is an anonymous array of format [ $value,
+# $value|$classifier, $value|$classifier ], where $value is numeric
+# value against which the reclassified value is compared to.
+# @note Numeric value requires decimal point.
+#
+# In the example below, the real line is divided into ranges
+# [-inf..3), [3..5), and [5..inf], i.e., three ranges with indexes 0,
+# 1, and 2.
+# \code
+# $classifier = [ '<', [5.0, [3.0, 1.0, 2.0], 3.0] ];
+# \endcode
+# @return a reference to an anonymous hash, which contains the class
+# values (indexes) as keys and the number of cells with that value or
+# in that range as values. If the subroutine is user terminated an
+# error is raised.
+
+## @method Reclassify($classifier, $progress = undef, $progress_data = undef)
+# Reclassify the cells in the band.
+# @note This method is defined only for integer bands.
+# @note NoData values are reclassified if explicitly specified in the
+# map. However, they are not reclassified to the default value, if one
+# is specified.
+# @note If the subroutine is user terminated or the classifier is
+# incorrect, already reclassified cells will stay reclassified but an
+# error is raised.
+# @param classifier For integer rasters an anonymous hash, which
+# contains old class values as keys and new class values as values. A
+# special key '*' (star) can be used as default, to act as a fallback
+# new class value. For float rasters as in Geo::GDAL::Band::ClassCounts.
+
 ## @method ComputeRasterMinMax($approx_ok = 0)
 # @return arrayref MinMax = [min, max]
 
@@ -1079,7 +1116,23 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 # @param imag_part Imaginary component of fill value.
 #
 
+## @method Piddle($piddle, $xoff = 0, $yoff = 0, $xsize = <width>, $ysize = <height>, $xdim, $ydim)
+# Read or write band data from/into a piddle.
+#
+# \note The PDL module must be available for this method to work. Also, you
+# should 'use PDL' in the code that you use this method.
+#
+# @param piddle [only when writing] The piddle from which to read the data to be written into the band.
+# @param xoff, yoff The offset for data in the band, default is top left (0, 0).
+# @param xsize, ysize [optional] The size of the window in the band.
+# @param xdim, ydim [optional, only when reading from a band] The size of the piddle to create.
+# @return A new piddle when reading from a band (no not use when writing into a band).
+
 ## @method WriteTile($data, $xoff = 0, $yoff = 0)
+# Write band data from a Perl array.
+#
+# \note Accessing band data in this way is slow. Consider using PDL and Geo::GDAL::Band::Piddle.
+#
 # @param data A two-dimensional Perl array, organizes as data->[y][x], y =
 # 0..height-1, x = 0..width-1.
 # @param xoff
@@ -1087,6 +1140,9 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 #
 
 ## @method \@ReadTile($xoff = 0, $yoff = 0, $xsize = <width>, $ysize = <height>)
+# Read band data into a Perl array.
+#
+# \note Accessing band data in this way is slow. Consider using PDL and Geo::GDAL::Band::Piddle.
 #
 # Usage example (print the data from a band):
 # \code
@@ -1094,22 +1150,22 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 # \endcode
 # Another usage example (process the data of a large dataset that has one band):
 # \code
-# my($W,$H) = $dataset->Band(1)->Size();
+# my($W,$H) = $dataset->Band()->Size();
 # my($xoff,$yoff,$w,$h) = (0,0,200,200);
 # while (1) {
-# .    if ($xoff >= $W) {
-# .        $xoff = 0;
-# .        $yoff += $h;
-# .        last if $yoff >= $H;
-# .    }
-# .    my $data = $dataset->Band(1)->ReadTile($xoff,$yoff,min($W-$xoff,$w),min($H-$yoff,$h));
-# .    # add your data processing code here
-# .    $dataset->Band(1)->WriteTile($data,$xoff,$yoff);
-# .    $xoff += $w;
+#     if ($xoff >= $W) {
+#         $xoff = 0;
+#         $yoff += $h;
+#         last if $yoff >= $H;
+#     }
+#     my $data = $dataset->Band(1)->ReadTile($xoff,$yoff,min($W-$xoff,$w),min($H-$yoff,$h));
+#     # add your data processing code here
+#     $dataset->Band(1)->WriteTile($data,$xoff,$yoff);
+#     $xoff += $w;
 # }
 #
 # sub min {
-# .    return $_[0] < $_[1] ? $_[0] : $_[1];
+#     return $_[0] < $_[1] ? $_[0] : $_[1];
 # }
 # \endcode
 # @param xoff Number of cell to skip before starting to read from a row. Pixels are read from left to right.
@@ -1213,7 +1269,7 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 # - \a PerDataset: The mask band is shared between all bands on the dataset.
 # - \a Alpha: The mask band is actually an alpha band and may have values
 # other than 0 and 255.
-# - \a NoData: Indicates the mask is actually being generated from nodata values.
+# - \a NoData: Indicates the mask is actually being generated from NoData values.
 # (mutually exclusive of Alpha).
 
 ## @method CreateMaskBand(@flags)
@@ -1253,7 +1309,12 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 # - \a Mask A raster band, which is used as a mask to select polygonized areas. Default is undef.
 # - \a OutLayer A vector layer into which the polygons are written. If not given, an in-memory layer 'polygonized' is created and returned.
 # - \a PixValField The name of the field in the output layer into which the cell value of the polygon area is stored. Default is 'val'.
-# - \a Options Hash or list of options. Connectedness can be set to 4 to use 4-connectedness, otherwise 8-connectedness is used. ForceIntPixel can be set to 1 to force using a 32 bit int buffer for cell values in the process. If this is not set and the data type of this raster does not fit into a 32 bit int buffer, a 32 bit float buffer is used.
+# - \a Options Hash or list of options. Connectedness can be set to 8
+to use 8-connectedness, otherwise 4-connectedness is
+used. ForceIntPixel can be set to 1 to force using a 32 bit int buffer
+for cell values in the process. If this is not set and the data type
+of this raster does not fit into a 32 bit int buffer, a 32 bit float
+buffer is used.
 # - \a Progress Progress function.
 # - \a ProgressData Additional parameter for the progress function.
 #
@@ -1338,9 +1399,9 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 # - \a Options Hash of options. Options are:
 #   - \a Values A list of cell values in this band to measure the distance from. If this option is not provided, the distance will be computed to non-zero pixel values. Currently pixel values are internally processed as integers.
 #   - \a DistUnits=PIXEL|GEO Indicates whether distances will be computed in cells or in georeferenced units. The default is pixel units. This also determines the interpretation of MaxDist.
-#   - \a MaxDist=n The maximum distance to search. Distances greater than this value will not be computed. Instead output cells will be set to a nodata value.
-#   - \a NoData=n The nodata value to use on the distance band for cells that are beyond MaxDist. If not provided, the distance band will be queried for a nodata value. If one is not found, 65535 will be used (255 if the type is Byte).
-#   - \a Use_Input_NoData=YES|NO If this option is set, the nodata value of this band will be respected. Leaving nodata cells in the input as nodata pixels in the distance raster.
+#   - \a MaxDist=n The maximum distance to search. Distances greater than this value will not be computed. Instead output cells will be set to a NoData value.
+#   - \a NoData=n The NoData value to use on the distance band for cells that are beyond MaxDist. If not provided, the distance band will be queried for a NoData value. If one is not found, 65535 will be used (255 if the type is Byte).
+#   - \a Use_Input_NoData=YES|NO If this option is set, the NoData value of this band will be respected. Leaving NoData cells in the input as NoData pixels in the distance raster.
 #   - \a Fixed_Buf_Val=n If this option is set, all cells within the MaxDist threshold are set to this value instead of the distance value.
 #   - \a DataType The data type for the result if it is not given.
 # - \a Progress Progress function.
@@ -1354,6 +1415,7 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 
 ## @class Geo::GDAL::ColorTable
 # @brief A color table from a raster band or a color table, which can be used for a band.
+# @details
 # @isa ( Geo::GDAL::MajorObject Geo::GDAL )
 
 ## @cmethod Geo::GDAL::ColorTable new($GDALPaletteInterp = 'RGB')
@@ -1410,6 +1472,7 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 
 ## @class Geo::GDAL::RasterAttributeTable
 # @brief An attribute table in a raster band.
+# @details
 # @isa = ( Geo::GDAL::MajorObject Geo::GDAL )
 
 ## @cmethod Geo::GDAL::RasterAttributeTable new()
@@ -1516,8 +1579,7 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 
 ## @class Geo::GDAL::Transformer
 # @brief
-#
-# This class is not yet documented for the GDAL Perl bindings.
+# @details This class is not yet documented for the GDAL Perl bindings.
 # @todo Test and document.
 
 
@@ -1525,6 +1587,7 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 
 ## @class Geo::GDAL::VSIF
 # @brief A GDAL virtual file system.
+# @details
 # @isa = ( Geo::GDAL )
 
 ## @sub Geo::GDAL::VSIF Open($filename, $mode)
@@ -1587,32 +1650,40 @@ Geo::GDAL::Driver('PNG')->Copy(Name => 'test.png', Src => $d->Dither->Dataset);
 
 ## @class Geo::GDAL::GeoTransform
 # @brief An array of affine transformation coefficients.
-#
-# The geo transformation has the form
+# @details The geo transformation has the form
 # \code
-# x = a + column * b + row * c
-# y = d + column * e + row * f
+x = a + column * b + row * c
+y = d + column * e + row * f
 # \endcode
-# where<br/>
-# (column,row) is the location in cell coordinates<br/>
-# (x,y) is the location in projection coordinates<br/>
-# or vice versa.
+# where
+# (column,row) is the location in cell coordinates, and
+# (x,y) is the location in projection coordinates, or vice versa.
 # A Geo::GDAL::GeoTransform object is a reference to an anonymous array [a,b,c,d,e,f].
 # @isa = ( Geo::GDAL )
 
-## @cmethod new(@coeffs)
+## @cmethod new(@params)
+# @param params nothing, a reference to an array [a,b,c,d,e,f], a list
+# (a,b,c,d,e,f), or named parameters
+# - \a GCPs A reference to an array of Geo::GDAL::GCP objects.
+# - \a ApproxOK Minimize the error in the coefficients (integer, default is 1 (true), used with GCPs).
+# - \a Extent A Geo::GDAL::Extent object used to obtain the coordinates of the up left corner position.
+# - \a CellSize The cell size (width and height) (default is 1, used with Extent).
+#
+# @note When Extent is specifid, the created geo transform will be
+# north up, have square cells, and coefficient f will be -1 times the
+# cell size (image y - row - will increase downwards and projection y
+# will increase upwards).
 # @return a new Geo::GDAL::GeoTransform object.
 
-## @method FromGCPs(@GCPs, $ApproxOK)
-# Compute transformation coefficients from a list of Geo::GDAL::GCP
-# objects
-# @param GCPs A list of Geo::GDAL::GCP objects.
-# @param ApproxOK [optional] Minimize the error in the coefficient (integer, default is true).
-# @return a new Geo::GDAL::GeoTransform object.
+## @ignore FromGCPs
+## @ignore FromExtentAndCellSize
+## @ignore Extent
 
-## @method Apply(array reference x, array reference y)
-# @return a list (x, y), where x and y are references to arrays of
-# transformed coordinates.
+## @method Apply($x, $y)
+# @param x Column or x, or a reference to an array of columns or x's
+# @param y Row or y, or a reference to an array of rows or y's
+# @return a list (x, y), where x and y are the transformed coordinates
+# or references to arrays of transformed coordinates.
 
 ## @method Inv
 # @return a new Geo::GDAL::GeoTransform object, which is the inverse
diff --git a/swig/perl/lib/Geo/GDAL.pm b/swig/perl/lib/Geo/GDAL.pm
index 1719e7a..548b063 100644
--- a/swig/perl/lib/Geo/GDAL.pm
+++ b/swig/perl/lib/Geo/GDAL.pm
@@ -126,6 +126,7 @@ package Geo::GDAL;
 *ContourGenerate = *Geo::GDALc::ContourGenerate;
 *_AutoCreateWarpedVRT = *Geo::GDALc::_AutoCreateWarpedVRT;
 *CreatePansharpenedVRT = *Geo::GDALc::CreatePansharpenedVRT;
+*ApplyVerticalShiftGrid = *Geo::GDALc::ApplyVerticalShiftGrid;
 *ApplyGeoTransform = *Geo::GDALc::ApplyGeoTransform;
 *InvGeoTransform = *Geo::GDALc::InvGeoTransform;
 *VersionInfo = *Geo::GDALc::VersionInfo;
@@ -153,6 +154,7 @@ package Geo::GDAL;
 *_OpenEx = *Geo::GDALc::_OpenEx;
 *_OpenShared = *Geo::GDALc::_OpenShared;
 *IdentifyDriver = *Geo::GDALc::IdentifyDriver;
+*IdentifyDriverEx = *Geo::GDALc::IdentifyDriverEx;
 *GeneralCmdLineProcessor = *Geo::GDALc::GeneralCmdLineProcessor;
 *GDALInfo = *Geo::GDALc::GDALInfo;
 *wrapper_GDALTranslate = *Geo::GDALc::wrapper_GDALTranslate;
@@ -269,7 +271,7 @@ sub DESTROY {
         Geo::GDALc::delete_GCP($self);
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
     if ($code) {
         Geo::GDAL::VSIStdoutUnsetRedirection();
         $code->close;
@@ -351,7 +353,7 @@ sub DESTROY {
         Geo::GDALc::delete_Dataset($self);
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
     if ($code) {
         Geo::GDAL::VSIStdoutUnsetRedirection();
         $code->close;
@@ -383,6 +385,8 @@ sub DESTROY {
 *GetLayerCount = *Geo::GDALc::Dataset_GetLayerCount;
 *GetLayerByIndex = *Geo::GDALc::Dataset_GetLayerByIndex;
 *GetLayerByName = *Geo::GDALc::Dataset_GetLayerByName;
+*ResetReading = *Geo::GDALc::Dataset_ResetReading;
+*GetNextFeature = *Geo::GDALc::Dataset_GetNextFeature;
 *_TestCapability = *Geo::GDALc::Dataset__TestCapability;
 *ExecuteSQL = *Geo::GDALc::Dataset_ExecuteSQL;
 *_ReleaseResultSet = *Geo::GDALc::Dataset__ReleaseResultSet;
@@ -465,6 +469,8 @@ use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
 *GetCategoryNames = *Geo::GDALc::Band_GetCategoryNames;
 *SetCategoryNames = *Geo::GDALc::Band_SetCategoryNames;
 *ContourGenerate = *Geo::GDALc::Band_ContourGenerate;
+*ClassCounts = *Geo::GDALc::Band_ClassCounts;
+*Reclassify = *Geo::GDALc::Band_Reclassify;
 sub DISOWN {
     my $self = shift;
     my $ptr = tied(%$self);
@@ -488,7 +494,7 @@ use Carp;
 sub new {
     my($pkg, $pi) = @_;
     $pi //= 'RGB';
-    $pi = Geo::GDAL::string2int($pi, \%PALETTE_INTERPRETATION_STRING2INT);
+    $pi = s2i(palette_interpretation => $pi);
     my $self = Geo::GDALc::new_ColorTable($pi);
     bless $self, $pkg if defined($self);
 }
@@ -507,7 +513,7 @@ sub DESTROY {
         Geo::GDALc::delete_ColorTable($self);
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
     if ($code) {
         Geo::GDAL::VSIStdoutUnsetRedirection();
         $code->close;
@@ -561,7 +567,7 @@ sub DESTROY {
         Geo::GDALc::delete_RasterAttributeTable($self);
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
     if ($code) {
         Geo::GDAL::VSIStdoutUnsetRedirection();
         $code->close;
@@ -982,6 +988,53 @@ package Geo::GDAL;
 *TermProgress = *Geo::GDALc::TermProgress;
 
 
+    # keeper maintains child -> parent relationships
+    # child is kept as a key, i.e., string not the real object 
+    # parent is kept as the value, i.e., a real object
+    # a child may have only one parent!
+    # call these as Geo::GDAL::*
+
+    my %keeper;
+    my %notes;
+
+    sub note {
+        my ($object, $note) = @_;
+        if (defined wantarray) {
+            return unless $note{$object};
+            return $notes{$object}{$note};
+        }
+        $notes{$object}{$note} = 1;
+    }
+
+    sub unnote {
+        my ($object, $note) = @_;
+        if ($note) {
+            delete $notes{$object}{$note};
+        } else {
+            delete $notes{$object};
+        }
+    }
+
+    sub keep {
+        my ($child, $parent) = @_;
+        $keeper{tied(%$child)} = $parent;
+        return $child;
+    }
+
+    # this is called from RELEASE_PARENT, so the child is already the tied one
+    sub unkeep {
+        my ($child) = @_;
+        delete $keeper{$child};
+    }
+    
+    sub parent {
+        my ($child) = @_;
+        $child = tied(%$child) if $child->isa('HASH');
+        return $keeper{$child};
+    }
+
+
+
 package Geo::GDAL;
 require 5.10.0; # we use //=
 use strict;
@@ -990,8 +1043,7 @@ use Carp;
 use Encode;
 use Exporter 'import';
 use Geo::GDAL::Const;
-use Geo::OGR;
-use Geo::OSR;
+
 # $VERSION is the Perl module (CPAN) version number, which must be
 # an increasing floating point number.  $GDAL_VERSION is the
 # version number of the GDAL that this module is a part of. It is
@@ -1003,8 +1055,8 @@ use Geo::OSR;
 # Note that the 1/100000 digits may be used to create more than one
 # CPAN release from one GDAL release.
 
-our $VERSION = '2.0103';
-our $GDAL_VERSION = '2.1.3';
+our $VERSION = '2.0200';
+our $GDAL_VERSION = '2.2.0';
 
 =pod
 
@@ -1071,15 +1123,22 @@ use Scalar::Util 'blessed';
 use vars qw/
     @EXPORT_OK %EXPORT_TAGS
     @DATA_TYPES @OPEN_FLAGS @RESAMPLING_TYPES @RIO_RESAMPLING_TYPES @NODE_TYPES
-    %TYPE_STRING2INT %TYPE_INT2STRING
-    %OF_STRING2INT
-    %RESAMPLING_STRING2INT %RESAMPLING_INT2STRING
-    %RIO_RESAMPLING_STRING2INT %RIO_RESAMPLING_INT2STRING
-    %NODE_TYPE_STRING2INT %NODE_TYPE_INT2STRING
-    @error %stdout_redirection
+    %S2I %I2S @error %stdout_redirection
     /;
- at EXPORT_OK = qw/Driver Open BuildVRT/;
-%EXPORT_TAGS = (all => [qw(Driver Open BuildVRT)]);
+BEGIN {
+ at EXPORT_OK = qw(
+    Driver Open BuildVRT
+    ParseXMLString NodeData Child Children NodeData ParseXMLString SerializeXMLTree
+    error last_error named_parameters keep unkeep parent note unnote make_processing_options
+    VSIStdoutSetRedirection VSIStdoutUnsetRedirection
+    i2s s2i s_exists);
+%EXPORT_TAGS = (
+    all => [qw(Driver Open BuildVRT)],
+    XML => [qw(ParseXMLString NodeData Child Children NodeData ParseXMLString SerializeXMLTree)],
+    INTERNAL => [qw(error last_error named_parameters keep unkeep parent note unnote make_processing_options
+                    VSIStdoutSetRedirection VSIStdoutUnsetRedirection i2s s2i s_exists)]
+    );
+}
 *BuildVRT = *Geo::GDAL::Dataset::BuildVRT;
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
@@ -1091,29 +1150,33 @@ for (keys %Geo::GDAL::Const::) {
 }
 for my $string (@DATA_TYPES) {
     my $int = eval "\$Geo::GDAL::Const::GDT_$string";
-    $TYPE_STRING2INT{$string} = $int;
-    $TYPE_INT2STRING{$int} = $string;
+    $S2I{data_type}{$string} = $int;
+    $I2S{data_type}{$int} = $string;
 }
 for my $string (@OPEN_FLAGS) {
     my $int = eval "\$Geo::GDAL::Const::OF_$string";
-    $OF_STRING2INT{$string} = $int;
+    $S2I{open_flag}{$string} = $int;
 }
 for my $string (@RESAMPLING_TYPES) {
     my $int = eval "\$Geo::GDAL::Const::GRA_$string";
-    $RESAMPLING_STRING2INT{$string} = $int;
-    $RESAMPLING_INT2STRING{$int} = $string;
+    $S2I{resampling}{$string} = $int;
+    $I2S{resampling}{$int} = $string;
 }
 for my $string (@RIO_RESAMPLING_TYPES) {
     my $int = eval "\$Geo::GDAL::Const::GRIORA_$string";
-    $RIO_RESAMPLING_STRING2INT{$string} = $int;
-    $RIO_RESAMPLING_INT2STRING{$int} = $string;
+    $S2I{rio_resampling}{$string} = $int;
+    $I2S{rio_resampling}{$int} = $string;
 }
 for my $string (@NODE_TYPES) {
     my $int = eval "\$Geo::GDAL::Const::CXT_$string";
-    $NODE_TYPE_STRING2INT{$string} = $int;
-    $NODE_TYPE_INT2STRING{$int} = $string;
+    $S2I{node_type}{$string} = $int;
+    $I2S{node_type}{$int} = $string;
 }
 
+our $HAVE_PDL;
+eval 'require PDL';
+$HAVE_PDL = 1 unless $@;
+
 sub error {
     if (@_) {
         my $error;
@@ -1141,7 +1204,17 @@ sub error {
 }
 
 sub last_error {
-    my $error = $error[$#error] // '';
+    my $error;
+    # all errors should be in @error
+    if (@error) {
+        $error = $error[$#error];
+    } elsif ($@) {
+        # swig exceptions are not in @error
+        $error = $@;
+        $error =~ s/ at .*//;
+    } else {
+        $error = 'unknown error';
+    }
     chomp($error);
     return $error;
 }
@@ -1192,16 +1265,60 @@ sub named_parameters {
     return \%named;
 }
 
-sub string2int {
-    my ($string, $string2int_hash, $int2string_hash, $default) = @_;
+sub i2s {
+    my ($class, $int) = @_;
+    return $I2S{$class}{$int} if exists $I2S{$class}{$int};
+    return $int;
+}
+
+sub s2i {
+    my ($class, $string, $backwards, $default) = @_;
     $string = $default if defined $default && !defined $string;
     return unless defined $string;
-    return $string if $int2string_hash && exists $int2string_hash->{$string};
-    error(1, $string, $string2int_hash) unless exists $string2int_hash->{$string};
-    $string2int_hash->{$string};
+    return $string if $backwards && exists $I2S{$class}{$string};
+    error(1, $string, $S2I{$class}) unless exists $S2I{$class}{$string};
+    $S2I{$class}{$string};
 }
 
-sub RELEASE_PARENTS {
+sub s_exists {
+    my ($class, $string) = @_;
+    return exists $S2I{$class}{$string};
+}
+
+sub make_processing_options {
+    my ($o) = @_;
+    my @options;
+    my $processor = sub {
+        my $val = shift;
+        if (ref $val eq 'ARRAY') {
+            return @$val;
+        } elsif (not ref $val) {
+            if ($val =~ /\s/ && $val =~ /^[+\-0-9.,% ]+$/) {
+                return split /\s+/, $val;
+            }
+            return $val;
+        } else {
+            error("'$val' is not a valid processing option.");
+        }
+    };
+    if (ref $o eq 'HASH') {
+        for my $key (keys %$o) {
+            my $val = $o->{$key};
+            # without hyphen is deprecated
+            $key = '-'.$key unless $key =~ /^-/;
+            push @options, $key;
+            push @options, $processor->($val);
+        }
+    } elsif (ref $o eq 'ARRAY') {
+        for my $item (@$o) {
+            push @options, $processor->($item);
+        }
+    }
+    $o = \@options;
+    return $o;
+}
+
+sub RELEASE_PARENT {
 }
 
 sub FindFile {
@@ -1234,13 +1351,13 @@ sub NodeTypes {
 
 sub NodeType {
     my $type = shift;
-    return $NODE_TYPE_INT2STRING{$type} if $type =~ /^\d/;
-    return $NODE_TYPE_STRING2INT{$type};
+    return i2s(node_type => $type) if $type =~ /^\d/;
+    return s2i(node_type => $type);
 }
 
 sub NodeData {
     my $node = shift;
-    return (Geo::GDAL::NodeType($node->[0]), $node->[1]);
+    return (NodeType($node->[0]), $node->[1]);
 }
 
 sub Children {
@@ -1254,12 +1371,12 @@ sub Child {
 }
 
 sub GetDataTypeSize {
-    return _GetDataTypeSize(string2int(shift, \%TYPE_STRING2INT, \%TYPE_INT2STRING));
+    return _GetDataTypeSize(s2i(data_type => shift, 1));
 }
 
 sub DataTypeValueRange {
     my $t = shift;
-    Geo::GDAL::error(1, $t, \%TYPE_STRING2INT) unless exists $TYPE_STRING2INT{$t};
+    s2i(data_type => $t);
     # these values are from gdalrasterband.cpp
     return (0,255) if $t =~ /Byte/;
     return (0,65535) if $t =~/UInt16/;
@@ -1271,13 +1388,13 @@ sub DataTypeValueRange {
 }
 
 sub DataTypeIsComplex {
-    return _DataTypeIsComplex(string2int(shift, \%TYPE_STRING2INT));
+    return _DataTypeIsComplex(s2i(data_type => shift));
 }
 
 sub PackCharacter {
     my $t = shift;
-    $t = $TYPE_INT2STRING{$t} if exists $TYPE_INT2STRING{$t};
-    Geo::GDAL::error(1, $t, \%TYPE_STRING2INT) unless exists $TYPE_STRING2INT{$t};
+    $t = i2s(data_type => $t);
+    s2i(data_type => $t); # test
     my $is_big_endian = unpack("h*", pack("s", 1)) =~ /01/; # from Programming Perl
     return 'C' if $t =~ /^Byte$/;
     return ($is_big_endian ? 'n': 'v') if $t =~ /^UInt16$/;
@@ -1309,7 +1426,11 @@ sub Drivers {
 
 sub Driver {
     return 'Geo::GDAL::Driver' unless @_;
-    return GetDriver(@_);
+    my $name = shift;
+    my $driver = GetDriver($name);
+    error("Driver \"$name\" not found. Is it built in? Check with Geo::GDAL::Drivers or Geo::OGR::Drivers.") 
+        unless $driver;
+    return $driver;
 }
 
 sub AccessTypes {
@@ -1317,13 +1438,13 @@ sub AccessTypes {
 }
 
 sub Open {
-    my $p = Geo::GDAL::named_parameters(\@_, Name => '.', Access => 'ReadOnly', Type => 'Any', Options => {}, Files => []);
+    my $p = named_parameters(\@_, Name => '.', Access => 'ReadOnly', Type => 'Any', Options => {}, Files => []);
     my @flags;
     my %o = (READONLY => 1, UPDATE => 1);
-    Geo::GDAL::error(1, $p->{access}, \%o) unless $o{uc($p->{access})};
+    error(1, $p->{access}, \%o) unless $o{uc($p->{access})};
     push @flags, uc($p->{access});
     %o = (RASTER => 1, VECTOR => 1, ANY => 1);
-    Geo::GDAL::error(1, $p->{type}, \%o) unless $o{uc($p->{type})};
+    error(1, $p->{type}, \%o) unless $o{uc($p->{type})};
     push @flags, uc($p->{type}) unless uc($p->{type}) eq 'ANY';
     my $dataset = OpenEx(Name => $p->{name}, Flags => \@flags, Options => $p->{options}, Files => $p->{files});
     unless ($dataset) {
@@ -1338,7 +1459,7 @@ sub OpenShared {
     my @p = @_; # name, update
     my @flags = qw/RASTER SHARED/;
     $p[1] //= 'ReadOnly';
-    Geo::GDAL::error(1, $p[1], {ReadOnly => 1, Update => 1}) unless ($p[1] eq 'ReadOnly' or $p[1] eq 'Update');
+    error(1, $p[1], {ReadOnly => 1, Update => 1}) unless ($p[1] eq 'ReadOnly' or $p[1] eq 'Update');
     push @flags, qw/READONLY/ if $p[1] eq 'ReadOnly';
     push @flags, qw/UPDATE/ if $p[1] eq 'Update';
     my $dataset = OpenEx($p[0], \@flags);
@@ -1347,7 +1468,7 @@ sub OpenShared {
 }
 
 sub OpenEx {
-    my $p = Geo::GDAL::named_parameters(\@_, Name => '.', Flags => [], Drivers => [], Options => {}, Files => []);
+    my $p = named_parameters(\@_, Name => '.', Flags => [], Drivers => [], Options => {}, Files => []);
     unless ($p) {
         my $name = shift // '';
         my @flags = @_;
@@ -1356,8 +1477,7 @@ sub OpenEx {
     if ($p->{flags}) {
         my $f = 0;
         for my $flag (@{$p->{flags}}) {
-            Geo::GDAL::error(1, $flag, \%OF_STRING2INT) unless exists $OF_STRING2INT{$flag};
-            $f |= $Geo::GDAL::OF_STRING2INT{$flag};
+            $f |= s2i(open_flag => $flag);
         }
         $p->{flags} = $f;
     }
@@ -1384,7 +1504,7 @@ sub RegenerateOverview {
 
 sub ReprojectImage {
     my @p = @_;
-    $p[4] = string2int($p[4], \%RESAMPLING_STRING2INT);
+    $p[4] = s2i(resampling => $p[4]);
     return _ReprojectImage(@p);
 }
 
@@ -1395,24 +1515,10 @@ sub AutoCreateWarpedVRT {
             $p[$i] = $p[$i]->ExportToWkt;
         }
     }
-    $p[3] = string2int($p[3], \%RESAMPLING_STRING2INT, undef, 'NearestNeighbour');
+    $p[3] = s2i(resampling => $p[3], undef, 'NearestNeighbour');
     return _AutoCreateWarpedVRT(@p);
 }
 
-sub make_processing_options {
-    my ($o) = @_;
-    if (ref $o eq 'HASH') {
-        for my $key (keys %$o) {
-            unless ($key =~ /^-/) {
-                $o->{'-'.$key} = $o->{$key};
-                delete $o->{$key};
-            }
-        }
-        $o = [%$o];
-    }
-    return $o;
-}
-
 
 
 
@@ -1448,6 +1554,8 @@ use warnings;
 use Carp;
 use Scalar::Util 'blessed';
 
+Geo::GDAL->import(qw(:XML :INTERNAL));
+
 use vars qw/@CAPABILITIES @DOMAINS/;
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
@@ -1484,7 +1592,20 @@ sub TestCapability {
 sub Extension {
     my $self = shift;
     my $h = $self->GetMetadata;
-    return $h->{DMD_EXTENSION};
+    if (wantarray) {
+        my $e = $h->{DMD_EXTENSIONS};
+        my @e = split / /, $e;
+        @e = split /\//, $e if $e =~ /\//; # ILWIS returns mpr/mpl
+        for my $i (0..$#e) {
+            $e[$i] =~ s/^\.//; # CALS returns extensions with a dot prefix
+        }
+        return @e;
+    } else {
+        my $e = $h->{DMD_EXTENSION};
+        return '' if $e =~ /\//; # ILWIS returns mpr/mpl
+        $e =~ s/^\.//;
+        return $e;
+    }
 }
 
 sub MIMEType {
@@ -1498,14 +1619,14 @@ sub CreationOptionList {
     my @options;
     my $h = $self->GetMetadata->{DMD_CREATIONOPTIONLIST};
     if ($h) {
-        $h = Geo::GDAL::ParseXMLString($h);
-        my($type, $value) = Geo::GDAL::NodeData($h);
+        $h = ParseXMLString($h);
+        my($type, $value) = NodeData($h);
         if ($value eq 'CreationOptionList') {
-            for my $o (Geo::GDAL::Children($h)) {
+            for my $o (Children($h)) {
                 my %option;
-                for my $a (Geo::GDAL::Children($o)) {
-                    my(undef, $key) = Geo::GDAL::NodeData($a);
-                    my(undef, $value) = Geo::GDAL::NodeData(Geo::GDAL::Child($a, 0));
+                for my $a (Children($o)) {
+                    my(undef, $key) = NodeData($a);
+                    my(undef, $value) = NodeData(Child($a, 0));
                     if ($key eq 'Value') {
                         push @{$option{$key}}, $value;
                     } else {
@@ -1531,7 +1652,7 @@ sub stdout_redirection_wrapper {
     if ($name && blessed $name) {
         $object = $name;
         my $ref = $object->can('write');
-        Geo::GDAL::VSIStdoutSetRedirection($ref);
+        VSIStdoutSetRedirection($ref);
         $name = '/vsistdout/';
     }
     my $ds;
@@ -1542,19 +1663,19 @@ sub stdout_redirection_wrapper {
         if ($ds) {
             $Geo::GDAL::stdout_redirection{tied(%$ds)} = $object;
         } else {
-            Geo::GDAL::VSIStdoutUnsetRedirection();
+            VSIStdoutUnsetRedirection();
             $object->close;
         }
     }
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
     confess("Failed. Use Geo::OGR::Driver for vector drivers.") unless $ds;
     return $ds;
 }
 
 sub Create {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Name => 'unnamed', Width => 256, Height => 256, Bands => 1, Type => 'Byte', Options => {});
-    my $type = Geo::GDAL::string2int($p->{type}, \%Geo::GDAL::TYPE_STRING2INT);
+    my $p = named_parameters(\@_, Name => 'unnamed', Width => 256, Height => 256, Bands => 1, Type => 'Byte', Options => {});
+    my $type = s2i(data_type => $p->{type});
     return $self->stdout_redirection_wrapper(
         $p->{name},
         $self->can('_Create'),
@@ -1565,7 +1686,7 @@ sub Create {
 
 sub Copy {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Name => 'unnamed', Src => undef, Strict => 1, Options => {}, Progress => undef, ProgressData => undef);
+    my $p = named_parameters(\@_, Name => 'unnamed', Src => undef, Strict => 1, Options => {}, Progress => undef, ProgressData => undef);
     return $self->stdout_redirection_wrapper(
         $p->{name},
         $self->can('_CreateCopy'),
@@ -1579,8 +1700,8 @@ sub Open {
     my @flags = qw/RASTER/;
     push @flags, qw/READONLY/ if $p[1] eq 'ReadOnly';
     push @flags, qw/UPDATE/ if $p[1] eq 'Update';
-    my $dataset = Geo::GDAL::OpenEx($p[0], \@flags, [$self->Name()]);
-    Geo::GDAL::error("Failed to open $p[0]. Is it a raster dataset?") unless $dataset;
+    my $dataset = OpenEx($p[0], \@flags, [$self->Name()]);
+    error("Failed to open $p[0]. Is it a raster dataset?") unless $dataset;
     return $dataset;
 }
 
@@ -1595,18 +1716,23 @@ use Scalar::Util 'blessed';
 use Carp;
 use Exporter 'import';
 
-use vars qw/@EXPORT @DOMAINS @CAPABILITIES %CAPABILITIES %BANDS %LAYERS %RESULT_SET/;
+Geo::GDAL->import(qw(:INTERNAL));
+
+use vars qw/@EXPORT @DOMAINS @CAPABILITIES %CAPABILITIES/;
+ 
 @EXPORT = qw/BuildVRT/;
 @DOMAINS = qw/IMAGE_STRUCTURE SUBDATASETS GEOLOCATION/;
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $BANDS{$self};
+    unkeep($self);
 }
 
+*Driver = *GetDriver;
+
 sub Dataset {
     my $self = shift;
-    return $BANDS{tied(%$self)};
+    parent($self);
 }
 
 sub Domains {
@@ -1638,16 +1764,15 @@ sub GetRasterBand {
     my ($self, $index) = @_;
     $index //= 1;
     my $band = _GetRasterBand($self, $index);
-    Geo::GDAL::error(2, $index, 'Band') unless $band;
-    $BANDS{tied(%{$band})} = $self;
-    return $band;
+    error(2, $index, 'Band') unless $band;
+    keep($band, $self);
 }
 *Band = *GetRasterBand;
 
 sub AddBand {
     my ($self, $type, $options) = @_;
     $type //= 'Byte';
-    $type = Geo::GDAL::string2int($type, \%Geo::GDAL::TYPE_STRING2INT);
+    $type = s2i(data_type => $type);
     $self->_AddBand($type, $options);
     return unless defined wantarray;
     return $self->GetRasterBand($self->{RasterCount});
@@ -1660,9 +1785,8 @@ sub CreateMaskBand {
 sub ExecuteSQL {
     my $self = shift;
     my $layer = $self->_ExecuteSQL(@_);
-    $LAYERS{tied(%$layer)} = $self;
-    $RESULT_SET{tied(%$layer)} = 1;
-    return $layer;
+    note($layer, "is result set");
+    keep($layer, $self);
 }
 
 sub ReleaseResultSet {
@@ -1673,9 +1797,8 @@ sub GetLayer {
     my($self, $name) = @_;
     my $layer = defined $name ? GetLayerByName($self, "$name") : GetLayerByIndex($self, 0);
     $name //= '';
-    Geo::GDAL::error(2, $name, 'Layer') unless $layer;
-    $LAYERS{tied(%$layer)} = $self;
-    return $layer;
+    error(2, $name, 'Layer') unless $layer;
+    keep($layer, $self);
 }
 *Layer = *GetLayer;
 
@@ -1692,15 +1815,15 @@ sub GetLayerNames {
 
 sub CreateLayer {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        Name => 'unnamed',
-                                        SRS => undef,
-                                        GeometryType => 'Unknown',
-                                        Options => {},
-                                        Schema => undef,
-                                        Fields => undef,
-                                        ApproxOK => 1);
-    Geo::GDAL::error("The 'Fields' argument must be an array reference.") if $p->{fields} && ref($p->{fields}) ne 'ARRAY';
+    my $p = named_parameters(\@_,
+                             Name => 'unnamed',
+                             SRS => undef,
+                             GeometryType => 'Unknown',
+                             Options => {},
+                             Schema => undef,
+                             Fields => undef,
+                             ApproxOK => 1);
+    error("The 'Fields' argument must be an array reference.") if $p->{fields} && ref($p->{fields}) ne 'ARRAY';
     if (defined $p->{schema}) {
         my $s = $p->{schema};
         $p->{geometrytype} = $s->{GeometryType} if exists $s->{GeometryType};
@@ -1710,18 +1833,18 @@ sub CreateLayer {
     $p->{fields} = [] unless ref($p->{fields}) eq 'ARRAY';
     # if fields contains spatial fields, then do not create default one
     for my $f (@{$p->{fields}}) {
-        if ($f->{GeometryType} or exists $Geo::OGR::Geometry::TYPE_STRING2INT{$f->{Type}}) {
+        error("Field definitions must be hash references.") unless ref $f eq 'HASH';
+        if ($f->{GeometryType} || ($f->{Type} && s_exists(geometry_type => $f->{Type}))) {
             $p->{geometrytype} = 'None';
             last;
         }
     }
-    my $gt = Geo::GDAL::string2int($p->{geometrytype}, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+    my $gt = s2i(geometry_type => $p->{geometrytype});
     my $layer = _CreateLayer($self, $p->{name}, $p->{srs}, $gt, $p->{options});
-    $LAYERS{tied(%$layer)} = $self;
     for my $f (@{$p->{fields}}) {
         $layer->CreateField($f);
     }
-    return $layer;
+    keep($layer, $self);
 }
 
 sub DeleteLayer {
@@ -1731,7 +1854,7 @@ sub DeleteLayer {
         my $layer = GetLayerByIndex($self, $i);
         $index = $i, last if $layer->GetName eq $name;
     }
-    Geo::GDAL::error(2, $name, 'Layer') unless defined $index;
+    error(2, $name, 'Layer') unless defined $index;
     _DeleteLayer($self, $index);
 }
 
@@ -1760,7 +1883,7 @@ sub GeoTransform {
             SetGeoTransform($self, \@_);
         }
     };
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
     return unless defined wantarray;
     my $t = GetGeoTransform($self);
     if (wantarray) {
@@ -1772,24 +1895,40 @@ sub GeoTransform {
 
 sub Extent {
     my $self = shift;
-    return $self->GeoTransform->Extent($self->Size);
+    my $t = $self->GeoTransform;
+    my $extent = $t->Extent($self->Size);
+    if (@_) {
+        my ($xoff, $yoff, $w, $h) = @_;
+        my ($x, $y) = $t->Apply([$xoff, $xoff+$w, $xoff+$w, $xoff], [$yoff, $yoff, $yoff+$h, $yoff+$h]);
+        my $xmin = shift @$x;
+        my $xmax = $xmin;
+        for my $x (@$x) {
+            $xmin = $x if $x < $xmin;
+            $xmax = $x if $x > $xmax;
+        }
+        my $ymin = shift @$y;
+        my $ymax = $ymin;
+        for my $y (@$y) {
+            $ymin = $y if $y < $ymin;
+            $ymax = $y if $y > $ymax;
+        }
+        $extent = Geo::GDAL::Extent->new($xmin, $ymin, $xmax, $ymax);
+    }
+    return $extent;
 }
 
 sub Tile { # $xoff, $yoff, $xsize, $ysize, assuming strict north up
     my ($self, $e) = @_;
     my ($w, $h) = $self->Size;
-    #print "sz $w $h\n";
-    my $gt = $self->GeoTransform;
-    #print "gt @$gt\n";
-    confess "GeoTransform is not \"north up\"." unless $gt->NorthUp;
-    my $x = $gt->Extent($w, $h);
-    my $xoff = floor(($e->[0] - $gt->[0])/$gt->[1]);
+    my $t = $self->GeoTransform;
+    confess "GeoTransform is not \"north up\"." unless $t->NorthUp;
+    my $xoff = floor(($e->[0] - $t->[0])/$t->[1]);
     $xoff = 0 if $xoff < 0;
-    my $yoff = floor(($gt->[3] - $e->[3])/(-$gt->[5]));
+    my $yoff = floor(($e->[1] - $t->[3])/$t->[5]);
     $yoff = 0 if $yoff < 0;
-    my $xsize = ceil(($e->[2] - $gt->[0])/$gt->[1]) - $xoff;
+    my $xsize = ceil(($e->[2] - $t->[0])/$t->[1]) - $xoff;
     $xsize = $w - $xoff if $xsize > $w - $xoff;
-    my $ysize = ceil(($gt->[3] - $e->[1])/(-$gt->[5])) - $yoff;
+    my $ysize = ceil(($e->[3] - $t->[3])/$t->[5]) - $yoff;
     $ysize = $h - $yoff if $ysize > $h - $yoff;
     return ($xoff, $yoff, $xsize, $ysize);
 }
@@ -1829,24 +1968,24 @@ sub ReadRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->Band->DataType;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        XOff => 0,
-                                        YOff => 0,
-                                        XSize => $width,
-                                        YSize => $height,
-                                        BufXSize => undef,
-                                        BufYSize => undef,
-                                        BufType => $type,
-                                        BandList => [1],
-                                        BufPixelSpace => 0,
-                                        BufLineSpace => 0,
-                                        BufBandSpace => 0,
-                                        ResampleAlg => 'NearestNeighbour',
-                                        Progress => undef,
-                                        ProgressData => undef
+    my $p = named_parameters(\@_,
+                             XOff => 0,
+                             YOff => 0,
+                             XSize => $width,
+                             YSize => $height,
+                             BufXSize => undef,
+                             BufYSize => undef,
+                             BufType => $type,
+                             BandList => [1],
+                             BufPixelSpace => 0,
+                             BufLineSpace => 0,
+                             BufBandSpace => 0,
+                             ResampleAlg => 'NearestNeighbour',
+                             Progress => undef,
+                             ProgressData => undef
         );
-    $p->{resamplealg} = Geo::GDAL::string2int($p->{resamplealg}, \%Geo::GDAL::RIO_RESAMPLING_STRING2INT);
-    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $p->{resamplealg} = s2i(rio_resampling => $p->{resamplealg});
+    $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
     $self->_ReadRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bandlist},$p->{bufpixelspace},$p->{buflinespace},$p->{bufbandspace},$p->{resamplealg},$p->{progress},$p->{progressdata});
 }
 
@@ -1854,21 +1993,21 @@ sub WriteRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->Band->DataType;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        XOff => 0,
-                                        YOff => 0,
-                                        XSize => $width,
-                                        YSize => $height,
-                                        Buf => undef,
-                                        BufXSize => undef,
-                                        BufYSize => undef,
-                                        BufType => $type,
-                                        BandList => [1],
-                                        BufPixelSpace => 0,
-                                        BufLineSpace => 0,
-                                        BufBandSpace => 0
+    my $p = named_parameters(\@_,
+                             XOff => 0,
+                             YOff => 0,
+                             XSize => $width,
+                             YSize => $height,
+                             Buf => undef,
+                             BufXSize => undef,
+                             BufYSize => undef,
+                             BufType => $type,
+                             BandList => [1],
+                             BufPixelSpace => 0,
+                             BufLineSpace => 0,
+                             BufBandSpace => 0
         );
-    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
     $self->_WriteRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{buf},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bandlist},$p->{bufpixelspace},$p->{buflinespace},$p->{bufbandspace});
 }
 
@@ -1879,7 +2018,7 @@ sub BuildOverviews {
     eval {
         $self->_BuildOverviews(@p);
     };
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
 }
 
 sub stdout_redirection_wrapper {
@@ -1888,7 +2027,7 @@ sub stdout_redirection_wrapper {
     if ($name && blessed $name) {
         $object = $name;
         my $ref = $object->can('write');
-        Geo::GDAL::VSIStdoutSetRedirection($ref);
+        VSIStdoutSetRedirection($ref);
         $name = '/vsistdout/';
     }
     my $ds;
@@ -1899,17 +2038,17 @@ sub stdout_redirection_wrapper {
         if ($ds) {
             $Geo::GDAL::stdout_redirection{tied(%$ds)} = $object;
         } else {
-            Geo::GDAL::VSIStdoutUnsetRedirection();
+            VSIStdoutUnsetRedirection();
             $object->close;
         }
     }
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
     return $ds;
 }
 
 sub DEMProcessing {
     my ($self, $dest, $Processing, $ColorFilename, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALDEMProcessingOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALDEMProcessingOptions->new(make_processing_options($options));
     return $self->stdout_redirection_wrapper(
         $dest,
         \&Geo::GDAL::wrapper_GDALDEMProcessing,
@@ -1919,7 +2058,7 @@ sub DEMProcessing {
 
 sub Nearblack {
     my ($self, $dest, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALNearblackOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALNearblackOptions->new(make_processing_options($options));
     my $b = blessed($dest);
     if ($b && $b eq 'Geo::GDAL::Dataset') {
         Geo::GDAL::wrapper_GDALNearblackDestDS($dest, $self, $options, $progress, $progress_data);
@@ -1940,10 +2079,10 @@ sub Translate {
             my ($dest, $self) = @_;
             my $ds;
             if ($self->_GetRasterBand(1)) {
-                $options = Geo::GDAL::GDALTranslateOptions->new(Geo::GDAL::make_processing_options($options));
+                $options = Geo::GDAL::GDALTranslateOptions->new(make_processing_options($options));
                 $ds = Geo::GDAL::wrapper_GDALTranslate($dest, $self, $options, $progress, $progress_data);
             } else {
-                $options = Geo::GDAL::GDALVectorTranslateOptions->new(Geo::GDAL::make_processing_options($options));
+                $options = Geo::GDAL::GDALVectorTranslateOptions->new(make_processing_options($options));
                 Geo::GDAL::wrapper_GDALVectorTranslateDestDS($dest, $self, $options, $progress, $progress_data);
                 $ds = Geo::GDAL::wrapper_GDALVectorTranslateDestName($dest, $self, $options, $progress, $progress_data);
             }
@@ -1954,20 +2093,19 @@ sub Translate {
 
 sub Warped {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, SrcSRS => undef, DstSRS => undef, ResampleAlg => 'NearestNeighbour', MaxError => 0);
+    my $p = named_parameters(\@_, SrcSRS => undef, DstSRS => undef, ResampleAlg => 'NearestNeighbour', MaxError => 0);
     for my $srs (qw/srcsrs dstsrs/) {
         $p->{$srs} = $p->{$srs}->ExportToWkt if $p->{$srs} && blessed $p->{$srs};
     }
-    $p->{resamplealg} = Geo::GDAL::string2int($p->{resamplealg}, \%Geo::GDAL::RESAMPLING_STRING2INT);
+    $p->{resamplealg} = s2i(resampling => $p->{resamplealg});
     my $warped = Geo::GDAL::_AutoCreateWarpedVRT($self, $p->{srcsrs}, $p->{dstsrs}, $p->{resamplealg}, $p->{maxerror});
-    $BANDS{tied(%{$warped})} = $self if $warped; # self must live as long as warped
-    return $warped;
+    keep($warped, $self) if $warped; # self must live as long as warped
 }
 
 sub Warp {
     my ($self, $dest, $options, $progress, $progress_data) = @_;
     # can be run as object method (one dataset) and as package sub (a list of datasets)
-    $options = Geo::GDAL::GDALWarpAppOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALWarpAppOptions->new(make_processing_options($options));
     my $b = blessed($dest);
     $self = [$self] unless ref $self eq 'ARRAY';
     if ($b && $b eq 'Geo::GDAL::Dataset') {
@@ -1984,13 +2122,13 @@ sub Warp {
 
 sub Info {
     my ($self, $o) = @_;
-    $o = Geo::GDAL::GDALInfoOptions->new(Geo::GDAL::make_processing_options($o));
-    return Geo::GDAL::GDALInfo($self, $o);
+    $o = Geo::GDAL::GDALInfoOptions->new(make_processing_options($o));
+    return GDALInfo($self, $o);
 }
 
 sub Grid {
     my ($self, $dest, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALGridOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALGridOptions->new(make_processing_options($options));
     return $self->stdout_redirection_wrapper(
         $dest,
         \&Geo::GDAL::wrapper_GDALGrid,
@@ -2000,11 +2138,12 @@ sub Grid {
 
 sub Rasterize {
     my ($self, $dest, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALRasterizeOptions->new(Geo::GDAL::make_processing_options($options));
+    $options = Geo::GDAL::GDALRasterizeOptions->new(make_processing_options($options));
     my $b = blessed($dest);
     if ($b && $b eq 'Geo::GDAL::Dataset') {
         Geo::GDAL::wrapper_GDALRasterizeDestDS($dest, $self, $options, $progress, $progress_data);
     } else {
+        # TODO: options need to force a new raster be made, otherwise segfault
         return $self->stdout_redirection_wrapper(
             $dest,
             \&Geo::GDAL::wrapper_GDALRasterizeDestName,
@@ -2015,8 +2154,8 @@ sub Rasterize {
 
 sub BuildVRT {
     my ($dest, $sources, $options, $progress, $progress_data) = @_;
-    $options = Geo::GDAL::GDALBuildVRTOptions->new(Geo::GDAL::make_processing_options($options));
-    Geo::GDAL::error("Usage: Geo::GDAL::DataSet::BuildVRT(\$vrt_file_name, \\\@sources)")
+    $options = Geo::GDAL::GDALBuildVRTOptions->new(make_processing_options($options));
+    error("Usage: Geo::GDAL::DataSet::BuildVRT(\$vrt_file_name, \\\@sources)")
         unless ref $sources eq 'ARRAY' && defined $sources->[0];
     unless (blessed($dest)) {
         if (blessed($sources->[0])) {
@@ -2041,14 +2180,14 @@ sub BuildVRT {
 
 sub ComputeColorTable {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        Red => undef,
-                                        Green => undef,
-                                        Blue => undef,
-                                        NumColors => 256,
-                                        Progress => undef,
-                                        ProgressData => undef,
-                                        Method => 'MedianCut');
+    my $p = named_parameters(\@_,
+                             Red => undef,
+                             Green => undef,
+                             Blue => undef,
+                             NumColors => 256,
+                             Progress => undef,
+                             ProgressData => undef,
+                             Method => 'MedianCut');
     for my $b ($self->Bands) {
         for my $cion ($b->ColorInterpretation) {
             if ($cion eq 'RedBand') { $p->{red} //= $b; last; }
@@ -2068,14 +2207,14 @@ sub ComputeColorTable {
 
 sub Dither {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        Red => undef,
-                                        Green => undef,
-                                        Blue => undef,
-                                        Dest => undef,
-                                        ColorTable => undef,
-                                        Progress => undef,
-                                        ProgressData => undef);
+    my $p = named_parameters(\@_,
+                             Red => undef,
+                             Green => undef,
+                             Blue => undef,
+                             Dest => undef,
+                             ColorTable => undef,
+                             Progress => undef,
+                             ProgressData => undef);
     for my $b ($self->Bands) {
         for my $cion ($b->ColorInterpretation) {
             if ($cion eq 'RedBand') { $p->{red} //= $b; last; }
@@ -2116,22 +2255,53 @@ use POSIX;
 use Carp;
 use Scalar::Util 'blessed';
 
-use vars qw/ %RATS
-    @COLOR_INTERPRETATIONS
-    %COLOR_INTERPRETATION_STRING2INT %COLOR_INTERPRETATION_INT2STRING @DOMAINS
-    %MASK_FLAGS
+Geo::GDAL->import(qw(:INTERNAL));
+
+use vars qw/
+    @COLOR_INTERPRETATIONS @DOMAINS
+    %MASK_FLAGS %DATATYPE2PDL %PDL2DATATYPE
     /;
+
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
     push(@COLOR_INTERPRETATIONS, $1), next if /^GCI_(\w+)/;
 }
 for my $string (@COLOR_INTERPRETATIONS) {
     my $int = eval "\$Geo::GDAL::Constc::GCI_$string";
-    $COLOR_INTERPRETATION_STRING2INT{$string} = $int;
-    $COLOR_INTERPRETATION_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{color_interpretation}{$string} = $int;
+    $Geo::GDAL::I2S{color_interpretation}{$int} = $string;
 }
 @DOMAINS = qw/IMAGE_STRUCTURE RESAMPLING/;
 %MASK_FLAGS = (AllValid => 1, PerDataset => 2, Alpha => 4, NoData => 8);
+if ($Geo::GDAL::HAVE_PDL) {
+    require PDL;
+    require PDL::Types;
+    %DATATYPE2PDL = (
+        $Geo::GDAL::Const::GDT_Byte => $PDL::Types::PDL_B,
+        $Geo::GDAL::Const::GDT_Int16 => $PDL::Types::PDL_S,
+        $Geo::GDAL::Const::GDT_UInt16 => $PDL::Types::PDL_US,
+        $Geo::GDAL::Const::GDT_Int32 => $PDL::Types::PDL_L,
+        $Geo::GDAL::Const::GDT_UInt32 => -1,
+        #$PDL_IND,
+        #$PDL_LL,
+        $Geo::GDAL::Const::GDT_Float32 => $PDL::Types::PDL_F,
+        $Geo::GDAL::Const::GDT_Float64 => $PDL::Types::PDL_D,
+        $Geo::GDAL::Const::GDT_CInt16 => -1,
+        $Geo::GDAL::Const::GDT_CInt32 => -1,
+        $Geo::GDAL::Const::GDT_CFloat32 => -1,
+        $Geo::GDAL::Const::GDT_CFloat64 => -1
+        );
+    %PDL2DATATYPE = (
+        $PDL::Types::PDL_B => $Geo::GDAL::Const::GDT_Byte,
+        $PDL::Types::PDL_S => $Geo::GDAL::Const::GDT_Int16,
+        $PDL::Types::PDL_US => $Geo::GDAL::Const::GDT_UInt16,
+        $PDL::Types::PDL_L  => $Geo::GDAL::Const::GDT_Int32,
+        $PDL::Types::PDL_IND  => -1,
+        $PDL::Types::PDL_LL  => -1,
+        $PDL::Types::PDL_F  => $Geo::GDAL::Const::GDT_Float32,
+        $PDL::Types::PDL_D => $Geo::GDAL::Const::GDT_Float64
+        );
+}
 
 sub Domains {
     return @DOMAINS;
@@ -2157,27 +2327,28 @@ sub DESTROY {
     if (exists $OWNER{$self}) {
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::GDAL::Dataset::BANDS{$self};
+    unkeep($self);
 }
 
 sub Dataset {
     my $self = shift;
-    return $Geo::GDAL::Dataset::BANDS{tied(%{$self})};
+    parent($self);
 }
 
 sub Size {
     my $self = shift;
     return ($self->{XSize}, $self->{YSize});
 }
+*BlockSize = *GetBlockSize;
 
 sub DataType {
     my $self = shift;
-    return $Geo::GDAL::TYPE_INT2STRING{$self->{DataType}};
+    return i2s(data_type => $self->{DataType});
 }
 
 sub PackCharacter {
@@ -2227,8 +2398,8 @@ sub ReadTile {
     $w_tile //= $xsize;
     $h_tile //= $ysize;
     $alg //= 'NearestNeighbour';
+    $alg = s2i(rio_resampling => $alg);
     my $t = $self->{DataType};
-    $alg = Geo::GDAL::string2int($alg, \%Geo::GDAL::RIO_RESAMPLING_STRING2INT);
     my $buf = $self->_ReadRaster($xoff, $yoff, $xsize, $ysize, $w_tile, $h_tile, $t, 0, 0, $alg);
     my $pc = Geo::GDAL::PackCharacter($t);
     my $w = $w_tile * Geo::GDAL::GetDataTypeSize($t)/8;
@@ -2246,6 +2417,7 @@ sub WriteTile {
     my($self, $data, $xoff, $yoff) = @_;
     $xoff //= 0;
     $yoff //= 0;
+    error('The data must be in a two-dimensional array') unless ref $data eq 'ARRAY' && ref $data->[0] eq 'ARRAY';
     my $xsize = @{$data->[0]};
     if ($xsize > $self->{XSize} - $xoff) {
         warn "Buffer XSize too large ($xsize) for this raster band (width = $self->{XSize}, offset = $xoff).";
@@ -2266,11 +2438,11 @@ sub WriteTile {
 sub ColorInterpretation {
     my($self, $ci) = @_;
     if (defined $ci) {
-        $ci = Geo::GDAL::string2int($ci, \%COLOR_INTERPRETATION_STRING2INT);
+        $ci = s2i(color_interpretation => $ci);
         SetRasterColorInterpretation($self, $ci);
     }
     return unless defined wantarray;
-    $COLOR_INTERPRETATION_INT2STRING{GetRasterColorInterpretation($self)};
+    i2s(color_interpretation => GetRasterColorInterpretation($self));
 }
 
 sub ColorTable {
@@ -2293,21 +2465,20 @@ sub AttributeTable {
     SetDefaultRAT($self, $_[0]) if @_ and defined $_[0];
     return unless defined wantarray;
     my $r = GetDefaultRAT($self);
-    $RATS{tied(%$r)} = $self if $r;
-    return $r;
+    keep($r, $self) if $r;
 }
 *RasterAttributeTable = *AttributeTable;
 
 sub GetHistogram {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        Min => -0.5,
-                                        Max => 255.5,
-                                        Buckets => 256,
-                                        IncludeOutOfRange => 0,
-                                        ApproxOK => 0,
-                                        Progress => undef,
-                                        ProgressData => undef);
+    my $p = named_parameters(\@_,
+                             Min => -0.5,
+                             Max => 255.5,
+                             Buckets => 256,
+                             IncludeOutOfRange => 0,
+                             ApproxOK => 0,
+                             Progress => undef,
+                             ProgressData => undef);
     $p->{progressdata} = 1 if $p->{progress} and not defined $p->{progressdata};
     _GetHistogram($self, $p->{min}, $p->{max}, $p->{buckets},
                   $p->{includeoutofrange}, $p->{approxok},
@@ -2316,17 +2487,17 @@ sub GetHistogram {
 
 sub Contours {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        DataSource => undef,
-                                        LayerConstructor => {Name => 'contours'},
-                                        ContourInterval => 100,
-                                        ContourBase => 0,
-                                        FixedLevels => [],
-                                        NoDataValue => undef,
-                                        IDField => -1,
-                                        ElevField => -1,
-                                        Progress => undef,
-                                        ProgressData => undef);
+    my $p = named_parameters(\@_,
+                             DataSource => undef,
+                             LayerConstructor => {Name => 'contours'},
+                             ContourInterval => 100,
+                             ContourBase => 0,
+                             FixedLevels => [],
+                             NoDataValue => undef,
+                             IDField => -1,
+                             ElevField => -1,
+                             Progress => undef,
+                             ProgressData => undef);
     $p->{datasource} //= Geo::OGR::GetDriver('Memory')->CreateDataSource('ds');
     $p->{layerconstructor}->{Schema} //= {};
     $p->{layerconstructor}->{Schema}{Fields} //= [];
@@ -2366,22 +2537,22 @@ sub ReadRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->DataType;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        XOff => 0,
-                                        YOff => 0,
-                                        XSize => $width,
-                                        YSize => $height,
-                                        BufXSize => undef,
-                                        BufYSize => undef,
-                                        BufType => $type,
-                                        BufPixelSpace => 0,
-                                        BufLineSpace => 0,
-                                        ResampleAlg => 'NearestNeighbour',
-                                        Progress => undef,
-                                        ProgressData => undef
+    my $p = named_parameters(\@_,
+                             XOff => 0,
+                             YOff => 0,
+                             XSize => $width,
+                             YSize => $height,
+                             BufXSize => undef,
+                             BufYSize => undef,
+                             BufType => $type,
+                             BufPixelSpace => 0,
+                             BufLineSpace => 0,
+                             ResampleAlg => 'NearestNeighbour',
+                             Progress => undef,
+                             ProgressData => undef
         );
-    $p->{resamplealg} = Geo::GDAL::string2int($p->{resamplealg}, \%Geo::GDAL::RIO_RESAMPLING_STRING2INT);
-    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $p->{resamplealg} = s2i(rio_resampling => $p->{resamplealg});
+    $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
     $self->_ReadRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bufpixelspace},$p->{buflinespace},$p->{resamplealg},$p->{progress},$p->{progressdata});
 }
 
@@ -2389,20 +2560,20 @@ sub WriteRaster {
     my $self = shift;
     my ($width, $height) = $self->Size;
     my ($type) = $self->DataType;
-    my $p = Geo::GDAL::named_parameters(\@_,
-                                        XOff => 0,
-                                        YOff => 0,
-                                        XSize => $width,
-                                        YSize => $height,
-                                        Buf => undef,
-                                        BufXSize => undef,
-                                        BufYSize => undef,
-                                        BufType => $type,
-                                        BufPixelSpace => 0,
-                                        BufLineSpace => 0
+    my $p = named_parameters(\@_,
+                             XOff => 0,
+                             YOff => 0,
+                             XSize => $width,
+                             YSize => $height,
+                             Buf => undef,
+                             BufXSize => undef,
+                             BufYSize => undef,
+                             BufType => $type,
+                             BufPixelSpace => 0,
+                             BufLineSpace => 0
         );
     confess "Usage: \$band->WriteRaster( Buf => \$data, ... )" unless defined $p->{buf};
-    $p->{buftype} = Geo::GDAL::string2int($p->{buftype}, \%Geo::GDAL::TYPE_STRING2INT, \%Geo::GDAL::TYPE_INT2STRING);
+    $p->{buftype} = s2i(data_type => $p->{buftype}, 1);
     $self->_WriteRaster($p->{xoff},$p->{yoff},$p->{xsize},$p->{ysize},$p->{buf},$p->{bufxsize},$p->{bufysize},$p->{buftype},$p->{bufpixelspace},$p->{buflinespace});
 }
 
@@ -2431,46 +2602,66 @@ sub CreateMaskBand {
 }
 
 sub Piddle {
-    my $self = shift; # should use named parameters for read raster and band
-    # add Piddle sub to dataset too to make N x M x n piddles
-    my ($w, $h) = $self->Size;
-    my $data = $self->ReadRaster;
+    # TODO: add Piddle sub to dataset too to make Width x Height x Bands piddles
+    error("PDL is not available.") unless $Geo::GDAL::HAVE_PDL;
+    my $self = shift;
+    my $t = $self->{DataType};
+    unless (defined wantarray) {
+        my $pdl = shift;
+        error("The datatype of the Piddle and the band do not match.") 
+          unless $PDL2DATATYPE{$pdl->get_datatype} == $t;
+        my ($xoff, $yoff, $xsize, $ysize) = @_;
+        $xoff //= 0;
+        $yoff //= 0;
+        my $data = $pdl->get_dataref();
+        my ($xdim, $ydim) = $pdl->dims();
+        if ($xdim > $self->{XSize} - $xoff) {
+            warn "Piddle XSize too large ($xdim) for this raster band (width = $self->{XSize}, offset = $xoff).";
+            $xdim = $self->{XSize} - $xoff;
+        }
+        if ($ydim > $self->{YSize} - $yoff) {
+            $ydim = $self->{YSize} - $yoff;
+            warn "Piddle YSize too large ($ydim) for this raster band (height = $self->{YSize}, offset = $yoff).";
+        }
+        $xsize //= $xdim;
+        $ysize //= $ydim;
+        $self->_WriteRaster($xoff, $yoff, $xsize, $ysize, $data, $xdim, $ydim, $t, 0, 0);
+        return;
+    }
+    my ($xoff, $yoff, $xsize, $ysize, $xdim, $ydim, $alg) = @_;
+    $xoff //= 0;
+    $yoff //= 0;
+    $xsize //= $self->{XSize} - $xoff;
+    $ysize //= $self->{YSize} - $yoff;
+    $xdim //= $xsize;
+    $ydim //= $ysize;
+    $alg //= 'NearestNeighbour';
+    $alg = s2i(rio_resampling => $alg);
+    my $buf = $self->_ReadRaster($xoff, $yoff, $xsize, $ysize, $xdim, $ydim, $t, 0, 0, $alg);
     my $pdl = PDL->new;
-    my %map = (
-        Byte => 0,
-        UInt16 => 2,
-        Int16 => 1,
-        UInt32 => -1,
-        Int32 => 3,
-        Float32 => 5,
-        Float64 => 6,
-        CInt16 => -1,
-        CInt32 => -1,
-        CFloat32 => -1,
-        CFloat64 => -1
-        );
-    my $datatype = $map{$self->DataType};
-    croak "there is no direct mapping between the band datatype and PDL" if $datatype < 0;
+    my $datatype = $DATATYPE2PDL{$t};
+    error("The band datatype is not supported by PDL.") if $datatype < 0;
     $pdl->set_datatype($datatype);
-    $pdl->setdims([1,$w,$h]);
-    my $dref = $pdl->get_dataref();
-    $$dref = $data;
+    $pdl->setdims([$xdim, $ydim]);
+    my $data = $pdl->get_dataref();
+    $$data = $buf;
     $pdl->upd_data;
+    # FIXME: we want approximate equality since no data value can be very large floating point value
+    my $bad = GetNoDataValue($self);
+    return $pdl->setbadif($pdl == $bad) if defined $bad;
     return $pdl;
 }
 
 sub GetMaskBand {
     my $self = shift;
     my $band = _GetMaskBand($self);
-    $Geo::GDAL::Dataset::BANDS{tied(%{$band})} = $self;
-    return $band;
+    keep($band, $self);
 }
 
 sub GetOverview {
     my ($self, $index) = @_;
     my $band = _GetOverview($self, $index);
-    $Geo::GDAL::Dataset::BANDS{tied(%{$band})} = $self;
-    return $band;
+    keep($band, $self);
 }
 
 sub RegenerateOverview {
@@ -2489,7 +2680,12 @@ sub RegenerateOverviews {
 
 sub Polygonize {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Mask => undef, OutLayer => undef, PixValField => 'val', Options => undef, Progress => undef, ProgressData => undef);
+    my $p = named_parameters(\@_, Mask => undef, OutLayer => undef, PixValField => 'val', Options => undef, Progress => undef, ProgressData => undef);
+    my %known_options = (Connectedness => 1, ForceIntPixel => 1, DATASET_FOR_GEOREF => 1, '8CONNECTED' => 1);
+    for my $option (keys %{$p->{options}}) {
+        error(1, $option, \%known_options) unless exists $known_options{$option};
+    }
+
     my $dt = $self->DataType;
     my %leInt32 = (Byte => 1, Int16 => 1, Int32 => 1, UInt16 => 1);
     my $leInt32 = $leInt32{$dt};
@@ -2499,7 +2695,7 @@ sub Polygonize {
                     Fields => [{Name => 'val', Type => $dt},
                                {Name => 'geom', Type => 'Polygon'}]);
     $p->{pixvalfield} = $p->{outlayer}->GetLayerDefn->GetFieldIndex($p->{pixvalfield});
-    $p->{options}{'8CONNECTED'} = $p->{options}{Connectedness} if $p->{options}{Connectedness};
+    $p->{options}{'8CONNECTED'} = 1 if $p->{options}{Connectedness} && $p->{options}{Connectedness} == 8;
     if ($leInt32 || $p->{options}{ForceIntPixel}) {
         Geo::GDAL::_Polygonize($self, $p->{mask}, $p->{outlayer}, $p->{pixvalfield}, $p->{options}, $p->{progress}, $p->{progressdata});
     } else {
@@ -2511,7 +2707,7 @@ sub Polygonize {
 
 sub Sieve {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Mask => undef, Dest => undef, Threshold => 10, Options => undef, Progress => undef, ProgressData => undef);
+    my $p = named_parameters(\@_, Mask => undef, Dest => undef, Threshold => 10, Options => undef, Progress => undef, ProgressData => undef);
     unless ($p->{dest}) {
         my ($w, $h) = $self->Size;
         $p->{dest} = Geo::GDAL::Driver('MEM')->Create(Name => 'sieved', Width => $w, Height => $h, Type => $self->DataType)->Band;
@@ -2527,7 +2723,7 @@ sub Sieve {
 
 sub Distance {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Distance => undef, Options => undef, Progress => undef, ProgressData => undef);
+    my $p = named_parameters(\@_, Distance => undef, Options => undef, Progress => undef, ProgressData => undef);
     for my $key (keys %{$p->{options}}) {
         $p->{options}{uc($key)} = $p->{options}{$key};
     }
@@ -2548,18 +2744,19 @@ use strict;
 use warnings;
 use Carp;
 
-use vars qw/%PALETTE_INTERPRETATION_STRING2INT %PALETTE_INTERPRETATION_INT2STRING/;
+Geo::GDAL->import(qw(:INTERNAL));
+
 for (keys %Geo::GDAL::Const::) {
     if (/^GPI_(\w+)/) {
         my $int = eval "\$Geo::GDAL::Const::GPI_$1";
-        $PALETTE_INTERPRETATION_STRING2INT{$1} = $int;
-        $PALETTE_INTERPRETATION_INT2STRING{$int} = $1;
+        $Geo::GDAL::S2I{palette_interpretation}{$1} = $int;
+        $Geo::GDAL::I2S{palette_interpretation}{$int} = $1;
     }
 }
 
 sub GetPaletteInterpretation {
     my $self = shift;
-    return $PALETTE_INTERPRETATION_INT2STRING{GetPaletteInterpretation($self)};
+    return i2s(palette_interpretation => GetPaletteInterpretation($self));
 }
 
 sub SetColorEntry {
@@ -2574,7 +2771,7 @@ sub SetColorEntry {
     eval {
         $self->_SetColorEntry($index, $color);
     };
-    confess(Geo::GDAL->last_error) if $@;
+    confess(last_error()) if $@;
 }
 
 sub ColorEntry {
@@ -2613,11 +2810,9 @@ use strict;
 use warnings;
 use Carp;
 
-use vars qw/
-    @FIELD_TYPES @FIELD_USAGES
-    %FIELD_TYPE_STRING2INT %FIELD_TYPE_INT2STRING
-    %FIELD_USAGE_STRING2INT %FIELD_USAGE_INT2STRING
-    /;
+Geo::GDAL->import(qw(:INTERNAL));
+
+use vars qw(@FIELD_TYPES @FIELD_USAGES);
 for (keys %Geo::GDAL::Const::) {
     next if /TypeCount/;
     push(@FIELD_TYPES, $1), next if /^GFT_(\w+)/;
@@ -2625,13 +2820,13 @@ for (keys %Geo::GDAL::Const::) {
 }
 for my $string (@FIELD_TYPES) {
     my $int = eval "\$Geo::GDAL::Constc::GFT_$string";
-    $FIELD_TYPE_STRING2INT{$string} = $int;
-    $FIELD_TYPE_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{rat_field_type}{$string} = $int;
+    $Geo::GDAL::I2S{rat_field_type}{$int} = $string;
 }
 for my $string (@FIELD_USAGES) {
     my $int = eval "\$Geo::GDAL::Constc::GFU_$string";
-    $FIELD_USAGE_STRING2INT{$string} = $int;
-    $FIELD_USAGE_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{rat_field_usage}{$string} = $int;
+    $Geo::GDAL::I2S{rat_field_usage}{$int} = $string;
 }
 
 sub FieldTypes {
@@ -2642,29 +2837,29 @@ sub FieldUsages {
     return @FIELD_USAGES;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::GDAL::Band::RATS{$self};
+    unkeep($self);
 }
 
 sub Band {
     my $self = shift;
-    return $Geo::GDAL::Band::RATS{tied(%$self)};
+    parent($self);
 }
 
 sub GetUsageOfCol {
     my($self, $col) = @_;
-    $FIELD_USAGE_INT2STRING{_GetUsageOfCol($self, $col)};
+    i2s(rat_field_usage => _GetUsageOfCol($self, $col));
 }
 
 sub GetColOfUsage {
     my($self, $usage) = @_;
-    _GetColOfUsage($self, $FIELD_USAGE_STRING2INT{$usage});
+    _GetColOfUsage($self, s2i(rat_field_usage => $usage));
 }
 
 sub GetTypeOfCol {
     my($self, $col) = @_;
-    $FIELD_TYPE_INT2STRING{_GetTypeOfCol($self, $col)};
+    i2s(rat_field_type => _GetTypeOfCol($self, $col));
 }
 
 sub Columns {
@@ -2690,8 +2885,8 @@ sub CreateColumn {
     for my $color (qw/Red Green Blue Alpha/) {
         carp "RAT column type will be 'Integer' for usage '$color'." if $usage eq $color and $type ne 'Integer';
     }
-    $type = Geo::GDAL::string2int($type, \%FIELD_TYPE_STRING2INT);
-    $usage = Geo::GDAL::string2int($usage, \%FIELD_USAGE_STRING2INT);
+    $type = s2i(rat_field_type => $type);
+    $usage = s2i(rat_field_usage => $usage);
     _CreateColumn($self, $name, $type, $usage);
 }
 
@@ -2720,7 +2915,7 @@ package Geo::GDAL::GCP;
 *swig_Line_get = *Geo::GDALc::GCP_Row_get;
 *swig_Line_set = *Geo::GDALc::GCP_Row_set;
 
-
+Geo::GDAL->import(qw(:INTERNAL));
 
 package Geo::GDAL::VSIF;
 use strict;
@@ -2732,6 +2927,8 @@ our @ISA = qw(Exporter);
 our @EXPORT_OK   = qw(Open Close Write Read Seek Tell Truncate MkDir ReadDir ReadDirRecursive Rename RmDir Stat Unlink);
 our %EXPORT_TAGS = (all => \@EXPORT_OK);
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub Open {
     my ($path, $mode) = @_;
     my $self = Geo::GDAL::VSIFOpenL($path, $mode);
@@ -2811,7 +3008,7 @@ sub RmDir {
     };
     if ($@) {
         my $r = $recursive ? ' recursively' : '';
-        Geo::GDAL::error("Cannot remove directory \"$dirname\"$r.");
+        error("Cannot remove directory \"$dirname\"$r.");
     }
 }
 *Rmdir = *RmDir;
@@ -2835,19 +3032,29 @@ use warnings;
 use Carp;
 use Scalar::Util 'blessed';
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub new {
     my $class = shift;
     my $self;
     if (@_ == 0) {
         $self = [0,1,0,0,0,1];
-    } elsif (@_ == 1) {
-        $self = $_[0];
+    } elsif (ref $_[0]) {
+        @$self = @{$_[0]};
+    } elsif ($_[0] =~ /^[a-zA-Z]/i) {
+        my $p = named_parameters(\@_, GCPs => undef, ApproxOK => 1, Extent => undef, CellSize => 1);
+        if ($p->{gcps}) {
+            $self = Geo::GDAL::GCPsToGeoTransform($p->{gcps}, $p->{approxok});
+        } elsif ($p->{extent}) {
+            $self = Geo::GDAL::GeoTransform->new($p->{extent}[0], $p->{cellsize}, 0, $p->{extent}[2], 0, -$p->{cellsize});
+        } else {
+            error("Missing GCPs or Extent");
+        }
     } else {
         my @a = @_;
         $self = \@a;
     }
     bless $self, $class;
-    return $self;
 }
 
 sub NorthUp {
@@ -2868,7 +3075,7 @@ sub FromGCPs {
         }
     }
     my $approx_ok = shift // 1;
-    Geo::GDAL::error('Usage: Geo::GDAL::GeoTransform::FromGCPs(\@gcps, $approx_ok)') unless @$gcps;
+    error('Usage: Geo::GDAL::GeoTransform::FromGCPs(\@gcps, $approx_ok)') unless @$gcps;
     my $self = Geo::GDAL::GCPsToGeoTransform($gcps, $approx_ok);
     bless $self, 'Geo::GDAL::GetTransform';
     return $self;
@@ -2876,6 +3083,7 @@ sub FromGCPs {
 
 sub Apply {
     my ($self, $columns, $rows) = @_;
+    return Geo::GDAL::ApplyGeoTransform($self, $columns, $rows) unless ref($columns) eq 'ARRAY';
     my (@x, @y);
     for my $i (0..$#$columns) {
         ($x[$i], $y[$i]) =
@@ -2887,7 +3095,7 @@ sub Apply {
 sub Inv {
     my $self = shift;
     my @inv = Geo::GDAL::InvGeoTransform($self);
-    return new(@inv) if defined wantarray;
+    return Geo::GDAL::GeoTransform->new(@inv) if defined wantarray;
     @$self = @inv;
 }
 
@@ -2912,11 +3120,13 @@ use warnings;
 use Carp;
 use Scalar::Util 'blessed';
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub new {
     my $class = shift;
     my $self;
     if (@_ == 0) {
-        $self = [0,0,0,0];
+        $self = [0,0,-1,0];
     } elsif (ref $_[0]) {
         @$self = @{$_[0]};
     } else {
@@ -2926,8 +3136,14 @@ sub new {
     return $self;
 }
 
+sub IsEmpty {
+    my $self = shift;
+    return $self->[2] < $self->[0];
+}
+
 sub Size {
     my $self = shift;
+    return (0,0) if $self->IsEmpty;
     return ($self->[2] - $self->[0], $self->[3] - $self->[1]);
 }
 
@@ -2938,7 +3154,7 @@ sub Overlaps {
 
 sub Overlap {
     my ($self, $e) = @_;
-    return undef unless $self->Overlaps($e);
+    return Geo::GDAL::Extent->new() unless $self->Overlaps($e);
     my $ret = Geo::GDAL::Extent->new($self);
     $ret->[0] = $e->[0] if $self->[0] < $e->[0];
     $ret->[1] = $e->[1] if $self->[1] < $e->[1];
@@ -2949,10 +3165,15 @@ sub Overlap {
 
 sub ExpandToInclude {
     my ($self, $e) = @_;
-    $self->[0] = $e->[0] if $e->[0] < $self->[0];
-    $self->[1] = $e->[1] if $e->[1] < $self->[1];
-    $self->[2] = $e->[2] if $e->[2] > $self->[2];
-    $self->[3] = $e->[3] if $e->[3] > $self->[3];
+    return if $e->IsEmpty;
+    if ($self->IsEmpty) {
+        @$self = @$e;
+    } else {
+        $self->[0] = $e->[0] if $e->[0] < $self->[0];
+        $self->[1] = $e->[1] if $e->[1] < $self->[1];
+        $self->[2] = $e->[2] if $e->[2] > $self->[2];
+        $self->[3] = $e->[3] if $e->[3] > $self->[3];
+    }
 }
 
 package Geo::GDAL::XML;
@@ -2961,6 +3182,8 @@ use strict;
 use warnings;
 use Carp;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 # XML related subs in Geo::GDAL
 
 #Geo::GDAL::Child
@@ -2974,7 +3197,7 @@ use Carp;
 sub new {
     my $class = shift;
     my $xml = shift // '';
-    my $self = Geo::GDAL::ParseXMLString($xml);
+    my $self = ParseXMLString($xml);
     bless $self, $class;
     $self->traverse(sub {my $node = shift; bless $node, $class});
     return $self;
@@ -2984,7 +3207,7 @@ sub traverse {
     my ($self, $sub) = @_;
     my $type = $self->[0];
     my $data = $self->[1];
-    $type = Geo::GDAL::NodeType($type);
+    $type = NodeType($type);
     $sub->($self, $type, $data);
     for my $child (@{$self}[2..$#$self]) {
         traverse($child, $sub);
@@ -2993,7 +3216,7 @@ sub traverse {
 
 sub serialize {
     my $self = shift;
-    return Geo::GDAL::SerializeXMLTree($self);
+    return SerializeXMLTree($self);
 }
 
 1;
diff --git a/swig/perl/lib/Geo/GDAL/Const.pm b/swig/perl/lib/Geo/GDAL/Const.pm
index 1f3a039..677a954 100644
--- a/swig/perl/lib/Geo/GDAL/Const.pm
+++ b/swig/perl/lib/Geo/GDAL/Const.pm
@@ -185,6 +185,9 @@ package Geo::GDAL::Const;
 *GMF_PER_DATASET = *Geo::GDAL::Constc::GMF_PER_DATASET;
 *GMF_ALPHA = *Geo::GDAL::Constc::GMF_ALPHA;
 *GMF_NODATA = *Geo::GDAL::Constc::GMF_NODATA;
+*GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED = *Geo::GDAL::Constc::GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED;
+*GDAL_DATA_COVERAGE_STATUS_DATA = *Geo::GDAL::Constc::GDAL_DATA_COVERAGE_STATUS_DATA;
+*GDAL_DATA_COVERAGE_STATUS_EMPTY = *Geo::GDAL::Constc::GDAL_DATA_COVERAGE_STATUS_EMPTY;
 *GARIO_PENDING = *Geo::GDAL::Constc::GARIO_PENDING;
 *GARIO_UPDATE = *Geo::GDAL::Constc::GARIO_UPDATE;
 *GARIO_ERROR = *Geo::GDAL::Constc::GARIO_ERROR;
diff --git a/swig/perl/lib/Geo/GNM.dox b/swig/perl/lib/Geo/GNM.dox
index de019ef..80d4d23 100644
--- a/swig/perl/lib/Geo/GNM.dox
+++ b/swig/perl/lib/Geo/GNM.dox
@@ -1,14 +1,18 @@
 ## @class Geo::GNM
 # @brief Base class for geographical networks in GDAL.
+# @details
 
 
 ## @class Geo::GNM::MajorObject
 # @isa (Geo::GNM)
+# @details
 
 
 ## @class Geo::GNM::Network
 # @isa (Geo::GNM::MajorObject Geo::GNM)
+# @details
 
 
 ## @class Geo::GNM::GenericNetwork
-# @isa ( Geo::GNM::Network Geo::GNM )
\ No newline at end of file
+# @isa ( Geo::GNM::Network Geo::GNM )
+# @details
diff --git a/swig/perl/lib/Geo/GNM.pm b/swig/perl/lib/Geo/GNM.pm
index d56df90..eb10e68 100644
--- a/swig/perl/lib/Geo/GNM.pm
+++ b/swig/perl/lib/Geo/GNM.pm
@@ -7,6 +7,9 @@
 package Geo::GNM;
 use base qw(Exporter);
 use base qw(DynaLoader);
+require Geo::OGR;
+require Geo::OSR;
+require Geo::GDAL;
 package Geo::GNMc;
 bootstrap Geo::GNM;
 package Geo::GNM;
@@ -52,38 +55,11 @@ package Geo::GNM;
 *CastToNetwork = *Geo::GNMc::CastToNetwork;
 *CastToGenericNetwork = *Geo::GNMc::CastToGenericNetwork;
 
-############# Class : Geo::GNM::MajorObject ##############
-
-package Geo::GNM::MajorObject;
-use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GNM );
-%OWNER = ();
-*GetDescription = *Geo::GNMc::MajorObject_GetDescription;
-*SetDescription = *Geo::GNMc::MajorObject_SetDescription;
-*GetMetadataDomainList = *Geo::GNMc::MajorObject_GetMetadataDomainList;
-*GetMetadata_Dict = *Geo::GNMc::MajorObject_GetMetadata_Dict;
-*GetMetadata_List = *Geo::GNMc::MajorObject_GetMetadata_List;
-*SetMetadata = *Geo::GNMc::MajorObject_SetMetadata;
-*GetMetadataItem = *Geo::GNMc::MajorObject_GetMetadataItem;
-*SetMetadataItem = *Geo::GNMc::MajorObject_SetMetadataItem;
-sub DISOWN {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    delete $OWNER{$ptr};
-}
-
-sub ACQUIRE {
-    my $self = shift;
-    my $ptr = tied(%$self);
-    $OWNER{$ptr} = 1;
-}
-
-
 ############# Class : Geo::GNM::Network ##############
 
 package Geo::GNM::Network;
 use vars qw(@ISA %OWNER %ITERATORS %BLESSEDMEMBERS);
- at ISA = qw( Geo::GNM::MajorObject Geo::GNM );
+ at ISA = qw( Geo::GDAL::MajorObject Geo::GNM );
 %OWNER = ();
 %ITERATORS = ();
 sub DESTROY {
@@ -97,7 +73,7 @@ sub DESTROY {
     }
 }
 
-*ReleaseResultSet = *Geo::GNMc::Network_ReleaseResultSet;
+*_ReleaseResultSet = *Geo::GNMc::Network__ReleaseResultSet;
 *GetVersion = *Geo::GNMc::Network_GetVersion;
 *GetName = *Geo::GNMc::Network_GetName;
 *GetFeatureByGlobalFID = *Geo::GNMc::Network_GetFeatureByGlobalFID;
@@ -106,13 +82,13 @@ sub DESTROY {
 *GetProjection = *Geo::GNMc::Network_GetProjection;
 *GetProjectionRef = *Geo::GNMc::Network_GetProjectionRef;
 *GetFileList = *Geo::GNMc::Network_GetFileList;
-*CreateLayer = *Geo::GNMc::Network_CreateLayer;
+*_CreateLayer = *Geo::GNMc::Network__CreateLayer;
 *CopyLayer = *Geo::GNMc::Network_CopyLayer;
-*DeleteLayer = *Geo::GNMc::Network_DeleteLayer;
+*_DeleteLayer = *Geo::GNMc::Network__DeleteLayer;
 *GetLayerCount = *Geo::GNMc::Network_GetLayerCount;
 *GetLayerByIndex = *Geo::GNMc::Network_GetLayerByIndex;
 *GetLayerByName = *Geo::GNMc::Network_GetLayerByName;
-*TestCapability = *Geo::GNMc::Network_TestCapability;
+*_TestCapability = *Geo::GNMc::Network__TestCapability;
 *StartTransaction = *Geo::GNMc::Network_StartTransaction;
 *CommitTransaction = *Geo::GNMc::Network_CommitTransaction;
 *RollbackTransaction = *Geo::GNMc::Network_RollbackTransaction;
diff --git a/swig/perl/lib/Geo/OGR.dox b/swig/perl/lib/Geo/OGR.dox
index 2166c26..17472d2 100644
--- a/swig/perl/lib/Geo/OGR.dox
+++ b/swig/perl/lib/Geo/OGR.dox
@@ -1,7 +1,6 @@
 ## @class Geo::OGR
 # @brief OGR utility functions.
-#
-# A wrapper for many OGR utility functions and a root class for all
+# @details A wrapper for many OGR utility functions and a root class for all
 # OGR classes.
 
 ## @ignore TermProgress
@@ -65,6 +64,9 @@
 
 ## @sub @DriverNames()
 # A.k.a GetDriverNames
+# \code
+# perl -MGeo::GDAL -e '@d=Geo::OGR::DriverNames;print "@d\n"'
+# \endcode
 # @note Use Geo::GDAL::DriverNames for raster drivers.
 # @return a list of the short names of all available GDAL vector drivers.
 
@@ -90,7 +92,8 @@
 
 
 ## @class Geo::OGR::Driver
-# @brief A vector format driver. This is a legacy class which
+# @brief A vector format driver.
+# @details This is a legacy class which
 # should not be used in new code. Use Geo::GDAL::Driver.
 
 ## @method Open
@@ -99,7 +102,7 @@
 ## @method Geo::GDAL::Dataset Create($name, hashref options = undef )
 # Create a new vector data source using this driver.
 # @param name The data source name.
-# @param options Driver specific dataset creation options. 
+# @param options Driver specific dataset creation options.
 
 ## @method Geo::GDAL::Dataset Copy(Geo::GDAL::Dataset source, $name, arrayref options = undef)
 # Copy a vector data source into a new data source with this driver.
@@ -114,7 +117,8 @@
 
 
 ## @class Geo::OGR::DataSource
-# @brief A vector dataset. This is a legacy class which should not be
+# @brief A vector dataset.
+# @details This is a legacy class which should not be
 # used in new code. Use Geo::GDAL::Dataset.
 
 ## @sub Geo::GDAL::Dataset Open
@@ -128,8 +132,7 @@
 
 ## @class Geo::OGR::Layer
 # @brief A collection of similar features.
-#
-# A layer object is typically obtained with a data source object. A
+# @details A layer object is typically obtained with a data source object. A
 # layer has a data model (a schema), which is maintained in a
 # definition object, and a set of features, which contain data
 # according to the data model. The schema is typically set when the
@@ -140,11 +143,10 @@
 # read, inserted and deleted. Reading can be filtered. Layers can be
 # compared to each other with methods Clip, Erase, Identity,
 # Intersection, SymDifference, Union, and Update.
-# @isa (Geo::OGR)
-#
 # A layer may have metadata OLMD_FID64 => 'YES' if it holds features
 # with 64 bit FIDs. The metadata of a layer can be obtained with
 # GetMetadata method.
+# @isa (Geo::OGR)
 
 ## @method @Capabilities()
 # Both a package subroutine and an object method.
@@ -275,11 +277,15 @@
 
 ## @ignore FindFieldIndex
 
-## @method %GetFieldDefn($name)
+## @method $GetFieldDefn($name)
 # Get the definition of a field.
 # @param name the name of the field.
-# @return the field definition object, either Geo::OGR::FieldDefn or
-# Geo::OGR::GeomFieldDefn.
+# @return a Geo::OGR::FieldDefn object.
+
+## @method $GetGeomFieldDefn($name)
+# Get the definition of a spatial field.
+# @param name the name of the spatial field.
+# @return a Geo::OGR::GeomFieldDefn object.
 
 ## @ignore CreateGeomField
 
@@ -404,6 +410,18 @@
 ## @method $GetName()
 # @return the name of the layer.
 
+## @method Geo::OGR::Feature Feature($f)
+#
+# @param f [optional] feature id, a feature, a row, or a tuple 
+#
+# @note If the argument feature has a null FID (FID not set) the
+# feature is inserted into the layer as a new feature. If the FID is
+# non null, then the feature replaces the feature in the layer with
+# that FID.
+#
+# @return a new Geo::OGR::Feature object that represents the feature
+# in the layer.
+
 ## @method Geo::OGR::Feature GetFeature($fid)
 # @param fid feature id
 # @return a new Geo::OGR::Feature object that represents the feature in the layer.
@@ -415,15 +433,6 @@
 # id. Requires RandomWrite capability.
 # @param feature a Geo::OGR::Feature object
 
-## @method CreateFeature($feature)
-# @deprecated use Geo::OGR::Layer::InsertFeature which accepts Perl
-# data and checks for geometry type and attribute data
-#
-# @note The feature should have the same schema as the layer.
-#
-# Inserts a feature into the layer. The given feature's id may change.
-# @param feature a Geo::OGR::Feature object
-
 ## @method InsertFeature($feature)
 # Creates a new feature which has the schema of the layer and
 # initializes it with data from the argument. Then inserts the feature
@@ -445,7 +454,8 @@
 # A.k.a GetLayerDefn.
 # @return a Geo::OGR::FeatureDefn object.
 
-## @method $GetFeatureCount($force = 1)
+## @method $FeatureCount($force = 1)
+# A.k.a GetFeatureCount
 # @param force
 # @return integer
 
@@ -492,8 +502,7 @@
 
 ## @class Geo::OGR::Feature
 # @brief A collection of non-spatial and spatial attributes.
-#
-# A feature is a collection of non-spatial and spatial attributes and
+# @details A feature is a collection of non-spatial and spatial attributes and
 # an id, which is a special attribute, and data records according to
 # this data model. Attributes are called fields and some fields are
 # spatial, i.e., their value is a geometry. Fields have at least a
@@ -503,14 +512,22 @@
 
 ## @cmethod Geo::OGR::Feature new(%schema)
 # @brief Create a new feature.
-# @param A Geo::OGR::FeatureDefn object or named parameters to create one:
-# - \a Name
+# @param Named parameters:
+# - \a Schema a reference to a schema hash, or a Geo::OGR::Layer,
+#      Geo::OGR::Feature, or Geo::OGR::FeatureDefn object.
+# - \a Values values for the feature attributes.
+# - \a StyleIgnored whether the style can be omitted when fetching
+#      features. (default is false)
+#
+# Schema is a hash with the following keys:
+# - \a Name name of the schema (not used).
 # - \a Fields a list of Geo::OGR::FieldDefn or Geo::OGR::GeomFieldDefn
-# objects or anonymous hashes from which such can be created.
+# objects or references to hashes from which fields can be created.
 # - \a GeometryType the geometry type if the feature has only one spatial field.
-# - \a StyleIgnored whether the style can be omitted when fetching features. (default is false)
 #
 # @note Do not mix GeometryType and geometry fields in Fields list.
+# @note Old syntax where the argument is a Geo::OGR::FeatureDefn
+# object or Schema hash is supported.
 #
 # @return a new Geo::OGR::Feature object.
 
@@ -577,11 +594,15 @@
 ## @ignore GetFieldType
 ## @ignore GetGeomFieldDefnRef
 
-## @method Geo::OGR::FieldDefn GetFieldDefn($name)
-# @note A.k.a GetFieldDefnRef
+## @method $GetFieldDefn($name)
+# Get the definition of a field.
 # @param name the name of the field.
-# @return a new Geo::OGR::FieldDefn object that represents the field
-# in question.
+# @return a Geo::OGR::FieldDefn object.
+
+## @method $GetGeomFieldDefn($name)
+# Get the definition of a spatial field.
+# @param name the name of the spatial field.
+# @return a Geo::OGR::GeomFieldDefn object.
 
 ## @method Geo::OGR::Feature Clone()
 # @return a new Geo::OGR::Feature object
@@ -635,6 +656,8 @@
 # @note Non-scalar fields (for example Date) can be set either from a
 # scalar, which is then assumed to be a string and parsed, or from a
 # list of values (for example year, month, day for Date).
+# @note Setting and getting Integer64 fields requires 'use bigint' if
+# \$Config{ivsize} is smaller than 8, i.e., in a 32 bit machine.
 # @return in non-void context the value of the field, which may be a
 # scalar or a list, depending on the field type. For unset fields the
 # undef value is returned.
@@ -711,8 +734,7 @@
 
 ## @class Geo::OGR::FeatureDefn
 # @brief The schema of a feature or a layer.
-#
-# A FeatureDefn object is a collection of field definition objects. A
+# @details A FeatureDefn object is a collection of field definition objects. A
 # read-only FeatureDefn object can be obtained from a layer
 # (Geo::OGR::Layer::GetDefn()) or a feature
 # (Geo::OGR::Feature::GetDefn()).
@@ -730,7 +752,7 @@
 #
 # Example usage:
 # \code
-# $fd = Geo::OGR::FeatureDefn->new( 
+# $fd = Geo::OGR::FeatureDefn->new(
 #     Name => "name",
 #     Fields => [{ Name => 'field1', Type => 'String' },
 #                { Name => 'geom', GeometryType => 'Point' }] );
@@ -739,7 +761,7 @@
 ## @ignore Schema
 
 ## @method \%GetSchema()
-# @brief Get the schema of this feature or layer definition. 
+# @brief Get the schema of this feature or layer definition.
 #
 # @return the schema as a hash whose keywords are Name, StyleIgnored
 # and Fields. Fields is an anonymous array of first non-spatial and
@@ -762,12 +784,16 @@
 
 ## @ignore GeometryIgnored
 ## @ignore GeometryType
-## @ignore GetGeomFieldDefn
 
-## @method object GetFieldDefn($name)
+## @method $GetFieldDefn($name)
+# Get the definition of a field.
 # @param name the name of the field.
-# @return either a Geo::OGR::FieldDefn or Geo::OGR::GeomFieldDefn
-# object that represents the field in question.
+# @return a Geo::OGR::FieldDefn object.
+
+## @method $GetGeomFieldDefn($name)
+# Get the definition of a spatial field.
+# @param name the name of the spatial field.
+# @return a Geo::OGR::GeomFieldDefn object.
 
 ## @ignore AddFieldDefn
 ## @ignore AddGeomFieldDefn
@@ -834,6 +860,7 @@
 
 ## @class Geo::OGR::FieldDefn
 # @brief A definition of a non-spatial attribute.
+# @details
 # @isa (Geo::OGR)
 
 ## @sub list Types
@@ -853,11 +880,14 @@
 # - \a Type Field type, one of Geo::OGR::FieldDefn::Types (default is 'String').
 # - \a SubType Field sub type, one of Geo::OGR::FieldDefn::SubTypes.
 # - \a Justify Justify value, one of Geo::OGR::FieldDefn::JustifyValues
-# - \a Width 
+# - \a Width
 # - \a Precision
 # - \a Nullable (default is true)
-# - \a Default 
+# - \a Default
 # - \a Ignored (default is false)
+#
+# @note Simplified parameters <name> => <type> is also supported.
+#
 # @return a new Geo::OGR::FieldDefn object
 
 ## @method \%Schema(%params)
@@ -955,6 +985,7 @@
 
 ## @class Geo::OGR::GeomFieldDefn
 # @brief A definition of a spatial attribute.
+# @details
 # @isa (Geo::OGR)
 
 ## @cmethod Geo::OGR::GeomFieldDefn new(%params)
@@ -966,6 +997,9 @@
 # - \a SpatialReference a Geo::OSR::SpatialReference object.
 # - \a Nullable (default is true)
 # - \a Ignored (default is false)
+#
+# @note Simplified parameters <name> => <type> is also supported.
+#
 # @return a new Geo::OGR::GeomFieldDefn object
 
 ## @method \%Schema(%params)
@@ -1020,16 +1054,15 @@
 
 
 ## @class Geo::OGR::Geometry
-# @isa (Geo::OGR)
 # @brief Spatial data.
-#
-# A geometry is spatial data (coordinate values, and a reference to a
+# @details A geometry is spatial data (coordinate values, and a reference to a
 # spatial reference system) organized into one of the geometry
 # types. Geometries can be created from several type of data including
 # a Perl data structure. There are several methods, which modify,
 # compare, test, or compute values from geometries.
 # @note Most spatial analysis methods require <a
 # href="http://geos.osgeo.org/doxygen/">GEOS</a> to work rigorously.
+# @isa (Geo::OGR)
 
 ## @sub @GeometryTypes()
 # Same as Geo::OGR::GeometryTypes
@@ -1056,7 +1089,7 @@
 # @return a new Geo::OGR::Geometry object.
 
 ## @sub Geo::OGR::Geometry ApproximateArcAngles(%params)
-# Create a line string, which approximates an arc. 
+# Create a line string, which approximates an arc.
 # @note All angles are in degrees.
 #
 # @param %params Named parameters:
@@ -1066,7 +1099,7 @@
 # - \a Rotation default is 0.
 # - \a StartAngle default is 0.
 # - \a EndAngle default is 360.
-# - \a MaxAngleStepSizeDegrees default is 4. 
+# - \a MaxAngleStepSizeDegrees default is 4.
 # @return a new Geo::OGR::Geometry object.
 
 ## @method FlattenTo2D()
@@ -1103,7 +1136,7 @@
 # Export the geometry into a known format.
 #
 # @param params Named parameters:
-# - \a Format One of 
+# - \a Format One of
 #     - \a WKT Well Known Text.
 #     - <em>ISO WKT</em>
 #     - \a Text Same as WKT.
@@ -1212,7 +1245,7 @@
 #
 # @param points [optional] A reference to an array. A point is a reference to an
 # array of numbers, a linestring or a ring is a reference to an array of points,
-# a polygon is a reference to an array of rings, etc. 
+# a polygon is a reference to an array of rings, etc.
 #
 # @return A reference to an array.
 
@@ -1352,7 +1385,7 @@
 ## @ignore SymmetricDifference
 
 ## @method Geo::OGR::Geometry SymDifference($other)
-# Compute symmetric difference. 
+# Compute symmetric difference.
 # @note a.k.a. SymmetricDifference
 # @param other a Geo::OGR::Geometry object
 # @return a new Geo::OGR::Geometry object
diff --git a/swig/perl/lib/Geo/OGR.pm b/swig/perl/lib/Geo/OGR.pm
index fbacbf3..549f19d 100644
--- a/swig/perl/lib/Geo/OGR.pm
+++ b/swig/perl/lib/Geo/OGR.pm
@@ -215,7 +215,7 @@ sub DESTROY {
         Geo::OGRc::delete_Feature($self);
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
     if ($code) {
         Geo::GDAL::VSIStdoutUnsetRedirection();
         $code->close;
@@ -226,15 +226,57 @@ sub DESTROY {
 use Carp;
 sub new {
     my $pkg = shift;
-    my $arg = blessed($_[0]);
-    my $defn;
-    if ($arg && $arg eq 'Geo::OGR::FeatureDefn') {
-        $defn = $_[0];
+    my $arg;
+    if (ref $_[0]) {
+        if (ref $_[0] eq 'HASH' && $_[0]->{Schema}) {
+            $arg = $_[0];
+        } else {
+            $arg = {Schema => $_[0]};
+        }
+    } elsif (@_ and @_ % 2 == 0) {
+        %$arg = @_;
+        unless ($arg->{Schema}) {
+            my %tmp = @_;
+            $arg->{Schema} = \%tmp;
+        }
     } else {
-        $defn = Geo::OGR::FeatureDefn->new(@_);
+        error("The argument must be either a schema or a hash.");
+    }
+    error("Missing schema.") unless $arg->{Schema};
+    my $defn;
+    for (ref $arg->{Schema}) {
+        (/Geo::OGR::Layer$/ || /Geo::OGR::Feature$/) && do {
+            $defn = $arg->{Schema}->GetDefn;
+            last;
+        };
+        /Geo::OGR::FeatureDefn$/ && do {
+            $defn = $arg->{Schema};
+            last;
+        };
+        $defn = Geo::OGR::FeatureDefn->new($arg->{Schema});
     }
     my $self = Geo::OGRc::new_Feature($defn);
-    bless $self, $pkg if defined($self);
+    error("Feature creation failed.") unless $self;
+    bless $self, $pkg;
+    for (ref $arg->{Values}) {
+        /ARRAY/  && do {
+            $self->Tuple($arg->{Values});
+            last;
+        };
+        /HASH/ && do {
+            $self->Row($arg->{Values});
+            last;
+        };
+        /Geo::OGR::Feature$/ && do {
+            $self->Tuple($arg->{Values}->Tuple);
+            last;
+        };
+        /^$/ && do {
+            last;
+        };
+        error("Value parameter must be an array, hash, or another feature. Not $_.");
+    }
+    return $self;
 }
 
 *GetDefnRef = *Geo::OGRc::Feature_GetDefnRef;
@@ -261,12 +303,15 @@ sub new {
 *GetFieldAsStringList = *Geo::OGRc::Feature_GetFieldAsStringList;
 *GetFieldAsBinary = *Geo::OGRc::Feature_GetFieldAsBinary;
 *IsFieldSet = *Geo::OGRc::Feature_IsFieldSet;
-*GetFieldIndex = *Geo::OGRc::Feature_GetFieldIndex;
-*GetGeomFieldIndex = *Geo::OGRc::Feature_GetGeomFieldIndex;
+*IsFieldNull = *Geo::OGRc::Feature_IsFieldNull;
+*IsFieldSetAndNotNull = *Geo::OGRc::Feature_IsFieldSetAndNotNull;
+*_GetFieldIndex = *Geo::OGRc::Feature__GetFieldIndex;
+*_GetGeomFieldIndex = *Geo::OGRc::Feature__GetGeomFieldIndex;
 *GetFID = *Geo::OGRc::Feature_GetFID;
 *SetFID = *Geo::OGRc::Feature_SetFID;
 *DumpReadable = *Geo::OGRc::Feature_DumpReadable;
 *_UnsetField = *Geo::OGRc::Feature__UnsetField;
+*SetFieldNull = *Geo::OGRc::Feature_SetFieldNull;
 *SetFieldInteger64 = *Geo::OGRc::Feature_SetFieldInteger64;
 *_SetField = *Geo::OGRc::Feature__SetField;
 *SetFieldIntegerList = *Geo::OGRc::Feature_SetFieldIntegerList;
@@ -319,7 +364,7 @@ sub DESTROY {
         Geo::OGRc::delete_FeatureDefn($self);
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
     if ($code) {
         Geo::GDAL::VSIStdoutUnsetRedirection();
         $code->close;
@@ -340,7 +385,7 @@ sub new {
         %schema = @_;
     }
     my $fields = $schema{Fields};
-    Geo::GDAL::error("The 'Fields' argument must be an array reference.") if $fields and ref($fields) ne 'ARRAY';
+    error("The 'Fields' argument must be an array reference.") if $fields and ref($fields) ne 'ARRAY';
     $schema{Name} //= '';
     my $self = Geo::OGRc::new_FeatureDefn($schema{Name});
     bless $self, $pkg;
@@ -354,7 +399,22 @@ sub new {
     for my $fd (@{$fields}) {
         my $d = $fd;
         if (ref($fd) eq 'HASH') {
-            if ($fd->{GeometryType} or exists $Geo::OGR::Geometry::TYPE_STRING2INT{$fd->{Type}}) {
+
+            # if Name and Type are missing, assume Name => Type
+            if (!(exists $fd->{Name} && exists $fd->{Type})) {
+                for my $key (sort keys %$fd) {
+                    if (s_exists(field_type => $fd->{$key}) ||
+                        s_exists(geometry_type => $fd->{$key}))
+                    {
+                        $fd->{Name} = $key;
+                        $fd->{Type} = $fd->{$key};
+                        delete $fd->{$key};
+                        last;
+                    }
+                }
+            }
+            
+            if ($fd->{GeometryType} or ($fd->{Type} && s_exists(geometry_type => $fd->{Type}))) {
                 $d = Geo::OGR::GeomFieldDefn->new(%$fd);
             } else {
                 $d = Geo::OGR::FieldDefn->new(%$fd);
@@ -363,10 +423,10 @@ sub new {
         if (blessed($d) and $d->isa('Geo::OGR::FieldDefn')) {
             AddFieldDefn($self, $d);
         } elsif (blessed($d) and $d->isa('Geo::OGR::GeomFieldDefn')) {
-            Geo::GDAL::error("Do not mix GeometryType and geometry fields in Fields.") if $gt;
+            error("Do not mix GeometryType and geometry fields in Fields.") if $gt;
             AddGeomFieldDefn($self, $d);
         } else {
-            Geo::GDAL::error("Item in field list does not define a field.");
+            error("Item in field list does not define a field.");
         }
     }
     return $self;
@@ -374,12 +434,12 @@ sub new {
 
 *GetName = *Geo::OGRc::FeatureDefn_GetName;
 *GetFieldCount = *Geo::OGRc::FeatureDefn_GetFieldCount;
-*GetFieldDefn = *Geo::OGRc::FeatureDefn_GetFieldDefn;
-*GetFieldIndex = *Geo::OGRc::FeatureDefn_GetFieldIndex;
+*_GetFieldDefn = *Geo::OGRc::FeatureDefn__GetFieldDefn;
+*_GetFieldIndex = *Geo::OGRc::FeatureDefn__GetFieldIndex;
 *AddFieldDefn = *Geo::OGRc::FeatureDefn_AddFieldDefn;
 *GetGeomFieldCount = *Geo::OGRc::FeatureDefn_GetGeomFieldCount;
-*GetGeomFieldDefn = *Geo::OGRc::FeatureDefn_GetGeomFieldDefn;
-*GetGeomFieldIndex = *Geo::OGRc::FeatureDefn_GetGeomFieldIndex;
+*_GetGeomFieldDefn = *Geo::OGRc::FeatureDefn__GetGeomFieldDefn;
+*_GetGeomFieldIndex = *Geo::OGRc::FeatureDefn__GetGeomFieldIndex;
 *AddGeomFieldDefn = *Geo::OGRc::FeatureDefn_AddGeomFieldDefn;
 *DeleteGeomFieldDefn = *Geo::OGRc::FeatureDefn_DeleteGeomFieldDefn;
 *GetGeomType = *Geo::OGRc::FeatureDefn_GetGeomType;
@@ -423,7 +483,7 @@ sub DESTROY {
         Geo::OGRc::delete_FieldDefn($self);
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
     if ($code) {
         Geo::GDAL::VSIStdoutUnsetRedirection();
         $code->close;
@@ -451,7 +511,7 @@ sub new {
             }
         }
     }
-    $params->{Type} = Geo::GDAL::string2int($params->{Type}, \%Geo::OGR::FieldDefn::TYPE_STRING2INT);
+    $params->{Type} = s2i(field_type => $params->{Type});
     my $self = Geo::OGRc::new_FieldDefn($params->{Name}, $params->{Type});
     bless $self, $pkg;
     delete $params->{Name};
@@ -534,7 +594,7 @@ sub new {
         }
         $params->{Type} //= $tmp->{GeometryType};
     }
-    $params->{Type} = Geo::GDAL::string2int($params->{Type}, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+    $params->{Type} = s2i(geometry_type => $params->{Type});
     my $self = Geo::OGRc::new_GeomFieldDefn($params->{Name}, $params->{Type});
     bless $self, $pkg;
     delete $params->{Name};
@@ -587,7 +647,7 @@ sub DESTROY {
         Geo::OGRc::delete_Geometry($self);
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
     if ($code) {
         Geo::GDAL::VSIStdoutUnsetRedirection();
         $code->close;
@@ -639,14 +699,14 @@ sub new {
     } elsif (defined $json) {
         $self = Geo::OGRc::CreateGeometryFromJson($json);
     } elsif (defined $type) {
-        $type = Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+        $type = s2i(geometry_type => $type);
         $self = Geo::OGRc::new_Geometry($type); # flattens the type
-        $self->Set3D(1) if Geo::OGR::GT_HasZ($type);
-        $self->SetMeasured(1) if Geo::OGR::GT_HasM($type);
+        $self->Set3D(1) if HasZ($type);
+        $self->SetMeasured(1) if HasM($type);
     } elsif (defined $arc) {
         $self = Geo::OGRc::ApproximateArcAngles(@$arc);
     } else {
-        Geo::GDAL::error(1, undef, map {$_=>1} qw/GeometryType WKT WKB HEXEWKB HEXWKB GML GeoJSON Arc/);
+        error(1, undef, map {$_=>1} qw/GeometryType WKT WKB HEXEWKB HEXWKB GML GeoJSON Arc/);
     }
     bless $self, $pkg if defined $self;
     $self->Points($points) if $points;
@@ -700,6 +760,7 @@ sub new {
 *SymDifference = *Geo::OGRc::Geometry_SymDifference;
 *SymmetricDifference = *Geo::OGRc::Geometry_SymmetricDifference;
 *Distance = *Geo::OGRc::Geometry_Distance;
+*Distance3D = *Geo::OGRc::Geometry_Distance3D;
 *Empty = *Geo::OGRc::Geometry_Empty;
 *IsEmpty = *Geo::OGRc::Geometry_IsEmpty;
 *IsValid = *Geo::OGRc::Geometry_IsValid;
@@ -776,6 +837,7 @@ package Geo::OGR;
 *wkbSurface = *Geo::OGRc::wkbSurface;
 *wkbPolyhedralSurface = *Geo::OGRc::wkbPolyhedralSurface;
 *wkbTIN = *Geo::OGRc::wkbTIN;
+*wkbTriangle = *Geo::OGRc::wkbTriangle;
 *wkbNone = *Geo::OGRc::wkbNone;
 *wkbLinearRing = *Geo::OGRc::wkbLinearRing;
 *wkbCircularStringZ = *Geo::OGRc::wkbCircularStringZ;
@@ -787,6 +849,7 @@ package Geo::OGR;
 *wkbSurfaceZ = *Geo::OGRc::wkbSurfaceZ;
 *wkbPolyhedralSurfaceZ = *Geo::OGRc::wkbPolyhedralSurfaceZ;
 *wkbTINZ = *Geo::OGRc::wkbTINZ;
+*wkbTriangleZ = *Geo::OGRc::wkbTriangleZ;
 *wkbPointM = *Geo::OGRc::wkbPointM;
 *wkbLineStringM = *Geo::OGRc::wkbLineStringM;
 *wkbPolygonM = *Geo::OGRc::wkbPolygonM;
@@ -803,6 +866,7 @@ package Geo::OGR;
 *wkbSurfaceM = *Geo::OGRc::wkbSurfaceM;
 *wkbPolyhedralSurfaceM = *Geo::OGRc::wkbPolyhedralSurfaceM;
 *wkbTINM = *Geo::OGRc::wkbTINM;
+*wkbTriangleM = *Geo::OGRc::wkbTriangleM;
 *wkbPointZM = *Geo::OGRc::wkbPointZM;
 *wkbLineStringZM = *Geo::OGRc::wkbLineStringZM;
 *wkbPolygonZM = *Geo::OGRc::wkbPolygonZM;
@@ -819,6 +883,7 @@ package Geo::OGR;
 *wkbSurfaceZM = *Geo::OGRc::wkbSurfaceZM;
 *wkbPolyhedralSurfaceZM = *Geo::OGRc::wkbPolyhedralSurfaceZM;
 *wkbTINZM = *Geo::OGRc::wkbTINZM;
+*wkbTriangleZM = *Geo::OGRc::wkbTriangleZM;
 *wkbPoint25D = *Geo::OGRc::wkbPoint25D;
 *wkbLineString25D = *Geo::OGRc::wkbLineString25D;
 *wkbPolygon25D = *Geo::OGRc::wkbPolygon25D;
@@ -886,6 +951,8 @@ package Geo::OGR;
 *ODsCTransactions = *Geo::OGRc::ODsCTransactions;
 *ODsCEmulatedTransactions = *Geo::OGRc::ODsCEmulatedTransactions;
 *ODsCMeasuredGeometries = *Geo::OGRc::ODsCMeasuredGeometries;
+*ODsCRandomLayerRead = *Geo::OGRc::ODsCRandomLayerRead;
+*ODsCRandomLayerWrite = *Geo::OGRc::ODsCRandomLayerWrite;
 *ODrCCreateDataSource = *Geo::OGRc::ODrCCreateDataSource;
 *ODrCDeleteDataSource = *Geo::OGRc::ODrCDeleteDataSource;
 *OLMD_FID64 = *Geo::OGRc::OLMD_FID64;
@@ -893,7 +960,21 @@ package Geo::OGR;
 
 
 package Geo::OGR;
-our $VERSION = '2.0103'; # this needs to be the same as that in gdal_perl.i
+our $VERSION = '2.0200'; # this needs to be the same as that in gdal_perl.i
+
+Geo::GDAL->import(qw(:INTERNAL));
+
+use vars qw(@EXPORT_OK %EXPORT_TAGS);
+BEGIN {
+ at EXPORT_OK = qw(HasZ HasM Flatten);
+%EXPORT_TAGS = (
+    all => [qw()],
+    INTERNAL => [qw(HasZ HasM Flatten)]
+    );
+}
+*HasZ = *GT_HasZ;
+*HasM = *GT_HasM;
+*Flatten = *GT_Flatten;
 
 sub Driver {
     return 'Geo::GDAL::Driver' unless @_;
@@ -925,7 +1006,7 @@ sub Open {
     my @flags = qw/VECTOR/;
     push @flags, qw/UPDATE/ if $p[1];
     my $dataset = Geo::GDAL::OpenEx($p[0], \@flags);
-    Geo::GDAL::error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
+    error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
     return $dataset;
 }
 
@@ -934,13 +1015,15 @@ sub OpenShared {
     my @flags = qw/VECTOR SHARED/;
     push @flags, qw/UPDATE/ if $p[1];
     my $dataset = Geo::GDAL::OpenEx($p[0], \@flags);
-    Geo::GDAL::error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
+    error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
     return $dataset;
 }
 
 package Geo::OGR::Driver;
 our @ISA = qw/Geo::GDAL::Driver/;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub Create {
     my ($self, $name, $options) = @_; # name, options
     $options //= {};
@@ -960,13 +1043,15 @@ sub Open {
     my @flags = qw/VECTOR/;
     push @flags, qw/UPDATE/ if $p[1];
     my $dataset = Geo::GDAL::OpenEx($p[0], \@flags, [$self->Name()]);
-    Geo::GDAL::error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
+    error("Failed to open $p[0]. Is it a vector dataset?") unless $dataset;
     return $dataset;
 }
 
 
 package Geo::OGR::DataSource;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 *Open = *Geo::OGR::Open;
 *OpenShared = *Geo::OGR::OpenShared;
 
@@ -976,7 +1061,10 @@ use strict;
 use warnings;
 use Carp;
 use Scalar::Util 'blessed';
-use vars qw /@CAPABILITIES %CAPABILITIES %DEFNS %FEATURES/;
+use vars qw /@CAPABILITIES %CAPABILITIES/;
+
+Geo::GDAL->import(qw(:INTERNAL));
+
 for (keys %Geo::OGR::) {
     push(@CAPABILITIES, $1), next if /^OLC(\w+)/;
 }
@@ -992,25 +1080,25 @@ sub DESTROY {
         $self = tied(%{$self});
         return unless defined $self;
     }
-    if ($Geo::GDAL::Dataset::RESULT_SET{$self}) {
-        $Geo::GDAL::Dataset::LAYERS{$self}->_ReleaseResultSet($self);
-        delete $Geo::GDAL::Dataset::RESULT_SET{$self}
+    if (note($self, 'is result set')) {
+        parent($self)->_ReleaseResultSet($self);
+        unnote($self);
     }
     delete $ITERATORS{$self};
     if (exists $OWNER{$self}) {
         delete $OWNER{$self};
     }
-    $self->RELEASE_PARENTS();
+    $self->RELEASE_PARENT;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::GDAL::Dataset::LAYERS{$self};
+    unkeep($self);
 }
 
 sub Dataset {
     my $self = shift;
-    return $Geo::GDAL::Dataset::LAYERS{tied(%$self)};
+    parent($self);
 }
 
 sub Capabilities {
@@ -1030,15 +1118,14 @@ sub TestCapability {
 
 sub GetDataSource {
     my $self = shift;
-    return $Geo::GDAL::Dataset::LAYERS{tied(%$self)};
+    parent($self);
 }
 *DataSource = *GetDataSource;
 
 sub GetDefn {
     my $self = shift;
     my $defn = $self->GetLayerDefn;
-    $DEFNS{tied(%$defn)} = $self;
-    return $defn;
+    keep($defn, $self);
 }
 
 sub CreateField {
@@ -1062,46 +1149,62 @@ sub CreateField {
     } elsif (blessed($_[0]) and $params{Defn}->isa('Geo::OGR::GeomFieldDefn')) {
         $self->CreateGeomField($params{Defn}, $params{ApproxOK});
     } else {
+        # if Name and Type are missing, assume Name => Type
+        if (!(exists $params{Name} && exists $params{Type})) {
+            for my $key (sort keys %params) {
+                if (s_exists(field_type => $params{$key}) ||
+                    s_exists(geometry_type => $params{$key}))
+                {
+                    $params{Name} = $key;
+                    $params{Type} = $params{$key};
+                    delete $params{$key};
+                    last;
+                }
+            }
+        }
         my $a = $params{ApproxOK};
         delete $params{ApproxOK};
         if (exists $params{GeometryType}) {
             $params{Type} = $params{GeometryType};
             delete $params{GeometryType};
         }
-        if (exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$params{Type}}) {
+        if (s_exists(field_type => $params{Type})) {
             my $fd = Geo::OGR::FieldDefn->new(%params);
             _CreateField($self, $fd, $a);
-        } elsif (exists $Geo::OGR::Geometry::TYPE_STRING2INT{$params{Type}}) {
+        } elsif (s_exists(geometry_type => $params{Type})) {
             my $fd = Geo::OGR::GeomFieldDefn->new(%params);
             CreateGeomField($self, $fd, $a);
+        } elsif ($params{Type} ) {
+            error("Invalid field type: $params{Type}.")
+        } elsif ($params{Name} ) {
+            error("Missing type for field: $params{Name}.")
         } else {
-            Geo::GDAL::error("Invalid field type: $params{Type}.")
+            error("Missing name and type for a field.")
         }
     }
 }
 
 sub AlterFieldDefn {
     my $self = shift;
-    my $field = shift;
-    my $index = $self->GetLayerDefn->GetFieldIndex($field);
-    if (blessed($_[0]) and $_[0]->isa('Geo::OGR::FieldDefn')) {
+    my $index = $self->GetLayerDefn->GetFieldIndex(shift // 0);
+    my $param = @_ % 2 == 0 ? {@_} : shift;
+    if (blessed($param) and $param->isa('Geo::OGR::FieldDefn')) {
         _AlterFieldDefn($self, $index, @_);
     } else {
-        my $params = @_ % 2 == 0 ? {@_} : shift;
-        my $definition = Geo::OGR::FieldDefn->new($params);
+        my $definition = Geo::OGR::FieldDefn->new($param);
         my $flags = 0;
-        $flags |= 1 if exists $params->{Name};
-        $flags |= 2 if exists $params->{Type};
-        $flags |= 4 if exists $params->{Width} or exists $params->{Precision};
-        $flags |= 8 if exists $params->{Nullable};
-        $flags |= 16 if exists $params->{Default};
+        $flags |= 1 if exists $param->{Name};
+        $flags |= 2 if exists $param->{Type};
+        $flags |= 4 if exists $param->{Width} or exists $param->{Precision};
+        $flags |= 8 if exists $param->{Nullable};
+        $flags |= 16 if exists $param->{Default};
         _AlterFieldDefn($self, $index, $definition, $flags);
     }
 }
 
 sub DeleteField {
-    my($self, $field) = @_;
-    my $index = $self->GetLayerDefn->GetFieldIndex($field);
+    my ($self, $field) = @_;
+    my $index = $self->GetLayerDefn->GetFieldIndex($field // 0);
     _DeleteField($self, $index);
 }
 
@@ -1163,30 +1266,47 @@ sub SpatialFilter {
     $self->GetSpatialFilter;
 }
 
+*FeatureCount = *GetFeatureCount;
+
 sub InsertFeature {
     my $self = shift;
     my $feature = shift;
-    Geo::GDAL::error("Usage: \$feature->InsertFeature(reference to a hash or array).") unless ref($feature);
-    my $new = Geo::OGR::Feature->new($self->GetDefn);
-    if (ref($feature) eq 'HASH') {
-        $new->Row(%$feature);
-    } elsif (ref($feature) eq 'ARRAY') {
-        $new->Tuple(@$feature);
-    } elsif (blessed($feature) and $feature->isa('Geo::OGR::Feature')) {
-        $new->Row($feature->Row);
-    }
+    error("Usage: \$feature->InsertFeature(reference to a hash or array).") unless ref($feature);
+    my $new = Geo::OGR::Feature->new(Schema => $self, Values => $feature);
     $self->CreateFeature($new);
     return unless defined wantarray;
-    $FEATURES{tied(%$new)} = $self;
-    return $new;
+    keep($new, $self);
 }
 
 sub GetFeature {
     my ($self, $fid) = @_;
     $fid //= 0;
     my $f = $self->_GetFeature($fid);
-    $FEATURES{tied(%$f)} = $self;
-    return $f;
+    error(2, "FID=$fid", '"Feature') unless ref $f eq 'Geo::OGR::Feature';
+    keep($f, $self);
+}
+
+sub Feature {
+    my $self = shift;
+    my $x = shift;
+    return $self->GetFeature($x) unless $x && ref $x;
+    # Insert or Set depending on the FID
+    my $fid;
+    if (ref $x eq 'ARRAY') {
+        # FID is the first item in the array
+        $fid = $x->[0];
+    } elsif (ref $x eq 'HASH') {
+        # FID is FID
+        $fid = $x->{FID};
+    } else {
+        $fid = $x->FID;
+    }
+    # OGRNullFID is -1
+    if (!defined $fid || $fid < 0) {
+        $self->InsertFeature($x);
+    } else {
+        $self->SetFeature($x);
+    }
 }
 
 sub ForFeatures {
@@ -1195,7 +1315,7 @@ sub ForFeatures {
     my $in_place = shift;
     $self->ResetReading;
     while (my $f = $self->GetNextFeature) {
-        $FEATURES{tied(%$f)} = $self;
+        keep($f, $self);
         $code->($f);
         $self->SetFeature($f) if $in_place;
     };
@@ -1230,37 +1350,33 @@ sub GetFieldNames {
 }
 
 sub GetFieldDefn {
-    my ($self, $name) = @_;
+    my $self = shift;
     my $d = $self->GetDefn;
-    for (my $i = 0; $i < $d->GetFieldCount; $i++) {
-        my $fd = $d->GetFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    for (my $i = 0; $i < $d->GetGeomFieldCount; $i++) {
-        my $fd = $d->GetGeomFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    Geo::GDAL::error(2, $name, 'Field');
+    my $field = $d->GetFieldIndex(shift // 0);
+    return $d->_GetFieldDefn($field);
+}
+
+sub GetGeomFieldDefn {
+    my $self = shift;
+    my $d = $self->GetDefn;
+    my $field = $d->GetGeomFieldIndex(shift // 0);
+    return $d->_GetGeomFieldDefn($field);
 }
 
 sub GeometryType {
     my $self = shift;
-    my $field = shift;
-    $field //= 0;
-    my $fd = $self->GetDefn->GetGeomFieldDefn($field);
+    my $d = $self->GetDefn;
+    my $field = $d->GetGeomFieldIndex(shift // 0);
+    my $fd = $d->_GetGeomFieldDefn($field);
     return $fd->Type if $fd;
 }
 
 sub SpatialReference {
-    my($self, $field, $sr) = @_;
+    my $self = shift;
     my $d = $self->GetDefn;
-    my $i;
-    if (not defined $field or (blessed($field) and $field->isa('Geo::OSR::SpatialReference'))) {
-        $i = 0;
-    } else {
-        $i = $d->GetGeomFieldIndex($field);
-    }
-    my $d2 = $d->GetGeomFieldDefn($i);
+    my $field = @_ == 2 ? $d->GetGeomFieldIndex(shift // 0) : 0;
+    my $sr = shift;
+    my $d2 = $d->_GetGeomFieldDefn($field);
     $d2->SpatialReference($sr) if defined $sr;
     return $d2->SpatialReference() if defined wantarray;
 }
@@ -1275,15 +1391,39 @@ use Encode;
 use Carp;
 use Scalar::Util 'blessed';
 
-sub RELEASE_PARENTS {
+Geo::GDAL->import(qw(:INTERNAL));
+
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::OGR::Feature::DEFNS{$self};
-    delete $Geo::OGR::Layer::DEFNS{$self};
+    unkeep($self);
 }
 
 sub Feature {
     my $self = shift;
-    return $Geo::OGR::Feature::DEFNS{tied(%$self)};
+    return parent($self);
+}
+
+
+sub GetFieldIndex {
+    my ($self, $name) = @_;
+    my $index = $self->_GetFieldIndex($name);
+    if ($index < 0 and $name =~ /^\d+$/) {
+        # the name is allowed to be an index
+        $index = $name if $name >= 0 && $name < $self->GetFieldCount();
+    }
+    error("'$name' is not a non-spatial field.") if $index < 0;
+    return $index;
+}
+
+sub GetGeomFieldIndex {
+    my ($self, $name) = @_;
+    my $index = $self->_GetGeomFieldIndex($name);
+    if ($index < 0 and $name =~ /^\d+$/) {
+        # the name is allowed to be an index
+        $index = $name if $name >= 0 && $name < $self->GetGeomFieldCount();
+    }
+    error("'$name' is not a spatial field.") if $index < 0;
+    return $index;
 }
 
 *Name = *GetName;
@@ -1304,11 +1444,11 @@ sub GetSchema {
     $schema{StyleIgnored} = $self->StyleIgnored();
     $schema{Fields} = [];
     for my $i (0..$self->GetFieldCount-1) {
-        my $s = $self->GetFieldDefn($i)->Schema;
+        my $s = $self->_GetFieldDefn($i)->Schema;
         push @{$schema{Fields}}, $s;
     }
     for my $i (0..$self->GetGeomFieldCount-1) {
-        my $s = $self->GetGeomFieldDefn($i)->Schema;
+        my $s = $self->_GetGeomFieldDefn($i)->Schema;
         push @{$schema{Fields}}, $s;
     }
     return wantarray ? %schema : \%schema;
@@ -1317,7 +1457,7 @@ sub GetSchema {
 
 sub AddField {
     my $self = shift;
-    Geo::GDAL::error("Read-only definition.") if $Geo::OGR::Feature::DEFNS{tied(%$self)} || $Geo::OGR::Layer::DEFNS{tied(%$self)};
+    error("Read-only definition.") if parent($self);
     my %params;
     if (@_ == 0) {
     } elsif (ref($_[0]) eq 'HASH') {
@@ -1326,7 +1466,7 @@ sub AddField {
         %params = @_;
     }
     $params{Type} //= '';
-    if (exists $Geo::OGR::FieldDefn::TYPE_STRING2INT{$params{Type}}) {
+    if (s_exists(field_type => $params{Type})) {
         my $fd = Geo::OGR::FieldDefn->new(%params);
         $self->AddFieldDefn($fd);
     } else {
@@ -1337,49 +1477,48 @@ sub AddField {
 
 sub DeleteField {
     my ($self, $name) = @_;
-    Geo::GDAL::error("Read-only definition.") if $Geo::OGR::Feature::DEFNS{tied(%$self)} || $Geo::OGR::Layer::DEFNS{tied(%$self)};
+    error("Read-only definition.") if parent($self);
     for my $i (0..$self->GetFieldCount-1) {
-        Geo::GDAL::error("Non-geometry fields cannot be deleted.") if $self->GetFieldDefn($i)->Name eq $name;
+        error("Non-spatial fields cannot be deleted.") if $self->_GetFieldDefn($i)->Name eq $name;
     }
     for my $i (0..$self->GetGeomFieldCount-1) {
-        $self->DeleteGeomFieldDefn($i) if $self->GetGeomFieldDefn($i)->Name eq $name;
+        $self->DeleteGeomFieldDefn($i) if $self->_GetGeomFieldDefn($i)->Name eq $name;
     }
-    Geo::GDAL::error(2, $name, 'Field');
+    error(2, $name, 'Field');
 }
 
 sub GetFieldNames {
     my $self = shift;
     my @names = ();
     for my $i (0..$self->GetFieldCount-1) {
-        push @names, $self->GetFieldDefn($i)->Name;
+        push @names, $self->_GetFieldDefn($i)->Name;
     }
     for my $i (0..$self->GetGeomFieldCount-1) {
-        push @names, $self->GetGeomFieldDefn($i)->Name;
+        push @names, $self->_GetGeomFieldDefn($i)->Name;
     }
     return @names;
 }
 
 sub GetFieldDefn {
-    my ($self, $name) = @_;
-    for my $i (0..$self->GetFieldCount-1) {
-        my $fd = $self->GetFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    for my $i (0..$self->GetGeomFieldCount-1) {
-        my $fd = $self->GetGeomFieldDefn($i);
-        return $fd if $fd->Name eq $name;
-    }
-    Geo::GDAL::error(2, $name, 'Field');
+    my $self = shift;
+    my $field = $self->GetFieldIndex(shift);
+    return $self->_GetFieldDefn($field);
+}
+
+sub GetGeomFieldDefn {
+    my $self = shift;
+    my $field = $self->GetGeomFieldIndex(shift);
+    return $self->_GetGeomFieldDefn($field);
 }
 
 sub GeomType {
     my ($self, $type) = @_;
-    Geo::GDAL::error("Read-only definition.") if $Geo::OGR::Feature::DEFNS{tied(%$self)} || $Geo::OGR::Layer::DEFNS{tied(%$self)};
+    error("Read-only definition.") if parent($self);
     if (defined $type) {
-        $type = Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+        $type = s2i(geometry_type => $type);
         SetGeomType($self, $type);
     }
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GetGeomType($self)} if defined wantarray;
+    return i2s(geometry_type => GetGeomType($self)) if defined wantarray;
 }
 *GeometryType = *GeomType;
 
@@ -1401,40 +1540,39 @@ sub StyleIgnored {
 package Geo::OGR::Feature;
 use strict;
 use warnings;
-use vars qw /%GEOMETRIES %DEFNS/;
 use Carp;
 use Encode;
 use Scalar::Util 'blessed';
 
+Geo::GDAL->import(qw(:INTERNAL));
 
-sub RELEASE_PARENTS {
+
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::OGR::Layer::FEATURES{$self};
+    unkeep($self);
 }
 
 sub Layer {
     my $self = shift;
-    return $Geo::OGR::Layer::FEATURES{tied(%$self)};
+    parent($self);
 }
 
 sub FETCH {
-    my($self, $index) = @_;
-    my $i;
-    eval {$i = $self->GetFieldIndex($index)};
-    return $self->GetField($i) unless $@;
-    Geo::GDAL::error("'$index' is not a non-spatial field and it is not safe to retrieve geometries from a feature this way.");
+    my $self = shift;
+    my $field = shift;
+    eval {my $i = $self->GetFieldIndex($field)};
+    return $self->GetField($field) unless $@;
+    error("'$field' is not a non-spatial field and it is not safe to retrieve geometries from a feature this way.");
 }
 
 sub STORE {
     my $self = shift;
-    my $index = shift;
-    my $i;
-    eval {$i = $self->GetFieldIndex($index)};
+    my $field = shift;
+    eval {my $i = $self->GetFieldIndex($field)};
     unless ($@) {
-      $self->SetField($i, @_);
+        $self->SetField($field, @_);
     } else {
-      $i = $self->GetGeomFieldIndex($index);
-      $self->Geometry($i, @_);
+        $self->Geometry($field, @_);
     }
 }
 
@@ -1445,6 +1583,40 @@ sub FID {
     $self->GetFID;
 }
 
+sub GetFieldIndex {
+    my ($self, $name) = @_;
+    my $index = $self->_GetFieldIndex($name);
+    if ($index < 0 and $name =~ /^\d+$/) {
+        # the name is allowed to be an index
+        $index = $name if $name >= 0 && $name < $self->GetFieldCount();
+    }
+    error("'$name' is not a non-spatial field.") if $index < 0;
+    return $index;
+}
+
+sub GetGeomFieldIndex {
+    my ($self, $name) = @_;
+    my $index = $self->_GetGeomFieldIndex($name);
+    if ($index < 0 and $name =~ /^\d+$/) {
+        # the name is allowed to be an index
+        $index = $name if $name >= 0 && $name < $self->GetGeomFieldCount();
+    }
+    error("'$name' is not a spatial field.") if $index < 0;
+    return $index;
+}
+
+sub GetFieldDefn {
+    my $self = shift;
+    my $field = $self->GetFieldIndex(shift);
+    return $self->GetFieldDefnRef($field);
+}
+
+sub GetGeomFieldDefn {
+    my $self = shift;
+    my $field = $self->GetGeomFieldIndex(shift);
+    return $self->GetGeomFieldDefnRef($field);
+}
+
 sub StyleString {
     my $self = shift;
     $self->SetStyleString($_[0]) if @_;
@@ -1464,7 +1636,7 @@ sub Validate {
 
 sub GetSchema {
     my $self = shift;
-    Geo::GDAL::error("Schema of a feature cannot be set directly.") if @_;
+    error("Schema of a feature cannot be set directly.") if @_;
     return $self->GetDefnRef->Schema;
 }
 *Schema = *GetSchema;
@@ -1480,7 +1652,7 @@ sub Row {
         } elsif (@_ and @_ % 2 == 0) {
             %row = @_;
         } else {
-            Geo::GDAL::error('Usage: $feature->Row(%FeatureData).');
+            error('Usage: $feature->Row(%FeatureData).');
         }
         $self->SetFID($row{FID}) if defined $row{FID};
         #$self->Geometry($schema, $row{Geometry}) if $row{Geometry};
@@ -1529,13 +1701,13 @@ sub Tuple {
     my $nf = $self->GetFieldCount;
     my $ngf = $self->GetGeomFieldCount;
     if (@_) {
+        my $values = ref $_[0] ? $_[0] : \@_;
         my $FID;
-        $FID = shift if @_ == $nf + $ngf + 1;
+        $FID = shift @$values if @$values == $nf + $ngf + 1;
         $self->SetFID($FID) if defined $FID;
-        my $values = \@_;
         if (@$values != $nf + $ngf) {
             my $n = $nf + $ngf;
-            Geo::GDAL::error("Too many or too few attribute values for a feature (need $n).");
+            error("Too many or too few attribute values for a feature (need $n).");
         }
         my $index = 0; # index to non-geometry and geometry fields
         for my $i (0..$nf-1) {
@@ -1561,31 +1733,20 @@ sub Tuple {
 sub GetDefn {
     my $self = shift;
     my $defn = $self->GetDefnRef;
-    $DEFNS{tied(%$defn)} = $self;
-    return $defn;
+    keep($defn, $self);
 }
 
-*GetGeomFieldDefn = *GetGeomFieldDefnRef;
-
 *GetFieldNames = *Geo::OGR::Layer::GetFieldNames;
-*GetFieldDefn = *Geo::OGR::Layer::GetFieldDefn;
 
 sub GetField {
-    my($self, $field) = @_;
+    my ($self, $field) = @_;
+    $field = $self->GetFieldIndex($field);
     return unless IsFieldSet($self, $field);
     my $type = GetFieldType($self, $field);
-    if ($type == $Geo::OGR::OFTInteger) {
-        return GetFieldAsInteger($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTInteger64) {
-        return GetFieldAsInteger64($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTReal) {
-        return GetFieldAsDouble($self, $field);
-    }
-    if ($type == $Geo::OGR::OFTString) {
-        return GetFieldAsString($self, $field);
-    }
+    return GetFieldAsInteger($self, $field) if $type == $Geo::OGR::OFTInteger;
+    return GetFieldAsInteger64($self, $field) if $type == $Geo::OGR::OFTInteger64;
+    return GetFieldAsDouble($self, $field) if $type == $Geo::OGR::OFTReal;
+    return GetFieldAsString($self, $field) if $type == $Geo::OGR::OFTString;
     if ($type == $Geo::OGR::OFTIntegerList) {
         my $ret = GetFieldAsIntegerList($self, $field);
         return wantarray ? @$ret : $ret;
@@ -1618,17 +1779,18 @@ sub GetField {
         my @ret = GetFieldAsDateTime($self, $field);
         return wantarray ? @ret : [@ret];
     }
-    Geo::GDAL::error("Perl bindings do not support field type '$Geo::OGR::FieldDefn::TYPE_INT2STRING{$type}'.");
+    error("Perl bindings do not support the field type '".i2s(field_type => $type)."'.");
 }
 
 sub UnsetField {
-    my($self, $field) = @_;
+    my ($self, $field) = @_;
+    $field = $self->GetFieldIndex($field);
     _UnsetField($self, $field);
 }
 
 sub SetField {
     my $self = shift;
-    my $field = shift;
+    my $field = $self->GetFieldIndex(shift);
     my $arg = $_[0];
     if (@_ == 0 or !defined($arg)) {
         _UnsetField($self, $field);
@@ -1660,22 +1822,39 @@ sub SetField {
             $arg->[6] //= 0;
             _SetField($self, $field, @$arg[0..6]);
         }
+        elsif ($type == $Geo::OGR::OFTInteger64)
+        {
+            SetFieldInteger64($self, $field, $arg);
+        }
         else {
-            _SetField($self, $field, @$arg);
+            $type = i2s(field_type => $type);
+            my $name = $self->GetFieldDefnRef($field)->Name;
+            error("'$arg' is not a suitable value for field $name($type).");
         }
     } else {
         if ($type == $Geo::OGR::OFTBinary) {
             #$arg = unpack('H*', $arg); # remove when SetFieldBinary is available
             $self->SetFieldBinary($field, $arg);
-        } else {
+        }
+        elsif ($type == $Geo::OGR::OFTInteger64)
+        {
+            SetFieldInteger64($self, $field, $arg);
+        }
+        elsif ($type == $Geo::OGR::OFTInteger or $type == $Geo::OGR::OFTReal or $type == $Geo::OGR::OFTString)
+        {
             _SetField($self, $field, $arg);
         }
+        else {
+            $type = i2s(field_type => $type);
+            my $name = $self->GetFieldDefnRef($field)->Name;
+            error("'$arg' is not a suitable value for field $name($type).");
+        }
     }
 }
 
 sub Field {
     my $self = shift;
-    my $field = shift;
+    my $field = $self->GetFieldIndex(shift // 0);
     $self->SetField($field, @_) if @_;
     $self->GetField($field) if defined wantarray;
 }
@@ -1683,6 +1862,7 @@ sub Field {
 sub Geometry {
     my $self = shift;
     my $field = ((@_ > 0 and ref($_[0]) eq '') or (@_ > 2 and @_ % 2 == 1)) ? shift : 0;
+    $field = $self->GetGeomFieldIndex($field);
     my $geometry;
     if (@_ and @_ % 2 == 0) {
         %$geometry = @_;
@@ -1693,33 +1873,32 @@ sub Geometry {
         my $type = $self->GetDefn->GetGeomFieldDefn($field)->Type;
         if (blessed($geometry) and $geometry->isa('Geo::OGR::Geometry')) {
             my $gtype = $geometry->GeometryType;
-            Geo::GDAL::error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
+            error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
                 if $type ne 'Unknown' and $type ne $gtype;
             eval {
                 $self->SetGeomFieldDirectly($field, $geometry->Clone);
             };
-            confess Geo::GDAL->last_error if $@;
+            confess last_error() if $@;
         } elsif (ref($geometry) eq 'HASH') {
             $geometry->{GeometryType} //= $type;
             eval {
                 $geometry = Geo::OGR::Geometry->new($geometry);
             };
             my $gtype = $geometry->GeometryType;
-            Geo::GDAL::error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
+            error("The type of the inserted geometry ('$gtype') is not the same as the type of the field ('$type').")
                 if $type ne 'Unknown' and $type ne $gtype;
             eval {
                 $self->SetGeomFieldDirectly($field, $geometry);
             };
-            confess Geo::GDAL->last_error if $@;
+            confess last_error() if $@;
         } else {
-            Geo::GDAL::error("Usage: \$feature->Geometry([field],[geometry])");
+            error("Usage: \$feature->Geometry([field],[geometry])");
         }
     }
     return unless defined wantarray;
     $geometry = $self->GetGeomFieldRef($field);
     return unless $geometry;
-    $GEOMETRIES{tied(%$geometry)} = $self;
-    return $geometry;
+    keep($geometry, $self);
 }
 *GetGeometry = *Geometry;
 *SetGeometry = *Geometry;
@@ -1743,47 +1922,43 @@ sub SetFrom {
 package Geo::OGR::FieldDefn;
 use strict;
 use warnings;
-use vars qw /
-    %SCHEMA_KEYS
-    @TYPES @SUB_TYPES @JUSTIFY_VALUES
-    %TYPE_STRING2INT %TYPE_INT2STRING
-    %SUB_TYPE_STRING2INT %SUB_TYPE_INT2STRING
-    %JUSTIFY_STRING2INT %JUSTIFY_INT2STRING
-    /;
+use vars qw(%SCHEMA_KEYS @TYPES @SUBTYPES @JUSTIFY);
 use Carp;
 use Encode;
 %SCHEMA_KEYS = map {$_ => 1} qw/Name Type SubType Justify Width Precision Nullable Default Ignored/;
 for (keys %Geo::OGR::) {
     push(@TYPES, $1), next if /^OFT(\w+)/;
-    push(@SUB_TYPES, $1), next if /^OFST(\w+)/;
-    push(@JUSTIFY_VALUES, $1), next if /^OJ(\w+)/;
+    push(@SUBTYPES, $1), next if /^OFST(\w+)/;
+    push(@JUSTIFY, $1), next if /^OJ(\w+)/;
 }
 for my $string (@TYPES) {
     my $int = eval "\$Geo::OGR::OFT$string";
-    $TYPE_STRING2INT{$string} = $int;
-    $TYPE_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{field_type}{$string} = $int;
+    $Geo::GDAL::I2S{field_type}{$int} = $string;
 }
-for my $string (@SUB_TYPES) {
+for my $string (@SUBTYPES) {
     my $int = eval "\$Geo::OGR::OFST$string";
-    $SUB_TYPE_STRING2INT{$string} = $int;
-    $SUB_TYPE_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{field_subtype}{$string} = $int;
+    $Geo::GDAL::I2S{field_subtype}{$int} = $string;
 }
-for my $string (@JUSTIFY_VALUES) {
+for my $string (@JUSTIFY) {
     my $int = eval "\$Geo::OGR::OJ$string";
-    $JUSTIFY_STRING2INT{$string} = $int;
-    $JUSTIFY_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{justify}{$string} = $int;
+    $Geo::GDAL::I2S{justify}{$int} = $string;
 }
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub Types {
     return @TYPES;
 }
 
 sub SubTypes {
-    return @SUB_TYPES;
+    return @SUBTYPES;
 }
 
 sub JustifyValues {
-    return @JUSTIFY_VALUES;
+    return @JUSTIFY;
 }
 
 sub Schema {
@@ -1793,7 +1968,7 @@ sub Schema {
         for my $key (keys %SCHEMA_KEYS) {
             next unless exists $params->{$key};
             eval "\$self->$key(\$params->{$key})";
-            confess(Geo::GDAL->last_error()) if $@;
+            confess(last_error()) if $@;
         }
     }
     return unless defined wantarray;
@@ -1815,31 +1990,28 @@ sub Name {
 sub Type {
     my($self, $type) = @_;
     if (defined $type) {
-        Geo::GDAL::error(1, $type, \%TYPE_STRING2INT) unless exists $TYPE_STRING2INT{$type};
-        $type = $TYPE_STRING2INT{$type};
+        $type = s2i(field_type => $type);
         SetType($self, $type);
     }
-    return $TYPE_INT2STRING{GetType($self)} if defined wantarray;
+    return i2s(field_type => GetType($self)) if defined wantarray;
 }
 
 sub SubType {
-    my($self, $sub_type) = @_;
-    if (defined $sub_type) {
-        Geo::GDAL::error(1, $sub_type, \%SUB_TYPE_STRING2INT) unless exists $SUB_TYPE_STRING2INT{$sub_type};
-        $sub_type = $SUB_TYPE_STRING2INT{$sub_type};
-        SetSubType($self, $sub_type);
+    my($self, $subtype) = @_;
+    if (defined $subtype) {
+        $subtype = s2i(field_subtype => $subtype);
+        SetSubType($self, $subtype);
     }
-    return $SUB_TYPE_INT2STRING{GetSubType($self)} if defined wantarray;
+    return i2s(field_subtype => GetSubType($self)) if defined wantarray;
 }
 
 sub Justify {
     my($self, $justify) = @_;
     if (defined $justify) {
-        Geo::GDAL::error(1, $justify, \%JUSTIFY_STRING2INT) unless exists $JUSTIFY_STRING2INT{$justify};
-        $justify = $JUSTIFY_STRING2INT{$justify} if exists $JUSTIFY_STRING2INT{$justify};
+        $justify = s2i(justify => $justify);
         SetJustify($self, $justify);
     }
-    return $JUSTIFY_INT2STRING{GetJustify($self)} if defined wantarray;
+    return i2s(justify => GetJustify($self)) if defined wantarray;
 }
 
 sub Width {
@@ -1883,6 +2055,8 @@ use Carp;
 use Scalar::Util 'blessed';
 %SCHEMA_KEYS = map {$_ => 1} qw/Name Type SpatialReference Nullable Ignored/;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub Schema {
     my $self = shift;
     if (@_) {
@@ -1890,7 +2064,7 @@ sub Schema {
         for my $key (keys %SCHEMA_KEYS) {
             next unless exists $params->{$key};
             eval "\$self->$key(\$params->{$key})";
-            confess Geo::GDAL->last_error() if $@;
+            confess last_error() if $@;
         }
     }
     return unless defined wantarray;
@@ -1912,15 +2086,15 @@ sub Name {
 sub Type {
     my($self, $type) = @_;
     if (defined $type) {
-        $type = Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT);
+        $type = s2i(geometry_type => $type);
         SetType($self, $type);
     }
-    $Geo::OGR::Geometry::TYPE_INT2STRING{GetType($self)} if defined wantarray;
+    i2s(geometry_type => GetType($self)) if defined wantarray;
 }
 *GeometryType = *Type;
 
 sub Types {
-  return @Geo::OGR::Geometry::GEOMETRY_TYPES;
+    return Geo::OGR::Geometry::GeometryTypes();
 }
 
 sub SpatialReference {
@@ -1950,14 +2124,12 @@ use warnings;
 use Carp;
 use vars qw /
     @BYTE_ORDER_TYPES @GEOMETRY_TYPES
-    %BYTE_ORDER_STRING2INT %BYTE_ORDER_INT2STRING
-    %TYPE_STRING2INT %TYPE_INT2STRING
     /;
 @BYTE_ORDER_TYPES = qw/XDR NDR/;
 for my $string (@BYTE_ORDER_TYPES) {
     my $int = eval "\$Geo::OGR::wkb$string";
-    $BYTE_ORDER_STRING2INT{$string} = $int;
-    $BYTE_ORDER_INT2STRING{$int} = $string;
+    $Geo::GDAL::S2I{byte_order}{$string} = $int;
+    $Geo::GDAL::I2S{byte_order}{$int} = $string;
 }
 for (keys %Geo::OGR::) {
     next if /^wkb25/;
@@ -1966,15 +2138,17 @@ for (keys %Geo::OGR::) {
 }
 for my $string (@GEOMETRY_TYPES) {
     my $int = eval "\$Geo::OGR::wkb$string";
-    $TYPE_STRING2INT{$string} = $int;
+    $Geo::GDAL::I2S{geometry_type}{$int} = $string;
+    $Geo::GDAL::S2I{geometry_type}{$string} = $int;
     if ($string =~ /25D/) {
-        my $s = $string;
-        $s =~ s/25D/Z/;
-        $TYPE_STRING2INT{$s} = $int;
+        $string =~ s/25D/Z/;
+        $Geo::GDAL::S2I{geometry_type}{$string} = $int;
     }
-    $TYPE_INT2STRING{$int} = $string;
 }
 
+Geo::GDAL->import(qw(:INTERNAL));
+Geo::OGR->import(qw(:INTERNAL));
+
 sub ByteOrders {
     return @BYTE_ORDER_TYPES;
 }
@@ -1983,14 +2157,14 @@ sub GeometryTypes {
     return @GEOMETRY_TYPES;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
     my $self = shift;
-    delete $Geo::OGR::Feature::GEOMETRIES{$self};
+    unkeep($self);
 }
 
 sub Feature {
     my $self = shift;
-    return $Geo::OGR::Feature::GEOMETRIES{tied(%$self)};
+    parent($self);
 }
 
 sub ApproximateArcAngles {
@@ -2013,7 +2187,7 @@ sub ApproximateArcAngles {
     for my $p (keys %default) {
         $p{$p} //= $default{$p};
     }
-    Geo::GDAL::error("Usage: Center => [x,y,z].") unless ref($p{Center}) eq 'ARRAY';
+    error("Usage: Center => [x,y,z].") unless ref($p{Center}) eq 'ARRAY';
     for my $i (0..2) {
         $p{Center}->[$i] //= 0;
     }
@@ -2022,7 +2196,7 @@ sub ApproximateArcAngles {
 
 sub As {
     my $self = shift;
-    my $p = Geo::GDAL::named_parameters(\@_, Format => undef, ByteOrder => 'XDR', SRID => undef, Options => undef, AltitudeMode => undef);
+    my $p = named_parameters(\@_, Format => undef, ByteOrder => 'XDR', SRID => undef, Options => undef, AltitudeMode => undef);
     my $f = $p->{format};
     if ($f =~ /text/i) {
         return $self->AsText;
@@ -2036,7 +2210,7 @@ sub As {
         return $self->ExportToWkb($p->{byteorder});
     } elsif ($f =~ /wkb/i) {
         if ($f =~ /iso/i) {
-            $p->{byteorder} = Geo::GDAL::string2int($p->{byteorder}, \%Geo::OGR::Geometry::BYTE_ORDER_STRING2INT);
+            $p->{byteorder} = s2i(byte_order => $p->{byteorder});
             return $self->ExportToIsoWkb($p->{byteorder});
         } elsif ($f =~ /ewkb/i) {
             return $self->AsHEXEWKB($p->{srid});
@@ -2052,7 +2226,7 @@ sub As {
     } elsif ($f =~ /json/i) {
         return $self->AsJSON;
     } else {
-        Geo::GDAL::error(1, $f, map {$_=>1} qw/Text WKT ISO_WKT ISO_WKB HEX_WKB HEX_EWKB Binary GML KML JSON/);
+        error(1, $f, map {$_=>1} qw/Text WKT ISO_WKT ISO_WKB HEX_WKB HEX_EWKB Binary GML KML JSON/);
     }
 }
 
@@ -2098,7 +2272,7 @@ sub AsHEXEWKB {
 
 sub GeometryType {
     my $self = shift;
-    return $TYPE_INT2STRING{$self->GetGeometryType};
+    return i2s(geometry_type => $self->GetGeometryType);
 }
 
 sub CoordinateDimension {
@@ -2115,8 +2289,8 @@ sub Extent {
 sub AddPoint {
     my $self = shift;
     my $t = $self->GetGeometryType;
-    my $has_z = Geo::OGR::GT_HasZ($t);
-    my $has_m = Geo::OGR::GT_HasM($t);
+    my $has_z = HasZ($t);
+    my $has_m = HasM($t);
     if (!$has_z && !$has_m) {
         $self->AddPoint_2D(@_[0..1]);
     } elsif ($has_z && !$has_m) {
@@ -2131,8 +2305,8 @@ sub AddPoint {
 sub SetPoint {
     my $self = shift;
     my $t = $self->GetGeometryType;
-    my $has_z = Geo::OGR::GT_HasZ($t);
-    my $has_m = Geo::OGR::GT_HasM($t);
+    my $has_z = HasZ($t);
+    my $has_m = HasM($t);
     if (!$has_z && !$has_m) {
         $self->SetPoint_2D(@_[0..2]);
     } elsif ($has_z && !$has_m) {
@@ -2148,8 +2322,8 @@ sub GetPoint {
     my($self, $i) = @_;
     $i //= 0;
     my $t = $self->GetGeometryType;
-    my $has_z = Geo::OGR::GT_HasZ($t);
-    my $has_m = Geo::OGR::GT_HasM($t);
+    my $has_z = HasZ($t);
+    my $has_m = HasM($t);
     my $point;
     if (!$has_z && !$has_m) {
         $point = $self->GetPoint_2D($i);
@@ -2170,9 +2344,9 @@ sub Point {
     if (@_) {
         my $t = $self->GetGeometryType;
         my $i;
-        if (Geo::OGR::GT_Flatten($t) == $Geo::OGR::wkbPoint) {
-            my $has_z = Geo::OGR::GT_HasZ($t);
-            my $has_m = Geo::OGR::GT_HasM($t);
+        if (Flatten($t) == $Geo::OGR::wkbPoint) {
+            my $has_z = HasZ($t);
+            my $has_m = HasM($t);
             if (!$has_z && !$has_m) {
                 shift if @_ > 2;
                 $i = 0;
@@ -2195,17 +2369,17 @@ sub Point {
 sub Points {
     my $self = shift;
     my $t = $self->GetGeometryType;
-    my $has_z = Geo::OGR::GT_HasZ($t);
-    my $has_m = Geo::OGR::GT_HasM($t);
+    my $has_z = HasZ($t);
+    my $has_m = HasM($t);
     my $postfix = '';
-    $postfix .= 'Z' if Geo::OGR::GT_HasZ($t);
-    $postfix .= 'M' if Geo::OGR::GT_HasM($t);
-    $t = $TYPE_INT2STRING{Geo::OGR::GT_Flatten($t)};
+    $postfix .= 'Z' if HasZ($t);
+    $postfix .= 'M' if HasM($t);
+    $t = i2s(geometry_type => Flatten($t));
     my $points = shift;
     if ($points) {
         Empty($self);
         if ($t eq 'Unknown' or $t eq 'None' or $t eq 'GeometryCollection') {
-            Geo::GDAL::error("Can't set points of a geometry of type '$t'.");
+            error("Can't set points of a geometry of type '$t'.");
         } elsif ($t eq 'Point') {
             # support both "Point" as a list of one point and one point
             if (ref($points->[0])) {
@@ -2272,18 +2446,18 @@ sub _GetPoints {
 
 sub ExportToWkb {
     my($self, $bo) = @_;
-    $bo = Geo::GDAL::string2int($bo, \%BYTE_ORDER_STRING2INT);
+    $bo = s2i(byte_order => $bo);
     return _ExportToWkb($self, $bo);
 }
 
 sub ForceTo {
     my $self = shift;
     my $type = shift;
-    $type = Geo::GDAL::string2int($type, \%TYPE_STRING2INT);
+    $type = s2i(geometry_type => $type);
     eval {
         $self = Geo::OGR::ForceTo($self, $type, @_);
     };
-    confess Geo::GDAL->last_error if $@;
+    confess last_error() if $@;
     return $self;
 }
 
@@ -2355,10 +2529,12 @@ use strict;
 use warnings;
 use Carp;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub GeometryType {
     my($type) = @_;
     if (defined $type) {
-        return Geo::GDAL::string2int($type, \%Geo::OGR::Geometry::TYPE_STRING2INT, \%Geo::OGR::Geometry::TYPE_INT2STRING);
+        return s2i(geometry_type => $type, 1);
     } else {
         return @Geo::OGR::Geometry::GEOMETRY_TYPES;
     }
@@ -2366,35 +2542,32 @@ sub GeometryType {
 
 sub GeometryTypeModify {
     my($type, $modifier) = @_;
-    Geo::GDAL::error(1, $type, \%Geo::OGR::Geometry::TYPE_STRING2INT) unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_Flatten($type)} if $modifier =~ /flat/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_SetZ($type)} if $modifier =~ /z/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetCollection($type)} if $modifier =~ /collection/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetCurve($type)} if $modifier =~ /curve/i;
-    return $Geo::OGR::Geometry::TYPE_INT2STRING{GT_GetLinear($type)} if $modifier =~ /linear/i;
-    Geo::GDAL::error(1, $modifier, {Flatten => 1, SetZ => 1, GetCollection => 1, GetCurve => 1, GetLinear => 1});
+    $type = s2i(geometry_type => $type);
+    return i2s(geometry_type => GT_Flatten($type)) if $modifier =~ /flat/i;
+    return i2s(geometry_type => GT_SetZ($type)) if $modifier =~ /z/i;
+    return i2s(geometry_type => GT_GetCollection($type)) if $modifier =~ /collection/i;
+    return i2s(geometry_type => GT_GetCurve($type)) if $modifier =~ /curve/i;
+    return i2s(geometry_type => GT_GetLinear($type)) if $modifier =~ /linear/i;
+    error(1, $modifier, {Flatten => 1, SetZ => 1, GetCollection => 1, GetCurve => 1, GetLinear => 1});
 }
 
 sub GeometryTypeTest {
     my($type, $test, $type2) = @_;
-    Geo::GDAL::error(1, $type, \%Geo::OGR::Geometry::TYPE_STRING2INT) unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
-    $type = $Geo::OGR::Geometry::TYPE_STRING2INT{$type};
+    $type = s2i(geometry_type => $type);
     if (defined $type2) {
-        Geo::GDAL::error(1, $type2, \%Geo::OGR::Geometry::TYPE_STRING2INT) unless exists $Geo::OGR::Geometry::TYPE_STRING2INT{$type2};
-        $type2 = $Geo::OGR::Geometry::TYPE_STRING2INT{$type2};
+        $type = s2i(geometry_type => $type);
     } else {
-        Geo::GDAL::error("Usage: GeometryTypeTest(type1, 'is_subclass_of', type2).") if $test =~ /subclass/i;
+        error("Usage: GeometryTypeTest(type1, 'is_subclass_of', type2).") if $test =~ /subclass/i;
     }
     return GT_HasZ($type) if $test =~ /z/i;
     return GT_IsSubClassOf($type, $type2) if $test =~ /subclass/i;
     return GT_IsCurve($type) if $test =~ /curve/i;
     return GT_IsSurface($type) if $test =~ /surface/i;
     return GT_IsNonLinear($type) if $test =~ /linear/i;
-    Geo::GDAL::error(1, $test, {HasZ => 1, IsSubClassOf => 1, IsCurve => 1, IsSurface => 1, IsNonLinear => 1});
+    error(1, $test, {HasZ => 1, IsSubClassOf => 1, IsCurve => 1, IsSurface => 1, IsNonLinear => 1});
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
 }
 
 *ByteOrders = *Geo::OGR::Geometry::ByteOrders;
diff --git a/swig/perl/lib/Geo/OSR.dox b/swig/perl/lib/Geo/OSR.dox
index ade5306..64ed7c9 100644
--- a/swig/perl/lib/Geo/OSR.dox
+++ b/swig/perl/lib/Geo/OSR.dox
@@ -1,5 +1,6 @@
 ## @class Geo::OSR
 # @brief Base class for projection related classes.
+# @details
 
 ## @sub @Projections()
 # @return list of known projections.
@@ -42,8 +43,7 @@
 
 ## @class Geo::OSR::SpatialReference
 # @brief A spatial reference system.
-#
-# <a href="http://www.gdal.org/classOGRSpatialReference.html">Documentation
+# @details <a href="http://www.gdal.org/classOGRSpatialReference.html">Documentation
 # of the underlying C++ class at www.gdal.org</a>
 
 ## @ignore ImportFromEPSGA
@@ -290,10 +290,10 @@
 
 ## @method GetSemiMinor()
 
-## @method GetSemiMajor() 
+## @method GetSemiMajor()
 
 ## @method GetUTMZone()
-# Get UTM zone information. 
+# Get UTM zone information.
 # @return The UTM zone (integer). In scalar context the returned value
 # is negative for southern hemisphere zones. In list context returns
 # two values ($zone, $north), where $zone is always non-negative and
@@ -320,6 +320,7 @@
 
 ## @class Geo::OSR::CoordinateTransformation
 # @brief An object for transforming from one projection to another.
+# @details
 
 ## @cmethod Geo::OSR::CoordinateTransformation new($src, $dst)
 # @param src a Geo::OSR::SpatialReference object
diff --git a/swig/perl/lib/Geo/OSR.pm b/swig/perl/lib/Geo/OSR.pm
index 0644c18..2bd3e98 100644
--- a/swig/perl/lib/Geo/OSR.pm
+++ b/swig/perl/lib/Geo/OSR.pm
@@ -104,9 +104,9 @@ sub new {
         eval {
             SetWellKnownGeogCS($self, 'WGS'.$param{WGS});
         };
-        confess Geo::GDAL->last_error if $@;
+        confess last_error() if $@;
     } else {
-        Geo::GDAL::error("Unrecognized/missing parameters: @_.");
+        error("Unrecognized/missing parameters: @_.");
     }
     bless $self, $pkg if defined $self;
 }
@@ -142,6 +142,7 @@ sub DESTROY {
 *SetTargetLinearUnits = *Geo::OSRc::SpatialReference_SetTargetLinearUnits;
 *SetLinearUnits = *Geo::OSRc::SpatialReference_SetLinearUnits;
 *SetLinearUnitsAndUpdateParameters = *Geo::OSRc::SpatialReference_SetLinearUnitsAndUpdateParameters;
+*GetTargetLinearUnits = *Geo::OSRc::SpatialReference_GetTargetLinearUnits;
 *GetLinearUnits = *Geo::OSRc::SpatialReference_GetLinearUnits;
 *GetLinearUnitsName = *Geo::OSRc::SpatialReference_GetLinearUnitsName;
 *GetAuthorityCode = *Geo::OSRc::SpatialReference_GetAuthorityCode;
@@ -518,7 +519,7 @@ sub Datums {
     return keys %DATUMS;
 }
 
-sub RELEASE_PARENTS {
+sub RELEASE_PARENT {
 }
 
 
@@ -527,6 +528,8 @@ use strict;
 use warnings;
 use Carp;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub Export {
     my $self = shift;
     my $format;
@@ -547,7 +550,7 @@ sub Export {
         MICoordSys => sub { return ExportToMICoordSys() },
         MapInfoCS => sub { return ExportToMICoordSys() },
         );
-    Geo::GDAL::error(1, $format, \%converters) unless $converters{$format};
+    error(1, $format, \%converters) unless $converters{$format};
     return $converters{$format}->();
 }
 *AsText = *ExportToWkt;
@@ -566,7 +569,7 @@ sub Set {
     } elsif (exists $params{LinearUnits} and exists $params{Value}) {
         SetLinearUnitsAndUpdateParameters($self, $params{LinearUnits}, $params{Value});
     } elsif ($params{Parameter} and exists $params{Value}) {
-        Geo::GDAL::error(1, $params{Parameter}, \%Geo::OSR::PARAMETERS) unless exists $Geo::OSR::PARAMETERS{$params{Parameter}};
+        error(1, $params{Parameter}, \%Geo::OSR::PARAMETERS) unless exists $Geo::OSR::PARAMETERS{$params{Parameter}};
         $params{Normalized} ?
             SetNormProjParm($self, $params{Parameter}, $params{Value}) :
             SetProjParm($self, $params{Parameter}, $params{Value});
@@ -602,7 +605,7 @@ sub Set {
             SetProjCS($self, $params{CoordinateSystem});
         }
     } elsif (exists $params{Projection}) {
-        Geo::GDAL::error(1, $params{Projection}, \%Geo::OSR::PROJECTIONS) unless exists $Geo::OSR::PROJECTIONS{$params{Projection}};
+        error(1, $params{Projection}, \%Geo::OSR::PROJECTIONS) unless exists $Geo::OSR::PROJECTIONS{$params{Projection}};
         my @parameters = ();
         @parameters = @{$params{Parameters}} if ref($params{Parameters});
         if ($params{Projection} eq 'Albers_Conic_Equal_Area') {
@@ -700,7 +703,7 @@ sub Set {
             SetProjection($self, $params{Projection});
         }
     } else {
-        Geo::GDAL::error("Not enough information to create a spatial reference object.");
+        error("Not enough information to create a spatial reference object.");
     }
 }
 
@@ -724,6 +727,8 @@ package Geo::OSR::CoordinateTransformation;
 use strict;
 use warnings;
 
+Geo::GDAL->import(qw(:INTERNAL));
+
 sub TransformPoints {
     my($self, $points) = @_;
     _TransformPoints($self, $points), return unless ref($points->[0]->[0]);
diff --git a/swig/perl/ogr_wrap.cpp b/swig/perl/ogr_wrap.cpp
index 42d2738..d6caeb7 100644
--- a/swig/perl/ogr_wrap.cpp
+++ b/swig/perl/ogr_wrap.cpp
@@ -1507,29 +1507,28 @@ SWIG_Perl_SetModule(swig_module_info *module) {
 /* -------- TYPES TABLE (BEGIN) -------- */
 
 #define SWIGTYPE_p_GDALMajorObjectShadow swig_types[0]
-#define SWIGTYPE_p_GDALProgressFunc swig_types[1]
-#define SWIGTYPE_p_GIntBig swig_types[2]
-#define SWIGTYPE_p_OGRFeatureDefnShadow swig_types[3]
-#define SWIGTYPE_p_OGRFeatureShadow swig_types[4]
-#define SWIGTYPE_p_OGRFieldDefnShadow swig_types[5]
-#define SWIGTYPE_p_OGRGeomFieldDefnShadow swig_types[6]
-#define SWIGTYPE_p_OGRGeometryShadow swig_types[7]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[8]
-#define SWIGTYPE_p_OGRStyleTableShadow swig_types[9]
-#define SWIGTYPE_p_OSRCoordinateTransformationShadow swig_types[10]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[11]
-#define SWIGTYPE_p_char swig_types[12]
-#define SWIGTYPE_p_double swig_types[13]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[14]
-#define SWIGTYPE_p_float swig_types[15]
-#define SWIGTYPE_p_int swig_types[16]
-#define SWIGTYPE_p_p_GIntBig swig_types[17]
-#define SWIGTYPE_p_p_char swig_types[18]
-#define SWIGTYPE_p_p_double swig_types[19]
-#define SWIGTYPE_p_p_int swig_types[20]
-#define SWIGTYPE_p_p_p_char swig_types[21]
-static swig_type_info *swig_types[23];
-static swig_module_info swig_module = {swig_types, 22, 0, 0, 0, 0};
+#define SWIGTYPE_p_GIntBig swig_types[1]
+#define SWIGTYPE_p_OGRFeatureDefnShadow swig_types[2]
+#define SWIGTYPE_p_OGRFeatureShadow swig_types[3]
+#define SWIGTYPE_p_OGRFieldDefnShadow swig_types[4]
+#define SWIGTYPE_p_OGRGeomFieldDefnShadow swig_types[5]
+#define SWIGTYPE_p_OGRGeometryShadow swig_types[6]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[7]
+#define SWIGTYPE_p_OGRStyleTableShadow swig_types[8]
+#define SWIGTYPE_p_OSRCoordinateTransformationShadow swig_types[9]
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[10]
+#define SWIGTYPE_p_char swig_types[11]
+#define SWIGTYPE_p_double swig_types[12]
+#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[13]
+#define SWIGTYPE_p_float swig_types[14]
+#define SWIGTYPE_p_int swig_types[15]
+#define SWIGTYPE_p_p_GIntBig swig_types[16]
+#define SWIGTYPE_p_p_char swig_types[17]
+#define SWIGTYPE_p_p_double swig_types[18]
+#define SWIGTYPE_p_p_int swig_types[19]
+#define SWIGTYPE_p_p_p_char swig_types[20]
+static swig_type_info *swig_types[22];
+static swig_module_info swig_module = {swig_types, 21, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -1730,11 +1729,13 @@ SWIG_FromCharPtr(const char *cptr)
     #define NEED_DEF "A parameter which must be defined or not empty, is not."
     #define WRONG_CLASS "Object has a wrong class."
     #define NEED_REF "A parameter which must be a reference, is not."
+    #define NEED_HASH_REF "A parameter/item which must be a hash reference, is not."
     #define NEED_ARRAY_REF "A parameter/item which must be an array reference, is not."
     #define NEED_BINARY_DATA "A parameter which must be binary data, is not."
     #define NEED_CODE_REF "A parameter which must be an anonymous subroutine, is not."
     #define WRONG_ITEM_IN_ARRAY "An item in an array parameter has wrong type."
     #define ARRAY_TO_XML_FAILED "An array parameter cannot be converted to an XMLTree."
+    #define NOT_ENOUGH_ELEMENTS "The supplied array does not have enough elements."
 
 
 void VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg ) {
@@ -1826,9 +1827,11 @@ SWIGINTERN int OGRStyleTableShadow_AddStyle(OGRStyleTableShadow *self,char const
         return OGR_STBL_AddStyle( (OGRStyleTableH) self, pszName, pszStyleString);
    }
 
-    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf) {
-        /* if tmpbuf, only tmpbuf is freed; if not, ret is freed*/
+    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf, bool *safefree = NULL) {
+        /* if tmpbuf is given, only tmpbuf needs to be freed, use Safefree!
+           if not, ret needs to be freed, if safefree use Safefree else use free! */
         char *ret;
+        if (safefree) *safefree = false;
         if (SvOK(sv)) {
             STRLEN len;
             ret = SvPV(sv, len);
@@ -1839,6 +1842,7 @@ SWIGINTERN int OGRStyleTableShadow_AddStyle(OGRStyleTableShadow *self,char const
                 } else {
                     ret = (char *)bytes_to_utf8((const U8*)ret, &len);
                 }
+                if (safefree) *safefree = true;
             } else {
                 if (!tmpbuf)
                     ret = strdup(ret);
@@ -2274,65 +2278,25 @@ SWIGINTERN bool OGRFeatureShadow_Equal(OGRFeatureShadow *self,OGRFeatureShadow *
 SWIGINTERN int OGRFeatureShadow_GetFieldCount(OGRFeatureShadow *self){
     return OGR_F_GetFieldCount(self);
   }
-SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_0(OGRFeatureShadow *self,int id){
+SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef(OGRFeatureShadow *self,int id){
     return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, id);
   }
-SWIGINTERN OGRFieldDefnShadow *OGRFeatureShadow_GetFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          return (OGRFieldDefnShadow *) OGR_F_GetFieldDefnRef(self, i);
-      return NULL;
-  }
 SWIGINTERN int OGRFeatureShadow_GetGeomFieldCount(OGRFeatureShadow *self){
     return OGR_F_GetGeomFieldCount(self);
   }
-SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(OGRFeatureShadow *self,int id){
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef(OGRFeatureShadow *self,int id){
       return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, id);
   }
-SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetGeomFieldIndex(self, name);
-      if (i == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          return (OGRGeomFieldDefnShadow *) OGR_F_GetGeomFieldDefnRef(self, i);
-      return NULL;
-  }
-SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_0(OGRFeatureShadow *self,int id){
+SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString(OGRFeatureShadow *self,int id){
     return (const char *) OGR_F_GetFieldAsString(self, id);
   }
-SWIGINTERN char const *OGRFeatureShadow_GetFieldAsString__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-	  return (const char *) OGR_F_GetFieldAsString(self, i);
-      return NULL;
-  }
-SWIGINTERN int OGRFeatureShadow_GetFieldAsInteger__SWIG_0(OGRFeatureShadow *self,int id){
+SWIGINTERN int OGRFeatureShadow_GetFieldAsInteger(OGRFeatureShadow *self,int id){
     return OGR_F_GetFieldAsInteger(self, id);
   }
-SWIGINTERN int OGRFeatureShadow_GetFieldAsInteger__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-	  return OGR_F_GetFieldAsInteger(self, i);
-      return 0;
-  }
-SWIGINTERN GIntBig OGRFeatureShadow_GetFieldAsInteger64__SWIG_0(OGRFeatureShadow *self,int id){
+SWIGINTERN GIntBig OGRFeatureShadow_GetFieldAsInteger64(OGRFeatureShadow *self,int id){
     return OGR_F_GetFieldAsInteger64(self, id);
   }
-SWIGINTERN GIntBig OGRFeatureShadow_GetFieldAsInteger64__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          return OGR_F_GetFieldAsInteger64(self, i);
-      return 0;
-  }
-SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble__SWIG_0(OGRFeatureShadow *self,int id){
+SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble(OGRFeatureShadow *self,int id){
     return OGR_F_GetFieldAsDouble(self, id);
   }
 
@@ -2342,14 +2306,6 @@ SWIG_From_double  SWIG_PERL_DECL_ARGS_1(double value)
   return sv_2mortal(newSVnv(value));
 }
 
-SWIGINTERN double OGRFeatureShadow_GetFieldAsDouble__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          return OGR_F_GetFieldAsDouble(self, i);
-      return 0;
-  }
 
 SWIGINTERNINLINE SV *
 SWIG_From_float  SWIG_PERL_DECL_ARGS_1(float value)
@@ -2357,20 +2313,11 @@ SWIG_From_float  SWIG_PERL_DECL_ARGS_1(float value)
   return SWIG_From_double  SWIG_PERL_CALL_ARGS_1(value);
 }
 
-SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime__SWIG_0(OGRFeatureShadow *self,int id,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
+SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime(OGRFeatureShadow *self,int id,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
       OGR_F_GetFieldAsDateTimeEx(self, id, pnYear, pnMonth, pnDay,
 			       pnHour, pnMinute, pfSecond,
 			       pnTZFlag);
   }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime__SWIG_1(OGRFeatureShadow *self,char const *name,int *pnYear,int *pnMonth,int *pnDay,int *pnHour,int *pnMinute,float *pfSecond,int *pnTZFlag){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-	  OGR_F_GetFieldAsDateTimeEx(self, id, pnYear, pnMonth, pnDay,
-			       pnHour, pnMinute, pfSecond,
-			       pnTZFlag);
-  }
 
     static SV *
         CreateArrayFromIntArray( int *first, unsigned int size ) {
@@ -2382,16 +2329,9 @@ SWIGINTERN void OGRFeatureShadow_GetFieldAsDateTime__SWIG_1(OGRFeatureShadow *se
         return sv_2mortal(newRV((SV*)av));
     }
     
-SWIGINTERN void OGRFeatureShadow_GetFieldAsIntegerList__SWIG_0(OGRFeatureShadow *self,int id,int *nLen,int const **pList){
+SWIGINTERN void OGRFeatureShadow_GetFieldAsIntegerList(OGRFeatureShadow *self,int id,int *nLen,int const **pList){
       *pList = OGR_F_GetFieldAsIntegerList(self, id, nLen);
   }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsIntegerList__SWIG_1(OGRFeatureShadow *self,char const *name,int *nLen,int const **pList){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          *pList = OGR_F_GetFieldAsIntegerList(self, id, nLen);
-  }
 
 #define LENGTH_OF_GIntBig_AS_STRING 30
     static SV *
@@ -2406,26 +2346,12 @@ SWIGINTERN void OGRFeatureShadow_GetFieldAsIntegerList__SWIG_1(OGRFeatureShadow
         return sv_2mortal(newRV((SV*)av));
     }
     
-SWIGINTERN void OGRFeatureShadow_GetFieldAsInteger64List__SWIG_0(OGRFeatureShadow *self,int id,int *nLen,GIntBig const **pList){
+SWIGINTERN void OGRFeatureShadow_GetFieldAsInteger64List(OGRFeatureShadow *self,int id,int *nLen,GIntBig const **pList){
       *pList = OGR_F_GetFieldAsInteger64List(self, id, nLen);
   }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsInteger64List__SWIG_1(OGRFeatureShadow *self,char const *name,int *nLen,GIntBig const **pList){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          *pList = OGR_F_GetFieldAsInteger64List(self, id, nLen);
-  }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsDoubleList__SWIG_0(OGRFeatureShadow *self,int id,int *nLen,double const **pList){
+SWIGINTERN void OGRFeatureShadow_GetFieldAsDoubleList(OGRFeatureShadow *self,int id,int *nLen,double const **pList){
       *pList = OGR_F_GetFieldAsDoubleList(self, id, nLen);
   }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsDoubleList__SWIG_1(OGRFeatureShadow *self,char const *name,int *nLen,double const **pList){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          *pList = OGR_F_GetFieldAsDoubleList(self, id, nLen);
-  }
 
     static SV *
         CreateArrayFromStringArray( char **first ) {
@@ -2439,71 +2365,31 @@ SWIGINTERN void OGRFeatureShadow_GetFieldAsDoubleList__SWIG_1(OGRFeatureShadow *
         return sv_2mortal(newRV((SV*)av));
     }
     
-SWIGINTERN void OGRFeatureShadow_GetFieldAsStringList__SWIG_0(OGRFeatureShadow *self,int id,char ***pList){
+SWIGINTERN void OGRFeatureShadow_GetFieldAsStringList(OGRFeatureShadow *self,int id,char ***pList){
       *pList = OGR_F_GetFieldAsStringList(self, id);
   }
-SWIGINTERN void OGRFeatureShadow_GetFieldAsStringList__SWIG_1(OGRFeatureShadow *self,char const *name,char ***pList){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          *pList = OGR_F_GetFieldAsStringList(self, id);
-  }
-SWIGINTERN OGRErr OGRFeatureShadow_GetFieldAsBinary__SWIG_0(OGRFeatureShadow *self,int id,int *nLen,char **pBuf){
+SWIGINTERN OGRErr OGRFeatureShadow_GetFieldAsBinary(OGRFeatureShadow *self,int id,int *nLen,char **pBuf){
     GByte* pabyBlob = OGR_F_GetFieldAsBinary(self, id, nLen);
     *pBuf = (char*)malloc(*nLen);
     memcpy(*pBuf, pabyBlob, *nLen);
     return OGRERR_NONE;
   }
-SWIGINTERN OGRErr OGRFeatureShadow_GetFieldAsBinary__SWIG_1(OGRFeatureShadow *self,char const *name,int *nLen,char **pBuf){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-      {
-        CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-        return OGRERR_FAILURE;
-      }
-      else
-      {
-        GByte* pabyBlob = OGR_F_GetFieldAsBinary(self, id, nLen);
-        *pBuf = (char*)malloc(*nLen);
-        memcpy(*pBuf, pabyBlob, *nLen);
-        return OGRERR_NONE;
-      }
-  }
-SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_0(OGRFeatureShadow *self,int id){
+SWIGINTERN bool OGRFeatureShadow_IsFieldSet(OGRFeatureShadow *self,int id){
     return (OGR_F_IsFieldSet(self, id) > 0);
   }
-SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-	  return (OGR_F_IsFieldSet(self, i) > 0);
-      return false;
-  }
-SWIGINTERN int OGRFeatureShadow_GetFieldIndex__SWIG_0(OGRFeatureShadow *self,int i){
-      if (i < 0 || i >= OGR_F_GetFieldCount(self))
-          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
-      return i;
-  }
-SWIGINTERN int OGRFeatureShadow_GetFieldIndex__SWIG_1(OGRFeatureShadow *self,char const *name){
-      // Perl bindings let Swig handle overloaded methods. Thus they need to behave similarly.
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i < 0)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      return i;
+SWIGINTERN bool OGRFeatureShadow_IsFieldNull(OGRFeatureShadow *self,int id){
+    return (OGR_F_IsFieldNull(self, id) > 0);
   }
-SWIGINTERN int OGRFeatureShadow_GetGeomFieldIndex__SWIG_0(OGRFeatureShadow *self,int i){
-      if (i < 0 || i >= OGR_F_GetGeomFieldCount(self))
-          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
-      return i;
+SWIGINTERN bool OGRFeatureShadow_IsFieldSetAndNotNull(OGRFeatureShadow *self,int id){
+    return (OGR_F_IsFieldSetAndNotNull(self, id) > 0);
   }
-SWIGINTERN int OGRFeatureShadow_GetGeomFieldIndex__SWIG_1(OGRFeatureShadow *self,char const *name){
-      // Perl bindings let Swig handle overloaded methods. Thus they need to behave similarly.
-      int i = OGR_F_GetGeomFieldIndex(self, name);
-      if (i < 0)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      return i;
+SWIGINTERN int OGRFeatureShadow_GetFieldIndex(OGRFeatureShadow *self,char const *name){
+      // Do not issue an error if the field doesn't exist. It is intended to be silent
+      return OGR_F_GetFieldIndex(self, name);
+  }
+SWIGINTERN int OGRFeatureShadow_GetGeomFieldIndex(OGRFeatureShadow *self,char const *name){
+      // Do not issue an error if the field doesn't exist. It is intended to be silent
+      return OGR_F_GetGeomFieldIndex(self, name);
   }
 SWIGINTERN GIntBig OGRFeatureShadow_GetFID(OGRFeatureShadow *self){
     return OGR_F_GetFID(self);
@@ -2514,49 +2400,24 @@ SWIGINTERN OGRErr OGRFeatureShadow_SetFID(OGRFeatureShadow *self,GIntBig fid){
 SWIGINTERN void OGRFeatureShadow_DumpReadable(OGRFeatureShadow *self){
     OGR_F_DumpReadable(self, NULL);
   }
-SWIGINTERN void OGRFeatureShadow_UnsetField__SWIG_0(OGRFeatureShadow *self,int id){
+SWIGINTERN void OGRFeatureShadow_UnsetField(OGRFeatureShadow *self,int id){
     OGR_F_UnsetField(self, id);
   }
-SWIGINTERN void OGRFeatureShadow_UnsetField__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_UnsetField(self, i);
+SWIGINTERN void OGRFeatureShadow_SetFieldNull(OGRFeatureShadow *self,int id){
+    OGR_F_SetFieldNull(self, id);
   }
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_0(OGRFeatureShadow *self,int id,char const *value){
     OGR_F_SetFieldString(self, id, value);
   }
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_1(OGRFeatureShadow *self,char const *name,char const *value){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_SetFieldString(self, i, value);
-  }
 SWIGINTERN void OGRFeatureShadow_SetFieldInteger64(OGRFeatureShadow *self,int id,GIntBig value){
     OGR_F_SetFieldInteger64(self, id, value);
   }
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_2(OGRFeatureShadow *self,int id,int value){
+SWIGINTERN void OGRFeatureShadow_SetField__SWIG_1(OGRFeatureShadow *self,int id,int value){
     OGR_F_SetFieldInteger(self, id, value);
   }
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_3(OGRFeatureShadow *self,char const *name,int value){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-	  OGR_F_SetFieldInteger(self, i, value);
-  }
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_4(OGRFeatureShadow *self,int id,double value){
+SWIGINTERN void OGRFeatureShadow_SetField__SWIG_2(OGRFeatureShadow *self,int id,double value){
     OGR_F_SetFieldDouble(self, id, value);
   }
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_5(OGRFeatureShadow *self,char const *name,double value){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-	  OGR_F_SetFieldDouble(self, i, value);
-  }
 
 /* Getting isfinite working pre C99 across multiple platforms is non-trivial. Users can provide SWIG_isfinite on older platforms. */
 #ifndef SWIG_isfinite
@@ -2594,88 +2455,32 @@ SWIG_AsVal_float SWIG_PERL_DECL_ARGS_2(SV * obj, float *val)
   return res;
 }
 
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_6(OGRFeatureShadow *self,int id,int year,int month,int day,int hour,int minute,float second,int tzflag){
+SWIGINTERN void OGRFeatureShadow_SetField__SWIG_3(OGRFeatureShadow *self,int id,int year,int month,int day,int hour,int minute,float second,int tzflag){
     OGR_F_SetFieldDateTimeEx(self, id, year, month, day,
                              hour, minute, second,
                              tzflag);
   }
-SWIGINTERN void OGRFeatureShadow_SetField__SWIG_7(OGRFeatureShadow *self,char const *name,int year,int month,int day,int hour,int minute,float second,int tzflag){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-	  OGR_F_SetFieldDateTimeEx(self, i, year, month, day,
-				 hour, minute, second,
-				 tzflag);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldIntegerList__SWIG_0(OGRFeatureShadow *self,int id,int nList,int *pList){
+SWIGINTERN void OGRFeatureShadow_SetFieldIntegerList(OGRFeatureShadow *self,int id,int nList,int *pList){
       OGR_F_SetFieldIntegerList(self, id, nList, pList);
   }
-SWIGINTERN void OGRFeatureShadow_SetFieldIntegerList__SWIG_1(OGRFeatureShadow *self,char const *name,int nList,int *pList){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-       	  OGR_F_SetFieldIntegerList(self, id, nList, pList);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldInteger64List__SWIG_0(OGRFeatureShadow *self,int id,int nList,GIntBig *pList){
+SWIGINTERN void OGRFeatureShadow_SetFieldInteger64List(OGRFeatureShadow *self,int id,int nList,GIntBig *pList){
       OGR_F_SetFieldInteger64List(self, id, nList, pList);
   }
-SWIGINTERN void OGRFeatureShadow_SetFieldInteger64List__SWIG_1(OGRFeatureShadow *self,char const *name,int nList,GIntBig *pList){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_SetFieldInteger64List(self, id, nList, pList);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldDoubleList__SWIG_0(OGRFeatureShadow *self,int id,int nList,double *pList){
+SWIGINTERN void OGRFeatureShadow_SetFieldDoubleList(OGRFeatureShadow *self,int id,int nList,double *pList){
       OGR_F_SetFieldDoubleList(self, id, nList, pList);
   }
-SWIGINTERN void OGRFeatureShadow_SetFieldDoubleList__SWIG_1(OGRFeatureShadow *self,char const *name,int nList,double *pList){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_SetFieldDoubleList(self, id, nList, pList);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldStringList__SWIG_0(OGRFeatureShadow *self,int id,char **pList){
+SWIGINTERN void OGRFeatureShadow_SetFieldStringList(OGRFeatureShadow *self,int id,char **pList){
       OGR_F_SetFieldStringList(self, id, pList);
   }
-SWIGINTERN void OGRFeatureShadow_SetFieldStringList__SWIG_1(OGRFeatureShadow *self,char const *name,char **pList){
-      int id = OGR_F_GetFieldIndex(self, name);
-      if (id == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_SetFieldStringList(self, id, pList);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldBinary__SWIG_0(OGRFeatureShadow *self,int i,int nBytes,GByte *pabyBuf){
+SWIGINTERN void OGRFeatureShadow_SetFieldBinary(OGRFeatureShadow *self,int i,int nBytes,GByte *pabyBuf){
       OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
   }
-SWIGINTERN void OGRFeatureShadow_SetFieldBinary__SWIG_1(OGRFeatureShadow *self,char const *name,int nBytes,GByte *pabyBuf){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
-  }
-SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(OGRFeatureShadow *self,int id,char const *pszValue){
+SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString(OGRFeatureShadow *self,int id,char const *pszValue){
      int nBytes;
      GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
      OGR_F_SetFieldBinary(self, id, nBytes, pabyBuf);
      CPLFree(pabyBuf);
   }
-SWIGINTERN void OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(OGRFeatureShadow *self,char const *name,char const *pszValue){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-      {
-          int nBytes;
-          GByte* pabyBuf = CPLHexToBinary(pszValue, &nBytes );
-          OGR_F_SetFieldBinary(self, i, nBytes, pabyBuf);
-          CPLFree(pabyBuf);
-      }
-  }
 SWIGINTERN OGRErr OGRFeatureShadow_SetFrom(OGRFeatureShadow *self,OGRFeatureShadow *other,int forgiving=1){
     return OGR_F_SetFrom(self, other, forgiving);
   }
@@ -2694,21 +2499,13 @@ SWIGINTERN char const *OGRFeatureShadow_GetStyleString(OGRFeatureShadow *self){
 SWIGINTERN void OGRFeatureShadow_SetStyleString(OGRFeatureShadow *self,char const *the_string){
     OGR_F_SetStyleString(self, the_string);
   }
-SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_0(OGRFeatureShadow *self,int id){
+SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType(OGRFeatureShadow *self,int id){
       OGRFieldDefnH fd = OGR_F_GetFieldDefnRef( self,  id );
       if (fd)
           return (OGRFieldType) OGR_Fld_GetType( fd );
       else
           return (OGRFieldType)0;
   }
-SWIGINTERN OGRFieldType OGRFeatureShadow_GetFieldType__SWIG_1(OGRFeatureShadow *self,char const *name){
-      int i = OGR_F_GetFieldIndex(self, name);
-      if (i == -1) {
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-          return (OGRFieldType)0;
-      } else
-          return (OGRFieldType) OGR_Fld_GetType( OGR_F_GetFieldDefnRef( self, i ) );
-  }
 SWIGINTERN int OGRFeatureShadow_Validate(OGRFeatureShadow *self,int flags=OGR_F_VAL_ALL,int bEmitError=TRUE){
     return OGR_F_Validate(self, flags, bEmitError);
   }
@@ -2745,6 +2542,11 @@ SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char
             case wkbCurvePolygon:
             case wkbMultiCurve:
             case wkbMultiSurface:
+            case wkbCurve:
+            case wkbSurface:
+            case wkbTriangle:
+            case wkbTIN:
+            case wkbPolyhedralSurface:
             case wkbNone:
             /*case wkbLinearRing:*/
             case wkbCircularStringZ:
@@ -2752,6 +2554,11 @@ SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char
             case wkbCurvePolygonZ:
             case wkbMultiCurveZ:
             case wkbMultiSurfaceZ:
+            case wkbCurveZ:
+            case wkbSurfaceZ:
+            case wkbTriangleZ:
+            case wkbTINZ:
+            case wkbPolyhedralSurfaceZ:
             case wkbPoint25D:
             case wkbLineString25D:
             case wkbPolygon25D:
@@ -2771,6 +2578,11 @@ SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char
             case wkbCurvePolygonM:
             case wkbMultiCurveM:
             case wkbMultiSurfaceM:
+            case wkbCurveM:
+            case wkbSurfaceM:
+            case wkbTriangleM:
+            case wkbTINM:
+            case wkbPolyhedralSurfaceM:
             case wkbPointZM:
             case wkbLineStringZM:
             case wkbPolygonZM:
@@ -2783,6 +2595,11 @@ SWIGINTERN void OGRFeatureShadow_SetNativeMediaType(OGRFeatureShadow *self,char
             case wkbCurvePolygonZM:
             case wkbMultiCurveZM:
             case wkbMultiSurfaceZM:
+            case wkbCurveZM:
+            case wkbSurfaceZM:
+            case wkbTriangleZM:
+            case wkbTINZM:
+            case wkbPolyhedralSurfaceZM:
                 return TRUE;
             default:
                 CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
@@ -2808,12 +2625,7 @@ SWIGINTERN int OGRFeatureDefnShadow_GetFieldCount(OGRFeatureDefnShadow *self){
 SWIGINTERN OGRFieldDefnShadow *OGRFeatureDefnShadow_GetFieldDefn(OGRFeatureDefnShadow *self,int i){
     return (OGRFieldDefnShadow*) OGR_FD_GetFieldDefn(self, i);
   }
-SWIGINTERN int OGRFeatureDefnShadow_GetFieldIndex__SWIG_0(OGRFeatureDefnShadow *self,int i){
-      if (i < 0 || i >= OGR_FD_GetFieldCount(self))
-          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
-      return i;
-  }
-SWIGINTERN int OGRFeatureDefnShadow_GetFieldIndex__SWIG_1(OGRFeatureDefnShadow *self,char const *name){
+SWIGINTERN int OGRFeatureDefnShadow_GetFieldIndex(OGRFeatureDefnShadow *self,char const *name){
       // Do not issue an error if the field doesn't exist. It is intended to be silent
       return OGR_FD_GetFieldIndex(self, name);
   }
@@ -2823,23 +2635,10 @@ SWIGINTERN void OGRFeatureDefnShadow_AddFieldDefn(OGRFeatureDefnShadow *self,OGR
 SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldCount(OGRFeatureDefnShadow *self){
     return OGR_FD_GetGeomFieldCount(self);
   }
-SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureDefnShadow_GetGeomFieldDefn__SWIG_0(OGRFeatureDefnShadow *self,int i){
+SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureDefnShadow_GetGeomFieldDefn(OGRFeatureDefnShadow *self,int i){
     return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, i);
   }
-SWIGINTERN OGRGeomFieldDefnShadow *OGRFeatureDefnShadow_GetGeomFieldDefn__SWIG_1(OGRFeatureDefnShadow *self,char const *name){
-      int iField = OGR_FD_GetGeomFieldIndex(self, name);
-      if (iField == -1)
-          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
-      else
-          return (OGRGeomFieldDefnShadow*) OGR_FD_GetGeomFieldDefn(self, iField);
-      return NULL;
-  }
-SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldIndex__SWIG_0(OGRFeatureDefnShadow *self,int i){
-      if (i < 0 || i >= OGR_FD_GetGeomFieldCount(self))
-          CPLError(CE_Failure, 1, FIELD_INDEX_ERROR_TMPL, i);
-      return i;
-  }
-SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldIndex__SWIG_1(OGRFeatureDefnShadow *self,char const *name){
+SWIGINTERN int OGRFeatureDefnShadow_GetGeomFieldIndex(OGRFeatureDefnShadow *self,char const *name){
       // Do not issue an error if the field doesn't exist. It is intended to be silent
       return OGR_FD_GetGeomFieldIndex(self, name);
   }
@@ -3328,6 +3127,9 @@ SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SymmetricDifference(OGRGeometryS
 SWIGINTERN double OGRGeometryShadow_Distance(OGRGeometryShadow *self,OGRGeometryShadow *other){
     return OGR_G_Distance(self, other);
   }
+SWIGINTERN double OGRGeometryShadow_Distance3D(OGRGeometryShadow *self,OGRGeometryShadow *other){
+    return OGR_G_Distance3D(self, other);
+  }
 SWIGINTERN void OGRGeometryShadow_Empty(OGRGeometryShadow *self){
     OGR_G_Empty(self);
   }
@@ -3774,14 +3576,14 @@ XS(_wrap_StyleTable_LoadStyleTable) {
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -3845,14 +3647,14 @@ XS(_wrap_StyleTable_SaveStyleTable) {
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* utf8_path) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -5646,7 +5448,7 @@ XS(_wrap_Layer_GetFeatureCount) {
     }
     {
       char temp[256];
-      sprintf(temp, ""CPL_FRMT_GIB"", result);
+      sprintf(temp, "" CPL_FRMT_GIB "", result);
       ST(argvi) = sv_2mortal(newSVpv(temp, 0));
       argvi++;
     }
@@ -6651,7 +6453,7 @@ XS(_wrap_Layer_GetFeaturesRead) {
     }
     {
       char temp[256];
-      sprintf(temp, ""CPL_FRMT_GIB"", result);
+      sprintf(temp, "" CPL_FRMT_GIB "", result);
       ST(argvi) = sv_2mortal(newSVpv(temp, 0));
       argvi++;
     }
@@ -6690,9 +6492,10 @@ XS(_wrap_Layer_SetIgnoredFields) {
             AV *av = (AV*)(SvRV(ST(1)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddString(arg2, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(1));
@@ -6702,9 +6505,10 @@ XS(_wrap_Layer_SetIgnoredFields) {
             arg2 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddNameValue(arg2, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -6811,9 +6615,10 @@ XS(_wrap_Layer_Intersection) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -6823,9 +6628,10 @@ XS(_wrap_Layer_Intersection) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -6963,9 +6769,10 @@ XS(_wrap_Layer_Union) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -6975,9 +6782,10 @@ XS(_wrap_Layer_Union) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -7115,9 +6923,10 @@ XS(_wrap_Layer_SymDifference) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -7127,9 +6936,10 @@ XS(_wrap_Layer_SymDifference) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -7267,9 +7077,10 @@ XS(_wrap_Layer_Identity) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -7279,9 +7090,10 @@ XS(_wrap_Layer_Identity) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -7419,9 +7231,10 @@ XS(_wrap_Layer_Update) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -7431,9 +7244,10 @@ XS(_wrap_Layer_Update) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -7571,9 +7385,10 @@ XS(_wrap_Layer_Clip) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -7583,9 +7398,10 @@ XS(_wrap_Layer_Clip) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -7723,9 +7539,10 @@ XS(_wrap_Layer_Erase) {
               AV *av = (AV*)(SvRV(ST(3)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddString(arg4, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(3)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(3));
@@ -7735,9 +7552,10 @@ XS(_wrap_Layer_Erase) {
               arg4 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg4 = CSLAddNameValue(arg4, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -8441,7 +8259,7 @@ XS(_wrap_Feature_SetGeomField__SWIG_1) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -8449,7 +8267,7 @@ XS(_wrap_Feature_SetGeomField__SWIG_1) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -8700,7 +8518,7 @@ XS(_wrap_Feature_SetGeomFieldDirectly__SWIG_1) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -8708,7 +8526,7 @@ XS(_wrap_Feature_SetGeomFieldDirectly__SWIG_1) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -8931,14 +8749,14 @@ XS(_wrap_Feature_GetGeomFieldRef__SWIG_1) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -9193,7 +9011,7 @@ XS(_wrap_Feature_GetFieldCount) {
 }
 
 
-XS(_wrap_Feature_GetFieldDefnRef__SWIG_0) {
+XS(_wrap_Feature_GetFieldDefnRef) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
@@ -9220,7 +9038,7 @@ XS(_wrap_Feature_GetFieldDefnRef__SWIG_0) {
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
+      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -9254,37 +9072,26 @@ XS(_wrap_Feature_GetFieldDefnRef__SWIG_0) {
 }
 
 
-XS(_wrap_Feature_GetFieldDefnRef__SWIG_1) {
+XS(_wrap_Feature_GetGeomFieldCount) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
     int argvi = 0;
-    OGRFieldDefnShadow *result = 0 ;
+    int result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldDefnRef(self,name);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_GetGeomFieldCount(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
       CPLErrorReset();
-      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+      result = (int)OGRFeatureShadow_GetGeomFieldCount(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -9306,124 +9113,44 @@ XS(_wrap_Feature_GetFieldDefnRef__SWIG_1) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldDefnRef) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldDefnRef__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldDefnRef__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldDefnRef'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetGeomFieldCount) {
+XS(_wrap_Feature_GetGeomFieldDefnRef) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    int result;
+    OGRGeomFieldDefnShadow *result = 0 ;
     dXSARGS;
     
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldCount(self);");
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetGeomFieldDefnRef(self,id);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetGeomFieldCount(arg1);
+      result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -9445,17 +9172,19 @@ XS(_wrap_Feature_GetGeomFieldCount) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    
     
     XSRETURN(argvi);
   fail:
     
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_0) {
+XS(_wrap_Feature_GetFieldAsString) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
@@ -9464,25 +9193,25 @@ XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_0) {
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
-    OGRGeomFieldDefnShadow *result = 0 ;
+    char *result = 0 ;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldDefnRef(self,id);");
+      SWIG_croak("Usage: Feature_GetFieldAsString(self,id);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsString" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(arg1,arg2);
+      result = (char *)OGRFeatureShadow_GetFieldAsString(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -9504,7 +9233,13 @@ XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_0) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    {
+      /* %typemap(out) const char * */
+      ST(argvi) = newSVpv(result, 0);
+      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
+      sv_2mortal(ST(argvi));
+      argvi++;
+    }
     
     
     XSRETURN(argvi);
@@ -9516,37 +9251,34 @@ XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_0) {
 }
 
 
-XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_1) {
+XS(_wrap_Feature_GetFieldAsInteger) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    OGRGeomFieldDefnShadow *result = 0 ;
+    int result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldDefnRef(self,name);");
+      SWIG_croak("Usage: Feature_GetFieldAsInteger(self,id);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldDefnRef" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+      result = (int)OGRFeatureShadow_GetFieldAsInteger(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -9568,105 +9300,19 @@ XS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_1) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeomFieldDefnRef) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
     
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldDefnRef__SWIG_1); return;
-    }
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_GetGeomFieldDefnRef'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_GetFieldAsString__SWIG_0) {
+XS(_wrap_Feature_GetFieldAsInteger64) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
@@ -9675,25 +9321,25 @@ XS(_wrap_Feature_GetFieldAsString__SWIG_0) {
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
+    GIntBig result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsString(self,id);");
+      SWIG_croak("Usage: Feature_GetFieldAsInteger64(self,id);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger64" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsString" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger64" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_0(arg1,arg2);
+      result = OGRFeatureShadow_GetFieldAsInteger64(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -9716,10 +9362,9 @@ XS(_wrap_Feature_GetFieldAsString__SWIG_0) {
       
     }
     {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
+      char temp[256];
+      sprintf(temp, "" CPL_FRMT_GIB "", result);
+      ST(argvi) = sv_2mortal(newSVpv(temp, 0));
       argvi++;
     }
     
@@ -9733,37 +9378,34 @@ XS(_wrap_Feature_GetFieldAsString__SWIG_0) {
 }
 
 
-XS(_wrap_Feature_GetFieldAsString__SWIG_1) {
+XS(_wrap_Feature_GetFieldAsDouble) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    char *result = 0 ;
+    double result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsString(self,name);");
+      SWIG_croak("Usage: Feature_GetFieldAsDouble(self,id);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDouble" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_1(arg1,(char const *)arg2);
+      result = (double)OGRFeatureShadow_GetFieldAsDouble(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -9785,138 +9427,73 @@ XS(_wrap_Feature_GetFieldAsString__SWIG_1) {
       
       
     }
-    {
-      /* %typemap(out) const char * */
-      ST(argvi) = newSVpv(result, 0);
-      SvUTF8_on(ST(argvi)); /* expecting GDAL to give us UTF-8 */
-      sv_2mortal(ST(argvi));
-      argvi++;
-    }
+    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
+    
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsString) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
     
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsString__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsString__SWIG_1); return;
-    }
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsString'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_GetFieldAsInteger__SWIG_0) {
+XS(_wrap_Feature_GetFieldAsDateTime) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
+    int *arg3 = (int *) 0 ;
+    int *arg4 = (int *) 0 ;
+    int *arg5 = (int *) 0 ;
+    int *arg6 = (int *) 0 ;
+    int *arg7 = (int *) 0 ;
+    float *arg8 = (float *) 0 ;
+    int *arg9 = (int *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsInteger(self,id);");
-    }
+    int temp3 ;
+    int res3 = SWIG_TMPOBJ ;
+    int temp4 ;
+    int res4 = SWIG_TMPOBJ ;
+    int temp5 ;
+    int res5 = SWIG_TMPOBJ ;
+    int temp6 ;
+    int res6 = SWIG_TMPOBJ ;
+    int temp7 ;
+    int res7 = SWIG_TMPOBJ ;
+    float temp8 ;
+    int res8 = SWIG_TMPOBJ ;
+    int temp9 ;
+    int res9 = SWIG_TMPOBJ ;
+    int argvi = 0;
+    dXSARGS;
+    
+    arg3 = &temp3;
+    arg4 = &temp4;
+    arg5 = &temp5;
+    arg6 = &temp6;
+    arg7 = &temp7;
+    arg8 = &temp8;
+    arg9 = &temp9;
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsDateTime(self,id);");
+    }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDateTime" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDateTime" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_0(arg1,arg2);
+      OGRFeatureShadow_GetFieldAsDateTime(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -9938,49 +9515,112 @@ XS(_wrap_Feature_GetFieldAsInteger__SWIG_0) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    {
+      /* %typemap(out) void */
+    }
+    if (SWIG_IsTmpObj(res3)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res4)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res5)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res6)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg6)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res7)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg7)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res8)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_float  SWIG_PERL_CALL_ARGS_1((*arg8)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_float, new_flags); argvi++  ;
+    }
+    if (SWIG_IsTmpObj(res9)) {
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg9)); argvi++  ;
+    } else {
+      int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN | 0) : 0;
+      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags); argvi++  ;
+    }
+    
+    
+    
+    
+    
+    
+    
     
     
     XSRETURN(argvi);
   fail:
     
     
+    
+    
+    
+    
+    
+    
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsInteger__SWIG_1) {
+XS(_wrap_Feature_GetFieldAsIntegerList) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    int arg2 ;
+    int *arg3 = (int *) 0 ;
+    int **arg4 = (int **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int nLen3 ;
+    int *pList3 ;
     int argvi = 0;
-    int result;
     dXSARGS;
     
+    {
+      /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) */
+      arg3 = &nLen3;
+      arg4 = &pList3;
+    }
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsInteger(self,name);");
+      SWIG_croak("Usage: Feature_GetFieldAsIntegerList(self,id,pList);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_1(arg1,(char const *)arg2);
+      OGRFeatureShadow_GetFieldAsIntegerList(arg1,arg2,arg3,(int const **)arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -10002,132 +9642,61 @@ XS(_wrap_Feature_GetFieldAsInteger__SWIG_1) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
     {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      /* %typemap(out) void */
     }
-    XSRETURN(argvi);
-  fail:
-    
     {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsInteger) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
+      /* %typemap(argout) (int *nLen, const int **pList) */
+      ST(argvi) = CreateArrayFromIntArray( *(arg4), *(arg3) );
+      argvi++;
     }
-  check_1:
     
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
     
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsInteger__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsInteger__SWIG_1); return;
-    }
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsInteger'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_GetFieldAsInteger64__SWIG_0) {
+XS(_wrap_Feature_GetFieldAsInteger64List) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
+    int *arg3 = (int *) 0 ;
+    GIntBig **arg4 = (GIntBig **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
+    int nLen3 ;
+    GIntBig *pList3 ;
     int argvi = 0;
-    GIntBig result;
     dXSARGS;
     
+    {
+      /* %typemap(in,numinputs=0) (int *nLen3, const GIntBig **pList3) */
+      arg3 = &nLen3;
+      arg4 = &pList3;
+    }
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsInteger64(self,id);");
+      SWIG_croak("Usage: Feature_GetFieldAsInteger64List(self,id,pList);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger64" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger64List" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger64" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger64List" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = OGRFeatureShadow_GetFieldAsInteger64__SWIG_0(arg1,arg2);
+      OGRFeatureShadow_GetFieldAsInteger64List(arg1,arg2,arg3,(GIntBig const **)arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -10150,9 +9719,11 @@ XS(_wrap_Feature_GetFieldAsInteger64__SWIG_0) {
       
     }
     {
-      char temp[256];
-      sprintf(temp, ""CPL_FRMT_GIB"", result);
-      ST(argvi) = sv_2mortal(newSVpv(temp, 0));
+      /* %typemap(out) void */
+    }
+    {
+      /* %typemap(argout) (int *nLen, const GIntBig **pList) */
+      ST(argvi) = CreateArrayFromGIntBigArray( *(arg4), *(arg3) );
       argvi++;
     }
     
@@ -10166,37 +9737,42 @@ XS(_wrap_Feature_GetFieldAsInteger64__SWIG_0) {
 }
 
 
-XS(_wrap_Feature_GetFieldAsInteger64__SWIG_1) {
+XS(_wrap_Feature_GetFieldAsDoubleList) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    int arg2 ;
+    int *arg3 = (int *) 0 ;
+    double **arg4 = (double **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int nLen3 ;
+    double *pList3 ;
     int argvi = 0;
-    GIntBig result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsInteger64(self,name);");
+    {
+      /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) */
+      arg3 = &nLen3;
+      arg4 = &pList3;
+    }
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsDoubleList(self,id,pList);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger64" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = OGRFeatureShadow_GetFieldAsInteger64__SWIG_1(arg1,(char const *)arg2);
+      OGRFeatureShadow_GetFieldAsDoubleList(arg1,arg2,arg3,(double const **)arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -10219,136 +9795,136 @@ XS(_wrap_Feature_GetFieldAsInteger64__SWIG_1) {
       
     }
     {
-      char temp[256];
-      sprintf(temp, ""CPL_FRMT_GIB"", result);
-      ST(argvi) = sv_2mortal(newSVpv(temp, 0));
-      argvi++;
+      /* %typemap(out) void */
     }
-    
     {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      /* %typemap(argout) (int *nLen, const double **pList) */
+      ST(argvi) = CreateArrayFromDoubleArray( *(arg4), *(arg3) );
+      argvi++;
     }
+    
+    
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsInteger64) {
-  dXSARGS;
-  
+XS(_wrap_Feature_GetFieldAsStringList) {
   {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    char ***arg3 = (char ***) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    char **pList3 ;
+    int argvi = 0;
+    dXSARGS;
     
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
+    {
+      /* %typemap(in,numinputs=0) (char ***pList3) */
+      arg3 = &pList3;
+    }
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_GetFieldAsStringList(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsStringList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_GetFieldAsStringList(arg1,arg2,arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
       }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
+      
+      
     }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsInteger64__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsInteger64__SWIG_1); return;
+    {
+      /* %typemap(out) void */
+    }
+    {
+      /* %typemap(argout) (char ***pList) */
+      ST(argvi) = CreateArrayFromStringArray( *(arg3) );
+      argvi++;
     }
+    
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsInteger64'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_GetFieldAsDouble__SWIG_0) {
+XS(_wrap_Feature_GetFieldAsBinary) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
+    int *arg3 = (int *) 0 ;
+    char **arg4 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
+    int nLen3 = 0 ;
+    char *pBuf3 = 0 ;
     int argvi = 0;
-    double result;
+    OGRErr result;
     dXSARGS;
     
+    {
+      /* %typemap(in,numinputs=0) (int *nLen3, char **pBuf3 ) */
+      arg3 = &nLen3;
+      arg4 = &pBuf3;
+    }
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDouble(self,id);");
+      SWIG_croak("Usage: Feature_GetFieldAsBinary(self,id,pBuf);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsBinary" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDouble" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsBinary" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_0(arg1,arg2);
+      result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary(arg1,arg2,arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -10370,49 +9946,70 @@ XS(_wrap_Feature_GetFieldAsDouble__SWIG_0) {
       
       
     }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
+    {
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) do_confess(err, 0); /* this is usually better */
+        do_confess( OGRErrMessages(result), 1 );
+      }
+    }
+    {
+      /* %typemap(argout) (int *nLen, char **pBuf ) */
+      ST(argvi) = sv_2mortal(newSVpv( *arg4, *arg3 ));
+      argvi++;
+    }
     
     
+    {
+      /* %typemap(freearg) (int *nLen, char **pBuf ) */
+      if( *arg3 ) {
+        free( *arg4 );
+      }
+    }
     XSRETURN(argvi);
   fail:
     
     
+    {
+      /* %typemap(freearg) (int *nLen, char **pBuf ) */
+      if( *arg3 ) {
+        free( *arg4 );
+      }
+    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsDouble__SWIG_1) {
+XS(_wrap_Feature_IsFieldSet) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
-    double result;
+    bool result;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDouble(self,name);");
+      SWIG_croak("Usage: Feature_IsFieldSet(self,id);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDouble" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldSet" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_1(arg1,(char const *)arg2);
+      result = (bool)OGRFeatureShadow_IsFieldSet(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -10434,159 +10031,107 @@ XS(_wrap_Feature_GetFieldAsDouble__SWIG_1) {
       
       
     }
-    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
+    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+    
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsDouble) {
-  dXSARGS;
-  
+XS(_wrap_Feature_IsFieldNull) {
   {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    bool result;
+    dXSARGS;
     
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature_IsFieldNull(self,id);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldNull" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldNull" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      CPLErrorReset();
+      result = (bool)OGRFeatureShadow_IsFieldNull(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
       }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
+      
+      
     }
-  check_2:
+    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
     
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsDouble__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsDouble__SWIG_1); return;
-    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsDouble'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_GetFieldAsDateTime__SWIG_0) {
+XS(_wrap_Feature_IsFieldSetAndNotNull) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
-    int *arg3 = (int *) 0 ;
-    int *arg4 = (int *) 0 ;
-    int *arg5 = (int *) 0 ;
-    int *arg6 = (int *) 0 ;
-    int *arg7 = (int *) 0 ;
-    float *arg8 = (float *) 0 ;
-    int *arg9 = (int *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
-    int temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    int temp4 ;
-    int res4 = SWIG_TMPOBJ ;
-    int temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    int temp6 ;
-    int res6 = SWIG_TMPOBJ ;
-    int temp7 ;
-    int res7 = SWIG_TMPOBJ ;
-    float temp8 ;
-    int res8 = SWIG_TMPOBJ ;
-    int temp9 ;
-    int res9 = SWIG_TMPOBJ ;
     int argvi = 0;
+    bool result;
     dXSARGS;
     
-    arg3 = &temp3;
-    arg4 = &temp4;
-    arg5 = &temp5;
-    arg6 = &temp6;
-    arg7 = &temp7;
-    arg8 = &temp8;
-    arg9 = &temp9;
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDateTime(self,id);");
+      SWIG_croak("Usage: Feature_IsFieldSetAndNotNull(self,id);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDateTime" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSetAndNotNull" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDateTime" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldSetAndNotNull" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsDateTime__SWIG_0(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      result = (bool)OGRFeatureShadow_IsFieldSetAndNotNull(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -10608,120 +10153,35 @@ XS(_wrap_Feature_GetFieldAsDateTime__SWIG_0) {
       
       
     }
-    {
-      /* %typemap(out) void */
-    }
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res4)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res6)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg6)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res7)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg7)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res8)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_float  SWIG_PERL_CALL_ARGS_1((*arg8)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_float, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res9)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg9)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    
-    
-    
-    
-    
-    
-    
+    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
     
     
     XSRETURN(argvi);
   fail:
     
     
-    
-    
-    
-    
-    
-    
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsDateTime__SWIG_1) {
+XS(_wrap_Feature__GetFieldIndex) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     char *arg2 = (char *) 0 ;
-    int *arg3 = (int *) 0 ;
-    int *arg4 = (int *) 0 ;
-    int *arg5 = (int *) 0 ;
-    int *arg6 = (int *) 0 ;
-    int *arg7 = (int *) 0 ;
-    float *arg8 = (float *) 0 ;
-    int *arg9 = (int *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     U8 *tmpbuf2 = NULL ;
-    int temp3 ;
-    int res3 = SWIG_TMPOBJ ;
-    int temp4 ;
-    int res4 = SWIG_TMPOBJ ;
-    int temp5 ;
-    int res5 = SWIG_TMPOBJ ;
-    int temp6 ;
-    int res6 = SWIG_TMPOBJ ;
-    int temp7 ;
-    int res7 = SWIG_TMPOBJ ;
-    float temp8 ;
-    int res8 = SWIG_TMPOBJ ;
-    int temp9 ;
-    int res9 = SWIG_TMPOBJ ;
     int argvi = 0;
+    int result;
     dXSARGS;
     
-    arg3 = &temp3;
-    arg4 = &temp4;
-    arg5 = &temp5;
-    arg6 = &temp6;
-    arg7 = &temp7;
-    arg8 = &temp8;
-    arg9 = &temp9;
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDateTime(self,name);");
+      SWIG_croak("Usage: Feature__GetFieldIndex(self,name);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDateTime" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     {
@@ -10735,7 +10195,7 @@ XS(_wrap_Feature_GetFieldAsDateTime__SWIG_1) {
     }
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsDateTime__SWIG_1(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -10757,198 +10217,114 @@ XS(_wrap_Feature_GetFieldAsDateTime__SWIG_1) {
       
       
     }
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    
     {
-      /* %typemap(out) void */
-    }
-    if (SWIG_IsTmpObj(res3)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg3)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res3) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg3), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res4)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg4)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res4) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg4), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res5)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg5)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res5) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg5), SWIGTYPE_p_int, new_flags); argvi++  ;
+      /* %typemap(freearg) (const char* name) */
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
-    if (SWIG_IsTmpObj(res6)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg6)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res6) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg6), SWIGTYPE_p_int, new_flags); argvi++  ;
+    XSRETURN(argvi);
+  fail:
+    
+    {
+      /* %typemap(freearg) (const char* name) */
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
-    if (SWIG_IsTmpObj(res7)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg7)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res8)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_float  SWIG_PERL_CALL_ARGS_1((*arg8)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res8) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg8), SWIGTYPE_p_float, new_flags); argvi++  ;
-    }
-    if (SWIG_IsTmpObj(res9)) {
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1((*arg9)); argvi++  ;
-    } else {
-      int new_flags = SWIG_IsNewObj(res9) ? (SWIG_POINTER_OWN | 0) : 0;
-      if (argvi >= items) EXTEND(sp,1);  ST(argvi) = SWIG_NewPointerObj((void*)(arg9), SWIGTYPE_p_int, new_flags); argvi++  ;
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    
-    
-    
-    
-    
-    
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsDateTime) {
-  dXSARGS;
-  
+XS(_wrap_Feature__GetGeomFieldIndex) {
   {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    U8 *tmpbuf2 = NULL ;
+    int argvi = 0;
+    int result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Feature__GetGeomFieldIndex(self,name);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    {
+      /* %typemap(in,numinputs=1) (const char* name) */
+      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
+    }
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
       }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
+    }
+    {
+      CPLErrorReset();
+      result = (int)OGRFeatureShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
       }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
+      
+      
     }
-  check_1:
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
+    {
+      /* %typemap(freearg) (const char* name) */
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
-  check_2:
+    XSRETURN(argvi);
+  fail:
     
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsDateTime__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsDateTime__SWIG_1); return;
+    {
+      /* %typemap(freearg) (const char* name) */
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsDateTime'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_GetFieldAsIntegerList__SWIG_0) {
+XS(_wrap_Feature_GetFID) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    int **arg4 = (int **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int nLen3 ;
-    int *pList3 ;
     int argvi = 0;
+    GIntBig result;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsIntegerList(self,id,pList);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_GetFID(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsIntegerList__SWIG_0(arg1,arg2,arg3,(int const **)arg4);
+      result = OGRFeatureShadow_GetFID(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -10971,63 +10347,44 @@ XS(_wrap_Feature_GetFieldAsIntegerList__SWIG_0) {
       
     }
     {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (int *nLen, const int **pList) */
-      ST(argvi) = CreateArrayFromIntArray( *(arg4), *(arg3) );
+      char temp[256];
+      sprintf(temp, "" CPL_FRMT_GIB "", result);
+      ST(argvi) = sv_2mortal(newSVpv(temp, 0));
       argvi++;
     }
     
-    
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsIntegerList__SWIG_1) {
+XS(_wrap_Feature_SetFID) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int *arg3 = (int *) 0 ;
-    int **arg4 = (int **) 0 ;
+    GIntBig arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int nLen3 ;
-    int *pList3 ;
     int argvi = 0;
+    OGRErr result;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const int **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsIntegerList(self,name,pList);");
+      SWIG_croak("Usage: Feature_SetFID(self,fid);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+      arg2 = CPLAtoGIntBig(SvPV_nolen(ST(1)));
     }
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsIntegerList__SWIG_1(arg1,(char const *)arg2,arg3,(int const **)arg4);
+      result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -11050,146 +10407,41 @@ XS(_wrap_Feature_GetFieldAsIntegerList__SWIG_1) {
       
     }
     {
-      /* %typemap(out) void */
-    }
-    {
-      /* %typemap(argout) (int *nLen, const int **pList) */
-      ST(argvi) = CreateArrayFromIntArray( *(arg4), *(arg3) );
-      argvi++;
+      /* %typemap(out) OGRErr */
+      if ( result != 0 ) {
+        const char *err = CPLGetLastErrorMsg();
+        if (err and *err) do_confess(err, 0); /* this is usually better */
+        do_confess( OGRErrMessages(result), 1 );
+      }
     }
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsIntegerList) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsIntegerList__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsIntegerList__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsIntegerList'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetFieldAsInteger64List__SWIG_0) {
+XS(_wrap_Feature_DumpReadable) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    GIntBig **arg4 = (GIntBig **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int nLen3 ;
-    GIntBig *pList3 ;
     int argvi = 0;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const GIntBig **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsInteger64List(self,id,pList);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: Feature_DumpReadable(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger64List" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_DumpReadable" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsInteger64List" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsInteger64List__SWIG_0(arg1,arg2,arg3,(GIntBig const **)arg4);
+      OGRFeatureShadow_DumpReadable(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -11214,61 +10466,42 @@ XS(_wrap_Feature_GetFieldAsInteger64List__SWIG_0) {
     {
       /* %typemap(out) void */
     }
-    {
-      /* %typemap(argout) (int *nLen, const GIntBig **pList) */
-      ST(argvi) = CreateArrayFromGIntBigArray( *(arg4), *(arg3) );
-      argvi++;
-    }
-    
     
     XSRETURN(argvi);
   fail:
     
-    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsInteger64List__SWIG_1) {
+XS(_wrap_Feature__UnsetField) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int *arg3 = (int *) 0 ;
-    GIntBig **arg4 = (GIntBig **) 0 ;
+    int arg2 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int nLen3 ;
-    GIntBig *pList3 ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const GIntBig **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsInteger64List(self,name,pList);");
+      SWIG_croak("Usage: Feature__UnsetField(self,id);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsInteger64List" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__UnsetField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsInteger64List__SWIG_1(arg1,(char const *)arg2,arg3,(GIntBig const **)arg4);
+      OGRFeatureShadow_UnsetField(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -11293,144 +10526,44 @@ XS(_wrap_Feature_GetFieldAsInteger64List__SWIG_1) {
     {
       /* %typemap(out) void */
     }
-    {
-      /* %typemap(argout) (int *nLen, const GIntBig **pList) */
-      ST(argvi) = CreateArrayFromGIntBigArray( *(arg4), *(arg3) );
-      argvi++;
-    }
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
+    
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsInteger64List) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
     
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsInteger64List__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsInteger64List__SWIG_1); return;
-    }
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsInteger64List'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_GetFieldAsDoubleList__SWIG_0) {
+XS(_wrap_Feature_SetFieldNull) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
-    int *arg3 = (int *) 0 ;
-    double **arg4 = (double **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
-    int nLen3 ;
-    double *pList3 ;
     int argvi = 0;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDoubleList(self,id,pList);");
+      SWIG_croak("Usage: Feature_SetFieldNull(self,id);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldNull" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldNull" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsDoubleList__SWIG_0(arg1,arg2,arg3,(double const **)arg4);
+      OGRFeatureShadow_SetFieldNull(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -11455,11 +10588,6 @@ XS(_wrap_Feature_GetFieldAsDoubleList__SWIG_0) {
     {
       /* %typemap(out) void */
     }
-    {
-      /* %typemap(argout) (int *nLen, const double **pList) */
-      ST(argvi) = CreateArrayFromDoubleArray( *(arg4), *(arg3) );
-      argvi++;
-    }
     
     
     XSRETURN(argvi);
@@ -11471,45 +10599,39 @@ XS(_wrap_Feature_GetFieldAsDoubleList__SWIG_0) {
 }
 
 
-XS(_wrap_Feature_GetFieldAsDoubleList__SWIG_1) {
+XS(_wrap_Feature__SetField__SWIG_0) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int *arg3 = (int *) 0 ;
-    double **arg4 = (double **) 0 ;
+    int arg2 ;
+    char *arg3 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int nLen3 ;
-    double *pList3 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    U8 *tmpbuf3 = NULL ;
     int argvi = 0;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, const double **pList3) */
-      arg3 = &nLen3;
-      arg4 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsDoubleList(self,name,pList);");
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature__SetField(self,id,value);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+      /* %typemap(in) (tostring argin) */
+      arg3 = sv_to_utf8_string(ST(2), &tmpbuf3);
     }
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsDoubleList__SWIG_1(arg1,(char const *)arg2,arg3,(double const **)arg4);
+      OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -11534,141 +10656,126 @@ XS(_wrap_Feature_GetFieldAsDoubleList__SWIG_1) {
     {
       /* %typemap(out) void */
     }
-    {
-      /* %typemap(argout) (int *nLen, const double **pList) */
-      ST(argvi) = CreateArrayFromDoubleArray( *(arg4), *(arg3) );
-      argvi++;
-    }
+    
     
     {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      /* %typemap(freearg) (tostring argin) */
+      if (tmpbuf3) Safefree(tmpbuf3);
     }
     XSRETURN(argvi);
   fail:
     
+    
     {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      /* %typemap(freearg) (tostring argin) */
+      if (tmpbuf3) Safefree(tmpbuf3);
     }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsDoubleList) {
-  dXSARGS;
-  
+XS(_wrap_Feature_SetFieldInteger64) {
   {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
+    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+    int arg2 ;
+    GIntBig arg3 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int argvi = 0;
+    dXSARGS;
     
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature_SetFieldInteger64(self,id,value);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldInteger64" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldInteger64" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    {
+      arg3 = CPLAtoGIntBig(SvPV_nolen(ST(2)));
+    }
+    {
+      CPLErrorReset();
+      OGRFeatureShadow_SetFieldInteger64(arg1,arg2,arg3);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
       }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
+      
+      
     }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsDoubleList__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsDoubleList__SWIG_1); return;
+    {
+      /* %typemap(out) void */
     }
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsDoubleList'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_GetFieldAsStringList__SWIG_0) {
+XS(_wrap_Feature__SetField__SWIG_1) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
-    char ***arg3 = (char ***) 0 ;
+    int arg3 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
-    char **pList3 ;
+    int val3 ;
+    int ecode3 = 0 ;
     int argvi = 0;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (char ***pList3) */
-      arg3 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsStringList(self,id);");
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature__SetField(self,id,value);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsStringList" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
+    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsStringList__SWIG_0(arg1,arg2,arg3);
+      OGRFeatureShadow_SetField__SWIG_1(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -11693,11 +10800,6 @@ XS(_wrap_Feature_GetFieldAsStringList__SWIG_0) {
     {
       /* %typemap(out) void */
     }
-    {
-      /* %typemap(argout) (char ***pList) */
-      ST(argvi) = CreateArrayFromStringArray( *(arg3) );
-      argvi++;
-    }
     
     
     
@@ -11711,42 +10813,41 @@ XS(_wrap_Feature_GetFieldAsStringList__SWIG_0) {
 }
 
 
-XS(_wrap_Feature_GetFieldAsStringList__SWIG_1) {
+XS(_wrap_Feature__SetField__SWIG_2) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char ***arg3 = (char ***) 0 ;
+    int arg2 ;
+    double arg3 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    char **pList3 ;
+    int val2 ;
+    int ecode2 = 0 ;
+    double val3 ;
+    int ecode3 = 0 ;
     int argvi = 0;
     dXSARGS;
     
-    {
-      /* %typemap(in,numinputs=0) (char ***pList3) */
-      arg3 = &pList3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsStringList(self,name);");
+    if ((items < 3) || (items > 3)) {
+      SWIG_croak("Usage: Feature__SetField(self,id,value);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "double""'");
+    } 
+    arg3 = static_cast< double >(val3);
     {
       CPLErrorReset();
-      OGRFeatureShadow_GetFieldAsStringList__SWIG_1(arg1,(char const *)arg2,arg3);
+      OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -11771,3429 +10872,102 @@ XS(_wrap_Feature_GetFieldAsStringList__SWIG_1) {
     {
       /* %typemap(out) void */
     }
-    {
-      /* %typemap(argout) (char ***pList) */
-      ST(argvi) = CreateArrayFromStringArray( *(arg3) );
-      argvi++;
-    }
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
+    
     
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
+    
     
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_GetFieldAsStringList) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsStringList__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsStringList__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsStringList'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetFieldAsBinary__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int *arg3 = (int *) 0 ;
-    char **arg4 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int nLen3 = 0 ;
-    char *pBuf3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, char **pBuf3 ) */
-      arg3 = &nLen3;
-      arg4 = &pBuf3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsBinary(self,id,pBuf);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsBinary" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldAsBinary" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary__SWIG_0(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) do_confess(err, 0); /* this is usually better */
-        do_confess( OGRErrMessages(result), 1 );
-      }
-    }
-    {
-      /* %typemap(argout) (int *nLen, char **pBuf ) */
-      ST(argvi) = sv_2mortal(newSVpv( *arg4, *arg3 ));
-      argvi++;
-    }
-    
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg3 ) {
-        free( *arg4 );
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg3 ) {
-        free( *arg4 );
-      }
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsBinary__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int *arg3 = (int *) 0 ;
-    char **arg4 = (char **) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int nLen3 = 0 ;
-    char *pBuf3 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    {
-      /* %typemap(in,numinputs=0) (int *nLen3, char **pBuf3 ) */
-      arg3 = &nLen3;
-      arg4 = &pBuf3;
-    }
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldAsBinary(self,name,pBuf);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldAsBinary" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary__SWIG_1(arg1,(char const *)arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) do_confess(err, 0); /* this is usually better */
-        do_confess( OGRErrMessages(result), 1 );
-      }
-    }
-    {
-      /* %typemap(argout) (int *nLen, char **pBuf ) */
-      ST(argvi) = sv_2mortal(newSVpv( *arg4, *arg3 ));
-      argvi++;
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg3 ) {
-        free( *arg4 );
-      }
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (int *nLen, char **pBuf ) */
-      if( *arg3 ) {
-        free( *arg4 );
-      }
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldAsBinary) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsBinary__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldAsBinary__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldAsBinary'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_IsFieldSet__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_IsFieldSet(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldSet" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_IsFieldSet__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int argvi = 0;
-    bool result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_IsFieldSet(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSet" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_bool  SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_IsFieldSet) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_IsFieldSet__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_IsFieldSet__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_IsFieldSet'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetFieldIndex__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldIndex(self,i);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetFieldIndex" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldIndex__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldIndex__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldIndex(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetFieldIndex__SWIG_1(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldIndex) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldIndex__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldIndex__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldIndex'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetGeomFieldIndex__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldIndex(self,i);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_GetGeomFieldIndex" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetGeomFieldIndex__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeomFieldIndex__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetGeomFieldIndex(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureShadow_GetGeomFieldIndex__SWIG_1(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetGeomFieldIndex) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldIndex__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetGeomFieldIndex__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_GetGeomFieldIndex'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_GetFID) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    GIntBig result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_GetFID(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = OGRFeatureShadow_GetFID(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      char temp[256];
-      sprintf(temp, ""CPL_FRMT_GIB"", result);
-      ST(argvi) = sv_2mortal(newSVpv(temp, 0));
-      argvi++;
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFID) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    GIntBig arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    OGRErr result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_SetFID(self,fid);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFID" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      arg2 = CPLAtoGIntBig(SvPV_nolen(ST(1)));
-    }
-    {
-      CPLErrorReset();
-      result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) OGRErr */
-      if ( result != 0 ) {
-        const char *err = CPLGetLastErrorMsg();
-        if (err and *err) do_confess(err, 0); /* this is usually better */
-        do_confess( OGRErrMessages(result), 1 );
-      }
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_DumpReadable) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: Feature_DumpReadable(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_DumpReadable" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_DumpReadable(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__UnsetField__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature__UnsetField(self,id);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__UnsetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_UnsetField__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__UnsetField__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature__UnsetField(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__UnsetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_UnsetField__SWIG_1(arg1,(char const *)arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__UnsetField) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__UnsetField__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__UnsetField__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature__UnsetField'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    char *arg3 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    U8 *tmpbuf3 = NULL ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in) (tostring argin) */
-      arg3 = sv_to_utf8_string(ST(2), &tmpbuf3);
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    {
-      /* %typemap(freearg) (tostring argin) */
-      if (tmpbuf3) free(tmpbuf3);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) (tostring argin) */
-      if (tmpbuf3) free(tmpbuf3);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char *arg3 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    U8 *tmpbuf3 = NULL ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,name,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      /* %typemap(in) (tostring argin) */
-      arg3 = sv_to_utf8_string(ST(2), &tmpbuf3);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (tostring argin) */
-      if (tmpbuf3) free(tmpbuf3);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (tostring argin) */
-      if (tmpbuf3) free(tmpbuf3);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldInteger64) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    GIntBig arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldInteger64(self,id,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldInteger64" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldInteger64" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      arg3 = CPLAtoGIntBig(SvPV_nolen(ST(2)));
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldInteger64(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_2) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_3) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,name,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_3(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_4) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_4(arg1,arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_5) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    double arg3 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    double val3 ;
-    int ecode3 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature__SetField(self,name,value);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    ecode3 = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "double""'");
-    } 
-    arg3 = static_cast< double >(val3);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_5(arg1,(char const *)arg2,arg3);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_6) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int arg4 ;
-    int arg5 ;
-    int arg6 ;
-    int arg7 ;
-    float arg8 ;
-    int arg9 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int val6 ;
-    int ecode6 = 0 ;
-    int val7 ;
-    int ecode7 = 0 ;
-    float val8 ;
-    int ecode8 = 0 ;
-    int val9 ;
-    int ecode9 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 9) || (items > 9)) {
-      SWIG_croak("Usage: Feature__SetField(self,id,year,month,day,hour,minute,second,tzflag);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature__SetField" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature__SetField" "', argument " "5"" of type '" "int""'");
-    } 
-    arg5 = static_cast< int >(val5);
-    ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature__SetField" "', argument " "6"" of type '" "int""'");
-    } 
-    arg6 = static_cast< int >(val6);
-    ecode7 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature__SetField" "', argument " "7"" of type '" "int""'");
-    } 
-    arg7 = static_cast< int >(val7);
-    ecode8 = SWIG_AsVal_float SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-    if (!SWIG_IsOK(ecode8)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature__SetField" "', argument " "8"" of type '" "float""'");
-    } 
-    arg8 = static_cast< float >(val8);
-    ecode9 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), &val9);
-    if (!SWIG_IsOK(ecode9)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature__SetField" "', argument " "9"" of type '" "int""'");
-    } 
-    arg9 = static_cast< int >(val9);
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_6(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField__SWIG_7) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 ;
-    int arg4 ;
-    int arg5 ;
-    int arg6 ;
-    int arg7 ;
-    float arg8 ;
-    int arg9 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int val3 ;
-    int ecode3 = 0 ;
-    int val4 ;
-    int ecode4 = 0 ;
-    int val5 ;
-    int ecode5 = 0 ;
-    int val6 ;
-    int ecode6 = 0 ;
-    int val7 ;
-    int ecode7 = 0 ;
-    float val8 ;
-    int ecode8 = 0 ;
-    int val9 ;
-    int ecode9 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 9) || (items > 9)) {
-      SWIG_croak("Usage: Feature__SetField(self,name,year,month,day,hour,minute,second,tzflag);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
-    if (!SWIG_IsOK(ecode3)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
-    } 
-    arg3 = static_cast< int >(val3);
-    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
-    if (!SWIG_IsOK(ecode4)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature__SetField" "', argument " "4"" of type '" "int""'");
-    } 
-    arg4 = static_cast< int >(val4);
-    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
-    if (!SWIG_IsOK(ecode5)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature__SetField" "', argument " "5"" of type '" "int""'");
-    } 
-    arg5 = static_cast< int >(val5);
-    ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
-    if (!SWIG_IsOK(ecode6)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature__SetField" "', argument " "6"" of type '" "int""'");
-    } 
-    arg6 = static_cast< int >(val6);
-    ecode7 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
-    if (!SWIG_IsOK(ecode7)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature__SetField" "', argument " "7"" of type '" "int""'");
-    } 
-    arg7 = static_cast< int >(val7);
-    ecode8 = SWIG_AsVal_float SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
-    if (!SWIG_IsOK(ecode8)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature__SetField" "', argument " "8"" of type '" "float""'");
-    } 
-    arg8 = static_cast< float >(val8);
-    ecode9 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), &val9);
-    if (!SWIG_IsOK(ecode9)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature__SetField" "', argument " "9"" of type '" "int""'");
-    } 
-    arg9 = static_cast< int >(val9);
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetField__SWIG_7(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    
-    
-    
-    
-    
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    
-    
-    
-    
-    
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature__SetField) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin) */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_3;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_3;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_3;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 3;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_3:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin) */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_4;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 4;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_4:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_5;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_5;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_5;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 5;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_5:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_6;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_6;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_6;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 6;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_6:
-    
-    if (items == 9) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_7;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_7;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_7;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_7;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_7;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_7;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_7;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_float SWIG_PERL_CALL_ARGS_2(ST(7), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_7;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_7;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 7;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_7:
-    
-    if (items == 9) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_8;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_8;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_8;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_8;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_8;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_8;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_8;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_float SWIG_PERL_CALL_ARGS_2(ST(7), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_8;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_8;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 8;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_8:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_2); return;
-    case 3:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_4); return;
-    case 4:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_1); return;
-    case 5:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_3); return;
-    case 6:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_5); return;
-    case 7:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_6); return;
-    case 8:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_7); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature__SetField'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_SetFieldIntegerList__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    int *arg4 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldIntegerList(self,id,nList,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldIntegerList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      do_confess(NEED_ARRAY_REF, 1);
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (int*)CPLMalloc(arg3*sizeof(int));
-      if (arg4) {
-        for( int i = 0; i<arg3; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  SvIV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldIntegerList__SWIG_0(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg4);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg4);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldIntegerList__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 ;
-    int *arg4 = (int *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldIntegerList(self,name,nList,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      /* %typemap(in,numinputs=1) (int nList, int* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      do_confess(NEED_ARRAY_REF, 1);
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (int*)CPLMalloc(arg3*sizeof(int));
-      if (arg4) {
-        for( int i = 0; i<arg3; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  SvIV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldIntegerList__SWIG_1(arg1,(char const *)arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg4);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (int nList, int* pList) */
-      CPLFree((void*) arg4);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldIntegerList) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GUIntBig* pList */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 3) {
-        {
-          {
-            /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, int* pList */
-            _v = 1;
-          }
-        }
-        if (!_v) goto check_1;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GUIntBig* pList */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 3) {
-        {
-          {
-            /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, int* pList */
-            _v = 1;
-          }
-        }
-        if (!_v) goto check_2;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldIntegerList__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldIntegerList__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_SetFieldIntegerList'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_SetFieldInteger64List__SWIG_0) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    int arg2 ;
-    int arg3 ;
-    GIntBig *arg4 = (GIntBig *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldInteger64List(self,id,nList,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldInteger64List" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldInteger64List" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in,numinputs=1) (int nList, GIntBig* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      do_confess(NEED_ARRAY_REF, 1);
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (GIntBig*)CPLMalloc(arg3*sizeof(GIntBig));
-      if (arg4) {
-        for( int i = 0; i<arg3; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  CPLAtoGIntBig(SvPV_nolen(*sv));
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldInteger64List__SWIG_0(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    {
-      /* %typemap(freearg) (int nList, GIntBig* pList) */
-      CPLFree((void*) arg4);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) (int nList, GIntBig* pList) */
-      CPLFree((void*) arg4);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldInteger64List__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 ;
-    GIntBig *arg4 = (GIntBig *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldInteger64List(self,name,nList,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldInteger64List" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      /* %typemap(in,numinputs=1) (int nList, GIntBig* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      do_confess(NEED_ARRAY_REF, 1);
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (GIntBig*)CPLMalloc(arg3*sizeof(GIntBig));
-      if (arg4) {
-        for( int i = 0; i<arg3; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  CPLAtoGIntBig(SvPV_nolen(*sv));
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldInteger64List__SWIG_1(arg1,(char const *)arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (int nList, GIntBig* pList) */
-      CPLFree((void*) arg4);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (int nList, GIntBig* pList) */
-      CPLFree((void*) arg4);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldInteger64List) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GUIntBig* pList */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 3) {
-        {
-          {
-            /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GIntBig* pList */
-            _v = 1;
-          }
-        }
-        if (!_v) goto check_1;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GUIntBig* pList */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 3) {
-        {
-          {
-            /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GIntBig* pList */
-            _v = 1;
-          }
-        }
-        if (!_v) goto check_2;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldInteger64List__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldInteger64List__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_SetFieldInteger64List'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_SetFieldDoubleList__SWIG_0) {
+XS(_wrap_Feature__SetField__SWIG_3) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
     int arg3 ;
-    double *arg4 = (double *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    dXSARGS;
-    
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldDoubleList(self,id,nList,pList);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldDoubleList" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      /* %typemap(in,numinputs=1) (int nList, double* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      do_confess(NEED_ARRAY_REF, 1);
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (double*)CPLMalloc(arg3*sizeof(double));
-      if (arg4) {
-        for( int i = 0; i<arg3; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  SvNV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      CPLErrorReset();
-      OGRFeatureShadow_SetFieldDoubleList__SWIG_0(arg1,arg2,arg3,arg4);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg4);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg4);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldDoubleList__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 ;
-    double *arg4 = (double *) 0 ;
+    int arg4 ;
+    int arg5 ;
+    int arg6 ;
+    int arg7 ;
+    float arg8 ;
+    int arg9 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
+    int val2 ;
+    int ecode2 = 0 ;
+    int val3 ;
+    int ecode3 = 0 ;
+    int val4 ;
+    int ecode4 = 0 ;
+    int val5 ;
+    int ecode5 = 0 ;
+    int val6 ;
+    int ecode6 = 0 ;
+    int val7 ;
+    int ecode7 = 0 ;
+    float val8 ;
+    int ecode8 = 0 ;
+    int val9 ;
+    int ecode9 = 0 ;
     int argvi = 0;
     dXSARGS;
     
-    if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldDoubleList(self,name,nList,pList);");
+    if ((items < 9) || (items > 9)) {
+      SWIG_croak("Usage: Feature__SetField(self,id,year,month,day,hour,minute,second,tzflag);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature__SetField" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      /* %typemap(in,numinputs=1) (int nList, double* pList) */
-      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
-      do_confess(NEED_ARRAY_REF, 1);
-      AV *av = (AV*)(SvRV(ST(2)));
-      arg3 = av_len(av)+1;
-      arg4 = (double*)CPLMalloc(arg3*sizeof(double));
-      if (arg4) {
-        for( int i = 0; i<arg3; i++ ) {
-          SV **sv = av_fetch(av, i, 0);
-          arg4[i] =  SvNV(*sv);
-        }
-      } else
-      SWIG_fail;
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature__SetField" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
+    ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Feature__SetField" "', argument " "3"" of type '" "int""'");
+    } 
+    arg3 = static_cast< int >(val3);
+    ecode4 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Feature__SetField" "', argument " "4"" of type '" "int""'");
+    } 
+    arg4 = static_cast< int >(val4);
+    ecode5 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), &val5);
+    if (!SWIG_IsOK(ecode5)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Feature__SetField" "', argument " "5"" of type '" "int""'");
+    } 
+    arg5 = static_cast< int >(val5);
+    ecode6 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), &val6);
+    if (!SWIG_IsOK(ecode6)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Feature__SetField" "', argument " "6"" of type '" "int""'");
+    } 
+    arg6 = static_cast< int >(val6);
+    ecode7 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), &val7);
+    if (!SWIG_IsOK(ecode7)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode7), "in method '" "Feature__SetField" "', argument " "7"" of type '" "int""'");
+    } 
+    arg7 = static_cast< int >(val7);
+    ecode8 = SWIG_AsVal_float SWIG_PERL_CALL_ARGS_2(ST(7), &val8);
+    if (!SWIG_IsOK(ecode8)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode8), "in method '" "Feature__SetField" "', argument " "8"" of type '" "float""'");
+    } 
+    arg8 = static_cast< float >(val8);
+    ecode9 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), &val9);
+    if (!SWIG_IsOK(ecode9)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode9), "in method '" "Feature__SetField" "', argument " "9"" of type '" "int""'");
+    } 
+    arg9 = static_cast< int >(val9);
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldDoubleList__SWIG_1(arg1,(char const *)arg2,arg3,arg4);
+      OGRFeatureShadow_SetField__SWIG_3(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -15219,31 +10993,31 @@ XS(_wrap_Feature_SetFieldDoubleList__SWIG_1) {
       /* %typemap(out) void */
     }
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg4);
-    }
+    
+    
+    
+    
+    
+    
+    
+    
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) (int nList, double* pList) */
-      CPLFree((void*) arg4);
-    }
+    
+    
+    
+    
+    
+    
+    
+    
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_SetFieldDoubleList) {
+XS(_wrap_Feature__SetField) {
   dXSARGS;
   
   {
@@ -15275,7 +11049,7 @@ XS(_wrap_Feature_SetFieldDoubleList) {
       _pi *= SWIG_MAXCASTRANK;
       {
         {
-          /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GUIntBig* pList */
+          /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) (tostring argin) */
           _v = 1;
         }
       }
@@ -15283,23 +11057,53 @@ XS(_wrap_Feature_SetFieldDoubleList) {
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
-      if (items > 3) {
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 1;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_1:
+    
+    if (items == 3) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+        _v = SWIG_CheckState(res);
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
         {
-          void *vptr = 0;
-          int res = SWIG_ConvertPtr(ST(3), &vptr, SWIGTYPE_p_double, 0);
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
           _v = SWIG_CheckState(res);
         }
-        if (!_v) goto check_1;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
       }
+      if (!_v) goto check_2;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
       if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
+        _rank = _ranki; _index = 2;
         if (_rank == _rankm) goto dispatch;
       }
     }
-  check_1:
+  check_2:
     
     if (items == 3) {
       SWIG_TypeRank _ranki = 0;
@@ -15311,65 +11115,162 @@ XS(_wrap_Feature_SetFieldDoubleList) {
         int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
         _v = SWIG_CheckState(res);
       }
-      if (!_v) goto check_2;
+      if (!_v) goto check_3;
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
       {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_3;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_double SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_3;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      if (!_index || (_ranki < _rank)) {
+        _rank = _ranki; _index = 3;
+        if (_rank == _rankm) goto dispatch;
+      }
+    }
+  check_3:
+    
+    if (items == 9) {
+      SWIG_TypeRank _ranki = 0;
+      SWIG_TypeRank _rankm = 0;
+      SWIG_TypeRank _pi = 1;
+      int _v = 0;
+      {
+        void *vptr = 0;
+        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
         _v = SWIG_CheckState(res);
       }
-      if (!_v) goto check_2;
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(3), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(4), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(5), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
+      {
+        {
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(6), NULL);
+          _v = SWIG_CheckState(res);
+        }
+      }
+      if (!_v) goto check_4;
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
       {
         {
-          /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nList, GUIntBig* pList */
-          _v = 1;
+          int res = SWIG_AsVal_float SWIG_PERL_CALL_ARGS_2(ST(7), NULL);
+          _v = SWIG_CheckState(res);
         }
       }
-      if (!_v) goto check_2;
+      if (!_v) goto check_4;
       _ranki += _v*_pi;
       _rankm += _pi;
       _pi *= SWIG_MAXCASTRANK;
-      if (items > 3) {
+      {
         {
-          void *vptr = 0;
-          int res = SWIG_ConvertPtr(ST(3), &vptr, SWIGTYPE_p_double, 0);
+          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(8), NULL);
           _v = SWIG_CheckState(res);
         }
-        if (!_v) goto check_2;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
       }
+      if (!_v) goto check_4;
+      _ranki += _v*_pi;
+      _rankm += _pi;
+      _pi *= SWIG_MAXCASTRANK;
       if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
+        _rank = _ranki; _index = 4;
         if (_rank == _rankm) goto dispatch;
       }
     }
-  check_2:
+  check_4:
     
   dispatch:
     switch(_index) {
     case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldDoubleList__SWIG_0); return;
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_0); return;
     case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldDoubleList__SWIG_1); return;
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_1); return;
+    case 3:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_2); return;
+    case 4:
+      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature__SetField__SWIG_3); return;
     }
   }
   
-  croak("No matching function for overloaded 'Feature_SetFieldDoubleList'");
+  croak("No matching function for overloaded 'Feature__SetField'");
   XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_SetFieldStringList__SWIG_0) {
+XS(_wrap_Feature_SetFieldIntegerList) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
-    char **arg3 = (char **) 0 ;
+    int arg3 ;
+    int *arg4 = (int *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
@@ -15378,51 +11279,36 @@ XS(_wrap_Feature_SetFieldStringList__SWIG_0) {
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldStringList(self,id,pList);");
+      SWIG_croak("Usage: Feature_SetFieldIntegerList(self,id,nList,pList);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldIntegerList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldStringList" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldIntegerList" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(2))) {
-        if (SvROK(ST(2))) {
-          if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(2)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
-              arg3 = CSLAddString(arg3, tmp);
-              free(tmp);
-            }
-          } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(2));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg3 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
-              arg3 = CSLAddNameValue(arg3, key, tmp);
-              free(tmp);
-            }
-          } else
-          do_confess(NEED_REF, 1);
-        } else
-        do_confess(NEED_REF, 1);
-      }
+      /* %typemap(in,numinputs=1) (int nList, int* pList) */
+      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
+      do_confess(NEED_ARRAY_REF, 1);
+      AV *av = (AV*)(SvRV(ST(2)));
+      arg3 = av_len(av)+1;
+      arg4 = (int*)CPLMalloc(arg3*sizeof(int));
+      if (arg4) {
+        for( int i = 0; i<arg3; i++ ) {
+          SV **sv = av_fetch(av, i, 0);
+          arg4[i] =  SvIV(*sv);
+        }
+      } else
+      SWIG_fail;
     }
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldStringList__SWIG_0(arg1,arg2,arg3);
+      OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -15450,83 +11336,66 @@ XS(_wrap_Feature_SetFieldStringList__SWIG_0) {
     
     
     {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
+      /* %typemap(freearg) (int nList, int* pList) */
+      CPLFree((void*) arg4);
     }
     XSRETURN(argvi);
   fail:
     
     
     {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
+      /* %typemap(freearg) (int nList, int* pList) */
+      CPLFree((void*) arg4);
     }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_SetFieldStringList__SWIG_1) {
+XS(_wrap_Feature_SetFieldInteger64List) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    char **arg3 = (char **) 0 ;
+    int arg2 ;
+    int arg3 ;
+    GIntBig *arg4 = (GIntBig *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldStringList(self,name,pList);");
+      SWIG_croak("Usage: Feature_SetFieldInteger64List(self,id,nList,pList);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldInteger64List" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldInteger64List" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      /* %typemap(in) char **options */
-      if (SvOK(ST(2))) {
-        if (SvROK(ST(2))) {
-          if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
-            AV *av = (AV*)(SvRV(ST(2)));
-            for (int i = 0; i < av_len(av)+1; i++) {
-              SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
-              arg3 = CSLAddString(arg3, tmp);
-              free(tmp);
-            }
-          } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
-            HV *hv = (HV*)SvRV(ST(2));
-            SV *sv;
-            char *key;
-            I32 klen;
-            arg3 = NULL;
-            hv_iterinit(hv);
-            while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
-              arg3 = CSLAddNameValue(arg3, key, tmp);
-              free(tmp);
-            }
-          } else
-          do_confess(NEED_REF, 1);
-        } else
-        do_confess(NEED_REF, 1);
-      }
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
+      /* %typemap(in,numinputs=1) (int nList, GIntBig* pList) */
+      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
+      do_confess(NEED_ARRAY_REF, 1);
+      AV *av = (AV*)(SvRV(ST(2)));
+      arg3 = av_len(av)+1;
+      arg4 = (GIntBig*)CPLMalloc(arg3*sizeof(GIntBig));
+      if (arg4) {
+        for( int i = 0; i<arg3; i++ ) {
+          SV **sv = av_fetch(av, i, 0);
+          arg4[i] =  CPLAtoGIntBig(SvPV_nolen(*sv));
+        }
+      } else
+      SWIG_fail;
     }
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldStringList__SWIG_1(arg1,(char const *)arg2,arg3);
+      OGRFeatureShadow_SetFieldInteger64List(arg1,arg2,arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -15541,147 +11410,41 @@ XS(_wrap_Feature_SetFieldStringList__SWIG_1) {
       /*
           Make warnings regular Perl warnings. This duplicates the warning
           message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    {
-      /* %typemap(out) void */
-    }
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    {
-      /* %typemap(freearg) char **options */
-      if (arg3) CSLDestroy( arg3 );
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_SetFieldStringList) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) char **options */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) char **options */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
+      
+      
+    }
+    {
+      /* %typemap(out) void */
     }
-  check_2:
     
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldStringList__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldStringList__SWIG_1); return;
+    
+    {
+      /* %typemap(freearg) (int nList, GIntBig* pList) */
+      CPLFree((void*) arg4);
+    }
+    XSRETURN(argvi);
+  fail:
+    
+    
+    {
+      /* %typemap(freearg) (int nList, GIntBig* pList) */
+      CPLFree((void*) arg4);
     }
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_SetFieldStringList'");
-  XSRETURN(0);
 }
 
 
-XS(_wrap_Feature_SetFieldBinary__SWIG_0) {
+XS(_wrap_Feature_SetFieldDoubleList) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
     int arg3 ;
-    GByte *arg4 = (GByte *) 0 ;
+    double *arg4 = (double *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
@@ -15690,26 +11453,36 @@ XS(_wrap_Feature_SetFieldBinary__SWIG_0) {
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldBinary(self,i,nBytes,pabyBuf);");
+      SWIG_croak("Usage: Feature_SetFieldDoubleList(self,id,nList,pList);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinary" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldDoubleList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldBinary" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldDoubleList" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
-      /* %typemap(in,numinputs=1) (int nBytes, GByte* pabyBuf) */
-      arg3 = SvCUR(ST(2));
-      arg4 = (GByte*)SvPV_nolen(ST(2));
+      /* %typemap(in,numinputs=1) (int nList, double* pList) */
+      if (!(SvROK(ST(2)) && (SvTYPE(SvRV(ST(2)))==SVt_PVAV)))
+      do_confess(NEED_ARRAY_REF, 1);
+      AV *av = (AV*)(SvRV(ST(2)));
+      arg3 = av_len(av)+1;
+      arg4 = (double*)CPLMalloc(arg3*sizeof(double));
+      if (arg4) {
+        for( int i = 0; i<arg3; i++ ) {
+          SV **sv = av_fetch(av, i, 0);
+          arg4[i] =  SvNV(*sv);
+        }
+      } else
+      SWIG_fail;
     }
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldBinary__SWIG_0(arg1,arg2,arg3,arg4);
+      OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -15736,52 +11509,83 @@ XS(_wrap_Feature_SetFieldBinary__SWIG_0) {
     }
     
     
+    {
+      /* %typemap(freearg) (int nList, double* pList) */
+      CPLFree((void*) arg4);
+    }
     XSRETURN(argvi);
   fail:
     
     
+    {
+      /* %typemap(freearg) (int nList, double* pList) */
+      CPLFree((void*) arg4);
+    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_SetFieldBinary__SWIG_1) {
+XS(_wrap_Feature_SetFieldStringList) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    int arg3 ;
-    GByte *arg4 = (GByte *) 0 ;
+    int arg2 ;
+    char **arg3 = (char **) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
+    int val2 ;
+    int ecode2 = 0 ;
     int argvi = 0;
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldBinary(self,name,nBytes,pabyBuf);");
+      SWIG_croak("Usage: Feature_SetFieldStringList(self,id,pList);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinary" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldStringList" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldStringList" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      /* %typemap(in,numinputs=1) (int nBytes, GByte* pabyBuf) */
-      arg3 = SvCUR(ST(2));
-      arg4 = (GByte*)SvPV_nolen(ST(2));
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      /* %typemap(in) char **options */
+      if (SvOK(ST(2))) {
+        if (SvROK(ST(2))) {
+          if (SvTYPE(SvRV(ST(2)))==SVt_PVAV) {
+            AV *av = (AV*)(SvRV(ST(2)));
+            for (int i = 0; i < av_len(av)+1; i++) {
+              SV *sv = *(av_fetch(av, i, 0));
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+              arg3 = CSLAddString(arg3, tmp);
+              if (sf) Safefree(tmp); else free(tmp);
+            }
+          } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
+            HV *hv = (HV*)SvRV(ST(2));
+            SV *sv;
+            char *key;
+            I32 klen;
+            arg3 = NULL;
+            hv_iterinit(hv);
+            while(sv = hv_iternextsv(hv, &key, &klen)) {
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
+              arg3 = CSLAddNameValue(arg3, key, tmp);
+              if (sf) Safefree(tmp); else free(tmp);
+            }
+          } else
+          do_confess(NEED_REF, 1);
+        } else
+        do_confess(NEED_REF, 1);
       }
     }
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldBinary__SWIG_1(arg1,(char const *)arg2,arg3,arg4);
+      OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -15807,16 +11611,18 @@ XS(_wrap_Feature_SetFieldBinary__SWIG_1) {
       /* %typemap(out) void */
     }
     
+    
     {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      /* %typemap(freearg) char **options */
+      if (arg3) CSLDestroy( arg3 );
     }
     XSRETURN(argvi);
   fail:
     
+    
     {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      /* %typemap(freearg) char **options */
+      if (arg3) CSLDestroy( arg3 );
     }
     SWIG_croak_null();
   }
@@ -15824,165 +11630,39 @@ XS(_wrap_Feature_SetFieldBinary__SWIG_1) {
 
 
 XS(_wrap_Feature_SetFieldBinary) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nBytes, GByte* pabyBuf */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 3) {
-        {
-          {
-            /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nBytes, GByte* pabyBuf */
-            _v = 1;
-          }
-        }
-        if (!_v) goto check_1;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nBytes, GByte* pabyBuf */
-          _v = 1;
-        }
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (items > 3) {
-        {
-          {
-            /* %typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) int nBytes, GByte* pabyBuf */
-            _v = 1;
-          }
-        }
-        if (!_v) goto check_2;
-        _ranki += _v*_pi;
-        _rankm += _pi;
-        _pi *= SWIG_MAXCASTRANK;
-      }
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldBinary__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldBinary__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_SetFieldBinary'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
-    char *arg3 = (char *) 0 ;
+    int arg3 ;
+    GByte *arg4 = (GByte *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
     int val2 ;
     int ecode2 = 0 ;
-    int res3 ;
-    char *buf3 = 0 ;
-    int alloc3 = 0 ;
     int argvi = 0;
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldBinaryFromHexString(self,id,pszValue);");
+      SWIG_croak("Usage: Feature_SetFieldBinary(self,i,nBytes,pabyBuf);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinary" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldBinary" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
-    res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "3"" of type '" "char const *""'");
+    {
+      /* %typemap(in,numinputs=1) (int nBytes, GByte* pabyBuf) */
+      arg3 = SvCUR(ST(2));
+      arg4 = (GByte*)SvPV_nolen(ST(2));
     }
-    arg3 = reinterpret_cast< char * >(buf3);
     {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(arg1,arg2,(char const *)arg3);
+      OGRFeatureShadow_SetFieldBinary(arg1,arg2,arg3,arg4);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -16009,25 +11689,24 @@ XS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0) {
     }
     
     
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     XSRETURN(argvi);
   fail:
     
     
-    if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1) {
+XS(_wrap_Feature_SetFieldBinaryFromHexString) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
+    int arg2 ;
     char *arg3 = (char *) 0 ;
     void *argp1 = 0 ;
     int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
+    int val2 ;
+    int ecode2 = 0 ;
     int res3 ;
     char *buf3 = 0 ;
     int alloc3 = 0 ;
@@ -16035,30 +11714,26 @@ XS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1) {
     dXSARGS;
     
     if ((items < 3) || (items > 3)) {
-      SWIG_croak("Usage: Feature_SetFieldBinaryFromHexString(self,name,pszValue);");
+      SWIG_croak("Usage: Feature_SetFieldBinaryFromHexString(self,id,pszValue);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
       SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
     }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
+    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "2"" of type '" "int""'");
+    } 
+    arg2 = static_cast< int >(val2);
     res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
     if (!SWIG_IsOK(res3)) {
       SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Feature_SetFieldBinaryFromHexString" "', argument " "3"" of type '" "char const *""'");
     }
     arg3 = reinterpret_cast< char * >(buf3);
     {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
       CPLErrorReset();
-      OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+      OGRFeatureShadow_SetFieldBinaryFromHexString(arg1,arg2,(char const *)arg3);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -16084,120 +11759,18 @@ XS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1) {
       /* %typemap(out) void */
     }
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
+    
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
+    
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_Feature_SetFieldBinaryFromHexString) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 3) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(2), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'Feature_SetFieldBinaryFromHexString'");
-  XSRETURN(0);
-}
-
-
 XS(_wrap_Feature__SetFrom) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
@@ -16511,7 +12084,7 @@ XS(_wrap_Feature_SetStyleString) {
 }
 
 
-XS(_wrap_Feature_GetFieldType__SWIG_0) {
+XS(_wrap_Feature_GetFieldType) {
   {
     OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
     int arg2 ;
@@ -16538,71 +12111,7 @@ XS(_wrap_Feature_GetFieldType__SWIG_0) {
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldType__SWIG_1) {
-  {
-    OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int argvi = 0;
-    OGRFieldType result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: Feature_GetFieldType(self,name);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_GetFieldType" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
-    {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
-      CPLErrorReset();
-      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
+      result = (OGRFieldType)OGRFeatureShadow_GetFieldType(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -16618,107 +12127,21 @@ XS(_wrap_Feature_GetFieldType__SWIG_1) {
           Make warnings regular Perl warnings. This duplicates the warning
           message if DontUseExceptions() is in effect (it is not by default).
           */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    XSRETURN(argvi);
-  fail:
-    
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_Feature_GetFieldType) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
       }
+      
+      
     }
-  check_2:
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldType__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_Feature_GetFieldType__SWIG_1); return;
-    }
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
   }
-  
-  croak("No matching function for overloaded 'Feature_GetFieldType'");
-  XSRETURN(0);
 }
 
 
@@ -16833,9 +12256,10 @@ XS(_wrap_Feature_FillUnsetWithDefault) {
               AV *av = (AV*)(SvRV(ST(2)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddString(arg3, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(2));
@@ -16845,9 +12269,10 @@ XS(_wrap_Feature_FillUnsetWithDefault) {
               arg3 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddNameValue(arg3, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -17356,7 +12781,7 @@ XS(_wrap_FeatureDefn_GetFieldCount) {
 }
 
 
-XS(_wrap_FeatureDefn_GetFieldDefn) {
+XS(_wrap_FeatureDefn__GetFieldDefn) {
   {
     OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     int arg2 ;
@@ -17369,16 +12794,16 @@ XS(_wrap_FeatureDefn_GetFieldDefn) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetFieldDefn(self,i);");
+      SWIG_croak("Usage: FeatureDefn__GetFieldDefn(self,i);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn__GetFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetFieldDefn" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn__GetFieldDefn" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
@@ -17417,68 +12842,7 @@ XS(_wrap_FeatureDefn_GetFieldDefn) {
 }
 
 
-XS(_wrap_FeatureDefn_GetFieldIndex__SWIG_0) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetFieldIndex(self,i);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetFieldIndex__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetFieldIndex__SWIG_1) {
+XS(_wrap_FeatureDefn__GetFieldIndex) {
   {
     OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     char *arg2 = (char *) 0 ;
@@ -17490,11 +12854,11 @@ XS(_wrap_FeatureDefn_GetFieldIndex__SWIG_1) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetFieldIndex(self,name);");
+      SWIG_croak("Usage: FeatureDefn__GetFieldIndex(self,name);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn__GetFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
@@ -17508,7 +12872,7 @@ XS(_wrap_FeatureDefn_GetFieldIndex__SWIG_1) {
     }
     {
       CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetFieldIndex__SWIG_1(arg1,(char const *)arg2);
+      result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -17534,100 +12898,20 @@ XS(_wrap_FeatureDefn_GetFieldIndex__SWIG_1) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FeatureDefn_GetFieldIndex) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureDefnShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureDefnShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_FeatureDefn_GetFieldIndex__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_FeatureDefn_GetFieldIndex__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'FeatureDefn_GetFieldIndex'");
-  XSRETURN(0);
-}
-
-
 XS(_wrap_FeatureDefn_AddFieldDefn) {
   {
     OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
@@ -17701,143 +12985,20 @@ XS(_wrap_FeatureDefn_GetGeomFieldCount) {
     void *argp1 = 0 ;
     int res1 = 0 ;
     int argvi = 0;
-    int result;
-    dXSARGS;
-    
-    if ((items < 1) || (items > 1)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomFieldCount(self);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    {
-      CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetGeomFieldCount(arg1);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
-    
-    XSRETURN(argvi);
-  fail:
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetGeomFieldDefn__SWIG_0) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    int arg2 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    int val2 ;
-    int ecode2 = 0 ;
-    int argvi = 0;
-    OGRGeomFieldDefnShadow *result = 0 ;
-    dXSARGS;
-    
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomFieldDefn(self,i);");
-    }
-    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
-    if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
-    }
-    arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
-    ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetGeomFieldDefn" "', argument " "2"" of type '" "int""'");
-    } 
-    arg2 = static_cast< int >(val2);
-    {
-      CPLErrorReset();
-      result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn__SWIG_0(arg1,arg2);
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        do_confess( CPLGetLastErrorMsg(), 0 );
-        
-        
-        
-        
-        
-      }
-      
-      
-      /*
-          Make warnings regular Perl warnings. This duplicates the warning
-          message if DontUseExceptions() is in effect (it is not by default).
-          */
-      if ( eclass == CE_Warning ) {
-        warn( CPLGetLastErrorMsg(), "%s" );
-      }
-      
-      
-    }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
-    
-    
-    XSRETURN(argvi);
-  fail:
-    
-    
-    SWIG_croak_null();
-  }
-}
-
-
-XS(_wrap_FeatureDefn_GetGeomFieldDefn__SWIG_1) {
-  {
-    OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
-    char *arg2 = (char *) 0 ;
-    void *argp1 = 0 ;
-    int res1 = 0 ;
-    U8 *tmpbuf2 = NULL ;
-    int argvi = 0;
-    OGRGeomFieldDefnShadow *result = 0 ;
+    int result;
     dXSARGS;
     
-    if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomFieldDefn(self,name);");
+    if ((items < 1) || (items > 1)) {
+      SWIG_croak("Usage: FeatureDefn_GetGeomFieldCount(self);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldCount" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
-      /* %typemap(in,numinputs=1) (const char* name) */
-      arg2 = sv_to_utf8_string(ST(1), &tmpbuf2);
-    }
-    {
-      if (!arg2) {
-        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-      }
-    }
-    {
       CPLErrorReset();
-      result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn__SWIG_1(arg1,(char const *)arg2);
+      result = (int)OGRFeatureDefnShadow_GetGeomFieldCount(arg1);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -17859,105 +13020,17 @@ XS(_wrap_FeatureDefn_GetGeomFieldDefn__SWIG_1) {
       
       
     }
-    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
+    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
     XSRETURN(argvi);
   fail:
     
-    {
-      /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
-    }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FeatureDefn_GetGeomFieldDefn) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureDefnShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureDefnShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_FeatureDefn_GetGeomFieldDefn__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_FeatureDefn_GetGeomFieldDefn__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'FeatureDefn_GetGeomFieldDefn'");
-  XSRETURN(0);
-}
-
-
-XS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_0) {
+XS(_wrap_FeatureDefn__GetGeomFieldDefn) {
   {
     OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     int arg2 ;
@@ -17966,25 +13039,25 @@ XS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_0) {
     int val2 ;
     int ecode2 = 0 ;
     int argvi = 0;
-    int result;
+    OGRGeomFieldDefnShadow *result = 0 ;
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomFieldIndex(self,i);");
+      SWIG_croak("Usage: FeatureDefn__GetGeomFieldDefn(self,i);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn__GetGeomFieldDefn" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     ecode2 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), &val2);
     if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn_GetGeomFieldIndex" "', argument " "2"" of type '" "int""'");
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "FeatureDefn__GetGeomFieldDefn" "', argument " "2"" of type '" "int""'");
     } 
     arg2 = static_cast< int >(val2);
     {
       CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex__SWIG_0(arg1,arg2);
+      result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn(arg1,arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -18006,7 +13079,7 @@ XS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_0) {
       
       
     }
-    ST(argvi) = SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
+    ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeomFieldDefnShadow, 0 | SWIG_SHADOW); argvi++ ;
     
     
     XSRETURN(argvi);
@@ -18018,7 +13091,7 @@ XS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_0) {
 }
 
 
-XS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_1) {
+XS(_wrap_FeatureDefn__GetGeomFieldIndex) {
   {
     OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
     char *arg2 = (char *) 0 ;
@@ -18030,11 +13103,11 @@ XS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_1) {
     dXSARGS;
     
     if ((items < 2) || (items > 2)) {
-      SWIG_croak("Usage: FeatureDefn_GetGeomFieldIndex(self,name);");
+      SWIG_croak("Usage: FeatureDefn__GetGeomFieldIndex(self,name);");
     }
     res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRFeatureDefnShadow, 0 |  0 );
     if (!SWIG_IsOK(res1)) {
-      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn_GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "FeatureDefn__GetGeomFieldIndex" "', argument " "1"" of type '" "OGRFeatureDefnShadow *""'"); 
     }
     arg1 = reinterpret_cast< OGRFeatureDefnShadow * >(argp1);
     {
@@ -18048,7 +13121,7 @@ XS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_1) {
     }
     {
       CPLErrorReset();
-      result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex__SWIG_1(arg1,(char const *)arg2);
+      result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
         do_confess( CPLGetLastErrorMsg(), 0 );
@@ -18074,100 +13147,20 @@ XS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_1) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
 }
 
 
-XS(_wrap_FeatureDefn_GetGeomFieldIndex) {
-  dXSARGS;
-  
-  {
-    unsigned long _index = 0;
-    SWIG_TypeRank _rank = 0; 
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureDefnShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        {
-          int res = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(1), NULL);
-          _v = SWIG_CheckState(res);
-        }
-      }
-      if (!_v) goto check_1;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 1;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_1:
-    
-    if (items == 2) {
-      SWIG_TypeRank _ranki = 0;
-      SWIG_TypeRank _rankm = 0;
-      SWIG_TypeRank _pi = 1;
-      int _v = 0;
-      {
-        void *vptr = 0;
-        int res = SWIG_ConvertPtr(ST(0), &vptr, SWIGTYPE_p_OGRFeatureDefnShadow, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      {
-        int res = SWIG_AsCharPtrAndSize(ST(1), 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-      }
-      if (!_v) goto check_2;
-      _ranki += _v*_pi;
-      _rankm += _pi;
-      _pi *= SWIG_MAXCASTRANK;
-      if (!_index || (_ranki < _rank)) {
-        _rank = _ranki; _index = 2;
-        if (_rank == _rankm) goto dispatch;
-      }
-    }
-  check_2:
-    
-  dispatch:
-    switch(_index) {
-    case 1:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_0); return;
-    case 2:
-      PUSHMARK(MARK); SWIG_CALLXS(_wrap_FeatureDefn_GetGeomFieldIndex__SWIG_1); return;
-    }
-  }
-  
-  croak("No matching function for overloaded 'FeatureDefn_GetGeomFieldIndex'");
-  XSRETURN(0);
-}
-
-
 XS(_wrap_FeatureDefn_AddGeomFieldDefn) {
   {
     OGRFeatureDefnShadow *arg1 = (OGRFeatureDefnShadow *) 0 ;
@@ -19048,14 +14041,14 @@ XS(_wrap_FieldDefn_SetName) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -20437,14 +15430,14 @@ XS(_wrap_GeomFieldDefn_SetName) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -21028,14 +16021,14 @@ XS(_wrap_CreateGeometryFromWkt) {
     ST(argvi) = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRGeometryShadow, SWIG_OWNER | SWIG_SHADOW); argvi++ ;
     {
       /* %typemap(freearg) (char **ignorechange) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     XSRETURN(argvi);
   fail:
     {
       /* %typemap(freearg) (char **ignorechange) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     
     SWIG_croak_null();
@@ -21655,9 +16648,10 @@ XS(_wrap_ForceTo) {
               AV *av = (AV*)(SvRV(ST(2)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddString(arg3, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(2));
@@ -21667,9 +16661,10 @@ XS(_wrap_ForceTo) {
               arg3 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddNameValue(arg3, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -22258,9 +17253,10 @@ XS(_wrap_Geometry_ExportToGML) {
               AV *av = (AV*)(SvRV(ST(1)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddString(arg2, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(1));
@@ -22270,9 +17266,10 @@ XS(_wrap_Geometry_ExportToGML) {
               arg2 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddNameValue(arg2, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -22438,9 +17435,10 @@ XS(_wrap_Geometry_ExportToJson) {
               AV *av = (AV*)(SvRV(ST(1)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddString(arg2, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(1));
@@ -22450,9 +17448,10 @@ XS(_wrap_Geometry_ExportToJson) {
               arg2 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddNameValue(arg2, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -25211,6 +20210,72 @@ XS(_wrap_Geometry_Distance) {
 }
 
 
+XS(_wrap_Geometry_Distance3D) {
+  {
+    OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+    OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    void *argp2 = 0 ;
+    int res2 = 0 ;
+    int argvi = 0;
+    double result;
+    dXSARGS;
+    
+    if ((items < 2) || (items > 2)) {
+      SWIG_croak("Usage: Geometry_Distance3D(self,other);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Distance3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+    res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Distance3D" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
+    }
+    arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
+    {
+      if (!arg2) {
+        SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+      }
+    }
+    {
+      CPLErrorReset();
+      result = (double)OGRGeometryShadow_Distance3D(arg1,arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
+    
+    
+    XSRETURN(argvi);
+  fail:
+    
+    
+    SWIG_croak_null();
+  }
+}
+
+
 XS(_wrap_Geometry_Empty) {
   {
     OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
@@ -27392,9 +22457,10 @@ XS(_wrap_Geometry_GetLinearGeometry) {
               AV *av = (AV*)(SvRV(ST(2)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddString(arg3, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(2)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(2));
@@ -27404,9 +22470,10 @@ XS(_wrap_Geometry_GetLinearGeometry) {
               arg3 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg3 = CSLAddNameValue(arg3, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -27486,9 +22553,10 @@ XS(_wrap_Geometry_GetCurveGeometry) {
               AV *av = (AV*)(SvRV(ST(1)));
               for (int i = 0; i < av_len(av)+1; i++) {
                 SV *sv = *(av_fetch(av, i, 0));
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddString(arg2, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
               HV *hv = (HV*)SvRV(ST(1));
@@ -27498,9 +22566,10 @@ XS(_wrap_Geometry_GetCurveGeometry) {
               arg2 = NULL;
               hv_iterinit(hv);
               while(sv = hv_iternextsv(hv, &key, &klen)) {
-                char *tmp = sv_to_utf8_string(sv, NULL);
+                bool sf;
+                char *tmp = sv_to_utf8_string(sv, NULL, &sf);
                 arg2 = CSLAddNameValue(arg2, key, tmp);
-                free(tmp);
+                if (sf) Safefree(tmp); else free(tmp);
               }
             } else
             do_confess(NEED_REF, 1);
@@ -28916,7 +23985,6 @@ static void *_p_OGRLayerShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSE
     return (void *)((GDALMajorObjectShadow *)  ((OGRLayerShadow *) x));
 }
 static swig_type_info _swigt__p_GDALMajorObjectShadow = {"_p_GDALMajorObjectShadow", "GDALMajorObjectShadow *", 0, 0, (void*)"Geo::GDAL::MajorObject", 0};
-static swig_type_info _swigt__p_GDALProgressFunc = {"_p_GDALProgressFunc", "GDALProgressFunc *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRFeatureDefnShadow = {"_p_OGRFeatureDefnShadow", "OGRFeatureDefnShadow *", 0, 0, (void*)"Geo::OGR::FeatureDefn", 0};
 static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)"Geo::OGR::Feature", 0};
@@ -28940,7 +24008,6 @@ static swig_type_info _swigt__p_p_p_char = {"_p_p_p_char", "char ***", 0, 0, (vo
 
 static swig_type_info *swig_type_initial[] = {
   &_swigt__p_GDALMajorObjectShadow,
-  &_swigt__p_GDALProgressFunc,
   &_swigt__p_GIntBig,
   &_swigt__p_OGRFeatureDefnShadow,
   &_swigt__p_OGRFeatureShadow,
@@ -28964,7 +24031,6 @@ static swig_type_info *swig_type_initial[] = {
 };
 
 static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_OGRLayerShadow, _p_OGRLayerShadowTo_p_GDALMajorObjectShadow, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_GDALProgressFunc[] = {  {&_swigt__p_GDALProgressFunc, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRFeatureDefnShadow[] = {  {&_swigt__p_OGRFeatureDefnShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
@@ -28988,7 +24054,6 @@ static swig_cast_info _swigc__p_p_p_char[] = {  {&_swigt__p_p_p_char, 0, 0, 0},{
 
 static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_GDALMajorObjectShadow,
-  _swigc__p_GDALProgressFunc,
   _swigc__p_GIntBig,
   _swigc__p_OGRFeatureDefnShadow,
   _swigc__p_OGRFeatureShadow,
@@ -29104,12 +24169,15 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Feature_GetFieldAsStringList", _wrap_Feature_GetFieldAsStringList},
 {"Geo::OGRc::Feature_GetFieldAsBinary", _wrap_Feature_GetFieldAsBinary},
 {"Geo::OGRc::Feature_IsFieldSet", _wrap_Feature_IsFieldSet},
-{"Geo::OGRc::Feature_GetFieldIndex", _wrap_Feature_GetFieldIndex},
-{"Geo::OGRc::Feature_GetGeomFieldIndex", _wrap_Feature_GetGeomFieldIndex},
+{"Geo::OGRc::Feature_IsFieldNull", _wrap_Feature_IsFieldNull},
+{"Geo::OGRc::Feature_IsFieldSetAndNotNull", _wrap_Feature_IsFieldSetAndNotNull},
+{"Geo::OGRc::Feature__GetFieldIndex", _wrap_Feature__GetFieldIndex},
+{"Geo::OGRc::Feature__GetGeomFieldIndex", _wrap_Feature__GetGeomFieldIndex},
 {"Geo::OGRc::Feature_GetFID", _wrap_Feature_GetFID},
 {"Geo::OGRc::Feature_SetFID", _wrap_Feature_SetFID},
 {"Geo::OGRc::Feature_DumpReadable", _wrap_Feature_DumpReadable},
 {"Geo::OGRc::Feature__UnsetField", _wrap_Feature__UnsetField},
+{"Geo::OGRc::Feature_SetFieldNull", _wrap_Feature_SetFieldNull},
 {"Geo::OGRc::Feature_SetFieldInteger64", _wrap_Feature_SetFieldInteger64},
 {"Geo::OGRc::Feature__SetField", _wrap_Feature__SetField},
 {"Geo::OGRc::Feature_SetFieldIntegerList", _wrap_Feature_SetFieldIntegerList},
@@ -29133,12 +24201,12 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::new_FeatureDefn", _wrap_new_FeatureDefn},
 {"Geo::OGRc::FeatureDefn_GetName", _wrap_FeatureDefn_GetName},
 {"Geo::OGRc::FeatureDefn_GetFieldCount", _wrap_FeatureDefn_GetFieldCount},
-{"Geo::OGRc::FeatureDefn_GetFieldDefn", _wrap_FeatureDefn_GetFieldDefn},
-{"Geo::OGRc::FeatureDefn_GetFieldIndex", _wrap_FeatureDefn_GetFieldIndex},
+{"Geo::OGRc::FeatureDefn__GetFieldDefn", _wrap_FeatureDefn__GetFieldDefn},
+{"Geo::OGRc::FeatureDefn__GetFieldIndex", _wrap_FeatureDefn__GetFieldIndex},
 {"Geo::OGRc::FeatureDefn_AddFieldDefn", _wrap_FeatureDefn_AddFieldDefn},
 {"Geo::OGRc::FeatureDefn_GetGeomFieldCount", _wrap_FeatureDefn_GetGeomFieldCount},
-{"Geo::OGRc::FeatureDefn_GetGeomFieldDefn", _wrap_FeatureDefn_GetGeomFieldDefn},
-{"Geo::OGRc::FeatureDefn_GetGeomFieldIndex", _wrap_FeatureDefn_GetGeomFieldIndex},
+{"Geo::OGRc::FeatureDefn__GetGeomFieldDefn", _wrap_FeatureDefn__GetGeomFieldDefn},
+{"Geo::OGRc::FeatureDefn__GetGeomFieldIndex", _wrap_FeatureDefn__GetGeomFieldIndex},
 {"Geo::OGRc::FeatureDefn_AddGeomFieldDefn", _wrap_FeatureDefn_AddGeomFieldDefn},
 {"Geo::OGRc::FeatureDefn_DeleteGeomFieldDefn", _wrap_FeatureDefn_DeleteGeomFieldDefn},
 {"Geo::OGRc::FeatureDefn_GetGeomType", _wrap_FeatureDefn_GetGeomType},
@@ -29247,6 +24315,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OGRc::Geometry_SymDifference", _wrap_Geometry_SymDifference},
 {"Geo::OGRc::Geometry_SymmetricDifference", _wrap_Geometry_SymmetricDifference},
 {"Geo::OGRc::Geometry_Distance", _wrap_Geometry_Distance},
+{"Geo::OGRc::Geometry_Distance3D", _wrap_Geometry_Distance3D},
 {"Geo::OGRc::Geometry_Empty", _wrap_Geometry_Empty},
 {"Geo::OGRc::Geometry_IsEmpty", _wrap_Geometry_IsEmpty},
 {"Geo::OGRc::Geometry_IsValid", _wrap_Geometry_IsValid},
@@ -29703,6 +24772,11 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
   /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "wkbTriangle", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(17)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbNone", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(100)));
     SvREADONLY_on(sv);
@@ -29758,6 +24832,11 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
   /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "wkbTriangleZ", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(1017)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbPointM", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2001)));
     SvREADONLY_on(sv);
@@ -29838,6 +24917,11 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
   /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "wkbTriangleM", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(2017)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbPointZM", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(3001)));
     SvREADONLY_on(sv);
@@ -29918,6 +25002,11 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
   /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "wkbTriangleZM", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(3017)));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "wkbPoint25D", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_From_int  SWIG_PERL_CALL_ARGS_1(static_cast< int >(0x80000001)));
     SvREADONLY_on(sv);
@@ -30253,6 +25342,16 @@ XS(SWIG_init) {
     SvREADONLY_on(sv);
   } while(0) /*@SWIG@*/;
   /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "ODsCRandomLayerRead", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("RandomLayerRead"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
+    SV *sv = get_sv((char*) SWIG_prefix "ODsCRandomLayerWrite", TRUE | 0x2 | GV_ADDMULTI);
+    sv_setsv(sv, SWIG_FromCharPtr("RandomLayerWrite"));
+    SvREADONLY_on(sv);
+  } while(0) /*@SWIG@*/;
+  /*@SWIG:/home/rouault/install-swig-2.0.12/share/swig/2.0.12/perl5/perltypemaps.swg,65,%set_constant@*/ do {
     SV *sv = get_sv((char*) SWIG_prefix "ODrCCreateDataSource", TRUE | 0x2 | GV_ADDMULTI);
     sv_setsv(sv, SWIG_FromCharPtr("CreateDataSource"));
     SvREADONLY_on(sv);
diff --git a/swig/perl/osr_wrap.cpp b/swig/perl/osr_wrap.cpp
index 495309d..c499e30 100644
--- a/swig/perl/osr_wrap.cpp
+++ b/swig/perl/osr_wrap.cpp
@@ -1644,11 +1644,13 @@ typedef void OSRCoordinateTransformationShadow;
     #define NEED_DEF "A parameter which must be defined or not empty, is not."
     #define WRONG_CLASS "Object has a wrong class."
     #define NEED_REF "A parameter which must be a reference, is not."
+    #define NEED_HASH_REF "A parameter/item which must be a hash reference, is not."
     #define NEED_ARRAY_REF "A parameter/item which must be an array reference, is not."
     #define NEED_BINARY_DATA "A parameter which must be binary data, is not."
     #define NEED_CODE_REF "A parameter which must be an anonymous subroutine, is not."
     #define WRONG_ITEM_IN_ARRAY "An item in an array parameter has wrong type."
     #define ARRAY_TO_XML_FAILED "An array parameter cannot be converted to an XMLTree."
+    #define NOT_ENOUGH_ELEMENTS "The supplied array does not have enough elements."
 
 
 void VeryQuietErrorHandler(CPLErr eclass, int code, const char *msg ) {
@@ -1685,9 +1687,11 @@ OGRErr GetWellKnownGeogCSAsWKT( const char *name, char **argout ) {
 }
 
 
-    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf) {
-        /* if tmpbuf, only tmpbuf is freed; if not, ret is freed*/
+    char *sv_to_utf8_string(SV *sv, U8 **tmpbuf, bool *safefree = NULL) {
+        /* if tmpbuf is given, only tmpbuf needs to be freed, use Safefree!
+           if not, ret needs to be freed, if safefree use Safefree else use free! */
         char *ret;
+        if (safefree) *safefree = false;
         if (SvOK(sv)) {
             STRLEN len;
             ret = SvPV(sv, len);
@@ -1698,6 +1702,7 @@ OGRErr GetWellKnownGeogCSAsWKT( const char *name, char **argout ) {
                 } else {
                     ret = (char *)bytes_to_utf8((const U8*)ret, &len);
                 }
+                if (safefree) *safefree = true;
             } else {
                 if (!tmpbuf)
                     ret = strdup(ret);
@@ -2020,6 +2025,10 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnits(OSRSpatialReferenceSh
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnitsAndUpdateParameters(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
     return OSRSetLinearUnitsAndUpdateParameters( self, name, to_meters );
   }
+SWIGINTERN double OSRSpatialReferenceShadow_GetTargetLinearUnits(OSRSpatialReferenceShadow *self,char const *target_key){
+    // Return code ignored.
+    return OSRGetTargetLinearUnits( self, target_key, 0 );
+  }
 SWIGINTERN double OSRSpatialReferenceShadow_GetLinearUnits(OSRSpatialReferenceShadow *self){
     // Return code ignored.
     return OSRGetLinearUnits( self, 0 );
@@ -2542,7 +2551,7 @@ XS(_wrap_GetWellKnownGeogCSAsWKT) {
     }
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) (char **argout) */
@@ -2553,7 +2562,7 @@ XS(_wrap_GetWellKnownGeogCSAsWKT) {
   fail:
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) (char **argout) */
@@ -2634,7 +2643,7 @@ XS(_wrap_GetUserInputAsWKT) {
     }
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) (char **argout) */
@@ -2645,7 +2654,7 @@ XS(_wrap_GetUserInputAsWKT) {
   fail:
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf1) free(tmpbuf1);
+      if (tmpbuf1) Safefree(tmpbuf1);
     }
     {
       /* %typemap(freearg) (char **argout) */
@@ -3805,7 +3814,7 @@ XS(_wrap_SpatialReference_GetAttrValue) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -3813,7 +3822,7 @@ XS(_wrap_SpatialReference_GetAttrValue) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -3893,7 +3902,7 @@ XS(_wrap_SpatialReference_SetAttrValue) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     XSRETURN(argvi);
@@ -3901,7 +3910,7 @@ XS(_wrap_SpatialReference_SetAttrValue) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
     SWIG_croak_null();
@@ -3980,7 +3989,7 @@ XS(_wrap_SpatialReference_SetAngularUnits) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -3988,7 +3997,7 @@ XS(_wrap_SpatialReference_SetAngularUnits) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -4185,7 +4194,7 @@ XS(_wrap_SpatialReference_SetTargetLinearUnits) {
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf3) free(tmpbuf3);
+      if (tmpbuf3) Safefree(tmpbuf3);
     }
     
     XSRETURN(argvi);
@@ -4194,7 +4203,7 @@ XS(_wrap_SpatialReference_SetTargetLinearUnits) {
     if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf3) free(tmpbuf3);
+      if (tmpbuf3) Safefree(tmpbuf3);
     }
     
     SWIG_croak_null();
@@ -4273,7 +4282,7 @@ XS(_wrap_SpatialReference_SetLinearUnits) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -4281,7 +4290,7 @@ XS(_wrap_SpatialReference_SetLinearUnits) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -4360,7 +4369,7 @@ XS(_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -4368,7 +4377,7 @@ XS(_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -4376,6 +4385,74 @@ XS(_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters) {
 }
 
 
+XS(_wrap_SpatialReference_GetTargetLinearUnits) {
+  {
+    OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+    char *arg2 = (char *) 0 ;
+    void *argp1 = 0 ;
+    int res1 = 0 ;
+    int res2 ;
+    char *buf2 = 0 ;
+    int alloc2 = 0 ;
+    int argvi = 0;
+    double result;
+    dXSARGS;
+    
+    {
+      /* %typemap(default) const char * target_key */
+      arg2 = NULL;
+    }
+    if ((items < 1) || (items > 2)) {
+      SWIG_croak("Usage: SpatialReference_GetTargetLinearUnits(self,target_key);");
+    }
+    res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+    if (!SWIG_IsOK(res1)) {
+      SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetTargetLinearUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+    }
+    arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+    if (items > 1) {
+      res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+      if (!SWIG_IsOK(res2)) {
+        SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_GetTargetLinearUnits" "', argument " "2"" of type '" "char const *""'");
+      }
+      arg2 = reinterpret_cast< char * >(buf2);
+    }
+    {
+      CPLErrorReset();
+      result = (double)OSRSpatialReferenceShadow_GetTargetLinearUnits(arg1,(char const *)arg2);
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        do_confess( CPLGetLastErrorMsg(), 0 );
+        
+        
+        
+        
+        
+      }
+      
+      
+      /*
+          Make warnings regular Perl warnings. This duplicates the warning
+          message if DontUseExceptions() is in effect (it is not by default).
+          */
+      if ( eclass == CE_Warning ) {
+        warn( CPLGetLastErrorMsg(), "%s" );
+      }
+      
+      
+    }
+    ST(argvi) = SWIG_From_double  SWIG_PERL_CALL_ARGS_1(static_cast< double >(result)); argvi++ ;
+    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    XSRETURN(argvi);
+  fail:
+    
+    if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+    SWIG_croak_null();
+  }
+}
+
+
 XS(_wrap_SpatialReference_GetLinearUnits) {
   {
     OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -5232,7 +5309,7 @@ XS(_wrap_SpatialReference_SetProjParm) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -5240,7 +5317,7 @@ XS(_wrap_SpatialReference_SetProjParm) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -5314,7 +5391,7 @@ XS(_wrap_SpatialReference_GetProjParm) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -5322,7 +5399,7 @@ XS(_wrap_SpatialReference_GetProjParm) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -5401,7 +5478,7 @@ XS(_wrap_SpatialReference_SetNormProjParm) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -5409,7 +5486,7 @@ XS(_wrap_SpatialReference_SetNormProjParm) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -5483,7 +5560,7 @@ XS(_wrap_SpatialReference_GetNormProjParm) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     XSRETURN(argvi);
@@ -5491,7 +5568,7 @@ XS(_wrap_SpatialReference_GetNormProjParm) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     SWIG_croak_null();
@@ -9806,14 +9883,14 @@ XS(_wrap_SpatialReference_SetWellKnownGeogCS) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -9883,14 +9960,14 @@ XS(_wrap_SpatialReference_SetFromUserInput) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -10480,14 +10557,14 @@ XS(_wrap_SpatialReference_SetProjCS) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -10559,14 +10636,14 @@ XS(_wrap_SpatialReference_SetGeocCS) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -10758,7 +10835,7 @@ XS(_wrap_SpatialReference_SetCompoundCS) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     
@@ -10767,7 +10844,7 @@ XS(_wrap_SpatialReference_SetCompoundCS) {
     
     {
       /* %typemap(freearg) (const char* name) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     
     
@@ -10836,14 +10913,14 @@ XS(_wrap_SpatialReference_ImportFromWkt) {
     
     {
       /* %typemap(freearg) (char **ignorechange) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     XSRETURN(argvi);
   fail:
     
     {
       /* %typemap(freearg) (char **ignorechange) */
-      if (tmpbuf2) free(tmpbuf2);
+      if (tmpbuf2) Safefree(tmpbuf2);
     }
     SWIG_croak_null();
   }
@@ -11019,9 +11096,10 @@ XS(_wrap_SpatialReference_ImportFromESRI) {
             AV *av = (AV*)(SvRV(ST(1)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddString(arg2, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(1));
@@ -11031,9 +11109,10 @@ XS(_wrap_SpatialReference_ImportFromESRI) {
             arg2 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddNameValue(arg2, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -11272,6 +11351,8 @@ XS(_wrap_SpatialReference_ImportFromPCI) {
         do_confess(NEED_ARRAY_REF, 1);
         arg4 = argin4;
         AV *av = (AV*)(SvRV(ST(3)));
+        if (av_len(av)+1 < 17)
+        do_confess(NOT_ENOUGH_ELEMENTS, 1);
         for (unsigned int i=0; i<17; i++) {
           SV *sv = *av_fetch(av, i, 0);
           if (!SvOK(sv))
@@ -11374,6 +11455,8 @@ XS(_wrap_SpatialReference_ImportFromUSGS) {
         do_confess(NEED_ARRAY_REF, 1);
         arg4 = argin4;
         AV *av = (AV*)(SvRV(ST(3)));
+        if (av_len(av)+1 < 15)
+        do_confess(NOT_ENOUGH_ELEMENTS, 1);
         for (unsigned int i=0; i<15; i++) {
           SV *sv = *av_fetch(av, i, 0);
           if (!SvOK(sv))
@@ -11703,9 +11786,10 @@ XS(_wrap_SpatialReference_ImportFromOzi) {
             AV *av = (AV*)(SvRV(ST(1)));
             for (int i = 0; i < av_len(av)+1; i++) {
               SV *sv = *(av_fetch(av, i, 0));
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddString(arg2, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else if (SvTYPE(SvRV(ST(1)))==SVt_PVHV) {
             HV *hv = (HV*)SvRV(ST(1));
@@ -11715,9 +11799,10 @@ XS(_wrap_SpatialReference_ImportFromOzi) {
             arg2 = NULL;
             hv_iterinit(hv);
             while(sv = hv_iternextsv(hv, &key, &klen)) {
-              char *tmp = sv_to_utf8_string(sv, NULL);
+              bool sf;
+              char *tmp = sv_to_utf8_string(sv, NULL, &sf);
               arg2 = CSLAddNameValue(arg2, key, tmp);
-              free(tmp);
+              if (sf) Safefree(tmp); else free(tmp);
             }
           } else
           do_confess(NEED_REF, 1);
@@ -13052,6 +13137,8 @@ XS(_wrap_CoordinateTransformation_TransformPoint__SWIG_0) {
       do_confess(NEED_ARRAY_REF, 1);
       arg2 = argin2;
       AV *av = (AV*)(SvRV(ST(1)));
+      if (av_len(av)+1 < 3)
+      do_confess(NOT_ENOUGH_ELEMENTS, 1);
       for (unsigned int i=0; i<3; i++) {
         SV *sv = *av_fetch(av, i, 0);
         if (!SvOK(sv))
@@ -13600,6 +13687,7 @@ static swig_command_info swig_commands[] = {
 {"Geo::OSRc::SpatialReference_SetTargetLinearUnits", _wrap_SpatialReference_SetTargetLinearUnits},
 {"Geo::OSRc::SpatialReference_SetLinearUnits", _wrap_SpatialReference_SetLinearUnits},
 {"Geo::OSRc::SpatialReference_SetLinearUnitsAndUpdateParameters", _wrap_SpatialReference_SetLinearUnitsAndUpdateParameters},
+{"Geo::OSRc::SpatialReference_GetTargetLinearUnits", _wrap_SpatialReference_GetTargetLinearUnits},
 {"Geo::OSRc::SpatialReference_GetLinearUnits", _wrap_SpatialReference_GetLinearUnits},
 {"Geo::OSRc::SpatialReference_GetLinearUnitsName", _wrap_SpatialReference_GetLinearUnitsName},
 {"Geo::OSRc::SpatialReference_GetAuthorityCode", _wrap_SpatialReference_GetAuthorityCode},
diff --git a/swig/perl/parse-for-doxygen.pl b/swig/perl/parse-for-doxygen.pl
index 6192fbd..9a105a7 100644
--- a/swig/perl/parse-for-doxygen.pl
+++ b/swig/perl/parse-for-doxygen.pl
@@ -4,11 +4,11 @@ use Modern::Perl;
 
 my @pm = qw(lib/Geo/GDAL.pm lib/Geo/OGR.pm lib/Geo/OSR.pm lib/Geo/GDAL/Const.pm lib/Geo/GNM.pm);
 
-my %internal_methods = map {$_=>1} qw/TIEHASH CLEAR FIRSTKEY NEXTKEY FETCH STORE 
+my %internal_methods = map {$_=>1} qw/TIEHASH CLEAR FIRSTKEY NEXTKEY FETCH STORE
                                       DESTROY DISOWN ACQUIRE RELEASE_PARENTS
                                       UseExceptions DontUseExceptions this AllRegister RegisterAll
                                       callback_d_cp_vp/;
-my %private_methods = map {$_=>1} qw/PushErrorHandler PopErrorHandler Error ErrorReset 
+my %private_methods = map {$_=>1} qw/PushErrorHandler PopErrorHandler Error ErrorReset
                                      GetLastErrorNo GetLastErrorType GetLastErrorMsg/;
 my %constant_prefixes = map {$_=>1} qw/DCAP_/;
 
@@ -188,6 +188,7 @@ for my $package (sort keys %package) {
         }
     }
     print "#** \@class $package\n";
+    # package may have brief, details, todo, isa
     for my $l (@{$package{$package}{package_dox}}) {
         print "# $l\n";
     }
@@ -237,7 +238,7 @@ for my $package (sort keys %package) {
         next if $sub =~ /^SRS_UL_/;
         next if $sub =~ /^SRS_UA_/;
         next if $sub =~ /^SRS_DN_/;
-        
+
         my $at = $package{$package}{dox}{$sub}{at} // '';
         next if $internal_methods{$sub} && !$at; # skip non-documented internal methods
 
@@ -318,5 +319,5 @@ sub fix_indentation {
                 $_ =~ s/^ //;
             }
         }
-    } 
+    }
 }
diff --git a/swig/perl/pdl.dox b/swig/perl/pdl.dox
index 7f7feb2..8298233 100644
--- a/swig/perl/pdl.dox
+++ b/swig/perl/pdl.dox
@@ -1,62 +1,62 @@
-/*! \page band_to_pdl Making a piddle from data in a band
+/*! \page band_to_pdl Using PDL to manipulate band data
 
 The code here does not have any warranty. It is recommended that
 before using any of this code, you look into it and try to understand
 what it does, what input it needs, etc. Do not blindly execute
 anything!
 
+The Piddle method of Band object can be used to read and write band
+data from a piddle or into a piddle. The PDL module provides ways
+to manipulate piddles.
+
 \code
-use Carp;
+use strict;
+use v5.10;
 use Geo::GDAL;
 use PDL;
 
-my $filename = 'xxx';
-my $update = undef;
-
-my $dataset = Geo::GDAL::Open($filename, $update);
-my $band = $dataset->Band(1);
-
-my($xoff,$yoff) = (1000,4000);
-my($w,$h) = (1000,1000);
-
-my $data = $band->ReadRaster($xoff,$yoff,$w,$h);
-
-my $pdl = PDL->new;
-
-# PDL data types:
-# 0 = unsigned char
-# 1 = short
-# 2 = unsigned short
-# 3 = int
-# 4 = long long
-# 5 = float
-# 6 = double
-
-# GDAL data types: Byte UInt16 Int16 UInt32 Int32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64
-# obtained with $band->DataType
-
-my %map = ( 
-    Byte => 0,
-    UInt16 => 2,
-    Int16 => 1,
-    UInt32 => -1,
-    Int32 => 3,
-    Float32 => 5,
-    Float64 => 6,
-    CInt16 => -1,
-    CInt32 => -1,
-    CFloat32 => -1,
-    CFloat64 => -1
-    );
-
-my $datatype = $map{$band->DataType};
-croak "there is no direct mapping between the band datatype and PDL" if $datatype < 0;
-$pdl->set_datatype($datatype);
-$pdl->setdims([1,$w,$h]);
-my $dref = $pdl->get_dataref();
-# this is not optimal, but the best what we can do in Perl:
-$$dref = $data;
-$pdl->upd_data;
+my $filename = 'some.tiff';
+my $update = 'UPDATE';
+my $band = Geo::GDAL::Open($filename, $update)->Band();
+
+my ($W,$H) = $band->Size;
+my ($w,$h) = $band->GetBlockSize;
+my ($xoff,$yoff) = (0,0);
+while (1) {
+    progress($yoff/$H);
+    if ($xoff >= $W) {
+        $xoff = 0;
+        $yoff += $h;
+        last if $yoff >= $H;
+    }
+    my $a = $band->Piddle($xoff, $yoff, my_min($W-$xoff,$w), my_min($H-$yoff,$h));
+
+    # do something with a
+    $a = ($a < 0) + ($a < -30) + ($a < -60);
+
+    $band->Piddle($a, $xoff, $yoff);
+    $xoff += $w;
+}
+progress(1);
+say;
+
+sub progress {
+    state $s = -1; # requires 'use v5.10;'
+    my $p = int($_[0]*100);
+    return 1 if $p == $s;
+    $s = 0 if $s < 0;
+    while ($s < $p) {
+        print $s%10 == 0 ? $s : ($s%2 == 0 ? '.' : '');
+        ++$s;
+    }
+    return 1;
+}
+
+sub my_min {
+    return $_[0] < $_[1] ? $_[0] : $_[1];
+}
+
+
 \endcode
 
 */
diff --git a/swig/perl/rv.dox b/swig/perl/rv.dox
index c8f6442..9e94d85 100644
--- a/swig/perl/rv.dox
+++ b/swig/perl/rv.dox
@@ -22,8 +22,8 @@ $datasource = Geo::GDAL::OpenEx($dsname);
 $layer = $datasource->Layer($lname);
 
 $layer->ResetReading();
-while ($feature = $layer->GetNextFeature()) {  
-    my $geom = $feature->GetGeometry(); 
+while ($feature = $layer->GetNextFeature()) {
+    my $geom = $feature->GetGeometry();
     my $value = $feature->GetField($field);
     my $extent = $geom->GetEnvelope();
     $data{$value}{width} = $extent->[1] - $extent->[0];
diff --git a/swig/perl/t/00-measures-00.t b/swig/perl/t/00-measures-00.t
index 57d2b9c..55f12a7 100644
--- a/swig/perl/t/00-measures-00.t
+++ b/swig/perl/t/00-measures-00.t
@@ -7,15 +7,13 @@ BEGIN { use_ok('Geo::GDAL') };
 
 # test geometry types
 
-my @t = @Geo::OGR::Geometry::GEOMETRY_TYPES;
-my %t2i = %Geo::OGR::Geometry::TYPE_STRING2INT;
-my %i2t = %Geo::OGR::Geometry::TYPE_INT2STRING;
+my @t = Geo::OGR::Geometry->GeometryTypes;
 
 for my $geom (@t) {
     next if $geom eq 'Unknown';
     next if $geom eq 'None';
 
-    my $i = $t2i{$geom};
+    my $i = Geo::GDAL::s2i(geometry_type => $geom);
 
     my $j = Geo::OGR::GT_Flatten($i);
     ok(!Geo::OGR::GT_HasZ($j), "$geom, no Z after GT_Flatten");
diff --git a/swig/perl/t/00-measures-03.t b/swig/perl/t/00-measures-03.t
index 560dbda..3be283e 100644
--- a/swig/perl/t/00-measures-03.t
+++ b/swig/perl/t/00-measures-03.t
@@ -51,20 +51,23 @@ my $dir = '/vsimem/';
 if (1) {
 for (my $i = 0; $i < @data; $i+=2) {
     my $type = $data[$i];
-    my $l = Geo::OGR::Driver($driver)->Create($dir.$type.'.shp')->CreateLayer(GeometryType => $type);
-    eval {
-        $l->InsertFeature({Geometry => {WKT => $data[$i+1]}});
-    };
-    if ($@) {
-        my @e = split /\n/, $@;
-        $e[0] =~ s/\. at .*/./;
-        ok(0, "$driver, insert feature: $type => $data[$i+1] ($e[0])");
-        next;
+    {
+        my $l = Geo::OGR::Driver($driver)->Create($dir.$type.'.shp')->CreateLayer(GeometryType => $type);
+        eval {
+            $l->InsertFeature({Geometry => {WKT => $data[$i+1]}});
+        };
+        if ($@) {
+            my @e = split /\n/, $@;
+            $e[0] =~ s/\. at .*/./;
+            ok(0, "$driver, insert feature: $type => $data[$i+1] ($e[0])");
+            next;
+        }
     }
     
-    # close and open
-    undef $l;
-    $l = Geo::OGR::Open($dir)->GetLayer($type);
+    # reopen
+    # !! if $l is not destroyed before this, an unifinished layer is opened !!
+    my $l = Geo::OGR::Open($dir)->GetLayer($type);
+    ok($l->FeatureCount == 1, "count is correct");
     my $t = $l->GeometryType;
     $t =~ s/25D/Z/;
     my $exp = $type;
diff --git a/swig/perl/t/00-measures-04.t b/swig/perl/t/00-measures-04.t
index de54d8d..14e29d2 100644
--- a/swig/perl/t/00-measures-04.t
+++ b/swig/perl/t/00-measures-04.t
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 use bytes;
 use v5.10;
-use Test::More qw(no_plan);
+use Test::More;
 BEGIN { use_ok('Geo::GDAL') };
 
 # test measured geometries in pg driver
@@ -42,6 +42,12 @@ my @data = (
 
 my $driver = 'PostgreSQL';
 
+eval {
+    Geo::OGR::Open('PG:dbname=autotest', 1);
+};
+SKIP: {
+    skip "PG connect to autotest failed. Probably it is not available.", 1 if $@;
+
 for (my $i = 0; $i < @data; $i+=2) {
     my $type = $data[$i];
     eval {
@@ -81,3 +87,5 @@ for (my $i = 0; $i < @data; $i+=2) {
 
     Geo::OGR::Open('PG:dbname=autotest', 1)->DeleteLayer(lc($type));
 }
+}
+done_testing();
diff --git a/swig/perl/t/00.t b/swig/perl/t/00.t
index 022c12e..d6c438c 100644
--- a/swig/perl/t/00.t
+++ b/swig/perl/t/00.t
@@ -43,7 +43,7 @@ eval {
 ok((@list > 0 and $@ eq ''), "DataTypes, got $@");
 
 for my $type (Geo::GDAL::DataTypes()) {
-    my $nr = $Geo::GDAL::TYPE_STRING2INT{$type};
+    my $nr = Geo::GDAL::s2i(data_type => $type);
     my $c = Geo::GDAL::GetDataTypeName($nr);
     ok($type eq $c, "Data type $type");
     eval {
@@ -218,7 +218,31 @@ sub traverse {
 my $dataset = Geo::GDAL::Driver('MEM')->Create();
 my $transform = Geo::GDAL::GeoTransform->new;
 $dataset->GeoTransform($transform);
-$transform = $dataset->GeoTransform();
+my $transform2 = $dataset->GeoTransform();
+is_deeply($transform, $transform2, "Set and get geotransform.");
+
+eval {
+    $dataset->GeoTransform(5,2,0,3,0);
+};
+ok($@ ne '', "It is an error to set GeoTransform with too few values.");
+
+my @t = (5,2,0,3,0,4);
+my @c = (2,3);
+$transform = Geo::GDAL::GeoTransform->new(@t);
+my @xy = $transform->Apply(@c);
+my @xy2 = $transform->Apply([$c[0]],[$c[1]]);
+ok((($xy[0] == $xy2[0][0]) and ($xy[1] == $xy2[1][0])), "Apply geotransform.");
+
+my $inv = $transform->Inv;
+ at xy = $transform->Apply(@c);
+my @c2 = $inv->Apply(@xy);
+is_deeply(\@c, \@c2, "Inverse of geotransform.");
+
+$inv = Geo::GDAL::GeoTransform->new(@t);
+$inv->Inv;
+ at xy = $transform->Apply(@c);
+ at c2 = $inv->Apply(@xy);
+is_deeply(\@c, \@c2, "Inverse of geotransform (2).");
 
 # package Geo::GDAL::VSIF
 # sub Close ok
diff --git a/swig/perl/t/01.t b/swig/perl/t/01.t
index 6d118e2..7f902a6 100644
--- a/swig/perl/t/01.t
+++ b/swig/perl/t/01.t
@@ -69,7 +69,9 @@ for my $dt (Geo::GDAL::Driver('GTiff')->Domains()) {
 }
 
 my $ext = Geo::GDAL::Driver('GTiff')->Extension;
-ok($ext eq 'tif', "Extension, got $ext");
+ok($ext eq 'tif', "Extension, got '$ext', not 'tif'");
+my @ext = Geo::GDAL::Driver('GTiff')->Extension;
+ok((($ext[0] eq 'tif') and ($ext[1] eq 'tiff')), "Extension, got '@ext', not 'tif tiff'");
 
 $ext = Geo::GDAL::Driver('GTiff')->MIMEType;
 ok($ext eq 'image/tiff', "MIMEType, got $ext");
diff --git a/swig/perl/t/alg.t b/swig/perl/t/alg.t
index a6831d8..b7942d6 100644
--- a/swig/perl/t/alg.t
+++ b/swig/perl/t/alg.t
@@ -2,10 +2,67 @@ use strict;
 use warnings;
 use v5.10;
 use Scalar::Util 'blessed';
-use Test::More tests => 9;
+use Test::More tests => 21;
 BEGIN { use_ok('Geo::GDAL') };
 
 {
+    # test making of processing options
+    my @a1 = ('-a', 1, '-b', 2, '-3.0%');
+    my @b1 = ('-b', 2, '-3.0%', '-a', 1);
+
+    my @a2 = ('-a', 1, '-b', '2 -3.0%');
+    my @b2 = ('-b', '2 -3.0%', '-a', 1);
+
+    my @a3 = ('-a', 1, '-b', 'a 3');
+    my @b3 = ('-b', 'a 3', '-a', 1);
+
+    sub test {
+        my ($got, $t, $test) = @_;
+        my $out = join("' , '", @$got);
+        my @a;
+        my @b;
+        if ($t == 1) {
+            @a = @a1; @b = @b1;
+        } elsif ($t == 2) {
+            @a = @a2; @b = @b2;
+        } else {
+            @a = @a3; @b = @b3;
+        }
+        ok(eq_array($got, \@a) || eq_array($got, \@b), "$test ($t): '$out'");
+    }
+    my $got = Geo::GDAL::make_processing_options({-a => 1, -b => [2,'-3.0%']});
+    test($got, 1, 'processing options hash');
+    $got = Geo::GDAL::make_processing_options({-a => 1, -b => "2 -3.0%"});
+    test($got, 1, 'processing options hash string to list');
+    $got = Geo::GDAL::make_processing_options({-a => 1, -b => "a 3"});
+    test($got, 3, 'processing options hash string to string');
+    $got = Geo::GDAL::make_processing_options({-a => 1, -b => ["2 -3.0%"]});
+    test($got, 2, 'processing options hash string from array');
+    
+    $got = Geo::GDAL::make_processing_options([-a => 1, -b => [2,'-3.0%']]);
+    test($got, 1, 'processing options array');
+    $got = Geo::GDAL::make_processing_options([-a => 1, -b => "2 -3.0%"]);
+    test($got, 1, 'processing options array string to list');
+    $got = Geo::GDAL::make_processing_options([-a => 1, -b => 2, '-3.0%']);
+    test($got, 1, 'processing options array list to list');
+    $got = Geo::GDAL::make_processing_options([-a => 1, -b => ["2 -3.0%"]]);
+    test($got, 2, 'processing options array string from array');
+    
+    $got = Geo::GDAL::make_processing_options({a => 1, b => [2,'-3.0%']});
+    test($got, 1, 'processing options hash');
+    $got = Geo::GDAL::make_processing_options({a => 1, b => "2 -3.0%"});
+    test($got, 1, 'processing options hash string to list');
+    $got = Geo::GDAL::make_processing_options({a => 1, b => ["2 -3.0%"]});
+    test($got, 2, 'processing options hash string from array');
+    
+    eval {
+        Geo::GDAL::make_processing_options({a => 1, b => {2,3}});
+    };
+    ok($@, "error in make processing options");
+    
+}
+
+{
     my $b = Geo::GDAL::Driver('MEM')->Create(Width => 40, Height => 40)->Band;
     my $d = $b->ReadTile;
     for my $y (20..29) {
@@ -97,7 +154,7 @@ BEGIN { use_ok('Geo::GDAL') };
     my $dest = '/vsimem/tmp';
     my $result;
     eval {
-        $result = Geo::GDAL::Dataset::Warp([$d], $dest, {to => 'SRC_METHOD=NO_GEOTRANSFORM'});
+        $result = Geo::GDAL::Dataset::Warp([$d], $dest, {-to => 'SRC_METHOD=NO_GEOTRANSFORM'});
         $result = blessed($result);
     };
     ok($@ eq '' && $result && $result eq 'Geo::GDAL::Dataset', "Warp datasets ($result) $@");
diff --git a/swig/perl/t/band.t b/swig/perl/t/band.t
new file mode 100644
index 0000000..8642c7b
--- /dev/null
+++ b/swig/perl/t/band.t
@@ -0,0 +1,105 @@
+use strict;
+use warnings;
+use Scalar::Util 'blessed';
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+for my $datatype (qw/Byte Int16 Int32 UInt16 UInt32/) {
+    my $band = Geo::GDAL::Driver('MEM')->Create(Type => $datatype, Width => 5, Height => 5)->Band;
+    my $tile = $band->ReadTile;
+    my $v = 0; # 3 of 0 to 7 and one 8
+    my $c = 0;
+    my %counts;
+    for my $y (0..$#$tile) {
+        for my $x (0..$#{$tile->[$y]}) {
+            $tile->[$y][$x] = $v;
+            $counts{$v} = $counts{$v} ? $counts{$v}+1 : 1;
+            if (++$c > 2) {
+                ++$v;
+                $c = 0;
+            }
+        }
+    }
+    $band->WriteTile($tile);
+    
+    $c = $band->ClassCounts;
+    is_deeply($c, \%counts, "$datatype: ClassCounts");
+
+    eval {
+        $band->ClassCounts(sub {return 1});
+    };
+    ok(!$@, "ClassCounts overload test $datatype: $@");
+    
+    $band->Reclassify({'*' => 10, 1 => 2, 2 => 3});
+    $c = $band->ClassCounts;
+    is_deeply($c, {2 => 3, 3 => 3, 10 => 19}, "Reclassify with default");
+    
+    $band->WriteTile($tile);
+    $band->Reclassify({1 => 2, 2 => 3});
+    $c = $band->ClassCounts;
+    delete $counts{1};
+    $counts{3} = 6;
+    is_deeply($c, \%counts, "$datatype: Reclassify without default");
+    
+    $band->WriteTile($tile);
+    $band->NoDataValue(5);
+    $band->Reclassify({'*' => 0});
+    $c = $band->ClassCounts;
+    #for my $key (keys %$c) {
+    #    print "$key $c->{$key}\n";
+    #}
+    is_deeply($c, {0 => 22, 5 => 3}, "Reclassify with default does not affect cells with NoData.");
+
+}
+
+for my $datatype (qw/Float32 Float64/) {
+    my $band = Geo::GDAL::Driver('MEM')->Create(Type => $datatype, Width => 2, Height => 2)->Band;
+    my $tile = $band->ReadTile;
+    $tile->[0] = [2,3];
+    $tile->[1] = [5,6];
+    $band->WriteTile($tile);
+
+    # 1   2   3
+    #   3   5
+    my $classifier = ['<', [5.0, [3.0, 1.0, 2.0], 3.0]];
+    my $counts = $band->ClassCounts($classifier);
+    #say STDERR $counts;
+    my @counts;
+    for my $key (sort {$a<=>$b} keys %$counts) {
+        #say STDERR "$key => $counts->{$key}";
+        push @counts, $key => $counts->{$key};
+    }
+    is_deeply(\@counts, [0=>1,1=>1,2=>2], "Class counts $datatype");
+    $band->Reclassify($classifier);
+    $tile = $band->ReadTile;
+    #for my $y (0..$#$tile) {
+    #    say STDERR "@{$tile->[$y]}";
+    #}
+    is_deeply($tile, [[1,2],[3,3]], "Reclassify $datatype");
+
+    eval {
+        $band->Reclassify($classifier, sub {return 1});
+    };
+    ok(!$@, "Reclassify overload test $datatype: $@");
+}
+    
+my $band = Geo::GDAL::Driver('MEM')->Create(Type => 'CFloat32', Width => 5, Height => 5)->Band;
+eval {
+    my $c = $band->ClassCounts;
+};
+ok($@, "ClassCounts works only on integer bands.");
+
+eval {
+    $band->Reclassify({1 => 2, 2 => 3});
+};
+ok($@, "Reclassify works only on integer bands.");
+
+eval {
+    my $c = $band->ClassCounts(sub {return 0});
+};
+ok($@, "Terminating ClassCounts raises an error.");
+
+eval {
+    $band->Reclassify({1 => 2, 2 => 3}, sub {return 0});
+};
+ok($@, "Terminating Reclassify raises an error.");   
diff --git a/swig/perl/t/dataset.t b/swig/perl/t/dataset.t
new file mode 100644
index 0000000..a976537
--- /dev/null
+++ b/swig/perl/t/dataset.t
@@ -0,0 +1,32 @@
+use strict;
+use warnings;
+use Scalar::Util 'blessed';
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+my $d = Geo::GDAL::Driver('MEM')->Create();
+
+my $e = $d->Extent;
+
+is_deeply($e, [0,0,256,256], "Default extent is default size.");
+
+my $g = $d->GeoTransform;
+
+is_deeply($g, [0,1,0,0,0,1], "Default transform.");
+
+$e = $d->Extent(10,20,10,20);
+
+is_deeply($e, [10,20,20,40], "Extent of a tile.");
+
+my @tile = $d->Tile($d->Extent);
+
+is_deeply(\@tile, [0,0,256,256], "As one tile.");
+
+ at tile = $d->Tile($d->Extent(10,20,10,20));
+
+is_deeply(\@tile, [10,20,10,20], "Subtile.");
+
+eval {
+    $d = Geo::GDAL::Driver('MEM')->Create(Width => 12.3);
+};
+ok($@ =~ /^TypeError/, "Catch swig exceptions in error messages.");
diff --git a/swig/perl/t/extent.t b/swig/perl/t/extent.t
new file mode 100644
index 0000000..d24f37e
--- /dev/null
+++ b/swig/perl/t/extent.t
@@ -0,0 +1,83 @@
+use strict;
+use warnings;
+use Scalar::Util 'blessed';
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+my $e = Geo::GDAL::Extent->new;
+
+ok(blessed($e), "Can create new extent objects");
+ok(ref $e eq 'Geo::GDAL::Extent', "Can create new extent objects (2)");
+
+ok($e->IsEmpty, "New, without arguments created extent is empty");
+
+my @s = $e->Size;
+
+is_deeply(\@s, [0,0], "The size of and empty extent is (0,0)");
+
+$e = Geo::GDAL::Extent->new([0,0,1,1]);
+
+ok(!$e->IsEmpty, "New, with arguments created extent is not empty");
+
+ at s = $e->Size;
+
+is_deeply(\@s, [1,1], "The size of 0,0,1,1 extent is 1,1");
+
+$e = Geo::GDAL::Extent->new(0,0,1,1);
+
+ok(!$e->IsEmpty, "New, with arguments created extent is not empty (2)");
+
+ at s = $e->Size;
+
+is_deeply(\@s, [1,1], "The size of 0,0,1,1 extent is 1,1 (2)");
+
+my $f = Geo::GDAL::Extent->new(1,1,2,2);
+ok(!$e->Overlaps($f), "Touching extents do not overlap");
+$f = Geo::GDAL::Extent->new(0.5,0.5,1.5,1.5);
+ok($e->Overlaps($f), "Overlapping extents overlap");
+
+$f = Geo::GDAL::Extent->new(1,-1,2,0);
+ok(!$e->Overlaps($f), "Touching extents do not overlap");
+$f = Geo::GDAL::Extent->new(0.5,-0.5,1.5,0.5);
+ok($e->Overlaps($f), "Overlapping extents overlap");
+
+$f = Geo::GDAL::Extent->new(-1,-1,0,0);
+ok(!$e->Overlaps($f), "Touching extents do not overlap");
+$f = Geo::GDAL::Extent->new(-0.5,-0.5,0.5,0.5);
+ok($e->Overlaps($f), "Overlapping extents overlap");
+
+$f = Geo::GDAL::Extent->new(-1,1,0,2);
+ok(!$e->Overlaps($f), "Touching extents do not overlap");
+$f = Geo::GDAL::Extent->new(-0.5,0.5,0.5,1.5);
+ok($e->Overlaps($f), "Overlapping extents overlap");
+
+$f = Geo::GDAL::Extent->new(0.5,0.5,1.5,1.5);
+my $g = $e->Overlap($f);
+is_deeply($g, [0.5,0.5,1,1], "Overlap is ok");
+
+$f = Geo::GDAL::Extent->new(1,1,2,2);
+$g = $e->Overlap($f);
+ok($g->IsEmpty, "Overlap of not overlapping extents is empty");
+
+$f = Geo::GDAL::Extent->new(1,1,2,2);
+$f->ExpandToInclude($e);
+is_deeply($f, [0,0,2,2], "Expand to NE");
+
+$f = Geo::GDAL::Extent->new(1,-1,2,0);
+$f->ExpandToInclude($e);
+is_deeply($f, [0,-1,2,1], "Expand to SE");
+
+$f = Geo::GDAL::Extent->new(-1,-1,0,0);
+$f->ExpandToInclude($e);
+is_deeply($f, [-1,-1,1,1], "Expand to SW");
+
+$f = Geo::GDAL::Extent->new(-1,1,0,2);
+$f->ExpandToInclude($e);
+is_deeply($f, [-1,0,1,2], "Expand to NW");
+
+$f = Geo::GDAL::Extent->new();
+$e->ExpandToInclude($f);
+is_deeply($e, [0,0,1,1], "Expand with empty");
+
+$f->ExpandToInclude($e);
+is_deeply($f, [0,0,1,1], "Expand empty");
diff --git a/swig/perl/t/feature.t b/swig/perl/t/feature.t
index 2d53a2b..3519a31 100644
--- a/swig/perl/t/feature.t
+++ b/swig/perl/t/feature.t
@@ -3,6 +3,7 @@ use strict;
 use warnings;
 use bytes;
 use v5.10;
+use Config;
 use Test::More qw(no_plan);
 BEGIN { use_ok('Geo::GDAL') };
 
@@ -61,7 +62,7 @@ my $f = Geo::OGR::Feature->new(
     eval {
         $f->{10} = 'x';
     };
-    ok ($@ ne '', "Set field using hashref syntax and field index does not work.");
+    ok ($@ eq '', "Set field using hashref syntax and field index works.");
     eval {
         $f->{No} = 'x';
     };
@@ -105,13 +106,13 @@ my $f = Geo::OGR::Feature->new(
 {
     my $b = 123.456;
     my $c = $f->Field(Real => $b);
-    ok("$b" eq "$c", "Set and get real field.");
+    ok($b-$c < 0.001, "Set and get real field.");
 }
 
 {
     my $b = [123.456,2123.4567];
     my $c = $f->Field(RealList => $b);
-    ok("@$b" eq "@$c", "Set and get real list field.");
+    ok(($b->[0]-$c->[0] < 0.001 and $b->[1]-$c->[1] < 0.001), "Set and get real list field.");
 }
 
 {
@@ -127,15 +128,29 @@ my $f = Geo::OGR::Feature->new(
 }
 
 {
-    my $b = 9223372036854775806;
-    my $c = $f->Field(Integer64 => $b);
-    ok($b eq $c, "Set and get integer64 field.");
+    if ($Config{ivsize} < 8) {
+        use bigint;
+        my $b = 9223372036854775806;
+        my $c = $f->Field(Integer64 => $b);
+        ok($b eq $c, "Set and get integer64 field (with 'use bigint').");
+    } else {
+        my $b = 9223372036854775806;
+        my $c = $f->Field(Integer64 => $b);
+        ok($b eq $c, "Set and get integer64 field.");
+    }
 }
 
 {
-    my $b = [9223372036854775806,12];
-    my $c = $f->Field(Integer64List => $b);
-    ok("@$b" eq "@$c", "Set and get integer64 list field.");
+    if ($Config{ivsize} < 8) {
+        use bigint;
+        my $b = [9223372036854775806,12];
+        my $c = $f->Field(Integer64List => $b);
+        ok("@$b" eq "@$c", "Set and get integer64 list field (with 'use bigint').");
+    } else {
+        my $b = [9223372036854775806,12];
+        my $c = $f->Field(Integer64List => $b);
+        ok("@$b" eq "@$c", "Set and get integer64 list field (with 'use bigint').");
+    }
 }
 
 {
@@ -205,3 +220,91 @@ $f = Geo::OGR::Feature->new(Fields => \@fields);
     my $c = $f->Geometry(Point => $b);
     ok($b->As(Format => 'ISO WKT') eq $c->As(Format => 'ISO WKT'), "Set and get the point field.");
 }
+
+eval {
+    my $geom_type = 'Point';
+    
+    my $fields = [{i => 'Integer'}];
+    
+    my $defn = Geo::OGR::FeatureDefn->new(
+        GeometryType => $geom_type, 
+        Fields => $fields);
+
+    my $feature = Geo::OGR::Feature->new($defn);
+
+    my $layer = Geo::OGR::Driver('Memory')
+        ->Create('test')
+        ->CreateLayer(
+        Name => 'test',
+        GeometryType => $geom_type,
+        Fields => $fields
+        );
+
+    my $name = 'name';
+
+    my $values_in_array = [1, {WKT => 'POINT (1 2)'}];
+    my $values_in_hash = {i => 1, Geometry => {WKT => 'POINT (1 2)'}};
+
+    $feature->Row($values_in_hash);
+
+    my $values_in_feature = $feature;
+    
+    my $f = Geo::OGR::Feature->new(Schema => {Name => $name, Fields => $fields, GeometryType => $geom_type}, 
+                                   Values => $values_in_feature);
+    
+    $f = Geo::OGR::Feature->new($defn);
+    $f = Geo::OGR::Feature->new($feature);
+    $f = Geo::OGR::Feature->new($layer);
+
+    $f = Geo::OGR::Feature->new(Name => $name, Fields => $fields, GeometryType => $geom_type);
+    $f = Geo::OGR::Feature->new({Name => $name, Fields => $fields, GeometryType => $geom_type});
+
+    $f = Geo::OGR::Feature->new(Fields => $fields, GeometryType => $geom_type);
+    $f = Geo::OGR::Feature->new({Fields => $fields, GeometryType => $geom_type});
+
+    $f = Geo::OGR::Feature->new(Fields => $fields);
+    $f = Geo::OGR::Feature->new({Fields => $fields});
+
+    $f = Geo::OGR::Feature->new(Schema => {Name => $name, Fields => $fields, GeometryType => $geom_type}, 
+                                Values => $values_in_array);
+
+    $f = Geo::OGR::Feature->new(Schema => {Name => $name, Fields => $fields, GeometryType => $geom_type}, 
+                                Values => $values_in_hash);
+    
+    $f = Geo::OGR::Feature->new(Schema => {Name => $name, Fields => $fields, GeometryType => $geom_type}, 
+                                Values => $values_in_feature);
+
+    $f = Geo::OGR::Feature->new(Schema => {Fields => $fields, GeometryType => $geom_type}, 
+                                Values => $values_in_array);
+
+    $f = Geo::OGR::Feature->new(Schema => {Fields => $fields, GeometryType => $geom_type}, 
+                                Values => $values_in_hash);
+    
+    $f = Geo::OGR::Feature->new(Schema => {Fields => $fields, GeometryType => $geom_type}, 
+                                Values => $values_in_feature);
+
+    $f = Geo::OGR::Feature->new(Schema => $defn, 
+                                Values => $values_in_array);
+    
+    $f = Geo::OGR::Feature->new(Schema => $feature,
+                                Values => $values_in_hash);
+    
+    $f = Geo::OGR::Feature->new(Schema => $layer,
+                                Values => $values_in_feature);
+
+    $fields = [{i => 'Integer'}, {geom => $geom_type}];
+
+    $f = Geo::OGR::Feature->new(Schema => {Fields => $fields}, 
+                                Values => $values_in_array);
+    
+    $f = Geo::OGR::Feature->new(Schema => {Fields => $fields}, 
+                                Values => $values_in_hash);
+    
+    $f = Geo::OGR::Feature->new(Schema => {Fields => $fields}, 
+                                Values => $values_in_feature);
+    
+
+};
+
+ok(!$@, "Multiple ways to construct a feature tested.");
+
diff --git a/swig/perl/t/geotransform.t b/swig/perl/t/geotransform.t
new file mode 100644
index 0000000..530e101
--- /dev/null
+++ b/swig/perl/t/geotransform.t
@@ -0,0 +1,53 @@
+use strict;
+use warnings;
+use Scalar::Util 'blessed';
+use Test::More qw(no_plan);
+BEGIN { use_ok('Geo::GDAL') };
+
+my $t = Geo::GDAL::GeoTransform->new;
+
+is_deeply($t, [0,1,0,0,0,1], "Default geotransform is 0,1,0, 0,0,1");
+
+$t = Geo::GDAL::GeoTransform->new([0,1,0,0,0,1]);
+
+is_deeply($t, [0,1,0,0,0,1], "Create from array ref");
+
+$t = Geo::GDAL::GeoTransform->new(Geo::GDAL::GeoTransform->new);
+
+is_deeply($t, [0,1,0,0,0,1], "Create from another geotransform");
+
+$t = Geo::GDAL::GeoTransform->new(0,1,0,0,0,1);
+
+is_deeply($t, [0,1,0,0,0,1], "Create from array");
+
+ok($t->NorthUp, "Default is north up");
+
+my @gcps;
+{
+    my @gcp_data = (
+        [0,6,0, 0,0],
+        [4,1,0, 4,5],
+        [0,3,0, 0,3]);
+    
+    for my $gcp (@gcp_data) {
+        push @gcps, Geo::GDAL::GCP->new(@$gcp);
+    }
+}
+
+$t = Geo::GDAL::GeoTransform->new(GCPs => \@gcps);
+@$t = round(@$t);
+is_deeply($t, [0,1,0,6,0,-1], "Create from GCPs");
+
+$t = Geo::GDAL::GeoTransform->new(Extent => [0,0,20,20], CellSize => 1);
+is_deeply($t, [0,1,0,20,0,-1], "Create from extent and cell size");
+
+# from Math::Round
+sub round {
+    my $x;
+    my $half = 0.50000000000008;
+    my @res  = map {
+        if ($_ >= 0) { POSIX::floor($_ + $half); }
+        else { POSIX::ceil($_ - $half); }
+    } @_;
+    return (wantarray) ? @res : $res[0];
+}
diff --git a/swig/perl/t/osr.t b/swig/perl/t/osr.t
index 0cf9602..eaa2915 100644
--- a/swig/perl/t/osr.t
+++ b/swig/perl/t/osr.t
@@ -25,15 +25,17 @@ SKIP: {
     my $src = Geo::OSR::SpatialReference->new(EPSG => 2392);
     my $dst = Geo::OSR::SpatialReference->new(EPSG => 2393);
 
-    skip "PROJSO not set", 1 if (!$ENV{PROJSO} and $^O eq 'MSWin32');
+    skip "PROJSO not set", 3 if (!$ENV{PROJSO} and $^O eq 'MSWin32');
     my ($t1, $t2);
     eval {
 	$t1 = Geo::OSR::CoordinateTransformation->new($src, $dst);
 	$t2 = Geo::OSR::CoordinateTransformation->new($dst, $src);
     };
+    skip "Unable to load PROJ.4 library", 3 if $@ =~ /Unable to load/;
+
     ok($t1, "new Geo::OSR::CoordinateTransformation $@");
 
-    skip "new Geo::OSR::CoordinateTransformation failed",1 unless ($t1 and $t2);
+    skip "new Geo::OSR::CoordinateTransformation failed", 2 unless ($t1 and $t2);
 
     my @points = ([2492055.205, 6830493.772],
 		  [2492065.205, 6830483.772],
diff --git a/swig/perl/t/pdl.t b/swig/perl/t/pdl.t
new file mode 100644
index 0000000..18e5dfb
--- /dev/null
+++ b/swig/perl/t/pdl.t
@@ -0,0 +1,32 @@
+use strict;
+use warnings;
+use Scalar::Util 'blessed';
+use Test::More tests => 5;
+BEGIN { use_ok('Geo::GDAL') };
+
+eval 'require PDL';
+SKIP: {
+      skip "No PDL", 4 if $@;
+
+use_ok('PDL');
+
+my $band = Geo::GDAL::Driver('GTiff')->Create(Name => '/vsimem/test.gtiff', Width => 23, Height => 45)->Band();
+my $t = $band->ReadTile;
+$t->[5][3] = 1;
+$band->WriteTile($t);
+
+my $pdl;
+
+$pdl = $band->Piddle;
+my @s = $pdl->dims;
+ok($s[0] == 23 && $s[1] == 45, "Get right size piddle.");
+
+$pdl = $band->Piddle(1,2,4,4);
+ok($pdl->at(2,3) == 1, "Data in piddle.");
+
+$pdl += 1;
+$band->Piddle($pdl,1,2);
+$t = $band->ReadTile;
+ok($t->[5][3] == 2, "Data from piddle into band.");
+
+}
diff --git a/swig/perl/t/utf8.t b/swig/perl/t/utf8.t
index 49bf9c0..98f155b 100644
--- a/swig/perl/t/utf8.t
+++ b/swig/perl/t/utf8.t
@@ -60,7 +60,7 @@ ok(!utf8::is_utf8($fn), "Perl does not know it has utf8");
 eval {
     Geo::GDAL::VSIF::Unlink($fn);
 };
-ok($@, "decoding utf8 ot utf8 is not a good idea");
+ok($@, "decoding utf8 to utf8 is not a good idea");
 
 Encode::_utf8_on($fn); # yes, you have utf8 now
 Geo::GDAL::VSIF::Unlink($fn);
diff --git a/swig/perl/t/util.t b/swig/perl/t/util.t
index f450013..c439d22 100644
--- a/swig/perl/t/util.t
+++ b/swig/perl/t/util.t
@@ -30,47 +30,3 @@ BEGIN { use_ok('Geo::GDAL') };
     ok($ret->{a} == 2, "named_parameters, hash, new value");
     ok($ret->{c} eq 'abc', "named_parameters, list, default value");
 }
-
-
-# string2int
-my %int2string = (1 => 'a', 2 => 'b', 3 => 'c');
-my %string2int = (a => 1, b => 2, c => 3);
-
-# undef is returned
-{
-    my $a = undef;
-    my $b = Geo::GDAL::string2int($a, \%string2int, \%int2string);
-    ok(!defined $b, "string2int undef is returned");
-}
-
-# default is returned
-{
-    my $a = undef;
-    my $b = Geo::GDAL::string2int($a, \%string2int, \%int2string, 'b');
-    ok($b == 2, "string2int default is returned");
-}
-
-# return given if known int
-{
-    my $a = 2;
-    my $b = Geo::GDAL::string2int($a, \%string2int, \%int2string);
-    ok($b == 2, "string2int return given if known int");
-}
-
-# return string converted to int if known
-{
-    my $a = 'c';
-    my $b = Geo::GDAL::string2int($a, \%string2int, \%int2string);
-    ok($b == 3, "string2int return string converted to int if known");
-}
-
-# error if string is not known
-{
-    my $a = 'x';
-    my $b;
-    eval {
-        $b = Geo::GDAL::string2int($a, \%string2int, \%int2string);
-    };
-    ok($@, "string2int error if string is not known");
-}
-
diff --git a/swig/perl/tips.dox b/swig/perl/tips.dox
new file mode 100644
index 0000000..7897438
--- /dev/null
+++ b/swig/perl/tips.dox
@@ -0,0 +1,75 @@
+/*! \page tips Tips and tricks
+
+This page is for tips and tricks when working with Geo::GDAL.
+
+\section tips_preamble First few lines
+
+You should probably use [Perlbrew](https://perlbrew.pl/) and the latest Perl.
+
+\code
+#!/usr/bin/env perl
+
+use strict;
+use v5.10;
+use Geo::GDAL;
+\endcode
+
+\section tips_progress GDAL style progress function in Perl
+
+\code
+
+# call this somewhere early:
+$|++; # flush print right away for one line progress
+
+sub progress {
+    state $s = -1; # requires 'use v5.10;'
+    my $p = int($_[0]*100);
+    return 1 if $p == $s;
+    $s = 0 if $s < 0;
+    while ($s < $p) {
+        print $s%10 == 0 ? $s : ($s%2 == 0 ? '.' : '');
+        ++$s;
+    }
+    return 1;
+}
+\endcode
+
+Note: this will not catch Ctrl-C (SIGINT). For that you could
+cook up something like the following.
+
+\code
+$SIG{'INT'} = progress('Return 0 next time!');
+# modify progress to understand the above
+\endcode
+
+\section tips_raster_coordinates Get the raster coordinates in iteration
+
+\code
+my $raster = Geo::GDAL::Open('bigraster.tiff');
+my $transform = $raster->GeoTransform;
+my ($xoff, $yoff, $w, $h) = (0, 0, 200, 200);
+$|++;
+while (1) {
+    progress($yoff/$H);
+    if ($xoff >= $W) {
+        $xoff = 0;
+        $yoff += $h;
+        last if $yoff >= $H;
+    }
+    my $data = $raster->Band(1)->ReadTile($xoff, $yoff, min($W-$xoff, $w), min($H-$yoff, $h));
+    for my $y (0..$#$data) {
+        for my $x (0..$#{$data->[$y]}) {
+            my ($px, $py) = $transform->Apply([$xoff+$x], [$yoff+$y]);
+            my $upper_left = Geo::OGR::Geometry->new(   
+                     GeometryType => 'Point',
+                     Points => [$px->[0], $py->[0]])});
+        }
+    }
+    $xoff += $w;
+}
+sub min {
+    return $_[0] < $_[1] ? $_[0] : $_[1];
+}
+\endcode
+
+*/
diff --git a/swig/perl/transform.dox b/swig/perl/transform.dox
index b5ef811..c47935b 100644
--- a/swig/perl/transform.dox
+++ b/swig/perl/transform.dox
@@ -6,7 +6,7 @@ what it does, what input it needs, etc. Do not blindly execute
 anything!
 
 This example will transform a vector dataset from spatial reference
-system EPSG 2392 to EPSG 2393. The geometries are translated 
+system EPSG 2392 to EPSG 2393. The geometries are translated
 by (dx, dy) = (2500000, 6600000) before applying the transformation.
 
 \code
@@ -35,7 +35,7 @@ while ($feature = $layer1->GetNextFeature()) {
     my $geom = $feature->GetGeometry();
     $geom->Move(2500000, 6600000);
     $geom->Transform($tr);
-    $layer2->InsertFeature($feature);    
+    $layer2->InsertFeature($feature);
 }
 \endcode
 
diff --git a/swig/php/GNUmakefile b/swig/php/GNUmakefile
index 57168ce..9aaa88b 100644
--- a/swig/php/GNUmakefile
+++ b/swig/php/GNUmakefile
@@ -12,7 +12,7 @@ CXX=g++
 CFLAGS=-fpic
 LDFLAGS=-shared
 PHP_INC=`php-config --includes`
-EXTRA_INC=-I../../port -I../../gcore -I../../alg -I../../ogr
+EXTRA_INC=-I../../port -I../../gcore -I../../alg -I../../ogr -I../../apps
 EXTRA_LIB=
 
 all_libs = php_gdal.so php_ogr.so php_gdalconst.so php_osr.so
diff --git a/swig/php/gdal.php b/swig/php/gdal.php
index 2972074..149cef1 100644
--- a/swig/php/gdal.php
+++ b/swig/php/gdal.php
@@ -3,11 +3,11 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
  * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 // Try to load our extension if it's not already loaded.
diff --git a/swig/php/gdalconst.php b/swig/php/gdalconst.php
index a7437a9..b6bf3c2 100644
--- a/swig/php/gdalconst.php
+++ b/swig/php/gdalconst.php
@@ -3,11 +3,11 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
  * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 // Try to load our extension if it's not already loaded.
diff --git a/swig/php/ogr.php b/swig/php/ogr.php
index ae05554..5947873 100644
--- a/swig/php/ogr.php
+++ b/swig/php/ogr.php
@@ -3,11 +3,11 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
  * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 // Try to load our extension if it's not already loaded.
diff --git a/swig/php/osr.php b/swig/php/osr.php
index c0e6f52..88f8050 100644
--- a/swig/php/osr.php
+++ b/swig/php/osr.php
@@ -3,11 +3,11 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
  * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 // Try to load our extension if it's not already loaded.
diff --git a/swig/php/php_gdal.h b/swig/php/php_gdal.h
index e97e7f1..5e782b0 100644
--- a/swig/php/php_gdal.h
+++ b/swig/php/php_gdal.h
@@ -1,11 +1,11 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
  * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 #ifndef PHP_GDAL_H
diff --git a/swig/php/php_gdalconst.h b/swig/php/php_gdalconst.h
index 5911622..8fcfefe 100644
--- a/swig/php/php_gdalconst.h
+++ b/swig/php/php_gdalconst.h
@@ -1,11 +1,11 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
  * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 #ifndef PHP_GDALCONST_H
diff --git a/swig/php/php_ogr.h b/swig/php/php_ogr.h
index 8129a35..2ff1164 100644
--- a/swig/php/php_ogr.h
+++ b/swig/php/php_ogr.h
@@ -1,11 +1,11 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
  * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 #ifndef PHP_OGR_H
diff --git a/swig/php/php_osr.h b/swig/php/php_osr.h
index 5cd7003..5f4546e 100644
--- a/swig/php/php_osr.h
+++ b/swig/php/php_osr.h
@@ -1,11 +1,11 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
  * Version 1.3.40
- * 
- * This file is not intended to be easily readable and contains a number of 
+ *
+ * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG 
- * interface file instead. 
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
  * ----------------------------------------------------------------------------- */
 
 #ifndef PHP_OSR_H
diff --git a/swig/python/GNUmakefile b/swig/python/GNUmakefile
index 57b31a7..3f7cfb0 100644
--- a/swig/python/GNUmakefile
+++ b/swig/python/GNUmakefile
@@ -14,7 +14,7 @@ include ../SWIGmake.base
 PACKAGE_DIR=osgeo
 SWIGOUTPUTDIR=extensions/
 
-SCRIPTS			= `ls ./scripts`
+SCRIPTS			= `ls ./scripts/*.py`
 PY_COMMANDS     =       epsg_tr.py gdalchksum.py gdal2xyz.py gcps2wld.py \
                         gdalimport.py gdal_merge.py pct2rgb.py rgb2pct.py \
                         gcps2vec.py
@@ -28,6 +28,7 @@ clean:
 	-rm -f *.so ./osgeo/*.so
 	-rm -rf dist
 
+SWIGARGS += -threads
 SWIGARGS += -outdir "${PACKAGE_DIR}" 
 
 
@@ -49,11 +50,7 @@ osr_wrap.cpp: ../include/python/osr_python.i
 gdal_array_wrap.cpp:  ../include/gdal_array.i ../include/python/typemaps_python.i
 	$(SWIG) $(SWIGARGS) $(SWIGDEFINES) -I$(GDAL_ROOT) -c++ -$(BINDING) -o $(SWIGOUTPUTDIR)$@ gdal_array.i
 
-# A few hacks (cat, mv) : the first one for SWIG < 1.3.36 and the second one for SWIG <= 1.3.39 python 3.X on 64bit platforms
-# The python3.2.patch is from https://sourceforge.net/tracker/?func=detail&aid=3057804&group_id=1645&atid=101645
-# and is no longer necessary with swig 2.0.4
 generate: ${WRAPPERS} gdal_array_wrap.cpp
-	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed "s/PyErr_Format(PyExc_RuntimeError, mesg)/PyErr_SetString(PyExc_RuntimeError, mesg)/" ${SWIGOUTPUTDIR}/$$i | sed "s/int len;/Py_ssize_t len;/" > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
 	# Following is to prevent Coverity Scan to warn about Dereference before null check (REVERSE_INULL)
 	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed "s/if (!PyTuple_Check(args)) SWIG_fail;/if (args == NULL || !PyTuple_Check(args)) SWIG_fail;/" ${SWIGOUTPUTDIR}/$$i | sed "s/argc = args ? (int)PyObject_Length(args) : 0/argc = (int)PyObject_Length(args)/" > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
 	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed "s/if (SWIG_IsTmpObj(res\([1-9]\)))/if (ReturnSame(SWIG_IsTmpObj(res\1)))/" ${SWIGOUTPUTDIR}/$$i  > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
@@ -64,11 +61,6 @@ generate: ${WRAPPERS} gdal_array_wrap.cpp
 	# Unused assigned variable
 	for i in gdal_wrap.cpp gdalconst_wrap.c ogr_wrap.cpp osr_wrap.cpp gdal_array_wrap.cpp gnm_wrap.cpp; do if test -f ${SWIGOUTPUTDIR}/$$i; then sed 's/module_head = \&swig_module;/\/\*module_head = \&swig_module;\*\//' ${SWIGOUTPUTDIR}/$$i  > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; fi; done
 	for i in gdal_wrap.cpp; do sed 's/result = (CPLErr)\(.*\);/CPL_IGNORE_RET_VAL(result = (CPLErr)\1);/' ${SWIGOUTPUTDIR}/$$i  > ${SWIGOUTPUTDIR}/$$i.tmp; mv -f ${SWIGOUTPUTDIR}/$$i.tmp ${SWIGOUTPUTDIR}/$$i; done
-	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && patch -p0 < python3.2.patch
-	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap/ogr_wrap/" | patch -p0
-	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap/osr_wrap/" | patch -p0
-	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap\.cpp/gdalconst_wrap\.c/" | patch -p0
-	-grep "1\.3\.40" extensions/gdal_wrap.cpp >/dev/null && cat python3.2.patch | sed "s/gdal_wrap/gdal_array_wrap/" | patch -p0
 
 build: extensions/gdal_wrap.cpp
 	rm -f setup_vars.ini
@@ -123,7 +115,7 @@ install:
 	fi
 	env PYTHONPATH=$(site_package_dir)$${PYTHONPATH:+:$$PYTHONPATH} \
 		$(PYTHON) setup.py install ${setup_opts}
-	for f in $(SCRIPTS) ; do $(INSTALL) ./scripts/$$f $(DESTDIR)$(INST_BIN) ; done
+	for f in $(SCRIPTS) ; do $(INSTALL) $$f $(DESTDIR)$(INST_BIN) ; done
 
 # see swig/include/python/docs/README to refresh the  ../include/python/docs/ files
 docs:
diff --git a/swig/python/README.txt b/swig/python/README.txt
index 17ebafb..2b077e8 100644
--- a/swig/python/README.txt
+++ b/swig/python/README.txt
@@ -16,7 +16,7 @@ reference documentation, but the `GDAL API Tutorial`_ includes Python examples.
 Dependencies
 ------------
  
- * libgdal (1.11.0 or greater) and header files (gdal-devel)
+ * libgdal (2.2.0 or greater) and header files (gdal-devel)
  * numpy (1.0.0 or greater) and header files (numpy-devel) (not explicitly 
    required, but many examples and utilities will not work without it)
 
diff --git a/swig/python/extensions/gdal_array_wrap.cpp b/swig/python/extensions/gdal_array_wrap.cpp
index 12e6559..bdcb361 100644
--- a/swig/python/extensions/gdal_array_wrap.cpp
+++ b/swig/python/extensions/gdal_array_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
+ * Version 3.0.8
  *
  * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -8,7 +8,12 @@
  * interface file instead.
  * ----------------------------------------------------------------------------- */
 
+
+#ifndef SWIGPYTHON
 #define SWIGPYTHON
+#endif
+
+#define SWIG_PYTHON_THREADS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 
@@ -143,6 +148,19 @@ template <typename T> T SwigValueInit() {
 # define _SCL_SECURE_NO_DEPRECATE
 #endif
 
+/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
+#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
+# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
+/* Intel's compiler complains if a variable which was never initialised is
+ * cast to void, which is a common idiom which we use to indicate that we
+ * are aware a variable isn't used.  So we just silence that warning.
+ * See: https://github.com/swig/swig/issues/192 for more discussion.
+ */
+#ifdef __INTEL_COMPILER
+# pragma warning disable 592
+#endif
 
 
 #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
@@ -560,14 +578,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   swig_module_info *iter = start;
   do {
     if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
+      size_t l = 0;
+      size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
+	size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
-	  register int compare = strcmp(name, iname);
+	  int compare = strcmp(name, iname);
 	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
@@ -611,7 +629,7 @@ SWIG_TypeQueryModule(swig_module_info *start,
        of the str field (the human readable name) */
     swig_module_info *iter = start;
     do {
-      register size_t i = 0;
+      size_t i = 0;
       for (; i < iter->size; ++i) {
 	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
 	  return iter->types[i];
@@ -630,10 +648,10 @@ SWIG_TypeQueryModule(swig_module_info *start,
 SWIGRUNTIME char *
 SWIG_PackData(char *c, void *ptr, size_t sz) {
   static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
+  const unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu =  u + sz;
   for (; u != eu; ++u) {
-    register unsigned char uu = *u;
+    unsigned char uu = *u;
     *(c++) = hex[(uu & 0xf0) >> 4];
     *(c++) = hex[uu & 0xf];
   }
@@ -645,11 +663,11 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
 */
 SWIGRUNTIME const char *
 SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
+  unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu = u + sz;
   for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
+    char d = *(c++);
+    unsigned char uu;
     if ((d >= '0') && (d <= '9'))
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
@@ -1312,7 +1330,7 @@ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
 
 /* Unpack the argument tuple */
 
-SWIGINTERN int
+SWIGINTERN Py_ssize_t
 SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
 {
   if (!args) {
@@ -1326,7 +1344,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
   }  
   if (!PyTuple_Check(args)) {
     if (min <= 1 && max >= 1) {
-      register int i;
+      Py_ssize_t i;
       objs[0] = args;
       for (i = 1; i < max; ++i) {
 	objs[i] = 0;
@@ -1336,7 +1354,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
-    register Py_ssize_t l = PyTuple_GET_SIZE(args);
+    Py_ssize_t l = PyTuple_GET_SIZE(args);
     if (l < min) {
       PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
 		   name, (min == max ? "" : "at least "), (int)min, (int)l);
@@ -1346,7 +1364,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 		   name, (min == max ? "" : "at most "), (int)max, (int)l);
       return 0;
     } else {
-      register int i;
+      Py_ssize_t i;
       for (i = 0; i < l; ++i) {
 	objs[i] = PyTuple_GET_ITEM(args, i);
       }
@@ -1532,6 +1550,23 @@ typedef struct {
 #endif
 } SwigPyObject;
 
+
+#ifdef SWIGPYTHON_BUILTIN
+
+SWIGRUNTIME PyObject *
+SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+
+  if (!sobj->dict)
+    sobj->dict = PyDict_New();
+
+  Py_INCREF(sobj->dict);
+  return sobj->dict;
+}
+
+#endif
+
 SWIGRUNTIME PyObject *
 SwigPyObject_long(SwigPyObject *v)
 {
@@ -1670,16 +1705,32 @@ SwigPyObject_dealloc(PyObject *v)
     if (destroy) {
       /* destroy is always a VARARGS method */
       PyObject *res;
+
+      /* PyObject_CallFunction() has the potential to silently drop
+         the active active exception.  In cases of unnamed temporary
+         variable or where we just finished iterating over a generator
+         StopIteration will be active right now, and this needs to
+         remain true upon return from SwigPyObject_dealloc.  So save
+         and restore. */
+      
+      PyObject *val = NULL, *type = NULL, *tb = NULL;
+      PyErr_Fetch(&val, &type, &tb);
+
       if (data->delargs) {
-	/* we need to create a temporary object to carry the destroy operation */
-	PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
-	res = SWIG_Python_CallFunctor(destroy, tmp);
-	Py_DECREF(tmp);
+        /* we need to create a temporary object to carry the destroy operation */
+        PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
+        res = SWIG_Python_CallFunctor(destroy, tmp);
+        Py_DECREF(tmp);
       } else {
-	PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
-	PyObject *mself = PyCFunction_GET_SELF(destroy);
-	res = ((*meth)(mself, v));
+        PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+        PyObject *mself = PyCFunction_GET_SELF(destroy);
+        res = ((*meth)(mself, v));
       }
+      if (!res)
+        PyErr_WriteUnraisable(destroy);
+
+      PyErr_Restore(val, type, tb);
+
       Py_XDECREF(res);
     } 
 #if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
@@ -1703,6 +1754,7 @@ SwigPyObject_append(PyObject* v, PyObject* next)
   next = tmp;
 #endif
   if (!SwigPyObject_Check(next)) {
+    PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject");
     return NULL;
   }
   sobj->next = next;
@@ -1802,7 +1854,7 @@ swigobject_methods[] = {
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_VARARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS,  (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_VARARGS,  (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_VARARGS,  (char *)"returns the next 'this' object"},
@@ -1858,7 +1910,9 @@ SwigPyObject_TypeOnce(void) {
     (unaryfunc)SwigPyObject_oct,  /*nb_oct*/
     (unaryfunc)SwigPyObject_hex,  /*nb_hex*/
 #endif
-#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */
+#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
 #elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
@@ -1938,10 +1992,19 @@ SwigPyObject_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpyobject_type = tmp;
@@ -2117,10 +2180,19 @@ SwigPyPacked_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpypacked_type = tmp;
@@ -2461,7 +2533,7 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
     }
   } else {
 #if PY_VERSION_HEX >= 0x03000000
-    inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
+    inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
     if (inst) {
       PyObject_SetAttr(inst, SWIG_This(), swig_this);
       Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
@@ -2571,18 +2643,21 @@ SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int f
 	  newobj = (SwigPyObject *) newobj->next;
         newobj->next = next_self;
         newobj = (SwigPyObject *)next_self;
+#ifdef SWIGPYTHON_BUILTIN
+        newobj->dict = 0;
+#endif
       }
     } else {
       newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
     }
     if (newobj) {
       newobj->ptr = ptr;
       newobj->ty = type;
       newobj->own = own;
       newobj->next = 0;
-#ifdef SWIGPYTHON_BUILTIN
-      newobj->dict = 0;
-#endif
       return (PyObject*) newobj;
     }
     return SWIG_Py_Void();
@@ -2645,13 +2720,11 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 {
   PyObject *dict;
   if (!PyModule_Check(m)) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs module as first arg");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg");
     return SWIG_ERROR;
   }
   if (!o) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs non-NULL value");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value");
     return SWIG_ERROR;
   }
   
@@ -2975,7 +3048,7 @@ static swig_module_info swig_module = {swig_types, 13, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_gdal_array"
 
-#define SWIGVERSION 0x020012 
+#define SWIGVERSION 0x030008 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -2998,27 +3071,35 @@ namespace swig {
 
     SwigPtr_PyObject(const SwigPtr_PyObject& item) : _obj(item._obj)
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(_obj);      
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     SwigPtr_PyObject(PyObject *obj, bool initial_ref = true) :_obj(obj)
     {
       if (initial_ref) {
+        SWIG_PYTHON_THREAD_BEGIN_BLOCK;
         Py_XINCREF(_obj);
+        SWIG_PYTHON_THREAD_END_BLOCK;
       }
     }
     
     SwigPtr_PyObject & operator=(const SwigPtr_PyObject& item) 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(item._obj);
       Py_XDECREF(_obj);
       _obj = item._obj;
+      SWIG_PYTHON_THREAD_END_BLOCK;
       return *this;      
     }
     
     ~SwigPtr_PyObject() 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XDECREF(_obj);
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     operator PyObject *() const
@@ -3048,6 +3129,17 @@ namespace swig {
 }
 
 
+// Define this unconditionnaly of whether DEBUG_BOOL is defined or not,
+// since we do not pass -DDEBUG_BOOL when building the bindings
+#define DO_NOT_USE_DEBUG_BOOL
+
+// So that override is properly defined
+#ifndef GDAL_COMPILATION
+#define GDAL_COMPILATION
+#endif
+
+
+
 #include "gdal.h"
 
 typedef struct
@@ -3086,9 +3178,11 @@ SWIG_AsVal_double (PyObject *obj, double *val)
   if (PyFloat_Check(obj)) {
     if (val) *val = PyFloat_AsDouble(obj);
     return SWIG_OK;
+#if PY_VERSION_HEX < 0x03000000
   } else if (PyInt_Check(obj)) {
     if (val) *val = PyInt_AsLong(obj);
     return SWIG_OK;
+#endif
   } else if (PyLong_Check(obj)) {
     double v = PyLong_AsDouble(obj);
     if (!PyErr_Occurred()) {
@@ -3180,18 +3274,7 @@ SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val)
       return SWIG_OK;
     } else {
       PyErr_Clear();
-#if PY_VERSION_HEX >= 0x03000000
-      {
-        long v = PyLong_AsLong(obj);
-        if (!PyErr_Occurred()) {
-          if (v < 0) {
-            return SWIG_OverflowError;
-          }
-        } else {
-          PyErr_Clear();
-        }
-      }
-#endif
+      return SWIG_OverflowError;
     }
   }
 #ifdef SWIG_PYTHON_CAST_MODE
@@ -3241,16 +3324,20 @@ SWIG_AsVal_size_t (PyObject * obj, size_t *val)
 SWIGINTERN int
 SWIG_AsVal_long (PyObject *obj, long* val)
 {
+#if PY_VERSION_HEX < 0x03000000
   if (PyInt_Check(obj)) {
     if (val) *val = PyInt_AsLong(obj);
     return SWIG_OK;
-  } else if (PyLong_Check(obj)) {
+  } else
+#endif
+  if (PyLong_Check(obj)) {
     long v = PyLong_AsLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_OK;
     } else {
       PyErr_Clear();
+      return SWIG_OverflowError;
     }
   }
 #ifdef SWIG_PYTHON_CAST_MODE
@@ -3410,16 +3497,16 @@ class NUMPYDataset : public GDALDataset
                  NUMPYDataset();
                  ~NUMPYDataset();
 
-    virtual const char *GetProjectionRef(void);
-    virtual CPLErr SetProjection( const char * );
-    virtual CPLErr GetGeoTransform( double * );
-    virtual CPLErr SetGeoTransform( double * );
+    virtual const char *GetProjectionRef(void) override;
+    virtual CPLErr SetProjection( const char * ) override;
+    virtual CPLErr GetGeoTransform( double * ) override;
+    virtual CPLErr SetGeoTransform( double * ) override;
 
-    virtual int    GetGCPCount();
-    virtual const char *GetGCPProjection();
-    virtual const GDAL_GCP *GetGCPs();
+    virtual int    GetGCPCount() override;
+    virtual const char *GetGCPProjection() override;
+    virtual const GDAL_GCP *GetGCPs() override;
     virtual CPLErr SetGCPs( int nGCPCount, const GDAL_GCP *pasGCPList,
-                            const char *pszGCPProjection );
+                            const char *pszGCPProjection ) override;
 
     static GDALDataset *Open( PyArrayObject *psArray );
     static GDALDataset *Open( GDALOpenInfo * );
@@ -3491,7 +3578,13 @@ NUMPYDataset::~NUMPYDataset()
     }
 
     FlushCache();
+
+    // Although the module has thread disabled, we go here from GDALClose()
+    SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
     Py_DECREF( psArray );
+
+    SWIG_PYTHON_THREAD_END_BLOCK;
 }
 
 /************************************************************************/
@@ -3624,7 +3717,8 @@ GDALDataset *NUMPYDataset::Open( GDALOpenInfo * poOpenInfo )
         return NULL;
     }
 
-    if( !CSLTestBoolean(CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME", "FALSE")) )
+    if( !CPLTestBool(CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME",
+                                        "FALSE")) )
     {
         if( CPLGetConfigOption("GDAL_ARRAY_OPEN_BY_FILENAME", NULL) == NULL )
         {
@@ -3750,20 +3844,36 @@ GDALDataset* NUMPYDataset::Open( PyArrayObject *psArray )
 
     if( psArray->nd == 3 )
     {
-        nBands = psArray->dimensions[0];
+        if( psArray->dimensions[0] > INT_MAX ||
+            psArray->dimensions[1] > INT_MAX ||
+            psArray->dimensions[2] > INT_MAX ||
+            !GDALCheckBandCount(static_cast<int>(psArray->dimensions[0]), 0) )
+        {
+            CPLError(CE_Failure, CPLE_NotSupported,
+                     "Too big array dimensions");
+            delete poDS;
+            return NULL;
+        }
+        nBands = static_cast<int>(psArray->dimensions[0]);
         nBandOffset = psArray->strides[0];
-        poDS->nRasterXSize = psArray->dimensions[2];
+        poDS->nRasterXSize = static_cast<int>(psArray->dimensions[2]);
         nPixelOffset = psArray->strides[2];
-        poDS->nRasterYSize = psArray->dimensions[1];
+        poDS->nRasterYSize = static_cast<int>(psArray->dimensions[1]);
         nLineOffset = psArray->strides[1];
     }
     else
     {
+        if( psArray->dimensions[0] > INT_MAX ||
+            psArray->dimensions[1] > INT_MAX )
+        {
+            delete poDS;
+            return NULL;
+        }
         nBands = 1;
         nBandOffset = 0;
-        poDS->nRasterXSize = psArray->dimensions[1];
+        poDS->nRasterXSize = static_cast<int>(psArray->dimensions[1]);
         nPixelOffset = psArray->strides[1];
-        poDS->nRasterYSize = psArray->dimensions[0];
+        poDS->nRasterYSize = static_cast<int>(psArray->dimensions[0]);
         nLineOffset = psArray->strides[0];
     }
 
@@ -3846,18 +3956,17 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 #else
 	if (*alloc == SWIG_NEWOBJ) 
 #endif
-	  {
-	    *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
-	    *alloc = SWIG_NEWOBJ;
-	  }
-	else {
+	{
+	  *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+	  *alloc = SWIG_NEWOBJ;
+	} else {
 	  *cptr = cstr;
 	  *alloc = SWIG_OLDOBJ;
 	}
       } else {
-        #if PY_VERSION_HEX>=0x03000000
-        assert(0); /* Should never reach here in Python 3 */
-        #endif
+	#if PY_VERSION_HEX>=0x03000000
+	assert(0); /* Should never reach here in Python 3 */
+	#endif
 	*cptr = SWIG_Python_str_AsChar(obj);
       }
     }
@@ -3867,6 +3976,30 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 #endif
     return SWIG_OK;
   } else {
+#if defined(SWIG_PYTHON_2_UNICODE)
+#if PY_VERSION_HEX<0x03000000
+    if (PyUnicode_Check(obj)) {
+      char *cstr; Py_ssize_t len;
+      if (!alloc && cptr) {
+        return SWIG_RuntimeError;
+      }
+      obj = PyUnicode_AsUTF8String(obj);
+      if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) {
+        if (cptr) {
+          if (alloc) *alloc = SWIG_NEWOBJ;
+          *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+        }
+        if (psize) *psize = len + 1;
+
+        Py_XDECREF(obj);
+        return SWIG_OK;
+      } else {
+        Py_XDECREF(obj);
+      }
+    }
+#endif
+#endif
+
     swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
     if (pchar_descriptor) {
       void* vptr = 0;
@@ -3922,6 +4055,8 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
     if( pszMessage == NULL )
         pszMessage = "";
 
+    SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
     if( psInfo->psPyCallbackData == NULL )
         psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, Py_None );
     else
@@ -3934,16 +4069,19 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
     if( PyErr_Occurred() != NULL )
     {
         PyErr_Clear();
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return FALSE;
     }
 
     if( psResult == NULL )
     {
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return TRUE;
     }
 
     if( psResult == Py_None )
     {
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return TRUE;
     }
 
@@ -3952,10 +4090,12 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
         PyErr_Clear();
         CPLError(CE_Failure, CPLE_AppDefined, "bad progress return value");
         Py_XDECREF(psResult);
-	return FALSE;
+        SWIG_PYTHON_THREAD_END_BLOCK;
+        return FALSE;
     }
 
     Py_XDECREF(psResult);
+    SWIG_PYTHON_THREAD_END_BLOCK;
 
     return bContinue;
 }
@@ -3974,7 +4114,7 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     GDALRegister_NUMPY();
 
     /* I wish I had a safe way of checking the type */
-    sprintf( szString, "NUMPY:::%p", psArray );
+    snprintf( szString, sizeof(szString), "NUMPY:::%p", psArray );
     return CPLStrdup(szString);
 }
 
@@ -3998,9 +4138,17 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
     int xdim = ( psArray->nd == 2) ? 1 : 2;
     int ydim = ( psArray->nd == 2) ? 0 : 1;
 
-    int nxsize, nysize, pixel_space, line_space;
-    nxsize = psArray->dimensions[xdim];
-    nysize = psArray->dimensions[ydim];
+    if( psArray->dimensions[xdim] > INT_MAX ||
+        psArray->dimensions[ydim] > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "Too big array dimensions");
+        return CE_Failure;
+    }
+    int nxsize, nysize;
+    GSpacing pixel_space, line_space;
+    nxsize = static_cast<int>(psArray->dimensions[xdim]);
+    nysize = static_cast<int>(psArray->dimensions[ydim]);
     pixel_space = psArray->strides[xdim];
     line_space = psArray->strides[ydim];
 
@@ -4047,12 +4195,20 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
 
     int xdim = 2;
     int ydim = 1;
+    if( psArray->dimensions[xdim] > INT_MAX ||
+        psArray->dimensions[ydim] > INT_MAX ||
+        psArray->dimensions[0] > INT_MAX )
+    {
+        CPLError(CE_Failure, CPLE_NotSupported,
+                    "Too big array dimensions");
+        return CE_Failure;
+    }
 
     int bandsize, nxsize, nysize;
     GIntBig pixel_space, line_space, band_space;
-    nxsize = psArray->dimensions[xdim];
-    nysize = psArray->dimensions[ydim];
-    bandsize = psArray->dimensions[0];
+    nxsize = static_cast<int>(psArray->dimensions[xdim]);
+    nysize = static_cast<int>(psArray->dimensions[ydim]);
+    bandsize = static_cast<int>(psArray->dimensions[0]);
     if( bandsize != GDALGetRasterCount(ds) )
     {
         CPLError( CE_Failure, CPLE_AppDefined,
@@ -4097,8 +4253,14 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
                   PyArray_NDIM(psArray) );
         return CE_Failure;
     }
+    if( PyArray_DIM(psArray, 0) > INT_MAX )
+    {
+        CPLError( CE_Failure, CPLE_NotSupported,
+                  "Too big array dimension");
+        return CE_Failure;
+    }
 
-    int nLength = PyArray_DIM(psArray, 0);
+    int nLength = static_cast<int>(PyArray_DIM(psArray, 0));
     int nType = PyArray_TYPE(psArray);
     CPLErr retval = CE_None;
 
@@ -4198,7 +4360,7 @@ retStringAndCPLFree* GetArrayFilename(PyArrayObject *psArray)
         {
             // note strlen doesn't include null char
             // but that is what numpy expects so all good
-            nLen = strlen(papszStringList[n]);
+            nLen = static_cast<int>(strlen(papszStringList[n]));
             if( nLen > nMaxLen )
                 nMaxLen = nLen;
         }
@@ -4267,7 +4429,11 @@ SWIGINTERN PyObject *_wrap_delete_VirtualMem(PyObject *SWIGUNUSEDPARM(self), PyO
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_VirtualMem" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
   }
   arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
-  delete_CPLVirtualMemShadow(arg1);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    delete_CPLVirtualMemShadow(arg1);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -4303,7 +4469,11 @@ SWIGINTERN PyObject *_wrap_VirtualMem_GetAddr(PyObject *SWIGUNUSEDPARM(self), Py
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMem_GetAddr" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
   }
   arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
-  CPLVirtualMemShadow_GetAddr(arg1,arg2,arg3,arg4,arg5);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    CPLVirtualMemShadow_GetAddr(arg1,arg2,arg3,arg4,arg5);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   {
 #if PY_VERSION_HEX >= 0x02070000
@@ -4404,7 +4574,11 @@ SWIGINTERN PyObject *_wrap_VirtualMem_Pin__SWIG_0(PyObject *SWIGUNUSEDPARM(self)
     SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "VirtualMem_Pin" "', argument " "4"" of type '" "int""'");
   } 
   arg4 = static_cast< int >(val4);
-  CPLVirtualMemShadow_Pin__SWIG_0(arg1,arg2,arg3,arg4);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    CPLVirtualMemShadow_Pin__SWIG_0(arg1,arg2,arg3,arg4);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -4443,7 +4617,11 @@ SWIGINTERN PyObject *_wrap_VirtualMem_Pin__SWIG_1(PyObject *SWIGUNUSEDPARM(self)
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VirtualMem_Pin" "', argument " "3"" of type '" "size_t""'");
   } 
   arg3 = static_cast< size_t >(val3);
-  CPLVirtualMemShadow_Pin__SWIG_0(arg1,arg2,arg3);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    CPLVirtualMemShadow_Pin__SWIG_0(arg1,arg2,arg3);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -4473,7 +4651,11 @@ SWIGINTERN PyObject *_wrap_VirtualMem_Pin__SWIG_2(PyObject *SWIGUNUSEDPARM(self)
     SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VirtualMem_Pin" "', argument " "2"" of type '" "size_t""'");
   } 
   arg2 = static_cast< size_t >(val2);
-  CPLVirtualMemShadow_Pin__SWIG_0(arg1,arg2);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    CPLVirtualMemShadow_Pin__SWIG_0(arg1,arg2);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -4494,7 +4676,11 @@ SWIGINTERN PyObject *_wrap_VirtualMem_Pin__SWIG_3(PyObject *SWIGUNUSEDPARM(self)
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VirtualMem_Pin" "', argument " "1"" of type '" "CPLVirtualMemShadow *""'"); 
   }
   arg1 = reinterpret_cast< CPLVirtualMemShadow * >(argp1);
-  CPLVirtualMemShadow_Pin__SWIG_0(arg1);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    CPLVirtualMemShadow_Pin__SWIG_0(arg1);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   return resultobj;
 fail:
@@ -4503,12 +4689,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_VirtualMem_Pin(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[5];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[5] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 4) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -4651,6 +4839,17 @@ fail:
 }
 
 
+SWIGINTERN PyObject *TermProgress_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  
+  return SWIG_Py_Void();
+}
+
+
 SWIGINTERN PyObject *_wrap_OpenNumPyArray(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   PyArrayObject *arg1 = (PyArrayObject *) 0 ;
@@ -4850,7 +5049,11 @@ SWIGINTERN PyObject *_wrap_BandRasterIONumPy(PyObject *SWIGUNUSEDPARM(self), PyO
       psProgressInfo->psPyCallbackData = obj10 ;
     }
   }
-  result = (CPLErr)BandRasterIONumPy(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result = (CPLErr)BandRasterIONumPy(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) ( void* callback_data=NULL)  */
@@ -5008,7 +5211,11 @@ SWIGINTERN PyObject *_wrap_DatasetIONumPy(PyObject *SWIGUNUSEDPARM(self), PyObje
       psProgressInfo->psPyCallbackData = obj10 ;
     }
   }
-  result = (CPLErr)DatasetIONumPy(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result = (CPLErr)DatasetIONumPy(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
     /* %typemap(freearg) ( void* callback_data=NULL)  */
@@ -5154,8 +5361,8 @@ SWIGINTERN PyObject *_wrap_VirtualMemGetArray(PyObject *SWIGUNUSEDPARM(self), Py
     }
     else
     {
-      int nTilesPerRow = (nBufXSize + nTileXSize - 1) / nTileXSize;
-      int nTilesPerCol = (nBufYSize + nTileYSize - 1) / nTileYSize;
+      npy_intp nTilesPerRow = static_cast<npy_intp>((nBufXSize + nTileXSize - 1) / nTileXSize);
+      npy_intp nTilesPerCol = static_cast<npy_intp>((nBufYSize + nTileYSize - 1) / nTileYSize);
       npy_intp shape[5], stride[5];
       if( nBandCount == 1 )
       {
@@ -5350,18 +5557,11 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"VirtualMem_swigregister", VirtualMem_swigregister, METH_VARARGS, NULL},
 	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"},
+	 { (char *)"TermProgress_swigconstant", TermProgress_swigconstant, METH_VARARGS, NULL},
 	 { (char *)"OpenNumPyArray", _wrap_OpenNumPyArray, METH_VARARGS, (char *)"OpenNumPyArray(PyArrayObject * psArray) -> Dataset"},
 	 { (char *)"GetArrayFilename", _wrap_GetArrayFilename, METH_VARARGS, (char *)"GetArrayFilename(PyArrayObject * psArray) -> retStringAndCPLFree *"},
-	 { (char *)"BandRasterIONumPy", (PyCFunction) _wrap_BandRasterIONumPy, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"BandRasterIONumPy(Band band, int bWrite, double xoff, double yoff, double xsize, double ysize, PyArrayObject * psArray, \n"
-		"    int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> CPLErr\n"
-		""},
-	 { (char *)"DatasetIONumPy", (PyCFunction) _wrap_DatasetIONumPy, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"DatasetIONumPy(Dataset ds, int bWrite, int xoff, int yoff, int xsize, int ysize, PyArrayObject * psArray, \n"
-		"    int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> CPLErr\n"
-		""},
+	 { (char *)"BandRasterIONumPy", (PyCFunction) _wrap_BandRasterIONumPy, METH_VARARGS | METH_KEYWORDS, (char *)"BandRasterIONumPy(Band band, int bWrite, double xoff, double yoff, double xsize, double ysize, PyArrayObject * psArray, int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"},
+	 { (char *)"DatasetIONumPy", (PyCFunction) _wrap_DatasetIONumPy, METH_VARARGS | METH_KEYWORDS, (char *)"DatasetIONumPy(Dataset ds, int bWrite, int xoff, int yoff, int xsize, int ysize, PyArrayObject * psArray, int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"},
 	 { (char *)"VirtualMemGetArray", _wrap_VirtualMemGetArray, METH_VARARGS, (char *)"VirtualMemGetArray(VirtualMem virtualmem)"},
 	 { (char *)"RATValuesIONumPyWrite", (PyCFunction) _wrap_RATValuesIONumPyWrite, METH_VARARGS | METH_KEYWORDS, (char *)"RATValuesIONumPyWrite(RasterAttributeTable poRAT, int nField, int nStart, PyArrayObject * psArray) -> CPLErr"},
 	 { (char *)"RATValuesIONumPyRead", (PyCFunction) _wrap_RATValuesIONumPyRead, METH_VARARGS | METH_KEYWORDS, (char *)"RATValuesIONumPyRead(RasterAttributeTable poRAT, int nField, int nStart, int nLength) -> PyObject *"},
@@ -5454,7 +5654,7 @@ static swig_const_info swig_const_table[] = {
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial
+ * The generated swig_type_info structures are assigned statically to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -5498,7 +5698,7 @@ SWIGRUNTIME void
 SWIG_InitializeModule(void *clientdata) {
   size_t i;
   swig_module_info *module_head, *iter;
-  int found, init;
+  int init;
   
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
@@ -5517,22 +5717,18 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
     iter=module_head;
     do {
       if (iter==&swig_module) {
-        found=1;
-        break;
+        /* Our module is already in the list, so there's nothing more to do. */
+        return;
       }
       iter=iter->next;
     } while (iter!= module_head);
     
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
+    /* otherwise we must add our module into the list */
     swig_module.next = module_head->next;
     module_head->next = &swig_module;
   }
@@ -5784,7 +5980,7 @@ extern "C" {
       var = var->next;
     }
     if (res == NULL && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -5801,7 +5997,7 @@ extern "C" {
       var = var->next;
     }
     if (res == 1 && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -5851,10 +6047,19 @@ extern "C" {
         0,                                  /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-        0,                                  /* tp_version */
+        0,                                  /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+        0,                                  /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-        0,0,0,0                             /* tp_alloc -> tp_next */
+        0,                                  /* tp_allocs */
+        0,                                  /* tp_frees */
+        0,                                  /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+        0,                                  /* tp_prev */
+#endif
+        0                                   /* tp_next */
 #endif
       };
       varlink_type = tmp;
@@ -5943,7 +6148,9 @@ extern "C" {
     size_t i;
     for (i = 0; methods[i].ml_name; ++i) {
       const char *c = methods[i].ml_doc;
-      if (c && (c = strstr(c, "swig_ptr: "))) {
+      if (!c) continue;
+      c = strstr(c, "swig_ptr: ");
+      if (c) {
         int j;
         swig_const_info *ci = 0;
         const char *name = c + 10;
@@ -6045,6 +6252,7 @@ SWIG_init(void) {
   PyObject *public_interface, *public_symbol;
   PyObject *this_descr;
   PyObject *thisown_descr;
+  PyObject *self = 0;
   int i;
   
   (void)builtin_pytype;
@@ -6052,6 +6260,7 @@ SWIG_init(void) {
   (void)builtin_basetype;
   (void)tuple;
   (void)static_getset;
+  (void)self;
   
   /* metatype is used to implement static member variables. */
   metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
@@ -6071,6 +6280,7 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
+  
   md = d = PyModule_GetDict(m);
   (void)md;
   
@@ -6119,6 +6329,8 @@ SWIG_init(void) {
   GDALRegister_NUMPY();
   
   
+  /* Initialize threading */
+  SWIG_PYTHON_INITIALIZE_THREADS;
 #if PY_VERSION_HEX >= 0x03000000
   return m;
 #else
diff --git a/swig/python/extensions/gdal_wrap.cpp b/swig/python/extensions/gdal_wrap.cpp
index 0760089..cca0a30 100644
--- a/swig/python/extensions/gdal_wrap.cpp
+++ b/swig/python/extensions/gdal_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
+ * Version 3.0.8
  *
  * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -8,8 +8,13 @@
  * interface file instead.
  * ----------------------------------------------------------------------------- */
 
+
+#ifndef SWIGPYTHON
 #define SWIGPYTHON
 #define SED_HACKS
+#endif
+
+#define SWIG_PYTHON_THREADS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 
@@ -144,6 +149,19 @@ template <typename T> T SwigValueInit() {
 # define _SCL_SECURE_NO_DEPRECATE
 #endif
 
+/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
+#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
+# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
+/* Intel's compiler complains if a variable which was never initialised is
+ * cast to void, which is a common idiom which we use to indicate that we
+ * are aware a variable isn't used.  So we just silence that warning.
+ * See: https://github.com/swig/swig/issues/192 for more discussion.
+ */
+#ifdef __INTEL_COMPILER
+# pragma warning disable 592
+#endif
 
 
 #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
@@ -561,14 +579,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   swig_module_info *iter = start;
   do {
     if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
+      size_t l = 0;
+      size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
+	size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
-	  register int compare = strcmp(name, iname);
+	  int compare = strcmp(name, iname);
 	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
@@ -612,7 +630,7 @@ SWIG_TypeQueryModule(swig_module_info *start,
        of the str field (the human readable name) */
     swig_module_info *iter = start;
     do {
-      register size_t i = 0;
+      size_t i = 0;
       for (; i < iter->size; ++i) {
 	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
 	  return iter->types[i];
@@ -631,10 +649,10 @@ SWIG_TypeQueryModule(swig_module_info *start,
 SWIGRUNTIME char *
 SWIG_PackData(char *c, void *ptr, size_t sz) {
   static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
+  const unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu =  u + sz;
   for (; u != eu; ++u) {
-    register unsigned char uu = *u;
+    unsigned char uu = *u;
     *(c++) = hex[(uu & 0xf0) >> 4];
     *(c++) = hex[uu & 0xf];
   }
@@ -646,11 +664,11 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
 */
 SWIGRUNTIME const char *
 SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
+  unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu = u + sz;
   for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
+    char d = *(c++);
+    unsigned char uu;
     if ((d >= '0') && (d <= '9'))
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
@@ -1313,7 +1331,7 @@ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
 
 /* Unpack the argument tuple */
 
-SWIGINTERN int
+SWIGINTERN Py_ssize_t
 SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
 {
   if (!args) {
@@ -1327,7 +1345,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
   }  
   if (!PyTuple_Check(args)) {
     if (min <= 1 && max >= 1) {
-      register int i;
+      Py_ssize_t i;
       objs[0] = args;
       for (i = 1; i < max; ++i) {
 	objs[i] = 0;
@@ -1337,7 +1355,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
-    register Py_ssize_t l = PyTuple_GET_SIZE(args);
+    Py_ssize_t l = PyTuple_GET_SIZE(args);
     if (l < min) {
       PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
 		   name, (min == max ? "" : "at least "), (int)min, (int)l);
@@ -1347,7 +1365,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 		   name, (min == max ? "" : "at most "), (int)max, (int)l);
       return 0;
     } else {
-      register int i;
+      Py_ssize_t i;
       for (i = 0; i < l; ++i) {
 	objs[i] = PyTuple_GET_ITEM(args, i);
       }
@@ -1533,6 +1551,23 @@ typedef struct {
 #endif
 } SwigPyObject;
 
+
+#ifdef SWIGPYTHON_BUILTIN
+
+SWIGRUNTIME PyObject *
+SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+
+  if (!sobj->dict)
+    sobj->dict = PyDict_New();
+
+  Py_INCREF(sobj->dict);
+  return sobj->dict;
+}
+
+#endif
+
 SWIGRUNTIME PyObject *
 SwigPyObject_long(SwigPyObject *v)
 {
@@ -1671,16 +1706,32 @@ SwigPyObject_dealloc(PyObject *v)
     if (destroy) {
       /* destroy is always a VARARGS method */
       PyObject *res;
+
+      /* PyObject_CallFunction() has the potential to silently drop
+         the active active exception.  In cases of unnamed temporary
+         variable or where we just finished iterating over a generator
+         StopIteration will be active right now, and this needs to
+         remain true upon return from SwigPyObject_dealloc.  So save
+         and restore. */
+      
+      PyObject *val = NULL, *type = NULL, *tb = NULL;
+      PyErr_Fetch(&val, &type, &tb);
+
       if (data->delargs) {
-	/* we need to create a temporary object to carry the destroy operation */
-	PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
-	res = SWIG_Python_CallFunctor(destroy, tmp);
-	Py_DECREF(tmp);
+        /* we need to create a temporary object to carry the destroy operation */
+        PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
+        res = SWIG_Python_CallFunctor(destroy, tmp);
+        Py_DECREF(tmp);
       } else {
-	PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
-	PyObject *mself = PyCFunction_GET_SELF(destroy);
-	res = ((*meth)(mself, v));
+        PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+        PyObject *mself = PyCFunction_GET_SELF(destroy);
+        res = ((*meth)(mself, v));
       }
+      if (!res)
+        PyErr_WriteUnraisable(destroy);
+
+      PyErr_Restore(val, type, tb);
+
       Py_XDECREF(res);
     } 
 #if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
@@ -1704,6 +1755,7 @@ SwigPyObject_append(PyObject* v, PyObject* next)
   next = tmp;
 #endif
   if (!SwigPyObject_Check(next)) {
+    PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject");
     return NULL;
   }
   sobj->next = next;
@@ -1803,7 +1855,7 @@ swigobject_methods[] = {
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_VARARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS,  (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_VARARGS,  (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_VARARGS,  (char *)"returns the next 'this' object"},
@@ -1859,7 +1911,9 @@ SwigPyObject_TypeOnce(void) {
     (unaryfunc)SwigPyObject_oct,  /*nb_oct*/
     (unaryfunc)SwigPyObject_hex,  /*nb_hex*/
 #endif
-#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */
+#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
 #elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
@@ -1939,10 +1993,19 @@ SwigPyObject_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpyobject_type = tmp;
@@ -2118,10 +2181,19 @@ SwigPyPacked_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpypacked_type = tmp;
@@ -2462,7 +2534,7 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
     }
   } else {
 #if PY_VERSION_HEX >= 0x03000000
-    inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
+    inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
     if (inst) {
       PyObject_SetAttr(inst, SWIG_This(), swig_this);
       Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
@@ -2572,18 +2644,21 @@ SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int f
 	  newobj = (SwigPyObject *) newobj->next;
         newobj->next = next_self;
         newobj = (SwigPyObject *)next_self;
+#ifdef SWIGPYTHON_BUILTIN
+        newobj->dict = 0;
+#endif
       }
     } else {
       newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
     }
     if (newobj) {
       newobj->ptr = ptr;
       newobj->ty = type;
       newobj->own = own;
       newobj->next = 0;
-#ifdef SWIGPYTHON_BUILTIN
-      newobj->dict = 0;
-#endif
       return (PyObject*) newobj;
     }
     return SWIG_Py_Void();
@@ -2646,13 +2721,11 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 {
   PyObject *dict;
   if (!PyModule_Check(m)) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs module as first arg");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg");
     return SWIG_ERROR;
   }
   if (!o) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs non-NULL value");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value");
     return SWIG_ERROR;
   }
   
@@ -2964,25 +3037,27 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
 #define SWIGTYPE_p_GDAL_GCP swig_types[23]
 #define SWIGTYPE_p_GIntBig swig_types[24]
 #define SWIGTYPE_p_GUIntBig swig_types[25]
-#define SWIGTYPE_p_OGRGeometryShadow swig_types[26]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[27]
-#define SWIGTYPE_p_OGRStyleTableShadow swig_types[28]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[29]
-#define SWIGTYPE_p_StatBuf swig_types[30]
-#define SWIGTYPE_p_char swig_types[31]
-#define SWIGTYPE_p_double swig_types[32]
-#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[33]
-#define SWIGTYPE_p_int swig_types[34]
-#define SWIGTYPE_p_p_GDALDatasetShadow swig_types[35]
-#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[36]
-#define SWIGTYPE_p_p_GDAL_GCP swig_types[37]
-#define SWIGTYPE_p_p_GUIntBig swig_types[38]
-#define SWIGTYPE_p_p_char swig_types[39]
-#define SWIGTYPE_p_p_void swig_types[40]
-#define SWIGTYPE_p_size_t swig_types[41]
-#define SWIGTYPE_p_void swig_types[42]
-static swig_type_info *swig_types[44];
-static swig_module_info swig_module = {swig_types, 43, 0, 0, 0, 0};
+#define SWIGTYPE_p_OGRFeatureShadow swig_types[26]
+#define SWIGTYPE_p_OGRGeometryShadow swig_types[27]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[28]
+#define SWIGTYPE_p_OGRStyleTableShadow swig_types[29]
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[30]
+#define SWIGTYPE_p_StatBuf swig_types[31]
+#define SWIGTYPE_p_char swig_types[32]
+#define SWIGTYPE_p_double swig_types[33]
+#define SWIGTYPE_p_f_double_p_q_const__char_p_void__int swig_types[34]
+#define SWIGTYPE_p_int swig_types[35]
+#define SWIGTYPE_p_p_GDALDatasetShadow swig_types[36]
+#define SWIGTYPE_p_p_GDALRasterBandShadow swig_types[37]
+#define SWIGTYPE_p_p_GDAL_GCP swig_types[38]
+#define SWIGTYPE_p_p_GUIntBig swig_types[39]
+#define SWIGTYPE_p_p_OGRLayerShadow swig_types[40]
+#define SWIGTYPE_p_p_char swig_types[41]
+#define SWIGTYPE_p_p_void swig_types[42]
+#define SWIGTYPE_p_size_t swig_types[43]
+#define SWIGTYPE_p_void swig_types[44]
+static swig_type_info *swig_types[46];
+static swig_module_info swig_module = {swig_types, 45, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -3006,7 +3081,7 @@ static swig_module_info swig_module = {swig_types, 43, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_gdal"
 
-#define SWIGVERSION 0x020012 
+#define SWIGVERSION 0x030008 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -3029,27 +3104,35 @@ namespace swig {
 
     SwigPtr_PyObject(const SwigPtr_PyObject& item) : _obj(item._obj)
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(_obj);      
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     SwigPtr_PyObject(PyObject *obj, bool initial_ref = true) :_obj(obj)
     {
       if (initial_ref) {
+        SWIG_PYTHON_THREAD_BEGIN_BLOCK;
         Py_XINCREF(_obj);
+        SWIG_PYTHON_THREAD_END_BLOCK;
       }
     }
     
     SwigPtr_PyObject & operator=(const SwigPtr_PyObject& item) 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(item._obj);
       Py_XDECREF(_obj);
       _obj = item._obj;
+      SWIG_PYTHON_THREAD_END_BLOCK;
       return *this;      
     }
     
     ~SwigPtr_PyObject() 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XDECREF(_obj);
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     operator PyObject *() const
@@ -3106,10 +3189,12 @@ typedef void GDALAsyncReaderShadow;
 #ifdef DEBUG
 typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
 typedef struct OGRLayerHS OGRLayerShadow;
+typedef struct OGRFeatureHS OGRFeatureShadow;
 typedef struct OGRGeometryHS OGRGeometryShadow;
 #else
 typedef void OSRSpatialReferenceShadow;
 typedef void OGRLayerShadow;
+typedef void OGRFeatureShadow;
 typedef void OGRGeometryShadow;
 #endif
 typedef struct OGRStyleTableHS OGRStyleTableShadow;
@@ -3271,10 +3356,10 @@ static void GDALPythonFreeCStr(void* ptr, int bToFree)
 
 
 
-int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
+unsigned int wrapper_VSIFReadL( void **buf, unsigned int nMembSize, unsigned int nMembCount, VSILFILE *fp)
 {
-    GUIntBig buf_size = (GUIntBig)nMembSize * nMembCount;
-    if( nMembSize < 0 || nMembCount < 0 || buf_size > 0xFFFFFFFFU )
+    size_t buf_size = static_cast<size_t>(nMembSize) * nMembCount;
+    if( buf_size > 0xFFFFFFFFU )
    {
         CPLError(CE_Failure, CPLE_AppDefined, "Too big request");
         *buf = NULL;
@@ -3303,7 +3388,7 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         _PyBytes_Resize(&o, nRet * nMembSize);
         *buf = o;
     }
-    return nRet;
+    return static_cast<unsigned int>(nRet);
 #else
     *buf = (void *)PyString_FromStringAndSize( NULL, buf_size );
     if (*buf == NULL)
@@ -3320,7 +3405,7 @@ int wrapper_VSIFReadL( void **buf, int nMembSize, int nMembCount, VSILFILE *fp)
         _PyString_Resize(&o, nRet * nMembSize);
         *buf = o;
     }
-    return nRet;
+    return static_cast<unsigned int>(nRet);
 #endif
 }
 
@@ -3342,9 +3427,11 @@ SWIG_AsVal_double (PyObject *obj, double *val)
   if (PyFloat_Check(obj)) {
     if (val) *val = PyFloat_AsDouble(obj);
     return SWIG_OK;
+#if PY_VERSION_HEX < 0x03000000
   } else if (PyInt_Check(obj)) {
     if (val) *val = PyInt_AsLong(obj);
     return SWIG_OK;
+#endif
   } else if (PyLong_Check(obj)) {
     double v = PyLong_AsDouble(obj);
     if (!PyErr_Occurred()) {
@@ -3416,24 +3503,33 @@ SWIG_CanCastAsInteger(double *d, double min, double max) {
 
 
 SWIGINTERN int
-SWIG_AsVal_long (PyObject *obj, long* val)
+SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) 
 {
+#if PY_VERSION_HEX < 0x03000000
   if (PyInt_Check(obj)) {
-    if (val) *val = PyInt_AsLong(obj);
-    return SWIG_OK;
-  } else if (PyLong_Check(obj)) {
-    long v = PyLong_AsLong(obj);
+    long v = PyInt_AsLong(obj);
+    if (v >= 0) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      return SWIG_OverflowError;
+    }
+  } else
+#endif
+  if (PyLong_Check(obj)) {
+    unsigned long v = PyLong_AsUnsignedLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_OK;
     } else {
       PyErr_Clear();
+      return SWIG_OverflowError;
     }
   }
 #ifdef SWIG_PYTHON_CAST_MODE
   {
     int dispatch = 0;
-    long v = PyInt_AsLong(obj);
+    unsigned long v = PyLong_AsUnsignedLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_AddCast(SWIG_OK);
@@ -3443,8 +3539,8 @@ SWIG_AsVal_long (PyObject *obj, long* val)
     if (!dispatch) {
       double d;
       int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
-      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
-	if (val) *val = (long)(d);
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
+	if (val) *val = (unsigned long)(d);
 	return res;
       }
     }
@@ -3455,21 +3551,28 @@ SWIG_AsVal_long (PyObject *obj, long* val)
 
 
 SWIGINTERN int
-SWIG_AsVal_int (PyObject * obj, int *val)
+SWIG_AsVal_unsigned_SS_int (PyObject * obj, unsigned int *val)
 {
-  long v;
-  int res = SWIG_AsVal_long (obj, &v);
+  unsigned long v;
+  int res = SWIG_AsVal_unsigned_SS_long (obj, &v);
   if (SWIG_IsOK(res)) {
-    if ((v < INT_MIN || v > INT_MAX)) {
+    if ((v > UINT_MAX)) {
       return SWIG_OverflowError;
     } else {
-      if (val) *val = static_cast< int >(v);
+      if (val) *val = static_cast< unsigned int >(v);
     }
   }  
   return res;
 }
 
 
+SWIGINTERNINLINE PyObject*
+  SWIG_From_unsigned_SS_int  (unsigned int value)
+{
+  return PyInt_FromSize_t((size_t) value);
+}
+
+
 
 typedef struct {
     PyObject *psPyCallback;
@@ -3500,6 +3603,8 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
     if( pszMessage == NULL )
         pszMessage = "";
 
+    SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
     if( psInfo->psPyCallbackData == NULL )
         psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, Py_None );
     else
@@ -3512,16 +3617,19 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
     if( PyErr_Occurred() != NULL )
     {
         PyErr_Clear();
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return FALSE;
     }
 
     if( psResult == NULL )
     {
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return TRUE;
     }
 
     if( psResult == Py_None )
     {
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return TRUE;
     }
 
@@ -3530,10 +3638,12 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
         PyErr_Clear();
         CPLError(CE_Failure, CPLE_AppDefined, "bad progress return value");
         Py_XDECREF(psResult);
-	return FALSE;
+        SWIG_PYTHON_THREAD_END_BLOCK;
+        return FALSE;
     }
 
     Py_XDECREF(psResult);
+    SWIG_PYTHON_THREAD_END_BLOCK;
 
     return bContinue;
 }
@@ -3618,18 +3728,17 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 #else
 	if (*alloc == SWIG_NEWOBJ) 
 #endif
-	  {
-	    *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
-	    *alloc = SWIG_NEWOBJ;
-	  }
-	else {
+	{
+	  *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+	  *alloc = SWIG_NEWOBJ;
+	} else {
 	  *cptr = cstr;
 	  *alloc = SWIG_OLDOBJ;
 	}
       } else {
-        #if PY_VERSION_HEX>=0x03000000
-        assert(0); /* Should never reach here in Python 3 */
-        #endif
+	#if PY_VERSION_HEX>=0x03000000
+	assert(0); /* Should never reach here in Python 3 */
+	#endif
 	*cptr = SWIG_Python_str_AsChar(obj);
       }
     }
@@ -3639,6 +3748,30 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 #endif
     return SWIG_OK;
   } else {
+#if defined(SWIG_PYTHON_2_UNICODE)
+#if PY_VERSION_HEX<0x03000000
+    if (PyUnicode_Check(obj)) {
+      char *cstr; Py_ssize_t len;
+      if (!alloc && cptr) {
+        return SWIG_RuntimeError;
+      }
+      obj = PyUnicode_AsUTF8String(obj);
+      if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) {
+        if (cptr) {
+          if (alloc) *alloc = SWIG_NEWOBJ;
+          *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+        }
+        if (psize) *psize = len + 1;
+
+        Py_XDECREF(obj);
+        return SWIG_OK;
+      } else {
+        Py_XDECREF(obj);
+      }
+    }
+#endif
+#endif
+
     swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
     if (pchar_descriptor) {
       void* vptr = 0;
@@ -3662,9 +3795,13 @@ void CPL_STDCALL PyCPLErrorHandler(CPLErr eErrClass, int err_no, const char* psz
     void* user_data = CPLGetErrorHandlerUserData();
     PyObject *psArgs;
 
+    SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
     psArgs = Py_BuildValue("(iis)", eErrClass, err_no, pszErrorMsg );
     PyEval_CallObject( (PyObject*)user_data, psArgs);
     Py_XDECREF(psArgs);
+
+    SWIG_PYTHON_THREAD_END_BLOCK;
 }
 
 
@@ -3682,7 +3819,9 @@ void CPL_STDCALL PyCPLErrorHandler(CPLErr eErrClass, int err_no, const char* psz
   {
      void* user_data = CPLGetErrorHandlerUserData();
      if( user_data != NULL )
-       Py_XDECREF((PyObject*)user_data);
+     {
+         Py_XDECREF((PyObject*)user_data);
+     }
      CPLPopErrorHandler();
   }
 
@@ -3692,6 +3831,65 @@ void CPL_STDCALL PyCPLErrorHandler(CPLErr eErrClass, int err_no, const char* psz
   }
 
 
+SWIGINTERN int
+SWIG_AsVal_long (PyObject *obj, long* val)
+{
+#if PY_VERSION_HEX < 0x03000000
+  if (PyInt_Check(obj)) {
+    if (val) *val = PyInt_AsLong(obj);
+    return SWIG_OK;
+  } else
+#endif
+  if (PyLong_Check(obj)) {
+    long v = PyLong_AsLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_OK;
+    } else {
+      PyErr_Clear();
+      return SWIG_OverflowError;
+    }
+  }
+#ifdef SWIG_PYTHON_CAST_MODE
+  {
+    int dispatch = 0;
+    long v = PyInt_AsLong(obj);
+    if (!PyErr_Occurred()) {
+      if (val) *val = v;
+      return SWIG_AddCast(SWIG_OK);
+    } else {
+      PyErr_Clear();
+    }
+    if (!dispatch) {
+      double d;
+      int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
+      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) {
+	if (val) *val = (long)(d);
+	return res;
+      }
+    }
+  }
+#endif
+  return SWIG_TypeError;
+}
+
+
+SWIGINTERN int
+SWIG_AsVal_int (PyObject * obj, int *val)
+{
+  long v;
+  int res = SWIG_AsVal_long (obj, &v);
+  if (SWIG_IsOK(res)) {
+    if ((v < INT_MIN || v > INT_MAX)) {
+      return SWIG_OverflowError;
+    } else {
+      if (val) *val = static_cast< int >(v);
+    }
+  }  
+  return res;
+}
+
+
 retStringAndCPLFree* EscapeString(int len, char *bin_string , int scheme=CPLES_SQL) {
     return CPLEscapeString(bin_string, len, scheme);
 }
@@ -3707,9 +3905,13 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
 	SWIG_InternalNewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
     } else {
 #if PY_VERSION_HEX >= 0x03000000
-      return PyUnicode_FromStringAndSize(carray, static_cast< int >(size));
+#if PY_VERSION_HEX >= 0x03010000
+      return PyUnicode_DecodeUTF8(carray, static_cast< Py_ssize_t >(size), "surrogateescape");
+#else
+      return PyUnicode_FromStringAndSize(carray, static_cast< Py_ssize_t >(size));
+#endif
 #else
-      return PyString_FromStringAndSize(carray, static_cast< int >(size));
+      return PyString_FromStringAndSize(carray, static_cast< Py_ssize_t >(size));
 #endif
     }
   } else {
@@ -3737,17 +3939,17 @@ const char *wrapper_CPLGetConfigOption( const char * pszKey, const char * pszDef
 }
 
 
-void wrapper_VSIFileFromMemBuffer( const char* utf8_path, int nBytes, const GByte *pabyData)
+void wrapper_VSIFileFromMemBuffer( const char* utf8_path, GIntBig nBytes, const GByte *pabyData)
 {
-    GByte* pabyDataDup = (GByte*)VSIMalloc(nBytes);
+    const size_t nSize = static_cast<size_t>(nBytes);
+    GByte* pabyDataDup = (GByte*)VSIMalloc(nSize);
     if (pabyDataDup == NULL)
             return;
-    memcpy(pabyDataDup, pabyData, nBytes);
-    VSIFCloseL(VSIFileFromMemBuffer(utf8_path, (GByte*) pabyDataDup, nBytes, TRUE));
+    memcpy(pabyDataDup, pabyData, nSize);
+    VSIFCloseL(VSIFileFromMemBuffer(utf8_path, (GByte*) pabyDataDup, nSize, TRUE));
 }
 
 
-
 int wrapper_HasThreadSupport()
 {
     return strcmp(CPLGetThreadingModel(), "stub") != 0;
@@ -3806,12 +4008,12 @@ VSILFILE   *wrapper_VSIFOpenExL( const char *utf8_path, const char *pszMode, int
 
 int wrapper_VSIFWriteL( int nLen, char *pBuf, int size, int memb, VSILFILE* fp)
 {
-    if (nLen < size * memb)
+    if (nLen < static_cast<GIntBig>(size) * memb)
     {
         CPLError(CE_Failure, CPLE_AppDefined, "Inconsistent buffer size with 'size' and 'memb' values");
         return 0;
     }
-    return VSIFWriteL(pBuf, size, memb, fp);
+    return static_cast<int>(VSIFWriteL(pBuf, size, memb, fp));
 }
 
 SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
@@ -4036,65 +4238,6 @@ SWIGINTERN void CPLVirtualMemShadow_GetAddr(CPLVirtualMemShadow *self,void **ppt
         *preadonly = self->bReadOnly;
     }
 
-SWIGINTERN int
-SWIG_AsVal_unsigned_SS_long (PyObject *obj, unsigned long *val) 
-{
-#if PY_VERSION_HEX < 0x03000000
-  if (PyInt_Check(obj)) {
-    long v = PyInt_AsLong(obj);
-    if (v >= 0) {
-      if (val) *val = v;
-      return SWIG_OK;
-    } else {
-      return SWIG_OverflowError;
-    }
-  } else
-#endif
-  if (PyLong_Check(obj)) {
-    unsigned long v = PyLong_AsUnsignedLong(obj);
-    if (!PyErr_Occurred()) {
-      if (val) *val = v;
-      return SWIG_OK;
-    } else {
-      PyErr_Clear();
-#if PY_VERSION_HEX >= 0x03000000
-      {
-        long v = PyLong_AsLong(obj);
-        if (!PyErr_Occurred()) {
-          if (v < 0) {
-            return SWIG_OverflowError;
-          }
-        } else {
-          PyErr_Clear();
-        }
-      }
-#endif
-    }
-  }
-#ifdef SWIG_PYTHON_CAST_MODE
-  {
-    int dispatch = 0;
-    unsigned long v = PyLong_AsUnsignedLong(obj);
-    if (!PyErr_Occurred()) {
-      if (val) *val = v;
-      return SWIG_AddCast(SWIG_OK);
-    } else {
-      PyErr_Clear();
-    }
-    if (!dispatch) {
-      double d;
-      int res = SWIG_AddCast(SWIG_AsVal_double (obj,&d));
-      if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) {
-	if (val) *val = (unsigned long)(d);
-	return res;
-      }
-    }
-  }
-#endif
-  return SWIG_TypeError;
-}
-
-
 SWIGINTERNINLINE int
 SWIG_AsVal_size_t (PyObject * obj, size_t *val)
 {
@@ -4222,6 +4365,7 @@ static void DeleteAsyncReaderWrapper(GDALAsyncReaderWrapperH hWrapper)
 
 
 
+
 static GDALAsyncReaderWrapper* CreateAsyncReaderWrapper(GDALAsyncReaderH  hAsyncReader,
                                                         void             *pyObject)
 {
@@ -4243,7 +4387,6 @@ static void DisableAsyncReaderWrapper(GDALAsyncReaderWrapperH hWrapper)
     psWrapper->hAsyncReader = NULL;
 }
 
-
 SWIGINTERN void delete_GDALAsyncReaderShadow(GDALAsyncReaderShadow *self){
         DeleteAsyncReaderWrapper(self);
     }
@@ -4418,8 +4561,8 @@ SWIGINTERN GDALAsyncReaderShadow *GDALDatasetShadow_BeginAsyncReader(GDALDataset
             else
             {
                 int nRes = 1 << nLevel;
-                buf_xsize = ceil(xSize / (1.0 * nRes));
-                buf_ysize = ceil(ySize / (1.0 * nRes));
+                buf_xsize = static_cast<int>(ceil(xSize / (1.0 * nRes)));
+                buf_ysize = static_cast<int>(ceil(ySize / (1.0 * nRes)));
             }
         }
     }
@@ -4489,7 +4632,7 @@ SWIGINTERN void GDALDatasetShadow_EndAsyncReader(GDALDatasetShadow *self,GDALAsy
   }
 SWIGINTERN CPLVirtualMemShadow *GDALDatasetShadow_GetVirtualMem(GDALDatasetShadow *self,GDALRWFlag eRWFlag,int nXOff,int nYOff,int nXSize,int nYSize,int nBufXSize,int nBufYSize,GDALDataType eBufType,int band_list,int *pband_list,int bIsBandSequential,size_t nCacheSize,size_t nPageSizeHint,char **options=NULL){
         int nPixelSpace;
-        GIntBig nBandSpace;
+        int nBandSpace;
         if( bIsBandSequential != 0 && bIsBandSequential != 1 )
             return NULL;
         if( band_list == 0 )
@@ -4502,7 +4645,7 @@ SWIGINTERN CPLVirtualMemShadow *GDALDatasetShadow_GetVirtualMem(GDALDatasetShado
         else
         {
             nBandSpace = GDALGetDataTypeSize(eBufType) / 8;
-            nPixelSpace  = nBandSpace * band_list;
+            nPixelSpace = nBandSpace * band_list;
         }
         CPLVirtualMem* vmem = GDALDatasetGetVirtualMem( self,
                                          eRWFlag,
@@ -4620,6 +4763,27 @@ SWIGINTERN OGRLayerShadow *GDALDatasetShadow_GetLayerByName(GDALDatasetShadow *s
     OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetGetLayerByName(self, layer_name);
     return layer;
   }
+SWIGINTERN void GDALDatasetShadow_ResetReading(GDALDatasetShadow *self){
+    GDALDatasetResetReading( self );
+  }
+
+SWIGINTERN int
+SWIG_AsVal_bool (PyObject *obj, bool *val)
+{
+  int r;
+  if (!PyBool_Check(obj))
+    return SWIG_ERROR;
+  r = PyObject_IsTrue(obj);
+  if (r == -1)
+    return SWIG_ERROR;
+  if (val) *val = r ? true : false;
+  return SWIG_OK;
+}
+
+SWIGINTERN OGRFeatureShadow *GDALDatasetShadow_GetNextFeature(GDALDatasetShadow *self,bool include_layer=true,bool include_pct=false,OGRLayerShadow **ppoBelongingLayer=NULL,double *pdfProgressPct=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
+    return GDALDatasetGetNextFeature( self, ppoBelongingLayer, pdfProgressPct,
+                                      callback, callback_data );
+  }
 SWIGINTERN bool GDALDatasetShadow_TestCapability(GDALDatasetShadow *self,char const *cap){
     return (GDALDatasetTestCapability(self, cap) > 0);
   }
@@ -4677,9 +4841,13 @@ SWIGINTERN CPLErr GDALDatasetShadow_ReadRaster1(GDALDatasetShadow *self,int xoff
     GIntBig band_space = (buf_band_space == 0) ? 0 : *buf_band_space;
 
     int ntypesize = GDALGetDataTypeSize( ntype ) / 8;
-    GIntBig buf_size = ComputeDatasetRasterIOSize (nxsize, nysize, ntypesize,
-                                               band_list ? band_list : GDALGetRasterCount(self), pband_list, band_list,
-                                               pixel_space, line_space, band_space, FALSE);
+    size_t buf_size = static_cast<size_t>(
+        ComputeDatasetRasterIOSize (nxsize, nysize, ntypesize,
+                                    band_list ? band_list :
+                                        GDALGetRasterCount(self),
+                                    pband_list, band_list,
+                                    pixel_space, line_space, band_space,
+                                    FALSE));
     if (buf_size == 0)
     {
         *buf = NULL;
@@ -4835,6 +5003,9 @@ SWIGINTERN int GDALRasterBandShadow_GetBand(GDALRasterBandShadow *self){
 SWIGINTERN void GDALRasterBandShadow_GetBlockSize(GDALRasterBandShadow *self,int *pnBlockXSize,int *pnBlockYSize){
       GDALGetBlockSize(self, pnBlockXSize, pnBlockYSize);
   }
+SWIGINTERN void GDALRasterBandShadow_GetActualBlockSize(GDALRasterBandShadow *self,int nXBlockOff,int nYBlockOff,int *pnxvalid,int *pnyvalid,int *pisvalid){
+    *pisvalid = (GDALGetActualBlockSize(self, nXBlockOff, nYBlockOff, pnxvalid, pnyvalid) == CE_None);
+  }
 SWIGINTERN GDALColorInterp GDALRasterBandShadow_GetColorInterpretation(GDALRasterBandShadow *self){
     return GDALGetRasterColorInterpretation( self );
   }
@@ -4894,17 +5065,6 @@ SWIGINTERN CPLErr GDALRasterBandShadow_GetStatistics(GDALRasterBandShadow *self,
     return GDALGetRasterStatistics( self, approx_ok, force,
 				    min, max, mean, stddev );
   }
-
-SWIGINTERN int
-SWIG_AsVal_bool (PyObject *obj, bool *val)
-{
-  int r = PyObject_IsTrue(obj);
-  if (r == -1)
-    return SWIG_ERROR;
-  if (val) *val = r ? true : false;
-  return SWIG_OK;
-}
-
 SWIGINTERN CPLErr GDALRasterBandShadow_ComputeStatistics(GDALRasterBandShadow *self,bool approx_ok,double *min=NULL,double *max=NULL,double *mean=NULL,double *stddev=NULL,GDALProgressFunc callback=NULL,void *callback_data=NULL){
     return GDALComputeRasterStatistics( self, approx_ok, min, max, mean, stddev, callback, callback_data );
   }
@@ -5070,16 +5230,24 @@ SWIGINTERN CPLVirtualMemShadow *GDALRasterBandShadow_GetTiledVirtualMem(GDALRast
         vmemshadow->nBandCount = 1;
         return vmemshadow;
     }
+SWIGINTERN int GDALRasterBandShadow_GetDataCoverageStatus(GDALRasterBandShadow *self,int nXOff,int nYOff,int nXSize,int nYSize,int nMaskFlagStop=0,double *pdfDataPct=NULL){
+        return GDALGetDataCoverageStatus(self, nXOff, nYOff,
+                                         nXSize, nYSize,
+                                         nMaskFlagStop,
+                                         pdfDataPct);
+    }
 SWIGINTERN CPLErr GDALRasterBandShadow_ReadRaster1(GDALRasterBandShadow *self,double xoff,double yoff,double xsize,double ysize,void **buf,int *buf_xsize=0,int *buf_ysize=0,int *buf_type=0,GIntBig *buf_pixel_space=0,GIntBig *buf_line_space=0,GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour,GDALProgressFunc callback=NULL,void *callback_data=NULL){
-    int nxsize = (buf_xsize==0) ? xsize : *buf_xsize;
-    int nysize = (buf_ysize==0) ? ysize : *buf_ysize;
+    int nxsize = (buf_xsize==0) ? static_cast<int>(xsize) : *buf_xsize;
+    int nysize = (buf_ysize==0) ? static_cast<int>(ysize) : *buf_ysize;
     GDALDataType ntype  = (buf_type==0) ? GDALGetRasterDataType(self)
                                         : (GDALDataType)*buf_type;
     GIntBig pixel_space = (buf_pixel_space == 0) ? 0 : *buf_pixel_space;
     GIntBig line_space = (buf_line_space == 0) ? 0 : *buf_line_space;
 
-    GIntBig buf_size = ComputeBandRasterIOSize( nxsize, nysize, GDALGetDataTypeSize( ntype ) / 8,
-                                            pixel_space, line_space, FALSE );
+    size_t buf_size = static_cast<size_t>(
+        ComputeBandRasterIOSize( nxsize, nysize,
+                                 GDALGetDataTypeSize( ntype ) / 8,
+                                 pixel_space, line_space, FALSE ) );
     if (buf_size == 0)
     {
         *buf = NULL;
@@ -5146,7 +5314,8 @@ SWIGINTERN CPLErr GDALRasterBandShadow_ReadBlock(GDALRasterBandShadow *self,int
     int nBlockXSize, nBlockYSize;
     GDALGetBlockSize(self, &nBlockXSize, &nBlockYSize);
     int nDataTypeSize = (GDALGetDataTypeSize(GDALGetRasterDataType(self)) / 8);
-    GIntBig buf_size = (GIntBig)nBlockXSize * nBlockYSize * nDataTypeSize;
+    size_t buf_size = static_cast<size_t>(nBlockXSize) *
+                                                nBlockYSize * nDataTypeSize;
 
 #if PY_VERSION_HEX >= 0x03000000
     *buf = (void *)PyBytes_FromStringAndSize( NULL, buf_size );
@@ -5709,6 +5878,22 @@ SWIGINTERN int GDALTransformerInfoShadow_TransformGeolocations(GDALTransformerIn
                             	      callback, callback_data, options );
   }
 
+GDALDatasetShadow* ApplyVerticalShiftGrid( GDALDatasetShadow *src_ds,
+                                           GDALDatasetShadow *grid_ds,
+                                           bool inverse = false,
+                                           double srcUnitToMeter = 1.0,
+                                           double dstUnitToMeter = 1.0,
+                                           char** options = NULL ) {
+  GDALDatasetShadow *ds = GDALApplyVerticalShiftGrid( src_ds, grid_ds,
+                                                      inverse,
+                                                      srcUnitToMeter,
+                                                      dstUnitToMeter,
+                                                      options );
+  return ds;
+
+}
+
+
 GIntBig wrapper_GDALGetCacheMax()
 {
     return GDALGetCacheMax64();
@@ -5771,7 +5956,12 @@ static CPLXMLNode *PyListToXMLTree( PyObject *pyList )
     CPLXMLNode *psChild;
     char       *pszText = NULL;
 
-    nChildCount = PyList_Size(pyList) - 2;
+    if( PyList_Size(pyList) > INT_MAX )
+    {
+        PyErr_SetString(PyExc_TypeError,"Error in input XMLTree." );
+        return NULL;
+    }
+    nChildCount = static_cast<int>(PyList_Size(pyList)) - 2;
     if( nChildCount < 0 )
     {
         PyErr_SetString(PyExc_TypeError,"Error in input XMLTree." );
@@ -5874,22 +6064,6 @@ GDALDatasetShadow* OpenEx( char const* utf8_path, unsigned int nOpenFlags = 0,
 }
 
 
-SWIGINTERN int
-SWIG_AsVal_unsigned_SS_int (PyObject * obj, unsigned int *val)
-{
-  unsigned long v;
-  int res = SWIG_AsVal_unsigned_SS_long (obj, &v);
-  if (SWIG_IsOK(res)) {
-    if ((v > UINT_MAX)) {
-      return SWIG_OverflowError;
-    } else {
-      if (val) *val = static_cast< unsigned int >(v);
-    }
-  }  
-  return res;
-}
-
-
 GDALDatasetShadow* OpenShared( char const* utf8_path, GDALAccess eAccess = GA_ReadOnly ) {
   CPLErrorReset();
   GDALDatasetShadow *ds = GDALOpenShared( utf8_path, eAccess );
@@ -5910,6 +6084,18 @@ GDALDriverShadow *IdentifyDriver( const char *utf8_path,
 }
 
 
+GDALDriverShadow *IdentifyDriverEx( const char* utf8_path,
+                                    unsigned int nIdentifyFlags = 0,
+                                    char** allowed_drivers = NULL,
+                                    char** sibling_files = NULL )
+{
+    return  (GDALDriverShadow *) GDALIdentifyDriverEx( utf8_path,
+                                                nIdentifyFlags,
+                                                allowed_drivers,
+                                                sibling_files );
+}
+
+
   char **GeneralCmdLineProcessor( char **papszArgv, int nOptions = 0 ) {
     int nResArgCount;
 
@@ -6304,7 +6490,11 @@ SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyOb
   int result;
   
   if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
-  result = (int)GetUseExceptions();
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result = (int)GetUseExceptions();
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -6317,7 +6507,11 @@ SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObjec
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
-  UseExceptions();
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    UseExceptions();
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -6330,7 +6524,11 @@ SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyO
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   
   if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
-  DontUseExceptions();
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    DontUseExceptions();
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -6342,35 +6540,35 @@ fail:
 SWIGINTERN PyObject *_wrap_VSIFReadL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   void **arg1 = (void **) 0 ;
-  int arg2 ;
-  int arg3 ;
+  unsigned int arg2 ;
+  unsigned int arg3 ;
   VSILFILE *arg4 = (VSILFILE *) 0 ;
   void *pyObject1 = NULL ;
-  int val2 ;
+  unsigned int val2 ;
   int ecode2 = 0 ;
-  int val3 ;
+  unsigned int val3 ;
   int ecode3 = 0 ;
   int res4 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
-  int result;
+  unsigned int result;
   
   {
     /* %typemap(in,numinputs=0) ( void **outPythonObject ) ( void *pyObject1 = NULL ) */
     arg1 = &pyObject1;
   }
   if (!PyArg_ParseTuple(args,(char *)"OOO:VSIFReadL",&obj0,&obj1,&obj2)) SWIG_fail;
-  ecode2 = SWIG_AsVal_int(obj0, &val2);
+  ecode2 = SWIG_AsVal_unsigned_SS_int(obj0, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VSIFReadL" "', argument " "2"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "VSIFReadL" "', argument " "2"" of type '" "unsigned int""'");
   } 
-  arg2 = static_cast< int >(val2);
-  ecode3 = SWIG_AsVal_int(obj1, &val3);
+  arg2 = static_cast< unsigned int >(val2);
+  ecode3 = SWIG_AsVal_unsigned_SS_int(obj1, &val3);
   if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIFReadL" "', argument " "3"" of type '" "int""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIFReadL" "', argument " "3"" of type '" "unsigned int""'");
   } 
-  arg3 = static_cast< int >(val3);
+  arg3 = static_cast< unsigned int >(val3);
   res4 = SWIG_ConvertPtr(obj2,SWIG_as_voidptrptr(&arg4), 0, 0);
   if (!SWIG_IsOK(res4)) {
     SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "VSIFReadL" "', argument " "4"" of type '" "VSILFILE *""'"); 
@@ -6379,7 +6577,11 @@ SWIGINTERN PyObject *_wrap_VSIFReadL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)wrapper_VSIFReadL(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (unsigned int)wrapper_VSIFReadL(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6389,7 +6591,7 @@ SWIGINTERN PyObject *_wrap_VSIFReadL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     }
 #endif
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_From_unsigned_SS_int(static_cast< unsigned int >(result));
   {
     /* %typemap(argout) ( void **outPythonObject ) */
     Py_XDECREF(resultobj);
@@ -6438,7 +6640,11 @@ SWIGINTERN PyObject *_wrap_Debug(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    Debug((char const *)arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      Debug((char const *)arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6481,7 +6687,11 @@ SWIGINTERN PyObject *_wrap_SetErrorHandler(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)SetErrorHandler((char const *)arg1));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)SetErrorHandler((char const *)arg1));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6636,7 +6846,11 @@ SWIGINTERN PyObject *_wrap_Error(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    Error(arg1,arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      Error(arg1,arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6675,7 +6889,11 @@ SWIGINTERN PyObject *_wrap_GOA2GetAuthorizationURL(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)GOA2GetAuthorizationURL((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)GOA2GetAuthorizationURL((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6731,7 +6949,11 @@ SWIGINTERN PyObject *_wrap_GOA2GetRefreshToken(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)GOA2GetRefreshToken((char const *)arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)GOA2GetRefreshToken((char const *)arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6789,7 +7011,11 @@ SWIGINTERN PyObject *_wrap_GOA2GetAccessToken(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)GOA2GetAccessToken((char const *)arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)GOA2GetAccessToken((char const *)arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6826,7 +7052,11 @@ SWIGINTERN PyObject *_wrap_ErrorReset(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPLErrorReset();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPLErrorReset();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6872,12 +7102,18 @@ SWIGINTERN PyObject *_wrap_EscapeString(PyObject *SWIGUNUSEDPARM(self), PyObject
       }
       
       if (safeLen) safeLen--;
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
       arg1 = (int) safeLen;
     }
     else if (PyBytes_Check(obj0))
     {
       Py_ssize_t safeLen = 0;
       PyBytes_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
       arg1 = (int) safeLen;
     }
     else
@@ -6890,6 +7126,9 @@ SWIGINTERN PyObject *_wrap_EscapeString(PyObject *SWIGUNUSEDPARM(self), PyObject
     {
       Py_ssize_t safeLen = 0;
       PyString_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
       arg1 = (int) safeLen;
     }
     else
@@ -6910,7 +7149,11 @@ SWIGINTERN PyObject *_wrap_EscapeString(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)EscapeString(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)EscapeString(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7016,7 +7259,11 @@ SWIGINTERN PyObject *_wrap_VSIGetLastErrorNo(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)VSIGetLastErrorNo();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)VSIGetLastErrorNo();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7043,7 +7290,11 @@ SWIGINTERN PyObject *_wrap_VSIGetLastErrorMsg(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)VSIGetLastErrorMsg();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)VSIGetLastErrorMsg();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7086,7 +7337,11 @@ SWIGINTERN PyObject *_wrap_PushFinderLocation(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPLPushFinderLocation((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPLPushFinderLocation((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7120,7 +7375,11 @@ SWIGINTERN PyObject *_wrap_PopFinderLocation(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPLPopFinderLocation();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPLPopFinderLocation();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7146,7 +7405,11 @@ SWIGINTERN PyObject *_wrap_FinderClean(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPLFinderClean();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPLFinderClean();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7200,7 +7463,11 @@ SWIGINTERN PyObject *_wrap_FindFile(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)CPLFindFile((char const *)arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)CPLFindFile((char const *)arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7265,7 +7532,11 @@ SWIGINTERN PyObject *_wrap_ReadDir(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)wrapper_VSIReadDirEx((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)wrapper_VSIReadDirEx((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7333,7 +7604,11 @@ SWIGINTERN PyObject *_wrap_ReadDirRecursive(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)VSIReadDirRecursive((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)VSIReadDirRecursive((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7408,7 +7683,11 @@ SWIGINTERN PyObject *_wrap_SetConfigOption(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPLSetConfigOption((char const *)arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPLSetConfigOption((char const *)arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7466,7 +7745,11 @@ SWIGINTERN PyObject *_wrap_GetConfigOption(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)wrapper_CPLGetConfigOption((char const *)arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)wrapper_CPLGetConfigOption((char const *)arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7509,12 +7792,18 @@ SWIGINTERN PyObject *_wrap_CPLBinaryToHex(PyObject *SWIGUNUSEDPARM(self), PyObje
       }
       
       if (safeLen) safeLen--;
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
       arg1 = (int) safeLen;
     }
     else if (PyBytes_Check(obj0))
     {
       Py_ssize_t safeLen = 0;
       PyBytes_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
       arg1 = (int) safeLen;
     }
     else
@@ -7527,6 +7816,9 @@ SWIGINTERN PyObject *_wrap_CPLBinaryToHex(PyObject *SWIGUNUSEDPARM(self), PyObje
     {
       Py_ssize_t safeLen = 0;
       PyString_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
       arg1 = (int) safeLen;
     }
     else
@@ -7540,7 +7832,11 @@ SWIGINTERN PyObject *_wrap_CPLBinaryToHex(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)CPLBinaryToHex(arg1,(GByte const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)CPLBinaryToHex(arg1,(GByte const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7605,7 +7901,11 @@ SWIGINTERN PyObject *_wrap_CPLHexToBinary(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GByte *)CPLHexToBinary((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GByte *)CPLHexToBinary((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7628,7 +7928,7 @@ fail:
 SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
-  int arg2 ;
+  GIntBig arg2 ;
   GByte *arg3 = (GByte *) 0 ;
   int bToFree1 = 0 ;
   int alloc2 = 0 ;
@@ -7646,7 +7946,7 @@ SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyO
     }
   }
   {
-    /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
+    /* %typemap(in,numinputs=1) (GIntBig nLen, char *pBuf ) */
 #if PY_VERSION_HEX>=0x03000000
     if (PyUnicode_Check(obj1))
     {
@@ -7657,13 +7957,13 @@ SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyO
       }
       
       if (safeLen) safeLen--;
-      arg2 = (int) safeLen;
+      arg2 = (GIntBig) safeLen;
     }
     else if (PyBytes_Check(obj1))
     {
       Py_ssize_t safeLen = 0;
       PyBytes_AsStringAndSize(obj1, (char**) &arg3, &safeLen);
-      arg2 = (int) safeLen;
+      arg2 = (GIntBig) safeLen;
     }
     else
     {
@@ -7675,7 +7975,7 @@ SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyO
     {
       Py_ssize_t safeLen = 0;
       PyString_AsStringAndSize(obj1, (char**) &arg3, &safeLen);
-      arg2 = (int) safeLen;
+      arg2 = (GIntBig) safeLen;
     }
     else
     {
@@ -7693,7 +7993,11 @@ SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    wrapper_VSIFileFromMemBuffer((char const *)arg1,arg2,(GByte const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      wrapper_VSIFileFromMemBuffer((char const *)arg1,arg2,(GByte const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7709,7 +8013,7 @@ SWIGINTERN PyObject *_wrap_FileFromMemBuffer(PyObject *SWIGUNUSEDPARM(self), PyO
     GDALPythonFreeCStr(arg1, bToFree1);
   }
   {
-    /* %typemap(freearg) (int *nLen, char *pBuf ) */
+    /* %typemap(freearg) (GIntBig *nLen, char *pBuf ) */
     if (ReturnSame(alloc2) == SWIG_NEWOBJ ) {
       delete[] arg3;
     }
@@ -7722,7 +8026,7 @@ fail:
     GDALPythonFreeCStr(arg1, bToFree1);
   }
   {
-    /* %typemap(freearg) (int *nLen, char *pBuf ) */
+    /* %typemap(freearg) (GIntBig *nLen, char *pBuf ) */
     if (ReturnSame(alloc2) == SWIG_NEWOBJ ) {
       delete[] arg3;
     }
@@ -7757,7 +8061,11 @@ SWIGINTERN PyObject *_wrap_Unlink(PyObject *SWIGUNUSEDPARM(self), PyObject *args
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = VSIUnlink((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = VSIUnlink((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7792,7 +8100,11 @@ SWIGINTERN PyObject *_wrap_HasThreadSupport(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)wrapper_HasThreadSupport();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)wrapper_HasThreadSupport();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7845,7 +8157,11 @@ SWIGINTERN PyObject *_wrap_Mkdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = VSIMkdir((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = VSIMkdir((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7897,7 +8213,11 @@ SWIGINTERN PyObject *_wrap_Rmdir(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = VSIRmdir((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = VSIRmdir((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7966,7 +8286,11 @@ SWIGINTERN PyObject *_wrap_Rename(PyObject *SWIGUNUSEDPARM(self), PyObject *args
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = VSIRename((char const *)arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = VSIRename((char const *)arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8000,6 +8324,39 @@ fail:
 }
 
 
+SWIGINTERN PyObject *VSI_STAT_EXISTS_FLAG_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "VSI_STAT_EXISTS_FLAG",SWIG_From_int(static_cast< int >(0x1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *VSI_STAT_NATURE_FLAG_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "VSI_STAT_NATURE_FLAG",SWIG_From_int(static_cast< int >(0x2)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *VSI_STAT_SIZE_FLAG_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "VSI_STAT_SIZE_FLAG",SWIG_From_int(static_cast< int >(0x4)));
+  return SWIG_Py_Void();
+}
+
+
 SWIGINTERN PyObject *_wrap_StatBuf_mode_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   StatBuf *arg1 = (StatBuf *) 0 ;
@@ -8014,7 +8371,11 @@ SWIGINTERN PyObject *_wrap_StatBuf_mode_get(PyObject *SWIGUNUSEDPARM(self), PyOb
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StatBuf_mode_get" "', argument " "1"" of type '" "StatBuf *""'"); 
   }
   arg1 = reinterpret_cast< StatBuf * >(argp1);
-  result = (int) ((arg1)->mode);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result = (int) ((arg1)->mode);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_From_int(static_cast< int >(result));
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -8037,7 +8398,11 @@ SWIGINTERN PyObject *_wrap_StatBuf_size_get(PyObject *SWIGUNUSEDPARM(self), PyOb
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StatBuf_size_get" "', argument " "1"" of type '" "StatBuf *""'"); 
   }
   arg1 = reinterpret_cast< StatBuf * >(argp1);
-  result =  ((arg1)->size);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result =  ((arg1)->size);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   {
     char szTmp[32];
     sprintf(szTmp, CPL_FRMT_GIB, result);
@@ -8068,7 +8433,11 @@ SWIGINTERN PyObject *_wrap_StatBuf_mtime_get(PyObject *SWIGUNUSEDPARM(self), PyO
     SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "StatBuf_mtime_get" "', argument " "1"" of type '" "StatBuf *""'"); 
   }
   arg1 = reinterpret_cast< StatBuf * >(argp1);
-  result =  ((arg1)->mtime);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result =  ((arg1)->mtime);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   {
     char szTmp[32];
     sprintf(szTmp, CPL_FRMT_GIB, result);
@@ -8103,7 +8472,11 @@ SWIGINTERN PyObject *_wrap_new_StatBuf(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (StatBuf *)new_StatBuf(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (StatBuf *)new_StatBuf(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8138,7 +8511,11 @@ SWIGINTERN PyObject *_wrap_delete_StatBuf(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_StatBuf(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_StatBuf(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8174,7 +8551,11 @@ SWIGINTERN PyObject *_wrap_StatBuf_IsDirectory(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)StatBuf_IsDirectory(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)StatBuf_IsDirectory(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8242,7 +8623,11 @@ SWIGINTERN PyObject *_wrap_VSIStatL(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)wrapper_VSIStatL((char const *)arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)wrapper_VSIStatL((char const *)arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8312,7 +8697,11 @@ SWIGINTERN PyObject *_wrap_VSIFOpenL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (VSILFILE *)wrapper_VSIFOpenL((char const *)arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (VSILFILE *)wrapper_VSIFOpenL((char const *)arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8385,7 +8774,11 @@ SWIGINTERN PyObject *_wrap_VSIFOpenExL(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (VSILFILE *)wrapper_VSIFOpenExL((char const *)arg1,(char const *)arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (VSILFILE *)wrapper_VSIFOpenExL((char const *)arg1,(char const *)arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8434,7 +8827,11 @@ SWIGINTERN PyObject *_wrap_VSIFCloseL(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = VSIFCloseL(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = VSIFCloseL(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8492,7 +8889,11 @@ SWIGINTERN PyObject *_wrap_VSIFSeekL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)VSIFSeekL(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)VSIFSeekL(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8531,7 +8932,11 @@ SWIGINTERN PyObject *_wrap_VSIFTellL(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = VSIFTellL(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = VSIFTellL(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8588,7 +8993,11 @@ SWIGINTERN PyObject *_wrap_VSIFTruncateL(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)VSIFTruncateL(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)VSIFTruncateL(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8606,81 +9015,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_VSIFWriteL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_VSISupportsSparseFiles(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  int arg1 ;
-  char *arg2 = (char *) 0 ;
-  int arg3 ;
-  int arg4 ;
-  VSILFILE *arg5 = (VSILFILE *) 0 ;
-  int alloc1 = 0 ;
-  int val3 ;
-  int ecode3 = 0 ;
-  int val4 ;
-  int ecode4 = 0 ;
-  int res5 ;
+  char *arg1 = (char *) 0 ;
+  int bToFree1 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
   int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOOO:VSIFWriteL",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:VSISupportsSparseFiles",&obj0)) SWIG_fail;
   {
-    /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
-#if PY_VERSION_HEX>=0x03000000
-    if (PyUnicode_Check(obj0))
-    {
-      size_t safeLen = 0;
-      int ret = SWIG_AsCharPtrAndSize(obj0, (char**) &arg2, &safeLen, &alloc1);
-      if (!SWIG_IsOK(ret)) {
-        SWIG_exception( SWIG_RuntimeError, "invalid Unicode string" );
-      }
-      
-      if (safeLen) safeLen--;
-      arg1 = (int) safeLen;
-    }
-    else if (PyBytes_Check(obj0))
-    {
-      Py_ssize_t safeLen = 0;
-      PyBytes_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
-      arg1 = (int) safeLen;
-    }
-    else
-    {
-      PyErr_SetString(PyExc_TypeError, "not a unicode string or a bytes");
-      SWIG_fail;
-    }
-#else
-    if (PyString_Check(obj0))
-    {
-      Py_ssize_t safeLen = 0;
-      PyString_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
-      arg1 = (int) safeLen;
-    }
-    else
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
     {
-      PyErr_SetString(PyExc_TypeError, "not a string");
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
       SWIG_fail;
     }
-#endif
-  }
-  ecode3 = SWIG_AsVal_int(obj1, &val3);
-  if (!SWIG_IsOK(ecode3)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIFWriteL" "', argument " "3"" of type '" "int""'");
-  } 
-  arg3 = static_cast< int >(val3);
-  ecode4 = SWIG_AsVal_int(obj2, &val4);
-  if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "VSIFWriteL" "', argument " "4"" of type '" "int""'");
-  } 
-  arg4 = static_cast< int >(val4);
-  res5 = SWIG_ConvertPtr(obj3,SWIG_as_voidptrptr(&arg5), 0, 0);
-  if (!SWIG_IsOK(res5)) {
-    SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "VSIFWriteL" "', argument " "5"" of type '" "VSILFILE *""'"); 
   }
   {
-    if (!arg5) {
+    if (!arg1) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
     }
   }
@@ -8688,7 +9041,11 @@ SWIGINTERN PyObject *_wrap_VSIFWriteL(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)wrapper_VSIFWriteL(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)VSISupportsSparseFiles((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8700,32 +9057,249 @@ SWIGINTERN PyObject *_wrap_VSIFWriteL(PyObject *SWIGUNUSEDPARM(self), PyObject *
   }
   resultobj = SWIG_From_int(static_cast< int >(result));
   {
-    /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
-      delete[] arg2;
-    }
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
   }
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
   {
-    /* %typemap(freearg) (int *nLen, char *pBuf ) */
-    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
-      delete[] arg2;
-    }
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
   }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_ParseCommandLine(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *VSI_RANGE_STATUS_UNKNOWN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "VSI_RANGE_STATUS_UNKNOWN",SWIG_From_int(static_cast< int >(0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *VSI_RANGE_STATUS_DATA_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "VSI_RANGE_STATUS_DATA",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *VSI_RANGE_STATUS_HOLE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "VSI_RANGE_STATUS_HOLE",SWIG_From_int(static_cast< int >(2)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *_wrap_VSIFGetRangeStatusL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  char *arg1 = (char *) 0 ;
-  int bToFree1 = 0 ;
+  VSILFILE *arg1 = (VSILFILE *) 0 ;
+  GIntBig arg2 ;
+  GIntBig arg3 ;
+  int res1 ;
   PyObject * obj0 = 0 ;
-  char **result = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  int result;
   
-  if (!PyArg_ParseTuple(args,(char *)"O:ParseCommandLine",&obj0)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OOO:VSIFGetRangeStatusL",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0,SWIG_as_voidptrptr(&arg1), 0, 0);
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "VSIFGetRangeStatusL" "', argument " "1"" of type '" "VSILFILE *""'"); 
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj1,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg2 = (GIntBig)val;
+  }
+  {
+    PY_LONG_LONG val;
+    if ( !PyArg_Parse(obj2,"L",&val) ) {
+      PyErr_SetString(PyExc_TypeError, "not an integer");
+      SWIG_fail;
+    }
+    arg3 = (GIntBig)val;
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)VSIFGetRangeStatusL(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_VSIFWriteL(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  int arg1 ;
+  char *arg2 = (char *) 0 ;
+  int arg3 ;
+  int arg4 ;
+  VSILFILE *arg5 = (VSILFILE *) 0 ;
+  int alloc1 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int res5 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OOOO:VSIFWriteL",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  {
+    /* %typemap(in,numinputs=1) (int nLen, char *pBuf ) */
+#if PY_VERSION_HEX>=0x03000000
+    if (PyUnicode_Check(obj0))
+    {
+      size_t safeLen = 0;
+      int ret = SWIG_AsCharPtrAndSize(obj0, (char**) &arg2, &safeLen, &alloc1);
+      if (!SWIG_IsOK(ret)) {
+        SWIG_exception( SWIG_RuntimeError, "invalid Unicode string" );
+      }
+      
+      if (safeLen) safeLen--;
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
+      arg1 = (int) safeLen;
+    }
+    else if (PyBytes_Check(obj0))
+    {
+      Py_ssize_t safeLen = 0;
+      PyBytes_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
+      arg1 = (int) safeLen;
+    }
+    else
+    {
+      PyErr_SetString(PyExc_TypeError, "not a unicode string or a bytes");
+      SWIG_fail;
+    }
+#else
+    if (PyString_Check(obj0))
+    {
+      Py_ssize_t safeLen = 0;
+      PyString_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
+      arg1 = (int) safeLen;
+    }
+    else
+    {
+      PyErr_SetString(PyExc_TypeError, "not a string");
+      SWIG_fail;
+    }
+#endif
+  }
+  ecode3 = SWIG_AsVal_int(obj1, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "VSIFWriteL" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj2, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "VSIFWriteL" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  res5 = SWIG_ConvertPtr(obj3,SWIG_as_voidptrptr(&arg5), 0, 0);
+  if (!SWIG_IsOK(res5)) {
+    SWIG_exception_fail(SWIG_ArgError(res5), "in method '" "VSIFWriteL" "', argument " "5"" of type '" "VSILFILE *""'"); 
+  }
+  {
+    if (!arg5) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)wrapper_VSIFWriteL(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  {
+    /* %typemap(freearg) (int *nLen, char *pBuf ) */
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
+      delete[] arg2;
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (int *nLen, char *pBuf ) */
+    if (ReturnSame(alloc1) == SWIG_NEWOBJ ) {
+      delete[] arg2;
+    }
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ParseCommandLine(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  int bToFree1 = 0 ;
+  PyObject * obj0 = 0 ;
+  char **result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ParseCommandLine",&obj0)) SWIG_fail;
   {
     /* %typemap(in) (const char *utf8_path) */
     arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
@@ -8744,7 +9318,11 @@ SWIGINTERN PyObject *_wrap_ParseCommandLine(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)CSLParseCommandLine((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)CSLParseCommandLine((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8804,7 +9382,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetDescription(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8854,7 +9436,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetDescription(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8892,7 +9478,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8956,7 +9546,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9029,7 +9623,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9159,7 +9757,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9227,7 +9829,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_1(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9250,12 +9856,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[4];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[4] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -9359,7 +9967,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataItem(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9436,7 +10048,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadataItem(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9485,7 +10101,11 @@ SWIGINTERN PyObject *_wrap_Driver_ShortName_get(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALDriverShadow_ShortName_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALDriverShadow_ShortName_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9521,7 +10141,11 @@ SWIGINTERN PyObject *_wrap_Driver_LongName_get(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALDriverShadow_LongName_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALDriverShadow_LongName_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9557,7 +10181,11 @@ SWIGINTERN PyObject *_wrap_Driver_HelpTopic_get(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALDriverShadow_HelpTopic_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALDriverShadow_HelpTopic_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9705,7 +10333,11 @@ SWIGINTERN PyObject *_wrap_Driver_Create(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)GDALDriverShadow_Create(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)GDALDriverShadow_Create(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9898,7 +10530,11 @@ SWIGINTERN PyObject *_wrap_Driver_CreateCopy(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)GDALDriverShadow_CreateCopy(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)GDALDriverShadow_CreateCopy(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9979,7 +10615,11 @@ SWIGINTERN PyObject *_wrap_Driver_Delete(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDriverShadow_Delete(arg1,(char const *)arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDriverShadow_Delete(arg1,(char const *)arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10053,7 +10693,11 @@ SWIGINTERN PyObject *_wrap_Driver_Rename(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDriverShadow_Rename(arg1,(char const *)arg2,(char const *)arg3));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDriverShadow_Rename(arg1,(char const *)arg2,(char const *)arg3));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10123,7 +10767,11 @@ SWIGINTERN PyObject *_wrap_Driver_CopyFiles(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDriverShadow_CopyFiles(arg1,(char const *)arg2,(char const *)arg3));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDriverShadow_CopyFiles(arg1,(char const *)arg2,(char const *)arg3));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10163,7 +10811,11 @@ SWIGINTERN PyObject *_wrap_Driver_Register(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALDriverShadow_Register(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALDriverShadow_Register(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10198,7 +10850,11 @@ SWIGINTERN PyObject *_wrap_Driver_Deregister(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALDriverShadow_Deregister(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALDriverShadow_Deregister(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10261,7 +10917,11 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c1_set(PyObject *SWIGUNUSEDPARM(self), PyO
     SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ColorEntry_c1_set" "', argument " "2"" of type '" "short""'");
   } 
   arg2 = static_cast< short >(val2);
-  if (arg1) (arg1)->c1 = arg2;
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    if (arg1) (arg1)->c1 = arg2;
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -10300,7 +10960,11 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c1_get(PyObject *SWIGUNUSEDPARM(self), PyO
     }
     arg1 = &ce1;
   }
-  result = (short) ((arg1)->c1);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result = (short) ((arg1)->c1);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_From_short(static_cast< short >(result));
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -10347,7 +11011,11 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c2_set(PyObject *SWIGUNUSEDPARM(self), PyO
     SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ColorEntry_c2_set" "', argument " "2"" of type '" "short""'");
   } 
   arg2 = static_cast< short >(val2);
-  if (arg1) (arg1)->c2 = arg2;
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    if (arg1) (arg1)->c2 = arg2;
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -10386,7 +11054,11 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c2_get(PyObject *SWIGUNUSEDPARM(self), PyO
     }
     arg1 = &ce1;
   }
-  result = (short) ((arg1)->c2);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result = (short) ((arg1)->c2);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_From_short(static_cast< short >(result));
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -10433,7 +11105,11 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c3_set(PyObject *SWIGUNUSEDPARM(self), PyO
     SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ColorEntry_c3_set" "', argument " "2"" of type '" "short""'");
   } 
   arg2 = static_cast< short >(val2);
-  if (arg1) (arg1)->c3 = arg2;
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    if (arg1) (arg1)->c3 = arg2;
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -10472,7 +11148,11 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c3_get(PyObject *SWIGUNUSEDPARM(self), PyO
     }
     arg1 = &ce1;
   }
-  result = (short) ((arg1)->c3);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result = (short) ((arg1)->c3);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_From_short(static_cast< short >(result));
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -10519,7 +11199,11 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c4_set(PyObject *SWIGUNUSEDPARM(self), PyO
     SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ColorEntry_c4_set" "', argument " "2"" of type '" "short""'");
   } 
   arg2 = static_cast< short >(val2);
-  if (arg1) (arg1)->c4 = arg2;
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    if (arg1) (arg1)->c4 = arg2;
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_Py_Void();
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -10558,7 +11242,11 @@ SWIGINTERN PyObject *_wrap_ColorEntry_c4_get(PyObject *SWIGUNUSEDPARM(self), PyO
     }
     arg1 = &ce1;
   }
-  result = (short) ((arg1)->c4);
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result = (short) ((arg1)->c4);
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
   resultobj = SWIG_From_short(static_cast< short >(result));
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -10600,7 +11288,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPX_set(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPX_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPX_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10636,7 +11328,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPX_get(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPX_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPX_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10680,7 +11376,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPY_set(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPY_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPY_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10716,7 +11416,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPY_get(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPY_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPY_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10760,7 +11464,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPZ_set(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPZ_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPZ_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10796,7 +11504,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPZ_get(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPZ_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPZ_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10840,7 +11552,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPPixel_set(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPPixel_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPPixel_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10876,7 +11592,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPPixel_get(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPPixel_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPPixel_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10920,7 +11640,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPLine_set(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPLine_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPLine_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10956,7 +11680,11 @@ SWIGINTERN PyObject *_wrap_GCP_GCPLine_get(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPLine_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPLine_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11001,7 +11729,11 @@ SWIGINTERN PyObject *_wrap_GCP_Info_set(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_Info_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_Info_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11039,7 +11771,11 @@ SWIGINTERN PyObject *_wrap_GCP_Info_get(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDAL_GCP_Info_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDAL_GCP_Info_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11084,7 +11820,11 @@ SWIGINTERN PyObject *_wrap_GCP_Id_set(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_Id_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_Id_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11122,7 +11862,11 @@ SWIGINTERN PyObject *_wrap_GCP_Id_get(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDAL_GCP_Id_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDAL_GCP_Id_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11228,7 +11972,11 @@ SWIGINTERN PyObject *_wrap_new_GCP(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDAL_GCP *)new_GDAL_GCP(arg1,arg2,arg3,arg4,arg5,(char const *)arg6,(char const *)arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDAL_GCP *)new_GDAL_GCP(arg1,arg2,arg3,arg4,arg5,(char const *)arg6,(char const *)arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11267,7 +12015,11 @@ SWIGINTERN PyObject *_wrap_delete_GCP(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDAL_GCP(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDAL_GCP(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11315,8 +12067,12 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPX_get(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPX_get(arg1);
-#ifndef SED_HACKS
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPX_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
       if ( eclass == CE_Failure || eclass == CE_Fatal ) {
@@ -11364,7 +12120,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPX_set(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPX_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPX_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11405,7 +12165,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPY_get(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPY_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPY_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11454,7 +12218,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPY_set(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPY_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPY_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11495,7 +12263,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPZ_get(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPZ_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPZ_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11544,7 +12316,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPZ_set(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPZ_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPZ_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11585,7 +12361,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPPixel_get(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPPixel_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPPixel_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11634,7 +12414,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPPixel_set(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPPixel_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPPixel_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11675,7 +12459,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPLine_get(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDAL_GCP_GCPLine_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDAL_GCP_GCPLine_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11724,7 +12512,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_GCPLine_set(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_GCPLine_set(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_GCPLine_set(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11765,7 +12557,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_Info_get(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDAL_GCP_Info_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDAL_GCP_Info_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11815,7 +12611,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_Info_set(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_Info_set(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_Info_set(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11858,7 +12658,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_Id_get(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDAL_GCP_Id_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDAL_GCP_Id_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11908,7 +12712,11 @@ SWIGINTERN PyObject *_wrap_GDAL_GCP_Id_set(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDAL_GCP_Id_set(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDAL_GCP_Id_set(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11987,7 +12795,11 @@ SWIGINTERN PyObject *_wrap_GCPsToGeoTransform(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (RETURN_NONE)GDALGCPsToGeoTransform(arg1,(GDAL_GCP const *)arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (RETURN_NONE)GDALGCPsToGeoTransform(arg1,(GDAL_GCP const *)arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12051,7 +12863,11 @@ SWIGINTERN PyObject *_wrap_delete_VirtualMem(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_CPLVirtualMemShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_CPLVirtualMemShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12101,7 +12917,11 @@ SWIGINTERN PyObject *_wrap_VirtualMem_GetAddr(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPLVirtualMemShadow_GetAddr(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPLVirtualMemShadow_GetAddr(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12222,7 +13042,11 @@ SWIGINTERN PyObject *_wrap_VirtualMem_Pin(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPLVirtualMemShadow_Pin(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPLVirtualMemShadow_Pin(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12264,7 +13088,11 @@ SWIGINTERN PyObject *_wrap_delete_AsyncReader(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALAsyncReaderShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALAsyncReaderShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12325,7 +13153,11 @@ SWIGINTERN PyObject *_wrap_AsyncReader_GetNextUpdatedRegion(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALAsyncStatusType)GDALAsyncReaderShadow_GetNextUpdatedRegion(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALAsyncStatusType)GDALAsyncReaderShadow_GetNextUpdatedRegion(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12390,7 +13222,11 @@ SWIGINTERN PyObject *_wrap_AsyncReader_GetBuffer(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALAsyncReaderShadow_GetBuffer(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALAsyncReaderShadow_GetBuffer(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12448,7 +13284,11 @@ SWIGINTERN PyObject *_wrap_AsyncReader_LockBuffer(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALAsyncReaderShadow_LockBuffer(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALAsyncReaderShadow_LockBuffer(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12483,7 +13323,11 @@ SWIGINTERN PyObject *_wrap_AsyncReader_UnlockBuffer(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALAsyncReaderShadow_UnlockBuffer(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALAsyncReaderShadow_UnlockBuffer(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12526,7 +13370,11 @@ SWIGINTERN PyObject *_wrap_Dataset_RasterXSize_get(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALDatasetShadow_RasterXSize_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALDatasetShadow_RasterXSize_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12562,7 +13410,11 @@ SWIGINTERN PyObject *_wrap_Dataset_RasterYSize_get(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALDatasetShadow_RasterYSize_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALDatasetShadow_RasterYSize_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12598,7 +13450,11 @@ SWIGINTERN PyObject *_wrap_Dataset_RasterCount_get(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALDatasetShadow_RasterCount_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALDatasetShadow_RasterCount_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12633,7 +13489,11 @@ SWIGINTERN PyObject *_wrap_delete_Dataset(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALDatasetShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALDatasetShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12669,7 +13529,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDriverShadow *)GDALDatasetShadow_GetDriver(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDriverShadow *)GDALDatasetShadow_GetDriver(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12714,7 +13578,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetRasterBand(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALRasterBandShadow *)GDALDatasetShadow_GetRasterBand(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALRasterBandShadow *)GDALDatasetShadow_GetRasterBand(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12750,7 +13618,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetProjection(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALDatasetShadow_GetProjection(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALDatasetShadow_GetProjection(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12786,7 +13658,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetProjectionRef(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALDatasetShadow_GetProjectionRef(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALDatasetShadow_GetProjectionRef(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12837,7 +13713,11 @@ SWIGINTERN PyObject *_wrap_Dataset_SetProjection(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_SetProjection(arg1,(char const *)arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_SetProjection(arg1,(char const *)arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12904,7 +13784,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGeoTransform(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALDatasetShadow_GetGeoTransform(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALDatasetShadow_GetGeoTransform(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12979,7 +13863,11 @@ SWIGINTERN PyObject *_wrap_Dataset_SetGeoTransform(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_SetGeoTransform(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_SetGeoTransform(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13103,7 +13991,11 @@ SWIGINTERN PyObject *_wrap_Dataset_BuildOverviews(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALDatasetShadow_BuildOverviews(arg1,(char const *)arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALDatasetShadow_BuildOverviews(arg1,(char const *)arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13165,7 +14057,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGCPCount(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALDatasetShadow_GetGCPCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALDatasetShadow_GetGCPCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13201,7 +14097,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGCPProjection(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALDatasetShadow_GetGCPProjection(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALDatasetShadow_GetGCPProjection(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13245,7 +14145,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetGCPs(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALDatasetShadow_GetGCPs(arg1,arg2,(GDAL_GCP const **)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALDatasetShadow_GetGCPs(arg1,arg2,(GDAL_GCP const **)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13341,7 +14245,11 @@ SWIGINTERN PyObject *_wrap_Dataset_SetGCPs(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_SetGCPs(arg1,arg2,(GDAL_GCP const *)arg3,(char const *)arg4));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_SetGCPs(arg1,arg2,(GDAL_GCP const *)arg3,(char const *)arg4));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13390,7 +14298,11 @@ SWIGINTERN PyObject *_wrap_Dataset_FlushCache(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALDatasetShadow_FlushCache(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALDatasetShadow_FlushCache(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13492,7 +14404,11 @@ SWIGINTERN PyObject *_wrap_Dataset_AddBand(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_AddBand(arg1,arg2,arg3));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_AddBand(arg1,arg2,arg3));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13545,7 +14461,11 @@ SWIGINTERN PyObject *_wrap_Dataset_CreateMaskBand(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_CreateMaskBand(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_CreateMaskBand(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13581,7 +14501,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetFileList(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALDatasetShadow_GetFileList(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GDALDatasetShadow_GetFileList(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13852,7 +14776,11 @@ SWIGINTERN PyObject *_wrap_Dataset_WriteRaster(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14128,7 +15056,11 @@ SWIGINTERN PyObject *_wrap_Dataset_BeginAsyncReader(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALAsyncReaderShadow *)GDALDatasetShadow_BeginAsyncReader(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALAsyncReaderShadow *)GDALDatasetShadow_BeginAsyncReader(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14192,7 +15124,11 @@ SWIGINTERN PyObject *_wrap_Dataset_EndAsyncReader(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALDatasetShadow_EndAsyncReader(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALDatasetShadow_EndAsyncReader(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14409,7 +15345,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLVirtualMemShadow *)GDALDatasetShadow_GetVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLVirtualMemShadow *)GDALDatasetShadow_GetVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14637,7 +15577,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLVirtualMemShadow *)GDALDatasetShadow_GetTiledVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLVirtualMemShadow *)GDALDatasetShadow_GetTiledVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14785,7 +15729,11 @@ SWIGINTERN PyObject *_wrap_Dataset_CreateLayer(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GDALDatasetShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GDALDatasetShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14910,7 +15858,11 @@ SWIGINTERN PyObject *_wrap_Dataset_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GDALDatasetShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GDALDatasetShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14965,7 +15917,11 @@ SWIGINTERN PyObject *_wrap_Dataset_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)GDALDatasetShadow_DeleteLayer(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)GDALDatasetShadow_DeleteLayer(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14978,6 +15934,10 @@ SWIGINTERN PyObject *_wrap_Dataset_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), P
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -15013,7 +15973,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetLayerCount(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALDatasetShadow_GetLayerCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALDatasetShadow_GetLayerCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15060,7 +16024,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GDALDatasetShadow_GetLayerByIndex(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GDALDatasetShadow_GetLayerByIndex(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15106,7 +16074,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetLayerByName(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GDALDatasetShadow_GetLayerByName(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GDALDatasetShadow_GetLayerByName(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15126,35 +16098,28 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_Dataset_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Dataset_ResetReading(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
   PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  bool result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:Dataset_TestCapability",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"O:Dataset_ResetReading",&obj0)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_TestCapability" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_ResetReading" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
   }
   arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Dataset_TestCapability" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
   {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)GDALDatasetShadow_TestCapability(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALDatasetShadow_ResetReading(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15164,76 +16129,120 @@ SWIGINTERN PyObject *_wrap_Dataset_TestCapability(PyObject *SWIGUNUSEDPARM(self)
     }
 #endif
   }
-  resultobj = SWIG_From_bool(static_cast< bool >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  resultobj = SWIG_Py_Void();
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Dataset_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+SWIGINTERN PyObject *_wrap_Dataset_GetNextFeature(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
-  char *arg4 = (char *) "" ;
+  bool arg2 = (bool) true ;
+  bool arg3 = (bool) false ;
+  OGRLayerShadow **arg4 = (OGRLayerShadow **) NULL ;
+  double *arg5 = (double *) NULL ;
+  GDALProgressFunc arg6 = (GDALProgressFunc) NULL ;
+  void *arg7 = (void *) NULL ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  void *argp3 = 0 ;
-  int res3 = 0 ;
-  int res4 ;
-  char *buf4 = 0 ;
-  int alloc4 = 0 ;
+  bool val2 ;
+  int ecode2 = 0 ;
+  bool val3 ;
+  int ecode3 = 0 ;
+  OGRLayerShadow *poBelongingLayer4 = NULL ;
+  double dfProgressPct4 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
   PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
   char *  kwnames[] = {
-    (char *) "self",(char *) "statement",(char *) "spatialFilter",(char *) "dialect", NULL 
+    (char *) "self",(char *) "include_layer",(char *) "include_pct",(char *) "callback",(char *) "callback_data", NULL 
   };
-  OGRLayerShadow *result = 0 ;
+  OGRFeatureShadow *result = 0 ;
   
-  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|OO:Dataset_ExecuteSQL",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  /* %typemap(arginit) ( const char* callback_data=NULL)  */
+  PyProgressData *psProgressInfo;
+  psProgressInfo = (PyProgressData *) CPLCalloc(1,sizeof(PyProgressData));
+  psProgressInfo->nLastReported = -1;
+  psProgressInfo->psPyCallback = NULL;
+  psProgressInfo->psPyCallbackData = NULL;
+  arg7 = psProgressInfo;
+  {
+    /* %typemap(in) (OGRLayerShadow** ppoBelongingLayer, double* pdfProgressPct)  */
+    arg4 = &poBelongingLayer4;
+    arg5 = &dfProgressPct4;
+  }
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|OOOO:Dataset_GetNextFeature",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_ExecuteSQL" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_GetNextFeature" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
   }
   arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Dataset_ExecuteSQL" "', argument " "2"" of type '" "char const *""'");
+  if (obj1) {
+    ecode2 = SWIG_AsVal_bool(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Dataset_GetNextFeature" "', argument " "2"" of type '" "bool""'");
+    } 
+    arg2 = static_cast< bool >(val2);
   }
-  arg2 = reinterpret_cast< char * >(buf2);
   if (obj2) {
-    res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Dataset_ExecuteSQL" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
-    }
-    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
+    ecode3 = SWIG_AsVal_bool(obj2, &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Dataset_GetNextFeature" "', argument " "3"" of type '" "bool""'");
+    } 
+    arg3 = static_cast< bool >(val3);
   }
   if (obj3) {
-    res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Dataset_ExecuteSQL" "', argument " "4"" of type '" "char const *""'");
+    {
+      /* %typemap(in) (GDALProgressFunc callback = NULL) */
+      /* callback_func typemap */
+      if (obj3 && obj3 != Py_None ) {
+        void* cbfunction = NULL;
+        CPL_IGNORE_RET_VAL(SWIG_ConvertPtr( obj3,
+            (void**)&cbfunction,
+            SWIGTYPE_p_f_double_p_q_const__char_p_void__int,
+            SWIG_POINTER_EXCEPTION | 0 ));
+        
+        if ( cbfunction == GDALTermProgress ) {
+          arg6 = GDALTermProgress;
+        } else {
+          if (!PyCallable_Check(obj3)) {
+            PyErr_SetString( PyExc_RuntimeError,
+              "Object given is not a Python function" );
+            SWIG_fail;
+          }
+          psProgressInfo->psPyCallback = obj3;
+          arg6 = PyProgressProxy;
+        }
+        
+      }
+      
     }
-    arg4 = reinterpret_cast< char * >(buf4);
   }
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+  if (obj4) {
+    {
+      /* %typemap(in) ( void* callback_data=NULL)  */
+      psProgressInfo->psPyCallbackData = obj4 ;
     }
   }
   {
+    /* %typemap(check) (OGRLayerShadow** ppoBelongingLayer, double* pdfProgressPct)  */
+    if( !arg3 )
+    arg5 = NULL;
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GDALDatasetShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFeatureShadow *)GDALDatasetShadow_GetNextFeature(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15243,27 +16252,204 @@ SWIGINTERN PyObject *_wrap_Dataset_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self), Py
     }
 #endif
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRFeatureShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(argout) (OGRLayerShadow** ppoBelongingLayer, double* pdfProgressPct)  */
+    
+    if( arg2 )
+    {
+      if( resultobj == Py_None )
+      {
+        resultobj = PyList_New(1);
+        PyList_SetItem(resultobj, 0, Py_None);
+      }
+      
+      if ( !*arg4 ) {
+        Py_INCREF(Py_None);
+        resultobj = SWIG_Python_AppendOutput(resultobj, Py_None);
+      }
+      else {
+        resultobj = SWIG_Python_AppendOutput(resultobj,
+          SWIG_NewPointerObj(SWIG_as_voidptr( *arg4), SWIGTYPE_p_OGRLayerShadow, 0 ));
+      }
+    }
+    
+    if( arg3 )
+    {
+      if( resultobj == Py_None )
+      {
+        resultobj = PyList_New(1);
+        PyList_SetItem(resultobj, 0, Py_None);
+      }
+      resultobj = SWIG_Python_AppendOutput(resultobj, PyFloat_FromDouble( *arg5));
+    }
+    
+  }
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  {
+    /* %typemap(freearg) ( void* callback_data=NULL)  */
+    
+    CPLFree(psProgressInfo);
+    
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_Dataset_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_Dataset_TestCapability(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
-  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int res2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Dataset_TestCapability",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_TestCapability" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Dataset_TestCapability" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)GDALDatasetShadow_TestCapability(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Dataset_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  OGRGeometryShadow *arg3 = (OGRGeometryShadow *) NULL ;
+  char *arg4 = (char *) "" ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  void *argp3 = 0 ;
+  int res3 = 0 ;
+  int res4 ;
+  char *buf4 = 0 ;
+  int alloc4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "self",(char *) "statement",(char *) "spatialFilter",(char *) "dialect", NULL 
+  };
+  OGRLayerShadow *result = 0 ;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|OO:Dataset_ExecuteSQL",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Dataset_ExecuteSQL" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Dataset_ExecuteSQL" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  if (obj2) {
+    res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+    if (!SWIG_IsOK(res3)) {
+      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "Dataset_ExecuteSQL" "', argument " "3"" of type '" "OGRGeometryShadow *""'"); 
+    }
+    arg3 = reinterpret_cast< OGRGeometryShadow * >(argp3);
+  }
+  if (obj3) {
+    res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
+    if (!SWIG_IsOK(res4)) {
+      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Dataset_ExecuteSQL" "', argument " "4"" of type '" "char const *""'");
+    }
+    arg4 = reinterpret_cast< char * >(buf4);
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GDALDatasetShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_OGRLayerShadow, 0 |  0 );
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Dataset_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  OGRLayerShadow *arg2 = (OGRLayerShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
   
   if (!PyArg_ParseTuple(args,(char *)"OO:Dataset_ReleaseResultSet",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
@@ -15279,7 +16465,11 @@ SWIGINTERN PyObject *_wrap_Dataset_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALDatasetShadow_ReleaseResultSet(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALDatasetShadow_ReleaseResultSet(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15315,7 +16505,11 @@ SWIGINTERN PyObject *_wrap_Dataset_GetStyleTable(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRStyleTableShadow *)GDALDatasetShadow_GetStyleTable(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRStyleTableShadow *)GDALDatasetShadow_GetStyleTable(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15359,7 +16553,11 @@ SWIGINTERN PyObject *_wrap_Dataset_SetStyleTable(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALDatasetShadow_SetStyleTable(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALDatasetShadow_SetStyleTable(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15409,7 +16607,11 @@ SWIGINTERN PyObject *_wrap_Dataset_StartTransaction(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)GDALDatasetShadow_StartTransaction(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)GDALDatasetShadow_StartTransaction(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15422,6 +16624,10 @@ SWIGINTERN PyObject *_wrap_Dataset_StartTransaction(PyObject *SWIGUNUSEDPARM(sel
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -15457,7 +16663,11 @@ SWIGINTERN PyObject *_wrap_Dataset_CommitTransaction(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)GDALDatasetShadow_CommitTransaction(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)GDALDatasetShadow_CommitTransaction(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15470,6 +16680,10 @@ SWIGINTERN PyObject *_wrap_Dataset_CommitTransaction(PyObject *SWIGUNUSEDPARM(se
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -15505,7 +16719,11 @@ SWIGINTERN PyObject *_wrap_Dataset_RollbackTransaction(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)GDALDatasetShadow_RollbackTransaction(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)GDALDatasetShadow_RollbackTransaction(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15518,6 +16736,10 @@ SWIGINTERN PyObject *_wrap_Dataset_RollbackTransaction(PyObject *SWIGUNUSEDPARM(
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -15790,7 +17012,11 @@ SWIGINTERN PyObject *_wrap_Dataset_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_ReadRaster1(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALDatasetShadow_ReadRaster1(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14,arg15,arg16,arg17));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15870,7 +17096,11 @@ SWIGINTERN PyObject *_wrap_Band_XSize_get(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterBandShadow_XSize_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_XSize_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15906,7 +17136,11 @@ SWIGINTERN PyObject *_wrap_Band_YSize_get(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterBandShadow_YSize_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_YSize_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15942,7 +17176,11 @@ SWIGINTERN PyObject *_wrap_Band_DataType_get(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDataType)GDALRasterBandShadow_DataType_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDataType)GDALRasterBandShadow_DataType_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15978,7 +17216,11 @@ SWIGINTERN PyObject *_wrap_Band_GetDataset(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)GDALRasterBandShadow_GetDataset(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)GDALRasterBandShadow_GetDataset(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16014,7 +17256,11 @@ SWIGINTERN PyObject *_wrap_Band_GetBand(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterBandShadow_GetBand(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_GetBand(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16057,7 +17303,11 @@ SWIGINTERN PyObject *_wrap_Band_GetBlockSize(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterBandShadow_GetBlockSize(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_GetBlockSize(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16087,6 +17337,89 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Band_GetActualBlockSize(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  int *arg4 = (int *) 0 ;
+  int *arg5 = (int *) 0 ;
+  int *arg6 = (int *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int nxvalid4 = 0 ;
+  int nyvalid4 = 0 ;
+  int isvalid4 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  
+  {
+    /* %typemap(in) (int *pnxvalid, int *pnyvalid, int* pisvalid) */
+    arg4 = &nxvalid4;
+    arg5 = &nyvalid4;
+    arg6 = &isvalid4;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"OOO:Band_GetActualBlockSize",&obj0,&obj1,&obj2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetActualBlockSize" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_GetActualBlockSize" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_GetActualBlockSize" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_GetActualBlockSize(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  {
+    /* %typemap(argout) (int *pnxvalid, int *pnyvalid, int* pisvalid)  */
+    PyObject *r;
+    if ( !*arg6 ) {
+      Py_INCREF(Py_None);
+      r = Py_None;
+    }
+    else {
+      r = PyTuple_New( 2 );
+      PyTuple_SetItem( r, 0, PyLong_FromLong(*arg4) );
+      PyTuple_SetItem( r, 1, PyLong_FromLong(*arg5) );
+    }
+    resultobj = t_output_helper(resultobj,r);
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Band_GetColorInterpretation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
@@ -16105,7 +17438,11 @@ SWIGINTERN PyObject *_wrap_Band_GetColorInterpretation(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALColorInterp)GDALRasterBandShadow_GetColorInterpretation(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALColorInterp)GDALRasterBandShadow_GetColorInterpretation(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16141,7 +17478,11 @@ SWIGINTERN PyObject *_wrap_Band_GetRasterColorInterpretation(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALColorInterp)GDALRasterBandShadow_GetRasterColorInterpretation(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALColorInterp)GDALRasterBandShadow_GetRasterColorInterpretation(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16186,7 +17527,11 @@ SWIGINTERN PyObject *_wrap_Band_SetColorInterpretation(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetColorInterpretation(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetColorInterpretation(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16231,7 +17576,11 @@ SWIGINTERN PyObject *_wrap_Band_SetRasterColorInterpretation(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetRasterColorInterpretation(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetRasterColorInterpretation(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16275,7 +17624,11 @@ SWIGINTERN PyObject *_wrap_Band_GetNoDataValue(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterBandShadow_GetNoDataValue(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_GetNoDataValue(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16333,7 +17686,11 @@ SWIGINTERN PyObject *_wrap_Band_SetNoDataValue(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetNoDataValue(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetNoDataValue(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16369,7 +17726,11 @@ SWIGINTERN PyObject *_wrap_Band_DeleteNoDataValue(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_DeleteNoDataValue(arg1));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_DeleteNoDataValue(arg1));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16405,7 +17766,11 @@ SWIGINTERN PyObject *_wrap_Band_GetUnitType(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALRasterBandShadow_GetUnitType(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALRasterBandShadow_GetUnitType(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16451,7 +17816,11 @@ SWIGINTERN PyObject *_wrap_Band_SetUnitType(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetUnitType(arg1,(char const *)arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetUnitType(arg1,(char const *)arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16489,7 +17858,11 @@ SWIGINTERN PyObject *_wrap_Band_GetRasterCategoryNames(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALRasterBandShadow_GetRasterCategoryNames(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GDALRasterBandShadow_GetRasterCategoryNames(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16590,7 +17963,11 @@ SWIGINTERN PyObject *_wrap_Band_SetRasterCategoryNames(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetRasterCategoryNames(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetRasterCategoryNames(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16642,7 +18019,11 @@ SWIGINTERN PyObject *_wrap_Band_GetMinimum(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterBandShadow_GetMinimum(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_GetMinimum(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16699,7 +18080,11 @@ SWIGINTERN PyObject *_wrap_Band_GetMaximum(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterBandShadow_GetMaximum(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_GetMaximum(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16756,7 +18141,11 @@ SWIGINTERN PyObject *_wrap_Band_GetOffset(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterBandShadow_GetOffset(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_GetOffset(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16813,7 +18202,11 @@ SWIGINTERN PyObject *_wrap_Band_GetScale(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterBandShadow_GetScale(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_GetScale(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16871,7 +18264,11 @@ SWIGINTERN PyObject *_wrap_Band_SetOffset(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetOffset(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetOffset(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16916,7 +18313,11 @@ SWIGINTERN PyObject *_wrap_Band_SetScale(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetScale(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetScale(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16986,7 +18387,11 @@ SWIGINTERN PyObject *_wrap_Band_GetStatistics(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_GetStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_GetStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17117,7 +18522,11 @@ SWIGINTERN PyObject *_wrap_Band_ComputeStatistics(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_ComputeStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_ComputeStatistics(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17227,7 +18636,11 @@ SWIGINTERN PyObject *_wrap_Band_SetStatistics(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetStatistics(arg1,arg2,arg3,arg4,arg5));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetStatistics(arg1,arg2,arg3,arg4,arg5));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17263,7 +18676,11 @@ SWIGINTERN PyObject *_wrap_Band_GetOverviewCount(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterBandShadow_GetOverviewCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_GetOverviewCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17308,7 +18725,11 @@ SWIGINTERN PyObject *_wrap_Band_GetOverview(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALRasterBandShadow *)GDALRasterBandShadow_GetOverview(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALRasterBandShadow *)GDALRasterBandShadow_GetOverview(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17405,7 +18826,11 @@ SWIGINTERN PyObject *_wrap_Band_Checksum(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterBandShadow_Checksum(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_Checksum(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17458,7 +18883,11 @@ SWIGINTERN PyObject *_wrap_Band_ComputeRasterMinMax(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterBandShadow_ComputeRasterMinMax(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_ComputeRasterMinMax(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17516,7 +18945,11 @@ SWIGINTERN PyObject *_wrap_Band_ComputeBandStats(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterBandShadow_ComputeBandStats(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_ComputeBandStats(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17577,7 +19010,11 @@ SWIGINTERN PyObject *_wrap_Band_Fill(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_Fill(arg1,arg2,arg3));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_Fill(arg1,arg2,arg3));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17785,7 +19222,11 @@ SWIGINTERN PyObject *_wrap_Band_WriteRaster(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_WriteRaster(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17832,7 +19273,11 @@ SWIGINTERN PyObject *_wrap_Band_FlushCache(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterBandShadow_FlushCache(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterBandShadow_FlushCache(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17868,7 +19313,11 @@ SWIGINTERN PyObject *_wrap_Band_GetRasterColorTable(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALColorTableShadow *)GDALRasterBandShadow_GetRasterColorTable(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALColorTableShadow *)GDALRasterBandShadow_GetRasterColorTable(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17904,7 +19353,11 @@ SWIGINTERN PyObject *_wrap_Band_GetColorTable(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALColorTableShadow *)GDALRasterBandShadow_GetColorTable(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALColorTableShadow *)GDALRasterBandShadow_GetColorTable(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17949,7 +19402,11 @@ SWIGINTERN PyObject *_wrap_Band_SetRasterColorTable(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterBandShadow_SetRasterColorTable(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_SetRasterColorTable(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17994,7 +19451,11 @@ SWIGINTERN PyObject *_wrap_Band_SetColorTable(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterBandShadow_SetColorTable(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_SetColorTable(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18030,7 +19491,11 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultRAT(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALRasterAttributeTableShadow *)GDALRasterBandShadow_GetDefaultRAT(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALRasterAttributeTableShadow *)GDALRasterBandShadow_GetDefaultRAT(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18075,7 +19540,11 @@ SWIGINTERN PyObject *_wrap_Band_SetDefaultRAT(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterBandShadow_SetDefaultRAT(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_SetDefaultRAT(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18111,7 +19580,11 @@ SWIGINTERN PyObject *_wrap_Band_GetMaskBand(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALRasterBandShadow *)GDALRasterBandShadow_GetMaskBand(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALRasterBandShadow *)GDALRasterBandShadow_GetMaskBand(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18147,7 +19620,11 @@ SWIGINTERN PyObject *_wrap_Band_GetMaskFlags(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterBandShadow_GetMaskFlags(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_GetMaskFlags(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18192,7 +19669,11 @@ SWIGINTERN PyObject *_wrap_Band_CreateMaskBand(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_CreateMaskBand(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_CreateMaskBand(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18348,7 +19829,11 @@ SWIGINTERN PyObject *_wrap_Band_GetHistogram(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_GetHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_GetHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18540,7 +20025,11 @@ SWIGINTERN PyObject *_wrap_Band_GetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_GetDefaultHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_GetDefaultHistogram(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18658,7 +20147,11 @@ SWIGINTERN PyObject *_wrap_Band_SetDefaultHistogram(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetDefaultHistogram(arg1,arg2,arg3,arg4,arg5));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetDefaultHistogram(arg1,arg2,arg3,arg4,arg5));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18706,7 +20199,11 @@ SWIGINTERN PyObject *_wrap_Band_HasArbitraryOverviews(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)GDALRasterBandShadow_HasArbitraryOverviews(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)GDALRasterBandShadow_HasArbitraryOverviews(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18742,7 +20239,11 @@ SWIGINTERN PyObject *_wrap_Band_GetCategoryNames(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALRasterBandShadow_GetCategoryNames(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GDALRasterBandShadow_GetCategoryNames(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18843,7 +20344,11 @@ SWIGINTERN PyObject *_wrap_Band_SetCategoryNames(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetCategoryNames(arg1,arg2));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_SetCategoryNames(arg1,arg2));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19032,7 +20537,11 @@ SWIGINTERN PyObject *_wrap_Band_GetVirtualMem(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19140,7 +20649,11 @@ SWIGINTERN PyObject *_wrap_Band_GetVirtualMemAuto(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetVirtualMemAuto(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetVirtualMemAuto(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19320,7 +20833,11 @@ SWIGINTERN PyObject *_wrap_Band_GetTiledVirtualMem(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetTiledVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLVirtualMemShadow *)GDALRasterBandShadow_GetTiledVirtualMem(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19346,6 +20863,103 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Band_GetDataCoverageStatus(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
+  int arg2 ;
+  int arg3 ;
+  int arg4 ;
+  int arg5 ;
+  int arg6 = (int) 0 ;
+  double *arg7 = (double *) NULL ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  int val3 ;
+  int ecode3 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
+  int val5 ;
+  int ecode5 = 0 ;
+  int val6 ;
+  int ecode6 = 0 ;
+  double temp7 ;
+  int res7 = SWIG_TMPOBJ ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  int result;
+  
+  arg7 = &temp7;
+  if (!PyArg_ParseTuple(args,(char *)"OOOOO|O:Band_GetDataCoverageStatus",&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALRasterBandShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Band_GetDataCoverageStatus" "', argument " "1"" of type '" "GDALRasterBandShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALRasterBandShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Band_GetDataCoverageStatus" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  ecode3 = SWIG_AsVal_int(obj2, &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Band_GetDataCoverageStatus" "', argument " "3"" of type '" "int""'");
+  } 
+  arg3 = static_cast< int >(val3);
+  ecode4 = SWIG_AsVal_int(obj3, &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Band_GetDataCoverageStatus" "', argument " "4"" of type '" "int""'");
+  } 
+  arg4 = static_cast< int >(val4);
+  ecode5 = SWIG_AsVal_int(obj4, &val5);
+  if (!SWIG_IsOK(ecode5)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "Band_GetDataCoverageStatus" "', argument " "5"" of type '" "int""'");
+  } 
+  arg5 = static_cast< int >(val5);
+  if (obj5) {
+    ecode6 = SWIG_AsVal_int(obj5, &val6);
+    if (!SWIG_IsOK(ecode6)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "Band_GetDataCoverageStatus" "', argument " "6"" of type '" "int""'");
+    } 
+    arg6 = static_cast< int >(val6);
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterBandShadow_GetDataCoverageStatus(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if (ReturnSame(SWIG_IsTmpObj(res7))) {
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_From_double((*arg7)));
+  } else {
+    int new_flags = SWIG_IsNewObj(res7) ? (SWIG_POINTER_OWN |  0 ) :  0 ;
+    resultobj = SWIG_Python_AppendOutput(resultobj, SWIG_NewPointerObj((void*)(arg7), SWIGTYPE_p_double, new_flags));
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
@@ -19554,7 +21168,11 @@ SWIGINTERN PyObject *_wrap_Band_ReadRaster1(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_ReadRaster1(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_ReadRaster1(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12,arg13,arg14));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19642,7 +21260,11 @@ SWIGINTERN PyObject *_wrap_Band_ReadBlock(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_ReadBlock(arg1,arg2,arg3,arg4));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)GDALRasterBandShadow_ReadBlock(arg1,arg2,arg3,arg4));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19703,7 +21325,11 @@ SWIGINTERN PyObject *_wrap_new_ColorTable(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALColorTableShadow *)new_GDALColorTableShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALColorTableShadow *)new_GDALColorTableShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19738,7 +21364,11 @@ SWIGINTERN PyObject *_wrap_delete_ColorTable(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALColorTableShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALColorTableShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19774,7 +21404,11 @@ SWIGINTERN PyObject *_wrap_ColorTable_Clone(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALColorTableShadow *)GDALColorTableShadow_Clone(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALColorTableShadow *)GDALColorTableShadow_Clone(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19810,7 +21444,11 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetPaletteInterpretation(PyObject *SWIGUNU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALPaletteInterp)GDALColorTableShadow_GetPaletteInterpretation(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALPaletteInterp)GDALColorTableShadow_GetPaletteInterpretation(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19846,7 +21484,11 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetCount(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALColorTableShadow_GetColorEntryCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALColorTableShadow_GetColorEntryCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19891,7 +21533,11 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetColorEntry(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALColorEntry *)GDALColorTableShadow_GetColorEntry(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALColorEntry *)GDALColorTableShadow_GetColorEntry(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19967,7 +21613,11 @@ SWIGINTERN PyObject *_wrap_ColorTable_GetColorEntryAsRGB(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALColorTableShadow_GetColorEntryAsRGB(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALColorTableShadow_GetColorEntryAsRGB(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20036,7 +21686,11 @@ SWIGINTERN PyObject *_wrap_ColorTable_SetColorEntry(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALColorTableShadow_SetColorEntry(arg1,arg2,(GDALColorEntry const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALColorTableShadow_SetColorEntry(arg1,arg2,(GDALColorEntry const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20139,7 +21793,11 @@ SWIGINTERN PyObject *_wrap_ColorTable_CreateColorRamp(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALColorTableShadow_CreateColorRamp(arg1,arg2,(GDALColorEntry const *)arg3,arg4,(GDALColorEntry const *)arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALColorTableShadow_CreateColorRamp(arg1,arg2,(GDALColorEntry const *)arg3,arg4,(GDALColorEntry const *)arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20173,7 +21831,11 @@ SWIGINTERN PyObject *_wrap_new_RasterAttributeTable(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALRasterAttributeTableShadow *)new_GDALRasterAttributeTableShadow();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALRasterAttributeTableShadow *)new_GDALRasterAttributeTableShadow();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20208,7 +21870,11 @@ SWIGINTERN PyObject *_wrap_delete_RasterAttributeTable(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALRasterAttributeTableShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALRasterAttributeTableShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20244,7 +21910,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_Clone(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALRasterAttributeTableShadow *)GDALRasterAttributeTableShadow_Clone(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALRasterAttributeTableShadow *)GDALRasterAttributeTableShadow_Clone(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20280,7 +21950,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetColumnCount(PyObject *SWIGUNU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterAttributeTableShadow_GetColumnCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterAttributeTableShadow_GetColumnCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20325,7 +21999,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetNameOfCol(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALRasterAttributeTableShadow_GetNameOfCol(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALRasterAttributeTableShadow_GetNameOfCol(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20370,7 +22048,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetUsageOfCol(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALRATFieldUsage)GDALRasterAttributeTableShadow_GetUsageOfCol(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALRATFieldUsage)GDALRasterAttributeTableShadow_GetUsageOfCol(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20415,7 +22097,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetTypeOfCol(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALRATFieldType)GDALRasterAttributeTableShadow_GetTypeOfCol(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALRATFieldType)GDALRasterAttributeTableShadow_GetTypeOfCol(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20460,7 +22146,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetColOfUsage(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterAttributeTableShadow_GetColOfUsage(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterAttributeTableShadow_GetColOfUsage(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20496,7 +22186,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetRowCount(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterAttributeTableShadow_GetRowCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterAttributeTableShadow_GetRowCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20550,7 +22244,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetValueAsString(PyObject *SWIGU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALRasterAttributeTableShadow_GetValueAsString(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALRasterAttributeTableShadow_GetValueAsString(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20604,7 +22302,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetValueAsInt(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterAttributeTableShadow_GetValueAsInt(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterAttributeTableShadow_GetValueAsInt(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20658,7 +22360,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetValueAsDouble(PyObject *SWIGU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDALRasterAttributeTableShadow_GetValueAsDouble(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDALRasterAttributeTableShadow_GetValueAsDouble(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20725,7 +22431,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsString(PyObject *SWIGU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterAttributeTableShadow_SetValueAsString(arg1,arg2,arg3,(char const *)arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterAttributeTableShadow_SetValueAsString(arg1,arg2,arg3,(char const *)arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20803,7 +22513,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsInt(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterAttributeTableShadow_SetValueAsInt(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterAttributeTableShadow_SetValueAsInt(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20865,7 +22579,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetValueAsDouble(PyObject *SWIGU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterAttributeTableShadow_SetValueAsDouble(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterAttributeTableShadow_SetValueAsDouble(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20909,7 +22627,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetRowCount(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterAttributeTableShadow_SetRowCount(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterAttributeTableShadow_SetRowCount(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20973,7 +22695,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_CreateColumn(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterAttributeTableShadow_CreateColumn(arg1,(char const *)arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterAttributeTableShadow_CreateColumn(arg1,(char const *)arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21019,7 +22745,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetLinearBinning(PyObject *SWIGU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)GDALRasterAttributeTableShadow_GetLinearBinning(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)GDALRasterAttributeTableShadow_GetLinearBinning(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21085,7 +22815,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_SetLinearBinning(PyObject *SWIGU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterAttributeTableShadow_SetLinearBinning(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterAttributeTableShadow_SetLinearBinning(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21130,7 +22864,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_GetRowOfValue(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterAttributeTableShadow_GetRowOfValue(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterAttributeTableShadow_GetRowOfValue(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21166,7 +22904,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_ChangesAreWrittenToFile(PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALRasterAttributeTableShadow_ChangesAreWrittenToFile(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21201,7 +22943,11 @@ SWIGINTERN PyObject *_wrap_RasterAttributeTable_DumpReadable(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALRasterAttributeTableShadow_DumpReadable(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALRasterAttributeTableShadow_DumpReadable(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21268,7 +23014,11 @@ SWIGINTERN PyObject *_wrap_TermProgress_nocb(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALTermProgress_nocb(arg1,(char const *)arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALTermProgress_nocb(arg1,(char const *)arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21288,6 +23038,17 @@ fail:
 }
 
 
+SWIGINTERN PyObject *TermProgress_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  
+  return SWIG_Py_Void();
+}
+
+
 SWIGINTERN PyObject *_wrap_ComputeMedianCutPCT(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALRasterBandShadow *arg1 = (GDALRasterBandShadow *) 0 ;
@@ -21409,7 +23170,11 @@ SWIGINTERN PyObject *_wrap_ComputeMedianCutPCT(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)ComputeMedianCutPCT(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)ComputeMedianCutPCT(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21565,7 +23330,11 @@ SWIGINTERN PyObject *_wrap_DitherRGB2PCT(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)DitherRGB2PCT(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)DitherRGB2PCT(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21788,7 +23557,11 @@ SWIGINTERN PyObject *_wrap_ReprojectImage(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    CPL_IGNORE_RET_VAL(result = (CPLErr)ReprojectImage(arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7,arg8,arg9,arg10));
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      CPL_IGNORE_RET_VAL(result = (CPLErr)ReprojectImage(arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7,arg8,arg9,arg10));
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21966,7 +23739,11 @@ SWIGINTERN PyObject *_wrap_ComputeProximity(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)ComputeProximity(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)ComputeProximity(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22214,7 +23991,11 @@ SWIGINTERN PyObject *_wrap_RasterizeLayer(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)RasterizeLayer(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)RasterizeLayer(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22430,7 +24211,11 @@ SWIGINTERN PyObject *_wrap_Polygonize(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)Polygonize(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)Polygonize(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22622,7 +24407,11 @@ SWIGINTERN PyObject *_wrap_FPolygonize(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)FPolygonize(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)FPolygonize(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22809,7 +24598,11 @@ SWIGINTERN PyObject *_wrap_FillNodata(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)FillNodata(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)FillNodata(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23012,7 +24805,11 @@ SWIGINTERN PyObject *_wrap_SieveFilter(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)SieveFilter(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)SieveFilter(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23102,7 +24899,7 @@ SWIGINTERN PyObject *_wrap_RegenerateOverviews(PyObject *SWIGUNUSEDPARM(self), P
     
     for( int i = 0; i<arg2; i++ ) {
       PyObject *o = PySequence_GetItem(obj1,i);
-#if 0x020012 <= 0x010337
+#if 0x030008 <= 0x010337
       PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
 #else
       SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
@@ -23167,7 +24964,11 @@ SWIGINTERN PyObject *_wrap_RegenerateOverviews(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)RegenerateOverviews(arg1,arg2,arg3,(char const *)arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)RegenerateOverviews(arg1,arg2,arg3,(char const *)arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23303,7 +25104,11 @@ SWIGINTERN PyObject *_wrap_RegenerateOverview(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)RegenerateOverview(arg1,arg2,(char const *)arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)RegenerateOverview(arg1,arg2,(char const *)arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23500,7 +25305,11 @@ SWIGINTERN PyObject *_wrap_ContourGenerate(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)ContourGenerate(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)ContourGenerate(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23611,7 +25420,11 @@ SWIGINTERN PyObject *_wrap_AutoCreateWarpedVRT(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)AutoCreateWarpedVRT(arg1,(char const *)arg2,(char const *)arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)AutoCreateWarpedVRT(arg1,(char const *)arg2,(char const *)arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23676,7 +25489,7 @@ SWIGINTERN PyObject *_wrap_CreatePansharpenedVRT(PyObject *SWIGUNUSEDPARM(self),
     
     for( int i = 0; i<arg3; i++ ) {
       PyObject *o = PySequence_GetItem(obj2,i);
-#if 0x020012 <= 0x010337
+#if 0x030008 <= 0x010337
       PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
 #else
       SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
@@ -23701,7 +25514,11 @@ SWIGINTERN PyObject *_wrap_CreatePansharpenedVRT(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)CreatePansharpenedVRT((char const *)arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)CreatePansharpenedVRT((char const *)arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23806,7 +25623,11 @@ SWIGINTERN PyObject *_wrap_new_Transformer(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALTransformerInfoShadow *)new_GDALTransformerInfoShadow(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALTransformerInfoShadow *)new_GDALTransformerInfoShadow(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23849,7 +25670,11 @@ SWIGINTERN PyObject *_wrap_delete_Transformer(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALTransformerInfoShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALTransformerInfoShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23921,7 +25746,11 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_0(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALTransformerInfoShadow_TransformPoint__SWIG_0(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALTransformerInfoShadow_TransformPoint__SWIG_0(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24007,7 +25836,11 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoint__SWIG_1(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALTransformerInfoShadow_TransformPoint__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALTransformerInfoShadow_TransformPoint__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24031,12 +25864,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Transformer_TransformPoint(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[6];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[6] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 5) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -24167,7 +26002,11 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformPoints(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALTransformerInfoShadow_TransformPoints(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALTransformerInfoShadow_TransformPoints(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24375,7 +26214,11 @@ SWIGINTERN PyObject *_wrap_Transformer_TransformGeolocations(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALTransformerInfoShadow_TransformGeolocations(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALTransformerInfoShadow_TransformGeolocations(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24420,6 +26263,161 @@ SWIGINTERN PyObject *Transformer_swigregister(PyObject *SWIGUNUSEDPARM(self), Py
   return SWIG_Py_Void();
 }
 
+SWIGINTERN PyObject *_wrap_ApplyVerticalShiftGrid(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  GDALDatasetShadow *arg1 = (GDALDatasetShadow *) 0 ;
+  GDALDatasetShadow *arg2 = (GDALDatasetShadow *) 0 ;
+  bool arg3 = (bool) false ;
+  double arg4 = (double) 1.0 ;
+  double arg5 = (double) 1.0 ;
+  char **arg6 = (char **) NULL ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  bool val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  double val5 ;
+  int ecode5 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  PyObject * obj4 = 0 ;
+  PyObject * obj5 = 0 ;
+  char *  kwnames[] = {
+    (char *) "src_ds",(char *) "grid_ds",(char *) "inverse",(char *) "srcUnitToMeter",(char *) "dstUnitToMeter",(char *) "options", NULL 
+  };
+  GDALDatasetShadow *result = 0 ;
+  
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO|OOOO:ApplyVerticalShiftGrid",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4,&obj5)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ApplyVerticalShiftGrid" "', argument " "1"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< GDALDatasetShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_GDALDatasetShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ApplyVerticalShiftGrid" "', argument " "2"" of type '" "GDALDatasetShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< GDALDatasetShadow * >(argp2);
+  if (obj2) {
+    ecode3 = SWIG_AsVal_bool(obj2, &val3);
+    if (!SWIG_IsOK(ecode3)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ApplyVerticalShiftGrid" "', argument " "3"" of type '" "bool""'");
+    } 
+    arg3 = static_cast< bool >(val3);
+  }
+  if (obj3) {
+    ecode4 = SWIG_AsVal_double(obj3, &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "ApplyVerticalShiftGrid" "', argument " "4"" of type '" "double""'");
+    } 
+    arg4 = static_cast< double >(val4);
+  }
+  if (obj4) {
+    ecode5 = SWIG_AsVal_double(obj4, &val5);
+    if (!SWIG_IsOK(ecode5)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "ApplyVerticalShiftGrid" "', argument " "5"" of type '" "double""'");
+    } 
+    arg5 = static_cast< double >(val5);
+  }
+  if (obj5) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj5) || PyUnicode_Check(obj5)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj5)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      Py_ssize_t size = PySequence_Size(obj5);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj5,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg6 = CSLAddString( arg6, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg6 = CSLAddString( arg6, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg6 = CSLAddString( arg6, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)ApplyVerticalShiftGrid(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg6 );
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg6 );
+  }
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_ApplyGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   double *arg1 ;
@@ -24481,7 +26479,11 @@ SWIGINTERN PyObject *_wrap_ApplyGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALApplyGeoTransform(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALApplyGeoTransform(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24554,7 +26556,11 @@ SWIGINTERN PyObject *_wrap_InvGeoTransform(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (RETURN_NONE)GDALInvGeoTransform(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (RETURN_NONE)GDALInvGeoTransform(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24610,7 +26616,11 @@ SWIGINTERN PyObject *_wrap_VersionInfo(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALVersionInfo((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALVersionInfo((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24638,7 +26648,11 @@ SWIGINTERN PyObject *_wrap_AllRegister(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALAllRegister();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALAllRegister();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24664,7 +26678,11 @@ SWIGINTERN PyObject *_wrap_GDALDestroyDriverManager(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALDestroyDriverManager();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALDestroyDriverManager();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24691,7 +26709,11 @@ SWIGINTERN PyObject *_wrap_GetCacheMax(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = wrapper_GDALGetCacheMax();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = wrapper_GDALGetCacheMax();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24726,7 +26748,11 @@ SWIGINTERN PyObject *_wrap_GetCacheUsed(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = wrapper_GDALGetCacheUsed();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = wrapper_GDALGetCacheUsed();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24770,7 +26796,11 @@ SWIGINTERN PyObject *_wrap_SetCacheMax(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    wrapper_GDALSetCacheMax(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      wrapper_GDALSetCacheMax(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24806,7 +26836,11 @@ SWIGINTERN PyObject *_wrap_GetDataTypeSize(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALGetDataTypeSize(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALGetDataTypeSize(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24842,7 +26876,11 @@ SWIGINTERN PyObject *_wrap_DataTypeIsComplex(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GDALDataTypeIsComplex(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GDALDataTypeIsComplex(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24878,7 +26916,11 @@ SWIGINTERN PyObject *_wrap_GetDataTypeName(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALGetDataTypeName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALGetDataTypeName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24915,7 +26957,11 @@ SWIGINTERN PyObject *_wrap_GetDataTypeByName(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDataType)GDALGetDataTypeByName((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDataType)GDALGetDataTypeByName((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24953,7 +26999,11 @@ SWIGINTERN PyObject *_wrap_GetColorInterpretationName(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALGetColorInterpretationName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALGetColorInterpretationName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24989,7 +27039,11 @@ SWIGINTERN PyObject *_wrap_GetPaletteInterpretationName(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALGetPaletteInterpretationName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALGetPaletteInterpretationName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25046,7 +27100,11 @@ SWIGINTERN PyObject *_wrap_DecToDMS(PyObject *SWIGUNUSEDPARM(self), PyObject *ar
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALDecToDMS(arg1,(char const *)arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALDecToDMS(arg1,(char const *)arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25084,7 +27142,11 @@ SWIGINTERN PyObject *_wrap_PackedDMSToDec(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDALPackedDMSToDec(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDALPackedDMSToDec(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25120,7 +27182,11 @@ SWIGINTERN PyObject *_wrap_DecToPackedDMS(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)GDALDecToPackedDMS(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)GDALDecToPackedDMS(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25157,7 +27223,11 @@ SWIGINTERN PyObject *_wrap_ParseXMLString(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLXMLNode *)CPLParseXMLString(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLXMLNode *)CPLParseXMLString(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25220,7 +27290,11 @@ SWIGINTERN PyObject *_wrap_SerializeXMLTree(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)CPLSerializeXMLTree(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)CPLSerializeXMLTree(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25329,7 +27403,11 @@ SWIGINTERN PyObject *_wrap_GetJPEG2000Structure(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLXMLNode *)GDALGetJPEG2000Structure((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLXMLNode *)GDALGetJPEG2000Structure((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25460,7 +27538,11 @@ SWIGINTERN PyObject *_wrap_GetJPEG2000StructureAsString(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)GetJPEG2000StructureAsString((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)GetJPEG2000StructureAsString((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25504,7 +27586,11 @@ SWIGINTERN PyObject *_wrap_GetDriverCount(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GetDriverCount();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GetDriverCount();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25546,7 +27632,11 @@ SWIGINTERN PyObject *_wrap_GetDriverByName(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDriverShadow *)GetDriverByName((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDriverShadow *)GetDriverByName((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25584,7 +27674,11 @@ SWIGINTERN PyObject *_wrap_GetDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDriverShadow *)GetDriver(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDriverShadow *)GetDriver(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25639,7 +27733,11 @@ SWIGINTERN PyObject *_wrap_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)Open((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)Open((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25861,7 +27959,11 @@ SWIGINTERN PyObject *_wrap_OpenEx(PyObject *SWIGUNUSEDPARM(self), PyObject *args
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)OpenEx((char const *)arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)OpenEx((char const *)arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25932,13 +28034,121 @@ SWIGINTERN PyObject *_wrap_OpenShared(PyObject *SWIGUNUSEDPARM(self), PyObject *
       SWIG_fail;
     }
   }
-  if (obj1) {
-    ecode2 = SWIG_AsVal_int(obj1, &val2);
-    if (!SWIG_IsOK(ecode2)) {
-      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "OpenShared" "', argument " "2"" of type '" "GDALAccess""'");
-    } 
-    arg2 = static_cast< GDALAccess >(val2);
-  }
+  if (obj1) {
+    ecode2 = SWIG_AsVal_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "OpenShared" "', argument " "2"" of type '" "GDALAccess""'");
+    } 
+    arg2 = static_cast< GDALAccess >(val2);
+  }
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)OpenShared((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  {
+    /* %typemap(freearg) (const char *utf8_path) */
+    GDALPythonFreeCStr(arg1, bToFree1);
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  char **arg2 = (char **) NULL ;
+  int bToFree1 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  GDALDriverShadow *result = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O|O:IdentifyDriver",&obj0,&obj1)) SWIG_fail;
+  {
+    /* %typemap(in) (const char *utf8_path) */
+    arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
+    if (arg1 == NULL)
+    {
+      PyErr_SetString( PyExc_RuntimeError, "not a string" );
+      SWIG_fail;
+    }
+  }
+  if (obj1) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj1) || PyUnicode_Check(obj1)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj1)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      Py_ssize_t size = PySequence_Size(obj1);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj1,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg2 = CSLAddString( arg2, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg2 = CSLAddString( arg2, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
   {
     if (!arg1) {
       SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
@@ -25948,7 +28158,11 @@ SWIGINTERN PyObject *_wrap_OpenShared(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)OpenShared((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDriverShadow *)IdentifyDriver((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25958,11 +28172,15 @@ SWIGINTERN PyObject *_wrap_OpenShared(PyObject *SWIGUNUSEDPARM(self), PyObject *
     }
 #endif
   }
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDatasetShadow, SWIG_POINTER_OWN |  0 );
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_GDALDriverShadow, 0 |  0 );
   {
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
@@ -25970,20 +28188,33 @@ fail:
     /* %typemap(freearg) (const char *utf8_path) */
     GDALPythonFreeCStr(arg1, bToFree1);
   }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg2 );
+  }
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_IdentifyDriverEx(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   char *arg1 = (char *) 0 ;
-  char **arg2 = (char **) NULL ;
+  unsigned int arg2 = (unsigned int) 0 ;
+  char **arg3 = (char **) NULL ;
+  char **arg4 = (char **) NULL ;
   int bToFree1 = 0 ;
+  unsigned int val2 ;
+  int ecode2 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
+  PyObject * obj2 = 0 ;
+  PyObject * obj3 = 0 ;
+  char *  kwnames[] = {
+    (char *) "utf8_path",(char *) "nIdentifyFlags",(char *) "allowed_drivers",(char *) "sibling_files", NULL 
+  };
   GDALDriverShadow *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"O|O:IdentifyDriver",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|OOO:IdentifyDriverEx",kwnames,&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
   {
     /* %typemap(in) (const char *utf8_path) */
     arg1 = GDALPythonObjectToCStr( obj0, &bToFree1 );
@@ -25994,25 +28225,32 @@ SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObje
     }
   }
   if (obj1) {
+    ecode2 = SWIG_AsVal_unsigned_SS_int(obj1, &val2);
+    if (!SWIG_IsOK(ecode2)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "IdentifyDriverEx" "', argument " "2"" of type '" "unsigned int""'");
+    } 
+    arg2 = static_cast< unsigned int >(val2);
+  }
+  if (obj2) {
     {
       /* %typemap(in) char **options */
       /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
-      if ( ! PySequence_Check(obj1) || PyUnicode_Check(obj1)
+      if ( ! PySequence_Check(obj2) || PyUnicode_Check(obj2)
   #if PY_VERSION_HEX < 0x03000000
-        || PyString_Check(obj1)
+        || PyString_Check(obj2)
   #endif
         ) {
         PyErr_SetString(PyExc_TypeError,"not a sequence");
         SWIG_fail;
       }
       
-      Py_ssize_t size = PySequence_Size(obj1);
+      Py_ssize_t size = PySequence_Size(obj2);
       if( size != (int)size ) {
         PyErr_SetString(PyExc_TypeError, "too big sequence");
         SWIG_fail;
       }
       for (int i = 0; i < (int)size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj1,i);
+        PyObject* pyObj = PySequence_GetItem(obj2,i);
         if (PyUnicode_Check(pyObj))
         {
           char *pszStr;
@@ -26023,15 +28261,65 @@ SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObje
 #else
           PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
 #endif
-          arg2 = CSLAddString( arg2, pszStr );
+          arg3 = CSLAddString( arg3, pszStr );
           Py_XDECREF(pyUTF8Str);
         }
 #if PY_VERSION_HEX >= 0x03000000
         else if (PyBytes_Check(pyObj))
-        arg2 = CSLAddString( arg2, PyBytes_AsString(pyObj) );
+        arg3 = CSLAddString( arg3, PyBytes_AsString(pyObj) );
 #else
         else if (PyString_Check(pyObj))
-        arg2 = CSLAddString( arg2, PyString_AsString(pyObj) );
+        arg3 = CSLAddString( arg3, PyString_AsString(pyObj) );
+#endif
+        else
+        {
+          Py_DECREF(pyObj);
+          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
+          SWIG_fail;
+        }
+        Py_DECREF(pyObj);
+      }
+    }
+  }
+  if (obj3) {
+    {
+      /* %typemap(in) char **options */
+      /* Check if is a list (and reject strings, that are seen as sequence of characters)  */
+      if ( ! PySequence_Check(obj3) || PyUnicode_Check(obj3)
+  #if PY_VERSION_HEX < 0x03000000
+        || PyString_Check(obj3)
+  #endif
+        ) {
+        PyErr_SetString(PyExc_TypeError,"not a sequence");
+        SWIG_fail;
+      }
+      
+      Py_ssize_t size = PySequence_Size(obj3);
+      if( size != (int)size ) {
+        PyErr_SetString(PyExc_TypeError, "too big sequence");
+        SWIG_fail;
+      }
+      for (int i = 0; i < (int)size; i++) {
+        PyObject* pyObj = PySequence_GetItem(obj3,i);
+        if (PyUnicode_Check(pyObj))
+        {
+          char *pszStr;
+          Py_ssize_t nLen;
+          PyObject* pyUTF8Str = PyUnicode_AsUTF8String(pyObj);
+#if PY_VERSION_HEX >= 0x03000000
+          PyBytes_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#else
+          PyString_AsStringAndSize(pyUTF8Str, &pszStr, &nLen);
+#endif
+          arg4 = CSLAddString( arg4, pszStr );
+          Py_XDECREF(pyUTF8Str);
+        }
+#if PY_VERSION_HEX >= 0x03000000
+        else if (PyBytes_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyBytes_AsString(pyObj) );
+#else
+        else if (PyString_Check(pyObj))
+        arg4 = CSLAddString( arg4, PyString_AsString(pyObj) );
 #endif
         else
         {
@@ -26052,7 +28340,11 @@ SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDriverShadow *)IdentifyDriver((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDriverShadow *)IdentifyDriverEx((char const *)arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26069,7 +28361,11 @@ SWIGINTERN PyObject *_wrap_IdentifyDriver(PyObject *SWIGUNUSEDPARM(self), PyObje
   }
   {
     /* %typemap(freearg) char **options */
-    CSLDestroy( arg2 );
+    CSLDestroy( arg3 );
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
@@ -26080,7 +28376,11 @@ fail:
   }
   {
     /* %typemap(freearg) char **options */
-    CSLDestroy( arg2 );
+    CSLDestroy( arg3 );
+  }
+  {
+    /* %typemap(freearg) char **options */
+    CSLDestroy( arg4 );
   }
   return NULL;
 }
@@ -26156,7 +28456,11 @@ SWIGINTERN PyObject *_wrap_GeneralCmdLineProcessor(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GeneralCmdLineProcessor(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GeneralCmdLineProcessor(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26257,7 +28561,11 @@ SWIGINTERN PyObject *_wrap_new_GDALInfoOptions(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALInfoOptions *)new_GDALInfoOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALInfoOptions *)new_GDALInfoOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26300,7 +28608,11 @@ SWIGINTERN PyObject *_wrap_delete_GDALInfoOptions(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALInfoOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALInfoOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26352,7 +28664,11 @@ SWIGINTERN PyObject *_wrap_InfoInternal(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)GDALInfo(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)GDALInfo(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26436,7 +28752,11 @@ SWIGINTERN PyObject *_wrap_new_GDALTranslateOptions(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALTranslateOptions *)new_GDALTranslateOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALTranslateOptions *)new_GDALTranslateOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26479,7 +28799,11 @@ SWIGINTERN PyObject *_wrap_delete_GDALTranslateOptions(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALTranslateOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALTranslateOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26597,7 +28921,11 @@ SWIGINTERN PyObject *_wrap_TranslateInternal(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)wrapper_GDALTranslate((char const *)arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)wrapper_GDALTranslate((char const *)arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26694,7 +29022,11 @@ SWIGINTERN PyObject *_wrap_new_GDALWarpAppOptions(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALWarpAppOptions *)new_GDALWarpAppOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALWarpAppOptions *)new_GDALWarpAppOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26737,7 +29069,11 @@ SWIGINTERN PyObject *_wrap_delete_GDALWarpAppOptions(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALWarpAppOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALWarpAppOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26810,7 +29146,7 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALWarpDestDS(PyObject *SWIGUNUSEDPARM(self)
     
     for( int i = 0; i<arg2; i++ ) {
       PyObject *o = PySequence_GetItem(obj1,i);
-#if 0x020012 <= 0x010337
+#if 0x030008 <= 0x010337
       PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
 #else
       SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
@@ -26868,7 +29204,11 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALWarpDestDS(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)wrapper_GDALWarpDestDS(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)wrapper_GDALWarpDestDS(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26957,7 +29297,7 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALWarpDestName(PyObject *SWIGUNUSEDPARM(sel
     
     for( int i = 0; i<arg2; i++ ) {
       PyObject *o = PySequence_GetItem(obj1,i);
-#if 0x020012 <= 0x010337
+#if 0x030008 <= 0x010337
       PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
 #else
       SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
@@ -27020,7 +29360,11 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALWarpDestName(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)wrapper_GDALWarpDestName((char const *)arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)wrapper_GDALWarpDestName((char const *)arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27125,7 +29469,11 @@ SWIGINTERN PyObject *_wrap_new_GDALVectorTranslateOptions(PyObject *SWIGUNUSEDPA
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALVectorTranslateOptions *)new_GDALVectorTranslateOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALVectorTranslateOptions *)new_GDALVectorTranslateOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27168,7 +29516,11 @@ SWIGINTERN PyObject *_wrap_delete_GDALVectorTranslateOptions(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALVectorTranslateOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALVectorTranslateOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27273,7 +29625,11 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALVectorTranslateDestDS(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)wrapper_GDALVectorTranslateDestDS(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)wrapper_GDALVectorTranslateDestDS(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27391,7 +29747,11 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALVectorTranslateDestName(PyObject *SWIGUNU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)wrapper_GDALVectorTranslateDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)wrapper_GDALVectorTranslateDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27488,7 +29848,11 @@ SWIGINTERN PyObject *_wrap_new_GDALDEMProcessingOptions(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDEMProcessingOptions *)new_GDALDEMProcessingOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDEMProcessingOptions *)new_GDALDEMProcessingOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27531,7 +29895,11 @@ SWIGINTERN PyObject *_wrap_delete_GDALDEMProcessingOptions(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALDEMProcessingOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALDEMProcessingOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27674,7 +30042,11 @@ SWIGINTERN PyObject *_wrap_DEMProcessingInternal(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)wrapper_GDALDEMProcessing((char const *)arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)wrapper_GDALDEMProcessing((char const *)arg1,arg2,(char const *)arg3,(char const *)arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27775,7 +30147,11 @@ SWIGINTERN PyObject *_wrap_new_GDALNearblackOptions(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALNearblackOptions *)new_GDALNearblackOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALNearblackOptions *)new_GDALNearblackOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27818,7 +30194,11 @@ SWIGINTERN PyObject *_wrap_delete_GDALNearblackOptions(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALNearblackOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALNearblackOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -27923,7 +30303,11 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALNearblackDestDS(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)wrapper_GDALNearblackDestDS(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)wrapper_GDALNearblackDestDS(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28041,7 +30425,11 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALNearblackDestName(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)wrapper_GDALNearblackDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)wrapper_GDALNearblackDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28138,7 +30526,11 @@ SWIGINTERN PyObject *_wrap_new_GDALGridOptions(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALGridOptions *)new_GDALGridOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALGridOptions *)new_GDALGridOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28181,7 +30573,11 @@ SWIGINTERN PyObject *_wrap_delete_GDALGridOptions(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALGridOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALGridOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28299,7 +30695,11 @@ SWIGINTERN PyObject *_wrap_GridInternal(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)wrapper_GDALGrid((char const *)arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)wrapper_GDALGrid((char const *)arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28396,7 +30796,11 @@ SWIGINTERN PyObject *_wrap_new_GDALRasterizeOptions(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALRasterizeOptions *)new_GDALRasterizeOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALRasterizeOptions *)new_GDALRasterizeOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28439,7 +30843,11 @@ SWIGINTERN PyObject *_wrap_delete_GDALRasterizeOptions(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALRasterizeOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALRasterizeOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28544,7 +30952,11 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALRasterizeDestDS(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)wrapper_GDALRasterizeDestDS(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)wrapper_GDALRasterizeDestDS(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28662,7 +31074,11 @@ SWIGINTERN PyObject *_wrap_wrapper_GDALRasterizeDestName(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)wrapper_GDALRasterizeDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)wrapper_GDALRasterizeDestName((char const *)arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28759,7 +31175,11 @@ SWIGINTERN PyObject *_wrap_new_GDALBuildVRTOptions(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALBuildVRTOptions *)new_GDALBuildVRTOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALBuildVRTOptions *)new_GDALBuildVRTOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28802,7 +31222,11 @@ SWIGINTERN PyObject *_wrap_delete_GDALBuildVRTOptions(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GDALBuildVRTOptions(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GDALBuildVRTOptions(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -28878,7 +31302,7 @@ SWIGINTERN PyObject *_wrap_BuildVRTInternalObjects(PyObject *SWIGUNUSEDPARM(self
     
     for( int i = 0; i<arg2; i++ ) {
       PyObject *o = PySequence_GetItem(obj1,i);
-#if 0x020012 <= 0x010337
+#if 0x030008 <= 0x010337
       PySwigObject *sobj = SWIG_Python_GetSwigThis(o);
 #else
       SwigPyObject *sobj = SWIG_Python_GetSwigThis(o);
@@ -28941,7 +31365,11 @@ SWIGINTERN PyObject *_wrap_BuildVRTInternalObjects(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)wrapper_GDALBuildVRT_objects((char const *)arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)wrapper_GDALBuildVRT_objects((char const *)arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -29116,7 +31544,11 @@ SWIGINTERN PyObject *_wrap_BuildVRTInternalNames(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GDALDatasetShadow *)wrapper_GDALBuildVRT_names((char const *)arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GDALDatasetShadow *)wrapper_GDALBuildVRT_names((char const *)arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -29167,17 +31599,17 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GetUseExceptions", _wrap_GetUseExceptions, METH_VARARGS, (char *)"GetUseExceptions() -> int"},
 	 { (char *)"UseExceptions", _wrap_UseExceptions, METH_VARARGS, (char *)"UseExceptions()"},
 	 { (char *)"DontUseExceptions", _wrap_DontUseExceptions, METH_VARARGS, (char *)"DontUseExceptions()"},
-	 { (char *)"VSIFReadL", _wrap_VSIFReadL, METH_VARARGS, (char *)"VSIFReadL(int nMembSize, int nMembCount, VSILFILE * fp) -> int"},
+	 { (char *)"VSIFReadL", _wrap_VSIFReadL, METH_VARARGS, (char *)"VSIFReadL(unsigned int nMembSize, unsigned int nMembCount, VSILFILE * fp) -> unsigned int"},
 	 { (char *)"Debug", _wrap_Debug, METH_VARARGS, (char *)"Debug(char const * msg_class, char const * message)"},
 	 { (char *)"SetErrorHandler", _wrap_SetErrorHandler, METH_VARARGS, (char *)"SetErrorHandler(char const * pszCallbackName=None) -> CPLErr"},
 	 { (char *)"PushErrorHandler", _wrap_PushErrorHandler, METH_VARARGS, (char *)"PushErrorHandler(CPLErrorHandler pfnErrorHandler=0) -> CPLErr"},
 	 { (char *)"PopErrorHandler", _wrap_PopErrorHandler, METH_VARARGS, (char *)"PopErrorHandler()"},
-	 { (char *)"Error", _wrap_Error, METH_VARARGS, (char *)"Error(CPLErr msg_class=CE_Failure, int err_code=0, char const * msg=\"error\")"},
+	 { (char *)"Error", _wrap_Error, METH_VARARGS, (char *)"Error(CPLErr msg_class, int err_code=0, char const * msg)"},
 	 { (char *)"GOA2GetAuthorizationURL", _wrap_GOA2GetAuthorizationURL, METH_VARARGS, (char *)"GOA2GetAuthorizationURL(char const * pszScope) -> retStringAndCPLFree *"},
 	 { (char *)"GOA2GetRefreshToken", _wrap_GOA2GetRefreshToken, METH_VARARGS, (char *)"GOA2GetRefreshToken(char const * pszAuthToken, char const * pszScope) -> retStringAndCPLFree *"},
 	 { (char *)"GOA2GetAccessToken", _wrap_GOA2GetAccessToken, METH_VARARGS, (char *)"GOA2GetAccessToken(char const * pszRefreshToken, char const * pszScope) -> retStringAndCPLFree *"},
 	 { (char *)"ErrorReset", _wrap_ErrorReset, METH_VARARGS, (char *)"ErrorReset()"},
-	 { (char *)"EscapeString", (PyCFunction) _wrap_EscapeString, METH_VARARGS | METH_KEYWORDS, (char *)"EscapeString(int len, int scheme=CPLES_SQL) -> retStringAndCPLFree *"},
+	 { (char *)"EscapeString", (PyCFunction) _wrap_EscapeString, METH_VARARGS | METH_KEYWORDS, (char *)"EscapeString(int len, int scheme) -> retStringAndCPLFree *"},
 	 { (char *)"GetLastErrorNo", _wrap_GetLastErrorNo, METH_VARARGS, (char *)"GetLastErrorNo() -> int"},
 	 { (char *)"GetLastErrorType", _wrap_GetLastErrorType, METH_VARARGS, (char *)"GetLastErrorType() -> int"},
 	 { (char *)"GetLastErrorMsg", _wrap_GetLastErrorMsg, METH_VARARGS, (char *)"GetLastErrorMsg() -> char const *"},
@@ -29193,12 +31625,15 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GetConfigOption", _wrap_GetConfigOption, METH_VARARGS, (char *)"GetConfigOption(char const * pszKey, char const * pszDefault=None) -> char const *"},
 	 { (char *)"CPLBinaryToHex", _wrap_CPLBinaryToHex, METH_VARARGS, (char *)"CPLBinaryToHex(int nBytes) -> retStringAndCPLFree *"},
 	 { (char *)"CPLHexToBinary", _wrap_CPLHexToBinary, METH_VARARGS, (char *)"CPLHexToBinary(char const * pszHex, int * pnBytes) -> GByte *"},
-	 { (char *)"FileFromMemBuffer", _wrap_FileFromMemBuffer, METH_VARARGS, (char *)"FileFromMemBuffer(char const * utf8_path, int nBytes)"},
+	 { (char *)"FileFromMemBuffer", _wrap_FileFromMemBuffer, METH_VARARGS, (char *)"FileFromMemBuffer(char const * utf8_path, GIntBig nBytes)"},
 	 { (char *)"Unlink", _wrap_Unlink, METH_VARARGS, (char *)"Unlink(char const * utf8_path) -> VSI_RETVAL"},
 	 { (char *)"HasThreadSupport", _wrap_HasThreadSupport, METH_VARARGS, (char *)"HasThreadSupport() -> int"},
 	 { (char *)"Mkdir", _wrap_Mkdir, METH_VARARGS, (char *)"Mkdir(char const * utf8_path, int mode) -> VSI_RETVAL"},
 	 { (char *)"Rmdir", _wrap_Rmdir, METH_VARARGS, (char *)"Rmdir(char const * utf8_path) -> VSI_RETVAL"},
 	 { (char *)"Rename", _wrap_Rename, METH_VARARGS, (char *)"Rename(char const * pszOld, char const * pszNew) -> VSI_RETVAL"},
+	 { (char *)"VSI_STAT_EXISTS_FLAG_swigconstant", VSI_STAT_EXISTS_FLAG_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"VSI_STAT_NATURE_FLAG_swigconstant", VSI_STAT_NATURE_FLAG_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"VSI_STAT_SIZE_FLAG_swigconstant", VSI_STAT_SIZE_FLAG_swigconstant, METH_VARARGS, NULL},
 	 { (char *)"StatBuf_mode_get", _wrap_StatBuf_mode_get, METH_VARARGS, (char *)"StatBuf_mode_get(StatBuf self) -> int"},
 	 { (char *)"StatBuf_size_get", _wrap_StatBuf_size_get, METH_VARARGS, (char *)"StatBuf_size_get(StatBuf self) -> GIntBig"},
 	 { (char *)"StatBuf_mtime_get", _wrap_StatBuf_mtime_get, METH_VARARGS, (char *)"StatBuf_mtime_get(StatBuf self) -> GIntBig"},
@@ -29213,31 +31648,30 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"VSIFSeekL", _wrap_VSIFSeekL, METH_VARARGS, (char *)"VSIFSeekL(VSILFILE * fp, GIntBig offset, int whence) -> int"},
 	 { (char *)"VSIFTellL", _wrap_VSIFTellL, METH_VARARGS, (char *)"VSIFTellL(VSILFILE * fp) -> GIntBig"},
 	 { (char *)"VSIFTruncateL", _wrap_VSIFTruncateL, METH_VARARGS, (char *)"VSIFTruncateL(VSILFILE * fp, GIntBig length) -> int"},
+	 { (char *)"VSISupportsSparseFiles", _wrap_VSISupportsSparseFiles, METH_VARARGS, (char *)"VSISupportsSparseFiles(char const * utf8_path) -> int"},
+	 { (char *)"VSI_RANGE_STATUS_UNKNOWN_swigconstant", VSI_RANGE_STATUS_UNKNOWN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"VSI_RANGE_STATUS_DATA_swigconstant", VSI_RANGE_STATUS_DATA_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"VSI_RANGE_STATUS_HOLE_swigconstant", VSI_RANGE_STATUS_HOLE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"VSIFGetRangeStatusL", _wrap_VSIFGetRangeStatusL, METH_VARARGS, (char *)"VSIFGetRangeStatusL(VSILFILE * fp, GIntBig offset, GIntBig length) -> int"},
 	 { (char *)"VSIFWriteL", _wrap_VSIFWriteL, METH_VARARGS, (char *)"VSIFWriteL(int nLen, int size, int memb, VSILFILE * fp) -> int"},
 	 { (char *)"ParseCommandLine", _wrap_ParseCommandLine, METH_VARARGS, (char *)"ParseCommandLine(char const * utf8_path) -> char **"},
 	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, (char *)"MajorObject_GetDescription(MajorObject self) -> char const *"},
 	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, (char *)"MajorObject_SetDescription(MajorObject self, char const * pszNewDesc)"},
 	 { (char *)"MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList, METH_VARARGS, (char *)"MajorObject_GetMetadataDomainList(MajorObject self) -> char **"},
-	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char const * pszDomain=\"\") -> char **"},
-	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, (char *)"MajorObject_GetMetadata_List(MajorObject self, char const * pszDomain=\"\") -> char **"},
+	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char const * pszDomain) -> char **"},
+	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, (char *)"MajorObject_GetMetadata_List(MajorObject self, char const * pszDomain) -> char **"},
 	 { (char *)"MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata, METH_VARARGS, (char *)"\n"
-		"SetMetadata(char ** papszMetadata, char const * pszDomain=\"\") -> CPLErr\n"
-		"MajorObject_SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain=\"\") -> CPLErr\n"
+		"SetMetadata(char ** papszMetadata, char const * pszDomain) -> CPLErr\n"
+		"MajorObject_SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain) -> CPLErr\n"
 		""},
-	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, (char *)"MajorObject_GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain=\"\") -> char const *"},
-	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, (char *)"MajorObject_SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain=\"\") -> CPLErr"},
+	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, (char *)"MajorObject_GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain) -> char const *"},
+	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, (char *)"MajorObject_SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain) -> CPLErr"},
 	 { (char *)"MajorObject_swigregister", MajorObject_swigregister, METH_VARARGS, NULL},
 	 { (char *)"Driver_ShortName_get", _wrap_Driver_ShortName_get, METH_VARARGS, (char *)"Driver_ShortName_get(Driver self) -> char const *"},
 	 { (char *)"Driver_LongName_get", _wrap_Driver_LongName_get, METH_VARARGS, (char *)"Driver_LongName_get(Driver self) -> char const *"},
 	 { (char *)"Driver_HelpTopic_get", _wrap_Driver_HelpTopic_get, METH_VARARGS, (char *)"Driver_HelpTopic_get(Driver self) -> char const *"},
-	 { (char *)"Driver_Create", (PyCFunction) _wrap_Driver_Create, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Driver_Create(Driver self, char const * utf8_path, int xsize, int ysize, int bands=1, GDALDataType eType=GDT_Byte, \n"
-		"    char ** options=None) -> Dataset\n"
-		""},
-	 { (char *)"Driver_CreateCopy", (PyCFunction) _wrap_Driver_CreateCopy, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Driver_CreateCopy(Driver self, char const * utf8_path, Dataset src, int strict=1, char ** options=None, \n"
-		"    GDALProgressFunc callback=0, void * callback_data=None) -> Dataset\n"
-		""},
+	 { (char *)"Driver_Create", (PyCFunction) _wrap_Driver_Create, METH_VARARGS | METH_KEYWORDS, (char *)"Driver_Create(Driver self, char const * utf8_path, int xsize, int ysize, int bands=1, GDALDataType eType, char ** options=None) -> Dataset"},
+	 { (char *)"Driver_CreateCopy", (PyCFunction) _wrap_Driver_CreateCopy, METH_VARARGS | METH_KEYWORDS, (char *)"Driver_CreateCopy(Driver self, char const * utf8_path, Dataset src, int strict=1, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
 	 { (char *)"Driver_Delete", _wrap_Driver_Delete, METH_VARARGS, (char *)"Driver_Delete(Driver self, char const * utf8_path) -> CPLErr"},
 	 { (char *)"Driver_Rename", _wrap_Driver_Rename, METH_VARARGS, (char *)"Driver_Rename(Driver self, char const * newName, char const * oldName) -> CPLErr"},
 	 { (char *)"Driver_CopyFiles", _wrap_Driver_CopyFiles, METH_VARARGS, (char *)"Driver_CopyFiles(Driver self, char const * newName, char const * oldName) -> CPLErr"},
@@ -29267,10 +31701,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GCP_Info_get", _wrap_GCP_Info_get, METH_VARARGS, (char *)"GCP_Info_get(GCP self) -> char *"},
 	 { (char *)"GCP_Id_set", _wrap_GCP_Id_set, METH_VARARGS, (char *)"GCP_Id_set(GCP self, char * Id)"},
 	 { (char *)"GCP_Id_get", _wrap_GCP_Id_get, METH_VARARGS, (char *)"GCP_Id_get(GCP self) -> char *"},
-	 { (char *)"new_GCP", _wrap_new_GCP, METH_VARARGS, (char *)"\n"
-		"new_GCP(double x=0.0, double y=0.0, double z=0.0, double pixel=0.0, double line=0.0, char const * info=\"\", \n"
-		"    char const * id=\"\") -> GCP\n"
-		""},
+	 { (char *)"new_GCP", _wrap_new_GCP, METH_VARARGS, (char *)"new_GCP(double x=0.0, double y=0.0, double z=0.0, double pixel=0.0, double line=0.0, char const * info, char const * id) -> GCP"},
 	 { (char *)"delete_GCP", _wrap_delete_GCP, METH_VARARGS, (char *)"delete_GCP(GCP self)"},
 	 { (char *)"GCP_swigregister", GCP_swigregister, METH_VARARGS, NULL},
 	 { (char *)"GDAL_GCP_GCPX_get", _wrap_GDAL_GCP_GCPX_get, METH_VARARGS, (char *)"GDAL_GCP_GCPX_get(GCP gcp) -> double"},
@@ -29309,63 +31740,37 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Dataset_SetProjection", _wrap_Dataset_SetProjection, METH_VARARGS, (char *)"Dataset_SetProjection(Dataset self, char const * prj) -> CPLErr"},
 	 { (char *)"Dataset_GetGeoTransform", (PyCFunction) _wrap_Dataset_GetGeoTransform, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_GetGeoTransform(Dataset self, int * can_return_null=None)"},
 	 { (char *)"Dataset_SetGeoTransform", _wrap_Dataset_SetGeoTransform, METH_VARARGS, (char *)"Dataset_SetGeoTransform(Dataset self, double [6] argin) -> CPLErr"},
-	 { (char *)"Dataset_BuildOverviews", (PyCFunction) _wrap_Dataset_BuildOverviews, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_BuildOverviews(Dataset self, char const * resampling=\"NEAREST\", int overviewlist=0, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
+	 { (char *)"Dataset_BuildOverviews", (PyCFunction) _wrap_Dataset_BuildOverviews, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_BuildOverviews(Dataset self, char const * resampling, int overviewlist=0, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
 	 { (char *)"Dataset_GetGCPCount", _wrap_Dataset_GetGCPCount, METH_VARARGS, (char *)"Dataset_GetGCPCount(Dataset self) -> int"},
 	 { (char *)"Dataset_GetGCPProjection", _wrap_Dataset_GetGCPProjection, METH_VARARGS, (char *)"Dataset_GetGCPProjection(Dataset self) -> char const *"},
 	 { (char *)"Dataset_GetGCPs", _wrap_Dataset_GetGCPs, METH_VARARGS, (char *)"Dataset_GetGCPs(Dataset self)"},
 	 { (char *)"Dataset_SetGCPs", _wrap_Dataset_SetGCPs, METH_VARARGS, (char *)"Dataset_SetGCPs(Dataset self, int nGCPs, char const * pszGCPProjection) -> CPLErr"},
 	 { (char *)"Dataset_FlushCache", _wrap_Dataset_FlushCache, METH_VARARGS, (char *)"Dataset_FlushCache(Dataset self)"},
-	 { (char *)"Dataset_AddBand", (PyCFunction) _wrap_Dataset_AddBand, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_AddBand(Dataset self, GDALDataType datatype=GDT_Byte, char ** options=None) -> CPLErr"},
+	 { (char *)"Dataset_AddBand", (PyCFunction) _wrap_Dataset_AddBand, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_AddBand(Dataset self, GDALDataType datatype, char ** options=None) -> CPLErr"},
 	 { (char *)"Dataset_CreateMaskBand", _wrap_Dataset_CreateMaskBand, METH_VARARGS, (char *)"Dataset_CreateMaskBand(Dataset self, int nFlags) -> CPLErr"},
 	 { (char *)"Dataset_GetFileList", _wrap_Dataset_GetFileList, METH_VARARGS, (char *)"Dataset_GetFileList(Dataset self) -> char **"},
-	 { (char *)"Dataset_WriteRaster", (PyCFunction) _wrap_Dataset_WriteRaster, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_WriteRaster(Dataset self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, \n"
-		"    int * buf_ysize=None, GDALDataType * buf_type=None, int band_list=0, \n"
-		"    GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None, GIntBig * buf_band_space=None) -> CPLErr\n"
-		""},
-	 { (char *)"Dataset_BeginAsyncReader", (PyCFunction) _wrap_Dataset_BeginAsyncReader, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_BeginAsyncReader(Dataset self, int xOff, int yOff, int xSize, int ySize, int buf_len, int buf_xsize, \n"
-		"    int buf_ysize, GDALDataType bufType=(GDALDataType) 0, int band_list=0, int nPixelSpace=0, \n"
-		"    int nLineSpace=0, int nBandSpace=0, char ** options=None) -> AsyncReader\n"
-		""},
+	 { (char *)"Dataset_WriteRaster", (PyCFunction) _wrap_Dataset_WriteRaster, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_WriteRaster(Dataset self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, int * buf_ysize=None, GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None, GIntBig * buf_band_space=None) -> CPLErr"},
+	 { (char *)"Dataset_BeginAsyncReader", (PyCFunction) _wrap_Dataset_BeginAsyncReader, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_BeginAsyncReader(Dataset self, int xOff, int yOff, int xSize, int ySize, int buf_len, int buf_xsize, int buf_ysize, GDALDataType bufType, int band_list=0, int nPixelSpace=0, int nLineSpace=0, int nBandSpace=0, char ** options=None) -> AsyncReader"},
 	 { (char *)"Dataset_EndAsyncReader", _wrap_Dataset_EndAsyncReader, METH_VARARGS, (char *)"Dataset_EndAsyncReader(Dataset self, AsyncReader ario)"},
-	 { (char *)"Dataset_GetVirtualMem", (PyCFunction) _wrap_Dataset_GetVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_GetVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, \n"
-		"    int nBufYSize, GDALDataType eBufType, int band_list, int bIsBandSequential, \n"
-		"    size_t nCacheSize, size_t nPageSizeHint, char ** options=None) -> VirtualMem\n"
-		""},
-	 { (char *)"Dataset_GetTiledVirtualMem", (PyCFunction) _wrap_Dataset_GetTiledVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_GetTiledVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, \n"
-		"    int nTileYSize, GDALDataType eBufType, int band_list, GDALTileOrganization eTileOrganization, \n"
-		"    size_t nCacheSize, char ** options=None) -> VirtualMem\n"
-		""},
-	 { (char *)"Dataset_CreateLayer", (PyCFunction) _wrap_Dataset_CreateLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_CreateLayer(Dataset self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type=wkbUnknown, \n"
-		"    char ** options=None) -> Layer\n"
-		""},
+	 { (char *)"Dataset_GetVirtualMem", (PyCFunction) _wrap_Dataset_GetVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_GetVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize, GDALDataType eBufType, int band_list, int bIsBandSequential, size_t nCacheSize, size_t nPageSizeHint, char ** options=None) -> VirtualMem"},
+	 { (char *)"Dataset_GetTiledVirtualMem", (PyCFunction) _wrap_Dataset_GetTiledVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_GetTiledVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, int nTileYSize, GDALDataType eBufType, int band_list, GDALTileOrganization eTileOrganization, size_t nCacheSize, char ** options=None) -> VirtualMem"},
+	 { (char *)"Dataset_CreateLayer", (PyCFunction) _wrap_Dataset_CreateLayer, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_CreateLayer(Dataset self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type, char ** options=None) -> Layer"},
 	 { (char *)"Dataset_CopyLayer", (PyCFunction) _wrap_Dataset_CopyLayer, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_CopyLayer(Dataset self, Layer src_layer, char const * new_name, char ** options=None) -> Layer"},
 	 { (char *)"Dataset_DeleteLayer", _wrap_Dataset_DeleteLayer, METH_VARARGS, (char *)"Dataset_DeleteLayer(Dataset self, int index) -> OGRErr"},
 	 { (char *)"Dataset_GetLayerCount", _wrap_Dataset_GetLayerCount, METH_VARARGS, (char *)"Dataset_GetLayerCount(Dataset self) -> int"},
 	 { (char *)"Dataset_GetLayerByIndex", _wrap_Dataset_GetLayerByIndex, METH_VARARGS, (char *)"Dataset_GetLayerByIndex(Dataset self, int index=0) -> Layer"},
 	 { (char *)"Dataset_GetLayerByName", _wrap_Dataset_GetLayerByName, METH_VARARGS, (char *)"Dataset_GetLayerByName(Dataset self, char const * layer_name) -> Layer"},
+	 { (char *)"Dataset_ResetReading", _wrap_Dataset_ResetReading, METH_VARARGS, (char *)"Dataset_ResetReading(Dataset self)"},
+	 { (char *)"Dataset_GetNextFeature", (PyCFunction) _wrap_Dataset_GetNextFeature, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_GetNextFeature(Dataset self, bool include_layer=True, bool include_pct=False, GDALProgressFunc callback=0, void * callback_data=None) -> Feature"},
 	 { (char *)"Dataset_TestCapability", _wrap_Dataset_TestCapability, METH_VARARGS, (char *)"Dataset_TestCapability(Dataset self, char const * cap) -> bool"},
-	 { (char *)"Dataset_ExecuteSQL", (PyCFunction) _wrap_Dataset_ExecuteSQL, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_ExecuteSQL(Dataset self, char const * statement, Geometry spatialFilter=None, char const * dialect=\"\") -> Layer"},
+	 { (char *)"Dataset_ExecuteSQL", (PyCFunction) _wrap_Dataset_ExecuteSQL, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_ExecuteSQL(Dataset self, char const * statement, Geometry spatialFilter=None, char const * dialect) -> Layer"},
 	 { (char *)"Dataset_ReleaseResultSet", _wrap_Dataset_ReleaseResultSet, METH_VARARGS, (char *)"Dataset_ReleaseResultSet(Dataset self, Layer layer)"},
 	 { (char *)"Dataset_GetStyleTable", _wrap_Dataset_GetStyleTable, METH_VARARGS, (char *)"Dataset_GetStyleTable(Dataset self) -> StyleTable"},
 	 { (char *)"Dataset_SetStyleTable", _wrap_Dataset_SetStyleTable, METH_VARARGS, (char *)"Dataset_SetStyleTable(Dataset self, StyleTable table)"},
 	 { (char *)"Dataset_StartTransaction", (PyCFunction) _wrap_Dataset_StartTransaction, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_StartTransaction(Dataset self, int force=False) -> OGRErr"},
 	 { (char *)"Dataset_CommitTransaction", _wrap_Dataset_CommitTransaction, METH_VARARGS, (char *)"Dataset_CommitTransaction(Dataset self) -> OGRErr"},
 	 { (char *)"Dataset_RollbackTransaction", _wrap_Dataset_RollbackTransaction, METH_VARARGS, (char *)"Dataset_RollbackTransaction(Dataset self) -> OGRErr"},
-	 { (char *)"Dataset_ReadRaster1", (PyCFunction) _wrap_Dataset_ReadRaster1, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Dataset_ReadRaster1(Dataset self, int xoff, int yoff, int xsize, int ysize, int * buf_xsize=None, int * buf_ysize=None, \n"
-		"    GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None, \n"
-		"    GIntBig * buf_line_space=None, GIntBig * buf_band_space=None, \n"
-		"    GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> CPLErr\n"
-		""},
+	 { (char *)"Dataset_ReadRaster1", (PyCFunction) _wrap_Dataset_ReadRaster1, METH_VARARGS | METH_KEYWORDS, (char *)"Dataset_ReadRaster1(Dataset self, int xoff, int yoff, int xsize, int ysize, int * buf_xsize=None, int * buf_ysize=None, GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None, GIntBig * buf_band_space=None, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"},
 	 { (char *)"Dataset_swigregister", Dataset_swigregister, METH_VARARGS, NULL},
 	 { (char *)"Band_XSize_get", _wrap_Band_XSize_get, METH_VARARGS, (char *)"Band_XSize_get(Band self) -> int"},
 	 { (char *)"Band_YSize_get", _wrap_Band_YSize_get, METH_VARARGS, (char *)"Band_YSize_get(Band self) -> int"},
@@ -29373,6 +31778,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Band_GetDataset", _wrap_Band_GetDataset, METH_VARARGS, (char *)"Band_GetDataset(Band self) -> Dataset"},
 	 { (char *)"Band_GetBand", _wrap_Band_GetBand, METH_VARARGS, (char *)"Band_GetBand(Band self) -> int"},
 	 { (char *)"Band_GetBlockSize", _wrap_Band_GetBlockSize, METH_VARARGS, (char *)"Band_GetBlockSize(Band self)"},
+	 { (char *)"Band_GetActualBlockSize", _wrap_Band_GetActualBlockSize, METH_VARARGS, (char *)"Band_GetActualBlockSize(Band self, int nXBlockOff, int nYBlockOff)"},
 	 { (char *)"Band_GetColorInterpretation", _wrap_Band_GetColorInterpretation, METH_VARARGS, (char *)"Band_GetColorInterpretation(Band self) -> GDALColorInterp"},
 	 { (char *)"Band_GetRasterColorInterpretation", _wrap_Band_GetRasterColorInterpretation, METH_VARARGS, (char *)"Band_GetRasterColorInterpretation(Band self) -> GDALColorInterp"},
 	 { (char *)"Band_SetColorInterpretation", _wrap_Band_SetColorInterpretation, METH_VARARGS, (char *)"Band_SetColorInterpretation(Band self, GDALColorInterp val) -> CPLErr"},
@@ -29399,11 +31805,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Band_ComputeRasterMinMax", _wrap_Band_ComputeRasterMinMax, METH_VARARGS, (char *)"Band_ComputeRasterMinMax(Band self, int approx_ok=0)"},
 	 { (char *)"Band_ComputeBandStats", _wrap_Band_ComputeBandStats, METH_VARARGS, (char *)"Band_ComputeBandStats(Band self, int samplestep=1)"},
 	 { (char *)"Band_Fill", _wrap_Band_Fill, METH_VARARGS, (char *)"Band_Fill(Band self, double real_fill, double imag_fill=0.0) -> CPLErr"},
-	 { (char *)"Band_WriteRaster", (PyCFunction) _wrap_Band_WriteRaster, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_WriteRaster(Band self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, \n"
-		"    int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None, \n"
-		"    GIntBig * buf_line_space=None) -> CPLErr\n"
-		""},
+	 { (char *)"Band_WriteRaster", (PyCFunction) _wrap_Band_WriteRaster, METH_VARARGS | METH_KEYWORDS, (char *)"Band_WriteRaster(Band self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None) -> CPLErr"},
 	 { (char *)"Band_FlushCache", _wrap_Band_FlushCache, METH_VARARGS, (char *)"Band_FlushCache(Band self)"},
 	 { (char *)"Band_GetRasterColorTable", _wrap_Band_GetRasterColorTable, METH_VARARGS, (char *)"Band_GetRasterColorTable(Band self) -> ColorTable"},
 	 { (char *)"Band_GetColorTable", _wrap_Band_GetColorTable, METH_VARARGS, (char *)"Band_GetColorTable(Band self) -> ColorTable"},
@@ -29414,37 +31816,20 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Band_GetMaskBand", _wrap_Band_GetMaskBand, METH_VARARGS, (char *)"Band_GetMaskBand(Band self) -> Band"},
 	 { (char *)"Band_GetMaskFlags", _wrap_Band_GetMaskFlags, METH_VARARGS, (char *)"Band_GetMaskFlags(Band self) -> int"},
 	 { (char *)"Band_CreateMaskBand", _wrap_Band_CreateMaskBand, METH_VARARGS, (char *)"Band_CreateMaskBand(Band self, int nFlags) -> CPLErr"},
-	 { (char *)"Band_GetHistogram", (PyCFunction) _wrap_Band_GetHistogram, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_GetHistogram(Band self, double min=-0.5, double max=255.5, int buckets=256, int include_out_of_range=0, \n"
-		"    int approx_ok=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr\n"
-		""},
-	 { (char *)"Band_GetDefaultHistogram", (PyCFunction) _wrap_Band_GetDefaultHistogram, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_GetDefaultHistogram(Band self, double * min_ret=None, double * max_ret=None, int * buckets_ret=None, \n"
-		"    GUIntBig ** ppanHistogram=None, int force=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr\n"
-		""},
+	 { (char *)"Band_GetHistogram", (PyCFunction) _wrap_Band_GetHistogram, METH_VARARGS | METH_KEYWORDS, (char *)"Band_GetHistogram(Band self, double min=-0.5, double max=255.5, int buckets=256, int include_out_of_range=0, int approx_ok=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"},
+	 { (char *)"Band_GetDefaultHistogram", (PyCFunction) _wrap_Band_GetDefaultHistogram, METH_VARARGS | METH_KEYWORDS, (char *)"Band_GetDefaultHistogram(Band self, double * min_ret=None, double * max_ret=None, int * buckets_ret=None, GUIntBig ** ppanHistogram=None, int force=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"},
 	 { (char *)"Band_SetDefaultHistogram", _wrap_Band_SetDefaultHistogram, METH_VARARGS, (char *)"Band_SetDefaultHistogram(Band self, double min, double max, int buckets_in) -> CPLErr"},
 	 { (char *)"Band_HasArbitraryOverviews", _wrap_Band_HasArbitraryOverviews, METH_VARARGS, (char *)"Band_HasArbitraryOverviews(Band self) -> bool"},
 	 { (char *)"Band_GetCategoryNames", _wrap_Band_GetCategoryNames, METH_VARARGS, (char *)"Band_GetCategoryNames(Band self) -> char **"},
 	 { (char *)"Band_SetCategoryNames", _wrap_Band_SetCategoryNames, METH_VARARGS, (char *)"Band_SetCategoryNames(Band self, char ** papszCategoryNames) -> CPLErr"},
-	 { (char *)"Band_GetVirtualMem", (PyCFunction) _wrap_Band_GetVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_GetVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, \n"
-		"    int nBufYSize, GDALDataType eBufType, size_t nCacheSize, size_t nPageSizeHint, \n"
-		"    char ** options=None) -> VirtualMem\n"
-		""},
+	 { (char *)"Band_GetVirtualMem", (PyCFunction) _wrap_Band_GetVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"Band_GetVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize, GDALDataType eBufType, size_t nCacheSize, size_t nPageSizeHint, char ** options=None) -> VirtualMem"},
 	 { (char *)"Band_GetVirtualMemAuto", (PyCFunction) _wrap_Band_GetVirtualMemAuto, METH_VARARGS | METH_KEYWORDS, (char *)"Band_GetVirtualMemAuto(Band self, GDALRWFlag eRWFlag, char ** options=None) -> VirtualMem"},
-	 { (char *)"Band_GetTiledVirtualMem", (PyCFunction) _wrap_Band_GetTiledVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_GetTiledVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, \n"
-		"    int nTileYSize, GDALDataType eBufType, size_t nCacheSize, char ** options=None) -> VirtualMem\n"
-		""},
-	 { (char *)"Band_ReadRaster1", (PyCFunction) _wrap_Band_ReadRaster1, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Band_ReadRaster1(Band self, double xoff, double yoff, double xsize, double ysize, int * buf_xsize=None, \n"
-		"    int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None, \n"
-		"    GIntBig * buf_line_space=None, GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour, \n"
-		"    GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr\n"
-		""},
+	 { (char *)"Band_GetTiledVirtualMem", (PyCFunction) _wrap_Band_GetTiledVirtualMem, METH_VARARGS | METH_KEYWORDS, (char *)"Band_GetTiledVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, int nTileYSize, GDALDataType eBufType, size_t nCacheSize, char ** options=None) -> VirtualMem"},
+	 { (char *)"Band_GetDataCoverageStatus", _wrap_Band_GetDataCoverageStatus, METH_VARARGS, (char *)"Band_GetDataCoverageStatus(Band self, int nXOff, int nYOff, int nXSize, int nYSize, int nMaskFlagStop=0) -> int"},
+	 { (char *)"Band_ReadRaster1", (PyCFunction) _wrap_Band_ReadRaster1, METH_VARARGS | METH_KEYWORDS, (char *)"Band_ReadRaster1(Band self, double xoff, double yoff, double xsize, double ysize, int * buf_xsize=None, int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"},
 	 { (char *)"Band_ReadBlock", (PyCFunction) _wrap_Band_ReadBlock, METH_VARARGS | METH_KEYWORDS, (char *)"Band_ReadBlock(Band self, int xoff, int yoff) -> CPLErr"},
 	 { (char *)"Band_swigregister", Band_swigregister, METH_VARARGS, NULL},
-	 { (char *)"new_ColorTable", (PyCFunction) _wrap_new_ColorTable, METH_VARARGS | METH_KEYWORDS, (char *)"new_ColorTable(GDALPaletteInterp palette=GPI_RGB) -> ColorTable"},
+	 { (char *)"new_ColorTable", (PyCFunction) _wrap_new_ColorTable, METH_VARARGS | METH_KEYWORDS, (char *)"new_ColorTable(GDALPaletteInterp palette) -> ColorTable"},
 	 { (char *)"delete_ColorTable", _wrap_delete_ColorTable, METH_VARARGS, (char *)"delete_ColorTable(ColorTable self)"},
 	 { (char *)"ColorTable_Clone", _wrap_ColorTable_Clone, METH_VARARGS, (char *)"ColorTable_Clone(ColorTable self) -> ColorTable"},
 	 { (char *)"ColorTable_GetPaletteInterpretation", _wrap_ColorTable_GetPaletteInterpretation, METH_VARARGS, (char *)"ColorTable_GetPaletteInterpretation(ColorTable self) -> GDALPaletteInterp"},
@@ -29478,62 +31863,20 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"RasterAttributeTable_DumpReadable", _wrap_RasterAttributeTable_DumpReadable, METH_VARARGS, (char *)"RasterAttributeTable_DumpReadable(RasterAttributeTable self)"},
 	 { (char *)"RasterAttributeTable_swigregister", RasterAttributeTable_swigregister, METH_VARARGS, NULL},
 	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"},
-	 { (char *)"ComputeMedianCutPCT", (PyCFunction) _wrap_ComputeMedianCutPCT, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"ComputeMedianCutPCT(Band red, Band green, Band blue, int num_colors, ColorTable colors, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"DitherRGB2PCT", (PyCFunction) _wrap_DitherRGB2PCT, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"DitherRGB2PCT(Band red, Band green, Band blue, Band target, ColorTable colors, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"ReprojectImage", (PyCFunction) _wrap_ReprojectImage, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"ReprojectImage(Dataset src_ds, Dataset dst_ds, char const * src_wkt=None, char const * dst_wkt=None, \n"
-		"    GDALResampleAlg eResampleAlg=GRA_NearestNeighbour, double WarpMemoryLimit=0.0, \n"
-		"    double maxerror=0.0, GDALProgressFunc callback=0, void * callback_data=None, \n"
-		"    char ** options=None) -> CPLErr\n"
-		""},
-	 { (char *)"ComputeProximity", (PyCFunction) _wrap_ComputeProximity, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"ComputeProximity(Band srcBand, Band proximityBand, char ** options=None, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"RasterizeLayer", (PyCFunction) _wrap_RasterizeLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"RasterizeLayer(Dataset dataset, int bands, Layer layer, void * pfnTransformer=None, void * pTransformArg=None, \n"
-		"    int burn_values=0, char ** options=None, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"Polygonize", (PyCFunction) _wrap_Polygonize, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Polygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, \n"
-		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"FPolygonize", (PyCFunction) _wrap_FPolygonize, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"FPolygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, \n"
-		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"FillNodata", (PyCFunction) _wrap_FillNodata, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations, char ** options=None, \n"
-		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"SieveFilter", (PyCFunction) _wrap_SieveFilter, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness=4, char ** options=None, \n"
-		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"RegenerateOverviews", (PyCFunction) _wrap_RegenerateOverviews, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"RegenerateOverviews(Band srcBand, int overviewBandCount, char const * resampling=\"average\", GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"RegenerateOverview", (PyCFunction) _wrap_RegenerateOverview, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"RegenerateOverview(Band srcBand, Band overviewBand, char const * resampling=\"average\", GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"ContourGenerate", (PyCFunction) _wrap_ContourGenerate, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"ContourGenerate(Band srcBand, double contourInterval, double contourBase, int fixedLevelCount, int useNoData, \n"
-		"    double noDataValue, Layer dstLayer, int idField, int elevField, \n"
-		"    GDALProgressFunc callback=0, void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"AutoCreateWarpedVRT", _wrap_AutoCreateWarpedVRT, METH_VARARGS, (char *)"\n"
-		"AutoCreateWarpedVRT(Dataset src_ds, char const * src_wkt=None, char const * dst_wkt=None, GDALResampleAlg eResampleAlg=GRA_NearestNeighbour, \n"
-		"    double maxerror=0.0) -> Dataset\n"
-		""},
+	 { (char *)"TermProgress_swigconstant", TermProgress_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ComputeMedianCutPCT", (PyCFunction) _wrap_ComputeMedianCutPCT, METH_VARARGS | METH_KEYWORDS, (char *)"ComputeMedianCutPCT(Band red, Band green, Band blue, int num_colors, ColorTable colors, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"DitherRGB2PCT", (PyCFunction) _wrap_DitherRGB2PCT, METH_VARARGS | METH_KEYWORDS, (char *)"DitherRGB2PCT(Band red, Band green, Band blue, Band target, ColorTable colors, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"ReprojectImage", (PyCFunction) _wrap_ReprojectImage, METH_VARARGS | METH_KEYWORDS, (char *)"ReprojectImage(Dataset src_ds, Dataset dst_ds, char const * src_wkt=None, char const * dst_wkt=None, GDALResampleAlg eResampleAlg, double WarpMemoryLimit=0.0, double maxerror=0.0, GDALProgressFunc callback=0, void * callback_data=None, char ** options=None) -> CPLErr"},
+	 { (char *)"ComputeProximity", (PyCFunction) _wrap_ComputeProximity, METH_VARARGS | METH_KEYWORDS, (char *)"ComputeProximity(Band srcBand, Band proximityBand, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"RasterizeLayer", (PyCFunction) _wrap_RasterizeLayer, METH_VARARGS | METH_KEYWORDS, (char *)"RasterizeLayer(Dataset dataset, int bands, Layer layer, void * pfnTransformer=None, void * pTransformArg=None, int burn_values=0, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"Polygonize", (PyCFunction) _wrap_Polygonize, METH_VARARGS | METH_KEYWORDS, (char *)"Polygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"FPolygonize", (PyCFunction) _wrap_FPolygonize, METH_VARARGS | METH_KEYWORDS, (char *)"FPolygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"FillNodata", (PyCFunction) _wrap_FillNodata, METH_VARARGS | METH_KEYWORDS, (char *)"FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"SieveFilter", (PyCFunction) _wrap_SieveFilter, METH_VARARGS | METH_KEYWORDS, (char *)"SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness=4, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"RegenerateOverviews", (PyCFunction) _wrap_RegenerateOverviews, METH_VARARGS | METH_KEYWORDS, (char *)"RegenerateOverviews(Band srcBand, int overviewBandCount, char const * resampling, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"RegenerateOverview", (PyCFunction) _wrap_RegenerateOverview, METH_VARARGS | METH_KEYWORDS, (char *)"RegenerateOverview(Band srcBand, Band overviewBand, char const * resampling, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"ContourGenerate", (PyCFunction) _wrap_ContourGenerate, METH_VARARGS | METH_KEYWORDS, (char *)"ContourGenerate(Band srcBand, double contourInterval, double contourBase, int fixedLevelCount, int useNoData, double noDataValue, Layer dstLayer, int idField, int elevField, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"AutoCreateWarpedVRT", _wrap_AutoCreateWarpedVRT, METH_VARARGS, (char *)"AutoCreateWarpedVRT(Dataset src_ds, char const * src_wkt=None, char const * dst_wkt=None, GDALResampleAlg eResampleAlg, double maxerror=0.0) -> Dataset"},
 	 { (char *)"CreatePansharpenedVRT", _wrap_CreatePansharpenedVRT, METH_VARARGS, (char *)"CreatePansharpenedVRT(char const * pszXML, Band panchroBand, int nInputSpectralBands) -> Dataset"},
 	 { (char *)"new_Transformer", _wrap_new_Transformer, METH_VARARGS, (char *)"new_Transformer(Dataset src, Dataset dst, char ** options) -> Transformer"},
 	 { (char *)"delete_Transformer", _wrap_delete_Transformer, METH_VARARGS, (char *)"delete_Transformer(Transformer self)"},
@@ -29542,14 +31885,12 @@ static PyMethodDef SwigMethods[] = {
 		"Transformer_TransformPoint(Transformer self, int bDstToSrc, double x, double y, double z=0.0) -> int\n"
 		""},
 	 { (char *)"Transformer_TransformPoints", _wrap_Transformer_TransformPoints, METH_VARARGS, (char *)"Transformer_TransformPoints(Transformer self, int bDstToSrc, int nCount) -> int"},
-	 { (char *)"Transformer_TransformGeolocations", (PyCFunction) _wrap_Transformer_TransformGeolocations, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Transformer_TransformGeolocations(Transformer self, Band xBand, Band yBand, Band zBand, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None, char ** options=None) -> int\n"
-		""},
+	 { (char *)"Transformer_TransformGeolocations", (PyCFunction) _wrap_Transformer_TransformGeolocations, METH_VARARGS | METH_KEYWORDS, (char *)"Transformer_TransformGeolocations(Transformer self, Band xBand, Band yBand, Band zBand, GDALProgressFunc callback=0, void * callback_data=None, char ** options=None) -> int"},
 	 { (char *)"Transformer_swigregister", Transformer_swigregister, METH_VARARGS, NULL},
+	 { (char *)"ApplyVerticalShiftGrid", (PyCFunction) _wrap_ApplyVerticalShiftGrid, METH_VARARGS | METH_KEYWORDS, (char *)"ApplyVerticalShiftGrid(Dataset src_ds, Dataset grid_ds, bool inverse=False, double srcUnitToMeter=1.0, double dstUnitToMeter=1.0, char ** options=None) -> Dataset"},
 	 { (char *)"ApplyGeoTransform", _wrap_ApplyGeoTransform, METH_VARARGS, (char *)"ApplyGeoTransform(double [6] padfGeoTransform, double dfPixel, double dfLine)"},
 	 { (char *)"InvGeoTransform", _wrap_InvGeoTransform, METH_VARARGS, (char *)"InvGeoTransform(double [6] gt_in) -> RETURN_NONE"},
-	 { (char *)"VersionInfo", _wrap_VersionInfo, METH_VARARGS, (char *)"VersionInfo(char const * request=\"VERSION_NUM\") -> char const *"},
+	 { (char *)"VersionInfo", _wrap_VersionInfo, METH_VARARGS, (char *)"VersionInfo(char const * request) -> char const *"},
 	 { (char *)"AllRegister", _wrap_AllRegister, METH_VARARGS, (char *)"AllRegister()"},
 	 { (char *)"GDALDestroyDriverManager", _wrap_GDALDestroyDriverManager, METH_VARARGS, (char *)"GDALDestroyDriverManager()"},
 	 { (char *)"GetCacheMax", _wrap_GetCacheMax, METH_VARARGS, (char *)"GetCacheMax() -> GIntBig"},
@@ -29571,13 +31912,11 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GetDriverCount", _wrap_GetDriverCount, METH_VARARGS, (char *)"GetDriverCount() -> int"},
 	 { (char *)"GetDriverByName", _wrap_GetDriverByName, METH_VARARGS, (char *)"GetDriverByName(char const * name) -> Driver"},
 	 { (char *)"GetDriver", _wrap_GetDriver, METH_VARARGS, (char *)"GetDriver(int i) -> Driver"},
-	 { (char *)"Open", _wrap_Open, METH_VARARGS, (char *)"Open(char const * utf8_path, GDALAccess eAccess=GA_ReadOnly) -> Dataset"},
-	 { (char *)"OpenEx", (PyCFunction) _wrap_OpenEx, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"OpenEx(char const * utf8_path, unsigned int nOpenFlags=0, char ** allowed_drivers=None, \n"
-		"    char ** open_options=None, char ** sibling_files=None) -> Dataset\n"
-		""},
-	 { (char *)"OpenShared", _wrap_OpenShared, METH_VARARGS, (char *)"OpenShared(char const * utf8_path, GDALAccess eAccess=GA_ReadOnly) -> Dataset"},
+	 { (char *)"Open", _wrap_Open, METH_VARARGS, (char *)"Open(char const * utf8_path, GDALAccess eAccess) -> Dataset"},
+	 { (char *)"OpenEx", (PyCFunction) _wrap_OpenEx, METH_VARARGS | METH_KEYWORDS, (char *)"OpenEx(char const * utf8_path, unsigned int nOpenFlags=0, char ** allowed_drivers=None, char ** open_options=None, char ** sibling_files=None) -> Dataset"},
+	 { (char *)"OpenShared", _wrap_OpenShared, METH_VARARGS, (char *)"OpenShared(char const * utf8_path, GDALAccess eAccess) -> Dataset"},
 	 { (char *)"IdentifyDriver", _wrap_IdentifyDriver, METH_VARARGS, (char *)"IdentifyDriver(char const * utf8_path, char ** papszSiblings=None) -> Driver"},
+	 { (char *)"IdentifyDriverEx", (PyCFunction) _wrap_IdentifyDriverEx, METH_VARARGS | METH_KEYWORDS, (char *)"IdentifyDriverEx(char const * utf8_path, unsigned int nIdentifyFlags=0, char ** allowed_drivers=None, char ** sibling_files=None) -> Driver"},
 	 { (char *)"GeneralCmdLineProcessor", _wrap_GeneralCmdLineProcessor, METH_VARARGS, (char *)"GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"},
 	 { (char *)"new_GDALInfoOptions", _wrap_new_GDALInfoOptions, METH_VARARGS, (char *)"new_GDALInfoOptions(char ** options) -> GDALInfoOptions"},
 	 { (char *)"delete_GDALInfoOptions", _wrap_delete_GDALInfoOptions, METH_VARARGS, (char *)"delete_GDALInfoOptions(GDALInfoOptions self)"},
@@ -29586,80 +31925,40 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"new_GDALTranslateOptions", _wrap_new_GDALTranslateOptions, METH_VARARGS, (char *)"new_GDALTranslateOptions(char ** options) -> GDALTranslateOptions"},
 	 { (char *)"delete_GDALTranslateOptions", _wrap_delete_GDALTranslateOptions, METH_VARARGS, (char *)"delete_GDALTranslateOptions(GDALTranslateOptions self)"},
 	 { (char *)"GDALTranslateOptions_swigregister", GDALTranslateOptions_swigregister, METH_VARARGS, NULL},
-	 { (char *)"TranslateInternal", _wrap_TranslateInternal, METH_VARARGS, (char *)"\n"
-		"TranslateInternal(char const * dest, Dataset dataset, GDALTranslateOptions translateOptions, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> Dataset\n"
-		""},
+	 { (char *)"TranslateInternal", _wrap_TranslateInternal, METH_VARARGS, (char *)"TranslateInternal(char const * dest, Dataset dataset, GDALTranslateOptions translateOptions, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
 	 { (char *)"new_GDALWarpAppOptions", _wrap_new_GDALWarpAppOptions, METH_VARARGS, (char *)"new_GDALWarpAppOptions(char ** options) -> GDALWarpAppOptions"},
 	 { (char *)"delete_GDALWarpAppOptions", _wrap_delete_GDALWarpAppOptions, METH_VARARGS, (char *)"delete_GDALWarpAppOptions(GDALWarpAppOptions self)"},
 	 { (char *)"GDALWarpAppOptions_swigregister", GDALWarpAppOptions_swigregister, METH_VARARGS, NULL},
-	 { (char *)"wrapper_GDALWarpDestDS", _wrap_wrapper_GDALWarpDestDS, METH_VARARGS, (char *)"\n"
-		"wrapper_GDALWarpDestDS(Dataset dstDS, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"wrapper_GDALWarpDestName", _wrap_wrapper_GDALWarpDestName, METH_VARARGS, (char *)"\n"
-		"wrapper_GDALWarpDestName(char const * dest, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> Dataset\n"
-		""},
+	 { (char *)"wrapper_GDALWarpDestDS", _wrap_wrapper_GDALWarpDestDS, METH_VARARGS, (char *)"wrapper_GDALWarpDestDS(Dataset dstDS, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"wrapper_GDALWarpDestName", _wrap_wrapper_GDALWarpDestName, METH_VARARGS, (char *)"wrapper_GDALWarpDestName(char const * dest, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
 	 { (char *)"new_GDALVectorTranslateOptions", _wrap_new_GDALVectorTranslateOptions, METH_VARARGS, (char *)"new_GDALVectorTranslateOptions(char ** options) -> GDALVectorTranslateOptions"},
 	 { (char *)"delete_GDALVectorTranslateOptions", _wrap_delete_GDALVectorTranslateOptions, METH_VARARGS, (char *)"delete_GDALVectorTranslateOptions(GDALVectorTranslateOptions self)"},
 	 { (char *)"GDALVectorTranslateOptions_swigregister", GDALVectorTranslateOptions_swigregister, METH_VARARGS, NULL},
-	 { (char *)"wrapper_GDALVectorTranslateDestDS", _wrap_wrapper_GDALVectorTranslateDestDS, METH_VARARGS, (char *)"\n"
-		"wrapper_GDALVectorTranslateDestDS(Dataset dstDS, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"wrapper_GDALVectorTranslateDestName", _wrap_wrapper_GDALVectorTranslateDestName, METH_VARARGS, (char *)"\n"
-		"wrapper_GDALVectorTranslateDestName(char const * dest, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> Dataset\n"
-		""},
+	 { (char *)"wrapper_GDALVectorTranslateDestDS", _wrap_wrapper_GDALVectorTranslateDestDS, METH_VARARGS, (char *)"wrapper_GDALVectorTranslateDestDS(Dataset dstDS, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"wrapper_GDALVectorTranslateDestName", _wrap_wrapper_GDALVectorTranslateDestName, METH_VARARGS, (char *)"wrapper_GDALVectorTranslateDestName(char const * dest, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
 	 { (char *)"new_GDALDEMProcessingOptions", _wrap_new_GDALDEMProcessingOptions, METH_VARARGS, (char *)"new_GDALDEMProcessingOptions(char ** options) -> GDALDEMProcessingOptions"},
 	 { (char *)"delete_GDALDEMProcessingOptions", _wrap_delete_GDALDEMProcessingOptions, METH_VARARGS, (char *)"delete_GDALDEMProcessingOptions(GDALDEMProcessingOptions self)"},
 	 { (char *)"GDALDEMProcessingOptions_swigregister", GDALDEMProcessingOptions_swigregister, METH_VARARGS, NULL},
-	 { (char *)"DEMProcessingInternal", _wrap_DEMProcessingInternal, METH_VARARGS, (char *)"\n"
-		"DEMProcessingInternal(char const * dest, Dataset dataset, char const * pszProcessing, char const * pszColorFilename, \n"
-		"    GDALDEMProcessingOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> Dataset\n"
-		""},
+	 { (char *)"DEMProcessingInternal", _wrap_DEMProcessingInternal, METH_VARARGS, (char *)"DEMProcessingInternal(char const * dest, Dataset dataset, char const * pszProcessing, char const * pszColorFilename, GDALDEMProcessingOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
 	 { (char *)"new_GDALNearblackOptions", _wrap_new_GDALNearblackOptions, METH_VARARGS, (char *)"new_GDALNearblackOptions(char ** options) -> GDALNearblackOptions"},
 	 { (char *)"delete_GDALNearblackOptions", _wrap_delete_GDALNearblackOptions, METH_VARARGS, (char *)"delete_GDALNearblackOptions(GDALNearblackOptions self)"},
 	 { (char *)"GDALNearblackOptions_swigregister", GDALNearblackOptions_swigregister, METH_VARARGS, NULL},
-	 { (char *)"wrapper_GDALNearblackDestDS", _wrap_wrapper_GDALNearblackDestDS, METH_VARARGS, (char *)"\n"
-		"wrapper_GDALNearblackDestDS(Dataset dstDS, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"wrapper_GDALNearblackDestName", _wrap_wrapper_GDALNearblackDestName, METH_VARARGS, (char *)"\n"
-		"wrapper_GDALNearblackDestName(char const * dest, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> Dataset\n"
-		""},
+	 { (char *)"wrapper_GDALNearblackDestDS", _wrap_wrapper_GDALNearblackDestDS, METH_VARARGS, (char *)"wrapper_GDALNearblackDestDS(Dataset dstDS, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"wrapper_GDALNearblackDestName", _wrap_wrapper_GDALNearblackDestName, METH_VARARGS, (char *)"wrapper_GDALNearblackDestName(char const * dest, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
 	 { (char *)"new_GDALGridOptions", _wrap_new_GDALGridOptions, METH_VARARGS, (char *)"new_GDALGridOptions(char ** options) -> GDALGridOptions"},
 	 { (char *)"delete_GDALGridOptions", _wrap_delete_GDALGridOptions, METH_VARARGS, (char *)"delete_GDALGridOptions(GDALGridOptions self)"},
 	 { (char *)"GDALGridOptions_swigregister", GDALGridOptions_swigregister, METH_VARARGS, NULL},
-	 { (char *)"GridInternal", _wrap_GridInternal, METH_VARARGS, (char *)"\n"
-		"GridInternal(char const * dest, Dataset dataset, GDALGridOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> Dataset\n"
-		""},
+	 { (char *)"GridInternal", _wrap_GridInternal, METH_VARARGS, (char *)"GridInternal(char const * dest, Dataset dataset, GDALGridOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
 	 { (char *)"new_GDALRasterizeOptions", _wrap_new_GDALRasterizeOptions, METH_VARARGS, (char *)"new_GDALRasterizeOptions(char ** options) -> GDALRasterizeOptions"},
 	 { (char *)"delete_GDALRasterizeOptions", _wrap_delete_GDALRasterizeOptions, METH_VARARGS, (char *)"delete_GDALRasterizeOptions(GDALRasterizeOptions self)"},
 	 { (char *)"GDALRasterizeOptions_swigregister", GDALRasterizeOptions_swigregister, METH_VARARGS, NULL},
-	 { (char *)"wrapper_GDALRasterizeDestDS", _wrap_wrapper_GDALRasterizeDestDS, METH_VARARGS, (char *)"\n"
-		"wrapper_GDALRasterizeDestDS(Dataset dstDS, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> int\n"
-		""},
-	 { (char *)"wrapper_GDALRasterizeDestName", _wrap_wrapper_GDALRasterizeDestName, METH_VARARGS, (char *)"\n"
-		"wrapper_GDALRasterizeDestName(char const * dest, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> Dataset\n"
-		""},
+	 { (char *)"wrapper_GDALRasterizeDestDS", _wrap_wrapper_GDALRasterizeDestDS, METH_VARARGS, (char *)"wrapper_GDALRasterizeDestDS(Dataset dstDS, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> int"},
+	 { (char *)"wrapper_GDALRasterizeDestName", _wrap_wrapper_GDALRasterizeDestName, METH_VARARGS, (char *)"wrapper_GDALRasterizeDestName(char const * dest, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
 	 { (char *)"new_GDALBuildVRTOptions", _wrap_new_GDALBuildVRTOptions, METH_VARARGS, (char *)"new_GDALBuildVRTOptions(char ** options) -> GDALBuildVRTOptions"},
 	 { (char *)"delete_GDALBuildVRTOptions", _wrap_delete_GDALBuildVRTOptions, METH_VARARGS, (char *)"delete_GDALBuildVRTOptions(GDALBuildVRTOptions self)"},
 	 { (char *)"GDALBuildVRTOptions_swigregister", GDALBuildVRTOptions_swigregister, METH_VARARGS, NULL},
-	 { (char *)"BuildVRTInternalObjects", _wrap_BuildVRTInternalObjects, METH_VARARGS, (char *)"\n"
-		"BuildVRTInternalObjects(char const * dest, int object_list_count, GDALBuildVRTOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> Dataset\n"
-		""},
-	 { (char *)"BuildVRTInternalNames", _wrap_BuildVRTInternalNames, METH_VARARGS, (char *)"\n"
-		"BuildVRTInternalNames(char const * dest, char ** source_filenames, GDALBuildVRTOptions options, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> Dataset\n"
-		""},
+	 { (char *)"BuildVRTInternalObjects", _wrap_BuildVRTInternalObjects, METH_VARARGS, (char *)"BuildVRTInternalObjects(char const * dest, int object_list_count, GDALBuildVRTOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
+	 { (char *)"BuildVRTInternalNames", _wrap_BuildVRTInternalNames, METH_VARARGS, (char *)"BuildVRTInternalNames(char const * dest, char ** source_filenames, GDALBuildVRTOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"},
 	 { NULL, NULL, 0, NULL }
 };
 
@@ -29704,6 +32003,7 @@ static swig_type_info _swigt__p_GDALWarpAppOptions = {"_p_GDALWarpAppOptions", "
 static swig_type_info _swigt__p_GDAL_GCP = {"_p_GDAL_GCP", "GDAL_GCP *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GUIntBig = {"_p_GUIntBig", "GUIntBig *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRGeometryShadow = {"_p_OGRGeometryShadow", "OGRGeometryShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRStyleTableShadow = {"_p_OGRStyleTableShadow", "OGRStyleTableShadow *", 0, 0, (void*)0, 0};
@@ -29717,6 +32017,7 @@ static swig_type_info _swigt__p_p_GDALDatasetShadow = {"_p_p_GDALDatasetShadow",
 static swig_type_info _swigt__p_p_GDALRasterBandShadow = {"_p_p_GDALRasterBandShadow", "GDALRasterBandShadow **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GDAL_GCP = {"_p_p_GDAL_GCP", "GDAL_GCP **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_GUIntBig = {"_p_p_GUIntBig", "GUIntBig **", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_OGRLayerShadow = {"_p_p_OGRLayerShadow", "OGRLayerShadow **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_void = {"_p_p_void", "void **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_size_t = {"_p_size_t", "size_t *", 0, 0, (void*)0, 0};
@@ -29749,6 +32050,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_GDAL_GCP,
   &_swigt__p_GIntBig,
   &_swigt__p_GUIntBig,
+  &_swigt__p_OGRFeatureShadow,
   &_swigt__p_OGRGeometryShadow,
   &_swigt__p_OGRLayerShadow,
   &_swigt__p_OGRStyleTableShadow,
@@ -29762,6 +32064,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_p_GDALRasterBandShadow,
   &_swigt__p_p_GDAL_GCP,
   &_swigt__p_p_GUIntBig,
+  &_swigt__p_p_OGRLayerShadow,
   &_swigt__p_p_char,
   &_swigt__p_p_void,
   &_swigt__p_size_t,
@@ -29794,6 +32097,7 @@ static swig_cast_info _swigc__p_GDALWarpAppOptions[] = {  {&_swigt__p_GDALWarpAp
 static swig_cast_info _swigc__p_GDAL_GCP[] = {  {&_swigt__p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GUIntBig[] = {  {&_swigt__p_GUIntBig, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRGeometryShadow[] = {  {&_swigt__p_OGRGeometryShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRStyleTableShadow[] = {  {&_swigt__p_OGRStyleTableShadow, 0, 0, 0},{0, 0, 0, 0}};
@@ -29807,6 +32111,7 @@ static swig_cast_info _swigc__p_p_GDALDatasetShadow[] = {  {&_swigt__p_p_GDALDat
 static swig_cast_info _swigc__p_p_GDALRasterBandShadow[] = {  {&_swigt__p_p_GDALRasterBandShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_GDAL_GCP[] = {  {&_swigt__p_p_GDAL_GCP, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_GUIntBig[] = {  {&_swigt__p_p_GUIntBig, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_OGRLayerShadow[] = {  {&_swigt__p_p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_char[] = {  {&_swigt__p_p_char, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_void[] = {  {&_swigt__p_p_void, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_size_t[] = {  {&_swigt__p_size_t, 0, 0, 0},{0, 0, 0, 0}};
@@ -29839,6 +32144,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_GDAL_GCP,
   _swigc__p_GIntBig,
   _swigc__p_GUIntBig,
+  _swigc__p_OGRFeatureShadow,
   _swigc__p_OGRGeometryShadow,
   _swigc__p_OGRLayerShadow,
   _swigc__p_OGRStyleTableShadow,
@@ -29852,6 +32158,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_p_GDALRasterBandShadow,
   _swigc__p_p_GDAL_GCP,
   _swigc__p_p_GUIntBig,
+  _swigc__p_p_OGRLayerShadow,
   _swigc__p_p_char,
   _swigc__p_p_void,
   _swigc__p_size_t,
@@ -29881,7 +32188,7 @@ static swig_const_info swig_const_table[] = {
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial
+ * The generated swig_type_info structures are assigned statically to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -29925,7 +32232,7 @@ SWIGRUNTIME void
 SWIG_InitializeModule(void *clientdata) {
   size_t i;
   swig_module_info *module_head, *iter;
-  int found, init;
+  int init;
   
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
@@ -29944,22 +32251,18 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
     iter=module_head;
     do {
       if (iter==&swig_module) {
-        found=1;
-        break;
+        /* Our module is already in the list, so there's nothing more to do. */
+        return;
       }
       iter=iter->next;
     } while (iter!= module_head);
     
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
+    /* otherwise we must add our module into the list */
     swig_module.next = module_head->next;
     module_head->next = &swig_module;
   }
@@ -30211,7 +32514,7 @@ extern "C" {
       var = var->next;
     }
     if (res == NULL && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -30228,7 +32531,7 @@ extern "C" {
       var = var->next;
     }
     if (res == 1 && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -30278,10 +32581,19 @@ extern "C" {
         0,                                  /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-        0,                                  /* tp_version */
+        0,                                  /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+        0,                                  /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-        0,0,0,0                             /* tp_alloc -> tp_next */
+        0,                                  /* tp_allocs */
+        0,                                  /* tp_frees */
+        0,                                  /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+        0,                                  /* tp_prev */
+#endif
+        0                                   /* tp_next */
 #endif
       };
       varlink_type = tmp;
@@ -30370,7 +32682,9 @@ extern "C" {
     size_t i;
     for (i = 0; methods[i].ml_name; ++i) {
       const char *c = methods[i].ml_doc;
-      if (c && (c = strstr(c, "swig_ptr: "))) {
+      if (!c) continue;
+      c = strstr(c, "swig_ptr: ");
+      if (c) {
         int j;
         swig_const_info *ci = 0;
         const char *name = c + 10;
@@ -30472,6 +32786,7 @@ SWIG_init(void) {
   PyObject *public_interface, *public_symbol;
   PyObject *this_descr;
   PyObject *thisown_descr;
+  PyObject *self = 0;
   int i;
   
   (void)builtin_pytype;
@@ -30479,6 +32794,7 @@ SWIG_init(void) {
   (void)builtin_basetype;
   (void)tuple;
   (void)static_getset;
+  (void)self;
   
   /* metatype is used to implement static member variables. */
   metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
@@ -30498,6 +32814,7 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
+  
   md = d = PyModule_GetDict(m);
   (void)md;
   
@@ -30547,10 +32864,9 @@ SWIG_init(void) {
     GDALAllRegister();
   }
   
-  SWIG_Python_SetConstant(d, "VSI_STAT_EXISTS_FLAG",SWIG_From_int(static_cast< int >(0x1)));
-  SWIG_Python_SetConstant(d, "VSI_STAT_NATURE_FLAG",SWIG_From_int(static_cast< int >(0x2)));
-  SWIG_Python_SetConstant(d, "VSI_STAT_SIZE_FLAG",SWIG_From_int(static_cast< int >(0x4)));
   
+  /* Initialize threading */
+  SWIG_PYTHON_INITIALIZE_THREADS;
 #if PY_VERSION_HEX >= 0x03000000
   return m;
 #else
diff --git a/swig/python/extensions/gdalconst_wrap.c b/swig/python/extensions/gdalconst_wrap.c
index ddb69a5..af32e68 100644
--- a/swig/python/extensions/gdalconst_wrap.c
+++ b/swig/python/extensions/gdalconst_wrap.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
+ * Version 3.0.8
  *
  * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -8,8 +8,13 @@
  * interface file instead.
  * ----------------------------------------------------------------------------- */
 
+
+#ifndef SWIGPYTHON
 #define SWIGPYTHON
 #define SED_HACKS
+#endif
+
+#define SWIG_PYTHON_THREADS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 /* -----------------------------------------------------------------------------
@@ -120,6 +125,19 @@
 # define _SCL_SECURE_NO_DEPRECATE
 #endif
 
+/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
+#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
+# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
+/* Intel's compiler complains if a variable which was never initialised is
+ * cast to void, which is a common idiom which we use to indicate that we
+ * are aware a variable isn't used.  So we just silence that warning.
+ * See: https://github.com/swig/swig/issues/192 for more discussion.
+ */
+#ifdef __INTEL_COMPILER
+# pragma warning disable 592
+#endif
 
 
 #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
@@ -537,14 +555,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   swig_module_info *iter = start;
   do {
     if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
+      size_t l = 0;
+      size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
+	size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
-	  register int compare = strcmp(name, iname);
+	  int compare = strcmp(name, iname);
 	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
@@ -588,7 +606,7 @@ SWIG_TypeQueryModule(swig_module_info *start,
        of the str field (the human readable name) */
     swig_module_info *iter = start;
     do {
-      register size_t i = 0;
+      size_t i = 0;
       for (; i < iter->size; ++i) {
 	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
 	  return iter->types[i];
@@ -607,10 +625,10 @@ SWIG_TypeQueryModule(swig_module_info *start,
 SWIGRUNTIME char *
 SWIG_PackData(char *c, void *ptr, size_t sz) {
   static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
+  const unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu =  u + sz;
   for (; u != eu; ++u) {
-    register unsigned char uu = *u;
+    unsigned char uu = *u;
     *(c++) = hex[(uu & 0xf0) >> 4];
     *(c++) = hex[uu & 0xf];
   }
@@ -622,11 +640,11 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
 */
 SWIGRUNTIME const char *
 SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
+  unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu = u + sz;
   for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
+    char d = *(c++);
+    unsigned char uu;
     if ((d >= '0') && (d <= '9'))
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
@@ -1289,7 +1307,7 @@ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
 
 /* Unpack the argument tuple */
 
-SWIGINTERN int
+SWIGINTERN Py_ssize_t
 SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
 {
   if (!args) {
@@ -1303,7 +1321,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
   }  
   if (!PyTuple_Check(args)) {
     if (min <= 1 && max >= 1) {
-      register int i;
+      Py_ssize_t i;
       objs[0] = args;
       for (i = 1; i < max; ++i) {
 	objs[i] = 0;
@@ -1313,7 +1331,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
-    register Py_ssize_t l = PyTuple_GET_SIZE(args);
+    Py_ssize_t l = PyTuple_GET_SIZE(args);
     if (l < min) {
       PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
 		   name, (min == max ? "" : "at least "), (int)min, (int)l);
@@ -1323,7 +1341,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 		   name, (min == max ? "" : "at most "), (int)max, (int)l);
       return 0;
     } else {
-      register int i;
+      Py_ssize_t i;
       for (i = 0; i < l; ++i) {
 	objs[i] = PyTuple_GET_ITEM(args, i);
       }
@@ -1509,6 +1527,23 @@ typedef struct {
 #endif
 } SwigPyObject;
 
+
+#ifdef SWIGPYTHON_BUILTIN
+
+SWIGRUNTIME PyObject *
+SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+
+  if (!sobj->dict)
+    sobj->dict = PyDict_New();
+
+  Py_INCREF(sobj->dict);
+  return sobj->dict;
+}
+
+#endif
+
 SWIGRUNTIME PyObject *
 SwigPyObject_long(SwigPyObject *v)
 {
@@ -1647,16 +1682,32 @@ SwigPyObject_dealloc(PyObject *v)
     if (destroy) {
       /* destroy is always a VARARGS method */
       PyObject *res;
+
+      /* PyObject_CallFunction() has the potential to silently drop
+         the active active exception.  In cases of unnamed temporary
+         variable or where we just finished iterating over a generator
+         StopIteration will be active right now, and this needs to
+         remain true upon return from SwigPyObject_dealloc.  So save
+         and restore. */
+      
+      PyObject *val = NULL, *type = NULL, *tb = NULL;
+      PyErr_Fetch(&val, &type, &tb);
+
       if (data->delargs) {
-	/* we need to create a temporary object to carry the destroy operation */
-	PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
-	res = SWIG_Python_CallFunctor(destroy, tmp);
-	Py_DECREF(tmp);
+        /* we need to create a temporary object to carry the destroy operation */
+        PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
+        res = SWIG_Python_CallFunctor(destroy, tmp);
+        Py_DECREF(tmp);
       } else {
-	PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
-	PyObject *mself = PyCFunction_GET_SELF(destroy);
-	res = ((*meth)(mself, v));
+        PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+        PyObject *mself = PyCFunction_GET_SELF(destroy);
+        res = ((*meth)(mself, v));
       }
+      if (!res)
+        PyErr_WriteUnraisable(destroy);
+
+      PyErr_Restore(val, type, tb);
+
       Py_XDECREF(res);
     } 
 #if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
@@ -1680,6 +1731,7 @@ SwigPyObject_append(PyObject* v, PyObject* next)
   next = tmp;
 #endif
   if (!SwigPyObject_Check(next)) {
+    PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject");
     return NULL;
   }
   sobj->next = next;
@@ -1779,7 +1831,7 @@ swigobject_methods[] = {
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_VARARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS,  (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_VARARGS,  (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_VARARGS,  (char *)"returns the next 'this' object"},
@@ -1835,7 +1887,9 @@ SwigPyObject_TypeOnce(void) {
     (unaryfunc)SwigPyObject_oct,  /*nb_oct*/
     (unaryfunc)SwigPyObject_hex,  /*nb_hex*/
 #endif
-#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */
+#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
 #elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
@@ -1915,10 +1969,19 @@ SwigPyObject_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpyobject_type = tmp;
@@ -2094,10 +2157,19 @@ SwigPyPacked_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpypacked_type = tmp;
@@ -2438,7 +2510,7 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
     }
   } else {
 #if PY_VERSION_HEX >= 0x03000000
-    inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
+    inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
     if (inst) {
       PyObject_SetAttr(inst, SWIG_This(), swig_this);
       Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
@@ -2548,18 +2620,21 @@ SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int f
 	  newobj = (SwigPyObject *) newobj->next;
         newobj->next = next_self;
         newobj = (SwigPyObject *)next_self;
+#ifdef SWIGPYTHON_BUILTIN
+        newobj->dict = 0;
+#endif
       }
     } else {
       newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
     }
     if (newobj) {
       newobj->ptr = ptr;
       newobj->ty = type;
       newobj->own = own;
       newobj->next = 0;
-#ifdef SWIGPYTHON_BUILTIN
-      newobj->dict = 0;
-#endif
       return (PyObject*) newobj;
     }
     return SWIG_Py_Void();
@@ -2622,13 +2697,11 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 {
   PyObject *dict;
   if (!PyModule_Check(m)) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs module as first arg");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg");
     return SWIG_ERROR;
   }
   if (!o) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs non-NULL value");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value");
     return SWIG_ERROR;
   }
   
@@ -2937,7 +3010,7 @@ static swig_module_info swig_module = {swig_types, 1, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_gdalconst"
 
-#define SWIGVERSION 0x020012 
+#define SWIGVERSION 0x030008 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -2981,9 +3054,13 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
 	SWIG_InternalNewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void();
     } else {
 #if PY_VERSION_HEX >= 0x03000000
-      return PyUnicode_FromStringAndSize(carray, (int)(size));
+#if PY_VERSION_HEX >= 0x03010000
+      return PyUnicode_DecodeUTF8(carray, (Py_ssize_t)(size), "surrogateescape");
+#else
+      return PyUnicode_FromStringAndSize(carray, (Py_ssize_t)(size));
+#endif
 #else
-      return PyString_FromStringAndSize(carray, (int)(size));
+      return PyString_FromStringAndSize(carray, (Py_ssize_t)(size));
 #endif
     }
   } else {
@@ -3001,226 +3078,1914 @@ SWIG_FromCharPtr(const char *cptr)
 #ifdef __cplusplus
 extern "C" {
 #endif
-static PyMethodDef SwigMethods[] = {
-	 { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL},
-	 { NULL, NULL, 0, NULL }
-};
+SWIGINTERN PyObject *GDT_Unknown_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_Unknown",SWIG_From_int((int)(GDT_Unknown)));
+  return SWIG_Py_Void();
+}
 
 
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+SWIGINTERN PyObject *GDT_Byte_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_Byte",SWIG_From_int((int)(GDT_Byte)));
+  return SWIG_Py_Void();
+}
 
-static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
 
-static swig_type_info *swig_type_initial[] = {
-  &_swigt__p_char,
-};
+SWIGINTERN PyObject *GDT_UInt16_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_UInt16",SWIG_From_int((int)(GDT_UInt16)));
+  return SWIG_Py_Void();
+}
 
-static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
 
-static swig_cast_info *swig_cast_initial[] = {
-  _swigc__p_char,
-};
+SWIGINTERN PyObject *GDT_Int16_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_Int16",SWIG_From_int((int)(GDT_Int16)));
+  return SWIG_Py_Void();
+}
 
 
-/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+SWIGINTERN PyObject *GDT_UInt32_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_UInt32",SWIG_From_int((int)(GDT_UInt32)));
+  return SWIG_Py_Void();
+}
 
-static swig_const_info swig_const_table[] = {
-{0, 0, 0, 0.0, 0, 0}};
 
-#ifdef __cplusplus
+SWIGINTERN PyObject *GDT_Int32_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_Int32",SWIG_From_int((int)(GDT_Int32)));
+  return SWIG_Py_Void();
 }
-#endif
-/* -----------------------------------------------------------------------------
- * Type initialization:
- * This problem is tough by the requirement that no dynamic
- * memory is used. Also, since swig_type_info structures store pointers to
- * swig_cast_info structures and swig_cast_info structures store pointers back
- * to swig_type_info structures, we need some lookup code at initialization.
- * The idea is that swig generates all the structures that are needed.
- * The runtime then collects these partially filled structures.
- * The SWIG_InitializeModule function takes these initial arrays out of
- * swig_module, and does all the lookup, filling in the swig_module.types
- * array with the correct data and linking the correct swig_cast_info
- * structures together.
- *
- * The generated swig_type_info structures are assigned staticly to an initial
- * array. We just loop through that array, and handle each type individually.
- * First we lookup if this type has been already loaded, and if so, use the
- * loaded structure instead of the generated one. Then we have to fill in the
- * cast linked list. The cast data is initially stored in something like a
- * two-dimensional array. Each row corresponds to a type (there are the same
- * number of rows as there are in the swig_type_initial array). Each entry in
- * a column is one of the swig_cast_info structures for that type.
- * The cast_initial array is actually an array of arrays, because each row has
- * a variable number of columns. So to actually build the cast linked list,
- * we find the array of casts associated with the type, and loop through it
- * adding the casts to the list. The one last trick we need to do is making
- * sure the type pointer in the swig_cast_info struct is correct.
- *
- * First off, we lookup the cast->type name to see if it is already loaded.
- * There are three cases to handle:
- *  1) If the cast->type has already been loaded AND the type we are adding
- *     casting info to has not been loaded (it is in this module), THEN we
- *     replace the cast->type pointer with the type pointer that has already
- *     been loaded.
- *  2) If BOTH types (the one we are adding casting info to, and the
- *     cast->type) are loaded, THEN the cast info has already been loaded by
- *     the previous module so we just ignore it.
- *  3) Finally, if cast->type has not already been loaded, then we add that
- *     swig_cast_info to the linked list (because the cast->type) pointer will
- *     be correct.
- * ----------------------------------------------------------------------------- */
 
-#ifdef __cplusplus
-extern "C" {
-#if 0
-} /* c-mode */
-#endif
-#endif
 
-#if 0
-#define SWIGRUNTIME_DEBUG
-#endif
+SWIGINTERN PyObject *GDT_Float32_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_Float32",SWIG_From_int((int)(GDT_Float32)));
+  return SWIG_Py_Void();
+}
 
 
-SWIGRUNTIME void
-SWIG_InitializeModule(void *clientdata) {
-  size_t i;
-  swig_module_info *module_head, *iter;
-  int found, init;
-  
-  /* check to see if the circular list has been setup, if not, set it up */
-  if (swig_module.next==0) {
-    /* Initialize the swig_module */
-    swig_module.type_initial = swig_type_initial;
-    swig_module.cast_initial = swig_cast_initial;
-    swig_module.next = &swig_module;
-    init = 1;
-  } else {
-    init = 0;
-  }
-  
-  /* Try and load any already created modules */
-  module_head = SWIG_GetModule(clientdata);
-  if (!module_head) {
-    /* This is the first module loaded for this interpreter */
-    /* so set the swig module into the interpreter */
-    SWIG_SetModule(clientdata, &swig_module);
-    /*module_head = &swig_module;*/
-  } else {
-    /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
-    iter=module_head;
-    do {
-      if (iter==&swig_module) {
-        found=1;
-        break;
-      }
-      iter=iter->next;
-    } while (iter!= module_head);
-    
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
-    swig_module.next = module_head->next;
-    module_head->next = &swig_module;
-  }
-  
-  /* When multiple interpreters are used, a module could have already been initialized in
-       a different interpreter, but not yet have a pointer in this interpreter.
-       In this case, we do not want to continue adding types... everything should be
-       set up already */
-  if (init == 0) return;
-  
-  /* Now work on filling in swig_module.types */
-#ifdef SWIGRUNTIME_DEBUG
-  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
-#endif
-  for (i = 0; i < swig_module.size; ++i) {
-    swig_type_info *type = 0;
-    swig_type_info *ret;
-    swig_cast_info *cast;
-    
-#ifdef SWIGRUNTIME_DEBUG
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-#endif
-    
-    /* if there is another module already loaded */
-    if (swig_module.next != &swig_module) {
-      type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
-    }
-    if (type) {
-      /* Overwrite clientdata field */
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: found type %s\n", type->name);
-#endif
-      if (swig_module.type_initial[i]->clientdata) {
-        type->clientdata = swig_module.type_initial[i]->clientdata;
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
-#endif
-      }
-    } else {
-      type = swig_module.type_initial[i];
-    }
-    
-    /* Insert casting types */
-    cast = swig_module.cast_initial[i];
-    while (cast->type) {
-      /* Don't need to add information already in the list */
-      ret = 0;
-#ifdef SWIGRUNTIME_DEBUG
-      printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
-#endif
-      if (swig_module.next != &swig_module) {
-        ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
-#ifdef SWIGRUNTIME_DEBUG
-        if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
-#endif
-      }
-      if (ret) {
-        if (type == swig_module.type_initial[i]) {
-#ifdef SWIGRUNTIME_DEBUG
-          printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
-#endif
-          cast->type = ret;
-          ret = 0;
-        } else {
-          /* Check for casting already in the list */
-          swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
-#ifdef SWIGRUNTIME_DEBUG
-          if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
-#endif
-          if (!ocast) ret = 0;
-        }
-      }
-      
-      if (!ret) {
-#ifdef SWIGRUNTIME_DEBUG
-        printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
-#endif
-        if (type->cast) {
-          type->cast->prev = cast;
-          cast->next = type->cast;
-        }
-        type->cast = cast;
-      }
-      cast++;
-    }
-    /* Set entry in modules->types array equal to the type */
-    swig_module.types[i] = type;
-  }
-  swig_module.types[i] = 0;
-  
-#ifdef SWIGRUNTIME_DEBUG
-  printf("**** SWIG_InitializeModule: Cast List ******\n");
-  for (i = 0; i < swig_module.size; ++i) {
-    int j = 0;
-    swig_cast_info *cast = swig_module.cast_initial[i];
-    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
-    while (cast->type) {
-      printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
-      cast++;
+SWIGINTERN PyObject *GDT_Float64_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_Float64",SWIG_From_int((int)(GDT_Float64)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GDT_CInt16_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_CInt16",SWIG_From_int((int)(GDT_CInt16)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GDT_CInt32_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_CInt32",SWIG_From_int((int)(GDT_CInt32)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GDT_CFloat32_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_CFloat32",SWIG_From_int((int)(GDT_CFloat32)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GDT_CFloat64_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_CFloat64",SWIG_From_int((int)(GDT_CFloat64)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GDT_TypeCount_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDT_TypeCount",SWIG_From_int((int)(GDT_TypeCount)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GA_ReadOnly_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GA_ReadOnly",SWIG_From_int((int)(GA_ReadOnly)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GA_Update_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GA_Update",SWIG_From_int((int)(GA_Update)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GF_Read_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GF_Read",SWIG_From_int((int)(GF_Read)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GF_Write_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GF_Write",SWIG_From_int((int)(GF_Write)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRIORA_NearestNeighbour_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRIORA_NearestNeighbour",SWIG_From_int((int)(GRIORA_NearestNeighbour)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRIORA_Bilinear_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRIORA_Bilinear",SWIG_From_int((int)(GRIORA_Bilinear)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRIORA_Cubic_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRIORA_Cubic",SWIG_From_int((int)(GRIORA_Cubic)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRIORA_CubicSpline_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRIORA_CubicSpline",SWIG_From_int((int)(GRIORA_CubicSpline)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRIORA_Lanczos_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRIORA_Lanczos",SWIG_From_int((int)(GRIORA_Lanczos)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRIORA_Average_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRIORA_Average",SWIG_From_int((int)(GRIORA_Average)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRIORA_Mode_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRIORA_Mode",SWIG_From_int((int)(GRIORA_Mode)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRIORA_Gauss_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRIORA_Gauss",SWIG_From_int((int)(GRIORA_Gauss)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_Undefined_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_Undefined",SWIG_From_int((int)(GCI_Undefined)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_GrayIndex_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_GrayIndex",SWIG_From_int((int)(GCI_GrayIndex)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_PaletteIndex_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_PaletteIndex",SWIG_From_int((int)(GCI_PaletteIndex)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_RedBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_RedBand",SWIG_From_int((int)(GCI_RedBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_GreenBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_GreenBand",SWIG_From_int((int)(GCI_GreenBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_BlueBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_BlueBand",SWIG_From_int((int)(GCI_BlueBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_AlphaBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_AlphaBand",SWIG_From_int((int)(GCI_AlphaBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_HueBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_HueBand",SWIG_From_int((int)(GCI_HueBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_SaturationBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_SaturationBand",SWIG_From_int((int)(GCI_SaturationBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_LightnessBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_LightnessBand",SWIG_From_int((int)(GCI_LightnessBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_CyanBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_CyanBand",SWIG_From_int((int)(GCI_CyanBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_MagentaBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_MagentaBand",SWIG_From_int((int)(GCI_MagentaBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_YellowBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_YellowBand",SWIG_From_int((int)(GCI_YellowBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_BlackBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_BlackBand",SWIG_From_int((int)(GCI_BlackBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_YCbCr_YBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_YCbCr_YBand",SWIG_From_int((int)(GCI_YCbCr_YBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_YCbCr_CrBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_YCbCr_CrBand",SWIG_From_int((int)(GCI_YCbCr_CrBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GCI_YCbCr_CbBand_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GCI_YCbCr_CbBand",SWIG_From_int((int)(GCI_YCbCr_CbBand)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRA_NearestNeighbour_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRA_NearestNeighbour",SWIG_From_int((int)(GRA_NearestNeighbour)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRA_Bilinear_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRA_Bilinear",SWIG_From_int((int)(GRA_Bilinear)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRA_Cubic_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRA_Cubic",SWIG_From_int((int)(GRA_Cubic)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRA_CubicSpline_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRA_CubicSpline",SWIG_From_int((int)(GRA_CubicSpline)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRA_Lanczos_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRA_Lanczos",SWIG_From_int((int)(GRA_Lanczos)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRA_Average_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRA_Average",SWIG_From_int((int)(GRA_Average)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GRA_Mode_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GRA_Mode",SWIG_From_int((int)(GRA_Mode)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GPI_Gray_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GPI_Gray",SWIG_From_int((int)(GPI_Gray)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GPI_RGB_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GPI_RGB",SWIG_From_int((int)(GPI_RGB)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GPI_CMYK_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GPI_CMYK",SWIG_From_int((int)(GPI_CMYK)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GPI_HLS_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GPI_HLS",SWIG_From_int((int)(GPI_HLS)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CXT_Element_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CXT_Element",SWIG_From_int((int)(CXT_Element)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CXT_Text_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CXT_Text",SWIG_From_int((int)(CXT_Text)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CXT_Attribute_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CXT_Attribute",SWIG_From_int((int)(CXT_Attribute)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CXT_Comment_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CXT_Comment",SWIG_From_int((int)(CXT_Comment)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CXT_Literal_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CXT_Literal",SWIG_From_int((int)(CXT_Literal)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CE_None_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CE_None",SWIG_From_int((int)(CE_None)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CE_Debug_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CE_Debug",SWIG_From_int((int)(CE_Debug)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CE_Warning_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CE_Warning",SWIG_From_int((int)(CE_Warning)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CE_Failure_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CE_Failure",SWIG_From_int((int)(CE_Failure)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CE_Fatal_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CE_Fatal",SWIG_From_int((int)(CE_Fatal)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_None_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_None",SWIG_From_int((int)(CPLE_None)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_AppDefined_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_AppDefined",SWIG_From_int((int)(CPLE_AppDefined)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_OutOfMemory_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_OutOfMemory",SWIG_From_int((int)(CPLE_OutOfMemory)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_FileIO_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_FileIO",SWIG_From_int((int)(CPLE_FileIO)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_OpenFailed_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_OpenFailed",SWIG_From_int((int)(CPLE_OpenFailed)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_IllegalArg_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_IllegalArg",SWIG_From_int((int)(CPLE_IllegalArg)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_NotSupported_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_NotSupported",SWIG_From_int((int)(CPLE_NotSupported)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_AssertionFailed_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_AssertionFailed",SWIG_From_int((int)(CPLE_AssertionFailed)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_NoWriteAccess_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_NoWriteAccess",SWIG_From_int((int)(CPLE_NoWriteAccess)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLE_UserInterrupt_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLE_UserInterrupt",SWIG_From_int((int)(CPLE_UserInterrupt)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OF_ALL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OF_ALL",SWIG_From_int((int)(GDAL_OF_ALL)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OF_RASTER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OF_RASTER",SWIG_From_int((int)(GDAL_OF_RASTER)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OF_VECTOR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OF_VECTOR",SWIG_From_int((int)(GDAL_OF_VECTOR)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OF_GNM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OF_GNM",SWIG_From_int((int)(GDAL_OF_GNM)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OF_READONLY_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OF_READONLY",SWIG_From_int((int)(GDAL_OF_READONLY)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OF_UPDATE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OF_UPDATE",SWIG_From_int((int)(GDAL_OF_UPDATE)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OF_SHARED_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OF_SHARED",SWIG_From_int((int)(GDAL_OF_SHARED)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OF_VERBOSE_ERROR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OF_VERBOSE_ERROR",SWIG_From_int((int)(GDAL_OF_VERBOSE_ERROR)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_LONGNAME_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_LONGNAME",SWIG_FromCharPtr(GDAL_DMD_LONGNAME));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_HELPTOPIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_HELPTOPIC",SWIG_FromCharPtr(GDAL_DMD_HELPTOPIC));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_MIMETYPE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_MIMETYPE",SWIG_FromCharPtr(GDAL_DMD_MIMETYPE));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_EXTENSION_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_EXTENSION",SWIG_FromCharPtr(GDAL_DMD_EXTENSION));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_EXTENSIONS_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_EXTENSIONS",SWIG_FromCharPtr(GDAL_DMD_EXTENSIONS));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_CONNECTION_PREFIX_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_CONNECTION_PREFIX",SWIG_FromCharPtr(GDAL_DMD_CONNECTION_PREFIX));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_CREATIONOPTIONLIST_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_CREATIONOPTIONLIST",SWIG_FromCharPtr(GDAL_DMD_CREATIONOPTIONLIST));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_CREATIONDATATYPES_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_CREATIONDATATYPES",SWIG_FromCharPtr(GDAL_DMD_CREATIONDATATYPES));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_CREATIONFIELDDATATYPES_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_CREATIONFIELDDATATYPES",SWIG_FromCharPtr(GDAL_DMD_CREATIONFIELDDATATYPES));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DMD_SUBDATASETS_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DMD_SUBDATASETS",SWIG_FromCharPtr(GDAL_DMD_SUBDATASETS));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DCAP_OPEN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DCAP_OPEN",SWIG_FromCharPtr(GDAL_DCAP_OPEN));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DCAP_CREATE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DCAP_CREATE",SWIG_FromCharPtr(GDAL_DCAP_CREATE));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DCAP_CREATECOPY_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DCAP_CREATECOPY",SWIG_FromCharPtr(GDAL_DCAP_CREATECOPY));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DCAP_VIRTUALIO_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DCAP_VIRTUALIO",SWIG_FromCharPtr(GDAL_DCAP_VIRTUALIO));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DCAP_RASTER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DCAP_RASTER",SWIG_FromCharPtr(GDAL_DCAP_RASTER));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DCAP_VECTOR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DCAP_VECTOR",SWIG_FromCharPtr(GDAL_DCAP_VECTOR));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DCAP_NOTNULL_FIELDS_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DCAP_NOTNULL_FIELDS",SWIG_FromCharPtr(GDAL_DCAP_NOTNULL_FIELDS));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DCAP_DEFAULT_FIELDS_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DCAP_DEFAULT_FIELDS",SWIG_FromCharPtr(GDAL_DCAP_DEFAULT_FIELDS));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *DCAP_NOTNULL_GEOMFIELDS_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "DCAP_NOTNULL_GEOMFIELDS",SWIG_FromCharPtr(GDAL_DCAP_NOTNULL_GEOMFIELDS));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLES_BackslashQuotable_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLES_BackslashQuotable",SWIG_From_int((int)(CPLES_BackslashQuotable)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLES_XML_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLES_XML",SWIG_From_int((int)(CPLES_XML)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLES_URL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLES_URL",SWIG_From_int((int)(CPLES_URL)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLES_SQL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLES_SQL",SWIG_From_int((int)(CPLES_SQL)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *CPLES_CSV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "CPLES_CSV",SWIG_From_int((int)(CPLES_CSV)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFT_Integer_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFT_Integer",SWIG_From_int((int)(GFT_Integer)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFT_Real_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFT_Real",SWIG_From_int((int)(GFT_Real)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFT_String_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFT_String",SWIG_From_int((int)(GFT_String)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_Generic_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_Generic",SWIG_From_int((int)(GFU_Generic)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_PixelCount_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_PixelCount",SWIG_From_int((int)(GFU_PixelCount)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_Name_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_Name",SWIG_From_int((int)(GFU_Name)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_Min_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_Min",SWIG_From_int((int)(GFU_Min)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_Max_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_Max",SWIG_From_int((int)(GFU_Max)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_MinMax_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_MinMax",SWIG_From_int((int)(GFU_MinMax)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_Red_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_Red",SWIG_From_int((int)(GFU_Red)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_Green_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_Green",SWIG_From_int((int)(GFU_Green)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_Blue_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_Blue",SWIG_From_int((int)(GFU_Blue)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_Alpha_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_Alpha",SWIG_From_int((int)(GFU_Alpha)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_RedMin_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_RedMin",SWIG_From_int((int)(GFU_RedMin)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_GreenMin_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_GreenMin",SWIG_From_int((int)(GFU_GreenMin)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_BlueMin_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_BlueMin",SWIG_From_int((int)(GFU_BlueMin)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_AlphaMin_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_AlphaMin",SWIG_From_int((int)(GFU_AlphaMin)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_RedMax_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_RedMax",SWIG_From_int((int)(GFU_RedMax)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_GreenMax_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_GreenMax",SWIG_From_int((int)(GFU_GreenMax)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_BlueMax_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_BlueMax",SWIG_From_int((int)(GFU_BlueMax)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_AlphaMax_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_AlphaMax",SWIG_From_int((int)(GFU_AlphaMax)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GFU_MaxCount_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GFU_MaxCount",SWIG_From_int((int)(GFU_MaxCount)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GMF_ALL_VALID_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GMF_ALL_VALID",SWIG_From_int((int)(0x01)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GMF_PER_DATASET_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GMF_PER_DATASET",SWIG_From_int((int)(0x02)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GMF_ALPHA_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GMF_ALPHA",SWIG_From_int((int)(0x04)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GMF_NODATA_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GMF_NODATA",SWIG_From_int((int)(0x08)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED",SWIG_From_int((int)(0x01)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GDAL_DATA_COVERAGE_STATUS_DATA_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDAL_DATA_COVERAGE_STATUS_DATA",SWIG_From_int((int)(0x02)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GDAL_DATA_COVERAGE_STATUS_EMPTY_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GDAL_DATA_COVERAGE_STATUS_EMPTY",SWIG_From_int((int)(0x04)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GARIO_PENDING_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GARIO_PENDING",SWIG_From_int((int)(GARIO_PENDING)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GARIO_UPDATE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GARIO_UPDATE",SWIG_From_int((int)(GARIO_UPDATE)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GARIO_ERROR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GARIO_ERROR",SWIG_From_int((int)(GARIO_ERROR)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GARIO_COMPLETE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GARIO_COMPLETE",SWIG_From_int((int)(GARIO_COMPLETE)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GTO_TIP_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GTO_TIP",SWIG_From_int((int)(GTO_TIP)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GTO_BIT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GTO_BIT",SWIG_From_int((int)(GTO_BIT)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GTO_BSQ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GTO_BSQ",SWIG_From_int((int)(GTO_BSQ)));
+  return SWIG_Py_Void();
+}
+
+
+static PyMethodDef SwigMethods[] = {
+	 { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL},
+	 { (char *)"GDT_Unknown_swigconstant", GDT_Unknown_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_Byte_swigconstant", GDT_Byte_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_UInt16_swigconstant", GDT_UInt16_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_Int16_swigconstant", GDT_Int16_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_UInt32_swigconstant", GDT_UInt32_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_Int32_swigconstant", GDT_Int32_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_Float32_swigconstant", GDT_Float32_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_Float64_swigconstant", GDT_Float64_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_CInt16_swigconstant", GDT_CInt16_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_CInt32_swigconstant", GDT_CInt32_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_CFloat32_swigconstant", GDT_CFloat32_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_CFloat64_swigconstant", GDT_CFloat64_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDT_TypeCount_swigconstant", GDT_TypeCount_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GA_ReadOnly_swigconstant", GA_ReadOnly_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GA_Update_swigconstant", GA_Update_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GF_Read_swigconstant", GF_Read_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GF_Write_swigconstant", GF_Write_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRIORA_NearestNeighbour_swigconstant", GRIORA_NearestNeighbour_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRIORA_Bilinear_swigconstant", GRIORA_Bilinear_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRIORA_Cubic_swigconstant", GRIORA_Cubic_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRIORA_CubicSpline_swigconstant", GRIORA_CubicSpline_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRIORA_Lanczos_swigconstant", GRIORA_Lanczos_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRIORA_Average_swigconstant", GRIORA_Average_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRIORA_Mode_swigconstant", GRIORA_Mode_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRIORA_Gauss_swigconstant", GRIORA_Gauss_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_Undefined_swigconstant", GCI_Undefined_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_GrayIndex_swigconstant", GCI_GrayIndex_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_PaletteIndex_swigconstant", GCI_PaletteIndex_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_RedBand_swigconstant", GCI_RedBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_GreenBand_swigconstant", GCI_GreenBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_BlueBand_swigconstant", GCI_BlueBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_AlphaBand_swigconstant", GCI_AlphaBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_HueBand_swigconstant", GCI_HueBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_SaturationBand_swigconstant", GCI_SaturationBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_LightnessBand_swigconstant", GCI_LightnessBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_CyanBand_swigconstant", GCI_CyanBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_MagentaBand_swigconstant", GCI_MagentaBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_YellowBand_swigconstant", GCI_YellowBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_BlackBand_swigconstant", GCI_BlackBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_YCbCr_YBand_swigconstant", GCI_YCbCr_YBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_YCbCr_CrBand_swigconstant", GCI_YCbCr_CrBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GCI_YCbCr_CbBand_swigconstant", GCI_YCbCr_CbBand_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRA_NearestNeighbour_swigconstant", GRA_NearestNeighbour_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRA_Bilinear_swigconstant", GRA_Bilinear_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRA_Cubic_swigconstant", GRA_Cubic_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRA_CubicSpline_swigconstant", GRA_CubicSpline_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRA_Lanczos_swigconstant", GRA_Lanczos_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRA_Average_swigconstant", GRA_Average_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GRA_Mode_swigconstant", GRA_Mode_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GPI_Gray_swigconstant", GPI_Gray_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GPI_RGB_swigconstant", GPI_RGB_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GPI_CMYK_swigconstant", GPI_CMYK_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GPI_HLS_swigconstant", GPI_HLS_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CXT_Element_swigconstant", CXT_Element_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CXT_Text_swigconstant", CXT_Text_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CXT_Attribute_swigconstant", CXT_Attribute_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CXT_Comment_swigconstant", CXT_Comment_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CXT_Literal_swigconstant", CXT_Literal_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CE_None_swigconstant", CE_None_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CE_Debug_swigconstant", CE_Debug_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CE_Warning_swigconstant", CE_Warning_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CE_Failure_swigconstant", CE_Failure_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CE_Fatal_swigconstant", CE_Fatal_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_None_swigconstant", CPLE_None_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_AppDefined_swigconstant", CPLE_AppDefined_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_OutOfMemory_swigconstant", CPLE_OutOfMemory_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_FileIO_swigconstant", CPLE_FileIO_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_OpenFailed_swigconstant", CPLE_OpenFailed_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_IllegalArg_swigconstant", CPLE_IllegalArg_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_NotSupported_swigconstant", CPLE_NotSupported_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_AssertionFailed_swigconstant", CPLE_AssertionFailed_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_NoWriteAccess_swigconstant", CPLE_NoWriteAccess_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLE_UserInterrupt_swigconstant", CPLE_UserInterrupt_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OF_ALL_swigconstant", OF_ALL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OF_RASTER_swigconstant", OF_RASTER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OF_VECTOR_swigconstant", OF_VECTOR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OF_GNM_swigconstant", OF_GNM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OF_READONLY_swigconstant", OF_READONLY_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OF_UPDATE_swigconstant", OF_UPDATE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OF_SHARED_swigconstant", OF_SHARED_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OF_VERBOSE_ERROR_swigconstant", OF_VERBOSE_ERROR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_LONGNAME_swigconstant", DMD_LONGNAME_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_HELPTOPIC_swigconstant", DMD_HELPTOPIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_MIMETYPE_swigconstant", DMD_MIMETYPE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_EXTENSION_swigconstant", DMD_EXTENSION_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_EXTENSIONS_swigconstant", DMD_EXTENSIONS_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_CONNECTION_PREFIX_swigconstant", DMD_CONNECTION_PREFIX_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_CREATIONOPTIONLIST_swigconstant", DMD_CREATIONOPTIONLIST_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_CREATIONDATATYPES_swigconstant", DMD_CREATIONDATATYPES_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_CREATIONFIELDDATATYPES_swigconstant", DMD_CREATIONFIELDDATATYPES_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DMD_SUBDATASETS_swigconstant", DMD_SUBDATASETS_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DCAP_OPEN_swigconstant", DCAP_OPEN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DCAP_CREATE_swigconstant", DCAP_CREATE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DCAP_CREATECOPY_swigconstant", DCAP_CREATECOPY_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DCAP_VIRTUALIO_swigconstant", DCAP_VIRTUALIO_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DCAP_RASTER_swigconstant", DCAP_RASTER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DCAP_VECTOR_swigconstant", DCAP_VECTOR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DCAP_NOTNULL_FIELDS_swigconstant", DCAP_NOTNULL_FIELDS_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DCAP_DEFAULT_FIELDS_swigconstant", DCAP_DEFAULT_FIELDS_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"DCAP_NOTNULL_GEOMFIELDS_swigconstant", DCAP_NOTNULL_GEOMFIELDS_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLES_BackslashQuotable_swigconstant", CPLES_BackslashQuotable_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLES_XML_swigconstant", CPLES_XML_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLES_URL_swigconstant", CPLES_URL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLES_SQL_swigconstant", CPLES_SQL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"CPLES_CSV_swigconstant", CPLES_CSV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFT_Integer_swigconstant", GFT_Integer_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFT_Real_swigconstant", GFT_Real_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFT_String_swigconstant", GFT_String_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_Generic_swigconstant", GFU_Generic_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_PixelCount_swigconstant", GFU_PixelCount_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_Name_swigconstant", GFU_Name_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_Min_swigconstant", GFU_Min_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_Max_swigconstant", GFU_Max_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_MinMax_swigconstant", GFU_MinMax_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_Red_swigconstant", GFU_Red_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_Green_swigconstant", GFU_Green_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_Blue_swigconstant", GFU_Blue_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_Alpha_swigconstant", GFU_Alpha_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_RedMin_swigconstant", GFU_RedMin_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_GreenMin_swigconstant", GFU_GreenMin_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_BlueMin_swigconstant", GFU_BlueMin_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_AlphaMin_swigconstant", GFU_AlphaMin_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_RedMax_swigconstant", GFU_RedMax_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_GreenMax_swigconstant", GFU_GreenMax_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_BlueMax_swigconstant", GFU_BlueMax_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_AlphaMax_swigconstant", GFU_AlphaMax_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GFU_MaxCount_swigconstant", GFU_MaxCount_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GMF_ALL_VALID_swigconstant", GMF_ALL_VALID_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GMF_PER_DATASET_swigconstant", GMF_PER_DATASET_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GMF_ALPHA_swigconstant", GMF_ALPHA_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GMF_NODATA_swigconstant", GMF_NODATA_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED_swigconstant", GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDAL_DATA_COVERAGE_STATUS_DATA_swigconstant", GDAL_DATA_COVERAGE_STATUS_DATA_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GDAL_DATA_COVERAGE_STATUS_EMPTY_swigconstant", GDAL_DATA_COVERAGE_STATUS_EMPTY_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GARIO_PENDING_swigconstant", GARIO_PENDING_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GARIO_UPDATE_swigconstant", GARIO_UPDATE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GARIO_ERROR_swigconstant", GARIO_ERROR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GARIO_COMPLETE_swigconstant", GARIO_COMPLETE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GTO_TIP_swigconstant", GTO_TIP_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GTO_BIT_swigconstant", GTO_BIT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GTO_BSQ_swigconstant", GTO_BSQ_swigconstant, METH_VARARGS, NULL},
+	 { NULL, NULL, 0, NULL }
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
+
+static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0};
+
+static swig_type_info *swig_type_initial[] = {
+  &_swigt__p_char,
+};
+
+static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
+
+static swig_cast_info *swig_cast_initial[] = {
+  _swigc__p_char,
+};
+
+
+/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */
+
+static swig_const_info swig_const_table[] = {
+{0, 0, 0, 0.0, 0, 0}};
+
+#ifdef __cplusplus
+}
+#endif
+/* -----------------------------------------------------------------------------
+ * Type initialization:
+ * This problem is tough by the requirement that no dynamic
+ * memory is used. Also, since swig_type_info structures store pointers to
+ * swig_cast_info structures and swig_cast_info structures store pointers back
+ * to swig_type_info structures, we need some lookup code at initialization.
+ * The idea is that swig generates all the structures that are needed.
+ * The runtime then collects these partially filled structures.
+ * The SWIG_InitializeModule function takes these initial arrays out of
+ * swig_module, and does all the lookup, filling in the swig_module.types
+ * array with the correct data and linking the correct swig_cast_info
+ * structures together.
+ *
+ * The generated swig_type_info structures are assigned statically to an initial
+ * array. We just loop through that array, and handle each type individually.
+ * First we lookup if this type has been already loaded, and if so, use the
+ * loaded structure instead of the generated one. Then we have to fill in the
+ * cast linked list. The cast data is initially stored in something like a
+ * two-dimensional array. Each row corresponds to a type (there are the same
+ * number of rows as there are in the swig_type_initial array). Each entry in
+ * a column is one of the swig_cast_info structures for that type.
+ * The cast_initial array is actually an array of arrays, because each row has
+ * a variable number of columns. So to actually build the cast linked list,
+ * we find the array of casts associated with the type, and loop through it
+ * adding the casts to the list. The one last trick we need to do is making
+ * sure the type pointer in the swig_cast_info struct is correct.
+ *
+ * First off, we lookup the cast->type name to see if it is already loaded.
+ * There are three cases to handle:
+ *  1) If the cast->type has already been loaded AND the type we are adding
+ *     casting info to has not been loaded (it is in this module), THEN we
+ *     replace the cast->type pointer with the type pointer that has already
+ *     been loaded.
+ *  2) If BOTH types (the one we are adding casting info to, and the
+ *     cast->type) are loaded, THEN the cast info has already been loaded by
+ *     the previous module so we just ignore it.
+ *  3) Finally, if cast->type has not already been loaded, then we add that
+ *     swig_cast_info to the linked list (because the cast->type) pointer will
+ *     be correct.
+ * ----------------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* c-mode */
+#endif
+#endif
+
+#if 0
+#define SWIGRUNTIME_DEBUG
+#endif
+
+
+SWIGRUNTIME void
+SWIG_InitializeModule(void *clientdata) {
+  size_t i;
+  swig_module_info *module_head, *iter;
+  int init;
+  
+  /* check to see if the circular list has been setup, if not, set it up */
+  if (swig_module.next==0) {
+    /* Initialize the swig_module */
+    swig_module.type_initial = swig_type_initial;
+    swig_module.cast_initial = swig_cast_initial;
+    swig_module.next = &swig_module;
+    init = 1;
+  } else {
+    init = 0;
+  }
+  
+  /* Try and load any already created modules */
+  module_head = SWIG_GetModule(clientdata);
+  if (!module_head) {
+    /* This is the first module loaded for this interpreter */
+    /* so set the swig module into the interpreter */
+    SWIG_SetModule(clientdata, &swig_module);
+  } else {
+    /* the interpreter has loaded a SWIG module, but has it loaded this one? */
+    iter=module_head;
+    do {
+      if (iter==&swig_module) {
+        /* Our module is already in the list, so there's nothing more to do. */
+        return;
+      }
+      iter=iter->next;
+    } while (iter!= module_head);
+    
+    /* otherwise we must add our module into the list */
+    swig_module.next = module_head->next;
+    module_head->next = &swig_module;
+  }
+  
+  /* When multiple interpreters are used, a module could have already been initialized in
+       a different interpreter, but not yet have a pointer in this interpreter.
+       In this case, we do not want to continue adding types... everything should be
+       set up already */
+  if (init == 0) return;
+  
+  /* Now work on filling in swig_module.types */
+#ifdef SWIGRUNTIME_DEBUG
+  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
+#endif
+  for (i = 0; i < swig_module.size; ++i) {
+    swig_type_info *type = 0;
+    swig_type_info *ret;
+    swig_cast_info *cast;
+    
+#ifdef SWIGRUNTIME_DEBUG
+    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+#endif
+    
+    /* if there is another module already loaded */
+    if (swig_module.next != &swig_module) {
+      type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name);
+    }
+    if (type) {
+      /* Overwrite clientdata field */
+#ifdef SWIGRUNTIME_DEBUG
+      printf("SWIG_InitializeModule: found type %s\n", type->name);
+#endif
+      if (swig_module.type_initial[i]->clientdata) {
+        type->clientdata = swig_module.type_initial[i]->clientdata;
+#ifdef SWIGRUNTIME_DEBUG
+        printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name);
+#endif
+      }
+    } else {
+      type = swig_module.type_initial[i];
+    }
+    
+    /* Insert casting types */
+    cast = swig_module.cast_initial[i];
+    while (cast->type) {
+      /* Don't need to add information already in the list */
+      ret = 0;
+#ifdef SWIGRUNTIME_DEBUG
+      printf("SWIG_InitializeModule: look cast %s\n", cast->type->name);
+#endif
+      if (swig_module.next != &swig_module) {
+        ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name);
+#ifdef SWIGRUNTIME_DEBUG
+        if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name);
+#endif
+      }
+      if (ret) {
+        if (type == swig_module.type_initial[i]) {
+#ifdef SWIGRUNTIME_DEBUG
+          printf("SWIG_InitializeModule: skip old type %s\n", ret->name);
+#endif
+          cast->type = ret;
+          ret = 0;
+        } else {
+          /* Check for casting already in the list */
+          swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type);
+#ifdef SWIGRUNTIME_DEBUG
+          if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name);
+#endif
+          if (!ocast) ret = 0;
+        }
+      }
+      
+      if (!ret) {
+#ifdef SWIGRUNTIME_DEBUG
+        printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name);
+#endif
+        if (type->cast) {
+          type->cast->prev = cast;
+          cast->next = type->cast;
+        }
+        type->cast = cast;
+      }
+      cast++;
+    }
+    /* Set entry in modules->types array equal to the type */
+    swig_module.types[i] = type;
+  }
+  swig_module.types[i] = 0;
+  
+#ifdef SWIGRUNTIME_DEBUG
+  printf("**** SWIG_InitializeModule: Cast List ******\n");
+  for (i = 0; i < swig_module.size; ++i) {
+    int j = 0;
+    swig_cast_info *cast = swig_module.cast_initial[i];
+    printf("SWIG_InitializeModule: type %d %s\n", i, swig_module.type_initial[i]->name);
+    while (cast->type) {
+      printf("SWIG_InitializeModule: cast type %s\n", cast->type->name);
+      cast++;
       ++j;
     }
     printf("---- Total casts: %d\n",j);
@@ -3373,7 +5138,7 @@ extern "C" {
       var = var->next;
     }
     if (res == NULL && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -3390,7 +5155,7 @@ extern "C" {
       var = var->next;
     }
     if (res == 1 && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -3440,10 +5205,19 @@ extern "C" {
         0,                                  /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-        0,                                  /* tp_version */
+        0,                                  /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+        0,                                  /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-        0,0,0,0                             /* tp_alloc -> tp_next */
+        0,                                  /* tp_allocs */
+        0,                                  /* tp_frees */
+        0,                                  /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+        0,                                  /* tp_prev */
+#endif
+        0                                   /* tp_next */
 #endif
       };
       varlink_type = tmp;
@@ -3532,7 +5306,9 @@ extern "C" {
     size_t i;
     for (i = 0; methods[i].ml_name; ++i) {
       const char *c = methods[i].ml_doc;
-      if (c && (c = strstr(c, "swig_ptr: "))) {
+      if (!c) continue;
+      c = strstr(c, "swig_ptr: ");
+      if (c) {
         int j;
         swig_const_info *ci = 0;
         const char *name = c + 10;
@@ -3634,6 +5410,7 @@ SWIG_init(void) {
   PyObject *public_interface, *public_symbol;
   PyObject *this_descr;
   PyObject *thisown_descr;
+  PyObject *self = 0;
   int i;
   
   (void)builtin_pytype;
@@ -3641,6 +5418,7 @@ SWIG_init(void) {
   (void)builtin_basetype;
   (void)tuple;
   (void)static_getset;
+  (void)self;
   
   /* metatype is used to implement static member variables. */
   metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
@@ -3660,6 +5438,7 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
+  
   md = d = PyModule_GetDict(m);
   (void)md;
   
@@ -3703,144 +5482,9 @@ SWIG_init(void) {
   
   SWIG_InstallConstants(d,swig_const_table);
   
-  SWIG_Python_SetConstant(d, "GDT_Unknown",SWIG_From_int((int)(GDT_Unknown)));
-  SWIG_Python_SetConstant(d, "GDT_Byte",SWIG_From_int((int)(GDT_Byte)));
-  SWIG_Python_SetConstant(d, "GDT_UInt16",SWIG_From_int((int)(GDT_UInt16)));
-  SWIG_Python_SetConstant(d, "GDT_Int16",SWIG_From_int((int)(GDT_Int16)));
-  SWIG_Python_SetConstant(d, "GDT_UInt32",SWIG_From_int((int)(GDT_UInt32)));
-  SWIG_Python_SetConstant(d, "GDT_Int32",SWIG_From_int((int)(GDT_Int32)));
-  SWIG_Python_SetConstant(d, "GDT_Float32",SWIG_From_int((int)(GDT_Float32)));
-  SWIG_Python_SetConstant(d, "GDT_Float64",SWIG_From_int((int)(GDT_Float64)));
-  SWIG_Python_SetConstant(d, "GDT_CInt16",SWIG_From_int((int)(GDT_CInt16)));
-  SWIG_Python_SetConstant(d, "GDT_CInt32",SWIG_From_int((int)(GDT_CInt32)));
-  SWIG_Python_SetConstant(d, "GDT_CFloat32",SWIG_From_int((int)(GDT_CFloat32)));
-  SWIG_Python_SetConstant(d, "GDT_CFloat64",SWIG_From_int((int)(GDT_CFloat64)));
-  SWIG_Python_SetConstant(d, "GDT_TypeCount",SWIG_From_int((int)(GDT_TypeCount)));
-  SWIG_Python_SetConstant(d, "GA_ReadOnly",SWIG_From_int((int)(GA_ReadOnly)));
-  SWIG_Python_SetConstant(d, "GA_Update",SWIG_From_int((int)(GA_Update)));
-  SWIG_Python_SetConstant(d, "GF_Read",SWIG_From_int((int)(GF_Read)));
-  SWIG_Python_SetConstant(d, "GF_Write",SWIG_From_int((int)(GF_Write)));
-  SWIG_Python_SetConstant(d, "GRIORA_NearestNeighbour",SWIG_From_int((int)(GRIORA_NearestNeighbour)));
-  SWIG_Python_SetConstant(d, "GRIORA_Bilinear",SWIG_From_int((int)(GRIORA_Bilinear)));
-  SWIG_Python_SetConstant(d, "GRIORA_Cubic",SWIG_From_int((int)(GRIORA_Cubic)));
-  SWIG_Python_SetConstant(d, "GRIORA_CubicSpline",SWIG_From_int((int)(GRIORA_CubicSpline)));
-  SWIG_Python_SetConstant(d, "GRIORA_Lanczos",SWIG_From_int((int)(GRIORA_Lanczos)));
-  SWIG_Python_SetConstant(d, "GRIORA_Average",SWIG_From_int((int)(GRIORA_Average)));
-  SWIG_Python_SetConstant(d, "GRIORA_Mode",SWIG_From_int((int)(GRIORA_Mode)));
-  SWIG_Python_SetConstant(d, "GRIORA_Gauss",SWIG_From_int((int)(GRIORA_Gauss)));
-  SWIG_Python_SetConstant(d, "GCI_Undefined",SWIG_From_int((int)(GCI_Undefined)));
-  SWIG_Python_SetConstant(d, "GCI_GrayIndex",SWIG_From_int((int)(GCI_GrayIndex)));
-  SWIG_Python_SetConstant(d, "GCI_PaletteIndex",SWIG_From_int((int)(GCI_PaletteIndex)));
-  SWIG_Python_SetConstant(d, "GCI_RedBand",SWIG_From_int((int)(GCI_RedBand)));
-  SWIG_Python_SetConstant(d, "GCI_GreenBand",SWIG_From_int((int)(GCI_GreenBand)));
-  SWIG_Python_SetConstant(d, "GCI_BlueBand",SWIG_From_int((int)(GCI_BlueBand)));
-  SWIG_Python_SetConstant(d, "GCI_AlphaBand",SWIG_From_int((int)(GCI_AlphaBand)));
-  SWIG_Python_SetConstant(d, "GCI_HueBand",SWIG_From_int((int)(GCI_HueBand)));
-  SWIG_Python_SetConstant(d, "GCI_SaturationBand",SWIG_From_int((int)(GCI_SaturationBand)));
-  SWIG_Python_SetConstant(d, "GCI_LightnessBand",SWIG_From_int((int)(GCI_LightnessBand)));
-  SWIG_Python_SetConstant(d, "GCI_CyanBand",SWIG_From_int((int)(GCI_CyanBand)));
-  SWIG_Python_SetConstant(d, "GCI_MagentaBand",SWIG_From_int((int)(GCI_MagentaBand)));
-  SWIG_Python_SetConstant(d, "GCI_YellowBand",SWIG_From_int((int)(GCI_YellowBand)));
-  SWIG_Python_SetConstant(d, "GCI_BlackBand",SWIG_From_int((int)(GCI_BlackBand)));
-  SWIG_Python_SetConstant(d, "GCI_YCbCr_YBand",SWIG_From_int((int)(GCI_YCbCr_YBand)));
-  SWIG_Python_SetConstant(d, "GCI_YCbCr_CrBand",SWIG_From_int((int)(GCI_YCbCr_CrBand)));
-  SWIG_Python_SetConstant(d, "GCI_YCbCr_CbBand",SWIG_From_int((int)(GCI_YCbCr_CbBand)));
-  SWIG_Python_SetConstant(d, "GRA_NearestNeighbour",SWIG_From_int((int)(GRA_NearestNeighbour)));
-  SWIG_Python_SetConstant(d, "GRA_Bilinear",SWIG_From_int((int)(GRA_Bilinear)));
-  SWIG_Python_SetConstant(d, "GRA_Cubic",SWIG_From_int((int)(GRA_Cubic)));
-  SWIG_Python_SetConstant(d, "GRA_CubicSpline",SWIG_From_int((int)(GRA_CubicSpline)));
-  SWIG_Python_SetConstant(d, "GRA_Lanczos",SWIG_From_int((int)(GRA_Lanczos)));
-  SWIG_Python_SetConstant(d, "GRA_Average",SWIG_From_int((int)(GRA_Average)));
-  SWIG_Python_SetConstant(d, "GRA_Mode",SWIG_From_int((int)(GRA_Mode)));
-  SWIG_Python_SetConstant(d, "GPI_Gray",SWIG_From_int((int)(GPI_Gray)));
-  SWIG_Python_SetConstant(d, "GPI_RGB",SWIG_From_int((int)(GPI_RGB)));
-  SWIG_Python_SetConstant(d, "GPI_CMYK",SWIG_From_int((int)(GPI_CMYK)));
-  SWIG_Python_SetConstant(d, "GPI_HLS",SWIG_From_int((int)(GPI_HLS)));
-  SWIG_Python_SetConstant(d, "CXT_Element",SWIG_From_int((int)(CXT_Element)));
-  SWIG_Python_SetConstant(d, "CXT_Text",SWIG_From_int((int)(CXT_Text)));
-  SWIG_Python_SetConstant(d, "CXT_Attribute",SWIG_From_int((int)(CXT_Attribute)));
-  SWIG_Python_SetConstant(d, "CXT_Comment",SWIG_From_int((int)(CXT_Comment)));
-  SWIG_Python_SetConstant(d, "CXT_Literal",SWIG_From_int((int)(CXT_Literal)));
-  SWIG_Python_SetConstant(d, "CE_None",SWIG_From_int((int)(CE_None)));
-  SWIG_Python_SetConstant(d, "CE_Debug",SWIG_From_int((int)(CE_Debug)));
-  SWIG_Python_SetConstant(d, "CE_Warning",SWIG_From_int((int)(CE_Warning)));
-  SWIG_Python_SetConstant(d, "CE_Failure",SWIG_From_int((int)(CE_Failure)));
-  SWIG_Python_SetConstant(d, "CE_Fatal",SWIG_From_int((int)(CE_Fatal)));
-  SWIG_Python_SetConstant(d, "CPLE_None",SWIG_From_int((int)(CPLE_None)));
-  SWIG_Python_SetConstant(d, "CPLE_AppDefined",SWIG_From_int((int)(CPLE_AppDefined)));
-  SWIG_Python_SetConstant(d, "CPLE_OutOfMemory",SWIG_From_int((int)(CPLE_OutOfMemory)));
-  SWIG_Python_SetConstant(d, "CPLE_FileIO",SWIG_From_int((int)(CPLE_FileIO)));
-  SWIG_Python_SetConstant(d, "CPLE_OpenFailed",SWIG_From_int((int)(CPLE_OpenFailed)));
-  SWIG_Python_SetConstant(d, "CPLE_IllegalArg",SWIG_From_int((int)(CPLE_IllegalArg)));
-  SWIG_Python_SetConstant(d, "CPLE_NotSupported",SWIG_From_int((int)(CPLE_NotSupported)));
-  SWIG_Python_SetConstant(d, "CPLE_AssertionFailed",SWIG_From_int((int)(CPLE_AssertionFailed)));
-  SWIG_Python_SetConstant(d, "CPLE_NoWriteAccess",SWIG_From_int((int)(CPLE_NoWriteAccess)));
-  SWIG_Python_SetConstant(d, "CPLE_UserInterrupt",SWIG_From_int((int)(CPLE_UserInterrupt)));
-  SWIG_Python_SetConstant(d, "OF_ALL",SWIG_From_int((int)(GDAL_OF_ALL)));
-  SWIG_Python_SetConstant(d, "OF_RASTER",SWIG_From_int((int)(GDAL_OF_RASTER)));
-  SWIG_Python_SetConstant(d, "OF_VECTOR",SWIG_From_int((int)(GDAL_OF_VECTOR)));
-  SWIG_Python_SetConstant(d, "OF_GNM",SWIG_From_int((int)(GDAL_OF_GNM)));
-  SWIG_Python_SetConstant(d, "OF_READONLY",SWIG_From_int((int)(GDAL_OF_READONLY)));
-  SWIG_Python_SetConstant(d, "OF_UPDATE",SWIG_From_int((int)(GDAL_OF_UPDATE)));
-  SWIG_Python_SetConstant(d, "OF_SHARED",SWIG_From_int((int)(GDAL_OF_SHARED)));
-  SWIG_Python_SetConstant(d, "OF_VERBOSE_ERROR",SWIG_From_int((int)(GDAL_OF_VERBOSE_ERROR)));
-  SWIG_Python_SetConstant(d, "DMD_LONGNAME",SWIG_FromCharPtr(GDAL_DMD_LONGNAME));
-  SWIG_Python_SetConstant(d, "DMD_HELPTOPIC",SWIG_FromCharPtr(GDAL_DMD_HELPTOPIC));
-  SWIG_Python_SetConstant(d, "DMD_MIMETYPE",SWIG_FromCharPtr(GDAL_DMD_MIMETYPE));
-  SWIG_Python_SetConstant(d, "DMD_EXTENSION",SWIG_FromCharPtr(GDAL_DMD_EXTENSION));
-  SWIG_Python_SetConstant(d, "DMD_EXTENSIONS",SWIG_FromCharPtr(GDAL_DMD_EXTENSIONS));
-  SWIG_Python_SetConstant(d, "DMD_CONNECTION_PREFIX",SWIG_FromCharPtr(GDAL_DMD_CONNECTION_PREFIX));
-  SWIG_Python_SetConstant(d, "DMD_CREATIONOPTIONLIST",SWIG_FromCharPtr(GDAL_DMD_CREATIONOPTIONLIST));
-  SWIG_Python_SetConstant(d, "DMD_CREATIONDATATYPES",SWIG_FromCharPtr(GDAL_DMD_CREATIONDATATYPES));
-  SWIG_Python_SetConstant(d, "DMD_CREATIONFIELDDATATYPES",SWIG_FromCharPtr(GDAL_DMD_CREATIONFIELDDATATYPES));
-  SWIG_Python_SetConstant(d, "DMD_SUBDATASETS",SWIG_FromCharPtr(GDAL_DMD_SUBDATASETS));
-  SWIG_Python_SetConstant(d, "DCAP_OPEN",SWIG_FromCharPtr(GDAL_DCAP_OPEN));
-  SWIG_Python_SetConstant(d, "DCAP_CREATE",SWIG_FromCharPtr(GDAL_DCAP_CREATE));
-  SWIG_Python_SetConstant(d, "DCAP_CREATECOPY",SWIG_FromCharPtr(GDAL_DCAP_CREATECOPY));
-  SWIG_Python_SetConstant(d, "DCAP_VIRTUALIO",SWIG_FromCharPtr(GDAL_DCAP_VIRTUALIO));
-  SWIG_Python_SetConstant(d, "DCAP_RASTER",SWIG_FromCharPtr(GDAL_DCAP_RASTER));
-  SWIG_Python_SetConstant(d, "DCAP_VECTOR",SWIG_FromCharPtr(GDAL_DCAP_VECTOR));
-  SWIG_Python_SetConstant(d, "DCAP_NOTNULL_FIELDS",SWIG_FromCharPtr(GDAL_DCAP_NOTNULL_FIELDS));
-  SWIG_Python_SetConstant(d, "DCAP_DEFAULT_FIELDS",SWIG_FromCharPtr(GDAL_DCAP_DEFAULT_FIELDS));
-  SWIG_Python_SetConstant(d, "DCAP_NOTNULL_GEOMFIELDS",SWIG_FromCharPtr(GDAL_DCAP_NOTNULL_GEOMFIELDS));
-  SWIG_Python_SetConstant(d, "CPLES_BackslashQuotable",SWIG_From_int((int)(CPLES_BackslashQuotable)));
-  SWIG_Python_SetConstant(d, "CPLES_XML",SWIG_From_int((int)(CPLES_XML)));
-  SWIG_Python_SetConstant(d, "CPLES_URL",SWIG_From_int((int)(CPLES_URL)));
-  SWIG_Python_SetConstant(d, "CPLES_SQL",SWIG_From_int((int)(CPLES_SQL)));
-  SWIG_Python_SetConstant(d, "CPLES_CSV",SWIG_From_int((int)(CPLES_CSV)));
-  SWIG_Python_SetConstant(d, "GFT_Integer",SWIG_From_int((int)(GFT_Integer)));
-  SWIG_Python_SetConstant(d, "GFT_Real",SWIG_From_int((int)(GFT_Real)));
-  SWIG_Python_SetConstant(d, "GFT_String",SWIG_From_int((int)(GFT_String)));
-  SWIG_Python_SetConstant(d, "GFU_Generic",SWIG_From_int((int)(GFU_Generic)));
-  SWIG_Python_SetConstant(d, "GFU_PixelCount",SWIG_From_int((int)(GFU_PixelCount)));
-  SWIG_Python_SetConstant(d, "GFU_Name",SWIG_From_int((int)(GFU_Name)));
-  SWIG_Python_SetConstant(d, "GFU_Min",SWIG_From_int((int)(GFU_Min)));
-  SWIG_Python_SetConstant(d, "GFU_Max",SWIG_From_int((int)(GFU_Max)));
-  SWIG_Python_SetConstant(d, "GFU_MinMax",SWIG_From_int((int)(GFU_MinMax)));
-  SWIG_Python_SetConstant(d, "GFU_Red",SWIG_From_int((int)(GFU_Red)));
-  SWIG_Python_SetConstant(d, "GFU_Green",SWIG_From_int((int)(GFU_Green)));
-  SWIG_Python_SetConstant(d, "GFU_Blue",SWIG_From_int((int)(GFU_Blue)));
-  SWIG_Python_SetConstant(d, "GFU_Alpha",SWIG_From_int((int)(GFU_Alpha)));
-  SWIG_Python_SetConstant(d, "GFU_RedMin",SWIG_From_int((int)(GFU_RedMin)));
-  SWIG_Python_SetConstant(d, "GFU_GreenMin",SWIG_From_int((int)(GFU_GreenMin)));
-  SWIG_Python_SetConstant(d, "GFU_BlueMin",SWIG_From_int((int)(GFU_BlueMin)));
-  SWIG_Python_SetConstant(d, "GFU_AlphaMin",SWIG_From_int((int)(GFU_AlphaMin)));
-  SWIG_Python_SetConstant(d, "GFU_RedMax",SWIG_From_int((int)(GFU_RedMax)));
-  SWIG_Python_SetConstant(d, "GFU_GreenMax",SWIG_From_int((int)(GFU_GreenMax)));
-  SWIG_Python_SetConstant(d, "GFU_BlueMax",SWIG_From_int((int)(GFU_BlueMax)));
-  SWIG_Python_SetConstant(d, "GFU_AlphaMax",SWIG_From_int((int)(GFU_AlphaMax)));
-  SWIG_Python_SetConstant(d, "GFU_MaxCount",SWIG_From_int((int)(GFU_MaxCount)));
-  SWIG_Python_SetConstant(d, "GMF_ALL_VALID",SWIG_From_int((int)(0x01)));
-  SWIG_Python_SetConstant(d, "GMF_PER_DATASET",SWIG_From_int((int)(0x02)));
-  SWIG_Python_SetConstant(d, "GMF_ALPHA",SWIG_From_int((int)(0x04)));
-  SWIG_Python_SetConstant(d, "GMF_NODATA",SWIG_From_int((int)(0x08)));
-  SWIG_Python_SetConstant(d, "GARIO_PENDING",SWIG_From_int((int)(GARIO_PENDING)));
-  SWIG_Python_SetConstant(d, "GARIO_UPDATE",SWIG_From_int((int)(GARIO_UPDATE)));
-  SWIG_Python_SetConstant(d, "GARIO_ERROR",SWIG_From_int((int)(GARIO_ERROR)));
-  SWIG_Python_SetConstant(d, "GARIO_COMPLETE",SWIG_From_int((int)(GARIO_COMPLETE)));
-  SWIG_Python_SetConstant(d, "GTO_TIP",SWIG_From_int((int)(GTO_TIP)));
-  SWIG_Python_SetConstant(d, "GTO_BIT",SWIG_From_int((int)(GTO_BIT)));
-  SWIG_Python_SetConstant(d, "GTO_BSQ",SWIG_From_int((int)(GTO_BSQ)));
+  
+  /* Initialize threading */
+  SWIG_PYTHON_INITIALIZE_THREADS;
 #if PY_VERSION_HEX >= 0x03000000
   return m;
 #else
diff --git a/swig/python/extensions/gnm_wrap.cpp b/swig/python/extensions/gnm_wrap.cpp
index c482d1d..2ac91a0 100644
--- a/swig/python/extensions/gnm_wrap.cpp
+++ b/swig/python/extensions/gnm_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
+ * Version 3.0.8
  *
  * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -8,8 +8,13 @@
  * interface file instead.
  * ----------------------------------------------------------------------------- */
 
+
+#ifndef SWIGPYTHON
 #define SWIGPYTHON
 #define SED_HACKS
+#endif
+
+#define SWIG_PYTHON_THREADS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 
@@ -144,6 +149,19 @@ template <typename T> T SwigValueInit() {
 # define _SCL_SECURE_NO_DEPRECATE
 #endif
 
+/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
+#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
+# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
+/* Intel's compiler complains if a variable which was never initialised is
+ * cast to void, which is a common idiom which we use to indicate that we
+ * are aware a variable isn't used.  So we just silence that warning.
+ * See: https://github.com/swig/swig/issues/192 for more discussion.
+ */
+#ifdef __INTEL_COMPILER
+# pragma warning disable 592
+#endif
 
 
 #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
@@ -561,14 +579,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   swig_module_info *iter = start;
   do {
     if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
+      size_t l = 0;
+      size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
+	size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
-	  register int compare = strcmp(name, iname);
+	  int compare = strcmp(name, iname);
 	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
@@ -612,7 +630,7 @@ SWIG_TypeQueryModule(swig_module_info *start,
        of the str field (the human readable name) */
     swig_module_info *iter = start;
     do {
-      register size_t i = 0;
+      size_t i = 0;
       for (; i < iter->size; ++i) {
 	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
 	  return iter->types[i];
@@ -631,10 +649,10 @@ SWIG_TypeQueryModule(swig_module_info *start,
 SWIGRUNTIME char *
 SWIG_PackData(char *c, void *ptr, size_t sz) {
   static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
+  const unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu =  u + sz;
   for (; u != eu; ++u) {
-    register unsigned char uu = *u;
+    unsigned char uu = *u;
     *(c++) = hex[(uu & 0xf0) >> 4];
     *(c++) = hex[uu & 0xf];
   }
@@ -646,11 +664,11 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
 */
 SWIGRUNTIME const char *
 SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
+  unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu = u + sz;
   for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
+    char d = *(c++);
+    unsigned char uu;
     if ((d >= '0') && (d <= '9'))
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
@@ -1313,7 +1331,7 @@ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
 
 /* Unpack the argument tuple */
 
-SWIGINTERN int
+SWIGINTERN Py_ssize_t
 SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
 {
   if (!args) {
@@ -1327,7 +1345,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
   }  
   if (!PyTuple_Check(args)) {
     if (min <= 1 && max >= 1) {
-      register int i;
+      Py_ssize_t i;
       objs[0] = args;
       for (i = 1; i < max; ++i) {
 	objs[i] = 0;
@@ -1337,7 +1355,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
-    register Py_ssize_t l = PyTuple_GET_SIZE(args);
+    Py_ssize_t l = PyTuple_GET_SIZE(args);
     if (l < min) {
       PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
 		   name, (min == max ? "" : "at least "), (int)min, (int)l);
@@ -1347,7 +1365,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 		   name, (min == max ? "" : "at most "), (int)max, (int)l);
       return 0;
     } else {
-      register int i;
+      Py_ssize_t i;
       for (i = 0; i < l; ++i) {
 	objs[i] = PyTuple_GET_ITEM(args, i);
       }
@@ -1533,6 +1551,23 @@ typedef struct {
 #endif
 } SwigPyObject;
 
+
+#ifdef SWIGPYTHON_BUILTIN
+
+SWIGRUNTIME PyObject *
+SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+
+  if (!sobj->dict)
+    sobj->dict = PyDict_New();
+
+  Py_INCREF(sobj->dict);
+  return sobj->dict;
+}
+
+#endif
+
 SWIGRUNTIME PyObject *
 SwigPyObject_long(SwigPyObject *v)
 {
@@ -1671,16 +1706,32 @@ SwigPyObject_dealloc(PyObject *v)
     if (destroy) {
       /* destroy is always a VARARGS method */
       PyObject *res;
+
+      /* PyObject_CallFunction() has the potential to silently drop
+         the active active exception.  In cases of unnamed temporary
+         variable or where we just finished iterating over a generator
+         StopIteration will be active right now, and this needs to
+         remain true upon return from SwigPyObject_dealloc.  So save
+         and restore. */
+      
+      PyObject *val = NULL, *type = NULL, *tb = NULL;
+      PyErr_Fetch(&val, &type, &tb);
+
       if (data->delargs) {
-	/* we need to create a temporary object to carry the destroy operation */
-	PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
-	res = SWIG_Python_CallFunctor(destroy, tmp);
-	Py_DECREF(tmp);
+        /* we need to create a temporary object to carry the destroy operation */
+        PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
+        res = SWIG_Python_CallFunctor(destroy, tmp);
+        Py_DECREF(tmp);
       } else {
-	PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
-	PyObject *mself = PyCFunction_GET_SELF(destroy);
-	res = ((*meth)(mself, v));
+        PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+        PyObject *mself = PyCFunction_GET_SELF(destroy);
+        res = ((*meth)(mself, v));
       }
+      if (!res)
+        PyErr_WriteUnraisable(destroy);
+
+      PyErr_Restore(val, type, tb);
+
       Py_XDECREF(res);
     } 
 #if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
@@ -1704,6 +1755,7 @@ SwigPyObject_append(PyObject* v, PyObject* next)
   next = tmp;
 #endif
   if (!SwigPyObject_Check(next)) {
+    PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject");
     return NULL;
   }
   sobj->next = next;
@@ -1803,7 +1855,7 @@ swigobject_methods[] = {
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_VARARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS,  (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_VARARGS,  (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_VARARGS,  (char *)"returns the next 'this' object"},
@@ -1859,7 +1911,9 @@ SwigPyObject_TypeOnce(void) {
     (unaryfunc)SwigPyObject_oct,  /*nb_oct*/
     (unaryfunc)SwigPyObject_hex,  /*nb_hex*/
 #endif
-#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */
+#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
 #elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
@@ -1939,10 +1993,19 @@ SwigPyObject_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpyobject_type = tmp;
@@ -2118,10 +2181,19 @@ SwigPyPacked_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpypacked_type = tmp;
@@ -2462,7 +2534,7 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
     }
   } else {
 #if PY_VERSION_HEX >= 0x03000000
-    inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
+    inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
     if (inst) {
       PyObject_SetAttr(inst, SWIG_This(), swig_this);
       Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
@@ -2572,18 +2644,21 @@ SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int f
 	  newobj = (SwigPyObject *) newobj->next;
         newobj->next = next_self;
         newobj = (SwigPyObject *)next_self;
+#ifdef SWIGPYTHON_BUILTIN
+        newobj->dict = 0;
+#endif
       }
     } else {
       newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
     }
     if (newobj) {
       newobj->ptr = ptr;
       newobj->ty = type;
       newobj->own = own;
       newobj->next = 0;
-#ifdef SWIGPYTHON_BUILTIN
-      newobj->dict = 0;
-#endif
       return (PyObject*) newobj;
     }
     return SWIG_Py_Void();
@@ -2646,13 +2721,11 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 {
   PyObject *dict;
   if (!PyModule_Check(m)) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs module as first arg");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg");
     return SWIG_ERROR;
   }
   if (!o) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs non-NULL value");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value");
     return SWIG_ERROR;
   }
   
@@ -2943,15 +3016,16 @@ SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) {
 #define SWIGTYPE_p_GNMGenericNetworkShadow swig_types[2]
 #define SWIGTYPE_p_GNMGraphAlgorithmType swig_types[3]
 #define SWIGTYPE_p_GNMNetworkShadow swig_types[4]
-#define SWIGTYPE_p_OGRFeatureShadow swig_types[5]
-#define SWIGTYPE_p_OGRLayerShadow swig_types[6]
-#define SWIGTYPE_p_OGRwkbGeometryType swig_types[7]
-#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[8]
-#define SWIGTYPE_p_char swig_types[9]
-#define SWIGTYPE_p_int swig_types[10]
-#define SWIGTYPE_p_p_char swig_types[11]
-static swig_type_info *swig_types[13];
-static swig_module_info swig_module = {swig_types, 12, 0, 0, 0, 0};
+#define SWIGTYPE_p_OGRDataSourceShadow swig_types[5]
+#define SWIGTYPE_p_OGRDriverShadow swig_types[6]
+#define SWIGTYPE_p_OGRFeatureShadow swig_types[7]
+#define SWIGTYPE_p_OGRLayerShadow swig_types[8]
+#define SWIGTYPE_p_OSRSpatialReferenceShadow swig_types[9]
+#define SWIGTYPE_p_char swig_types[10]
+#define SWIGTYPE_p_int swig_types[11]
+#define SWIGTYPE_p_p_char swig_types[12]
+static swig_type_info *swig_types[14];
+static swig_module_info swig_module = {swig_types, 13, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -2975,7 +3049,7 @@ static swig_module_info swig_module = {swig_types, 12, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_gnm"
 
-#define SWIGVERSION 0x020012 
+#define SWIGVERSION 0x030008 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -2998,27 +3072,35 @@ namespace swig {
 
     SwigPtr_PyObject(const SwigPtr_PyObject& item) : _obj(item._obj)
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(_obj);      
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     SwigPtr_PyObject(PyObject *obj, bool initial_ref = true) :_obj(obj)
     {
       if (initial_ref) {
+        SWIG_PYTHON_THREAD_BEGIN_BLOCK;
         Py_XINCREF(_obj);
+        SWIG_PYTHON_THREAD_END_BLOCK;
       }
     }
     
     SwigPtr_PyObject & operator=(const SwigPtr_PyObject& item) 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(item._obj);
       Py_XDECREF(_obj);
       _obj = item._obj;
+      SWIG_PYTHON_THREAD_END_BLOCK;
       return *this;      
     }
     
     ~SwigPtr_PyObject() 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XDECREF(_obj);
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     operator PyObject *() const
@@ -3048,23 +3130,50 @@ namespace swig {
 }
 
 
+#include <iostream>
+using namespace std;
+
 #include "gdal.h"
+#include "ogr_api.h"
+#include "ogr_p.h"
+#include "ogr_core.h"
+#include "cpl_port.h"
+#include "cpl_string.h"
+#include "ogr_srs_api.h"
 #include "gnm_api.h"
 
 typedef void GDALMajorObjectShadow;
 typedef void GNMNetworkShadow;
 typedef void GNMGenericNetworkShadow;
 
-
 #ifdef DEBUG
+typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
+typedef struct OGRDriverHS OGRDriverShadow;
+typedef struct OGRDataSourceHS OGRDataSourceShadow;
+#endif
 typedef struct OGRLayerHS OGRLayerShadow;
 typedef struct OGRFeatureHS OGRFeatureShadow;
-typedef struct OGRSpatialReferenceHS OSRSpatialReferenceShadow;
+typedef struct OGRFeatureDefnHS OGRFeatureDefnShadow;
+typedef struct OGRGeometryHS OGRGeometryShadow;
+typedef struct OGRCoordinateTransformationHS OSRCoordinateTransformationShadow;
+typedef struct OGRCoordinateTransformationHS OGRCoordinateTransformationShadow;
+typedef struct OGRFieldDefnHS OGRFieldDefnShadow;
 #else
+typedef void OSRSpatialReferenceShadow;
+#ifndef SWIGPERL
+typedef void OGRDriverShadow;
+typedef void OGRDataSourceShadow;
+#endif
 typedef void OGRLayerShadow;
 typedef void OGRFeatureShadow;
-typedef void OSRSpatialReferenceShadow;
+typedef void OGRFeatureDefnShadow;
+typedef void OGRGeometryShadow;
+typedef void OSRCoordinateTransformationShadow;
+typedef void OGRFieldDefnShadow;
 #endif
+typedef struct OGRStyleTableHS OGRStyleTableShadow;
+typedef struct OGRGeomFieldDefnHS OGRGeomFieldDefnShadow;
 
 
 static int bUseExceptions=0;
@@ -3216,10 +3325,34 @@ static void GDALPythonFreeCStr(void* ptr, int bToFree)
 }
 
 
-SWIGINTERN char const *GDALMajorObjectShadow_GetDescription(GDALMajorObjectShadow *self){
-    return GDALGetDescription( self );
+
+#include "gdal.h"
+
+
+  GNMNetworkShadow* CastToNetwork(GDALMajorObjectShadow* base) {
+      return (GNMNetworkShadow*)dynamic_cast<GNMNetwork*>((GDALMajorObject*)base);
+  }
+
+
+  GNMGenericNetworkShadow* CastToGenericNetwork(GDALMajorObjectShadow* base) {
+      return (GNMGenericNetworkShadow*)dynamic_cast<GNMGenericNetwork*>((GDALMajorObject*)base);
   }
 
+SWIGINTERN void delete_GNMNetworkShadow(GNMNetworkShadow *self){
+            if ( GDALDereferenceDataset( self ) <= 0 ) {
+              GDALClose(self);
+            }
+        }
+SWIGINTERN void GNMNetworkShadow_ReleaseResultSet(GNMNetworkShadow *self,OGRLayerShadow *layer){
+            GDALDatasetReleaseResultSet(self, layer);
+        }
+SWIGINTERN int GNMNetworkShadow_GetVersion(GNMNetworkShadow *self){
+            return GNMGetVersion(self);
+        }
+SWIGINTERN char const *GNMNetworkShadow_GetName(GNMNetworkShadow *self){
+            return GNMGetName(self);
+        }
+
 SWIGINTERN swig_type_info*
 SWIG_pchar_descriptor(void)
 {
@@ -3243,9 +3376,13 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
 	SWIG_InternalNewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
     } else {
 #if PY_VERSION_HEX >= 0x03000000
-      return PyUnicode_FromStringAndSize(carray, static_cast< int >(size));
+#if PY_VERSION_HEX >= 0x03010000
+      return PyUnicode_DecodeUTF8(carray, static_cast< Py_ssize_t >(size), "surrogateescape");
 #else
-      return PyString_FromStringAndSize(carray, static_cast< int >(size));
+      return PyUnicode_FromStringAndSize(carray, static_cast< Py_ssize_t >(size));
+#endif
+#else
+      return PyString_FromStringAndSize(carray, static_cast< Py_ssize_t >(size));
 #endif
     }
   } else {
@@ -3260,139 +3397,6 @@ SWIG_FromCharPtr(const char *cptr)
   return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0));
 }
 
-
-SWIGINTERN int
-SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
-{
-#if PY_VERSION_HEX>=0x03000000
-  if (PyUnicode_Check(obj))
-#else  
-  if (PyString_Check(obj))
-#endif
-  {
-    char *cstr; Py_ssize_t len;
-#if PY_VERSION_HEX>=0x03000000
-    if (!alloc && cptr) {
-        /* We can't allow converting without allocation, since the internal
-           representation of string in Python 3 is UCS-2/UCS-4 but we require
-           a UTF-8 representation.
-           TODO(bhy) More detailed explanation */
-        return SWIG_RuntimeError;
-    }
-    obj = PyUnicode_AsUTF8String(obj);
-    PyBytes_AsStringAndSize(obj, &cstr, &len);
-    if(alloc) *alloc = SWIG_NEWOBJ;
-#else
-    PyString_AsStringAndSize(obj, &cstr, &len);
-#endif
-    if (cptr) {
-      if (alloc) {
-	/* 
-	   In python the user should not be able to modify the inner
-	   string representation. To warranty that, if you define
-	   SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string
-	   buffer is always returned.
-
-	   The default behavior is just to return the pointer value,
-	   so, be careful.
-	*/ 
-#if defined(SWIG_PYTHON_SAFE_CSTRINGS)
-	if (*alloc != SWIG_OLDOBJ) 
-#else
-	if (*alloc == SWIG_NEWOBJ) 
-#endif
-	  {
-	    *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
-	    *alloc = SWIG_NEWOBJ;
-	  }
-	else {
-	  *cptr = cstr;
-	  *alloc = SWIG_OLDOBJ;
-	}
-      } else {
-        #if PY_VERSION_HEX>=0x03000000
-        assert(0); /* Should never reach here in Python 3 */
-        #endif
-	*cptr = SWIG_Python_str_AsChar(obj);
-      }
-    }
-    if (psize) *psize = len + 1;
-#if PY_VERSION_HEX>=0x03000000
-    Py_XDECREF(obj);
-#endif
-    return SWIG_OK;
-  } else {
-    swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
-    if (pchar_descriptor) {
-      void* vptr = 0;
-      if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) {
-	if (cptr) *cptr = (char *) vptr;
-	if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0;
-	if (alloc) *alloc = SWIG_OLDOBJ;
-	return SWIG_OK;
-      }
-    }
-  }
-  return SWIG_TypeError;
-}
-
-
-
-
-SWIGINTERN void GDALMajorObjectShadow_SetDescription(GDALMajorObjectShadow *self,char const *pszNewDesc){
-    GDALSetDescription( self, pszNewDesc );
-  }
-SWIGINTERN char **GDALMajorObjectShadow_GetMetadataDomainList(GDALMajorObjectShadow *self){
-    return GDALGetMetadataDomainList( self );
-  }
-SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_Dict(GDALMajorObjectShadow *self,char const *pszDomain=""){
-    return GDALGetMetadata( self, pszDomain );
-  }
-SWIGINTERN char **GDALMajorObjectShadow_GetMetadata_List(GDALMajorObjectShadow *self,char const *pszDomain=""){
-    return GDALGetMetadata( self, pszDomain );
-  }
-SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_0(GDALMajorObjectShadow *self,char **papszMetadata,char const *pszDomain=""){
-    return GDALSetMetadata( self, papszMetadata, pszDomain );
-  }
-SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadata__SWIG_1(GDALMajorObjectShadow *self,char *pszMetadataString,char const *pszDomain=""){
-    char *tmpList[2];
-    tmpList[0] = pszMetadataString;
-    tmpList[1] = 0;
-    return GDALSetMetadata( self, tmpList, pszDomain );
-  }
-SWIGINTERN char const *GDALMajorObjectShadow_GetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszDomain=""){
-    return GDALGetMetadataItem( self, pszName, pszDomain);
-  }
-SWIGINTERN CPLErr GDALMajorObjectShadow_SetMetadataItem(GDALMajorObjectShadow *self,char const *pszName,char const *pszValue,char const *pszDomain=""){
-    return GDALSetMetadataItem( self, pszName, pszValue, pszDomain);
-  }
-
-  GNMNetworkShadow* CastToNetwork(GDALMajorObjectShadow* base) {
-      return (GNMNetworkShadow*)dynamic_cast<GNMNetwork*>((GDALMajorObject*)base);
-  }
-
-
-  GNMGenericNetworkShadow* CastToGenericNetwork(GDALMajorObjectShadow* base) {
-      return (GNMGenericNetworkShadow*)dynamic_cast<GNMGenericNetwork*>((GDALMajorObject*)base);
-  }
-
-
-typedef char retStringAndCPLFree;
-
-SWIGINTERN void delete_GNMNetworkShadow(GNMNetworkShadow *self){
-            if ( GDALDereferenceDataset( self ) <= 0 ) {
-              GDALClose(self);
-            }
-        }
-SWIGINTERN void GNMNetworkShadow_ReleaseResultSet(GNMNetworkShadow *self,OGRLayerShadow *layer){
-            GDALDatasetReleaseResultSet(self, layer);
-        }
-SWIGINTERN int GNMNetworkShadow_GetVersion(GNMNetworkShadow *self){
-            return GNMGetVersion(self);
-        }
-SWIGINTERN char const *GNMNetworkShadow_GetName(GNMNetworkShadow *self){
-            return GNMGetName(self);
-        }
 SWIGINTERN OGRFeatureShadow *GNMNetworkShadow_GetFeatureByGlobalFID(GNMNetworkShadow *self,GIntBig GFID){
             return GNMGetFeatureByGlobalFID(self, GFID);
         }
@@ -3414,9 +3418,11 @@ SWIG_AsVal_double (PyObject *obj, double *val)
   if (PyFloat_Check(obj)) {
     if (val) *val = PyFloat_AsDouble(obj);
     return SWIG_OK;
+#if PY_VERSION_HEX < 0x03000000
   } else if (PyInt_Check(obj)) {
     if (val) *val = PyInt_AsLong(obj);
     return SWIG_OK;
+#endif
   } else if (PyLong_Check(obj)) {
     double v = PyLong_AsDouble(obj);
     if (!PyErr_Occurred()) {
@@ -3490,16 +3496,20 @@ SWIG_CanCastAsInteger(double *d, double min, double max) {
 SWIGINTERN int
 SWIG_AsVal_long (PyObject *obj, long* val)
 {
+#if PY_VERSION_HEX < 0x03000000
   if (PyInt_Check(obj)) {
     if (val) *val = PyInt_AsLong(obj);
     return SWIG_OK;
-  } else if (PyLong_Check(obj)) {
+  } else
+#endif
+  if (PyLong_Check(obj)) {
     long v = PyLong_AsLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_OK;
     } else {
       PyErr_Clear();
+      return SWIG_OverflowError;
     }
   }
 #ifdef SWIG_PYTHON_CAST_MODE
@@ -3556,75 +3566,177 @@ SWIGINTERN char const *GNMNetworkShadow_GetProjectionRef(GNMNetworkShadow *self)
 SWIGINTERN char **GNMNetworkShadow_GetFileList(GNMNetworkShadow *self){
             return GDALGetFileList( self );
         }
-SWIGINTERN OGRLayerShadow *GNMNetworkShadow_CreateLayer(GNMNetworkShadow *self,char const *name,OSRSpatialReferenceShadow *srs=NULL,OGRwkbGeometryType geom_type=wkbUnknown,char **options=0){
-            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCreateLayer( self,
-                                      name,
-                                      srs,
-                                      geom_type,
-                                      options);
-            return layer;
-        }
-SWIGINTERN OGRLayerShadow *GNMNetworkShadow_CopyLayer(GNMNetworkShadow *self,OGRLayerShadow *src_layer,char const *new_name,char **options=0){
-            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCopyLayer( self,
-                                                      src_layer,
-                                                      new_name,
-                                                      options);
-            return layer;
-        }
-SWIGINTERN OGRErr GNMNetworkShadow_DeleteLayer(GNMNetworkShadow *self,int index){
-            return GDALDatasetDeleteLayer(self, index);
-        }
-
-
-#include "ogr_core.h"
-static char const *
-OGRErrMessages( int rc ) {
-  switch( rc ) {
-  case OGRERR_NONE:
-    return "OGR Error: None";
-  case OGRERR_NOT_ENOUGH_DATA:
-    return "OGR Error: Not enough data to deserialize";
-  case OGRERR_NOT_ENOUGH_MEMORY:
-    return "OGR Error: Not enough memory";
-  case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
-    return "OGR Error: Unsupported geometry type";
-  case OGRERR_UNSUPPORTED_OPERATION:
-    return "OGR Error: Unsupported operation";
-  case OGRERR_CORRUPT_DATA:
-    return "OGR Error: Corrupt data";
-  case OGRERR_FAILURE:
-    return "OGR Error: General Error";
-  case OGRERR_UNSUPPORTED_SRS:
-    return "OGR Error: Unsupported SRS";
-  case OGRERR_INVALID_HANDLE:
-    return "OGR Error: Invalid handle";
-  case OGRERR_NON_EXISTING_FEATURE:
-    return "OGR Error: Non existing feature";
-  default:
-    return "OGR Error: Unknown";
-  }
-}
-
-SWIGINTERN int GNMNetworkShadow_GetLayerCount(GNMNetworkShadow *self){
-            return GDALDatasetGetLayerCount(self);
-        }
-SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetLayerByIndex(GNMNetworkShadow *self,int index=0){
-        
-        OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetGetLayer(self,
-                                                                      index);
-            return layer;
-        }
-SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetLayerByName(GNMNetworkShadow *self,char const *layer_name){
-            OGRLayerShadow* layer =
-                  (OGRLayerShadow*) GDALDatasetGetLayerByName(self, layer_name);
-            return layer;
-        }
-SWIGINTERN bool GNMNetworkShadow_TestCapability(GNMNetworkShadow *self,char const *cap){
-            return (GDALDatasetTestCapability(self, cap) > 0);
-        }
 
-SWIGINTERNINLINE PyObject*
-  SWIG_From_bool  (bool value)
+SWIGINTERN int
+SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
+{
+#if PY_VERSION_HEX>=0x03000000
+  if (PyUnicode_Check(obj))
+#else  
+  if (PyString_Check(obj))
+#endif
+  {
+    char *cstr; Py_ssize_t len;
+#if PY_VERSION_HEX>=0x03000000
+    if (!alloc && cptr) {
+        /* We can't allow converting without allocation, since the internal
+           representation of string in Python 3 is UCS-2/UCS-4 but we require
+           a UTF-8 representation.
+           TODO(bhy) More detailed explanation */
+        return SWIG_RuntimeError;
+    }
+    obj = PyUnicode_AsUTF8String(obj);
+    PyBytes_AsStringAndSize(obj, &cstr, &len);
+    if(alloc) *alloc = SWIG_NEWOBJ;
+#else
+    PyString_AsStringAndSize(obj, &cstr, &len);
+#endif
+    if (cptr) {
+      if (alloc) {
+	/* 
+	   In python the user should not be able to modify the inner
+	   string representation. To warranty that, if you define
+	   SWIG_PYTHON_SAFE_CSTRINGS, a new/copy of the python string
+	   buffer is always returned.
+
+	   The default behavior is just to return the pointer value,
+	   so, be careful.
+	*/ 
+#if defined(SWIG_PYTHON_SAFE_CSTRINGS)
+	if (*alloc != SWIG_OLDOBJ) 
+#else
+	if (*alloc == SWIG_NEWOBJ) 
+#endif
+	{
+	  *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+	  *alloc = SWIG_NEWOBJ;
+	} else {
+	  *cptr = cstr;
+	  *alloc = SWIG_OLDOBJ;
+	}
+      } else {
+	#if PY_VERSION_HEX>=0x03000000
+	assert(0); /* Should never reach here in Python 3 */
+	#endif
+	*cptr = SWIG_Python_str_AsChar(obj);
+      }
+    }
+    if (psize) *psize = len + 1;
+#if PY_VERSION_HEX>=0x03000000
+    Py_XDECREF(obj);
+#endif
+    return SWIG_OK;
+  } else {
+#if defined(SWIG_PYTHON_2_UNICODE)
+#if PY_VERSION_HEX<0x03000000
+    if (PyUnicode_Check(obj)) {
+      char *cstr; Py_ssize_t len;
+      if (!alloc && cptr) {
+        return SWIG_RuntimeError;
+      }
+      obj = PyUnicode_AsUTF8String(obj);
+      if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) {
+        if (cptr) {
+          if (alloc) *alloc = SWIG_NEWOBJ;
+          *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+        }
+        if (psize) *psize = len + 1;
+
+        Py_XDECREF(obj);
+        return SWIG_OK;
+      } else {
+        Py_XDECREF(obj);
+      }
+    }
+#endif
+#endif
+
+    swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
+    if (pchar_descriptor) {
+      void* vptr = 0;
+      if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) {
+	if (cptr) *cptr = (char *) vptr;
+	if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0;
+	if (alloc) *alloc = SWIG_OLDOBJ;
+	return SWIG_OK;
+      }
+    }
+  }
+  return SWIG_TypeError;
+}
+
+
+
+
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_CreateLayer(GNMNetworkShadow *self,char const *name,OSRSpatialReferenceShadow *srs=NULL,OGRwkbGeometryType geom_type=wkbUnknown,char **options=0){
+            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCreateLayer( self,
+                                      name,
+                                      srs,
+                                      geom_type,
+                                      options);
+            return layer;
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_CopyLayer(GNMNetworkShadow *self,OGRLayerShadow *src_layer,char const *new_name,char **options=0){
+            OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetCopyLayer( self,
+                                                      src_layer,
+                                                      new_name,
+                                                      options);
+            return layer;
+        }
+SWIGINTERN OGRErr GNMNetworkShadow_DeleteLayer(GNMNetworkShadow *self,int index){
+            return GDALDatasetDeleteLayer(self, index);
+        }
+
+
+#include "ogr_core.h"
+static char const *
+OGRErrMessages( int rc ) {
+  switch( rc ) {
+  case OGRERR_NONE:
+    return "OGR Error: None";
+  case OGRERR_NOT_ENOUGH_DATA:
+    return "OGR Error: Not enough data to deserialize";
+  case OGRERR_NOT_ENOUGH_MEMORY:
+    return "OGR Error: Not enough memory";
+  case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
+    return "OGR Error: Unsupported geometry type";
+  case OGRERR_UNSUPPORTED_OPERATION:
+    return "OGR Error: Unsupported operation";
+  case OGRERR_CORRUPT_DATA:
+    return "OGR Error: Corrupt data";
+  case OGRERR_FAILURE:
+    return "OGR Error: General Error";
+  case OGRERR_UNSUPPORTED_SRS:
+    return "OGR Error: Unsupported SRS";
+  case OGRERR_INVALID_HANDLE:
+    return "OGR Error: Invalid handle";
+  case OGRERR_NON_EXISTING_FEATURE:
+    return "OGR Error: Non existing feature";
+  default:
+    return "OGR Error: Unknown";
+  }
+}
+
+SWIGINTERN int GNMNetworkShadow_GetLayerCount(GNMNetworkShadow *self){
+            return GDALDatasetGetLayerCount(self);
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetLayerByIndex(GNMNetworkShadow *self,int index=0){
+        
+        OGRLayerShadow* layer = (OGRLayerShadow*) GDALDatasetGetLayer(self,
+                                                                      index);
+            return layer;
+        }
+SWIGINTERN OGRLayerShadow *GNMNetworkShadow_GetLayerByName(GNMNetworkShadow *self,char const *layer_name){
+            OGRLayerShadow* layer =
+                  (OGRLayerShadow*) GDALDatasetGetLayerByName(self, layer_name);
+            return layer;
+        }
+SWIGINTERN bool GNMNetworkShadow_TestCapability(GNMNetworkShadow *self,char const *cap){
+            return (GDALDatasetTestCapability(self, cap) > 0);
+        }
+
+SWIGINTERNINLINE PyObject*
+  SWIG_From_bool  (bool value)
 {
   return PyBool_FromLong(value ? 1 : 0);
 }
@@ -3676,7 +3788,10 @@ SWIGINTERN CPLErr GNMGenericNetworkShadow_ConnectPointsByLines(GNMGenericNetwork
 SWIGINTERN int
 SWIG_AsVal_bool (PyObject *obj, bool *val)
 {
-  int r = PyObject_IsTrue(obj);
+  int r;
+  if (!PyBool_Check(obj))
+    return SWIG_ERROR;
+  r = PyObject_IsTrue(obj);
   if (r == -1)
     return SWIG_ERROR;
   if (val) *val = r ? true : false;
@@ -3686,733 +3801,130 @@ SWIG_AsVal_bool (PyObject *obj, bool *val)
 SWIGINTERN CPLErr GNMGenericNetworkShadow_ChangeBlockState(GNMGenericNetworkShadow *self,GIntBig nFID,bool bIsBlock){
             return GNMChangeBlockState(self, nFID, bIsBlock);
         }
-SWIGINTERN CPLErr GNMGenericNetworkShadow_ChangeAllBlockState(GNMGenericNetworkShadow *self,bool bIsBlock=false){
-            return GNMChangeAllBlockState(self, bIsBlock);
-        }
-#ifdef __cplusplus
-extern "C" {
-#endif
-SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  int result;
-  
-  if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
-  result = (int)GetUseExceptions();
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  
-  if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
-  UseExceptions();
-  resultobj = SWIG_Py_Void();
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  
-  if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
-  DontUseExceptions();
-  resultobj = SWIG_Py_Void();
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_MajorObject_GetDescription(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  char *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:MajorObject_GetDescription",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetDescription" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
-  }
-  resultobj = SWIG_FromCharPtr((const char *)result);
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_MajorObject_SetDescription(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:MajorObject_SetDescription",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetDescription" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetDescription" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
-  }
-  resultobj = SWIG_Py_Void();
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  char **result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:MajorObject_GetMetadataDomainList",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataDomainList" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
-  }
-  {
-    /* %typemap(out) char **CSL -> ( string ) */
-    char **stringarray = result;
-    if ( stringarray == NULL ) {
-      resultobj = Py_None;
-      Py_INCREF( resultobj );
-    }
-    else {
-      int len = CSLCount( stringarray );
-      resultobj = PyList_New( len );
-      for ( int i = 0; i < len; ++i ) {
-        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
-        PyList_SetItem(resultobj, i, o );
-      }
-    }
-    CSLDestroy(result);
-  }
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-  char *arg2 = (char *) "" ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  char **result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O|O:MajorObject_GetMetadata_Dict",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadata_Dict" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-  if (obj1) {
-    res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadata_Dict" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
-  }
-  {
-    /* %typemap(out) char **dict */
-    char **stringarray = result;
-    resultobj = PyDict_New();
-    if ( stringarray != NULL ) {
-      while (*stringarray != NULL ) {
-        char const *valptr;
-        char *keyptr;
-        const char* pszSep = strchr( *stringarray, '=' );
-        if ( pszSep != NULL) {
-          keyptr = CPLStrdup(*stringarray);
-          keyptr[pszSep - *stringarray] = '\0';
-          valptr = pszSep + 1;
-          PyObject *nm = GDALPythonObjectFromCStr( keyptr );
-          PyObject *val = GDALPythonObjectFromCStr( valptr );
-          PyDict_SetItem(resultobj, nm, val );
-          Py_DECREF(nm);
-          Py_DECREF(val);
-          CPLFree( keyptr );
-        }
-        stringarray++;
-      }
-    }
-  }
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-  char *arg2 = (char *) "" ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  char **result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O|O:MajorObject_GetMetadata_List",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadata_List" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-  if (obj1) {
-    res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadata_List" "', argument " "2"" of type '" "char const *""'");
-    }
-    arg2 = reinterpret_cast< char * >(buf2);
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
-  }
-  {
-    /* %typemap(out) char **options -> ( string ) */
-    char **stringarray = result;
-    if ( stringarray == NULL ) {
-      resultobj = Py_None;
-      Py_INCREF( resultobj );
-    }
-    else {
-      int len = CSLCount( stringarray );
-      resultobj = PyList_New( len );
-      for ( int i = 0; i < len; ++i ) {
-        PyObject *o = GDALPythonObjectFromCStr( stringarray[i] );
-        PyList_SetItem(resultobj, i, o );
-      }
-    }
-  }
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-  char **arg2 = (char **) 0 ;
-  char *arg3 = (char *) "" ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res3 ;
-  char *buf3 = 0 ;
-  int alloc3 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  CPLErr result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO|O:MajorObject_SetMetadata",&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadata" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-  {
-    /* %typemap(in) char **dict */
-    arg2 = NULL;
-    if ( PySequence_Check( obj1 ) ) {
-      Py_ssize_t size = PySequence_Size(obj1);
-      if( size != (int)size ) {
-        PyErr_SetString(PyExc_TypeError, "too big sequence");
-        SWIG_fail;
-      }
-      for (int i = 0; i < (int)size; i++) {
-        PyObject* pyObj = PySequence_GetItem(obj1,i);
-        int bFreeStr;
-        char* pszStr = GDALPythonObjectToCStr(pyObj, &bFreeStr);
-        if ( pszStr == NULL ) {
-          Py_DECREF(pyObj);
-          PyErr_SetString(PyExc_TypeError,"sequence must contain strings");
-          SWIG_fail;
-        }
-        arg2 = CSLAddString( arg2, pszStr );
-        GDALPythonFreeCStr(pszStr, bFreeStr);
-        Py_DECREF(pyObj);
-      }
-    }
-    else if ( PyMapping_Check( obj1 ) ) {
-      /* We need to use the dictionary form. */
-      Py_ssize_t size = PyMapping_Length( obj1 );
-      if ( size > 0 && size == (int)size) {
-        PyObject *item_list = PyMapping_Items( obj1 );
-        for( int i=0; i<(int)size; i++ ) {
-          PyObject *it = PySequence_GetItem( item_list, i );
-          
-          PyObject *k, *v;
-          if ( ! PyArg_ParseTuple( it, "OO", &k, &v ) ) {
-            Py_DECREF(it);
-            PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
-            SWIG_fail;
-          }
-          
-          int bFreeK, bFreeV;
-          char* pszK = GDALPythonObjectToCStr(k, &bFreeK);
-          char* pszV = GDALPythonObjectToCStr(v, &bFreeV);
-          if( pszK == NULL || pszV == NULL )
-          {
-            GDALPythonFreeCStr(pszK, bFreeK);
-            GDALPythonFreeCStr(pszV, bFreeV);
-            Py_DECREF(it);
-            PyErr_SetString(PyExc_TypeError,"Dictionary must contain tuples of strings");
-            SWIG_fail;
-          }
-          arg2 = CSLAddNameValue( arg2, pszK, pszV );
-          
-          GDALPythonFreeCStr(pszK, bFreeK);
-          GDALPythonFreeCStr(pszV, bFreeV);
-          Py_DECREF(it);
-        }
-        Py_DECREF(item_list);
-      }
-    }
-    else {
-      PyErr_SetString(PyExc_TypeError,"Argument must be dictionary or sequence of strings");
-      SWIG_fail;
-    }
-  }
-  if (obj2) {
-    res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadata" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
-  }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  {
-    /* %typemap(freearg) char **dict */
-    CSLDestroy( arg2 );
-  }
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  {
-    /* %typemap(freearg) char **dict */
-    CSLDestroy( arg2 );
-  }
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  char *arg3 = (char *) "" ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  int res3 ;
-  char *buf3 = 0 ;
-  int alloc3 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  CPLErr result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO|O:MajorObject_SetMetadata",&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadata" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetMetadata" "', argument " "2"" of type '" "char *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  if (obj2) {
-    res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadata" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
-  }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[4];
-  int ii;
-  
-  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
-  for (ii = 0; (ii < 3) && (ii < argc); ii++) {
-    argv[ii] = PyTuple_GET_ITEM(args,ii);
-  }
-  if ((argc >= 2) && (argc <= 3)) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_GDALMajorObjectShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      {
-        /* %typecheck(SWIG_TYPECHECK_POINTER) (char **dict) */
-        /* Note: we exclude explicitly strings, because they can be considered as a sequence of characters, */
-        /* which is not desirable since it makes it impossible to define bindings such as SetMetadata(string) and SetMetadata(array_of_string) */
-        /* (see #4816) */
-        _v = ((PyMapping_Check(argv[1]) || PySequence_Check(argv[1]) ) && !SWIG_CheckState(SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0)) ) ? 1 : 0;
-      }
-      if (_v) {
-        if (argc <= 2) {
-          return _wrap_MajorObject_SetMetadata__SWIG_0(self, args);
-        }
-        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-        if (_v) {
-          return _wrap_MajorObject_SetMetadata__SWIG_0(self, args);
-        }
-      }
-    }
-  }
-  if ((argc >= 2) && (argc <= 3)) {
-    int _v;
-    void *vptr = 0;
-    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_GDALMajorObjectShadow, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        if (argc <= 2) {
-          return _wrap_MajorObject_SetMetadata__SWIG_1(self, args);
-        }
-        int res = SWIG_AsCharPtrAndSize(argv[2], 0, NULL, 0);
-        _v = SWIG_CheckState(res);
-        if (_v) {
-          return _wrap_MajorObject_SetMetadata__SWIG_1(self, args);
+SWIGINTERN CPLErr GNMGenericNetworkShadow_ChangeAllBlockState(GNMGenericNetworkShadow *self,bool bIsBlock=false){
+            return GNMChangeAllBlockState(self, bIsBlock);
         }
-      }
-    }
-  }
+#ifdef __cplusplus
+extern "C" {
+#endif
+SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  int result;
   
+  if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
+  {
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    result = (int)GetUseExceptions();
+    SWIG_PYTHON_THREAD_END_ALLOW;
+  }
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
 fail:
-  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'MajorObject_SetMetadata'.\n"
-    "  Possible C/C++ prototypes are:\n"
-    "    GDALMajorObjectShadow::SetMetadata(char **,char const *)\n"
-    "    GDALMajorObjectShadow::SetMetadata(char *,char const *)\n");
-  return 0;
+  return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  char *arg3 = (char *) "" ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  int res3 ;
-  char *buf3 = 0 ;
-  int alloc3 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  char *result = 0 ;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO|O:MajorObject_GetMetadataItem",&obj0,&obj1,&obj2)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_GetMetadataItem" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_GetMetadataItem" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  if (obj2) {
-    res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
-    if (!SWIG_IsOK(res3)) {
-      SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_GetMetadataItem" "', argument " "3"" of type '" "char const *""'");
-    }
-    arg3 = reinterpret_cast< char * >(buf3);
-  }
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
+  if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    UseExceptions();
+    SWIG_PYTHON_THREAD_END_ALLOW;
   }
-  resultobj = SWIG_FromCharPtr((const char *)result);
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+  resultobj = SWIG_Py_Void();
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *_wrap_MajorObject_SetMetadataItem(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
-  char *arg2 = (char *) 0 ;
-  char *arg3 = (char *) 0 ;
-  char *arg4 = (char *) "" ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  int res2 ;
-  char *buf2 = 0 ;
-  int alloc2 = 0 ;
-  int res3 ;
-  char *buf3 = 0 ;
-  int alloc3 = 0 ;
-  int res4 ;
-  char *buf4 = 0 ;
-  int alloc4 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  PyObject * obj2 = 0 ;
-  PyObject * obj3 = 0 ;
-  CPLErr result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OOO|O:MajorObject_SetMetadataItem",&obj0,&obj1,&obj2,&obj3)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_GDALMajorObjectShadow, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MajorObject_SetMetadataItem" "', argument " "1"" of type '" "GDALMajorObjectShadow *""'"); 
-  }
-  arg1 = reinterpret_cast< GDALMajorObjectShadow * >(argp1);
-  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
-  if (!SWIG_IsOK(res2)) {
-    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "MajorObject_SetMetadataItem" "', argument " "2"" of type '" "char const *""'");
-  }
-  arg2 = reinterpret_cast< char * >(buf2);
-  res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
-  if (!SWIG_IsOK(res3)) {
-    SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "MajorObject_SetMetadataItem" "', argument " "3"" of type '" "char const *""'");
-  }
-  arg3 = reinterpret_cast< char * >(buf3);
-  if (obj3) {
-    res4 = SWIG_AsCharPtrAndSize(obj3, &buf4, NULL, &alloc4);
-    if (!SWIG_IsOK(res4)) {
-      SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "MajorObject_SetMetadataItem" "', argument " "4"" of type '" "char const *""'");
-    }
-    arg4 = reinterpret_cast< char * >(buf4);
-  }
-  {
-    if (!arg2) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
+  if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
   {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
+    SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+    DontUseExceptions();
+    SWIG_PYTHON_THREAD_END_ALLOW;
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
+  resultobj = SWIG_Py_Void();
   if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
   return resultobj;
 fail:
-  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
-  if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
-  if (alloc4 == SWIG_NEWOBJ) delete[] buf4;
   return NULL;
 }
 
 
-SWIGINTERN PyObject *MajorObject_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *obj;
-  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_GDALMajorObjectShadow, SWIG_NewClientData(obj));
+SWIGINTERN PyObject *GATDijkstraShortestPath_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GATDijkstraShortestPath",SWIG_From_int(static_cast< int >(GATDijkstraShortestPath)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GATKShortestPath_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GATKShortestPath",SWIG_From_int(static_cast< int >(GATKShortestPath)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GATConnectedComponents_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GATConnectedComponents",SWIG_From_int(static_cast< int >(GATConnectedComponents)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GNM_EDGE_DIR_BOTH_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GNM_EDGE_DIR_BOTH",SWIG_From_int(static_cast< int >(0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GNM_EDGE_DIR_SRCTOTGT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GNM_EDGE_DIR_SRCTOTGT",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *GNM_EDGE_DIR_TGTTOSRC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "GNM_EDGE_DIR_TGTTOSRC",SWIG_From_int(static_cast< int >(2)));
   return SWIG_Py_Void();
 }
 
+
 SWIGINTERN PyObject *_wrap_CastToNetwork(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   GDALMajorObjectShadow *arg1 = (GDALMajorObjectShadow *) 0 ;
@@ -4431,7 +3943,11 @@ SWIGINTERN PyObject *_wrap_CastToNetwork(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GNMNetworkShadow *)CastToNetwork(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GNMNetworkShadow *)CastToNetwork(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4467,7 +3983,11 @@ SWIGINTERN PyObject *_wrap_CastToGenericNetwork(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (GNMGenericNetworkShadow *)CastToGenericNetwork(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (GNMGenericNetworkShadow *)CastToGenericNetwork(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4502,7 +4022,11 @@ SWIGINTERN PyObject *_wrap_delete_Network(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GNMNetworkShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GNMNetworkShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4544,7 +4068,11 @@ SWIGINTERN PyObject *_wrap_Network_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GNMNetworkShadow_ReleaseResultSet(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GNMNetworkShadow_ReleaseResultSet(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4580,7 +4108,11 @@ SWIGINTERN PyObject *_wrap_Network_GetVersion(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GNMNetworkShadow_GetVersion(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GNMNetworkShadow_GetVersion(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4616,7 +4148,11 @@ SWIGINTERN PyObject *_wrap_Network_GetName(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GNMNetworkShadow_GetName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GNMNetworkShadow_GetName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4662,7 +4198,11 @@ SWIGINTERN PyObject *_wrap_Network_GetFeatureByGlobalFID(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureShadow *)GNMNetworkShadow_GetFeatureByGlobalFID(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFeatureShadow *)GNMNetworkShadow_GetFeatureByGlobalFID(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4782,7 +4322,11 @@ SWIGINTERN PyObject *_wrap_Network_GetPath(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_GetPath(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GNMNetworkShadow_GetPath(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4826,7 +4370,11 @@ SWIGINTERN PyObject *_wrap_Network_DisconnectAll(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMNetworkShadow_DisconnectAll(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMNetworkShadow_DisconnectAll(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4862,7 +4410,11 @@ SWIGINTERN PyObject *_wrap_Network_GetProjection(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GNMNetworkShadow_GetProjection(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GNMNetworkShadow_GetProjection(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4898,7 +4450,11 @@ SWIGINTERN PyObject *_wrap_Network_GetProjectionRef(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GNMNetworkShadow_GetProjectionRef(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GNMNetworkShadow_GetProjectionRef(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4934,7 +4490,11 @@ SWIGINTERN PyObject *_wrap_Network_GetFileList(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GNMNetworkShadow_GetFileList(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GNMNetworkShadow_GetFileList(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -4982,8 +4542,8 @@ SWIGINTERN PyObject *_wrap_Network_CreateLayer(PyObject *SWIGUNUSEDPARM(self), P
   int alloc2 = 0 ;
   void *argp3 = 0 ;
   int res3 = 0 ;
-  void *argp4 ;
-  int res4 = 0 ;
+  int val4 ;
+  int ecode4 = 0 ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   PyObject * obj2 = 0 ;
@@ -5013,19 +4573,11 @@ SWIGINTERN PyObject *_wrap_Network_CreateLayer(PyObject *SWIGUNUSEDPARM(self), P
     arg3 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp3);
   }
   if (obj3) {
-    {
-      res4 = SWIG_ConvertPtr(obj3, &argp4, SWIGTYPE_p_OGRwkbGeometryType,  0  | 0);
-      if (!SWIG_IsOK(res4)) {
-        SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "Network_CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'"); 
-      }  
-      if (!argp4) {
-        SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "Network_CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
-      } else {
-        OGRwkbGeometryType * temp = reinterpret_cast< OGRwkbGeometryType * >(argp4);
-        arg4 = *temp;
-        if (SWIG_IsNewObj(res4)) delete temp;
-      }
-    }
+    ecode4 = SWIG_AsVal_int(obj3, &val4);
+    if (!SWIG_IsOK(ecode4)) {
+      SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "Network_CreateLayer" "', argument " "4"" of type '" "OGRwkbGeometryType""'");
+    } 
+    arg4 = static_cast< OGRwkbGeometryType >(val4);
   }
   if (obj4) {
     {
@@ -5078,10 +4630,19 @@ SWIGINTERN PyObject *_wrap_Network_CreateLayer(PyObject *SWIGUNUSEDPARM(self), P
     }
   }
   {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GNMNetworkShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5206,7 +4767,11 @@ SWIGINTERN PyObject *_wrap_Network_CopyLayer(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GNMNetworkShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5261,7 +4826,11 @@ SWIGINTERN PyObject *_wrap_Network_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = GNMNetworkShadow_DeleteLayer(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)GNMNetworkShadow_DeleteLayer(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5274,6 +4843,10 @@ SWIGINTERN PyObject *_wrap_Network_DeleteLayer(PyObject *SWIGUNUSEDPARM(self), P
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5309,7 +4882,11 @@ SWIGINTERN PyObject *_wrap_Network_GetLayerCount(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)GNMNetworkShadow_GetLayerCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)GNMNetworkShadow_GetLayerCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5356,7 +4933,11 @@ SWIGINTERN PyObject *_wrap_Network_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByIndex(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByIndex(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5402,7 +4983,11 @@ SWIGINTERN PyObject *_wrap_Network_GetLayerByName(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByName(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)GNMNetworkShadow_GetLayerByName(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5447,10 +5032,19 @@ SWIGINTERN PyObject *_wrap_Network_TestCapability(PyObject *SWIGUNUSEDPARM(self)
   }
   arg2 = reinterpret_cast< char * >(buf2);
   {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)GNMNetworkShadow_TestCapability(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)GNMNetworkShadow_TestCapability(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5502,7 +5096,11 @@ SWIGINTERN PyObject *_wrap_Network_StartTransaction(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = GNMNetworkShadow_StartTransaction(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)GNMNetworkShadow_StartTransaction(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5515,6 +5113,10 @@ SWIGINTERN PyObject *_wrap_Network_StartTransaction(PyObject *SWIGUNUSEDPARM(sel
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5550,7 +5152,11 @@ SWIGINTERN PyObject *_wrap_Network_CommitTransaction(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = GNMNetworkShadow_CommitTransaction(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)GNMNetworkShadow_CommitTransaction(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5563,6 +5169,10 @@ SWIGINTERN PyObject *_wrap_Network_CommitTransaction(PyObject *SWIGUNUSEDPARM(se
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5598,7 +5208,11 @@ SWIGINTERN PyObject *_wrap_Network_RollbackTransaction(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = GNMNetworkShadow_RollbackTransaction(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)GNMNetworkShadow_RollbackTransaction(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5611,6 +5225,10 @@ SWIGINTERN PyObject *_wrap_Network_RollbackTransaction(PyObject *SWIGUNUSEDPARM(
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5652,7 +5270,11 @@ SWIGINTERN PyObject *_wrap_delete_GenericNetwork(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_GNMGenericNetworkShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_GNMGenericNetworkShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5745,7 +5367,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_ConnectFeatures(PyObject *SWIGUNUSEDPA
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_ConnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_ConnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5811,7 +5437,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_DisconnectFeatures(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeatures(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeatures(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5857,7 +5487,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_DisconnectFeaturesWithId(PyObject *SWI
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeaturesWithId(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_DisconnectFeaturesWithId(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5950,7 +5584,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_ReconnectFeatures(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_ReconnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_ReconnectFeatures(arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6001,7 +5639,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_CreateRule(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_CreateRule(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_CreateRule(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6039,7 +5681,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_DeleteAllRules(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_DeleteAllRules(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_DeleteAllRules(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6090,7 +5736,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_DeleteRule(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_DeleteRule(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_DeleteRule(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6128,7 +5778,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_GetRules(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GNMGenericNetworkShadow_GetRules(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GNMGenericNetworkShadow_GetRules(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6269,7 +5923,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_ConnectPointsByLines(PyObject *SWIGUNU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_ConnectPointsByLines(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_ConnectPointsByLines(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6332,7 +5990,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_ChangeBlockState(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_ChangeBlockState(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_ChangeBlockState(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6379,7 +6041,11 @@ SWIGINTERN PyObject *_wrap_GenericNetwork_ChangeAllBlockState(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GNMGenericNetworkShadow_ChangeAllBlockState(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GNMGenericNetworkShadow_ChangeAllBlockState(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6409,63 +6075,45 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GetUseExceptions", _wrap_GetUseExceptions, METH_VARARGS, NULL},
 	 { (char *)"UseExceptions", _wrap_UseExceptions, METH_VARARGS, NULL},
 	 { (char *)"DontUseExceptions", _wrap_DontUseExceptions, METH_VARARGS, NULL},
-	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, NULL},
-	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, NULL},
-	 { (char *)"MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList, METH_VARARGS, NULL},
-	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, NULL},
-	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, NULL},
-	 { (char *)"MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata, METH_VARARGS, NULL},
-	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, NULL},
-	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, NULL},
-	 { (char *)"MajorObject_swigregister", MajorObject_swigregister, METH_VARARGS, NULL},
+	 { (char *)"GATDijkstraShortestPath_swigconstant", GATDijkstraShortestPath_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GATKShortestPath_swigconstant", GATKShortestPath_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GATConnectedComponents_swigconstant", GATConnectedComponents_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GNM_EDGE_DIR_BOTH_swigconstant", GNM_EDGE_DIR_BOTH_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GNM_EDGE_DIR_SRCTOTGT_swigconstant", GNM_EDGE_DIR_SRCTOTGT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"GNM_EDGE_DIR_TGTTOSRC_swigconstant", GNM_EDGE_DIR_TGTTOSRC_swigconstant, METH_VARARGS, NULL},
 	 { (char *)"CastToNetwork", _wrap_CastToNetwork, METH_VARARGS, (char *)"CastToNetwork(MajorObject base) -> Network"},
 	 { (char *)"CastToGenericNetwork", _wrap_CastToGenericNetwork, METH_VARARGS, (char *)"CastToGenericNetwork(MajorObject base) -> GenericNetwork"},
 	 { (char *)"delete_Network", _wrap_delete_Network, METH_VARARGS, (char *)"delete_Network(Network self)"},
-	 { (char *)"Network_ReleaseResultSet", _wrap_Network_ReleaseResultSet, METH_VARARGS, (char *)"Network_ReleaseResultSet(Network self, OGRLayerShadow * layer)"},
+	 { (char *)"Network_ReleaseResultSet", _wrap_Network_ReleaseResultSet, METH_VARARGS, (char *)"Network_ReleaseResultSet(Network self, Layer layer)"},
 	 { (char *)"Network_GetVersion", _wrap_Network_GetVersion, METH_VARARGS, (char *)"Network_GetVersion(Network self) -> int"},
 	 { (char *)"Network_GetName", _wrap_Network_GetName, METH_VARARGS, (char *)"Network_GetName(Network self) -> char const *"},
-	 { (char *)"Network_GetFeatureByGlobalFID", _wrap_Network_GetFeatureByGlobalFID, METH_VARARGS, (char *)"Network_GetFeatureByGlobalFID(Network self, GIntBig GFID) -> OGRFeatureShadow *"},
-	 { (char *)"Network_GetPath", (PyCFunction) _wrap_Network_GetPath, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Network_GetPath(Network self, GIntBig nStartFID, GIntBig nEndFID, GNMGraphAlgorithmType eAlgorithm, \n"
-		"    char ** options=None) -> OGRLayerShadow *\n"
-		""},
+	 { (char *)"Network_GetFeatureByGlobalFID", _wrap_Network_GetFeatureByGlobalFID, METH_VARARGS, (char *)"Network_GetFeatureByGlobalFID(Network self, GIntBig GFID) -> Feature"},
+	 { (char *)"Network_GetPath", (PyCFunction) _wrap_Network_GetPath, METH_VARARGS | METH_KEYWORDS, (char *)"Network_GetPath(Network self, GIntBig nStartFID, GIntBig nEndFID, GNMGraphAlgorithmType eAlgorithm, char ** options=None) -> Layer"},
 	 { (char *)"Network_DisconnectAll", _wrap_Network_DisconnectAll, METH_VARARGS, (char *)"Network_DisconnectAll(Network self) -> CPLErr"},
 	 { (char *)"Network_GetProjection", _wrap_Network_GetProjection, METH_VARARGS, (char *)"Network_GetProjection(Network self) -> char const *"},
 	 { (char *)"Network_GetProjectionRef", _wrap_Network_GetProjectionRef, METH_VARARGS, (char *)"Network_GetProjectionRef(Network self) -> char const *"},
 	 { (char *)"Network_GetFileList", _wrap_Network_GetFileList, METH_VARARGS, (char *)"Network_GetFileList(Network self) -> char **"},
-	 { (char *)"Network_CreateLayer", (PyCFunction) _wrap_Network_CreateLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Network_CreateLayer(Network self, char const * name, OSRSpatialReferenceShadow * srs=None, OGRwkbGeometryType geom_type=wkbUnknown, \n"
-		"    char ** options=None) -> OGRLayerShadow *\n"
-		""},
-	 { (char *)"Network_CopyLayer", (PyCFunction) _wrap_Network_CopyLayer, METH_VARARGS | METH_KEYWORDS, (char *)"Network_CopyLayer(Network self, OGRLayerShadow * src_layer, char const * new_name, char ** options=None) -> OGRLayerShadow *"},
+	 { (char *)"Network_CreateLayer", (PyCFunction) _wrap_Network_CreateLayer, METH_VARARGS | METH_KEYWORDS, (char *)"Network_CreateLayer(Network self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type, char ** options=None) -> Layer"},
+	 { (char *)"Network_CopyLayer", (PyCFunction) _wrap_Network_CopyLayer, METH_VARARGS | METH_KEYWORDS, (char *)"Network_CopyLayer(Network self, Layer src_layer, char const * new_name, char ** options=None) -> Layer"},
 	 { (char *)"Network_DeleteLayer", _wrap_Network_DeleteLayer, METH_VARARGS, (char *)"Network_DeleteLayer(Network self, int index) -> OGRErr"},
 	 { (char *)"Network_GetLayerCount", _wrap_Network_GetLayerCount, METH_VARARGS, (char *)"Network_GetLayerCount(Network self) -> int"},
-	 { (char *)"Network_GetLayerByIndex", _wrap_Network_GetLayerByIndex, METH_VARARGS, (char *)"Network_GetLayerByIndex(Network self, int index=0) -> OGRLayerShadow *"},
-	 { (char *)"Network_GetLayerByName", _wrap_Network_GetLayerByName, METH_VARARGS, (char *)"Network_GetLayerByName(Network self, char const * layer_name) -> OGRLayerShadow *"},
+	 { (char *)"Network_GetLayerByIndex", _wrap_Network_GetLayerByIndex, METH_VARARGS, (char *)"Network_GetLayerByIndex(Network self, int index=0) -> Layer"},
+	 { (char *)"Network_GetLayerByName", _wrap_Network_GetLayerByName, METH_VARARGS, (char *)"Network_GetLayerByName(Network self, char const * layer_name) -> Layer"},
 	 { (char *)"Network_TestCapability", _wrap_Network_TestCapability, METH_VARARGS, (char *)"Network_TestCapability(Network self, char const * cap) -> bool"},
 	 { (char *)"Network_StartTransaction", (PyCFunction) _wrap_Network_StartTransaction, METH_VARARGS | METH_KEYWORDS, (char *)"Network_StartTransaction(Network self, int force=False) -> OGRErr"},
 	 { (char *)"Network_CommitTransaction", _wrap_Network_CommitTransaction, METH_VARARGS, (char *)"Network_CommitTransaction(Network self) -> OGRErr"},
 	 { (char *)"Network_RollbackTransaction", _wrap_Network_RollbackTransaction, METH_VARARGS, (char *)"Network_RollbackTransaction(Network self) -> OGRErr"},
 	 { (char *)"Network_swigregister", Network_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_GenericNetwork", _wrap_delete_GenericNetwork, METH_VARARGS, (char *)"delete_GenericNetwork(GenericNetwork self)"},
-	 { (char *)"GenericNetwork_ConnectFeatures", _wrap_GenericNetwork_ConnectFeatures, METH_VARARGS, (char *)"\n"
-		"GenericNetwork_ConnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, \n"
-		"    double dfInvCost, GNMDirection eDir) -> CPLErr\n"
-		""},
+	 { (char *)"GenericNetwork_ConnectFeatures", _wrap_GenericNetwork_ConnectFeatures, METH_VARARGS, (char *)"GenericNetwork_ConnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost, GNMDirection eDir) -> CPLErr"},
 	 { (char *)"GenericNetwork_DisconnectFeatures", _wrap_GenericNetwork_DisconnectFeatures, METH_VARARGS, (char *)"GenericNetwork_DisconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID) -> CPLErr"},
 	 { (char *)"GenericNetwork_DisconnectFeaturesWithId", _wrap_GenericNetwork_DisconnectFeaturesWithId, METH_VARARGS, (char *)"GenericNetwork_DisconnectFeaturesWithId(GenericNetwork self, GIntBig nFID) -> CPLErr"},
-	 { (char *)"GenericNetwork_ReconnectFeatures", _wrap_GenericNetwork_ReconnectFeatures, METH_VARARGS, (char *)"\n"
-		"GenericNetwork_ReconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, \n"
-		"    double dfInvCost, GNMDirection eDir) -> CPLErr\n"
-		""},
+	 { (char *)"GenericNetwork_ReconnectFeatures", _wrap_GenericNetwork_ReconnectFeatures, METH_VARARGS, (char *)"GenericNetwork_ReconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost, GNMDirection eDir) -> CPLErr"},
 	 { (char *)"GenericNetwork_CreateRule", _wrap_GenericNetwork_CreateRule, METH_VARARGS, (char *)"GenericNetwork_CreateRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"},
 	 { (char *)"GenericNetwork_DeleteAllRules", _wrap_GenericNetwork_DeleteAllRules, METH_VARARGS, (char *)"GenericNetwork_DeleteAllRules(GenericNetwork self) -> CPLErr"},
 	 { (char *)"GenericNetwork_DeleteRule", _wrap_GenericNetwork_DeleteRule, METH_VARARGS, (char *)"GenericNetwork_DeleteRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"},
 	 { (char *)"GenericNetwork_GetRules", _wrap_GenericNetwork_GetRules, METH_VARARGS, (char *)"GenericNetwork_GetRules(GenericNetwork self) -> char **"},
-	 { (char *)"GenericNetwork_ConnectPointsByLines", (PyCFunction) _wrap_GenericNetwork_ConnectPointsByLines, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"GenericNetwork_ConnectPointsByLines(GenericNetwork self, char ** papszLayerList, double dfTolerance, double dfCost, double dfInvCost, \n"
-		"    GNMDirection eDir) -> CPLErr\n"
-		""},
+	 { (char *)"GenericNetwork_ConnectPointsByLines", (PyCFunction) _wrap_GenericNetwork_ConnectPointsByLines, METH_VARARGS | METH_KEYWORDS, (char *)"GenericNetwork_ConnectPointsByLines(GenericNetwork self, char ** papszLayerList, double dfTolerance, double dfCost, double dfInvCost, GNMDirection eDir) -> CPLErr"},
 	 { (char *)"GenericNetwork_ChangeBlockState", _wrap_GenericNetwork_ChangeBlockState, METH_VARARGS, (char *)"GenericNetwork_ChangeBlockState(GenericNetwork self, GIntBig nFID, bool bIsBlock) -> CPLErr"},
 	 { (char *)"GenericNetwork_ChangeAllBlockState", _wrap_GenericNetwork_ChangeAllBlockState, METH_VARARGS, (char *)"GenericNetwork_ChangeAllBlockState(GenericNetwork self, bool bIsBlock=False) -> CPLErr"},
 	 { (char *)"GenericNetwork_swigregister", GenericNetwork_swigregister, METH_VARARGS, NULL},
@@ -6475,6 +6123,15 @@ static PyMethodDef SwigMethods[] = {
 
 /* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */
 
+static void *_p_OGRDriverShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GDALMajorObjectShadow *)  ((OGRDriverShadow *) x));
+}
+static void *_p_OGRLayerShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GDALMajorObjectShadow *)  ((OGRLayerShadow *) x));
+}
+static void *_p_OGRDataSourceShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((GDALMajorObjectShadow *)  ((OGRDataSourceShadow *) x));
+}
 static void *_p_GNMNetworkShadowTo_p_GDALMajorObjectShadow(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((GDALMajorObjectShadow *)  ((GNMNetworkShadow *) x));
 }
@@ -6485,16 +6142,17 @@ static void *_p_GNMGenericNetworkShadowTo_p_GNMNetworkShadow(void *x, int *SWIGU
     return (void *)((GNMNetworkShadow *)  ((GNMGenericNetworkShadow *) x));
 }
 static swig_type_info _swigt__p_GDALMajorObjectShadow = {"_p_GDALMajorObjectShadow", "GDALMajorObjectShadow *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_OGRDriverShadow = {"_p_OGRDriverShadow", 0, 0, 0, 0, 0};
+static swig_type_info _swigt__p_OGRDataSourceShadow = {"_p_OGRDataSourceShadow", 0, 0, 0, 0, 0};
 static swig_type_info _swigt__p_GIntBig = {"_p_GIntBig", "GIntBig *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GNMGenericNetworkShadow = {"_p_GNMGenericNetworkShadow", "GNMGenericNetworkShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GNMGraphAlgorithmType = {"_p_GNMGraphAlgorithmType", "enum GNMGraphAlgorithmType *|GNMGraphAlgorithmType *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GNMNetworkShadow = {"_p_GNMNetworkShadow", "GNMNetworkShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRFeatureShadow = {"_p_OGRFeatureShadow", "OGRFeatureShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OGRLayerShadow = {"_p_OGRLayerShadow", "OGRLayerShadow *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_OGRwkbGeometryType = {"_p_OGRwkbGeometryType", "OGRwkbGeometryType *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_OSRSpatialReferenceShadow = {"_p_OSRSpatialReferenceShadow", "OSRSpatialReferenceShadow *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_char = {"_p_char", "char *|retStringAndCPLFree *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_int = {"_p_int", "CPLErr *|int *|GNMDirection *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_int = {"_p_int", "OGRFieldSubType *|OGRFieldType *|CPLErr *|int *|OGRwkbGeometryType *|OGRJustification *|OGRAxisOrientation *|GNMDirection *|OGRwkbByteOrder *|OGRErr *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_char = {"_p_p_char", "char **", 0, 0, (void*)0, 0};
 
 static swig_type_info *swig_type_initial[] = {
@@ -6503,23 +6161,25 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_GNMGenericNetworkShadow,
   &_swigt__p_GNMGraphAlgorithmType,
   &_swigt__p_GNMNetworkShadow,
+  &_swigt__p_OGRDataSourceShadow,
+  &_swigt__p_OGRDriverShadow,
   &_swigt__p_OGRFeatureShadow,
   &_swigt__p_OGRLayerShadow,
-  &_swigt__p_OGRwkbGeometryType,
   &_swigt__p_OSRSpatialReferenceShadow,
   &_swigt__p_char,
   &_swigt__p_int,
   &_swigt__p_p_char,
 };
 
-static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_GNMNetworkShadow, _p_GNMNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGenericNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRDriverShadow[] = {{&_swigt__p_OGRDriverShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_OGRDataSourceShadow[] = {{&_swigt__p_OGRDataSourceShadow, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_GDALMajorObjectShadow[] = {  {&_swigt__p_GDALMajorObjectShadow, 0, 0, 0},  {&_swigt__p_OGRDriverShadow, _p_OGRDriverShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_OGRLayerShadow, _p_OGRLayerShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_OGRDataSourceShadow, _p_OGRDataSourceShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GNMNetworkShadow, _p_GNMNetworkShadowTo_p_GDALMajorObjectShadow, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGe [...]
 static swig_cast_info _swigc__p_GIntBig[] = {  {&_swigt__p_GIntBig, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GNMGenericNetworkShadow[] = {  {&_swigt__p_GNMGenericNetworkShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GNMGraphAlgorithmType[] = {  {&_swigt__p_GNMGraphAlgorithmType, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GNMNetworkShadow[] = {  {&_swigt__p_GNMNetworkShadow, 0, 0, 0},  {&_swigt__p_GNMGenericNetworkShadow, _p_GNMGenericNetworkShadowTo_p_GNMNetworkShadow, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRFeatureShadow[] = {  {&_swigt__p_OGRFeatureShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OGRLayerShadow[] = {  {&_swigt__p_OGRLayerShadow, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_OGRwkbGeometryType[] = {  {&_swigt__p_OGRwkbGeometryType, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_OSRSpatialReferenceShadow[] = {  {&_swigt__p_OSRSpatialReferenceShadow, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_char[] = {  {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_int[] = {  {&_swigt__p_int, 0, 0, 0},{0, 0, 0, 0}};
@@ -6531,9 +6191,10 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_GNMGenericNetworkShadow,
   _swigc__p_GNMGraphAlgorithmType,
   _swigc__p_GNMNetworkShadow,
+  _swigc__p_OGRDataSourceShadow,
+  _swigc__p_OGRDriverShadow,
   _swigc__p_OGRFeatureShadow,
   _swigc__p_OGRLayerShadow,
-  _swigc__p_OGRwkbGeometryType,
   _swigc__p_OSRSpatialReferenceShadow,
   _swigc__p_char,
   _swigc__p_int,
@@ -6562,7 +6223,7 @@ static swig_const_info swig_const_table[] = {
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial
+ * The generated swig_type_info structures are assigned statically to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -6606,7 +6267,7 @@ SWIGRUNTIME void
 SWIG_InitializeModule(void *clientdata) {
   size_t i;
   swig_module_info *module_head, *iter;
-  int found, init;
+  int init;
   
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
@@ -6625,22 +6286,18 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
     iter=module_head;
     do {
       if (iter==&swig_module) {
-        found=1;
-        break;
+        /* Our module is already in the list, so there's nothing more to do. */
+        return;
       }
       iter=iter->next;
     } while (iter!= module_head);
     
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
+    /* otherwise we must add our module into the list */
     swig_module.next = module_head->next;
     module_head->next = &swig_module;
   }
@@ -6892,7 +6549,7 @@ extern "C" {
       var = var->next;
     }
     if (res == NULL && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -6909,7 +6566,7 @@ extern "C" {
       var = var->next;
     }
     if (res == 1 && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -6959,10 +6616,19 @@ extern "C" {
         0,                                  /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-        0,                                  /* tp_version */
+        0,                                  /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+        0,                                  /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-        0,0,0,0                             /* tp_alloc -> tp_next */
+        0,                                  /* tp_allocs */
+        0,                                  /* tp_frees */
+        0,                                  /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+        0,                                  /* tp_prev */
+#endif
+        0                                   /* tp_next */
 #endif
       };
       varlink_type = tmp;
@@ -7051,7 +6717,9 @@ extern "C" {
     size_t i;
     for (i = 0; methods[i].ml_name; ++i) {
       const char *c = methods[i].ml_doc;
-      if (c && (c = strstr(c, "swig_ptr: "))) {
+      if (!c) continue;
+      c = strstr(c, "swig_ptr: ");
+      if (c) {
         int j;
         swig_const_info *ci = 0;
         const char *name = c + 10;
@@ -7153,6 +6821,7 @@ SWIG_init(void) {
   PyObject *public_interface, *public_symbol;
   PyObject *this_descr;
   PyObject *thisown_descr;
+  PyObject *self = 0;
   int i;
   
   (void)builtin_pytype;
@@ -7160,6 +6829,7 @@ SWIG_init(void) {
   (void)builtin_basetype;
   (void)tuple;
   (void)static_getset;
+  (void)self;
   
   /* metatype is used to implement static member variables. */
   metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
@@ -7179,6 +6849,7 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
+  
   md = d = PyModule_GetDict(m);
   (void)md;
   
@@ -7222,12 +6893,9 @@ SWIG_init(void) {
   
   SWIG_InstallConstants(d,swig_const_table);
   
-  SWIG_Python_SetConstant(d, "GATDijkstraShortestPath",SWIG_From_int(static_cast< int >(GATDijkstraShortestPath)));
-  SWIG_Python_SetConstant(d, "GATKShortestPath",SWIG_From_int(static_cast< int >(GATKShortestPath)));
-  SWIG_Python_SetConstant(d, "GATConnectedComponents",SWIG_From_int(static_cast< int >(GATConnectedComponents)));
-  SWIG_Python_SetConstant(d, "GNM_EDGE_DIR_BOTH",SWIG_From_int(static_cast< int >(0)));
-  SWIG_Python_SetConstant(d, "GNM_EDGE_DIR_SRCTOTGT",SWIG_From_int(static_cast< int >(1)));
-  SWIG_Python_SetConstant(d, "GNM_EDGE_DIR_TGTTOSRC",SWIG_From_int(static_cast< int >(2)));
+  
+  /* Initialize threading */
+  SWIG_PYTHON_INITIALIZE_THREADS;
 #if PY_VERSION_HEX >= 0x03000000
   return m;
 #else
diff --git a/swig/python/extensions/ogr_wrap.cpp b/swig/python/extensions/ogr_wrap.cpp
index 8c9a50d..0696dcb 100644
--- a/swig/python/extensions/ogr_wrap.cpp
+++ b/swig/python/extensions/ogr_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
+ * Version 3.0.8
  *
  * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -8,8 +8,13 @@
  * interface file instead.
  * ----------------------------------------------------------------------------- */
 
+
+#ifndef SWIGPYTHON
 #define SWIGPYTHON
 #define SED_HACKS
+#endif
+
+#define SWIG_PYTHON_THREADS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 
@@ -144,6 +149,19 @@ template <typename T> T SwigValueInit() {
 # define _SCL_SECURE_NO_DEPRECATE
 #endif
 
+/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
+#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
+# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
+/* Intel's compiler complains if a variable which was never initialised is
+ * cast to void, which is a common idiom which we use to indicate that we
+ * are aware a variable isn't used.  So we just silence that warning.
+ * See: https://github.com/swig/swig/issues/192 for more discussion.
+ */
+#ifdef __INTEL_COMPILER
+# pragma warning disable 592
+#endif
 
 
 #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
@@ -561,14 +579,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   swig_module_info *iter = start;
   do {
     if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
+      size_t l = 0;
+      size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
+	size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
-	  register int compare = strcmp(name, iname);
+	  int compare = strcmp(name, iname);
 	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
@@ -612,7 +630,7 @@ SWIG_TypeQueryModule(swig_module_info *start,
        of the str field (the human readable name) */
     swig_module_info *iter = start;
     do {
-      register size_t i = 0;
+      size_t i = 0;
       for (; i < iter->size; ++i) {
 	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
 	  return iter->types[i];
@@ -631,10 +649,10 @@ SWIG_TypeQueryModule(swig_module_info *start,
 SWIGRUNTIME char *
 SWIG_PackData(char *c, void *ptr, size_t sz) {
   static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
+  const unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu =  u + sz;
   for (; u != eu; ++u) {
-    register unsigned char uu = *u;
+    unsigned char uu = *u;
     *(c++) = hex[(uu & 0xf0) >> 4];
     *(c++) = hex[uu & 0xf];
   }
@@ -646,11 +664,11 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
 */
 SWIGRUNTIME const char *
 SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
+  unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu = u + sz;
   for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
+    char d = *(c++);
+    unsigned char uu;
     if ((d >= '0') && (d <= '9'))
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
@@ -1313,7 +1331,7 @@ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
 
 /* Unpack the argument tuple */
 
-SWIGINTERN int
+SWIGINTERN Py_ssize_t
 SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
 {
   if (!args) {
@@ -1327,7 +1345,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
   }  
   if (!PyTuple_Check(args)) {
     if (min <= 1 && max >= 1) {
-      register int i;
+      Py_ssize_t i;
       objs[0] = args;
       for (i = 1; i < max; ++i) {
 	objs[i] = 0;
@@ -1337,7 +1355,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
-    register Py_ssize_t l = PyTuple_GET_SIZE(args);
+    Py_ssize_t l = PyTuple_GET_SIZE(args);
     if (l < min) {
       PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
 		   name, (min == max ? "" : "at least "), (int)min, (int)l);
@@ -1347,7 +1365,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 		   name, (min == max ? "" : "at most "), (int)max, (int)l);
       return 0;
     } else {
-      register int i;
+      Py_ssize_t i;
       for (i = 0; i < l; ++i) {
 	objs[i] = PyTuple_GET_ITEM(args, i);
       }
@@ -1533,6 +1551,23 @@ typedef struct {
 #endif
 } SwigPyObject;
 
+
+#ifdef SWIGPYTHON_BUILTIN
+
+SWIGRUNTIME PyObject *
+SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+
+  if (!sobj->dict)
+    sobj->dict = PyDict_New();
+
+  Py_INCREF(sobj->dict);
+  return sobj->dict;
+}
+
+#endif
+
 SWIGRUNTIME PyObject *
 SwigPyObject_long(SwigPyObject *v)
 {
@@ -1671,16 +1706,32 @@ SwigPyObject_dealloc(PyObject *v)
     if (destroy) {
       /* destroy is always a VARARGS method */
       PyObject *res;
+
+      /* PyObject_CallFunction() has the potential to silently drop
+         the active active exception.  In cases of unnamed temporary
+         variable or where we just finished iterating over a generator
+         StopIteration will be active right now, and this needs to
+         remain true upon return from SwigPyObject_dealloc.  So save
+         and restore. */
+      
+      PyObject *val = NULL, *type = NULL, *tb = NULL;
+      PyErr_Fetch(&val, &type, &tb);
+
       if (data->delargs) {
-	/* we need to create a temporary object to carry the destroy operation */
-	PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
-	res = SWIG_Python_CallFunctor(destroy, tmp);
-	Py_DECREF(tmp);
+        /* we need to create a temporary object to carry the destroy operation */
+        PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
+        res = SWIG_Python_CallFunctor(destroy, tmp);
+        Py_DECREF(tmp);
       } else {
-	PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
-	PyObject *mself = PyCFunction_GET_SELF(destroy);
-	res = ((*meth)(mself, v));
+        PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+        PyObject *mself = PyCFunction_GET_SELF(destroy);
+        res = ((*meth)(mself, v));
       }
+      if (!res)
+        PyErr_WriteUnraisable(destroy);
+
+      PyErr_Restore(val, type, tb);
+
       Py_XDECREF(res);
     } 
 #if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
@@ -1704,6 +1755,7 @@ SwigPyObject_append(PyObject* v, PyObject* next)
   next = tmp;
 #endif
   if (!SwigPyObject_Check(next)) {
+    PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject");
     return NULL;
   }
   sobj->next = next;
@@ -1803,7 +1855,7 @@ swigobject_methods[] = {
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_VARARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS,  (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_VARARGS,  (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_VARARGS,  (char *)"returns the next 'this' object"},
@@ -1859,7 +1911,9 @@ SwigPyObject_TypeOnce(void) {
     (unaryfunc)SwigPyObject_oct,  /*nb_oct*/
     (unaryfunc)SwigPyObject_hex,  /*nb_hex*/
 #endif
-#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */
+#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
 #elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
@@ -1939,10 +1993,19 @@ SwigPyObject_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpyobject_type = tmp;
@@ -2118,10 +2181,19 @@ SwigPyPacked_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpypacked_type = tmp;
@@ -2462,7 +2534,7 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
     }
   } else {
 #if PY_VERSION_HEX >= 0x03000000
-    inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
+    inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
     if (inst) {
       PyObject_SetAttr(inst, SWIG_This(), swig_this);
       Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
@@ -2572,18 +2644,21 @@ SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int f
 	  newobj = (SwigPyObject *) newobj->next;
         newobj->next = next_self;
         newobj = (SwigPyObject *)next_self;
+#ifdef SWIGPYTHON_BUILTIN
+        newobj->dict = 0;
+#endif
       }
     } else {
       newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
     }
     if (newobj) {
       newobj->ptr = ptr;
       newobj->ty = type;
       newobj->own = own;
       newobj->next = 0;
-#ifdef SWIGPYTHON_BUILTIN
-      newobj->dict = 0;
-#endif
       return (PyObject*) newobj;
     }
     return SWIG_Py_Void();
@@ -2646,13 +2721,11 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 {
   PyObject *dict;
   if (!PyModule_Check(m)) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs module as first arg");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg");
     return SWIG_ERROR;
   }
   if (!o) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs non-NULL value");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value");
     return SWIG_ERROR;
   }
   
@@ -2986,7 +3059,7 @@ static swig_module_info swig_module = {swig_types, 23, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_ogr"
 
-#define SWIGVERSION 0x020012 
+#define SWIGVERSION 0x030008 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -3009,27 +3082,35 @@ namespace swig {
 
     SwigPtr_PyObject(const SwigPtr_PyObject& item) : _obj(item._obj)
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(_obj);      
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     SwigPtr_PyObject(PyObject *obj, bool initial_ref = true) :_obj(obj)
     {
       if (initial_ref) {
+        SWIG_PYTHON_THREAD_BEGIN_BLOCK;
         Py_XINCREF(_obj);
+        SWIG_PYTHON_THREAD_END_BLOCK;
       }
     }
     
     SwigPtr_PyObject & operator=(const SwigPtr_PyObject& item) 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(item._obj);
       Py_XDECREF(_obj);
       _obj = item._obj;
+      SWIG_PYTHON_THREAD_END_BLOCK;
       return *this;      
     }
     
     ~SwigPtr_PyObject() 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XDECREF(_obj);
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     operator PyObject *() const
@@ -3138,9 +3219,13 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
 	SWIG_InternalNewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
     } else {
 #if PY_VERSION_HEX >= 0x03000000
-      return PyUnicode_FromStringAndSize(carray, static_cast< int >(size));
+#if PY_VERSION_HEX >= 0x03010000
+      return PyUnicode_DecodeUTF8(carray, static_cast< Py_ssize_t >(size), "surrogateescape");
 #else
-      return PyString_FromStringAndSize(carray, static_cast< int >(size));
+      return PyUnicode_FromStringAndSize(carray, static_cast< Py_ssize_t >(size));
+#endif
+#else
+      return PyString_FromStringAndSize(carray, static_cast< Py_ssize_t >(size));
 #endif
     }
   } else {
@@ -3329,6 +3414,8 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
     if( pszMessage == NULL )
         pszMessage = "";
 
+    SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+
     if( psInfo->psPyCallbackData == NULL )
         psArgs = Py_BuildValue("(dsO)", dfComplete, pszMessage, Py_None );
     else
@@ -3341,16 +3428,19 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
     if( PyErr_Occurred() != NULL )
     {
         PyErr_Clear();
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return FALSE;
     }
 
     if( psResult == NULL )
     {
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return TRUE;
     }
 
     if( psResult == Py_None )
     {
+        SWIG_PYTHON_THREAD_END_BLOCK;
         return TRUE;
     }
 
@@ -3359,10 +3449,12 @@ PyProgressProxy( double dfComplete, const char *pszMessage, void *pData )
         PyErr_Clear();
         CPLError(CE_Failure, CPLE_AppDefined, "bad progress return value");
         Py_XDECREF(psResult);
-	return FALSE;
+        SWIG_PYTHON_THREAD_END_BLOCK;
+        return FALSE;
     }
 
     Py_XDECREF(psResult);
+    SWIG_PYTHON_THREAD_END_BLOCK;
 
     return bContinue;
 }
@@ -3414,18 +3506,17 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 #else
 	if (*alloc == SWIG_NEWOBJ) 
 #endif
-	  {
-	    *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
-	    *alloc = SWIG_NEWOBJ;
-	  }
-	else {
+	{
+	  *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+	  *alloc = SWIG_NEWOBJ;
+	} else {
 	  *cptr = cstr;
 	  *alloc = SWIG_OLDOBJ;
 	}
       } else {
-        #if PY_VERSION_HEX>=0x03000000
-        assert(0); /* Should never reach here in Python 3 */
-        #endif
+	#if PY_VERSION_HEX>=0x03000000
+	assert(0); /* Should never reach here in Python 3 */
+	#endif
 	*cptr = SWIG_Python_str_AsChar(obj);
       }
     }
@@ -3435,6 +3526,30 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 #endif
     return SWIG_OK;
   } else {
+#if defined(SWIG_PYTHON_2_UNICODE)
+#if PY_VERSION_HEX<0x03000000
+    if (PyUnicode_Check(obj)) {
+      char *cstr; Py_ssize_t len;
+      if (!alloc && cptr) {
+        return SWIG_RuntimeError;
+      }
+      obj = PyUnicode_AsUTF8String(obj);
+      if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) {
+        if (cptr) {
+          if (alloc) *alloc = SWIG_NEWOBJ;
+          *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+        }
+        if (psize) *psize = len + 1;
+
+        Py_XDECREF(obj);
+        return SWIG_OK;
+      } else {
+        Py_XDECREF(obj);
+      }
+    }
+#endif
+#endif
+
     swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
     if (pchar_descriptor) {
       void* vptr = 0;
@@ -3532,9 +3647,11 @@ SWIG_AsVal_double (PyObject *obj, double *val)
   if (PyFloat_Check(obj)) {
     if (val) *val = PyFloat_AsDouble(obj);
     return SWIG_OK;
+#if PY_VERSION_HEX < 0x03000000
   } else if (PyInt_Check(obj)) {
     if (val) *val = PyInt_AsLong(obj);
     return SWIG_OK;
+#endif
   } else if (PyLong_Check(obj)) {
     double v = PyLong_AsDouble(obj);
     if (!PyErr_Occurred()) {
@@ -3608,16 +3725,20 @@ SWIG_CanCastAsInteger(double *d, double min, double max) {
 SWIGINTERN int
 SWIG_AsVal_long (PyObject *obj, long* val)
 {
+#if PY_VERSION_HEX < 0x03000000
   if (PyInt_Check(obj)) {
     if (val) *val = PyInt_AsLong(obj);
     return SWIG_OK;
-  } else if (PyLong_Check(obj)) {
+  } else
+#endif
+  if (PyLong_Check(obj)) {
     long v = PyLong_AsLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_OK;
     } else {
       PyErr_Clear();
+      return SWIG_OverflowError;
     }
   }
 #ifdef SWIG_PYTHON_CAST_MODE
@@ -4176,6 +4297,28 @@ SWIGINTERN bool OGRFeatureShadow_IsFieldSet__SWIG_1(OGRFeatureShadow *self,char
 	  return (OGR_F_IsFieldSet(self, i) > 0);
       return false;
   }
+SWIGINTERN bool OGRFeatureShadow_IsFieldNull__SWIG_0(OGRFeatureShadow *self,int id){
+    return (OGR_F_IsFieldNull(self, id) > 0);
+  }
+SWIGINTERN bool OGRFeatureShadow_IsFieldNull__SWIG_1(OGRFeatureShadow *self,char const *name){
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+	  return (OGR_F_IsFieldNull(self, i) > 0);
+      return false;
+  }
+SWIGINTERN bool OGRFeatureShadow_IsFieldSetAndNotNull__SWIG_0(OGRFeatureShadow *self,int id){
+    return (OGR_F_IsFieldSetAndNotNull(self, id) > 0);
+  }
+SWIGINTERN bool OGRFeatureShadow_IsFieldSetAndNotNull__SWIG_1(OGRFeatureShadow *self,char const *name){
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+	  CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+	  return (OGR_F_IsFieldSetAndNotNull(self, i) > 0);
+      return false;
+  }
 SWIGINTERN int OGRFeatureShadow_GetFieldIndex(OGRFeatureShadow *self,char const *name){
       // Do not issue an error if the field doesn't exist. It is intended to be silent
       return OGR_F_GetFieldIndex(self, name);
@@ -4203,6 +4346,16 @@ SWIGINTERN void OGRFeatureShadow_UnsetField__SWIG_1(OGRFeatureShadow *self,char
       else
           OGR_F_UnsetField(self, i);
   }
+SWIGINTERN void OGRFeatureShadow_SetFieldNull__SWIG_0(OGRFeatureShadow *self,int id){
+    OGR_F_SetFieldNull(self, id);
+  }
+SWIGINTERN void OGRFeatureShadow_SetFieldNull__SWIG_1(OGRFeatureShadow *self,char const *name){
+      int i = OGR_F_GetFieldIndex(self, name);
+      if (i == -1)
+          CPLError(CE_Failure, 1, FIELD_NAME_ERROR_TMPL, name);
+      else
+          OGR_F_SetFieldNull(self, i);
+  }
 SWIGINTERN void OGRFeatureShadow_SetField__SWIG_0(OGRFeatureShadow *self,int id,char const *value){
     OGR_F_SetFieldString(self, id, value);
   }
@@ -4379,6 +4532,11 @@ SWIGINTERN void OGRFeatureShadow_SetFieldString(OGRFeatureShadow *self,int id,ch
             case wkbCurvePolygon:
             case wkbMultiCurve:
             case wkbMultiSurface:
+            case wkbCurve:
+            case wkbSurface:
+            case wkbTriangle:
+            case wkbTIN:
+            case wkbPolyhedralSurface:
             case wkbNone:
             /*case wkbLinearRing:*/
             case wkbCircularStringZ:
@@ -4386,6 +4544,11 @@ SWIGINTERN void OGRFeatureShadow_SetFieldString(OGRFeatureShadow *self,int id,ch
             case wkbCurvePolygonZ:
             case wkbMultiCurveZ:
             case wkbMultiSurfaceZ:
+            case wkbCurveZ:
+            case wkbSurfaceZ:
+            case wkbTriangleZ:
+            case wkbTINZ:
+            case wkbPolyhedralSurfaceZ:
             case wkbPoint25D:
             case wkbLineString25D:
             case wkbPolygon25D:
@@ -4405,6 +4568,11 @@ SWIGINTERN void OGRFeatureShadow_SetFieldString(OGRFeatureShadow *self,int id,ch
             case wkbCurvePolygonM:
             case wkbMultiCurveM:
             case wkbMultiSurfaceM:
+            case wkbCurveM:
+            case wkbSurfaceM:
+            case wkbTriangleM:
+            case wkbTINM:
+            case wkbPolyhedralSurfaceM:
             case wkbPointZM:
             case wkbLineStringZM:
             case wkbPolygonZM:
@@ -4417,6 +4585,11 @@ SWIGINTERN void OGRFeatureShadow_SetFieldString(OGRFeatureShadow *self,int id,ch
             case wkbCurvePolygonZM:
             case wkbMultiCurveZM:
             case wkbMultiSurfaceZM:
+            case wkbCurveZM:
+            case wkbSurfaceZM:
+            case wkbTriangleZM:
+            case wkbTINZM:
+            case wkbPolyhedralSurfaceZM:
                 return TRUE;
             default:
                 CPLError(CE_Failure, CPLE_IllegalArg, "Illegal geometry type value");
@@ -4982,6 +5155,9 @@ SWIGINTERN OGRGeometryShadow *OGRGeometryShadow_SymmetricDifference(OGRGeometryS
 SWIGINTERN double OGRGeometryShadow_Distance(OGRGeometryShadow *self,OGRGeometryShadow *other){
     return OGR_G_Distance(self, other);
   }
+SWIGINTERN double OGRGeometryShadow_Distance3D(OGRGeometryShadow *self,OGRGeometryShadow *other){
+    return OGR_G_Distance3D(self, other);
+  }
 SWIGINTERN void OGRGeometryShadow_Empty(OGRGeometryShadow *self){
     OGR_G_Empty(self);
   }
@@ -5198,6 +5374,1634 @@ int GDALTermProgress_nocb( double dfProgress, const char * pszMessage=NULL, void
 #ifdef __cplusplus
 extern "C" {
 #endif
+SWIGINTERN PyObject *wkb25DBit_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkb25DBit",SWIG_From_int(static_cast< int >(0x80000000)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkb25Bit_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkb25Bit",SWIG_From_int(static_cast< int >(0x80000000)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbUnknown_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbUnknown",SWIG_From_int(static_cast< int >(0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPoint_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPoint",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbLineString_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbLineString",SWIG_From_int(static_cast< int >(2)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPolygon_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPolygon",SWIG_From_int(static_cast< int >(3)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiPoint_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiPoint",SWIG_From_int(static_cast< int >(4)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiLineString_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiLineString",SWIG_From_int(static_cast< int >(5)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiPolygon_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiPolygon",SWIG_From_int(static_cast< int >(6)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbGeometryCollection_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbGeometryCollection",SWIG_From_int(static_cast< int >(7)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCircularString_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCircularString",SWIG_From_int(static_cast< int >(8)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCompoundCurve_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCompoundCurve",SWIG_From_int(static_cast< int >(9)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCurvePolygon_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCurvePolygon",SWIG_From_int(static_cast< int >(10)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiCurve_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiCurve",SWIG_From_int(static_cast< int >(11)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiSurface_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiSurface",SWIG_From_int(static_cast< int >(12)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCurve_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCurve",SWIG_From_int(static_cast< int >(13)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbSurface_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbSurface",SWIG_From_int(static_cast< int >(14)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPolyhedralSurface_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPolyhedralSurface",SWIG_From_int(static_cast< int >(15)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbTIN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbTIN",SWIG_From_int(static_cast< int >(16)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbTriangle_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbTriangle",SWIG_From_int(static_cast< int >(17)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbNone_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbNone",SWIG_From_int(static_cast< int >(100)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbLinearRing_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbLinearRing",SWIG_From_int(static_cast< int >(101)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCircularStringZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCircularStringZ",SWIG_From_int(static_cast< int >(1008)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCompoundCurveZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCompoundCurveZ",SWIG_From_int(static_cast< int >(1009)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCurvePolygonZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCurvePolygonZ",SWIG_From_int(static_cast< int >(1010)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiCurveZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiCurveZ",SWIG_From_int(static_cast< int >(1011)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiSurfaceZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiSurfaceZ",SWIG_From_int(static_cast< int >(1012)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCurveZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCurveZ",SWIG_From_int(static_cast< int >(1013)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbSurfaceZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbSurfaceZ",SWIG_From_int(static_cast< int >(1014)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPolyhedralSurfaceZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPolyhedralSurfaceZ",SWIG_From_int(static_cast< int >(1015)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbTINZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbTINZ",SWIG_From_int(static_cast< int >(1016)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbTriangleZ_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbTriangleZ",SWIG_From_int(static_cast< int >(1017)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPointM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPointM",SWIG_From_int(static_cast< int >(2001)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbLineStringM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbLineStringM",SWIG_From_int(static_cast< int >(2002)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPolygonM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPolygonM",SWIG_From_int(static_cast< int >(2003)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiPointM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiPointM",SWIG_From_int(static_cast< int >(2004)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiLineStringM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiLineStringM",SWIG_From_int(static_cast< int >(2005)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiPolygonM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiPolygonM",SWIG_From_int(static_cast< int >(2006)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbGeometryCollectionM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbGeometryCollectionM",SWIG_From_int(static_cast< int >(2007)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCircularStringM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCircularStringM",SWIG_From_int(static_cast< int >(2008)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCompoundCurveM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCompoundCurveM",SWIG_From_int(static_cast< int >(2009)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCurvePolygonM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCurvePolygonM",SWIG_From_int(static_cast< int >(2010)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiCurveM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiCurveM",SWIG_From_int(static_cast< int >(2011)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiSurfaceM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiSurfaceM",SWIG_From_int(static_cast< int >(2012)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCurveM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCurveM",SWIG_From_int(static_cast< int >(2013)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbSurfaceM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbSurfaceM",SWIG_From_int(static_cast< int >(2014)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPolyhedralSurfaceM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPolyhedralSurfaceM",SWIG_From_int(static_cast< int >(2015)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbTINM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbTINM",SWIG_From_int(static_cast< int >(2016)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbTriangleM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbTriangleM",SWIG_From_int(static_cast< int >(2017)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPointZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPointZM",SWIG_From_int(static_cast< int >(3001)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbLineStringZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbLineStringZM",SWIG_From_int(static_cast< int >(3002)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPolygonZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPolygonZM",SWIG_From_int(static_cast< int >(3003)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiPointZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiPointZM",SWIG_From_int(static_cast< int >(3004)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiLineStringZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiLineStringZM",SWIG_From_int(static_cast< int >(3005)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiPolygonZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiPolygonZM",SWIG_From_int(static_cast< int >(3006)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbGeometryCollectionZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbGeometryCollectionZM",SWIG_From_int(static_cast< int >(3007)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCircularStringZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCircularStringZM",SWIG_From_int(static_cast< int >(3008)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCompoundCurveZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCompoundCurveZM",SWIG_From_int(static_cast< int >(3009)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCurvePolygonZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCurvePolygonZM",SWIG_From_int(static_cast< int >(3010)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiCurveZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiCurveZM",SWIG_From_int(static_cast< int >(3011)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiSurfaceZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiSurfaceZM",SWIG_From_int(static_cast< int >(3012)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbCurveZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbCurveZM",SWIG_From_int(static_cast< int >(3013)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbSurfaceZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbSurfaceZM",SWIG_From_int(static_cast< int >(3014)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPolyhedralSurfaceZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPolyhedralSurfaceZM",SWIG_From_int(static_cast< int >(3015)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbTINZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbTINZM",SWIG_From_int(static_cast< int >(3016)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbTriangleZM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbTriangleZM",SWIG_From_int(static_cast< int >(3017)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPoint25D_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPoint25D",SWIG_From_int(static_cast< int >(0x80000001)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbLineString25D_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbLineString25D",SWIG_From_int(static_cast< int >(0x80000002)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbPolygon25D_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbPolygon25D",SWIG_From_int(static_cast< int >(0x80000003)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiPoint25D_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiPoint25D",SWIG_From_int(static_cast< int >(0x80000004)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiLineString25D_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiLineString25D",SWIG_From_int(static_cast< int >(0x80000005)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbMultiPolygon25D_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbMultiPolygon25D",SWIG_From_int(static_cast< int >(0x80000006)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbGeometryCollection25D_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbGeometryCollection25D",SWIG_From_int(static_cast< int >(0x80000007)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTInteger_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTInteger",SWIG_From_int(static_cast< int >(0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTIntegerList_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTIntegerList",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTReal_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTReal",SWIG_From_int(static_cast< int >(2)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTRealList_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTRealList",SWIG_From_int(static_cast< int >(3)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTString_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTString",SWIG_From_int(static_cast< int >(4)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTStringList_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTStringList",SWIG_From_int(static_cast< int >(5)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTWideString_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTWideString",SWIG_From_int(static_cast< int >(6)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTWideStringList_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTWideStringList",SWIG_From_int(static_cast< int >(7)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTBinary_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTBinary",SWIG_From_int(static_cast< int >(8)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTDate_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTDate",SWIG_From_int(static_cast< int >(9)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTTime_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTTime",SWIG_From_int(static_cast< int >(10)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTDateTime_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTDateTime",SWIG_From_int(static_cast< int >(11)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTInteger64_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTInteger64",SWIG_From_int(static_cast< int >(12)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFTInteger64List_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFTInteger64List",SWIG_From_int(static_cast< int >(13)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFSTNone_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFSTNone",SWIG_From_int(static_cast< int >(0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFSTBoolean_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFSTBoolean",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFSTInt16_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFSTInt16",SWIG_From_int(static_cast< int >(2)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OFSTFloat32_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OFSTFloat32",SWIG_From_int(static_cast< int >(3)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OJUndefined_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OJUndefined",SWIG_From_int(static_cast< int >(0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OJLeft_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OJLeft",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OJRight_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OJRight",SWIG_From_int(static_cast< int >(2)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbXDR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbXDR",SWIG_From_int(static_cast< int >(0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *wkbNDR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "wkbNDR",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *NullFID_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "NullFID",SWIG_From_int(static_cast< int >(-1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ALTER_NAME_FLAG_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ALTER_NAME_FLAG",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ALTER_TYPE_FLAG_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ALTER_TYPE_FLAG",SWIG_From_int(static_cast< int >(2)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ALTER_WIDTH_PRECISION_FLAG_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ALTER_WIDTH_PRECISION_FLAG",SWIG_From_int(static_cast< int >(4)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ALTER_NULLABLE_FLAG_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ALTER_NULLABLE_FLAG",SWIG_From_int(static_cast< int >(8)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ALTER_DEFAULT_FLAG_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ALTER_DEFAULT_FLAG",SWIG_From_int(static_cast< int >(16)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ALTER_ALL_FLAG_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ALTER_ALL_FLAG",SWIG_From_int(static_cast< int >(1+2+4+8+16)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *F_VAL_NULL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "F_VAL_NULL",SWIG_From_int(static_cast< int >(0x00000001)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *F_VAL_GEOM_TYPE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "F_VAL_GEOM_TYPE",SWIG_From_int(static_cast< int >(0x00000002)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *F_VAL_WIDTH_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "F_VAL_WIDTH",SWIG_From_int(static_cast< int >(0x00000004)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *F_VAL_ALLOW_NULL_WHEN_DEFAULT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "F_VAL_ALLOW_NULL_WHEN_DEFAULT",SWIG_From_int(static_cast< int >(0x00000008)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *F_VAL_ALL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "F_VAL_ALL",SWIG_From_int(static_cast< int >(0xFFFFFFFF)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCRandomRead_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCRandomRead",SWIG_FromCharPtr("RandomRead"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCSequentialWrite_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCSequentialWrite",SWIG_FromCharPtr("SequentialWrite"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCRandomWrite_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCRandomWrite",SWIG_FromCharPtr("RandomWrite"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCFastSpatialFilter_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCFastSpatialFilter",SWIG_FromCharPtr("FastSpatialFilter"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCFastFeatureCount_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCFastFeatureCount",SWIG_FromCharPtr("FastFeatureCount"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCFastGetExtent_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCFastGetExtent",SWIG_FromCharPtr("FastGetExtent"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCCreateField_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCCreateField",SWIG_FromCharPtr("CreateField"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCDeleteField_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCDeleteField",SWIG_FromCharPtr("DeleteField"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCReorderFields_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCReorderFields",SWIG_FromCharPtr("ReorderFields"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCAlterFieldDefn_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCAlterFieldDefn",SWIG_FromCharPtr("AlterFieldDefn"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCTransactions_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCTransactions",SWIG_FromCharPtr("Transactions"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCDeleteFeature_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCDeleteFeature",SWIG_FromCharPtr("DeleteFeature"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCFastSetNextByIndex_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCFastSetNextByIndex",SWIG_FromCharPtr("FastSetNextByIndex"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCStringsAsUTF8_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCStringsAsUTF8",SWIG_FromCharPtr("StringsAsUTF8"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCIgnoreFields_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCIgnoreFields",SWIG_FromCharPtr("IgnoreFields"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCCreateGeomField_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCCreateGeomField",SWIG_FromCharPtr("CreateGeomField"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCCurveGeometries_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCCurveGeometries",SWIG_FromCharPtr("CurveGeometries"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLCMeasuredGeometries_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLCMeasuredGeometries",SWIG_FromCharPtr("MeasuredGeometries"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODsCCreateLayer_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODsCCreateLayer",SWIG_FromCharPtr("CreateLayer"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODsCDeleteLayer_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODsCDeleteLayer",SWIG_FromCharPtr("DeleteLayer"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODsCCreateGeomFieldAfterCreateLayer_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODsCCreateGeomFieldAfterCreateLayer",SWIG_FromCharPtr("CreateGeomFieldAfterCreateLayer"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODsCCurveGeometries_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODsCCurveGeometries",SWIG_FromCharPtr("CurveGeometries"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODsCTransactions_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODsCTransactions",SWIG_FromCharPtr("Transactions"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODsCEmulatedTransactions_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODsCEmulatedTransactions",SWIG_FromCharPtr("EmulatedTransactions"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODsCMeasuredGeometries_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODsCMeasuredGeometries",SWIG_FromCharPtr("MeasuredGeometries"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODsCRandomLayerRead_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODsCRandomLayerRead",SWIG_FromCharPtr("RandomLayerRead"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODsCRandomLayerWrite_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODsCRandomLayerWrite",SWIG_FromCharPtr("RandomLayerWrite"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODrCCreateDataSource_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODrCCreateDataSource",SWIG_FromCharPtr("CreateDataSource"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *ODrCDeleteDataSource_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "ODrCDeleteDataSource",SWIG_FromCharPtr("DeleteDataSource"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OLMD_FID64_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OLMD_FID64",SWIG_FromCharPtr("OLMD_FID64"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_NONE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_NONE",SWIG_From_int(static_cast< int >(0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_NOT_ENOUGH_DATA_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_NOT_ENOUGH_DATA",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_NOT_ENOUGH_MEMORY_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_NOT_ENOUGH_MEMORY",SWIG_From_int(static_cast< int >(2)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_UNSUPPORTED_GEOMETRY_TYPE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_UNSUPPORTED_GEOMETRY_TYPE",SWIG_From_int(static_cast< int >(3)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_UNSUPPORTED_OPERATION_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_UNSUPPORTED_OPERATION",SWIG_From_int(static_cast< int >(4)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_CORRUPT_DATA_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_CORRUPT_DATA",SWIG_From_int(static_cast< int >(5)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_FAILURE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_FAILURE",SWIG_From_int(static_cast< int >(6)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_UNSUPPORTED_SRS_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_UNSUPPORTED_SRS",SWIG_From_int(static_cast< int >(7)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_INVALID_HANDLE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_INVALID_HANDLE",SWIG_From_int(static_cast< int >(8)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OGRERR_NON_EXISTING_FEATURE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OGRERR_NON_EXISTING_FEATURE",SWIG_From_int(static_cast< int >(9)));
+  return SWIG_Py_Void();
+}
+
+
 SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   int result;
@@ -5256,7 +7060,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetDescription(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALMajorObjectShadow_GetDescription(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5306,7 +7114,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetDescription(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      GDALMajorObjectShadow_SetDescription(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5344,7 +7156,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataDomainList(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GDALMajorObjectShadow_GetMetadataDomainList(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5408,7 +7224,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_Dict(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GDALMajorObjectShadow_GetMetadata_Dict(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5481,7 +7301,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadata_List(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)GDALMajorObjectShadow_GetMetadata_List(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5611,7 +7435,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_0(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_0(arg1,arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5679,7 +7507,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata__SWIG_1(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GDALMajorObjectShadow_SetMetadata__SWIG_1(arg1,arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5702,12 +7534,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_MajorObject_SetMetadata(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[4];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[4] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -5811,7 +7645,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_GetMetadataItem(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)GDALMajorObjectShadow_GetMetadataItem(arg1,(char const *)arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5888,7 +7726,11 @@ SWIGINTERN PyObject *_wrap_MajorObject_SetMetadataItem(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (CPLErr)GDALMajorObjectShadow_SetMetadataItem(arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5928,7 +7770,11 @@ SWIGINTERN PyObject *_wrap_new_StyleTable(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRStyleTableShadow *)new_OGRStyleTableShadow();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRStyleTableShadow *)new_OGRStyleTableShadow();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -5963,7 +7809,11 @@ SWIGINTERN PyObject *_wrap_delete_StyleTable(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRStyleTableShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_OGRStyleTableShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6019,7 +7869,11 @@ SWIGINTERN PyObject *_wrap_StyleTable_AddStyle(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRStyleTableShadow_AddStyle(arg1,(char const *)arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRStyleTableShadow_AddStyle(arg1,(char const *)arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6071,7 +7925,11 @@ SWIGINTERN PyObject *_wrap_StyleTable_LoadStyleTable(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRStyleTableShadow_LoadStyleTable(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRStyleTableShadow_LoadStyleTable(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6127,7 +7985,11 @@ SWIGINTERN PyObject *_wrap_StyleTable_SaveStyleTable(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRStyleTableShadow_SaveStyleTable(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRStyleTableShadow_SaveStyleTable(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6181,7 +8043,11 @@ SWIGINTERN PyObject *_wrap_StyleTable_Find(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRStyleTableShadow_Find(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRStyleTableShadow_Find(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6218,7 +8084,11 @@ SWIGINTERN PyObject *_wrap_StyleTable_ResetStyleStringReading(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRStyleTableShadow_ResetStyleStringReading(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRStyleTableShadow_ResetStyleStringReading(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6254,7 +8124,11 @@ SWIGINTERN PyObject *_wrap_StyleTable_GetNextStyle(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRStyleTableShadow_GetNextStyle(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRStyleTableShadow_GetNextStyle(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6290,7 +8164,11 @@ SWIGINTERN PyObject *_wrap_StyleTable_GetLastStyleName(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRStyleTableShadow_GetLastStyleName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRStyleTableShadow_GetLastStyleName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6333,7 +8211,11 @@ SWIGINTERN PyObject *_wrap_Driver_name_get(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRDriverShadow_name_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRDriverShadow_name_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6436,7 +8318,11 @@ SWIGINTERN PyObject *_wrap_Driver_CreateDataSource(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRDataSourceShadow *)OGRDriverShadow_CreateDataSource(arg1,(char const *)arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6564,7 +8450,11 @@ SWIGINTERN PyObject *_wrap_Driver_CopyDataSource(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRDataSourceShadow *)OGRDriverShadow_CopyDataSource(arg1,arg2,(char const *)arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6642,7 +8532,11 @@ SWIGINTERN PyObject *_wrap_Driver_Open(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRDataSourceShadow *)OGRDriverShadow_Open(arg1,(char const *)arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6908,7 +8802,11 @@ SWIGINTERN PyObject *_wrap_DataSource_name_get(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRDataSourceShadow_name_get(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRDataSourceShadow_name_get(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6943,7 +8841,11 @@ SWIGINTERN PyObject *_wrap_delete_DataSource(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRDataSourceShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_OGRDataSourceShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -6979,7 +8881,11 @@ SWIGINTERN PyObject *_wrap_DataSource_GetRefCount(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRDataSourceShadow_GetRefCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRDataSourceShadow_GetRefCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7015,7 +8921,11 @@ SWIGINTERN PyObject *_wrap_DataSource_GetSummaryRefCount(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRDataSourceShadow_GetSummaryRefCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7051,7 +8961,11 @@ SWIGINTERN PyObject *_wrap_DataSource_GetLayerCount(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRDataSourceShadow_GetLayerCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7087,7 +9001,11 @@ SWIGINTERN PyObject *_wrap_DataSource_GetDriver(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRDriverShadow *)OGRDataSourceShadow_GetDriver(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7123,7 +9041,11 @@ SWIGINTERN PyObject *_wrap_DataSource_GetName(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRDataSourceShadow_GetName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRDataSourceShadow_GetName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7168,7 +9090,11 @@ SWIGINTERN PyObject *_wrap_DataSource_DeleteLayer(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRDataSourceShadow_DeleteLayer(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7181,6 +9107,10 @@ SWIGINTERN PyObject *_wrap_DataSource_DeleteLayer(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7216,7 +9146,11 @@ SWIGINTERN PyObject *_wrap_DataSource_SyncToDisk(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRDataSourceShadow_SyncToDisk(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7229,6 +9163,10 @@ SWIGINTERN PyObject *_wrap_DataSource_SyncToDisk(PyObject *SWIGUNUSEDPARM(self),
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7263,7 +9201,11 @@ SWIGINTERN PyObject *_wrap_DataSource_FlushCache(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRDataSourceShadow_FlushCache(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRDataSourceShadow_FlushCache(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7391,7 +9333,11 @@ SWIGINTERN PyObject *_wrap_DataSource_CreateLayer(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)OGRDataSourceShadow_CreateLayer(arg1,(char const *)arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7516,7 +9462,11 @@ SWIGINTERN PyObject *_wrap_DataSource_CopyLayer(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)OGRDataSourceShadow_CopyLayer(arg1,arg2,(char const *)arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7573,7 +9523,11 @@ SWIGINTERN PyObject *_wrap_DataSource_GetLayerByIndex(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByIndex(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7619,7 +9573,11 @@ SWIGINTERN PyObject *_wrap_DataSource_GetLayerByName(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)OGRDataSourceShadow_GetLayerByName(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7672,7 +9630,11 @@ SWIGINTERN PyObject *_wrap_DataSource_TestCapability(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRDataSourceShadow_TestCapability(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7751,7 +9713,11 @@ SWIGINTERN PyObject *_wrap_DataSource_ExecuteSQL(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRLayerShadow *)OGRDataSourceShadow_ExecuteSQL(arg1,(char const *)arg2,arg3,(char const *)arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7797,7 +9763,11 @@ SWIGINTERN PyObject *_wrap_DataSource_ReleaseResultSet(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRDataSourceShadow_ReleaseResultSet(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7833,7 +9803,11 @@ SWIGINTERN PyObject *_wrap_DataSource_GetStyleTable(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRStyleTableShadow *)OGRDataSourceShadow_GetStyleTable(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRStyleTableShadow *)OGRDataSourceShadow_GetStyleTable(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7877,7 +9851,11 @@ SWIGINTERN PyObject *_wrap_DataSource_SetStyleTable(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRDataSourceShadow_SetStyleTable(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRDataSourceShadow_SetStyleTable(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7927,7 +9905,11 @@ SWIGINTERN PyObject *_wrap_DataSource_StartTransaction(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRDataSourceShadow_StartTransaction(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRDataSourceShadow_StartTransaction(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7940,6 +9922,10 @@ SWIGINTERN PyObject *_wrap_DataSource_StartTransaction(PyObject *SWIGUNUSEDPARM(
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7975,7 +9961,11 @@ SWIGINTERN PyObject *_wrap_DataSource_CommitTransaction(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRDataSourceShadow_CommitTransaction(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRDataSourceShadow_CommitTransaction(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -7988,6 +9978,10 @@ SWIGINTERN PyObject *_wrap_DataSource_CommitTransaction(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8023,7 +10017,11 @@ SWIGINTERN PyObject *_wrap_DataSource_RollbackTransaction(PyObject *SWIGUNUSEDPA
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRDataSourceShadow_RollbackTransaction(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRDataSourceShadow_RollbackTransaction(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8036,6 +10034,10 @@ SWIGINTERN PyObject *_wrap_DataSource_RollbackTransaction(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8078,7 +10080,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetRefCount(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRLayerShadow_GetRefCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRLayerShadow_GetRefCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8122,7 +10128,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter__SWIG_0(PyObject *SWIGUNUSEDPA
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_SetSpatialFilter__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRLayerShadow_SetSpatialFilter__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8193,7 +10203,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect__SWIG_0(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_SetSpatialFilterRect__SWIG_0(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRLayerShadow_SetSpatialFilterRect__SWIG_0(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8246,7 +10260,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter__SWIG_1(PyObject *SWIGUNUSEDPA
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_SetSpatialFilter__SWIG_1(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRLayerShadow_SetSpatialFilter__SWIG_1(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8265,12 +10283,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilter(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[4];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[4] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -8380,7 +10400,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect__SWIG_1(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_SetSpatialFilterRect__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRLayerShadow_SetSpatialFilterRect__SWIG_1(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8399,12 +10423,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Layer_SetSpatialFilterRect(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[7];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[7] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 6) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -8508,7 +10534,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetSpatialFilter(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRLayerShadow_GetSpatialFilter(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8554,7 +10584,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetAttributeFilter(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_SetAttributeFilter(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8567,6 +10601,10 @@ SWIGINTERN PyObject *_wrap_Layer_SetAttributeFilter(PyObject *SWIGUNUSEDPARM(sel
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8603,7 +10641,11 @@ SWIGINTERN PyObject *_wrap_Layer_ResetReading(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_ResetReading(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRLayerShadow_ResetReading(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8639,7 +10681,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetName(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRLayerShadow_GetName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRLayerShadow_GetName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8675,7 +10721,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetGeomType(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGRLayerShadow_GetGeomType(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8711,7 +10761,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetGeometryColumn(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRLayerShadow_GetGeometryColumn(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8747,7 +10801,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetFIDColumn(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRLayerShadow_GetFIDColumn(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8793,7 +10851,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeature(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFeatureShadow *)OGRLayerShadow_GetFeature(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8829,7 +10891,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetNextFeature(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFeatureShadow *)OGRLayerShadow_GetNextFeature(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8875,7 +10941,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetNextByIndex(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_SetNextByIndex(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8888,6 +10958,10 @@ SWIGINTERN PyObject *_wrap_Layer_SetNextByIndex(PyObject *SWIGUNUSEDPARM(self),
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8937,7 +11011,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetFeature(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_SetFeature(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -8950,6 +11028,10 @@ SWIGINTERN PyObject *_wrap_Layer_SetFeature(PyObject *SWIGUNUSEDPARM(self), PyOb
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8999,7 +11081,11 @@ SWIGINTERN PyObject *_wrap_Layer_CreateFeature(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_CreateFeature(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9012,6 +11098,10 @@ SWIGINTERN PyObject *_wrap_Layer_CreateFeature(PyObject *SWIGUNUSEDPARM(self), P
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9057,7 +11147,11 @@ SWIGINTERN PyObject *_wrap_Layer_DeleteFeature(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_DeleteFeature(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9070,6 +11164,10 @@ SWIGINTERN PyObject *_wrap_Layer_DeleteFeature(PyObject *SWIGUNUSEDPARM(self), P
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9105,7 +11203,11 @@ SWIGINTERN PyObject *_wrap_Layer_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_SyncToDisk(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9118,6 +11220,10 @@ SWIGINTERN PyObject *_wrap_Layer_SyncToDisk(PyObject *SWIGUNUSEDPARM(self), PyOb
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9153,7 +11259,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetLayerDefn(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFeatureDefnShadow *)OGRLayerShadow_GetLayerDefn(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9203,7 +11313,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeatureCount(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = OGRLayerShadow_GetFeatureCount(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = OGRLayerShadow_GetFeatureCount(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9291,7 +11405,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetExtent(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_GetExtent(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRLayerShadow_GetExtent(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9354,7 +11472,11 @@ SWIGINTERN PyObject *_wrap_Layer_TestCapability(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRLayerShadow_TestCapability(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9420,7 +11542,11 @@ SWIGINTERN PyObject *_wrap_Layer_CreateField(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_CreateField(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9433,6 +11559,10 @@ SWIGINTERN PyObject *_wrap_Layer_CreateField(PyObject *SWIGUNUSEDPARM(self), PyO
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9477,7 +11607,11 @@ SWIGINTERN PyObject *_wrap_Layer_DeleteField(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_DeleteField(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9490,6 +11624,10 @@ SWIGINTERN PyObject *_wrap_Layer_DeleteField(PyObject *SWIGUNUSEDPARM(self), PyO
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9543,7 +11681,11 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderField(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_ReorderField(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9556,6 +11698,10 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderField(PyObject *SWIGUNUSEDPARM(self), Py
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9618,7 +11764,11 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_ReorderFields(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9631,6 +11781,10 @@ SWIGINTERN PyObject *_wrap_Layer_ReorderFields(PyObject *SWIGUNUSEDPARM(self), P
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9710,7 +11864,11 @@ SWIGINTERN PyObject *_wrap_Layer_AlterFieldDefn(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_AlterFieldDefn(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9723,6 +11881,10 @@ SWIGINTERN PyObject *_wrap_Layer_AlterFieldDefn(PyObject *SWIGUNUSEDPARM(self),
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9786,7 +11948,11 @@ SWIGINTERN PyObject *_wrap_Layer_CreateGeomField(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_CreateGeomField(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_CreateGeomField(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9799,6 +11965,10 @@ SWIGINTERN PyObject *_wrap_Layer_CreateGeomField(PyObject *SWIGUNUSEDPARM(self),
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9834,7 +12004,11 @@ SWIGINTERN PyObject *_wrap_Layer_StartTransaction(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_StartTransaction(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9847,6 +12021,10 @@ SWIGINTERN PyObject *_wrap_Layer_StartTransaction(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9882,7 +12060,11 @@ SWIGINTERN PyObject *_wrap_Layer_CommitTransaction(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_CommitTransaction(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9895,6 +12077,10 @@ SWIGINTERN PyObject *_wrap_Layer_CommitTransaction(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9930,7 +12116,11 @@ SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_RollbackTransaction(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -9943,6 +12133,10 @@ SWIGINTERN PyObject *_wrap_Layer_RollbackTransaction(PyObject *SWIGUNUSEDPARM(se
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9997,7 +12191,11 @@ SWIGINTERN PyObject *_wrap_Layer_FindFieldIndex(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRLayerShadow_FindFieldIndex(arg1,(char const *)arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRLayerShadow_FindFieldIndex(arg1,(char const *)arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10035,7 +12233,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetSpatialRef(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OSRSpatialReferenceShadow *)OGRLayerShadow_GetSpatialRef(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10071,7 +12273,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetFeaturesRead(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = OGRLayerShadow_GetFeaturesRead(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = OGRLayerShadow_GetFeaturesRead(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10165,7 +12371,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_SetIgnoredFields(arg1,(char const **)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10178,6 +12388,10 @@ SWIGINTERN PyObject *_wrap_Layer_SetIgnoredFields(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10338,7 +12552,11 @@ SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_Intersection(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10351,6 +12569,10 @@ SWIGINTERN PyObject *_wrap_Layer_Intersection(PyObject *SWIGUNUSEDPARM(self), Py
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10523,7 +12745,11 @@ SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_Union(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10536,6 +12762,10 @@ SWIGINTERN PyObject *_wrap_Layer_Union(PyObject *SWIGUNUSEDPARM(self), PyObject
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10708,7 +12938,11 @@ SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_SymDifference(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10721,6 +12955,10 @@ SWIGINTERN PyObject *_wrap_Layer_SymDifference(PyObject *SWIGUNUSEDPARM(self), P
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10893,7 +13131,11 @@ SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_Identity(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -10906,6 +13148,10 @@ SWIGINTERN PyObject *_wrap_Layer_Identity(PyObject *SWIGUNUSEDPARM(self), PyObje
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11078,7 +13324,11 @@ SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_Update(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11091,6 +13341,10 @@ SWIGINTERN PyObject *_wrap_Layer_Update(PyObject *SWIGUNUSEDPARM(self), PyObject
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11263,7 +13517,11 @@ SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_Clip(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11276,6 +13534,10 @@ SWIGINTERN PyObject *_wrap_Layer_Clip(PyObject *SWIGUNUSEDPARM(self), PyObject *
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11448,7 +13710,11 @@ SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRLayerShadow_Erase(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11461,6 +13727,10 @@ SWIGINTERN PyObject *_wrap_Layer_Erase(PyObject *SWIGUNUSEDPARM(self), PyObject
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11516,7 +13786,11 @@ SWIGINTERN PyObject *_wrap_Layer_GetStyleTable(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRStyleTableShadow *)OGRLayerShadow_GetStyleTable(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRStyleTableShadow *)OGRLayerShadow_GetStyleTable(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11560,7 +13834,11 @@ SWIGINTERN PyObject *_wrap_Layer_SetStyleTable(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRLayerShadow_SetStyleTable(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRLayerShadow_SetStyleTable(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11602,7 +13880,11 @@ SWIGINTERN PyObject *_wrap_delete_Feature(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRFeatureShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_OGRFeatureShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11646,7 +13928,11 @@ SWIGINTERN PyObject *_wrap_new_Feature(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFeatureShadow *)new_OGRFeatureShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11682,7 +13968,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetDefnRef(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFeatureDefnShadow *)OGRFeatureShadow_GetDefnRef(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11727,7 +14017,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometry(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_SetGeometry(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11740,6 +14034,10 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometry(PyObject *SWIGUNUSEDPARM(self), P
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11782,7 +14080,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometryDirectly(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_SetGeometryDirectly(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11795,6 +14097,10 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeometryDirectly(PyObject *SWIGUNUSEDPARM(
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11830,7 +14136,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeometryRef(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeometryRef(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11884,7 +14194,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_0(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_0(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_0(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11897,6 +14211,10 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_0(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11956,7 +14274,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_1(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_1(arg1,(char const *)arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_SetGeomField__SWIG_1(arg1,(char const *)arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -11969,6 +14291,10 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomField__SWIG_1(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11989,12 +14315,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetGeomField(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[4];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[4] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -12080,7 +14408,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_0(PyObject *SWIGUN
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_0(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12093,6 +14425,10 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_0(PyObject *SWIGUN
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12150,7 +14486,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_1(PyObject *SWIGUN
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(arg1,(char const *)arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_SetGeomFieldDirectly__SWIG_1(arg1,(char const *)arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12163,6 +14503,10 @@ SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly__SWIG_1(PyObject *SWIGUN
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12183,12 +14527,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetGeomFieldDirectly(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[4];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[4] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -12267,7 +14613,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef__SWIG_0(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12318,7 +14668,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef__SWIG_1(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRFeatureShadow_GetGeomFieldRef__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12339,12 +14693,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldRef(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -12404,7 +14760,11 @@ SWIGINTERN PyObject *_wrap_Feature_Clone(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFeatureShadow *)OGRFeatureShadow_Clone(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12454,7 +14814,11 @@ SWIGINTERN PyObject *_wrap_Feature_Equal(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRFeatureShadow_Equal(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12490,7 +14854,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldCount(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureShadow_GetFieldCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureShadow_GetFieldCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12535,7 +14903,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_0(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12586,7 +14958,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef__SWIG_1(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFieldDefnShadow *)OGRFeatureShadow_GetFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12607,12 +14983,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldDefnRef(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -12672,7 +15050,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldCount(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureShadow_GetGeomFieldCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureShadow_GetGeomFieldCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12717,7 +15099,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef__SWIG_0(PyObject *SWIGUNU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12768,7 +15154,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef__SWIG_1(PyObject *SWIGUNU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeomFieldDefnShadow *)OGRFeatureShadow_GetGeomFieldDefnRef__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12789,12 +15179,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldDefnRef(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -12863,7 +15255,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_0(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12914,7 +15310,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString__SWIG_1(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFeatureShadow_GetFieldAsString__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -12935,12 +15335,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsString(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -13009,7 +15411,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_0(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13060,7 +15466,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger__SWIG_1(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureShadow_GetFieldAsInteger__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13081,12 +15491,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -13155,7 +15567,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64__SWIG_0(PyObject *SWIGUNU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = OGRFeatureShadow_GetFieldAsInteger64__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = OGRFeatureShadow_GetFieldAsInteger64__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13214,7 +15630,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64__SWIG_1(PyObject *SWIGUNU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = OGRFeatureShadow_GetFieldAsInteger64__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = OGRFeatureShadow_GetFieldAsInteger64__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13243,12 +15663,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -13317,7 +15739,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_0(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13368,7 +15794,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble__SWIG_1(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRFeatureShadow_GetFieldAsDouble__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13389,12 +15819,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDouble(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -13490,7 +15922,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime__SWIG_0(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsDateTime__SWIG_0(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_GetFieldAsDateTime__SWIG_0(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13610,7 +16046,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime__SWIG_1(PyObject *SWIGUNUS
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsDateTime__SWIG_1(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_GetFieldAsDateTime__SWIG_1(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13673,12 +16113,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDateTime(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -13730,8 +16172,8 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList__SWIG_0(PyObject *SWIGU
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
-  int nLen3 ;
-  int *pList3 ;
+  int nLen3 = 0 ;
+  int *pList3 = NULL ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
@@ -13755,7 +16197,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList__SWIG_0(PyObject *SWIGU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsIntegerList__SWIG_0(arg1,arg2,arg3,(int const **)arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_GetFieldAsIntegerList__SWIG_0(arg1,arg2,arg3,(int const **)arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13794,8 +16240,8 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList__SWIG_1(PyObject *SWIGU
   int res2 ;
   char *buf2 = 0 ;
   int alloc2 = 0 ;
-  int nLen3 ;
-  int *pList3 ;
+  int nLen3 = 0 ;
+  int *pList3 = NULL ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
@@ -13824,7 +16270,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList__SWIG_1(PyObject *SWIGU
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsIntegerList__SWIG_1(arg1,(char const *)arg2,arg3,(int const **)arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_GetFieldAsIntegerList__SWIG_1(arg1,(char const *)arg2,arg3,(int const **)arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13855,12 +16305,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsIntegerList(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -13912,8 +16364,8 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64List(PyObject *SWIGUNUSEDP
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
-  int nLen3 ;
-  GIntBig *pList3 ;
+  int nLen3 = 0 ;
+  GIntBig *pList3 = NULL ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
@@ -13937,7 +16389,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsInteger64List(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsInteger64List(arg1,arg2,arg3,(GIntBig const **)arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_GetFieldAsInteger64List(arg1,arg2,arg3,(GIntBig const **)arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -13982,8 +16438,8 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList__SWIG_0(PyObject *SWIGUN
   int res1 = 0 ;
   int val2 ;
   int ecode2 = 0 ;
-  int nLen3 ;
-  double *pList3 ;
+  int nLen3 = 0 ;
+  double *pList3 = NULL ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
@@ -14007,7 +16463,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList__SWIG_0(PyObject *SWIGUN
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsDoubleList__SWIG_0(arg1,arg2,arg3,(double const **)arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_GetFieldAsDoubleList__SWIG_0(arg1,arg2,arg3,(double const **)arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14046,8 +16506,8 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList__SWIG_1(PyObject *SWIGUN
   int res2 ;
   char *buf2 = 0 ;
   int alloc2 = 0 ;
-  int nLen3 ;
-  double *pList3 ;
+  int nLen3 = 0 ;
+  double *pList3 = NULL ;
   PyObject * obj0 = 0 ;
   PyObject * obj1 = 0 ;
   
@@ -14076,7 +16536,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList__SWIG_1(PyObject *SWIGUN
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_GetFieldAsDoubleList__SWIG_1(arg1,(char const *)arg2,arg3,(double const **)arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_GetFieldAsDoubleList__SWIG_1(arg1,(char const *)arg2,arg3,(double const **)arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14107,12 +16571,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsDoubleList(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -14181,7 +16647,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsStringList(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char **)OGRFeatureShadow_GetFieldAsStringList(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char **)OGRFeatureShadow_GetFieldAsStringList(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14250,7 +16720,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary__SWIG_0(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary__SWIG_0(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary__SWIG_0(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14263,6 +16737,10 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary__SWIG_0(PyObject *SWIGUNUSED
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -14343,7 +16821,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary__SWIG_1(PyObject *SWIGUNUSED
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary__SWIG_1(arg1,(char const *)arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_GetFieldAsBinary__SWIG_1(arg1,(char const *)arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14356,6 +16838,10 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary__SWIG_1(PyObject *SWIGUNUSED
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -14397,12 +16883,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldAsBinary(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -14471,7 +16959,11 @@ SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_0(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14522,7 +17014,11 @@ SWIGINTERN PyObject *_wrap_Feature_IsFieldSet__SWIG_1(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRFeatureShadow_IsFieldSet__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14543,12 +17039,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_IsFieldSet(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -14590,6 +17088,318 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Feature_IsFieldNull__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_IsFieldNull",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldNull" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldNull" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRFeatureShadow_IsFieldNull__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_IsFieldNull__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_IsFieldNull",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldNull" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_IsFieldNull" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRFeatureShadow_IsFieldNull__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_IsFieldNull(PyObject *self, PyObject *args) {
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
+  
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
+  argc = args ? PyObject_Length(args) : 0;
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_IsFieldNull__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_IsFieldNull__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_IsFieldNull'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    OGRFeatureShadow::IsFieldNull(int)\n"
+    "    OGRFeatureShadow::IsFieldNull(char const *)\n");
+  return 0;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_IsFieldSetAndNotNull__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_IsFieldSetAndNotNull",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSetAndNotNull" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_IsFieldSetAndNotNull" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRFeatureShadow_IsFieldSetAndNotNull__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_IsFieldSetAndNotNull__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  bool result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_IsFieldSetAndNotNull",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_IsFieldSetAndNotNull" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_IsFieldSetAndNotNull" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRFeatureShadow_IsFieldSetAndNotNull__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_bool(static_cast< bool >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_IsFieldSetAndNotNull(PyObject *self, PyObject *args) {
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
+  
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
+  argc = args ? PyObject_Length(args) : 0;
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_IsFieldSetAndNotNull__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_IsFieldSetAndNotNull__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_IsFieldSetAndNotNull'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    OGRFeatureShadow::IsFieldSetAndNotNull(int)\n"
+    "    OGRFeatureShadow::IsFieldSetAndNotNull(char const *)\n");
+  return 0;
+}
+
+
 SWIGINTERN PyObject *_wrap_Feature_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
@@ -14623,7 +17433,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldIndex(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureShadow_GetFieldIndex(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14676,7 +17490,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetGeomFieldIndex(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14714,7 +17532,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFID(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = OGRFeatureShadow_GetFID(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = OGRFeatureShadow_GetFID(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14768,7 +17590,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFID(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_SetFID(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14781,6 +17607,10 @@ SWIGINTERN PyObject *_wrap_Feature_SetFID(PyObject *SWIGUNUSEDPARM(self), PyObje
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -14815,7 +17645,11 @@ SWIGINTERN PyObject *_wrap_Feature_DumpReadable(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_DumpReadable(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_DumpReadable(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14859,7 +17693,11 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_0(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_UnsetField__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_UnsetField__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14909,7 +17747,11 @@ SWIGINTERN PyObject *_wrap_Feature_UnsetField__SWIG_1(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_UnsetField__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_UnsetField__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -14930,12 +17772,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_UnsetField(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -14977,6 +17821,160 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_Feature_SetFieldNull__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  int arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetFieldNull",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldNull" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  ecode2 = SWIG_AsVal_int(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Feature_SetFieldNull" "', argument " "2"" of type '" "int""'");
+  } 
+  arg2 = static_cast< int >(val2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetFieldNull__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFieldNull__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Feature_SetFieldNull",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRFeatureShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Feature_SetFieldNull" "', argument " "1"" of type '" "OGRFeatureShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRFeatureShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Feature_SetFieldNull" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetFieldNull__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_Py_Void();
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Feature_SetFieldNull(PyObject *self, PyObject *args) {
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
+  
+  if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
+  argc = args ? PyObject_Length(args) : 0;
+  for (ii = 0; (ii < 2) && (ii < argc); ii++) {
+    argv[ii] = PyTuple_GET_ITEM(args,ii);
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      {
+        int res = SWIG_AsVal_int(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        return _wrap_Feature_SetFieldNull__SWIG_0(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_OGRFeatureShadow, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      int res = SWIG_AsCharPtrAndSize(argv[1], 0, NULL, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_Feature_SetFieldNull__SWIG_1(self, args);
+      }
+    }
+  }
+  
+fail:
+  SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'Feature_SetFieldNull'.\n"
+    "  Possible C/C++ prototypes are:\n"
+    "    OGRFeatureShadow::SetFieldNull(int)\n"
+    "    OGRFeatureShadow::SetFieldNull(char const *)\n");
+  return 0;
+}
+
+
 SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_0(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OGRFeatureShadow *arg1 = (OGRFeatureShadow *) 0 ;
@@ -15017,7 +18015,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_0(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetField__SWIG_0(arg1,arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15097,7 +18099,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_1(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetField__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15169,7 +18175,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldInteger64(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldInteger64(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetFieldInteger64(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15222,7 +18232,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_2(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetField__SWIG_2(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15281,7 +18295,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_3(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_3(arg1,(char const *)arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetField__SWIG_3(arg1,(char const *)arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15390,7 +18408,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_4(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_4(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetField__SWIG_4(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15503,7 +18525,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetField__SWIG_5(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetField__SWIG_5(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetField__SWIG_5(arg1,(char const *)arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15524,12 +18550,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetField(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[10];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[10] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 9) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -15788,7 +18816,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldIntegerList(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetFieldIntegerList(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15873,7 +18905,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldInteger64List(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldInteger64List(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetFieldInteger64List(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -15956,7 +18992,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldDoubleList(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetFieldDoubleList(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16062,7 +19102,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldStringList(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetFieldStringList(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16124,7 +19168,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString__SWIG_0(PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(arg1,arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_0(arg1,arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16186,7 +19234,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString__SWIG_1(PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetFieldBinaryFromHexString__SWIG_1(arg1,(char const *)arg2,(char const *)arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16209,12 +19261,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_SetFieldBinaryFromHexString(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[4];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[4] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 3) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -16310,7 +19364,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFrom(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_SetFrom(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16323,6 +19381,10 @@ SWIGINTERN PyObject *_wrap_Feature_SetFrom(PyObject *SWIGUNUSEDPARM(self), PyObj
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -16408,7 +19470,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetFromWithMap(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureShadow_SetFromWithMap(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16421,6 +19487,10 @@ SWIGINTERN PyObject *_wrap_Feature_SetFromWithMap(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -16468,7 +19538,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetStyleString(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFeatureShadow_GetStyleString(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFeatureShadow_GetStyleString(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16513,7 +19587,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetStyleString(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetStyleString(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16560,7 +19638,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_0(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_0(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16611,7 +19693,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetFieldType__SWIG_1(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFieldType)OGRFeatureShadow_GetFieldType__SWIG_1(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16632,12 +19718,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_Feature_GetFieldType(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[3];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[3] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 2) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -16719,7 +19807,11 @@ SWIGINTERN PyObject *_wrap_Feature_Validate(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureShadow_Validate(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureShadow_Validate(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16817,7 +19909,11 @@ SWIGINTERN PyObject *_wrap_Feature_FillUnsetWithDefault(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_FillUnsetWithDefault(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_FillUnsetWithDefault(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16861,7 +19957,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetNativeData(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFeatureShadow_GetNativeData(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFeatureShadow_GetNativeData(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16897,7 +19997,11 @@ SWIGINTERN PyObject *_wrap_Feature_GetNativeMediaType(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFeatureShadow_GetNativeMediaType(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFeatureShadow_GetNativeMediaType(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16942,7 +20046,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetNativeData(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetNativeData(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetNativeData(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -16989,7 +20097,11 @@ SWIGINTERN PyObject *_wrap_Feature_SetNativeMediaType(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureShadow_SetNativeMediaType(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureShadow_SetNativeMediaType(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17097,7 +20209,11 @@ SWIGINTERN PyObject *_wrap_delete_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRFeatureDefnShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_OGRFeatureDefnShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17139,7 +20255,11 @@ SWIGINTERN PyObject *_wrap_new_FeatureDefn(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFeatureDefnShadow *)new_OGRFeatureDefnShadow((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17177,7 +20297,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetName(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFeatureDefnShadow_GetName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFeatureDefnShadow_GetName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17213,7 +20337,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldCount(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureDefnShadow_GetFieldCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17258,7 +20386,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldDefn(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFieldDefnShadow *)OGRFeatureDefnShadow_GetFieldDefn(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17309,7 +20441,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetFieldIndex(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureDefnShadow_GetFieldIndex(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17360,7 +20496,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_AddFieldDefn(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureDefnShadow_AddFieldDefn(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17396,7 +20536,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldCount(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_GetGeomFieldCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureDefnShadow_GetGeomFieldCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17441,7 +20585,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldDefn(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeomFieldDefnShadow *)OGRFeatureDefnShadow_GetGeomFieldDefn(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17492,7 +20640,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomFieldIndex(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureDefnShadow_GetGeomFieldIndex(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17543,7 +20695,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_AddGeomFieldDefn(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureDefnShadow_AddGeomFieldDefn(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureDefnShadow_AddGeomFieldDefn(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17588,7 +20744,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_DeleteGeomFieldDefn(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRFeatureDefnShadow_DeleteGeomFieldDefn(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRFeatureDefnShadow_DeleteGeomFieldDefn(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17601,6 +20761,10 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_DeleteGeomFieldDefn(PyObject *SWIGUNUSEDP
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -17636,7 +20800,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetGeomType(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGRFeatureDefnShadow_GetGeomType(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17680,7 +20848,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeomType(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureDefnShadow_SetGeomType(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17716,7 +20888,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_GetReferenceCount(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureDefnShadow_GetReferenceCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17752,7 +20928,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_IsGeometryIgnored(PyObject *SWIGUNUSEDPAR
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureDefnShadow_IsGeometryIgnored(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17796,7 +20976,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_SetGeometryIgnored(PyObject *SWIGUNUSEDPA
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureDefnShadow_SetGeometryIgnored(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17832,7 +21016,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_IsStyleIgnored(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureDefnShadow_IsStyleIgnored(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17876,7 +21064,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_SetStyleIgnored(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFeatureDefnShadow_SetStyleIgnored(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17926,7 +21118,11 @@ SWIGINTERN PyObject *_wrap_FeatureDefn_IsSame(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFeatureDefnShadow_IsSame(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFeatureDefnShadow_IsSame(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -17968,7 +21164,11 @@ SWIGINTERN PyObject *_wrap_delete_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRFieldDefnShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_OGRFieldDefnShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18021,7 +21221,11 @@ SWIGINTERN PyObject *_wrap_new_FieldDefn(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFieldDefnShadow *)new_OGRFieldDefnShadow((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18059,7 +21263,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFieldDefnShadow_GetName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFieldDefnShadow_GetName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18095,7 +21303,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetNameRef(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFieldDefnShadow_GetNameRef(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18145,7 +21357,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFieldDefnShadow_SetName(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18183,7 +21399,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFieldType)OGRFieldDefnShadow_GetType(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18227,7 +21447,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetType(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetType(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFieldDefnShadow_SetType(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18263,7 +21487,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetSubType(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRFieldSubType)OGRFieldDefnShadow_GetSubType(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRFieldSubType)OGRFieldDefnShadow_GetSubType(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18307,7 +21535,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetSubType(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetSubType(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFieldDefnShadow_SetSubType(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18343,7 +21575,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetJustify(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRJustification)OGRFieldDefnShadow_GetJustify(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18387,7 +21623,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetJustify(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetJustify(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFieldDefnShadow_SetJustify(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18423,7 +21663,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetWidth(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFieldDefnShadow_GetWidth(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFieldDefnShadow_GetWidth(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18467,7 +21711,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetWidth(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetWidth(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFieldDefnShadow_SetWidth(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18503,7 +21751,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetPrecision(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFieldDefnShadow_GetPrecision(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18547,7 +21799,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetPrecision(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetPrecision(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFieldDefnShadow_SetPrecision(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18583,7 +21839,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetTypeName(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFieldDefnShadow_GetTypeName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18628,7 +21888,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetFieldTypeName(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFieldDefnShadow_GetFieldTypeName(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18664,7 +21928,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_IsIgnored(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFieldDefnShadow_IsIgnored(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18708,7 +21976,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetIgnored(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFieldDefnShadow_SetIgnored(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18744,7 +22016,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_IsNullable(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFieldDefnShadow_IsNullable(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFieldDefnShadow_IsNullable(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18788,7 +22064,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetNullable(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetNullable(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFieldDefnShadow_SetNullable(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18824,7 +22104,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_GetDefault(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRFieldDefnShadow_GetDefault(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRFieldDefnShadow_GetDefault(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18869,7 +22153,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_SetDefault(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRFieldDefnShadow_SetDefault(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRFieldDefnShadow_SetDefault(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18907,7 +22195,11 @@ SWIGINTERN PyObject *_wrap_FieldDefn_IsDefaultDriverSpecific(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRFieldDefnShadow_IsDefaultDriverSpecific(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRFieldDefnShadow_IsDefaultDriverSpecific(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -18949,7 +22241,11 @@ SWIGINTERN PyObject *_wrap_delete_GeomFieldDefn(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRGeomFieldDefnShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_OGRGeomFieldDefnShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19002,7 +22298,11 @@ SWIGINTERN PyObject *_wrap_new_GeomFieldDefn(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeomFieldDefnShadow *)new_OGRGeomFieldDefnShadow((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeomFieldDefnShadow *)new_OGRGeomFieldDefnShadow((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19040,7 +22340,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetName(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRGeomFieldDefnShadow_GetName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRGeomFieldDefnShadow_GetName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19076,7 +22380,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetNameRef(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRGeomFieldDefnShadow_GetNameRef(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRGeomFieldDefnShadow_GetNameRef(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19126,7 +22434,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetName(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeomFieldDefnShadow_SetName(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeomFieldDefnShadow_SetName(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19164,7 +22476,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetType(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGRGeomFieldDefnShadow_GetType(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGRGeomFieldDefnShadow_GetType(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19208,7 +22524,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetType(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeomFieldDefnShadow_SetType(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeomFieldDefnShadow_SetType(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19244,7 +22564,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_GetSpatialRef(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OSRSpatialReferenceShadow *)OGRGeomFieldDefnShadow_GetSpatialRef(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OSRSpatialReferenceShadow *)OGRGeomFieldDefnShadow_GetSpatialRef(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19288,7 +22612,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetSpatialRef(PyObject *SWIGUNUSEDPARM(
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeomFieldDefnShadow_SetSpatialRef(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeomFieldDefnShadow_SetSpatialRef(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19324,7 +22652,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_IsIgnored(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeomFieldDefnShadow_IsIgnored(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeomFieldDefnShadow_IsIgnored(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19368,7 +22700,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetIgnored(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeomFieldDefnShadow_SetIgnored(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeomFieldDefnShadow_SetIgnored(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19404,7 +22740,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_IsNullable(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeomFieldDefnShadow_IsNullable(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeomFieldDefnShadow_IsNullable(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19448,7 +22788,11 @@ SWIGINTERN PyObject *_wrap_GeomFieldDefn_SetNullable(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeomFieldDefnShadow_SetNullable(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeomFieldDefnShadow_SetNullable(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19501,12 +22845,18 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromWkb(PyObject *SWIGUNUSEDPARM(self),
       }
       
       if (safeLen) safeLen--;
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
       arg1 = (int) safeLen;
     }
     else if (PyBytes_Check(obj0))
     {
       Py_ssize_t safeLen = 0;
       PyBytes_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
       arg1 = (int) safeLen;
     }
     else
@@ -19519,6 +22869,9 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromWkb(PyObject *SWIGUNUSEDPARM(self),
     {
       Py_ssize_t safeLen = 0;
       PyString_AsStringAndSize(obj0, (char**) &arg2, &safeLen);
+      if( safeLen > INT_MAX ) {
+        SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+      }
       arg1 = (int) safeLen;
     }
     else
@@ -19539,7 +22892,11 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromWkb(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)CreateGeometryFromWkb(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)CreateGeometryFromWkb(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19603,7 +22960,11 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromWkt(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)CreateGeometryFromWkt(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)CreateGeometryFromWkt(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19640,7 +23001,11 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromGML(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)CreateGeometryFromGML((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)CreateGeometryFromGML((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19679,7 +23044,11 @@ SWIGINTERN PyObject *_wrap_CreateGeometryFromJson(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)CreateGeometryFromJson((char const *)arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)CreateGeometryFromJson((char const *)arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19753,7 +23122,11 @@ SWIGINTERN PyObject *_wrap_BuildPolygonFromEdges(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)BuildPolygonFromEdges(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)BuildPolygonFromEdges(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19864,7 +23237,11 @@ SWIGINTERN PyObject *_wrap_ApproximateArcAngles(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)ApproximateArcAngles(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)ApproximateArcAngles(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19900,7 +23277,11 @@ SWIGINTERN PyObject *_wrap_ForceToPolygon(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)ForceToPolygon(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)ForceToPolygon(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19936,7 +23317,11 @@ SWIGINTERN PyObject *_wrap_ForceToLineString(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)ForceToLineString(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)ForceToLineString(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -19972,7 +23357,11 @@ SWIGINTERN PyObject *_wrap_ForceToMultiPolygon(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)ForceToMultiPolygon(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)ForceToMultiPolygon(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20008,7 +23397,11 @@ SWIGINTERN PyObject *_wrap_ForceToMultiPoint(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)ForceToMultiPoint(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)ForceToMultiPoint(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20044,7 +23437,11 @@ SWIGINTERN PyObject *_wrap_ForceToMultiLineString(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)ForceToMultiLineString(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)ForceToMultiLineString(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20141,7 +23538,11 @@ SWIGINTERN PyObject *_wrap_ForceTo(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)ForceTo(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)ForceTo(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20184,7 +23585,11 @@ SWIGINTERN PyObject *_wrap_delete_Geometry(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    delete_OGRGeometryShadow(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      delete_OGRGeometryShadow(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20255,12 +23660,18 @@ SWIGINTERN PyObject *_wrap_new_Geometry(PyObject *SWIGUNUSEDPARM(self), PyObject
         }
         
         if (safeLen) safeLen--;
+        if( safeLen > INT_MAX ) {
+          SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+        }
         arg3 = (int) safeLen;
       }
       else if (PyBytes_Check(obj2))
       {
         Py_ssize_t safeLen = 0;
         PyBytes_AsStringAndSize(obj2, (char**) &arg4, &safeLen);
+        if( safeLen > INT_MAX ) {
+          SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+        }
         arg3 = (int) safeLen;
       }
       else
@@ -20273,6 +23684,9 @@ SWIGINTERN PyObject *_wrap_new_Geometry(PyObject *SWIGUNUSEDPARM(self), PyObject
       {
         Py_ssize_t safeLen = 0;
         PyString_AsStringAndSize(obj2, (char**) &arg4, &safeLen);
+        if( safeLen > INT_MAX ) {
+          SWIG_exception( SWIG_RuntimeError, "too large buffer (>2GB)" );
+        }
         arg3 = (int) safeLen;
       }
       else
@@ -20294,7 +23708,11 @@ SWIGINTERN PyObject *_wrap_new_Geometry(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)new_OGRGeometryShadow(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)new_OGRGeometryShadow(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20352,7 +23770,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToWkt(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRGeometryShadow_ExportToWkt(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRGeometryShadow_ExportToWkt(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20365,6 +23787,10 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToWkt(PyObject *SWIGUNUSEDPARM(self),
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -20428,7 +23854,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkt(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRGeometryShadow_ExportToIsoWkt(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRGeometryShadow_ExportToIsoWkt(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20441,6 +23871,10 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkt(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -20521,7 +23955,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToWkb(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRGeometryShadow_ExportToWkb(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRGeometryShadow_ExportToWkb(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20534,6 +23972,10 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToWkb(PyObject *SWIGUNUSEDPARM(self),
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -20613,7 +24055,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkb(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRGeometryShadow_ExportToIsoWkb(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRGeometryShadow_ExportToIsoWkb(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20626,6 +24072,10 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToIsoWkb(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -20737,7 +24187,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToGML(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToGML(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToGML(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20800,7 +24254,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToKML(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToKML(arg1,(char const *)arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToKML(arg1,(char const *)arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20900,7 +24358,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ExportToJson(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (retStringAndCPLFree *)OGRGeometryShadow_ExportToJson(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -20982,7 +24444,11 @@ SWIGINTERN PyObject *_wrap_Geometry_AddPoint(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_AddPoint(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_AddPoint(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21047,7 +24513,11 @@ SWIGINTERN PyObject *_wrap_Geometry_AddPointM(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_AddPointM(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_AddPointM(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21121,7 +24591,11 @@ SWIGINTERN PyObject *_wrap_Geometry_AddPointZM(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_AddPointZM(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_AddPointZM(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21174,7 +24648,11 @@ SWIGINTERN PyObject *_wrap_Geometry_AddPoint_2D(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_AddPoint_2D(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_AddPoint_2D(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21222,7 +24700,11 @@ SWIGINTERN PyObject *_wrap_Geometry_AddGeometryDirectly(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRGeometryShadow_AddGeometryDirectly(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRGeometryShadow_AddGeometryDirectly(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21235,6 +24717,10 @@ SWIGINTERN PyObject *_wrap_Geometry_AddGeometryDirectly(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -21284,7 +24770,11 @@ SWIGINTERN PyObject *_wrap_Geometry_AddGeometry(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRGeometryShadow_AddGeometry(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRGeometryShadow_AddGeometry(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21297,6 +24787,10 @@ SWIGINTERN PyObject *_wrap_Geometry_AddGeometry(PyObject *SWIGUNUSEDPARM(self),
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -21332,7 +24826,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Clone(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_Clone(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_Clone(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21368,7 +24866,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetGeometryType(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGRGeometryShadow_GetGeometryType(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGRGeometryShadow_GetGeometryType(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21404,7 +24906,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetGeometryName(PyObject *SWIGUNUSEDPARM(sel
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRGeometryShadow_GetGeometryName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRGeometryShadow_GetGeometryName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21440,7 +24946,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Length(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRGeometryShadow_Length(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRGeometryShadow_Length(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21476,7 +24986,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Area(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRGeometryShadow_Area(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRGeometryShadow_Area(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21512,7 +25026,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetArea(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRGeometryShadow_GetArea(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRGeometryShadow_GetArea(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21548,7 +25066,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPointCount(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_GetPointCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeometryShadow_GetPointCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21609,7 +25131,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoints(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_GetPoints(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_GetPoints(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21692,7 +25218,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetX(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRGeometryShadow_GetX(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRGeometryShadow_GetX(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21742,7 +25272,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetY(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRGeometryShadow_GetY(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRGeometryShadow_GetY(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21792,7 +25326,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetZ(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRGeometryShadow_GetZ(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRGeometryShadow_GetZ(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21842,7 +25380,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetM(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRGeometryShadow_GetM(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRGeometryShadow_GetM(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21895,7 +25437,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoint(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_GetPoint(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_GetPoint(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -21953,7 +25499,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPointZM(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_GetPointZM(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_GetPointZM(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22011,7 +25561,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetPoint_2D(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_GetPoint_2D(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_GetPoint_2D(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22052,7 +25606,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetGeometryCount(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_GetGeometryCount(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeometryShadow_GetGeometryCount(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22128,7 +25686,11 @@ SWIGINTERN PyObject *_wrap_Geometry_SetPoint(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_SetPoint(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_SetPoint(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22202,7 +25764,11 @@ SWIGINTERN PyObject *_wrap_Geometry_SetPointM(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_SetPointM(arg1,arg2,arg3,arg4,arg5);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_SetPointM(arg1,arg2,arg3,arg4,arg5);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22285,7 +25851,11 @@ SWIGINTERN PyObject *_wrap_Geometry_SetPointZM(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_SetPointZM(arg1,arg2,arg3,arg4,arg5,arg6);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_SetPointZM(arg1,arg2,arg3,arg4,arg5,arg6);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22350,7 +25920,11 @@ SWIGINTERN PyObject *_wrap_Geometry_SetPoint_2D(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_SetPoint_2D(arg1,arg2,arg3,arg4);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_SetPoint_2D(arg1,arg2,arg3,arg4);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22395,7 +25969,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetGeometryRef(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_GetGeometryRef(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_GetGeometryRef(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22440,7 +26018,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Simplify(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_Simplify(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_Simplify(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22485,7 +26067,11 @@ SWIGINTERN PyObject *_wrap_Geometry_SimplifyPreserveTopology(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_SimplifyPreserveTopology(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_SimplifyPreserveTopology(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22546,7 +26132,11 @@ SWIGINTERN PyObject *_wrap_Geometry_DelaunayTriangulation(PyObject *SWIGUNUSEDPA
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_DelaunayTriangulation(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_DelaunayTriangulation(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22582,7 +26172,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Boundary(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_Boundary(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_Boundary(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22618,7 +26212,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetBoundary(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_GetBoundary(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_GetBoundary(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22654,7 +26252,11 @@ SWIGINTERN PyObject *_wrap_Geometry_ConvexHull(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_ConvexHull(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_ConvexHull(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22713,7 +26315,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Buffer(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_Buffer(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_Buffer(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22763,7 +26369,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Intersection(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_Intersection(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_Intersection(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22813,7 +26423,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Union(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_Union(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_Union(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22849,7 +26463,11 @@ SWIGINTERN PyObject *_wrap_Geometry_UnionCascaded(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_UnionCascaded(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_UnionCascaded(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22899,7 +26517,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Difference(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_Difference(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_Difference(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22949,7 +26571,11 @@ SWIGINTERN PyObject *_wrap_Geometry_SymDifference(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_SymDifference(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_SymDifference(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -22999,7 +26625,11 @@ SWIGINTERN PyObject *_wrap_Geometry_SymmetricDifference(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_SymmetricDifference(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_SymmetricDifference(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23049,7 +26679,65 @@ SWIGINTERN PyObject *_wrap_Geometry_Distance(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (double)OGRGeometryShadow_Distance(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRGeometryShadow_Distance(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_double(static_cast< double >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_Geometry_Distance3D(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OGRGeometryShadow *arg1 = (OGRGeometryShadow *) 0 ;
+  OGRGeometryShadow *arg2 = (OGRGeometryShadow *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  double result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:Geometry_Distance3D",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Geometry_Distance3D" "', argument " "1"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OGRGeometryShadow * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_OGRGeometryShadow, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Geometry_Distance3D" "', argument " "2"" of type '" "OGRGeometryShadow *""'"); 
+  }
+  arg2 = reinterpret_cast< OGRGeometryShadow * >(argp2);
+  {
+    if (!arg2) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (double)OGRGeometryShadow_Distance3D(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23084,7 +26772,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Empty(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_Empty(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_Empty(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23120,7 +26812,11 @@ SWIGINTERN PyObject *_wrap_Geometry_IsEmpty(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_IsEmpty(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_IsEmpty(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23156,7 +26852,11 @@ SWIGINTERN PyObject *_wrap_Geometry_IsValid(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_IsValid(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_IsValid(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23192,7 +26892,11 @@ SWIGINTERN PyObject *_wrap_Geometry_IsSimple(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_IsSimple(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_IsSimple(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23228,7 +26932,11 @@ SWIGINTERN PyObject *_wrap_Geometry_IsRing(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_IsRing(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_IsRing(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23278,7 +26986,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Intersects(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Intersects(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Intersects(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23328,7 +27040,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Intersect(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Intersect(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Intersect(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23378,7 +27094,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Equals(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Equals(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Equals(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23428,7 +27148,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Equal(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Equal(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Equal(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23478,7 +27202,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Disjoint(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Disjoint(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Disjoint(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23528,7 +27256,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Touches(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Touches(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Touches(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23578,7 +27310,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Crosses(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Crosses(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Crosses(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23628,7 +27364,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Within(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Within(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Within(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23678,7 +27418,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Contains(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Contains(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Contains(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23728,7 +27472,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Overlaps(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (bool)OGRGeometryShadow_Overlaps(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (bool)OGRGeometryShadow_Overlaps(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23778,7 +27526,11 @@ SWIGINTERN PyObject *_wrap_Geometry_TransformTo(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRGeometryShadow_TransformTo(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRGeometryShadow_TransformTo(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23791,6 +27543,10 @@ SWIGINTERN PyObject *_wrap_Geometry_TransformTo(PyObject *SWIGUNUSEDPARM(self),
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -23840,7 +27596,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Transform(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRGeometryShadow_Transform(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRGeometryShadow_Transform(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23853,6 +27613,10 @@ SWIGINTERN PyObject *_wrap_Geometry_Transform(PyObject *SWIGUNUSEDPARM(self), Py
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -23888,7 +27652,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetSpatialReference(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OSRSpatialReferenceShadow *)OGRGeometryShadow_GetSpatialReference(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OSRSpatialReferenceShadow *)OGRGeometryShadow_GetSpatialReference(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23932,7 +27700,11 @@ SWIGINTERN PyObject *_wrap_Geometry_AssignSpatialReference(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_AssignSpatialReference(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_AssignSpatialReference(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -23967,7 +27739,11 @@ SWIGINTERN PyObject *_wrap_Geometry_CloseRings(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_CloseRings(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_CloseRings(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24002,7 +27778,11 @@ SWIGINTERN PyObject *_wrap_Geometry_FlattenTo2D(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_FlattenTo2D(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_FlattenTo2D(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24046,7 +27826,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Segmentize(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_Segmentize(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_Segmentize(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24088,7 +27872,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_GetEnvelope(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_GetEnvelope(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24135,7 +27923,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetEnvelope3D(PyObject *SWIGUNUSEDPARM(self)
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_GetEnvelope3D(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_GetEnvelope3D(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24176,7 +27968,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Centroid(PyObject *SWIGUNUSEDPARM(self), PyO
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_Centroid(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_Centroid(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24212,7 +28008,11 @@ SWIGINTERN PyObject *_wrap_Geometry_PointOnSurface(PyObject *SWIGUNUSEDPARM(self
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_PointOnSurface(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_PointOnSurface(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24248,7 +28048,11 @@ SWIGINTERN PyObject *_wrap_Geometry_WkbSize(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_WkbSize(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeometryShadow_WkbSize(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24284,7 +28088,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetCoordinateDimension(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_GetCoordinateDimension(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeometryShadow_GetCoordinateDimension(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24320,7 +28128,11 @@ SWIGINTERN PyObject *_wrap_Geometry_CoordinateDimension(PyObject *SWIGUNUSEDPARM
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_CoordinateDimension(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeometryShadow_CoordinateDimension(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24356,7 +28168,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Is3D(PyObject *SWIGUNUSEDPARM(self), PyObjec
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_Is3D(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeometryShadow_Is3D(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24392,7 +28208,11 @@ SWIGINTERN PyObject *_wrap_Geometry_IsMeasured(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_IsMeasured(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeometryShadow_IsMeasured(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24436,7 +28256,11 @@ SWIGINTERN PyObject *_wrap_Geometry_SetCoordinateDimension(PyObject *SWIGUNUSEDP
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_SetCoordinateDimension(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_SetCoordinateDimension(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24480,7 +28304,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Set3D(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_Set3D(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_Set3D(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24524,7 +28352,11 @@ SWIGINTERN PyObject *_wrap_Geometry_SetMeasured(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRGeometryShadow_SetMeasured(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRGeometryShadow_SetMeasured(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24560,7 +28392,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetDimension(PyObject *SWIGUNUSEDPARM(self),
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_GetDimension(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeometryShadow_GetDimension(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24607,7 +28443,11 @@ SWIGINTERN PyObject *_wrap_Geometry_HasCurveGeometry(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGeometryShadow_HasCurveGeometry(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGeometryShadow_HasCurveGeometry(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24709,7 +28549,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetLinearGeometry(PyObject *SWIGUNUSEDPARM(s
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_GetLinearGeometry(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_GetLinearGeometry(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24808,7 +28652,11 @@ SWIGINTERN PyObject *_wrap_Geometry_GetCurveGeometry(PyObject *SWIGUNUSEDPARM(se
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_GetCurveGeometry(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_GetCurveGeometry(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24861,7 +28709,11 @@ SWIGINTERN PyObject *_wrap_Geometry_Value(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRGeometryShadow *)OGRGeometryShadow_Value(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRGeometryShadow *)OGRGeometryShadow_Value(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24895,7 +28747,11 @@ SWIGINTERN PyObject *_wrap_GetDriverCount(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGetDriverCount();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGetDriverCount();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24922,7 +28778,11 @@ SWIGINTERN PyObject *_wrap_GetOpenDSCount(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGetOpenDSCount();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGetOpenDSCount();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24958,7 +28818,11 @@ SWIGINTERN PyObject *_wrap_SetGenerate_DB2_V72_BYTE_ORDER(PyObject *SWIGUNUSEDPA
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRErr)OGRSetGenerate_DB2_V72_BYTE_ORDER(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRErr)OGRSetGenerate_DB2_V72_BYTE_ORDER(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -24971,6 +28835,10 @@ SWIGINTERN PyObject *_wrap_SetGenerate_DB2_V72_BYTE_ORDER(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -24996,7 +28864,11 @@ SWIGINTERN PyObject *_wrap_RegisterAll(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRRegisterAll();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRRegisterAll();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25032,7 +28904,11 @@ SWIGINTERN PyObject *_wrap_GeometryTypeToName(PyObject *SWIGUNUSEDPARM(self), Py
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGRGeometryTypeToName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGRGeometryTypeToName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25068,7 +28944,11 @@ SWIGINTERN PyObject *_wrap_GetFieldTypeName(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGR_GetFieldTypeName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGR_GetFieldTypeName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25104,7 +28984,11 @@ SWIGINTERN PyObject *_wrap_GetFieldSubTypeName(PyObject *SWIGUNUSEDPARM(self), P
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (char *)OGR_GetFieldSubTypeName(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (char *)OGR_GetFieldSubTypeName(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25140,7 +29024,11 @@ SWIGINTERN PyObject *_wrap_GT_Flatten(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGR_GT_Flatten(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGR_GT_Flatten(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25176,7 +29064,11 @@ SWIGINTERN PyObject *_wrap_GT_SetZ(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGR_GT_SetZ(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGR_GT_SetZ(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25212,7 +29104,11 @@ SWIGINTERN PyObject *_wrap_GT_SetM(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGR_GT_SetM(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGR_GT_SetM(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25268,7 +29164,11 @@ SWIGINTERN PyObject *_wrap_GT_SetModifier(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)GT_SetModifier(arg1,arg2,arg3);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)GT_SetModifier(arg1,arg2,arg3);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25304,7 +29204,11 @@ SWIGINTERN PyObject *_wrap_GT_HasZ(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGR_GT_HasZ(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGR_GT_HasZ(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25340,7 +29244,11 @@ SWIGINTERN PyObject *_wrap_GT_HasM(PyObject *SWIGUNUSEDPARM(self), PyObject *arg
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGR_GT_HasM(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGR_GT_HasM(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25385,7 +29293,11 @@ SWIGINTERN PyObject *_wrap_GT_IsSubClassOf(PyObject *SWIGUNUSEDPARM(self), PyObj
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGR_GT_IsSubClassOf(arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGR_GT_IsSubClassOf(arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25421,7 +29333,11 @@ SWIGINTERN PyObject *_wrap_GT_IsCurve(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGR_GT_IsCurve(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGR_GT_IsCurve(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25457,7 +29373,11 @@ SWIGINTERN PyObject *_wrap_GT_IsSurface(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGR_GT_IsSurface(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGR_GT_IsSurface(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25493,7 +29413,11 @@ SWIGINTERN PyObject *_wrap_GT_IsNonLinear(PyObject *SWIGUNUSEDPARM(self), PyObje
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGR_GT_IsNonLinear(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGR_GT_IsNonLinear(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25529,7 +29453,11 @@ SWIGINTERN PyObject *_wrap_GT_GetCollection(PyObject *SWIGUNUSEDPARM(self), PyOb
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGR_GT_GetCollection(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGR_GT_GetCollection(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25565,7 +29493,11 @@ SWIGINTERN PyObject *_wrap_GT_GetCurve(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGR_GT_GetCurve(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGR_GT_GetCurve(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25601,7 +29533,11 @@ SWIGINTERN PyObject *_wrap_GT_GetLinear(PyObject *SWIGUNUSEDPARM(self), PyObject
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRwkbGeometryType)OGR_GT_GetLinear(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRwkbGeometryType)OGR_GT_GetLinear(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25636,7 +29572,11 @@ SWIGINTERN PyObject *_wrap_SetNonLinearGeometriesEnabledFlag(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    OGRSetNonLinearGeometriesEnabledFlag(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      OGRSetNonLinearGeometriesEnabledFlag(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25663,7 +29603,11 @@ SWIGINTERN PyObject *_wrap_GetNonLinearGeometriesEnabledFlag(PyObject *SWIGUNUSE
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (int)OGRGetNonLinearGeometriesEnabledFlag();
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (int)OGRGetNonLinearGeometriesEnabledFlag();
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25699,7 +29643,11 @@ SWIGINTERN PyObject *_wrap_GetOpenDS(PyObject *SWIGUNUSEDPARM(self), PyObject *a
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRDataSourceShadow *)GetOpenDS(arg1);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRDataSourceShadow *)GetOpenDS(arg1);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25752,7 +29700,11 @@ SWIGINTERN PyObject *_wrap_Open(PyObject *SWIGUNUSEDPARM(self), PyObject *args,
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRDataSourceShadow *)Open((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRDataSourceShadow *)Open((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -25813,7 +29765,11 @@ SWIGINTERN PyObject *_wrap_OpenShared(PyObject *SWIGUNUSEDPARM(self), PyObject *
     if ( bUseExceptions ) {
       CPLErrorReset();
     }
-    result = (OGRDataSourceShadow *)OpenShared((char const *)arg1,arg2);
+    {
+      SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+      result = (OGRDataSourceShadow *)OpenShared((char const *)arg1,arg2);
+      SWIG_PYTHON_THREAD_END_ALLOW;
+    }
 #ifndef SED_HACKS
     if ( bUseExceptions ) {
       CPLErr eclass = CPLGetLastErrorType();
@@ -26093,22 +30049,181 @@ fail:
 }
 
 
+SWIGINTERN PyObject *TermProgress_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  
+  return SWIG_Py_Void();
+}
+
+
 static PyMethodDef SwigMethods[] = {
 	 { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL},
+	 { (char *)"wkb25DBit_swigconstant", wkb25DBit_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkb25Bit_swigconstant", wkb25Bit_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbUnknown_swigconstant", wkbUnknown_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPoint_swigconstant", wkbPoint_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbLineString_swigconstant", wkbLineString_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPolygon_swigconstant", wkbPolygon_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiPoint_swigconstant", wkbMultiPoint_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiLineString_swigconstant", wkbMultiLineString_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiPolygon_swigconstant", wkbMultiPolygon_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbGeometryCollection_swigconstant", wkbGeometryCollection_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCircularString_swigconstant", wkbCircularString_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCompoundCurve_swigconstant", wkbCompoundCurve_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCurvePolygon_swigconstant", wkbCurvePolygon_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiCurve_swigconstant", wkbMultiCurve_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiSurface_swigconstant", wkbMultiSurface_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCurve_swigconstant", wkbCurve_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbSurface_swigconstant", wkbSurface_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPolyhedralSurface_swigconstant", wkbPolyhedralSurface_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbTIN_swigconstant", wkbTIN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbTriangle_swigconstant", wkbTriangle_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbNone_swigconstant", wkbNone_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbLinearRing_swigconstant", wkbLinearRing_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCircularStringZ_swigconstant", wkbCircularStringZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCompoundCurveZ_swigconstant", wkbCompoundCurveZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCurvePolygonZ_swigconstant", wkbCurvePolygonZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiCurveZ_swigconstant", wkbMultiCurveZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiSurfaceZ_swigconstant", wkbMultiSurfaceZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCurveZ_swigconstant", wkbCurveZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbSurfaceZ_swigconstant", wkbSurfaceZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPolyhedralSurfaceZ_swigconstant", wkbPolyhedralSurfaceZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbTINZ_swigconstant", wkbTINZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbTriangleZ_swigconstant", wkbTriangleZ_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPointM_swigconstant", wkbPointM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbLineStringM_swigconstant", wkbLineStringM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPolygonM_swigconstant", wkbPolygonM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiPointM_swigconstant", wkbMultiPointM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiLineStringM_swigconstant", wkbMultiLineStringM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiPolygonM_swigconstant", wkbMultiPolygonM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbGeometryCollectionM_swigconstant", wkbGeometryCollectionM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCircularStringM_swigconstant", wkbCircularStringM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCompoundCurveM_swigconstant", wkbCompoundCurveM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCurvePolygonM_swigconstant", wkbCurvePolygonM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiCurveM_swigconstant", wkbMultiCurveM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiSurfaceM_swigconstant", wkbMultiSurfaceM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCurveM_swigconstant", wkbCurveM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbSurfaceM_swigconstant", wkbSurfaceM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPolyhedralSurfaceM_swigconstant", wkbPolyhedralSurfaceM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbTINM_swigconstant", wkbTINM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbTriangleM_swigconstant", wkbTriangleM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPointZM_swigconstant", wkbPointZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbLineStringZM_swigconstant", wkbLineStringZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPolygonZM_swigconstant", wkbPolygonZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiPointZM_swigconstant", wkbMultiPointZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiLineStringZM_swigconstant", wkbMultiLineStringZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiPolygonZM_swigconstant", wkbMultiPolygonZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbGeometryCollectionZM_swigconstant", wkbGeometryCollectionZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCircularStringZM_swigconstant", wkbCircularStringZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCompoundCurveZM_swigconstant", wkbCompoundCurveZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCurvePolygonZM_swigconstant", wkbCurvePolygonZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiCurveZM_swigconstant", wkbMultiCurveZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiSurfaceZM_swigconstant", wkbMultiSurfaceZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbCurveZM_swigconstant", wkbCurveZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbSurfaceZM_swigconstant", wkbSurfaceZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPolyhedralSurfaceZM_swigconstant", wkbPolyhedralSurfaceZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbTINZM_swigconstant", wkbTINZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbTriangleZM_swigconstant", wkbTriangleZM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPoint25D_swigconstant", wkbPoint25D_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbLineString25D_swigconstant", wkbLineString25D_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbPolygon25D_swigconstant", wkbPolygon25D_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiPoint25D_swigconstant", wkbMultiPoint25D_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiLineString25D_swigconstant", wkbMultiLineString25D_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbMultiPolygon25D_swigconstant", wkbMultiPolygon25D_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbGeometryCollection25D_swigconstant", wkbGeometryCollection25D_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTInteger_swigconstant", OFTInteger_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTIntegerList_swigconstant", OFTIntegerList_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTReal_swigconstant", OFTReal_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTRealList_swigconstant", OFTRealList_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTString_swigconstant", OFTString_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTStringList_swigconstant", OFTStringList_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTWideString_swigconstant", OFTWideString_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTWideStringList_swigconstant", OFTWideStringList_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTBinary_swigconstant", OFTBinary_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTDate_swigconstant", OFTDate_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTTime_swigconstant", OFTTime_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTDateTime_swigconstant", OFTDateTime_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTInteger64_swigconstant", OFTInteger64_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFTInteger64List_swigconstant", OFTInteger64List_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFSTNone_swigconstant", OFSTNone_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFSTBoolean_swigconstant", OFSTBoolean_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFSTInt16_swigconstant", OFSTInt16_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OFSTFloat32_swigconstant", OFSTFloat32_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OJUndefined_swigconstant", OJUndefined_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OJLeft_swigconstant", OJLeft_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OJRight_swigconstant", OJRight_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbXDR_swigconstant", wkbXDR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"wkbNDR_swigconstant", wkbNDR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"NullFID_swigconstant", NullFID_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ALTER_NAME_FLAG_swigconstant", ALTER_NAME_FLAG_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ALTER_TYPE_FLAG_swigconstant", ALTER_TYPE_FLAG_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ALTER_WIDTH_PRECISION_FLAG_swigconstant", ALTER_WIDTH_PRECISION_FLAG_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ALTER_NULLABLE_FLAG_swigconstant", ALTER_NULLABLE_FLAG_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ALTER_DEFAULT_FLAG_swigconstant", ALTER_DEFAULT_FLAG_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ALTER_ALL_FLAG_swigconstant", ALTER_ALL_FLAG_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"F_VAL_NULL_swigconstant", F_VAL_NULL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"F_VAL_GEOM_TYPE_swigconstant", F_VAL_GEOM_TYPE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"F_VAL_WIDTH_swigconstant", F_VAL_WIDTH_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"F_VAL_ALLOW_NULL_WHEN_DEFAULT_swigconstant", F_VAL_ALLOW_NULL_WHEN_DEFAULT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"F_VAL_ALL_swigconstant", F_VAL_ALL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCRandomRead_swigconstant", OLCRandomRead_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCSequentialWrite_swigconstant", OLCSequentialWrite_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCRandomWrite_swigconstant", OLCRandomWrite_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCFastSpatialFilter_swigconstant", OLCFastSpatialFilter_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCFastFeatureCount_swigconstant", OLCFastFeatureCount_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCFastGetExtent_swigconstant", OLCFastGetExtent_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCCreateField_swigconstant", OLCCreateField_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCDeleteField_swigconstant", OLCDeleteField_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCReorderFields_swigconstant", OLCReorderFields_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCAlterFieldDefn_swigconstant", OLCAlterFieldDefn_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCTransactions_swigconstant", OLCTransactions_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCDeleteFeature_swigconstant", OLCDeleteFeature_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCFastSetNextByIndex_swigconstant", OLCFastSetNextByIndex_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCStringsAsUTF8_swigconstant", OLCStringsAsUTF8_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCIgnoreFields_swigconstant", OLCIgnoreFields_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCCreateGeomField_swigconstant", OLCCreateGeomField_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCCurveGeometries_swigconstant", OLCCurveGeometries_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLCMeasuredGeometries_swigconstant", OLCMeasuredGeometries_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODsCCreateLayer_swigconstant", ODsCCreateLayer_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODsCDeleteLayer_swigconstant", ODsCDeleteLayer_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODsCCreateGeomFieldAfterCreateLayer_swigconstant", ODsCCreateGeomFieldAfterCreateLayer_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODsCCurveGeometries_swigconstant", ODsCCurveGeometries_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODsCTransactions_swigconstant", ODsCTransactions_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODsCEmulatedTransactions_swigconstant", ODsCEmulatedTransactions_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODsCMeasuredGeometries_swigconstant", ODsCMeasuredGeometries_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODsCRandomLayerRead_swigconstant", ODsCRandomLayerRead_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODsCRandomLayerWrite_swigconstant", ODsCRandomLayerWrite_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODrCCreateDataSource_swigconstant", ODrCCreateDataSource_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"ODrCDeleteDataSource_swigconstant", ODrCDeleteDataSource_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OLMD_FID64_swigconstant", OLMD_FID64_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_NONE_swigconstant", OGRERR_NONE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_NOT_ENOUGH_DATA_swigconstant", OGRERR_NOT_ENOUGH_DATA_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_NOT_ENOUGH_MEMORY_swigconstant", OGRERR_NOT_ENOUGH_MEMORY_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_UNSUPPORTED_GEOMETRY_TYPE_swigconstant", OGRERR_UNSUPPORTED_GEOMETRY_TYPE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_UNSUPPORTED_OPERATION_swigconstant", OGRERR_UNSUPPORTED_OPERATION_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_CORRUPT_DATA_swigconstant", OGRERR_CORRUPT_DATA_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_FAILURE_swigconstant", OGRERR_FAILURE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_UNSUPPORTED_SRS_swigconstant", OGRERR_UNSUPPORTED_SRS_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_INVALID_HANDLE_swigconstant", OGRERR_INVALID_HANDLE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OGRERR_NON_EXISTING_FEATURE_swigconstant", OGRERR_NON_EXISTING_FEATURE_swigconstant, METH_VARARGS, NULL},
 	 { (char *)"GetUseExceptions", _wrap_GetUseExceptions, METH_VARARGS, (char *)"GetUseExceptions() -> int"},
 	 { (char *)"UseExceptions", _wrap_UseExceptions, METH_VARARGS, (char *)"UseExceptions()"},
 	 { (char *)"DontUseExceptions", _wrap_DontUseExceptions, METH_VARARGS, (char *)"DontUseExceptions()"},
 	 { (char *)"MajorObject_GetDescription", _wrap_MajorObject_GetDescription, METH_VARARGS, (char *)"MajorObject_GetDescription(MajorObject self) -> char const *"},
 	 { (char *)"MajorObject_SetDescription", _wrap_MajorObject_SetDescription, METH_VARARGS, (char *)"MajorObject_SetDescription(MajorObject self, char const * pszNewDesc)"},
 	 { (char *)"MajorObject_GetMetadataDomainList", _wrap_MajorObject_GetMetadataDomainList, METH_VARARGS, (char *)"MajorObject_GetMetadataDomainList(MajorObject self) -> char **"},
-	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char const * pszDomain=\"\") -> char **"},
-	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, (char *)"MajorObject_GetMetadata_List(MajorObject self, char const * pszDomain=\"\") -> char **"},
+	 { (char *)"MajorObject_GetMetadata_Dict", _wrap_MajorObject_GetMetadata_Dict, METH_VARARGS, (char *)"MajorObject_GetMetadata_Dict(MajorObject self, char const * pszDomain) -> char **"},
+	 { (char *)"MajorObject_GetMetadata_List", _wrap_MajorObject_GetMetadata_List, METH_VARARGS, (char *)"MajorObject_GetMetadata_List(MajorObject self, char const * pszDomain) -> char **"},
 	 { (char *)"MajorObject_SetMetadata", _wrap_MajorObject_SetMetadata, METH_VARARGS, (char *)"\n"
-		"SetMetadata(char ** papszMetadata, char const * pszDomain=\"\") -> CPLErr\n"
-		"MajorObject_SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain=\"\") -> CPLErr\n"
+		"SetMetadata(char ** papszMetadata, char const * pszDomain) -> CPLErr\n"
+		"MajorObject_SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain) -> CPLErr\n"
 		""},
-	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, (char *)"MajorObject_GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain=\"\") -> char const *"},
-	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, (char *)"MajorObject_SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain=\"\") -> CPLErr"},
+	 { (char *)"MajorObject_GetMetadataItem", _wrap_MajorObject_GetMetadataItem, METH_VARARGS, (char *)"MajorObject_GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain) -> char const *"},
+	 { (char *)"MajorObject_SetMetadataItem", _wrap_MajorObject_SetMetadataItem, METH_VARARGS, (char *)"MajorObject_SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain) -> CPLErr"},
 	 { (char *)"MajorObject_swigregister", MajorObject_swigregister, METH_VARARGS, NULL},
 	 { (char *)"new_StyleTable", _wrap_new_StyleTable, METH_VARARGS, (char *)"new_StyleTable() -> StyleTable"},
 	 { (char *)"delete_StyleTable", _wrap_delete_StyleTable, METH_VARARGS, (char *)"delete_StyleTable(StyleTable self)"},
@@ -26407,8 +30522,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"DataSource_FlushCache", _wrap_DataSource_FlushCache, METH_VARARGS, (char *)"DataSource_FlushCache(DataSource self)"},
 	 { (char *)"DataSource_CreateLayer", (PyCFunction) _wrap_DataSource_CreateLayer, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"DataSource_CreateLayer(DataSource self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type=wkbUnknown, \n"
-		"    char ** options=None) -> Layer\n"
+		"DataSource_CreateLayer(DataSource self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type, char ** options=None) -> Layer\n"
 		"\n"
 		"OGRLayerH\n"
 		"OGR_DS_CreateLayer(OGRDataSourceH hDS, const char *pszName,\n"
@@ -26539,7 +30653,7 @@ static PyMethodDef SwigMethods[] = {
 		"TRUE if capability available otherwise FALSE. \n"
 		""},
 	 { (char *)"DataSource_ExecuteSQL", (PyCFunction) _wrap_DataSource_ExecuteSQL, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"DataSource_ExecuteSQL(DataSource self, char const * statement, Geometry spatialFilter=None, char const * dialect=\"\") -> Layer\n"
+		"DataSource_ExecuteSQL(DataSource self, char const * statement, Geometry spatialFilter=None, char const * dialect) -> Layer\n"
 		"\n"
 		"OGRLayerH\n"
 		"OGR_DS_ExecuteSQL(OGRDataSourceH hDS, const char *pszStatement,\n"
@@ -27709,8 +31823,7 @@ static PyMethodDef SwigMethods[] = {
 		"does not support this method) \n"
 		""},
 	 { (char *)"Layer_Intersection", (PyCFunction) _wrap_Layer_Intersection, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Intersection(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> OGRErr\n"
+		"Layer_Intersection(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
 		"OGR_L_Intersection(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,\n"
@@ -27785,8 +31898,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGR 1.10 \n"
 		""},
 	 { (char *)"Layer_Union", (PyCFunction) _wrap_Layer_Union, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Union(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> OGRErr\n"
+		"Layer_Union(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr\n"
 		"\n"
 		"OGRErr OGR_L_Union(OGRLayerH\n"
 		"pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char\n"
@@ -27857,8 +31969,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGR 1.10 \n"
 		""},
 	 { (char *)"Layer_SymDifference", (PyCFunction) _wrap_Layer_SymDifference, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_SymDifference(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> OGRErr\n"
+		"Layer_SymDifference(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
 		"OGR_L_SymDifference(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,\n"
@@ -27926,8 +32037,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGR 1.10 \n"
 		""},
 	 { (char *)"Layer_Identity", (PyCFunction) _wrap_Layer_Identity, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Identity(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> OGRErr\n"
+		"Layer_Identity(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr\n"
 		"\n"
 		"OGRErr OGR_L_Identity(OGRLayerH\n"
 		"pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char\n"
@@ -27996,8 +32106,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGR 1.10 \n"
 		""},
 	 { (char *)"Layer_Update", (PyCFunction) _wrap_Layer_Update, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Update(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> OGRErr\n"
+		"Layer_Update(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr\n"
 		"\n"
 		"OGRErr OGR_L_Update(OGRLayerH\n"
 		"pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char\n"
@@ -28064,8 +32173,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGR 1.10 \n"
 		""},
 	 { (char *)"Layer_Clip", (PyCFunction) _wrap_Layer_Clip, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Clip(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> OGRErr\n"
+		"Layer_Clip(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr\n"
 		"\n"
 		"OGRErr OGR_L_Clip(OGRLayerH pLayerInput,\n"
 		"OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char **papszOptions,\n"
@@ -28125,8 +32233,7 @@ static PyMethodDef SwigMethods[] = {
 		"OGR 1.10 \n"
 		""},
 	 { (char *)"Layer_Erase", (PyCFunction) _wrap_Layer_Erase, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Layer_Erase(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, \n"
-		"    void * callback_data=None) -> OGRErr\n"
+		"Layer_Erase(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr\n"
 		"\n"
 		"OGRErr OGR_L_Erase(OGRLayerH\n"
 		"pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char\n"
@@ -28805,6 +32912,14 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"TRUE if the field has been set, otherwise false. \n"
 		""},
+	 { (char *)"Feature_IsFieldNull", _wrap_Feature_IsFieldNull, METH_VARARGS, (char *)"\n"
+		"IsFieldNull(int id) -> bool\n"
+		"Feature_IsFieldNull(Feature self, char const * name) -> bool\n"
+		""},
+	 { (char *)"Feature_IsFieldSetAndNotNull", _wrap_Feature_IsFieldSetAndNotNull, METH_VARARGS, (char *)"\n"
+		"IsFieldSetAndNotNull(int id) -> bool\n"
+		"Feature_IsFieldSetAndNotNull(Feature self, char const * name) -> bool\n"
+		""},
 	 { (char *)"Feature_GetFieldIndex", _wrap_Feature_GetFieldIndex, METH_VARARGS, (char *)"\n"
 		"Feature_GetFieldIndex(Feature self, char const * name) -> int\n"
 		"\n"
@@ -28936,6 +33051,10 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"iField:  the field to unset. \n"
 		""},
+	 { (char *)"Feature_SetFieldNull", _wrap_Feature_SetFieldNull, METH_VARARGS, (char *)"\n"
+		"SetFieldNull(int id)\n"
+		"Feature_SetFieldNull(Feature self, char const * name)\n"
+		""},
 	 { (char *)"Feature_SetFieldInteger64", _wrap_Feature_SetFieldInteger64, METH_VARARGS, (char *)"\n"
 		"Feature_SetFieldInteger64(Feature self, int id, GIntBig value)\n"
 		"\n"
@@ -28968,8 +33087,7 @@ static PyMethodDef SwigMethods[] = {
 		"SetField(int id, double value)\n"
 		"SetField(char const * name, double value)\n"
 		"SetField(int id, int year, int month, int day, int hour, int minute, float second, int tzflag)\n"
-		"Feature_SetField(Feature self, char const * name, int year, int month, int day, int hour, int minute, \n"
-		"    float second, int tzflag)\n"
+		"Feature_SetField(Feature self, char const * name, int year, int month, int day, int hour, int minute, float second, int tzflag)\n"
 		""},
 	 { (char *)"Feature_SetFieldIntegerList", _wrap_Feature_SetFieldIntegerList, METH_VARARGS, (char *)"\n"
 		"Feature_SetFieldIntegerList(Feature self, int id, int nList)\n"
@@ -29195,7 +33313,7 @@ static PyMethodDef SwigMethods[] = {
 		"Feature_GetFieldType(Feature self, char const * name) -> OGRFieldType\n"
 		""},
 	 { (char *)"Feature_Validate", _wrap_Feature_Validate, METH_VARARGS, (char *)"\n"
-		"Feature_Validate(Feature self, int flags=OGR_F_VAL_ALL, int bEmitError=True) -> int\n"
+		"Feature_Validate(Feature self, int flags, int bEmitError=True) -> int\n"
 		"\n"
 		"int OGR_F_Validate(OGRFeatureH\n"
 		"hFeat, int nValidateFlags, int bEmitError)\n"
@@ -29820,7 +33938,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"FeatureDefn_swigregister", FeatureDefn_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_FieldDefn", _wrap_delete_FieldDefn, METH_VARARGS, (char *)"delete_FieldDefn(FieldDefn self)"},
-	 { (char *)"new_FieldDefn", (PyCFunction) _wrap_new_FieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_FieldDefn(char const * name_null_ok=\"unnamed\", OGRFieldType field_type=OFTString) -> FieldDefn"},
+	 { (char *)"new_FieldDefn", (PyCFunction) _wrap_new_FieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_FieldDefn(char const * name_null_ok, OGRFieldType field_type) -> FieldDefn"},
 	 { (char *)"FieldDefn_GetName", _wrap_FieldDefn_GetName, METH_VARARGS, (char *)"FieldDefn_GetName(FieldDefn self) -> char const *"},
 	 { (char *)"FieldDefn_GetNameRef", _wrap_FieldDefn_GetNameRef, METH_VARARGS, (char *)"\n"
 		"FieldDefn_GetNameRef(FieldDefn self) -> char const *\n"
@@ -30223,7 +34341,7 @@ static PyMethodDef SwigMethods[] = {
 		""},
 	 { (char *)"FieldDefn_swigregister", FieldDefn_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_GeomFieldDefn", _wrap_delete_GeomFieldDefn, METH_VARARGS, (char *)"delete_GeomFieldDefn(GeomFieldDefn self)"},
-	 { (char *)"new_GeomFieldDefn", (PyCFunction) _wrap_new_GeomFieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_GeomFieldDefn(char const * name_null_ok=\"\", OGRwkbGeometryType field_type=wkbUnknown) -> GeomFieldDefn"},
+	 { (char *)"new_GeomFieldDefn", (PyCFunction) _wrap_new_GeomFieldDefn, METH_VARARGS | METH_KEYWORDS, (char *)"new_GeomFieldDefn(char const * name_null_ok, OGRwkbGeometryType field_type) -> GeomFieldDefn"},
 	 { (char *)"GeomFieldDefn_GetName", _wrap_GeomFieldDefn_GetName, METH_VARARGS, (char *)"GeomFieldDefn_GetName(GeomFieldDefn self) -> char const *"},
 	 { (char *)"GeomFieldDefn_GetNameRef", _wrap_GeomFieldDefn_GetNameRef, METH_VARARGS, (char *)"GeomFieldDefn_GetNameRef(GeomFieldDefn self) -> char const *"},
 	 { (char *)"GeomFieldDefn_SetName", _wrap_GeomFieldDefn_SetName, METH_VARARGS, (char *)"GeomFieldDefn_SetName(GeomFieldDefn self, char const * name)"},
@@ -30241,10 +34359,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"CreateGeometryFromGML", _wrap_CreateGeometryFromGML, METH_VARARGS, (char *)"CreateGeometryFromGML(char const * input_string) -> Geometry"},
 	 { (char *)"CreateGeometryFromJson", _wrap_CreateGeometryFromJson, METH_VARARGS, (char *)"CreateGeometryFromJson(char const * input_string) -> Geometry"},
 	 { (char *)"BuildPolygonFromEdges", (PyCFunction) _wrap_BuildPolygonFromEdges, METH_VARARGS | METH_KEYWORDS, (char *)"BuildPolygonFromEdges(Geometry hLineCollection, int bBestEffort=0, int bAutoClose=0, double dfTolerance=0) -> Geometry"},
-	 { (char *)"ApproximateArcAngles", (PyCFunction) _wrap_ApproximateArcAngles, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, double dfSecondaryAxis, \n"
-		"    double dfRotation, double dfStartAngle, double dfEndAngle, double dfMaxAngleStepSizeDegrees) -> Geometry\n"
-		""},
+	 { (char *)"ApproximateArcAngles", (PyCFunction) _wrap_ApproximateArcAngles, METH_VARARGS | METH_KEYWORDS, (char *)"ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation, double dfStartAngle, double dfEndAngle, double dfMaxAngleStepSizeDegrees) -> Geometry"},
 	 { (char *)"ForceToPolygon", _wrap_ForceToPolygon, METH_VARARGS, (char *)"ForceToPolygon(Geometry geom_in) -> Geometry"},
 	 { (char *)"ForceToLineString", _wrap_ForceToLineString, METH_VARARGS, (char *)"ForceToLineString(Geometry geom_in) -> Geometry"},
 	 { (char *)"ForceToMultiPolygon", _wrap_ForceToMultiPolygon, METH_VARARGS, (char *)"ForceToMultiPolygon(Geometry geom_in) -> Geometry"},
@@ -30252,7 +34367,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"ForceToMultiLineString", _wrap_ForceToMultiLineString, METH_VARARGS, (char *)"ForceToMultiLineString(Geometry geom_in) -> Geometry"},
 	 { (char *)"ForceTo", _wrap_ForceTo, METH_VARARGS, (char *)"ForceTo(Geometry geom_in, OGRwkbGeometryType eTargetType, char ** options=None) -> Geometry"},
 	 { (char *)"delete_Geometry", _wrap_delete_Geometry, METH_VARARGS, (char *)"delete_Geometry(Geometry self)"},
-	 { (char *)"new_Geometry", (PyCFunction) _wrap_new_Geometry, METH_VARARGS | METH_KEYWORDS, (char *)"new_Geometry(OGRwkbGeometryType type=wkbUnknown, char * wkt=None, int wkb=0, char * gml=None) -> Geometry"},
+	 { (char *)"new_Geometry", (PyCFunction) _wrap_new_Geometry, METH_VARARGS | METH_KEYWORDS, (char *)"new_Geometry(OGRwkbGeometryType type, char * wkt=None, int wkb=0, char * gml=None) -> Geometry"},
 	 { (char *)"Geometry_ExportToWkt", _wrap_Geometry_ExportToWkt, METH_VARARGS, (char *)"\n"
 		"Geometry_ExportToWkt(Geometry self) -> OGRErr\n"
 		"\n"
@@ -30278,7 +34393,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"ppszSrcText:  a text buffer is allocated by the program, and assigned\n"
 		"to the passed pointer. After use, *ppszDstText should be freed with\n"
-		"OGRFree().\n"
+		"CPLFree().\n"
 		"\n"
 		"Currently OGRERR_NONE is always returned. \n"
 		""},
@@ -30305,14 +34420,14 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"ppszSrcText:  a text buffer is allocated by the program, and assigned\n"
 		"to the passed pointer. After use, *ppszDstText should be freed with\n"
-		"OGRFree().\n"
+		"CPLFree().\n"
 		"\n"
 		"Currently OGRERR_NONE is always returned.\n"
 		"\n"
 		"GDAL 2.0 \n"
 		""},
 	 { (char *)"Geometry_ExportToWkb", (PyCFunction) _wrap_Geometry_ExportToWkb, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Geometry_ExportToWkb(Geometry self, OGRwkbByteOrder byte_order=wkbXDR) -> OGRErr\n"
+		"Geometry_ExportToWkb(Geometry self, OGRwkbByteOrder byte_order) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
 		"OGR_G_ExportToWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder, unsigned\n"
@@ -30346,7 +34461,7 @@ static PyMethodDef SwigMethods[] = {
 		"Currently OGRERR_NONE is always returned. \n"
 		""},
 	 { (char *)"Geometry_ExportToIsoWkb", (PyCFunction) _wrap_Geometry_ExportToIsoWkb, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"Geometry_ExportToIsoWkb(Geometry self, OGRwkbByteOrder byte_order=wkbXDR) -> OGRErr\n"
+		"Geometry_ExportToIsoWkb(Geometry self, OGRwkbByteOrder byte_order) -> OGRErr\n"
 		"\n"
 		"OGRErr\n"
 		"OGR_G_ExportToIsoWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder,\n"
@@ -30832,6 +34947,7 @@ static PyMethodDef SwigMethods[] = {
 		"\n"
 		"the distance between the geometries or -1 if an error occurs. \n"
 		""},
+	 { (char *)"Geometry_Distance3D", _wrap_Geometry_Distance3D, METH_VARARGS, (char *)"Geometry_Distance3D(Geometry self, Geometry other) -> double"},
 	 { (char *)"Geometry_Empty", _wrap_Geometry_Empty, METH_VARARGS, (char *)"\n"
 		"Geometry_Empty(Geometry self)\n"
 		"\n"
@@ -31638,6 +35754,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"GetDriver", _wrap_GetDriver, METH_VARARGS, (char *)"GetDriver(int driver_number) -> Driver"},
 	 { (char *)"GeneralCmdLineProcessor", _wrap_GeneralCmdLineProcessor, METH_VARARGS, (char *)"GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"},
 	 { (char *)"TermProgress_nocb", (PyCFunction) _wrap_TermProgress_nocb, METH_VARARGS | METH_KEYWORDS, (char *)"TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"},
+	 { (char *)"TermProgress_swigconstant", TermProgress_swigconstant, METH_VARARGS, NULL},
 	 { NULL, NULL, 0, NULL }
 };
 
@@ -31776,7 +35893,7 @@ static swig_const_info swig_const_table[] = {
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial
+ * The generated swig_type_info structures are assigned statically to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -31820,7 +35937,7 @@ SWIGRUNTIME void
 SWIG_InitializeModule(void *clientdata) {
   size_t i;
   swig_module_info *module_head, *iter;
-  int found, init;
+  int init;
   
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
@@ -31839,22 +35956,18 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
     iter=module_head;
     do {
       if (iter==&swig_module) {
-        found=1;
-        break;
+        /* Our module is already in the list, so there's nothing more to do. */
+        return;
       }
       iter=iter->next;
     } while (iter!= module_head);
     
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
+    /* otherwise we must add our module into the list */
     swig_module.next = module_head->next;
     module_head->next = &swig_module;
   }
@@ -32106,7 +36219,7 @@ extern "C" {
       var = var->next;
     }
     if (res == NULL && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -32123,7 +36236,7 @@ extern "C" {
       var = var->next;
     }
     if (res == 1 && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -32173,10 +36286,19 @@ extern "C" {
         0,                                  /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-        0,                                  /* tp_version */
+        0,                                  /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+        0,                                  /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-        0,0,0,0                             /* tp_alloc -> tp_next */
+        0,                                  /* tp_allocs */
+        0,                                  /* tp_frees */
+        0,                                  /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+        0,                                  /* tp_prev */
+#endif
+        0                                   /* tp_next */
 #endif
       };
       varlink_type = tmp;
@@ -32265,7 +36387,9 @@ extern "C" {
     size_t i;
     for (i = 0; methods[i].ml_name; ++i) {
       const char *c = methods[i].ml_doc;
-      if (c && (c = strstr(c, "swig_ptr: "))) {
+      if (!c) continue;
+      c = strstr(c, "swig_ptr: ");
+      if (c) {
         int j;
         swig_const_info *ci = 0;
         const char *name = c + 10;
@@ -32367,6 +36491,7 @@ SWIG_init(void) {
   PyObject *public_interface, *public_symbol;
   PyObject *this_descr;
   PyObject *thisown_descr;
+  PyObject *self = 0;
   int i;
   
   (void)builtin_pytype;
@@ -32374,6 +36499,7 @@ SWIG_init(void) {
   (void)builtin_basetype;
   (void)tuple;
   (void)static_getset;
+  (void)self;
   
   /* metatype is used to implement static member variables. */
   metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
@@ -32393,6 +36519,7 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
+  
   md = d = PyModule_GetDict(m);
   (void)md;
   
@@ -32436,148 +36563,6 @@ SWIG_init(void) {
   
   SWIG_InstallConstants(d,swig_const_table);
   
-  SWIG_Python_SetConstant(d, "wkb25DBit",SWIG_From_int(static_cast< int >(0x80000000)));
-  SWIG_Python_SetConstant(d, "wkb25Bit",SWIG_From_int(static_cast< int >(0x80000000)));
-  SWIG_Python_SetConstant(d, "wkbUnknown",SWIG_From_int(static_cast< int >(0)));
-  SWIG_Python_SetConstant(d, "wkbPoint",SWIG_From_int(static_cast< int >(1)));
-  SWIG_Python_SetConstant(d, "wkbLineString",SWIG_From_int(static_cast< int >(2)));
-  SWIG_Python_SetConstant(d, "wkbPolygon",SWIG_From_int(static_cast< int >(3)));
-  SWIG_Python_SetConstant(d, "wkbMultiPoint",SWIG_From_int(static_cast< int >(4)));
-  SWIG_Python_SetConstant(d, "wkbMultiLineString",SWIG_From_int(static_cast< int >(5)));
-  SWIG_Python_SetConstant(d, "wkbMultiPolygon",SWIG_From_int(static_cast< int >(6)));
-  SWIG_Python_SetConstant(d, "wkbGeometryCollection",SWIG_From_int(static_cast< int >(7)));
-  SWIG_Python_SetConstant(d, "wkbCircularString",SWIG_From_int(static_cast< int >(8)));
-  SWIG_Python_SetConstant(d, "wkbCompoundCurve",SWIG_From_int(static_cast< int >(9)));
-  SWIG_Python_SetConstant(d, "wkbCurvePolygon",SWIG_From_int(static_cast< int >(10)));
-  SWIG_Python_SetConstant(d, "wkbMultiCurve",SWIG_From_int(static_cast< int >(11)));
-  SWIG_Python_SetConstant(d, "wkbMultiSurface",SWIG_From_int(static_cast< int >(12)));
-  SWIG_Python_SetConstant(d, "wkbCurve",SWIG_From_int(static_cast< int >(13)));
-  SWIG_Python_SetConstant(d, "wkbSurface",SWIG_From_int(static_cast< int >(14)));
-  SWIG_Python_SetConstant(d, "wkbPolyhedralSurface",SWIG_From_int(static_cast< int >(15)));
-  SWIG_Python_SetConstant(d, "wkbTIN",SWIG_From_int(static_cast< int >(16)));
-  SWIG_Python_SetConstant(d, "wkbNone",SWIG_From_int(static_cast< int >(100)));
-  SWIG_Python_SetConstant(d, "wkbLinearRing",SWIG_From_int(static_cast< int >(101)));
-  SWIG_Python_SetConstant(d, "wkbCircularStringZ",SWIG_From_int(static_cast< int >(1008)));
-  SWIG_Python_SetConstant(d, "wkbCompoundCurveZ",SWIG_From_int(static_cast< int >(1009)));
-  SWIG_Python_SetConstant(d, "wkbCurvePolygonZ",SWIG_From_int(static_cast< int >(1010)));
-  SWIG_Python_SetConstant(d, "wkbMultiCurveZ",SWIG_From_int(static_cast< int >(1011)));
-  SWIG_Python_SetConstant(d, "wkbMultiSurfaceZ",SWIG_From_int(static_cast< int >(1012)));
-  SWIG_Python_SetConstant(d, "wkbCurveZ",SWIG_From_int(static_cast< int >(1013)));
-  SWIG_Python_SetConstant(d, "wkbSurfaceZ",SWIG_From_int(static_cast< int >(1014)));
-  SWIG_Python_SetConstant(d, "wkbPolyhedralSurfaceZ",SWIG_From_int(static_cast< int >(1015)));
-  SWIG_Python_SetConstant(d, "wkbTINZ",SWIG_From_int(static_cast< int >(1016)));
-  SWIG_Python_SetConstant(d, "wkbPointM",SWIG_From_int(static_cast< int >(2001)));
-  SWIG_Python_SetConstant(d, "wkbLineStringM",SWIG_From_int(static_cast< int >(2002)));
-  SWIG_Python_SetConstant(d, "wkbPolygonM",SWIG_From_int(static_cast< int >(2003)));
-  SWIG_Python_SetConstant(d, "wkbMultiPointM",SWIG_From_int(static_cast< int >(2004)));
-  SWIG_Python_SetConstant(d, "wkbMultiLineStringM",SWIG_From_int(static_cast< int >(2005)));
-  SWIG_Python_SetConstant(d, "wkbMultiPolygonM",SWIG_From_int(static_cast< int >(2006)));
-  SWIG_Python_SetConstant(d, "wkbGeometryCollectionM",SWIG_From_int(static_cast< int >(2007)));
-  SWIG_Python_SetConstant(d, "wkbCircularStringM",SWIG_From_int(static_cast< int >(2008)));
-  SWIG_Python_SetConstant(d, "wkbCompoundCurveM",SWIG_From_int(static_cast< int >(2009)));
-  SWIG_Python_SetConstant(d, "wkbCurvePolygonM",SWIG_From_int(static_cast< int >(2010)));
-  SWIG_Python_SetConstant(d, "wkbMultiCurveM",SWIG_From_int(static_cast< int >(2011)));
-  SWIG_Python_SetConstant(d, "wkbMultiSurfaceM",SWIG_From_int(static_cast< int >(2012)));
-  SWIG_Python_SetConstant(d, "wkbCurveM",SWIG_From_int(static_cast< int >(2013)));
-  SWIG_Python_SetConstant(d, "wkbSurfaceM",SWIG_From_int(static_cast< int >(2014)));
-  SWIG_Python_SetConstant(d, "wkbPolyhedralSurfaceM",SWIG_From_int(static_cast< int >(2015)));
-  SWIG_Python_SetConstant(d, "wkbTINM",SWIG_From_int(static_cast< int >(2016)));
-  SWIG_Python_SetConstant(d, "wkbPointZM",SWIG_From_int(static_cast< int >(3001)));
-  SWIG_Python_SetConstant(d, "wkbLineStringZM",SWIG_From_int(static_cast< int >(3002)));
-  SWIG_Python_SetConstant(d, "wkbPolygonZM",SWIG_From_int(static_cast< int >(3003)));
-  SWIG_Python_SetConstant(d, "wkbMultiPointZM",SWIG_From_int(static_cast< int >(3004)));
-  SWIG_Python_SetConstant(d, "wkbMultiLineStringZM",SWIG_From_int(static_cast< int >(3005)));
-  SWIG_Python_SetConstant(d, "wkbMultiPolygonZM",SWIG_From_int(static_cast< int >(3006)));
-  SWIG_Python_SetConstant(d, "wkbGeometryCollectionZM",SWIG_From_int(static_cast< int >(3007)));
-  SWIG_Python_SetConstant(d, "wkbCircularStringZM",SWIG_From_int(static_cast< int >(3008)));
-  SWIG_Python_SetConstant(d, "wkbCompoundCurveZM",SWIG_From_int(static_cast< int >(3009)));
-  SWIG_Python_SetConstant(d, "wkbCurvePolygonZM",SWIG_From_int(static_cast< int >(3010)));
-  SWIG_Python_SetConstant(d, "wkbMultiCurveZM",SWIG_From_int(static_cast< int >(3011)));
-  SWIG_Python_SetConstant(d, "wkbMultiSurfaceZM",SWIG_From_int(static_cast< int >(3012)));
-  SWIG_Python_SetConstant(d, "wkbCurveZM",SWIG_From_int(static_cast< int >(3013)));
-  SWIG_Python_SetConstant(d, "wkbSurfaceZM",SWIG_From_int(static_cast< int >(3014)));
-  SWIG_Python_SetConstant(d, "wkbPolyhedralSurfaceZM",SWIG_From_int(static_cast< int >(3015)));
-  SWIG_Python_SetConstant(d, "wkbTINZM",SWIG_From_int(static_cast< int >(3016)));
-  SWIG_Python_SetConstant(d, "wkbPoint25D",SWIG_From_int(static_cast< int >(0x80000001)));
-  SWIG_Python_SetConstant(d, "wkbLineString25D",SWIG_From_int(static_cast< int >(0x80000002)));
-  SWIG_Python_SetConstant(d, "wkbPolygon25D",SWIG_From_int(static_cast< int >(0x80000003)));
-  SWIG_Python_SetConstant(d, "wkbMultiPoint25D",SWIG_From_int(static_cast< int >(0x80000004)));
-  SWIG_Python_SetConstant(d, "wkbMultiLineString25D",SWIG_From_int(static_cast< int >(0x80000005)));
-  SWIG_Python_SetConstant(d, "wkbMultiPolygon25D",SWIG_From_int(static_cast< int >(0x80000006)));
-  SWIG_Python_SetConstant(d, "wkbGeometryCollection25D",SWIG_From_int(static_cast< int >(0x80000007)));
-  SWIG_Python_SetConstant(d, "OFTInteger",SWIG_From_int(static_cast< int >(0)));
-  SWIG_Python_SetConstant(d, "OFTIntegerList",SWIG_From_int(static_cast< int >(1)));
-  SWIG_Python_SetConstant(d, "OFTReal",SWIG_From_int(static_cast< int >(2)));
-  SWIG_Python_SetConstant(d, "OFTRealList",SWIG_From_int(static_cast< int >(3)));
-  SWIG_Python_SetConstant(d, "OFTString",SWIG_From_int(static_cast< int >(4)));
-  SWIG_Python_SetConstant(d, "OFTStringList",SWIG_From_int(static_cast< int >(5)));
-  SWIG_Python_SetConstant(d, "OFTWideString",SWIG_From_int(static_cast< int >(6)));
-  SWIG_Python_SetConstant(d, "OFTWideStringList",SWIG_From_int(static_cast< int >(7)));
-  SWIG_Python_SetConstant(d, "OFTBinary",SWIG_From_int(static_cast< int >(8)));
-  SWIG_Python_SetConstant(d, "OFTDate",SWIG_From_int(static_cast< int >(9)));
-  SWIG_Python_SetConstant(d, "OFTTime",SWIG_From_int(static_cast< int >(10)));
-  SWIG_Python_SetConstant(d, "OFTDateTime",SWIG_From_int(static_cast< int >(11)));
-  SWIG_Python_SetConstant(d, "OFTInteger64",SWIG_From_int(static_cast< int >(12)));
-  SWIG_Python_SetConstant(d, "OFTInteger64List",SWIG_From_int(static_cast< int >(13)));
-  SWIG_Python_SetConstant(d, "OFSTNone",SWIG_From_int(static_cast< int >(0)));
-  SWIG_Python_SetConstant(d, "OFSTBoolean",SWIG_From_int(static_cast< int >(1)));
-  SWIG_Python_SetConstant(d, "OFSTInt16",SWIG_From_int(static_cast< int >(2)));
-  SWIG_Python_SetConstant(d, "OFSTFloat32",SWIG_From_int(static_cast< int >(3)));
-  SWIG_Python_SetConstant(d, "OJUndefined",SWIG_From_int(static_cast< int >(0)));
-  SWIG_Python_SetConstant(d, "OJLeft",SWIG_From_int(static_cast< int >(1)));
-  SWIG_Python_SetConstant(d, "OJRight",SWIG_From_int(static_cast< int >(2)));
-  SWIG_Python_SetConstant(d, "wkbXDR",SWIG_From_int(static_cast< int >(0)));
-  SWIG_Python_SetConstant(d, "wkbNDR",SWIG_From_int(static_cast< int >(1)));
-  SWIG_Python_SetConstant(d, "NullFID",SWIG_From_int(static_cast< int >(-1)));
-  SWIG_Python_SetConstant(d, "ALTER_NAME_FLAG",SWIG_From_int(static_cast< int >(1)));
-  SWIG_Python_SetConstant(d, "ALTER_TYPE_FLAG",SWIG_From_int(static_cast< int >(2)));
-  SWIG_Python_SetConstant(d, "ALTER_WIDTH_PRECISION_FLAG",SWIG_From_int(static_cast< int >(4)));
-  SWIG_Python_SetConstant(d, "ALTER_NULLABLE_FLAG",SWIG_From_int(static_cast< int >(8)));
-  SWIG_Python_SetConstant(d, "ALTER_DEFAULT_FLAG",SWIG_From_int(static_cast< int >(16)));
-  SWIG_Python_SetConstant(d, "ALTER_ALL_FLAG",SWIG_From_int(static_cast< int >(1+2+4+8+16)));
-  SWIG_Python_SetConstant(d, "F_VAL_NULL",SWIG_From_int(static_cast< int >(0x00000001)));
-  SWIG_Python_SetConstant(d, "F_VAL_GEOM_TYPE",SWIG_From_int(static_cast< int >(0x00000002)));
-  SWIG_Python_SetConstant(d, "F_VAL_WIDTH",SWIG_From_int(static_cast< int >(0x00000004)));
-  SWIG_Python_SetConstant(d, "F_VAL_ALLOW_NULL_WHEN_DEFAULT",SWIG_From_int(static_cast< int >(0x00000008)));
-  SWIG_Python_SetConstant(d, "F_VAL_ALL",SWIG_From_int(static_cast< int >(0xFFFFFFFF)));
-  SWIG_Python_SetConstant(d, "OLCRandomRead",SWIG_FromCharPtr("RandomRead"));
-  SWIG_Python_SetConstant(d, "OLCSequentialWrite",SWIG_FromCharPtr("SequentialWrite"));
-  SWIG_Python_SetConstant(d, "OLCRandomWrite",SWIG_FromCharPtr("RandomWrite"));
-  SWIG_Python_SetConstant(d, "OLCFastSpatialFilter",SWIG_FromCharPtr("FastSpatialFilter"));
-  SWIG_Python_SetConstant(d, "OLCFastFeatureCount",SWIG_FromCharPtr("FastFeatureCount"));
-  SWIG_Python_SetConstant(d, "OLCFastGetExtent",SWIG_FromCharPtr("FastGetExtent"));
-  SWIG_Python_SetConstant(d, "OLCCreateField",SWIG_FromCharPtr("CreateField"));
-  SWIG_Python_SetConstant(d, "OLCDeleteField",SWIG_FromCharPtr("DeleteField"));
-  SWIG_Python_SetConstant(d, "OLCReorderFields",SWIG_FromCharPtr("ReorderFields"));
-  SWIG_Python_SetConstant(d, "OLCAlterFieldDefn",SWIG_FromCharPtr("AlterFieldDefn"));
-  SWIG_Python_SetConstant(d, "OLCTransactions",SWIG_FromCharPtr("Transactions"));
-  SWIG_Python_SetConstant(d, "OLCDeleteFeature",SWIG_FromCharPtr("DeleteFeature"));
-  SWIG_Python_SetConstant(d, "OLCFastSetNextByIndex",SWIG_FromCharPtr("FastSetNextByIndex"));
-  SWIG_Python_SetConstant(d, "OLCStringsAsUTF8",SWIG_FromCharPtr("StringsAsUTF8"));
-  SWIG_Python_SetConstant(d, "OLCIgnoreFields",SWIG_FromCharPtr("IgnoreFields"));
-  SWIG_Python_SetConstant(d, "OLCCreateGeomField",SWIG_FromCharPtr("CreateGeomField"));
-  SWIG_Python_SetConstant(d, "OLCCurveGeometries",SWIG_FromCharPtr("CurveGeometries"));
-  SWIG_Python_SetConstant(d, "OLCMeasuredGeometries",SWIG_FromCharPtr("MeasuredGeometries"));
-  SWIG_Python_SetConstant(d, "ODsCCreateLayer",SWIG_FromCharPtr("CreateLayer"));
-  SWIG_Python_SetConstant(d, "ODsCDeleteLayer",SWIG_FromCharPtr("DeleteLayer"));
-  SWIG_Python_SetConstant(d, "ODsCCreateGeomFieldAfterCreateLayer",SWIG_FromCharPtr("CreateGeomFieldAfterCreateLayer"));
-  SWIG_Python_SetConstant(d, "ODsCCurveGeometries",SWIG_FromCharPtr("CurveGeometries"));
-  SWIG_Python_SetConstant(d, "ODsCTransactions",SWIG_FromCharPtr("Transactions"));
-  SWIG_Python_SetConstant(d, "ODsCEmulatedTransactions",SWIG_FromCharPtr("EmulatedTransactions"));
-  SWIG_Python_SetConstant(d, "ODsCMeasuredGeometries",SWIG_FromCharPtr("MeasuredGeometries"));
-  SWIG_Python_SetConstant(d, "ODrCCreateDataSource",SWIG_FromCharPtr("CreateDataSource"));
-  SWIG_Python_SetConstant(d, "ODrCDeleteDataSource",SWIG_FromCharPtr("DeleteDataSource"));
-  SWIG_Python_SetConstant(d, "OLMD_FID64",SWIG_FromCharPtr("OLMD_FID64"));
-  SWIG_Python_SetConstant(d, "OGRERR_NONE",SWIG_From_int(static_cast< int >(0)));
-  SWIG_Python_SetConstant(d, "OGRERR_NOT_ENOUGH_DATA",SWIG_From_int(static_cast< int >(1)));
-  SWIG_Python_SetConstant(d, "OGRERR_NOT_ENOUGH_MEMORY",SWIG_From_int(static_cast< int >(2)));
-  SWIG_Python_SetConstant(d, "OGRERR_UNSUPPORTED_GEOMETRY_TYPE",SWIG_From_int(static_cast< int >(3)));
-  SWIG_Python_SetConstant(d, "OGRERR_UNSUPPORTED_OPERATION",SWIG_From_int(static_cast< int >(4)));
-  SWIG_Python_SetConstant(d, "OGRERR_CORRUPT_DATA",SWIG_From_int(static_cast< int >(5)));
-  SWIG_Python_SetConstant(d, "OGRERR_FAILURE",SWIG_From_int(static_cast< int >(6)));
-  SWIG_Python_SetConstant(d, "OGRERR_UNSUPPORTED_SRS",SWIG_From_int(static_cast< int >(7)));
-  SWIG_Python_SetConstant(d, "OGRERR_INVALID_HANDLE",SWIG_From_int(static_cast< int >(8)));
-  SWIG_Python_SetConstant(d, "OGRERR_NON_EXISTING_FEATURE",SWIG_From_int(static_cast< int >(9)));
   
   
   if ( OGRGetDriverCount() == 0 ) {
@@ -32586,6 +36571,8 @@ SWIG_init(void) {
   
   
   
+  /* Initialize threading */
+  SWIG_PYTHON_INITIALIZE_THREADS;
 #if PY_VERSION_HEX >= 0x03000000
   return m;
 #else
diff --git a/swig/python/extensions/osr_wrap.cpp b/swig/python/extensions/osr_wrap.cpp
index e70583c..e52efe3 100644
--- a/swig/python/extensions/osr_wrap.cpp
+++ b/swig/python/extensions/osr_wrap.cpp
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.12
+ * Version 3.0.8
  *
  * This file is not intended to be easily readable and contains a number of
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -8,8 +8,13 @@
  * interface file instead.
  * ----------------------------------------------------------------------------- */
 
+
+#ifndef SWIGPYTHON
 #define SWIGPYTHON
 #define SED_HACKS
+#endif
+
+#define SWIG_PYTHON_THREADS
 #define SWIG_PYTHON_DIRECTOR_NO_VTABLE
 
 
@@ -144,6 +149,19 @@ template <typename T> T SwigValueInit() {
 # define _SCL_SECURE_NO_DEPRECATE
 #endif
 
+/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */
+#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES)
+# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
+#endif
+
+/* Intel's compiler complains if a variable which was never initialised is
+ * cast to void, which is a common idiom which we use to indicate that we
+ * are aware a variable isn't used.  So we just silence that warning.
+ * See: https://github.com/swig/swig/issues/192 for more discussion.
+ */
+#ifdef __INTEL_COMPILER
+# pragma warning disable 592
+#endif
 
 
 #if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG)
@@ -561,14 +579,14 @@ SWIG_MangledTypeQueryModule(swig_module_info *start,
   swig_module_info *iter = start;
   do {
     if (iter->size) {
-      register size_t l = 0;
-      register size_t r = iter->size - 1;
+      size_t l = 0;
+      size_t r = iter->size - 1;
       do {
 	/* since l+r >= 0, we can (>> 1) instead (/ 2) */
-	register size_t i = (l + r) >> 1;
+	size_t i = (l + r) >> 1;
 	const char *iname = iter->types[i]->name;
 	if (iname) {
-	  register int compare = strcmp(name, iname);
+	  int compare = strcmp(name, iname);
 	  if (compare == 0) {
 	    return iter->types[i];
 	  } else if (compare < 0) {
@@ -612,7 +630,7 @@ SWIG_TypeQueryModule(swig_module_info *start,
        of the str field (the human readable name) */
     swig_module_info *iter = start;
     do {
-      register size_t i = 0;
+      size_t i = 0;
       for (; i < iter->size; ++i) {
 	if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name)))
 	  return iter->types[i];
@@ -631,10 +649,10 @@ SWIG_TypeQueryModule(swig_module_info *start,
 SWIGRUNTIME char *
 SWIG_PackData(char *c, void *ptr, size_t sz) {
   static const char hex[17] = "0123456789abcdef";
-  register const unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu =  u + sz;
+  const unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu =  u + sz;
   for (; u != eu; ++u) {
-    register unsigned char uu = *u;
+    unsigned char uu = *u;
     *(c++) = hex[(uu & 0xf0) >> 4];
     *(c++) = hex[uu & 0xf];
   }
@@ -646,11 +664,11 @@ SWIG_PackData(char *c, void *ptr, size_t sz) {
 */
 SWIGRUNTIME const char *
 SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
-  register unsigned char *u = (unsigned char *) ptr;
-  register const unsigned char *eu = u + sz;
+  unsigned char *u = (unsigned char *) ptr;
+  const unsigned char *eu = u + sz;
   for (; u != eu; ++u) {
-    register char d = *(c++);
-    register unsigned char uu;
+    char d = *(c++);
+    unsigned char uu;
     if ((d >= '0') && (d <= '9'))
       uu = ((d - '0') << 4);
     else if ((d >= 'a') && (d <= 'f'))
@@ -1313,7 +1331,7 @@ SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) {
 
 /* Unpack the argument tuple */
 
-SWIGINTERN int
+SWIGINTERN Py_ssize_t
 SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs)
 {
   if (!args) {
@@ -1327,7 +1345,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
   }  
   if (!PyTuple_Check(args)) {
     if (min <= 1 && max >= 1) {
-      register int i;
+      Py_ssize_t i;
       objs[0] = args;
       for (i = 1; i < max; ++i) {
 	objs[i] = 0;
@@ -1337,7 +1355,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
     PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple");
     return 0;
   } else {
-    register Py_ssize_t l = PyTuple_GET_SIZE(args);
+    Py_ssize_t l = PyTuple_GET_SIZE(args);
     if (l < min) {
       PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", 
 		   name, (min == max ? "" : "at least "), (int)min, (int)l);
@@ -1347,7 +1365,7 @@ SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssi
 		   name, (min == max ? "" : "at most "), (int)max, (int)l);
       return 0;
     } else {
-      register int i;
+      Py_ssize_t i;
       for (i = 0; i < l; ++i) {
 	objs[i] = PyTuple_GET_ITEM(args, i);
       }
@@ -1533,6 +1551,23 @@ typedef struct {
 #endif
 } SwigPyObject;
 
+
+#ifdef SWIGPYTHON_BUILTIN
+
+SWIGRUNTIME PyObject *
+SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args))
+{
+  SwigPyObject *sobj = (SwigPyObject *)v;
+
+  if (!sobj->dict)
+    sobj->dict = PyDict_New();
+
+  Py_INCREF(sobj->dict);
+  return sobj->dict;
+}
+
+#endif
+
 SWIGRUNTIME PyObject *
 SwigPyObject_long(SwigPyObject *v)
 {
@@ -1671,16 +1706,32 @@ SwigPyObject_dealloc(PyObject *v)
     if (destroy) {
       /* destroy is always a VARARGS method */
       PyObject *res;
+
+      /* PyObject_CallFunction() has the potential to silently drop
+         the active active exception.  In cases of unnamed temporary
+         variable or where we just finished iterating over a generator
+         StopIteration will be active right now, and this needs to
+         remain true upon return from SwigPyObject_dealloc.  So save
+         and restore. */
+      
+      PyObject *val = NULL, *type = NULL, *tb = NULL;
+      PyErr_Fetch(&val, &type, &tb);
+
       if (data->delargs) {
-	/* we need to create a temporary object to carry the destroy operation */
-	PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
-	res = SWIG_Python_CallFunctor(destroy, tmp);
-	Py_DECREF(tmp);
+        /* we need to create a temporary object to carry the destroy operation */
+        PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0);
+        res = SWIG_Python_CallFunctor(destroy, tmp);
+        Py_DECREF(tmp);
       } else {
-	PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
-	PyObject *mself = PyCFunction_GET_SELF(destroy);
-	res = ((*meth)(mself, v));
+        PyCFunction meth = PyCFunction_GET_FUNCTION(destroy);
+        PyObject *mself = PyCFunction_GET_SELF(destroy);
+        res = ((*meth)(mself, v));
       }
+      if (!res)
+        PyErr_WriteUnraisable(destroy);
+
+      PyErr_Restore(val, type, tb);
+
       Py_XDECREF(res);
     } 
 #if !defined(SWIG_PYTHON_SILENT_MEMLEAK)
@@ -1704,6 +1755,7 @@ SwigPyObject_append(PyObject* v, PyObject* next)
   next = tmp;
 #endif
   if (!SwigPyObject_Check(next)) {
+    PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject");
     return NULL;
   }
   sobj->next = next;
@@ -1803,7 +1855,7 @@ swigobject_methods[] = {
 static PyMethodDef
 swigobject_methods[] = {
   {(char *)"disown",  (PyCFunction)SwigPyObject_disown,  METH_VARARGS,  (char *)"releases ownership of the pointer"},
-  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"aquires ownership of the pointer"},
+  {(char *)"acquire", (PyCFunction)SwigPyObject_acquire, METH_VARARGS,  (char *)"acquires ownership of the pointer"},
   {(char *)"own",     (PyCFunction)SwigPyObject_own,     METH_VARARGS,  (char *)"returns/sets ownership of the pointer"},
   {(char *)"append",  (PyCFunction)SwigPyObject_append,  METH_VARARGS,  (char *)"appends another 'this' object"},
   {(char *)"next",    (PyCFunction)SwigPyObject_next,    METH_VARARGS,  (char *)"returns the next 'this' object"},
@@ -1859,7 +1911,9 @@ SwigPyObject_TypeOnce(void) {
     (unaryfunc)SwigPyObject_oct,  /*nb_oct*/
     (unaryfunc)SwigPyObject_hex,  /*nb_hex*/
 #endif
-#if PY_VERSION_HEX >= 0x03000000 /* 3.0 */
+#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */
+#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */
 #elif PY_VERSION_HEX >= 0x02050000 /* 2.5.0 */
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */
@@ -1939,10 +1993,19 @@ SwigPyObject_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpyobject_type = tmp;
@@ -2118,10 +2181,19 @@ SwigPyPacked_TypeOnce(void) {
       0,                                    /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-      0,                                    /* tp_version */
+      0,                                    /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+      0,                                    /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-      0,0,0,0                               /* tp_alloc -> tp_next */
+      0,                                    /* tp_allocs */
+      0,                                    /* tp_frees */
+      0,                                    /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+      0,                                    /* tp_prev */
+#endif
+      0                                     /* tp_next */
 #endif
     };
     swigpypacked_type = tmp;
@@ -2462,7 +2534,7 @@ SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this)
     }
   } else {
 #if PY_VERSION_HEX >= 0x03000000
-    inst = PyBaseObject_Type.tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
+    inst = ((PyTypeObject*) data->newargs)->tp_new((PyTypeObject*) data->newargs, Py_None, Py_None);
     if (inst) {
       PyObject_SetAttr(inst, SWIG_This(), swig_this);
       Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
@@ -2572,18 +2644,21 @@ SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int f
 	  newobj = (SwigPyObject *) newobj->next;
         newobj->next = next_self;
         newobj = (SwigPyObject *)next_self;
+#ifdef SWIGPYTHON_BUILTIN
+        newobj->dict = 0;
+#endif
       }
     } else {
       newobj = PyObject_New(SwigPyObject, clientdata->pytype);
+#ifdef SWIGPYTHON_BUILTIN
+      newobj->dict = 0;
+#endif
     }
     if (newobj) {
       newobj->ptr = ptr;
       newobj->ty = type;
       newobj->own = own;
       newobj->next = 0;
-#ifdef SWIGPYTHON_BUILTIN
-      newobj->dict = 0;
-#endif
       return (PyObject*) newobj;
     }
     return SWIG_Py_Void();
@@ -2646,13 +2721,11 @@ PyModule_AddObject(PyObject *m, char *name, PyObject *o)
 {
   PyObject *dict;
   if (!PyModule_Check(m)) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs module as first arg");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs module as first arg");
     return SWIG_ERROR;
   }
   if (!o) {
-    PyErr_SetString(PyExc_TypeError,
-		    "PyModule_AddObject() needs non-NULL value");
+    PyErr_SetString(PyExc_TypeError, "PyModule_AddObject() needs non-NULL value");
     return SWIG_ERROR;
   }
   
@@ -2971,7 +3044,7 @@ static swig_module_info swig_module = {swig_types, 8, 0, 0, 0, 0};
 #endif
 #define SWIG_name    "_osr"
 
-#define SWIGVERSION 0x020012 
+#define SWIGVERSION 0x030008 
 #define SWIG_VERSION SWIGVERSION
 
 
@@ -2994,27 +3067,35 @@ namespace swig {
 
     SwigPtr_PyObject(const SwigPtr_PyObject& item) : _obj(item._obj)
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(_obj);      
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     SwigPtr_PyObject(PyObject *obj, bool initial_ref = true) :_obj(obj)
     {
       if (initial_ref) {
+        SWIG_PYTHON_THREAD_BEGIN_BLOCK;
         Py_XINCREF(_obj);
+        SWIG_PYTHON_THREAD_END_BLOCK;
       }
     }
     
     SwigPtr_PyObject & operator=(const SwigPtr_PyObject& item) 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XINCREF(item._obj);
       Py_XDECREF(_obj);
       _obj = item._obj;
+      SWIG_PYTHON_THREAD_END_BLOCK;
       return *this;      
     }
     
     ~SwigPtr_PyObject() 
     {
+      SWIG_PYTHON_THREAD_BEGIN_BLOCK;
       Py_XDECREF(_obj);
+      SWIG_PYTHON_THREAD_END_BLOCK;
     }
     
     operator PyObject *() const
@@ -3067,9 +3148,13 @@ SWIG_FromCharPtrAndSize(const char* carray, size_t size)
 	SWIG_InternalNewPointerObj(const_cast< char * >(carray), pchar_descriptor, 0) : SWIG_Py_Void();
     } else {
 #if PY_VERSION_HEX >= 0x03000000
-      return PyUnicode_FromStringAndSize(carray, static_cast< int >(size));
+#if PY_VERSION_HEX >= 0x03010000
+      return PyUnicode_DecodeUTF8(carray, static_cast< Py_ssize_t >(size), "surrogateescape");
+#else
+      return PyUnicode_FromStringAndSize(carray, static_cast< Py_ssize_t >(size));
+#endif
 #else
-      return PyString_FromStringAndSize(carray, static_cast< int >(size));
+      return PyString_FromStringAndSize(carray, static_cast< Py_ssize_t >(size));
 #endif
     }
   } else {
@@ -3372,18 +3457,17 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 #else
 	if (*alloc == SWIG_NEWOBJ) 
 #endif
-	  {
-	    *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
-	    *alloc = SWIG_NEWOBJ;
-	  }
-	else {
+	{
+	  *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+	  *alloc = SWIG_NEWOBJ;
+	} else {
 	  *cptr = cstr;
 	  *alloc = SWIG_OLDOBJ;
 	}
       } else {
-        #if PY_VERSION_HEX>=0x03000000
-        assert(0); /* Should never reach here in Python 3 */
-        #endif
+	#if PY_VERSION_HEX>=0x03000000
+	assert(0); /* Should never reach here in Python 3 */
+	#endif
 	*cptr = SWIG_Python_str_AsChar(obj);
       }
     }
@@ -3393,6 +3477,30 @@ SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc)
 #endif
     return SWIG_OK;
   } else {
+#if defined(SWIG_PYTHON_2_UNICODE)
+#if PY_VERSION_HEX<0x03000000
+    if (PyUnicode_Check(obj)) {
+      char *cstr; Py_ssize_t len;
+      if (!alloc && cptr) {
+        return SWIG_RuntimeError;
+      }
+      obj = PyUnicode_AsUTF8String(obj);
+      if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) {
+        if (cptr) {
+          if (alloc) *alloc = SWIG_NEWOBJ;
+          *cptr = reinterpret_cast< char* >(memcpy((new char[len + 1]), cstr, sizeof(char)*(len + 1)));
+        }
+        if (psize) *psize = len + 1;
+
+        Py_XDECREF(obj);
+        return SWIG_OK;
+      } else {
+        Py_XDECREF(obj);
+      }
+    }
+#endif
+#endif
+
     swig_type_info* pchar_descriptor = SWIG_pchar_descriptor();
     if (pchar_descriptor) {
       void* vptr = 0;
@@ -3518,9 +3626,11 @@ SWIG_AsVal_double (PyObject *obj, double *val)
   if (PyFloat_Check(obj)) {
     if (val) *val = PyFloat_AsDouble(obj);
     return SWIG_OK;
+#if PY_VERSION_HEX < 0x03000000
   } else if (PyInt_Check(obj)) {
     if (val) *val = PyInt_AsLong(obj);
     return SWIG_OK;
+#endif
   } else if (PyLong_Check(obj)) {
     double v = PyLong_AsDouble(obj);
     if (!PyErr_Occurred()) {
@@ -3594,16 +3704,20 @@ SWIG_CanCastAsInteger(double *d, double min, double max) {
 SWIGINTERN int
 SWIG_AsVal_long (PyObject *obj, long* val)
 {
+#if PY_VERSION_HEX < 0x03000000
   if (PyInt_Check(obj)) {
     if (val) *val = PyInt_AsLong(obj);
     return SWIG_OK;
-  } else if (PyLong_Check(obj)) {
+  } else
+#endif
+  if (PyLong_Check(obj)) {
     long v = PyLong_AsLong(obj);
     if (!PyErr_Occurred()) {
       if (val) *val = v;
       return SWIG_OK;
     } else {
       PyErr_Clear();
+      return SWIG_OverflowError;
     }
   }
 #ifdef SWIG_PYTHON_CAST_MODE
@@ -3676,6 +3790,10 @@ SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnits(OSRSpatialReferenceSh
 SWIGINTERN OGRErr OSRSpatialReferenceShadow_SetLinearUnitsAndUpdateParameters(OSRSpatialReferenceShadow *self,char const *name,double to_meters){
     return OSRSetLinearUnitsAndUpdateParameters( self, name, to_meters );
   }
+SWIGINTERN double OSRSpatialReferenceShadow_GetTargetLinearUnits(OSRSpatialReferenceShadow *self,char const *target_key){
+    // Return code ignored.
+    return OSRGetTargetLinearUnits( self, target_key, 0 );
+  }
 SWIGINTERN double OSRSpatialReferenceShadow_GetLinearUnits(OSRSpatialReferenceShadow *self){
     // Return code ignored.
     return OSRGetLinearUnits( self, 0 );
@@ -4148,207 +4266,2118 @@ SWIGINTERN void OSRCoordinateTransformationShadow_TransformPoints(OSRCoordinateT
 #ifdef __cplusplus
 extern "C" {
 #endif
-SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  int result;
-  
-  if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
-  result = (int)GetUseExceptions();
-  resultobj = SWIG_From_int(static_cast< int >(result));
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  return NULL;
+SWIGINTERN PyObject *SRS_WKT_WGS84_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_WKT_WGS84",SWIG_FromCharPtr("GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"));
+  return SWIG_Py_Void();
 }
 
 
-SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  
-  if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
-  UseExceptions();
-  resultobj = SWIG_Py_Void();
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  return NULL;
+SWIGINTERN PyObject *SRS_PT_ALBERS_CONIC_EQUAL_AREA_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_ALBERS_CONIC_EQUAL_AREA",SWIG_FromCharPtr("Albers_Conic_Equal_Area"));
+  return SWIG_Py_Void();
 }
 
 
-SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  
-  if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
-  DontUseExceptions();
-  resultobj = SWIG_Py_Void();
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  return NULL;
+SWIGINTERN PyObject *SRS_PT_AZIMUTHAL_EQUIDISTANT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_AZIMUTHAL_EQUIDISTANT",SWIG_FromCharPtr("Azimuthal_Equidistant"));
+  return SWIG_Py_Void();
 }
 
 
-SWIGINTERN PyObject *_wrap_GetWellKnownGeogCSAsWKT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  char *arg1 = (char *) 0 ;
-  char **arg2 = (char **) 0 ;
-  int res1 ;
-  char *buf1 = 0 ;
-  int alloc1 = 0 ;
-  char *argout2 = 0 ;
-  PyObject * obj0 = 0 ;
-  OGRErr result;
-  
-  {
-    /* %typemap(in,numinputs=0) (char **argout2) */
-    arg2 = &argout2;
-  }
-  if (!PyArg_ParseTuple(args,(char *)"O:GetWellKnownGeogCSAsWKT",&obj0)) SWIG_fail;
-  res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetWellKnownGeogCSAsWKT" "', argument " "1"" of type '" "char const *""'");
-  }
-  arg1 = reinterpret_cast< char * >(buf1);
-  {
-    if (!arg1) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (OGRErr)GetWellKnownGeogCSAsWKT((char const *)arg1,arg2);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
-  }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(argout) (char **argout) */
-    PyObject *o;
-    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
-      o = GDALPythonObjectFromCStr( *arg2 );
-    }
-    else {
-      o = Py_None;
-      Py_INCREF( o );
-    }
-    resultobj = t_output_helper(resultobj, o);
-  }
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-  {
-    /* %typemap(freearg) (char **argout) */
-    if ( *arg2 )
-    CPLFree( *arg2 );
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
-      resultobj = PyInt_FromLong( result );
-    }
-  }
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-  {
-    /* %typemap(freearg) (char **argout) */
-    if ( *arg2 )
-    CPLFree( *arg2 );
-  }
-  return NULL;
+SWIGINTERN PyObject *SRS_PT_CASSINI_SOLDNER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_CASSINI_SOLDNER",SWIG_FromCharPtr("Cassini_Soldner"));
+  return SWIG_Py_Void();
 }
 
 
-SWIGINTERN PyObject *_wrap_GetUserInputAsWKT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
-  char *arg1 = (char *) 0 ;
-  char **arg2 = (char **) 0 ;
-  int res1 ;
-  char *buf1 = 0 ;
-  int alloc1 = 0 ;
-  char *argout2 = 0 ;
-  PyObject * obj0 = 0 ;
-  OGRErr result;
-  
-  {
-    /* %typemap(in,numinputs=0) (char **argout2) */
-    arg2 = &argout2;
-  }
-  if (!PyArg_ParseTuple(args,(char *)"O:GetUserInputAsWKT",&obj0)) SWIG_fail;
-  res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetUserInputAsWKT" "', argument " "1"" of type '" "char const *""'");
-  }
-  arg1 = reinterpret_cast< char * >(buf1);
-  {
-    if (!arg1) {
-      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
-    }
-  }
-  {
-    if ( bUseExceptions ) {
-      CPLErrorReset();
-    }
-    result = (OGRErr)GetUserInputAsWKT((char const *)arg1,arg2);
-#ifndef SED_HACKS
-    if ( bUseExceptions ) {
-      CPLErr eclass = CPLGetLastErrorType();
-      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
-        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
-      }
-    }
-#endif
-  }
-  {
-    /* %typemap(out) OGRErr */
-    if ( result != 0 && bUseExceptions) {
-      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
-      SWIG_fail;
-    }
-  }
-  {
-    /* %typemap(argout) (char **argout) */
-    PyObject *o;
-    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
-      o = GDALPythonObjectFromCStr( *arg2 );
-    }
-    else {
-      o = Py_None;
-      Py_INCREF( o );
-    }
-    resultobj = t_output_helper(resultobj, o);
-  }
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-  {
-    /* %typemap(freearg) (char **argout) */
-    if ( *arg2 )
-    CPLFree( *arg2 );
-  }
-  {
-    /* %typemap(ret) OGRErr */
-    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
-      resultobj = PyInt_FromLong( result );
-    }
-  }
-  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
-  return resultobj;
-fail:
-  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
-  {
-    /* %typemap(freearg) (char **argout) */
+SWIGINTERN PyObject *SRS_PT_CYLINDRICAL_EQUAL_AREA_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_CYLINDRICAL_EQUAL_AREA",SWIG_FromCharPtr("Cylindrical_Equal_Area"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_BONNE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_BONNE",SWIG_FromCharPtr("Bonne"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_ECKERT_I_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_I",SWIG_FromCharPtr("Eckert_I"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_ECKERT_II_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_II",SWIG_FromCharPtr("Eckert_II"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_ECKERT_III_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_III",SWIG_FromCharPtr("Eckert_III"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_ECKERT_IV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_IV",SWIG_FromCharPtr("Eckert_IV"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_ECKERT_V_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_V",SWIG_FromCharPtr("Eckert_V"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_ECKERT_VI_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_VI",SWIG_FromCharPtr("Eckert_VI"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_EQUIDISTANT_CONIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_EQUIDISTANT_CONIC",SWIG_FromCharPtr("Equidistant_Conic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_EQUIRECTANGULAR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_EQUIRECTANGULAR",SWIG_FromCharPtr("Equirectangular"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_GALL_STEREOGRAPHIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_GALL_STEREOGRAPHIC",SWIG_FromCharPtr("Gall_Stereographic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_GAUSSSCHREIBERTMERCATOR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_GAUSSSCHREIBERTMERCATOR",SWIG_FromCharPtr("Gauss_Schreiber_Transverse_Mercator"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_GEOSTATIONARY_SATELLITE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_GEOSTATIONARY_SATELLITE",SWIG_FromCharPtr("Geostationary_Satellite"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_GOODE_HOMOLOSINE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_GOODE_HOMOLOSINE",SWIG_FromCharPtr("Goode_Homolosine"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_IGH_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_IGH",SWIG_FromCharPtr("Interrupted_Goode_Homolosine"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_GNOMONIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_GNOMONIC",SWIG_FromCharPtr("Gnomonic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER",SWIG_FromCharPtr("Hotine_Oblique_Mercator_Azimuth_Center"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_HOTINE_OBLIQUE_MERCATOR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_HOTINE_OBLIQUE_MERCATOR",SWIG_FromCharPtr("Hotine_Oblique_Mercator"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN",SWIG_FromCharPtr("Hotine_Oblique_Mercator_Two_Point_Natural_Origin"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_LABORDE_OBLIQUE_MERCATOR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_LABORDE_OBLIQUE_MERCATOR",SWIG_FromCharPtr("Laborde_Oblique_Mercator"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP",SWIG_FromCharPtr("Lambert_Conformal_Conic_1SP"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP",SWIG_FromCharPtr("Lambert_Conformal_Conic_2SP"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM",SWIG_FromCharPtr("Lambert_Conformal_Conic_2SP_Belgium"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA",SWIG_FromCharPtr("Lambert_Azimuthal_Equal_Area"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_MERCATOR_1SP_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_MERCATOR_1SP",SWIG_FromCharPtr("Mercator_1SP"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_MERCATOR_2SP_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_MERCATOR_2SP",SWIG_FromCharPtr("Mercator_2SP"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_MERCATOR_AUXILIARY_SPHERE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_MERCATOR_AUXILIARY_SPHERE",SWIG_FromCharPtr("Mercator_Auxiliary_Sphere"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_MILLER_CYLINDRICAL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_MILLER_CYLINDRICAL",SWIG_FromCharPtr("Miller_Cylindrical"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_MOLLWEIDE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_MOLLWEIDE",SWIG_FromCharPtr("Mollweide"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_NEW_ZEALAND_MAP_GRID_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_NEW_ZEALAND_MAP_GRID",SWIG_FromCharPtr("New_Zealand_Map_Grid"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_OBLIQUE_STEREOGRAPHIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_OBLIQUE_STEREOGRAPHIC",SWIG_FromCharPtr("Oblique_Stereographic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_ORTHOGRAPHIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_ORTHOGRAPHIC",SWIG_FromCharPtr("Orthographic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_POLAR_STEREOGRAPHIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_POLAR_STEREOGRAPHIC",SWIG_FromCharPtr("Polar_Stereographic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_POLYCONIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_POLYCONIC",SWIG_FromCharPtr("Polyconic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_ROBINSON_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_ROBINSON",SWIG_FromCharPtr("Robinson"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_SINUSOIDAL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_SINUSOIDAL",SWIG_FromCharPtr("Sinusoidal"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_STEREOGRAPHIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_STEREOGRAPHIC",SWIG_FromCharPtr("Stereographic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_SWISS_OBLIQUE_CYLINDRICAL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_SWISS_OBLIQUE_CYLINDRICAL",SWIG_FromCharPtr("Swiss_Oblique_Cylindrical"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_TRANSVERSE_MERCATOR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR",SWIG_FromCharPtr("Transverse_Mercator"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED",SWIG_FromCharPtr("Transverse_Mercator_South_Orientated"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_TRANSVERSE_MERCATOR_MI_21_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_21",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_21"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_TRANSVERSE_MERCATOR_MI_22_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_22",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_22"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_TRANSVERSE_MERCATOR_MI_23_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_23",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_23"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_TRANSVERSE_MERCATOR_MI_24_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_24",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_24"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_TRANSVERSE_MERCATOR_MI_25_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_25",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_25"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_TUNISIA_MINING_GRID_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_TUNISIA_MINING_GRID",SWIG_FromCharPtr("Tunisia_Mining_Grid"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_TWO_POINT_EQUIDISTANT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_TWO_POINT_EQUIDISTANT",SWIG_FromCharPtr("Two_Point_Equidistant"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_VANDERGRINTEN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_VANDERGRINTEN",SWIG_FromCharPtr("VanDerGrinten"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_KROVAK_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_KROVAK",SWIG_FromCharPtr("Krovak"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_IMW_POLYCONIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_IMW_POLYCONIC",SWIG_FromCharPtr("International_Map_of_the_World_Polyconic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WAGNER_I_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_I",SWIG_FromCharPtr("Wagner_I"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WAGNER_II_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_II",SWIG_FromCharPtr("Wagner_II"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WAGNER_III_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_III",SWIG_FromCharPtr("Wagner_III"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WAGNER_IV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_IV",SWIG_FromCharPtr("Wagner_IV"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WAGNER_V_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_V",SWIG_FromCharPtr("Wagner_V"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WAGNER_VI_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_VI",SWIG_FromCharPtr("Wagner_VI"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WAGNER_VII_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_VII",SWIG_FromCharPtr("Wagner_VII"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_QSC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_QSC",SWIG_FromCharPtr("Quadrilateralized_Spherical_Cube"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_AITOFF_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_AITOFF",SWIG_FromCharPtr("Aitoff"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WINKEL_I_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WINKEL_I",SWIG_FromCharPtr("Winkel_I"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WINKEL_II_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WINKEL_II",SWIG_FromCharPtr("Winkel_II"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_WINKEL_TRIPEL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_WINKEL_TRIPEL",SWIG_FromCharPtr("Winkel_Tripel"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_CRASTER_PARABOLIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_CRASTER_PARABOLIC",SWIG_FromCharPtr("Craster_Parabolic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_LOXIMUTHAL_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_LOXIMUTHAL",SWIG_FromCharPtr("Loximuthal"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_QUARTIC_AUTHALIC_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_QUARTIC_AUTHALIC",SWIG_FromCharPtr("Quartic_Authalic"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PT_SCH_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PT_SCH",SWIG_FromCharPtr("Spherical_Cross_Track_Height"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_CENTRAL_MERIDIAN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_CENTRAL_MERIDIAN",SWIG_FromCharPtr("central_meridian"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_SCALE_FACTOR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_SCALE_FACTOR",SWIG_FromCharPtr("scale_factor"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_STANDARD_PARALLEL_1_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_STANDARD_PARALLEL_1",SWIG_FromCharPtr("standard_parallel_1"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_STANDARD_PARALLEL_2_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_STANDARD_PARALLEL_2",SWIG_FromCharPtr("standard_parallel_2"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_PSEUDO_STD_PARALLEL_1_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_PSEUDO_STD_PARALLEL_1",SWIG_FromCharPtr("pseudo_standard_parallel_1"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LONGITUDE_OF_CENTER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_CENTER",SWIG_FromCharPtr("longitude_of_center"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LATITUDE_OF_CENTER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_CENTER",SWIG_FromCharPtr("latitude_of_center"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LONGITUDE_OF_ORIGIN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_ORIGIN",SWIG_FromCharPtr("longitude_of_origin"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LATITUDE_OF_ORIGIN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_ORIGIN",SWIG_FromCharPtr("latitude_of_origin"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_FALSE_EASTING_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_FALSE_EASTING",SWIG_FromCharPtr("false_easting"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_FALSE_NORTHING_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_FALSE_NORTHING",SWIG_FromCharPtr("false_northing"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_AZIMUTH_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_AZIMUTH",SWIG_FromCharPtr("azimuth"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LONGITUDE_OF_POINT_1_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_POINT_1",SWIG_FromCharPtr("longitude_of_point_1"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LATITUDE_OF_POINT_1_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_POINT_1",SWIG_FromCharPtr("latitude_of_point_1"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LONGITUDE_OF_POINT_2_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_POINT_2",SWIG_FromCharPtr("longitude_of_point_2"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LATITUDE_OF_POINT_2_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_POINT_2",SWIG_FromCharPtr("latitude_of_point_2"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LONGITUDE_OF_POINT_3_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_POINT_3",SWIG_FromCharPtr("longitude_of_point_3"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LATITUDE_OF_POINT_3_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_POINT_3",SWIG_FromCharPtr("latitude_of_point_3"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_RECTIFIED_GRID_ANGLE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_RECTIFIED_GRID_ANGLE",SWIG_FromCharPtr("rectified_grid_angle"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LANDSAT_NUMBER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LANDSAT_NUMBER",SWIG_FromCharPtr("landsat_number"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_PATH_NUMBER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_PATH_NUMBER",SWIG_FromCharPtr("path_number"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_PERSPECTIVE_POINT_HEIGHT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_PERSPECTIVE_POINT_HEIGHT",SWIG_FromCharPtr("perspective_point_height"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_SATELLITE_HEIGHT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_SATELLITE_HEIGHT",SWIG_FromCharPtr("satellite_height"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_FIPSZONE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_FIPSZONE",SWIG_FromCharPtr("fipszone"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_ZONE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_ZONE",SWIG_FromCharPtr("zone"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LATITUDE_OF_1ST_POINT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_1ST_POINT",SWIG_FromCharPtr("Latitude_Of_1st_Point"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LONGITUDE_OF_1ST_POINT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_1ST_POINT",SWIG_FromCharPtr("Longitude_Of_1st_Point"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LATITUDE_OF_2ND_POINT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_2ND_POINT",SWIG_FromCharPtr("Latitude_Of_2nd_Point"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_LONGITUDE_OF_2ND_POINT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_2ND_POINT",SWIG_FromCharPtr("Longitude_Of_2nd_Point"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_PEG_POINT_LATITUDE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_LATITUDE",SWIG_FromCharPtr("peg_point_latitude"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_PEG_POINT_LONGITUDE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_LONGITUDE",SWIG_FromCharPtr("peg_point_longitude"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_PEG_POINT_HEADING_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_HEADING",SWIG_FromCharPtr("peg_point_heading"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PP_PEG_POINT_HEIGHT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_HEIGHT",SWIG_FromCharPtr("peg_point_height"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_METER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_METER",SWIG_FromCharPtr("Meter"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_FOOT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_FOOT",SWIG_FromCharPtr("Foot (International)"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_FOOT_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_FOOT_CONV",SWIG_FromCharPtr("0.3048"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_FOOT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_FOOT",SWIG_FromCharPtr("Foot_US"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_FOOT_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_FOOT_CONV",SWIG_FromCharPtr("0.3048006096012192"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_NAUTICAL_MILE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_NAUTICAL_MILE",SWIG_FromCharPtr("Nautical Mile"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_NAUTICAL_MILE_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_NAUTICAL_MILE_CONV",SWIG_FromCharPtr("1852.0"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_LINK_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_LINK",SWIG_FromCharPtr("Link"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_LINK_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_LINK_CONV",SWIG_FromCharPtr("0.20116684023368047"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_CHAIN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_CHAIN",SWIG_FromCharPtr("Chain"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_CHAIN_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_CHAIN_CONV",SWIG_FromCharPtr("20.116684023368047"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_ROD_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_ROD",SWIG_FromCharPtr("Rod"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_ROD_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_ROD_CONV",SWIG_FromCharPtr("5.02921005842012"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_LINK_Clarke_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_LINK_Clarke",SWIG_FromCharPtr("Link_Clarke"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_LINK_Clarke_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_LINK_Clarke_CONV",SWIG_FromCharPtr("0.2011661949"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_KILOMETER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_KILOMETER",SWIG_FromCharPtr("Kilometer"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_KILOMETER_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_KILOMETER_CONV",SWIG_FromCharPtr("1000."));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_DECIMETER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_DECIMETER",SWIG_FromCharPtr("Decimeter"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_DECIMETER_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_DECIMETER_CONV",SWIG_FromCharPtr("0.1"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_CENTIMETER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_CENTIMETER",SWIG_FromCharPtr("Centimeter"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_CENTIMETER_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_CENTIMETER_CONV",SWIG_FromCharPtr("0.01"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_MILLIMETER_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_MILLIMETER",SWIG_FromCharPtr("Millimeter"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_MILLIMETER_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_MILLIMETER_CONV",SWIG_FromCharPtr("0.001"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_NAUT_MILE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_NAUT_MILE",SWIG_FromCharPtr("Nautical_Mile_International"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_NAUT_MILE_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_NAUT_MILE_CONV",SWIG_FromCharPtr("1852.0"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_INCH_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_INCH",SWIG_FromCharPtr("Inch_International"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_INCH_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_INCH_CONV",SWIG_FromCharPtr("0.0254"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_FOOT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FOOT",SWIG_FromCharPtr("Foot_International"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_FOOT_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FOOT_CONV",SWIG_FromCharPtr("0.3048"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_YARD_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_YARD",SWIG_FromCharPtr("Yard_International"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_YARD_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_YARD_CONV",SWIG_FromCharPtr("0.9144"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_STAT_MILE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_STAT_MILE",SWIG_FromCharPtr("Statute_Mile_International"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_STAT_MILE_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_STAT_MILE_CONV",SWIG_FromCharPtr("1609.344"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_FATHOM_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FATHOM",SWIG_FromCharPtr("Fathom_International"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_FATHOM_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FATHOM_CONV",SWIG_FromCharPtr("1.8288"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_CHAIN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_CHAIN",SWIG_FromCharPtr("Chain_International"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_CHAIN_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_CHAIN_CONV",SWIG_FromCharPtr("20.1168"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_LINK_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_LINK",SWIG_FromCharPtr("Link_International"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INTL_LINK_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INTL_LINK_CONV",SWIG_FromCharPtr("0.201168"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_INCH_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_INCH",SWIG_FromCharPtr("Inch_US_Surveyor"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_INCH_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_INCH_CONV",SWIG_FromCharPtr("0.025400050800101603"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_YARD_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_YARD",SWIG_FromCharPtr("Yard_US_Surveyor"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_YARD_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_YARD_CONV",SWIG_FromCharPtr("0.914401828803658"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_CHAIN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_CHAIN",SWIG_FromCharPtr("Chain_US_Surveyor"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_CHAIN_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_CHAIN_CONV",SWIG_FromCharPtr("20.11684023368047"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_STAT_MILE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_STAT_MILE",SWIG_FromCharPtr("Statute_Mile_US_Surveyor"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_US_STAT_MILE_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_US_STAT_MILE_CONV",SWIG_FromCharPtr("1609.347218694437"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INDIAN_YARD_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_YARD",SWIG_FromCharPtr("Yard_Indian"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INDIAN_YARD_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_YARD_CONV",SWIG_FromCharPtr("0.91439523"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INDIAN_FOOT_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_FOOT",SWIG_FromCharPtr("Foot_Indian"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INDIAN_FOOT_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_FOOT_CONV",SWIG_FromCharPtr("0.30479841"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INDIAN_CHAIN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_CHAIN",SWIG_FromCharPtr("Chain_Indian"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UL_INDIAN_CHAIN_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_CHAIN_CONV",SWIG_FromCharPtr("20.11669506"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UA_DEGREE_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UA_DEGREE",SWIG_FromCharPtr("degree"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UA_DEGREE_CONV_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UA_DEGREE_CONV",SWIG_FromCharPtr("0.0174532925199433"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_UA_RADIAN_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_UA_RADIAN",SWIG_FromCharPtr("radian"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_PM_GREENWICH_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_PM_GREENWICH",SWIG_FromCharPtr("Greenwich"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_DN_NAD27_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_DN_NAD27",SWIG_FromCharPtr("North_American_Datum_1927"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_DN_NAD83_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_DN_NAD83",SWIG_FromCharPtr("North_American_Datum_1983"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_DN_WGS72_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_DN_WGS72",SWIG_FromCharPtr("WGS_1972"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_DN_WGS84_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_DN_WGS84",SWIG_FromCharPtr("WGS_1984"));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_WGS84_SEMIMAJOR_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_WGS84_SEMIMAJOR",SWIG_From_double(static_cast< double >(6378137.0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *SRS_WGS84_INVFLATTENING_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "SRS_WGS84_INVFLATTENING",SWIG_From_double(static_cast< double >(298.257223563)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OAO_Other_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OAO_Other",SWIG_From_int(static_cast< int >(0)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OAO_North_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OAO_North",SWIG_From_int(static_cast< int >(1)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OAO_South_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OAO_South",SWIG_From_int(static_cast< int >(2)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OAO_East_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OAO_East",SWIG_From_int(static_cast< int >(3)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OAO_West_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OAO_West",SWIG_From_int(static_cast< int >(4)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OAO_Up_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OAO_Up",SWIG_From_int(static_cast< int >(5)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *OAO_Down_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *module;
+  PyObject *d;
+  if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
+  d = PyModule_GetDict(module);
+  if (!d) return NULL;
+  SWIG_Python_SetConstant(d, "OAO_Down",SWIG_From_int(static_cast< int >(6)));
+  return SWIG_Py_Void();
+}
+
+
+SWIGINTERN PyObject *_wrap_GetUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  int result;
+  
+  if (!PyArg_ParseTuple(args,(char *)":GetUseExceptions")) SWIG_fail;
+  result = (int)GetUseExceptions();
+  resultobj = SWIG_From_int(static_cast< int >(result));
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_UseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  
+  if (!PyArg_ParseTuple(args,(char *)":UseExceptions")) SWIG_fail;
+  UseExceptions();
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_DontUseExceptions(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  
+  if (!PyArg_ParseTuple(args,(char *)":DontUseExceptions")) SWIG_fail;
+  DontUseExceptions();
+  resultobj = SWIG_Py_Void();
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GetWellKnownGeogCSAsWKT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  char **arg2 = (char **) 0 ;
+  int res1 ;
+  char *buf1 = 0 ;
+  int alloc1 = 0 ;
+  char *argout2 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRErr result;
+  
+  {
+    /* %typemap(in,numinputs=0) (char **argout2) */
+    arg2 = &argout2;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"O:GetWellKnownGeogCSAsWKT",&obj0)) SWIG_fail;
+  res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetWellKnownGeogCSAsWKT" "', argument " "1"" of type '" "char const *""'");
+  }
+  arg1 = reinterpret_cast< char * >(buf1);
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)GetWellKnownGeogCSAsWKT((char const *)arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(argout) (char **argout) */
+    PyObject *o;
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
+      o = GDALPythonObjectFromCStr( *arg2 );
+    }
+    else {
+      o = Py_None;
+      Py_INCREF( o );
+    }
+    resultobj = t_output_helper(resultobj, o);
+  }
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* %typemap(freearg) (char **argout) */
+    if ( *arg2 )
+    CPLFree( *arg2 );
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* %typemap(freearg) (char **argout) */
+    if ( *arg2 )
+    CPLFree( *arg2 );
+  }
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_GetUserInputAsWKT(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  char *arg1 = (char *) 0 ;
+  char **arg2 = (char **) 0 ;
+  int res1 ;
+  char *buf1 = 0 ;
+  int alloc1 = 0 ;
+  char *argout2 = 0 ;
+  PyObject * obj0 = 0 ;
+  OGRErr result;
+  
+  {
+    /* %typemap(in,numinputs=0) (char **argout2) */
+    arg2 = &argout2;
+  }
+  if (!PyArg_ParseTuple(args,(char *)"O:GetUserInputAsWKT",&obj0)) SWIG_fail;
+  res1 = SWIG_AsCharPtrAndSize(obj0, &buf1, NULL, &alloc1);
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetUserInputAsWKT" "', argument " "1"" of type '" "char const *""'");
+  }
+  arg1 = reinterpret_cast< char * >(buf1);
+  {
+    if (!arg1) {
+      SWIG_exception(SWIG_ValueError,"Received a NULL pointer.");
+    }
+  }
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (OGRErr)GetUserInputAsWKT((char const *)arg1,arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  {
+    /* %typemap(out) OGRErr */
+    if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
+      PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
+      SWIG_fail;
+    }
+  }
+  {
+    /* %typemap(argout) (char **argout) */
+    PyObject *o;
+    if ( ReturnSame(arg2) != NULL && *arg2 != NULL ) {
+      o = GDALPythonObjectFromCStr( *arg2 );
+    }
+    else {
+      o = Py_None;
+      Py_INCREF( o );
+    }
+    resultobj = t_output_helper(resultobj, o);
+  }
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* %typemap(freearg) (char **argout) */
+    if ( *arg2 )
+    CPLFree( *arg2 );
+  }
+  {
+    /* %typemap(ret) OGRErr */
+    if ( ReturnSame(resultobj == Py_None || resultobj == 0) ) {
+      resultobj = PyInt_FromLong( result );
+    }
+  }
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
+  {
+    /* %typemap(freearg) (char **argout) */
     if ( *arg2 )
     CPLFree( *arg2 );
   }
@@ -4976,6 +7005,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAuthority(PyObject *SWIGUNUSEDPAR
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5117,6 +7150,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAttrValue(PyObject *SWIGUNUSEDPAR
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5193,6 +7230,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAngularUnits(PyObject *SWIGUNUSED
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5349,6 +7390,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTargetLinearUnits(PyObject *SWIGU
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5425,6 +7470,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLinearUnits(PyObject *SWIGUNUSEDP
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5499,6 +7548,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLinearUnitsAndUpdateParameters(Py
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5518,6 +7571,54 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_SpatialReference_GetTargetLinearUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
+  OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
+  char *arg2 = (char *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  int res2 ;
+  char *buf2 = 0 ;
+  int alloc2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  double result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:SpatialReference_GetTargetLinearUnits",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_OSRSpatialReferenceShadow, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SpatialReference_GetTargetLinearUnits" "', argument " "1"" of type '" "OSRSpatialReferenceShadow *""'"); 
+  }
+  arg1 = reinterpret_cast< OSRSpatialReferenceShadow * >(argp1);
+  res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "SpatialReference_GetTargetLinearUnits" "', argument " "2"" of type '" "char const *""'");
+  }
+  arg2 = reinterpret_cast< char * >(buf2);
+  {
+    if ( bUseExceptions ) {
+      CPLErrorReset();
+    }
+    result = (double)OSRSpatialReferenceShadow_GetTargetLinearUnits(arg1,(char const *)arg2);
+#ifndef SED_HACKS
+    if ( bUseExceptions ) {
+      CPLErr eclass = CPLGetLastErrorType();
+      if ( eclass == CE_Failure || eclass == CE_Fatal ) {
+        SWIG_exception( SWIG_RuntimeError, CPLGetLastErrorMsg() );
+      }
+    }
+#endif
+  }
+  resultobj = SWIG_From_double(static_cast< double >(result));
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  if ( ReturnSame(bLocalUseExceptionsCode) ) { CPLErr eclass = CPLGetLastErrorType(); if ( eclass == CE_Failure || eclass == CE_Fatal ) { Py_XDECREF(resultobj); SWIG_Error( SWIG_RuntimeError, CPLGetLastErrorMsg() ); return NULL; } }
+  return resultobj;
+fail:
+  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_SpatialReference_GetLinearUnits(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0; int bLocalUseExceptionsCode = bUseExceptions;
   OSRSpatialReferenceShadow *arg1 = (OSRSpatialReferenceShadow *) 0 ;
@@ -5851,6 +7952,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetUTM(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -5978,6 +8083,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetStatePlane(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -6028,6 +8137,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_AutoIdentifyEPSG(PyObject *SWIGUNUSE
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -6086,6 +8199,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetProjection(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -6160,6 +8277,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetProjParm(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -6298,6 +8419,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetNormProjParm(PyObject *SWIGUNUSED
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -6577,6 +8702,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetACEA(PyObject *SWIGUNUSEDPARM(sel
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -6664,6 +8793,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetAE(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -6751,6 +8884,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetBonne(PyObject *SWIGUNUSEDPARM(se
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -6838,6 +8975,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetCEA(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -6925,6 +9066,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetCS(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7030,6 +9175,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEC(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7108,6 +9257,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEckertIV(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7186,6 +9339,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEckertVI(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7273,6 +9430,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEquirectangular(PyObject *SWIGUNU
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7369,6 +9530,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetEquirectangular2(PyObject *SWIGUN
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7465,6 +9630,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGaussSchreiberTMercator(PyObject
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7543,6 +9712,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGS(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7621,6 +9794,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGH(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7669,6 +9846,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetIGH(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7756,6 +9937,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGEOS(PyObject *SWIGUNUSEDPARM(sel
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7843,6 +10028,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGnomonic(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -7957,6 +10146,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetHOM(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8080,6 +10273,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetHOM2PNO(PyObject *SWIGUNUSEDPARM(
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8194,6 +10391,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetKrovak(PyObject *SWIGUNUSEDPARM(s
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8281,6 +10482,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLAEA(PyObject *SWIGUNUSEDPARM(sel
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8386,6 +10591,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLCC(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8482,6 +10691,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLCC1SP(PyObject *SWIGUNUSEDPARM(s
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8587,6 +10800,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLCCB(PyObject *SWIGUNUSEDPARM(sel
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8674,6 +10891,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetMC(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8770,6 +10991,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetMercator(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8848,6 +11073,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetMollweide(PyObject *SWIGUNUSEDPAR
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -8935,6 +11164,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetNZMG(PyObject *SWIGUNUSEDPARM(sel
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9031,6 +11264,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetOS(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9118,6 +11355,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetOrthographic(PyObject *SWIGUNUSED
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9205,6 +11446,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetPolyconic(PyObject *SWIGUNUSEDPAR
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9301,6 +11546,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetPS(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9379,6 +11628,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetRobinson(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9457,6 +11710,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetSinusoidal(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9553,6 +11810,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetStereographic(PyObject *SWIGUNUSE
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9640,6 +11901,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetSOC(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9736,6 +12001,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTM(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9842,6 +12111,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTMVariant(PyObject *SWIGUNUSEDPAR
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -9931,6 +12204,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTMG(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10027,6 +12304,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTMSO(PyObject *SWIGUNUSEDPARM(sel
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10105,6 +12386,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetVDG(PyObject *SWIGUNUSEDPARM(self
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10168,6 +12453,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetWellKnownGeogCS(PyObject *SWIGUNU
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10233,6 +12522,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetFromUserInput(PyObject *SWIGUNUSE
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10297,6 +12590,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_CopyGeogCSFrom(PyObject *SWIGUNUSEDP
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10416,6 +12713,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetTOWGS84(PyObject *SWIGUNUSEDPARM(
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10471,6 +12772,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_GetTOWGS84(PyObject *SWIGUNUSEDPARM(
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10534,6 +12839,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetLocalCS(PyObject *SWIGUNUSEDPARM(
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10678,6 +12987,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGeogCS(PyObject *SWIGUNUSEDPARM(s
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10753,6 +13066,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetProjCS(PyObject *SWIGUNUSEDPARM(s
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10820,6 +13137,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetGeocCS(PyObject *SWIGUNUSEDPARM(s
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -10905,6 +13226,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetVertCS(PyObject *SWIGUNUSEDPARM(s
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11000,6 +13325,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_SetCompoundCS(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11061,6 +13390,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromWkt(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11119,6 +13452,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromProj4(PyObject *SWIGUNUSED
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11184,6 +13521,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUrl(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11284,6 +13625,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromESRI(PyObject *SWIGUNUSEDP
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11349,6 +13694,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromEPSG(PyObject *SWIGUNUSEDP
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11406,6 +13755,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromEPSGA(PyObject *SWIGUNUSED
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11505,6 +13858,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromPCI(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11617,6 +13974,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromUSGS(PyObject *SWIGUNUSEDP
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11675,6 +14036,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromXML(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11765,6 +14130,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromERM(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11829,6 +14198,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromMICoordSys(PyObject *SWIGU
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11934,6 +14307,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ImportFromOzi(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -11996,6 +14373,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToWkt(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12083,6 +14464,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPrettyWkt(PyObject *SWIGUNUS
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12159,6 +14544,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToProj4(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12248,6 +14637,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToPCI(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12372,6 +14765,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToUSGS(PyObject *SWIGUNUSEDPAR
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12469,6 +14866,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToXML(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12547,6 +14948,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_ExportToMICoordSys(PyObject *SWIGUNU
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12689,6 +15094,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_Validate(PyObject *SWIGUNUSEDPARM(se
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12737,6 +15146,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_StripCTParms(PyObject *SWIGUNUSEDPAR
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12785,6 +15198,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_FixupOrdering(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12833,6 +15250,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_Fixup(PyObject *SWIGUNUSEDPARM(self)
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12881,6 +15302,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_MorphToESRI(PyObject *SWIGUNUSEDPARM
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -12929,6 +15354,10 @@ SWIGINTERN PyObject *_wrap_SpatialReference_MorphFromESRI(PyObject *SWIGUNUSEDPA
   {
     /* %typemap(out) OGRErr */
     if ( result != 0 && bUseExceptions) {
+      const char* pszMessage = CPLGetLastErrorMsg();
+      if( pszMessage[0] != '\0' )
+      PyErr_SetString( PyExc_RuntimeError, pszMessage );
+      else
       PyErr_SetString( PyExc_RuntimeError, OGRErrMessages(result) );
       SWIG_fail;
     }
@@ -13177,12 +15606,14 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_CoordinateTransformation_TransformPoint(PyObject *self, PyObject *args) {
-  int argc;
-  PyObject *argv[5];
-  int ii;
+  Py_ssize_t argc;
+  PyObject *argv[5] = {
+    0
+  };
+  Py_ssize_t ii;
   
   if (args == NULL || !PyTuple_Check(args)) SWIG_fail;
-  argc = (int)PyObject_Length(args);
+  argc = args ? PyObject_Length(args) : 0;
   for (ii = 0; (ii < 4) && (ii < argc); ii++) {
     argv[ii] = PyTuple_GET_ITEM(args,ii);
   }
@@ -13385,13 +15816,186 @@ fail:
 
 static PyMethodDef SwigMethods[] = {
 	 { (char *)"SWIG_PyInstanceMethod_New", (PyCFunction)SWIG_PyInstanceMethod_New, METH_O, NULL},
+	 { (char *)"SRS_WKT_WGS84_swigconstant", SRS_WKT_WGS84_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_ALBERS_CONIC_EQUAL_AREA_swigconstant", SRS_PT_ALBERS_CONIC_EQUAL_AREA_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_AZIMUTHAL_EQUIDISTANT_swigconstant", SRS_PT_AZIMUTHAL_EQUIDISTANT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_CASSINI_SOLDNER_swigconstant", SRS_PT_CASSINI_SOLDNER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_CYLINDRICAL_EQUAL_AREA_swigconstant", SRS_PT_CYLINDRICAL_EQUAL_AREA_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_BONNE_swigconstant", SRS_PT_BONNE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_ECKERT_I_swigconstant", SRS_PT_ECKERT_I_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_ECKERT_II_swigconstant", SRS_PT_ECKERT_II_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_ECKERT_III_swigconstant", SRS_PT_ECKERT_III_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_ECKERT_IV_swigconstant", SRS_PT_ECKERT_IV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_ECKERT_V_swigconstant", SRS_PT_ECKERT_V_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_ECKERT_VI_swigconstant", SRS_PT_ECKERT_VI_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_EQUIDISTANT_CONIC_swigconstant", SRS_PT_EQUIDISTANT_CONIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_EQUIRECTANGULAR_swigconstant", SRS_PT_EQUIRECTANGULAR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_GALL_STEREOGRAPHIC_swigconstant", SRS_PT_GALL_STEREOGRAPHIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_GAUSSSCHREIBERTMERCATOR_swigconstant", SRS_PT_GAUSSSCHREIBERTMERCATOR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_GEOSTATIONARY_SATELLITE_swigconstant", SRS_PT_GEOSTATIONARY_SATELLITE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_GOODE_HOMOLOSINE_swigconstant", SRS_PT_GOODE_HOMOLOSINE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_IGH_swigconstant", SRS_PT_IGH_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_GNOMONIC_swigconstant", SRS_PT_GNOMONIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER_swigconstant", SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_HOTINE_OBLIQUE_MERCATOR_swigconstant", SRS_PT_HOTINE_OBLIQUE_MERCATOR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN_swigconstant", SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_LABORDE_OBLIQUE_MERCATOR_swigconstant", SRS_PT_LABORDE_OBLIQUE_MERCATOR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP_swigconstant", SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_swigconstant", SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM_swigconstant", SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA_swigconstant", SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_MERCATOR_1SP_swigconstant", SRS_PT_MERCATOR_1SP_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_MERCATOR_2SP_swigconstant", SRS_PT_MERCATOR_2SP_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_MERCATOR_AUXILIARY_SPHERE_swigconstant", SRS_PT_MERCATOR_AUXILIARY_SPHERE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_MILLER_CYLINDRICAL_swigconstant", SRS_PT_MILLER_CYLINDRICAL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_MOLLWEIDE_swigconstant", SRS_PT_MOLLWEIDE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_NEW_ZEALAND_MAP_GRID_swigconstant", SRS_PT_NEW_ZEALAND_MAP_GRID_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_OBLIQUE_STEREOGRAPHIC_swigconstant", SRS_PT_OBLIQUE_STEREOGRAPHIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_ORTHOGRAPHIC_swigconstant", SRS_PT_ORTHOGRAPHIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_POLAR_STEREOGRAPHIC_swigconstant", SRS_PT_POLAR_STEREOGRAPHIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_POLYCONIC_swigconstant", SRS_PT_POLYCONIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_ROBINSON_swigconstant", SRS_PT_ROBINSON_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_SINUSOIDAL_swigconstant", SRS_PT_SINUSOIDAL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_STEREOGRAPHIC_swigconstant", SRS_PT_STEREOGRAPHIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_SWISS_OBLIQUE_CYLINDRICAL_swigconstant", SRS_PT_SWISS_OBLIQUE_CYLINDRICAL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_TRANSVERSE_MERCATOR_swigconstant", SRS_PT_TRANSVERSE_MERCATOR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED_swigconstant", SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_TRANSVERSE_MERCATOR_MI_21_swigconstant", SRS_PT_TRANSVERSE_MERCATOR_MI_21_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_TRANSVERSE_MERCATOR_MI_22_swigconstant", SRS_PT_TRANSVERSE_MERCATOR_MI_22_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_TRANSVERSE_MERCATOR_MI_23_swigconstant", SRS_PT_TRANSVERSE_MERCATOR_MI_23_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_TRANSVERSE_MERCATOR_MI_24_swigconstant", SRS_PT_TRANSVERSE_MERCATOR_MI_24_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_TRANSVERSE_MERCATOR_MI_25_swigconstant", SRS_PT_TRANSVERSE_MERCATOR_MI_25_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_TUNISIA_MINING_GRID_swigconstant", SRS_PT_TUNISIA_MINING_GRID_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_TWO_POINT_EQUIDISTANT_swigconstant", SRS_PT_TWO_POINT_EQUIDISTANT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_VANDERGRINTEN_swigconstant", SRS_PT_VANDERGRINTEN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_KROVAK_swigconstant", SRS_PT_KROVAK_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_IMW_POLYCONIC_swigconstant", SRS_PT_IMW_POLYCONIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WAGNER_I_swigconstant", SRS_PT_WAGNER_I_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WAGNER_II_swigconstant", SRS_PT_WAGNER_II_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WAGNER_III_swigconstant", SRS_PT_WAGNER_III_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WAGNER_IV_swigconstant", SRS_PT_WAGNER_IV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WAGNER_V_swigconstant", SRS_PT_WAGNER_V_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WAGNER_VI_swigconstant", SRS_PT_WAGNER_VI_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WAGNER_VII_swigconstant", SRS_PT_WAGNER_VII_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_QSC_swigconstant", SRS_PT_QSC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_AITOFF_swigconstant", SRS_PT_AITOFF_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WINKEL_I_swigconstant", SRS_PT_WINKEL_I_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WINKEL_II_swigconstant", SRS_PT_WINKEL_II_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_WINKEL_TRIPEL_swigconstant", SRS_PT_WINKEL_TRIPEL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_CRASTER_PARABOLIC_swigconstant", SRS_PT_CRASTER_PARABOLIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_LOXIMUTHAL_swigconstant", SRS_PT_LOXIMUTHAL_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_QUARTIC_AUTHALIC_swigconstant", SRS_PT_QUARTIC_AUTHALIC_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PT_SCH_swigconstant", SRS_PT_SCH_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_CENTRAL_MERIDIAN_swigconstant", SRS_PP_CENTRAL_MERIDIAN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_SCALE_FACTOR_swigconstant", SRS_PP_SCALE_FACTOR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_STANDARD_PARALLEL_1_swigconstant", SRS_PP_STANDARD_PARALLEL_1_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_STANDARD_PARALLEL_2_swigconstant", SRS_PP_STANDARD_PARALLEL_2_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_PSEUDO_STD_PARALLEL_1_swigconstant", SRS_PP_PSEUDO_STD_PARALLEL_1_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LONGITUDE_OF_CENTER_swigconstant", SRS_PP_LONGITUDE_OF_CENTER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LATITUDE_OF_CENTER_swigconstant", SRS_PP_LATITUDE_OF_CENTER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LONGITUDE_OF_ORIGIN_swigconstant", SRS_PP_LONGITUDE_OF_ORIGIN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LATITUDE_OF_ORIGIN_swigconstant", SRS_PP_LATITUDE_OF_ORIGIN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_FALSE_EASTING_swigconstant", SRS_PP_FALSE_EASTING_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_FALSE_NORTHING_swigconstant", SRS_PP_FALSE_NORTHING_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_AZIMUTH_swigconstant", SRS_PP_AZIMUTH_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LONGITUDE_OF_POINT_1_swigconstant", SRS_PP_LONGITUDE_OF_POINT_1_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LATITUDE_OF_POINT_1_swigconstant", SRS_PP_LATITUDE_OF_POINT_1_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LONGITUDE_OF_POINT_2_swigconstant", SRS_PP_LONGITUDE_OF_POINT_2_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LATITUDE_OF_POINT_2_swigconstant", SRS_PP_LATITUDE_OF_POINT_2_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LONGITUDE_OF_POINT_3_swigconstant", SRS_PP_LONGITUDE_OF_POINT_3_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LATITUDE_OF_POINT_3_swigconstant", SRS_PP_LATITUDE_OF_POINT_3_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_RECTIFIED_GRID_ANGLE_swigconstant", SRS_PP_RECTIFIED_GRID_ANGLE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LANDSAT_NUMBER_swigconstant", SRS_PP_LANDSAT_NUMBER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_PATH_NUMBER_swigconstant", SRS_PP_PATH_NUMBER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_PERSPECTIVE_POINT_HEIGHT_swigconstant", SRS_PP_PERSPECTIVE_POINT_HEIGHT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_SATELLITE_HEIGHT_swigconstant", SRS_PP_SATELLITE_HEIGHT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_FIPSZONE_swigconstant", SRS_PP_FIPSZONE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_ZONE_swigconstant", SRS_PP_ZONE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LATITUDE_OF_1ST_POINT_swigconstant", SRS_PP_LATITUDE_OF_1ST_POINT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LONGITUDE_OF_1ST_POINT_swigconstant", SRS_PP_LONGITUDE_OF_1ST_POINT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LATITUDE_OF_2ND_POINT_swigconstant", SRS_PP_LATITUDE_OF_2ND_POINT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_LONGITUDE_OF_2ND_POINT_swigconstant", SRS_PP_LONGITUDE_OF_2ND_POINT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_PEG_POINT_LATITUDE_swigconstant", SRS_PP_PEG_POINT_LATITUDE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_PEG_POINT_LONGITUDE_swigconstant", SRS_PP_PEG_POINT_LONGITUDE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_PEG_POINT_HEADING_swigconstant", SRS_PP_PEG_POINT_HEADING_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PP_PEG_POINT_HEIGHT_swigconstant", SRS_PP_PEG_POINT_HEIGHT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_METER_swigconstant", SRS_UL_METER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_FOOT_swigconstant", SRS_UL_FOOT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_FOOT_CONV_swigconstant", SRS_UL_FOOT_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_FOOT_swigconstant", SRS_UL_US_FOOT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_FOOT_CONV_swigconstant", SRS_UL_US_FOOT_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_NAUTICAL_MILE_swigconstant", SRS_UL_NAUTICAL_MILE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_NAUTICAL_MILE_CONV_swigconstant", SRS_UL_NAUTICAL_MILE_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_LINK_swigconstant", SRS_UL_LINK_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_LINK_CONV_swigconstant", SRS_UL_LINK_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_CHAIN_swigconstant", SRS_UL_CHAIN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_CHAIN_CONV_swigconstant", SRS_UL_CHAIN_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_ROD_swigconstant", SRS_UL_ROD_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_ROD_CONV_swigconstant", SRS_UL_ROD_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_LINK_Clarke_swigconstant", SRS_UL_LINK_Clarke_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_LINK_Clarke_CONV_swigconstant", SRS_UL_LINK_Clarke_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_KILOMETER_swigconstant", SRS_UL_KILOMETER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_KILOMETER_CONV_swigconstant", SRS_UL_KILOMETER_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_DECIMETER_swigconstant", SRS_UL_DECIMETER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_DECIMETER_CONV_swigconstant", SRS_UL_DECIMETER_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_CENTIMETER_swigconstant", SRS_UL_CENTIMETER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_CENTIMETER_CONV_swigconstant", SRS_UL_CENTIMETER_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_MILLIMETER_swigconstant", SRS_UL_MILLIMETER_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_MILLIMETER_CONV_swigconstant", SRS_UL_MILLIMETER_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_NAUT_MILE_swigconstant", SRS_UL_INTL_NAUT_MILE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_NAUT_MILE_CONV_swigconstant", SRS_UL_INTL_NAUT_MILE_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_INCH_swigconstant", SRS_UL_INTL_INCH_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_INCH_CONV_swigconstant", SRS_UL_INTL_INCH_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_FOOT_swigconstant", SRS_UL_INTL_FOOT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_FOOT_CONV_swigconstant", SRS_UL_INTL_FOOT_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_YARD_swigconstant", SRS_UL_INTL_YARD_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_YARD_CONV_swigconstant", SRS_UL_INTL_YARD_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_STAT_MILE_swigconstant", SRS_UL_INTL_STAT_MILE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_STAT_MILE_CONV_swigconstant", SRS_UL_INTL_STAT_MILE_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_FATHOM_swigconstant", SRS_UL_INTL_FATHOM_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_FATHOM_CONV_swigconstant", SRS_UL_INTL_FATHOM_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_CHAIN_swigconstant", SRS_UL_INTL_CHAIN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_CHAIN_CONV_swigconstant", SRS_UL_INTL_CHAIN_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_LINK_swigconstant", SRS_UL_INTL_LINK_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INTL_LINK_CONV_swigconstant", SRS_UL_INTL_LINK_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_INCH_swigconstant", SRS_UL_US_INCH_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_INCH_CONV_swigconstant", SRS_UL_US_INCH_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_YARD_swigconstant", SRS_UL_US_YARD_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_YARD_CONV_swigconstant", SRS_UL_US_YARD_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_CHAIN_swigconstant", SRS_UL_US_CHAIN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_CHAIN_CONV_swigconstant", SRS_UL_US_CHAIN_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_STAT_MILE_swigconstant", SRS_UL_US_STAT_MILE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_US_STAT_MILE_CONV_swigconstant", SRS_UL_US_STAT_MILE_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INDIAN_YARD_swigconstant", SRS_UL_INDIAN_YARD_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INDIAN_YARD_CONV_swigconstant", SRS_UL_INDIAN_YARD_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INDIAN_FOOT_swigconstant", SRS_UL_INDIAN_FOOT_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INDIAN_FOOT_CONV_swigconstant", SRS_UL_INDIAN_FOOT_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INDIAN_CHAIN_swigconstant", SRS_UL_INDIAN_CHAIN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UL_INDIAN_CHAIN_CONV_swigconstant", SRS_UL_INDIAN_CHAIN_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UA_DEGREE_swigconstant", SRS_UA_DEGREE_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UA_DEGREE_CONV_swigconstant", SRS_UA_DEGREE_CONV_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_UA_RADIAN_swigconstant", SRS_UA_RADIAN_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_PM_GREENWICH_swigconstant", SRS_PM_GREENWICH_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_DN_NAD27_swigconstant", SRS_DN_NAD27_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_DN_NAD83_swigconstant", SRS_DN_NAD83_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_DN_WGS72_swigconstant", SRS_DN_WGS72_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_DN_WGS84_swigconstant", SRS_DN_WGS84_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_WGS84_SEMIMAJOR_swigconstant", SRS_WGS84_SEMIMAJOR_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"SRS_WGS84_INVFLATTENING_swigconstant", SRS_WGS84_INVFLATTENING_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OAO_Other_swigconstant", OAO_Other_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OAO_North_swigconstant", OAO_North_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OAO_South_swigconstant", OAO_South_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OAO_East_swigconstant", OAO_East_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OAO_West_swigconstant", OAO_West_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OAO_Up_swigconstant", OAO_Up_swigconstant, METH_VARARGS, NULL},
+	 { (char *)"OAO_Down_swigconstant", OAO_Down_swigconstant, METH_VARARGS, NULL},
 	 { (char *)"GetUseExceptions", _wrap_GetUseExceptions, METH_VARARGS, (char *)"GetUseExceptions() -> int"},
 	 { (char *)"UseExceptions", _wrap_UseExceptions, METH_VARARGS, (char *)"UseExceptions()"},
 	 { (char *)"DontUseExceptions", _wrap_DontUseExceptions, METH_VARARGS, (char *)"DontUseExceptions()"},
 	 { (char *)"GetProjectionMethods", py_OPTGetProjectionMethods, METH_VARARGS, NULL},
 	 { (char *)"GetWellKnownGeogCSAsWKT", _wrap_GetWellKnownGeogCSAsWKT, METH_VARARGS, (char *)"GetWellKnownGeogCSAsWKT(char const * name) -> OGRErr"},
 	 { (char *)"GetUserInputAsWKT", _wrap_GetUserInputAsWKT, METH_VARARGS, (char *)"GetUserInputAsWKT(char const * name) -> OGRErr"},
-	 { (char *)"new_SpatialReference", (PyCFunction) _wrap_new_SpatialReference, METH_VARARGS | METH_KEYWORDS, (char *)"new_SpatialReference(char const * wkt=\"\") -> SpatialReference"},
+	 { (char *)"new_SpatialReference", (PyCFunction) _wrap_new_SpatialReference, METH_VARARGS | METH_KEYWORDS, (char *)"new_SpatialReference(char const * wkt) -> SpatialReference"},
 	 { (char *)"delete_SpatialReference", _wrap_delete_SpatialReference, METH_VARARGS, (char *)"delete_SpatialReference(SpatialReference self)"},
 	 { (char *)"SpatialReference___str__", _wrap_SpatialReference___str__, METH_VARARGS, (char *)"SpatialReference___str__(SpatialReference self) -> retStringAndCPLFree *"},
 	 { (char *)"SpatialReference_IsSame", _wrap_SpatialReference_IsSame, METH_VARARGS, (char *)"SpatialReference_IsSame(SpatialReference self, SpatialReference rhs) -> int"},
@@ -13414,6 +16018,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference_SetTargetLinearUnits", _wrap_SpatialReference_SetTargetLinearUnits, METH_VARARGS, (char *)"SpatialReference_SetTargetLinearUnits(SpatialReference self, char const * target, char const * name, double to_meters) -> OGRErr"},
 	 { (char *)"SpatialReference_SetLinearUnits", _wrap_SpatialReference_SetLinearUnits, METH_VARARGS, (char *)"SpatialReference_SetLinearUnits(SpatialReference self, char const * name, double to_meters) -> OGRErr"},
 	 { (char *)"SpatialReference_SetLinearUnitsAndUpdateParameters", _wrap_SpatialReference_SetLinearUnitsAndUpdateParameters, METH_VARARGS, (char *)"SpatialReference_SetLinearUnitsAndUpdateParameters(SpatialReference self, char const * name, double to_meters) -> OGRErr"},
+	 { (char *)"SpatialReference_GetTargetLinearUnits", _wrap_SpatialReference_GetTargetLinearUnits, METH_VARARGS, (char *)"SpatialReference_GetTargetLinearUnits(SpatialReference self, char const * target_key) -> double"},
 	 { (char *)"SpatialReference_GetLinearUnits", _wrap_SpatialReference_GetLinearUnits, METH_VARARGS, (char *)"SpatialReference_GetLinearUnits(SpatialReference self) -> double"},
 	 { (char *)"SpatialReference_GetLinearUnitsName", _wrap_SpatialReference_GetLinearUnitsName, METH_VARARGS, (char *)"SpatialReference_GetLinearUnitsName(SpatialReference self) -> char const *"},
 	 { (char *)"SpatialReference_GetAuthorityCode", _wrap_SpatialReference_GetAuthorityCode, METH_VARARGS, (char *)"SpatialReference_GetAuthorityCode(SpatialReference self, char const * target_key) -> char const *"},
@@ -13422,7 +16027,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference_GetAxisOrientation", _wrap_SpatialReference_GetAxisOrientation, METH_VARARGS, (char *)"SpatialReference_GetAxisOrientation(SpatialReference self, char const * target_key, int iAxis) -> OGRAxisOrientation"},
 	 { (char *)"SpatialReference_SetUTM", _wrap_SpatialReference_SetUTM, METH_VARARGS, (char *)"SpatialReference_SetUTM(SpatialReference self, int zone, int north=1) -> OGRErr"},
 	 { (char *)"SpatialReference_GetUTMZone", _wrap_SpatialReference_GetUTMZone, METH_VARARGS, (char *)"SpatialReference_GetUTMZone(SpatialReference self) -> int"},
-	 { (char *)"SpatialReference_SetStatePlane", _wrap_SpatialReference_SetStatePlane, METH_VARARGS, (char *)"SpatialReference_SetStatePlane(SpatialReference self, int zone, int is_nad83=1, char const * unitsname=\"\", double units=0.0) -> OGRErr"},
+	 { (char *)"SpatialReference_SetStatePlane", _wrap_SpatialReference_SetStatePlane, METH_VARARGS, (char *)"SpatialReference_SetStatePlane(SpatialReference self, int zone, int is_nad83=1, char const * unitsname, double units=0.0) -> OGRErr"},
 	 { (char *)"SpatialReference_AutoIdentifyEPSG", _wrap_SpatialReference_AutoIdentifyEPSG, METH_VARARGS, (char *)"SpatialReference_AutoIdentifyEPSG(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_SetProjection", _wrap_SpatialReference_SetProjection, METH_VARARGS, (char *)"SpatialReference_SetProjection(SpatialReference self, char const * arg) -> OGRErr"},
 	 { (char *)"SpatialReference_SetProjParm", _wrap_SpatialReference_SetProjParm, METH_VARARGS, (char *)"SpatialReference_SetProjParm(SpatialReference self, char const * name, double val) -> OGRErr"},
@@ -13432,61 +16037,34 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference_GetSemiMajor", _wrap_SpatialReference_GetSemiMajor, METH_VARARGS, (char *)"SpatialReference_GetSemiMajor(SpatialReference self) -> double"},
 	 { (char *)"SpatialReference_GetSemiMinor", _wrap_SpatialReference_GetSemiMinor, METH_VARARGS, (char *)"SpatialReference_GetSemiMinor(SpatialReference self) -> double"},
 	 { (char *)"SpatialReference_GetInvFlattening", _wrap_SpatialReference_GetInvFlattening, METH_VARARGS, (char *)"SpatialReference_GetInvFlattening(SpatialReference self) -> double"},
-	 { (char *)"SpatialReference_SetACEA", (PyCFunction) _wrap_SpatialReference_SetACEA, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetACEA(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetACEA", (PyCFunction) _wrap_SpatialReference_SetACEA, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetACEA(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetAE", (PyCFunction) _wrap_SpatialReference_SetAE, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetAE(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetBonne", (PyCFunction) _wrap_SpatialReference_SetBonne, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetBonne(SpatialReference self, double stdp, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetCEA", (PyCFunction) _wrap_SpatialReference_SetCEA, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetCEA(SpatialReference self, double stdp1, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetCS", (PyCFunction) _wrap_SpatialReference_SetCS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetCS(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetEC", (PyCFunction) _wrap_SpatialReference_SetEC, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetEC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetEC", (PyCFunction) _wrap_SpatialReference_SetEC, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetEC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetEckertIV", (PyCFunction) _wrap_SpatialReference_SetEckertIV, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetEckertIV(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetEckertVI", (PyCFunction) _wrap_SpatialReference_SetEckertVI, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetEckertVI(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetEquirectangular", (PyCFunction) _wrap_SpatialReference_SetEquirectangular, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetEquirectangular(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetEquirectangular2", (PyCFunction) _wrap_SpatialReference_SetEquirectangular2, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetEquirectangular2(SpatialReference self, double clat, double clong, double pseudostdparallellat, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetEquirectangular2", (PyCFunction) _wrap_SpatialReference_SetEquirectangular2, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetEquirectangular2(SpatialReference self, double clat, double clong, double pseudostdparallellat, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGaussSchreiberTMercator", (PyCFunction) _wrap_SpatialReference_SetGaussSchreiberTMercator, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGaussSchreiberTMercator(SpatialReference self, double clat, double clong, double sc, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGS", (PyCFunction) _wrap_SpatialReference_SetGS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGS(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGH", (PyCFunction) _wrap_SpatialReference_SetGH, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGH(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetIGH", _wrap_SpatialReference_SetIGH, METH_VARARGS, (char *)"SpatialReference_SetIGH(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGEOS", (PyCFunction) _wrap_SpatialReference_SetGEOS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGEOS(SpatialReference self, double cm, double satelliteheight, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetGnomonic", (PyCFunction) _wrap_SpatialReference_SetGnomonic, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetGnomonic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetHOM", (PyCFunction) _wrap_SpatialReference_SetHOM, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetHOM(SpatialReference self, double clat, double clong, double azimuth, double recttoskew, \n"
-		"    double scale, double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetHOM2PNO", (PyCFunction) _wrap_SpatialReference_SetHOM2PNO, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetHOM2PNO(SpatialReference self, double clat, double dfLat1, double dfLong1, double dfLat2, \n"
-		"    double dfLong2, double scale, double fe, double fn) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetKrovak", (PyCFunction) _wrap_SpatialReference_SetKrovak, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetKrovak(SpatialReference self, double clat, double clong, double azimuth, double pseudostdparallellat, \n"
-		"    double scale, double fe, double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetHOM", (PyCFunction) _wrap_SpatialReference_SetHOM, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetHOM(SpatialReference self, double clat, double clong, double azimuth, double recttoskew, double scale, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetHOM2PNO", (PyCFunction) _wrap_SpatialReference_SetHOM2PNO, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetHOM2PNO(SpatialReference self, double clat, double dfLat1, double dfLong1, double dfLat2, double dfLong2, double scale, double fe, double fn) -> OGRErr"},
+	 { (char *)"SpatialReference_SetKrovak", (PyCFunction) _wrap_SpatialReference_SetKrovak, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetKrovak(SpatialReference self, double clat, double clong, double azimuth, double pseudostdparallellat, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetLAEA", (PyCFunction) _wrap_SpatialReference_SetLAEA, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetLAEA(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetLCC", (PyCFunction) _wrap_SpatialReference_SetLCC, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetLCC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetLCC", (PyCFunction) _wrap_SpatialReference_SetLCC, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetLCC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetLCC1SP", (PyCFunction) _wrap_SpatialReference_SetLCC1SP, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetLCC1SP(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetLCCB", (PyCFunction) _wrap_SpatialReference_SetLCCB, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetLCCB(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetLCCB", (PyCFunction) _wrap_SpatialReference_SetLCCB, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetLCCB(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetMC", (PyCFunction) _wrap_SpatialReference_SetMC, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetMC(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetMercator", (PyCFunction) _wrap_SpatialReference_SetMercator, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetMercator(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetMollweide", (PyCFunction) _wrap_SpatialReference_SetMollweide, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetMollweide(SpatialReference self, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetNZMG", (PyCFunction) _wrap_SpatialReference_SetNZMG, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetNZMG(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetOS", (PyCFunction) _wrap_SpatialReference_SetOS, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetOS(SpatialReference self, double dfOriginLat, double dfCMeridian, double scale, double fe, \n"
-		"    double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetOS", (PyCFunction) _wrap_SpatialReference_SetOS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetOS(SpatialReference self, double dfOriginLat, double dfCMeridian, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetOrthographic", (PyCFunction) _wrap_SpatialReference_SetOrthographic, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetOrthographic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetPolyconic", (PyCFunction) _wrap_SpatialReference_SetPolyconic, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetPolyconic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetPS", (PyCFunction) _wrap_SpatialReference_SetPS, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetPS(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
@@ -13495,34 +16073,20 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference_SetStereographic", (PyCFunction) _wrap_SpatialReference_SetStereographic, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetStereographic(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetSOC", (PyCFunction) _wrap_SpatialReference_SetSOC, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetSOC(SpatialReference self, double latitudeoforigin, double cm, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetTM", (PyCFunction) _wrap_SpatialReference_SetTM, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetTM(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
-	 { (char *)"SpatialReference_SetTMVariant", (PyCFunction) _wrap_SpatialReference_SetTMVariant, METH_VARARGS | METH_KEYWORDS, (char *)"\n"
-		"SpatialReference_SetTMVariant(SpatialReference self, char const * pszVariantName, double clat, double clong, double scale, \n"
-		"    double fe, double fn) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetTMVariant", (PyCFunction) _wrap_SpatialReference_SetTMVariant, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetTMVariant(SpatialReference self, char const * pszVariantName, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetTMG", (PyCFunction) _wrap_SpatialReference_SetTMG, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetTMG(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetTMSO", (PyCFunction) _wrap_SpatialReference_SetTMSO, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetTMSO(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetVDG", (PyCFunction) _wrap_SpatialReference_SetVDG, METH_VARARGS | METH_KEYWORDS, (char *)"SpatialReference_SetVDG(SpatialReference self, double clong, double fe, double fn) -> OGRErr"},
 	 { (char *)"SpatialReference_SetWellKnownGeogCS", _wrap_SpatialReference_SetWellKnownGeogCS, METH_VARARGS, (char *)"SpatialReference_SetWellKnownGeogCS(SpatialReference self, char const * name) -> OGRErr"},
 	 { (char *)"SpatialReference_SetFromUserInput", _wrap_SpatialReference_SetFromUserInput, METH_VARARGS, (char *)"SpatialReference_SetFromUserInput(SpatialReference self, char const * name) -> OGRErr"},
 	 { (char *)"SpatialReference_CopyGeogCSFrom", _wrap_SpatialReference_CopyGeogCSFrom, METH_VARARGS, (char *)"SpatialReference_CopyGeogCSFrom(SpatialReference self, SpatialReference rhs) -> OGRErr"},
-	 { (char *)"SpatialReference_SetTOWGS84", _wrap_SpatialReference_SetTOWGS84, METH_VARARGS, (char *)"\n"
-		"SpatialReference_SetTOWGS84(SpatialReference self, double p1, double p2, double p3, double p4=0.0, double p5=0.0, \n"
-		"    double p6=0.0, double p7=0.0) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetTOWGS84", _wrap_SpatialReference_SetTOWGS84, METH_VARARGS, (char *)"SpatialReference_SetTOWGS84(SpatialReference self, double p1, double p2, double p3, double p4=0.0, double p5=0.0, double p6=0.0, double p7=0.0) -> OGRErr"},
 	 { (char *)"SpatialReference_GetTOWGS84", _wrap_SpatialReference_GetTOWGS84, METH_VARARGS, (char *)"SpatialReference_GetTOWGS84(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_SetLocalCS", _wrap_SpatialReference_SetLocalCS, METH_VARARGS, (char *)"SpatialReference_SetLocalCS(SpatialReference self, char const * pszName) -> OGRErr"},
-	 { (char *)"SpatialReference_SetGeogCS", _wrap_SpatialReference_SetGeogCS, METH_VARARGS, (char *)"\n"
-		"SpatialReference_SetGeogCS(SpatialReference self, char const * pszGeogName, char const * pszDatumName, char const * pszEllipsoidName, \n"
-		"    double dfSemiMajor, double dfInvFlattening, char const * pszPMName=\"Greenwich\", \n"
-		"    double dfPMOffset=0.0, char const * pszUnits=\"degree\", \n"
-		"    double dfConvertToRadians=0.0174532925199433) -> OGRErr\n"
-		""},
-	 { (char *)"SpatialReference_SetProjCS", _wrap_SpatialReference_SetProjCS, METH_VARARGS, (char *)"SpatialReference_SetProjCS(SpatialReference self, char const * name=\"unnamed\") -> OGRErr"},
-	 { (char *)"SpatialReference_SetGeocCS", _wrap_SpatialReference_SetGeocCS, METH_VARARGS, (char *)"SpatialReference_SetGeocCS(SpatialReference self, char const * name=\"unnamed\") -> OGRErr"},
-	 { (char *)"SpatialReference_SetVertCS", _wrap_SpatialReference_SetVertCS, METH_VARARGS, (char *)"\n"
-		"SpatialReference_SetVertCS(SpatialReference self, char const * VertCSName=\"unnamed\", char const * VertDatumName=\"unnamed\", \n"
-		"    int VertDatumType=0) -> OGRErr\n"
-		""},
+	 { (char *)"SpatialReference_SetGeogCS", _wrap_SpatialReference_SetGeogCS, METH_VARARGS, (char *)"SpatialReference_SetGeogCS(SpatialReference self, char const * pszGeogName, char const * pszDatumName, char const * pszEllipsoidName, double dfSemiMajor, double dfInvFlattening, char const * pszPMName, double dfPMOffset=0.0, char const * pszUnits, double dfConvertToRadians=0.0174532925199433) -> OGRErr"},
+	 { (char *)"SpatialReference_SetProjCS", _wrap_SpatialReference_SetProjCS, METH_VARARGS, (char *)"SpatialReference_SetProjCS(SpatialReference self, char const * name) -> OGRErr"},
+	 { (char *)"SpatialReference_SetGeocCS", _wrap_SpatialReference_SetGeocCS, METH_VARARGS, (char *)"SpatialReference_SetGeocCS(SpatialReference self, char const * name) -> OGRErr"},
+	 { (char *)"SpatialReference_SetVertCS", _wrap_SpatialReference_SetVertCS, METH_VARARGS, (char *)"SpatialReference_SetVertCS(SpatialReference self, char const * VertCSName, char const * VertDatumName, int VertDatumType=0) -> OGRErr"},
 	 { (char *)"SpatialReference_SetCompoundCS", _wrap_SpatialReference_SetCompoundCS, METH_VARARGS, (char *)"SpatialReference_SetCompoundCS(SpatialReference self, char const * name, SpatialReference horizcs, SpatialReference vertcs) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromWkt", _wrap_SpatialReference_ImportFromWkt, METH_VARARGS, (char *)"SpatialReference_ImportFromWkt(SpatialReference self, char ** ppszInput) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromProj4", _wrap_SpatialReference_ImportFromProj4, METH_VARARGS, (char *)"SpatialReference_ImportFromProj4(SpatialReference self, char * ppszInput) -> OGRErr"},
@@ -13530,7 +16094,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference_ImportFromESRI", _wrap_SpatialReference_ImportFromESRI, METH_VARARGS, (char *)"SpatialReference_ImportFromESRI(SpatialReference self, char ** ppszInput) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromEPSG", _wrap_SpatialReference_ImportFromEPSG, METH_VARARGS, (char *)"SpatialReference_ImportFromEPSG(SpatialReference self, int arg) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromEPSGA", _wrap_SpatialReference_ImportFromEPSGA, METH_VARARGS, (char *)"SpatialReference_ImportFromEPSGA(SpatialReference self, int arg) -> OGRErr"},
-	 { (char *)"SpatialReference_ImportFromPCI", _wrap_SpatialReference_ImportFromPCI, METH_VARARGS, (char *)"SpatialReference_ImportFromPCI(SpatialReference self, char const * proj, char const * units=\"METRE\", double [17] argin=0) -> OGRErr"},
+	 { (char *)"SpatialReference_ImportFromPCI", _wrap_SpatialReference_ImportFromPCI, METH_VARARGS, (char *)"SpatialReference_ImportFromPCI(SpatialReference self, char const * proj, char const * units, double [17] argin=0) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromUSGS", _wrap_SpatialReference_ImportFromUSGS, METH_VARARGS, (char *)"SpatialReference_ImportFromUSGS(SpatialReference self, long proj_code, long zone=0, double [15] argin=0, long datum_code=0) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromXML", _wrap_SpatialReference_ImportFromXML, METH_VARARGS, (char *)"SpatialReference_ImportFromXML(SpatialReference self, char const * xmlString) -> OGRErr"},
 	 { (char *)"SpatialReference_ImportFromERM", _wrap_SpatialReference_ImportFromERM, METH_VARARGS, (char *)"SpatialReference_ImportFromERM(SpatialReference self, char const * proj, char const * datum, char const * units) -> OGRErr"},
@@ -13541,7 +16105,7 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"SpatialReference_ExportToProj4", _wrap_SpatialReference_ExportToProj4, METH_VARARGS, (char *)"SpatialReference_ExportToProj4(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_ExportToPCI", _wrap_SpatialReference_ExportToPCI, METH_VARARGS, (char *)"SpatialReference_ExportToPCI(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_ExportToUSGS", _wrap_SpatialReference_ExportToUSGS, METH_VARARGS, (char *)"SpatialReference_ExportToUSGS(SpatialReference self) -> OGRErr"},
-	 { (char *)"SpatialReference_ExportToXML", _wrap_SpatialReference_ExportToXML, METH_VARARGS, (char *)"SpatialReference_ExportToXML(SpatialReference self, char const * dialect=\"\") -> OGRErr"},
+	 { (char *)"SpatialReference_ExportToXML", _wrap_SpatialReference_ExportToXML, METH_VARARGS, (char *)"SpatialReference_ExportToXML(SpatialReference self, char const * dialect) -> OGRErr"},
 	 { (char *)"SpatialReference_ExportToMICoordSys", _wrap_SpatialReference_ExportToMICoordSys, METH_VARARGS, (char *)"SpatialReference_ExportToMICoordSys(SpatialReference self) -> OGRErr"},
 	 { (char *)"SpatialReference_CloneGeogCS", _wrap_SpatialReference_CloneGeogCS, METH_VARARGS, (char *)"SpatialReference_CloneGeogCS(SpatialReference self) -> SpatialReference"},
 	 { (char *)"SpatialReference_Clone", _wrap_SpatialReference_Clone, METH_VARARGS, (char *)"SpatialReference_Clone(SpatialReference self) -> SpatialReference"},
@@ -13629,7 +16193,7 @@ static swig_const_info swig_const_table[] = {
  * array with the correct data and linking the correct swig_cast_info
  * structures together.
  *
- * The generated swig_type_info structures are assigned staticly to an initial
+ * The generated swig_type_info structures are assigned statically to an initial
  * array. We just loop through that array, and handle each type individually.
  * First we lookup if this type has been already loaded, and if so, use the
  * loaded structure instead of the generated one. Then we have to fill in the
@@ -13673,7 +16237,7 @@ SWIGRUNTIME void
 SWIG_InitializeModule(void *clientdata) {
   size_t i;
   swig_module_info *module_head, *iter;
-  int found, init;
+  int init;
   
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
@@ -13692,22 +16256,18 @@ SWIG_InitializeModule(void *clientdata) {
     /* This is the first module loaded for this interpreter */
     /* so set the swig module into the interpreter */
     SWIG_SetModule(clientdata, &swig_module);
-    /*module_head = &swig_module;*/
   } else {
     /* the interpreter has loaded a SWIG module, but has it loaded this one? */
-    found=0;
     iter=module_head;
     do {
       if (iter==&swig_module) {
-        found=1;
-        break;
+        /* Our module is already in the list, so there's nothing more to do. */
+        return;
       }
       iter=iter->next;
     } while (iter!= module_head);
     
-    /* if the is found in the list, then all is done and we may leave */
-    if (found) return;
-    /* otherwise we must add out module into the list */
+    /* otherwise we must add our module into the list */
     swig_module.next = module_head->next;
     module_head->next = &swig_module;
   }
@@ -13959,7 +16519,7 @@ extern "C" {
       var = var->next;
     }
     if (res == NULL && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -13976,7 +16536,7 @@ extern "C" {
       var = var->next;
     }
     if (res == 1 && !PyErr_Occurred()) {
-      PyErr_SetString(PyExc_NameError,"Unknown C global variable");
+      PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n);
     }
     return res;
   }
@@ -14026,10 +16586,19 @@ extern "C" {
         0,                                  /* tp_del */
 #endif
 #if PY_VERSION_HEX >= 0x02060000
-        0,                                  /* tp_version */
+        0,                                  /* tp_version_tag */
+#endif
+#if PY_VERSION_HEX >= 0x03040000
+        0,                                  /* tp_finalize */
 #endif
 #ifdef COUNT_ALLOCS
-        0,0,0,0                             /* tp_alloc -> tp_next */
+        0,                                  /* tp_allocs */
+        0,                                  /* tp_frees */
+        0,                                  /* tp_maxalloc */
+#if PY_VERSION_HEX >= 0x02050000
+        0,                                  /* tp_prev */
+#endif
+        0                                   /* tp_next */
 #endif
       };
       varlink_type = tmp;
@@ -14118,7 +16687,9 @@ extern "C" {
     size_t i;
     for (i = 0; methods[i].ml_name; ++i) {
       const char *c = methods[i].ml_doc;
-      if (c && (c = strstr(c, "swig_ptr: "))) {
+      if (!c) continue;
+      c = strstr(c, "swig_ptr: ");
+      if (c) {
         int j;
         swig_const_info *ci = 0;
         const char *name = c + 10;
@@ -14220,6 +16791,7 @@ SWIG_init(void) {
   PyObject *public_interface, *public_symbol;
   PyObject *this_descr;
   PyObject *thisown_descr;
+  PyObject *self = 0;
   int i;
   
   (void)builtin_pytype;
@@ -14227,6 +16799,7 @@ SWIG_init(void) {
   (void)builtin_basetype;
   (void)tuple;
   (void)static_getset;
+  (void)self;
   
   /* metatype is used to implement static member variables. */
   metatype_args = Py_BuildValue("(s(O){})", "SwigPyObjectType", &PyType_Type);
@@ -14246,6 +16819,7 @@ SWIG_init(void) {
 #else
   m = Py_InitModule((char *) SWIG_name, SwigMethods);
 #endif
+  
   md = d = PyModule_GetDict(m);
   (void)md;
   
@@ -14289,179 +16863,9 @@ SWIG_init(void) {
   
   SWIG_InstallConstants(d,swig_const_table);
   
-  SWIG_Python_SetConstant(d, "SRS_WKT_WGS84",SWIG_FromCharPtr("GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]"));
-  SWIG_Python_SetConstant(d, "SRS_PT_ALBERS_CONIC_EQUAL_AREA",SWIG_FromCharPtr("Albers_Conic_Equal_Area"));
-  SWIG_Python_SetConstant(d, "SRS_PT_AZIMUTHAL_EQUIDISTANT",SWIG_FromCharPtr("Azimuthal_Equidistant"));
-  SWIG_Python_SetConstant(d, "SRS_PT_CASSINI_SOLDNER",SWIG_FromCharPtr("Cassini_Soldner"));
-  SWIG_Python_SetConstant(d, "SRS_PT_CYLINDRICAL_EQUAL_AREA",SWIG_FromCharPtr("Cylindrical_Equal_Area"));
-  SWIG_Python_SetConstant(d, "SRS_PT_BONNE",SWIG_FromCharPtr("Bonne"));
-  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_I",SWIG_FromCharPtr("Eckert_I"));
-  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_II",SWIG_FromCharPtr("Eckert_II"));
-  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_III",SWIG_FromCharPtr("Eckert_III"));
-  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_IV",SWIG_FromCharPtr("Eckert_IV"));
-  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_V",SWIG_FromCharPtr("Eckert_V"));
-  SWIG_Python_SetConstant(d, "SRS_PT_ECKERT_VI",SWIG_FromCharPtr("Eckert_VI"));
-  SWIG_Python_SetConstant(d, "SRS_PT_EQUIDISTANT_CONIC",SWIG_FromCharPtr("Equidistant_Conic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_EQUIRECTANGULAR",SWIG_FromCharPtr("Equirectangular"));
-  SWIG_Python_SetConstant(d, "SRS_PT_GALL_STEREOGRAPHIC",SWIG_FromCharPtr("Gall_Stereographic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_GAUSSSCHREIBERTMERCATOR",SWIG_FromCharPtr("Gauss_Schreiber_Transverse_Mercator"));
-  SWIG_Python_SetConstant(d, "SRS_PT_GEOSTATIONARY_SATELLITE",SWIG_FromCharPtr("Geostationary_Satellite"));
-  SWIG_Python_SetConstant(d, "SRS_PT_GOODE_HOMOLOSINE",SWIG_FromCharPtr("Goode_Homolosine"));
-  SWIG_Python_SetConstant(d, "SRS_PT_IGH",SWIG_FromCharPtr("Interrupted_Goode_Homolosine"));
-  SWIG_Python_SetConstant(d, "SRS_PT_GNOMONIC",SWIG_FromCharPtr("Gnomonic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER",SWIG_FromCharPtr("Hotine_Oblique_Mercator_Azimuth_Center"));
-  SWIG_Python_SetConstant(d, "SRS_PT_HOTINE_OBLIQUE_MERCATOR",SWIG_FromCharPtr("Hotine_Oblique_Mercator"));
-  SWIG_Python_SetConstant(d, "SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN",SWIG_FromCharPtr("Hotine_Oblique_Mercator_Two_Point_Natural_Origin"));
-  SWIG_Python_SetConstant(d, "SRS_PT_LABORDE_OBLIQUE_MERCATOR",SWIG_FromCharPtr("Laborde_Oblique_Mercator"));
-  SWIG_Python_SetConstant(d, "SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP",SWIG_FromCharPtr("Lambert_Conformal_Conic_1SP"));
-  SWIG_Python_SetConstant(d, "SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP",SWIG_FromCharPtr("Lambert_Conformal_Conic_2SP"));
-  SWIG_Python_SetConstant(d, "SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM",SWIG_FromCharPtr("Lambert_Conformal_Conic_2SP_Belgium"));
-  SWIG_Python_SetConstant(d, "SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA",SWIG_FromCharPtr("Lambert_Azimuthal_Equal_Area"));
-  SWIG_Python_SetConstant(d, "SRS_PT_MERCATOR_1SP",SWIG_FromCharPtr("Mercator_1SP"));
-  SWIG_Python_SetConstant(d, "SRS_PT_MERCATOR_2SP",SWIG_FromCharPtr("Mercator_2SP"));
-  SWIG_Python_SetConstant(d, "SRS_PT_MERCATOR_AUXILIARY_SPHERE",SWIG_FromCharPtr("Mercator_Auxiliary_Sphere"));
-  SWIG_Python_SetConstant(d, "SRS_PT_MILLER_CYLINDRICAL",SWIG_FromCharPtr("Miller_Cylindrical"));
-  SWIG_Python_SetConstant(d, "SRS_PT_MOLLWEIDE",SWIG_FromCharPtr("Mollweide"));
-  SWIG_Python_SetConstant(d, "SRS_PT_NEW_ZEALAND_MAP_GRID",SWIG_FromCharPtr("New_Zealand_Map_Grid"));
-  SWIG_Python_SetConstant(d, "SRS_PT_OBLIQUE_STEREOGRAPHIC",SWIG_FromCharPtr("Oblique_Stereographic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_ORTHOGRAPHIC",SWIG_FromCharPtr("Orthographic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_POLAR_STEREOGRAPHIC",SWIG_FromCharPtr("Polar_Stereographic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_POLYCONIC",SWIG_FromCharPtr("Polyconic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_ROBINSON",SWIG_FromCharPtr("Robinson"));
-  SWIG_Python_SetConstant(d, "SRS_PT_SINUSOIDAL",SWIG_FromCharPtr("Sinusoidal"));
-  SWIG_Python_SetConstant(d, "SRS_PT_STEREOGRAPHIC",SWIG_FromCharPtr("Stereographic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_SWISS_OBLIQUE_CYLINDRICAL",SWIG_FromCharPtr("Swiss_Oblique_Cylindrical"));
-  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR",SWIG_FromCharPtr("Transverse_Mercator"));
-  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED",SWIG_FromCharPtr("Transverse_Mercator_South_Orientated"));
-  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_21",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_21"));
-  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_22",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_22"));
-  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_23",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_23"));
-  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_24",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_24"));
-  SWIG_Python_SetConstant(d, "SRS_PT_TRANSVERSE_MERCATOR_MI_25",SWIG_FromCharPtr("Transverse_Mercator_MapInfo_25"));
-  SWIG_Python_SetConstant(d, "SRS_PT_TUNISIA_MINING_GRID",SWIG_FromCharPtr("Tunisia_Mining_Grid"));
-  SWIG_Python_SetConstant(d, "SRS_PT_TWO_POINT_EQUIDISTANT",SWIG_FromCharPtr("Two_Point_Equidistant"));
-  SWIG_Python_SetConstant(d, "SRS_PT_VANDERGRINTEN",SWIG_FromCharPtr("VanDerGrinten"));
-  SWIG_Python_SetConstant(d, "SRS_PT_KROVAK",SWIG_FromCharPtr("Krovak"));
-  SWIG_Python_SetConstant(d, "SRS_PT_IMW_POLYCONIC",SWIG_FromCharPtr("International_Map_of_the_World_Polyconic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_I",SWIG_FromCharPtr("Wagner_I"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_II",SWIG_FromCharPtr("Wagner_II"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_III",SWIG_FromCharPtr("Wagner_III"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_IV",SWIG_FromCharPtr("Wagner_IV"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_V",SWIG_FromCharPtr("Wagner_V"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_VI",SWIG_FromCharPtr("Wagner_VI"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WAGNER_VII",SWIG_FromCharPtr("Wagner_VII"));
-  SWIG_Python_SetConstant(d, "SRS_PT_QSC",SWIG_FromCharPtr("Quadrilateralized_Spherical_Cube"));
-  SWIG_Python_SetConstant(d, "SRS_PT_AITOFF",SWIG_FromCharPtr("Aitoff"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WINKEL_I",SWIG_FromCharPtr("Winkel_I"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WINKEL_II",SWIG_FromCharPtr("Winkel_II"));
-  SWIG_Python_SetConstant(d, "SRS_PT_WINKEL_TRIPEL",SWIG_FromCharPtr("Winkel_Tripel"));
-  SWIG_Python_SetConstant(d, "SRS_PT_CRASTER_PARABOLIC",SWIG_FromCharPtr("Craster_Parabolic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_LOXIMUTHAL",SWIG_FromCharPtr("Loximuthal"));
-  SWIG_Python_SetConstant(d, "SRS_PT_QUARTIC_AUTHALIC",SWIG_FromCharPtr("Quartic_Authalic"));
-  SWIG_Python_SetConstant(d, "SRS_PT_SCH",SWIG_FromCharPtr("Spherical_Cross_Track_Height"));
-  SWIG_Python_SetConstant(d, "SRS_PP_CENTRAL_MERIDIAN",SWIG_FromCharPtr("central_meridian"));
-  SWIG_Python_SetConstant(d, "SRS_PP_SCALE_FACTOR",SWIG_FromCharPtr("scale_factor"));
-  SWIG_Python_SetConstant(d, "SRS_PP_STANDARD_PARALLEL_1",SWIG_FromCharPtr("standard_parallel_1"));
-  SWIG_Python_SetConstant(d, "SRS_PP_STANDARD_PARALLEL_2",SWIG_FromCharPtr("standard_parallel_2"));
-  SWIG_Python_SetConstant(d, "SRS_PP_PSEUDO_STD_PARALLEL_1",SWIG_FromCharPtr("pseudo_standard_parallel_1"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_CENTER",SWIG_FromCharPtr("longitude_of_center"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_CENTER",SWIG_FromCharPtr("latitude_of_center"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_ORIGIN",SWIG_FromCharPtr("longitude_of_origin"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_ORIGIN",SWIG_FromCharPtr("latitude_of_origin"));
-  SWIG_Python_SetConstant(d, "SRS_PP_FALSE_EASTING",SWIG_FromCharPtr("false_easting"));
-  SWIG_Python_SetConstant(d, "SRS_PP_FALSE_NORTHING",SWIG_FromCharPtr("false_northing"));
-  SWIG_Python_SetConstant(d, "SRS_PP_AZIMUTH",SWIG_FromCharPtr("azimuth"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_POINT_1",SWIG_FromCharPtr("longitude_of_point_1"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_POINT_1",SWIG_FromCharPtr("latitude_of_point_1"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_POINT_2",SWIG_FromCharPtr("longitude_of_point_2"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_POINT_2",SWIG_FromCharPtr("latitude_of_point_2"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_POINT_3",SWIG_FromCharPtr("longitude_of_point_3"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_POINT_3",SWIG_FromCharPtr("latitude_of_point_3"));
-  SWIG_Python_SetConstant(d, "SRS_PP_RECTIFIED_GRID_ANGLE",SWIG_FromCharPtr("rectified_grid_angle"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LANDSAT_NUMBER",SWIG_FromCharPtr("landsat_number"));
-  SWIG_Python_SetConstant(d, "SRS_PP_PATH_NUMBER",SWIG_FromCharPtr("path_number"));
-  SWIG_Python_SetConstant(d, "SRS_PP_PERSPECTIVE_POINT_HEIGHT",SWIG_FromCharPtr("perspective_point_height"));
-  SWIG_Python_SetConstant(d, "SRS_PP_SATELLITE_HEIGHT",SWIG_FromCharPtr("satellite_height"));
-  SWIG_Python_SetConstant(d, "SRS_PP_FIPSZONE",SWIG_FromCharPtr("fipszone"));
-  SWIG_Python_SetConstant(d, "SRS_PP_ZONE",SWIG_FromCharPtr("zone"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_1ST_POINT",SWIG_FromCharPtr("Latitude_Of_1st_Point"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_1ST_POINT",SWIG_FromCharPtr("Longitude_Of_1st_Point"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LATITUDE_OF_2ND_POINT",SWIG_FromCharPtr("Latitude_Of_2nd_Point"));
-  SWIG_Python_SetConstant(d, "SRS_PP_LONGITUDE_OF_2ND_POINT",SWIG_FromCharPtr("Longitude_Of_2nd_Point"));
-  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_LATITUDE",SWIG_FromCharPtr("peg_point_latitude"));
-  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_LONGITUDE",SWIG_FromCharPtr("peg_point_longitude"));
-  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_HEADING",SWIG_FromCharPtr("peg_point_heading"));
-  SWIG_Python_SetConstant(d, "SRS_PP_PEG_POINT_HEIGHT",SWIG_FromCharPtr("peg_point_height"));
-  SWIG_Python_SetConstant(d, "SRS_UL_METER",SWIG_FromCharPtr("Meter"));
-  SWIG_Python_SetConstant(d, "SRS_UL_FOOT",SWIG_FromCharPtr("Foot (International)"));
-  SWIG_Python_SetConstant(d, "SRS_UL_FOOT_CONV",SWIG_FromCharPtr("0.3048"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_FOOT",SWIG_FromCharPtr("Foot_US"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_FOOT_CONV",SWIG_FromCharPtr("0.3048006096012192"));
-  SWIG_Python_SetConstant(d, "SRS_UL_NAUTICAL_MILE",SWIG_FromCharPtr("Nautical Mile"));
-  SWIG_Python_SetConstant(d, "SRS_UL_NAUTICAL_MILE_CONV",SWIG_FromCharPtr("1852.0"));
-  SWIG_Python_SetConstant(d, "SRS_UL_LINK",SWIG_FromCharPtr("Link"));
-  SWIG_Python_SetConstant(d, "SRS_UL_LINK_CONV",SWIG_FromCharPtr("0.20116684023368047"));
-  SWIG_Python_SetConstant(d, "SRS_UL_CHAIN",SWIG_FromCharPtr("Chain"));
-  SWIG_Python_SetConstant(d, "SRS_UL_CHAIN_CONV",SWIG_FromCharPtr("20.116684023368047"));
-  SWIG_Python_SetConstant(d, "SRS_UL_ROD",SWIG_FromCharPtr("Rod"));
-  SWIG_Python_SetConstant(d, "SRS_UL_ROD_CONV",SWIG_FromCharPtr("5.02921005842012"));
-  SWIG_Python_SetConstant(d, "SRS_UL_LINK_Clarke",SWIG_FromCharPtr("Link_Clarke"));
-  SWIG_Python_SetConstant(d, "SRS_UL_LINK_Clarke_CONV",SWIG_FromCharPtr("0.2011661949"));
-  SWIG_Python_SetConstant(d, "SRS_UL_KILOMETER",SWIG_FromCharPtr("Kilometer"));
-  SWIG_Python_SetConstant(d, "SRS_UL_KILOMETER_CONV",SWIG_FromCharPtr("1000."));
-  SWIG_Python_SetConstant(d, "SRS_UL_DECIMETER",SWIG_FromCharPtr("Decimeter"));
-  SWIG_Python_SetConstant(d, "SRS_UL_DECIMETER_CONV",SWIG_FromCharPtr("0.1"));
-  SWIG_Python_SetConstant(d, "SRS_UL_CENTIMETER",SWIG_FromCharPtr("Centimeter"));
-  SWIG_Python_SetConstant(d, "SRS_UL_CENTIMETER_CONV",SWIG_FromCharPtr("0.01"));
-  SWIG_Python_SetConstant(d, "SRS_UL_MILLIMETER",SWIG_FromCharPtr("Millimeter"));
-  SWIG_Python_SetConstant(d, "SRS_UL_MILLIMETER_CONV",SWIG_FromCharPtr("0.001"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_NAUT_MILE",SWIG_FromCharPtr("Nautical_Mile_International"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_NAUT_MILE_CONV",SWIG_FromCharPtr("1852.0"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_INCH",SWIG_FromCharPtr("Inch_International"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_INCH_CONV",SWIG_FromCharPtr("0.0254"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FOOT",SWIG_FromCharPtr("Foot_International"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FOOT_CONV",SWIG_FromCharPtr("0.3048"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_YARD",SWIG_FromCharPtr("Yard_International"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_YARD_CONV",SWIG_FromCharPtr("0.9144"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_STAT_MILE",SWIG_FromCharPtr("Statute_Mile_International"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_STAT_MILE_CONV",SWIG_FromCharPtr("1609.344"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FATHOM",SWIG_FromCharPtr("Fathom_International"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_FATHOM_CONV",SWIG_FromCharPtr("1.8288"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_CHAIN",SWIG_FromCharPtr("Chain_International"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_CHAIN_CONV",SWIG_FromCharPtr("20.1168"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_LINK",SWIG_FromCharPtr("Link_International"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INTL_LINK_CONV",SWIG_FromCharPtr("0.201168"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_INCH",SWIG_FromCharPtr("Inch_US_Surveyor"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_INCH_CONV",SWIG_FromCharPtr("0.025400050800101603"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_YARD",SWIG_FromCharPtr("Yard_US_Surveyor"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_YARD_CONV",SWIG_FromCharPtr("0.914401828803658"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_CHAIN",SWIG_FromCharPtr("Chain_US_Surveyor"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_CHAIN_CONV",SWIG_FromCharPtr("20.11684023368047"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_STAT_MILE",SWIG_FromCharPtr("Statute_Mile_US_Surveyor"));
-  SWIG_Python_SetConstant(d, "SRS_UL_US_STAT_MILE_CONV",SWIG_FromCharPtr("1609.347218694437"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_YARD",SWIG_FromCharPtr("Yard_Indian"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_YARD_CONV",SWIG_FromCharPtr("0.91439523"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_FOOT",SWIG_FromCharPtr("Foot_Indian"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_FOOT_CONV",SWIG_FromCharPtr("0.30479841"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_CHAIN",SWIG_FromCharPtr("Chain_Indian"));
-  SWIG_Python_SetConstant(d, "SRS_UL_INDIAN_CHAIN_CONV",SWIG_FromCharPtr("20.11669506"));
-  SWIG_Python_SetConstant(d, "SRS_UA_DEGREE",SWIG_FromCharPtr("degree"));
-  SWIG_Python_SetConstant(d, "SRS_UA_DEGREE_CONV",SWIG_FromCharPtr("0.0174532925199433"));
-  SWIG_Python_SetConstant(d, "SRS_UA_RADIAN",SWIG_FromCharPtr("radian"));
-  SWIG_Python_SetConstant(d, "SRS_PM_GREENWICH",SWIG_FromCharPtr("Greenwich"));
-  SWIG_Python_SetConstant(d, "SRS_DN_NAD27",SWIG_FromCharPtr("North_American_Datum_1927"));
-  SWIG_Python_SetConstant(d, "SRS_DN_NAD83",SWIG_FromCharPtr("North_American_Datum_1983"));
-  SWIG_Python_SetConstant(d, "SRS_DN_WGS72",SWIG_FromCharPtr("WGS_1972"));
-  SWIG_Python_SetConstant(d, "SRS_DN_WGS84",SWIG_FromCharPtr("WGS_1984"));
-  SWIG_Python_SetConstant(d, "SRS_WGS84_SEMIMAJOR",SWIG_From_double(static_cast< double >(6378137.0)));
-  SWIG_Python_SetConstant(d, "SRS_WGS84_INVFLATTENING",SWIG_From_double(static_cast< double >(298.257223563)));
-  SWIG_Python_SetConstant(d, "OAO_Other",SWIG_From_int(static_cast< int >(0)));
-  SWIG_Python_SetConstant(d, "OAO_North",SWIG_From_int(static_cast< int >(1)));
-  SWIG_Python_SetConstant(d, "OAO_South",SWIG_From_int(static_cast< int >(2)));
-  SWIG_Python_SetConstant(d, "OAO_East",SWIG_From_int(static_cast< int >(3)));
-  SWIG_Python_SetConstant(d, "OAO_West",SWIG_From_int(static_cast< int >(4)));
-  SWIG_Python_SetConstant(d, "OAO_Up",SWIG_From_int(static_cast< int >(5)));
-  SWIG_Python_SetConstant(d, "OAO_Down",SWIG_From_int(static_cast< int >(6)));
+  
+  /* Initialize threading */
+  SWIG_PYTHON_INITIALIZE_THREADS;
 #if PY_VERSION_HEX >= 0x03000000
   return m;
 #else
diff --git a/swig/python/fallback_build.bat b/swig/python/fallback_build.bat
index 2ae452f..19dc124 100755
--- a/swig/python/fallback_build.bat
+++ b/swig/python/fallback_build.bat
@@ -18,16 +18,16 @@ cl.exe %CLARGS% extensions\gdal_array_wrap.cpp
 
 set LINKOPTS=/DLL /nologo /INCREMENTAL:NO /LIBPATH:../../ /LIBPATH:%PYTHONHOME%\libs /LIBPATH:%PYTHONHOME%\PCBuild gdal_i.lib
 
-link.exe %LINKOPTS% /EXPORT:init_gdal gdal_wrap.obj /OUT:%OUTDIR%\_gdal.pyd 
+link.exe %LINKOPTS% /EXPORT:init_gdal gdal_wrap.obj /OUT:%OUTDIR%\_gdal.pyd
 if exist %OUTDIR%\_gdal.pyd.manifest mt -manifest %OUTDIR%\_gdal.pyd.manifest -outputresource:%OUTDIR%\_gdal.pyd;2
 
-link.exe %LINKOPTS% /EXPORT:init_osr  osr_wrap.obj /OUT:%OUTDIR%\_osr.pyd 
+link.exe %LINKOPTS% /EXPORT:init_osr  osr_wrap.obj /OUT:%OUTDIR%\_osr.pyd
 if exist %OUTDIR%\_osr.pyd.manifest mt -manifest %OUTDIR%\_osr.pyd.manifest -outputresource:%OUTDIR%\_osr.pyd;2
 
-link.exe %LINKOPTS% /EXPORT:init_ogr  ogr_wrap.obj /OUT:%OUTDIR%\_ogr.pyd 
+link.exe %LINKOPTS% /EXPORT:init_ogr  ogr_wrap.obj /OUT:%OUTDIR%\_ogr.pyd
 if exist %OUTDIR%\_ogr.pyd.manifest mt -manifest %OUTDIR%\_ogr.pyd.manifest -outputresource:%OUTDIR%\_ogr.pyd;2
 
-link.exe %LINKOPTS% /EXPORT:init_gdalconst gdalconst_wrap.obj /OUT:%OUTDIR%\_gdalconst.pyd 
+link.exe %LINKOPTS% /EXPORT:init_gdalconst gdalconst_wrap.obj /OUT:%OUTDIR%\_gdalconst.pyd
 if exist %OUTDIR%\_gdalconst.pyd.manifest mt -manifest %OUTDIR%\_gdalconst.pyd.manifest -outputresource:%OUTDIR%\_gdalconst.pyd;2
 
 link.exe %LINKOPTS% /EXPORT:init_gdal_array gdal_array_wrap.obj /OUT:%OUTDIR%\_gdal_array.pyd
diff --git a/swig/python/osgeo/gdal.py b/swig/python/osgeo/gdal.py
index 7af2df1..28c3822 100644
--- a/swig/python/osgeo/gdal.py
+++ b/swig/python/osgeo/gdal.py
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
+# Version 3.0.8
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
@@ -9,7 +9,7 @@
 
 
 from sys import version_info
-if version_info >= (2,6,0):
+if version_info >= (2, 6, 0):
     def swig_import_helper():
         from os.path import dirname
         import imp
@@ -33,42 +33,66 @@ del version_info
 try:
     _swig_property = property
 except NameError:
-    pass # Python < 2.2 doesn't have 'property'.
-def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
-    if (name == "thisown"): return self.this.own(value)
+    pass  # Python < 2.2 doesn't have 'property'.
+
+
+def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
+    if (name == "thisown"):
+        return self.this.own(value)
     if (name == "this"):
         if type(value).__name__ == 'SwigPyObject':
             self.__dict__[name] = value
             return
-    method = class_type.__swig_setmethods__.get(name,None)
-    if method: return method(self,value)
+    method = class_type.__swig_setmethods__.get(name, None)
+    if method:
+        return method(self, value)
     if (not static):
-        self.__dict__[name] = value
+        if _newclass:
+            object.__setattr__(self, name, value)
+        else:
+            self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
 
-def _swig_setattr(self,class_type,name,value):
-    return _swig_setattr_nondynamic(self,class_type,name,value,0)
 
-def _swig_getattr(self,class_type,name):
-    if (name == "thisown"): return self.this.own()
-    method = class_type.__swig_getmethods__.get(name,None)
-    if method: return method(self)
-    raise AttributeError(name)
+def _swig_setattr(self, class_type, name, value):
+    return _swig_setattr_nondynamic(self, class_type, name, value, 0)
+
+
+def _swig_getattr_nondynamic(self, class_type, name, static=1):
+    if (name == "thisown"):
+        return self.this.own()
+    method = class_type.__swig_getmethods__.get(name, None)
+    if method:
+        return method(self)
+    if (not static):
+        return object.__getattr__(self, name)
+    else:
+        raise AttributeError(name)
+
+def _swig_getattr(self, class_type, name):
+    return _swig_getattr_nondynamic(self, class_type, name, 0)
+
 
 def _swig_repr(self):
-    try: strthis = "proxy of " + self.this.__repr__()
-    except: strthis = ""
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except Exception:
+        strthis = ""
     return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
 
 try:
     _object = object
     _newclass = 1
 except AttributeError:
-    class _object : pass
+    class _object:
+        pass
     _newclass = 0
 
 
+
+
+
 have_warned = 0
 def deprecation_warn( module ):
   global have_warned
@@ -134,20 +158,22 @@ def RGBFile2PCTFile( src_filename, dst_filename ):
 
 
 def GetUseExceptions(*args):
-  """GetUseExceptions() -> int"""
-  return _gdal.GetUseExceptions(*args)
+    """GetUseExceptions() -> int"""
+    return _gdal.GetUseExceptions(*args)
 
 def UseExceptions(*args):
-  """UseExceptions()"""
-  return _gdal.UseExceptions(*args)
+    """UseExceptions()"""
+    return _gdal.UseExceptions(*args)
 
 def DontUseExceptions(*args):
-  """DontUseExceptions()"""
-  return _gdal.DontUseExceptions(*args)
+    """DontUseExceptions()"""
+    return _gdal.DontUseExceptions(*args)
 
 def VSIFReadL(*args):
-  """VSIFReadL(int nMembSize, int nMembCount, VSILFILE * fp) -> int"""
-  return _gdal.VSIFReadL(*args)
+    """VSIFReadL(unsigned int nMembSize, unsigned int nMembCount, VSILFILE * fp) -> unsigned int"""
+    return _gdal.VSIFReadL(*args)
+
+
 def _is_str_or_unicode(o):
     return isinstance(o, str) or str(type(o)) == "<type 'unicode'>"
 
@@ -352,7 +378,7 @@ def Translate(destName, srcDS, **kwargs):
           destName --- Output dataset name
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.TranslateOptions(), string or array of strings
           other keywords arguments of gdal.TranslateOptions()
         If options is provided as a gdal.TranslateOptions() object, other keywords are ignored. """
 
@@ -525,7 +551,7 @@ def Warp(destNameOrDestDS, srcDSOrSrcDSTab, **kwargs):
           destNameOrDestDS --- Output dataset name or object
           srcDSOrSrcDSTab --- an array of Dataset objects or filenames, or a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.WarpOptions(), string or array of strings
           other keywords arguments of gdal.WarpOptions()
         If options is provided as a gdal.WarpOptions() object, other keywords are ignored. """
 
@@ -554,7 +580,8 @@ def Warp(destNameOrDestDS, srcDSOrSrcDSTab, **kwargs):
 def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
          accessMode = None,
          srcSRS = None, dstSRS = None, reproject = True,
-         SQLStatement = None, SQLDialect = None, where = None, selectFields = None, spatFilter = None,
+         SQLStatement = None, SQLDialect = None, where = None, selectFields = None,
+         spatFilter = None, spatSRS = None,
          datasetCreationOptions = None,
          layerCreationOptions = None,
          layers = None,
@@ -564,6 +591,7 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
          segmentizeMaxDist= None,
          zField = None,
          skipFailures = False,
+         limit = None,
          callback = None, callback_data = None):
     """ Create a VectorTranslateOptions() object that can be passed to gdal.VectorTranslate()
         Keyword arguments are :
@@ -578,6 +606,7 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
           where --- WHERE clause to apply to source layer(s)
           selectFields --- list of fields to select
           spatFilter --- spatial filter as (minX, minY, maxX, maxY) bounding box
+          spatSRS --- SRS in which the spatFilter is expressed. If not specified, it is assumed to be the one of the layer(s)
           datasetCreationOptions --- list of dataset creation options
           layerCreationOptions --- list of layer creation options
           layers --- list of layers to convert
@@ -587,6 +616,7 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
           segmentizeMaxDist --- maximum distance between consecutive nodes of a line geometry
           zField --- name of field to use to set the Z component of geometries
           skipFailures --- whether to skip failures
+          limit -- maximum number of features to read per layer
           callback --- callback method
           callback_data --- user data for callback
     """
@@ -633,12 +663,17 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
             for opt in layerCreationOptions:
                 new_options += ['-lco', opt ]
         if layers is not None:
-            for lyr in layers:
-                new_options += [ lyr ]
+            if _is_str_or_unicode(layers):
+                new_options += [ layers ]
+            else:
+                for lyr in layers:
+                    new_options += [ lyr ]
         if segmentizeMaxDist is not None:
             new_options += ['-segmentize', str(segmentizeMaxDist) ]
         if spatFilter is not None:
             new_options += ['-spat', str(spatFilter[0]), str(spatFilter[1]), str(spatFilter[2]), str(spatFilter[3]) ]
+        if spatSRS is not None:
+            new_options += ['-spat_srs', str(spatSRS) ]
         if layerName is not None:
             new_options += ['-nln', layerName]
         if geometryType is not None:
@@ -649,7 +684,8 @@ def VectorTranslateOptions(options = [], format = 'ESRI Shapefile',
             new_options += ['-zfield', zField]
         if skipFailures:
             new_options += ['-skip']
-
+        if limit is not None:
+            new_options += ['-limit', str(limit)]
     if callback is not None:
         new_options += [ '-progress' ]
 
@@ -661,7 +697,7 @@ def VectorTranslate(destNameOrDestDS, srcDS, **kwargs):
           destNameOrDestDS --- Output dataset name or object
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.VectorTranslateOptions(), string or array of strings
           other keywords arguments of gdal.VectorTranslateOptions()
         If options is provided as a gdal.VectorTranslateOptions() object, other keywords are ignored. """
 
@@ -679,7 +715,8 @@ def VectorTranslate(destNameOrDestDS, srcDS, **kwargs):
 
 def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
               creationOptions = None, computeEdges = False, alg = 'Horn', band = 1,
-              zFactor = None, scale = None, azimuth = None, altitude = None, combined = False,
+              zFactor = None, scale = None, azimuth = None, altitude = None,
+              combined = False, multiDirectional = False,
               slopeFormat = None, trigonometric = False, zeroForFlat = False,
               callback = None, callback_data = None):
     """ Create a DEMProcessingOptions() object that can be passed to gdal.DEMProcessing()
@@ -696,6 +733,7 @@ def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
           azimuth --- (hillshade only) azimuth of the light, in degrees. 0 if it comes from the top of the raster, 90 from the east, ... The default value, 315, should rarely be changed as it is the value generally used to generate shaded maps.
           altitude ---(hillshade only) altitude of the light, in degrees. 90 if the light comes from above the DEM, 0 if it is raking light.
           combined --- (hillshade only) whether to compute combined shading, a combination of slope and oblique shading.
+          multiDirectional --- (hillshade only) whether to compute multi-directional shading
           slopeformat --- (slope only) "degree" or "percent".
           trigonometric --- (aspect only) whether to return trigonometric angle instead of azimuth. Thus 0deg means East, 90deg North, 180deg West, 270deg South.
           zeroForFlat --- (aspect only) whether to return 0 for flat areas with slope=0, instead of -9999.
@@ -727,6 +765,8 @@ def DEMProcessingOptions(options = [], colorFilename = None, format = 'GTiff',
             new_options += ['-alt', str(altitude) ]
         if combined:
             new_options += ['-combined' ]
+        if multiDirectional:
+            new_options += ['-multidirectional' ]
         if slopeFormat == 'percent':
             new_options += ['-p' ]
         if trigonometric:
@@ -743,7 +783,7 @@ def DEMProcessing(destName, srcDS, processing, **kwargs):
           srcDS --- a Dataset object or a filename
           processing --- one of "hillshade", "slope", "aspect", "color-relief", "TRI", "TPI", "Roughness"
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.DEMProcessingOptions(), string or array of strings
           other keywords arguments of gdal.DEMProcessingOptions()
         If options is provided as a gdal.DEMProcessingOptions() object, other keywords are ignored. """
 
@@ -812,7 +852,7 @@ def Nearblack(destNameOrDestDS, srcDS, **kwargs):
           destNameOrDestDS --- Output dataset name or object
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.NearblackOptions(), string or array of strings
           other keywords arguments of gdal.NearblackOptions()
         If options is provided as a gdal.NearblackOptions() object, other keywords are ignored. """
 
@@ -914,7 +954,7 @@ def Grid(destName, srcDS, **kwargs):
           destName --- Output dataset name
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.GridOptions(), string or array of strings
           other keywords arguments of gdal.GridOptions()
         If options is provided as a gdal.GridOptions() object, other keywords are ignored. """
 
@@ -1035,7 +1075,7 @@ def Rasterize(destNameOrDestDS, srcDS, **kwargs):
           destNameOrDestDS --- Output dataset name or object
           srcDS --- a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.RasterizeOptions(), string or array of strings
           other keywords arguments of gdal.RasterizeOptions()
         If options is provided as a gdal.RasterizeOptions() object, other keywords are ignored. """
 
@@ -1145,7 +1185,7 @@ def BuildVRT(destName, srcDSOrSrcDSTab, **kwargs):
           destName --- Output dataset name
           srcDSOrSrcDSTab --- an array of Dataset objects or filenames, or a Dataset object or a filename
         Keyword arguments are :
-          options --- return of gdal.InfoOptions(), string or array of strings
+          options --- return of gdal.BuildVRTOptions(), string or array of strings
           other keywords arguments of gdal.BuildVRTOptions()
         If options is provided as a gdal.BuildVRTOptions() object, other keywords are ignored. """
 
@@ -1177,151 +1217,165 @@ def BuildVRT(destName, srcDSOrSrcDSTab, **kwargs):
 
 
 def Debug(*args):
-  """Debug(char const * msg_class, char const * message)"""
-  return _gdal.Debug(*args)
+    """Debug(char const * msg_class, char const * message)"""
+    return _gdal.Debug(*args)
 
 def SetErrorHandler(*args):
-  """SetErrorHandler(char const * pszCallbackName=None) -> CPLErr"""
-  return _gdal.SetErrorHandler(*args)
+    """SetErrorHandler(char const * pszCallbackName=None) -> CPLErr"""
+    return _gdal.SetErrorHandler(*args)
 
 def PushErrorHandler(*args):
-  """PushErrorHandler(CPLErrorHandler pfnErrorHandler=0) -> CPLErr"""
-  return _gdal.PushErrorHandler(*args)
+    """PushErrorHandler(CPLErrorHandler pfnErrorHandler=0) -> CPLErr"""
+    return _gdal.PushErrorHandler(*args)
 
 def PopErrorHandler(*args):
-  """PopErrorHandler()"""
-  return _gdal.PopErrorHandler(*args)
+    """PopErrorHandler()"""
+    return _gdal.PopErrorHandler(*args)
 
 def Error(*args):
-  """Error(CPLErr msg_class=CE_Failure, int err_code=0, char const * msg="error")"""
-  return _gdal.Error(*args)
+    """Error(CPLErr msg_class, int err_code=0, char const * msg)"""
+    return _gdal.Error(*args)
 
 def GOA2GetAuthorizationURL(*args):
-  """GOA2GetAuthorizationURL(char const * pszScope) -> retStringAndCPLFree *"""
-  return _gdal.GOA2GetAuthorizationURL(*args)
+    """GOA2GetAuthorizationURL(char const * pszScope) -> retStringAndCPLFree *"""
+    return _gdal.GOA2GetAuthorizationURL(*args)
 
 def GOA2GetRefreshToken(*args):
-  """GOA2GetRefreshToken(char const * pszAuthToken, char const * pszScope) -> retStringAndCPLFree *"""
-  return _gdal.GOA2GetRefreshToken(*args)
+    """GOA2GetRefreshToken(char const * pszAuthToken, char const * pszScope) -> retStringAndCPLFree *"""
+    return _gdal.GOA2GetRefreshToken(*args)
 
 def GOA2GetAccessToken(*args):
-  """GOA2GetAccessToken(char const * pszRefreshToken, char const * pszScope) -> retStringAndCPLFree *"""
-  return _gdal.GOA2GetAccessToken(*args)
+    """GOA2GetAccessToken(char const * pszRefreshToken, char const * pszScope) -> retStringAndCPLFree *"""
+    return _gdal.GOA2GetAccessToken(*args)
 
 def ErrorReset(*args):
-  """ErrorReset()"""
-  return _gdal.ErrorReset(*args)
+    """ErrorReset()"""
+    return _gdal.ErrorReset(*args)
 
 def EscapeString(*args, **kwargs):
-  """EscapeString(int len, int scheme=CPLES_SQL) -> retStringAndCPLFree *"""
-  return _gdal.EscapeString(*args, **kwargs)
+    """EscapeString(int len, int scheme) -> retStringAndCPLFree *"""
+    return _gdal.EscapeString(*args, **kwargs)
 
 def GetLastErrorNo(*args):
-  """GetLastErrorNo() -> int"""
-  return _gdal.GetLastErrorNo(*args)
+    """GetLastErrorNo() -> int"""
+    return _gdal.GetLastErrorNo(*args)
 
 def GetLastErrorType(*args):
-  """GetLastErrorType() -> int"""
-  return _gdal.GetLastErrorType(*args)
+    """GetLastErrorType() -> int"""
+    return _gdal.GetLastErrorType(*args)
 
 def GetLastErrorMsg(*args):
-  """GetLastErrorMsg() -> char const *"""
-  return _gdal.GetLastErrorMsg(*args)
+    """GetLastErrorMsg() -> char const *"""
+    return _gdal.GetLastErrorMsg(*args)
 
 def VSIGetLastErrorNo(*args):
-  """VSIGetLastErrorNo() -> int"""
-  return _gdal.VSIGetLastErrorNo(*args)
+    """VSIGetLastErrorNo() -> int"""
+    return _gdal.VSIGetLastErrorNo(*args)
 
 def VSIGetLastErrorMsg(*args):
-  """VSIGetLastErrorMsg() -> char const *"""
-  return _gdal.VSIGetLastErrorMsg(*args)
+    """VSIGetLastErrorMsg() -> char const *"""
+    return _gdal.VSIGetLastErrorMsg(*args)
 
 def PushFinderLocation(*args):
-  """PushFinderLocation(char const * utf8_path)"""
-  return _gdal.PushFinderLocation(*args)
+    """PushFinderLocation(char const * utf8_path)"""
+    return _gdal.PushFinderLocation(*args)
 
 def PopFinderLocation(*args):
-  """PopFinderLocation()"""
-  return _gdal.PopFinderLocation(*args)
+    """PopFinderLocation()"""
+    return _gdal.PopFinderLocation(*args)
 
 def FinderClean(*args):
-  """FinderClean()"""
-  return _gdal.FinderClean(*args)
+    """FinderClean()"""
+    return _gdal.FinderClean(*args)
 
 def FindFile(*args):
-  """FindFile(char const * pszClass, char const * utf8_path) -> char const *"""
-  return _gdal.FindFile(*args)
+    """FindFile(char const * pszClass, char const * utf8_path) -> char const *"""
+    return _gdal.FindFile(*args)
 
 def ReadDir(*args):
-  """ReadDir(char const * utf8_path, int nMaxFiles=0) -> char **"""
-  return _gdal.ReadDir(*args)
+    """ReadDir(char const * utf8_path, int nMaxFiles=0) -> char **"""
+    return _gdal.ReadDir(*args)
 
 def ReadDirRecursive(*args):
-  """ReadDirRecursive(char const * utf8_path) -> char **"""
-  return _gdal.ReadDirRecursive(*args)
+    """ReadDirRecursive(char const * utf8_path) -> char **"""
+    return _gdal.ReadDirRecursive(*args)
 
 def SetConfigOption(*args):
-  """SetConfigOption(char const * pszKey, char const * pszValue)"""
-  return _gdal.SetConfigOption(*args)
+    """SetConfigOption(char const * pszKey, char const * pszValue)"""
+    return _gdal.SetConfigOption(*args)
 
 def GetConfigOption(*args):
-  """GetConfigOption(char const * pszKey, char const * pszDefault=None) -> char const *"""
-  return _gdal.GetConfigOption(*args)
+    """GetConfigOption(char const * pszKey, char const * pszDefault=None) -> char const *"""
+    return _gdal.GetConfigOption(*args)
 
 def CPLBinaryToHex(*args):
-  """CPLBinaryToHex(int nBytes) -> retStringAndCPLFree *"""
-  return _gdal.CPLBinaryToHex(*args)
+    """CPLBinaryToHex(int nBytes) -> retStringAndCPLFree *"""
+    return _gdal.CPLBinaryToHex(*args)
 
 def CPLHexToBinary(*args):
-  """CPLHexToBinary(char const * pszHex, int * pnBytes) -> GByte *"""
-  return _gdal.CPLHexToBinary(*args)
+    """CPLHexToBinary(char const * pszHex, int * pnBytes) -> GByte *"""
+    return _gdal.CPLHexToBinary(*args)
 
 def FileFromMemBuffer(*args):
-  """FileFromMemBuffer(char const * utf8_path, int nBytes)"""
-  return _gdal.FileFromMemBuffer(*args)
+    """FileFromMemBuffer(char const * utf8_path, GIntBig nBytes)"""
+    return _gdal.FileFromMemBuffer(*args)
 
 def Unlink(*args):
-  """Unlink(char const * utf8_path) -> VSI_RETVAL"""
-  return _gdal.Unlink(*args)
+    """Unlink(char const * utf8_path) -> VSI_RETVAL"""
+    return _gdal.Unlink(*args)
 
 def HasThreadSupport(*args):
-  """HasThreadSupport() -> int"""
-  return _gdal.HasThreadSupport(*args)
+    """HasThreadSupport() -> int"""
+    return _gdal.HasThreadSupport(*args)
 
 def Mkdir(*args):
-  """Mkdir(char const * utf8_path, int mode) -> VSI_RETVAL"""
-  return _gdal.Mkdir(*args)
+    """Mkdir(char const * utf8_path, int mode) -> VSI_RETVAL"""
+    return _gdal.Mkdir(*args)
 
 def Rmdir(*args):
-  """Rmdir(char const * utf8_path) -> VSI_RETVAL"""
-  return _gdal.Rmdir(*args)
+    """Rmdir(char const * utf8_path) -> VSI_RETVAL"""
+    return _gdal.Rmdir(*args)
 
 def Rename(*args):
-  """Rename(char const * pszOld, char const * pszNew) -> VSI_RETVAL"""
-  return _gdal.Rename(*args)
+    """Rename(char const * pszOld, char const * pszNew) -> VSI_RETVAL"""
+    return _gdal.Rename(*args)
+
+_gdal.VSI_STAT_EXISTS_FLAG_swigconstant(_gdal)
 VSI_STAT_EXISTS_FLAG = _gdal.VSI_STAT_EXISTS_FLAG
+
+_gdal.VSI_STAT_NATURE_FLAG_swigconstant(_gdal)
 VSI_STAT_NATURE_FLAG = _gdal.VSI_STAT_NATURE_FLAG
+
+_gdal.VSI_STAT_SIZE_FLAG_swigconstant(_gdal)
 VSI_STAT_SIZE_FLAG = _gdal.VSI_STAT_SIZE_FLAG
 class StatBuf(_object):
-    """Proxy of C++ StatBuf class"""
+    """Proxy of C++ StatBuf class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, StatBuf, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, StatBuf, name)
     __repr__ = _swig_repr
     __swig_getmethods__["mode"] = _gdal.StatBuf_mode_get
-    if _newclass:mode = _swig_property(_gdal.StatBuf_mode_get)
+    if _newclass:
+        mode = _swig_property(_gdal.StatBuf_mode_get)
     __swig_getmethods__["size"] = _gdal.StatBuf_size_get
-    if _newclass:size = _swig_property(_gdal.StatBuf_size_get)
+    if _newclass:
+        size = _swig_property(_gdal.StatBuf_size_get)
     __swig_getmethods__["mtime"] = _gdal.StatBuf_mtime_get
-    if _newclass:mtime = _swig_property(_gdal.StatBuf_mtime_get)
-    def __init__(self, *args): 
+    if _newclass:
+        mtime = _swig_property(_gdal.StatBuf_mtime_get)
+
+    def __init__(self, *args):
         """__init__(StatBuf self, StatBuf psStatBuf) -> StatBuf"""
         this = _gdal.new_StatBuf(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_StatBuf
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def IsDirectory(self, *args):
         """IsDirectory(StatBuf self) -> int"""
         return _gdal.StatBuf_IsDirectory(self, *args)
@@ -1331,83 +1385,112 @@ StatBuf_swigregister(StatBuf)
 
 
 def VSIStatL(*args):
-  """VSIStatL(char const * utf8_path, int nFlags=0) -> int"""
-  return _gdal.VSIStatL(*args)
+    """VSIStatL(char const * utf8_path, int nFlags=0) -> int"""
+    return _gdal.VSIStatL(*args)
 
 def VSIFOpenL(*args):
-  """VSIFOpenL(char const * utf8_path, char const * pszMode) -> VSILFILE *"""
-  return _gdal.VSIFOpenL(*args)
+    """VSIFOpenL(char const * utf8_path, char const * pszMode) -> VSILFILE *"""
+    return _gdal.VSIFOpenL(*args)
 
 def VSIFOpenExL(*args):
-  """VSIFOpenExL(char const * utf8_path, char const * pszMode, int bSetError) -> VSILFILE *"""
-  return _gdal.VSIFOpenExL(*args)
+    """VSIFOpenExL(char const * utf8_path, char const * pszMode, int bSetError) -> VSILFILE *"""
+    return _gdal.VSIFOpenExL(*args)
 
 def VSIFCloseL(*args):
-  """VSIFCloseL(VSILFILE * fp) -> VSI_RETVAL"""
-  return _gdal.VSIFCloseL(*args)
+    """VSIFCloseL(VSILFILE * fp) -> VSI_RETVAL"""
+    return _gdal.VSIFCloseL(*args)
 
 def VSIFSeekL(*args):
-  """VSIFSeekL(VSILFILE * fp, GIntBig offset, int whence) -> int"""
-  return _gdal.VSIFSeekL(*args)
+    """VSIFSeekL(VSILFILE * fp, GIntBig offset, int whence) -> int"""
+    return _gdal.VSIFSeekL(*args)
 
 def VSIFTellL(*args):
-  """VSIFTellL(VSILFILE * fp) -> GIntBig"""
-  return _gdal.VSIFTellL(*args)
+    """VSIFTellL(VSILFILE * fp) -> GIntBig"""
+    return _gdal.VSIFTellL(*args)
 
 def VSIFTruncateL(*args):
-  """VSIFTruncateL(VSILFILE * fp, GIntBig length) -> int"""
-  return _gdal.VSIFTruncateL(*args)
+    """VSIFTruncateL(VSILFILE * fp, GIntBig length) -> int"""
+    return _gdal.VSIFTruncateL(*args)
+
+def VSISupportsSparseFiles(*args):
+    """VSISupportsSparseFiles(char const * utf8_path) -> int"""
+    return _gdal.VSISupportsSparseFiles(*args)
+
+_gdal.VSI_RANGE_STATUS_UNKNOWN_swigconstant(_gdal)
+VSI_RANGE_STATUS_UNKNOWN = _gdal.VSI_RANGE_STATUS_UNKNOWN
+
+_gdal.VSI_RANGE_STATUS_DATA_swigconstant(_gdal)
+VSI_RANGE_STATUS_DATA = _gdal.VSI_RANGE_STATUS_DATA
+
+_gdal.VSI_RANGE_STATUS_HOLE_swigconstant(_gdal)
+VSI_RANGE_STATUS_HOLE = _gdal.VSI_RANGE_STATUS_HOLE
+
+def VSIFGetRangeStatusL(*args):
+    """VSIFGetRangeStatusL(VSILFILE * fp, GIntBig offset, GIntBig length) -> int"""
+    return _gdal.VSIFGetRangeStatusL(*args)
 
 def VSIFWriteL(*args):
-  """VSIFWriteL(int nLen, int size, int memb, VSILFILE * fp) -> int"""
-  return _gdal.VSIFWriteL(*args)
+    """VSIFWriteL(int nLen, int size, int memb, VSILFILE * fp) -> int"""
+    return _gdal.VSIFWriteL(*args)
 
 def ParseCommandLine(*args):
-  """ParseCommandLine(char const * utf8_path) -> char **"""
-  return _gdal.ParseCommandLine(*args)
+    """ParseCommandLine(char const * utf8_path) -> char **"""
+    return _gdal.ParseCommandLine(*args)
 class MajorObject(_object):
-    """Proxy of C++ GDALMajorObjectShadow class"""
+    """Proxy of C++ GDALMajorObjectShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, MajorObject, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, MajorObject, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
+
     def GetDescription(self, *args):
         """GetDescription(MajorObject self) -> char const *"""
         return _gdal.MajorObject_GetDescription(self, *args)
 
+
     def SetDescription(self, *args):
         """SetDescription(MajorObject self, char const * pszNewDesc)"""
         return _gdal.MajorObject_SetDescription(self, *args)
 
+
     def GetMetadataDomainList(self, *args):
         """GetMetadataDomainList(MajorObject self) -> char **"""
         return _gdal.MajorObject_GetMetadataDomainList(self, *args)
 
+
     def GetMetadata_Dict(self, *args):
-        """GetMetadata_Dict(MajorObject self, char const * pszDomain="") -> char **"""
+        """GetMetadata_Dict(MajorObject self, char const * pszDomain) -> char **"""
         return _gdal.MajorObject_GetMetadata_Dict(self, *args)
 
+
     def GetMetadata_List(self, *args):
-        """GetMetadata_List(MajorObject self, char const * pszDomain="") -> char **"""
+        """GetMetadata_List(MajorObject self, char const * pszDomain) -> char **"""
         return _gdal.MajorObject_GetMetadata_List(self, *args)
 
+
     def SetMetadata(self, *args):
         """
-        SetMetadata(MajorObject self, char ** papszMetadata, char const * pszDomain="") -> CPLErr
-        SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain="") -> CPLErr
+        SetMetadata(MajorObject self, char ** papszMetadata, char const * pszDomain) -> CPLErr
+        SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain) -> CPLErr
         """
         return _gdal.MajorObject_SetMetadata(self, *args)
 
+
     def GetMetadataItem(self, *args):
-        """GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain="") -> char const *"""
+        """GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain) -> char const *"""
         return _gdal.MajorObject_GetMetadataItem(self, *args)
 
+
     def SetMetadataItem(self, *args):
-        """SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain="") -> CPLErr"""
+        """SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain) -> CPLErr"""
         return _gdal.MajorObject_SetMetadataItem(self, *args)
 
+
     def GetMetadata( self, domain = '' ):
       if domain[:4] == 'xml:':
         return self.GetMetadata_List( domain )
@@ -1417,51 +1500,60 @@ MajorObject_swigregister = _gdal.MajorObject_swigregister
 MajorObject_swigregister(MajorObject)
 
 class Driver(MajorObject):
-    """Proxy of C++ GDALDriverShadow class"""
+    """Proxy of C++ GDALDriverShadow class."""
+
     __swig_setmethods__ = {}
-    for _s in [MajorObject]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
     __setattr__ = lambda self, name, value: _swig_setattr(self, Driver, name, value)
     __swig_getmethods__ = {}
-    for _s in [MajorObject]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
     __getattr__ = lambda self, name: _swig_getattr(self, Driver, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_getmethods__["ShortName"] = _gdal.Driver_ShortName_get
-    if _newclass:ShortName = _swig_property(_gdal.Driver_ShortName_get)
+    if _newclass:
+        ShortName = _swig_property(_gdal.Driver_ShortName_get)
     __swig_getmethods__["LongName"] = _gdal.Driver_LongName_get
-    if _newclass:LongName = _swig_property(_gdal.Driver_LongName_get)
+    if _newclass:
+        LongName = _swig_property(_gdal.Driver_LongName_get)
     __swig_getmethods__["HelpTopic"] = _gdal.Driver_HelpTopic_get
-    if _newclass:HelpTopic = _swig_property(_gdal.Driver_HelpTopic_get)
+    if _newclass:
+        HelpTopic = _swig_property(_gdal.Driver_HelpTopic_get)
+
     def Create(self, *args, **kwargs):
-        """
-        Create(Driver self, char const * utf8_path, int xsize, int ysize, int bands=1, GDALDataType eType=GDT_Byte, 
-            char ** options=None) -> Dataset
-        """
+        """Create(Driver self, char const * utf8_path, int xsize, int ysize, int bands=1, GDALDataType eType, char ** options=None) -> Dataset"""
         return _gdal.Driver_Create(self, *args, **kwargs)
 
+
     def CreateCopy(self, *args, **kwargs):
-        """
-        CreateCopy(Driver self, char const * utf8_path, Dataset src, int strict=1, char ** options=None, GDALProgressFunc callback=0, 
-            void * callback_data=None) -> Dataset
-        """
+        """CreateCopy(Driver self, char const * utf8_path, Dataset src, int strict=1, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
         return _gdal.Driver_CreateCopy(self, *args, **kwargs)
 
+
     def Delete(self, *args):
         """Delete(Driver self, char const * utf8_path) -> CPLErr"""
         return _gdal.Driver_Delete(self, *args)
 
+
     def Rename(self, *args):
         """Rename(Driver self, char const * newName, char const * oldName) -> CPLErr"""
         return _gdal.Driver_Rename(self, *args)
 
+
     def CopyFiles(self, *args):
         """CopyFiles(Driver self, char const * newName, char const * oldName) -> CPLErr"""
         return _gdal.Driver_CopyFiles(self, *args)
 
+
     def Register(self, *args):
         """Register(Driver self) -> int"""
         return _gdal.Driver_Register(self, *args)
 
+
     def Deregister(self, *args):
         """Deregister(Driver self)"""
         return _gdal.Driver_Deregister(self, *args)
@@ -1472,30 +1564,38 @@ Driver_swigregister(Driver)
 import ogr
 import osr
 class ColorEntry(_object):
-    """Proxy of C++ GDALColorEntry class"""
+    """Proxy of C++ GDALColorEntry class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, ColorEntry, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, ColorEntry, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_setmethods__["c1"] = _gdal.ColorEntry_c1_set
     __swig_getmethods__["c1"] = _gdal.ColorEntry_c1_get
-    if _newclass:c1 = _swig_property(_gdal.ColorEntry_c1_get, _gdal.ColorEntry_c1_set)
+    if _newclass:
+        c1 = _swig_property(_gdal.ColorEntry_c1_get, _gdal.ColorEntry_c1_set)
     __swig_setmethods__["c2"] = _gdal.ColorEntry_c2_set
     __swig_getmethods__["c2"] = _gdal.ColorEntry_c2_get
-    if _newclass:c2 = _swig_property(_gdal.ColorEntry_c2_get, _gdal.ColorEntry_c2_set)
+    if _newclass:
+        c2 = _swig_property(_gdal.ColorEntry_c2_get, _gdal.ColorEntry_c2_set)
     __swig_setmethods__["c3"] = _gdal.ColorEntry_c3_set
     __swig_getmethods__["c3"] = _gdal.ColorEntry_c3_get
-    if _newclass:c3 = _swig_property(_gdal.ColorEntry_c3_get, _gdal.ColorEntry_c3_set)
+    if _newclass:
+        c3 = _swig_property(_gdal.ColorEntry_c3_get, _gdal.ColorEntry_c3_set)
     __swig_setmethods__["c4"] = _gdal.ColorEntry_c4_set
     __swig_getmethods__["c4"] = _gdal.ColorEntry_c4_get
-    if _newclass:c4 = _swig_property(_gdal.ColorEntry_c4_get, _gdal.ColorEntry_c4_set)
+    if _newclass:
+        c4 = _swig_property(_gdal.ColorEntry_c4_get, _gdal.ColorEntry_c4_set)
 ColorEntry_swigregister = _gdal.ColorEntry_swigregister
 ColorEntry_swigregister(ColorEntry)
 
 class GCP(_object):
-    """Proxy of C++ GDAL_GCP class"""
+    """Proxy of C++ GDAL_GCP class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GCP, name, value)
     __swig_getmethods__ = {}
@@ -1503,35 +1603,43 @@ class GCP(_object):
     __repr__ = _swig_repr
     __swig_setmethods__["GCPX"] = _gdal.GCP_GCPX_set
     __swig_getmethods__["GCPX"] = _gdal.GCP_GCPX_get
-    if _newclass:GCPX = _swig_property(_gdal.GCP_GCPX_get, _gdal.GCP_GCPX_set)
+    if _newclass:
+        GCPX = _swig_property(_gdal.GCP_GCPX_get, _gdal.GCP_GCPX_set)
     __swig_setmethods__["GCPY"] = _gdal.GCP_GCPY_set
     __swig_getmethods__["GCPY"] = _gdal.GCP_GCPY_get
-    if _newclass:GCPY = _swig_property(_gdal.GCP_GCPY_get, _gdal.GCP_GCPY_set)
+    if _newclass:
+        GCPY = _swig_property(_gdal.GCP_GCPY_get, _gdal.GCP_GCPY_set)
     __swig_setmethods__["GCPZ"] = _gdal.GCP_GCPZ_set
     __swig_getmethods__["GCPZ"] = _gdal.GCP_GCPZ_get
-    if _newclass:GCPZ = _swig_property(_gdal.GCP_GCPZ_get, _gdal.GCP_GCPZ_set)
+    if _newclass:
+        GCPZ = _swig_property(_gdal.GCP_GCPZ_get, _gdal.GCP_GCPZ_set)
     __swig_setmethods__["GCPPixel"] = _gdal.GCP_GCPPixel_set
     __swig_getmethods__["GCPPixel"] = _gdal.GCP_GCPPixel_get
-    if _newclass:GCPPixel = _swig_property(_gdal.GCP_GCPPixel_get, _gdal.GCP_GCPPixel_set)
+    if _newclass:
+        GCPPixel = _swig_property(_gdal.GCP_GCPPixel_get, _gdal.GCP_GCPPixel_set)
     __swig_setmethods__["GCPLine"] = _gdal.GCP_GCPLine_set
     __swig_getmethods__["GCPLine"] = _gdal.GCP_GCPLine_get
-    if _newclass:GCPLine = _swig_property(_gdal.GCP_GCPLine_get, _gdal.GCP_GCPLine_set)
+    if _newclass:
+        GCPLine = _swig_property(_gdal.GCP_GCPLine_get, _gdal.GCP_GCPLine_set)
     __swig_setmethods__["Info"] = _gdal.GCP_Info_set
     __swig_getmethods__["Info"] = _gdal.GCP_Info_get
-    if _newclass:Info = _swig_property(_gdal.GCP_Info_get, _gdal.GCP_Info_set)
+    if _newclass:
+        Info = _swig_property(_gdal.GCP_Info_get, _gdal.GCP_Info_set)
     __swig_setmethods__["Id"] = _gdal.GCP_Id_set
     __swig_getmethods__["Id"] = _gdal.GCP_Id_get
-    if _newclass:Id = _swig_property(_gdal.GCP_Id_get, _gdal.GCP_Id_set)
-    def __init__(self, *args): 
-        """
-        __init__(GDAL_GCP self, double x=0.0, double y=0.0, double z=0.0, double pixel=0.0, double line=0.0, char const * info="", 
-            char const * id="") -> GCP
-        """
+    if _newclass:
+        Id = _swig_property(_gdal.GCP_Id_get, _gdal.GCP_Id_set)
+
+    def __init__(self, *args):
+        """__init__(GDAL_GCP self, double x=0.0, double y=0.0, double z=0.0, double pixel=0.0, double line=0.0, char const * info, char const * id) -> GCP"""
         this = _gdal.new_GCP(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GCP
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def __str__(self):
       str = '%s (%.2fP,%.2fL) -> (%.7fE,%.7fN,%.2f) %s '\
             % (self.Id, self.GCPPixel, self.GCPLine,
@@ -1559,78 +1667,83 @@ GCP_swigregister(GCP)
 
 
 def GDAL_GCP_GCPX_get(*args):
-  """GDAL_GCP_GCPX_get(GCP gcp) -> double"""
-  return _gdal.GDAL_GCP_GCPX_get(*args)
+    """GDAL_GCP_GCPX_get(GCP gcp) -> double"""
+    return _gdal.GDAL_GCP_GCPX_get(*args)
 
 def GDAL_GCP_GCPX_set(*args):
-  """GDAL_GCP_GCPX_set(GCP gcp, double dfGCPX)"""
-  return _gdal.GDAL_GCP_GCPX_set(*args)
+    """GDAL_GCP_GCPX_set(GCP gcp, double dfGCPX)"""
+    return _gdal.GDAL_GCP_GCPX_set(*args)
 
 def GDAL_GCP_GCPY_get(*args):
-  """GDAL_GCP_GCPY_get(GCP gcp) -> double"""
-  return _gdal.GDAL_GCP_GCPY_get(*args)
+    """GDAL_GCP_GCPY_get(GCP gcp) -> double"""
+    return _gdal.GDAL_GCP_GCPY_get(*args)
 
 def GDAL_GCP_GCPY_set(*args):
-  """GDAL_GCP_GCPY_set(GCP gcp, double dfGCPY)"""
-  return _gdal.GDAL_GCP_GCPY_set(*args)
+    """GDAL_GCP_GCPY_set(GCP gcp, double dfGCPY)"""
+    return _gdal.GDAL_GCP_GCPY_set(*args)
 
 def GDAL_GCP_GCPZ_get(*args):
-  """GDAL_GCP_GCPZ_get(GCP gcp) -> double"""
-  return _gdal.GDAL_GCP_GCPZ_get(*args)
+    """GDAL_GCP_GCPZ_get(GCP gcp) -> double"""
+    return _gdal.GDAL_GCP_GCPZ_get(*args)
 
 def GDAL_GCP_GCPZ_set(*args):
-  """GDAL_GCP_GCPZ_set(GCP gcp, double dfGCPZ)"""
-  return _gdal.GDAL_GCP_GCPZ_set(*args)
+    """GDAL_GCP_GCPZ_set(GCP gcp, double dfGCPZ)"""
+    return _gdal.GDAL_GCP_GCPZ_set(*args)
 
 def GDAL_GCP_GCPPixel_get(*args):
-  """GDAL_GCP_GCPPixel_get(GCP gcp) -> double"""
-  return _gdal.GDAL_GCP_GCPPixel_get(*args)
+    """GDAL_GCP_GCPPixel_get(GCP gcp) -> double"""
+    return _gdal.GDAL_GCP_GCPPixel_get(*args)
 
 def GDAL_GCP_GCPPixel_set(*args):
-  """GDAL_GCP_GCPPixel_set(GCP gcp, double dfGCPPixel)"""
-  return _gdal.GDAL_GCP_GCPPixel_set(*args)
+    """GDAL_GCP_GCPPixel_set(GCP gcp, double dfGCPPixel)"""
+    return _gdal.GDAL_GCP_GCPPixel_set(*args)
 
 def GDAL_GCP_GCPLine_get(*args):
-  """GDAL_GCP_GCPLine_get(GCP gcp) -> double"""
-  return _gdal.GDAL_GCP_GCPLine_get(*args)
+    """GDAL_GCP_GCPLine_get(GCP gcp) -> double"""
+    return _gdal.GDAL_GCP_GCPLine_get(*args)
 
 def GDAL_GCP_GCPLine_set(*args):
-  """GDAL_GCP_GCPLine_set(GCP gcp, double dfGCPLine)"""
-  return _gdal.GDAL_GCP_GCPLine_set(*args)
+    """GDAL_GCP_GCPLine_set(GCP gcp, double dfGCPLine)"""
+    return _gdal.GDAL_GCP_GCPLine_set(*args)
 
 def GDAL_GCP_Info_get(*args):
-  """GDAL_GCP_Info_get(GCP gcp) -> char const *"""
-  return _gdal.GDAL_GCP_Info_get(*args)
+    """GDAL_GCP_Info_get(GCP gcp) -> char const *"""
+    return _gdal.GDAL_GCP_Info_get(*args)
 
 def GDAL_GCP_Info_set(*args):
-  """GDAL_GCP_Info_set(GCP gcp, char const * pszInfo)"""
-  return _gdal.GDAL_GCP_Info_set(*args)
+    """GDAL_GCP_Info_set(GCP gcp, char const * pszInfo)"""
+    return _gdal.GDAL_GCP_Info_set(*args)
 
 def GDAL_GCP_Id_get(*args):
-  """GDAL_GCP_Id_get(GCP gcp) -> char const *"""
-  return _gdal.GDAL_GCP_Id_get(*args)
+    """GDAL_GCP_Id_get(GCP gcp) -> char const *"""
+    return _gdal.GDAL_GCP_Id_get(*args)
 
 def GDAL_GCP_Id_set(*args):
-  """GDAL_GCP_Id_set(GCP gcp, char const * pszId)"""
-  return _gdal.GDAL_GCP_Id_set(*args)
+    """GDAL_GCP_Id_set(GCP gcp, char const * pszId)"""
+    return _gdal.GDAL_GCP_Id_set(*args)
 
 def GCPsToGeoTransform(*args):
-  """GCPsToGeoTransform(int nGCPs, int bApproxOK=1) -> RETURN_NONE"""
-  return _gdal.GCPsToGeoTransform(*args)
+    """GCPsToGeoTransform(int nGCPs, int bApproxOK=1) -> RETURN_NONE"""
+    return _gdal.GCPsToGeoTransform(*args)
 class VirtualMem(_object):
-    """Proxy of C++ CPLVirtualMemShadow class"""
+    """Proxy of C++ CPLVirtualMemShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, VirtualMem, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, VirtualMem, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_destroy__ = _gdal.delete_VirtualMem
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def GetAddr(self, *args):
         """GetAddr(VirtualMem self)"""
         return _gdal.VirtualMem_GetAddr(self, *args)
 
+
     def Pin(self, *args):
         """Pin(VirtualMem self, size_t start_offset=0, size_t nsize=0, int bWriteOp=0)"""
         return _gdal.VirtualMem_Pin(self, *args)
@@ -1639,27 +1752,34 @@ VirtualMem_swigregister = _gdal.VirtualMem_swigregister
 VirtualMem_swigregister(VirtualMem)
 
 class AsyncReader(_object):
-    """Proxy of C++ GDALAsyncReaderShadow class"""
+    """Proxy of C++ GDALAsyncReaderShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, AsyncReader, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, AsyncReader, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_destroy__ = _gdal.delete_AsyncReader
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def GetNextUpdatedRegion(self, *args):
         """GetNextUpdatedRegion(AsyncReader self, double timeout) -> GDALAsyncStatusType"""
         return _gdal.AsyncReader_GetNextUpdatedRegion(self, *args)
 
+
     def GetBuffer(self, *args):
         """GetBuffer(AsyncReader self)"""
         return _gdal.AsyncReader_GetBuffer(self, *args)
 
+
     def LockBuffer(self, *args):
         """LockBuffer(AsyncReader self, double timeout) -> int"""
         return _gdal.AsyncReader_LockBuffer(self, *args)
 
+
     def UnlockBuffer(self, *args):
         """UnlockBuffer(AsyncReader self)"""
         return _gdal.AsyncReader_UnlockBuffer(self, *args)
@@ -1668,195 +1788,223 @@ AsyncReader_swigregister = _gdal.AsyncReader_swigregister
 AsyncReader_swigregister(AsyncReader)
 
 class Dataset(MajorObject):
-    """Proxy of C++ GDALDatasetShadow class"""
+    """Proxy of C++ GDALDatasetShadow class."""
+
     __swig_setmethods__ = {}
-    for _s in [MajorObject]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
     __setattr__ = lambda self, name, value: _swig_setattr(self, Dataset, name, value)
     __swig_getmethods__ = {}
-    for _s in [MajorObject]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
     __getattr__ = lambda self, name: _swig_getattr(self, Dataset, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_getmethods__["RasterXSize"] = _gdal.Dataset_RasterXSize_get
-    if _newclass:RasterXSize = _swig_property(_gdal.Dataset_RasterXSize_get)
+    if _newclass:
+        RasterXSize = _swig_property(_gdal.Dataset_RasterXSize_get)
     __swig_getmethods__["RasterYSize"] = _gdal.Dataset_RasterYSize_get
-    if _newclass:RasterYSize = _swig_property(_gdal.Dataset_RasterYSize_get)
+    if _newclass:
+        RasterYSize = _swig_property(_gdal.Dataset_RasterYSize_get)
     __swig_getmethods__["RasterCount"] = _gdal.Dataset_RasterCount_get
-    if _newclass:RasterCount = _swig_property(_gdal.Dataset_RasterCount_get)
+    if _newclass:
+        RasterCount = _swig_property(_gdal.Dataset_RasterCount_get)
     __swig_destroy__ = _gdal.delete_Dataset
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def GetDriver(self, *args):
         """GetDriver(Dataset self) -> Driver"""
         return _gdal.Dataset_GetDriver(self, *args)
 
+
     def GetRasterBand(self, *args):
         """GetRasterBand(Dataset self, int nBand) -> Band"""
         return _gdal.Dataset_GetRasterBand(self, *args)
 
+
     def GetProjection(self, *args):
         """GetProjection(Dataset self) -> char const *"""
         return _gdal.Dataset_GetProjection(self, *args)
 
+
     def GetProjectionRef(self, *args):
         """GetProjectionRef(Dataset self) -> char const *"""
         return _gdal.Dataset_GetProjectionRef(self, *args)
 
+
     def SetProjection(self, *args):
         """SetProjection(Dataset self, char const * prj) -> CPLErr"""
         return _gdal.Dataset_SetProjection(self, *args)
 
+
     def GetGeoTransform(self, *args, **kwargs):
         """GetGeoTransform(Dataset self, int * can_return_null=None)"""
         return _gdal.Dataset_GetGeoTransform(self, *args, **kwargs)
 
+
     def SetGeoTransform(self, *args):
         """SetGeoTransform(Dataset self, double [6] argin) -> CPLErr"""
         return _gdal.Dataset_SetGeoTransform(self, *args)
 
+
     def BuildOverviews(self, *args, **kwargs):
-        """
-        BuildOverviews(Dataset self, char const * resampling="NEAREST", int overviewlist=0, GDALProgressFunc callback=0, 
-            void * callback_data=None) -> int
-        """
+        """BuildOverviews(Dataset self, char const * resampling, int overviewlist=0, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
         return _gdal.Dataset_BuildOverviews(self, *args, **kwargs)
 
+
     def GetGCPCount(self, *args):
         """GetGCPCount(Dataset self) -> int"""
         return _gdal.Dataset_GetGCPCount(self, *args)
 
+
     def GetGCPProjection(self, *args):
         """GetGCPProjection(Dataset self) -> char const *"""
         return _gdal.Dataset_GetGCPProjection(self, *args)
 
+
     def GetGCPs(self, *args):
         """GetGCPs(Dataset self)"""
         return _gdal.Dataset_GetGCPs(self, *args)
 
+
     def SetGCPs(self, *args):
         """SetGCPs(Dataset self, int nGCPs, char const * pszGCPProjection) -> CPLErr"""
         return _gdal.Dataset_SetGCPs(self, *args)
 
+
     def FlushCache(self, *args):
         """FlushCache(Dataset self)"""
         return _gdal.Dataset_FlushCache(self, *args)
 
+
     def AddBand(self, *args, **kwargs):
-        """AddBand(Dataset self, GDALDataType datatype=GDT_Byte, char ** options=None) -> CPLErr"""
+        """AddBand(Dataset self, GDALDataType datatype, char ** options=None) -> CPLErr"""
         return _gdal.Dataset_AddBand(self, *args, **kwargs)
 
+
     def CreateMaskBand(self, *args):
         """CreateMaskBand(Dataset self, int nFlags) -> CPLErr"""
         return _gdal.Dataset_CreateMaskBand(self, *args)
 
+
     def GetFileList(self, *args):
         """GetFileList(Dataset self) -> char **"""
         return _gdal.Dataset_GetFileList(self, *args)
 
+
     def WriteRaster(self, *args, **kwargs):
-        """
-        WriteRaster(Dataset self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, 
-            int * buf_ysize=None, GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None, 
-            GIntBig * buf_line_space=None, GIntBig * buf_band_space=None) -> CPLErr
-        """
+        """WriteRaster(Dataset self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, int * buf_ysize=None, GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None, GIntBig * buf_band_space=None) -> CPLErr"""
         return _gdal.Dataset_WriteRaster(self, *args, **kwargs)
 
+
     def BeginAsyncReader(self, *args, **kwargs):
-        """
-        BeginAsyncReader(Dataset self, int xOff, int yOff, int xSize, int ySize, int buf_len, int buf_xsize, int buf_ysize, 
-            GDALDataType bufType=(GDALDataType) 0, int band_list=0, int nPixelSpace=0, 
-            int nLineSpace=0, int nBandSpace=0, char ** options=None) -> AsyncReader
-        """
+        """BeginAsyncReader(Dataset self, int xOff, int yOff, int xSize, int ySize, int buf_len, int buf_xsize, int buf_ysize, GDALDataType bufType, int band_list=0, int nPixelSpace=0, int nLineSpace=0, int nBandSpace=0, char ** options=None) -> AsyncReader"""
         return _gdal.Dataset_BeginAsyncReader(self, *args, **kwargs)
 
+
     def EndAsyncReader(self, *args):
         """EndAsyncReader(Dataset self, AsyncReader ario)"""
         return _gdal.Dataset_EndAsyncReader(self, *args)
 
+
     def GetVirtualMem(self, *args, **kwargs):
-        """
-        GetVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, 
-            int nBufYSize, GDALDataType eBufType, int band_list, int bIsBandSequential, 
-            size_t nCacheSize, size_t nPageSizeHint, char ** options=None) -> VirtualMem
-        """
+        """GetVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize, GDALDataType eBufType, int band_list, int bIsBandSequential, size_t nCacheSize, size_t nPageSizeHint, char ** options=None) -> VirtualMem"""
         return _gdal.Dataset_GetVirtualMem(self, *args, **kwargs)
 
+
     def GetTiledVirtualMem(self, *args, **kwargs):
-        """
-        GetTiledVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, 
-            int nTileYSize, GDALDataType eBufType, int band_list, GDALTileOrganization eTileOrganization, 
-            size_t nCacheSize, char ** options=None) -> VirtualMem
-        """
+        """GetTiledVirtualMem(Dataset self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, int nTileYSize, GDALDataType eBufType, int band_list, GDALTileOrganization eTileOrganization, size_t nCacheSize, char ** options=None) -> VirtualMem"""
         return _gdal.Dataset_GetTiledVirtualMem(self, *args, **kwargs)
 
+
     def CreateLayer(self, *args, **kwargs):
-        """
-        CreateLayer(Dataset self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type=wkbUnknown, 
-            char ** options=None) -> Layer
-        """
+        """CreateLayer(Dataset self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type, char ** options=None) -> Layer"""
         return _gdal.Dataset_CreateLayer(self, *args, **kwargs)
 
+
     def CopyLayer(self, *args, **kwargs):
         """CopyLayer(Dataset self, Layer src_layer, char const * new_name, char ** options=None) -> Layer"""
         return _gdal.Dataset_CopyLayer(self, *args, **kwargs)
 
+
     def DeleteLayer(self, *args):
         """DeleteLayer(Dataset self, int index) -> OGRErr"""
         return _gdal.Dataset_DeleteLayer(self, *args)
 
+
     def GetLayerCount(self, *args):
         """GetLayerCount(Dataset self) -> int"""
         return _gdal.Dataset_GetLayerCount(self, *args)
 
+
     def GetLayerByIndex(self, *args):
         """GetLayerByIndex(Dataset self, int index=0) -> Layer"""
         return _gdal.Dataset_GetLayerByIndex(self, *args)
 
+
     def GetLayerByName(self, *args):
         """GetLayerByName(Dataset self, char const * layer_name) -> Layer"""
         return _gdal.Dataset_GetLayerByName(self, *args)
 
+
+    def ResetReading(self, *args):
+        """ResetReading(Dataset self)"""
+        return _gdal.Dataset_ResetReading(self, *args)
+
+
+    def GetNextFeature(self, *args, **kwargs):
+        """GetNextFeature(Dataset self, bool include_layer=True, bool include_pct=False, GDALProgressFunc callback=0, void * callback_data=None) -> Feature"""
+        return _gdal.Dataset_GetNextFeature(self, *args, **kwargs)
+
+
     def TestCapability(self, *args):
         """TestCapability(Dataset self, char const * cap) -> bool"""
         return _gdal.Dataset_TestCapability(self, *args)
 
+
     def ExecuteSQL(self, *args, **kwargs):
-        """ExecuteSQL(Dataset self, char const * statement, Geometry spatialFilter=None, char const * dialect="") -> Layer"""
+        """ExecuteSQL(Dataset self, char const * statement, Geometry spatialFilter=None, char const * dialect) -> Layer"""
         return _gdal.Dataset_ExecuteSQL(self, *args, **kwargs)
 
+
     def ReleaseResultSet(self, *args):
         """ReleaseResultSet(Dataset self, Layer layer)"""
         return _gdal.Dataset_ReleaseResultSet(self, *args)
 
+
     def GetStyleTable(self, *args):
         """GetStyleTable(Dataset self) -> StyleTable"""
         return _gdal.Dataset_GetStyleTable(self, *args)
 
+
     def SetStyleTable(self, *args):
         """SetStyleTable(Dataset self, StyleTable table)"""
         return _gdal.Dataset_SetStyleTable(self, *args)
 
+
     def StartTransaction(self, *args, **kwargs):
         """StartTransaction(Dataset self, int force=False) -> OGRErr"""
         return _gdal.Dataset_StartTransaction(self, *args, **kwargs)
 
+
     def CommitTransaction(self, *args):
         """CommitTransaction(Dataset self) -> OGRErr"""
         return _gdal.Dataset_CommitTransaction(self, *args)
 
+
     def RollbackTransaction(self, *args):
         """RollbackTransaction(Dataset self) -> OGRErr"""
         return _gdal.Dataset_RollbackTransaction(self, *args)
 
+
     def ReadRaster1(self, *args, **kwargs):
-        """
-        ReadRaster1(Dataset self, int xoff, int yoff, int xsize, int ysize, int * buf_xsize=None, int * buf_ysize=None, 
-            GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None, 
-            GIntBig * buf_line_space=None, GIntBig * buf_band_space=None, GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour, 
-            GDALProgressFunc callback=0, 
-            void * callback_data=None) -> CPLErr
-        """
+        """ReadRaster1(Dataset self, int xoff, int yoff, int xsize, int ysize, int * buf_xsize=None, int * buf_ysize=None, GDALDataType * buf_type=None, int band_list=0, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None, GIntBig * buf_band_space=None, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
         return _gdal.Dataset_ReadRaster1(self, *args, **kwargs)
 
+
+
     def ReadAsArray(self, xoff=0, yoff=0, xsize=None, ysize=None, buf_obj=None,
                     buf_xsize = None, buf_ysize = None, buf_type = None,
                     resample_alg = GRIORA_NearestNeighbour,
@@ -2049,247 +2197,309 @@ Dataset_swigregister = _gdal.Dataset_swigregister
 Dataset_swigregister(Dataset)
 
 class Band(MajorObject):
-    """Proxy of C++ GDALRasterBandShadow class"""
+    """Proxy of C++ GDALRasterBandShadow class."""
+
     __swig_setmethods__ = {}
-    for _s in [MajorObject]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
     __setattr__ = lambda self, name, value: _swig_setattr(self, Band, name, value)
     __swig_getmethods__ = {}
-    for _s in [MajorObject]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
     __getattr__ = lambda self, name: _swig_getattr(self, Band, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_getmethods__["XSize"] = _gdal.Band_XSize_get
-    if _newclass:XSize = _swig_property(_gdal.Band_XSize_get)
+    if _newclass:
+        XSize = _swig_property(_gdal.Band_XSize_get)
     __swig_getmethods__["YSize"] = _gdal.Band_YSize_get
-    if _newclass:YSize = _swig_property(_gdal.Band_YSize_get)
+    if _newclass:
+        YSize = _swig_property(_gdal.Band_YSize_get)
     __swig_getmethods__["DataType"] = _gdal.Band_DataType_get
-    if _newclass:DataType = _swig_property(_gdal.Band_DataType_get)
+    if _newclass:
+        DataType = _swig_property(_gdal.Band_DataType_get)
+
     def GetDataset(self, *args):
         """GetDataset(Band self) -> Dataset"""
         return _gdal.Band_GetDataset(self, *args)
 
+
     def GetBand(self, *args):
         """GetBand(Band self) -> int"""
         return _gdal.Band_GetBand(self, *args)
 
+
     def GetBlockSize(self, *args):
         """GetBlockSize(Band self)"""
         return _gdal.Band_GetBlockSize(self, *args)
 
+
+    def GetActualBlockSize(self, *args):
+        """GetActualBlockSize(Band self, int nXBlockOff, int nYBlockOff)"""
+        return _gdal.Band_GetActualBlockSize(self, *args)
+
+
     def GetColorInterpretation(self, *args):
         """GetColorInterpretation(Band self) -> GDALColorInterp"""
         return _gdal.Band_GetColorInterpretation(self, *args)
 
+
     def GetRasterColorInterpretation(self, *args):
         """GetRasterColorInterpretation(Band self) -> GDALColorInterp"""
         return _gdal.Band_GetRasterColorInterpretation(self, *args)
 
+
     def SetColorInterpretation(self, *args):
         """SetColorInterpretation(Band self, GDALColorInterp val) -> CPLErr"""
         return _gdal.Band_SetColorInterpretation(self, *args)
 
+
     def SetRasterColorInterpretation(self, *args):
         """SetRasterColorInterpretation(Band self, GDALColorInterp val) -> CPLErr"""
         return _gdal.Band_SetRasterColorInterpretation(self, *args)
 
+
     def GetNoDataValue(self, *args):
         """GetNoDataValue(Band self)"""
         return _gdal.Band_GetNoDataValue(self, *args)
 
+
     def SetNoDataValue(self, *args):
         """SetNoDataValue(Band self, double d) -> CPLErr"""
         return _gdal.Band_SetNoDataValue(self, *args)
 
+
     def DeleteNoDataValue(self, *args):
         """DeleteNoDataValue(Band self) -> CPLErr"""
         return _gdal.Band_DeleteNoDataValue(self, *args)
 
+
     def GetUnitType(self, *args):
         """GetUnitType(Band self) -> char const *"""
         return _gdal.Band_GetUnitType(self, *args)
 
+
     def SetUnitType(self, *args):
         """SetUnitType(Band self, char const * val) -> CPLErr"""
         return _gdal.Band_SetUnitType(self, *args)
 
+
     def GetRasterCategoryNames(self, *args):
         """GetRasterCategoryNames(Band self) -> char **"""
         return _gdal.Band_GetRasterCategoryNames(self, *args)
 
+
     def SetRasterCategoryNames(self, *args):
         """SetRasterCategoryNames(Band self, char ** names) -> CPLErr"""
         return _gdal.Band_SetRasterCategoryNames(self, *args)
 
+
     def GetMinimum(self, *args):
         """GetMinimum(Band self)"""
         return _gdal.Band_GetMinimum(self, *args)
 
+
     def GetMaximum(self, *args):
         """GetMaximum(Band self)"""
         return _gdal.Band_GetMaximum(self, *args)
 
+
     def GetOffset(self, *args):
         """GetOffset(Band self)"""
         return _gdal.Band_GetOffset(self, *args)
 
+
     def GetScale(self, *args):
         """GetScale(Band self)"""
         return _gdal.Band_GetScale(self, *args)
 
+
     def SetOffset(self, *args):
         """SetOffset(Band self, double val) -> CPLErr"""
         return _gdal.Band_SetOffset(self, *args)
 
+
     def SetScale(self, *args):
         """SetScale(Band self, double val) -> CPLErr"""
         return _gdal.Band_SetScale(self, *args)
 
+
     def GetStatistics(self, *args):
         """GetStatistics(Band self, int approx_ok, int force) -> CPLErr"""
         return _gdal.Band_GetStatistics(self, *args)
 
+
     def ComputeStatistics(self, *args):
         """ComputeStatistics(Band self, bool approx_ok, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
         return _gdal.Band_ComputeStatistics(self, *args)
 
+
     def SetStatistics(self, *args):
         """SetStatistics(Band self, double min, double max, double mean, double stddev) -> CPLErr"""
         return _gdal.Band_SetStatistics(self, *args)
 
+
     def GetOverviewCount(self, *args):
         """GetOverviewCount(Band self) -> int"""
         return _gdal.Band_GetOverviewCount(self, *args)
 
+
     def GetOverview(self, *args):
         """GetOverview(Band self, int i) -> Band"""
         return _gdal.Band_GetOverview(self, *args)
 
+
     def Checksum(self, *args, **kwargs):
         """Checksum(Band self, int xoff=0, int yoff=0, int * xsize=None, int * ysize=None) -> int"""
         return _gdal.Band_Checksum(self, *args, **kwargs)
 
+
     def ComputeRasterMinMax(self, *args):
         """ComputeRasterMinMax(Band self, int approx_ok=0)"""
         return _gdal.Band_ComputeRasterMinMax(self, *args)
 
+
     def ComputeBandStats(self, *args):
         """ComputeBandStats(Band self, int samplestep=1)"""
         return _gdal.Band_ComputeBandStats(self, *args)
 
+
     def Fill(self, *args):
         """Fill(Band self, double real_fill, double imag_fill=0.0) -> CPLErr"""
         return _gdal.Band_Fill(self, *args)
 
+
     def WriteRaster(self, *args, **kwargs):
-        """
-        WriteRaster(Band self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, 
-            int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None, 
-            GIntBig * buf_line_space=None) -> CPLErr
-        """
+        """WriteRaster(Band self, int xoff, int yoff, int xsize, int ysize, GIntBig buf_len, int * buf_xsize=None, int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None) -> CPLErr"""
         return _gdal.Band_WriteRaster(self, *args, **kwargs)
 
+
     def FlushCache(self, *args):
         """FlushCache(Band self)"""
         return _gdal.Band_FlushCache(self, *args)
 
+
     def GetRasterColorTable(self, *args):
         """GetRasterColorTable(Band self) -> ColorTable"""
         return _gdal.Band_GetRasterColorTable(self, *args)
 
+
     def GetColorTable(self, *args):
         """GetColorTable(Band self) -> ColorTable"""
         return _gdal.Band_GetColorTable(self, *args)
 
+
     def SetRasterColorTable(self, *args):
         """SetRasterColorTable(Band self, ColorTable arg) -> int"""
         return _gdal.Band_SetRasterColorTable(self, *args)
 
+
     def SetColorTable(self, *args):
         """SetColorTable(Band self, ColorTable arg) -> int"""
         return _gdal.Band_SetColorTable(self, *args)
 
+
     def GetDefaultRAT(self, *args):
         """GetDefaultRAT(Band self) -> RasterAttributeTable"""
         return _gdal.Band_GetDefaultRAT(self, *args)
 
+
     def SetDefaultRAT(self, *args):
         """SetDefaultRAT(Band self, RasterAttributeTable table) -> int"""
         return _gdal.Band_SetDefaultRAT(self, *args)
 
+
     def GetMaskBand(self, *args):
         """GetMaskBand(Band self) -> Band"""
         return _gdal.Band_GetMaskBand(self, *args)
 
+
     def GetMaskFlags(self, *args):
         """GetMaskFlags(Band self) -> int"""
         return _gdal.Band_GetMaskFlags(self, *args)
 
+
     def CreateMaskBand(self, *args):
         """CreateMaskBand(Band self, int nFlags) -> CPLErr"""
         return _gdal.Band_CreateMaskBand(self, *args)
 
+
     def GetHistogram(self, *args, **kwargs):
-        """
-        GetHistogram(Band self, double min=-0.5, double max=255.5, int buckets=256, int include_out_of_range=0, int approx_ok=1, 
-            GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr
-        """
+        """GetHistogram(Band self, double min=-0.5, double max=255.5, int buckets=256, int include_out_of_range=0, int approx_ok=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
         return _gdal.Band_GetHistogram(self, *args, **kwargs)
 
+
     def GetDefaultHistogram(self, *args, **kwargs):
-        """
-        GetDefaultHistogram(Band self, double * min_ret=None, double * max_ret=None, int * buckets_ret=None, GUIntBig ** ppanHistogram=None, 
-            int force=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr
-        """
+        """GetDefaultHistogram(Band self, double * min_ret=None, double * max_ret=None, int * buckets_ret=None, GUIntBig ** ppanHistogram=None, int force=1, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
         return _gdal.Band_GetDefaultHistogram(self, *args, **kwargs)
 
+
     def SetDefaultHistogram(self, *args):
         """SetDefaultHistogram(Band self, double min, double max, int buckets_in) -> CPLErr"""
         return _gdal.Band_SetDefaultHistogram(self, *args)
 
+
     def HasArbitraryOverviews(self, *args):
         """HasArbitraryOverviews(Band self) -> bool"""
         return _gdal.Band_HasArbitraryOverviews(self, *args)
 
+
     def GetCategoryNames(self, *args):
         """GetCategoryNames(Band self) -> char **"""
         return _gdal.Band_GetCategoryNames(self, *args)
 
+
     def SetCategoryNames(self, *args):
         """SetCategoryNames(Band self, char ** papszCategoryNames) -> CPLErr"""
         return _gdal.Band_SetCategoryNames(self, *args)
 
+
     def GetVirtualMem(self, *args, **kwargs):
-        """
-        GetVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, 
-            int nBufYSize, GDALDataType eBufType, size_t nCacheSize, size_t nPageSizeHint, 
-            char ** options=None) -> VirtualMem
-        """
+        """GetVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nBufXSize, int nBufYSize, GDALDataType eBufType, size_t nCacheSize, size_t nPageSizeHint, char ** options=None) -> VirtualMem"""
         return _gdal.Band_GetVirtualMem(self, *args, **kwargs)
 
+
     def GetVirtualMemAuto(self, *args, **kwargs):
         """GetVirtualMemAuto(Band self, GDALRWFlag eRWFlag, char ** options=None) -> VirtualMem"""
         return _gdal.Band_GetVirtualMemAuto(self, *args, **kwargs)
 
+
     def GetTiledVirtualMem(self, *args, **kwargs):
-        """
-        GetTiledVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, 
-            int nTileYSize, GDALDataType eBufType, size_t nCacheSize, char ** options=None) -> VirtualMem
-        """
+        """GetTiledVirtualMem(Band self, GDALRWFlag eRWFlag, int nXOff, int nYOff, int nXSize, int nYSize, int nTileXSize, int nTileYSize, GDALDataType eBufType, size_t nCacheSize, char ** options=None) -> VirtualMem"""
         return _gdal.Band_GetTiledVirtualMem(self, *args, **kwargs)
 
+
+    def GetDataCoverageStatus(self, *args):
+        """GetDataCoverageStatus(Band self, int nXOff, int nYOff, int nXSize, int nYSize, int nMaskFlagStop=0) -> int"""
+        return _gdal.Band_GetDataCoverageStatus(self, *args)
+
+
     def ReadRaster1(self, *args, **kwargs):
-        """
-        ReadRaster1(Band self, double xoff, double yoff, double xsize, double ysize, int * buf_xsize=None, int * buf_ysize=None, 
-            int * buf_type=None, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None, 
-            GDALRIOResampleAlg resample_alg=GRIORA_NearestNeighbour, 
-            GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr
-        """
+        """ReadRaster1(Band self, double xoff, double yoff, double xsize, double ysize, int * buf_xsize=None, int * buf_ysize=None, int * buf_type=None, GIntBig * buf_pixel_space=None, GIntBig * buf_line_space=None, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
         return _gdal.Band_ReadRaster1(self, *args, **kwargs)
 
+
     def ReadBlock(self, *args, **kwargs):
         """ReadBlock(Band self, int xoff, int yoff) -> CPLErr"""
         return _gdal.Band_ReadBlock(self, *args, **kwargs)
 
+
+
+    def ComputeStatistics(self, approx_ok):
+      """ComputeStatistics(Band self, bool approx_ok, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
+
+    # For backward compatibility. New SWIG has stricter typing and really
+    # enforces bool
+      if approx_ok == 0:
+          approx_ok = False
+      elif approx_ok == 1:
+          approx_ok = True
+
+      return _gdal.Band_ComputeStatistics(self, approx_ok)
+
+
     def ReadRaster(self, xoff = 0, yoff = 0, xsize = None, ysize = None,
                      buf_xsize = None, buf_ysize = None, buf_type = None,
                      buf_pixel_space = None, buf_line_space = None,
@@ -2406,43 +2616,54 @@ Band_swigregister = _gdal.Band_swigregister
 Band_swigregister(Band)
 
 class ColorTable(_object):
-    """Proxy of C++ GDALColorTableShadow class"""
+    """Proxy of C++ GDALColorTableShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, ColorTable, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, ColorTable, name)
     __repr__ = _swig_repr
-    def __init__(self, *args, **kwargs): 
-        """__init__(GDALColorTableShadow self, GDALPaletteInterp palette=GPI_RGB) -> ColorTable"""
+
+    def __init__(self, *args, **kwargs):
+        """__init__(GDALColorTableShadow self, GDALPaletteInterp palette) -> ColorTable"""
         this = _gdal.new_ColorTable(*args, **kwargs)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_ColorTable
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def Clone(self, *args):
         """Clone(ColorTable self) -> ColorTable"""
         return _gdal.ColorTable_Clone(self, *args)
 
+
     def GetPaletteInterpretation(self, *args):
         """GetPaletteInterpretation(ColorTable self) -> GDALPaletteInterp"""
         return _gdal.ColorTable_GetPaletteInterpretation(self, *args)
 
+
     def GetCount(self, *args):
         """GetCount(ColorTable self) -> int"""
         return _gdal.ColorTable_GetCount(self, *args)
 
+
     def GetColorEntry(self, *args):
         """GetColorEntry(ColorTable self, int entry) -> ColorEntry"""
         return _gdal.ColorTable_GetColorEntry(self, *args)
 
+
     def GetColorEntryAsRGB(self, *args):
         """GetColorEntryAsRGB(ColorTable self, int entry, ColorEntry centry) -> int"""
         return _gdal.ColorTable_GetColorEntryAsRGB(self, *args)
 
+
     def SetColorEntry(self, *args):
         """SetColorEntry(ColorTable self, int entry, ColorEntry centry)"""
         return _gdal.ColorTable_SetColorEntry(self, *args)
 
+
     def CreateColorRamp(self, *args):
         """CreateColorRamp(ColorTable self, int nStartIndex, ColorEntry startcolor, int nEndIndex, ColorEntry endcolor)"""
         return _gdal.ColorTable_CreateColorRamp(self, *args)
@@ -2451,99 +2672,124 @@ ColorTable_swigregister = _gdal.ColorTable_swigregister
 ColorTable_swigregister(ColorTable)
 
 class RasterAttributeTable(_object):
-    """Proxy of C++ GDALRasterAttributeTableShadow class"""
+    """Proxy of C++ GDALRasterAttributeTableShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, RasterAttributeTable, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, RasterAttributeTable, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALRasterAttributeTableShadow self) -> RasterAttributeTable"""
         this = _gdal.new_RasterAttributeTable(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_RasterAttributeTable
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def Clone(self, *args):
         """Clone(RasterAttributeTable self) -> RasterAttributeTable"""
         return _gdal.RasterAttributeTable_Clone(self, *args)
 
+
     def GetColumnCount(self, *args):
         """GetColumnCount(RasterAttributeTable self) -> int"""
         return _gdal.RasterAttributeTable_GetColumnCount(self, *args)
 
+
     def GetNameOfCol(self, *args):
         """GetNameOfCol(RasterAttributeTable self, int iCol) -> char const *"""
         return _gdal.RasterAttributeTable_GetNameOfCol(self, *args)
 
+
     def GetUsageOfCol(self, *args):
         """GetUsageOfCol(RasterAttributeTable self, int iCol) -> GDALRATFieldUsage"""
         return _gdal.RasterAttributeTable_GetUsageOfCol(self, *args)
 
+
     def GetTypeOfCol(self, *args):
         """GetTypeOfCol(RasterAttributeTable self, int iCol) -> GDALRATFieldType"""
         return _gdal.RasterAttributeTable_GetTypeOfCol(self, *args)
 
+
     def GetColOfUsage(self, *args):
         """GetColOfUsage(RasterAttributeTable self, GDALRATFieldUsage eUsage) -> int"""
         return _gdal.RasterAttributeTable_GetColOfUsage(self, *args)
 
+
     def GetRowCount(self, *args):
         """GetRowCount(RasterAttributeTable self) -> int"""
         return _gdal.RasterAttributeTable_GetRowCount(self, *args)
 
+
     def GetValueAsString(self, *args):
         """GetValueAsString(RasterAttributeTable self, int iRow, int iCol) -> char const *"""
         return _gdal.RasterAttributeTable_GetValueAsString(self, *args)
 
+
     def GetValueAsInt(self, *args):
         """GetValueAsInt(RasterAttributeTable self, int iRow, int iCol) -> int"""
         return _gdal.RasterAttributeTable_GetValueAsInt(self, *args)
 
+
     def GetValueAsDouble(self, *args):
         """GetValueAsDouble(RasterAttributeTable self, int iRow, int iCol) -> double"""
         return _gdal.RasterAttributeTable_GetValueAsDouble(self, *args)
 
+
     def SetValueAsString(self, *args):
         """SetValueAsString(RasterAttributeTable self, int iRow, int iCol, char const * pszValue)"""
         return _gdal.RasterAttributeTable_SetValueAsString(self, *args)
 
+
     def SetValueAsInt(self, *args):
         """SetValueAsInt(RasterAttributeTable self, int iRow, int iCol, int nValue)"""
         return _gdal.RasterAttributeTable_SetValueAsInt(self, *args)
 
+
     def SetValueAsDouble(self, *args):
         """SetValueAsDouble(RasterAttributeTable self, int iRow, int iCol, double dfValue)"""
         return _gdal.RasterAttributeTable_SetValueAsDouble(self, *args)
 
+
     def SetRowCount(self, *args):
         """SetRowCount(RasterAttributeTable self, int nCount)"""
         return _gdal.RasterAttributeTable_SetRowCount(self, *args)
 
+
     def CreateColumn(self, *args):
         """CreateColumn(RasterAttributeTable self, char const * pszName, GDALRATFieldType eType, GDALRATFieldUsage eUsage) -> int"""
         return _gdal.RasterAttributeTable_CreateColumn(self, *args)
 
+
     def GetLinearBinning(self, *args):
         """GetLinearBinning(RasterAttributeTable self) -> bool"""
         return _gdal.RasterAttributeTable_GetLinearBinning(self, *args)
 
+
     def SetLinearBinning(self, *args):
         """SetLinearBinning(RasterAttributeTable self, double dfRow0Min, double dfBinSize) -> int"""
         return _gdal.RasterAttributeTable_SetLinearBinning(self, *args)
 
+
     def GetRowOfValue(self, *args):
         """GetRowOfValue(RasterAttributeTable self, double dfValue) -> int"""
         return _gdal.RasterAttributeTable_GetRowOfValue(self, *args)
 
+
     def ChangesAreWrittenToFile(self, *args):
         """ChangesAreWrittenToFile(RasterAttributeTable self) -> int"""
         return _gdal.RasterAttributeTable_ChangesAreWrittenToFile(self, *args)
 
+
     def DumpReadable(self, *args):
         """DumpReadable(RasterAttributeTable self)"""
         return _gdal.RasterAttributeTable_DumpReadable(self, *args)
 
+
     def WriteArray(self, array, field, start=0):
         import gdalnumeric
 
@@ -2559,136 +2805,86 @@ RasterAttributeTable_swigregister(RasterAttributeTable)
 
 
 def TermProgress_nocb(*args, **kwargs):
-  """TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"""
-  return _gdal.TermProgress_nocb(*args, **kwargs)
+    """TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"""
+    return _gdal.TermProgress_nocb(*args, **kwargs)
+
+_gdal.TermProgress_swigconstant(_gdal)
 TermProgress = _gdal.TermProgress
 
 def ComputeMedianCutPCT(*args, **kwargs):
-  """
-    ComputeMedianCutPCT(Band red, Band green, Band blue, int num_colors, ColorTable colors, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.ComputeMedianCutPCT(*args, **kwargs)
-ComputeMedianCutPCT = _gdal.ComputeMedianCutPCT
+    """ComputeMedianCutPCT(Band red, Band green, Band blue, int num_colors, ColorTable colors, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.ComputeMedianCutPCT(*args, **kwargs)
 
 def DitherRGB2PCT(*args, **kwargs):
-  """
-    DitherRGB2PCT(Band red, Band green, Band blue, Band target, ColorTable colors, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.DitherRGB2PCT(*args, **kwargs)
-DitherRGB2PCT = _gdal.DitherRGB2PCT
+    """DitherRGB2PCT(Band red, Band green, Band blue, Band target, ColorTable colors, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.DitherRGB2PCT(*args, **kwargs)
 
 def ReprojectImage(*args, **kwargs):
-  """
-    ReprojectImage(Dataset src_ds, Dataset dst_ds, char const * src_wkt=None, char const * dst_wkt=None, 
-        GDALResampleAlg eResampleAlg=GRA_NearestNeighbour, double WarpMemoryLimit=0.0, 
-        double maxerror=0.0, GDALProgressFunc callback=0, void * callback_data=None, 
-        char ** options=None) -> CPLErr
-    """
-  return _gdal.ReprojectImage(*args, **kwargs)
-ReprojectImage = _gdal.ReprojectImage
+    """ReprojectImage(Dataset src_ds, Dataset dst_ds, char const * src_wkt=None, char const * dst_wkt=None, GDALResampleAlg eResampleAlg, double WarpMemoryLimit=0.0, double maxerror=0.0, GDALProgressFunc callback=0, void * callback_data=None, char ** options=None) -> CPLErr"""
+    return _gdal.ReprojectImage(*args, **kwargs)
 
 def ComputeProximity(*args, **kwargs):
-  """
-    ComputeProximity(Band srcBand, Band proximityBand, char ** options=None, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.ComputeProximity(*args, **kwargs)
-ComputeProximity = _gdal.ComputeProximity
+    """ComputeProximity(Band srcBand, Band proximityBand, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.ComputeProximity(*args, **kwargs)
 
 def RasterizeLayer(*args, **kwargs):
-  """
-    RasterizeLayer(Dataset dataset, int bands, Layer layer, void * pfnTransformer=None, void * pTransformArg=None, 
-        int burn_values=0, char ** options=None, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.RasterizeLayer(*args, **kwargs)
-RasterizeLayer = _gdal.RasterizeLayer
+    """RasterizeLayer(Dataset dataset, int bands, Layer layer, void * pfnTransformer=None, void * pTransformArg=None, int burn_values=0, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.RasterizeLayer(*args, **kwargs)
 
 def Polygonize(*args, **kwargs):
-  """
-    Polygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, 
-        GDALProgressFunc callback=0, void * callback_data=None) -> int
-    """
-  return _gdal.Polygonize(*args, **kwargs)
-Polygonize = _gdal.Polygonize
+    """Polygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.Polygonize(*args, **kwargs)
 
 def FPolygonize(*args, **kwargs):
-  """
-    FPolygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, 
-        GDALProgressFunc callback=0, void * callback_data=None) -> int
-    """
-  return _gdal.FPolygonize(*args, **kwargs)
-FPolygonize = _gdal.FPolygonize
+    """FPolygonize(Band srcBand, Band maskBand, Layer outLayer, int iPixValField, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.FPolygonize(*args, **kwargs)
 
 def FillNodata(*args, **kwargs):
-  """
-    FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations, char ** options=None, 
-        GDALProgressFunc callback=0, void * callback_data=None) -> int
-    """
-  return _gdal.FillNodata(*args, **kwargs)
-FillNodata = _gdal.FillNodata
+    """FillNodata(Band targetBand, Band maskBand, double maxSearchDist, int smoothingIterations, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.FillNodata(*args, **kwargs)
 
 def SieveFilter(*args, **kwargs):
-  """
-    SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness=4, char ** options=None, 
-        GDALProgressFunc callback=0, void * callback_data=None) -> int
-    """
-  return _gdal.SieveFilter(*args, **kwargs)
-SieveFilter = _gdal.SieveFilter
+    """SieveFilter(Band srcBand, Band maskBand, Band dstBand, int threshold, int connectedness=4, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.SieveFilter(*args, **kwargs)
 
 def RegenerateOverviews(*args, **kwargs):
-  """
-    RegenerateOverviews(Band srcBand, int overviewBandCount, char const * resampling="average", GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.RegenerateOverviews(*args, **kwargs)
-RegenerateOverviews = _gdal.RegenerateOverviews
+    """RegenerateOverviews(Band srcBand, int overviewBandCount, char const * resampling, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.RegenerateOverviews(*args, **kwargs)
 
 def RegenerateOverview(*args, **kwargs):
-  """
-    RegenerateOverview(Band srcBand, Band overviewBand, char const * resampling="average", GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.RegenerateOverview(*args, **kwargs)
-RegenerateOverview = _gdal.RegenerateOverview
+    """RegenerateOverview(Band srcBand, Band overviewBand, char const * resampling, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.RegenerateOverview(*args, **kwargs)
 
 def ContourGenerate(*args, **kwargs):
-  """
-    ContourGenerate(Band srcBand, double contourInterval, double contourBase, int fixedLevelCount, int useNoData, 
-        double noDataValue, Layer dstLayer, int idField, int elevField, 
-        GDALProgressFunc callback=0, void * callback_data=None) -> int
-    """
-  return _gdal.ContourGenerate(*args, **kwargs)
-ContourGenerate = _gdal.ContourGenerate
+    """ContourGenerate(Band srcBand, double contourInterval, double contourBase, int fixedLevelCount, int useNoData, double noDataValue, Layer dstLayer, int idField, int elevField, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.ContourGenerate(*args, **kwargs)
 
 def AutoCreateWarpedVRT(*args):
-  """
-    AutoCreateWarpedVRT(Dataset src_ds, char const * src_wkt=None, char const * dst_wkt=None, GDALResampleAlg eResampleAlg=GRA_NearestNeighbour, 
-        double maxerror=0.0) -> Dataset
-    """
-  return _gdal.AutoCreateWarpedVRT(*args)
-AutoCreateWarpedVRT = _gdal.AutoCreateWarpedVRT
+    """AutoCreateWarpedVRT(Dataset src_ds, char const * src_wkt=None, char const * dst_wkt=None, GDALResampleAlg eResampleAlg, double maxerror=0.0) -> Dataset"""
+    return _gdal.AutoCreateWarpedVRT(*args)
 
 def CreatePansharpenedVRT(*args):
-  """CreatePansharpenedVRT(char const * pszXML, Band panchroBand, int nInputSpectralBands) -> Dataset"""
-  return _gdal.CreatePansharpenedVRT(*args)
-CreatePansharpenedVRT = _gdal.CreatePansharpenedVRT
+    """CreatePansharpenedVRT(char const * pszXML, Band panchroBand, int nInputSpectralBands) -> Dataset"""
+    return _gdal.CreatePansharpenedVRT(*args)
 class Transformer(_object):
-    """Proxy of C++ GDALTransformerInfoShadow class"""
+    """Proxy of C++ GDALTransformerInfoShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, Transformer, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, Transformer, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALTransformerInfoShadow self, Dataset src, Dataset dst, char ** options) -> Transformer"""
         this = _gdal.new_Transformer(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_Transformer
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def TransformPoint(self, *args):
         """
         TransformPoint(Transformer self, int bDstToSrc, double [3] inout) -> int
@@ -2696,433 +2892,391 @@ class Transformer(_object):
         """
         return _gdal.Transformer_TransformPoint(self, *args)
 
+
     def TransformPoints(self, *args):
         """TransformPoints(Transformer self, int bDstToSrc, int nCount) -> int"""
         return _gdal.Transformer_TransformPoints(self, *args)
 
+
     def TransformGeolocations(self, *args, **kwargs):
-        """
-        TransformGeolocations(Transformer self, Band xBand, Band yBand, Band zBand, GDALProgressFunc callback=0, void * callback_data=None, 
-            char ** options=None) -> int
-        """
+        """TransformGeolocations(Transformer self, Band xBand, Band yBand, Band zBand, GDALProgressFunc callback=0, void * callback_data=None, char ** options=None) -> int"""
         return _gdal.Transformer_TransformGeolocations(self, *args, **kwargs)
 
 Transformer_swigregister = _gdal.Transformer_swigregister
 Transformer_swigregister(Transformer)
 
 
+def ApplyVerticalShiftGrid(*args, **kwargs):
+    """ApplyVerticalShiftGrid(Dataset src_ds, Dataset grid_ds, bool inverse=False, double srcUnitToMeter=1.0, double dstUnitToMeter=1.0, char ** options=None) -> Dataset"""
+    return _gdal.ApplyVerticalShiftGrid(*args, **kwargs)
+
 def ApplyGeoTransform(*args):
-  """ApplyGeoTransform(double [6] padfGeoTransform, double dfPixel, double dfLine)"""
-  return _gdal.ApplyGeoTransform(*args)
-ApplyGeoTransform = _gdal.ApplyGeoTransform
+    """ApplyGeoTransform(double [6] padfGeoTransform, double dfPixel, double dfLine)"""
+    return _gdal.ApplyGeoTransform(*args)
 
 def InvGeoTransform(*args):
-  """InvGeoTransform(double [6] gt_in) -> RETURN_NONE"""
-  return _gdal.InvGeoTransform(*args)
-InvGeoTransform = _gdal.InvGeoTransform
+    """InvGeoTransform(double [6] gt_in) -> RETURN_NONE"""
+    return _gdal.InvGeoTransform(*args)
 
 def VersionInfo(*args):
-  """VersionInfo(char const * request="VERSION_NUM") -> char const *"""
-  return _gdal.VersionInfo(*args)
-VersionInfo = _gdal.VersionInfo
+    """VersionInfo(char const * request) -> char const *"""
+    return _gdal.VersionInfo(*args)
 
 def AllRegister(*args):
-  """AllRegister()"""
-  return _gdal.AllRegister(*args)
-AllRegister = _gdal.AllRegister
+    """AllRegister()"""
+    return _gdal.AllRegister(*args)
 
 def GDALDestroyDriverManager(*args):
-  """GDALDestroyDriverManager()"""
-  return _gdal.GDALDestroyDriverManager(*args)
-GDALDestroyDriverManager = _gdal.GDALDestroyDriverManager
+    """GDALDestroyDriverManager()"""
+    return _gdal.GDALDestroyDriverManager(*args)
 
 def GetCacheMax(*args):
-  """GetCacheMax() -> GIntBig"""
-  return _gdal.GetCacheMax(*args)
-GetCacheMax = _gdal.GetCacheMax
+    """GetCacheMax() -> GIntBig"""
+    return _gdal.GetCacheMax(*args)
 
 def GetCacheUsed(*args):
-  """GetCacheUsed() -> GIntBig"""
-  return _gdal.GetCacheUsed(*args)
-GetCacheUsed = _gdal.GetCacheUsed
+    """GetCacheUsed() -> GIntBig"""
+    return _gdal.GetCacheUsed(*args)
 
 def SetCacheMax(*args):
-  """SetCacheMax(GIntBig nBytes)"""
-  return _gdal.SetCacheMax(*args)
-SetCacheMax = _gdal.SetCacheMax
+    """SetCacheMax(GIntBig nBytes)"""
+    return _gdal.SetCacheMax(*args)
 
 def GetDataTypeSize(*args):
-  """GetDataTypeSize(GDALDataType eDataType) -> int"""
-  return _gdal.GetDataTypeSize(*args)
-GetDataTypeSize = _gdal.GetDataTypeSize
+    """GetDataTypeSize(GDALDataType eDataType) -> int"""
+    return _gdal.GetDataTypeSize(*args)
 
 def DataTypeIsComplex(*args):
-  """DataTypeIsComplex(GDALDataType eDataType) -> int"""
-  return _gdal.DataTypeIsComplex(*args)
-DataTypeIsComplex = _gdal.DataTypeIsComplex
+    """DataTypeIsComplex(GDALDataType eDataType) -> int"""
+    return _gdal.DataTypeIsComplex(*args)
 
 def GetDataTypeName(*args):
-  """GetDataTypeName(GDALDataType eDataType) -> char const *"""
-  return _gdal.GetDataTypeName(*args)
-GetDataTypeName = _gdal.GetDataTypeName
+    """GetDataTypeName(GDALDataType eDataType) -> char const *"""
+    return _gdal.GetDataTypeName(*args)
 
 def GetDataTypeByName(*args):
-  """GetDataTypeByName(char const * pszDataTypeName) -> GDALDataType"""
-  return _gdal.GetDataTypeByName(*args)
-GetDataTypeByName = _gdal.GetDataTypeByName
+    """GetDataTypeByName(char const * pszDataTypeName) -> GDALDataType"""
+    return _gdal.GetDataTypeByName(*args)
 
 def GetColorInterpretationName(*args):
-  """GetColorInterpretationName(GDALColorInterp eColorInterp) -> char const *"""
-  return _gdal.GetColorInterpretationName(*args)
-GetColorInterpretationName = _gdal.GetColorInterpretationName
+    """GetColorInterpretationName(GDALColorInterp eColorInterp) -> char const *"""
+    return _gdal.GetColorInterpretationName(*args)
 
 def GetPaletteInterpretationName(*args):
-  """GetPaletteInterpretationName(GDALPaletteInterp ePaletteInterp) -> char const *"""
-  return _gdal.GetPaletteInterpretationName(*args)
-GetPaletteInterpretationName = _gdal.GetPaletteInterpretationName
+    """GetPaletteInterpretationName(GDALPaletteInterp ePaletteInterp) -> char const *"""
+    return _gdal.GetPaletteInterpretationName(*args)
 
 def DecToDMS(*args):
-  """DecToDMS(double arg1, char const * arg2, int arg3=2) -> char const *"""
-  return _gdal.DecToDMS(*args)
-DecToDMS = _gdal.DecToDMS
+    """DecToDMS(double arg1, char const * arg2, int arg3=2) -> char const *"""
+    return _gdal.DecToDMS(*args)
 
 def PackedDMSToDec(*args):
-  """PackedDMSToDec(double dfPacked) -> double"""
-  return _gdal.PackedDMSToDec(*args)
-PackedDMSToDec = _gdal.PackedDMSToDec
+    """PackedDMSToDec(double dfPacked) -> double"""
+    return _gdal.PackedDMSToDec(*args)
 
 def DecToPackedDMS(*args):
-  """DecToPackedDMS(double dfDec) -> double"""
-  return _gdal.DecToPackedDMS(*args)
-DecToPackedDMS = _gdal.DecToPackedDMS
+    """DecToPackedDMS(double dfDec) -> double"""
+    return _gdal.DecToPackedDMS(*args)
 
 def ParseXMLString(*args):
-  """ParseXMLString(char * pszXMLString) -> CPLXMLNode *"""
-  return _gdal.ParseXMLString(*args)
-ParseXMLString = _gdal.ParseXMLString
+    """ParseXMLString(char * pszXMLString) -> CPLXMLNode *"""
+    return _gdal.ParseXMLString(*args)
 
 def SerializeXMLTree(*args):
-  """SerializeXMLTree(CPLXMLNode * xmlnode) -> retStringAndCPLFree *"""
-  return _gdal.SerializeXMLTree(*args)
-SerializeXMLTree = _gdal.SerializeXMLTree
+    """SerializeXMLTree(CPLXMLNode * xmlnode) -> retStringAndCPLFree *"""
+    return _gdal.SerializeXMLTree(*args)
 
 def GetJPEG2000Structure(*args):
-  """GetJPEG2000Structure(char const * pszFilename, char ** options=None) -> CPLXMLNode *"""
-  return _gdal.GetJPEG2000Structure(*args)
-GetJPEG2000Structure = _gdal.GetJPEG2000Structure
+    """GetJPEG2000Structure(char const * pszFilename, char ** options=None) -> CPLXMLNode *"""
+    return _gdal.GetJPEG2000Structure(*args)
 
 def GetJPEG2000StructureAsString(*args):
-  """GetJPEG2000StructureAsString(char const * pszFilename, char ** options=None) -> retStringAndCPLFree *"""
-  return _gdal.GetJPEG2000StructureAsString(*args)
-GetJPEG2000StructureAsString = _gdal.GetJPEG2000StructureAsString
+    """GetJPEG2000StructureAsString(char const * pszFilename, char ** options=None) -> retStringAndCPLFree *"""
+    return _gdal.GetJPEG2000StructureAsString(*args)
 
 def GetDriverCount(*args):
-  """GetDriverCount() -> int"""
-  return _gdal.GetDriverCount(*args)
-GetDriverCount = _gdal.GetDriverCount
+    """GetDriverCount() -> int"""
+    return _gdal.GetDriverCount(*args)
 
 def GetDriverByName(*args):
-  """GetDriverByName(char const * name) -> Driver"""
-  return _gdal.GetDriverByName(*args)
-GetDriverByName = _gdal.GetDriverByName
+    """GetDriverByName(char const * name) -> Driver"""
+    return _gdal.GetDriverByName(*args)
 
 def GetDriver(*args):
-  """GetDriver(int i) -> Driver"""
-  return _gdal.GetDriver(*args)
-GetDriver = _gdal.GetDriver
+    """GetDriver(int i) -> Driver"""
+    return _gdal.GetDriver(*args)
 
 def Open(*args):
-  """Open(char const * utf8_path, GDALAccess eAccess=GA_ReadOnly) -> Dataset"""
-  return _gdal.Open(*args)
-Open = _gdal.Open
+    """Open(char const * utf8_path, GDALAccess eAccess) -> Dataset"""
+    return _gdal.Open(*args)
 
 def OpenEx(*args, **kwargs):
-  """
-    OpenEx(char const * utf8_path, unsigned int nOpenFlags=0, char ** allowed_drivers=None, 
-        char ** open_options=None, char ** sibling_files=None) -> Dataset
-    """
-  return _gdal.OpenEx(*args, **kwargs)
-OpenEx = _gdal.OpenEx
+    """OpenEx(char const * utf8_path, unsigned int nOpenFlags=0, char ** allowed_drivers=None, char ** open_options=None, char ** sibling_files=None) -> Dataset"""
+    return _gdal.OpenEx(*args, **kwargs)
 
 def OpenShared(*args):
-  """OpenShared(char const * utf8_path, GDALAccess eAccess=GA_ReadOnly) -> Dataset"""
-  return _gdal.OpenShared(*args)
-OpenShared = _gdal.OpenShared
+    """OpenShared(char const * utf8_path, GDALAccess eAccess) -> Dataset"""
+    return _gdal.OpenShared(*args)
 
 def IdentifyDriver(*args):
-  """IdentifyDriver(char const * utf8_path, char ** papszSiblings=None) -> Driver"""
-  return _gdal.IdentifyDriver(*args)
-IdentifyDriver = _gdal.IdentifyDriver
+    """IdentifyDriver(char const * utf8_path, char ** papszSiblings=None) -> Driver"""
+    return _gdal.IdentifyDriver(*args)
+
+def IdentifyDriverEx(*args, **kwargs):
+    """IdentifyDriverEx(char const * utf8_path, unsigned int nIdentifyFlags=0, char ** allowed_drivers=None, char ** sibling_files=None) -> Driver"""
+    return _gdal.IdentifyDriverEx(*args, **kwargs)
 
 def GeneralCmdLineProcessor(*args):
-  """GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"""
-  return _gdal.GeneralCmdLineProcessor(*args)
-GeneralCmdLineProcessor = _gdal.GeneralCmdLineProcessor
+    """GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"""
+    return _gdal.GeneralCmdLineProcessor(*args)
+
 __version__ = _gdal.VersionInfo("RELEASE_NAME")
 
 class GDALInfoOptions(_object):
-    """Proxy of C++ GDALInfoOptions class"""
+    """Proxy of C++ GDALInfoOptions class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GDALInfoOptions, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GDALInfoOptions, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALInfoOptions self, char ** options) -> GDALInfoOptions"""
         this = _gdal.new_GDALInfoOptions(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GDALInfoOptions
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
 GDALInfoOptions_swigregister = _gdal.GDALInfoOptions_swigregister
 GDALInfoOptions_swigregister(GDALInfoOptions)
 
 
 def InfoInternal(*args):
-  """InfoInternal(Dataset hDataset, GDALInfoOptions infoOptions) -> retStringAndCPLFree *"""
-  return _gdal.InfoInternal(*args)
-InfoInternal = _gdal.InfoInternal
+    """InfoInternal(Dataset hDataset, GDALInfoOptions infoOptions) -> retStringAndCPLFree *"""
+    return _gdal.InfoInternal(*args)
 class GDALTranslateOptions(_object):
-    """Proxy of C++ GDALTranslateOptions class"""
+    """Proxy of C++ GDALTranslateOptions class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GDALTranslateOptions, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GDALTranslateOptions, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALTranslateOptions self, char ** options) -> GDALTranslateOptions"""
         this = _gdal.new_GDALTranslateOptions(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GDALTranslateOptions
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
 GDALTranslateOptions_swigregister = _gdal.GDALTranslateOptions_swigregister
 GDALTranslateOptions_swigregister(GDALTranslateOptions)
 
 
 def TranslateInternal(*args):
-  """
-    TranslateInternal(char const * dest, Dataset dataset, GDALTranslateOptions translateOptions, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> Dataset
-    """
-  return _gdal.TranslateInternal(*args)
-TranslateInternal = _gdal.TranslateInternal
+    """TranslateInternal(char const * dest, Dataset dataset, GDALTranslateOptions translateOptions, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
+    return _gdal.TranslateInternal(*args)
 class GDALWarpAppOptions(_object):
-    """Proxy of C++ GDALWarpAppOptions class"""
+    """Proxy of C++ GDALWarpAppOptions class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GDALWarpAppOptions, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GDALWarpAppOptions, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALWarpAppOptions self, char ** options) -> GDALWarpAppOptions"""
         this = _gdal.new_GDALWarpAppOptions(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GDALWarpAppOptions
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
 GDALWarpAppOptions_swigregister = _gdal.GDALWarpAppOptions_swigregister
 GDALWarpAppOptions_swigregister(GDALWarpAppOptions)
 
 
 def wrapper_GDALWarpDestDS(*args):
-  """
-    wrapper_GDALWarpDestDS(Dataset dstDS, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.wrapper_GDALWarpDestDS(*args)
-wrapper_GDALWarpDestDS = _gdal.wrapper_GDALWarpDestDS
+    """wrapper_GDALWarpDestDS(Dataset dstDS, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.wrapper_GDALWarpDestDS(*args)
 
 def wrapper_GDALWarpDestName(*args):
-  """
-    wrapper_GDALWarpDestName(char const * dest, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> Dataset
-    """
-  return _gdal.wrapper_GDALWarpDestName(*args)
-wrapper_GDALWarpDestName = _gdal.wrapper_GDALWarpDestName
+    """wrapper_GDALWarpDestName(char const * dest, int object_list_count, GDALWarpAppOptions warpAppOptions, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
+    return _gdal.wrapper_GDALWarpDestName(*args)
 class GDALVectorTranslateOptions(_object):
-    """Proxy of C++ GDALVectorTranslateOptions class"""
+    """Proxy of C++ GDALVectorTranslateOptions class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GDALVectorTranslateOptions, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GDALVectorTranslateOptions, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALVectorTranslateOptions self, char ** options) -> GDALVectorTranslateOptions"""
         this = _gdal.new_GDALVectorTranslateOptions(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GDALVectorTranslateOptions
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
 GDALVectorTranslateOptions_swigregister = _gdal.GDALVectorTranslateOptions_swigregister
 GDALVectorTranslateOptions_swigregister(GDALVectorTranslateOptions)
 
 
 def wrapper_GDALVectorTranslateDestDS(*args):
-  """
-    wrapper_GDALVectorTranslateDestDS(Dataset dstDS, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.wrapper_GDALVectorTranslateDestDS(*args)
-wrapper_GDALVectorTranslateDestDS = _gdal.wrapper_GDALVectorTranslateDestDS
+    """wrapper_GDALVectorTranslateDestDS(Dataset dstDS, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.wrapper_GDALVectorTranslateDestDS(*args)
 
 def wrapper_GDALVectorTranslateDestName(*args):
-  """
-    wrapper_GDALVectorTranslateDestName(char const * dest, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> Dataset
-    """
-  return _gdal.wrapper_GDALVectorTranslateDestName(*args)
-wrapper_GDALVectorTranslateDestName = _gdal.wrapper_GDALVectorTranslateDestName
+    """wrapper_GDALVectorTranslateDestName(char const * dest, Dataset srcDS, GDALVectorTranslateOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
+    return _gdal.wrapper_GDALVectorTranslateDestName(*args)
 class GDALDEMProcessingOptions(_object):
-    """Proxy of C++ GDALDEMProcessingOptions class"""
+    """Proxy of C++ GDALDEMProcessingOptions class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GDALDEMProcessingOptions, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GDALDEMProcessingOptions, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALDEMProcessingOptions self, char ** options) -> GDALDEMProcessingOptions"""
         this = _gdal.new_GDALDEMProcessingOptions(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GDALDEMProcessingOptions
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
 GDALDEMProcessingOptions_swigregister = _gdal.GDALDEMProcessingOptions_swigregister
 GDALDEMProcessingOptions_swigregister(GDALDEMProcessingOptions)
 
 
 def DEMProcessingInternal(*args):
-  """
-    DEMProcessingInternal(char const * dest, Dataset dataset, char const * pszProcessing, char const * pszColorFilename, 
-        GDALDEMProcessingOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> Dataset
-    """
-  return _gdal.DEMProcessingInternal(*args)
-DEMProcessingInternal = _gdal.DEMProcessingInternal
+    """DEMProcessingInternal(char const * dest, Dataset dataset, char const * pszProcessing, char const * pszColorFilename, GDALDEMProcessingOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
+    return _gdal.DEMProcessingInternal(*args)
 class GDALNearblackOptions(_object):
-    """Proxy of C++ GDALNearblackOptions class"""
+    """Proxy of C++ GDALNearblackOptions class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GDALNearblackOptions, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GDALNearblackOptions, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALNearblackOptions self, char ** options) -> GDALNearblackOptions"""
         this = _gdal.new_GDALNearblackOptions(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GDALNearblackOptions
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
 GDALNearblackOptions_swigregister = _gdal.GDALNearblackOptions_swigregister
 GDALNearblackOptions_swigregister(GDALNearblackOptions)
 
 
 def wrapper_GDALNearblackDestDS(*args):
-  """
-    wrapper_GDALNearblackDestDS(Dataset dstDS, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.wrapper_GDALNearblackDestDS(*args)
-wrapper_GDALNearblackDestDS = _gdal.wrapper_GDALNearblackDestDS
+    """wrapper_GDALNearblackDestDS(Dataset dstDS, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.wrapper_GDALNearblackDestDS(*args)
 
 def wrapper_GDALNearblackDestName(*args):
-  """
-    wrapper_GDALNearblackDestName(char const * dest, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> Dataset
-    """
-  return _gdal.wrapper_GDALNearblackDestName(*args)
-wrapper_GDALNearblackDestName = _gdal.wrapper_GDALNearblackDestName
+    """wrapper_GDALNearblackDestName(char const * dest, Dataset srcDS, GDALNearblackOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
+    return _gdal.wrapper_GDALNearblackDestName(*args)
 class GDALGridOptions(_object):
-    """Proxy of C++ GDALGridOptions class"""
+    """Proxy of C++ GDALGridOptions class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GDALGridOptions, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GDALGridOptions, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALGridOptions self, char ** options) -> GDALGridOptions"""
         this = _gdal.new_GDALGridOptions(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GDALGridOptions
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
 GDALGridOptions_swigregister = _gdal.GDALGridOptions_swigregister
 GDALGridOptions_swigregister(GDALGridOptions)
 
 
 def GridInternal(*args):
-  """
-    GridInternal(char const * dest, Dataset dataset, GDALGridOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> Dataset
-    """
-  return _gdal.GridInternal(*args)
-GridInternal = _gdal.GridInternal
+    """GridInternal(char const * dest, Dataset dataset, GDALGridOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
+    return _gdal.GridInternal(*args)
 class GDALRasterizeOptions(_object):
-    """Proxy of C++ GDALRasterizeOptions class"""
+    """Proxy of C++ GDALRasterizeOptions class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GDALRasterizeOptions, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GDALRasterizeOptions, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALRasterizeOptions self, char ** options) -> GDALRasterizeOptions"""
         this = _gdal.new_GDALRasterizeOptions(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GDALRasterizeOptions
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
 GDALRasterizeOptions_swigregister = _gdal.GDALRasterizeOptions_swigregister
 GDALRasterizeOptions_swigregister(GDALRasterizeOptions)
 
 
 def wrapper_GDALRasterizeDestDS(*args):
-  """
-    wrapper_GDALRasterizeDestDS(Dataset dstDS, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> int
-    """
-  return _gdal.wrapper_GDALRasterizeDestDS(*args)
-wrapper_GDALRasterizeDestDS = _gdal.wrapper_GDALRasterizeDestDS
+    """wrapper_GDALRasterizeDestDS(Dataset dstDS, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> int"""
+    return _gdal.wrapper_GDALRasterizeDestDS(*args)
 
 def wrapper_GDALRasterizeDestName(*args):
-  """
-    wrapper_GDALRasterizeDestName(char const * dest, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> Dataset
-    """
-  return _gdal.wrapper_GDALRasterizeDestName(*args)
-wrapper_GDALRasterizeDestName = _gdal.wrapper_GDALRasterizeDestName
+    """wrapper_GDALRasterizeDestName(char const * dest, Dataset srcDS, GDALRasterizeOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
+    return _gdal.wrapper_GDALRasterizeDestName(*args)
 class GDALBuildVRTOptions(_object):
-    """Proxy of C++ GDALBuildVRTOptions class"""
+    """Proxy of C++ GDALBuildVRTOptions class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GDALBuildVRTOptions, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GDALBuildVRTOptions, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(GDALBuildVRTOptions self, char ** options) -> GDALBuildVRTOptions"""
         this = _gdal.new_GDALBuildVRTOptions(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _gdal.delete_GDALBuildVRTOptions
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
 GDALBuildVRTOptions_swigregister = _gdal.GDALBuildVRTOptions_swigregister
 GDALBuildVRTOptions_swigregister(GDALBuildVRTOptions)
 
 
 def BuildVRTInternalObjects(*args):
-  """
-    BuildVRTInternalObjects(char const * dest, int object_list_count, GDALBuildVRTOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> Dataset
-    """
-  return _gdal.BuildVRTInternalObjects(*args)
-BuildVRTInternalObjects = _gdal.BuildVRTInternalObjects
+    """BuildVRTInternalObjects(char const * dest, int object_list_count, GDALBuildVRTOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
+    return _gdal.BuildVRTInternalObjects(*args)
 
 def BuildVRTInternalNames(*args):
-  """
-    BuildVRTInternalNames(char const * dest, char ** source_filenames, GDALBuildVRTOptions options, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> Dataset
-    """
-  return _gdal.BuildVRTInternalNames(*args)
-BuildVRTInternalNames = _gdal.BuildVRTInternalNames
+    """BuildVRTInternalNames(char const * dest, char ** source_filenames, GDALBuildVRTOptions options, GDALProgressFunc callback=0, void * callback_data=None) -> Dataset"""
+    return _gdal.BuildVRTInternalNames(*args)
 # This file is compatible with both classic and new-style classes.
 
 
diff --git a/swig/python/osgeo/gdal_array.py b/swig/python/osgeo/gdal_array.py
index b270066..fd6b555 100644
--- a/swig/python/osgeo/gdal_array.py
+++ b/swig/python/osgeo/gdal_array.py
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
+# Version 3.0.8
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
@@ -9,7 +9,7 @@
 
 
 from sys import version_info
-if version_info >= (2,6,0):
+if version_info >= (2, 6, 0):
     def swig_import_helper():
         from os.path import dirname
         import imp
@@ -33,57 +33,83 @@ del version_info
 try:
     _swig_property = property
 except NameError:
-    pass # Python < 2.2 doesn't have 'property'.
-def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
-    if (name == "thisown"): return self.this.own(value)
+    pass  # Python < 2.2 doesn't have 'property'.
+
+
+def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
+    if (name == "thisown"):
+        return self.this.own(value)
     if (name == "this"):
         if type(value).__name__ == 'SwigPyObject':
             self.__dict__[name] = value
             return
-    method = class_type.__swig_setmethods__.get(name,None)
-    if method: return method(self,value)
+    method = class_type.__swig_setmethods__.get(name, None)
+    if method:
+        return method(self, value)
     if (not static):
-        self.__dict__[name] = value
+        if _newclass:
+            object.__setattr__(self, name, value)
+        else:
+            self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
 
-def _swig_setattr(self,class_type,name,value):
-    return _swig_setattr_nondynamic(self,class_type,name,value,0)
 
-def _swig_getattr(self,class_type,name):
-    if (name == "thisown"): return self.this.own()
-    method = class_type.__swig_getmethods__.get(name,None)
-    if method: return method(self)
-    raise AttributeError(name)
+def _swig_setattr(self, class_type, name, value):
+    return _swig_setattr_nondynamic(self, class_type, name, value, 0)
+
+
+def _swig_getattr_nondynamic(self, class_type, name, static=1):
+    if (name == "thisown"):
+        return self.this.own()
+    method = class_type.__swig_getmethods__.get(name, None)
+    if method:
+        return method(self)
+    if (not static):
+        return object.__getattr__(self, name)
+    else:
+        raise AttributeError(name)
+
+def _swig_getattr(self, class_type, name):
+    return _swig_getattr_nondynamic(self, class_type, name, 0)
+
 
 def _swig_repr(self):
-    try: strthis = "proxy of " + self.this.__repr__()
-    except: strthis = ""
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except Exception:
+        strthis = ""
     return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
 
 try:
     _object = object
     _newclass = 1
 except AttributeError:
-    class _object : pass
+    class _object:
+        pass
     _newclass = 0
 
 
 import gdal
 class VirtualMem(_object):
-    """Proxy of C++ CPLVirtualMemShadow class"""
+    """Proxy of C++ CPLVirtualMemShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, VirtualMem, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, VirtualMem, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_destroy__ = _gdal_array.delete_VirtualMem
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def GetAddr(self):
         """GetAddr(VirtualMem self)"""
         return _gdal_array.VirtualMem_GetAddr(self)
 
+
     def Pin(self, start_offset=0, nsize=0, bWriteOp=0):
         """
         Pin(VirtualMem self, size_t start_offset=0, size_t nsize=0, int bWriteOp=0)
@@ -97,55 +123,43 @@ VirtualMem_swigregister = _gdal_array.VirtualMem_swigregister
 VirtualMem_swigregister(VirtualMem)
 
 
-def TermProgress_nocb(*args, **kwargs):
-  """TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"""
-  return _gdal_array.TermProgress_nocb(*args, **kwargs)
+def TermProgress_nocb(dfProgress, pszMessage=None, pData=None):
+    """TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"""
+    return _gdal_array.TermProgress_nocb(dfProgress, pszMessage, pData)
+
+_gdal_array.TermProgress_swigconstant(_gdal_array)
 TermProgress = _gdal_array.TermProgress
 
-def OpenNumPyArray(*args):
-  """OpenNumPyArray(PyArrayObject * psArray) -> Dataset"""
-  return _gdal_array.OpenNumPyArray(*args)
-OpenNumPyArray = _gdal_array.OpenNumPyArray
-
-def GetArrayFilename(*args):
-  """GetArrayFilename(PyArrayObject * psArray) -> retStringAndCPLFree *"""
-  return _gdal_array.GetArrayFilename(*args)
-GetArrayFilename = _gdal_array.GetArrayFilename
-
-def BandRasterIONumPy(*args, **kwargs):
-  """
-    BandRasterIONumPy(Band band, int bWrite, double xoff, double yoff, double xsize, double ysize, PyArrayObject * psArray, 
-        int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> CPLErr
-    """
-  return _gdal_array.BandRasterIONumPy(*args, **kwargs)
-BandRasterIONumPy = _gdal_array.BandRasterIONumPy
-
-def DatasetIONumPy(*args, **kwargs):
-  """
-    DatasetIONumPy(Dataset ds, int bWrite, int xoff, int yoff, int xsize, int ysize, PyArrayObject * psArray, 
-        int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, 
-        void * callback_data=None) -> CPLErr
-    """
-  return _gdal_array.DatasetIONumPy(*args, **kwargs)
-DatasetIONumPy = _gdal_array.DatasetIONumPy
-
-def VirtualMemGetArray(*args):
-  """VirtualMemGetArray(VirtualMem virtualmem)"""
-  return _gdal_array.VirtualMemGetArray(*args)
-VirtualMemGetArray = _gdal_array.VirtualMemGetArray
-
-def RATValuesIONumPyWrite(*args, **kwargs):
-  """RATValuesIONumPyWrite(RasterAttributeTable poRAT, int nField, int nStart, PyArrayObject * psArray) -> CPLErr"""
-  return _gdal_array.RATValuesIONumPyWrite(*args, **kwargs)
-RATValuesIONumPyWrite = _gdal_array.RATValuesIONumPyWrite
-
-def RATValuesIONumPyRead(*args, **kwargs):
-  """RATValuesIONumPyRead(RasterAttributeTable poRAT, int nField, int nStart, int nLength) -> PyObject *"""
-  return _gdal_array.RATValuesIONumPyRead(*args, **kwargs)
-RATValuesIONumPyRead = _gdal_array.RATValuesIONumPyRead
+def OpenNumPyArray(psArray):
+    """OpenNumPyArray(PyArrayObject * psArray) -> Dataset"""
+    return _gdal_array.OpenNumPyArray(psArray)
+
+def GetArrayFilename(psArray):
+    """GetArrayFilename(PyArrayObject * psArray) -> retStringAndCPLFree *"""
+    return _gdal_array.GetArrayFilename(psArray)
+
+def BandRasterIONumPy(band, bWrite, xoff, yoff, xsize, ysize, psArray, buf_type, resample_alg, callback=0, callback_data=None):
+    """BandRasterIONumPy(Band band, int bWrite, double xoff, double yoff, double xsize, double ysize, PyArrayObject * psArray, int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
+    return _gdal_array.BandRasterIONumPy(band, bWrite, xoff, yoff, xsize, ysize, psArray, buf_type, resample_alg, callback, callback_data)
+
+def DatasetIONumPy(ds, bWrite, xoff, yoff, xsize, ysize, psArray, buf_type, resample_alg, callback=0, callback_data=None):
+    """DatasetIONumPy(Dataset ds, int bWrite, int xoff, int yoff, int xsize, int ysize, PyArrayObject * psArray, int buf_type, GDALRIOResampleAlg resample_alg, GDALProgressFunc callback=0, void * callback_data=None) -> CPLErr"""
+    return _gdal_array.DatasetIONumPy(ds, bWrite, xoff, yoff, xsize, ysize, psArray, buf_type, resample_alg, callback, callback_data)
+
+def VirtualMemGetArray(virtualmem):
+    """VirtualMemGetArray(VirtualMem virtualmem)"""
+    return _gdal_array.VirtualMemGetArray(virtualmem)
+
+def RATValuesIONumPyWrite(poRAT, nField, nStart, psArray):
+    """RATValuesIONumPyWrite(RasterAttributeTable poRAT, int nField, int nStart, PyArrayObject * psArray) -> CPLErr"""
+    return _gdal_array.RATValuesIONumPyWrite(poRAT, nField, nStart, psArray)
+
+def RATValuesIONumPyRead(poRAT, nField, nStart, nLength):
+    """RATValuesIONumPyRead(RasterAttributeTable poRAT, int nField, int nStart, int nLength) -> PyObject *"""
+    return _gdal_array.RATValuesIONumPyRead(poRAT, nField, nStart, nLength)
+
 import numpy
-import _gdal_array
+from . import _gdal_array
 
 import gdalconst
 import gdal
@@ -179,8 +193,8 @@ def OpenArray( array, prototype_ds = None ):
 
 def flip_code(code):
     if isinstance(code, (numpy.dtype,type)):
-        # since several things map to complex64 we must carefully select
-        # the opposite that is an exact match (ticket 1518)
+# since several things map to complex64 we must carefully select
+# the opposite that is an exact match (ticket 1518)
         if code == numpy.int8:
             return gdalconst.GDT_Byte
         if code == numpy.complex64:
@@ -366,8 +380,8 @@ def BandWriteArray( band, array, xoff=0, yoff=0,
 
     datatype = NumericTypeCodeToGDALTypeCode( array.dtype.type )
 
-    # if we receive some odd type, like int64, try casting to a very
-    # generic type we do support (#2285)
+# if we receive some odd type, like int64, try casting to a very
+# generic type we do support (#2285)
     if not datatype:
         gdal.Debug( 'gdal_array', 'force array to float64' )
         array = array.astype( numpy.float64 )
@@ -388,7 +402,7 @@ def RATWriteArray(rat, array, field, start=0):
     if array is None:
         raise ValueError("Expected array of dim 1")
 
-    # if not the array type convert it to handle lists etc
+# if not the array type convert it to handle lists etc
     if not isinstance(array, numpy.ndarray):
         array = numpy.array(array)
 
@@ -399,15 +413,15 @@ def RATWriteArray(rat, array, field, start=0):
         raise ValueError("Array too big to fit into RAT from start position")
 
     if numpy.issubdtype(array.dtype, numpy.integer):
-        # is some type of integer - coerce to standard int
-        # TODO: must check this is fine on all platforms
-        # confusingly numpy.int 64 bit even if native type 32 bit
+# is some type of integer - coerce to standard int
+# TODO: must check this is fine on all platforms
+# confusingly numpy.int 64 bit even if native type 32 bit
         array = array.astype(numpy.int32)
     elif numpy.issubdtype(array.dtype, numpy.floating):
-        # is some type of floating point - coerce to double
+# is some type of floating point - coerce to double
         array = array.astype(numpy.double)
     elif numpy.issubdtype(array.dtype, numpy.character):
-        # cast away any kind of Unicode etc
+# cast away any kind of Unicode etc
         array = array.astype(numpy.character)
     else:
         raise ValueError("Array not of a supported type (integer, double or string)")
@@ -440,7 +454,7 @@ def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
 
 
 
-    #Check for geo transform
+#Check for geo transform
     gt = src.GetGeoTransform()
     if gt != (0,1,0,0,0,1):
         dst.SetProjection( src.GetProjectionRef() )
@@ -453,14 +467,14 @@ def CopyDatasetInfo( src, dst, xoff=0, yoff=0 ):
             ngt[3] = gt[3] + xoff*gt[4] + yoff*gt[5];
             dst.SetGeoTransform( ( ngt[0], ngt[1], ngt[2], ngt[3], ngt[4], ngt[5] ) )
 
-    #Check for GCPs
+#Check for GCPs
     elif src.GetGCPCount() > 0:
 
         if (xoff == 0) and (yoff == 0):
             dst.SetGCPs( src.GetGCPs(), src.GetGCPProjection() )
         else:
             gcps = src.GetGCPs()
-            #Shift gcps
+#Shift gcps
             new_gcps = []
             for gcp in gcps:
                 ngcp = gdal.GCP()
diff --git a/swig/python/osgeo/gdalconst.py b/swig/python/osgeo/gdalconst.py
index 7477963..43dd8b5 100644
--- a/swig/python/osgeo/gdalconst.py
+++ b/swig/python/osgeo/gdalconst.py
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
+# Version 3.0.8
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
@@ -9,7 +9,7 @@
 
 
 from sys import version_info
-if version_info >= (2,6,0):
+if version_info >= (2, 6, 0):
     def swig_import_helper():
         from os.path import dirname
         import imp
@@ -33,179 +33,485 @@ del version_info
 try:
     _swig_property = property
 except NameError:
-    pass # Python < 2.2 doesn't have 'property'.
-def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
-    if (name == "thisown"): return self.this.own(value)
+    pass  # Python < 2.2 doesn't have 'property'.
+
+
+def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
+    if (name == "thisown"):
+        return self.this.own(value)
     if (name == "this"):
         if type(value).__name__ == 'SwigPyObject':
             self.__dict__[name] = value
             return
-    method = class_type.__swig_setmethods__.get(name,None)
-    if method: return method(self,value)
+    method = class_type.__swig_setmethods__.get(name, None)
+    if method:
+        return method(self, value)
     if (not static):
-        self.__dict__[name] = value
+        if _newclass:
+            object.__setattr__(self, name, value)
+        else:
+            self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
 
-def _swig_setattr(self,class_type,name,value):
-    return _swig_setattr_nondynamic(self,class_type,name,value,0)
 
-def _swig_getattr(self,class_type,name):
-    if (name == "thisown"): return self.this.own()
-    method = class_type.__swig_getmethods__.get(name,None)
-    if method: return method(self)
-    raise AttributeError(name)
+def _swig_setattr(self, class_type, name, value):
+    return _swig_setattr_nondynamic(self, class_type, name, value, 0)
+
+
+def _swig_getattr_nondynamic(self, class_type, name, static=1):
+    if (name == "thisown"):
+        return self.this.own()
+    method = class_type.__swig_getmethods__.get(name, None)
+    if method:
+        return method(self)
+    if (not static):
+        return object.__getattr__(self, name)
+    else:
+        raise AttributeError(name)
+
+def _swig_getattr(self, class_type, name):
+    return _swig_getattr_nondynamic(self, class_type, name, 0)
+
 
 def _swig_repr(self):
-    try: strthis = "proxy of " + self.this.__repr__()
-    except: strthis = ""
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except Exception:
+        strthis = ""
     return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
 
 try:
     _object = object
     _newclass = 1
 except AttributeError:
-    class _object : pass
+    class _object:
+        pass
     _newclass = 0
 
 
+
+_gdalconst.GDT_Unknown_swigconstant(_gdalconst)
 GDT_Unknown = _gdalconst.GDT_Unknown
+
+_gdalconst.GDT_Byte_swigconstant(_gdalconst)
 GDT_Byte = _gdalconst.GDT_Byte
+
+_gdalconst.GDT_UInt16_swigconstant(_gdalconst)
 GDT_UInt16 = _gdalconst.GDT_UInt16
+
+_gdalconst.GDT_Int16_swigconstant(_gdalconst)
 GDT_Int16 = _gdalconst.GDT_Int16
+
+_gdalconst.GDT_UInt32_swigconstant(_gdalconst)
 GDT_UInt32 = _gdalconst.GDT_UInt32
+
+_gdalconst.GDT_Int32_swigconstant(_gdalconst)
 GDT_Int32 = _gdalconst.GDT_Int32
+
+_gdalconst.GDT_Float32_swigconstant(_gdalconst)
 GDT_Float32 = _gdalconst.GDT_Float32
+
+_gdalconst.GDT_Float64_swigconstant(_gdalconst)
 GDT_Float64 = _gdalconst.GDT_Float64
+
+_gdalconst.GDT_CInt16_swigconstant(_gdalconst)
 GDT_CInt16 = _gdalconst.GDT_CInt16
+
+_gdalconst.GDT_CInt32_swigconstant(_gdalconst)
 GDT_CInt32 = _gdalconst.GDT_CInt32
+
+_gdalconst.GDT_CFloat32_swigconstant(_gdalconst)
 GDT_CFloat32 = _gdalconst.GDT_CFloat32
+
+_gdalconst.GDT_CFloat64_swigconstant(_gdalconst)
 GDT_CFloat64 = _gdalconst.GDT_CFloat64
+
+_gdalconst.GDT_TypeCount_swigconstant(_gdalconst)
 GDT_TypeCount = _gdalconst.GDT_TypeCount
+
+_gdalconst.GA_ReadOnly_swigconstant(_gdalconst)
 GA_ReadOnly = _gdalconst.GA_ReadOnly
+
+_gdalconst.GA_Update_swigconstant(_gdalconst)
 GA_Update = _gdalconst.GA_Update
+
+_gdalconst.GF_Read_swigconstant(_gdalconst)
 GF_Read = _gdalconst.GF_Read
+
+_gdalconst.GF_Write_swigconstant(_gdalconst)
 GF_Write = _gdalconst.GF_Write
+
+_gdalconst.GRIORA_NearestNeighbour_swigconstant(_gdalconst)
 GRIORA_NearestNeighbour = _gdalconst.GRIORA_NearestNeighbour
+
+_gdalconst.GRIORA_Bilinear_swigconstant(_gdalconst)
 GRIORA_Bilinear = _gdalconst.GRIORA_Bilinear
+
+_gdalconst.GRIORA_Cubic_swigconstant(_gdalconst)
 GRIORA_Cubic = _gdalconst.GRIORA_Cubic
+
+_gdalconst.GRIORA_CubicSpline_swigconstant(_gdalconst)
 GRIORA_CubicSpline = _gdalconst.GRIORA_CubicSpline
+
+_gdalconst.GRIORA_Lanczos_swigconstant(_gdalconst)
 GRIORA_Lanczos = _gdalconst.GRIORA_Lanczos
+
+_gdalconst.GRIORA_Average_swigconstant(_gdalconst)
 GRIORA_Average = _gdalconst.GRIORA_Average
+
+_gdalconst.GRIORA_Mode_swigconstant(_gdalconst)
 GRIORA_Mode = _gdalconst.GRIORA_Mode
+
+_gdalconst.GRIORA_Gauss_swigconstant(_gdalconst)
 GRIORA_Gauss = _gdalconst.GRIORA_Gauss
+
+_gdalconst.GCI_Undefined_swigconstant(_gdalconst)
 GCI_Undefined = _gdalconst.GCI_Undefined
+
+_gdalconst.GCI_GrayIndex_swigconstant(_gdalconst)
 GCI_GrayIndex = _gdalconst.GCI_GrayIndex
+
+_gdalconst.GCI_PaletteIndex_swigconstant(_gdalconst)
 GCI_PaletteIndex = _gdalconst.GCI_PaletteIndex
+
+_gdalconst.GCI_RedBand_swigconstant(_gdalconst)
 GCI_RedBand = _gdalconst.GCI_RedBand
+
+_gdalconst.GCI_GreenBand_swigconstant(_gdalconst)
 GCI_GreenBand = _gdalconst.GCI_GreenBand
+
+_gdalconst.GCI_BlueBand_swigconstant(_gdalconst)
 GCI_BlueBand = _gdalconst.GCI_BlueBand
+
+_gdalconst.GCI_AlphaBand_swigconstant(_gdalconst)
 GCI_AlphaBand = _gdalconst.GCI_AlphaBand
+
+_gdalconst.GCI_HueBand_swigconstant(_gdalconst)
 GCI_HueBand = _gdalconst.GCI_HueBand
+
+_gdalconst.GCI_SaturationBand_swigconstant(_gdalconst)
 GCI_SaturationBand = _gdalconst.GCI_SaturationBand
+
+_gdalconst.GCI_LightnessBand_swigconstant(_gdalconst)
 GCI_LightnessBand = _gdalconst.GCI_LightnessBand
+
+_gdalconst.GCI_CyanBand_swigconstant(_gdalconst)
 GCI_CyanBand = _gdalconst.GCI_CyanBand
+
+_gdalconst.GCI_MagentaBand_swigconstant(_gdalconst)
 GCI_MagentaBand = _gdalconst.GCI_MagentaBand
+
+_gdalconst.GCI_YellowBand_swigconstant(_gdalconst)
 GCI_YellowBand = _gdalconst.GCI_YellowBand
+
+_gdalconst.GCI_BlackBand_swigconstant(_gdalconst)
 GCI_BlackBand = _gdalconst.GCI_BlackBand
+
+_gdalconst.GCI_YCbCr_YBand_swigconstant(_gdalconst)
 GCI_YCbCr_YBand = _gdalconst.GCI_YCbCr_YBand
+
+_gdalconst.GCI_YCbCr_CrBand_swigconstant(_gdalconst)
 GCI_YCbCr_CrBand = _gdalconst.GCI_YCbCr_CrBand
+
+_gdalconst.GCI_YCbCr_CbBand_swigconstant(_gdalconst)
 GCI_YCbCr_CbBand = _gdalconst.GCI_YCbCr_CbBand
+
+_gdalconst.GRA_NearestNeighbour_swigconstant(_gdalconst)
 GRA_NearestNeighbour = _gdalconst.GRA_NearestNeighbour
+
+_gdalconst.GRA_Bilinear_swigconstant(_gdalconst)
 GRA_Bilinear = _gdalconst.GRA_Bilinear
+
+_gdalconst.GRA_Cubic_swigconstant(_gdalconst)
 GRA_Cubic = _gdalconst.GRA_Cubic
+
+_gdalconst.GRA_CubicSpline_swigconstant(_gdalconst)
 GRA_CubicSpline = _gdalconst.GRA_CubicSpline
+
+_gdalconst.GRA_Lanczos_swigconstant(_gdalconst)
 GRA_Lanczos = _gdalconst.GRA_Lanczos
+
+_gdalconst.GRA_Average_swigconstant(_gdalconst)
 GRA_Average = _gdalconst.GRA_Average
+
+_gdalconst.GRA_Mode_swigconstant(_gdalconst)
 GRA_Mode = _gdalconst.GRA_Mode
+
+_gdalconst.GPI_Gray_swigconstant(_gdalconst)
 GPI_Gray = _gdalconst.GPI_Gray
+
+_gdalconst.GPI_RGB_swigconstant(_gdalconst)
 GPI_RGB = _gdalconst.GPI_RGB
+
+_gdalconst.GPI_CMYK_swigconstant(_gdalconst)
 GPI_CMYK = _gdalconst.GPI_CMYK
+
+_gdalconst.GPI_HLS_swigconstant(_gdalconst)
 GPI_HLS = _gdalconst.GPI_HLS
+
+_gdalconst.CXT_Element_swigconstant(_gdalconst)
 CXT_Element = _gdalconst.CXT_Element
+
+_gdalconst.CXT_Text_swigconstant(_gdalconst)
 CXT_Text = _gdalconst.CXT_Text
+
+_gdalconst.CXT_Attribute_swigconstant(_gdalconst)
 CXT_Attribute = _gdalconst.CXT_Attribute
+
+_gdalconst.CXT_Comment_swigconstant(_gdalconst)
 CXT_Comment = _gdalconst.CXT_Comment
+
+_gdalconst.CXT_Literal_swigconstant(_gdalconst)
 CXT_Literal = _gdalconst.CXT_Literal
+
+_gdalconst.CE_None_swigconstant(_gdalconst)
 CE_None = _gdalconst.CE_None
+
+_gdalconst.CE_Debug_swigconstant(_gdalconst)
 CE_Debug = _gdalconst.CE_Debug
+
+_gdalconst.CE_Warning_swigconstant(_gdalconst)
 CE_Warning = _gdalconst.CE_Warning
+
+_gdalconst.CE_Failure_swigconstant(_gdalconst)
 CE_Failure = _gdalconst.CE_Failure
+
+_gdalconst.CE_Fatal_swigconstant(_gdalconst)
 CE_Fatal = _gdalconst.CE_Fatal
+
+_gdalconst.CPLE_None_swigconstant(_gdalconst)
 CPLE_None = _gdalconst.CPLE_None
+
+_gdalconst.CPLE_AppDefined_swigconstant(_gdalconst)
 CPLE_AppDefined = _gdalconst.CPLE_AppDefined
+
+_gdalconst.CPLE_OutOfMemory_swigconstant(_gdalconst)
 CPLE_OutOfMemory = _gdalconst.CPLE_OutOfMemory
+
+_gdalconst.CPLE_FileIO_swigconstant(_gdalconst)
 CPLE_FileIO = _gdalconst.CPLE_FileIO
+
+_gdalconst.CPLE_OpenFailed_swigconstant(_gdalconst)
 CPLE_OpenFailed = _gdalconst.CPLE_OpenFailed
+
+_gdalconst.CPLE_IllegalArg_swigconstant(_gdalconst)
 CPLE_IllegalArg = _gdalconst.CPLE_IllegalArg
+
+_gdalconst.CPLE_NotSupported_swigconstant(_gdalconst)
 CPLE_NotSupported = _gdalconst.CPLE_NotSupported
+
+_gdalconst.CPLE_AssertionFailed_swigconstant(_gdalconst)
 CPLE_AssertionFailed = _gdalconst.CPLE_AssertionFailed
+
+_gdalconst.CPLE_NoWriteAccess_swigconstant(_gdalconst)
 CPLE_NoWriteAccess = _gdalconst.CPLE_NoWriteAccess
+
+_gdalconst.CPLE_UserInterrupt_swigconstant(_gdalconst)
 CPLE_UserInterrupt = _gdalconst.CPLE_UserInterrupt
+
+_gdalconst.OF_ALL_swigconstant(_gdalconst)
 OF_ALL = _gdalconst.OF_ALL
+
+_gdalconst.OF_RASTER_swigconstant(_gdalconst)
 OF_RASTER = _gdalconst.OF_RASTER
+
+_gdalconst.OF_VECTOR_swigconstant(_gdalconst)
 OF_VECTOR = _gdalconst.OF_VECTOR
+
+_gdalconst.OF_GNM_swigconstant(_gdalconst)
 OF_GNM = _gdalconst.OF_GNM
+
+_gdalconst.OF_READONLY_swigconstant(_gdalconst)
 OF_READONLY = _gdalconst.OF_READONLY
+
+_gdalconst.OF_UPDATE_swigconstant(_gdalconst)
 OF_UPDATE = _gdalconst.OF_UPDATE
+
+_gdalconst.OF_SHARED_swigconstant(_gdalconst)
 OF_SHARED = _gdalconst.OF_SHARED
+
+_gdalconst.OF_VERBOSE_ERROR_swigconstant(_gdalconst)
 OF_VERBOSE_ERROR = _gdalconst.OF_VERBOSE_ERROR
+
+_gdalconst.DMD_LONGNAME_swigconstant(_gdalconst)
 DMD_LONGNAME = _gdalconst.DMD_LONGNAME
+
+_gdalconst.DMD_HELPTOPIC_swigconstant(_gdalconst)
 DMD_HELPTOPIC = _gdalconst.DMD_HELPTOPIC
+
+_gdalconst.DMD_MIMETYPE_swigconstant(_gdalconst)
 DMD_MIMETYPE = _gdalconst.DMD_MIMETYPE
+
+_gdalconst.DMD_EXTENSION_swigconstant(_gdalconst)
 DMD_EXTENSION = _gdalconst.DMD_EXTENSION
+
+_gdalconst.DMD_EXTENSIONS_swigconstant(_gdalconst)
 DMD_EXTENSIONS = _gdalconst.DMD_EXTENSIONS
+
+_gdalconst.DMD_CONNECTION_PREFIX_swigconstant(_gdalconst)
 DMD_CONNECTION_PREFIX = _gdalconst.DMD_CONNECTION_PREFIX
+
+_gdalconst.DMD_CREATIONOPTIONLIST_swigconstant(_gdalconst)
 DMD_CREATIONOPTIONLIST = _gdalconst.DMD_CREATIONOPTIONLIST
+
+_gdalconst.DMD_CREATIONDATATYPES_swigconstant(_gdalconst)
 DMD_CREATIONDATATYPES = _gdalconst.DMD_CREATIONDATATYPES
+
+_gdalconst.DMD_CREATIONFIELDDATATYPES_swigconstant(_gdalconst)
 DMD_CREATIONFIELDDATATYPES = _gdalconst.DMD_CREATIONFIELDDATATYPES
+
+_gdalconst.DMD_SUBDATASETS_swigconstant(_gdalconst)
 DMD_SUBDATASETS = _gdalconst.DMD_SUBDATASETS
+
+_gdalconst.DCAP_OPEN_swigconstant(_gdalconst)
 DCAP_OPEN = _gdalconst.DCAP_OPEN
+
+_gdalconst.DCAP_CREATE_swigconstant(_gdalconst)
 DCAP_CREATE = _gdalconst.DCAP_CREATE
+
+_gdalconst.DCAP_CREATECOPY_swigconstant(_gdalconst)
 DCAP_CREATECOPY = _gdalconst.DCAP_CREATECOPY
+
+_gdalconst.DCAP_VIRTUALIO_swigconstant(_gdalconst)
 DCAP_VIRTUALIO = _gdalconst.DCAP_VIRTUALIO
+
+_gdalconst.DCAP_RASTER_swigconstant(_gdalconst)
 DCAP_RASTER = _gdalconst.DCAP_RASTER
+
+_gdalconst.DCAP_VECTOR_swigconstant(_gdalconst)
 DCAP_VECTOR = _gdalconst.DCAP_VECTOR
+
+_gdalconst.DCAP_NOTNULL_FIELDS_swigconstant(_gdalconst)
 DCAP_NOTNULL_FIELDS = _gdalconst.DCAP_NOTNULL_FIELDS
+
+_gdalconst.DCAP_DEFAULT_FIELDS_swigconstant(_gdalconst)
 DCAP_DEFAULT_FIELDS = _gdalconst.DCAP_DEFAULT_FIELDS
+
+_gdalconst.DCAP_NOTNULL_GEOMFIELDS_swigconstant(_gdalconst)
 DCAP_NOTNULL_GEOMFIELDS = _gdalconst.DCAP_NOTNULL_GEOMFIELDS
+
+_gdalconst.CPLES_BackslashQuotable_swigconstant(_gdalconst)
 CPLES_BackslashQuotable = _gdalconst.CPLES_BackslashQuotable
+
+_gdalconst.CPLES_XML_swigconstant(_gdalconst)
 CPLES_XML = _gdalconst.CPLES_XML
+
+_gdalconst.CPLES_URL_swigconstant(_gdalconst)
 CPLES_URL = _gdalconst.CPLES_URL
+
+_gdalconst.CPLES_SQL_swigconstant(_gdalconst)
 CPLES_SQL = _gdalconst.CPLES_SQL
+
+_gdalconst.CPLES_CSV_swigconstant(_gdalconst)
 CPLES_CSV = _gdalconst.CPLES_CSV
+
+_gdalconst.GFT_Integer_swigconstant(_gdalconst)
 GFT_Integer = _gdalconst.GFT_Integer
+
+_gdalconst.GFT_Real_swigconstant(_gdalconst)
 GFT_Real = _gdalconst.GFT_Real
+
+_gdalconst.GFT_String_swigconstant(_gdalconst)
 GFT_String = _gdalconst.GFT_String
+
+_gdalconst.GFU_Generic_swigconstant(_gdalconst)
 GFU_Generic = _gdalconst.GFU_Generic
+
+_gdalconst.GFU_PixelCount_swigconstant(_gdalconst)
 GFU_PixelCount = _gdalconst.GFU_PixelCount
+
+_gdalconst.GFU_Name_swigconstant(_gdalconst)
 GFU_Name = _gdalconst.GFU_Name
+
+_gdalconst.GFU_Min_swigconstant(_gdalconst)
 GFU_Min = _gdalconst.GFU_Min
+
+_gdalconst.GFU_Max_swigconstant(_gdalconst)
 GFU_Max = _gdalconst.GFU_Max
+
+_gdalconst.GFU_MinMax_swigconstant(_gdalconst)
 GFU_MinMax = _gdalconst.GFU_MinMax
+
+_gdalconst.GFU_Red_swigconstant(_gdalconst)
 GFU_Red = _gdalconst.GFU_Red
+
+_gdalconst.GFU_Green_swigconstant(_gdalconst)
 GFU_Green = _gdalconst.GFU_Green
+
+_gdalconst.GFU_Blue_swigconstant(_gdalconst)
 GFU_Blue = _gdalconst.GFU_Blue
+
+_gdalconst.GFU_Alpha_swigconstant(_gdalconst)
 GFU_Alpha = _gdalconst.GFU_Alpha
+
+_gdalconst.GFU_RedMin_swigconstant(_gdalconst)
 GFU_RedMin = _gdalconst.GFU_RedMin
+
+_gdalconst.GFU_GreenMin_swigconstant(_gdalconst)
 GFU_GreenMin = _gdalconst.GFU_GreenMin
+
+_gdalconst.GFU_BlueMin_swigconstant(_gdalconst)
 GFU_BlueMin = _gdalconst.GFU_BlueMin
+
+_gdalconst.GFU_AlphaMin_swigconstant(_gdalconst)
 GFU_AlphaMin = _gdalconst.GFU_AlphaMin
+
+_gdalconst.GFU_RedMax_swigconstant(_gdalconst)
 GFU_RedMax = _gdalconst.GFU_RedMax
+
+_gdalconst.GFU_GreenMax_swigconstant(_gdalconst)
 GFU_GreenMax = _gdalconst.GFU_GreenMax
+
+_gdalconst.GFU_BlueMax_swigconstant(_gdalconst)
 GFU_BlueMax = _gdalconst.GFU_BlueMax
+
+_gdalconst.GFU_AlphaMax_swigconstant(_gdalconst)
 GFU_AlphaMax = _gdalconst.GFU_AlphaMax
+
+_gdalconst.GFU_MaxCount_swigconstant(_gdalconst)
 GFU_MaxCount = _gdalconst.GFU_MaxCount
+
+_gdalconst.GMF_ALL_VALID_swigconstant(_gdalconst)
 GMF_ALL_VALID = _gdalconst.GMF_ALL_VALID
+
+_gdalconst.GMF_PER_DATASET_swigconstant(_gdalconst)
 GMF_PER_DATASET = _gdalconst.GMF_PER_DATASET
+
+_gdalconst.GMF_ALPHA_swigconstant(_gdalconst)
 GMF_ALPHA = _gdalconst.GMF_ALPHA
+
+_gdalconst.GMF_NODATA_swigconstant(_gdalconst)
 GMF_NODATA = _gdalconst.GMF_NODATA
+
+_gdalconst.GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED_swigconstant(_gdalconst)
+GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED = _gdalconst.GDAL_DATA_COVERAGE_STATUS_UNIMPLEMENTED
+
+_gdalconst.GDAL_DATA_COVERAGE_STATUS_DATA_swigconstant(_gdalconst)
+GDAL_DATA_COVERAGE_STATUS_DATA = _gdalconst.GDAL_DATA_COVERAGE_STATUS_DATA
+
+_gdalconst.GDAL_DATA_COVERAGE_STATUS_EMPTY_swigconstant(_gdalconst)
+GDAL_DATA_COVERAGE_STATUS_EMPTY = _gdalconst.GDAL_DATA_COVERAGE_STATUS_EMPTY
+
+_gdalconst.GARIO_PENDING_swigconstant(_gdalconst)
 GARIO_PENDING = _gdalconst.GARIO_PENDING
+
+_gdalconst.GARIO_UPDATE_swigconstant(_gdalconst)
 GARIO_UPDATE = _gdalconst.GARIO_UPDATE
+
+_gdalconst.GARIO_ERROR_swigconstant(_gdalconst)
 GARIO_ERROR = _gdalconst.GARIO_ERROR
+
+_gdalconst.GARIO_COMPLETE_swigconstant(_gdalconst)
 GARIO_COMPLETE = _gdalconst.GARIO_COMPLETE
+
+_gdalconst.GTO_TIP_swigconstant(_gdalconst)
 GTO_TIP = _gdalconst.GTO_TIP
+
+_gdalconst.GTO_BIT_swigconstant(_gdalconst)
 GTO_BIT = _gdalconst.GTO_BIT
+
+_gdalconst.GTO_BSQ_swigconstant(_gdalconst)
 GTO_BSQ = _gdalconst.GTO_BSQ
 # This file is compatible with both classic and new-style classes.
 
diff --git a/swig/python/osgeo/gnm.py b/swig/python/osgeo/gnm.py
index 7355595..515cc79 100644
--- a/swig/python/osgeo/gnm.py
+++ b/swig/python/osgeo/gnm.py
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
+# Version 3.0.8
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
@@ -9,7 +9,7 @@
 
 
 from sys import version_info
-if version_info >= (2,6,0):
+if version_info >= (2, 6, 0):
     def swig_import_helper():
         from os.path import dirname
         import imp
@@ -33,173 +33,211 @@ del version_info
 try:
     _swig_property = property
 except NameError:
-    pass # Python < 2.2 doesn't have 'property'.
-def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
-    if (name == "thisown"): return self.this.own(value)
+    pass  # Python < 2.2 doesn't have 'property'.
+
+
+def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
+    if (name == "thisown"):
+        return self.this.own(value)
     if (name == "this"):
         if type(value).__name__ == 'SwigPyObject':
             self.__dict__[name] = value
             return
-    method = class_type.__swig_setmethods__.get(name,None)
-    if method: return method(self,value)
+    method = class_type.__swig_setmethods__.get(name, None)
+    if method:
+        return method(self, value)
     if (not static):
-        self.__dict__[name] = value
+        if _newclass:
+            object.__setattr__(self, name, value)
+        else:
+            self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
 
-def _swig_setattr(self,class_type,name,value):
-    return _swig_setattr_nondynamic(self,class_type,name,value,0)
 
-def _swig_getattr(self,class_type,name):
-    if (name == "thisown"): return self.this.own()
-    method = class_type.__swig_getmethods__.get(name,None)
-    if method: return method(self)
-    raise AttributeError(name)
+def _swig_setattr(self, class_type, name, value):
+    return _swig_setattr_nondynamic(self, class_type, name, value, 0)
+
+
+def _swig_getattr_nondynamic(self, class_type, name, static=1):
+    if (name == "thisown"):
+        return self.this.own()
+    method = class_type.__swig_getmethods__.get(name, None)
+    if method:
+        return method(self)
+    if (not static):
+        return object.__getattr__(self, name)
+    else:
+        raise AttributeError(name)
+
+def _swig_getattr(self, class_type, name):
+    return _swig_getattr_nondynamic(self, class_type, name, 0)
+
 
 def _swig_repr(self):
-    try: strthis = "proxy of " + self.this.__repr__()
-    except: strthis = ""
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except Exception:
+        strthis = ""
     return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
 
 try:
     _object = object
     _newclass = 1
 except AttributeError:
-    class _object : pass
+    class _object:
+        pass
     _newclass = 0
 
 
 
 def GetUseExceptions(*args):
-  return _gnm.GetUseExceptions(*args)
+    return _gnm.GetUseExceptions(*args)
 GetUseExceptions = _gnm.GetUseExceptions
 
 def UseExceptions(*args):
-  return _gnm.UseExceptions(*args)
+    return _gnm.UseExceptions(*args)
 UseExceptions = _gnm.UseExceptions
 
 def DontUseExceptions(*args):
-  return _gnm.DontUseExceptions(*args)
+    return _gnm.DontUseExceptions(*args)
 DontUseExceptions = _gnm.DontUseExceptions
-class MajorObject(_object):
-    __swig_setmethods__ = {}
-    __setattr__ = lambda self, name, value: _swig_setattr(self, MajorObject, name, value)
-    __swig_getmethods__ = {}
-    __getattr__ = lambda self, name: _swig_getattr(self, MajorObject, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
-    __repr__ = _swig_repr
-    def GetDescription(self, *args): return _gnm.MajorObject_GetDescription(self, *args)
-    def SetDescription(self, *args): return _gnm.MajorObject_SetDescription(self, *args)
-    def GetMetadataDomainList(self, *args): return _gnm.MajorObject_GetMetadataDomainList(self, *args)
-    def GetMetadata_Dict(self, *args): return _gnm.MajorObject_GetMetadata_Dict(self, *args)
-    def GetMetadata_List(self, *args): return _gnm.MajorObject_GetMetadata_List(self, *args)
-    def SetMetadata(self, *args): return _gnm.MajorObject_SetMetadata(self, *args)
-    def GetMetadataItem(self, *args): return _gnm.MajorObject_GetMetadataItem(self, *args)
-    def SetMetadataItem(self, *args): return _gnm.MajorObject_SetMetadataItem(self, *args)
-MajorObject_swigregister = _gnm.MajorObject_swigregister
-MajorObject_swigregister(MajorObject)
+import ogr
+import osr
 
+_gnm.GATDijkstraShortestPath_swigconstant(_gnm)
 GATDijkstraShortestPath = _gnm.GATDijkstraShortestPath
+
+_gnm.GATKShortestPath_swigconstant(_gnm)
 GATKShortestPath = _gnm.GATKShortestPath
+
+_gnm.GATConnectedComponents_swigconstant(_gnm)
 GATConnectedComponents = _gnm.GATConnectedComponents
+
+_gnm.GNM_EDGE_DIR_BOTH_swigconstant(_gnm)
 GNM_EDGE_DIR_BOTH = _gnm.GNM_EDGE_DIR_BOTH
+
+_gnm.GNM_EDGE_DIR_SRCTOTGT_swigconstant(_gnm)
 GNM_EDGE_DIR_SRCTOTGT = _gnm.GNM_EDGE_DIR_SRCTOTGT
+
+_gnm.GNM_EDGE_DIR_TGTTOSRC_swigconstant(_gnm)
 GNM_EDGE_DIR_TGTTOSRC = _gnm.GNM_EDGE_DIR_TGTTOSRC
 
 def CastToNetwork(*args):
-  """CastToNetwork(MajorObject base) -> Network"""
-  return _gnm.CastToNetwork(*args)
+    """CastToNetwork(MajorObject base) -> Network"""
+    return _gnm.CastToNetwork(*args)
 
 def CastToGenericNetwork(*args):
-  """CastToGenericNetwork(MajorObject base) -> GenericNetwork"""
-  return _gnm.CastToGenericNetwork(*args)
-class Network(MajorObject):
-    """Proxy of C++ GNMNetworkShadow class"""
+    """CastToGenericNetwork(MajorObject base) -> GenericNetwork"""
+    return _gnm.CastToGenericNetwork(*args)
+class Network(ogr.MajorObject):
+    """Proxy of C++ GNMNetworkShadow class."""
+
     __swig_setmethods__ = {}
-    for _s in [MajorObject]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    for _s in [ogr.MajorObject]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
     __setattr__ = lambda self, name, value: _swig_setattr(self, Network, name, value)
     __swig_getmethods__ = {}
-    for _s in [MajorObject]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    for _s in [ogr.MajorObject]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
     __getattr__ = lambda self, name: _swig_getattr(self, Network, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_destroy__ = _gnm.delete_Network
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def ReleaseResultSet(self, *args):
-        """ReleaseResultSet(Network self, OGRLayerShadow * layer)"""
+        """ReleaseResultSet(Network self, Layer layer)"""
         return _gnm.Network_ReleaseResultSet(self, *args)
 
+
     def GetVersion(self, *args):
         """GetVersion(Network self) -> int"""
         return _gnm.Network_GetVersion(self, *args)
 
+
     def GetName(self, *args):
         """GetName(Network self) -> char const *"""
         return _gnm.Network_GetName(self, *args)
 
+
     def GetFeatureByGlobalFID(self, *args):
-        """GetFeatureByGlobalFID(Network self, GIntBig GFID) -> OGRFeatureShadow *"""
+        """GetFeatureByGlobalFID(Network self, GIntBig GFID) -> Feature"""
         return _gnm.Network_GetFeatureByGlobalFID(self, *args)
 
+
     def GetPath(self, *args, **kwargs):
-        """GetPath(Network self, GIntBig nStartFID, GIntBig nEndFID, GNMGraphAlgorithmType eAlgorithm, char ** options=None) -> OGRLayerShadow *"""
+        """GetPath(Network self, GIntBig nStartFID, GIntBig nEndFID, GNMGraphAlgorithmType eAlgorithm, char ** options=None) -> Layer"""
         return _gnm.Network_GetPath(self, *args, **kwargs)
 
+
     def DisconnectAll(self, *args):
         """DisconnectAll(Network self) -> CPLErr"""
         return _gnm.Network_DisconnectAll(self, *args)
 
+
     def GetProjection(self, *args):
         """GetProjection(Network self) -> char const *"""
         return _gnm.Network_GetProjection(self, *args)
 
+
     def GetProjectionRef(self, *args):
         """GetProjectionRef(Network self) -> char const *"""
         return _gnm.Network_GetProjectionRef(self, *args)
 
+
     def GetFileList(self, *args):
         """GetFileList(Network self) -> char **"""
         return _gnm.Network_GetFileList(self, *args)
 
+
     def CreateLayer(self, *args, **kwargs):
-        """
-        CreateLayer(Network self, char const * name, OSRSpatialReferenceShadow * srs=None, OGRwkbGeometryType geom_type=wkbUnknown, 
-            char ** options=None) -> OGRLayerShadow *
-        """
+        """CreateLayer(Network self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type, char ** options=None) -> Layer"""
         return _gnm.Network_CreateLayer(self, *args, **kwargs)
 
+
     def CopyLayer(self, *args, **kwargs):
-        """CopyLayer(Network self, OGRLayerShadow * src_layer, char const * new_name, char ** options=None) -> OGRLayerShadow *"""
+        """CopyLayer(Network self, Layer src_layer, char const * new_name, char ** options=None) -> Layer"""
         return _gnm.Network_CopyLayer(self, *args, **kwargs)
 
+
     def DeleteLayer(self, *args):
         """DeleteLayer(Network self, int index) -> OGRErr"""
         return _gnm.Network_DeleteLayer(self, *args)
 
+
     def GetLayerCount(self, *args):
         """GetLayerCount(Network self) -> int"""
         return _gnm.Network_GetLayerCount(self, *args)
 
+
     def GetLayerByIndex(self, *args):
-        """GetLayerByIndex(Network self, int index=0) -> OGRLayerShadow *"""
+        """GetLayerByIndex(Network self, int index=0) -> Layer"""
         return _gnm.Network_GetLayerByIndex(self, *args)
 
+
     def GetLayerByName(self, *args):
-        """GetLayerByName(Network self, char const * layer_name) -> OGRLayerShadow *"""
+        """GetLayerByName(Network self, char const * layer_name) -> Layer"""
         return _gnm.Network_GetLayerByName(self, *args)
 
+
     def TestCapability(self, *args):
         """TestCapability(Network self, char const * cap) -> bool"""
         return _gnm.Network_TestCapability(self, *args)
 
+
     def StartTransaction(self, *args, **kwargs):
         """StartTransaction(Network self, int force=False) -> OGRErr"""
         return _gnm.Network_StartTransaction(self, *args, **kwargs)
 
+
     def CommitTransaction(self, *args):
         """CommitTransaction(Network self) -> OGRErr"""
         return _gnm.Network_CommitTransaction(self, *args)
 
+
     def RollbackTransaction(self, *args):
         """RollbackTransaction(Network self) -> OGRErr"""
         return _gnm.Network_RollbackTransaction(self, *args)
@@ -208,63 +246,73 @@ Network_swigregister = _gnm.Network_swigregister
 Network_swigregister(Network)
 
 class GenericNetwork(Network):
-    """Proxy of C++ GNMGenericNetworkShadow class"""
+    """Proxy of C++ GNMGenericNetworkShadow class."""
+
     __swig_setmethods__ = {}
-    for _s in [Network]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    for _s in [Network]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
     __setattr__ = lambda self, name, value: _swig_setattr(self, GenericNetwork, name, value)
     __swig_getmethods__ = {}
-    for _s in [Network]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    for _s in [Network]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
     __getattr__ = lambda self, name: _swig_getattr(self, GenericNetwork, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_destroy__ = _gnm.delete_GenericNetwork
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def ConnectFeatures(self, *args):
-        """
-        ConnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost, 
-            GNMDirection eDir) -> CPLErr
-        """
+        """ConnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost, GNMDirection eDir) -> CPLErr"""
         return _gnm.GenericNetwork_ConnectFeatures(self, *args)
 
+
     def DisconnectFeatures(self, *args):
         """DisconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID) -> CPLErr"""
         return _gnm.GenericNetwork_DisconnectFeatures(self, *args)
 
+
     def DisconnectFeaturesWithId(self, *args):
         """DisconnectFeaturesWithId(GenericNetwork self, GIntBig nFID) -> CPLErr"""
         return _gnm.GenericNetwork_DisconnectFeaturesWithId(self, *args)
 
+
     def ReconnectFeatures(self, *args):
-        """
-        ReconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost, 
-            GNMDirection eDir) -> CPLErr
-        """
+        """ReconnectFeatures(GenericNetwork self, GIntBig nSrcFID, GIntBig nTgtFID, GIntBig nConFID, double dfCost, double dfInvCost, GNMDirection eDir) -> CPLErr"""
         return _gnm.GenericNetwork_ReconnectFeatures(self, *args)
 
+
     def CreateRule(self, *args):
         """CreateRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"""
         return _gnm.GenericNetwork_CreateRule(self, *args)
 
+
     def DeleteAllRules(self, *args):
         """DeleteAllRules(GenericNetwork self) -> CPLErr"""
         return _gnm.GenericNetwork_DeleteAllRules(self, *args)
 
+
     def DeleteRule(self, *args):
         """DeleteRule(GenericNetwork self, char const * pszRuleStr) -> CPLErr"""
         return _gnm.GenericNetwork_DeleteRule(self, *args)
 
+
     def GetRules(self, *args):
         """GetRules(GenericNetwork self) -> char **"""
         return _gnm.GenericNetwork_GetRules(self, *args)
 
+
     def ConnectPointsByLines(self, *args, **kwargs):
         """ConnectPointsByLines(GenericNetwork self, char ** papszLayerList, double dfTolerance, double dfCost, double dfInvCost, GNMDirection eDir) -> CPLErr"""
         return _gnm.GenericNetwork_ConnectPointsByLines(self, *args, **kwargs)
 
+
     def ChangeBlockState(self, *args):
         """ChangeBlockState(GenericNetwork self, GIntBig nFID, bool bIsBlock) -> CPLErr"""
         return _gnm.GenericNetwork_ChangeBlockState(self, *args)
 
+
     def ChangeAllBlockState(self, *args):
         """ChangeAllBlockState(GenericNetwork self, bool bIsBlock=False) -> CPLErr"""
         return _gnm.GenericNetwork_ChangeAllBlockState(self, *args)
diff --git a/swig/python/osgeo/ogr.py b/swig/python/osgeo/ogr.py
index 12718e7..eb2fa7e 100644
--- a/swig/python/osgeo/ogr.py
+++ b/swig/python/osgeo/ogr.py
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
+# Version 3.0.8
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
@@ -9,7 +9,7 @@
 
 
 from sys import version_info
-if version_info >= (2,6,0):
+if version_info >= (2, 6, 0):
     def swig_import_helper():
         from os.path import dirname
         import imp
@@ -33,240 +33,575 @@ del version_info
 try:
     _swig_property = property
 except NameError:
-    pass # Python < 2.2 doesn't have 'property'.
-def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
-    if (name == "thisown"): return self.this.own(value)
+    pass  # Python < 2.2 doesn't have 'property'.
+
+
+def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
+    if (name == "thisown"):
+        return self.this.own(value)
     if (name == "this"):
         if type(value).__name__ == 'SwigPyObject':
             self.__dict__[name] = value
             return
-    method = class_type.__swig_setmethods__.get(name,None)
-    if method: return method(self,value)
+    method = class_type.__swig_setmethods__.get(name, None)
+    if method:
+        return method(self, value)
     if (not static):
-        self.__dict__[name] = value
+        if _newclass:
+            object.__setattr__(self, name, value)
+        else:
+            self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
 
-def _swig_setattr(self,class_type,name,value):
-    return _swig_setattr_nondynamic(self,class_type,name,value,0)
 
-def _swig_getattr(self,class_type,name):
-    if (name == "thisown"): return self.this.own()
-    method = class_type.__swig_getmethods__.get(name,None)
-    if method: return method(self)
-    raise AttributeError(name)
+def _swig_setattr(self, class_type, name, value):
+    return _swig_setattr_nondynamic(self, class_type, name, value, 0)
+
+
+def _swig_getattr_nondynamic(self, class_type, name, static=1):
+    if (name == "thisown"):
+        return self.this.own()
+    method = class_type.__swig_getmethods__.get(name, None)
+    if method:
+        return method(self)
+    if (not static):
+        return object.__getattr__(self, name)
+    else:
+        raise AttributeError(name)
+
+def _swig_getattr(self, class_type, name):
+    return _swig_getattr_nondynamic(self, class_type, name, 0)
+
 
 def _swig_repr(self):
-    try: strthis = "proxy of " + self.this.__repr__()
-    except: strthis = ""
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except Exception:
+        strthis = ""
     return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
 
 try:
     _object = object
     _newclass = 1
 except AttributeError:
-    class _object : pass
+    class _object:
+        pass
     _newclass = 0
 
 
+
+_ogr.wkb25DBit_swigconstant(_ogr)
 wkb25DBit = _ogr.wkb25DBit
+
+_ogr.wkb25Bit_swigconstant(_ogr)
 wkb25Bit = _ogr.wkb25Bit
+
+_ogr.wkbUnknown_swigconstant(_ogr)
 wkbUnknown = _ogr.wkbUnknown
+
+_ogr.wkbPoint_swigconstant(_ogr)
 wkbPoint = _ogr.wkbPoint
+
+_ogr.wkbLineString_swigconstant(_ogr)
 wkbLineString = _ogr.wkbLineString
+
+_ogr.wkbPolygon_swigconstant(_ogr)
 wkbPolygon = _ogr.wkbPolygon
+
+_ogr.wkbMultiPoint_swigconstant(_ogr)
 wkbMultiPoint = _ogr.wkbMultiPoint
+
+_ogr.wkbMultiLineString_swigconstant(_ogr)
 wkbMultiLineString = _ogr.wkbMultiLineString
+
+_ogr.wkbMultiPolygon_swigconstant(_ogr)
 wkbMultiPolygon = _ogr.wkbMultiPolygon
+
+_ogr.wkbGeometryCollection_swigconstant(_ogr)
 wkbGeometryCollection = _ogr.wkbGeometryCollection
+
+_ogr.wkbCircularString_swigconstant(_ogr)
 wkbCircularString = _ogr.wkbCircularString
+
+_ogr.wkbCompoundCurve_swigconstant(_ogr)
 wkbCompoundCurve = _ogr.wkbCompoundCurve
+
+_ogr.wkbCurvePolygon_swigconstant(_ogr)
 wkbCurvePolygon = _ogr.wkbCurvePolygon
+
+_ogr.wkbMultiCurve_swigconstant(_ogr)
 wkbMultiCurve = _ogr.wkbMultiCurve
+
+_ogr.wkbMultiSurface_swigconstant(_ogr)
 wkbMultiSurface = _ogr.wkbMultiSurface
+
+_ogr.wkbCurve_swigconstant(_ogr)
 wkbCurve = _ogr.wkbCurve
+
+_ogr.wkbSurface_swigconstant(_ogr)
 wkbSurface = _ogr.wkbSurface
+
+_ogr.wkbPolyhedralSurface_swigconstant(_ogr)
 wkbPolyhedralSurface = _ogr.wkbPolyhedralSurface
+
+_ogr.wkbTIN_swigconstant(_ogr)
 wkbTIN = _ogr.wkbTIN
+
+_ogr.wkbTriangle_swigconstant(_ogr)
+wkbTriangle = _ogr.wkbTriangle
+
+_ogr.wkbNone_swigconstant(_ogr)
 wkbNone = _ogr.wkbNone
+
+_ogr.wkbLinearRing_swigconstant(_ogr)
 wkbLinearRing = _ogr.wkbLinearRing
+
+_ogr.wkbCircularStringZ_swigconstant(_ogr)
 wkbCircularStringZ = _ogr.wkbCircularStringZ
+
+_ogr.wkbCompoundCurveZ_swigconstant(_ogr)
 wkbCompoundCurveZ = _ogr.wkbCompoundCurveZ
+
+_ogr.wkbCurvePolygonZ_swigconstant(_ogr)
 wkbCurvePolygonZ = _ogr.wkbCurvePolygonZ
+
+_ogr.wkbMultiCurveZ_swigconstant(_ogr)
 wkbMultiCurveZ = _ogr.wkbMultiCurveZ
+
+_ogr.wkbMultiSurfaceZ_swigconstant(_ogr)
 wkbMultiSurfaceZ = _ogr.wkbMultiSurfaceZ
+
+_ogr.wkbCurveZ_swigconstant(_ogr)
 wkbCurveZ = _ogr.wkbCurveZ
+
+_ogr.wkbSurfaceZ_swigconstant(_ogr)
 wkbSurfaceZ = _ogr.wkbSurfaceZ
+
+_ogr.wkbPolyhedralSurfaceZ_swigconstant(_ogr)
 wkbPolyhedralSurfaceZ = _ogr.wkbPolyhedralSurfaceZ
+
+_ogr.wkbTINZ_swigconstant(_ogr)
 wkbTINZ = _ogr.wkbTINZ
+
+_ogr.wkbTriangleZ_swigconstant(_ogr)
+wkbTriangleZ = _ogr.wkbTriangleZ
+
+_ogr.wkbPointM_swigconstant(_ogr)
 wkbPointM = _ogr.wkbPointM
+
+_ogr.wkbLineStringM_swigconstant(_ogr)
 wkbLineStringM = _ogr.wkbLineStringM
+
+_ogr.wkbPolygonM_swigconstant(_ogr)
 wkbPolygonM = _ogr.wkbPolygonM
+
+_ogr.wkbMultiPointM_swigconstant(_ogr)
 wkbMultiPointM = _ogr.wkbMultiPointM
+
+_ogr.wkbMultiLineStringM_swigconstant(_ogr)
 wkbMultiLineStringM = _ogr.wkbMultiLineStringM
+
+_ogr.wkbMultiPolygonM_swigconstant(_ogr)
 wkbMultiPolygonM = _ogr.wkbMultiPolygonM
+
+_ogr.wkbGeometryCollectionM_swigconstant(_ogr)
 wkbGeometryCollectionM = _ogr.wkbGeometryCollectionM
+
+_ogr.wkbCircularStringM_swigconstant(_ogr)
 wkbCircularStringM = _ogr.wkbCircularStringM
+
+_ogr.wkbCompoundCurveM_swigconstant(_ogr)
 wkbCompoundCurveM = _ogr.wkbCompoundCurveM
+
+_ogr.wkbCurvePolygonM_swigconstant(_ogr)
 wkbCurvePolygonM = _ogr.wkbCurvePolygonM
+
+_ogr.wkbMultiCurveM_swigconstant(_ogr)
 wkbMultiCurveM = _ogr.wkbMultiCurveM
+
+_ogr.wkbMultiSurfaceM_swigconstant(_ogr)
 wkbMultiSurfaceM = _ogr.wkbMultiSurfaceM
+
+_ogr.wkbCurveM_swigconstant(_ogr)
 wkbCurveM = _ogr.wkbCurveM
+
+_ogr.wkbSurfaceM_swigconstant(_ogr)
 wkbSurfaceM = _ogr.wkbSurfaceM
+
+_ogr.wkbPolyhedralSurfaceM_swigconstant(_ogr)
 wkbPolyhedralSurfaceM = _ogr.wkbPolyhedralSurfaceM
+
+_ogr.wkbTINM_swigconstant(_ogr)
 wkbTINM = _ogr.wkbTINM
+
+_ogr.wkbTriangleM_swigconstant(_ogr)
+wkbTriangleM = _ogr.wkbTriangleM
+
+_ogr.wkbPointZM_swigconstant(_ogr)
 wkbPointZM = _ogr.wkbPointZM
+
+_ogr.wkbLineStringZM_swigconstant(_ogr)
 wkbLineStringZM = _ogr.wkbLineStringZM
+
+_ogr.wkbPolygonZM_swigconstant(_ogr)
 wkbPolygonZM = _ogr.wkbPolygonZM
+
+_ogr.wkbMultiPointZM_swigconstant(_ogr)
 wkbMultiPointZM = _ogr.wkbMultiPointZM
+
+_ogr.wkbMultiLineStringZM_swigconstant(_ogr)
 wkbMultiLineStringZM = _ogr.wkbMultiLineStringZM
+
+_ogr.wkbMultiPolygonZM_swigconstant(_ogr)
 wkbMultiPolygonZM = _ogr.wkbMultiPolygonZM
+
+_ogr.wkbGeometryCollectionZM_swigconstant(_ogr)
 wkbGeometryCollectionZM = _ogr.wkbGeometryCollectionZM
+
+_ogr.wkbCircularStringZM_swigconstant(_ogr)
 wkbCircularStringZM = _ogr.wkbCircularStringZM
+
+_ogr.wkbCompoundCurveZM_swigconstant(_ogr)
 wkbCompoundCurveZM = _ogr.wkbCompoundCurveZM
+
+_ogr.wkbCurvePolygonZM_swigconstant(_ogr)
 wkbCurvePolygonZM = _ogr.wkbCurvePolygonZM
+
+_ogr.wkbMultiCurveZM_swigconstant(_ogr)
 wkbMultiCurveZM = _ogr.wkbMultiCurveZM
+
+_ogr.wkbMultiSurfaceZM_swigconstant(_ogr)
 wkbMultiSurfaceZM = _ogr.wkbMultiSurfaceZM
+
+_ogr.wkbCurveZM_swigconstant(_ogr)
 wkbCurveZM = _ogr.wkbCurveZM
+
+_ogr.wkbSurfaceZM_swigconstant(_ogr)
 wkbSurfaceZM = _ogr.wkbSurfaceZM
+
+_ogr.wkbPolyhedralSurfaceZM_swigconstant(_ogr)
 wkbPolyhedralSurfaceZM = _ogr.wkbPolyhedralSurfaceZM
+
+_ogr.wkbTINZM_swigconstant(_ogr)
 wkbTINZM = _ogr.wkbTINZM
+
+_ogr.wkbTriangleZM_swigconstant(_ogr)
+wkbTriangleZM = _ogr.wkbTriangleZM
+
+_ogr.wkbPoint25D_swigconstant(_ogr)
 wkbPoint25D = _ogr.wkbPoint25D
+
+_ogr.wkbLineString25D_swigconstant(_ogr)
 wkbLineString25D = _ogr.wkbLineString25D
+
+_ogr.wkbPolygon25D_swigconstant(_ogr)
 wkbPolygon25D = _ogr.wkbPolygon25D
+
+_ogr.wkbMultiPoint25D_swigconstant(_ogr)
 wkbMultiPoint25D = _ogr.wkbMultiPoint25D
+
+_ogr.wkbMultiLineString25D_swigconstant(_ogr)
 wkbMultiLineString25D = _ogr.wkbMultiLineString25D
+
+_ogr.wkbMultiPolygon25D_swigconstant(_ogr)
 wkbMultiPolygon25D = _ogr.wkbMultiPolygon25D
+
+_ogr.wkbGeometryCollection25D_swigconstant(_ogr)
 wkbGeometryCollection25D = _ogr.wkbGeometryCollection25D
+
+_ogr.OFTInteger_swigconstant(_ogr)
 OFTInteger = _ogr.OFTInteger
+
+_ogr.OFTIntegerList_swigconstant(_ogr)
 OFTIntegerList = _ogr.OFTIntegerList
+
+_ogr.OFTReal_swigconstant(_ogr)
 OFTReal = _ogr.OFTReal
+
+_ogr.OFTRealList_swigconstant(_ogr)
 OFTRealList = _ogr.OFTRealList
+
+_ogr.OFTString_swigconstant(_ogr)
 OFTString = _ogr.OFTString
+
+_ogr.OFTStringList_swigconstant(_ogr)
 OFTStringList = _ogr.OFTStringList
+
+_ogr.OFTWideString_swigconstant(_ogr)
 OFTWideString = _ogr.OFTWideString
+
+_ogr.OFTWideStringList_swigconstant(_ogr)
 OFTWideStringList = _ogr.OFTWideStringList
+
+_ogr.OFTBinary_swigconstant(_ogr)
 OFTBinary = _ogr.OFTBinary
+
+_ogr.OFTDate_swigconstant(_ogr)
 OFTDate = _ogr.OFTDate
+
+_ogr.OFTTime_swigconstant(_ogr)
 OFTTime = _ogr.OFTTime
+
+_ogr.OFTDateTime_swigconstant(_ogr)
 OFTDateTime = _ogr.OFTDateTime
+
+_ogr.OFTInteger64_swigconstant(_ogr)
 OFTInteger64 = _ogr.OFTInteger64
+
+_ogr.OFTInteger64List_swigconstant(_ogr)
 OFTInteger64List = _ogr.OFTInteger64List
+
+_ogr.OFSTNone_swigconstant(_ogr)
 OFSTNone = _ogr.OFSTNone
+
+_ogr.OFSTBoolean_swigconstant(_ogr)
 OFSTBoolean = _ogr.OFSTBoolean
+
+_ogr.OFSTInt16_swigconstant(_ogr)
 OFSTInt16 = _ogr.OFSTInt16
+
+_ogr.OFSTFloat32_swigconstant(_ogr)
 OFSTFloat32 = _ogr.OFSTFloat32
+
+_ogr.OJUndefined_swigconstant(_ogr)
 OJUndefined = _ogr.OJUndefined
+
+_ogr.OJLeft_swigconstant(_ogr)
 OJLeft = _ogr.OJLeft
+
+_ogr.OJRight_swigconstant(_ogr)
 OJRight = _ogr.OJRight
+
+_ogr.wkbXDR_swigconstant(_ogr)
 wkbXDR = _ogr.wkbXDR
+
+_ogr.wkbNDR_swigconstant(_ogr)
 wkbNDR = _ogr.wkbNDR
+
+_ogr.NullFID_swigconstant(_ogr)
 NullFID = _ogr.NullFID
+
+_ogr.ALTER_NAME_FLAG_swigconstant(_ogr)
 ALTER_NAME_FLAG = _ogr.ALTER_NAME_FLAG
+
+_ogr.ALTER_TYPE_FLAG_swigconstant(_ogr)
 ALTER_TYPE_FLAG = _ogr.ALTER_TYPE_FLAG
+
+_ogr.ALTER_WIDTH_PRECISION_FLAG_swigconstant(_ogr)
 ALTER_WIDTH_PRECISION_FLAG = _ogr.ALTER_WIDTH_PRECISION_FLAG
+
+_ogr.ALTER_NULLABLE_FLAG_swigconstant(_ogr)
 ALTER_NULLABLE_FLAG = _ogr.ALTER_NULLABLE_FLAG
+
+_ogr.ALTER_DEFAULT_FLAG_swigconstant(_ogr)
 ALTER_DEFAULT_FLAG = _ogr.ALTER_DEFAULT_FLAG
+
+_ogr.ALTER_ALL_FLAG_swigconstant(_ogr)
 ALTER_ALL_FLAG = _ogr.ALTER_ALL_FLAG
+
+_ogr.F_VAL_NULL_swigconstant(_ogr)
 F_VAL_NULL = _ogr.F_VAL_NULL
+
+_ogr.F_VAL_GEOM_TYPE_swigconstant(_ogr)
 F_VAL_GEOM_TYPE = _ogr.F_VAL_GEOM_TYPE
+
+_ogr.F_VAL_WIDTH_swigconstant(_ogr)
 F_VAL_WIDTH = _ogr.F_VAL_WIDTH
+
+_ogr.F_VAL_ALLOW_NULL_WHEN_DEFAULT_swigconstant(_ogr)
 F_VAL_ALLOW_NULL_WHEN_DEFAULT = _ogr.F_VAL_ALLOW_NULL_WHEN_DEFAULT
+
+_ogr.F_VAL_ALL_swigconstant(_ogr)
 F_VAL_ALL = _ogr.F_VAL_ALL
+
+_ogr.OLCRandomRead_swigconstant(_ogr)
 OLCRandomRead = _ogr.OLCRandomRead
+
+_ogr.OLCSequentialWrite_swigconstant(_ogr)
 OLCSequentialWrite = _ogr.OLCSequentialWrite
+
+_ogr.OLCRandomWrite_swigconstant(_ogr)
 OLCRandomWrite = _ogr.OLCRandomWrite
+
+_ogr.OLCFastSpatialFilter_swigconstant(_ogr)
 OLCFastSpatialFilter = _ogr.OLCFastSpatialFilter
+
+_ogr.OLCFastFeatureCount_swigconstant(_ogr)
 OLCFastFeatureCount = _ogr.OLCFastFeatureCount
+
+_ogr.OLCFastGetExtent_swigconstant(_ogr)
 OLCFastGetExtent = _ogr.OLCFastGetExtent
+
+_ogr.OLCCreateField_swigconstant(_ogr)
 OLCCreateField = _ogr.OLCCreateField
+
+_ogr.OLCDeleteField_swigconstant(_ogr)
 OLCDeleteField = _ogr.OLCDeleteField
+
+_ogr.OLCReorderFields_swigconstant(_ogr)
 OLCReorderFields = _ogr.OLCReorderFields
+
+_ogr.OLCAlterFieldDefn_swigconstant(_ogr)
 OLCAlterFieldDefn = _ogr.OLCAlterFieldDefn
+
+_ogr.OLCTransactions_swigconstant(_ogr)
 OLCTransactions = _ogr.OLCTransactions
+
+_ogr.OLCDeleteFeature_swigconstant(_ogr)
 OLCDeleteFeature = _ogr.OLCDeleteFeature
+
+_ogr.OLCFastSetNextByIndex_swigconstant(_ogr)
 OLCFastSetNextByIndex = _ogr.OLCFastSetNextByIndex
+
+_ogr.OLCStringsAsUTF8_swigconstant(_ogr)
 OLCStringsAsUTF8 = _ogr.OLCStringsAsUTF8
+
+_ogr.OLCIgnoreFields_swigconstant(_ogr)
 OLCIgnoreFields = _ogr.OLCIgnoreFields
+
+_ogr.OLCCreateGeomField_swigconstant(_ogr)
 OLCCreateGeomField = _ogr.OLCCreateGeomField
+
+_ogr.OLCCurveGeometries_swigconstant(_ogr)
 OLCCurveGeometries = _ogr.OLCCurveGeometries
+
+_ogr.OLCMeasuredGeometries_swigconstant(_ogr)
 OLCMeasuredGeometries = _ogr.OLCMeasuredGeometries
+
+_ogr.ODsCCreateLayer_swigconstant(_ogr)
 ODsCCreateLayer = _ogr.ODsCCreateLayer
+
+_ogr.ODsCDeleteLayer_swigconstant(_ogr)
 ODsCDeleteLayer = _ogr.ODsCDeleteLayer
+
+_ogr.ODsCCreateGeomFieldAfterCreateLayer_swigconstant(_ogr)
 ODsCCreateGeomFieldAfterCreateLayer = _ogr.ODsCCreateGeomFieldAfterCreateLayer
+
+_ogr.ODsCCurveGeometries_swigconstant(_ogr)
 ODsCCurveGeometries = _ogr.ODsCCurveGeometries
+
+_ogr.ODsCTransactions_swigconstant(_ogr)
 ODsCTransactions = _ogr.ODsCTransactions
+
+_ogr.ODsCEmulatedTransactions_swigconstant(_ogr)
 ODsCEmulatedTransactions = _ogr.ODsCEmulatedTransactions
+
+_ogr.ODsCMeasuredGeometries_swigconstant(_ogr)
 ODsCMeasuredGeometries = _ogr.ODsCMeasuredGeometries
+
+_ogr.ODsCRandomLayerRead_swigconstant(_ogr)
+ODsCRandomLayerRead = _ogr.ODsCRandomLayerRead
+
+_ogr.ODsCRandomLayerWrite_swigconstant(_ogr)
+ODsCRandomLayerWrite = _ogr.ODsCRandomLayerWrite
+
+_ogr.ODrCCreateDataSource_swigconstant(_ogr)
 ODrCCreateDataSource = _ogr.ODrCCreateDataSource
+
+_ogr.ODrCDeleteDataSource_swigconstant(_ogr)
 ODrCDeleteDataSource = _ogr.ODrCDeleteDataSource
+
+_ogr.OLMD_FID64_swigconstant(_ogr)
 OLMD_FID64 = _ogr.OLMD_FID64
+
+_ogr.OGRERR_NONE_swigconstant(_ogr)
 OGRERR_NONE = _ogr.OGRERR_NONE
+
+_ogr.OGRERR_NOT_ENOUGH_DATA_swigconstant(_ogr)
 OGRERR_NOT_ENOUGH_DATA = _ogr.OGRERR_NOT_ENOUGH_DATA
+
+_ogr.OGRERR_NOT_ENOUGH_MEMORY_swigconstant(_ogr)
 OGRERR_NOT_ENOUGH_MEMORY = _ogr.OGRERR_NOT_ENOUGH_MEMORY
+
+_ogr.OGRERR_UNSUPPORTED_GEOMETRY_TYPE_swigconstant(_ogr)
 OGRERR_UNSUPPORTED_GEOMETRY_TYPE = _ogr.OGRERR_UNSUPPORTED_GEOMETRY_TYPE
+
+_ogr.OGRERR_UNSUPPORTED_OPERATION_swigconstant(_ogr)
 OGRERR_UNSUPPORTED_OPERATION = _ogr.OGRERR_UNSUPPORTED_OPERATION
+
+_ogr.OGRERR_CORRUPT_DATA_swigconstant(_ogr)
 OGRERR_CORRUPT_DATA = _ogr.OGRERR_CORRUPT_DATA
+
+_ogr.OGRERR_FAILURE_swigconstant(_ogr)
 OGRERR_FAILURE = _ogr.OGRERR_FAILURE
+
+_ogr.OGRERR_UNSUPPORTED_SRS_swigconstant(_ogr)
 OGRERR_UNSUPPORTED_SRS = _ogr.OGRERR_UNSUPPORTED_SRS
+
+_ogr.OGRERR_INVALID_HANDLE_swigconstant(_ogr)
 OGRERR_INVALID_HANDLE = _ogr.OGRERR_INVALID_HANDLE
+
+_ogr.OGRERR_NON_EXISTING_FEATURE_swigconstant(_ogr)
 OGRERR_NON_EXISTING_FEATURE = _ogr.OGRERR_NON_EXISTING_FEATURE
 
 def GetUseExceptions(*args):
-  """GetUseExceptions() -> int"""
-  return _ogr.GetUseExceptions(*args)
+    """GetUseExceptions() -> int"""
+    return _ogr.GetUseExceptions(*args)
 
 def UseExceptions(*args):
-  """UseExceptions()"""
-  return _ogr.UseExceptions(*args)
+    """UseExceptions()"""
+    return _ogr.UseExceptions(*args)
 
 def DontUseExceptions(*args):
-  """DontUseExceptions()"""
-  return _ogr.DontUseExceptions(*args)
+    """DontUseExceptions()"""
+    return _ogr.DontUseExceptions(*args)
 import osr
 class MajorObject(_object):
-    """Proxy of C++ GDALMajorObjectShadow class"""
+    """Proxy of C++ GDALMajorObjectShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, MajorObject, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, MajorObject, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
+
     def GetDescription(self, *args):
         """GetDescription(MajorObject self) -> char const *"""
         return _ogr.MajorObject_GetDescription(self, *args)
 
+
     def SetDescription(self, *args):
         """SetDescription(MajorObject self, char const * pszNewDesc)"""
         return _ogr.MajorObject_SetDescription(self, *args)
 
+
     def GetMetadataDomainList(self, *args):
         """GetMetadataDomainList(MajorObject self) -> char **"""
         return _ogr.MajorObject_GetMetadataDomainList(self, *args)
 
+
     def GetMetadata_Dict(self, *args):
-        """GetMetadata_Dict(MajorObject self, char const * pszDomain="") -> char **"""
+        """GetMetadata_Dict(MajorObject self, char const * pszDomain) -> char **"""
         return _ogr.MajorObject_GetMetadata_Dict(self, *args)
 
+
     def GetMetadata_List(self, *args):
-        """GetMetadata_List(MajorObject self, char const * pszDomain="") -> char **"""
+        """GetMetadata_List(MajorObject self, char const * pszDomain) -> char **"""
         return _ogr.MajorObject_GetMetadata_List(self, *args)
 
+
     def SetMetadata(self, *args):
         """
-        SetMetadata(MajorObject self, char ** papszMetadata, char const * pszDomain="") -> CPLErr
-        SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain="") -> CPLErr
+        SetMetadata(MajorObject self, char ** papszMetadata, char const * pszDomain) -> CPLErr
+        SetMetadata(MajorObject self, char * pszMetadataString, char const * pszDomain) -> CPLErr
         """
         return _ogr.MajorObject_SetMetadata(self, *args)
 
+
     def GetMetadataItem(self, *args):
-        """GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain="") -> char const *"""
+        """GetMetadataItem(MajorObject self, char const * pszName, char const * pszDomain) -> char const *"""
         return _ogr.MajorObject_GetMetadataItem(self, *args)
 
+
     def SetMetadataItem(self, *args):
-        """SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain="") -> CPLErr"""
+        """SetMetadataItem(MajorObject self, char const * pszName, char const * pszValue, char const * pszDomain) -> CPLErr"""
         return _ogr.MajorObject_SetMetadataItem(self, *args)
 
+
     def GetMetadata( self, domain = '' ):
       if domain[:4] == 'xml:':
         return self.GetMetadata_List( domain )
@@ -276,43 +611,54 @@ MajorObject_swigregister = _ogr.MajorObject_swigregister
 MajorObject_swigregister(MajorObject)
 
 class StyleTable(_object):
-    """Proxy of C++ OGRStyleTableShadow class"""
+    """Proxy of C++ OGRStyleTableShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, StyleTable, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, StyleTable, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(OGRStyleTableShadow self) -> StyleTable"""
         this = _ogr.new_StyleTable(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _ogr.delete_StyleTable
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def AddStyle(self, *args):
         """AddStyle(StyleTable self, char const * pszName, char const * pszStyleString) -> int"""
         return _ogr.StyleTable_AddStyle(self, *args)
 
+
     def LoadStyleTable(self, *args):
         """LoadStyleTable(StyleTable self, char const * utf8_path) -> int"""
         return _ogr.StyleTable_LoadStyleTable(self, *args)
 
+
     def SaveStyleTable(self, *args):
         """SaveStyleTable(StyleTable self, char const * utf8_path) -> int"""
         return _ogr.StyleTable_SaveStyleTable(self, *args)
 
+
     def Find(self, *args):
         """Find(StyleTable self, char const * pszName) -> char const *"""
         return _ogr.StyleTable_Find(self, *args)
 
+
     def ResetStyleStringReading(self, *args):
         """ResetStyleStringReading(StyleTable self)"""
         return _ogr.StyleTable_ResetStyleStringReading(self, *args)
 
+
     def GetNextStyle(self, *args):
         """GetNextStyle(StyleTable self) -> char const *"""
         return _ogr.StyleTable_GetNextStyle(self, *args)
 
+
     def GetLastStyleName(self, *args):
         """GetLastStyleName(StyleTable self) -> char const *"""
         return _ogr.StyleTable_GetLastStyleName(self, *args)
@@ -321,17 +667,24 @@ StyleTable_swigregister = _ogr.StyleTable_swigregister
 StyleTable_swigregister(StyleTable)
 
 class Driver(MajorObject):
-    """Proxy of C++ OGRDriverShadow class"""
+    """Proxy of C++ OGRDriverShadow class."""
+
     __swig_setmethods__ = {}
-    for _s in [MajorObject]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
     __setattr__ = lambda self, name, value: _swig_setattr(self, Driver, name, value)
     __swig_getmethods__ = {}
-    for _s in [MajorObject]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
     __getattr__ = lambda self, name: _swig_getattr(self, Driver, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_getmethods__["name"] = _ogr.Driver_name_get
-    if _newclass:name = _swig_property(_ogr.Driver_name_get)
+    if _newclass:
+        name = _swig_property(_ogr.Driver_name_get)
+
     def CreateDataSource(self, *args, **kwargs):
         """
         CreateDataSource(Driver self, char const * utf8_path, char ** options=None) -> DataSource
@@ -368,6 +721,7 @@ class Driver(MajorObject):
         """
         return _ogr.Driver_CreateDataSource(self, *args, **kwargs)
 
+
     def CopyDataSource(self, *args, **kwargs):
         """
         CopyDataSource(Driver self, DataSource copy_ds, char const * utf8_path, char ** options=None) -> DataSource
@@ -402,6 +756,7 @@ class Driver(MajorObject):
         """
         return _ogr.Driver_CopyDataSource(self, *args, **kwargs)
 
+
     def Open(self, *args, **kwargs):
         """
         Open(Driver self, char const * utf8_path, int update=0) -> DataSource
@@ -434,6 +789,7 @@ class Driver(MajorObject):
         """
         return _ogr.Driver_Open(self, *args, **kwargs)
 
+
     def DeleteDataSource(self, *args):
         """
         DeleteDataSource(Driver self, char const * utf8_path) -> int
@@ -465,6 +821,7 @@ class Driver(MajorObject):
         """
         return _ogr.Driver_DeleteDataSource(self, *args)
 
+
     def TestCapability(self, *args):
         """
         TestCapability(Driver self, char const * cap) -> bool
@@ -501,6 +858,7 @@ class Driver(MajorObject):
         """
         return _ogr.Driver_TestCapability(self, *args)
 
+
     def GetName(self, *args):
         """
         GetName(Driver self) -> char const *
@@ -525,10 +883,12 @@ class Driver(MajorObject):
         """
         return _ogr.Driver_GetName(self, *args)
 
+
     def Register(self, *args):
         """Register(Driver self)"""
         return _ogr.Driver_Register(self, *args)
 
+
     def Deregister(self, *args):
         """Deregister(Driver self)"""
         return _ogr.Driver_Deregister(self, *args)
@@ -537,19 +897,26 @@ Driver_swigregister = _ogr.Driver_swigregister
 Driver_swigregister(Driver)
 
 class DataSource(MajorObject):
-    """Proxy of C++ OGRDataSourceShadow class"""
+    """Proxy of C++ OGRDataSourceShadow class."""
+
     __swig_setmethods__ = {}
-    for _s in [MajorObject]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
     __setattr__ = lambda self, name, value: _swig_setattr(self, DataSource, name, value)
     __swig_getmethods__ = {}
-    for _s in [MajorObject]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
     __getattr__ = lambda self, name: _swig_getattr(self, DataSource, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
     __swig_getmethods__["name"] = _ogr.DataSource_name_get
-    if _newclass:name = _swig_property(_ogr.DataSource_name_get)
+    if _newclass:
+        name = _swig_property(_ogr.DataSource_name_get)
     __swig_destroy__ = _ogr.delete_DataSource
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def GetRefCount(self, *args):
         """
         GetRefCount(DataSource self) -> int
@@ -559,6 +926,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_GetRefCount(self, *args)
 
+
     def GetSummaryRefCount(self, *args):
         """
         GetSummaryRefCount(DataSource self) -> int
@@ -568,6 +936,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_GetSummaryRefCount(self, *args)
 
+
     def GetLayerCount(self, *args):
         """
         GetLayerCount(DataSource self) -> int
@@ -589,6 +958,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_GetLayerCount(self, *args)
 
+
     def GetDriver(self, *args):
         """
         GetDriver(DataSource self) -> Driver
@@ -614,6 +984,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_GetDriver(self, *args)
 
+
     def GetName(self, *args):
         """
         GetName(DataSource self) -> char const *
@@ -640,6 +1011,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_GetName(self, *args)
 
+
     def DeleteLayer(self, *args):
         """
         DeleteLayer(DataSource self, int index) -> OGRErr
@@ -666,6 +1038,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_DeleteLayer(self, *args)
 
+
     def SyncToDisk(self, *args):
         """
         SyncToDisk(DataSource self) -> OGRErr
@@ -675,14 +1048,15 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_SyncToDisk(self, *args)
 
+
     def FlushCache(self, *args):
         """FlushCache(DataSource self)"""
         return _ogr.DataSource_FlushCache(self, *args)
 
+
     def CreateLayer(self, *args, **kwargs):
         """
-        CreateLayer(DataSource self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type=wkbUnknown, 
-            char ** options=None) -> Layer
+        CreateLayer(DataSource self, char const * name, SpatialReference srs=None, OGRwkbGeometryType geom_type, char ** options=None) -> Layer
 
         OGRLayerH
         OGR_DS_CreateLayer(OGRDataSourceH hDS, const char *pszName,
@@ -721,6 +1095,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_CreateLayer(self, *args, **kwargs)
 
+
     def CopyLayer(self, *args, **kwargs):
         """
         CopyLayer(DataSource self, Layer src_layer, char const * new_name, char ** options=None) -> Layer
@@ -756,10 +1131,12 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_CopyLayer(self, *args, **kwargs)
 
+
     def GetLayerByIndex(self, *args):
         """GetLayerByIndex(DataSource self, int index=0) -> Layer"""
         return _ogr.DataSource_GetLayerByIndex(self, *args)
 
+
     def GetLayerByName(self, *args):
         """
         GetLayerByName(DataSource self, char const * layer_name) -> Layer
@@ -786,6 +1163,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_GetLayerByName(self, *args)
 
+
     def TestCapability(self, *args):
         """
         TestCapability(DataSource self, char const * cap) -> bool
@@ -826,9 +1204,10 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_TestCapability(self, *args)
 
+
     def ExecuteSQL(self, *args, **kwargs):
         """
-        ExecuteSQL(DataSource self, char const * statement, Geometry spatialFilter=None, char const * dialect="") -> Layer
+        ExecuteSQL(DataSource self, char const * statement, Geometry spatialFilter=None, char const * dialect) -> Layer
 
         OGRLayerH
         OGR_DS_ExecuteSQL(OGRDataSourceH hDS, const char *pszStatement,
@@ -872,6 +1251,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_ExecuteSQL(self, *args, **kwargs)
 
+
     def ReleaseResultSet(self, *args):
         """
         ReleaseResultSet(DataSource self, Layer layer)
@@ -898,6 +1278,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_ReleaseResultSet(self, *args)
 
+
     def GetStyleTable(self, *args):
         """
         GetStyleTable(DataSource self) -> StyleTable
@@ -907,6 +1288,7 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_GetStyleTable(self, *args)
 
+
     def SetStyleTable(self, *args):
         """
         SetStyleTable(DataSource self, StyleTable table)
@@ -917,18 +1299,22 @@ class DataSource(MajorObject):
         """
         return _ogr.DataSource_SetStyleTable(self, *args)
 
+
     def StartTransaction(self, *args, **kwargs):
         """StartTransaction(DataSource self, int force=False) -> OGRErr"""
         return _ogr.DataSource_StartTransaction(self, *args, **kwargs)
 
+
     def CommitTransaction(self, *args):
         """CommitTransaction(DataSource self) -> OGRErr"""
         return _ogr.DataSource_CommitTransaction(self, *args)
 
+
     def RollbackTransaction(self, *args):
         """RollbackTransaction(DataSource self) -> OGRErr"""
         return _ogr.DataSource_RollbackTransaction(self, *args)
 
+
     def Destroy(self):
       "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_DataSource( self )
@@ -999,15 +1385,21 @@ DataSource_swigregister = _ogr.DataSource_swigregister
 DataSource_swigregister(DataSource)
 
 class Layer(MajorObject):
-    """Proxy of C++ OGRLayerShadow class"""
+    """Proxy of C++ OGRLayerShadow class."""
+
     __swig_setmethods__ = {}
-    for _s in [MajorObject]: __swig_setmethods__.update(getattr(_s,'__swig_setmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_setmethods__.update(getattr(_s, '__swig_setmethods__', {}))
     __setattr__ = lambda self, name, value: _swig_setattr(self, Layer, name, value)
     __swig_getmethods__ = {}
-    for _s in [MajorObject]: __swig_getmethods__.update(getattr(_s,'__swig_getmethods__',{}))
+    for _s in [MajorObject]:
+        __swig_getmethods__.update(getattr(_s, '__swig_getmethods__', {}))
     __getattr__ = lambda self, name: _swig_getattr(self, Layer, name)
-    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
+
+    def __init__(self, *args, **kwargs):
+        raise AttributeError("No constructor defined")
     __repr__ = _swig_repr
+
     def GetRefCount(self, *args):
         """
         GetRefCount(Layer self) -> int
@@ -1017,6 +1409,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetRefCount(self, *args)
 
+
     def SetSpatialFilter(self, *args):
         """
         SetSpatialFilter(Layer self, Geometry filter)
@@ -1060,6 +1453,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_SetSpatialFilter(self, *args)
 
+
     def SetSpatialFilterRect(self, *args):
         """
         SetSpatialFilterRect(Layer self, double minx, double miny, double maxx, double maxy)
@@ -1102,6 +1496,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_SetSpatialFilterRect(self, *args)
 
+
     def GetSpatialFilter(self, *args):
         """
         GetSpatialFilter(Layer self) -> Geometry
@@ -1126,6 +1521,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetSpatialFilter(self, *args)
 
+
     def SetAttributeFilter(self, *args):
         """
         SetAttributeFilter(Layer self, char * filter_string) -> OGRErr
@@ -1167,6 +1563,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_SetAttributeFilter(self, *args)
 
+
     def ResetReading(self, *args):
         """
         ResetReading(Layer self)
@@ -1187,6 +1584,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_ResetReading(self, *args)
 
+
     def GetName(self, *args):
         """
         GetName(Layer self) -> char const *
@@ -1214,6 +1612,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetName(self, *args)
 
+
     def GetGeomType(self, *args):
         """
         GetGeomType(Layer self) -> OGRwkbGeometryType
@@ -1247,6 +1646,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetGeomType(self, *args)
 
+
     def GetGeometryColumn(self, *args):
         """
         GetGeometryColumn(Layer self) -> char const *
@@ -1274,6 +1674,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetGeometryColumn(self, *args)
 
+
     def GetFIDColumn(self, *args):
         """
         GetFIDColumn(Layer self) -> char const *
@@ -1295,6 +1696,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetFIDColumn(self, *args)
 
+
     def GetFeature(self, *args):
         """
         GetFeature(Layer self, GIntBig fid) -> Feature
@@ -1337,6 +1739,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetFeature(self, *args)
 
+
     def GetNextFeature(self, *args):
         """
         GetNextFeature(Layer self) -> Feature
@@ -1380,6 +1783,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetNextFeature(self, *args)
 
+
     def SetNextByIndex(self, *args):
         """
         SetNextByIndex(Layer self, GIntBig new_index) -> OGRErr
@@ -1417,6 +1821,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_SetNextByIndex(self, *args)
 
+
     def SetFeature(self, *args):
         """
         SetFeature(Layer self, Feature feature) -> OGRErr
@@ -1447,6 +1852,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_SetFeature(self, *args)
 
+
     def CreateFeature(self, *args):
         """
         CreateFeature(Layer self, Feature feature) -> OGRErr
@@ -1476,6 +1882,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_CreateFeature(self, *args)
 
+
     def DeleteFeature(self, *args):
         """
         DeleteFeature(Layer self, GIntBig fid) -> OGRErr
@@ -1506,6 +1913,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_DeleteFeature(self, *args)
 
+
     def SyncToDisk(self, *args):
         """
         SyncToDisk(Layer self) -> OGRErr
@@ -1539,6 +1947,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_SyncToDisk(self, *args)
 
+
     def GetLayerDefn(self, *args):
         """
         GetLayerDefn(Layer self) -> FeatureDefn
@@ -1563,6 +1972,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetLayerDefn(self, *args)
 
+
     def GetFeatureCount(self, *args, **kwargs):
         """
         GetFeatureCount(Layer self, int force=1) -> GIntBig
@@ -1600,6 +2010,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetFeatureCount(self, *args, **kwargs)
 
+
     def GetExtent(self, *args, **kwargs):
         """
         GetExtent(Layer self, int force=1, int can_return_null=0, int geom_field=0)
@@ -1641,6 +2052,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetExtent(self, *args, **kwargs)
 
+
     def TestCapability(self, *args):
         """
         TestCapability(Layer self, char const * cap) -> bool
@@ -1738,6 +2150,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_TestCapability(self, *args)
 
+
     def CreateField(self, *args, **kwargs):
         """
         CreateField(Layer self, FieldDefn field_def, int approx_ok=1) -> OGRErr
@@ -1783,6 +2196,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_CreateField(self, *args, **kwargs)
 
+
     def DeleteField(self, *args):
         """
         DeleteField(Layer self, int iField) -> OGRErr
@@ -1822,6 +2236,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_DeleteField(self, *args)
 
+
     def ReorderField(self, *args):
         """
         ReorderField(Layer self, int iOldFieldPos, int iNewFieldPos) -> OGRErr
@@ -1877,6 +2292,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_ReorderField(self, *args)
 
+
     def ReorderFields(self, *args):
         """
         ReorderFields(Layer self, int nList) -> OGRErr
@@ -1925,6 +2341,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_ReorderFields(self, *args)
 
+
     def AlterFieldDefn(self, *args):
         """
         AlterFieldDefn(Layer self, int iField, FieldDefn field_def, int nFlags) -> OGRErr
@@ -1975,6 +2392,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_AlterFieldDefn(self, *args)
 
+
     def CreateGeomField(self, *args, **kwargs):
         """
         CreateGeomField(Layer self, GeomFieldDefn field_def, int approx_ok=1) -> OGRErr
@@ -2022,6 +2440,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_CreateGeomField(self, *args, **kwargs)
 
+
     def StartTransaction(self, *args):
         """
         StartTransaction(Layer self) -> OGRErr
@@ -2054,6 +2473,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_StartTransaction(self, *args)
 
+
     def CommitTransaction(self, *args):
         """
         CommitTransaction(Layer self) -> OGRErr
@@ -2080,6 +2500,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_CommitTransaction(self, *args)
 
+
     def RollbackTransaction(self, *args):
         """
         RollbackTransaction(Layer self) -> OGRErr
@@ -2107,6 +2528,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_RollbackTransaction(self, *args)
 
+
     def FindFieldIndex(self, *args):
         """
         FindFieldIndex(Layer self, char const * pszFieldName, int bExactMatch) -> int
@@ -2131,6 +2553,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_FindFieldIndex(self, *args)
 
+
     def GetSpatialRef(self, *args):
         """
         GetSpatialRef(Layer self) -> SpatialReference
@@ -2154,6 +2577,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetSpatialRef(self, *args)
 
+
     def GetFeaturesRead(self, *args):
         """
         GetFeaturesRead(Layer self) -> GIntBig
@@ -2163,6 +2587,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetFeaturesRead(self, *args)
 
+
     def SetIgnoredFields(self, *args):
         """
         SetIgnoredFields(Layer self, char const ** options) -> OGRErr
@@ -2197,10 +2622,10 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_SetIgnoredFields(self, *args)
 
+
     def Intersection(self, *args, **kwargs):
         """
-        Intersection(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, 
-            void * callback_data=None) -> OGRErr
+        Intersection(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr
 
         OGRErr
         OGR_L_Intersection(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
@@ -2276,10 +2701,10 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_Intersection(self, *args, **kwargs)
 
+
     def Union(self, *args, **kwargs):
         """
-        Union(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, 
-            void * callback_data=None) -> OGRErr
+        Union(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr
 
         OGRErr OGR_L_Union(OGRLayerH
         pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
@@ -2351,10 +2776,10 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_Union(self, *args, **kwargs)
 
+
     def SymDifference(self, *args, **kwargs):
         """
-        SymDifference(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, 
-            void * callback_data=None) -> OGRErr
+        SymDifference(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr
 
         OGRErr
         OGR_L_SymDifference(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
@@ -2423,10 +2848,10 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_SymDifference(self, *args, **kwargs)
 
+
     def Identity(self, *args, **kwargs):
         """
-        Identity(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, 
-            void * callback_data=None) -> OGRErr
+        Identity(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr
 
         OGRErr OGR_L_Identity(OGRLayerH
         pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
@@ -2496,10 +2921,10 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_Identity(self, *args, **kwargs)
 
+
     def Update(self, *args, **kwargs):
         """
-        Update(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, 
-            void * callback_data=None) -> OGRErr
+        Update(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr
 
         OGRErr OGR_L_Update(OGRLayerH
         pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
@@ -2567,10 +2992,10 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_Update(self, *args, **kwargs)
 
+
     def Clip(self, *args, **kwargs):
         """
-        Clip(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, 
-            void * callback_data=None) -> OGRErr
+        Clip(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr
 
         OGRErr OGR_L_Clip(OGRLayerH pLayerInput,
         OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char **papszOptions,
@@ -2631,10 +3056,10 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_Clip(self, *args, **kwargs)
 
+
     def Erase(self, *args, **kwargs):
         """
-        Erase(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, 
-            void * callback_data=None) -> OGRErr
+        Erase(Layer self, Layer method_layer, Layer result_layer, char ** options=None, GDALProgressFunc callback=0, void * callback_data=None) -> OGRErr
 
         OGRErr OGR_L_Erase(OGRLayerH
         pLayerInput, OGRLayerH pLayerMethod, OGRLayerH pLayerResult, char
@@ -2694,6 +3119,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_Erase(self, *args, **kwargs)
 
+
     def GetStyleTable(self, *args):
         """
         GetStyleTable(Layer self) -> StyleTable
@@ -2703,6 +3129,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_GetStyleTable(self, *args)
 
+
     def SetStyleTable(self, *args):
         """
         SetStyleTable(Layer self, StyleTable table)
@@ -2712,6 +3139,7 @@ class Layer(MajorObject):
         """
         return _ogr.Layer_SetStyleTable(self, *args)
 
+
     def Reference(self):
       "For backwards compatibility only."
       pass
@@ -2740,9 +3168,9 @@ class Layer(MajorObject):
             import sys
             output = []
             if value.stop == sys.maxint:
-                #for an unending slice, sys.maxint is used
-                #We need to stop before that or GDAL will write an
-                ##error to stdout
+    #for an unending slice, sys.maxint is used
+    #We need to stop before that or GDAL will write an
+    ##error to stdout
                 stop = len(self) - 1
             else:
                 stop = value.stop
@@ -2788,19 +3216,24 @@ Layer_swigregister = _ogr.Layer_swigregister
 Layer_swigregister(Layer)
 
 class Feature(_object):
-    """Proxy of C++ OGRFeatureShadow class"""
+    """Proxy of C++ OGRFeatureShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, Feature, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, Feature, name)
     __repr__ = _swig_repr
     __swig_destroy__ = _ogr.delete_Feature
-    __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
+    __del__ = lambda self: None
+
+    def __init__(self, *args, **kwargs):
         """__init__(OGRFeatureShadow self, FeatureDefn feature_def) -> Feature"""
         this = _ogr.new_Feature(*args, **kwargs)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
+
     def GetDefnRef(self, *args):
         """
         GetDefnRef(Feature self) -> FeatureDefn
@@ -2822,6 +3255,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetDefnRef(self, *args)
 
+
     def SetGeometry(self, *args):
         """
         SetGeometry(Feature self, Geometry geom) -> OGRErr
@@ -2850,6 +3284,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetGeometry(self, *args)
 
+
     def SetGeometryDirectly(self, *args):
         """
         SetGeometryDirectly(Feature self, Geometry geom) -> OGRErr
@@ -2879,6 +3314,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetGeometryDirectly(self, *args)
 
+
     def GetGeometryRef(self, *args):
         """
         GetGeometryRef(Feature self) -> Geometry
@@ -2901,6 +3337,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetGeometryRef(self, *args)
 
+
     def SetGeomField(self, *args):
         """
         SetGeomField(Feature self, int iField, Geometry geom) -> OGRErr
@@ -2932,6 +3369,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetGeomField(self, *args)
 
+
     def SetGeomFieldDirectly(self, *args):
         """
         SetGeomFieldDirectly(Feature self, int iField, Geometry geom) -> OGRErr
@@ -2967,6 +3405,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetGeomFieldDirectly(self, *args)
 
+
     def GetGeomFieldRef(self, *args):
         """
         GetGeomFieldRef(Feature self, int iField) -> Geometry
@@ -2994,6 +3433,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetGeomFieldRef(self, *args)
 
+
     def Clone(self, *args):
         """
         Clone(Feature self) -> Feature
@@ -3017,6 +3457,7 @@ class Feature(_object):
         """
         return _ogr.Feature_Clone(self, *args)
 
+
     def Equal(self, *args):
         """
         Equal(Feature self, Feature feature) -> bool
@@ -3043,6 +3484,7 @@ class Feature(_object):
         """
         return _ogr.Feature_Equal(self, *args)
 
+
     def GetFieldCount(self, *args):
         """
         GetFieldCount(Feature self) -> int
@@ -3065,6 +3507,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldCount(self, *args)
 
+
     def GetFieldDefnRef(self, *args):
         """
         GetFieldDefnRef(Feature self, int id) -> FieldDefn
@@ -3090,6 +3533,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldDefnRef(self, *args)
 
+
     def GetGeomFieldCount(self, *args):
         """
         GetGeomFieldCount(Feature self) -> int
@@ -3114,6 +3558,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetGeomFieldCount(self, *args)
 
+
     def GetGeomFieldDefnRef(self, *args):
         """
         GetGeomFieldDefnRef(Feature self, int id) -> GeomFieldDefn
@@ -3141,6 +3586,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetGeomFieldDefnRef(self, *args)
 
+
     def GetFieldAsString(self, *args):
         """
         GetFieldAsString(Feature self, int id) -> char const
@@ -3170,6 +3616,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsString(self, *args)
 
+
     def GetFieldAsInteger(self, *args):
         """
         GetFieldAsInteger(Feature self, int id) -> int
@@ -3198,6 +3645,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsInteger(self, *args)
 
+
     def GetFieldAsInteger64(self, *args):
         """
         GetFieldAsInteger64(Feature self, int id) -> GIntBig
@@ -3229,6 +3677,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsInteger64(self, *args)
 
+
     def GetFieldAsDouble(self, *args):
         """
         GetFieldAsDouble(Feature self, int id) -> double
@@ -3257,6 +3706,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsDouble(self, *args)
 
+
     def GetFieldAsDateTime(self, *args):
         """
         GetFieldAsDateTime(Feature self, int id)
@@ -3304,6 +3754,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsDateTime(self, *args)
 
+
     def GetFieldAsIntegerList(self, *args):
         """
         GetFieldAsIntegerList(Feature self, int id)
@@ -3335,6 +3786,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsIntegerList(self, *args)
 
+
     def GetFieldAsInteger64List(self, *args):
         """
         GetFieldAsInteger64List(Feature self, int id)
@@ -3367,6 +3819,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsInteger64List(self, *args)
 
+
     def GetFieldAsDoubleList(self, *args):
         """
         GetFieldAsDoubleList(Feature self, int id)
@@ -3398,6 +3851,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsDoubleList(self, *args)
 
+
     def GetFieldAsStringList(self, *args):
         """
         GetFieldAsStringList(Feature self, int id) -> char **
@@ -3427,6 +3881,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsStringList(self, *args)
 
+
     def GetFieldAsBinary(self, *args):
         """
         GetFieldAsBinary(Feature self, int id) -> OGRErr
@@ -3456,6 +3911,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldAsBinary(self, *args)
 
+
     def IsFieldSet(self, *args):
         """
         IsFieldSet(Feature self, int id) -> bool
@@ -3479,6 +3935,23 @@ class Feature(_object):
         """
         return _ogr.Feature_IsFieldSet(self, *args)
 
+
+    def IsFieldNull(self, *args):
+        """
+        IsFieldNull(Feature self, int id) -> bool
+        IsFieldNull(Feature self, char const * name) -> bool
+        """
+        return _ogr.Feature_IsFieldNull(self, *args)
+
+
+    def IsFieldSetAndNotNull(self, *args):
+        """
+        IsFieldSetAndNotNull(Feature self, int id) -> bool
+        IsFieldSetAndNotNull(Feature self, char const * name) -> bool
+        """
+        return _ogr.Feature_IsFieldSetAndNotNull(self, *args)
+
+
     def GetFieldIndex(self, *args):
         """
         GetFieldIndex(Feature self, char const * name) -> int
@@ -3504,6 +3977,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldIndex(self, *args)
 
+
     def GetGeomFieldIndex(self, *args):
         """
         GetGeomFieldIndex(Feature self, char const * name) -> int
@@ -3532,6 +4006,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetGeomFieldIndex(self, *args)
 
+
     def GetFID(self, *args):
         """
         GetFID(Feature self) -> GIntBig
@@ -3555,6 +4030,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFID(self, *args)
 
+
     def SetFID(self, *args):
         """
         SetFID(Feature self, GIntBig fid) -> OGRErr
@@ -3582,6 +4058,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFID(self, *args)
 
+
     def DumpReadable(self, *args):
         """
         DumpReadable(Feature self)
@@ -3607,6 +4084,7 @@ class Feature(_object):
         """
         return _ogr.Feature_DumpReadable(self, *args)
 
+
     def UnsetField(self, *args):
         """
         UnsetField(Feature self, int id)
@@ -3628,6 +4106,15 @@ class Feature(_object):
         """
         return _ogr.Feature_UnsetField(self, *args)
 
+
+    def SetFieldNull(self, *args):
+        """
+        SetFieldNull(Feature self, int id)
+        SetFieldNull(Feature self, char const * name)
+        """
+        return _ogr.Feature_SetFieldNull(self, *args)
+
+
     def SetFieldInteger64(self, *args):
         """
         SetFieldInteger64(Feature self, int id, GIntBig value)
@@ -3657,6 +4144,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFieldInteger64(self, *args)
 
+
     def SetField(self, *args):
         """
         SetField(Feature self, int id, char const * value)
@@ -3664,11 +4152,11 @@ class Feature(_object):
         SetField(Feature self, int id, double value)
         SetField(Feature self, char const * name, double value)
         SetField(Feature self, int id, int year, int month, int day, int hour, int minute, float second, int tzflag)
-        SetField(Feature self, char const * name, int year, int month, int day, int hour, int minute, float second, 
-            int tzflag)
+        SetField(Feature self, char const * name, int year, int month, int day, int hour, int minute, float second, int tzflag)
         """
         return _ogr.Feature_SetField(self, *args)
 
+
     def SetFieldIntegerList(self, *args):
         """
         SetFieldIntegerList(Feature self, int id, int nList)
@@ -3697,6 +4185,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFieldIntegerList(self, *args)
 
+
     def SetFieldInteger64List(self, *args):
         """
         SetFieldInteger64List(Feature self, int id, int nList)
@@ -3727,6 +4216,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFieldInteger64List(self, *args)
 
+
     def SetFieldDoubleList(self, *args):
         """
         SetFieldDoubleList(Feature self, int id, int nList)
@@ -3755,6 +4245,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFieldDoubleList(self, *args)
 
+
     def SetFieldStringList(self, *args):
         """
         SetFieldStringList(Feature self, int id, char ** pList)
@@ -3780,6 +4271,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFieldStringList(self, *args)
 
+
     def SetFieldBinaryFromHexString(self, *args):
         """
         SetFieldBinaryFromHexString(Feature self, int id, char const * pszValue)
@@ -3787,6 +4279,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFieldBinaryFromHexString(self, *args)
 
+
     def SetFrom(self, *args, **kwargs):
         """
         SetFrom(Feature self, Feature other, int forgiving=1) -> OGRErr
@@ -3820,6 +4313,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFrom(self, *args, **kwargs)
 
+
     def SetFromWithMap(self, *args):
         """
         SetFromWithMap(Feature self, Feature other, int forgiving, int nList) -> OGRErr
@@ -3863,6 +4357,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFromWithMap(self, *args)
 
+
     def GetStyleString(self, *args):
         """
         GetStyleString(Feature self) -> char const *
@@ -3889,6 +4384,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetStyleString(self, *args)
 
+
     def SetStyleString(self, *args):
         """
         SetStyleString(Feature self, char const * the_string)
@@ -3915,6 +4411,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetStyleString(self, *args)
 
+
     def GetFieldType(self, *args):
         """
         GetFieldType(Feature self, int id) -> OGRFieldType
@@ -3922,9 +4419,10 @@ class Feature(_object):
         """
         return _ogr.Feature_GetFieldType(self, *args)
 
+
     def Validate(self, *args):
         """
-        Validate(Feature self, int flags=OGR_F_VAL_ALL, int bEmitError=True) -> int
+        Validate(Feature self, int flags, int bEmitError=True) -> int
 
         int OGR_F_Validate(OGRFeatureH
         hFeat, int nValidateFlags, int bEmitError)
@@ -3958,6 +4456,7 @@ class Feature(_object):
         """
         return _ogr.Feature_Validate(self, *args)
 
+
     def FillUnsetWithDefault(self, *args):
         """
         FillUnsetWithDefault(Feature self, int bNotNullableOnly=False, char ** options=None)
@@ -3985,6 +4484,7 @@ class Feature(_object):
         """
         return _ogr.Feature_FillUnsetWithDefault(self, *args)
 
+
     def GetNativeData(self, *args):
         """
         GetNativeData(Feature self) -> char const *
@@ -4027,6 +4527,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetNativeData(self, *args)
 
+
     def GetNativeMediaType(self, *args):
         """
         GetNativeMediaType(Feature self) -> char const *
@@ -4059,6 +4560,7 @@ class Feature(_object):
         """
         return _ogr.Feature_GetNativeMediaType(self, *args)
 
+
     def SetNativeData(self, *args):
         """
         SetNativeData(Feature self, char const * nativeData)
@@ -4092,6 +4594,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetNativeData(self, *args)
 
+
     def SetNativeMediaType(self, *args):
         """
         SetNativeMediaType(Feature self, char const * nativeMediaType)
@@ -4126,6 +4629,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetNativeMediaType(self, *args)
 
+
     def SetFieldString(self, *args):
         """
         SetFieldString(Feature self, int id, char const * value)
@@ -4155,6 +4659,7 @@ class Feature(_object):
         """
         return _ogr.Feature_SetFieldString(self, *args)
 
+
     def Reference(self):
       pass
 
@@ -4242,7 +4747,7 @@ class Feature(_object):
             fld_index = self.GetFieldIndex(fld_index)
         if (fld_index < 0) or (fld_index > self.GetFieldCount()):
             raise ValueError("Illegal field requested in GetField()")
-        if not (self.IsFieldSet(fld_index)):
+        if not (self.IsFieldSet(fld_index)) or self.IsFieldNull(fld_index):
             return None
         fld_type = self.GetFieldType(fld_index)
         if fld_type == OFTInteger:
@@ -4259,13 +4764,13 @@ class Feature(_object):
             return self.GetFieldAsInteger64List(fld_index)
         if fld_type == OFTRealList:
             return self.GetFieldAsDoubleList(fld_index)
-        ## if fld_type == OFTDateTime or fld_type == OFTDate or fld_type == OFTTime:
-        #     return self.GetFieldAsDate(fld_index)
-        # default to returning as a string.  Should we add more types?
+    ## if fld_type == OFTDateTime or fld_type == OFTDate or fld_type == OFTTime:
+    #     return self.GetFieldAsDate(fld_index)
+    # default to returning as a string.  Should we add more types?
         try:
             return self.GetFieldAsString(fld_index)
         except:
-            # For Python3 on non-UTF8 strings
+    # For Python3 on non-UTF8 strings
             return self.GetFieldAsBinary(fld_index)
 
     # With several override, SWIG cannot dispatch automatically unicode strings
@@ -4284,6 +4789,9 @@ class Feature(_object):
             int minute, int second, int tzflag)
         """
 
+        if len(args) == 2 and args[1] is None:
+            return _ogr.Feature_SetFieldNull(self, args[0])
+
         if len(args) == 2 and (type(args[1]) == type(1) or type(args[1]) == type(12345678901234)):
             fld_index = args[0]
             if isinstance(fld_index, str):
@@ -4306,12 +4814,12 @@ class Feature(_object):
             raise ValueError("Illegal field requested in SetField2()")
 
         if value is None:
-            self.UnsetField( fld_index )
+            self.SetFieldNull( fld_index )
             return
 
         if isinstance(value,list):
             if len(value) == 0:
-                self.UnsetField( fld_index )
+                self.SetFieldNull( fld_index )
                 return
             if isinstance(value[0],type(1)) or isinstance(value[0],type(12345678901234)):
                 self.SetFieldInteger64List(fld_index,value)
@@ -4400,19 +4908,24 @@ Feature_swigregister = _ogr.Feature_swigregister
 Feature_swigregister(Feature)
 
 class FeatureDefn(_object):
-    """Proxy of C++ OGRFeatureDefnShadow class"""
+    """Proxy of C++ OGRFeatureDefnShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, FeatureDefn, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, FeatureDefn, name)
     __repr__ = _swig_repr
     __swig_destroy__ = _ogr.delete_FeatureDefn
-    __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
+    __del__ = lambda self: None
+
+    def __init__(self, *args, **kwargs):
         """__init__(OGRFeatureDefnShadow self, char const * name_null_ok=None) -> FeatureDefn"""
         this = _ogr.new_FeatureDefn(*args, **kwargs)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
+
     def GetName(self, *args):
         """
         GetName(FeatureDefn self) -> char const *
@@ -4434,6 +4947,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_GetName(self, *args)
 
+
     def GetFieldCount(self, *args):
         """
         GetFieldCount(FeatureDefn self) -> int
@@ -4454,6 +4968,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_GetFieldCount(self, *args)
 
+
     def GetFieldDefn(self, *args):
         """
         GetFieldDefn(FeatureDefn self, int i) -> FieldDefn
@@ -4483,6 +4998,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_GetFieldDefn(self, *args)
 
+
     def GetFieldIndex(self, *args):
         """
         GetFieldIndex(FeatureDefn self, char const * name) -> int
@@ -4509,6 +5025,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_GetFieldIndex(self, *args)
 
+
     def AddFieldDefn(self, *args):
         """
         AddFieldDefn(FeatureDefn self, FieldDefn defn)
@@ -4538,6 +5055,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_AddFieldDefn(self, *args)
 
+
     def GetGeomFieldCount(self, *args):
         """
         GetGeomFieldCount(FeatureDefn self) -> int
@@ -4561,6 +5079,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_GetGeomFieldCount(self, *args)
 
+
     def GetGeomFieldDefn(self, *args):
         """
         GetGeomFieldDefn(FeatureDefn self, int i) -> GeomFieldDefn
@@ -4589,6 +5108,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_GetGeomFieldDefn(self, *args)
 
+
     def GetGeomFieldIndex(self, *args):
         """
         GetGeomFieldIndex(FeatureDefn self, char const * name) -> int
@@ -4616,6 +5136,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_GetGeomFieldIndex(self, *args)
 
+
     def AddGeomFieldDefn(self, *args):
         """
         AddGeomFieldDefn(FeatureDefn self, GeomFieldDefn defn)
@@ -4649,6 +5170,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_AddGeomFieldDefn(self, *args)
 
+
     def DeleteGeomFieldDefn(self, *args):
         """
         DeleteGeomFieldDefn(FeatureDefn self, int idx) -> OGRErr
@@ -4681,6 +5203,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_DeleteGeomFieldDefn(self, *args)
 
+
     def GetGeomType(self, *args):
         """
         GetGeomType(FeatureDefn self) -> OGRwkbGeometryType
@@ -4706,6 +5229,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_GetGeomType(self, *args)
 
+
     def SetGeomType(self, *args):
         """
         SetGeomType(FeatureDefn self, OGRwkbGeometryType geom_type)
@@ -4737,6 +5261,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_SetGeomType(self, *args)
 
+
     def GetReferenceCount(self, *args):
         """
         GetReferenceCount(FeatureDefn self) -> int
@@ -4759,6 +5284,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_GetReferenceCount(self, *args)
 
+
     def IsGeometryIgnored(self, *args):
         """
         IsGeometryIgnored(FeatureDefn self) -> int
@@ -4784,6 +5310,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_IsGeometryIgnored(self, *args)
 
+
     def SetGeometryIgnored(self, *args):
         """
         SetGeometryIgnored(FeatureDefn self, int bIgnored)
@@ -4809,6 +5336,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_SetGeometryIgnored(self, *args)
 
+
     def IsStyleIgnored(self, *args):
         """
         IsStyleIgnored(FeatureDefn self) -> int
@@ -4831,6 +5359,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_IsStyleIgnored(self, *args)
 
+
     def SetStyleIgnored(self, *args):
         """
         SetStyleIgnored(FeatureDefn self, int bIgnored)
@@ -4853,6 +5382,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_SetStyleIgnored(self, *args)
 
+
     def IsSame(self, *args):
         """
         IsSame(FeatureDefn self, FeatureDefn other_defn) -> int
@@ -4876,6 +5406,7 @@ class FeatureDefn(_object):
         """
         return _ogr.FeatureDefn_IsSame(self, *args)
 
+
     def Destroy(self):
       "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_FeatureDefn( self )
@@ -4886,23 +5417,29 @@ FeatureDefn_swigregister = _ogr.FeatureDefn_swigregister
 FeatureDefn_swigregister(FeatureDefn)
 
 class FieldDefn(_object):
-    """Proxy of C++ OGRFieldDefnShadow class"""
+    """Proxy of C++ OGRFieldDefnShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, FieldDefn, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, FieldDefn, name)
     __repr__ = _swig_repr
     __swig_destroy__ = _ogr.delete_FieldDefn
-    __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
-        """__init__(OGRFieldDefnShadow self, char const * name_null_ok="unnamed", OGRFieldType field_type=OFTString) -> FieldDefn"""
+    __del__ = lambda self: None
+
+    def __init__(self, *args, **kwargs):
+        """__init__(OGRFieldDefnShadow self, char const * name_null_ok, OGRFieldType field_type) -> FieldDefn"""
         this = _ogr.new_FieldDefn(*args, **kwargs)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
+
     def GetName(self, *args):
         """GetName(FieldDefn self) -> char const *"""
         return _ogr.FieldDefn_GetName(self, *args)
 
+
     def GetNameRef(self, *args):
         """
         GetNameRef(FieldDefn self) -> char const *
@@ -4924,6 +5461,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_GetNameRef(self, *args)
 
+
     def SetName(self, *args):
         """
         SetName(FieldDefn self, char const * name)
@@ -4944,6 +5482,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_SetName(self, *args)
 
+
     def GetType(self, *args):
         """
         GetType(FieldDefn self) -> OGRFieldType
@@ -4964,6 +5503,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_GetType(self, *args)
 
+
     def SetType(self, *args):
         """
         SetType(FieldDefn self, OGRFieldType type)
@@ -4987,6 +5527,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_SetType(self, *args)
 
+
     def GetSubType(self, *args):
         """
         GetSubType(FieldDefn self) -> OGRFieldSubType
@@ -5010,6 +5551,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_GetSubType(self, *args)
 
+
     def SetSubType(self, *args):
         """
         SetSubType(FieldDefn self, OGRFieldSubType type)
@@ -5036,6 +5578,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_SetSubType(self, *args)
 
+
     def GetJustify(self, *args):
         """
         GetJustify(FieldDefn self) -> OGRJustification
@@ -5059,6 +5602,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_GetJustify(self, *args)
 
+
     def SetJustify(self, *args):
         """
         SetJustify(FieldDefn self, OGRJustification justify)
@@ -5082,6 +5626,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_SetJustify(self, *args)
 
+
     def GetWidth(self, *args):
         """
         GetWidth(FieldDefn self) -> int
@@ -5102,6 +5647,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_GetWidth(self, *args)
 
+
     def SetWidth(self, *args):
         """
         SetWidth(FieldDefn self, int width)
@@ -5122,6 +5668,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_SetWidth(self, *args)
 
+
     def GetPrecision(self, *args):
         """
         GetPrecision(FieldDefn self) -> int
@@ -5145,6 +5692,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_GetPrecision(self, *args)
 
+
     def SetPrecision(self, *args):
         """
         SetPrecision(FieldDefn self, int precision)
@@ -5168,14 +5716,17 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_SetPrecision(self, *args)
 
+
     def GetTypeName(self, *args):
         """GetTypeName(FieldDefn self) -> char const *"""
         return _ogr.FieldDefn_GetTypeName(self, *args)
 
+
     def GetFieldTypeName(self, *args):
         """GetFieldTypeName(FieldDefn self, OGRFieldType type) -> char const *"""
         return _ogr.FieldDefn_GetFieldTypeName(self, *args)
 
+
     def IsIgnored(self, *args):
         """
         IsIgnored(FieldDefn self) -> int
@@ -5196,6 +5747,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_IsIgnored(self, *args)
 
+
     def SetIgnored(self, *args):
         """
         SetIgnored(FieldDefn self, int bIgnored)
@@ -5216,6 +5768,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_SetIgnored(self, *args)
 
+
     def IsNullable(self, *args):
         """
         IsNullable(FieldDefn self) -> int
@@ -5245,6 +5798,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_IsNullable(self, *args)
 
+
     def SetNullable(self, *args):
         """
         SetNullable(FieldDefn self, int bNullable)
@@ -5273,6 +5827,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_SetNullable(self, *args)
 
+
     def GetDefault(self, *args):
         """
         GetDefault(FieldDefn self) -> char const *
@@ -5296,6 +5851,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_GetDefault(self, *args)
 
+
     def SetDefault(self, *args):
         """
         SetDefault(FieldDefn self, char const * pszValue)
@@ -5337,6 +5893,7 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_SetDefault(self, *args)
 
+
     def IsDefaultDriverSpecific(self, *args):
         """
         IsDefaultDriverSpecific(FieldDefn self) -> int
@@ -5365,12 +5922,14 @@ class FieldDefn(_object):
         """
         return _ogr.FieldDefn_IsDefaultDriverSpecific(self, *args)
 
+
     width = property(GetWidth, SetWidth)
     type = property(GetType, SetType)
     precision = property(GetPrecision, SetPrecision)
     name = property(GetName, SetName)
     justify = property(GetJustify, SetJustify)
 
+
     def Destroy(self):
       "Once called, self has effectively been destroyed.  Do not access. For backwards compatibility only"
       _ogr.delete_FieldDefn( self )
@@ -5380,63 +5939,79 @@ FieldDefn_swigregister = _ogr.FieldDefn_swigregister
 FieldDefn_swigregister(FieldDefn)
 
 class GeomFieldDefn(_object):
-    """Proxy of C++ OGRGeomFieldDefnShadow class"""
+    """Proxy of C++ OGRGeomFieldDefnShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, GeomFieldDefn, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, GeomFieldDefn, name)
     __repr__ = _swig_repr
     __swig_destroy__ = _ogr.delete_GeomFieldDefn
-    __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
-        """__init__(OGRGeomFieldDefnShadow self, char const * name_null_ok="", OGRwkbGeometryType field_type=wkbUnknown) -> GeomFieldDefn"""
+    __del__ = lambda self: None
+
+    def __init__(self, *args, **kwargs):
+        """__init__(OGRGeomFieldDefnShadow self, char const * name_null_ok, OGRwkbGeometryType field_type) -> GeomFieldDefn"""
         this = _ogr.new_GeomFieldDefn(*args, **kwargs)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
+
     def GetName(self, *args):
         """GetName(GeomFieldDefn self) -> char const *"""
         return _ogr.GeomFieldDefn_GetName(self, *args)
 
+
     def GetNameRef(self, *args):
         """GetNameRef(GeomFieldDefn self) -> char const *"""
         return _ogr.GeomFieldDefn_GetNameRef(self, *args)
 
+
     def SetName(self, *args):
         """SetName(GeomFieldDefn self, char const * name)"""
         return _ogr.GeomFieldDefn_SetName(self, *args)
 
+
     def GetType(self, *args):
         """GetType(GeomFieldDefn self) -> OGRwkbGeometryType"""
         return _ogr.GeomFieldDefn_GetType(self, *args)
 
+
     def SetType(self, *args):
         """SetType(GeomFieldDefn self, OGRwkbGeometryType type)"""
         return _ogr.GeomFieldDefn_SetType(self, *args)
 
+
     def GetSpatialRef(self, *args):
         """GetSpatialRef(GeomFieldDefn self) -> SpatialReference"""
         return _ogr.GeomFieldDefn_GetSpatialRef(self, *args)
 
+
     def SetSpatialRef(self, *args):
         """SetSpatialRef(GeomFieldDefn self, SpatialReference srs)"""
         return _ogr.GeomFieldDefn_SetSpatialRef(self, *args)
 
+
     def IsIgnored(self, *args):
         """IsIgnored(GeomFieldDefn self) -> int"""
         return _ogr.GeomFieldDefn_IsIgnored(self, *args)
 
+
     def SetIgnored(self, *args):
         """SetIgnored(GeomFieldDefn self, int bIgnored)"""
         return _ogr.GeomFieldDefn_SetIgnored(self, *args)
 
+
     def IsNullable(self, *args):
         """IsNullable(GeomFieldDefn self) -> int"""
         return _ogr.GeomFieldDefn_IsNullable(self, *args)
 
+
     def SetNullable(self, *args):
         """SetNullable(GeomFieldDefn self, int bNullable)"""
         return _ogr.GeomFieldDefn_SetNullable(self, *args)
 
+
     type = property(GetType, SetType)
     name = property(GetName, SetName)
     srs = property(GetSpatialRef, SetSpatialRef)
@@ -5446,69 +6021,71 @@ GeomFieldDefn_swigregister(GeomFieldDefn)
 
 
 def CreateGeometryFromWkb(*args, **kwargs):
-  """CreateGeometryFromWkb(int len, SpatialReference reference=None) -> Geometry"""
-  return _ogr.CreateGeometryFromWkb(*args, **kwargs)
+    """CreateGeometryFromWkb(int len, SpatialReference reference=None) -> Geometry"""
+    return _ogr.CreateGeometryFromWkb(*args, **kwargs)
 
 def CreateGeometryFromWkt(*args, **kwargs):
-  """CreateGeometryFromWkt(char ** val, SpatialReference reference=None) -> Geometry"""
-  return _ogr.CreateGeometryFromWkt(*args, **kwargs)
+    """CreateGeometryFromWkt(char ** val, SpatialReference reference=None) -> Geometry"""
+    return _ogr.CreateGeometryFromWkt(*args, **kwargs)
 
 def CreateGeometryFromGML(*args):
-  """CreateGeometryFromGML(char const * input_string) -> Geometry"""
-  return _ogr.CreateGeometryFromGML(*args)
+    """CreateGeometryFromGML(char const * input_string) -> Geometry"""
+    return _ogr.CreateGeometryFromGML(*args)
 
 def CreateGeometryFromJson(*args):
-  """CreateGeometryFromJson(char const * input_string) -> Geometry"""
-  return _ogr.CreateGeometryFromJson(*args)
+    """CreateGeometryFromJson(char const * input_string) -> Geometry"""
+    return _ogr.CreateGeometryFromJson(*args)
 
 def BuildPolygonFromEdges(*args, **kwargs):
-  """BuildPolygonFromEdges(Geometry hLineCollection, int bBestEffort=0, int bAutoClose=0, double dfTolerance=0) -> Geometry"""
-  return _ogr.BuildPolygonFromEdges(*args, **kwargs)
+    """BuildPolygonFromEdges(Geometry hLineCollection, int bBestEffort=0, int bAutoClose=0, double dfTolerance=0) -> Geometry"""
+    return _ogr.BuildPolygonFromEdges(*args, **kwargs)
 
 def ApproximateArcAngles(*args, **kwargs):
-  """
-    ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, double dfSecondaryAxis, 
-        double dfRotation, double dfStartAngle, double dfEndAngle, double dfMaxAngleStepSizeDegrees) -> Geometry
-    """
-  return _ogr.ApproximateArcAngles(*args, **kwargs)
+    """ApproximateArcAngles(double dfCenterX, double dfCenterY, double dfZ, double dfPrimaryRadius, double dfSecondaryAxis, double dfRotation, double dfStartAngle, double dfEndAngle, double dfMaxAngleStepSizeDegrees) -> Geometry"""
+    return _ogr.ApproximateArcAngles(*args, **kwargs)
 
 def ForceToPolygon(*args):
-  """ForceToPolygon(Geometry geom_in) -> Geometry"""
-  return _ogr.ForceToPolygon(*args)
+    """ForceToPolygon(Geometry geom_in) -> Geometry"""
+    return _ogr.ForceToPolygon(*args)
 
 def ForceToLineString(*args):
-  """ForceToLineString(Geometry geom_in) -> Geometry"""
-  return _ogr.ForceToLineString(*args)
+    """ForceToLineString(Geometry geom_in) -> Geometry"""
+    return _ogr.ForceToLineString(*args)
 
 def ForceToMultiPolygon(*args):
-  """ForceToMultiPolygon(Geometry geom_in) -> Geometry"""
-  return _ogr.ForceToMultiPolygon(*args)
+    """ForceToMultiPolygon(Geometry geom_in) -> Geometry"""
+    return _ogr.ForceToMultiPolygon(*args)
 
 def ForceToMultiPoint(*args):
-  """ForceToMultiPoint(Geometry geom_in) -> Geometry"""
-  return _ogr.ForceToMultiPoint(*args)
+    """ForceToMultiPoint(Geometry geom_in) -> Geometry"""
+    return _ogr.ForceToMultiPoint(*args)
 
 def ForceToMultiLineString(*args):
-  """ForceToMultiLineString(Geometry geom_in) -> Geometry"""
-  return _ogr.ForceToMultiLineString(*args)
+    """ForceToMultiLineString(Geometry geom_in) -> Geometry"""
+    return _ogr.ForceToMultiLineString(*args)
 
 def ForceTo(*args):
-  """ForceTo(Geometry geom_in, OGRwkbGeometryType eTargetType, char ** options=None) -> Geometry"""
-  return _ogr.ForceTo(*args)
+    """ForceTo(Geometry geom_in, OGRwkbGeometryType eTargetType, char ** options=None) -> Geometry"""
+    return _ogr.ForceTo(*args)
 class Geometry(_object):
-    """Proxy of C++ OGRGeometryShadow class"""
+    """Proxy of C++ OGRGeometryShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, Geometry, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, Geometry, name)
     __repr__ = _swig_repr
     __swig_destroy__ = _ogr.delete_Geometry
-    __del__ = lambda self : None;
-    def __init__(self, *args, **kwargs): 
-        """__init__(OGRGeometryShadow self, OGRwkbGeometryType type=wkbUnknown, char * wkt=None, int wkb=0, char * gml=None) -> Geometry"""
+    __del__ = lambda self: None
+
+    def __init__(self, *args, **kwargs):
+        """__init__(OGRGeometryShadow self, OGRwkbGeometryType type, char * wkt=None, int wkb=0, char * gml=None) -> Geometry"""
         this = _ogr.new_Geometry(*args, **kwargs)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
+
     def ExportToWkt(self, *args):
         """
         ExportToWkt(Geometry self) -> OGRErr
@@ -5535,12 +6112,13 @@ class Geometry(_object):
 
         ppszSrcText:  a text buffer is allocated by the program, and assigned
         to the passed pointer. After use, *ppszDstText should be freed with
-        OGRFree().
+        CPLFree().
 
         Currently OGRERR_NONE is always returned. 
         """
         return _ogr.Geometry_ExportToWkt(self, *args)
 
+
     def ExportToIsoWkt(self, *args):
         """
         ExportToIsoWkt(Geometry self) -> OGRErr
@@ -5565,7 +6143,7 @@ class Geometry(_object):
 
         ppszSrcText:  a text buffer is allocated by the program, and assigned
         to the passed pointer. After use, *ppszDstText should be freed with
-        OGRFree().
+        CPLFree().
 
         Currently OGRERR_NONE is always returned.
 
@@ -5573,9 +6151,10 @@ class Geometry(_object):
         """
         return _ogr.Geometry_ExportToIsoWkt(self, *args)
 
+
     def ExportToWkb(self, *args, **kwargs):
         """
-        ExportToWkb(Geometry self, OGRwkbByteOrder byte_order=wkbXDR) -> OGRErr
+        ExportToWkb(Geometry self, OGRwkbByteOrder byte_order) -> OGRErr
 
         OGRErr
         OGR_G_ExportToWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder, unsigned
@@ -5610,9 +6189,10 @@ class Geometry(_object):
         """
         return _ogr.Geometry_ExportToWkb(self, *args, **kwargs)
 
+
     def ExportToIsoWkb(self, *args, **kwargs):
         """
-        ExportToIsoWkb(Geometry self, OGRwkbByteOrder byte_order=wkbXDR) -> OGRErr
+        ExportToIsoWkb(Geometry self, OGRwkbByteOrder byte_order) -> OGRErr
 
         OGRErr
         OGR_G_ExportToIsoWkb(OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
@@ -5647,42 +6227,52 @@ class Geometry(_object):
         """
         return _ogr.Geometry_ExportToIsoWkb(self, *args, **kwargs)
 
+
     def ExportToGML(self, *args, **kwargs):
         """ExportToGML(Geometry self, char ** options=None) -> retStringAndCPLFree *"""
         return _ogr.Geometry_ExportToGML(self, *args, **kwargs)
 
+
     def ExportToKML(self, *args):
         """ExportToKML(Geometry self, char const * altitude_mode=None) -> retStringAndCPLFree *"""
         return _ogr.Geometry_ExportToKML(self, *args)
 
+
     def ExportToJson(self, *args, **kwargs):
         """ExportToJson(Geometry self, char ** options=None) -> retStringAndCPLFree *"""
         return _ogr.Geometry_ExportToJson(self, *args, **kwargs)
 
+
     def AddPoint(self, *args, **kwargs):
         """AddPoint(Geometry self, double x, double y, double z=0)"""
         return _ogr.Geometry_AddPoint(self, *args, **kwargs)
 
+
     def AddPointM(self, *args, **kwargs):
         """AddPointM(Geometry self, double x, double y, double m)"""
         return _ogr.Geometry_AddPointM(self, *args, **kwargs)
 
+
     def AddPointZM(self, *args, **kwargs):
         """AddPointZM(Geometry self, double x, double y, double z, double m)"""
         return _ogr.Geometry_AddPointZM(self, *args, **kwargs)
 
+
     def AddPoint_2D(self, *args):
         """AddPoint_2D(Geometry self, double x, double y)"""
         return _ogr.Geometry_AddPoint_2D(self, *args)
 
+
     def AddGeometryDirectly(self, *args):
         """AddGeometryDirectly(Geometry self, Geometry other_disown) -> OGRErr"""
         return _ogr.Geometry_AddGeometryDirectly(self, *args)
 
+
     def AddGeometry(self, *args):
         """AddGeometry(Geometry self, Geometry other) -> OGRErr"""
         return _ogr.Geometry_AddGeometry(self, *args)
 
+
     def Clone(self, *args):
         """
         Clone(Geometry self) -> Geometry
@@ -5706,6 +6296,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Clone(self, *args)
 
+
     def GetGeometryType(self, *args):
         """
         GetGeometryType(Geometry self) -> OGRwkbGeometryType
@@ -5731,6 +6322,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_GetGeometryType(self, *args)
 
+
     def GetGeometryName(self, *args):
         """
         GetGeometryName(Geometry self) -> char const *
@@ -5754,78 +6346,97 @@ class Geometry(_object):
         """
         return _ogr.Geometry_GetGeometryName(self, *args)
 
+
     def Length(self, *args):
         """Length(Geometry self) -> double"""
         return _ogr.Geometry_Length(self, *args)
 
+
     def Area(self, *args):
         """Area(Geometry self) -> double"""
         return _ogr.Geometry_Area(self, *args)
 
+
     def GetArea(self, *args):
         """GetArea(Geometry self) -> double"""
         return _ogr.Geometry_GetArea(self, *args)
 
+
     def GetPointCount(self, *args):
         """GetPointCount(Geometry self) -> int"""
         return _ogr.Geometry_GetPointCount(self, *args)
 
+
     def GetPoints(self, *args, **kwargs):
         """GetPoints(Geometry self, int nCoordDimension=0)"""
         return _ogr.Geometry_GetPoints(self, *args, **kwargs)
 
+
     def GetX(self, *args, **kwargs):
         """GetX(Geometry self, int point=0) -> double"""
         return _ogr.Geometry_GetX(self, *args, **kwargs)
 
+
     def GetY(self, *args, **kwargs):
         """GetY(Geometry self, int point=0) -> double"""
         return _ogr.Geometry_GetY(self, *args, **kwargs)
 
+
     def GetZ(self, *args, **kwargs):
         """GetZ(Geometry self, int point=0) -> double"""
         return _ogr.Geometry_GetZ(self, *args, **kwargs)
 
+
     def GetM(self, *args, **kwargs):
         """GetM(Geometry self, int point=0) -> double"""
         return _ogr.Geometry_GetM(self, *args, **kwargs)
 
+
     def GetPoint(self, *args):
         """GetPoint(Geometry self, int iPoint=0)"""
         return _ogr.Geometry_GetPoint(self, *args)
 
+
     def GetPointZM(self, *args):
         """GetPointZM(Geometry self, int iPoint=0)"""
         return _ogr.Geometry_GetPointZM(self, *args)
 
+
     def GetPoint_2D(self, *args):
         """GetPoint_2D(Geometry self, int iPoint=0)"""
         return _ogr.Geometry_GetPoint_2D(self, *args)
 
+
     def GetGeometryCount(self, *args):
         """GetGeometryCount(Geometry self) -> int"""
         return _ogr.Geometry_GetGeometryCount(self, *args)
 
+
     def SetPoint(self, *args, **kwargs):
         """SetPoint(Geometry self, int point, double x, double y, double z=0)"""
         return _ogr.Geometry_SetPoint(self, *args, **kwargs)
 
+
     def SetPointM(self, *args, **kwargs):
         """SetPointM(Geometry self, int point, double x, double y, double m)"""
         return _ogr.Geometry_SetPointM(self, *args, **kwargs)
 
+
     def SetPointZM(self, *args, **kwargs):
         """SetPointZM(Geometry self, int point, double x, double y, double z, double m)"""
         return _ogr.Geometry_SetPointZM(self, *args, **kwargs)
 
+
     def SetPoint_2D(self, *args, **kwargs):
         """SetPoint_2D(Geometry self, int point, double x, double y)"""
         return _ogr.Geometry_SetPoint_2D(self, *args, **kwargs)
 
+
     def GetGeometryRef(self, *args):
         """GetGeometryRef(Geometry self, int geom) -> Geometry"""
         return _ogr.Geometry_GetGeometryRef(self, *args)
 
+
     def Simplify(self, *args):
         """
         Simplify(Geometry self, double tolerance) -> Geometry
@@ -5855,6 +6466,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Simplify(self, *args)
 
+
     def SimplifyPreserveTopology(self, *args):
         """
         SimplifyPreserveTopology(Geometry self, double tolerance) -> Geometry
@@ -5885,6 +6497,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_SimplifyPreserveTopology(self, *args)
 
+
     def DelaunayTriangulation(self, *args, **kwargs):
         """
         DelaunayTriangulation(Geometry self, double dfTolerance=0.0, int bOnlyEdges=False) -> Geometry
@@ -5920,6 +6533,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_DelaunayTriangulation(self, *args, **kwargs)
 
+
     def Boundary(self, *args):
         """
         Boundary(Geometry self) -> Geometry
@@ -5951,6 +6565,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Boundary(self, *args)
 
+
     def GetBoundary(self, *args):
         """
         GetBoundary(Geometry self) -> Geometry
@@ -5964,6 +6579,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_GetBoundary(self, *args)
 
+
     def ConvexHull(self, *args):
         """
         ConvexHull(Geometry self) -> Geometry
@@ -5993,6 +6609,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_ConvexHull(self, *args)
 
+
     def Buffer(self, *args, **kwargs):
         """
         Buffer(Geometry self, double distance, int quadsecs=30) -> Geometry
@@ -6035,6 +6652,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Buffer(self, *args, **kwargs)
 
+
     def Intersection(self, *args):
         """
         Intersection(Geometry self, Geometry other) -> Geometry
@@ -6068,6 +6686,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Intersection(self, *args)
 
+
     def Union(self, *args):
         """
         Union(Geometry self, Geometry other) -> Geometry
@@ -6098,6 +6717,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Union(self, *args)
 
+
     def UnionCascaded(self, *args):
         """
         UnionCascaded(Geometry self) -> Geometry
@@ -6124,6 +6744,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_UnionCascaded(self, *args)
 
+
     def Difference(self, *args):
         """
         Difference(Geometry self, Geometry other) -> Geometry
@@ -6155,6 +6776,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Difference(self, *args)
 
+
     def SymDifference(self, *args):
         """
         SymDifference(Geometry self, Geometry other) -> Geometry
@@ -6189,6 +6811,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_SymDifference(self, *args)
 
+
     def SymmetricDifference(self, *args):
         """
         SymmetricDifference(Geometry self, Geometry other) -> Geometry
@@ -6202,6 +6825,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_SymmetricDifference(self, *args)
 
+
     def Distance(self, *args):
         """
         Distance(Geometry self, Geometry other) -> double
@@ -6232,6 +6856,12 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Distance(self, *args)
 
+
+    def Distance3D(self, *args):
+        """Distance3D(Geometry self, Geometry other) -> double"""
+        return _ogr.Geometry_Distance3D(self, *args)
+
+
     def Empty(self, *args):
         """
         Empty(Geometry self)
@@ -6254,6 +6884,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Empty(self, *args)
 
+
     def IsEmpty(self, *args):
         """
         IsEmpty(Geometry self) -> bool
@@ -6273,6 +6904,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_IsEmpty(self, *args)
 
+
     def IsValid(self, *args):
         """
         IsValid(Geometry self) -> bool
@@ -6296,6 +6928,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_IsValid(self, *args)
 
+
     def IsSimple(self, *args):
         """
         IsSimple(Geometry self) -> bool
@@ -6325,6 +6958,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_IsSimple(self, *args)
 
+
     def IsRing(self, *args):
         """
         IsRing(Geometry self) -> bool
@@ -6348,6 +6982,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_IsRing(self, *args)
 
+
     def Intersects(self, *args):
         """
         Intersects(Geometry self, Geometry other) -> bool
@@ -6374,6 +7009,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Intersects(self, *args)
 
+
     def Intersect(self, *args):
         """
         Intersect(Geometry self, Geometry other) -> bool
@@ -6383,6 +7019,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Intersect(self, *args)
 
+
     def Equals(self, *args):
         """
         Equals(Geometry self, Geometry other) -> bool
@@ -6406,6 +7043,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Equals(self, *args)
 
+
     def Equal(self, *args):
         """
         Equal(Geometry self, Geometry other) -> bool
@@ -6415,6 +7053,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Equal(self, *args)
 
+
     def Disjoint(self, *args):
         """
         Disjoint(Geometry self, Geometry other) -> bool
@@ -6444,6 +7083,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Disjoint(self, *args)
 
+
     def Touches(self, *args):
         """
         Touches(Geometry self, Geometry other) -> bool
@@ -6473,6 +7113,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Touches(self, *args)
 
+
     def Crosses(self, *args):
         """
         Crosses(Geometry self, Geometry other) -> bool
@@ -6502,6 +7143,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Crosses(self, *args)
 
+
     def Within(self, *args):
         """
         Within(Geometry self, Geometry other) -> bool
@@ -6531,6 +7173,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Within(self, *args)
 
+
     def Contains(self, *args):
         """
         Contains(Geometry self, Geometry other) -> bool
@@ -6560,6 +7203,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Contains(self, *args)
 
+
     def Overlaps(self, *args):
         """
         Overlaps(Geometry self, Geometry other) -> bool
@@ -6590,6 +7234,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Overlaps(self, *args)
 
+
     def TransformTo(self, *args):
         """
         TransformTo(Geometry self, SpatialReference reference) -> OGRErr
@@ -6628,6 +7273,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_TransformTo(self, *args)
 
+
     def Transform(self, *args):
         """
         Transform(Geometry self, CoordinateTransformation trans) -> OGRErr
@@ -6663,6 +7309,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Transform(self, *args)
 
+
     def GetSpatialReference(self, *args):
         """
         GetSpatialReference(Geometry self) -> SpatialReference
@@ -6687,6 +7334,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_GetSpatialReference(self, *args)
 
+
     def AssignSpatialReference(self, *args):
         """
         AssignSpatialReference(Geometry self, SpatialReference reference)
@@ -6718,6 +7366,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_AssignSpatialReference(self, *args)
 
+
     def CloseRings(self, *args):
         """
         CloseRings(Geometry self)
@@ -6738,6 +7387,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_CloseRings(self, *args)
 
+
     def FlattenTo2D(self, *args):
         """
         FlattenTo2D(Geometry self)
@@ -6759,6 +7409,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_FlattenTo2D(self, *args)
 
+
     def Segmentize(self, *args):
         """
         Segmentize(Geometry self, double dfMaxLength)
@@ -6784,6 +7435,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Segmentize(self, *args)
 
+
     def GetEnvelope(self, *args):
         """
         GetEnvelope(Geometry self)
@@ -6806,6 +7458,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_GetEnvelope(self, *args)
 
+
     def GetEnvelope3D(self, *args):
         """
         GetEnvelope3D(Geometry self)
@@ -6830,6 +7483,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_GetEnvelope3D(self, *args)
 
+
     def Centroid(self, *args):
         """
         Centroid(Geometry self) -> Geometry
@@ -6860,6 +7514,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Centroid(self, *args)
 
+
     def PointOnSurface(self, *args):
         """
         PointOnSurface(Geometry self) -> Geometry
@@ -6889,6 +7544,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_PointOnSurface(self, *args)
 
+
     def WkbSize(self, *args):
         """
         WkbSize(Geometry self) -> int
@@ -6914,6 +7570,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_WkbSize(self, *args)
 
+
     def GetCoordinateDimension(self, *args):
         """
         GetCoordinateDimension(Geometry self) -> int
@@ -6939,6 +7596,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_GetCoordinateDimension(self, *args)
 
+
     def CoordinateDimension(self, *args):
         """
         CoordinateDimension(Geometry self) -> int
@@ -6961,6 +7619,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_CoordinateDimension(self, *args)
 
+
     def Is3D(self, *args):
         """
         Is3D(Geometry self) -> int
@@ -6982,6 +7641,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Is3D(self, *args)
 
+
     def IsMeasured(self, *args):
         """
         IsMeasured(Geometry self) -> int
@@ -7004,6 +7664,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_IsMeasured(self, *args)
 
+
     def SetCoordinateDimension(self, *args):
         """
         SetCoordinateDimension(Geometry self, int dimension)
@@ -7031,6 +7692,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_SetCoordinateDimension(self, *args)
 
+
     def Set3D(self, *args):
         """
         Set3D(Geometry self, int b3D)
@@ -7056,6 +7718,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_Set3D(self, *args)
 
+
     def SetMeasured(self, *args):
         """
         SetMeasured(Geometry self, int bMeasured)
@@ -7083,6 +7746,7 @@ class Geometry(_object):
         """
         return _ogr.Geometry_SetMeasured(self, *args)
 
+
     def GetDimension(self, *args):
         """
         GetDimension(Geometry self) -> int
@@ -7109,22 +7773,27 @@ class Geometry(_object):
         """
         return _ogr.Geometry_GetDimension(self, *args)
 
+
     def HasCurveGeometry(self, *args):
         """HasCurveGeometry(Geometry self, int bLookForCircular=False) -> int"""
         return _ogr.Geometry_HasCurveGeometry(self, *args)
 
+
     def GetLinearGeometry(self, *args, **kwargs):
         """GetLinearGeometry(Geometry self, double dfMaxAngleStepSizeDegrees=0.0, char ** options=None) -> Geometry"""
         return _ogr.Geometry_GetLinearGeometry(self, *args, **kwargs)
 
+
     def GetCurveGeometry(self, *args, **kwargs):
         """GetCurveGeometry(Geometry self, char ** options=None) -> Geometry"""
         return _ogr.Geometry_GetCurveGeometry(self, *args, **kwargs)
 
+
     def Value(self, *args):
         """Value(Geometry self, double dfDistance) -> Geometry"""
         return _ogr.Geometry_Value(self, *args)
 
+
     def Destroy(self):
       self.__swig_destroy__(self)
       self.__del__()
@@ -7158,120 +7827,122 @@ Geometry_swigregister(Geometry)
 
 
 def GetDriverCount(*args):
-  """GetDriverCount() -> int"""
-  return _ogr.GetDriverCount(*args)
+    """GetDriverCount() -> int"""
+    return _ogr.GetDriverCount(*args)
 
 def GetOpenDSCount(*args):
-  """GetOpenDSCount() -> int"""
-  return _ogr.GetOpenDSCount(*args)
+    """GetOpenDSCount() -> int"""
+    return _ogr.GetOpenDSCount(*args)
 
 def SetGenerate_DB2_V72_BYTE_ORDER(*args):
-  """SetGenerate_DB2_V72_BYTE_ORDER(int bGenerate_DB2_V72_BYTE_ORDER) -> OGRErr"""
-  return _ogr.SetGenerate_DB2_V72_BYTE_ORDER(*args)
+    """SetGenerate_DB2_V72_BYTE_ORDER(int bGenerate_DB2_V72_BYTE_ORDER) -> OGRErr"""
+    return _ogr.SetGenerate_DB2_V72_BYTE_ORDER(*args)
 
 def RegisterAll(*args):
-  """RegisterAll()"""
-  return _ogr.RegisterAll(*args)
+    """RegisterAll()"""
+    return _ogr.RegisterAll(*args)
 
 def GeometryTypeToName(*args):
-  """GeometryTypeToName(OGRwkbGeometryType eType) -> char const *"""
-  return _ogr.GeometryTypeToName(*args)
+    """GeometryTypeToName(OGRwkbGeometryType eType) -> char const *"""
+    return _ogr.GeometryTypeToName(*args)
 
 def GetFieldTypeName(*args):
-  """GetFieldTypeName(OGRFieldType type) -> char const *"""
-  return _ogr.GetFieldTypeName(*args)
+    """GetFieldTypeName(OGRFieldType type) -> char const *"""
+    return _ogr.GetFieldTypeName(*args)
 
 def GetFieldSubTypeName(*args):
-  """GetFieldSubTypeName(OGRFieldSubType type) -> char const *"""
-  return _ogr.GetFieldSubTypeName(*args)
+    """GetFieldSubTypeName(OGRFieldSubType type) -> char const *"""
+    return _ogr.GetFieldSubTypeName(*args)
 
 def GT_Flatten(*args):
-  """GT_Flatten(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
-  return _ogr.GT_Flatten(*args)
+    """GT_Flatten(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
+    return _ogr.GT_Flatten(*args)
 
 def GT_SetZ(*args):
-  """GT_SetZ(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
-  return _ogr.GT_SetZ(*args)
+    """GT_SetZ(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
+    return _ogr.GT_SetZ(*args)
 
 def GT_SetM(*args):
-  """GT_SetM(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
-  return _ogr.GT_SetM(*args)
+    """GT_SetM(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
+    return _ogr.GT_SetM(*args)
 
 def GT_SetModifier(*args):
-  """GT_SetModifier(OGRwkbGeometryType eType, int bSetZ, int bSetM=False) -> OGRwkbGeometryType"""
-  return _ogr.GT_SetModifier(*args)
+    """GT_SetModifier(OGRwkbGeometryType eType, int bSetZ, int bSetM=False) -> OGRwkbGeometryType"""
+    return _ogr.GT_SetModifier(*args)
 
 def GT_HasZ(*args):
-  """GT_HasZ(OGRwkbGeometryType eType) -> int"""
-  return _ogr.GT_HasZ(*args)
+    """GT_HasZ(OGRwkbGeometryType eType) -> int"""
+    return _ogr.GT_HasZ(*args)
 
 def GT_HasM(*args):
-  """GT_HasM(OGRwkbGeometryType eType) -> int"""
-  return _ogr.GT_HasM(*args)
+    """GT_HasM(OGRwkbGeometryType eType) -> int"""
+    return _ogr.GT_HasM(*args)
 
 def GT_IsSubClassOf(*args):
-  """GT_IsSubClassOf(OGRwkbGeometryType eType, OGRwkbGeometryType eSuperType) -> int"""
-  return _ogr.GT_IsSubClassOf(*args)
+    """GT_IsSubClassOf(OGRwkbGeometryType eType, OGRwkbGeometryType eSuperType) -> int"""
+    return _ogr.GT_IsSubClassOf(*args)
 
 def GT_IsCurve(*args):
-  """GT_IsCurve(OGRwkbGeometryType arg1) -> int"""
-  return _ogr.GT_IsCurve(*args)
+    """GT_IsCurve(OGRwkbGeometryType arg1) -> int"""
+    return _ogr.GT_IsCurve(*args)
 
 def GT_IsSurface(*args):
-  """GT_IsSurface(OGRwkbGeometryType arg1) -> int"""
-  return _ogr.GT_IsSurface(*args)
+    """GT_IsSurface(OGRwkbGeometryType arg1) -> int"""
+    return _ogr.GT_IsSurface(*args)
 
 def GT_IsNonLinear(*args):
-  """GT_IsNonLinear(OGRwkbGeometryType arg1) -> int"""
-  return _ogr.GT_IsNonLinear(*args)
+    """GT_IsNonLinear(OGRwkbGeometryType arg1) -> int"""
+    return _ogr.GT_IsNonLinear(*args)
 
 def GT_GetCollection(*args):
-  """GT_GetCollection(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
-  return _ogr.GT_GetCollection(*args)
+    """GT_GetCollection(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
+    return _ogr.GT_GetCollection(*args)
 
 def GT_GetCurve(*args):
-  """GT_GetCurve(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
-  return _ogr.GT_GetCurve(*args)
+    """GT_GetCurve(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
+    return _ogr.GT_GetCurve(*args)
 
 def GT_GetLinear(*args):
-  """GT_GetLinear(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
-  return _ogr.GT_GetLinear(*args)
+    """GT_GetLinear(OGRwkbGeometryType eType) -> OGRwkbGeometryType"""
+    return _ogr.GT_GetLinear(*args)
 
 def SetNonLinearGeometriesEnabledFlag(*args):
-  """SetNonLinearGeometriesEnabledFlag(int bFlag)"""
-  return _ogr.SetNonLinearGeometriesEnabledFlag(*args)
+    """SetNonLinearGeometriesEnabledFlag(int bFlag)"""
+    return _ogr.SetNonLinearGeometriesEnabledFlag(*args)
 
 def GetNonLinearGeometriesEnabledFlag(*args):
-  """GetNonLinearGeometriesEnabledFlag() -> int"""
-  return _ogr.GetNonLinearGeometriesEnabledFlag(*args)
+    """GetNonLinearGeometriesEnabledFlag() -> int"""
+    return _ogr.GetNonLinearGeometriesEnabledFlag(*args)
 
 def GetOpenDS(*args):
-  """GetOpenDS(int ds_number) -> DataSource"""
-  return _ogr.GetOpenDS(*args)
+    """GetOpenDS(int ds_number) -> DataSource"""
+    return _ogr.GetOpenDS(*args)
 
 def Open(*args, **kwargs):
-  """Open(char const * utf8_path, int update=0) -> DataSource"""
-  return _ogr.Open(*args, **kwargs)
+    """Open(char const * utf8_path, int update=0) -> DataSource"""
+    return _ogr.Open(*args, **kwargs)
 
 def OpenShared(*args, **kwargs):
-  """OpenShared(char const * utf8_path, int update=0) -> DataSource"""
-  return _ogr.OpenShared(*args, **kwargs)
+    """OpenShared(char const * utf8_path, int update=0) -> DataSource"""
+    return _ogr.OpenShared(*args, **kwargs)
 
 def GetDriverByName(*args):
-  """GetDriverByName(char const * name) -> Driver"""
-  return _ogr.GetDriverByName(*args)
+    """GetDriverByName(char const * name) -> Driver"""
+    return _ogr.GetDriverByName(*args)
 
 def GetDriver(*args):
-  """GetDriver(int driver_number) -> Driver"""
-  return _ogr.GetDriver(*args)
+    """GetDriver(int driver_number) -> Driver"""
+    return _ogr.GetDriver(*args)
 
 def GeneralCmdLineProcessor(*args):
-  """GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"""
-  return _ogr.GeneralCmdLineProcessor(*args)
+    """GeneralCmdLineProcessor(char ** papszArgv, int nOptions=0) -> char **"""
+    return _ogr.GeneralCmdLineProcessor(*args)
 
 def TermProgress_nocb(*args, **kwargs):
-  """TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"""
-  return _ogr.TermProgress_nocb(*args, **kwargs)
+    """TermProgress_nocb(double dfProgress, char const * pszMessage=None, void * pData=None) -> int"""
+    return _ogr.TermProgress_nocb(*args, **kwargs)
+
+_ogr.TermProgress_swigconstant(_ogr)
 TermProgress = _ogr.TermProgress
 # This file is compatible with both classic and new-style classes.
 
diff --git a/swig/python/osgeo/osr.py b/swig/python/osgeo/osr.py
index b041567..dba628b 100644
--- a/swig/python/osgeo/osr.py
+++ b/swig/python/osgeo/osr.py
@@ -1,5 +1,5 @@
 # This file was automatically generated by SWIG (http://www.swig.org).
-# Version 2.0.12
+# Version 3.0.8
 #
 # Do not make changes to this file unless you know what you are doing--modify
 # the SWIG interface file instead.
@@ -9,7 +9,7 @@
 
 
 from sys import version_info
-if version_info >= (2,6,0):
+if version_info >= (2, 6, 0):
     def swig_import_helper():
         from os.path import dirname
         import imp
@@ -33,729 +33,1206 @@ del version_info
 try:
     _swig_property = property
 except NameError:
-    pass # Python < 2.2 doesn't have 'property'.
-def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
-    if (name == "thisown"): return self.this.own(value)
+    pass  # Python < 2.2 doesn't have 'property'.
+
+
+def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
+    if (name == "thisown"):
+        return self.this.own(value)
     if (name == "this"):
         if type(value).__name__ == 'SwigPyObject':
             self.__dict__[name] = value
             return
-    method = class_type.__swig_setmethods__.get(name,None)
-    if method: return method(self,value)
+    method = class_type.__swig_setmethods__.get(name, None)
+    if method:
+        return method(self, value)
     if (not static):
-        self.__dict__[name] = value
+        if _newclass:
+            object.__setattr__(self, name, value)
+        else:
+            self.__dict__[name] = value
     else:
         raise AttributeError("You cannot add attributes to %s" % self)
 
-def _swig_setattr(self,class_type,name,value):
-    return _swig_setattr_nondynamic(self,class_type,name,value,0)
 
-def _swig_getattr(self,class_type,name):
-    if (name == "thisown"): return self.this.own()
-    method = class_type.__swig_getmethods__.get(name,None)
-    if method: return method(self)
-    raise AttributeError(name)
+def _swig_setattr(self, class_type, name, value):
+    return _swig_setattr_nondynamic(self, class_type, name, value, 0)
+
+
+def _swig_getattr_nondynamic(self, class_type, name, static=1):
+    if (name == "thisown"):
+        return self.this.own()
+    method = class_type.__swig_getmethods__.get(name, None)
+    if method:
+        return method(self)
+    if (not static):
+        return object.__getattr__(self, name)
+    else:
+        raise AttributeError(name)
+
+def _swig_getattr(self, class_type, name):
+    return _swig_getattr_nondynamic(self, class_type, name, 0)
+
 
 def _swig_repr(self):
-    try: strthis = "proxy of " + self.this.__repr__()
-    except: strthis = ""
+    try:
+        strthis = "proxy of " + self.this.__repr__()
+    except Exception:
+        strthis = ""
     return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
 
 try:
     _object = object
     _newclass = 1
 except AttributeError:
-    class _object : pass
+    class _object:
+        pass
     _newclass = 0
 
 
+
+_osr.SRS_WKT_WGS84_swigconstant(_osr)
 SRS_WKT_WGS84 = _osr.SRS_WKT_WGS84
+
+_osr.SRS_PT_ALBERS_CONIC_EQUAL_AREA_swigconstant(_osr)
 SRS_PT_ALBERS_CONIC_EQUAL_AREA = _osr.SRS_PT_ALBERS_CONIC_EQUAL_AREA
+
+_osr.SRS_PT_AZIMUTHAL_EQUIDISTANT_swigconstant(_osr)
 SRS_PT_AZIMUTHAL_EQUIDISTANT = _osr.SRS_PT_AZIMUTHAL_EQUIDISTANT
+
+_osr.SRS_PT_CASSINI_SOLDNER_swigconstant(_osr)
 SRS_PT_CASSINI_SOLDNER = _osr.SRS_PT_CASSINI_SOLDNER
+
+_osr.SRS_PT_CYLINDRICAL_EQUAL_AREA_swigconstant(_osr)
 SRS_PT_CYLINDRICAL_EQUAL_AREA = _osr.SRS_PT_CYLINDRICAL_EQUAL_AREA
+
+_osr.SRS_PT_BONNE_swigconstant(_osr)
 SRS_PT_BONNE = _osr.SRS_PT_BONNE
+
+_osr.SRS_PT_ECKERT_I_swigconstant(_osr)
 SRS_PT_ECKERT_I = _osr.SRS_PT_ECKERT_I
+
+_osr.SRS_PT_ECKERT_II_swigconstant(_osr)
 SRS_PT_ECKERT_II = _osr.SRS_PT_ECKERT_II
+
+_osr.SRS_PT_ECKERT_III_swigconstant(_osr)
 SRS_PT_ECKERT_III = _osr.SRS_PT_ECKERT_III
+
+_osr.SRS_PT_ECKERT_IV_swigconstant(_osr)
 SRS_PT_ECKERT_IV = _osr.SRS_PT_ECKERT_IV
+
+_osr.SRS_PT_ECKERT_V_swigconstant(_osr)
 SRS_PT_ECKERT_V = _osr.SRS_PT_ECKERT_V
+
+_osr.SRS_PT_ECKERT_VI_swigconstant(_osr)
 SRS_PT_ECKERT_VI = _osr.SRS_PT_ECKERT_VI
+
+_osr.SRS_PT_EQUIDISTANT_CONIC_swigconstant(_osr)
 SRS_PT_EQUIDISTANT_CONIC = _osr.SRS_PT_EQUIDISTANT_CONIC
+
+_osr.SRS_PT_EQUIRECTANGULAR_swigconstant(_osr)
 SRS_PT_EQUIRECTANGULAR = _osr.SRS_PT_EQUIRECTANGULAR
+
+_osr.SRS_PT_GALL_STEREOGRAPHIC_swigconstant(_osr)
 SRS_PT_GALL_STEREOGRAPHIC = _osr.SRS_PT_GALL_STEREOGRAPHIC
+
+_osr.SRS_PT_GAUSSSCHREIBERTMERCATOR_swigconstant(_osr)
 SRS_PT_GAUSSSCHREIBERTMERCATOR = _osr.SRS_PT_GAUSSSCHREIBERTMERCATOR
+
+_osr.SRS_PT_GEOSTATIONARY_SATELLITE_swigconstant(_osr)
 SRS_PT_GEOSTATIONARY_SATELLITE = _osr.SRS_PT_GEOSTATIONARY_SATELLITE
+
+_osr.SRS_PT_GOODE_HOMOLOSINE_swigconstant(_osr)
 SRS_PT_GOODE_HOMOLOSINE = _osr.SRS_PT_GOODE_HOMOLOSINE
+
+_osr.SRS_PT_IGH_swigconstant(_osr)
 SRS_PT_IGH = _osr.SRS_PT_IGH
+
+_osr.SRS_PT_GNOMONIC_swigconstant(_osr)
 SRS_PT_GNOMONIC = _osr.SRS_PT_GNOMONIC
+
+_osr.SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER_swigconstant(_osr)
 SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER = _osr.SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER
+
+_osr.SRS_PT_HOTINE_OBLIQUE_MERCATOR_swigconstant(_osr)
 SRS_PT_HOTINE_OBLIQUE_MERCATOR = _osr.SRS_PT_HOTINE_OBLIQUE_MERCATOR
+
+_osr.SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN_swigconstant(_osr)
 SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN = _osr.SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN
+
+_osr.SRS_PT_LABORDE_OBLIQUE_MERCATOR_swigconstant(_osr)
 SRS_PT_LABORDE_OBLIQUE_MERCATOR = _osr.SRS_PT_LABORDE_OBLIQUE_MERCATOR
+
+_osr.SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP_swigconstant(_osr)
 SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP = _osr.SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP
+
+_osr.SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_swigconstant(_osr)
 SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP = _osr.SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP
+
+_osr.SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM_swigconstant(_osr)
 SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM = _osr.SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM
+
+_osr.SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA_swigconstant(_osr)
 SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA = _osr.SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA
+
+_osr.SRS_PT_MERCATOR_1SP_swigconstant(_osr)
 SRS_PT_MERCATOR_1SP = _osr.SRS_PT_MERCATOR_1SP
+
+_osr.SRS_PT_MERCATOR_2SP_swigconstant(_osr)
 SRS_PT_MERCATOR_2SP = _osr.SRS_PT_MERCATOR_2SP
+
+_osr.SRS_PT_MERCATOR_AUXILIARY_SPHERE_swigconstant(_osr)
 SRS_PT_MERCATOR_AUXILIARY_SPHERE = _osr.SRS_PT_MERCATOR_AUXILIARY_SPHERE
+
+_osr.SRS_PT_MILLER_CYLINDRICAL_swigconstant(_osr)
 SRS_PT_MILLER_CYLINDRICAL = _osr.SRS_PT_MILLER_CYLINDRICAL
+
+_osr.SRS_PT_MOLLWEIDE_swigconstant(_osr)
 SRS_PT_MOLLWEIDE = _osr.SRS_PT_MOLLWEIDE
+
+_osr.SRS_PT_NEW_ZEALAND_MAP_GRID_swigconstant(_osr)
 SRS_PT_NEW_ZEALAND_MAP_GRID = _osr.SRS_PT_NEW_ZEALAND_MAP_GRID
+
+_osr.SRS_PT_OBLIQUE_STEREOGRAPHIC_swigconstant(_osr)
 SRS_PT_OBLIQUE_STEREOGRAPHIC = _osr.SRS_PT_OBLIQUE_STEREOGRAPHIC
+
+_osr.SRS_PT_ORTHOGRAPHIC_swigconstant(_osr)
 SRS_PT_ORTHOGRAPHIC = _osr.SRS_PT_ORTHOGRAPHIC
+
+_osr.SRS_PT_POLAR_STEREOGRAPHIC_swigconstant(_osr)
 SRS_PT_POLAR_STEREOGRAPHIC = _osr.SRS_PT_POLAR_STEREOGRAPHIC
+
+_osr.SRS_PT_POLYCONIC_swigconstant(_osr)
 SRS_PT_POLYCONIC = _osr.SRS_PT_POLYCONIC
+
+_osr.SRS_PT_ROBINSON_swigconstant(_osr)
 SRS_PT_ROBINSON = _osr.SRS_PT_ROBINSON
+
+_osr.SRS_PT_SINUSOIDAL_swigconstant(_osr)
 SRS_PT_SINUSOIDAL = _osr.SRS_PT_SINUSOIDAL
+
+_osr.SRS_PT_STEREOGRAPHIC_swigconstant(_osr)
 SRS_PT_STEREOGRAPHIC = _osr.SRS_PT_STEREOGRAPHIC
+
+_osr.SRS_PT_SWISS_OBLIQUE_CYLINDRICAL_swigconstant(_osr)
 SRS_PT_SWISS_OBLIQUE_CYLINDRICAL = _osr.SRS_PT_SWISS_OBLIQUE_CYLINDRICAL
+
+_osr.SRS_PT_TRANSVERSE_MERCATOR_swigconstant(_osr)
 SRS_PT_TRANSVERSE_MERCATOR = _osr.SRS_PT_TRANSVERSE_MERCATOR
+
+_osr.SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED_swigconstant(_osr)
 SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED = _osr.SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED
+
+_osr.SRS_PT_TRANSVERSE_MERCATOR_MI_21_swigconstant(_osr)
 SRS_PT_TRANSVERSE_MERCATOR_MI_21 = _osr.SRS_PT_TRANSVERSE_MERCATOR_MI_21
+
+_osr.SRS_PT_TRANSVERSE_MERCATOR_MI_22_swigconstant(_osr)
 SRS_PT_TRANSVERSE_MERCATOR_MI_22 = _osr.SRS_PT_TRANSVERSE_MERCATOR_MI_22
+
+_osr.SRS_PT_TRANSVERSE_MERCATOR_MI_23_swigconstant(_osr)
 SRS_PT_TRANSVERSE_MERCATOR_MI_23 = _osr.SRS_PT_TRANSVERSE_MERCATOR_MI_23
+
+_osr.SRS_PT_TRANSVERSE_MERCATOR_MI_24_swigconstant(_osr)
 SRS_PT_TRANSVERSE_MERCATOR_MI_24 = _osr.SRS_PT_TRANSVERSE_MERCATOR_MI_24
+
+_osr.SRS_PT_TRANSVERSE_MERCATOR_MI_25_swigconstant(_osr)
 SRS_PT_TRANSVERSE_MERCATOR_MI_25 = _osr.SRS_PT_TRANSVERSE_MERCATOR_MI_25
+
+_osr.SRS_PT_TUNISIA_MINING_GRID_swigconstant(_osr)
 SRS_PT_TUNISIA_MINING_GRID = _osr.SRS_PT_TUNISIA_MINING_GRID
+
+_osr.SRS_PT_TWO_POINT_EQUIDISTANT_swigconstant(_osr)
 SRS_PT_TWO_POINT_EQUIDISTANT = _osr.SRS_PT_TWO_POINT_EQUIDISTANT
+
+_osr.SRS_PT_VANDERGRINTEN_swigconstant(_osr)
 SRS_PT_VANDERGRINTEN = _osr.SRS_PT_VANDERGRINTEN
+
+_osr.SRS_PT_KROVAK_swigconstant(_osr)
 SRS_PT_KROVAK = _osr.SRS_PT_KROVAK
+
+_osr.SRS_PT_IMW_POLYCONIC_swigconstant(_osr)
 SRS_PT_IMW_POLYCONIC = _osr.SRS_PT_IMW_POLYCONIC
+
+_osr.SRS_PT_WAGNER_I_swigconstant(_osr)
 SRS_PT_WAGNER_I = _osr.SRS_PT_WAGNER_I
+
+_osr.SRS_PT_WAGNER_II_swigconstant(_osr)
 SRS_PT_WAGNER_II = _osr.SRS_PT_WAGNER_II
+
+_osr.SRS_PT_WAGNER_III_swigconstant(_osr)
 SRS_PT_WAGNER_III = _osr.SRS_PT_WAGNER_III
+
+_osr.SRS_PT_WAGNER_IV_swigconstant(_osr)
 SRS_PT_WAGNER_IV = _osr.SRS_PT_WAGNER_IV
+
+_osr.SRS_PT_WAGNER_V_swigconstant(_osr)
 SRS_PT_WAGNER_V = _osr.SRS_PT_WAGNER_V
+
+_osr.SRS_PT_WAGNER_VI_swigconstant(_osr)
 SRS_PT_WAGNER_VI = _osr.SRS_PT_WAGNER_VI
+
+_osr.SRS_PT_WAGNER_VII_swigconstant(_osr)
 SRS_PT_WAGNER_VII = _osr.SRS_PT_WAGNER_VII
+
+_osr.SRS_PT_QSC_swigconstant(_osr)
 SRS_PT_QSC = _osr.SRS_PT_QSC
+
+_osr.SRS_PT_AITOFF_swigconstant(_osr)
 SRS_PT_AITOFF = _osr.SRS_PT_AITOFF
+
+_osr.SRS_PT_WINKEL_I_swigconstant(_osr)
 SRS_PT_WINKEL_I = _osr.SRS_PT_WINKEL_I
+
+_osr.SRS_PT_WINKEL_II_swigconstant(_osr)
 SRS_PT_WINKEL_II = _osr.SRS_PT_WINKEL_II
+
+_osr.SRS_PT_WINKEL_TRIPEL_swigconstant(_osr)
 SRS_PT_WINKEL_TRIPEL = _osr.SRS_PT_WINKEL_TRIPEL
+
+_osr.SRS_PT_CRASTER_PARABOLIC_swigconstant(_osr)
 SRS_PT_CRASTER_PARABOLIC = _osr.SRS_PT_CRASTER_PARABOLIC
+
+_osr.SRS_PT_LOXIMUTHAL_swigconstant(_osr)
 SRS_PT_LOXIMUTHAL = _osr.SRS_PT_LOXIMUTHAL
+
+_osr.SRS_PT_QUARTIC_AUTHALIC_swigconstant(_osr)
 SRS_PT_QUARTIC_AUTHALIC = _osr.SRS_PT_QUARTIC_AUTHALIC
+
+_osr.SRS_PT_SCH_swigconstant(_osr)
 SRS_PT_SCH = _osr.SRS_PT_SCH
+
+_osr.SRS_PP_CENTRAL_MERIDIAN_swigconstant(_osr)
 SRS_PP_CENTRAL_MERIDIAN = _osr.SRS_PP_CENTRAL_MERIDIAN
+
+_osr.SRS_PP_SCALE_FACTOR_swigconstant(_osr)
 SRS_PP_SCALE_FACTOR = _osr.SRS_PP_SCALE_FACTOR
+
+_osr.SRS_PP_STANDARD_PARALLEL_1_swigconstant(_osr)
 SRS_PP_STANDARD_PARALLEL_1 = _osr.SRS_PP_STANDARD_PARALLEL_1
+
+_osr.SRS_PP_STANDARD_PARALLEL_2_swigconstant(_osr)
 SRS_PP_STANDARD_PARALLEL_2 = _osr.SRS_PP_STANDARD_PARALLEL_2
+
+_osr.SRS_PP_PSEUDO_STD_PARALLEL_1_swigconstant(_osr)
 SRS_PP_PSEUDO_STD_PARALLEL_1 = _osr.SRS_PP_PSEUDO_STD_PARALLEL_1
+
+_osr.SRS_PP_LONGITUDE_OF_CENTER_swigconstant(_osr)
 SRS_PP_LONGITUDE_OF_CENTER = _osr.SRS_PP_LONGITUDE_OF_CENTER
+
+_osr.SRS_PP_LATITUDE_OF_CENTER_swigconstant(_osr)
 SRS_PP_LATITUDE_OF_CENTER = _osr.SRS_PP_LATITUDE_OF_CENTER
+
+_osr.SRS_PP_LONGITUDE_OF_ORIGIN_swigconstant(_osr)
 SRS_PP_LONGITUDE_OF_ORIGIN = _osr.SRS_PP_LONGITUDE_OF_ORIGIN
+
+_osr.SRS_PP_LATITUDE_OF_ORIGIN_swigconstant(_osr)
 SRS_PP_LATITUDE_OF_ORIGIN = _osr.SRS_PP_LATITUDE_OF_ORIGIN
+
+_osr.SRS_PP_FALSE_EASTING_swigconstant(_osr)
 SRS_PP_FALSE_EASTING = _osr.SRS_PP_FALSE_EASTING
+
+_osr.SRS_PP_FALSE_NORTHING_swigconstant(_osr)
 SRS_PP_FALSE_NORTHING = _osr.SRS_PP_FALSE_NORTHING
+
+_osr.SRS_PP_AZIMUTH_swigconstant(_osr)
 SRS_PP_AZIMUTH = _osr.SRS_PP_AZIMUTH
+
+_osr.SRS_PP_LONGITUDE_OF_POINT_1_swigconstant(_osr)
 SRS_PP_LONGITUDE_OF_POINT_1 = _osr.SRS_PP_LONGITUDE_OF_POINT_1
+
+_osr.SRS_PP_LATITUDE_OF_POINT_1_swigconstant(_osr)
 SRS_PP_LATITUDE_OF_POINT_1 = _osr.SRS_PP_LATITUDE_OF_POINT_1
+
+_osr.SRS_PP_LONGITUDE_OF_POINT_2_swigconstant(_osr)
 SRS_PP_LONGITUDE_OF_POINT_2 = _osr.SRS_PP_LONGITUDE_OF_POINT_2
+
+_osr.SRS_PP_LATITUDE_OF_POINT_2_swigconstant(_osr)
 SRS_PP_LATITUDE_OF_POINT_2 = _osr.SRS_PP_LATITUDE_OF_POINT_2
+
+_osr.SRS_PP_LONGITUDE_OF_POINT_3_swigconstant(_osr)
 SRS_PP_LONGITUDE_OF_POINT_3 = _osr.SRS_PP_LONGITUDE_OF_POINT_3
+
+_osr.SRS_PP_LATITUDE_OF_POINT_3_swigconstant(_osr)
 SRS_PP_LATITUDE_OF_POINT_3 = _osr.SRS_PP_LATITUDE_OF_POINT_3
+
+_osr.SRS_PP_RECTIFIED_GRID_ANGLE_swigconstant(_osr)
 SRS_PP_RECTIFIED_GRID_ANGLE = _osr.SRS_PP_RECTIFIED_GRID_ANGLE
+
+_osr.SRS_PP_LANDSAT_NUMBER_swigconstant(_osr)
 SRS_PP_LANDSAT_NUMBER = _osr.SRS_PP_LANDSAT_NUMBER
+
+_osr.SRS_PP_PATH_NUMBER_swigconstant(_osr)
 SRS_PP_PATH_NUMBER = _osr.SRS_PP_PATH_NUMBER
+
+_osr.SRS_PP_PERSPECTIVE_POINT_HEIGHT_swigconstant(_osr)
 SRS_PP_PERSPECTIVE_POINT_HEIGHT = _osr.SRS_PP_PERSPECTIVE_POINT_HEIGHT
+
+_osr.SRS_PP_SATELLITE_HEIGHT_swigconstant(_osr)
 SRS_PP_SATELLITE_HEIGHT = _osr.SRS_PP_SATELLITE_HEIGHT
+
+_osr.SRS_PP_FIPSZONE_swigconstant(_osr)
 SRS_PP_FIPSZONE = _osr.SRS_PP_FIPSZONE
+
+_osr.SRS_PP_ZONE_swigconstant(_osr)
 SRS_PP_ZONE = _osr.SRS_PP_ZONE
+
+_osr.SRS_PP_LATITUDE_OF_1ST_POINT_swigconstant(_osr)
 SRS_PP_LATITUDE_OF_1ST_POINT = _osr.SRS_PP_LATITUDE_OF_1ST_POINT
+
+_osr.SRS_PP_LONGITUDE_OF_1ST_POINT_swigconstant(_osr)
 SRS_PP_LONGITUDE_OF_1ST_POINT = _osr.SRS_PP_LONGITUDE_OF_1ST_POINT
+
+_osr.SRS_PP_LATITUDE_OF_2ND_POINT_swigconstant(_osr)
 SRS_PP_LATITUDE_OF_2ND_POINT = _osr.SRS_PP_LATITUDE_OF_2ND_POINT
+
+_osr.SRS_PP_LONGITUDE_OF_2ND_POINT_swigconstant(_osr)
 SRS_PP_LONGITUDE_OF_2ND_POINT = _osr.SRS_PP_LONGITUDE_OF_2ND_POINT
+
+_osr.SRS_PP_PEG_POINT_LATITUDE_swigconstant(_osr)
 SRS_PP_PEG_POINT_LATITUDE = _osr.SRS_PP_PEG_POINT_LATITUDE
+
+_osr.SRS_PP_PEG_POINT_LONGITUDE_swigconstant(_osr)
 SRS_PP_PEG_POINT_LONGITUDE = _osr.SRS_PP_PEG_POINT_LONGITUDE
+
+_osr.SRS_PP_PEG_POINT_HEADING_swigconstant(_osr)
 SRS_PP_PEG_POINT_HEADING = _osr.SRS_PP_PEG_POINT_HEADING
+
+_osr.SRS_PP_PEG_POINT_HEIGHT_swigconstant(_osr)
 SRS_PP_PEG_POINT_HEIGHT = _osr.SRS_PP_PEG_POINT_HEIGHT
+
+_osr.SRS_UL_METER_swigconstant(_osr)
 SRS_UL_METER = _osr.SRS_UL_METER
+
+_osr.SRS_UL_FOOT_swigconstant(_osr)
 SRS_UL_FOOT = _osr.SRS_UL_FOOT
+
+_osr.SRS_UL_FOOT_CONV_swigconstant(_osr)
 SRS_UL_FOOT_CONV = _osr.SRS_UL_FOOT_CONV
+
+_osr.SRS_UL_US_FOOT_swigconstant(_osr)
 SRS_UL_US_FOOT = _osr.SRS_UL_US_FOOT
+
+_osr.SRS_UL_US_FOOT_CONV_swigconstant(_osr)
 SRS_UL_US_FOOT_CONV = _osr.SRS_UL_US_FOOT_CONV
+
+_osr.SRS_UL_NAUTICAL_MILE_swigconstant(_osr)
 SRS_UL_NAUTICAL_MILE = _osr.SRS_UL_NAUTICAL_MILE
+
+_osr.SRS_UL_NAUTICAL_MILE_CONV_swigconstant(_osr)
 SRS_UL_NAUTICAL_MILE_CONV = _osr.SRS_UL_NAUTICAL_MILE_CONV
+
+_osr.SRS_UL_LINK_swigconstant(_osr)
 SRS_UL_LINK = _osr.SRS_UL_LINK
+
+_osr.SRS_UL_LINK_CONV_swigconstant(_osr)
 SRS_UL_LINK_CONV = _osr.SRS_UL_LINK_CONV
+
+_osr.SRS_UL_CHAIN_swigconstant(_osr)
 SRS_UL_CHAIN = _osr.SRS_UL_CHAIN
+
+_osr.SRS_UL_CHAIN_CONV_swigconstant(_osr)
 SRS_UL_CHAIN_CONV = _osr.SRS_UL_CHAIN_CONV
+
+_osr.SRS_UL_ROD_swigconstant(_osr)
 SRS_UL_ROD = _osr.SRS_UL_ROD
+
+_osr.SRS_UL_ROD_CONV_swigconstant(_osr)
 SRS_UL_ROD_CONV = _osr.SRS_UL_ROD_CONV
+
+_osr.SRS_UL_LINK_Clarke_swigconstant(_osr)
 SRS_UL_LINK_Clarke = _osr.SRS_UL_LINK_Clarke
+
+_osr.SRS_UL_LINK_Clarke_CONV_swigconstant(_osr)
 SRS_UL_LINK_Clarke_CONV = _osr.SRS_UL_LINK_Clarke_CONV
+
+_osr.SRS_UL_KILOMETER_swigconstant(_osr)
 SRS_UL_KILOMETER = _osr.SRS_UL_KILOMETER
+
+_osr.SRS_UL_KILOMETER_CONV_swigconstant(_osr)
 SRS_UL_KILOMETER_CONV = _osr.SRS_UL_KILOMETER_CONV
+
+_osr.SRS_UL_DECIMETER_swigconstant(_osr)
 SRS_UL_DECIMETER = _osr.SRS_UL_DECIMETER
+
+_osr.SRS_UL_DECIMETER_CONV_swigconstant(_osr)
 SRS_UL_DECIMETER_CONV = _osr.SRS_UL_DECIMETER_CONV
+
+_osr.SRS_UL_CENTIMETER_swigconstant(_osr)
 SRS_UL_CENTIMETER = _osr.SRS_UL_CENTIMETER
+
+_osr.SRS_UL_CENTIMETER_CONV_swigconstant(_osr)
 SRS_UL_CENTIMETER_CONV = _osr.SRS_UL_CENTIMETER_CONV
+
+_osr.SRS_UL_MILLIMETER_swigconstant(_osr)
 SRS_UL_MILLIMETER = _osr.SRS_UL_MILLIMETER
+
+_osr.SRS_UL_MILLIMETER_CONV_swigconstant(_osr)
 SRS_UL_MILLIMETER_CONV = _osr.SRS_UL_MILLIMETER_CONV
+
+_osr.SRS_UL_INTL_NAUT_MILE_swigconstant(_osr)
 SRS_UL_INTL_NAUT_MILE = _osr.SRS_UL_INTL_NAUT_MILE
+
+_osr.SRS_UL_INTL_NAUT_MILE_CONV_swigconstant(_osr)
 SRS_UL_INTL_NAUT_MILE_CONV = _osr.SRS_UL_INTL_NAUT_MILE_CONV
+
+_osr.SRS_UL_INTL_INCH_swigconstant(_osr)
 SRS_UL_INTL_INCH = _osr.SRS_UL_INTL_INCH
+
+_osr.SRS_UL_INTL_INCH_CONV_swigconstant(_osr)
 SRS_UL_INTL_INCH_CONV = _osr.SRS_UL_INTL_INCH_CONV
+
+_osr.SRS_UL_INTL_FOOT_swigconstant(_osr)
 SRS_UL_INTL_FOOT = _osr.SRS_UL_INTL_FOOT
+
+_osr.SRS_UL_INTL_FOOT_CONV_swigconstant(_osr)
 SRS_UL_INTL_FOOT_CONV = _osr.SRS_UL_INTL_FOOT_CONV
+
+_osr.SRS_UL_INTL_YARD_swigconstant(_osr)
 SRS_UL_INTL_YARD = _osr.SRS_UL_INTL_YARD
+
+_osr.SRS_UL_INTL_YARD_CONV_swigconstant(_osr)
 SRS_UL_INTL_YARD_CONV = _osr.SRS_UL_INTL_YARD_CONV
+
+_osr.SRS_UL_INTL_STAT_MILE_swigconstant(_osr)
 SRS_UL_INTL_STAT_MILE = _osr.SRS_UL_INTL_STAT_MILE
+
+_osr.SRS_UL_INTL_STAT_MILE_CONV_swigconstant(_osr)
 SRS_UL_INTL_STAT_MILE_CONV = _osr.SRS_UL_INTL_STAT_MILE_CONV
+
+_osr.SRS_UL_INTL_FATHOM_swigconstant(_osr)
 SRS_UL_INTL_FATHOM = _osr.SRS_UL_INTL_FATHOM
+
+_osr.SRS_UL_INTL_FATHOM_CONV_swigconstant(_osr)
 SRS_UL_INTL_FATHOM_CONV = _osr.SRS_UL_INTL_FATHOM_CONV
+
+_osr.SRS_UL_INTL_CHAIN_swigconstant(_osr)
 SRS_UL_INTL_CHAIN = _osr.SRS_UL_INTL_CHAIN
+
+_osr.SRS_UL_INTL_CHAIN_CONV_swigconstant(_osr)
 SRS_UL_INTL_CHAIN_CONV = _osr.SRS_UL_INTL_CHAIN_CONV
+
+_osr.SRS_UL_INTL_LINK_swigconstant(_osr)
 SRS_UL_INTL_LINK = _osr.SRS_UL_INTL_LINK
+
+_osr.SRS_UL_INTL_LINK_CONV_swigconstant(_osr)
 SRS_UL_INTL_LINK_CONV = _osr.SRS_UL_INTL_LINK_CONV
+
+_osr.SRS_UL_US_INCH_swigconstant(_osr)
 SRS_UL_US_INCH = _osr.SRS_UL_US_INCH
+
+_osr.SRS_UL_US_INCH_CONV_swigconstant(_osr)
 SRS_UL_US_INCH_CONV = _osr.SRS_UL_US_INCH_CONV
+
+_osr.SRS_UL_US_YARD_swigconstant(_osr)
 SRS_UL_US_YARD = _osr.SRS_UL_US_YARD
+
+_osr.SRS_UL_US_YARD_CONV_swigconstant(_osr)
 SRS_UL_US_YARD_CONV = _osr.SRS_UL_US_YARD_CONV
+
+_osr.SRS_UL_US_CHAIN_swigconstant(_osr)
 SRS_UL_US_CHAIN = _osr.SRS_UL_US_CHAIN
+
+_osr.SRS_UL_US_CHAIN_CONV_swigconstant(_osr)
 SRS_UL_US_CHAIN_CONV = _osr.SRS_UL_US_CHAIN_CONV
+
+_osr.SRS_UL_US_STAT_MILE_swigconstant(_osr)
 SRS_UL_US_STAT_MILE = _osr.SRS_UL_US_STAT_MILE
+
+_osr.SRS_UL_US_STAT_MILE_CONV_swigconstant(_osr)
 SRS_UL_US_STAT_MILE_CONV = _osr.SRS_UL_US_STAT_MILE_CONV
+
+_osr.SRS_UL_INDIAN_YARD_swigconstant(_osr)
 SRS_UL_INDIAN_YARD = _osr.SRS_UL_INDIAN_YARD
+
+_osr.SRS_UL_INDIAN_YARD_CONV_swigconstant(_osr)
 SRS_UL_INDIAN_YARD_CONV = _osr.SRS_UL_INDIAN_YARD_CONV
+
+_osr.SRS_UL_INDIAN_FOOT_swigconstant(_osr)
 SRS_UL_INDIAN_FOOT = _osr.SRS_UL_INDIAN_FOOT
+
+_osr.SRS_UL_INDIAN_FOOT_CONV_swigconstant(_osr)
 SRS_UL_INDIAN_FOOT_CONV = _osr.SRS_UL_INDIAN_FOOT_CONV
+
+_osr.SRS_UL_INDIAN_CHAIN_swigconstant(_osr)
 SRS_UL_INDIAN_CHAIN = _osr.SRS_UL_INDIAN_CHAIN
+
+_osr.SRS_UL_INDIAN_CHAIN_CONV_swigconstant(_osr)
 SRS_UL_INDIAN_CHAIN_CONV = _osr.SRS_UL_INDIAN_CHAIN_CONV
+
+_osr.SRS_UA_DEGREE_swigconstant(_osr)
 SRS_UA_DEGREE = _osr.SRS_UA_DEGREE
+
+_osr.SRS_UA_DEGREE_CONV_swigconstant(_osr)
 SRS_UA_DEGREE_CONV = _osr.SRS_UA_DEGREE_CONV
+
+_osr.SRS_UA_RADIAN_swigconstant(_osr)
 SRS_UA_RADIAN = _osr.SRS_UA_RADIAN
+
+_osr.SRS_PM_GREENWICH_swigconstant(_osr)
 SRS_PM_GREENWICH = _osr.SRS_PM_GREENWICH
+
+_osr.SRS_DN_NAD27_swigconstant(_osr)
 SRS_DN_NAD27 = _osr.SRS_DN_NAD27
+
+_osr.SRS_DN_NAD83_swigconstant(_osr)
 SRS_DN_NAD83 = _osr.SRS_DN_NAD83
+
+_osr.SRS_DN_WGS72_swigconstant(_osr)
 SRS_DN_WGS72 = _osr.SRS_DN_WGS72
+
+_osr.SRS_DN_WGS84_swigconstant(_osr)
 SRS_DN_WGS84 = _osr.SRS_DN_WGS84
+
+_osr.SRS_WGS84_SEMIMAJOR_swigconstant(_osr)
 SRS_WGS84_SEMIMAJOR = _osr.SRS_WGS84_SEMIMAJOR
+
+_osr.SRS_WGS84_INVFLATTENING_swigconstant(_osr)
 SRS_WGS84_INVFLATTENING = _osr.SRS_WGS84_INVFLATTENING
+
+_osr.OAO_Other_swigconstant(_osr)
 OAO_Other = _osr.OAO_Other
+
+_osr.OAO_North_swigconstant(_osr)
 OAO_North = _osr.OAO_North
+
+_osr.OAO_South_swigconstant(_osr)
 OAO_South = _osr.OAO_South
+
+_osr.OAO_East_swigconstant(_osr)
 OAO_East = _osr.OAO_East
+
+_osr.OAO_West_swigconstant(_osr)
 OAO_West = _osr.OAO_West
+
+_osr.OAO_Up_swigconstant(_osr)
 OAO_Up = _osr.OAO_Up
+
+_osr.OAO_Down_swigconstant(_osr)
 OAO_Down = _osr.OAO_Down
 
 def GetUseExceptions(*args):
-  """GetUseExceptions() -> int"""
-  return _osr.GetUseExceptions(*args)
+    """GetUseExceptions() -> int"""
+    return _osr.GetUseExceptions(*args)
 
 def UseExceptions(*args):
-  """UseExceptions()"""
-  return _osr.UseExceptions(*args)
+    """UseExceptions()"""
+    return _osr.UseExceptions(*args)
 
 def DontUseExceptions(*args):
-  """DontUseExceptions()"""
-  return _osr.DontUseExceptions(*args)
+    """DontUseExceptions()"""
+    return _osr.DontUseExceptions(*args)
 
 def GetWellKnownGeogCSAsWKT(*args):
-  """GetWellKnownGeogCSAsWKT(char const * name) -> OGRErr"""
-  return _osr.GetWellKnownGeogCSAsWKT(*args)
+    """GetWellKnownGeogCSAsWKT(char const * name) -> OGRErr"""
+    return _osr.GetWellKnownGeogCSAsWKT(*args)
 
 def GetUserInputAsWKT(*args):
-  """GetUserInputAsWKT(char const * name) -> OGRErr"""
-  return _osr.GetUserInputAsWKT(*args)
+    """GetUserInputAsWKT(char const * name) -> OGRErr"""
+    return _osr.GetUserInputAsWKT(*args)
 class SpatialReference(_object):
-    """Proxy of C++ OSRSpatialReferenceShadow class"""
+    """Proxy of C++ OSRSpatialReferenceShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, SpatialReference, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, SpatialReference, name)
     __repr__ = _swig_repr
-    def __init__(self, *args, **kwargs): 
-        """__init__(OSRSpatialReferenceShadow self, char const * wkt="") -> SpatialReference"""
+
+    def __init__(self, *args, **kwargs):
+        """__init__(OSRSpatialReferenceShadow self, char const * wkt) -> SpatialReference"""
         this = _osr.new_SpatialReference(*args, **kwargs)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _osr.delete_SpatialReference
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def __str__(self, *args):
         """__str__(SpatialReference self) -> retStringAndCPLFree *"""
         return _osr.SpatialReference___str__(self, *args)
 
+
     def IsSame(self, *args):
         """IsSame(SpatialReference self, SpatialReference rhs) -> int"""
         return _osr.SpatialReference_IsSame(self, *args)
 
+
     def IsSameGeogCS(self, *args):
         """IsSameGeogCS(SpatialReference self, SpatialReference rhs) -> int"""
         return _osr.SpatialReference_IsSameGeogCS(self, *args)
 
+
     def IsSameVertCS(self, *args):
         """IsSameVertCS(SpatialReference self, SpatialReference rhs) -> int"""
         return _osr.SpatialReference_IsSameVertCS(self, *args)
 
+
     def IsGeographic(self, *args):
         """IsGeographic(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsGeographic(self, *args)
 
+
     def IsProjected(self, *args):
         """IsProjected(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsProjected(self, *args)
 
+
     def IsCompound(self, *args):
         """IsCompound(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsCompound(self, *args)
 
+
     def IsGeocentric(self, *args):
         """IsGeocentric(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsGeocentric(self, *args)
 
+
     def IsLocal(self, *args):
         """IsLocal(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsLocal(self, *args)
 
+
     def IsVertical(self, *args):
         """IsVertical(SpatialReference self) -> int"""
         return _osr.SpatialReference_IsVertical(self, *args)
 
+
     def EPSGTreatsAsLatLong(self, *args):
         """EPSGTreatsAsLatLong(SpatialReference self) -> int"""
         return _osr.SpatialReference_EPSGTreatsAsLatLong(self, *args)
 
+
     def EPSGTreatsAsNorthingEasting(self, *args):
         """EPSGTreatsAsNorthingEasting(SpatialReference self) -> int"""
         return _osr.SpatialReference_EPSGTreatsAsNorthingEasting(self, *args)
 
+
     def SetAuthority(self, *args):
         """SetAuthority(SpatialReference self, char const * pszTargetKey, char const * pszAuthority, int nCode) -> OGRErr"""
         return _osr.SpatialReference_SetAuthority(self, *args)
 
+
     def GetAttrValue(self, *args):
         """GetAttrValue(SpatialReference self, char const * name, int child=0) -> char const *"""
         return _osr.SpatialReference_GetAttrValue(self, *args)
 
+
     def SetAttrValue(self, *args):
         """SetAttrValue(SpatialReference self, char const * name, char const * value) -> OGRErr"""
         return _osr.SpatialReference_SetAttrValue(self, *args)
 
+
     def SetAngularUnits(self, *args):
         """SetAngularUnits(SpatialReference self, char const * name, double to_radians) -> OGRErr"""
         return _osr.SpatialReference_SetAngularUnits(self, *args)
 
+
     def GetAngularUnits(self, *args):
         """GetAngularUnits(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetAngularUnits(self, *args)
 
+
     def GetAngularUnitsName(self, *args):
         """GetAngularUnitsName(SpatialReference self) -> char const *"""
         return _osr.SpatialReference_GetAngularUnitsName(self, *args)
 
+
     def SetTargetLinearUnits(self, *args):
         """SetTargetLinearUnits(SpatialReference self, char const * target, char const * name, double to_meters) -> OGRErr"""
         return _osr.SpatialReference_SetTargetLinearUnits(self, *args)
 
+
     def SetLinearUnits(self, *args):
         """SetLinearUnits(SpatialReference self, char const * name, double to_meters) -> OGRErr"""
         return _osr.SpatialReference_SetLinearUnits(self, *args)
 
+
     def SetLinearUnitsAndUpdateParameters(self, *args):
         """SetLinearUnitsAndUpdateParameters(SpatialReference self, char const * name, double to_meters) -> OGRErr"""
         return _osr.SpatialReference_SetLinearUnitsAndUpdateParameters(self, *args)
 
+
+    def GetTargetLinearUnits(self, *args):
+        """GetTargetLinearUnits(SpatialReference self, char const * target_key) -> double"""
+        return _osr.SpatialReference_GetTargetLinearUnits(self, *args)
+
+
     def GetLinearUnits(self, *args):
         """GetLinearUnits(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetLinearUnits(self, *args)
 
+
     def GetLinearUnitsName(self, *args):
         """GetLinearUnitsName(SpatialReference self) -> char const *"""
         return _osr.SpatialReference_GetLinearUnitsName(self, *args)
 
+
     def GetAuthorityCode(self, *args):
         """GetAuthorityCode(SpatialReference self, char const * target_key) -> char const *"""
         return _osr.SpatialReference_GetAuthorityCode(self, *args)
 
+
     def GetAuthorityName(self, *args):
         """GetAuthorityName(SpatialReference self, char const * target_key) -> char const *"""
         return _osr.SpatialReference_GetAuthorityName(self, *args)
 
+
     def GetAxisName(self, *args):
         """GetAxisName(SpatialReference self, char const * target_key, int iAxis) -> char const *"""
         return _osr.SpatialReference_GetAxisName(self, *args)
 
+
     def GetAxisOrientation(self, *args):
         """GetAxisOrientation(SpatialReference self, char const * target_key, int iAxis) -> OGRAxisOrientation"""
         return _osr.SpatialReference_GetAxisOrientation(self, *args)
 
+
     def SetUTM(self, *args):
         """SetUTM(SpatialReference self, int zone, int north=1) -> OGRErr"""
         return _osr.SpatialReference_SetUTM(self, *args)
 
+
     def GetUTMZone(self, *args):
         """GetUTMZone(SpatialReference self) -> int"""
         return _osr.SpatialReference_GetUTMZone(self, *args)
 
+
     def SetStatePlane(self, *args):
-        """SetStatePlane(SpatialReference self, int zone, int is_nad83=1, char const * unitsname="", double units=0.0) -> OGRErr"""
+        """SetStatePlane(SpatialReference self, int zone, int is_nad83=1, char const * unitsname, double units=0.0) -> OGRErr"""
         return _osr.SpatialReference_SetStatePlane(self, *args)
 
+
     def AutoIdentifyEPSG(self, *args):
         """AutoIdentifyEPSG(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_AutoIdentifyEPSG(self, *args)
 
+
     def SetProjection(self, *args):
         """SetProjection(SpatialReference self, char const * arg) -> OGRErr"""
         return _osr.SpatialReference_SetProjection(self, *args)
 
+
     def SetProjParm(self, *args):
         """SetProjParm(SpatialReference self, char const * name, double val) -> OGRErr"""
         return _osr.SpatialReference_SetProjParm(self, *args)
 
+
     def GetProjParm(self, *args):
         """GetProjParm(SpatialReference self, char const * name, double default_val=0.0) -> double"""
         return _osr.SpatialReference_GetProjParm(self, *args)
 
+
     def SetNormProjParm(self, *args):
         """SetNormProjParm(SpatialReference self, char const * name, double val) -> OGRErr"""
         return _osr.SpatialReference_SetNormProjParm(self, *args)
 
+
     def GetNormProjParm(self, *args):
         """GetNormProjParm(SpatialReference self, char const * name, double default_val=0.0) -> double"""
         return _osr.SpatialReference_GetNormProjParm(self, *args)
 
+
     def GetSemiMajor(self, *args):
         """GetSemiMajor(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetSemiMajor(self, *args)
 
+
     def GetSemiMinor(self, *args):
         """GetSemiMinor(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetSemiMinor(self, *args)
 
+
     def GetInvFlattening(self, *args):
         """GetInvFlattening(SpatialReference self) -> double"""
         return _osr.SpatialReference_GetInvFlattening(self, *args)
 
+
     def SetACEA(self, *args, **kwargs):
         """SetACEA(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetACEA(self, *args, **kwargs)
 
+
     def SetAE(self, *args, **kwargs):
         """SetAE(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetAE(self, *args, **kwargs)
 
+
     def SetBonne(self, *args, **kwargs):
         """SetBonne(SpatialReference self, double stdp, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetBonne(self, *args, **kwargs)
 
+
     def SetCEA(self, *args, **kwargs):
         """SetCEA(SpatialReference self, double stdp1, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetCEA(self, *args, **kwargs)
 
+
     def SetCS(self, *args, **kwargs):
         """SetCS(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetCS(self, *args, **kwargs)
 
+
     def SetEC(self, *args, **kwargs):
         """SetEC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEC(self, *args, **kwargs)
 
+
     def SetEckertIV(self, *args, **kwargs):
         """SetEckertIV(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEckertIV(self, *args, **kwargs)
 
+
     def SetEckertVI(self, *args, **kwargs):
         """SetEckertVI(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEckertVI(self, *args, **kwargs)
 
+
     def SetEquirectangular(self, *args, **kwargs):
         """SetEquirectangular(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEquirectangular(self, *args, **kwargs)
 
+
     def SetEquirectangular2(self, *args, **kwargs):
         """SetEquirectangular2(SpatialReference self, double clat, double clong, double pseudostdparallellat, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetEquirectangular2(self, *args, **kwargs)
 
+
     def SetGaussSchreiberTMercator(self, *args, **kwargs):
         """SetGaussSchreiberTMercator(SpatialReference self, double clat, double clong, double sc, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGaussSchreiberTMercator(self, *args, **kwargs)
 
+
     def SetGS(self, *args, **kwargs):
         """SetGS(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGS(self, *args, **kwargs)
 
+
     def SetGH(self, *args, **kwargs):
         """SetGH(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGH(self, *args, **kwargs)
 
+
     def SetIGH(self, *args):
         """SetIGH(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_SetIGH(self, *args)
 
+
     def SetGEOS(self, *args, **kwargs):
         """SetGEOS(SpatialReference self, double cm, double satelliteheight, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGEOS(self, *args, **kwargs)
 
+
     def SetGnomonic(self, *args, **kwargs):
         """SetGnomonic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetGnomonic(self, *args, **kwargs)
 
+
     def SetHOM(self, *args, **kwargs):
-        """
-        SetHOM(SpatialReference self, double clat, double clong, double azimuth, double recttoskew, double scale, double fe, 
-            double fn) -> OGRErr
-        """
+        """SetHOM(SpatialReference self, double clat, double clong, double azimuth, double recttoskew, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetHOM(self, *args, **kwargs)
 
+
     def SetHOM2PNO(self, *args, **kwargs):
-        """
-        SetHOM2PNO(SpatialReference self, double clat, double dfLat1, double dfLong1, double dfLat2, double dfLong2, double scale, 
-            double fe, double fn) -> OGRErr
-        """
+        """SetHOM2PNO(SpatialReference self, double clat, double dfLat1, double dfLong1, double dfLat2, double dfLong2, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetHOM2PNO(self, *args, **kwargs)
 
+
     def SetKrovak(self, *args, **kwargs):
-        """
-        SetKrovak(SpatialReference self, double clat, double clong, double azimuth, double pseudostdparallellat, double scale, 
-            double fe, double fn) -> OGRErr
-        """
+        """SetKrovak(SpatialReference self, double clat, double clong, double azimuth, double pseudostdparallellat, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetKrovak(self, *args, **kwargs)
 
+
     def SetLAEA(self, *args, **kwargs):
         """SetLAEA(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetLAEA(self, *args, **kwargs)
 
+
     def SetLCC(self, *args, **kwargs):
         """SetLCC(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetLCC(self, *args, **kwargs)
 
+
     def SetLCC1SP(self, *args, **kwargs):
         """SetLCC1SP(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetLCC1SP(self, *args, **kwargs)
 
+
     def SetLCCB(self, *args, **kwargs):
         """SetLCCB(SpatialReference self, double stdp1, double stdp2, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetLCCB(self, *args, **kwargs)
 
+
     def SetMC(self, *args, **kwargs):
         """SetMC(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetMC(self, *args, **kwargs)
 
+
     def SetMercator(self, *args, **kwargs):
         """SetMercator(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetMercator(self, *args, **kwargs)
 
+
     def SetMollweide(self, *args, **kwargs):
         """SetMollweide(SpatialReference self, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetMollweide(self, *args, **kwargs)
 
+
     def SetNZMG(self, *args, **kwargs):
         """SetNZMG(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetNZMG(self, *args, **kwargs)
 
+
     def SetOS(self, *args, **kwargs):
         """SetOS(SpatialReference self, double dfOriginLat, double dfCMeridian, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetOS(self, *args, **kwargs)
 
+
     def SetOrthographic(self, *args, **kwargs):
         """SetOrthographic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetOrthographic(self, *args, **kwargs)
 
+
     def SetPolyconic(self, *args, **kwargs):
         """SetPolyconic(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetPolyconic(self, *args, **kwargs)
 
+
     def SetPS(self, *args, **kwargs):
         """SetPS(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetPS(self, *args, **kwargs)
 
+
     def SetRobinson(self, *args, **kwargs):
         """SetRobinson(SpatialReference self, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetRobinson(self, *args, **kwargs)
 
+
     def SetSinusoidal(self, *args, **kwargs):
         """SetSinusoidal(SpatialReference self, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetSinusoidal(self, *args, **kwargs)
 
+
     def SetStereographic(self, *args, **kwargs):
         """SetStereographic(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetStereographic(self, *args, **kwargs)
 
+
     def SetSOC(self, *args, **kwargs):
         """SetSOC(SpatialReference self, double latitudeoforigin, double cm, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetSOC(self, *args, **kwargs)
 
+
     def SetTM(self, *args, **kwargs):
         """SetTM(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetTM(self, *args, **kwargs)
 
+
     def SetTMVariant(self, *args, **kwargs):
-        """
-        SetTMVariant(SpatialReference self, char const * pszVariantName, double clat, double clong, double scale, double fe, 
-            double fn) -> OGRErr
-        """
+        """SetTMVariant(SpatialReference self, char const * pszVariantName, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetTMVariant(self, *args, **kwargs)
 
+
     def SetTMG(self, *args, **kwargs):
         """SetTMG(SpatialReference self, double clat, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetTMG(self, *args, **kwargs)
 
+
     def SetTMSO(self, *args, **kwargs):
         """SetTMSO(SpatialReference self, double clat, double clong, double scale, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetTMSO(self, *args, **kwargs)
 
+
     def SetVDG(self, *args, **kwargs):
         """SetVDG(SpatialReference self, double clong, double fe, double fn) -> OGRErr"""
         return _osr.SpatialReference_SetVDG(self, *args, **kwargs)
 
+
     def SetWellKnownGeogCS(self, *args):
         """SetWellKnownGeogCS(SpatialReference self, char const * name) -> OGRErr"""
         return _osr.SpatialReference_SetWellKnownGeogCS(self, *args)
 
+
     def SetFromUserInput(self, *args):
         """SetFromUserInput(SpatialReference self, char const * name) -> OGRErr"""
         return _osr.SpatialReference_SetFromUserInput(self, *args)
 
+
     def CopyGeogCSFrom(self, *args):
         """CopyGeogCSFrom(SpatialReference self, SpatialReference rhs) -> OGRErr"""
         return _osr.SpatialReference_CopyGeogCSFrom(self, *args)
 
+
     def SetTOWGS84(self, *args):
         """SetTOWGS84(SpatialReference self, double p1, double p2, double p3, double p4=0.0, double p5=0.0, double p6=0.0, double p7=0.0) -> OGRErr"""
         return _osr.SpatialReference_SetTOWGS84(self, *args)
 
+
     def GetTOWGS84(self, *args):
         """GetTOWGS84(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_GetTOWGS84(self, *args)
 
+
     def SetLocalCS(self, *args):
         """SetLocalCS(SpatialReference self, char const * pszName) -> OGRErr"""
         return _osr.SpatialReference_SetLocalCS(self, *args)
 
+
     def SetGeogCS(self, *args):
-        """
-        SetGeogCS(SpatialReference self, char const * pszGeogName, char const * pszDatumName, char const * pszEllipsoidName, 
-            double dfSemiMajor, double dfInvFlattening, char const * pszPMName="Greenwich", 
-            double dfPMOffset=0.0, char const * pszUnits="degree", double dfConvertToRadians=0.0174532925199433) -> OGRErr
-        """
+        """SetGeogCS(SpatialReference self, char const * pszGeogName, char const * pszDatumName, char const * pszEllipsoidName, double dfSemiMajor, double dfInvFlattening, char const * pszPMName, double dfPMOffset=0.0, char const * pszUnits, double dfConvertToRadians=0.0174532925199433) -> OGRErr"""
         return _osr.SpatialReference_SetGeogCS(self, *args)
 
+
     def SetProjCS(self, *args):
-        """SetProjCS(SpatialReference self, char const * name="unnamed") -> OGRErr"""
+        """SetProjCS(SpatialReference self, char const * name) -> OGRErr"""
         return _osr.SpatialReference_SetProjCS(self, *args)
 
+
     def SetGeocCS(self, *args):
-        """SetGeocCS(SpatialReference self, char const * name="unnamed") -> OGRErr"""
+        """SetGeocCS(SpatialReference self, char const * name) -> OGRErr"""
         return _osr.SpatialReference_SetGeocCS(self, *args)
 
+
     def SetVertCS(self, *args):
-        """SetVertCS(SpatialReference self, char const * VertCSName="unnamed", char const * VertDatumName="unnamed", int VertDatumType=0) -> OGRErr"""
+        """SetVertCS(SpatialReference self, char const * VertCSName, char const * VertDatumName, int VertDatumType=0) -> OGRErr"""
         return _osr.SpatialReference_SetVertCS(self, *args)
 
+
     def SetCompoundCS(self, *args):
         """SetCompoundCS(SpatialReference self, char const * name, SpatialReference horizcs, SpatialReference vertcs) -> OGRErr"""
         return _osr.SpatialReference_SetCompoundCS(self, *args)
 
+
     def ImportFromWkt(self, *args):
         """ImportFromWkt(SpatialReference self, char ** ppszInput) -> OGRErr"""
         return _osr.SpatialReference_ImportFromWkt(self, *args)
 
+
     def ImportFromProj4(self, *args):
         """ImportFromProj4(SpatialReference self, char * ppszInput) -> OGRErr"""
         return _osr.SpatialReference_ImportFromProj4(self, *args)
 
+
     def ImportFromUrl(self, *args):
         """ImportFromUrl(SpatialReference self, char * url) -> OGRErr"""
         return _osr.SpatialReference_ImportFromUrl(self, *args)
 
+
     def ImportFromESRI(self, *args):
         """ImportFromESRI(SpatialReference self, char ** ppszInput) -> OGRErr"""
         return _osr.SpatialReference_ImportFromESRI(self, *args)
 
+
     def ImportFromEPSG(self, *args):
         """ImportFromEPSG(SpatialReference self, int arg) -> OGRErr"""
         return _osr.SpatialReference_ImportFromEPSG(self, *args)
 
+
     def ImportFromEPSGA(self, *args):
         """ImportFromEPSGA(SpatialReference self, int arg) -> OGRErr"""
         return _osr.SpatialReference_ImportFromEPSGA(self, *args)
 
+
     def ImportFromPCI(self, *args):
-        """ImportFromPCI(SpatialReference self, char const * proj, char const * units="METRE", double [17] argin=0) -> OGRErr"""
+        """ImportFromPCI(SpatialReference self, char const * proj, char const * units, double [17] argin=0) -> OGRErr"""
         return _osr.SpatialReference_ImportFromPCI(self, *args)
 
+
     def ImportFromUSGS(self, *args):
         """ImportFromUSGS(SpatialReference self, long proj_code, long zone=0, double [15] argin=0, long datum_code=0) -> OGRErr"""
         return _osr.SpatialReference_ImportFromUSGS(self, *args)
 
+
     def ImportFromXML(self, *args):
         """ImportFromXML(SpatialReference self, char const * xmlString) -> OGRErr"""
         return _osr.SpatialReference_ImportFromXML(self, *args)
 
+
     def ImportFromERM(self, *args):
         """ImportFromERM(SpatialReference self, char const * proj, char const * datum, char const * units) -> OGRErr"""
         return _osr.SpatialReference_ImportFromERM(self, *args)
 
+
     def ImportFromMICoordSys(self, *args):
         """ImportFromMICoordSys(SpatialReference self, char const * pszCoordSys) -> OGRErr"""
         return _osr.SpatialReference_ImportFromMICoordSys(self, *args)
 
+
     def ImportFromOzi(self, *args):
         """ImportFromOzi(SpatialReference self, char const *const * papszLines) -> OGRErr"""
         return _osr.SpatialReference_ImportFromOzi(self, *args)
 
+
     def ExportToWkt(self, *args):
         """ExportToWkt(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToWkt(self, *args)
 
+
     def ExportToPrettyWkt(self, *args):
         """ExportToPrettyWkt(SpatialReference self, int simplify=0) -> OGRErr"""
         return _osr.SpatialReference_ExportToPrettyWkt(self, *args)
 
+
     def ExportToProj4(self, *args):
         """ExportToProj4(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToProj4(self, *args)
 
+
     def ExportToPCI(self, *args):
         """ExportToPCI(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToPCI(self, *args)
 
+
     def ExportToUSGS(self, *args):
         """ExportToUSGS(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToUSGS(self, *args)
 
+
     def ExportToXML(self, *args):
-        """ExportToXML(SpatialReference self, char const * dialect="") -> OGRErr"""
+        """ExportToXML(SpatialReference self, char const * dialect) -> OGRErr"""
         return _osr.SpatialReference_ExportToXML(self, *args)
 
+
     def ExportToMICoordSys(self, *args):
         """ExportToMICoordSys(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_ExportToMICoordSys(self, *args)
 
+
     def CloneGeogCS(self, *args):
         """CloneGeogCS(SpatialReference self) -> SpatialReference"""
         return _osr.SpatialReference_CloneGeogCS(self, *args)
 
+
     def Clone(self, *args):
         """Clone(SpatialReference self) -> SpatialReference"""
         return _osr.SpatialReference_Clone(self, *args)
 
+
     def Validate(self, *args):
         """Validate(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_Validate(self, *args)
 
+
     def StripCTParms(self, *args):
         """StripCTParms(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_StripCTParms(self, *args)
 
+
     def FixupOrdering(self, *args):
         """FixupOrdering(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_FixupOrdering(self, *args)
 
+
     def Fixup(self, *args):
         """Fixup(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_Fixup(self, *args)
 
+
     def MorphToESRI(self, *args):
         """MorphToESRI(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_MorphToESRI(self, *args)
 
+
     def MorphFromESRI(self, *args):
         """MorphFromESRI(SpatialReference self) -> OGRErr"""
         return _osr.SpatialReference_MorphFromESRI(self, *args)
@@ -765,19 +1242,24 @@ SpatialReference_swigregister(SpatialReference)
 GetProjectionMethods = _osr.GetProjectionMethods
 
 class CoordinateTransformation(_object):
-    """Proxy of C++ OSRCoordinateTransformationShadow class"""
+    """Proxy of C++ OSRCoordinateTransformationShadow class."""
+
     __swig_setmethods__ = {}
     __setattr__ = lambda self, name, value: _swig_setattr(self, CoordinateTransformation, name, value)
     __swig_getmethods__ = {}
     __getattr__ = lambda self, name: _swig_getattr(self, CoordinateTransformation, name)
     __repr__ = _swig_repr
-    def __init__(self, *args): 
+
+    def __init__(self, *args):
         """__init__(OSRCoordinateTransformationShadow self, SpatialReference src, SpatialReference dst) -> CoordinateTransformation"""
         this = _osr.new_CoordinateTransformation(*args)
-        try: self.this.append(this)
-        except: self.this = this
+        try:
+            self.this.append(this)
+        except Exception:
+            self.this = this
     __swig_destroy__ = _osr.delete_CoordinateTransformation
-    __del__ = lambda self : None;
+    __del__ = lambda self: None
+
     def TransformPoint(self, *args):
         """
         TransformPoint(CoordinateTransformation self, double [3] inout)
@@ -785,6 +1267,7 @@ class CoordinateTransformation(_object):
         """
         return _osr.CoordinateTransformation_TransformPoint(self, *args)
 
+
     def TransformPoints(self, *args):
         """TransformPoints(CoordinateTransformation self, int nCount)"""
         return _osr.CoordinateTransformation_TransformPoints(self, *args)
@@ -794,8 +1277,8 @@ CoordinateTransformation_swigregister(CoordinateTransformation)
 
 
 def CreateCoordinateTransformation(*args):
-  """CreateCoordinateTransformation(SpatialReference src, SpatialReference dst) -> CoordinateTransformation"""
-  return _osr.CreateCoordinateTransformation(*args)
+    """CreateCoordinateTransformation(SpatialReference src, SpatialReference dst) -> CoordinateTransformation"""
+    return _osr.CreateCoordinateTransformation(*args)
 # This file is compatible with both classic and new-style classes.
 
 
diff --git a/swig/python/python3.2.patch b/swig/python/python3.2.patch
deleted file mode 100644
index 0a62b6f..0000000
--- a/swig/python/python3.2.patch
+++ /dev/null
@@ -1,88 +0,0 @@
---- extensions/gdal_wrap.cpp.before	2011-02-21 21:35:04.495185339 +0100
-+++ extensions/gdal_wrap.cpp	2011-02-21 21:36:08.275188019 +0100
-@@ -1129,6 +1129,10 @@
- 
- /* Runtime API */
- 
-+#if PY_VERSION_HEX >= 0x03020000
-+#define SWIG_PYTHON_USE_CAPSULE
-+#endif
-+
- #define SWIG_GetModule(clientdata)                      SWIG_Python_GetModule()
- #define SWIG_SetModule(clientdata, pointer)             SWIG_Python_SetModule(pointer)
- #define SWIG_NewClientData(obj)                         SwigPyClientData_New(obj)
-@@ -2448,8 +2452,12 @@
- #ifdef SWIG_LINK_RUNTIME
-     type_pointer = SWIG_ReturnGlobalTypeList((void *)0);
- #else
-+#ifdef SWIG_PYTHON_USE_CAPSULE
-+    type_pointer = PyCapsule_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME, 0);
-+#else
-     type_pointer = PyCObject_Import((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
- 				    (char*)"type_pointer" SWIG_TYPE_TABLE_NAME);
-+#endif
-     if (PyErr_Occurred()) {
-       PyErr_Clear();
-       type_pointer = (void *)0;
-@@ -2492,11 +2500,26 @@
- #endif
- 
- SWIGRUNTIME void
-+#ifdef SWIG_PYTHON_USE_CAPSULE
-+SWIG_Python_DestroyModule(PyObject *capsule)
-+{
-+  swig_module_info *swig_module;
-+  swig_type_info **types;
-+  size_t i;
-+  swig_module = (swig_module_info *)PyCapsule_GetPointer(capsule, (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION);
-+  if (swig_module == NULL)
-+  {
-+    PyErr_Clear();
-+    return;
-+  }
-+  types = swig_module->types;
-+#else
- SWIG_Python_DestroyModule(void *vptr)
- {
-   swig_module_info *swig_module = (swig_module_info *) vptr;
-   swig_type_info **types = swig_module->types;
-   size_t i;
-+#endif
-   for (i =0; i < swig_module->size; ++i) {
-     swig_type_info *ty = types[i];
-     if (ty->owndata) {
-@@ -2518,7 +2541,13 @@
-   PyObject *module = Py_InitModule((char*)"swig_runtime_data" SWIG_RUNTIME_VERSION,
- 				   swig_empty_runtime_method_table);
- #endif
-+#ifdef SWIG_PYTHON_USE_CAPSULE
-+  PyObject *pointer = PyCapsule_New((void *) swig_module,
-+                                    (char*)"swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer" SWIG_TYPE_TABLE_NAME,
-+                                    SWIG_Python_DestroyModule);
-+#else
-   PyObject *pointer = PyCObject_FromVoidPtr((void *) swig_module, SWIG_Python_DestroyModule);
-+#endif
-   if (pointer && module) {
-     PyModule_AddObject(module, (char*)"type_pointer" SWIG_TYPE_TABLE_NAME, pointer);
-   } else {
-@@ -2541,12 +2570,20 @@
-   PyObject *obj = PyDict_GetItem(cache, key);
-   swig_type_info *descriptor;
-   if (obj) {
-+#ifdef SWIG_PYTHON_USE_CAPSULE
-+    descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, (char*)"swig_type_info");
-+#else
-     descriptor = (swig_type_info *) PyCObject_AsVoidPtr(obj);
-+#endif
-   } else {
-     swig_module_info *swig_module = SWIG_Python_GetModule();
-     descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type);
-     if (descriptor) {
-+#ifdef SWIG_PYTHON_USE_CAPSULE
-+      obj = PyCapsule_New(descriptor, (char*)"swig_type_info", NULL);
-+#else
-       obj = PyCObject_FromVoidPtr(descriptor, NULL);
-+#endif
-       PyDict_SetItem(cache, key, obj);
-       Py_DECREF(obj);
-     }
diff --git a/swig/python/samples/README b/swig/python/samples/README
index 164efe1..71172f0 100644
--- a/swig/python/samples/README
+++ b/swig/python/samples/README
@@ -16,7 +16,7 @@ fft.py			Script to perform forward and inverse two-dimensional
 gdal2grd.py		Script to write out ASCII GRD rasters (used in Golden
 			Software Surfer) from any source supported by GDAL.
 
-gdal_vrtmerge.py	Similar to gdal_merge.py, but produces a VRT file. 
+gdal_vrtmerge.py	Similar to gdal_merge.py, but produces a VRT file.
 
 gdalcopyproj.py		Duplicate the geotransform, projection and/or GCPs from
 			one raster dataset to another, which can be useful after
@@ -37,7 +37,7 @@ get_soundg.py		Script to copy the SOUNDG layer from an S-57 file to
 
 histrep.py		Module to extract data from many rasters into one output.
 
-load2odbc.py		Load ODBC table to an ODBC datastore.  Uses direct SQL 
+load2odbc.py		Load ODBC table to an ODBC datastore.  Uses direct SQL
 			since the ODBC driver is read-only for OGR.
 
 rel.py			Script to produce a shaded relief image from the
@@ -45,7 +45,7 @@ rel.py			Script to produce a shaded relief image from the
 
 tigerpoly.py		Script demonstrating how to assemble polygons from
 			arcs in TIGER/Line datasource, writing results to
-			a newly created shapefile. 
+			a newly created shapefile.
 
 tolatlong.py		Script to read coordinate system and geotransformation
 			matrix from input file and report latitude/longitude
@@ -57,16 +57,16 @@ val_repl.py		Script to replace specified values from the input
 			and want replace it with other value. Input file
 			remains unchanged, results stored in other file.
 
-vec_tr.py		Example of applying some algorithm to all the 
+vec_tr.py		Example of applying some algorithm to all the
 			geometries in the file, such as a fixed offset.
 
-vec_tr_spat.py		Example of using Intersect() to filter based on 
+vec_tr_spat.py		Example of using Intersect() to filter based on
 			only those features that truly intersect a given
 			rectangle.  Easily extended to general polygon!
 
 classify.py             Demonstrates using numpy for simple range based
                         classification of an image.  This is only an example
-                        that has stuff hardcoded.  
+                        that has stuff hardcoded.
 
 gdal_lut.py             Read a LUT from a text file, and apply it to an image.
                         Sort of a '1 band' version of pct2rgb.py.
diff --git a/swig/python/samples/ogr2vrt.py b/swig/python/samples/ogr2vrt.py
index a23356c..3f72246 100755
--- a/swig/python/samples/ogr2vrt.py
+++ b/swig/python/samples/ogr2vrt.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: ogr2vrt.py 33791 2016-03-26 12:51:23Z goatbar $
+# $Id: ogr2vrt.py 36883 2016-12-15 13:31:12Z rouault $
 #
 # Project:  OGR Python samples
 # Purpose:  Create OGR VRT from source datasource
@@ -54,7 +54,10 @@ def GeomType2Name( type ):
             ogr.wkbMultiCurve : ('wkbMultiCurve', 'Z'),
             ogr.wkbMultiSurface : ('wkbMultiSurface', 'Z'),
             ogr.wkbCurve : ('wkbCurve', 'Z'),
-            ogr.wkbSurface : ('wkbSurface', 'Z') }
+            ogr.wkbSurface : ('wkbSurface', 'Z'),
+            ogr.wkbPolyhedralSurface : ('wkbPolyhedralSurface', 'Z'),
+            ogr.wkbTIN : ('wkbTIN', 'Z'),
+            ogr.wkbTriangle : ('wkbTriangle', 'Z') }
     ret = dic[flat_type][0]
     if flat_type != type:
         if ogr.GT_HasM(type):
diff --git a/swig/python/samples/validate_cloud_optimized_geotiff.py b/swig/python/samples/validate_cloud_optimized_geotiff.py
new file mode 100644
index 0000000..20298f4
--- /dev/null
+++ b/swig/python/samples/validate_cloud_optimized_geotiff.py
@@ -0,0 +1,194 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# *****************************************************************************
+#  $Id: validate_cloud_optimized_geotiff.py 37254 2017-01-31 12:17:52Z rouault $
+#
+#  Project:  GDAL
+#  Purpose:  Validate Cloud Optimized GeoTIFF file structure
+#  Author:   Even Rouault, <even dot rouault at spatialys dot com>
+#
+# *****************************************************************************
+#  Copyright (c) 2017, Even Rouault
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+#  and/or sell copies of the Software, and to permit persons to whom the
+#  Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice shall be included
+#  in all copies or substantial portions of the Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+#  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+#  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+#  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+#  DEALINGS IN THE SOFTWARE.
+# *****************************************************************************
+
+import sys
+from osgeo import gdal
+
+
+def Usage():
+    print('Usage: validate_cloud_optimized_geotiff.py [-q] test.tif')
+    print('')
+    return 1
+
+
+class ValidateCloudOptimizedGeoTIFFException(Exception):
+    pass
+
+
+def validate(filename, check_tiled=True):
+    """ Return if the passed file is a (Geo)TIFF file with a cloud
+        optimized compatible structure, otherwise raise a
+        ValidateCloudOptimizedGeoTIFFException exception. """
+
+    if int(gdal.VersionInfo('VERSION_NUM')) < 2020000:
+        raise ValidateCloudOptimizedGeoTIFFException(
+            "GDAL 2.2 or above required")
+
+    gdal.PushErrorHandler()
+    ds = gdal.Open(filename)
+    gdal.PopErrorHandler()
+    if ds is None:
+        raise ValidateCloudOptimizedGeoTIFFException(
+            "Invalid file : %s" % gdal.GetLastErrorMsg())
+    if ds.GetDriver().ShortName != 'GTiff':
+        raise ValidateCloudOptimizedGeoTIFFException(
+            "The file is not a GeoTIFF")
+
+    main_band = ds.GetRasterBand(1)
+    ovr_count = main_band.GetOverviewCount()
+    if filename + '.ovr' in ds.GetFileList():
+        raise ValidateCloudOptimizedGeoTIFFException(
+            "Overviews should be internal")
+
+    if check_tiled:
+        block_size = main_band.GetBlockSize()
+        if block_size[0] == main_band.XSize:
+            raise ValidateCloudOptimizedGeoTIFFException(
+                "Full resolution image is not tiled")
+
+    if main_band.XSize >= 512 or main_band.YSize >= 512:
+        if ovr_count == 0:
+            raise ValidateCloudOptimizedGeoTIFFException(
+                "The file should have overviews")
+
+    ifd_offset = \
+        [int(main_band.GetMetadataItem('IFD_OFFSET', 'TIFF'))]
+    if ifd_offset[0] != 8:
+        raise ValidateCloudOptimizedGeoTIFFException(
+            "The offset of the main IFD should be 8. It is %d instead" %
+            ifd_offset[0])
+
+    for i in range(ovr_count):
+        # Check that overviews are by descending sizes
+        ovr_band = ds.GetRasterBand(1).GetOverview(i)
+        if i == 0:
+            if ovr_band.XSize > main_band.XSize or \
+               ovr_band.YSize > main_band.YSize:
+                    raise ValidateCloudOptimizedGeoTIFFException(
+                       "First overview has larger dimension than main band")
+        else:
+            prev_ovr_band = ds.GetRasterBand(1).GetOverview(i-1)
+            if ovr_band.XSize > prev_ovr_band.XSize or \
+               ovr_band.YSize > prev_ovr_band.YSize:
+                    raise ValidateCloudOptimizedGeoTIFFException(
+                       "Overview of index %d has larger dimension than "
+                       "overview of index %d" % (i, i-1))
+
+        if check_tiled:
+            block_size = ovr_band.GetBlockSize()
+            if block_size[0] == ovr_band.XSize:
+                raise ValidateCloudOptimizedGeoTIFFException(
+                    "Overview of index %d is not tiled" % i)
+
+        # Check that the IFD of descending overviews are sorted by increasing
+        # offsets
+        ifd_offset.append(int(ovr_band.GetMetadataItem('IFD_OFFSET', 'TIFF')))
+        if ifd_offset[-1] < ifd_offset[-2]:
+            if i == 0:
+                raise ValidateCloudOptimizedGeoTIFFException(
+                    "The offset of the IFD for overview of index %d is %d, "
+                    "whereas it should be greater than the one of the main "
+                    "image, which is at byte %d" %
+                    (i, ifd_offset[-1], ifd_offset[-2]))
+            else:
+                raise ValidateCloudOptimizedGeoTIFFException(
+                    "The offset of the IFD for overview of index %d is %d, "
+                    "whereas it should be greater than the one of index %d, "
+                    "which is at byte %d" %
+                    (i, ifd_offset[-1], i-1, ifd_offset[-2]))
+
+    # Check that the imagery starts by the smallest overview and ends with
+    # the main resolution dataset
+    data_offset = [int(main_band.GetMetadataItem('BLOCK_OFFSET_0_0', 'TIFF'))]
+    for i in range(ovr_count):
+        ovr_band = ds.GetRasterBand(1).GetOverview(i)
+        data_offset.append(int(
+            ovr_band.GetMetadataItem('BLOCK_OFFSET_0_0', 'TIFF')))
+
+    if data_offset[-1] < ifd_offset[-1]:
+        if ovr_count > 0:
+            raise ValidateCloudOptimizedGeoTIFFException(
+                "The offset of the first block of the smallest overview "
+                "should be after its IFD")
+        else:
+            raise ValidateCloudOptimizedGeoTIFFException(
+                "The offset of the first block of the image should "
+                "be after its IFD")
+    for i in range(len(data_offset)-2, 0, -1):
+        if data_offset[i] < data_offset[i+1]:
+            raise ValidateCloudOptimizedGeoTIFFException(
+                "The offset of the first block of overview of index %d should "
+                "be after the one of the overview of index %d" %
+                (i-1, i))
+    if len(data_offset) >= 2 and data_offset[0] < data_offset[1]:
+        raise ValidateCloudOptimizedGeoTIFFException(
+            "The offset of the first block of the main resolution image "
+            "should be after the one of the overview of index %d" %
+            (ovr_count - 1))
+
+
+def main():
+    """ Returns 0 in case of success """
+
+    i = 1
+    filename = None
+    quiet = False
+    while i < len(sys.argv):
+        if sys.argv[i] == '-q':
+            quiet = True
+        elif sys.argv[i][0] == '-':
+            return Usage()
+        elif filename is None:
+            filename = sys.argv[i]
+        else:
+            return Usage()
+
+        i = i + 1
+
+    if filename is None:
+        return Usage()
+
+    try:
+        validate(filename)
+        ret = 0
+        if not quiet:
+            print('%s is a valid cloud optimized GeoTIFF' % filename)
+    except ValidateCloudOptimizedGeoTIFFException as e:
+        if not quiet:
+            print('%s is NOT a valid cloud optimized GeoTIFF : %s' %
+                  (filename, str(e)))
+        ret = 1
+
+    return ret
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/swig/python/samples/validate_gpkg.py b/swig/python/samples/validate_gpkg.py
new file mode 100644
index 0000000..79d1011
--- /dev/null
+++ b/swig/python/samples/validate_gpkg.py
@@ -0,0 +1,1554 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+###############################################################################
+# $Id: validate_gpkg.py 37981 2017-04-13 17:15:15Z rouault $
+#
+# Project:  GDAL/OGR
+# Purpose:  Test compliance of GeoPackage database w.r.t GeoPackage spec
+# Author:   Even Rouault <even.rouault at spatialys.com>
+#
+###############################################################################
+# Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+import datetime
+import os
+import sqlite3
+import struct
+import sys
+
+# GDAL may be used for checks on tile content for the tiled gridded extension.
+# If not available, those tests will be skipped
+try:
+    from osgeo import gdal
+    has_gdal = True
+except:
+    has_gdal = False
+
+
+def _esc_id(identifier):
+    return '"' + identifier.replace('"', "\"\"") + '"'
+
+
+def _is_valid_data_type(type):
+    return type in ('BOOLEAN', 'TINYINT', 'SMALLINT', 'MEDIUMINT',
+                    'INT', 'INTEGER', 'FLOAT', 'DOUBLE', 'REAL',
+                    'TEXT', 'BLOB', 'DATE', 'DATETIME') or \
+            type.startswith('TEXT(') or type.startswith('BLOB(')
+
+
+class GPKGCheckException(Exception):
+    pass
+
+
+class GPKGChecker:
+
+    def __init__(self, filename, abort_at_first_error=True, verbose=False):
+        self.filename = filename
+        self.extended_pragma_info = False
+        self.abort_at_first_error = abort_at_first_error
+        self.verbose = verbose
+        self.errors = []
+
+    def _log(self, msg):
+        if self.verbose:
+            print(msg)
+
+    def _assert(self, cond, req, msg):
+        # self._log('Verified requirement %s' % req)
+        if not cond:
+            self.errors += [(req, msg)]
+            if self.abort_at_first_error:
+                if req:
+                    raise GPKGCheckException('Req %d: %s' % (req, msg))
+                else:
+                    raise GPKGCheckException(msg)
+        return cond
+
+    def _check_structure(self, columns, expected_columns, req, table_name):
+        self._assert(len(columns) == len(expected_columns), req,
+                     'Table %s has %d columns, whereas %d are expected' %
+                     (table_name, len(columns), len(expected_columns)))
+        for (_, expected_name, expected_type, expected_notnull,
+             expected_default, expected_pk) in expected_columns:
+            found = False
+            for (_, name, type, notnull, default, pk) in columns:
+                if name != expected_name:
+                    continue
+
+                if expected_type == 'INTEGER' and expected_pk:
+                    expected_notnull = 1
+                if type == 'INTEGER' and pk:
+                    notnull = 1
+                if not self.extended_pragma_info and expected_pk > 1:
+                    expected_pk = 1
+
+                self._assert(type == expected_type, req,
+                             'Wrong type for %s of %s. Expected %s, got %s' %
+                             (name, table_name, expected_type, type))
+                self._assert(notnull == expected_notnull, req,
+                             ('Wrong notnull for %s of %s. ' +
+                              'Expected %s, got %s') %
+                             (name, table_name, expected_notnull, notnull))
+                self._assert(default == expected_default, req,
+                             ('Wrong default for %s of %s. ' +
+                              'Expected %s, got %s') %
+                             (name, table_name, expected_default, default))
+                self._assert(pk == expected_pk, req,
+                             'Wrong pk for %s of %s. Expected %s, got %s' %
+                             (name, table_name, expected_pk, pk))
+                found = True
+                break
+
+            self._assert(found, req, 'Column %s of %s not found!' %
+                         (expected_name, table_name))
+
+    def _check_gpkg_spatial_ref_sys(self, c):
+
+        self._log('Checking gpkg_spatial_ref_sys')
+
+        c.execute("SELECT 1 FROM sqlite_master WHERE "
+                  "name = 'gpkg_spatial_ref_sys'")
+        if not self._assert(c.fetchone() is not None, 10,
+                            "gpkg_spatial_ref_sys table missing"):
+            return
+
+        c.execute("PRAGMA table_info(gpkg_spatial_ref_sys)")
+        columns = c.fetchall()
+        has_definition_12_063 = False
+        for (_, name, _, _, _, _) in columns:
+            if name == 'definition_12_063':
+                has_definition_12_063 = True
+
+        if has_definition_12_063:
+            expected_columns = [
+                (0, 'srs_name', 'TEXT', 1, None, 0),
+                (1, 'srs_id', 'INTEGER', 1, None, 1),
+                (2, 'organization', 'TEXT', 1, None, 0),
+                (3, 'organization_coordsys_id', 'INTEGER', 1, None, 0),
+                (4, 'definition', 'TEXT', 1, None, 0),
+                (5, 'description', 'TEXT', 0, None, 0),
+                (6, 'definition_12_063', 'TEXT', 1, None, 0)
+            ]
+        else:
+            expected_columns = [
+                (0, 'srs_name', 'TEXT', 1, None, 0),
+                (1, 'srs_id', 'INTEGER', 1, None, 1),
+                (2, 'organization', 'TEXT', 1, None, 0),
+                (3, 'organization_coordsys_id', 'INTEGER', 1, None, 0),
+                (4, 'definition', 'TEXT', 1, None, 0),
+                (5, 'description', 'TEXT', 0, None, 0)
+            ]
+        self._check_structure(columns, expected_columns, 10,
+                              'gpkg_spatial_ref_sys')
+
+        if has_definition_12_063:
+            c.execute("SELECT srs_id, organization, organization_coordsys_id, "
+                      "definition, definition_12_063 "
+                      "FROM gpkg_spatial_ref_sys "
+                      "WHERE srs_id IN (-1, 0, 4326) ORDER BY srs_id")
+        else:
+            c.execute("SELECT srs_id, organization, organization_coordsys_id, "
+                      "definition FROM gpkg_spatial_ref_sys "
+                      "WHERE srs_id IN (-1, 0, 4326) ORDER BY srs_id")
+        ret = c.fetchall()
+        self._assert(ret[0][1] == 'NONE', 11,
+                     'wrong value for organization for srs_id = -1: %s' %
+                     ret[0][1])
+        self._assert(ret[0][2] == -1, 11,
+                     'wrong value for organization_coordsys_id for '
+                     'srs_id = -1: %s' % ret[0][2])
+        self._assert(ret[0][3] == 'undefined', 11,
+                     'wrong value for definition for srs_id = -1: %s' %
+                     ret[0][3])
+        if has_definition_12_063:
+            self._assert(ret[0][4] == 'undefined', 116,
+                         'wrong value for definition_12_063 for ' +
+                         'srs_id = -1: %s' % ret[0][4])
+
+        self._assert(ret[1][1] == 'NONE', 11,
+                     'wrong value for organization for srs_id = 0: %s' %
+                     ret[1][1])
+        self._assert(ret[1][2] == 0, 11,
+                     'wrong value for organization_coordsys_id for '
+                     'srs_id = 0: %s' % ret[1][2])
+        self._assert(ret[1][3] == 'undefined', 11,
+                     'wrong value for definition for srs_id = 0: %s' %
+                     ret[1][3])
+        if has_definition_12_063:
+            self._assert(ret[1][4] == 'undefined', 116,
+                         'wrong value for definition_12_063 for ' +
+                         'srs_id = 0: %s' % ret[1][4])
+
+        self._assert(ret[2][1].lower() == 'epsg', 11,
+                     'wrong value for organization for srs_id = 4326: %s' %
+                     ret[2][1])
+        self._assert(ret[2][2] == 4326, 11,
+                     'wrong value for organization_coordsys_id for '
+                     'srs_id = 4326: %s' % ret[2][2])
+        self._assert(ret[2][3] != 'undefined', 11,
+                     'wrong value for definition for srs_id = 4326: %s' %
+                     ret[2][3])
+        if has_definition_12_063:
+            self._assert(ret[2][4] != 'undefined', 116,
+                         'wrong value for definition_12_063 for ' +
+                         'srs_id = 4326: %s' % ret[2][4])
+
+        if has_definition_12_063:
+            c.execute("SELECT srs_id FROM gpkg_spatial_ref_sys "
+                      "WHERE srs_id NOT IN (0, -1) AND "
+                      "definition = 'undefined' AND "
+                      "definition_12_063 = 'undefined'")
+            rows = c.fetchall()
+            for (srs_id, ) in rows:
+                self._assert(False, 117,
+                             'srs_id = %d has both definition and ' % srs_id +
+                             'definition_12_063 undefined')
+
+    def _check_gpkg_contents(self, c):
+
+        self._log('Checking gpkg_contents')
+
+        c.execute("SELECT 1 FROM sqlite_master WHERE name = 'gpkg_contents'")
+        self._assert(c.fetchone() is not None, 13,
+                     "gpkg_contents table missing")
+
+        c.execute("PRAGMA table_info(gpkg_contents)")
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'table_name', 'TEXT', 1, None, 1),
+            (1, 'data_type', 'TEXT', 1, None, 0),
+            (2, 'identifier', 'TEXT', 0, None, 0),
+            (3, 'description', 'TEXT', 0, "''", 0),
+            (4, 'last_change', 'DATETIME', 1,
+             "strftime('%Y-%m-%dT%H:%M:%fZ','now')", 0),
+            (5, 'min_x', 'DOUBLE', 0, None, 0),
+            (6, 'min_y', 'DOUBLE', 0, None, 0),
+            (7, 'max_x', 'DOUBLE', 0, None, 0),
+            (8, 'max_y', 'DOUBLE', 0, None, 0),
+            (9, 'srs_id', 'INTEGER', 0, None, 0)
+        ]
+        self._check_structure(columns, expected_columns, 13, 'gpkg_contents')
+
+        c.execute("SELECT 1 FROM gpkg_contents "
+                  "WHERE data_type IN ('features', 'tiles')")
+        self._assert(c.fetchone() is not None, 17,
+                     'gpkg_contents should at least have one table with '
+                     'data_type = features and/or tiles')
+
+        c.execute("SELECT table_name, data_type FROM gpkg_contents "
+                  "WHERE data_type NOT IN "
+                  "('features', 'tiles', 'attributes', '2d-gridded-coverage')")
+        ret = c.fetchall()
+        self._assert(len(ret) == 0, 17,
+                     'Unexpected data types in gpkg_contents: %s' % str(ret))
+
+        c.execute('SELECT table_name, last_change, srs_id FROM gpkg_contents')
+        rows = c.fetchall()
+        for (table_name, last_change, srs_id) in rows:
+            c.execute("SELECT 1 FROM sqlite_master WHERE "
+                      "name = ? AND type IN ('table', 'view')", (table_name,))
+            self._assert(c.fetchone() is not None, 14,
+                         ('table_name=%s in gpkg_contents is not a ' +
+                          'table or view') % table_name)
+
+            try:
+                datetime.datetime.strptime(
+                    last_change, '%Y-%m-%dT%H:%M:%S.%fZ')
+            except:
+                self._assert(False, 15,
+                             ('last_change = %s for table_name = %s ' +
+                              'is invalid datetime') %
+                             (last_change, table_name))
+
+            if srs_id is not None:
+                c.execute('SELECT 1 FROM gpkg_spatial_ref_sys '
+                          'WHERE srs_id = ?', (srs_id, ))
+                self._assert(c.fetchone() is not None, 14,
+                             ("table_name=%s has srs_id=%d in gpkg_contents " +
+                              "which isn't found in gpkg_spatial_ref_sys") %
+                             (table_name, srs_id))
+
+    def _check_vector_user_table(self, c, table_name):
+
+        self._log('Checking vector user table ' + table_name)
+
+        c.execute("SELECT column_name, z, m, geometry_type_name, srs_id "
+                  "FROM gpkg_geometry_columns WHERE table_name = ?",
+                  (table_name,))
+        rows_gpkg_geometry_columns = c.fetchall()
+        self._assert(len(rows_gpkg_geometry_columns) == 1, 22,
+                     ('table_name = %s is not registered in ' +
+                      'gpkg_geometry_columns') % table_name)
+        geom_column_name = rows_gpkg_geometry_columns[0][0]
+        z = rows_gpkg_geometry_columns[0][1]
+        m = rows_gpkg_geometry_columns[0][2]
+        geometry_type_name = rows_gpkg_geometry_columns[0][3]
+        srs_id = rows_gpkg_geometry_columns[0][4]
+
+        c.execute('PRAGMA table_info(%s)' % table_name)
+        base_geom_types = ('GEOMETRY', 'POINT', 'LINESTRING', 'POLYGON',
+                           'MULTIPOINT', 'MULTILINESTRING', 'MULTIPOLYGON',
+                           'GEOMETRYCOLLECTION')
+        ext_geom_types = ('CIRCULARSTRING', 'COMPOUNDCURVE', 'CURVEPOLYGON',
+                          'MULTICURVE', 'MULTISURFACE', 'CURVE', 'SURFACE')
+        cols = c.fetchall()
+        found_geom = False
+        count_pkid = 0
+        for (_, name, type, notnull, default, pk) in cols:
+            if name == geom_column_name:
+                found_geom = True
+                self._assert(
+                    type in base_geom_types or type in ext_geom_types,
+                    25, ('invalid type (%s) for geometry ' +
+                         'column of table %s') % (type, table_name))
+                self._assert(type == geometry_type_name, 31,
+                             ('table %s has geometry column of type %s in ' +
+                              'SQL and %s in geometry_type_name of ' +
+                              'gpkg_geometry_columns') %
+                             (table_name, type, geometry_type_name))
+
+            elif pk == 1:
+                count_pkid += 1
+                self._assert(type == 'INTEGER', 29,
+                             ('table %s has a PRIMARY KEY of type %s ' +
+                              'instead of INTEGER') % (table_name, type))
+
+            else:
+                self._assert(_is_valid_data_type(type), 5,
+                             ('table %s has column %s of unexpected type %s'
+                             % (table_name, name, type)))
+        self._assert(found_geom, 24,
+                     'table %s has no %s column' %
+                     (table_name, geom_column_name))
+        self._assert(count_pkid == 1, 29,
+                     'table %s has no INTEGER PRIMARY KEY' % table_name)
+
+        self._assert(z in (0, 1, 2), 27, ("z value of %s is %d. " +
+                     "Expected 0, 1 or 2") % (table_name, z))
+
+        self._assert(m in (0, 1, 2), 27, ("m value of %s is %d. " +
+                     "Expected 0, 1 or 2") % (table_name, m))
+
+        if geometry_type_name in ext_geom_types:
+            c.execute("SELECT 1 FROM gpkg_extensions WHERE "
+                      "extension_name = 'gpkg_geom_%s' AND "
+                      "table_name = ? AND column_name = ? AND "
+                      "scope = 'read-write'" % geometry_type_name,
+                      (table_name, geom_column_name))
+            self._assert(c.fetchone() is not None, 68,
+                         "gpkg_geom_%s extension should be declared for "
+                         "table %s" % (geometry_type_name, table_name))
+
+        wkb_geometries = base_geom_types + ext_geom_types
+        c.execute("SELECT %s FROM %s " %
+                  (_esc_id(geom_column_name), _esc_id(table_name)))
+        found_geom_types = set()
+        for (blob,) in c.fetchall():
+            if blob is None:
+                continue
+            self._assert(len(blob) >= 8, 19, 'Invalid geometry')
+            max_size_needed = min(len(blob), 8 + 4 * 2 * 8 + 5)
+            blob_ar = struct.unpack('B' * max_size_needed,
+                                    blob[0:max_size_needed])
+            self._assert(blob_ar[0] == ord('G'), 19, 'Invalid geometry')
+            self._assert(blob_ar[1] == ord('P'), 19, 'Invalid geometry')
+            self._assert(blob_ar[2] == 0, 19, 'Invalid geometry')
+            flags = blob_ar[3]
+            big_endian = (flags & 1) == 0
+            env_ind = (flags >> 1) & 7
+            self._assert(((flags >> 5) & 1) == 0, 19,
+                         'Invalid geometry: ExtendedGeoPackageBinary not '
+                         'allowed')
+            self._assert(env_ind <= 4, 19,
+                         'Invalid geometry: invalid envelope indicator code')
+            if big_endian:
+                geom_srs_id = struct.unpack('>I' * 1, blob[4:8])[0]
+            else:
+                geom_srs_id = struct.unpack('<I' * 1, blob[4:8])[0]
+            self._assert(srs_id == geom_srs_id, 33,
+                         ('table %s has geometries with SRID %d, ' +
+                          'whereas only %d is expected') %
+                         (table_name, geom_srs_id, srs_id))
+            if env_ind == 0:
+                coord_dim = 0
+            elif env_ind == 1:
+                coord_dim = 2
+            elif env_ind == 2 or env_ind == 3:
+                coord_dim = 3
+            else:
+                coord_dim = 4
+
+            # if env_ind == 2 or env_ind == 4:
+            #    self._assert(z > 0, 19,
+            #        'z found in geometry, but not in gpkg_geometry_columns')
+            # if env_ind == 3 or env_ind == 4:
+            #    self._assert(m > 0, 19,
+            #        'm found in geometry, but not in gpkg_geometry_columns')
+
+            header_len = 8 + coord_dim * 2 * 8
+            self._assert(len(blob) >= header_len, 19, 'Invalid geometry')
+            wkb_endianness = blob_ar[header_len]
+            wkb_big_endian = (wkb_endianness == 0)
+            if wkb_big_endian:
+                wkb_geom_type = struct.unpack(
+                    '>I' * 1, blob[header_len+1:header_len+5])[0]
+            else:
+                wkb_geom_type = struct.unpack(
+                    '<I' * 1, blob[header_len+1:header_len+5])[0]
+            self._assert(wkb_geom_type >= 0 and
+                         (wkb_geom_type % 1000) < len(wkb_geometries),
+                         19, 'Invalid WKB geometry type')
+
+            wkb_dim = int(wkb_geom_type / 1000)
+            if z == 1:
+                self._assert(wkb_dim == 1 or wkb_dim == 3, 19,
+                             'geometry without Z found')
+            if m == 1:
+                self._assert(wkb_dim == 2 or wkb_dim == 3, 19,
+                             'geometry without M found')
+            if wkb_dim == 1 or wkb_dim == 3:  # Z or ZM
+                self._assert(z > 0, 19,
+                             'z found in geometry, but not in '
+                             'gpkg_geometry_columns')
+            if wkb_dim == 2 or wkb_dim == 3:  # M or ZM
+                self._assert(m > 0, 19,
+                             'm found in geometry, but not in '
+                             'gpkg_geometry_columns')
+
+            found_geom_types.add(wkb_geometries[wkb_geom_type % 1000])
+
+        if geometry_type_name in ('POINT', 'LINESTRING', 'POLYGON',
+                                  'MULTIPOINT', 'MULTILINESTRING',
+                                  'MULTIPOLYGON'):
+            self._assert(len(found_geom_types) == 0 or
+                         found_geom_types == set([geometry_type_name]), 32,
+                         'in table %s, found geometry types %s' %
+                         (table_name, str(found_geom_types)))
+        elif geometry_type_name == 'GEOMETRYCOLLECTION':
+            self._assert(len(found_geom_types) == 0 or
+                         len(found_geom_types.difference(
+                            set(['GEOMETRYCOLLECTION', 'MULTIPOINT',
+                                 'MULTILINESTRING', 'MULTIPOLYGON',
+                                 'MULTICURVE', 'MULTISURFACE']))) == 0, 32,
+                         'in table %s, found geometry types %s' %
+                         (table_name, str(found_geom_types)))
+        elif geometry_type_name in ('CURVEPOLYGON', 'SURFACE'):
+            self._assert(len(found_geom_types) == 0 or
+                         len(found_geom_types.difference(
+                            set(['POLYGON', 'CURVEPOLYGON']))) == 0, 32,
+                         'in table %s, found geometry types %s' %
+                         (table_name, str(found_geom_types)))
+        elif geometry_type_name == 'MULTICURVE':
+            self._assert(len(found_geom_types) == 0 or
+                         len(found_geom_types.difference(
+                            set(['MULTILINESTRING', 'MULTICURVE']))) == 0, 32,
+                         'in table %s, found geometry types %s' %
+                         (table_name, str(found_geom_types)))
+        elif geometry_type_name == 'MULTISURFACE':
+            self._assert(len(found_geom_types) == 0 or
+                         len(found_geom_types.difference(
+                            set(['MULTIPOLYGON', 'MULTISURFACE']))) == 0, 32,
+                         'in table %s, found geometry types %s' %
+                         (table_name, str(found_geom_types)))
+        elif geometry_type_name == 'CURVE':
+            self._assert(len(found_geom_types) == 0 or
+                         len(found_geom_types.difference(
+                            set(['LINESTRING', 'CIRCULARSTRING',
+                                 'COMPOUNDCURVE']))) == 0, 32,
+                         'in table %s, found geometry types %s' %
+                         (table_name, str(found_geom_types)))
+
+        for geom_type in found_geom_types:
+            if geom_type in ext_geom_types:
+                c.execute("SELECT 1 FROM gpkg_extensions WHERE "
+                          "extension_name = 'gpkg_geom_%s' AND "
+                          "table_name = ? AND column_name = ? AND "
+                          "scope = 'read-write'" % geom_type,
+                          (table_name, geom_column_name))
+                self._assert(c.fetchone() is not None, 68,
+                             "gpkg_geom_%s extension should be declared for "
+                             "table %s" % (geom_type, table_name))
+
+        rtree_name = 'rtree_%s_%s' % (table_name, geom_column_name)
+        c.execute("SELECT 1 FROM sqlite_master WHERE name = ?", (rtree_name,))
+        has_rtree = c.fetchone() is not None
+        if has_rtree:
+            c.execute("SELECT 1 FROM gpkg_extensions WHERE "
+                      "extension_name = 'gpkg_rtree_index' AND "
+                      "table_name=? AND column_name=? AND "
+                      "scope='write-only'",
+                      (table_name, geom_column_name))
+            self._assert(c.fetchone() is not None, 78,
+                         ("Table %s has a RTree, but not declared in " +
+                          "gpkg_extensions") % table_name)
+
+            c.execute('PRAGMA table_info(%s)' % rtree_name)
+            columns = c.fetchall()
+            expected_columns = [
+                (0, 'id', '', 0, None, 0),
+                (1, 'minx', '', 0, None, 0),
+                (2, 'maxx', '', 0, None, 0),
+                (3, 'miny', '', 0, None, 0),
+                (4, 'maxy', '', 0, None, 0)
+            ]
+            self._check_structure(columns, expected_columns, 77, rtree_name)
+
+            c.execute("SELECT 1 FROM sqlite_master WHERE type = 'trigger' " +
+                      "AND name = '%s_insert'" % rtree_name)
+            self._assert(c.fetchone() is not None, 75,
+                         "%s_insert trigger missing" % rtree_name)
+
+            for i in range(4):
+                c.execute("SELECT 1 FROM sqlite_master WHERE " +
+                          "type = 'trigger' " +
+                          "AND name = '%s_update%d'" % (rtree_name, i+1))
+                self._assert(c.fetchone() is not None, 75,
+                             "%s_update%d trigger missing" % (rtree_name, i+1))
+
+            c.execute("SELECT 1 FROM sqlite_master WHERE type = 'trigger' " +
+                      "AND name = '%s_delete'" % rtree_name)
+            self._assert(c.fetchone() is not None, 75,
+                         "%s_delete trigger missing" % rtree_name)
+
+    def _check_features(self, c):
+
+        self._log('Checking features')
+
+        c.execute("SELECT 1 FROM gpkg_contents WHERE data_type = 'features'")
+        if c.fetchone() is None:
+            self._log('... No features table')
+            return
+
+        self._log('Checking gpkg_geometry_columns')
+        c.execute("SELECT 1 FROM sqlite_master WHERE "
+                  "name = 'gpkg_geometry_columns'")
+        self._assert(c.fetchone() is not None, 21,
+                     "gpkg_geometry_columns table missing")
+
+        c.execute("PRAGMA table_info(gpkg_geometry_columns)")
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'table_name', 'TEXT', 1, None, 1),
+            (1, 'column_name', 'TEXT', 1, None, 2),
+            (2, 'geometry_type_name', 'TEXT', 1, None, 0),
+            (3, 'srs_id', 'INTEGER', 1, None, 0),
+            (4, 'z', 'TINYINT', 1, None, 0),
+            (5, 'm', 'TINYINT', 1, None, 0)
+        ]
+        self._check_structure(columns, expected_columns, 21,
+                              'gpkg_geometry_columns')
+
+        c.execute("SELECT table_name FROM gpkg_contents WHERE "
+                  "data_type = 'features'")
+        rows = c.fetchall()
+        for (table_name,) in rows:
+            self._check_vector_user_table(c, table_name)
+
+        c.execute("SELECT table_name, srs_id FROM gpkg_geometry_columns")
+        rows = c.fetchall()
+        for (table_name, srs_id) in rows:
+            c.execute("SELECT 1 FROM gpkg_contents WHERE table_name = ? " +
+                      "AND data_type='features'", (table_name,))
+            ret = c.fetchall()
+            self._assert(len(ret) == 1, 23,
+                         ('table_name = %s is registered in ' +
+                          'gpkg_geometry_columns, but not in gpkg_contents') %
+                         table_name)
+
+            c.execute('SELECT 1 FROM gpkg_spatial_ref_sys WHERE ' +
+                      'srs_id = ?', (srs_id, ))
+            self._assert(c.fetchone() is not None, 14,
+                         ("table_name=%s has srs_id=%d in " +
+                          "gpkg_geometry_columns which isn't found in " +
+                          "gpkg_spatial_ref_sys") % (table_name, srs_id))
+
+    def _check_attributes(self, c):
+
+        self._log('Checking attributes')
+        c.execute("SELECT table_name FROM gpkg_contents WHERE "
+                  "data_type = 'attributes'")
+        rows = c.fetchall()
+        if len(rows) == 0:
+            self._log('... No attributes table')
+        for (table_name,) in rows:
+            self._log('Checking attributes table ' + table_name)
+
+            c.execute('PRAGMA table_info(%s)' % table_name)
+            cols = c.fetchall()
+            count_pkid = 0
+            for (_, name, type, notnull, default, pk) in cols:
+                if pk == 1:
+                    count_pkid += 1
+                    self._assert(type == 'INTEGER', 119,
+                                 ('table %s has a PRIMARY KEY of type %s ' +
+                                  'instead of INTEGER') % (table_name, type))
+
+                else:
+                    self._assert(_is_valid_data_type(type), 5,
+                                 'table %s has column %s of unexpected type %s'
+                                 % (table_name, name, type))
+
+            self._assert(count_pkid == 1, 119,
+                         'table %s has no INTEGER PRIMARY KEY' % table_name)
+
+    def _check_tile_user_table(self, c, table_name, data_type):
+
+        self._log('Checking tile pyramid user table ' + table_name)
+
+        c.execute("PRAGMA table_info(%s)" % table_name)
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'id', 'INTEGER', 0, None, 1),
+            (1, 'zoom_level', 'INTEGER', 1, None, 0),
+            (2, 'tile_column', 'INTEGER', 1, None, 0),
+            (3, 'tile_row', 'INTEGER', 1, None, 0),
+            (4, 'tile_data', 'BLOB', 1, None, 0)
+        ]
+
+        self._check_structure(columns, expected_columns, 54,
+                              'gpkg_tile_matrix_set')
+
+        c.execute("SELECT DISTINCT zoom_level FROM %s" % _esc_id(table_name))
+        rows = c.fetchall()
+        for (zoom_level, ) in rows:
+            c.execute("SELECT 1 FROM gpkg_tile_matrix WHERE table_name = ? "
+                      "AND zoom_level = ?", (table_name, zoom_level))
+            self._assert(c.fetchone() is not None, 44,
+                         ("Table %s has data for zoom_level = %d, but no " +
+                          "corresponding row in gpkg_tile_matrix") %
+                         (table_name, zoom_level))
+
+        zoom_other_levels = False
+        c.execute("SELECT 1 FROM sqlite_master WHERE name = 'gpkg_extensions'")
+        if c.fetchone() is not None:
+            c.execute("SELECT column_name FROM gpkg_extensions WHERE "
+                      "table_name = ? "
+                      "AND extension_name = 'gpkg_zoom_other'", (table_name,))
+            row = c.fetchone()
+            if row is not None:
+                (column_name, ) = row
+                self._assert(column_name == 'tile_data', 88,
+                             'Wrong column_name in gpkg_extensions for '
+                             'gpkg_zoom_other')
+                zoom_other_levels = True
+
+        c.execute("SELECT zoom_level, pixel_x_size, pixel_y_size "
+                  "FROM gpkg_tile_matrix "
+                  "WHERE table_name = ? ORDER BY zoom_level", (table_name,))
+        rows = c.fetchall()
+        prev_zoom_level = None
+        prev_pixel_x_size = None
+        prev_pixel_y_size = None
+        for (zoom_level, pixel_x_size, pixel_y_size) in rows:
+            if prev_pixel_x_size is not None:
+                self._assert(
+                    pixel_x_size < prev_pixel_x_size and
+                    pixel_y_size < prev_pixel_y_size,
+                    53,
+                    ('For table %s, pixel size are not consistent ' +
+                     'with zoom_level') % table_name)
+            if prev_zoom_level is not None and \
+               zoom_level == prev_zoom_level + 1 and not zoom_other_levels:
+                    self._assert(
+                        abs((pixel_x_size-prev_pixel_x_size/2) /
+                            prev_pixel_x_size) < 1e-5, 35,
+                        "Expected pixel_x_size=%f for zoom_level=%d. Got %f" %
+                        (prev_pixel_x_size/2, zoom_level, pixel_x_size))
+                    self._assert(
+                        abs((pixel_y_size-prev_pixel_y_size/2) /
+                            prev_pixel_y_size) < 1e-5, 35,
+                        "Expected pixel_y_size=%f for zoom_level=%d. Got %f" %
+                        (prev_pixel_y_size/2, zoom_level, pixel_y_size))
+
+            prev_pixel_x_size = pixel_x_size
+            prev_pixel_y_size = pixel_y_size
+            prev_zoom_level = zoom_level
+
+        c.execute("SELECT max_x - min_x, "
+                  "       MIN(matrix_width * tile_width * pixel_x_size), "
+                  "       MAX(matrix_width * tile_width * pixel_x_size), "
+                  "       max_y - min_y, "
+                  "       MIN(matrix_height * tile_height * pixel_y_size), "
+                  "       MAX(matrix_height * tile_height * pixel_y_size) "
+                  "FROM gpkg_tile_matrix tm JOIN gpkg_tile_matrix_set tms "
+                  "ON tm.table_name = tms.table_name WHERE tm.table_name = ?",
+                  (table_name,))
+        rows = c.fetchall()
+        if len(rows) != 0:
+            (dx, min_dx, max_dx, dy, min_dy, max_dy) = rows[0]
+            self._assert(abs((min_dx - dx) / dx) < 1e-3 and
+                         abs((max_dx - dx) / dx) < 1e-3 and
+                         abs((min_dy - dy) / dy) < 1e-3 and
+                         abs((max_dy - dy) / dy) < 1e-3, 45,
+                         ("Inconsistent values in gpkg_tile_matrix and " +
+                          "gpkg_tile_matrix_set for table %s") % table_name)
+
+        c.execute("SELECT DISTINCT zoom_level FROM %s" % _esc_id(table_name))
+        rows = c.fetchall()
+        for (zoom_level,) in rows:
+            c.execute(("SELECT MIN(tile_column), MAX(tile_column), " +
+                       "MIN(tile_row), MAX(tile_row) FROM %s " +
+                       "WHERE zoom_level = %d") %
+                      (_esc_id(table_name), zoom_level))
+            min_col, max_col, min_row, max_row = c.fetchone()
+
+            c.execute("SELECT matrix_width, matrix_height FROM "
+                      "gpkg_tile_matrix "
+                      "WHERE table_name = ? AND zoom_level = ?",
+                      (table_name, zoom_level))
+            rows2 = c.fetchall()
+            if len(rows2) == 0:
+                self._assert(False, 55,
+                             "Invalid zoom_level in %s" % table_name)
+            else:
+                matrix_width, matrix_height = rows2[0]
+                self._assert(min_col >= 0 and min_col < matrix_width, 56,
+                             "Invalid tile_col in %s" % table_name)
+                self._assert(min_row >= 0 and min_row < matrix_height, 57,
+                             "Invalid tile_row in %s" % table_name)
+
+        c.execute("SELECT tile_data FROM %s" % _esc_id(table_name))
+        found_jpeg = False
+        found_png = False
+        found_webp = False
+        found_tiff = False
+        for (blob,) in c.fetchall():
+            self._assert(blob is not None and len(blob) >= 12, 19,
+                         'Invalid blob')
+            max_size_needed = 12
+            blob_ar = struct.unpack('B' * max_size_needed,
+                                    blob[0:max_size_needed])
+            is_jpeg = blob_ar[0:3] == (0xff, 0xd8, 0xff)
+            is_png = blob_ar[0:4] == (0x89, 0x50, 0x4E, 0x47)
+            is_webp = blob_ar[0:4] == (ord('R'), ord('I'),
+                                       ord('F'), ord('F')) and \
+                blob_ar[8:12] == (ord('W'), ord('E'), ord('B'), ord('P'))
+            is_tiff = blob_ar[0:4] == (0x49, 0x49, 0x2A, 0x00) or \
+                blob_ar[0:4] == (0x4D, 0x4D, 0x00, 0x2A)
+            self._assert(is_jpeg or is_png or is_webp or is_tiff, 36,
+                         'Unrecognized image mime type')
+            if data_type == 'tiles':
+                self._assert(is_jpeg or is_png or is_webp, 36,
+                             'Unrecognized image mime type')
+            elif data_type == '2d-gridded-coverage':
+                self._assert(is_png or is_tiff, 36,
+                             'Unrecognized image mime type')
+
+            if is_jpeg:
+                found_jpeg = True
+            if is_png:
+                found_png = True
+            if is_webp:
+                found_webp = True
+            if is_tiff:
+                found_tiff = True
+
+        if found_webp:
+            self._assert(not found_png and not found_jpeg and not found_tiff,
+                         92,
+                         "Table %s should contain only webp tiles" %
+                         table_name)
+            c.execute("SELECT 1 FROM gpkg_extensions WHERE "
+                      "table_name = ? AND column_name = 'tile_data' AND "
+                      "extension_name = 'gpkg_webp' AND "
+                      "scope = 'read-write'", (table_name, ))
+            self._assert(c.fetchone() is not None, 91,
+                         ("Table %s has webp content, but not registered "
+                          "in gpkg_extensions" % table_name))
+
+    def _check_tiles(self, c):
+
+        self._log('Checking tiles')
+
+        c.execute("SELECT 1 FROM gpkg_contents WHERE data_type IN "
+                  "('tiles', '2d-gridded-coverage')")
+        if c.fetchone() is None:
+            self._log('... No tiles table')
+            return
+
+        self._log('Checking gpkg_tile_matrix_set ')
+        c.execute("SELECT 1 FROM sqlite_master WHERE "
+                  "name = 'gpkg_tile_matrix_set'")
+        self._assert(c.fetchone() is not None, 38,
+                     "gpkg_tile_matrix_set table missing")
+
+        c.execute("PRAGMA table_info(gpkg_tile_matrix_set)")
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'table_name', 'TEXT', 1, None, 1),
+            (1, 'srs_id', 'INTEGER', 1, None, 0),
+            (2, 'min_x', 'DOUBLE', 1, None, 0),
+            (3, 'min_y', 'DOUBLE', 1, None, 0),
+            (4, 'max_x', 'DOUBLE', 1, None, 0),
+            (5, 'max_y', 'DOUBLE', 1, None, 0)]
+        self._check_structure(columns, expected_columns, 38,
+                              'gpkg_tile_matrix_set')
+
+        c.execute("SELECT table_name, srs_id FROM gpkg_tile_matrix_set")
+        rows = c.fetchall()
+        for (table_name, srs_id) in rows:
+            c.execute("SELECT 1 FROM gpkg_contents WHERE table_name = ? " +
+                      "AND data_type IN ('tiles', '2d-gridded-coverage')",
+                      (table_name,))
+            ret = c.fetchall()
+            self._assert(len(ret) == 1, 39,
+                         ('table_name = %s is registered in ' +
+                          'gpkg_tile_matrix_set, but not in gpkg_contents') %
+                         table_name)
+
+            c.execute('SELECT 1 FROM gpkg_spatial_ref_sys WHERE srs_id = ?',
+                      (srs_id, ))
+            self._assert(c.fetchone() is not None, 41,
+                         ("table_name=%s has srs_id=%d in " +
+                          "gpkg_tile_matrix_set which isn't found in " +
+                          "gpkg_spatial_ref_sys") % (table_name, srs_id))
+
+        self._log('Checking gpkg_tile_matrix')
+        c.execute("SELECT 1 FROM sqlite_master WHERE "
+                  "name = 'gpkg_tile_matrix'")
+        self._assert(c.fetchone() is not None, 42,
+                     "gpkg_tile_matrix table missing")
+
+        c.execute("PRAGMA table_info(gpkg_tile_matrix)")
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'table_name', 'TEXT', 1, None, 1),
+            (1, 'zoom_level', 'INTEGER', 1, None, 2),
+            (2, 'matrix_width', 'INTEGER', 1, None, 0),
+            (3, 'matrix_height', 'INTEGER', 1, None, 0),
+            (4, 'tile_width', 'INTEGER', 1, None, 0),
+            (5, 'tile_height', 'INTEGER', 1, None, 0),
+            (6, 'pixel_x_size', 'DOUBLE', 1, None, 0),
+            (7, 'pixel_y_size', 'DOUBLE', 1, None, 0)
+        ]
+        self._check_structure(columns, expected_columns, 42,
+                              'gpkg_tile_matrix')
+
+        c.execute("SELECT table_name, zoom_level, matrix_width, "
+                  "matrix_height, tile_width, tile_height, pixel_x_size, "
+                  "pixel_y_size FROM gpkg_tile_matrix")
+        rows = c.fetchall()
+        for (table_name, zoom_level, matrix_width, matrix_height, tile_width,
+             tile_height, pixel_x_size, pixel_y_size) in rows:
+            c.execute("SELECT 1 FROM gpkg_contents WHERE table_name = ? "
+                      "AND data_type IN ('tiles', '2d-gridded-coverage')",
+                      (table_name,))
+            ret = c.fetchall()
+            self._assert(len(ret) == 1, 43,
+                         ('table_name = %s is registered in ' +
+                          'gpkg_tile_matrix, but not in gpkg_contents') %
+                         table_name)
+            self._assert(zoom_level >= 0, 46,
+                         "Invalid zoom_level = %d for table %s" %
+                         (zoom_level, table_name))
+            self._assert(matrix_width > 0, 47,
+                         "Invalid matrix_width = %d for table %s" %
+                         (matrix_width, table_name))
+            self._assert(matrix_height > 0, 48,
+                         "Invalid matrix_height = %d for table %s" %
+                         (matrix_height, table_name))
+            self._assert(tile_width > 0, 49,
+                         "Invalid tile_width = %d for table %s" %
+                         (tile_width, table_name))
+            self._assert(tile_height > 0, 50,
+                         "Invalid tile_height = %d for table %s" %
+                         (tile_height, table_name))
+            self._assert(pixel_x_size > 0, 51,
+                         "Invalid pixel_x_size = %f for table %s" %
+                         (pixel_x_size, table_name))
+            self._assert(pixel_y_size > 0, 52,
+                         "Invalid pixel_y_size = %f for table %s" %
+                         (pixel_y_size, table_name))
+
+        c.execute("SELECT table_name, data_type FROM gpkg_contents WHERE "
+                  "data_type IN ('tiles', '2d-gridded-coverage')")
+        rows = c.fetchall()
+        for (table_name, data_type) in rows:
+            self._check_tile_user_table(c, table_name, data_type)
+
+    def _check_tiled_gridded_elevation_data(self, c):
+
+        self._log('Checking tiled gridded elevation data')
+
+        c.execute("SELECT table_name FROM gpkg_contents WHERE "
+                  "data_type = '2d-gridded-coverage'")
+        tables = c.fetchall()
+        if len(tables) == 0:
+            self._log('... No tiled gridded coverage table')
+            return
+        tables = [tables[i][0] for i in range(len(tables))]
+
+        c.execute("SELECT 1 FROM sqlite_master WHERE "
+                  "name = 'gpkg_2d_gridded_coverage_ancillary'")
+        self._assert(c.fetchone() is not None, 120,
+                     'gpkg_2d_gridded_coverage_ancillary table is missing')
+
+        c.execute("PRAGMA table_info(gpkg_2d_gridded_coverage_ancillary)")
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'id', 'INTEGER', 0, None, 1),
+            (1, 'tile_matrix_set_name', 'TEXT', 1, None, 0),
+            (2, 'datatype', 'TEXT', 1, "'integer'", 0),
+            (3, 'scale', 'REAL', 1, '1.0', 0),
+            (4, 'offset', 'REAL', 1, '0.0', 0),
+            (5, 'precision', 'REAL', 0, '1.0', 0),
+            (6, 'data_null', 'REAL', 0, None, 0)
+        ]
+        self._check_structure(columns, expected_columns, 120,
+                              'gpkg_2d_gridded_coverage_ancillary')
+
+        c.execute("SELECT 1 FROM sqlite_master WHERE "
+                  "name = 'gpkg_2d_gridded_tile_ancillary'")
+        self._assert(c.fetchone() is not None, 121,
+                     'gpkg_2d_gridded_tile_ancillary table is missing')
+
+        c.execute("PRAGMA table_info(gpkg_2d_gridded_tile_ancillary)")
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'id', 'INTEGER', 0, None, 1),
+            (1, 'tpudt_name', 'TEXT', 1, None, 0),
+            (2, 'tpudt_id', 'INTEGER', 1, None, 0),
+            (3, 'scale', 'REAL', 1, '1.0', 0),
+            (4, 'offset', 'REAL', 1, '0.0', 0),
+            (5, 'min', 'REAL', 0, 'NULL', 0),
+            (6, 'max', 'REAL', 0, 'NULL', 0),
+            (7, 'mean', 'REAL', 0, 'NULL', 0),
+            (8, 'std_dev', 'REAL', 0, 'NULL', 0)
+        ]
+
+        self._check_structure(columns, expected_columns, 121,
+                              'gpkg_2d_gridded_tile_ancillary')
+
+        c.execute("SELECT srs_id, organization, organization_coordsys_id, "
+                  "definition FROM gpkg_spatial_ref_sys "
+                  "WHERE srs_id = 4979")
+        ret = c.fetchall()
+        self._assert(len(ret) == 1, 122,
+                     "gpkg_spatial_ref_sys shall have a row for srs_id=4979")
+        self._assert(ret[0][1].lower() == 'epsg', 122,
+                     'wrong value for organization for srs_id = 4979: %s' %
+                     ret[0][1])
+        self._assert(ret[0][2] == 4979, 122,
+                     ('wrong value for organization_coordsys_id for ' +
+                      'srs_id = 4979: %s') % ret[0][2])
+
+        c.execute("SELECT 1 FROM sqlite_master WHERE name = 'gpkg_extensions'")
+        self._assert(c.fetchone() is not None, 125,
+                     'gpkg_extensions does not exist')
+        c.execute("SELECT table_name, column_name, definition, scope FROM "
+                  "gpkg_extensions WHERE "
+                  "extension_name = 'gpkg_elevation_tiles'")
+        rows = c.fetchall()
+        self._assert(len(rows) == 2 + len(tables), 125,
+                     "Wrong number of entries in gpkg_elevation_tiles with"
+                     "gpkg_elevation_tiles extension name")
+        found_gpkg_2d_gridded_coverage_ancillary = False
+        found_gpkg_2d_gridded_tile_ancillary = False
+        expected_def = \
+            'http://www.geopackage.org/spec/' \
+            '#extension_tiled_gridded_elevation_data'
+        for (table_name, column_name, definition, scope) in rows:
+            if table_name == 'gpkg_2d_gridded_coverage_ancillary':
+                found_gpkg_2d_gridded_coverage_ancillary = True
+                self._assert(column_name is None, 125,
+                             "Wrong entry for "
+                             "gpkg_2d_gridded_coverage_ancillary "
+                             "in gpkg_extensions")
+                self._assert(definition == expected_def, 125,
+                             "Wrong entry for "
+                             "gpkg_2d_gridded_coverage_ancillary "
+                             "in gpkg_extensions")
+                self._assert(scope == 'read-write', 125,
+                             "Wrong entry for "
+                             "gpkg_2d_gridded_coverage_ancillary "
+                             "in gpkg_extensions")
+            elif table_name == 'gpkg_2d_gridded_tile_ancillary':
+                found_gpkg_2d_gridded_tile_ancillary = True
+                self._assert(column_name is None, 125,
+                             "Wrong entry for "
+                             "gpkg_2d_gridded_tile_ancillary "
+                             "in gpkg_extensions")
+                self._assert(definition == expected_def, 125,
+                             "Wrong entry for "
+                             "gpkg_2d_gridded_tile_ancillary "
+                             "in gpkg_extensions")
+                self._assert(scope == 'read-write', 125,
+                             "Wrong entry for "
+                             "gpkg_2d_gridded_tile_ancillary "
+                             "in gpkg_extensions")
+            else:
+                self._assert(table_name in tables, 125,
+                             "Unexpected table_name registered for " +
+                             "gpkg_elevation_tiles: %s" % table_name)
+                self._assert(column_name == 'tile_data', 125,
+                             "Wrong entry for %s " % table_name +
+                             "in gpkg_extensions")
+                self._assert(definition == expected_def, 125,
+                             "Wrong entry for %s " % table_name +
+                             "in gpkg_extensions")
+                self._assert(scope == 'read-write', 125,
+                             "Wrong entry for %s " % table_name +
+                             "in gpkg_extensions")
+
+        self._assert(found_gpkg_2d_gridded_coverage_ancillary, 125,
+                     "gpkg_2d_gridded_coverage_ancillary not registered "
+                     "for gpkg_elevation_tiles")
+        self._assert(found_gpkg_2d_gridded_tile_ancillary, 125,
+                     "gpkg_2d_gridded_tile_ancillary not registered "
+                     "for gpkg_elevation_tiles")
+
+        c.execute("SELECT tile_matrix_set_name, datatype FROM "
+                  "gpkg_2d_gridded_coverage_ancillary")
+        rows = c.fetchall()
+        self._assert(len(rows) == len(tables), 126,
+                     "Wrong number of entries in "
+                     "gpkg_2d_gridded_coverage_ancillary")
+        for (tile_matrix_set_name, datatype) in rows:
+            self._assert(tile_matrix_set_name in tables, 126,
+                         "Table %s has a row in " % tile_matrix_set_name +
+                         "gpkg_2d_gridded_coverage_ancillary, but not in "
+                         "gpkg_contents")
+            c.execute('SELECT 1 FROM gpkg_tile_matrix_set WHERE '
+                      'table_name = ?', (tile_matrix_set_name,))
+            self._assert(c.fetchone() is not None, 127,
+                         'missing entry in gpkg_tile_matrix_set ' +
+                         'for %s' % tile_matrix_set_name)
+            self._assert(datatype in ('integer', 'float'), 128,
+                         'Unexpected datatype = %s' % datatype)
+
+        for table in tables:
+            c.execute("SELECT COUNT(*) FROM %s" % _esc_id(table))
+            count_tpudt = c.fetchone()
+            c.execute("SELECT COUNT(*) FROM gpkg_2d_gridded_tile_ancillary "
+                      "WHERE tpudt_name = ?", (table, ))
+            count_tile_ancillary = c.fetchone()
+            self._assert(count_tpudt == count_tile_ancillary, 129,
+                         ("Inconsistent number of rows in " +
+                          "gpkg_2d_gridded_tile_ancillary for %s") % table)
+
+        c.execute("SELECT DISTINCT tpudt_name FROM "
+                  "gpkg_2d_gridded_tile_ancillary")
+        rows = c.fetchall()
+        for (tpudt_name, ) in rows:
+            self._assert(tpudt_name in tables, 130,
+                         "tpudt_name = %s is invalid" % tpudt_name)
+
+        c.execute("SELECT tile_matrix_set_name FROM "
+                  "gpkg_2d_gridded_coverage_ancillary WHERE "
+                  "datatype = 'float'")
+        rows = c.fetchall()
+        for (tile_matrix_set_name, ) in rows:
+            c.execute("SELECT 1 FROM gpkg_2d_gridded_tile_ancillary WHERE "
+                      "tpudt_name = ? AND "
+                      "NOT (offset == 0.0 AND scale == 1.0)",
+                      (tile_matrix_set_name,))
+            self._assert(len(c.fetchall()) == 0, 130,
+                         "Wrong scale and offset values " +
+                         "for %s " % tile_matrix_set_name +
+                         "in gpkg_2d_gridded_coverage_ancillary")
+
+        for table in tables:
+            c.execute("SELECT 1 FROM gpkg_2d_gridded_tile_ancillary WHERE " +
+                      "tpudt_name = ? AND tpudt_id NOT IN (SELECT id FROM " +
+                      "%s)" % table, (table,))
+            self._assert(len(c.fetchall()) == 0, 131,
+                         "tpudt_id in gpkg_2d_gridded_coverage_ancillary " +
+                         "not referencing an id from %s" % table)
+
+        c.execute("SELECT tile_matrix_set_name, datatype FROM "
+                  "gpkg_2d_gridded_coverage_ancillary")
+        rows = c.fetchall()
+        warn_gdal_not_available = False
+        for (table_name, datatype) in rows:
+            c.execute("SELECT id, tile_data FROM %s" % _esc_id(table_name))
+            for (id, blob) in c.fetchall():
+                self._assert(blob is not None and len(blob) >= 12, 19,
+                             'Invalid blob')
+                max_size_needed = 12
+                blob_ar = struct.unpack('B' * max_size_needed,
+                                        blob[0:max_size_needed])
+                is_png = blob_ar[0:4] == (0x89, 0x50, 0x4E, 0x47)
+                is_tiff = blob_ar[0:4] == (0x49, 0x49, 0x2A, 0x00) or \
+                    blob_ar[0:4] == (0x4D, 0x4D, 0x00, 0x2A)
+                if datatype == 'integer':
+                    self._assert(is_png, 132,
+                                 'Tile for %s should be PNG' % table_name)
+                    if has_gdal:
+                        tmp_file = '/vsimem/temp_validate_gpkg.tif'
+                        try:
+                            blob = bytes(blob)
+                        except:
+                            blob = str(blob)
+                        gdal.FileFromMemBuffer(tmp_file, blob)
+                        ds = gdal.Open(tmp_file)
+                        try:
+                            self._assert(ds is not None, 132,
+                                         'Invalid tile %d in %s' %
+                                         (id, table_name))
+                            self._assert(ds.RasterCount == 1, 132,
+                                         'Invalid tile %d in %s' %
+                                         (id, table_name))
+                            self._assert(ds.GetRasterBand(1).DataType ==
+                                         gdal.GDT_UInt16, 132,
+                                         'Invalid tile %d in %s' %
+                                         (id, table_name))
+                        finally:
+                            gdal.Unlink(tmp_file)
+                    else:
+                        if not warn_gdal_not_available:
+                            warn_gdal_not_available = True
+                            self._log('GDAL not available. Req 132 not tested')
+
+                elif datatype == 'float':
+                    self._assert(is_tiff, 133,
+                                 'Tile for %s should be TIFF' % table_name)
+                    if has_gdal:
+                        tmp_file = '/vsimem/temp_validate_gpkg.tif'
+                        try:
+                            blob = bytes(blob)
+                        except:
+                            blob = str(blob)
+                        gdal.FileFromMemBuffer(tmp_file, blob)
+                        ds = gdal.Open(tmp_file)
+                        try:
+                            self._assert(ds is not None, 134,
+                                         'Invalid tile %d in %s' %
+                                         (id, table_name))
+                            self._assert(ds.RasterCount == 1, 135,
+                                         'Invalid tile %d in %s' %
+                                         (id, table_name))
+                            self._assert(ds.GetRasterBand(1).DataType ==
+                                         gdal.GDT_Float32, 136,
+                                         'Invalid tile %d in %s' %
+                                         (id, table_name))
+                            compression = ds.GetMetadataItem('COMPRESSION',
+                                                             'IMAGE_STRUCTURE')
+                            self._assert(compression is None or
+                                         compression == 'LZW', 137,
+                                         'Invalid tile %d in %s' %
+                                         (id, table_name))
+                            ovr_count = ds.GetRasterBand(1).GetOverviewCount()
+                            self._assert(len(ds.GetSubDatasets()) == 0 and
+                                         ovr_count == 0, 138,
+                                         'Invalid tile %d in %s' %
+                                         (id, table_name))
+                            (blockxsize, _) = \
+                                ds.GetRasterBand(1).GetBlockSize()
+                            self._assert(blockxsize == ds.RasterXSize, 139,
+                                         'Invalid tile %d in %s' %
+                                         (id, table_name))
+                        finally:
+                            gdal.Unlink(tmp_file)
+                    else:
+                        if not warn_gdal_not_available:
+                            warn_gdal_not_available = True
+                            self._log('GDAL not available. '
+                                      'Req 134-139 not tested')
+
+    def _check_gpkg_extensions(self, c):
+
+        self._log('Checking gpkg_extensions')
+        c.execute("SELECT 1 FROM sqlite_master WHERE name = 'gpkg_extensions'")
+        if c.fetchone() is None:
+            self._log('... No extensions')
+            return
+
+        c.execute("PRAGMA table_info(gpkg_extensions)")
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'table_name', 'TEXT', 0, None, 0),
+            (1, 'column_name', 'TEXT', 0, None, 0),
+            (2, 'extension_name', 'TEXT', 1, None, 0),
+            (3, 'definition', 'TEXT', 1, None, 0),
+            (4, 'scope', 'TEXT', 1, None, 0)]
+        self._check_structure(columns, expected_columns, 58,
+                              'gpkg_extensions')
+
+        c.execute("SELECT table_name, column_name FROM gpkg_extensions WHERE "
+                  "table_name IS NOT NULL")
+        rows = c.fetchall()
+        for (table_name, column_name) in rows:
+
+            # Doesn't work for gpkg_2d_gridded_coverage_ancillary
+            # c.execute("SELECT 1 FROM gpkg_contents WHERE table_name = ?", \
+            #          (table_name,) )
+            # ret = c.fetchall()
+            # self._assert(len(ret) == 1, \
+            #    60, ('table_name = %s is registered in ' +\
+            #    'gpkg_extensions, but not in gpkg_contents') % table_name)
+
+            if column_name is not None:
+                try:
+                    c.execute('SELECT %s FROM %s' %
+                              (_esc_id(column_name), _esc_id(table_name)))
+                    c.fetchone()
+                except:
+                    self._assert(False, 61,
+                                 ("Column %s of table %s mentioned in " +
+                                  "gpkg_extensions doesn't exist") %
+                                 (column_name, table_name))
+
+        c.execute("SELECT extension_name FROM gpkg_extensions "
+                  "WHERE extension_name NOT LIKE 'gpkg_%'")
+        rows = c.fetchall()
+        for (extension_name,) in rows:
+            self._assert(False, 63,
+                         "extension_name %s not valid" % extension_name)
+
+        c.execute("SELECT extension_name, scope FROM gpkg_extensions "
+                  "WHERE scope NOT IN ('read-write', 'write-only')")
+        rows = c.fetchall()
+        for (extension_name, scope) in rows:
+            self._assert(False, 64,
+                         "extension_name %s has invalid scope %s" %
+                         (extension_name, scope))
+
+        c.execute("SELECT table_name, scope FROM gpkg_extensions "
+                  "WHERE extension_name = 'gpkg_rtree_index' ")
+        rows = c.fetchall()
+        for (table_name, scope) in rows:
+            c.execute("SELECT 1 FROM gpkg_contents WHERE table_name = ? "
+                      "AND data_type = 'features'", (table_name,))
+            self._assert(c.fetchone() is not None, 75,
+                         ('gpkg_extensions declares gpkg_rtree_index for %s,' +
+                          ' but this is not a features table') % table_name)
+
+            self._assert(scope == 'write-only', 75,
+                         'Invalid scope %s for gpkg_rtree_index' % scope)
+
+    def _check_metadata(self, c):
+
+        self._log('Checking gpkg_metadata')
+
+        must_have_gpkg_metadata = False
+        c.execute("SELECT 1 FROM sqlite_master WHERE name = 'gpkg_extensions'")
+        if c.fetchone() is not None:
+            c.execute("SELECT scope FROM gpkg_extensions WHERE "
+                      "extension_name = 'gpkg_metadata'")
+            row = c.fetchone()
+            if row is not None:
+                must_have_gpkg_metadata = True
+                (scope, ) = row
+                self._assert(scope == 'read-write', 140,
+                             "Wrong scope for gpkg_metadata in "
+                             "gpkg_extensions")
+
+        c.execute("SELECT 1 FROM sqlite_master WHERE name = 'gpkg_metadata'")
+        if c.fetchone() is None:
+            if must_have_gpkg_metadata:
+                self._assert(False, 140, "gpkg_metadata table missing")
+            else:
+                self._log('... No metadata')
+            return
+
+        c.execute("PRAGMA table_info(gpkg_metadata)")
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'id', 'INTEGER', 1, None, 1),
+            (1, 'md_scope', 'TEXT', 1, "'dataset'", 0),
+            (2, 'md_standard_uri', 'TEXT', 1, None, 0),
+            (3, 'mime_type', 'TEXT', 1, "'text/xml'", 0),
+            (4, 'metadata', 'TEXT', 1, "''", 0)
+        ]
+        self._check_structure(columns, expected_columns, 93,
+                              'gpkg_metadata')
+
+        c.execute("SELECT 1 FROM sqlite_master "
+                  "WHERE name = 'gpkg_metadata_reference'")
+        self._assert(c.fetchone() is not None, 95,
+                     "gpkg_metadata_reference is missing")
+
+        c.execute("PRAGMA table_info(gpkg_metadata_reference)")
+        columns = c.fetchall()
+        expected_columns = [
+            (0, 'reference_scope', 'TEXT', 1, None, 0),
+            (1, 'table_name', 'TEXT', 0, None, 0),
+            (2, 'column_name', 'TEXT', 0, None, 0),
+            (3, 'row_id_value', 'INTEGER', 0, None, 0),
+            (4, 'timestamp', 'DATETIME', 1,
+             "strftime('%Y-%m-%dT%H:%M:%fZ','now')", 0),
+            (5, 'md_file_id', 'INTEGER', 1, None, 0),
+            (6, 'md_parent_id', 'INTEGER', 0, None, 0)
+        ]
+        self._check_structure(columns, expected_columns, 95,
+                              'gpkg_metadata_reference')
+
+        c.execute("SELECT DISTINCT md_scope FROM gpkg_metadata WHERE "
+                  "md_scope NOT IN ('undefined', 'fieldSession', "
+                  "'collectionSession', 'series', 'dataset', 'featureType', "
+                  "'feature', 'attributeType', 'attribute', 'tile', "
+                  "'model', 'catalog', 'schema', 'taxonomy', 'software', "
+                  "'service', 'collectionHardware', 'nonGeographicDataset', "
+                  "'dimensionGroup')")
+        rows = c.fetchall()
+        for (md_scope, ) in rows:
+            self._assert(False, 94, 'Invalid md_scope %s found' % md_scope)
+
+        c.execute("SELECT DISTINCT reference_scope FROM "
+                  "gpkg_metadata_reference WHERE "
+                  "reference_scope NOT IN ('geopackage', 'table', "
+                  "'column', 'row', 'row/col')")
+        rows = c.fetchall()
+        for (md_scope, ) in rows:
+            self._assert(False, 96,
+                         'Invalid reference_scope %s found' % md_scope)
+
+        c.execute("SELECT table_name FROM "
+                  "gpkg_metadata_reference WHERE "
+                  "reference_scope = 'geopackage' AND table_name is NOT NULL")
+        rows = c.fetchall()
+        for (table_name, ) in rows:
+            self._assert(False, 97,
+                         "row in gpkg_metadata_reference with table_name " +
+                         "not null (%s)" % table_name +
+                         "but reference_scope = geopackage")
+
+        c.execute("SELECT table_name FROM "
+                  "gpkg_metadata_reference WHERE "
+                  "reference_scope != 'geopackage'")
+        rows = c.fetchall()
+        for (table_name, ) in rows:
+            self._assert(table_name is not None, 97,
+                         "row in gpkg_metadata_reference with null table_name")
+            c.execute("SELECT 1 FROM gpkg_contents WHERE table_name = ?",
+                      (table_name,))
+            self._assert(c.fetchone() is not None, 97,
+                         "row in gpkg_metadata_reference with table_name " +
+                         "not null (%s) with no reference in " % table_name +
+                         "gpkg_contents but reference_scope != geopackage")
+
+        c.execute("SELECT table_name FROM "
+                  "gpkg_metadata_reference WHERE "
+                  "reference_scope IN ('geopackage', 'table', 'row') "
+                  "AND column_name is NOT NULL")
+        rows = c.fetchall()
+        for (table_name, ) in rows:
+            self._assert(False, 98,
+                         "row in gpkg_metadata_reference with column_name " +
+                         "not null (table=%s)" % table_name +
+                         "but reference_scope = geopackage, table or row")
+
+        c.execute("SELECT table_name, column_name FROM "
+                  "gpkg_metadata_reference WHERE "
+                  "reference_scope NOT IN ('geopackage', 'table', 'row')")
+        rows = c.fetchall()
+        for (table_name, column_name) in rows:
+            self._assert(column_name is not None, 98,
+                         "row in gpkg_metadata_reference with null "
+                         "column_name")
+            try:
+                c.execute("SELECT %s FROM %s" %
+                          (_esc_id(column_name), _esc_id(table_name)))
+            except:
+                self._assert(False, 98,
+                             "column %s of %s does not exist" %
+                             (column_name, table_name))
+
+        c.execute("SELECT table_name FROM "
+                  "gpkg_metadata_reference WHERE "
+                  "reference_scope IN ('geopackage', 'table', 'column') "
+                  "AND row_id_value is NOT NULL")
+        rows = c.fetchall()
+        for (table_name, ) in rows:
+            self._assert(False, 99,
+                         "row in gpkg_metadata_reference with row_id_value " +
+                         "not null (table=%s)" % table_name +
+                         "but reference_scope = geopackage, table or column")
+
+        c.execute("SELECT table_name, row_id_value FROM "
+                  "gpkg_metadata_reference WHERE "
+                  "reference_scope NOT IN ('geopackage', 'table', 'column')")
+        rows = c.fetchall()
+        for (table_name, row_id_value) in rows:
+            self._assert(row_id_value is not None, 99,
+                         "row in gpkg_metadata_reference with null "
+                         "row_id_value")
+            c.execute("SELECT 1 FROM %s WHERE ROWID = ?" %
+                      _esc_id(column_name), (row_id_value, ))
+            self._assert(c.fetchone() is not None, 99,
+                         "row %s of %s does not exist" %
+                         (str(row_id_value), table_name))
+
+        c.execute("SELECT timestamp FROM gpkg_metadata_reference")
+        rows = c.fetchall()
+        for (timestamp, ) in rows:
+            try:
+                datetime.datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%fZ')
+            except:
+                self._assert(False, 100,
+                             ('timestamp = %s in gpkg_metadata_reference' +
+                              'is invalid datetime') % (timestamp))
+
+        c.execute("SELECT md_file_id FROM gpkg_metadata_reference")
+        rows = c.fetchall()
+        for (md_file_id, ) in rows:
+            c.execute("SELECT 1 FROM gpkg_metadata WHERE id = ?",
+                      (md_file_id,))
+            self._assert(c.fetchone() is not None, 101,
+                         "md_file_id = %s " % str(md_file_id) +
+                         "does not have a row in gpkg_metadata")
+
+        c.execute("SELECT md_parent_id FROM gpkg_metadata_reference "
+                  "WHERE md_parent_id IS NOT NULL")
+        rows = c.fetchall()
+        for (md_parent_id, ) in rows:
+            c.execute("SELECT 1 FROM gpkg_metadata WHERE id = ?",
+                      (md_parent_id,))
+            self._assert(c.fetchone() is not None, 102,
+                         "md_parent_id = %s " % str(md_parent_id) +
+                         "does not have a row in gpkg_metadata")
+
+        c.execute("SELECT md_file_id FROM "
+                  "gpkg_metadata_reference WHERE md_parent_id IS NOT NULL "
+                  "AND md_file_id = md_parent_id")
+        rows = c.fetchall()
+        for (md_file_id, ) in rows:
+            self._assert(False, 102,
+                         "Row with md_file_id = md_parent_id = %s " %
+                         str(md_file_id))
+
+    def check(self):
+        self._assert(os.path.exists(self.filename), None,
+                     "%s does not exist" % self.filename)
+
+        self._assert(self.filename.lower().endswith('.gpkg'), 3,
+                     "filename extension isn't .gpkg'")
+
+        with open(self.filename, 'rb') as f:
+            f.seek(68, 0)
+            application_id = struct.unpack('B' * 4, f.read(4))
+            gp10 = struct.unpack('B' * 4, 'GP10'.encode('ASCII'))
+            gp11 = struct.unpack('B' * 4, 'GP11'.encode('ASCII'))
+            gpkg = struct.unpack('B' * 4, 'GPKG'.encode('ASCII'))
+            self._assert(application_id in (gp10, gp11, gpkg), 2,
+                         ("Wrong application_id: %s. " +
+                          "Expected one of GP10, GP11, GPKG") %
+                         str(application_id))
+
+            if application_id == gpkg:
+                f.seek(60, 0)
+                user_version = f.read(4)
+                expected_version = 10200
+                user_version = struct.unpack('>I', user_version)[0]
+                self._assert(user_version >= expected_version, 2,
+                             'Wrong user_version: %d. Expected >= %d' %
+                             (user_version, expected_version))
+
+        conn = sqlite3.connect(':memory:')
+        c = conn.cursor()
+        c.execute('CREATE TABLE foo(one TEXT, two TEXT, '
+                  'CONSTRAINT pk PRIMARY KEY (one, two))')
+        c.execute('PRAGMA table_info(foo)')
+        rows = c.fetchall()
+        if rows[1][5] == 2:
+            self.extended_pragma_info = True
+        c.close()
+        conn.close()
+
+        conn = sqlite3.connect(self.filename)
+        c = conn.cursor()
+        try:
+            try:
+                c.execute('SELECT 1 FROM sqlite_master')
+                c.fetchone()
+            except:
+                self._assert(False, 1, 'not a sqlite3 database')
+
+            c.execute('PRAGMA foreign_key_check')
+            ret = c.fetchall()
+            self._assert(len(ret) == 0, 7,
+                         'foreign_key_check failed: %s' % str(ret))
+
+            c.execute('PRAGMA integrity_check')
+            self._assert(c.fetchone()[0] == 'ok', 6, 'integrity_check failed')
+
+            self._check_gpkg_spatial_ref_sys(c)
+
+            self._check_gpkg_contents(c)
+
+            self._check_features(c)
+
+            self._check_tiles(c)
+
+            self._check_attributes(c)
+
+            self._check_tiled_gridded_elevation_data(c)
+
+            self._check_gpkg_extensions(c)
+
+            self._check_metadata(c)
+
+            # TODO: check gpkg_schema
+        finally:
+            c.close()
+            conn.close()
+
+
+def check(filename, abort_at_first_error=True, verbose=False):
+
+    checker = GPKGChecker(filename,
+                          abort_at_first_error=abort_at_first_error,
+                          verbose=verbose)
+    checker.check()
+    return checker.errors
+
+
+def Usage():
+    print('validate_gpkg.py [[-v]|[-q]] [-k] my.gpkg')
+    print('')
+    print('-q: quiet mode')
+    print('-k: (try to) keep going when error is encountered')
+    sys.exit(1)
+
+
+if __name__ == '__main__':
+
+    filename = None
+    verbose = False
+    abort_at_first_error = True
+    if len(sys.argv) == 1:
+        Usage()
+    for arg in sys.argv[1:]:
+        if arg == '-k':
+            abort_at_first_error = False
+        elif arg == '-q':
+            verbose = False
+        elif arg == '-v':
+            verbose = True
+        elif arg[0] == '-':
+            Usage()
+        else:
+            filename = arg
+    if filename is None:
+        Usage()
+    ret = check(filename, abort_at_first_error=abort_at_first_error,
+                verbose=verbose)
+    if not abort_at_first_error:
+        if len(ret) == 0:
+            sys.exit(0)
+        else:
+            for (req, msg) in ret:
+                if req:
+                    print('Req %d: %s' % (req, msg))
+                else:
+                    print(msg)
+            sys.exit(1)
diff --git a/swig/python/samples/validate_jp2.py b/swig/python/samples/validate_jp2.py
index 7198bb6..024f1c0 100644
--- a/swig/python/samples/validate_jp2.py
+++ b/swig/python/samples/validate_jp2.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: validate_jp2.py 31957 2015-12-02 12:44:54Z goatbar $
+#  $Id: validate_jp2.py 36293 2016-11-19 14:05:15Z rouault $
 #
 #  Project:  GDAL
 #  Purpose:  Validate JPEG2000 file structure
@@ -377,7 +377,7 @@ def check_oi_rg_consistency(filename, serialized_oi_rg, error_report):
         if proj4 != oi_proj4:
             error_report.EmitError('INSPIRE_TG', 'Inconsistent SRS between OrthoImagery (wkt=%s, proj4=%s) and GMLJP2/GeoJP2 (wkt=%s, proj4=%s)' % (wkt, proj4, oi_wkt, oi_proj4), conformance_class = 'A.8.8')
 
-def validate(filename, oidoc, inspire_tg, expected_gmljp2, ogc_schemas_location, datatype = 'imagery', error_report = None):
+def validate(filename, oidoc, inspire_tg, expected_gmljp2, ogc_schemas_location, datatype = 'imagery', error_report = None, expected_ftyp_branding = None):
 
     if error_report is None:
         error_report = ErrorReport()
@@ -459,8 +459,15 @@ def validate(filename, oidoc, inspire_tg, expected_gmljp2, ogc_schemas_location,
         if ftyp:
             JP2CLFound = False
             JPXCLFound = False
-            if get_field_val(ftyp, 'BR') != 'jp2 ':
-                error_report.EmitError('GENERAL', 'ftyp.BR = "%s" instead of "jp2 "' % get_field_val(ftyp, 'BR'))
+
+            if expected_ftyp_branding is None:
+                if gmljp2_found and gmljp2.find('gmljp2:GMLJP2CoverageCollection') >= 0:
+                    expected_ftyp_branding = 'jpx '
+                else:
+                    expected_ftyp_branding = 'jp2 '
+
+            if get_field_val(ftyp, 'BR') != expected_ftyp_branding:
+                error_report.EmitError('GENERAL', 'ftyp.BR = "%s" instead of "%s"' % (get_field_val(ftyp, 'BR'), expected_ftyp_branding))
 
             if get_field_val(ftyp, 'MinV') != '0':
                 error_report.EmitError('GENERAL', 'ftyp.MinV = "%s" instead of 0' % get_field_val(ftyp, 'MinV'))
diff --git a/swig/python/scripts/gdal2tiles.py b/swig/python/scripts/gdal2tiles.py
index 2e0cfe9..5c67ad6 100755
--- a/swig/python/scripts/gdal2tiles.py
+++ b/swig/python/scripts/gdal2tiles.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-#******************************************************************************
-#  $Id: gdal2tiles.py 33790 2016-03-26 12:42:12Z goatbar $
+# ******************************************************************************
+#  $Id: gdal2tiles.py 37426 2017-02-19 21:47:49Z rouault $
 #
 # Project:  Google Summer of Code 2007, 2008 (http://code.google.com/soc/)
 # Support:  BRGM (http://www.brgm.fr)
@@ -35,7 +35,7 @@
 #  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 #  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 #  DEALINGS IN THE SOFTWARE.
-#******************************************************************************
+# ******************************************************************************
 
 import math
 import os
@@ -48,15 +48,15 @@ try:
     from PIL import Image
     import numpy
     import osgeo.gdal_array as gdalarray
-except:
+except Exception:
     # 'antialias' resampling is not available
     pass
 
-__version__ = "$Id: gdal2tiles.py 33790 2016-03-26 12:42:12Z goatbar $"
+__version__ = "$Id: gdal2tiles.py 37426 2017-02-19 21:47:49Z rouault $"
 
-resampling_list = ('average','near','bilinear','cubic','cubicspline','lanczos','antialias')
-profile_list = ('mercator','geodetic','raster') #,'zoomify')
-webviewer_list = ('all','google','openlayers','leaflet','none')
+resampling_list = ('average', 'near', 'bilinear', 'cubic', 'cubicspline', 'lanczos',  'antialias')
+profile_list = ('mercator', 'geodetic', 'raster')
+webviewer_list = ('all', 'google', 'openlayers', 'leaflet', 'none')
 
 # =============================================================================
 # =============================================================================
@@ -96,17 +96,18 @@ Class is available under the open-source GDAL license (www.gdal.org).
 
 MAXZOOMLEVEL = 32
 
+
 class GlobalMercator(object):
-    """
+    r"""
     TMS Global Mercator Profile
     ---------------------------
 
-  Functions necessary for generation of tiles in Spherical Mercator projection,
-  EPSG:3857.
+    Functions necessary for generation of tiles in Spherical Mercator projection,
+    EPSG:3857.
 
-  Such tiles are compatible with Google Maps, Bing Maps, Yahoo Maps,
-  UK Ordnance Survey OpenSpace API, ...
-  and you can overlay them on top of base maps of those web mapping applications.
+    Such tiles are compatible with Google Maps, Bing Maps, Yahoo Maps,
+    UK Ordnance Survey OpenSpace API, ...
+    and you can overlay them on top of base maps of those web mapping applications.
 
     Pixel and tile coordinates are in TMS notation (origin [0,0] in bottom-left).
 
@@ -203,28 +204,28 @@ class GlobalMercator(object):
         self.originShift = 2 * math.pi * 6378137 / 2.0
         # 20037508.342789244
 
-    def LatLonToMeters(self, lat, lon ):
+    def LatLonToMeters(self, lat, lon):
         "Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator EPSG:3857"
 
         mx = lon * self.originShift / 180.0
-        my = math.log( math.tan((90 + lat) * math.pi / 360.0 )) / (math.pi / 180.0)
+        my = math.log(math.tan((90 + lat) * math.pi / 360.0)) / (math.pi / 180.0)
 
         my = my * self.originShift / 180.0
         return mx, my
 
-    def MetersToLatLon(self, mx, my ):
+    def MetersToLatLon(self, mx, my):
         "Converts XY point from Spherical Mercator EPSG:3857 to lat/lon in WGS84 Datum"
 
         lon = (mx / self.originShift) * 180.0
         lat = (my / self.originShift) * 180.0
 
-        lat = 180 / math.pi * (2 * math.atan( math.exp( lat * math.pi / 180.0)) - math.pi / 2.0)
+        lat = 180 / math.pi * (2 * math.atan(math.exp(lat * math.pi / 180.0)) - math.pi / 2.0)
         return lat, lon
 
     def PixelsToMeters(self, px, py, zoom):
         "Converts pixel coordinates in given zoom level of pyramid to EPSG:3857"
 
-        res = self.Resolution( zoom )
+        res = self.Resolution(zoom)
         mx = px * res - self.originShift
         my = py * res - self.originShift
         return mx, my
@@ -232,7 +233,7 @@ class GlobalMercator(object):
     def MetersToPixels(self, mx, my, zoom):
         "Converts EPSG:3857 to pyramid pixel coordinates in given zoom level"
 
-        res = self.Resolution( zoom )
+        res = self.Resolution(zoom)
         px = (mx + self.originShift) / res
         py = (my + self.originShift) / res
         return px, py
@@ -240,8 +241,8 @@ class GlobalMercator(object):
     def PixelsToTile(self, px, py):
         "Returns a tile covering region in given pixel coordinates"
 
-        tx = int( math.ceil( px / float(self.tileSize) ) - 1 )
-        ty = int( math.ceil( py / float(self.tileSize) ) - 1 )
+        tx = int(math.ceil(px / float(self.tileSize)) - 1)
+        ty = int(math.ceil(py / float(self.tileSize)) - 1)
         return tx, ty
 
     def PixelsToRaster(self, px, py, zoom):
@@ -253,40 +254,40 @@ class GlobalMercator(object):
     def MetersToTile(self, mx, my, zoom):
         "Returns tile for given mercator coordinates"
 
-        px, py = self.MetersToPixels( mx, my, zoom)
-        return self.PixelsToTile( px, py)
+        px, py = self.MetersToPixels(mx, my, zoom)
+        return self.PixelsToTile(px, py)
 
     def TileBounds(self, tx, ty, zoom):
         "Returns bounds of the given tile in EPSG:3857 coordinates"
 
-        minx, miny = self.PixelsToMeters( tx*self.tileSize, ty*self.tileSize, zoom )
-        maxx, maxy = self.PixelsToMeters( (tx+1)*self.tileSize, (ty+1)*self.tileSize, zoom )
-        return ( minx, miny, maxx, maxy )
+        minx, miny = self.PixelsToMeters(tx*self.tileSize, ty*self.tileSize, zoom)
+        maxx, maxy = self.PixelsToMeters((tx+1)*self.tileSize, (ty+1)*self.tileSize, zoom)
+        return (minx, miny, maxx, maxy)
 
-    def TileLatLonBounds(self, tx, ty, zoom ):
+    def TileLatLonBounds(self, tx, ty, zoom):
         "Returns bounds of the given tile in latitude/longitude using WGS84 datum"
 
-        bounds = self.TileBounds( tx, ty, zoom)
+        bounds = self.TileBounds(tx, ty, zoom)
         minLat, minLon = self.MetersToLatLon(bounds[0], bounds[1])
         maxLat, maxLon = self.MetersToLatLon(bounds[2], bounds[3])
 
-        return ( minLat, minLon, maxLat, maxLon )
+        return (minLat, minLon, maxLat, maxLon)
 
-    def Resolution(self, zoom ):
+    def Resolution(self, zoom):
         "Resolution (meters/pixel) for given zoom level (measured at Equator)"
 
         # return (2 * math.pi * 6378137) / (self.tileSize * 2**zoom)
         return self.initialResolution / (2**zoom)
 
-    def ZoomForPixelSize(self, pixelSize ):
+    def ZoomForPixelSize(self, pixelSize):
         "Maximal scaledown zoom of the pyramid closest to the pixelSize."
 
         for i in range(MAXZOOMLEVEL):
             if pixelSize > self.Resolution(i):
-                if i!=0:
+                if i != -1:
                     return i-1
                 else:
-                    return 0 # We don't want to scale up
+                    return 0    # We don't want to scale up
 
     def GoogleTile(self, tx, ty, zoom):
         "Converts TMS tile coordinates to Google Tile coordinates"
@@ -294,7 +295,7 @@ class GlobalMercator(object):
         # coordinate origin is moved from bottom-left to top-left corner of the extent
         return tx, (2**zoom - 1) - ty
 
-    def QuadTree(self, tx, ty, zoom ):
+    def QuadTree(self, tx, ty, zoom):
         "Converts TMS tile coordinates to Microsoft QuadTree"
 
         quadKey = ""
@@ -310,10 +311,9 @@ class GlobalMercator(object):
 
         return quadKey
 
-#---------------------
 
 class GlobalGeodetic(object):
-    """
+    r"""
     TMS Global Geodetic Profile
     ---------------------------
 
@@ -347,11 +347,12 @@ class GlobalGeodetic(object):
        WMS, KML    Web Clients, Google Earth  TileMapService
     """
 
-    def __init__(self, tmscompatible, tileSize = 256):
+    def __init__(self, tmscompatible, tileSize=256):
         self.tileSize = tileSize
         if tmscompatible is not None:
             # Defaults the resolution factor to 0.703125 (2 tiles @ level 0)
-            # Adhers to OSGeo TMS spec http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic
+            # Adhers to OSGeo TMS spec
+            # http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification#global-geodetic
             self.resFact = 180.0 / self.tileSize
         else:
             # Defaults the resolution factor to 1.40625 (1 tile @ level 0)
@@ -369,31 +370,30 @@ class GlobalGeodetic(object):
     def PixelsToTile(self, px, py):
         "Returns coordinates of the tile covering region in pixel coordinates"
 
-        tx = int( math.ceil( px / float(self.tileSize) ) - 1 )
-        ty = int( math.ceil( py / float(self.tileSize) ) - 1 )
+        tx = int(math.ceil(px / float(self.tileSize)) - 1)
+        ty = int(math.ceil(py / float(self.tileSize)) - 1)
         return tx, ty
 
     def LonLatToTile(self, lon, lat, zoom):
         "Returns the tile for zoom which covers given lon/lat coordinates"
 
-        px, py = self.LonLatToPixels( lon, lat, zoom)
-        return self.PixelsToTile(px,py)
+        px, py = self.LonLatToPixels(lon, lat, zoom)
+        return self.PixelsToTile(px, py)
 
-    def Resolution(self, zoom ):
+    def Resolution(self, zoom):
         "Resolution (arc/pixel) for given zoom level (measured at Equator)"
 
         return self.resFact / 2**zoom
-        #return 180 / float( 1 << (8+zoom) )
 
-    def ZoomForPixelSize(self, pixelSize ):
+    def ZoomForPixelSize(self, pixelSize):
         "Maximal scaledown zoom of the pyramid closest to the pixelSize."
 
         for i in range(MAXZOOMLEVEL):
             if pixelSize > self.Resolution(i):
-                if i!=0:
+                if i != 0:
                     return i-1
                 else:
-                    return 0 # We don't want to scale up
+                    return 0    # We don't want to scale up
 
     def TileBounds(self, tx, ty, zoom):
         "Returns bounds of the given tile"
@@ -408,37 +408,36 @@ class GlobalGeodetic(object):
     def TileLatLonBounds(self, tx, ty, zoom):
         "Returns bounds of the given tile in the SWNE form"
         b = self.TileBounds(tx, ty, zoom)
-        return (b[1],b[0],b[3],b[2])
+        return (b[1], b[0], b[3], b[2])
+
 
-#---------------------
-# TODO: Finish Zoomify implementation.
 class Zoomify(object):
     """
     Tiles compatible with the Zoomify viewer
     ----------------------------------------
     """
 
-    def __init__(self, width, height, tilesize = 256, tileformat='jpg'):
+    def __init__(self, width, height, tilesize=256, tileformat='jpg'):
         """Initialization of the Zoomify tile tree"""
 
         self.tilesize = tilesize
         self.tileformat = tileformat
         imagesize = (width, height)
-        tiles = ( math.ceil( width / tilesize ), math.ceil( height / tilesize ) )
+        tiles = (math.ceil(width / tilesize), math.ceil(height / tilesize))
 
         # Size (in tiles) for each tier of pyramid.
         self.tierSizeInTiles = []
-        self.tierSizeInTiles.append( tiles )
+        self.tierSizeInTiles.append(tiles)
 
         # Image size in pixels for each pyramid tierself
         self.tierImageSize = []
-        self.tierImageSize.append( imagesize );
+        self.tierImageSize.append(imagesize)
 
-        while (imagesize[0] > tilesize or imagesize[1] > tilesize ):
-            imagesize = (math.floor( imagesize[0] / 2 ), math.floor( imagesize[1] / 2) )
-            tiles = ( math.ceil( imagesize[0] / tilesize ), math.ceil( imagesize[1] / tilesize ) )
-            self.tierSizeInTiles.append( tiles )
-            self.tierImageSize.append( imagesize )
+        while (imagesize[0] > tilesize or imagesize[1] > tilesize):
+            imagesize = (math.floor(imagesize[0] / 2), math.floor(imagesize[1] / 2))
+            tiles = (math.ceil(imagesize[0] / tilesize), math.ceil(imagesize[1] / tilesize))
+            self.tierSizeInTiles.append(tiles)
+            self.tierImageSize.append(imagesize)
 
         self.tierSizeInTiles.reverse()
         self.tierImageSize.reverse()
@@ -451,23 +450,24 @@ class Zoomify(object):
         self.tileCountUpToTier[0] = 0
         for i in range(1, self.numberOfTiers+1):
             self.tileCountUpToTier.append(
-                self.tierSizeInTiles[i-1][0] * self.tierSizeInTiles[i-1][1] + self.tileCountUpToTier[i-1]
+                self.tierSizeInTiles[i-1][0] * self.tierSizeInTiles[i-1][1] +
+                self.tileCountUpToTier[i-1]
             )
 
     def tilefilename(self, x, y, z):
         """Returns filename for tile with given coordinates"""
 
         tileIndex = x + y * self.tierSizeInTiles[z][0] + self.tileCountUpToTier[z]
-        return os.path.join("TileGroup%.0f" % math.floor( tileIndex / 256 ),
-            "%s-%s-%s.%s" % ( z, x, y, self.tileformat))
+        return os.path.join("TileGroup%.0f" % math.floor(tileIndex / 256),
+                            "%s-%s-%s.%s" % (z, x, y, self.tileformat))
+
+
+class Gdal2TilesError(Exception):
+    pass
 
-# =============================================================================
-# =============================================================================
-# =============================================================================
 
 class GDAL2Tiles(object):
 
-    # -------------------------------------------------------------------------
     def process(self):
         """The main processing function, runs all the main steps of processing"""
 
@@ -483,22 +483,17 @@ class GDAL2Tiles(object):
         # Generation of the overview tiles (higher in the pyramid)
         self.generate_overview_tiles()
 
-    # -------------------------------------------------------------------------
-    def error(self, msg, details = "" ):
+    def error(self, msg, details=""):
         """Print an error message and stop the processing"""
-
         if details:
             self.parser.error(msg + "\n\n" + details)
         else:
             self.parser.error(msg)
 
-    # -------------------------------------------------------------------------
-    def progressbar(self, complete = 0.0):
+    def progressbar(self, complete=0.0):
         """Print progressbar for float value 0..1"""
-
         gdal.TermProgress_nocb(complete)
 
-    # -------------------------------------------------------------------------
     def gettempfilename(self, suffix):
         """Returns a temporary filename"""
         if '_' in os.environ:
@@ -510,20 +505,37 @@ class GDAL2Tiles(object):
                 import time
                 import random
                 random.seed(time.time())
-                random_part = 'file%d' % random.randint(0,1000000000)
+                random_part = 'file%d' % random.randint(0, 1000000000)
                 return os.path.join(tmpdir, random_part + suffix)
 
         import tempfile
         return tempfile.mktemp(suffix)
 
-    # -------------------------------------------------------------------------
     def stop(self):
         """Stop the rendering immediately"""
         self.stopped = True
 
-    # -------------------------------------------------------------------------
-    def __init__(self, arguments ):
+    def __init__(self, arguments):
         """Constructor function - initialization"""
+        self.out_drv = None
+        self.mem_drv = None
+        self.in_ds = None
+        self.out_ds = None
+        self.out_srs = None
+        self.nativezoom = None
+        self.tminmax = None
+        self.tsize = None
+        self.mercator = None
+        self.geodetic = None
+        self.alphaband = None
+        self.dataBandsCount = None
+        self.out_gt = None
+        self.tileswne = None
+        self.swne = None
+        self.ominx = None
+        self.omaxx = None
+        self.omaxy = None
+        self.ominy = None
 
         self.stopped = False
         self.input = None
@@ -560,16 +572,17 @@ class GDAL2Tiles(object):
 
         # Workaround for old versions of GDAL
         try:
-            if (self.options.verbose and self.options.resampling == 'near') or gdal.TermProgress_nocb:
+            if ((self.options.verbose and self.options.resampling == 'near') or
+                    gdal.TermProgress_nocb):
                 pass
-        except:
+        except Exception:
             self.error("This version of GDAL is not supported. Please upgrade to 1.6+.")
-            #,"You can try run crippled version of gdal2tiles with parameters: -v -r 'near'")
 
         # Is output directory the last argument?
 
         # Test output directory, if it doesn't exist
-        if os.path.isdir(self.args[-1]) or ( len(self.args) > 1 and not os.path.exists(self.args[-1])):
+        if (os.path.isdir(self.args[-1]) or
+                (len(self.args) > 1 and not os.path.exists(self.args[-1]))):
             self.output = self.args[-1]
             self.args = self.args[:-1]
 
@@ -577,9 +590,8 @@ class GDAL2Tiles(object):
 
         if (len(self.args) > 1):
             self.error("Processing of several input files is not supported.",
-            """Please first use a tool like gdal_vrtmerge.py or gdal_merge.py on the files:
-gdal_vrtmerge.py -o merged.vrt %s""" % " ".join(self.args))
-            # TODO: Call functions from gdal_vrtmerge.py directly
+                       "Please first use a tool like gdal_vrtmerge.py or gdal_merge.py on the "
+                       "files: gdal_vrtmerge.py -o merged.vrt %s" % " ".join(self.args))
 
         self.input = self.args[0]
 
@@ -587,15 +599,15 @@ gdal_vrtmerge.py -o merged.vrt %s""" % " ".join(self.args))
 
         if not self.output:
             # Directory with input filename without extension in actual directory
-            self.output = os.path.splitext(os.path.basename( self.input ))[0]
+            self.output = os.path.splitext(os.path.basename(self.input))[0]
 
         if not self.options.title:
-            self.options.title = os.path.basename( self.input )
+            self.options.title = os.path.basename(self.input)
 
         if self.options.url and not self.options.url.endswith('/'):
             self.options.url += '/'
         if self.options.url:
-            self.options.url += os.path.basename( self.output ) + '/'
+            self.options.url += os.path.basename(self.output) + '/'
 
         # Supported options
 
@@ -605,15 +617,17 @@ gdal_vrtmerge.py -o merged.vrt %s""" % " ".join(self.args))
             try:
                 if gdal.RegenerateOverview:
                     pass
-            except:
-                self.error("'average' resampling algorithm is not available.", "Please use -r 'near' argument or upgrade to newer version of GDAL.")
+            except Exception:
+                self.error("'average' resampling algorithm is not available.",
+                           "Please use -r 'near' argument or upgrade to newer version of GDAL.")
 
         elif self.options.resampling == 'antialias':
             try:
-                if numpy:
+                if numpy:     # pylint:disable=W0125
                     pass
-            except:
-                self.error("'antialias' resampling algorithm is not available.", "Install PIL (Python Imaging Library) and numpy.")
+            except Exception:
+                self.error("'antialias' resampling algorithm is not available.",
+                           "Install PIL (Python Imaging Library) and numpy.")
 
         elif self.options.resampling == 'near':
             self.resampling = gdal.GRA_NearestNeighbour
@@ -636,20 +650,36 @@ gdal_vrtmerge.py -o merged.vrt %s""" % " ".join(self.args))
         self.tminz = None
         self.tmaxz = None
         if self.options.zoom:
-            minmax = self.options.zoom.split('-',1)
+            minmax = self.options.zoom.split('-', 1)
             minmax.extend([''])
-            min, max = minmax[:2]
-            self.tminz = int(min)
-            if max:
-                self.tmaxz = int(max)
+            zoom_min, zoom_max = minmax[:2]
+            self.tminz = int(zoom_min)
+            if zoom_max:
+                self.tmaxz = int(zoom_max)
             else:
-                self.tmaxz = int(min)
+                self.tmaxz = int(zoom_min)
 
         # KML generation
         self.kml = self.options.kml
 
-        # Output the results
+        # Check if the input filename is full ascii or not
+        try:
+            os.path.basename(self.input).encode('ascii')
+        except UnicodeEncodeError:
+            full_ascii = False
+        else:
+            full_ascii = True
+
+        # LC_CTYPE check
+        if not full_ascii and 'UTF-8' not in os.environ.get("LC_CTYPE", ""):
+            if not self.options.quiet:
+                print("\nWARNING: "
+                      "You are running gdal2tiles.py with a LC_CTYPE environment variable that is "
+                      "not UTF-8 compatible, and your input file contains non-ascii characters. "
+                      "The generated sample googlemaps, openlayers or "
+                      "leaflet files might contain some invalid characters as a result\n")
 
+        # Output the results
         if self.options.verbose:
             print("Options:", self.options)
             print("Input:", self.input)
@@ -657,83 +687,82 @@ gdal_vrtmerge.py -o merged.vrt %s""" % " ".join(self.args))
             print("Cache: %s MB" % (gdal.GetCacheMax() / 1024 / 1024))
             print('')
 
-    # -------------------------------------------------------------------------
     def optparse_init(self):
         """Prepare the option parser for input (argv)"""
 
         from optparse import OptionParser, OptionGroup
         usage = "Usage: %prog [options] input_file(s) [output]"
-        p = OptionParser(usage, version="%prog "+ __version__)
-        p.add_option("-p", "--profile", dest='profile', type='choice', choices=profile_list,
-                          help="Tile cutting profile (%s) - default 'mercator' (Google Maps compatible)" % ",".join(profile_list))
-        p.add_option("-r", "--resampling", dest="resampling", type='choice', choices=resampling_list,
-                        help="Resampling method (%s) - default 'average'" % ",".join(resampling_list))
+        p = OptionParser(usage, version="%prog " + __version__)
+        p.add_option("-p", "--profile", dest='profile',
+                     type='choice', choices=profile_list,
+                     help=("Tile cutting profile (%s) - default 'mercator' "
+                           "(Google Maps compatible)" % ",".join(profile_list)))
+        p.add_option("-r", "--resampling", dest="resampling",
+                     type='choice', choices=resampling_list,
+                     help="Resampling method (%s) - default 'average'" % ",".join(resampling_list))
         p.add_option('-s', '--s_srs', dest="s_srs", metavar="SRS",
-                          help="The spatial reference system used for the source input data")
+                     help="The spatial reference system used for the source input data")
         p.add_option('-z', '--zoom', dest="zoom",
-                          help="Zoom levels to render (format:'2-5' or '10').")
+                     help="Zoom levels to render (format:'2-5' or '10').")
         p.add_option('-e', '--resume', dest="resume", action="store_true",
-                          help="Resume mode. Generate only missing files.")
+                     help="Resume mode. Generate only missing files.")
         p.add_option('-a', '--srcnodata', dest="srcnodata", metavar="NODATA",
-                          help="NODATA transparency value to assign to the input data")
+                     help="NODATA transparency value to assign to the input data")
         p.add_option('-d', '--tmscompatible', dest="tmscompatible", action="store_true",
-                          help="When using the geodetic profile, specifies the base resolution as 0.703125 or 2 tiles at zoom level 0.")
+                     help=("When using the geodetic profile, specifies the base resolution "
+                           "as 0.703125 or 2 tiles at zoom level 0."))
         p.add_option("-v", "--verbose",
-                          action="store_true", dest="verbose",
-                          help="Print status messages to stdout")
+                     action="store_true", dest="verbose",
+                     help="Print status messages to stdout")
         p.add_option("-q", "--quiet",
-                          action="store_true", dest="quiet",
-                          help="Disable messages and status to stdout")
+                     action="store_true", dest="quiet",
+                     help="Disable messages and status to stdout")
 
         # KML options
-        g = OptionGroup(p, "KML (Google Earth) options", "Options for generated Google Earth SuperOverlay metadata")
+        g = OptionGroup(p, "KML (Google Earth) options",
+                        "Options for generated Google Earth SuperOverlay metadata")
         g.add_option("-k", "--force-kml", dest='kml', action="store_true",
-                          help="Generate KML for Google Earth - default for 'geodetic' profile and 'raster' in EPSG:4326. For a dataset with different projection use with caution!")
+                     help=("Generate KML for Google Earth - default for 'geodetic' profile and "
+                           "'raster' in EPSG:4326. For a dataset with different projection use "
+                           "with caution!"))
         g.add_option("-n", "--no-kml", dest='kml', action="store_false",
-                          help="Avoid automatic generation of KML files for EPSG:4326")
+                     help="Avoid automatic generation of KML files for EPSG:4326")
         g.add_option("-u", "--url", dest='url',
-                          help="URL address where the generated tiles are going to be published")
+                     help="URL address where the generated tiles are going to be published")
         p.add_option_group(g)
 
         # HTML options
-        g = OptionGroup(p, "Web viewer options", "Options for generated HTML viewers a la Google Maps")
+        g = OptionGroup(p, "Web viewer options",
+                        "Options for generated HTML viewers a la Google Maps")
         g.add_option("-w", "--webviewer", dest='webviewer', type='choice', choices=webviewer_list,
-                          help="Web viewer to generate (%s) - default 'all'" % ",".join(webviewer_list))
+                     help="Web viewer to generate (%s) - default 'all'" % ",".join(webviewer_list))
         g.add_option("-t", "--title", dest='title',
-                          help="Title of the map")
+                     help="Title of the map")
         g.add_option("-c", "--copyright", dest='copyright',
-                          help="Copyright for the map")
+                     help="Copyright for the map")
         g.add_option("-g", "--googlekey", dest='googlekey',
-                          help="Google Maps API key from http://code.google.com/apis/maps/signup.html")
+                     help="Google Maps API key from http://code.google.com/apis/maps/signup.html")
         g.add_option("-b", "--bingkey", dest='bingkey',
-                          help="Bing Maps API key from https://www.bingmapsportal.com/"),
+                     help="Bing Maps API key from https://www.bingmapsportal.com/")
         p.add_option_group(g)
 
-        # TODO: MapFile + TileIndexes per zoom level for efficient MapServer WMS
-            #g = OptionGroup(p, "WMS MapServer metadata", "Options for generated mapfile and tileindexes for MapServer")
-            #g.add_option("-i", "--tileindex", dest='wms', action="store_true"
-            #                 help="Generate tileindex and mapfile for MapServer (WMS)")
-            # p.add_option_group(g)
-
         p.set_defaults(verbose=False, profile="mercator", kml=False, url='',
-        webviewer='all', copyright='', resampling='average', resume=False,
-        googlekey='INSERT_YOUR_KEY_HERE', bingkey='INSERT_YOUR_KEY_HERE')
+                       webviewer='all', copyright='', resampling='average', resume=False,
+                       googlekey='INSERT_YOUR_KEY_HERE', bingkey='INSERT_YOUR_KEY_HERE')
 
         self.parser = p
 
     # -------------------------------------------------------------------------
     def open_input(self):
         """Initialization of the input raster, reprojection if necessary"""
-
         gdal.AllRegister()
 
-        # Initialize necessary GDAL drivers
-
-        self.out_drv = gdal.GetDriverByName( self.tiledriver )
-        self.mem_drv = gdal.GetDriverByName( 'MEM' )
+        self.out_drv = gdal.GetDriverByName(self.tiledriver)
+        self.mem_drv = gdal.GetDriverByName('MEM')
 
         if not self.out_drv:
-            raise Exception("The '%s' driver was not found, is it available in this GDAL build?", self.tiledriver)
+            raise Exception("The '%s' driver was not found, is it available in this GDAL build?",
+                            self.tiledriver)
         if not self.mem_drv:
             raise Exception("The 'MEM' driver was not found, is it available in this GDAL build?")
 
@@ -745,66 +774,58 @@ gdal_vrtmerge.py -o merged.vrt %s""" % " ".join(self.args))
             raise Exception("No input file was specified")
 
         if self.options.verbose:
-            print("Input file:", "( %sP x %sL - %s bands)" % (self.in_ds.RasterXSize, self.in_ds.RasterYSize, self.in_ds.RasterCount))
+            print("Input file:",
+                  "( %sP x %sL - %s bands)" % (self.in_ds.RasterXSize, self.in_ds.RasterYSize,
+                                               self.in_ds.RasterCount))
 
         if not self.in_ds:
             # Note: GDAL prints the ERROR message too
-            self.error("It is not possible to open the input file '%s'." % self.input )
+            self.error("It is not possible to open the input file '%s'." % self.input)
 
         # Read metadata from the input file
         if self.in_ds.RasterCount == 0:
-            self.error( "Input file '%s' has no raster band" % self.input )
+            self.error("Input file '%s' has no raster band" % self.input)
 
         if self.in_ds.GetRasterBand(1).GetRasterColorTable():
-            # TODO: Process directly paletted dataset by generating VRT in memory
-            self.error( "Please convert this file to RGB/RGBA and run gdal2tiles on the result.",
-            """From paletted file you can create RGBA file (temp.vrt) by:
-gdal_translate -of vrt -expand rgba %s temp.vrt
-then run:
-gdal2tiles temp.vrt""" % self.input )
+            self.error("Please convert this file to RGB/RGBA and run gdal2tiles on the result.",
+                       "From paletted file you can create RGBA file (temp.vrt) by:\n"
+                       "gdal_translate -of vrt -expand rgba %s temp.vrt\n"
+                       "then run:\n"
+                       "gdal2tiles temp.vrt" % self.input)
 
         # Get NODATA value
-        self.in_nodata = []
+        in_nodata = []
         for i in range(1, self.in_ds.RasterCount+1):
-            if self.in_ds.GetRasterBand(i).GetNoDataValue() != None:
-                self.in_nodata.append( self.in_ds.GetRasterBand(i).GetNoDataValue() )
+            if self.in_ds.GetRasterBand(i).GetNoDataValue() is not None:
+                in_nodata.append(self.in_ds.GetRasterBand(i).GetNoDataValue())
         if self.options.srcnodata:
-            nds = list(map( float, self.options.srcnodata.split(',')))
+            nds = list(map(float, self.options.srcnodata.split(',')))
             if len(nds) < self.in_ds.RasterCount:
-                self.in_nodata = (nds * self.in_ds.RasterCount)[:self.in_ds.RasterCount]
+                in_nodata = (nds * self.in_ds.RasterCount)[:self.in_ds.RasterCount]
             else:
-                self.in_nodata = nds
+                in_nodata = nds
 
         if self.options.verbose:
-            print("NODATA: %s" % self.in_nodata)
-
-        #
-        # Here we should have RGBA input dataset opened in self.in_ds
-        #
+            print("NODATA: %s" % in_nodata)
 
         if self.options.verbose:
-            print("Preprocessed file:", "( %sP x %sL - %s bands)" % (self.in_ds.RasterXSize, self.in_ds.RasterYSize, self.in_ds.RasterCount))
+            print("Preprocessed file:",
+                  "( %sP x %sL - %s bands)" % (self.in_ds.RasterXSize, self.in_ds.RasterYSize,
+                                               self.in_ds.RasterCount))
 
-        # Spatial Reference System of the input raster
-
-
-        self.in_srs = None
+        in_srs = None
 
         if self.options.s_srs:
-            self.in_srs = osr.SpatialReference()
-            self.in_srs.SetFromUserInput(self.options.s_srs)
-            self.in_srs_wkt = self.in_srs.ExportToWkt()
+            in_srs = osr.SpatialReference()
+            in_srs.SetFromUserInput(self.options.s_srs)
+            in_srs_wkt = in_srs.ExportToWkt()
         else:
-            self.in_srs_wkt = self.in_ds.GetProjection()
-            if not self.in_srs_wkt and self.in_ds.GetGCPCount() != 0:
-                self.in_srs_wkt = self.in_ds.GetGCPProjection()
-            if self.in_srs_wkt:
-                self.in_srs = osr.SpatialReference()
-                self.in_srs.ImportFromWkt(self.in_srs_wkt)
-            #elif self.options.profile != 'raster':
-            #   self.error("There is no spatial reference system info included in the input file.","You should run gdal2tiles with --s_srs EPSG:XXXX or similar.")
-
-        # Spatial Reference System of tiles
+            in_srs_wkt = self.in_ds.GetProjection()
+            if not in_srs_wkt and self.in_ds.GetGCPCount() != 0:
+                in_srs_wkt = self.in_ds.GetGCPProjection()
+            if in_srs_wkt:
+                in_srs = osr.SpatialReference()
+                in_srs.ImportFromWkt(in_srs_wkt)
 
         self.out_srs = osr.SpatialReference()
 
@@ -813,7 +834,7 @@ gdal2tiles temp.vrt""" % self.input )
         elif self.options.profile == 'geodetic':
             self.out_srs.ImportFromEPSG(4326)
         else:
-            self.out_srs = self.in_srs
+            self.out_srs = in_srs
 
         # Are the reference systems the same? Reproject if necessary.
 
@@ -821,92 +842,116 @@ gdal2tiles temp.vrt""" % self.input )
 
         if self.options.profile in ('mercator', 'geodetic'):
 
-            if (self.in_ds.GetGeoTransform() == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0)) and (self.in_ds.GetGCPCount() == 0):
-                self.error("There is no georeference - neither affine transformation (worldfile) nor GCPs. You can generate only 'raster' profile tiles.",
-                "Either gdal2tiles with parameter -p 'raster' or use another GIS software for georeference e.g. gdal_transform -gcp / -a_ullr / -a_srs")
-
-            if self.in_srs:
-
-                if (self.in_srs.ExportToProj4() != self.out_srs.ExportToProj4()) or (self.in_ds.GetGCPCount() != 0):
-
-                    # Generation of VRT dataset in tile projection, default 'nearest neighbour' warping
-                    self.out_ds = gdal.AutoCreateWarpedVRT( self.in_ds, self.in_srs_wkt, self.out_srs.ExportToWkt() )
-
-                    # TODO: HIGH PRIORITY: Correction of AutoCreateWarpedVRT according the max zoomlevel for correct direct warping!!!
+            if ((self.in_ds.GetGeoTransform() == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0)) and
+                    (self.in_ds.GetGCPCount() == 0)):
+                self.error("There is no georeference - neither affine transformation (worldfile) "
+                           "nor GCPs. You can generate only 'raster' profile tiles.",
+                           "Either gdal2tiles with parameter -p 'raster' or use another GIS "
+                           "software for georeference e.g. gdal_transform -gcp / -a_ullr / -a_srs")
+
+            if in_srs:
+                if ((in_srs.ExportToProj4() != self.out_srs.ExportToProj4()) or
+                        (self.in_ds.GetGCPCount() != 0)):
+                    # Generation of VRT dataset in tile projection,
+                    # default 'nearest neighbour' warping
+                    self.out_ds = gdal.AutoCreateWarpedVRT(
+                        self.in_ds, in_srs_wkt, self.out_srs.ExportToWkt())
 
                     if self.options.verbose:
-                        print("Warping of the raster by AutoCreateWarpedVRT (result saved into 'tiles.vrt')")
+                        print("Warping of the raster by AutoCreateWarpedVRT "
+                              "(result saved into 'tiles.vrt')")
                         self.out_ds.GetDriver().CreateCopy("tiles.vrt", self.out_ds)
 
-                    # Note: self.in_srs and self.in_srs_wkt contain still the non-warped reference system!!!
-
                     # Correction of AutoCreateWarpedVRT for NODATA values
-                    if self.in_nodata != []:
+                    if in_nodata != []:
                         tempfilename = self.gettempfilename('-gdal2tiles.vrt')
                         self.out_ds.GetDriver().CreateCopy(tempfilename, self.out_ds)
                         # open as a text file
                         s = open(tempfilename).read()
                         # Add the warping options
-                        s = s.replace("""<GDALWarpOptions>""","""<GDALWarpOptions>
+                        s = s.replace(
+                            "<GDALWarpOptions>",
+                            """
+    <GDALWarpOptions>
       <Option name="INIT_DEST">NO_DATA</Option>
-      <Option name="UNIFIED_SRC_NODATA">YES</Option>""")
+      <Option name="UNIFIED_SRC_NODATA">YES</Option>
+                            """)
                         # replace BandMapping tag for NODATA bands....
-                        for i in range(len(self.in_nodata)):
-                            s = s.replace("""<BandMapping src="%i" dst="%i"/>""" % ((i+1),(i+1)),"""<BandMapping src="%i" dst="%i">
+                        for i in range(len(in_nodata)):
+                            s = s.replace(
+                                '<BandMapping src="%i" dst="%i"/>' % ((i+1), (i+1)),
+                                """
+        <BandMapping src="%i" dst="%i">
           <SrcNoDataReal>%i</SrcNoDataReal>
           <SrcNoDataImag>0</SrcNoDataImag>
           <DstNoDataReal>%i</DstNoDataReal>
           <DstNoDataImag>0</DstNoDataImag>
-        </BandMapping>""" % ((i+1), (i+1), self.in_nodata[i], self.in_nodata[i])) # Or rewrite to white by: , 255 ))
+        </BandMapping>
+                                """ % ((i+1), (i+1), in_nodata[i], in_nodata[i]))
                         # save the corrected VRT
-                        open(tempfilename,"w").write(s)
+                        open(tempfilename, "w").write(s)
                         # open by GDAL as self.out_ds
-                        self.out_ds = gdal.Open(tempfilename) #, gdal.GA_ReadOnly)
+                        self.out_ds = gdal.Open(tempfilename)
                         # delete the temporary file
                         os.unlink(tempfilename)
 
                         # set NODATA_VALUE metadata
-                        self.out_ds.SetMetadataItem('NODATA_VALUES',' '.join([str(i) for i in self.in_nodata]))
+                        self.out_ds.SetMetadataItem(
+                            'NODATA_VALUES', ' '.join([str(i) for i in in_nodata]))
 
                         if self.options.verbose:
                             print("Modified warping result saved into 'tiles1.vrt'")
-                            open("tiles1.vrt","w").write(s)
+                            open("tiles1.vrt", "w").write(s)
 
-                    # -----------------------------------
-                    # Correction of AutoCreateWarpedVRT for Mono (1 band) and RGB (3 bands) files without NODATA:
+                    # Correction of AutoCreateWarpedVRT for Mono (1 band) and RGB (3 bands) files
+                    # without NODATA:
                     # equivalent of gdalwarp -dstalpha
-                    if self.in_nodata == [] and self.out_ds.RasterCount in [1,3]:
+                    if in_nodata == [] and self.out_ds.RasterCount in [1, 3]:
                         tempfilename = self.gettempfilename('-gdal2tiles.vrt')
                         self.out_ds.GetDriver().CreateCopy(tempfilename, self.out_ds)
                         # open as a text file
                         s = open(tempfilename).read()
                         # Add the warping options
-                        s = s.replace("""<BlockXSize>""","""<VRTRasterBand dataType="Byte" band="%i" subClass="VRTWarpedRasterBand">
+                        s = s.replace(
+                            "<BlockXSize>",
+                            """
+  <VRTRasterBand dataType="Byte" band="%i" subClass="VRTWarpedRasterBand">
     <ColorInterp>Alpha</ColorInterp>
   </VRTRasterBand>
-  <BlockXSize>""" % (self.out_ds.RasterCount + 1))
-                        s = s.replace("""</GDALWarpOptions>""", """<DstAlphaBand>%i</DstAlphaBand>
-  </GDALWarpOptions>""" % (self.out_ds.RasterCount + 1))
-                        s = s.replace("""</WorkingDataType>""", """</WorkingDataType>
-    <Option name="INIT_DEST">0</Option>""")
+  <BlockXSize>
+                            """ % (self.out_ds.RasterCount + 1))
+                        s = s.replace(
+                            "</GDALWarpOptions>",
+                            """
+    <DstAlphaBand>%i</DstAlphaBand>
+  </GDALWarpOptions>
+                            """ % (self.out_ds.RasterCount + 1))
+                        s = s.replace(
+                            "</WorkingDataType>",
+                            """
+    </WorkingDataType>
+    <Option name="INIT_DEST">0</Option>
+                            """)
                         # save the corrected VRT
-                        open(tempfilename,"w").write(s)
+                        open(tempfilename, "w").write(s)
                         # open by GDAL as self.out_ds
-                        self.out_ds = gdal.Open(tempfilename) #, gdal.GA_ReadOnly)
+                        self.out_ds = gdal.Open(tempfilename)
                         # delete the temporary file
                         os.unlink(tempfilename)
 
                         if self.options.verbose:
                             print("Modified -dstalpha warping result saved into 'tiles1.vrt'")
-                            open("tiles1.vrt","w").write(s)
+                            open("tiles1.vrt", "w").write(s)
                     s = '''
                     '''
 
             else:
-                self.error("Input file has unknown SRS.", "Use --s_srs ESPG:xyz (or similar) to provide source reference system." )
+                self.error("Input file has unknown SRS.",
+                           "Use --s_srs ESPG:xyz (or similar) to provide source reference system.")
 
             if self.out_ds and self.options.verbose:
-                print("Projected file:", "tiles.vrt", "( %sP x %sL - %s bands)" % (self.out_ds.RasterXSize, self.out_ds.RasterYSize, self.out_ds.RasterCount))
+                print("Projected file:", "tiles.vrt", "( %sP x %sL - %s bands)" % (
+                    self.out_ds.RasterXSize, self.out_ds.RasterYSize, self.out_ds.RasterCount))
 
         if not self.out_ds:
             self.out_ds = self.in_ds
@@ -917,71 +962,58 @@ gdal2tiles temp.vrt""" % self.input )
 
         # Get alpha band (either directly or from NODATA value)
         self.alphaband = self.out_ds.GetRasterBand(1).GetMaskBand()
-        if (self.alphaband.GetMaskFlags() & gdal.GMF_ALPHA) or self.out_ds.RasterCount==4 or self.out_ds.RasterCount==2:
-            # TODO: Better test for alpha band in the dataset
+        if ((self.alphaband.GetMaskFlags() & gdal.GMF_ALPHA) or
+                self.out_ds.RasterCount == 4 or
+                self.out_ds.RasterCount == 2):
             self.dataBandsCount = self.out_ds.RasterCount - 1
         else:
             self.dataBandsCount = self.out_ds.RasterCount
 
         # KML test
-        self.isepsg4326 = False
+        isepsg4326 = False
         srs4326 = osr.SpatialReference()
         srs4326.ImportFromEPSG(4326)
         if self.out_srs and srs4326.ExportToProj4() == self.out_srs.ExportToProj4():
             self.kml = True
-            self.isepsg4326 = True
+            isepsg4326 = True
             if self.options.verbose:
                 print("KML autotest OK!")
 
         # Read the georeference
-
         self.out_gt = self.out_ds.GetGeoTransform()
 
-        #originX, originY = self.out_gt[0], self.out_gt[3]
-        #pixelSize = self.out_gt[1] # = self.out_gt[5]
-
         # Test the size of the pixel
 
-        # MAPTILER - COMMENTED
-        #if self.out_gt[1] != (-1 * self.out_gt[5]) and self.options.profile != 'raster':
-            # TODO: Process correctly coordinates with are have switched Y axis (display in OpenLayers too)
-            #self.error("Size of the pixel in the output differ for X and Y axes.")
-
         # Report error in case rotation/skew is in geotransform (possible only in 'raster' profile)
-        if (self.out_gt[2], self.out_gt[4]) != (0,0):
-            self.error("Georeference of the raster contains rotation or skew. Such raster is not supported. Please use gdalwarp first.")
-            # TODO: Do the warping in this case automatically
+        if (self.out_gt[2], self.out_gt[4]) != (0, 0):
+            self.error("Georeference of the raster contains rotation or skew. "
+                       "Such raster is not supported. Please use gdalwarp first.")
 
-        #
         # Here we expect: pixel is square, no rotation on the raster
-        #
 
         # Output Bounds - coordinates in the output SRS
         self.ominx = self.out_gt[0]
-        self.omaxx = self.out_gt[0]+self.out_ds.RasterXSize*self.out_gt[1]
+        self.omaxx = self.out_gt[0] + self.out_ds.RasterXSize * self.out_gt[1]
         self.omaxy = self.out_gt[3]
-        self.ominy = self.out_gt[3]-self.out_ds.RasterYSize*self.out_gt[1]
+        self.ominy = self.out_gt[3] - self.out_ds.RasterYSize * self.out_gt[1]
         # Note: maybe round(x, 14) to avoid the gdal_translate behaviour, when 0 becomes -1e-15
 
         if self.options.verbose:
             print("Bounds (output srs):", round(self.ominx, 13), self.ominy, self.omaxx, self.omaxy)
 
-        #
         # Calculating ranges for tiles in different zoom levels
-        #
-
         if self.options.profile == 'mercator':
 
-            self.mercator = GlobalMercator() # from globalmaptiles.py
+            self.mercator = GlobalMercator()
 
             # Function which generates SWNE in LatLong for given tile
             self.tileswne = self.mercator.TileLatLonBounds
 
             # Generate table with min max tile coordinates for all zoomlevels
-            self.tminmax = list(range(0,32))
+            self.tminmax = list(range(0, 32))
             for tz in range(0, 32):
-                tminx, tminy = self.mercator.MetersToTile( self.ominx, self.ominy, tz )
-                tmaxx, tmaxy = self.mercator.MetersToTile( self.omaxx, self.omaxy, tz )
+                tminx, tminy = self.mercator.MetersToTile(self.ominx, self.ominy, tz)
+                tmaxx, tmaxy = self.mercator.MetersToTile(self.omaxx, self.omaxy, tz)
                 # crop tiles extending world limits (+-180,+-90)
                 tminx, tminy = max(0, tminx), max(0, tminy)
                 tmaxx, tmaxy = min(2**tz-1, tmaxx), min(2**tz-1, tmaxy)
@@ -990,30 +1022,39 @@ gdal2tiles temp.vrt""" % self.input )
             # TODO: Maps crossing 180E (Alaska?)
 
             # Get the minimal zoom level (map covers area equivalent to one tile)
-            if self.tminz == None:
-                self.tminz = self.mercator.ZoomForPixelSize( self.out_gt[1] * max( self.out_ds.RasterXSize, self.out_ds.RasterYSize) / float(self.tilesize) )
+            if self.tminz is None:
+                self.tminz = self.mercator.ZoomForPixelSize(
+                    self.out_gt[1] * max(self.out_ds.RasterXSize,
+                                         self.out_ds.RasterYSize) / float(self.tilesize))
 
-            # Get the maximal zoom level (closest possible zoom level up on the resolution of raster)
-            if self.tmaxz == None:
-                self.tmaxz = self.mercator.ZoomForPixelSize( self.out_gt[1] )
+            # Get the maximal zoom level
+            # (closest possible zoom level up on the resolution of raster)
+            if self.tmaxz is None:
+                self.tmaxz = self.mercator.ZoomForPixelSize(self.out_gt[1])
 
             if self.options.verbose:
-                print("Bounds (latlong):", self.mercator.MetersToLatLon( self.ominx, self.ominy), self.mercator.MetersToLatLon( self.omaxx, self.omaxy))
+                print("Bounds (latlong):",
+                      self.mercator.MetersToLatLon(self.ominx, self.ominy),
+                      self.mercator.MetersToLatLon(self.omaxx, self.omaxy))
                 print('MinZoomLevel:', self.tminz)
-                print("MaxZoomLevel:", self.tmaxz, "(", self.mercator.Resolution( self.tmaxz ),")")
+                print("MaxZoomLevel:",
+                      self.tmaxz,
+                      "(",
+                      self.mercator.Resolution(self.tmaxz),
+                      ")")
 
         if self.options.profile == 'geodetic':
 
-            self.geodetic = GlobalGeodetic(self.options.tmscompatible) # from globalmaptiles.py
+            self.geodetic = GlobalGeodetic(self.options.tmscompatible)
 
             # Function which generates SWNE in LatLong for given tile
             self.tileswne = self.geodetic.TileLatLonBounds
 
             # Generate table with min max tile coordinates for all zoomlevels
-            self.tminmax = list(range(0,32))
+            self.tminmax = list(range(0, 32))
             for tz in range(0, 32):
-                tminx, tminy = self.geodetic.LonLatToTile( self.ominx, self.ominy, tz )
-                tmaxx, tmaxy = self.geodetic.LonLatToTile( self.omaxx, self.omaxy, tz )
+                tminx, tminy = self.geodetic.LonLatToTile(self.ominx, self.ominy, tz)
+                tmaxx, tmaxy = self.geodetic.LonLatToTile(self.omaxx, self.omaxy, tz)
                 # crop tiles extending world limits (+-180,+-90)
                 tminx, tminy = max(0, tminx), max(0, tminy)
                 tmaxx, tmaxy = min(2**(tz+1)-1, tmaxx), min(2**tz-1, tmaxy)
@@ -1021,33 +1062,39 @@ gdal2tiles temp.vrt""" % self.input )
 
             # TODO: Maps crossing 180E (Alaska?)
 
-            # Get the maximal zoom level (closest possible zoom level up on the resolution of raster)
-            if self.tminz == None:
-                self.tminz = self.geodetic.ZoomForPixelSize( self.out_gt[1] * max( self.out_ds.RasterXSize, self.out_ds.RasterYSize) / float(self.tilesize) )
+            # Get the maximal zoom level
+            # (closest possible zoom level up on the resolution of raster)
+            if self.tminz is None:
+                self.tminz = self.geodetic.ZoomForPixelSize(
+                    self.out_gt[1] * max(self.out_ds.RasterXSize,
+                                         self.out_ds.RasterYSize) / float(self.tilesize))
 
-            # Get the maximal zoom level (closest possible zoom level up on the resolution of raster)
-            if self.tmaxz == None:
-                self.tmaxz = self.geodetic.ZoomForPixelSize( self.out_gt[1] )
+            # Get the maximal zoom level
+            # (closest possible zoom level up on the resolution of raster)
+            if self.tmaxz is None:
+                self.tmaxz = self.geodetic.ZoomForPixelSize(self.out_gt[1])
 
             if self.options.verbose:
                 print("Bounds (latlong):", self.ominx, self.ominy, self.omaxx, self.omaxy)
 
         if self.options.profile == 'raster':
 
-            log2 = lambda x: math.log10(x) / math.log10(2) # log2 (base 2 logarithm)
+            def log2(x):
+                return math.log10(x) / math.log10(2)
 
-            self.nativezoom = int(max( math.ceil(log2(self.out_ds.RasterXSize/float(self.tilesize))),
-                                       math.ceil(log2(self.out_ds.RasterYSize/float(self.tilesize)))))
+            self.nativezoom = int(
+                max(math.ceil(log2(self.out_ds.RasterXSize/float(self.tilesize))),
+                    math.ceil(log2(self.out_ds.RasterYSize/float(self.tilesize)))))
 
             if self.options.verbose:
                 print("Native zoom of the raster:", self.nativezoom)
 
             # Get the minimal zoom level (whole raster in one tile)
-            if self.tminz == None:
+            if self.tminz is None:
                 self.tminz = 0
 
             # Get the maximal zoom level (native resolution of the raster)
-            if self.tmaxz == None:
+            if self.tmaxz is None:
                 self.tmaxz = self.nativezoom
 
             # Generate table with min max tile coordinates for all zoomlevels
@@ -1056,67 +1103,70 @@ gdal2tiles temp.vrt""" % self.input )
             for tz in range(0, self.tmaxz+1):
                 tsize = 2.0**(self.nativezoom-tz)*self.tilesize
                 tminx, tminy = 0, 0
-                tmaxx = int(math.ceil( self.out_ds.RasterXSize / tsize )) - 1
-                tmaxy = int(math.ceil( self.out_ds.RasterYSize / tsize )) - 1
+                tmaxx = int(math.ceil(self.out_ds.RasterXSize / tsize)) - 1
+                tmaxy = int(math.ceil(self.out_ds.RasterYSize / tsize)) - 1
                 self.tsize[tz] = math.ceil(tsize)
                 self.tminmax[tz] = (tminx, tminy, tmaxx, tmaxy)
 
             # Function which generates SWNE in LatLong for given tile
-            if self.kml and self.in_srs_wkt:
-                self.ct = osr.CoordinateTransformation(self.in_srs, srs4326)
+            if self.kml and in_srs_wkt:
+                ct = osr.CoordinateTransformation(in_srs, srs4326)
 
-                def rastertileswne(x,y,z):
-                    pixelsizex = (2**(self.tmaxz-z) * self.out_gt[1]) # X-pixel size in level
-                    #Comment pixelsizey as unused...
-                    #pixelsizey = (2**(self.tmaxz-z) * self.out_gt[1]) # Y-pixel size in level (usually -1*pixelsizex)
+                def rastertileswne(x, y, z):
+                    pixelsizex = (2**(self.tmaxz-z) * self.out_gt[1])       # X-pixel size in level
                     west = self.out_gt[0] + x*self.tilesize*pixelsizex
                     east = west + self.tilesize*pixelsizex
                     south = self.ominy + y*self.tilesize*pixelsizex
                     north = south + self.tilesize*pixelsizex
-                    if not self.isepsg4326:
+                    if not isepsg4326:
                         # Transformation to EPSG:4326 (WGS84 datum)
-                        west, south = self.ct.TransformPoint(west, south)[:2]
-                        east, north = self.ct.TransformPoint(east, north)[:2]
+                        west, south = ct.TransformPoint(west, south)[:2]
+                        east, north = ct.TransformPoint(east, north)[:2]
                     return south, west, north, east
 
                 self.tileswne = rastertileswne
             else:
-                self.tileswne = lambda x, y, z: (0,0,0,0)
+                self.tileswne = lambda x, y, z: (0, 0, 0, 0)   # noqa
 
-    # -------------------------------------------------------------------------
     def generate_metadata(self):
-        """Generation of main metadata files and HTML viewers (metadata related to particular tiles are generated during the tile processing)."""
+        """
+        Generation of main metadata files and HTML viewers (metadata related to particular
+        tiles are generated during the tile processing).
+        """
 
         if not os.path.exists(self.output):
             os.makedirs(self.output)
 
         if self.options.profile == 'mercator':
 
-            south, west = self.mercator.MetersToLatLon( self.ominx, self.ominy)
-            north, east = self.mercator.MetersToLatLon( self.omaxx, self.omaxy)
+            south, west = self.mercator.MetersToLatLon(self.ominx, self.ominy)
+            north, east = self.mercator.MetersToLatLon(self.omaxx, self.omaxy)
             south, west = max(-85.05112878, south), max(-180.0, west)
             north, east = min(85.05112878, north), min(180.0, east)
             self.swne = (south, west, north, east)
 
             # Generate googlemaps.html
-            if self.options.webviewer in ('all','google') and self.options.profile == 'mercator':
-                if not self.options.resume or not os.path.exists(os.path.join(self.output, 'googlemaps.html')):
-                    f = open(os.path.join(self.output, 'googlemaps.html'), 'w')
-                    f.write( self.generate_googlemaps() )
+            if self.options.webviewer in ('all', 'google') and self.options.profile == 'mercator':
+                if (not self.options.resume or not
+                        os.path.exists(os.path.join(self.output, 'googlemaps.html'))):
+                    f = open(os.path.join(self.output, 'googlemaps.html'), 'wb')
+                    f.write(self.generate_googlemaps().encode('utf-8'))
                     f.close()
 
             # Generate openlayers.html
-            if self.options.webviewer in ('all','openlayers'):
-                if not self.options.resume or not os.path.exists(os.path.join(self.output, 'openlayers.html')):
-                    f = open(os.path.join(self.output, 'openlayers.html'), 'w')
-                    f.write( self.generate_openlayers() )
+            if self.options.webviewer in ('all', 'openlayers'):
+                if (not self.options.resume or not
+                        os.path.exists(os.path.join(self.output, 'openlayers.html'))):
+                    f = open(os.path.join(self.output, 'openlayers.html'), 'wb')
+                    f.write(self.generate_openlayers().encode('utf-8'))
                     f.close()
 
             # Generate leaflet.html
-            if self.options.webviewer in ('all','leaflet'):
-                if not self.options.resume or not os.path.exists(os.path.join(self.output, 'leaflet.html')):
-                    f = open(os.path.join(self.output, 'leaflet.html'), 'w')
-                    f.write( self.generate_leaflet() )
+            if self.options.webviewer in ('all', 'leaflet'):
+                if (not self.options.resume or not
+                        os.path.exists(os.path.join(self.output, 'leaflet.html'))):
+                    f = open(os.path.join(self.output, 'leaflet.html'), 'wb')
+                    f.write(self.generate_leaflet().encode('utf-8'))
                     f.close()
 
         elif self.options.profile == 'geodetic':
@@ -1128,10 +1178,11 @@ gdal2tiles temp.vrt""" % self.input )
             self.swne = (south, west, north, east)
 
             # Generate openlayers.html
-            if self.options.webviewer in ('all','openlayers'):
-                if not self.options.resume or not os.path.exists(os.path.join(self.output, 'openlayers.html')):
-                    f = open(os.path.join(self.output, 'openlayers.html'), 'w')
-                    f.write( self.generate_openlayers() )
+            if self.options.webviewer in ('all', 'openlayers'):
+                if (not self.options.resume or not
+                        os.path.exists(os.path.join(self.output, 'openlayers.html'))):
+                    f = open(os.path.join(self.output, 'openlayers.html'), 'wb')
+                    f.write(self.generate_openlayers().encode('utf-8'))
                     f.close()
 
         elif self.options.profile == 'raster':
@@ -1142,17 +1193,16 @@ gdal2tiles temp.vrt""" % self.input )
             self.swne = (south, west, north, east)
 
             # Generate openlayers.html
-            if self.options.webviewer in ('all','openlayers'):
-                if not self.options.resume or not os.path.exists(os.path.join(self.output, 'openlayers.html')):
-                    f = open(os.path.join(self.output, 'openlayers.html'), 'w')
-                    f.write( self.generate_openlayers() )
+            if self.options.webviewer in ('all', 'openlayers'):
+                if (not self.options.resume or not
+                        os.path.exists(os.path.join(self.output, 'openlayers.html'))):
+                    f = open(os.path.join(self.output, 'openlayers.html'), 'wb')
+                    f.write(self.generate_openlayers().encode('utf-8'))
                     f.close()
 
-
         # Generate tilemapresource.xml.
-        if not self.options.resume or not os.path.exists(os.path.join(self.output, 'tilemapresource.xml')):
-            f = open(os.path.join(self.output, 'tilemapresource.xml'), 'w')
-            f.write( self.generate_tilemapresource())
+            f = open(os.path.join(self.output, 'tilemapresource.xml'), 'wb')
+            f.write(self.generate_tilemapresource().encode('utf-8'))
             f.close()
 
         if self.kml:
@@ -1162,40 +1212,32 @@ gdal2tiles temp.vrt""" % self.input )
             xmin, ymin, xmax, ymax = self.tminmax[self.tminz]
             for x in range(xmin, xmax+1):
                 for y in range(ymin, ymax+1):
-                    children.append( [ x, y, self.tminz ] )
+                    children.append([x, y, self.tminz])
             # Generate Root KML
             if self.kml:
-                if not self.options.resume or not os.path.exists(os.path.join(self.output, 'doc.kml')):
-                    f = open(os.path.join(self.output, 'doc.kml'), 'w')
-                    f.write( self.generate_kml( None, None, None, children) )
+                if (not self.options.resume or not
+                        os.path.exists(os.path.join(self.output, 'doc.kml'))):
+                    f = open(os.path.join(self.output, 'doc.kml'), 'wb')
+                    f.write(self.generate_kml(None, None, None, children).encode('utf-8'))
                     f.close()
 
-    # -------------------------------------------------------------------------
     def generate_base_tiles(self):
-        """Generation of the base tiles (the lowest in the pyramid) directly from the input raster"""
+        """
+        Generation of the base tiles (the lowest in the pyramid) directly from the input raster
+        """
 
         if not self.options.quiet:
             print("Generating Base Tiles:")
 
         if self.options.verbose:
-            #mx, my = self.out_gt[0], self.out_gt[3] # OriginX, OriginY
-            #px, py = self.mercator.MetersToPixels( mx, my, self.tmaxz)
-            #print "Pixel coordinates:", px, py, (mx, my)
             print('')
             print("Tiles generated from the max zoom level:")
             print("----------------------------------------")
             print('')
 
-
         # Set the bounds
         tminx, tminy, tmaxx, tmaxy = self.tminmax[self.tmaxz]
 
-        # Just the center tile
-        #tminx = tminx+ (tmaxx - tminx)/2
-        #tminy = tminy+ (tmaxy - tminy)/2
-        #tmaxx = tminx
-        #tmaxy = tminy
-
         ds = self.out_ds
         tilebands = self.dataBandsCount + 1
         querysize = self.querysize
@@ -1204,27 +1246,26 @@ gdal2tiles temp.vrt""" % self.input )
             print("dataBandsCount: ", self.dataBandsCount)
             print("tilebands: ", tilebands)
 
-        #print tminx, tminy, tmaxx, tmaxy
         tcount = (1+abs(tmaxx-tminx)) * (1+abs(tmaxy-tminy))
-        #print tcount
         ti = 0
 
         tz = self.tmaxz
-        for ty in range(tmaxy, tminy-1, -1): #range(tminy, tmaxy+1):
+        for ty in range(tmaxy, tminy-1, -1):
             for tx in range(tminx, tmaxx+1):
 
                 if self.stopped:
                     break
                 ti += 1
-                tilefilename = os.path.join(self.output, str(tz), str(tx), "%s.%s" % (ty, self.tileext))
+                tilefilename = os.path.join(
+                    self.output, str(tz), str(tx), "%s.%s" % (ty, self.tileext))
                 if self.options.verbose:
-                    print(ti,'/',tcount, tilefilename) #, "( TileMapService: z / x / y )"
+                    print(ti, '/', tcount, tilefilename)
 
                 if self.options.resume and os.path.exists(tilefilename):
                     if self.options.verbose:
                         print("Tile generation skipped because of --resume")
                     else:
-                        self.progressbar( ti / float(tcount) )
+                        self.progressbar(ti / float(tcount))
                     continue
 
                 # Create directories for the tile
@@ -1237,30 +1278,30 @@ gdal2tiles temp.vrt""" % self.input )
                 elif self.options.profile == 'geodetic':
                     b = self.geodetic.TileBounds(tx, ty, tz)
 
-                #print "\tgdalwarp -ts 256 256 -te %s %s %s %s %s %s_%s_%s.tif" % ( b[0], b[1], b[2], b[3], "tiles.vrt", tz, tx, ty)
-
                 # Don't scale up by nearest neighbour, better change the querysize
                 # to the native resolution (and return smaller query tile) for scaling
 
-                if self.options.profile in ('mercator','geodetic'):
-                    rb, wb = self.geo_query( ds, b[0], b[3], b[2], b[1])
-                    nativesize = wb[0]+wb[2] # Pixel size in the raster covering query geo extent
+                if self.options.profile in ('mercator', 'geodetic'):
+                    rb, wb = self.geo_query(ds, b[0], b[3], b[2], b[1])
+
+                    # Pixel size in the raster covering query geo extent
+                    nativesize = wb[0] + wb[2]
                     if self.options.verbose:
-                        print("\tNative Extent (querysize",nativesize,"): ", rb, wb)
+                        print("\tNative Extent (querysize", nativesize, "): ", rb, wb)
 
                     # Tile bounds in raster coordinates for ReadRaster query
-                    rb, wb = self.geo_query( ds, b[0], b[3], b[2], b[1], querysize=querysize)
+                    rb, wb = self.geo_query(ds, b[0], b[3], b[2], b[1], querysize=querysize)
 
                     rx, ry, rxsize, rysize = rb
                     wx, wy, wxsize, wysize = wb
 
-                else: # 'raster' profile:
+                else:     # 'raster' profile:
 
-                    tsize = int(self.tsize[tz]) # tilesize in raster coordinates for actual zoom
-                    xsize = self.out_ds.RasterXSize # size of the raster in pixels
+                    tsize = int(self.tsize[tz])   # tilesize in raster coordinates for actual zoom
+                    xsize = self.out_ds.RasterXSize     # size of the raster in pixels
                     ysize = self.out_ds.RasterYSize
                     if tz >= self.nativezoom:
-                        querysize = self.tilesize # int(2**(self.nativezoom-tz) * self.tilesize)
+                        querysize = self.tilesize
 
                     rx = (tx) * tsize
                     rxsize = 0
@@ -1277,40 +1318,54 @@ gdal2tiles temp.vrt""" % self.input )
                     ry = ysize - (ty * tsize) - rysize
 
                     wx, wy = 0, 0
-                    wxsize, wysize = int(rxsize/float(tsize) * self.tilesize), int(rysize/float(tsize) * self.tilesize)
+                    wxsize = int(rxsize/float(tsize) * self.tilesize)
+                    wysize = int(rysize/float(tsize) * self.tilesize)
                     if wysize != self.tilesize:
                         wy = self.tilesize - wysize
 
                 if self.options.verbose:
-                    print("\tReadRaster Extent: ", (rx, ry, rxsize, rysize), (wx, wy, wxsize, wysize))
+                    print("\tReadRaster Extent: ",
+                          (rx, ry, rxsize, rysize), (wx, wy, wxsize, wysize))
 
                 # Query is in 'nearest neighbour' but can be bigger in then the tilesize
                 # We scale down the query to the tilesize by supplied algorithm.
 
                 # Tile dataset in memory
                 dstile = self.mem_drv.Create('', self.tilesize, self.tilesize, tilebands)
-                data = ds.ReadRaster(rx, ry, rxsize, rysize, wxsize, wysize, band_list=list(range(1,self.dataBandsCount+1)))
-                alpha = self.alphaband.ReadRaster(rx, ry, rxsize, rysize, wxsize, wysize)
-
-                if self.tilesize == querysize:
-                    # Use the ReadRaster result directly in tiles ('nearest neighbour' query)
-                    dstile.WriteRaster(wx, wy, wxsize, wysize, data, band_list=list(range(1,self.dataBandsCount+1)))
-                    dstile.WriteRaster(wx, wy, wxsize, wysize, alpha, band_list=[tilebands])
 
-                    # Note: For source drivers based on WaveLet compression (JPEG2000, ECW, MrSID)
-                    # the ReadRaster function returns high-quality raster (not ugly nearest neighbour)
-                    # TODO: Use directly 'near' for WaveLet files
-                else:
-                    # Big ReadRaster query in memory scaled to the tilesize - all but 'near' algo
-                    dsquery = self.mem_drv.Create('', querysize, querysize, tilebands)
-                    # TODO: fill the null value in case a tile without alpha is produced (now only png tiles are supported)
-                    #for i in range(1, tilebands+1):
-                    #   dsquery.GetRasterBand(1).Fill(tilenodata)
-                    dsquery.WriteRaster(wx, wy, wxsize, wysize, data, band_list=list(range(1,self.dataBandsCount+1)))
-                    dsquery.WriteRaster(wx, wy, wxsize, wysize, alpha, band_list=[tilebands])
-
-                    self.scale_query_to_tile(dsquery, dstile, tilefilename)
-                    del dsquery
+                data = alpha = None
+                # Read the source raster if anything is going inside the tile as per the computed
+                # geo_query
+                if rxsize != 0 and rysize != 0 and wxsize != 0 and wysize != 0:
+                    data = ds.ReadRaster(rx, ry, rxsize, rysize, wxsize, wysize,
+                                         band_list=list(range(1, self.dataBandsCount+1)))
+                    alpha = self.alphaband.ReadRaster(rx, ry, rxsize, rysize, wxsize, wysize)
+
+                # The tile in memory is a transparent file by default. Write pixel values into it if
+                # any
+                if data:
+                    if self.tilesize == querysize:
+                        # Use the ReadRaster result directly in tiles ('nearest neighbour' query)
+                        dstile.WriteRaster(wx, wy, wxsize, wysize, data,
+                                           band_list=list(range(1, self.dataBandsCount+1)))
+                        dstile.WriteRaster(wx, wy, wxsize, wysize, alpha, band_list=[tilebands])
+
+                        # Note: For source drivers based on WaveLet compression (JPEG2000, ECW,
+                        # MrSID) the ReadRaster function returns high-quality raster (not ugly
+                        # nearest neighbour)
+                        # TODO: Use directly 'near' for WaveLet files
+                    else:
+                        # Big ReadRaster query in memory scaled to the tilesize - all but 'near'
+                        # algo
+                        dsquery = self.mem_drv.Create('', querysize, querysize, tilebands)
+                        # TODO: fill the null value in case a tile without alpha is produced (now
+                        # only png tiles are supported)
+                        dsquery.WriteRaster(wx, wy, wxsize, wysize, data,
+                                            band_list=list(range(1, self.dataBandsCount+1)))
+                        dsquery.WriteRaster(wx, wy, wxsize, wysize, alpha, band_list=[tilebands])
+
+                        self.scale_query_to_tile(dsquery, dstile, tilefilename)
+                        del dsquery
 
                 del data
 
@@ -1324,14 +1379,13 @@ gdal2tiles temp.vrt""" % self.input )
                 if self.kml:
                     kmlfilename = os.path.join(self.output, str(tz), str(tx), '%d.kml' % ty)
                     if not self.options.resume or not os.path.exists(kmlfilename):
-                        f = open( kmlfilename, 'w')
-                        f.write( self.generate_kml( tx, ty, tz ))
+                        f = open(kmlfilename, 'wb')
+                        f.write(self.generate_kml(tx, ty, tz).encode('utf-8'))
                         f.close()
 
                 if not self.options.verbose and not self.options.quiet:
-                    self.progressbar( ti / float(tcount) )
+                    self.progressbar(ti / float(tcount))
 
-    # -------------------------------------------------------------------------
     def generate_overview_tiles(self):
         """Generation of the overview tiles (higher in the pyramid) based on existing tiles"""
 
@@ -1349,27 +1403,28 @@ gdal2tiles temp.vrt""" % self.input )
 
         ti = 0
 
-        # querysize = tilesize * 2
-
         for tz in range(self.tmaxz-1, self.tminz-1, -1):
             tminx, tminy, tmaxx, tmaxy = self.tminmax[tz]
-            for ty in range(tmaxy, tminy-1, -1): #range(tminy, tmaxy+1):
+            for ty in range(tmaxy, tminy-1, -1):
                 for tx in range(tminx, tmaxx+1):
 
                     if self.stopped:
                         break
 
                     ti += 1
-                    tilefilename = os.path.join( self.output, str(tz), str(tx), "%s.%s" % (ty, self.tileext) )
+                    tilefilename = os.path.join(self.output,
+                                                str(tz),
+                                                str(tx),
+                                                "%s.%s" % (ty, self.tileext))
 
                     if self.options.verbose:
-                        print(ti,'/',tcount, tilefilename) #, "( TileMapService: z / x / y )"
+                        print(ti, '/', tcount, tilefilename)
 
                     if self.options.resume and os.path.exists(tilefilename):
                         if self.options.verbose:
                             print("Tile generation skipped because of --resume")
                         else:
-                            self.progressbar( ti / float(tcount) )
+                            self.progressbar(ti / float(tcount))
                         continue
 
                     # Create directories for the tile
@@ -1378,8 +1433,6 @@ gdal2tiles temp.vrt""" % self.input )
 
                     dsquery = self.mem_drv.Create('', 2*self.tilesize, 2*self.tilesize, tilebands)
                     # TODO: fill the null value
-                    #for i in range(1, tilebands+1):
-                    #   dsquery.GetRasterBand(1).Fill(tilenodata)
                     dstile = self.mem_drv.Create('', self.tilesize, self.tilesize, tilebands)
 
                     # TODO: Implement more clever walking on the tiles with cache functionality
@@ -1388,25 +1441,29 @@ gdal2tiles temp.vrt""" % self.input )
 
                     children = []
                     # Read the tiles and write them to query window
-                    for y in range(2*ty,2*ty+2):
-                        for x in range(2*tx,2*tx+2):
+                    for y in range(2*ty, 2*ty+2):
+                        for x in range(2*tx, 2*tx+2):
                             minx, miny, maxx, maxy = self.tminmax[tz+1]
                             if x >= minx and x <= maxx and y >= miny and y <= maxy:
-                                dsquerytile = gdal.Open( os.path.join( self.output, str(tz+1), str(x), "%s.%s" % (y, self.tileext)), gdal.GA_ReadOnly)
-                                if (ty==0 and y==1) or (ty!=0 and (y % (2*ty)) != 0):
+                                dsquerytile = gdal.Open(
+                                    os.path.join(self.output, str(tz+1), str(x),
+                                                 "%s.%s" % (y, self.tileext)),
+                                    gdal.GA_ReadOnly)
+                                if (ty == 0 and y == 1) or (ty != 0 and (y % (2*ty)) != 0):
                                     tileposy = 0
                                 else:
                                     tileposy = self.tilesize
                                 if tx:
                                     tileposx = x % (2*tx) * self.tilesize
-                                elif tx==0 and x==1:
+                                elif tx == 0 and x == 1:
                                     tileposx = self.tilesize
                                 else:
                                     tileposx = 0
-                                dsquery.WriteRaster( tileposx, tileposy, self.tilesize, self.tilesize,
-                                    dsquerytile.ReadRaster(0,0,self.tilesize,self.tilesize),
-                                    band_list=list(range(1,tilebands+1)))
-                                children.append( [x, y, tz+1] )
+                                dsquery.WriteRaster(
+                                    tileposx, tileposy, self.tilesize, self.tilesize,
+                                    dsquerytile.ReadRaster(0, 0, self.tilesize, self.tilesize),
+                                    band_list=list(range(1, tilebands+1)))
+                                children.append([x, y, tz+1])
 
                     self.scale_query_to_tile(dsquery, dstile, tilefilename)
                     # Write a copy of tile to png/jpg
@@ -1415,30 +1472,32 @@ gdal2tiles temp.vrt""" % self.input )
                         self.out_drv.CreateCopy(tilefilename, dstile, strict=0)
 
                     if self.options.verbose:
-                        print("\tbuild from zoom", tz+1," tiles:", (2*tx, 2*ty), (2*tx+1, 2*ty),(2*tx, 2*ty+1), (2*tx+1, 2*ty+1))
+                        print("\tbuild from zoom", tz+1,
+                              " tiles:", (2*tx, 2*ty), (2*tx+1, 2*ty),
+                              (2*tx, 2*ty+1), (2*tx+1, 2*ty+1))
 
                     # Create a KML file for this tile.
                     if self.kml:
-                        f = open( os.path.join(self.output, '%d/%d/%d.kml' % (tz, tx, ty)), 'w')
-                        f.write( self.generate_kml( tx, ty, tz, children ) )
+                        f = open(os.path.join(self.output, '%d/%d/%d.kml' % (tz, tx, ty)), 'wb')
+                        f.write(self.generate_kml(tx, ty, tz, children).encode('utf-8'))
                         f.close()
 
                     if not self.options.verbose and not self.options.quiet:
-                        self.progressbar( ti / float(tcount) )
+                        self.progressbar(ti / float(tcount))
 
+    def geo_query(self, ds, ulx, uly, lrx, lry, querysize=0):
+        """
+        For given dataset and query in cartographic coordinates returns parameters for ReadRaster()
+        in raster coordinates and x/y shifts (for border tiles). If the querysize is not given, the
+        extent is returned in the native resolution of dataset ds.
 
-    # -------------------------------------------------------------------------
-    def geo_query(self, ds, ulx, uly, lrx, lry, querysize = 0):
-        """For given dataset and query in cartographic coordinates
-        returns parameters for ReadRaster() in raster coordinates and
-        x/y shifts (for border tiles). If the querysize is not given, the
-        extent is returned in the native resolution of dataset ds."""
-
+        raises Gdal2TilesError if the dataset does not contain anything inside this geo_query
+        """
         geotran = ds.GetGeoTransform()
-        rx= int((ulx - geotran[0]) / geotran[1] + 0.001)
-        ry= int((uly - geotran[3]) / geotran[5] + 0.001)
-        rxsize= int((lrx - ulx) / geotran[1] + 0.5)
-        rysize= int((lry - uly) / geotran[5] + 0.5)
+        rx = int((ulx - geotran[0]) / geotran[1] + 0.001)
+        ry = int((uly - geotran[3]) / geotran[5] + 0.001)
+        rxsize = int((lrx - ulx) / geotran[1] + 0.5)
+        rysize = int((lry - uly) / geotran[5] + 0.5)
 
         if not querysize:
             wxsize, wysize = rxsize, rysize
@@ -1449,28 +1508,27 @@ gdal2tiles temp.vrt""" % self.input )
         wx = 0
         if rx < 0:
             rxshift = abs(rx)
-            wx = int( wxsize * (float(rxshift) / rxsize) )
+            wx = int(wxsize * (float(rxshift) / rxsize))
             wxsize = wxsize - wx
-            rxsize = rxsize - int( rxsize * (float(rxshift) / rxsize) )
+            rxsize = rxsize - int(rxsize * (float(rxshift) / rxsize))
             rx = 0
         if rx+rxsize > ds.RasterXSize:
-            wxsize = int( wxsize * (float(ds.RasterXSize - rx) / rxsize) )
+            wxsize = int(wxsize * (float(ds.RasterXSize - rx) / rxsize))
             rxsize = ds.RasterXSize - rx
 
         wy = 0
         if ry < 0:
             ryshift = abs(ry)
-            wy = int( wysize * (float(ryshift) / rysize) )
+            wy = int(wysize * (float(ryshift) / rysize))
             wysize = wysize - wy
-            rysize = rysize - int( rysize * (float(ryshift) / rysize) )
+            rysize = rysize - int(rysize * (float(ryshift) / rysize))
             ry = 0
         if ry+rysize > ds.RasterYSize:
-            wysize = int( wysize * (float(ds.RasterYSize - ry) / rysize) )
+            wysize = int(wysize * (float(ds.RasterYSize - ry) / rysize))
             rysize = ds.RasterYSize - ry
 
         return (rx, ry, rxsize, rysize), (wx, wy, wxsize, wysize)
 
-    # -------------------------------------------------------------------------
     def scale_query_to_tile(self, dsquery, dstile, tilefilename=''):
         """Scales down query dataset to the tile dataset"""
 
@@ -1481,12 +1539,10 @@ gdal2tiles temp.vrt""" % self.input )
         if self.options.resampling == 'average':
 
             # Function: gdal.RegenerateOverview()
-            for i in range(1,tilebands+1):
+            for i in range(1, tilebands+1):
                 # Black border around NODATA
-                #if i != 4:
-                #   dsquery.GetRasterBand(i).SetNoDataValue(0)
-                res = gdal.RegenerateOverview( dsquery.GetRasterBand(i),
-                    dstile.GetRasterBand(i), 'average' )
+                res = gdal.RegenerateOverview(dsquery.GetRasterBand(i), dstile.GetRasterBand(i),
+                                              'average')
                 if res != 0:
                     self.error("RegenerateOverview() failed on %s, error %d" % (tilefilename, res))
 
@@ -1495,25 +1551,26 @@ gdal2tiles temp.vrt""" % self.input )
             # Scaling by PIL (Python Imaging Library) - improved Lanczos
             array = numpy.zeros((querysize, querysize, tilebands), numpy.uint8)
             for i in range(tilebands):
-                array[:,:,i] = gdalarray.BandReadAsArray(dsquery.GetRasterBand(i+1), 0, 0, querysize, querysize)
-            im = Image.fromarray(array, 'RGBA') # Always four bands
-            im1 = im.resize((tilesize,tilesize), Image.ANTIALIAS)
+                array[:, :, i] = gdalarray.BandReadAsArray(dsquery.GetRasterBand(i+1),
+                                                           0, 0, querysize, querysize)
+            im = Image.fromarray(array, 'RGBA')     # Always four bands
+            im1 = im.resize((tilesize, tilesize), Image.ANTIALIAS)
             if os.path.exists(tilefilename):
                 im0 = Image.open(tilefilename)
                 im1 = Image.composite(im1, im0, im1)
-            im1.save(tilefilename,self.tiledriver)
+            im1.save(tilefilename, self.tiledriver)
 
         else:
 
             # Other algorithms are implemented by gdal.ReprojectImage().
-            dsquery.SetGeoTransform( (0.0, tilesize / float(querysize), 0.0, 0.0, 0.0, tilesize / float(querysize)) )
-            dstile.SetGeoTransform( (0.0, 1.0, 0.0, 0.0, 0.0, 1.0) )
+            dsquery.SetGeoTransform((0.0, tilesize / float(querysize), 0.0, 0.0, 0.0,
+                                     tilesize / float(querysize)))
+            dstile.SetGeoTransform((0.0, 1.0, 0.0, 0.0, 0.0, 1.0))
 
             res = gdal.ReprojectImage(dsquery, dstile, None, None, self.resampling)
             if res != 0:
                 self.error("ReprojectImage() failed on %s, error %d" % (tilefilename, res))
 
-    # -------------------------------------------------------------------------
     def generate_tilemapresource(self):
         """
         Template for tilemapresource.xml. Returns filled string. Expected variables:
@@ -1549,37 +1606,42 @@ gdal2tiles temp.vrt""" % self.input )
       <Origin x="%(west).14f" y="%(south).14f"/>
       <TileFormat width="%(tilesize)d" height="%(tilesize)d" mime-type="image/%(tileformat)s" extension="%(tileformat)s"/>
       <TileSets profile="%(profile)s">
-""" % args
+""" % args    # noqa
         for z in range(self.tminz, self.tmaxz+1):
             if self.options.profile == 'raster':
-                s += """        <TileSet href="%s%d" units-per-pixel="%.14f" order="%d"/>\n""" % (args['publishurl'], z, (2**(self.nativezoom-z) * self.out_gt[1]), z)
+                s += """        <TileSet href="%s%d" units-per-pixel="%.14f" order="%d"/>\n""" % (
+                    args['publishurl'], z, (2**(self.nativezoom-z) * self.out_gt[1]), z)
             elif self.options.profile == 'mercator':
-                s += """        <TileSet href="%s%d" units-per-pixel="%.14f" order="%d"/>\n""" % (args['publishurl'], z, 156543.0339/2**z, z)
+                s += """        <TileSet href="%s%d" units-per-pixel="%.14f" order="%d"/>\n""" % (
+                    args['publishurl'], z, 156543.0339/2**z, z)
             elif self.options.profile == 'geodetic':
-                s += """        <TileSet href="%s%d" units-per-pixel="%.14f" order="%d"/>\n""" % (args['publishurl'], z, 0.703125/2**z, z)
+                s += """        <TileSet href="%s%d" units-per-pixel="%.14f" order="%d"/>\n""" % (
+                    args['publishurl'], z, 0.703125/2**z, z)
         s += """      </TileSets>
     </TileMap>
     """
         return s
 
-    # -------------------------------------------------------------------------
-    def generate_kml(self, tx, ty, tz, children = [], **args ):
+    def generate_kml(self, tx, ty, tz, children=None, **args):
         """
         Template for the KML. Returns filled string.
         """
+        if not children:
+            children = []
+
         args['tx'], args['ty'], args['tz'] = tx, ty, tz
         args['tileformat'] = self.tileext
         if 'tilesize' not in args:
             args['tilesize'] = self.tilesize
 
         if 'minlodpixels' not in args:
-            args['minlodpixels'] = int( args['tilesize'] / 2 ) # / 2.56) # default 128
+            args['minlodpixels'] = int(args['tilesize'] / 2)
         if 'maxlodpixels' not in args:
-            args['maxlodpixels'] = int( args['tilesize'] * 8 ) # 1.7) # default 2048 (used to be -1)
+            args['maxlodpixels'] = int(args['tilesize'] * 8)
         if children == []:
             args['maxlodpixels'] = -1
 
-        if tx==None:
+        if tx is None:
             tilekml = False
             args['title'] = self.options.title
         else:
@@ -1589,7 +1651,7 @@ gdal2tiles temp.vrt""" % self.input )
 
         if tx == 0:
             args['drawOrder'] = 2 * tz + 1
-        elif tx != None:
+        elif tx is not None:
             args['drawOrder'] = 2 * tz
         else:
             args['drawOrder'] = 0
@@ -1662,19 +1724,20 @@ gdal2tiles temp.vrt""" % self.input )
             <viewFormat/>
           </Link>
         </NetworkLink>
-    """ % (cz, cx, cy, args['tileformat'], cnorth, csouth, ceast, cwest, args['minlodpixels'], url, cz, cx, cy)
+            """ % (cz, cx, cy, args['tileformat'], cnorth, csouth, ceast, cwest,
+                   args['minlodpixels'], url, cz, cx, cy)
 
         s += """      </Document>
     </kml>
-    """
+        """
         return s
 
-    # -------------------------------------------------------------------------
     def generate_googlemaps(self):
         """
         Template for googlemaps.html implementing Overlay of tiles for 'mercator' profile.
         It returns filled string. Expected variables:
-        title, googlemapskey, north, south, east, west, minzoom, maxzoom, tilesize, tileformat, publishurl
+        title, googlemapskey, north, south, east, west, minzoom, maxzoom, tilesize, tileformat,
+        publishurl
         """
         args = {}
         args['title'] = self.options.title
@@ -1687,7 +1750,7 @@ gdal2tiles temp.vrt""" % self.input )
         args['publishurl'] = self.options.url
         args['copyright'] = self.options.copyright
 
-        s = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+        s = r"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
             <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
               <head>
                 <title>%(title)s</title>
@@ -1910,7 +1973,7 @@ gdal2tiles temp.vrt""" % self.input )
                       map.addControl(new GLargeMapControl());
                       map.addControl(new GHierarchicalMapTypeControl());
                       map.addControl(new CTransparencyControl( overlay ));
-        """ % args
+        """ % args    # noqa
         if self.kml:
             s += """
                       map.addMapType(G_SATELLITE_3D_MAP);
@@ -1947,7 +2010,7 @@ gdal2tiles temp.vrt""" % self.input )
                        // add div with the link to generated KML... - maybe JavaScript redirect to the URL of KML?
                    }
                 }
-        """ % args
+        """ % args    # noqa
         s += """
                 onresize=function(){ resize(); };
 
@@ -1962,12 +2025,10 @@ gdal2tiles temp.vrt""" % self.input )
                    <div id="map"></div>
               </body>
             </html>
-        """ % args
+        """ % args    # noqa
 
         return s
 
-
-    # -------------------------------------------------------------------------
     def generate_leaflet(self):
         """
         Template for leaflet.html implementing overlay of tiles for 'mercator' profile.
@@ -2061,12 +2122,12 @@ gdal2tiles temp.vrt""" % self.input )
         // Title
         var title = L.control();
         title.onAdd = function(map) {
-	        this._div = L.DomUtil.create('div', 'ctl title');
-	        this.update();
-	        return this._div;
+            this._div = L.DomUtil.create('div', 'ctl title');
+            this.update();
+            return this._div;
         };
         title.update = function(props) {
-	        this._div.innerHTML = "%(title)s";
+            this._div.innerHTML = "%(title)s";
         };
         title.addTo(map);
 
@@ -2074,12 +2135,12 @@ gdal2tiles temp.vrt""" % self.input )
         var src = 'Generated by <a href="http://www.klokan.cz/projects/gdal2tiles/">GDAL2Tiles</a>, Copyright © 2008 <a href="http://www.klokan.cz/">Klokan Petr Pridal</a>,  <a href="http://www.gdal.org/">GDAL</a> & <a href="http://www.osgeo.org/">OSGeo</a> <a href="http://code.google.com/soc/">GSoC</a>';
         var title = L.control({position: 'bottomleft'});
         title.onAdd = function(map) {
-	        this._div = L.DomUtil.create('div', 'ctl src');
-	        this.update();
-	        return this._div;
+            this._div = L.DomUtil.create('div', 'ctl src');
+            this.update();
+            return this._div;
         };
         title.update = function(props) {
-	        this._div.innerHTML = src;
+            this._div.innerHTML = src;
         };
         title.addTo(map);
 
@@ -2095,13 +2156,11 @@ gdal2tiles temp.vrt""" % self.input )
         </body>
         </html>
 
-        """ % args
+        """ % args    # noqa
 
         return s
 
-
-    # -------------------------------------------------------------------------
-    def generate_openlayers( self ):
+    def generate_openlayers(self):
         """
         Template for openlayers.html implementing overlay of available Spherical Mercator layers.
 
@@ -2127,7 +2186,7 @@ gdal2tiles temp.vrt""" % self.input )
             args['rasterzoomlevels'] = self.tmaxz+1
             args['rastermaxresolution'] = 2**(self.nativezoom) * self.out_gt[1]
 
-        s = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+        s = r"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
         <html xmlns="http://www.w3.org/1999/xhtml"
           <head>
             <title>%(title)s</title>
@@ -2141,11 +2200,12 @@ gdal2tiles temp.vrt""" % self.input )
             #map { height: 95%%; border: 1px solid #888; }
             .olImageLoadError { display: none; }
             .olControlLayerSwitcher .layersDiv { border-radius: 10px 0 0 10px; }
-        </style>""" % args
+        </style>""" % args    # noqa
 
         if self.options.profile == 'mercator':
-          s += """
-            <script src='http://maps.google.com/maps/api/js?sensor=false&v=3.7'></script>""" % args
+            s += """
+            <script src='http://maps.google.com/maps/api/js?sensor=false&v=3.7'></script>
+            """ % args
 
         s += """
             <script src="http://www.openlayers.org/api/2.12/OpenLayers.js"></script>
@@ -2160,7 +2220,7 @@ gdal2tiles temp.vrt""" % self.input )
               function init(){""" % args
 
         if self.options.profile == 'mercator':
-          s += """
+            s += """
                   var options = {
                       div: "map",
                       controls: [],
@@ -2238,10 +2298,10 @@ gdal2tiles temp.vrt""" % self.input )
                   switcherControl.maximizeControl();
 
                   map.zoomToExtent(mapBounds.transform(map.displayProjection, map.projection));
-          """ % args
+          """ % args    # noqa
 
         elif self.options.profile == 'geodetic':
-          s += """
+            s += """
                   var options = {
                       div: "map",
                       controls: [],
@@ -2276,10 +2336,10 @@ gdal2tiles temp.vrt""" % self.input )
                   switcherControl.maximizeControl();
 
                   map.zoomToExtent(mapBounds);
-           """ % args
+           """ % args   # noqa
 
         elif self.options.profile == 'raster':
-          s += """
+            s += """
                   var options = {
                       div: "map",
                       controls: [],
@@ -2300,8 +2360,7 @@ gdal2tiles temp.vrt""" % self.input )
 
                   map.addLayer(layer);
                   map.zoomToExtent(mapBounds);
-        """ % args
-
+        """ % args    # noqa
 
         s += """
                   map.addControls([new OpenLayers.Control.PanZoomBar(),
@@ -2310,10 +2369,10 @@ gdal2tiles temp.vrt""" % self.input )
                                    new OpenLayers.Control.ArgParser(),
                                    new OpenLayers.Control.Attribution()]);
               }
-          """ % args
+        """ % args
 
         if self.options.profile == 'mercator':
-          s += """
+            s += """
               function getURL(bounds) {
                   bounds = this.adjustBounds(bounds);
                   var res = this.getServerResolution();
@@ -2334,10 +2393,10 @@ gdal2tiles temp.vrt""" % self.input )
                       return emptyTileURL;
                   }
               }
-          """ % args
+            """ % args    # noqa
 
         elif self.options.profile == 'geodetic':
-          s += """
+            s += """
               function getURL(bounds) {
                   bounds = this.adjustBounds(bounds);
                   var res = this.getServerResolution();
@@ -2355,10 +2414,10 @@ gdal2tiles temp.vrt""" % self.input )
                       return emptyTileURL;
                   }
               }
-          """ % args
+            """ % args    # noqa
 
         elif self.options.profile == 'raster':
-          s += """
+            s += """
               function getURL(bounds) {
                   bounds = this.adjustBounds(bounds);
                   var res = this.getServerResolution();
@@ -2376,7 +2435,7 @@ gdal2tiles temp.vrt""" % self.input )
                       return emptyTileURL;
                   }
               }
-          """ % args
+            """ % args    # noqa
 
         s += """
            function getWindowHeight() {
@@ -2418,19 +2477,18 @@ gdal2tiles temp.vrt""" % self.input )
                 <div id="map"></div>
                 <script type="text/javascript" >resize()</script>
               </body>
-            </html>""" % args
+            </html>""" % args   # noqa
 
         return s
 
-# =============================================================================
-# =============================================================================
-# =============================================================================
 
 def main():
-    argv = gdal.GeneralCmdLineProcessor( sys.argv )
+    argv = gdal.GeneralCmdLineProcessor(sys.argv)
     if argv:
-        gdal2tiles = GDAL2Tiles( argv[1:] )
+        gdal2tiles = GDAL2Tiles(argv[1:])
         gdal2tiles.process()
 
-if __name__=='__main__':
+if __name__ == '__main__':
     main()
+
+# vim: set tabstop=4 shiftwidth=4 expandtab:
diff --git a/swig/python/scripts/gdal2xyz.py b/swig/python/scripts/gdal2xyz.py
index d271376..cd307b7 100755
--- a/swig/python/scripts/gdal2xyz.py
+++ b/swig/python/scripts/gdal2xyz.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-# $Id: gdal2xyz.py 35367 2016-09-08 09:30:10Z rouault $
+# $Id: gdal2xyz.py 35366 2016-09-08 09:29:24Z rouault $
 #
 # Project:  GDAL
 # Purpose:  Script to translate GDAL supported raster into XYZ ASCII
diff --git a/swig/python/scripts/gdal_calc.dox b/swig/python/scripts/gdal_calc.dox
index 7bac888..f0525d8 100644
--- a/swig/python/scripts/gdal_calc.dox
+++ b/swig/python/scripts/gdal_calc.dox
@@ -1,42 +1,46 @@
 
-/*! \page gdal_calc gdal_calc.py
+/*!
+\if man
+\page gdal_calc
+\else
+\page gdal_calc gdal_calc.py
+\endif
 
-Command line raster calculator with numpy syntax
+Command line raster calculator with numpy syntax.
 
 \section gdal_calc_synopsis SYNOPSIS
 
 \verbatim
-gdal_calc.py [-A <filename>] [--A_band] [-B...-Z filename] [other_options]
+gdal_calc.py --calc=expression --outfile=out_filename [-A filename]
+             [--A_band=n] [-B...-Z filename] [other_options]
 
 Options:
   -h, --help            show this help message and exit
-  --calc=CALC           calculation in gdalnumeric syntax using +-/* or any
-                        numpy array functions (i.e. logical_and())
-  -A A                  input gdal raster file, note you can use any letter
-                        A-Z
-  --A_band=A_BAND       number of raster band for file A (default 1)
-  --outfile=OUTF        output file to generate or fill
-  --NoDataValue=NODATAVALUE
-                        set output nodata value (Defaults to datatype specific
-                        value)
-  --type=TYPE           output datatype, must be one of ['Int32', 'Int16',
+  --calc=expression     calculation in gdalnumeric syntax using +-/* or any
+                        numpy array functions (i.e. log10())
+  -A filename           input gdal raster file, you can use any letter (A-Z)
+  --A_band=n            number of raster band for file A (default 1)
+  --outfile=filename    output file to generate or fill
+  --NoDataValue=value   output nodata value (default datatype specific value)
+  --type=datatype       output datatype, must be one of ['Int32', 'Int16',
                         'Float64', 'UInt16', 'Byte', 'UInt32', 'Float32']
-  --format=FORMAT       GDAL format for output file (default 'GTiff')
-  --creation-option=CREATION_OPTIONS, --co=CREATION_OPTIONS
+  --format=gdal_format  GDAL format for output file (default 'GTiff')
+  --creation-option=option, --co=option
                         Passes a creation option to the output format driver.
                         Multiple options may be listed. See format specific
                         documentation for legal creation options for each
                         format.
-  --allBands=ALLBANDS   process all bands of given raster (A-Z)
+  --allBands=[A-Z]      process all bands of given raster (A-Z)
   --overwrite           overwrite output file if it already exists
   --debug               print debugging information
+  --quiet               suppress progress messages
 \endverbatim
 
-\section gdal_edit_description DESCRIPTION
+\section gdal_calc_description DESCRIPTION
 
 Command line raster calculator with numpy syntax. Use any basic arithmetic supported by numpy arrays such as +-*\ along with logical operators such as >.  Note that all files must have the same dimensions, but no projection checking is performed.
 
-\section gdal_edit_example EXAMPLE
+\section gdal_calc_example EXAMPLE
 
 add two files together
 \verbatim
@@ -54,9 +58,9 @@ gdal_calc.py -A input.tif --outfile=result.tif --calc="A*(A>0)" --NoDataValue=0
 \endverbatim
 
 \if man
-\section gdal_edit_author AUTHORS
-Chris Yesson <chris dot yesson at ioz dot ac dot uk>
-Etienne Tourigny <etourigny dot dev at gmail dot com>
+\section gdal_calc_author AUTHORS
+Chris Yesson <chris dot yesson at ioz dot ac dot uk>
+Etienne Tourigny <etourigny dot dev at gmail dot com>
 \endif
 */
 
diff --git a/swig/python/scripts/gdal_calc.py b/swig/python/scripts/gdal_calc.py
index eaf0e01..0a2286f 100755
--- a/swig/python/scripts/gdal_calc.py
+++ b/swig/python/scripts/gdal_calc.py
@@ -9,6 +9,7 @@
 #******************************************************************************
 #  Copyright (c) 2010, Chris Yesson <chris.yesson at ioz.ac.uk>
 #  Copyright (c) 2010-2011, Even Rouault <even dot rouault at mines-paris dot org>
+#  Copyright (c) 2016, Piers Titus van der Torren <pierstitus at gmail.com>
 #
 #  Permission is hereby granted, free of charge, to any person obtaining a
 #  copy of this software and associated documentation files (the "Software"),
@@ -42,7 +43,7 @@
 # gdal_calc.py -A input.tif --outfile=result.tif --calc="A*(A>0)" --NoDataValue=0
 ################################################################
 
-from optparse import OptionParser
+from optparse import OptionParser, Values
 import os
 import sys
 
@@ -57,9 +58,7 @@ AlphaList=["A","B","C","D","E","F","G","H","I","J","K","L","M",
            "N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
 
 # set up some default nodatavalues for each datatype
-DefaultNDVLookup={'Byte':255, 'UInt16':65535, 'Int16':-32767, 'UInt32':4294967293, 'Int32':-2147483647, 'Float32':1.175494351E-38, 'Float64':1.7976931348623158E+308}
-
-#3.402823466E+38
+DefaultNDVLookup={'Byte':255, 'UInt16':65535, 'Int16':-32767, 'UInt32':4294967293, 'Int32':-2147483647, 'Float32':3.402823466E+38, 'Float64':1.7976931348623158E+308}
 
 ################################################################
 def doit(opts, args):
@@ -71,6 +70,11 @@ def doit(opts, args):
     global_namespace = dict([(key, getattr(gdalnumeric, key))
         for key in dir(gdalnumeric) if not key.startswith('__')])
 
+    if not opts.calc:
+        raise Exception("No calculation provided.")
+    elif not opts.outF:
+        raise Exception("No output file provided.")
+
     ################################################################
     # fetch details of input layers
     ################################################################
@@ -85,31 +89,34 @@ def doit(opts, args):
     DimensionsCheck=None
 
     # loop through input files - checking dimensions
-    for i,myI in enumerate(AlphaList[0:len(sys.argv)-1]):
-        myF = eval("opts.%s" %(myI))
-        myBand = eval("opts.%s_band" %(myI))
-        if myF:
-            myFiles.append(gdal.Open(myF, gdal.GA_ReadOnly))
+    for myI, myF in opts.input_files.items():
+        if not myI.endswith("_band"):
             # check if we have asked for a specific band...
-            if myBand:
-                myBands.append(myBand)
+            if "%s_band" % myI in opts.input_files:
+                myBand = opts.input_files["%s_band" % myI]
             else:
-                myBands.append(1)
+                myBand = 1
+
+            myFile = gdal.Open(myF, gdal.GA_ReadOnly)
+            if not myFile:
+                raise IOError("No such file or directory: '%s'" % myF)
+
+            myFiles.append(myFile)
+            myBands.append(myBand)
             myAlphaList.append(myI)
-            myDataType.append(gdal.GetDataTypeName(myFiles[i].GetRasterBand(myBands[i]).DataType))
-            myDataTypeNum.append(myFiles[i].GetRasterBand(myBands[i]).DataType)
-            myNDV.append(myFiles[i].GetRasterBand(myBands[i]).GetNoDataValue())
+            myDataType.append(gdal.GetDataTypeName(myFile.GetRasterBand(myBand).DataType))
+            myDataTypeNum.append(myFile.GetRasterBand(myBand).DataType)
+            myNDV.append(myFile.GetRasterBand(myBand).GetNoDataValue())
             # check that the dimensions of each layer are the same
             if DimensionsCheck:
-                if DimensionsCheck!=[myFiles[i].RasterXSize, myFiles[i].RasterYSize]:
-                    print("Error! Dimensions of file %s (%i, %i) are different from other files (%i, %i).  Cannot proceed" % \
-                            (myF,myFiles[i].RasterXSize, myFiles[i].RasterYSize,DimensionsCheck[0],DimensionsCheck[1]))
-                    return
+                if DimensionsCheck != [myFile.RasterXSize, myFile.RasterYSize]:
+                    raise Exception("Error! Dimensions of file %s (%i, %i) are different from other files (%i, %i).  Cannot proceed" % \
+                            (myF, myFile.RasterXSize, myFile.RasterYSize, DimensionsCheck[0], DimensionsCheck[1]))
             else:
-                DimensionsCheck=[myFiles[i].RasterXSize, myFiles[i].RasterYSize]
+                DimensionsCheck = [myFile.RasterXSize, myFile.RasterYSize]
 
             if opts.debug:
-                print("file %s: %s, dimensions: %s, %s, type: %s" %(myI,myF,DimensionsCheck[0],DimensionsCheck[1],myDataType[i]))
+                print("file %s: %s, dimensions: %s, %s, type: %s" %(myI,myF,DimensionsCheck[0],DimensionsCheck[1],myDataType[-1]))
 
     # process allBands option
     allBandsIndex=None
@@ -118,8 +125,7 @@ def doit(opts, args):
         try:
             allBandsIndex=myAlphaList.index(opts.allBands)
         except ValueError:
-            print("Error! allBands option was given but Band %s not found.  Cannot proceed" % (opts.allBands))
-            return
+            raise Exception("Error! allBands option was given but Band %s not found.  Cannot proceed" % (opts.allBands))
         allBandsCount=myFiles[allBandsIndex].RasterCount
         if allBandsCount <= 1:
             allBandsIndex=None
@@ -131,14 +137,12 @@ def doit(opts, args):
     # open output file exists
     if os.path.isfile(opts.outF) and not opts.overwrite:
         if allBandsIndex is not None:
-            print("Error! allBands option was given but Output file exists, must use --overwrite option!")
-            return
+            raise Exception("Error! allBands option was given but Output file exists, must use --overwrite option!")
         if opts.debug:
             print("Output file %s exists - filling in results into file" %(opts.outF))
         myOut=gdal.Open(opts.outF, gdal.GA_Update)
         if [myOut.RasterXSize,myOut.RasterYSize] != DimensionsCheck:
-            print("Error! Output exists, but is the wrong size.  Use the --overwrite option to automatically overwrite the existing file")
-            return
+            raise Exception("Error! Output exists, but is the wrong size.  Use the --overwrite option to automatically overwrite the existing file")
         myOutB=myOut.GetRasterBand(1)
         myOutNDV=myOutB.GetNoDataValue()
         myOutType=gdal.GetDataTypeName(myOutB.DataType)
@@ -233,7 +237,7 @@ def doit(opts, args):
             # loop through Y lines
             for Y in range(0,nYBlocks):
                 ProgressCt+=1
-                if 10*ProgressCt/ProgressEnd%10!=ProgressMk:
+                if 10*ProgressCt/ProgressEnd%10!=ProgressMk and not opts.quiet:
                     ProgressMk=10*ProgressCt/ProgressEnd%10
                     from sys import version_info
                     if version_info >= (3,0,0):
@@ -250,10 +254,9 @@ def doit(opts, args):
                 myY=Y*myBlockSize[1]
 
                 # create empty buffer to mark where nodata occurs
-                myNDVs=numpy.zeros(myBufSize)
-                myNDVs.shape=(nYValid,nXValid)
+                myNDVs = None
 
-                # modules available to calculation
+                # make local namespace for calculation
                 local_namespace = {}
 
                 # fetch data for each input layer
@@ -269,7 +272,11 @@ def doit(opts, args):
                                           win_xsize=nXValid, win_ysize=nYValid)
 
                     # fill in nodata values
-                    myNDVs=1*numpy.logical_or(myNDVs==1, myval==myNDV[i])
+                    if myNDV[i] is not None:
+                        if myNDVs is None:
+                            myNDVs = numpy.zeros(myBufSize)
+                            myNDVs.shape=(nYValid,nXValid)
+                        myNDVs=1*numpy.logical_or(myNDVs==1, myval==myNDV[i])
 
                     # add an array of values for this block to the eval namespace
                     local_namespace[Alpha] = myval
@@ -285,51 +292,110 @@ def doit(opts, args):
 
                 # Propagate nodata values (set nodata cells to zero
                 # then add nodata value to these cells).
-                myResult = ((1*(myNDVs==0))*myResult) + (myOutNDV*myNDVs)
+                if myNDVs is not None:
+                    myResult = ((1*(myNDVs==0))*myResult) + (myOutNDV*myNDVs)
+                elif not isinstance(myResult, numpy.ndarray):
+                    myResult = numpy.ones( (nYValid,nXValid) ) * myResult
 
                 # write data block to the output file
                 myOutB=myOut.GetRasterBand(bandNo)
                 gdalnumeric.BandWriteArray(myOutB, myResult, xoff=myX, yoff=myY)
 
-    print("100 - Done")
+    if not opts.quiet:
+        print("100 - Done")
     #print("Finished - Results written to %s" %opts.outF)
 
     return
 
 ################################################################
+def Calc(calc, outfile, NoDataValue=None, type=None, format='GTiff', creation_options=[], allBands='', overwrite=False, debug=False, quiet=False, **input_files):
+    """ Perform raster calculations with numpy syntax.
+    Use any basic arithmetic supported by numpy arrays such as +-*\ along with logical
+    operators such as >. Note that all files must have the same dimensions, but no projection checking is performed.
+
+    Keyword arguments:
+        [A-Z]: input files
+        [A_band - Z_band]: band to use for respective input file
+
+    Examples:
+    add two files together:
+        Calc("A+B", A="input1.tif", B="input2.tif", outfile="result.tif")
+
+    average of two layers:
+        Calc(calc="(A+B)/2", A="input1.tif", B="input2.tif", outfile="result.tif")
+
+    set values of zero and below to null:
+        Calc(calc="A*(A>0)", A="input.tif", A_Band=2, outfile="result.tif", NoDataValue=0)
+    """
+    opts = Values()
+    opts.input_files = input_files
+    opts.calc = calc
+    opts.outF = outfile
+    opts.NoDataValue = NoDataValue
+    opts.type = type
+    opts.format = format
+    opts.creation_options = creation_options
+    opts.allBands = allBands
+    opts.overwrite = overwrite
+    opts.debug = debug
+    opts.quiet = quiet
+
+    doit(opts, None)
+
+def store_input_file(option, opt_str, value, parser):
+    if not hasattr(parser.values, 'input_files'):
+        parser.values.input_files = {}
+    parser.values.input_files[opt_str.lstrip('-')] = value
+
 def main():
-    usage = "usage: %prog [-A <filename>] [--A_band=n] [-B...-Z filename] [other_options]"
+    usage = """usage: %prog --calc=expression --outfile=out_filename [-A filename]
+                    [--A_band=n] [-B...-Z filename] [other_options]"""
     parser = OptionParser(usage)
 
     # define options
-    parser.add_option("--calc", dest="calc", help="calculation in gdalnumeric syntax using +-/* or any numpy array functions (i.e. logical_and())")
-    # hack to limit the number of input file options close to required number
-    for myAlpha in AlphaList[0:len(sys.argv)-1]:
-        eval('parser.add_option("-%s", dest="%s", help="input gdal raster file, note you can use any letter A-Z")' %(myAlpha, myAlpha))
-        eval('parser.add_option("--%s_band", dest="%s_band", default=1, type=int, help="number of raster band for file %s (default 1)")' %(myAlpha, myAlpha, myAlpha))
-
-    parser.add_option("--outfile", dest="outF", default='gdal_calc.tif', help="output file to generate or fill")
-    parser.add_option("--NoDataValue", dest="NoDataValue", type=float, help="set output nodata value (Defaults to datatype specific value)")
-    parser.add_option("--type", dest="type", help="output datatype, must be one of %s" % list(DefaultNDVLookup.keys()))
-    parser.add_option("--format", dest="format", default="GTiff", help="GDAL format for output file (default 'GTiff')")
+    parser.add_option("--calc", dest="calc", help="calculation in gdalnumeric syntax using +-/* or any numpy array functions (i.e. log10())", metavar="expression")
+    # limit the input file options to the ones in the argument list
+    given_args = set([a[1] for a in sys.argv if a[1:2] in AlphaList] + ['A'])
+    for myAlpha in given_args:
+        parser.add_option("-%s" % myAlpha, action="callback", callback=store_input_file, type=str, help="input gdal raster file, you can use any letter (A-Z)", metavar='filename')
+        parser.add_option("--%s_band" % myAlpha, action="callback", callback=store_input_file, type=int, help="number of raster band for file %s (default 1)" % myAlpha, metavar='n')
+
+    parser.add_option("--outfile", dest="outF", help="output file to generate or fill", metavar="filename")
+    parser.add_option("--NoDataValue", dest="NoDataValue", type=float, help="output nodata value (default datatype specific value)", metavar="value")
+    parser.add_option("--type", dest="type", help="output datatype, must be one of %s" % list(DefaultNDVLookup.keys()), metavar="datatype")
+    parser.add_option("--format", dest="format", default="GTiff", help="GDAL format for output file (default 'GTiff')", metavar="gdal_format")
     parser.add_option(
         "--creation-option", "--co", dest="creation_options", default=[], action="append",
         help="Passes a creation option to the output format driver. Multiple "
         "options may be listed. See format specific documentation for legal "
-        "creation options for each format.")
-    parser.add_option("--allBands", dest="allBands", default="", help="process all bands of given raster (A-Z)")
+        "creation options for each format.", metavar="option")
+    parser.add_option("--allBands", dest="allBands", default="", help="process all bands of given raster (A-Z)", metavar="[A-Z]")
     parser.add_option("--overwrite", dest="overwrite", action="store_true", help="overwrite output file if it already exists")
     parser.add_option("--debug", dest="debug", action="store_true", help="print debugging information")
+    parser.add_option("--quiet", dest="quiet", action="store_true", help="suppress progress messages")
 
     (opts, args) = parser.parse_args()
+    if not hasattr(opts, "input_files"):
+        opts.input_files = {}
 
     if len(sys.argv) == 1:
         parser.print_help()
+        sys.exit(1)
     elif not opts.calc:
-        print("No calculation provided.  Nothing to do!")
+        print("No calculation provided. Nothing to do!")
+        parser.print_help()
+        sys.exit(1)
+    elif not opts.outF:
+        print("No output file provided. Cannot proceed.")
         parser.print_help()
+        sys.exit(1)
     else:
-        doit(opts, args)
+        try:
+            doit(opts, args)
+        except IOError as e:
+            print(e)
+            sys.exit(1)
+
 
 if __name__ == "__main__":
     main()
diff --git a/swig/python/scripts/gdal_edit.dox b/swig/python/scripts/gdal_edit.dox
index 4a0c886..674812f 100644
--- a/swig/python/scripts/gdal_edit.dox
+++ b/swig/python/scripts/gdal_edit.dox
@@ -1,7 +1,12 @@
 
-/*! \page gdal_edit gdal_edit.py
+/*!
+\if man
+\page gdal_edit
+\else
+\page gdal_edit gdal_edit.py
+\endif
 
-Edit in place various information of an existing GDAL dataset
+Edit in place various information of an existing GDAL dataset.
 
 \section gdal_edit_synopsis SYNOPSIS
 
@@ -9,6 +14,7 @@ Edit in place various information of an existing GDAL dataset
 gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]
           [-tr xres yres] [-unsetgt] [-a_nodata value] [-unsetnodata]
           [-unsetstats] [-stats] [-approx_stats]
+          [-scale value] [-offset value]
           [-gcp pixel line easting northing [elevation]]*
           [-unsetmd] [-oo NAME=VALUE]* [-mo "META-TAG=VALUE"]*  datasetname
 \endverbatim
@@ -20,10 +26,16 @@ of an existing GDAL dataset (projection, geotransform, nodata, metadata).
 
 It works only with raster formats that support update access to
 existing datasets.
+
+CAUTION: depending on the format, older values of the updated information might
+still be found in the file in a "ghost" state, even if no longer accessible
+through the GDAL API. This is for example the case of the GTiff format (this is
+not a exhaustive list)
+
 <dl>
 
 <dt> <b>--help-general</b></dt>:<dd>
-Gives a brief usage message for the generic GDAL commandline options 
+Gives a brief usage message for the generic GDAL commandline options
 and exit.
 </dd>
 
@@ -35,7 +47,9 @@ into PAM .aux.xml files.</dd>
 <dt> <b>-a_srs</b> <i>srs_def</i>:</dt><dd>
 
 Defines the target coordinate system.  This coordinate system will be
-written to the dataset.
+written to the dataset. If the empty string or None is specified, then the
+existing coordinate system will be removed (for TIFF/GeoTIFF, might not be
+well supported besides that).
 
 <dt> <b>-a_ullr</b> <i>ulx uly lrx lry</i>:</dt><dd>
 Assign/override the georeferenced bounds of the dataset.</dd>
@@ -62,9 +76,22 @@ Assign a specified nodata value to output bands.</dd>
 <dt> <b>-unsetnodata</b></dt>:<dd> (GDAL >= 2.1)
 Remove existing nodata values.</dd>
 
+<dt> <b>-scale</b> <i>value</i>:</dt><dd> (GDAL >= 2.2)
+Assign a specified scale value to output bands. If no scale is needed, it
+it recommended to set the value to 1. Scale and Offset are generally used
+together. For example, scale and offset might be used to store elevations in 
+a unsigned 16bit integer file with a precision of 0.1, and starting from -100.
+True values would be calculated as: 
+true_value = (pixel_value * scale) + offset 
+Note: these values can be applied using -unscale during a gdal_translate run.</dd> 
+
+<dt> <b>-offset</b> <i>value</i>:</dt><dd> (GDAL >= 2.2)
+Assign a specified offset value to output bands. If no offset is needed, it
+recommended to set the value to 0. For more see scale.</dd> 
+
 <dt> <b>-gcp</b> <i>pixel line easting northing [elevation]</i>:</dt><dd>
-Add the indicated ground control point to the dataset.  This option 
-may be provided multiple times to provide a set of GCPs. 
+Add the indicated ground control point to the dataset.  This option
+may be provided multiple times to provide a set of GCPs.
 </dd>
 
 <dt> <b>-unsetmd</b></dt>:<dd> (GDAL >= 2.0)
@@ -75,7 +102,7 @@ with -mo.</dd>
 value to set on the output dataset if possible. This metadata is added to
 the existing metadata items, unless -unsetmd is also specified.</dd>
 
-<dt> <b>-oo</b> <i>"NAME=VALUE"</i>:</dt><dd> 
+<dt> <b>-oo</b> <i>"NAME=VALUE"</i>:</dt><dd>
 (GDAL >= 2.0) Open option (format specific).</dd>
 
 </dl>
@@ -92,7 +119,7 @@ gdal_edit -mo DATUM=WGS84 -mo PROJ=GEODETIC -a_ullr 7 47 8 46 test.ecw
 
 \if man
 \section gdal_edit_author AUTHORS
-Even Rouault <even dot rouault at mines dash paris dot org>
+Even Rouault <even dot rouault at mines dash paris dot org>
 \endif
 */
 
diff --git a/swig/python/scripts/gdal_edit.py b/swig/python/scripts/gdal_edit.py
index 8dbfa0a..1684b61 100755
--- a/swig/python/scripts/gdal_edit.py
+++ b/swig/python/scripts/gdal_edit.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 ###############################################################################
-# $Id: gdal_edit.py 32555 2015-12-30 19:26:44Z goatbar $
+# $Id: gdal_edit.py 37709 2017-03-14 14:52:15Z rouault $
 #
 #  Project:  GDAL samples
 #  Purpose:  Edit in place various information of an existing GDAL dataset
@@ -37,6 +37,7 @@ from osgeo import osr
 def Usage():
     print('Usage: gdal_edit [--help-general] [-ro] [-a_srs srs_def] [-a_ullr ulx uly lrx lry]')
     print('                 [-tr xres yres] [-unsetgt] [-a_nodata value] [-unsetnodata]')
+    print('                 [-offset value] [-scale value]')
     print('                 [-unsetstats] [-stats] [-approx_stats]')
     print('                 [-gcp pixel line easting northing [elevation]]*')
     print('                 [-unsetmd] [-oo NAME=VALUE]* [-mo "META-TAG=VALUE"]*  datasetname')
@@ -80,6 +81,8 @@ def gdal_edit(argv):
     molist = []
     gcp_list = []
     open_options = []
+    offset = None
+    scale = None
 
     i = 1
     argc = len(argv)
@@ -106,6 +109,12 @@ def gdal_edit(argv):
         elif argv[i] == '-a_nodata' and i < len(argv)-1:
             nodata = float(argv[i+1])
             i = i + 1
+        elif argv[i] == '-scale' and i < len(argv)-1:
+            scale = float(argv[i+1])
+            i = i + 1
+        elif argv[i] == '-offset' and i < len(argv)-1:
+            offset = float(argv[i+1])
+            i = i + 1
         elif argv[i] == '-mo' and i < len(argv)-1:
             molist.append(argv[i+1])
             i = i + 1
@@ -157,7 +166,9 @@ def gdal_edit(argv):
 
     if (srs is None and lry is None and yres is None and not unsetgt
             and not unsetstats and not stats and nodata is None
-            and len(molist) == 0 and not unsetmd and len(gcp_list) == 0 and not unsetnodata):
+            and len(molist) == 0 and not unsetmd and len(gcp_list) == 0
+            and not unsetnodata
+            and scale is None and offset is None):
         print('No option specified')
         print('')
         return Usage()
@@ -239,6 +250,14 @@ def gdal_edit(argv):
         for i in range(ds.RasterCount):
             ds.GetRasterBand(i+1).DeleteNoDataValue()
 
+    if scale is not None:
+        for i in range(ds.RasterCount):
+            ds.GetRasterBand(i+1).SetScale(scale)
+
+    if offset is not None:
+       for i in range(ds.RasterCount):
+           ds.GetRasterBand(i+1).SetOffset(offset)
+ 
     if unsetstats:
         for i in range(ds.RasterCount):
             band = ds.GetRasterBand(i+1)
diff --git a/swig/python/scripts/gdal_fillnodata.dox b/swig/python/scripts/gdal_fillnodata.dox
index 4f3cf6c..fb9c0c7 100644
--- a/swig/python/scripts/gdal_fillnodata.dox
+++ b/swig/python/scripts/gdal_fillnodata.dox
@@ -1,7 +1,12 @@
 
-/*! \page gdal_fillnodata gdal_fillnodata.py
+/*!
+\if man
+\page gdal_fillnodata
+\else
+\page gdal_fillnodata gdal_fillnodata.py
+\endif
 
-fill raster regions by interpolation from edges
+Fill raster regions by interpolation from edges.
 
 \section gdal_fillnodata_synopsis SYNOPSIS
 
@@ -14,9 +19,9 @@ gdal_fillnodata.py [-q] [-md max_distance] [-si smooth_iterations]
 \section gdal_fillnodata_description DESCRIPTION
 
 The gdal_fillnodata.py script fills selection regions (usually nodata areas)
-by interpolating from valid pixels around the edges of the area.  
+by interpolating from valid pixels around the edges of the area.
 
-Additional details on the algorithm are available in the GDALFillNodata() 
+Additional details on the algorithm are available in the GDALFillNodata()
 docs.
 
 <dl>
@@ -27,7 +32,7 @@ messages are not displayed.
 
 <dt> <b>-md</b> <i>max_distance</i>:</dt><dd>
 The maximum distance (in pixels) that the algorithm will search out for
-values to interpolate. 
+values to interpolate.
 
 <dt> <b>-si</b> <i>smooth_iterations</i>:</dt><dd>
 The number of 3x3 average filter smoothing iterations to run after the
@@ -44,13 +49,13 @@ The band to operate on, by default the first band is operated on.
 <dt> <i>srcfile</i></dt><dd> The source raster file used to identify target pixels.  Only one band is used.</dd>
 
 <dt> <b>-nomask</b>:</dt><dd>
-Do not use the default validity mask for the input band (such as nodata, or 
-alpha masks). 
+Do not use the default validity mask for the input band (such as nodata, or
+alpha masks).
 </dd>
 
 <dt> <b>-mask</b> <i>filename</i>:</dt><dd>
-Use the first band of the specified file as a validity mask (zero is invalid, 
-non-zero is valid). 
+Use the first band of the specified file as a validity mask (zero is invalid,
+non-zero is valid).
 </dd>
 
 <dt> <i>dstfile</i></dt><dd> The new file to create with the interpolated result.  If not provided, the source band is updated in place.</dd>
diff --git a/swig/python/scripts/gdal_polygonize.dox b/swig/python/scripts/gdal_polygonize.dox
index 8457d1f..39efb12 100644
--- a/swig/python/scripts/gdal_polygonize.dox
+++ b/swig/python/scripts/gdal_polygonize.dox
@@ -1,7 +1,12 @@
 
-/*! \page gdal_polygonize gdal_polygonize.py
+/*!
+\if man
+\page gdal_polygonize
+\else
+\page gdal_polygonize gdal_polygonize.py
+\endif
 
-produces a polygon feature layer from a raster 
+Produces a polygon feature layer from a raster.
 
 \section gdal_polygonize_synopsis SYNOPSIS
 
@@ -13,15 +18,15 @@ gdal_polygonize.py [-8] [-nomask] [-mask filename] raster_file [-b band]
 \section gdal_polygonize_description DESCRIPTION
 
 This utility creates vector polygons for all connected regions of pixels in
-the raster sharing a common pixel value.  Each polygon is created with an 
+the raster sharing a common pixel value.  Each polygon is created with an
 attribute indicating the pixel value of that polygon.  A raster mask
 may also be provided to determine which pixels are eligible for processing.
 
 The utility will create the output vector datasource if it does not already
-exist, defaulting to GML format.  
+exist, defaulting to GML format.
 
-The utility is based on the GDALPolygonize() function which has additional 
-details on the algorithm. 
+The utility is based on the GDALPolygonize() function which has additional
+details on the algorithm.
 
 <dl>
 
@@ -30,19 +35,22 @@ Use 8 connectedness. Default is 4 connectedness.
 </dd>
 
 <dt> <b>-nomask</b>:</dt><dd>
-Do not use the default validity mask for the input band (such as nodata, or 
-alpha masks). 
+Do not use the default validity mask for the input band (such as nodata, or
+alpha masks).
 </dd>
 
 <dt> <b>-mask</b> <i>filename</i>:</dt><dd>
-Use the first band of the specified file as a validity mask (zero is invalid, 
-non-zero is valid). 
+Use the first band of the specified file as a validity mask (zero is invalid,
+non-zero is valid). If not specified, the default validity mask for the input
+band (such as nodata, or alpha masks) will be used (unless -nomask is specified)
 </dd>
 
 <dt> <i>raster_file</i></dt><dd> The source raster file from which polygons are derived.</dd>
 
 <dt> <b>-b</b> <i>band</i>:</dt> <dd> The band on <i>raster_file</i> to build
-the polygons from.
+the polygons from. Starting with GDAL 2.2, the value can also be set to "mask",
+to indicate that the mask band of the first band must be used (or
+"mask,band_number" for the mask of a specified band)
 </dd>
 
 <dt> <b>-f</b> <i>ogr_format</i></dt><dd> Select the output format of the
@@ -55,8 +63,8 @@ file to be created.  Default is GML.
 <dt> <i>layer</i></dt><dd> The name of the layer created to hold the polygon features.
 </dd>
 
-<dt> <i>fieldname</i></dt><dd> The name of the field to create (defaults to 
-"DN"). 
+<dt> <i>fieldname</i></dt><dd> The name of the field to create (defaults to
+"DN").
 </dd>
 
 <dt> <b>-q</b>:</dt><dd>
diff --git a/swig/python/scripts/gdal_polygonize.py b/swig/python/scripts/gdal_polygonize.py
index 1f8c7c8..efebff8 100755
--- a/swig/python/scripts/gdal_polygonize.py
+++ b/swig/python/scripts/gdal_polygonize.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #******************************************************************************
-#  $Id: gdal_polygonize.py 34304 2016-05-27 17:46:17Z rouault $
+#  $Id: gdal_polygonize.py 36130 2016-11-06 15:51:48Z rouault $
 #
 #  Project:  GDAL Python Interface
 #  Purpose:  Application for converting raster data to a vector polygon layer.
@@ -39,7 +39,7 @@ from osgeo import osr
 
 def Usage():
     print("""
-gdal_polygonize [-8] [-nomask] [-mask filename] raster_file [-b band]
+gdal_polygonize [-8] [-nomask] [-mask filename] raster_file [-b band|mask]
                 [-q] [-f ogr_format] out_file [layer] [fieldname]
 """)
     sys.exit(1)
@@ -90,7 +90,10 @@ while i < len(argv):
 
     elif arg == '-b':
         i = i + 1
-        src_band_n = int(argv[i])
+        if argv[i].startswith('mask'):
+            src_band_n = argv[i]
+        else:
+            src_band_n = int(argv[i])
 
     elif src_filename is None:
         src_filename = argv[i]
@@ -137,7 +140,16 @@ if src_ds is None:
     print('Unable to open %s' % src_filename)
     sys.exit(1)
 
-srcband = src_ds.GetRasterBand(src_band_n)
+if src_band_n == 'mask':
+    srcband = src_ds.GetRasterBand(1).GetMaskBand()
+    # Workaround the fact that most source bands have no dataset attached
+    options.append('DATASET_FOR_GEOREF=' + src_filename)
+elif isinstance(src_band_n, str) and src_band_n.startswith('mask,'):
+    srcband = src_ds.GetRasterBand(int(src_band_n[len('mask,'):])).GetMaskBand()
+    # Workaround the fact that most source bands have no dataset attached
+    options.append('DATASET_FOR_GEOREF=' + src_filename)
+else:
+    srcband = src_ds.GetRasterBand(src_band_n)
 
 if mask is 'default':
     maskband = srcband.GetMaskBand()
diff --git a/swig/python/scripts/gdal_proximity.dox b/swig/python/scripts/gdal_proximity.dox
index ff46362..401e40e 100644
--- a/swig/python/scripts/gdal_proximity.dox
+++ b/swig/python/scripts/gdal_proximity.dox
@@ -1,23 +1,28 @@
 
-/*! \page gdal_proximity gdal_proximity.py
+/*!
+\if man
+\page gdal_proximity
+\else
+\page gdal_proximity gdal_proximity.py
+\endif
 
-produces a raster proximity map
+Produces a raster proximity map.
 
 \section gdal_proximity_synopsis SYNOPSIS
 
 \verbatim
-gdal_proximity.py srcfile dstfile [-srcband n] [-dstband n] 
+gdal_proximity.py srcfile dstfile [-srcband n] [-dstband n]
                   [-of format] [-co name=value]*
                   [-ot Byte/Int16/Int32/Float32/etc]
                   [-values n,n,n] [-distunits PIXEL/GEO]
                   [-maxdist n] [-nodata n] [-use_input_nodata YES/NO]
-                  [-fixed-buf-val n] 
+                  [-fixed-buf-val n]
 \endverbatim
 
 \section gdal_proximity_description DESCRIPTION
 
 The gdal_proximity.py script generates a raster proximity map indicating
-the distance from the center of each pixel to the center of the nearest 
+the distance from the center of each pixel to the center of the nearest
 pixel identified as a target pixel.  Target pixels are those in the source
 raster for which the raster pixel value is in the set of target pixel values.
 
@@ -37,11 +42,11 @@ the output format driver. Multiple <b>-co</b> options may be listed. See
 format specific documentation for legal creation options for each format.
 </dd>
 
-<dt> <b>-ot</b> <i>datatype</i>:</dt><dd> 
+<dt> <b>-ot</b> <i>datatype</i>:</dt><dd>
 Force the output image bands to have a specific type. Use type names (i.e. Byte, Int16,...)
 </dd>
 
-<dt> <b>-values</b> <i>n,n,n</i>:</dt><dd> 
+<dt> <b>-values</b> <i>n,n,n</i>:</dt><dd>
 A list of target pixel values in the source image to be considered target
 pixels. If not specified, all non-zero pixels will be considered target pixels.
 </dd>
diff --git a/swig/python/scripts/gdal_retile.py b/swig/python/scripts/gdal_retile.py
index a414c5c..a8867c0 100755
--- a/swig/python/scripts/gdal_retile.py
+++ b/swig/python/scripts/gdal_retile.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 ###############################################################################
-#  $Id: gdal_retile.py 33790 2016-03-26 12:42:12Z goatbar $
+#  $Id: gdal_retile.py 35009 2016-08-09 13:25:10Z rouault $
 #
 # Purpose:  Module for retiling (merging) tiles and building tiled pyramids
 # Author:   Christian Meuller, christian.mueller at nvoe.at
@@ -100,33 +100,26 @@ class DataSetCache:
 
 class tile_info:
     """ A class holding info how to tile """
-    def __init__(self,xsize,ysize,tileWidth,tileHeight):
+    def __init__(self,xsize,ysize,tileWidth,tileHeight,overlap):
+        self.width = xsize
+        self.height = ysize
         self.tileWidth=tileWidth
         self.tileHeight=tileHeight
-        self.countTilesX= int(xsize / tileWidth)
-        self.countTilesY= int(ysize / tileHeight)
-        self.lastTileWidth = int(xsize - self.countTilesX *  tileWidth)
-        self.lastTileHeight = int(ysize - self.countTilesY *  tileHeight)
-
-        if (self.lastTileWidth > 0 ):
-            self.countTilesX=self.countTilesX+1
-        else:
-            self.lastTileWidth=tileWidth
-
-        if (self.lastTileHeight > 0 ):
-            self.countTilesY=self.countTilesY+1
-        else:
-            self.lastTileHeight=tileHeight
-
+        self.countTilesX= 1
+        if xsize > tileWidth:
+            self.countTilesX += int((xsize - tileWidth + (tileWidth - overlap) - 1) / (tileWidth - overlap))
+        self.countTilesY= 1
+        if ysize > tileHeight:
+            self.countTilesY += int((ysize - tileHeight + (tileHeight - overlap) - 1) / (tileHeight - overlap))
+        self.overlap = overlap
 
 
     def report( self ):
-        print('tileWidth       %d' % self.tileWidth)
-        print('tileHeight      %d' % self.tileHeight)
-        print('countTilesX:    %d' % self.countTilesX)
-        print('countTilesY:    %d' % self.countTilesY)
-        print('lastTileWidth:  %d' % self.lastTileWidth)
-        print('lastTileHeight: %d' % self.lastTileHeight)
+        print('tileWidth:   %d' % self.tileWidth)
+        print('tileHeight:  %d' % self.tileHeight)
+        print('countTilesX: %d' % self.countTilesX)
+        print('countTilesY: %d' % self.countTilesY)
+        print('overlap:     %d' % self.overlap)
 
 
 
@@ -352,21 +345,20 @@ def tileImage(minfo, ti ):
 
     for yIndex in yRange:
         for xIndex in xRange:
-            offsetY=(yIndex-1)* ti.tileHeight
-            offsetX=(xIndex-1)* ti.tileWidth
-            if yIndex==ti.countTilesY:
-                height=ti.lastTileHeight
-            else:
-                height=ti.tileHeight
-
-            if xIndex==ti.countTilesX:
-                width=ti.lastTileWidth
-            else:
-                width=ti.tileWidth
+            offsetY=(yIndex-1)* (ti.tileHeight - ti.overlap)
+            offsetX=(xIndex-1)* (ti.tileWidth - ti.overlap)
+            height=ti.tileHeight
+            width=ti.tileWidth
             if UseDirForEachRow :
                 tilename=getTileName(minfo,ti, xIndex, yIndex,0)
             else:
                 tilename=getTileName(minfo,ti, xIndex, yIndex)
+
+            if offsetX + width > ti.width:
+                width = ti.width - offsetX
+            if offsetY + height > ti.height:
+                height = ti.height - offsetY
+
             createTile(minfo, offsetX, offsetY, width, height,tilename,OGRDS)
 
             if not Quiet and not Verbose:
@@ -630,14 +622,14 @@ def closeTileIndex(OGRDataSource):
     OGRDataSource.Destroy()
 
 
-def buildPyramid(minfo,createdTileIndexDS,tileWidth, tileHeight):
+def buildPyramid(minfo,createdTileIndexDS,tileWidth, tileHeight, overlap):
 
     global LastRowIndx
     inputDS=createdTileIndexDS
     for level in range(1,Levels+1):
         LastRowIndx = -1
         levelMosaicInfo = mosaic_info(minfo.filename,inputDS)
-        levelOutputTileInfo = tile_info(levelMosaicInfo.xsize/2,levelMosaicInfo.ysize/2,tileWidth,tileHeight)
+        levelOutputTileInfo = tile_info(int(levelMosaicInfo.xsize/2),int(levelMosaicInfo.ysize/2),tileWidth,tileHeight,overlap)
         inputDS=buildPyramidLevel(levelMosaicInfo,levelOutputTileInfo,level)
 
 
@@ -649,17 +641,16 @@ def buildPyramidLevel(levelMosaicInfo,levelOutputTileInfo, level):
 
     for yIndex in yRange:
         for xIndex in xRange:
-            offsetY=(yIndex-1)* levelOutputTileInfo.tileHeight
-            offsetX=(xIndex-1)* levelOutputTileInfo.tileWidth
-            if yIndex==levelOutputTileInfo.countTilesY:
-                height=levelOutputTileInfo.lastTileHeight
-            else:
-                height=levelOutputTileInfo.tileHeight
+            offsetY=(yIndex-1)* (levelOutputTileInfo.tileHeight - levelOutputTileInfo.overlap)
+            offsetX=(xIndex-1)* (levelOutputTileInfo.tileWidth - levelOutputTileInfo.overlap)
+            height=levelOutputTileInfo.tileHeight
+            width=levelOutputTileInfo.tileWidth
+
+            if offsetX + width > levelOutputTileInfo.width:
+                width = levelOutputTileInfo.width - offsetX
+            if offsetY + height > levelOutputTileInfo.height:
+                height = levelOutputTileInfo.height - offsetY
 
-            if xIndex==levelOutputTileInfo.countTilesX:
-                width=levelOutputTileInfo.lastTileWidth
-            else:
-                width=levelOutputTileInfo.tileWidth
             tilename=getTileName(levelMosaicInfo,levelOutputTileInfo, xIndex, yIndex,level)
             createPyramidTile(levelMosaicInfo, offsetX, offsetY, width, height,tilename,OGRDS)
 
@@ -717,6 +708,7 @@ def Usage():
      print('Usage: gdal_retile.py ')
      print('        [-v] [-q] [-co NAME=VALUE]* [-of out_format]')
      print('        [-ps pixelWidth pixelHeight]')
+     print('        [-overlap val_in_pixel]')
      print('        [-ot  {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/')
      print('               CInt16/CInt32/CFloat32/CFloat64}]')
      print('        [ -tileIndex tileIndexName [-tileIndexField fieldName]]')
@@ -742,6 +734,7 @@ def main(args = None):
     global Names
     global TileWidth
     global TileHeight
+    global Overlap
     global Format
     global BandType
     global Driver
@@ -808,6 +801,10 @@ def main(args = None):
             i+=1
             TileHeight=int(argv[i])
 
+        elif arg == '-overlap':
+            i+=1
+            Overlap=int(argv[i])
+
         elif arg == '-r':
             i+=1
             ResamplingMethodString=argv[i]
@@ -877,6 +874,9 @@ def main(args = None):
     if (TileWidth==0 or TileHeight==0):
         print("Invalid tile dimension %d,%d" % (TileWidth,TileHeight))
         return 1
+    if (TileWidth - Overlap <= 0 or TileHeight - Overlap <=0):
+        print("Overlap too big w.r.t tile height/width")
+        return 1
 
     if (TargetDir is None):
         print("Missing Directory for Tiles -targetDir")
@@ -923,7 +923,7 @@ def main(args = None):
         print("Error building tile index")
         return 1;
     minfo = mosaic_info(Names[0],tileIndexDS)
-    ti=tile_info(minfo.xsize,minfo.ysize, TileWidth, TileHeight)
+    ti=tile_info(minfo.xsize,minfo.ysize, TileWidth, TileHeight, Overlap)
 
     if Source_SRS is None and len(minfo.projection) > 0 :
        Source_SRS = osr.SpatialReference()
@@ -943,7 +943,7 @@ def main(args = None):
        dsCreatedTileIndex=tileIndexDS
 
     if Levels>0:
-       buildPyramid(minfo,dsCreatedTileIndex,TileWidth, TileHeight)
+       buildPyramid(minfo,dsCreatedTileIndex,TileWidth, TileHeight, Overlap)
 
     if Verbose:
         print("FINISHED")
@@ -956,6 +956,7 @@ def initGlobals():
     global Names
     global TileWidth
     global TileHeight
+    global Overlap
     global Format
     global BandType
     global Driver
@@ -980,6 +981,7 @@ def initGlobals():
     Names=[]
     TileWidth=256
     TileHeight=256
+    Overlap=0
     Format='GTiff'
     BandType = None
     Driver=None
@@ -1008,6 +1010,7 @@ CreateOptions = []
 Names=[]
 TileWidth=256
 TileHeight=256
+Overlap=0
 Format='GTiff'
 BandType = None
 Driver=None
diff --git a/swig/python/scripts/gdal_sieve.dox b/swig/python/scripts/gdal_sieve.dox
index 8ede34f..da52a82 100644
--- a/swig/python/scripts/gdal_sieve.dox
+++ b/swig/python/scripts/gdal_sieve.dox
@@ -1,7 +1,12 @@
 
-/*! \page gdal_sieve gdal_sieve.py
+/*!
+\if man
+\page gdal_sieve
+\else
+\page gdal_sieve gdal_sieve.py
+\endif
 
-removes small raster polygons
+Removes small raster polygons.
 
 \section gdal_sieve_synopsis SYNOPSIS
 
@@ -13,11 +18,15 @@ gdal_sieve.py [-q] [-st threshold] [-4] [-8] [-o name=value]
 \section gdal_sieve_description DESCRIPTION
 
 The gdal_sieve.py script removes raster polygons smaller than a provided
-threshold size (in pixels) and replaces replaces them with the pixel value 
-of the largest neighbour polygon.  The result can be written back to the 
-existing raster band, or copied into a new file. 
+threshold size (in pixels) and replaces replaces them with the pixel value
+of the largest neighbour polygon.  The result can be written back to the
+existing raster band, or copied into a new file.
+
+The input dataset is read as integer data which means that floating point
+values are rounded to integers. Re-scaling source data may be necessary in
+some cases (e.g. 32-bit floating point data with min=0 and max=1).
 
-Additional details on the algorithm are available in the GDALSieveFilter() 
+Additional details on the algorithm are available in the GDALSieveFilter()
 docs.
 
 <dl>
@@ -27,7 +36,7 @@ The script runs in quiet mode.  The progress monitor is suppressed and routine
 messages are not displayed.
 
 <dt> <b>-st</b> <i>threshold</i>:</dt><dd>
-Set the size threshold in pixels.  Only raster polygons smaller than this size 
+Set the size threshold in pixels.  Only raster polygons smaller than this size
 will be removed.
 
 <dt> <b>-o</b> <i>name=value</i>:</dt><dd>
@@ -35,25 +44,25 @@ Specify a special argument to the algorithm.  Currently none are supported.
 </dd>
 
 <dt> <b>-4</b>:</dt><dd>
-Four connectedness should be used when determining polygons.  That is 
+Four connectedness should be used when determining polygons.  That is
 diagonal pixels are not considered directly connected.  This is the default.
 </dd>
 
 <dt> <b>-8</b>:</dt><dd>
-Eight connectedness should be used when determining polygons.  That is 
+Eight connectedness should be used when determining polygons.  That is
 diagonal pixels are considered directly connected.
 </dd>
 
 <dt> <i>srcfile</i></dt><dd> The source raster file used to identify target pixels.  Only the first band is used.</dd>
 
 <dt> <b>-nomask</b>:</dt><dd>
-Do not use the default validity mask for the input band (such as nodata, or 
-alpha masks). 
+Do not use the default validity mask for the input band (such as nodata, or
+alpha masks).
 </dd>
 
 <dt> <b>-mask</b> <i>filename</i>:</dt><dd>
-Use the first band of the specified file as a validity mask (zero is invalid, 
-non-zero is valid). 
+Use the first band of the specified file as a validity mask (zero is invalid,
+non-zero is valid).
 </dd>
 
 <dt> <i>dstfile</i></dt><dd> The new file to create with the filtered result.  If not provided, the source band is updated in place.</dd>
diff --git a/swig/python/scripts/gdalcompare.dox b/swig/python/scripts/gdalcompare.dox
index 505116d..f83eae1 100644
--- a/swig/python/scripts/gdalcompare.dox
+++ b/swig/python/scripts/gdalcompare.dox
@@ -1,7 +1,12 @@
 
-/*! \page gdalcompare gdalcompare.py
+/*!
+\if man
+\page gdalcompare
+\else
+\page gdalcompare gdalcompare.py
+\endif
 
-compare two images
+Compare two images.
 
 \section gdalcompare_synopsis SYNOPSIS
 
@@ -13,12 +18,12 @@ gdalcompare.py [-sds] golden_file new_file
 
 The gdalcompare.py script compares two GDAL supported datasets and reports
 the differences.  In addition to reporting differences to the standard out
-the script will also return the difference count in it's exit value. 
+the script will also return the difference count in it's exit value.
 
 Image pixels, and various metadata are checked.  There is also a byte by
-byte comparison done which will count as one difference.  So if it is 
+byte comparison done which will count as one difference.  So if it is
 only important that the GDAL visible data is identical a difference count
-of 1 (the binary difference) should be considered acceptable. 
+of 1 (the binary difference) should be considered acceptable.
 
 
 <dl>
@@ -35,7 +40,7 @@ The file being compared to the golden file, referred to as the new file.
 
 </dl>
 
-Note that the gdalcompare.py script can also be called as a library from 
+Note that the gdalcompare.py script can also be called as a library from
 python code though it is not typically in the python path for including. The
 primary entry point is gdalcompare.compare() which takes a golden gdal.Dataset
 and a new gdal.Dataset as arguments and returns a difference count (excluding
diff --git a/swig/python/scripts/gdalmove.dox b/swig/python/scripts/gdalmove.dox
index fe037c2..c26aea7 100644
--- a/swig/python/scripts/gdalmove.dox
+++ b/swig/python/scripts/gdalmove.dox
@@ -1,7 +1,12 @@
 
-/*! \page gdalmove gdalmove.py
+/*!
+\if man
+\page gdalmove
+\else
+\page gdalmove gdalmove.py
+\endif
 
-Transform georeferencing of raster file in place
+Transform georeferencing of raster file in place.
 
 \section gdalmove_synopsis SYNOPSIS
 
@@ -14,28 +19,28 @@ gdalmove.py [-s_srs <srs_defn>] -t_srs <srs_defn>
 
 The gdalmove.py script transforms the bounds of a raster file from
 one coordinate system to another, and then updates the coordinate
-system and geotransform of the file.  This is done without altering 
+system and geotransform of the file.  This is done without altering
 pixel values at all.  It is loosely similar to using gdalwarp to transform
-an image but avoiding the resampling step in order to avoid image damage. 
+an image but avoiding the resampling step in order to avoid image damage.
 It is generally only suitable for transformations that are effectively linear
-in the area of the file. 
+in the area of the file.
 
 If no error threshold value (-et) is provided then the file is not actually
 updated, but the errors that would be incurred are reported.  If -et is
 provided then the file is only modify if the apparent error being introduced
-is less than the indicate threshold (in pixels). 
+is less than the indicate threshold (in pixels).
 
-Currently the transformed geotransform is computed based on the 
+Currently the transformed geotransform is computed based on the
 transformation of the top left, top right, and bottom left corners.  A reduced
 overall error could be produced using a least squares fit of at least all
-four corner points. 
+four corner points.
 
 <dl>
 
 <dt> <b>-s_srs</b> <i>srs_defn</i>:</dt><dd>
 
 Override the coordinate system of the file with the indicated coordinate
-system definition.  Optional.  If not provided the source coordinate 
+system definition.  Optional.  If not provided the source coordinate
 system is read from the source file.
 
 <dt> <b>-t_srs</b> <i>srs_defn</i>:</dt><dd>
diff --git a/swig/python/scripts/ogrmerge.dox b/swig/python/scripts/ogrmerge.dox
new file mode 100644
index 0000000..2e691af
--- /dev/null
+++ b/swig/python/scripts/ogrmerge.dox
@@ -0,0 +1,169 @@
+
+/*!
+\if man
+\page ogrmerge
+\else
+\page ogrmerge ogrmerge.py
+\endif
+
+Merge several vector datasets into a single one.
+
+\section ogrmerge_synopsis SYNOPSIS
+
+\verbatim
+ogrmerge.py -o out_dsname src_dsname [src_dsname]*
+            [-f format] [-single] [-nln layer_name_template]
+            [-update | -overwrite_ds] [-append | -overwrite_layer]
+            [-src_geom_type geom_type_name[,geom_type_name]*]
+            [-dsco NAME=VALUE]* [-lco NAME=VALUE]*
+            [-s_srs srs_def] [-t_srs srs_def | -a_srs srs_def]
+            [-progress] [-skipfailures] [--help-general]
+
+Options specific to -single:
+            [-field_strategy FirstLayer|Union|Intersection]
+            [-src_layer_field_name name]
+            [-src_layer_field_content layer_name_template]
+\endverbatim
+
+\section ogrmerge_description DESCRIPTION
+
+(Available since GDAL 2.2)
+
+The ogrmerge.py script takes as input several vector datasets, each of them
+having one or several vector layers, and copy them in a target dataset.
+
+There are essential two modes :
+- the default one, where each input vector layer, is copied as a separate
+layer into the target dataset
+- another one, activated with the -single switch, where the content of all
+input vector layers is appended into a single target layer. This assumes that
+the schema of those vector layers is more or less the same.
+
+Internally this generates a <a href="drv_vrt.html">VRT</a> file,
+and if the output format is not VRT,
+final translation is done with ogr2ogr / gdal.VectorTranslate.
+So for advanced uses, output to VRT, potential manual editing of it and
+ogr2ogr can be done.
+
+<dl>
+
+<dt> <b>-o</b> <i>out_dsname</i>:</dt><dd>
+Output dataset name. Required.
+</dd>
+
+<dt> <i>src_dsname</i>:</dt><dd>
+One or several input vector datasets. Required
+</dd>
+
+<dt> <b>-f</b> <em>format</em>:</dt><dd>Select the output format.
+VRT is a valid output format as well. Defaults to "ESRI Shapefile"</dd>
+
+<dt> <b>-single</b>:</dt><dd>If specified, all input vector layers will be
+merged into a single one.</dd>
+
+<dt> <b>-nln</b> <em>layer_name_template</em>:</dt><dd>Name of the output
+vector layer (in single mode, and the default is "merged"), or template to
+name the output vector layers in default mode (the default value is
+"{AUTO_NAME}"). The template can be a string with the following variables
+that will be susbstitued with a value computed from the input layer being
+processed:
+
+- {AUTO_NAME}: equivalent to {DS_BASENAME}_{LAYER_NAME} if both values are
+different, or {LAYER_NAME} when they are identical (case of shapefile).
+          'different
+- {DS_NAME}    : name of the source dataset
+- {DS_BASENAME}: base name of the source dataset
+- {DS_INDEX}   : index of the source dataset
+- {LAYER_NAME} : name of the source layer
+- {LAYER_INDEX}: index of the source layer
+</dd>
+
+<dt> <b>-update</b> </dt><dd>Open an existing dataset in update mode.</dd>
+
+<dt> <b>-overwrite_ds</b> </dt><dd>Overwrite the existing dataset if it
+already exists (for file based datasets)</dd>
+
+<dt> <b>-append</b> </dt><dd>Open an existing dataset in update mode, and
+if output layers already exist, append the content of input layers to them.
+</dd>
+
+<dt> <b>-overwrite_layer</b> </dt><dd>Open an existing dataset in update mode,
+and if output layers already exist, replace their content with the one of the
+input layer.</dd>
+
+<dt> <b>-src_geom_type</b> <em>geom_type_name[,geom_type_name]*]</em>:</dt><dd>
+Only take into account input layers whose geometry type match the type(s)
+specified. Valid values for geom_type_name are GEOMETRY, POINT, LINESTRING,
+POLYGON, MULTIPOINT, MULTILINESTRING, MULTIPOINT, GEOMETRYCOLLECTION,
+CIRCULARSTRING,  CURVEPOLYGON, MULTICURVE, MULTISURFACE, CURVE, SURFACE,
+TRIANGLE, POLYHEDRALSURFACE and TIN.</dd>
+
+<dt> <b>-dsco</b> <em>NAME=VALUE</em>:</dt><dd>
+Dataset creation option (format specific)</dd>
+
+<dt> <b>-lco</b><em>  NAME=VALUE</em>:</dt><dd>
+Layer creation option (format specific)</dd>
+
+<dt> <b>-a_srs</b><em> srs_def</em>:</dt><dd>
+Assign an output SRS</dd>
+
+<dt> <b>-t_srs</b><em> srs_def</em>:</dt><dd>
+Reproject/transform to this SRS on output</dd>
+
+<dt> <b>-s_srs</b><em> srs_def</em>:</dt><dd>
+Override source SRS</dd>
+
+<dt> <b>-progress</b>:</dt><dd>
+Display progress on terminal. Only works if input layers have the
+"fast feature count" capability.</dd>
+
+<dt> <b>-skipfailures</b>:</dt><dd>
+Continue after a failure, skipping the failed feature.</dd>
+
+<dt> <b>-field_strategy</b><em> FirstLayer|Union|Intersection</em>:</dt><dd>
+Only used with -single. Determines how the schema of the target layer is built
+from the schemas of the input layers. May be FirstLayer to use the fields from
+the first layer found, Union to use a super-set of all the fields from all
+source layers, or Intersection to use a sub-set of all the common fields from
+all source layers. Defaults to Union.</dd>
+
+<dt> <b>-src_layer_field_name</b><em> name</em>:</dt><dd>
+Only used with -single. If specified, the schema of the target layer will be
+extended with a new field 'name', whose content is determined by
+-src_layer_field_content.</dd>
+
+<dt> <b>-src_layer_field_content</b><em> layer_name_template</em>:</dt><dd>
+Only used with -single. If specified, the schema of the target layer will be
+extended with a new field (whose name is given by -src_layer_field_name, or
+'source_ds_lyr' otherwise), whose content is determined by layer_name_template.
+The syntax of layer_name_template is the same as for -nln.
+</dd>
+
+</dl>
+
+\section ogrmerge_examples EXAMPLES
+
+
+- Creates a VRT with a layer for each input shapefiles
+\verbatim
+ogrmerge.py -f VRT -o merged.vrt *.shp
+\endverbatim
+
+- Same, but creates a GeoPackage file
+\verbatim
+ogrmerge.py -f GPKG -o merged.gpkg *.shp
+\endverbatim
+
+- Concatenate the content of france.shp and germany.shp in merged.shp, and
+adds a 'country' field to each feature whose value is 'france' or 'germany'
+depending where it comes from.
+\verbatim
+ogrmerge.py -single -o merged.shp france.shp germany.shp -src_layer_field_name country
+\endverbatim
+
+\if man
+\section ogrmerge_author AUTHORS
+Even Rouault <even.rouault at spatialys.com>
+\endif
+*/
+
diff --git a/swig/python/scripts/ogrmerge.py b/swig/python/scripts/ogrmerge.py
new file mode 100755
index 0000000..d12a048
--- /dev/null
+++ b/swig/python/scripts/ogrmerge.py
@@ -0,0 +1,542 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+###############################################################################
+# $Id: ogrmerge.py 37620 2017-03-06 09:19:57Z rouault $
+#
+# Project:  GDAL/OGR samples
+# Purpose:  Merge the content of several vector datasets into a single one.
+# Author:   Even Rouault <even dot rouault at spatialys dot com>
+#
+###############################################################################
+# Copyright (c) 2017, Even Rouault <even dot rouault at spatialys dot com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+###############################################################################
+
+import os
+import sys
+
+from osgeo import gdal
+from osgeo import ogr
+
+###############################################################
+# Usage()
+
+
+def Usage():
+    print('ogrmerge.py -o out_dsname src_dsname [src_dsname]*')
+    print('            [-f format] [-single] [-nln layer_name_template]')
+    print('            [-update | -overwrite_ds] [-append | -overwrite_layer]')
+    print('            [-src_geom_type geom_type_name[,geom_type_name]*]')
+    print('            [-dsco NAME=VALUE]* [-lco NAME=VALUE]*')
+    print('            [-s_srs srs_def] [-t_srs srs_def | -a_srs srs_def]')
+    print('            [-progress] [-skipfailures] [--help-general]')
+    print('')
+    print('Options specific to -single:')
+    print('            [-field_strategy FirstLayer|Union|Intersection]')
+    print('            [-src_layer_field_name name]')
+    print('            [-src_layer_field_content layer_name_template]')
+    print('')
+    print('* layer_name_template can contain the following substituable '
+          'variables:')
+    print('     {AUTO_NAME}  : {DS_BASENAME}_{LAYER_NAME} if they are '
+          'different')
+    print('                    or {LAYER_NAME} if they are identical')
+    print('     {DS_NAME}    : name of the source dataset')
+    print('     {DS_BASENAME}: base name of the source dataset')
+    print('     {DS_INDEX}   : index of the source dataset')
+    print('     {LAYER_NAME} : name of the source layer')
+    print('     {LAYER_INDEX}: index of the source layer')
+
+    return 1
+
+#############################################################################
+
+
+def _VSIFPrintfL(f, s):
+    gdal.VSIFWriteL(s, 1, len(s), f)
+
+#############################################################################
+
+
+def EQUAL(x, y):
+    return x.lower() == y.lower()
+
+#############################################################################
+
+
+def _GetGeomType(src_geom_type_name):
+    if EQUAL(src_geom_type_name, "GEOMETRY"):
+        return ogr.wkbGeometry
+    try:
+        max_geom_type = ogr.wkbTriangle
+    except:
+        # GDAL 2.1 compat
+        max_geom_type = ogr.wkbSurface
+    for i in range(max_geom_type + 1):
+        if EQUAL(src_geom_type_name,
+                 ogr.GeometryTypeToName(i).replace(' ', '')):
+            return i
+    return None
+
+#############################################################################
+
+
+def _Esc(x):
+    return gdal.EscapeString(x, gdal.CPLES_XML)
+
+
+class XMLWriter:
+
+    def __init__(self, f):
+        self.f = f
+        self.inc = 0
+        self.elements = []
+
+    def _indent(self):
+        return ''.join(['  ' for i in range(self.inc)])
+
+    def open_element(self, name, attrs=None):
+        xml_attrs = ''
+        if attrs is not None:
+            for key in attrs:
+                xml_attrs = xml_attrs + ' %s=\"%s\"' % (key, _Esc(attrs[key]))
+        _VSIFPrintfL(self.f, '%s<%s%s>\n' % (self._indent(), name, xml_attrs))
+        self.inc = self.inc + 1
+        self.elements.append(name)
+
+    def write_element_value(self, name, value, attrs=None):
+        xml_attrs = ''
+        if attrs is not None:
+            for key in attrs:
+                xml_attrs = xml_attrs + ' %s=\"%s\"' % (key, _Esc(attrs[key]))
+        _VSIFPrintfL(self.f, '%s<%s%s>%s</%s>\n' %
+                     (self._indent(), name, xml_attrs,
+                      _Esc(value), name))
+
+    def close_element(self, closing_name=None):
+        self.inc = self.inc - 1
+        name = self.elements[-1]
+        if closing_name is not None:
+            assert name == closing_name
+        self.elements = self.elements[0:-1]
+        _VSIFPrintfL(self.f, '%s</%s>\n' % (self._indent(), name))
+
+
+###############################################################
+# process()
+
+
+def process(argv, progress=None, progress_arg=None):
+
+    if len(argv) == 0:
+        return Usage()
+
+    dst_filename = None
+    output_format = None
+    src_datasets = []
+    overwrite_ds = False
+    overwrite_layer = False
+    update = False
+    append = False
+    single_layer = False
+    layer_name_template = None
+    skip_failures = False
+    src_geom_types = []
+    field_strategy = None
+    src_layer_field_name = None
+    src_layer_field_content = None
+    a_srs = None
+    s_srs = None
+    t_srs = None
+    dsco = []
+    lco = []
+
+    i = 0
+    while i < len(argv):
+        arg = argv[i]
+        if (arg == '-f' or arg == '-of') and i+1 < len(argv):
+            i = i + 1
+            output_format = argv[i]
+        elif arg == '-o' and i+1 < len(argv):
+            i = i + 1
+            dst_filename = argv[i]
+        elif arg == '-progress':
+            progress = ogr.TermProgress_nocb
+            progress_arg = None
+        elif arg == '-q' or arg == '-quiet':
+            pass
+        elif arg[0:5] == '-skip':
+            skip_failures = True
+        elif arg == '-update':
+            update = True
+        elif arg == '-overwrite_ds':
+            overwrite_ds = True
+        elif arg == '-overwrite_layer':
+            overwrite_layer = True
+            update = True
+        elif arg == '-append':
+            append = True
+            update = True
+        elif arg == '-single':
+            single_layer = True
+        elif arg == '-a_srs' and i+1 < len(argv):
+            i = i + 1
+            a_srs = argv[i]
+        elif arg == '-s_srs' and i+1 < len(argv):
+            i = i + 1
+            s_srs = argv[i]
+        elif arg == '-t_srs' and i+1 < len(argv):
+            i = i + 1
+            t_srs = argv[i]
+        elif arg == '-nln' and i+1 < len(argv):
+            i = i + 1
+            layer_name_template = argv[i]
+        elif arg == '-field_strategy' and i+1 < len(argv):
+            i = i + 1
+            field_strategy = argv[i]
+        elif arg == '-src_layer_field_name' and i+1 < len(argv):
+            i = i + 1
+            src_layer_field_name = argv[i]
+        elif arg == '-src_layer_field_content' and i+1 < len(argv):
+            i = i + 1
+            src_layer_field_content = argv[i]
+        elif arg == '-dsco' and i+1 < len(argv):
+            i = i + 1
+            dsco.append(argv[i])
+        elif arg == '-lco' and i+1 < len(argv):
+            i = i + 1
+            lco.append(argv[i])
+        elif arg == '-src_geom_type' and i+1 < len(argv):
+            i = i + 1
+            src_geom_type_names = argv[i].split(',')
+            for src_geom_type_name in src_geom_type_names:
+                src_geom_type = _GetGeomType(src_geom_type_name)
+                if src_geom_type is None:
+                    print('ERROR: Unrecognized geometry type: %s' %
+                          src_geom_type_name)
+                    return 1
+                src_geom_types.append(src_geom_type)
+        elif arg[0] == '-':
+            print('ERROR: Unrecognized argument : %s' % arg)
+            return Usage()
+        else:
+            src_datasets.append(arg)
+        i = i + 1
+
+    if dst_filename is None:
+        print('Missing -o')
+        return 1
+
+    if update:
+        if output_format is not None:
+            print('ERROR: -f incompatible with -update')
+            return 1
+        if len(dsco) != 0:
+            print('ERROR: -dsco incompatible with -update')
+            return 1
+        output_format = ''
+    else:
+        if output_format is None:
+            output_format = 'ESRI Shapefile'
+
+    if src_layer_field_content is None:
+        src_layer_field_content = '{AUTO_NAME}'
+    elif src_layer_field_name is None:
+        src_layer_field_name = 'source_ds_lyr'
+
+    if not single_layer and output_format == 'ESRI Shapefile' and \
+       dst_filename.lower().endswith('.shp'):
+        print('ERROR: Non-single layer mode incompatible with non-directory '
+              'shapefile output')
+        return 1
+
+    if len(src_datasets) == 0:
+        print('ERROR: No source datasets')
+        return 1
+
+    if layer_name_template is None:
+        if single_layer:
+            layer_name_template = 'merged'
+        else:
+            layer_name_template = '{AUTO_NAME}'
+
+    vrt_filename = None
+    if not EQUAL(output_format, 'VRT'):
+        dst_ds = gdal.OpenEx(dst_filename, gdal.OF_VECTOR | gdal.OF_UPDATE)
+        if dst_ds is not None:
+            if not update and not overwrite_ds:
+                print('ERROR: Destination dataset already exists, ' +
+                      'but -update nor -overwrite_ds are specified')
+                return 1
+            if overwrite_ds:
+                drv = dst_ds.GetDriver()
+                dst_ds = None
+                if drv.GetDescription() == 'OGR_VRT':
+                    # We don't want to destroy the sources of the VRT
+                    gdal.Unlink(dst_filename)
+                else:
+                    drv.Delete(dst_filename)
+        elif update:
+            print('ERROR: Destination dataset does not exist')
+            return 1
+        if dst_ds is None:
+            drv = gdal.GetDriverByName(output_format)
+            if drv is None:
+                print('ERROR: Invalid driver: %s' % output_format)
+                return 1
+            dst_ds = drv.Create(
+                dst_filename, 0, 0, 0, gdal.GDT_Unknown, dsco)
+            if dst_ds is None:
+                return 1
+
+        vrt_filename = '/vsimem/_ogrmerge_.vrt'
+    else:
+        vrt_filename = dst_filename
+
+    f = gdal.VSIFOpenL(vrt_filename, 'wb')
+    if f is None:
+        print('ERROR: Cannot create %s' % vrt_filename)
+        return 1
+
+    writer = XMLWriter(f)
+    writer.open_element('OGRVRTDataSource')
+
+    if single_layer:
+
+        ogr_vrt_union_layer_written = False
+
+        for src_ds_idx, src_dsname in enumerate(src_datasets):
+            src_ds = ogr.Open(src_dsname)
+            if src_ds is None:
+                print('ERROR: Cannot open %s' % src_dsname)
+                if skip_failures:
+                    continue
+                gdal.VSIFCloseL(f)
+                gdal.Unlink(vrt_filename)
+                return 1
+            for src_lyr_idx, src_lyr in enumerate(src_ds):
+                if len(src_geom_types) != 0:
+                    gt = ogr.GT_Flatten(src_lyr.GetGeomType())
+                    if gt not in src_geom_types:
+                        continue
+
+                if not ogr_vrt_union_layer_written:
+                    ogr_vrt_union_layer_written = True
+                    writer.open_element('OGRVRTUnionLayer',
+                                        attrs={'name': layer_name_template})
+
+                    if src_layer_field_name is not None:
+                        writer.write_element_value('SourceLayerFieldName',
+                                                   src_layer_field_name)
+
+                    if field_strategy is not None:
+                        writer.write_element_value('FieldStrategy',
+                                                   field_strategy)
+
+                layer_name = src_layer_field_content
+
+                basename = None
+                if os.path.exists(src_dsname):
+                    basename = os.path.basename(src_dsname)
+                    if basename.find('.') >= 0:
+                        basename = '.'.join(basename.split(".")[0:-1])
+
+                if basename == src_lyr.GetName():
+                    layer_name = layer_name.replace('{AUTO_NAME}', basename)
+                elif basename is None:
+                    layer_name = layer_name.replace(
+                        '{AUTO_NAME}',
+                        'Dataset%d_%s' % (src_ds_idx, src_lyr.GetName()))
+                else:
+                    layer_name = layer_name.replace(
+                        '{AUTO_NAME}', basename + '_' + src_lyr.GetName())
+
+                if basename is not None:
+                    layer_name = layer_name.replace('{DS_BASENAME}', basename)
+                else:
+                    layer_name = layer_name.replace('{DS_BASENAME}',
+                                                    src_dsname)
+                layer_name = layer_name.replace('{DS_NAME}', '%s' %
+                                                src_dsname)
+                layer_name = layer_name.replace('{DS_INDEX}', '%d' %
+                                                src_ds_idx)
+                layer_name = layer_name.replace('{LAYER_NAME}',
+                                                src_lyr.GetName())
+                layer_name = layer_name.replace('{LAYER_INDEX}',  '%d' %
+                                                src_lyr_idx)
+
+                if t_srs is not None:
+                    writer.open_element('OGRVRTWarpedLayer')
+
+                writer.open_element('OGRVRTLayer',
+                                    attrs={'name': layer_name})
+                attrs = None
+                if os.path.exists(src_dsname) and \
+                   src_dsname.find('/') < 0 and \
+                   src_ds.name.find('\\') < 0 and \
+                   os.path.exists(src_dsname) and \
+                   not os.path.isabs(src_dsname):
+                    attrs = {'relativeToVRT': '1'}
+                writer.write_element_value('SrcDataSource', src_dsname,
+                                           attrs=attrs)
+                writer.write_element_value('SrcLayer', src_lyr.GetName())
+
+                if a_srs is not None:
+                    writer.write_element_value('LayerSRS', a_srs)
+
+                writer.close_element('OGRVRTLayer')
+
+                if t_srs is not None:
+                    if s_srs is not None:
+                        writer.write_element_value('SrcSRS', s_srs)
+
+                    writer.write_element_value('TargetSRS', t_srs)
+
+                    writer.close_element('OGRVRTWarpedLayer')
+
+        if ogr_vrt_union_layer_written:
+            writer.close_element('OGRVRTUnionLayer')
+
+    else:
+
+        for src_ds_idx, src_dsname in enumerate(src_datasets):
+            src_ds = ogr.Open(src_dsname)
+            if src_ds is None:
+                print('ERROR: Cannot open %s' % src_dsname)
+                if skip_failures:
+                    continue
+                gdal.VSIFCloseL(f)
+                gdal.Unlink(vrt_filename)
+                return 1
+            for src_lyr_idx, src_lyr in enumerate(src_ds):
+                if len(src_geom_types) != 0:
+                    gt = ogr.GT_Flatten(src_lyr.GetGeomType())
+                    if gt not in src_geom_types:
+                        continue
+
+                layer_name = layer_name_template
+                basename = None
+                if os.path.exists(src_dsname):
+                    basename = os.path.basename(src_dsname)
+                    if basename.find('.') >= 0:
+                        basename = '.'.join(basename.split(".")[0:-1])
+
+                if basename == src_lyr.GetName():
+                    layer_name = layer_name.replace('{AUTO_NAME}', basename)
+                elif basename is None:
+                    layer_name = layer_name.replace(
+                        '{AUTO_NAME}',
+                        'Dataset%d_%s' % (src_ds_idx, src_lyr.GetName()))
+                else:
+                    layer_name = layer_name.replace(
+                        '{AUTO_NAME}', basename + '_' + src_lyr.GetName())
+
+                if basename is not None:
+                    layer_name = layer_name.replace('{DS_BASENAME}', basename)
+                elif layer_name.find('{DS_BASENAME}') >= 0:
+                    if skip_failures:
+                        if layer_name.find('{DS_INDEX}') < 0:
+                            layer_name = layer_name.replace(
+                                '{DS_BASENAME}', 'Dataset%d' % src_ds_idx)
+                    else:
+                        print('ERROR: Layer name template %s '
+                              'includes {DS_BASENAME} '
+                              'but %s is not a file' %
+                              (layer_name_template, src_dsname))
+
+                        gdal.VSIFCloseL(f)
+                        gdal.Unlink(vrt_filename)
+                        return 1
+                layer_name = layer_name.replace('{DS_NAME}', '%s' %
+                                                src_dsname)
+                layer_name = layer_name.replace('{DS_INDEX}', '%d' %
+                                                src_ds_idx)
+                layer_name = layer_name.replace('{LAYER_NAME}',
+                                                src_lyr.GetName())
+                layer_name = layer_name.replace('{LAYER_INDEX}',  '%d' %
+                                                src_lyr_idx)
+
+                if t_srs is not None:
+                    writer.open_element('OGRVRTWarpedLayer')
+
+                writer.open_element('OGRVRTLayer',
+                                    attrs={'name': layer_name})
+                attrs = None
+                if os.path.exists(src_dsname) and \
+                   src_dsname.find('/') < 0 and \
+                   src_ds.name.find('\\') < 0 and \
+                   os.path.exists(src_dsname) and \
+                   not os.path.isabs(src_dsname):
+                    attrs = {'relativeToVRT': '1'}
+                writer.write_element_value('SrcDataSource', src_dsname,
+                                           attrs=attrs)
+                writer.write_element_value('SrcLayer', src_lyr.GetName())
+
+                if a_srs is not None:
+                    writer.write_element_value('LayerSRS', a_srs)
+
+                writer.close_element('OGRVRTLayer')
+
+                if t_srs is not None:
+                    if s_srs is not None:
+                        writer.write_element_value('SrcSRS', s_srs)
+
+                    writer.write_element_value('TargetSRS', t_srs)
+
+                    writer.close_element('OGRVRTWarpedLayer')
+
+    writer.close_element('OGRVRTDataSource')
+
+    gdal.VSIFCloseL(f)
+
+    ret = 0
+    if not EQUAL(output_format, 'VRT'):
+        accessMode = None
+        if append:
+            accessMode = 'append'
+        elif overwrite_layer:
+            accessMode = 'overwrite'
+        ret = gdal.VectorTranslate(dst_ds, vrt_filename,
+                                   accessMode=accessMode,
+                                   layerCreationOptions=lco,
+                                   skipFailures=skip_failures,
+                                   callback=progress,
+                                   callback_data=progress_arg)
+        if ret == 1:
+            ret = 0
+        else:
+            ret = 1
+        gdal.Unlink(vrt_filename)
+
+    return ret
+
+###############################################################
+# Entry point
+
+
+def main():
+    argv = ogr.GeneralCmdLineProcessor(sys.argv)
+    if argv is None:
+        return 1
+    return process(argv[1:])
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/swig/python/setup.cfg b/swig/python/setup.cfg
index 8950416..49f548f 100644
--- a/swig/python/setup.cfg
+++ b/swig/python/setup.cfg
@@ -1,8 +1,10 @@
 # You can override default build options here
+[flake8]
+max-line-length=100
 
 [build_ext]
-#include_dirs = ../../port:../../gcore:../../alg:../../ogr/ 
-#library_dirs = ../../.libs:../../ 
-#libraries = gdal 
+#include_dirs = ../../port:../../gcore:../../alg:../../ogr/
+#library_dirs = ../../.libs:../../
+#libraries = gdal
 gdal_config=../../apps/gdal-config
 
diff --git a/swig/python/setup.py b/swig/python/setup.py
index 6b0580a..da199aa 100644
--- a/swig/python/setup.py
+++ b/swig/python/setup.py
@@ -7,7 +7,7 @@
 # Howard Butler hobu.inc at gmail.com
 
 
-gdal_version = '2.1.3'
+gdal_version = '2.2.0'
 
 import sys
 import os
@@ -34,7 +34,7 @@ if 'CXX' in os.environ and os.environ['CXX'].strip().find(' ') >= 0:
 HAVE_NUMPY=False
 HAVE_SETUPTOOLS = False
 BUILD_FOR_CHEESESHOP = False
-GNM_ENABLED = False
+GNM_ENABLED = True
 
 # ---------------------------------------------------------------------------
 # Default build options
@@ -190,8 +190,14 @@ class gdal_ext(build_ext):
     def finalize_options(self):
         if self.include_dirs is None:
             self.include_dirs = include_dirs
+        # Needed on recent MacOSX
+        elif isinstance(self.include_dirs, str) and sys.platform == 'darwin':
+            self.include_dirs += ':' + ':'.join(include_dirs)
         if self.library_dirs is None:
             self.library_dirs = library_dirs
+        # Needed on recent MacOSX
+        elif isinstance(self.library_dirs, str) and sys.platform == 'darwin':
+            self.library_dirs += ':' + ':'.join(library_dirs)
         if self.libraries is None:
             if self.get_compiler() == 'msvc':
                 libraries.remove('gdal')
@@ -262,8 +268,8 @@ py_modules = ['gdal',
 if os.path.exists('setup_vars.ini'):
     with open('setup_vars.ini') as f:
         lines = f.readlines()
-        if 'GNM_ENABLED=yes' in lines or 'GNM_ENABLED=yes\n' in lines:
-            GNM_ENABLED = True
+        if 'GNM_ENABLED=no' in lines or 'GNM_ENABLED=no\n' in lines:
+            GNM_ENABLED = False
 
 if GNM_ENABLED:
     ext_modules.append(gnm_module)
diff --git a/vb6/GDAL.bas b/vb6/GDAL.bas
deleted file mode 100644
index 84ef582..0000000
--- a/vb6/GDAL.bas
+++ /dev/null
@@ -1,187 +0,0 @@
-Attribute VB_Name = "GDAL"
-'*****************************************************************************
-' $Id: GDAL.bas 7980 2005-08-04 20:54:10Z fwarmerdam $
-'
-' Project:  GDAL VB6 Bindings
-' Purpose:  Main GDAL Public Module - public non-class GDAL declarations.
-' Author:   Frank Warmerdam, warmerdam at pobox.com
-'
-'*****************************************************************************
-' Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-'
-' Permission is hereby granted, free of charge, to any person obtaining a
-' copy of this software and associated documentation files (the "Software"),
-' to deal in the Software without restriction, including without limitation
-' the rights to use, copy, modify, merge, publish, distribute, sublicense,
-' and/or sell copies of the Software, and to permit persons to whom the
-' Software is furnished to do so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included
-' in all copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-' DEALINGS IN THE SOFTWARE.
-'*****************************************************************************
-'
-' $Log$
-' Revision 1.6  2005/08/04 20:53:51  fwarmerdam
-' convert to DOS text mode
-'
-' Revision 1.5  2005/04/11 19:58:47  fwarmerdam
-' added CPLSet/GetConfigOption
-'
-' Revision 1.4  2005/04/08 14:36:25  fwarmerdam
-' applied owned flag, and auto-destroy
-'
-' Revision 1.3  2005/04/06 22:29:50  fwarmerdam
-' added CreateCoordinateTransformation() function
-'
-' Revision 1.2  2005/03/16 23:34:07  fwarmerdam
-' fixed up open to always return a GDALDataset
-'
-' Revision 1.1  2005/03/16 19:40:49  fwarmerdam
-' new
-'
-'
-
-
-' GDALAccess (for open)
-Public Const GA_ReadOnly As Long = 0
-Public Const GA_Update As Long = 1
-
-' GDALDataTypes
-Public Const GDT_Unknown As Long = 0
-Public Const GDT_Byte As Long = 1
-Public Const GDT_UInt16 As Long = 2
-Public Const GDT_Int16 As Long = 3
-Public Const GDT_UInt32 As Long = 4
-Public Const GDT_Int32 As Long = 5
-Public Const GDT_Float32 As Long = 6
-Public Const GDT_Float64 As Long = 7
-Public Const GDT_CInt16 As Long = 8
-Public Const GDT_CInt32 As Long = 9
-Public Const GDT_CFloat32 As Long = 10
-Public Const GDT_CFloat64 As Long = 11
-Public Const GDT_TypeCount As Long = 12
-
-' read/write flags for RasterIO
-Public Const GF_Read As Long = 0
-Public Const GF_Write As Long = 1
-
-' Palette Interpretation
-Public Const GPI_Gray As Long = 0
-Public Const GPI_RGB As Long = 1
-Public Const GPI_CMYK As Long = 2
-Public Const GPI_HLS As Long = 3
-
-' Driver metadata items.
-Public Const DMD_SHORTNAME As String = "DMD_SHORTNAME"
-Public Const DMD_LONGNAME As String = "DMD_LONGNAME"
-Public Const DMD_HELPTOPIC As String = "DMD_HELPTOPIC"
-Public Const DMD_MIMETYPE As String = "DMD_MIMETYPE"
-Public Const DMD_EXTENSION As String = "DMD_EXTENSION"
-Public Const DMD_CREATIONOPTIONLIST As String = "DMD_CREATIONOPTIONLIST"
-Public Const DMD_CREATIONDATATYPES As String = "DMD_CREATIONDATATYPES"
-
-Public Const DCAP_CREATE As String = "DCAP_CREATE"
-Public Const DCAP_CREATECOPY As String = "DCAP_CREATECOPY"
-
-' ----------------------------------------------------------------------------
-Public Function GetLastErrorMsg() As String
-    GetLastErrorMsg = CStr2VB(GDALCore.CPLGetLastErrorMsg())
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetConfigOption(Key As String, Default As String)
-    GetConfigOption = CStr2VB(GDALCore.CPLGetConfigOption(Key, Default))
-End Function
-
-' ----------------------------------------------------------------------------
-Public Sub SetConfigOption(Key As String, Value As String)
-    Call GDALCore.CPLSetConfigOption(Key, Value)
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub AllRegister()
-    Call GDALCore.GDALAllRegister
-End Sub
-' ----------------------------------------------------------------------------
-Public Function GetDriverByName(DriverName As String) As GDALDriver
-    Dim drv_c As Long
-    drv_c = GDALCore.GDALGetDriverByName(DriverName)
-    If drv_c <> 0 Then
-        Set GetDriverByName = New GDALDriver
-        GetDriverByName.CInit (drv_c)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetDriver(ByVal DriverIndex As Long) As GDALDriver
-    Dim drv_c As Long
-    drv_c = GDALCore.GDALGetDriver(DriverIndex)
-    If drv_c <> 0 Then
-        Set GetDriver = New GDALDriver
-        GetDriver.CInit (drv_c)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetDriverCount() As Long
-    GetDriverCount = GDALCore.GDALGetDriverCount()
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetDataTypeName(ByVal DataType As Long) As String
-    GetDataTypeName = GDALCore.CStr2VB(GDALCore.GDALGetDataTypeName(DataType))
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetDataTypeSize(ByVal DataType As Long) As Long
-    GetDataTypeSize = GDALCore.GDALGetDataTypeSize(DataType)
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function OpenDS(Filename As String, ByVal Access As Long) As GDALDataset
-    Set OpenDS = New GDALDataset
-    Call OpenDS.CInit(GDALCore.GDALOpen(Filename, Access), 1)
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function OpenSharedDS(Filename As String, ByVal Access As Long) As GDALDataset
-    Set OpenSharedDS = New GDALDataset
-    Call OpenSharedDS.CInit(GDALCore.GDALOpenShared(Filename, Access), 1)
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function CreateColorTable(ByVal PaletteInterp As Long) _
-                As GDALColorTable
-    Dim obj As Long
-    obj = GDALCore.GDALCreateColorTable(PaletteInterp)
-    If obj <> 0 Then
-        Set CreateColorTable = New GDALColorTable
-        Call CreateColorTable.CInit(obj, 1)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function CreateCoordinateTransformation( _
-        SrcSRS As OGRSpatialReference, TrgSRS As OGRSpatialReference) _
-        As OGRCoordinateTransformation
-        
-    Dim obj As Long
-    
-    Set ct = New OGRCoordinateTransformation
-
-    obj = GDALCore.OCTNewCoordinateTransformation(SrcSRS.GetObjPtr(), _
-                                                  TrgSRS.GetObjPtr())
-    If obj <> 0 Then
-        Call ct.CInit(obj, 1)
-    End If
-    Set CreateCoordinateTransformation = ct
-End Function
-
diff --git a/vb6/GDALColorTable.cls b/vb6/GDALColorTable.cls
deleted file mode 100644
index b4b8601..0000000
--- a/vb6/GDALColorTable.cls
+++ /dev/null
@@ -1,173 +0,0 @@
-'*****************************************************************************
-' $Id: GDALColorTable.cls 7980 2005-08-04 20:54:10Z fwarmerdam $
-'
-' Project:  GDAL VB6 Bindings
-' Purpose:  VB6 GDALColorTable Shadow Class.
-' Author:   Frank Warmerdam, warmerdam at pobox.com
-'
-'*****************************************************************************
-' Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-'
-' Permission is hereby granted, free of charge, to any person obtaining a
-' copy of this software and associated documentation files (the "Software"),
-' to deal in the Software without restriction, including without limitation
-' the rights to use, copy, modify, merge, publish, distribute, sublicense,
-' and/or sell copies of the Software, and to permit persons to whom the
-' Software is furnished to do so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included
-' in all copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-' DEALINGS IN THE SOFTWARE.
-'*****************************************************************************
-'
-' $Log$
-' Revision 1.3  2005/08/04 20:53:51  fwarmerdam
-' convert to DOS text mode
-'
-' Revision 1.2  2005/04/08 14:36:25  fwarmerdam
-' applied owned flag, and auto-destroy
-'
-' Revision 1.1  2005/03/16 23:34:27  fwarmerdam
-' new
-'
-'
-VERSION 1.0 CLASS
-BEGIN
-  MultiUse = -1  'True
-  Persistable = 0  'NotPersistable
-  DataBindingBehavior = 0  'vbNone
-  DataSourceBehavior  = 0  'vbNone
-  MTSTransactionMode  = 0  'NotAnMTSObject
-END
-Attribute VB_Name = "GDALColorTable"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = True
-Attribute VB_PredeclaredId = False
-Attribute VB_Exposed = False
-
-
-Option Explicit
-Private obj As Long
-Private owned As Long
-Public EntryCount As Long
-Public PaletteInterpretation As Long
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Initialize()
-    obj = 0
-    owned = 0
-    EntryCount = 0
-    PaletteInterpretation = 0
-End Sub
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Terminate()
-    If obj <> 0 and owned <> 0 Then
-        call Destroy()
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub CInit(obj_in As Long, owned_in As Long )
-    if obj <> 0 and owned <> 0 Then
-	Call Destroy()
-    End If
-    obj = obj_in
-    owned = owned_in
-    If obj <> 0 Then
-        EntryCount = GDALCore.GDALGetColorEntryCount(obj)
-        PaletteInterpretation = GDALCore.GDALGetPaletteInterpretation(obj)
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub Destroy()
-    If obj <> 0 Then
-	'Call MsgBox( "Destroying ColorTable" )
-	Call GDALCore.GDALDestroyColorTable( obj )
-	obj = 0
-	owned = 0
-    End If 
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Function GetObjPtr() As Long
-    GetObjPtr = obj
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function IsValid() As Boolean
-    If obj = 0 Then
-        IsValid = False
-    Else
-        IsValid = True
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function Clone()
-    Dim other_c_obj As Long
-    Dim other_ct As GDALColorTable
-
-    If obj <> 0 Then
-        other_c_obj = GDALCore.GDALCloneColorTable(obj)
-        Set other_ct = New GDALColorTable
-        Call other_ct.CInit(other_c_obj,1)
-        Set Clone = other_ct
-    End If
-End Function
-' ----------------------------------------------------------------------------
-Public Sub SetColorEntry(ByVal ColorIndex As Long, _
-                               ColorEntry() As Integer)
-
-    If obj <> 0 Then
-        Dim SafeColorEntry(4) As Integer
-        SafeColorEntry(0) = ColorEntry(0)
-        SafeColorEntry(1) = ColorEntry(1)
-        SafeColorEntry(2) = ColorEntry(2)
-        SafeColorEntry(3) = ColorEntry(3)
-
-        Call GDALCore.GDALSetColorEntry(obj, ColorIndex, SafeColorEntry(0))
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Function GetColorEntry(ByVal ColorIndex As Long, ColorEntry() As Integer) As Long
-
-    If obj <> 0 Then
-        Dim SafeColorEntry(4) As Integer
-        GetColorEntry = GDALCore.GDALGetColorEntry(obj, ColorIndex, _
-                                                    SafeColorEntry(0))
-        ColorEntry(0) = SafeColorEntry(0)
-        ColorEntry(1) = SafeColorEntry(1)
-        ColorEntry(2) = SafeColorEntry(2)
-        ColorEntry(3) = SafeColorEntry(3)
-    Else
-        GetColorEntry = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetColorEntryAsRGB(ByVal ColorIndex As Long, _
-                                    ColorEntry() As Integer) As Long
-
-    If obj <> 0 Then
-        Dim SafeColorEntry(4) As Integer
-
-        GetColorEntryAsRGB = GDALCore.GDALGetColorEntryAsRGB( _
-                obj, ColorIndex, SafeColorEntry(0))
-        ColorEntry(0) = SafeColorEntry(0)
-        ColorEntry(1) = SafeColorEntry(1)
-        ColorEntry(2) = SafeColorEntry(2)
-        ColorEntry(3) = SafeColorEntry(3)
-    Else
-        GetColorEntryAsRGB = GDALCore.ObjIsNULLError
-    End If
-End Function
diff --git a/vb6/GDALCore.bas b/vb6/GDALCore.bas
deleted file mode 100644
index 13a23fa..0000000
--- a/vb6/GDALCore.bas
+++ /dev/null
@@ -1,506 +0,0 @@
-Attribute VB_Name = "GDALCore"
-'*****************************************************************************
-' $Id: GDALCore.bas 7980 2005-08-04 20:54:10Z fwarmerdam $
-'
-' Project:  GDAL VB6 Bindings
-' Purpose:  GDAL VB6 internal support functions.  Items in this module should
-'           only be used by the VB6 shadow classes and GDAL.bas.  Application
-'           level code should not need access to this module.
-' Author:   Frank Warmerdam, warmerdam at pobox.com
-'
-'*****************************************************************************
-' Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-'
-' Permission is hereby granted, free of charge, to any person obtaining a
-' copy of this software and associated documentation files (the "Software"),
-' to deal in the Software without restriction, including without limitation
-' the rights to use, copy, modify, merge, publish, distribute, sublicense,
-' and/or sell copies of the Software, and to permit persons to whom the
-' Software is furnished to do so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included
-' in all copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-' DEALINGS IN THE SOFTWARE.
-'*****************************************************************************
-'
-' $Log$
-' Revision 1.8  2005/08/04 20:53:51  fwarmerdam
-' convert to DOS text mode
-'
-' Revision 1.7  2005/04/11 19:58:47  fwarmerdam
-' added CPLSet/GetConfigOption
-'
-' Revision 1.6  2005/04/08 14:36:25  fwarmerdam
-' applied owned flag, and auto-destroy
-'
-' Revision 1.5  2005/04/06 22:30:15  fwarmerdam
-' added OGRCoordinateTransformation and OGRSpatialReference functions
-'
-' Revision 1.4  2005/04/04 15:34:30  fwarmerdam
-' fixed in bindings for colortable stuff per bug 814
-'
-' Revision 1.3  2005/04/04 15:32:35  fwarmerdam
-' use gdal12.dll
-'
-' Revision 1.2  2005/03/16 23:34:55  fwarmerdam
-' added colortable support
-'
-' Revision 1.1  2005/03/16 19:45:19  fwarmerdam
-' new
-'
-'
-
-' ****************************************************************************
-'               Declarations for C API functions.
-' ****************************************************************************
-
-Public Const ObjIsNULLError = 1001
- 
-' ----------------------------------------------------------------------------
-'       Misc
-' ----------------------------------------------------------------------------
-
-Public Declare Function GDALGetDataTypeName _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetDataTypeName at 4" _
-    (ByVal DataType As Long) As Long
-
-Public Declare Function GDALGetDataTypeSize _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetDataTypeSize at 4" _
-    (ByVal DataType As Long) As Long
-
-Public Declare Function CPLGetLastErrorMsg _
-    Lib "gdal12.dll" _
-    Alias "_CPLGetLastErrorMsg at 0" _
-    () As Long
-    
-Public Declare Sub CSLDestroy _
-    Lib "gdal12.dll" _
-    Alias "_CSLDestroy at 4" _
-    (ByVal CSLList As Long)
-    
-Public Declare Function CPLGetConfigOption _
-    Lib "gdal12.dll" _
-    Alias "_CPLGetConfigOption at 8" _
-    (ByVal Key As String, ByVal Default As String) As Long
-    
-Public Declare Sub CPLSetConfigOption _
-    Lib "gdal12.dll" _
-    Alias "_CPLSetConfigOption at 8" _
-    (ByVal Key As String, ByVal Value As String)
-    
-' ----------------------------------------------------------------------------
-'       GDALMajorObject
-' ----------------------------------------------------------------------------
-Public Declare Function GDALGetMetadataItem _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetMetadataItem at 12" _
-    (ByVal Handle As Long, ByVal Name As String, _
-     ByVal Domain As String) As Long
-
-Public Declare Function GDALGetMetadata _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetMetadata at 8" _
-    (ByVal Handle As Long, ByVal Domain As String) As Long
-
-Public Declare Function GDALSetMetadataItem _
-    Lib "gdal12.dll" _
-    Alias "_GDALSetMetadataItem at 16" _
-    (ByVal Handle As Long, ByVal Name As String, _
-     ByVal Value As String, ByVal Domain As String) As Long
-
-Public Declare Function GDALSetMetadata _
-    Lib "gdal12.dll" _
-    Alias "_GDALSetMetadata at 12" _
-    (ByVal Handle As Long, ByVal MetaData As Long, _
-     ByVal Domain As String) As Long
-
-Public Declare Function GDALGetDescription _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetDescription at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Sub GDALSetDescription _
-    Lib "gdal12.dll" _
-    Alias "_GDALSetDescription at 8" _
-    (ByVal Handle As Long, ByVal Description As String)
-
-' ----------------------------------------------------------------------------
-'       GDAL Dataset
-' ----------------------------------------------------------------------------
-Public Declare Function GDALOpen _
-    Lib "gdal12.dll" _
-    Alias "_GDALOpen at 8" _
-    (ByVal Filename As String, ByVal Access As Long) As Long
-    
-Public Declare Function GDALOpenShared _
-    Lib "gdal12.dll" _
-    Alias "_GDALOpenShared at 8" _
-    (ByVal Filename As String, ByVal Access As Long) As Long
-    
-Public Declare Sub GDALClose _
-    Lib "gdal12.dll" _
-    Alias "_GDALClose at 4" _
-    (ByVal Handle As Long)
-
-Public Declare Function GDALGetRasterXSize _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterXSize at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Function GDALGetRasterYSize _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterYSize at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Function GDALGetRasterCount _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterCount at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Function GDALGetRasterBand _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterBand at 8" _
-    (ByVal Handle As Long, ByVal BandNo As Long) As Long
-
-Public Declare Function GDALGetProjectionRef _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetProjectionRef at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Function GDALSetProjection _
-    Lib "gdal12.dll" _
-    Alias "_GDALSetProjection at 8" _
-    (ByVal Handle As Long, ByVal WKTProj As String) As Long
-
-Public Declare Function GDALGetGeoTransform _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetGeoTransform at 8" _
-    (ByVal Handle As Long, ByRef Geotransform As Double) As Long
-
-Public Declare Function GDALSetGeoTransform _
-    Lib "gdal12.dll" _
-    Alias "_GDALSetGeoTransform at 8" _
-    (ByVal Handle As Long, ByRef Geotransform As Double) As Long
-
-Public Declare Function GDALReferenceDataset _
-    Lib "gdal12.dll" _
-    Alias "_GDALReferenceDataset at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Function GDALDereferenceDataset _
-    Lib "gdal12.dll" _
-    Alias "_GDALDereferenceDataset at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Sub GDALFlushCache _
-    Lib "gdal12.dll" _
-    Alias "_GDALFlushCache at 4" _
-    (ByVal Handle As Long)
-
-' ----------------------------------------------------------------------------
-'       GDALRasterBand
-' ----------------------------------------------------------------------------
-Public Declare Function GDALGetRasterDataType _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterDataType at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Function GDALGetRasterBandXSize _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterBandXSize at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Function GDALGetRasterBandYSize _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterBandYSize at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Sub GDALGetBlockSize _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetBlockSize at 12" _
-    (ByVal Handle As Long, ByRef XSize As Long, ByRef YSize As Long)
-
-Public Declare Function GDALGetRasterNoDataValue _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterNoDataValue at 8" _
-    (ByVal Handle As Long, ByRef bSuccess As Long) As Double
-    
-Public Declare Function GDALSetRasterNoDataValue _
-    Lib "gdal12.dll" _
-    Alias "_GDALSetRasterNoDataValue at 12" _
-    (ByVal Handle As Long, ByVal NoDataValue As Double) As Long
-
-Public Declare Function GDALGetRasterMinimum _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterMinimum at 8" _
-    (ByVal Handle As Long, ByRef bSuccess As Long) As Double
-
-Public Declare Function GDALGetRasterMaximum _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterMaximum at 8" _
-    (ByVal Handle As Long, ByRef bSuccess As Long) As Double
-
-Public Declare Function GDALGetRasterOffset _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterOffset at 8" _
-    (ByVal Handle As Long, ByRef bSuccess As Long) As Double
-
-Public Declare Function GDALSetRasterOffset _
-    Lib "gdal12.dll" _
-    Alias "_GDALSetRasterOffset at 12" _
-    (ByVal Handle As Long, ByVal Offset As Double) As Long
-
-Public Declare Function GDALGetRasterScale _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterScale at 8" _
-    (ByVal Handle As Long, ByRef bSuccess As Long) As Double
-
-Public Declare Function GDALSetRasterScale _
-    Lib "gdal12.dll" _
-    Alias "_GDALSetRasterScale at 12" _
-    (ByVal Handle As Long, ByVal NewScale As Double) As Long
-
-Public Declare Function GDALRasterIO _
-    Lib "gdal12.dll" _
-    Alias "_GDALRasterIO at 48" _
-    (ByVal Handle As Long, ByVal RWFlag As Long, _
-     ByVal XOff As Long, ByVal YOff As Long, _
-     ByVal XSize As Long, ByVal YSize As Long, _
-     ByVal pData As Long, ByVal BufXSize As Long, ByVal BufYSize As Long, _
-     ByVal DataType As Long, _
-     ByVal PixelSpace As Long, ByVal LineSpace As Long) As Long
-
-Public Declare Function GDALGetRasterColorTable _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetRasterColorTable at 4" _
-    (ByVal Handle As Long) As Long
-
-Public Declare Function GDALSetRasterColorTable _
-    Lib "gdal12.dll" _
-    Alias "_GDALSetRasterColorTable at 8" _
-    (ByVal BandHandle As Long, ByVal TableHandle As Long) As Long
-
-' ----------------------------------------------------------------------------
-'       GDALDriver
-' ----------------------------------------------------------------------------
-Public Declare Sub GDALAllRegister _
-    Lib "gdal12.dll" _
-    Alias "_GDALAllRegister at 0" ()
-
-Public Declare Function GDALGetDriverByName _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetDriverByName at 4" _
-    (ByVal Filename As String) As Long
-
-Public Declare Function GDALGetDriverCount _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetDriverCount at 0" () As Long
-
-Public Declare Function GDALGetDriver _
-    Lib "gdal12.dll" _
-    Alias "_GDALGetDriver at 4" _
-    (ByVal DriverIndex As Long) As Long
-
-Public Declare Sub GDALDestroyDriverManager _
-    Lib "gdal12.dll" _
-    Alias "_GDALDestroyDriverManager at 0" ()
-
-Public Declare Function GDALCreate _
-    Lib "gdal12.dll" _
-    Alias "_GDALCreate at 28" _
-    (ByVal Handle As Long, ByVal Filename As String, _
-     ByVal XSize As Long, ByVal YSize As Long, ByVal BandCount As Long, _
-     ByVal DataType As Long, ByVal Options As Long) As Long
-
-Public Declare Function GDALCreateCopy _
-    Lib "gdal12.dll" _
-    Alias "_GDALCreateCopy at 28" _
-    (ByVal Handle As Long, ByVal Filename As String, _
-     ByVal SrcDS As Long, ByVal ApproxOK As Long, ByVal Options As Long, _
-     ByVal ProgressFunc As Long, ByVal ProgressArg As Long) As Long
-
-' ----------------------------------------------------------------------------
-'       GDALColorTable
-' ----------------------------------------------------------------------------
-Public Declare Function GDALCreateColorTable _
-        Lib "gdal12.dll" _
-        Alias "_GDALCreateColorTable at 4" _
-        (ByVal PaletteInterp As Long) As Long
-
-Public Declare Sub GDALDestroyColorTable _
-        Lib "gdal12.dll" _
-        Alias "_GDALDestroyColorTable at 4" _
-        (ByVal Handle As Long)
-
-Public Declare Function GDALCloneColorTable _
-        Lib "gdal12.dll" _
-        Alias "_GDALCloneColorTable at 4" _
-        (ByVal Handle As Long) As Long
-
-Public Declare Function GDALGetPaletteInterpretation _
-        Lib "gdal12.dll" _
-        Alias "_GDALGetPaletteInterpretation at 4" _
-        (ByVal Handle As Long) As Long
-
-Public Declare Function GDALGetColorEntryCount _
-        Lib "gdal12.dll" _
-        Alias "_GDALGetColorEntryCount at 4" _
-        (ByVal Handle As Long) As Long
-
-Public Declare Function GDALGetColorEntryAsRGB _
-        Lib "gdal12.dll" _
-        Alias "_GDALGetColorEntryAsRGB at 12" _
-        (ByVal Handle As Long, ByVal ColorIndex As Long, _
-          ByRef ColorEntry As Integer) As Long
-
-Public Declare Function GDALGetColorEntry _
-        Lib "gdal12.dll" _
-        Alias "_GDALGetColorEntry at 12" _
-        (ByVal Handle As Long, ByVal ColorIndex As Long, _
-          ByRef ColorEntry As Integer) As Long
-     
-Public Declare Sub GDALSetColorEntry _
-        Lib "gdal12.dll" _
-        Alias "_GDALSetColorEntry at 12" _
-        (ByVal Handle As Long, ByVal ColorIndex As Long, _
-          ByRef ColorEntry As Integer)
-
-' ----------------------------------------------------------------------------
-'       OGRSpatialReference
-' ----------------------------------------------------------------------------
-Public Declare Function OSRNewSpatialReference _
-        Lib "gdal12.dll" _
-        Alias "_OSRNewSpatialReference at 4" _
-        (ByVal WKT As String) As Long
-
-Public Declare Function OSRCloneGeogCS _
-        Lib "gdal12.dll" _
-        Alias "_OSRCloneGeogCS at 4" _
-        (ByVal Handle As Long) As Long
-
-Public Declare Function OSRClone _
-        Lib "gdal12.dll" _
-        Alias "_OSRClone at 4" _
-        (ByVal Handle As Long) As Long
-
-Public Declare Sub OSRDestroySpatialReference _
-        Lib "gdal12.dll" _
-        Alias "_OSRDestroySpatialReference at 4" _
-        (ByVal Handle As Long)
-
-Public Declare Function OSRImportFromEPSG _
-        Lib "gdal12.dll" _
-        Alias "_OSRImportFromEPSG at 8" _
-        (ByVal Handle As Long, EPSGCode As Long) As Long
-
-Public Declare Function OSRExportToWkt _
-        Lib "gdal12.dll" _
-        Alias "_OSRExportToWkt at 8" _
-        (ByVal Handle As Long, ByRef wktptr As Long) As Long
-
-Public Declare Function OSRExportToPrettyWkt _
-        Lib "gdal12.dll" _
-        Alias "_OSRExportToPrettyWkt at 12" _
-        (ByVal Handle As Long, ByRef wktptr As Long, Simplify As Long) As Long
-
-Public Declare Function OSRSetFromUserInput _
-        Lib "gdal12.dll" _
-        Alias "_OSRSetFromUserInput at 8" _
-        (ByVal Handle As Long, ByVal UserInput As String) As Long
-
-Public Declare Function OSRSetAttrValue _
-        Lib "gdal12.dll" _
-        Alias "_OSRSetAttrValue at 12" _
-        (ByVal Handle As Long, ByVal NodePath As String, _
-        ByVal NodeValue As String) As Long
-
-Public Declare Function OSRGetAttrValue _
-        Lib "gdal12.dll" _
-        Alias "_OSRGetAttrValue at 12" _
-        (ByVal Handle As Long, ByVal NodePath As String, _
-        ByVal iChild As Long) As Long
-
-' ----------------------------------------------------------------------------
-' OGRCoordinateTransformation
-' ----------------------------------------------------------------------------
-Public Declare Function OCTNewCoordinateTransformation _
-        Lib "gdal12.dll" _
-        Alias "_OCTNewCoordinateTransformation at 8" _
-        (ByVal hSourceSRS As Long, ByVal hTargetSRS As Long) As Long
-
-Public Declare Sub OCTDestroyCoordinateTransformation _
-        Lib "gdal12.dll" _
-        Alias "_OCTDestroyCoordinateTransformation at 4" _
-        (ByVal Handle As Long)
-
-Public Declare Function OCTTransformEx _
-        Lib "gdal12.dll" _
-        Alias "_OCTTransformEx at 24" _
-        (ByVal Handle As Long, ByVal PointCount As Long, _
-        ByRef X As Double, ByRef Y As Double, ByRef Z As Double, _
-        ByRef Success As Long) As Long
-
-' ----------------------------------------------------------------------------
-' Special VB6 Support functions
-' ----------------------------------------------------------------------------
-Public Declare Function CStringToVB6 _
-    Lib "gdal12.dll" _
-    Alias "_vbCStringToVB6 at 8" _
-    (result As Variant, ByVal cString As Long) As Long
-    
-Public Declare Function VariantToCSL _
-    Lib "gdal12.dll" _
-    Alias "_vbVariantToCSL at 4" _
-    (InList As Variant) As Long
-    
-Public Declare Sub CSLToVariant _
-    Lib "gdal12.dll" _
-    Alias "_vbCSLToVariant at 8" _
-    (ByVal InList As Long, OutList As Variant)
-    
-Public Declare Function SafeArrayToPtr _
-    Lib "gdal12.dll" _
-    Alias "_vbSafeArrayToPtr at 16" _
-    (InArray As Variant, ByRef DataType As Long, _
-     ByRef XSize As Long, ByRef YSize As Long) As Long
-    
-' ****************************************************************************
-'       VB Wrapper functions.
-' ****************************************************************************
-
-' ----------------------------------------------------------------------------
-Public Function CStr2VB(c_str As Long)
-    Dim msg As Variant
-    Dim n As Long
-    n = CStringToVB6(msg, c_str)
-    CStr2VB = msg
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetMetadata(MajorObject As Long, Domain As String)
-    Dim CSLMetadata As Long
-    Dim ResultMD As Variant
-   
-    CSLMetadata = GDALGetMetadata(MajorObject, Domain)
-    Call CSLToVariant(CSLMetadata, ResultMD)
-    GetMetadata = ResultMD
-End Function
-
-Public Function SetMetadata(Object As Long, MetaData As Variant, _
-                             Domain As String)
-    Dim CSLMetadata As Long
-
-    CSLMetadata = VariantToCSL(MetaData)
-    SetMetadata = GDALSetMetadata(Object, CSLMetadata, Domain)
-    Call CSLDestroy(CSLMetadata)
-End Function
-
diff --git a/vb6/GDALDataset.cls b/vb6/GDALDataset.cls
deleted file mode 100644
index fb959ed..0000000
--- a/vb6/GDALDataset.cls
+++ /dev/null
@@ -1,231 +0,0 @@
-'*****************************************************************************
-' $Id: GDALDataset.cls 7980 2005-08-04 20:54:10Z fwarmerdam $
-'
-' Project:  GDAL VB6 Bindings
-' Purpose:  VB6 GDALDataset Shadow Class.
-' Author:   Frank Warmerdam, warmerdam at pobox.com
-'
-'*****************************************************************************
-' Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-'
-' Permission is hereby granted, free of charge, to any person obtaining a
-' copy of this software and associated documentation files (the "Software"),
-' to deal in the Software without restriction, including without limitation
-' the rights to use, copy, modify, merge, publish, distribute, sublicense,
-' and/or sell copies of the Software, and to permit persons to whom the
-' Software is furnished to do so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included
-' in all copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-' DEALINGS IN THE SOFTWARE.
-'*****************************************************************************
-'
-' $Log$
-' Revision 1.3  2005/08/04 20:53:51  fwarmerdam
-' convert to DOS text mode
-'
-' Revision 1.2  2005/04/08 14:36:25  fwarmerdam
-' applied owned flag, and auto-destroy
-'
-' Revision 1.1  2005/03/16 19:45:19  fwarmerdam
-' new
-'
-'
-
-VERSION 1.0 CLASS
-BEGIN
-  MultiUse = -1  'True
-  Persistable = 0  'NotPersistable
-  DataBindingBehavior = 0  'vbNone
-  DataSourceBehavior  = 0  'vbNone
-  MTSTransactionMode  = 0  'NotAnMTSObject
-END
-Attribute VB_Name = "GDALDataset"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = True
-Attribute VB_PredeclaredId = False
-Attribute VB_Exposed = False
-
-Option Explicit
-Private obj As Long
-Private owned As Long
-Public XSize As Long
-Public YSize As Long
-Public BandCount As Long
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Initialize()
-    obj = 0
-    owned = 0
-    XSize = 0
-    YSize = 0
-    BandCount = 0
-End Sub
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Terminate()
-    If obj <> 0 and owned <> 0 Then
-        call CloseDS()
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub CInit(obj_in As Long, owned_in As Long )
-    obj = obj_in
-    owned = owned_in
-    If obj <> 0 Then
-        XSize = GDALCore.GDALGetRasterXSize(obj)
-        YSize = GDALCore.GDALGetRasterYSize(obj)
-        BandCount = GDALCore.GDALGetRasterCount(obj)
-    End If
-End Sub
-' ----------------------------------------------------------------------------
-Public Function IsValid() As Boolean
-
-    If obj = 0 Then
-        IsValid = False
-    Else
-        IsValid = True
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetObjPtr() As Long
-    GetObjPtr = obj
-End Function
-
-' ----------------------------------------------------------------------------
-Public Sub CloseDS()
-    If obj <> 0 Then
-        'Call MsgBox("CloseDS " & GetDescription() )
-        Call GDALCore.GDALClose(obj)
-        obj = 0
-        owned = 0
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub FlushCache()
-    If obj <> 0 Then
-        Call GDALCore.GDALFlushCache(obj)
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Function GetRasterBand(ByVal BandNo As Long) As GDALRasterBand
-    Dim c_obj As Long
-    Dim band As GDALRasterBand
-    
-    Set band = Nothing
-    If obj <> 0 Then
-        c_obj = GDALCore.GDALGetRasterBand(obj, BandNo)
-        If c_obj <> 0 Then
-            Set band = New GDALRasterBand
-            band.CInit (c_obj)
-        End If
-    End If
-    Set GetRasterBand = band
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetProjection() As String
-    Dim c_str As Long
-    
-    If obj <> 0 Then
-        c_str = GDALCore.GDALGetProjectionRef(obj)
-        GetProjection = GDALCore.CStr2VB(c_str)
-    Else
-        GetProjection = ""
-    End If
-End Function
-' ----------------------------------------------------------------------------
-Public Function SetProjection(WKTProj As String) As String
-    Dim err As Long
-    
-    If obj <> 0 Then
-        SetProjection = GDALCore.GDALSetProjection(obj, WKTProj)
-    Else
-        SetProjection = GDALCore.ObjIsNULLError
-    End If
-End Function
-' ----------------------------------------------------------------------------
-Public Function GetGeoTransform(Geotransform() As Double) As Long
-    Dim gtsafe() As Double
-    ReDim gtsafe(6) As Double
-    
-    If obj <> 0 Then
-        GetGeoTransform = GDALCore.GDALGetGeoTransform(obj, gtsafe(0))
-        Geotransform(0) = gtsafe(0)
-        Geotransform(1) = gtsafe(1)
-        Geotransform(2) = gtsafe(2)
-        Geotransform(3) = gtsafe(3)
-        Geotransform(4) = gtsafe(4)
-        Geotransform(5) = gtsafe(5)
-    Else
-        GetGeoTransform = GDALCore.ObjIsNULLError
-    End If
-End Function
-' ----------------------------------------------------------------------------
-Public Function SetGeoTransform(Geotransform() As Double) As Long
-    Dim gtsafe() As Double
-    ReDim gtsafe(6) As Double
-    
-    If obj <> 0 Then
-        Dim i As Integer
-        For i = 0 To 5
-                gtsafe(i) = Geotransform(i)
-        Next i
-        SetGeoTransform = GDALCore.GDALSetGeoTransform(obj, gtsafe(0))
-    Else
-        SetGeoTransform = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetMetadata(Domain As String) As Variant
-    If obj <> 0 Then
-        GetMetadata = GDALCore.GetMetadata(obj, Domain)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetMetadata(MetaData As Variant, Domain As String) As Variant
-    If obj <> 0 Then
-        SetMetadata = GDALCore.SetMetadata(obj, MetaData, Domain)
-    Else
-        SetMetadata = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetMetadataItem(Name As String, Domain As String) As String
-    If obj <> 0 Then
-        GetMetadataItem = GDALCore.CStr2VB(GDALCore.GDALGetMetadataItem(obj, Name, Domain))
-    Else
-        GetMetadataItem = vbNullString
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetMetadataItem(Name As String, _
-                                Value As String, Domain As String) As Long
-    If obj <> 0 Then
-        SetMetadataItem = GDALCore.GDALSetMetadataItem(obj, Name, Value, Domain)
-    Else
-        SetMetadataItem = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetDescription() As String
-    If obj <> 0 Then
-        GetDescription = GDALCore.CStr2VB(GDALCore.GDALGetDescription(obj))
-    End If
-End Function
diff --git a/vb6/GDALDriver.cls b/vb6/GDALDriver.cls
deleted file mode 100644
index d67a072..0000000
--- a/vb6/GDALDriver.cls
+++ /dev/null
@@ -1,157 +0,0 @@
-'*****************************************************************************
-' $Id: GDALDriver.cls 7980 2005-08-04 20:54:10Z fwarmerdam $
-'
-' Project:  GDAL VB6 Bindings
-' Purpose:  VB6 GDALDriver Shadow Class.
-' Author:   Frank Warmerdam, warmerdam at pobox.com
-'
-'*****************************************************************************
-' Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-'
-' Permission is hereby granted, free of charge, to any person obtaining a
-' copy of this software and associated documentation files (the "Software"),
-' to deal in the Software without restriction, including without limitation
-' the rights to use, copy, modify, merge, publish, distribute, sublicense,
-' and/or sell copies of the Software, and to permit persons to whom the
-' Software is furnished to do so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included
-' in all copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-' DEALINGS IN THE SOFTWARE.
-'*****************************************************************************
-'
-' $Log$
-' Revision 1.3  2005/08/04 20:53:51  fwarmerdam
-' convert to DOS text mode
-'
-' Revision 1.2  2005/04/08 14:36:25  fwarmerdam
-' applied owned flag, and auto-destroy
-'
-' Revision 1.1  2005/03/16 19:45:19  fwarmerdam
-' new
-'
-'
-
-VERSION 1.0 CLASS
-BEGIN
-  MultiUse = -1  'True
-  Persistable = 0  'NotPersistable
-  DataBindingBehavior = 0  'vbNone
-  DataSourceBehavior  = 0  'vbNone
-  MTSTransactionMode  = 0  'NotAnMTSObject
-END
-Attribute VB_Name = "GDALDriver"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = True
-Attribute VB_PredeclaredId = False
-Attribute VB_Exposed = False
-Option Explicit
-Private obj As Long
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Initialize()
-    obj = 0
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub CInit(obj_in As Long)
-    obj = obj_in
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Function Create(ByVal Filename As String, _
-     ByVal XSize As Long, ByVal YSize As Long, ByVal BandCount As Long, _
-     ByVal DataType As Long, Options As Variant) As GDALDataset
-
-    If obj <> 0 Then
-        Dim CSLOptions As Long, ds_obj As Long
-
-        CSLOptions = GDALCore.VariantToCSL(Options)
-        ds_obj = GDALCore.GDALCreate(obj, Filename, XSize, YSize, BandCount, _
-                                     DataType, CSLOptions)
-        Call GDALCore.CSLDestroy(CSLOptions)
-
-        If ds_obj <> 0 Then
-            Dim ds As New GDALDataset
-            Call ds.CInit(ds_obj,1)
-            Set Create = ds
-        End If
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function CreateCopy(Filename As String, SrcDS As GDALDataset, _
-     ApproxOK As Boolean, Options As Variant) As GDALDataset
-
-    If obj <> 0 And SrcDS.GetObjPtr() Then
-        Dim CSLOptions As Long, ds_obj As Long, ApproxOK_Int As Long
-
-        If ApproxOK Then
-            ApproxOK_Int = 1
-        Else
-            ApproxOK_Int = 0
-        End If
-  
-        CSLOptions = GDALCore.VariantToCSL(Options)
-        ds_obj = GDALCore.GDALCreateCopy(obj, Filename, SrcDS.GetObjPtr(), _
-                                         ApproxOK_Int, CSLOptions, 0, 0)
-        Call GDALCore.CSLDestroy(CSLOptions)
-
-        If ds_obj <> 0 Then
-            Dim ds As New GDALDataset
-            Call ds.CInit(ds_obj,1)
-            Set CreateCopy = ds
-        End If
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetMetadata(Domain As String) As Variant
-    If obj <> 0 Then
-        GetMetadata = GDALCore.GetMetadata(obj, Domain)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetMetadata(MetaData As Variant, Domain As String) As Variant
-    If obj <> 0 Then
-        SetMetadata = GDALCore.SetMetadata(obj, MetaData, Domain)
-    Else
-        SetMetadata = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetMetadataItem(Name As String, Domain As String) As String
-    If obj <> 0 Then
-        GetMetadataItem = GDALCore.CStr2VB(GDALCore.GDALGetMetadataItem(obj, _
-					   Name, Domain))
-    Else
-        GetMetadataItem = vbNullString
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetMetadataItem(Name As String, _
-                                Value As String, Domain As String) As Long
-    If obj <> 0 Then
-        SetMetadataItem = GDALCore.GDALSetMetadataItem(obj, Name, Value, Domain)
-    Else
-        SetMetadataItem = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetShortName() As String
-    If obj <> 0 Then
-        GetShortName = GDALCore.CStr2VB(GDALCore.GDALGetDescription(obj))
-    End If
-End Function
-
diff --git a/vb6/GDALRasterBand.cls b/vb6/GDALRasterBand.cls
deleted file mode 100644
index dbaa27e..0000000
--- a/vb6/GDALRasterBand.cls
+++ /dev/null
@@ -1,241 +0,0 @@
-'*****************************************************************************
-' $Id: GDALRasterBand.cls 7980 2005-08-04 20:54:10Z fwarmerdam $
-'
-' Project:  GDAL VB6 Bindings
-' Purpose:  VB6 GDALRasterBand Shadow Class.
-' Author:   Frank Warmerdam, warmerdam at pobox.com
-'
-'*****************************************************************************
-' Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-'
-' Permission is hereby granted, free of charge, to any person obtaining a
-' copy of this software and associated documentation files (the "Software"),
-' to deal in the Software without restriction, including without limitation
-' the rights to use, copy, modify, merge, publish, distribute, sublicense,
-' and/or sell copies of the Software, and to permit persons to whom the
-' Software is furnished to do so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included
-' in all copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-' DEALINGS IN THE SOFTWARE.
-'*****************************************************************************
-'
-' $Log$
-' Revision 1.5  2005/08/04 20:53:51  fwarmerdam
-' convert to DOS text mode
-'
-' Revision 1.4  2005/04/08 14:36:25  fwarmerdam
-' applied owned flag, and auto-destroy
-'
-' Revision 1.3  2005/04/06 22:30:39  fwarmerdam
-' fixed some color table stuff, added headers
-'
-'
-
-VERSION 1.0 CLASS
-BEGIN
-  MultiUse = -1  'True
-  Persistable = 0  'NotPersistable
-  DataBindingBehavior = 0  'vbNone
-  DataSourceBehavior  = 0  'vbNone
-  MTSTransactionMode  = 0  'NotAnMTSObject
-END
-Attribute VB_Name = "GDALRasterBand"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = True
-Attribute VB_PredeclaredId = False
-Attribute VB_Exposed = False
-
-' ----------------------------------------------------------------------------
-Option Explicit
-
-Private obj As Long
-Public XSize As Long
-Public YSize As Long
-Public BlockXSize As Long
-Public BlockYSize As Long
-Public DataType As Long
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Initialize()
-    obj = 0
-    XSize = 0
-    YSize = 0
-    BlockXSize = 0
-    BlockYSize = 0
-    DataType = 0
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub CInit(obj_in As Long)
-    obj = obj_in
-    XSize = GDALCore.GDALGetRasterBandXSize(obj)
-    YSize = GDALCore.GDALGetRasterBandYSize(obj)
-    Call GDALCore.GDALGetBlockSize(obj, BlockXSize, BlockYSize)
-    DataType = GDALCore.GDALGetRasterDataType(obj)
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Function GetMinimum()
-    Dim Success As Long
-    If obj <> 0 Then
-        GetMinimum = GDALCore.GDALGetRasterMinimum(obj, Success)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetMaximum()
-    Dim Success As Long
-    If obj <> 0 Then
-        GetMaximum = GDALCore.GDALGetRasterMaximum(obj, Success)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetOffset() As Double
-    Dim Success As Long
-    If obj <> 0 Then
-        GetOffset = GDALCore.GDALGetRasterOffset(obj, Success)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetOffset(ByVal Offset As Double) As Long
-    If obj <> 0 Then
-        SetOffset = GDALCore.GDALSetRasterOffset(obj, Offset)
-    Else
-        SetOffset = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetScale() As Double
-    Dim Success As Long
-    If obj <> 0 Then
-        GetScale = GDALCore.GDALGetRasterScale(obj, Success)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetScale(ByVal NewScale As Double) As Long
-    If obj <> 0 Then
-        SetScale = GDALCore.GDALSetRasterScale(obj, NewScale)
-    Else
-        SetScale = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetNoDataValue(ByRef Success As Long)
-    If obj <> 0 Then
-        GetNoDataValue = GDALCore.GDALGetRasterNoDataValue(obj, Success)
-    Else
-        Success = 0
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetNoDataValue(ByVal NoDataValue As Double)
-    If obj <> 0 Then
-        SetNoDataValue = GDALCore.GDALSetRasterNoDataValue(obj, NoDataValue)
-    Else
-        SetNoDataValue = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function RasterIO _
-    (ByVal RWFlag As Long, _
-     ByVal XOff As Long, ByVal YOff As Long, _
-     ByVal XSize As Long, ByVal YSize As Long, _
-     DataArray As Variant) As Long
-
-    If obj <> 0 Then
-        Dim BufXSize, BufYSize, RawPtr, DataType As Long
-        RawPtr = GDALCore.SafeArrayToPtr(DataArray, DataType, _
-                                          BufXSize, BufYSize)
-
-        If RawPtr <> 0 Then
-            RasterIO = GDALCore.GDALRasterIO( _
-                obj, RWFlag, XOff, YOff, XSize, YSize, _
-                RawPtr, BufXSize, BufYSize, DataType, 0, 0)
-        Else
-            RasterIO = 3 ' CE_Failure
-        End If
-    Else
-        RasterIO = GDALCore.ObjIsNULLError
-    End If
-
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetMetadata(Domain As String) As Variant
-    If obj <> 0 Then
-        GetMetadata = GDALCore.GetMetadata(obj, Domain)
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetMetadata(MetaData As Variant, Domain As String) As Variant
-    If obj <> 0 Then
-        SetMetadata = GDALCore.SetMetadata(obj, MetaData, Domain)
-    Else
-        SetMetadata = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetMetadataItem(Name As String, Domain As String) As String
-    If obj <> 0 Then
-        GetMetadataItem = GDALCore.CStr2VB(GDALCore.GDALGetMetadataItem(obj, Name, Domain))
-    Else
-        GetMetadataItem = vbNullString
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetMetadataItem(Name As String, _
-                                Value As String, Domain As String) As Long
-    If obj <> 0 Then
-        SetMetadataItem = GDALCore.GDALSetMetadataItem(obj, Name, Value, Domain)
-    Else
-        SetMetadataItem = GDALCore.ObjIsNULLError
-    End If
-End Function
-' ----------------------------------------------------------------------------
-Public Function GetDescription() As String
-    If obj <> 0 Then
-        GetDescription = GDALCore.CStr2VB(GDALCore.GDALGetDescription(obj))
-    End If
-End Function
-' ----------------------------------------------------------------------------
-Public Function GetColorTable() As GDALColorTable
-    Dim ct As New GDALColorTable
-    If obj <> 0 Then
-        Dim CTHandle As Long
-
-        CTHandle = GDALCore.GDALGetRasterColorTable(obj)
-        If CTHandle <> 0 Then
-            Call ct.CInit(CTHandle,0)
-        End If
-    End If
-    Set GetColorTable = ct
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetColorTable(ColorTable As GDALColorTable) As Long
-    If obj <> 0 And ColorTable.GetObjPtr() <> 0 Then
-        SetColorTable = GDALCore.GDALSetRasterColorTable( _
-                obj, ColorTable.GetObjPtr())
-    Else
-        SetColorTable = GDALCore.ObjIsNULLError
-    End If
-End Function
-
diff --git a/vb6/OGRCoordinateTransformation.cls b/vb6/OGRCoordinateTransformation.cls
deleted file mode 100644
index 8db4328..0000000
--- a/vb6/OGRCoordinateTransformation.cls
+++ /dev/null
@@ -1,176 +0,0 @@
-'*****************************************************************************
-
-
-' $Id: OGRCoordinateTransformation.cls 9361 2006-03-22 04:38:16Z fwarmerdam $
-
-
-'
-
-
-' Project:  GDAL VB6 Bindings
-
-
-' Purpose:  VB6 OGRCoordinateTransformation Shadow Class.
-
-
-' Author:   Frank Warmerdam, warmerdam at pobox.com
-
-
-'
-
-
-'*****************************************************************************
-
-
-' Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-
-
-'
-
-
-' Permission is hereby granted, free of charge, to any person obtaining a
-
-
-' copy of this software and associated documentation files (the "Software"),
-
-
-' to deal in the Software without restriction, including without limitation
-
-
-' the rights to use, copy, modify, merge, publish, distribute, sublicense,
-
-
-' and/or sell copies of the Software, and to permit persons to whom the
-
-
-' Software is furnished to do so, subject to the following conditions:
-
-
-'
-
-
-' The above copyright notice and this permission notice shall be included
-
-
-' in all copies or substantial portions of the Software.
-
-
-'
-
-
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-
-
-' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-
-
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-
-
-' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-
-
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-
-
-' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-
-
-' DEALINGS IN THE SOFTWARE.
-
-
-'*****************************************************************************
-
-
-'
-
-
-' $Log$
-' Revision 1.5  2006/03/22 04:38:16  fwarmerdam
-' fixed header
-'
-' Revision 1.4  2006/03/22 04:37:10  fwarmerdam
-' Added copyright header
-'
-'
-
-VERSION 1.0 CLASS
-BEGIN
-  MultiUse = -1  'True
-  Persistable = 0  'NotPersistable
-  DataBindingBehavior = 0  'vbNone
-  DataSourceBehavior  = 0  'vbNone
-  MTSTransactionMode  = 0  'NotAnMTSObject
-END
-Attribute VB_Name = "OGRCoordinateTransformation"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = True
-Attribute VB_PredeclaredId = False
-Attribute VB_Exposed = False
-
-' ----------------------------------------------------------------------------
-Option Explicit
-
-Private obj As Long
-Private owned As Long
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Initialize()
-    obj = 0
-    owned = 0
-End Sub
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Terminate()
-    If obj <> 0 And owned <> 0 Then
-        Call Destroy
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub CInit(obj_in As Long, owned_in As Long)
-    If obj <> 0 Then
-        Call GDALCore.OCTDestroyCoordinateTransformation(obj)
-    End If
-    obj = obj_in
-    owned = owned_in
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub Destroy()
-    If obj <> 0 Then
-        Call GDALCore.OCTDestroyCoordinateTransformation(obj)
-'        Call MsgBox("Destroying OGRCoordinateTransformation")
-        obj = 0
-        owned = 0
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Function IsValid() As Boolean
-    If obj <> 0 Then
-        IsValid = True
-    Else
-        IsValid = False
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-' Eventually we might add a multi-point version but this is simple
-' to do for now, and quite useful.
-Public Function TransformOne(ByRef X As Double, ByRef Y As Double, _
-                              ByRef Z As Double) As Boolean
-    If obj <> 0 Then
-        Dim Success As Long
-        Dim RetValue As Long
-
-        RetValue = GDALCore.OCTTransformEx(obj, 1, X, Y, Z, Success)
-        If Success = 0 Or RetValue = 0 Then
-            TransformOne = False
-        Else
-            TransformOne = True
-        End If
-    Else
-        TransformOne = False
-    End If
-End Function
diff --git a/vb6/OGRSpatialReference.cls b/vb6/OGRSpatialReference.cls
deleted file mode 100644
index be22bb6..0000000
--- a/vb6/OGRSpatialReference.cls
+++ /dev/null
@@ -1,246 +0,0 @@
-'*****************************************************************************
-
-
-' $Id: OGRSpatialReference.cls 9360 2006-03-22 04:38:09Z fwarmerdam $
-
-
-'
-
-
-' Project:  GDAL VB6 Bindings
-
-
-' Purpose:  VB6 OGRSpatialReference Shadow Class.
-
-
-' Author:   Frank Warmerdam, warmerdam at pobox.com
-
-
-'
-
-
-'*****************************************************************************
-
-
-' Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-
-
-'
-
-
-' Permission is hereby granted, free of charge, to any person obtaining a
-
-
-' copy of this software and associated documentation files (the "Software"),
-
-
-' to deal in the Software without restriction, including without limitation
-
-
-' the rights to use, copy, modify, merge, publish, distribute, sublicense,
-
-
-' and/or sell copies of the Software, and to permit persons to whom the
-
-
-' Software is furnished to do so, subject to the following conditions:
-
-
-'
-
-
-' The above copyright notice and this permission notice shall be included
-
-
-' in all copies or substantial portions of the Software.
-
-
-'
-
-
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-
-
-' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-
-
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-
-
-' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-
-
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-
-
-' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-
-
-' DEALINGS IN THE SOFTWARE.
-
-
-'*****************************************************************************
-
-
-'
-
-
-' $Log$
-' Revision 1.4  2006/03/22 04:38:09  fwarmerdam
-' Added copyright header
-'
-'
-'
-
-VERSION 1.0 CLASS
-BEGIN
-  MultiUse = -1  'True
-  Persistable = 0  'NotPersistable
-  DataBindingBehavior = 0  'vbNone
-  DataSourceBehavior  = 0  'vbNone
-  MTSTransactionMode  = 0  'NotAnMTSObject
-END
-Attribute VB_Name = "OGRSpatialReference"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = True
-Attribute VB_PredeclaredId = False
-Attribute VB_Exposed = False
-
-' ----------------------------------------------------------------------------
-Option Explicit
-
-Private obj As Long
-Private owned As Long
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Initialize()
-    obj = GDALCore.OSRNewSpatialReference("")
-    owned = 1
-End Sub
-
-' ----------------------------------------------------------------------------
-Private Sub Class_Terminate()
-    If obj <> 0 And owned <> 0 Then
-        Call Destroy
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub CInit(obj_in As Long, owned_in As Long)
-    If obj <> 0 And owned <> 0 Then
-        Call Destroy
-        Call GDALCore.OSRDestroySpatialReference(obj)
-    End If
-    obj = obj_in
-    owned = owned_in
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Sub Destroy()
-    If obj <> 0 Then
-        'Call MsgBox("Destroy OGRSpatialReference: " & ExportToWkt())
-        Call GDALCore.OSRDestroySpatialReference(obj)
-        obj = 0
-        owned = 0
-    End If
-End Sub
-
-' ----------------------------------------------------------------------------
-Public Function GetObjPtr() As Long
-    GetObjPtr = obj
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetFromUserInput(InputText As String) As Long
-    If obj <> 0 Then
-        SetFromUserInput = GDALCore.OSRSetFromUserInput(obj, InputText)
-    Else
-        SetFromUserInput = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function Clone() As OGRSpatialReference
-    Dim srs As New OGRSpatialReference
-    If obj <> 0 Then
-        Dim obj_new As Long
-  
-        obj_new = GDALCore.OSRClone(obj)
-        Call srs.CInit(obj_new, 1)
-    End If
-    Set Clone = srs
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function CloneGeogCS() As OGRSpatialReference
-    Dim srs As New OGRSpatialReference
-    If obj <> 0 Then
-        Dim obj_new As Long
-  
-        obj_new = GDALCore.OSRCloneGeogCS(obj)
-        Call srs.CInit(obj_new, 1)
-    End If
-    Set CloneGeogCS = srs
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function ImportFromEPSG(EPSGCode As Long) As Long
-    If obj <> 0 Then
-        ImportFromEPSG = GDALCore.OSRImportFromEPSG(obj, EPSGCode)
-    Else
-        ImportFromEPSG = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function ExportToWkt() As String
-    If obj <> 0 Then
-        Dim wktptr As Long
-        Dim err As Long
-        
-        err = GDALCore.OSRExportToWkt(obj, wktptr)
-        ExportToWkt = GDALCore.CStr2VB(wktptr)
-        ' We really should free wktptr here.
-    Else
-        ExportToWkt = ""
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function ExportToPrettyWkt(bSimplify As Long) As String
-    If obj <> 0 Then
-        Dim wktptr As Long
-        Dim err As Long
-        
-        err = GDALCore.OSRExportToPrettyWkt(obj, wktptr, bSimplify)
-        ExportToPrettyWkt = GDALCore.CStr2VB(wktptr)
-        ' We really should free wktptr here.
-    Else
-        ExportToPrettyWkt = ""
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function SetAttrValue(NodePath As String, NodeValue As String) As Long
-    If obj <> 0 Then
-        SetAttrValue = GDALCore.OSRSetAttrValue(obj, NodePath, NodeValue)
-    Else
-        SetAttrValue = GDALCore.ObjIsNULLError
-    End If
-End Function
-
-' ----------------------------------------------------------------------------
-Public Function GetAttrValue(NodePath As String, iChild As Long) As String
-    If obj <> 0 Then
-        Dim c_str As Long
-        c_str = GDALCore.OSRGetAttrValue(obj, NodePath, iChild)
-        If c_str = 0 Then
-            GetAttrValue = ""
-        Else
-            GetAttrValue = GDALCore.CStr2VB(c_str)
-        End If
-    Else
-        GetAttrValue = ""
-    End If
-End Function
-
diff --git a/vb6/README.TXT b/vb6/README.TXT
deleted file mode 100644
index 6d135b3..0000000
--- a/vb6/README.TXT
+++ /dev/null
@@ -1,67 +0,0 @@
-	GDAL Visual Basic 6 Bindings
-	============================
-
-Preliminary notes on VB6 bindings. 
-
-A VB6 project should include the following files from this directory for
-GDAL access:
-
-  GDAL.bas: Base GDAL access.
-  GDALCore.bas: External DLL entry point declarations and a few private
-                support functions. 
-  GDALDriver.cls
-  GDALDataset.cls
-  GDALRasterBand.cls
-  GDALColorTable.cls
-
-A small (and not very fancy) test application demonstrating some of the use
-of the GDAL VB6 classes is available in the "test" directory.
-
-Quick Test Run
---------------
-
-1) VB6 needs to be launched in such a way that it can find the gdal12vb.dll.
-   This could be accomplished by having VB6 run in the same directory as the
-   DLL, or by copying the DLL into windows\system32 or by editing GDALCore.bas
-   and changing all occurrences of "gdal12vb.dll" to a full path to the DLL. 
-
-   But for the test app to run, you need to have the sample files in the
-   current directory, so you might as well just make a shortcut copy of your
-   VB6 launch icon, and set the current working directory to this directory.
-
-2) Launch VB6. 
-
-3) Open test\GDALVB6Test project. 
-
-4) Hit F5 to run it. 
-
-5) Select Tools->List Drivers menu item to get a list of configured drivers.
-   If this works, the DLL has been found, and calls to it are working fine.
-
-6) File->Exit, and F5 to restart.  This gives a clear form again.
-
-7) Tools->Read Test: This reads a bunch of info from the test file, and
-   dumps it in the form.  Shows access to metadata, color table, etc. 
-
-8) exit and restart to clear screen.
-
-9) Tools->Create Test: This creates an out_create.tif file using explicit
-   creation and copies metadata, georeferencing and actual image data to 
-   it "manually".  This shows most of the setting API is working OK. 
-
-10) Tools->CreateCopy: Simpler option to create out.tif, demonstrates 
-    simple file copying. 
-
-
-Sample App Notes
-----------------
-
-The sample app is very simple, partly because I know very little about
-writing VB apps, and partly because it is only intended to exercise the
-API a bit.  Note, the only thing that works in the file menu is the 
-File->Exit. 
-
-To understand how things work, feel free to review the menu callbacks in 
-VB6Test.frm.  Most have hardcoded filenames. 
-
-
diff --git a/vb6/makefile.vc b/vb6/makefile.vc
deleted file mode 100644
index fbeb964..0000000
--- a/vb6/makefile.vc
+++ /dev/null
@@ -1,15 +0,0 @@
-GDAL_ROOT	=	..
-
-!INCLUDE ..\nmake.opt
-
-VB6_GDAL_DLL =	gdalvb.dll
-OBJ	=	vb6_support.obj
-
-default:	$(OBJ)
-
-$(VB6_GDAL_DLL):	$(OBJ)
-	link /dll /debug $(OBJ) ../gdal_i.lib /out:$(VB6_GDAL_DLL)
-	copy $(VB6_GDAL_DLL) D:\local\bin
-
-clean:	
-	-del vb6_support.obj
diff --git a/vb6/test/GDALVB6Test.vbp b/vb6/test/GDALVB6Test.vbp
deleted file mode 100644
index 5b8ddab..0000000
--- a/vb6/test/GDALVB6Test.vbp
+++ /dev/null
@@ -1,46 +0,0 @@
-Type=Exe
-Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#E:\WINDOWS\system32\Stdole2.tlb#OLE Automation
-Module=Module1; Module1.bas
-Form=VB6Test.frm
-Object={F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0; COMDLG32.OCX
-Object={831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0; MSCOMCTL.OCX
-Class=GDALDataset; ..\GDALDataset.cls
-Module=GDALCore; ..\GDALCore.bas
-Class=GDALRasterBand; ..\GDALRasterBand.cls
-Module=GDAL; ..\GDAL.bas
-Class=GDALDriver; ..\GDALDriver.cls
-Class=GDALColorTable; ..\GDALColorTable.cls
-Class=OGRSpatialReference; ..\OGRSpatialReference.cls
-Class=OGRCoordinateTransformation; ..\OGRCoordinateTransformation.cls
-Startup="Sub Main"
-HelpFile=""
-Title="GDALVB6Test"
-Command32=""
-Name="GDALVB6Test"
-HelpContextID="0"
-CompatibleMode="0"
-MajorVer=1
-MinorVer=0
-RevisionVer=0
-AutoIncrementVer=0
-ServerSupportFiles=0
-VersionCompanyName="Independent"
-CompilationType=0
-OptimizationType=0
-FavorPentiumPro(tm)=0
-CodeViewDebugInfo=0
-NoAliasing=0
-BoundsCheck=0
-OverflowCheck=0
-FlPointCheck=0
-FDIVCheck=0
-UnroundedFP=0
-StartMode=0
-Unattended=0
-Retained=0
-ThreadPerObject=0
-MaxNumberOfThreads=1
-DebugStartupOption=0
-
-[MS Transaction Server]
-AutoRefresh=1
diff --git a/vb6/test/GDALVB6Test.vbw b/vb6/test/GDALVB6Test.vbw
deleted file mode 100644
index 2c4e50f..0000000
--- a/vb6/test/GDALVB6Test.vbw
+++ /dev/null
@@ -1,10 +0,0 @@
-Module1 = 44, 58, 825, 705, C
-frmMain = 198, 29, 955, 713, , 46, 121, 827, 768, C
-GDALDataset = 82, 83, 928, 730, C
-GDALCore = 93, 68, 816, 715, 
-GDALRasterBand = 138, -7, 895, 640, 
-GDAL = 96, 167, 853, 814, 
-GDALDriver = 163, 117, 920, 764, 
-GDALColorTable = 107, 56, 867, 703, 
-OGRSpatialReference = 143, 65, 903, 712, 
-OGRCoordinateTransformation = 171, 77, 931, 724, 
diff --git a/vb6/test/Module1.bas b/vb6/test/Module1.bas
deleted file mode 100644
index 80ef68a..0000000
--- a/vb6/test/Module1.bas
+++ /dev/null
@@ -1,9 +0,0 @@
-Attribute VB_Name = "Module1"
-Public fMainForm As frmMain
-
-
-Sub Main()
-    Set fMainForm = New frmMain
-    fMainForm.Show
-End Sub
-
diff --git a/vb6/test/VB6Test.frm b/vb6/test/VB6Test.frm
deleted file mode 100644
index 5465ec3..0000000
--- a/vb6/test/VB6Test.frm
+++ /dev/null
@@ -1,435 +0,0 @@
-'*****************************************************************************
-' $Id: VB6Test.frm 9362 2006-03-22 04:40:57Z fwarmerdam $
-'
-' Project:  GDAL VB6 Bindings
-' Purpose:  test form
-' Author:   Frank Warmerdam, warmerdam at pobox.com
-'
-'*****************************************************************************
-' Copyright (c) 2005, Frank Warmerdam <warmerdam at pobox.com>
-'
-' Permission is hereby granted, free of charge, to any person obtaining a
-' copy of this software and associated documentation files (the "Software"),
-' to deal in the Software without restriction, including without limitation
-' the rights to use, copy, modify, merge, publish, distribute, sublicense,
-' and/or sell copies of the Software, and to permit persons to whom the
-' Software is furnished to do so, subject to the following conditions:
-'
-' The above copyright notice and this permission notice shall be included
-' in all copies or substantial portions of the Software.
-'
-' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-' OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-' DEALINGS IN THE SOFTWARE.
-'*****************************************************************************
-'
-' $Log$
-' Revision 1.6  2006/03/22 04:40:57  fwarmerdam
-' added copyright header
-'
-'
-
-VERSION 5.00
-Object = "{F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.2#0"; "COMDLG32.OCX"
-Object = "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}#2.0#0"; "MSCOMCTL.OCX"
-Begin VB.Form frmMain 
-   Caption         =   "GDALVB6Test"
-   ClientHeight    =   5970
-   ClientLeft      =   165
-   ClientTop       =   855
-   ClientWidth     =   8565
-   LinkTopic       =   "Form1"
-   ScaleHeight     =   5970
-   ScaleWidth      =   8565
-   StartUpPosition =   3  'Windows Default
-   Begin MSComDlg.CommonDialog FileDlg 
-      Left            =   7800
-      Top             =   120
-      _ExtentX        =   847
-      _ExtentY        =   847
-      _Version        =   393216
-      FileName        =   "dolphins_i.png"
-   End
-   Begin MSComctlLib.StatusBar sbStatusBar 
-      Align           =   2  'Align Bottom
-      Height          =   270
-      Left            =   0
-      TabIndex        =   0
-      Top             =   5700
-      Width           =   8565
-      _ExtentX        =   15108
-      _ExtentY        =   476
-      _Version        =   393216
-      BeginProperty Panels {8E3867A5-8586-11D1-B16A-00C0F0283628} 
-         NumPanels       =   3
-         BeginProperty Panel1 {8E3867AB-8586-11D1-B16A-00C0F0283628} 
-            AutoSize        =   1
-            Object.Width           =   9446
-            Text            =   "Status"
-            TextSave        =   "Status"
-         EndProperty
-         BeginProperty Panel2 {8E3867AB-8586-11D1-B16A-00C0F0283628} 
-            Style           =   6
-            AutoSize        =   2
-            TextSave        =   "4/11/2005"
-         EndProperty
-         BeginProperty Panel3 {8E3867AB-8586-11D1-B16A-00C0F0283628} 
-            Style           =   5
-            AutoSize        =   2
-            TextSave        =   "3:59 PM"
-         EndProperty
-      EndProperty
-   End
-   Begin VB.Menu mnuFile 
-      Caption         =   "&File"
-      Begin VB.Menu mnuOpen 
-         Caption         =   "&Open"
-      End
-      Begin VB.Menu mnuFileExit 
-         Caption         =   "E&xit"
-      End
-   End
-   Begin VB.Menu mnuTools 
-      Caption         =   "&Tools"
-      Begin VB.Menu mnuToolsTest1 
-         Caption         =   "Read Test"
-      End
-      Begin VB.Menu mnuCSInfo 
-         Caption         =   "Coordinate System Info"
-      End
-      Begin VB.Menu mnuListDrivers 
-         Caption         =   "List Drivers"
-      End
-      Begin VB.Menu mnuCCTest 
-         Caption         =   "CreateCopy Test"
-      End
-      Begin VB.Menu mnuCreate 
-         Caption         =   "Create Test"
-      End
-   End
-End
-Attribute VB_Name = "frmMain"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-
-Private Sub Form_Load()
-    Me.Left = GetSetting(App.Title, "Settings", "MainLeft", 1000)
-    Me.Top = GetSetting(App.Title, "Settings", "MainTop", 1000)
-    Me.Width = GetSetting(App.Title, "Settings", "MainWidth", 6500)
-    Me.Height = GetSetting(App.Title, "Settings", "MainHeight", 6500)
-
-    Call GDAL.AllRegister
-    Call GDAL.SetConfigOption("GDAL_DATA", "D:\warmerda\fao\bld\data")
-End Sub
-
-
-Private Sub Form_Unload(Cancel As Integer)
-    Dim i As Integer
-    
-    'close all sub forms
-    For i = Forms.Count - 1 To 1 Step -1
-        Unload Forms(i)
-    Next
-    If Me.WindowState <> vbMinimized Then
-        SaveSetting App.Title, "Settings", "MainLeft", Me.Left
-        SaveSetting App.Title, "Settings", "MainTop", Me.Top
-        SaveSetting App.Title, "Settings", "MainWidth", Me.Width
-        SaveSetting App.Title, "Settings", "MainHeight", Me.Height
-    End If
-End Sub
-
-
-Private Sub mnuCCTest_Click()
-    Dim SrcFilename As String, DstFilename As String
-    Dim Drv As GDALDriver
-    Dim SrcDS As GDALDataset, DstDS As GDALDataset
-        
-    SrcFilename = FileDlg.Filename
-    
-    DstFilename = "out.tif"
-    
-    Call GDALCore.GDALAllRegister
-    Set SrcDS = GDAL.OpenDS(SrcFilename, GDAL.GA_ReadOnly)
-    
-    Set Drv = GDAL.GetDriverByName("GTiff")
- 
-    Set DstDS = Drv.CreateCopy(DstFilename, SrcDS, True, Nothing)
-    If DstDS.IsValid() Then
-        Print "CreateCopy Succeeded, output is " & DstFilename
-    Else
-        Print "Create Copy Failed: " & GDAL.GetLastErrorMsg()
-    End If
-    Call DstDS.CloseDS
-    Call SrcDS.CloseDS
-    
-End Sub
-
-
-Private Sub mnuCreate_Click()
-    Dim SrcFilename As String, DstFilename As String
-    Dim Drv As GDALDriver
-    Dim SrcDS As GDALDataset, DstDS As GDALDataset
-    Dim err As Long
-        
-    SrcFilename = FileDlg.Filename
-    DstFilename = "out_create.tif"
-    
-    Call GDALCore.GDALAllRegister
-    Set SrcDS = GDAL.OpenDS(SrcFilename, GDAL.GA_ReadOnly)
-    If Not SrcDS.IsValid() Then
-        Print GDAL.GetLastErrorMsg()
-        Exit Sub
-    End If
-    
-    Set Drv = GDAL.GetDriverByName("GTiff")
-    Set DstDS = Drv.Create(DstFilename, SrcDS.XSize, SrcDS.YSize, _
-                           SrcDS.BandCount, GDAL.GDT_Byte, Nothing)
-    If DstDS.IsValid() Then
-        Print "Create Succeeded, file is " & DstFilename
-    Else
-        Print "Create Failed: " & GDAL.GetLastErrorMsg()
-        Exit Sub
-    End If
-    
-    ' Copy geotransform
-    Dim gt(6) As Double
-    
-    err = SrcDS.GetGeoTransform(gt)
-    If err = 0 Then
-        Call DstDS.SetGeoTransform(gt)
-    End If
-    
-    ' Copy projection
-    Call DstDS.SetProjection(SrcDS.GetProjection())
-    
-    ' Copy metadata.
-    Call DstDS.SetMetadata(SrcDS.GetMetadata(""), "")
-    
-    ' Copy band info
-    Dim Scanline() As Double
-    ReDim Scanline(SrcDS.XSize) As Double
-   
-    For iBand = 1 To SrcDS.BandCount
-        Dim SrcBand As GDALRasterBand, DstBand As GDALRasterBand
-        
-        Set SrcBand = SrcDS.GetRasterBand(iBand)
-        Set DstBand = DstDS.GetRasterBand(iBand)
-        
-        Call DstBand.SetMetadata(SrcBand.GetMetadata(""), "")
-        Call DstBand.SetOffset(SrcBand.GetOffset())
-        Call DstBand.SetScale(SrcBand.GetScale())
-        
-        Dim NoDataValue As Double, Success As Long
-        
-        NoDataValue = SrcBand.GetNoDataValue(Success)
-        If Success <> 0 Then
-            Call DstBand.SetNoDataValue(NoDataValue)
-        End If
-                
-        ' Copy Paletted if one present.
-        Dim ct As GDALColorTable
-        Set ct = SrcBand.GetColorTable()
-        If ct.IsValid() Then
-            ' We manually copy the color table.  This isn't really
-            ' necessary, but gives us a chance to try out all color
-            ' table methods.
-            Dim ct2 As GDALColorTable
-            Dim iColor As Integer
-            Dim Tuple(4) As Integer
-
-            Set ct2 = GDAL.CreateColorTable(GDAL.GPI_RGB)
-            For iColor = 0 To ct.EntryCount
-                Call ct.GetColorEntryAsRGB(iColor, Tuple)
-                Call ct2.SetColorEntry(iColor, Tuple)
-            Next iColor
-            err = DstBand.SetColorTable(ct2)
-        End If
-        
-        ' Copy band raster data.
-        For iLine = 0 To SrcDS.YSize - 1
-            Call SrcBand.RasterIO(GDAL.GF_Read, 0, iLine, SrcDS.XSize, 1, Scanline)
-            Call DstBand.RasterIO(GDAL.GF_Write, 0, iLine, SrcDS.XSize, 1, Scanline)
-        Next iLine
-    Next iBand
-    
-    Call DstDS.CloseDS
-    Call SrcDS.CloseDS
-    
-    Print "Copy seems to have completed."
-End Sub
-
-
-Private Sub mnuCSInfo_Click()
-    Dim ds As GDALDataset
-    
-    Call GDALCore.GDALAllRegister
-    Set ds = GDAL.OpenDS(FileDlg.Filename, GDAL.GA_ReadOnly)
-    
-    If ds.IsValid() Then
-        Dim Geotransform(6) As Double
-        Dim err As Long
-        Dim srs As New OGRSpatialReference
-        Dim latlong_srs As OGRSpatialReference
-        Dim ct As New OGRCoordinateTransformation
-        Dim WKT As String
-        
-        Call ds.GetGeoTransform(Geotransform)
-        
-        Print "Size: " & ds.XSize & "P x " & ds.YSize & "L"
-        
-        ' report projection in pretty format.
-        WKT = ds.GetProjection()
-        If Len(WKT) > 0 Then
-            Print "Projection: "
-            Call srs.SetFromUserInput(WKT)
-            Print srs.ExportToPrettyWkt(0)
-
-            If srs.GetAttrValue("PROJECTION", 0) <> "" Then
-                Set latlong_srs = srs.CloneGeogCS()
-                Set ct = GDAL.CreateCoordinateTransformation(srs, latlong_srs)
-            End If
-        End If
-        
-        Print "Origin: " & Geotransform(0) & "," & Geotransform(3)
-        Print "Pixel Size: " & Geotransform(1) & "x" & (-1 * Geotransform(5))
-        
-        Call ReportCorner("Top Left      ", 0, 0, _
-                          Geotransform, ct)
-        Call ReportCorner("Top Right     ", ds.XSize, 0, _
-                          Geotransform, ct)
-        Call ReportCorner("Bottom Left   ", 0, ds.YSize, _
-                          Geotransform, ct)
-        Call ReportCorner("Bottom Right  ", ds.XSize, ds.YSize, _
-                          Geotransform, ct)
-        Call ReportCorner("Center        ", ds.XSize / 2#, ds.YSize / 2#, _
-                          Geotransform, ct)
-    Else
-        Print GDAL.GetLastErrorMsg()
-    End If
-End Sub
-
-Private Sub ReportCorner(CornerName As String, pixel As Double, line As Double, _
-                         gt() As Double, ct As OGRCoordinateTransformation)
-                             
-    Dim geox As Double, geoy As Double
-    Dim longitude As Double, latitude As Double, Z As Double
-    Dim latlong_valid As Boolean
-    
-    geox = gt(0) + pixel * gt(1) + line * gt(2)
-    geoy = gt(3) + pixel * gt(4) + line * gt(5)
-
-    latlong_valid = False
-    
-    If ct.IsValid() Then
-        Z = 0
-        longitude = geox
-        latitude = geoy
-        latlong_valid = ct.TransformOne(longitude, latitude, Z)
-    End If
-                         
-    If latlong_valid Then
-        Print CornerName & geox & "," & geoy & "    " & longitude & "," & latitude
-    Else
-        Print CornerName & geox & "," & geoy
-    End If
-End Sub
-
-                          
-
-Private Sub mnuListDrivers_Click()
-    Dim Drv As GDALDriver
-    
-    Print "GDAL_DATA = " & GDAL.GetConfigOption("GDAL_DATA", "<not set>")
-    
-    If GDAL.GetDriverCount() < 1 Then
-        Call GDAL.AllRegister
-    End If
-    drvCount = GDAL.GetDriverCount
-    Print "Count = " & drvCount
-    For drvIndex = 0 To drvCount - 1
-        Set Drv = GDAL.GetDriver(drvIndex)
-        If Drv.GetMetadataItem(GDAL.DCAP_CREATE, "") = "YES" _
-            Or Drv.GetMetadataItem(GDAL.DCAP_CREATECOPY, "") = "YES" Then
-            xMsg = " (Read/Write)"
-        Else
-            xMsg = " (ReadOnly)"
-        End If
-              
-        Print Drv.GetShortName() & ": " & Drv.GetMetadataItem(GDAL.DMD_LONGNAME, "") & xMsg
-    Next drvIndex
-End Sub
-
-Private Sub mnuOpen_Click()
-    Call FileDlg.ShowOpen
-    Print "Filename " & FileDlg.Filename & " selected."
-End Sub
-
-Private Sub mnuToolsTest1_Click()
-    Dim ds As GDALDataset
-    Dim Filename As String
-    
-    Filename = FileDlg.Filename
-    
-    Call GDALCore.GDALAllRegister
-    Set ds = GDAL.OpenDS(Filename, GDAL.GA_ReadOnly)
-    
-    If ds.IsValid() Then
-        Dim Geotransform(6) As Double
-        Dim MD As Variant
-        Dim i, err As Integer
-        
-        Print "Open succeeded"
-        Print "Size: " & ds.XSize & "x" & ds.YSize & "x" & ds.BandCount
-    
-        MD = ds.GetMetadata(vbNullString)
-        If (UBound(MD) > 0) Then
-            Print "Metadata:"
-            For i = 1 To UBound(MD)
-                Print "  " & MD(i)
-            Next i
-        End If
-        
-        For i = 1 To ds.BandCount
-            Dim band As GDALRasterBand
-            
-            Set band = ds.GetRasterBand(i)
-            Print "Band " & i & " BlockSize: " & band.BlockXSize & "x" & band.BlockYSize
-            Print "     DataType=" & GDAL.GetDataTypeName(band.DataType) _
-                & " Offset=" & band.GetOffset() & " Scale=" & band.GetScale() _
-                & " Min=" & band.GetMinimum() & " Max=" & band.GetMaximum()
-                
-            Dim RawData() As Double
-            ReDim RawData(ds.XSize) As Double
-            err = band.RasterIO(GDAL.GF_Read, 0, 0, ds.XSize, 1, RawData)
-            Print "    Data: " & RawData(1) & " " & RawData(10)
-            
-            Dim ct As GDALColorTable
-            Set ct = band.GetColorTable()
-            If ct.IsValid() Then
-                Dim CEntry(4) As Integer
-                Print "    Has Color Table, " & ct.EntryCount & " entries"
-                For iColor = 0 To ct.EntryCount - 1
-                    Call ct.GetColorEntryAsRGB(iColor, CEntry)
-                    Print "      " & iColor & ": " & CEntry(0) & "," & CEntry(1) & "," & CEntry(2) & "," & CEntry(3)
-                Next iColor
-            End If
-        Next i
-        
-        Call ds.CloseDS
-    Else
-        Print GDAL.GetLastErrorMsg()
-    End If
-End Sub
-
-Private Sub mnuFileExit_Click()
-    'unload the form
-    Unload Me
-
-End Sub
-
diff --git a/vb6/vb6_support.cpp b/vb6/vb6_support.cpp
deleted file mode 100644
index 36ae844..0000000
--- a/vb6/vb6_support.cpp
+++ /dev/null
@@ -1,341 +0,0 @@
-/******************************************************************************
- * $Id: vb6_support.cpp 33713 2016-03-12 17:41:57Z goatbar $
- *
- * Project:  GDAL VB6 Bindings
- * Purpose:  Support functions for GDAL VB6 bindings.
- * Author:   Frank Warmerdam, warmerdam at pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2005, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ****************************************************************************/
-
-#include <windows.h>
-#include "cpl_string.h"
-#include "gdal.h"
-
-// This is just for the USES_CONVERSION & OLESTR stuff.
-#include <atlbase.h>
-
-CPL_CVSID("$Id: vb6_support.cpp 33713 2016-03-12 17:41:57Z goatbar $");
-
-// External entry points (from VB)
-extern "C" {
-
-int __declspec(dllexport) __stdcall
-vbCStringToVB6( VARIANT *vResult, char *pszInput );
-
-void __declspec(dllexport) __stdcall
-vbCSLToVariant( char **papszList, VARIANT *out_list );
-
-char __declspec(dllexport) ** __stdcall
-vbVariantToCSL( VARIANT *vList );
-
-int __declspec(dllexport) __stdcall
-vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType,
-                  int *pnXSize, int *pnYSize );
-
-}
-
-static char *pszErrorMessage = NULL;
-
-/************************************************************************/
-/*                            CStringToVB6()                            */
-/************************************************************************/
-
-int __declspec(dllexport) __stdcall
-vbCStringToVB6( VARIANT *vResult, char *pszInput )
-
-{
-    USES_CONVERSION;
-
-    VariantClear( vResult );
-
-    if( pszInput != NULL )
-    {
-        vResult->vt = VT_BSTR;
-        vResult->bstrVal = SysAllocString( A2BSTR(pszInput) );
-        return 0;
-    }
-    else
-        return 1;
-}
-
-/************************************************************************/
-/*                            CSLToVariant()                            */
-/*                                                                      */
-/*      Translate a list of C strings into a VARIANT array of           */
-/*      VARIANT strings that can be returned to VB.                     */
-/************************************************************************/
-
-void __declspec(dllexport) __stdcall
-vbCSLToVariant( char **papszList, VARIANT *out_list )
-
-{
-    USES_CONVERSION;
-    SAFEARRAYBOUND sBounds;
-    SAFEARRAY *result;
-    long i, nLength = CSLCount( papszList );
-
-/* -------------------------------------------------------------------- */
-/*      Create safe array result.                                       */
-/* -------------------------------------------------------------------- */
-    sBounds.lLbound = 1;
-    sBounds.cElements = nLength;
-
-    result = SafeArrayCreate( VT_BSTR, 1, &sBounds );
-
-    for( i = 1; i <= nLength; i++ )
-    {
-        SafeArrayPutElement( result, &i,
-                             SysAllocString( A2BSTR(papszList[i-1]) ) );
-//        MessageBox( NULL, papszList[i-1], "Metadata Item", MB_OK );
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Assign to variant.                                              */
-/* -------------------------------------------------------------------- */
-    VariantClear( out_list );
-
-    out_list->vt = VT_BSTR | VT_ARRAY;
-    out_list->parray = result;
-}
-
-/************************************************************************/
-/*                            VariantToCSL()                            */
-/*                                                                      */
-/*      Extract a list of strings from a variant as a stringlist.       */
-/************************************************************************/
-
-char __declspec(dllexport) ** __stdcall
-vbVariantToCSL( VARIANT *vList )
-
-{
-    char **papszResult = NULL;
-    SAFEARRAY *psSA;
-    long nLBound, nUBound;
-    VARTYPE eVartype;
-
-/* -------------------------------------------------------------------- */
-/*      Get and verify info about safe array.                           */
-/* -------------------------------------------------------------------- */
-    if( vList == NULL )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "VARIANT is NULL in VariantToCSL()." );
-        return NULL;
-    }
-
-    if( vList->vt == (VT_BSTR | VT_ARRAY | VT_BYREF) )
-        psSA = *(vList->pparray);
-    else if( vList->vt == (VT_BSTR | VT_ARRAY) )
-        psSA = vList->parray;
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "VARIANT is wrong type (%x).",
-                  vList->vt );
-        return NULL;
-    }
-
-    if( SafeArrayGetDim(psSA) != 1 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Wrong dimension in array (%d)",
-                  SafeArrayGetDim(psSA) );
-        return NULL;
-    }
-
-    if( FAILED(SafeArrayGetLBound( psSA, 1, &nLBound ))
-        || FAILED(SafeArrayGetUBound( psSA, 1, &nUBound)) )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "SafeARrayGet{L,U}Bound() failed." );
-        return NULL;
-    }
-
-    if( nUBound < nLBound )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Crazy L/U Bound (L=%d, U=%d)",
-                  nLBound, nUBound );
-        return NULL;
-    }
-
-    SafeArrayGetVartype(psSA, &eVartype );
-    if( eVartype != VT_BSTR )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "SafeArray contains type %d instead of VT_BSTR.",
-                  eVartype );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Create string list from safe array BSTRings.                    */
-/* -------------------------------------------------------------------- */
-    papszResult = (char **) CPLCalloc(sizeof(char *),(nUBound-nLBound+2));
-
-    for( long iElement = nLBound; iElement <= nUBound; iElement++ )
-    {
-        BSTR bstrValue;
-        char szValue[5000];
-
-        if( FAILED(SafeArrayGetElement(psSA, &iElement, &bstrValue)) )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "SafeArrayGetElement(%d) failed.",
-                      iElement );
-            CSLDestroy( papszResult );
-            return NULL;
-        }
-
-        sprintf( szValue, "%S", bstrValue );
-        papszResult[iElement - nLBound] = CPLStrdup( szValue );
-    }
-
-    return papszResult;
-}
-
-/************************************************************************/
-/*                          vbSafeArrayToPtr()                          */
-/*                                                                      */
-/*      Get the raw pointer (as LONG) and datatype and size from a      */
-/*      SafeArray.                                                      */
-/************************************************************************/
-
-int __declspec(dllexport) __stdcall
-vbSafeArrayToPtr( VARIANT *vArray, GDALDataType *peDataType,
-                  int *pnXSize, int *pnYSize )
-
-{
-    char **papszResult = NULL;
-    SAFEARRAY *psSA;
-    long nLBound, nUBound;
-    VARTYPE eVartype;
-
-/* -------------------------------------------------------------------- */
-/*      Get and verify info about safe array.                           */
-/* -------------------------------------------------------------------- */
-    if( vArray == NULL )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "VARIANT is NULL in SafeArrayToPtr()." );
-        return NULL;
-    }
-
-    if( (vArray->vt & (VT_ARRAY | VT_BYREF)) == (VT_ARRAY | VT_BYREF) )
-        psSA = *(vArray->pparray);
-    else if( (vArray->vt & VT_ARRAY) == VT_ARRAY )
-        psSA = vArray->parray;
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "VARIANT is wrong type (%x).",
-                  vArray->vt );
-        return NULL;
-    }
-
-    if( SafeArrayGetDim(psSA) < 1 || SafeArrayGetDim(psSA) > 2 )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Wrong dimension in array (%d)",
-                  SafeArrayGetDim(psSA) );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Get XSize                                                       */
-/* -------------------------------------------------------------------- */
-    if( FAILED(SafeArrayGetLBound( psSA, 1, &nLBound ))
-        || FAILED(SafeArrayGetUBound( psSA, 1, &nUBound)) )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "SafeARrayGet{L,U}Bound() failed." );
-        return NULL;
-    }
-
-    if( nUBound <= nLBound )
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "Crazy L/U Bound (L=%d, U=%d)",
-                  nLBound, nUBound );
-        return NULL;
-    }
-
-    *pnXSize = nUBound - nLBound + 1;
-
-/* -------------------------------------------------------------------- */
-/*      Get YSize                                                       */
-/* -------------------------------------------------------------------- */
-    if( SafeArrayGetDim(psSA) == 1 )
-        *pnYSize = 1;
-    else
-    {
-        if( FAILED(SafeArrayGetLBound( psSA, 1, &nLBound ))
-            || FAILED(SafeArrayGetUBound( psSA, 1, &nUBound)) )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "SafeARrayGet{L,U}Bound() failed." );
-            return NULL;
-        }
-
-        if( nUBound <= nLBound )
-        {
-            CPLError( CE_Failure, CPLE_AppDefined,
-                      "Crazy L/U Bound (L=%d, U=%d)",
-                      nLBound, nUBound );
-            return NULL;
-        }
-
-        *pnYSize = nUBound - nLBound + 1;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Translate the type.                                             */
-/* -------------------------------------------------------------------- */
-    SafeArrayGetVartype(psSA, &eVartype );
-    if( eVartype == VT_UI1 )
-        *peDataType = GDT_Byte;
-    else if( eVartype == VT_UI2 )
-        *peDataType = GDT_UInt16;
-    else if( eVartype == VT_I2 )
-        *peDataType = GDT_Int16;
-    else if( eVartype == VT_I4 || eVartype == VT_INT )
-        *peDataType = GDT_Int32;
-    else if( eVartype == VT_UI4 || eVartype == VT_UINT )
-        *peDataType = GDT_UInt32;
-    else if( eVartype == VT_R4 )
-        *peDataType = GDT_Float32;
-    else if( eVartype == VT_R8 )
-        *peDataType = GDT_Float64;
-    else
-    {
-        CPLError( CE_Failure, CPLE_AppDefined,
-                  "SafeArray contains type %d which is not supported.",
-                  eVartype );
-        return NULL;
-    }
-
-/* -------------------------------------------------------------------- */
-/*      Return the raw data pointer cast to an int.                     */
-/* -------------------------------------------------------------------- */
-    return (int) psSA->pvData;
-}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/gdal.git



More information about the Pkg-grass-devel mailing list